From pavel at ucw.cz  Sun May  1 01:52:36 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Sun, 1 May 2016 10:52:36 +0200
Subject: Nokia N900 retention mode in v4.6, camera buttons fun
In-Reply-To: <20160429200559.GA16598@earth>
References: <20160407234134.GQ16484@atomide.com> <20160411093023.GC11814@amd>
 <20160411094130.GA5753@amd> <20160411211026.GH5995@atomide.com>
 <20160412121658.GA32486@amd> <20160412123013.GA12296@amd>
 <20160412163055.GP5995@atomide.com> <20160417175539.GA502@amd>
 <20160421130450.GQ29406@pali> <20160429200559.GA16598@earth>
Message-ID: <20160501085236.GA14243@amd>

On Fri 2016-04-29 22:06:00, Sebastian Reichel wrote:
> Hi,
> 
> On Thu, Apr 21, 2016 at 03:04:50PM +0200, Pali Roh?r wrote:
> > > CONFIG_HSI breaks power management completely, so power management
> > > with modem will be another topic.  
> > 
> > Sebastian, any idea why power management does not work for HSI?
> 
> I wasn't aware, that pm_runtime_irq_safe() basically breaks runtime
> PM until Tony's fix for musb (even though it's logical when thinking
> about it). Currently omap-ssi and omap-ssi-port make use of
> pm_runtime_irq_safe().
> 
> Since pm_runtime_get_sync/pm_runtime_put_sync is called from
> tasklets in omap-ssi (and omap-ssi-port) it cannot be simply
> removed. So fixing PM for the ssi controller requires reworking
> the driver in a non trivial way.

I see latest series, and it also talks about frequency scaling. But I
guess it is not going to fix this issue?

Thanks,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From linus.walleij at linaro.org  Sun May  1 02:03:55 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Sun, 1 May 2016 11:03:55 +0200
Subject: [PATCH 1/2] pinctrl: amlogic: Add support for Amlogic Meson GXBB
 SoC
In-Reply-To: <1462036875-22625-2-git-send-email-carlo@caione.org>
References: <1462036875-22625-1-git-send-email-carlo@caione.org>
 <1462036875-22625-2-git-send-email-carlo@caione.org>
Message-ID: <CACRpkdbfSgVH_zGMdgyfvBbnpiTkd7dzugza4_w0_7MLMVNzyA@mail.gmail.com>

On Sat, Apr 30, 2016 at 7:21 PM, Carlo Caione <carlo at caione.org> wrote:

> From: Carlo Caione <carlo at endlessm.com>
>
> This patch adds the basic platform file to support the pin controller
> found on the Amlogic Meson GXBB SoCs.
>
> Signed-off-by: Carlo Caione <carlo at endlessm.com>

>  .../devicetree/bindings/pinctrl/meson,pinctrl.txt  |   2 +

This thing conflicts with upstream. Make a separate patch for
updating the bindings I think.

>  arch/arm64/Kconfig.platforms                       |   2 +

This needs to be split off and sent separatelt to the ARM64
maintainers. Since it's just a symbol dependency (I think?) it
can be merged orthogonally.

>  drivers/pinctrl/meson/Makefile                     |   2 +-
>  drivers/pinctrl/meson/pinctrl-meson-gxbb.c         | 432 +++++++++++++++++++++
>  drivers/pinctrl/meson/pinctrl-meson.c              |   8 +
>  drivers/pinctrl/meson/pinctrl-meson.h              |   2 +
>  include/dt-bindings/gpio/meson-gxbb-gpio.h         | 154 ++++++++
>  7 files changed, 601 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/pinctrl/meson/pinctrl-meson-gxbb.c
>  create mode 100644 include/dt-bindings/gpio/meson-gxbb-gpio.h

This stuff I can merge, if I get it in a separate patch.

> diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
> index 32f4a2d..fe7fe0b 100644
> --- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
> +++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
> @@ -5,6 +5,8 @@ Required properties for the root node:
>                       "amlogic,meson8b-cbus-pinctrl"
>                       "amlogic,meson8-aobus-pinctrl"
>                       "amlogic,meson8b-aobus-pinctrl"
> +                     "amlogic,meson-gxbb-periphs-pinctrl"
> +                     "amlogic,meson-gxbb-aobus-pinctrl"

This is not how upstream looks...

Yours,
Linus Walleij


From linus.walleij at linaro.org  Sun May  1 02:05:01 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Sun, 1 May 2016 11:05:01 +0200
Subject: [PATCH 2/2] ARM64: dts: amlogic: Enable pin controller on
 GXBB-based platforms
In-Reply-To: <1462036875-22625-3-git-send-email-carlo@caione.org>
References: <1462036875-22625-1-git-send-email-carlo@caione.org>
 <1462036875-22625-3-git-send-email-carlo@caione.org>
Message-ID: <CACRpkdb1XwjJEeKxadRWxeD1gq7yj9RMJfZQbiX+xG0sRNXz4w@mail.gmail.com>

On Sat, Apr 30, 2016 at 7:21 PM, Carlo Caione <carlo at caione.org> wrote:

> From: Carlo Caione <carlo at endlessm.com>
>
> Update DTS and DTSI files to enable the pin controller. We also now
> support the blinking blue LED on the Odroid-C2.
>
> Signed-off-by: Carlo Caione <carlo at endlessm.com>

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

Yours,
Linus Walleij


From carlo at caione.org  Sun May  1 02:20:14 2016
From: carlo at caione.org (Carlo Caione)
Date: Sun, 1 May 2016 11:20:14 +0200
Subject: [PATCH 1/2] pinctrl: amlogic: Add support for Amlogic Meson GXBB
 SoC
In-Reply-To: <CACRpkdbfSgVH_zGMdgyfvBbnpiTkd7dzugza4_w0_7MLMVNzyA@mail.gmail.com>
References: <1462036875-22625-1-git-send-email-carlo@caione.org>
 <1462036875-22625-2-git-send-email-carlo@caione.org>
 <CACRpkdbfSgVH_zGMdgyfvBbnpiTkd7dzugza4_w0_7MLMVNzyA@mail.gmail.com>
Message-ID: <CAOQ7t2YEVsk9cB-kmp-fXSVsVVtXynFbMSxPzTPE_0+s0qY9PQ@mail.gmail.com>

On Sun, May 1, 2016 at 11:03 AM, Linus Walleij <linus.walleij at linaro.org> wrote:
> On Sat, Apr 30, 2016 at 7:21 PM, Carlo Caione <carlo at caione.org> wrote:
>
>> From: Carlo Caione <carlo at endlessm.com>
>>
>> This patch adds the basic platform file to support the pin controller
>> found on the Amlogic Meson GXBB SoCs.
>>
>> Signed-off-by: Carlo Caione <carlo at endlessm.com>
>
>>  .../devicetree/bindings/pinctrl/meson,pinctrl.txt  |   2 +
>
> This thing conflicts with upstream. Make a separate patch for
> updating the bindings I think.

This patch is based on linux-next where the documentation is correctly
updated (see 11ca8735) but apparently this is missing from upstream.
Probably slipped through the cracks with the latest PR.

Kevin, did you merge both the commits in
https://patchwork.ozlabs.org/patch/603580/ or just the DT changes?

>>  arch/arm64/Kconfig.platforms                       |   2 +
>
> This needs to be split off and sent separatelt to the ARM64
> maintainers. Since it's just a symbol dependency (I think?) it
> can be merged orthogonally.

Ok

>>  drivers/pinctrl/meson/Makefile                     |   2 +-
>>  drivers/pinctrl/meson/pinctrl-meson-gxbb.c         | 432 +++++++++++++++++++++
>>  drivers/pinctrl/meson/pinctrl-meson.c              |   8 +
>>  drivers/pinctrl/meson/pinctrl-meson.h              |   2 +
>>  include/dt-bindings/gpio/meson-gxbb-gpio.h         | 154 ++++++++
>>  7 files changed, 601 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/pinctrl/meson/pinctrl-meson-gxbb.c
>>  create mode 100644 include/dt-bindings/gpio/meson-gxbb-gpio.h
>
> This stuff I can merge, if I get it in a separate patch.

I'll split it in v2

>> diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
>> index 32f4a2d..fe7fe0b 100644
>> --- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
>> +++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
>> @@ -5,6 +5,8 @@ Required properties for the root node:
>>                       "amlogic,meson8b-cbus-pinctrl"
>>                       "amlogic,meson8-aobus-pinctrl"
>>                       "amlogic,meson8b-aobus-pinctrl"
>> +                     "amlogic,meson-gxbb-periphs-pinctrl"
>> +                     "amlogic,meson-gxbb-aobus-pinctrl"
>
> This is not how upstream looks...

yeah, trying to figure this out,

Thanks,

-- 
Carlo Caione


From yamada.masahiro at socionext.com  Sun May  1 03:37:02 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Sun,  1 May 2016 19:37:02 +0900
Subject: [PATCH 6/7] reset: socfpga: use devm_reset_controller_register()
In-Reply-To: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462099023-11819-7-git-send-email-yamada.masahiro@socionext.com>

Use devm_reset_controller_register() for the reset controller
registration and drop the .remove callback.

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

 drivers/reset/reset-socfpga.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
index cd05a70..12add9b 100644
--- a/drivers/reset/reset-socfpga.c
+++ b/drivers/reset/reset-socfpga.c
@@ -134,16 +134,7 @@ static int socfpga_reset_probe(struct platform_device *pdev)
 	data->rcdev.ops = &socfpga_reset_ops;
 	data->rcdev.of_node = pdev->dev.of_node;
 
-	return reset_controller_register(&data->rcdev);
-}
-
-static int socfpga_reset_remove(struct platform_device *pdev)
-{
-	struct socfpga_reset_data *data = platform_get_drvdata(pdev);
-
-	reset_controller_unregister(&data->rcdev);
-
-	return 0;
+	return devm_reset_controller_register(dev, &data->rcdev);
 }
 
 static const struct of_device_id socfpga_reset_dt_ids[] = {
@@ -153,7 +144,6 @@ static const struct of_device_id socfpga_reset_dt_ids[] = {
 
 static struct platform_driver socfpga_reset_driver = {
 	.probe	= socfpga_reset_probe,
-	.remove	= socfpga_reset_remove,
 	.driver = {
 		.name		= "socfpga-reset",
 		.of_match_table	= socfpga_reset_dt_ids,
-- 
1.9.1



From yamada.masahiro at socionext.com  Sun May  1 03:36:59 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Sun,  1 May 2016 19:36:59 +0900
Subject: [PATCH 3/7] reset: lpc18xx: use devm_reset_controller_register()
In-Reply-To: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462099023-11819-4-git-send-email-yamada.masahiro@socionext.com>

Use devm_reset_controller_register() for the reset controller
registration and remove the unregister call from the .remove callback.

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

 drivers/reset/reset-lpc18xx.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c
index 3b8a4f5..dd4f27e 100644
--- a/drivers/reset/reset-lpc18xx.c
+++ b/drivers/reset/reset-lpc18xx.c
@@ -199,7 +199,7 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, rc);
 
-	ret = reset_controller_register(&rc->rcdev);
+	ret = devm_reset_controller_register(&pdev->dev, &rc->rcdev);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to register device\n");
 		goto dis_clks;
@@ -229,8 +229,6 @@ static int lpc18xx_rgu_remove(struct platform_device *pdev)
 	if (ret)
 		dev_warn(&pdev->dev, "failed to unregister restart handler\n");
 
-	reset_controller_unregister(&rc->rcdev);
-
 	clk_disable_unprepare(rc->clk_delay);
 	clk_disable_unprepare(rc->clk_reg);
 
-- 
1.9.1



From yamada.masahiro at socionext.com  Sun May  1 03:37:00 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Sun,  1 May 2016 19:37:00 +0900
Subject: [PATCH 4/7] reset: pistachio: use devm_reset_controller_register()
In-Reply-To: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462099023-11819-5-git-send-email-yamada.masahiro@socionext.com>

Use devm_reset_controller_register() for the reset controller
registration and drop the .remove callback.

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

 drivers/reset/reset-pistachio.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/reset/reset-pistachio.c b/drivers/reset/reset-pistachio.c
index 72a97a1..bbc4c06 100644
--- a/drivers/reset/reset-pistachio.c
+++ b/drivers/reset/reset-pistachio.c
@@ -121,16 +121,7 @@ static int pistachio_reset_probe(struct platform_device *pdev)
 	rd->rcdev.ops = &pistachio_reset_ops;
 	rd->rcdev.of_node = np;
 
-	return reset_controller_register(&rd->rcdev);
-}
-
-static int pistachio_reset_remove(struct platform_device *pdev)
-{
-	struct pistachio_reset_data *data = platform_get_drvdata(pdev);
-
-	reset_controller_unregister(&data->rcdev);
-
-	return 0;
+	return devm_reset_controller_register(dev, &rd->rcdev);
 }
 
 static const struct of_device_id pistachio_reset_dt_ids[] = {
@@ -141,7 +132,6 @@ MODULE_DEVICE_TABLE(of, pistachio_reset_dt_ids);
 
 static struct platform_driver pistachio_reset_driver = {
 	.probe	= pistachio_reset_probe,
-	.remove	= pistachio_reset_remove,
 	.driver = {
 		.name		= "pistachio-reset",
 		.of_match_table	= pistachio_reset_dt_ids,
-- 
1.9.1



From yamada.masahiro at socionext.com  Sun May  1 03:37:01 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Sun,  1 May 2016 19:37:01 +0900
Subject: [PATCH 5/7] reset: sunxi: use devm_reset_controller_register()
In-Reply-To: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462099023-11819-6-git-send-email-yamada.masahiro@socionext.com>

Use devm_reset_controller_register() for the reset controller
registration and drop the .remove callback.

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

 drivers/reset/reset-sunxi.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
index 677f865..3080190 100644
--- a/drivers/reset/reset-sunxi.c
+++ b/drivers/reset/reset-sunxi.c
@@ -165,21 +165,11 @@ static int sunxi_reset_probe(struct platform_device *pdev)
 	data->rcdev.ops = &sunxi_reset_ops;
 	data->rcdev.of_node = pdev->dev.of_node;
 
-	return reset_controller_register(&data->rcdev);
-}
-
-static int sunxi_reset_remove(struct platform_device *pdev)
-{
-	struct sunxi_reset_data *data = platform_get_drvdata(pdev);
-
-	reset_controller_unregister(&data->rcdev);
-
-	return 0;
+	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
 }
 
 static struct platform_driver sunxi_reset_driver = {
 	.probe	= sunxi_reset_probe,
-	.remove	= sunxi_reset_remove,
 	.driver = {
 		.name		= "sunxi-reset",
 		.of_match_table	= sunxi_reset_dt_ids,
-- 
1.9.1



From yamada.masahiro at socionext.com  Sun May  1 03:36:58 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Sun,  1 May 2016 19:36:58 +0900
Subject: [PATCH 2/7] reset: ath79: use devm_reset_controller_register()
In-Reply-To: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462099023-11819-3-git-send-email-yamada.masahiro@socionext.com>

Use devm_reset_controller_register() for the reset controller
registration and remove the unregister call from the .remove callback.

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

 drivers/reset/reset-ath79.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/reset/reset-ath79.c b/drivers/reset/reset-ath79.c
index ccb940a..16d410c 100644
--- a/drivers/reset/reset-ath79.c
+++ b/drivers/reset/reset-ath79.c
@@ -112,7 +112,7 @@ static int ath79_reset_probe(struct platform_device *pdev)
 	ath79_reset->rcdev.of_reset_n_cells = 1;
 	ath79_reset->rcdev.nr_resets = 32;
 
-	err = reset_controller_register(&ath79_reset->rcdev);
+	err = devm_reset_controller_register(&pdev->dev, &ath79_reset->rcdev);
 	if (err)
 		return err;
 
@@ -131,7 +131,6 @@ static int ath79_reset_remove(struct platform_device *pdev)
 	struct ath79_reset *ath79_reset = platform_get_drvdata(pdev);
 
 	unregister_restart_handler(&ath79_reset->restart_nb);
-	reset_controller_unregister(&ath79_reset->rcdev);
 
 	return 0;
 }
-- 
1.9.1



From yamada.masahiro at socionext.com  Sun May  1 03:36:57 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Sun,  1 May 2016 19:36:57 +0900
Subject: [PATCH 1/7] reset: add devm_reset_controller_register API
In-Reply-To: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462099023-11819-2-git-send-email-yamada.masahiro@socionext.com>

Add a device managed API for reset_controller_register().

This helps in reducing code in .remove callbacks and sometimes
dropping .remove callbacks entirely.

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

 Documentation/driver-model/devres.txt |  4 ++++
 drivers/reset/core.c                  | 37 +++++++++++++++++++++++++++++++++++
 include/linux/reset-controller.h      |  4 ++++
 3 files changed, 45 insertions(+)

diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 108d455..5270435 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -340,6 +340,10 @@ REGULATOR
   devm_regulator_put()
   devm_regulator_register()
 
+RESET
+  devm_reset_control_get()
+  devm_reset_controller_register()
+
 SLAVE DMA ENGINE
   devm_acpi_dma_controller_register()
 
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index f15f150..181b05d 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -82,6 +82,43 @@ void reset_controller_unregister(struct reset_controller_dev *rcdev)
 }
 EXPORT_SYMBOL_GPL(reset_controller_unregister);
 
+static void devm_reset_controller_release(struct device *dev, void *res)
+{
+	reset_controller_unregister(*(struct reset_controller_dev **)res);
+}
+
+/**
+ * devm_reset_controller_register - resource managed reset_controller_register()
+ * @dev: device that is registering this reset controller
+ * @rcdev: a pointer to the initialized reset controller device
+ *
+ * Managed reset_controller_register(). For reset controllers registered by
+ * this function, reset_controller_unregister() is automatically called on
+ * driver detach. See reset_controller_register() for more information.
+ */
+int devm_reset_controller_register(struct device *dev,
+				   struct reset_controller_dev *rcdev)
+{
+	struct reset_controller_dev **rcdevp;
+	int ret;
+
+	rcdevp = devres_alloc(devm_reset_controller_release, sizeof(*rcdevp),
+			      GFP_KERNEL);
+	if (!rcdevp)
+		return -ENOMEM;
+
+	ret = reset_controller_register(rcdev);
+	if (!ret) {
+		*rcdevp = rcdev;
+		devres_add(dev, rcdevp);
+	} else {
+		devres_free(rcdevp);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(devm_reset_controller_register);
+
 /**
  * reset_control_reset - reset the controlled device
  * @rstc: reset controller
diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
index a3a5bcd..a4eaf1c 100644
--- a/include/linux/reset-controller.h
+++ b/include/linux/reset-controller.h
@@ -51,4 +51,8 @@ struct reset_controller_dev {
 int reset_controller_register(struct reset_controller_dev *rcdev);
 void reset_controller_unregister(struct reset_controller_dev *rcdev);
 
+struct device;
+int devm_reset_controller_register(struct device *dev,
+				   struct reset_controller_dev *rcdev);
+
 #endif
-- 
1.9.1



From yamada.masahiro at socionext.com  Sun May  1 03:37:03 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Sun,  1 May 2016 19:37:03 +0900
Subject: [PATCH 7/7] reset: zynq: use devm_reset_controller_register()
In-Reply-To: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462099023-11819-8-git-send-email-yamada.masahiro@socionext.com>

Use devm_reset_controller_register() for the reset controller
registration and drop the .remove callback.

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

 drivers/reset/reset-zynq.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/reset/reset-zynq.c b/drivers/reset/reset-zynq.c
index a7e87bc..138f2f2 100644
--- a/drivers/reset/reset-zynq.c
+++ b/drivers/reset/reset-zynq.c
@@ -122,16 +122,7 @@ static int zynq_reset_probe(struct platform_device *pdev)
 	priv->rcdev.ops = &zynq_reset_ops;
 	priv->rcdev.of_node = pdev->dev.of_node;
 
-	return reset_controller_register(&priv->rcdev);
-}
-
-static int zynq_reset_remove(struct platform_device *pdev)
-{
-	struct zynq_reset_data *priv = platform_get_drvdata(pdev);
-
-	reset_controller_unregister(&priv->rcdev);
-
-	return 0;
+	return devm_reset_controller_register(&pdev->dev, &priv->rcdev);
 }
 
 static const struct of_device_id zynq_reset_dt_ids[] = {
@@ -141,7 +132,6 @@ static const struct of_device_id zynq_reset_dt_ids[] = {
 
 static struct platform_driver zynq_reset_driver = {
 	.probe	= zynq_reset_probe,
-	.remove	= zynq_reset_remove,
 	.driver = {
 		.name		= KBUILD_MODNAME,
 		.of_match_table	= zynq_reset_dt_ids,
-- 
1.9.1



From yamada.masahiro at socionext.com  Sun May  1 03:36:56 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Sun,  1 May 2016 19:36:56 +0900
Subject: [PATCH 0/7] reset: add managned reset_controller_register()
Message-ID: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>


Masahiro Yamada (7):
  reset: add devm_reset_controller_register API
  reset: ath79: use devm_reset_controller_register()
  reset: lpc18xx: use devm_reset_controller_register()
  reset: pistachio: use devm_reset_controller_register()
  reset: sunxi: use devm_reset_controller_register()
  reset: socfpga: use devm_reset_controller_register()
  reset: zynq: use devm_reset_controller_register()

 Documentation/driver-model/devres.txt |  4 ++++
 drivers/reset/core.c                  | 37 +++++++++++++++++++++++++++++++++++
 drivers/reset/reset-ath79.c           |  3 +--
 drivers/reset/reset-lpc18xx.c         |  4 +---
 drivers/reset/reset-pistachio.c       | 12 +-----------
 drivers/reset/reset-socfpga.c         | 12 +-----------
 drivers/reset/reset-sunxi.c           | 12 +-----------
 drivers/reset/reset-zynq.c            | 12 +-----------
 include/linux/reset-controller.h      |  4 ++++
 9 files changed, 51 insertions(+), 49 deletions(-)

-- 
1.9.1



From chunkeey at googlemail.com  Sun May  1 05:18:37 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Sun,  1 May 2016 14:18:37 +0200
Subject: [RFC v6 1/3] gpio: dt-bindings: add wd,mbl-gpio bindings
In-Reply-To: <cover.1462104492.git.chunkeey@googlemail.com>
References: <cover.1462104492.git.chunkeey@googlemail.com>
Message-ID: <103bf8fceb426a9c3b09641ea989955e3ec1c7d4.1462104492.git.chunkeey@googlemail.com>

This patch adds the device tree bindings for the Western Digital's
MyBook Live memory-mapped GPIO controllers.

The gpios will be supported by gpio-mmio code of the
GPIO generic library.

Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
---
 .../devicetree/bindings/gpio/wd,mbl-gpio.txt       | 38 ++++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt

diff --git a/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
new file mode 100644
index 0000000..038c3a6
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
@@ -0,0 +1,38 @@
+Bindings for the Western Digital's MyBook Live memory-mapped GPIO controllers.
+
+The Western Digital MyBook Live has two memory-mapped GPIO controllers.
+Both GPIO controller only have a single 8-bit data register, where GPIO
+state can be read and/or written.
+
+Required properties:
+	- compatible: should be "wd,mbl-gpio"
+	- reg-names: must contain
+		"dat" - data register
+	- reg: address + size pairs describing the GPIO register sets;
+		order must correspond with the order of entries in reg-names
+	- #gpio-cells: must be set to 2. The first cell is the pin number and
+			the second cell is used to specify the gpio polarity:
+			0 = active high
+			1 = active low
+	- gpio-controller: Marks the device node as a gpio controller.
+
+Optional properties:
+	- no-output: GPIOs are read-only.
+
+Examples:
+	gpio0: gpio0 at e0000000 {
+		compatible = "wd,mbl-gpio";
+		reg-names = "dat";
+		reg = <0xe0000000 0x1>;
+		#gpio-cells = <2>;
+		gpio-controller;
+	};
+
+	gpio1: gpio1 at e0100000 {
+		compatible = "wd,mbl-gpio";
+		reg-names = "dat";
+		reg = <0xe0100000 0x1>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		no-output;
+	};
-- 
2.8.1



From chunkeey at googlemail.com  Sun May  1 05:18:36 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Sun,  1 May 2016 14:18:36 +0200
Subject: [RFC v6 0/3] gpio: add DT support for memory-mapped GPIOs
Message-ID: <cover.1462104492.git.chunkeey@googlemail.com>

This patch series adds device tree support for generic memory-mapped GPIOs.
The GPIO library already allows drivers and architecture support code to
reuse generic code for managing a GPIO chip. Currently, a developer has
to create a platform device "basic-mmio-gpio" and attach a bgpio_pdata
platform data structure to make use of it. However, for architectures
which rely on the device tree to enumerate devices, creating custom
platform devices is another extra step that can be avoided by having
direct support via a device tree binding.

I initially came across this patch [0] from ?lvaro Fern?ndez Rojas,
while looking for an easy way to add support for the GPIO of my
WD MyBook Live [1] (APM82181 - ppc464). His generic approach patch
allowed me to easily get the GPIO (and the connected LEDs,
buttons, gpiohogs, etc.) up and running. Even thought, Mr. Fernandez
initially developed it for his work on the brcm63xx [2].

The drivers for gpio-clps711x, gpio-ge, gpio-moxart and gpio-ts4800
are now part of the gpio-mmio.c driver. The old driver files have
been removed and the Kconfig, Makefile entries have been updated
accordingly.

And finally, the most important stat about the series:
	>>> 333 insertions(+), 411 deletions(-) <<<
	It still removes more lines than it adds!

Thanks! (Please keep me in the CC)

[0] <https://patchwork.ozlabs.org/patch/422121/>
[1] <https://github.com/chunkeey/MBL-openwrt>
[2] <https://wiki.openwrt.org/doc/hardware/soc/soc.broadcom.bcm63xx>

changelog:

v5 -> v6:
	- rewrote bindings and driver patch to fit the wd,mbl-gpio
	- unified parser code for gpio-ge, gpio-moxart and gpio-ts4800
	- fixed gpio chip's base being overwritten with bogus "0"
	- fixed compat driver crash when reload gpio-generic.ko module
	- dropped already applied patches from the series
	- rebased code on linus' devel tree
	- moved dt bindings patch to the top of the series

v4 -> v5:
	- reverted rename of gpio-mmio.c back to gpio-generic.c
	- fixed Andy Shevchenko's comments
	- consolidated changes from clps711x, gpio-ge, gpio-moxart and
	  gpio-ts4800 into one patch.

v3 -> v4:
	- renamed gpio-generic.c to gpio-mmio.c
	- changed compat. string to "linux,gpio-mmio"
	- integrated Cirrus clps711x driver
	- integrated GE FGPA gpio-ge driver
	- integrated MOXA ART GPIO driver
	- integrated TS4800 gpio driver
	- reshuffled patches, reworded commits, fixed spelling errors, etc.

Christian Lamparter (2):
  gpio: dt-bindings: add wd,mbl-gpio bindings
  gpio: move clps711x, moxart, ts4800 and gpio-ge into gpio-mmio

?lvaro Fern?ndez Rojas (1):
  gpio: mmio: add DT support for memory-mapped GPIOs

 .../devicetree/bindings/gpio/wd,mbl-gpio.txt       |  38 +++
 drivers/gpio/Kconfig                               |  43 +--
 drivers/gpio/Makefile                              |   4 -
 drivers/gpio/gpio-clps711x.c                       |  91 -------
 drivers/gpio/gpio-ge.c                             | 114 --------
 drivers/gpio/gpio-mmio.c                           | 289 ++++++++++++++++++++-
 drivers/gpio/gpio-moxart.c                         |  84 ------
 drivers/gpio/gpio-ts4800.c                         |  81 ------
 8 files changed, 333 insertions(+), 411 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
 delete mode 100644 drivers/gpio/gpio-clps711x.c
 delete mode 100644 drivers/gpio/gpio-ge.c
 delete mode 100644 drivers/gpio/gpio-moxart.c
 delete mode 100644 drivers/gpio/gpio-ts4800.c

-- 
2.8.1



From chunkeey at googlemail.com  Sun May  1 05:18:38 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Sun,  1 May 2016 14:18:38 +0200
Subject: [RFC v6 2/3] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <cover.1462104492.git.chunkeey@googlemail.com>
References: <cover.1462104492.git.chunkeey@googlemail.com>
Message-ID: <891081fc8cc10771d235f5ba04e13e08144293c9.1462104492.git.chunkeey@googlemail.com>

From: ?lvaro Fern?ndez Rojas <noltari at gmail.com>

This patch adds support for defining memory-mapped GPIOs which
are compatible with the existing gpio-mmio interface. The generic
library provides support for many memory-mapped GPIO controllers
that are found in various on-board FPGA and ASIC solutions that
are used to control board's switches, LEDs, chip-selects,
Ethernet/USB PHY power, etc.

For setting GPIO's there are three configurations:
	1. single input/output register resource (named "dat"),
	2. set/clear pair (named "set" and "clr"),
	3. single output register resource and single input resource
	   ("set" and dat").

The configuration is detected by which resources are present.
For the single output register, this drives a 1 by setting a bit
and a zero by clearing a bit.  For the set clr pair, this drives
a 1 by setting a bit in the set register and clears it by setting
a bit in the clear register. The configuration is detected by
which resources are present.

For setting the GPIO direction, there are three configurations:
	a. simple bidirectional GPIOs that requires no configuration.
	b. an output direction register (named "dirout")
	   where a 1 bit indicates the GPIO is an output.
	c. an input direction register (named "dirin")
	   where a 1 bit indicates the GPIO is an input.

The first user for this binding is "wd,mbl-gpio".

Signed-off-by: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
---
 drivers/gpio/gpio-mmio.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 6c1cb3b..1cfb70a 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -61,6 +61,8 @@ o        `                     ~~~~\___/~~~~    ` controller in FPGA is ,.`
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
 #include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 static void bgpio_write8(void __iomem *reg, unsigned long data)
 {
@@ -569,6 +571,89 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
 	return devm_ioremap_resource(&pdev->dev, r);
 }
 
+#ifdef CONFIG_OF
+static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
+				     struct bgpio_pdata *pdata,
+				     unsigned long *flags)
+{
+	struct device *dev = &pdev->dev;
+	int err;
+
+	pdata->base = -1;
+	/* If ngpio property is not specified, of_property_read_u32
+	 * will return -EINVAL. In this case the number of GPIOs is
+	 * automatically determined by the register width. Any
+	 * other error of of_property_read_u32 is due bad data and
+	 * needs to be dealt with.
+	 */
+	err = of_property_read_u32(dev->of_node, "ngpio", &pdata->ngpio);
+	if (err && err != -EINVAL)
+		return err;
+
+	if (of_device_is_big_endian(dev->of_node))
+		*flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
+
+	if (of_property_read_bool(dev->of_node, "unreadable-reg-set"))
+		*flags |= BGPIOF_UNREADABLE_REG_SET;
+
+	if (of_property_read_bool(dev->of_node, "unreadable-reg-dir"))
+		*flags |= BGPIOF_UNREADABLE_REG_DIR;
+
+	if (of_property_read_bool(dev->of_node, "big-endian-byte-order"))
+		*flags |= BGPIOF_BIG_ENDIAN;
+
+	if (of_property_read_bool(dev->of_node, "read-output-reg-set"))
+		*flags |= BGPIOF_READ_OUTPUT_REG_SET;
+
+	if (of_property_read_bool(dev->of_node, "no-output"))
+		*flags |= BGPIOF_NO_OUTPUT;
+	return 0;
+}
+
+#define ADD(_name, _func) { .compatible = _name, .data = _func }
+
+static const struct of_device_id bgpio_of_match[] = {
+	ADD("wd,mbl-gpio", bgpio_basic_mmio_parse_dt),
+	{ }
+};
+#undef ADD
+MODULE_DEVICE_TABLE(of, bgpio_of_match);
+
+static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
+					  unsigned long *flags)
+{
+	const int (*parse_dt)(struct platform_device *,
+			      struct bgpio_pdata *, unsigned long *);
+	const struct device_node *node = pdev->dev.of_node;
+	const struct of_device_id *of_id;
+	struct bgpio_pdata *pdata;
+	int err = -ENODEV;
+
+	of_id = of_match_node(bgpio_of_match, node);
+	if (!of_id)
+		return NULL;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata),
+			     GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	parse_dt = (const void *)of_id->data;
+	if (parse_dt)
+		err = parse_dt(pdev, pdata, flags);
+	if (err)
+		return ERR_PTR(err);
+
+	return pdata;
+}
+#else
+static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
+					  unsigned long *flags)
+{
+	return NULL;
+}
+#endif /* CONFIG_OF */
+
 static int bgpio_pdev_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -579,10 +664,19 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
 	void __iomem *dirout;
 	void __iomem *dirin;
 	unsigned long sz;
-	unsigned long flags = pdev->id_entry->driver_data;
+	unsigned long flags = 0;
 	int err;
 	struct gpio_chip *gc;
-	struct bgpio_pdata *pdata = dev_get_platdata(dev);
+	struct bgpio_pdata *pdata;
+
+	pdata = bgpio_parse_dt(pdev, &flags);
+	if (IS_ERR(pdata))
+		return PTR_ERR(pdata);
+
+	if (!pdata) {
+		pdata = dev_get_platdata(dev);
+		flags = pdev->id_entry->driver_data;
+	}
 
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
 	if (!r)
@@ -646,6 +740,7 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table);
 static struct platform_driver bgpio_driver = {
 	.driver = {
 		.name = "basic-mmio-gpio",
+		.of_match_table = of_match_ptr(bgpio_of_match),
 	},
 	.id_table = bgpio_id_table,
 	.probe = bgpio_pdev_probe,
-- 
2.8.1



From chunkeey at googlemail.com  Sun May  1 05:18:39 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Sun,  1 May 2016 14:18:39 +0200
Subject: [RFC v6 3/3] gpio: move clps711x, moxart,
 ts4800 and gpio-ge into gpio-mmio
In-Reply-To: <cover.1462104492.git.chunkeey@googlemail.com>
References: <cover.1462104492.git.chunkeey@googlemail.com>
Message-ID: <ee8ec54d026fd6ec0bed852a9ae51f8604fc8547.1462104492.git.chunkeey@googlemail.com>

This patch integrates these GPIO drivers into gpio-mmio.

Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
---
 drivers/gpio/Kconfig         |  43 ++--------
 drivers/gpio/Makefile        |   4 -
 drivers/gpio/gpio-clps711x.c |  91 ---------------------
 drivers/gpio/gpio-ge.c       | 114 --------------------------
 drivers/gpio/gpio-mmio.c     | 190 +++++++++++++++++++++++++++++++++++++++++++
 drivers/gpio/gpio-moxart.c   |  84 -------------------
 drivers/gpio/gpio-ts4800.c   |  81 ------------------
 7 files changed, 198 insertions(+), 409 deletions(-)
 delete mode 100644 drivers/gpio/gpio-clps711x.c
 delete mode 100644 drivers/gpio/gpio-ge.c
 delete mode 100644 drivers/gpio/gpio-moxart.c
 delete mode 100644 drivers/gpio/gpio-ts4800.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index f73f26b..df6ca48 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -152,13 +152,6 @@ config GPIO_BRCMSTB
 	help
 	  Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs.
 
-config GPIO_CLPS711X
-	tristate "CLPS711X GPIO support"
-	depends on ARCH_CLPS711X || COMPILE_TEST
-	select GPIO_GENERIC
-	help
-	  Say yes here to support GPIO on CLPS711X SoCs.
-
 config GPIO_DAVINCI
 	bool "TI Davinci/Keystone GPIO support"
 	default y if ARCH_DAVINCI
@@ -194,22 +187,18 @@ config GPIO_ETRAXFS
 	help
 	  Say yes here to support the GPIO controller on Axis ETRAX FS SoCs.
 
-config GPIO_GE_FPGA
-	bool "GE FPGA based GPIO"
-	depends on GE_FPGA
-	select GPIO_GENERIC
-	help
-	  Support for common GPIO functionality provided on some GE Single Board
-	  Computers.
-
-	  This driver provides basic support (configure as input or output, read
-	  and write pin state) for GPIO implemented in a number of GE single
-	  board computers.
-
 config GPIO_GENERIC_PLATFORM
 	tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
 	select GPIO_GENERIC
 	help
+	  Select this to support many generic memory-mapped GPIO controllers.
+
+	  This driver also includes support for the following GPIOs:
+	    CLPS711X SoCs
+	    MOXA ART SoC
+	    TS-4800 FPGA DIO blocks and compatibles.
+	    GPIOs found on some GE Single Board Computers.
+
 	  Say yes here to support basic platform_device memory-mapped GPIO controllers.
 
 config GPIO_GRGPIO
@@ -286,14 +275,6 @@ config GPIO_MM_LANTIQ
 	  (EBU) found on Lantiq SoCs. The gpios are output only as they are
 	  created by attaching a 16bit latch to the bus.
 
-config GPIO_MOXART
-	bool "MOXART GPIO support"
-	depends on ARCH_MOXART || COMPILE_TEST
-	select GPIO_GENERIC
-	help
-	  Select this option to enable GPIO driver for
-	  MOXA ART SoC devices.
-
 config GPIO_MPC5200
 	def_bool y
 	depends on PPC_MPC52xx
@@ -405,14 +386,6 @@ config GPIO_TEGRA
 	default y
 	depends on ARCH_TEGRA || COMPILE_TEST
 
-config GPIO_TS4800
-	tristate "TS-4800 DIO blocks and compatibles"
-	depends on OF_GPIO
-	depends on SOC_IMX51 || COMPILE_TEST
-	select GPIO_GENERIC
-	help
-	  This driver support TS-4800 FPGA GPIO controllers.
-
 config GPIO_TZ1090
 	bool "Toumaz Xenif TZ1090 GPIO support"
 	depends on SOC_TZ1090
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 991598e..d8d63ae 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -31,7 +31,6 @@ obj-$(CONFIG_GPIO_ATH79)	+= gpio-ath79.o
 obj-$(CONFIG_GPIO_BCM_KONA)	+= gpio-bcm-kona.o
 obj-$(CONFIG_GPIO_BRCMSTB)	+= gpio-brcmstb.o
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
-obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o
 obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o
 obj-$(CONFIG_GPIO_CRYSTAL_COVE)	+= gpio-crystalcove.o
 obj-$(CONFIG_GPIO_DA9052)	+= gpio-da9052.o
@@ -43,7 +42,6 @@ obj-$(CONFIG_GPIO_EM)		+= gpio-em.o
 obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o
 obj-$(CONFIG_GPIO_ETRAXFS)	+= gpio-etraxfs.o
 obj-$(CONFIG_GPIO_F7188X)	+= gpio-f7188x.o
-obj-$(CONFIG_GPIO_GE_FPGA)	+= gpio-ge.o
 obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o
 obj-$(CONFIG_GPIO_ICH)		+= gpio-ich.o
 obj-$(CONFIG_GPIO_IOP)		+= gpio-iop.o
@@ -68,7 +66,6 @@ obj-$(CONFIG_GPIO_MC9S08DZ60)	+= gpio-mc9s08dz60.o
 obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)	+= gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MM_LANTIQ)	+= gpio-mm-lantiq.o
-obj-$(CONFIG_GPIO_MOXART)	+= gpio-moxart.o
 obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSIC)		+= gpio-msic.o
@@ -107,7 +104,6 @@ obj-$(CONFIG_GPIO_TPS65218)	+= gpio-tps65218.o
 obj-$(CONFIG_GPIO_TPS6586X)	+= gpio-tps6586x.o
 obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
 obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
-obj-$(CONFIG_GPIO_TS4800)	+= gpio-ts4800.o
 obj-$(CONFIG_GPIO_TS5500)	+= gpio-ts5500.o
 obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
 obj-$(CONFIG_GPIO_TWL6040)	+= gpio-twl6040.o
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
deleted file mode 100644
index 5a69025..0000000
--- a/drivers/gpio/gpio-clps711x.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  CLPS711X GPIO driver
- *
- *  Copyright (C) 2012,2013 Alexander Shiyan <shc_work at mail.ru>
- *
- * 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.
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/gpio/driver.h>
-#include <linux/platform_device.h>
-
-static int clps711x_gpio_probe(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	void __iomem *dat, *dir;
-	struct gpio_chip *gc;
-	struct resource *res;
-	int err, id = np ? of_alias_get_id(np, "gpio") : pdev->id;
-
-	if ((id < 0) || (id > 4))
-		return -ENODEV;
-
-	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	dat = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dat))
-		return PTR_ERR(dat);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	dir = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dir))
-		return PTR_ERR(dir);
-
-	switch (id) {
-	case 3:
-		/* PORTD is inverted logic for direction register */
-		err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
-				 NULL, dir, 0);
-		break;
-	default:
-		err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
-				 dir, NULL, 0);
-		break;
-	}
-
-	if (err)
-		return err;
-
-	switch (id) {
-	case 4:
-		/* PORTE is 3 lines only */
-		gc->ngpio = 3;
-		break;
-	default:
-		break;
-	}
-
-	gc->base = id * 8;
-	gc->owner = THIS_MODULE;
-	platform_set_drvdata(pdev, gc);
-
-	return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
-}
-
-static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = {
-	{ .compatible = "cirrus,clps711x-gpio" },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, clps711x_gpio_ids);
-
-static struct platform_driver clps711x_gpio_driver = {
-	.driver	= {
-		.name		= "clps711x-gpio",
-		.of_match_table	= of_match_ptr(clps711x_gpio_ids),
-	},
-	.probe	= clps711x_gpio_probe,
-};
-module_platform_driver(clps711x_gpio_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Alexander Shiyan <shc_work at mail.ru>");
-MODULE_DESCRIPTION("CLPS711X GPIO driver");
-MODULE_ALIAS("platform:clps711x-gpio");
diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c
deleted file mode 100644
index 8650b29..0000000
--- a/drivers/gpio/gpio-ge.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Driver for GE FPGA based GPIO
- *
- * Author: Martyn Welch <martyn.welch at ge.com>
- *
- * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-/* TODO
- *
- * Configuration of output modes (totem-pole/open-drain)
- * Interrupt configuration - interrupts are always generated the FPGA relies on
- * the I/O interrupt controllers mask to stop them propergating
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/of_address.h>
-#include <linux/module.h>
-#include <linux/gpio/driver.h>
-
-#define GEF_GPIO_DIRECT		0x00
-#define GEF_GPIO_IN		0x04
-#define GEF_GPIO_OUT		0x08
-#define GEF_GPIO_TRIG		0x0C
-#define GEF_GPIO_POLAR_A	0x10
-#define GEF_GPIO_POLAR_B	0x14
-#define GEF_GPIO_INT_STAT	0x18
-#define GEF_GPIO_OVERRUN	0x1C
-#define GEF_GPIO_MODE		0x20
-
-static const struct of_device_id gef_gpio_ids[] = {
-	{
-		.compatible	= "gef,sbc610-gpio",
-		.data		= (void *)19,
-	}, {
-		.compatible	= "gef,sbc310-gpio",
-		.data		= (void *)6,
-	}, {
-		.compatible	= "ge,imp3a-gpio",
-		.data		= (void *)16,
-	},
-	{ }
-};
-MODULE_DEVICE_TABLE(of, gef_gpio_ids);
-
-static int __init gef_gpio_probe(struct platform_device *pdev)
-{
-	const struct of_device_id *of_id =
-		of_match_device(gef_gpio_ids, &pdev->dev);
-	struct gpio_chip *gc;
-	void __iomem *regs;
-	int ret;
-
-	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	regs = of_iomap(pdev->dev.of_node, 0);
-	if (!regs)
-		return -ENOMEM;
-
-	ret = bgpio_init(gc, &pdev->dev, 4, regs + GEF_GPIO_IN,
-			 regs + GEF_GPIO_OUT, NULL, NULL,
-			 regs + GEF_GPIO_DIRECT, BGPIOF_BIG_ENDIAN_BYTE_ORDER);
-	if (ret) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		goto err0;
-	}
-
-	/* Setup pointers to chip functions */
-	gc->label = devm_kstrdup(&pdev->dev, pdev->dev.of_node->full_name,
-				     GFP_KERNEL);
-	if (!gc->label) {
-		ret = -ENOMEM;
-		goto err0;
-	}
-
-	gc->base = -1;
-	gc->ngpio = (u16)(uintptr_t)of_id->data;
-	gc->of_gpio_n_cells = 2;
-	gc->of_node = pdev->dev.of_node;
-
-	/* This function adds a memory mapped GPIO chip */
-	ret = devm_gpiochip_add_data(&pdev->dev, gc, NULL);
-	if (ret)
-		goto err0;
-
-	return 0;
-err0:
-	iounmap(regs);
-	pr_err("%s: GPIO chip registration failed\n",
-			pdev->dev.of_node->full_name);
-	return ret;
-};
-
-static struct platform_driver gef_gpio_driver = {
-	.driver = {
-		.name		= "gef-gpio",
-		.of_match_table	= gef_gpio_ids,
-	},
-};
-module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);
-
-MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
-MODULE_AUTHOR("Martyn Welch <martyn.welch at ge.com");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 1cfb70a..f116786 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -610,10 +610,200 @@ static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
 	return 0;
 }
 
+static int clps711x_parse_dt(struct platform_device *pdev,
+			     struct bgpio_pdata *pdata,
+			     unsigned long *flags)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	const char *dir_reg_name;
+	int id = np ? of_alias_get_id(np, "gpio") : pdev->id;
+
+	if ((id < 0) || (id > 4))
+		return -ENODEV;
+
+	/* PORTE is 3 lines only */
+	pdata->ngpio = (id == 4) ? 3 : /* determined by register width */ 0;
+
+	/* PORTD is inverted logic for direction register */
+	dir_reg_name = (id == 3) ? "dirin" : "dirout",
+
+	pdata->base = id * 8;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+	if (!res->name || strcmp("dat", res->name))
+		res->name = devm_kstrdup(&pdev->dev, "dat", GFP_KERNEL);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -EINVAL;
+	if (!res->name || strcmp(dir_reg_name, res->name))
+		res->name = devm_kstrdup(&pdev->dev, dir_reg_name, GFP_KERNEL);
+
+	return 0;
+}
+
+static int ge_dt_cb(struct platform_device *pdev,
+		    struct bgpio_pdata *pdata,
+		    unsigned long *flags)
+{
+	struct device_node *np = pdev->dev.of_node;
+
+	pdata->label = devm_kstrdup(&pdev->dev, np->full_name, GFP_KERNEL);
+	if (!pdata->label)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int moxart_dt_cb(struct platform_device *pdev,
+			struct bgpio_pdata *pdata,
+			unsigned long *flags)
+{
+	pdata->base = 0;
+	pdata->label = "moxart-gpio";
+	return 0;
+}
+
+
+static int ts4800_dt_cb(struct platform_device *pdev,
+			struct bgpio_pdata *pdata,
+			unsigned long *flags)
+{
+	int err;
+
+	err = of_property_read_u32(pdev->dev.of_node, "ngpios", &pdata->ngpio);
+	if (err == -EINVAL) {
+		pdata->ngpio = 16;
+		err = 0;
+	}
+	return err;
+}
+
+struct compat_gpio_device_data {
+	unsigned int expected_resource_size;
+	unsigned int ngpio;
+	resource_size_t register_width;
+	unsigned long flags;
+	int (*call_back)(struct platform_device *pdev,
+			 struct bgpio_pdata *pdata,
+			 unsigned long *flags);
+	struct resource_replacement {
+		resource_size_t start_offset;
+		const char *name;
+	} resources[5];
+};
+
+#define ADD_COMPAT_REGISTER(_name, _offset)	\
+	{ .name = (_name), .start_offset = (_offset) }
+
+#define ADD_COMPAT_GPIO(_comp, _sz, _ngpio, _width, _cb, _f, _res...)	\
+	{ .compatible = (_comp),					\
+	  .data = &(struct compat_gpio_device_data) {			\
+		.expected_resource_size = (_sz),			\
+		.ngpio = (_ngpio),					\
+		.register_width = (_width),				\
+		.flags = (_f),						\
+		.call_back = (_cb),					\
+		.resources = { _res },					\
+	}								\
+}
+
+#define ADD_COMPAT_GE_GPIO(_name, _ngpio)				\
+	ADD_COMPAT_GPIO(_name, 0x24, _ngpio, 0x4, ge_dt_cb,		\
+		 BGPIOF_BIG_ENDIAN_BYTE_ORDER,				\
+		 ADD_COMPAT_REGISTER("dat", 0x04),			\
+		 ADD_COMPAT_REGISTER("set", 0x08),			\
+		 ADD_COMPAT_REGISTER("dirin", 0x00))			\
+
+static const struct of_device_id compat_gpio_devices[] = {
+	ADD_COMPAT_GE_GPIO("ge,imp3a-gpio", 16),
+	ADD_COMPAT_GE_GPIO("gef,sbc310-gpio", 6),
+	ADD_COMPAT_GE_GPIO("gef,sbc610-gpio", 19),
+	ADD_COMPAT_GPIO("moxa,moxart-gpio", 0xc, 0, 0x4, moxart_dt_cb,
+		 BGPIOF_READ_OUTPUT_REG_SET,
+		 ADD_COMPAT_REGISTER("dat", 0x04),
+		 ADD_COMPAT_REGISTER("set", 0x00),
+		 ADD_COMPAT_REGISTER("dirout", 0x08)),
+	ADD_COMPAT_GPIO("technologic,ts4800-gpio", 0x6, 16, 0x2, ts4800_dt_cb,
+		 0, ADD_COMPAT_REGISTER("dat", 0x00),
+		 ADD_COMPAT_REGISTER("set", 0x02),
+		 ADD_COMPAT_REGISTER("dirout", 0x04)),
+};
+
+#undef ADD_COMPAT_GE_GPIO
+#undef ADD_COMPAT_GPIO
+#undef ADD_COMPAT_REGISTER
+
+static int compat_parse_dt(struct platform_device *pdev,
+			   struct bgpio_pdata *pdata,
+			   unsigned long *flags)
+{
+	const struct device_node *node = pdev->dev.of_node;
+	const struct compat_gpio_device_data *entry;
+	const struct of_device_id *of_id;
+	struct resource *res;
+	int err;
+
+	of_id = of_match_node(compat_gpio_devices, node);
+	if (!of_id)
+		return -ENODEV;
+
+	entry = of_id->data;
+	if (!entry || !entry->resources[0].name)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	if (!res->name || strcmp(entry->resources[0].name, res->name)) {
+		struct resource nres[ARRAY_SIZE(entry->resources)];
+		int i;
+
+		if (resource_size(res) != entry->expected_resource_size)
+			return -EINVAL;
+
+		for (i = 0; i < ARRAY_SIZE(entry->resources); i++) {
+			if (!entry->resources[i].name)
+				continue;
+
+			nres[i].name = devm_kstrdup(&pdev->dev,
+				entry->resources[i].name, GFP_KERNEL);
+			nres[i].start = res->start +
+				entry->resources[i].start_offset;
+			nres[i].end = nres[i].start +
+				entry->register_width - 1;
+			nres[i].flags = IORESOURCE_MEM;
+		}
+
+		err = platform_device_add_resources(pdev, nres, i);
+		if (err)
+			return err;
+	}
+
+	pdata->base = -1;
+	pdata->ngpio = entry->ngpio;
+	*flags = entry->flags;
+
+	if (entry->call_back)
+		err = entry->call_back(pdev, pdata, flags);
+
+	return err;
+}
+
 #define ADD(_name, _func) { .compatible = _name, .data = _func }
 
 static const struct of_device_id bgpio_of_match[] = {
 	ADD("wd,mbl-gpio", bgpio_basic_mmio_parse_dt),
+	ADD("cirrus,clps711x-gpio", clps711x_parse_dt),
+	ADD("ge,imp3a-gpio", compat_parse_dt),
+	ADD("gef,sbc310-gpio", compat_parse_dt),
+	ADD("gef,sbc610-gpio", compat_parse_dt),
+	ADD("moxa,moxart-gpio", compat_parse_dt),
+	ADD("technologic,ts4800-gpio", compat_parse_dt),
 	{ }
 };
 #undef ADD
diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c
deleted file mode 100644
index d58d389..0000000
--- a/drivers/gpio/gpio-moxart.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * MOXA ART SoCs GPIO driver.
- *
- * Copyright (C) 2013 Jonas Jensen
- *
- * Jonas Jensen <jonas.jensen at gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/of_address.h>
-#include <linux/of_gpio.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/bitops.h>
-#include <linux/gpio/driver.h>
-
-#define GPIO_DATA_OUT		0x00
-#define GPIO_DATA_IN		0x04
-#define GPIO_PIN_DIRECTION	0x08
-
-static int moxart_gpio_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct resource *res;
-	struct gpio_chip *gc;
-	void __iomem *base;
-	int ret;
-
-	gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	ret = bgpio_init(gc, dev, 4, base + GPIO_DATA_IN,
-			 base + GPIO_DATA_OUT, NULL,
-			 base + GPIO_PIN_DIRECTION, NULL,
-			 BGPIOF_READ_OUTPUT_REG_SET);
-	if (ret) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		return ret;
-	}
-
-	gc->label = "moxart-gpio";
-	gc->request = gpiochip_generic_request;
-	gc->free = gpiochip_generic_free;
-	gc->base = 0;
-	gc->owner = THIS_MODULE;
-
-	ret = devm_gpiochip_add_data(dev, gc, NULL);
-	if (ret) {
-		dev_err(dev, "%s: gpiochip_add failed\n",
-			dev->of_node->full_name);
-		return ret;
-	}
-
-	return ret;
-}
-
-static const struct of_device_id moxart_gpio_match[] = {
-	{ .compatible = "moxa,moxart-gpio" },
-	{ }
-};
-
-static struct platform_driver moxart_gpio_driver = {
-	.driver	= {
-		.name		= "moxart-gpio",
-		.of_match_table	= moxart_gpio_match,
-	},
-	.probe	= moxart_gpio_probe,
-};
-builtin_platform_driver(moxart_gpio_driver);
diff --git a/drivers/gpio/gpio-ts4800.c b/drivers/gpio/gpio-ts4800.c
deleted file mode 100644
index 0c144a7..0000000
--- a/drivers/gpio/gpio-ts4800.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * GPIO driver for the TS-4800 board
- *
- * Copyright (c) 2016 - Savoir-faire Linux
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/gpio/driver.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-
-#define DEFAULT_PIN_NUMBER      16
-#define INPUT_REG_OFFSET        0x00
-#define OUTPUT_REG_OFFSET       0x02
-#define DIRECTION_REG_OFFSET    0x04
-
-static int ts4800_gpio_probe(struct platform_device *pdev)
-{
-	struct device_node *node;
-	struct gpio_chip *chip;
-	struct resource *res;
-	void __iomem *base_addr;
-	int retval;
-	u32 ngpios;
-
-	chip = devm_kzalloc(&pdev->dev, sizeof(struct gpio_chip), GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base_addr = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(base_addr))
-		return PTR_ERR(base_addr);
-
-	node = pdev->dev.of_node;
-	if (!node)
-		return -EINVAL;
-
-	retval = of_property_read_u32(node, "ngpios", &ngpios);
-	if (retval == -EINVAL)
-		ngpios = DEFAULT_PIN_NUMBER;
-	else if (retval)
-		return retval;
-
-	retval = bgpio_init(chip, &pdev->dev, 2, base_addr + INPUT_REG_OFFSET,
-			    base_addr + OUTPUT_REG_OFFSET, NULL,
-			    base_addr + DIRECTION_REG_OFFSET, NULL, 0);
-	if (retval) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		return retval;
-	}
-
-	chip->ngpio = ngpios;
-
-	platform_set_drvdata(pdev, chip);
-
-	return devm_gpiochip_add_data(&pdev->dev, chip, NULL);
-}
-
-static const struct of_device_id ts4800_gpio_of_match[] = {
-	{ .compatible = "technologic,ts4800-gpio", },
-	{},
-};
-
-static struct platform_driver ts4800_gpio_driver = {
-	.driver = {
-		   .name = "ts4800-gpio",
-		   .of_match_table = ts4800_gpio_of_match,
-		   },
-	.probe = ts4800_gpio_probe,
-};
-
-module_platform_driver_probe(ts4800_gpio_driver, ts4800_gpio_probe);
-
-MODULE_AUTHOR("Julien Grossholtz <julien.grossholtz at savoirfairelinux.com>");
-MODULE_DESCRIPTION("TS4800 FPGA GPIO driver");
-MODULE_LICENSE("GPL v2");
-- 
2.8.1



From Julia.Lawall at lip6.fr  Sun May  1 05:49:15 2016
From: Julia.Lawall at lip6.fr (Julia Lawall)
Date: Sun,  1 May 2016 14:49:15 +0200
Subject: [PATCH] VSOCK: constify vsock_transport structure
Message-ID: <1462106955-22131-1-git-send-email-Julia.Lawall@lip6.fr>

The vsock_transport structure is never modified, so declare it as const.

Done with the help of Coccinelle.

Signed-off-by: Julia Lawall <Julia.Lawall at lip6.fr>

---
 net/vmw_vsock/vmci_transport.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
index 5621473..4120b7a 100644
--- a/net/vmw_vsock/vmci_transport.c
+++ b/net/vmw_vsock/vmci_transport.c
@@ -2051,7 +2051,7 @@ static u32 vmci_transport_get_local_cid(void)
 	return vmci_get_context_id();
 }
 
-static struct vsock_transport vmci_transport = {
+static const struct vsock_transport vmci_transport = {
 	.init = vmci_transport_socket_init,
 	.destruct = vmci_transport_destruct,
 	.release = vmci_transport_release,



From k.kozlowski at samsung.com  Sun May  1 06:17:46 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Sun, 1 May 2016 15:17:46 +0200
Subject: [RFT PATCH 0/3] usb: misc: usb3503: Fix missing device when TFTP
 booting
In-Reply-To: <57247E50.1020000@xs4all.nl>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <57247E50.1020000@xs4all.nl>
Message-ID: <20160501131746.GA16766@kozik-lap>

On Sat, Apr 30, 2016 at 11:43:44AM +0200, Hans Verkuil wrote:
> Hi Krzysztof,
> 
> On 04/29/2016 12:59 PM, Krzysztof Kozlowski wrote:
> > Hi,
> > 
> > Patches are independent, please pick up as you wish.
> > 
> > However all of them are needed to solve the issue, so I am sending
> > everything together for easier testng.
> > 
> > 
> > Problem
> > =======
> > When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
> > the usb3503 does not show up in "lsusb". Hard-reset is required, e.g.
> > by suspend to RAM. The actual TFTP boot does not have to happen. Just
> > "usb start" from U-Boot is sufficient.
> > 
> > 
> > Solution
> > ========
> > Perform real hardware reset (including regulator off/on) when probing.
> > 
> > 
> > Tested on Odroid U3 so far. Please kindly test on X2 and other
> > configurations and bootloaders.
> 
> Against which kernel git repo is this patch?
> 
> I did apply this patch series first:
> 
> http://www.spinics.net/lists/arm-kernel/msg500764.html

Indeed it is based on above patchset... and on linux-next. It touches
multiple trees so next seems the easiest base.

> 
> followed by this patch series.
> 
> I've tested with both 4.6.0-rc2 and -rc5, but in all cases (even without
> applying these patches!) the boot sequence hangs here:
> 
> ...
> [drm] Exynos DRM: using 12c10000.mixer device for DMA mapping operations
> exynos-drm exynos-drm: bound 12c10000.mixer (ops mixer_component_ops)
> exynos-drm exynos-drm: bound 12d00000.hdmi (ops hdmi_component_ops)
> [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
> [drm] No driver support for vblank timestamp query.
> Console: switching to colour frame buffer device 240x67
> exynos-drm exynos-drm: fb0:  frame buffer device
> [drm] Initialized exynos 1.0.0 20110530 on minor 0
> brd: module loaded
> loop: module loaded
> s3c64xx-spi 13930000.spi: spi bus clock parent not specified, using clock
> at index 0 as parent
> s3c64xx-spi 13930000.spi: number of chip select lines not specified,
> assuming 1 chip select line
> tun: Universal TUN/TAP device driver, 1.6
> tun: (C) 1999-2004 Max Krasnyansky <maxk at qualcomm.com>
> usbcore: registered new interface driver asix
> usbcore: registered new interface driver ax88179_178a
> usbcore: registered new interface driver cdc_ether
> usbcore: registered new interface driver smsc95xx
> usbcore: registered new interface driver cdc_ncm
> dwc2 12480000.hsotg: Specified GNPTXFDEP=1024 > 768
> dwc2 12480000.hsotg: EPs: 16, dedicated fifos, 7808 entries in SPRAM
> ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
> ehci-exynos: EHCI EXYNOS driver
> exynos-ehci 12580000.ehci: EHCI Host Controller
> exynos-ehci 12580000.ehci: new USB bus registered, assigned bus number 1
> exynos-ehci 12580000.ehci: irq 51, io mem 0x12580000
> exynos-ehci 12580000.ehci: USB 2.0 started, EHCI 1.00
> usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
> usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> usb usb1: Product: EHCI Host Controller
> usb usb1: Manufacturer: Linux 4.6.0-rc5-odroid ehci_hcd
> usb usb1: SerialNumber: 12580000.ehci
> hub 1-0:1.0: USB hub found
> hub 1-0:1.0: 3 ports detected
> ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
> ohci-exynos: OHCI EXYNOS driver
> usbcore: registered new interface driver usb-storage
> usb3503 0-0008: switched to HUB mode
> usb3503 0-0008: usb3503_probe: probed in hub mode
> using random self ethernet address
> using random host ethernet address
> usb0: HOST MAC 66:79:ef:11:72:85
> usb0: MAC 1e:66:f2:66:8e:2a
> using random self ethernet address
> using random host ethernet address
> g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
> g_ether gadget: g_ether ready
> dwc2 12480000.hsotg: bound driver g_ether
> mousedev: PS/2 mouse device common for all mice
> max77686-rtc max77686-rtc: rtc core: registered max77686-rtc as rtc0
> i2c /dev entries driver
> s5p-fimc-md camera: Entity type for entity FIMC.0 was not initialized!
> usb 1-2: new high-speed USB device number 2 using exynos-ehci
> usb 1-2: New USB device found, idVendor=0424, idProduct=9730
> usb 1-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
> smsc95xx v1.0.4
> smsc95xx 1-2:1.0 eth0: register 'smsc95xx' at usb-12580000.ehci-2, smsc95xx
> USB 2.0 Ethernet, c2:22:09:f2:5f:e8
> usb 1-3: new high-speed USB device number 3 using exynos-ehci
> usb 1-3: New USB device found, idVendor=0424, idProduct=3503
> usb 1-3: New USB device strings: Mfr=0, Product=0, SerialNumber=0
> hub 1-3:1.0: USB hub found
> hub 1-3:1.0: 3 ports detected
> 
> No oops, no nothing. It's just sitting there.

Apparently you have encountered different issue. sysrq with 'l' might be
useful.

> Is this a regression that was introduced in 4.6? Or is there some special
> new config that needs to be turned on first in 4.6?

I think it was like that for looong time... although I did not use
netboot before on that target.

> I've been running
> 4.5.0-rc3 before this, but I can't apply these patches there because there
> is no drivers/regulator/max77686-regulator.c in 4.5.

In that case skip the regulator patch or apply it for
drivers/regulator/max77686.c driver.

Best regards,
Krzysztof


From sakari.ailus at iki.fi  Sun May  1 07:08:31 2016
From: sakari.ailus at iki.fi (Sakari Ailus)
Date: Sun, 1 May 2016 17:08:31 +0300
Subject: camera application for testing (was Re: v4l subdevs without big
 device)
In-Reply-To: <20160429221359.GA29297@amd>
References: <20160428084546.GA9957@amd> <20160429071525.GA4823@amd>
 <57230DE7.3020701@xs4all.nl> <20160429221359.GA29297@amd>
Message-ID: <20160501140831.GH26360@valkosipuli.retiisi.org.uk>

Hi Pavel,

On Sat, Apr 30, 2016 at 12:13:59AM +0200, Pavel Machek wrote:
> Hi!
> 
> What is reasonable camera application for testing?
> 
> N900 looks like a low-end digital camera. I have now have the hardware
> working (can set focus to X cm using command line), but that's not
> going to be useful for taking photos.

I guess you already knew about omap3camd; it's proprietary but from purely
practical point of view it'd be an option to support taking photos on the
N900. That would not be extensible any way, the best possible functionality
is limited what the daemon implements.

I'm just mentioning the option of implementing wrapper for the omap3camd so
that it can work with upsteam APIs, I don't propose that however.

> 
> In particular, who is going to do computation neccessary for
> autofocus, whitebalance and exposure/gain?

I think libv4l itself has algorithms to control at least some of these. It
relies on the image data so the CPU time consumption will be high.

AFAIR Laurent has also worked on implementing some algorithms that use the
histogram and some of the statistics. Add him to cc list.

> 
> There's http://fcam.garage.maemo.org/gettingStarted.html that should
> work on maemo, but a) it is not in Debian, b) it has non-trivial
> dependencies and c) will be a lot of fun to get working...
> 
> (and d), will not be too useful, anyway, due to 1sec shutter lag:

I believe this will be shorter nowadays. I don't remember the exact
technical solution which the text below refers to but I'm pretty sure it'll
be better with the current upstream. API-wise, there's work to be done there
(to port FCAM to upsteram APIs) but it's a possibility.

> 
> Fast resolution switching (less shutter lag)
> FCam is built on top of V4L2, which doesn't handle rapidly varying
> resolutions. When a Shot with a different resolution to the previous
> one comes down the pipeline, FCam currently flushes the entire V4L2
> pipeline, shuts down and restarts the whole camera subsystem, then
> starts streaming at the new resolution. This takes a long time (nearly
> a second), and is the cause of the horrible shutter lag on the N900. A
> brave kernel hacker may be able to reduce this time by fiddling with
> the FCam ISP kernel modules and the guts of the FCam library source
> (primarily Daemon.cpp).
> Anyone who solves this one will have our undying gratitude. An ideal
> solution would be able to insert a 5MP capture into a stream of
> 640x480 frames running at 30fps, without skipping more than the frame
> time of the 5MP capture. That is, the viewfinder would effectively
> stay live while taking a photograph.
> 
> )
> 
> Any other application I should look at? Thanks,

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus at iki.fi	XMPP: sailus at retiisi.org.uk


From hverkuil at xs4all.nl  Sun May  1 07:09:34 2016
From: hverkuil at xs4all.nl (Hans Verkuil)
Date: Sun, 1 May 2016 16:09:34 +0200
Subject: [RFT PATCH 0/3] usb: misc: usb3503: Fix missing device when TFTP
 booting
In-Reply-To: <20160501131746.GA16766@kozik-lap>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <57247E50.1020000@xs4all.nl> <20160501131746.GA16766@kozik-lap>
Message-ID: <57260E1E.70205@xs4all.nl>

On 05/01/2016 03:17 PM, Krzysztof Kozlowski wrote:
> On Sat, Apr 30, 2016 at 11:43:44AM +0200, Hans Verkuil wrote:
>> Hi Krzysztof,
>>
>> On 04/29/2016 12:59 PM, Krzysztof Kozlowski wrote:
>>> Hi,
>>>
>>> Patches are independent, please pick up as you wish.
>>>
>>> However all of them are needed to solve the issue, so I am sending
>>> everything together for easier testng.
>>>
>>>
>>> Problem
>>> =======
>>> When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
>>> the usb3503 does not show up in "lsusb". Hard-reset is required, e.g.
>>> by suspend to RAM. The actual TFTP boot does not have to happen. Just
>>> "usb start" from U-Boot is sufficient.
>>>
>>>
>>> Solution
>>> ========
>>> Perform real hardware reset (including regulator off/on) when probing.
>>>
>>>
>>> Tested on Odroid U3 so far. Please kindly test on X2 and other
>>> configurations and bootloaders.
>>
>> Against which kernel git repo is this patch?
>>
>> I did apply this patch series first:
>>
>> http://www.spinics.net/lists/arm-kernel/msg500764.html
> 
> Indeed it is based on above patchset... and on linux-next. It touches
> multiple trees so next seems the easiest base.
> 
>>
>> followed by this patch series.
>>
>> I've tested with both 4.6.0-rc2 and -rc5, but in all cases (even without
>> applying these patches!) the boot sequence hangs here:
>>
>> ...
>> [drm] Exynos DRM: using 12c10000.mixer device for DMA mapping operations
>> exynos-drm exynos-drm: bound 12c10000.mixer (ops mixer_component_ops)
>> exynos-drm exynos-drm: bound 12d00000.hdmi (ops hdmi_component_ops)
>> [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
>> [drm] No driver support for vblank timestamp query.
>> Console: switching to colour frame buffer device 240x67
>> exynos-drm exynos-drm: fb0:  frame buffer device
>> [drm] Initialized exynos 1.0.0 20110530 on minor 0
>> brd: module loaded
>> loop: module loaded
>> s3c64xx-spi 13930000.spi: spi bus clock parent not specified, using clock
>> at index 0 as parent
>> s3c64xx-spi 13930000.spi: number of chip select lines not specified,
>> assuming 1 chip select line
>> tun: Universal TUN/TAP device driver, 1.6
>> tun: (C) 1999-2004 Max Krasnyansky <maxk at qualcomm.com>
>> usbcore: registered new interface driver asix
>> usbcore: registered new interface driver ax88179_178a
>> usbcore: registered new interface driver cdc_ether
>> usbcore: registered new interface driver smsc95xx
>> usbcore: registered new interface driver cdc_ncm
>> dwc2 12480000.hsotg: Specified GNPTXFDEP=1024 > 768
>> dwc2 12480000.hsotg: EPs: 16, dedicated fifos, 7808 entries in SPRAM
>> ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
>> ehci-exynos: EHCI EXYNOS driver
>> exynos-ehci 12580000.ehci: EHCI Host Controller
>> exynos-ehci 12580000.ehci: new USB bus registered, assigned bus number 1
>> exynos-ehci 12580000.ehci: irq 51, io mem 0x12580000
>> exynos-ehci 12580000.ehci: USB 2.0 started, EHCI 1.00
>> usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
>> usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
>> usb usb1: Product: EHCI Host Controller
>> usb usb1: Manufacturer: Linux 4.6.0-rc5-odroid ehci_hcd
>> usb usb1: SerialNumber: 12580000.ehci
>> hub 1-0:1.0: USB hub found
>> hub 1-0:1.0: 3 ports detected
>> ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
>> ohci-exynos: OHCI EXYNOS driver
>> usbcore: registered new interface driver usb-storage
>> usb3503 0-0008: switched to HUB mode
>> usb3503 0-0008: usb3503_probe: probed in hub mode
>> using random self ethernet address
>> using random host ethernet address
>> usb0: HOST MAC 66:79:ef:11:72:85
>> usb0: MAC 1e:66:f2:66:8e:2a
>> using random self ethernet address
>> using random host ethernet address
>> g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
>> g_ether gadget: g_ether ready
>> dwc2 12480000.hsotg: bound driver g_ether
>> mousedev: PS/2 mouse device common for all mice
>> max77686-rtc max77686-rtc: rtc core: registered max77686-rtc as rtc0
>> i2c /dev entries driver
>> s5p-fimc-md camera: Entity type for entity FIMC.0 was not initialized!
>> usb 1-2: new high-speed USB device number 2 using exynos-ehci
>> usb 1-2: New USB device found, idVendor=0424, idProduct=9730
>> usb 1-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
>> smsc95xx v1.0.4
>> smsc95xx 1-2:1.0 eth0: register 'smsc95xx' at usb-12580000.ehci-2, smsc95xx
>> USB 2.0 Ethernet, c2:22:09:f2:5f:e8
>> usb 1-3: new high-speed USB device number 3 using exynos-ehci
>> usb 1-3: New USB device found, idVendor=0424, idProduct=3503
>> usb 1-3: New USB device strings: Mfr=0, Product=0, SerialNumber=0
>> hub 1-3:1.0: USB hub found
>> hub 1-3:1.0: 3 ports detected
>>
>> No oops, no nothing. It's just sitting there.
> 
> Apparently you have encountered different issue. sysrq with 'l' might be
> useful.
> 
>> Is this a regression that was introduced in 4.6? Or is there some special
>> new config that needs to be turned on first in 4.6?
> 
> I think it was like that for looong time... although I did not use
> netboot before on that target.

Sorry, I meant the hanging issue I got in 4.6, not the ethernet issue.
I get the same problem with linux-next. Can you mail me the .config you are using?

After some more testing I don't think it is hanging, instead it seems that the mmc
isn't enabled/found and so it just sits waiting for the root partition to appear.

Weird.

Regards,

	Hans


From sre at kernel.org  Sun May  1 08:48:56 2016
From: sre at kernel.org (Sebastian Reichel)
Date: Sun, 1 May 2016 17:48:56 +0200
Subject: Nokia N900 retention mode in v4.6, camera buttons fun
In-Reply-To: <20160501085236.GA14243@amd>
References: <20160411093023.GC11814@amd> <20160411094130.GA5753@amd>
 <20160411211026.GH5995@atomide.com> <20160412121658.GA32486@amd>
 <20160412123013.GA12296@amd> <20160412163055.GP5995@atomide.com>
 <20160417175539.GA502@amd> <20160421130450.GQ29406@pali>
 <20160429200559.GA16598@earth> <20160501085236.GA14243@amd>
Message-ID: <20160501154855.GA24970@earth>

Hi,

On Sun, May 01, 2016 at 10:52:36AM +0200, Pavel Machek wrote:
> On Fri 2016-04-29 22:06:00, Sebastian Reichel wrote:
> > On Thu, Apr 21, 2016 at 03:04:50PM +0200, Pali Roh?r wrote:
> > > > CONFIG_HSI breaks power management completely, so power management
> > > > with modem will be another topic.  
> > > 
> > > Sebastian, any idea why power management does not work for HSI?
> > 
> > I wasn't aware, that pm_runtime_irq_safe() basically breaks runtime
> > PM until Tony's fix for musb (even though it's logical when thinking
> > about it). Currently omap-ssi and omap-ssi-port make use of
> > pm_runtime_irq_safe().
> > 
> > Since pm_runtime_get_sync/pm_runtime_put_sync is called from
> > tasklets in omap-ssi (and omap-ssi-port) it cannot be simply
> > removed. So fixing PM for the ssi controller requires reworking
> > the driver in a non trivial way.
> 
> I see latest series, and it also talks about frequency scaling. But I
> guess it is not going to fix this issue?

No, this is independent of the runtime PM problems. I also worked
on runtime PM/idling yesterday and pm_runtime_irq_safe is the main
culprit for breaking it (not the only one, though). It's not yet
finished though

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160501/4466ff82/attachment-0001.sig>

From hverkuil at xs4all.nl  Sun May  1 09:01:08 2016
From: hverkuil at xs4all.nl (Hans Verkuil)
Date: Sun, 1 May 2016 18:01:08 +0200
Subject: [RFT PATCH 0/3] usb: misc: usb3503: Fix missing device when TFTP
 booting
In-Reply-To: <57260E1E.70205@xs4all.nl>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <57247E50.1020000@xs4all.nl> <20160501131746.GA16766@kozik-lap>
 <57260E1E.70205@xs4all.nl>
Message-ID: <57262844.7060809@xs4all.nl>

On 05/01/2016 04:09 PM, Hans Verkuil wrote:
> On 05/01/2016 03:17 PM, Krzysztof Kozlowski wrote:
>> On Sat, Apr 30, 2016 at 11:43:44AM +0200, Hans Verkuil wrote:
>>> Hi Krzysztof,
>>>
>>> On 04/29/2016 12:59 PM, Krzysztof Kozlowski wrote:
>>>> Hi,
>>>>
>>>> Patches are independent, please pick up as you wish.
>>>>
>>>> However all of them are needed to solve the issue, so I am sending
>>>> everything together for easier testng.
>>>>
>>>>
>>>> Problem
>>>> =======
>>>> When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
>>>> the usb3503 does not show up in "lsusb". Hard-reset is required, e.g.
>>>> by suspend to RAM. The actual TFTP boot does not have to happen. Just
>>>> "usb start" from U-Boot is sufficient.
>>>>
>>>>
>>>> Solution
>>>> ========
>>>> Perform real hardware reset (including regulator off/on) when probing.
>>>>
>>>>
>>>> Tested on Odroid U3 so far. Please kindly test on X2 and other
>>>> configurations and bootloaders.
>>>
>>> Against which kernel git repo is this patch?
>>>
>>> I did apply this patch series first:
>>>
>>> http://www.spinics.net/lists/arm-kernel/msg500764.html
>>
>> Indeed it is based on above patchset... and on linux-next. It touches
>> multiple trees so next seems the easiest base.
>>
>>>
>>> followed by this patch series.
>>>
>>> I've tested with both 4.6.0-rc2 and -rc5, but in all cases (even without
>>> applying these patches!) the boot sequence hangs here:
>>>
>>> ...
>>> [drm] Exynos DRM: using 12c10000.mixer device for DMA mapping operations
>>> exynos-drm exynos-drm: bound 12c10000.mixer (ops mixer_component_ops)
>>> exynos-drm exynos-drm: bound 12d00000.hdmi (ops hdmi_component_ops)
>>> [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
>>> [drm] No driver support for vblank timestamp query.
>>> Console: switching to colour frame buffer device 240x67
>>> exynos-drm exynos-drm: fb0:  frame buffer device
>>> [drm] Initialized exynos 1.0.0 20110530 on minor 0
>>> brd: module loaded
>>> loop: module loaded
>>> s3c64xx-spi 13930000.spi: spi bus clock parent not specified, using clock
>>> at index 0 as parent
>>> s3c64xx-spi 13930000.spi: number of chip select lines not specified,
>>> assuming 1 chip select line
>>> tun: Universal TUN/TAP device driver, 1.6
>>> tun: (C) 1999-2004 Max Krasnyansky <maxk at qualcomm.com>
>>> usbcore: registered new interface driver asix
>>> usbcore: registered new interface driver ax88179_178a
>>> usbcore: registered new interface driver cdc_ether
>>> usbcore: registered new interface driver smsc95xx
>>> usbcore: registered new interface driver cdc_ncm
>>> dwc2 12480000.hsotg: Specified GNPTXFDEP=1024 > 768
>>> dwc2 12480000.hsotg: EPs: 16, dedicated fifos, 7808 entries in SPRAM
>>> ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
>>> ehci-exynos: EHCI EXYNOS driver
>>> exynos-ehci 12580000.ehci: EHCI Host Controller
>>> exynos-ehci 12580000.ehci: new USB bus registered, assigned bus number 1
>>> exynos-ehci 12580000.ehci: irq 51, io mem 0x12580000
>>> exynos-ehci 12580000.ehci: USB 2.0 started, EHCI 1.00
>>> usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
>>> usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
>>> usb usb1: Product: EHCI Host Controller
>>> usb usb1: Manufacturer: Linux 4.6.0-rc5-odroid ehci_hcd
>>> usb usb1: SerialNumber: 12580000.ehci
>>> hub 1-0:1.0: USB hub found
>>> hub 1-0:1.0: 3 ports detected
>>> ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
>>> ohci-exynos: OHCI EXYNOS driver
>>> usbcore: registered new interface driver usb-storage
>>> usb3503 0-0008: switched to HUB mode
>>> usb3503 0-0008: usb3503_probe: probed in hub mode
>>> using random self ethernet address
>>> using random host ethernet address
>>> usb0: HOST MAC 66:79:ef:11:72:85
>>> usb0: MAC 1e:66:f2:66:8e:2a
>>> using random self ethernet address
>>> using random host ethernet address
>>> g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
>>> g_ether gadget: g_ether ready
>>> dwc2 12480000.hsotg: bound driver g_ether
>>> mousedev: PS/2 mouse device common for all mice
>>> max77686-rtc max77686-rtc: rtc core: registered max77686-rtc as rtc0
>>> i2c /dev entries driver
>>> s5p-fimc-md camera: Entity type for entity FIMC.0 was not initialized!
>>> usb 1-2: new high-speed USB device number 2 using exynos-ehci
>>> usb 1-2: New USB device found, idVendor=0424, idProduct=9730
>>> usb 1-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
>>> smsc95xx v1.0.4
>>> smsc95xx 1-2:1.0 eth0: register 'smsc95xx' at usb-12580000.ehci-2, smsc95xx
>>> USB 2.0 Ethernet, c2:22:09:f2:5f:e8
>>> usb 1-3: new high-speed USB device number 3 using exynos-ehci
>>> usb 1-3: New USB device found, idVendor=0424, idProduct=3503
>>> usb 1-3: New USB device strings: Mfr=0, Product=0, SerialNumber=0
>>> hub 1-3:1.0: USB hub found
>>> hub 1-3:1.0: 3 ports detected
>>>
>>> No oops, no nothing. It's just sitting there.
>>
>> Apparently you have encountered different issue. sysrq with 'l' might be
>> useful.
>>
>>> Is this a regression that was introduced in 4.6? Or is there some special
>>> new config that needs to be turned on first in 4.6?
>>
>> I think it was like that for looong time... although I did not use
>> netboot before on that target.
> 
> Sorry, I meant the hanging issue I got in 4.6, not the ethernet issue.
> I get the same problem with linux-next. Can you mail me the .config you are using?

Never mind.

> After some more testing I don't think it is hanging, instead it seems that the mmc
> isn't enabled/found and so it just sits waiting for the root partition to appear.

That was fun. There are two problems that both caused the boot to end at the same
place: first of all the root partition is now called mmcblk1p1 instead of mmcblk0p1
in 4.6, so it was just waiting for the root partition to appear. Nothing to do with
your patch series, just unexpected.

The second is that enabling CONFIG_VIDEO_S5P_FIMC causes the boot to hang at that
same place. I suspect there is a deadlock somewhere. I'm digging deeper into that
but again, unrelated to your patch series.

Anyway, after disabling that config option I was finally able to test your patch
series:

Tested-by: Hans Verkuil <hans.verkuil at cisco.com>

Thanks!

	Hans


From k.kozlowski at samsung.com  Sun May  1 09:42:52 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Sun, 1 May 2016 18:42:52 +0200
Subject: [RFT PATCH 0/3] usb: misc: usb3503: Fix missing device when TFTP
 booting
In-Reply-To: <57262844.7060809@xs4all.nl>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <57247E50.1020000@xs4all.nl> <20160501131746.GA16766@kozik-lap>
 <57260E1E.70205@xs4all.nl> <57262844.7060809@xs4all.nl>
Message-ID: <20160501164252.GA3581@kozik-lap>

On Sun, May 01, 2016 at 06:01:08PM +0200, Hans Verkuil wrote:
> > Sorry, I meant the hanging issue I got in 4.6, not the ethernet issue.
> > I get the same problem with linux-next. Can you mail me the .config you are using?
> 
> Never mind.
> 
> > After some more testing I don't think it is hanging, instead it seems that the mmc
> > isn't enabled/found and so it just sits waiting for the root partition to appear.
> 
> That was fun. There are two problems that both caused the boot to end at the same
> place: first of all the root partition is now called mmcblk1p1 instead of mmcblk0p1
> in 4.6, so it was just waiting for the root partition to appear. Nothing to do with
> your patch series, just unexpected.

Yes, annoying issue and unfortunately this is known... recommended
solution is to use root=PARTUUID=xxxx (you can get the PARTUUID with
blkid)... or replace the mmc device.

> The second is that enabling CONFIG_VIDEO_S5P_FIMC causes the boot to hang at that
> same place. I suspect there is a deadlock somewhere. I'm digging deeper into that
> but again, unrelated to your patch series.
> 
> Anyway, after disabling that config option I was finally able to test your patch
> series:
> 
> Tested-by: Hans Verkuil <hans.verkuil at cisco.com>

Thanks!

Best regards,
Krzysztof


From swarren at wwwdotorg.org  Sun May  1 09:58:43 2016
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Sun, 1 May 2016 10:58:43 -0600
Subject: [PATCH v4] ARM: bcm2835: dt: Add the ethernet to the device trees
In-Reply-To: <1462000432-18452-1-git-send-email-lkundrak@v3.sk>
References: <1462000432-18452-1-git-send-email-lkundrak@v3.sk>
Message-ID: <572635C3.7070102@wwwdotorg.org>

On 04/30/2016 01:13 AM, Lubomir Rintel wrote:
> The hub and the ethernet in its port 1 are hardwired on the board.
>
> Compared to the adapters that can be plugged into the USB ports, this
> one has no serial EEPROM to store its MAC. Nevertheless, the Raspberry Pi
> has the MAC address for this adapter in its ROM, accessible from its
> firmware.
>
> U-Boot can read out the address and set the local-mac-address property of the
> node with "ethernet" alias. Let's add the node so that U-Boot can do its
> business.
>
> Model B rev2 and Model B+ entries were verified by me, the hierarchy and
> pid/vid pair for the Version 2 was provided by Peter Chen. Original
> Model B is a blind short, though very likely correct.

Acked-by: Stephen Warren <swarren at wwwdotorg.org>

One nit:

> diff --git a/arch/arm/boot/dts/bcm283x-rpi-smsc9512.dtsi b/arch/arm/boot/dts/bcm283x-rpi-smsc9512.dtsi
> new file mode 100644
> index 0000000..7200238
> --- /dev/null
> +++ b/arch/arm/boot/dts/bcm283x-rpi-smsc9512.dtsi
> @@ -0,0 +1,20 @@
> +
> +/ {

There's an extra blank line at the top of the file.


From okaya at codeaurora.org  Sun May  1 10:55:43 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sun, 1 May 2016 13:55:43 -0400
Subject: [PATCH V3 1/3] vfio, platform: add support for ACPI while
 detecting the reset driver
In-Reply-To: <4981390.J9tsJr16lM@wuerfel>
References: <1459172124-6730-1-git-send-email-okaya@codeaurora.org>
 <147496989.L43SVC7xRY@wuerfel>
 <8f766d081b33d91f196e7bd5e13b6f33@codeaurora.org>
 <4981390.J9tsJr16lM@wuerfel>
Message-ID: <5726431F.7070106@codeaurora.org>

On 3/29/2016 8:44 AM, Arnd Bergmann wrote:
>>  can certainly drop patch #3 and push the reset responsibility to acpi.
>> > 
>> > I never liked having a fragmented sw design across multiple drivers.
>> > 
>> > I need something for patch #1. Compatible is a DT property not ACPI.but 
>> > then, I won't have a reset driver anymore.
>> > 
>> > If we think about how vfio pci works, we pass the pci vendor and device 
>> > id to new_id file to find out which pci device needs to be pass thru.
>> > 
>> > I can go to a similar route. This time we pass the object id through 
>> > new_id and I call reset method on this object.
>> > 
>> > Let me know what you think?
> It would certainly be nice to make it work more like PCI VFIO does
> here, where you can assign any device as long as it has an IOMMU
> (and a _rst method in this case).
> 
> 	Arnd

I looked at the code today. This doesn't have to be as convoluted as PCI is. 
The VFIO platform driver already has a pointer to the actual object in
vdev->pdev.dev.

This is really as simple as calling _RST method on the passed oject at the last
step below. We don't need to create a dynamic list like PCI does. 

This is how the driver gets called. 

echo vfio-platform | tee -a /sys/bus/platform/devices/QCOM8061:00/driver_override
echo QCOM8061:00 | tee -a  /sys/bus/platform/devices/QCOM8061:00/driver/unbind
echo QCOM8061:00 |tee -a /sys/bus/platform/drivers_probe

I'll post a patch as soon as I test it.

-- 
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


From sricharan at codeaurora.org  Sun May  1 11:54:28 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon,  2 May 2016 00:24:28 +0530
Subject: [PATCH V3 0/7] iommu/msm: Add DT adaptation and generic bindings
 support
Message-ID: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>

The msm_iommu.c driver currently works based on platform data.
A single master device can be connected to more than one iommu and multiple
contexts in each of the iommu. This association between master and iommus was
represented from platform data using parent/child devices. The master drivers
were responsible for attaching all of the iommus/context to a domain. Now the
platform data support is removed and DT support is added. The master/iommus are
added through generic iommu bindings.

This is essentially rework of the patch posted earlier by
Rob Clark <robdclark at gmail.com>. This series folds the changes in to the
existing driver with the addition of generic bindings.

        http://www.spinics.net/lists/linux-arm-msm/msg10077.html

Tested this series on ifc6410 board.

[V3] Addressed comments to correct the usage
     of the #iommu-cells binding, improve the flush_iotlb_range function,
     added a new patch to use writel_relaxed for register access and split
     up the documentation patch.

[V2] Adapted the driver to use generic ARMV7S short descriptor pagetable ops
     and addressed comments.

[V1]
   https://lists.linuxfoundation.org/pipermail/iommu/2015-August/014074.html

Sricharan R (7):
  iommu/msm: Add DT adaptation
  documentation: iommu: Add bindings for msm,iommu-v0 ip
  iommu/msm: Move the contents from msm_iommu_dev.c to msm_iommu.c
  iommu/msm: Add support for generic master bindings
  iommu/msm: use generic ARMV7S short descriptor pagetable ops
  iommu/msm: Use writel_relaxed and add a barrier
  iommu/msm: Remove driver BROKEN

 .../devicetree/bindings/iommu/msm,iommu-v0.txt     |  62 ++
 drivers/iommu/Kconfig                              |   2 +-
 drivers/iommu/Makefile                             |   2 +-
 drivers/iommu/msm_iommu.c                          | 872 +++++++++++----------
 drivers/iommu/msm_iommu.h                          |  73 +-
 drivers/iommu/msm_iommu_dev.c                      | 381 ---------
 drivers/iommu/msm_iommu_hw-8xxx.h                  |   7 +-
 7 files changed, 567 insertions(+), 832 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
 delete mode 100644 drivers/iommu/msm_iommu_dev.c

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May  1 11:54:29 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon,  2 May 2016 00:24:29 +0530
Subject: [PATCH V3 1/7] iommu/msm: Add DT adaptation
In-Reply-To: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
References: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1462128875-20988-2-git-send-email-sricharan@codeaurora.org>

The driver currently works based on platform data. Remove this
and add support for DT. A single master can have multiple ports
connected to more than one iommu.

                      master
                        |
                        |
                        |
           ------------------------
           |                      |
         IOMMU0                 IOMMU1
           |                      |
      ctx0   ctx1            ctx0   ctx1

This association of master and iommus/contexts were previously
represented by platform data parent/child device details. The client
drivers were responsible for programming all of the iommus/contexts
for the device. Now while adapting to generic DT bindings we maintain the
list of iommus, contexts that each master domain is connected to and
program all of them on attach/detach.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/msm_iommu.c     | 252 ++++++++++++++++++---------------
 drivers/iommu/msm_iommu.h     |  73 ++++------
 drivers/iommu/msm_iommu_dev.c | 315 ++++++++++--------------------------------
 3 files changed, 237 insertions(+), 403 deletions(-)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index e321fa5..bc1a4e3 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -48,6 +48,7 @@ __asm__ __volatile__ (							\
 static int msm_iommu_tex_class[4];
 
 DEFINE_SPINLOCK(msm_iommu_lock);
+static LIST_HEAD(qcom_iommu_devices);
 
 struct msm_priv {
 	unsigned long *pgtable;
@@ -60,35 +61,37 @@ static struct msm_priv *to_msm_priv(struct iommu_domain *dom)
 	return container_of(dom, struct msm_priv, domain);
 }
 
-static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
+static int __enable_clocks(struct msm_iommu_dev *iommu)
 {
 	int ret;
 
-	ret = clk_enable(drvdata->pclk);
+	ret = clk_enable(iommu->pclk);
 	if (ret)
 		goto fail;
 
-	if (drvdata->clk) {
-		ret = clk_enable(drvdata->clk);
+	if (iommu->clk) {
+		ret = clk_enable(iommu->clk);
 		if (ret)
-			clk_disable(drvdata->pclk);
+			clk_disable(iommu->pclk);
 	}
 fail:
 	return ret;
 }
 
-static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
+static void __disable_clocks(struct msm_iommu_dev *iommu)
 {
-	clk_disable(drvdata->clk);
-	clk_disable(drvdata->pclk);
+	if (iommu->clk)
+		clk_disable(iommu->clk);
+	clk_disable(iommu->pclk);
 }
 
 static int __flush_iotlb(struct iommu_domain *domain)
 {
 	struct msm_priv *priv = to_msm_priv(domain);
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	struct msm_iommu_dev *iommu = NULL;
+	struct msm_iommu_ctx_dev *master;
 	int ret = 0;
+
 #ifndef CONFIG_IOMMU_PGTABLES_L2
 	unsigned long *fl_table = priv->pgtable;
 	int i;
@@ -105,24 +108,67 @@ static int __flush_iotlb(struct iommu_domain *domain)
 	}
 #endif
 
-	list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
-
-		BUG_ON(!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent);
-
-		iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
-		BUG_ON(!iommu_drvdata);
-
-		ret = __enable_clocks(iommu_drvdata);
+	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
+		ret = __enable_clocks(iommu);
 		if (ret)
 			goto fail;
 
-		SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
-		__disable_clocks(iommu_drvdata);
+		list_for_each_entry(master, &iommu->ctx_list, list)
+			SET_CTX_TLBIALL(iommu->base, master->num, 0);
+
+		__disable_clocks(iommu);
 	}
 fail:
 	return ret;
 }
 
+static int msm_iommu_alloc_ctx(unsigned long *map, int start, int end)
+{
+	int idx;
+
+	do {
+		idx = find_next_zero_bit(map, end, start);
+		if (idx == end)
+			return -ENOSPC;
+	} while (test_and_set_bit(idx, map));
+
+	return idx;
+}
+
+static void msm_iommu_free_ctx(unsigned long *map, int idx)
+{
+	clear_bit(idx, map);
+}
+
+static void config_mids(struct msm_iommu_dev *iommu,
+			struct msm_iommu_ctx_dev *master)
+{
+	int mid, ctx, i;
+
+	for (i = 0; i < master->num_mids; i++) {
+		mid = master->mids[i];
+		ctx = master->num;
+
+		SET_M2VCBR_N(iommu->base, mid, 0);
+		SET_CBACR_N(iommu->base, ctx, 0);
+
+		/* Set VMID = 0 */
+		SET_VMID(iommu->base, mid, 0);
+
+		/* Set the context number for that MID to this context */
+		SET_CBNDX(iommu->base, mid, ctx);
+
+		/* Set MID associated with this context bank to 0*/
+		SET_CBVMID(iommu->base, ctx, 0);
+
+		/* Set the ASID for TLB tagging for this context */
+		SET_CONTEXTIDR_ASID(iommu->base, ctx, ctx);
+
+		/* Set security bit override to be Non-secure */
+		SET_NSCFG(iommu->base, mid, 3);
+	}
+}
+
 static void __reset_context(void __iomem *base, int ctx)
 {
 	SET_BPRCOSH(base, ctx, 0);
@@ -272,94 +318,76 @@ static void msm_iommu_domain_free(struct iommu_domain *domain)
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
-	struct msm_priv *priv;
-	struct msm_iommu_ctx_dev *ctx_dev;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-	struct msm_iommu_ctx_drvdata *tmp_drvdata;
 	int ret = 0;
 	unsigned long flags;
+	struct msm_iommu_dev *iommu;
+	struct msm_priv *priv = to_msm_priv(domain);
+	struct msm_iommu_ctx_dev *master;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	priv = to_msm_priv(domain);
-
-	if (!dev) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	iommu_drvdata = dev_get_drvdata(dev->parent);
-	ctx_drvdata = dev_get_drvdata(dev);
-	ctx_dev = dev->platform_data;
-
-	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (!list_empty(&ctx_drvdata->attached_elm)) {
-		ret = -EBUSY;
-		goto fail;
-	}
-
-	list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
-		if (tmp_drvdata == ctx_drvdata) {
-			ret = -EBUSY;
-			goto fail;
+	list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) {
+		master = list_first_entry(&iommu->ctx_list,
+					  struct msm_iommu_ctx_dev,
+					  list);
+		if (master->of_node == dev->of_node) {
+			ret = __enable_clocks(iommu);
+			if (ret)
+				goto fail;
+
+			list_for_each_entry(master, &iommu->ctx_list, list) {
+				if (master->num) {
+					dev_err(dev, "domain already attached");
+					ret = -EEXIST;
+					goto fail;
+				}
+				master->num =
+					msm_iommu_alloc_ctx(iommu->context_map,
+							    0, iommu->ncb);
+					if (IS_ERR_VALUE(master->num)) {
+						ret = -ENODEV;
+						goto fail;
+					}
+				config_mids(iommu, master);
+				__program_context(iommu->base, master->num,
+						  __pa(priv->pgtable));
+			}
+			__disable_clocks(iommu);
+			list_add(&iommu->dom_node, &priv->list_attached);
 		}
+	}
 
-	ret = __enable_clocks(iommu_drvdata);
-	if (ret)
-		goto fail;
-
-	__program_context(iommu_drvdata->base, ctx_dev->num,
-			  __pa(priv->pgtable));
-
-	__disable_clocks(iommu_drvdata);
-	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
 	ret = __flush_iotlb(domain);
-
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+
 	return ret;
 }
 
 static void msm_iommu_detach_dev(struct iommu_domain *domain,
 				 struct device *dev)
 {
-	struct msm_priv *priv;
-	struct msm_iommu_ctx_dev *ctx_dev;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	struct msm_priv *priv = to_msm_priv(domain);
 	unsigned long flags;
+	struct msm_iommu_dev *iommu;
+	struct msm_iommu_ctx_dev *master;
 	int ret;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
-	priv = to_msm_priv(domain);
-
-	if (!dev)
-		goto fail;
-
-	iommu_drvdata = dev_get_drvdata(dev->parent);
-	ctx_drvdata = dev_get_drvdata(dev);
-	ctx_dev = dev->platform_data;
-
-	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
-		goto fail;
-
 	ret = __flush_iotlb(domain);
 	if (ret)
 		goto fail;
 
-	ret = __enable_clocks(iommu_drvdata);
-	if (ret)
-		goto fail;
-
-	__reset_context(iommu_drvdata->base, ctx_dev->num);
-	__disable_clocks(iommu_drvdata);
-	list_del_init(&ctx_drvdata->attached_elm);
+	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
+		ret = __enable_clocks(iommu);
+		if (ret)
+			goto fail;
 
+		list_for_each_entry(master, &iommu->ctx_list, list) {
+			msm_iommu_free_ctx(iommu->context_map, master->num);
+			__reset_context(iommu->base, master->num);
+		}
+		__disable_clocks(iommu);
+	}
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 }
@@ -555,47 +583,46 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
 					  dma_addr_t va)
 {
 	struct msm_priv *priv;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	struct msm_iommu_dev *iommu;
+	struct msm_iommu_ctx_dev *master;
 	unsigned int par;
 	unsigned long flags;
-	void __iomem *base;
 	phys_addr_t ret = 0;
-	int ctx;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
 
 	priv = to_msm_priv(domain);
-	if (list_empty(&priv->list_attached))
-		goto fail;
+	iommu = list_first_entry(&priv->list_attached,
+				 struct msm_iommu_dev, dom_node);
 
-	ctx_drvdata = list_entry(priv->list_attached.next,
-				 struct msm_iommu_ctx_drvdata, attached_elm);
-	iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+	if (list_empty(&iommu->ctx_list))
+		goto fail;
 
-	base = iommu_drvdata->base;
-	ctx = ctx_drvdata->num;
+	master = list_first_entry(&iommu->ctx_list,
+				  struct msm_iommu_ctx_dev, list);
+	if (!master)
+		goto fail;
 
-	ret = __enable_clocks(iommu_drvdata);
+	ret = __enable_clocks(iommu);
 	if (ret)
 		goto fail;
 
 	/* Invalidate context TLB */
-	SET_CTX_TLBIALL(base, ctx, 0);
-	SET_V2PPR(base, ctx, va & V2Pxx_VA);
+	SET_CTX_TLBIALL(iommu->base, master->num, 0);
+	SET_V2PPR(iommu->base, master->num, va & V2Pxx_VA);
 
-	par = GET_PAR(base, ctx);
+	par = GET_PAR(iommu->base, master->num);
 
 	/* We are dealing with a supersection */
-	if (GET_NOFAULT_SS(base, ctx))
+	if (GET_NOFAULT_SS(iommu->base, master->num))
 		ret = (par & 0xFF000000) | (va & 0x00FFFFFF);
 	else	/* Upper 20 bits from PAR, lower 12 from VA */
 		ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
 
-	if (GET_FAULT(base, ctx))
+	if (GET_FAULT(iommu->base, master->num))
 		ret = 0;
 
-	__disable_clocks(iommu_drvdata);
+	__disable_clocks(iommu);
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
@@ -635,37 +662,34 @@ static void print_ctx_regs(void __iomem *base, int ctx)
 
 irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 {
-	struct msm_iommu_drvdata *drvdata = dev_id;
-	void __iomem *base;
+	struct msm_iommu_dev *iommu = dev_id;
 	unsigned int fsr;
 	int i, ret;
 
 	spin_lock(&msm_iommu_lock);
 
-	if (!drvdata) {
+	if (!iommu) {
 		pr_err("Invalid device ID in context interrupt handler\n");
 		goto fail;
 	}
 
-	base = drvdata->base;
-
 	pr_err("Unexpected IOMMU page fault!\n");
-	pr_err("base = %08x\n", (unsigned int) base);
+	pr_err("base = %08x\n", (unsigned int)iommu->base);
 
-	ret = __enable_clocks(drvdata);
+	ret = __enable_clocks(iommu);
 	if (ret)
 		goto fail;
 
-	for (i = 0; i < drvdata->ncb; i++) {
-		fsr = GET_FSR(base, i);
+	for (i = 0; i < iommu->ncb; i++) {
+		fsr = GET_FSR(iommu->base, i);
 		if (fsr) {
 			pr_err("Fault occurred in context %d.\n", i);
 			pr_err("Interesting registers:\n");
-			print_ctx_regs(base, i);
-			SET_FSR(base, i, 0x4000000F);
+			print_ctx_regs(iommu->base, i);
+			SET_FSR(iommu->base, i, 0x4000000F);
 		}
 	}
-	__disable_clocks(drvdata);
+	__disable_clocks(iommu);
 fail:
 	spin_unlock(&msm_iommu_lock);
 	return 0;
diff --git a/drivers/iommu/msm_iommu.h b/drivers/iommu/msm_iommu.h
index 5c7c955..4ca25d5 100644
--- a/drivers/iommu/msm_iommu.h
+++ b/drivers/iommu/msm_iommu.h
@@ -42,74 +42,53 @@
  */
 #define MAX_NUM_MIDS	32
 
+/* Maximum number of context banks that can be present in IOMMU */
+#define IOMMU_MAX_CBS	128
+
 /**
  * struct msm_iommu_dev - a single IOMMU hardware instance
- * name		Human-readable name given to this IOMMU HW instance
  * ncb		Number of context banks present on this IOMMU HW instance
+ * dev:		IOMMU device
+ * irq:		Interrupt number
+ * clk:		The bus clock for this IOMMU hardware instance
+ * pclk:	The clock for the IOMMU bus interconnect
+ * dev_node:	list head in qcom_iommu_device_list
+ * dom_node:	list head for domain
+ * ctx_list:	list of 'struct msm_iommu_ctx_dev'
+ * context_map: Bitmap to track allocated context banks
  */
 struct msm_iommu_dev {
-	const char *name;
+	void __iomem *base;
 	int ncb;
+	struct device *dev;
+	int irq;
+	struct clk *clk;
+	struct clk *pclk;
+	struct list_head dev_node;
+	struct list_head dom_node;
+	struct list_head ctx_list;
+	DECLARE_BITMAP(context_map, IOMMU_MAX_CBS);
 };
 
 /**
  * struct msm_iommu_ctx_dev - an IOMMU context bank instance
- * name		Human-readable name given to this context bank
+ * of_node	node ptr of client device
  * num		Index of this context bank within the hardware
  * mids		List of Machine IDs that are to be mapped into this context
  *		bank, terminated by -1. The MID is a set of signals on the
  *		AXI bus that identifies the function associated with a specific
  *		memory request. (See ARM spec).
+ * num_mids	Total number of mids
+ * node		list head in ctx_list
  */
 struct msm_iommu_ctx_dev {
-	const char *name;
+	struct device_node *of_node;
 	int num;
 	int mids[MAX_NUM_MIDS];
+	int num_mids;
+	struct list_head list;
 };
 
-
-/**
- * struct msm_iommu_drvdata - A single IOMMU hardware instance
- * @base:	IOMMU config port base address (VA)
- * @ncb		The number of contexts on this IOMMU
- * @irq:	Interrupt number
- * @clk:	The bus clock for this IOMMU hardware instance
- * @pclk:	The clock for the IOMMU bus interconnect
- *
- * A msm_iommu_drvdata holds the global driver data about a single piece
- * of an IOMMU hardware instance.
- */
-struct msm_iommu_drvdata {
-	void __iomem *base;
-	int irq;
-	int ncb;
-	struct clk *clk;
-	struct clk *pclk;
-};
-
-/**
- * struct msm_iommu_ctx_drvdata - an IOMMU context bank instance
- * @num:		Hardware context number of this context
- * @pdev:		Platform device associated wit this HW instance
- * @attached_elm:	List element for domains to track which devices are
- *			attached to them
- *
- * A msm_iommu_ctx_drvdata holds the driver data for a single context bank
- * within each IOMMU hardware instance
- */
-struct msm_iommu_ctx_drvdata {
-	int num;
-	struct platform_device *pdev;
-	struct list_head attached_elm;
-};
-
-/*
- * Look up an IOMMU context device by its context name. NULL if none found.
- * Useful for testing and drivers that do not yet fully have IOMMU stuff in
- * their platform devices.
- */
-struct device *msm_iommu_get_ctx(const char *ctx_name);
-
 /*
  * Interrupt handler for the IOMMU context fault interrupt. Hooking the
  * interrupt is not supported in the API yet, but this will print an error
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
index 4b09e81..c2cf5e7b 100644
--- a/drivers/iommu/msm_iommu_dev.c
+++ b/drivers/iommu/msm_iommu_dev.c
@@ -30,60 +30,6 @@
 #include "msm_iommu_hw-8xxx.h"
 #include "msm_iommu.h"
 
-struct iommu_ctx_iter_data {
-	/* input */
-	const char *name;
-
-	/* output */
-	struct device *dev;
-};
-
-static struct platform_device *msm_iommu_root_dev;
-
-static int each_iommu_ctx(struct device *dev, void *data)
-{
-	struct iommu_ctx_iter_data *res = data;
-	struct msm_iommu_ctx_dev *c = dev->platform_data;
-
-	if (!res || !c || !c->name || !res->name)
-		return -EINVAL;
-
-	if (!strcmp(res->name, c->name)) {
-		res->dev = dev;
-		return 1;
-	}
-	return 0;
-}
-
-static int each_iommu(struct device *dev, void *data)
-{
-	return device_for_each_child(dev, data, each_iommu_ctx);
-}
-
-struct device *msm_iommu_get_ctx(const char *ctx_name)
-{
-	struct iommu_ctx_iter_data r;
-	int found;
-
-	if (!msm_iommu_root_dev) {
-		pr_err("No root IOMMU device.\n");
-		goto fail;
-	}
-
-	r.name = ctx_name;
-	found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
-
-	if (!found) {
-		pr_err("Could not find context <%s>\n", ctx_name);
-		goto fail;
-	}
-
-	return r.dev;
-fail:
-	return NULL;
-}
-EXPORT_SYMBOL(msm_iommu_get_ctx);
-
 static void msm_iommu_reset(void __iomem *base, int ncb)
 {
 	int ctx;
@@ -128,237 +74,122 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
 static int msm_iommu_probe(struct platform_device *pdev)
 {
 	struct resource *r;
-	struct clk *iommu_clk;
-	struct clk *iommu_pclk;
-	struct msm_iommu_drvdata *drvdata;
-	struct msm_iommu_dev *iommu_dev = dev_get_platdata(&pdev->dev);
-	void __iomem *regs_base;
-	int ret, irq, par;
+	struct msm_iommu_dev *iommu;
+	int ret, par, val;
 
-	if (pdev->id == -1) {
-		msm_iommu_root_dev = pdev;
-		return 0;
-	}
+	iommu = devm_kzalloc(&pdev->dev, sizeof(*iommu), GFP_KERNEL);
+	if (!iommu)
+		return -ENODEV;
 
-	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+	iommu->dev = &pdev->dev;
+	INIT_LIST_HEAD(&iommu->ctx_list);
 
-	if (!drvdata) {
-		ret = -ENOMEM;
-		goto fail;
+	iommu->pclk = devm_clk_get(iommu->dev, "smmu_pclk");
+	if (IS_ERR(iommu->pclk)) {
+		dev_err(iommu->dev, "could not get smmu_pclk\n");
+		return PTR_ERR(iommu->pclk);
 	}
 
-	if (!iommu_dev) {
-		ret = -ENODEV;
-		goto fail;
+	ret = clk_prepare(iommu->pclk);
+	if (ret) {
+		dev_err(iommu->dev, "could not prepare smmu_pclk\n");
+		return ret;
 	}
 
-	iommu_pclk = clk_get(NULL, "smmu_pclk");
-	if (IS_ERR(iommu_pclk)) {
-		ret = -ENODEV;
-		goto fail;
+	iommu->clk = devm_clk_get(iommu->dev, "iommu_clk");
+	if (IS_ERR(iommu->clk)) {
+		dev_err(iommu->dev, "could not get iommu_clk\n");
+		clk_unprepare(iommu->pclk);
+		return PTR_ERR(iommu->clk);
 	}
 
-	ret = clk_prepare_enable(iommu_pclk);
-	if (ret)
-		goto fail_enable;
-
-	iommu_clk = clk_get(&pdev->dev, "iommu_clk");
-
-	if (!IS_ERR(iommu_clk))	{
-		if (clk_get_rate(iommu_clk) == 0)
-			clk_set_rate(iommu_clk, 1);
-
-		ret = clk_prepare_enable(iommu_clk);
-		if (ret) {
-			clk_put(iommu_clk);
-			goto fail_pclk;
-		}
-	} else
-		iommu_clk = NULL;
+	ret = clk_prepare(iommu->clk);
+	if (ret) {
+		dev_err(iommu->dev, "could not prepare iommu_clk\n");
+		clk_unprepare(iommu->pclk);
+		return ret;
+	}
 
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");
-	regs_base = devm_ioremap_resource(&pdev->dev, r);
-	if (IS_ERR(regs_base)) {
-		ret = PTR_ERR(regs_base);
-		goto fail_clk;
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	iommu->base = devm_ioremap_resource(iommu->dev, r);
+	if (IS_ERR(iommu->base)) {
+		dev_err(iommu->dev, "could not get iommu base\n");
+		ret = PTR_ERR(iommu->base);
+		goto fail;
 	}
 
-	irq = platform_get_irq_byname(pdev, "secure_irq");
-	if (irq < 0) {
+	iommu->irq = platform_get_irq(pdev, 0);
+	if (iommu->irq < 0) {
+		dev_err(iommu->dev, "could not get iommu irq\n");
 		ret = -ENODEV;
-		goto fail_clk;
+		goto fail;
 	}
 
-	msm_iommu_reset(regs_base, iommu_dev->ncb);
+	ret = of_property_read_u32(iommu->dev->of_node, "ncb", &val);
+	if (ret) {
+		dev_err(iommu->dev, "could not get ncb\n");
+		goto fail;
+	}
+	iommu->ncb = val;
 
-	SET_M(regs_base, 0, 1);
-	SET_PAR(regs_base, 0, 0);
-	SET_V2PCFG(regs_base, 0, 1);
-	SET_V2PPR(regs_base, 0, 0);
-	par = GET_PAR(regs_base, 0);
-	SET_V2PCFG(regs_base, 0, 0);
-	SET_M(regs_base, 0, 0);
+	msm_iommu_reset(iommu->base, iommu->ncb);
+	SET_M(iommu->base, 0, 1);
+	SET_PAR(iommu->base, 0, 0);
+	SET_V2PCFG(iommu->base, 0, 1);
+	SET_V2PPR(iommu->base, 0, 0);
+	par = GET_PAR(iommu->base, 0);
+	SET_V2PCFG(iommu->base, 0, 0);
+	SET_M(iommu->base, 0, 0);
 
 	if (!par) {
-		pr_err("%s: Invalid PAR value detected\n", iommu_dev->name);
+		pr_err("Invalid PAR value detected\n");
 		ret = -ENODEV;
-		goto fail_clk;
+		goto fail;
 	}
 
-	ret = request_irq(irq, msm_iommu_fault_handler, 0,
-			"msm_iommu_secure_irpt_handler", drvdata);
+	ret = devm_request_threaded_irq(iommu->dev, iommu->irq, NULL,
+					msm_iommu_fault_handler,
+					IRQF_ONESHOT | IRQF_SHARED,
+					"msm_iommu_secure_irpt_handler",
+					iommu);
 	if (ret) {
-		pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
-		goto fail_clk;
+		pr_err("Request IRQ %d failed with ret=%d\n", iommu->irq, ret);
+		goto fail;
 	}
 
+	list_add(&iommu->dev_node, &qcom_iommu_devices);
 
-	drvdata->pclk = iommu_pclk;
-	drvdata->clk = iommu_clk;
-	drvdata->base = regs_base;
-	drvdata->irq = irq;
-	drvdata->ncb = iommu_dev->ncb;
-
-	pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
-		iommu_dev->name, regs_base, irq, iommu_dev->ncb);
-
-	platform_set_drvdata(pdev, drvdata);
-
-	clk_disable(iommu_clk);
-
-	clk_disable(iommu_pclk);
-
-	return 0;
-fail_clk:
-	if (iommu_clk) {
-		clk_disable(iommu_clk);
-		clk_put(iommu_clk);
-	}
-fail_pclk:
-	clk_disable_unprepare(iommu_pclk);
-fail_enable:
-	clk_put(iommu_pclk);
+	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
+		iommu->base, iommu->irq, iommu->ncb);
 fail:
-	kfree(drvdata);
+	clk_unprepare(iommu->clk);
+	clk_unprepare(iommu->pclk);
 	return ret;
 }
 
+static const struct of_device_id msm_iommu_dt_match[] = {
+	{ .compatible = "msm,iommu-v0" },
+	{}
+};
+
 static int msm_iommu_remove(struct platform_device *pdev)
 {
-	struct msm_iommu_drvdata *drv = NULL;
+	struct msm_iommu_dev *iommu = platform_get_drvdata(pdev);
 
-	drv = platform_get_drvdata(pdev);
-	if (drv) {
-		if (drv->clk) {
-			clk_unprepare(drv->clk);
-			clk_put(drv->clk);
-		}
-		clk_unprepare(drv->pclk);
-		clk_put(drv->pclk);
-		memset(drv, 0, sizeof(*drv));
-		kfree(drv);
-	}
-	return 0;
-}
-
-static int msm_iommu_ctx_probe(struct platform_device *pdev)
-{
-	struct msm_iommu_ctx_dev *c = dev_get_platdata(&pdev->dev);
-	struct msm_iommu_drvdata *drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-	int i, ret;
-
-	if (!c || !pdev->dev.parent)
-		return -EINVAL;
-
-	drvdata = dev_get_drvdata(pdev->dev.parent);
-	if (!drvdata)
-		return -ENODEV;
-
-	ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL);
-	if (!ctx_drvdata)
-		return -ENOMEM;
-
-	ctx_drvdata->num = c->num;
-	ctx_drvdata->pdev = pdev;
-
-	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
-	platform_set_drvdata(pdev, ctx_drvdata);
-
-	ret = clk_prepare_enable(drvdata->pclk);
-	if (ret)
-		goto fail;
-
-	if (drvdata->clk) {
-		ret = clk_prepare_enable(drvdata->clk);
-		if (ret) {
-			clk_disable_unprepare(drvdata->pclk);
-			goto fail;
-		}
-	}
-
-	/* Program the M2V tables for this context */
-	for (i = 0; i < MAX_NUM_MIDS; i++) {
-		int mid = c->mids[i];
-		if (mid == -1)
-			break;
-
-		SET_M2VCBR_N(drvdata->base, mid, 0);
-		SET_CBACR_N(drvdata->base, c->num, 0);
-
-		/* Set VMID = 0 */
-		SET_VMID(drvdata->base, mid, 0);
-
-		/* Set the context number for that MID to this context */
-		SET_CBNDX(drvdata->base, mid, c->num);
-
-		/* Set MID associated with this context bank to 0*/
-		SET_CBVMID(drvdata->base, c->num, 0);
-
-		/* Set the ASID for TLB tagging for this context */
-		SET_CONTEXTIDR_ASID(drvdata->base, c->num, c->num);
-
-		/* Set security bit override to be Non-secure */
-		SET_NSCFG(drvdata->base, mid, 3);
-	}
-
-	clk_disable(drvdata->clk);
-	clk_disable(drvdata->pclk);
-
-	dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
-	return 0;
-fail:
-	kfree(ctx_drvdata);
-	return ret;
-}
-
-static int msm_iommu_ctx_remove(struct platform_device *pdev)
-{
-	struct msm_iommu_ctx_drvdata *drv = NULL;
-	drv = platform_get_drvdata(pdev);
-	if (drv) {
-		memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
-		kfree(drv);
-	}
+	clk_unprepare(iommu->clk);
+	clk_unprepare(iommu->pclk);
 	return 0;
 }
 
 static struct platform_driver msm_iommu_driver = {
 	.driver = {
 		.name	= "msm_iommu",
+		.of_match_table = msm_iommu_dt_match,
 	},
 	.probe		= msm_iommu_probe,
 	.remove		= msm_iommu_remove,
 };
 
-static struct platform_driver msm_iommu_ctx_driver = {
-	.driver = {
-		.name	= "msm_iommu_ctx",
-	},
-	.probe		= msm_iommu_ctx_probe,
-	.remove		= msm_iommu_ctx_remove,
-};
-
 static struct platform_driver * const drivers[] = {
 	&msm_iommu_driver,
 	&msm_iommu_ctx_driver,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May  1 11:54:30 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon,  2 May 2016 00:24:30 +0530
Subject: [PATCH V3 2/7] documentation: iommu: Add bindings for msm, iommu-v0 ip
In-Reply-To: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
References: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1462128875-20988-3-git-send-email-sricharan@codeaurora.org>

The MSM IOMMU is an implementation compatible with the ARM VMSA short
descriptor page tables. It provides address translation for bus masters outside
of the CPU, each connected to the IOMMU through a port called micro-TLB.
Adding the DT bindings for the same.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 .../devicetree/bindings/iommu/msm,iommu-v0.txt     | 62 ++++++++++++++++++++++
 1 file changed, 62 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt

diff --git a/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
new file mode 100644
index 0000000..63b4f96
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
@@ -0,0 +1,62 @@
+* MSM IOMMU
+
+The MSM IOMMU is an implementation compatible with the ARM VMSA short
+descriptor page tables. It provides address translation for bus masters outside
+of the CPU, each connected to the IOMMU through a port called micro-TLB.
+
+Required Properties:
+
+  - compatible: Must contain "msm,iommu-v0".
+  - reg: Base address and size of the IOMMU registers.
+  - interrupts: Specifiers for the MMU fault interrupts. For instances that
+    support secure mode two interrupts must be specified, for non-secure and
+    secure mode, in that order. For instances that don't support secure mode a
+    single interrupt must be specified.
+  - #iommu-cells: The number of cells needed to specify the stream id. This
+		  is always 1.
+  - qcom,ncb:	  The total number of context banks in the IOMMU.
+  - clocks	: List of clocks to be used during SMMU register access. See
+		  Documentation/devicetree/bindings/clock/clock-bindings.txt
+		  for information about the format. For each clock specified
+		  here, there must be a corresponding entry in clock-names
+		  (see below).
+
+  - clock-names	: List of clock names corresponding to the clocks specified in
+		  the "clocks" property (above). See
+		  Documentation/devicetree/bindings/clock/clock-bindings.txt
+		  for more info.
+
+Each bus master connected to an IOMMU must reference the IOMMU in its device
+node with the following property:
+
+  - iommus: A reference to the IOMMU in multiple cells. The first cell is a
+	    phandle to the IOMMU and the second cell is the stream id.
+	    A single master device can be connected to more than one iommu
+	    and multiple contexts in each of the iommu. So multiple entries
+	    are required to list all the iommus and the stream ids that the
+	    master is connected to.
+
+Example: mdp iommu and its bus master
+
+                mdp_port0: iommu at 7500000 {
+			compatible = "msm,iommu-v0";
+			#iommu-cells = <1>;
+			clock-names =
+			    "smmu_pclk",
+			    "iommu_clk";
+			clocks =
+			    <&mmcc SMMU_AHB_CLK>,
+			    <&mmcc MDP_AXI_CLK>;
+			reg = <0x07500000 0x100000>;
+			interrupts =
+			    <GIC_SPI 63 0>,
+			    <GIC_SPI 64 0>;
+			qcom,ncb = <2>;
+		};
+
+		mdp: qcom,mdp at 5100000 {
+			compatible = "qcom,mdp";
+			...
+			iommus = <&mdp_port0 0
+				  &mdp_port0 2>;
+		};
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May  1 11:54:31 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon,  2 May 2016 00:24:31 +0530
Subject: [PATCH V3 3/7] iommu/msm: Move the contents from msm_iommu_dev.c to
 msm_iommu.c
In-Reply-To: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
References: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1462128875-20988-4-git-send-email-sricharan@codeaurora.org>

There are only two functions left in msm_iommu_dev.c. Move it to
msm_iommu.c and delete the file.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/Makefile        |   2 +-
 drivers/iommu/msm_iommu.c     | 182 ++++++++++++++++++++++++++++++++++++
 drivers/iommu/msm_iommu_dev.c | 212 ------------------------------------------
 3 files changed, 183 insertions(+), 213 deletions(-)
 delete mode 100644 drivers/iommu/msm_iommu_dev.c

diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index e7b64d1..6de2fb1 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
-obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
+obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
 obj-$(CONFIG_QCOM_IOMMU_V1) += qcom/
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index bc1a4e3..459cd43 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/iommu.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
@@ -85,6 +86,47 @@ static void __disable_clocks(struct msm_iommu_dev *iommu)
 	clk_disable(iommu->pclk);
 }
 
+static void msm_iommu_reset(void __iomem *base, int ncb)
+{
+	int ctx;
+
+	SET_RPUE(base, 0);
+	SET_RPUEIE(base, 0);
+	SET_ESRRESTORE(base, 0);
+	SET_TBE(base, 0);
+	SET_CR(base, 0);
+	SET_SPDMBE(base, 0);
+	SET_TESTBUSCR(base, 0);
+	SET_TLBRSW(base, 0);
+	SET_GLOBAL_TLBIALL(base, 0);
+	SET_RPU_ACR(base, 0);
+	SET_TLBLKCRWE(base, 1);
+
+	for (ctx = 0; ctx < ncb; ctx++) {
+		SET_BPRCOSH(base, ctx, 0);
+		SET_BPRCISH(base, ctx, 0);
+		SET_BPRCNSH(base, ctx, 0);
+		SET_BPSHCFG(base, ctx, 0);
+		SET_BPMTCFG(base, ctx, 0);
+		SET_ACTLR(base, ctx, 0);
+		SET_SCTLR(base, ctx, 0);
+		SET_FSRRESTORE(base, ctx, 0);
+		SET_TTBR0(base, ctx, 0);
+		SET_TTBR1(base, ctx, 0);
+		SET_TTBCR(base, ctx, 0);
+		SET_BFBCR(base, ctx, 0);
+		SET_PAR(base, ctx, 0);
+		SET_FAR(base, ctx, 0);
+		SET_CTX_TLBIALL(base, ctx, 0);
+		SET_TLBFLPTER(base, ctx, 0);
+		SET_TLBSLPTER(base, ctx, 0);
+		SET_TLBLKCR(base, ctx, 0);
+		SET_PRRR(base, ctx, 0);
+		SET_NMRR(base, ctx, 0);
+		SET_CONTEXTIDR(base, ctx, 0);
+	}
+}
+
 static int __flush_iotlb(struct iommu_domain *domain)
 {
 	struct msm_priv *priv = to_msm_priv(domain);
@@ -708,6 +750,146 @@ static const struct iommu_ops msm_iommu_ops = {
 	.pgsize_bitmap = MSM_IOMMU_PGSIZES,
 };
 
+static int msm_iommu_probe(struct platform_device *pdev)
+{
+	struct resource *r;
+	struct msm_iommu_dev *iommu;
+	int ret, par, val;
+
+	iommu = devm_kzalloc(&pdev->dev, sizeof(*iommu), GFP_KERNEL);
+	if (!iommu)
+		return -ENODEV;
+
+	iommu->dev = &pdev->dev;
+	INIT_LIST_HEAD(&iommu->ctx_list);
+
+	iommu->pclk = devm_clk_get(iommu->dev, "smmu_pclk");
+	if (IS_ERR(iommu->pclk)) {
+		dev_err(iommu->dev, "could not get smmu_pclk\n");
+		return PTR_ERR(iommu->pclk);
+	}
+
+	ret = clk_prepare(iommu->pclk);
+	if (ret) {
+		dev_err(iommu->dev, "could not prepare smmu_pclk\n");
+		return ret;
+	}
+
+	iommu->clk = devm_clk_get(iommu->dev, "iommu_clk");
+	if (IS_ERR(iommu->clk)) {
+		dev_err(iommu->dev, "could not get iommu_clk\n");
+		clk_unprepare(iommu->pclk);
+		return PTR_ERR(iommu->clk);
+	}
+
+	ret = clk_prepare(iommu->clk);
+	if (ret) {
+		dev_err(iommu->dev, "could not prepare iommu_clk\n");
+		clk_unprepare(iommu->pclk);
+		return ret;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	iommu->base = devm_ioremap_resource(iommu->dev, r);
+	if (IS_ERR(iommu->base)) {
+		dev_err(iommu->dev, "could not get iommu base\n");
+		ret = PTR_ERR(iommu->base);
+		goto fail;
+	}
+
+	iommu->irq = platform_get_irq(pdev, 0);
+	if (iommu->irq < 0) {
+		dev_err(iommu->dev, "could not get iommu irq\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	ret = of_property_read_u32(iommu->dev->of_node, "qcom,ncb", &val);
+	if (ret) {
+		dev_err(iommu->dev, "could not get ncb\n");
+		goto fail;
+	}
+	iommu->ncb = val;
+
+	msm_iommu_reset(iommu->base, iommu->ncb);
+	SET_M(iommu->base, 0, 1);
+	SET_PAR(iommu->base, 0, 0);
+	SET_V2PCFG(iommu->base, 0, 1);
+	SET_V2PPR(iommu->base, 0, 0);
+	par = GET_PAR(iommu->base, 0);
+	SET_V2PCFG(iommu->base, 0, 0);
+	SET_M(iommu->base, 0, 0);
+
+	if (!par) {
+		pr_err("Invalid PAR value detected\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	ret = devm_request_threaded_irq(iommu->dev, iommu->irq, NULL,
+					msm_iommu_fault_handler,
+					IRQF_ONESHOT | IRQF_SHARED,
+					"msm_iommu_secure_irpt_handler",
+					iommu);
+	if (ret) {
+		pr_err("Request IRQ %d failed with ret=%d\n", iommu->irq, ret);
+		goto fail;
+	}
+
+	list_add(&iommu->dev_node, &qcom_iommu_devices);
+
+	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
+		iommu->base, iommu->irq, iommu->ncb);
+
+	return ret;
+fail:
+	clk_unprepare(iommu->clk);
+	clk_unprepare(iommu->pclk);
+	return ret;
+}
+
+static const struct of_device_id msm_iommu_dt_match[] = {
+	{ .compatible = "msm,iommu-v0" },
+	{}
+};
+
+static int msm_iommu_remove(struct platform_device *pdev)
+{
+	struct msm_iommu_dev *iommu = platform_get_drvdata(pdev);
+
+	clk_unprepare(iommu->clk);
+	clk_unprepare(iommu->pclk);
+	return 0;
+}
+
+static struct platform_driver msm_iommu_driver = {
+	.driver = {
+		.name	= "msm_iommu",
+		.of_match_table = msm_iommu_dt_match,
+	},
+	.probe		= msm_iommu_probe,
+	.remove		= msm_iommu_remove,
+};
+
+static int __init msm_iommu_driver_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&msm_iommu_driver);
+	if (ret != 0)
+		pr_err("Failed to register IOMMU driver\n");
+
+	return ret;
+}
+
+static void __exit msm_iommu_driver_exit(void)
+{
+	platform_driver_unregister(&msm_iommu_driver);
+}
+
+subsys_initcall(msm_iommu_driver_init);
+module_exit(msm_iommu_driver_exit);
+
 static int __init get_tex_class(int icp, int ocp, int mt, int nos)
 {
 	int i = 0;
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
deleted file mode 100644
index c2cf5e7b..0000000
--- a/drivers/iommu/msm_iommu_dev.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/iommu.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-#include "msm_iommu_hw-8xxx.h"
-#include "msm_iommu.h"
-
-static void msm_iommu_reset(void __iomem *base, int ncb)
-{
-	int ctx;
-
-	SET_RPUE(base, 0);
-	SET_RPUEIE(base, 0);
-	SET_ESRRESTORE(base, 0);
-	SET_TBE(base, 0);
-	SET_CR(base, 0);
-	SET_SPDMBE(base, 0);
-	SET_TESTBUSCR(base, 0);
-	SET_TLBRSW(base, 0);
-	SET_GLOBAL_TLBIALL(base, 0);
-	SET_RPU_ACR(base, 0);
-	SET_TLBLKCRWE(base, 1);
-
-	for (ctx = 0; ctx < ncb; ctx++) {
-		SET_BPRCOSH(base, ctx, 0);
-		SET_BPRCISH(base, ctx, 0);
-		SET_BPRCNSH(base, ctx, 0);
-		SET_BPSHCFG(base, ctx, 0);
-		SET_BPMTCFG(base, ctx, 0);
-		SET_ACTLR(base, ctx, 0);
-		SET_SCTLR(base, ctx, 0);
-		SET_FSRRESTORE(base, ctx, 0);
-		SET_TTBR0(base, ctx, 0);
-		SET_TTBR1(base, ctx, 0);
-		SET_TTBCR(base, ctx, 0);
-		SET_BFBCR(base, ctx, 0);
-		SET_PAR(base, ctx, 0);
-		SET_FAR(base, ctx, 0);
-		SET_CTX_TLBIALL(base, ctx, 0);
-		SET_TLBFLPTER(base, ctx, 0);
-		SET_TLBSLPTER(base, ctx, 0);
-		SET_TLBLKCR(base, ctx, 0);
-		SET_PRRR(base, ctx, 0);
-		SET_NMRR(base, ctx, 0);
-		SET_CONTEXTIDR(base, ctx, 0);
-	}
-}
-
-static int msm_iommu_probe(struct platform_device *pdev)
-{
-	struct resource *r;
-	struct msm_iommu_dev *iommu;
-	int ret, par, val;
-
-	iommu = devm_kzalloc(&pdev->dev, sizeof(*iommu), GFP_KERNEL);
-	if (!iommu)
-		return -ENODEV;
-
-	iommu->dev = &pdev->dev;
-	INIT_LIST_HEAD(&iommu->ctx_list);
-
-	iommu->pclk = devm_clk_get(iommu->dev, "smmu_pclk");
-	if (IS_ERR(iommu->pclk)) {
-		dev_err(iommu->dev, "could not get smmu_pclk\n");
-		return PTR_ERR(iommu->pclk);
-	}
-
-	ret = clk_prepare(iommu->pclk);
-	if (ret) {
-		dev_err(iommu->dev, "could not prepare smmu_pclk\n");
-		return ret;
-	}
-
-	iommu->clk = devm_clk_get(iommu->dev, "iommu_clk");
-	if (IS_ERR(iommu->clk)) {
-		dev_err(iommu->dev, "could not get iommu_clk\n");
-		clk_unprepare(iommu->pclk);
-		return PTR_ERR(iommu->clk);
-	}
-
-	ret = clk_prepare(iommu->clk);
-	if (ret) {
-		dev_err(iommu->dev, "could not prepare iommu_clk\n");
-		clk_unprepare(iommu->pclk);
-		return ret;
-	}
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	iommu->base = devm_ioremap_resource(iommu->dev, r);
-	if (IS_ERR(iommu->base)) {
-		dev_err(iommu->dev, "could not get iommu base\n");
-		ret = PTR_ERR(iommu->base);
-		goto fail;
-	}
-
-	iommu->irq = platform_get_irq(pdev, 0);
-	if (iommu->irq < 0) {
-		dev_err(iommu->dev, "could not get iommu irq\n");
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	ret = of_property_read_u32(iommu->dev->of_node, "ncb", &val);
-	if (ret) {
-		dev_err(iommu->dev, "could not get ncb\n");
-		goto fail;
-	}
-	iommu->ncb = val;
-
-	msm_iommu_reset(iommu->base, iommu->ncb);
-	SET_M(iommu->base, 0, 1);
-	SET_PAR(iommu->base, 0, 0);
-	SET_V2PCFG(iommu->base, 0, 1);
-	SET_V2PPR(iommu->base, 0, 0);
-	par = GET_PAR(iommu->base, 0);
-	SET_V2PCFG(iommu->base, 0, 0);
-	SET_M(iommu->base, 0, 0);
-
-	if (!par) {
-		pr_err("Invalid PAR value detected\n");
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	ret = devm_request_threaded_irq(iommu->dev, iommu->irq, NULL,
-					msm_iommu_fault_handler,
-					IRQF_ONESHOT | IRQF_SHARED,
-					"msm_iommu_secure_irpt_handler",
-					iommu);
-	if (ret) {
-		pr_err("Request IRQ %d failed with ret=%d\n", iommu->irq, ret);
-		goto fail;
-	}
-
-	list_add(&iommu->dev_node, &qcom_iommu_devices);
-
-	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
-		iommu->base, iommu->irq, iommu->ncb);
-fail:
-	clk_unprepare(iommu->clk);
-	clk_unprepare(iommu->pclk);
-	return ret;
-}
-
-static const struct of_device_id msm_iommu_dt_match[] = {
-	{ .compatible = "msm,iommu-v0" },
-	{}
-};
-
-static int msm_iommu_remove(struct platform_device *pdev)
-{
-	struct msm_iommu_dev *iommu = platform_get_drvdata(pdev);
-
-	clk_unprepare(iommu->clk);
-	clk_unprepare(iommu->pclk);
-	return 0;
-}
-
-static struct platform_driver msm_iommu_driver = {
-	.driver = {
-		.name	= "msm_iommu",
-		.of_match_table = msm_iommu_dt_match,
-	},
-	.probe		= msm_iommu_probe,
-	.remove		= msm_iommu_remove,
-};
-
-static struct platform_driver * const drivers[] = {
-	&msm_iommu_driver,
-	&msm_iommu_ctx_driver,
-};
-
-static int __init msm_iommu_driver_init(void)
-{
-	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
-}
-
-static void __exit msm_iommu_driver_exit(void)
-{
-	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
-}
-
-subsys_initcall(msm_iommu_driver_init);
-module_exit(msm_iommu_driver_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Stepan Moskovchenko <stepanm at codeaurora.org>");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May  1 11:54:32 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon,  2 May 2016 00:24:32 +0530
Subject: [PATCH V3 4/7] iommu/msm: Add support for generic master bindings
In-Reply-To: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
References: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1462128875-20988-5-git-send-email-sricharan@codeaurora.org>

This adds the xlate callback which gets invoked during
device registration from DT. The master devices gets added
through this.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/msm_iommu.c | 61 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 59 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 459cd43..71b04c7 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -28,6 +28,7 @@
 #include <linux/iommu.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/of_iommu.h>
 
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
@@ -702,6 +703,54 @@ static void print_ctx_regs(void __iomem *base, int ctx)
 	       GET_PRRR(base, ctx), GET_NMRR(base, ctx));
 }
 
+static void insert_iommu_master(struct device *dev,
+				struct msm_iommu_dev **iommu,
+				struct of_phandle_args *spec)
+{
+	struct msm_iommu_ctx_dev *master = dev->archdata.iommu;
+	int sid;
+
+	if (list_empty(&(*iommu)->ctx_list)) {
+		master = kzalloc(sizeof(*master), GFP_ATOMIC);
+		master->of_node = dev->of_node;
+		list_add(&master->list, &(*iommu)->ctx_list);
+		dev->archdata.iommu = master;
+	}
+
+	for (sid = 0; sid < master->num_mids; sid++)
+		if (master->mids[sid] == spec->args[0]) {
+			dev_warn(dev, "Stream ID 0x%hx repeated; ignoring\n",
+				 sid);
+			return;
+		}
+
+	master->mids[master->num_mids++] = spec->args[0];
+}
+
+static int qcom_iommu_of_xlate(struct device *dev,
+			       struct of_phandle_args *spec)
+{
+	struct msm_iommu_dev *iommu;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+	list_for_each_entry(iommu, &qcom_iommu_devices, dev_node)
+		if (iommu->dev->of_node == spec->np)
+			break;
+
+	if (!iommu || iommu->dev->of_node != spec->np) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	insert_iommu_master(dev, &iommu, spec);
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+
+	return ret;
+}
+
 irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 {
 	struct msm_iommu_dev *iommu = dev_id;
@@ -737,7 +786,7 @@ fail:
 	return 0;
 }
 
-static const struct iommu_ops msm_iommu_ops = {
+static struct iommu_ops msm_iommu_ops = {
 	.capable = msm_iommu_capable,
 	.domain_alloc = msm_iommu_domain_alloc,
 	.domain_free = msm_iommu_domain_free,
@@ -748,6 +797,7 @@ static const struct iommu_ops msm_iommu_ops = {
 	.map_sg = default_iommu_map_sg,
 	.iova_to_phys = msm_iommu_iova_to_phys,
 	.pgsize_bitmap = MSM_IOMMU_PGSIZES,
+	.of_xlate = qcom_iommu_of_xlate,
 };
 
 static int msm_iommu_probe(struct platform_device *pdev)
@@ -837,6 +887,7 @@ static int msm_iommu_probe(struct platform_device *pdev)
 	}
 
 	list_add(&iommu->dev_node, &qcom_iommu_devices);
+	of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops);
 
 	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
 		iommu->base, iommu->irq, iommu->ncb);
@@ -935,7 +986,13 @@ static int __init msm_iommu_init(void)
 	return 0;
 }
 
-subsys_initcall(msm_iommu_init);
+static int __init msm_iommu_of_setup(struct device_node *np)
+{
+	msm_iommu_init();
+	return 0;
+}
+
+IOMMU_OF_DECLARE(msm_iommu_of, "msm,iommu-v0", msm_iommu_of_setup);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Stepan Moskovchenko <stepanm at codeaurora.org>");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May  1 11:54:34 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon,  2 May 2016 00:24:34 +0530
Subject: [PATCH V3 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
References: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1462128875-20988-7-git-send-email-sricharan@codeaurora.org>

While using the generic pagetable ops the tlb maintenance
operation gets completed in the sync callback. So use writel_relaxed
for all register access and add a mb() at appropriate places.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/msm_iommu.c         | 11 ++++++++---
 drivers/iommu/msm_iommu_hw-8xxx.h |  7 ++++---
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index db82f4a..39e81d3 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -124,6 +124,7 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
 		SET_TLBLKCR(base, ctx, 0);
 		SET_CONTEXTIDR(base, ctx, 0);
 	}
+	mb(); /* sync */
 }
 
 static void __flush_iotlb(void *cookie)
@@ -143,6 +144,7 @@ static void __flush_iotlb(void *cookie)
 
 		__disable_clocks(iommu);
 	}
+	mb(); /* sync */
 fail:
 	return;
 }
@@ -181,7 +183,7 @@ fail:
 
 static void __flush_iotlb_sync(void *cookie)
 {
-	/* To avoid a null function pointer */
+	mb(); /* sync */
 }
 
 static const struct iommu_gather_ops msm_iommu_gather_ops = {
@@ -235,6 +237,7 @@ static void config_mids(struct msm_iommu_dev *iommu,
 		/* Set security bit override to be Non-secure */
 		SET_NSCFG(iommu->base, mid, 3);
 	}
+	mb(); /* sync */
 }
 
 static void __reset_context(void __iomem *base, int ctx)
@@ -257,6 +260,7 @@ static void __reset_context(void __iomem *base, int ctx)
 	SET_TLBFLPTER(base, ctx, 0);
 	SET_TLBSLPTER(base, ctx, 0);
 	SET_TLBLKCR(base, ctx, 0);
+	mb(); /* sync */
 }
 
 static void __program_context(void __iomem *base, int ctx,
@@ -305,6 +309,7 @@ static void __program_context(void __iomem *base, int ctx,
 
 	/* Enable the MMU */
 	SET_M(base, ctx, 1);
+	mb(); /* sync */
 }
 
 static struct iommu_domain *msm_iommu_domain_alloc(unsigned type)
@@ -500,7 +505,7 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
 	/* Invalidate context TLB */
 	SET_CTX_TLBIALL(iommu->base, master->num, 0);
 	SET_V2PPR(iommu->base, master->num, va & V2Pxx_VA);
-
+	mb(); /* sync */
 	par = GET_PAR(iommu->base, master->num);
 
 	/* We are dealing with a supersection */
@@ -714,7 +719,7 @@ static int msm_iommu_probe(struct platform_device *pdev)
 	par = GET_PAR(iommu->base, 0);
 	SET_V2PCFG(iommu->base, 0, 0);
 	SET_M(iommu->base, 0, 0);
-
+	mb(); /* sync */
 	if (!par) {
 		pr_err("Invalid PAR value detected\n");
 		ret = -ENODEV;
diff --git a/drivers/iommu/msm_iommu_hw-8xxx.h b/drivers/iommu/msm_iommu_hw-8xxx.h
index 84ba5739..161036c 100644
--- a/drivers/iommu/msm_iommu_hw-8xxx.h
+++ b/drivers/iommu/msm_iommu_hw-8xxx.h
@@ -24,10 +24,10 @@
 #define GET_CTX_REG(reg, base, ctx) \
 				(readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
 
-#define SET_GLOBAL_REG(reg, base, val)	writel((val), ((base) + (reg)))
+#define SET_GLOBAL_REG(reg, base, val)	writel_relaxed((val), ((base) + (reg)))
 
 #define SET_CTX_REG(reg, base, ctx, val) \
-			writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
+		writel_relaxed((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
 
 /* Wrappers for numbered registers */
 #define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG(b, ((r) + (n << 2)), (v))
@@ -48,7 +48,8 @@
 #define SET_FIELD(addr, mask, shift, v) \
 do { \
 	int t = readl(addr); \
-	writel((t & ~((mask) << (shift))) + (((v) & (mask)) << (shift)), addr);\
+	writel_relaxed((t & ~((mask) << (shift))) + \
+		       (((v) & (mask)) << (shift)), addr);\
 } while (0)
 
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May  1 11:54:33 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon,  2 May 2016 00:24:33 +0530
Subject: [PATCH V3 5/7] iommu/msm: use generic ARMV7S short descriptor
 pagetable ops
In-Reply-To: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
References: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1462128875-20988-6-git-send-email-sricharan@codeaurora.org>

This iommu uses the armv7 short descriptor format. So use the
generic ARMV7S pagetable ops instead of rewriting the same stuff
in the driver.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/Kconfig     |   1 +
 drivers/iommu/msm_iommu.c | 400 ++++++++++++----------------------------------
 2 files changed, 104 insertions(+), 297 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 55b2b3a..1f5d496 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -92,6 +92,7 @@ config MSM_IOMMU
 	depends on ARCH_MSM8X60 || ARCH_MSM8960 || COMPILE_TEST
 	depends on BROKEN
 	select IOMMU_API
+	select IOMMU_IO_PGTABLE_ARMV7S
 	help
 	  Support for the IOMMUs found on certain Qualcomm SOCs.
 	  These IOMMUs allow virtualization of the address space used by most
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 71b04c7..db82f4a 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -35,27 +35,27 @@
 
 #include "msm_iommu_hw-8xxx.h"
 #include "msm_iommu.h"
+#include "io-pgtable.h"
 
 #define MRC(reg, processor, op1, crn, crm, op2)				\
 __asm__ __volatile__ (							\
 "   mrc   "   #processor "," #op1 ", %0,"  #crn "," #crm "," #op2 "\n"  \
 : "=r" (reg))
 
-#define RCP15_PRRR(reg)		MRC(reg, p15, 0, c10, c2, 0)
-#define RCP15_NMRR(reg)		MRC(reg, p15, 0, c10, c2, 1)
-
 /* bitmap of the page sizes currently supported */
 #define MSM_IOMMU_PGSIZES	(SZ_4K | SZ_64K | SZ_1M | SZ_16M)
 
-static int msm_iommu_tex_class[4];
-
 DEFINE_SPINLOCK(msm_iommu_lock);
 static LIST_HEAD(qcom_iommu_devices);
+static struct iommu_ops msm_iommu_ops;
 
 struct msm_priv {
-	unsigned long *pgtable;
 	struct list_head list_attached;
 	struct iommu_domain domain;
+	struct io_pgtable_cfg	cfg;
+	struct io_pgtable_ops	*iop;
+	struct device		*dev;
+	spinlock_t		pgtlock; /* pagetable lock */
 };
 
 static struct msm_priv *to_msm_priv(struct iommu_domain *dom)
@@ -122,49 +122,74 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
 		SET_TLBFLPTER(base, ctx, 0);
 		SET_TLBSLPTER(base, ctx, 0);
 		SET_TLBLKCR(base, ctx, 0);
-		SET_PRRR(base, ctx, 0);
-		SET_NMRR(base, ctx, 0);
 		SET_CONTEXTIDR(base, ctx, 0);
 	}
 }
 
-static int __flush_iotlb(struct iommu_domain *domain)
+static void __flush_iotlb(void *cookie)
 {
-	struct msm_priv *priv = to_msm_priv(domain);
+	struct msm_priv *priv = cookie;
 	struct msm_iommu_dev *iommu = NULL;
 	struct msm_iommu_ctx_dev *master;
 	int ret = 0;
 
-#ifndef CONFIG_IOMMU_PGTABLES_L2
-	unsigned long *fl_table = priv->pgtable;
-	int i;
+	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
+		ret = __enable_clocks(iommu);
+		if (ret)
+			goto fail;
 
-	if (!list_empty(&priv->list_attached)) {
-		dmac_flush_range(fl_table, fl_table + SZ_16K);
+		list_for_each_entry(master, &iommu->ctx_list, list)
+			SET_CTX_TLBIALL(iommu->base, master->num, 0);
 
-		for (i = 0; i < NUM_FL_PTE; i++)
-			if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) {
-				void *sl_table = __va(fl_table[i] &
-								FL_BASE_MASK);
-				dmac_flush_range(sl_table, sl_table + SZ_4K);
-			}
+		__disable_clocks(iommu);
 	}
-#endif
+fail:
+	return;
+}
+
+static void __flush_iotlb_range(unsigned long iova, size_t size,
+				size_t granule, bool leaf, void *cookie)
+{
+	struct msm_priv *priv = cookie;
+	struct msm_iommu_dev *iommu = NULL;
+	struct msm_iommu_ctx_dev *master;
+	int ret = 0;
+	int temp_size;
 
 	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
 		ret = __enable_clocks(iommu);
 		if (ret)
 			goto fail;
 
-		list_for_each_entry(master, &iommu->ctx_list, list)
-			SET_CTX_TLBIALL(iommu->base, master->num, 0);
+		list_for_each_entry(master, &iommu->ctx_list, list) {
+			temp_size = size;
+			do {
+				iova &= TLBIVA_VA;
+				iova |= GET_CONTEXTIDR_ASID(iommu->base,
+							    master->num);
+				SET_TLBIVA(iommu->base, master->num, iova);
+				iova += granule;
+			} while (temp_size -= granule);
+		}
 
 		__disable_clocks(iommu);
 	}
+
 fail:
-	return ret;
+	return;
+}
+
+static void __flush_iotlb_sync(void *cookie)
+{
+	/* To avoid a null function pointer */
 }
 
+static const struct iommu_gather_ops msm_iommu_gather_ops = {
+	.tlb_flush_all = __flush_iotlb,
+	.tlb_add_flush = __flush_iotlb_range,
+	.tlb_sync = __flush_iotlb_sync,
+};
+
 static int msm_iommu_alloc_ctx(unsigned long *map, int start, int end)
 {
 	int idx;
@@ -232,15 +257,17 @@ static void __reset_context(void __iomem *base, int ctx)
 	SET_TLBFLPTER(base, ctx, 0);
 	SET_TLBSLPTER(base, ctx, 0);
 	SET_TLBLKCR(base, ctx, 0);
-	SET_PRRR(base, ctx, 0);
-	SET_NMRR(base, ctx, 0);
 }
 
-static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
+static void __program_context(void __iomem *base, int ctx,
+			      struct msm_priv *priv)
 {
-	unsigned int prrr, nmrr;
 	__reset_context(base, ctx);
 
+	/* Turn on TEX Remap */
+	SET_TRE(base, ctx, 1);
+	SET_AFE(base, ctx, 1);
+
 	/* Set up HTW mode */
 	/* TLB miss configuration: perform HTW on miss */
 	SET_TLBMCFG(base, ctx, 0x3);
@@ -248,8 +275,13 @@ static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
 	/* V2P configuration: HTW for access */
 	SET_V2PCFG(base, ctx, 0x3);
 
-	SET_TTBCR(base, ctx, 0);
-	SET_TTBR0_PA(base, ctx, (pgtable >> 14));
+	SET_TTBCR(base, ctx, priv->cfg.arm_v7s_cfg.tcr);
+	SET_TTBR0(base, ctx, priv->cfg.arm_v7s_cfg.ttbr[0]);
+	SET_TTBR1(base, ctx, priv->cfg.arm_v7s_cfg.ttbr[1]);
+
+	/* Set prrr and nmrr */
+	SET_PRRR(base, ctx, priv->cfg.arm_v7s_cfg.prrr);
+	SET_NMRR(base, ctx, priv->cfg.arm_v7s_cfg.nmrr);
 
 	/* Invalidate the TLB for this context */
 	SET_CTX_TLBIALL(base, ctx, 0);
@@ -268,38 +300,9 @@ static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
 	SET_RCOSH(base, ctx, 1);
 	SET_RCNSH(base, ctx, 1);
 
-	/* Turn on TEX Remap */
-	SET_TRE(base, ctx, 1);
-
-	/* Set TEX remap attributes */
-	RCP15_PRRR(prrr);
-	RCP15_NMRR(nmrr);
-	SET_PRRR(base, ctx, prrr);
-	SET_NMRR(base, ctx, nmrr);
-
 	/* Turn on BFB prefetch */
 	SET_BFBDFE(base, ctx, 1);
 
-#ifdef CONFIG_IOMMU_PGTABLES_L2
-	/* Configure page tables as inner-cacheable and shareable to reduce
-	 * the TLB miss penalty.
-	 */
-	SET_TTBR0_SH(base, ctx, 1);
-	SET_TTBR1_SH(base, ctx, 1);
-
-	SET_TTBR0_NOS(base, ctx, 1);
-	SET_TTBR1_NOS(base, ctx, 1);
-
-	SET_TTBR0_IRGNH(base, ctx, 0); /* WB, WA */
-	SET_TTBR0_IRGNL(base, ctx, 1);
-
-	SET_TTBR1_IRGNH(base, ctx, 0); /* WB, WA */
-	SET_TTBR1_IRGNL(base, ctx, 1);
-
-	SET_TTBR0_ORGN(base, ctx, 1); /* WB, WA */
-	SET_TTBR1_ORGN(base, ctx, 1); /* WB, WA */
-#endif
-
 	/* Enable the MMU */
 	SET_M(base, ctx, 1);
 }
@@ -316,13 +319,6 @@ static struct iommu_domain *msm_iommu_domain_alloc(unsigned type)
 		goto fail_nomem;
 
 	INIT_LIST_HEAD(&priv->list_attached);
-	priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL,
-							  get_order(SZ_16K));
-
-	if (!priv->pgtable)
-		goto fail_nomem;
-
-	memset(priv->pgtable, 0, SZ_16K);
 
 	priv->domain.geometry.aperture_start = 0;
 	priv->domain.geometry.aperture_end   = (1ULL << 32) - 1;
@@ -339,24 +335,35 @@ static void msm_iommu_domain_free(struct iommu_domain *domain)
 {
 	struct msm_priv *priv;
 	unsigned long flags;
-	unsigned long *fl_table;
-	int i;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
 	priv = to_msm_priv(domain);
+	kfree(priv);
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+}
 
-	fl_table = priv->pgtable;
+static int msm_iommu_domain_config(struct msm_priv *priv)
+{
+	spin_lock_init(&priv->pgtlock);
 
-	for (i = 0; i < NUM_FL_PTE; i++)
-		if ((fl_table[i] & 0x03) == FL_TYPE_TABLE)
-			free_page((unsigned long) __va(((fl_table[i]) &
-							FL_BASE_MASK)));
+	priv->cfg = (struct io_pgtable_cfg) {
+		.quirks = IO_PGTABLE_QUIRK_TLBI_ON_MAP,
+		.pgsize_bitmap = msm_iommu_ops.pgsize_bitmap,
+		.ias = 32,
+		.oas = 32,
+		.tlb = &msm_iommu_gather_ops,
+		.iommu_dev = priv->dev,
+	};
 
-	free_pages((unsigned long)priv->pgtable, get_order(SZ_16K));
-	priv->pgtable = NULL;
+	priv->iop = alloc_io_pgtable_ops(ARM_V7S, &priv->cfg, priv);
+	if (!priv->iop) {
+		dev_err(priv->dev, "Failed to allocate pgtable\n");
+		return -EINVAL;
+	}
 
-	kfree(priv);
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	msm_iommu_ops.pgsize_bitmap = priv->cfg.pgsize_bitmap;
+
+	return 0;
 }
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -367,6 +374,9 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 	struct msm_priv *priv = to_msm_priv(domain);
 	struct msm_iommu_ctx_dev *master;
 
+	priv->dev = dev;
+	msm_iommu_domain_config(priv);
+
 	spin_lock_irqsave(&msm_iommu_lock, flags);
 	list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) {
 		master = list_first_entry(&iommu->ctx_list,
@@ -392,14 +402,13 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 					}
 				config_mids(iommu, master);
 				__program_context(iommu->base, master->num,
-						  __pa(priv->pgtable));
+						  priv);
 			}
 			__disable_clocks(iommu);
 			list_add(&iommu->dom_node, &priv->list_attached);
 		}
 	}
 
-	ret = __flush_iotlb(domain);
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 
@@ -415,11 +424,9 @@ static void msm_iommu_detach_dev(struct iommu_domain *domain,
 	struct msm_iommu_ctx_dev *master;
 	int ret;
 
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-	ret = __flush_iotlb(domain);
-	if (ret)
-		goto fail;
+	free_io_pgtable_ops(priv->iop);
 
+	spin_lock_irqsave(&msm_iommu_lock, flags);
 	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
 		ret = __enable_clocks(iommu);
 		if (ret)
@@ -435,190 +442,30 @@ fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 }
 
-static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
+static int msm_iommu_map(struct iommu_domain *domain, unsigned long iova,
 			 phys_addr_t pa, size_t len, int prot)
 {
-	struct msm_priv *priv;
+	struct msm_priv *priv = to_msm_priv(domain);
 	unsigned long flags;
-	unsigned long *fl_table;
-	unsigned long *fl_pte;
-	unsigned long fl_offset;
-	unsigned long *sl_table;
-	unsigned long *sl_pte;
-	unsigned long sl_offset;
-	unsigned int pgprot;
-	int ret = 0, tex, sh;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	sh = (prot & MSM_IOMMU_ATTR_SH) ? 1 : 0;
-	tex = msm_iommu_tex_class[prot & MSM_IOMMU_CP_MASK];
-
-	if (tex < 0 || tex > NUM_TEX_CLASS - 1) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	priv = to_msm_priv(domain);
-
-	fl_table = priv->pgtable;
-
-	if (len != SZ_16M && len != SZ_1M &&
-	    len != SZ_64K && len != SZ_4K) {
-		pr_debug("Bad size: %d\n", len);
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (!fl_table) {
-		pr_debug("Null page table\n");
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (len == SZ_16M || len == SZ_1M) {
-		pgprot = sh ? FL_SHARED : 0;
-		pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0;
-		pgprot |= tex & 0x02 ? FL_CACHEABLE : 0;
-		pgprot |= tex & 0x04 ? FL_TEX0 : 0;
-	} else	{
-		pgprot = sh ? SL_SHARED : 0;
-		pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0;
-		pgprot |= tex & 0x02 ? SL_CACHEABLE : 0;
-		pgprot |= tex & 0x04 ? SL_TEX0 : 0;
-	}
-
-	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
-	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
-
-	if (len == SZ_16M) {
-		int i = 0;
-		for (i = 0; i < 16; i++)
-			*(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
-				  FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
-				  FL_SHARED | FL_NG | pgprot;
-	}
-
-	if (len == SZ_1M)
-		*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE | FL_NG |
-					    FL_TYPE_SECT | FL_SHARED | pgprot;
-
-	/* Need a 2nd level table */
-	if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) {
-		unsigned long *sl;
-		sl = (unsigned long *) __get_free_pages(GFP_ATOMIC,
-							get_order(SZ_4K));
-
-		if (!sl) {
-			pr_debug("Could not allocate second level table\n");
-			ret = -ENOMEM;
-			goto fail;
-		}
-
-		memset(sl, 0, SZ_4K);
-		*fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | FL_TYPE_TABLE);
-	}
-
-	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
-	sl_offset = SL_OFFSET(va);
-	sl_pte = sl_table + sl_offset;
-
-
-	if (len == SZ_4K)
-		*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | SL_NG |
-					  SL_SHARED | SL_TYPE_SMALL | pgprot;
-
-	if (len == SZ_64K) {
-		int i;
+	int ret;
 
-		for (i = 0; i < 16; i++)
-			*(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
-			    SL_NG | SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
-	}
+	spin_lock_irqsave(&priv->pgtlock, flags);
+	ret = priv->iop->map(priv->iop, iova, pa, len, prot);
+	spin_unlock_irqrestore(&priv->pgtlock, flags);
 
-	ret = __flush_iotlb(domain);
-fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
 }
 
-static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
-			    size_t len)
+static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
+			      size_t len)
 {
-	struct msm_priv *priv;
+	struct msm_priv *priv = to_msm_priv(domain);
 	unsigned long flags;
-	unsigned long *fl_table;
-	unsigned long *fl_pte;
-	unsigned long fl_offset;
-	unsigned long *sl_table;
-	unsigned long *sl_pte;
-	unsigned long sl_offset;
-	int i, ret = 0;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	priv = to_msm_priv(domain);
 
-	fl_table = priv->pgtable;
+	spin_lock_irqsave(&priv->pgtlock, flags);
+	len = priv->iop->unmap(priv->iop, iova, len);
+	spin_unlock_irqrestore(&priv->pgtlock, flags);
 
-	if (len != SZ_16M && len != SZ_1M &&
-	    len != SZ_64K && len != SZ_4K) {
-		pr_debug("Bad length: %d\n", len);
-		goto fail;
-	}
-
-	if (!fl_table) {
-		pr_debug("Null page table\n");
-		goto fail;
-	}
-
-	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
-	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
-
-	if (*fl_pte == 0) {
-		pr_debug("First level PTE is 0\n");
-		goto fail;
-	}
-
-	/* Unmap supersection */
-	if (len == SZ_16M)
-		for (i = 0; i < 16; i++)
-			*(fl_pte+i) = 0;
-
-	if (len == SZ_1M)
-		*fl_pte = 0;
-
-	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
-	sl_offset = SL_OFFSET(va);
-	sl_pte = sl_table + sl_offset;
-
-	if (len == SZ_64K) {
-		for (i = 0; i < 16; i++)
-			*(sl_pte+i) = 0;
-	}
-
-	if (len == SZ_4K)
-		*sl_pte = 0;
-
-	if (len == SZ_4K || len == SZ_64K) {
-		int used = 0;
-
-		for (i = 0; i < NUM_SL_PTE; i++)
-			if (sl_table[i])
-				used = 1;
-		if (!used) {
-			free_page((unsigned long)sl_table);
-			*fl_pte = 0;
-		}
-	}
-
-	ret = __flush_iotlb(domain);
-
-fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
-
-	/* the IOMMU API requires us to return how many bytes were unmapped */
-	len = ret ? 0 : len;
 	return len;
 }
 
@@ -699,8 +546,6 @@ static void print_ctx_regs(void __iomem *base, int ctx)
 	       GET_TTBR0(base, ctx), GET_TTBR1(base, ctx));
 	pr_err("SCTLR  = %08x    ACTLR  = %08x\n",
 	       GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
-	pr_err("PRRR   = %08x    NMRR   = %08x\n",
-	       GET_PRRR(base, ctx), GET_NMRR(base, ctx));
 }
 
 static void insert_iommu_master(struct device *dev,
@@ -941,47 +786,8 @@ static void __exit msm_iommu_driver_exit(void)
 subsys_initcall(msm_iommu_driver_init);
 module_exit(msm_iommu_driver_exit);
 
-static int __init get_tex_class(int icp, int ocp, int mt, int nos)
-{
-	int i = 0;
-	unsigned int prrr = 0;
-	unsigned int nmrr = 0;
-	int c_icp, c_ocp, c_mt, c_nos;
-
-	RCP15_PRRR(prrr);
-	RCP15_NMRR(nmrr);
-
-	for (i = 0; i < NUM_TEX_CLASS; i++) {
-		c_nos = PRRR_NOS(prrr, i);
-		c_mt = PRRR_MT(prrr, i);
-		c_icp = NMRR_ICP(nmrr, i);
-		c_ocp = NMRR_OCP(nmrr, i);
-
-		if (icp == c_icp && ocp == c_ocp && c_mt == mt && c_nos == nos)
-			return i;
-	}
-
-	return -ENODEV;
-}
-
-static void __init setup_iommu_tex_classes(void)
-{
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_NONCACHED] =
-			get_tex_class(CP_NONCACHED, CP_NONCACHED, MT_NORMAL, 1);
-
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_WA] =
-			get_tex_class(CP_WB_WA, CP_WB_WA, MT_NORMAL, 1);
-
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_NWA] =
-			get_tex_class(CP_WB_NWA, CP_WB_NWA, MT_NORMAL, 1);
-
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WT] =
-			get_tex_class(CP_WT, CP_WT, MT_NORMAL, 1);
-}
-
 static int __init msm_iommu_init(void)
 {
-	setup_iommu_tex_classes();
 	bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
 	return 0;
 }
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May  1 11:54:35 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon,  2 May 2016 00:24:35 +0530
Subject: [PATCH V3 7/7] iommu/msm: Remove driver BROKEN
In-Reply-To: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
References: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1462128875-20988-8-git-send-email-sricharan@codeaurora.org>

Now that the driver is DT adapted, bus_set_iommu gets called only
when on compatible matching. So the driver should not break multiplatform
builds now. So remove the BROKEN config.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 1f5d496..b81a0bb 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -90,7 +90,6 @@ config MSM_IOMMU
 	bool "MSM IOMMU Support"
 	depends on ARM
 	depends on ARCH_MSM8X60 || ARCH_MSM8960 || COMPILE_TEST
-	depends on BROKEN
 	select IOMMU_API
 	select IOMMU_IO_PGTABLE_ARMV7S
 	help
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From pavel at ucw.cz  Sun May  1 12:21:31 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Sun, 1 May 2016 21:21:31 +0200
Subject: camera application for testing (was Re: v4l subdevs without big
 device)
In-Reply-To: <20160501140831.GH26360@valkosipuli.retiisi.org.uk>
References: <20160428084546.GA9957@amd> <20160429071525.GA4823@amd>
 <57230DE7.3020701@xs4all.nl> <20160429221359.GA29297@amd>
 <20160501140831.GH26360@valkosipuli.retiisi.org.uk>
Message-ID: <20160501192131.GH14243@amd>

Hi!
> > 
> > What is reasonable camera application for testing?
> > 
> > N900 looks like a low-end digital camera. I have now have the hardware
> > working (can set focus to X cm using command line), but that's not
> > going to be useful for taking photos.
> 
> I guess you already knew about omap3camd; it's proprietary but from purely
> practical point of view it'd be an option to support taking photos on the
> N900. That would not be extensible any way, the best possible functionality
> is limited what the daemon implements.
> 
> I'm just mentioning the option of implementing wrapper for the omap3camd so
> that it can work with upsteam APIs, I don't propose that however.

I knew it existed, but I'd prefer not to touch proprietary code.

> > In particular, who is going to do computation neccessary for
> > autofocus, whitebalance and exposure/gain?
> 
> I think libv4l itself has algorithms to control at least some of these. It
> relies on the image data so the CPU time consumption will be high.
> 
> AFAIR Laurent has also worked on implementing some algorithms that use the
> histogram and some of the statistics. Add him to cc list.

Aha, good, let me know.

> > There's http://fcam.garage.maemo.org/gettingStarted.html that should
> > work on maemo, but a) it is not in Debian, b) it has non-trivial
> > dependencies and c) will be a lot of fun to get working...
> > 
> > (and d), will not be too useful, anyway, due to 1sec shutter lag:
> 
> I believe this will be shorter nowadays. I don't remember the exact
> technical solution which the text below refers to but I'm pretty sure it'll
> be better with the current upstream. API-wise, there's work to be done there
> (to port FCAM to upsteram APIs) but it's a possibility.

I took a look at fcam-dev in the meantime... and it does not look too
bad. It is quite n900-specific -- it needs hardware support for
histograms and sharpness maps -- but it should not be too hard to
modify.

Relying on hardware support without having fallback software
implementation feels wrong, but... it should actually be ok as I
already have the hardware...

(Is there accepted "upstream" for it?)
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From gregkh at linuxfoundation.org  Sun May  1 14:01:46 2016
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Sun, 1 May 2016 14:01:46 -0700
Subject: [PATCH 08/12] nvmem: mtk-efuse: remove nvmem regmap dependency
In-Reply-To: <1461526096-29584-9-git-send-email-srinivas.kandagatla@linaro.org>
References: <1461526096-29584-1-git-send-email-srinivas.kandagatla@linaro.org>
 <1461526096-29584-9-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <20160501210146.GA29070@kroah.com>

On Sun, Apr 24, 2016 at 08:28:12PM +0100, Srinivas Kandagatla wrote:
> This patch moves to nvmem support in the driver to use callback
> instead of regmap.
> 
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
> Acked-by: Andrew-CT Chen <andrew-ct.chen at mediatek.com>
> ---
>  drivers/nvmem/Kconfig     |  1 -
>  drivers/nvmem/mtk-efuse.c | 47 ++++++++++++++++++++++++++++++++---------------
>  2 files changed, 32 insertions(+), 16 deletions(-)

This patch didn't apply to my tree.  Can you fix it up and resend, and
also patch 11/12?

thanks,

greg k-h


From manabian at gmail.com  Sun May  1 14:04:33 2016
From: manabian at gmail.com (Joachim Eastwood)
Date: Sun, 1 May 2016 23:04:33 +0200
Subject: [PATCH 3/7] reset: lpc18xx: use devm_reset_controller_register()
In-Reply-To: <1462099023-11819-4-git-send-email-yamada.masahiro@socionext.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
 <1462099023-11819-4-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CAGhQ9Vy-Cux5G0EsVv_eU9a97x5qr7T17GKSxGOKgf5JABeEZw@mail.gmail.com>

On 1 May 2016 at 12:36, Masahiro Yamada <yamada.masahiro at socionext.com> wrote:
> Use devm_reset_controller_register() for the reset controller
> registration and remove the unregister call from the .remove callback.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> ---

Acked-by: Joachim Eastwood <manabian at gmail.com>


regards,
Joachim Eastwood


From okaya at codeaurora.org  Sun May  1 14:07:50 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sun,  1 May 2016 17:07:50 -0400
Subject: [PATCH V4 0/2] vfio, platform: add ACPI support
Message-ID: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>

The patchset makes three different changes.
1. Add support for probing ACPI platform devices.
2. Add support for ACPI _RST method support during reset
3. Make reset driver a requirement by default with an optional
   kernel command line override

Sinan Kaya (2):
  vfio, platform: add support for ACPI during probe and reset
  vfio, platform: make reset driver a requirement by default

 drivers/vfio/platform/vfio_amba.c             |   5 +
 drivers/vfio/platform/vfio_platform.c         |   5 +
 drivers/vfio/platform/vfio_platform_common.c  | 184 +++++++++++++++++++++-----
 drivers/vfio/platform/vfio_platform_private.h |   8 +-
 4 files changed, 165 insertions(+), 37 deletions(-)

-- 
1.8.2.1



From okaya at codeaurora.org  Sun May  1 14:07:52 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sun,  1 May 2016 17:07:52 -0400
Subject: [PATCH V4 2/2] vfio,
 platform: make reset driver a requirement by default
In-Reply-To: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>
References: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1462136872-17590-3-git-send-email-okaya@codeaurora.org>

The code was allowing platform devices to be used without a supporting VFIO
reset driver. The hardware can be left in some inconsistent state after a
guest machine abort.

The reset driver will put the hardware back to safe state and disable
interrupts before returning the control back to the host machine.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_amba.c             | 5 +++++
 drivers/vfio/platform/vfio_platform.c         | 5 +++++
 drivers/vfio/platform/vfio_platform_common.c  | 8 +++++++-
 drivers/vfio/platform/vfio_platform_private.h | 1 +
 4 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c
index a66479b..7585902 100644
--- a/drivers/vfio/platform/vfio_amba.c
+++ b/drivers/vfio/platform/vfio_amba.c
@@ -23,6 +23,10 @@
 #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis at virtualopensystems.com>"
 #define DRIVER_DESC     "VFIO for AMBA devices - User Level meta-driver"
 
+static bool reset_required = true;
+module_param(reset_required, bool, 0644);
+MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)");
+
 /* probing devices from the AMBA bus */
 
 static struct resource *get_amba_resource(struct vfio_platform_device *vdev,
@@ -68,6 +72,7 @@ static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
 	vdev->get_resource = get_amba_resource;
 	vdev->get_irq = get_amba_irq;
 	vdev->parent_module = THIS_MODULE;
+	vdev->reset_required = reset_required;
 
 	ret = vfio_platform_probe_common(vdev, &adev->dev);
 	if (ret) {
diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
index b1cc3a7..ef89146 100644
--- a/drivers/vfio/platform/vfio_platform.c
+++ b/drivers/vfio/platform/vfio_platform.c
@@ -23,6 +23,10 @@
 #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis at virtualopensystems.com>"
 #define DRIVER_DESC     "VFIO for platform devices - User Level meta-driver"
 
+static bool reset_required = true;
+module_param(reset_required, bool, 0644);
+MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)");
+
 /* probing devices from the linux platform bus */
 
 static struct resource *get_platform_resource(struct vfio_platform_device *vdev,
@@ -66,6 +70,7 @@ static int vfio_platform_probe(struct platform_device *pdev)
 	vdev->get_resource = get_platform_resource;
 	vdev->get_irq = get_platform_irq;
 	vdev->parent_module = THIS_MODULE;
+	vdev->reset_required = reset_required;
 
 	ret = vfio_platform_probe_common(vdev, &pdev->dev);
 	if (ret)
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 528ec04..b342538 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -683,7 +683,13 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 		return ret;
 	}
 
-	vfio_platform_get_reset(vdev);
+	ret = vfio_platform_get_reset(vdev);
+	if (ret && vdev->reset_required) {
+		pr_err("vfio: no reset function found for device %s\n",
+		       vdev->name);
+		iommu_group_put(group);
+		return ret;
+	}
 
 	mutex_init(&vdev->igate);
 
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index ba9e4f8..68fbc00 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -50,6 +50,7 @@ struct vfio_platform_region {
 };
 
 struct vfio_platform_device {
+	bool				reset_required;
 	struct vfio_platform_region	*regions;
 	u32				num_regions;
 	struct vfio_platform_irq	*irqs;
-- 
1.8.2.1



From okaya at codeaurora.org  Sun May  1 14:07:51 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sun,  1 May 2016 17:07:51 -0400
Subject: [PATCH V4 1/2] vfio,
 platform: add support for ACPI during probe and reset
In-Reply-To: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>
References: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1462136872-17590-2-git-send-email-okaya@codeaurora.org>

The code is using the compatible DT string to associate a reset driver with
the actual device itself. The compatible string does not exist on ACPI
based systems. HID is the unique identifier for a device driver instead.

When ACPI is enabled, the change will query the presence of _RST method
and will call it instead of querying an external reset driver.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_platform_common.c  | 176 +++++++++++++++++++++-----
 drivers/vfio/platform/vfio_platform_private.h |   7 +-
 2 files changed, 147 insertions(+), 36 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index e65b142..528ec04 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/acpi.h>
 #include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -41,7 +42,7 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 		if (!strcmp(iter->compat, compat) &&
 			try_module_get(iter->owner)) {
 			*module = iter->owner;
-			reset_fn = iter->reset;
+			reset_fn = iter->of_reset;
 			break;
 		}
 	}
@@ -49,20 +50,111 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 	return reset_fn;
 }
 
-static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
+
+#ifdef CONFIG_ACPI
+int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
+			     struct device *dev)
 {
-	vdev->reset = vfio_platform_lookup_reset(vdev->compat,
-						&vdev->reset_module);
-	if (!vdev->reset) {
-		request_module("vfio-reset:%s", vdev->compat);
-		vdev->reset = vfio_platform_lookup_reset(vdev->compat,
-							 &vdev->reset_module);
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	if (!adev)
+		return -ENODEV;
+
+	vdev->acpihid = acpi_device_hid(adev);
+	if (!vdev->acpihid) {
+		pr_err("VFIO: cannot find ACPI HID for %s\n",
+		       vdev->name);
+		return -ENODEV;
 	}
+	return 0;
+}
+
+static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
+{
+	struct device *dev = vdev->device;
+	acpi_handle handle = ACPI_HANDLE(dev);
+	acpi_status acpi_ret;
+	unsigned long long val;
+
+	acpi_ret = acpi_evaluate_integer(handle, "_RST", NULL, &val);
+	if (ACPI_FAILURE(acpi_ret))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
+{
+	struct device *dev = vdev->device;
+	acpi_handle handle = ACPI_HANDLE(dev);
+
+	if (acpi_has_method(handle, "_RST"))
+		return 0;
+
+	return -EINVAL;
+}
+#else
+int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
+			     struct device *dev)
+{
+	return -EINVAL;
+}
+
+static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
+{
+	return -EINVAL;
+}
+
+static int vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
+{
+	return -EINVAL;
+}
+#endif
+
+static int vfio_platform_has_reset(struct vfio_platform_device *vdev)
+{
+	if (vdev->acpihid)
+		return vfio_platform_acpi_has_reset(vdev);
+
+	if (vdev->of_reset)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int vfio_platform_get_reset(struct vfio_platform_device *vdev)
+{
+	int rc;
+
+	if (vdev->acpihid)
+		return vfio_platform_acpi_has_reset(vdev);
+
+	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
+						    &vdev->reset_module);
+	if (vdev->of_reset)
+		return 0;
+
+	rc = request_module("vfio-reset:%s", vdev->compat);
+	if (rc)
+		return rc;
+
+	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
+						    &vdev->reset_module);
+	if (vdev->of_reset)
+		return 0;
+
+	return -EINVAL;
 }
 
 static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
 {
-	if (vdev->reset)
+	if (vdev->acpihid)
+		return;
+
+	if (vdev->of_reset)
 		module_put(vdev->reset_module);
 }
 
@@ -134,6 +226,20 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
 	kfree(vdev->regions);
 }
 
+static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
+{
+	if (vdev->of_reset) {
+		dev_info(vdev->device, "reset\n");
+		vdev->of_reset(vdev);
+		return 0;
+	} else if (vdev->acpihid) {
+		return vfio_platform_acpi_call_reset(vdev);
+	}
+
+	dev_warn(vdev->device, "no reset function found!\n");
+	return -EINVAL;
+}
+
 static void vfio_platform_release(void *device_data)
 {
 	struct vfio_platform_device *vdev = device_data;
@@ -141,12 +247,7 @@ static void vfio_platform_release(void *device_data)
 	mutex_lock(&driver_lock);
 
 	if (!(--vdev->refcnt)) {
-		if (vdev->reset) {
-			dev_info(vdev->device, "reset\n");
-			vdev->reset(vdev);
-		} else {
-			dev_warn(vdev->device, "no reset function found!\n");
-		}
+		vfio_platform_call_reset(vdev);
 		vfio_platform_regions_cleanup(vdev);
 		vfio_platform_irq_cleanup(vdev);
 	}
@@ -175,12 +276,9 @@ static int vfio_platform_open(void *device_data)
 		if (ret)
 			goto err_irq;
 
-		if (vdev->reset) {
-			dev_info(vdev->device, "reset\n");
-			vdev->reset(vdev);
-		} else {
-			dev_warn(vdev->device, "no reset function found!\n");
-		}
+		ret = vfio_platform_call_reset(vdev);
+		if (ret)
+			goto err_irq;
 	}
 
 	vdev->refcnt++;
@@ -213,7 +311,7 @@ static long vfio_platform_ioctl(void *device_data,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		if (vdev->reset)
+		if (!vfio_platform_has_reset(vdev))
 			vdev->flags |= VFIO_DEVICE_FLAGS_RESET;
 		info.flags = vdev->flags;
 		info.num_regions = vdev->num_regions;
@@ -312,10 +410,7 @@ static long vfio_platform_ioctl(void *device_data,
 		return ret;
 
 	} else if (cmd == VFIO_DEVICE_RESET) {
-		if (vdev->reset)
-			return vdev->reset(vdev);
-		else
-			return -EINVAL;
+		return vfio_platform_call_reset(vdev);
 	}
 
 	return -ENOTTY;
@@ -544,6 +639,21 @@ static const struct vfio_device_ops vfio_platform_ops = {
 	.mmap		= vfio_platform_mmap,
 };
 
+int vfio_platform_of_probe(struct vfio_platform_device *vdev,
+			   struct device *dev)
+{
+	int ret;
+
+	ret = device_property_read_string(dev, "compatible",
+					  &vdev->compat);
+	if (ret) {
+		pr_err("VFIO: cannot retrieve compat for %s\n",
+			vdev->name);
+		return ret;
+	}
+	return 0;
+}
+
 int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 			       struct device *dev)
 {
@@ -553,14 +663,14 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 	if (!vdev)
 		return -EINVAL;
 
-	ret = device_property_read_string(dev, "compatible", &vdev->compat);
-	if (ret) {
-		pr_err("VFIO: cannot retrieve compat for %s\n", vdev->name);
-		return -EINVAL;
-	}
+	ret = vfio_platform_acpi_probe(vdev, dev);
+	if (ret)
+		ret = vfio_platform_of_probe(vdev, dev);
 
-	vdev->device = dev;
+	if (ret)
+		return ret;
 
+	vdev->device = dev;
 	group = iommu_group_get(dev);
 	if (!group) {
 		pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
@@ -611,7 +721,7 @@ void vfio_platform_unregister_reset(const char *compat,
 
 	mutex_lock(&driver_lock);
 	list_for_each_entry_safe(iter, temp, &reset_list, link) {
-		if (!strcmp(iter->compat, compat) && (iter->reset == fn)) {
+		if (!strcmp(iter->compat, compat) && (iter->of_reset == fn)) {
 			list_del(&iter->link);
 			break;
 		}
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 42816dd..ba9e4f8 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -58,6 +58,7 @@ struct vfio_platform_device {
 	struct mutex			igate;
 	struct module			*parent_module;
 	const char			*compat;
+	const char			*acpihid;
 	struct module			*reset_module;
 	struct device			*device;
 
@@ -71,7 +72,7 @@ struct vfio_platform_device {
 	struct resource*
 		(*get_resource)(struct vfio_platform_device *vdev, int i);
 	int	(*get_irq)(struct vfio_platform_device *vdev, int i);
-	int	(*reset)(struct vfio_platform_device *vdev);
+	int	(*of_reset)(struct vfio_platform_device *vdev);
 };
 
 typedef int (*vfio_platform_reset_fn_t)(struct vfio_platform_device *vdev);
@@ -80,7 +81,7 @@ struct vfio_platform_reset_node {
 	struct list_head link;
 	char *compat;
 	struct module *owner;
-	vfio_platform_reset_fn_t reset;
+	vfio_platform_reset_fn_t of_reset;
 };
 
 extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
@@ -103,7 +104,7 @@ extern void vfio_platform_unregister_reset(const char *compat,
 static struct vfio_platform_reset_node __reset ## _node = {	\
 	.owner = THIS_MODULE,					\
 	.compat = __compat,					\
-	.reset = __reset,					\
+	.of_reset = __reset,					\
 };								\
 __vfio_platform_register_reset(&__reset ## _node)
 
-- 
1.8.2.1



From jic23 at kernel.org  Sun May  1 11:02:50 2016
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 1 May 2016 19:02:50 +0100
Subject: [PATCH 0/3] mxs-lradc: Add support for current sources
In-Reply-To: <aadb3f41413d093312c0af3e4c207a8a@ccbib.org>
References: <1461333147-11873-1-git-send-email-harald@ccbib.org>
 <572379F5.8000501@i2se.com> <aadb3f41413d093312c0af3e4c207a8a@ccbib.org>
Message-ID: <ac57f3e9-f8f2-a6ef-52fa-0a13d7df5d4f@kernel.org>

On 29/04/16 18:45, Harald Geyer wrote:
> Hi Stefan!
> 
> On 29.04.2016 17:12, Stefan Wahren wrote:
>> Hi Harald,
>>
>> Am 22.04.2016 um 15:52 schrieb Harald Geyer:
>>> Patch 1/3 changes the driver and updates the binding documentation
>>> (I guess it is still in staging.)
>>>
>>> Patches 2/3 and 3/3 add the devicetree nodes to imx23 and imx28 boards.
>>> I'd like to get input whether this is actually desired. On boards where
>>> these regulators would never be enabled this costs a few extra bytes of
>>> RAM for allocation of the device data, because the nodes can't be easily
>>> removed in .dts files which are including the .dtsi files. The alternative
>>> is to add the new nodes to many .dts files, which would be a lot code
>>> duplication.
>>
>> if i get it right the real intention of this patch series is to make the
>> mxs-lradc provide resistance values instead of voltages.
> 
> ... or even temperature values if a thermistor is connected.
> 
>> So how about
>> dropping the whole regulator stuff and provide the values as
>> IIO_RESISTANCE via iio interface?
> 
> Can you elaborate on this?
> 
> My thinking is that there should be a thermistor (or whatever else) driver,
> that is a consumer of the regulator and a consumer of the IIO_VOLTAGE
> iio channel and provides a new device with an IIO_RESISTANCE or IIO_TEMP
> channel. Maybe there is a simpler solution, that I'm missing?
I agree with that approach - need a way to describe the upstream hardware - so
will need a thermistor driver
> 
> Actually I'm not 100% happy with the above solution myself, because if we
> start supporting devices that act as an iio-multiplexer (some device that
> is an iio consumer and provides many new iio channels and can control
> via gpios which of it child channels is actually routed to the upstream
> device) I don't know how to properly manage the regulator device.
Hmm. Are you talking about muxing the regulator as well?  That will get
complex indeed.  Might be possible to cheat and imply the regulators are
always connected to all inputs...  or do you want to dynamically change
the regulator output?  That gets messy fast - though in theory might be
possible...
> However since this is only hypothetical ATM, I think we don't have to
> worry about this too much.
> 
>> Btw this feature should be only added to dts files where is actually used.
> 
> Ok, so how do we figure out which boards these are?
> I use this on the olinuxino and I guess all evaluation boards support the
> use case too. The others I don't know enough about to be sure and I guess
> it's not a good idea to just wait until somebody speaks up and complains
> that the feature is missing on board X ...
> 
> Thanks,
> Harald
> 
>> Regards
>> Stefan
>>
>>>
>>> Harald Geyer (3):
>>>   iio: mxs-lradc: Add regulators for current sources
>>>   ARM: dts: imx23: Provide regulators for the current sources of the
>>>     LRADC
>>>   ARM: dts: imx28: Provide regulators for the current sources of the
>>>     LRADC
>>>
>>>  .../bindings/staging/iio/adc/mxs-lradc.txt         |  29 ++++
>>>  arch/arm/boot/dts/imx23.dtsi                       |   8 ++
>>>  arch/arm/boot/dts/imx28.dtsi                       |   8 ++
>>>  drivers/iio/adc/Kconfig                            |   1 +
>>>  drivers/iio/adc/mxs-lradc.c                        | 152 +++++++++++++++++++++
>>>  5 files changed, 198 insertions(+)
>>>
> 



From jic23 at kernel.org  Sun May  1 13:08:50 2016
From: jic23 at kernel.org (Jonathan Cameron)
Date: Sun, 1 May 2016 21:08:50 +0100
Subject: [PATCH V3 0/3] iio: mxs-lradc: simplify TS handling
In-Reply-To: <1461441479-23218-1-git-send-email-stefan.wahren@i2se.com>
References: <1461441479-23218-1-git-send-email-stefan.wahren@i2se.com>
Message-ID: <500c5874-4ef8-b37b-e12f-80fd5205c172@kernel.org>

Ksenija,

How would you prefer we handle this interaction of this set and your series.
Options are:

1. I apply these now and you rebase on top of the result.
2. You pull these into your series, probably after the driver split making sure these
   improvements end up in the new drivers.
3. We ask Stephan to re roll them at a later date (least preferred option as that adds
another person we need to chase down to get to the end of this process!)

No immediate rush on any of the above as we've probably missed this cycle now anyway.
I've been cut off today so not sure what Linus has said today.

Jonathan
On 23/04/16 20:57, Stefan Wahren wrote:
> This patch series simplifies TS handling of mxs-lradc.
> 
> These patches has been tested with i.MX23 and i.MX28 but without
> a touchscreen. I added only a bogus touchscreen in devicetree.
> 
> It would be nice if someone with a real touchscreen could test it.
> 
> Changes in V3:
> - remove dev.parent assignment as suggested by Dimitry
> - add new patch to remove mxs_lradc_ts_unregister
> - remove PM implementation from series in order to wait until 
>   Ksenija has split the driver
> 
> Changes in V2:
> - rebase on iio/testing since patch 2 and 3 from V1 has been applied
> - also remove input_unregister_device in patch 1
> - use mask of virtual channels for IRQ disabling in patch 2
> 
> Stefan Wahren (3):
>   iio: mxs-lradc: simplify TS registration
>   iio: mxs-lradc: remove mxs_lradc_ts_unregister
>   iio: mxs-lradc: disable only masked channels in     
>     mxs_lradc_hw_stop
> 
>  drivers/iio/adc/mxs-lradc.c |   34 ++++++----------------------------
>  1 file changed, 6 insertions(+), 28 deletions(-)
> 



From khilman at baylibre.com  Sun May  1 16:48:51 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Sun, 01 May 2016 16:48:51 -0700
Subject: [PATCH 1/2] pinctrl: amlogic: Add support for Amlogic Meson GXBB
 SoC
In-Reply-To: <CAOQ7t2YEVsk9cB-kmp-fXSVsVVtXynFbMSxPzTPE_0+s0qY9PQ@mail.gmail.com>
 (Carlo Caione's message of "Sun, 1 May 2016 11:20:14 +0200")
References: <1462036875-22625-1-git-send-email-carlo@caione.org>
 <1462036875-22625-2-git-send-email-carlo@caione.org>
 <CACRpkdbfSgVH_zGMdgyfvBbnpiTkd7dzugza4_w0_7MLMVNzyA@mail.gmail.com>
 <CAOQ7t2YEVsk9cB-kmp-fXSVsVVtXynFbMSxPzTPE_0+s0qY9PQ@mail.gmail.com>
Message-ID: <m2y47tuyos.fsf@baylibre.com>

Carlo Caione <carlo at caione.org> writes:

> On Sun, May 1, 2016 at 11:03 AM, Linus Walleij <linus.walleij at linaro.org> wrote:
>> On Sat, Apr 30, 2016 at 7:21 PM, Carlo Caione <carlo at caione.org> wrote:
>>
>>> From: Carlo Caione <carlo at endlessm.com>
>>>
>>> This patch adds the basic platform file to support the pin controller
>>> found on the Amlogic Meson GXBB SoCs.
>>>
>>> Signed-off-by: Carlo Caione <carlo at endlessm.com>
>>
>>>  .../devicetree/bindings/pinctrl/meson,pinctrl.txt  |   2 +
>>
>> This thing conflicts with upstream. Make a separate patch for
>> updating the bindings I think.
>
> This patch is based on linux-next where the documentation is correctly
> updated (see 11ca8735) but apparently this is missing from upstream.
> Probably slipped through the cracks with the latest PR.
>
> Kevin, did you merge both the commits in
> https://patchwork.ozlabs.org/patch/603580/ or just the DT changes?

Yes, I just pulled your branch.

That pull was merged for v4.7, which is why it's in next, but not yet
mainline (where v4.6 is just now being finalized.)

Kevin


From bsingharora at gmail.com  Sun May  1 18:05:25 2016
From: bsingharora at gmail.com (Balbir Singh)
Date: Mon, 2 May 2016 11:05:25 +1000
Subject: [RFC 1/5] powerpc: Rename context.vdso_base to context.vdso
In-Reply-To: <1461856737-17071-2-git-send-email-cov@codeaurora.org>
References: <20151202121918.GA4523@arm.com>
 <1461856737-17071-1-git-send-email-cov@codeaurora.org>
 <1461856737-17071-2-git-send-email-cov@codeaurora.org>
Message-ID: <5726A7D5.7030305@gmail.com>



On 29/04/16 01:18, Christopher Covington wrote:
> In order to share remap and unmap support for the VDSO with other
> architectures without duplicating the code, we need a common name and type
> for the address of the VDSO. An informal survey of the architectures
> indicates unsigned long vdso is popular. Change the variable name in
> powerpc from mm->context.vdso_base to simply mm->context.vdso.
> 

Could you please provide additional details on why the remap/unmap operations are required?
This patch does rename, but should it abstract via a function acesss to vmap field using arch_* operations? Not sure

Balbir Singh


From Vineet.Gupta1 at synopsys.com  Sun May  1 22:13:46 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Mon, 2 May 2016 05:13:46 +0000
Subject: [PATCH v2] asm-generic: Drop renameat syscall from default list
References: <1461965366-7893-1-git-send-email-james.hogan@imgtec.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4EA010A@us01wembx1.internal.synopsys.com>

On Saturday 30 April 2016 02:59 AM, James Hogan wrote:
> The newer renameat2 syscall provides all the functionality provided by
> the renameat syscall and adds flags, so future architectures won't need
> to include renameat.
>
> Therefore drop the renameat syscall from the generic syscall list unless
> __ARCH_WANT_RENAMEAT is defined by the architecture's unistd.h prior to
> including asm-generic/unistd.h, and adjust all architectures using the
> generic syscall list to define it so that no in-tree architectures are
> affected.
>
> Signed-off-by: James Hogan <james.hogan at imgtec.com>
> Cc: Arnd Bergmann <arnd at arndb.de>
> Cc: linux-arch at vger.kernel.org
> Cc: Vineet Gupta <vgupta at synopsys.com>
> Cc: linux-snps-arc at lists.infradead.org
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: Mark Salter <msalter at redhat.com>
> Cc: Aurelien Jacquiot <a-jacquiot at ti.com>
> Cc: linux-c6x-dev at linux-c6x.org
> Cc: Richard Kuo <rkuo at codeaurora.org>
> Cc: linux-hexagon at vger.kernel.org
> Cc: linux-metag at vger.kernel.org
> Cc: Jonas Bonn <jonas at southpole.se>
> Cc: linux at lists.openrisc.net
> Cc: Chen Liqin <liqin.linux at gmail.com>
> Cc: Lennox Wu <lennox.wu at gmail.com>
> Cc: Chris Metcalf <cmetcalf at mellanox.com>
> Cc: Guan Xuetao <gxt at mprc.pku.edu.cn>
> Cc: Ley Foon Tan <lftan at altera.com>
> Cc: nios2-dev at lists.rocketboards.org
> Cc: Yoshinori Sato <ysato at users.sourceforge.jp>
> Cc: uclinux-h8-devel at lists.sourceforge.jp
> ---
> I just found this patch on an old branch, it appears to have slipped
> through the cracks. Time for a respon.
>
> Changes in v2:
> - Rebase onto v4.6-rc5.
> - Add __ARCH_WANT_RENAMEAT to h8300 and nios2 arches too.
> ---
>  arch/arc/include/uapi/asm/unistd.h       | 1 +

Acked-by: Vineet Gupta <vgupta at synopsys.com>  # for arch/arc


From sricharan at codeaurora.org  Sun May  1 22:23:55 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon,  2 May 2016 10:53:55 +0530
Subject: [PATCH 0/2] drivers: i2c: qup: Some misc fixes
Message-ID: <1462166637-16778-1-git-send-email-sricharan@codeaurora.org>

One for fixing the bug with CONFIG_DEBUG_SG enabled and another
to suspend the transfer for all errors instead of just for nack.

Sricharan R (2):
  drivers: i2c: qup: Fix broken dma when CONFIG_DEBUG_SG is enabled.
  drivers: i2c: qup: Fix error handling

 drivers/i2c/busses/i2c-qup.c | 87 +++++++++++++++++++++-----------------------
 1 file changed, 42 insertions(+), 45 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May  1 22:23:57 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon,  2 May 2016 10:53:57 +0530
Subject: [PATCH 2/2] drivers: i2c: qup: Fix error handling
In-Reply-To: <1462166637-16778-1-git-send-email-sricharan@codeaurora.org>
References: <1462166637-16778-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1462166637-16778-3-git-send-email-sricharan@codeaurora.org>

Among the bus errors reported from the QUP_MASTER_STATUS register
only NACK is considered and transfer gets suspended, while
other errors are ignored. Correct this and suspend the transfer
for other errors as well. This avoids unnessecary 'timeouts' which
happens when waiting for events that would never happen when there
is already an error condition on the bus.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/i2c/busses/i2c-qup.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 8620e99..8afb733 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -310,6 +310,7 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
 	u32 opflags;
 	u32 status;
 	u32 shift = __ffs(op);
+	int ret = 0;
 
 	len *= qup->one_byte_t;
 	/* timeout after a wait of twice the max time */
@@ -321,18 +322,31 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
 
 		if (((opflags & op) >> shift) == val) {
 			if ((op == QUP_OUT_NOT_EMPTY) && qup->is_last) {
-				if (!(status & I2C_STATUS_BUS_ACTIVE))
-					return 0;
+				if (!(status & I2C_STATUS_BUS_ACTIVE)) {
+					ret = 0;
+					goto done;
+				}
 			} else {
-				return 0;
+				ret = 0;
+				goto done;
 			}
 		}
 
-		if (time_after(jiffies, timeout))
-			return -ETIMEDOUT;
-
+		if (time_after(jiffies, timeout)) {
+			ret = -ETIMEDOUT;
+			goto done;
+		}
 		usleep_range(len, len * 2);
 	}
+
+done:
+	if (qup->bus_err || qup->qup_err) {
+		if (qup->bus_err & QUP_I2C_NACK_FLAG)
+			dev_err(qup->dev, "NACK from %x\n", qup->msg->addr);
+		ret = -EIO;
+	}
+
+	return ret;
 }
 
 static void qup_i2c_set_write_mode_v2(struct qup_i2c_dev *qup,
@@ -882,10 +896,9 @@ static int qup_i2c_wait_for_complete(struct qup_i2c_dev *qup,
 	}
 
 	if (qup->bus_err || qup->qup_err) {
-		if (qup->bus_err & QUP_I2C_NACK_FLAG) {
+		if (qup->bus_err & QUP_I2C_NACK_FLAG)
 			dev_err(qup->dev, "NACK from %x\n", msg->addr);
-			ret = -EIO;
-		}
+		ret = -EIO;
 	}
 
 	return ret;
@@ -1227,6 +1240,9 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
 	int ret, len, idx = 0, use_dma = 0;
 
+	qup->bus_err = 0;
+	qup->qup_err = 0;
+
 	ret = pm_runtime_get_sync(qup->dev);
 	if (ret < 0)
 		goto out;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May  1 22:23:56 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon,  2 May 2016 10:53:56 +0530
Subject: [PATCH 1/2] drivers: i2c: qup: Fix broken dma when CONFIG_DEBUG_SG is
 enabled
In-Reply-To: <1462166637-16778-1-git-send-email-sricharan@codeaurora.org>
References: <1462166637-16778-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1462166637-16778-2-git-send-email-sricharan@codeaurora.org>

With CONFIG_DEBUG_SG is enabled and when dma mode is used, below dump is seen,

------------[ cut here ]------------
kernel BUG at include/linux/scatterlist.h:140!
Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.0-00459-g9f087b9-dirty #7
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
task: ffffffc036868000 ti: ffffffc036870000 task.ti: ffffffc036870000
PC is at qup_sg_set_buf.isra.13+0x138/0x154
LR is at qup_sg_set_buf.isra.13+0x50/0x154
pc : [<ffffffc0005a0ed8>] lr : [<ffffffc0005a0df0>] pstate: 60000145
sp : ffffffc0368735c0
x29: ffffffc0368735c0 x28: ffffffc036873752
x27: ffffffc035233018 x26: ffffffc000c4e000
x25: 0000000000000000 x24: 0000000000000004
x23: 0000000000000000 x22: ffffffc035233668
x21: ffffff80004e3000 x20: ffffffc0352e0018
x19: 0000004000000000 x18: 0000000000000028
x17: 0000000000000004 x16: ffffffc0017a39c8
x15: 0000000000001cdf x14: ffffffc0019929d8
x13: ffffffc0352e0018 x12: 0000000000000000
x11: 0000000000000001 x10: 0000000000000001
x9 : ffffffc0012b2d70 x8 : ffffff80004e3000
x7 : 0000000000000018 x6 : 0000000030000000
x5 : ffffffc00199f018 x4 : ffffffc035233018
x3 : 0000000000000004 x2 : 00000000c0000000
x1 : 0000000000000003 x0 : 0000000000000000

Process swapper/0 (pid: 1, stack limit = 0xffffffc036870020)
Stack: (0xffffffc0368735c0 to 0xffffffc036874000)

Change allocation of sg buffers from dma_coherent memory to kzalloc
to fix the issue.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/i2c/busses/i2c-qup.c | 53 ++++++++++++++------------------------------
 1 file changed, 17 insertions(+), 36 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 23eaabb..8620e99 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -585,8 +585,8 @@ static void qup_i2c_bam_cb(void *data)
 }
 
 static int qup_sg_set_buf(struct scatterlist *sg, void *buf,
-			  struct qup_i2c_tag *tg, unsigned int buflen,
-			  struct qup_i2c_dev *qup, int map, int dir)
+			  unsigned int buflen, struct qup_i2c_dev *qup,
+			  int dir)
 {
 	int ret;
 
@@ -595,9 +595,6 @@ static int qup_sg_set_buf(struct scatterlist *sg, void *buf,
 	if (!ret)
 		return -EINVAL;
 
-	if (!map)
-		sg_dma_address(sg) = tg->addr + ((u8 *)buf - tg->start);
-
 	return 0;
 }
 
@@ -670,16 +667,15 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 				/* scratch buf to read the start and len tags */
 				ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
 						     &qup->brx.tag.start[0],
-						     &qup->brx.tag,
-						     2, qup, 0, 0);
+						     2, qup, DMA_FROM_DEVICE);
 
 				if (ret)
 					return ret;
 
 				ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
 						     &msg->buf[limit * i],
-						     NULL, tlen, qup,
-						     1, DMA_FROM_DEVICE);
+						     tlen, qup,
+						     DMA_FROM_DEVICE);
 				if (ret)
 					return ret;
 
@@ -688,7 +684,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 			}
 			ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
 					     &qup->start_tag.start[off],
-					     &qup->start_tag, len, qup, 0, 0);
+					     len, qup, DMA_TO_DEVICE);
 			if (ret)
 				return ret;
 
@@ -696,8 +692,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 			/* scratch buf to read the BAM EOT and FLUSH tags */
 			ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
 					     &qup->brx.tag.start[0],
-					     &qup->brx.tag, 2,
-					     qup, 0, 0);
+					     2, qup, DMA_FROM_DEVICE);
 			if (ret)
 				return ret;
 		} else {
@@ -709,17 +704,15 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 				len = qup_i2c_set_tags(tags, qup, msg, 1);
 
 				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
-						     tags,
-						     &qup->start_tag, len,
-						     qup, 0, 0);
+						     tags, len,
+						     qup, DMA_TO_DEVICE);
 				if (ret)
 					return ret;
 
 				tx_len += len;
 				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
 						     &msg->buf[limit * i],
-						     NULL, tlen, qup, 1,
-						     DMA_TO_DEVICE);
+						     tlen, qup, DMA_TO_DEVICE);
 				if (ret)
 					return ret;
 				i++;
@@ -738,8 +731,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 							QUP_BAM_FLUSH_STOP;
 				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
 						     &qup->btx.tag.start[0],
-						     &qup->btx.tag, len,
-						     qup, 0, 0);
+						     len, qup, DMA_TO_DEVICE);
 				if (ret)
 					return ret;
 				tx_nents += 1;
@@ -1268,6 +1260,8 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
 		}
 	}
 
+	idx = 0;
+
 	do {
 		if (msgs[idx].len == 0) {
 			ret = -EINVAL;
@@ -1407,27 +1401,21 @@ static int qup_i2c_probe(struct platform_device *pdev)
 
 		/* 2 tag bytes for each block + 5 for start, stop tags */
 		size = blocks * 2 + 5;
-		qup->dpool = dma_pool_create("qup_i2c-dma-pool", &pdev->dev,
-					     size, 4, 0);
 
-		qup->start_tag.start = dma_pool_alloc(qup->dpool, GFP_KERNEL,
-						      &qup->start_tag.addr);
+		qup->start_tag.start = devm_kzalloc(&pdev->dev,
+						    size, GFP_KERNEL);
 		if (!qup->start_tag.start) {
 			ret = -ENOMEM;
 			goto fail_dma;
 		}
 
-		qup->brx.tag.start = dma_pool_alloc(qup->dpool,
-						    GFP_KERNEL,
-						    &qup->brx.tag.addr);
+		qup->brx.tag.start = devm_kzalloc(&pdev->dev, 2, GFP_KERNEL);
 		if (!qup->brx.tag.start) {
 			ret = -ENOMEM;
 			goto fail_dma;
 		}
 
-		qup->btx.tag.start = dma_pool_alloc(qup->dpool,
-						    GFP_KERNEL,
-						    &qup->btx.tag.addr);
+		qup->btx.tag.start = devm_kzalloc(&pdev->dev, 2, GFP_KERNEL);
 		if (!qup->btx.tag.start) {
 			ret = -ENOMEM;
 			goto fail_dma;
@@ -1566,13 +1554,6 @@ static int qup_i2c_remove(struct platform_device *pdev)
 	struct qup_i2c_dev *qup = platform_get_drvdata(pdev);
 
 	if (qup->is_dma) {
-		dma_pool_free(qup->dpool, qup->start_tag.start,
-			      qup->start_tag.addr);
-		dma_pool_free(qup->dpool, qup->brx.tag.start,
-			      qup->brx.tag.addr);
-		dma_pool_free(qup->dpool, qup->btx.tag.start,
-			      qup->btx.tag.addr);
-		dma_pool_destroy(qup->dpool);
 		dma_release_channel(qup->btx.dma);
 		dma_release_channel(qup->brx.dma);
 	}
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From myungjoo.ham at samsung.com  Sun May  1 22:48:52 2016
From: myungjoo.ham at samsung.com (MyungJoo Ham)
Date: Mon, 02 May 2016 05:48:52 +0000 (GMT)
Subject: Fwd: [PATCH v2 0/8] PM / devfreq: Add NoCP devfreq-event and support
 busfreq on exyno5422-odroidxu3
Message-ID: <1894783822.297231462168123817.JavaMail.weblogic@ep2mlwas04a>

Sender : ???<cw00.choi at samsung.com> S5(??)/Change Agent/Tizen Platform Lab(S/W??)/????
Date : 2016-04-15 15:32 (GMT+09:00)
> 
> This patchset support the AMBA bus frequency scaling on Exynos5422-based
> Odroid-XU3 board. But, this series only support the bus frequency scaling
> for INT (Internal) block using VDD_INT power line.

Along with Devfreq/Passive patchset, the patchset is merged in
devfreq for-4.7 tree.

https://git.kernel.org/cgit/linux/kernel/git/mzx/devfreq.git/log/?h=for-4.7

@Chanwoo: If there are commits to be merged by a tree other than Linux/PM,
please let me know. I'll send out pull-request soon.


Cheers,
MyungJoo

> 
> Also, to support the bus frequency scaling for Exynos542x SoC,
> Exynos542x SoC has the specific 'NoC (Network on Chip) Probe' device
> to measure the transfered data traffic on NoC (Network on Chip)
> instead of PPMU (Platform Performance Monitoring Unit). NoC Probe device
> provide the utilization for INT block of Exynos542x SoC.
> 
> The generic exynos-bus frequency driver uses the 'NoC Probe' devfreq-event
> device (drivers/devfreq/event/exynos-nocp.c) without any modification.
> Just add the phandle of 'NoC Probe' dt node to bus dt node.
> 
> Depend on:
> This patchset depends on patch[1] which support the generic exynos-bus
> frequency driver.
> [1] http://www.spinics.net/lists/arm-kernel/msg495976.html
> - [PATCH v9 00/20] PM / devferq: Add generic exynos bus frequency driver and new passive governor
> 
> 

From m.szyprowski at samsung.com  Sun May  1 22:50:20 2016
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Mon, 02 May 2016 07:50:20 +0200
Subject: [RFT PATCH 0/3] usb: misc: usb3503: Fix missing device when TFTP
 booting
In-Reply-To: <57262844.7060809@xs4all.nl>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <57247E50.1020000@xs4all.nl> <20160501131746.GA16766@kozik-lap>
 <57260E1E.70205@xs4all.nl> <57262844.7060809@xs4all.nl>
Message-ID: <58498d36-e4e1-61fc-9a11-488582972ead@samsung.com>

Hi Hans,


On 2016-05-01 18:01, Hans Verkuil wrote:
> On 05/01/2016 04:09 PM, Hans Verkuil wrote:
>> On 05/01/2016 03:17 PM, Krzysztof Kozlowski wrote:
>>> On Sat, Apr 30, 2016 at 11:43:44AM +0200, Hans Verkuil wrote:
>>>> Hi Krzysztof,
>>>>
>>>> On 04/29/2016 12:59 PM, Krzysztof Kozlowski wrote:
>>>>> Hi,
>>>>>
>>>>> Patches are independent, please pick up as you wish.
>>>>>
>>>>> However all of them are needed to solve the issue, so I am sending
>>>>> everything together for easier testng.
>>>>>
>>>>>
>>>>> Problem
>>>>> =======
>>>>> When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
>>>>> the usb3503 does not show up in "lsusb". Hard-reset is required, e.g.
>>>>> by suspend to RAM. The actual TFTP boot does not have to happen. Just
>>>>> "usb start" from U-Boot is sufficient.
>>>>>
>>>>>
>>>>> Solution
>>>>> ========
>>>>> Perform real hardware reset (including regulator off/on) when probing.
>>>>>
>>>>>
>>>>> Tested on Odroid U3 so far. Please kindly test on X2 and other
>>>>> configurations and bootloaders.
>>>> Against which kernel git repo is this patch?
>>>>
>>>> I did apply this patch series first:
>>>>
>>>> http://www.spinics.net/lists/arm-kernel/msg500764.html
>>> Indeed it is based on above patchset... and on linux-next. It touches
>>> multiple trees so next seems the easiest base.
>>>
>>>> followed by this patch series.
>>>>
>>>> I've tested with both 4.6.0-rc2 and -rc5, but in all cases (even without
>>>> applying these patches!) the boot sequence hangs here:
>>>>
>>>> ...
>>>> [drm] Exynos DRM: using 12c10000.mixer device for DMA mapping operations
>>>> exynos-drm exynos-drm: bound 12c10000.mixer (ops mixer_component_ops)
>>>> exynos-drm exynos-drm: bound 12d00000.hdmi (ops hdmi_component_ops)
>>>> [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
>>>> [drm] No driver support for vblank timestamp query.
>>>> Console: switching to colour frame buffer device 240x67
>>>> exynos-drm exynos-drm: fb0:  frame buffer device
>>>> [drm] Initialized exynos 1.0.0 20110530 on minor 0
>>>> brd: module loaded
>>>> loop: module loaded
>>>> s3c64xx-spi 13930000.spi: spi bus clock parent not specified, using clock
>>>> at index 0 as parent
>>>> s3c64xx-spi 13930000.spi: number of chip select lines not specified,
>>>> assuming 1 chip select line
>>>> tun: Universal TUN/TAP device driver, 1.6
>>>> tun: (C) 1999-2004 Max Krasnyansky <maxk at qualcomm.com>
>>>> usbcore: registered new interface driver asix
>>>> usbcore: registered new interface driver ax88179_178a
>>>> usbcore: registered new interface driver cdc_ether
>>>> usbcore: registered new interface driver smsc95xx
>>>> usbcore: registered new interface driver cdc_ncm
>>>> dwc2 12480000.hsotg: Specified GNPTXFDEP=1024 > 768
>>>> dwc2 12480000.hsotg: EPs: 16, dedicated fifos, 7808 entries in SPRAM
>>>> ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
>>>> ehci-exynos: EHCI EXYNOS driver
>>>> exynos-ehci 12580000.ehci: EHCI Host Controller
>>>> exynos-ehci 12580000.ehci: new USB bus registered, assigned bus number 1
>>>> exynos-ehci 12580000.ehci: irq 51, io mem 0x12580000
>>>> exynos-ehci 12580000.ehci: USB 2.0 started, EHCI 1.00
>>>> usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
>>>> usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
>>>> usb usb1: Product: EHCI Host Controller
>>>> usb usb1: Manufacturer: Linux 4.6.0-rc5-odroid ehci_hcd
>>>> usb usb1: SerialNumber: 12580000.ehci
>>>> hub 1-0:1.0: USB hub found
>>>> hub 1-0:1.0: 3 ports detected
>>>> ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
>>>> ohci-exynos: OHCI EXYNOS driver
>>>> usbcore: registered new interface driver usb-storage
>>>> usb3503 0-0008: switched to HUB mode
>>>> usb3503 0-0008: usb3503_probe: probed in hub mode
>>>> using random self ethernet address
>>>> using random host ethernet address
>>>> usb0: HOST MAC 66:79:ef:11:72:85
>>>> usb0: MAC 1e:66:f2:66:8e:2a
>>>> using random self ethernet address
>>>> using random host ethernet address
>>>> g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
>>>> g_ether gadget: g_ether ready
>>>> dwc2 12480000.hsotg: bound driver g_ether
>>>> mousedev: PS/2 mouse device common for all mice
>>>> max77686-rtc max77686-rtc: rtc core: registered max77686-rtc as rtc0
>>>> i2c /dev entries driver
>>>> s5p-fimc-md camera: Entity type for entity FIMC.0 was not initialized!
>>>> usb 1-2: new high-speed USB device number 2 using exynos-ehci
>>>> usb 1-2: New USB device found, idVendor=0424, idProduct=9730
>>>> usb 1-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
>>>> smsc95xx v1.0.4
>>>> smsc95xx 1-2:1.0 eth0: register 'smsc95xx' at usb-12580000.ehci-2, smsc95xx
>>>> USB 2.0 Ethernet, c2:22:09:f2:5f:e8
>>>> usb 1-3: new high-speed USB device number 3 using exynos-ehci
>>>> usb 1-3: New USB device found, idVendor=0424, idProduct=3503
>>>> usb 1-3: New USB device strings: Mfr=0, Product=0, SerialNumber=0
>>>> hub 1-3:1.0: USB hub found
>>>> hub 1-3:1.0: 3 ports detected
>>>>
>>>> No oops, no nothing. It's just sitting there.
>>> Apparently you have encountered different issue. sysrq with 'l' might be
>>> useful.
>>>
>>>> Is this a regression that was introduced in 4.6? Or is there some special
>>>> new config that needs to be turned on first in 4.6?
>>> I think it was like that for looong time... although I did not use
>>> netboot before on that target.
>> Sorry, I meant the hanging issue I got in 4.6, not the ethernet issue.
>> I get the same problem with linux-next. Can you mail me the .config you are using?
> Never mind.
>
>> After some more testing I don't think it is hanging, instead it seems that the mmc
>> isn't enabled/found and so it just sits waiting for the root partition to appear.
> That was fun. There are two problems that both caused the boot to end at the same
> place: first of all the root partition is now called mmcblk1p1 instead of mmcblk0p1
> in 4.6, so it was just waiting for the root partition to appear. Nothing to do with
> your patch series, just unexpected.

This is known "issue", it has been reported several times. This is 
caused by some
changes in mmc core. The best workaround is to use PARTUUID instead of 
hardcoding
root device path.

>
> The second is that enabling CONFIG_VIDEO_S5P_FIMC causes the boot to hang at that
> same place. I suspect there is a deadlock somewhere. I'm digging deeper into that
> but again, unrelated to your patch series.

I've posted a fix a few days ago: https://patchwork.linuxtv.org/patch/34117/
A change to media device core causes deadlock on driver registration.

> Anyway, after disabling that config option I was finally able to test your patch
> series:
>
> Tested-by: Hans Verkuil <hans.verkuil at cisco.com>

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



From k.kozlowski at samsung.com  Sun May  1 22:55:35 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 02 May 2016 07:55:35 +0200
Subject: Fwd: [PATCH v2 0/8] PM / devfreq: Add NoCP devfreq-event and
 support busfreq on exyno5422-odroidxu3
In-Reply-To: <1894783822.297231462168123817.JavaMail.weblogic@ep2mlwas04a>
References: <1894783822.297231462168123817.JavaMail.weblogic@ep2mlwas04a>
Message-ID: <5726EBD7.30403@samsung.com>

On 05/02/2016 07:48 AM, MyungJoo Ham wrote:
> Sender : ???<cw00.choi at samsung.com> S5(??)/Change Agent/Tizen Platform Lab(S/W??)/????
> Date : 2016-04-15 15:32 (GMT+09:00)
>>
>> This patchset support the AMBA bus frequency scaling on Exynos5422-based
>> Odroid-XU3 board. But, this series only support the bus frequency scaling
>> for INT (Internal) block using VDD_INT power line.
> 
> Along with Devfreq/Passive patchset, the patchset is merged in
> devfreq for-4.7 tree.
> 
> https://git.kernel.org/cgit/linux/kernel/git/mzx/devfreq.git/log/?h=for-4.7
> 
> @Chanwoo: If there are commits to be merged by a tree other than Linux/PM,
> please let me know. I'll send out pull-request soon.

As we discussed before, don't apply the DTS changes. The DTS are
independent so they should go through samsung/arm-soc.

Best regards,
Krzysztof



From k.kozlowski at samsung.com  Sun May  1 23:06:13 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 02 May 2016 08:06:13 +0200
Subject: Fwd: [PATCH v2 0/8] PM / devfreq: Add NoCP devfreq-event and
 support busfreq on exyno5422-odroidxu3
In-Reply-To: <5726EBD7.30403@samsung.com>
References: <1894783822.297231462168123817.JavaMail.weblogic@ep2mlwas04a>
 <5726EBD7.30403@samsung.com>
Message-ID: <5726EE55.7050204@samsung.com>

On 05/02/2016 07:55 AM, Krzysztof Kozlowski wrote:
> On 05/02/2016 07:48 AM, MyungJoo Ham wrote:
>> Sender : ???<cw00.choi at samsung.com> S5(??)/Change Agent/Tizen Platform Lab(S/W??)/????
>> Date : 2016-04-15 15:32 (GMT+09:00)
>>>
>>> This patchset support the AMBA bus frequency scaling on Exynos5422-based
>>> Odroid-XU3 board. But, this series only support the bus frequency scaling
>>> for INT (Internal) block using VDD_INT power line.
>>
>> Along with Devfreq/Passive patchset, the patchset is merged in
>> devfreq for-4.7 tree.
>>
>> https://git.kernel.org/cgit/linux/kernel/git/mzx/devfreq.git/log/?h=for-4.7
>>
>> @Chanwoo: If there are commits to be merged by a tree other than Linux/PM,
>> please let me know. I'll send out pull-request soon.
> 
> As we discussed before, don't apply the DTS changes. The DTS are
> independent so they should go through samsung/arm-soc.

Another point is that you applied patches without your signed-off-by...
that is not the proper way. If you touch a patch or apply it, you must
signed it off.

BR,
Krzysztof



From ksenija.stanojevic at gmail.com  Sun May  1 23:06:58 2016
From: ksenija.stanojevic at gmail.com (=?UTF-8?Q?Ksenija_Stanojevi=C4=87?=)
Date: Mon, 2 May 2016 08:06:58 +0200
Subject: [PATCH V3 0/3] iio: mxs-lradc: simplify TS handling
In-Reply-To: <500c5874-4ef8-b37b-e12f-80fd5205c172@kernel.org>
References: <1461441479-23218-1-git-send-email-stefan.wahren@i2se.com>
 <500c5874-4ef8-b37b-e12f-80fd5205c172@kernel.org>
Message-ID: <CAL7P5jJF9EL4Zk-AC9csyadfrmUp4R+6ceVAN_kNm7dKgo+ZgQ@mail.gmail.com>

Hi Jonathan,

On Sun, May 1, 2016 at 10:08 PM, Jonathan Cameron <jic23 at kernel.org> wrote:
> Ksenija,
>
> How would you prefer we handle this interaction of this set and your series.
> Options are:
>
> 1. I apply these now and you rebase on top of the result.
> 2. You pull these into your series, probably after the driver split making sure these
>    improvements end up in the new drivers.
> 3. We ask Stephan to re roll them at a later date (least preferred option as that adds
> another person we need to chase down to get to the end of this process!)
>
> No immediate rush on any of the above as we've probably missed this cycle now anyway.
> I've been cut off today so not sure what Linus has said today.

My understanding was that you will take this patch series so I already included
changes made by this patch set in touchscreen part, I will check if I missed
something.
I think the best is to apply these now.

Thanks,
Ksenija

> Jonathan
> On 23/04/16 20:57, Stefan Wahren wrote:
>> This patch series simplifies TS handling of mxs-lradc.
>>
>> These patches has been tested with i.MX23 and i.MX28 but without
>> a touchscreen. I added only a bogus touchscreen in devicetree.
>>
>> It would be nice if someone with a real touchscreen could test it.
>>
>> Changes in V3:
>> - remove dev.parent assignment as suggested by Dimitry
>> - add new patch to remove mxs_lradc_ts_unregister
>> - remove PM implementation from series in order to wait until
>>   Ksenija has split the driver
>>
>> Changes in V2:
>> - rebase on iio/testing since patch 2 and 3 from V1 has been applied
>> - also remove input_unregister_device in patch 1
>> - use mask of virtual channels for IRQ disabling in patch 2
>>
>> Stefan Wahren (3):
>>   iio: mxs-lradc: simplify TS registration
>>   iio: mxs-lradc: remove mxs_lradc_ts_unregister
>>   iio: mxs-lradc: disable only masked channels in
>>     mxs_lradc_hw_stop
>>
>>  drivers/iio/adc/mxs-lradc.c |   34 ++++++----------------------------
>>  1 file changed, 6 insertions(+), 28 deletions(-)
>>
>


From tiffany.lin at mediatek.com  Sun May  1 23:22:03 2016
From: tiffany.lin at mediatek.com (tiffany lin)
Date: Mon, 2 May 2016 14:22:03 +0800
Subject: [PATCH v9 0/8] Add MT8173 Video Encoder Driver and VPU Driver
In-Reply-To: <5723422E.4030109@xs4all.nl>
References: <1461661117-4657-1-git-send-email-tiffany.lin@mediatek.com>
 <5723422E.4030109@xs4all.nl>
Message-ID: <1462170123.18420.3.camel@mtksdaap41>

Hi Hans,

On Fri, 2016-04-29 at 13:14 +0200, Hans Verkuil wrote:
> Hi Tiffany,
> 
> On 04/26/2016 10:58 AM, Tiffany Lin wrote:
> > ==============
> >  Introduction
> > ==============
> > 
> > The purpose of this series is to add the driver for video codec hw embedded in the Mediatek's MT8173 SoCs.
> > Mediatek Video Codec is able to handle video encoding of in a range of formats.
> > 
> > This patch series also include VPU driver. Mediatek Video Codec driver rely on VPU driver to load,
> > communicate with VPU.
> > 
> > Internally the driver uses videobuf2 framework and MTK IOMMU and MTK SMI both have been merged in v4.6-rc1.
> > 
> > ==================
> >  Device interface
> > ==================
> > 
> > In principle the driver bases on v4l2 memory-to-memory framework:
> > it provides a single video node and each opened file handle gets its own private context with separate
> > buffer queues. Each context consist of 2 buffer queues: OUTPUT (for source buffers, i.e. raw video
> > frames) and CAPTURE (for destination buffers, i.e. encoded video frames).
> > 
> > ==============================
> >  VPU (Video Processor Unit)
> > ==============================
> > The VPU driver for hw video codec embedded in Mediatek's MT8173 SOCs.
> > It is able to handle video decoding/encoding in a range of formats.
> > The driver provides with VPU firmware download, memory management and the communication interface between CPU and VPU.
> > For VPU initialization, it will create virtual memory for CPU access and physical address for VPU hw device access. 
> > When a decode/encode instance opens a device node, vpu driver will download vpu firmware to the device.
> > A decode/encode instant will decode/encode a frame using VPU interface to interrupt vpu to handle decoding/encoding jobs.
> > 
> > Please have a look at the code and comments will be very much appreciated.
> 
> I build this using my daily build setup and got a bunch of errors and warnings
> from both the compiler (when this driver is compile-tested on a 32 bit arch)
> and from sparse/smatch.
> 
> Can you fix these?

Our driver only support for ARM/ARM64 architecture.
I will add 
MTK_IOMMU [=y] && (ARM || ARM64) to Kconfig for VIDEO_MEDIATEK_VCODEC.
And we will fix compiler warning.

best regards,
Tiffany
> 
> linux-git-i686: WARNINGS
> 
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vpu/mtk_vpu.c: In function 'load_requested_vpu':
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vpu/mtk_vpu.c:498:117: warning: format '%lx' expects argument of type 'long unsigned int', but argument 4 has type 'size_t {aka unsigned int}' [-Wformat=]
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vpu/mtk_vpu.c:498:117: warning: format '%lx' expects argument of type 'long unsigned int', but argument 5 has type 'size_t {aka unsigned int}' [-Wformat=]
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vpu/mtk_vpu.c:501:410: warning: format '%lx' expects argument of type 'long unsigned int', but argument 4 has type 'size_t {aka unsigned int}' [-Wformat=]
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/venc_vpu_if.c: In function 'vpu_enc_ipi_handler':
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/venc_vpu_if.c:40:30: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
>   struct venc_vpu_inst *vpu = (struct venc_vpu_inst *)msg->venc_inst;
>                               ^
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c: In function 'mtk_venc_worker':
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c:1046:43: warning: format '%lx' expects argument of type 'long unsigned int', but argument 7 has type 'size_t {aka unsigned int}' [-Wformat=]
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c:1046:43: warning: format '%lx' expects argument of type 'long unsigned int', but argument 10 has type 'size_t {aka unsigned int}' [-Wformat=]
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c:1046:43: warning: format '%lx' expects argument of type 'long unsigned int', but argument 13 has type 'size_t {aka unsigned int}' [-Wformat=]
> 
> Tip: use %zu or %zx for size_t.
> 
> sparse: ERRORS
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c:261:24: warning: incorrect type in assignment (different base types)
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c:476:23: warning: symbol 'get_vp8_enc_comm_if' was not declared. Should it be static?
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vpu/mtk_vpu.c:237:6: warning: symbol 'vpu_clock_disable' was not declared. Should it be static?
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vpu/mtk_vpu.c:250:5: warning: symbol 'vpu_clock_enable' was not declared. Should it be static?
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vpu/mtk_vpu.c:436:54: warning: incorrect type in return expression (different address spaces)
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vpu/mtk_vpu.c:504:14: warning: incorrect type in assignment (different address spaces)
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vpu/mtk_vpu.c:710:26: warning: cast removes address space of expression
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c:674:23: warning: symbol 'get_h264_enc_comm_if' was not declared. Should it be static?
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c:804:41: warning: Using plain integer as NULL pointer
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c:905:25: warning: Using plain integer as NULL pointer
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c:989:50: warning: Using plain integer as NULL pointer
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c:133:15: error: undefined identifier 'kzalloc'
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c:206:9: error: undefined identifier 'kfree'
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c:228:9: error: undefined identifier 'kfree'
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vpu/mtk_vpu.c:548:6: warning: 'vpu_fw' may be used uninitialized in this function [-Wmaybe-uninitialized]
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c:133:8: error: implicit declaration of function 'kzalloc' [-Werror=implicit-function-declaration]
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c:133:6: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c:206:2: error: implicit declaration of function 'kfree' [-Werror=implicit-function-declaration]
> 
> smatch: ERRORS
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c:921 mtk_venc_encode_header() warn: inconsistent indenting
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vpu/mtk_vpu.c:397 vpu_wdt_reg_handler() warn: variable dereferenced before check 'vpu' (see line 395)
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vpu/mtk_vpu.c:398 vpu_wdt_reg_handler() error: we previously assumed 'vpu' could be null (see line 397)
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c:142 fops_vcodec_open() error: we previously assumed 'ctx' could be null (see line 134)
> /home/hans/work/build/media-git/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c:363 mtk_vcodec_probe() warn: passing zero to 'PTR_ERR'
> 
> Thanks!
> 
> 	Hans




From k.kozlowski at samsung.com  Sun May  1 23:24:16 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 02 May 2016 08:24:16 +0200
Subject: Fwd: [PATCH v2 0/8] PM / devfreq: Add NoCP devfreq-event and
 support busfreq on exyno5422-odroidxu3
In-Reply-To: <5726EE55.7050204@samsung.com>
References: <1894783822.297231462168123817.JavaMail.weblogic@ep2mlwas04a>
 <5726EBD7.30403@samsung.com> <5726EE55.7050204@samsung.com>
Message-ID: <5726F290.8050808@samsung.com>

On 05/02/2016 08:06 AM, Krzysztof Kozlowski wrote:
> On 05/02/2016 07:55 AM, Krzysztof Kozlowski wrote:
>> On 05/02/2016 07:48 AM, MyungJoo Ham wrote:
>>> Sender : ???<cw00.choi at samsung.com> S5(??)/Change Agent/Tizen Platform Lab(S/W??)/????
>>> Date : 2016-04-15 15:32 (GMT+09:00)
>>>>
>>>> This patchset support the AMBA bus frequency scaling on Exynos5422-based
>>>> Odroid-XU3 board. But, this series only support the bus frequency scaling
>>>> for INT (Internal) block using VDD_INT power line.
>>>
>>> Along with Devfreq/Passive patchset, the patchset is merged in
>>> devfreq for-4.7 tree.
>>>
>>> https://git.kernel.org/cgit/linux/kernel/git/mzx/devfreq.git/log/?h=for-4.7
>>>
>>> @Chanwoo: If there are commits to be merged by a tree other than Linux/PM,
>>> please let me know. I'll send out pull-request soon.

... and now I noticed that you also applied clock patches. Please don't.
They are for some time in clk tree. Sylwester prepared a tag for that,
if you need one.

Best regards,
Krzysztof



From maxime.ripard at free-electrons.com  Sun May  1 23:46:45 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 2 May 2016 08:46:45 +0200
Subject: [PATCH v2 1/1] add missing UARTs pins and I2C entriesfor
 AllWinner H3 DTSI
In-Reply-To: <CAKQ8BtjPhfJC+njOUvo-4ZQ+Oj==LqQEhJ1LQROjY85hswE9Mg@mail.gmail.com>
References: <CAKQ8BtjPhfJC+njOUvo-4ZQ+Oj==LqQEhJ1LQROjY85hswE9Mg@mail.gmail.com>
Message-ID: <20160502064645.GK17159@lukather>

Hi,

On Tue, Apr 19, 2016 at 03:50:39PM -0400, Martin Ayotte wrote:
> Hi everyone,
> 
> This patch is submit to provide endusers access to additional UARTs on
> AllWinner H3 SoC along with I2C ports.

Unfortunately, your patch cannot be applied in its current form, both
because of process and technical reasons:

  * Every commits should have a commit title and log. While you do
    have a title, you used the log to store your cover letter. This is
    an issue, because that will be kept in the git history, which is
    obviously something we don't want.
    If you want to make a cover letter, you can either send it as a
    separate mail, or after the "---" below that will be ignored when
    applying the mails.
    On the other hand, the commit log should be used to say why ?our
    doing this patch and why it was needed.

  * You do not have a Signed-off-by tag in your commit log. This and
    the point above is documented in Documentation/SubmittingPatches,
    please make sure to read that first.

  * Your mailer completely corrupted the patch when you sent it,
    replacing all tabs by spaces, and wrapping the longer lines. That
    means that the patch cannot be applied anymore. Please fix your
    mailer, or use one that just works, like git send-email.

  * Finally, like Chen-Yu already told you, you're doing several
    different things here in a single patch, while you should have
    done separate patches. From what I can see, you're adding pinctrl
    groups for the uart and i2c pins, and adding the i2c controller
    nodes. That should have been ideally 3 patches: 1 for the uart
    pinctrl groups, 1 for the i2c pinctrl groups, 1 for the i2c
    controller nodes. We also don't take pinctrl groups that are not
    enabled on any boards to keep the DT size as small as possible.

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/9ea79816/attachment.sig>

From sr at denx.de  Sun May  1 23:47:15 2016
From: sr at denx.de (Stefan Roese)
Date: Mon, 2 May 2016 08:47:15 +0200
Subject: [PATCH v6] spi: orion.c: Add direct access mode
In-Reply-To: <1461147068-4829-1-git-send-email-sr@denx.de>
References: <1461147068-4829-1-git-send-email-sr@denx.de>
Message-ID: <5726F7F3.9070700@denx.de>

On 20.04.2016 12:11, Stefan Roese wrote:
> This patch adds support for the direct write mode to the Orion SPI
> driver which is used on the Marvell Armada based SoCs. In this direct
> mode, all data written to (or read from) a specifically mapped MBus
> window (linked to one SPI chip-select on one of the SPI controllers)
> will be transferred directly to the SPI bus. Without the need to control
> the SPI registers in between. This can improve the SPI transfer rate in
> such cases.
> 
> Currently only the direct write mode is supported. This mode especially
> benefits from the SPI direct mode, as the data bytes are written
> head-to-head to the SPI bus, without any additional addresses, that
> are also written in the direct read mode.
> 
> One use-case for this direct write mode is, programming a FPGA bitstream
> image into the FPGA connected to the SPI bus at maximum speed.
> 
> This mode is described in chapter "22.5.2 Direct Write to SPI" in the
> Marvell Armada XP Functional Spec Datasheet.
> 
> It should be possible to support SPI-NOR and SPI-NAND devices via
> this direct access mode as well. But this needs further work, e.g.:
> - The mapping of the MBus window needs to get extended to span
>    the complete flash device size
> - The address / control data needs to get inserted into the SPI
>    controller registers
> 
> Signed-off-by: Stefan Roese <sr at denx.de>
> Cc: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
> Cc: Gregory CLEMENT <gregory.clement at free-electrons.com>
> Cc: Andrew Lunn <andrew at lunn.ch>
> Cc: Arnd Bergmann <arnd at arndb.de>
> Cc: Mark Brown <broonie at kernel.org>

Its been a while since v6 of this direct write access mode has been
posted. This is a gentle ping on its status.

Arnd / Mark, do you have any additional change requests or are you okay
with the current version?

Thanks,
Stefan


From maxime.ripard at free-electrons.com  Sun May  1 23:48:54 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 2 May 2016 08:48:54 +0200
Subject: [PATCH v3] sunxi-irq: Fix Kconfig dependency on GENERIC_IRQ_CHIP
In-Reply-To: <1461546292-21110-1-git-send-email-andre.przywara@arm.com>
References: <1461546292-21110-1-git-send-email-andre.przywara@arm.com>
Message-ID: <20160502064854.GL17159@lukather>

Hi,

On Mon, Apr 25, 2016 at 02:04:52AM +0100, Andre Przywara wrote:
> The Allwinner NMI irqchip driver requires GENERIC_IRQ_CHIP, but
> we can't select it directly, because there is no specific Kconfig entry
> for the driver. Compiling this NMI driver with certain arm64
> configurations thus fails due to the missing dependency:
> 
> drivers/built-in.o: In function `sunxi_sc_nmi_set_type':
> drivers/irqchip/irq-sunxi-nmi.c:114: undefined reference to `irq_setup_alt_chip'
> drivers/built-in.o: In function `irq_domain_add_linear':
> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
> drivers/built-in.o: In function `sunxi_sc_nmi_irq_init':
> drivers/irqchip/irq-sunxi-nmi.c:146: undefined reference to `irq_alloc_domain_generic_chips'
> drivers/irqchip/irq-sunxi-nmi.c:161: undefined reference to `irq_get_domain_generic_chip'
> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
> drivers/irqchip/irq-sunxi-nmi.c:171: undefined reference to `irq_gc_mask_set_bit'
> drivers/irqchip/irq-sunxi-nmi.c:172: undefined reference to `irq_gc_ack_set_bit'
> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
> 
> Add separate Kconfig options for both Allwinner specific irqchip
> drivers and select GENERIC_IRQ_CHIP for the NMI driver.
> The older sun4i IRQ driver only gets selected when support for these
> specific SoCs is compiled, while the NMI driver is selected for all
> Allwinner SoCs (copying the current behaviour and covering future SoCs
> automatically).
> 
> Reported-by: Suzuki K Poulose <Suzuki.Poulose at arm.com>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Hi,
> 
> this is a new approach to the problem that Suzuki tried to address
> already.
> It separates the sun4i IRQ controller driver and the NMI driver as
> Maxime requested.
> While there should be no difference for the NMI driver, the sun4i
> driver now only gets selected for certain SoCs, which is admittedly
> a bold call for -rc5. If people find this too risky, I can bring the
> sun4i in line with the NMI driver (selected for all ARCH_SUNXI) for
> this release and re-create the more selective dependency as a merge
> window patch, so that it gets more testing.
> Please let me know.
> 
> Cheers,
> Andre.
> 
>  arch/arm/mach-sunxi/Kconfig | 3 ++-
>  drivers/irqchip/Kconfig     | 8 ++++++++
>  drivers/irqchip/Makefile    | 4 ++--
>  3 files changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> index c124d65..c092bc2 100644
> --- a/arch/arm/mach-sunxi/Kconfig
> +++ b/arch/arm/mach-sunxi/Kconfig
> @@ -4,7 +4,6 @@ menuconfig ARCH_SUNXI
>  	select ARCH_REQUIRE_GPIOLIB
>  	select ARCH_HAS_RESET_CONTROLLER
>  	select CLKSRC_MMIO
> -	select GENERIC_IRQ_CHIP
>  	select PINCTRL
>  	select SUN4I_TIMER
>  	select RESET_CONTROLLER
> @@ -14,11 +13,13 @@ if ARCH_SUNXI
>  config MACH_SUN4I
>  	bool "Allwinner A10 (sun4i) SoCs support"
>  	default ARCH_SUNXI
> +	select SUN4I_IRQCHIP
>  
>  config MACH_SUN5I
>  	bool "Allwinner A10s / A13 (sun5i) SoCs support"
>  	default ARCH_SUNXI
>  	select SUN5I_HSTIMER
> +	select SUN4I_IRQCHIP
>  
>  config MACH_SUN6I
>  	bool "Allwinner A31 (sun6i) SoCs support"
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index 3e12479..94f3f42 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -165,6 +165,14 @@ config ST_IRQCHIP
>  	help
>  	  Enables SysCfg Controlled IRQs on STi based platforms.
>  
> +config SUN4I_IRQCHIP
> +	bool
> +
> +config SUNXI_NMI
> +	bool "Allwinner SoC NMI controller"
> +	default ARCH_SUNXI
> +	select GENERIC_IRQ_CHIP

This one is only used on SUN6I, SUN7I and SUN8I. There's no need to
enable it for all the SoCs.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/d0f52893/attachment.sig>

From pavel at ucw.cz  Mon May  2 00:05:55 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Mon, 2 May 2016 09:05:55 +0200
Subject: [PATCH 1/2] ARM: OMAP2+: n900 needs MMC slot names for legacy
 user space
In-Reply-To: <1461714383-9956-2-git-send-email-tony@atomide.com>
References: <1461714383-9956-1-git-send-email-tony@atomide.com>
 <1461714383-9956-2-git-send-email-tony@atomide.com>
Message-ID: <20160502070555.GA13215@amd>

On Tue 2016-04-26 16:46:22, Tony Lindgren wrote:
> Let's pass the slot names in pdata like the legacy code does.
> Once we have a generic DT binding for the slot names we can
> switch to that.
> 
> Signed-off-by: Tony Lindgren <tony at atomide.com>

Acked-by: Pavel Machek <pavel at ucw.cz>

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From pavel at ucw.cz  Mon May  2 00:06:04 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Mon, 2 May 2016 09:06:04 +0200
Subject: [PATCH 1/5] leds: triggers: Allow to switch the trigger to
 "panic" on a kernel panic
In-Reply-To: <571DBFAE.7060605@samsung.com>
References: <1459801326-5541-1-git-send-email-ezequiel@vanguardiasur.com.ar>
 <1459801326-5541-2-git-send-email-ezequiel@vanguardiasur.com.ar>
 <20160424092551.GB23015@amd> <20160424092951.GA25596@amd>
 <571DBFAE.7060605@samsung.com>
Message-ID: <20160502070604.GB13215@amd>

On Mon 2016-04-25 08:56:46, Jacek Anaszewski wrote:
> On 04/24/2016 11:29 AM, Pavel Machek wrote:
> >On Sun 2016-04-24 11:25:51, Pavel Machek wrote:
> >>On Mon 2016-04-04 17:22:02, Ezequiel Garcia wrote:
> >>>This commit adds a new led_cdev flag LED_BLINK_AT_PANIC, which
> >>>allows to mark a specific LED to be switched to the "panic"
> >>>trigger, on a kernel panic.
> >>>
> >>>This is useful to allow the user to assign a regular trigger
> >>>to a given LED, and still blink that LED on a kernel panic.
> >>>
> >>>Signed-off-by: Ezequiel Garcia <ezequiel at vanguardiasur.com.ar>
> >>
> >>
> >>>  drivers/leds/led-triggers.c | 52 +++++++++++++++++++++++++++++++++++++++++++++
> >>>  include/linux/leds.h        |  1 +
> >>
> >>Could we get this out of the core? I'm pretty sure most users are not
> >>interested...
> 
> Good point.

Dunno. Perhaps we can have something like struct led *panic_led, which
architecture can set, and then some helper that would blink the panic
led...? Should be smaller than this and will only be compiled on
platforms where it makes sense. On x86 we already have such support...

> >Thinking about it some more....
> >
> >This is not really a trigger. This is very special. Maybe hard-coded
> >handling, like we do for keyboard leds on x86 would be suitable?
> 
> Could you please spot the piece of code you have on mind?

drivers/input/serio/i8042.c: * i8042_panic_blink() will turn the keyboard LEDs on or off and is called

			       			   	     	 	  Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From lkundrak at v3.sk  Mon May  2 00:06:51 2016
From: lkundrak at v3.sk (Lubomir Rintel)
Date: Mon,  2 May 2016 09:06:51 +0200
Subject: [PATCH v5] ARM: bcm2835: dt: Add the ethernet to the device trees
Message-ID: <1462172811-24206-1-git-send-email-lkundrak@v3.sk>

The hub and the ethernet in its port 1 are hardwired on the board.

Compared to the adapters that can be plugged into the USB ports, this
one has no serial EEPROM to store its MAC. Nevertheless, the Raspberry Pi
has the MAC address for this adapter in its ROM, accessible from its
firmware.

U-Boot can read out the address and set the local-mac-address property of the
node with "ethernet" alias. Let's add the node so that U-Boot can do its
business.

Model B rev2 and Model B+ entries were verified by me, the hierarchy and
pid/vid pair for the Version 2 was provided by Peter Chen. Original
Model B is a blind shot, though very likely correct.

Signed-off-by: Lubomir Rintel <lkundrak at v3.sk>
Acked-by: Stephen Warren <swarren at wwwdotorg.org>
---
Changes since v4:
  - A whitespace fix

Changes since v3:
  - Include the ethernet alias in 9514 dtsi too

Changes since v2:
  - Removed leading zeroes in vendor name and reg
  - Split the common files in separate includes per model

Changes since v1:
  - s/@01/@1/ for ethernet and the hub
  - Corrected the vid/pid pairs for hub and ethernet
  - Added Model B rev2 and version 2 board changes
  - Fixed a missing semicolon typo

 arch/arm/boot/dts/bcm2835-rpi-b-plus.dts    |  1 +
 arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts    |  1 +
 arch/arm/boot/dts/bcm2835-rpi-b.dts         |  1 +
 arch/arm/boot/dts/bcm2836-rpi-2-b.dts       |  1 +
 arch/arm/boot/dts/bcm283x-rpi-smsc9512.dtsi | 19 +++++++++++++++++++
 arch/arm/boot/dts/bcm283x-rpi-smsc9514.dtsi | 19 +++++++++++++++++++
 arch/arm/boot/dts/bcm283x.dtsi              |  2 ++
 7 files changed, 44 insertions(+)
 create mode 100644 arch/arm/boot/dts/bcm283x-rpi-smsc9512.dtsi
 create mode 100644 arch/arm/boot/dts/bcm283x-rpi-smsc9514.dtsi

diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
index ef54050..c3e01ce 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
@@ -1,6 +1,7 @@
 /dts-v1/;
 #include "bcm2835.dtsi"
 #include "bcm2835-rpi.dtsi"
+#include "bcm283x-rpi-smsc9514.dtsi"
 
 / {
 	compatible = "raspberrypi,model-b-plus", "brcm,bcm2835";
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
index 86f1f2f..364086a 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
@@ -1,6 +1,7 @@
 /dts-v1/;
 #include "bcm2835.dtsi"
 #include "bcm2835-rpi.dtsi"
+#include "bcm283x-rpi-smsc9512.dtsi"
 
 / {
 	compatible = "raspberrypi,model-b-rev2", "brcm,bcm2835";
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts
index 4859e9d..4420b09 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
@@ -1,6 +1,7 @@
 /dts-v1/;
 #include "bcm2835.dtsi"
 #include "bcm2835-rpi.dtsi"
+#include "bcm283x-rpi-smsc9512.dtsi"
 
 / {
 	compatible = "raspberrypi,model-b", "brcm,bcm2835";
diff --git a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
index ff94666..b975f29 100644
--- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
+++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
@@ -1,6 +1,7 @@
 /dts-v1/;
 #include "bcm2836.dtsi"
 #include "bcm2835-rpi.dtsi"
+#include "bcm283x-rpi-smsc9514.dtsi"
 
 / {
 	compatible = "raspberrypi,2-model-b", "brcm,bcm2836";
diff --git a/arch/arm/boot/dts/bcm283x-rpi-smsc9512.dtsi b/arch/arm/boot/dts/bcm283x-rpi-smsc9512.dtsi
new file mode 100644
index 0000000..12c981e
--- /dev/null
+++ b/arch/arm/boot/dts/bcm283x-rpi-smsc9512.dtsi
@@ -0,0 +1,19 @@
+/ {
+	aliases {
+		ethernet = &ethernet;
+	};
+};
+
+&usb {
+	usb1 at 1 {
+		compatible = "usb424,9512";
+		reg = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethernet: usbether at 1 {
+			compatible = "usb424,ec00";
+			reg = <1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/bcm283x-rpi-smsc9514.dtsi b/arch/arm/boot/dts/bcm283x-rpi-smsc9514.dtsi
new file mode 100644
index 0000000..3f0a56e
--- /dev/null
+++ b/arch/arm/boot/dts/bcm283x-rpi-smsc9514.dtsi
@@ -0,0 +1,19 @@
+/ {
+	aliases {
+		ethernet = &ethernet;
+	};
+};
+
+&usb {
+	usb1 at 1 {
+		compatible = "usb424,9514";
+		reg = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethernet: usbether at 1 {
+			compatible = "usb424,ec00";
+			reg = <1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index 8aaf193..04504b7 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
+++ b/arch/arm/boot/dts/bcm283x.dtsi
@@ -230,6 +230,8 @@
 			compatible = "brcm,bcm2835-usb";
 			reg = <0x7e980000 0x10000>;
 			interrupts = <1 9>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 		};
 	};
 
-- 
2.7.4



From maitysanchayan at gmail.com  Mon May  2 00:04:59 2016
From: maitysanchayan at gmail.com (Sanchayan Maity)
Date: Mon,  2 May 2016 12:34:59 +0530
Subject: [PATCH v2 0/5] Implement SoC bus driver for Vybrid
Message-ID: <cover.1462171989.git.maitysanchayan@gmail.com>

Hello,

This second patch series is rebased on top of shawn's for-next branch
and tested on Colibri Vybrid VF50 and VF61 modules.

This patchset implements SoC bus support for Freescale Vybrid platform,
implementing the following
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-soc

This a reworked version of an older patchset series posted in June 2015
which was at v5 then [1]. Since the NVMEM framework was then getting
introduced, we decided that first a NVMEM driver for OCOTP peripheral
being in place would be better.

Compared to the older revisions, this driver now relies on NVMEM
consumer API using the NVMEM based vf610_ocotp driver which has
already been in mainline for a while now. Also now a new syscon
abstraction "syscon_regmap_read_from_offset" is implemented and
exported from syscon allowing accessing a register from a syscon
reference like this

ocotp-cfg1 = <&ocotp 0x20>;

avoiding code repetition in the driver.

One point on which we were not sure here is whether we really should
introduce a new Kconfig symbol as being introduced here. While we
could just enable it when SOC_VF610 is selected, this however would
introduce circular dependencies.

Feedback is most welcome.

Changes since v1:
Add device tree binding documentation.

v1 new patchset
https://lkml.org/lkml/2016/3/11/132

[1] Older v5:
http://lkml.iu.edu/hypermail/linux/kernel/1506.0/03787.html
Even earlier versions:
Version 4 of the patchset can be found here
https://lkml.org/lkml/2015/5/26/199
Version 3 of the patchset can be found here
http://www.spinics.net/lists/arm-kernel/msg420847.html
Version 2 of the patchset can be found here
http://www.spinics.net/lists/devicetree/msg80654.html
Version 1 of the patchset can be found here
http://www.spinics.net/lists/devicetree/msg80257.html
The RFC version can be found here
https://lkml.org/lkml/2015/5/11/13

Regards,
Sanchayan.

Sanchayan Maity (5):
  mfd: syscon: Introduce syscon_regmap_read_from_offset
  ARM: dts: vfxxx: Add device tree node for OCOTP
  ARM: dts: vfxxx: Add OCROM and phandle entries for Vybrid SoC bus driver
  soc: Add SoC bus driver for Freescale Vybrid Platform
  vf610-soc: Add Vybrid SoC device tree binding documentation

 .../bindings/arm/freescale/fsl,vf610-soc.txt       |  35 +++++
 arch/arm/boot/dts/vfxxx.dtsi                       |  28 +++-
 drivers/mfd/syscon.c                               |  30 ++++
 drivers/soc/Kconfig                                |   1 +
 drivers/soc/fsl/Kconfig                            |  10 ++
 drivers/soc/fsl/Makefile                           |   1 +
 drivers/soc/fsl/soc-vf610.c                        | 160 +++++++++++++++++++++
 include/linux/mfd/syscon.h                         |  10 ++
 8 files changed, 274 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
 create mode 100644 drivers/soc/fsl/Kconfig
 create mode 100644 drivers/soc/fsl/soc-vf610.c

-- 
2.8.2



From maitysanchayan at gmail.com  Mon May  2 00:05:00 2016
From: maitysanchayan at gmail.com (Sanchayan Maity)
Date: Mon,  2 May 2016 12:35:00 +0530
Subject: [PATCH v2 1/5] mfd: syscon: Introduce syscon_regmap_read_from_offset
In-Reply-To: <cover.1462171989.git.maitysanchayan@gmail.com>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
Message-ID: <b234b680c77ae5f0678be10a226eac7976a83c34.1462171990.git.maitysanchayan@gmail.com>

Currently syscon does not provide an abstraction to access a
register from syscon reference like below

ocotp-cfg1 = <&ocotp 0x20>

syscon_regmap_read_from_offset provides a generic abstraction to
access a register from syscon reference as above. It allows to
specify the node and node name of phandle reference, reading the
offset from the node entry and providing the value from the offset
in the register map.

Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
---
 drivers/mfd/syscon.c       | 30 ++++++++++++++++++++++++++++++
 include/linux/mfd/syscon.h | 10 ++++++++++
 2 files changed, 40 insertions(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 2f2225e..74724c3 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -136,6 +136,36 @@ struct regmap *syscon_node_to_regmap(struct device_node *np)
 }
 EXPORT_SYMBOL_GPL(syscon_node_to_regmap);
 
+int syscon_regmap_read_from_offset(struct device_node *np,
+				const char *s, unsigned int *val)
+{
+	struct of_phandle_args pargs;
+	struct regmap *regmap;
+	int offset;
+	int ret;
+
+	if (!np)
+		return -ENODEV;
+
+	ret = of_parse_phandle_with_fixed_args(np, s, 1, 0, &pargs);
+	if (ret)
+		return ret;
+
+	regmap = syscon_node_to_regmap(pargs.np);
+	if (IS_ERR(regmap)) {
+		of_node_put(pargs.np);
+		return PTR_ERR(regmap);
+	}
+
+	offset = pargs.args[0];
+	of_node_put(pargs.np);
+
+	ret = regmap_read(regmap, offset, val);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(syscon_regmap_read_from_offset);
+
 struct regmap *syscon_regmap_lookup_by_compatible(const char *s)
 {
 	struct device_node *syscon_np;
diff --git a/include/linux/mfd/syscon.h b/include/linux/mfd/syscon.h
index 1088149..42b0759 100644
--- a/include/linux/mfd/syscon.h
+++ b/include/linux/mfd/syscon.h
@@ -26,6 +26,9 @@ extern struct regmap *syscon_regmap_lookup_by_pdevname(const char *s);
 extern struct regmap *syscon_regmap_lookup_by_phandle(
 					struct device_node *np,
 					const char *property);
+extern int syscon_regmap_read_from_offset(struct device_node *np,
+					  const char *s,
+					  unsigned int *val);
 #else
 static inline struct regmap *syscon_node_to_regmap(struct device_node *np)
 {
@@ -48,6 +51,13 @@ static inline struct regmap *syscon_regmap_lookup_by_phandle(
 {
 	return ERR_PTR(-ENOTSUPP);
 }
+
+static inline int syscon_regmap_read_from_offset(struct device_node *np,
+						 const char *s,
+						 unsigned int *val)
+{
+	return ERR_PTR(-ENOSYS);
+}
 #endif
 
 #endif /* __LINUX_MFD_SYSCON_H__ */
-- 
2.8.2



From maitysanchayan at gmail.com  Mon May  2 00:05:01 2016
From: maitysanchayan at gmail.com (Sanchayan Maity)
Date: Mon,  2 May 2016 12:35:01 +0530
Subject: [PATCH v2 2/5] ARM: dts: vfxxx: Add device tree node for OCOTP
In-Reply-To: <cover.1462171989.git.maitysanchayan@gmail.com>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
Message-ID: <b5c1ff5a805eae3e53f07f8d0161f0af51586c00.1462171990.git.maitysanchayan@gmail.com>

Add device tree node for the OCOTP peripheral on Vybrid.

Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
---
 arch/arm/boot/dts/vfxxx.dtsi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
index 2c13ec6..0e34d44 100644
--- a/arch/arm/boot/dts/vfxxx.dtsi
+++ b/arch/arm/boot/dts/vfxxx.dtsi
@@ -520,6 +520,22 @@
 				status = "disabled";
 			};
 
+			ocotp at 400a5000 {
+				compatible = "fsl,vf610-ocotp";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x400a5000 0xCF0>;
+				clocks = <&clks VF610_CLK_OCOTP>;
+
+				ocotp_cfg0: cfg0 at 410 {
+					reg = <0x410 0x4>;
+				};
+
+				ocotp_cfg1: cfg1 at 420 {
+					reg = <0x420 0x4>;
+				};
+			};
+
 			snvs0: snvs at 400a7000 {
 			    compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
 				reg = <0x400a7000 0x2000>;
-- 
2.8.2



From maitysanchayan at gmail.com  Mon May  2 00:05:03 2016
From: maitysanchayan at gmail.com (Sanchayan Maity)
Date: Mon,  2 May 2016 12:35:03 +0530
Subject: [PATCH v2 4/5] soc: Add SoC bus driver for Freescale Vybrid Platform
In-Reply-To: <cover.1462171989.git.maitysanchayan@gmail.com>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
Message-ID: <fb62813ff0931532431c72a4a4b15c9bda4454fb.1462171990.git.maitysanchayan@gmail.com>

This adds a SoC driver to be used by Freescale Vybrid SoC's.
Driver utilises syscon and nvmem consumer API's to get the
various register values needed and sysfs exposes the SoC specific
properties.

A sample output from Colibri Vybrid VF61 is below:

root at colibri-vf:~# cd /sys/bus/soc/devices/soc0
root at colibri-vf:/sys/bus/soc/devices/soc0# ls
family     machine    power      revision   soc_id     subsystem  uevent
root at colibri-vf:/sys/bus/soc/devices/soc0# cat family
Freescale Vybrid VF610
root at colibri-vf:/sys/bus/soc/devices/soc0# cat machine
Freescale Vybrid
root at colibri-vf:/sys/bus/soc/devices/soc0# cat revision
00000013
root at colibri-vf:/sys/bus/soc/devices/soc0# cat soc_id
df6472a6130f29d4

Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
---
 drivers/soc/Kconfig         |   1 +
 drivers/soc/fsl/Kconfig     |  10 +++
 drivers/soc/fsl/Makefile    |   1 +
 drivers/soc/fsl/soc-vf610.c | 160 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+)
 create mode 100644 drivers/soc/fsl/Kconfig
 create mode 100644 drivers/soc/fsl/soc-vf610.c

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cb58ef0..4410eb7 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -2,6 +2,7 @@ menu "SOC (System On Chip) specific Drivers"
 
 source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/brcmstb/Kconfig"
+source "drivers/soc/fsl/Kconfig"
 source "drivers/soc/fsl/qe/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
new file mode 100644
index 0000000..029ea17
--- /dev/null
+++ b/drivers/soc/fsl/Kconfig
@@ -0,0 +1,10 @@
+#
+# Freescale SoC drivers
+
+config SOC_BUS_VF610
+	bool "SoC bus device for the Freescale Vybrid platform"
+	depends on NVMEM && NVMEM_VF610_OCOTP
+	select SOC_BUS
+	help
+	 Include support for the SoC bus on the Freescale Vybrid platform
+	 providing sysfs information about the module variant.
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index 203307f..afaf092 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -2,5 +2,6 @@
 # Makefile for the Linux Kernel SOC fsl specific device drivers
 #
 
+obj-$(CONFIG_SOC_VF610)			+= soc-vf610.o
 obj-$(CONFIG_QUICC_ENGINE)		+= qe/
 obj-$(CONFIG_CPM)			+= qe/
diff --git a/drivers/soc/fsl/soc-vf610.c b/drivers/soc/fsl/soc-vf610.c
new file mode 100644
index 0000000..99bf641
--- /dev/null
+++ b/drivers/soc/fsl/soc-vf610.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2016 Toradex AG.
+ *
+ * Author: Sanchayan Maity <sanchayan.maity at toradex.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+
+struct vf610_soc {
+	struct device *dev;
+	struct soc_device_attribute *soc_dev_attr;
+	struct soc_device *soc_dev;
+	struct nvmem_cell *ocotp_cfg0;
+	struct nvmem_cell *ocotp_cfg1;
+};
+
+static int vf610_soc_probe(struct platform_device *pdev)
+{
+	struct vf610_soc *info;
+	struct device *dev = &pdev->dev;
+	struct device_node *soc_node;
+	char soc_type[] = "xx0";
+	size_t id1_len;
+	size_t id2_len;
+	u32 cpucount;
+	u32 l2size;
+	u32 rom_rev;
+	u8 *socid1;
+	u8 *socid2;
+	int ret;
+
+	info = devm_kzalloc(dev, sizeof(struct vf610_soc), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+	info->dev = dev;
+
+	info->ocotp_cfg0 = devm_nvmem_cell_get(dev, "cfg0");
+	if (IS_ERR(info->ocotp_cfg0))
+		return -EPROBE_DEFER;
+
+	info->ocotp_cfg1 = devm_nvmem_cell_get(dev, "cfg1");
+	if (IS_ERR(info->ocotp_cfg1))
+		return -EPROBE_DEFER;
+
+	socid1 = nvmem_cell_read(info->ocotp_cfg0, &id1_len);
+	if (IS_ERR(socid1)) {
+		dev_err(dev, "Could not read nvmem cell %ld\n",
+			PTR_ERR(socid1));
+		return PTR_ERR(socid1);
+	}
+
+	socid2 = nvmem_cell_read(info->ocotp_cfg1, &id2_len);
+	if (IS_ERR(socid2)) {
+		dev_err(dev, "Could not read nvmem cell %ld\n",
+			PTR_ERR(socid2));
+		return PTR_ERR(socid2);
+	}
+	add_device_randomness(socid1, id1_len);
+	add_device_randomness(socid2, id2_len);
+
+	soc_node = of_find_node_by_path("/soc");
+	if (soc_node == NULL)
+		return -ENODEV;
+
+	ret = syscon_regmap_read_from_offset(soc_node,
+					"fsl,rom-revision", &rom_rev);
+	if (ret) {
+		of_node_put(soc_node);
+		return ret;
+	}
+
+	ret = syscon_regmap_read_from_offset(soc_node,
+					"fsl,cpu-count", &cpucount);
+	if (ret) {
+		of_node_put(soc_node);
+		return ret;
+	}
+
+	ret = syscon_regmap_read_from_offset(soc_node,
+					"fsl,l2-size", &l2size);
+	if (ret) {
+		of_node_put(soc_node);
+		return ret;
+	}
+
+	of_node_put(soc_node);
+
+	soc_type[0] = cpucount ? '6' : '5'; /* Dual Core => VF6x0 */
+	soc_type[1] = l2size ? '1' : '0'; /* L2 Cache => VFx10 */
+
+	info->soc_dev_attr = devm_kzalloc(dev,
+				sizeof(info->soc_dev_attr), GFP_KERNEL);
+	if (!info->soc_dev_attr)
+		return -ENOMEM;
+
+	info->soc_dev_attr->machine = devm_kasprintf(dev,
+					GFP_KERNEL, "Freescale Vybrid");
+	info->soc_dev_attr->soc_id = devm_kasprintf(dev,
+					GFP_KERNEL,
+					"%02x%02x%02x%02x%02x%02x%02x%02x",
+					socid1[3], socid1[2], socid1[1],
+					socid1[0], socid2[3], socid2[2],
+					socid2[1], socid2[0]);
+	info->soc_dev_attr->family = devm_kasprintf(&pdev->dev,
+					GFP_KERNEL, "Freescale Vybrid VF%s",
+					soc_type);
+	info->soc_dev_attr->revision = devm_kasprintf(dev,
+					GFP_KERNEL, "%08x", rom_rev);
+
+	platform_set_drvdata(pdev, info);
+
+	info->soc_dev = soc_device_register(info->soc_dev_attr);
+	if (IS_ERR(info->soc_dev))
+		return -ENODEV;
+
+	return 0;
+}
+
+static int vf610_soc_remove(struct platform_device *pdev)
+{
+	struct vf610_soc *info = platform_get_drvdata(pdev);
+
+	if (info->soc_dev)
+		soc_device_unregister(info->soc_dev);
+
+	return 0;
+}
+
+static const struct of_device_id vf610_soc_bus_match[] = {
+	{ .compatible = "fsl,vf610-soc-bus", },
+	{ /* */ }
+};
+
+static struct platform_driver vf610_soc_driver = {
+	.probe		= vf610_soc_probe,
+	.remove		= vf610_soc_remove,
+	.driver		= {
+		.name = "vf610-soc-bus",
+		.of_match_table = vf610_soc_bus_match,
+	},
+};
+builtin_platform_driver(vf610_soc_driver);
-- 
2.8.2



From maitysanchayan at gmail.com  Mon May  2 00:05:02 2016
From: maitysanchayan at gmail.com (Sanchayan Maity)
Date: Mon,  2 May 2016 12:35:02 +0530
Subject: [PATCH v2 3/5] ARM: dts: vfxxx: Add OCROM and phandle entries for
 Vybrid SoC bus driver
In-Reply-To: <cover.1462171989.git.maitysanchayan@gmail.com>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
Message-ID: <dc3203a3aa6f081410c8e627de6dc85afbba9e79.1462171990.git.maitysanchayan@gmail.com>

Add OCROM node and introduce phandles to OCROM, MSCM and NVMEM
OCOTP for use by the Vybrid SoC bus driver.

Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
---
 arch/arm/boot/dts/vfxxx.dtsi | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
index 0e34d44..e58f4c6 100644
--- a/arch/arm/boot/dts/vfxxx.dtsi
+++ b/arch/arm/boot/dts/vfxxx.dtsi
@@ -87,9 +87,19 @@
 	soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "simple-bus";
+		compatible = "fsl,vf610-soc-bus", "simple-bus";
 		interrupt-parent = <&mscm_ir>;
 		ranges;
+		fsl,rom-revision = <&ocrom 0x80>;
+		fsl,cpu-count = <&mscm_cpucfg 0x2C>;
+		fsl,l2-size = <&mscm_cpucfg 0x14>;
+		nvmem-cells = <&ocotp_cfg0>, <&ocotp_cfg1>;
+		nvmem-cell-names = "cfg0", "cfg1";
+
+		ocrom: ocrom at 00000000 {
+			compatible = "fsl,vf610-ocrom", "syscon";
+			reg = <0x00000000 0x18000>;
+		};
 
 		aips0: aips-bus at 40000000 {
 			compatible = "fsl,aips-bus", "simple-bus";
-- 
2.8.2



From maitysanchayan at gmail.com  Mon May  2 00:05:04 2016
From: maitysanchayan at gmail.com (Sanchayan Maity)
Date: Mon,  2 May 2016 12:35:04 +0530
Subject: [PATCH v2 5/5] vf610-soc: Add Vybrid SoC device tree binding
 documentation
In-Reply-To: <cover.1462171989.git.maitysanchayan@gmail.com>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
Message-ID: <65f3a7bd7a9faf1b390644d7c599c69683c753c4.1462171990.git.maitysanchayan@gmail.com>

Add device tree binding documentation for Vybrid SoC.

Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
---
 .../bindings/arm/freescale/fsl,vf610-soc.txt       | 35 ++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt

diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
new file mode 100644
index 0000000..bdd95e8
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
@@ -0,0 +1,35 @@
+Vybrid System-on-Chip
+---------------------
+
+Required properties:
+
+- #address-cells: must be 1
+- #size-cells: must be 1
+- compatible: "fsl,vf610-soc-bus", "simple-bus"
+- interrupt-parent: phandle to the MSCM interrupt router node
+- ranges
+- fsl,rom-revision: phandle to the on-chip ROM node and address of rom
+  revision register
+- fsl,cpu-count: phandle to the MSCM CPU configuration node and address of
+  CPU count register
+- fsl,l2-size: phandle to the MSCM CPU configuration node and address of
+  L2 cache size register
+- nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
+- nvmem-cell-names: should contain string names "cfg0" and "cfg1"
+
+Example:
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,vf610-soc-bus", "simple-bus";
+		interrupt-parent = <&mscm_ir>;
+		ranges;
+		fsl,rom-revision = <&ocrom 0x80>;
+		fsl,cpu-count = <&mscm_cpucfg 0x2C>;
+		fsl,l2-size = <&mscm_cpucfg 0x14>;
+		nvmem-cells = <&ocotp_cfg0>, <&ocotp_cfg1>;
+		nvmem-cell-names = "cfg0", "cfg1";
+
+		...
+	};
-- 
2.8.2



From arnd at arndb.de  Mon May  2 00:28:34 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 02 May 2016 09:28:34 +0200
Subject: [PATCH v6] spi: orion.c: Add direct access mode
In-Reply-To: <5726F7F3.9070700@denx.de>
References: <1461147068-4829-1-git-send-email-sr@denx.de>
 <5726F7F3.9070700@denx.de>
Message-ID: <8919835.yGyvx4h0Tr@wuerfel>

On Monday 02 May 2016 08:47:15 Stefan Roese wrote:
> On 20.04.2016 12:11, Stefan Roese wrote:
> > This patch adds support for the direct write mode to the Orion SPI
> > driver which is used on the Marvell Armada based SoCs. In this direct
> > mode, all data written to (or read from) a specifically mapped MBus
> > window (linked to one SPI chip-select on one of the SPI controllers)
> > will be transferred directly to the SPI bus. Without the need to control
> > the SPI registers in between. This can improve the SPI transfer rate in
> > such cases.
> > 
> > Currently only the direct write mode is supported. This mode especially
> > benefits from the SPI direct mode, as the data bytes are written
> > head-to-head to the SPI bus, without any additional addresses, that
> > are also written in the direct read mode.
> > 
> > One use-case for this direct write mode is, programming a FPGA bitstream
> > image into the FPGA connected to the SPI bus at maximum speed.
> > 
> > This mode is described in chapter "22.5.2 Direct Write to SPI" in the
> > Marvell Armada XP Functional Spec Datasheet.
> > 
> > It should be possible to support SPI-NOR and SPI-NAND devices via
> > this direct access mode as well. But this needs further work, e.g.:
> > - The mapping of the MBus window needs to get extended to span
> >    the complete flash device size
> > - The address / control data needs to get inserted into the SPI
> >    controller registers
> > 
> > Signed-off-by: Stefan Roese <sr at denx.de>
> > Cc: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
> > Cc: Gregory CLEMENT <gregory.clement at free-electrons.com>
> > Cc: Andrew Lunn <andrew at lunn.ch>
> > Cc: Arnd Bergmann <arnd at arndb.de>
> > Cc: Mark Brown <broonie at kernel.org>
> 
> Its been a while since v6 of this direct write access mode has been
> posted. This is a gentle ping on its status.
> 
> Arnd / Mark, do you have any additional change requests or are you okay
> with the current version?

No objections, please add

Acked-by: Arnd Bergmann <arnd at arndb.de>

Two questions though:

- you now always send a multiple of four byte in each transfer, are
  there any downsides in doing this, e.g. some SPI devices that might
  get confused by receiving additional uninitialized data?

- How does the performance compare to the normal mode, is it basically
  unchanged, or does this patch make things faster?

	Arnd


From arnd at arndb.de  Mon May  2 00:31:12 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 02 May 2016 09:31:12 +0200
Subject: [PATCH v2 2/5] ARM: dts: vfxxx: Add device tree node for OCOTP
In-Reply-To: <b5c1ff5a805eae3e53f07f8d0161f0af51586c00.1462171990.git.maitysanchayan@gmail.com>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
 <b5c1ff5a805eae3e53f07f8d0161f0af51586c00.1462171990.git.maitysanchayan@gmail.com>
Message-ID: <4759698.elnRBldlxl@wuerfel>

On Monday 02 May 2016 12:35:01 Sanchayan Maity wrote:
> +                       ocotp at 400a5000 {
> +                               compatible = "fsl,vf610-ocotp";
> +                               #address-cells = <1>;
> +                               #size-cells = <1>;
> +                               reg = <0x400a5000 0xCF0>;
> +                               clocks = <&clks VF610_CLK_OCOTP>;
> +
> +                               ocotp_cfg0: cfg0 at 410 {
> +                                       reg = <0x410 0x4>;
> +                               };
> +
> +                               ocotp_cfg1: cfg1 at 420 {
> +                                       reg = <0x420 0x4>;
> +                               };
> +                       };

How do the registers of the child nodes relate to the registers of the
parent? If there are in the same address space, it might be good to
add a "ranges" property to describe it.

	Arnd
-------------- next part --------------
An embedded message was scrubbed...
From: Gavin Shan <gwshan at linux.vnet.ibm.com>
Subject: Re: [PATCH v8 40/45] drivers/of: Split unflatten_dt_node()
Date: Mon, 02 May 2016 12:02:21 +1000
Size: 8869
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/8b012f87/attachment-0001.mht>

From wsa at the-dreams.de  Mon May  2 00:32:54 2016
From: wsa at the-dreams.de (Wolfram Sang)
Date: Mon, 2 May 2016 09:32:54 +0200
Subject: [PATCH 02/12] eeprom: at24: remove nvmem regmap dependency
In-Reply-To: <1461526096-29584-3-git-send-email-srinivas.kandagatla@linaro.org>
References: <1461526096-29584-1-git-send-email-srinivas.kandagatla@linaro.org>
 <1461526096-29584-3-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <20160502073254.GA2015@tetsubishi>

On Sun, Apr 24, 2016 at 08:28:06PM +0100, Srinivas Kandagatla wrote:
> This patch moves to nvmem support in the driver to use callback instead
> of regmap.
> 
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>

Andrew, since you did the NVMEM implementation, could you have a look at
this? That would be awesome. Thanks!

> ---
>  drivers/misc/eeprom/Kconfig |   1 -
>  drivers/misc/eeprom/at24.c  | 103 ++++++++++----------------------------------
>  2 files changed, 22 insertions(+), 82 deletions(-)
> 
> diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
> index cfc493c..2d70464 100644
> --- a/drivers/misc/eeprom/Kconfig
> +++ b/drivers/misc/eeprom/Kconfig
> @@ -3,7 +3,6 @@ menu "EEPROM support"
>  config EEPROM_AT24
>  	tristate "I2C EEPROMs / RAMs / ROMs from most vendors"
>  	depends on I2C && SYSFS
> -	select REGMAP
>  	select NVMEM
>  	help
>  	  Enable this driver to get read/write support to most I2C EEPROMs
> diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
> index 089d694..de550a6 100644
> --- a/drivers/misc/eeprom/at24.c
> +++ b/drivers/misc/eeprom/at24.c
> @@ -23,7 +23,6 @@
>  #include <linux/acpi.h>
>  #include <linux/i2c.h>
>  #include <linux/nvmem-provider.h>
> -#include <linux/regmap.h>
>  #include <linux/platform_data/at24.h>
>  
>  /*
> @@ -69,7 +68,6 @@ struct at24_data {
>  	unsigned write_max;
>  	unsigned num_addresses;
>  
> -	struct regmap_config regmap_config;
>  	struct nvmem_config nvmem_config;
>  	struct nvmem_device *nvmem;
>  
> @@ -252,10 +250,10 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
>  	return -ETIMEDOUT;
>  }
>  
> -static ssize_t at24_read(struct at24_data *at24,
> -		char *buf, loff_t off, size_t count)
> +static int at24_read(void *priv, unsigned int off, void *val, size_t count)
>  {
> -	ssize_t retval = 0;
> +	struct at24_data *at24 = priv;
> +	char *buf = val;
>  
>  	if (unlikely(!count))
>  		return count;
> @@ -267,23 +265,21 @@ static ssize_t at24_read(struct at24_data *at24,
>  	mutex_lock(&at24->lock);
>  
>  	while (count) {
> -		ssize_t	status;
> +		int	status;
>  
>  		status = at24_eeprom_read(at24, buf, off, count);
> -		if (status <= 0) {
> -			if (retval == 0)
> -				retval = status;
> -			break;
> +		if (status < 0) {
> +			mutex_unlock(&at24->lock);
> +			return status;
>  		}
>  		buf += status;
>  		off += status;
>  		count -= status;
> -		retval += status;
>  	}
>  
>  	mutex_unlock(&at24->lock);
>  
> -	return retval;
> +	return 0;
>  }
>  
>  /*
> @@ -372,13 +368,13 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf,
>  	return -ETIMEDOUT;
>  }
>  
> -static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
> -			  size_t count)
> +static int at24_write(void *priv, unsigned int off, void *val, size_t count)
>  {
> -	ssize_t retval = 0;
> +	struct at24_data *at24 = priv;
> +	char *buf = val;
>  
>  	if (unlikely(!count))
> -		return count;
> +		return -EINVAL;
>  
>  	/*
>  	 * Write data to chip, protecting against concurrent updates
> @@ -387,70 +383,23 @@ static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
>  	mutex_lock(&at24->lock);
>  
>  	while (count) {
> -		ssize_t	status;
> +		int status;
>  
>  		status = at24_eeprom_write(at24, buf, off, count);
> -		if (status <= 0) {
> -			if (retval == 0)
> -				retval = status;
> -			break;
> +		if (status < 0) {
> +			mutex_unlock(&at24->lock);
> +			return status;
>  		}
>  		buf += status;
>  		off += status;
>  		count -= status;
> -		retval += status;
>  	}
>  
>  	mutex_unlock(&at24->lock);
>  
> -	return retval;
> -}
> -
> -/*-------------------------------------------------------------------------*/
> -
> -/*
> - * Provide a regmap interface, which is registered with the NVMEM
> - * framework
> -*/
> -static int at24_regmap_read(void *context, const void *reg, size_t reg_size,
> -			    void *val, size_t val_size)
> -{
> -	struct at24_data *at24 = context;
> -	off_t offset = *(u32 *)reg;
> -	int err;
> -
> -	err = at24_read(at24, val, offset, val_size);
> -	if (err)
> -		return err;
> -	return 0;
> -}
> -
> -static int at24_regmap_write(void *context, const void *data, size_t count)
> -{
> -	struct at24_data *at24 = context;
> -	const char *buf;
> -	u32 offset;
> -	size_t len;
> -	int err;
> -
> -	memcpy(&offset, data, sizeof(offset));
> -	buf = (const char *)data + sizeof(offset);
> -	len = count - sizeof(offset);
> -
> -	err = at24_write(at24, buf, offset, len);
> -	if (err)
> -		return err;
>  	return 0;
>  }
>  
> -static const struct regmap_bus at24_regmap_bus = {
> -	.read = at24_regmap_read,
> -	.write = at24_regmap_write,
> -	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
> -};
> -
> -/*-------------------------------------------------------------------------*/
> -
>  #ifdef CONFIG_OF
>  static void at24_get_ofdata(struct i2c_client *client,
>  		struct at24_platform_data *chip)
> @@ -482,7 +431,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	struct at24_data *at24;
>  	int err;
>  	unsigned i, num_addresses;
> -	struct regmap *regmap;
>  
>  	if (client->dev.platform_data) {
>  		chip = *(struct at24_platform_data *)client->dev.platform_data;
> @@ -612,19 +560,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  		}
>  	}
>  
> -	at24->regmap_config.reg_bits = 32;
> -	at24->regmap_config.val_bits = 8;
> -	at24->regmap_config.reg_stride = 1;
> -	at24->regmap_config.max_register = chip.byte_len - 1;
> -
> -	regmap = devm_regmap_init(&client->dev, &at24_regmap_bus, at24,
> -				  &at24->regmap_config);
> -	if (IS_ERR(regmap)) {
> -		dev_err(&client->dev, "regmap init failed\n");
> -		err = PTR_ERR(regmap);
> -		goto err_clients;
> -	}
> -
>  	at24->nvmem_config.name = dev_name(&client->dev);
>  	at24->nvmem_config.dev = &client->dev;
>  	at24->nvmem_config.read_only = !writable;
> @@ -632,6 +567,12 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	at24->nvmem_config.owner = THIS_MODULE;
>  	at24->nvmem_config.compat = true;
>  	at24->nvmem_config.base_dev = &client->dev;
> +	at24->nvmem_config.reg_read = at24_read;
> +	at24->nvmem_config.reg_write = at24_write;
> +	at24->nvmem_config.priv = at24;
> +	at24->nvmem_config.stride = 4;
> +	at24->nvmem_config.word_size = 1;
> +	at24->nvmem_config.size = chip.byte_len;
>  
>  	at24->nvmem = nvmem_register(&at24->nvmem_config);
>  
> -- 
> 2.5.0
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/d9123fc5/attachment.sig>

From panand at redhat.com  Mon May  2 00:34:28 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 2 May 2016 13:04:28 +0530
Subject: [PATCH 06/12] ARM: kexec: advertise location of bootable RAM
In-Reply-To: <20160430082055.GG19428@n2100.arm.linux.org.uk>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <E1aviF4-0000jG-MO@rmk-PC.arm.linux.org.uk>
 <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <20160429180024.GS19428@n2100.arm.linux.org.uk>
 <CAHB_GuqhPJ7J-MNbjxqeQnogW-J6=Bt2e1STKSG5kzJT+4PJpg@mail.gmail.com>
 <20160430082055.GG19428@n2100.arm.linux.org.uk>
Message-ID: <CAHB_Guq+w7JKXEpLHkefMaYuYowh7dqsdvxgG_dnGv-GdkX39A@mail.gmail.com>

On Sat, Apr 30, 2016 at 1:50 PM, Russell King - ARM Linux
<linux at arm.linux.org.uk> wrote:
> On Sat, Apr 30, 2016 at 08:57:34AM +0530, Pratyush Anand wrote:
>> On Fri, Apr 29, 2016 at 11:30 PM, Russell King - ARM Linux
>> <linux at arm.linux.org.uk> wrote:
>> > On Fri, Apr 29, 2016 at 08:26:00PM +0530, Pratyush Anand wrote:
>> >> Hi Russell,
>> >>
>> >> On Thu, Apr 28, 2016 at 2:58 PM, Russell King
>> >> <rmk+kernel at arm.linux.org.uk> wrote:
>> >> > Advertise the location of bootable RAM to kexec-tools.  kexec needs to
>> >> > know where it can place the kernel in RAM, and so be executable when
>> >> > the system needs to jump into it.
>> >> >
>> >> > Advertise these areas in /proc/iomem with a "System RAM (boot alias)"
>> >> > tag.
>> >> >
>> >> > Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
>> >>
>> >> Can you please also share git tree path of corresponding kexec-tools changes?
>> >>
>> >> Could it be a better idea (if things in user space become simpler)
>> >> that in stead of patch 5 and 6, we pass arch_phys_to_idmap_offset to
>> >> user space, and then user space manipulates existing "Crash kernel"
>> >> and "System RAM" resources.
>> >
>> > Given that it's only _one_ platform right now, I don't think that
>> > additional complexity is worth it.  It means that we have to invent
>>
>> Probably, I could not communicate it well.  I was not trying  to have
>> *additional* complexity. Wanted to see if things could be simpler
>> rather. So this is what my understanding was:
>> -- We create one patch to pass arch_phys_to_idmap_offset to user space
>> (say in /sys/kernel/bootmem_idmap_offset)
>> -- We do not use patch 5,6,11 and 12 of this series. Probably few more
>> content of the series will go away.
>
> Patches 11 and 12 don't go away with what you're suggesting.  Patches
> 11 and 12 are necessary to allow the boot-view addresses to be passed
> into the kernel through kexec, and to allow kexec to find appropriate
> memory resources.

But once we would have manipulated "start" and "end" of "Crash Kernel"
and "System RAM" resources in user space using
/sys/kernel/bootmem_idmap_offset , then kernel through kexec system
call would have already receive boot-view addresses, no?

~Pratyush


From carlo at caione.org  Mon May  2 01:02:14 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon,  2 May 2016 10:02:14 +0200
Subject: [PATCH v2 0/4] Amlogic: GXBB: Add pin controller
Message-ID: <1462176138-29433-1-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Patchset to add and enable the pin controller driver on a couple of Amlogic
boards with a Meson GXBB SoC.

Please note that:
* This patch depends on http://www.spinics.net/lists/devicetree/msg120964.html
  ([PATCH] ARM64: dts: amlogic: Add hiu and periphs buses).

* The platform driver is still missing a lot of muxing configurations. This is
  because Amlogic still hasn't publicly released documentation for the GXBB.
  Since Kevin has already this documentation under NDA, he will integrate and
  complete this driver with a separate submission.

Changelog:
* v2:
  - Split patchset in 4 different patches

Carlo Caione (4):
  pinctrl: amlogic: Add support for Amlogic Meson GXBB SoC
  documentation: Add compatibles for Amlogic Meson GXBB pin controllers
  ARM64: Kconfig: Select the Amlogic Meson pin controller driver
  ARM64: dts: amlogic: Enable pin controller on GXBB-based platforms

 .../devicetree/bindings/pinctrl/meson,pinctrl.txt  |   2 +
 arch/arm64/Kconfig.platforms                       |   2 +
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts |  13 +
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |   2 +
 .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      |   3 +
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  41 ++
 drivers/pinctrl/meson/Makefile                     |   2 +-
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c         | 432 +++++++++++++++++++++
 drivers/pinctrl/meson/pinctrl-meson.c              |   8 +
 drivers/pinctrl/meson/pinctrl-meson.h              |   2 +
 include/dt-bindings/gpio/meson-gxbb-gpio.h         | 154 ++++++++
 11 files changed, 660 insertions(+), 1 deletion(-)
 create mode 100644 drivers/pinctrl/meson/pinctrl-meson-gxbb.c
 create mode 100644 include/dt-bindings/gpio/meson-gxbb-gpio.h

-- 
2.7.4



From carlo at caione.org  Mon May  2 01:02:15 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon,  2 May 2016 10:02:15 +0200
Subject: [PATCH v2 1/4] pinctrl: amlogic: Add support for Amlogic Meson GXBB
 SoC
In-Reply-To: <1462176138-29433-1-git-send-email-carlo@caione.org>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
Message-ID: <1462176138-29433-2-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

This patch adds the basic platform file to support the pin controller
found on the Amlogic Meson GXBB SoCs.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 drivers/pinctrl/meson/Makefile             |   2 +-
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 432 +++++++++++++++++++++++++++++
 drivers/pinctrl/meson/pinctrl-meson.c      |   8 +
 drivers/pinctrl/meson/pinctrl-meson.h      |   2 +
 include/dt-bindings/gpio/meson-gxbb-gpio.h | 154 ++++++++++
 5 files changed, 597 insertions(+), 1 deletion(-)
 create mode 100644 drivers/pinctrl/meson/pinctrl-meson-gxbb.c
 create mode 100644 include/dt-bindings/gpio/meson-gxbb-gpio.h

diff --git a/drivers/pinctrl/meson/Makefile b/drivers/pinctrl/meson/Makefile
index c751d22..24434f1 100644
--- a/drivers/pinctrl/meson/Makefile
+++ b/drivers/pinctrl/meson/Makefile
@@ -1,2 +1,2 @@
-obj-y	+= pinctrl-meson8.o pinctrl-meson8b.o
+obj-y	+= pinctrl-meson8.o pinctrl-meson8b.o pinctrl-meson-gxbb.o
 obj-y	+= pinctrl-meson.o
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
new file mode 100644
index 0000000..eeabafb
--- /dev/null
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -0,0 +1,432 @@
+/*
+ * Pin controller and GPIO driver for Amlogic Meson GXBB.
+ *
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <dt-bindings/gpio/meson-gxbb-gpio.h>
+#include "pinctrl-meson.h"
+
+#define EE_OFF	14
+
+static const struct pinctrl_pin_desc meson_gxbb_periphs_pins[] = {
+	MESON_PIN(GPIOZ_0, EE_OFF),
+	MESON_PIN(GPIOZ_1, EE_OFF),
+	MESON_PIN(GPIOZ_2, EE_OFF),
+	MESON_PIN(GPIOZ_3, EE_OFF),
+	MESON_PIN(GPIOZ_4, EE_OFF),
+	MESON_PIN(GPIOZ_5, EE_OFF),
+	MESON_PIN(GPIOZ_6, EE_OFF),
+	MESON_PIN(GPIOZ_7, EE_OFF),
+	MESON_PIN(GPIOZ_8, EE_OFF),
+	MESON_PIN(GPIOZ_9, EE_OFF),
+	MESON_PIN(GPIOZ_10, EE_OFF),
+	MESON_PIN(GPIOZ_11, EE_OFF),
+	MESON_PIN(GPIOZ_12, EE_OFF),
+	MESON_PIN(GPIOZ_13, EE_OFF),
+	MESON_PIN(GPIOZ_14, EE_OFF),
+	MESON_PIN(GPIOZ_15, EE_OFF),
+
+	MESON_PIN(GPIOH_0, EE_OFF),
+	MESON_PIN(GPIOH_1, EE_OFF),
+	MESON_PIN(GPIOH_2, EE_OFF),
+	MESON_PIN(GPIOH_3, EE_OFF),
+
+	MESON_PIN(BOOT_0, EE_OFF),
+	MESON_PIN(BOOT_1, EE_OFF),
+	MESON_PIN(BOOT_2, EE_OFF),
+	MESON_PIN(BOOT_3, EE_OFF),
+	MESON_PIN(BOOT_4, EE_OFF),
+	MESON_PIN(BOOT_5, EE_OFF),
+	MESON_PIN(BOOT_6, EE_OFF),
+	MESON_PIN(BOOT_7, EE_OFF),
+	MESON_PIN(BOOT_8, EE_OFF),
+	MESON_PIN(BOOT_9, EE_OFF),
+	MESON_PIN(BOOT_10, EE_OFF),
+	MESON_PIN(BOOT_11, EE_OFF),
+	MESON_PIN(BOOT_12, EE_OFF),
+	MESON_PIN(BOOT_13, EE_OFF),
+	MESON_PIN(BOOT_14, EE_OFF),
+	MESON_PIN(BOOT_15, EE_OFF),
+	MESON_PIN(BOOT_16, EE_OFF),
+	MESON_PIN(BOOT_17, EE_OFF),
+
+	MESON_PIN(CARD_0, EE_OFF),
+	MESON_PIN(CARD_1, EE_OFF),
+	MESON_PIN(CARD_2, EE_OFF),
+	MESON_PIN(CARD_3, EE_OFF),
+	MESON_PIN(CARD_4, EE_OFF),
+	MESON_PIN(CARD_5, EE_OFF),
+	MESON_PIN(CARD_6, EE_OFF),
+
+	MESON_PIN(GPIODV_0, EE_OFF),
+	MESON_PIN(GPIODV_1, EE_OFF),
+	MESON_PIN(GPIODV_2, EE_OFF),
+	MESON_PIN(GPIODV_3, EE_OFF),
+	MESON_PIN(GPIODV_4, EE_OFF),
+	MESON_PIN(GPIODV_5, EE_OFF),
+	MESON_PIN(GPIODV_6, EE_OFF),
+	MESON_PIN(GPIODV_7, EE_OFF),
+	MESON_PIN(GPIODV_8, EE_OFF),
+	MESON_PIN(GPIODV_9, EE_OFF),
+	MESON_PIN(GPIODV_10, EE_OFF),
+	MESON_PIN(GPIODV_11, EE_OFF),
+	MESON_PIN(GPIODV_12, EE_OFF),
+	MESON_PIN(GPIODV_13, EE_OFF),
+	MESON_PIN(GPIODV_14, EE_OFF),
+	MESON_PIN(GPIODV_15, EE_OFF),
+	MESON_PIN(GPIODV_16, EE_OFF),
+	MESON_PIN(GPIODV_17, EE_OFF),
+	MESON_PIN(GPIODV_19, EE_OFF),
+	MESON_PIN(GPIODV_20, EE_OFF),
+	MESON_PIN(GPIODV_21, EE_OFF),
+	MESON_PIN(GPIODV_22, EE_OFF),
+	MESON_PIN(GPIODV_23, EE_OFF),
+	MESON_PIN(GPIODV_24, EE_OFF),
+	MESON_PIN(GPIODV_25, EE_OFF),
+	MESON_PIN(GPIODV_26, EE_OFF),
+	MESON_PIN(GPIODV_27, EE_OFF),
+	MESON_PIN(GPIODV_28, EE_OFF),
+	MESON_PIN(GPIODV_29, EE_OFF),
+
+	MESON_PIN(GPIOY_0, EE_OFF),
+	MESON_PIN(GPIOY_1, EE_OFF),
+	MESON_PIN(GPIOY_2, EE_OFF),
+	MESON_PIN(GPIOY_3, EE_OFF),
+	MESON_PIN(GPIOY_4, EE_OFF),
+	MESON_PIN(GPIOY_5, EE_OFF),
+	MESON_PIN(GPIOY_6, EE_OFF),
+	MESON_PIN(GPIOY_7, EE_OFF),
+	MESON_PIN(GPIOY_8, EE_OFF),
+	MESON_PIN(GPIOY_9, EE_OFF),
+	MESON_PIN(GPIOY_10, EE_OFF),
+	MESON_PIN(GPIOY_11, EE_OFF),
+	MESON_PIN(GPIOY_12, EE_OFF),
+	MESON_PIN(GPIOY_13, EE_OFF),
+	MESON_PIN(GPIOY_14, EE_OFF),
+	MESON_PIN(GPIOY_15, EE_OFF),
+	MESON_PIN(GPIOY_16, EE_OFF),
+
+	MESON_PIN(GPIOX_0, EE_OFF),
+	MESON_PIN(GPIOX_1, EE_OFF),
+	MESON_PIN(GPIOX_2, EE_OFF),
+	MESON_PIN(GPIOX_3, EE_OFF),
+	MESON_PIN(GPIOX_4, EE_OFF),
+	MESON_PIN(GPIOX_5, EE_OFF),
+	MESON_PIN(GPIOX_6, EE_OFF),
+	MESON_PIN(GPIOX_7, EE_OFF),
+	MESON_PIN(GPIOX_8, EE_OFF),
+	MESON_PIN(GPIOX_9, EE_OFF),
+	MESON_PIN(GPIOX_10, EE_OFF),
+	MESON_PIN(GPIOX_11, EE_OFF),
+	MESON_PIN(GPIOX_12, EE_OFF),
+	MESON_PIN(GPIOX_13, EE_OFF),
+	MESON_PIN(GPIOX_14, EE_OFF),
+	MESON_PIN(GPIOX_15, EE_OFF),
+	MESON_PIN(GPIOX_16, EE_OFF),
+	MESON_PIN(GPIOX_17, EE_OFF),
+	MESON_PIN(GPIOX_18, EE_OFF),
+	MESON_PIN(GPIOX_19, EE_OFF),
+	MESON_PIN(GPIOX_20, EE_OFF),
+	MESON_PIN(GPIOX_21, EE_OFF),
+	MESON_PIN(GPIOX_22, EE_OFF),
+
+	MESON_PIN(GPIOCLK_0, EE_OFF),
+	MESON_PIN(GPIOCLK_1, EE_OFF),
+	MESON_PIN(GPIOCLK_2, EE_OFF),
+	MESON_PIN(GPIOCLK_3, EE_OFF),
+
+	MESON_PIN(GPIO_TEST_N, EE_OFF),
+};
+
+static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
+	MESON_PIN(GPIOAO_0, 0),
+	MESON_PIN(GPIOAO_1, 0),
+	MESON_PIN(GPIOAO_2, 0),
+	MESON_PIN(GPIOAO_3, 0),
+	MESON_PIN(GPIOAO_4, 0),
+	MESON_PIN(GPIOAO_5, 0),
+	MESON_PIN(GPIOAO_6, 0),
+	MESON_PIN(GPIOAO_7, 0),
+	MESON_PIN(GPIOAO_8, 0),
+	MESON_PIN(GPIOAO_9, 0),
+	MESON_PIN(GPIOAO_10, 0),
+	MESON_PIN(GPIOAO_11, 0),
+	MESON_PIN(GPIOAO_12, 0),
+	MESON_PIN(GPIOAO_13, 0),
+};
+
+static const unsigned int uart_tx_ao_a_pins[]	= { PIN(GPIOAO_0, 0) };
+static const unsigned int uart_rx_ao_a_pins[]	= { PIN(GPIOAO_1, 0) };
+static const unsigned int uart_cts_ao_a_pins[]	= { PIN(GPIOAO_2, 0) };
+static const unsigned int uart_rts_ao_a_pins[]	= { PIN(GPIOAO_3, 0) };
+
+static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
+	GPIO_GROUP(GPIOZ_0, EE_OFF),
+	GPIO_GROUP(GPIOZ_1, EE_OFF),
+	GPIO_GROUP(GPIOZ_2, EE_OFF),
+	GPIO_GROUP(GPIOZ_3, EE_OFF),
+	GPIO_GROUP(GPIOZ_4, EE_OFF),
+	GPIO_GROUP(GPIOZ_5, EE_OFF),
+	GPIO_GROUP(GPIOZ_6, EE_OFF),
+	GPIO_GROUP(GPIOZ_7, EE_OFF),
+	GPIO_GROUP(GPIOZ_8, EE_OFF),
+	GPIO_GROUP(GPIOZ_9, EE_OFF),
+	GPIO_GROUP(GPIOZ_10, EE_OFF),
+	GPIO_GROUP(GPIOZ_11, EE_OFF),
+	GPIO_GROUP(GPIOZ_12, EE_OFF),
+	GPIO_GROUP(GPIOZ_13, EE_OFF),
+	GPIO_GROUP(GPIOZ_14, EE_OFF),
+	GPIO_GROUP(GPIOZ_15, EE_OFF),
+
+	GPIO_GROUP(GPIOH_0, EE_OFF),
+	GPIO_GROUP(GPIOH_1, EE_OFF),
+	GPIO_GROUP(GPIOH_2, EE_OFF),
+	GPIO_GROUP(GPIOH_3, EE_OFF),
+
+	GPIO_GROUP(BOOT_0, EE_OFF),
+	GPIO_GROUP(BOOT_1, EE_OFF),
+	GPIO_GROUP(BOOT_2, EE_OFF),
+	GPIO_GROUP(BOOT_3, EE_OFF),
+	GPIO_GROUP(BOOT_4, EE_OFF),
+	GPIO_GROUP(BOOT_5, EE_OFF),
+	GPIO_GROUP(BOOT_6, EE_OFF),
+	GPIO_GROUP(BOOT_7, EE_OFF),
+	GPIO_GROUP(BOOT_8, EE_OFF),
+	GPIO_GROUP(BOOT_9, EE_OFF),
+	GPIO_GROUP(BOOT_10, EE_OFF),
+	GPIO_GROUP(BOOT_11, EE_OFF),
+	GPIO_GROUP(BOOT_12, EE_OFF),
+	GPIO_GROUP(BOOT_13, EE_OFF),
+	GPIO_GROUP(BOOT_14, EE_OFF),
+	GPIO_GROUP(BOOT_15, EE_OFF),
+	GPIO_GROUP(BOOT_16, EE_OFF),
+	GPIO_GROUP(BOOT_17, EE_OFF),
+
+	GPIO_GROUP(CARD_0, EE_OFF),
+	GPIO_GROUP(CARD_1, EE_OFF),
+	GPIO_GROUP(CARD_2, EE_OFF),
+	GPIO_GROUP(CARD_3, EE_OFF),
+	GPIO_GROUP(CARD_4, EE_OFF),
+	GPIO_GROUP(CARD_5, EE_OFF),
+	GPIO_GROUP(CARD_6, EE_OFF),
+
+	GPIO_GROUP(GPIODV_0, EE_OFF),
+	GPIO_GROUP(GPIODV_1, EE_OFF),
+	GPIO_GROUP(GPIODV_2, EE_OFF),
+	GPIO_GROUP(GPIODV_3, EE_OFF),
+	GPIO_GROUP(GPIODV_4, EE_OFF),
+	GPIO_GROUP(GPIODV_5, EE_OFF),
+	GPIO_GROUP(GPIODV_6, EE_OFF),
+	GPIO_GROUP(GPIODV_7, EE_OFF),
+	GPIO_GROUP(GPIODV_8, EE_OFF),
+	GPIO_GROUP(GPIODV_9, EE_OFF),
+	GPIO_GROUP(GPIODV_10, EE_OFF),
+	GPIO_GROUP(GPIODV_11, EE_OFF),
+	GPIO_GROUP(GPIODV_12, EE_OFF),
+	GPIO_GROUP(GPIODV_13, EE_OFF),
+	GPIO_GROUP(GPIODV_14, EE_OFF),
+	GPIO_GROUP(GPIODV_15, EE_OFF),
+	GPIO_GROUP(GPIODV_16, EE_OFF),
+	GPIO_GROUP(GPIODV_17, EE_OFF),
+	GPIO_GROUP(GPIODV_19, EE_OFF),
+	GPIO_GROUP(GPIODV_20, EE_OFF),
+	GPIO_GROUP(GPIODV_21, EE_OFF),
+	GPIO_GROUP(GPIODV_22, EE_OFF),
+	GPIO_GROUP(GPIODV_23, EE_OFF),
+	GPIO_GROUP(GPIODV_24, EE_OFF),
+	GPIO_GROUP(GPIODV_25, EE_OFF),
+	GPIO_GROUP(GPIODV_26, EE_OFF),
+	GPIO_GROUP(GPIODV_27, EE_OFF),
+	GPIO_GROUP(GPIODV_28, EE_OFF),
+	GPIO_GROUP(GPIODV_29, EE_OFF),
+
+	GPIO_GROUP(GPIOY_0, EE_OFF),
+	GPIO_GROUP(GPIOY_1, EE_OFF),
+	GPIO_GROUP(GPIOY_2, EE_OFF),
+	GPIO_GROUP(GPIOY_3, EE_OFF),
+	GPIO_GROUP(GPIOY_4, EE_OFF),
+	GPIO_GROUP(GPIOY_5, EE_OFF),
+	GPIO_GROUP(GPIOY_6, EE_OFF),
+	GPIO_GROUP(GPIOY_7, EE_OFF),
+	GPIO_GROUP(GPIOY_8, EE_OFF),
+	GPIO_GROUP(GPIOY_9, EE_OFF),
+	GPIO_GROUP(GPIOY_10, EE_OFF),
+	GPIO_GROUP(GPIOY_11, EE_OFF),
+	GPIO_GROUP(GPIOY_12, EE_OFF),
+	GPIO_GROUP(GPIOY_13, EE_OFF),
+	GPIO_GROUP(GPIOY_14, EE_OFF),
+	GPIO_GROUP(GPIOY_15, EE_OFF),
+	GPIO_GROUP(GPIOY_16, EE_OFF),
+
+	GPIO_GROUP(GPIOX_0, EE_OFF),
+	GPIO_GROUP(GPIOX_1, EE_OFF),
+	GPIO_GROUP(GPIOX_2, EE_OFF),
+	GPIO_GROUP(GPIOX_3, EE_OFF),
+	GPIO_GROUP(GPIOX_4, EE_OFF),
+	GPIO_GROUP(GPIOX_5, EE_OFF),
+	GPIO_GROUP(GPIOX_6, EE_OFF),
+	GPIO_GROUP(GPIOX_7, EE_OFF),
+	GPIO_GROUP(GPIOX_8, EE_OFF),
+	GPIO_GROUP(GPIOX_9, EE_OFF),
+	GPIO_GROUP(GPIOX_10, EE_OFF),
+	GPIO_GROUP(GPIOX_11, EE_OFF),
+	GPIO_GROUP(GPIOX_12, EE_OFF),
+	GPIO_GROUP(GPIOX_13, EE_OFF),
+	GPIO_GROUP(GPIOX_14, EE_OFF),
+	GPIO_GROUP(GPIOX_15, EE_OFF),
+	GPIO_GROUP(GPIOX_16, EE_OFF),
+	GPIO_GROUP(GPIOX_17, EE_OFF),
+	GPIO_GROUP(GPIOX_18, EE_OFF),
+	GPIO_GROUP(GPIOX_19, EE_OFF),
+	GPIO_GROUP(GPIOX_20, EE_OFF),
+	GPIO_GROUP(GPIOX_21, EE_OFF),
+	GPIO_GROUP(GPIOX_22, EE_OFF),
+
+	GPIO_GROUP(GPIOCLK_0, EE_OFF),
+	GPIO_GROUP(GPIOCLK_1, EE_OFF),
+	GPIO_GROUP(GPIOCLK_2, EE_OFF),
+	GPIO_GROUP(GPIOCLK_3, EE_OFF),
+
+	GPIO_GROUP(GPIO_TEST_N, EE_OFF),
+};
+
+static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
+	GPIO_GROUP(GPIOAO_0, 0),
+	GPIO_GROUP(GPIOAO_1, 0),
+	GPIO_GROUP(GPIOAO_2, 0),
+	GPIO_GROUP(GPIOAO_3, 0),
+	GPIO_GROUP(GPIOAO_4, 0),
+	GPIO_GROUP(GPIOAO_5, 0),
+	GPIO_GROUP(GPIOAO_6, 0),
+	GPIO_GROUP(GPIOAO_7, 0),
+	GPIO_GROUP(GPIOAO_8, 0),
+	GPIO_GROUP(GPIOAO_9, 0),
+	GPIO_GROUP(GPIOAO_10, 0),
+	GPIO_GROUP(GPIOAO_11, 0),
+	GPIO_GROUP(GPIOAO_12, 0),
+	GPIO_GROUP(GPIOAO_13, 0),
+
+	/* bank AO */
+	GROUP(uart_tx_ao_a,	0,	12),
+	GROUP(uart_rx_ao_a,	0,	11),
+	GROUP(uart_cts_ao_a,	0,	10),
+	GROUP(uart_rts_ao_a,	0,	9),
+};
+
+static const char * const gpio_periphs_groups[] = {
+	"GPIOZ_0", "GPIOZ_1", "GPIOZ_2", "GPIOZ_3", "GPIOZ_4",
+	"GPIOZ_5", "GPIOZ_6", "GPIOZ_7", "GPIOZ_8", "GPIOZ_9",
+	"GPIOZ_10", "GPIOZ_11", "GPIOZ_12", "GPIOZ_13", "GPIOZ_14",
+	"GPIOZ_15",
+
+	"GPIOH_0", "GPIOH_1", "GPIOH_2", "GPIOH_3",
+
+	"BOOT_0", "BOOT_1", "BOOT_2", "BOOT_3", "BOOT_4",
+	"BOOT_5", "BOOT_6", "BOOT_7", "BOOT_8", "BOOT_9",
+	"BOOT_10", "BOOT_11", "BOOT_12", "BOOT_13", "BOOT_14",
+	"BOOT_15", "BOOT_16", "BOOT_17",
+
+	"CARD_0", "CARD_1", "CARD_2", "CARD_3", "CARD_4",
+	"CARD_5", "CARD_6",
+
+	"GPIODV_0", "GPIODV_1", "GPIODV_2", "GPIODV_3", "GPIODV_4",
+	"GPIODV_5", "GPIODV_6", "GPIODV_7", "GPIODV_8", "GPIODV_9",
+	"GPIODV_10", "GPIODV_11", "GPIODV_12", "GPIODV_13", "GPIODV_14",
+	"GPIODV_15", "GPIODV_16", "GPIODV_17", "GPIODV_18", "GPIODV_19",
+	"GPIODV_20", "GPIODV_21", "GPIODV_22", "GPIODV_23", "GPIODV_24",
+	"GPIODV_25", "GPIODV_26", "GPIODV_27", "GPIODV_28", "GPIODV_29",
+
+	"GPIOY_0", "GPIOY_1", "GPIOY_2", "GPIOY_3", "GPIOY_4",
+	"GPIOY_5", "GPIOY_6", "GPIOY_7", "GPIOY_8", "GPIOY_9",
+	"GPIOY_10", "GPIOY_11", "GPIOY_12", "GPIOY_13", "GPIOY_14",
+	"GPIOY_15", "GPIOY_16",
+
+	"GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4",
+	"GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9",
+	"GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14",
+	"GPIOX_15", "GPIOX_16", "GPIOX_17", "GPIOX_18", "GPIOX_19",
+	"GPIOX_20", "GPIOX_21", "GPIOX_22",
+
+	"GPIO_TEST_N",
+};
+
+static const char * const gpio_aobus_groups[] = {
+	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
+	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
+	"GPIOAO_10", "GPIOAO_11", "GPIOAO_12", "GPIOAO_13",
+};
+
+static const char * const uart_ao_groups[] = {
+	"uart_tx_ao_a", "uart_rx_ao_a", "uart_cts_ao_a", "uart_rts_ao_a"
+};
+
+static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
+	FUNCTION(gpio_periphs),
+};
+
+static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
+	FUNCTION(gpio_aobus),
+	FUNCTION(uart_ao),
+};
+
+static struct meson_bank meson_gxbb_periphs_banks[] = {
+	/*   name    first                      last                    pullen  pull    dir     out     in  */
+	BANK("X",    PIN(GPIOX_0, EE_OFF),	PIN(GPIOX_22, EE_OFF),  4,  0,  4,  0,  12, 0,  13, 0,  14, 0),
+	BANK("Y",    PIN(GPIOY_0, EE_OFF),	PIN(GPIOY_16, EE_OFF),  1,  0,  1,  0,  3,  0,  4,  0,  5,  0),
+	BANK("DV",   PIN(GPIODV_0, EE_OFF),	PIN(GPIODV_29, EE_OFF), 0,  0,  0,  0,  0,  0,  1,  0,  2,  0),
+	BANK("H",    PIN(GPIOH_0, EE_OFF),	PIN(GPIOH_3, EE_OFF),   1, 20,  1, 20,  3, 20,  4, 20,  5, 20),
+	BANK("Z",    PIN(GPIOZ_0, EE_OFF),	PIN(GPIOZ_15, EE_OFF),  3,  0,  3,  0,  9,  0,  10, 0, 11,  0),
+	BANK("CARD", PIN(CARD_0, EE_OFF),	PIN(CARD_6, EE_OFF),    2, 20,  2, 20,  6, 20,  7, 20,  8, 20),
+	BANK("BOOT", PIN(BOOT_0, EE_OFF),	PIN(BOOT_17, EE_OFF),   2,  0,  2,  0,  6,  0,  7,  0,  8,  0),
+	BANK("CLK",  PIN(GPIOCLK_0, EE_OFF),	PIN(GPIOCLK_3, EE_OFF), 3, 28,  3, 28,  9, 28, 10, 28, 11, 28),
+};
+
+static struct meson_bank meson_gxbb_aobus_banks[] = {
+	/*   name    first              last               pullen  pull    dir     out     in  */
+	BANK("AO",   PIN(GPIOAO_0, 0),  PIN(GPIOAO_13, 0), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
+};
+
+static struct meson_domain_data meson_gxbb_periphs_domain_data = {
+	.name		= "periphs-banks",
+	.banks		= meson_gxbb_periphs_banks,
+	.num_banks	= ARRAY_SIZE(meson_gxbb_periphs_banks),
+	.pin_base	= 14,
+	.num_pins	= 120,
+};
+
+static struct meson_domain_data meson_gxbb_aobus_domain_data = {
+	.name		= "aobus-banks",
+	.banks		= meson_gxbb_aobus_banks,
+	.num_banks	= ARRAY_SIZE(meson_gxbb_aobus_banks),
+	.pin_base	= 0,
+	.num_pins	= 14,
+};
+
+struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data = {
+	.pins		= meson_gxbb_periphs_pins,
+	.groups		= meson_gxbb_periphs_groups,
+	.funcs		= meson_gxbb_periphs_functions,
+	.domain_data	= &meson_gxbb_periphs_domain_data,
+	.num_pins	= ARRAY_SIZE(meson_gxbb_periphs_pins),
+	.num_groups	= ARRAY_SIZE(meson_gxbb_periphs_groups),
+	.num_funcs	= ARRAY_SIZE(meson_gxbb_periphs_functions),
+};
+
+struct meson_pinctrl_data meson_gxbb_aobus_pinctrl_data = {
+	.pins		= meson_gxbb_aobus_pins,
+	.groups		= meson_gxbb_aobus_groups,
+	.funcs		= meson_gxbb_aobus_functions,
+	.domain_data	= &meson_gxbb_aobus_domain_data,
+	.num_pins	= ARRAY_SIZE(meson_gxbb_aobus_pins),
+	.num_groups	= ARRAY_SIZE(meson_gxbb_aobus_groups),
+	.num_funcs	= ARRAY_SIZE(meson_gxbb_aobus_functions),
+};
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index e610112..11623c6 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -549,6 +549,14 @@ static const struct of_device_id meson_pinctrl_dt_match[] = {
 		.compatible = "amlogic,meson8b-aobus-pinctrl",
 		.data = &meson8b_aobus_pinctrl_data,
 	},
+	{
+		.compatible = "amlogic,meson-gxbb-periphs-pinctrl",
+		.data = &meson_gxbb_periphs_pinctrl_data,
+	},
+	{
+		.compatible = "amlogic,meson-gxbb-aobus-pinctrl",
+		.data = &meson_gxbb_aobus_pinctrl_data,
+	},
 	{ },
 };
 
diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
index 9c93e0d..d89442e 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.h
+++ b/drivers/pinctrl/meson/pinctrl-meson.h
@@ -199,3 +199,5 @@ extern struct meson_pinctrl_data meson8_cbus_pinctrl_data;
 extern struct meson_pinctrl_data meson8_aobus_pinctrl_data;
 extern struct meson_pinctrl_data meson8b_cbus_pinctrl_data;
 extern struct meson_pinctrl_data meson8b_aobus_pinctrl_data;
+extern struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data;
+extern struct meson_pinctrl_data meson_gxbb_aobus_pinctrl_data;
diff --git a/include/dt-bindings/gpio/meson-gxbb-gpio.h b/include/dt-bindings/gpio/meson-gxbb-gpio.h
new file mode 100644
index 0000000..58654fd
--- /dev/null
+++ b/include/dt-bindings/gpio/meson-gxbb-gpio.h
@@ -0,0 +1,154 @@
+/*
+ * GPIO definitions for Amlogic Meson GXBB SoCs
+ *
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _DT_BINDINGS_MESON_GXBB_GPIO_H
+#define _DT_BINDINGS_MESON_GXBB_GPIO_H
+
+#define	GPIOAO_0	0
+#define	GPIOAO_1	1
+#define	GPIOAO_2	2
+#define	GPIOAO_3	3
+#define	GPIOAO_4	4
+#define	GPIOAO_5	5
+#define	GPIOAO_6	6
+#define	GPIOAO_7	7
+#define	GPIOAO_8	8
+#define	GPIOAO_9	9
+#define	GPIOAO_10	10
+#define	GPIOAO_11	11
+#define	GPIOAO_12	12
+#define	GPIOAO_13	13
+
+#define	GPIOZ_0		0
+#define	GPIOZ_1		1
+#define	GPIOZ_2		2
+#define	GPIOZ_3		3
+#define	GPIOZ_4		4
+#define	GPIOZ_5		5
+#define	GPIOZ_6		6
+#define	GPIOZ_7		7
+#define	GPIOZ_8		8
+#define	GPIOZ_9		9
+#define	GPIOZ_10	10
+#define	GPIOZ_11	11
+#define	GPIOZ_12	12
+#define	GPIOZ_13	13
+#define	GPIOZ_14	14
+#define	GPIOZ_15	15
+#define	GPIOH_0		16
+#define	GPIOH_1		17
+#define	GPIOH_2		18
+#define	GPIOH_3		19
+#define	BOOT_0		20
+#define	BOOT_1		21
+#define	BOOT_2		22
+#define	BOOT_3		23
+#define	BOOT_4		24
+#define	BOOT_5		25
+#define	BOOT_6		26
+#define	BOOT_7		27
+#define	BOOT_8		28
+#define	BOOT_9		29
+#define	BOOT_10		30
+#define	BOOT_11		31
+#define	BOOT_12		32
+#define	BOOT_13		33
+#define	BOOT_14		34
+#define	BOOT_15		35
+#define	BOOT_16		36
+#define	BOOT_17		37
+#define	CARD_0		38
+#define	CARD_1		39
+#define	CARD_2		40
+#define	CARD_3		41
+#define	CARD_4		42
+#define	CARD_5		43
+#define	CARD_6		44
+#define	GPIODV_0	45
+#define	GPIODV_1	46
+#define	GPIODV_2	47
+#define	GPIODV_3	48
+#define	GPIODV_4	49
+#define	GPIODV_5	50
+#define	GPIODV_6	51
+#define	GPIODV_7	52
+#define	GPIODV_8	53
+#define	GPIODV_9	54
+#define	GPIODV_10	55
+#define	GPIODV_11	56
+#define	GPIODV_12	57
+#define	GPIODV_13	58
+#define	GPIODV_14	59
+#define	GPIODV_15	60
+#define	GPIODV_16	61
+#define	GPIODV_17	62
+#define	GPIODV_18	63
+#define	GPIODV_19	64
+#define	GPIODV_20	65
+#define	GPIODV_21	66
+#define	GPIODV_22	67
+#define	GPIODV_23	68
+#define	GPIODV_24	69
+#define	GPIODV_25	70
+#define	GPIODV_26	71
+#define	GPIODV_27	72
+#define	GPIODV_28	73
+#define	GPIODV_29	74
+#define	GPIOY_0		75
+#define	GPIOY_1		76
+#define	GPIOY_2		77
+#define	GPIOY_3		78
+#define	GPIOY_4		79
+#define	GPIOY_5		80
+#define	GPIOY_6		81
+#define	GPIOY_7		82
+#define	GPIOY_8		83
+#define	GPIOY_9		84
+#define	GPIOY_10	85
+#define	GPIOY_11	86
+#define	GPIOY_12	87
+#define	GPIOY_13	88
+#define	GPIOY_14	89
+#define	GPIOY_15	90
+#define	GPIOY_16	91
+#define	GPIOX_0		92
+#define	GPIOX_1		93
+#define	GPIOX_2		94
+#define	GPIOX_3		95
+#define	GPIOX_4		96
+#define	GPIOX_5		97
+#define	GPIOX_6		98
+#define	GPIOX_7		99
+#define	GPIOX_8		100
+#define	GPIOX_9		101
+#define	GPIOX_10	102
+#define	GPIOX_11	103
+#define	GPIOX_12	104
+#define	GPIOX_13	105
+#define	GPIOX_14	106
+#define	GPIOX_15	107
+#define	GPIOX_16	108
+#define	GPIOX_17	109
+#define	GPIOX_18	110
+#define	GPIOX_19	111
+#define	GPIOX_20	112
+#define	GPIOX_21	113
+#define	GPIOX_22	114
+#define	GPIOCLK_0	115
+#define	GPIOCLK_1	116
+#define	GPIOCLK_2	117
+#define	GPIOCLK_3	118
+#define	GPIO_TEST_N	119
+
+#endif
-- 
2.7.4



From carlo at caione.org  Mon May  2 01:02:16 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon,  2 May 2016 10:02:16 +0200
Subject: [PATCH v2 2/4] documentation: Add compatibles for Amlogic Meson GXBB
 pin controllers
In-Reply-To: <1462176138-29433-1-git-send-email-carlo@caione.org>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
Message-ID: <1462176138-29433-3-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add the two new compatibles for the Amlogic Meson GXBB pin controllers.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
index 32f4a2d..fe7fe0b 100644
--- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
@@ -5,6 +5,8 @@ Required properties for the root node:
 		      "amlogic,meson8b-cbus-pinctrl"
 		      "amlogic,meson8-aobus-pinctrl"
 		      "amlogic,meson8b-aobus-pinctrl"
+		      "amlogic,meson-gxbb-periphs-pinctrl"
+		      "amlogic,meson-gxbb-aobus-pinctrl"
  - reg: address and size of registers controlling irq functionality
 
 === GPIO sub-nodes ===
-- 
2.7.4



From carlo at caione.org  Mon May  2 01:02:17 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon,  2 May 2016 10:02:17 +0200
Subject: [PATCH v2 3/4] ARM64: Kconfig: Select the Amlogic Meson pin
 controller driver
In-Reply-To: <1462176138-29433-1-git-send-email-carlo@caione.org>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
Message-ID: <1462176138-29433-4-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Select the Meson pin controller driver also for the AArch64 Meson
platform.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 arch/arm64/Kconfig.platforms | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 54967ff..fc051f0 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -65,6 +65,8 @@ config ARCH_MEDIATEK
 
 config ARCH_MESON
 	bool "Amlogic Platforms"
+	select PINCTRL
+	select PINCTRL_MESON
 	help
 	  This enables support for the Amlogic S905 SoCs.
 
-- 
2.7.4



From carlo at caione.org  Mon May  2 01:02:18 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon,  2 May 2016 10:02:18 +0200
Subject: [PATCH v2 4/4] ARM64: dts: amlogic: Enable pin controller on
 GXBB-based platforms
In-Reply-To: <1462176138-29433-1-git-send-email-carlo@caione.org>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
Message-ID: <1462176138-29433-5-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Update DTS and DTSI files to enable the pin controller. We also now
support the blinking blue LED on the Odroid-C2.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
Acked-by: Linus Walleij <linus.walleij at linaro.org>
---
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 13 +++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |  2 ++
 .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      |  3 ++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        | 41 ++++++++++++++++++++++
 4 files changed, 59 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index 7f2c674..41e1e66 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -45,6 +45,7 @@
 /dts-v1/;
 
 #include "meson-gxbb.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	compatible = "hardkernel,odroid-c2", "amlogic,meson-gxbb";
@@ -62,8 +63,20 @@
 		device_type = "memory";
 		reg = <0x0 0x0 0x0 0x80000000>;
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		blue {
+			label = "c2:blue:alive";
+			gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+	};
 };
 
 &uart_AO {
 	status = "okay";
+	pinctrl-0 = <&uart_ao_a_pins>;
+	pinctrl-names = "default";
 };
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index bf7ff1d..22e6298 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -62,4 +62,6 @@
 /* This UART is brought out to the DB9 connector */
 &uart_AO {
 	status = "okay";
+	pinctrl-0 = <&uart_ao_a_pins>;
+	pinctrl-names = "default";
 };
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
index 012cdcc..54bb7c7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
@@ -56,4 +56,7 @@
 
 &uart_AO {
 	status = "okay";
+	pinctrl-0 = <&uart_ao_a_pins>;
+	pinctrl-names = "default";
+
 };
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 3126f0c..6dd2768 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -43,6 +43,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/gpio/meson-gxbb-gpio.h>
 
 / {
 	compatible = "amlogic,meson-gxbb";
@@ -158,6 +159,29 @@
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
 
+			pinctrl_aobus: pinctrl at 14 {
+				compatible = "amlogic,meson-gxbb-aobus-pinctrl";
+				#address-cells = <2>;
+				#size-cells = <2>;
+				ranges;
+
+				gpio_ao: bank at 14 {
+					reg = <0x0 0x00014 0x0 0x8>,
+					      <0x0 0x0002c 0x0 0x4>,
+					      <0x0 0x00024 0x0 0x8>;
+					reg-names = "mux", "pull", "gpio";
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+
+				uart_ao_a_pins: uart_ao_a {
+					mux {
+						groups = "uart_tx_ao_a", "uart_rx_ao_a";
+						function = "uart_ao";
+					};
+				};
+			};
+
 			uart_AO: serial at 4c0 {
 				compatible = "amlogic,meson-uart";
 				reg = <0x0 0x004c0 0x0 0x14>;
@@ -173,6 +197,23 @@
 			#address-cells = <2>;
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>;
+
+			pinctrl_periphs: pinctrl at 4b0 {
+				compatible = "amlogic,meson-gxbb-periphs-pinctrl";
+				#address-cells = <2>;
+				#size-cells = <2>;
+				ranges;
+
+				gpio: bank at 4b0 {
+					reg = <0x0 0x004b0 0x0 0x28>,
+					      <0x0 0x004e8 0x0 0x14>,
+					      <0x0 0x00120 0x0 0x14>,
+					      <0x0 0x00430 0x0 0x40>;
+					reg-names = "mux", "pull", "pull-enable", "gpio";
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+			};
 		};
 
 		hiubus: hiubus at c883c000 {
-- 
2.7.4



From maitysanchayan at gmail.com  Mon May  2 01:12:12 2016
From: maitysanchayan at gmail.com (maitysanchayan at gmail.com)
Date: Mon, 2 May 2016 13:42:12 +0530
Subject: [PATCH v2 2/5] ARM: dts: vfxxx: Add device tree node for OCOTP
In-Reply-To: <4759698.elnRBldlxl@wuerfel>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
 <b5c1ff5a805eae3e53f07f8d0161f0af51586c00.1462171990.git.maitysanchayan@gmail.com>
 <4759698.elnRBldlxl@wuerfel>
Message-ID: <20160502081211.GA7847@Sanchayan-Arch.localdomain>

Hello Arnd,

On 16-05-02 09:31:12, Arnd Bergmann wrote:
> On Monday 02 May 2016 12:35:01 Sanchayan Maity wrote:
> > +                       ocotp at 400a5000 {
> > +                               compatible = "fsl,vf610-ocotp";
> > +                               #address-cells = <1>;
> > +                               #size-cells = <1>;
> > +                               reg = <0x400a5000 0xCF0>;
> > +                               clocks = <&clks VF610_CLK_OCOTP>;
> > +
> > +                               ocotp_cfg0: cfg0 at 410 {
> > +                                       reg = <0x410 0x4>;
> > +                               };
> > +
> > +                               ocotp_cfg1: cfg1 at 420 {
> > +                                       reg = <0x420 0x4>;
> > +                               };
> > +                       };
> 
> How do the registers of the child nodes relate to the registers of the
> parent? If there are in the same address space, it might be good to
> add a "ranges" property to describe it.

cfg0 and cfg1 are in the same address space viz. 0x400a5410 and 0x400a5420
respectively. These nodes are primarily for use by the NVMEM consumer API in
the SoC bus driver to retrieve the values from these registers leveraging
the NVMEM vf610 ocotp driver.

Based on the NVMEM bindings here
http://lxr.free-electrons.com/source/Documentation/devicetree/bindings/nvmem/nvmem.txt#L33

Thanks.

Regards,
Sanchayan.

> 
> 	Arnd

> Date: Mon, 02 May 2016 12:02:21 +1000
> From: Gavin Shan <gwshan at linux.vnet.ibm.com>
> To: Rob Herring <robherring2 at gmail.com>
> Cc: "devicetree at vger.kernel.org" <devicetree at vger.kernel.org>,
>  aik at ozlabs.ru, Gavin Shan <gwshan at linux.vnet.ibm.com>, Grant Likely
>  <grant.likely at linaro.org>, "linux-pci at vger.kernel.org"
>  <linux-pci at vger.kernel.org>, Bjorn Helgaas <bhelgaas at google.com>,
>  linuxppc-dev <linuxppc-dev at lists.ozlabs.org>, dja at axtens.net
> Subject: Re: [PATCH v8 40/45] drivers/of: Split unflatten_dt_node()
> 
> On Wed, Feb 17, 2016 at 08:30:42AM -0600, Rob Herring wrote:
> >On Tue, Feb 16, 2016 at 9:44 PM, Gavin Shan <gwshan at linux.vnet.ibm.com> wrote:
> >> The function unflatten_dt_node() is called recursively to unflatten
> >> device nodes and properties in the FDT blob. It looks complicated
> >> and hard to be understood.
> >>
> >> This splits the function into 3 functions: populate_properties(),
> >> populate_node() and unflatten_dt_node(). populate_properties(),
> >> which is called by populate_node(), creates properties for the
> >> indicated device node. The later one creates the device nodes
> >> from FDT blob. populate_node() gets the offset in FDT blob for
> >> next device nodes and then calls populate_node(). No logical
> >> changes introduced.
> >>
> >> Signed-off-by: Gavin Shan <gwshan at linux.vnet.ibm.com>
> >> ---
> >>  drivers/of/fdt.c | 249 ++++++++++++++++++++++++++++++++-----------------------
> >>  1 file changed, 147 insertions(+), 102 deletions(-)
> >
> >One nit, otherwise:
> >
> >Acked-by: Rob Herring <robh at kernel.org>
> >
> >[...]
> >
> >> +               /* And we process the "ibm,phandle" property
> >> +                * used in pSeries dynamic device tree
> >> +                * stuff
> >> +                */
> >> +               if (!strcmp(pname, "ibm,phandle"))
> >> +                       np->phandle = be32_to_cpup(val);
> >> +
> >> +               pp->name   = (char *)pname;
> >> +               pp->length = sz;
> >> +               pp->value  = (__be32 *)val;
> >
> >This cast should not be needed.
> >
> 
> It's needed. Otherwise, we will have warning. So I will keep it. I just
> went through this one for next revision and sorry for late response.
> 
> drivers/of/fdt.c:225:14: warning: assignment discards ?const? qualifier from pointer target type
>    pp->value  = val;
>               ^
> 
> Thanks,
> Gavin
> 
> >> +               *pprev     = pp;
> >> +               pprev      = &pp->next;
> >> +       }
> >
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev



From p.zabel at pengutronix.de  Mon May  2 01:26:21 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Mon, 02 May 2016 10:26:21 +0200
Subject: [PATCH 3/7] reset: lpc18xx: use devm_reset_controller_register()
In-Reply-To: <1462099023-11819-4-git-send-email-yamada.masahiro@socionext.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
 <1462099023-11819-4-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462177581.3933.7.camel@pengutronix.de>

Am Sonntag, den 01.05.2016, 19:36 +0900 schrieb Masahiro Yamada:
> Use devm_reset_controller_register() for the reset controller
> registration and remove the unregister call from the .remove callback.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> ---
> 
>  drivers/reset/reset-lpc18xx.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c
> index 3b8a4f5..dd4f27e 100644
> --- a/drivers/reset/reset-lpc18xx.c
> +++ b/drivers/reset/reset-lpc18xx.c
> @@ -199,7 +199,7 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
>  
>  	platform_set_drvdata(pdev, rc);
>  
> -	ret = reset_controller_register(&rc->rcdev);
> +	ret = devm_reset_controller_register(&pdev->dev, &rc->rcdev);
>  	if (ret) {
>  		dev_err(&pdev->dev, "unable to register device\n");
>  		goto dis_clks;
> @@ -229,8 +229,6 @@ static int lpc18xx_rgu_remove(struct platform_device *pdev)
>  	if (ret)
>  		dev_warn(&pdev->dev, "failed to unregister restart handler\n");
>  
> -	reset_controller_unregister(&rc->rcdev);
> -
>  	clk_disable_unprepare(rc->clk_delay);
>  	clk_disable_unprepare(rc->clk_reg);
>  

Hmm, would this patch theoretically allow a window between the calls to
clk_disable_unprepare(clk_reg) and devm_reset_controller_release() where
reset_control_get() + reset_control_(de)assert() would access unclocked
registers?

regards
Philipp



From mcoquelin.stm32 at gmail.com  Mon May  2 01:32:14 2016
From: mcoquelin.stm32 at gmail.com (Maxime Coquelin)
Date: Mon, 2 May 2016 10:32:14 +0200
Subject: [PATCH v2 6/9] pinctrl: Add IRQ support to STM32 gpios
In-Reply-To: <CACRpkdbW133h_HNXhszzk2MdtMyrX5WBC_5GnqD5wrmo=yT27A@mail.gmail.com>
References: <1459436979-17275-1-git-send-email-mcoquelin.stm32@gmail.com>
 <1459436979-17275-7-git-send-email-mcoquelin.stm32@gmail.com>
 <CACRpkdYLPWNQZgdFHVwLOZv+rS=bdERM9St5b0hVHTd_+ZJMKg@mail.gmail.com>
 <CALszF6CUFKAjzUpEh3pDtSDdJuFan1ON0Kcu_uKD_OX36kXOHQ@mail.gmail.com>
 <CACRpkdZXz8-UnOd6ee48AWqDX2X9Hvux=+ZQ7qdg6a4KVoArww@mail.gmail.com>
 <CALszF6D1nPJ8NVghWo27y1KABwN7-QQfjPTmgY2pgdY_8jjkTQ@mail.gmail.com>
 <CACRpkdbW133h_HNXhszzk2MdtMyrX5WBC_5GnqD5wrmo=yT27A@mail.gmail.com>
Message-ID: <CALszF6C7_9pZt-xywczinNFDppmwWmJjwrjVGyx6VL08yJFxgA@mail.gmail.com>

2016-04-30 13:32 GMT+02:00 Linus Walleij <linus.walleij at linaro.org>:
> On Fri, Apr 29, 2016 at 1:19 PM, Maxime Coquelin
> <mcoquelin.stm32 at gmail.com> wrote:
>> It looks like this: http://pastebin.com/raw/cs2WiNKZ
>> You can directly check section 12.2.5 of the stm32f429 reference manual:
>> http://www2.st.com/resource/en/reference_manual/dm00031020.pdf
>
> Nice ASCII art, include that into the commit message :)

I will! :)

>
>> For example, we can imagine a board where gpioa0 is used SD's card detect,
>> and gpiob0 used to control a led.
>>
>> If we set the mux at request time, gpiob0 request may overwrite the mux
>> configuration set by gpioa0, whereas it is not used as interrupt.
>>
>> That is the reason why I did it in .to_irq().
>
> Well now I am even *more* convinced that this should not happen in
> .to_irq(). .to_irq() should not do *anything*.
>
> This needs to happen as part of the irqchip setting up the actual
> interrupt.
>
> And it seems the problem is that this driver does *not* define its
> own irqchip, but it *should*.
>
> What you want to do is implement an hierarchical irqdomain in your
> irqchip, which is what other drivers of this type are doing, see:
> drivers/gpio/gpio-xgene-sb.c
> irq_domain_create_hierarchy() is your friend.
>
>>> It should *also* be done in the set-up path for the irqchip
>>> side, if that line is used without any interaction with the
>>> gpio side of things.
>>
>> Actually, a line is either used by a GPIO, (exclusive) or another purpose.
>> In the case of a GPIO line, I think we should always go through the gpio.
>
> This is a textbook example of a hierarchichal irq domain I think.
>
>>> The point is that each IRQ that ever get used
>>> has a 1-to-1 relationship to a certain GPIO line, and if that
>>> relationship cannot be resolved from the irqchip side,
>>> something is wrong. The irqchip needs to enable the
>>> GPIO line it is backing to recieve interrupts without any
>>> requirements that .to_irq() have been called first.
>>
>> Actually, this is not a 1:1 relationship, as for example, exti0 can be connected
>> to either gpioa0, or gpiob0,..., or gpiok0.
>
> That is what hierarchical irqdomain is for.
>
> You should expose an irqchip from the gpio driver, that give you
> unique irq translations for *all* GPIO lines.
>
> Then, at runtime, if the hierarchical irqdomain cannot map
> (i.e. mux) the interrupt onto one of the available lines,
> you will get an error.

Thanks a lot for this valuable feedback.
I will have a look at hierachical irq domains, and hope to come back this week
with an implementation.

Regards,
Maxime


From christoffer.dall at linaro.org  Mon May  2 01:38:50 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Mon, 2 May 2016 10:38:50 +0200
Subject: [PATCH v2 32/54] KVM: arm/arm64: vgic-new: Add GICv3 MMIO
 handling framework
In-Reply-To: <57236E3B.2000501@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-33-git-send-email-andre.przywara@arm.com>
 <572369F0.20704@arm.com> <57236E3B.2000501@arm.com>
Message-ID: <20160502083850.GC963@cbox>

On Fri, Apr 29, 2016 at 03:22:51PM +0100, Vladimir Murzin wrote:
> On 29/04/16 15:04, Vladimir Murzin wrote:
> > Hi Andre,
> > 
> > On 28/04/16 17:45, Andre Przywara wrote:
> >> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
> >> +{
> >> +	int nr_vcpus = atomic_read(&kvm->online_vcpus);
> >> +	struct kvm_vcpu *vcpu;
> >> +	struct vgic_io_device *devices, *device;
> >> +	int c, ret = 0;
> >> +
> >> +	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
> >> +			  GFP_KERNEL);
> >> +	if (!devices)
> >> +		return -ENOMEM;
> >> +
> >> +	device = devices;
> >> +	kvm_for_each_vcpu(c, vcpu, kvm) {
> >> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
> >> +		device->base_addr = redist_base_address;
> >> +		device->regions = vgic_v3_redist_registers;
> >> +		device->nr_regions = ARRAY_SIZE(vgic_v3_redist_registers);
> >> +		device->redist_vcpu = vcpu;
> >> +
> >> +		mutex_lock(&kvm->slots_lock);
> >> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
> >> +					      redist_base_address,
> >> +					      SZ_64K, &device->dev);
> >> +		mutex_unlock(&kvm->slots_lock);
> >> +
> >> +		if (ret)
> >> +			break;
> >> +
> >> +		device++;
> >> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
> >> +		device->base_addr = redist_base_address + SZ_64K;
> >> +		device->regions = vgic_v3_private_registers;
> >> +		device->nr_regions = ARRAY_SIZE(vgic_v3_private_registers);
> >> +		device->redist_vcpu = vcpu;
> >> +
> >> +		mutex_lock(&kvm->slots_lock);
> >> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
> >> +					      redist_base_address + SZ_64K,
> >> +					      SZ_64K, &device->dev);
> >> +		mutex_unlock(&kvm->slots_lock);
> >> +		if (ret) {
> >> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
> >> +						  &devices[c * 2].dev);
> >> +			break;
> >> +		}
> >> +		device++;
> >> +		redist_base_address += 2 * SZ_64K;
> >> +	}
> > 
> > Can we put cond_resched() somewhere in kvm_for_each_vcpu to avoid
> 
> Apologies, it seems to come from kvm_io_bus infrastructure.
> 
The stack trace seems to indicate that this comes from the fact that the
kvm_io_bus logic does a full heapsort on the regions for every
insertion.  (My analysis skills fails me here as I have no idea what an
arithmetic series of an n*log(n) bound is.)

But if that's the case, then the io_bus framework must either implement
a more clever insertion logic using a better data structure which
optimizes for this case, or provide a way to lock the whole thing,
insert unsorted, and sort in the end.

-Christoffer

> 
> > complains with CONFIG_PREEMPT_NONE=y and many many cpus been used?
> > 
> >>   # lkvm run -k gic-test.flat.a64 -m 316 -c 255 --name guest-727
> >>   Info: Loaded kernel to 0x80080000 (69624 bytes)
> >>   Info: Placing fdt at 0x8fe00000 - 0x8fffffff
> >>   # Warning: The maximum recommended amount of VCPUs is 4
> >>   Info: virtio-mmio.devices=0x200 at 0x10000:36
> >>
> >>   Info: virtio-mmio.devices=0x200 at 0x10200:37
> >>
> >>   Info: virtio-mmio.devices=0x200 at 0x10400:38
> >>
> >>   Info: virtio-mmio.devices=0x200 at 0x10600:39
> >>
> >> INFO: rcu_sched self-detected stall on CPU
> >>  0-...: (5249 ticks this GP) idle=589/140000000000001/0 softirq=393/393 fqs=5244 
> >>   (t=5250 jiffies g=-166 c=-167 q=0)
> >> Task dump for CPU 0:
> >> kvm-vcpu-0      R  running task        0   735      1 0x00000002
> >> Call trace:
> >> [<ffffff8008088cc4>] dump_backtrace+0x0/0x194
> >> [<ffffff8008088e6c>] show_stack+0x14/0x1c
> >> [<ffffff80080d4dd0>] sched_show_task+0xa4/0xe8
> >> [<ffffff80080d6ddc>] dump_cpu_task+0x40/0x4c
> >> [<ffffff80080fd398>] rcu_dump_cpu_stacks+0xa8/0xdc
> >> [<ffffff8008100214>] rcu_check_callbacks+0x28c/0x7a4
> >> [<ffffff80081034a8>] update_process_times+0x3c/0x68
> >> [<ffffff8008111820>] tick_sched_handle.isra.15+0x50/0x60
> >> [<ffffff8008111874>] tick_sched_timer+0x44/0x7c
> >> [<ffffff8008103bf8>] __hrtimer_run_queues+0xc8/0x150
> >> [<ffffff8008104110>] hrtimer_interrupt+0x9c/0x1b0
> >> [<ffffff80083b8b74>] arch_timer_handler_phys+0x2c/0x38
> >> [<ffffff80080f6d14>] handle_percpu_devid_irq+0x78/0x98
> >> [<ffffff80080f2a2c>] generic_handle_irq+0x24/0x38
> >> [<ffffff80080f2d98>] __handle_domain_irq+0x84/0xa8
> >> [<ffffff80080825e0>] gic_handle_irq+0x74/0x178
> >> Exception stack(0xffffffc0173e3830 to 0xffffffc0173e3950)
> >> 3820:                                   ffffffc0165ac038 ffffffc0165ac080
> >> 3840: 0000000000000018 0000000000000004 0000000000000014 000000000000003f
> >> 3860: ffffffc0165aeea8 ffffffc000010000 ffffffc017ef5af0 ffffffc0173ecd28
> >> 3880: 000000003fef0000 cfdfdfdf00010000 ffffffc0173ecd50 000000003ff00000
> >> 38a0: cfdfdfdf00010000 0000000000000000 ffffff80081acaf0 0000000000000000
> >> 38c0: 0000000000000000 00000000000000f0 ffffffc0165ac008 0000000000000018
> >> 38e0: ffffff80080992e8 0000000000000078 ffffff8008276b54 0000000000002970
> >> 3900: 0000000000000018 ffffffc0165ac080 ffffffc0165ac038 ffffffc0173e3950
> >> 3920: ffffff8008276d8c ffffffc0173e3950 ffffff8008276b58 0000000020000145
> >> 3940: 0000000000000000 0000000000000001
> >> [<ffffff8008084f20>] el1_irq+0xa0/0x100
> >> [<ffffff8008276b58>] generic_swap+0x4/0x28
> >> [<ffffff800809e108>] kvm_io_bus_register_dev+0xc8/0x110
> >> [<ffffff80080ab054>] vgic_register_redist_iodevs+0xd8/0x20c
> >> [<ffffff80080a98f8>] vgic_v3_map_resources+0x98/0xec
> >> [<ffffff80080a8cd8>] kvm_vgic_map_resources+0x4c/0x6c
> >> [<ffffff80080a06d4>] kvm_arch_vcpu_ioctl_run+0x68/0x424
> >> [<ffffff800809bc98>] kvm_vcpu_ioctl+0x1b4/0x6f8
> >> [<ffffff80081aca98>] do_vfs_ioctl+0x708/0x760
> >> [<ffffff80081acb4c>] SyS_ioctl+0x5c/0x8c
> >> [<ffffff8008085630>] el0_svc_naked+0x24/0x28
> > 
> > Cheers
> > Vladimir
> > _______________________________________________
> > kvmarm mailing list
> > kvmarm at lists.cs.columbia.edu
> > https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
> > 
> > 
> 


From linus.walleij at linaro.org  Mon May  2 01:43:18 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon,  2 May 2016 10:43:18 +0200
Subject: [PATCH 1/2] ARM: u8500_defconfig: remove staging from defconfig
Message-ID: <1462178598-13651-1-git-send-email-linus.walleij@linaro.org>

Ux500 was enabling the staging drivers due to the RMI4
touchscreen driver, this is now properly upstream, so drop
this and the dead symbol for the old RMI4 hack from
the defconfig.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 arch/arm/configs/u8500_defconfig | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index d2a3a67f198a..0ce2aa73c28a 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -107,8 +107,6 @@ CONFIG_RTC_DRV_AB8500=y
 CONFIG_RTC_DRV_PL031=y
 CONFIG_DMADEVICES=y
 CONFIG_STE_DMA40=y
-CONFIG_STAGING=y
-CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_HSEM_U8500=y
 CONFIG_IIO=y
 CONFIG_IIO_ST_ACCEL_3AXIS=y
-- 
2.4.11



From linus.walleij at linaro.org  Mon May  2 01:43:30 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon,  2 May 2016 10:43:30 +0200
Subject: [PATCH 2/2] ARM: u8500_defconfig: update sensor config
Message-ID: <1462178610-13698-1-git-send-email-linus.walleij@linaro.org>

The Ux500 is using buffered IIO as the sensors support
IRQs. The BH1780 ambient light sensor was added to IIO,
so disable the old misc driver and activate the driver
in IIO.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 arch/arm/configs/u8500_defconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index 0ce2aa73c28a..d95796881b89 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -45,7 +45,6 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
-CONFIG_SENSORS_BH1780=y
 CONFIG_NETDEVICES=y
 CONFIG_SMSC911X=y
 CONFIG_SMSC_PHY=y
@@ -109,8 +108,10 @@ CONFIG_DMADEVICES=y
 CONFIG_STE_DMA40=y
 CONFIG_HSEM_U8500=y
 CONFIG_IIO=y
+CONFIG_IIO_BUFFER=y
 CONFIG_IIO_ST_ACCEL_3AXIS=y
 CONFIG_IIO_ST_GYRO_3AXIS=y
+CONFIG_BH1780=y
 CONFIG_IIO_ST_MAGN_3AXIS=y
 CONFIG_IIO_ST_PRESS=y
 CONFIG_EXT2_FS=y
-- 
2.4.11



From linus.walleij at linaro.org  Mon May  2 01:49:06 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 2 May 2016 10:49:06 +0200
Subject: [GIT PULL] Ux500 defconfig updates for v4.7
Message-ID: <CACRpkdaf39+gQzBb5U9gM5n17QwsNd7FxTbd3J+hLcuBNczKWA@mail.gmail.com>

Hi ARM SoC folks,

here are some defconfig updates for the v4.7 merge cycle.
Please pull them in to whatever defconfig branch is apropriate.

Yours,
Linus Walleij


The following changes since commit 04974df8049fc4240d22759a91e035082ccd18b4:

  Linux 4.6-rc6 (2016-05-01 15:52:31 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
tags/ux500-defconfig-armsoc

for you to fetch changes up to 95d48536d51c946a69ba251f2a198a3f63abe521:

  ARM: u8500_defconfig: update sensor config (2016-05-02 10:42:58 +0200)

----------------------------------------------------------------
Ux500 defconfig update for v4.7:
- Remove the unused MACH_UX500_DT option from the multi_v7 defconfig
- Remove staging driver from u8500_defconfig
- Update sensor support in u8500_defconfig

----------------------------------------------------------------
Lee Jones (1):
      ARM: multi_v7_defconfig: Remove unused Kconfig option MACH_UX500_DT

Linus Walleij (2):
      ARM: u8500_defconfig: remove staging from defconfig
      ARM: u8500_defconfig: update sensor config

 arch/arm/configs/multi_v7_defconfig | 1 -
 arch/arm/configs/u8500_defconfig    | 5 ++---
 2 files changed, 2 insertions(+), 4 deletions(-)


From martin at sperl.org  Mon May  2 01:54:29 2016
From: martin at sperl.org (Martin Sperl)
Date: Mon, 2 May 2016 10:54:29 +0200
Subject: [PATCH 2/2] clk: bcm2835: Skip PLLC clocks when deciding on a new
 clock parent
In-Reply-To: <C771F70C-2F88-49E1-A370-D76D13262C1E@martin.sperl.org>
References: <1461699585-6649-1-git-send-email-eric@anholt.net>
 <1461699585-6649-2-git-send-email-eric@anholt.net>
 <C771F70C-2F88-49E1-A370-D76D13262C1E@martin.sperl.org>
Message-ID: <572715C5.6070700@sperl.org>


On 30.04.2016 11:28, Martin Sperl wrote:
>> On 26.04.2016, at 21:39, Eric Anholt <eric at anholt.net> wrote:
>>
>> If the firmware had set up a clock to source from PLLC, go along with
>> it.  But if we're looking for a new parent, we don't want to switch it
>> to PLLC because the firmware will force PLLC (and thus the AXI bus
>> clock) to different frequencies during over-temp/under-voltage,
>> without notification to Linux.
>>
>> On my system, this moves the Linux-enabled HDMI state machine and DSI1
>> escape clock over to plld_per from pllc_per.  EMMC still ends up on
>> pllc_per, because the firmware had set it up to use that.
>>
>> Signed-off-by: Eric Anholt <eric at anholt.net>
>> Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks")
>> ?
> I guess this patch looks to me as if it is a policy inside the kernel,
> which is AFAIK frowned upon.
>
> I am looking into making "assigned-clock-parents? inside the dt
> work with the driver.
>
> Could look something like this:
> i2s: i2s at 7e203000 {
> 	assigned-clock-parents = <&cprman BCM2835_PLLD_PER>, <&clk_osc>;
> 	assigned-clocks = <&cprman BCM2835_CLOCK_PCM>, <&cprman BCM2835_CLOCK_PCM>;
> };
> (not sure if that works really - the same clock in assigned-clocks looks suspicious)
>
> This would move the policy out of the kernel into the device-tree,
> which - i guess is a better solution.

So after some more investigation it seems that we can not really use those
assigned-clock-parents properties for our purpose of filtering the parent
clocks, as it:
a) requires also assigned-clocks to be set (this may be OK)
b) it does not allow to define a list of clocks to get used - it will 
just set the
     parent of the assigned-clock - if we take the example shown above, 
it would
     call clk_set_parent 2 times for the PCM clock - once with PLLD_PER
     and once with clk_osc.

So I start to wonder if it would not be better to use an approach like this:
cprman: cprman at 7e101000 {
     ...
     brcm,clock-flags = <flags for PCM>, <flags for PWM>;
     brcm,clock-index = <BCM2835_CLOCK_PCM>, <BCM2835_CLOCK_PWM>;
}

the flags would be a bitfield that select the parent clocks.

So it could look like this:
cprman: cprman at 7e101000 {
     ...
     brcm,clock-flags = (BIT(BCM2835_PER_PARENT_OSC) |
BIT(BCM2835_PER_PARENT_PLLD_PER)), ...;
     brcm,clock-index = <BCM2835_CLOCK_PCM>, <BCM2835_CLOCK_PWM>;
}

BCM2835_PER_PARENT_PLLD_PER and BCM2835_PER_PARENT_OSC
would then be defined in include/dt-bindings/clock/bcm2835.h

In addition this would also allow us to add other flags to enable
higher order MASH clock dividers - we currently only allow simple
fractional dividers - we could even force the use of integer dividers
if there comes a need.

This would really allow us to define the parents freely and if the
firmware ever changes its behavior with regards to PLLC, then we can
easily change the device-tree.

Is this approach acceptable - maybe in a variation?

Thanks,
                     Martin



From eballetbo at gmail.com  Mon May  2 02:13:31 2016
From: eballetbo at gmail.com (Enric Balletbo Serra)
Date: Mon, 2 May 2016 11:13:31 +0200
Subject: [PATCH 1/2] ASoC: rockchip: i2s: separate capture and playback
In-Reply-To: <20160430070049.GF14612@serenity.lan>
References: <1449657147-26959-1-git-send-email-john@metanate.com>
 <CAFqH_52C4JKno4uyt54UdWKAJKM4FPGRiQaQQ9_H-Mz1Cr+Hqg@mail.gmail.com>
 <20160430070049.GF14612@serenity.lan>
Message-ID: <CAFqH_51sSqaoUtadYux+A38wQ1y9T-GKU3_PEcgT9rp_19_b8g@mail.gmail.com>

Hi John,

Thanks for answer.

2016-04-30 9:00 GMT+02:00 John Keeping <john at keeping.me.uk>:
> Hi Enric,
>
> On Fri, Apr 29, 2016 at 04:59:27PM +0200, Enric Balletbo Serra wrote:
>> 2015-12-09 11:32 GMT+01:00 John Keeping <john at metanate.com>:
>> > If we only clear the tx/rx state when both are disabled it is not
>> > possible to start/stop one multiple times while the other is running.
>> > Since the two are independently controlled, treat them as such and
>> > remove the false dependency between capture and playback.
>> >
>> > Signed-off-by: John Keeping <john at metanate.com>
>> > ---
>> >  sound/soc/rockchip/rockchip_i2s.c | 72 +++++++++++++++++----------------------
>> >  1 file changed, 32 insertions(+), 40 deletions(-)
>> >
>> > diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
>> > index 83b1b9c..acc6225 100644
>> > --- a/sound/soc/rockchip/rockchip_i2s.c
>> > +++ b/sound/soc/rockchip/rockchip_i2s.c
>> > @@ -82,8 +82,8 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
>> >                                    I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
>> >
>> >                 regmap_update_bits(i2s->regmap, I2S_XFER,
>> > -                                  I2S_XFER_TXS_START | I2S_XFER_RXS_START,
>> > -                                  I2S_XFER_TXS_START | I2S_XFER_RXS_START);
>> > +                                  I2S_XFER_TXS_START,
>> > +                                  I2S_XFER_TXS_START);
>> >
>> >                 i2s->tx_start = true;
>> >         } else {
>> > @@ -92,27 +92,23 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
>> >                 regmap_update_bits(i2s->regmap, I2S_DMACR,
>> >                                    I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
>> >
>> > -               if (!i2s->rx_start) {
>> > -                       regmap_update_bits(i2s->regmap, I2S_XFER,
>> > -                                          I2S_XFER_TXS_START |
>> > -                                          I2S_XFER_RXS_START,
>> > -                                          I2S_XFER_TXS_STOP |
>> > -                                          I2S_XFER_RXS_STOP);
>> > +               regmap_update_bits(i2s->regmap, I2S_XFER,
>> > +                                  I2S_XFER_TXS_START,
>> > +                                  I2S_XFER_TXS_STOP);
>> >
>> > -                       regmap_update_bits(i2s->regmap, I2S_CLR,
>> > -                                          I2S_CLR_TXC | I2S_CLR_RXC,
>> > -                                          I2S_CLR_TXC | I2S_CLR_RXC);
>> > +               regmap_update_bits(i2s->regmap, I2S_CLR,
>> > +                                  I2S_CLR_TXC,
>> > +                                  I2S_CLR_TXC);
>> >
>> > -                       regmap_read(i2s->regmap, I2S_CLR, &val);
>> > +               regmap_read(i2s->regmap, I2S_CLR, &val);
>> >
>> > -                       /* Should wait for clear operation to finish */
>> > -                       while (val) {
>> > -                               regmap_read(i2s->regmap, I2S_CLR, &val);
>> > -                               retry--;
>> > -                               if (!retry) {
>> > -                                       dev_warn(i2s->dev, "fail to clear\n");
>> > -                                       break;
>> > -                               }
>> > +               /* Should wait for clear operation to finish */
>> > +               while (val & I2S_CLR_TXC) {
>> > +                       regmap_read(i2s->regmap, I2S_CLR, &val);
>> > +                       retry--;
>> > +                       if (!retry) {
>> > +                               dev_warn(i2s->dev, "fail to clear\n");
>> > +                               break;
>> >                         }
>> >                 }
>> >         }
>> > @@ -128,8 +124,8 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
>> >                                    I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
>> >
>> >                 regmap_update_bits(i2s->regmap, I2S_XFER,
>> > -                                  I2S_XFER_TXS_START | I2S_XFER_RXS_START,
>> > -                                  I2S_XFER_TXS_START | I2S_XFER_RXS_START);
>> > +                                  I2S_XFER_RXS_START,
>> > +                                  I2S_XFER_RXS_START);
>> >
>> >                 i2s->rx_start = true;
>> >         } else {
>> > @@ -138,27 +134,23 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
>> >                 regmap_update_bits(i2s->regmap, I2S_DMACR,
>> >                                    I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
>> >
>> > -               if (!i2s->tx_start) {
>> > -                       regmap_update_bits(i2s->regmap, I2S_XFER,
>> > -                                          I2S_XFER_TXS_START |
>> > -                                          I2S_XFER_RXS_START,
>> > -                                          I2S_XFER_TXS_STOP |
>> > -                                          I2S_XFER_RXS_STOP);
>> > +               regmap_update_bits(i2s->regmap, I2S_XFER,
>> > +                                  I2S_XFER_RXS_START,
>> > +                                  I2S_XFER_RXS_STOP);
>> >
>> > -                       regmap_update_bits(i2s->regmap, I2S_CLR,
>> > -                                          I2S_CLR_TXC | I2S_CLR_RXC,
>> > -                                          I2S_CLR_TXC | I2S_CLR_RXC);
>> > +               regmap_update_bits(i2s->regmap, I2S_CLR,
>> > +                                  I2S_CLR_RXC,
>> > +                                  I2S_CLR_RXC);
>> >
>> > -                       regmap_read(i2s->regmap, I2S_CLR, &val);
>> > +               regmap_read(i2s->regmap, I2S_CLR, &val);
>> >
>> > -                       /* Should wait for clear operation to finish */
>> > -                       while (val) {
>> > -                               regmap_read(i2s->regmap, I2S_CLR, &val);
>> > -                               retry--;
>> > -                               if (!retry) {
>> > -                                       dev_warn(i2s->dev, "fail to clear\n");
>> > -                                       break;
>> > -                               }
>> > +               /* Should wait for clear operation to finish */
>> > +               while (val & I2S_CLR_RXC) {
>> > +                       regmap_read(i2s->regmap, I2S_CLR, &val);
>> > +                       retry--;
>> > +                       if (!retry) {
>> > +                               dev_warn(i2s->dev, "fail to clear\n");
>> > +                               break;
>> >                         }
>> >                 }
>> >         }
>> > --
>> > 2.6.3.462.gbe2c914
>>
>> Using my Veyron Jerry Chromebook wiht latest kernel I found that the
>> speakers doesn't work. Bisect points to this patch as the offending
>> commit. However your changes looks reasonable the fact is that
>> reverting the patch makes the audio work again on my device. I need to
>> dig a bit more into the issue, but meanwhile, any idea on what is
>> happening ? Can I ask which device did you test?
>
> I tested this on a Radxa Rock2 square.  This change fixed an issue I
> found when running separate processes for playback and recording (I was
> testing with arecord and speaker-test IIRC) but I don't think that
> should be relevant.  I just read through the patch again and I can't see
> anything obviously wrong so I'm afraid I don't have any idea what's
> causing the problem you're seeing.
>

By chance, do you have a git repo containing the changes required to
test the sound on Radxa Rock2? Guess this is not in mainline.

Thanks,
 Enric

>
> John


From vinod.koul at intel.com  Mon May  2 02:25:52 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Mon, 2 May 2016 14:55:52 +0530
Subject: [PATCH V17 2/3] dmaengine: qcom_hidma: add debugfs hooks
In-Reply-To: <57258799.70803@codeaurora.org>
References: <1460384473-5775-1-git-send-email-okaya@codeaurora.org>
 <1460384473-5775-3-git-send-email-okaya@codeaurora.org>
 <20160426033029.GB2274@localhost>
 <b068ead6474f2ffee5acef9ea799aba3@codeaurora.org>
 <20160426162529.GK2274@localhost> <571F9D76.2060809@codeaurora.org>
 <20160427081501.GV2274@localhost>
 <2c7ac0732fb16f952db24b7c70065318@codeaurora.org>
 <57258799.70803@codeaurora.org>
Message-ID: <20160502092552.GC2274@localhost>

On Sun, May 01, 2016 at 12:35:37AM -0400, Sinan Kaya wrote:
> >>> >
> >>> > Hmm, have you thought about using regmap?
> >>>
> >>> To be honest, I didn't know what regmap is but I just read some code
> >>> and looked at how it is used. Feel free to correct me if I got it
> >>> wrong.
> >>>
> >>> Regmap seems to be designed for *slow* speed peripherals to improve frequent
> >>> accesses by the SW. It looks like it is used by MFD, SPI and I2C drivers.
> >>>
> >>> It seems to cache the register contents and flush/invalidate them only when
> >>> needed.
> >>>
> >>> The MMIO version seems to be assuming the presence of device-tree like CLK
> >>> API which doesn't exist on ACPI systems and is not portable.
> >>>
> >>> My reaction is that it is a lot of code with no added functionality to what
> >>> HIDMA driver is trying to achieve.
> >>>
> >>> Given that the use case here is only for debug purposes; I think it is OK
> >>> to keep this runtime call here. I don't want to add any overhead into the
> >>> existing code just to support the debug use case.
> >>>
> >>> None of my register read/writes are slow. This file will only be used to
> >>> troubleshoot customer issues.
> >>
> >> $ is always faster than MMIO. This way you can give reg contents to users
> >> without waking up hw.
> >>
> >> Also we at Intel use regmap on ACPI systems without CLK API
> > 
> > I can try and see the performance impact is. What happens to registers that hw updates like status registers. Those will be most interesting during debug. How does remap get updated for those? Is there a way to tell it not to cache certain registers
> 
> My evaluation turned out negative. The regmap code is nice for bus like peripherals
> like I2C and SPI where everything is bitwise accessed. This is not the case
> in this code. 

I do not entirely agree with the statements here, it does give big benefit
on our systems with MMIO. I am going to ask Mark to comment on this, he
know better and understands ARM.

I am probably going to be okay with this not using regmap and it is debug
but you should give that a try in future for better performance and ofcourse
you can add to regmap to get a better model for your device

> Regmap is a nice tool if used properly but it doesn't mean that it will work
> in every single case. It doesn't match with the goal of this driver. 
> 
> As soon as I abstract register accesses, the regmap code writes all MMIO registers
> with the readl variant functions.
> 
> Barriers are really expensive on ARM. I paid very special attention in the 
> code to decide when to use relaxed version vs. the readl version. I lose 
> all of this optimization. 
> 
> Since the clocks are restored only during the debug case, I don't see any
> problems here. It is not worth the effort to do redo the whole thing and 
> introduce errors as I see a lot of tripping points like regmap_sync variants.

-- 
~Vinod


From vinod.koul at intel.com  Mon May  2 02:30:15 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Mon, 2 May 2016 15:00:15 +0530
Subject: [PATCH 03/18] dmaengine: st_fdma: Add STMicroelectronics FDMA
 engine driver support
In-Reply-To: <20160427125923.GA12756@griffinp-ThinkPad-X1-Carbon-2nd>
References: <1461236675-10176-1-git-send-email-peter.griffin@linaro.org>
 <1461236675-10176-4-git-send-email-peter.griffin@linaro.org>
 <20160426165622.GR2274@localhost>
 <20160427125923.GA12756@griffinp-ThinkPad-X1-Carbon-2nd>
Message-ID: <20160502093015.GD2274@localhost>

On Wed, Apr 27, 2016 at 01:59:23PM +0100, Peter Griffin wrote:
> > bunch of this seems similar to cyclic case, can you create common setup
> > routine for these, anyway cyclic is a special cases of slave_sg
> 
> In v4 I've made a st_fdma_prep_common() which abstracts out all the common
> checks at the beginning of the *_prep*() functions.
> 
> In v3 fill_fw_node() is already (from one of your previous reviews)
> abstracting out all the common parts from these loops. So everything
> that is now left is actually differences between the two setups.
> 
> Is that Ok?

Sounds better

> > and you irq is still enabled and tasklets can be scheduled!!
> > 
> Eeek! Very good point. Also looking at some other drivers we
> should be doing a of_dma_controller_free() and
> dma_async_device_unregister().
> 
> So something like this: -
> 
>   st_fdma_disable(); /*disables irqs*/
>   of_dma_controller_free(pdev->dev.of_node);
>   dma_async_device_unregister(&priv->slave);
>   st_fdma_clk_disable(fdev);

you can call devm_free_irq() explictyly, that will syncronize irq and
free it up. Also you should kill the tasklet afterwards.

-- 
~Vinod


From vinod.koul at intel.com  Mon May  2 02:39:09 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Mon, 2 May 2016 15:09:09 +0530
Subject: [PATCH V2] dmaengine: bcm2835: fix typo/added newline in
 legacy-mode warning message
In-Reply-To: <1461309168-21221-1-git-send-email-kernel@martin.sperl.org>
References: <1461309168-21221-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <20160502093909.GF2274@localhost>

On Fri, Apr 22, 2016 at 07:12:48AM +0000, kernel at martin.sperl.org wrote:
> From: Martin Sperl <kernel at martin.sperl.org>
> 
> Fix typo in warning message that there is no "interrupt-names"
> property defined in the device-tree and legacy-mode is used.
> 
> Also added newline to end of message.

Applied, thanks

-- 
~Vinod


From vinod.koul at intel.com  Mon May  2 02:52:15 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Mon, 2 May 2016 15:22:15 +0530
Subject: [PATCH v4 0/3] dmaengine: Add clock support for AXI DMAS
In-Reply-To: <1461305630-4826-1-git-send-email-appanad@xilinx.com>
References: <1461305630-4826-1-git-send-email-appanad@xilinx.com>
Message-ID: <20160502095214.GG2274@localhost>

On Fri, Apr 22, 2016 at 11:43:47AM +0530, Kedareswara rao Appana wrote:
> This patch series adds basic clock support for AXI DMAS
> This patch series is created on top of the
> "dmaengine: vdma: AXI DMA's enhancments" patch series.

This fails due to above series not merged. Please resubmit once that one is
merged

-- 
~Vinod


From k.kozlowski at samsung.com  Mon May  2 02:49:12 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 02 May 2016 11:49:12 +0200
Subject: [RFT PATCH 1/3] usb: misc: usb3503: Fix HUB mode after bootloader
 initialization
In-Reply-To: <20160429164448.GY3217@sirena.org.uk>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <1461927591-7864-2-git-send-email-k.kozlowski@samsung.com>
 <20160429113059.GX3217@sirena.org.uk> <57234BA2.6020304@samsung.com>
 <20160429164448.GY3217@sirena.org.uk>
Message-ID: <57272298.50701@samsung.com>

On 04/29/2016 06:44 PM, Mark Brown wrote:
> On Fri, Apr 29, 2016 at 01:55:14PM +0200, Krzysztof Kozlowski wrote:
>> On 04/29/2016 01:30 PM, Mark Brown wrote:
> 
>>> Supplies are only optional if they may be physically absent.  In this
>>> case it's possible that on device regulators may be used instead, a
>>> pattern more like that used for arizona-ldo1 where we represent those
>>> regulators might be better as it's more clearly describing the
>>> situation.  I'm just wondering if the supply lookup stuff there should
>>> be factored out as this is not an uncommon pattern..
> 
>>> It should at least be clearly stated what's going on, ignoring failure
>>> to get supplies is generally a bug and people will tend to blindly cut
>>> and paste things (witness all the breakage in graphics drivers with
>>> this).
> 
>> The VDD33 is really optional. The device can work in different
>> configuration, e.g. only on VBAT. How the reset logic would work then? I
>> don't know... I would suspect that it could be exactly the same (just
>> replace VDD33 with VBAT) but I am not sure.
> 
> What the Arizona example I mentioned does is look for the property
> specifying an external supply in DT and if there isn't one assumes that
> it must be using the internal regulator.  That's a bit icky but it does
> the right thing and is much simpler from a user point of view.

Okay, that indeed looks similar... in case of lack of external supplies
the usb3503 pins should be tied to the internal regulators.

However it seems I was wrong at the beginning. We've been looking here
at the schematics and the datasheet. The design is unfortunately a
little bit confusing but finally I think we got the impression how does
it work.

This VDD regulator supply actually is not a usb3503 USB HUB regulator
supply... but a supply to the LAN attached to this HUB. Regulator off/on
is needed for LAN to show up. The hub will show up with typical reset
(which is also missing before my patchset btw).

The LAN, as a USB device, is auto-probed so it cannot take the regulator
and play with it. The simplest idea I have is to add it as "external
supply"  to the parent: usb3503.

Best regards,
Krzysztof



From appana.durga.rao at xilinx.com  Mon May  2 02:57:47 2016
From: appana.durga.rao at xilinx.com (Appana Durga Kedareswara Rao)
Date: Mon, 2 May 2016 09:57:47 +0000
Subject: [PATCH v4 0/3] dmaengine: Add clock support for AXI DMAS
In-Reply-To: <20160502095214.GG2274@localhost>
References: <1461305630-4826-1-git-send-email-appanad@xilinx.com>
 <20160502095214.GG2274@localhost>
Message-ID: <C246CAC1457055469EF09E3A7AC4E11A4A57D3C8@XAP-PVEXMBX01.xlnx.xilinx.com>

Hi Vinod,

	

> -----Original Message-----
> From: dmaengine-owner at vger.kernel.org [mailto:dmaengine-
> owner at vger.kernel.org] On Behalf Of Vinod Koul
> Sent: Monday, May 02, 2016 3:22 PM
> To: Appana Durga Kedareswara Rao <appanad at xilinx.com>
> Cc: robh+dt at kernel.org; pawel.moll at arm.com; mark.rutland at arm.com;
> ijc+devicetree at hellion.org.uk; galak at codeaurora.org; Michal Simek
> <michals at xilinx.com>; Soren Brinkmann <sorenb at xilinx.com>;
> dan.j.williams at intel.com; Appana Durga Kedareswara Rao
> <appanad at xilinx.com>; moritz.fischer at ettus.com;
> laurent.pinchart at ideasonboard.com; luis at debethencourt.com; Anirudha
> Sarangi <anirudh at xilinx.com>; Punnaiah Choudary Kalluri
> <punnaia at xilinx.com>; Shubhrajyoti Datta <shubhraj at xilinx.com>;
> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-
> kernel at vger.kernel.org; dmaengine at vger.kernel.org
> Subject: Re: [PATCH v4 0/3] dmaengine: Add clock support for AXI DMAS
> 
> On Fri, Apr 22, 2016 at 11:43:47AM +0530, Kedareswara rao Appana wrote:
> > This patch series adds basic clock support for AXI DMAS This patch
> > series is created on top of the
> > "dmaengine: vdma: AXI DMA's enhancments" patch series.
> 
> This fails due to above series not merged. Please resubmit once that one is
> merged

Ok sure will resend once the above series got merged...

Regards,
Kedar.

> 
> --
> ~Vinod
> --
> To unsubscribe from this list: send the line "unsubscribe dmaengine" in the body
> of a message to majordomo at vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html


From vinod.koul at intel.com  Mon May  2 03:09:53 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Mon, 2 May 2016 15:39:53 +0530
Subject: [PATCH v7 1/2] Documentation: DT: dma: Add Xilinx zynqmp dma
 device tree binding documentation
In-Reply-To: <5721D38A.8010501@metafoo.de>
References: <1461740729-30715-1-git-send-email-appanad@xilinx.com>
 <57206632.7010508@metafoo.de>
 <C246CAC1457055469EF09E3A7AC4E11A4A57B840@XAP-PVEXMBX01.xlnx.xilinx.com>
 <5720B333.4000804@metafoo.de>
 <C246CAC1457055469EF09E3A7AC4E11A4A57C2E2@XAP-PVEXMBX01.xlnx.xilinx.com>
 <5721D38A.8010501@metafoo.de>
Message-ID: <20160502100953.GJ2274@localhost>

On Thu, Apr 28, 2016 at 11:10:34AM +0200, Lars-Peter Clausen wrote:
> >> -----Original Message-----
> >> From: Lars-Peter Clausen [mailto:lars at metafoo.de]
> >> Sent: Wednesday, April 27, 2016 6:10 PM
> >> To: Appana Durga Kedareswara Rao <appanad at xilinx.com>;
> >> robh+dt at kernel.org; pawel.moll at arm.com; mark.rutland at arm.com;
> >> ijc+devicetree at hellion.org.uk; galak at codeaurora.org; Michal Simek
> >> <michals at xilinx.com>; Soren Brinkmann <sorenb at xilinx.com>;
> >> vinod.koul at intel.com; dan.j.williams at intel.com; moritz.fischer at ettus.com;
> >> laurent.pinchart at ideasonboard.com; luis at debethencourt.com; Anirudha
> >> Sarangi <anirudh at xilinx.com>; Punnaiah Choudary Kalluri
> >> <punnaia at xilinx.com>
> >> Cc: devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-
> >> kernel at vger.kernel.org; dmaengine at vger.kernel.org
> >> Subject: Re: [PATCH v7 1/2] Documentation: DT: dma: Add Xilinx zynqmp dma
> >> device tree binding documentation
> >>
> >> On 04/27/2016 09:33 AM, Appana Durga Kedareswara Rao wrote:
> >>> Hi Lars,
> >>>
> >>>> -----Original Message-----
> >>>> From: Lars-Peter Clausen [mailto:lars at metafoo.de]
> >>>> Sent: Wednesday, April 27, 2016 12:42 PM
> >>>> To: Appana Durga Kedareswara Rao <appanad at xilinx.com>;
> >>>> robh+dt at kernel.org; pawel.moll at arm.com; mark.rutland at arm.com;
> >>>> ijc+devicetree at hellion.org.uk; galak at codeaurora.org; Michal Simek
> >>>> <michals at xilinx.com>; Soren Brinkmann <sorenb at xilinx.com>;
> >>>> vinod.koul at intel.com; dan.j.williams at intel.com; Appana Durga
> >>>> Kedareswara Rao <appanad at xilinx.com>; moritz.fischer at ettus.com;
> >>>> laurent.pinchart at ideasonboard.com; luis at debethencourt.com; Anirudha
> >>>> Sarangi <anirudh at xilinx.com>; Punnaiah Choudary Kalluri
> >>>> <punnaia at xilinx.com>
> >>>> Cc: devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> >>>> linux- kernel at vger.kernel.org; dmaengine at vger.kernel.org
> >>>> Subject: Re: [PATCH v7 1/2] Documentation: DT: dma: Add Xilinx zynqmp

PLEASE strip the crap from your MUA, better use a linux MUA


> >>>>> +- xlnx,include-sg	: Indicates the controller to operate in simple or
> >>>>> +			  scatter gather dma mode
> >>>>> +- xlnx,ratectrl		: Scheduling interval in terms of clock cycles for
> >>>>> +			  source AXI transaction
> >>>>> +- xlnx,overfetch	: Tells whether the channel is allowed to over
> >>>>> +			  fetch the data
> >>>>> +- xlnx,src-issue	: Number of AXI outstanding transactions on source
> >>>> side
> >>>>> +- xlnx,src-burst-len	: AXI length for data read. Support only power of
> >>>>> +			  2 byte values.
> >>>>> +- xlnx,dst-burst-len	: AXI length for data write. Support only power of
> >>>>
> >>>> These are all software runtime configuration parameters that you'd
> >>>> want to change at runtime depending on which peripheral you are
> >>>> targeting with a specific DMA transfer. These really do not belong into the
> >> devicetree.
> >>>
> >>> You mean to have a separate config structure in the driver and handle
> >>> the above parameters Through that structure???
> >>>
> >>> I understand that above will work for slave dma transfer types what
> >>> about memory to memory Transfers where we don't have provision to the use
> >> this parameters...
> >>
> >> These parameters are just as application specific as e.g. the DMA
> >> source/destination address or the DMA transfer length. If you want to use the
> >> DMA controller in a different configuration you'd have to re-compile the DTB
> >> and reboot your board, that is not really practical. Especially considering that
> >> you'd typically have multiple applications using the DMA controller in different
> >> configurations concurrently. In general if I have to reconfigure the DT depending
> >> on what application software is running something is fundamentally broken.
> >>
> >> Derive these parameters at runtime depending on the requested transfer. E.g.
> >> some transfer types only work in SG mode, others only work in non-SG modes.
> >> For those which can work in both modes choose the one that is more efficient.
> >> Similar for the other parameters.
> > 
> > Ok will fix in the next version...
> > Will use module_params for the above properties.
> 
> Sorry, but that is just as broken. You need to derive those parameters from
> the DMA transfer as they are transfer specific.

Right, for memcpy you should derive the parameters. Frankly burst size
and lengths, rate control should be set to maximun to achives best
performance on mecpy.  People want memcpy to be done asap

-- 
~Vinod


From linux at arm.linux.org.uk  Mon May  2 03:10:30 2016
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 2 May 2016 11:10:30 +0100
Subject: [PATCH 06/12] ARM: kexec: advertise location of bootable RAM
In-Reply-To: <CAHB_Guq+w7JKXEpLHkefMaYuYowh7dqsdvxgG_dnGv-GdkX39A@mail.gmail.com>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <E1aviF4-0000jG-MO@rmk-PC.arm.linux.org.uk>
 <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <20160429180024.GS19428@n2100.arm.linux.org.uk>
 <CAHB_GuqhPJ7J-MNbjxqeQnogW-J6=Bt2e1STKSG5kzJT+4PJpg@mail.gmail.com>
 <20160430082055.GG19428@n2100.arm.linux.org.uk>
 <CAHB_Guq+w7JKXEpLHkefMaYuYowh7dqsdvxgG_dnGv-GdkX39A@mail.gmail.com>
Message-ID: <20160502101030.GK19428@n2100.arm.linux.org.uk>

On Mon, May 02, 2016 at 01:04:28PM +0530, Pratyush Anand wrote:
> On Sat, Apr 30, 2016 at 1:50 PM, Russell King - ARM Linux
> <linux at arm.linux.org.uk> wrote:
> > On Sat, Apr 30, 2016 at 08:57:34AM +0530, Pratyush Anand wrote:
> >> On Fri, Apr 29, 2016 at 11:30 PM, Russell King - ARM Linux
> >> <linux at arm.linux.org.uk> wrote:
> >> > On Fri, Apr 29, 2016 at 08:26:00PM +0530, Pratyush Anand wrote:
> >> >> Hi Russell,
> >> >>
> >> >> On Thu, Apr 28, 2016 at 2:58 PM, Russell King
> >> >> <rmk+kernel at arm.linux.org.uk> wrote:
> >> >> > Advertise the location of bootable RAM to kexec-tools.  kexec needs to
> >> >> > know where it can place the kernel in RAM, and so be executable when
> >> >> > the system needs to jump into it.
> >> >> >
> >> >> > Advertise these areas in /proc/iomem with a "System RAM (boot alias)"
> >> >> > tag.
> >> >> >
> >> >> > Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
> >> >>
> >> >> Can you please also share git tree path of corresponding kexec-tools changes?
> >> >>
> >> >> Could it be a better idea (if things in user space become simpler)
> >> >> that in stead of patch 5 and 6, we pass arch_phys_to_idmap_offset to
> >> >> user space, and then user space manipulates existing "Crash kernel"
> >> >> and "System RAM" resources.
> >> >
> >> > Given that it's only _one_ platform right now, I don't think that
> >> > additional complexity is worth it.  It means that we have to invent
> >>
> >> Probably, I could not communicate it well.  I was not trying  to have
> >> *additional* complexity. Wanted to see if things could be simpler
> >> rather. So this is what my understanding was:
> >> -- We create one patch to pass arch_phys_to_idmap_offset to user space
> >> (say in /sys/kernel/bootmem_idmap_offset)
> >> -- We do not use patch 5,6,11 and 12 of this series. Probably few more
> >> content of the series will go away.
> >
> > Patches 11 and 12 don't go away with what you're suggesting.  Patches
> > 11 and 12 are necessary to allow the boot-view addresses to be passed
> > into the kernel through kexec, and to allow kexec to find appropriate
> > memory resources.
> 
> But once we would have manipulated "start" and "end" of "Crash Kernel"
> and "System RAM" resources in user space using
> /sys/kernel/bootmem_idmap_offset , then kernel through kexec system
> call would have already receive boot-view addresses, no?

Correct, but that's still a problem for all the reasons I gave in the
email to which you replied to.

I'm not sure where the misunderstanding is.

Let me repeat: even if we do what you're suggesting, patches 11 and 12
do *not* go away.  I've explained in detail why each of the changes are
necessary (which you have cut from your reply.)

In other words: exporting this offset via
/sys/kernel/bootmem_idmap_offset is technically inferior to the solution
I have come up with here, and it saves very little complexity and code.

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From vinod.koul at intel.com  Mon May  2 03:29:20 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Mon, 2 May 2016 15:59:20 +0530
Subject: [PATCH v6 0/3] dmaengine: sun6i: Upgrade for audio transfers
In-Reply-To: <cover.1461856751.git.moinejf@free.fr>
References: <cover.1461856751.git.moinejf@free.fr>
Message-ID: <20160502102920.GK2274@localhost>

On Thu, Apr 28, 2016 at 05:19:11PM +0200, Jean-Francois Moine wrote:
> This patch series contains most of the remaining changes to
> the sun6i DMA driver for audio streaming (tested in
> a Allwinner H3 - Orange PI 2).
> The lacking patch (Add 4 as a possible burst value for H3) will be
> submitted when a consensus with Maxime Ripard will be found.
> This series is based on the previous patches applied by Vinod Koul.

Applied, thanks

-- 
~Vinod


From sr at denx.de  Mon May  2 03:33:21 2016
From: sr at denx.de (Stefan Roese)
Date: Mon, 2 May 2016 12:33:21 +0200
Subject: [PATCH v6] spi: orion.c: Add direct access mode
In-Reply-To: <8919835.yGyvx4h0Tr@wuerfel>
References: <1461147068-4829-1-git-send-email-sr@denx.de>
 <5726F7F3.9070700@denx.de> <8919835.yGyvx4h0Tr@wuerfel>
Message-ID: <57272CF1.9060706@denx.de>

Hi Arnd,

On 02.05.2016 09:28, Arnd Bergmann wrote:
> On Monday 02 May 2016 08:47:15 Stefan Roese wrote:
>> On 20.04.2016 12:11, Stefan Roese wrote:
>>> This patch adds support for the direct write mode to the Orion SPI
>>> driver which is used on the Marvell Armada based SoCs. In this direct
>>> mode, all data written to (or read from) a specifically mapped MBus
>>> window (linked to one SPI chip-select on one of the SPI controllers)
>>> will be transferred directly to the SPI bus. Without the need to control
>>> the SPI registers in between. This can improve the SPI transfer rate in
>>> such cases.
>>>
>>> Currently only the direct write mode is supported. This mode especially
>>> benefits from the SPI direct mode, as the data bytes are written
>>> head-to-head to the SPI bus, without any additional addresses, that
>>> are also written in the direct read mode.
>>>
>>> One use-case for this direct write mode is, programming a FPGA bitstream
>>> image into the FPGA connected to the SPI bus at maximum speed.
>>>
>>> This mode is described in chapter "22.5.2 Direct Write to SPI" in the
>>> Marvell Armada XP Functional Spec Datasheet.
>>>
>>> It should be possible to support SPI-NOR and SPI-NAND devices via
>>> this direct access mode as well. But this needs further work, e.g.:
>>> - The mapping of the MBus window needs to get extended to span
>>>     the complete flash device size
>>> - The address / control data needs to get inserted into the SPI
>>>     controller registers
>>>
>>> Signed-off-by: Stefan Roese <sr at denx.de>
>>> Cc: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
>>> Cc: Gregory CLEMENT <gregory.clement at free-electrons.com>
>>> Cc: Andrew Lunn <andrew at lunn.ch>
>>> Cc: Arnd Bergmann <arnd at arndb.de>
>>> Cc: Mark Brown <broonie at kernel.org>
>>
>> Its been a while since v6 of this direct write access mode has been
>> posted. This is a gentle ping on its status.
>>
>> Arnd / Mark, do you have any additional change requests or are you okay
>> with the current version?
> 
> No objections, please add
> 
> Acked-by: Arnd Bergmann <arnd at arndb.de>

Thanks.
 
> Two questions though:
> 
> - you now always send a multiple of four byte in each transfer, are
>    there any downsides in doing this, e.g. some SPI devices that might
>    get confused by receiving additional uninitialized data?

Yes, this is something that might happen on such devices. AFAIK, my
device (Altera FPGA) has no such restriction though. IIRC, the
size of the bitfiles is always 4-byte aligned.

I'll try to send v7 of this patch with a fully byte-size correct 
handling later today.
 
> - How does the performance compare to the normal mode, is it basically
>    unchanged, or does this patch make things faster?

The performance is increased. The factor of course depends on the SPI
transfer speed. Here the numbers for a ~70KiB image transferred at
27MHz SPI speed:

Using the PIO SPI transfer:

real    0m0.128s
user    0m0.010s
sys     0m0.120s

Using the direct write mode:

real    0m0.040s
user    0m0.000s
sys     0m0.020s

Thanks,
Stefan


From broonie at kernel.org  Mon May  2 03:40:49 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 2 May 2016 11:40:49 +0100
Subject: [PATCH V17 2/3] dmaengine: qcom_hidma: add debugfs hooks
In-Reply-To: <20160502092552.GC2274@localhost>
References: <1460384473-5775-1-git-send-email-okaya@codeaurora.org>
 <1460384473-5775-3-git-send-email-okaya@codeaurora.org>
 <20160426033029.GB2274@localhost>
 <b068ead6474f2ffee5acef9ea799aba3@codeaurora.org>
 <20160426162529.GK2274@localhost> <571F9D76.2060809@codeaurora.org>
 <20160427081501.GV2274@localhost>
 <2c7ac0732fb16f952db24b7c70065318@codeaurora.org>
 <57258799.70803@codeaurora.org> <20160502092552.GC2274@localhost>
Message-ID: <20160502104049.GB6292@sirena.org.uk>

On Mon, May 02, 2016 at 02:55:52PM +0530, Vinod Koul wrote:
> On Sun, May 01, 2016 at 12:35:37AM -0400, Sinan Kaya wrote:

> > My evaluation turned out negative. The regmap code is nice for bus like peripherals
> > like I2C and SPI where everything is bitwise accessed. This is not the case
> > in this code. 

> I do not entirely agree with the statements here, it does give big benefit
> on our systems with MMIO. I am going to ask Mark to comment on this, he
> know better and understands ARM.

> I am probably going to be okay with this not using regmap and it is debug
> but you should give that a try in future for better performance and ofcourse
> you can add to regmap to get a better model for your device

I've no idea what "this" is, sorry.  All I've got here is an enormous
backtrace with a bunch of the messages not even word wrapped.

Please be aware that I get CCed on so much irrelevant crap that copying
me into the middle of a thread about some other subsystem is likely to
get missed - almost always it's review of some patch I've got no
interest in.

> > Barriers are really expensive on ARM. I paid very special attention in the 
> > code to decide when to use relaxed version vs. the readl version. I lose 
> > all of this optimization. 

Drivers should not be using the relaxed accessors, they are there for
the generic code to build on not for drivers and they really need the
cache flush operations.  Getting the cache flush operations right,
especially on ARM, isn't easy and needs detailed review.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/15836f4d/attachment.sig>

From broonie at kernel.org  Mon May  2 03:41:54 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 2 May 2016 11:41:54 +0100
Subject: [PATCH v3 5/7] ASoc: omap-mcbsp: Rename
 omap_mcbsp_sysfs_remove() to omap_mcbsp_cleanup()
In-Reply-To: <1461927202-17677-6-git-send-email-peter.ujfalusi@ti.com>
References: <1461927202-17677-1-git-send-email-peter.ujfalusi@ti.com>
 <1461927202-17677-6-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <20160502104154.GC6292@sirena.org.uk>

On Fri, Apr 29, 2016 at 01:53:20PM +0300, Peter Ujfalusi wrote:
> The function will do more then removing the sysfs files in the future.

Please fix the subject line but otherwise this looks OK.

Acked-by: Mark Brown <broonie at kernel.org>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/95287bcb/attachment.sig>

From broonie at kernel.org  Mon May  2 03:42:13 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 2 May 2016 11:42:13 +0100
Subject: [PATCH v3 6/7] ASoC: omap-mcbsp: sidetone: Use the new callback
 for iclk handling
In-Reply-To: <1461927202-17677-7-git-send-email-peter.ujfalusi@ti.com>
References: <1461927202-17677-1-git-send-email-peter.ujfalusi@ti.com>
 <1461927202-17677-7-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <20160502104213.GD6292@sirena.org.uk>

On Fri, Apr 29, 2016 at 01:53:21PM +0300, Peter Ujfalusi wrote:
> The McBSP sidetone (in OMAP3 McBSP2 and 3 module) is working with the
> module's interface clock. When the sidetone is enabled the iclk must not
> idle because it will result in choppy sidetone.

Acked-by: Mark Brown <broonie at kernel.org>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/4fc40c4e/attachment.sig>

From panand at redhat.com  Mon May  2 03:48:47 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 2 May 2016 16:18:47 +0530
Subject: [PATCH 06/12] ARM: kexec: advertise location of bootable RAM
In-Reply-To: <20160502101030.GK19428@n2100.arm.linux.org.uk>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <E1aviF4-0000jG-MO@rmk-PC.arm.linux.org.uk>
 <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <20160429180024.GS19428@n2100.arm.linux.org.uk>
 <CAHB_GuqhPJ7J-MNbjxqeQnogW-J6=Bt2e1STKSG5kzJT+4PJpg@mail.gmail.com>
 <20160430082055.GG19428@n2100.arm.linux.org.uk>
 <CAHB_Guq+w7JKXEpLHkefMaYuYowh7dqsdvxgG_dnGv-GdkX39A@mail.gmail.com>
 <20160502101030.GK19428@n2100.arm.linux.org.uk>
Message-ID: <CAHB_GuoUcVPexeaHzZ6O1bVTSksd39jVZpO63+jX=rACEe1QsA@mail.gmail.com>

On Mon, May 2, 2016 at 3:40 PM, Russell King - ARM Linux
<linux at arm.linux.org.uk> wrote:
> On Mon, May 02, 2016 at 01:04:28PM +0530, Pratyush Anand wrote:
>> On Sat, Apr 30, 2016 at 1:50 PM, Russell King - ARM Linux
>> <linux at arm.linux.org.uk> wrote:
>> > On Sat, Apr 30, 2016 at 08:57:34AM +0530, Pratyush Anand wrote:
>> >> On Fri, Apr 29, 2016 at 11:30 PM, Russell King - ARM Linux
>> >> <linux at arm.linux.org.uk> wrote:
>> >> > On Fri, Apr 29, 2016 at 08:26:00PM +0530, Pratyush Anand wrote:
>> >> >> Hi Russell,
>> >> >>
>> >> >> On Thu, Apr 28, 2016 at 2:58 PM, Russell King
>> >> >> <rmk+kernel at arm.linux.org.uk> wrote:
>> >> >> > Advertise the location of bootable RAM to kexec-tools.  kexec needs to
>> >> >> > know where it can place the kernel in RAM, and so be executable when
>> >> >> > the system needs to jump into it.
>> >> >> >
>> >> >> > Advertise these areas in /proc/iomem with a "System RAM (boot alias)"
>> >> >> > tag.
>> >> >> >
>> >> >> > Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
>> >> >>
>> >> >> Can you please also share git tree path of corresponding kexec-tools changes?
>> >> >>
>> >> >> Could it be a better idea (if things in user space become simpler)
>> >> >> that in stead of patch 5 and 6, we pass arch_phys_to_idmap_offset to
>> >> >> user space, and then user space manipulates existing "Crash kernel"
>> >> >> and "System RAM" resources.
>> >> >
>> >> > Given that it's only _one_ platform right now, I don't think that
>> >> > additional complexity is worth it.  It means that we have to invent
>> >>
>> >> Probably, I could not communicate it well.  I was not trying  to have
>> >> *additional* complexity. Wanted to see if things could be simpler
>> >> rather. So this is what my understanding was:
>> >> -- We create one patch to pass arch_phys_to_idmap_offset to user space
>> >> (say in /sys/kernel/bootmem_idmap_offset)
>> >> -- We do not use patch 5,6,11 and 12 of this series. Probably few more
>> >> content of the series will go away.
>> >
>> > Patches 11 and 12 don't go away with what you're suggesting.  Patches
>> > 11 and 12 are necessary to allow the boot-view addresses to be passed
>> > into the kernel through kexec, and to allow kexec to find appropriate
>> > memory resources.
>>
>> But once we would have manipulated "start" and "end" of "Crash Kernel"
>> and "System RAM" resources in user space using
>> /sys/kernel/bootmem_idmap_offset , then kernel through kexec system
>> call would have already receive boot-view addresses, no?
>
> Correct, but that's still a problem for all the reasons I gave in the
> email to which you replied to.
>
> I'm not sure where the misunderstanding is.

No, no..there is no misunderstanding. I agreed to your implementation
because that will work for generic cases and for me complete series is
OK.

I just wanted to clarify my understanding, and so was the last argument.

>
> Let me repeat: even if we do what you're suggesting, patches 11 and 12
> do *not* go away.  I've explained in detail why each of the changes are
> necessary (which you have cut from your reply.)
>

Again, it is just for clarifying myself.
I cut the reply because I understood that in patch 11 and 12, you
convert addresses passed by kexec tools from run time view to boot
view using different helpers like phys_to_boot_phys(). So, had kexec
system call passed boot view addresses, we would have not needed 11
and 12. This is what I wanted to clarify.

> In other words: exporting this offset via
> /sys/kernel/bootmem_idmap_offset is technically inferior to the solution
> I have come up with here, and it saves very little complexity and code.

I still have opinion that code will probably be more simple and reduce
significantly, however solution will siege to work the moment
idmap_offset is not a simple additive value.

Therefore, I am OK with your implementation.

~Pratyush


From k.kozlowski at samsung.com  Mon May  2 03:49:16 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 02 May 2016 12:49:16 +0200
Subject: [RFT PATCH 1/3] usb: misc: usb3503: Fix HUB mode after bootloader
 initialization
In-Reply-To: <57272298.50701@samsung.com>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <1461927591-7864-2-git-send-email-k.kozlowski@samsung.com>
 <20160429113059.GX3217@sirena.org.uk> <57234BA2.6020304@samsung.com>
 <20160429164448.GY3217@sirena.org.uk> <57272298.50701@samsung.com>
Message-ID: <572730AC.4030602@samsung.com>

On 05/02/2016 11:49 AM, Krzysztof Kozlowski wrote:
> On 04/29/2016 06:44 PM, Mark Brown wrote:
>> On Fri, Apr 29, 2016 at 01:55:14PM +0200, Krzysztof Kozlowski wrote:
>>> On 04/29/2016 01:30 PM, Mark Brown wrote:
>>
>>>> Supplies are only optional if they may be physically absent.  In this
>>>> case it's possible that on device regulators may be used instead, a
>>>> pattern more like that used for arizona-ldo1 where we represent those
>>>> regulators might be better as it's more clearly describing the
>>>> situation.  I'm just wondering if the supply lookup stuff there should
>>>> be factored out as this is not an uncommon pattern..
>>
>>>> It should at least be clearly stated what's going on, ignoring failure
>>>> to get supplies is generally a bug and people will tend to blindly cut
>>>> and paste things (witness all the breakage in graphics drivers with
>>>> this).
>>
>>> The VDD33 is really optional. The device can work in different
>>> configuration, e.g. only on VBAT. How the reset logic would work then? I
>>> don't know... I would suspect that it could be exactly the same (just
>>> replace VDD33 with VBAT) but I am not sure.
>>
>> What the Arizona example I mentioned does is look for the property
>> specifying an external supply in DT and if there isn't one assumes that
>> it must be using the internal regulator.  That's a bit icky but it does
>> the right thing and is much simpler from a user point of view.
> 
> Okay, that indeed looks similar... in case of lack of external supplies
> the usb3503 pins should be tied to the internal regulators.
> 
> However it seems I was wrong at the beginning. We've been looking here
> at the schematics and the datasheet. The design is unfortunately a
> little bit confusing but finally I think we got the impression how does
> it work.
> 
> This VDD regulator supply actually is not a usb3503 USB HUB regulator
> supply... but a supply to the LAN attached to this HUB. Regulator off/on
> is needed for LAN to show up. The hub will show up with typical reset
> (which is also missing before my patchset btw).
> 
> The LAN, as a USB device, is auto-probed so it cannot take the regulator
> and play with it. The simplest idea I have is to add it as "external
> supply"  to the parent: usb3503.

I run some more tests which adds more confusion. If the usb3503 hub does
not turn off/on the supply (LAN regulator supply in reality) it usually
does not show up as USB device (lsusb) neither. In such case sometimes
it is present, sometimes not.

"Hardware" reset with regulator fixes all the problems: with LAN and
with USB hub... It really does not match the schematics but apparently
usb3503 also needs the regulator.

Best regards,
Krzysztof




From broonie at kernel.org  Mon May  2 03:55:01 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 2 May 2016 11:55:01 +0100
Subject: [RFT PATCH 1/3] usb: misc: usb3503: Fix HUB mode after
 bootloader initialization
In-Reply-To: <57272298.50701@samsung.com>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <1461927591-7864-2-git-send-email-k.kozlowski@samsung.com>
 <20160429113059.GX3217@sirena.org.uk>
 <57234BA2.6020304@samsung.com>
 <20160429164448.GY3217@sirena.org.uk> <57272298.50701@samsung.com>
Message-ID: <20160502105501.GE6292@sirena.org.uk>

On Mon, May 02, 2016 at 11:49:12AM +0200, Krzysztof Kozlowski wrote:

> This VDD regulator supply actually is not a usb3503 USB HUB regulator
> supply... but a supply to the LAN attached to this HUB. Regulator off/on
> is needed for LAN to show up. The hub will show up with typical reset
> (which is also missing before my patchset btw).

> The LAN, as a USB device, is auto-probed so it cannot take the regulator
> and play with it. The simplest idea I have is to add it as "external
> supply"  to the parent: usb3503.

This is common enough that that just isn't going to scale well I fear
without some generic handling, either walking child devices at the bus
level or at the device level with a pre-probe() callback to get the
device to power on.  The latter is more appropriate to things like
Slimbus where the device is more likely to do active management at
runtime, it's not clear people are building USB devices like that.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/7f61db57/attachment.sig>

From maxime.ripard at free-electrons.com  Mon May  2 03:55:46 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 2 May 2016 12:55:46 +0200
Subject: [PATCH 1/1] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
References: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
Message-ID: <20160502105546.GN17159@lukather>

Hi,

On Thu, Apr 28, 2016 at 09:19:58AM +0200, Olliver Schinagl wrote:
> There are 3 kinds of OLinuXino Lime2 boards.
> One without any on board storage, one with NAND storage and one with
> eMMC storage. This patch adds the eMMC variant of boards.
> 
> eMMC storage is different from a regular SD card in that it is soldered
> on the board and cannot be changed. Additionally, it shares pins with
> the NAND module and with the second SPI port.
> 
> Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>

Is it a publicly available board, or is it a private hack you made
yourself?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/16ec5bd4/attachment.sig>

From arnd at arndb.de  Mon May  2 03:59:19 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon,  2 May 2016 12:59:19 +0200
Subject: [PATCH] of: include errno.h in of_graph.h
Message-ID: <1462186769-2205767-1-git-send-email-arnd@arndb.de>

When CONFIG_OF is disabled, we have to include linux/errno.h before
including of_graph.h, or get build errors like in the newly added
sun4i drm driver:

In file included from ../drivers/gpu/drm/sun4i/sun4i_drv.c:14:0:
include/linux/of_graph.h: In function 'of_graph_parse_endpoint':
include/linux/of_graph.h:58:10: error: 'ENOSYS' undeclared (first use in this function)

A better solution is to ensure that the header can be included
by itself, so let's include linux/errno.h here to fix the error
we just got, and any similar future error.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")
---
 include/linux/of_graph.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index f8bcd0e21a26..bb3a5a2cd570 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -15,6 +15,7 @@
 #define __LINUX_OF_GRAPH_H
 
 #include <linux/types.h>
+#include <linux/errno.h>
 
 /**
  * struct of_endpoint - the OF graph endpoint data structure
-- 
2.7.0



From arnd at arndb.de  Mon May  2 03:59:48 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon,  2 May 2016 12:59:48 +0200
Subject: [PATCH] drm/sun4i: add COMMON_CLK dependency
Message-ID: <1462186805-2211918-1-git-send-email-arnd@arndb.de>

The sun4i drm driver uses the clk-provider interfaces, which are not available
when CONFIG_COMMON_CLK is disabled:

drivers/gpu/drm/sun4i/sun4i_dotclock.c:19:16: error: field 'hw' has incomplete type
  struct clk_hw hw;
In file included from ../include/asm-generic/bug.h:13:0,
                 from ../arch/arm/include/asm/bug.h:59,
                 from ../include/linux/bug.h:4,
                 from ../include/linux/io.h:23,
                 from ../include/linux/clk-provider.h:14,
                 from ../drivers/gpu/drm/sun4i/sun4i_dotclock.c:13:
drivers/gpu/drm/sun4i/sun4i_dotclock.c: In function 'hw_to_dclk':
include/linux/kernel.h:831:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
...

This adds a Kconfig dependency to prevent the driver from being enabled
in this case.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")
---
 drivers/gpu/drm/sun4i/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 99510e64e91a..a4b357db8856 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -1,6 +1,6 @@
 config DRM_SUN4I
 	tristate "DRM Support for Allwinner A10 Display Engine"
-	depends on DRM && ARM
+	depends on DRM && ARM && COMMON_CLK
 	depends on ARCH_SUNXI || COMPILE_TEST
 	select DRM_GEM_CMA_HELPER
 	select DRM_KMS_HELPER
-- 
2.7.0



From arnd at arndb.de  Mon May  2 04:00:26 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon,  2 May 2016 13:00:26 +0200
Subject: [PATCH] drm/fsl-dcu: add COMMON_CLK dependency
Message-ID: <1462186839-2224021-1-git-send-email-arnd@arndb.de>

The fsl dcu now uses the clk-provider interfaces, which are not available
when CONFIG_COMMON_CLK is disabled:

drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c: In function 'fsl_dcu_drm_probe':
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c:362:20: error: implicit declaration of function '__clk_get_name' [-Werror=implicit-function-declaration]
  pix_clk_in_name = __clk_get_name(pix_clk_in);

This adds a Kconfig dependency to prevent the driver from being enabled
in this case.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 2d701449bce1 ("drm/fsl-dcu: use common clock framework for pixel clock divider")
---
 drivers/gpu/drm/fsl-dcu/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig
index c78cf3f605d0..b9c714de6e40 100644
--- a/drivers/gpu/drm/fsl-dcu/Kconfig
+++ b/drivers/gpu/drm/fsl-dcu/Kconfig
@@ -1,6 +1,6 @@
 config DRM_FSL_DCU
 	tristate "DRM Support for Freescale DCU"
-	depends on DRM && OF && ARM
+	depends on DRM && OF && ARM && COMMON_CLK
 	select BACKLIGHT_CLASS_DEVICE
 	select BACKLIGHT_LCD_SUPPORT
 	select DRM_KMS_HELPER
-- 
2.7.0



From tn at semihalf.com  Mon May  2 04:03:57 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 2 May 2016 13:03:57 +0200
Subject: [PATCH V6 09/13] pci, acpi: Support for ACPI based generic PCI
 host controller
In-Reply-To: <20160428214800.GG25125@localhost>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-10-git-send-email-tn@semihalf.com>
 <20160428214800.GG25125@localhost>
Message-ID: <5727341D.1080906@semihalf.com>

On 04/28/2016 11:48 PM, Bjorn Helgaas wrote:
> Hey, I really kind of like this.  I think this might work out well.
>
> On Fri, Apr 15, 2016 at 07:06:44PM +0200, Tomasz Nowicki wrote:
>> This patch is going to implement generic PCI host controller for
>> ACPI world, similar to what pci-host-generic.c driver does for DT world.
>>
>> All such drivers, which we have seen so far, were implemented within
>> arch/ directory since they had some arch assumptions (x86 and ia64).
>> However, they all are doing similar thing, so it makes sense to find
>> some common code and abstract it into the generic driver.
>>
>> In order to handle PCI config space regions properly, we define new
>> MCFG interface which parses MCFG table and keep its entries
>> in a list. New pci_mcfg_init call is defined so that we do not depend
>> on PCI_MMCONFIG. Regions are not mapped until host bridge ask for it.
>>
>> The implementation of pci_acpi_scan_root() looks up the saved MCFG entries
>> and sets up a new mapping. Generic PCI functions are used for
>> accessing config space. Driver selects PCI_GENERIC_ECAM and uses functions
>> from drivers/pci/ecam.h to create and access ECAM mappings.
>>
>> As mentioned in Kconfig help section, ACPI_PCI_HOST_GENERIC choice
>> should be made on a per-architecture basis.
>>
>> This patch is heavily based on the updated version from Jayachandran C:
>> https://lkml.org/lkml/2016/4/11/908
>> git: https://github.com/jchandra-brcm/linux/ (arm64-acpi-pci-v3)
>>
>> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
>> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
>> ---
>>   drivers/acpi/Kconfig        |   8 ++
>>   drivers/acpi/Makefile       |   1 +
>>   drivers/acpi/bus.c          |   1 +
>>   drivers/acpi/pci_gen_host.c | 231 ++++++++++++++++++++++++++++++++++++++++++++
>>   include/linux/pci.h         |   6 ++
>>   5 files changed, 247 insertions(+)
>>   create mode 100644 drivers/acpi/pci_gen_host.c
>>
>> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
>> index 183ffa3..70272c5 100644
>> --- a/drivers/acpi/Kconfig
>> +++ b/drivers/acpi/Kconfig
>> @@ -346,6 +346,14 @@ config ACPI_PCI_SLOT
>>   	  i.e., segment/bus/device/function tuples, with physical slots in
>>   	  the system.  If you are unsure, say N.
>>   
>> +config ACPI_PCI_HOST_GENERIC
>> +	bool
>> +	select PCI_GENERIC_ECAM
>> +	help
>> +	  Select this config option from the architecture Kconfig,
>> +	  if it is preferred to enable ACPI PCI host controller driver which
>> +	  has no arch-specific assumptions.
>> +
>>   config X86_PM_TIMER
>>   	bool "Power Management Timer Support" if EXPERT
>>   	depends on X86
>> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
>> index 81e5cbc..b12fa64 100644
>> --- a/drivers/acpi/Makefile
>> +++ b/drivers/acpi/Makefile
>> @@ -40,6 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
>>   acpi-y				+= ec.o
>>   acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
>>   acpi-y				+= pci_root.o pci_link.o pci_irq.o
>> +obj-$(CONFIG_ACPI_PCI_HOST_GENERIC)	+= pci_gen_host.o
> Maybe "pci_root_generic.c" so it shows up next to and is obviously
> related to pci_root.c?

Yes, this is good idea.

>
>>   acpi-y				+= acpi_lpss.o acpi_apd.o
>>   acpi-y				+= acpi_platform.o
>>   acpi-y				+= acpi_pnp.o
>> diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
>> index c068c82..803a1d7 100644
>> --- a/drivers/acpi/bus.c
>> +++ b/drivers/acpi/bus.c
>> @@ -1107,6 +1107,7 @@ static int __init acpi_init(void)
>>   	}
>>   
>>   	pci_mmcfg_late_init();
>> +	pci_mcfg_init();
>>   	acpi_scan_init();
>>   	acpi_ec_init();
>>   	acpi_debugfs_init();
>> diff --git a/drivers/acpi/pci_gen_host.c b/drivers/acpi/pci_gen_host.c
>> new file mode 100644
>> index 0000000..fd360b5
>> --- /dev/null
>> +++ b/drivers/acpi/pci_gen_host.c
>> @@ -0,0 +1,231 @@
>> +/*
>> + * 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 (the "GPL").
>> + *
>> + * 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 version 2 (GPLv2) for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * version 2 (GPLv2) along with this source code.
>> + */
>> +#include <linux/kernel.h>
>> +#include <linux/pci.h>
>> +#include <linux/pci-acpi.h>
>> +#include <linux/sfi_acpi.h>
>> +#include <linux/slab.h>
>> +
>> +#include "../pci/ecam.h"
>> +
>> +#define PREFIX	"ACPI: "
>> +
>> +/* Structure to hold entries from the MCFG table */
>> +struct mcfg_entry {
>> +	struct list_head	list;
>> +	phys_addr_t		addr;
>> +	u16			segment;
>> +	u8			bus_start;
>> +	u8			bus_end;
>> +};
>> +
>> +/* List to save mcfg entries */
>> +static LIST_HEAD(pci_mcfg_list);
>> +static DEFINE_MUTEX(pci_mcfg_lock);
>> +
>> +/* ACPI info for generic ACPI PCI controller */
>> +struct acpi_pci_generic_root_info {
>> +	struct acpi_pci_root_info	common;
>> +	struct pci_config_window	*cfg;	/* config space mapping */
>> +};
>> +
>> +/* Find the entry in mcfg list which contains range bus_start */
>> +static struct mcfg_entry *pci_mcfg_lookup(u16 seg, u8 bus_start)
>> +{
>> +	struct mcfg_entry *e;
>> +
>> +	list_for_each_entry(e, &pci_mcfg_list, list) {
>> +		if (e->segment == seg &&
>> +		    e->bus_start <= bus_start && bus_start <= e->bus_end)
>> +			return e;
>> +	}
>> +
>> +	return NULL;
>> +}
> Can you put the MCFG parsing, caching, and searching in a different
> file, e.g., drivers/acpi/pci_mcfg.c?
I will.
>
>> +/*
>> + * Lookup the bus range for the domain in MCFG, and set up config space
>> + * mapping.
>> + */
>> +static int pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root,
>> +				       struct acpi_pci_generic_root_info *ri)
>> +{
>> +	u16 seg = root->segment;
>> +	u8 bus_start = root->secondary.start;
>> +	u8 bus_end = root->secondary.end;
>> +	struct pci_config_window *cfg;
>> +	struct mcfg_entry *e;
>> +	phys_addr_t addr;
>> +	int err = 0;
>> +
>> +	mutex_lock(&pci_mcfg_lock);
> What does this lock protect?  The pci_mcfg_list should already be
> initialized by the time we get there, and it should be immutable for
> the life of the system.
Right, lock is useless.
>    In fact, I would prefer if we could just
> search the static table itself whenever we need it rather than caching
> it in our own list.  But I don't think we can easily do that because
> acpi_table_parse() is __init.

It is doable. We can implement our MCFG __init parsing handle to do 
necessary sanity checks and then store MCFG table root pointer in 
pci_mcfg.c. Then lookup call would use that pointer to traverse 
available entries on demand.

>
>> +	e = pci_mcfg_lookup(seg, bus_start);
> I would argue that we should check for _CBA first, and fall back to
> MCFG if _CBA doesn't exist.
Agree.
>
>> +	if (!e) {
>> +		addr = acpi_pci_root_get_mcfg_addr(root->device->handle);
> IMO, acpi_pci_root_get_mcfg_addr() is misnamed.  It should be
> acpi_pci_config_base_addr() or similar.  It definitely is not related
> to MCFG.  Not your fault, obviously.
>
>> +		if (addr == 0) {
>> +			pr_err(PREFIX"%04x:%02x-%02x bus range error\n",
>> +			       seg, bus_start, bus_end);
>> +			err = -ENOENT;
>> +			goto err_out;
>> +		}
>> +	} else {
>> +		if (bus_start != e->bus_start) {
>> +			pr_err("%04x:%02x-%02x bus range mismatch %02x\n",
>> +			       seg, bus_start, bus_end, e->bus_start);
>> +			err = -EINVAL;
>> +			goto err_out;
>> +		} else if (bus_end != e->bus_end) {
>> +			pr_warn("%04x:%02x-%02x bus end mismatch %02x\n",
>> +				seg, bus_start, bus_end, e->bus_end);
>> +			bus_end = min(bus_end, e->bus_end);
>> +		}
>> +		addr = e->addr;
>> +	}
> I really don't think you need a lock around this, so you can factor
> out the address lookup into something like:
>
>    addr = acpi_pci_config_base_addr(...);
>    if (addr)
>      return addr;
>
>    return acpi_pci_mcfg_lookup(seg, busn_res);
>
> You can check inside acpi_pci_mcfg_lookup() to make sure the entry you
> find covers the entire [busn_res.start-busn_res.end] range and return
> failure if it doesn't.  At this point, I'm not sure it's worth it to
> truncate the host bridge bus range to match something we find in MCFG.
>
> If the MCFG entry covers *more* than the host bridge range from _CRS,
> that's fine.
Makes sense for me.

>    In any case, we have to be careful with the start address,
> because the MCFG start address is always based on bus 0, but I think
> pci_generic_ecam_create() expects the start address based on the
> bus_start you pass to it.

We will have a look how to fix this.
>
>> +
>> +	cfg = pci_generic_ecam_create(&root->device->dev, addr, bus_start,
>> +				      bus_end, &pci_generic_ecam_default_ops);
>> +	if (IS_ERR(cfg)) {
>> +		err = PTR_ERR(cfg);
>> +		pr_err("%04x:%02x-%02x error %d mapping CAM\n", seg,
>> +			bus_start, bus_end, err);
>> +		goto err_out;
>> +	}
>> +
>> +	cfg->domain = seg;
>> +	ri->cfg = cfg;
>> +err_out:
>> +	mutex_unlock(&pci_mcfg_lock);
>> +	return err;
>> +}
>> +
>> +/* release_info: free resrouces allocated by init_info */
>> +static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci)
>> +{
>> +	struct acpi_pci_generic_root_info *ri;
>> +
>> +	ri = container_of(ci, struct acpi_pci_generic_root_info, common);
>> +	pci_generic_ecam_free(ri->cfg);
>> +	kfree(ri);
>> +}
>> +
>> +static struct acpi_pci_root_ops acpi_pci_root_ops = {
>> +	.release_info = pci_acpi_generic_release_info,
>> +};
>> +
>> +/* Interface called from ACPI code to setup PCI host controller */
>> +struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>> +{
>> +	int node = acpi_get_node(root->device->handle);
>> +	struct acpi_pci_generic_root_info *ri;
>> +	struct pci_bus *bus, *child;
>> +	int err;
>> +
>> +	ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node);
>> +	if (!ri)
>> +		return NULL;
>> +
>> +	err = pci_acpi_setup_ecam_mapping(root, ri);
>> +	if (err)
>> +		return NULL;
>> +
>> +	acpi_pci_root_ops.pci_ops = &ri->cfg->ops->pci_ops;
>> +	bus = acpi_pci_root_create(root, &acpi_pci_root_ops, &ri->common,
>> +				   ri->cfg);
>> +	if (!bus)
>> +		return NULL;
>> +
>> +	pci_bus_size_bridges(bus);
>> +	pci_bus_assign_resources(bus);
>> +
>> +	list_for_each_entry(child, &bus->children, node)
>> +		pcie_bus_configure_settings(child);
>> +
>> +	return bus;
>> +}
>> +
>> +/* handle MCFG table entries */
>> +static __init int pci_mcfg_parse(struct acpi_table_header *header)
>> +{
>> +	struct acpi_table_mcfg *mcfg;
>> +	struct acpi_mcfg_allocation *mptr;
>> +	struct mcfg_entry *e, *arr;
>> +	int i, n;
>> +
>> +	if (!header)
>> +		return -EINVAL;
>> +
>> +	mcfg = (struct acpi_table_mcfg *)header;
>> +	mptr = (struct acpi_mcfg_allocation *) &mcfg[1];
>> +	n = (header->length - sizeof(*mcfg)) / sizeof(*mptr);
>> +	if (n <= 0 || n > 255) {
>> +		pr_err(PREFIX " MCFG has incorrect entries (%d).\n", n);
>> +		return -EINVAL;
>> +	}
>> +
>> +	arr = kcalloc(n, sizeof(*arr), GFP_KERNEL);
>> +	if (!arr)
>> +		return -ENOMEM;
>> +
>> +	for (i = 0, e = arr; i < n; i++, mptr++, e++) {
>> +		e->segment = mptr->pci_segment;
>> +		e->addr =  mptr->address;
>> +		e->bus_start = mptr->start_bus_number;
>> +		e->bus_end = mptr->end_bus_number;
>> +		list_add(&e->list, &pci_mcfg_list);
>> +		pr_info(PREFIX
>> +			"MCFG entry for domain %04x [bus %02x-%02x] (base %pa)\n",
>> +			e->segment, e->bus_start, e->bus_end, &e->addr);
> Ah, this is information similar to what I suggested we might print in
> pci_generic_ecam_create().  Could go either way, but personally I
> think I'd put it in pci_generic_ecam_create() instead, because then we
> only print the info we're actually using.  And I think it'd be nice to
> have the actual MMIO resource ("[mem 0x...-0x...]") instead of just
> the base.

Giving above that I will drop MCFG entries cache, this will be printed 
in pci_generic_ecam_create, as you suggested.
>
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +/* Interface called by ACPI - parse and save MCFG table */
>> +void __init pci_mcfg_init(void)
>> +{
>> +	int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse);
>> +	if (err)
>> +		pr_err(PREFIX "Failed to parse MCFG (%d)\n", err);
>> +	else if (list_empty(&pci_mcfg_list))
>> +		pr_info(PREFIX "No valid entries in MCFG table.\n");
>> +	else {
>> +		struct mcfg_entry *e;
>> +		int i = 0;
>> +		list_for_each_entry(e, &pci_mcfg_list, list)
>> +			i++;
>> +		pr_info(PREFIX "MCFG table loaded, %d entries\n", i);
>> +	}
>> +}
>> +
>> +/* Raw operations, works only for MCFG entries with an associated bus */
> Can you elaborate a little on the connection with MCFG?  I don't quite
> see how they're related.  Obviously the device has to be on a bus
> we've already enumerated and assigned bus->ops for, but it seems like
> we don't really know or care what bus->ops actually is.  Given that
> these are in this file, acpi_pci_root_ops is the only possibility,
> since that's what we pass to acpi_pci_root_create(), but it doesn't
> seem worth mentioning specifically in a comment.

Yes, you are right. I will drop this comment.

>
>> +int raw_pci_read(unsigned int domain, unsigned int busn, unsigned int devfn,
>> +		 int reg, int len, u32 *val)
>> +{
>> +	struct pci_bus *bus = pci_find_bus(domain, busn);
>> +
>> +	if (!bus)
>> +		return PCIBIOS_DEVICE_NOT_FOUND;
>> +	return bus->ops->read(bus, devfn, reg, len, val);
>> +}
>> +
>> +int raw_pci_write(unsigned int domain, unsigned int busn, unsigned int devfn,
>> +		  int reg, int len, u32 val)
>> +{
>> +	struct pci_bus *bus = pci_find_bus(domain, busn);
>> +
>> +	if (!bus)
>> +		return PCIBIOS_DEVICE_NOT_FOUND;
>> +	return bus->ops->write(bus, devfn, reg, len, val);
>> +}
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index df1f33d..c0422ea 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -1729,6 +1729,12 @@ static inline void pci_mmcfg_early_init(void) { }
>>   static inline void pci_mmcfg_late_init(void) { }
>>   #endif
>>   
>> +#ifdef CONFIG_ACPI_PCI_HOST_GENERIC
>> +void __init pci_mcfg_init(void);
>> +#else
>> +static inline void pci_mcfg_init(void) { return; }
>> +#endif
>> +
>>   int pci_ext_cfg_avail(void);
>>   
>>   void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
>> -- 
>> 1.9.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Thanks,
Tomasz


From broonie at kernel.org  Mon May  2 04:04:04 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 02 May 2016 12:04:04 +0100
Subject: Applied "spi: davinci: Use dma_request_chan() for requesting DMA
 channel" to the spi tree
In-Reply-To: <1448891145-10766-12-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <E1axBe0-0001mJ-5g@debutante>

The patch

   spi: davinci: Use dma_request_chan() for requesting DMA channel

has been applied to the spi tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From fe5fd2540947a6c584e70f1249007dd636e62d78 Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi at ti.com>
Date: Fri, 29 Apr 2016 16:10:22 +0300
Subject: [PATCH] spi: davinci: Use dma_request_chan() for requesting DMA
 channel

With the new dma_request_chan() the client driver does not need to look for
the DMA resource and it does not need to pass filter_fn anymore.
By switching to the new API the driver can now support deferred probing
against DMA.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 drivers/spi/spi-davinci.c | 76 +++++++++++++++--------------------------------
 1 file changed, 24 insertions(+), 52 deletions(-)

diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index fddb7a3be322..d36c11b73a35 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -23,7 +23,6 @@
 #include <linux/clk.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
-#include <linux/edma.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
@@ -33,8 +32,6 @@
 
 #include <linux/platform_data/spi-davinci.h>
 
-#define SPI_NO_RESOURCE		((resource_size_t)-1)
-
 #define CS_DEFAULT	0xFF
 
 #define SPIFMT_PHASE_MASK	BIT(16)
@@ -130,8 +127,6 @@ struct davinci_spi {
 
 	struct dma_chan		*dma_rx;
 	struct dma_chan		*dma_tx;
-	int			dma_rx_chnum;
-	int			dma_tx_chnum;
 
 	struct davinci_spi_platform_data pdata;
 
@@ -797,35 +792,19 @@ static irqreturn_t davinci_spi_irq(s32 irq, void *data)
 
 static int davinci_spi_request_dma(struct davinci_spi *dspi)
 {
-	dma_cap_mask_t mask;
 	struct device *sdev = dspi->bitbang.master->dev.parent;
-	int r;
-
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
 
-	dspi->dma_rx = dma_request_channel(mask, edma_filter_fn,
-					   &dspi->dma_rx_chnum);
-	if (!dspi->dma_rx) {
-		dev_err(sdev, "request RX DMA channel failed\n");
-		r = -ENODEV;
-		goto rx_dma_failed;
-	}
+	dspi->dma_rx = dma_request_chan(sdev, "rx");
+	if (IS_ERR(dspi->dma_rx))
+		return PTR_ERR(dspi->dma_rx);
 
-	dspi->dma_tx = dma_request_channel(mask, edma_filter_fn,
-					   &dspi->dma_tx_chnum);
-	if (!dspi->dma_tx) {
-		dev_err(sdev, "request TX DMA channel failed\n");
-		r = -ENODEV;
-		goto tx_dma_failed;
+	dspi->dma_tx = dma_request_chan(sdev, "tx");
+	if (IS_ERR(dspi->dma_tx)) {
+		dma_release_channel(dspi->dma_rx);
+		return PTR_ERR(dspi->dma_tx);
 	}
 
 	return 0;
-
-tx_dma_failed:
-	dma_release_channel(dspi->dma_rx);
-rx_dma_failed:
-	return r;
 }
 
 #if defined(CONFIG_OF)
@@ -936,8 +915,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
 	struct davinci_spi *dspi;
 	struct davinci_spi_platform_data *pdata;
 	struct resource *r;
-	resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
-	resource_size_t	dma_tx_chan = SPI_NO_RESOURCE;
 	int ret = 0;
 	u32 spipc0;
 
@@ -1044,27 +1021,15 @@ static int davinci_spi_probe(struct platform_device *pdev)
 		}
 	}
 
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (r)
-		dma_rx_chan = r->start;
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (r)
-		dma_tx_chan = r->start;
-
 	dspi->bitbang.txrx_bufs = davinci_spi_bufs;
-	if (dma_rx_chan != SPI_NO_RESOURCE &&
-	    dma_tx_chan != SPI_NO_RESOURCE) {
-		dspi->dma_rx_chnum = dma_rx_chan;
-		dspi->dma_tx_chnum = dma_tx_chan;
-
-		ret = davinci_spi_request_dma(dspi);
-		if (ret)
-			goto free_clk;
-
-		dev_info(&pdev->dev, "DMA: supported\n");
-		dev_info(&pdev->dev, "DMA: RX channel: %pa, TX channel: %pa, event queue: %d\n",
-				&dma_rx_chan, &dma_tx_chan,
-				pdata->dma_event_q);
+
+	ret = davinci_spi_request_dma(dspi);
+	if (ret == -EPROBE_DEFER) {
+		goto free_clk;
+	} else if (ret) {
+		dev_info(&pdev->dev, "DMA is not supported (%d)\n", ret);
+		dspi->dma_rx = NULL;
+		dspi->dma_tx = NULL;
 	}
 
 	dspi->get_rx = davinci_spi_rx_buf_u8;
@@ -1102,8 +1067,10 @@ static int davinci_spi_probe(struct platform_device *pdev)
 	return ret;
 
 free_dma:
-	dma_release_channel(dspi->dma_rx);
-	dma_release_channel(dspi->dma_tx);
+	if (dspi->dma_rx) {
+		dma_release_channel(dspi->dma_rx);
+		dma_release_channel(dspi->dma_tx);
+	}
 free_clk:
 	clk_disable_unprepare(dspi->clk);
 free_master:
@@ -1134,6 +1101,11 @@ static int davinci_spi_remove(struct platform_device *pdev)
 	clk_disable_unprepare(dspi->clk);
 	spi_master_put(master);
 
+	if (dspi->dma_rx) {
+		dma_release_channel(dspi->dma_rx);
+		dma_release_channel(dspi->dma_tx);
+	}
+
 	return 0;
 }
 
-- 
2.8.1



From maxime.ripard at free-electrons.com  Mon May  2 04:07:09 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 2 May 2016 13:07:09 +0200
Subject: [linux-sunxi] Re: [PATCH 2/3] sunxi: A20-OLinuXino-LIME2: Add
 usb-power-supply
In-Reply-To: <dec3f06a-1b27-8426-9119-fd7472e0a090@computerlinguist.org>
References: <1458932647-24268-1-git-send-email-haas@computerlinguist.org>
 <1458932647-24268-2-git-send-email-haas@computerlinguist.org>
 <20160402103648.GI4227@lukather>
 <dec3f06a-1b27-8426-9119-fd7472e0a090@computerlinguist.org>
Message-ID: <20160502110709.GP17159@lukather>

On Sun, May 01, 2016 at 08:46:28AM +0200, Michael Haas wrote:
> Hi Maxime,
> 
> 
> On 04/02/2016 12:36 PM, Maxime Ripard wrote:
> > Hi,
> > 
> > On Fri, Mar 25, 2016 at 08:04:06PM +0100, Michael Haas wrote:
> >> The A20-OLinuXino-LIME2 uses the AXP209 PMIC. This patch adds the
> >> corresponding usb-power-supply node to the DTS.
> >> If CONFIG_AXP20X_POWER is set, this patch enables the /sys/class/power_supply/
> >> diirectory.
> >>
> >> Signed-off-by: Michael Haas <haas at computerlinguist.org>
> > 
> > Is there *any* reason to not use the AXP209 dtsi where it's already
> > defined?
> > 
> 
> do you have any preference for this being in the AXP209 dtsi? I've been
> thinking about it and it makes sense to enable the power supply nodes
> for all devices using the AXP209. They will just report themselves as
> offline if the PMIC indicates nothing is connected.

Yes, I'd prefer that a lot :)

It avoids enabling it on all the boards.

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/c0040715/attachment-0001.sig>

From maxime.ripard at free-electrons.com  Mon May  2 04:13:37 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 2 May 2016 13:13:37 +0200
Subject: [PATCH v2] clk: sunxi: predivider handling for factors clock
In-Reply-To: <1461084466-20889-2-git-send-email-vishnupatekar0510@gmail.com>
References: <1461084466-20889-1-git-send-email-vishnupatekar0510@gmail.com>
 <1461084466-20889-2-git-send-email-vishnupatekar0510@gmail.com>
Message-ID: <20160502111337.GR17159@lukather>

Hi,

On Wed, Apr 20, 2016 at 12:47:46AM +0800, Vishnu Patekar wrote:
> For A31 ahb1 and a83t ahb1 clocks have predivider for certain parent.
> To handle this, this patch adds predivider table with parent index,
> prediv shift and width, parents with predivider will have nonzero width.
> 
> Rate adjustment is moved from clock specific recalc function to generic
> factors recalc. Also, adds prediv table for a31.
> 
> Signed-off-by: Vishnu Patekar <vishnupatekar0510 at gmail.com>
> ---
>  drivers/clk/sunxi/clk-factors.c | 31 +++++++++++++++----------------
>  drivers/clk/sunxi/clk-factors.h | 10 +++++++++-
>  drivers/clk/sunxi/clk-sunxi.c   | 31 +++++++++----------------------
>  3 files changed, 33 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
> index ddefe96..8f3b637 100644
> --- a/drivers/clk/sunxi/clk-factors.c
> +++ b/drivers/clk/sunxi/clk-factors.c
> @@ -45,10 +45,12 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw *hw,
>  					     unsigned long parent_rate)
>  {
>  	u8 n = 1, k = 0, p = 0, m = 0;
> +	u8 par_index = 0;
>  	u32 reg;
>  	unsigned long rate;
>  	struct clk_factors *factors = to_clk_factors(hw);
>  	const struct clk_factors_config *config = factors->config;
> +	const struct clk_factors_prediv *prediv = factors->prediv_config;
>  
>  	/* Fetch the register value */
>  	reg = readl(factors->reg);
> @@ -63,24 +65,16 @@ static unsigned long clk_factors_recalc_rate(struct clk_hw *hw,
>  	if (config->pwidth != SUNXI_FACTORS_NOT_APPLICABLE)
>  		p = FACTOR_GET(config->pshift, config->pwidth, reg);
>  
> -	if (factors->recalc) {
> -		struct factors_request factors_req = {
> -			.parent_rate = parent_rate,
> -			.n = n,
> -			.k = k,
> -			.m = m,
> -			.p = p,
> -		};
> -
> +	if (prediv) {
>  		/* get mux details from mux clk structure */
>  		if (factors->mux)
> -			factors_req.parent_index =
> -				(reg >> factors->mux->shift) &
> -				factors->mux->mask;
> -
> -		factors->recalc(&factors_req);
> +			par_index = (reg >> factors->mux->shift) &
> +					factors->mux->mask;
>  
> -		return factors_req.rate;
> +		if (prediv[par_index].width != SUNXI_FACTORS_NOT_APPLICABLE) {
> +			m = FACTOR_GET(prediv[par_index].shift,
> +				prediv[par_index].width, reg);
> +		}
>  	}
>  
>  	/* Calculate the rate */
> @@ -102,8 +96,12 @@ static int clk_factors_determine_rate(struct clk_hw *hw,
>  	for (i = 0; i < num_parents; i++) {
>  		struct factors_request factors_req = {
>  			.rate = req->rate,
> -			.parent_index = i,
>  		};
> +
> +		if (factors->prediv_config)
> +			factors_req.prediv_width =
> +						factors->prediv_config[i].width;
> +
>  		parent = clk_hw_get_parent_by_index(hw, i);
>  		if (!parent)
>  			continue;
> @@ -211,6 +209,7 @@ struct clk *sunxi_factors_register(struct device_node *node,
>  	/* set up factors properties */
>  	factors->reg = reg;
>  	factors->config = data->table;
> +	factors->prediv_config = data->prediv_table;
>  	factors->get_factors = data->getter;
>  	factors->recalc = data->recalc;
>  	factors->lock = lock;
> diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
> index 1e63c5b..b1b7745 100644
> --- a/drivers/clk/sunxi/clk-factors.h
> +++ b/drivers/clk/sunxi/clk-factors.h
> @@ -18,10 +18,16 @@ struct clk_factors_config {
>  	u8 n_start;
>  };
>  
> +struct clk_factors_prediv {
> +	u8 parent_index;
> +	u8 shift;
> +	u8 width;
> +};
> +
>  struct factors_request {
>  	unsigned long rate;
>  	unsigned long parent_rate;
> -	u8 parent_index;
> +	u8 prediv_width;
>  	u8 n;
>  	u8 k;
>  	u8 m;
> @@ -33,6 +39,7 @@ struct factors_data {
>  	int mux;
>  	int muxmask;
>  	const struct clk_factors_config *table;
> +	const struct clk_factors_prediv *prediv_table;
>  	void (*getter)(struct factors_request *req);
>  	void (*recalc)(struct factors_request *req);
>  	const char *name;
> @@ -42,6 +49,7 @@ struct clk_factors {
>  	struct clk_hw hw;
>  	void __iomem *reg;
>  	const struct clk_factors_config *config;
> +	const struct clk_factors_prediv *prediv_config;
>  	void (*get_factors)(struct factors_request *req);
>  	void (*recalc)(struct factors_request *req);
>  	spinlock_t *lock;
> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> index 91de0a0..5a5f26b 100644
> --- a/drivers/clk/sunxi/clk-sunxi.c
> +++ b/drivers/clk/sunxi/clk-sunxi.c
> @@ -282,8 +282,6 @@ static void sun5i_a13_get_ahb_factors(struct factors_request *req)
>  	req->p = div;
>  }
>  
> -#define SUN6I_AHB1_PARENT_PLL6	3
> -
>  /**
>   * sun6i_a31_get_ahb_factors() - calculates m, p factors for AHB
>   * AHB rate is calculated as follows
> @@ -307,7 +305,7 @@ static void sun6i_get_ahb1_factors(struct factors_request *req)
>  	div = DIV_ROUND_UP(req->parent_rate, req->rate);
>  
>  	/* calculate pre-divider if parent is pll6 */
> -	if (req->parent_index == SUN6I_AHB1_PARENT_PLL6) {
> +	if (req->prediv_width) {
>  		if (div < 4)
>  			calcp = 0;
>  		else if (div / 2 < 4)

You should also remove that code from that function. Now that the core
can tell the pre-divider configuration, it can adjust the parent rate
so that you don't have to care anymore.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/7d4f7805/attachment.sig>

From sr at denx.de  Mon May  2 04:19:24 2016
From: sr at denx.de (Stefan Roese)
Date: Mon,  2 May 2016 13:19:24 +0200
Subject: [PATCH v7] spi: orion.c: Add direct access mode
Message-ID: <1462187964-21876-1-git-send-email-sr@denx.de>

This patch adds support for the direct access mode to the Orion SPI
driver which is used on the Marvell Armada based SoCs. In this direct
mode, all data written to (or read from) a specifically mapped MBus
window (linked to one SPI chip-select on one of the SPI controllers)
will be transferred directly to the SPI bus. Without the need to control
the SPI registers in between. This can improve the SPI transfer rate in
such cases.

Both, direct-read and -write mode are supported. But only the write
mode has been tested. This mode especially benefits from the SPI direct
mode, as the data bytes are written head-to-head to the SPI bus,
without any additional addresses.

One use-case for this direct write mode is, programming a FPGA bitstream
image into the FPGA connected to the SPI bus at maximum speed.

This mode is described in chapter "22.5.2 Direct Write to SPI" in the
Marvell Armada XP Functional Spec Datasheet.

Signed-off-by: Stefan Roese <sr at denx.de>
Cc: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
Cc: Gregory CLEMENT <gregory.clement at free-electrons.com>
Cc: Andrew Lunn <andrew at lunn.ch>
Acked-by: Arnd Bergmann <arnd at arndb.de>
Cc: Mark Brown <broonie at kernel.org>
---
v7:
- Changed tx function to only write the really intended number of
  bytes (drop DIV_ROUND_UP) as suggested by Arnd.
- Added Arnd's Acked-by

v6:
- Switched from memcpy() to writesl() for the TX transfer.
- Only one page is mapped via ioremap as this is sufficient for
  the currently implemented simple TX transfer.
- Removed max_transfer_size() as its not needed with the current
  one page mapping that supports an unlimited amount of SPI data.
- Added a comment to the 'reg' description in the DT bindings
  documentation as suggested by Arnd.
- Changed 'reg' and 'ranges' to use '<' and '>' in this file.
- Changed size to 0xffffffff in this file.
- Added a small paragraph to the commit text, describing the
  possibility to support SPI-NOR & SPI-NAND devices via this
  direct access mode.

v5:
- Added some documentation for the direct mode to the orion-spi DT
  bindings document, including an example and a reference to the
  mbus DT bindings documentation.

v4:
- Add max_transfer_size()
- Fall back from direct-write mode to PIO mode when
  - transfer size is exceedeed
  - non-8bit transfers
- Restrict to direct-write mode for now. SPI direct read mode can
  be added later, when someone has a platform supporting this
  mode.

v3:
- Used static MBus windows again, as suggested by Arnd
- No new DT bindings needed for this. The MBus windows need to be
  configured in the 'reg' property of the SPI controller. This is
  done in a separate patch for the Armada platforms.
- The direct mapping is configured and enable by adding the
  specific MBus entry to the 'ranges' property of the 'soc' node
  in the board dts file.

v2:
- Use one MBus window for each SPI controller instead of one for
  for each SPI device. This MBus window is re-assigned, once the
  CS changes.
- Assert the CS over the entire message
- Don't restrict the direct access mode to only direct write mode
- Add check for max size before using memcpy()
- Remove spidev from DT bindings documentation

 .../devicetree/bindings/spi/spi-orion.txt          | 49 +++++++++++-
 drivers/spi/spi-orion.c                            | 87 ++++++++++++++++++++++
 2 files changed, 135 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-orion.txt b/Documentation/devicetree/bindings/spi/spi-orion.txt
index 98bc698..4f629cc 100644
--- a/Documentation/devicetree/bindings/spi/spi-orion.txt
+++ b/Documentation/devicetree/bindings/spi/spi-orion.txt
@@ -8,7 +8,15 @@ Required properties:
     - "marvell,armada-380-spi", for the Armada 38x SoCs
     - "marvell,armada-390-spi", for the Armada 39x SoCs
     - "marvell,armada-xp-spi", for the Armada XP SoCs
-- reg : offset and length of the register set for the device
+- reg : offset and length of the register set for the device.
+	This property can optionally have additional entries to configure
+	the SPI direct access mode that some of the Marvell SoCs support
+	additionally to the normal indirect access (PIO) mode. The values
+	for the MBus "target" and "attribute" are defined in the Marvell
+	SoC "Functional Specifications" Manual in the chapter "Marvell
+	Core Processor Address Decoding".
+	The eight register sets following the control registers refer to
+	chip-select lines 0 through 7 respectively.
 - cell-index : Which of multiple SPI controllers is this.
 Optional properties:
 - interrupts : Is currently not used.
@@ -23,3 +31,42 @@ Example:
 	       interrupts = <23>;
 	       status = "disabled";
        };
+
+Example with SPI direct mode support (optionally):
+	spi0: spi at 10600 {
+		compatible = "marvell,orion-spi";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cell-index = <0>;
+		reg = <MBUS_ID(0xf0, 0x01) 0x10600 0x28>, /* control */
+		      <MBUS_ID(0x01, 0x1e) 0 0xffffffff>, /* CS0 */
+		      <MBUS_ID(0x01, 0x5e) 0 0xffffffff>, /* CS1 */
+		      <MBUS_ID(0x01, 0x9e) 0 0xffffffff>, /* CS2 */
+		      <MBUS_ID(0x01, 0xde) 0 0xffffffff>, /* CS3 */
+		      <MBUS_ID(0x01, 0x1f) 0 0xffffffff>, /* CS4 */
+		      <MBUS_ID(0x01, 0x5f) 0 0xffffffff>, /* CS5 */
+		      <MBUS_ID(0x01, 0x9f) 0 0xffffffff>, /* CS6 */
+		      <MBUS_ID(0x01, 0xdf) 0 0xffffffff>; /* CS7 */
+		interrupts = <23>;
+		status = "disabled";
+	};
+
+To enable the direct mode, the board specific 'ranges' property in the
+'soc' node needs to add the entries for the desired SPI controllers
+and its chip-selects that are used in the direct mode instead of PIO
+mode. Here an example for this (SPI controller 0, device 1 and SPI
+controller 1, device 2 are used in direct mode. All other SPI device
+are used in the default indirect (PIO) mode):
+	soc {
+		/*
+		 * Enable the SPI direct access by configuring an entry
+		 * here in the board-specific ranges property
+		 */
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000>,	/* internal regs */
+			 <MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>,	/* BootROM       */
+			 <MBUS_ID(0x01, 0x5e) 0 0 0xf1100000 0x10000>,	/* SPI0-DEV1 */
+			 <MBUS_ID(0x01, 0x9a) 0 0 0xf1110000 0x10000>;	/* SPI1-DEV2 */
+
+For further information on the MBus bindings, please see the MBus
+DT documentation:
+Documentation/devicetree/bindings/bus/mvebu-mbus.txt
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index a87cfd4..71ea533 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/clk.h>
 #include <linux/sizes.h>
@@ -43,6 +44,9 @@
 #define ORION_SPI_INT_CAUSE_REG		0x10
 #define ORION_SPI_TIMING_PARAMS_REG	0x18
 
+/* Register for the "Direct Mode" */
+#define SPI_DIRECT_WRITE_CONFIG_REG	0x20
+
 #define ORION_SPI_TMISO_SAMPLE_MASK	(0x3 << 6)
 #define ORION_SPI_TMISO_SAMPLE_1	(1 << 6)
 #define ORION_SPI_TMISO_SAMPLE_2	(2 << 6)
@@ -78,11 +82,18 @@ struct orion_spi_dev {
 	bool			is_errata_50mhz_ac;
 };
 
+struct orion_direct_acc {
+	void __iomem		*vaddr;
+	u32			size;
+};
+
 struct orion_spi {
 	struct spi_master	*master;
 	void __iomem		*base;
 	struct clk              *clk;
 	const struct orion_spi_dev *devdata;
+
+	struct orion_direct_acc	direct_access[ORION_NUM_CHIPSELECTS];
 };
 
 static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
@@ -372,10 +383,38 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
 {
 	unsigned int count;
 	int word_len;
+	struct orion_spi *orion_spi;
+	int cs = spi->chip_select;
 
 	word_len = spi->bits_per_word;
 	count = xfer->len;
 
+	orion_spi = spi_master_get_devdata(spi->master);
+
+	/*
+	 * Use SPI direct write mode if base address is available. Otherwise
+	 * fall back to PIO mode for this transfer.
+	 */
+	if ((orion_spi->direct_access[cs].vaddr) && (xfer->tx_buf) &&
+	    (word_len == 8)) {
+		unsigned int cnt = count >> 2;
+		unsigned int rem = count % 4;
+
+		/*
+		 * Send the TX-data to the SPI device via the direct
+		 * mapped address window
+		 */
+		writesl(orion_spi->direct_access[cs].vaddr, xfer->tx_buf, cnt);
+		if (rem) {
+			u32 *buf = (u32 *)xfer->tx_buf;
+
+			writesb(orion_spi->direct_access[cs].vaddr, &buf[cnt],
+				rem);
+		}
+
+		return count;
+	}
+
 	if (word_len == 8) {
 		const u8 *tx = xfer->tx_buf;
 		u8 *rx = xfer->rx_buf;
@@ -425,6 +464,10 @@ static int orion_spi_reset(struct orion_spi *orion_spi)
 {
 	/* Verify that the CS is deasserted */
 	orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+
+	/* Don't deassert CS between the direct mapped SPI transfers */
+	writel(0, spi_reg(orion_spi, SPI_DIRECT_WRITE_CONFIG_REG));
+
 	return 0;
 }
 
@@ -504,6 +547,7 @@ static int orion_spi_probe(struct platform_device *pdev)
 	struct resource *r;
 	unsigned long tclk_hz;
 	int status = 0;
+	struct device_node *np;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(*spi));
 	if (master == NULL) {
@@ -576,6 +620,49 @@ static int orion_spi_probe(struct platform_device *pdev)
 		goto out_rel_clk;
 	}
 
+	/* Scan all SPI devices of this controller for direct mapped devices */
+	for_each_available_child_of_node(pdev->dev.of_node, np) {
+		u32 cs;
+
+		/* Get chip-select number from the "reg" property */
+		status = of_property_read_u32(np, "reg", &cs);
+		if (status) {
+			dev_err(&pdev->dev,
+				"%s has no valid 'reg' property (%d)\n",
+				np->full_name, status);
+			status = 0;
+			continue;
+		}
+
+		/*
+		 * Check if an address is configured for this SPI device. If
+		 * not, the MBus mapping via the 'ranges' property in the 'soc'
+		 * node is not configured and this device should not use the
+		 * direct mode. In this case, just continue with the next
+		 * device.
+		 */
+		status = of_address_to_resource(pdev->dev.of_node, cs + 1, r);
+		if (status)
+			continue;
+
+		/*
+		 * Only map one page for direct access. This is enough for the
+		 * simple TX transfer which only writes to the first word.
+		 * This needs to get extended for the direct SPI-NOR / SPI-NAND
+		 * support, once this gets implemented.
+		 */
+		spi->direct_access[cs].vaddr = devm_ioremap(&pdev->dev,
+							    r->start,
+							    PAGE_SIZE);
+		if (IS_ERR(spi->direct_access[cs].vaddr)) {
+			status = PTR_ERR(spi->direct_access[cs].vaddr);
+			goto out_rel_clk;
+		}
+		spi->direct_access[cs].size = PAGE_SIZE;
+
+		dev_info(&pdev->dev, "CS%d configured for direct access\n", cs);
+	}
+
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
-- 
2.8.2



From tn at semihalf.com  Mon May  2 04:31:46 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 2 May 2016 13:31:46 +0200
Subject: [PATCH V6 09/13] pci, acpi: Support for ACPI based generic PCI
 host controller
In-Reply-To: <CAKc_7PUcjKkCrCTj9q26P8a+Tb3N_MffynnTXnJRacm6VNmFRw@mail.gmail.com>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-10-git-send-email-tn@semihalf.com>
 <20160428214800.GG25125@localhost> <20160429083709.GA3249@red-moon>
 <CAKc_7PUcjKkCrCTj9q26P8a+Tb3N_MffynnTXnJRacm6VNmFRw@mail.gmail.com>
Message-ID: <57273AA2.4080806@semihalf.com>

On 04/29/2016 07:35 PM, Jayachandran C wrote:
> On Fri, Apr 29, 2016 at 2:07 PM, Lorenzo Pieralisi
> <lorenzo.pieralisi at arm.com> wrote:
>> On Thu, Apr 28, 2016 at 04:48:00PM -0500, Bjorn Helgaas wrote:
>>
>> [...]
>>
>>>> +static int pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root,
>>>> +                                  struct acpi_pci_generic_root_info *ri)
>>>> +{
>>>> +   u16 seg = root->segment;
>>>> +   u8 bus_start = root->secondary.start;
>>>> +   u8 bus_end = root->secondary.end;
>>>> +   struct pci_config_window *cfg;
>>>> +   struct mcfg_entry *e;
>>>> +   phys_addr_t addr;
>>>> +   int err = 0;
>>>> +
>>>> +   mutex_lock(&pci_mcfg_lock);
>>> What does this lock protect?  The pci_mcfg_list should already be
>>> initialized by the time we get there, and it should be immutable for
>>> the life of the system.  In fact, I would prefer if we could just
>>> search the static table itself whenever we need it rather than caching
>>> it in our own list.  But I don't think we can easily do that because
>>> acpi_table_parse() is __init.
>>>
>>>> +   e = pci_mcfg_lookup(seg, bus_start);
>>> I would argue that we should check for _CBA first, and fall back to
>>> MCFG if _CBA doesn't exist.
>>>
>>>> +   if (!e) {
>>>> +           addr = acpi_pci_root_get_mcfg_addr(root->device->handle);
>>> IMO, acpi_pci_root_get_mcfg_addr() is misnamed.  It should be
>>> acpi_pci_config_base_addr() or similar.  It definitely is not related
>>> to MCFG.  Not your fault, obviously.
>>>
>>>> +           if (addr == 0) {
>>>> +                   pr_err(PREFIX"%04x:%02x-%02x bus range error\n",
>>>> +                          seg, bus_start, bus_end);
>>>> +                   err = -ENOENT;
>>>> +                   goto err_out;
>>>> +           }
>>>> +   } else {
>>>> +           if (bus_start != e->bus_start) {
>>>> +                   pr_err("%04x:%02x-%02x bus range mismatch %02x\n",
>>>> +                          seg, bus_start, bus_end, e->bus_start);
>>>> +                   err = -EINVAL;
>>>> +                   goto err_out;
>>>> +           } else if (bus_end != e->bus_end) {
>>>> +                   pr_warn("%04x:%02x-%02x bus end mismatch %02x\n",
>>>> +                           seg, bus_start, bus_end, e->bus_end);
>>>> +                   bus_end = min(bus_end, e->bus_end);
>>>> +           }
>>>> +           addr = e->addr;
>>>> +   }
>>> I really don't think you need a lock around this, so you can factor
>>> out the address lookup into something like:
>>>
>>>    addr = acpi_pci_config_base_addr(...);
>>>    if (addr)
>>>      return addr;
>>>
>>>    return acpi_pci_mcfg_lookup(seg, busn_res);
>>>
>>> You can check inside acpi_pci_mcfg_lookup() to make sure the entry you
>>> find covers the entire [busn_res.start-busn_res.end] range and return
>>> failure if it doesn't.  At this point, I'm not sure it's worth it to
>>> truncate the host bridge bus range to match something we find in MCFG.
>>>
>>> If the MCFG entry covers *more* than the host bridge range from _CRS,
>>> that's fine.  In any case, we have to be careful with the start address,
>>> because the MCFG start address is always based on bus 0, but I think
>>> pci_generic_ecam_create() expects the start address based on the
>>> bus_start you pass to it.
>> Yes, I spotted this too, it is unfortunate but DT and MCFG handle
>> the ECAM regions differently. In DT the reg property is relative
>> to bus_start - ie reg MMIO region maps config space starting at
>> the first bus in bus-range:
>>
>> Documentation/devicetree/bindings/pci/host-generic-pci.txt
>>
>> in ACPI(MCFG) as you said it is always relative to bus 0, it is
>> unfortunate but the address to be mapped should be computed
>> differently in the ECAM layer.
> Can't this be handled by fixing up the address before passing to
> pci_generic_ecam_create?
>
I agree, this should work, IMO.

Tomasz


From festevam at gmail.com  Mon May  2 04:31:57 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 2 May 2016 08:31:57 -0300
Subject: [PATCH v4 2/2] ARM: dts: imx6ul-pico-hobbit: Add initial support
In-Reply-To: <1461729621-13283-2-git-send-email-festevam@gmail.com>
References: <1461729621-13283-1-git-send-email-festevam@gmail.com>
 <1461729621-13283-2-git-send-email-festevam@gmail.com>
Message-ID: <CAOMZO5DX-QAB+kH=xeM6Pp6rzD6TjVkyuaHrBPUPn-BA0Xmefg@mail.gmail.com>

Hi Shawn,

On Wed, Apr 27, 2016 at 1:00 AM, Fabio Estevam <festevam at gmail.com> wrote:
> From: Fabio Estevam <fabio.estevam at nxp.com>
>
> Add initial support for imx6ul pico hobbit board.
>
> For information about this board, please visit:
> http://www.wandboard.org/images/hobbit/hobbitboard-imx6ul-reva1.pdf
>
> Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>

I understand we are still waiting for Rob's Ack on the first patch of
this series.

Could this one be applied to your tree in case you are happy with it?

Would like to get this one for 4.7 if possible.

Thanks


From linus.walleij at linaro.org  Mon May  2 04:52:31 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 2 May 2016 13:52:31 +0200
Subject: [PATCH 1/2] pinctrl: at91: Make at91_gpio_template const
In-Reply-To: <1461934203-3206-1-git-send-email-alexanders83@web.de>
References: <1461934203-3206-1-git-send-email-alexanders83@web.de>
Message-ID: <CACRpkdbLB3s3AbgB7rexY8GFueAY_ywpKY3krX6tTVrq1X4Wcg@mail.gmail.com>

On Fri, Apr 29, 2016 at 2:50 PM, Alexander Stein <alexanders83 at web.de> wrote:

> This template is only assigned, so make it const.
>
> Signed-off-by: Alexander Stein <alexanders83 at web.de>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Mon May  2 04:53:31 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 2 May 2016 13:53:31 +0200
Subject: [PATCH 2/2] pinctrl: at91: Merge clk_prepare and clk_enable into
 clk_prepare_enable
In-Reply-To: <1461934203-3206-2-git-send-email-alexanders83@web.de>
References: <1461934203-3206-1-git-send-email-alexanders83@web.de>
 <1461934203-3206-2-git-send-email-alexanders83@web.de>
Message-ID: <CACRpkdYcbVtCkrhmC0Wu8-_miGdi1y+Ja8kcHnY1a7GKPiHSeg@mail.gmail.com>

On Fri, Apr 29, 2016 at 2:50 PM, Alexander Stein <alexanders83 at web.de> wrote:

> This simplifies the normal as well as the error path.
>
> Signed-off-by: Alexander Stein <alexanders83 at web.de>

Patch applied.

Yours,
Linus Walleij


From appana.durga.rao at xilinx.com  Mon May  2 05:02:44 2016
From: appana.durga.rao at xilinx.com (Appana Durga Kedareswara Rao)
Date: Mon, 2 May 2016 12:02:44 +0000
Subject: [PATCH v4 4/5] Documentation: DT: vdma: update binding doc for
 AXI CDMA
In-Reply-To: <C246CAC1457055469EF09E3A7AC4E11A4A57553D@XAP-PVEXMBX01.xlnx.xilinx.com>
References: <1460006985-14805-1-git-send-email-appanad@xilinx.com>
 <1460006985-14805-5-git-send-email-appanad@xilinx.com>
 <20160411140243.GA827@rob-hp-laptop>
 <C246CAC1457055469EF09E3A7AC4E11A4A57553D@XAP-PVEXMBX01.xlnx.xilinx.com>
Message-ID: <C246CAC1457055469EF09E3A7AC4E11A4A57D479@XAP-PVEXMBX01.xlnx.xilinx.com>

Hi Vinod,

> -----Original Message-----
> From: dmaengine-owner at vger.kernel.org [mailto:dmaengine-
> owner at vger.kernel.org] On Behalf Of Appana Durga Kedareswara Rao
> Sent: Tuesday, April 12, 2016 11:51 AM
> To: Rob Herring <robh at kernel.org>; vinod.koul at intel.com
> Cc: pawel.moll at arm.com; mark.rutland at arm.com;
> ijc+devicetree at hellion.org.uk; galak at codeaurora.org; Michal Simek
> <michals at xilinx.com>; Soren Brinkmann <sorenb at xilinx.com>;
> vinod.koul at intel.com; dan.j.williams at intel.com; moritz.fischer at ettus.com;
> laurent.pinchart at ideasonboard.com; luis at debethencourt.com; Anirudha
> Sarangi <anirudh at xilinx.com>; devicetree at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> dmaengine at vger.kernel.org; Punnaiah Choudary Kalluri <punnaia at xilinx.com>
> Subject: RE: [PATCH v4 4/5] Documentation: DT: vdma: update binding doc for
> AXI CDMA
> 
> 
> 
> > -----Original Message-----
> > From: Rob Herring [mailto:robh at kernel.org]
> > Sent: Monday, April 11, 2016 7:33 PM
> > To: Appana Durga Kedareswara Rao <appanad at xilinx.com>
> > Cc: pawel.moll at arm.com; mark.rutland at arm.com;
> > ijc+devicetree at hellion.org.uk; galak at codeaurora.org; Michal Simek
> > <michals at xilinx.com>; Soren Brinkmann <sorenb at xilinx.com>;
> > vinod.koul at intel.com; dan.j.williams at intel.com; Appana Durga Kedareswara
> > Rao <appanad at xilinx.com>; moritz.fischer at ettus.com;
> > laurent.pinchart at ideasonboard.com; luis at debethencourt.com; Anirudha
> > Sarangi <anirudh at xilinx.com>; devicetree at vger.kernel.org; linux-arm-
> > kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> > dmaengine at vger.kernel.org
> > Subject: Re: [PATCH v4 4/5] Documentation: DT: vdma: update binding doc for
> > AXI CDMA
> >
> > On Thu, Apr 07, 2016 at 10:59:44AM +0530, Kedareswara rao Appana wrote:
> > > This patch updates the device-tree binding doc for adding support for
> > > AXI CDMA.
> > >
> > > Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
> > > ---
> > > Changes for v4:
> > > ---> None.
> > > Changes for v3:
> > > ---> Removed CDMA DT example from the patch as suggested by the Rob.
> > > Changes for v2:
> > > ---> Modified commit message as suggested by Vinod.
> > > ---> Moved the patch to forward in the series as suggested by vinod.
> > >
> > >  Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt | 6
> > > +++++-
> > >  1 file changed, 5 insertions(+), 1 deletion(-)
> >
> > Acked-by: Rob Herring <robh at kernel.org>
> 
> Thanks for the Ack Rob...
> 
> @Vinod: I got the Ack's for the binding doc patches in this series
> If you are ok with the other patches could you please apply this patch series?

Could you please review this patch Series?
If you are ok with this patch series will resend on top of the dma-next  

Regards,
Kedar.

> 
> Regards,
> Kedar.
> --
> To unsubscribe from this list: send the line "unsubscribe dmaengine" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From marc.zyngier at arm.com  Mon May  2 05:05:35 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 2 May 2016 13:05:35 +0100
Subject: [PATCH] arm64: kvm: Fix kvm teardown for systems using the
 extended idmap
In-Reply-To: <1461950823-9790-1-git-send-email-james.morse@arm.com>
References: <1461775633-29715-1-git-send-email-james.morse@arm.com>
 <1461950823-9790-1-git-send-email-james.morse@arm.com>
Message-ID: <20160502130535.19b20b79@arm.com>

On Fri, 29 Apr 2016 18:27:03 +0100
James Morse <james.morse at arm.com> wrote:

Hi James,

> If memory is located above 1<<VA_BITS, kvm adds an extra level to its page
> tables, merging the runtime tables and boot tables that contain the idmap.
> This lets us avoid the trampoline dance during initialisation.
> 
> This also means there is no trampoline page mapped, so
> __cpu_reset_hyp_mode() can't call __kvm_hyp_reset() in this page. The good
> news is the idmap is still mapped, so we don't need the trampoline page.
> The bad news is we can't call it directly as the idmap is above
> HYP_PAGE_OFFSET, so its address is masked by kvm_call_hyp.
> 
> Add a function __extended_idmap_trampoline which will branch into
> __kvm_hyp_reset in the idmap, change kvm_hyp_reset_entry() to return
> this address if __kvm_cpu_uses_extended_idmap(). In this case
> __kvm_hyp_reset() will still switch to the boot tables (which are the
> merged tables that were already in use), and branch into the idmap (where
> it already was).
> 
> This fixes boot failures on these systems, where we fail to execute the
> missing trampoline page when tearing down kvm in init_subsystems():
> [    2.508922] kvm [1]: 8-bit VMID
> [    2.512057] kvm [1]: Hyp mode initialized successfully
> [    2.517242] kvm [1]: interrupt-controller at e1140000 IRQ13
> [    2.522622] kvm [1]: timer IRQ3
> [    2.525783] Kernel panic - not syncing: HYP panic:
> [    2.525783] PS:200003c9 PC:0000007ffffff820 ESR:86000005
> [    2.525783] FAR:0000007ffffff820 HPFAR:00000000003ffff0 PAR:0000000000000000
> [    2.525783] VCPU:          (null)
> [    2.525783]
> [    2.547667] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G        W       4.6.0-rc5+ #1
> [    2.555137] Hardware name: Default string Default string/Default string, BIOS ROD0084E 09/03/2015
> [    2.563994] Call trace:
> [    2.566432] [<ffffff80080888d0>] dump_backtrace+0x0/0x240
> [    2.571818] [<ffffff8008088b24>] show_stack+0x14/0x20
> [    2.576858] [<ffffff80083423ac>] dump_stack+0x94/0xb8
> [    2.581899] [<ffffff8008152130>] panic+0x10c/0x250
> [    2.586677] [<ffffff8008152024>] panic+0x0/0x250
> [    2.591281] SMP: stopping secondary CPUs
> [    3.649692] SMP: failed to stop secondary CPUs 0-2,4-7
> [    3.654818] Kernel Offset: disabled
> [    3.658293] Memory Limit: none
> [    3.661337] ---[ end Kernel panic - not syncing: HYP panic:
> [    3.661337] PS:200003c9 PC:0000007ffffff820 ESR:86000005
> [    3.661337] FAR:0000007ffffff820 HPFAR:00000000003ffff0 PAR:0000000000000000
> [    3.661337] VCPU:          (null)
> [    3.661337]
> 
> 
> Reported-by: Will Deacon <will.deacon at arm.com>
> Signed-off-by: James Morse <james.morse at arm.com>
> ---
>  arch/arm64/include/asm/kvm_host.h |  3 ++-
>  arch/arm64/kvm/hyp-init.S         |  5 +++++
>  arch/arm64/kvm/hyp/entry.S        | 19 +++++++++++++++++++
>  arch/arm64/kvm/reset.c            | 30 +++++++++++++++++++++++-------
>  4 files changed, 49 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index b6f194d9f6b2..88a34670ddef 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -46,7 +46,8 @@
>  int __attribute_const__ kvm_target_cpu(void);
>  int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
>  int kvm_arch_dev_ioctl_check_extension(long ext);
> -phys_addr_t kvm_hyp_reset_entry(void);
> +unsigned long kvm_hyp_reset_entry(void);
> +void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t idmap_start);
>  
>  struct kvm_arch {
>  	/* The VMID generation used for the virt. memory system */
> diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
> index 44ec4cb23ae7..a873a6d8be90 100644
> --- a/arch/arm64/kvm/hyp-init.S
> +++ b/arch/arm64/kvm/hyp-init.S
> @@ -140,6 +140,11 @@ merged:
>  ENDPROC(__kvm_hyp_init)
>  
>  	/*
> +	 * Reset kvm back to the hyp stub. This is the trampoline dance in
> +	 * reverse. If kvm used an extended idmap, __extended_idmap_trampoline
> +	 * calls this code directly in the idmap. In this case switching to the
> +	 * boot tables is a no-op.
> +	 *
>  	 * x0: HYP boot pgd
>  	 * x1: HYP phys_idmap_start
>  	 */
> diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
> index ce9e5e5f28cf..70254a65bd5b 100644
> --- a/arch/arm64/kvm/hyp/entry.S
> +++ b/arch/arm64/kvm/hyp/entry.S
> @@ -164,3 +164,22 @@ alternative_endif
>  
>  	eret
>  ENDPROC(__fpsimd_guest_restore)
> +
> +/*
> + * When using the extended idmap, we don't have a trampoline page we can use
> + * while we switch pages tables during __kvm_hyp_reset. Accessing the idmap
> + * directly would be ideal, but if we're using the extended idmap then the
> + * idmap is located above HYP_PAGE_OFFSET, and the address will be masked by
> + * kvm_call_hyp using kern_hyp_va.
> + *
> + * x0: HYP boot pgd
> + * x1: HYP phys_idmap_start
> + */
> +ENTRY(__extended_idmap_trampoline)
> +	mov	x4, x1
> +	adr_l	x3, __kvm_hyp_reset
> +
> +	/* insert __kvm_hyp_reset()s offset into phys_idmap_start */
> +	bfi	x4, x3, #0, #PAGE_SHIFT
> +	br	x4
> +ENDPROC(__extended_idmap_trampoline)
> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> index 4062e6dd4cc1..b1ad730e1567 100644
> --- a/arch/arm64/kvm/reset.c
> +++ b/arch/arm64/kvm/reset.c
> @@ -135,12 +135,28 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
>  
>  extern char __hyp_idmap_text_start[];
>  
> -phys_addr_t kvm_hyp_reset_entry(void)
> +unsigned long kvm_hyp_reset_entry(void)
>  {
> -	unsigned long offset;
> -
> -	offset = (unsigned long)__kvm_hyp_reset
> -		 - ((unsigned long)__hyp_idmap_text_start & PAGE_MASK);
> -
> -	return TRAMPOLINE_VA + offset;
> +	if (!__kvm_cpu_uses_extended_idmap()) {
> +		unsigned long offset;
> +
> +		/*
> +		 * Find the address of __kvm_hyp_reset() in the trampoline page.
> +		 * This is present in the running page tables, and the boot page
> +		 * tables, so we call the code here to start the trampoline
> +		 * dance in reverse.
> +		 */
> +		offset = (unsigned long)__kvm_hyp_reset
> +			 - ((unsigned long)__hyp_idmap_text_start & PAGE_MASK);
> +
> +		return TRAMPOLINE_VA + offset;
> +	} else {
> +		/*
> +		 * KVM is running with merged page tables, which don't have the
> +		 * trampoline page mapped. We know the idmap is still mapped,
> +		 * but can't be called into directly. Use
> +		 * __extended_idmap_trampoline to do the call.
> +		 */
> +		return (unsigned long)kvm_ksym_ref(__extended_idmap_trampoline);
> +	}
>  }

This looks correct, and gives me yet another incentive to revisit this
code with a view of keeping the idmap at all times in the EL2 page
tables. This should ensure that (1) the merged page tables become the
only configuration, and (2) that we get rid off of the potential TLB
conflict when swapping TTBR0_EL2 at boot time (intermediate level
caching). In the meantime:

Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.


From marc.zyngier at arm.com  Mon May  2 05:16:37 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 2 May 2016 13:16:37 +0100
Subject: [PATCH v2 17/54] KVM: arm/arm64: vgic-new: Add GICv2 world
 switch backend
In-Reply-To: <1461861973-26464-18-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-18-git-send-email-andre.przywara@arm.com>
Message-ID: <20160502131637.054b6b23@arm.com>

On Thu, 28 Apr 2016 17:45:36 +0100
Andre Przywara <andre.przywara at arm.com> wrote:

> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Processing maintenance interrupts and accessing the list registers
> are dependent on the host's GIC version.
> Introduce vgic-v2.c to contain GICv2 specific functions.
> Implement the GICv2 specific code for syncing the emulation state
> into the VGIC registers.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - remove explicit LR_STATE clearing on maintenance interrupt handling
> - improve documentation for vgic_v2_populate_lr()
> - remove WARN_ON on non-edge IRQs in maintenance interrupts
> - simplify multi-CPU source SGI handling
> 
> Changelog v1 .. v2:
> - inject the IRQ priority into the list register
> 
>  include/linux/irqchip/arm-gic.h |   1 +
>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.c        |  19 ++---
>  virt/kvm/arm/vgic/vgic.h        |   6 ++
>  4 files changed, 194 insertions(+), 10 deletions(-)
>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
> 

[...]

> @@ -441,14 +447,12 @@ static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
>  static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
>  {
>  	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> -	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
> -	u32 model = dist->vgic_model;
>  	struct vgic_irq *irq;
>  	int count = 0;
>  
>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(vgic_cpu->ap_list_lock));
>  
> -	if (unlikely(!dist->enabled))
> +	if (unlikely(!vcpu->kvm->arch.vgic.enabled))
>  		goto out_clean;
>  
>  	if (compute_ap_list_depth(vcpu) > kvm_vgic_global_state.nr_lr) {
> @@ -466,14 +470,9 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
>  		 * If we get an SGI with multiple sources, try to get
>  		 * them in all at once.
>  		 */
> -		if (model == KVM_DEV_TYPE_ARM_VGIC_V2 &&
> -		    vgic_irq_is_sgi(irq->intid)) {
> -			while (irq->source &&
> -			       count < kvm_vgic_global_state.nr_lr)
> -				vgic_populate_lr(vcpu, irq, count++);
> -		} else {
> +		do {
>  			vgic_populate_lr(vcpu, irq, count++);
> -		}
> +		} while (irq->source && count < kvm_vgic_global_state.nr_lr);
>  
>  next:

Most, if not all of the changes in this function should be folded in the
previous patch, as we only have generic code in this file (this looks
like a leftover from an earlier rework).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.


From harald at ccbib.org  Mon May  2 05:25:00 2016
From: harald at ccbib.org (Harald Geyer)
Date: Mon, 02 May 2016 14:25:00 +0200
Subject: [PATCH 0/3] mxs-lradc: Add support for current sources
In-Reply-To: <ac57f3e9-f8f2-a6ef-52fa-0a13d7df5d4f@kernel.org>
References: <1461333147-11873-1-git-send-email-harald@ccbib.org>
 <572379F5.8000501@i2se.com> <aadb3f41413d093312c0af3e4c207a8a@ccbib.org>
 <ac57f3e9-f8f2-a6ef-52fa-0a13d7df5d4f@kernel.org>
Message-ID: <a0d59747ffca9d900feecece4cfcae82@ccbib.org>

On 01.05.2016 20:02, Jonathan Cameron wrote:
> On 29/04/16 18:45, Harald Geyer wrote:
>> My thinking is that there should be a thermistor (or whatever else) 
>> driver,
>> that is a consumer of the regulator and a consumer of the 
>> IIO_VOLTAGE
>> iio channel and provides a new device with an IIO_RESISTANCE or 
>> IIO_TEMP
>> channel. Maybe there is a simpler solution, that I'm missing?
> I agree with that approach - need a way to describe the upstream
> hardware - so
> will need a thermistor driver
>>
>> Actually I'm not 100% happy with the above solution myself, because 
>> if we
>> start supporting devices that act as an iio-multiplexer (some device 
>> that
>> is an iio consumer and provides many new iio channels and can 
>> control
>> via gpios which of it child channels is actually routed to the 
>> upstream
>> device) I don't know how to properly manage the regulator device.
> Hmm. Are you talking about muxing the regulator as well?  That will 
> get
> complex indeed.  Might be possible to cheat and imply the regulators 
> are
> always connected to all inputs...  or do you want to dynamically 
> change
> the regulator output?  That gets messy fast - though in theory might 
> be
> possible...

Yes, that's a good summary of what I'm thinking. As there is no
iio-multiplexer yet, this is sort of an academic question. But it's
kind of an obvious thing to want, so we shouldn't be surprised when
somebody actually starts working on that.

Thanks,
Harald


From eric.auger at linaro.org  Mon May  2 05:24:53 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 2 May 2016 14:24:53 +0200
Subject: [PATCH v2 19/54] KVM: arm/arm64: vgic-new: Implement
In-Reply-To: <1461861973-26464-20-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-20-git-send-email-andre.przywara@arm.com>
Message-ID: <57274715.8080801@linaro.org>

Hi Andre,

minor comment: patch title has been altered since v1, should be

KVM: arm/arm64: vgic-new: Implement kvm_vgic_vcpu_pending_irq

Cheers

Eric

On 04/28/2016 06:45 PM, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> Tell KVM whether a particular VCPU has an IRQ that needs handling
> in the guest. This is used to decide whether a VCPU is runnable.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - return false if distributor is disabled
> - add vgic_kick_vcpus() implementations
> 
>  include/kvm/vgic/vgic.h  |  2 ++
>  virt/kvm/arm/vgic/vgic.c | 40 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h |  1 +
>  3 files changed, 43 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 5fae4a9..2615205 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -184,6 +184,8 @@ struct vgic_cpu {
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  			bool level);
>  
> +int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
> +
>  #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
>  #define vgic_initialized(k)	(false)
>  #define vgic_ready(k)		((k)->arch.vgic.ready)
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index ae52928..eeb766e 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -519,3 +519,43 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
>  	vgic_flush_lr_state(vcpu);
>  	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
>  }
> +
> +int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq;
> +	bool pending = false;
> +
> +	if (!vcpu->kvm->arch.vgic.enabled)
> +		return false;
> +
> +	spin_lock(&vgic_cpu->ap_list_lock);
> +
> +	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
> +		spin_lock(&irq->irq_lock);
> +		pending = irq->pending && irq->enabled;
> +		spin_unlock(&irq->irq_lock);
> +
> +		if (pending)
> +			break;
> +	}
> +
> +	spin_unlock(&vgic_cpu->ap_list_lock);
> +
> +	return pending;
> +}
> +
> +void vgic_kick_vcpus(struct kvm *kvm)
> +{
> +	struct kvm_vcpu *vcpu;
> +	int c;
> +
> +	/*
> +	 * We've injected an interrupt, time to find out who deserves
> +	 * a good kick...
> +	 */
> +	kvm_for_each_vcpu(c, vcpu, kvm) {
> +		if (kvm_vgic_vcpu_pending_irq(vcpu))
> +			kvm_vcpu_kick(vcpu);
> +	}
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 81b1a20..0c92cda 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -21,6 +21,7 @@
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid);
>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
> +void vgic_kick_vcpus(struct kvm *kvm);
>  
>  void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
>  void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
> 



From stefan.wahren at i2se.com  Mon May  2 05:29:08 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Mon, 2 May 2016 14:29:08 +0200
Subject: [PATCH 0/3] mxs-lradc: Add support for current sources
In-Reply-To: <ac57f3e9-f8f2-a6ef-52fa-0a13d7df5d4f@kernel.org>
References: <1461333147-11873-1-git-send-email-harald@ccbib.org>
 <572379F5.8000501@i2se.com> <aadb3f41413d093312c0af3e4c207a8a@ccbib.org>
 <ac57f3e9-f8f2-a6ef-52fa-0a13d7df5d4f@kernel.org>
Message-ID: <57274814.3090208@i2se.com>

Hi Harald,

Am 01.05.2016 um 20:02 schrieb Jonathan Cameron:
> On 29/04/16 18:45, Harald Geyer wrote:
>> Hi Stefan!
>>
>> On 29.04.2016 17:12, Stefan Wahren wrote:
>>> Hi Harald,
>>>
>>> Am 22.04.2016 um 15:52 schrieb Harald Geyer:
>>>> Patch 1/3 changes the driver and updates the binding documentation
>>>> (I guess it is still in staging.)
>>>>
>>>> Patches 2/3 and 3/3 add the devicetree nodes to imx23 and imx28 boards.
>>>> I'd like to get input whether this is actually desired. On boards where
>>>> these regulators would never be enabled this costs a few extra bytes of
>>>> RAM for allocation of the device data, because the nodes can't be easily
>>>> removed in .dts files which are including the .dtsi files. The alternative
>>>> is to add the new nodes to many .dts files, which would be a lot code
>>>> duplication.
>>> if i get it right the real intention of this patch series is to make the
>>> mxs-lradc provide resistance values instead of voltages.
>> ... or even temperature values if a thermistor is connected.
>>
>>> So how about
>>> dropping the whole regulator stuff and provide the values as
>>> IIO_RESISTANCE via iio interface?
>> Can you elaborate on this?
>>
>> My thinking is that there should be a thermistor (or whatever else) driver,
>> that is a consumer of the regulator and a consumer of the IIO_VOLTAGE
>> iio channel and provides a new device with an IIO_RESISTANCE or IIO_TEMP
>> channel. Maybe there is a simpler solution, that I'm missing?
> I agree with that approach - need a way to describe the upstream hardware - so
> will need a thermistor driver

okay, this makes more sense to me. In this case it would be good to have
this new driver in this patch series. So it's possible to verify the
matching binding.

>> Actually I'm not 100% happy with the above solution myself, because if we
>> start supporting devices that act as an iio-multiplexer (some device that
>> is an iio consumer and provides many new iio channels and can control
>> via gpios which of it child channels is actually routed to the upstream
>> device) I don't know how to properly manage the regulator device.
> Hmm. Are you talking about muxing the regulator as well?  That will get
> complex indeed.  Might be possible to cheat and imply the regulators are
> always connected to all inputs...  or do you want to dynamically change
> the regulator output?  That gets messy fast - though in theory might be
> possible...
>> However since this is only hypothetical ATM, I think we don't have to
>> worry about this too much.
>>
>>> Btw this feature should be only added to dts files where is actually used.
>> Ok, so how do we figure out which boards these are?
>> I use this on the olinuxino and I guess all evaluation boards support the
>> use case too. The others I don't know enough about to be sure and I guess
>> it's not a good idea to just wait until somebody speaks up and complains
>> that the feature is missing on board X ...

The imx23 dtsi file specifies features on SoC level and i think this
should be kept. We shouldn't implement features for ADC pins without
deeper knowledge about these boards.

Maybe we could introduce a new dtsi file in order to reduce copy &
paste. But at first the OlinuXino should be a good starting point ...

Regards
Stefan



From tn at semihalf.com  Mon May  2 05:43:56 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 2 May 2016 14:43:56 +0200
Subject: [PATCH V6 02/13] pci, acpi: Provide generic way to assign bus
 domain number.
In-Reply-To: <20160427111758.GA6234@red-moon>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-3-git-send-email-tn@semihalf.com>
 <20160427022649.GD6789@localhost> <20160427111758.GA6234@red-moon>
Message-ID: <57274B8C.5030304@semihalf.com>

On 04/27/2016 01:17 PM, Lorenzo Pieralisi wrote:
> On Tue, Apr 26, 2016 at 09:26:49PM -0500, Bjorn Helgaas wrote:
>> On Fri, Apr 15, 2016 at 07:06:37PM +0200, Tomasz Nowicki wrote:
[...]
>>   
>> +int acpi_pci_bus_domain_nr(struct device *parent)
>> +{
>> +	struct acpi_device *acpi_dev = to_acpi_device(parent);
>> +	unsigned long long segment = 0;
>> +	acpi_status status;
>> +
>> +	/*
>> +	 * If _SEG method does not exist, following ACPI spec (6.5.6)
>> +	 * all PCI buses belong to domain 0.
>> +	 */
>> +	status = acpi_evaluate_integer(acpi_dev->handle, METHOD_NAME__SEG, NULL,
>> +				       &segment);
>> We already have code in acpi_pci_root_add() to evaluate _SEG.  We
>> don't want to evaluate it *twice*, do we?
>>
>> I was sort of expecting that if you added it here, we'd remove the
>> existing call, but it looks like you're keeping both?
> We can't remove the existing call, since it is used on X86 and IA64
> to store the segment number that, in the process, is used in their
> pci_domain_nr() arch specific callback to retrieve the domain nr.
>
> On ARM64, that selects PCI_DOMAINS_GENERIC, we have to find a way
> to retrieve the domain number that is not arch dependent, since
> this is generic code, we can't rely on any bus->sysdata format (unless
> we do something like JC did below), therefore the only way is to call
> the _SEG method *again* here, which also forced Tomasz to go through
> the ACPI_COMPANION setting song and dance and pass the parent pointer
> to pci_create_root_bus() (see patch 1), which BTW is a source of
> trouble on its own as you noticed.
What trouble in patch 1 do you mean? I may miss something.

I agree that patch 1 is not necessary if we decide to use sysdata or 
rework root bus scanning to move domain to host bridge. Nevertheless, 
patch 1 is still a cleanup IMO.

Thanks,
Tomasz


From jason at lakedaemon.net  Mon May  2 05:54:14 2016
From: jason at lakedaemon.net (Jason Cooper)
Date: Mon, 2 May 2016 12:54:14 +0000
Subject: [PATCH v6 00/10] arm64: Add support for KVM with ACPI
In-Reply-To: <57220C73.7010900@arm.com>
References: <1460388780-914-1-git-send-email-julien.grall@arm.com>
 <57220C73.7010900@arm.com>
Message-ID: <20160502125414.GR27057@io.lakedaemon.net>

On Thu, Apr 28, 2016 at 02:13:23PM +0100, Marc Zyngier wrote:
> [+ Thomas, Jason]
> 
> Do you have any objection against this going through the KVM tree? The
> dependencies are rather intricate, and Daniel gave us his green light
> already for the clocksource part.
> 
> If you'd rather maintain the usual flow, please let us know and we'll
> deal with it.

I've no objection.

Acked-by: Jason Cooper <jason at lakedaemon.net>

thx,

Jason.


From kamlakant.patel at broadcom.com  Mon May  2 06:12:41 2016
From: kamlakant.patel at broadcom.com (Kamlakant Patel)
Date: Mon, 2 May 2016 18:42:41 +0530
Subject: [PATCH] arm64: vulcan: enable GPIOLIB in Kconfig
In-Reply-To: <CACRpkdY07afPyo35Fh25FXPCXED8UymbwS3AbqFnGauSmRHMwA@mail.gmail.com>
References: <1461819767-17539-1-git-send-email-kamlakant.patel@broadcom.com>
 <CACRpkdY07afPyo35Fh25FXPCXED8UymbwS3AbqFnGauSmRHMwA@mail.gmail.com>
Message-ID: <CAB=aS0NbfH-YRJKtZ1N_OukpdXXdYeQTnuSBSP1HnCWoYSV2cw@mail.gmail.com>

Hi Linus,

On Sat, Apr 30, 2016 at 2:02 PM, Linus Walleij <linus.walleij at linaro.org> wrote:
> On Thu, Apr 28, 2016 at 7:02 AM,  <kamlakant.patel at broadcom.com> wrote:
>
>> From: Kamlakant Patel <kamlakant.patel at broadcom.com>
>>
>> Add select GPIOLIB in Kconfig for Broadcom Vulcan ARM64 GPIO driver.
>>
>> Signed-off-by: Kamlakant Patel <kamlakant.patel at broadcom.com>
>
> Acked-by: Linus Walleij <linus.walleij at linaro.org>
>
> But don't you also want to select the actual driver?
>
Vulcan GPIO is compatible with gpio/gpio-xlp.c driver. We have already
updated gpio/Kconfig for this.
I will send the device tree changes in next patch.


Thanks,
Kamlakant Patel


From arnd at arndb.de  Mon May  2 06:23:12 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 02 May 2016 15:23:12 +0200
Subject: [PATCH v2] asm-generic: Drop renameat syscall from default list
In-Reply-To: <C2D7FE5348E1B147BCA15975FBA23075F4EA010A@us01wembx1.internal.synopsys.com>
References: <1461965366-7893-1-git-send-email-james.hogan@imgtec.com>
 <C2D7FE5348E1B147BCA15975FBA23075F4EA010A@us01wembx1.internal.synopsys.com>
Message-ID: <5769874.XvA4zrbPZs@wuerfel>

On Monday 02 May 2016 05:13:46 Vineet Gupta wrote:
> On Saturday 30 April 2016 02:59 AM, James Hogan wrote:
> > The newer renameat2 syscall provides all the functionality provided by
> > the renameat syscall and adds flags, so future architectures won't need
> > to include renameat.
> >
> > Therefore drop the renameat syscall from the generic syscall list unless
> > __ARCH_WANT_RENAMEAT is defined by the architecture's unistd.h prior to
> > including asm-generic/unistd.h, and adjust all architectures using the
> > generic syscall list to define it so that no in-tree architectures are
> > affected.
> >
> > Signed-off-by: James Hogan <james.hogan at imgtec.com>
> 
> Acked-by: Vineet Gupta <vgupta at synopsys.com>  # for arch/arc

Applied to the asm-generic, tree, thanks!

	Arnd


From jchandra at broadcom.com  Mon May  2 06:26:13 2016
From: jchandra at broadcom.com (Jayachandran C)
Date: Mon, 2 May 2016 18:56:13 +0530
Subject: [PATCH V6 02/13] pci, acpi: Provide generic way to assign bus
 domain number.
In-Reply-To: <57274B8C.5030304@semihalf.com>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-3-git-send-email-tn@semihalf.com>
 <20160427022649.GD6789@localhost>
 <20160427111758.GA6234@red-moon> <57274B8C.5030304@semihalf.com>
Message-ID: <CAKc_7PU1AszF4y0OjZ3KVGaTEx9OL1cuT5YgOxQKhAQgQom7tA@mail.gmail.com>

On Mon, May 2, 2016 at 6:13 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> On 04/27/2016 01:17 PM, Lorenzo Pieralisi wrote:
>>
>> On Tue, Apr 26, 2016 at 09:26:49PM -0500, Bjorn Helgaas wrote:
>>>
>>> On Fri, Apr 15, 2016 at 07:06:37PM +0200, Tomasz Nowicki wrote:
>
> [...]
>
>>>   +int acpi_pci_bus_domain_nr(struct device *parent)
>>> +{
>>> +       struct acpi_device *acpi_dev = to_acpi_device(parent);
>>> +       unsigned long long segment = 0;
>>> +       acpi_status status;
>>> +
>>> +       /*
>>> +        * If _SEG method does not exist, following ACPI spec (6.5.6)
>>> +        * all PCI buses belong to domain 0.
>>> +        */
>>> +       status = acpi_evaluate_integer(acpi_dev->handle,
>>> METHOD_NAME__SEG, NULL,
>>> +                                      &segment);
>>> We already have code in acpi_pci_root_add() to evaluate _SEG.  We
>>> don't want to evaluate it *twice*, do we?
>>>
>>> I was sort of expecting that if you added it here, we'd remove the
>>> existing call, but it looks like you're keeping both?
>>
>> We can't remove the existing call, since it is used on X86 and IA64
>> to store the segment number that, in the process, is used in their
>> pci_domain_nr() arch specific callback to retrieve the domain nr.
>>
>> On ARM64, that selects PCI_DOMAINS_GENERIC, we have to find a way
>> to retrieve the domain number that is not arch dependent, since
>> this is generic code, we can't rely on any bus->sysdata format (unless
>> we do something like JC did below), therefore the only way is to call
>> the _SEG method *again* here, which also forced Tomasz to go through
>> the ACPI_COMPANION setting song and dance and pass the parent pointer
>> to pci_create_root_bus() (see patch 1), which BTW is a source of
>> trouble on its own as you noticed.
>
> What trouble in patch 1 do you mean? I may miss something.
>
> I agree that patch 1 is not necessary if we decide to use sysdata or rework
> root bus scanning to move domain to host bridge. Nevertheless, patch 1 is
> still a cleanup IMO.

In this case, getting the domain should be trivial since the ACPI
companion on parent is already set, this should work

int acpi_pci_bus_domain_nr(struct device *parent)
{
        struct acpi_device *acpi_dev = to_acpi_device(parent);
        struct acpi_pci_root *root = acpi_dev->driver_data;

        return root->segment;
}

Or am I missing something here?

JC.


From arnd at arndb.de  Mon May  2 06:36:08 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 02 May 2016 15:36:08 +0200
Subject: [PATCH v2 1/2] pinctrl: ns2: add pinmux driver support for
 Broadcom NS2 SoC
In-Reply-To: <1461934299-14774-2-git-send-email-yendapally.reddy@broadcom.com>
References: <1461934299-14774-1-git-send-email-yendapally.reddy@broadcom.com>
 <1461934299-14774-2-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <7673779.BeEs3iufq4@wuerfel>

On Friday 29 April 2016 08:51:38 Yendapally Reddy Dhananjaya Reddy wrote:
> +static struct pinctrl_ops ns2_pinctrl_ops = {
> +       .get_groups_count = ns2_get_groups_count,
> +       .get_group_name = ns2_get_group_name,
> +       .get_group_pins = ns2_get_group_pins,
> +       .pin_dbg_show = ns2_pin_dbg_show,
> +       .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
> +       .dt_free_map = pinctrl_utils_dt_free_map,
> +};
> +

This does not build:

drivers/pinctrl/bcm/pinctrl-ns2-mux.c:540:17: error: 'pinctrl_utils_dt_free_map' undeclared here (not in a function)
  .dt_free_map = pinctrl_utils_dt_free_map,
                 ^~~~~~~~~~~~~~~~~~~~~~~~~

Apparently this function got renamed to pinctrl_utils_free_map

	Arnd


From hverkuil at xs4all.nl  Mon May  2 06:40:01 2016
From: hverkuil at xs4all.nl (Hans Verkuil)
Date: Mon, 2 May 2016 15:40:01 +0200
Subject: [RFT PATCH 0/3] usb: misc: usb3503: Fix missing device when TFTP
 booting
In-Reply-To: <20160501164252.GA3581@kozik-lap>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <57247E50.1020000@xs4all.nl> <20160501131746.GA16766@kozik-lap>
 <57260E1E.70205@xs4all.nl> <57262844.7060809@xs4all.nl>
 <20160501164252.GA3581@kozik-lap>
Message-ID: <572758B1.60202@xs4all.nl>

On 05/01/16 18:42, Krzysztof Kozlowski wrote:
> On Sun, May 01, 2016 at 06:01:08PM +0200, Hans Verkuil wrote:
>>> Sorry, I meant the hanging issue I got in 4.6, not the ethernet issue.
>>> I get the same problem with linux-next. Can you mail me the .config you are using?
>>
>> Never mind.
>>
>>> After some more testing I don't think it is hanging, instead it seems that the mmc
>>> isn't enabled/found and so it just sits waiting for the root partition to appear.
>>
>> That was fun. There are two problems that both caused the boot to end at the same
>> place: first of all the root partition is now called mmcblk1p1 instead of mmcblk0p1
>> in 4.6, so it was just waiting for the root partition to appear. Nothing to do with
>> your patch series, just unexpected.
> 
> Yes, annoying issue and unfortunately this is known... recommended
> solution is to use root=PARTUUID=xxxx (you can get the PARTUUID with
> blkid)... or replace the mmc device.
> 
>> The second is that enabling CONFIG_VIDEO_S5P_FIMC causes the boot to hang at that
>> same place. I suspect there is a deadlock somewhere. I'm digging deeper into that
>> but again, unrelated to your patch series.
>>
>> Anyway, after disabling that config option I was finally able to test your patch
>> series:
>>
>> Tested-by: Hans Verkuil <hans.verkuil at cisco.com>

BTW, one thing I noticed is that to have u-boot detect the network device I
need to call 'usb reset' twice. This is with u-boot 2016.1 release.

Not a big deal, but I wondered if you see the same.

Regards,

	Hans


From petr at barix.com  Mon May  2 06:40:38 2016
From: petr at barix.com (Petr Kulhavy)
Date: Mon,  2 May 2016 15:40:38 +0200
Subject: [PATCH 1/2] ARM: DTS: da850: add pinmux configuration for mmc1
Message-ID: <1462196439-4693-1-git-send-email-petr@barix.com>

The da850.dtsi defined a pinmux configuration only for MMC0
and not for MMC1.
This adds a (4-bit) pinmux configuration for MMC1.

Signed-off-by: Petr Kulhavy <petr at barix.com>
---
 arch/arm/boot/dts/da850.dtsi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index 226cda76e77c..4983b3d0be55 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -72,6 +72,22 @@
 					0x28 0x00222222  0x00ffffff
 				>;
 			};
+			mmc1_pins: pinmux_mmc1_pins {
+				pinctrl-single,bits = <
+					/*
+					 * PINMUX18:
+					 * MMCSD1_CMD MMCSD1_CLK
+					 * MMCSD0_DAT[0]
+					 */
+					0x48 0x00022200  0x000fff00
+					/*
+					 * PINMUX19:
+					 * MMCSD0_DAT[1] MMCSD0_DAT[2]
+					 * MMCSD0_DAT[3]
+					 */
+					0x4c 0x00022200  0x000fff00
+				>;
+			};
 			ehrpwm0a_pins: pinmux_ehrpwm0a_pins {
 				pinctrl-single,bits = <
 					/* EPWM0A */
-- 
1.9.1



From petr at barix.com  Mon May  2 06:40:39 2016
From: petr at barix.com (Petr Kulhavy)
Date: Mon,  2 May 2016 15:40:39 +0200
Subject: [PATCH 2/2] ARM: davinci: da8xx-dt: add OF_DEV_AUXDATA entry for mmc1
In-Reply-To: <1462196439-4693-1-git-send-email-petr@barix.com>
References: <1462196439-4693-1-git-send-email-petr@barix.com>
Message-ID: <1462196439-4693-2-git-send-email-petr@barix.com>

The da8xx-dt.c contained OF_DEV_AUXDATA entry for mmc0 only. The usage of
mmc1 was not possible from device tree because the probe was failing to
get the related MMC clock.

Add OF_DEV_AUXDATA entry for mmc1 in order to be able to use the mmc1
clocks and therefore the mmc1 interface.

Signed-off-by: Petr Kulhavy <petr at barix.com>
---
 arch/arm/mach-davinci/da8xx-dt.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c
index c4b5808ca7c1..115c316e9b76 100644
--- a/arch/arm/mach-davinci/da8xx-dt.c
+++ b/arch/arm/mach-davinci/da8xx-dt.c
@@ -34,6 +34,7 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("ti,davinci-i2c", 0x01c22000, "i2c_davinci.1", NULL),
 	OF_DEV_AUXDATA("ti,davinci-wdt", 0x01c21000, "davinci-wdt", NULL),
 	OF_DEV_AUXDATA("ti,da830-mmc", 0x01c40000, "da830-mmc.0", NULL),
+	OF_DEV_AUXDATA("ti,da830-mmc", 0x01e1b000, "da830-mmc.1", NULL),
 	OF_DEV_AUXDATA("ti,da850-ehrpwm", 0x01f00000, "ehrpwm", NULL),
 	OF_DEV_AUXDATA("ti,da850-ehrpwm", 0x01f02000, "ehrpwm", NULL),
 	OF_DEV_AUXDATA("ti,da850-ecap", 0x01f06000, "ecap", NULL),
-- 
1.9.1



From k.kozlowski at samsung.com  Mon May  2 06:41:51 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 02 May 2016 15:41:51 +0200
Subject: [RFT PATCH 0/3] usb: misc: usb3503: Fix missing device when TFTP
 booting
In-Reply-To: <572758B1.60202@xs4all.nl>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <57247E50.1020000@xs4all.nl> <20160501131746.GA16766@kozik-lap>
 <57260E1E.70205@xs4all.nl> <57262844.7060809@xs4all.nl>
 <20160501164252.GA3581@kozik-lap> <572758B1.60202@xs4all.nl>
Message-ID: <5727591F.3000100@samsung.com>

On 05/02/2016 03:40 PM, Hans Verkuil wrote:
>>> Anyway, after disabling that config option I was finally able to test your patch
>>> series:
>>>
>>> Tested-by: Hans Verkuil <hans.verkuil at cisco.com>
> 
> BTW, one thing I noticed is that to have u-boot detect the network device I
> need to call 'usb reset' twice. This is with u-boot 2016.1 release.
> 
> Not a big deal, but I wondered if you see the same.

Yes, I also have to do it twice.

Best regards,
Krzysztof



From ynorov at caviumnetworks.com  Mon May  2 06:47:06 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Mon, 2 May 2016 16:47:06 +0300
Subject: [question] pread2, pwrite2 unistd symbols for compat
Message-ID: <20160502134706.GA11396@yury-N73SV>

Hi Andre, 

In patch 987aedb5d (eneric syscalls: wire up preadv2 and pwritev2
syscalls) you add those syscalls with __SYSCALL macro. However,
compat architectures that does not use generic unistd (mips, s390),
declare compat version in their syscall tables. Maybe we'd replace
__SYSCALL macro with __SC_COMP?

Yury.


diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 723479c..6ed4613 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -721,9 +721,9 @@ __SC_WRAP(__NR_mlock2, sys_mlock2)
 #define __NR_copy_file_range 285
 __SC_WRAP(__NR_copy_file_range, sys_copy_file_range)
 #define __NR_preadv2 286
-__SYSCALL(__NR_preadv2, sys_preadv2)
+__SC_COMP(__NR_preadv2, sys_preadv2, compat_sys_preadv2)
 #define __NR_pwritev2 287
-__SYSCALL(__NR_pwritev2, sys_pwritev2)
+__SC_COMP(__NR_pwritev2, sys_pwritev2, compat_sys_pwritev2)
 
 #undef __NR_syscalls
 #define __NR_syscalls 288


From stefan.wahren at i2se.com  Mon May  2 06:55:53 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Mon, 2 May 2016 15:55:53 +0200
Subject: [PATCH v2] nvmem/mxs-ocotp: fix buffer overflow in read
In-Reply-To: <1f26dfe5-c75f-39df-e21e-77aeea408258@meduna.org>
References: <1f26dfe5-c75f-39df-e21e-77aeea408258@meduna.org>
Message-ID: <57275C69.9060902@i2se.com>

Hi Srinivas,
hi Greg,

Am 27.04.2016 um 14:39 schrieb Stanislav Meduna:
> This patch fixes the issue where the mxs_ocotp_read is reading
> the ocotp in reg_size steps but decrements the remaining size
> by 1. The number of iterations is thus four times higher,
> overwriting the area behind the output buffer.
>
> Fixes: c01e9a11ab6f ("nvmem: add driver for ocotp in i.MX23 and i.MX28")
> Tested-by: Stefan Wahren <stefan.wahren at i2se.com>
> Signed-off-by: Stanislav Meduna <stano at meduna.org>

any change to get this critical fix into 4.6?

Regards
Stefan

> ---
>  drivers/nvmem/mxs-ocotp.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/nvmem/mxs-ocotp.c b/drivers/nvmem/mxs-ocotp.c
> index 8ba19bb..2bb3c57 100644
> --- a/drivers/nvmem/mxs-ocotp.c
> +++ b/drivers/nvmem/mxs-ocotp.c
> @@ -94,7 +94,7 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
>  	if (ret)
>  		goto close_banks;
>
> -	while (val_size) {
> +	while (val_size >= reg_size) {
>  		if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) {
>  			/* fill up non-data register */
>  			*buf = 0;
> @@ -103,7 +103,7 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
>  		}
>
>  		buf++;
> -		val_size--;
> +		val_size -= reg_size;
>  		offset += reg_size;
>  	}
>



From robh at kernel.org  Mon May  2 07:00:32 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 2 May 2016 09:00:32 -0500
Subject: [PATCH] of: include errno.h in of_graph.h
In-Reply-To: <1462186769-2205767-1-git-send-email-arnd@arndb.de>
References: <1462186769-2205767-1-git-send-email-arnd@arndb.de>
Message-ID: <20160502140032.GA12801@rob-hp-laptop>

On Mon, May 02, 2016 at 12:59:19PM +0200, Arnd Bergmann wrote:
> When CONFIG_OF is disabled, we have to include linux/errno.h before
> including of_graph.h, or get build errors like in the newly added
> sun4i drm driver:
> 
> In file included from ../drivers/gpu/drm/sun4i/sun4i_drv.c:14:0:
> include/linux/of_graph.h: In function 'of_graph_parse_endpoint':
> include/linux/of_graph.h:58:10: error: 'ENOSYS' undeclared (first use in this function)
> 
> A better solution is to ensure that the header can be included
> by itself, so let's include linux/errno.h here to fix the error
> we just got, and any similar future error.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")
> ---
>  include/linux/of_graph.h | 1 +
>  1 file changed, 1 insertion(+)

Applied.

Rob


From slash.tmp at free.fr  Mon May  2 07:33:17 2016
From: slash.tmp at free.fr (Mason)
Date: Mon, 2 May 2016 16:33:17 +0200
Subject: [PATCH] ARM: dts: tango4: Update device tree
Message-ID: <5727652D.9020900@free.fr>

From: Marc Gonzalez <marc_gonzalez at sigmadesigns.com>

Match device tree with latest clock driver.
Update cpus node for cpufreq.
Import watchdog node.

Signed-off-by: Marc Gonzalez <marc_gonzalez at sigmadesigns.com>
---
This patch applies on top of the thermal DT changes.
[PATCH v8 2/2] ARM: dts: tango4: Initial thermal support
Acked-by: Eduardo Valentin <edubezval at gmail.com>
---
 arch/arm/boot/dts/tango4-common.dtsi      | 16 ++++++++++++----
 arch/arm/boot/dts/tango4-smp8758.dtsi     |  5 ++++-
 arch/arm/boot/dts/tango4-vantage-1172.dts |  1 -
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/tango4-common.dtsi b/arch/arm/boot/dts/tango4-common.dtsi
index ef665d21d317..dd7eb5f624d9 100644
--- a/arch/arm/boot/dts/tango4-common.dtsi
+++ b/arch/arm/boot/dts/tango4-common.dtsi
@@ -3,11 +3,13 @@
  * https://github.com/mansr/linux-tangox
  */
 
-#define CPU_CLK 0
-#define SYS_CLK 1
-
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
+#define  CPU_CLK	0
+#define  SYS_CLK	1
+#define  USB_CLK	2
+#define SDIO_CLK	3
+
 / {
 	interrupt-parent = <&gic>;
 	#address-cells = <1>;
@@ -70,7 +72,7 @@
 
 		clkgen: clkgen at 10000 {
 			compatible = "sigma,tango4-clkgen";
-			reg = <0x10000 0x40>;
+			reg = <0x10000 0x100>;
 			clocks = <&xtal>;
 			#clock-cells = <1>;
 		};
@@ -89,6 +91,12 @@
 			reg-shift = <2>;
 		};
 
+		watchdog at 1fd00 {
+			compatible = "sigma,smp8759-wdt";
+			reg = <0x1fd00 8>;
+			clocks = <&xtal>;
+		};
+
 		eth0: ethernet at 26000 {
 			compatible = "sigma,smp8734-ethernet";
 			reg = <0x26000 0x800>;
diff --git a/arch/arm/boot/dts/tango4-smp8758.dtsi b/arch/arm/boot/dts/tango4-smp8758.dtsi
index 01d5f8f1c71d..d2e65c46bcc7 100644
--- a/arch/arm/boot/dts/tango4-smp8758.dtsi
+++ b/arch/arm/boot/dts/tango4-smp8758.dtsi
@@ -1,4 +1,4 @@
-#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "tango4-common.dtsi"
 
 / {
 	cpus {
@@ -11,6 +11,9 @@
 			next-level-cache = <&l2cc>;
 			device_type = "cpu";
 			reg = <0>;
+			clocks = <&clkgen CPU_CLK>;
+			clock-latency = <1>;
+			operating-points = <1215000 0 607500 0 405000 0 243000 0 135000 0>;
 		};
 
 		cpu1: cpu at 1 {
diff --git a/arch/arm/boot/dts/tango4-vantage-1172.dts b/arch/arm/boot/dts/tango4-vantage-1172.dts
index 3e5b9c81a51c..4cab64cb581e 100644
--- a/arch/arm/boot/dts/tango4-vantage-1172.dts
+++ b/arch/arm/boot/dts/tango4-vantage-1172.dts
@@ -1,7 +1,6 @@
 /dts-v1/;
 
 #include "tango4-smp8758.dtsi"
-#include "tango4-common.dtsi"
 
 / {
 	model = "Sigma Designs SMP8758 Vantage-1172 Rev E1";
-- 
2.8.1


From matthias.bgg at gmail.com  Mon May  2 07:34:11 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 2 May 2016 16:34:11 +0200
Subject: [GIT PULL] ARM: mediatek soc updates for v4.7
Message-ID: <CABuKBeJV6bA=2Sx_apRp2HMfuyymFCV67zxaoJzBeRbRMzv0AQ@mail.gmail.com>

Hi all,

Please take the following patches for v4.7.

Thanks,
Matthias

---

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  https://github.com/mbgg/linux-mediatek.git tags/v4.6-next-soc

for you to fetch changes up to 601bac7638fa693204dc70035d2651474704967c:

  ARM: mediatek: enable gpt6 on boot up to make arch timer work on
mt7623 (2016-04-20 13:58:45 +0200)

----------------------------------------------------------------
- re-organize pmic wrapper code for easier and cleaner addiont of new
SoCs and pmic wrappers
- add support for pmic wrapper mt6323
- add support for SoC mt2701
- enable gpt6 arch timer on mt7623

----------------------------------------------------------------
John Crispin (11):
      soc: mediatek: PMIC wrap: don't duplicate the wrapper data
      soc: mediatek: PMIC wrap: add wrapper callbacks for init_reg_clock
      soc: mediatek: PMIC wrap: split SoC specific init into callback
      soc: mediatek: PMIC wrap: WRAP_INT_EN needs a different bitmask
for MT2701/7623
      soc: mediatek: PMIC wrap: SPI_WRITE needs a different bitmask
for MT2701/7623
      soc: mediatek: PMIC wrap: move wdt_src into the pmic_wrapper_type struct
      soc: mediatek: PMIC wrap: remove pwrap_is_mt8135() and pwrap_is_mt8173()
      soc: mediatek: PMIC wrap: add a slave specific struct
      soc: mediatek: PMIC wrap: add mt6323 slave support
      soc: mediatek: PMIC wrap: add MT2701/7623 support
      ARM: mediatek: enable gpt6 on boot up to make arch timer work on mt7623

 arch/arm/mach-mediatek/mediatek.c    |   1 +
 drivers/soc/mediatek/mtk-pmic-wrap.c | 544 ++++++++++++++++++++++++++---------
 2 files changed, 414 insertions(+), 131 deletions(-)


From matthias.bgg at gmail.com  Mon May  2 07:35:20 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 2 May 2016 16:35:20 +0200
Subject: [GIT PULL] ARM: mediatek: kconfig updates for v4.7
Message-ID: <CABuKBeLwgcZ10pcSoOBnOFhFOMzr9sjoj28Qbi1pqAXGt0h0GQ@mail.gmail.com>

Hi all,

Please take the following patches for v4.7.

Thanks,
Matthias

---

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  https://github.com/mbgg/linux-mediatek.git tags/v4.6-next-kconfig

for you to fetch changes up to d86786474babdf1a2b0dfe245e38f18afc203cc2:

  ARM: mediatek: Add MT2701 config options for mediatek SoCs.
(2016-04-13 11:31:56 +0200)

----------------------------------------------------------------
Add mt2701 support

----------------------------------------------------------------
Erin Lo (1):
      ARM: mediatek: Add MT2701 config options for mediatek SoCs.

 arch/arm/mach-mediatek/Kconfig | 4 ++++
 1 file changed, 4 insertions(+)


From matthias.bgg at gmail.com  Mon May  2 07:37:23 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 2 May 2016 16:37:23 +0200
Subject: [GIT PULL] ARM: mediatek: dts updates for v4.7
Message-ID: <CABuKBe+jtD4nLXFrxTxKJ_Fq9t9D9a_ibXsSkvvZw5e5p_fZeA@mail.gmail.com>

Hi all,

Please take the following updates.

Thanks,
Matthias

---

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  https://github.com/mbgg/linux-mediatek.git tags/v4.6-next-dts

for you to fetch changes up to 610175b7972afc78f0e4a622a17a32b1fccad4bf:

  dt-bindings: MediaTek: Add binding document for the AUXADC
(2016-04-20 13:32:57 +0200)

----------------------------------------------------------------
- add pinctrl node for mt2701
- add mt2701 pmic wrapper binding
- add auxadc binding document

----------------------------------------------------------------
Biao Huang (1):
      arm: dts: Add pinctrl/GPIO/EINT node for mt2701

John Crispin (1):
      dt-bindings: ARM: Mediatek: add MT2701/7623 string to the PMIC wrapper doc

Sascha Hauer (1):
      dt-bindings: MediaTek: Add binding document for the AUXADC

 .../devicetree/bindings/soc/mediatek/auxadc.txt     | 21 +++++++++++++++++++++
 .../devicetree/bindings/soc/mediatek/pwrap.txt      |  1 +
 arch/arm/boot/dts/mt2701.dtsi                       | 19 +++++++++++++++++++
 3 files changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/auxadc.txt


From matthias.bgg at gmail.com  Mon May  2 07:38:40 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 2 May 2016 16:38:40 +0200
Subject: [GIT PULL] ARM: mediatek: dts64 updates for v4.7
Message-ID: <CABuKBe+2KnF_WFvhZ9ROz3mqJm1jv_+WteHvubfJQhNfS7vuUA@mail.gmail.com>

Hi all,

Please feel free to pull the following patches.

Thanks a lot,
Matthias

---
The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  https://github.com/mbgg/linux-mediatek.git tags/v4.6-next-dts64

for you to fetch changes up to 962f5143b30568bf67be97365d0616b0050ddaa5:

  arm64: dts: mt8173: Add thermal zone node. (2016-04-21 15:55:11 +0200)

----------------------------------------------------------------
- add thermal and auxadc device nodes to mt8173
- add thermal zone nodes to mt8173

----------------------------------------------------------------
Sascha Hauer (1):
      ARM64: dts: mt8173: Add thermal/auxadc device nodes

dawei.chien at mediatek.com (1):
      arm64: dts: mt8173: Add thermal zone node.

 arch/arm64/boot/dts/mediatek/mt8173.dtsi | 60 ++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)


From paulmck at linux.vnet.ibm.com  Mon May  2 07:22:13 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon,  2 May 2016 07:22:13 -0700
Subject: [PATCH omap 3/6] arm: Additional _rcuidle tracepoints to allow use
 from idle
In-Reply-To: <20160502142117.GA2911@linux.vnet.ibm.com>
References: <20160502142117.GA2911@linux.vnet.ibm.com>
Message-ID: <1462198936-3496-3-git-send-email-paulmck@linux.vnet.ibm.com>

This commit adds an _rcuidle suffix to a pair of trace events to
prevent the following splat:

> ===============================
> [ INFO: suspicious RCU usage. ]
> 4.6.0-rc5-next-20160426+ #1114 Not tainted
> -------------------------------
> include/trace/events/clk.h:59 suspicious rcu_dereference_check() usage!
>
> other info that might help us debug this:
>
>
> RCU used illegally from idle CPU!
> rcu_scheduler_active = 1, debug_locks = 0
> RCU used illegally from extended quiescent state!
> 2 locks held by swapper/0/0:
>  #0:  (&oh->hwmod_key#30){......}, at: [<c0121b40>] omap_hwmod_idle+0x18/0x44
>  #1:  (enable_lock){......}, at: [<c0630998>] clk_enable_lock+0x18/0x124
>
> stack backtrace:
> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1114
> Hardware name: Generic OMAP36xx (Flattened Device Tree)
> [<c0110290>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
> [<c010c3a8>] (show_stack) from [<c047fd68>] (dump_stack+0xb0/0xe4)
> [<c047fd68>] (dump_stack) from [<c0631618>] (clk_core_disable+0x17c/0x348)
> [<c0631618>] (clk_core_disable) from [<c0632774>] (clk_disable+0x24/0x30)
> [<c0632774>] (clk_disable) from [<c0120590>] (_disable_clocks+0x18/0x7c)
> [<c0120590>] (_disable_clocks) from [<c0121680>] (_idle+0x12c/0x230)
> [<c0121680>] (_idle) from [<c0121b4c>] (omap_hwmod_idle+0x24/0x44)
> [<c0121b4c>] (omap_hwmod_idle) from [<c0122c24>] (omap_device_idle+0x3c/0x90)
> [<c0122c24>] (omap_device_idle) from [<c052cc00>] (__rpm_callback+0x2c/0x60)
> [<c052cc00>] (__rpm_callback) from [<c052cc54>] (rpm_callback+0x20/0x80)
> [<c052cc54>] (rpm_callback) from [<c052d150>] (rpm_suspend+0x100/0x768)
> [<c052d150>] (rpm_suspend) from [<c052ec58>] (__pm_runtime_suspend+0x64/0x84)
> [<c052ec58>] (__pm_runtime_suspend) from [<c04bf25c>] (omap2_gpio_prepare_for_idle+0x5
> c/0x70)
> [<c04bf25c>] (omap2_gpio_prepare_for_idle) from [<c0125568>] (omap_sram_idle+0x140/0x2
> 44)
> [<c0125568>] (omap_sram_idle) from [<c01269dc>] (omap3_enter_idle_bm+0xfc/0x1ec)
> [<c01269dc>] (omap3_enter_idle_bm) from [<c0601bdc>] (cpuidle_enter_state+0x80/0x3d4)
> [<c0601bdc>] (cpuidle_enter_state) from [<c0183b08>] (cpu_startup_entry+0x198/0x3a0)
> [<c0183b08>] (cpu_startup_entry) from [<c0b00c0c>] (start_kernel+0x354/0x3c8)
> [<c0b00c0c>] (start_kernel) from [<8000807c>] (0x8000807c)

Reported-by: Tony Lindgren <tony at atomide.com>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Tested-by: Tony Lindgren <tony at atomide.com>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Steven Rostedt <rostedt at goodmis.org>
Cc: <linux-omap at vger.kernel.org>
Cc: <linux-arm-kernel at lists.infradead.org>
---
 drivers/clk/clk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index fb74dc1f7520..4fa43c02d682 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -682,12 +682,12 @@ static void clk_core_disable(struct clk_core *core)
 	if (--core->enable_count > 0)
 		return;
 
-	trace_clk_disable(core);
+	trace_clk_disable_rcuidle(core);
 
 	if (core->ops->disable)
 		core->ops->disable(core->hw);
 
-	trace_clk_disable_complete(core);
+	trace_clk_disable_complete_rcuidle(core);
 
 	clk_core_disable(core->parent);
 }
-- 
2.5.2



From paulmck at linux.vnet.ibm.com  Mon May  2 07:22:15 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon,  2 May 2016 07:22:15 -0700
Subject: [PATCH omap 5/6] arm: Whack yet another event-trace-from-idle mole
In-Reply-To: <20160502142117.GA2911@linux.vnet.ibm.com>
References: <20160502142117.GA2911@linux.vnet.ibm.com>
Message-ID: <1462198936-3496-5-git-send-email-paulmck@linux.vnet.ibm.com>

This commit applies another _rcuidle suffix to fix an RCU use from
idle.

> ===============================
> [ INFO: suspicious RCU usage. ]
> 4.6.0-rc5-next-20160426+ #1122 Not tainted
> -------------------------------
> include/trace/events/rpm.h:69 suspicious rcu_dereference_check() usage!
>
> other info that might help us debug this:
>
>
> RCU used illegally from idle CPU!
> rcu_scheduler_active = 1, debug_locks = 0
> RCU used illegally from extended quiescent state!
> 1 lock held by swapper/0/0:
>  #0:  (&(&dev->power.lock)->rlock){-.-...}, at: [<c052e3dc>] __pm_runtime_resume+0x3c/0x64
>
> stack backtrace:
> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1122
> Hardware name: Generic OMAP36xx (Flattened Device Tree)
> [<c0110290>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
> [<c010c3a8>] (show_stack) from [<c047fd68>] (dump_stack+0xb0/0xe4)
> [<c047fd68>] (dump_stack) from [<c052e178>] (rpm_resume+0x5cc/0x7f4)
> [<c052e178>] (rpm_resume) from [<c052e3ec>] (__pm_runtime_resume+0x4c/0x64)
> [<c052e3ec>] (__pm_runtime_resume) from [<c04bf2c4>] (omap2_gpio_resume_after_idle+0x54/0x68)
> [<c04bf2c4>] (omap2_gpio_resume_after_idle) from [<c01269dc>] (omap3_enter_idle_bm+0xfc/0x1ec)
> [<c01269dc>] (omap3_enter_idle_bm) from [<c060198c>] (cpuidle_enter_state+0x80/0x3d4)
> [<c060198c>] (cpuidle_enter_state) from [<c0183b08>] (cpu_startup_entry+0x198/0x3a0)
> [<c0183b08>] (cpu_startup_entry) from [<c0b00c0c>] (start_kernel+0x354/0x3c8)
> [<c0b00c0c>] (start_kernel) from [<8000807c>] (0x8000807c)

Reported-by: Tony Lindgren <tony at atomide.com>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Tested-by: Tony Lindgren <tony at atomide.com>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Steven Rostedt <rostedt at goodmis.org>
Cc: <linux-omap at vger.kernel.org>
Cc: <linux-arm-kernel at lists.infradead.org>
---
 drivers/base/power/runtime.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index e4c2b8fdeff3..15b6d5b199d4 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -601,7 +601,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
 	struct device *parent = NULL;
 	int retval = 0;
 
-	trace_rpm_resume(dev, rpmflags);
+	trace_rpm_resume_rcuidle(dev, rpmflags);
 
  repeat:
 	if (dev->power.runtime_error)
@@ -764,7 +764,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
 		spin_lock_irq(&dev->power.lock);
 	}
 
-	trace_rpm_return_int(dev, _THIS_IP_, retval);
+	trace_rpm_return_int_rcuidle(dev, _THIS_IP_, retval);
 
 	return retval;
 }
-- 
2.5.2



From paulmck at linux.vnet.ibm.com  Mon May  2 07:21:17 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon, 2 May 2016 07:21:17 -0700
Subject: [PATCH omap 0/6] Fix OMAP uses of RCU from idle loop
Message-ID: <20160502142117.GA2911@linux.vnet.ibm.com>

Hello!

The following series fixes a number of uses of RCU from the idle loop.
These are all due to tracing, so the fix is simply to append _rcuidle
to the event-tracing call.

							Thanx, Paul

------------------------------------------------------------------------

 arch/arm/kernel/smp.c             |    2 +-
 arch/arm/mach-omap2/powerdomain.c |    9 +++++----
 drivers/base/power/runtime.c      |   14 +++++++-------
 drivers/clk/clk.c                 |    8 ++++----
 4 files changed, 17 insertions(+), 16 deletions(-)



From paulmck at linux.vnet.ibm.com  Mon May  2 07:22:14 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon,  2 May 2016 07:22:14 -0700
Subject: [PATCH omap 4/6] arm: Whack another event-trace-from-idle mole
In-Reply-To: <20160502142117.GA2911@linux.vnet.ibm.com>
References: <20160502142117.GA2911@linux.vnet.ibm.com>
Message-ID: <1462198936-3496-4-git-send-email-paulmck@linux.vnet.ibm.com>

This commit appends a few _rcuidle suffixes to fix the following
RCU-used-from-idle bug:

> ===============================
> [ INFO: suspicious RCU usage. ]
> 4.6.0-rc5-next-20160426+ #1116 Not tainted
> -------------------------------
> include/trace/events/rpm.h:95 suspicious rcu_dereference_check() usage!
>
> other info that might help us debug this:
>
>
> RCU used illegally from idle CPU!
> rcu_scheduler_active = 1, debug_locks = 0
> RCU used illegally from extended quiescent state!
> 1 lock held by swapper/0/0:
>  #0:  (&(&dev->power.lock)->rlock){-.-...}, at: [<c052cc2c>] __rpm_callback+0x58/0x60
>
> stack backtrace:
> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1116
> Hardware name: Generic OMAP36xx (Flattened Device Tree)
> [<c0110290>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
> [<c010c3a8>] (show_stack) from [<c047fd68>] (dump_stack+0xb0/0xe4)
> [<c047fd68>] (dump_stack) from [<c052d5d0>] (rpm_suspend+0x580/0x768)
> [<c052d5d0>] (rpm_suspend) from [<c052ec58>] (__pm_runtime_suspend+0x64/0x84)
> [<c052ec58>] (__pm_runtime_suspend) from [<c04bf25c>] (omap2_gpio_prepare_for_idle+0x5c/0x70)
> [<c04bf25c>] (omap2_gpio_prepare_for_idle) from [<c0125568>] (omap_sram_idle+0x140/0x244)
> [<c0125568>] (omap_sram_idle) from [<c01269dc>] (omap3_enter_idle_bm+0xfc/0x1ec)
> [<c01269dc>] (omap3_enter_idle_bm) from [<c0601bdc>] (cpuidle_enter_state+0x80/0x3d4)
> [<c0601bdc>] (cpuidle_enter_state) from [<c0183b08>] (cpu_startup_entry+0x198/0x3a0)
> [<c0183b08>] (cpu_startup_entry) from [<c0b00c0c>] (start_kernel+0x354/0x3c8)
> [<c0b00c0c>] (start_kernel) from [<8000807c>] (0x8000807c)

In the immortal words of Steven Rostedt, "*Whack* *Whack* *Whack*!!!"

Reported-by: Tony Lindgren <tony at atomide.com>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Tested-by: Tony Lindgren <tony at atomide.com>
Cc: Russell King <linux at arm.linux.org.uk>
WhACKED-by: Steven Rostedt <rostedt at goodmis.org>
Cc: <linux-omap at vger.kernel.org>
Cc: <linux-arm-kernel at lists.infradead.org>
---
 drivers/base/power/runtime.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index ad115568ce58..e4c2b8fdeff3 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -301,7 +301,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
 	int (*callback)(struct device *);
 	int retval;
 
-	trace_rpm_idle(dev, rpmflags);
+	trace_rpm_idle_rcuidle(dev, rpmflags);
 	retval = rpm_check_suspend_allowed(dev);
 	if (retval < 0)
 		;	/* Conditions are wrong. */
@@ -337,7 +337,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
 			dev->power.request_pending = true;
 			queue_work(pm_wq, &dev->power.work);
 		}
-		trace_rpm_return_int(dev, _THIS_IP_, 0);
+		trace_rpm_return_int_rcuidle(dev, _THIS_IP_, 0);
 		return 0;
 	}
 
@@ -352,7 +352,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
 	wake_up_all(&dev->power.wait_queue);
 
  out:
-	trace_rpm_return_int(dev, _THIS_IP_, retval);
+	trace_rpm_return_int_rcuidle(dev, _THIS_IP_, retval);
 	return retval ? retval : rpm_suspend(dev, rpmflags | RPM_AUTO);
 }
 
-- 
2.5.2



From paulmck at linux.vnet.ibm.com  Mon May  2 07:22:16 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon,  2 May 2016 07:22:16 -0700
Subject: [PATCH omap 6/6] arm: Whack an expected event-trace-from-idle mole
In-Reply-To: <20160502142117.GA2911@linux.vnet.ibm.com>
References: <20160502142117.GA2911@linux.vnet.ibm.com>
Message-ID: <1462198936-3496-6-git-send-email-paulmck@linux.vnet.ibm.com>

This commit fixes the RCU use-from-idle bug corresponding the following
splat:

> [ INFO: suspicious RCU usage. ]
> 4.6.0-rc5-next-20160426+ #1127 Not tainted
> -------------------------------
> include/trace/events/clk.h:45 suspicious rcu_dereference_check() usage!
>
> other info that might help us debug this:
>
>
> RCU used illegally from idle CPU!
> rcu_scheduler_active = 1, debug_locks = 0
> RCU used illegally from extended quiescent state!
> 2 locks held by swapper/0/0:
>  #0:  (&oh->hwmod_key#30){......}, at: [<c0121afc>] omap_hwmod_enable+0x18/0x44
>  #1:  (enable_lock){......}, at: [<c0630684>] clk_enable_lock+0x18/0x124
>
> stack backtrace:
> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1127
> Hardware name: Generic OMAP36xx (Flattened Device Tree)
> [<c0110290>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
> [<c010c3a8>] (show_stack) from [<c047fd68>] (dump_stack+0xb0/0xe4)
> [<c047fd68>] (dump_stack) from [<c06315c0>] (clk_core_enable+0x1e0/0x36c)
> [<c06315c0>] (clk_core_enable) from [<c0632298>] (clk_enable+0x1c/0x38)
> [<c0632298>] (clk_enable) from [<c01204e0>] (_enable_clocks+0x18/0x7c)
> [<c01204e0>] (_enable_clocks) from [<c012137c>] (_enable+0x114/0x2ec)
> [<c012137c>] (_enable) from [<c0121b08>] (omap_hwmod_enable+0x24/0x44)
> [<c0121b08>] (omap_hwmod_enable) from [<c0122ad0>] (omap_device_enable+0x3c/0x90)
> [<c0122ad0>] (omap_device_enable) from [<c0122b34>] (_od_runtime_resume+0x10/0x38)
> [<c0122b34>] (_od_runtime_resume) from [<c052cc00>] (__rpm_callback+0x2c/0x60)
> [<c052cc00>] (__rpm_callback) from [<c052cc54>] (rpm_callback+0x20/0x80)
> [<c052cc54>] (rpm_callback) from [<c052df7c>] (rpm_resume+0x3d0/0x6f0)
> [<c052df7c>] (rpm_resume) from [<c052e2e8>] (__pm_runtime_resume+0x4c/0x64)
> [<c052e2e8>] (__pm_runtime_resume) from [<c04bf2c4>] (omap2_gpio_resume_after_idle+0x54/0x68)
> [<c04bf2c4>] (omap2_gpio_resume_after_idle) from [<c01269dc>] (omap3_enter_idle_bm+0xfc/0x1ec)
> [<c01269dc>] (omap3_enter_idle_bm) from [<c0601888>] (cpuidle_enter_state+0x80/0x3d4)
> [<c0601888>] (cpuidle_enter_state) from [<c0183b08>] (cpu_startup_entry+0x198/0x3a0)
> [<c0183b08>] (cpu_startup_entry) from [<c0b00c0c>] (start_kernel+0x354/0x3c8)
> [<c0b00c0c>] (start_kernel) from [<8000807c>] (0x8000807c)

Reported-by: Tony Lindgren <tony at atomide.com>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Tested-by: Tony Lindgren <tony at atomide.com>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Steven Rostedt <rostedt at goodmis.org>
Cc: <linux-omap at vger.kernel.org>
Cc: <linux-arm-kernel at lists.infradead.org>
---
 drivers/clk/clk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 4fa43c02d682..ec83f404c1d2 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -735,12 +735,12 @@ static int clk_core_enable(struct clk_core *core)
 		if (ret)
 			return ret;
 
-		trace_clk_enable(core);
+		trace_clk_enable_rcuidle(core);
 
 		if (core->ops->enable)
 			ret = core->ops->enable(core->hw);
 
-		trace_clk_enable_complete(core);
+		trace_clk_enable_complete_rcuidle(core);
 
 		if (ret) {
 			clk_core_disable(core->parent);
-- 
2.5.2



From paulmck at linux.vnet.ibm.com  Mon May  2 07:22:11 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon,  2 May 2016 07:22:11 -0700
Subject: [PATCH omap 1/6] arm: Use _rcuidle tracepoint to allow use from idle
In-Reply-To: <20160502142117.GA2911@linux.vnet.ibm.com>
References: <20160502142117.GA2911@linux.vnet.ibm.com>
Message-ID: <1462198936-3496-1-git-send-email-paulmck@linux.vnet.ibm.com>

Testing on ARM encountered the following pair of lockdep-RCU splats:

------------------------------------------------------------------------

===============================
[ INFO: suspicious RCU usage. ]
4.6.0-rc4-next-20160422 #1 Not tainted
-------------------------------
include/trace/events/power.h:328 suspicious rcu_dereference_check() usage!

other info that might help us debug this:

RCU used illegally from idle CPU!
rcu_scheduler_active = 1, debug_locks = 0
RCU used illegally from extended quiescent state!
no locks held by swapper/0/0.

stack backtrace:
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc4-next-20160422 #1
Hardware name: Generic OMAP3-GP (Flattened Device Tree)
[<c010f55c>] (unwind_backtrace) from [<c010b64c>] (show_stack+0x10/0x14)
[<c010b64c>] (show_stack) from [<c047acbc>] (dump_stack+0xa8/0xe0)
[<c047acbc>] (dump_stack) from [<c012bc10>] (pwrdm_set_next_pwrst+0xf8/0x1cc)
[<c012bc10>] (pwrdm_set_next_pwrst) from [<c01269fc>] (omap3_enter_idle_bm+0x1b8/0x1e8)
[<c01269fc>] (omap3_enter_idle_bm) from [<c05fa0b8>] (cpuidle_enter_state+0x84/0x408)
[<c05fa0b8>] (cpuidle_enter_state) from [<c0182c1c>] (cpu_startup_entry+0x1c8/0x3f0)
[<c0182c1c>] (cpu_startup_entry) from [<c0b00c20>] (start_kernel+0x354/0x3cc)

------------------------------------------------------------------------

[<c010f55c>] (unwind_backtrace) from [<c010b64c>] (show_stack+0x10/0x14)
[<c010b64c>] (show_stack) from [<c047ac3c>] (dump_stack+0xa8/0xe0)
[<c047ac3c>] (dump_stack) from [<c012c340>] (_pwrdm_state_switch+0x188/0x32c)
[<c012c340>] (_pwrdm_state_switch) from [<c012c4f0>] (_pwrdm_post_transition_cb+0xc/0x14)
[<c012c4f0>] (_pwrdm_post_transition_cb) from [<c012ba74>] (pwrdm_for_each+0x30/0x5c)
[<c012ba74>] (pwrdm_for_each) from [<c012c72c>] (pwrdm_post_transition+0x24/0x30)
[<c012c72c>] (pwrdm_post_transition) from [<c012548c>] (omap_sram_idle+0xfc/0x240)
[<c012548c>] (omap_sram_idle) from [<c0126934>] (omap3_enter_idle_bm+0xf0/0x1e8)
[<c0126934>] (omap3_enter_idle_bm) from [<c05fa038>] (cpuidle_enter_state+0x84/0x408)
[<c05fa038>] (cpuidle_enter_state) from [<c0182b90>] (cpu_startup_entry+0x1c8/0x3f0)
[<c0182b90>] (cpu_startup_entry) from [<c0b00c20>] (start_kernel+0x354/0x3cc)

------------------------------------------------------------------------

These are caused by event tracing from the idle loop, and they were
exposed by commit 293e2421fe25 ("rcu: Remove superfluous versions of
rcu_read_lock_sched_held()"), which suppressed some false negatives.
The current commit therefore adds the _rcuidle suffix to make RCU aware
of this implicit use of RCU by event tracing, thus preventing both splats.

Reported-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Tested-by: Guenter Roeck <linux at roeck-us.net>
Tested-by: Tony Lindgren <tony at atomide.com>
Cc: Russell King <linux at arm.linux.org.uk>
Reviewed-by: Steven Rostedt <rostedt at goodmis.org>
Cc: <linux-omap at vger.kernel.org>
Cc: <linux-arm-kernel at lists.infradead.org>
---
 arch/arm/mach-omap2/powerdomain.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 78af6d8cf2e2..daf2753de7aa 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -186,8 +186,9 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 			trace_state = (PWRDM_TRACE_STATES_FLAG |
 				       ((next & OMAP_POWERSTATE_MASK) << 8) |
 				       ((prev & OMAP_POWERSTATE_MASK) << 0));
-			trace_power_domain_target(pwrdm->name, trace_state,
-						  smp_processor_id());
+			trace_power_domain_target_rcuidle(pwrdm->name,
+							  trace_state,
+							  smp_processor_id());
 		}
 		break;
 	default:
@@ -523,8 +524,8 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 
 	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) {
 		/* Trace the pwrdm desired target state */
-		trace_power_domain_target(pwrdm->name, pwrst,
-					  smp_processor_id());
+		trace_power_domain_target_rcuidle(pwrdm->name, pwrst,
+						  smp_processor_id());
 		/* Program the pwrdm desired target state */
 		ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
 	}
-- 
2.5.2



From paulmck at linux.vnet.ibm.com  Mon May  2 07:22:12 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon,  2 May 2016 07:22:12 -0700
Subject: [PATCH omap 2/6] arm: Use more _rcuidle tracepoints to allow use from
 idle
In-Reply-To: <20160502142117.GA2911@linux.vnet.ibm.com>
References: <20160502142117.GA2911@linux.vnet.ibm.com>
Message-ID: <1462198936-3496-2-git-send-email-paulmck@linux.vnet.ibm.com>

Further testing with false negatives suppressed by commit 293e2421fe25
("rcu: Remove superfluous versions of rcu_read_lock_sched_held()")
identified a few more unprotected uses of RCU from the idle loop.
Because RCU actively ignores idle-loop code (for energy-efficiency
reasons, among other things), using RCU from the idle loop can result
in too-short grace periods, in turn resulting in arbitrary misbehavior.

The resulting lockdep-RCU splats are as follows:

------------------------------------------------------------------------

===============================
[ INFO: suspicious RCU usage. ]
4.6.0-rc5-next-20160426+ #1112 Not tainted
-------------------------------
include/trace/events/ipi.h:35 suspicious rcu_dereference_check() usage!

other info that might help us debug this:

RCU used illegally from idle CPU!
rcu_scheduler_active = 1, debug_locks = 0
RCU used illegally from extended quiescent state!
no locks held by swapper/0/0.

stack backtrace:
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1112
Hardware name: Generic OMAP4 (Flattened Device Tree)
[<c0110308>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
[<c010c3a8>] (show_stack) from [<c047fec8>] (dump_stack+0xb0/0xe4)
[<c047fec8>] (dump_stack) from [<c010dcfc>] (smp_cross_call+0xbc/0x188)
[<c010dcfc>] (smp_cross_call) from [<c01c9e28>] (generic_exec_single+0x9c/0x15c)
[<c01c9e28>] (generic_exec_single) from [<c01ca0a0>] (smp_call_function_single_async+0 x38/0x9c)
[<c01ca0a0>] (smp_call_function_single_async) from [<c0603728>] (cpuidle_coupled_poke_others+0x8c/0xa8)
[<c0603728>] (cpuidle_coupled_poke_others) from [<c0603c10>] (cpuidle_enter_state_coupled+0x26c/0x390)
[<c0603c10>] (cpuidle_enter_state_coupled) from [<c0183c74>] (cpu_startup_entry+0x198/0x3a0)
[<c0183c74>] (cpu_startup_entry) from [<c0b00c0c>] (start_kernel+0x354/0x3c8)
[<c0b00c0c>] (start_kernel) from [<8000807c>] (0x8000807c)

------------------------------------------------------------------------

Warning from omap3
===============================
[ INFO: suspicious RCU usage. ]
4.6.0-rc5-next-20160426+ #1112 Not tainted
-------------------------------
include/trace/events/rpm.h:63 suspicious rcu_dereference_check() usage!

other info that might help us debug this:

RCU used illegally from idle CPU!
rcu_scheduler_active = 1, debug_locks = 0
RCU used illegally from extended quiescent state!
1 lock held by swapper/0/0:
 #0:  (&(&dev->power.lock)->rlock){-.-...}, at: [<c052ee24>] __pm_runtime_suspend+0x54/0x84

stack backtrace:
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1112
Hardware name: Generic OMAP36xx (Flattened Device Tree)
[<c0110308>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
[<c010c3a8>] (show_stack) from [<c047fec8>] (dump_stack+0xb0/0xe4)
[<c047fec8>] (dump_stack) from [<c052d7b4>] (rpm_suspend+0x604/0x7e4)
[<c052d7b4>] (rpm_suspend) from [<c052ee34>] (__pm_runtime_suspend+0x64/0x84)
[<c052ee34>] (__pm_runtime_suspend) from [<c04bf3bc>] (omap2_gpio_prepare_for_idle+0x5c/0x70)
[<c04bf3bc>] (omap2_gpio_prepare_for_idle) from [<c01255e8>] (omap_sram_idle+0x140/0x244)
[<c01255e8>] (omap_sram_idle) from [<c0126b48>] (omap3_enter_idle_bm+0xfc/0x1ec)
[<c0126b48>] (omap3_enter_idle_bm) from [<c0601db8>] (cpuidle_enter_state+0x80/0x3d4)
[<c0601db8>] (cpuidle_enter_state) from [<c0183c74>] (cpu_startup_entry+0x198/0x3a0)
[<c0183c74>] (cpu_startup_entry) from [<c0b00c0c>] (start_kernel+0x354/0x3c8)
[<c0b00c0c>] (start_kernel) from [<8000807c>] (0x8000807c)

------------------------------------------------------------------------

Reported-by: Tony Lindgren <tony at atomide.com>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Tested-by: Tony Lindgren <tony at atomide.com>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Steven Rostedt <rostedt at goodmis.org>
Cc: <linux-omap at vger.kernel.org>
Cc: <linux-arm-kernel at lists.infradead.org>
---
 arch/arm/kernel/smp.c        | 2 +-
 drivers/base/power/runtime.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index baee70267f29..7afe48ae5d76 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -486,7 +486,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = {
 
 static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
 {
-	trace_ipi_raise(target, ipi_types[ipinr]);
+	trace_ipi_raise_rcuidle(target, ipi_types[ipinr]);
 	__smp_cross_call(target, ipinr);
 }
 
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 4c7055009bd6..ad115568ce58 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -419,7 +419,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
 	struct device *parent = NULL;
 	int retval;
 
-	trace_rpm_suspend(dev, rpmflags);
+	trace_rpm_suspend_rcuidle(dev, rpmflags);
 
  repeat:
 	retval = rpm_check_suspend_allowed(dev);
@@ -549,7 +549,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
 	}
 
  out:
-	trace_rpm_return_int(dev, _THIS_IP_, retval);
+	trace_rpm_return_int_rcuidle(dev, _THIS_IP_, retval);
 
 	return retval;
 
-- 
2.5.2



From gregkh at linuxfoundation.org  Mon May  2 07:44:58 2016
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Mon, 2 May 2016 07:44:58 -0700
Subject: [PATCH v2] nvmem/mxs-ocotp: fix buffer overflow in read
In-Reply-To: <57275C69.9060902@i2se.com>
References: <1f26dfe5-c75f-39df-e21e-77aeea408258@meduna.org>
 <57275C69.9060902@i2se.com>
Message-ID: <20160502144458.GA15555@kroah.com>

On Mon, May 02, 2016 at 03:55:53PM +0200, Stefan Wahren wrote:
> Hi Srinivas,
> hi Greg,
> 
> Am 27.04.2016 um 14:39 schrieb Stanislav Meduna:
> > This patch fixes the issue where the mxs_ocotp_read is reading
> > the ocotp in reg_size steps but decrements the remaining size
> > by 1. The number of iterations is thus four times higher,
> > overwriting the area behind the output buffer.
> >
> > Fixes: c01e9a11ab6f ("nvmem: add driver for ocotp in i.MX23 and i.MX28")
> > Tested-by: Stefan Wahren <stefan.wahren at i2se.com>
> > Signed-off-by: Stanislav Meduna <stano at meduna.org>
> 
> any change to get this critical fix into 4.6?

This is the first I've seen this patch :(

Can you resend it in a format I can apply it in?

thanks,

greg k-h


From stefan.wahren at i2se.com  Mon May  2 07:50:51 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Mon, 2 May 2016 16:50:51 +0200
Subject: [PATCH v2] nvmem/mxs-ocotp: fix buffer overflow in read
In-Reply-To: <20160502144458.GA15555@kroah.com>
References: <1f26dfe5-c75f-39df-e21e-77aeea408258@meduna.org>
 <57275C69.9060902@i2se.com> <20160502144458.GA15555@kroah.com>
Message-ID: <5727694B.80708@i2se.com>

Hi Stano,

Am 02.05.2016 um 16:44 schrieb Greg Kroah-Hartman:
> On Mon, May 02, 2016 at 03:55:53PM +0200, Stefan Wahren wrote:
>> Hi Srinivas,
>> hi Greg,
>>
>> Am 27.04.2016 um 14:39 schrieb Stanislav Meduna:
>>> This patch fixes the issue where the mxs_ocotp_read is reading
>>> the ocotp in reg_size steps but decrements the remaining size
>>> by 1. The number of iterations is thus four times higher,
>>> overwriting the area behind the output buffer.
>>>
>>> Fixes: c01e9a11ab6f ("nvmem: add driver for ocotp in i.MX23 and i.MX28")
>>> Tested-by: Stefan Wahren <stefan.wahren at i2se.com>
>>> Signed-off-by: Stanislav Meduna <stano at meduna.org>
>> any change to get this critical fix into 4.6?
> This is the first I've seen this patch :(

sorry for this.

>
> Can you resend it in a format I can apply it in?

Could you please resend V2 to Greg?

Thanks
Stefan

>
> thanks,
>
> greg k-h
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



From srinivas.kandagatla at linaro.org  Mon May  2 07:58:56 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon, 2 May 2016 15:58:56 +0100
Subject: [PATCH v2] nvmem/mxs-ocotp: fix buffer overflow in read
In-Reply-To: <5727694B.80708@i2se.com>
References: <1f26dfe5-c75f-39df-e21e-77aeea408258@meduna.org>
 <57275C69.9060902@i2se.com> <20160502144458.GA15555@kroah.com>
 <5727694B.80708@i2se.com>
Message-ID: <57276B30.8080909@linaro.org>

Hi Stefan,


On 02/05/16 15:50, Stefan Wahren wrote:
> Hi Stano,
>
> Am 02.05.2016 um 16:44 schrieb Greg Kroah-Hartman:
>> On Mon, May 02, 2016 at 03:55:53PM +0200, Stefan Wahren wrote:
>>> Hi Srinivas,
>>> hi Greg,
>>>
>>> Am 27.04.2016 um 14:39 schrieb Stanislav Meduna:
>>>> This patch fixes the issue where the mxs_ocotp_read is reading
>>>> the ocotp in reg_size steps but decrements the remaining size
>>>> by 1. The number of iterations is thus four times higher,
>>>> overwriting the area behind the output buffer.
>>>>
>>>> Fixes: c01e9a11ab6f ("nvmem: add driver for ocotp in i.MX23 and i.MX28")
>>>> Tested-by: Stefan Wahren <stefan.wahren at i2se.com>
>>>> Signed-off-by: Stanislav Meduna <stano at meduna.org>
>>> any change to get this critical fix into 4.6?
>> This is the first I've seen this patch :(
>
> sorry for this.
>
>>
>> Can you resend it in a format I can apply it in?
>
> Could you please resend V2 to Greg?

I will re-send this patch to Greg in next few mins..

thanks,
srini

>
> Thanks
> Stefan
>
>>
>> thanks,
>>
>> greg k-h
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>


From srinivas.kandagatla at linaro.org  Mon May  2 08:05:11 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon,  2 May 2016 16:05:11 +0100
Subject: [PATCH v2] nvmem: mxs-ocotp: fix buffer overflow in read
Message-ID: <1462201511-3942-1-git-send-email-srinivas.kandagatla@linaro.org>

From: Stanislav Meduna <stano at meduna.org>

This patch fixes the issue where the mxs_ocotp_read is reading
the ocotp in reg_size steps but decrements the remaining size
by 1. The number of iterations is thus four times higher,
overwriting the area behind the output buffer.

Fixes: c01e9a11ab6f ("nvmem: add driver for ocotp in i.MX23 and i.MX28")
Tested-by: Stefan Wahren <stefan.wahren at i2se.com>
Signed-off-by: Stanislav Meduna <stano at meduna.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
---
 drivers/nvmem/mxs-ocotp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/nvmem/mxs-ocotp.c b/drivers/nvmem/mxs-ocotp.c
index 8ba19bb..2bb3c57 100644
--- a/drivers/nvmem/mxs-ocotp.c
+++ b/drivers/nvmem/mxs-ocotp.c
@@ -94,7 +94,7 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
 	if (ret)
 		goto close_banks;
 
-	while (val_size) {
+	while (val_size >= reg_size) {
 		if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) {
 			/* fill up non-data register */
 			*buf = 0;
@@ -103,7 +103,7 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
 		}
 
 		buf++;
-		val_size--;
+		val_size -= reg_size;
 		offset += reg_size;
 	}
 
-- 
2.5.0



From arnd at arndb.de  Mon May  2 08:20:22 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 02 May 2016 17:20:22 +0200
Subject: [question] pread2, pwrite2 unistd symbols for compat
In-Reply-To: <20160502134706.GA11396@yury-N73SV>
References: <20160502134706.GA11396@yury-N73SV>
Message-ID: <9552994.HgmuyIW9Ty@wuerfel>

On Monday 02 May 2016 16:47:06 Yury Norov wrote:
> Hi Andre, 
> 
> In patch 987aedb5d (eneric syscalls: wire up preadv2 and pwritev2
> syscalls) you add those syscalls with __SYSCALL macro. However,
> compat architectures that does not use generic unistd (mips, s390),
> declare compat version in their syscall tables. Maybe we'd replace
> __SYSCALL macro with __SC_COMP?

I think you are right and your change looks good.

After I got the original patch from Andre and the same one from Christoph,
I did not consider the possibility that they were both wrong and so I
applied Andre's version.

Can you resend the patch in proper form (with a Signed-off-by line,
rebased to mainline and with a changelog I can use)? I'll apply it as
soon as I get an Ack from Christoph then.

Thanks!

	Arnd

> diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
> index 723479c..6ed4613 100644
> --- a/include/uapi/asm-generic/unistd.h
> +++ b/include/uapi/asm-generic/unistd.h
> @@ -721,9 +721,9 @@ __SC_WRAP(__NR_mlock2, sys_mlock2)
>  #define __NR_copy_file_range 285
>  __SC_WRAP(__NR_copy_file_range, sys_copy_file_range)
>  #define __NR_preadv2 286
> -__SYSCALL(__NR_preadv2, sys_preadv2)
> +__SC_COMP(__NR_preadv2, sys_preadv2, compat_sys_preadv2)
>  #define __NR_pwritev2 287
> -__SYSCALL(__NR_pwritev2, sys_pwritev2)
> +__SC_COMP(__NR_pwritev2, sys_pwritev2, compat_sys_pwritev2)
>  
>  #undef __NR_syscalls
>  #define __NR_syscalls 288
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



From hch at lst.de  Mon May  2 08:22:48 2016
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 2 May 2016 17:22:48 +0200
Subject: [question] pread2, pwrite2 unistd symbols for compat
In-Reply-To: <9552994.HgmuyIW9Ty@wuerfel>
References: <20160502134706.GA11396@yury-N73SV> <9552994.HgmuyIW9Ty@wuerfel>
Message-ID: <20160502152248.GA716@lst.de>

On Mon, May 02, 2016 at 05:20:22PM +0200, Arnd Bergmann wrote:
> After I got the original patch from Andre and the same one from Christoph,
> I did not consider the possibility that they were both wrong and so I
> applied Andre's version.

It's because adding syscalls is simple a giant pain, full of pitfalls
that are completely non-obvious.  When asked to add syscalls for
architectures I can't personally test I'll have to rely on the test
bot giving me some feedback - and it seems the wrong thing here will
just silently pass without any notice.

The change looks fine to me, but then again I just demonstrated a complete
lack of clue on asm-generic syscalls..


From srinivas.kandagatla at linaro.org  Mon May  2 08:22:56 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon,  2 May 2016 16:22:56 +0100
Subject: [PATCH v2 0/2] nvmem: remove regmap dependency
Message-ID: <1462202578-15433-1-git-send-email-srinivas.kandagatla@linaro.org>

Hi Greg, 

This is v2 patchset for the leftover 2 patches on top of char-misc tree.

Changes since v1:
 - rebased mtk-efuse on top of char-misc
 - addressed concerns raised by Stefan Wahren.

Thanks,
srini

Srinivas Kandagatla (2):
  nvmem: mtk-efuse: remove nvmem regmap dependency
  nvmem: mxs-ocotp: remove nvmem regmap dependency

 drivers/nvmem/Kconfig     |  1 -
 drivers/nvmem/mtk-efuse.c | 47 ++++++++++++++++++---------
 drivers/nvmem/mxs-ocotp.c | 81 +++++++++++++----------------------------------
 3 files changed, 54 insertions(+), 75 deletions(-)

-- 
2.5.0



From srinivas.kandagatla at linaro.org  Mon May  2 08:22:58 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon,  2 May 2016 16:22:58 +0100
Subject: [PATCH v2 2/2] nvmem: mxs-ocotp: remove nvmem regmap dependency
In-Reply-To: <1462202578-15433-1-git-send-email-srinivas.kandagatla@linaro.org>
References: <1462202578-15433-1-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <1462202578-15433-3-git-send-email-srinivas.kandagatla@linaro.org>

This patch moves to nvmem support in the driver to use callback
instead of regmap.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
---
 drivers/nvmem/mxs-ocotp.c | 81 +++++++++++++----------------------------------
 1 file changed, 22 insertions(+), 59 deletions(-)

diff --git a/drivers/nvmem/mxs-ocotp.c b/drivers/nvmem/mxs-ocotp.c
index 2bb3c57..9bf59d6 100644
--- a/drivers/nvmem/mxs-ocotp.c
+++ b/drivers/nvmem/mxs-ocotp.c
@@ -25,7 +25,6 @@
 #include <linux/nvmem-provider.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
-#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/stmp_device.h>
 
@@ -66,11 +65,10 @@ static int mxs_ocotp_wait(struct mxs_ocotp *otp)
 	return 0;
 }
 
-static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
-			  void *val, size_t val_size)
+static int mxs_ocotp_read(void *context, unsigned int offset,
+			  void *val, size_t bytes)
 {
 	struct mxs_ocotp *otp = context;
-	unsigned int offset = *(u32 *)reg;
 	u32 *buf = val;
 	int ret;
 
@@ -94,17 +92,16 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
 	if (ret)
 		goto close_banks;
 
-	while (val_size >= reg_size) {
+	while (bytes) {
 		if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) {
 			/* fill up non-data register */
-			*buf = 0;
+			*buf++ = 0;
 		} else {
-			*buf = readl(otp->base + offset);
+			*buf++ = readl(otp->base + offset);
 		}
 
-		buf++;
-		val_size -= reg_size;
-		offset += reg_size;
+		bytes -= 4;
+		offset += 4;
 	}
 
 close_banks:
@@ -117,57 +114,29 @@ disable_clk:
 	return ret;
 }
 
-static int mxs_ocotp_write(void *context, const void *data, size_t count)
-{
-	/* We don't want to support writing */
-	return 0;
-}
-
-static bool mxs_ocotp_writeable_reg(struct device *dev, unsigned int reg)
-{
-	return false;
-}
-
 static struct nvmem_config ocotp_config = {
 	.name = "mxs-ocotp",
+	.stride = 16,
+	.word_size = 4,
 	.owner = THIS_MODULE,
+	.reg_read = mxs_ocotp_read,
 };
 
-static const struct regmap_range imx23_ranges[] = {
-	regmap_reg_range(OCOTP_DATA_OFFSET, 0x210),
-};
-
-static const struct regmap_access_table imx23_access = {
-	.yes_ranges = imx23_ranges,
-	.n_yes_ranges = ARRAY_SIZE(imx23_ranges),
-};
-
-static const struct regmap_range imx28_ranges[] = {
-	regmap_reg_range(OCOTP_DATA_OFFSET, 0x290),
-};
-
-static const struct regmap_access_table imx28_access = {
-	.yes_ranges = imx28_ranges,
-	.n_yes_ranges = ARRAY_SIZE(imx28_ranges),
+struct mxs_data {
+	int size;
 };
 
-static struct regmap_bus mxs_ocotp_bus = {
-	.read = mxs_ocotp_read,
-	.write = mxs_ocotp_write, /* make regmap_init() happy */
-	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
-	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+static const struct mxs_data imx23_data = {
+	.size = 0x210,
 };
 
-static struct regmap_config mxs_ocotp_config = {
-	.reg_bits = 32,
-	.val_bits = 32,
-	.reg_stride = 16,
-	.writeable_reg = mxs_ocotp_writeable_reg,
+static const struct mxs_data imx28_data = {
+	.size = 0x290,
 };
 
 static const struct of_device_id mxs_ocotp_match[] = {
-	{ .compatible = "fsl,imx23-ocotp", .data = &imx23_access },
-	{ .compatible = "fsl,imx28-ocotp", .data = &imx28_access },
+	{ .compatible = "fsl,imx23-ocotp", .data = &imx23_data },
+	{ .compatible = "fsl,imx28-ocotp", .data = &imx23_data },
 	{ /* sentinel */},
 };
 MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
@@ -175,6 +144,7 @@ MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
 static int mxs_ocotp_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct mxs_data *data;
 	struct mxs_ocotp *otp;
 	struct resource *res;
 	const struct of_device_id *match;
@@ -205,17 +175,10 @@ static int mxs_ocotp_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	access = match->data;
-	mxs_ocotp_config.rd_table = access;
-	mxs_ocotp_config.max_register = access->yes_ranges[0].range_max;
-
-	regmap = devm_regmap_init(dev, &mxs_ocotp_bus, otp, &mxs_ocotp_config);
-	if (IS_ERR(regmap)) {
-		dev_err(dev, "regmap init failed\n");
-		ret = PTR_ERR(regmap);
-		goto err_clk;
-	}
+	data = match->data;
 
+	ocotp_config.size = data->size;
+	ocotp_config.priv = otp;
 	ocotp_config.dev = dev;
 	otp->nvmem = nvmem_register(&ocotp_config);
 	if (IS_ERR(otp->nvmem)) {
-- 
2.5.0



From srinivas.kandagatla at linaro.org  Mon May  2 08:22:57 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon,  2 May 2016 16:22:57 +0100
Subject: [PATCH v2 1/2] nvmem: mtk-efuse: remove nvmem regmap dependency
In-Reply-To: <1462202578-15433-1-git-send-email-srinivas.kandagatla@linaro.org>
References: <1462202578-15433-1-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <1462202578-15433-2-git-send-email-srinivas.kandagatla@linaro.org>

This patch moves to nvmem support in the driver to use callback
instead of regmap.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
---
 drivers/nvmem/Kconfig     |  1 -
 drivers/nvmem/mtk-efuse.c | 47 ++++++++++++++++++++++++++++++++---------------
 2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 3041d48..5ff2189 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -50,7 +50,6 @@ config MTK_EFUSE
 	tristate "Mediatek SoCs EFUSE support"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
 	depends on HAS_IOMEM
-	select REGMAP_MMIO
 	help
 	  This is a driver to access hardware related data like sensor
 	  calibration, HDMI impedance etc.
diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c
index 9c49369..32fd572 100644
--- a/drivers/nvmem/mtk-efuse.c
+++ b/drivers/nvmem/mtk-efuse.c
@@ -14,15 +14,35 @@
 
 #include <linux/device.h>
 #include <linux/module.h>
+#include <linux/io.h>
 #include <linux/nvmem-provider.h>
 #include <linux/platform_device.h>
-#include <linux/regmap.h>
 
-static struct regmap_config mtk_regmap_config = {
-	.reg_bits = 32,
-	.val_bits = 32,
-	.reg_stride = 4,
-};
+static int mtk_reg_read(void *context,
+			unsigned int reg, void *_val, size_t bytes)
+{
+	void __iomem *base = context;
+	u32 *val = _val;
+	int i = 0, words = bytes / 4;
+
+	while (words--)
+		*val++ = readl(base + reg + (i++ * 4));
+
+	return 0;
+}
+
+static int mtk_reg_write(void *context,
+			 unsigned int reg, void *_val, size_t bytes)
+{
+	void __iomem *base = context;
+	u32 *val = _val;
+	int i = 0, words = bytes / 4;
+
+	while (words--)
+		writel(*val++, base + reg + (i++ * 4));
+
+	return 0;
+}
 
 static int mtk_efuse_probe(struct platform_device *pdev)
 {
@@ -30,7 +50,6 @@ static int mtk_efuse_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct nvmem_device *nvmem;
 	struct nvmem_config *econfig;
-	struct regmap *regmap;
 	void __iomem *base;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -42,14 +61,12 @@ static int mtk_efuse_probe(struct platform_device *pdev)
 	if (!econfig)
 		return -ENOMEM;
 
-	mtk_regmap_config.max_register = resource_size(res) - 1;
-
-	regmap = devm_regmap_init_mmio(dev, base, &mtk_regmap_config);
-	if (IS_ERR(regmap)) {
-		dev_err(dev, "regmap init failed\n");
-		return PTR_ERR(regmap);
-	}
-
+	econfig->stride = 4;
+	econfig->word_size = 4;
+	econfig->reg_read = mtk_reg_read;
+	econfig->reg_write = mtk_reg_write;
+	econfig->size = resource_size(res);
+	econfig->priv = base;
 	econfig->dev = dev;
 	econfig->owner = THIS_MODULE;
 	nvmem = nvmem_register(econfig);
-- 
2.5.0



From eric at anholt.net  Mon May  2 08:29:30 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon, 02 May 2016 08:29:30 -0700
Subject: [PATCH 2/2] clk: bcm2835: Skip PLLC clocks when deciding on a new
 clock parent
In-Reply-To: <C771F70C-2F88-49E1-A370-D76D13262C1E@martin.sperl.org>
References: <1461699585-6649-1-git-send-email-eric@anholt.net>
 <1461699585-6649-2-git-send-email-eric@anholt.net>
 <C771F70C-2F88-49E1-A370-D76D13262C1E@martin.sperl.org>
Message-ID: <878tzsiilh.fsf@eliezer.anholt.net>

Martin Sperl <kernel at martin.sperl.org> writes:

>> On 26.04.2016, at 21:39, Eric Anholt <eric at anholt.net> wrote:
>> 
>> If the firmware had set up a clock to source from PLLC, go along with
>> it.  But if we're looking for a new parent, we don't want to switch it
>> to PLLC because the firmware will force PLLC (and thus the AXI bus
>> clock) to different frequencies during over-temp/under-voltage,
>> without notification to Linux.
>> 
>> On my system, this moves the Linux-enabled HDMI state machine and DSI1
>> escape clock over to plld_per from pllc_per.  EMMC still ends up on
>> pllc_per, because the firmware had set it up to use that.
>> 
>> Signed-off-by: Eric Anholt <eric at anholt.net>
>> Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks")
>> ?
>
> I guess this patch looks to me as if it is a policy inside the kernel,
> which is AFAIK frowned upon.

Can you come up with a use for putting peripherals on PLLC ever, such
that we need choice?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/32cf10a4/attachment.sig>

From eric at anholt.net  Mon May  2 08:34:28 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon, 02 May 2016 08:34:28 -0700
Subject: [PATCH v5] ARM: bcm2835: dt: Add the ethernet to the device trees
In-Reply-To: <1462172811-24206-1-git-send-email-lkundrak@v3.sk>
References: <1462172811-24206-1-git-send-email-lkundrak@v3.sk>
Message-ID: <8737q0iid7.fsf@eliezer.anholt.net>

Lubomir Rintel <lkundrak at v3.sk> writes:

> The hub and the ethernet in its port 1 are hardwired on the board.
>
> Compared to the adapters that can be plugged into the USB ports, this
> one has no serial EEPROM to store its MAC. Nevertheless, the Raspberry Pi
> has the MAC address for this adapter in its ROM, accessible from its
> firmware.
>
> U-Boot can read out the address and set the local-mac-address property of the
> node with "ethernet" alias. Let's add the node so that U-Boot can do its
> business.
>
> Model B rev2 and Model B+ entries were verified by me, the hierarchy and
> pid/vid pair for the Version 2 was provided by Peter Chen. Original
> Model B is a blind shot, though very likely correct.
>
> Signed-off-by: Lubomir Rintel <lkundrak at v3.sk>
> Acked-by: Stephen Warren <swarren at wwwdotorg.org>
> ---

Applied to bcm2835-dt-next locally.  We've already sent out pull
requests for 4.7, so I'll push it once 4.7-rc1 happens.

Thanks!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/5a998f3f/attachment-0001.sig>

From eric at anholt.net  Mon May  2 08:36:18 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon, 02 May 2016 08:36:18 -0700
Subject: [PATCH V4 1/2] clk: bcm2835: mark enabled clocks with
 CLK_IS_CRITICAL
In-Reply-To: <1461951756-16804-2-git-send-email-kernel@martin.sperl.org>
References: <1461951756-16804-1-git-send-email-kernel@martin.sperl.org>
 <1461951756-16804-2-git-send-email-kernel@martin.sperl.org>
Message-ID: <87zis8h3pp.fsf@eliezer.anholt.net>

kernel at martin.sperl.org writes:

> From: Martin Sperl <kernel at martin.sperl.org>
>
> The bcm2835 firmware enables several clocks and plls before
> booting the linux kernel.
>
> These plls should never get disabled as it may result in a
> stopped system clock and more.
>
> So during probing we check if the clock is enabled
> and if it is then mark that clock with CLK_IS_CRITICAL.
>
> As a consequence this will also enable the corresponding
> parent plls and pll-divs.
>
> This is intended as a stop-gap until CLK_ENABLE_HAND_OFF
> becomes available, at which point it should be used instead.
>
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>

I still think that we don't want this patch.  We should be able to
disable clocks that the firmware turned on, unless they really need to
stay on.  If you have troubles on the upstream DT, let's talk about
individual clocks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/6d3b4a8c/attachment.sig>

From broonie at kernel.org  Mon May  2 08:40:23 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 2 May 2016 16:40:23 +0100
Subject: [PATCH v6] spi: orion.c: Add direct access mode
In-Reply-To: <8919835.yGyvx4h0Tr@wuerfel>
References: <1461147068-4829-1-git-send-email-sr@denx.de>
 <5726F7F3.9070700@denx.de> <8919835.yGyvx4h0Tr@wuerfel>
Message-ID: <20160502154023.GI6292@sirena.org.uk>

On Mon, May 02, 2016 at 09:28:34AM +0200, Arnd Bergmann wrote:
> On Monday 02 May 2016 08:47:15 Stefan Roese wrote:

> > Its been a while since v6 of this direct write access mode has been
> > posted. This is a gentle ping on its status.

> > Arnd / Mark, do you have any additional change requests or are you okay
> > with the current version?

Please don't send content free pings and please allow a reasonable time
for review.  People get busy, go on holiday, attend conferences and so 
on so unless there is some reason for urgency (like critical bug fixes)
please allow at least a couple of weeks for review.  If there have been
review comments then people may be waiting for those to be addressed.
Sending content free pings just adds to the mail volume (if they are
seen at all) and if something has gone wrong you'll have to resend the
patches anyway.

> - you now always send a multiple of four byte in each transfer, are
>   there any downsides in doing this, e.g. some SPI devices that might
>   get confused by receiving additional uninitialized data?

Yes, this will break a large proportion of devices.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/b84af846/attachment.sig>

From arnd at arndb.de  Mon May  2 08:40:30 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 02 May 2016 17:40:30 +0200
Subject: [question] pread2, pwrite2 unistd symbols for compat
In-Reply-To: <20160502152248.GA716@lst.de>
References: <20160502134706.GA11396@yury-N73SV> <9552994.HgmuyIW9Ty@wuerfel>
 <20160502152248.GA716@lst.de>
Message-ID: <1979597.XqcnTZ9GDk@wuerfel>

On Monday 02 May 2016 17:22:48 Christoph Hellwig wrote:
> On Mon, May 02, 2016 at 05:20:22PM +0200, Arnd Bergmann wrote:
> > After I got the original patch from Andre and the same one from Christoph,
> > I did not consider the possibility that they were both wrong and so I
> > applied Andre's version.
> 
> It's because adding syscalls is simple a giant pain, full of pitfalls
> that are completely non-obvious.  When asked to add syscalls for
> architectures I can't personally test I'll have to rely on the test
> bot giving me some feedback - and it seems the wrong thing here will
> just silently pass without any notice.
> 
> The change looks fine to me, but then again I just demonstrated a complete
> lack of clue on asm-generic syscalls..

Ok, so I didn't miss anything obvious here and will forward the patch
as soon as Yury sends it.

I guess this is one more reason for me to finally do the job of
generalizing the system call tables to the point where we only
add them in one place of the kernel. There are probably 22 new syscalls
we need for 64-bit time_t, so doing it right then can also some
copy-paste errors.

	Arnd


From broonie at kernel.org  Mon May  2 08:44:41 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 2 May 2016 16:44:41 +0100
Subject: [PATCH v7] spi: orion.c: Add direct access mode
In-Reply-To: <1462187964-21876-1-git-send-email-sr@denx.de>
References: <1462187964-21876-1-git-send-email-sr@denx.de>
Message-ID: <20160502154441.GJ6292@sirena.org.uk>

On Mon, May 02, 2016 at 01:19:24PM +0200, Stefan Roese wrote:

> +	if ((orion_spi->direct_access[cs].vaddr) && (xfer->tx_buf) &&
> +	    (word_len == 8)) {
> +		unsigned int cnt = count >> 2;
> +		unsigned int rem = count % 4;

For the benefit of readers please write divisions as divisions and let
the compiler figure out if they can be turned into shifts.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/bf2b69b6/attachment.sig>

From eric.auger at linaro.org  Mon May  2 08:48:13 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 2 May 2016 17:48:13 +0200
Subject: [PATCH v8 6/8] iommu/msi-iommu: iommu_msi_domain
In-Reply-To: <20160428162740.28db4b8d@t450s.home>
References: <1461831323-5480-1-git-send-email-eric.auger@linaro.org>
 <1461831323-5480-7-git-send-email-eric.auger@linaro.org>
 <20160428162740.28db4b8d@t450s.home>
Message-ID: <572776BD.2080503@linaro.org>

Hi Alex,
On 04/29/2016 12:27 AM, Alex Williamson wrote:
> On Thu, 28 Apr 2016 08:15:21 +0000
> Eric Auger <eric.auger at linaro.org> wrote:
> 
>> This function checks whether
>> - the device belongs to a non default iommu domain
>> - this iommu domain requires the MSI address to be mapped.
>>
>> If those conditions are met, the function returns the iommu domain
>> to be used for mapping the MSI doorbell; else it returns NULL.
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>
>> ---
>>
>> v7 -> v8:
>> - renamed  iommu_msi_mapping_desc_to_domain to iommu_msi_domain
>> - the function now takes a struct device *
>> - use DOMAIN_ATTR_MSI_GEOMETRY attribute
>> ---
>>  drivers/iommu/msi-iommu.c | 17 +++++++++++++++++
>>  include/linux/msi-iommu.h | 14 ++++++++++++++
>>  2 files changed, 31 insertions(+)
>>
>> diff --git a/drivers/iommu/msi-iommu.c b/drivers/iommu/msi-iommu.c
>> index 203e86e..023ff17 100644
>> --- a/drivers/iommu/msi-iommu.c
>> +++ b/drivers/iommu/msi-iommu.c
>> @@ -243,3 +243,20 @@ unlock:
>>  	}
>>  }
>>  EXPORT_SYMBOL_GPL(iommu_msi_put_doorbell_iova);
>> +
>> +struct iommu_domain *iommu_msi_domain(struct device *dev)
>> +{
>> +	struct iommu_domain *d = iommu_get_domain_for_dev(dev);
>> +	struct iommu_domain_msi_geometry msi_geometry;
>> +
>> +	if (!d || (d->type == IOMMU_DOMAIN_DMA))
>> +		return NULL;
>> +
>> +	iommu_domain_get_attr(d, DOMAIN_ATTR_MSI_GEOMETRY, &msi_geometry);
>> +	if (!msi_geometry.programmable)
> 
> It feels like we're conflating ideas with using the "programmable" flag
> in this way.  AIUI the IOMMU API consumer is supposed to see the
> invalid MSI geometry with the programmable feature set and know to call
> iommu_msi_set_aperture().  Looking for the msi_cookie would tell us if
> that had been done, but that doesn't tell us if it should have been
> done.  iommu_msi_msg_pa_to_va() handles this later, if we return
> NULL here that function returns success otherwise it goes on to fail if
> the iova or msi cookie is not set.  So really what we're trying to flag
> is that the MSI geometry participates in the IOMMU-MSI API you've
> created and we should pick a feature name that says that rather than
> something as vague a "programmable".  Perhaps simply iommu_msi_api
> rather than programmable.
Yes I had the same questioning too when I wrote this code. So if my
understanding is correct we would have
- programmable: tells whether the MSI range is fixed or pogrammable and,
- mapping_required (new boolean field): indicating whether MSIs need to
be mapped in the IOMMU
> 
> BTW, I don't see that you ever set aperture_start/end once
> iommu_msi_set_aperture() has been called.  It seems like doing so would
> add some consistency to that MSI geometry attribute.
Indeed currently I mentionned:
/* In case the aperture is programmable, start/end are set to 0 */

If I set start/end in iommu_msi_set_aperture then I think I should also
return the actual values in iommu_domain_get_attr. I thought the extra
care to handle the possible race between the set_aperture (msi_iommu)
and the get_attr (iommu) was maybe not worth the benefits:
is_aperture_set is not visible to get_attr so I would be forced to
introduce a mutex at iommu_domain level or call an msi-iommu function
from iommu implementation. So I preferred to keep start/end as read-only
info initialized by the iommu driver.

> 
> Nice series overall.  Thanks,

Thanks

Eric
> 
> Alex
> 
>> +		return NULL;
>> +
>> +	return d;
>> +}
>> +EXPORT_SYMBOL_GPL(iommu_msi_domain);
>> +
>> diff --git a/include/linux/msi-iommu.h b/include/linux/msi-iommu.h
>> index 1cd115f..114bd69 100644
>> --- a/include/linux/msi-iommu.h
>> +++ b/include/linux/msi-iommu.h
>> @@ -81,6 +81,15 @@ int iommu_msi_get_doorbell_iova(struct iommu_domain *domain,
>>   */
>>  void iommu_msi_put_doorbell_iova(struct iommu_domain *domain, phys_addr_t addr);
>>  
>> +/**
>> + * iommu_msi_domain: in case the device is upstream to an IOMMU and this IOMMU
>> + * translates the MSI transaction, returns the iommu domain the MSI doorbell
>> + * address must be mapped in; else returns NULL.
>> + *
>> + * @dev: device handle
>> + */
>> +struct iommu_domain *iommu_msi_domain(struct device *dev);
>> +
>>  #else
>>  
>>  static inline int
>> @@ -100,5 +109,10 @@ static inline int iommu_msi_get_doorbell_iova(struct iommu_domain *domain,
>>  static inline void iommu_msi_put_doorbell_iova(struct iommu_domain *domain,
>>  					       phys_addr_t addr) {}
>>  
>> +static inline struct iommu_domain *iommu_msi_domain(struct device *dev)
>> +{
>> +	return NULL;
>> +}
>> +
>>  #endif	/* CONFIG_IOMMU_MSI */
>>  #endif	/* __MSI_IOMMU_H */
> 



From yamada.masahiro at socionext.com  Mon May  2 08:52:18 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 3 May 2016 00:52:18 +0900
Subject: [PATCH 3/7] reset: lpc18xx: use devm_reset_controller_register()
In-Reply-To: <1462177581.3933.7.camel@pengutronix.de>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
 <1462099023-11819-4-git-send-email-yamada.masahiro@socionext.com>
 <1462177581.3933.7.camel@pengutronix.de>
Message-ID: <CAK7LNAQ5LztGBbHCQxfLyWT7c_kWL=zpdKfkC9vsOKw95XL_Yw@mail.gmail.com>

2016-05-02 17:26 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> Am Sonntag, den 01.05.2016, 19:36 +0900 schrieb Masahiro Yamada:
>> Use devm_reset_controller_register() for the reset controller
>> registration and remove the unregister call from the .remove callback.
>>
>> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
>> ---
>>
>>  drivers/reset/reset-lpc18xx.c | 4 +---
>>  1 file changed, 1 insertion(+), 3 deletions(-)
>>
>> diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c
>> index 3b8a4f5..dd4f27e 100644
>> --- a/drivers/reset/reset-lpc18xx.c
>> +++ b/drivers/reset/reset-lpc18xx.c
>> @@ -199,7 +199,7 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
>>
>>       platform_set_drvdata(pdev, rc);
>>
>> -     ret = reset_controller_register(&rc->rcdev);
>> +     ret = devm_reset_controller_register(&pdev->dev, &rc->rcdev);
>>       if (ret) {
>>               dev_err(&pdev->dev, "unable to register device\n");
>>               goto dis_clks;
>> @@ -229,8 +229,6 @@ static int lpc18xx_rgu_remove(struct platform_device *pdev)
>>       if (ret)
>>               dev_warn(&pdev->dev, "failed to unregister restart handler\n");
>>
>> -     reset_controller_unregister(&rc->rcdev);
>> -
>>       clk_disable_unprepare(rc->clk_delay);
>>       clk_disable_unprepare(rc->clk_reg);
>>
>
> Hmm, would this patch theoretically allow a window between the calls to
> clk_disable_unprepare(clk_reg) and devm_reset_controller_release() where
> reset_control_get() + reset_control_(de)assert() would access unclocked
> registers?

This is not clear to me.

Why reset_control_get() + reset_control_(de)assert() would happen here?


devm_reset_controller_release() just calls reset_controller_unregister().

It is just a manipulation of a linked list.


void reset_controller_unregister(struct reset_controller_dev *rcdev)
{
      mutex_lock(&reset_controller_list_mutex);
      list_del(&rcdev->list);
      mutex_unlock(&reset_controller_list_mutex);
}




-- 
Best Regards
Masahiro Yamada


From yamada.masahiro at socionext.com  Mon May  2 08:56:31 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 3 May 2016 00:56:31 +0900
Subject: [PATCH v2,
 RESEND] clk: uniphier: add clock drivers for UniPhier SoCs
In-Reply-To: <20160104083629.15239.29413@quark.deferred.io>
References: <1451298058-28910-1-git-send-email-yamada.masahiro@socionext.com>
 <20151231013511.21505.59601@quark.deferred.io>
 <CAK7LNARHuogHfsSyXVkkoakOq61xfhYJOa08cC7tvvn1kdPRoQ@mail.gmail.com>
 <20160104083629.15239.29413@quark.deferred.io>
Message-ID: <CAK7LNASf918a3gp2oFc=Y-=TiOpgWrg0cQikdK7nn35DVZ=VSA@mail.gmail.com>

Hi Michael,

I am back after long pause.

2016-01-04 17:36 GMT+09:00 Michael Turquette <mturquette at baylibre.com>:
> Quoting Masahiro Yamada (2016-01-01 17:26:05)
>> Hi Michael,
>>
>>
>> 2015-12-31 10:35 GMT+09:00 Michael Turquette <mturquette at baylibre.com>:
>> > Hello Yamada-san,
>> >
>> > Quoting Masahiro Yamada (2015-12-28 02:20:58)
>> >> diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
>> >> new file mode 100644
>> >> index 0000000..7606f27
>> >> --- /dev/null
>> >> +++ b/drivers/clk/uniphier/Kconfig
>> >> @@ -0,0 +1,35 @@
>> >> +menuconfig CLK_UNIPHIER
>> >> +       bool "Clock drivers for UniPhier SoCs"
>> >> +       depends on ARCH_UNIPHIER
>> >
>> > Might want to make the above line:
>> >
>> >         depends on ARCH_UNIPHIER || COMPILE_TEST
>> >
>> >> +       depends on OF
>> >> +       default y
>> >> +       help
>> >> +         Supports clock drivers for UniPhier SoCs.
>> >
>> > Why menuconfig? Can we make this a non-visible config option selected by
>> > the UniPhier platform?
>>
>> Yes, I can do that if you like.
>
> Thanks, and the other questions I asked in my previous reply are
> relevant here: can you make these into platform_drivers and compile them
> as loadable modules? That would be ideal.


I noticed a conflict between two of your requests.

If I have CLK_UNIPHIER selected by ARCH_UNIPHIER,
it is impossible to add "depends on COMPILE_TEST".


I see some drivers that have "depends on ARCH_<SOC> || COMPILE_TEST"
as follows:


config COMMON_CLK_HI6220
        bool "Hi6220 Clock Driver"
        depends on ARCH_HISI || COMPILE_TEST

config COMMON_CLK_QCOM
        tristate "Support for Qualcomm's clock controllers"
        depends on OF
        depends on ARCH_QCOM || COMPILE_TEST


I think the style above works fine with COMPILE_TEST.


But, if we make it a non-visible config option selected by ARCH,
how can COMPILE_TEST select it?


config COMMON_CLK_HI6220
        bool
        prompt "Hi6220 Clock Driver" if COMPILE_TEST

should work, but looks a bit tricky.   Hmm...






>> >
>> > Where can I find the DT binding description and DTS for this clock
>> > controller?
>
> Any update on the above question? I wasn't able to find the DT binding
> description anywhere.


OK, will add a binding document in the next version.



>>
>> So, I implemented uniphier_clk_update_parent_name()
>> to convert the clock-names into the parent clock name.
>> In this case, this function takes "input" and converts it into "for-bar123".
>>
>>
>> Is there any good idea to solve this problem?
>
> Well, using the clock-output-names DT property in conjunction with
> of_clk_get_parent_name() solves this for you in a common way. However I
> would like to get rid of clock-output-names in the future. In general
> I'm working slowy to reduce the reliance on clock string names, but it
> is a long-term side project.


I do not intend to add clock-output-names in my device trees.

of_clk_get_parent_name() tries best to take the parent name via
of_clk_get_from_provider() if clock-output-names is missing.
I wanted to use this feature.



> How bad is it for you to hard-code the string names in your driver? Are
> the foo, bar and baz clock providers all on the same chip?

No problem, but not 100% happy.

If we allow to hardcode the parent name strings,
"clock-names" and "clocks" properties are useless in clock-cascading.

Like IRQ controllers can be cascaded by "interrupts" chain,
I want to describe the hierarchy of clock-providers
without hard-coding the detail of parent.



-- 
Best Regards
Masahiro Yamada


From yamada.masahiro at socionext.com  Mon May  2 08:59:19 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 3 May 2016 00:59:19 +0900
Subject: [PATCH v2] clk: uniphier: add clock drivers for UniPhier SoCs
In-Reply-To: <20160226000713.GO28849@codeaurora.org>
References: <1451298003-28841-1-git-send-email-yamada.masahiro@socionext.com>
 <20160226000713.GO28849@codeaurora.org>
Message-ID: <CAK7LNASQD4fpi=iDRbX96tSBvYjT_-N8EJnNk1VpuMxBTEnONg@mail.gmail.com>

Hi Stephen,

I am back after long silence.

2016-02-26 9:07 GMT+09:00 Stephen Boyd <sboyd at codeaurora.org>:
> On 12/28, Masahiro Yamada wrote:
>> This is the initial commit for the UniPhier clock drivers, including
>> support for PH1-sLD3, PH1-LD4, PH1-Pro4, PH1-sLD8, PH1-Pro5, and
>> ProXstream2/PH1-LD6b.
>>
>> To improve the code maintainability, the driver consists of common
>> functions (clk-uniphier-core.c) and clock data arrays needed to
>> support each SoC.
>>
>> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
>> ---
>
> Where's the DT binding? Also, can these clks be registered from a
> platform device driver instead of from
>>
>> diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
>> new file mode 100644
>> index 0000000..7606f27
>> --- /dev/null
>> +++ b/drivers/clk/uniphier/Kconfig
>> @@ -0,0 +1,35 @@
>> +menuconfig CLK_UNIPHIER
>> +     bool "Clock drivers for UniPhier SoCs"
>> +     depends on ARCH_UNIPHIER
>
> Can we have COMPILE_TEST here?

OK.
But if you recommend to drop "depends on ARCH_UNIPHIER",
COMPILE_TEST is not necessary.


>> +     depends on OF
>> +     default y
>
> And then default ARCH_UNIPHIER instead.



The problem is that CLK_UNIPHIER is not enabled along with
ARCH_UNIPHIER in "make menuconfig".

If we use "depends on ARCH_UNIPHIER"
and we enable ARCH_UNIPHIER from "make menuconfig",
CLK_UNIPHIER is automatically enabled as well.

Is the latter more like what we expect?




>> +endif
>> diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
>
> Maybe this patch can be split between core code and SoC specific
> data? That way we can focus on the core code without wading
> through all the random clk data arrays.

OK.  will do so.



>> +static void __init uniphier_clk_update_parent_name(struct device_node *np,
>> +                                                const char **parent_name)
>> +{
>> +     const char *new_name;
>> +     int index;
>> +
>> +     if (!parent_name || !*parent_name)
>> +             return;
>> +
>> +     if (strncmp(*parent_name, UNIPHIER_CLK_EXT, strlen(UNIPHIER_CLK_EXT)))
>> +             return;
>> +
>> +     index = of_property_match_string(np, "clock-names",
>> +                             *parent_name + strlen(UNIPHIER_CLK_EXT));
>
> If possible please don't use clock-names to set up clock
> hierarchy.

So, what shall I do instead?

I am not comfortable with hard-coding the parents' names
for clock-cascading.

Maybe, can we support clk registration
with clk_hw of parents, not names of parents?

For example, by adding  "struct clk_hw **parents"
to struct clk_init_data.



>> +int __init uniphier_clk_init(struct device_node *np,
>> +                          struct uniphier_clk_init_data *idata)
>> +{
>> +     struct clk_onecell_data *clk_data;
>> +     struct uniphier_clk_init_data *p;
>> +     void __iomem *regbase;
>> +     int max_index = 0;
>> +     int ret;
>> +
>> +     regbase = of_iomap(np, 0);
>
> If not a platform device, use of_io_request_and_map()?


I am planning to change all of them into platform drivers in the next version.



>> +#ifndef __CLK_UNIPHIER_H__
>> +#define __CLK_UNIPHIER_H__
>> +
>> +#include <linux/kernel.h>
>
> What's this include for?

Probably my mistake.  Will remove.


>> +
>> +#define UNIPHIER_CLK_EXT     "[EXT]"
>> +
>> +enum uniphier_clk_type {
>> +     UNIPHIER_CLK_TYPE_FIXED_FACTOR,
>> +     UNIPHIER_CLK_TYPE_FIXED_RATE,
>> +     UNIPHIER_CLK_TYPE_GATE,
>> +     UNIPHIER_CLK_TYPE_MUX,
>> +};
>> +
>> +struct uniphier_clk_fixed_factor_data {
>> +     const char *parent_name;
>> +     unsigned int mult;
>> +     unsigned int div;
>> +};
>> +
>> +struct uniphier_clk_fixed_rate_data {
>> +     unsigned long fixed_rate;
>> +};
>> +
>> +struct uniphier_clk_gate_data {
>> +     const char *parent_name;
>> +     unsigned int reg;
>> +     u8 bit_idx;
>> +};
>> +
>> +struct uniphier_clk_mux_data {
>> +     const char *parent_names[4];
>> +     u8 num_parents;
>> +     unsigned int reg;
>> +     u8 shift;
>> +};
>> +
>> +struct uniphier_clk_init_data {
>> +     const char *name;
>> +     enum uniphier_clk_type type;
>> +     int output_index;
>> +     union {
>> +             struct uniphier_clk_fixed_factor_data factor;
>> +             struct uniphier_clk_fixed_rate_data rate;
>> +             struct uniphier_clk_gate_data gate;
>> +             struct uniphier_clk_mux_data mux;
>> +     } data;
>> +     struct clk *clk;
>
> Probably need to forward declare this struct.


OK, thanks.

>> +};
>> +
>> +int uniphier_clk_init(struct device_node *np,
>
> Same for device_node.



-- 
Best Regards
Masahiro Yamada


From eric.auger at linaro.org  Mon May  2 09:13:26 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 2 May 2016 18:13:26 +0200
Subject: [PATCH v2 32/54] KVM: arm/arm64: vgic-new: Add GICv3 MMIO
 handling framework
In-Reply-To: <1461861973-26464-33-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-33-git-send-email-andre.przywara@arm.com>
Message-ID: <57277CA6.6060804@linaro.org>

Hi Andre,

Some minor comments below.
On 04/28/2016 06:45 PM, Andre Przywara wrote:
> Create a new file called vgic-mmio-v3.c and describe the GICv3
> distributor and redistributor registers there.
> This adds a special macro to deal with the split of SGI/PPI in the
> redistributor and SPIs in the distributor, which allows us to reuse
> the existing GICv2 handlers for those registers which are compatible.
> Also we provide a function to deal with the registration of the two
> separate redistributor frames per VCPU.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - adapt to new MMIO registration approach:
>   register one device for the distributor and two for each VCPU
> - implement special handling for private interrupts
> - remove empty stub functions
> - make IGROUPR return RAO
> 
> Changelog v1 .. v2:
> - adapt to new framework, introduce vgic-mmio-v3.c
> - remove userland register access functions (for now)
> - precompute .len when describing a VGIC register
> - add missed pointer incrementation on registering redist regions
> - replace _nyi stub functions with raz/wi versions
> 
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
>  virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
>  virt/kvm/arm/vgic/vgic.h         |   3 +
>  4 files changed, 201 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> new file mode 100644
> index 0000000..c6765d4
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -0,0 +1,191 @@
> +/*
> + * VGICv3 MMIO handling functions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/irqchip/arm-gic-v3.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/iodev.h>
> +#include <kvm/vgic/vgic.h>
> +
> +#include <asm/kvm_emulate.h>
> +
> +#include "vgic.h"
> +#include "vgic-mmio.h"
> +
> +/*
> + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
> + * redistributors, while SPIs are covered by registers in the distributor
> + * block. Trying to set private IRQs in this block gets ignored.
> + * We take some special care here to fix the calculation of the register
> + * offset.
> + */
> +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \
> +	{								\
> +		.reg_offset = off,					\
> +		.bits_per_irq = bpi,					\
> +		.len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8,		\
> +		.read = vgic_mmio_read_raz,				\
> +		.write = vgic_mmio_write_wi,				\
> +	}, {								\
> +		.reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8,	\
> +		.bits_per_irq = bpi,					\
> +		.len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
> +		.read = read_ops,					\
> +		.write = write_ops,					\
> +	}
> +
> +static const struct vgic_register_region vgic_v3_dist_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
> +		vgic_mmio_read_config, vgic_mmio_write_config, 2),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 64),
> +	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
> +};
> +
would add a comment to say this corresponds to RD_base frame, to use the
same terminology as the spec. IHI0069B.
> +static const struct vgic_register_region vgic_v3_redist_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
> +};
> +
same as above: SGI_base frame. Used terminology was a bit misleading for
me since this is also part of redist, 2d frame.
> +static const struct vgic_register_region vgic_v3_private_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 32),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
> +		vgic_mmio_read_config, vgic_mmio_write_config, 8),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +};
> +
> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
> +{
> +	dev->regions = vgic_v3_dist_registers;
> +	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
> +
> +	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
> +
> +	return SZ_64K;
> +}
> +
> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
> +{
> +	int nr_vcpus = atomic_read(&kvm->online_vcpus);
> +	struct kvm_vcpu *vcpu;
> +	struct vgic_io_device *devices, *device;
> +	int c, ret = 0;
> +
> +	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
> +			  GFP_KERNEL);
> +	if (!devices)
> +		return -ENOMEM;
> +
> +	device = devices;
> +	kvm_for_each_vcpu(c, vcpu, kvm) {
> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
> +		device->base_addr = redist_base_address;
> +		device->regions = vgic_v3_redist_registers;
> +		device->nr_regions = ARRAY_SIZE(vgic_v3_redist_registers);
> +		device->redist_vcpu = vcpu;
> +
> +		mutex_lock(&kvm->slots_lock);
> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
> +					      redist_base_address,
> +					      SZ_64K, &device->dev);
> +		mutex_unlock(&kvm->slots_lock);
> +
> +		if (ret)
> +			break;
> +
> +		device++;
> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
> +		device->base_addr = redist_base_address + SZ_64K;
> +		device->regions = vgic_v3_private_registers;
> +		device->nr_regions = ARRAY_SIZE(vgic_v3_private_registers);
> +		device->redist_vcpu = vcpu;
> +
> +		mutex_lock(&kvm->slots_lock);
> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
> +					      redist_base_address + SZ_64K,
> +					      SZ_64K, &device->dev);
> +		mutex_unlock(&kvm->slots_lock);
> +		if (ret) {
> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
> +						  &devices[c * 2].dev);
> +			break;
> +		}
> +		device++;
> +		redist_base_address += 2 * SZ_64K;
> +	}
> +
> +	if (ret) {
> +		for (c--; c >= 0; c--) {
> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
> +						  &devices[c * 2].dev);
> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
> +						  &devices[c * 2 + 1].dev);
> +		}
> +		kfree(devices);
> +	} else {
> +		kvm->arch.vgic.redist_iodevs = devices;
> +	}
> +
> +	return ret;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index bf4278c..80d977e 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -502,6 +502,11 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>  	case VGIC_V2:
>  		len = vgic_v2_init_dist_iodev(io_device);
>  		break;
> +#ifdef CONFIG_KVM_ARM_VGIC_V3
> +	case VGIC_V3:
> +		len = vgic_v3_init_dist_iodev(io_device);
> +		break;
> +#endif
>  	default:
>  		BUG_ON(1);
>  	}
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index 884eb71..3585ac6 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -123,4 +123,6 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
>  
>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>  
> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
> +
>  #endif
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 1ab7d97..6fe07df 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -61,6 +61,9 @@ static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
>  static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>  {
>  }
> +
>  #endif
>  
> +void kvm_register_vgic_device(unsigned long type);
I don't think this relates to this patch.

Besides Reviewed-by: Eric Auger <eric.auger at linaro.org>

Cheers

Eric
> +

>  #endif
> 



From festevam at gmail.com  Mon May  2 09:15:22 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 2 May 2016 13:15:22 -0300
Subject: [PATCH v2 2/2] nvmem: mxs-ocotp: remove nvmem regmap dependency
In-Reply-To: <1462202578-15433-3-git-send-email-srinivas.kandagatla@linaro.org>
References: <1462202578-15433-1-git-send-email-srinivas.kandagatla@linaro.org>
 <1462202578-15433-3-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <CAOMZO5DoqdOPM+i6D37PviCbiDSc3OV2rz8vGRi0mqV4uBvgaw@mail.gmail.com>

On Mon, May 2, 2016 at 12:22 PM, Srinivas Kandagatla
<srinivas.kandagatla at linaro.org> wrote:
> This patch moves to nvmem support in the driver to use callback
> instead of regmap.

It would be nice if you could explain the reason for doing this.


From kernel at martin.sperl.org  Mon May  2 09:16:08 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Mon, 2 May 2016 18:16:08 +0200
Subject: [PATCH V4 1/2] clk: bcm2835: mark enabled clocks with
 CLK_IS_CRITICAL
In-Reply-To: <87zis8h3pp.fsf@eliezer.anholt.net>
References: <1461951756-16804-1-git-send-email-kernel@martin.sperl.org>
 <1461951756-16804-2-git-send-email-kernel@martin.sperl.org>
 <87zis8h3pp.fsf@eliezer.anholt.net>
Message-ID: <5CC0D984-91E5-4401-8AB6-5827269C4395@martin.sperl.org>


> On 02.05.2016, at 17:36, Eric Anholt <eric at anholt.net> wrote:
> 
> kernel at martin.sperl.org writes:
> 
>> From: Martin Sperl <kernel at martin.sperl.org>
>> 
>> The bcm2835 firmware enables several clocks and plls before
>> booting the linux kernel.
>> 
>> These plls should never get disabled as it may result in a
>> stopped system clock and more.
>> 
>> So during probing we check if the clock is enabled
>> and if it is then mark that clock with CLK_IS_CRITICAL.
>> 
>> As a consequence this will also enable the corresponding
>> parent plls and pll-divs.
>> 
>> This is intended as a stop-gap until CLK_ENABLE_HAND_OFF
>> becomes available, at which point it should be used instead.
>> 
>> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
> 
> I still think that we don't want this patch.  We should be able to
> disable clocks that the firmware turned on, unless they really need to
> stay on.  If you have troubles on the upstream DT, let's talk about
> individual clocks.

May I ask you what is your main concern about using
CLK_IS_CRITICAL as a stop-gap/in general?

This is just a stop-gap until we get CLK_ENABLE_HAND_OFF merged
and I really want to use HAND_OFF as soon as possible, that is why
I have split it into 2 patches.

We essentially just replace the CLK_IS_CRITICAL with
CLK_ENABLE_HAND_OFF (plus comments and debug messages).

Any custom temporary code for specific clocks (which you propose)
is much more complicated than this simple patch and does not handle
things better in any way.

Also the current situation of the machine crashing when releasing the
PCM clock when the parent is PLLC or PLLD is worse than having some
clocks/pll running unnecessarily.

Also this is an incentive to merge HAND_OFF - there is now an
immediate user that would make immediate use of it.




From festevam at gmail.com  Mon May  2 09:17:18 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 2 May 2016 13:17:18 -0300
Subject: [PATCH v2 2/2] nvmem: mxs-ocotp: remove nvmem regmap dependency
In-Reply-To: <1462202578-15433-3-git-send-email-srinivas.kandagatla@linaro.org>
References: <1462202578-15433-1-git-send-email-srinivas.kandagatla@linaro.org>
 <1462202578-15433-3-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <CAOMZO5A5JbJV00AsxfqkAsPPR=gB81gobhU4t-+HSX07Q=bCZA@mail.gmail.com>

On Mon, May 2, 2016 at 12:22 PM, Srinivas Kandagatla
<srinivas.kandagatla at linaro.org> wrote:

>  static const struct of_device_id mxs_ocotp_match[] = {
> -       { .compatible = "fsl,imx23-ocotp", .data = &imx23_access },
> -       { .compatible = "fsl,imx28-ocotp", .data = &imx28_access },
> +       { .compatible = "fsl,imx23-ocotp", .data = &imx23_data },
> +       { .compatible = "fsl,imx28-ocotp", .data = &imx23_data },

This should &imx28_data.


From stefan.wahren at i2se.com  Mon May  2 09:26:48 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Mon, 2 May 2016 18:26:48 +0200 (CEST)
Subject: [PATCH v2 2/2] nvmem: mxs-ocotp: remove nvmem regmap dependency
In-Reply-To: <1462202578-15433-3-git-send-email-srinivas.kandagatla@linaro.org>
References: <1462202578-15433-1-git-send-email-srinivas.kandagatla@linaro.org>
 <1462202578-15433-3-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <1787061216.114034.428859d7-5360-40c1-b83f-7fe418a8fcaa.open-xchange@email.1und1.de>

Hi Srinivas,

unfortunately still some points from V1.

> Srinivas Kandagatla <srinivas.kandagatla at linaro.org> hat am 2. Mai 2016 um
> 17:22 geschrieben:
> 
> This patch moves to nvmem support in the driver to use callback
> instead of regmap.
> 
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
> ---
>  drivers/nvmem/mxs-ocotp.c | 81
> +++++++++++++----------------------------------
>  1 file changed, 22 insertions(+), 59 deletions(-)
> 
> diff --git a/drivers/nvmem/mxs-ocotp.c b/drivers/nvmem/mxs-ocotp.c
> index 2bb3c57..9bf59d6 100644
> --- a/drivers/nvmem/mxs-ocotp.c
> +++ b/drivers/nvmem/mxs-ocotp.c
> @@ -25,7 +25,6 @@
>  #include <linux/nvmem-provider.h>
>  #include <linux/of_device.h>
>  #include <linux/platform_device.h>
> -#include <linux/regmap.h>
>  #include <linux/slab.h>
>  #include <linux/stmp_device.h>
> 
> @@ -66,11 +65,10 @@ static int mxs_ocotp_wait(struct mxs_ocotp *otp)
>  return 0;
>  }
> 
> -static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
> - void *val, size_t val_size)
> +static int mxs_ocotp_read(void *context, unsigned int offset,
> + void *val, size_t bytes)
>  {
>  struct mxs_ocotp *otp = context;
> - unsigned int offset = *(u32 *)reg;
>  u32 *buf = val;
>  int ret;
> 
> @@ -94,17 +92,16 @@ static int mxs_ocotp_read(void *context, const void *reg,
> size_t reg_size,
>  if (ret)
>  goto close_banks;
> 
> - while (val_size >= reg_size) {
> + while (bytes) {
>  if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) {
>  /* fill up non-data register */
> - *buf = 0;
> + *buf++ = 0;
>  } else {
> - *buf = readl(otp->base + offset);
> + *buf++ = readl(otp->base + offset);
>  }
> 
> - buf++;
> - val_size -= reg_size;
> - offset += reg_size;
> + bytes -= 4;
> + offset += 4;
>  }
> 
>  close_banks:
> @@ -117,57 +114,29 @@ disable_clk:
>  return ret;
>  }
> 
> -static int mxs_ocotp_write(void *context, const void *data, size_t count)
> -{
> - /* We don't want to support writing */
> - return 0;
> -}
> -
> -static bool mxs_ocotp_writeable_reg(struct device *dev, unsigned int reg)
> -{
> - return false;
> -}
> -
>  static struct nvmem_config ocotp_config = {
>  .name = "mxs-ocotp",
> + .stride = 16,
> + .word_size = 4,
>  .owner = THIS_MODULE,
> + .reg_read = mxs_ocotp_read,
>  };
> 
> -static const struct regmap_range imx23_ranges[] = {
> - regmap_reg_range(OCOTP_DATA_OFFSET, 0x210),
> -};
> -
> -static const struct regmap_access_table imx23_access = {
> - .yes_ranges = imx23_ranges,
> - .n_yes_ranges = ARRAY_SIZE(imx23_ranges),
> -};
> -
> -static const struct regmap_range imx28_ranges[] = {
> - regmap_reg_range(OCOTP_DATA_OFFSET, 0x290),
> -};
> -
> -static const struct regmap_access_table imx28_access = {
> - .yes_ranges = imx28_ranges,
> - .n_yes_ranges = ARRAY_SIZE(imx28_ranges),
> +struct mxs_data {
> + int size;
>  };
> 
> -static struct regmap_bus mxs_ocotp_bus = {
> - .read = mxs_ocotp_read,
> - .write = mxs_ocotp_write, /* make regmap_init() happy */
> - .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
> - .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
> +static const struct mxs_data imx23_data = {
> + .size = 0x210,

0x220

because the regmap_reg_range defined the max register instead of size.

>  };
> 
> -static struct regmap_config mxs_ocotp_config = {
> - .reg_bits = 32,
> - .val_bits = 32,
> - .reg_stride = 16,
> - .writeable_reg = mxs_ocotp_writeable_reg,
> +static const struct mxs_data imx28_data = {
> + .size = 0x290,

0x2a0

ditto

>  };
> 
>  static const struct of_device_id mxs_ocotp_match[] = {
> - { .compatible = "fsl,imx23-ocotp", .data = &imx23_access },
> - { .compatible = "fsl,imx28-ocotp", .data = &imx28_access },
> + { .compatible = "fsl,imx23-ocotp", .data = &imx23_data },
> + { .compatible = "fsl,imx28-ocotp", .data = &imx23_data },

s/imx23_data/imx28_data/

>  { /* sentinel */},
>  };
>  MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
> @@ -175,6 +144,7 @@ MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
>  static int mxs_ocotp_probe(struct platform_device *pdev)
>  {
>  struct device *dev = &pdev->dev;
> + struct mxs_data *data;

I made this "const" in order to avoid a compiler warning below.

Stefan

>  struct mxs_ocotp *otp;
>  struct resource *res;
>  const struct of_device_id *match;
> @@ -205,17 +175,10 @@ static int mxs_ocotp_probe(struct platform_device *pdev)
>  return ret;
>  }
> 
> - access = match->data;
> - mxs_ocotp_config.rd_table = access;
> - mxs_ocotp_config.max_register = access->yes_ranges[0].range_max;
> -
> - regmap = devm_regmap_init(dev, &mxs_ocotp_bus, otp, &mxs_ocotp_config);
> - if (IS_ERR(regmap)) {
> - dev_err(dev, "regmap init failed\n");
> - ret = PTR_ERR(regmap);
> - goto err_clk;
> - }
> + data = match->data;
> 
> + ocotp_config.size = data->size;
> + ocotp_config.priv = otp;
>  ocotp_config.dev = dev;
>  otp->nvmem = nvmem_register(&ocotp_config);
>  if (IS_ERR(otp->nvmem)) {
> -- 
> 2.5.0


From kernel at martin.sperl.org  Mon May  2 09:36:24 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Mon, 2 May 2016 18:36:24 +0200
Subject: [PATCH 2/2] clk: bcm2835: Skip PLLC clocks when deciding on a new
 clock parent
In-Reply-To: <878tzsiilh.fsf@eliezer.anholt.net>
References: <1461699585-6649-1-git-send-email-eric@anholt.net>
 <1461699585-6649-2-git-send-email-eric@anholt.net>
 <C771F70C-2F88-49E1-A370-D76D13262C1E@martin.sperl.org>
 <878tzsiilh.fsf@eliezer.anholt.net>
Message-ID: <FB575328-E891-4ECC-B0D5-E7243CDEE44E@martin.sperl.org>


> On 02.05.2016, at 17:29, Eric Anholt <eric at anholt.net> wrote:
> 
> Martin Sperl <kernel at martin.sperl.org> writes:
> 
>>> On 26.04.2016, at 21:39, Eric Anholt <eric at anholt.net> wrote:
>>> 
>>> If the firmware had set up a clock to source from PLLC, go along with
>>> it.  But if we're looking for a new parent, we don't want to switch it
>>> to PLLC because the firmware will force PLLC (and thus the AXI bus
>>> clock) to different frequencies during over-temp/under-voltage,
>>> without notification to Linux.
>>> 
>>> On my system, this moves the Linux-enabled HDMI state machine and DSI1
>>> escape clock over to plld_per from pllc_per.  EMMC still ends up on
>>> pllc_per, because the firmware had set it up to use that.
>>> 
>>> Signed-off-by: Eric Anholt <eric at anholt.net>
>>> Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks")
>>> ?
>> 
>> I guess this patch looks to me as if it is a policy inside the kernel,
>> which is AFAIK frowned upon.
> 
> Can you come up with a use for putting peripherals on PLLC ever, such
> that we need choice?

For PLLC not right now, but with clk_notifier_register drivers could
work around those clock changes (assuming we get that information
from the firmware somehow - or if we could move this decision into the
kernel: even better).

But I can come up with a scenario that would make use of the pllh_aux
under some circumstances - e.g when requesting 290039Hz on clock gp0/1/2.

Similarly: if we ever enable the testdebugX clocks these become immediate
candidates for parent-clocks as well which can result in more headache.

Being able to define which clocks to use at least give the dts author
a means also to control clock selection if he wants to enable the
testdebug clocks.

Another similar situation can occur with plla_per - under some
circumstances it may get used unexpectedly.

Martin

From eric.auger at linaro.org  Mon May  2 09:44:18 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 2 May 2016 18:44:18 +0200
Subject: [PATCH v2 06/54] KVM: arm/arm64: arch_timer: Remove irq_phys_map
In-Reply-To: <1461861973-26464-7-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-7-git-send-email-andre.przywara@arm.com>
Message-ID: <572783E2.30204@linaro.org>

On 04/28/2016 06:45 PM, Andre Przywara wrote:
> Now that the interface between the arch timer and the VGIC does not
> require passing the irq_phys_map entry pointer anymore, let's remove
> it from the virtual arch timer and use the virtual IRQ number instead
> directly.
> The remaining pointer returned by kvm_vgic_map_phys_irq() will be
> removed in the following patch.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - remove extra virt_irq member from struct, instead use irq.irq directly
> 
>  include/kvm/arm_arch_timer.h |  3 ---
>  virt/kvm/arm/arch_timer.c    | 11 +++++------
>  2 files changed, 5 insertions(+), 9 deletions(-)
> 
> diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
> index b651aed..a47b7de 100644
> --- a/include/kvm/arm_arch_timer.h
> +++ b/include/kvm/arm_arch_timer.h
> @@ -53,9 +53,6 @@ struct arch_timer_cpu {
>  	/* Timer IRQ */
>  	struct kvm_irq_level		irq;
>  
> -	/* VGIC mapping */
> -	struct irq_phys_map		*map;
> -
>  	/* Active IRQ state caching */
>  	bool				active_cleared_last;
>  };
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index b470632..3a74b17 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -175,10 +175,10 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
>  
>  	timer->active_cleared_last = false;
>  	timer->irq.level = new_level;
> -	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
> +	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
>  				   timer->irq.level);
>  	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
> -					 timer->map->virt_irq,
> +					 timer->irq.irq,
>  					 timer->irq.level);
>  	WARN_ON(ret);
>  }
> @@ -276,7 +276,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
>  	* exit.
>  	*/
>  	phys_active = timer->irq.level ||
> -			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
> +			kvm_vgic_map_is_active(vcpu, timer->irq.irq);
>  
>  	/*
>  	 * We want to avoid hitting the (re)distributor as much as
> @@ -378,7 +378,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
>  	if (WARN_ON(IS_ERR(map)))
>  		return PTR_ERR(map);
>  
> -	timer->map = map;
>  	return 0;
>  }
>  
> @@ -521,8 +520,8 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
>  	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
>  
>  	timer_disarm(timer);
> -	if (timer->map)
> -		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
> +	if (timer->irq.irq)
> +		kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq);
thought you agreed to always unmap. Is it an oversight or did you change
your mind?

Besides Reviewed-by: Eric Auger <eric.auger at linaro.org>

Cheers

Eric
>  }
>  
>  void kvm_timer_enable(struct kvm *kvm)
> 



From Linux.HWI at garmin.com  Mon May  2 10:12:00 2016
From: Linux.HWI at garmin.com (J.D. Schroeder)
Date: Mon, 2 May 2016 12:12:00 -0500
Subject: [PATCH v2 0/3] AM57/DRA7 Clock Tree DTSI Fix-ups
In-Reply-To: <20160427171658.GA5995@atomide.com>
References: <20160427171658.GA5995@atomide.com>
Message-ID: <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>

This series of patches fixes several discrepancies between the
AM57/DRA7 clock tree description and the actual hardware behavior and
frequencies. With these changes a more complete picture of the clock
tree is represented for a few of the clocks and their resulting
frequencies.

v2 Changes:
* Rebased on linux-next as requested by Tony Lindgren
* Eliminated previous patch 2 as another change fixing the same thing
  was merged in eea08802f586acd6aef377d1b4a541821013cc0b
* Added to the commit message in patch 2 to clarify the source of the
  clock being internal to the processor
* Added a new patch 3 to fix a new warning introduced by
  eea08802f586acd6aef377d1b4a541821013cc0b



From Linux.HWI at garmin.com  Mon May  2 10:12:02 2016
From: Linux.HWI at garmin.com (J.D. Schroeder)
Date: Mon, 2 May 2016 12:12:02 -0500
Subject: [PATCH v2 2/3] ARM: DRA7x: dts: Update the OSC_32K_CLK frequency
In-Reply-To: <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
Message-ID: <1462209123-7332-3-git-send-email-Linux.HWI@garmin.com>

From: "J.D. Schroeder" <jay.schroeder at garmin.com>

This commit updates the OSC_32K_CLK (secure_32k_clk_src_ck) frequency
from the precise 32kHz frequency (i.e., 32.768 kHz) to a more
accurate frequency of ~34.6 kHz. Actual measured frequencies of the
clock vary from processor to processor anywhere from 34.4 kHz up to
34.8 kHz. Note that the ~34 kHz frequency clock is generated
internally by the processor, not an input to the processor. This
change makes it more clear that the consumer of the
secure_32k_clk_src_ck will not get a precise 32.768 kHz frequency
output.

Signed-off-by: J.D. Schroeder <jay.schroeder at garmin.com>
Reviewed-by: Trenton Andres <trenton.andres at garmin.com>
---
 arch/arm/boot/dts/dra7xx-clocks.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi
index 3f0c61d..f7ec976 100644
--- a/arch/arm/boot/dts/dra7xx-clocks.dtsi
+++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi
@@ -95,7 +95,7 @@
 	secure_32k_clk_src_ck: secure_32k_clk_src_ck {
 		#clock-cells = <0>;
 		compatible = "fixed-clock";
-		clock-frequency = <32768>;
+		clock-frequency = <34600>; /* approximate frequency */
 	};
 
 	sys_clk32_crystal_ck: sys_clk32_crystal_ck {
-- 
1.9.1



From Linux.HWI at garmin.com  Mon May  2 10:12:03 2016
From: Linux.HWI at garmin.com (J.D. Schroeder)
Date: Mon, 2 May 2016 12:12:03 -0500
Subject: [PATCH v2 3/3] ARM: dts: dra7: fix clock node definition to avoid
 build warning
In-Reply-To: <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
Message-ID: <1462209123-7332-4-git-send-email-Linux.HWI@garmin.com>

From: "J.D. Schroeder" <jay.schroeder at garmin.com>

This patch fixes the following warning for the DRA7 clock node:
Warning (unit_address_vs_reg): Node
/ocp/l4 at 4a000000/scm at 2000/scm_conf at 0/clocks/sys_32k_ck
has a reg or ranges property, but no unit name

Signed-off-by: J.D. Schroeder <jay.schroeder at garmin.com>
---
 arch/arm/boot/dts/dra7xx-clocks.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi
index f7ec976..34cda4b 100644
--- a/arch/arm/boot/dts/dra7xx-clocks.dtsi
+++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi
@@ -2186,7 +2186,7 @@
 		reg = <0x0558>;
 	};
 
-	sys_32k_ck: sys_32k_ck {
+	sys_32k_ck: sys_32k_ck at 6c4 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clk32_crystal_ck>, <&sys_clk32_pseudo_ck>, <&sys_clk32_pseudo_ck>, <&sys_clk32_pseudo_ck>;
-- 
1.9.1



From Linux.HWI at garmin.com  Mon May  2 10:12:01 2016
From: Linux.HWI at garmin.com (J.D. Schroeder)
Date: Mon, 2 May 2016 12:12:01 -0500
Subject: [PATCH v2 1/3] DRA7: Fix clock data for gmac_gmii_ref_clk_div
In-Reply-To: <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
Message-ID: <1462209123-7332-2-git-send-email-Linux.HWI@garmin.com>

From: "J.D. Schroeder" <jay.schroeder at garmin.com>

This commit fixes the clock data inside the DRA7xx clocks device tree
structure for the gmac_gmii_ref_clk_div clock. This clock is actually
the GMAC_MAIN_CLK and has nothing to do with the register at address
0x4a0093d0. If CLKSEL_REF bit 24 inside of CM_GMAC_GMAC_CLKCTRL, is
set to 1 in order to use the GMAC_RMII_CLK instead of the
GMAC_RMII_HS_CLK, the kernel generates a clock divider warning:
    WARNING: CPU: 0 PID: 0 at drivers/clk/clk-divider.c:129 clk_divider_recalc_rate+0xa8/0xe0()
    gmac_gmii_ref_clk_div: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set

By properly configuring the gmac_gmii_ref_clk_div (GMAC_MAIN_CLK) to
have the parent of dpll_gmac_m2_ck always divided by 2 the warning is
resolved and the clock tree is fixed up.

Additionally, a new clock called rmii_50mhz_clk_mux is defined that
does utilize CM_GMAC_GMAC_CLKCTRL[24] CLKSEL_REF to configure the
source clock for the RMII_50MHZ_CLK.

Signed-off-by: J.D. Schroeder <jay.schroeder at garmin.com>
Reviewed-by: Trenton Andres <trenton.andres at garmin.com>
---
 arch/arm/boot/dts/dra7xx-clocks.dtsi | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi
index 8378b44..3f0c61d 100644
--- a/arch/arm/boot/dts/dra7xx-clocks.dtsi
+++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi
@@ -1718,13 +1718,20 @@
 		reg = <0x0c00>;
 	};
 
-	gmac_gmii_ref_clk_div: gmac_gmii_ref_clk_div at 13d0 {
+	rmii_50mhz_clk_mux: rmii_50mhz_clk_mux at 13d0 {
 		#clock-cells = <0>;
-		compatible = "ti,divider-clock";
-		clocks = <&dpll_gmac_m2_ck>;
+		compatible = "ti,mux-clock";
+		clocks = <&dpll_gmac_h11x2_ck>, <&rmii_clk_ck>;
 		ti,bit-shift = <24>;
 		reg = <0x13d0>;
-		ti,dividers = <2>;
+	};
+
+	gmac_gmii_ref_clk_div: gmac_gmii_ref_clk_div {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&dpll_gmac_m2_ck>;
+		clock-mult = <1>;
+		clock-div = <2>;
 	};
 
 	gmac_rft_clk_mux: gmac_rft_clk_mux at 13d0 {
-- 
1.9.1



From javier at osg.samsung.com  Mon May  2 10:27:54 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon,  2 May 2016 13:27:54 -0400
Subject: [PATCH] s5p-mfc: Don't try to put pm->clock if lookup failed
Message-ID: <1462210075-5320-1-git-send-email-javier@osg.samsung.com>

Failing to get the struct s5p_mfc_pm .clock is a non-fatal error so the
clock field can have a errno pointer value. But s5p_mfc_final_pm() only
checks if .clock is not NULL before attempting to unprepare and put it.

This leads to the following warning in clk_put() due s5p_mfc_final_pm():

WARNING: CPU: 3 PID: 1023 at drivers/clk/clk.c:2814 s5p_mfc_final_pm+0x48/0x74 [s5p_mfc]
CPU: 3 PID: 1023 Comm: rmmod Tainted: G        W       4.6.0-rc6-next-20160502-00005-g5a15a49106bc #9
Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[<c010e1bc>] (unwind_backtrace) from [<c010af28>] (show_stack+0x10/0x14)
[<c010af28>] (show_stack) from [<c032485c>] (dump_stack+0x88/0x9c)
[<c032485c>] (dump_stack) from [<c011b8e8>] (__warn+0xe8/0x100)
[<c011b8e8>] (__warn) from [<c011b9b0>] (warn_slowpath_null+0x20/0x28)
[<c011b9b0>] (warn_slowpath_null) from [<bf16004c>] (s5p_mfc_final_pm+0x48/0x74 [s5p_mfc])
[<bf16004c>] (s5p_mfc_final_pm [s5p_mfc]) from [<bf157414>] (s5p_mfc_remove+0x8c/0x94 [s5p_mfc])
[<bf157414>] (s5p_mfc_remove [s5p_mfc]) from [<c03fe1f8>] (platform_drv_remove+0x24/0x3c)
[<c03fe1f8>] (platform_drv_remove) from [<c03fcc70>] (__device_release_driver+0x84/0x110)
[<c03fcc70>] (__device_release_driver) from [<c03fcdd8>] (driver_detach+0xac/0xb0)
[<c03fcdd8>] (driver_detach) from [<c03fbff8>] (bus_remove_driver+0x4c/0xa0)
[<c03fbff8>] (bus_remove_driver) from [<c01886a8>] (SyS_delete_module+0x174/0x1b8)
[<c01886a8>] (SyS_delete_module) from [<c01078c0>] (ret_fast_syscall+0x0/0x3c)

So check if the pointer is not an errno value before calling clk_put().

Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

 drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index 5f97a3398c11..d011f30be265 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -85,7 +85,7 @@ err_g_ip_clk:
 void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
 {
 	if (dev->variant->version != MFC_VERSION_V6 &&
-	    pm->clock) {
+	    !IS_ERR_OR_NULL(pm->clock)) {
 		clk_disable_unprepare(pm->clock);
 		clk_put(pm->clock);
 	}
-- 
2.5.5



From helgaas at kernel.org  Mon May  2 10:34:08 2016
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 2 May 2016 12:34:08 -0500
Subject: [PATCH] pci, pci-thunder-pem: Don't clobber read-only bits in
 bridge config registers.
In-Reply-To: <1460417372-13147-1-git-send-email-ddaney.cavm@gmail.com>
References: <1460417372-13147-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <20160502173408.GG24851@localhost>

On Mon, Apr 11, 2016 at 04:29:32PM -0700, David Daney wrote:
> From: David Daney <david.daney at cavium.com>
> 
> The 32-bit addressing modes in the I/O and Prefetchable Memory
> registers are required to be read-only.  Since the underlying access
> method allows them to be set, we must emulate their read-only nature
> and always set them.
> 
> Signed-off-by: David Daney <david.daney at cavium.com>

Applied to pci/host-thunder for v4.7, thanks, David!

> ---
>  drivers/pci/host/pci-thunder-pem.c | 42 ++++++++++++++++++++++++++++++--------
>  1 file changed, 34 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
> index cabb92a..196adf6 100644
> --- a/drivers/pci/host/pci-thunder-pem.c
> +++ b/drivers/pci/host/pci-thunder-pem.c
> @@ -153,11 +153,11 @@ static int thunder_pem_config_read(struct pci_bus *bus, unsigned int devfn,
>   * reserved bits, this makes the code simpler and is OK as the bits
>   * are not affected by writing zeros to them.
>   */
> -static u32 thunder_pem_bridge_w1c_bits(int where)
> +static u32 thunder_pem_bridge_w1c_bits(u64 where_aligned)
>  {
>  	u32 w1c_bits = 0;
>  
> -	switch (where & ~3) {
> +	switch (where_aligned) {
>  	case 0x04: /* Command/Status */
>  	case 0x1c: /* Base and I/O Limit/Secondary Status */
>  		w1c_bits = 0xff000000;
> @@ -184,12 +184,34 @@ static u32 thunder_pem_bridge_w1c_bits(int where)
>  	return w1c_bits;
>  }
>  
> +/* Some bits must be written to one so they appear to be read-only. */
> +static u32 thunder_pem_bridge_w1_bits(u64 where_aligned)
> +{
> +	u32 w1_bits;
> +
> +	switch (where_aligned) {
> +	case 0x1c: /* I/O Base / I/O Limit, Secondary Status*/
> +		/* Force 32-bit I/O addressing. */
> +		w1_bits = 0x0101;
> +		break;
> +	case 0x24: /* Prefetchable Memory Base / Prefetchable Memory Limit */
> +		/* Force 64-bit addressing */
> +		w1_bits = 0x00010001;
> +		break;
> +	default:
> +		w1_bits = 0;
> +		break;
> +	}
> +	return w1_bits;
> +}
> +
>  static int thunder_pem_bridge_write(struct pci_bus *bus, unsigned int devfn,
>  				    int where, int size, u32 val)
>  {
>  	struct gen_pci *pci = bus->sysdata;
>  	struct thunder_pem_pci *pem_pci;
>  	u64 write_val, read_val;
> +	u64 where_aligned = where & ~3ull;
>  	u32 mask = 0;
>  
>  	pem_pci = container_of(pci, struct thunder_pem_pci, gen_pci);
> @@ -205,8 +227,7 @@ static int thunder_pem_bridge_write(struct pci_bus *bus, unsigned int devfn,
>  	 */
>  	switch (size) {
>  	case 1:
> -		read_val = where & ~3ull;
> -		writeq(read_val, pem_pci->pem_reg_base + PEM_CFG_RD);
> +		writeq(where_aligned, pem_pci->pem_reg_base + PEM_CFG_RD);
>  		read_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
>  		read_val >>= 32;
>  		mask = ~(0xff << (8 * (where & 3)));
> @@ -215,8 +236,7 @@ static int thunder_pem_bridge_write(struct pci_bus *bus, unsigned int devfn,
>  		val |= (u32)read_val;
>  		break;
>  	case 2:
> -		read_val = where & ~3ull;
> -		writeq(read_val, pem_pci->pem_reg_base + PEM_CFG_RD);
> +		writeq(where_aligned, pem_pci->pem_reg_base + PEM_CFG_RD);
>  		read_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
>  		read_val >>= 32;
>  		mask = ~(0xffff << (8 * (where & 3)));
> @@ -244,11 +264,17 @@ static int thunder_pem_bridge_write(struct pci_bus *bus, unsigned int devfn,
>  	}
>  
>  	/*
> +	 * Some bits must be read-only with value of one.  Since the
> +	 * access method allows these to be cleared if a zero is
> +	 * written, force them to one before writing.
> +	 */
> +	val |= thunder_pem_bridge_w1_bits(where_aligned);
> +
> +	/*
>  	 * Low order bits are the config address, the high order 32
>  	 * bits are the data to be written.
>  	 */
> -	write_val = where & ~3ull;
> -	write_val |= (((u64)val) << 32);
> +	write_val = (((u64)val) << 32) | where_aligned;
>  	writeq(write_val, pem_pci->pem_reg_base + PEM_CFG_WR);
>  	return PCIBIOS_SUCCESSFUL;
>  }
> -- 
> 1.8.3.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From srinivas.kandagatla at linaro.org  Mon May  2 11:03:41 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon, 2 May 2016 19:03:41 +0100
Subject: [PATCH v2 2/2] nvmem: mxs-ocotp: remove nvmem regmap dependency
In-Reply-To: <CAOMZO5DoqdOPM+i6D37PviCbiDSc3OV2rz8vGRi0mqV4uBvgaw@mail.gmail.com>
References: <1462202578-15433-1-git-send-email-srinivas.kandagatla@linaro.org>
 <1462202578-15433-3-git-send-email-srinivas.kandagatla@linaro.org>
 <CAOMZO5DoqdOPM+i6D37PviCbiDSc3OV2rz8vGRi0mqV4uBvgaw@mail.gmail.com>
Message-ID: <5727967D.8030202@linaro.org>



On 02/05/16 17:15, Fabio Estevam wrote:
> On Mon, May 2, 2016 at 12:22 PM, Srinivas Kandagatla
> <srinivas.kandagatla at linaro.org> wrote:
>> This patch moves to nvmem support in the driver to use callback
>> instead of regmap.
>
> It would be nice if you could explain the reason for doing this.
>

Sure, Basically using regmap raw accessors in a generic way in nvmem 
core broken nvmem providers based on regmap mmio bus.

More details at 
https://groups.google.com/forum/#!topic/linux.kernel/LT3hM-GOf1k

thanks,
srini


From srinivas.kandagatla at linaro.org  Mon May  2 11:06:08 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon, 2 May 2016 19:06:08 +0100
Subject: [PATCH v2 2/2] nvmem: mxs-ocotp: remove nvmem regmap dependency
In-Reply-To: <1787061216.114034.428859d7-5360-40c1-b83f-7fe418a8fcaa.open-xchange@email.1und1.de>
References: <1462202578-15433-1-git-send-email-srinivas.kandagatla@linaro.org>
 <1462202578-15433-3-git-send-email-srinivas.kandagatla@linaro.org>
 <1787061216.114034.428859d7-5360-40c1-b83f-7fe418a8fcaa.open-xchange@email.1und1.de>
Message-ID: <57279710.3080005@linaro.org>



On 02/05/16 17:26, Stefan Wahren wrote:
> Hi Srinivas,
>
> unfortunately still some points from V1.
Thanks for reviewing.

Oops, Will take care of them in v3.

thanks,
srini
>
>> Srinivas Kandagatla <srinivas.kandagatla at linaro.org> hat am 2. Mai 2016 um
>> 17:22 geschrieben:
>>
>> This patch moves to nvmem support in the driver to use callback
>> instead of regmap.
>>
>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
>> ---
>>   drivers/nvmem/mxs-ocotp.c | 81
>> +++++++++++++----------------------------------
>>   1 file changed, 22 insertions(+), 59 deletions(-)
>>
>> diff --git a/drivers/nvmem/mxs-ocotp.c b/drivers/nvmem/mxs-ocotp.c
>> index 2bb3c57..9bf59d6 100644
>> --- a/drivers/nvmem/mxs-ocotp.c
>> +++ b/drivers/nvmem/mxs-ocotp.c
>> @@ -25,7 +25,6 @@
>>   #include <linux/nvmem-provider.h>
>>   #include <linux/of_device.h>
>>   #include <linux/platform_device.h>
>> -#include <linux/regmap.h>
>>   #include <linux/slab.h>
>>   #include <linux/stmp_device.h>
>>
>> @@ -66,11 +65,10 @@ static int mxs_ocotp_wait(struct mxs_ocotp *otp)
>>   return 0;
>>   }
>>
>> -static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
>> - void *val, size_t val_size)
>> +static int mxs_ocotp_read(void *context, unsigned int offset,
>> + void *val, size_t bytes)
>>   {
>>   struct mxs_ocotp *otp = context;
>> - unsigned int offset = *(u32 *)reg;
>>   u32 *buf = val;
>>   int ret;
>>
>> @@ -94,17 +92,16 @@ static int mxs_ocotp_read(void *context, const void *reg,
>> size_t reg_size,
>>   if (ret)
>>   goto close_banks;
>>
>> - while (val_size >= reg_size) {
>> + while (bytes) {
>>   if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) {
>>   /* fill up non-data register */
>> - *buf = 0;
>> + *buf++ = 0;
>>   } else {
>> - *buf = readl(otp->base + offset);
>> + *buf++ = readl(otp->base + offset);
>>   }
>>
>> - buf++;
>> - val_size -= reg_size;
>> - offset += reg_size;
>> + bytes -= 4;
>> + offset += 4;
>>   }
>>
>>   close_banks:
>> @@ -117,57 +114,29 @@ disable_clk:
>>   return ret;
>>   }
>>
>> -static int mxs_ocotp_write(void *context, const void *data, size_t count)
>> -{
>> - /* We don't want to support writing */
>> - return 0;
>> -}
>> -
>> -static bool mxs_ocotp_writeable_reg(struct device *dev, unsigned int reg)
>> -{
>> - return false;
>> -}
>> -
>>   static struct nvmem_config ocotp_config = {
>>   .name = "mxs-ocotp",
>> + .stride = 16,
>> + .word_size = 4,
>>   .owner = THIS_MODULE,
>> + .reg_read = mxs_ocotp_read,
>>   };
>>
>> -static const struct regmap_range imx23_ranges[] = {
>> - regmap_reg_range(OCOTP_DATA_OFFSET, 0x210),
>> -};
>> -
>> -static const struct regmap_access_table imx23_access = {
>> - .yes_ranges = imx23_ranges,
>> - .n_yes_ranges = ARRAY_SIZE(imx23_ranges),
>> -};
>> -
>> -static const struct regmap_range imx28_ranges[] = {
>> - regmap_reg_range(OCOTP_DATA_OFFSET, 0x290),
>> -};
>> -
>> -static const struct regmap_access_table imx28_access = {
>> - .yes_ranges = imx28_ranges,
>> - .n_yes_ranges = ARRAY_SIZE(imx28_ranges),
>> +struct mxs_data {
>> + int size;
>>   };
>>
>> -static struct regmap_bus mxs_ocotp_bus = {
>> - .read = mxs_ocotp_read,
>> - .write = mxs_ocotp_write, /* make regmap_init() happy */
>> - .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
>> - .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
>> +static const struct mxs_data imx23_data = {
>> + .size = 0x210,
>
> 0x220
>
> because the regmap_reg_range defined the max register instead of size.
>
>>   };
>>
>> -static struct regmap_config mxs_ocotp_config = {
>> - .reg_bits = 32,
>> - .val_bits = 32,
>> - .reg_stride = 16,
>> - .writeable_reg = mxs_ocotp_writeable_reg,
>> +static const struct mxs_data imx28_data = {
>> + .size = 0x290,
>
> 0x2a0
>
> ditto
>
>>   };
>>
>>   static const struct of_device_id mxs_ocotp_match[] = {
>> - { .compatible = "fsl,imx23-ocotp", .data = &imx23_access },
>> - { .compatible = "fsl,imx28-ocotp", .data = &imx28_access },
>> + { .compatible = "fsl,imx23-ocotp", .data = &imx23_data },
>> + { .compatible = "fsl,imx28-ocotp", .data = &imx23_data },
>
> s/imx23_data/imx28_data/
>
>>   { /* sentinel */},
>>   };
>>   MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
>> @@ -175,6 +144,7 @@ MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
>>   static int mxs_ocotp_probe(struct platform_device *pdev)
>>   {
>>   struct device *dev = &pdev->dev;
>> + struct mxs_data *data;
>
> I made this "const" in order to avoid a compiler warning below.
>
> Stefan
>
>>   struct mxs_ocotp *otp;
>>   struct resource *res;
>>   const struct of_device_id *match;
>> @@ -205,17 +175,10 @@ static int mxs_ocotp_probe(struct platform_device *pdev)
>>   return ret;
>>   }
>>
>> - access = match->data;
>> - mxs_ocotp_config.rd_table = access;
>> - mxs_ocotp_config.max_register = access->yes_ranges[0].range_max;
>> -
>> - regmap = devm_regmap_init(dev, &mxs_ocotp_bus, otp, &mxs_ocotp_config);
>> - if (IS_ERR(regmap)) {
>> - dev_err(dev, "regmap init failed\n");
>> - ret = PTR_ERR(regmap);
>> - goto err_clk;
>> - }
>> + data = match->data;
>>
>> + ocotp_config.size = data->size;
>> + ocotp_config.priv = otp;
>>   ocotp_config.dev = dev;
>>   otp->nvmem = nvmem_register(&ocotp_config);
>>   if (IS_ERR(otp->nvmem)) {
>> --
>> 2.5.0


From srinivas.kandagatla at linaro.org  Mon May  2 11:36:13 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon,  2 May 2016 19:36:13 +0100
Subject: [PATCH v3 1/2] nvmem: mtk-efuse: remove nvmem regmap dependency
In-Reply-To: <1462214174-469-1-git-send-email-srinivas.kandagatla@linaro.org>
References: <1462214174-469-1-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <1462214174-469-2-git-send-email-srinivas.kandagatla@linaro.org>

Regmap raw accessors are bus specific implementations, using regmap raw
apis in nvmem breaks nvmem providers based on regmap mmio.
This patch moves to nvmem support in the driver to use callback
instead of regmap, which is what the nvmem core supports now.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
---
 drivers/nvmem/Kconfig     |  1 -
 drivers/nvmem/mtk-efuse.c | 47 ++++++++++++++++++++++++++++++++---------------
 2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 3041d48..5ff2189 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -50,7 +50,6 @@ config MTK_EFUSE
 	tristate "Mediatek SoCs EFUSE support"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
 	depends on HAS_IOMEM
-	select REGMAP_MMIO
 	help
 	  This is a driver to access hardware related data like sensor
 	  calibration, HDMI impedance etc.
diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c
index 9c49369..32fd572 100644
--- a/drivers/nvmem/mtk-efuse.c
+++ b/drivers/nvmem/mtk-efuse.c
@@ -14,15 +14,35 @@
 
 #include <linux/device.h>
 #include <linux/module.h>
+#include <linux/io.h>
 #include <linux/nvmem-provider.h>
 #include <linux/platform_device.h>
-#include <linux/regmap.h>
 
-static struct regmap_config mtk_regmap_config = {
-	.reg_bits = 32,
-	.val_bits = 32,
-	.reg_stride = 4,
-};
+static int mtk_reg_read(void *context,
+			unsigned int reg, void *_val, size_t bytes)
+{
+	void __iomem *base = context;
+	u32 *val = _val;
+	int i = 0, words = bytes / 4;
+
+	while (words--)
+		*val++ = readl(base + reg + (i++ * 4));
+
+	return 0;
+}
+
+static int mtk_reg_write(void *context,
+			 unsigned int reg, void *_val, size_t bytes)
+{
+	void __iomem *base = context;
+	u32 *val = _val;
+	int i = 0, words = bytes / 4;
+
+	while (words--)
+		writel(*val++, base + reg + (i++ * 4));
+
+	return 0;
+}
 
 static int mtk_efuse_probe(struct platform_device *pdev)
 {
@@ -30,7 +50,6 @@ static int mtk_efuse_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct nvmem_device *nvmem;
 	struct nvmem_config *econfig;
-	struct regmap *regmap;
 	void __iomem *base;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -42,14 +61,12 @@ static int mtk_efuse_probe(struct platform_device *pdev)
 	if (!econfig)
 		return -ENOMEM;
 
-	mtk_regmap_config.max_register = resource_size(res) - 1;
-
-	regmap = devm_regmap_init_mmio(dev, base, &mtk_regmap_config);
-	if (IS_ERR(regmap)) {
-		dev_err(dev, "regmap init failed\n");
-		return PTR_ERR(regmap);
-	}
-
+	econfig->stride = 4;
+	econfig->word_size = 4;
+	econfig->reg_read = mtk_reg_read;
+	econfig->reg_write = mtk_reg_write;
+	econfig->size = resource_size(res);
+	econfig->priv = base;
 	econfig->dev = dev;
 	econfig->owner = THIS_MODULE;
 	nvmem = nvmem_register(econfig);
-- 
2.5.0



From srinivas.kandagatla at linaro.org  Mon May  2 11:36:12 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon,  2 May 2016 19:36:12 +0100
Subject: [PATCH v3 0/2] nvmem: remove regmap dependency
Message-ID: <1462214174-469-1-git-send-email-srinivas.kandagatla@linaro.org>

Hi Greg, 

This is v3 patchset for the leftover 2 patches for nvmem regmap
removal series [1]. These patches are based on char-misc tree.

nvmem uses regmap_raw_read/write apis to read/write data from providers,
With recent patch 922a9f936e40 ("regmap: mmio: Convert to regmap_bus
and fix accessor usage") nvmem providers based on regmap-mmio stopped
working, as nvmem core was using raw accessors.
This issue can be fixed temporarly by moving to other regmap apis,
but we might hit same issue in future, and regmap looks like an
overdo for nvmem. Moving to interfaces based on read/write callbacks
from providers would be more robust.

This patchset converts the nvmem core and nvmem provider drivers to
use the new callbacks. Tested this patchset on qfprom and at24 drivers.
Other driver are only compile tested, any testing on them would be great.

Most of the patches have been applied to char-misc tree, these are the
two patches which had some outstanding comments on mxs nvmemprovider,
which are now fixed.

Changes since v2:
 - Fixed the mxs size and dt data pointer spotted by Stefan and Fabio

Changes since v1:
 - rebased mtk-efuse on top of char-misc
 - addressed concerns raised by Stefan Wahren.

[1] https://www.mail-archive.com/linux-kernel at vger.kernel.org/msg1130026.html

Thanks,
srini

Srinivas Kandagatla (2):
  nvmem: mtk-efuse: remove nvmem regmap dependency
  nvmem: mxs-ocotp: remove nvmem regmap dependency

 drivers/nvmem/Kconfig     |  1 -
 drivers/nvmem/mtk-efuse.c | 47 ++++++++++++++++++---------
 drivers/nvmem/mxs-ocotp.c | 83 +++++++++++++----------------------------------
 3 files changed, 54 insertions(+), 77 deletions(-)

-- 
2.5.0



From srinivas.kandagatla at linaro.org  Mon May  2 11:36:14 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon,  2 May 2016 19:36:14 +0100
Subject: [PATCH v3 2/2] nvmem: mxs-ocotp: remove nvmem regmap dependency
In-Reply-To: <1462214174-469-1-git-send-email-srinivas.kandagatla@linaro.org>
References: <1462214174-469-1-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <1462214174-469-3-git-send-email-srinivas.kandagatla@linaro.org>

Regmap raw accessors are bus specific implementations, using regmap raw
apis in nvmem breaks nvmem providers based on regmap mmio.
This patch moves to nvmem support in the driver to use callback
instead of regmap, which is what the nvmem core supports now.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
---
 drivers/nvmem/mxs-ocotp.c | 83 +++++++++++++----------------------------------
 1 file changed, 22 insertions(+), 61 deletions(-)

diff --git a/drivers/nvmem/mxs-ocotp.c b/drivers/nvmem/mxs-ocotp.c
index 2bb3c57..d26dd03 100644
--- a/drivers/nvmem/mxs-ocotp.c
+++ b/drivers/nvmem/mxs-ocotp.c
@@ -25,7 +25,6 @@
 #include <linux/nvmem-provider.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
-#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/stmp_device.h>
 
@@ -66,11 +65,10 @@ static int mxs_ocotp_wait(struct mxs_ocotp *otp)
 	return 0;
 }
 
-static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
-			  void *val, size_t val_size)
+static int mxs_ocotp_read(void *context, unsigned int offset,
+			  void *val, size_t bytes)
 {
 	struct mxs_ocotp *otp = context;
-	unsigned int offset = *(u32 *)reg;
 	u32 *buf = val;
 	int ret;
 
@@ -94,17 +92,16 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
 	if (ret)
 		goto close_banks;
 
-	while (val_size >= reg_size) {
+	while (bytes) {
 		if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) {
 			/* fill up non-data register */
-			*buf = 0;
+			*buf++ = 0;
 		} else {
-			*buf = readl(otp->base + offset);
+			*buf++ = readl(otp->base + offset);
 		}
 
-		buf++;
-		val_size -= reg_size;
-		offset += reg_size;
+		bytes -= 4;
+		offset += 4;
 	}
 
 close_banks:
@@ -117,57 +114,29 @@ disable_clk:
 	return ret;
 }
 
-static int mxs_ocotp_write(void *context, const void *data, size_t count)
-{
-	/* We don't want to support writing */
-	return 0;
-}
-
-static bool mxs_ocotp_writeable_reg(struct device *dev, unsigned int reg)
-{
-	return false;
-}
-
 static struct nvmem_config ocotp_config = {
 	.name = "mxs-ocotp",
+	.stride = 16,
+	.word_size = 4,
 	.owner = THIS_MODULE,
+	.reg_read = mxs_ocotp_read,
 };
 
-static const struct regmap_range imx23_ranges[] = {
-	regmap_reg_range(OCOTP_DATA_OFFSET, 0x210),
-};
-
-static const struct regmap_access_table imx23_access = {
-	.yes_ranges = imx23_ranges,
-	.n_yes_ranges = ARRAY_SIZE(imx23_ranges),
-};
-
-static const struct regmap_range imx28_ranges[] = {
-	regmap_reg_range(OCOTP_DATA_OFFSET, 0x290),
-};
-
-static const struct regmap_access_table imx28_access = {
-	.yes_ranges = imx28_ranges,
-	.n_yes_ranges = ARRAY_SIZE(imx28_ranges),
+struct mxs_data {
+	int size;
 };
 
-static struct regmap_bus mxs_ocotp_bus = {
-	.read = mxs_ocotp_read,
-	.write = mxs_ocotp_write, /* make regmap_init() happy */
-	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
-	.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+static const struct mxs_data imx23_data = {
+	.size = 0x220,
 };
 
-static struct regmap_config mxs_ocotp_config = {
-	.reg_bits = 32,
-	.val_bits = 32,
-	.reg_stride = 16,
-	.writeable_reg = mxs_ocotp_writeable_reg,
+static const struct mxs_data imx28_data = {
+	.size = 0x2a0,
 };
 
 static const struct of_device_id mxs_ocotp_match[] = {
-	{ .compatible = "fsl,imx23-ocotp", .data = &imx23_access },
-	{ .compatible = "fsl,imx28-ocotp", .data = &imx28_access },
+	{ .compatible = "fsl,imx23-ocotp", .data = &imx23_data },
+	{ .compatible = "fsl,imx28-ocotp", .data = &imx28_data },
 	{ /* sentinel */},
 };
 MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
@@ -175,11 +144,10 @@ MODULE_DEVICE_TABLE(of, mxs_ocotp_match);
 static int mxs_ocotp_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	const struct mxs_data *data;
 	struct mxs_ocotp *otp;
 	struct resource *res;
 	const struct of_device_id *match;
-	struct regmap *regmap;
-	const struct regmap_access_table *access;
 	int ret;
 
 	match = of_match_device(dev->driver->of_match_table, dev);
@@ -205,17 +173,10 @@ static int mxs_ocotp_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	access = match->data;
-	mxs_ocotp_config.rd_table = access;
-	mxs_ocotp_config.max_register = access->yes_ranges[0].range_max;
-
-	regmap = devm_regmap_init(dev, &mxs_ocotp_bus, otp, &mxs_ocotp_config);
-	if (IS_ERR(regmap)) {
-		dev_err(dev, "regmap init failed\n");
-		ret = PTR_ERR(regmap);
-		goto err_clk;
-	}
+	data = match->data;
 
+	ocotp_config.size = data->size;
+	ocotp_config.priv = otp;
 	ocotp_config.dev = dev;
 	otp->nvmem = nvmem_register(&ocotp_config);
 	if (IS_ERR(otp->nvmem)) {
-- 
2.5.0



From arnd at arndb.de  Mon May  2 11:41:11 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 02 May 2016 20:41:11 +0200
Subject: [PATCH] s5p-mfc: Don't try to put pm->clock if lookup failed
In-Reply-To: <1462210075-5320-1-git-send-email-javier@osg.samsung.com>
References: <1462210075-5320-1-git-send-email-javier@osg.samsung.com>
Message-ID: <2610031.B6nN8fjXyO@wuerfel>

On Monday 02 May 2016 13:27:54 Javier Martinez Canillas wrote:
> Failing to get the struct s5p_mfc_pm .clock is a non-fatal error so the
> clock field can have a errno pointer value. But s5p_mfc_final_pm() only
> checks if .clock is not NULL before attempting to unprepare and put it.
> 
> This leads to the following warning in clk_put() due s5p_mfc_final_pm():
> 

Better assign the pointer to NULL in case of a non-fatal error
return code. That way, the reader doesn't have to wonder why you
have the IS_ERR_OR_NULL() check here.

	Arnd


From javier at osg.samsung.com  Mon May  2 12:12:48 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 2 May 2016 15:12:48 -0400
Subject: [PATCH] s5p-mfc: Don't try to put pm->clock if lookup failed
In-Reply-To: <2610031.B6nN8fjXyO@wuerfel>
References: <1462210075-5320-1-git-send-email-javier@osg.samsung.com>
 <2610031.B6nN8fjXyO@wuerfel>
Message-ID: <090a74db-f168-ed0a-f0f5-5ecd10ec80fc@osg.samsung.com>

Hello Arnd,

Thanks for your feedback.

On 05/02/2016 02:41 PM, Arnd Bergmann wrote:
> On Monday 02 May 2016 13:27:54 Javier Martinez Canillas wrote:
>> Failing to get the struct s5p_mfc_pm .clock is a non-fatal error so the
>> clock field can have a errno pointer value. But s5p_mfc_final_pm() only
>> checks if .clock is not NULL before attempting to unprepare and put it.
>>
>> This leads to the following warning in clk_put() due s5p_mfc_final_pm():
>>
> 
> Better assign the pointer to NULL in case of a non-fatal error
> return code. That way, the reader doesn't have to wonder why you
> have the IS_ERR_OR_NULL() check here.
>

Ok, I'll re-spin the patch doing that instead.
 
> 	Arnd
> 

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Mon May  2 12:14:22 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon,  2 May 2016 15:14:22 -0400
Subject: [PATCH v2] s5p-mfc: Don't try to put pm->clock if lookup failed
Message-ID: <1462216462-32665-1-git-send-email-javier@osg.samsung.com>

Failing to get the struct s5p_mfc_pm .clock is a non-fatal error so the
clock field can have a errno pointer value. But s5p_mfc_final_pm() only
checks if .clock is not NULL before attempting to unprepare and put it.

This leads to the following warning in clk_put() due s5p_mfc_final_pm():

WARNING: CPU: 3 PID: 1023 at drivers/clk/clk.c:2814 s5p_mfc_final_pm+0x48/0x74 [s5p_mfc]
CPU: 3 PID: 1023 Comm: rmmod Tainted: G        W       4.6.0-rc6-next-20160502-00005-g5a15a49106bc #9
Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[<c010e1bc>] (unwind_backtrace) from [<c010af28>] (show_stack+0x10/0x14)
[<c010af28>] (show_stack) from [<c032485c>] (dump_stack+0x88/0x9c)
[<c032485c>] (dump_stack) from [<c011b8e8>] (__warn+0xe8/0x100)
[<c011b8e8>] (__warn) from [<c011b9b0>] (warn_slowpath_null+0x20/0x28)
[<c011b9b0>] (warn_slowpath_null) from [<bf16004c>] (s5p_mfc_final_pm+0x48/0x74 [s5p_mfc])
[<bf16004c>] (s5p_mfc_final_pm [s5p_mfc]) from [<bf157414>] (s5p_mfc_remove+0x8c/0x94 [s5p_mfc])
[<bf157414>] (s5p_mfc_remove [s5p_mfc]) from [<c03fe1f8>] (platform_drv_remove+0x24/0x3c)
[<c03fe1f8>] (platform_drv_remove) from [<c03fcc70>] (__device_release_driver+0x84/0x110)
[<c03fcc70>] (__device_release_driver) from [<c03fcdd8>] (driver_detach+0xac/0xb0)
[<c03fcdd8>] (driver_detach) from [<c03fbff8>] (bus_remove_driver+0x4c/0xa0)
[<c03fbff8>] (bus_remove_driver) from [<c01886a8>] (SyS_delete_module+0x174/0x1b8)
[<c01886a8>] (SyS_delete_module) from [<c01078c0>] (ret_fast_syscall+0x0/0x3c)

Assign the pointer to NULL in case of a lookup failure to fix the issue.

Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

Changes in v2:
- Set the clock pointer to NULL instead of checking for !IS_ERR_OR_NULL().
  Suggested by Arnd Bergmann.

 drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index 5f97a3398c11..9f7522104333 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -54,6 +54,7 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
 		pm->clock = clk_get(&dev->plat_dev->dev, MFC_SCLK_NAME);
 		if (IS_ERR(pm->clock)) {
 			mfc_info("Failed to get MFC special clock control\n");
+			pm->clock = NULL;
 		} else {
 			clk_set_rate(pm->clock, MFC_SCLK_RATE);
 			ret = clk_prepare_enable(pm->clock);
-- 
2.5.5



From keescook at chromium.org  Mon May  2 12:34:05 2016
From: keescook at chromium.org (Kees Cook)
Date: Mon, 2 May 2016 12:34:05 -0700
Subject: [RFC PATCH] arm64: Make arch_randomize_brk avoid stack area
In-Reply-To: <1461853042.2848.24.camel@linaro.org>
References: <1461848638.2848.19.camel@linaro.org>
 <1461853042.2848.24.camel@linaro.org>
Message-ID: <CAGXu5jJKDE_pLCxy-FF7PN5+YC7wyvpQ_9DTDGqHuk+tb1mvJA@mail.gmail.com>

On Thu, Apr 28, 2016 at 7:17 AM, Jon Medhurst (Tixy) <tixy at linaro.org> wrote:
> Sorry, the code patch has errors (I forgot to commit fixes before
> running git format-patch), the correct code, which was in the kernel I
> built and tested, is at the end of this email.

Please resend this as a v2 (with a changelog, etc). Conceptually, it
looks fine to me: it will limit the entropy of the brk base address
when close to the stack on old kernels and should be effectively a
no-op on modern kernels. However, I have some notes inline below.

Also, for v2, can you validate the text vs brk offset entropy on a 4.6
kernel before/after this patch?

This (aslr.c) may be helpful in running a few thousand iterations:

http://bazaar.launchpad.net/~ubuntu-bugcontrol/qa-regression-testing/master/files/head:/scripts/kernel-security/aslr/

$ for i in $(seq 10000); do ./aslr --report brk ; done | ...

>
> On Thu, 2016-04-28 at 14:03 +0100, Jon Medhurst (Tixy) wrote:
> Some incorrect code...
>> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
>> index 8062482..7126a5a 100644
>> --- a/arch/arm64/kernel/process.c
>> +++ b/arch/arm64/kernel/process.c
>> @@ -382,13 +382,24 @@ unsigned long arch_align_stack(unsigned long sp)
>>       return sp & ~0xf;
>>  }
>>
>> -static unsigned long randomize_base(unsigned long base)
>> +unsigned long arch_randomize_brk(struct mm_struct *mm)
>>  {
>>       unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
>> -     return randomize_range(base, range_end, 0) ? : base;
>> -}
>> +     unsigned long max_stack, range_limit;
>>
>> -unsigned long arch_randomize_brk(struct mm_struct *mm)
>> -{
>> -     return randomize_base(mm->brk);
>> +     /*
>> +      * Determine how much room do we need to leave available for the stack.
>> +      * We limit this to a reasonable value, because extremely large or
>> +      * unlimited stacks are always going to bump up against brk at some
>> +      * point and we don't want to fail to randomise brk in those cases.
>> +      */
>> +     max_stack = rlimit(RLIMIT_STACK);
>> +     if (max_stack > SZ_128M)
>> +             max_stack = SZ_128M;
>> +
>> +     range_limit = mm->start_stack - max_stack - 1;
>> +     if (range_end > range_limit)
>> +             range_end > range_limit
>> +
>> +     return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
>>  }
>
> Corrected code...
>
>  arch/arm64/kernel/process.c | 24 ++++++++++++++++++------
>  1 file changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> index 07c4c53..7e0f404 100644
> --- a/arch/arm64/kernel/process.c
> +++ b/arch/arm64/kernel/process.c
> @@ -434,13 +434,25 @@ unsigned long arch_align_stack(unsigned long sp)
>         return sp & ~0xf;
>  }
>
> -static unsigned long randomize_base(unsigned long base)
> +unsigned long arch_randomize_brk(struct mm_struct *mm)
>  {
> +       unsigned long base = mm->brk;
>         unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;

This looks wrong. Shouldn't it be (STACK_RND_MASK + 1) << PAGE_SHIFT ?

STACK_RND_MASK is 0x7ff (32-bit) or 0x3ffff (64-bit):

#define STACK_RND_MASK                  (test_thread_flag(TIF_32BIT) ? \
                                                0x7ff >> (PAGE_SHIFT - 12) : \
                                                0x3ffff >> (PAGE_SHIFT - 12))

(4K paged PAGE_SHIFT is 12)

So the correct offset max would be 0x800000 (32-bit) and 0x40000000
(64-bit), instead of
0x7ff0001 and 0x3ffff0001.

Even with that correction, this looks wrong for 32-bit, which uses
0x2000000 natively:

unsigned long arch_randomize_brk(struct mm_struct *mm)
{
        unsigned long range_end = mm->brk + 0x02000000;
        return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
}

Seems like arm64 compat is using 4 times less entropy than native arm?
(Note that STACK_RND_MASK is correct for arm64 compat: this matches
the default in fs/binfmt_elf.c that arm uses. It just seems like the
brk randomization is accidentally too small on arm64 compat since arm
uses a fixed value unrelated to stack randomization.)

0x02000000 arm native
0x00800000 arm64 compat  <- bug?
0x40000000 arm64


> -       return randomize_range(base, range_end, 0) ? : base;
> -}
> +       unsigned long max_stack, range_limit;
>
> -unsigned long arch_randomize_brk(struct mm_struct *mm)
> -{
> -       return randomize_base(mm->brk);
> +       /*
> +        * Determine how much room do we need to leave available for the stack.
> +        * We limit this to a reasonable value, because extremely large or
> +        * unlimited stacks are always going to bump up against brk at some
> +        * point and we don't want to fail to randomise brk in those cases.
> +        */
> +       max_stack = rlimit(RLIMIT_STACK);
> +       if (max_stack > SZ_128M)
> +               max_stack = SZ_128M;
> +
> +       range_limit = mm->start_stack - max_stack - 1;
> +       if (range_end > range_limit)
> +               range_end = range_limit;
> +
> +       return randomize_range(base, range_end, 0) ? : base;
>  }
> --
> 2.1.4
>

-Kees

-- 
Kees Cook
Chrome OS & Brillo Security


From helgaas at kernel.org  Mon May  2 12:37:51 2016
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 2 May 2016 14:37:51 -0500
Subject: [PATCH v3 1/3] PCI: imx6: Use enum instead of bool for variant
 indicator
In-Reply-To: <1461167131-26025-1-git-send-email-andrew.smirnov@gmail.com>
References: <1461167131-26025-1-git-send-email-andrew.smirnov@gmail.com>
Message-ID: <20160502193751.GJ24851@localhost>

On Wed, Apr 20, 2016 at 08:45:29AM -0700, Andrey Smirnov wrote:
> Use enumerated type instead of a boolean flag to specify the variant of
> the PCIe IP block (6Q, 6SX, etc). This patch has zero functional impact,
> however it makes the code easier to extend for the case of more than 2
> possible variants of an IP block (of which there are).
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>

Applied with Fabio's Reviewed-by and Gary's Tested-by to pci/host-imx6
for v4.7, thanks, Andrey!  Also, thank you Fabio, Gary, and Lucas for
reviewing and testing.

> ---
> 
> Changes since v2:
> 	- Removed default clause in all introduced switch statements
> 	- Switched to using of_device_get_match_data instead of
>           explicit of_device_is_compatible checks
> 	- Added a mention of the new DT compatibility string in the documentation
> 
> Changes since v1:
> 
> 	- Patchset is rebased against
>           https://git.kernel.org/cgit/linux/kernel/git/helgaas/pci.git/log/?h=pci/host-imx6
> 
> 	- DTS files changes moved into a separate patch
> 
>  drivers/pci/host/pci-imx6.c | 124 ++++++++++++++++++++++++--------------------
>  1 file changed, 67 insertions(+), 57 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index 0f6d630..a77e7fd 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -19,6 +19,7 @@
>  #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
>  #include <linux/module.h>
>  #include <linux/of_gpio.h>
> +#include <linux/of_device.h>
>  #include <linux/pci.h>
>  #include <linux/platform_device.h>
>  #include <linux/regmap.h>
> @@ -31,6 +32,11 @@
>  
>  #define to_imx6_pcie(x)	container_of(x, struct imx6_pcie, pp)
>  
> +enum imx6_pcie_variants {
> +	IMX6Q,
> +	IMX6SX
> +};
> +
>  struct imx6_pcie {
>  	struct gpio_desc	*reset_gpio;
>  	struct clk		*pcie_bus;
> @@ -39,7 +45,7 @@ struct imx6_pcie {
>  	struct clk		*pcie;
>  	struct pcie_port	pp;
>  	struct regmap		*iomuxc_gpr;
> -	bool			is_imx6sx;
> +	enum imx6_pcie_variants variant;
>  	void __iomem		*mem_base;
>  	u32			tx_deemph_gen1;
>  	u32			tx_deemph_gen2_3p5db;
> @@ -238,7 +244,8 @@ static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
>  	struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
>  	u32 val, gpr1, gpr12;
>  
> -	if (imx6_pcie->is_imx6sx) {
> +	switch (imx6_pcie->variant) {
> +	case IMX6SX:
>  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
>  				   IMX6SX_GPR12_PCIE_TEST_POWERDOWN,
>  				   IMX6SX_GPR12_PCIE_TEST_POWERDOWN);
> @@ -246,72 +253,76 @@ static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
>  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
>  				   IMX6SX_GPR5_PCIE_BTNRST_RESET,
>  				   IMX6SX_GPR5_PCIE_BTNRST_RESET);
> -		return 0;
> -	}
> -
> -	/*
> -	 * If the bootloader already enabled the link we need some special
> -	 * handling to get the core back into a state where it is safe to
> -	 * touch it for configuration.  As there is no dedicated reset signal
> -	 * wired up for MX6QDL, we need to manually force LTSSM into "detect"
> -	 * state before completely disabling LTSSM, which is a prerequisite
> -	 * for core configuration.
> -	 *
> -	 * If both LTSSM_ENABLE and REF_SSP_ENABLE are active we have a strong
> -	 * indication that the bootloader activated the link.
> -	 */
> -	regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, &gpr1);
> -	regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, &gpr12);
> -
> -	if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) &&
> -	    (gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) {
> -		val = readl(pp->dbi_base + PCIE_PL_PFLR);
> -		val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
> -		val |= PCIE_PL_PFLR_FORCE_LINK;
> -		writel(val, pp->dbi_base + PCIE_PL_PFLR);
> +		break;
> +	case IMX6Q:
> +		/*
> +		 * If the bootloader already enabled the link we need some special
> +		 * handling to get the core back into a state where it is safe to
> +		 * touch it for configuration.  As there is no dedicated reset signal
> +		 * wired up for MX6QDL, we need to manually force LTSSM into "detect"
> +		 * state before completely disabling LTSSM, which is a prerequisite
> +		 * for core configuration.
> +		 *
> +		 * If both LTSSM_ENABLE and REF_SSP_ENABLE are active we have a strong
> +		 * indication that the bootloader activated the link.
> +		 */
> +		regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, &gpr1);
> +		regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, &gpr12);
> +
> +		if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) &&
> +		    (gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) {
> +			val = readl(pp->dbi_base + PCIE_PL_PFLR);
> +			val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
> +			val |= PCIE_PL_PFLR_FORCE_LINK;
> +			writel(val, pp->dbi_base + PCIE_PL_PFLR);
> +
> +			regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
> +					   IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
> +		}
>  
> -		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
> -				IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
> +		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
> +				   IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
> +		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
> +				   IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
> +		break;
>  	}
>  
> -	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
> -			IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
> -	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
> -			IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
> -
>  	return 0;
>  }
>  
>  static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
>  {
>  	struct pcie_port *pp = &imx6_pcie->pp;
> -	int ret;
> +	int ret = 0;
>  
> -	if (imx6_pcie->is_imx6sx) {
> +	switch (imx6_pcie->variant) {
> +	case IMX6SX:
>  		ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi);
>  		if (ret) {
>  			dev_err(pp->dev, "unable to enable pcie_axi clock\n");
> -			return ret;
> +			break;
>  		}
>  
>  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
>  				   IMX6SX_GPR12_PCIE_TEST_POWERDOWN, 0);
> -		return ret;
> +		break;
> +	case IMX6Q:
> +		/* power up core phy and enable ref clock */
> +		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
> +				   IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
> +		/*
> +		 * the async reset input need ref clock to sync internally,
> +		 * when the ref clock comes after reset, internal synced
> +		 * reset time is too short, cannot meet the requirement.
> +		 * add one ~10us delay here.
> +		 */
> +		udelay(10);
> +		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
> +				   IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
> +		break;
>  	}
>  
> -	/* power up core phy and enable ref clock */
> -	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
> -			IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
> -	/*
> -	 * the async reset input need ref clock to sync internally,
> -	 * when the ref clock comes after reset, internal synced
> -	 * reset time is too short, cannot meet the requirement.
> -	 * add one ~10us delay here.
> -	 */
> -	udelay(10);
> -	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
> -			IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
> -	return 0;
> +	return ret;
>  }
>  
>  static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
> @@ -353,7 +364,7 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
>  		gpiod_set_value_cansleep(imx6_pcie->reset_gpio, 1);
>  	}
>  
> -	if (imx6_pcie->is_imx6sx)
> +	if (imx6_pcie->variant == IMX6SX)
>  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
>  				   IMX6SX_GPR5_PCIE_BTNRST_RESET, 0);
>  
> @@ -374,11 +385,10 @@ static void imx6_pcie_init_phy(struct pcie_port *pp)
>  {
>  	struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
>  
> -	if (imx6_pcie->is_imx6sx) {
> +	if (imx6_pcie->variant == IMX6SX)
>  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
>  				   IMX6SX_GPR12_PCIE_RX_EQ_MASK,
>  				   IMX6SX_GPR12_PCIE_RX_EQ_2);
> -	}
>  
>  	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
>  			IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
> @@ -585,8 +595,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
>  	pp = &imx6_pcie->pp;
>  	pp->dev = &pdev->dev;
>  
> -	imx6_pcie->is_imx6sx = of_device_is_compatible(pp->dev->of_node,
> -						       "fsl,imx6sx-pcie");
> +	imx6_pcie->variant =
> +		(enum imx6_pcie_variants)of_device_get_match_data(&pdev->dev);
>  
>  	/* Added for PCI abort handling */
>  	hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
> @@ -623,7 +633,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
>  		return PTR_ERR(imx6_pcie->pcie);
>  	}
>  
> -	if (imx6_pcie->is_imx6sx) {
> +	if (imx6_pcie->variant == IMX6SX) {
>  		imx6_pcie->pcie_inbound_axi = devm_clk_get(&pdev->dev,
>  							   "pcie_inbound_axi");
>  		if (IS_ERR(imx6_pcie->pcie_inbound_axi)) {
> @@ -679,8 +689,8 @@ static void imx6_pcie_shutdown(struct platform_device *pdev)
>  }
>  
>  static const struct of_device_id imx6_pcie_of_match[] = {
> -	{ .compatible = "fsl,imx6q-pcie", },
> -	{ .compatible = "fsl,imx6sx-pcie", },
> +	{ .compatible = "fsl,imx6q-pcie",  .data = (void *)IMX6Q,  },
> +	{ .compatible = "fsl,imx6sx-pcie", .data = (void *)IMX6SX, },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, imx6_pcie_of_match);
> -- 
> 2.5.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From sre at kernel.org  Mon May  2 13:12:17 2016
From: sre at kernel.org (Sebastian Reichel)
Date: Mon, 2 May 2016 22:12:17 +0200
Subject: Nokia N900 retention mode in v4.6, camera buttons fun
In-Reply-To: <20160501154855.GA24970@earth>
References: <20160411094130.GA5753@amd> <20160411211026.GH5995@atomide.com>
 <20160412121658.GA32486@amd> <20160412123013.GA12296@amd>
 <20160412163055.GP5995@atomide.com> <20160417175539.GA502@amd>
 <20160421130450.GQ29406@pali> <20160429200559.GA16598@earth>
 <20160501085236.GA14243@amd> <20160501154855.GA24970@earth>
Message-ID: <20160502201216.GA19211@earth>

Hi Pavel,

On Sun, May 01, 2016 at 05:48:56PM +0200, Sebastian Reichel wrote:
> > I see latest series, and it also talks about frequency scaling.
> > But I guess it is not going to fix this issue?
> 
> No, this is independent of the runtime PM problems. I also worked
> on runtime PM/idling yesterday and pm_runtime_irq_safe is the main
> culprit for breaking it (not the only one, though). It's not yet
> finished though

I will be on vacation for a week starting tomorrow. If you want to
play around with my intermediate SSI PM status, you can try this branch:

https://git.kernel.org/cgit/linux/kernel/git/sre/linux-hsi.git/log/?h=runtime-pm-fixes

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/70e10112/attachment.sig>

From ahs3 at redhat.com  Mon May  2 13:19:32 2016
From: ahs3 at redhat.com (Al Stone)
Date: Mon, 2 May 2016 14:19:32 -0600
Subject: [PATCH v5 0/1] ARM64: ACPI: Update documentation for latest
 specification version
In-Reply-To: <1461619287-27211-1-git-send-email-al.stone@linaro.org>
References: <1461619287-27211-1-git-send-email-al.stone@linaro.org>
Message-ID: <3b6d5be3-40ab-94dc-2590-8b2638cbdc15@redhat.com>

On 04/25/2016 03:21 PM, Al Stone wrote:
> The ACPI 6.1 specification was recently released at the end of January
> 2016, but the arm64 kernel documentation for the use of ACPI was written
> for the 5.1 version of the spec.  There were significant additions to the
> spec that had not yet been mentioned -- for example, the 6.0 mechanisms
> added to make it easier to define processors and low power idle states,
> as well as the 6.1 addition allowing regular interrupts (not just from
> GPIO) be used to signal ACPI general purpose events.
> 
> This patch reflects going back through and examining the specs in detail
> and updating content appropriately.  Whilst there, a few odds and ends of
> typos were caught as well.  This brings the documentation up to date with
> ACPI 6.1 for arm64.
> 
> Changes for v5:
>    -- Miscellaneous typos and corrections (Lorenzo Pieralisi)
>    -- Add linux-acpi@ ML to the distribution list (Alexey Klimov)
>    -- Corrections to CPPC information (Alexey Klimov)
>    -- ACK from Lorenzo Pieralisi
>    -- Updated bibliographic info (Al Stone)
> 
> Changes for v4:
>    -- Clarify that IORT can sometimes be optional (Jon Masters).
>    -- Remove "Use as needed" descriptions of ACPI objects; they provide
>       no substantive information and doing so simplifies maintenance of
>       this document over time.  These have been replaced with a simpler
>       notice that states that unless otherwise noted, do what the ACPI
>       specification says is needed.
>    -- Corrected the _OSI object usage recommendation; it described kernel
>       behavior that does not exist (Al Stone).
> 
> Changes for v3:
>    -- Clarify use of _LPI/_RDI (Vikas Sajjan)
>    -- Whitespace cleanup as pointed out by checkpatch
> 
> Changes for v2:
>    -- Clean up white space (Harb Abdulhahmid)
>    -- Clarification on _CCA usage (Harb Abdulhamid)
>    -- IORT moved to required from recommended (Hanjun Guo)
>    -- Clarify IORT description (Hanjun Guo)
> 
> 
> Al Stone (1):
>   ARM64: ACPI: Update documentation for latest specification version
> 
>  Documentation/arm64/acpi_object_usage.txt | 343 ++++++++++++++++--------------
>  Documentation/arm64/arm-acpi.txt          |  40 ++--
>  2 files changed, 213 insertions(+), 170 deletions(-)
> 

Ping?  If there are no further comments, can this be pulled in through
either the documentation or arm64 tree?

Thanks.

-- 
ciao,
al
-----------------------------------
Al Stone
Software Engineer
Red Hat, Inc.
ahs3 at redhat.com
-----------------------------------


From alex.williamson at redhat.com  Mon May  2 13:23:28 2016
From: alex.williamson at redhat.com (Alex Williamson)
Date: Mon, 2 May 2016 14:23:28 -0600
Subject: [PATCH v8 6/8] iommu/msi-iommu: iommu_msi_domain
In-Reply-To: <572776BD.2080503@linaro.org>
References: <1461831323-5480-1-git-send-email-eric.auger@linaro.org>
 <1461831323-5480-7-git-send-email-eric.auger@linaro.org>
 <20160428162740.28db4b8d@t450s.home> <572776BD.2080503@linaro.org>
Message-ID: <20160502142328.2d97f7a4@t450s.home>

Hi Eric,

On Mon, 2 May 2016 17:48:13 +0200
Eric Auger <eric.auger at linaro.org> wrote:

> Hi Alex,
> On 04/29/2016 12:27 AM, Alex Williamson wrote:
> > On Thu, 28 Apr 2016 08:15:21 +0000
> > Eric Auger <eric.auger at linaro.org> wrote:
> >   
> >> This function checks whether
> >> - the device belongs to a non default iommu domain
> >> - this iommu domain requires the MSI address to be mapped.
> >>
> >> If those conditions are met, the function returns the iommu domain
> >> to be used for mapping the MSI doorbell; else it returns NULL.
> >>
> >> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> >>
> >> ---
> >>
> >> v7 -> v8:
> >> - renamed  iommu_msi_mapping_desc_to_domain to iommu_msi_domain
> >> - the function now takes a struct device *
> >> - use DOMAIN_ATTR_MSI_GEOMETRY attribute
> >> ---
> >>  drivers/iommu/msi-iommu.c | 17 +++++++++++++++++
> >>  include/linux/msi-iommu.h | 14 ++++++++++++++
> >>  2 files changed, 31 insertions(+)
> >>
> >> diff --git a/drivers/iommu/msi-iommu.c b/drivers/iommu/msi-iommu.c
> >> index 203e86e..023ff17 100644
> >> --- a/drivers/iommu/msi-iommu.c
> >> +++ b/drivers/iommu/msi-iommu.c
> >> @@ -243,3 +243,20 @@ unlock:
> >>  	}
> >>  }
> >>  EXPORT_SYMBOL_GPL(iommu_msi_put_doorbell_iova);
> >> +
> >> +struct iommu_domain *iommu_msi_domain(struct device *dev)
> >> +{
> >> +	struct iommu_domain *d = iommu_get_domain_for_dev(dev);
> >> +	struct iommu_domain_msi_geometry msi_geometry;
> >> +
> >> +	if (!d || (d->type == IOMMU_DOMAIN_DMA))
> >> +		return NULL;
> >> +
> >> +	iommu_domain_get_attr(d, DOMAIN_ATTR_MSI_GEOMETRY, &msi_geometry);
> >> +	if (!msi_geometry.programmable)  
> > 
> > It feels like we're conflating ideas with using the "programmable" flag
> > in this way.  AIUI the IOMMU API consumer is supposed to see the
> > invalid MSI geometry with the programmable feature set and know to call
> > iommu_msi_set_aperture().  Looking for the msi_cookie would tell us if
> > that had been done, but that doesn't tell us if it should have been
> > done.  iommu_msi_msg_pa_to_va() handles this later, if we return
> > NULL here that function returns success otherwise it goes on to fail if
> > the iova or msi cookie is not set.  So really what we're trying to flag
> > is that the MSI geometry participates in the IOMMU-MSI API you've
> > created and we should pick a feature name that says that rather than
> > something as vague a "programmable".  Perhaps simply iommu_msi_api
> > rather than programmable.  
> Yes I had the same questioning too when I wrote this code. So if my
> understanding is correct we would have
> - programmable: tells whether the MSI range is fixed or pogrammable and,
> - mapping_required (new boolean field): indicating whether MSIs need to
> be mapped in the IOMMU

Let's say we had a flag "iommu_msi_supported", doesn't that already
tell us whether the MSI range is programmable and the API to use to do
it?  Can't we figure out if mapping is required based on whether
iommu_msi_supported is set and aperture_start and aperture_end indicate
a valid range?  It seems like what we want on this code path is to
simply know whether the IOMMU domain is relevant to the IOMMU MSI API,
which would be abundantly clear with such a flag.

> > 
> > BTW, I don't see that you ever set aperture_start/end once
> > iommu_msi_set_aperture() has been called.  It seems like doing so would
> > add some consistency to that MSI geometry attribute.  
> Indeed currently I mentionned:
> /* In case the aperture is programmable, start/end are set to 0 */

Which is confusing, if a user sets an aperture, I would think they'd
like to see the MSI geometry updated to reflect that.

> If I set start/end in iommu_msi_set_aperture then I think I should also
> return the actual values in iommu_domain_get_attr. I thought the extra
> care to handle the possible race between the set_aperture (msi_iommu)
> and the get_attr (iommu) was maybe not worth the benefits:
> is_aperture_set is not visible to get_attr so I would be forced to
> introduce a mutex at iommu_domain level or call an msi-iommu function
> from iommu implementation. So I preferred to keep start/end as read-only
> info initialized by the iommu driver.

Seems like a race between iommu_msi_set_aperture() and
iommu_domain_get_attr() is the caller's problem.  We can always define
that start >= end is invalid and set them in the right order that
iommu_domain_get_attr() may get different versions of invalid, but it
will always be invalid or valid.  A helper function could tell us if we
have a valid range rather than using is_aperture_set.  Thanks,

Alex


From davem at davemloft.net  Mon May  2 13:48:18 2016
From: davem at davemloft.net (David Miller)
Date: Mon, 02 May 2016 16:48:18 -0400 (EDT)
Subject: [PATCH v2 0/3] drivers: net: xgene: fix: Get channel number
 from device binding
In-Reply-To: <1461953415-9741-1-git-send-email-isubramanian@apm.com>
References: <1461953415-9741-1-git-send-email-isubramanian@apm.com>
Message-ID: <20160502.164818.1876590443775185144.davem@davemloft.net>

From: Iyappan Subramanian <isubramanian at apm.com>
Date: Fri, 29 Apr 2016 11:10:12 -0700

> This patch set adds 'channel' property to get ethernet to CPU channel number,
> thus decoupling the Linux driver from static resource selection.
> 
> v2: Address review comments from v1
> - removed irq reference from Linux driver
> - added 'channel' property to get ethernet to CPU channel number
> 
> v1:
> - Initial version
> 
> Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>

Series applied, thanks.


From arnd at arndb.de  Mon May  2 13:49:58 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 02 May 2016 22:49:58 +0200
Subject: [PATCH v2] s5p-mfc: Don't try to put pm->clock if lookup failed
In-Reply-To: <1462216462-32665-1-git-send-email-javier@osg.samsung.com>
References: <1462216462-32665-1-git-send-email-javier@osg.samsung.com>
Message-ID: <3778841.dDMP2IXCSZ@wuerfel>

On Monday 02 May 2016 15:14:22 Javier Martinez Canillas wrote:
> Failing to get the struct s5p_mfc_pm .clock is a non-fatal error so the
> clock field can have a errno pointer value. But s5p_mfc_final_pm() only
> checks if .clock is not NULL before attempting to unprepare and put it.
> 
> This leads to the following warning in clk_put() due s5p_mfc_final_pm():
> 
> WARNING: CPU: 3 PID: 1023 at drivers/clk/clk.c:2814 s5p_mfc_final_pm+0x48/0x74 [s5p_mfc]
> CPU: 3 PID: 1023 Comm: rmmod Tainted: G        W       4.6.0-rc6-next-20160502-00005-g5a15a49106bc #9
> Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [<c010e1bc>] (unwind_backtrace) from [<c010af28>] (show_stack+0x10/0x14)
> [<c010af28>] (show_stack) from [<c032485c>] (dump_stack+0x88/0x9c)
> [<c032485c>] (dump_stack) from [<c011b8e8>] (__warn+0xe8/0x100)
> [<c011b8e8>] (__warn) from [<c011b9b0>] (warn_slowpath_null+0x20/0x28)
> [<c011b9b0>] (warn_slowpath_null) from [<bf16004c>] (s5p_mfc_final_pm+0x48/0x74 [s5p_mfc])
> [<bf16004c>] (s5p_mfc_final_pm [s5p_mfc]) from [<bf157414>] (s5p_mfc_remove+0x8c/0x94 [s5p_mfc])
> [<bf157414>] (s5p_mfc_remove [s5p_mfc]) from [<c03fe1f8>] (platform_drv_remove+0x24/0x3c)
> [<c03fe1f8>] (platform_drv_remove) from [<c03fcc70>] (__device_release_driver+0x84/0x110)
> [<c03fcc70>] (__device_release_driver) from [<c03fcdd8>] (driver_detach+0xac/0xb0)
> [<c03fcdd8>] (driver_detach) from [<c03fbff8>] (bus_remove_driver+0x4c/0xa0)
> [<c03fbff8>] (bus_remove_driver) from [<c01886a8>] (SyS_delete_module+0x174/0x1b8)
> [<c01886a8>] (SyS_delete_module) from [<c01078c0>] (ret_fast_syscall+0x0/0x3c)
> 
> Assign the pointer to NULL in case of a lookup failure to fix the issue.
> 
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
> 
> 

Acked-by: Arnd Bergmann <arnd at arndb.de>


From robh at kernel.org  Mon May  2 13:56:48 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 2 May 2016 15:56:48 -0500
Subject: [PATCH v2 2/4] Documentation: Add documentation for APM X-Gene
 SoC PMU DTS binding
In-Reply-To: <20160420113121.GE2514@arm.com>
References: <1460510547-17611-1-git-send-email-ttnguyen@apm.com>
 <1460510547-17611-3-git-send-email-ttnguyen@apm.com>
 <20160418170009.GA15338@rob-hp-laptop>
 <CACgAJHyBbO_LXwtfNVK1f=dY3v1Jfxwxq1dw98EZ0aYdhjPpAg@mail.gmail.com>
 <20160420113121.GE2514@arm.com>
Message-ID: <20160502205648.GA7374@rob-hp-laptop>

On Wed, Apr 20, 2016 at 12:31:22PM +0100, Will Deacon wrote:
> On Mon, Apr 18, 2016 at 01:04:53PM -0700, Tai Tri Nguyen wrote:
> > >> +Required properties for MCB subnode:
> > >> +- compatible         : Shall be "apm,xgene-pmu-mcb".
> > >> +- reg                        : First resource shall be the MCB PMU resource.
> > >> +- index                      : Instance number of the MCB PMU.
> > >> +
> > >> +Required properties for MC subnode:
> > >> +- compatible         : Shall be "apm,xgene-pmu-mc".
> > >> +- reg                        : First resource shall be the MC PMU resource.
> > >> +- index                      : Instance number of the MC PMU.
> > >
> > > Don't use indexes. You probably need phandles to the nodes these are
> > > related to.
> > >
> > > How many variations of child nodes do you expect to have? 2, 10, 50? You
> > > might want to just collapse all this down to a single node and put this
> > > information in the driver if it is fixed for each SoC and there's only a
> > > handful.
> > >
> > 
> > For each kind of PMU, for example memory controller PMU, I expect to
> > have the number of instances up to 8.
> > They are actually all independent PMU nodes and have their own CSR memory bases.
> > The indexes are used for exposing the devices to perf user only. It
> > doesn't have an impact on the programming model.
> > Mark also had the same concern.
> 
> Regardless, I'll need an ack from Rob or Mark before I can merge this.

I still have a concern with this. Needing an index to expose to the user 
is generally not a valid reason. That's OS specific and therefore 
doesn't belong in DT.

Rob


From xhnjupt at gmail.com  Mon May  2 14:14:07 2016
From: xhnjupt at gmail.com (Han Xu)
Date: Mon, 2 May 2016 16:14:07 -0500
Subject: [PATCH 6/9] mtd: spi-nor: Support R/W for S25FS-S family flash
In-Reply-To: <DB5PR0401MB184503776038D76AD91B1779976D0@DB5PR0401MB1845.eurprd04.prod.outlook.com>
References: <1460605855-6689-1-git-send-email-B56489@freescale.com>
 <1460605855-6689-7-git-send-email-B56489@freescale.com>
 <DB5PR0401MB184503776038D76AD91B1779976D0@DB5PR0401MB1845.eurprd04.prod.outlook.com>
Message-ID: <CA+EcR23DG-9RbKSiGZOx56OoD5zEqcGbP_TjWtvuHv1_CGN3JQ@mail.gmail.com>

On Wed, Apr 20, 2016 at 5:34 PM, Han Xu <han.xu at nxp.com> wrote:
>
>
> ________________________________________
> From: Yunhui Cui <B56489 at freescale.com>
> Sent: Wednesday, April 13, 2016 9:50 PM
> To: dwmw2 at infradead.org; computersforpeace at gmail.com; han.xu at freescale.com
> Cc: linux-kernel at vger.kernel.org; linux-mtd at lists.infradead.org; linux-arm-kernel at lists.infradead.org; Yao Yuan; Yunhui Cui
> Subject: [PATCH 6/9] mtd: spi-nor: Support R/W for S25FS-S family flash
>
> From: Yunhui Cui <yunhui.cui at nxp.com>
>
> With the physical sectors combination, S25FS-S family flash
> requires some special operations for read/write functions.
>
> Signed-off-by: Yunhui Cui <yunhui.cui at nxp.com>
> ---
>  drivers/mtd/spi-nor/spi-nor.c | 59 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 59 insertions(+)
>
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> index 157841d..91ee920 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -39,6 +39,10 @@
>
>  #define SPI_NOR_MAX_ID_LEN     6
>  #define SPI_NOR_MAX_ADDR_WIDTH 4
> +/* Added for S25FS-S family flash */
> +#define SPINOR_CONFIG_REG3_OFFSET      0x800004
> +#define CR3V_4KB_ERASE_UNABLE  0x8
> +#define SPINOR_S25FS_FAMILY_ID 0x81
>
>  struct flash_info {
>         char            *name;
> @@ -78,6 +82,7 @@ struct flash_info {
>  };
>
>  #define JEDEC_MFR(info)        ((info)->id[0])
> +#define EXT_ID(info)   ((info)->id[5])
>
>  static const struct flash_info *spi_nor_match_id(const char *name);
>
> @@ -881,6 +886,7 @@ static const struct flash_info spi_nor_ids[] = {
>          */
>         { "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
>         { "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> +       { "s25fs256s1", INFO6(0x010219, 0x4d0181, 64 * 1024, 512, 0)},
>         { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
>         { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
>         { "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> @@ -1018,6 +1024,53 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
>         return ERR_PTR(-ENODEV);
>  }
>
> +/*
> + * The S25FS-S family physical sectors may be configured as a
> + * hybrid combination of eight 4-kB parameter sectors
> + * at the top or bottom of the address space with all
> + * but one of the remaining sectors being uniform size.
> + * The Parameter Sector Erase commands (20h or 21h) must
> + * be used to erase the 4-kB parameter sectors individually.
> + * The Sector (uniform sector) Erase commands (D8h or DCh)
> + * must be used to erase any of the remaining
> + * sectors, including the portion of highest or lowest address
> + * sector that is not overlaid by the parameter sectors.
> + * The uniform sector erase command has no effect on parameter sectors.
> + */
> +static int spansion_s25fs_disable_4kb_erase(struct spi_nor *nor)
> +{
> +       struct fsl_qspi *q;
> +       u32 cr3v_addr  = SPINOR_CONFIG_REG3_OFFSET;
> +       u8 cr3v = 0x0;
> +       int ret = 0x0;
> +
> +       q = nor->priv;
> +
> +       nor->cmd_buf[2] = cr3v_addr >> 16;
> +       nor->cmd_buf[1] = cr3v_addr >> 8;
> +       nor->cmd_buf[0] = cr3v_addr >> 0;
>
> I feel it's hacking code.
>
> Hi Brian, do we have any plan to support this special case? The RDAR(
> Read Any Register) needs an extra address parameter.

Hi Brian,

I was wondering if you have some free time to check the questions. Thanks.
>
> +
> +       ret = nor->read_reg(nor, SPINOR_OP_SPANSION_RDAR, &cr3v, 1);
> +       if (ret)
> +               return ret;
> +       if (cr3v & CR3V_4KB_ERASE_UNABLE)
> +               return 0;
> +       ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0);
> +       if (ret)
> +               return ret;
> +       cr3v = CR3V_4KB_ERASE_UNABLE;
> +       nor->program_opcode = SPINOR_OP_SPANSION_WRAR;
> +       nor->write(nor, cr3v_addr, 1, NULL, &cr3v);
> +
> +       ret = nor->read_reg(nor, SPINOR_OP_SPANSION_RDAR, &cr3v, 1);
> +       if (ret)
> +               return ret;
> +       if (!(cr3v & CR3V_4KB_ERASE_UNABLE))
> +               return -EPERM;
> +
> +       return 0;
> +}
> +
>  static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
>                         size_t *retlen, u_char *buf)
>  {
> @@ -1311,6 +1364,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
>                 spi_nor_wait_till_ready(nor);
>         }
>
> +       if (EXT_ID(info) == SPINOR_S25FS_FAMILY_ID) {
> +               ret = spansion_s25fs_disable_4kb_erase(nor);
> +               if (ret)
> +                       return ret;
> +       }
> +
>         if (!mtd->name)
>                 mtd->name = dev_name(dev);
>         mtd->priv = nor;
> --
> 2.1.0.27.g96db324
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/


From stefan at agner.ch  Mon May  2 14:22:04 2016
From: stefan at agner.ch (Stefan Agner)
Date: Mon, 02 May 2016 14:22:04 -0700
Subject: [PATCH] drm/fsl-dcu: add COMMON_CLK dependency
In-Reply-To: <1462186839-2224021-1-git-send-email-arnd@arndb.de>
References: <1462186839-2224021-1-git-send-email-arnd@arndb.de>
Message-ID: <96882621acf64dca8d6c1d2f25307385@agner.ch>

On 2016-05-02 04:00, Arnd Bergmann wrote:
> The fsl dcu now uses the clk-provider interfaces, which are not available
> when CONFIG_COMMON_CLK is disabled:
> 
> drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c: In function 'fsl_dcu_drm_probe':
> drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c:362:20: error: implicit
> declaration of function '__clk_get_name'
> [-Werror=implicit-function-declaration]
>   pix_clk_in_name = __clk_get_name(pix_clk_in);
> 
> This adds a Kconfig dependency to prevent the driver from being enabled
> in this case.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Fixes: 2d701449bce1 ("drm/fsl-dcu: use common clock framework for
> pixel clock divider")

Oh right, thx!

Acked-by: Stefan Agner <stefan at agner.ch>

@Dave, can you pick that up directly or do you prefer a pull request?

--
Stefan

> ---
>  drivers/gpu/drm/fsl-dcu/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig
> index c78cf3f605d0..b9c714de6e40 100644
> --- a/drivers/gpu/drm/fsl-dcu/Kconfig
> +++ b/drivers/gpu/drm/fsl-dcu/Kconfig
> @@ -1,6 +1,6 @@
>  config DRM_FSL_DCU
>  	tristate "DRM Support for Freescale DCU"
> -	depends on DRM && OF && ARM
> +	depends on DRM && OF && ARM && COMMON_CLK
>  	select BACKLIGHT_CLASS_DEVICE
>  	select BACKLIGHT_LCD_SUPPORT
>  	select DRM_KMS_HELPER


From ttnguyen at apm.com  Mon May  2 14:46:05 2016
From: ttnguyen at apm.com (Tai Tri Nguyen)
Date: Mon, 2 May 2016 14:46:05 -0700
Subject: [PATCH v2 2/4] Documentation: Add documentation for APM X-Gene
 SoC PMU DTS binding
In-Reply-To: <20160502205648.GA7374@rob-hp-laptop>
References: <1460510547-17611-1-git-send-email-ttnguyen@apm.com>
 <1460510547-17611-3-git-send-email-ttnguyen@apm.com>
 <20160418170009.GA15338@rob-hp-laptop>
 <CACgAJHyBbO_LXwtfNVK1f=dY3v1Jfxwxq1dw98EZ0aYdhjPpAg@mail.gmail.com>
 <20160420113121.GE2514@arm.com>
 <20160502205648.GA7374@rob-hp-laptop>
Message-ID: <CACgAJHyT31DuVNoyRQZVKjv=zM5Fc-EY0gy=y=pHHrBTT+1Xow@mail.gmail.com>

Hi Rob,

On Mon, May 2, 2016 at 1:56 PM, Rob Herring <robh at kernel.org> wrote:
> On Wed, Apr 20, 2016 at 12:31:22PM +0100, Will Deacon wrote:
>> On Mon, Apr 18, 2016 at 01:04:53PM -0700, Tai Tri Nguyen wrote:
>> > >> +Required properties for MCB subnode:
>> > >> +- compatible         : Shall be "apm,xgene-pmu-mcb".
>> > >> +- reg                        : First resource shall be the MCB PMU resource.
>> > >> +- index                      : Instance number of the MCB PMU.
>> > >> +
>> > >> +Required properties for MC subnode:
>> > >> +- compatible         : Shall be "apm,xgene-pmu-mc".
>> > >> +- reg                        : First resource shall be the MC PMU resource.
>> > >> +- index                      : Instance number of the MC PMU.
>> > >
>> > > Don't use indexes. You probably need phandles to the nodes these are
>> > > related to.
>> > >
>> > > How many variations of child nodes do you expect to have? 2, 10, 50? You
>> > > might want to just collapse all this down to a single node and put this
>> > > information in the driver if it is fixed for each SoC and there's only a
>> > > handful.
>> > >
>> >
>> > For each kind of PMU, for example memory controller PMU, I expect to
>> > have the number of instances up to 8.
>> > They are actually all independent PMU nodes and have their own CSR memory bases.
>> > The indexes are used for exposing the devices to perf user only. It
>> > doesn't have an impact on the programming model.
>> > Mark also had the same concern.
>>
>> Regardless, I'll need an ack from Rob or Mark before I can merge this.
>
> I still have a concern with this. Needing an index to expose to the user
> is generally not a valid reason. That's OS specific and therefore
> doesn't belong in DT.
>
> Rob

I can use device name here. However, the perf event names will be
different between DT and ACPI which I want to avoid.
And the names don't look good at all.
Also, specifically for MC and MCB PMUs, the indexes are compared
against the active MC/MCB mask to find out whether they are populated
or not.
Without using the index property, I will also need a mapping function
of physical device addresses and their physical ids.

Thanks,
-- 
Tai


From festevam at gmail.com  Mon May  2 16:56:26 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon,  2 May 2016 20:56:26 -0300
Subject: [PATCH] ARM: dts: imx6ul-14x14-evk: Add audio support
Message-ID: <1462233386-23185-1-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam at nxp.com>

imx6ul-14x14-evk has a wm8960 codec connected via SAI2 port.

Add support for it.

Thanks to Petr Kulhavy <brain at jikos.cz> for the hint on initializing
the PLL4 frequency to get a correct MCLK.

Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
---
Shawn,

In order to get audio functional it is still needed to get bit 20
of GPR1 register.

This is a separate patch though and I will discuss it on another thread.

 arch/arm/boot/dts/imx6ul-14x14-evk.dts | 75 ++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dts b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
index 7207280..8b4776a 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk.dts
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
@@ -36,6 +36,45 @@
 			enable-active-high;
 		};
 	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "mx6ul-wm8960";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&dailink_master>;
+		simple-audio-card,frame-master = <&dailink_master>;
+		simple-audio-card,widgets =
+			"Microphone", "Mic Jack",
+			"Line", "Line In",
+			"Line", "Line Out",
+			"Speaker", "Speaker",
+			"Headphone", "Headphone Jack";
+		simple-audio-card,routing =
+			"Headphone Jack", "HP_L",
+			"Headphone Jack", "HP_R",
+			"Speaker", "SPK_LP",
+			"Speaker", "SPK_LN",
+			"Speaker", "SPK_RP",
+			"Speaker", "SPK_RN",
+			"LINPUT1", "Mic Jack",
+			"LINPUT3", "Mic Jack",
+			"RINPUT1", "Mic Jack",
+			"RINPUT2", "Mic Jack";
+
+		simple-audio-card,cpu {
+			sound-dai = <&sai2>;
+		};
+
+		dailink_master: simple-audio-card,codec {
+			sound-dai = <&codec>;
+			clocks = <&clks IMX6UL_CLK_SAI2>;
+		};
+	};
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <786432000>;
 };
 
 &cpu0 {
@@ -43,6 +82,20 @@
 	soc-supply = <&reg_soc>;
 };
 
+&i2c2 {
+	clock_frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	codec: wm8960 at 1a {
+		#sound-dai-cells = <0>;
+		compatible = "wlf,wm8960";
+		reg = <0x1a>;
+		wlf,shared-lrclk;
+	};
+};
+
 &fec1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet1>;
@@ -86,6 +139,17 @@
 	};
 };
 
+&sai2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai2>;
+
+	assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
+			  <&clks IMX6UL_CLK_SAI2>;
+	assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <0>, <12288000>;
+	status = "okay";
+};
+
 &snvs_poweroff {
 	status = "okay";
 };
@@ -272,6 +336,17 @@
 		>;
 	};
 
+	pinctrl_sai2: sai2grp {
+		fsl,pins = <
+			MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK	0x17088
+			MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC	0x17088
+			MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA	0x11088
+			MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA	0x11088
+			MX6UL_PAD_JTAG_TMS__SAI2_MCLK		0x17088
+			MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04	0x17059
+		>;
+	};
+
 	pinctrl_pwm1: pwm1grp {
 		fsl,pins = <
 			MX6UL_PAD_GPIO1_IO08__PWM1_OUT   0x110b0
-- 
1.9.1



From festevam at gmail.com  Mon May  2 16:59:17 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 2 May 2016 20:59:17 -0300
Subject: mx6ul: Finding a good place to configure SAI2_MCLK
Message-ID: <CAOMZO5CvT1rcHFPm6KoCBBgM1UACByLUQcJ_zDxY9ucbxCpgYA@mail.gmail.com>

Hi,

In order to get audio working on imx6ul-evk board we need to enable
the SAI2 MCLK clock by setting bit 20 (SAI2_MCLK_DIR) of the
IOMUXC_GPR_GPR1 register.

I am not sure where is the appropriate place to set this bit.

Doing like this works fine:

--- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
+++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
@@ -447,5 +447,6 @@
 #define IMX6UL_GPR1_ENET2_CLK_OUTPUT           (0x1 << 18)
 #define IMX6UL_GPR1_ENET_CLK_DIR               (0x3 << 17)
 #define IMX6UL_GPR1_ENET_CLK_OUTPUT            (0x3 << 17)
+#define IMX6UL_GPR1_SAI2_MCLK_DIR              (0x1 << 20)

index a38b16b..92cfb0f 100644
--- a/arch/arm/mach-imx/mach-imx6ul.c
+++ b/arch/arm/mach-imx/mach-imx6ul.c
@@ -56,6 +56,19 @@ static inline void imx6ul_enet_init(void)
        imx6ul_enet_phy_init();
 }

+static void __init imx6ul_mclk_init(void)
+{
+       struct regmap *gpr;
+
+       gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr");
+       if (!IS_ERR(gpr))
+               regmap_update_bits(gpr, IOMUXC_GPR1, IMX6UL_GPR1_SAI2_MCLK_DIR,
+                                  IMX6UL_GPR1_SAI2_MCLK_DIR);
+       else
+               pr_err("failed to find fsl,imx6ul-iomux-gpr regmap\n");
+
+}
+
 static void __init imx6ul_init_machine(void)
 {
        struct device *parent;
@@ -68,6 +81,7 @@ static void __init imx6ul_init_machine(void)
        imx6ul_enet_init();
        imx_anatop_init();
        imx6ul_pm_init();
+       imx6ul_mclk_init();
 }

but it does not seem correct as this should be board specific. Should
we call it only if the compatible string matches imx6sl-14x14-evk
string? Looks like that will not scale as well.

Currently in arch/arm/mach-imx/mach-imx6ul.c we also have
imx6ul_enet_clk_init() function which sets the ENET_CLK in the GPR1
register.

IMHO this is not correct because not all mx6ul boards need such clock
and then we need to change this too.

So where should we set the SAI2_MCLK_DIR bit of GPR1? Inside the SAI driver?

Appreciate some feedback.

Thanks,

Fabio Estevam


From sboyd at codeaurora.org  Mon May  2 17:02:48 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 2 May 2016 17:02:48 -0700
Subject: [GIT PULL] clk: tegra: Changes for v4.7-rc1
In-Reply-To: <1461945596-24090-1-git-send-email-thierry.reding@gmail.com>
References: <1461945596-24090-1-git-send-email-thierry.reding@gmail.com>
Message-ID: <20160503000248.GB3492@codeaurora.org>

On 04/29, Thierry Reding wrote:
> Hi Michael, Stephen,
> 
> The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:
> 
>   Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-4.7-clk
> 
> for you to fetch changes up to 2690e912644e610854c4c3b23d0a0daec9d030ca:
> 
>   clk: tegra: dfll: Reformat CVB frequency table (2016-04-28 12:41:54 +0200)
> 
> Note that the first patch is this pull request is a dependency for a
> larger series that will have to go in through the ARM-SoC tree in order
> to properly handle the dependencies.
> 

Thanks. Pulled.

Are there any thoughts on making that hw control stuff more
generic? Perhaps using something like power domains to do that
instead of having drivers cross-call to the clk driver with
custom tegra APIs?

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


From sboyd at codeaurora.org  Mon May  2 17:05:08 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 2 May 2016 17:05:08 -0700
Subject: [GIT PULL] Allwinner clocks additions for 4.7
In-Reply-To: <20160429164933.GA8913@lukather>
References: <20160429164933.GA8913@lukather>
Message-ID: <20160503000508.GC3492@codeaurora.org>

On 04/29, Maxime Ripard wrote:
> Hi Mike, Stephen,
> 
> Please pull the following tag for the next merge window.
> 

Thanks. Pulled.

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


From gregkh at linuxfoundation.org  Mon May  2 17:12:26 2016
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Mon,  2 May 2016 17:12:26 -0700
Subject: [PATCH 4.4 118/163] irqchip/sunxi-nmi: Fix error check of
 of_io_request_and_map()
In-Reply-To: <20160503000508.556845508@linuxfoundation.org>
References: <20160503000508.556845508@linuxfoundation.org>
Message-ID: <20160503000512.384002600@linuxfoundation.org>

4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Vladimir Zapolskiy <vz at mleia.com>

commit cfe199afefe6201e998ddc07102fc1fdb55f196c upstream.

The of_io_request_and_map() returns a valid pointer in iomem region or
ERR_PTR(), check for NULL always fails and may cause a NULL pointer
dereference on error path.

Fixes: 0e841b04c829 ("irqchip/sunxi-nmi: Switch to of_io_request_and_map() from of_iomap()")
Signed-off-by: Vladimir Zapolskiy <vz at mleia.com>
Cc: Jason Cooper <jason at lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier at arm.com>
Cc: Chen-Yu Tsai <wens at csie.org>
Cc: Maxime Ripard <maxime.ripard at free-electrons.com>
Cc: linux-arm-kernel at lists.infradead.org
Link: http://lkml.kernel.org/r/1457486489-10189-1-git-send-email-vz at mleia.com
Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>

---
 drivers/irqchip/irq-sunxi-nmi.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/drivers/irqchip/irq-sunxi-nmi.c
+++ b/drivers/irqchip/irq-sunxi-nmi.c
@@ -154,9 +154,9 @@ static int __init sunxi_sc_nmi_irq_init(
 
 	gc = irq_get_domain_generic_chip(domain, 0);
 	gc->reg_base = of_io_request_and_map(node, 0, of_node_full_name(node));
-	if (!gc->reg_base) {
+	if (IS_ERR(gc->reg_base)) {
 		pr_err("unable to map resource\n");
-		ret = -ENOMEM;
+		ret = PTR_ERR(gc->reg_base);
 		goto fail_irqd_remove;
 	}
 




From gregkh at linuxfoundation.org  Mon May  2 17:12:27 2016
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Mon,  2 May 2016 17:12:27 -0700
Subject: [PATCH 4.4 119/163] irqchip/mxs: Fix error check of
 of_io_request_and_map()
In-Reply-To: <20160503000508.556845508@linuxfoundation.org>
References: <20160503000508.556845508@linuxfoundation.org>
Message-ID: <20160503000512.416870174@linuxfoundation.org>

4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Vladimir Zapolskiy <vz at mleia.com>

commit edf8fcdc6b254236be005851af35ea5e826e7e09 upstream.

The of_io_request_and_map() returns a valid pointer in iomem region or
ERR_PTR(), check for NULL always fails and may cause a NULL pointer
dereference on error path.

Fixes: 25e34b44313b ("irqchip/mxs: Prepare driver for hardware with different offsets")
Signed-off-by: Vladimir Zapolskiy <vz at mleia.com>
Cc: Jason Cooper <jason at lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier at arm.com>
Cc: Oleksij Rempel <linux at rempel-privat.de>
Cc: Sascha Hauer <kernel at pengutronix.de>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org
Link: http://lkml.kernel.org/r/1457486500-10237-1-git-send-email-vz at mleia.com
Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>

---
 drivers/irqchip/irq-mxs.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -183,7 +183,7 @@ static void __iomem * __init icoll_init_
 	void __iomem *icoll_base;
 
 	icoll_base = of_io_request_and_map(np, 0, np->name);
-	if (!icoll_base)
+	if (IS_ERR(icoll_base))
 		panic("%s: unable to map resource", np->full_name);
 	return icoll_base;
 }




From sboyd at codeaurora.org  Mon May  2 17:33:11 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 2 May 2016 17:33:11 -0700
Subject: [PATCH v2] clk: uniphier: add clock drivers for UniPhier SoCs
In-Reply-To: <CAK7LNASQD4fpi=iDRbX96tSBvYjT_-N8EJnNk1VpuMxBTEnONg@mail.gmail.com>
References: <1451298003-28841-1-git-send-email-yamada.masahiro@socionext.com>
 <20160226000713.GO28849@codeaurora.org>
 <CAK7LNASQD4fpi=iDRbX96tSBvYjT_-N8EJnNk1VpuMxBTEnONg@mail.gmail.com>
Message-ID: <20160503003311.GE3492@codeaurora.org>

On 05/03, Masahiro Yamada wrote:
> 
> 2016-02-26 9:07 GMT+09:00 Stephen Boyd <sboyd at codeaurora.org>:
> > On 12/28, Masahiro Yamada wrote:
> >>
> >> diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
> >> new file mode 100644
> >> index 0000000..7606f27
> >> --- /dev/null
> >> +++ b/drivers/clk/uniphier/Kconfig
> >> @@ -0,0 +1,35 @@
> >> +menuconfig CLK_UNIPHIER
> >> +     bool "Clock drivers for UniPhier SoCs"
> >> +     depends on ARCH_UNIPHIER
> >
> > Can we have COMPILE_TEST here?
> 
> OK.
> But if you recommend to drop "depends on ARCH_UNIPHIER",
> COMPILE_TEST is not necessary.

Right, I wasn't recommending removing the depends on
ARCH_UNIPHIER. Sorry if that wasn't clear.

> 
> 
> >> +     depends on OF
> >> +     default y
> >
> > And then default ARCH_UNIPHIER instead.
> 
> 
> 
> The problem is that CLK_UNIPHIER is not enabled along with
> ARCH_UNIPHIER in "make menuconfig".
> 
> If we use "depends on ARCH_UNIPHIER"
> and we enable ARCH_UNIPHIER from "make menuconfig",
> CLK_UNIPHIER is automatically enabled as well.
> 
> Is the latter more like what we expect?

I'm thinking

	menuconfig CLK_UNIPHIER
		bool "Clock drivers for UniPhier SoCs"
		depends on ARCH_UNIPHIER || COMPILE_TEST
		depends on OF
		default ARCH_UNIPHIER

That way we can build it even if we're not the arch, and it's
defaulted to be built if we have the arch enabled, but it isn't
defaulted to be built if that arch isn't enabled and compile test
is enabled.

> 
> >
> > If possible please don't use clock-names to set up clock
> > hierarchy.
> 
> So, what shall I do instead?
> 
> I am not comfortable with hard-coding the parents' names
> for clock-cascading.
> 
> Maybe, can we support clk registration
> with clk_hw of parents, not names of parents?
> 
> For example, by adding  "struct clk_hw **parents"
> to struct clk_init_data.
> 

Sounds like it isn't possible to avoid clock-names DT property
then. Not a big deal.

We've been trying to figure out some way to register clks without
requiring strings, but so far nothing has really happened. The
clk_hw approach would work, except for the case where some of the
provider's clks rely on another provider's clks that also rely on
the first provider (sort of a spiral of dependencies). In that
case we want to break the provider level loop by letting clks say
something besides clk_hw pointers are parents.

Strings work well here because we have support for clock-names
and string based parent-child descriptions already, but maybe
we'd be better off having some way to say that this clk we're
registering uses provider X's 24th output as its second parent.
It would be good if we avoided tying it to any DT construct
though, because DT isn't the only way clks are registered and
provided to the system.

This is all because we know that forcing driver authors to come
up with globally unique names for clks just doesn't work when it
comes to things like the same clk controller IP instantiated
twice in the hardware and thus the same driver matches both
device instances.

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


From sboyd at codeaurora.org  Mon May  2 17:37:16 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 2 May 2016 17:37:16 -0700
Subject: [PATCH v2 04/13] clkdev: Add clk_hw based registration APIs
In-Reply-To: <1461277324-27185-5-git-send-email-sboyd@codeaurora.org>
References: <1461277324-27185-1-git-send-email-sboyd@codeaurora.org>
 <1461277324-27185-5-git-send-email-sboyd@codeaurora.org>
Message-ID: <20160503003716.GH3492@codeaurora.org>

On 04/21, Stephen Boyd wrote:
> Now that we have a clk registration API that doesn't return
> struct clks, we need to have some way to hand out struct clks via
> the clk_get() APIs that doesn't involve associating struct clk
> pointers with a struct clk_lookup. Luckily, clkdev already
> operates on struct clk_hw pointers, except for the registration
> facing APIs where it converts struct clk pointers into struct
> clk_hw pointers almost immediately.
> 
> Let's add clk_hw based registration APIs so that we can skip the
> conversion step and provide a way for clk provider drivers to
> operate exclusively on clk_hw structs. This way we clearly
> split the API between consumers and providers.
> 
> Cc: Russell King <linux at arm.linux.org.uk>
> Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
> ---

Applied to clk-next

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


From sboyd at codeaurora.org  Mon May  2 17:37:12 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 2 May 2016 17:37:12 -0700
Subject: [PATCH v2 01/13] clkdev: Remove clk_register_clkdevs()
In-Reply-To: <1461277324-27185-2-git-send-email-sboyd@codeaurora.org>
References: <1461277324-27185-1-git-send-email-sboyd@codeaurora.org>
 <1461277324-27185-2-git-send-email-sboyd@codeaurora.org>
Message-ID: <20160503003712.GG3492@codeaurora.org>

On 04/21, Stephen Boyd wrote:
> Now that we've converted the only caller over to another clkdev
> API, remove this one.
> 
> Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
> Cc: Russell King <linux at arm.linux.org.uk>
> Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
> ---

Applied to clk-next

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


From sboyd at codeaurora.org  Mon May  2 17:45:11 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 2 May 2016 17:45:11 -0700
Subject: [PATCH V2 5/7] mvebu: Use dev_pm_opp_set_sharing_cpus() to mark
 OPP tables as shared
In-Reply-To: <e13515db21cb178a8834d50f8b6b68e9b650aaec.1461727086.git.viresh.kumar@linaro.org>
References: <cover.1461727086.git.viresh.kumar@linaro.org>
 <e13515db21cb178a8834d50f8b6b68e9b650aaec.1461727086.git.viresh.kumar@linaro.org>
Message-ID: <20160503004511.GL3492@codeaurora.org>

On 04/27, Viresh Kumar wrote:
> That will allow us to avoid using cpufreq-dt platform data.
> 
> Cc: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
> Cc: Jason Cooper <jason at lakedaemon.net>
> Cc: Andrew Lunn <andrew at lunn.ch>
> Cc: Gregory Clement <gregory.clement at free-electrons.com>
> Cc: Sebastian Hesselbarth <sebastian.hesselbarth at gmail.com>
> Signed-off-by: Viresh Kumar <viresh.kumar at linaro.org>
> ---

Reviewed-by: Stephen Boyd <sboyd at codeaurora.org>

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


From gregkh at linuxfoundation.org  Mon May  2 17:12:19 2016
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Mon,  2 May 2016 17:12:19 -0700
Subject: [PATCH 4.5 140/200] irqchip/sunxi-nmi: Fix error check of
 of_io_request_and_map()
In-Reply-To: <20160503000554.631204776@linuxfoundation.org>
References: <20160503000554.631204776@linuxfoundation.org>
Message-ID: <20160503000559.214372089@linuxfoundation.org>

4.5-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Vladimir Zapolskiy <vz at mleia.com>

commit cfe199afefe6201e998ddc07102fc1fdb55f196c upstream.

The of_io_request_and_map() returns a valid pointer in iomem region or
ERR_PTR(), check for NULL always fails and may cause a NULL pointer
dereference on error path.

Fixes: 0e841b04c829 ("irqchip/sunxi-nmi: Switch to of_io_request_and_map() from of_iomap()")
Signed-off-by: Vladimir Zapolskiy <vz at mleia.com>
Cc: Jason Cooper <jason at lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier at arm.com>
Cc: Chen-Yu Tsai <wens at csie.org>
Cc: Maxime Ripard <maxime.ripard at free-electrons.com>
Cc: linux-arm-kernel at lists.infradead.org
Link: http://lkml.kernel.org/r/1457486489-10189-1-git-send-email-vz at mleia.com
Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>

---
 drivers/irqchip/irq-sunxi-nmi.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/drivers/irqchip/irq-sunxi-nmi.c
+++ b/drivers/irqchip/irq-sunxi-nmi.c
@@ -160,9 +160,9 @@ static int __init sunxi_sc_nmi_irq_init(
 
 	gc = irq_get_domain_generic_chip(domain, 0);
 	gc->reg_base = of_io_request_and_map(node, 0, of_node_full_name(node));
-	if (!gc->reg_base) {
+	if (IS_ERR(gc->reg_base)) {
 		pr_err("unable to map resource\n");
-		ret = -ENOMEM;
+		ret = PTR_ERR(gc->reg_base);
 		goto fail_irqd_remove;
 	}
 




From gregkh at linuxfoundation.org  Mon May  2 17:12:20 2016
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Mon,  2 May 2016 17:12:20 -0700
Subject: [PATCH 4.5 141/200] irqchip/mxs: Fix error check of
 of_io_request_and_map()
In-Reply-To: <20160503000554.631204776@linuxfoundation.org>
References: <20160503000554.631204776@linuxfoundation.org>
Message-ID: <20160503000559.246766070@linuxfoundation.org>

4.5-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Vladimir Zapolskiy <vz at mleia.com>

commit edf8fcdc6b254236be005851af35ea5e826e7e09 upstream.

The of_io_request_and_map() returns a valid pointer in iomem region or
ERR_PTR(), check for NULL always fails and may cause a NULL pointer
dereference on error path.

Fixes: 25e34b44313b ("irqchip/mxs: Prepare driver for hardware with different offsets")
Signed-off-by: Vladimir Zapolskiy <vz at mleia.com>
Cc: Jason Cooper <jason at lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier at arm.com>
Cc: Oleksij Rempel <linux at rempel-privat.de>
Cc: Sascha Hauer <kernel at pengutronix.de>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: linux-arm-kernel at lists.infradead.org
Link: http://lkml.kernel.org/r/1457486500-10237-1-git-send-email-vz at mleia.com
Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>

---
 drivers/irqchip/irq-mxs.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -183,7 +183,7 @@ static void __iomem * __init icoll_init_
 	void __iomem *icoll_base;
 
 	icoll_base = of_io_request_and_map(np, 0, np->name);
-	if (!icoll_base)
+	if (IS_ERR(icoll_base))
 		panic("%s: unable to map resource", np->full_name);
 	return icoll_base;
 }




From Yisen.zhuang at huawei.com  Mon May  2 17:54:11 2016
From: Yisen.zhuang at huawei.com (Yisen Zhuang)
Date: Tue, 3 May 2016 08:54:11 +0800
Subject: [PATCH net-next 0/4] net: hns: update DT properties according to
 Rob's comments
In-Reply-To: <20160429.133949.1719521222260369497.davem@davemloft.net>
References: <1461827344-52230-1-git-send-email-Yisen.Zhuang@huawei.com>
 <20160429.133949.1719521222260369497.davem@davemloft.net>
Message-ID: <5727F6B3.2080007@huawei.com>

Hi David,

Thanks for applying the patches.

The series which i reposted is my misoperation. Please ignore them.

Thanks,

Yisen

? 2016/4/30 1:39, David Miller ??:
> From: Yisen Zhuang <Yisen.Zhuang at huawei.com>
> Date: Thu, 28 Apr 2016 15:09:00 +0800
> 
>> There are some inappropriate properties definition in hns DT. We update the definition
>> according to Rob's review comments and fix some typos in binding.
>>
>> For more details, please see individual patches.
> 
> Series applied, thanks.
> 
> BTW, you reposted your 10 part series for adding the dsaf-debug device, but I
> already applied the series you posted for that nearly a week ago.
> 
> .
> 



From eric at anholt.net  Mon May  2 18:09:22 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon, 02 May 2016 18:09:22 -0700
Subject: [PATCH 2/2] clk: bcm2835: Skip PLLC clocks when deciding on a new
 clock parent
In-Reply-To: <FB575328-E891-4ECC-B0D5-E7243CDEE44E@martin.sperl.org>
References: <1461699585-6649-1-git-send-email-eric@anholt.net>
 <1461699585-6649-2-git-send-email-eric@anholt.net>
 <C771F70C-2F88-49E1-A370-D76D13262C1E@martin.sperl.org>
 <878tzsiilh.fsf@eliezer.anholt.net>
 <FB575328-E891-4ECC-B0D5-E7243CDEE44E@martin.sperl.org>
Message-ID: <87zis8uev1.fsf@eliezer.anholt.net>

Martin Sperl <kernel at martin.sperl.org> writes:

>> On 02.05.2016, at 17:29, Eric Anholt <eric at anholt.net> wrote:
>> 
>> Martin Sperl <kernel at martin.sperl.org> writes:
>> 
>>>> On 26.04.2016, at 21:39, Eric Anholt <eric at anholt.net> wrote:
>>>> 
>>>> If the firmware had set up a clock to source from PLLC, go along with
>>>> it.  But if we're looking for a new parent, we don't want to switch it
>>>> to PLLC because the firmware will force PLLC (and thus the AXI bus
>>>> clock) to different frequencies during over-temp/under-voltage,
>>>> without notification to Linux.
>>>> 
>>>> On my system, this moves the Linux-enabled HDMI state machine and DSI1
>>>> escape clock over to plld_per from pllc_per.  EMMC still ends up on
>>>> pllc_per, because the firmware had set it up to use that.
>>>> 
>>>> Signed-off-by: Eric Anholt <eric at anholt.net>
>>>> Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks")
>>>> ?
>>> 
>>> I guess this patch looks to me as if it is a policy inside the kernel,
>>> which is AFAIK frowned upon.
>> 
>> Can you come up with a use for putting peripherals on PLLC ever, such
>> that we need choice?
>
> For PLLC not right now, but with clk_notifier_register drivers could
> work around those clock changes (assuming we get that information
> from the firmware somehow - or if we could move this decision into the
> kernel: even better).

Why would you want to automatically choose an unstable clock instead of
the stable clock we have available?

> But I can come up with a scenario that would make use of the pllh_aux
> under some circumstances - e.g when requesting 290039Hz on clock gp0/1/2.
>
> Similarly: if we ever enable the testdebugX clocks these become immediate
> candidates for parent-clocks as well which can result in more headache.

How are you planning to make use of the testdebug inputs?  As far as I
know, those are for bit-banging your clocks during hardware bringup
debugging.  They wouldn't be clocks you'd automatically choose.

> Being able to define which clocks to use at least give the dts author
> a means also to control clock selection if he wants to enable the
> testdebug clocks.

If you were to clock-assigned-parents something to PLLC, this code won't
override that.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/6df893d2/attachment.sig>

From eric at anholt.net  Mon May  2 18:13:09 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon, 02 May 2016 18:13:09 -0700
Subject: [PATCH V4 1/2] clk: bcm2835: mark enabled clocks with
 CLK_IS_CRITICAL
In-Reply-To: <5CC0D984-91E5-4401-8AB6-5827269C4395@martin.sperl.org>
References: <1461951756-16804-1-git-send-email-kernel@martin.sperl.org>
 <1461951756-16804-2-git-send-email-kernel@martin.sperl.org>
 <87zis8h3pp.fsf@eliezer.anholt.net>
 <5CC0D984-91E5-4401-8AB6-5827269C4395@martin.sperl.org>
Message-ID: <87wpncueoq.fsf@eliezer.anholt.net>

Martin Sperl <kernel at martin.sperl.org> writes:

>> On 02.05.2016, at 17:36, Eric Anholt <eric at anholt.net> wrote:
>> 
>> kernel at martin.sperl.org writes:
>> 
>>> From: Martin Sperl <kernel at martin.sperl.org>
>>> 
>>> The bcm2835 firmware enables several clocks and plls before
>>> booting the linux kernel.
>>> 
>>> These plls should never get disabled as it may result in a
>>> stopped system clock and more.
>>> 
>>> So during probing we check if the clock is enabled
>>> and if it is then mark that clock with CLK_IS_CRITICAL.
>>> 
>>> As a consequence this will also enable the corresponding
>>> parent plls and pll-divs.
>>> 
>>> This is intended as a stop-gap until CLK_ENABLE_HAND_OFF
>>> becomes available, at which point it should be used instead.
>>> 
>>> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
>> 
>> I still think that we don't want this patch.  We should be able to
>> disable clocks that the firmware turned on, unless they really need to
>> stay on.  If you have troubles on the upstream DT, let's talk about
>> individual clocks.
>
> May I ask you what is your main concern about using
> CLK_IS_CRITICAL as a stop-gap/in general?

Burning power when you shouldn't, which is a bug.

> Also the current situation of the machine crashing when releasing the
> PCM clock when the parent is PLLC or PLLD is worse than having some
> clocks/pll running unnecessarily.

Are you saying this happens on the upstream kernel?  This sounds like a
bug you'd see in the downstream kernel because they haven't hooked up
the clocks in their DT.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160502/a6e893d2/attachment.sig>

From f.fainelli at gmail.com  Mon May  2 18:25:47 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Mon,  2 May 2016 18:25:47 -0700
Subject: [PATCH 0/2] pci: host: Broadcom STB PCIE RC controller support
Message-ID: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>

Hi all,

This patch series adds support for Broadcom STB SoC's PCIe root complex driver.

This was primarily tested on BCM7445 (ARM) and BCM7435 (MIPS).

Jim is the original author, and I picked up our downstream 4.1 driver and
updated it to utilize the non-ARM hw_pci functions as well as made some
stylistic changes.

Thanks!

Jim Quinlan (2):
  Documentation: DT: bindings: Add Broadcom STB PCIe bindings
  pci: host: Add Broadcom STB PCIE RC controller

 .../devicetree/bindings/pci/brcm,brcmstb-pcie.txt  |   81 ++
 MAINTAINERS                                        |    1 +
 drivers/pci/host/Kconfig                           |    9 +
 drivers/pci/host/Makefile                          |    1 +
 drivers/pci/host/pcie-brcmstb.c                    | 1243 ++++++++++++++++++++
 5 files changed, 1335 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
 create mode 100644 drivers/pci/host/pcie-brcmstb.c

-- 
2.1.0



From f.fainelli at gmail.com  Mon May  2 18:25:48 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Mon,  2 May 2016 18:25:48 -0700
Subject: [PATCH 1/2] Documentation: DT: bindings: Add Broadcom STB PCIe
 bindings
In-Reply-To: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>
References: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1462238749-19715-2-git-send-email-f.fainelli@gmail.com>

From: Jim Quinlan <jim2101024 at gmail.com>

This patchs adds the Device Tree bindings for the Broadcom STB PCIe root
complex hardware.

Signed-off-by: Jim Quinlan <jim2101024 at gmail.com>
Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
 .../devicetree/bindings/pci/brcm,brcmstb-pcie.txt  | 81 ++++++++++++++++++++++
 1 file changed, 81 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt

diff --git a/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
new file mode 100644
index 000000000000..922317969ab5
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
@@ -0,0 +1,81 @@
+Brcmstb PCIe Host Controller Device Tree Bindings
+
+Introduction:
+
+The brcmstb host controller closely follows the example set in
+
+	[1] http://devicetree.org/Device_Tree_Usage#PCI_Host_Bridge
+
+The rest of this document explains some added customizations and
+offers an example Brcmstb PCIe host controller DT node.
+
+Required Properties:
+  reg -- the register start address and length for the PCIe block.
+      Additional start,length pairs may be specified for clock addresses.
+  interrupts -- this must be specified but it is used indirectly.  Interrupt
+      zero must be specified; the Brcmstb driver code uses this interrupt
+      to determine the offset used for all interrupts, specifically, those
+      listed in interrupt-map.
+  compatible -- must be one of: "brcm,bcm7425-pcie", "brcm,bcm7435-pcie" or
+      "brcm,bcm7445-pcie".
+  #address-cells -- the number of address cells for PCI-space.
+  #size-cells -- the number of size cells for PCI-space.
+  ranges -- See [1]; a specification of the outbound windows for the host
+      controller.  Each outbound window is described by a 7-tuple:
+          (3 entries) -- PCIe space start address (0th entry is ignored).
+          (2 entries) -- CPU/System start address
+          (2 entries) -- Size of region.
+      Due to hardware limitations, there may be a maximum of four windows
+      specified.
+  #interrupt-cells -- number of cells used to describe the interrupt.
+  interrupt-map -- See [1]; each interrupt requires 7 entries, and
+      currently all but the fifth entry (order 0) -- the interrupt
+      number -- is ignored.  There must be four interrupts specified
+      for the PCI's INTA, INTB, INTC, and INTD.
+
+Optional Properties:
+  interrupt-names -- names of the interrupts listed in the interrupt map.
+  clocks -- list of clock phandles.  If specified, this should list one
+      clock.
+  clock-names -- the "local" names of the clocks specified in 'clocks'.  Note
+      that if the 'clocks' property is given, 'clock-names' is mandatory,
+      and the name of the clock is expected to be "sw_pcie".
+  brcm,ssc -- (boolean) indicates usage of spread-spectrum clocking.
+  brcm,gen --  (integer) indicates desired generation of link:
+      1 => 2.5 Gbps, 2 => 5.0 Gbps, 3 => 8.0 Gbps.
+  supply-names -- the names of voltage regulators that the root
+      complex should turn off/on/on on suspend/resume/boot.  This
+      is a string list.
+  supplies -- A collection of phandles to a regulator nodes, see
+	Documentation/devicetree/bindings/regulator/ for specific
+	bindings. The number and order of phandles must match
+	exactly the number of strings in the "supply-names" property.
+
+Example Node:
+
+	pcie at f0460000 {
+		reg = <0x0 0xf0460000 0x0 0x9310>;
+		interrupts = <0x0 0x0 0x4>;
+		compatible = "brcm,pci-plat-dev";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		ranges = <0x02000000 0x00000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x08000000
+			  0x02000000 0x00000000 0x08000000 0x00000000 0xc8000000 0x00000000 0x08000000>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0 0 0 1 &intc 47 3
+				 0 0 0 2 &intc 48 3
+				 0 0 0 3 &intc 49 3
+				 0 0 0 4 &intc 50 3>;
+		interrupt-names = "pcie_0_inta",
+				  "pcie_0_intb",
+				  "pcie_0_intc",
+				  "pcie_0_intd";
+		clocks = <&sw_pcie0>;
+		clock-names = "sw_pcie";
+		brcm,ssc;
+		brcm,gen = <1>;
+		supply-names = "vreg-wifi-pwr";
+		supplies = <&vreg-wifi-pwr>;
+
+	};
-- 
2.1.0



From f.fainelli at gmail.com  Mon May  2 18:25:49 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Mon,  2 May 2016 18:25:49 -0700
Subject: [PATCH 2/2] pci: host: Add Broadcom STB PCIE RC controller
In-Reply-To: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>
References: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1462238749-19715-3-git-send-email-f.fainelli@gmail.com>

From: Jim Quinlan <jim2101024 at gmail.com>

This patch adds support for Broadcom's STB SoC PCIE root complex
controller. This controller can be found in MIPS-based chips such as
BCM7425, 7429 and 7435 and ARM-based SoCs such as BCM7445.

This driver enables support for MSI, regulators that need to be turned
on prior to scanning the bus, and S2/S3 suspend/resume modes.

Signed-off-by: Jim Quinlan <jim2101024 at gmail.com>
Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
 MAINTAINERS                     |    1 +
 drivers/pci/host/Kconfig        |    9 +
 drivers/pci/host/Makefile       |    1 +
 drivers/pci/host/pcie-brcmstb.c | 1243 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 1254 insertions(+)
 create mode 100644 drivers/pci/host/pcie-brcmstb.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 42e65d128d01..0450874b5623 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2458,6 +2458,7 @@ S:	Maintained
 F:	arch/arm/mach-bcm/*brcmstb*
 F:	arch/arm/boot/dts/bcm7*.dts*
 F:	drivers/bus/brcmstb_gisb.c
+F:	drivers/pci/host/pcie-brcmstb.c
 N:	brcmstb
 
 BROADCOM BMIPS MIPS ARCHITECTURE
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 7a0780d56d2d..2345c753bddf 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -143,6 +143,15 @@ config PCI_VERSATILE
 	bool "ARM Versatile PB PCI controller"
 	depends on ARCH_VERSATILE
 
+config PCIE_BRCMSTB
+	tristate "Broadcom STB PCIe controller"
+	depends on OF && (ARCH_BRCMSTB || BMIPS_GENERIC)
+	default ARCH_BRCMSTB || BMIPS_GENERIC
+	help
+	  Say Y here if you want to use the Broadcom STB PCIe controller. This
+	  controller supports Broadcom's STB SoCs such a 7425, 7429, 7435 and
+	  7445 and compatible chips.
+
 config PCIE_IPROC
 	tristate
 	help
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index d85b5faf9bbc..8c0df3d63b5d 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
 obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
 obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
 obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
+obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
 obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
 obj-$(CONFIG_PCIE_IPROC_MSI) += pcie-iproc-msi.o
 obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
diff --git a/drivers/pci/host/pcie-brcmstb.c b/drivers/pci/host/pcie-brcmstb.c
new file mode 100644
index 000000000000..cbdb96f4d849
--- /dev/null
+++ b/drivers/pci/host/pcie-brcmstb.c
@@ -0,0 +1,1243 @@
+/*
+ * Broadcom STB PCIe root complex driver
+ *
+ * Copyright (C) 2009 - 2016 Broadcom
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/msi.h>
+#include <linux/printk.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/module.h>
+#include <linux/irqdomain.h>
+#include <linux/regulator/consumer.h>
+#include <linux/string.h>
+#include <linux/sizes.h>
+
+/* Broadcom PCIE Offsets */
+#define PCIE_RC_CFG_PCIE_LINK_CAPABILITY		0x00b8
+#define PCIE_RC_CFG_PCIE_LINK_STATUS_CONTROL		0x00bc
+#define PCIE_RC_CFG_PCIE_ROOT_CAP_CONTROL		0x00c8
+#define PCIE_RC_CFG_PCIE_LINK_STATUS_CONTROL_2		0x00dc
+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1		0x0188
+#define PCIE_RC_CFG_PRIV1_ID_VAL3			0x043c
+#define PCIE_RC_DL_MDIO_ADDR				0x1100
+#define PCIE_RC_DL_MDIO_WR_DATA				0x1104
+#define PCIE_RC_DL_MDIO_RD_DATA				0x1108
+#define PCIE_MISC_MISC_CTRL				0x4008
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO		0x400c
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI		0x4010
+#define PCIE_MISC_RC_BAR1_CONFIG_LO			0x402c
+#define PCIE_MISC_RC_BAR1_CONFIG_HI			0x4030
+#define PCIE_MISC_RC_BAR2_CONFIG_LO			0x4034
+#define PCIE_MISC_RC_BAR2_CONFIG_HI			0x4038
+#define PCIE_MISC_RC_BAR3_CONFIG_LO			0x403c
+#define PCIE_MISC_RC_BAR3_CONFIG_HI			0x4040
+#define PCIE_MISC_MSI_BAR_CONFIG_LO			0x4044
+#define PCIE_MISC_MSI_BAR_CONFIG_HI			0x4048
+#define PCIE_MISC_MSI_DATA_CONFIG			0x404c
+#define PCIE_MISC_PCIE_CTRL				0x4064
+#define PCIE_MISC_PCIE_STATUS				0x4068
+#define PCIE_MISC_REVISION				0x406c
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT	0x4070
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG			0x4204
+#define PCIE_INTR2_CPU_BASE				0x4300
+#define PCIE_MSI_INTR2_BASE				0x4500
+#define BRCM_NUM_PCI_OUT_WINS		0x4
+#define BRCM_MAX_SCB			0x4
+#define BRCM_INT_PCI_MSI_NR		32
+#define BRCM_PCIE_HW_REV_33		0x0303
+#define BRCM_MSI_TARGET_ADDR_LO		0x0
+#define BRCM_MSI_TARGET_ADDR_HI		0xffffffff
+
+/* Offsets from PCIE_INTR2_CPU_BASE and PCIE_MSI_INTR2_BASE */
+#define STATUS				0x0
+#define SET				0x4
+#define CLR				0x8
+#define MASK_STATUS			0xc
+#define MASK_SET			0x10
+#define MASK_CLR			0x14
+
+#define PCI_BUSNUM_SHIFT		20
+#define PCI_SLOT_SHIFT			15
+#define PCI_FUNC_SHIFT			12
+
+/* Helper macros for reading registers varying from chip-to-chip */
+#define IDX_ADDR(pcie)			((pcie->base) + \
+					 pcie->reg_offsets[EXT_CFG_INDEX])
+#define DATA_ADDR(pcie)			((pcie->base) + \
+					 pcie->reg_offsets[EXT_CFG_DATA])
+#define PCIE_RGR1_SW_INIT_1(pcie)	((pcie->base) + \
+					 pcie->reg_offsets[RGR1_SW_INIT_1])
+
+enum {
+	RGR1_SW_INIT_1,
+	EXT_CFG_INDEX,
+	EXT_CFG_DATA,
+};
+
+enum pcie_type {
+	BCM7425,
+	BCM7435,
+	GENERIC,
+};
+
+struct pcie_cfg_data {
+	const int *offsets;
+	const enum pcie_type type;
+};
+
+static const int pcie_offset_bcm7425[] = {
+	[RGR1_SW_INIT_1] = 0x8010,
+	[EXT_CFG_INDEX]  = 0x8300,
+	[EXT_CFG_DATA]   = 0x8304,
+};
+
+static const struct pcie_cfg_data bcm7425_cfg = {
+	.offsets	= pcie_offset_bcm7425,
+	.type		= BCM7425,
+};
+
+static const int pcie_offsets[] = {
+	[RGR1_SW_INIT_1] = 0x9210,
+	[EXT_CFG_INDEX]  = 0x9000,
+	[EXT_CFG_DATA]   = 0x9004,
+};
+
+static const struct pcie_cfg_data bcm7435_cfg = {
+	.offsets	= pcie_offsets,
+	.type		= BCM7435,
+};
+
+static const struct pcie_cfg_data generic_cfg = {
+	.offsets	= pcie_offsets,
+	.type		= GENERIC,
+};
+
+struct brcm_msi {
+	struct irq_domain *domain;
+	struct irq_chip irq_chip;
+	struct msi_controller chip;
+	struct mutex lock;
+	int irq;
+	/* intr_base is the base pointer for interrupt status/set/clr regs */
+	void __iomem *intr_base;
+	/* intr_legacy_mask indicates how many bits are MSI interrupts */
+	u32 intr_legacy_mask;
+	/* intr_legacy_offset indicates bit position of MSI_01 */
+	u32 intr_legacy_offset;
+	/* used indicates which MSI interrupts have been alloc'd */
+	unsigned long used;
+	/* working indicates that on boot we have brought up MSI */
+	bool working;
+};
+
+struct brcm_window {
+	u64 size;
+	u64 cpu_addr;
+	struct resource pcie_iomem_res;
+};
+
+struct brcm_dev_pwr_supply {
+	struct list_head node;
+	char name[32];
+	struct regulator *regulator;
+};
+
+/* Internal Bus Controller Information.*/
+struct brcm_pcie {
+	struct list_head	list;
+	void __iomem		*base;
+	char			name[8];
+	bool			suspended;
+	struct clk		*clk;
+	struct device_node	*dn;
+	int			pcie_irq[4];
+	int			irq;
+	int			num_out_wins;
+	bool			ssc;
+	int			gen;
+	int			scb_size_vals[BRCM_MAX_SCB];
+	struct brcm_window	out_wins[BRCM_NUM_PCI_OUT_WINS];
+	struct pci_bus		*bus;
+	struct device		*dev;
+	struct list_head	resource;
+	struct list_head	pwr_supplies;
+	struct brcm_msi		msi;
+	unsigned int		rev;
+	unsigned int		num;
+	bool			bridge_setup_done;
+	const int		*reg_offsets;
+	enum pcie_type		type;
+};
+
+static int brcm_num_pci_controllers;
+static int num_memc;
+
+#if defined(__BIG_ENDIAN)
+#define	DATA_ENDIAN		2	/* PCI->DDR inbound accesses */
+#define MMIO_ENDIAN		2	/* CPU->PCI outbound accesses */
+#else
+#define	DATA_ENDIAN		0
+#define MMIO_ENDIAN		0
+#endif
+
+/*
+ * MIPS endianness is configured by boot strap, which also reverses all
+ * bus endianness (i.e., big-endian CPU + big endian bus ==> native
+ * endian I/O).
+ *
+ * Other architectures (e.g., ARM) either do not support big endian, or
+ * else leave I/O in little endian mode.
+ */
+static inline u32 bpcie_readl(void __iomem *base)
+{
+	if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
+		return __raw_readl(base);
+	else
+		return readl_relaxed(base);
+}
+
+static inline void bpcie_writel(u32 val, void __iomem *base)
+{
+	if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
+		__raw_writel(val, base);
+	else
+		writel_relaxed(val, base);
+}
+
+/* negative return value indicates error */
+static int mdio_read(void __iomem *base, u8 phyad, u8 regad)
+{
+	u32 data = ((phyad & 0xf) << 16)
+		| (regad & 0x1f)
+		| 0x100000;
+
+	bpcie_writel(data, base + PCIE_RC_DL_MDIO_ADDR);
+	bpcie_readl(base + PCIE_RC_DL_MDIO_ADDR);
+
+	data = bpcie_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
+	if (!(data & 0x80000000)) {
+		mdelay(1);
+		data = bpcie_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
+	}
+	return (data & 0x80000000) ? (data & 0xffff) : -EIO;
+}
+
+/* negative return value indicates error */
+static int mdio_write(void __iomem *base, u8 phyad, u8 regad, u16 wrdata)
+{
+	u32 data = ((phyad & 0xf) << 16) | (regad & 0x1f);
+
+	bpcie_writel(data, base + PCIE_RC_DL_MDIO_ADDR);
+	bpcie_readl(base + PCIE_RC_DL_MDIO_ADDR);
+
+	bpcie_writel(0x80000000 | wrdata, base + PCIE_RC_DL_MDIO_WR_DATA);
+	data = bpcie_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
+	if (!(data & 0x80000000)) {
+		mdelay(1);
+		data = bpcie_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
+	}
+	return (data & 0x80000000) ? 0 : -EIO;
+}
+
+
+static void wr_fld(void __iomem *p, u32 mask, int shift, u32 val)
+{
+	u32 reg;
+
+	reg = bpcie_readl(p);
+	reg = (reg & ~mask) | (val << shift);
+	bpcie_writel(reg, p);
+}
+
+static void wr_fld_rb(void __iomem *p, u32 mask, int shift, u32 val)
+{
+	wr_fld(p, mask, shift, val);
+	(void) bpcie_readl(p);
+}
+
+/* configures device for ssc mode; negative return value indicates error */
+static int set_ssc(void __iomem *base)
+{
+	int tmp;
+	u16 wrdata;
+
+	tmp = mdio_write(base, 0, 0x1f, 0x1100);
+	if (tmp < 0)
+		return tmp;
+
+	tmp = mdio_read(base, 0, 2);
+	if (tmp < 0)
+		return tmp;
+
+	wrdata = ((u16)tmp & 0x3fff) | 0xc000;
+	tmp = mdio_write(base, 0, 2, wrdata);
+	if (tmp < 0)
+		return tmp;
+
+	mdelay(1);
+	tmp = mdio_read(base, 0, 1);
+	if (tmp < 0)
+		return tmp;
+
+	return 0;
+}
+
+
+/* returns 0 if in ssc mode, 1 if not, <0 on error */
+static int is_ssc(void __iomem *base)
+{
+	int tmp = mdio_write(base, 0, 0x1f, 0x1100);
+
+	if (tmp < 0)
+		return tmp;
+	tmp = mdio_read(base, 0, 1);
+	if (tmp < 0)
+		return tmp;
+	return (tmp & 0xc00) == 0xc00 ? 0 : 1;
+}
+
+
+/* limits operation to a specific generation (1, 2, or 3) */
+static void set_gen(void __iomem *base, int gen)
+{
+	wr_fld(base + PCIE_RC_CFG_PCIE_LINK_CAPABILITY, 0xf, 0, gen);
+	wr_fld(base + PCIE_RC_CFG_PCIE_LINK_STATUS_CONTROL_2, 0xf, 0, gen);
+}
+
+
+static void set_pcie_outbound_win(void __iomem *base, unsigned int win,
+				  u64 start, u64 len)
+{
+	u32 tmp;
+
+	bpcie_writel((u32)(start) + MMIO_ENDIAN,
+		     base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO+(win*8));
+	bpcie_writel((u32)(start >> 32),
+		     base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI+(win*8));
+	tmp = ((((u32)start) >> 20) << 4)
+		| (((((u32)start) + ((u32)len) - 1) >> 20) << 20);
+	bpcie_writel(tmp,
+		     base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT+(win*4));
+}
+
+
+static int is_pcie_link_up(struct brcm_pcie *pcie)
+{
+	void __iomem *base = pcie->base;
+	u32 val = bpcie_readl(base + PCIE_MISC_PCIE_STATUS);
+
+	return  ((val & 0x30) == 0x30) ? 1 : 0;
+}
+
+
+static inline struct brcm_msi *to_brcm_msi(struct msi_controller *chip)
+{
+	return container_of(chip, struct brcm_msi, chip);
+}
+
+
+static int brcm_msi_alloc(struct brcm_msi *chip)
+{
+	int msi;
+
+	mutex_lock(&chip->lock);
+	msi = ~chip->used ? ffz(chip->used) : -1;
+
+	if (msi >= 0 && msi < BRCM_INT_PCI_MSI_NR)
+		chip->used |= (1 << msi);
+	else
+		msi = -ENOSPC;
+
+	mutex_unlock(&chip->lock);
+	return msi;
+}
+
+
+static void brcm_msi_free(struct brcm_msi *chip, unsigned long irq)
+{
+	mutex_lock(&chip->lock);
+	chip->used &= ~(1 << irq);
+	mutex_unlock(&chip->lock);
+}
+
+
+static irqreturn_t brcm_pcie_msi_irq(int irq, void *data)
+{
+	struct brcm_pcie *pcie = data;
+	struct brcm_msi *msi = &pcie->msi;
+	unsigned long status;
+
+	status = bpcie_readl(msi->intr_base + STATUS) & msi->intr_legacy_mask;
+
+	if (!status)
+		return IRQ_NONE;
+
+	while (status) {
+		unsigned int index = ffs(status) - 1;
+		unsigned int irq;
+
+		/* clear the interrupt */
+		bpcie_writel(1 << index, msi->intr_base + CLR);
+		status &= ~(1 << index);
+
+		/* Account for legacy interrupt offset */
+		index -= msi->intr_legacy_offset;
+
+		irq = irq_find_mapping(msi->domain, index);
+		if (irq) {
+			if (msi->used & (1 << index))
+				generic_handle_irq(irq);
+			else
+				dev_info(pcie->dev, "unhandled MSI %d\n",
+					 index);
+		} else {
+			/* Unknown MSI, just clear it */
+			dev_dbg(pcie->dev, "unexpected MSI\n");
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+
+static int brcm_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
+			      struct msi_desc *desc)
+{
+	struct brcm_msi *msi = to_brcm_msi(chip);
+	struct brcm_pcie *pcie = container_of(chip, struct brcm_pcie, msi.chip);
+	struct msi_msg msg;
+	unsigned int irq;
+	int hwirq;
+	u32 data;
+
+	hwirq = brcm_msi_alloc(msi);
+	if (hwirq < 0)
+		return hwirq;
+
+	irq = irq_create_mapping(msi->domain, hwirq);
+	if (!irq) {
+		brcm_msi_free(msi, hwirq);
+		return -EINVAL;
+	}
+
+	irq_set_msi_desc(irq, desc);
+
+	msg.address_lo = BRCM_MSI_TARGET_ADDR_LO;
+	msg.address_hi = BRCM_MSI_TARGET_ADDR_HI;
+	data = bpcie_readl(pcie->base + PCIE_MISC_MSI_DATA_CONFIG);
+	msg.data = ((data >> 16) & (data & 0xffff)) | hwirq;
+	wmb(); /* just being cautious */
+	write_msi_msg(irq, &msg);
+
+	return 0;
+}
+
+
+static void brcm_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
+{
+	struct brcm_msi *msi = to_brcm_msi(chip);
+	struct irq_data *d = irq_get_irq_data(irq);
+
+	brcm_msi_free(msi, d->hwirq);
+}
+
+
+static int brcm_msi_map(struct irq_domain *domain, unsigned int irq,
+			irq_hw_number_t hwirq)
+{
+	struct brcm_pcie *pcie = domain->host_data;
+
+	irq_set_chip_and_handler(irq, &pcie->msi.irq_chip, handle_simple_irq);
+	irq_set_chip_data(irq, domain->host_data);
+
+	return 0;
+}
+
+static const struct irq_domain_ops msi_domain_ops = {
+	.map = brcm_msi_map,
+};
+
+static int brcm_pcie_enable_msi(struct brcm_pcie *pcie, int nr)
+{
+	static const char brcm_msi_name[] = "brcmstb_pcieX_msi";
+	struct brcm_msi *msi = &pcie->msi;
+	u32 data_val;
+	char *name;
+	int err;
+
+	if (!pcie->suspended) {
+		/* We are only here on cold boot */
+		mutex_init(&msi->lock);
+
+		msi->chip.dev = pcie->dev;
+		msi->chip.setup_irq = brcm_msi_setup_irq;
+		msi->chip.teardown_irq = brcm_msi_teardown_irq;
+
+		/* We have multiple RC controllers.  We may have as many
+		 * MSI controllers for them.  We want each to have a
+		 * unique name, so we go to the trouble of having an
+		 * irq_chip per RC (instead of one for all of them).
+		 */
+		name = devm_kzalloc(pcie->dev, sizeof(brcm_msi_name),
+				    GFP_KERNEL);
+		if (name) {
+			char *p;
+
+			strcpy(name, brcm_msi_name);
+			p = strchr(name, 'X');
+			if (p)
+				*p = '0' + nr;
+			msi->irq_chip.name = name;
+		} else {
+			msi->irq_chip.name = brcm_msi_name;
+		}
+
+		msi->irq_chip.irq_enable = unmask_msi_irq;
+		msi->irq_chip.irq_disable = mask_msi_irq;
+		msi->irq_chip.irq_mask = mask_msi_irq;
+		msi->irq_chip.irq_unmask = unmask_msi_irq;
+
+		msi->domain =
+			irq_domain_add_linear(pcie->dn, BRCM_INT_PCI_MSI_NR,
+					      &msi_domain_ops, pcie);
+		if (!msi->domain) {
+			dev_err(pcie->dev,
+				"failed to create IRQ domain for MSI\n");
+			return -ENOMEM;
+		}
+
+		err = devm_request_irq(pcie->dev, msi->irq, brcm_pcie_msi_irq,
+				       IRQF_SHARED, msi->irq_chip.name,
+				       pcie);
+
+		if (err < 0) {
+			dev_err(pcie->dev,
+				"failed to request IRQ (%d) for MSI\n",	err);
+			goto msi_en_err;
+		}
+
+		if (pcie->rev >= BRCM_PCIE_HW_REV_33) {
+			msi->intr_base = pcie->base + PCIE_MSI_INTR2_BASE;
+			/* This version of PCIe hw has only 32 intr bits
+			 * starting at bit position 0.
+			 */
+			msi->intr_legacy_mask = 0xffffffff;
+			msi->intr_legacy_offset = 0x0;
+			msi->used = 0x0;
+
+		} else {
+			msi->intr_base = pcie->base + PCIE_INTR2_CPU_BASE;
+			/* This version of PCIe hw has only 8 intr bits starting
+			 * at bit position 24.
+			 */
+			msi->intr_legacy_mask = 0xff000000;
+			msi->intr_legacy_offset = 24;
+			msi->used = 0xffffff00;
+		}
+		msi->working = true;
+	}
+
+	/* If we are here, and msi->working is false, it means that we've
+	 * already tried and failed to bring up MSI.  Just return 0
+	 * since there is nothing to be done.
+	 */
+	if (!msi->working)
+		return 0;
+
+	if (pcie->rev >= BRCM_PCIE_HW_REV_33) {
+		/* ffe0 -- least sig 5 bits are 0 indicating 32 msgs
+		 * 6540 -- this is our arbitrary unique data value
+		 */
+		data_val = 0xffe06540;
+	} else {
+		/* fff8 -- least sig 3 bits are 0 indicating 8 msgs
+		 * 6540 -- this is our arbitrary unique data value
+		 */
+		data_val = 0xfff86540;
+	}
+
+	/* Make sure we are not masking MSIs.  Note that MSIs can be masked,
+	 * but that occurs on the PCIe EP device
+	 */
+	bpcie_writel(0xffffffff & msi->intr_legacy_mask,
+		     msi->intr_base + MASK_CLR);
+
+	/* The 0 bit of BRCM_MSI_TARGET_ADDR_LO is repurposed to MSI enable,
+	 * which we set to 1.
+	 */
+	bpcie_writel(BRCM_MSI_TARGET_ADDR_LO | 1, pcie->base
+		     + PCIE_MISC_MSI_BAR_CONFIG_LO);
+	bpcie_writel(BRCM_MSI_TARGET_ADDR_HI, pcie->base
+		     + PCIE_MISC_MSI_BAR_CONFIG_HI);
+	bpcie_writel(data_val, pcie->base + PCIE_MISC_MSI_DATA_CONFIG);
+
+	return 0;
+
+msi_en_err:
+	irq_domain_remove(msi->domain);
+	return err;
+}
+
+
+static void brcm_pcie_setup_early(struct brcm_pcie *pcie)
+{
+	void __iomem *base = pcie->base;
+	unsigned int scb_size_val;
+	int i;
+
+	/* reset the bridge and the endpoint device
+	 * field: PCIE_BRIDGE_SW_INIT = 1
+	 */
+	wr_fld_rb(PCIE_RGR1_SW_INIT_1(pcie), 0x00000002, 1, 1);
+
+	/* field: PCIE_SW_PERST = 1 */
+	wr_fld_rb(PCIE_RGR1_SW_INIT_1(pcie), 0x00000001, 0, 1);
+
+	/* delay 100us */
+	udelay(100);
+
+	/* take the bridge out of reset
+	 * field: PCIE_BRIDGE_SW_INIT = 0
+	 */
+	wr_fld_rb(PCIE_RGR1_SW_INIT_1(pcie), 0x00000002, 1, 0);
+
+	/* Grab the PCIe hw revision number */
+	pcie->rev = bpcie_readl(base + PCIE_MISC_REVISION) & 0xffff;
+
+	/* enable SCB_MAX_BURST_SIZE | CSR_READ_UR_MODE | SCB_ACCESS_EN */
+	if (pcie->type == GENERIC)
+		bpcie_writel(0x81e03000, base + PCIE_MISC_MISC_CTRL);
+	else
+		bpcie_writel(0x00103000, base + PCIE_MISC_MISC_CTRL);
+
+	for (i = 0; i < pcie->num_out_wins; i++) {
+		struct brcm_window *w = &pcie->out_wins[i];
+
+		set_pcie_outbound_win(base, i, w->cpu_addr, w->size);
+	}
+
+	/* set up 4GB PCIE->SCB memory window on BAR2 */
+	bpcie_writel(0x00000011, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
+	bpcie_writel(0x00000000, base + PCIE_MISC_RC_BAR2_CONFIG_HI);
+
+	/* field: SCB0_SIZE, default = 0xf (1 GB) */
+	scb_size_val = pcie->scb_size_vals[0] ? pcie->scb_size_vals[0] : 0xf;
+	wr_fld(base + PCIE_MISC_MISC_CTRL, 0xf8000000, 27, scb_size_val);
+
+	/* field: SCB1_SIZE, default = 0xf (1 GB) */
+	if (num_memc > 1) {
+		scb_size_val = pcie->scb_size_vals[1]
+			? pcie->scb_size_vals[1] : 0xf;
+		wr_fld(base + PCIE_MISC_MISC_CTRL, 0x07c00000,
+		       22, scb_size_val);
+	}
+
+	/* field: SCB2_SIZE, default = 0xf (1 GB) */
+	if (num_memc > 2) {
+		scb_size_val = pcie->scb_size_vals[2]
+			? pcie->scb_size_vals[2] : 0xf;
+		wr_fld(base + PCIE_MISC_MISC_CTRL, 0x0000001f,
+		       0, scb_size_val);
+	}
+
+	/* disable the PCIE->GISB memory window */
+	bpcie_writel(0x00000000, base + PCIE_MISC_RC_BAR1_CONFIG_LO);
+
+	/* disable the PCIE->SCB memory window */
+	bpcie_writel(0x00000000, base + PCIE_MISC_RC_BAR3_CONFIG_LO);
+
+	if (!pcie->suspended) {
+		/* clear any interrupts we find on boot */
+		bpcie_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + CLR);
+		(void) bpcie_readl(base + PCIE_INTR2_CPU_BASE + CLR);
+	}
+
+	/* Mask all interrupts since we are not handling any yet */
+	bpcie_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + MASK_SET);
+	(void) bpcie_readl(base + PCIE_INTR2_CPU_BASE + MASK_SET);
+
+	if (pcie->ssc)
+		if (set_ssc(base))
+			dev_err(pcie->dev, "error while configuring ssc mode\n");
+	if (pcie->gen)
+		set_gen(base, pcie->gen);
+
+	/* take the EP device out of reset */
+	/* field: PCIE_SW_PERST = 0 */
+	wr_fld_rb(PCIE_RGR1_SW_INIT_1(pcie), 0x00000001, 0, 0);
+}
+
+static void brcm_pcie_turn_off(struct brcm_pcie *pcie)
+{
+	void __iomem *base = pcie->base;
+	/* Reset endpoint device */
+	wr_fld_rb(PCIE_RGR1_SW_INIT_1(pcie), 0x00000001, 0, 1);
+	/* deassert request for L23 in case it was asserted */
+	wr_fld_rb(base + PCIE_MISC_PCIE_CTRL, 0x1, 0, 0);
+	/* SERDES_IDDQ = 1 */
+	wr_fld_rb(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG, 0x08000000,
+		  27, 1);
+	/* Shutdown PCIe bridge */
+	wr_fld_rb(PCIE_RGR1_SW_INIT_1(pcie), 0x00000002, 1, 1);
+}
+
+static void brcm_pcie_enter_l23(struct brcm_pcie *pcie)
+{
+	void __iomem *base = pcie->base;
+	int timeout = 1000;
+	int l23;
+
+	/* assert request for L23 */
+	wr_fld_rb(base + PCIE_MISC_PCIE_CTRL, 0x1, 0, 1);
+	do {
+		/* poll L23 status */
+		l23 = bpcie_readl(base + PCIE_MISC_PCIE_STATUS) & (1 << 6);
+	} while (--timeout && !l23);
+
+	if (!timeout)
+		dev_err(pcie->dev, "failed to enter L23\n");
+}
+
+static int brcm_setup_pcie_bridge(struct brcm_pcie *pcie)
+{
+	static const char *link_speed[4] = { "???", "2.5", "5.0", "8.0" };
+	void __iomem *base = pcie->base;
+	const int limit = pcie->suspended ? 1000 : 100;
+	struct clk *clk;
+	unsigned int status;
+	int i, j, ret;
+	bool ssc_good = false;
+
+	/* Give the RC/EP time to wake up, before trying to configure RC.
+	 * Intermittently check status for link-up, up to a total of 100ms
+	 * when we don't know if the device is there, and up to 1000ms if
+	 * we do know the device is there.
+	 */
+	for (i = 1, j = 0; j < limit && !is_pcie_link_up(pcie); j += i, i = i*2)
+		mdelay(i + j > limit ? limit - j : i);
+
+	if (!is_pcie_link_up(pcie)) {
+		dev_info(pcie->dev, "link down\n");
+		goto fail;
+	}
+
+	/* Attempt to enable MSI if we have an interrupt for it. */
+	if (pcie->msi.irq > 0) {
+		ret = brcm_pcie_enable_msi(pcie, pcie->num);
+		if (ret < 0) {
+			dev_err(pcie->dev, "failed to enable MSI support: %d\n",
+				ret);
+		}
+	}
+
+	/* For config space accesses on the RC, show the right class for
+	 * a PCI-PCI bridge
+	 */
+	wr_fld_rb(base + PCIE_RC_CFG_PRIV1_ID_VAL3, 0x00ffffff, 0, 0x060400);
+
+	status = bpcie_readl(base + PCIE_RC_CFG_PCIE_LINK_STATUS_CONTROL);
+
+	if (pcie->ssc) {
+		if (is_ssc(base) == 0)
+			ssc_good = true;
+		else
+			dev_err(pcie->dev, "failed to enter SSC mode\n");
+	}
+
+	dev_info(pcie->dev, "link up, %s Gbps x%u %s\n",
+		 link_speed[((status & 0x000f0000) >> 16) & 0x3],
+		 (status & 0x03f00000) >> 20, ssc_good ? "(SSC)" : "(!SSC)");
+
+	/* Enable configuration request retry (see pci_scan_device()) */
+	/* field RC_CRS_EN = 1
+	 */
+	wr_fld(base + PCIE_RC_CFG_PCIE_ROOT_CAP_CONTROL, 0x00000010, 4, 1);
+
+	/* PCIE->SCB endian mode for BAR ield ENDIAN_MODE_BAR2 = DATA_ENDIAN
+	 */
+	wr_fld_rb(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1, 0x0000000c, 2,
+		  DATA_ENDIAN);
+
+	/* Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1
+	 * is enabled =>  setting the CLKREQ_DEBUG_ENABLE field to 1.
+	 */
+	wr_fld_rb(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG, 0x00000002, 1, 1);
+
+	/* Add bogus IO resource structure so that pcibios_init_resources()
+	 * does not allocate the same IO region for different domains
+	 */
+
+	pcie->bridge_setup_done = true;
+
+	return 0;
+fail:
+	if (IS_ENABLED(CONFIG_PM))
+		brcm_pcie_turn_off(pcie);
+
+	clk = pcie->clk;
+	if (pcie->suspended)
+		clk_disable(clk);
+	else {
+		clk_disable_unprepare(clk);
+		clk_put(clk);
+	}
+
+	pcie->bridge_setup_done = false;
+
+	return -ENODEV;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int brcm_pcie_suspend(struct device *dev)
+{
+	struct brcm_pcie *pcie = dev_get_drvdata(dev);
+	struct brcm_dev_pwr_supply *supply;
+	struct list_head *pos;
+	int ret;
+
+	if (!pcie->bridge_setup_done)
+		return 0;
+
+	brcm_pcie_enter_l23(pcie);
+	brcm_pcie_turn_off(pcie);
+	clk_disable(pcie->clk);
+	list_for_each(pos, &pcie->pwr_supplies) {
+		supply = list_entry(pos, struct brcm_dev_pwr_supply,
+				    node);
+
+		ret = regulator_disable(supply->regulator);
+		if (ret)
+			dev_dbg(dev, "Unable to turn off %s supply\n",
+				supply->name);
+
+	}
+	pcie->suspended = true;
+
+	return 0;
+}
+
+static int brcm_pcie_resume(struct device *dev)
+{
+	struct brcm_pcie *pcie = dev_get_drvdata(dev);
+	struct brcm_dev_pwr_supply *supply;
+	struct list_head *pos;
+	void __iomem *base;
+	int ret;
+
+	if (!pcie->bridge_setup_done)
+		return 0;
+
+	base = pcie->base;
+	list_for_each(pos, &pcie->pwr_supplies) {
+		supply = list_entry(pos, struct brcm_dev_pwr_supply,
+				    node);
+		ret = regulator_enable(supply->regulator);
+		if (ret)
+			dev_dbg(dev, "Unable to turn on %s supply\n",
+				supply->name);
+	}
+	clk_enable(pcie->clk);
+
+	/* Take bridge out of reset so we can access the SERDES reg */
+	wr_fld_rb(PCIE_RGR1_SW_INIT_1(pcie), 0x00000002, 1, 0);
+
+	/* SERDES_IDDQ = 0 */
+	wr_fld_rb(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG, 0x08000000,
+		  27, 0);
+	/* wait for serdes to be stable */
+	udelay(100);
+
+	brcm_pcie_setup_early(pcie);
+
+	brcm_setup_pcie_bridge(pcie);
+	pcie->suspended = false;
+
+	return 0;
+}
+
+static const struct dev_pm_ops brcm_pcie_pm_ops = {
+	.suspend_noirq = brcm_pcie_suspend,
+	.resume_noirq = brcm_pcie_resume,
+};
+#else
+#define brcm_pcie_pm_ops	NULL
+#endif /* CONFIG_PM_SLEEP */
+
+static int cfg_index(int busnr, int devfn, int reg)
+{
+	return ((PCI_SLOT(devfn) & 0x1f) << PCI_SLOT_SHIFT)
+		| ((PCI_FUNC(devfn) & 0x07) << PCI_FUNC_SHIFT)
+		| (busnr << PCI_BUSNUM_SHIFT)
+		| (reg & ~3);
+}
+
+static u32 read_config(struct brcm_pcie *pcie, int cfg_idx)
+{
+	bpcie_writel(cfg_idx, IDX_ADDR(pcie));
+	bpcie_readl(IDX_ADDR(pcie));
+	return bpcie_readl(DATA_ADDR(pcie));
+}
+
+static void write_config(struct brcm_pcie *pcie, int cfg_idx, u32 val)
+{
+	bpcie_writel(cfg_idx, IDX_ADDR(pcie));
+	bpcie_readl(IDX_ADDR(pcie));
+	bpcie_writel(val, DATA_ADDR(pcie));
+	bpcie_readl(DATA_ADDR(pcie));
+}
+
+static int brcm_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
+				  int where, int size, u32 data)
+{
+	struct brcm_pcie *pcie = bus->sysdata;
+	u32 val = 0, mask, shift;
+	void __iomem *base;
+	bool rc_access;
+	int idx;
+
+	if (!is_pcie_link_up(pcie))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	base = pcie->base;
+
+	rc_access = !!pci_is_root_bus(bus);
+
+	idx = cfg_index(bus->number, devfn, where);
+	WARN_ON(((where & 3) + size) > 4);
+
+	if (rc_access && PCI_SLOT(devfn))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (size < 4) {
+		/* partial word - read, modify, write */
+		if (rc_access)
+			val = bpcie_readl(base + (where & ~3));
+		else
+			val = read_config(pcie, idx);
+	}
+
+	shift = (where & 3) << 3;
+	mask = (0xffffffff >> ((4 - size) << 3)) << shift;
+	val = (val & ~mask) | ((data << shift) & mask);
+
+	if (rc_access) {
+		bpcie_writel(val, base + (where & ~3));
+		bpcie_readl(base + (where & ~3));
+	} else {
+		write_config(pcie, idx, val);
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int brcm_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 *data)
+{
+	struct brcm_pcie *pcie = bus->sysdata;
+	u32 val, mask, shift;
+	void __iomem *base;
+	bool rc_access;
+	int idx;
+
+	if (!is_pcie_link_up(pcie))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	base = pcie->base;
+
+	rc_access = !!pci_is_root_bus(bus);
+	idx = cfg_index(bus->number, devfn, where);
+	WARN_ON(((where & 3) + size) > 4);
+
+	if (rc_access && PCI_SLOT(devfn)) {
+		*data = 0xffffffff;
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+
+	if (rc_access)
+		val = bpcie_readl(base + (where & ~3));
+	else
+		val = read_config(pcie, idx);
+
+	shift = (where & 3) << 3;
+	mask = (0xffffffff >> ((4 - size) << 3)) << shift;
+	*data = (val & mask) >> shift;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static const struct of_device_id brcm_pcie_match[] = {
+	{ .compatible = "brcm,bcm7425-pcie", .data = &bcm7425_cfg },
+	{ .compatible = "brcm,bcm7435-pcie", .data = &bcm7435_cfg },
+	{ .compatible = "brcm,bcm7445-pcie", .data = &generic_cfg },
+	{},
+};
+MODULE_DEVICE_TABLE(of, brcm_pcie_match);
+
+static struct pci_ops brcm_pcie_ops = {
+	.read = brcm_pcie_read_config,
+	.write = brcm_pcie_write_config,
+};
+
+static int brcm_pcie_probe(struct platform_device *pdev)
+{
+	struct device_node *dn = pdev->dev.of_node, *mdn;
+	const u32 *log2_scb_sizes, *dma_ranges;
+	struct brcm_dev_pwr_supply *supply;
+	const struct of_device_id *of_id;
+	const struct pcie_cfg_data *data;
+	struct resource_entry *win;
+	struct brcm_pcie *pcie;
+	struct list_head *pos;
+	void __iomem *base;
+	int i, rlen, ret;
+	struct resource *r;
+	const char *name;
+	int supplies;
+	LIST_HEAD(res);
+	u32 tmp;
+
+	pcie = devm_kzalloc(&pdev->dev, sizeof(struct brcm_pcie), GFP_KERNEL);
+	if (!pcie)
+		return -ENOMEM;
+
+	of_id = of_match_node(brcm_pcie_match, dn);
+	if (!of_id)
+		return -EINVAL;
+
+	data = of_id->data;
+	pcie->reg_offsets = data->offsets;
+	pcie->type = data->type;
+
+	platform_set_drvdata(pdev, pcie);
+
+	INIT_LIST_HEAD(&pcie->pwr_supplies);
+	INIT_LIST_HEAD(&pcie->resource);
+
+	supplies = of_property_count_strings(dn, "supply-names");
+	if (supplies <= 0)
+		supplies = 0;
+
+	for (i = 0; i < supplies; i++) {
+		if (of_property_read_string_index(dn, "supply-names", i,
+						  &name))
+			continue;
+		supply = devm_kzalloc(&pdev->dev, sizeof(*supply), GFP_KERNEL);
+		if (!supply)
+			return -ENOMEM;
+
+		strncpy(supply->name, name, sizeof(supply->name));
+		supply->name[sizeof(supply->name) - 1] = '\0';
+		supply->regulator = devm_regulator_get(&pdev->dev, name);
+		if (IS_ERR(supply->regulator)) {
+			dev_err(&pdev->dev, "Unable to get %s supply, err=%d\n",
+				name, (int)PTR_ERR(supply->regulator));
+			continue;
+		}
+
+		if (regulator_enable(supply->regulator))
+			dev_err(&pdev->dev, "Unable to enable %s supply.\n",
+				name);
+		list_add_tail(&supply->node, &pcie->pwr_supplies);
+	}
+
+	/* 'num_memc' will be set only by the first controller, and all
+	 * other controllers will use the value set by the first.
+	 */
+	if (num_memc == 0)
+		for_each_compatible_node(mdn, NULL, "brcm,brcmstb-memc")
+			if (of_device_is_available(mdn))
+				num_memc++;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -EINVAL;
+
+	base = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	snprintf(pcie->name,
+		 sizeof(pcie->name)-1, "PCIe%d", brcm_num_pci_controllers);
+	pcie->num = brcm_num_pci_controllers;
+	pcie->suspended = false;
+	pcie->clk = devm_clk_get(&pdev->dev, "sw_pcie");
+	if (IS_ERR(pcie->clk)) {
+		dev_err(&pdev->dev, "could not get clock\n");
+		pcie->clk = NULL;
+	}
+	ret = clk_prepare_enable(pcie->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "could not enable clock\n");
+		return ret;
+	}
+	pcie->dn = dn;
+	pcie->base = base;
+	pcie->dev = &pdev->dev;
+	pcie->dev->of_node = dn;
+	pcie->gen = 0;
+
+	ret = of_property_read_u32(dn, "brcm,gen", &tmp);
+	if (ret == 0) {
+		if (tmp > 0 && tmp < 3)
+			pcie->gen = (int) tmp;
+		else
+			dev_warn(pcie->dev, "bad DT value for prop 'brcm,gen");
+	} else if (ret != -EINVAL) {
+		dev_warn(pcie->dev, "error reading DT prop 'brcm,gen");
+	}
+
+	pcie->ssc = of_property_read_bool(dn, "brcm,ssc");
+
+	/* Get the value for the log2 of the scb sizes.  Subtract 15 from
+	 * each because the target register field has 0==disabled and 1==64KB.
+	 */
+	log2_scb_sizes = of_get_property(dn, "brcm,log2-scb-sizes", &rlen);
+	if (log2_scb_sizes != NULL)
+		for (i = 0; i < rlen/4; i++)
+			pcie->scb_size_vals[i]
+				= (int) of_read_number(log2_scb_sizes + i, 1)
+					- 15;
+
+	/* Look for the dma-ranges property.  If it exists, issue a warning
+	 * as PCIe drivers may not work.  This is because the identity
+	 * mapping between system memory and PCIe space is not preserved,
+	 * and we need Linux to massage the dma_addr_t values it gets
+	 * from dma memory allocation.  This functionality will be added
+	 * in the near future.
+	 */
+	dma_ranges = of_get_property(dn, "dma-ranges", &rlen);
+	if (dma_ranges != NULL)
+		dev_warn(pcie->dev, "no identity map; PCI drivers may fail");
+
+	pcie->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+
+	if (IS_ENABLED(CONFIG_PCI_MSI)) {
+		ret = irq_of_parse_and_map(pdev->dev.of_node, 1);
+		if (ret == 0)
+			dev_warn(pcie->dev, "cannot get msi intr; MSI disabled\n");
+		else
+			pcie->msi.irq = ret;
+	}
+
+	ret = of_pci_get_host_bridge_resources(dn, 0, 0xff, &res, NULL);
+	if (ret) {
+		dev_err(pcie->dev, "ranges parsing failed\n");
+		return ret;
+	}
+
+	i = 0;
+	resource_list_for_each_entry(win, &res) {
+		struct brcm_window *w = &pcie->out_wins[i];
+
+		r = win->res;
+
+		if (!r->flags)
+			continue;
+
+		switch (resource_type(r)) {
+		case IORESOURCE_MEM:
+			w->cpu_addr = r->start;
+			w->size = resource_size(r);
+			w->pcie_iomem_res.name  = "External PCIe MEM";
+			w->pcie_iomem_res.flags = r->flags;
+			w->pcie_iomem_res.start = r->start;
+			w->pcie_iomem_res.end   = r->end;
+			pcie->num_out_wins++;
+			i++;
+			/* Request memory region resources. */
+			ret = devm_request_resource(&pdev->dev,
+						    &iomem_resource,
+						    &w->pcie_iomem_res);
+			if (ret) {
+				dev_err(&pdev->dev,
+					"request PCIe memory resource failed\n");
+				goto out_err_clk;
+			}
+			break;
+
+		default:
+			continue;
+		}
+	}
+
+	brcm_pcie_setup_early(pcie);
+
+	ret = brcm_setup_pcie_bridge(pcie);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup PCIe bridge\n");
+		/* If setup bridge fails, it cleans up behind itself */
+		goto out_err;
+	}
+
+	pcie->bus = pci_scan_root_bus(pcie->dev, pcie->num, &brcm_pcie_ops,
+				      pcie, &res);
+	if (!pcie->bus) {
+		ret = -ENOMEM;
+		goto out_err_bus;
+	}
+
+	if (IS_ENABLED(CONFIG_PCI_MSI))
+		pcie->bus->msi = &pcie->msi.chip;
+	pci_bus_size_bridges(pcie->bus);
+	pci_bus_assign_resources(pcie->bus);
+
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+	pci_bus_add_devices(pcie->bus);
+
+	brcm_num_pci_controllers++;
+
+	return 0;
+
+out_err_bus:
+	brcm_pcie_enter_l23(pcie);
+	brcm_pcie_turn_off(pcie);
+out_err_clk:
+	clk_disable_unprepare(pcie->clk);
+	list_for_each(pos, &pcie->pwr_supplies) {
+		supply = list_entry(pos, struct brcm_dev_pwr_supply,
+				    node);
+		regulator_disable(supply->regulator);
+
+	}
+out_err:
+	return ret;
+}
+
+static int brcm_pcie_remove(struct platform_device *pdev)
+{
+	return brcm_pcie_suspend(&pdev->dev);
+}
+
+static struct platform_driver brcm_pcie_driver = {
+	.probe = brcm_pcie_probe,
+	.remove = brcm_pcie_remove,
+	.driver = {
+		.name = "brcm-pcie",
+		.owner = THIS_MODULE,
+		.of_match_table = brcm_pcie_match,
+		.pm = &brcm_pcie_pm_ops,
+	},
+};
+module_platform_driver(brcm_pcie_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Broadcom STB PCIE RC driver");
+MODULE_AUTHOR("Broadcom");
-- 
2.1.0



From cw00.choi at samsung.com  Mon May  2 19:17:45 2016
From: cw00.choi at samsung.com (Chanwoo Choi)
Date: Tue, 03 May 2016 11:17:45 +0900
Subject: Fwd: [PATCH v2 0/8] PM / devfreq: Add NoCP devfreq-event and
 support busfreq on exyno5422-odroidxu3
In-Reply-To: <1894783822.297231462168123817.JavaMail.weblogic@ep2mlwas04a>
References: <1894783822.297231462168123817.JavaMail.weblogic@ep2mlwas04a>
Message-ID: <57280A49.6060609@samsung.com>

Dear Myungjoo,

On 2016? 05? 02? 14:48, MyungJoo Ham wrote:
> Sender : ???<cw00.choi at samsung.com> S5(??)/Change Agent/Tizen Platform Lab(S/W??)/????
> Date : 2016-04-15 15:32 (GMT+09:00)
>>
>> This patchset support the AMBA bus frequency scaling on Exynos5422-based
>> Odroid-XU3 board. But, this series only support the bus frequency scaling
>> for INT (Internal) block using VDD_INT power line.
> 
> Along with Devfreq/Passive patchset, the patchset is merged in
> devfreq for-4.7 tree.
> 
> https://git.kernel.org/cgit/linux/kernel/git/mzx/devfreq.git/log/?h=for-4.7
> 
> @Chanwoo: If there are commits to be merged by a tree other than Linux/PM,
> please let me know. I'll send out pull-request soon.

On Krzysztof Kozlowski's reply, dts patches will be merged on samsung-soc tree.
and then the clock patches about exynos5420 was already merged to samsung-clk tree
by Sylwester.

Only devfreq patches should be merged on devfreq tree.

We already discussed this topic on offline. I expect that you will again handle
this patchset according to reply of both Krzysztof and me.

Best Regards,
Chanwoo Choi

> 
> 
> Cheers,
> MyungJoo
> 
>>
>> Also, to support the bus frequency scaling for Exynos542x SoC,
>> Exynos542x SoC has the specific 'NoC (Network on Chip) Probe' device
>> to measure the transfered data traffic on NoC (Network on Chip)
>> instead of PPMU (Platform Performance Monitoring Unit). NoC Probe device
>> provide the utilization for INT block of Exynos542x SoC.
>>
>> The generic exynos-bus frequency driver uses the 'NoC Probe' devfreq-event
>> device (drivers/devfreq/event/exynos-nocp.c) without any modification.
>> Just add the phandle of 'NoC Probe' dt node to bus dt node.
>>
>> Depend on:
>> This patchset depends on patch[1] which support the generic exynos-bus
>> frequency driver.
>> [1] http://www.spinics.net/lists/arm-kernel/msg495976.html
>> - [PATCH v9 00/20] PM / devferq: Add generic exynos bus frequency driver and new passive governor
>>
>>



From wxt at rock-chips.com  Mon May  2 19:23:50 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue,  3 May 2016 10:23:50 +0800
Subject: [PATCH] thermal: rockchip: use the usleep_range instead of udelay
Message-ID: <1462242230-20873-1-git-send-email-wxt@rock-chips.com>

Documentation/timers/timers-howto.txt recommends to use
usleep_range on delays > 10usec.
The usleep_range indeed reduces CPU load, since the udelay will busy wait
for enough loop cycles to achieve the desired delay.

Fixes commit b06c52db39fd ("thermal: rockchip:
handle the power sequence for tsadc controller").

Cc: Zhang Rui <rui.zhang at intel.com>
Cc: Eduardo Valentin <edubezval at gmail.com>
Cc: Heiko Stuebner <heiko at sntech.de>
Suggested-by: Eduardo Valentin <edubezval at gmail.com>
Signed-off-by: Caesar Wang <wxt at rock-chips.com>

---

 drivers/thermal/rockchip_thermal.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index 86a1ab0..5d491f1 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -547,10 +547,10 @@ static void rk_tsadcv3_initialize(struct regmap *grf, void __iomem *regs,
 		regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_TSEN_PD_ON);
 		mdelay(10);
 		regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_TSEN_PD_OFF);
-		udelay(100); /* The spec note says at least 15 us */
+		usleep_range(15, 100); /* The spec note says at least 15 us */
 		regmap_write(grf, GRF_SARADC_TESTBIT, GRF_SARADC_TESTBIT_ON);
 		regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_TESTBIT_H_ON);
-		udelay(200); /* The spec note says at least 90 us */
+		usleep_range(90, 200); /* The spec note says at least 90 us */
 	}
 
 	if (tshut_polarity == TSHUT_HIGH_ACTIVE)
-- 
1.9.1



From paul at pwsan.com  Mon May  2 19:24:22 2016
From: paul at pwsan.com (Paul Walmsley)
Date: Tue, 3 May 2016 02:24:22 +0000 (UTC)
Subject: OMAP baseline test results for v4.6-rc6
Message-ID: <alpine.DEB.2.02.1605030223440.22468@utopia.booyaka.com>


Here are some basic OMAP test results for Linux v4.6-rc6.
Logs and other details at:

    http://www.pwsan.com/omap/testlogs/test_v4.6-rc6/20160502170254/


Test summary
------------

Build: uImage:
    Pass ( 3/ 3): omap1_defconfig, omap1_defconfig_1510innovator_only,
		  omap1_defconfig_5912osk_only

Build: uImage+dtb:
    Pass (13/13): omap2plus_defconfig_am33xx_only/am335x-bone,
		  omap2plus_defconfig/omap4-panda,
		  omap2plus_defconfig/omap4-panda-es,
		  omap2plus_defconfig/omap4-var-stk-om44,
		  omap2plus_defconfig/omap3-evm-37xx,
		  omap2plus_defconfig_n800_only_a/omap2420-n800,
		  omap2plus_defconfig/omap2430-sdp,
		  omap2plus_defconfig/am3517-evm,
		  omap2plus_defconfig/omap3-beagle,
		  omap2plus_defconfig/omap3-beagle-xm,
		  omap2plus_defconfig/omap3-sbc-t3517,
		  omap2plus_defconfig/omap5-uevm,
		  omap2plus_defconfig/omap5-sbc-t54

Build: zImage:
    Pass (18/18): omap2plus_defconfig, omap2plus_defconfig_am33xx_only,
		  omap2plus_defconfig_n800_only_a,
		  omap2plus_defconfig_n800_multi_omap2xxx,
		  omap2plus_defconfig_2430sdp_only,
		  omap2plus_defconfig_cpupm, omap2plus_defconfig_no_pm,
		  omap2plus_defconfig_omap2_4_only,
		  omap2plus_defconfig_omap3_4_only,
		  omap2plus_defconfig_omap5_only,
		  omap2plus_defconfig_dra7xx_only,
		  omap2plus_defconfig_am43xx_only,
		  omap2plus_defconfig_ti81xx_only,
		  rmk_omap3430_ldp_oldconfig,
		  rmk_omap3430_ldp_allnoconfig,
		  rmk_omap4430_sdp_oldconfig,
		  rmk_omap4430_sdp_allnoconfig, multi_v7_defconfig

Build warnings from toolchain: uImage:
    (none)

Build warnings from toolchain: uImage+dtb:
    (none)

Build warnings from toolchain: zImage:
    FAIL ( 1/18): multi_v7_defconfig

Boot to userspace:
    FAIL ( 1/18): 2430sdp
    skip ( 3/18): 5912osk, 3517evm, 5430es2sbct54
    Pass (14/18): am335xbonelt, am437xsk, am335xbone, 4430es2panda,
		  4460pandaes, 4460varsomom, 37xxevm, 3530es3beagle,
		  3530es31beagle, 3730beaglexm, 3730es12beaglexm,
		  cmt3517, 5430es2uevm, 2420n800

Kernel warnings during boot to userspace:
    FAIL ( 2/18): 4430es2panda, cmt3517

PM: chip retention via suspend:
    FAIL ( 6/11): am335xbonelt, 4430es2panda, 4460varsomom, 37xxevm,
		  2430sdp, 5430es2uevm
    Pass ( 5/11): 4460pandaes, 3530es3beagle, 3530es31beagle,
		  3730beaglexm, 3730es12beaglexm

PM: chip retention via dynamic idle:
    FAIL ( 8/11): am335xbonelt, 4430es2panda, 4460varsomom, 37xxevm,
		  3530es3beagle, 3530es31beagle, 2430sdp, 5430es2uevm
    Pass ( 3/11): 4460pandaes, 3730beaglexm, 3730es12beaglexm

PM: chip off (except CORE, due to errata) via suspend:
    Pass ( 1/ 1): 3730beaglexm

PM: chip off (except CORE, due to errata) via dynamic idle:
    Pass ( 1/ 1): 3730beaglexm

PM: chip off via suspend:
    FAIL ( 2/ 4): 37xxevm, 3530es3beagle
    Pass ( 2/ 4): 3530es31beagle, 3730es12beaglexm

PM: chip off via dynamic idle:
    FAIL ( 3/ 4): 37xxevm, 3530es3beagle, 3530es31beagle
    Pass ( 1/ 4): 3730es12beaglexm

Kernel warnings during PM test:
    FAIL ( 1/18): 4430es2panda

Obsolete Kconfig symbols:
    FAIL ( 3/21): omap1_defconfig, omap2plus_defconfig,
		  multi_v7_defconfig


vmlinux object size
(delta in bytes from test_v4.6-rc5 (02da2d72174c61988eb4456b53f405e3ebdebce4)):
   text     data      bss    total  kernel
    +88        0        0      +88  omap1_defconfig
    +56        0        0      +56  omap1_defconfig_1510innovator_only
    +88        0        0      +88  omap1_defconfig_5912osk_only
   +168        0        0     +168  multi_v7_defconfig
   +268        0        0     +268  omap2plus_defconfig
   +360      +32        0     +392  omap2plus_defconfig_2430sdp_only
   +208        0        0     +208  omap2plus_defconfig_am33xx_only
   +204        0        0     +204  omap2plus_defconfig_am43xx_only
   +268    +4096        0    +4364  omap2plus_defconfig_cpupm
   +268        0        0     +268  omap2plus_defconfig_dra7xx_only
   +192      +64        0     +256  omap2plus_defconfig_n800_multi_omap2xxx
   +160        0        0     +160  omap2plus_defconfig_n800_only_a
   +260        0        0     +260  omap2plus_defconfig_no_pm
   +268        0        0     +268  omap2plus_defconfig_omap2_4_only
   +268        0        0     +268  omap2plus_defconfig_omap3_4_only
   +268        0        0     +268  omap2plus_defconfig_omap5_only
   +208        0        0     +208  omap2plus_defconfig_ti81xx_only
    -24        0      +24        0  rmk_omap3430_ldp_allnoconfig
   +128       +8        0     +136  rmk_omap3430_ldp_oldconfig
      0        0      +16      +16  rmk_omap4430_sdp_allnoconfig
   +128        0        0     +128  rmk_omap4430_sdp_oldconfig

Boot-time memory difference
(delta in bytes from test_v4.6-rc5 (02da2d72174c61988eb4456b53f405e3ebdebce4))
  avail  rsrvd   high  freed  board          kconfig
  (no differences)



From caesar.upstream at gmail.com  Mon May  2 19:27:26 2016
From: caesar.upstream at gmail.com (Caesar Wang)
Date: Tue, 3 May 2016 10:27:26 +0800
Subject: [PATCH 4/9] thermal: rockchip: handle the power sequence for
 tsadc controller
In-Reply-To: <20160428150432.GA20009@localhost.localdomain>
References: <1460950562-20652-1-git-send-email-wxt@rock-chips.com>
 <1460950562-20652-5-git-send-email-wxt@rock-chips.com>
 <20160427234818.GB2590@localhost.localdomain> <57216C65.5040501@gmail.com>
 <20160428150432.GA20009@localhost.localdomain>
Message-ID: <57280C8E.5080406@gmail.com>



? 2016?04?28? 23:04, Eduardo Valentin ??:
> On Thu, Apr 28, 2016 at 09:50:29AM +0800, Caesar Wang wrote:
>>
>> ? 2016?04?28? 07:48, Eduardo Valentin ??:
>>> On Mon, Apr 18, 2016 at 11:35:56AM +0800, Caesar Wang wrote:
>>>> +		regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_TSEN_PD_ON);
>>>> +		mdelay(10);
>>>> +		regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_TSEN_PD_OFF);
>>>> +		udelay(100); /* The spec note says at least 15 us */
>>>> +		regmap_write(grf, GRF_SARADC_TESTBIT, GRF_SARADC_TESTBIT_ON);
>>>> +		regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_TESTBIT_H_ON);
>>>> +		udelay(200); /* The spec note says at least 90 us */
>>> Does it make sense to use usleep_range() instead?
>> I think so in the past, but I'm digging into the the udelay/usleep for
>> kernel.
> What do you mean by in the past? timekeeping doc still recommends the
> range 10us to 20ms for usleep_range()
>
>> In general,
>>
>> udelay < 10us ~100us
>> mdelay > 1m, <1000ms/HZ
>> usleep_range(min,max) > 100us, <20ms
> even here, your udelays could be replaced by usleep_range().
>
> Any particular reason you believe spining is better than sleeping in
> your case?
>
>> msleep > 20ms,  < 1000ms
>>
>> So the udelay is suit for tsadc power sequence.
>> ---
>>
>>
>> Also,  we have used the mdelay(10), so it doesn't matter if use the udelay.
>> After all the udelay is stable than the usleep_range.
> What do you mean udelay is stable than usleep_range? usleep_range will
> give the opportunity to the scheduler to coalesce wakeups. udelay is a
> busyloop spin. Besides, I am not sure the current situation, but
> busylooping may be affected by cpu frequency.

Okay, thanks for pointing out.

Send the fixes patch on https://patchwork.kernel.org/patch/8999971/

Thank you!


-Caesar
>
>> -Caesar
>>
>>> 1.9.1
>>>
>>>
>>>
>>>
>>> -- 
>>> Thanks,
>>> Caesar
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip


-- 
Thanks,
Caesar



From wens at csie.org  Mon May  2 20:33:09 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 3 May 2016 11:33:09 +0800
Subject: [PATCH 1/1] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
References: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
Message-ID: <CAGb2v66E2TuN3+tYaAbniV3q67waDZOfqKAW14VJz6xZFomZ=Q@mail.gmail.com>

Hi,

On Thu, Apr 28, 2016 at 3:19 PM, Olliver Schinagl <oliver at schinagl.nl> wrote:
> There are 3 kinds of OLinuXino Lime2 boards.
> One without any on board storage, one with NAND storage and one with
> eMMC storage. This patch adds the eMMC variant of boards.
>
> eMMC storage is different from a regular SD card in that it is soldered
> on the board and cannot be changed. Additionally, it shares pins with
> the NAND module and with the second SPI port.
>
> Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>
> ---
>  .../boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts    | 64 ++++++++++++++++++++++
>  1 file changed, 64 insertions(+)
>  create mode 100644 arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
>
> diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
> new file mode 100644
> index 0000000..689da36
> --- /dev/null
> +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
> @@ -0,0 +1,64 @@
> + /*
> + * Copyright 2015 - Ultimaker B.V.
> + * Author Olliver Schinagl <oliver at schinagl.nl>
> + *
> + * 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.
> + */
> +
> +#include "sun7i-a20-olinuxino-lime2.dts"
> +
> +/ {
> +       model = "Olimex A20-OLinuXino-LIME2-eMMC";
> +};
> +
> +&mmc2 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&mmc2_pins_a>;
> +       vmmc-supply = <&reg_vcc3v3>;
> +       bus-width = <4>;

Only 4 bits? We normally see eMMC with 8 bits. 4 bits are some kind of
embedded SD card.

> +       non-removable;
> +       no-1-8-v;

This flag is not supported on sunxi.

Instead, use the vqmmc-supply with the correct regulator and constraints.

ChenYu

> +       status = "okay";
> +
> +       emmc: emmc at 0 {
> +               reg = <0>;
> +               compatible = "mmc-card";
> +               broken-hpi;
> +       };
> +};
> --
> 2.8.0.rc3
>


From shawnguo at kernel.org  Mon May  2 20:33:54 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 11:33:54 +0800
Subject: [PATCH v4 2/2] ARM: dts: imx6ul-pico-hobbit: Add initial support
In-Reply-To: <1461729621-13283-2-git-send-email-festevam@gmail.com>
References: <1461729621-13283-1-git-send-email-festevam@gmail.com>
 <1461729621-13283-2-git-send-email-festevam@gmail.com>
Message-ID: <20160503033354.GA5874@tiger>

On Wed, Apr 27, 2016 at 01:00:21AM -0300, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam at nxp.com>
> 
> Add initial support for imx6ul pico hobbit board.
> 
> For information about this board, please visit:
> http://www.wandboard.org/images/hobbit/hobbitboard-imx6ul-reva1.pdf
> 
> Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>

Applied, thanks.


From sugar.zhang at rock-chips.com  Mon May  2 21:12:34 2016
From: sugar.zhang at rock-chips.com (sugar)
Date: Tue, 3 May 2016 12:12:34 +0800
Subject: [PATCH 1/2] ASoC: rockchip: i2s: separate capture and playback
In-Reply-To: <20160430070049.GF14612@serenity.lan>
References: <1449657147-26959-1-git-send-email-john@metanate.com>
 <CAFqH_52C4JKno4uyt54UdWKAJKM4FPGRiQaQQ9_H-Mz1Cr+Hqg@mail.gmail.com>
 <20160430070049.GF14612@serenity.lan>
Message-ID: <57282532.7000402@rock-chips.com>

Hi John,

On 4/30/2016 15:00, John Keeping Wrote:
> Hi Enric,
>
> On Fri, Apr 29, 2016 at 04:59:27PM +0200, Enric Balletbo Serra wrote:
>> 2015-12-09 11:32 GMT+01:00 John Keeping <john at metanate.com>:
>>> If we only clear the tx/rx state when both are disabled it is not
>>> possible to start/stop one multiple times while the other is running.
>>> Since the two are independently controlled, treat them as such and
>>> remove the false dependency between capture and playback.
>>>
>>> Signed-off-by: John Keeping <john at metanate.com>
>>> ---
>>>   sound/soc/rockchip/rockchip_i2s.c | 72 +++++++++++++++++----------------------
>>>   1 file changed, 32 insertions(+), 40 deletions(-)
>>>
>>> diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
>>> index 83b1b9c..acc6225 100644
>>> --- a/sound/soc/rockchip/rockchip_i2s.c
>>> +++ b/sound/soc/rockchip/rockchip_i2s.c
>>> @@ -82,8 +82,8 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
>>>                                     I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
>>>
>>>                  regmap_update_bits(i2s->regmap, I2S_XFER,
>>> -                                  I2S_XFER_TXS_START | I2S_XFER_RXS_START,
>>> -                                  I2S_XFER_TXS_START | I2S_XFER_RXS_START);
>>> +                                  I2S_XFER_TXS_START,
>>> +                                  I2S_XFER_TXS_START);
>>>
>>>                  i2s->tx_start = true;
>>>          } else {
>>> @@ -92,27 +92,23 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
>>>                  regmap_update_bits(i2s->regmap, I2S_DMACR,
>>>                                     I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
>>>
>>> -               if (!i2s->rx_start) {
>>> -                       regmap_update_bits(i2s->regmap, I2S_XFER,
>>> -                                          I2S_XFER_TXS_START |
>>> -                                          I2S_XFER_RXS_START,
>>> -                                          I2S_XFER_TXS_STOP |
>>> -                                          I2S_XFER_RXS_STOP);
>>> +               regmap_update_bits(i2s->regmap, I2S_XFER,
>>> +                                  I2S_XFER_TXS_START,
>>> +                                  I2S_XFER_TXS_STOP);
>>>
>>> -                       regmap_update_bits(i2s->regmap, I2S_CLR,
>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC,
>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC);
>>> +               regmap_update_bits(i2s->regmap, I2S_CLR,
>>> +                                  I2S_CLR_TXC,
>>> +                                  I2S_CLR_TXC);
>>>
>>> -                       regmap_read(i2s->regmap, I2S_CLR, &val);
>>> +               regmap_read(i2s->regmap, I2S_CLR, &val);
>>>
>>> -                       /* Should wait for clear operation to finish */
>>> -                       while (val) {
>>> -                               regmap_read(i2s->regmap, I2S_CLR, &val);
>>> -                               retry--;
>>> -                               if (!retry) {
>>> -                                       dev_warn(i2s->dev, "fail to clear\n");
>>> -                                       break;
>>> -                               }
>>> +               /* Should wait for clear operation to finish */
>>> +               while (val & I2S_CLR_TXC) {
>>> +                       regmap_read(i2s->regmap, I2S_CLR, &val);
>>> +                       retry--;
>>> +                       if (!retry) {
>>> +                               dev_warn(i2s->dev, "fail to clear\n");
>>> +                               break;
>>>                          }
>>>                  }
>>>          }
>>> @@ -128,8 +124,8 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
>>>                                     I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
>>>
>>>                  regmap_update_bits(i2s->regmap, I2S_XFER,
>>> -                                  I2S_XFER_TXS_START | I2S_XFER_RXS_START,
>>> -                                  I2S_XFER_TXS_START | I2S_XFER_RXS_START);
>>> +                                  I2S_XFER_RXS_START,
>>> +                                  I2S_XFER_RXS_START);
>>>
>>>                  i2s->rx_start = true;
>>>          } else {
>>> @@ -138,27 +134,23 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
>>>                  regmap_update_bits(i2s->regmap, I2S_DMACR,
>>>                                     I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
>>>
>>> -               if (!i2s->tx_start) {
>>> -                       regmap_update_bits(i2s->regmap, I2S_XFER,
>>> -                                          I2S_XFER_TXS_START |
>>> -                                          I2S_XFER_RXS_START,
>>> -                                          I2S_XFER_TXS_STOP |
>>> -                                          I2S_XFER_RXS_STOP);
>>> +               regmap_update_bits(i2s->regmap, I2S_XFER,
>>> +                                  I2S_XFER_RXS_START,
>>> +                                  I2S_XFER_RXS_STOP);
>>>
>>> -                       regmap_update_bits(i2s->regmap, I2S_CLR,
>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC,
>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC);
>>> +               regmap_update_bits(i2s->regmap, I2S_CLR,
>>> +                                  I2S_CLR_RXC,
>>> +                                  I2S_CLR_RXC);
>>>
>>> -                       regmap_read(i2s->regmap, I2S_CLR, &val);
>>> +               regmap_read(i2s->regmap, I2S_CLR, &val);
>>>
>>> -                       /* Should wait for clear operation to finish */
>>> -                       while (val) {
>>> -                               regmap_read(i2s->regmap, I2S_CLR, &val);
>>> -                               retry--;
>>> -                               if (!retry) {
>>> -                                       dev_warn(i2s->dev, "fail to clear\n");
>>> -                                       break;
>>> -                               }
>>> +               /* Should wait for clear operation to finish */
>>> +               while (val & I2S_CLR_RXC) {
>>> +                       regmap_read(i2s->regmap, I2S_CLR, &val);
>>> +                       retry--;
>>> +                       if (!retry) {
>>> +                               dev_warn(i2s->dev, "fail to clear\n");
>>> +                               break;
>>>                          }
>>>                  }
>>>          }
>>> --
>>> 2.6.3.462.gbe2c914
>>
>> Using my Veyron Jerry Chromebook wiht latest kernel I found that the
>> speakers doesn't work. Bisect points to this patch as the offending
>> commit. However your changes looks reasonable the fact is that
>> reverting the patch makes the audio work again on my device. I need to
>> dig a bit more into the issue, but meanwhile, any idea on what is
>> happening ? Can I ask which device did you test?
>
> I tested this on a Radxa Rock2 square.  This change fixed an issue I
> found when running separate processes for playback and recording (I was
> testing with arecord and speaker-test IIRC) but I don't think that
> should be relevant.  I just read through the patch again and I can't see
> anything obviously wrong so I'm afraid I don't have any idea what's
> causing the problem you're seeing.
>
Do you have test playback/capture at the same time? I think you may 
reproduce this issue if you do as follows:

step 1: tinyplay test.wav -D 0 -d 0 -p 1024 -n 4 &
step 2: tinycap r.wav -D 0 -d 0 -p 1024 -n 4 &

you will find that there is no music now.

because of this problem, we enable tx/rx at the same time to WA this issue.

May I know what's the issue that you met before?
>
> John
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip
>
>
>



From bhe at redhat.com  Mon May  2 21:24:41 2016
From: bhe at redhat.com (Baoquan He)
Date: Tue, 3 May 2016 12:24:41 +0800
Subject: [PATCH 10/12] kexec: arrange for paddr_vmcoreinfo_note() to
 return phys_addr_t
In-Reply-To: <CAHB_GurwYqPbccLU9UHppLxbBr4Cfs47myKAer-RJicT=T7uBw@mail.gmail.com>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <E1aviFP-0000je-5t@rmk-PC.arm.linux.org.uk>
 <CAHB_Gur-6oyEheN-Pom7OwivdvrQpCBaXvM1V2H0JPFRCFZthA@mail.gmail.com>
 <20160429151639.GC23726@leverpostej>
 <CAHB_GurwYqPbccLU9UHppLxbBr4Cfs47myKAer-RJicT=T7uBw@mail.gmail.com>
Message-ID: <20160503042441.GA2518@x1.redhat.com>

This patch is clearly related to kdump. The prefix of subject should be
changed to kdump. Kexec doesn't need to handle vmcore things. 

And patches realted to kexec/kdump should be CCed to Andrew, he usually
picks up and add them into akpm tree.

Hi Pratyush,

Could you please help tell why arm PAE kernel can be put above 4G?
Since the change is related to common code, I am curious about how
it's so different with other ARCHs.

Thanks
Baoquan


On 04/29/16 at 09:17pm, Pratyush Anand wrote:
> On Fri, Apr 29, 2016 at 8:46 PM, Mark Rutland <mark.rutland at arm.com> wrote:
> > On Fri, Apr 29, 2016 at 08:36:43PM +0530, Pratyush Anand wrote:
> >> > +       phys_addr_t vmcore_base = paddr_vmcoreinfo_note();
> >> > +       return sprintf(buf, "%pa %x\n", &vmcore_base,
> >>
> >> Why do we pass &vmcore_base? Shouldn't it be vmcore_base?
> >
> > The %pa* printk format specifiers take the value by reference (as
> > phys_addr_t and friends are not necessarily the same width as a
> > pointer). Per Documentation/printk-formats.txt:
> >
> > Physical addresses types phys_addr_t:
> >
> >         %pa[p]  0x01234567 or 0x0123456789abcdef
> >
> >         For printing a phys_addr_t type (and its derivatives, such as
> >         resource_size_t) which can vary based on build options, regardless of
> >         the width of the CPU data path. Passed by reference.
> >
> > So the above prints the value of vmcore_base as expected.
> 
> Thanks a lot Mark for explaining :-)
> 
> Reviewed-by: Pratyush Anand <panand at redhat.com>
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


From lokeshvutla at ti.com  Mon May  2 21:20:04 2016
From: lokeshvutla at ti.com (Lokesh Vutla)
Date: Tue, 3 May 2016 09:50:04 +0530
Subject: [PATCH v2 0/3] AM57/DRA7 Clock Tree DTSI Fix-ups
In-Reply-To: <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
Message-ID: <572826F4.3080500@ti.com>



On Monday 02 May 2016 10:42 PM, J.D. Schroeder wrote:
> This series of patches fixes several discrepancies between the
> AM57/DRA7 clock tree description and the actual hardware behavior and
> frequencies. With these changes a more complete picture of the clock
> tree is represented for a few of the clocks and their resulting
> frequencies.

Tested on my DRA74-evm.

Tested-by: Lokesh Vutla <lokeshvutla at ti.com>

Thanks and regards,
Lokesh

> 
> v2 Changes:
> * Rebased on linux-next as requested by Tony Lindgren
> * Eliminated previous patch 2 as another change fixing the same thing
>   was merged in eea08802f586acd6aef377d1b4a541821013cc0b
> * Added to the commit message in patch 2 to clarify the source of the
>   clock being internal to the processor
> * Added a new patch 3 to fix a new warning introduced by
>   eea08802f586acd6aef377d1b4a541821013cc0b
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


From kernel at martin.sperl.org  Mon May  2 22:07:11 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Tue, 3 May 2016 07:07:11 +0200
Subject: [PATCH V4 1/2] clk: bcm2835: mark enabled clocks with
 CLK_IS_CRITICAL
In-Reply-To: <87wpncueoq.fsf@eliezer.anholt.net>
References: <1461951756-16804-1-git-send-email-kernel@martin.sperl.org>
 <1461951756-16804-2-git-send-email-kernel@martin.sperl.org>
 <87zis8h3pp.fsf@eliezer.anholt.net>
 <5CC0D984-91E5-4401-8AB6-5827269C4395@martin.sperl.org>
 <87wpncueoq.fsf@eliezer.anholt.net>
Message-ID: <399371FE-CC25-469C-9917-FDFCDA741D56@martin.sperl.org>



> On 03.05.2016, at 03:13, Eric Anholt <eric at anholt.net> wrote:
> 
> Martin Sperl <kernel at martin.sperl.org> writes:
> 
>>> On 02.05.2016, at 17:36, Eric Anholt <eric at anholt.net> wrote:
>>> 
>>> kernel at martin.sperl.org writes:
>>> 
>>>> From: Martin Sperl <kernel at martin.sperl.org>
>>>> 
>>>> The bcm2835 firmware enables several clocks and plls before
>>>> booting the linux kernel.
>>>> 
>>>> These plls should never get disabled as it may result in a
>>>> stopped system clock and more.
>>>> 
>>>> So during probing we check if the clock is enabled
>>>> and if it is then mark that clock with CLK_IS_CRITICAL.
>>>> 
>>>> As a consequence this will also enable the corresponding
>>>> parent plls and pll-divs.
>>>> 
>>>> This is intended as a stop-gap until CLK_ENABLE_HAND_OFF
>>>> becomes available, at which point it should be used instead.
>>>> 
>>>> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
>>> 
>>> I still think that we don't want this patch.  We should be able to
>>> disable clocks that the firmware turned on, unless they really need to
>>> stay on.  If you have troubles on the upstream DT, let's talk about
>>> individual clocks.
>> 
>> May I ask you what is your main concern about using
>> CLK_IS_CRITICAL as a stop-gap/in general?
> 
> Burning power when you shouldn't, which is a bug.
It is a bug, but it is better than a crash that happens currently
because of a stopped clock.
Also there is a proposed way forward when hand-off
becomes available.

> 
>> Also the current situation of the machine crashing when releasing the
>> PCM clock when the parent is PLLC or PLLD is worse than having some
>> clocks/pll running unnecessarily.
> 
> Are you saying this happens on the upstream kernel?  This sounds like a
> bug you'd see in the downstream kernel because they haven't hooked up
> the clocks in their DT.
This happens for both upstream and downstream when using
cprman...

You remember the main-uart crashing discussion (when 
loaded as a module or not used as the kernel console?) it is
exactly what an unclaimed clock is triggering when the clock
Is prepared/enabled and then released.

I have also seen the same issue happen with PCM without
the patch - as soon as we request a frequency which will use
pllc/d-per as the parent, and we later release the clock the
system crashes -  but there only if we run the dt with minimal
clocks using cprman, as it is hidden as soon as you increase enable
count of the plls because of an enabled clock by a different
device that also consumes the same pll.

So this bug is mostly hidden behind the complete dts that
just consumes lots of parent clocks, but it still may occur 
when we select a frequency that will select the firmware 
enabled but not claimed plla_per - no idea what stopping
that pll would trigger in the system.

Hence we need this patch for the running clocks , but we
also need it for the pll_divs, so actually my patch is
incomplete!


From sr at denx.de  Mon May  2 22:53:11 2016
From: sr at denx.de (Stefan Roese)
Date: Tue,  3 May 2016 07:53:11 +0200
Subject: [PATCH v8] spi: orion.c: Add direct access mode
Message-ID: <1462254791-5694-1-git-send-email-sr@denx.de>

This patch adds support for the direct access mode to the Orion SPI
driver which is used on the Marvell Armada based SoCs. In this direct
mode, all data written to (or read from) a specifically mapped MBus
window (linked to one SPI chip-select on one of the SPI controllers)
will be transferred directly to the SPI bus. Without the need to control
the SPI registers in between. This can improve the SPI transfer rate in
such cases.

Both, direct-read and -write mode are supported. But only the write
mode has been tested. This mode especially benefits from the SPI direct
mode, as the data bytes are written head-to-head to the SPI bus,
without any additional addresses.

One use-case for this direct write mode is, programming a FPGA bitstream
image into the FPGA connected to the SPI bus at maximum speed.

This mode is described in chapter "22.5.2 Direct Write to SPI" in the
Marvell Armada XP Functional Spec Datasheet.

Signed-off-by: Stefan Roese <sr at denx.de>
Cc: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
Cc: Gregory CLEMENT <gregory.clement at free-electrons.com>
Cc: Andrew Lunn <andrew at lunn.ch>
Acked-by: Arnd Bergmann <arnd at arndb.de>
Cc: Mark Brown <broonie at kernel.org>
---
v8:
- Use "/ 4" instead of ">> 2" as suggested by Mark

v7:
- Changed tx function to only write the really intended number of
  bytes (drop DIV_ROUND_UP) as suggested by Arnd
- Added Arnd's Acked-by

v6:
- Switched from memcpy() to writesl() for the TX transfer.
- Only one page is mapped via ioremap as this is sufficient for
  the currently implemented simple TX transfer.
- Removed max_transfer_size() as its not needed with the current
  one page mapping that supports an unlimited amount of SPI data.
- Added a comment to the 'reg' description in the DT bindings
  documentation as suggested by Arnd.
- Changed 'reg' and 'ranges' to use '<' and '>' in this file.
- Changed size to 0xffffffff in this file.
- Added a small paragraph to the commit text, describing the
  possibility to support SPI-NOR & SPI-NAND devices via this
  direct access mode.

v5:
- Added some documentation for the direct mode to the orion-spi DT
  bindings document, including an example and a reference to the
  mbus DT bindings documentation.

v4:
- Add max_transfer_size()
- Fall back from direct-write mode to PIO mode when
  - transfer size is exceedeed
  - non-8bit transfers
- Restrict to direct-write mode for now. SPI direct read mode can
  be added later, when someone has a platform supporting this
  mode.

v3:
- Used static MBus windows again, as suggested by Arnd
- No new DT bindings needed for this. The MBus windows need to be
  configured in the 'reg' property of the SPI controller. This is
  done in a separate patch for the Armada platforms.
- The direct mapping is configured and enable by adding the
  specific MBus entry to the 'ranges' property of the 'soc' node
  in the board dts file.

v2:
- Use one MBus window for each SPI controller instead of one for
  for each SPI device. This MBus window is re-assigned, once the
  CS changes.
- Assert the CS over the entire message
- Don't restrict the direct access mode to only direct write mode
- Add check for max size before using memcpy()
- Remove spidev from DT bindings documentation

 .../devicetree/bindings/spi/spi-orion.txt          | 49 +++++++++++-
 drivers/spi/spi-orion.c                            | 87 ++++++++++++++++++++++
 2 files changed, 135 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-orion.txt b/Documentation/devicetree/bindings/spi/spi-orion.txt
index 98bc698..4f629cc 100644
--- a/Documentation/devicetree/bindings/spi/spi-orion.txt
+++ b/Documentation/devicetree/bindings/spi/spi-orion.txt
@@ -8,7 +8,15 @@ Required properties:
     - "marvell,armada-380-spi", for the Armada 38x SoCs
     - "marvell,armada-390-spi", for the Armada 39x SoCs
     - "marvell,armada-xp-spi", for the Armada XP SoCs
-- reg : offset and length of the register set for the device
+- reg : offset and length of the register set for the device.
+	This property can optionally have additional entries to configure
+	the SPI direct access mode that some of the Marvell SoCs support
+	additionally to the normal indirect access (PIO) mode. The values
+	for the MBus "target" and "attribute" are defined in the Marvell
+	SoC "Functional Specifications" Manual in the chapter "Marvell
+	Core Processor Address Decoding".
+	The eight register sets following the control registers refer to
+	chip-select lines 0 through 7 respectively.
 - cell-index : Which of multiple SPI controllers is this.
 Optional properties:
 - interrupts : Is currently not used.
@@ -23,3 +31,42 @@ Example:
 	       interrupts = <23>;
 	       status = "disabled";
        };
+
+Example with SPI direct mode support (optionally):
+	spi0: spi at 10600 {
+		compatible = "marvell,orion-spi";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cell-index = <0>;
+		reg = <MBUS_ID(0xf0, 0x01) 0x10600 0x28>, /* control */
+		      <MBUS_ID(0x01, 0x1e) 0 0xffffffff>, /* CS0 */
+		      <MBUS_ID(0x01, 0x5e) 0 0xffffffff>, /* CS1 */
+		      <MBUS_ID(0x01, 0x9e) 0 0xffffffff>, /* CS2 */
+		      <MBUS_ID(0x01, 0xde) 0 0xffffffff>, /* CS3 */
+		      <MBUS_ID(0x01, 0x1f) 0 0xffffffff>, /* CS4 */
+		      <MBUS_ID(0x01, 0x5f) 0 0xffffffff>, /* CS5 */
+		      <MBUS_ID(0x01, 0x9f) 0 0xffffffff>, /* CS6 */
+		      <MBUS_ID(0x01, 0xdf) 0 0xffffffff>; /* CS7 */
+		interrupts = <23>;
+		status = "disabled";
+	};
+
+To enable the direct mode, the board specific 'ranges' property in the
+'soc' node needs to add the entries for the desired SPI controllers
+and its chip-selects that are used in the direct mode instead of PIO
+mode. Here an example for this (SPI controller 0, device 1 and SPI
+controller 1, device 2 are used in direct mode. All other SPI device
+are used in the default indirect (PIO) mode):
+	soc {
+		/*
+		 * Enable the SPI direct access by configuring an entry
+		 * here in the board-specific ranges property
+		 */
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000>,	/* internal regs */
+			 <MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>,	/* BootROM       */
+			 <MBUS_ID(0x01, 0x5e) 0 0 0xf1100000 0x10000>,	/* SPI0-DEV1 */
+			 <MBUS_ID(0x01, 0x9a) 0 0 0xf1110000 0x10000>;	/* SPI1-DEV2 */
+
+For further information on the MBus bindings, please see the MBus
+DT documentation:
+Documentation/devicetree/bindings/bus/mvebu-mbus.txt
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index a87cfd4..604b5dd 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/clk.h>
 #include <linux/sizes.h>
@@ -43,6 +44,9 @@
 #define ORION_SPI_INT_CAUSE_REG		0x10
 #define ORION_SPI_TIMING_PARAMS_REG	0x18
 
+/* Register for the "Direct Mode" */
+#define SPI_DIRECT_WRITE_CONFIG_REG	0x20
+
 #define ORION_SPI_TMISO_SAMPLE_MASK	(0x3 << 6)
 #define ORION_SPI_TMISO_SAMPLE_1	(1 << 6)
 #define ORION_SPI_TMISO_SAMPLE_2	(2 << 6)
@@ -78,11 +82,18 @@ struct orion_spi_dev {
 	bool			is_errata_50mhz_ac;
 };
 
+struct orion_direct_acc {
+	void __iomem		*vaddr;
+	u32			size;
+};
+
 struct orion_spi {
 	struct spi_master	*master;
 	void __iomem		*base;
 	struct clk              *clk;
 	const struct orion_spi_dev *devdata;
+
+	struct orion_direct_acc	direct_access[ORION_NUM_CHIPSELECTS];
 };
 
 static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
@@ -372,10 +383,38 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
 {
 	unsigned int count;
 	int word_len;
+	struct orion_spi *orion_spi;
+	int cs = spi->chip_select;
 
 	word_len = spi->bits_per_word;
 	count = xfer->len;
 
+	orion_spi = spi_master_get_devdata(spi->master);
+
+	/*
+	 * Use SPI direct write mode if base address is available. Otherwise
+	 * fall back to PIO mode for this transfer.
+	 */
+	if ((orion_spi->direct_access[cs].vaddr) && (xfer->tx_buf) &&
+	    (word_len == 8)) {
+		unsigned int cnt = count / 4;
+		unsigned int rem = count % 4;
+
+		/*
+		 * Send the TX-data to the SPI device via the direct
+		 * mapped address window
+		 */
+		writesl(orion_spi->direct_access[cs].vaddr, xfer->tx_buf, cnt);
+		if (rem) {
+			u32 *buf = (u32 *)xfer->tx_buf;
+
+			writesb(orion_spi->direct_access[cs].vaddr, &buf[cnt],
+				rem);
+		}
+
+		return count;
+	}
+
 	if (word_len == 8) {
 		const u8 *tx = xfer->tx_buf;
 		u8 *rx = xfer->rx_buf;
@@ -425,6 +464,10 @@ static int orion_spi_reset(struct orion_spi *orion_spi)
 {
 	/* Verify that the CS is deasserted */
 	orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+
+	/* Don't deassert CS between the direct mapped SPI transfers */
+	writel(0, spi_reg(orion_spi, SPI_DIRECT_WRITE_CONFIG_REG));
+
 	return 0;
 }
 
@@ -504,6 +547,7 @@ static int orion_spi_probe(struct platform_device *pdev)
 	struct resource *r;
 	unsigned long tclk_hz;
 	int status = 0;
+	struct device_node *np;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(*spi));
 	if (master == NULL) {
@@ -576,6 +620,49 @@ static int orion_spi_probe(struct platform_device *pdev)
 		goto out_rel_clk;
 	}
 
+	/* Scan all SPI devices of this controller for direct mapped devices */
+	for_each_available_child_of_node(pdev->dev.of_node, np) {
+		u32 cs;
+
+		/* Get chip-select number from the "reg" property */
+		status = of_property_read_u32(np, "reg", &cs);
+		if (status) {
+			dev_err(&pdev->dev,
+				"%s has no valid 'reg' property (%d)\n",
+				np->full_name, status);
+			status = 0;
+			continue;
+		}
+
+		/*
+		 * Check if an address is configured for this SPI device. If
+		 * not, the MBus mapping via the 'ranges' property in the 'soc'
+		 * node is not configured and this device should not use the
+		 * direct mode. In this case, just continue with the next
+		 * device.
+		 */
+		status = of_address_to_resource(pdev->dev.of_node, cs + 1, r);
+		if (status)
+			continue;
+
+		/*
+		 * Only map one page for direct access. This is enough for the
+		 * simple TX transfer which only writes to the first word.
+		 * This needs to get extended for the direct SPI-NOR / SPI-NAND
+		 * support, once this gets implemented.
+		 */
+		spi->direct_access[cs].vaddr = devm_ioremap(&pdev->dev,
+							    r->start,
+							    PAGE_SIZE);
+		if (IS_ERR(spi->direct_access[cs].vaddr)) {
+			status = PTR_ERR(spi->direct_access[cs].vaddr);
+			goto out_rel_clk;
+		}
+		spi->direct_access[cs].size = PAGE_SIZE;
+
+		dev_info(&pdev->dev, "CS%d configured for direct access\n", cs);
+	}
+
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
-- 
2.8.2



From panand at redhat.com  Mon May  2 22:53:29 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 3 May 2016 11:23:29 +0530
Subject: [PATCH 10/12] kexec: arrange for paddr_vmcoreinfo_note() to
 return phys_addr_t
In-Reply-To: <20160503042441.GA2518@x1.redhat.com>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <E1aviFP-0000je-5t@rmk-PC.arm.linux.org.uk>
 <CAHB_Gur-6oyEheN-Pom7OwivdvrQpCBaXvM1V2H0JPFRCFZthA@mail.gmail.com>
 <20160429151639.GC23726@leverpostej>
 <CAHB_GurwYqPbccLU9UHppLxbBr4Cfs47myKAer-RJicT=T7uBw@mail.gmail.com>
 <20160503042441.GA2518@x1.redhat.com>
Message-ID: <20160503055329.GA13045@dhcppc6.redhat.com>

Hi Baoquan,

On 03/05/2016:12:24:41 PM, Baoquan He wrote:
> Hi Pratyush,
> 
> Could you please help tell why arm PAE kernel can be put above 4G?

PAE system can have physical addresses above 4G. So, if a CPU is supporting the
LPAE page table format then we should be able to access physical addresses
beyond 4G.

> Since the change is related to common code, I am curious about how
> it's so different with other ARCHs.

paddr_vmcoreinfo_note() returns a physical address, so returning phys_addr_t
seems most appropriate. So, kernel variable may land into above 4G locations,
even with the platform in other architecture (with PAE support), if start of RAM
is located very high,

So, in my opinion it would be safer to have these changes for other ARCHs as
well.

~Pratyush


From joel at jms.id.au  Mon May  2 22:56:33 2016
From: joel at jms.id.au (Joel Stanley)
Date: Tue, 3 May 2016 15:26:33 +0930
Subject: [PATCH v2 04/11] clocksource/moxart: Generalise timer for use on
 other socs
In-Reply-To: <571A5FBA.9010204@linaro.org>
References: <1461225849-28074-1-git-send-email-joel@jms.id.au>
 <1461225849-28074-5-git-send-email-joel@jms.id.au>
 <571A5FBA.9010204@linaro.org>
Message-ID: <CACPK8XfgDPPYG=ON-Z+gEKSg1fe4PuqRWoMz8P-9oCMvgQKmhw@mail.gmail.com>

Hey Daniel,

Thanks for the review.

On Sat, Apr 23, 2016 at 3:00 AM, Daniel Lezcano
<daniel.lezcano at linaro.org> wrote:
> On 04/21/2016 10:04 AM, Joel Stanley wrote:
>>
>> The moxart timer IP is shared with another soc made by Aspeed.
>> Generalise the registers that differ so the same driver can be used for
>> both.
>>
>> As we now depend on CLKSRC_MMIO, create a Kconfig symbol for the driver
>> so we can express this dependency.
>>
>> Signed-off-by: Joel Stanley <joel at jms.id.au>
>> ---
>
>
> In the future, please Cc the maintainers.

Sure.

>
> You probably can remove all the unused macro definition here for both MOXART
> and ASPEED to have something just a couple of definition.

I agree with Ben; we're helping out by documenting the hardware in
lieu of a public datasheet. I'd prefer to keep this here.

>>   static void __iomem *base;
>>   static unsigned int clock_count_per_tick;
>> +static unsigned int t1_disable_val, t1_enable_val;
>
>
> It will be cleaner to:
>
> 1. Factor out:
>         writel(TIMER1_DISABLE, base + TIMER_CR);
>         writel(TIMER1_ENABLE, base + TIMER_CR);

I considered this myself but went with the minimal change. I'm not
fussed, so I will rework it as you suggest.

>From the register layout I suspect this IP block is a Faraday Tech
FTTMR010[1], but I don't have any other evidence. Would you take a
patch to change the name or would you prefer leaving it as moxart?

Cheers,

Joel

[1] https://lists.nongnu.org/archive/html/qemu-devel/2013-03/msg04333.html


From yamada.masahiro at socionext.com  Mon May  2 23:29:52 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue,  3 May 2016 15:29:52 +0900
Subject: [PATCH] reset: fix Kconfig menu to include reset drivers in sub-menu
Message-ID: <1462256992-31063-1-git-send-email-yamada.masahiro@socionext.com>

In "make menuconfig", reset drivers are currently lined up together
with the reset sub-system menu, like this:

    -*- Reset Controller Support  ----
    < > Hi6220 Reset Driver

(It also means, the menu "Reset Controller Support" is always empty.)

"Hi6220 Reset Driver" should go into the sub-menu of the
"Reset Controller Support".

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

 drivers/reset/Kconfig     | 4 ++++
 drivers/reset/sti/Kconfig | 1 -
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index df37212..6a0b24b 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -12,5 +12,9 @@ menuconfig RESET_CONTROLLER
 
 	  If unsure, say no.
 
+if RESET_CONTROLLER
+
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
+
+endif
diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig
index f8c15a3..6131785 100644
--- a/drivers/reset/sti/Kconfig
+++ b/drivers/reset/sti/Kconfig
@@ -2,7 +2,6 @@ if ARCH_STI
 
 config STI_RESET_SYSCFG
 	bool
-	select RESET_CONTROLLER
 
 config STIH415_RESET
 	bool
-- 
1.9.1



From vinod.koul at intel.com  Mon May  2 23:55:34 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Tue, 3 May 2016 12:25:34 +0530
Subject: [PATCH 0/5] Use dma_pool_zalloc
In-Reply-To: <1461960552-7429-1-git-send-email-Julia.Lawall@lip6.fr>
References: <1461960552-7429-1-git-send-email-Julia.Lawall@lip6.fr>
Message-ID: <20160503065533.GO2274@localhost>

On Fri, Apr 29, 2016 at 10:09:07PM +0200, Julia Lawall wrote:
> Dma_pool_zalloc combines dma_pool_alloc and memset 0.  The semantic patch
> that makes this transformation is as follows: (http://coccinelle.lip6.fr/)

Applied all dmaengine patches

-- 
~Vinod


From vinod.koul at intel.com  Mon May  2 23:58:12 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Tue, 3 May 2016 12:28:12 +0530
Subject: [PATCH v4 0/5] Add XOR engine support to Armada 3700 SoC (ARM64)
In-Reply-To: <1461916149-30900-1-git-send-email-gregory.clement@free-electrons.com>
References: <1461916149-30900-1-git-send-email-gregory.clement@free-electrons.com>
Message-ID: <20160503065811.GP2274@localhost>

On Fri, Apr 29, 2016 at 09:49:04AM +0200, Gregory CLEMENT wrote:
> Hi,
> 
> This series adds the support of the Marvell XOR engine to the Armada
> 3700 SoC. As this SoC is an ARM64 one, then the code has been fixed to
> support the 64 bits platform.
> 
> The initialization for the Armada 3700 is different from the other
> SoCs, so in order to support it, a new way of handling the different
> family have been added.
> 
> Once the dmaengine part will be approved, I will apply the dts part
> in the mvebu/dt64 tree.
> 
> In this fourth series I took into account the remarks from Vinoud, I
> also updated the dts patch that I will apply on my tree.

Applied, 1 thru 4.

-- 
~Vinod


From christo.radev at gmail.com  Tue May  3 00:12:06 2016
From: christo.radev at gmail.com (christo.radev at gmail.com)
Date: Tue, 3 May 2016 00:12:06 -0700 (PDT)
Subject: [PATCH 1/1] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
References: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
Message-ID: <f3da30a6-9ac0-4d5e-8611-ebb80cb3589e@googlegroups.com>

Hi to All,

I have already solved and tested this issue on Armbian build.
Find patches for both legacy (3.4.111) and mainline (4.5.2) kernels on:
http://forum.armbian.com/index.php/topic/853-armbian-customization/page-2#entry7494
There it is also described how to do eMMC bootable and much more.

About the board - Olimex already sold all 3 kinds after migration to their HW rev. E. One have to specify Lime2-eMMC as A20-Olinuxino-Lime2-eMMC instead of their old 2 options A20-Olinuxino-Lime2(-4GB).

Regards
Chris

From oliver at schinagl.nl  Tue May  3 00:21:06 2016
From: oliver at schinagl.nl (Olliver Schinagl)
Date: Tue, 3 May 2016 09:21:06 +0200
Subject: [PATCH 1/1] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <CAGb2v66E2TuN3+tYaAbniV3q67waDZOfqKAW14VJz6xZFomZ=Q@mail.gmail.com>
References: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
 <CAGb2v66E2TuN3+tYaAbniV3q67waDZOfqKAW14VJz6xZFomZ=Q@mail.gmail.com>
Message-ID: <57285162.2000704@schinagl.nl>

Hey Chen,

On 03-05-16 05:33, Chen-Yu Tsai wrote:
> Hi,
>
> On Thu, Apr 28, 2016 at 3:19 PM, Olliver Schinagl <oliver at schinagl.nl> wrote:
>> There are 3 kinds of OLinuXino Lime2 boards.
>> One without any on board storage, one with NAND storage and one with
>> eMMC storage. This patch adds the eMMC variant of boards.
>>
>> eMMC storage is different from a regular SD card in that it is soldered
>> on the board and cannot be changed. Additionally, it shares pins with
>> the NAND module and with the second SPI port.
>>
>> Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>
>> ---
>>   .../boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts    | 64 ++++++++++++++++++++++
>>   1 file changed, 64 insertions(+)
>>   create mode 100644 arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
>>
>> diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
>> new file mode 100644
>> index 0000000..689da36
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
>> @@ -0,0 +1,64 @@
>> + /*
>> + * Copyright 2015 - Ultimaker B.V.
>> + * Author Olliver Schinagl <oliver at schinagl.nl>
>> + *
>> + * 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.
>> + */
>> +
>> +#include "sun7i-a20-olinuxino-lime2.dts"
>> +
>> +/ {
>> +       model = "Olimex A20-OLinuXino-LIME2-eMMC";
>> +};
>> +
>> +&mmc2 {
>> +       pinctrl-names = "default";
>> +       pinctrl-0 = <&mmc2_pins_a>;
>> +       vmmc-supply = <&reg_vcc3v3>;
>> +       bus-width = <4>;
> Only 4 bits? We normally see eMMC with 8 bits. 4 bits are some kind of
> embedded SD card.
On A20 as well? Our investigations so far have concluded that the A10 
and A20 have those pins not mapped out to pads. The IP does support it 
however we assume.
>
>> +       non-removable;
>> +       no-1-8-v;
> This flag is not supported on sunxi.
>
> Instead, use the vqmmc-supply with the correct regulator and constraints.
That was not supposed to be there, i'll fix it! Sorry.
>
> ChenYu
>
>> +       status = "okay";
>> +
>> +       emmc: emmc at 0 {
>> +               reg = <0>;
>> +               compatible = "mmc-card";
>> +               broken-hpi;
>> +       };
>> +};
>> --
>> 2.8.0.rc3
>>



From wens at csie.org  Tue May  3 00:25:25 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 3 May 2016 15:25:25 +0800
Subject: [PATCH 1/1] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <57285162.2000704@schinagl.nl>
References: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
 <CAGb2v66E2TuN3+tYaAbniV3q67waDZOfqKAW14VJz6xZFomZ=Q@mail.gmail.com>
 <57285162.2000704@schinagl.nl>
Message-ID: <CAGb2v66r9m7qVW6BszeT2wqs0KyEr4x5ivTJYqu2Fes=R9-Ltw@mail.gmail.com>

On Tue, May 3, 2016 at 3:21 PM, Olliver Schinagl <oliver at schinagl.nl> wrote:
> Hey Chen,

ChenYu :)

>
>
> On 03-05-16 05:33, Chen-Yu Tsai wrote:
>>
>> Hi,
>>
>> On Thu, Apr 28, 2016 at 3:19 PM, Olliver Schinagl <oliver at schinagl.nl>
>> wrote:
>>>
>>> There are 3 kinds of OLinuXino Lime2 boards.
>>> One without any on board storage, one with NAND storage and one with
>>> eMMC storage. This patch adds the eMMC variant of boards.
>>>
>>> eMMC storage is different from a regular SD card in that it is soldered
>>> on the board and cannot be changed. Additionally, it shares pins with
>>> the NAND module and with the second SPI port.
>>>
>>> Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>
>>> ---
>>>   .../boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts    | 64
>>> ++++++++++++++++++++++
>>>   1 file changed, 64 insertions(+)
>>>   create mode 100644 arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
>>>
>>> diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
>>> b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
>>> new file mode 100644
>>> index 0000000..689da36
>>> --- /dev/null
>>> +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
>>> @@ -0,0 +1,64 @@
>>> + /*
>>> + * Copyright 2015 - Ultimaker B.V.
>>> + * Author Olliver Schinagl <oliver at schinagl.nl>
>>> + *
>>> + * 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.
>>> + */
>>> +
>>> +#include "sun7i-a20-olinuxino-lime2.dts"
>>> +
>>> +/ {
>>> +       model = "Olimex A20-OLinuXino-LIME2-eMMC";
>>> +};
>>> +
>>> +&mmc2 {
>>> +       pinctrl-names = "default";
>>> +       pinctrl-0 = <&mmc2_pins_a>;
>>> +       vmmc-supply = <&reg_vcc3v3>;
>>> +       bus-width = <4>;
>>
>> Only 4 bits? We normally see eMMC with 8 bits. 4 bits are some kind of
>> embedded SD card.
>
> On A20 as well? Our investigations so far have concluded that the A10 and
> A20 have those pins not mapped out to pads. The IP does support it however
> we assume.

You're right. My bad. First time A10/A20 sees eMMC support.

>>
>>
>>> +       non-removable;
>>> +       no-1-8-v;
>>
>> This flag is not supported on sunxi.
>>
>> Instead, use the vqmmc-supply with the correct regulator and constraints.
>
> That was not supposed to be there, i'll fix it! Sorry.

Thanks
ChenYu

>
>>
>> ChenYu
>>
>>> +       status = "okay";
>>> +
>>> +       emmc: emmc at 0 {
>>> +               reg = <0>;
>>> +               compatible = "mmc-card";
>>> +               broken-hpi;
>>> +       };
>>> +};
>>> --
>>> 2.8.0.rc3
>>>
>


From chunfeng.yun at mediatek.com  Tue May  3 00:44:18 2016
From: chunfeng.yun at mediatek.com (chunfeng yun)
Date: Tue, 3 May 2016 15:44:18 +0800
Subject: [PATCH] usb: xhci-mtk: fixup mouse wakeup failure during system
 suspend
In-Reply-To: <1461204293-18243-1-git-send-email-chunfeng.yun@mediatek.com>
References: <1461204293-18243-1-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <1462261458.11651.7.camel@mhfsdcap03>

Hi Mathias,

On Thu, 2016-04-21 at 10:04 +0800, Chunfeng Yun wrote:
> Click mouse after xhci suspend completion but before system suspend
> completion, system will not be waken up by mouse if the duration of
> them is larger than 20ms which is the device UFP's resume signaling
> lasted. Another reason is that the SPM is not enabled before system
> suspend compeltion, this causes SPM also not notice the resume signal.
> So in order to reduce the duration less than 20ms, make use of
> syscore's suspend/resume interface.
> In fact it is a work around solution which only reduces the
> probability of failure, because we can't ensure that the duration from
> syscore's suspend completion to SPM working is always less than 20ms.
> 
> Because the syscore runs on irq disabled context, and xhci's
> suspend/resume calls some sleeping functions, enable local irq
> and then disable it during suspend/resume. This may be not a problem,
> since only boot CPU is runing.
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
> ---
>  drivers/usb/host/xhci-mtk.c |   31 ++++++++++++++++++++++++++++++-
>  1 file changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
> index 79959f1..8277f02 100644
> --- a/drivers/usb/host/xhci-mtk.c
> +++ b/drivers/usb/host/xhci-mtk.c
> @@ -28,6 +28,7 @@
>  #include <linux/pm_runtime.h>
>  #include <linux/regmap.h>
>  #include <linux/regulator/consumer.h>
> +#include <linux/syscore_ops.h>
>  
>  #include "xhci.h"
>  #include "xhci-mtk.h"
> @@ -490,6 +491,8 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
>  	return xhci_gen_setup(hcd, xhci_mtk_quirks);
>  }
>  
> +static struct device *xhci_mtk_syscore_dev;
> +
>  static int xhci_mtk_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -512,6 +515,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)
>  	if (!mtk)
>  		return -ENOMEM;
>  
> +	xhci_mtk_syscore_dev = dev;
>  	mtk->dev = dev;
>  	mtk->vbus = devm_regulator_get(dev, "vbus");
>  	if (IS_ERR(mtk->vbus)) {
> @@ -740,6 +744,29 @@ static int __maybe_unused xhci_mtk_resume(struct device *dev)
>  	return 0;
>  }
>  
> +static int xhci_mtk_syscore_suspend(void)
> +{
> +	local_irq_enable();
> +	xhci_mtk_suspend(xhci_mtk_syscore_dev);
> +	local_irq_disable();
> +
> +	return 0;
> +}
> +
> +static void xhci_mtk_syscore_resume(void)
> +{
> +	local_irq_enable();
> +	xhci_mtk_resume(xhci_mtk_syscore_dev);
> +	local_irq_disable();
> +
> +	return;
> +}
> +
> +static struct syscore_ops xhci_mtk_syscore_ops = {
> +	.suspend = xhci_mtk_syscore_suspend,
> +	.resume = xhci_mtk_syscore_resume,
> +};
> +
>  static const struct dev_pm_ops xhci_mtk_pm_ops = {
>  	SET_SYSTEM_SLEEP_PM_OPS(xhci_mtk_suspend, xhci_mtk_resume)
>  };
> @@ -758,7 +785,7 @@ static struct platform_driver mtk_xhci_driver = {
>  	.remove	= xhci_mtk_remove,
>  	.driver	= {
>  		.name = "xhci-mtk",
> -		.pm = DEV_PM_OPS,
> +		/*.pm = DEV_PM_OPS,*/
>  		.of_match_table = of_match_ptr(mtk_xhci_of_match),
>  	},
>  };
> @@ -766,6 +793,7 @@ MODULE_ALIAS("platform:xhci-mtk");
>  
>  static int __init xhci_mtk_init(void)
>  {
> +	register_syscore_ops(&xhci_mtk_syscore_ops);
>  	xhci_init_driver(&xhci_mtk_hc_driver, &xhci_mtk_overrides);
>  	return platform_driver_register(&mtk_xhci_driver);
>  }
> @@ -774,6 +802,7 @@ module_init(xhci_mtk_init);
>  static void __exit xhci_mtk_exit(void)
>  {
>  	platform_driver_unregister(&mtk_xhci_driver);
> +	unregister_syscore_ops(&xhci_mtk_syscore_ops);
>  }
>  module_exit(xhci_mtk_exit);

Do you have any suggestions about the patch?

Thanks
>  




From felipe.balbi at linux.intel.com  Tue May  3 00:51:53 2016
From: felipe.balbi at linux.intel.com (Felipe Balbi)
Date: Tue, 03 May 2016 10:51:53 +0300
Subject: [PATCH] usb: xhci-mtk: fixup mouse wakeup failure during system
 suspend
In-Reply-To: <1462261458.11651.7.camel@mhfsdcap03>
References: <1461204293-18243-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462261458.11651.7.camel@mhfsdcap03>
Message-ID: <87vb2vfujq.fsf@intel.com>


Hi,

chunfeng yun <chunfeng.yun at mediatek.com> writes:
> On Thu, 2016-04-21 at 10:04 +0800, Chunfeng Yun wrote:
>> Click mouse after xhci suspend completion but before system suspend
>> completion, system will not be waken up by mouse if the duration of
>> them is larger than 20ms which is the device UFP's resume signaling

what is "them" here ? The duration of what is longer than 20ms ?

>> lasted. Another reason is that the SPM is not enabled before system

what's SPM ?

>> suspend compeltion, this causes SPM also not notice the resume signal.
           ^^^^^^^^^^
           completion

>> So in order to reduce the duration less than 20ms, make use of
>> syscore's suspend/resume interface.

no, this is the wrong approach

>> In fact it is a work around solution which only reduces the
>> probability of failure, because we can't ensure that the duration from
>> syscore's suspend completion to SPM working is always less than 20ms.

right, which means you're not really fixing anything. Morevoer, you make
it so that this won't work with multiple instances of the XHCI IP in
your SoC.

>> Because the syscore runs on irq disabled context, and xhci's
>> suspend/resume calls some sleeping functions, enable local irq
>> and then disable it during suspend/resume. This may be not a problem,
>> since only boot CPU is runing.

another problem :) calling local_irq_{enable,disable}() is an indication
that something's wrong.

>> Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
>> ---
>>  drivers/usb/host/xhci-mtk.c |   31 ++++++++++++++++++++++++++++++-
>>  1 file changed, 30 insertions(+), 1 deletion(-)
>> 
>> diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
>> index 79959f1..8277f02 100644
>> --- a/drivers/usb/host/xhci-mtk.c
>> +++ b/drivers/usb/host/xhci-mtk.c
>> @@ -28,6 +28,7 @@
>>  #include <linux/pm_runtime.h>
>>  #include <linux/regmap.h>
>>  #include <linux/regulator/consumer.h>
>> +#include <linux/syscore_ops.h>
>>  
>>  #include "xhci.h"
>>  #include "xhci-mtk.h"
>> @@ -490,6 +491,8 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
>>  	return xhci_gen_setup(hcd, xhci_mtk_quirks);
>>  }
>>  
>> +static struct device *xhci_mtk_syscore_dev;

now, what happens when you have more than one XHCI instance ?

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160503/58d632ac/attachment.sig>

From marc.zyngier at arm.com  Tue May  3 00:54:27 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 08:54:27 +0100
Subject: [RFC PATCH] irqchip/gic-v3-its: Allocate ITS tables from
 corresponding node memory
In-Reply-To: <1461932322-1206-1-git-send-email-ashoks@broadcom.com>
References: <1461932322-1206-1-git-send-email-ashoks@broadcom.com>
Message-ID: <57285933.3060300@arm.com>

[Please CC LKML and all the irqchip maintainers on these patches]

On 29/04/16 13:18, Ashok Kumar wrote:
> In the case of systems having multi socket and multi ITS, allocating
> local node memory for ITS device table, collection table, interrupt
> translation table and command queue will help in reducing inter-chip
> traffic even though they(except command queue) could be cached in the GIC.
> 
> Signed-off-by: Ashok Kumar <ashoks at broadcom.com>
> ---
> This patch is created on top of Cavium thunderx erratum 23144 patch [1].
> 
> I am not sure how to do this for ACPI as GIC ITS ID in MADT doesn't map to
> _PXM. Am I missing something here? Any thoughts?

Indeed, and SRAT doesn't provide any valuable information either.

> 
> [1] https://lkml.org/lkml/2016/4/15/830 - [PATCH v5] irqchip, gicv3-its, \
> numa: Enable workaround for Cavium thunderx erratum 23144
> 
> Thanks,
> Ashok
> 
> CC: marc.zyngier at arm.com
> CC: rrichter at caviumnetworks.com
> CC: gkulkarni at caviumnetworks.com
> CC: jchandra at broadcom.com
> 
>  drivers/irqchip/irq-gic-v3-its.c |   12 ++++++++----
>  1 files changed, 8 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 75f258f..9a187c0 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -860,6 +860,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
>  		int alloc_pages;
>  		u64 tmp;
>  		void *base;
> +		struct page *pg;
>  
>  		if (type == GITS_BASER_TYPE_NONE)
>  			continue;
> @@ -897,11 +898,13 @@ retry_alloc_baser:
>  				node_name, order, alloc_pages);
>  		}
>  
> -		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
> -		if (!base) {
> +		pg = alloc_pages_node(its->numa_node,
> +				      GFP_KERNEL | __GFP_ZERO, order);
> +		if (!pg) {
>  			err = -ENOMEM;
>  			goto out_free;
>  		}
> +		base = page_address(pg);
>  
>  		its->tables[i].base = base;
>  		its->tables[i].order = order;
> @@ -1184,7 +1187,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
>  	nr_ites = max(2UL, roundup_pow_of_two(nvecs));
>  	sz = nr_ites * its->ite_size;
>  	sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
> -	itt = kzalloc(sz, GFP_KERNEL);
> +	itt = kzalloc_node(sz, GFP_KERNEL, its->numa_node);
>  	lpi_map = its_lpi_alloc_chunks(nvecs, &lpi_base, &nr_lpis);
>  	if (lpi_map)
>  		col_map = kzalloc(sizeof(*col_map) * nr_lpis, GFP_KERNEL);
> @@ -1526,7 +1529,8 @@ static int __init its_probe(struct device_node *node,
>  	its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
>  	its->numa_node = of_node_to_nid(node);
>  
> -	its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
> +	its->cmd_base = kzalloc_node(ITS_CMD_QUEUE_SZ, GFP_KERNEL,
> +				     its->numa_node);
>  	if (!its->cmd_base) {
>  		err = -ENOMEM;
>  		goto out_free_its;
> 

Does this lead to an improvement you've actually measured? If so, I'd
like to see numbers to back it up. Or is that purely theoretical?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From ashoks at broadcom.com  Tue May  3 01:05:25 2016
From: ashoks at broadcom.com (Ashok Kumar)
Date: Tue, 3 May 2016 01:05:25 -0700
Subject: [RFC PATCH] irqchip/gic-v3-its: Allocate ITS tables from
 corresponding node memory
In-Reply-To: <57285933.3060300@arm.com>
References: <1461932322-1206-1-git-send-email-ashoks@broadcom.com>
 <57285933.3060300@arm.com>
Message-ID: <20160503080524.GA12258@ashok.sekar@broadcom.com>

On Tue, May 03, 2016 at 08:54:27AM +0100, Marc Zyngier wrote:
> [Please CC LKML and all the irqchip maintainers on these patches]
> 
> On 29/04/16 13:18, Ashok Kumar wrote:
> > In the case of systems having multi socket and multi ITS, allocating
> > local node memory for ITS device table, collection table, interrupt
> > translation table and command queue will help in reducing inter-chip
> > traffic even though they(except command queue) could be cached in the GIC.
> > 
> > Signed-off-by: Ashok Kumar <ashoks at broadcom.com>
> > ---
> > This patch is created on top of Cavium thunderx erratum 23144 patch [1].
> > 
> > I am not sure how to do this for ACPI as GIC ITS ID in MADT doesn't map to
> > _PXM. Am I missing something here? Any thoughts?
> 
> Indeed, and SRAT doesn't provide any valuable information either.
> 
> > 
> > [1] https://lkml.org/lkml/2016/4/15/830 - [PATCH v5] irqchip, gicv3-its, \
> > numa: Enable workaround for Cavium thunderx erratum 23144
> > 
> > Thanks,
> > Ashok
> > 
> > CC: marc.zyngier at arm.com
> > CC: rrichter at caviumnetworks.com
> > CC: gkulkarni at caviumnetworks.com
> > CC: jchandra at broadcom.com
> > 
> >  drivers/irqchip/irq-gic-v3-its.c |   12 ++++++++----
> >  1 files changed, 8 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> > index 75f258f..9a187c0 100644
> > --- a/drivers/irqchip/irq-gic-v3-its.c
> > +++ b/drivers/irqchip/irq-gic-v3-its.c
> > @@ -860,6 +860,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
> >  		int alloc_pages;
> >  		u64 tmp;
> >  		void *base;
> > +		struct page *pg;
> >  
> >  		if (type == GITS_BASER_TYPE_NONE)
> >  			continue;
> > @@ -897,11 +898,13 @@ retry_alloc_baser:
> >  				node_name, order, alloc_pages);
> >  		}
> >  
> > -		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
> > -		if (!base) {
> > +		pg = alloc_pages_node(its->numa_node,
> > +				      GFP_KERNEL | __GFP_ZERO, order);
> > +		if (!pg) {
> >  			err = -ENOMEM;
> >  			goto out_free;
> >  		}
> > +		base = page_address(pg);
> >  
> >  		its->tables[i].base = base;
> >  		its->tables[i].order = order;
> > @@ -1184,7 +1187,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
> >  	nr_ites = max(2UL, roundup_pow_of_two(nvecs));
> >  	sz = nr_ites * its->ite_size;
> >  	sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
> > -	itt = kzalloc(sz, GFP_KERNEL);
> > +	itt = kzalloc_node(sz, GFP_KERNEL, its->numa_node);
> >  	lpi_map = its_lpi_alloc_chunks(nvecs, &lpi_base, &nr_lpis);
> >  	if (lpi_map)
> >  		col_map = kzalloc(sizeof(*col_map) * nr_lpis, GFP_KERNEL);
> > @@ -1526,7 +1529,8 @@ static int __init its_probe(struct device_node *node,
> >  	its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
> >  	its->numa_node = of_node_to_nid(node);
> >  
> > -	its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
> > +	its->cmd_base = kzalloc_node(ITS_CMD_QUEUE_SZ, GFP_KERNEL,
> > +				     its->numa_node);
> >  	if (!its->cmd_base) {
> >  		err = -ENOMEM;
> >  		goto out_free_its;
> > 
> 
> Does this lead to an improvement you've actually measured? If so, I'd
> like to see numbers to back it up. Or is that purely theoretical?
It is purely theoretical. I don't have the hardware setup to test it.

Thanks,
Ashok
> 
> Thanks,
> 
> 	M.
> -- 
> Jazz is not dead. It just smells funny...


From t-kristo at ti.com  Tue May  3 01:16:38 2016
From: t-kristo at ti.com (Tero Kristo)
Date: Tue, 3 May 2016 11:16:38 +0300
Subject: [PATCH v2 2/3] ARM: DRA7x: dts: Update the OSC_32K_CLK frequency
In-Reply-To: <1462209123-7332-3-git-send-email-Linux.HWI@garmin.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
 <1462209123-7332-3-git-send-email-Linux.HWI@garmin.com>
Message-ID: <57285E66.2000708@ti.com>

On 02/05/16 20:12, J.D. Schroeder wrote:
> From: "J.D. Schroeder" <jay.schroeder at garmin.com>
>
> This commit updates the OSC_32K_CLK (secure_32k_clk_src_ck) frequency
> from the precise 32kHz frequency (i.e., 32.768 kHz) to a more
> accurate frequency of ~34.6 kHz. Actual measured frequencies of the
> clock vary from processor to processor anywhere from 34.4 kHz up to
> 34.8 kHz. Note that the ~34 kHz frequency clock is generated
> internally by the processor, not an input to the processor. This
> change makes it more clear that the consumer of the
> secure_32k_clk_src_ck will not get a precise 32.768 kHz frequency
> output.
>
> Signed-off-by: J.D. Schroeder <jay.schroeder at garmin.com>
> Reviewed-by: Trenton Andres <trenton.andres at garmin.com>
> ---
>   arch/arm/boot/dts/dra7xx-clocks.dtsi | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi
> index 3f0c61d..f7ec976 100644
> --- a/arch/arm/boot/dts/dra7xx-clocks.dtsi
> +++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi
> @@ -95,7 +95,7 @@
>   	secure_32k_clk_src_ck: secure_32k_clk_src_ck {
>   		#clock-cells = <0>;
>   		compatible = "fixed-clock";
> -		clock-frequency = <32768>;
> +		clock-frequency = <34600>; /* approximate frequency */
>   	};
>
>   	sys_clk32_crystal_ck: sys_clk32_crystal_ck {
>

I still don't agree with this patch. The actual frequency can drift much 
more, you are just seeing this number at your setup. There is some 
internal discussion going on in TI about this, but I can't share any 
data on this yet.

-Tero


From daniel at ffwll.ch  Tue May  3 01:18:06 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Tue, 3 May 2016 10:18:06 +0200
Subject: [PATCH] drm/fsl-dcu: add COMMON_CLK dependency
In-Reply-To: <96882621acf64dca8d6c1d2f25307385@agner.ch>
References: <1462186839-2224021-1-git-send-email-arnd@arndb.de>
 <96882621acf64dca8d6c1d2f25307385@agner.ch>
Message-ID: <20160503081806.GE14148@phenom.ffwll.local>

On Mon, May 02, 2016 at 02:22:04PM -0700, Stefan Agner wrote:
> On 2016-05-02 04:00, Arnd Bergmann wrote:
> > The fsl dcu now uses the clk-provider interfaces, which are not available
> > when CONFIG_COMMON_CLK is disabled:
> > 
> > drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c: In function 'fsl_dcu_drm_probe':
> > drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c:362:20: error: implicit
> > declaration of function '__clk_get_name'
> > [-Werror=implicit-function-declaration]
> >   pix_clk_in_name = __clk_get_name(pix_clk_in);
> > 
> > This adds a Kconfig dependency to prevent the driver from being enabled
> > in this case.
> > 
> > Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> > Fixes: 2d701449bce1 ("drm/fsl-dcu: use common clock framework for
> > pixel clock divider")
> 
> Oh right, thx!
> 
> Acked-by: Stefan Agner <stefan at agner.ch>
> 
> @Dave, can you pick that up directly or do you prefer a pull request?

Smashed into drm-misc, thanks.
-Daniel

> 
> --
> Stefan
> 
> > ---
> >  drivers/gpu/drm/fsl-dcu/Kconfig | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig
> > index c78cf3f605d0..b9c714de6e40 100644
> > --- a/drivers/gpu/drm/fsl-dcu/Kconfig
> > +++ b/drivers/gpu/drm/fsl-dcu/Kconfig
> > @@ -1,6 +1,6 @@
> >  config DRM_FSL_DCU
> >  	tristate "DRM Support for Freescale DCU"
> > -	depends on DRM && OF && ARM
> > +	depends on DRM && OF && ARM && COMMON_CLK
> >  	select BACKLIGHT_CLASS_DEVICE
> >  	select BACKLIGHT_LCD_SUPPORT
> >  	select DRM_KMS_HELPER

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From christoffer.dall at linaro.org  Tue May  3 01:21:24 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 3 May 2016 10:21:24 +0200
Subject: [PATCH v6 00/10] arm64: Add support for KVM with ACPI
In-Reply-To: <20160502125414.GR27057@io.lakedaemon.net>
References: <1460388780-914-1-git-send-email-julien.grall@arm.com>
 <57220C73.7010900@arm.com>
 <20160502125414.GR27057@io.lakedaemon.net>
Message-ID: <20160503082124.GA17923@cbox>

On Mon, May 02, 2016 at 12:54:14PM +0000, Jason Cooper wrote:
> On Thu, Apr 28, 2016 at 02:13:23PM +0100, Marc Zyngier wrote:
> > [+ Thomas, Jason]
> > 
> > Do you have any objection against this going through the KVM tree? The
> > dependencies are rather intricate, and Daniel gave us his green light
> > already for the clocksource part.
> > 
> > If you'd rather maintain the usual flow, please let us know and we'll
> > deal with it.
> 
> I've no objection.
> 
> Acked-by: Jason Cooper <jason at lakedaemon.net>
> 
Just to be clear, that's on all the irqchip patches, right?

Thanks!
-Christoffer


From panand at redhat.com  Tue May  3 01:20:42 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue,  3 May 2016 13:50:42 +0530
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
Message-ID: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>

Currently only WOR is used to program both first and second stage which
provided very limited range of timeout.

This patch uses WCV as well to achieve higher range of timeout. This patch
programs max_timeout as 255, but that can be increased further as well.

Following testing shows that we can happily achieve 40 second default timeout.

 # modprobe sbsa_gwdt action=1
 [  131.187562] sbsa-gwdt sbsa-gwdt.0: Initialized with 40s timeout @ 250000000 Hz, action=1.
 # cd /sys/class/watchdog/watchdog0/
 # cat state
 inactive
 # cat /dev/watchdog0
 cat: /dev/watchdog0: Invalid argument
 [  161.710593] watchdog: watchdog0: watchdog did not stop!
 # cat state
 active
 # cat timeout
 40
 # cat timeleft
 38
 # cat timeleft
 25
 # cat /dev/watchdog0
 cat: /dev/watchdog0: Invalid argument
 [  184.931030] watchdog: watchdog0: watchdog did not stop!
 # cat timeleft
 37
 # cat timeleft
 21
 ...
 ...
 # cat timeleft
 1

panic() is called upon timeout of 40s. See timestamp of last kick (cat) and
next panic() message.

 [  224.939065] Kernel panic - not syncing: SBSA Watchdog timeout

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 drivers/watchdog/sbsa_gwdt.c | 83 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 62 insertions(+), 21 deletions(-)

diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
index ad383f6f15fc..529dd5e99fcd 100644
--- a/drivers/watchdog/sbsa_gwdt.c
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -35,17 +35,23 @@
  *
  * SBSA GWDT:
  * if action is 1 (the two stages mode):
- * |--------WOR-------WS0--------WOR-------WS1
+ * |--------WCV-------WS0--------WCV-------WS1
  * |----timeout-----(panic)----timeout-----reset
  *
  * if action is 0 (the single stage mode):
- * |------WOR-----WS0(ignored)-----WOR------WS1
+ * |------WCV-----WS0(ignored)-----WOR------WS1
  * |--------------timeout-------------------reset
  *
- * Note: Since this watchdog timer has two stages, and each stage is determined
- * by WOR, in the single stage mode, the timeout is (WOR * 2); in the two
- * stages mode, the timeout is WOR. The maximum timeout in the two stages mode
- * is half of that in the single stage mode.
+ * Note: This watchdog timer has two stages. If action is 0, first stage is
+ * determined by directly programming WCV and second by WOR. When first
+ * timeout is reached, WS0 is triggered and WCV is reloaded with value in
+ * WOR. WS0 interrupt will be ignored, then the second watch period starts;
+ * when second timeout is reached, then WS1 is triggered, system resets. WCV
+ * and WOR are programmed in such a way that total time corresponding to
+ * WCV+WOR becomes equivalent to user programmed "timeout".
+ * If action is 1, then we expect to call panic() at user programmed
+ * "timeout". Therefore, we program both first and second stage using WCV
+ * only.
  *
  */
 
@@ -95,7 +101,17 @@ struct sbsa_gwdt {
 	void __iomem		*control_base;
 };
 
-#define DEFAULT_TIMEOUT		10 /* seconds */
+/*
+ * Max Timeout Can be in days, but 255 seconds seems reasonable for all use
+ * cases
+ */
+#define MAX_TIMEOUT		255
+
+/* Default timeout is 40 seconds, which is the 1st + 2nd watch periods when
+ * action is 0. When action is 1 then both 1st and 2nd watch periods will
+ * be of 40 seconds.
+ */
+#define DEFAULT_TIMEOUT		40 /* seconds */
 
 static unsigned int timeout;
 module_param(timeout, uint, 0);
@@ -127,20 +143,21 @@ static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
 				 unsigned int timeout)
 {
 	struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
+	u64 timeout_1, timeout_2;
 
 	wdd->timeout = timeout;
 
 	if (action)
-		writel(gwdt->clk * timeout,
-		       gwdt->control_base + SBSA_GWDT_WOR);
+		timeout_1 = (u64)gwdt->clk * timeout;
 	else
-		/*
-		 * In the single stage mode, The first signal (WS0) is ignored,
-		 * the timeout is (WOR * 2), so the WOR should be configured
-		 * to half value of timeout.
-		 */
-		writel(gwdt->clk / 2 * timeout,
-		       gwdt->control_base + SBSA_GWDT_WOR);
+		timeout_1 = (u64)gwdt->clk * (timeout - wdd->min_timeout);
+
+	/* when action=1, timeout_2 will be overwritten in ISR */
+	timeout_2 = (u64)gwdt->clk * wdd->min_timeout;
+
+	writel(timeout_2, gwdt->control_base + SBSA_GWDT_WOR);
+	writeq(timeout_1 + arch_counter_get_cntvct(),
+		gwdt->control_base + SBSA_GWDT_WCV);
 
 	return 0;
 }
@@ -172,12 +189,17 @@ static int sbsa_gwdt_keepalive(struct watchdog_device *wdd)
 	struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
 
 	/*
-	 * Writing WRR for an explicit watchdog refresh.
-	 * You can write anyting (like 0).
+	 * play safe: program WOR with max value so that we have sufficient
+	 * time to overwrite them after explicit refresh
 	 */
+	writel(U32_MAX, gwdt->control_base + SBSA_GWDT_WOR);
+	/*
+	* Writing WRR for an explicit watchdog refresh.
+	* You can write anyting (like 0).
+	*/
 	writel(0, gwdt->refresh_base + SBSA_GWDT_WRR);
 
-	return 0;
+	return sbsa_gwdt_set_timeout(wdd, wdd->timeout);;
 }
 
 static unsigned int sbsa_gwdt_status(struct watchdog_device *wdd)
@@ -193,10 +215,15 @@ static int sbsa_gwdt_start(struct watchdog_device *wdd)
 {
 	struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
 
+	/*
+	 * play safe: program WOR with max value so that we have sufficient
+	 * time to overwrite them after explicit refresh
+	 */
+	writel(U32_MAX, gwdt->control_base + SBSA_GWDT_WOR);
 	/* writing WCS will cause an explicit watchdog refresh */
 	writel(SBSA_GWDT_WCS_EN, gwdt->control_base + SBSA_GWDT_WCS);
 
-	return 0;
+	return sbsa_gwdt_set_timeout(wdd, wdd->timeout);;
 }
 
 static int sbsa_gwdt_stop(struct watchdog_device *wdd)
@@ -211,6 +238,20 @@ static int sbsa_gwdt_stop(struct watchdog_device *wdd)
 
 static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
 {
+	struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
+	struct watchdog_device *wdd = &gwdt->wdd;
+	u64 timeout_2 = (u64)gwdt->clk * wdd->timeout;
+
+	/*
+	 * Since we can not trust system at this moment, therefore re-write
+	 * WCV only if wdd->timeout <= MAX_TIMEOUT to avoid a corner
+	 * scenario when we might have corrupted wdd->timeout values at
+	 * this point.
+	 */
+	if (wdd->timeout <= MAX_TIMEOUT)
+		writeq(timeout_2 + arch_counter_get_cntvct(),
+			gwdt->control_base + SBSA_GWDT_WCV);
+
 	panic(WATCHDOG_NAME " timeout");
 
 	return IRQ_HANDLED;
@@ -273,7 +314,7 @@ static int sbsa_gwdt_probe(struct platform_device *pdev)
 	wdd->info = &sbsa_gwdt_info;
 	wdd->ops = &sbsa_gwdt_ops;
 	wdd->min_timeout = 1;
-	wdd->max_timeout = U32_MAX / gwdt->clk;
+	wdd->max_timeout = MAX_TIMEOUT;
 	wdd->timeout = DEFAULT_TIMEOUT;
 	watchdog_set_drvdata(wdd, gwdt);
 	watchdog_set_nowayout(wdd, nowayout);
-- 
2.5.5



From andre.przywara at arm.com  Tue May  3 01:26:23 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue, 3 May 2016 09:26:23 +0100
Subject: [PATCH v2 19/54] KVM: arm/arm64: vgic-new: Implement
In-Reply-To: <57274715.8080801@linaro.org>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-20-git-send-email-andre.przywara@arm.com>
 <57274715.8080801@linaro.org>
Message-ID: <572860AF.5000202@arm.com>

Hi Eric,

On 02/05/16 13:24, Eric Auger wrote:
> Hi Andre,
> 
> minor comment: patch title has been altered since v1, should be
> 
> KVM: arm/arm64: vgic-new: Implement kvm_vgic_vcpu_pending_irq

Indeed, that was line-broken accidentally when I added the Changelog.
Thanks for pointing out!

Cheers,
Andre.

> On 04/28/2016 06:45 PM, Andre Przywara wrote:
>> From: Eric Auger <eric.auger at linaro.org>
>>
>> Tell KVM whether a particular VCPU has an IRQ that needs handling
>> in the guest. This is used to decide whether a VCPU is runnable.
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - return false if distributor is disabled
>> - add vgic_kick_vcpus() implementations
>>
>>  include/kvm/vgic/vgic.h  |  2 ++
>>  virt/kvm/arm/vgic/vgic.c | 40 ++++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic.h |  1 +
>>  3 files changed, 43 insertions(+)
>>
>> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
>> index 5fae4a9..2615205 100644
>> --- a/include/kvm/vgic/vgic.h
>> +++ b/include/kvm/vgic/vgic.h
>> @@ -184,6 +184,8 @@ struct vgic_cpu {
>>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>>  			bool level);
>>  
>> +int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
>> +
>>  #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
>>  #define vgic_initialized(k)	(false)
>>  #define vgic_ready(k)		((k)->arch.vgic.ready)
>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>> index ae52928..eeb766e 100644
>> --- a/virt/kvm/arm/vgic/vgic.c
>> +++ b/virt/kvm/arm/vgic/vgic.c
>> @@ -519,3 +519,43 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
>>  	vgic_flush_lr_state(vcpu);
>>  	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
>>  }
>> +
>> +int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
>> +{
>> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
>> +	struct vgic_irq *irq;
>> +	bool pending = false;
>> +
>> +	if (!vcpu->kvm->arch.vgic.enabled)
>> +		return false;
>> +
>> +	spin_lock(&vgic_cpu->ap_list_lock);
>> +
>> +	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
>> +		spin_lock(&irq->irq_lock);
>> +		pending = irq->pending && irq->enabled;
>> +		spin_unlock(&irq->irq_lock);
>> +
>> +		if (pending)
>> +			break;
>> +	}
>> +
>> +	spin_unlock(&vgic_cpu->ap_list_lock);
>> +
>> +	return pending;
>> +}
>> +
>> +void vgic_kick_vcpus(struct kvm *kvm)
>> +{
>> +	struct kvm_vcpu *vcpu;
>> +	int c;
>> +
>> +	/*
>> +	 * We've injected an interrupt, time to find out who deserves
>> +	 * a good kick...
>> +	 */
>> +	kvm_for_each_vcpu(c, vcpu, kvm) {
>> +		if (kvm_vgic_vcpu_pending_irq(vcpu))
>> +			kvm_vcpu_kick(vcpu);
>> +	}
>> +}
>> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>> index 81b1a20..0c92cda 100644
>> --- a/virt/kvm/arm/vgic/vgic.h
>> +++ b/virt/kvm/arm/vgic/vgic.h
>> @@ -21,6 +21,7 @@
>>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>>  			      u32 intid);
>>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
>> +void vgic_kick_vcpus(struct kvm *kvm);
>>  
>>  void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
>>  void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
>>
> 


From andre.przywara at arm.com  Tue May  3 01:26:40 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue, 3 May 2016 09:26:40 +0100
Subject: [PATCH v2 17/54] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <20160502131637.054b6b23@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-18-git-send-email-andre.przywara@arm.com>
 <20160502131637.054b6b23@arm.com>
Message-ID: <572860C0.2030407@arm.com>

On 02/05/16 13:16, Marc Zyngier wrote:
> On Thu, 28 Apr 2016 17:45:36 +0100
> Andre Przywara <andre.przywara at arm.com> wrote:
> 
>> From: Marc Zyngier <marc.zyngier at arm.com>
>>
>> Processing maintenance interrupts and accessing the list registers
>> are dependent on the host's GIC version.
>> Introduce vgic-v2.c to contain GICv2 specific functions.
>> Implement the GICv2 specific code for syncing the emulation state
>> into the VGIC registers.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - remove explicit LR_STATE clearing on maintenance interrupt handling
>> - improve documentation for vgic_v2_populate_lr()
>> - remove WARN_ON on non-edge IRQs in maintenance interrupts
>> - simplify multi-CPU source SGI handling
>>
>> Changelog v1 .. v2:
>> - inject the IRQ priority into the list register
>>
>>  include/linux/irqchip/arm-gic.h |   1 +
>>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic.c        |  19 ++---
>>  virt/kvm/arm/vgic/vgic.h        |   6 ++
>>  4 files changed, 194 insertions(+), 10 deletions(-)
>>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
>>
> 
> [...]
> 
>> @@ -441,14 +447,12 @@ static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
>>  static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
>>  {
>>  	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
>> -	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>> -	u32 model = dist->vgic_model;
>>  	struct vgic_irq *irq;
>>  	int count = 0;
>>  
>>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(vgic_cpu->ap_list_lock));
>>  
>> -	if (unlikely(!dist->enabled))
>> +	if (unlikely(!vcpu->kvm->arch.vgic.enabled))
>>  		goto out_clean;
>>  
>>  	if (compute_ap_list_depth(vcpu) > kvm_vgic_global_state.nr_lr) {
>> @@ -466,14 +470,9 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
>>  		 * If we get an SGI with multiple sources, try to get
>>  		 * them in all at once.
>>  		 */
>> -		if (model == KVM_DEV_TYPE_ARM_VGIC_V2 &&
>> -		    vgic_irq_is_sgi(irq->intid)) {
>> -			while (irq->source &&
>> -			       count < kvm_vgic_global_state.nr_lr)
>> -				vgic_populate_lr(vcpu, irq, count++);
>> -		} else {
>> +		do {
>>  			vgic_populate_lr(vcpu, irq, count++);
>> -		}
>> +		} while (irq->source && count < kvm_vgic_global_state.nr_lr);
>>  
>>  next:
> 
> Most, if not all of the changes in this function should be folded in the
> previous patch, as we only have generic code in this file (this looks
> like a leftover from an earlier rework).

Oh dear, you are totally right. Sorry for the mess!

Will fix it!

Cheers,
Andre.


From shawnguo at kernel.org  Tue May  3 01:27:44 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 16:27:44 +0800
Subject: [PATCH v2] ARM: dts: imx28-m28: Remove unneeded partition nodes
In-Reply-To: <1461770872-26510-1-git-send-email-fabio.estevam@nxp.com>
References: <1461770872-26510-1-git-send-email-fabio.estevam@nxp.com>
Message-ID: <20160503082744.GB5874@tiger>

On Wed, Apr 27, 2016 at 12:27:52PM -0300, Fabio Estevam wrote:
> mtdparts is passed from command line, so there is no need to have a
> default partitioning in device-tree.
> 
> Suggested-by: Marek Vasut <marex at denx.de>
> Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>

Applied, thanks.


From shawnguo at kernel.org  Tue May  3 01:32:53 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 16:32:53 +0800
Subject: [PATCH] clk: imx: fix ahb clock mux 1
In-Reply-To: <1461877623-26838-1-git-send-email-stefan@agner.ch>
References: <1461877623-26838-1-git-send-email-stefan@agner.ch>
Message-ID: <20160503083253.GC5874@tiger>

On Thu, Apr 28, 2016 at 02:07:03PM -0700, Stefan Agner wrote:
> The clock parent of the AHB root clock when using mux option 1
> is the SYS PLL 270MHz clock. This is specified in  Table 5-11
> Clock Root Table of the i.MX 7Dual Applications Processor
> Reference Manual.
> 
> While it could be a documentation error, the 270MHz parent is
> also mentioned in the boot ROM configuration in Table 6-28: The
> clock is by default at 135MHz due to a POST_PODF value of 1
> (=> divider of 2).
> 
> Signed-off-by: Stefan Agner <stefan at agner.ch>

Anson, Frank,

Can you guys confirm this change is correct?

Shawn

> ---
> Hi Shawn,
> 
> I did not found a clock which was based on this clock which I
> could measure externally... But the change is backed by the
> documentation.
> 
> --
> Stefan
> 
>  drivers/clk/imx/clk-imx7d.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
> index 7912be8..5229968 100644
> --- a/drivers/clk/imx/clk-imx7d.c
> +++ b/drivers/clk/imx/clk-imx7d.c
> @@ -56,7 +56,7 @@ static const char *nand_usdhc_bus_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
>  	"pll_sys_pfd2_135m_clk", "pll_sys_pfd6_clk", "pll_enet_250m_clk",
>  	"pll_audio_main_clk", };
>  
> -static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
> +static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
>  	"pll_dram_533m_clk", "pll_sys_pfd0_392m_clk",
>  	"pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_main_clk",
>  	"pll_video_main_clk", };
> -- 
> 2.8.0
> 
> 


From marc.zyngier at arm.com  Tue May  3 01:34:03 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 09:34:03 +0100
Subject: [PATCH v2 2/4] irqchip: add LPC32xx interrupt controller driver
In-Reply-To: <57228B68.8030706@mleia.com>
References: <1461545990-25560-1-git-send-email-vz@mleia.com>
 <1461546038-25668-1-git-send-email-vz@mleia.com>
 <1461678082.9433.3.camel@localhost> <57228B68.8030706@mleia.com>
Message-ID: <5728627B.1020602@arm.com>

On 28/04/16 23:15, Vladimir Zapolskiy wrote:
> On 26.04.2016 16:41, Sylvain Lemieux wrote:
>> Hi Vladimir,
>>
>> On Mon, 2016-04-25 at 04:00 +0300, Vladimir Zapolskiy wrote:
>>> The change adds improved support of NXP LPC32xx MIC, SIC1 and SIC2
>>> interrupt controllers.
>>>
>>> This is a list of new features in comparison to the legacy driver:
>>> * irq types are taken from device tree settings, no more need to
>>>   hardcode them,
>>> * old driver is based on irq_domain_add_legacy, which causes problems
>>>   with handling MIC hardware interrupt 0 produced by SIC1,
>>> * there is one driver for MIC, SIC1 and SIC2, no more need to handle
>>>   them separately, e.g. have two separate handlers for SIC1 and SIC2,
>>> * the driver does not have any dependencies on hardcoded register
>>>   offsets,
>>> * the driver is much simpler for maintenance,
>>> * SPARSE_IRQS option is supported.
>>>
>>> Legacy LPC32xx interrupt controller driver was broken since commit
>>> 76ba59f8366f ("genirq: Add irq_domain-aware core IRQ handler"), which
>>> requires a private interrupt handler, otherwise any SIC1 generated
>>> interrupt (mapped to MIC hwirq 0) breaks the kernel with the message
>>> "unexpected IRQ trap at vector 00".
>>>
>>> The change disables compilation of a legacy driver found at
>>> arch/arm/mach-lpc32xx/irq.c, the file will be removed in a separate
>>> commit.
>>>
>>> Signed-off-by: Vladimir Zapolskiy <vz at mleia.com>
>>> ---
>>> Changes from v1 to v2:
>>> * added chained_irq_{enter,exit} for SIC chained handler,
>>> * use {writel,readl}_relaxed flavour of io access functions,
>>> * changed anchor data type to access iomem from struct irq_domain
>>>   to private struct lpc32xx_irq_chip,
>>> * do not read irq status register twice on every irq event,
>>> * resource deallocation fixes on error path of irqchip driver init,
>>> * removed handling of "interrupt-controller-name" property, name
>>>   is constructed from mic/sic type and controller's physical address,
>>> * minor improvements (renames, __ffs instead of ffs, etc.)
>>>
>>> Many kudos to Marc for review of v1.
>>>
>>>  arch/arm/Kconfig                |   2 +
>>>  arch/arm/mach-lpc32xx/phy3250.c |   1 -
>>>  drivers/irqchip/Makefile        |   1 +
>>>  drivers/irqchip/irq-lpc32xx.c   | 238 ++++++++++++++++++++++++++++++++++++++++
>>>  4 files changed, 241 insertions(+), 1 deletion(-)
>>>  create mode 100644 drivers/irqchip/irq-lpc32xx.c
>>>
>> I tested the driver on a custom LPC3250 board; I was having at
>> least 1 interrupt generated from each source (MIC/SIC1/SIC2).
>>
>> Tested-by: Sylvain Lemieux <slemieux.tyco at gmail.com>
>>
> 
> Thomas, Marc, Jason, Russell,
> 
> in your opinion would it be still possible to accept this change v2 2/4 for v4.7?

I'll queue them.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From christoffer.dall at linaro.org  Tue May  3 01:36:51 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 3 May 2016 10:36:51 +0200
Subject: [PATCH] arm64: kvm: Fix kvm teardown for systems using the
 extended idmap
In-Reply-To: <20160502130535.19b20b79@arm.com>
References: <1461775633-29715-1-git-send-email-james.morse@arm.com>
 <1461950823-9790-1-git-send-email-james.morse@arm.com>
 <20160502130535.19b20b79@arm.com>
Message-ID: <20160503083651.GB17923@cbox>

On Mon, May 02, 2016 at 01:05:35PM +0100, Marc Zyngier wrote:
> On Fri, 29 Apr 2016 18:27:03 +0100
> James Morse <james.morse at arm.com> wrote:
> 
> Hi James,
> 
> > If memory is located above 1<<VA_BITS, kvm adds an extra level to its page
> > tables, merging the runtime tables and boot tables that contain the idmap.
> > This lets us avoid the trampoline dance during initialisation.
> > 
> > This also means there is no trampoline page mapped, so
> > __cpu_reset_hyp_mode() can't call __kvm_hyp_reset() in this page. The good
> > news is the idmap is still mapped, so we don't need the trampoline page.
> > The bad news is we can't call it directly as the idmap is above
> > HYP_PAGE_OFFSET, so its address is masked by kvm_call_hyp.
> > 
> > Add a function __extended_idmap_trampoline which will branch into
> > __kvm_hyp_reset in the idmap, change kvm_hyp_reset_entry() to return
> > this address if __kvm_cpu_uses_extended_idmap(). In this case
> > __kvm_hyp_reset() will still switch to the boot tables (which are the
> > merged tables that were already in use), and branch into the idmap (where
> > it already was).
> > 
> > This fixes boot failures on these systems, where we fail to execute the
> > missing trampoline page when tearing down kvm in init_subsystems():
> > [    2.508922] kvm [1]: 8-bit VMID
> > [    2.512057] kvm [1]: Hyp mode initialized successfully
> > [    2.517242] kvm [1]: interrupt-controller at e1140000 IRQ13
> > [    2.522622] kvm [1]: timer IRQ3
> > [    2.525783] Kernel panic - not syncing: HYP panic:
> > [    2.525783] PS:200003c9 PC:0000007ffffff820 ESR:86000005
> > [    2.525783] FAR:0000007ffffff820 HPFAR:00000000003ffff0 PAR:0000000000000000
> > [    2.525783] VCPU:          (null)
> > [    2.525783]
> > [    2.547667] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G        W       4.6.0-rc5+ #1
> > [    2.555137] Hardware name: Default string Default string/Default string, BIOS ROD0084E 09/03/2015
> > [    2.563994] Call trace:
> > [    2.566432] [<ffffff80080888d0>] dump_backtrace+0x0/0x240
> > [    2.571818] [<ffffff8008088b24>] show_stack+0x14/0x20
> > [    2.576858] [<ffffff80083423ac>] dump_stack+0x94/0xb8
> > [    2.581899] [<ffffff8008152130>] panic+0x10c/0x250
> > [    2.586677] [<ffffff8008152024>] panic+0x0/0x250
> > [    2.591281] SMP: stopping secondary CPUs
> > [    3.649692] SMP: failed to stop secondary CPUs 0-2,4-7
> > [    3.654818] Kernel Offset: disabled
> > [    3.658293] Memory Limit: none
> > [    3.661337] ---[ end Kernel panic - not syncing: HYP panic:
> > [    3.661337] PS:200003c9 PC:0000007ffffff820 ESR:86000005
> > [    3.661337] FAR:0000007ffffff820 HPFAR:00000000003ffff0 PAR:0000000000000000
> > [    3.661337] VCPU:          (null)
> > [    3.661337]
> > 
> > 
> > Reported-by: Will Deacon <will.deacon at arm.com>
> > Signed-off-by: James Morse <james.morse at arm.com>
> > ---
> >  arch/arm64/include/asm/kvm_host.h |  3 ++-
> >  arch/arm64/kvm/hyp-init.S         |  5 +++++
> >  arch/arm64/kvm/hyp/entry.S        | 19 +++++++++++++++++++
> >  arch/arm64/kvm/reset.c            | 30 +++++++++++++++++++++++-------
> >  4 files changed, 49 insertions(+), 8 deletions(-)
> > 
> > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > index b6f194d9f6b2..88a34670ddef 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -46,7 +46,8 @@
> >  int __attribute_const__ kvm_target_cpu(void);
> >  int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
> >  int kvm_arch_dev_ioctl_check_extension(long ext);
> > -phys_addr_t kvm_hyp_reset_entry(void);
> > +unsigned long kvm_hyp_reset_entry(void);
> > +void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t idmap_start);
> >  
> >  struct kvm_arch {
> >  	/* The VMID generation used for the virt. memory system */
> > diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
> > index 44ec4cb23ae7..a873a6d8be90 100644
> > --- a/arch/arm64/kvm/hyp-init.S
> > +++ b/arch/arm64/kvm/hyp-init.S
> > @@ -140,6 +140,11 @@ merged:
> >  ENDPROC(__kvm_hyp_init)
> >  
> >  	/*
> > +	 * Reset kvm back to the hyp stub. This is the trampoline dance in
> > +	 * reverse. If kvm used an extended idmap, __extended_idmap_trampoline
> > +	 * calls this code directly in the idmap. In this case switching to the
> > +	 * boot tables is a no-op.
> > +	 *
> >  	 * x0: HYP boot pgd
> >  	 * x1: HYP phys_idmap_start
> >  	 */
> > diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
> > index ce9e5e5f28cf..70254a65bd5b 100644
> > --- a/arch/arm64/kvm/hyp/entry.S
> > +++ b/arch/arm64/kvm/hyp/entry.S
> > @@ -164,3 +164,22 @@ alternative_endif
> >  
> >  	eret
> >  ENDPROC(__fpsimd_guest_restore)
> > +
> > +/*
> > + * When using the extended idmap, we don't have a trampoline page we can use
> > + * while we switch pages tables during __kvm_hyp_reset. Accessing the idmap
> > + * directly would be ideal, but if we're using the extended idmap then the
> > + * idmap is located above HYP_PAGE_OFFSET, and the address will be masked by
> > + * kvm_call_hyp using kern_hyp_va.
> > + *
> > + * x0: HYP boot pgd
> > + * x1: HYP phys_idmap_start
> > + */
> > +ENTRY(__extended_idmap_trampoline)
> > +	mov	x4, x1
> > +	adr_l	x3, __kvm_hyp_reset
> > +
> > +	/* insert __kvm_hyp_reset()s offset into phys_idmap_start */
> > +	bfi	x4, x3, #0, #PAGE_SHIFT
> > +	br	x4
> > +ENDPROC(__extended_idmap_trampoline)
> > diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> > index 4062e6dd4cc1..b1ad730e1567 100644
> > --- a/arch/arm64/kvm/reset.c
> > +++ b/arch/arm64/kvm/reset.c
> > @@ -135,12 +135,28 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
> >  
> >  extern char __hyp_idmap_text_start[];
> >  
> > -phys_addr_t kvm_hyp_reset_entry(void)
> > +unsigned long kvm_hyp_reset_entry(void)
> >  {
> > -	unsigned long offset;
> > -
> > -	offset = (unsigned long)__kvm_hyp_reset
> > -		 - ((unsigned long)__hyp_idmap_text_start & PAGE_MASK);
> > -
> > -	return TRAMPOLINE_VA + offset;
> > +	if (!__kvm_cpu_uses_extended_idmap()) {
> > +		unsigned long offset;
> > +
> > +		/*
> > +		 * Find the address of __kvm_hyp_reset() in the trampoline page.
> > +		 * This is present in the running page tables, and the boot page
> > +		 * tables, so we call the code here to start the trampoline
> > +		 * dance in reverse.
> > +		 */
> > +		offset = (unsigned long)__kvm_hyp_reset
> > +			 - ((unsigned long)__hyp_idmap_text_start & PAGE_MASK);
> > +
> > +		return TRAMPOLINE_VA + offset;
> > +	} else {
> > +		/*
> > +		 * KVM is running with merged page tables, which don't have the
> > +		 * trampoline page mapped. We know the idmap is still mapped,
> > +		 * but can't be called into directly. Use
> > +		 * __extended_idmap_trampoline to do the call.
> > +		 */
> > +		return (unsigned long)kvm_ksym_ref(__extended_idmap_trampoline);
> > +	}
> >  }
> 
> This looks correct, and gives me yet another incentive to revisit this
> code with a view of keeping the idmap at all times in the EL2 page
> tables. This should ensure that (1) the merged page tables become the
> only configuration, and (2) that we get rid off of the potential TLB
> conflict when swapping TTBR0_EL2 at boot time (intermediate level
> caching). In the meantime:
> 
> Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
> 
thanks!  Will, should this go via the kvmarm tree or the arm64 tree?

-Christoffer


From shawnguo at kernel.org  Tue May  3 01:37:19 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 16:37:19 +0800
Subject: [PATCH] ARM: dts: imx6sx-sdb: Add 198MHz operational point
In-Reply-To: <1461897267-20458-1-git-send-email-festevam@gmail.com>
References: <1461897267-20458-1-git-send-email-festevam@gmail.com>
Message-ID: <20160503083719.GD5874@tiger>

On Thu, Apr 28, 2016 at 11:34:27PM -0300, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam at nxp.com>
> 
> imx6sx-sdb has custom operating points entries because it has one
> power supply that drives both VDDARM_IN and VDDSOC_IN.
> 
> As per the MX6UL datasheet we have the following minimum voltages for
> 198 MHz operation (after adding the 25mV margin value):
> VDDARM_IN = 0.975 V
> VDDSOC_IN = 1.175 V
> 
> So use 1.175V for the 198MHz operation.
> 
> Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>

Applied, thanks.


From shawnguo at kernel.org  Tue May  3 01:39:30 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 16:39:30 +0800
Subject: [PATCH] ARM: dts: imx6: apalis: parallel lcd display support on
 ixora
In-Reply-To: <1461961249-3792-1-git-send-email-marcel.ziswiler@toradex.com>
References: <1461961249-3792-1-git-send-email-marcel.ziswiler@toradex.com>
Message-ID: <20160503083930.GE5874@tiger>

On Fri, Apr 29, 2016 at 10:20:49PM +0200, Marcel Ziswiler wrote:
> Add parallel LCD display support for the EDT ET057090DHU 5.7" LCD TFT
> panel.
> 
> Signed-off-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>

Applied, thanks.


From marc.zyngier at arm.com  Tue May  3 01:41:22 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 09:41:22 +0100
Subject: [PATCH] arm64: kvm: Fix kvm teardown for systems using the
 extended idmap
In-Reply-To: <20160503083651.GB17923@cbox>
References: <1461775633-29715-1-git-send-email-james.morse@arm.com>
 <1461950823-9790-1-git-send-email-james.morse@arm.com>
 <20160502130535.19b20b79@arm.com> <20160503083651.GB17923@cbox>
Message-ID: <57286432.2000606@arm.com>

On 03/05/16 09:36, Christoffer Dall wrote:
> On Mon, May 02, 2016 at 01:05:35PM +0100, Marc Zyngier wrote:
>> On Fri, 29 Apr 2016 18:27:03 +0100
>> James Morse <james.morse at arm.com> wrote:
>>
>> Hi James,
>>
>>> If memory is located above 1<<VA_BITS, kvm adds an extra level to its page
>>> tables, merging the runtime tables and boot tables that contain the idmap.
>>> This lets us avoid the trampoline dance during initialisation.
>>>
>>> This also means there is no trampoline page mapped, so
>>> __cpu_reset_hyp_mode() can't call __kvm_hyp_reset() in this page. The good
>>> news is the idmap is still mapped, so we don't need the trampoline page.
>>> The bad news is we can't call it directly as the idmap is above
>>> HYP_PAGE_OFFSET, so its address is masked by kvm_call_hyp.
>>>
>>> Add a function __extended_idmap_trampoline which will branch into
>>> __kvm_hyp_reset in the idmap, change kvm_hyp_reset_entry() to return
>>> this address if __kvm_cpu_uses_extended_idmap(). In this case
>>> __kvm_hyp_reset() will still switch to the boot tables (which are the
>>> merged tables that were already in use), and branch into the idmap (where
>>> it already was).
>>>
>>> This fixes boot failures on these systems, where we fail to execute the
>>> missing trampoline page when tearing down kvm in init_subsystems():
>>> [    2.508922] kvm [1]: 8-bit VMID
>>> [    2.512057] kvm [1]: Hyp mode initialized successfully
>>> [    2.517242] kvm [1]: interrupt-controller at e1140000 IRQ13
>>> [    2.522622] kvm [1]: timer IRQ3
>>> [    2.525783] Kernel panic - not syncing: HYP panic:
>>> [    2.525783] PS:200003c9 PC:0000007ffffff820 ESR:86000005
>>> [    2.525783] FAR:0000007ffffff820 HPFAR:00000000003ffff0 PAR:0000000000000000
>>> [    2.525783] VCPU:          (null)
>>> [    2.525783]
>>> [    2.547667] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G        W       4.6.0-rc5+ #1
>>> [    2.555137] Hardware name: Default string Default string/Default string, BIOS ROD0084E 09/03/2015
>>> [    2.563994] Call trace:
>>> [    2.566432] [<ffffff80080888d0>] dump_backtrace+0x0/0x240
>>> [    2.571818] [<ffffff8008088b24>] show_stack+0x14/0x20
>>> [    2.576858] [<ffffff80083423ac>] dump_stack+0x94/0xb8
>>> [    2.581899] [<ffffff8008152130>] panic+0x10c/0x250
>>> [    2.586677] [<ffffff8008152024>] panic+0x0/0x250
>>> [    2.591281] SMP: stopping secondary CPUs
>>> [    3.649692] SMP: failed to stop secondary CPUs 0-2,4-7
>>> [    3.654818] Kernel Offset: disabled
>>> [    3.658293] Memory Limit: none
>>> [    3.661337] ---[ end Kernel panic - not syncing: HYP panic:
>>> [    3.661337] PS:200003c9 PC:0000007ffffff820 ESR:86000005
>>> [    3.661337] FAR:0000007ffffff820 HPFAR:00000000003ffff0 PAR:0000000000000000
>>> [    3.661337] VCPU:          (null)
>>> [    3.661337]
>>>
>>>
>>> Reported-by: Will Deacon <will.deacon at arm.com>
>>> Signed-off-by: James Morse <james.morse at arm.com>
>>> ---
>>>  arch/arm64/include/asm/kvm_host.h |  3 ++-
>>>  arch/arm64/kvm/hyp-init.S         |  5 +++++
>>>  arch/arm64/kvm/hyp/entry.S        | 19 +++++++++++++++++++
>>>  arch/arm64/kvm/reset.c            | 30 +++++++++++++++++++++++-------
>>>  4 files changed, 49 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
>>> index b6f194d9f6b2..88a34670ddef 100644
>>> --- a/arch/arm64/include/asm/kvm_host.h
>>> +++ b/arch/arm64/include/asm/kvm_host.h
>>> @@ -46,7 +46,8 @@
>>>  int __attribute_const__ kvm_target_cpu(void);
>>>  int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
>>>  int kvm_arch_dev_ioctl_check_extension(long ext);
>>> -phys_addr_t kvm_hyp_reset_entry(void);
>>> +unsigned long kvm_hyp_reset_entry(void);
>>> +void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t idmap_start);
>>>  
>>>  struct kvm_arch {
>>>  	/* The VMID generation used for the virt. memory system */
>>> diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
>>> index 44ec4cb23ae7..a873a6d8be90 100644
>>> --- a/arch/arm64/kvm/hyp-init.S
>>> +++ b/arch/arm64/kvm/hyp-init.S
>>> @@ -140,6 +140,11 @@ merged:
>>>  ENDPROC(__kvm_hyp_init)
>>>  
>>>  	/*
>>> +	 * Reset kvm back to the hyp stub. This is the trampoline dance in
>>> +	 * reverse. If kvm used an extended idmap, __extended_idmap_trampoline
>>> +	 * calls this code directly in the idmap. In this case switching to the
>>> +	 * boot tables is a no-op.
>>> +	 *
>>>  	 * x0: HYP boot pgd
>>>  	 * x1: HYP phys_idmap_start
>>>  	 */
>>> diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
>>> index ce9e5e5f28cf..70254a65bd5b 100644
>>> --- a/arch/arm64/kvm/hyp/entry.S
>>> +++ b/arch/arm64/kvm/hyp/entry.S
>>> @@ -164,3 +164,22 @@ alternative_endif
>>>  
>>>  	eret
>>>  ENDPROC(__fpsimd_guest_restore)
>>> +
>>> +/*
>>> + * When using the extended idmap, we don't have a trampoline page we can use
>>> + * while we switch pages tables during __kvm_hyp_reset. Accessing the idmap
>>> + * directly would be ideal, but if we're using the extended idmap then the
>>> + * idmap is located above HYP_PAGE_OFFSET, and the address will be masked by
>>> + * kvm_call_hyp using kern_hyp_va.
>>> + *
>>> + * x0: HYP boot pgd
>>> + * x1: HYP phys_idmap_start
>>> + */
>>> +ENTRY(__extended_idmap_trampoline)
>>> +	mov	x4, x1
>>> +	adr_l	x3, __kvm_hyp_reset
>>> +
>>> +	/* insert __kvm_hyp_reset()s offset into phys_idmap_start */
>>> +	bfi	x4, x3, #0, #PAGE_SHIFT
>>> +	br	x4
>>> +ENDPROC(__extended_idmap_trampoline)
>>> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
>>> index 4062e6dd4cc1..b1ad730e1567 100644
>>> --- a/arch/arm64/kvm/reset.c
>>> +++ b/arch/arm64/kvm/reset.c
>>> @@ -135,12 +135,28 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
>>>  
>>>  extern char __hyp_idmap_text_start[];
>>>  
>>> -phys_addr_t kvm_hyp_reset_entry(void)
>>> +unsigned long kvm_hyp_reset_entry(void)
>>>  {
>>> -	unsigned long offset;
>>> -
>>> -	offset = (unsigned long)__kvm_hyp_reset
>>> -		 - ((unsigned long)__hyp_idmap_text_start & PAGE_MASK);
>>> -
>>> -	return TRAMPOLINE_VA + offset;
>>> +	if (!__kvm_cpu_uses_extended_idmap()) {
>>> +		unsigned long offset;
>>> +
>>> +		/*
>>> +		 * Find the address of __kvm_hyp_reset() in the trampoline page.
>>> +		 * This is present in the running page tables, and the boot page
>>> +		 * tables, so we call the code here to start the trampoline
>>> +		 * dance in reverse.
>>> +		 */
>>> +		offset = (unsigned long)__kvm_hyp_reset
>>> +			 - ((unsigned long)__hyp_idmap_text_start & PAGE_MASK);
>>> +
>>> +		return TRAMPOLINE_VA + offset;
>>> +	} else {
>>> +		/*
>>> +		 * KVM is running with merged page tables, which don't have the
>>> +		 * trampoline page mapped. We know the idmap is still mapped,
>>> +		 * but can't be called into directly. Use
>>> +		 * __extended_idmap_trampoline to do the call.
>>> +		 */
>>> +		return (unsigned long)kvm_ksym_ref(__extended_idmap_trampoline);
>>> +	}
>>>  }
>>
>> This looks correct, and gives me yet another incentive to revisit this
>> code with a view of keeping the idmap at all times in the EL2 page
>> tables. This should ensure that (1) the merged page tables become the
>> only configuration, and (2) that we get rid off of the potential TLB
>> conflict when swapping TTBR0_EL2 at boot time (intermediate level
>> caching). In the meantime:
>>
>> Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
>>
> thanks!  Will, should this go via the kvmarm tree or the arm64 tree?

I believe this issue only exists with the hibernation patches, so I
suggest we let Will handle this though the arm64 tree together with the
rest of this series.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From lorenzo.pieralisi at arm.com  Tue May  3 01:46:28 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Tue, 3 May 2016 09:46:28 +0100
Subject: [PATCH V6 09/13] pci, acpi: Support for ACPI based generic PCI
 host controller
In-Reply-To: <CAKc_7PUcjKkCrCTj9q26P8a+Tb3N_MffynnTXnJRacm6VNmFRw@mail.gmail.com>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-10-git-send-email-tn@semihalf.com>
 <20160428214800.GG25125@localhost> <20160429083709.GA3249@red-moon>
 <CAKc_7PUcjKkCrCTj9q26P8a+Tb3N_MffynnTXnJRacm6VNmFRw@mail.gmail.com>
Message-ID: <20160503084628.GA31158@red-moon>

On Fri, Apr 29, 2016 at 11:05:34PM +0530, Jayachandran C wrote:
> On Fri, Apr 29, 2016 at 2:07 PM, Lorenzo Pieralisi
> <lorenzo.pieralisi at arm.com> wrote:
> > On Thu, Apr 28, 2016 at 04:48:00PM -0500, Bjorn Helgaas wrote:
> >
> > [...]
> >
> >> > +static int pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root,
> >> > +                                  struct acpi_pci_generic_root_info *ri)
> >> > +{
> >> > +   u16 seg = root->segment;
> >> > +   u8 bus_start = root->secondary.start;
> >> > +   u8 bus_end = root->secondary.end;
> >> > +   struct pci_config_window *cfg;
> >> > +   struct mcfg_entry *e;
> >> > +   phys_addr_t addr;
> >> > +   int err = 0;
> >> > +
> >> > +   mutex_lock(&pci_mcfg_lock);
> >>
> >> What does this lock protect?  The pci_mcfg_list should already be
> >> initialized by the time we get there, and it should be immutable for
> >> the life of the system.  In fact, I would prefer if we could just
> >> search the static table itself whenever we need it rather than caching
> >> it in our own list.  But I don't think we can easily do that because
> >> acpi_table_parse() is __init.
> >>
> >> > +   e = pci_mcfg_lookup(seg, bus_start);
> >>
> >> I would argue that we should check for _CBA first, and fall back to
> >> MCFG if _CBA doesn't exist.
> >>
> >> > +   if (!e) {
> >> > +           addr = acpi_pci_root_get_mcfg_addr(root->device->handle);
> >>
> >> IMO, acpi_pci_root_get_mcfg_addr() is misnamed.  It should be
> >> acpi_pci_config_base_addr() or similar.  It definitely is not related
> >> to MCFG.  Not your fault, obviously.
> >>
> >> > +           if (addr == 0) {
> >> > +                   pr_err(PREFIX"%04x:%02x-%02x bus range error\n",
> >> > +                          seg, bus_start, bus_end);
> >> > +                   err = -ENOENT;
> >> > +                   goto err_out;
> >> > +           }
> >> > +   } else {
> >> > +           if (bus_start != e->bus_start) {
> >> > +                   pr_err("%04x:%02x-%02x bus range mismatch %02x\n",
> >> > +                          seg, bus_start, bus_end, e->bus_start);
> >> > +                   err = -EINVAL;
> >> > +                   goto err_out;
> >> > +           } else if (bus_end != e->bus_end) {
> >> > +                   pr_warn("%04x:%02x-%02x bus end mismatch %02x\n",
> >> > +                           seg, bus_start, bus_end, e->bus_end);
> >> > +                   bus_end = min(bus_end, e->bus_end);
> >> > +           }
> >> > +           addr = e->addr;
> >> > +   }
> >>
> >> I really don't think you need a lock around this, so you can factor
> >> out the address lookup into something like:
> >>
> >>   addr = acpi_pci_config_base_addr(...);
> >>   if (addr)
> >>     return addr;
> >>
> >>   return acpi_pci_mcfg_lookup(seg, busn_res);
> >>
> >> You can check inside acpi_pci_mcfg_lookup() to make sure the entry you
> >> find covers the entire [busn_res.start-busn_res.end] range and return
> >> failure if it doesn't.  At this point, I'm not sure it's worth it to
> >> truncate the host bridge bus range to match something we find in MCFG.
> >>
> >> If the MCFG entry covers *more* than the host bridge range from _CRS,
> >> that's fine.  In any case, we have to be careful with the start address,
> >> because the MCFG start address is always based on bus 0, but I think
> >> pci_generic_ecam_create() expects the start address based on the
> >> bus_start you pass to it.
> >
> > Yes, I spotted this too, it is unfortunate but DT and MCFG handle
> > the ECAM regions differently. In DT the reg property is relative
> > to bus_start - ie reg MMIO region maps config space starting at
> > the first bus in bus-range:
> >
> > Documentation/devicetree/bindings/pci/host-generic-pci.txt
> >
> > in ACPI(MCFG) as you said it is always relative to bus 0, it is
> > unfortunate but the address to be mapped should be computed
> > differently in the ECAM layer.
> 
> Can't this be handled by fixing up the address before passing to
> pci_generic_ecam_create?

Yes it can, you just need to apply the bus shift, given that we know
it is ECAM anyway you can even add a macro in the ecam generic header to
compute it, anyway that's a minor detail, we just should not forget to
fix it.

Lorenzo


From catalin.marinas at arm.com  Tue May  3 01:52:01 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 3 May 2016 09:52:01 +0100
Subject: [PATCH] arm64: always use STRICT_MM_TYPECHECKS
In-Reply-To: <1461964074-12544-1-git-send-email-yang.shi@linaro.org>
References: <1461964074-12544-1-git-send-email-yang.shi@linaro.org>
Message-ID: <20160503085201.GA10733@e104818-lin.cambridge.arm.com>

On Fri, Apr 29, 2016 at 02:07:54PM -0700, Yang Shi wrote:
> Inspired by the counterpart of powerpc [1], which shows there is no negative
> effect on code generation from enabling STRICT_MM_TYPECHECKS with a modern
> compiler.
> 
> And, Arnd's comment [2] about that patch says STRICT_MM_TYPECHECKS could
> be default as long as the architecture can pass structures in registers as
> function arguments. ARM64 can do it as long as the size of structure <= 16
> bytes. All the page table value types are u64 on ARM64.
> 
> The below disassembly demonstrates it, entry is pte_t type:
> 
>             entry = arch_make_huge_pte(entry, vma, page, writable);
>    0xffff00000826fc38 <+80>:    and     x0, x0, #0xfffffffffffffffd
>    0xffff00000826fc3c <+84>:    mov     w3, w21
>    0xffff00000826fc40 <+88>:    mov     x2, x20
>    0xffff00000826fc44 <+92>:    mov     x1, x19
>    0xffff00000826fc48 <+96>:    orr     x0, x0, #0x400
>    0xffff00000826fc4c <+100>:   bl      0xffff00000809bcc0 <arch_make_huge_pte>
> 
> [1] http://www.spinics.net/lists/linux-mm/msg105951.html
> [2] http://www.spinics.net/lists/linux-mm/msg105969.html
> 
> Signed-off-by: Yang Shi <yang.shi at linaro.org>
> CC: Arnd Bergmann <arnd at arndb.de>
> CC: Ard Biesheuvel <ard.biesheuvel at linaro.org>

I'm fine with this change. If Will is still cherry-picking patches for
4.7:

Acked-by: Catalin Marinas <catalin.marinas at arm.com>


From p.zabel at pengutronix.de  Tue May  3 01:52:28 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Tue, 03 May 2016 10:52:28 +0200
Subject: [GIT PULL] Reset controller changes for v4.7: build fix and OXNAS
 driver
Message-ID: <1462265548.3617.6.camel@pengutronix.de>

Dear arm-soc maintainers,

this tag contains a stub for the device_reset() function as a build fix
for drivers that use this function when compiling without
CONFIG_RESET_CONTROLLER enabled, and a reset driver for OXNAS SoCs.

regards
Philipp

The following changes since commit 773fe72630c8aca874ec8a07ebacace4ae305a02:

  reset: lpc18xx: get rid of global variables for restart notifier (2016-03-30 15:42:07 +0200)

are available in the git repository at:

  git://git.pengutronix.de/git/pza/linux.git tags/reset-for-4.7-2

for you to fetch changes up to 4113652252fad972e0c191b1e536dc74a6faebdc:

  reset: Add missing function stub for device_reset (2016-04-04 18:15:23 +0200)

----------------------------------------------------------------
Reset controller changes for v4.7

- add missing stub for device_reset
- add support for OXNAS SoCs

----------------------------------------------------------------
Daniel Lezcano (1):
      reset: Add missing function stub for device_reset

Neil Armstrong (2):
      reset: Add Oxford Semiconductor Reset Controller driver
      dt-bindings: Add Oxford Semiconductor Reset Controller bindings

 .../devicetree/bindings/reset/oxnas,reset.txt      |  58 +++++++++
 drivers/reset/Kconfig                              |   3 +
 drivers/reset/Makefile                             |   1 +
 drivers/reset/reset-oxnas.c                        | 136 +++++++++++++++++++++
 include/linux/reset.h                              |   6 +
 5 files changed, 204 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/oxnas,reset.txt
 create mode 100644 drivers/reset/reset-oxnas.c


From will.deacon at arm.com  Tue May  3 01:57:59 2016
From: will.deacon at arm.com (Will Deacon)
Date: Tue, 3 May 2016 09:57:59 +0100
Subject: [PATCH] arm64: kvm: Fix kvm teardown for systems using the
 extended idmap
In-Reply-To: <57286432.2000606@arm.com>
References: <1461775633-29715-1-git-send-email-james.morse@arm.com>
 <1461950823-9790-1-git-send-email-james.morse@arm.com>
 <20160502130535.19b20b79@arm.com> <20160503083651.GB17923@cbox>
 <57286432.2000606@arm.com>
Message-ID: <20160503085758.GA2604@arm.com>

Hi all,

On Tue, May 03, 2016 at 09:41:22AM +0100, Marc Zyngier wrote:
> On 03/05/16 09:36, Christoffer Dall wrote:
> > On Mon, May 02, 2016 at 01:05:35PM +0100, Marc Zyngier wrote:
> >> On Fri, 29 Apr 2016 18:27:03 +0100
> >> James Morse <james.morse at arm.com> wrote:
> >>> If memory is located above 1<<VA_BITS, kvm adds an extra level to its page
> >>> tables, merging the runtime tables and boot tables that contain the idmap.
> >>> This lets us avoid the trampoline dance during initialisation.
> >>>
> >>> This also means there is no trampoline page mapped, so
> >>> __cpu_reset_hyp_mode() can't call __kvm_hyp_reset() in this page. The good
> >>> news is the idmap is still mapped, so we don't need the trampoline page.
> >>> The bad news is we can't call it directly as the idmap is above
> >>> HYP_PAGE_OFFSET, so its address is masked by kvm_call_hyp.
> >>>
> >>> Add a function __extended_idmap_trampoline which will branch into
> >>> __kvm_hyp_reset in the idmap, change kvm_hyp_reset_entry() to return
> >>> this address if __kvm_cpu_uses_extended_idmap(). In this case
> >>> __kvm_hyp_reset() will still switch to the boot tables (which are the
> >>> merged tables that were already in use), and branch into the idmap (where
> >>> it already was).
> >>>
> >>> This fixes boot failures on these systems, where we fail to execute the
> >>> missing trampoline page when tearing down kvm in init_subsystems():
> >>> [    2.508922] kvm [1]: 8-bit VMID
> >>> [    2.512057] kvm [1]: Hyp mode initialized successfully
> >>> [    2.517242] kvm [1]: interrupt-controller at e1140000 IRQ13
> >>> [    2.522622] kvm [1]: timer IRQ3
> >>> [    2.525783] Kernel panic - not syncing: HYP panic:
> >>> [    2.525783] PS:200003c9 PC:0000007ffffff820 ESR:86000005
> >>> [    2.525783] FAR:0000007ffffff820 HPFAR:00000000003ffff0 PAR:0000000000000000
> >>> [    2.525783] VCPU:          (null)
> >>> [    2.525783]
> >>> [    2.547667] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G        W       4.6.0-rc5+ #1
> >>> [    2.555137] Hardware name: Default string Default string/Default string, BIOS ROD0084E 09/03/2015
> >>> [    2.563994] Call trace:
> >>> [    2.566432] [<ffffff80080888d0>] dump_backtrace+0x0/0x240
> >>> [    2.571818] [<ffffff8008088b24>] show_stack+0x14/0x20
> >>> [    2.576858] [<ffffff80083423ac>] dump_stack+0x94/0xb8
> >>> [    2.581899] [<ffffff8008152130>] panic+0x10c/0x250
> >>> [    2.586677] [<ffffff8008152024>] panic+0x0/0x250
> >>> [    2.591281] SMP: stopping secondary CPUs
> >>> [    3.649692] SMP: failed to stop secondary CPUs 0-2,4-7
> >>> [    3.654818] Kernel Offset: disabled
> >>> [    3.658293] Memory Limit: none
> >>> [    3.661337] ---[ end Kernel panic - not syncing: HYP panic:
> >>> [    3.661337] PS:200003c9 PC:0000007ffffff820 ESR:86000005
> >>> [    3.661337] FAR:0000007ffffff820 HPFAR:00000000003ffff0 PAR:0000000000000000
> >>> [    3.661337] VCPU:          (null)
> >>> [    3.661337]
> >>>
> >>>
> >>> Reported-by: Will Deacon <will.deacon at arm.com>
> >>> Signed-off-by: James Morse <james.morse at arm.com>

[...]

> >> Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
> >>
> > thanks!  Will, should this go via the kvmarm tree or the arm64 tree?
> 
> I believe this issue only exists with the hibernation patches, so I
> suggest we let Will handle this though the arm64 tree together with the
> rest of this series.

Appplied and pushed to for-next/core. Sorry for the delay (bank holiday
here) and thanks for the comments.

Will


From catalin.marinas at arm.com  Tue May  3 02:00:45 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 3 May 2016 10:00:45 +0100
Subject: [PATCH 24/25] arm64:ilp32: add vdso-ilp32 and use for signal
 return
In-Reply-To: <1554541.oDP7Ro5zB2@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1459894127-17698-25-git-send-email-ynorov@caviumnetworks.com>
 <20160429160154.GC30316@e104818-lin.cambridge.arm.com>
 <1554541.oDP7Ro5zB2@wuerfel>
Message-ID: <20160503090045.GB10733@e104818-lin.cambridge.arm.com>

On Fri, Apr 29, 2016 at 07:30:19PM +0200, Arnd Bergmann wrote:
> On Friday 29 April 2016 17:01:55 Catalin Marinas wrote:
> > On Wed, Apr 06, 2016 at 01:08:46AM +0300, Yury Norov wrote:
> > > ILP32 VDSO exports next symbols:
> > >  __kernel_rt_sigreturn;
> > >  __kernel_gettimeofday;
> > >  __kernel_clock_gettime;
> > >  __kernel_clock_getres;
> > 
> > [...]
> > 
> > > +$(obj)/gettimeofday-ilp32.o: $(src)/../vdso/gettimeofday.S
> > > +	$(call if_changed_dep,vdso-ilp32as)
> > 
> > Are struct timeval and timespec the same between ILP32 and LP64? For
> > example, __kernel_gettimeofday() assumes TVAL_TV_SEC offset defined in
> > asm-offsets.c based on the LP64 timeval.
> 
> No, ilp32 uses the generic 32-bit data structures, which have a 32-bit
> time_t. I guess that means it can work for little-endian but not
> big-endian, right?

I don't think it works for little-endian either. The LP64 struct timeval
is 16 bytes while the ILP32 one is 8 bytes. The VDSO gettimeofday is
storing 16 bytes (stp x10, x11, [x0, #TVAL_TV_SEC])

-- 
Catalin


From bhe at redhat.com  Tue May  3 02:01:20 2016
From: bhe at redhat.com (Baoquan He)
Date: Tue, 3 May 2016 17:01:20 +0800
Subject: [PATCH 10/12] kexec: arrange for paddr_vmcoreinfo_note() to
 return phys_addr_t
In-Reply-To: <20160503055329.GA13045@dhcppc6.redhat.com>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <E1aviFP-0000je-5t@rmk-PC.arm.linux.org.uk>
 <CAHB_Gur-6oyEheN-Pom7OwivdvrQpCBaXvM1V2H0JPFRCFZthA@mail.gmail.com>
 <20160429151639.GC23726@leverpostej>
 <CAHB_GurwYqPbccLU9UHppLxbBr4Cfs47myKAer-RJicT=T7uBw@mail.gmail.com>
 <20160503042441.GA2518@x1.redhat.com>
 <20160503055329.GA13045@dhcppc6.redhat.com>
Message-ID: <20160503090120.GB3287@x1.redhat.com>

On 05/03/16 at 11:23am, Pratyush Anand wrote:
> Hi Baoquan,
> 
> On 03/05/2016:12:24:41 PM, Baoquan He wrote:
> > Hi Pratyush,
> > 
> > Could you please help tell why arm PAE kernel can be put above 4G?
> 
> PAE system can have physical addresses above 4G. So, if a CPU is supporting the
> LPAE page table format then we should be able to access physical addresses
> beyond 4G.

OK, after patient explanation from Pratush on irc, I finally understand on
arm LPAE there's PHYS_OFFSET which indicats the physical address of main
memory since arm could map some amount of device memory to cpu address space
below 4G. Then physical ram has to be started from above 4G form cpu
point of view. That's why kernel need be put above 4G. It's fair enough to
fix it in this patch. Certainly if this explanation is also added into
patch log, non arm developer will understand the change better.

Thanks
Baoquan

> 
> > Since the change is related to common code, I am curious about how
> > it's so different with other ARCHs.
> 
> paddr_vmcoreinfo_note() returns a physical address, so returning phys_addr_t
> seems most appropriate. So, kernel variable may land into above 4G locations,
> even with the platform in other architecture (with PAE support), if start of RAM
> is located very high,
> 
> So, in my opinion it would be safer to have these changes for other ARCHs as
> well.
> 
> ~Pratyush
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


From p.zabel at pengutronix.de  Tue May  3 02:05:44 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Tue, 03 May 2016 11:05:44 +0200
Subject: [PATCH 3/7] reset: lpc18xx: use devm_reset_controller_register()
In-Reply-To: <CAK7LNAQ5LztGBbHCQxfLyWT7c_kWL=zpdKfkC9vsOKw95XL_Yw@mail.gmail.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
 <1462099023-11819-4-git-send-email-yamada.masahiro@socionext.com>
 <1462177581.3933.7.camel@pengutronix.de>
 <CAK7LNAQ5LztGBbHCQxfLyWT7c_kWL=zpdKfkC9vsOKw95XL_Yw@mail.gmail.com>
Message-ID: <1462266344.3617.12.camel@pengutronix.de>

Am Dienstag, den 03.05.2016, 00:52 +0900 schrieb Masahiro Yamada:
> 2016-05-02 17:26 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> > Am Sonntag, den 01.05.2016, 19:36 +0900 schrieb Masahiro Yamada:
> >> Use devm_reset_controller_register() for the reset controller
> >> registration and remove the unregister call from the .remove callback.
> >>
> >> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> >> ---
> >>
> >>  drivers/reset/reset-lpc18xx.c | 4 +---
> >>  1 file changed, 1 insertion(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c
> >> index 3b8a4f5..dd4f27e 100644
> >> --- a/drivers/reset/reset-lpc18xx.c
> >> +++ b/drivers/reset/reset-lpc18xx.c
> >> @@ -199,7 +199,7 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
> >>
> >>       platform_set_drvdata(pdev, rc);
> >>
> >> -     ret = reset_controller_register(&rc->rcdev);
> >> +     ret = devm_reset_controller_register(&pdev->dev, &rc->rcdev);
> >>       if (ret) {
> >>               dev_err(&pdev->dev, "unable to register device\n");
> >>               goto dis_clks;
> >> @@ -229,8 +229,6 @@ static int lpc18xx_rgu_remove(struct platform_device *pdev)
> >>       if (ret)
> >>               dev_warn(&pdev->dev, "failed to unregister restart handler\n");
> >>
> >> -     reset_controller_unregister(&rc->rcdev);
> >> -
> >>       clk_disable_unprepare(rc->clk_delay);
> >>       clk_disable_unprepare(rc->clk_reg);
> >>
> >
> > Hmm, would this patch theoretically allow a window between the calls to
> > clk_disable_unprepare(clk_reg) and devm_reset_controller_release() where
> > reset_control_get() + reset_control_(de)assert() would access unclocked
> > registers?
> 
> This is not clear to me.
> 
> Why reset_control_get() + reset_control_(de)assert() would happen here?

I suppose on a non-SMP device, without parallel probing this can't
really happen in practice.
It still seems weird that suddenly we disable the clocks before
unregistering the reset controller instead of afterwards.

regards
Philipp



From arnd at arndb.de  Tue May  3 02:05:02 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 03 May 2016 11:05:02 +0200
Subject: [PATCH 24/25] arm64:ilp32: add vdso-ilp32 and use for signal
 return
In-Reply-To: <20160503090045.GB10733@e104818-lin.cambridge.arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1554541.oDP7Ro5zB2@wuerfel>
 <20160503090045.GB10733@e104818-lin.cambridge.arm.com>
Message-ID: <3846428.6xx69KGEja@wuerfel>

On Tuesday 03 May 2016 10:00:45 Catalin Marinas wrote:
> On Fri, Apr 29, 2016 at 07:30:19PM +0200, Arnd Bergmann wrote:
> > On Friday 29 April 2016 17:01:55 Catalin Marinas wrote:
> > > On Wed, Apr 06, 2016 at 01:08:46AM +0300, Yury Norov wrote:
> > > > ILP32 VDSO exports next symbols:
> > > >  __kernel_rt_sigreturn;
> > > >  __kernel_gettimeofday;
> > > >  __kernel_clock_gettime;
> > > >  __kernel_clock_getres;
> > > 
> > > [...]
> > > 
> > > > +$(obj)/gettimeofday-ilp32.o: $(src)/../vdso/gettimeofday.S
> > > > + $(call if_changed_dep,vdso-ilp32as)
> > > 
> > > Are struct timeval and timespec the same between ILP32 and LP64? For
> > > example, __kernel_gettimeofday() assumes TVAL_TV_SEC offset defined in
> > > asm-offsets.c based on the LP64 timeval.
> > 
> > No, ilp32 uses the generic 32-bit data structures, which have a 32-bit
> > time_t. I guess that means it can work for little-endian but not
> > big-endian, right?
> 
> I don't think it works for little-endian either. The LP64 struct timeval
> is 16 bytes while the ILP32 one is 8 bytes. The VDSO gettimeofday is
> storing 16 bytes (stp x10, x11, [x0, #TVAL_TV_SEC])

You are right. Yury asked pointed out the same thing on IRC as well.
Using the 64-bit gettimeofday() will put the right number in the
.tv_sec member on little-endian, but will write zeroes to tv_nsec
and corrupt the memory following it.

Yury also tried it out and noticed that for a (so far) unknown reason,
the vdso gets never used by his glibc build, so it has not triggered
any test case failures.

	Arnd


From chunfeng.yun at mediatek.com  Tue May  3 02:09:51 2016
From: chunfeng.yun at mediatek.com (chunfeng yun)
Date: Tue, 3 May 2016 17:09:51 +0800
Subject: [PATCH] usb: xhci-mtk: fixup mouse wakeup failure during system
 suspend
In-Reply-To: <87vb2vfujq.fsf@intel.com>
References: <1461204293-18243-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462261458.11651.7.camel@mhfsdcap03> <87vb2vfujq.fsf@intel.com>
Message-ID: <1462266591.11651.34.camel@mhfsdcap03>

On Tue, 2016-05-03 at 10:51 +0300, Felipe Balbi wrote:
> Hi,
> 
> chunfeng yun <chunfeng.yun at mediatek.com> writes:
> > On Thu, 2016-04-21 at 10:04 +0800, Chunfeng Yun wrote:
> >> Click mouse after xhci suspend completion but before system suspend
> >> completion, system will not be waken up by mouse if the duration of
> >> them is larger than 20ms which is the device UFP's resume signaling
> 
> what is "them" here ? The duration of what is longer than 20ms ?
They are "xhci suspend completion" and "system suspend completion";

It's time duration

> 
> >> lasted. Another reason is that the SPM is not enabled before system
> 
> what's SPM ?
It is System Power Management which is powered off when system is
running in normal mode, and is powered on when system enters suspend
mode. It is used to wakeup system when some wakeup sources, such as
bluetooth or powerkey etc, tigger wakeup event.

> 
> >> suspend compeltion, this causes SPM also not notice the resume signal.
>            ^^^^^^^^^^
>            completion
> 
> >> So in order to reduce the duration less than 20ms, make use of
> >> syscore's suspend/resume interface.
> 
> no, this is the wrong approach
But it seems only one workable approach from software side

> 
> >> In fact it is a work around solution which only reduces the
> >> probability of failure, because we can't ensure that the duration from
> >> syscore's suspend completion to SPM working is always less than 20ms.
> 
> right, which means you're not really fixing anything. Morevoer, you make
> it so that this won't work with multiple instances of the XHCI IP in
> your SoC.
> 
It can be easily fixed up from hardware side by latching resume signal
until SPM is powered on.

I forgot to take into account of multiple instances
 
> >> Because the syscore runs on irq disabled context, and xhci's
> >> suspend/resume calls some sleeping functions, enable local irq
> >> and then disable it during suspend/resume. This may be not a problem,
> >> since only boot CPU is runing.
> 
> another problem :) calling local_irq_{enable,disable}() is an indication
> that something's wrong.
Oh!

BTW: There will be warning logs if they are not called.

Thanks a lot
> 
> >> Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
> >> ---
> >>  drivers/usb/host/xhci-mtk.c |   31 ++++++++++++++++++++++++++++++-
> >>  1 file changed, 30 insertions(+), 1 deletion(-)
> >> 
> >> diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
> >> index 79959f1..8277f02 100644
> >> --- a/drivers/usb/host/xhci-mtk.c
> >> +++ b/drivers/usb/host/xhci-mtk.c
> >> @@ -28,6 +28,7 @@
> >>  #include <linux/pm_runtime.h>
> >>  #include <linux/regmap.h>
> >>  #include <linux/regulator/consumer.h>
> >> +#include <linux/syscore_ops.h>
> >>  
> >>  #include "xhci.h"
> >>  #include "xhci-mtk.h"
> >> @@ -490,6 +491,8 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
> >>  	return xhci_gen_setup(hcd, xhci_mtk_quirks);
> >>  }
> >>  
> >> +static struct device *xhci_mtk_syscore_dev;
> 
> now, what happens when you have more than one XHCI instance ?
> 




From appana.durga.rao at xilinx.com  Tue May  3 02:12:24 2016
From: appana.durga.rao at xilinx.com (Appana Durga Kedareswara Rao)
Date: Tue, 3 May 2016 09:12:24 +0000
Subject: [PATCH v7 1/2] Documentation: DT: dma: Add Xilinx zynqmp dma
 device tree binding documentation
In-Reply-To: <20160502100953.GJ2274@localhost>
References: <1461740729-30715-1-git-send-email-appanad@xilinx.com>
 <57206632.7010508@metafoo.de>
 <C246CAC1457055469EF09E3A7AC4E11A4A57B840@XAP-PVEXMBX01.xlnx.xilinx.com>
 <5720B333.4000804@metafoo.de>
 <C246CAC1457055469EF09E3A7AC4E11A4A57C2E2@XAP-PVEXMBX01.xlnx.xilinx.com>
 <5721D38A.8010501@metafoo.de> <20160502100953.GJ2274@localhost>
Message-ID: <C246CAC1457055469EF09E3A7AC4E11A4A57E033@XAP-PVEXMBX01.xlnx.xilinx.com>


Hi Vinod,

> 
> PLEASE strip the crap from your MUA, better use a linux MUA

OK will fix Sorry for the noise...

> 
> 
> > >>>>> +- xlnx,include-sg	: Indicates the controller to operate in simple
> or
> > >>>>> +			  scatter gather dma mode
> > >>>>> +- xlnx,ratectrl		: Scheduling interval in terms of clock cycles for
> > >>>>> +			  source AXI transaction
> > >>>>> +- xlnx,overfetch	: Tells whether the channel is allowed to over
> > >>>>> +			  fetch the data
> > >>>>> +- xlnx,src-issue	: Number of AXI outstanding transactions on source
> > >>>> side
> > >>>>> +- xlnx,src-burst-len	: AXI length for data read. Support only power
> of
> > >>>>> +			  2 byte values.
> > >>>>> +- xlnx,dst-burst-len	: AXI length for data write. Support only power
> of
> > >>>>
> > >>>> These are all software runtime configuration parameters that you'd
> > >>>> want to change at runtime depending on which peripheral you are
> > >>>> targeting with a specific DMA transfer. These really do not belong into

> > Sorry, but that is just as broken. You need to derive those parameters from
> > the DMA transfer as they are transfer specific.
> 
> Right, for memcpy you should derive the parameters. Frankly burst size
> and lengths, rate control should be set to maximun to achives best
> performance on mecpy.  People want memcpy to be done asap

Ok Will fix in the next version of the patch...

Regards,
Kedar.



From eballetbo at gmail.com  Tue May  3 02:16:58 2016
From: eballetbo at gmail.com (Enric Balletbo Serra)
Date: Tue, 3 May 2016 11:16:58 +0200
Subject: [alsa-devel] [PATCH 1/2] ASoC: rockchip: i2s: separate capture
 and playback
In-Reply-To: <57282532.7000402@rock-chips.com>
References: <1449657147-26959-1-git-send-email-john@metanate.com>
 <CAFqH_52C4JKno4uyt54UdWKAJKM4FPGRiQaQQ9_H-Mz1Cr+Hqg@mail.gmail.com>
 <20160430070049.GF14612@serenity.lan>
 <57282532.7000402@rock-chips.com>
Message-ID: <CAFqH_50D5PQOkpCDefds3Nyktvitoe2Wx=YcXM2POox1ooO=0g@mail.gmail.com>

Hi all,

2016-05-03 6:12 GMT+02:00 sugar <sugar.zhang at rock-chips.com>:
> Hi John,
>
>
> On 4/30/2016 15:00, John Keeping Wrote:
>>
>> Hi Enric,
>>
>> On Fri, Apr 29, 2016 at 04:59:27PM +0200, Enric Balletbo Serra wrote:
>>>
>>> 2015-12-09 11:32 GMT+01:00 John Keeping <john at metanate.com>:
>>>>
>>>> If we only clear the tx/rx state when both are disabled it is not
>>>> possible to start/stop one multiple times while the other is running.
>>>> Since the two are independently controlled, treat them as such and
>>>> remove the false dependency between capture and playback.
>>>>
>>>> Signed-off-by: John Keeping <john at metanate.com>
>>>> ---
>>>>   sound/soc/rockchip/rockchip_i2s.c | 72
>>>> +++++++++++++++++----------------------
>>>>   1 file changed, 32 insertions(+), 40 deletions(-)
>>>>
>>>> diff --git a/sound/soc/rockchip/rockchip_i2s.c
>>>> b/sound/soc/rockchip/rockchip_i2s.c
>>>> index 83b1b9c..acc6225 100644
>>>> --- a/sound/soc/rockchip/rockchip_i2s.c
>>>> +++ b/sound/soc/rockchip/rockchip_i2s.c
>>>> @@ -82,8 +82,8 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev
>>>> *i2s, int on)
>>>>                                     I2S_DMACR_TDE_ENABLE,
>>>> I2S_DMACR_TDE_ENABLE);
>>>>
>>>>                  regmap_update_bits(i2s->regmap, I2S_XFER,
>>>> -                                  I2S_XFER_TXS_START |
>>>> I2S_XFER_RXS_START,
>>>> -                                  I2S_XFER_TXS_START |
>>>> I2S_XFER_RXS_START);
>>>> +                                  I2S_XFER_TXS_START,
>>>> +                                  I2S_XFER_TXS_START);
>>>>
>>>>                  i2s->tx_start = true;
>>>>          } else {
>>>> @@ -92,27 +92,23 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev
>>>> *i2s, int on)
>>>>                  regmap_update_bits(i2s->regmap, I2S_DMACR,
>>>>                                     I2S_DMACR_TDE_ENABLE,
>>>> I2S_DMACR_TDE_DISABLE);
>>>>
>>>> -               if (!i2s->rx_start) {
>>>> -                       regmap_update_bits(i2s->regmap, I2S_XFER,
>>>> -                                          I2S_XFER_TXS_START |
>>>> -                                          I2S_XFER_RXS_START,
>>>> -                                          I2S_XFER_TXS_STOP |
>>>> -                                          I2S_XFER_RXS_STOP);
>>>> +               regmap_update_bits(i2s->regmap, I2S_XFER,
>>>> +                                  I2S_XFER_TXS_START,
>>>> +                                  I2S_XFER_TXS_STOP);
>>>>
>>>> -                       regmap_update_bits(i2s->regmap, I2S_CLR,
>>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC,
>>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC);
>>>> +               regmap_update_bits(i2s->regmap, I2S_CLR,
>>>> +                                  I2S_CLR_TXC,
>>>> +                                  I2S_CLR_TXC);
>>>>
>>>> -                       regmap_read(i2s->regmap, I2S_CLR, &val);
>>>> +               regmap_read(i2s->regmap, I2S_CLR, &val);
>>>>
>>>> -                       /* Should wait for clear operation to finish */
>>>> -                       while (val) {
>>>> -                               regmap_read(i2s->regmap, I2S_CLR, &val);
>>>> -                               retry--;
>>>> -                               if (!retry) {
>>>> -                                       dev_warn(i2s->dev, "fail to
>>>> clear\n");
>>>> -                                       break;
>>>> -                               }
>>>> +               /* Should wait for clear operation to finish */
>>>> +               while (val & I2S_CLR_TXC) {
>>>> +                       regmap_read(i2s->regmap, I2S_CLR, &val);
>>>> +                       retry--;
>>>> +                       if (!retry) {
>>>> +                               dev_warn(i2s->dev, "fail to clear\n");
>>>> +                               break;
>>>>                          }
>>>>                  }
>>>>          }
>>>> @@ -128,8 +124,8 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev
>>>> *i2s, int on)
>>>>                                     I2S_DMACR_RDE_ENABLE,
>>>> I2S_DMACR_RDE_ENABLE);
>>>>
>>>>                  regmap_update_bits(i2s->regmap, I2S_XFER,
>>>> -                                  I2S_XFER_TXS_START |
>>>> I2S_XFER_RXS_START,
>>>> -                                  I2S_XFER_TXS_START |
>>>> I2S_XFER_RXS_START);
>>>> +                                  I2S_XFER_RXS_START,
>>>> +                                  I2S_XFER_RXS_START);
>>>>
>>>>                  i2s->rx_start = true;
>>>>          } else {
>>>> @@ -138,27 +134,23 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev
>>>> *i2s, int on)
>>>>                  regmap_update_bits(i2s->regmap, I2S_DMACR,
>>>>                                     I2S_DMACR_RDE_ENABLE,
>>>> I2S_DMACR_RDE_DISABLE);
>>>>
>>>> -               if (!i2s->tx_start) {
>>>> -                       regmap_update_bits(i2s->regmap, I2S_XFER,
>>>> -                                          I2S_XFER_TXS_START |
>>>> -                                          I2S_XFER_RXS_START,
>>>> -                                          I2S_XFER_TXS_STOP |
>>>> -                                          I2S_XFER_RXS_STOP);
>>>> +               regmap_update_bits(i2s->regmap, I2S_XFER,
>>>> +                                  I2S_XFER_RXS_START,
>>>> +                                  I2S_XFER_RXS_STOP);
>>>>
>>>> -                       regmap_update_bits(i2s->regmap, I2S_CLR,
>>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC,
>>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC);
>>>> +               regmap_update_bits(i2s->regmap, I2S_CLR,
>>>> +                                  I2S_CLR_RXC,
>>>> +                                  I2S_CLR_RXC);
>>>>
>>>> -                       regmap_read(i2s->regmap, I2S_CLR, &val);
>>>> +               regmap_read(i2s->regmap, I2S_CLR, &val);
>>>>
>>>> -                       /* Should wait for clear operation to finish */
>>>> -                       while (val) {
>>>> -                               regmap_read(i2s->regmap, I2S_CLR, &val);
>>>> -                               retry--;
>>>> -                               if (!retry) {
>>>> -                                       dev_warn(i2s->dev, "fail to
>>>> clear\n");
>>>> -                                       break;
>>>> -                               }
>>>> +               /* Should wait for clear operation to finish */
>>>> +               while (val & I2S_CLR_RXC) {
>>>> +                       regmap_read(i2s->regmap, I2S_CLR, &val);
>>>> +                       retry--;
>>>> +                       if (!retry) {
>>>> +                               dev_warn(i2s->dev, "fail to clear\n");
>>>> +                               break;
>>>>                          }
>>>>                  }
>>>>          }
>>>> --
>>>> 2.6.3.462.gbe2c914
>>>
>>>
>>> Using my Veyron Jerry Chromebook wiht latest kernel I found that the
>>> speakers doesn't work. Bisect points to this patch as the offending
>>> commit. However your changes looks reasonable the fact is that
>>> reverting the patch makes the audio work again on my device. I need to
>>> dig a bit more into the issue, but meanwhile, any idea on what is
>>> happening ? Can I ask which device did you test?
>>
>>
>> I tested this on a Radxa Rock2 square.  This change fixed an issue I
>> found when running separate processes for playback and recording (I was
>> testing with arecord and speaker-test IIRC) but I don't think that
>> should be relevant.  I just read through the patch again and I can't see
>> anything obviously wrong so I'm afraid I don't have any idea what's
>> causing the problem you're seeing.
>>
> Do you have test playback/capture at the same time? I think you may
> reproduce this issue if you do as follows:
>
> step 1: tinyplay test.wav -D 0 -d 0 -p 1024 -n 4 &
> step 2: tinycap r.wav -D 0 -d 0 -p 1024 -n 4 &
>
> you will find that there is no music now.
>
> because of this problem, we enable tx/rx at the same time to WA this issue.
>

I can confirm that reverting John's patch audio playback/capture at
the same time works on my Veyron Jerry Chromebook.

> May I know what's the issue that you met before?
>>
>>
>> John
>>
>> _______________________________________________
>> Linux-rockchip mailing list
>> Linux-rockchip at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-rockchip
>>
>>
>>
>
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel at alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel


From wxt at rock-chips.com  Tue May  3 02:33:28 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue,  3 May 2016 17:33:28 +0800
Subject: [PATCH v2 0/5] Thermal: Support for hardware-tracked trip points
Message-ID: <1462268013-14992-1-git-send-email-wxt@rock-chips.com>

The history patches come from Mikko and Sascha.
http://thread.gmane.org/gmane.linux.power-management.general/59451

Now, I pick them up to continue upstream.
Nevermind!

This series history patches:
v1: https://lkml.org/lkml/2016/4/24/227

This series adds support for hardware trip points. It picks up earlier
work from Mikko Perttunen. Mikko implemented hardware trip points as part
of the device tree support. It was suggested back then to move the
functionality to the thermal core instead of putting more code into the
device tree support. This series does exactly that.

This series patches rebase the conflicts.
Note that the hardware-tracked trip points are very well tested currently.

Verified and tested on https://github.com/Caesar-github/rockchip/tree/wip/fixes-thermal-0503
That's based on linux-kernel 20160502.
.Linux version 4.6.0-rc6-next-20160502-08922-g860ed34 (wxt at nb)


Changes in v2:
- update the sysfs-api.txt for set_trips
- add the commit in patch[v2 2/5].
- Update the commit for patch[v2 4/5].

Caesar Wang (1):
  thermal: rockchip: add the set_trips function

Sascha Hauer (4):
  thermal: Add support for hardware-tracked trip points
  thermal: of: implement .set_trips for device tree thermal zones
  thermal: streamline get_trend callbacks
  thermal: bang-bang governor: act on lower trip boundary

 Documentation/thermal/sysfs-api.txt                |  7 +++
 drivers/thermal/gov_bang_bang.c                    |  2 +-
 drivers/thermal/of-thermal.c                       | 23 +++++-----
 drivers/thermal/rockchip_thermal.c                 | 39 ++++++++++++++++
 drivers/thermal/thermal_core.c                     | 52 ++++++++++++++++++++++
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 25 ++++-------
 include/linux/thermal.h                            |  9 +++-
 7 files changed, 128 insertions(+), 29 deletions(-)

-- 
1.9.1



From wxt at rock-chips.com  Tue May  3 02:33:33 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue,  3 May 2016 17:33:33 +0800
Subject: [PATCH v2 5/5] thermal: rockchip: add the set_trips function
In-Reply-To: <1462268013-14992-1-git-send-email-wxt@rock-chips.com>
References: <1462268013-14992-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1462268013-14992-6-git-send-email-wxt@rock-chips.com>

Whenever the current temperature is updated, the trip points immediately
below and above the current temperature are found. A sensor driver
callback `set_trips' is then called with the temperatures.
Lastly, The sensor will trigger the hardware high temperature interrupts
to increase the sampleing rate and throttle frequency to limit the
temperature rising When performing passive cooling.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Zhang Rui <rui.zhang at intel.com>
Cc: Eduardo Valentin <edubezval at gmail.com>
Cc: linux-pm at vger.kernel.org

---

Changes in v2: None

 drivers/thermal/rockchip_thermal.c | 39 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index 5d491f1..8175cdb 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -96,6 +96,7 @@ struct chip_tsadc_table {
  * @initialize: SoC special initialize tsadc controller method
  * @irq_ack: clear the interrupt
  * @get_temp: get the temperature
+ * @set_alarm_temp: set the high temperature interrupt
  * @set_tshut_temp: set the hardware-controlled shutdown temperature
  * @set_tshut_mode: set the hardware-controlled shutdown mode
  * @table: the chip-specific conversion table
@@ -119,6 +120,8 @@ struct rockchip_tsadc_chip {
 	/* Per-sensor methods */
 	int (*get_temp)(struct chip_tsadc_table table,
 			int chn, void __iomem *reg, int *temp);
+	void (*set_alarm_temp)(struct chip_tsadc_table table,
+			       int chn, void __iomem *reg, int temp);
 	void (*set_tshut_temp)(struct chip_tsadc_table table,
 			       int chn, void __iomem *reg, int temp);
 	void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
@@ -183,6 +186,7 @@ struct rockchip_thermal_data {
 #define TSADCV2_INT_EN				0x08
 #define TSADCV2_INT_PD				0x0c
 #define TSADCV2_DATA(chn)			(0x20 + (chn) * 0x04)
+#define TSADCV2_COMP_INT(chn)		        (0x30 + (chn) * 0x04)
 #define TSADCV2_COMP_SHUT(chn)		        (0x40 + (chn) * 0x04)
 #define TSADCV2_HIGHT_INT_DEBOUNCE		0x60
 #define TSADCV2_HIGHT_TSHUT_DEBOUNCE		0x64
@@ -628,6 +632,20 @@ static int rk_tsadcv2_get_temp(struct chip_tsadc_table table,
 	return rk_tsadcv2_code_to_temp(table, val, temp);
 }
 
+static void rk_tsadcv2_alarm_temp(struct chip_tsadc_table table,
+				  int chn, void __iomem *regs, int temp)
+{
+	u32 alarm_value, int_en;
+
+	alarm_value = rk_tsadcv2_temp_to_code(table, temp);
+	writel_relaxed(alarm_value & table.data_mask,
+		       regs + TSADCV2_COMP_INT(chn));
+
+	int_en = readl_relaxed(regs + TSADCV2_INT_EN);
+	int_en |= TSADCV2_INT_SRC_EN(chn);
+	writel_relaxed(int_en, regs + TSADCV2_INT_EN);
+}
+
 static void rk_tsadcv2_tshut_temp(struct chip_tsadc_table table,
 				  int chn, void __iomem *regs, int temp)
 {
@@ -670,6 +688,7 @@ static const struct rockchip_tsadc_chip rk3228_tsadc_data = {
 	.irq_ack = rk_tsadcv3_irq_ack,
 	.control = rk_tsadcv3_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -694,6 +713,7 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
 	.irq_ack = rk_tsadcv2_irq_ack,
 	.control = rk_tsadcv2_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -718,6 +738,7 @@ static const struct rockchip_tsadc_chip rk3366_tsadc_data = {
 	.irq_ack = rk_tsadcv3_irq_ack,
 	.control = rk_tsadcv3_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -742,6 +763,7 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = {
 	.irq_ack = rk_tsadcv2_irq_ack,
 	.control = rk_tsadcv2_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -766,6 +788,7 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
 	.irq_ack = rk_tsadcv3_irq_ack,
 	.control = rk_tsadcv3_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -826,6 +849,21 @@ static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
+static int rockchip_thermal_set_trips(void *_sensor, int low, int high)
+{
+	struct rockchip_thermal_sensor *sensor = _sensor;
+	struct rockchip_thermal_data *thermal = sensor->thermal;
+	const struct rockchip_tsadc_chip *tsadc = thermal->chip;
+
+	dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n",
+		__func__, sensor->id, low, high);
+
+	tsadc->set_alarm_temp(tsadc->table,
+			      sensor->id, thermal->regs, high);
+
+	return 0;
+}
+
 static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
 {
 	struct rockchip_thermal_sensor *sensor = _sensor;
@@ -843,6 +881,7 @@ static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
 
 static const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = {
 	.get_temp = rockchip_thermal_get_temp,
+	.set_trips = rockchip_thermal_set_trips,
 };
 
 static int rockchip_configure_from_dt(struct device *dev,
-- 
1.9.1



From felipe.balbi at linux.intel.com  Tue May  3 02:33:31 2016
From: felipe.balbi at linux.intel.com (Felipe Balbi)
Date: Tue, 03 May 2016 12:33:31 +0300
Subject: [PATCH] usb: xhci-mtk: fixup mouse wakeup failure during system
 suspend
In-Reply-To: <1462266591.11651.34.camel@mhfsdcap03>
References: <1461204293-18243-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462261458.11651.7.camel@mhfsdcap03> <87vb2vfujq.fsf@intel.com>
 <1462266591.11651.34.camel@mhfsdcap03>
Message-ID: <87mvo7fpuc.fsf@intel.com>


Hi,

chunfeng yun <chunfeng.yun at mediatek.com> writes:
>> chunfeng yun <chunfeng.yun at mediatek.com> writes:
>> > On Thu, 2016-04-21 at 10:04 +0800, Chunfeng Yun wrote:
>> >> Click mouse after xhci suspend completion but before system suspend
>> >> completion, system will not be waken up by mouse if the duration of
>> >> them is larger than 20ms which is the device UFP's resume signaling
>> 
>> what is "them" here ? The duration of what is longer than 20ms ?
> They are "xhci suspend completion" and "system suspend completion";
>
> It's time duration

okay. So if xhci suspend takes longer than 20ms your SPM doesn't see a
wakeup ?

>> >> lasted. Another reason is that the SPM is not enabled before system
>> 
>> what's SPM ?
> It is System Power Management which is powered off when system is
> running in normal mode, and is powered on when system enters suspend
> mode. It is used to wakeup system when some wakeup sources, such as
> bluetooth or powerkey etc, tigger wakeup event.

okay, thanks

>> >> suspend compeltion, this causes SPM also not notice the resume signal.
>>            ^^^^^^^^^^
>>            completion
>> 
>> >> So in order to reduce the duration less than 20ms, make use of
>> >> syscore's suspend/resume interface.
>> 
>> no, this is the wrong approach
> But it seems only one workable approach from software side

I wouldn't say that. It seems to me SPM should be enabled earlier.

>> >> Because the syscore runs on irq disabled context, and xhci's
>> >> suspend/resume calls some sleeping functions, enable local irq
>> >> and then disable it during suspend/resume. This may be not a problem,
>> >> since only boot CPU is runing.
>> 
>> another problem :) calling local_irq_{enable,disable}() is an indication
>> that something's wrong.
> Oh!
>
> BTW: There will be warning logs if they are not called.

yeah, I got that :-) But it's still wrong to use
local_irq_{enable,disable}() the way you're using them :-)

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160503/6371eb03/attachment.sig>

From arnd at arndb.de  Tue May  3 02:36:21 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 03 May 2016 11:36:21 +0200
Subject: [PATCH 1/2] Documentation: DT: bindings: Add Broadcom STB PCIe
 bindings
In-Reply-To: <1462238749-19715-2-git-send-email-f.fainelli@gmail.com>
References: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>
 <1462238749-19715-2-git-send-email-f.fainelli@gmail.com>
Message-ID: <3271950.m2VfxN38UI@wuerfel>

On Monday 02 May 2016 18:25:48 Florian Fainelli wrote:
> diff --git a/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
> new file mode 100644
> index 000000000000..922317969ab5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
> @@ -0,0 +1,81 @@
> +Brcmstb PCIe Host Controller Device Tree Bindings
> +
> +Introduction:
> +
> +The brcmstb host controller closely follows the example set in
> +
> +	[1] http://devicetree.org/Device_Tree_Usage#PCI_Host_Bridge
> +
> +The rest of this document explains some added customizations and
> +offers an example Brcmstb PCIe host controller DT node.
> +
> +Required Properties:
> +  reg -- the register start address and length for the PCIe block.
> +      Additional start,length pairs may be specified for clock addresses.
> +  interrupts -- this must be specified but it is used indirectly.  Interrupt
> +      zero must be specified; the Brcmstb driver code uses this interrupt
> +      to determine the offset used for all interrupts, specifically, those
> +      listed in interrupt-map.

The description for "interrupts" is lacking. You don't mention here
what the interrupt names are supposed to be, how many interrupts there
are and which functions they are connected to.

> +  ranges -- See [1]; a specification of the outbound windows for the host
> +      controller.  Each outbound window is described by a 7-tuple:
> +          (3 entries) -- PCIe space start address (0th entry is ignored).

The "(0th entry is ignored)" makes no sense

> +          (2 entries) -- CPU/System start address

Strictly speaking, this is the address relative to the parent node, not to
the root. The binding for a device should not care about where in the DT
that device is located.

> +          (2 entries) -- Size of region.
> +      Due to hardware limitations, there may be a maximum of four windows
> +      specified.

I see that the example lists two separate non-prefetchable areas. It would
be good to mention what types of mappings are valid for this device, in
particular whether prefetchable, 64-bit or I/O space are possible.

I would also mention whether the ranges for this driver are meant to
describe what windows are set up by the boot loader, or whether they
describe the windows that the driver itself needs to set up.

> +  #interrupt-cells -- number of cells used to describe the interrupt.
> +  interrupt-map -- See [1]; each interrupt requires 7 entries, and
> +      currently all but the fifth entry (order 0) -- the interrupt
> +      number -- is ignored.  There must be four interrupts specified
> +      for the PCI's INTA, INTB, INTC, and INTD.

This does not describe the relevant properties, and the part it describes
looks wrong. I think you should just refer to the generic PCI binding
that describes how IRQs get mapped for the odd cases e.g. when you
have a PCIe-PCI bridge and a PCI slot IRQ line is connected to a GPIO.

Also, the '7' entries here only makes sense if #address-cells for the
parent is '2'.

> +Optional Properties:
> +  interrupt-names -- names of the interrupts listed in the interrupt map.
> +  clocks -- list of clock phandles.  If specified, this should list one
> +      clock.
> +  clock-names -- the "local" names of the clocks specified in 'clocks'.  Note
> +      that if the 'clocks' property is given, 'clock-names' is mandatory,
> +      and the name of the clock is expected to be "sw_pcie".

Replace underscores with dashes, as in "sw-pcie". What is "sw" anyway?

> +  brcm,ssc -- (boolean) indicates usage of spread-spectrum clocking.
> +  brcm,gen --  (integer) indicates desired generation of link:
> +      1 => 2.5 Gbps, 2 => 5.0 Gbps, 3 => 8.0 Gbps.

Shouldn't the link generation be probed automatically?

> +  supply-names -- the names of voltage regulators that the root
> +      complex should turn off/on/on on suspend/resume/boot.  This
> +      is a string list.
> +  supplies -- A collection of phandles to a regulator nodes, see
> +	Documentation/devicetree/bindings/regulator/ for specific
> +	bindings. The number and order of phandles must match
> +	exactly the number of strings in the "supply-names" property.

This does not follow the binding for regulators. Please change
this to match what others do.

> +Example Node:
> +
> +	pcie at f0460000 {
> +		reg = <0x0 0xf0460000 0x0 0x9310>;

		regs

> +		interrupts = <0x0 0x0 0x4>;
> +		compatible = "brcm,pci-plat-dev";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +		ranges = <0x02000000 0x00000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x08000000
> +			  0x02000000 0x00000000 0x08000000 0x00000000 0xc8000000 0x00000000 0x08000000>;
> +		#interrupt-cells = <1>;
> +		interrupt-map-mask = <0xf800 0 0 7>;
> +		interrupt-map = <0 0 0 1 &intc 47 3
> +				 0 0 0 2 &intc 48 3
> +				 0 0 0 3 &intc 49 3
> +				 0 0 0 4 &intc 50 3>;

Please reformat the lists to look like

		ranges = <0x02000000 0x00000000 0x00000000  0x00000000 0xc0000000  0x00000000 0x08000000>
			  <0x02000000 0x00000000 0x08000000  0x00000000 0xc8000000  0x00000000 0x08000000>;
		interrupt-map = <0 0 0 1  &intc  47 3>,
				 <0 0 0 2  &intc  48 3>,
				 <0 0 0 3  &intc  49 3>,
				 <0 0 0 4  &intc  50 3>;


> +		interrupt-names = "pcie_0_inta",
> +				  "pcie_0_intb",
> +				  "pcie_0_intc",
> +				  "pcie_0_intd";

interrupt-names is misplaced here, you only have one entry in the "interrupts"
property, and is different from the "inta" in your interrupt-map.

	Arnd


From vz at mleia.com  Tue May  3 02:38:44 2016
From: vz at mleia.com (Vladimir Zapolskiy)
Date: Tue, 3 May 2016 12:38:44 +0300
Subject: [PATCH v2 2/4] irqchip: add LPC32xx interrupt controller driver
In-Reply-To: <5728627B.1020602@arm.com>
References: <1461545990-25560-1-git-send-email-vz@mleia.com>
 <1461546038-25668-1-git-send-email-vz@mleia.com>
 <1461678082.9433.3.camel@localhost> <57228B68.8030706@mleia.com>
 <5728627B.1020602@arm.com>
Message-ID: <572871A4.5050003@mleia.com>

On 03.05.2016 11:34, Marc Zyngier wrote:
> On 28/04/16 23:15, Vladimir Zapolskiy wrote:
>> On 26.04.2016 16:41, Sylvain Lemieux wrote:
>>> Hi Vladimir,
>>>
>>> On Mon, 2016-04-25 at 04:00 +0300, Vladimir Zapolskiy wrote:
>>>> The change adds improved support of NXP LPC32xx MIC, SIC1 and SIC2
>>>> interrupt controllers.
>>>>
>>>> This is a list of new features in comparison to the legacy driver:
>>>> * irq types are taken from device tree settings, no more need to
>>>>   hardcode them,
>>>> * old driver is based on irq_domain_add_legacy, which causes problems
>>>>   with handling MIC hardware interrupt 0 produced by SIC1,
>>>> * there is one driver for MIC, SIC1 and SIC2, no more need to handle
>>>>   them separately, e.g. have two separate handlers for SIC1 and SIC2,
>>>> * the driver does not have any dependencies on hardcoded register
>>>>   offsets,
>>>> * the driver is much simpler for maintenance,
>>>> * SPARSE_IRQS option is supported.
>>>>
>>>> Legacy LPC32xx interrupt controller driver was broken since commit
>>>> 76ba59f8366f ("genirq: Add irq_domain-aware core IRQ handler"), which
>>>> requires a private interrupt handler, otherwise any SIC1 generated
>>>> interrupt (mapped to MIC hwirq 0) breaks the kernel with the message
>>>> "unexpected IRQ trap at vector 00".
>>>>
>>>> The change disables compilation of a legacy driver found at
>>>> arch/arm/mach-lpc32xx/irq.c, the file will be removed in a separate
>>>> commit.
>>>>
>>>> Signed-off-by: Vladimir Zapolskiy <vz at mleia.com>
>>>> ---
>>>> Changes from v1 to v2:
>>>> * added chained_irq_{enter,exit} for SIC chained handler,
>>>> * use {writel,readl}_relaxed flavour of io access functions,
>>>> * changed anchor data type to access iomem from struct irq_domain
>>>>   to private struct lpc32xx_irq_chip,
>>>> * do not read irq status register twice on every irq event,
>>>> * resource deallocation fixes on error path of irqchip driver init,
>>>> * removed handling of "interrupt-controller-name" property, name
>>>>   is constructed from mic/sic type and controller's physical address,
>>>> * minor improvements (renames, __ffs instead of ffs, etc.)
>>>>
>>>> Many kudos to Marc for review of v1.
>>>>
>>>>  arch/arm/Kconfig                |   2 +
>>>>  arch/arm/mach-lpc32xx/phy3250.c |   1 -
>>>>  drivers/irqchip/Makefile        |   1 +
>>>>  drivers/irqchip/irq-lpc32xx.c   | 238 ++++++++++++++++++++++++++++++++++++++++
>>>>  4 files changed, 241 insertions(+), 1 deletion(-)
>>>>  create mode 100644 drivers/irqchip/irq-lpc32xx.c
>>>>
>>> I tested the driver on a custom LPC3250 board; I was having at
>>> least 1 interrupt generated from each source (MIC/SIC1/SIC2).
>>>
>>> Tested-by: Sylvain Lemieux <slemieux.tyco at gmail.com>
>>>
>>
>> Thomas, Marc, Jason, Russell,
>>
>> in your opinion would it be still possible to accept this change v2 2/4 for v4.7?
> 
> I'll queue them.
> 

Marc, thank you in advance, please note that I ask to review/pick up
only 2/4 for v4.7 ("irqchip: add LPC32xx interrupt controller driver"),
DT changes are merged through arm-soc and the last 4/4 clean-up can
be deferred till v4.8.

--
With best wishes,
Vladimir


From john at metanate.com  Tue May  3 02:43:18 2016
From: john at metanate.com (John Keeping)
Date: Tue, 3 May 2016 10:43:18 +0100
Subject: [alsa-devel] [PATCH 1/2] ASoC: rockchip: i2s: separate capture
 and playback
In-Reply-To: <CAFqH_50D5PQOkpCDefds3Nyktvitoe2Wx=YcXM2POox1ooO=0g@mail.gmail.com>
References: <1449657147-26959-1-git-send-email-john@metanate.com>
 <CAFqH_52C4JKno4uyt54UdWKAJKM4FPGRiQaQQ9_H-Mz1Cr+Hqg@mail.gmail.com>
 <20160430070049.GF14612@serenity.lan>
 <57282532.7000402@rock-chips.com>
 <CAFqH_50D5PQOkpCDefds3Nyktvitoe2Wx=YcXM2POox1ooO=0g@mail.gmail.com>
Message-ID: <20160503104318.62739a91.john@metanate.com>

Hi Enric,

On Tue, 3 May 2016 11:16:58 +0200, Enric Balletbo Serra wrote:
> 2016-05-03 6:12 GMT+02:00 sugar <sugar.zhang at rock-chips.com>:
> > On 4/30/2016 15:00, John Keeping Wrote:  
> >> On Fri, Apr 29, 2016 at 04:59:27PM +0200, Enric Balletbo Serra wrote:  
> >>>
> >>> 2015-12-09 11:32 GMT+01:00 John Keeping <john at metanate.com>:  
> >>>>
> >>>> If we only clear the tx/rx state when both are disabled it is not
> >>>> possible to start/stop one multiple times while the other is running.
> >>>> Since the two are independently controlled, treat them as such and
> >>>> remove the false dependency between capture and playback.
> >>>>
> >>>> Signed-off-by: John Keeping <john at metanate.com>
> >>>> ---
> >>>>   sound/soc/rockchip/rockchip_i2s.c | 72
> >>>> +++++++++++++++++----------------------
> >>>>   1 file changed, 32 insertions(+), 40 deletions(-)
> >>>>
> >>>> diff --git a/sound/soc/rockchip/rockchip_i2s.c
> >>>> b/sound/soc/rockchip/rockchip_i2s.c
> >>>> index 83b1b9c..acc6225 100644
> >>>> --- a/sound/soc/rockchip/rockchip_i2s.c
> >>>> +++ b/sound/soc/rockchip/rockchip_i2s.c
> >>>> @@ -82,8 +82,8 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev
> >>>> *i2s, int on)
> >>>>                                     I2S_DMACR_TDE_ENABLE,
> >>>> I2S_DMACR_TDE_ENABLE);
> >>>>
> >>>>                  regmap_update_bits(i2s->regmap, I2S_XFER,
> >>>> -                                  I2S_XFER_TXS_START |
> >>>> I2S_XFER_RXS_START,
> >>>> -                                  I2S_XFER_TXS_START |
> >>>> I2S_XFER_RXS_START);
> >>>> +                                  I2S_XFER_TXS_START,
> >>>> +                                  I2S_XFER_TXS_START);
> >>>>
> >>>>                  i2s->tx_start = true;
> >>>>          } else {
> >>>> @@ -92,27 +92,23 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev
> >>>> *i2s, int on)
> >>>>                  regmap_update_bits(i2s->regmap, I2S_DMACR,
> >>>>                                     I2S_DMACR_TDE_ENABLE,
> >>>> I2S_DMACR_TDE_DISABLE);
> >>>>
> >>>> -               if (!i2s->rx_start) {
> >>>> -                       regmap_update_bits(i2s->regmap, I2S_XFER,
> >>>> -                                          I2S_XFER_TXS_START |
> >>>> -                                          I2S_XFER_RXS_START,
> >>>> -                                          I2S_XFER_TXS_STOP |
> >>>> -                                          I2S_XFER_RXS_STOP);
> >>>> +               regmap_update_bits(i2s->regmap, I2S_XFER,
> >>>> +                                  I2S_XFER_TXS_START,
> >>>> +                                  I2S_XFER_TXS_STOP);
> >>>>
> >>>> -                       regmap_update_bits(i2s->regmap, I2S_CLR,
> >>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC,
> >>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC);
> >>>> +               regmap_update_bits(i2s->regmap, I2S_CLR,
> >>>> +                                  I2S_CLR_TXC,
> >>>> +                                  I2S_CLR_TXC);
> >>>>
> >>>> -                       regmap_read(i2s->regmap, I2S_CLR, &val);
> >>>> +               regmap_read(i2s->regmap, I2S_CLR, &val);
> >>>>
> >>>> -                       /* Should wait for clear operation to finish */
> >>>> -                       while (val) {
> >>>> -                               regmap_read(i2s->regmap, I2S_CLR, &val);
> >>>> -                               retry--;
> >>>> -                               if (!retry) {
> >>>> -                                       dev_warn(i2s->dev, "fail to
> >>>> clear\n");
> >>>> -                                       break;
> >>>> -                               }
> >>>> +               /* Should wait for clear operation to finish */
> >>>> +               while (val & I2S_CLR_TXC) {
> >>>> +                       regmap_read(i2s->regmap, I2S_CLR, &val);
> >>>> +                       retry--;
> >>>> +                       if (!retry) {
> >>>> +                               dev_warn(i2s->dev, "fail to clear\n");
> >>>> +                               break;
> >>>>                          }
> >>>>                  }
> >>>>          }
> >>>> @@ -128,8 +124,8 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev
> >>>> *i2s, int on)
> >>>>                                     I2S_DMACR_RDE_ENABLE,
> >>>> I2S_DMACR_RDE_ENABLE);
> >>>>
> >>>>                  regmap_update_bits(i2s->regmap, I2S_XFER,
> >>>> -                                  I2S_XFER_TXS_START |
> >>>> I2S_XFER_RXS_START,
> >>>> -                                  I2S_XFER_TXS_START |
> >>>> I2S_XFER_RXS_START);
> >>>> +                                  I2S_XFER_RXS_START,
> >>>> +                                  I2S_XFER_RXS_START);
> >>>>
> >>>>                  i2s->rx_start = true;
> >>>>          } else {
> >>>> @@ -138,27 +134,23 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev
> >>>> *i2s, int on)
> >>>>                  regmap_update_bits(i2s->regmap, I2S_DMACR,
> >>>>                                     I2S_DMACR_RDE_ENABLE,
> >>>> I2S_DMACR_RDE_DISABLE);
> >>>>
> >>>> -               if (!i2s->tx_start) {
> >>>> -                       regmap_update_bits(i2s->regmap, I2S_XFER,
> >>>> -                                          I2S_XFER_TXS_START |
> >>>> -                                          I2S_XFER_RXS_START,
> >>>> -                                          I2S_XFER_TXS_STOP |
> >>>> -                                          I2S_XFER_RXS_STOP);
> >>>> +               regmap_update_bits(i2s->regmap, I2S_XFER,
> >>>> +                                  I2S_XFER_RXS_START,
> >>>> +                                  I2S_XFER_RXS_STOP);
> >>>>
> >>>> -                       regmap_update_bits(i2s->regmap, I2S_CLR,
> >>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC,
> >>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC);
> >>>> +               regmap_update_bits(i2s->regmap, I2S_CLR,
> >>>> +                                  I2S_CLR_RXC,
> >>>> +                                  I2S_CLR_RXC);
> >>>>
> >>>> -                       regmap_read(i2s->regmap, I2S_CLR, &val);
> >>>> +               regmap_read(i2s->regmap, I2S_CLR, &val);
> >>>>
> >>>> -                       /* Should wait for clear operation to finish */
> >>>> -                       while (val) {
> >>>> -                               regmap_read(i2s->regmap, I2S_CLR, &val);
> >>>> -                               retry--;
> >>>> -                               if (!retry) {
> >>>> -                                       dev_warn(i2s->dev, "fail to
> >>>> clear\n");
> >>>> -                                       break;
> >>>> -                               }
> >>>> +               /* Should wait for clear operation to finish */
> >>>> +               while (val & I2S_CLR_RXC) {
> >>>> +                       regmap_read(i2s->regmap, I2S_CLR, &val);
> >>>> +                       retry--;
> >>>> +                       if (!retry) {
> >>>> +                               dev_warn(i2s->dev, "fail to clear\n");
> >>>> +                               break;
> >>>>                          }
> >>>>                  }
> >>>>          }
> >>>> --
> >>>> 2.6.3.462.gbe2c914  
> >>>
> >>>
> >>> Using my Veyron Jerry Chromebook wiht latest kernel I found that the
> >>> speakers doesn't work. Bisect points to this patch as the offending
> >>> commit. However your changes looks reasonable the fact is that
> >>> reverting the patch makes the audio work again on my device. I need to
> >>> dig a bit more into the issue, but meanwhile, any idea on what is
> >>> happening ? Can I ask which device did you test?  
> >>
> >>
> >> I tested this on a Radxa Rock2 square.  This change fixed an issue I
> >> found when running separate processes for playback and recording (I was
> >> testing with arecord and speaker-test IIRC) but I don't think that
> >> should be relevant.  I just read through the patch again and I can't see
> >> anything obviously wrong so I'm afraid I don't have any idea what's
> >> causing the problem you're seeing.
> >>  
> > Do you have test playback/capture at the same time? I think you may
> > reproduce this issue if you do as follows:
> >
> > step 1: tinyplay test.wav -D 0 -d 0 -p 1024 -n 4 &
> > step 2: tinycap r.wav -D 0 -d 0 -p 1024 -n 4 &
> >
> > you will find that there is no music now.
> >
> > because of this problem, we enable tx/rx at the same time to WA this issue.
> >  
> 
> I can confirm that reverting John's patch audio playback/capture at
> the same time works on my Veyron Jerry Chromebook.

Have you tried stopping one of the processes and then starting it again
(without touching the other process)?  That's the case that was broken
for me without this patch.

I have had a quick look through the code I'm using and I noticed that I
have another change that hasn't been sent upstream, which marks the
I2S_FIFOLR register as volatile in rockchip_i2s_volatile_reg():

-- >8 --
Subject: [PATCH] ASoC: rockchip: i2s: mark FIFOLR register volatile

The FIFO levels will be updated by the device so they should not be
cached.

Signed-off-by: John Keeping <john at metanate.com>
---
 sound/soc/rockchip/rockchip_i2s.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index d78f4c925b02..b517d8abcc40 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -434,6 +434,7 @@ static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg)
 	switch (reg) {
 	case I2S_INTSR:
 	case I2S_CLR:
+	case I2S_FIFOLR:
 		return true;
 	default:
 		return false;
-- 8< --


Regards,
John


From marc.zyngier at arm.com  Tue May  3 02:50:13 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 10:50:13 +0100
Subject: [PATCH v2 2/4] irqchip: add LPC32xx interrupt controller driver
In-Reply-To: <572871A4.5050003@mleia.com>
References: <1461545990-25560-1-git-send-email-vz@mleia.com>
 <1461546038-25668-1-git-send-email-vz@mleia.com>
 <1461678082.9433.3.camel@localhost> <57228B68.8030706@mleia.com>
 <5728627B.1020602@arm.com> <572871A4.5050003@mleia.com>
Message-ID: <57287455.8050706@arm.com>

On 03/05/16 10:38, Vladimir Zapolskiy wrote:
> On 03.05.2016 11:34, Marc Zyngier wrote:
>> On 28/04/16 23:15, Vladimir Zapolskiy wrote:
>>> On 26.04.2016 16:41, Sylvain Lemieux wrote:
>>>> Hi Vladimir,
>>>>
>>>> On Mon, 2016-04-25 at 04:00 +0300, Vladimir Zapolskiy wrote:
>>>>> The change adds improved support of NXP LPC32xx MIC, SIC1 and SIC2
>>>>> interrupt controllers.
>>>>>
>>>>> This is a list of new features in comparison to the legacy driver:
>>>>> * irq types are taken from device tree settings, no more need to
>>>>>   hardcode them,
>>>>> * old driver is based on irq_domain_add_legacy, which causes problems
>>>>>   with handling MIC hardware interrupt 0 produced by SIC1,
>>>>> * there is one driver for MIC, SIC1 and SIC2, no more need to handle
>>>>>   them separately, e.g. have two separate handlers for SIC1 and SIC2,
>>>>> * the driver does not have any dependencies on hardcoded register
>>>>>   offsets,
>>>>> * the driver is much simpler for maintenance,
>>>>> * SPARSE_IRQS option is supported.
>>>>>
>>>>> Legacy LPC32xx interrupt controller driver was broken since commit
>>>>> 76ba59f8366f ("genirq: Add irq_domain-aware core IRQ handler"), which
>>>>> requires a private interrupt handler, otherwise any SIC1 generated
>>>>> interrupt (mapped to MIC hwirq 0) breaks the kernel with the message
>>>>> "unexpected IRQ trap at vector 00".
>>>>>
>>>>> The change disables compilation of a legacy driver found at
>>>>> arch/arm/mach-lpc32xx/irq.c, the file will be removed in a separate
>>>>> commit.
>>>>>
>>>>> Signed-off-by: Vladimir Zapolskiy <vz at mleia.com>
>>>>> ---
>>>>> Changes from v1 to v2:
>>>>> * added chained_irq_{enter,exit} for SIC chained handler,
>>>>> * use {writel,readl}_relaxed flavour of io access functions,
>>>>> * changed anchor data type to access iomem from struct irq_domain
>>>>>   to private struct lpc32xx_irq_chip,
>>>>> * do not read irq status register twice on every irq event,
>>>>> * resource deallocation fixes on error path of irqchip driver init,
>>>>> * removed handling of "interrupt-controller-name" property, name
>>>>>   is constructed from mic/sic type and controller's physical address,
>>>>> * minor improvements (renames, __ffs instead of ffs, etc.)
>>>>>
>>>>> Many kudos to Marc for review of v1.
>>>>>
>>>>>  arch/arm/Kconfig                |   2 +
>>>>>  arch/arm/mach-lpc32xx/phy3250.c |   1 -
>>>>>  drivers/irqchip/Makefile        |   1 +
>>>>>  drivers/irqchip/irq-lpc32xx.c   | 238 ++++++++++++++++++++++++++++++++++++++++
>>>>>  4 files changed, 241 insertions(+), 1 deletion(-)
>>>>>  create mode 100644 drivers/irqchip/irq-lpc32xx.c
>>>>>
>>>> I tested the driver on a custom LPC3250 board; I was having at
>>>> least 1 interrupt generated from each source (MIC/SIC1/SIC2).
>>>>
>>>> Tested-by: Sylvain Lemieux <slemieux.tyco at gmail.com>
>>>>
>>>
>>> Thomas, Marc, Jason, Russell,
>>>
>>> in your opinion would it be still possible to accept this change v2 2/4 for v4.7?
>>
>> I'll queue them.
>>
> 
> Marc, thank you in advance, please note that I ask to review/pick up
> only 2/4 for v4.7 ("irqchip: add LPC32xx interrupt controller driver"),
> DT changes are merged through arm-soc and the last 4/4 clean-up can
> be deferred till v4.8.

Right. I'll drop patch 1/4 then.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From arnd at arndb.de  Tue May  3 02:57:43 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 03 May 2016 11:57:43 +0200
Subject: [PATCH 2/2] pci: host: Add Broadcom STB PCIE RC controller
In-Reply-To: <1462238749-19715-3-git-send-email-f.fainelli@gmail.com>
References: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>
 <1462238749-19715-3-git-send-email-f.fainelli@gmail.com>
Message-ID: <2339405.90vXV1p6zU@wuerfel>

On Monday 02 May 2016 18:25:49 Florian Fainelli wrote:

> +/* Helper macros for reading registers varying from chip-to-chip */
> +#define IDX_ADDR(pcie)			((pcie->base) + \
> +					 pcie->reg_offsets[EXT_CFG_INDEX])
> +#define DATA_ADDR(pcie)			((pcie->base) + \
> +					 pcie->reg_offsets[EXT_CFG_DATA])
> +#define PCIE_RGR1_SW_INIT_1(pcie)	((pcie->base) + \
> +					 pcie->reg_offsets[RGR1_SW_INIT_1])
> +
> +static const int pcie_offset_bcm7425[] = {
> +	[RGR1_SW_INIT_1] = 0x8010,
> +	[EXT_CFG_INDEX]  = 0x8300,
> +	[EXT_CFG_DATA]   = 0x8304,
> +};
> +
> +static const struct pcie_cfg_data bcm7425_cfg = {
> +	.offsets	= pcie_offset_bcm7425,
> +	.type		= BCM7425,
> +};
> +
> +static const int pcie_offsets[] = {
> +	[RGR1_SW_INIT_1] = 0x9210,
> +	[EXT_CFG_INDEX]  = 0x9000,
> +	[EXT_CFG_DATA]   = 0x9004,
> +};
> +
> +static const struct pcie_cfg_data bcm7435_cfg = {
> +	.offsets	= pcie_offsets,
> +	.type		= BCM7435,
> +};
> +
> +static const struct pcie_cfg_data generic_cfg = {
> +	.offsets	= pcie_offsets,
> +	.type		= GENERIC,
> +};

The way you access the config space here seems very indirect. I'd
suggest instead writing two sets of pci_ops, with hardcoded registers
offsets in them, and a function pointer to access the RGR1_SW_INIT_1
register.

> +struct brcm_msi {
> +	struct irq_domain *domain;
> +	struct irq_chip irq_chip;
> +	struct msi_controller chip;
> +	struct mutex lock;
> +	int irq;
> +	/* intr_base is the base pointer for interrupt status/set/clr regs */
> +	void __iomem *intr_base;
> +	/* intr_legacy_mask indicates how many bits are MSI interrupts */
> +	u32 intr_legacy_mask;
> +	/* intr_legacy_offset indicates bit position of MSI_01 */
> +	u32 intr_legacy_offset;
> +	/* used indicates which MSI interrupts have been alloc'd */
> +	unsigned long used;
> +	/* working indicates that on boot we have brought up MSI */
> +	bool working;
> +};

I'd move the MSI controller stuff into a separate file, and add a way to
override it. It's likely that at some point the same PCIe implementation
will be used with a modern GICv3 or GICv2m, so you should be able to
look up the msi controller from a property.

> +struct brcm_window {
> +	u64 size;
> +	u64 cpu_addr;
> +	struct resource pcie_iomem_res;
> +};

This appears to duplicate things we already have. Try to get rid of
the structure and use what is already there.

> +struct brcm_dev_pwr_supply {
> +	struct list_head node;
> +	char name[32];
> +	struct regulator *regulator;
> +};

Same here: Just get all the regulators you know about by name
and put them into the main structure.

> +/* Internal Bus Controller Information.*/
> +struct brcm_pcie {
> +	struct list_head	list;
> +	void __iomem		*base;
> +	char			name[8];
> +	bool			suspended;
> +	struct clk		*clk;
> +	struct device_node	*dn;
> +	int			pcie_irq[4];
> +	int			irq;
> +	int			num_out_wins;
> +	bool			ssc;
> +	int			gen;
> +	int			scb_size_vals[BRCM_MAX_SCB];
> +	struct brcm_window	out_wins[BRCM_NUM_PCI_OUT_WINS];
> +	struct pci_bus		*bus;
> +	struct device		*dev;
> +	struct list_head	resource;
> +	struct list_head	pwr_supplies;
> +	struct brcm_msi		msi;
> +	unsigned int		rev;
> +	unsigned int		num;
> +	bool			bridge_setup_done;
> +	const int		*reg_offsets;
> +	enum pcie_type		type;
> +};
> +
> +static int brcm_num_pci_controllers;
> +static int num_memc;

Remove the globals.

> +
> +/*
> + * MIPS endianness is configured by boot strap, which also reverses all
> + * bus endianness (i.e., big-endian CPU + big endian bus ==> native
> + * endian I/O).
> + *
> + * Other architectures (e.g., ARM) either do not support big endian, or
> + * else leave I/O in little endian mode.
> + */
> +static inline u32 bpcie_readl(void __iomem *base)
> +{
> +	if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
> +		return __raw_readl(base);
> +	else
> +		return readl_relaxed(base);
> +}

I think it would make more sense to only make this depend on the
architecture, not on endianess: If the __raw_ version works on MIPS
in big-endian mode, you should be able to also use it in little-endian
mode.

For the default (ARM) version, please use the non-relaxed accessor
by default, unless you can show a difference in performance and prove
that you don't need the implied barriers.

> +/* negative return value indicates error */
> +static int mdio_read(void __iomem *base, u8 phyad, u8 regad)
> +{
> +	u32 data = ((phyad & 0xf) << 16)
> +		| (regad & 0x1f)
> +		| 0x100000;
> +
> +	bpcie_writel(data, base + PCIE_RC_DL_MDIO_ADDR);
> +	bpcie_readl(base + PCIE_RC_DL_MDIO_ADDR);
> +
> +	data = bpcie_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
> +	if (!(data & 0x80000000)) {
> +		mdelay(1);

Try to restructure the code so this is never called with spinlocks
held and then replace the mdelay() with an msleep().

> +		data = bpcie_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
> +	}
> +	return (data & 0x80000000) ? (data & 0xffff) : -EIO;
> +}
> +
> +/* negative return value indicates error */
> +static int mdio_write(void __iomem *base, u8 phyad, u8 regad, u16 wrdata)
> +{
> +	u32 data = ((phyad & 0xf) << 16) | (regad & 0x1f);
> +
> +	bpcie_writel(data, base + PCIE_RC_DL_MDIO_ADDR);
> +	bpcie_readl(base + PCIE_RC_DL_MDIO_ADDR);
> +
> +	bpcie_writel(0x80000000 | wrdata, base + PCIE_RC_DL_MDIO_WR_DATA);
> +	data = bpcie_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
> +	if (!(data & 0x80000000)) {
> +		mdelay(1);
> +		data = bpcie_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
> +	}
> +	return (data & 0x80000000) ? 0 : -EIO;
> +}

Same here.

> +
> +	/* set up 4GB PCIE->SCB memory window on BAR2 */
> +	bpcie_writel(0x00000011, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
> +	bpcie_writel(0x00000000, base + PCIE_MISC_RC_BAR2_CONFIG_HI);

Where does this window come from? It's not in the DT as far as I can see.

> +static int brcm_setup_pcie_bridge(struct brcm_pcie *pcie)
> +{
> +	static const char *link_speed[4] = { "???", "2.5", "5.0", "8.0" };
> +	void __iomem *base = pcie->base;
> +	const int limit = pcie->suspended ? 1000 : 100;
> +	struct clk *clk;
> +	unsigned int status;
> +	int i, j, ret;
> +	bool ssc_good = false;
> +
> +	/* Give the RC/EP time to wake up, before trying to configure RC.
> +	 * Intermittently check status for link-up, up to a total of 100ms
> +	 * when we don't know if the device is there, and up to 1000ms if
> +	 * we do know the device is there.
> +	 */
> +	for (i = 1, j = 0; j < limit && !is_pcie_link_up(pcie); j += i, i = i*2)
> +		mdelay(i + j > limit ? limit - j : i);

Again, try to use msleep() instead of mdelay(). Blocking the CPU for 1 second
seems highly suspicious.

> +	INIT_LIST_HEAD(&pcie->pwr_supplies);
> +	INIT_LIST_HEAD(&pcie->resource);
> +
> +	supplies = of_property_count_strings(dn, "supply-names");
> +	if (supplies <= 0)
> +		supplies = 0;
> +
> +	for (i = 0; i < supplies; i++) {
> +		if (of_property_read_string_index(dn, "supply-names", i,
> +						  &name))
> +			continue;
> +		supply = devm_kzalloc(&pdev->dev, sizeof(*supply), GFP_KERNEL);
> +		if (!supply)
> +			return -ENOMEM;
> +
> +		strncpy(supply->name, name, sizeof(supply->name));
> +		supply->name[sizeof(supply->name) - 1] = '\0';
> +		supply->regulator = devm_regulator_get(&pdev->dev, name);
> +		if (IS_ERR(supply->regulator)) {
> +			dev_err(&pdev->dev, "Unable to get %s supply, err=%d\n",
> +				name, (int)PTR_ERR(supply->regulator));
> +			continue;
> +		}
> +
> +		if (regulator_enable(supply->regulator))
> +			dev_err(&pdev->dev, "Unable to enable %s supply.\n",
> +				name);
> +		list_add_tail(&supply->node, &pcie->pwr_supplies);
> +	}

Don't parse the regulator properties yourself here, use the proper APIs.

> +	/* 'num_memc' will be set only by the first controller, and all
> +	 * other controllers will use the value set by the first.
> +	 */
> +	if (num_memc == 0)
> +		for_each_compatible_node(mdn, NULL, "brcm,brcmstb-memc")
> +			if (of_device_is_available(mdn))
> +				num_memc++;

Why is this?

> +	resource_list_for_each_entry(win, &res) {
> +		struct brcm_window *w = &pcie->out_wins[i];
> +
> +		r = win->res;
> +
> +		if (!r->flags)
> +			continue;
> +
> +		switch (resource_type(r)) {
> +		case IORESOURCE_MEM:
> +			w->cpu_addr = r->start;
> +			w->size = resource_size(r);
> +			w->pcie_iomem_res.name  = "External PCIe MEM";
> +			w->pcie_iomem_res.flags = r->flags;
> +			w->pcie_iomem_res.start = r->start;
> +			w->pcie_iomem_res.end   = r->end;
> +			pcie->num_out_wins++;
> +			i++;
> +			/* Request memory region resources. */
> +			ret = devm_request_resource(&pdev->dev,
> +						    &iomem_resource,
> +						    &w->pcie_iomem_res);
> +			if (ret) {
> +				dev_err(&pdev->dev,
> +					"request PCIe memory resource failed\n");
> +				goto out_err_clk;
> +			}
> +			break;
> +
> +		default:
> +			continue;
> +		}
> +	}

What about IORESOURCE_IO?

	Arnd


From marc.zyngier at arm.com  Tue May  3 02:59:13 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 10:59:13 +0100
Subject: [PATCH v2 42/54] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 access to VGIC registers
In-Reply-To: <1461861973-26464-43-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-43-git-send-email-andre.przywara@arm.com>
Message-ID: <57287671.3000902@arm.com>

On 28/04/16 17:46, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
> and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
> access VGIC registers.
> 
> At that stage the interfaces with the MMIO API are not implemented:
> - vgic_attr_regs_access
> - vgic_v2_has_attr_regs
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 34 ++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h            |  1 +
>  3 files changed, 86 insertions(+), 2 deletions(-)
> 

[...]

> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index ae6077e..f2a8efe 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -276,3 +276,37 @@ int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  
>  	return ret;
>  }
> +
> +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
> +{
> +	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
> +	const struct vgic_register_region *regions;
> +	gpa_t addr;
> +	int nr_regions, i, len;
> +
> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
> +
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> +		regions = vgic_v2_dist_registers;
> +		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
> +		break;
> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> +		return -ENXIO;		/* TODO: describe CPU i/f regs also */

This definitely needs addressing, as it breaks guest migration.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From andre.przywara at arm.com  Tue May  3 03:09:12 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue, 3 May 2016 11:09:12 +0100
Subject: [PATCH v2 42/54] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 access to VGIC registers
In-Reply-To: <57287671.3000902@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-43-git-send-email-andre.przywara@arm.com>
 <57287671.3000902@arm.com>
Message-ID: <572878C8.5070306@arm.com>

Hi,

On 03/05/16 10:59, Marc Zyngier wrote:
> On 28/04/16 17:46, Andre Przywara wrote:
>> From: Eric Auger <eric.auger at linaro.org>
>>
>> This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
>> and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
>> access VGIC registers.
>>
>> At that stage the interfaces with the MMIO API are not implemented:
>> - vgic_attr_regs_access
>> - vgic_v2_has_attr_regs
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>>  virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
>>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 34 ++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic.h            |  1 +
>>  3 files changed, 86 insertions(+), 2 deletions(-)
>>
> 
> [...]
> 
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> index ae6077e..f2a8efe 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> @@ -276,3 +276,37 @@ int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>>  
>>  	return ret;
>>  }
>> +
>> +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
>> +{
>> +	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
>> +	const struct vgic_register_region *regions;
>> +	gpa_t addr;
>> +	int nr_regions, i, len;
>> +
>> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
>> +
>> +	switch (attr->group) {
>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>> +		regions = vgic_v2_dist_registers;
>> +		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
>> +		break;
>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>> +		return -ENXIO;		/* TODO: describe CPU i/f regs also */
> 
> This definitely needs addressing, as it breaks guest migration.

It is implemented in patch 46/54.
Shall I remove the TODO to avoid confusion and/or replace it with a note
either in a comment or in this commit message that the implementation
will follow in one the next patches?

Cheers,
Andre.


From tiffany.lin at mediatek.com  Tue May  3 03:11:27 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Tue, 3 May 2016 18:11:27 +0800
Subject: [PATCH v10 8/8] arm64: dts: mediatek: Add Video Encoder for MT8173
In-Reply-To: <1462270287-11374-8-git-send-email-tiffany.lin@mediatek.com>
References: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-2-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-3-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-4-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-5-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-6-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-7-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-8-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1462270287-11374-9-git-send-email-tiffany.lin@mediatek.com>

Add video encoder node for MT8173

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>

---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi |   39 ++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index ae147bb..348ce0e 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -717,6 +717,45 @@
 			clock-names = "apb", "smi";
 		};
 
+		vcodec_enc: vcodec at 18002000 {
+			compatible = "mediatek,mt8173-vcodec-enc";
+			reg = <0 0x18002000 0 0x1000>,	/* VENC_SYS */
+			      <0 0x19002000 0 0x1000>;	/* VENC_LT_SYS */
+			interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_LOW>,
+				     <GIC_SPI 202 IRQ_TYPE_LEVEL_LOW>;
+			mediatek,larb = <&larb3>,
+					<&larb5>;
+			iommus = <&iommu M4U_PORT_VENC_RCPU>,
+				 <&iommu M4U_PORT_VENC_REC>,
+				 <&iommu M4U_PORT_VENC_BSDMA>,
+				 <&iommu M4U_PORT_VENC_SV_COMV>,
+				 <&iommu M4U_PORT_VENC_RD_COMV>,
+				 <&iommu M4U_PORT_VENC_CUR_LUMA>,
+				 <&iommu M4U_PORT_VENC_CUR_CHROMA>,
+				 <&iommu M4U_PORT_VENC_REF_LUMA>,
+				 <&iommu M4U_PORT_VENC_REF_CHROMA>,
+				 <&iommu M4U_PORT_VENC_NBM_RDMA>,
+				 <&iommu M4U_PORT_VENC_NBM_WDMA>,
+				 <&iommu M4U_PORT_VENC_RCPU_SET2>,
+				 <&iommu M4U_PORT_VENC_REC_FRM_SET2>,
+				 <&iommu M4U_PORT_VENC_BSDMA_SET2>,
+				 <&iommu M4U_PORT_VENC_SV_COMA_SET2>,
+				 <&iommu M4U_PORT_VENC_RD_COMA_SET2>,
+				 <&iommu M4U_PORT_VENC_CUR_LUMA_SET2>,
+				 <&iommu M4U_PORT_VENC_CUR_CHROMA_SET2>,
+				 <&iommu M4U_PORT_VENC_REF_LUMA_SET2>,
+				 <&iommu M4U_PORT_VENC_REC_CHROMA_SET2>;
+			mediatek,vpu = <&vpu>;
+			clocks = <&topckgen CLK_TOP_VENCPLL_D2>,
+				 <&topckgen CLK_TOP_VENC_SEL>,
+				 <&topckgen CLK_TOP_UNIVPLL1_D2>,
+				 <&topckgen CLK_TOP_VENC_LT_SEL>;
+			clock-names = "venc_sel_src",
+				      "venc_sel",
+				      "venc_lt_sel_src",
+				      "venc_lt_sel";
+		};
+
 		vencltsys: clock-controller at 19000000 {
 			compatible = "mediatek,mt8173-vencltsys", "syscon";
 			reg = <0 0x19000000 0 0x1000>;
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Tue May  3 03:11:23 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Tue, 3 May 2016 18:11:23 +0800
Subject: [PATCH v10 4/8] dt-bindings: Add a binding for Mediatek Video Encoder
In-Reply-To: <1462270287-11374-4-git-send-email-tiffany.lin@mediatek.com>
References: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-2-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-3-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-4-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1462270287-11374-5-git-send-email-tiffany.lin@mediatek.com>

Add a DT binding documentation of Video Encoder for the
MT8173 SoC from Mediatek.

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
Acked-by: Rob Herring <robh at kernel.org>

---
 .../devicetree/bindings/media/mediatek-vcodec.txt  |   59 ++++++++++++++++++++
 1 file changed, 59 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/mediatek-vcodec.txt

diff --git a/Documentation/devicetree/bindings/media/mediatek-vcodec.txt b/Documentation/devicetree/bindings/media/mediatek-vcodec.txt
new file mode 100644
index 0000000..59a47a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/mediatek-vcodec.txt
@@ -0,0 +1,59 @@
+Mediatek Video Codec
+
+Mediatek Video Codec is the video codec hw present in Mediatek SoCs which
+supports high resolution encoding functionalities.
+
+Required properties:
+- compatible : "mediatek,mt8173-vcodec-enc" for encoder
+- reg : Physical base address of the video codec registers and length of
+  memory mapped region.
+- interrupts : interrupt number to the cpu.
+- mediatek,larb : must contain the local arbiters in the current Socs.
+- clocks : list of clock specifiers, corresponding to entries in
+  the clock-names property.
+- clock-names: encoder must contain "venc_sel_src", "venc_sel",
+- "venc_lt_sel_src", "venc_lt_sel".
+- iommus : should point to the respective IOMMU block with master port as
+  argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+  for details.
+- mediatek,vpu : the node of video processor unit
+
+Example:
+vcodec_enc: vcodec at 0x18002000 {
+    compatible = "mediatek,mt8173-vcodec-enc";
+    reg = <0 0x18002000 0 0x1000>,    /*VENC_SYS*/
+          <0 0x19002000 0 0x1000>;    /*VENC_LT_SYS*/
+    interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_LOW>,
+		 <GIC_SPI 202 IRQ_TYPE_LEVEL_LOW>;
+    mediatek,larb = <&larb3>,
+		    <&larb5>;
+    iommus = <&iommu M4U_PORT_VENC_RCPU>,
+             <&iommu M4U_PORT_VENC_REC>,
+             <&iommu M4U_PORT_VENC_BSDMA>,
+             <&iommu M4U_PORT_VENC_SV_COMV>,
+             <&iommu M4U_PORT_VENC_RD_COMV>,
+             <&iommu M4U_PORT_VENC_CUR_LUMA>,
+             <&iommu M4U_PORT_VENC_CUR_CHROMA>,
+             <&iommu M4U_PORT_VENC_REF_LUMA>,
+             <&iommu M4U_PORT_VENC_REF_CHROMA>,
+             <&iommu M4U_PORT_VENC_NBM_RDMA>,
+             <&iommu M4U_PORT_VENC_NBM_WDMA>,
+             <&iommu M4U_PORT_VENC_RCPU_SET2>,
+             <&iommu M4U_PORT_VENC_REC_FRM_SET2>,
+             <&iommu M4U_PORT_VENC_BSDMA_SET2>,
+             <&iommu M4U_PORT_VENC_SV_COMA_SET2>,
+             <&iommu M4U_PORT_VENC_RD_COMA_SET2>,
+             <&iommu M4U_PORT_VENC_CUR_LUMA_SET2>,
+             <&iommu M4U_PORT_VENC_CUR_CHROMA_SET2>,
+             <&iommu M4U_PORT_VENC_REF_LUMA_SET2>,
+             <&iommu M4U_PORT_VENC_REC_CHROMA_SET2>;
+    mediatek,vpu = <&vpu>;
+    clocks = <&topckgen CLK_TOP_VENCPLL_D2>,
+             <&topckgen CLK_TOP_VENC_SEL>,
+             <&topckgen CLK_TOP_UNIVPLL1_D2>,
+             <&topckgen CLK_TOP_VENC_LT_SEL>;
+    clock-names = "venc_sel_src",
+                  "venc_sel",
+                  "venc_lt_sel_src",
+                  "venc_lt_sel";
+  };
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Tue May  3 03:11:19 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Tue, 3 May 2016 18:11:19 +0800
Subject: [PATCH v10 0/8] Add MT8173 Video Encoder Driver and VPU Driver
Message-ID: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>

==============
 Introduction
==============

The purpose of this series is to add the driver for video codec hw embedded in the Mediatek's MT8173 SoCs.
Mediatek Video Codec is able to handle video encoding of in a range of formats.

This patch series also include VPU driver. Mediatek Video Codec driver rely on VPU driver to load,
communicate with VPU.

Internally the driver uses videobuf2 framework and MTK IOMMU and MTK SMI both have been merged in v4.6-rc1.
This patch series need [PATCH v15 8/8] memory: mtk-smi: export mtk_smi_larb_get/put[1] to build as module

[1]http://lists.infradead.org/pipermail/linux-mediatek/2016-April/005173.html

==================
 Device interface
==================

In principle the driver bases on v4l2 memory-to-memory framework:
it provides a single video node and each opened file handle gets its own private context with separate
buffer queues. Each context consist of 2 buffer queues: OUTPUT (for source buffers, i.e. raw video
frames) and CAPTURE (for destination buffers, i.e. encoded video frames).

==============================
 VPU (Video Processor Unit)
==============================
The VPU driver for hw video codec embedded in Mediatek's MT8173 SOCs.
It is able to handle video decoding/encoding in a range of formats.
The driver provides with VPU firmware download, memory management and the communication interface between CPU and VPU.
For VPU initialization, it will create virtual memory for CPU access and physical address for VPU hw device access. 
When a decode/encode instance opens a device node, vpu driver will download vpu firmware to the device.
A decode/encode instant will decode/encode a frame using VPU interface to interrupt vpu to handle decoding/encoding jobs.

Please have a look at the code and comments will be very much appreciated.

Change in v10:
1. Fix smatch/sparse error message
2. Add depends on ARM || ARM64 and MTK_IOMMU in Kconfig

VPU part
1. Fix smatch/sparse error message
2. Use totalram_pages instead of max_pfn to decide VPU 4GB mode
3. Protect variable "fw_load"
4. Add depends on ARM || ARM64 in Kconfig

Change in v9:
1. Rename idx in mtk_vcodec_ctx to id and curr_max_idx in mtk_vcodec_dev to id_counter.
2. Refine fops_vcodec_open

VPU part
Merge Julia Lawall's fixes to "[PATCH v9 2/8] [media] VPU: mediatek: support Mediatek VPU"
1.[PATCH] VPU: mediatek: fix simple_open.cocci warnings 
2.[PATCH] VPU: mediatek: fix platform_no_drv_owner.cocci warnings

Change in v8:
1. Refine indentation
2. Refine colorspace information process vidioc_try_fmt_vid_out_mplane
3. Remove instance_mask in mtk_vcodec_dev, use curr_max_idx for instance index
4. Use kzalloc to allocate ctx
5. Refine fops_vcodec_open

VPU Part
1. Refine vpu_load_firmware

Change in v7:
1. Rebase against the master branch of git://linuxtv.org/media_tree.git
2. Add ycbcr_enc, quantization and xfer_func in try_fmt, g_fmt, s_fmt
3. Merge h264_enc and vp8_enc to venc directory

Change in v6:
1. Add synchronization access protect between irq handler and work thread
2. Add DMA_ATTR_ALLOC_SINGLE_PAGES support
3. S_FMT will return coded_width, coded_height, so user space could allocate correct size memory that HW required
4. merge h264/vp8 enc ap and md32 ipi msg
5. separate h264/vp8 enc gop_size and intra_period handle
6. remove sizeimage relative code in work buffer function
7. Refine makefile to build as an module
8. Code clean up

VPU Part
1. export symbols for building VPU as an module
2. change function from "wait_event_interruptible_timeout" to "wait_event_timeout" since
   CPU needs to wait for ACK from VPU even if it was interrupted by a signal

v4l2-compliance test output:
localhost Encode # ./v4l2-compliance -d /dev/video1
Driver Info:
        Driver name   : mtk-vcodec-enc
        Card type     : platform:mt8173
        Bus info      : platform:mt8173
        Driver version: 4.4.0
        Capabilities  : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps   : 0x04204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format

Compliance test for device /dev/video1 (not using libv4l2):

Required ioctls:
        test VIDIOC_QUERYCAP: OK

Allow for multiple opens:
        test second video open: OK
        test VIDIOC_QUERYCAP: OK
        test VIDIOC_G/S_PRIORITY: OK

Debug ioctls:
        test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
        test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
        test VIDIOC_ENUMAUDIO: OK (Not Supported)
        test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDIO: OK (Not Supported)
        Inputs: 0 Audio Inputs: 0 Tuners: 0

Output ioctls:
        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
        Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
        test VIDIOC_G/S_EDID: OK (Not Supported)

        Control ioctls:
                test VIDIOC_QUERYCTRL/MENU: OK
                test VIDIOC_G/S_CTRL: OK
                test VIDIOC_G/S/TRY_EXT_CTRLS: OK
                test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
                test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
                Standard Controls: 12 Private Controls: 0

        Format ioctls:
                test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
                test VIDIOC_G/S_PARM: OK
                test VIDIOC_G_FBUF: OK (Not Supported)
                test VIDIOC_G_FMT: OK
                test VIDIOC_TRY_FMT: OK
                test VIDIOC_S_FMT: OK
                test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)

        Codec ioctls:
                test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
                test VIDIOC_G_ENC_INDEX: OK (Not Supported)
                test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

        Buffer ioctls:
                test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
                test VIDIOC_EXPBUF: OK
Total: 38, Succeeded: 38, Failed: 0, Warnings: 0


v4l2-compliance test output:
localhost ~ # /usr/bin/v4l2-compliance -d /dev/video1
 
Change in v5:
Vcodec Part
1. Pass checkpatch and v4l2-compliance test
2. Remove unused g/s_selection for now
3. add vidioc_g_parm support
4. add vidioc_create_bufs and vidioc_prepare_buf support
5. Remove instance check in fops_vcodec_open
6. Fix comments for data structure and code
7. Refine venc, venc_lt clock source name in devicetree and binding document
8. Fix Author information and copyright information
9. Refine code according to review comments

VPU Part

v4l2-compliance test output:
localhost ~ # /usr/bin/v4l2-compliance -d /dev/video1
Driver Info:
        Driver name   : mtk-vcodec-enc
        Card type     : platform:mt8173
        Bus info      : platform:mt8173
        Driver version: 4.4.0
        Capabilities  : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps   : 0x04204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format

Compliance test for device /dev/video1 (not using libv4l2):

Required ioctls:
        test VIDIOC_QUERYCAP: OK

Allow for multiple opens:
        test second video open: OK
        test VIDIOC_QUERYCAP: OK
        test VIDIOC_G/S_PRIORITY: OK

Debug ioctls:
        test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
        test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
        test VIDIOC_ENUMAUDIO: OK (Not Supported)
        test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDIO: OK (Not Supported)
        Inputs: 0 Audio Inputs: 0 Tuners: 0

Output ioctls:
        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
        Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
        test VIDIOC_G/S_EDID: OK (Not Supported)

        Control ioctls:
                test VIDIOC_QUERYCTRL/MENU: OK
                test VIDIOC_G/S_CTRL: OK
                test VIDIOC_G/S/TRY_EXT_CTRLS: OK
                test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
                test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
                Standard Controls: 12 Private Controls: 0

        Format ioctls:
                test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
                test VIDIOC_G/S_PARM: OK
                test VIDIOC_G_FBUF: OK (Not Supported)
                test VIDIOC_G_FMT: OK
                test VIDIOC_TRY_FMT: OK
                test VIDIOC_S_FMT: OK
                test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)

        Codec ioctls:
                test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
                test VIDIOC_G_ENC_INDEX: OK (Not Supported)
                test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

        Buffer ioctls:
                test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
                test VIDIOC_EXPBUF: OK


Total: 38, Succeeded: 38, Failed: 0, Warnings: 0


Change in v4:
Vcodec Part
1. Remove MTK_ENCODE_PARAM_SKIP_FRAME support
2. Remove MTK_ENCODE_PARAM_FRAME_TYPE and change to use V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME[3]
3. Refine Encoder HW clock source
4. Refine debug log
5. Add watchdog support
6. With patch "media: v4l2-compat-ioctl32: fix missing length copy in put_v4l2_buffer32"[4],
v4l2-compliance test passed[5] in v4.4-rc5 

VPU Part
1. These two patches were Acked-by: Rob Herring <robh <at> kernel.org> in v3
   [PATCH v3 1/8] dt-bindings: Add a binding for Mediatek Video Processor
   [PATCH v3 3/8] arm64: dts: mediatek: Add node for Mediatek Video Processor Unit
   Because we were wrong about how the hardware works, there is no connection between VPU and IOMMU HW
   We remove VPU attaching to IOMMU
2. Support VPU running on 4GB DRAM system
3. Support VPU watchdog reset
4. Refine for coding style 

[3]https://patchwork.linuxtv.org/patch/32670/
[4] https://patchwork.linuxtv.org/patch/32631/
[5]localhost ~ # /usr/bin/v4l2-compliance -d /dev/video1
Driver Info:
        Driver name   : mtk-vcodec-en
        Card type     : platform:mt817
        Bus info      : platform:mt817
        Driver version: 4.4.0
        Capabilities  : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps   : 0x04204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format

Compliance test for device /dev/video1 (not using libv4l2):

Required ioctls:
        test VIDIOC_QUERYCAP: OK

Allow for multiple opens:
        test second video open: OK
        test VIDIOC_QUERYCAP: OK
        test VIDIOC_G/S_PRIORITY: OK

Debug ioctls:
        test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
        test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
        test VIDIOC_ENUMAUDIO: OK (Not Supported)
        test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDIO: OK (Not Supported)
        Inputs: 0 Audio Inputs: 0 Tuners: 0

Output ioctls:
        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
        Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
        test VIDIOC_G/S_EDID: OK (Not Supported)

        Control ioctls:
                test VIDIOC_QUERYCTRL/MENU: OK
                test VIDIOC_G/S_CTRL: OK
                test VIDIOC_G/S/TRY_EXT_CTRLS: OK
                test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
                test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
                Standard Controls: 12 Private Controls: 0

        Format ioctls:
                test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
                test VIDIOC_G/S_PARM: OK (Not Supported)
                test VIDIOC_G_FBUF: OK (Not Supported)
                test VIDIOC_G_FMT: OK
                test VIDIOC_TRY_FMT: OK
                test VIDIOC_S_FMT: OK
                test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)

        Codec ioctls:
                test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
                test VIDIOC_G_ENC_INDEX: OK (Not Supported)
                test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

        Buffer ioctls:
                warn: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(475):
VIDIOC_CREATE_BUFS not supported
                warn: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(475):
VIDIOC_CREATE_BUFS not supported
                test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
                test VIDIOC_EXPBUF: OK

Total: 38, Succeeded: 38, Failed: 0, Warnings: 2

Change in v3:
1.Refine code to pass v4l2-compliance test, now it still has 2 issues 2.Refine code according to latest MTK
IOMMU patches[1] 3.Remove MFC51 specific CIDs and add MTK specific CIDs for for keyframe and
  skip I-frame
4.Refine code according to review comments

Below is the v1.6 version v4l2-compliance report for the mt8173 encoder driver.
Now there are still 2 test fail in v1.6.
For VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF, we directly use v4l2_m2m_ioctl_* functions, but it still
fail. It pass in kernel 3.18 but fail in kernel 4.4.
We will try v1.8 in next version.
VIDIOC_EXPBUF is becuase we support all three memory types VB2_DMABUF, VB2_MMAP and VB2_USERPTR.
VIDIOC_EXPBUF only allowed when only VB2_MMAP supported.
localhost ~ # /usr/bin/v4l2-compliance -d /dev/video1 Driver Info:
        Driver name   : mtk-vcodec-en
        Card type     : platform:mt817
        Bus info      : platform:mt817
        Driver version: 4.4.0
        Capabilities  : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps   : 0x04204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format

Compliance test for device /dev/video1 (not using libv4l2):

Required ioctls:
        test VIDIOC_QUERYCAP: OK

Allow for multiple opens:
        test second video open: OK
        test VIDIOC_QUERYCAP: OK
        test VIDIOC_G/S_PRIORITY: OK

Debug ioctls:
        test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
        test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
        test VIDIOC_ENUMAUDIO: OK (Not Supported)
        test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDIO: OK (Not Supported)
        Inputs: 0 Audio Inputs: 0 Tuners: 0

Output ioctls:
        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
        Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
        test VIDIOC_G/S_EDID: OK (Not Supported)

        Control ioctls:
                test VIDIOC_QUERYCTRL/MENU: OK
                test VIDIOC_G/S_CTRL: OK
                test VIDIOC_G/S/TRY_EXT_CTRLS: OK
                test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
                test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
                Standard Controls: 11 Private Controls: 2

        Format ioctls:
                test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
                test VIDIOC_G/S_PARM: OK (Not Supported)
                test VIDIOC_G_FBUF: OK (Not Supported)
                test VIDIOC_G_FMT: OK
                test VIDIOC_TRY_FMT: OK
                test VIDIOC_S_FMT: OK
                test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)

        Codec ioctls:
                test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
                test VIDIOC_G_ENC_INDEX: OK (Not Supported)
                test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

        Buffer ioctls:
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(266): vp->length
== 0
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(335):
buf.check(Unqueued, i)
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(420):
testQueryBuf(node, i, q.g_buffers())
                test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: FAIL
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(500): q.has_expbuf(node)
                test VIDIOC_EXPBUF: FAIL
Total: 38, Succeeded: 36, Failed: 2, Warnings: 0

Change in v2:
Vcodec Part
1.Remove common and include directory in mtk-vcodec 2.Refine vb2ops_venc_start_streaming and
vb2ops_venc_stop_streaming and state machine 3.Remove venc_if_init and venc_if_deinit 4.Refine
debug message 5.Refine lab and vpu decription in mediatek-vcodec.txt

VPU Part
1. Modify VPU Kconfig
2. Move encoder header files to other patch sets 3. Remove marcos for extended virtual/iova address 4.
Change register and variable names 5. Add a reference counter for VPU watchdog 6. Remove one busy waiting
in function vpu_ipi_send 7. Operate VPU clock in VPU driver (not called by encoder drivers) 8. Refine
memory mapping, firmware download and extended memory allocation/free functions 9. Release more
allocated resources in driver remove function

Andrew-CT Chen (3):
  dt-bindings: Add a binding for Mediatek Video Processor
  VPU: mediatek: support Mediatek VPU
  arm64: dts: mediatek: Add node for Mediatek Video Processor Unit

Tiffany Lin (5):
  dt-bindings: Add a binding for Mediatek Video Encoder
  vcodec: mediatek: Add Mediatek V4L2 Video Encoder Driver
  vcodec: mediatek: Add Mediatek VP8 Video Encoder Driver
  vcodec: mediatek: Add Mediatek H264 Video Encoder Driver
  arm64: dts: mediatek: Add Video Encoder for MT8173

 .../devicetree/bindings/media/mediatek-vcodec.txt  |   59 +
 .../devicetree/bindings/media/mediatek-vpu.txt     |   31 +
 arch/arm64/boot/dts/mediatek/mt8173.dtsi           |   62 +
 drivers/media/platform/Kconfig                     |   32 +
 drivers/media/platform/Makefile                    |    4 +
 drivers/media/platform/mtk-vcodec/Makefile         |   19 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h |  338 +++++
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 1288 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h |   58 +
 .../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c |  454 +++++++
 .../media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c  |  137 +++
 .../media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h  |   26 +
 .../media/platform/mtk-vcodec/mtk_vcodec_intr.c    |   55 +
 .../media/platform/mtk-vcodec/mtk_vcodec_intr.h    |   27 +
 .../media/platform/mtk-vcodec/mtk_vcodec_util.c    |   94 ++
 .../media/platform/mtk-vcodec/mtk_vcodec_util.h    |   87 ++
 .../media/platform/mtk-vcodec/venc/venc_h264_if.c  |  679 +++++++++++
 .../media/platform/mtk-vcodec/venc/venc_vp8_if.c   |  481 ++++++++
 drivers/media/platform/mtk-vcodec/venc_drv_base.h  |   62 +
 drivers/media/platform/mtk-vcodec/venc_drv_if.c    |  113 ++
 drivers/media/platform/mtk-vcodec/venc_drv_if.h    |  163 +++
 drivers/media/platform/mtk-vcodec/venc_ipi_msg.h   |  210 ++++
 drivers/media/platform/mtk-vcodec/venc_vpu_if.c    |  237 ++++
 drivers/media/platform/mtk-vcodec/venc_vpu_if.h    |   61 +
 drivers/media/platform/mtk-vpu/Makefile            |    3 +
 drivers/media/platform/mtk-vpu/mtk_vpu.c           |  950 +++++++++++++++
 drivers/media/platform/mtk-vpu/mtk_vpu.h           |  162 +++
 27 files changed, 5892 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/mediatek-vcodec.txt
 create mode 100644 Documentation/devicetree/bindings/media/mediatek-vpu.txt
 create mode 100644 drivers/media/platform/mtk-vcodec/Makefile
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
 create mode 100644 drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/venc_drv_base.h
 create mode 100644 drivers/media/platform/mtk-vcodec/venc_drv_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/venc_drv_if.h
 create mode 100644 drivers/media/platform/mtk-vcodec/venc_ipi_msg.h
 create mode 100644 drivers/media/platform/mtk-vcodec/venc_vpu_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/venc_vpu_if.h
 create mode 100644 drivers/media/platform/mtk-vpu/Makefile
 create mode 100644 drivers/media/platform/mtk-vpu/mtk_vpu.c
 create mode 100644 drivers/media/platform/mtk-vpu/mtk_vpu.h

-- 
1.7.9.5



From tiffany.lin at mediatek.com  Tue May  3 03:11:21 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Tue, 3 May 2016 18:11:21 +0800
Subject: [PATCH v10 2/8] [media] VPU: mediatek: support Mediatek VPU
In-Reply-To: <1462270287-11374-2-git-send-email-tiffany.lin@mediatek.com>
References: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-2-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1462270287-11374-3-git-send-email-tiffany.lin@mediatek.com>

From: Andrew-CT Chen <andrew-ct.chen at mediatek.com>

The VPU driver for hw video codec embedded in Mediatek's MT8173 SOCs.
It is able to handle video decoding/encoding of in a range of formats.
The driver provides with VPU firmware download, memory management and
the communication interface between CPU and VPU.
For VPU initialization, it will create virtual memory for CPU access and
IOMMU address for vcodec hw device access. When a decode/encode instance
opens a device node, vpu driver will download vpu firmware to the device.
A decode/encode instant will decode/encode a frame using VPU
interface to interrupt vpu to handle decoding/encoding jobs.

Signed-off-by: Andrew-CT Chen <andrew-ct.chen at mediatek.com>
Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>

---
 drivers/media/platform/Kconfig           |   14 +
 drivers/media/platform/Makefile          |    2 +
 drivers/media/platform/mtk-vpu/Makefile  |    3 +
 drivers/media/platform/mtk-vpu/mtk_vpu.c |  950 ++++++++++++++++++++++++++++++
 drivers/media/platform/mtk-vpu/mtk_vpu.h |  162 +++++
 5 files changed, 1131 insertions(+)
 create mode 100644 drivers/media/platform/mtk-vpu/Makefile
 create mode 100644 drivers/media/platform/mtk-vpu/mtk_vpu.c
 create mode 100644 drivers/media/platform/mtk-vpu/mtk_vpu.h

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 84e041c..d87ae31 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -152,6 +152,20 @@ config VIDEO_CODA
 	   Coda is a range of video codec IPs that supports
 	   H.264, MPEG-4, and other video formats.
 
+config VIDEO_MEDIATEK_VPU
+	tristate "Mediatek Video Processor Unit"
+	depends on ARM || ARM64
+	depends on VIDEO_DEV && VIDEO_V4L2
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	---help---
+	    This driver provides downloading VPU firmware and
+	    communicating with VPU. This driver for hw video
+	    codec embedded in Mediatek's MT8173 SOCs. It is able
+	    to handle video decoding/encoding in a range of formats.
+
+	    To compile this driver as a module, choose M here: the
+	    module will be called mtk-vpu.
+
 config VIDEO_MEM2MEM_DEINTERLACE
 	tristate "Deinterlace support"
 	depends on VIDEO_DEV && VIDEO_V4L2 && DMA_ENGINE
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index bbb7bd1..2efb7b1 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -56,3 +56,5 @@ obj-$(CONFIG_VIDEO_AM437X_VPFE)		+= am437x/
 obj-$(CONFIG_VIDEO_XILINX)		+= xilinx/
 
 ccflags-y += -I$(srctree)/drivers/media/i2c
+
+obj-$(CONFIG_VIDEO_MEDIATEK_VPU)	+= mtk-vpu/
diff --git a/drivers/media/platform/mtk-vpu/Makefile b/drivers/media/platform/mtk-vpu/Makefile
new file mode 100644
index 0000000..58cc1b4
--- /dev/null
+++ b/drivers/media/platform/mtk-vpu/Makefile
@@ -0,0 +1,3 @@
+mtk-vpu-y += mtk_vpu.o
+
+obj-$(CONFIG_VIDEO_MEDIATEK_VPU) += mtk-vpu.o
diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c
new file mode 100644
index 0000000..b60d02c
--- /dev/null
+++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c
@@ -0,0 +1,950 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: Andrew-CT Chen <andrew-ct.chen at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/iommu.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/sched.h>
+#include <linux/sizes.h>
+
+#include "mtk_vpu.h"
+
+/**
+ * VPU (video processor unit) is a tiny processor controlling video hardware
+ * related to video codec, scaling and color format converting.
+ * VPU interfaces with other blocks by share memory and interrupt.
+ **/
+
+#define INIT_TIMEOUT_MS		2000U
+#define IPI_TIMEOUT_MS		2000U
+#define VPU_FW_VER_LEN		16
+
+/* maximum program/data TCM (Tightly-Coupled Memory) size */
+#define VPU_PTCM_SIZE		(96 * SZ_1K)
+#define VPU_DTCM_SIZE		(32 * SZ_1K)
+/* the offset to get data tcm address */
+#define VPU_DTCM_OFFSET		0x18000UL
+/* daynamic allocated maximum extended memory size */
+#define VPU_EXT_P_SIZE		SZ_1M
+#define VPU_EXT_D_SIZE		SZ_4M
+/* maximum binary firmware size */
+#define VPU_P_FW_SIZE		(VPU_PTCM_SIZE + VPU_EXT_P_SIZE)
+#define VPU_D_FW_SIZE		(VPU_DTCM_SIZE + VPU_EXT_D_SIZE)
+/* the size of share buffer between Host and  VPU */
+#define SHARE_BUF_SIZE		48
+
+/* binary firmware name */
+#define VPU_P_FW		"vpu_p.bin"
+#define VPU_D_FW		"vpu_d.bin"
+
+#define VPU_RESET		0x0
+#define VPU_TCM_CFG		0x0008
+#define VPU_PMEM_EXT0_ADDR	0x000C
+#define VPU_PMEM_EXT1_ADDR	0x0010
+#define VPU_TO_HOST		0x001C
+#define VPU_DMEM_EXT0_ADDR	0x0014
+#define VPU_DMEM_EXT1_ADDR	0x0018
+#define HOST_TO_VPU		0x0024
+#define VPU_PC_REG		0x0060
+#define VPU_WDT_REG		0x0084
+
+/* vpu inter-processor communication interrupt */
+#define VPU_IPC_INT		BIT(8)
+
+/**
+ * enum vpu_fw_type - VPU firmware type
+ *
+ * @P_FW: program firmware
+ * @D_FW: data firmware
+ *
+ */
+enum vpu_fw_type {
+	P_FW,
+	D_FW,
+};
+
+/**
+ * struct vpu_mem - VPU extended program/data memory information
+ *
+ * @va:		the kernel virtual memory address of VPU extended memory
+ * @pa:		the physical memory address of VPU extended memory
+ *
+ */
+struct vpu_mem {
+	void *va;
+	dma_addr_t pa;
+};
+
+/**
+ * struct vpu_regs - VPU TCM and configuration registers
+ *
+ * @tcm:	the register for VPU Tightly-Coupled Memory
+ * @cfg:	the register for VPU configuration
+ * @irq:	the irq number for VPU interrupt
+ */
+struct vpu_regs {
+	void __iomem *tcm;
+	void __iomem *cfg;
+	int irq;
+};
+
+/**
+ * struct vpu_wdt_handler - VPU watchdog reset handler
+ *
+ * @reset_func:	reset handler
+ * @priv:	private data
+ */
+struct vpu_wdt_handler {
+	void (*reset_func)(void *);
+	void *priv;
+};
+
+/**
+ * struct vpu_wdt - VPU watchdog workqueue
+ *
+ * @handler:	VPU watchdog reset handler
+ * @ws:		workstruct for VPU watchdog
+ * @wq:		workqueue for VPU watchdog
+ */
+struct vpu_wdt {
+	struct vpu_wdt_handler handler[VPU_RST_MAX];
+	struct work_struct ws;
+	struct workqueue_struct *wq;
+};
+
+/**
+ * struct vpu_run - VPU initialization status
+ *
+ * @signaled:		the signal of vpu initialization completed
+ * @fw_ver:		VPU firmware version
+ * @enc_capability:	encoder capability which is not used for now and
+ *			the value is reserved for future use
+ * @wq:			wait queue for VPU initialization status
+ */
+struct vpu_run {
+	u32 signaled;
+	char fw_ver[VPU_FW_VER_LEN];
+	unsigned int	enc_capability;
+	wait_queue_head_t wq;
+};
+
+/**
+ * struct vpu_ipi_desc - VPU IPI descriptor
+ *
+ * @handler:	IPI handler
+ * @name:	the name of IPI handler
+ * @priv:	the private data of IPI handler
+ */
+struct vpu_ipi_desc {
+	ipi_handler_t handler;
+	const char *name;
+	void *priv;
+};
+
+/**
+ * struct share_obj - DTCM (Data Tightly-Coupled Memory) buffer shared with
+ *		      AP and VPU
+ *
+ * @id:		IPI id
+ * @len:	share buffer length
+ * @share_buf:	share buffer data
+ */
+struct share_obj {
+	s32 id;
+	u32 len;
+	unsigned char share_buf[SHARE_BUF_SIZE];
+};
+
+/**
+ * struct mtk_vpu - vpu driver data
+ * @extmem:		VPU extended memory information
+ * @reg:		VPU TCM and configuration registers
+ * @run:		VPU initialization status
+ * @ipi_desc:		VPU IPI descriptor
+ * @recv_buf:		VPU DTCM share buffer for receiving. The
+ *			receive buffer is only accessed in interrupt context.
+ * @send_buf:		VPU DTCM share buffer for sending
+ * @dev:		VPU struct device
+ * @clk:		VPU clock on/off
+ * @fw_loaded:		indicate VPU firmware loaded
+ * @enable_4GB:		VPU 4GB mode on/off
+ * @vpu_mutex:		protect mtk_vpu (except recv_buf) and ensure only
+ *			one client to use VPU service at a time. For example,
+ *			suppose a client is using VPU to decode VP8.
+ *			If the other client wants to encode VP8,
+ *			it has to wait until VP8 decode completes.
+ * @wdt_refcnt		WDT reference count to make sure the watchdog can be
+ *			disabled if no other client is using VPU service
+ * @ack_wq:		The wait queue for each codec and mdp. When sleeping
+ *			processes wake up, they will check the condition
+ *			"ipi_id_ack" to run the corresponding action or
+ *			go back to sleep.
+ * @ipi_id_ack:		The ACKs for registered IPI function sending
+ *			interrupt to VPU
+ *
+ */
+struct mtk_vpu {
+	struct vpu_mem extmem[2];
+	struct vpu_regs reg;
+	struct vpu_run run;
+	struct vpu_wdt wdt;
+	struct vpu_ipi_desc ipi_desc[IPI_MAX];
+	struct share_obj *recv_buf;
+	struct share_obj *send_buf;
+	struct device *dev;
+	struct clk *clk;
+	bool fw_loaded;
+	bool enable_4GB;
+	struct mutex vpu_mutex; /* for protecting vpu data data structure */
+	u32 wdt_refcnt;
+	wait_queue_head_t ack_wq;
+	bool ipi_id_ack[IPI_MAX];
+};
+
+static inline void vpu_cfg_writel(struct mtk_vpu *vpu, u32 val, u32 offset)
+{
+	writel(val, vpu->reg.cfg + offset);
+}
+
+static inline u32 vpu_cfg_readl(struct mtk_vpu *vpu, u32 offset)
+{
+	return readl(vpu->reg.cfg + offset);
+}
+
+static inline bool vpu_running(struct mtk_vpu *vpu)
+{
+	return vpu_cfg_readl(vpu, VPU_RESET) & BIT(0);
+}
+
+static void vpu_clock_disable(struct mtk_vpu *vpu)
+{
+	/* Disable VPU watchdog */
+	mutex_lock(&vpu->vpu_mutex);
+	if (!--vpu->wdt_refcnt)
+		vpu_cfg_writel(vpu,
+			       vpu_cfg_readl(vpu, VPU_WDT_REG) & ~(1L << 31),
+			       VPU_WDT_REG);
+	mutex_unlock(&vpu->vpu_mutex);
+
+	clk_disable(vpu->clk);
+}
+
+static int vpu_clock_enable(struct mtk_vpu *vpu)
+{
+	int ret;
+
+	ret = clk_enable(vpu->clk);
+	if (ret)
+		return ret;
+	/* Enable VPU watchdog */
+	mutex_lock(&vpu->vpu_mutex);
+	if (!vpu->wdt_refcnt++)
+		vpu_cfg_writel(vpu,
+			       vpu_cfg_readl(vpu, VPU_WDT_REG) | (1L << 31),
+			       VPU_WDT_REG);
+	mutex_unlock(&vpu->vpu_mutex);
+
+	return ret;
+}
+
+int vpu_ipi_register(struct platform_device *pdev,
+		     enum ipi_id id, ipi_handler_t handler,
+		     const char *name, void *priv)
+{
+	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
+	struct vpu_ipi_desc *ipi_desc;
+
+	if (!vpu) {
+		dev_err(&pdev->dev, "vpu device in not ready\n");
+		return -EPROBE_DEFER;
+	}
+
+	if (id >= 0 && id < IPI_MAX && handler) {
+		ipi_desc = vpu->ipi_desc;
+		ipi_desc[id].name = name;
+		ipi_desc[id].handler = handler;
+		ipi_desc[id].priv = priv;
+		return 0;
+	}
+
+	dev_err(&pdev->dev, "register vpu ipi id %d with invalid arguments\n",
+		id);
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(vpu_ipi_register);
+
+int vpu_ipi_send(struct platform_device *pdev,
+		 enum ipi_id id, void *buf,
+		 unsigned int len)
+{
+	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
+	struct share_obj *send_obj = vpu->send_buf;
+	unsigned long timeout;
+	int ret = 0;
+
+	if (id <= IPI_VPU_INIT || id >= IPI_MAX ||
+	    len > sizeof(send_obj->share_buf) || !buf) {
+		dev_err(vpu->dev, "failed to send ipi message\n");
+		return -EINVAL;
+	}
+
+	ret = vpu_clock_enable(vpu);
+	if (ret) {
+		dev_err(vpu->dev, "failed to enable vpu clock\n");
+		return ret;
+	}
+	if (!vpu_running(vpu)) {
+		dev_err(vpu->dev, "vpu_ipi_send: VPU is not running\n");
+		ret = -EINVAL;
+		goto clock_disable;
+	}
+
+	mutex_lock(&vpu->vpu_mutex);
+
+	 /* Wait until VPU receives the last command */
+	timeout = jiffies + msecs_to_jiffies(IPI_TIMEOUT_MS);
+	do {
+		if (time_after(jiffies, timeout)) {
+			dev_err(vpu->dev, "vpu_ipi_send: IPI timeout!\n");
+			ret = -EIO;
+			goto mut_unlock;
+		}
+	} while (vpu_cfg_readl(vpu, HOST_TO_VPU));
+
+	memcpy((void *)send_obj->share_buf, buf, len);
+	send_obj->len = len;
+	send_obj->id = id;
+
+	vpu->ipi_id_ack[id] = false;
+	/* send the command to VPU */
+	vpu_cfg_writel(vpu, 0x1, HOST_TO_VPU);
+
+	mutex_unlock(&vpu->vpu_mutex);
+
+	/* wait for VPU's ACK */
+	timeout = msecs_to_jiffies(IPI_TIMEOUT_MS);
+	ret = wait_event_timeout(vpu->ack_wq, vpu->ipi_id_ack[id], timeout);
+	vpu->ipi_id_ack[id] = false;
+	if (ret == 0) {
+		dev_err(vpu->dev, "vpu ipi %d ack time out !", id);
+		ret = -EIO;
+		goto clock_disable;
+	}
+	vpu_clock_disable(vpu);
+
+	return 0;
+
+mut_unlock:
+	mutex_unlock(&vpu->vpu_mutex);
+clock_disable:
+	vpu_clock_disable(vpu);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vpu_ipi_send);
+
+static void vpu_wdt_reset_func(struct work_struct *ws)
+{
+	struct vpu_wdt *wdt = container_of(ws, struct vpu_wdt, ws);
+	struct mtk_vpu *vpu = container_of(wdt, struct mtk_vpu, wdt);
+	struct vpu_wdt_handler *handler = wdt->handler;
+	int index, ret;
+
+	dev_info(vpu->dev, "vpu reset\n");
+	ret = vpu_clock_enable(vpu);
+	if (ret) {
+		dev_err(vpu->dev, "[VPU] wdt enables clock failed %d\n", ret);
+		return;
+	}
+	mutex_lock(&vpu->vpu_mutex);
+	vpu_cfg_writel(vpu, 0x0, VPU_RESET);
+	vpu->fw_loaded = false;
+	mutex_unlock(&vpu->vpu_mutex);
+	vpu_clock_disable(vpu);
+
+	for (index = 0; index < VPU_RST_MAX; index++) {
+		if (handler[index].reset_func) {
+			handler[index].reset_func(handler[index].priv);
+			dev_dbg(vpu->dev, "wdt handler func %d\n", index);
+		}
+	}
+}
+
+int vpu_wdt_reg_handler(struct platform_device *pdev,
+			void wdt_reset(void *),
+			void *priv, enum rst_id id)
+{
+	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
+	struct vpu_wdt_handler *handler;
+
+	if (!vpu) {
+		dev_err(&pdev->dev, "vpu device in not ready\n");
+		return -EPROBE_DEFER;
+	}
+
+	handler = vpu->wdt.handler;
+
+	if (id >= 0 && id < VPU_RST_MAX && wdt_reset) {
+		dev_dbg(vpu->dev, "wdt register id %d\n", id);
+		mutex_lock(&vpu->vpu_mutex);
+		handler[id].reset_func = wdt_reset;
+		handler[id].priv = priv;
+		mutex_unlock(&vpu->vpu_mutex);
+		return 0;
+	}
+
+	dev_err(vpu->dev, "register vpu wdt handler failed\n");
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(vpu_wdt_reg_handler);
+
+unsigned int vpu_get_venc_hw_capa(struct platform_device *pdev)
+{
+	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
+
+	return vpu->run.enc_capability;
+}
+EXPORT_SYMBOL_GPL(vpu_get_venc_hw_capa);
+
+void *vpu_mapping_dm_addr(struct platform_device *pdev,
+			  u32 dtcm_dmem_addr)
+{
+	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
+
+	if (!dtcm_dmem_addr ||
+	    (dtcm_dmem_addr > (VPU_DTCM_SIZE + VPU_EXT_D_SIZE))) {
+		dev_err(vpu->dev, "invalid virtual data memory address\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (dtcm_dmem_addr < VPU_DTCM_SIZE)
+		return (__force void *)(dtcm_dmem_addr + vpu->reg.tcm +
+					VPU_DTCM_OFFSET);
+
+	return vpu->extmem[D_FW].va + (dtcm_dmem_addr - VPU_DTCM_SIZE);
+}
+EXPORT_SYMBOL_GPL(vpu_mapping_dm_addr);
+
+struct platform_device *vpu_get_plat_device(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *vpu_node;
+	struct platform_device *vpu_pdev;
+
+	vpu_node = of_parse_phandle(dev->of_node, "mediatek,vpu", 0);
+	if (!vpu_node) {
+		dev_err(dev, "can't get vpu node\n");
+		return NULL;
+	}
+
+	vpu_pdev = of_find_device_by_node(vpu_node);
+	if (WARN_ON(!vpu_pdev)) {
+		dev_err(dev, "vpu pdev failed\n");
+		of_node_put(vpu_node);
+		return NULL;
+	}
+
+	return vpu_pdev;
+}
+EXPORT_SYMBOL_GPL(vpu_get_plat_device);
+
+/* load vpu program/data memory */
+static int load_requested_vpu(struct mtk_vpu *vpu,
+			      const struct firmware *vpu_fw,
+			      u8 fw_type)
+{
+	size_t tcm_size = fw_type ? VPU_DTCM_SIZE : VPU_PTCM_SIZE;
+	size_t fw_size = fw_type ? VPU_D_FW_SIZE : VPU_P_FW_SIZE;
+	char *fw_name = fw_type ? VPU_D_FW : VPU_P_FW;
+	size_t dl_size = 0;
+	size_t extra_fw_size = 0;
+	void *dest;
+	int ret;
+
+	ret = request_firmware(&vpu_fw, fw_name, vpu->dev);
+	if (ret < 0) {
+		dev_err(vpu->dev, "Failed to load %s, %d\n", fw_name, ret);
+		return ret;
+	}
+	dl_size = vpu_fw->size;
+	if (dl_size > fw_size) {
+		dev_err(vpu->dev, "fw %s size %zu is abnormal\n", fw_name,
+			dl_size);
+		release_firmware(vpu_fw);
+		return  -EFBIG;
+	}
+	dev_dbg(vpu->dev, "Downloaded fw %s size: %zu.\n",
+		fw_name,
+		dl_size);
+	/* reset VPU */
+	vpu_cfg_writel(vpu, 0x0, VPU_RESET);
+
+	/* handle extended firmware size */
+	if (dl_size > tcm_size) {
+		dev_dbg(vpu->dev, "fw size %zu > limited fw size %zu\n",
+			dl_size, tcm_size);
+		extra_fw_size = dl_size - tcm_size;
+		dev_dbg(vpu->dev, "extra_fw_size %zu\n", extra_fw_size);
+		dl_size = tcm_size;
+	}
+	dest = (__force void *)vpu->reg.tcm;
+	if (fw_type == D_FW)
+		dest += VPU_DTCM_OFFSET;
+	memcpy(dest, vpu_fw->data, dl_size);
+	/* download to extended memory if need */
+	if (extra_fw_size > 0) {
+		dest = vpu->extmem[fw_type].va;
+		dev_dbg(vpu->dev, "download extended memory type %x\n",
+			fw_type);
+		memcpy(dest, vpu_fw->data + tcm_size, extra_fw_size);
+	}
+
+	release_firmware(vpu_fw);
+
+	return 0;
+}
+
+int vpu_load_firmware(struct platform_device *pdev)
+{
+	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+	struct vpu_run *run = &vpu->run;
+	const struct firmware *vpu_fw = NULL;
+	int ret;
+
+	if (!pdev) {
+		dev_err(dev, "VPU platform device is invalid\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&vpu->vpu_mutex);
+	if (vpu->fw_loaded) {
+		mutex_unlock(&vpu->vpu_mutex);
+		return 0;
+	}
+	mutex_unlock(&vpu->vpu_mutex);
+
+	ret = vpu_clock_enable(vpu);
+	if (ret) {
+		dev_err(dev, "enable clock failed %d\n", ret);
+		return ret;
+	}
+
+	mutex_lock(&vpu->vpu_mutex);
+
+	run->signaled = false;
+	dev_dbg(vpu->dev, "firmware request\n");
+	/* Downloading program firmware to device*/
+	ret = load_requested_vpu(vpu, vpu_fw, P_FW);
+	if (ret < 0) {
+		dev_err(dev, "Failed to request %s, %d\n", VPU_P_FW, ret);
+		goto OUT_LOAD_FW;
+	}
+
+	/* Downloading data firmware to device */
+	ret = load_requested_vpu(vpu, vpu_fw, D_FW);
+	if (ret < 0) {
+		dev_err(dev, "Failed to request %s, %d\n", VPU_D_FW, ret);
+		goto OUT_LOAD_FW;
+	}
+
+	vpu->fw_loaded = true;
+	/* boot up vpu */
+	vpu_cfg_writel(vpu, 0x1, VPU_RESET);
+
+	ret = wait_event_interruptible_timeout(run->wq,
+					       run->signaled,
+					       msecs_to_jiffies(INIT_TIMEOUT_MS)
+					       );
+	if (ret == 0) {
+		ret = -ETIME;
+		dev_err(dev, "wait vpu initialization timout!\n");
+		goto OUT_LOAD_FW;
+	} else if (-ERESTARTSYS == ret) {
+		dev_err(dev, "wait vpu interrupted by a signal!\n");
+		goto OUT_LOAD_FW;
+	}
+
+	ret = 0;
+	dev_info(dev, "vpu is ready. Fw version %s\n", run->fw_ver);
+
+OUT_LOAD_FW:
+	mutex_unlock(&vpu->vpu_mutex);
+	vpu_clock_disable(vpu);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vpu_load_firmware);
+
+static void vpu_init_ipi_handler(void *data, unsigned int len, void *priv)
+{
+	struct mtk_vpu *vpu = (struct mtk_vpu *)priv;
+	struct vpu_run *run = (struct vpu_run *)data;
+
+	vpu->run.signaled = run->signaled;
+	strncpy(vpu->run.fw_ver, run->fw_ver, VPU_FW_VER_LEN);
+	vpu->run.enc_capability = run->enc_capability;
+	wake_up_interruptible(&vpu->run.wq);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static ssize_t vpu_debug_read(struct file *file, char __user *user_buf,
+			      size_t count, loff_t *ppos)
+{
+	char buf[256];
+	unsigned int len;
+	unsigned int running, pc, vpu_to_host, host_to_vpu, wdt;
+	int ret;
+	struct device *dev = file->private_data;
+	struct mtk_vpu *vpu = dev_get_drvdata(dev);
+
+	ret = vpu_clock_enable(vpu);
+	if (ret) {
+		dev_err(vpu->dev, "[VPU] enable clock failed %d\n", ret);
+		return 0;
+	}
+
+	/* vpu register status */
+	running = vpu_running(vpu);
+	pc = vpu_cfg_readl(vpu, VPU_PC_REG);
+	wdt = vpu_cfg_readl(vpu, VPU_WDT_REG);
+	host_to_vpu = vpu_cfg_readl(vpu, HOST_TO_VPU);
+	vpu_to_host = vpu_cfg_readl(vpu, VPU_TO_HOST);
+	vpu_clock_disable(vpu);
+
+	if (running) {
+		len = snprintf(buf, sizeof(buf), "VPU is running\n\n"
+		"FW Version: %s\n"
+		"PC: 0x%x\n"
+		"WDT: 0x%x\n"
+		"Host to VPU: 0x%x\n"
+		"VPU to Host: 0x%x\n",
+		vpu->run.fw_ver, pc, wdt,
+		host_to_vpu, vpu_to_host);
+	} else {
+		len = snprintf(buf, sizeof(buf), "VPU not running\n");
+	}
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations vpu_debug_fops = {
+	.open = simple_open,
+	.read = vpu_debug_read,
+};
+#endif /* CONFIG_DEBUG_FS */
+
+static void vpu_free_ext_mem(struct mtk_vpu *vpu, u8 fw_type)
+{
+	struct device *dev = vpu->dev;
+	size_t fw_ext_size = fw_type ? VPU_EXT_D_SIZE : VPU_EXT_P_SIZE;
+
+	dma_free_coherent(dev, fw_ext_size, vpu->extmem[fw_type].va,
+			  vpu->extmem[fw_type].pa);
+}
+
+static int vpu_alloc_ext_mem(struct mtk_vpu *vpu, u32 fw_type)
+{
+	struct device *dev = vpu->dev;
+	size_t fw_ext_size = fw_type ? VPU_EXT_D_SIZE : VPU_EXT_P_SIZE;
+	u32 vpu_ext_mem0 = fw_type ? VPU_DMEM_EXT0_ADDR : VPU_PMEM_EXT0_ADDR;
+	u32 vpu_ext_mem1 = fw_type ? VPU_DMEM_EXT1_ADDR : VPU_PMEM_EXT1_ADDR;
+	u32 offset_4gb = vpu->enable_4GB ? 0x40000000 : 0;
+
+	vpu->extmem[fw_type].va = dma_alloc_coherent(dev,
+					       fw_ext_size,
+					       &vpu->extmem[fw_type].pa,
+					       GFP_KERNEL);
+	if (!vpu->extmem[fw_type].va) {
+		dev_err(dev, "Failed to allocate the extended program memory\n");
+		return PTR_ERR(vpu->extmem[fw_type].va);
+	}
+
+	/* Disable extend0. Enable extend1 */
+	vpu_cfg_writel(vpu, 0x1, vpu_ext_mem0);
+	vpu_cfg_writel(vpu, (vpu->extmem[fw_type].pa & 0xFFFFF000) + offset_4gb,
+		       vpu_ext_mem1);
+
+	dev_info(dev, "%s extend memory phy=0x%llx virt=0x%p\n",
+		 fw_type ? "Data" : "Program",
+		 (unsigned long long)vpu->extmem[fw_type].pa,
+		 vpu->extmem[fw_type].va);
+
+	return 0;
+}
+
+static void vpu_ipi_handler(struct mtk_vpu *vpu)
+{
+	struct share_obj *rcv_obj = vpu->recv_buf;
+	struct vpu_ipi_desc *ipi_desc = vpu->ipi_desc;
+
+	if (rcv_obj->id < IPI_MAX && ipi_desc[rcv_obj->id].handler) {
+		ipi_desc[rcv_obj->id].handler(rcv_obj->share_buf,
+					      rcv_obj->len,
+					      ipi_desc[rcv_obj->id].priv);
+		if (rcv_obj->id > IPI_VPU_INIT) {
+			vpu->ipi_id_ack[rcv_obj->id] = true;
+			wake_up(&vpu->ack_wq);
+		}
+	} else {
+		dev_err(vpu->dev, "No such ipi id = %d\n", rcv_obj->id);
+	}
+}
+
+static int vpu_ipi_init(struct mtk_vpu *vpu)
+{
+	/* Disable VPU to host interrupt */
+	vpu_cfg_writel(vpu, 0x0, VPU_TO_HOST);
+
+	/* shared buffer initialization */
+	vpu->recv_buf = (__force struct share_obj *)(vpu->reg.tcm +
+						     VPU_DTCM_OFFSET);
+	vpu->send_buf = vpu->recv_buf + 1;
+	memset(vpu->recv_buf, 0, sizeof(struct share_obj));
+	memset(vpu->send_buf, 0, sizeof(struct share_obj));
+
+	return 0;
+}
+
+static irqreturn_t vpu_irq_handler(int irq, void *priv)
+{
+	struct mtk_vpu *vpu = priv;
+	u32 vpu_to_host;
+	int ret;
+
+	/*
+	 * Clock should have been enabled already.
+	 * Enable again in case vpu_ipi_send times out
+	 * and has disabled the clock.
+	 */
+	ret = clk_enable(vpu->clk);
+	if (ret) {
+		dev_err(vpu->dev, "[VPU] enable clock failed %d\n", ret);
+		return IRQ_NONE;
+	}
+	vpu_to_host = vpu_cfg_readl(vpu, VPU_TO_HOST);
+	if (vpu_to_host & VPU_IPC_INT) {
+		vpu_ipi_handler(vpu);
+	} else {
+		dev_err(vpu->dev, "vpu watchdog timeout! 0x%x", vpu_to_host);
+		queue_work(vpu->wdt.wq, &vpu->wdt.ws);
+	}
+
+	/* VPU won't send another interrupt until we set VPU_TO_HOST to 0. */
+	vpu_cfg_writel(vpu, 0x0, VPU_TO_HOST);
+	clk_disable(vpu->clk);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *vpu_debugfs;
+#endif
+static int mtk_vpu_probe(struct platform_device *pdev)
+{
+	struct mtk_vpu *vpu;
+	struct device *dev;
+	struct resource *res;
+	int ret = 0;
+
+	dev_dbg(&pdev->dev, "initialization\n");
+
+	dev = &pdev->dev;
+	vpu = devm_kzalloc(dev, sizeof(*vpu), GFP_KERNEL);
+	if (!vpu)
+		return -ENOMEM;
+
+	vpu->dev = &pdev->dev;
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tcm");
+	vpu->reg.tcm = devm_ioremap_resource(dev, res);
+	if (IS_ERR((__force void *)vpu->reg.tcm)) {
+		dev_err(dev, "devm_ioremap_resource vpu tcm failed.\n");
+		return PTR_ERR((__force void *)vpu->reg.tcm);
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_reg");
+	vpu->reg.cfg = devm_ioremap_resource(dev, res);
+	if (IS_ERR((__force void *)vpu->reg.cfg)) {
+		dev_err(dev, "devm_ioremap_resource vpu cfg failed.\n");
+		return PTR_ERR((__force void *)vpu->reg.cfg);
+	}
+
+	/* Get VPU clock */
+	vpu->clk = devm_clk_get(dev, "main");
+	if (!vpu->clk) {
+		dev_err(dev, "get vpu clock failed\n");
+		return -EINVAL;
+	}
+
+	platform_set_drvdata(pdev, vpu);
+
+	ret = clk_prepare(vpu->clk);
+	if (ret) {
+		dev_err(dev, "prepare vpu clock failed\n");
+		return ret;
+	}
+
+	/* VPU watchdog */
+	vpu->wdt.wq = create_singlethread_workqueue("vpu_wdt");
+	if (!vpu->wdt.wq) {
+		dev_err(dev, "initialize wdt workqueue failed\n");
+		return -ENOMEM;
+	}
+	INIT_WORK(&vpu->wdt.ws, vpu_wdt_reset_func);
+	mutex_init(&vpu->vpu_mutex);
+
+	ret = vpu_clock_enable(vpu);
+	if (ret) {
+		dev_err(dev, "enable vpu clock failed\n");
+		goto workqueue_destroy;
+	}
+
+	dev_dbg(dev, "vpu ipi init\n");
+	ret = vpu_ipi_init(vpu);
+	if (ret) {
+		dev_err(dev, "Failed to init ipi\n");
+		goto disable_vpu_clk;
+	}
+
+	/* register vpu initialization IPI */
+	ret = vpu_ipi_register(pdev, IPI_VPU_INIT, vpu_init_ipi_handler,
+			       "vpu_init", vpu);
+	if (ret) {
+		dev_err(dev, "Failed to register IPI_VPU_INIT\n");
+		goto vpu_mutex_destroy;
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	vpu_debugfs = debugfs_create_file("mtk_vpu", S_IRUGO, NULL, (void *)dev,
+					  &vpu_debug_fops);
+	if (!vpu_debugfs) {
+		ret = -ENOMEM;
+		goto cleanup_ipi;
+	}
+#endif
+
+	/* Set PTCM to 96K and DTCM to 32K */
+	vpu_cfg_writel(vpu, 0x2, VPU_TCM_CFG);
+
+	vpu->enable_4GB = !!(totalram_pages > (SZ_2G >> PAGE_SHIFT));
+	dev_info(dev, "4GB mode %u\n", vpu->enable_4GB);
+
+	if (vpu->enable_4GB) {
+		ret = of_reserved_mem_device_init(dev);
+		if (ret)
+			dev_info(dev, "init reserved memory failed\n");
+			/* continue to use dynamic allocation if failed */
+	}
+
+	ret = vpu_alloc_ext_mem(vpu, D_FW);
+	if (ret) {
+		dev_err(dev, "Allocate DM failed\n");
+		goto remove_debugfs;
+	}
+
+	ret = vpu_alloc_ext_mem(vpu, P_FW);
+	if (ret) {
+		dev_err(dev, "Allocate PM failed\n");
+		goto free_d_mem;
+	}
+
+	init_waitqueue_head(&vpu->run.wq);
+	init_waitqueue_head(&vpu->ack_wq);
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev, "get IRQ resource failed.\n");
+		ret = -ENXIO;
+		goto free_p_mem;
+	}
+	vpu->reg.irq = platform_get_irq(pdev, 0);
+	ret = devm_request_irq(dev, vpu->reg.irq, vpu_irq_handler, 0,
+			       pdev->name, vpu);
+	if (ret) {
+		dev_err(dev, "failed to request irq\n");
+		goto free_p_mem;
+	}
+
+	vpu_clock_disable(vpu);
+	dev_dbg(dev, "initialization completed\n");
+
+	return 0;
+
+free_p_mem:
+	vpu_free_ext_mem(vpu, P_FW);
+free_d_mem:
+	vpu_free_ext_mem(vpu, D_FW);
+remove_debugfs:
+	of_reserved_mem_device_release(dev);
+#ifdef CONFIG_DEBUG_FS
+	debugfs_remove(vpu_debugfs);
+cleanup_ipi:
+#endif
+	memset(vpu->ipi_desc, 0, sizeof(struct vpu_ipi_desc) * IPI_MAX);
+vpu_mutex_destroy:
+	mutex_destroy(&vpu->vpu_mutex);
+disable_vpu_clk:
+	vpu_clock_disable(vpu);
+workqueue_destroy:
+	destroy_workqueue(vpu->wdt.wq);
+
+	return ret;
+}
+
+static const struct of_device_id mtk_vpu_match[] = {
+	{
+		.compatible = "mediatek,mt8173-vpu",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_vpu_match);
+
+static int mtk_vpu_remove(struct platform_device *pdev)
+{
+	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
+
+#ifdef CONFIG_DEBUG_FS
+	debugfs_remove(vpu_debugfs);
+#endif
+	if (vpu->wdt.wq) {
+		flush_workqueue(vpu->wdt.wq);
+		destroy_workqueue(vpu->wdt.wq);
+	}
+	vpu_free_ext_mem(vpu, P_FW);
+	vpu_free_ext_mem(vpu, D_FW);
+	mutex_destroy(&vpu->vpu_mutex);
+	clk_unprepare(vpu->clk);
+
+	return 0;
+}
+
+static struct platform_driver mtk_vpu_driver = {
+	.probe	= mtk_vpu_probe,
+	.remove	= mtk_vpu_remove,
+	.driver	= {
+		.name	= "mtk_vpu",
+		.of_match_table = mtk_vpu_match,
+	},
+};
+
+module_platform_driver(mtk_vpu_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Mediatek Video Prosessor Unit driver");
diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.h b/drivers/media/platform/mtk-vpu/mtk_vpu.h
new file mode 100644
index 0000000..5ab37f0
--- /dev/null
+++ b/drivers/media/platform/mtk-vpu/mtk_vpu.h
@@ -0,0 +1,162 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: Andrew-CT Chen <andrew-ct.chen at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MTK_VPU_H
+#define _MTK_VPU_H
+
+#include <linux/platform_device.h>
+
+/**
+ * VPU (video processor unit) is a tiny processor controlling video hardware
+ * related to video codec, scaling and color format converting.
+ * VPU interfaces with other blocks by share memory and interrupt.
+ **/
+
+typedef void (*ipi_handler_t) (void *data,
+			       unsigned int len,
+			       void *priv);
+
+/**
+ * enum ipi_id - the id of inter-processor interrupt
+ *
+ * @IPI_VPU_INIT:	 The interrupt from vpu is to notfiy kernel
+			 VPU initialization completed.
+			 IPI_VPU_INIT is sent from VPU when firmware is
+			 loaded. AP doesn't need to send IPI_VPU_INIT
+			 command to VPU.
+			 For other IPI below, AP should send the request
+			 to VPU to trigger the interrupt.
+ * @IPI_VENC_H264:	 The interrupt from vpu is to notify kernel to
+			 handle H264 video encoder job, and vice versa.
+ * @IPI_VENC_VP8:	 The interrupt fro vpu is to notify kernel to
+			 handle VP8 video encoder job,, and vice versa.
+ * @IPI_MAX:		 The maximum IPI number
+ */
+
+enum ipi_id {
+	IPI_VPU_INIT = 0,
+	IPI_VENC_H264,
+	IPI_VENC_VP8,
+	IPI_MAX,
+};
+
+/**
+ * enum rst_id - reset id to register reset function for VPU watchdog timeout
+ *
+ * @VPU_RST_ENC: encoder reset id
+ * @VPU_RST_MAX: maximum reset id
+ */
+enum rst_id {
+	VPU_RST_ENC,
+	VPU_RST_MAX,
+};
+
+/**
+ * vpu_ipi_register - register an ipi function
+ *
+ * @pdev:	VPU platform device
+ * @id:		IPI ID
+ * @handler:	IPI handler
+ * @name:	IPI name
+ * @priv:	private data for IPI handler
+ *
+ * Register an ipi function to receive ipi interrupt from VPU.
+ *
+ * Return: Return 0 if ipi registers successfully, otherwise it is failed.
+ */
+int vpu_ipi_register(struct platform_device *pdev, enum ipi_id id,
+		     ipi_handler_t handler, const char *name, void *priv);
+
+/**
+ * vpu_ipi_send - send data from AP to vpu.
+ *
+ * @pdev:	VPU platform device
+ * @id:		IPI ID
+ * @buf:	the data buffer
+ * @len:	the data buffer length
+ *
+ * This function is thread-safe. When this function returns,
+ * VPU has received the data and starts the processing.
+ * When the processing completes, IPI handler registered
+ * by vpu_ipi_register will be called in interrupt context.
+ *
+ * Return: Return 0 if sending data successfully, otherwise it is failed.
+ **/
+int vpu_ipi_send(struct platform_device *pdev,
+		 enum ipi_id id, void *buf,
+		 unsigned int len);
+
+/**
+ * vpu_get_plat_device - get VPU's platform device
+ *
+ * @pdev:	the platform device of the module requesting VPU platform
+ *		device for using VPU API.
+ *
+ * Return: Return NULL if it is failed.
+ * otherwise it is VPU's platform device
+ **/
+struct platform_device *vpu_get_plat_device(struct platform_device *pdev);
+
+/**
+ * vpu_wdt_reg_handler - register a VPU watchdog handler
+ *
+ * @pdev:               VPU platform device
+ * @vpu_wdt_reset_func:	the callback reset function
+ * @private_data:       the private data for reset function
+ * @rst_id:		reset id
+ *
+ * Register a handler performing own tasks when vpu reset by watchdog
+ *
+ * Return: Return 0 if the handler is added successfully,
+ * otherwise it is failed.
+ *
+ **/
+int vpu_wdt_reg_handler(struct platform_device *pdev,
+			void vpu_wdt_reset_func(void *),
+			void *priv, enum rst_id id);
+/**
+ * vpu_get_venc_hw_capa - get video encoder hardware capability
+ *
+ * @pdev:	VPU platform device
+ *
+ * Return: video encoder hardware capability
+ **/
+unsigned int vpu_get_venc_hw_capa(struct platform_device *pdev);
+
+/**
+ * vpu_load_firmware - download VPU firmware and boot it
+ *
+ * @pdev:	VPU platform device
+ *
+ * Return: Return 0 if downloading firmware successfully,
+ * otherwise it is failed
+ **/
+int vpu_load_firmware(struct platform_device *pdev);
+
+/**
+ * vpu_mapping_dm_addr - Mapping DTCM/DMEM to kernel virtual address
+ *
+ * @pdev:	VPU platform device
+ * @dmem_addr:	VPU's data memory address
+ *
+ * Mapping the VPU's DTCM (Data Tightly-Coupled Memory) /
+ * DMEM (Data Extended Memory) memory address to
+ * kernel virtual address.
+ *
+ * Return: Return ERR_PTR(-EINVAL) if mapping failed,
+ * otherwise the mapped kernel virtual address
+ **/
+void *vpu_mapping_dm_addr(struct platform_device *pdev,
+			  u32 dtcm_dmem_addr);
+#endif /* _MTK_VPU_H */
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Tue May  3 03:11:25 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Tue, 3 May 2016 18:11:25 +0800
Subject: [PATCH v10 6/8] [media] vcodec: mediatek: Add Mediatek VP8 Video
 Encoder Driver
In-Reply-To: <1462270287-11374-6-git-send-email-tiffany.lin@mediatek.com>
References: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-2-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-3-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-4-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-5-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-6-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1462270287-11374-7-git-send-email-tiffany.lin@mediatek.com>

Add vp8 encoder driver for MT8173

Signed-off-by: PoChun Lin <pochun.lin at mediatek.com>
Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>

---
 drivers/media/platform/mtk-vcodec/Makefile         |    6 +-
 .../media/platform/mtk-vcodec/venc/venc_vp8_if.c   |  481 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/venc_drv_if.c    |    7 +-
 drivers/media/platform/mtk-vcodec/venc_vpu_if.c    |  237 ++++++++++
 drivers/media/platform/mtk-vcodec/venc_vpu_if.h    |   61 +++
 5 files changed, 790 insertions(+), 2 deletions(-)
 create mode 100644 drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/venc_vpu_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/venc_vpu_if.h

diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
index d04433be..bf73a45 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -1,12 +1,16 @@
 
+
 obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-enc.o mtk-vcodec-common.o
 
 
 
-mtk-vcodec-enc-y := mtk_vcodec_enc.o \
+mtk-vcodec-enc-y := venc/venc_vp8_if.o \
+		venc/venc_h264_if.o \
+		mtk_vcodec_enc.o \
 		mtk_vcodec_enc_drv.o \
 		mtk_vcodec_enc_pm.o \
 		venc_drv_if.o \
+		venc_vpu_if.o \
 
 mtk-vcodec-common-y := mtk_vcodec_intr.o \
 		mtk_vcodec_util.o\
diff --git a/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c
new file mode 100644
index 0000000..431ae70
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c
@@ -0,0 +1,481 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Daniel Hsiao <daniel.hsiao at mediatek.com>
+ *         PoChun Lin <pochun.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "../mtk_vcodec_drv.h"
+#include "../mtk_vcodec_util.h"
+#include "../mtk_vcodec_intr.h"
+#include "../mtk_vcodec_enc.h"
+#include "../mtk_vcodec_enc_pm.h"
+#include "../venc_drv_base.h"
+#include "../venc_ipi_msg.h"
+#include "../venc_vpu_if.h"
+#include "mtk_vpu.h"
+
+#define VENC_BITSTREAM_FRAME_SIZE 0x0098
+#define VENC_BITSTREAM_HEADER_LEN 0x00e8
+
+/* This ac_tag is vp8 frame tag. */
+#define MAX_AC_TAG_SIZE 10
+
+/**
+ * enum venc_vp8_vpu_work_buf - vp8 encoder buffer index
+ */
+enum venc_vp8_vpu_work_buf {
+	VENC_VP8_VPU_WORK_BUF_LUMA,
+	VENC_VP8_VPU_WORK_BUF_LUMA2,
+	VENC_VP8_VPU_WORK_BUF_LUMA3,
+	VENC_VP8_VPU_WORK_BUF_CHROMA,
+	VENC_VP8_VPU_WORK_BUF_CHROMA2,
+	VENC_VP8_VPU_WORK_BUF_CHROMA3,
+	VENC_VP8_VPU_WORK_BUF_MV_INFO,
+	VENC_VP8_VPU_WORK_BUF_BS_HEADER,
+	VENC_VP8_VPU_WORK_BUF_PROB_BUF,
+	VENC_VP8_VPU_WORK_BUF_RC_INFO,
+	VENC_VP8_VPU_WORK_BUF_RC_CODE,
+	VENC_VP8_VPU_WORK_BUF_RC_CODE2,
+	VENC_VP8_VPU_WORK_BUF_RC_CODE3,
+	VENC_VP8_VPU_WORK_BUF_MAX,
+};
+
+/*
+ * struct venc_vp8_vpu_config - Structure for vp8 encoder configuration
+ * @input_fourcc: input fourcc
+ * @bitrate: target bitrate (in bps)
+ * @pic_w: picture width. Picture size is visible stream resolution, in pixels,
+ *         to be used for display purposes; must be smaller or equal to buffer
+ *         size.
+ * @pic_h: picture height
+ * @buf_w: buffer width (with 16 alignment). Buffer size is stream resolution
+ *         in pixels aligned to hardware requirements.
+ * @buf_h: buffer height (with 16 alignment)
+ * @gop_size: group of picture size (key frame)
+ * @framerate: frame rate in fps
+ * @ts_mode: temporal scalability mode (0: disable, 1: enable)
+ *	     support three temporal layers - 0: 7.5fps 1: 7.5fps 2: 15fps.
+ */
+struct venc_vp8_vpu_config {
+	u32 input_fourcc;
+	u32 bitrate;
+	u32 pic_w;
+	u32 pic_h;
+	u32 buf_w;
+	u32 buf_h;
+	u32 gop_size;
+	u32 framerate;
+	u32 ts_mode;
+};
+
+/*
+ * struct venc_vp8_vpu_buf -Structure for buffer information
+ * @align: buffer alignment (in bytes)
+ * @iova: IO virtual address
+ * @vpua: VPU side memory addr which is used by RC_CODE
+ * @size: buffer size (in bytes)
+ */
+struct venc_vp8_vpu_buf {
+	u32 align;
+	u32 iova;
+	u32 vpua;
+	u32 size;
+};
+
+/*
+ * struct venc_vp8_vsi - Structure for VPU driver control and info share
+ * This structure is allocated in VPU side and shared to AP side.
+ * @config: vp8 encoder configuration
+ * @work_bufs: working buffer information in VPU side
+ * The work_bufs here is for storing the 'size' info shared to AP side.
+ * The similar item in struct venc_vp8_inst is for memory allocation
+ * in AP side. The AP driver will copy the 'size' from here to the one in
+ * struct mtk_vcodec_mem, then invoke mtk_vcodec_mem_alloc to allocate
+ * the buffer. After that, bypass the 'dma_addr' to the 'iova' field here for
+ * register setting in VPU side.
+ */
+struct venc_vp8_vsi {
+	struct venc_vp8_vpu_config config;
+	struct venc_vp8_vpu_buf work_bufs[VENC_VP8_VPU_WORK_BUF_MAX];
+};
+
+/*
+ * struct venc_vp8_inst - vp8 encoder AP driver instance
+ * @hw_base: vp8 encoder hardware register base
+ * @work_bufs: working buffer
+ * @work_buf_allocated: working buffer allocated flag
+ * @frm_cnt: encoded frame count, it's used for I-frame judgement and
+ *	     reset when force intra cmd received.
+ * @ts_mode: temporal scalability mode (0: disable, 1: enable)
+ *	     support three temporal layers - 0: 7.5fps 1: 7.5fps 2: 15fps.
+ * @vpu_inst: VPU instance to exchange information between AP and VPU
+ * @vsi: driver structure allocated by VPU side and shared to AP side for
+ *	 control and info share
+ * @ctx: context for v4l2 layer integration
+ */
+struct venc_vp8_inst {
+	void __iomem *hw_base;
+	struct mtk_vcodec_mem work_bufs[VENC_VP8_VPU_WORK_BUF_MAX];
+	bool work_buf_allocated;
+	unsigned int frm_cnt;
+	unsigned int ts_mode;
+	struct venc_vpu_inst vpu_inst;
+	struct venc_vp8_vsi *vsi;
+	struct mtk_vcodec_ctx *ctx;
+};
+
+static inline void vp8_enc_write_reg(struct venc_vp8_inst *inst, u32 addr,
+				     u32 val)
+{
+	writel(val, inst->hw_base + addr);
+}
+
+static inline u32 vp8_enc_read_reg(struct venc_vp8_inst *inst, u32 addr)
+{
+	return readl(inst->hw_base + addr);
+}
+
+static void vp8_enc_free_work_buf(struct venc_vp8_inst *inst)
+{
+	int i;
+
+	mtk_vcodec_debug_enter(inst);
+
+	/* Buffers need to be freed by AP. */
+	for (i = 0; i < VENC_VP8_VPU_WORK_BUF_MAX; i++) {
+		if ((inst->work_bufs[i].size == 0))
+			continue;
+		mtk_vcodec_mem_free(inst->ctx, &inst->work_bufs[i]);
+	}
+
+	mtk_vcodec_debug_leave(inst);
+}
+
+static int vp8_enc_alloc_work_buf(struct venc_vp8_inst *inst)
+{
+	int i;
+	int ret = 0;
+	struct venc_vp8_vpu_buf *wb = inst->vsi->work_bufs;
+
+	mtk_vcodec_debug_enter(inst);
+
+	for (i = 0; i < VENC_VP8_VPU_WORK_BUF_MAX; i++) {
+		if ((wb[i].size == 0))
+			continue;
+		/*
+		 * This 'wb' structure is set by VPU side and shared to AP for
+		 * buffer allocation and IO virtual addr mapping. For most of
+		 * the buffers, AP will allocate the buffer according to 'size'
+		 * field and store the IO virtual addr in 'iova' field. For the
+		 * RC_CODEx buffers, they are pre-allocated in the VPU side
+		 * because they are inside VPU SRAM, and save the VPU addr in
+		 * the 'vpua' field. The AP will translate the VPU addr to the
+		 * corresponding IO virtual addr and store in 'iova' field.
+		 */
+		inst->work_bufs[i].size = wb[i].size;
+		ret = mtk_vcodec_mem_alloc(inst->ctx, &inst->work_bufs[i]);
+		if (ret) {
+			mtk_vcodec_err(inst,
+				       "cannot alloc work_bufs[%d]", i);
+			goto err_alloc;
+		}
+		/*
+		 * This RC_CODEx is pre-allocated by VPU and saved in VPU addr.
+		 * So we need use memcpy to copy RC_CODEx from VPU addr into IO
+		 * virtual addr in 'iova' field for reg setting in VPU side.
+		 */
+		if (i == VENC_VP8_VPU_WORK_BUF_RC_CODE ||
+		    i == VENC_VP8_VPU_WORK_BUF_RC_CODE2 ||
+		    i == VENC_VP8_VPU_WORK_BUF_RC_CODE3) {
+			void *tmp_va;
+
+			tmp_va = vpu_mapping_dm_addr(inst->vpu_inst.dev,
+						     wb[i].vpua);
+			memcpy(inst->work_bufs[i].va, tmp_va, wb[i].size);
+		}
+		wb[i].iova = inst->work_bufs[i].dma_addr;
+
+		mtk_vcodec_debug(inst,
+				 "work_bufs[%d] va=0x%p,iova=0x%p,size=%zu",
+				 i, inst->work_bufs[i].va,
+				 (void *)inst->work_bufs[i].dma_addr,
+				 inst->work_bufs[i].size);
+	}
+
+	mtk_vcodec_debug_leave(inst);
+
+	return ret;
+
+err_alloc:
+	vp8_enc_free_work_buf(inst);
+
+	return ret;
+}
+
+static unsigned int vp8_enc_wait_venc_done(struct venc_vp8_inst *inst)
+{
+	unsigned int irq_status = 0;
+	struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)inst->ctx;
+
+	if (!mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED,
+					  WAIT_INTR_TIMEOUT_MS)) {
+		irq_status = ctx->irq_status;
+		mtk_vcodec_debug(inst, "isr return %x", irq_status);
+	}
+	return irq_status;
+}
+
+/*
+ * Compose ac_tag, bitstream header and bitstream payload into
+ * one bitstream buffer.
+ */
+static int vp8_enc_compose_one_frame(struct venc_vp8_inst *inst,
+				     struct mtk_vcodec_mem *bs_buf,
+				     unsigned int *bs_size)
+{
+	unsigned int not_key;
+	u32 bs_frm_size;
+	u32 bs_hdr_len;
+	unsigned int ac_tag_size;
+	u8 ac_tag[MAX_AC_TAG_SIZE];
+
+	bs_frm_size = vp8_enc_read_reg(inst, VENC_BITSTREAM_FRAME_SIZE);
+	bs_hdr_len = vp8_enc_read_reg(inst, VENC_BITSTREAM_HEADER_LEN);
+
+	/* if a frame is key frame, not_key is 0 */
+	not_key = !inst->vpu_inst.is_key_frm;
+	*(u32 *)ac_tag = __cpu_to_le32((bs_hdr_len << 5) | 0x10 | not_key);
+	/* key frame */
+	if (not_key == 0) {
+		ac_tag_size = MAX_AC_TAG_SIZE;
+		ac_tag[3] = 0x9d;
+		ac_tag[4] = 0x01;
+		ac_tag[5] = 0x2a;
+		ac_tag[6] = inst->vsi->config.pic_w;
+		ac_tag[7] = inst->vsi->config.pic_w >> 8;
+		ac_tag[8] = inst->vsi->config.pic_h;
+		ac_tag[9] = inst->vsi->config.pic_h >> 8;
+	} else {
+		ac_tag_size = 3;
+	}
+
+	if (bs_buf->size < bs_hdr_len + bs_frm_size + ac_tag_size) {
+		mtk_vcodec_err(inst, "bitstream buf size is too small(%zu)",
+			       bs_buf->size);
+		return -EINVAL;
+	}
+
+	/*
+	* (1) The vp8 bitstream header and body are generated by the HW vp8
+	* encoder separately at the same time. We cannot know the bitstream
+	* header length in advance.
+	* (2) From the vp8 spec, there is no stuffing byte allowed between the
+	* ac tag, bitstream header and bitstream body.
+	*/
+	memmove(bs_buf->va + bs_hdr_len + ac_tag_size,
+		bs_buf->va, bs_frm_size);
+	memcpy(bs_buf->va + ac_tag_size,
+	       inst->work_bufs[VENC_VP8_VPU_WORK_BUF_BS_HEADER].va,
+	       bs_hdr_len);
+	memcpy(bs_buf->va, ac_tag, ac_tag_size);
+	*bs_size = bs_frm_size + bs_hdr_len + ac_tag_size;
+
+	return 0;
+}
+
+static int vp8_enc_encode_frame(struct venc_vp8_inst *inst,
+				struct venc_frm_buf *frm_buf,
+				struct mtk_vcodec_mem *bs_buf,
+				unsigned int *bs_size)
+{
+	int ret = 0;
+	unsigned int irq_status;
+
+	mtk_vcodec_debug(inst, "->frm_cnt=%d", inst->frm_cnt);
+
+	ret = vpu_enc_encode(&inst->vpu_inst, 0, frm_buf, bs_buf, bs_size);
+	if (ret)
+		return ret;
+
+	irq_status = vp8_enc_wait_venc_done(inst);
+	if (irq_status != MTK_VENC_IRQ_STATUS_FRM) {
+		mtk_vcodec_err(inst, "irq_status=%d failed", irq_status);
+		return -EIO;
+	}
+
+	if (vp8_enc_compose_one_frame(inst, bs_buf, bs_size)) {
+		mtk_vcodec_err(inst, "vp8_enc_compose_one_frame failed");
+		return -EINVAL;
+	}
+
+	inst->frm_cnt++;
+	mtk_vcodec_debug(inst, "<-size=%d key_frm=%d", *bs_size,
+			 inst->vpu_inst.is_key_frm);
+
+	return ret;
+}
+
+static int vp8_enc_init(struct mtk_vcodec_ctx *ctx, unsigned long *handle)
+{
+	int ret = 0;
+	struct venc_vp8_inst *inst;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->ctx = ctx;
+	inst->vpu_inst.ctx = ctx;
+	inst->vpu_inst.dev = ctx->dev->vpu_plat_dev;
+	inst->vpu_inst.id = IPI_VENC_VP8;
+	inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx, VENC_LT_SYS);
+
+	mtk_vcodec_debug_enter(inst);
+
+	ret = vpu_enc_init(&inst->vpu_inst);
+
+	inst->vsi = (struct venc_vp8_vsi *)inst->vpu_inst.vsi;
+
+	mtk_vcodec_debug_leave(inst);
+
+	if (ret)
+		kfree(inst);
+	else
+		(*handle) = (unsigned long)inst;
+
+	return ret;
+}
+
+static int vp8_enc_encode(unsigned long handle,
+			  enum venc_start_opt opt,
+			  struct venc_frm_buf *frm_buf,
+			  struct mtk_vcodec_mem *bs_buf,
+			  struct venc_done_result *result)
+{
+	int ret = 0;
+	struct venc_vp8_inst *inst = (struct venc_vp8_inst *)handle;
+	struct mtk_vcodec_ctx *ctx = inst->ctx;
+
+	mtk_vcodec_debug_enter(inst);
+
+	enable_irq(ctx->dev->enc_lt_irq);
+
+	switch (opt) {
+	case VENC_START_OPT_ENCODE_FRAME:
+		ret = vp8_enc_encode_frame(inst, frm_buf, bs_buf,
+					   &result->bs_size);
+		if (ret)
+			goto encode_err;
+		result->is_key_frm = inst->vpu_inst.is_key_frm;
+		break;
+
+	default:
+		mtk_vcodec_err(inst, "opt not support:%d", opt);
+		ret = -EINVAL;
+		break;
+	}
+
+encode_err:
+
+	disable_irq(ctx->dev->enc_lt_irq);
+	mtk_vcodec_debug_leave(inst);
+
+	return ret;
+}
+
+static int vp8_enc_set_param(unsigned long handle,
+			     enum venc_set_param_type type,
+			     struct venc_enc_param *enc_prm)
+{
+	int ret = 0;
+	struct venc_vp8_inst *inst = (struct venc_vp8_inst *)handle;
+
+	mtk_vcodec_debug(inst, "->type=%d", type);
+
+	switch (type) {
+	case VENC_SET_PARAM_ENC:
+		inst->vsi->config.input_fourcc = enc_prm->input_yuv_fmt;
+		inst->vsi->config.bitrate = enc_prm->bitrate;
+		inst->vsi->config.pic_w = enc_prm->width;
+		inst->vsi->config.pic_h = enc_prm->height;
+		inst->vsi->config.buf_w = enc_prm->buf_width;
+		inst->vsi->config.buf_h = enc_prm->buf_height;
+		inst->vsi->config.gop_size = enc_prm->gop_size;
+		inst->vsi->config.framerate = enc_prm->frm_rate;
+		inst->vsi->config.ts_mode = inst->ts_mode;
+		ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
+		if (ret)
+			break;
+		if (inst->work_buf_allocated) {
+			vp8_enc_free_work_buf(inst);
+			inst->work_buf_allocated = false;
+		}
+		ret = vp8_enc_alloc_work_buf(inst);
+		if (ret)
+			break;
+		inst->work_buf_allocated = true;
+		break;
+
+	/*
+	 * VENC_SET_PARAM_TS_MODE must be called before VENC_SET_PARAM_ENC
+	 */
+	case VENC_SET_PARAM_TS_MODE:
+		inst->ts_mode = 1;
+		mtk_vcodec_debug(inst, "set ts_mode");
+		break;
+
+	default:
+		ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
+		break;
+	}
+
+	mtk_vcodec_debug_leave(inst);
+
+	return ret;
+}
+
+static int vp8_enc_deinit(unsigned long handle)
+{
+	int ret = 0;
+	struct venc_vp8_inst *inst = (struct venc_vp8_inst *)handle;
+
+	mtk_vcodec_debug_enter(inst);
+
+	ret = vpu_enc_deinit(&inst->vpu_inst);
+
+	if (inst->work_buf_allocated)
+		vp8_enc_free_work_buf(inst);
+
+	mtk_vcodec_debug_leave(inst);
+	kfree(inst);
+
+	return ret;
+}
+
+static struct venc_common_if venc_vp8_if = {
+	vp8_enc_init,
+	vp8_enc_encode,
+	vp8_enc_set_param,
+	vp8_enc_deinit,
+};
+
+struct venc_common_if *get_vp8_enc_comm_if(void);
+
+struct venc_common_if *get_vp8_enc_comm_if(void)
+{
+	return &venc_vp8_if;
+}
diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_if.c b/drivers/media/platform/mtk-vcodec/venc_drv_if.c
index 79ec9f5..77c39d2 100644
--- a/drivers/media/platform/mtk-vcodec/venc_drv_if.c
+++ b/drivers/media/platform/mtk-vcodec/venc_drv_if.c
@@ -19,12 +19,15 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 
+#include "venc_drv_base.h"
 #include "venc_drv_if.h"
+
 #include "mtk_vcodec_enc.h"
 #include "mtk_vcodec_enc_pm.h"
 #include "mtk_vpu.h"
 
-#include "venc_drv_base.h"
+
+struct venc_common_if *get_vp8_enc_comm_if(void);
 
 int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 {
@@ -32,6 +35,8 @@ int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 
 	switch (fourcc) {
 	case V4L2_PIX_FMT_VP8:
+		ctx->enc_if = get_vp8_enc_comm_if();
+		break;
 	case V4L2_PIX_FMT_H264:
 	default:
 		return -EINVAL;
diff --git a/drivers/media/platform/mtk-vcodec/venc_vpu_if.c b/drivers/media/platform/mtk-vcodec/venc_vpu_if.c
new file mode 100644
index 0000000..b92c6d2
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/venc_vpu_if.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PoChun Lin <pochun.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "mtk_vpu.h"
+#include "venc_ipi_msg.h"
+#include "venc_vpu_if.h"
+
+static void handle_enc_init_msg(struct venc_vpu_inst *vpu, void *data)
+{
+	struct venc_vpu_ipi_msg_init *msg = data;
+
+	vpu->inst_addr = msg->vpu_inst_addr;
+	vpu->vsi = vpu_mapping_dm_addr(vpu->dev, msg->vpu_inst_addr);
+}
+
+static void handle_enc_encode_msg(struct venc_vpu_inst *vpu, void *data)
+{
+	struct venc_vpu_ipi_msg_enc *msg = data;
+
+	vpu->state = msg->state;
+	vpu->bs_size = msg->bs_size;
+	vpu->is_key_frm = msg->is_key_frm;
+}
+
+static void vpu_enc_ipi_handler(void *data, unsigned int len, void *priv)
+{
+	struct venc_vpu_ipi_msg_common *msg = data;
+	struct venc_vpu_inst *vpu = (struct venc_vpu_inst *)msg->venc_inst;
+
+	mtk_vcodec_debug(vpu, "msg_id %x inst %p status %d",
+			 msg->msg_id, vpu, msg->status);
+
+	switch (msg->msg_id) {
+	case VPU_IPIMSG_ENC_INIT_DONE:
+		handle_enc_init_msg(vpu, data);
+		break;
+	case VPU_IPIMSG_ENC_SET_PARAM_DONE:
+		break;
+	case VPU_IPIMSG_ENC_ENCODE_DONE:
+		handle_enc_encode_msg(vpu, data);
+		break;
+	case VPU_IPIMSG_ENC_DEINIT_DONE:
+		break;
+	default:
+		mtk_vcodec_err(vpu, "unknown msg id %x", msg->msg_id);
+		break;
+	}
+
+	vpu->signaled = 1;
+	vpu->failure = (msg->status != VENC_IPI_MSG_STATUS_OK);
+
+	mtk_vcodec_debug_leave(vpu);
+}
+
+static int vpu_enc_send_msg(struct venc_vpu_inst *vpu, void *msg,
+			    int len)
+{
+	int status;
+
+	mtk_vcodec_debug_enter(vpu);
+
+	if (!vpu->dev) {
+		mtk_vcodec_err(vpu, "inst dev is NULL");
+		return -EINVAL;
+	}
+
+	status = vpu_ipi_send(vpu->dev, vpu->id, msg, len);
+	if (status) {
+		uint32_t msg_id = *(uint32_t *)msg;
+
+		mtk_vcodec_err(vpu, "vpu_ipi_send msg_id %x len %d fail %d",
+			       msg_id, len, status);
+		return -EINVAL;
+	}
+	if (vpu->failure)
+		return -EINVAL;
+
+	mtk_vcodec_debug_leave(vpu);
+
+	return 0;
+}
+
+int vpu_enc_init(struct venc_vpu_inst *vpu)
+{
+	int status;
+	struct venc_ap_ipi_msg_init out;
+
+	mtk_vcodec_debug_enter(vpu);
+
+	init_waitqueue_head(&vpu->wq_hd);
+	vpu->signaled = 0;
+	vpu->failure = 0;
+
+	status = vpu_ipi_register(vpu->dev, vpu->id, vpu_enc_ipi_handler,
+				  NULL, NULL);
+	if (status) {
+		mtk_vcodec_err(vpu, "vpu_ipi_register fail %d", status);
+		return -EINVAL;
+	}
+
+	memset(&out, 0, sizeof(out));
+	out.msg_id = AP_IPIMSG_ENC_INIT;
+	out.venc_inst = (unsigned long)vpu;
+	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {
+		mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_INIT fail");
+		return -EINVAL;
+	}
+
+	mtk_vcodec_debug_leave(vpu);
+
+	return 0;
+}
+
+int vpu_enc_set_param(struct venc_vpu_inst *vpu,
+		      enum venc_set_param_type id,
+		      struct venc_enc_param *enc_param)
+{
+	struct venc_ap_ipi_msg_set_param out;
+
+	mtk_vcodec_debug(vpu, "id %d ->", id);
+
+	memset(&out, 0, sizeof(out));
+	out.msg_id = AP_IPIMSG_ENC_SET_PARAM;
+	out.vpu_inst_addr = vpu->inst_addr;
+	out.param_id = id;
+	switch (id) {
+	case VENC_SET_PARAM_ENC:
+		out.data_item = 0;
+		break;
+	case VENC_SET_PARAM_FORCE_INTRA:
+		out.data_item = 0;
+		break;
+	case VENC_SET_PARAM_ADJUST_BITRATE:
+		out.data_item = 1;
+		out.data[0] = enc_param->bitrate;
+		break;
+	case VENC_SET_PARAM_ADJUST_FRAMERATE:
+		out.data_item = 1;
+		out.data[0] = enc_param->frm_rate;
+		break;
+	case VENC_SET_PARAM_GOP_SIZE:
+		out.data_item = 1;
+		out.data[0] = enc_param->gop_size;
+		break;
+	case VENC_SET_PARAM_INTRA_PERIOD:
+		out.data_item = 1;
+		out.data[0] = enc_param->intra_period;
+		break;
+	case VENC_SET_PARAM_SKIP_FRAME:
+		out.data_item = 0;
+		break;
+	default:
+		mtk_vcodec_err(vpu, "id %d not supported", id);
+		return -EINVAL;
+	}
+	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {
+		mtk_vcodec_err(vpu,
+			       "AP_IPIMSG_ENC_SET_PARAM %d fail", id);
+		return -EINVAL;
+	}
+
+	mtk_vcodec_debug(vpu, "id %d <-", id);
+
+	return 0;
+}
+
+int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode,
+		   struct venc_frm_buf *frm_buf,
+		   struct mtk_vcodec_mem *bs_buf,
+		   unsigned int *bs_size)
+{
+	struct venc_ap_ipi_msg_enc out;
+
+	mtk_vcodec_debug(vpu, "bs_mode %d ->", bs_mode);
+
+	memset(&out, 0, sizeof(out));
+	out.msg_id = AP_IPIMSG_ENC_ENCODE;
+	out.vpu_inst_addr = vpu->inst_addr;
+	out.bs_mode = bs_mode;
+	if (frm_buf) {
+		if ((frm_buf->fb_addr[0].dma_addr % 16 == 0) &&
+		    (frm_buf->fb_addr[1].dma_addr % 16 == 0) &&
+		    (frm_buf->fb_addr[2].dma_addr % 16 == 0)) {
+			out.input_addr[0] = frm_buf->fb_addr[0].dma_addr;
+			out.input_addr[1] = frm_buf->fb_addr[1].dma_addr;
+			out.input_addr[2] = frm_buf->fb_addr[2].dma_addr;
+		} else {
+			mtk_vcodec_err(vpu, "dma_addr not align to 16");
+			return -EINVAL;
+		}
+	}
+	if (bs_buf) {
+		out.bs_addr = bs_buf->dma_addr;
+		out.bs_size = bs_buf->size;
+	}
+	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {
+		mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_ENCODE %d fail",
+			       bs_mode);
+		return -EINVAL;
+	}
+
+	mtk_vcodec_debug(vpu, "bs_mode %d state %d size %d key_frm %d <-",
+			 bs_mode, vpu->state, vpu->bs_size, vpu->is_key_frm);
+
+	return 0;
+}
+
+int vpu_enc_deinit(struct venc_vpu_inst *vpu)
+{
+	struct venc_ap_ipi_msg_deinit out;
+
+	mtk_vcodec_debug_enter(vpu);
+
+	memset(&out, 0, sizeof(out));
+	out.msg_id = AP_IPIMSG_ENC_DEINIT;
+	out.vpu_inst_addr = vpu->inst_addr;
+	if (vpu_enc_send_msg(vpu, &out, sizeof(out))) {
+		mtk_vcodec_err(vpu, "AP_IPIMSG_ENC_DEINIT fail");
+		return -EINVAL;
+	}
+
+	mtk_vcodec_debug_leave(vpu);
+
+	return 0;
+}
diff --git a/drivers/media/platform/mtk-vcodec/venc_vpu_if.h b/drivers/media/platform/mtk-vcodec/venc_vpu_if.h
new file mode 100644
index 0000000..215d1e0
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/venc_vpu_if.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PoChun Lin <pochun.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VENC_VPU_IF_H_
+#define _VENC_VPU_IF_H_
+
+#include "mtk_vpu.h"
+#include "venc_drv_if.h"
+
+/*
+ * struct venc_vpu_inst - encoder VPU driver instance
+ * @wq_hd: wait queue used for vpu cmd trigger then wait vpu interrupt done
+ * @signaled: flag used for checking vpu interrupt done
+ * @failure: flag to show vpu cmd succeeds or not
+ * @state: enum venc_ipi_msg_enc_state
+ * @bs_size: bitstream size for skip frame case usage
+ * @is_key_frm: key frame flag
+ * @inst_addr: VPU instance addr
+ * @vsi: driver structure allocated by VPU side and shared to AP side for
+ *	 control and info share
+ * @id: the id of inter-processor interrupt
+ * @ctx: context for v4l2 layer integration
+ * @dev: device for v4l2 layer integration
+ */
+struct venc_vpu_inst {
+	wait_queue_head_t wq_hd;
+	int signaled;
+	int failure;
+	int state;
+	int bs_size;
+	int is_key_frm;
+	unsigned int inst_addr;
+	void *vsi;
+	enum ipi_id id;
+	struct mtk_vcodec_ctx *ctx;
+	struct platform_device *dev;
+};
+
+int vpu_enc_init(struct venc_vpu_inst *vpu);
+int vpu_enc_set_param(struct venc_vpu_inst *vpu,
+		      enum venc_set_param_type id,
+		      struct venc_enc_param *param);
+int vpu_enc_encode(struct venc_vpu_inst *vpu, unsigned int bs_mode,
+		   struct venc_frm_buf *frm_buf,
+		   struct mtk_vcodec_mem *bs_buf,
+		   unsigned int *bs_size);
+int vpu_enc_deinit(struct venc_vpu_inst *vpu);
+
+#endif
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Tue May  3 03:11:24 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Tue, 3 May 2016 18:11:24 +0800
Subject: [PATCH v10 5/8] [media] vcodec: mediatek: Add Mediatek V4L2 Video
 Encoder Driver
In-Reply-To: <1462270287-11374-5-git-send-email-tiffany.lin@mediatek.com>
References: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-2-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-3-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-4-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-5-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1462270287-11374-6-git-send-email-tiffany.lin@mediatek.com>

Add v4l2 layer encoder driver for MT8173

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>

---
 drivers/media/platform/Kconfig                     |   18 +
 drivers/media/platform/Makefile                    |    2 +
 drivers/media/platform/mtk-vcodec/Makefile         |   14 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h |  338 +++++
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 1288 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h |   58 +
 .../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c |  454 +++++++
 .../media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c  |  137 +++
 .../media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h  |   26 +
 .../media/platform/mtk-vcodec/mtk_vcodec_intr.c    |   55 +
 .../media/platform/mtk-vcodec/mtk_vcodec_intr.h    |   27 +
 .../media/platform/mtk-vcodec/mtk_vcodec_util.c    |   94 ++
 .../media/platform/mtk-vcodec/mtk_vcodec_util.h    |   87 ++
 drivers/media/platform/mtk-vcodec/venc_drv_base.h  |   62 +
 drivers/media/platform/mtk-vcodec/venc_drv_if.c    |  106 ++
 drivers/media/platform/mtk-vcodec/venc_drv_if.h    |  163 +++
 drivers/media/platform/mtk-vcodec/venc_ipi_msg.h   |  210 ++++
 17 files changed, 3139 insertions(+)
 create mode 100644 drivers/media/platform/mtk-vcodec/Makefile
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
 create mode 100644 drivers/media/platform/mtk-vcodec/venc_drv_base.h
 create mode 100644 drivers/media/platform/mtk-vcodec/venc_drv_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/venc_drv_if.h
 create mode 100644 drivers/media/platform/mtk-vcodec/venc_ipi_msg.h

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index d87ae31..c425461 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -166,6 +166,24 @@ config VIDEO_MEDIATEK_VPU
 	    To compile this driver as a module, choose M here: the
 	    module will be called mtk-vpu.
 
+config VIDEO_MEDIATEK_VCODEC
+	tristate "Mediatek Video Codec driver"
+        depends on ARM || ARM64
+        depends on MTK_IOMMU
+	depends on VIDEO_DEV && VIDEO_V4L2
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	select VIDEOBUF2_DMA_CONTIG
+	select V4L2_MEM2MEM_DEV
+	select VIDEO_MEDIATEK_VPU
+	default n
+	---help---
+	    Mediatek video codec driver provides HW capability to
+	    encode and decode in a range of video formats
+	    This driver rely on VPU driver to communicate with VPU.
+
+	    To compile this driver as a module, choose M here: the
+	    module will be called mtk-vcodec
+
 config VIDEO_MEM2MEM_DEINTERLACE
 	tristate "Deinterlace support"
 	depends on VIDEO_DEV && VIDEO_V4L2 && DMA_ENGINE
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 2efb7b1..6e735fe 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -58,3 +58,5 @@ obj-$(CONFIG_VIDEO_XILINX)		+= xilinx/
 ccflags-y += -I$(srctree)/drivers/media/i2c
 
 obj-$(CONFIG_VIDEO_MEDIATEK_VPU)	+= mtk-vpu/
+
+obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC)	+= mtk-vcodec/
diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
new file mode 100644
index 0000000..d04433be
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -0,0 +1,14 @@
+
+obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-enc.o mtk-vcodec-common.o
+
+
+
+mtk-vcodec-enc-y := mtk_vcodec_enc.o \
+		mtk_vcodec_enc_drv.o \
+		mtk_vcodec_enc_pm.o \
+		venc_drv_if.o \
+
+mtk-vcodec-common-y := mtk_vcodec_intr.o \
+		mtk_vcodec_util.o\
+
+ccflags-y += -I$(srctree)/drivers/media/platform/mtk-vpu
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
new file mode 100644
index 0000000..78eee50
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -0,0 +1,338 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen at mediatek.com>
+*         Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MTK_VCODEC_DRV_H_
+#define _MTK_VCODEC_DRV_H_
+
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+
+#include "mtk_vcodec_util.h"
+
+#define MTK_VCODEC_DRV_NAME	"mtk_vcodec_drv"
+#define MTK_VCODEC_ENC_NAME	"mtk-vcodec-enc"
+#define MTK_PLATFORM_STR	"platform:mt8173"
+
+
+#define MTK_VCODEC_MAX_PLANES	3
+#define MTK_V4L2_BENCHMARK	0
+#define WAIT_INTR_TIMEOUT_MS	1000
+
+/**
+ * enum mtk_hw_reg_idx - MTK hw register base index
+ */
+enum mtk_hw_reg_idx {
+	VDEC_SYS,
+	VDEC_MISC,
+	VDEC_LD,
+	VDEC_TOP,
+	VDEC_CM,
+	VDEC_AD,
+	VDEC_AV,
+	VDEC_PP,
+	VDEC_HWD,
+	VDEC_HWQ,
+	VDEC_HWB,
+	VDEC_HWG,
+	NUM_MAX_VDEC_REG_BASE,
+	/* h264 encoder */
+	VENC_SYS = NUM_MAX_VDEC_REG_BASE,
+	/* vp8 encoder */
+	VENC_LT_SYS,
+	NUM_MAX_VCODEC_REG_BASE
+};
+
+/**
+ * enum mtk_instance_type - The type of an MTK Vcodec instance.
+ */
+enum mtk_instance_type {
+	MTK_INST_DECODER		= 0,
+	MTK_INST_ENCODER		= 1,
+};
+
+/**
+ * enum mtk_instance_state - The state of an MTK Vcodec instance.
+ * @MTK_STATE_FREE - default state when instance is created
+ * @MTK_STATE_INIT - vcodec instance is initialized
+ * @MTK_STATE_HEADER - vdec had sps/pps header parsed or venc
+ *			had sps/pps header encoded
+ * @MTK_STATE_FLUSH - vdec is flushing. Only used by decoder
+ * @MTK_STATE_ABORT - vcodec should be aborted
+ */
+enum mtk_instance_state {
+	MTK_STATE_FREE = 0,
+	MTK_STATE_INIT = 1,
+	MTK_STATE_HEADER = 2,
+	MTK_STATE_FLUSH = 3,
+	MTK_STATE_ABORT = 4,
+};
+
+/**
+ * struct mtk_encode_param - General encoding parameters type
+ */
+enum mtk_encode_param {
+	MTK_ENCODE_PARAM_NONE = 0,
+	MTK_ENCODE_PARAM_BITRATE = (1 << 0),
+	MTK_ENCODE_PARAM_FRAMERATE = (1 << 1),
+	MTK_ENCODE_PARAM_INTRA_PERIOD = (1 << 2),
+	MTK_ENCODE_PARAM_FORCE_INTRA = (1 << 3),
+	MTK_ENCODE_PARAM_GOP_SIZE = (1 << 4),
+};
+
+enum mtk_fmt_type {
+	MTK_FMT_DEC = 0,
+	MTK_FMT_ENC = 1,
+	MTK_FMT_FRAME = 2,
+};
+
+/**
+ * struct mtk_video_fmt - Structure used to store information about pixelformats
+ */
+struct mtk_video_fmt {
+	u32	fourcc;
+	enum mtk_fmt_type	type;
+	u32	num_planes;
+};
+
+/**
+ * struct mtk_codec_framesizes - Structure used to store information about
+ *							framesizes
+ */
+struct mtk_codec_framesizes {
+	u32	fourcc;
+	struct	v4l2_frmsize_stepwise	stepwise;
+};
+
+/**
+ * struct mtk_q_type - Type of queue
+ */
+enum mtk_q_type {
+	MTK_Q_DATA_SRC = 0,
+	MTK_Q_DATA_DST = 1,
+};
+
+/**
+ * struct mtk_q_data - Structure used to store information about queue
+ */
+struct mtk_q_data {
+	unsigned int	visible_width;
+	unsigned int	visible_height;
+	unsigned int	coded_width;
+	unsigned int	coded_height;
+	enum v4l2_field	field;
+	unsigned int	bytesperline[MTK_VCODEC_MAX_PLANES];
+	unsigned int	sizeimage[MTK_VCODEC_MAX_PLANES];
+	struct mtk_video_fmt	*fmt;
+};
+
+/**
+ * struct mtk_enc_params - General encoding parameters
+ * @bitrate: target bitrate in bits per second
+ * @num_b_frame: number of b frames between p-frame
+ * @rc_frame: frame based rate control
+ * @rc_mb: macroblock based rate control
+ * @seq_hdr_mode: H.264 sequence header is encoded separately or joined
+ *		  with the first frame
+ * @intra_period: I frame period
+ * @gop_size: group of picture size, it's used as the intra frame period
+ * @framerate_num: frame rate numerator. ex: framerate_num=30 and
+ *		   framerate_denom=1 menas FPS is 30
+ * @framerate_denom: frame rate denominator. ex: framerate_num=30 and
+ *		     framerate_denom=1 menas FPS is 30
+ * @h264_max_qp: Max value for H.264 quantization parameter
+ * @h264_profile: V4L2 defined H.264 profile
+ * @h264_level: V4L2 defined H.264 level
+ * @force_intra: force/insert intra frame
+ */
+struct mtk_enc_params {
+	unsigned int	bitrate;
+	unsigned int	num_b_frame;
+	unsigned int	rc_frame;
+	unsigned int	rc_mb;
+	unsigned int	seq_hdr_mode;
+	unsigned int	intra_period;
+	unsigned int	gop_size;
+	unsigned int	framerate_num;
+	unsigned int	framerate_denom;
+	unsigned int	h264_max_qp;
+	unsigned int	h264_profile;
+	unsigned int	h264_level;
+	unsigned int	force_intra;
+};
+
+/**
+ * struct mtk_vcodec_pm - Power management data structure
+ */
+struct mtk_vcodec_pm {
+	struct clk	*vcodecpll;
+	struct clk	*univpll_d2;
+	struct clk	*clk_cci400_sel;
+	struct clk	*vdecpll;
+	struct clk	*vdec_sel;
+	struct clk	*vencpll_d2;
+	struct clk	*venc_sel;
+	struct clk	*univpll1_d2;
+	struct clk	*venc_lt_sel;
+	struct device	*larbvdec;
+	struct device	*larbvenc;
+	struct device	*larbvenclt;
+	struct device	*dev;
+	struct mtk_vcodec_dev	*mtkdev;
+};
+
+/**
+ * struct mtk_vcodec_ctx - Context (instance) private data.
+ *
+ * @type: type of the instance - decoder or encoder
+ * @dev: pointer to the mtk_vcodec_dev of the device
+ * @list: link to ctx_list of mtk_vcodec_dev
+ * @fh: struct v4l2_fh
+ * @m2m_ctx: pointer to the v4l2_m2m_ctx of the context
+ * @q_data: store information of input and output queue
+ *	    of the context
+ * @id: index of the context that this structure describes
+ * @state: state of the context
+ * @param_change: indicate encode parameter type
+ * @enc_params: encoding parameters
+ * @enc_if: hoooked encoder driver interface
+ * @drv_handle: driver handle for specific decode/encode instance
+ *
+ * @int_cond: variable used by the waitqueue
+ * @int_type: type of the last interrupt
+ * @queue: waitqueue that can be used to wait for this context to
+ *	   finish
+ * @irq_status: irq status
+ *
+ * @ctrl_hdl: handler for v4l2 framework
+ * @encode_work: worker for the encoding
+ *
+ * @colorspace: enum v4l2_colorspace; supplemental to pixelformat
+ * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
+ * @quantization: enum v4l2_quantization, colorspace quantization
+ * @xfer_func: enum v4l2_xfer_func, colorspace transfer function
+ */
+struct mtk_vcodec_ctx {
+	enum mtk_instance_type type;
+	struct mtk_vcodec_dev *dev;
+	struct list_head list;
+
+	struct v4l2_fh fh;
+	struct v4l2_m2m_ctx *m2m_ctx;
+	struct mtk_q_data q_data[2];
+	int id;
+	enum mtk_instance_state state;
+	enum mtk_encode_param param_change;
+	struct mtk_enc_params enc_params;
+
+	struct venc_common_if *enc_if;
+	unsigned long drv_handle;
+
+	int int_cond;
+	int int_type;
+	wait_queue_head_t queue;
+	unsigned int irq_status;
+
+	struct v4l2_ctrl_handler ctrl_hdl;
+	struct work_struct encode_work;
+
+	enum v4l2_colorspace colorspace;
+	enum v4l2_ycbcr_encoding ycbcr_enc;
+	enum v4l2_quantization quantization;
+	enum v4l2_xfer_func xfer_func;
+};
+
+/**
+ * struct mtk_vcodec_dev - driver data
+ * @v4l2_dev: V4L2 device to register video devices for.
+ * @vfd_enc: Video device for encoder.
+ *
+ * @m2m_dev_enc: m2m device for encoder.
+ * @plat_dev: platform device
+ * @vpu_plat_dev: mtk vpu platform device
+ * @alloc_ctx: VB2 allocator context
+ *	       (for allocations without kernel mapping).
+ * @ctx_list: list of struct mtk_vcodec_ctx
+ * @irqlock: protect data access by irq handler and work thread
+ * @curr_ctx: The context that is waiting for codec hardware
+ *
+ * @reg_base: Mapped address of MTK Vcodec registers.
+ *
+ * @id_counter: used to identify current opened instance
+ * @num_instances: counter of active MTK Vcodec instances
+ *
+ * @encode_workqueue: encode work queue
+ *
+ * @int_cond: used to identify interrupt condition happen
+ * @int_type: used to identify what kind of interrupt condition happen
+ * @dev_mutex: video_device lock
+ * @queue: waitqueue for waiting for completion of device commands
+ *
+ * @enc_irq: h264 encoder irq resource
+ * @enc_lt_irq: vp8 encoder irq resource
+ *
+ * @enc_mutex: encoder hardware lock.
+ *
+ * @pm: power management control
+ * @dec_capability: used to identify decode capability, ex: 4k
+ * @enc_capability: used to identify encode capability
+ */
+struct mtk_vcodec_dev {
+	struct v4l2_device v4l2_dev;
+	struct video_device *vfd_enc;
+
+	struct v4l2_m2m_dev *m2m_dev_enc;
+	struct platform_device *plat_dev;
+	struct platform_device *vpu_plat_dev;
+	struct vb2_alloc_ctx *alloc_ctx;
+	struct list_head ctx_list;
+	spinlock_t irqlock;
+	struct mtk_vcodec_ctx *curr_ctx;
+	void __iomem *reg_base[NUM_MAX_VCODEC_REG_BASE];
+
+	unsigned long id_counter;
+	int num_instances;
+
+	struct workqueue_struct *encode_workqueue;
+
+	int int_cond;
+	int int_type;
+	struct mutex dev_mutex;
+	wait_queue_head_t queue;
+
+	int enc_irq;
+	int enc_lt_irq;
+
+	struct mutex enc_mutex;
+
+	struct mtk_vcodec_pm pm;
+	unsigned int dec_capability;
+	unsigned int enc_capability;
+};
+
+static inline struct mtk_vcodec_ctx *fh_to_ctx(struct v4l2_fh *fh)
+{
+	return container_of(fh, struct mtk_vcodec_ctx, fh);
+}
+
+static inline struct mtk_vcodec_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl)
+{
+	return container_of(ctrl->handler, struct mtk_vcodec_ctx, ctrl_hdl);
+}
+
+#endif /* _MTK_VCODEC_DRV_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
new file mode 100644
index 0000000..6e72d73
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
@@ -0,0 +1,1288 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen at mediatek.com>
+*         Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+#include <soc/mediatek/smi.h>
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_enc.h"
+#include "mtk_vcodec_intr.h"
+#include "mtk_vcodec_util.h"
+#include "venc_drv_if.h"
+
+#define MTK_VENC_MIN_W	160U
+#define MTK_VENC_MIN_H	128U
+#define MTK_VENC_MAX_W	1920U
+#define MTK_VENC_MAX_H	1088U
+#define DFT_CFG_WIDTH	MTK_VENC_MIN_W
+#define DFT_CFG_HEIGHT	MTK_VENC_MIN_H
+#define MTK_MAX_CTRLS_HINT	20
+#define OUT_FMT_IDX		0
+#define CAP_FMT_IDX		4
+
+
+static void mtk_venc_worker(struct work_struct *work);
+
+static struct mtk_video_fmt mtk_video_formats[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_NV12M,
+		.type = MTK_FMT_FRAME,
+		.num_planes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV21M,
+		.type = MTK_FMT_FRAME,
+		.num_planes = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YUV420M,
+		.type = MTK_FMT_FRAME,
+		.num_planes = 3,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YVU420M,
+		.type = MTK_FMT_FRAME,
+		.num_planes = 3,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_H264,
+		.type = MTK_FMT_ENC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP8,
+		.type = MTK_FMT_ENC,
+		.num_planes = 1,
+	},
+};
+
+#define NUM_FORMATS ARRAY_SIZE(mtk_video_formats)
+
+static const struct mtk_codec_framesizes mtk_venc_framesizes[] = {
+	{
+		.fourcc	= V4L2_PIX_FMT_H264,
+		.stepwise = { MTK_VENC_MIN_W, MTK_VENC_MAX_W, 16,
+			      MTK_VENC_MIN_H, MTK_VENC_MAX_H, 16 },
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP8,
+		.stepwise = { MTK_VENC_MIN_W, MTK_VENC_MAX_W, 16,
+			      MTK_VENC_MIN_H, MTK_VENC_MAX_H, 16 },
+	},
+};
+
+#define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(mtk_venc_framesizes)
+
+static int vidioc_venc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mtk_vcodec_ctx *ctx = ctrl_to_ctx(ctrl);
+	struct mtk_enc_params *p = &ctx->enc_params;
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_BITRATE val = %d",
+			       ctrl->val);
+		p->bitrate = ctrl->val;
+		ctx->param_change |= MTK_ENCODE_PARAM_BITRATE;
+		break;
+	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_B_FRAMES val = %d",
+			       ctrl->val);
+		p->num_b_frame = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
+		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE val = %d",
+			       ctrl->val);
+		p->rc_frame = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_H264_MAX_QP val = %d",
+			       ctrl->val);
+		p->h264_max_qp = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_HEADER_MODE val = %d",
+			       ctrl->val);
+		p->seq_hdr_mode = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
+		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE val = %d",
+			       ctrl->val);
+		p->rc_mb = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_H264_PROFILE val = %d",
+			       ctrl->val);
+		p->h264_profile = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_H264_LEVEL val = %d",
+			       ctrl->val);
+		p->h264_level = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
+		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_H264_I_PERIOD val = %d",
+			       ctrl->val);
+		p->intra_period = ctrl->val;
+		ctx->param_change |= MTK_ENCODE_PARAM_INTRA_PERIOD;
+		break;
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_GOP_SIZE val = %d",
+			       ctrl->val);
+		p->gop_size = ctrl->val;
+		ctx->param_change |= MTK_ENCODE_PARAM_GOP_SIZE;
+		break;
+	case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:
+		mtk_v4l2_debug(2, "V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME");
+		p->force_intra = 1;
+		ctx->param_change |= MTK_ENCODE_PARAM_FORCE_INTRA;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops mtk_vcodec_enc_ctrl_ops = {
+	.s_ctrl = vidioc_venc_s_ctrl,
+};
+
+static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue)
+{
+	struct mtk_video_fmt *fmt;
+	int i, j = 0;
+
+	for (i = 0; i < NUM_FORMATS; ++i) {
+		if (output_queue && mtk_video_formats[i].type != MTK_FMT_FRAME)
+			continue;
+		if (!output_queue && mtk_video_formats[i].type != MTK_FMT_ENC)
+			continue;
+
+		if (j == f->index) {
+			fmt = &mtk_video_formats[i];
+			f->pixelformat = fmt->fourcc;
+			memset(f->reserved, 0, sizeof(f->reserved));
+			return 0;
+		}
+		++j;
+	}
+
+	return -EINVAL;
+}
+
+static int vidioc_enum_framesizes(struct file *file, void *fh,
+				  struct v4l2_frmsizeenum *fsize)
+{
+	int i = 0;
+
+	if (fsize->index != 0)
+		return -EINVAL;
+
+	for (i = 0; i < NUM_SUPPORTED_FRAMESIZE; ++i) {
+		if (fsize->pixel_format != mtk_venc_framesizes[i].fourcc)
+			continue;
+
+		fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+		fsize->stepwise = mtk_venc_framesizes[i].stepwise;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
+					  struct v4l2_fmtdesc *f)
+{
+	return vidioc_enum_fmt(f, false);
+}
+
+static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
+					  struct v4l2_fmtdesc *f)
+{
+	return vidioc_enum_fmt(f, true);
+}
+
+static int vidioc_venc_querycap(struct file *file, void *priv,
+				struct v4l2_capability *cap)
+{
+	strlcpy(cap->driver, MTK_VCODEC_ENC_NAME, sizeof(cap->driver));
+	strlcpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info));
+	strlcpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card));
+
+	return 0;
+}
+
+static int vidioc_venc_s_parm(struct file *file, void *priv,
+			      struct v4l2_streamparm *a)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return -EINVAL;
+
+	ctx->enc_params.framerate_num =
+			a->parm.output.timeperframe.denominator;
+	ctx->enc_params.framerate_denom =
+			a->parm.output.timeperframe.numerator;
+	ctx->param_change |= MTK_ENCODE_PARAM_FRAMERATE;
+
+	return 0;
+}
+
+static int vidioc_venc_g_parm(struct file *file, void *priv,
+			      struct v4l2_streamparm *a)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return -EINVAL;
+
+	a->parm.output.timeperframe.denominator =
+			ctx->enc_params.framerate_num;
+	a->parm.output.timeperframe.numerator =
+			ctx->enc_params.framerate_denom;
+
+	return 0;
+}
+
+static struct mtk_q_data *mtk_venc_get_q_data(struct mtk_vcodec_ctx *ctx,
+					      enum v4l2_buf_type type)
+{
+	if (V4L2_TYPE_IS_OUTPUT(type))
+		return &ctx->q_data[MTK_Q_DATA_SRC];
+
+	return &ctx->q_data[MTK_Q_DATA_DST];
+}
+
+static struct mtk_video_fmt *mtk_venc_find_format(struct v4l2_format *f)
+{
+	struct mtk_video_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < NUM_FORMATS; k++) {
+		fmt = &mtk_video_formats[k];
+		if (fmt->fourcc == f->fmt.pix.pixelformat)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+/* V4L2 specification suggests the driver corrects the format struct if any of
+ * the dimensions is unsupported
+ */
+static int vidioc_try_fmt(struct v4l2_format *f, struct mtk_video_fmt *fmt)
+{
+	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+	int i;
+
+	pix_fmt_mp->field = V4L2_FIELD_NONE;
+
+	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		pix_fmt_mp->num_planes = 1;
+		pix_fmt_mp->plane_fmt[0].bytesperline = 0;
+	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		int tmp_w, tmp_h;
+
+		pix_fmt_mp->height = clamp(pix_fmt_mp->height,
+					MTK_VENC_MIN_H,
+					MTK_VENC_MAX_H);
+		pix_fmt_mp->width = clamp(pix_fmt_mp->width,
+					MTK_VENC_MIN_W,
+					MTK_VENC_MAX_W);
+
+		/* find next closer width align 16, heign align 32, size align
+		 * 64 rectangle
+		 */
+		tmp_w = pix_fmt_mp->width;
+		tmp_h = pix_fmt_mp->height;
+		v4l_bound_align_image(&pix_fmt_mp->width,
+					MTK_VENC_MIN_W,
+					MTK_VENC_MAX_W, 4,
+					&pix_fmt_mp->height,
+					MTK_VENC_MIN_H,
+					MTK_VENC_MAX_H, 5, 6);
+
+		if (pix_fmt_mp->width < tmp_w &&
+			(pix_fmt_mp->width + 16) <= MTK_VENC_MAX_W)
+			pix_fmt_mp->width += 16;
+		if (pix_fmt_mp->height < tmp_h &&
+			(pix_fmt_mp->height + 32) <= MTK_VENC_MAX_H)
+			pix_fmt_mp->height += 32;
+
+		mtk_v4l2_debug(0,
+			"before resize width=%d, height=%d, after resize width=%d, height=%d, sizeimage=%d",
+			tmp_w, tmp_h, pix_fmt_mp->width,
+			pix_fmt_mp->height,
+			pix_fmt_mp->width * pix_fmt_mp->height);
+
+		pix_fmt_mp->num_planes = fmt->num_planes;
+		pix_fmt_mp->plane_fmt[0].sizeimage =
+				pix_fmt_mp->width * pix_fmt_mp->height +
+				((ALIGN(pix_fmt_mp->width, 16) * 2) * 16);
+		pix_fmt_mp->plane_fmt[0].bytesperline = pix_fmt_mp->width;
+
+		if (pix_fmt_mp->num_planes == 2) {
+			pix_fmt_mp->plane_fmt[1].sizeimage =
+				(pix_fmt_mp->width * pix_fmt_mp->height) / 2 +
+				(ALIGN(pix_fmt_mp->width, 16) * 16);
+			pix_fmt_mp->plane_fmt[2].sizeimage = 0;
+			pix_fmt_mp->plane_fmt[1].bytesperline =
+							pix_fmt_mp->width;
+			pix_fmt_mp->plane_fmt[2].bytesperline = 0;
+		} else if (pix_fmt_mp->num_planes == 3) {
+			pix_fmt_mp->plane_fmt[1].sizeimage =
+			pix_fmt_mp->plane_fmt[2].sizeimage =
+				(pix_fmt_mp->width * pix_fmt_mp->height) / 4 +
+				((ALIGN(pix_fmt_mp->width, 16) / 2) * 16);
+			pix_fmt_mp->plane_fmt[1].bytesperline =
+				pix_fmt_mp->plane_fmt[2].bytesperline =
+				pix_fmt_mp->width / 2;
+		}
+	}
+
+	for (i = 0; i < pix_fmt_mp->num_planes; i++)
+		memset(&(pix_fmt_mp->plane_fmt[i].reserved[0]), 0x0,
+			   sizeof(pix_fmt_mp->plane_fmt[0].reserved));
+
+	pix_fmt_mp->flags = 0;
+	memset(&pix_fmt_mp->reserved, 0x0,
+		sizeof(pix_fmt_mp->reserved));
+
+	return 0;
+}
+
+static void mtk_venc_set_param(struct mtk_vcodec_ctx *ctx,
+				struct venc_enc_param *param)
+{
+	struct mtk_q_data *q_data_src = &ctx->q_data[MTK_Q_DATA_SRC];
+	struct mtk_enc_params *enc_params = &ctx->enc_params;
+
+	switch (q_data_src->fmt->fourcc) {
+	case V4L2_PIX_FMT_YUV420M:
+		param->input_yuv_fmt = VENC_YUV_FORMAT_I420;
+		break;
+	case V4L2_PIX_FMT_YVU420M:
+		param->input_yuv_fmt = VENC_YUV_FORMAT_YV12;
+		break;
+	case V4L2_PIX_FMT_NV12M:
+		param->input_yuv_fmt = VENC_YUV_FORMAT_NV12;
+		break;
+	case V4L2_PIX_FMT_NV21M:
+		param->input_yuv_fmt = VENC_YUV_FORMAT_NV21;
+		break;
+	default:
+		mtk_v4l2_err("Unsupport fourcc =%d", q_data_src->fmt->fourcc);
+		break;
+	}
+	param->h264_profile = enc_params->h264_profile;
+	param->h264_level = enc_params->h264_level;
+
+	/* Config visible resolution */
+	param->width = q_data_src->visible_width;
+	param->height = q_data_src->visible_height;
+	/* Config coded resolution */
+	param->buf_width = q_data_src->coded_width;
+	param->buf_height = q_data_src->coded_height;
+	param->frm_rate = enc_params->framerate_num /
+			enc_params->framerate_denom;
+	param->intra_period = enc_params->intra_period;
+	param->gop_size = enc_params->gop_size;
+	param->bitrate = enc_params->bitrate;
+
+	mtk_v4l2_debug(0,
+		"fmt 0x%x, P/L %d/%d, w/h %d/%d, buf %d/%d, fps/bps %d/%d, gop %d, i_period %d",
+		param->input_yuv_fmt, param->h264_profile,
+		param->h264_level, param->width, param->height,
+		param->buf_width, param->buf_height,
+		param->frm_rate, param->bitrate,
+		param->gop_size, param->intra_period);
+}
+
+static int vidioc_venc_s_fmt_cap(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct vb2_queue *vq;
+	struct mtk_q_data *q_data;
+	int i, ret;
+	struct mtk_video_fmt *fmt;
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+	if (!vq) {
+		mtk_v4l2_err("fail to get vq");
+		return -EINVAL;
+	}
+
+	if (vb2_is_busy(vq)) {
+		mtk_v4l2_err("queue busy");
+		return -EBUSY;
+	}
+
+	q_data = mtk_venc_get_q_data(ctx, f->type);
+	if (!q_data) {
+		mtk_v4l2_err("fail to get q data");
+		return -EINVAL;
+	}
+
+	fmt = mtk_venc_find_format(f);
+	if (!fmt) {
+		f->fmt.pix.pixelformat = mtk_video_formats[CAP_FMT_IDX].fourcc;
+		fmt = mtk_venc_find_format(f);
+	}
+
+	q_data->fmt = fmt;
+	ret = vidioc_try_fmt(f, q_data->fmt);
+	if (ret)
+		return ret;
+
+	q_data->coded_width = f->fmt.pix_mp.width;
+	q_data->coded_height = f->fmt.pix_mp.height;
+	q_data->field = f->fmt.pix_mp.field;
+
+	for (i = 0; i < f->fmt.pix_mp.num_planes; i++) {
+		struct v4l2_plane_pix_format	*plane_fmt;
+
+		plane_fmt = &f->fmt.pix_mp.plane_fmt[i];
+		q_data->bytesperline[i]	= plane_fmt->bytesperline;
+		q_data->sizeimage[i] = plane_fmt->sizeimage;
+	}
+
+	if (ctx->state == MTK_STATE_FREE) {
+		ret = venc_if_init(ctx, q_data->fmt->fourcc);
+		if (ret) {
+			mtk_v4l2_err("venc_if_init failed=%d, codec type=%x",
+					ret, q_data->fmt->fourcc);
+			return -EBUSY;
+		}
+		ctx->state = MTK_STATE_INIT;
+	}
+
+	return 0;
+}
+
+static int vidioc_venc_s_fmt_out(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct vb2_queue *vq;
+	struct mtk_q_data *q_data;
+	int ret, i;
+	struct mtk_video_fmt *fmt;
+	unsigned int pitch_w_div16;
+	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+	if (!vq) {
+		mtk_v4l2_err("fail to get vq");
+		return -EINVAL;
+	}
+
+	if (vb2_is_busy(vq)) {
+		mtk_v4l2_err("queue busy");
+		return -EBUSY;
+	}
+
+	q_data = mtk_venc_get_q_data(ctx, f->type);
+	if (!q_data) {
+		mtk_v4l2_err("fail to get q data");
+		return -EINVAL;
+	}
+
+	fmt = mtk_venc_find_format(f);
+	if (!fmt) {
+		f->fmt.pix.pixelformat = mtk_video_formats[OUT_FMT_IDX].fourcc;
+		fmt = mtk_venc_find_format(f);
+	}
+
+	pix_fmt_mp->height = clamp(pix_fmt_mp->height,
+				MTK_VENC_MIN_H,
+				MTK_VENC_MAX_H);
+	pix_fmt_mp->width = clamp(pix_fmt_mp->width,
+				MTK_VENC_MIN_W,
+				MTK_VENC_MAX_W);
+
+	q_data->visible_width = f->fmt.pix_mp.width;
+	q_data->visible_height = f->fmt.pix_mp.height;
+	q_data->fmt = fmt;
+	ret = vidioc_try_fmt(f, q_data->fmt);
+	if (ret)
+		return ret;
+
+	q_data->coded_width = f->fmt.pix_mp.width;
+	q_data->coded_height = f->fmt.pix_mp.height;
+
+	pitch_w_div16 = DIV_ROUND_UP(q_data->visible_width, 16);
+	if (pitch_w_div16 % 8 != 0) {
+		/* Adjust returned width/height, so application could correctly
+		 * allocate hw required memory
+		 */
+		q_data->visible_height += 32;
+		vidioc_try_fmt(f, q_data->fmt);
+	}
+
+	q_data->field = f->fmt.pix_mp.field;
+	ctx->colorspace = f->fmt.pix_mp.colorspace;
+	ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
+	ctx->quantization = f->fmt.pix_mp.quantization;
+	ctx->xfer_func = f->fmt.pix_mp.xfer_func;
+
+	for (i = 0; i < f->fmt.pix_mp.num_planes; i++) {
+		struct v4l2_plane_pix_format *plane_fmt;
+
+		plane_fmt = &f->fmt.pix_mp.plane_fmt[i];
+		q_data->bytesperline[i] = plane_fmt->bytesperline;
+		q_data->sizeimage[i] = plane_fmt->sizeimage;
+	}
+
+	return 0;
+}
+
+static int vidioc_venc_g_fmt(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct vb2_queue *vq;
+	struct mtk_q_data *q_data;
+	int i;
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+	if (!vq)
+		return -EINVAL;
+
+	q_data = mtk_venc_get_q_data(ctx, f->type);
+
+	pix->width = q_data->coded_width;
+	pix->height = q_data->coded_height;
+	pix->pixelformat = q_data->fmt->fourcc;
+	pix->field = q_data->field;
+	pix->num_planes = q_data->fmt->num_planes;
+	for (i = 0; i < pix->num_planes; i++) {
+		pix->plane_fmt[i].bytesperline = q_data->bytesperline[i];
+		pix->plane_fmt[i].sizeimage = q_data->sizeimage[i];
+		memset(&(pix->plane_fmt[i].reserved[0]), 0x0,
+		       sizeof(pix->plane_fmt[i].reserved));
+	}
+
+	pix->flags = 0;
+	pix->colorspace = ctx->colorspace;
+	pix->ycbcr_enc = ctx->ycbcr_enc;
+	pix->quantization = ctx->quantization;
+	pix->xfer_func = ctx->xfer_func;
+
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv,
+					 struct v4l2_format *f)
+{
+	struct mtk_video_fmt *fmt;
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	fmt = mtk_venc_find_format(f);
+	if (!fmt) {
+		f->fmt.pix.pixelformat = mtk_video_formats[CAP_FMT_IDX].fourcc;
+		fmt = mtk_venc_find_format(f);
+	}
+	f->fmt.pix_mp.colorspace = ctx->colorspace;
+	f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc;
+	f->fmt.pix_mp.quantization = ctx->quantization;
+	f->fmt.pix_mp.xfer_func = ctx->xfer_func;
+
+	return vidioc_try_fmt(f, fmt);
+}
+
+static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv,
+					 struct v4l2_format *f)
+{
+	struct mtk_video_fmt *fmt;
+
+	fmt = mtk_venc_find_format(f);
+	if (!fmt) {
+		f->fmt.pix.pixelformat = mtk_video_formats[OUT_FMT_IDX].fourcc;
+		fmt = mtk_venc_find_format(f);
+	}
+	if (!f->fmt.pix_mp.colorspace) {
+		f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709;
+		f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+		f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;
+		f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;
+	}
+
+	return vidioc_try_fmt(f, fmt);
+}
+
+static int vidioc_venc_qbuf(struct file *file, void *priv,
+			    struct v4l2_buffer *buf)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (ctx->state == MTK_STATE_ABORT) {
+		mtk_v4l2_err("[%d] Call on QBUF after unrecoverable error",
+				ctx->id);
+		return -EIO;
+	}
+
+	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_venc_dqbuf(struct file *file, void *priv,
+			     struct v4l2_buffer *buf)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (ctx->state == MTK_STATE_ABORT) {
+		mtk_v4l2_err("[%d] Call on QBUF after unrecoverable error",
+				ctx->id);
+		return -EIO;
+	}
+
+	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+}
+
+const struct v4l2_ioctl_ops mtk_venc_ioctl_ops = {
+	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
+
+	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
+	.vidioc_qbuf			= vidioc_venc_qbuf,
+	.vidioc_dqbuf			= vidioc_venc_dqbuf,
+
+	.vidioc_querycap		= vidioc_venc_querycap,
+	.vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
+	.vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
+	.vidioc_enum_framesizes		= vidioc_enum_framesizes,
+
+	.vidioc_try_fmt_vid_cap_mplane	= vidioc_try_fmt_vid_cap_mplane,
+	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_out_mplane,
+	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+
+	.vidioc_s_parm			= vidioc_venc_s_parm,
+	.vidioc_g_parm			= vidioc_venc_g_parm,
+	.vidioc_s_fmt_vid_cap_mplane	= vidioc_venc_s_fmt_cap,
+	.vidioc_s_fmt_vid_out_mplane	= vidioc_venc_s_fmt_out,
+
+	.vidioc_g_fmt_vid_cap_mplane	= vidioc_venc_g_fmt,
+	.vidioc_g_fmt_vid_out_mplane	= vidioc_venc_g_fmt,
+
+	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,
+	.vidioc_prepare_buf		= v4l2_m2m_ioctl_prepare_buf,
+};
+
+static int vb2ops_venc_queue_setup(struct vb2_queue *vq,
+				   unsigned int *nbuffers,
+				   unsigned int *nplanes,
+				   unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vq);
+	struct mtk_q_data *q_data;
+	unsigned int i;
+
+	q_data = mtk_venc_get_q_data(ctx, vq->type);
+
+	if (q_data == NULL)
+		return -EINVAL;
+
+	if (*nplanes) {
+		for (i = 0; i < *nplanes; i++) {
+			if (sizes[i] < q_data->sizeimage[i])
+				return -EINVAL;
+			alloc_ctxs[i] = ctx->dev->alloc_ctx;
+		}
+	} else {
+		*nplanes = q_data->fmt->num_planes;
+		for (i = 0; i < *nplanes; i++) {
+			sizes[i] = q_data->sizeimage[i];
+			alloc_ctxs[i] = ctx->dev->alloc_ctx;
+		}
+	}
+
+	return 0;
+}
+
+static int vb2ops_venc_buf_prepare(struct vb2_buffer *vb)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct mtk_q_data *q_data;
+	int i;
+
+	q_data = mtk_venc_get_q_data(ctx, vb->vb2_queue->type);
+
+	for (i = 0; i < q_data->fmt->num_planes; i++) {
+		if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) {
+			mtk_v4l2_err("data will not fit into plane %d (%lu < %d)",
+				i, vb2_plane_size(vb, i),
+				q_data->sizeimage[i]);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static void vb2ops_venc_buf_queue(struct vb2_buffer *vb)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vb2_v4l2 =
+			container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
+
+	struct mtk_video_enc_buf *mtk_buf =
+			container_of(vb2_v4l2, struct mtk_video_enc_buf, vb);
+
+	if ((vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) &&
+	    (ctx->param_change != MTK_ENCODE_PARAM_NONE)) {
+		mtk_v4l2_debug(1, "[%d] Before id=%d encode parameter change %x",
+			       ctx->id,
+			       mtk_buf->vb.vb2_buf.index,
+			       ctx->param_change);
+		mtk_buf->param_change = ctx->param_change;
+		mtk_buf->enc_params = ctx->enc_params;
+		ctx->param_change = MTK_ENCODE_PARAM_NONE;
+	}
+
+	v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb));
+}
+
+static int vb2ops_venc_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q);
+	struct venc_enc_param param;
+	int ret;
+	int i;
+
+	/* Once state turn into MTK_STATE_ABORT, we need stop_streaming
+	  * to clear it
+	  */
+	if ((ctx->state == MTK_STATE_ABORT) || (ctx->state == MTK_STATE_FREE)) {
+		ret = -EIO;
+		goto err_set_param;
+	}
+
+	/* Do the initialization when both start_streaming have been called */
+	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+		if (!vb2_start_streaming_called(&ctx->m2m_ctx->cap_q_ctx.q))
+			return 0;
+	} else {
+		if (!vb2_start_streaming_called(&ctx->m2m_ctx->out_q_ctx.q))
+			return 0;
+	}
+
+	mtk_venc_set_param(ctx, &param);
+	ret = venc_if_set_param(ctx, VENC_SET_PARAM_ENC, &param);
+	if (ret) {
+		mtk_v4l2_err("venc_if_set_param failed=%d", ret);
+		ctx->state = MTK_STATE_ABORT;
+		goto err_set_param;
+	}
+	ctx->param_change = MTK_ENCODE_PARAM_NONE;
+
+	if ((ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_H264) &&
+	    (ctx->enc_params.seq_hdr_mode !=
+				V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE)) {
+		ret = venc_if_set_param(ctx,
+					VENC_SET_PARAM_PREPEND_HEADER,
+					NULL);
+		if (ret) {
+			mtk_v4l2_err("venc_if_set_param failed=%d", ret);
+			ctx->state = MTK_STATE_ABORT;
+			goto err_set_param;
+		}
+		ctx->state = MTK_STATE_HEADER;
+	}
+
+	return 0;
+
+err_set_param:
+	for (i = 0; i < q->num_buffers; ++i) {
+		if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
+			mtk_v4l2_debug(0, "[%d] id=%d, type=%d, %d -> VB2_BUF_STATE_QUEUED",
+					ctx->id, i, q->type,
+					(int)q->bufs[i]->state);
+			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(q->bufs[i]),
+					VB2_BUF_STATE_QUEUED);
+		}
+	}
+
+	return ret;
+}
+
+static void vb2ops_venc_stop_streaming(struct vb2_queue *q)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q);
+	struct vb2_buffer *src_buf, *dst_buf;
+	int ret;
+
+	mtk_v4l2_debug(2, "[%d]-> type=%d", ctx->id, q->type);
+
+	if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) {
+			dst_buf->planes[0].bytesused = 0;
+			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
+					VB2_BUF_STATE_ERROR);
+		}
+	} else {
+		while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
+			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+					VB2_BUF_STATE_ERROR);
+	}
+
+	if ((q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+	     vb2_is_streaming(&ctx->m2m_ctx->out_q_ctx.q)) ||
+	    (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+	     vb2_is_streaming(&ctx->m2m_ctx->cap_q_ctx.q))) {
+		mtk_v4l2_debug(1, "[%d]-> q type %d out=%d cap=%d",
+			       ctx->id, q->type,
+			       vb2_is_streaming(&ctx->m2m_ctx->out_q_ctx.q),
+			       vb2_is_streaming(&ctx->m2m_ctx->cap_q_ctx.q));
+		return;
+	}
+
+	/* Release the encoder if both streams are stopped. */
+	ret = venc_if_deinit(ctx);
+	if (ret)
+		mtk_v4l2_err("venc_if_deinit failed=%d", ret);
+
+	ctx->state = MTK_STATE_FREE;
+}
+
+static struct vb2_ops mtk_venc_vb2_ops = {
+	.queue_setup		= vb2ops_venc_queue_setup,
+	.buf_prepare		= vb2ops_venc_buf_prepare,
+	.buf_queue		= vb2ops_venc_buf_queue,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
+	.start_streaming	= vb2ops_venc_start_streaming,
+	.stop_streaming		= vb2ops_venc_stop_streaming,
+};
+
+static int mtk_venc_encode_header(void *priv)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+	int ret;
+	struct vb2_buffer *dst_buf;
+	struct mtk_vcodec_mem bs_buf;
+	struct venc_done_result enc_result;
+
+	dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+	if (!dst_buf) {
+		mtk_v4l2_debug(1, "No dst buffer");
+		return -EINVAL;
+	}
+
+	bs_buf.va = vb2_plane_vaddr(dst_buf, 0);
+	bs_buf.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+	bs_buf.size = (size_t)dst_buf->planes[0].length;
+
+	mtk_v4l2_debug(1,
+			"[%d] buf id=%d va=0x%p dma_addr=0x%llx size=%zu",
+			ctx->id,
+			dst_buf->index, bs_buf.va,
+			(u64)bs_buf.dma_addr,
+			bs_buf.size);
+
+	ret = venc_if_encode(ctx,
+			VENC_START_OPT_ENCODE_SEQUENCE_HEADER,
+			NULL, &bs_buf, &enc_result);
+
+	if (ret) {
+		dst_buf->planes[0].bytesused = 0;
+		ctx->state = MTK_STATE_ABORT;
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
+				  VB2_BUF_STATE_ERROR);
+		mtk_v4l2_err("venc_if_encode failed=%d", ret);
+		return -EINVAL;
+	}
+
+	ctx->state = MTK_STATE_HEADER;
+	dst_buf->planes[0].bytesused = enc_result.bs_size;
+	v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf), VB2_BUF_STATE_DONE);
+
+	return 0;
+}
+
+static int mtk_venc_param_change(struct mtk_vcodec_ctx *ctx)
+{
+	struct venc_enc_param enc_prm;
+	struct vb2_buffer *vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+	struct vb2_v4l2_buffer *vb2_v4l2 =
+			container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
+	struct mtk_video_enc_buf *mtk_buf =
+			container_of(vb2_v4l2, struct mtk_video_enc_buf, vb);
+
+	int ret = 0;
+
+	memset(&enc_prm, 0, sizeof(enc_prm));
+	if (mtk_buf->param_change == MTK_ENCODE_PARAM_NONE)
+		return 0;
+
+	if (mtk_buf->param_change & MTK_ENCODE_PARAM_BITRATE) {
+		enc_prm.bitrate = mtk_buf->enc_params.bitrate;
+		mtk_v4l2_debug(1, "[%d] id=%d, change param br=%d",
+				ctx->id,
+				mtk_buf->vb.vb2_buf.index,
+				enc_prm.bitrate);
+		ret |= venc_if_set_param(ctx,
+					 VENC_SET_PARAM_ADJUST_BITRATE,
+					 &enc_prm);
+	}
+	if (!ret && mtk_buf->param_change & MTK_ENCODE_PARAM_FRAMERATE) {
+		enc_prm.frm_rate = mtk_buf->enc_params.framerate_num /
+				   mtk_buf->enc_params.framerate_denom;
+		mtk_v4l2_debug(1, "[%d] id=%d, change param fr=%d",
+			       ctx->id,
+			       mtk_buf->vb.vb2_buf.index,
+			       enc_prm.frm_rate);
+		ret |= venc_if_set_param(ctx,
+					 VENC_SET_PARAM_ADJUST_FRAMERATE,
+					 &enc_prm);
+	}
+	if (!ret && mtk_buf->param_change & MTK_ENCODE_PARAM_GOP_SIZE) {
+		enc_prm.gop_size = mtk_buf->enc_params.gop_size;
+		mtk_v4l2_debug(1, "change param intra period=%d",
+			       enc_prm.gop_size);
+		ret |= venc_if_set_param(ctx,
+					 VENC_SET_PARAM_GOP_SIZE,
+					 &enc_prm);
+	}
+	if (!ret && mtk_buf->param_change & MTK_ENCODE_PARAM_FORCE_INTRA) {
+		mtk_v4l2_debug(1, "[%d] id=%d, change param force I=%d",
+				ctx->id,
+				mtk_buf->vb.vb2_buf.index,
+				mtk_buf->enc_params.force_intra);
+		if (mtk_buf->enc_params.force_intra)
+			ret |= venc_if_set_param(ctx,
+						 VENC_SET_PARAM_FORCE_INTRA,
+						 NULL);
+	}
+
+	mtk_buf->param_change = MTK_ENCODE_PARAM_NONE;
+
+	if (ret) {
+		ctx->state = MTK_STATE_ABORT;
+		mtk_v4l2_err("venc_if_set_param %d failed=%d",
+				mtk_buf->param_change, ret);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * v4l2_m2m_streamoff() holds dev_mutex and waits mtk_venc_worker()
+ * to call v4l2_m2m_job_finish().
+ * If mtk_venc_worker() tries to acquire dev_mutex, it will deadlock.
+ * So this function must not try to acquire dev->dev_mutex.
+ * This means v4l2 ioctls and mtk_venc_worker() can run at the same time.
+ * mtk_venc_worker() should be carefully implemented to avoid bugs.
+ */
+static void mtk_venc_worker(struct work_struct *work)
+{
+	struct mtk_vcodec_ctx *ctx = container_of(work, struct mtk_vcodec_ctx,
+				    encode_work);
+	struct vb2_buffer *src_buf, *dst_buf;
+	struct venc_frm_buf frm_buf;
+	struct mtk_vcodec_mem bs_buf;
+	struct venc_done_result enc_result;
+	int ret, i;
+	struct vb2_v4l2_buffer *vb2_v4l2;
+
+	/* check dst_buf, dst_buf may be removed in device_run
+	 * to stored encdoe header so we need check dst_buf and
+	 * call job_finish here to prevent recursion
+	 */
+	dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+	if (!dst_buf) {
+		v4l2_m2m_job_finish(ctx->dev->m2m_dev_enc, ctx->m2m_ctx);
+		return;
+	}
+
+	src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+	memset(&frm_buf, 0, sizeof(frm_buf));
+	for (i = 0; i < src_buf->num_planes ; i++) {
+		frm_buf.fb_addr[i].va = vb2_plane_vaddr(src_buf, i);
+		frm_buf.fb_addr[i].dma_addr =
+				vb2_dma_contig_plane_dma_addr(src_buf, i);
+		frm_buf.fb_addr[i].size =
+				(size_t)src_buf->planes[i].length;
+	}
+	bs_buf.va = vb2_plane_vaddr(dst_buf, 0);
+	bs_buf.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+	bs_buf.size = (size_t)dst_buf->planes[0].length;
+
+	mtk_v4l2_debug(2,
+			"Framebuf VA=%p PA=%llx Size=0x%lx;VA=%p PA=0x%llx Size=0x%lx;VA=%p PA=0x%llx Size=%zu",
+			frm_buf.fb_addr[0].va,
+			(u64)frm_buf.fb_addr[0].dma_addr,
+			frm_buf.fb_addr[0].size,
+			frm_buf.fb_addr[1].va,
+			(u64)frm_buf.fb_addr[1].dma_addr,
+			frm_buf.fb_addr[1].size,
+			frm_buf.fb_addr[2].va,
+			(u64)frm_buf.fb_addr[2].dma_addr,
+			frm_buf.fb_addr[2].size);
+
+	ret = venc_if_encode(ctx, VENC_START_OPT_ENCODE_FRAME,
+			     &frm_buf, &bs_buf, &enc_result);
+
+	vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf);
+	if (enc_result.is_key_frm)
+		vb2_v4l2->flags |= V4L2_BUF_FLAG_KEYFRAME;
+
+	if (ret) {
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+				  VB2_BUF_STATE_ERROR);
+		dst_buf->planes[0].bytesused = 0;
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
+				  VB2_BUF_STATE_ERROR);
+		mtk_v4l2_err("venc_if_encode failed=%d", ret);
+	} else {
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+				  VB2_BUF_STATE_DONE);
+		dst_buf->planes[0].bytesused = enc_result.bs_size;
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
+				  VB2_BUF_STATE_DONE);
+		mtk_v4l2_debug(2, "venc_if_encode bs size=%d",
+				 enc_result.bs_size);
+	}
+
+	v4l2_m2m_job_finish(ctx->dev->m2m_dev_enc, ctx->m2m_ctx);
+
+	mtk_v4l2_debug(1, "<=== src_buf[%d] dst_buf[%d] venc_if_encode ret=%d Size=%u===>",
+			src_buf->index, dst_buf->index, ret,
+			enc_result.bs_size);
+}
+
+static void m2mops_venc_device_run(void *priv)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+
+	if ((ctx->q_data[MTK_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_H264) &&
+	    (ctx->state != MTK_STATE_HEADER)) {
+		/* encode h264 sps/pps header */
+		mtk_venc_encode_header(ctx);
+		queue_work(ctx->dev->encode_workqueue, &ctx->encode_work);
+		return;
+	}
+
+	mtk_venc_param_change(ctx);
+	queue_work(ctx->dev->encode_workqueue, &ctx->encode_work);
+}
+
+static int m2mops_venc_job_ready(void *m2m_priv)
+{
+	struct mtk_vcodec_ctx *ctx = m2m_priv;
+
+	if (ctx->state == MTK_STATE_ABORT || ctx->state == MTK_STATE_FREE) {
+		mtk_v4l2_debug(3, "[%d]Not ready: state=0x%x.",
+			       ctx->id, ctx->state);
+		return 0;
+	}
+
+	return 1;
+}
+
+static void m2mops_venc_job_abort(void *priv)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+
+	ctx->state = MTK_STATE_ABORT;
+}
+
+static void m2mops_venc_lock(void *m2m_priv)
+{
+	struct mtk_vcodec_ctx *ctx = m2m_priv;
+
+	mutex_lock(&ctx->dev->dev_mutex);
+}
+
+static void m2mops_venc_unlock(void *m2m_priv)
+{
+	struct mtk_vcodec_ctx *ctx = m2m_priv;
+
+	mutex_unlock(&ctx->dev->dev_mutex);
+}
+
+const struct v4l2_m2m_ops mtk_venc_m2m_ops = {
+	.device_run	= m2mops_venc_device_run,
+	.job_ready	= m2mops_venc_job_ready,
+	.job_abort	= m2mops_venc_job_abort,
+	.lock		= m2mops_venc_lock,
+	.unlock		= m2mops_venc_unlock,
+};
+
+void mtk_vcodec_enc_set_default_params(struct mtk_vcodec_ctx *ctx)
+{
+	struct mtk_q_data *q_data;
+
+	ctx->m2m_ctx->q_lock = &ctx->dev->dev_mutex;
+	ctx->fh.m2m_ctx = ctx->m2m_ctx;
+	ctx->fh.ctrl_handler = &ctx->ctrl_hdl;
+	INIT_WORK(&ctx->encode_work, mtk_venc_worker);
+
+	ctx->colorspace = V4L2_COLORSPACE_REC709;
+	ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
+	ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+
+	q_data = &ctx->q_data[MTK_Q_DATA_SRC];
+	memset(q_data, 0, sizeof(struct mtk_q_data));
+	q_data->visible_width = DFT_CFG_WIDTH;
+	q_data->visible_height = DFT_CFG_HEIGHT;
+	q_data->coded_width = DFT_CFG_WIDTH;
+	q_data->coded_height = DFT_CFG_HEIGHT;
+	q_data->field = V4L2_FIELD_NONE;
+
+	q_data->fmt = &mtk_video_formats[OUT_FMT_IDX];
+
+	v4l_bound_align_image(&q_data->coded_width,
+				MTK_VENC_MIN_W,
+				MTK_VENC_MAX_W, 4,
+				&q_data->coded_height,
+				MTK_VENC_MIN_H,
+				MTK_VENC_MAX_H, 5, 6);
+
+	if (q_data->coded_width < DFT_CFG_WIDTH &&
+		(q_data->coded_width + 16) <= MTK_VENC_MAX_W)
+		q_data->coded_width += 16;
+	if (q_data->coded_height < DFT_CFG_HEIGHT &&
+		(q_data->coded_height + 32) <= MTK_VENC_MAX_H)
+		q_data->coded_height += 32;
+
+	q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height;
+	q_data->bytesperline[0] = q_data->coded_width;
+	q_data->sizeimage[1] = q_data->sizeimage[0] / 2;
+	q_data->bytesperline[1] = q_data->coded_width;
+
+	q_data = &ctx->q_data[MTK_Q_DATA_DST];
+	memset(q_data, 0, sizeof(struct mtk_q_data));
+	q_data->coded_width = DFT_CFG_WIDTH;
+	q_data->coded_height = DFT_CFG_HEIGHT;
+	q_data->fmt = &mtk_video_formats[CAP_FMT_IDX];
+	q_data->field = V4L2_FIELD_NONE;
+	ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
+		DFT_CFG_WIDTH * DFT_CFG_HEIGHT;
+	ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] = 0;
+
+}
+
+int mtk_vcodec_enc_ctrls_setup(struct mtk_vcodec_ctx *ctx)
+{
+	const struct v4l2_ctrl_ops *ops = &mtk_vcodec_enc_ctrl_ops;
+	struct v4l2_ctrl_handler *handler = &ctx->ctrl_hdl;
+
+	v4l2_ctrl_handler_init(handler, MTK_MAX_CTRLS_HINT);
+
+	v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_BITRATE,
+			1, 4000000, 1, 4000000);
+	v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_B_FRAMES,
+			0, 2, 1, 0);
+	v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE,
+			0, 1, 1, 1);
+	v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
+			0, 51, 1, 51);
+	v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
+			0, 65535, 1, 0);
+	v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+			0, 65535, 1, 0);
+	v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE,
+			0, 1, 1, 0);
+	v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
+			0, 0, 0, 0);
+	v4l2_ctrl_new_std_menu(handler, ops,
+			V4L2_CID_MPEG_VIDEO_HEADER_MODE,
+			V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+			0, V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE);
+	v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+			V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+			0, V4L2_MPEG_VIDEO_H264_PROFILE_MAIN);
+	v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+			V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
+			0, V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
+	if (handler->error) {
+		mtk_v4l2_err("Init control handler fail %d",
+				handler->error);
+		return handler->error;
+	}
+
+	v4l2_ctrl_handler_setup(&ctx->ctrl_hdl);
+
+	return 0;
+}
+
+int mtk_vcodec_enc_queue_init(void *priv, struct vb2_queue *src_vq,
+			      struct vb2_queue *dst_vq)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+	int ret;
+
+	/* Note: VB2_USERPTR works with dma-contig because mt8173
+	 * support iommu
+	 * https://patchwork.kernel.org/patch/8335461/
+	 * https://patchwork.kernel.org/patch/7596181/
+	 */
+	src_vq->type		= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes	= VB2_DMABUF | VB2_MMAP | VB2_USERPTR;
+	src_vq->drv_priv	= ctx;
+	src_vq->buf_struct_size = sizeof(struct mtk_video_enc_buf);
+	src_vq->ops		= &mtk_venc_vb2_ops;
+	src_vq->mem_ops		= &vb2_dma_contig_memops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock		= &ctx->dev->dev_mutex;
+
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	dst_vq->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes	= VB2_DMABUF | VB2_MMAP | VB2_USERPTR;
+	dst_vq->drv_priv	= ctx;
+	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	dst_vq->ops		= &mtk_venc_vb2_ops;
+	dst_vq->mem_ops		= &vb2_dma_contig_memops;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock		= &ctx->dev->dev_mutex;
+
+	return vb2_queue_init(dst_vq);
+}
+
+int mtk_venc_unlock(struct mtk_vcodec_ctx *ctx)
+{
+	struct mtk_vcodec_dev *dev = ctx->dev;
+
+	mutex_unlock(&dev->enc_mutex);
+	return 0;
+}
+
+int mtk_venc_lock(struct mtk_vcodec_ctx *ctx)
+{
+	struct mtk_vcodec_dev *dev = ctx->dev;
+
+	mutex_lock(&dev->enc_mutex);
+	return 0;
+}
+
+void mtk_vcodec_enc_release(struct mtk_vcodec_ctx *ctx)
+{
+	venc_if_deinit(ctx);
+}
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
new file mode 100644
index 0000000..d7a154a
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
@@ -0,0 +1,58 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen at mediatek.com>
+*         Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MTK_VCODEC_ENC_H_
+#define _MTK_VCODEC_ENC_H_
+
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
+
+#define MTK_VENC_IRQ_STATUS_SPS	0x1
+#define MTK_VENC_IRQ_STATUS_PPS	0x2
+#define MTK_VENC_IRQ_STATUS_FRM	0x4
+#define MTK_VENC_IRQ_STATUS_DRAM	0x8
+#define MTK_VENC_IRQ_STATUS_PAUSE	0x10
+#define MTK_VENC_IRQ_STATUS_SWITCH	0x20
+
+#define MTK_VENC_IRQ_STATUS_OFFSET	0x05C
+#define MTK_VENC_IRQ_ACK_OFFSET	0x060
+
+/**
+ * struct mtk_video_enc_buf - Private data related to each VB2 buffer.
+ * @vb: Pointer to related VB2 buffer.
+ * @list:	list that buffer link to
+ * @param_change: Types of encode parameter change before encoding this
+ *				buffer
+ * @enc_params: Encode parameters changed before encode this buffer
+ */
+struct mtk_video_enc_buf {
+	struct vb2_v4l2_buffer vb;
+	struct list_head list;
+	u32 param_change;
+	struct mtk_enc_params enc_params;
+};
+
+extern const struct v4l2_ioctl_ops mtk_venc_ioctl_ops;
+extern const struct v4l2_m2m_ops mtk_venc_m2m_ops;
+
+int mtk_venc_unlock(struct mtk_vcodec_ctx *ctx);
+int mtk_venc_lock(struct mtk_vcodec_ctx *ctx);
+int mtk_vcodec_enc_queue_init(void *priv, struct vb2_queue *src_vq,
+			      struct vb2_queue *dst_vq);
+void mtk_vcodec_enc_release(struct mtk_vcodec_ctx *ctx);
+int mtk_vcodec_enc_ctrls_setup(struct mtk_vcodec_ctx *ctx);
+void mtk_vcodec_enc_set_default_params(struct mtk_vcodec_ctx *ctx);
+
+#endif /* _MTK_VCODEC_ENC_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
new file mode 100644
index 0000000..06105e9
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -0,0 +1,454 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen at mediatek.com>
+*	Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+#include <linux/pm_runtime.h>
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_enc.h"
+#include "mtk_vcodec_enc_pm.h"
+#include "mtk_vcodec_intr.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
+
+module_param(mtk_v4l2_dbg_level, int, S_IRUGO | S_IWUSR);
+module_param(mtk_vcodec_dbg, bool, S_IRUGO | S_IWUSR);
+
+/* Wake up context wait_queue */
+static void wake_up_ctx(struct mtk_vcodec_ctx *ctx, unsigned int reason)
+{
+	ctx->int_cond = 1;
+	ctx->int_type = reason;
+	wake_up_interruptible(&ctx->queue);
+}
+
+static void clean_irq_status(unsigned int irq_status, void __iomem *addr)
+{
+	if (irq_status & MTK_VENC_IRQ_STATUS_PAUSE)
+		writel(MTK_VENC_IRQ_STATUS_PAUSE, addr);
+
+	if (irq_status & MTK_VENC_IRQ_STATUS_SWITCH)
+		writel(MTK_VENC_IRQ_STATUS_SWITCH, addr);
+
+	if (irq_status & MTK_VENC_IRQ_STATUS_DRAM)
+		writel(MTK_VENC_IRQ_STATUS_DRAM, addr);
+
+	if (irq_status & MTK_VENC_IRQ_STATUS_SPS)
+		writel(MTK_VENC_IRQ_STATUS_SPS, addr);
+
+	if (irq_status & MTK_VENC_IRQ_STATUS_PPS)
+		writel(MTK_VENC_IRQ_STATUS_PPS, addr);
+
+	if (irq_status & MTK_VENC_IRQ_STATUS_FRM)
+		writel(MTK_VENC_IRQ_STATUS_FRM, addr);
+
+}
+static irqreturn_t mtk_vcodec_enc_irq_handler(int irq, void *priv)
+{
+	struct mtk_vcodec_dev *dev = priv;
+	struct mtk_vcodec_ctx *ctx;
+	unsigned long flags;
+	void __iomem *addr;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+	ctx = dev->curr_ctx;
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+
+	mtk_v4l2_debug(1, "id=%d", ctx->id);
+	addr = dev->reg_base[VENC_SYS] + MTK_VENC_IRQ_ACK_OFFSET;
+
+	ctx->irq_status = readl(dev->reg_base[VENC_SYS] +
+				(MTK_VENC_IRQ_STATUS_OFFSET));
+
+	clean_irq_status(ctx->irq_status, addr);
+
+	wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mtk_vcodec_enc_lt_irq_handler(int irq, void *priv)
+{
+	struct mtk_vcodec_dev *dev = priv;
+	struct mtk_vcodec_ctx *ctx;
+	unsigned long flags;
+	void __iomem *addr;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+	ctx = dev->curr_ctx;
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+
+	mtk_v4l2_debug(1, "id=%d", ctx->id);
+	ctx->irq_status = readl(dev->reg_base[VENC_LT_SYS] +
+				(MTK_VENC_IRQ_STATUS_OFFSET));
+
+	addr = dev->reg_base[VENC_LT_SYS] + MTK_VENC_IRQ_ACK_OFFSET;
+
+	clean_irq_status(ctx->irq_status, addr);
+
+	wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED);
+	return IRQ_HANDLED;
+}
+
+static void mtk_vcodec_enc_reset_handler(void *priv)
+{
+	struct mtk_vcodec_dev *dev = priv;
+	struct mtk_vcodec_ctx *ctx;
+
+	mtk_v4l2_debug(0, "Watchdog timeout!!");
+
+	mutex_lock(&dev->dev_mutex);
+	list_for_each_entry(ctx, &dev->ctx_list, list) {
+		ctx->state = MTK_STATE_ABORT;
+		mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ABORT",
+				ctx->id);
+	}
+	mutex_unlock(&dev->dev_mutex);
+}
+
+static int fops_vcodec_open(struct file *file)
+{
+	struct mtk_vcodec_dev *dev = video_drvdata(file);
+	struct mtk_vcodec_ctx *ctx = NULL;
+	int ret = 0;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	mutex_lock(&dev->dev_mutex);
+	/*
+	 * Use simple counter to uniquely identify this context. Only
+	 * used for logging.
+	 */
+	ctx->id = dev->id_counter++;
+	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	file->private_data = &ctx->fh;
+	v4l2_fh_add(&ctx->fh);
+	INIT_LIST_HEAD(&ctx->list);
+	ctx->dev = dev;
+	init_waitqueue_head(&ctx->queue);
+
+	ctx->type = MTK_INST_ENCODER;
+	ret = mtk_vcodec_enc_ctrls_setup(ctx);
+	if (ret) {
+		mtk_v4l2_err("Failed to setup controls() (%d)",
+				ret);
+		goto err_ctrls_setup;
+	}
+	ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_enc, ctx,
+				&mtk_vcodec_enc_queue_init);
+	if (IS_ERR((__force void *)ctx->m2m_ctx)) {
+		ret = PTR_ERR((__force void *)ctx->m2m_ctx);
+		mtk_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)",
+				ret);
+		goto err_m2m_ctx_init;
+	}
+	mtk_vcodec_enc_set_default_params(ctx);
+
+	if (v4l2_fh_is_singular(&ctx->fh)) {
+		/*
+		 * vpu_load_firmware checks if it was loaded already and
+		 * does nothing in that case
+		 */
+		ret = vpu_load_firmware(dev->vpu_plat_dev);
+		if (ret < 0) {
+			/*
+			 * Return 0 if downloading firmware successfully,
+			 * otherwise it is failed
+			 */
+			mtk_v4l2_err("vpu_load_firmware failed!");
+			goto err_load_fw;
+		}
+
+		dev->enc_capability =
+			vpu_get_venc_hw_capa(dev->vpu_plat_dev);
+		mtk_v4l2_debug(0, "encoder capability %x", dev->enc_capability);
+	}
+
+	mtk_v4l2_debug(2, "Create instance [%d]@%p m2m_ctx=%p ",
+			ctx->id, ctx, ctx->m2m_ctx);
+
+	dev->num_instances++;
+	list_add(&ctx->list, &dev->ctx_list);
+
+	mutex_unlock(&dev->dev_mutex);
+	mtk_v4l2_debug(0, "%s encoder [%d]", dev_name(&dev->plat_dev->dev),
+			ctx->id);
+	return ret;
+
+	/* Deinit when failure occurred */
+err_load_fw:
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+err_m2m_ctx_init:
+	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+err_ctrls_setup:
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	kfree(ctx);
+	mutex_unlock(&dev->dev_mutex);
+
+	return ret;
+}
+
+static int fops_vcodec_release(struct file *file)
+{
+	struct mtk_vcodec_dev *dev = video_drvdata(file);
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(file->private_data);
+
+	mtk_v4l2_debug(1, "[%d] encoder", ctx->id);
+	mutex_lock(&dev->dev_mutex);
+
+	mtk_vcodec_enc_release(ctx);
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+
+	list_del_init(&ctx->list);
+	dev->num_instances--;
+	kfree(ctx);
+	mutex_unlock(&dev->dev_mutex);
+	return 0;
+}
+
+static const struct v4l2_file_operations mtk_vcodec_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fops_vcodec_open,
+	.release	= fops_vcodec_release,
+	.poll		= v4l2_m2m_fop_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= v4l2_m2m_fop_mmap,
+};
+
+static int mtk_vcodec_probe(struct platform_device *pdev)
+{
+	struct mtk_vcodec_dev *dev;
+	struct video_device *vfd_enc;
+	struct resource *res;
+	int i, j, ret;
+	DEFINE_DMA_ATTRS(attrs);
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&dev->ctx_list);
+	dev->plat_dev = pdev;
+
+	dev->vpu_plat_dev = vpu_get_plat_device(dev->plat_dev);
+	if (dev->vpu_plat_dev == NULL) {
+		mtk_v4l2_err("[VPU] vpu device in not ready");
+		return -EPROBE_DEFER;
+	}
+
+	vpu_wdt_reg_handler(dev->vpu_plat_dev, mtk_vcodec_enc_reset_handler,
+				dev, VPU_RST_ENC);
+
+	ret = mtk_vcodec_init_enc_pm(dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to get mt vcodec clock source!");
+		return ret;
+	}
+
+	for (i = VENC_SYS, j = 0; i < NUM_MAX_VCODEC_REG_BASE; i++, j++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, j);
+		if (res == NULL) {
+			dev_err(&pdev->dev, "get memory resource failed.");
+			ret = -ENXIO;
+			goto err_res;
+		}
+		dev->reg_base[i] = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR((__force void *)dev->reg_base[i])) {
+			dev_err(&pdev->dev,
+				"devm_ioremap_resource %d failed.", i);
+			ret = PTR_ERR((__force void *)dev->reg_base[i]);
+			goto err_res;
+		}
+		mtk_v4l2_debug(2, "reg[%d] base=0x%p", i, dev->reg_base[i]);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to get irq resource");
+		ret = -ENOENT;
+		goto err_res;
+	}
+
+	dev->enc_irq = platform_get_irq(pdev, 0);
+	ret = devm_request_irq(&pdev->dev, dev->enc_irq,
+			       mtk_vcodec_enc_irq_handler,
+			       0, pdev->name, dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to install dev->enc_irq %d (%d)",
+			dev->enc_irq,
+			ret);
+		ret = -EINVAL;
+		goto err_res;
+	}
+
+	dev->enc_lt_irq = platform_get_irq(pdev, 1);
+	ret = devm_request_irq(&pdev->dev,
+			       dev->enc_lt_irq, mtk_vcodec_enc_lt_irq_handler,
+			       0, pdev->name, dev);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Failed to install dev->enc_lt_irq %d (%d)",
+			dev->enc_lt_irq, ret);
+		ret = -EINVAL;
+		goto err_res;
+	}
+
+	disable_irq(dev->enc_irq);
+	disable_irq(dev->enc_lt_irq); /* VENC_LT */
+	mutex_init(&dev->enc_mutex);
+	mutex_init(&dev->dev_mutex);
+	spin_lock_init(&dev->irqlock);
+
+	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
+		 "[MTK_V4L2_VENC]");
+
+	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+	if (ret) {
+		mtk_v4l2_err("v4l2_device_register err=%d", ret);
+		goto err_res;
+	}
+
+	init_waitqueue_head(&dev->queue);
+
+	/* allocate video device for encoder and register it */
+	vfd_enc = video_device_alloc();
+	if (!vfd_enc) {
+		mtk_v4l2_err("Failed to allocate video device");
+		ret = -ENOMEM;
+		goto err_enc_alloc;
+	}
+	vfd_enc->fops           = &mtk_vcodec_fops;
+	vfd_enc->ioctl_ops      = &mtk_venc_ioctl_ops;
+	vfd_enc->release        = video_device_release;
+	vfd_enc->lock           = &dev->dev_mutex;
+	vfd_enc->v4l2_dev       = &dev->v4l2_dev;
+	vfd_enc->vfl_dir        = VFL_DIR_M2M;
+	vfd_enc->device_caps	= V4L2_CAP_VIDEO_M2M_MPLANE |
+					V4L2_CAP_STREAMING;
+
+	snprintf(vfd_enc->name, sizeof(vfd_enc->name), "%s",
+		 MTK_VCODEC_ENC_NAME);
+	video_set_drvdata(vfd_enc, dev);
+	dev->vfd_enc = vfd_enc;
+	platform_set_drvdata(pdev, dev);
+
+	dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	if (IS_ERR((__force void *)dev->alloc_ctx)) {
+		mtk_v4l2_err("Failed to alloc vb2 dma context 0");
+		ret = PTR_ERR((__force void *)dev->alloc_ctx);
+		dev->alloc_ctx = NULL;
+		goto err_vb2_ctx_init;
+	}
+
+	dev->m2m_dev_enc = v4l2_m2m_init(&mtk_venc_m2m_ops);
+	if (IS_ERR((__force void *)dev->m2m_dev_enc)) {
+		mtk_v4l2_err("Failed to init mem2mem enc device");
+		ret = PTR_ERR((__force void *)dev->m2m_dev_enc);
+		goto err_enc_mem_init;
+	}
+
+	dev->encode_workqueue =
+			alloc_ordered_workqueue(MTK_VCODEC_ENC_NAME,
+						WQ_MEM_RECLAIM |
+						WQ_FREEZABLE);
+	if (!dev->encode_workqueue) {
+		mtk_v4l2_err("Failed to create encode workqueue");
+		ret = -EINVAL;
+		goto err_event_workq;
+	}
+
+	ret = video_register_device(vfd_enc, VFL_TYPE_GRABBER, 1);
+	if (ret) {
+		mtk_v4l2_err("Failed to register video device");
+		goto err_enc_reg;
+	}
+
+	/* Avoid the iommu eat big hunks */
+	dma_set_attr(DMA_ATTR_ALLOC_SINGLE_PAGES, &attrs);
+
+	mtk_v4l2_debug(0, "encoder registered as /dev/video%d",
+			vfd_enc->num);
+
+	return 0;
+
+err_enc_reg:
+	destroy_workqueue(dev->encode_workqueue);
+err_event_workq:
+	v4l2_m2m_release(dev->m2m_dev_enc);
+err_enc_mem_init:
+	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+err_vb2_ctx_init:
+	video_unregister_device(vfd_enc);
+err_enc_alloc:
+	v4l2_device_unregister(&dev->v4l2_dev);
+err_res:
+	mtk_vcodec_release_enc_pm(dev);
+	return ret;
+}
+
+static const struct of_device_id mtk_vcodec_enc_match[] = {
+	{.compatible = "mediatek,mt8173-vcodec-enc",},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_vcodec_enc_match);
+
+static int mtk_vcodec_enc_remove(struct platform_device *pdev)
+{
+	struct mtk_vcodec_dev *dev = platform_get_drvdata(pdev);
+
+	mtk_v4l2_debug_enter();
+	flush_workqueue(dev->encode_workqueue);
+	destroy_workqueue(dev->encode_workqueue);
+	if (dev->m2m_dev_enc)
+		v4l2_m2m_release(dev->m2m_dev_enc);
+	if (dev->alloc_ctx)
+		vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+
+	if (dev->vfd_enc)
+		video_unregister_device(dev->vfd_enc);
+
+	v4l2_device_unregister(&dev->v4l2_dev);
+	mtk_vcodec_release_enc_pm(dev);
+	return 0;
+}
+
+static struct platform_driver mtk_vcodec_enc_driver = {
+	.probe	= mtk_vcodec_probe,
+	.remove	= mtk_vcodec_enc_remove,
+	.driver	= {
+		.name	= MTK_VCODEC_ENC_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = mtk_vcodec_enc_match,
+	},
+};
+
+module_platform_driver(mtk_vcodec_enc_driver);
+
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Mediatek video codec V4L2 encoder driver");
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
new file mode 100644
index 0000000..2379e97
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
@@ -0,0 +1,137 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/clk.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <soc/mediatek/smi.h>
+
+#include "mtk_vcodec_enc_pm.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
+
+
+int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *mtkdev)
+{
+	struct device_node *node;
+	struct platform_device *pdev;
+	struct device *dev;
+	struct mtk_vcodec_pm *pm;
+	int ret = 0;
+
+	pdev = mtkdev->plat_dev;
+	pm = &mtkdev->pm;
+	memset(pm, 0, sizeof(struct mtk_vcodec_pm));
+	pm->mtkdev = mtkdev;
+	pm->dev = &pdev->dev;
+	dev = &pdev->dev;
+
+	node = of_parse_phandle(dev->of_node, "mediatek,larb", 0);
+	if (!node) {
+		mtk_v4l2_err("no mediatek,larb found");
+		return -1;
+	}
+	pdev = of_find_device_by_node(node);
+	if (!pdev) {
+		mtk_v4l2_err("no mediatek,larb device found");
+		return -1;
+	}
+	pm->larbvenc = &pdev->dev;
+
+	node = of_parse_phandle(dev->of_node, "mediatek,larb", 1);
+	if (!node) {
+		mtk_v4l2_err("no mediatek,larb found");
+		return -1;
+	}
+
+	pdev = of_find_device_by_node(node);
+	if (!pdev) {
+		mtk_v4l2_err("no mediatek,larb device found");
+		return -1;
+	}
+
+	pm->larbvenclt = &pdev->dev;
+	pdev = mtkdev->plat_dev;
+	pm->dev = &pdev->dev;
+
+	pm->vencpll_d2 = devm_clk_get(&pdev->dev, "venc_sel_src");
+	if (pm->vencpll_d2 == NULL) {
+		mtk_v4l2_err("devm_clk_get vencpll_d2 fail");
+		ret = -1;
+	}
+
+	pm->venc_sel = devm_clk_get(&pdev->dev, "venc_sel");
+	if (pm->venc_sel == NULL) {
+		mtk_v4l2_err("devm_clk_get venc_sel fail");
+		ret = -1;
+	}
+
+	pm->univpll1_d2 = devm_clk_get(&pdev->dev, "venc_lt_sel_src");
+	if (pm->univpll1_d2 == NULL) {
+		mtk_v4l2_err("devm_clk_get univpll1_d2 fail");
+		ret = -1;
+	}
+
+	pm->venc_lt_sel = devm_clk_get(&pdev->dev, "venc_lt_sel");
+	if (pm->venc_lt_sel == NULL) {
+		mtk_v4l2_err("devm_clk_get venc_lt_sel fail");
+		ret = -1;
+	}
+
+	return ret;
+}
+
+void mtk_vcodec_release_enc_pm(struct mtk_vcodec_dev *mtkdev)
+{
+}
+
+
+void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm)
+{
+	int ret;
+
+	ret = clk_prepare_enable(pm->venc_sel);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable fail %d", ret);
+
+	ret = clk_set_parent(pm->venc_sel, pm->vencpll_d2);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent fail %d", ret);
+
+	ret = clk_prepare_enable(pm->venc_lt_sel);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable fail %d", ret);
+
+	ret = clk_set_parent(pm->venc_lt_sel, pm->univpll1_d2);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent fail %d", ret);
+
+	ret = mtk_smi_larb_get(pm->larbvenc);
+	if (ret)
+		mtk_v4l2_err("mtk_smi_larb_get larb3 fail %d", ret);
+
+	ret = mtk_smi_larb_get(pm->larbvenclt);
+	if (ret)
+		mtk_v4l2_err("mtk_smi_larb_get larb4 fail %d", ret);
+
+}
+
+void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm)
+{
+	mtk_smi_larb_put(pm->larbvenc);
+	mtk_smi_larb_put(pm->larbvenclt);
+	clk_disable_unprepare(pm->venc_lt_sel);
+	clk_disable_unprepare(pm->venc_sel);
+}
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
new file mode 100644
index 0000000..f321671
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
@@ -0,0 +1,26 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MTK_VCODEC_ENC_PM_H_
+#define _MTK_VCODEC_ENC_PM_H_
+
+#include "mtk_vcodec_drv.h"
+
+int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *dev);
+void mtk_vcodec_release_enc_pm(struct mtk_vcodec_dev *dev);
+
+void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm);
+void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm);
+
+#endif /* _MTK_VCODEC_ENC_PM_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c
new file mode 100644
index 0000000..7f1f104
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/errno.h>
+#include <linux/wait.h>
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_intr.h"
+#include "mtk_vcodec_util.h"
+
+int mtk_vcodec_wait_for_done_ctx(struct mtk_vcodec_ctx  *ctx, int command,
+				 unsigned int timeout_ms)
+{
+	wait_queue_head_t *waitqueue;
+	long timeout_jiff, ret;
+	int status = 0;
+
+	waitqueue = (wait_queue_head_t *)&ctx->queue;
+	timeout_jiff = msecs_to_jiffies(timeout_ms);
+
+	ret = wait_event_interruptible_timeout(*waitqueue,
+				(ctx->int_cond &&
+				(ctx->int_type == command)),
+				timeout_jiff);
+
+	if (!ret) {
+		status = -1;	/* timeout */
+		mtk_v4l2_err("[%d] cmd=%d, ctx->type=%d, wait_event_interruptible_timeout time=%ums out %d %d!",
+				ctx->id, ctx->type, command, timeout_ms,
+				ctx->int_cond, ctx->int_type);
+	} else if (-ERESTARTSYS == ret) {
+		mtk_v4l2_err("[%d] cmd=%d, ctx->type=%d, wait_event_interruptible_timeout interrupted by a signal %d %d",
+				ctx->id, ctx->type, command, ctx->int_cond,
+				ctx->int_type);
+		status = -1;
+	}
+
+	ctx->int_cond = 0;
+	ctx->int_type = 0;
+
+	return status;
+}
+EXPORT_SYMBOL(mtk_vcodec_wait_for_done_ctx);
+
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h
new file mode 100644
index 0000000..33e890f
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h
@@ -0,0 +1,27 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MTK_VCODEC_INTR_H_
+#define _MTK_VCODEC_INTR_H_
+
+#define MTK_INST_IRQ_RECEIVED		0x1
+#define MTK_INST_WORK_THREAD_ABORT_DONE	0x2
+
+struct mtk_vcodec_ctx;
+
+/* timeout is ms */
+int mtk_vcodec_wait_for_done_ctx(struct mtk_vcodec_ctx *data, int command,
+				unsigned int timeout_ms);
+
+#endif /* _MTK_VCODEC_INTR_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
new file mode 100644
index 0000000..5e36513
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
@@ -0,0 +1,94 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen at mediatek.com>
+*	Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/module.h>
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
+
+/* For encoder, this will enable logs in venc/*/
+bool mtk_vcodec_dbg;
+EXPORT_SYMBOL(mtk_vcodec_dbg);
+
+/* The log level of v4l2 encoder or decoder driver.
+ * That is, files under mtk-vcodec/.
+ */
+int mtk_v4l2_dbg_level;
+EXPORT_SYMBOL(mtk_v4l2_dbg_level);
+
+void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data,
+					unsigned int reg_idx)
+{
+	struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)data;
+
+	if (!data || reg_idx >= NUM_MAX_VCODEC_REG_BASE) {
+		mtk_v4l2_err("Invalid arguments, reg_idx=%d", reg_idx);
+		return NULL;
+	}
+	return ctx->dev->reg_base[reg_idx];
+}
+EXPORT_SYMBOL(mtk_vcodec_get_reg_addr);
+
+int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data,
+			struct mtk_vcodec_mem *mem)
+{
+	unsigned long size = mem->size;
+	struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)data;
+	struct device *dev = &ctx->dev->plat_dev->dev;
+
+	mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL);
+
+	if (!mem->va) {
+		mtk_v4l2_err("%s dma_alloc size=%ld failed!", dev_name(dev),
+			     size);
+		return -ENOMEM;
+	}
+
+	memset(mem->va, 0, size);
+
+	mtk_v4l2_debug(3, "[%d]  - va      = %p", ctx->id, mem->va);
+	mtk_v4l2_debug(3, "[%d]  - dma     = 0x%lx", ctx->id,
+		       (unsigned long)mem->dma_addr);
+	mtk_v4l2_debug(3, "[%d]    size = 0x%lx", ctx->id, size);
+
+	return 0;
+}
+EXPORT_SYMBOL(mtk_vcodec_mem_alloc);
+
+void mtk_vcodec_mem_free(struct mtk_vcodec_ctx *data,
+			struct mtk_vcodec_mem *mem)
+{
+	unsigned long size = mem->size;
+	struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)data;
+	struct device *dev = &ctx->dev->plat_dev->dev;
+
+	if (!mem->va) {
+		mtk_v4l2_err("%s dma_free size=%ld failed!", dev_name(dev),
+			     size);
+		return;
+	}
+
+	dma_free_coherent(dev, size, mem->va, mem->dma_addr);
+	mem->va = NULL;
+	mem->dma_addr = 0;
+	mem->size = 0;
+
+	mtk_v4l2_debug(3, "[%d]  - va      = %p", ctx->id, mem->va);
+	mtk_v4l2_debug(3, "[%d]  - dma     = 0x%lx", ctx->id,
+		       (unsigned long)mem->dma_addr);
+	mtk_v4l2_debug(3, "[%d]    size = 0x%lx", ctx->id, size);
+}
+EXPORT_SYMBOL(mtk_vcodec_mem_free);
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
new file mode 100644
index 0000000..d6345fc
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
@@ -0,0 +1,87 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen at mediatek.com>
+*	Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MTK_VCODEC_UTIL_H_
+#define _MTK_VCODEC_UTIL_H_
+
+#include <linux/types.h>
+#include <linux/dma-direction.h>
+
+struct mtk_vcodec_mem {
+	size_t size;
+	void *va;
+	dma_addr_t dma_addr;
+};
+
+struct mtk_vcodec_ctx;
+
+extern int mtk_v4l2_dbg_level;
+extern bool mtk_vcodec_dbg;
+
+#define DEBUG	1
+
+#if defined(DEBUG)
+
+#define mtk_v4l2_debug(level, fmt, args...)				 \
+	do {								 \
+		if (mtk_v4l2_dbg_level >= level)			 \
+			pr_info("[MTK_V4L2] level=%d %s(),%d: " fmt "\n",\
+				level, __func__, __LINE__, ##args);	 \
+	} while (0)
+
+#define mtk_v4l2_err(fmt, args...)                \
+	pr_err("[MTK_V4L2][ERROR] %s:%d: " fmt "\n", __func__, __LINE__, \
+	       ##args)
+
+
+#define mtk_v4l2_debug_enter()  mtk_v4l2_debug(3, "+")
+#define mtk_v4l2_debug_leave()  mtk_v4l2_debug(3, "-")
+
+#define mtk_vcodec_debug(h, fmt, args...)				\
+	do {								\
+		if (mtk_vcodec_dbg)					\
+			pr_info("[MTK_VCODEC][%d]: %s() " fmt "\n",	\
+				((struct mtk_vcodec_ctx *)h->ctx)->id, \
+				__func__, ##args);			\
+	} while (0)
+
+#define mtk_vcodec_err(h, fmt, args...)					\
+	pr_err("[MTK_VCODEC][ERROR][%d]: %s() " fmt "\n",		\
+	       ((struct mtk_vcodec_ctx *)h->ctx)->id, __func__, ##args)
+
+#define mtk_vcodec_debug_enter(h)  mtk_vcodec_debug(h, "+")
+#define mtk_vcodec_debug_leave(h)  mtk_vcodec_debug(h, "-")
+
+#else
+
+#define mtk_v4l2_debug(level, fmt, args...)
+#define mtk_v4l2_err(fmt, args...)
+#define mtk_v4l2_debug_enter()
+#define mtk_v4l2_debug_leave()
+
+#define mtk_vcodec_debug(h, fmt, args...)
+#define mtk_vcodec_err(h, fmt, args...)
+#define mtk_vcodec_debug_enter(h)
+#define mtk_vcodec_debug_leave(h)
+
+#endif
+
+void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data,
+				unsigned int reg_idx);
+int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data,
+				struct mtk_vcodec_mem *mem);
+void mtk_vcodec_mem_free(struct mtk_vcodec_ctx *data,
+				struct mtk_vcodec_mem *mem);
+#endif /* _MTK_VCODEC_UTIL_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_base.h b/drivers/media/platform/mtk-vcodec/venc_drv_base.h
new file mode 100644
index 0000000..6308d44
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/venc_drv_base.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Daniel Hsiao <daniel.hsiao at mediatek.com>
+ *	Jungchang Tsao <jungchang.tsao at mediatek.com>
+ *	Tiffany Lin <tiffany.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VENC_DRV_BASE_
+#define _VENC_DRV_BASE_
+
+#include "mtk_vcodec_drv.h"
+
+#include "venc_drv_if.h"
+
+struct venc_common_if {
+	/**
+	 * (*init)() - initialize driver
+	 * @ctx:	[in] mtk v4l2 context
+	 * @handle: [out] driver handle
+	 */
+	int (*init)(struct mtk_vcodec_ctx *ctx, unsigned long *handle);
+
+	/**
+	 * (*encode)() - trigger encode
+	 * @handle: [in] driver handle
+	 * @opt: [in] encode option
+	 * @frm_buf: [in] frame buffer to store input frame
+	 * @bs_buf: [in] bitstream buffer to store output bitstream
+	 * @result: [out] encode result
+	 */
+	int (*encode)(unsigned long handle, enum venc_start_opt opt,
+		      struct venc_frm_buf *frm_buf,
+		      struct mtk_vcodec_mem *bs_buf,
+		      struct venc_done_result *result);
+
+	/**
+	 * (*set_param)() - set driver's parameter
+	 * @handle: [in] driver handle
+	 * @type: [in] parameter type
+	 * @in: [in] buffer to store the parameter
+	 */
+	int (*set_param)(unsigned long handle, enum venc_set_param_type type,
+			 struct venc_enc_param *in);
+
+	/**
+	 * (*deinit)() - deinitialize driver.
+	 * @handle: [in] driver handle
+	 */
+	int (*deinit)(unsigned long handle);
+};
+
+#endif
diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_if.c b/drivers/media/platform/mtk-vcodec/venc_drv_if.c
new file mode 100644
index 0000000..79ec9f5
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/venc_drv_if.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Daniel Hsiao <daniel.hsiao at mediatek.com>
+ *	Jungchang Tsao <jungchang.tsao at mediatek.com>
+ *	Tiffany Lin <tiffany.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "venc_drv_if.h"
+#include "mtk_vcodec_enc.h"
+#include "mtk_vcodec_enc_pm.h"
+#include "mtk_vpu.h"
+
+#include "venc_drv_base.h"
+
+int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
+{
+	int ret = 0;
+
+	switch (fourcc) {
+	case V4L2_PIX_FMT_VP8:
+	case V4L2_PIX_FMT_H264:
+	default:
+		return -EINVAL;
+	}
+
+	mtk_venc_lock(ctx);
+	mtk_vcodec_enc_clock_on(&ctx->dev->pm);
+	ret = ctx->enc_if->init(ctx, (unsigned long *)&ctx->drv_handle);
+	mtk_vcodec_enc_clock_off(&ctx->dev->pm);
+	mtk_venc_unlock(ctx);
+
+	return ret;
+}
+
+int venc_if_set_param(struct mtk_vcodec_ctx *ctx,
+		enum venc_set_param_type type, struct venc_enc_param *in)
+{
+	int ret = 0;
+
+	mtk_venc_lock(ctx);
+	mtk_vcodec_enc_clock_on(&ctx->dev->pm);
+	ret = ctx->enc_if->set_param(ctx->drv_handle, type, in);
+	mtk_vcodec_enc_clock_off(&ctx->dev->pm);
+	mtk_venc_unlock(ctx);
+
+	return ret;
+}
+
+int venc_if_encode(struct mtk_vcodec_ctx *ctx,
+		   enum venc_start_opt opt, struct venc_frm_buf *frm_buf,
+		   struct mtk_vcodec_mem *bs_buf,
+		   struct venc_done_result *result)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	mtk_venc_lock(ctx);
+
+	spin_lock_irqsave(&ctx->dev->irqlock, flags);
+	ctx->dev->curr_ctx = ctx;
+	spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
+
+	mtk_vcodec_enc_clock_on(&ctx->dev->pm);
+	ret = ctx->enc_if->encode(ctx->drv_handle, opt, frm_buf,
+				  bs_buf, result);
+	mtk_vcodec_enc_clock_off(&ctx->dev->pm);
+
+	spin_lock_irqsave(&ctx->dev->irqlock, flags);
+	ctx->dev->curr_ctx = NULL;
+	spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
+
+	mtk_venc_unlock(ctx);
+	return ret;
+}
+
+int venc_if_deinit(struct mtk_vcodec_ctx *ctx)
+{
+	int ret = 0;
+
+	if (ctx->drv_handle == 0)
+		return 0;
+
+	mtk_venc_lock(ctx);
+	mtk_vcodec_enc_clock_on(&ctx->dev->pm);
+	ret = ctx->enc_if->deinit(ctx->drv_handle);
+	mtk_vcodec_enc_clock_off(&ctx->dev->pm);
+	mtk_venc_unlock(ctx);
+
+	ctx->drv_handle = 0;
+
+	return ret;
+}
diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_if.h b/drivers/media/platform/mtk-vcodec/venc_drv_if.h
new file mode 100644
index 0000000..a6e7d32
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/venc_drv_if.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Daniel Hsiao <daniel.hsiao at mediatek.com>
+ *		Jungchang Tsao <jungchang.tsao at mediatek.com>
+ *		Tiffany Lin <tiffany.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VENC_DRV_IF_H_
+#define _VENC_DRV_IF_H_
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_util.h"
+
+/*
+ * enum venc_yuv_fmt - The type of input yuv format
+ * (VPU related: If you change the order, you must also update the VPU codes.)
+ * @VENC_YUV_FORMAT_I420: I420 YUV format
+ * @VENC_YUV_FORMAT_YV12: YV12 YUV format
+ * @VENC_YUV_FORMAT_NV12: NV12 YUV format
+ * @VENC_YUV_FORMAT_NV21: NV21 YUV format
+ */
+enum venc_yuv_fmt {
+	VENC_YUV_FORMAT_I420 = 3,
+	VENC_YUV_FORMAT_YV12 = 5,
+	VENC_YUV_FORMAT_NV12 = 6,
+	VENC_YUV_FORMAT_NV21 = 7,
+};
+
+/*
+ * enum venc_start_opt - encode frame option used in venc_if_encode()
+ * @VENC_START_OPT_ENCODE_SEQUENCE_HEADER: encode SPS/PPS for H264
+ * @VENC_START_OPT_ENCODE_FRAME: encode normal frame
+ */
+enum venc_start_opt {
+	VENC_START_OPT_ENCODE_SEQUENCE_HEADER,
+	VENC_START_OPT_ENCODE_FRAME,
+};
+
+/*
+ * enum venc_set_param_type - The type of set parameter used in
+ *						      venc_if_set_param()
+ * (VPU related: If you change the order, you must also update the VPU codes.)
+ * @VENC_SET_PARAM_ENC: set encoder parameters
+ * @VENC_SET_PARAM_FORCE_INTRA: force an intra frame
+ * @VENC_SET_PARAM_ADJUST_BITRATE: adjust bitrate (in bps)
+ * @VENC_SET_PARAM_ADJUST_FRAMERATE: set frame rate
+ * @VENC_SET_PARAM_GOP_SIZE: set IDR interval
+ * @VENC_SET_PARAM_INTRA_PERIOD: set I frame interval
+ * @VENC_SET_PARAM_SKIP_FRAME: set H264 skip one frame
+ * @VENC_SET_PARAM_PREPEND_HEADER: set H264 prepend SPS/PPS before IDR
+ * @VENC_SET_PARAM_TS_MODE: set VP8 temporal scalability mode
+ */
+enum venc_set_param_type {
+	VENC_SET_PARAM_ENC,
+	VENC_SET_PARAM_FORCE_INTRA,
+	VENC_SET_PARAM_ADJUST_BITRATE,
+	VENC_SET_PARAM_ADJUST_FRAMERATE,
+	VENC_SET_PARAM_GOP_SIZE,
+	VENC_SET_PARAM_INTRA_PERIOD,
+	VENC_SET_PARAM_SKIP_FRAME,
+	VENC_SET_PARAM_PREPEND_HEADER,
+	VENC_SET_PARAM_TS_MODE,
+};
+
+/*
+ * struct venc_enc_prm - encoder settings for VENC_SET_PARAM_ENC used in
+ *					  venc_if_set_param()
+ * @input_fourcc: input yuv format
+ * @h264_profile: V4L2 defined H.264 profile
+ * @h264_level: V4L2 defined H.264 level
+ * @width: image width
+ * @height: image height
+ * @buf_width: buffer width
+ * @buf_height: buffer height
+ * @frm_rate: frame rate in fps
+ * @intra_period: intra frame period
+ * @bitrate: target bitrate in bps
+ * @gop_size: group of picture size
+ */
+struct venc_enc_param {
+	enum venc_yuv_fmt input_yuv_fmt;
+	unsigned int h264_profile;
+	unsigned int h264_level;
+	unsigned int width;
+	unsigned int height;
+	unsigned int buf_width;
+	unsigned int buf_height;
+	unsigned int frm_rate;
+	unsigned int intra_period;
+	unsigned int bitrate;
+	unsigned int gop_size;
+};
+
+/*
+ * struct venc_frm_buf - frame buffer information used in venc_if_encode()
+ * @fb_addr: plane frame buffer addresses
+ */
+struct venc_frm_buf {
+	struct mtk_vcodec_mem fb_addr[MTK_VCODEC_MAX_PLANES];
+};
+
+/*
+ * struct venc_done_result - This is return information used in venc_if_encode()
+ * @bs_size: output bitstream size
+ * @is_key_frm: output is key frame or not
+ */
+struct venc_done_result {
+	unsigned int bs_size;
+	bool is_key_frm;
+};
+
+/*
+ * venc_if_init - Create the driver handle
+ * @ctx: device context
+ * @fourcc: encoder input format
+ * Return: 0 if creating handle successfully, otherwise it is failed.
+ */
+int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc);
+
+/*
+ * venc_if_deinit - Release the driver handle
+ * @ctx: device context
+ * Return: 0 if releasing handle successfully, otherwise it is failed.
+ */
+int venc_if_deinit(struct mtk_vcodec_ctx *ctx);
+
+/*
+ * venc_if_set_param - Set parameter to driver
+ * @ctx: device context
+ * @type: parameter type
+ * @in: input parameter
+ * Return: 0 if setting param successfully, otherwise it is failed.
+ */
+int venc_if_set_param(struct mtk_vcodec_ctx *ctx,
+		      enum venc_set_param_type type,
+		      struct venc_enc_param *in);
+
+/*
+ * venc_if_encode - Encode one frame
+ * @ctx: device context
+ * @opt: encode frame option
+ * @frm_buf: input frame buffer information
+ * @bs_buf: output bitstream buffer infomraiton
+ * @result: encode result
+ * Return: 0 if encoding frame successfully, otherwise it is failed.
+ */
+int venc_if_encode(struct mtk_vcodec_ctx *ctx,
+		   enum venc_start_opt opt,
+		   struct venc_frm_buf *frm_buf,
+		   struct mtk_vcodec_mem *bs_buf,
+		   struct venc_done_result *result);
+
+#endif /* _VENC_DRV_IF_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/venc_ipi_msg.h b/drivers/media/platform/mtk-vcodec/venc_ipi_msg.h
new file mode 100644
index 0000000..4c869cb
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/venc_ipi_msg.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Jungchang Tsao <jungchang.tsao at mediatek.com>
+ *	   Daniel Hsiao <daniel.hsiao at mediatek.com>
+ *	   Tiffany Lin <tiffany.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VENC_IPI_MSG_H_
+#define _VENC_IPI_MSG_H_
+
+#define AP_IPIMSG_VENC_BASE 0xC000
+#define VPU_IPIMSG_VENC_BASE 0xD000
+
+/**
+ * enum venc_ipi_msg_id - message id between AP and VPU
+ * (ipi stands for inter-processor interrupt)
+ * @AP_IPIMSG_ENC_XXX:		AP to VPU cmd message id
+ * @VPU_IPIMSG_ENC_XXX_DONE:	VPU ack AP cmd message id
+ */
+enum venc_ipi_msg_id {
+	AP_IPIMSG_ENC_INIT = AP_IPIMSG_VENC_BASE,
+	AP_IPIMSG_ENC_SET_PARAM,
+	AP_IPIMSG_ENC_ENCODE,
+	AP_IPIMSG_ENC_DEINIT,
+
+	VPU_IPIMSG_ENC_INIT_DONE = VPU_IPIMSG_VENC_BASE,
+	VPU_IPIMSG_ENC_SET_PARAM_DONE,
+	VPU_IPIMSG_ENC_ENCODE_DONE,
+	VPU_IPIMSG_ENC_DEINIT_DONE,
+};
+
+/**
+ * struct venc_ap_ipi_msg_init - AP to VPU init cmd structure
+ * @msg_id:	message id (AP_IPIMSG_XXX_ENC_INIT)
+ * @reserved:	reserved for future use. vpu is running in 32bit. Without
+ *		this reserved field, if kernel run in 64bit. this struct size
+ *		will be different between kernel and vpu
+ * @venc_inst:	AP encoder instance
+ *		(struct venc_vp8_inst/venc_h264_inst *)
+ */
+struct venc_ap_ipi_msg_init {
+	uint32_t msg_id;
+	uint32_t reserved;
+	uint64_t venc_inst;
+};
+
+/**
+ * struct venc_ap_ipi_msg_set_param - AP to VPU set_param cmd structure
+ * @msg_id:	message id (AP_IPIMSG_XXX_ENC_SET_PARAM)
+ * @vpu_inst_addr:	VPU encoder instance addr
+ *			(struct venc_vp8_vsi/venc_h264_vsi *)
+ * @param_id:	parameter id (venc_set_param_type)
+ * @data_item:	number of items in the data array
+ * @data[8]:	data array to store the set parameters
+ */
+struct venc_ap_ipi_msg_set_param {
+	uint32_t msg_id;
+	uint32_t vpu_inst_addr;
+	uint32_t param_id;
+	uint32_t data_item;
+	uint32_t data[8];
+};
+
+/**
+ * struct venc_ap_ipi_msg_enc - AP to VPU enc cmd structure
+ * @msg_id:	message id (AP_IPIMSG_XXX_ENC_ENCODE)
+ * @vpu_inst_addr:	VPU encoder instance addr
+ *			(struct venc_vp8_vsi/venc_h264_vsi *)
+ * @bs_mode:	bitstream mode for h264
+ *		(H264_BS_MODE_SPS/H264_BS_MODE_PPS/H264_BS_MODE_FRAME)
+ * @input_addr:	pointer to input image buffer plane
+ * @bs_addr:	pointer to output bit stream buffer
+ * @bs_size:	bit stream buffer size
+ */
+struct venc_ap_ipi_msg_enc {
+	uint32_t msg_id;
+	uint32_t vpu_inst_addr;
+	uint32_t bs_mode;
+	uint32_t input_addr[3];
+	uint32_t bs_addr;
+	uint32_t bs_size;
+};
+
+/**
+ * struct venc_ap_ipi_msg_deinit - AP to VPU deinit cmd structure
+ * @msg_id:	message id (AP_IPIMSG_XXX_ENC_DEINIT)
+ * @vpu_inst_addr:	VPU encoder instance addr
+ *			(struct venc_vp8_vsi/venc_h264_vsi *)
+ */
+struct venc_ap_ipi_msg_deinit {
+	uint32_t msg_id;
+	uint32_t vpu_inst_addr;
+};
+
+/**
+ * enum venc_ipi_msg_status - VPU ack AP cmd status
+ */
+enum venc_ipi_msg_status {
+	VENC_IPI_MSG_STATUS_OK,
+	VENC_IPI_MSG_STATUS_FAIL,
+};
+
+/**
+ * struct venc_vpu_ipi_msg_common - VPU ack AP cmd common structure
+ * @msg_id:	message id (VPU_IPIMSG_XXX_DONE)
+ * @status:	cmd status (venc_ipi_msg_status)
+ * @venc_inst:	AP encoder instance (struct venc_vp8_inst/venc_h264_inst *)
+ */
+struct venc_vpu_ipi_msg_common {
+	uint32_t msg_id;
+	uint32_t status;
+	uint64_t venc_inst;
+};
+
+/**
+ * struct venc_vpu_ipi_msg_init - VPU ack AP init cmd structure
+ * @msg_id:	message id (VPU_IPIMSG_XXX_ENC_SET_PARAM_DONE)
+ * @status:	cmd status (venc_ipi_msg_status)
+ * @venc_inst:	AP encoder instance (struct venc_vp8_inst/venc_h264_inst *)
+ * @vpu_inst_addr:	VPU encoder instance addr
+ *			(struct venc_vp8_vsi/venc_h264_vsi *)
+ * @reserved:	reserved for future use. vpu is running in 32bit. Without
+ *		this reserved field, if kernel run in 64bit. this struct size
+ *		will be different between kernel and vpu
+ */
+struct venc_vpu_ipi_msg_init {
+	uint32_t msg_id;
+	uint32_t status;
+	uint64_t venc_inst;
+	uint32_t vpu_inst_addr;
+	uint32_t reserved;
+};
+
+/**
+ * struct venc_vpu_ipi_msg_set_param - VPU ack AP set_param cmd structure
+ * @msg_id:	message id (VPU_IPIMSG_XXX_ENC_SET_PARAM_DONE)
+ * @status:	cmd status (venc_ipi_msg_status)
+ * @venc_inst:	AP encoder instance (struct venc_vp8_inst/venc_h264_inst *)
+ * @param_id:	parameter id (venc_set_param_type)
+ * @data_item:	number of items in the data array
+ * @data[6]:	data array to store the return result
+ */
+struct venc_vpu_ipi_msg_set_param {
+	uint32_t msg_id;
+	uint32_t status;
+	uint64_t venc_inst;
+	uint32_t param_id;
+	uint32_t data_item;
+	uint32_t data[6];
+};
+
+/**
+ * enum venc_ipi_msg_enc_state - Type of encode state
+ * VEN_IPI_MSG_ENC_STATE_FRAME:	one frame being encoded
+ * VEN_IPI_MSG_ENC_STATE_PART:	bit stream buffer full
+ * VEN_IPI_MSG_ENC_STATE_SKIP:	encoded skip frame
+ * VEN_IPI_MSG_ENC_STATE_ERROR:	encounter error
+ */
+enum venc_ipi_msg_enc_state {
+	VEN_IPI_MSG_ENC_STATE_FRAME,
+	VEN_IPI_MSG_ENC_STATE_PART,
+	VEN_IPI_MSG_ENC_STATE_SKIP,
+	VEN_IPI_MSG_ENC_STATE_ERROR,
+};
+
+/**
+ * struct venc_vpu_ipi_msg_enc - VPU ack AP enc cmd structure
+ * @msg_id:	message id (VPU_IPIMSG_XXX_ENC_ENCODE_DONE)
+ * @status:	cmd status (venc_ipi_msg_status)
+ * @venc_inst:	AP encoder instance (struct venc_vp8_inst/venc_h264_inst *)
+ * @state:	encode state (venc_ipi_msg_enc_state)
+ * @is_key_frm:	whether the encoded frame is key frame
+ * @bs_size:	encoded bitstream size
+ * @reserved:	reserved for future use. vpu is running in 32bit. Without
+ *		this reserved field, if kernel run in 64bit. this struct size
+ *		will be different between kernel and vpu
+ */
+struct venc_vpu_ipi_msg_enc {
+	uint32_t msg_id;
+	uint32_t status;
+	uint64_t venc_inst;
+	uint32_t state;
+	uint32_t is_key_frm;
+	uint32_t bs_size;
+	uint32_t reserved;
+};
+
+/**
+ * struct venc_vpu_ipi_msg_deinit - VPU ack AP deinit cmd structure
+ * @msg_id:   message id (VPU_IPIMSG_XXX_ENC_DEINIT_DONE)
+ * @status:   cmd status (venc_ipi_msg_status)
+ * @venc_inst:	AP encoder instance (struct venc_vp8_inst/venc_h264_inst *)
+ */
+struct venc_vpu_ipi_msg_deinit {
+	uint32_t msg_id;
+	uint32_t status;
+	uint64_t venc_inst;
+};
+
+#endif /* _VENC_IPI_MSG_H_ */
-- 
1.7.9.5



From marc.zyngier at arm.com  Tue May  3 03:12:41 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 11:12:41 +0100
Subject: [PATCH v2 42/54] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 access to VGIC registers
In-Reply-To: <572878C8.5070306@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-43-git-send-email-andre.przywara@arm.com>
 <57287671.3000902@arm.com> <572878C8.5070306@arm.com>
Message-ID: <57287999.4040801@arm.com>

On 03/05/16 11:09, Andre Przywara wrote:
> Hi,
> 
> On 03/05/16 10:59, Marc Zyngier wrote:
>> On 28/04/16 17:46, Andre Przywara wrote:
>>> From: Eric Auger <eric.auger at linaro.org>
>>>
>>> This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
>>> and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
>>> access VGIC registers.
>>>
>>> At that stage the interfaces with the MMIO API are not implemented:
>>> - vgic_attr_regs_access
>>> - vgic_v2_has_attr_regs
>>>
>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>>  virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 34 ++++++++++++++++++++++++
>>>  virt/kvm/arm/vgic/vgic.h            |  1 +
>>>  3 files changed, 86 insertions(+), 2 deletions(-)
>>>
>>
>> [...]
>>
>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> index ae6077e..f2a8efe 100644
>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> @@ -276,3 +276,37 @@ int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>>>  
>>>  	return ret;
>>>  }
>>> +
>>> +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
>>> +{
>>> +	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
>>> +	const struct vgic_register_region *regions;
>>> +	gpa_t addr;
>>> +	int nr_regions, i, len;
>>> +
>>> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
>>> +
>>> +	switch (attr->group) {
>>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>>> +		regions = vgic_v2_dist_registers;
>>> +		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
>>> +		break;
>>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>>> +		return -ENXIO;		/* TODO: describe CPU i/f regs also */
>>
>> This definitely needs addressing, as it breaks guest migration.
> 
> It is implemented in patch 46/54.

Ah, sorry. I was on my way there...

> Shall I remove the TODO to avoid confusion and/or replace it with a note
> either in a comment or in this commit message that the implementation
> will follow in one the next patches?

Just drop the comment.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From k.kozlowski at samsung.com  Tue May  3 03:15:09 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 3 May 2016 12:15:09 +0200
Subject: [PATCH v2] s5p-mfc: Don't try to put pm->clock if lookup failed
In-Reply-To: <1462216462-32665-1-git-send-email-javier@osg.samsung.com>
References: <1462216462-32665-1-git-send-email-javier@osg.samsung.com>
Message-ID: <20160503101509.GB3956@kozik-lap>

On Mon, May 02, 2016 at 03:14:22PM -0400, Javier Martinez Canillas wrote:
> Failing to get the struct s5p_mfc_pm .clock is a non-fatal error so the
> clock field can have a errno pointer value. But s5p_mfc_final_pm() only
> checks if .clock is not NULL before attempting to unprepare and put it.
> 
> This leads to the following warning in clk_put() due s5p_mfc_final_pm():
> 
> WARNING: CPU: 3 PID: 1023 at drivers/clk/clk.c:2814 s5p_mfc_final_pm+0x48/0x74 [s5p_mfc]
> CPU: 3 PID: 1023 Comm: rmmod Tainted: G        W       4.6.0-rc6-next-20160502-00005-g5a15a49106bc #9
> Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [<c010e1bc>] (unwind_backtrace) from [<c010af28>] (show_stack+0x10/0x14)
> [<c010af28>] (show_stack) from [<c032485c>] (dump_stack+0x88/0x9c)
> [<c032485c>] (dump_stack) from [<c011b8e8>] (__warn+0xe8/0x100)
> [<c011b8e8>] (__warn) from [<c011b9b0>] (warn_slowpath_null+0x20/0x28)
> [<c011b9b0>] (warn_slowpath_null) from [<bf16004c>] (s5p_mfc_final_pm+0x48/0x74 [s5p_mfc])
> [<bf16004c>] (s5p_mfc_final_pm [s5p_mfc]) from [<bf157414>] (s5p_mfc_remove+0x8c/0x94 [s5p_mfc])
> [<bf157414>] (s5p_mfc_remove [s5p_mfc]) from [<c03fe1f8>] (platform_drv_remove+0x24/0x3c)
> [<c03fe1f8>] (platform_drv_remove) from [<c03fcc70>] (__device_release_driver+0x84/0x110)
> [<c03fcc70>] (__device_release_driver) from [<c03fcdd8>] (driver_detach+0xac/0xb0)
> [<c03fcdd8>] (driver_detach) from [<c03fbff8>] (bus_remove_driver+0x4c/0xa0)
> [<c03fbff8>] (bus_remove_driver) from [<c01886a8>] (SyS_delete_module+0x174/0x1b8)
> [<c01886a8>] (SyS_delete_module) from [<c01078c0>] (ret_fast_syscall+0x0/0x3c)
> 
> Assign the pointer to NULL in case of a lookup failure to fix the issue.
> 
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
> 
> ---
> 
> Changes in v2:
> - Set the clock pointer to NULL instead of checking for !IS_ERR_OR_NULL().
>   Suggested by Arnd Bergmann.
> 
>  drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | 1 +
>  1 file changed, 1 insertion(+)

This is a fix for bug, so for statistics:
Fixes: d19f405a5a8d ("[media] s5p-mfc: Fix selective sclk_mfc init")

... and although not fatal, but annoying so I think this deserves:
Cc: <stable at vger.kernel.org>

Anyway:
Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

Best regards,
Krzysztof


From linux at arm.linux.org.uk  Tue May  3 03:12:59 2016
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Tue, 3 May 2016 11:12:59 +0100
Subject: [PATCH 10/12] kexec: arrange for paddr_vmcoreinfo_note() to
 return phys_addr_t
In-Reply-To: <20160503042441.GA2518@x1.redhat.com>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <E1aviFP-0000je-5t@rmk-PC.arm.linux.org.uk>
 <CAHB_Gur-6oyEheN-Pom7OwivdvrQpCBaXvM1V2H0JPFRCFZthA@mail.gmail.com>
 <20160429151639.GC23726@leverpostej>
 <CAHB_GurwYqPbccLU9UHppLxbBr4Cfs47myKAer-RJicT=T7uBw@mail.gmail.com>
 <20160503042441.GA2518@x1.redhat.com>
Message-ID: <20160503101258.GL19428@n2100.arm.linux.org.uk>

On Tue, May 03, 2016 at 12:24:41PM +0800, Baoquan He wrote:
> Could you please help tell why arm PAE kernel can be put above 4G?
> Since the change is related to common code, I am curious about how
> it's so different with other ARCHs.

This is explained in the covering email to the series.

The explanation given by Pratyush was incomplete.

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From van.freenix at gmail.com  Tue May  3 03:15:27 2016
From: van.freenix at gmail.com (Peng Fan)
Date: Tue,  3 May 2016 18:15:27 +0800
Subject: [PATCH] iommu/arm-smmu: clear cache lock bit of ACR
Message-ID: <1462270527-17074-1-git-send-email-van.freenix@gmail.com>

According MMU-500 TRM, section 3.7.1 Auxiliary Control registers,
You can modify ACTLR only when the ACR.CACHE_LOCK bit is 0.

So before clearing ARM_MMU500_ACTLR_CPRE of each context bank,
need clear CACHE_LOCK bit of ACR register first.

Signed-off-by: Peng Fan <van.freenix at gmail.com>
Cc: Will Deacon <will.deacon at arm.com>
Cc: Robin Murphy <robin.murphy at arm.com>
---

Hi Will,

 Patch based on iommu/devel branch.


 drivers/iommu/arm-smmu.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index acff332..d094a5a 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -98,6 +98,9 @@
 #define sCR0_BSU_SHIFT			14
 #define sCR0_BSU_MASK			0x3
 
+/* Auxiliary Configuration register */
+#define ARM_SMMU_GR0_sACR		0x10
+
 /* Identification registers */
 #define ARM_SMMU_GR0_ID0		0x20
 #define ARM_SMMU_GR0_ID1		0x24
@@ -235,6 +238,8 @@
 
 #define ARM_MMU500_ACTLR_CPRE		(1 << 1)
 
+#define ARM_MMU500_ACR_CACHE_LOCK	(1 << 26)
+
 #define CB_PAR_F			(1 << 0)
 
 #define ATSR_ACTIVE			(1 << 0)
@@ -1506,6 +1511,16 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
 		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(i));
 	}
 
+	/*
+	 * Before clearing ARM_MMU500_ACTLR_CPRE, need to
+	 * clear CACHE_LOCK bit of ACR first.
+	 */
+	if (smmu->model == ARM_MMU500) {
+		reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sACR);
+		reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
+		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sACR);
+	}
+
 	/* Make sure all context banks are disabled and clear CB_FSR  */
 	for (i = 0; i < smmu->num_context_banks; ++i) {
 		cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, i);
-- 
2.6.2



From marc.zyngier at arm.com  Tue May  3 03:16:41 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 11:16:41 +0100
Subject: [PATCH v2 42/54] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 access to VGIC registers
In-Reply-To: <572878C8.5070306@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-43-git-send-email-andre.przywara@arm.com>
 <57287671.3000902@arm.com> <572878C8.5070306@arm.com>
Message-ID: <57287A89.9010809@arm.com>

On 03/05/16 11:09, Andre Przywara wrote:
> Hi,
> 
> On 03/05/16 10:59, Marc Zyngier wrote:
>> On 28/04/16 17:46, Andre Przywara wrote:
>>> From: Eric Auger <eric.auger at linaro.org>
>>>
>>> This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
>>> and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
>>> access VGIC registers.
>>>
>>> At that stage the interfaces with the MMIO API are not implemented:
>>> - vgic_attr_regs_access
>>> - vgic_v2_has_attr_regs
>>>
>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>>  virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 34 ++++++++++++++++++++++++
>>>  virt/kvm/arm/vgic/vgic.h            |  1 +
>>>  3 files changed, 86 insertions(+), 2 deletions(-)
>>>
>>
>> [...]
>>
>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> index ae6077e..f2a8efe 100644
>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> @@ -276,3 +276,37 @@ int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>>>  
>>>  	return ret;
>>>  }
>>> +
>>> +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
>>> +{
>>> +	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
>>> +	const struct vgic_register_region *regions;
>>> +	gpa_t addr;
>>> +	int nr_regions, i, len;
>>> +
>>> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
>>> +
>>> +	switch (attr->group) {
>>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>>> +		regions = vgic_v2_dist_registers;
>>> +		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
>>> +		break;
>>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>>> +		return -ENXIO;		/* TODO: describe CPU i/f regs also */
>>
>> This definitely needs addressing, as it breaks guest migration.
> 
> It is implemented in patch 46/54.
> Shall I remove the TODO to avoid confusion and/or replace it with a note
> either in a comment or in this commit message that the implementation
> will follow in one the next patches?

I just checked, and I stand by my initial comment. Patch 46 does
implement the accessors, but nothing actually wires them here.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From tiffany.lin at mediatek.com  Tue May  3 03:11:22 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Tue, 3 May 2016 18:11:22 +0800
Subject: [PATCH v10 3/8] arm64: dts: mediatek: Add node for Mediatek Video
 Processor Unit
In-Reply-To: <1462270287-11374-3-git-send-email-tiffany.lin@mediatek.com>
References: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-2-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-3-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1462270287-11374-4-git-send-email-tiffany.lin@mediatek.com>

From: Andrew-CT Chen <andrew-ct.chen at mediatek.com>

Add VPU drivers for MT8173

Signed-off-by: Andrew-CT Chen <andrew-ct.chen at mediatek.com>
Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>

---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index eab7efc..ae147bb 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -125,6 +125,18 @@
 		clock-output-names = "cpum_ck";
 	};
 
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		vpu_dma_reserved: vpu_dma_mem_region {
+			compatible = "shared-dma-pool";
+			reg = <0 0xb7000000 0 0x500000>;
+			alignment = <0x1000>;
+			no-map;
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupt-parent = <&gic>;
@@ -269,6 +281,17 @@
 			clock-names = "spi", "wrap";
 		};
 
+		vpu: vpu at 10020000 {
+			compatible = "mediatek,mt8173-vpu";
+			reg = <0 0x10020000 0 0x30000>,
+			      <0 0x10050000 0 0x100>;
+			reg-names = "tcm", "cfg_reg";
+			interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&topckgen CLK_TOP_SCP_SEL>;
+			clock-names = "main";
+			memory-region = <&vpu_dma_reserved>;
+		};
+
 		sysirq: intpol-controller at 10200620 {
 			compatible = "mediatek,mt8173-sysirq",
 				     "mediatek,mt6577-sysirq";
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Tue May  3 03:11:20 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Tue, 3 May 2016 18:11:20 +0800
Subject: [PATCH v10 1/8] dt-bindings: Add a binding for Mediatek Video
 Processor
In-Reply-To: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
References: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1462270287-11374-2-git-send-email-tiffany.lin@mediatek.com>

From: Andrew-CT Chen <andrew-ct.chen at mediatek.com>

Add a DT binding documentation of Video Processor Unit for the
MT8173 SoC from Mediatek.

Signed-off-by: Andrew-CT Chen <andrew-ct.chen at mediatek.com>
Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
Acked-by: Rob Herring <robh at kernel.org>

---
 .../devicetree/bindings/media/mediatek-vpu.txt     |   31 ++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/mediatek-vpu.txt

diff --git a/Documentation/devicetree/bindings/media/mediatek-vpu.txt b/Documentation/devicetree/bindings/media/mediatek-vpu.txt
new file mode 100644
index 0000000..2a5bac3
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/mediatek-vpu.txt
@@ -0,0 +1,31 @@
+* Mediatek Video Processor Unit
+
+Video Processor Unit is a HW video controller. It controls HW Codec including
+H.264/VP8/VP9 Decode, H.264/VP8 Encode and Image Processor (scale/rotate/color convert).
+
+Required properties:
+  - compatible: "mediatek,mt8173-vpu"
+  - reg: Must contain an entry for each entry in reg-names.
+  - reg-names: Must include the following entries:
+    "tcm": tcm base
+    "cfg_reg": Main configuration registers base
+  - interrupts: interrupt number to the cpu.
+  - clocks : clock name from clock manager
+  - clock-names: must be main. It is the main clock of VPU
+
+Optional properties:
+  - memory-region: phandle to a node describing memory (see
+    Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt)
+    to be used for VPU extended memory; if not present, VPU may be located
+    anywhere in the memory
+
+Example:
+	vpu: vpu at 10020000 {
+		compatible = "mediatek,mt8173-vpu";
+		reg = <0 0x10020000 0 0x30000>,
+		      <0 0x10050000 0 0x100>;
+		reg-names = "tcm", "cfg_reg";
+		interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&topckgen TOP_SCP_SEL>;
+		clock-names = "main";
+	};
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Tue May  3 03:11:26 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Tue, 3 May 2016 18:11:26 +0800
Subject: [PATCH v10 7/8] [media] vcodec: mediatek: Add Mediatek H264 Video
 Encoder Driver
In-Reply-To: <1462270287-11374-7-git-send-email-tiffany.lin@mediatek.com>
References: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-2-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-3-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-4-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-5-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-6-git-send-email-tiffany.lin@mediatek.com>
 <1462270287-11374-7-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1462270287-11374-8-git-send-email-tiffany.lin@mediatek.com>

Add h264 encoder driver for MT8173

Signed-off-by: PoChun Lin <pochun.lin at mediatek.com>
Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>

---
 drivers/media/platform/mtk-vcodec/Makefile         |    1 +
 .../media/platform/mtk-vcodec/venc/venc_h264_if.c  |  679 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/venc_drv_if.c    |    4 +-
 3 files changed, 683 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c

diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
index bf73a45..dc5cb00 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -12,6 +12,7 @@ mtk-vcodec-enc-y := venc/venc_vp8_if.o \
 		venc_drv_if.o \
 		venc_vpu_if.o \
 
+
 mtk-vcodec-common-y := mtk_vcodec_intr.o \
 		mtk_vcodec_util.o\
 
diff --git a/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
new file mode 100644
index 0000000..f4e18bb
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
@@ -0,0 +1,679 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Jungchang Tsao <jungchang.tsao at mediatek.com>
+ *         Daniel Hsiao <daniel.hsiao at mediatek.com>
+ *         PoChun Lin <pochun.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "../mtk_vcodec_drv.h"
+#include "../mtk_vcodec_util.h"
+#include "../mtk_vcodec_intr.h"
+#include "../mtk_vcodec_enc.h"
+#include "../mtk_vcodec_enc_pm.h"
+#include "../venc_drv_base.h"
+#include "../venc_ipi_msg.h"
+#include "../venc_vpu_if.h"
+#include "mtk_vpu.h"
+
+static const char h264_filler_marker[] = {0x0, 0x0, 0x0, 0x1, 0xc};
+
+#define H264_FILLER_MARKER_SIZE ARRAY_SIZE(h264_filler_marker)
+#define VENC_PIC_BITSTREAM_BYTE_CNT 0x0098
+
+/**
+ * enum venc_h264_vpu_work_buf - h264 encoder buffer index
+ */
+enum venc_h264_vpu_work_buf {
+	VENC_H264_VPU_WORK_BUF_RC_INFO,
+	VENC_H264_VPU_WORK_BUF_RC_CODE,
+	VENC_H264_VPU_WORK_BUF_REC_LUMA,
+	VENC_H264_VPU_WORK_BUF_REC_CHROMA,
+	VENC_H264_VPU_WORK_BUF_REF_LUMA,
+	VENC_H264_VPU_WORK_BUF_REF_CHROMA,
+	VENC_H264_VPU_WORK_BUF_MV_INFO_1,
+	VENC_H264_VPU_WORK_BUF_MV_INFO_2,
+	VENC_H264_VPU_WORK_BUF_SKIP_FRAME,
+	VENC_H264_VPU_WORK_BUF_MAX,
+};
+
+/**
+ * enum venc_h264_bs_mode - for bs_mode argument in h264_enc_vpu_encode
+ */
+enum venc_h264_bs_mode {
+	H264_BS_MODE_SPS,
+	H264_BS_MODE_PPS,
+	H264_BS_MODE_FRAME,
+};
+
+/*
+ * struct venc_h264_vpu_config - Structure for h264 encoder configuration
+ * @input_fourcc: input fourcc
+ * @bitrate: target bitrate (in bps)
+ * @pic_w: picture width. Picture size is visible stream resolution, in pixels,
+ *         to be used for display purposes; must be smaller or equal to buffer
+ *         size.
+ * @pic_h: picture height
+ * @buf_w: buffer width. Buffer size is stream resolution in pixels aligned to
+ *         hardware requirements.
+ * @buf_h: buffer height
+ * @gop_size: group of picture size (idr frame)
+ * @intra_period: intra frame period
+ * @framerate: frame rate in fps
+ * @profile: as specified in standard
+ * @level: as specified in standard
+ * @wfd: WFD mode 1:on, 0:off
+ */
+struct venc_h264_vpu_config {
+	u32 input_fourcc;
+	u32 bitrate;
+	u32 pic_w;
+	u32 pic_h;
+	u32 buf_w;
+	u32 buf_h;
+	u32 gop_size;
+	u32 intra_period;
+	u32 framerate;
+	u32 profile;
+	u32 level;
+	u32 wfd;
+};
+
+/*
+ * struct venc_h264_vpu_buf - Structure for buffer information
+ * @align: buffer alignment (in bytes)
+ * @iova: IO virtual address
+ * @vpua: VPU side memory addr which is used by RC_CODE
+ * @size: buffer size (in bytes)
+ */
+struct venc_h264_vpu_buf {
+	u32 align;
+	u32 iova;
+	u32 vpua;
+	u32 size;
+};
+
+/*
+ * struct venc_h264_vsi - Structure for VPU driver control and info share
+ * This structure is allocated in VPU side and shared to AP side.
+ * @config: h264 encoder configuration
+ * @work_bufs: working buffer information in VPU side
+ * The work_bufs here is for storing the 'size' info shared to AP side.
+ * The similar item in struct venc_h264_inst is for memory allocation
+ * in AP side. The AP driver will copy the 'size' from here to the one in
+ * struct mtk_vcodec_mem, then invoke mtk_vcodec_mem_alloc to allocate
+ * the buffer. After that, bypass the 'dma_addr' to the 'iova' field here for
+ * register setting in VPU side.
+ */
+struct venc_h264_vsi {
+	struct venc_h264_vpu_config config;
+	struct venc_h264_vpu_buf work_bufs[VENC_H264_VPU_WORK_BUF_MAX];
+};
+
+/*
+ * struct venc_h264_inst - h264 encoder AP driver instance
+ * @hw_base: h264 encoder hardware register base
+ * @work_bufs: working buffer
+ * @pps_buf: buffer to store the pps bitstream
+ * @work_buf_allocated: working buffer allocated flag
+ * @frm_cnt: encoded frame count
+ * @prepend_hdr: when the v4l2 layer send VENC_SET_PARAM_PREPEND_HEADER cmd
+ *  through h264_enc_set_param interface, it will set this flag and prepend the
+ *  sps/pps in h264_enc_encode function.
+ * @vpu_inst: VPU instance to exchange information between AP and VPU
+ * @vsi: driver structure allocated by VPU side and shared to AP side for
+ *	 control and info share
+ * @ctx: context for v4l2 layer integration
+ */
+struct venc_h264_inst {
+	void __iomem *hw_base;
+	struct mtk_vcodec_mem work_bufs[VENC_H264_VPU_WORK_BUF_MAX];
+	struct mtk_vcodec_mem pps_buf;
+	bool work_buf_allocated;
+	unsigned int frm_cnt;
+	unsigned int prepend_hdr;
+	struct venc_vpu_inst vpu_inst;
+	struct venc_h264_vsi *vsi;
+	struct mtk_vcodec_ctx *ctx;
+};
+
+static inline void h264_write_reg(struct venc_h264_inst *inst, u32 addr,
+				  u32 val)
+{
+	writel(val, inst->hw_base + addr);
+}
+
+static inline u32 h264_read_reg(struct venc_h264_inst *inst, u32 addr)
+{
+	return readl(inst->hw_base + addr);
+}
+
+static unsigned int h264_get_profile(struct venc_h264_inst *inst,
+				     unsigned int profile)
+{
+	switch (profile) {
+	case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+		return 66;
+	case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+		return 77;
+	case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
+		return 100;
+	case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+		mtk_vcodec_err(inst, "unsupported CONSTRAINED_BASELINE");
+		return 0;
+	case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
+		mtk_vcodec_err(inst, "unsupported EXTENDED");
+		return 0;
+	default:
+		mtk_vcodec_debug(inst, "unsupported profile %d", profile);
+		return 100;
+	}
+}
+
+static unsigned int h264_get_level(struct venc_h264_inst *inst,
+				   unsigned int level)
+{
+	switch (level) {
+	case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
+		mtk_vcodec_err(inst, "unsupported 1B");
+		return 0;
+	case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
+		return 10;
+	case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
+		return 11;
+	case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
+		return 12;
+	case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
+		return 13;
+	case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
+		return 20;
+	case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
+		return 21;
+	case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
+		return 22;
+	case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
+		return 30;
+	case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
+		return 31;
+	case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
+		return 32;
+	case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
+		return 40;
+	case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
+		return 41;
+	default:
+		mtk_vcodec_debug(inst, "unsupported level %d", level);
+		return 31;
+	}
+}
+
+static void h264_enc_free_work_buf(struct venc_h264_inst *inst)
+{
+	int i;
+
+	mtk_vcodec_debug_enter(inst);
+
+	/* Except the SKIP_FRAME buffers,
+	 * other buffers need to be freed by AP.
+	 */
+	for (i = 0; i < VENC_H264_VPU_WORK_BUF_MAX; i++) {
+		if (i != VENC_H264_VPU_WORK_BUF_SKIP_FRAME)
+			mtk_vcodec_mem_free(inst->ctx, &inst->work_bufs[i]);
+	}
+
+	mtk_vcodec_mem_free(inst->ctx, &inst->pps_buf);
+
+	mtk_vcodec_debug_leave(inst);
+}
+
+static int h264_enc_alloc_work_buf(struct venc_h264_inst *inst)
+{
+	int i;
+	int ret = 0;
+	struct venc_h264_vpu_buf *wb = inst->vsi->work_bufs;
+
+	mtk_vcodec_debug_enter(inst);
+
+	for (i = 0; i < VENC_H264_VPU_WORK_BUF_MAX; i++) {
+		/*
+		 * This 'wb' structure is set by VPU side and shared to AP for
+		 * buffer allocation and IO virtual addr mapping. For most of
+		 * the buffers, AP will allocate the buffer according to 'size'
+		 * field and store the IO virtual addr in 'iova' field. There
+		 * are two exceptions:
+		 * (1) RC_CODE buffer, it's pre-allocated in the VPU side, and
+		 * save the VPU addr in the 'vpua' field. The AP will translate
+		 * the VPU addr to the corresponding IO virtual addr and store
+		 * in 'iova' field for reg setting in VPU side.
+		 * (2) SKIP_FRAME buffer, it's pre-allocated in the VPU side,
+		 * and save the VPU addr in the 'vpua' field. The AP will
+		 * translate the VPU addr to the corresponding AP side virtual
+		 * address and do some memcpy access to move to bitstream buffer
+		 * assigned by v4l2 layer.
+		 */
+		inst->work_bufs[i].size = wb[i].size;
+		if (i == VENC_H264_VPU_WORK_BUF_SKIP_FRAME) {
+			inst->work_bufs[i].va = vpu_mapping_dm_addr(
+				inst->vpu_inst.dev, wb[i].vpua);
+			inst->work_bufs[i].dma_addr = 0;
+		} else {
+			ret = mtk_vcodec_mem_alloc(inst->ctx,
+						   &inst->work_bufs[i]);
+			if (ret) {
+				mtk_vcodec_err(inst,
+					       "cannot allocate buf %d", i);
+				goto err_alloc;
+			}
+			/*
+			 * This RC_CODE is pre-allocated by VPU and saved in VPU
+			 * addr. So we need use memcpy to copy RC_CODE from VPU
+			 * addr into IO virtual addr in 'iova' field for reg
+			 * setting in VPU side.
+			 */
+			if (i == VENC_H264_VPU_WORK_BUF_RC_CODE) {
+				void *tmp_va;
+
+				tmp_va = vpu_mapping_dm_addr(inst->vpu_inst.dev,
+							     wb[i].vpua);
+				memcpy(inst->work_bufs[i].va, tmp_va,
+				       wb[i].size);
+			}
+		}
+		wb[i].iova = inst->work_bufs[i].dma_addr;
+
+		mtk_vcodec_debug(inst,
+				 "work_buf[%d] va=0x%p iova=0x%p size=%zu",
+				 i, inst->work_bufs[i].va,
+				 (void *)inst->work_bufs[i].dma_addr,
+				 inst->work_bufs[i].size);
+	}
+
+	/* the pps_buf is used by AP side only */
+	inst->pps_buf.size = 128;
+	ret = mtk_vcodec_mem_alloc(inst->ctx, &inst->pps_buf);
+	if (ret) {
+		mtk_vcodec_err(inst, "cannot allocate pps_buf");
+		goto err_alloc;
+	}
+
+	mtk_vcodec_debug_leave(inst);
+
+	return ret;
+
+err_alloc:
+	h264_enc_free_work_buf(inst);
+
+	return ret;
+}
+
+static unsigned int h264_enc_wait_venc_done(struct venc_h264_inst *inst)
+{
+	unsigned int irq_status = 0;
+	struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)inst->ctx;
+
+	if (!mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED,
+					  WAIT_INTR_TIMEOUT_MS)) {
+		irq_status = ctx->irq_status;
+		mtk_vcodec_debug(inst, "irq_status %x <-", irq_status);
+	}
+	return irq_status;
+}
+
+static int h264_encode_sps(struct venc_h264_inst *inst,
+			   struct mtk_vcodec_mem *bs_buf,
+			   unsigned int *bs_size)
+{
+	int ret = 0;
+	unsigned int irq_status;
+
+	mtk_vcodec_debug_enter(inst);
+
+	ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_SPS, NULL,
+			     bs_buf, bs_size);
+	if (ret)
+		return ret;
+
+	irq_status = h264_enc_wait_venc_done(inst);
+	if (irq_status != MTK_VENC_IRQ_STATUS_SPS) {
+		mtk_vcodec_err(inst, "expect irq status %d",
+			       MTK_VENC_IRQ_STATUS_SPS);
+		return -EINVAL;
+	}
+
+	*bs_size = h264_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
+	mtk_vcodec_debug(inst, "bs size %d <-", *bs_size);
+
+	return ret;
+}
+
+static int h264_encode_pps(struct venc_h264_inst *inst,
+			   struct mtk_vcodec_mem *bs_buf,
+			   unsigned int *bs_size)
+{
+	int ret = 0;
+	unsigned int irq_status;
+
+	mtk_vcodec_debug_enter(inst);
+
+	ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_PPS, NULL,
+			     bs_buf, bs_size);
+	if (ret)
+		return ret;
+
+	irq_status = h264_enc_wait_venc_done(inst);
+	if (irq_status != MTK_VENC_IRQ_STATUS_PPS) {
+		mtk_vcodec_err(inst, "expect irq status %d",
+			       MTK_VENC_IRQ_STATUS_PPS);
+		return -EINVAL;
+	}
+
+	*bs_size = h264_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
+	mtk_vcodec_debug(inst, "bs size %d <-", *bs_size);
+
+	return ret;
+}
+
+static int h264_encode_header(struct venc_h264_inst *inst,
+			      struct mtk_vcodec_mem *bs_buf,
+			      unsigned int *bs_size)
+{
+	int ret = 0;
+	unsigned int bs_size_sps;
+	unsigned int bs_size_pps;
+
+	ret = h264_encode_sps(inst, bs_buf, &bs_size_sps);
+	if (ret)
+		return ret;
+
+	ret = h264_encode_pps(inst, &inst->pps_buf, &bs_size_pps);
+	if (ret)
+		return ret;
+
+	memcpy(bs_buf->va + bs_size_sps, inst->pps_buf.va, bs_size_pps);
+	*bs_size = bs_size_sps + bs_size_pps;
+
+	return ret;
+}
+
+static int h264_encode_frame(struct venc_h264_inst *inst,
+			     struct venc_frm_buf *frm_buf,
+			     struct mtk_vcodec_mem *bs_buf,
+			     unsigned int *bs_size)
+{
+	int ret = 0;
+	unsigned int irq_status;
+
+	mtk_vcodec_debug_enter(inst);
+
+	ret = vpu_enc_encode(&inst->vpu_inst, H264_BS_MODE_FRAME, frm_buf,
+			     bs_buf, bs_size);
+	if (ret)
+		return ret;
+
+	/*
+	 * skip frame case: The skip frame buffer is composed by vpu side only,
+	 * it does not trigger the hw, so skip the wait interrupt operation.
+	 */
+	if (inst->vpu_inst.state == VEN_IPI_MSG_ENC_STATE_SKIP) {
+		*bs_size = inst->vpu_inst.bs_size;
+		memcpy(bs_buf->va,
+		       inst->work_bufs[VENC_H264_VPU_WORK_BUF_SKIP_FRAME].va,
+		       *bs_size);
+		++inst->frm_cnt;
+		return ret;
+	}
+
+	irq_status = h264_enc_wait_venc_done(inst);
+	if (irq_status != MTK_VENC_IRQ_STATUS_FRM) {
+		mtk_vcodec_err(inst, "irq_status=%d failed", irq_status);
+		return -EIO;
+	}
+
+	*bs_size = h264_read_reg(inst, VENC_PIC_BITSTREAM_BYTE_CNT);
+
+	++inst->frm_cnt;
+	mtk_vcodec_debug(inst, "frm %d bs_size %d key_frm %d <-",
+			 inst->frm_cnt, *bs_size, inst->vpu_inst.is_key_frm);
+
+	return ret;
+}
+
+static void h264_encode_filler(struct venc_h264_inst *inst, void *buf,
+			       int size)
+{
+	unsigned char *p = buf;
+
+	if (size < H264_FILLER_MARKER_SIZE) {
+		mtk_vcodec_err(inst, "filler size too small %d", size);
+		return;
+	}
+
+	memcpy(p, h264_filler_marker, ARRAY_SIZE(h264_filler_marker));
+	size -= H264_FILLER_MARKER_SIZE;
+	p += H264_FILLER_MARKER_SIZE;
+	memset(p, 0xff, size);
+}
+
+static int h264_enc_init(struct mtk_vcodec_ctx *ctx, unsigned long *handle)
+{
+	int ret = 0;
+	struct venc_h264_inst *inst;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->ctx = ctx;
+	inst->vpu_inst.ctx = ctx;
+	inst->vpu_inst.dev = ctx->dev->vpu_plat_dev;
+	inst->vpu_inst.id = IPI_VENC_H264;
+	inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx, VENC_SYS);
+
+	mtk_vcodec_debug_enter(inst);
+
+	ret = vpu_enc_init(&inst->vpu_inst);
+
+	inst->vsi = (struct venc_h264_vsi *)inst->vpu_inst.vsi;
+
+	mtk_vcodec_debug_leave(inst);
+
+	if (ret)
+		kfree(inst);
+	else
+		(*handle) = (unsigned long)inst;
+
+	return ret;
+}
+
+static int h264_enc_encode(unsigned long handle,
+			   enum venc_start_opt opt,
+			   struct venc_frm_buf *frm_buf,
+			   struct mtk_vcodec_mem *bs_buf,
+			   struct venc_done_result *result)
+{
+	int ret = 0;
+	struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
+	struct mtk_vcodec_ctx *ctx = inst->ctx;
+
+	mtk_vcodec_debug(inst, "opt %d ->", opt);
+
+	enable_irq(ctx->dev->enc_irq);
+
+	switch (opt) {
+	case VENC_START_OPT_ENCODE_SEQUENCE_HEADER: {
+		unsigned int bs_size_hdr;
+
+		ret = h264_encode_header(inst, bs_buf, &bs_size_hdr);
+		if (ret)
+			goto encode_err;
+
+		result->bs_size = bs_size_hdr;
+		result->is_key_frm = false;
+		break;
+	}
+
+	case VENC_START_OPT_ENCODE_FRAME: {
+		int hdr_sz;
+		int hdr_sz_ext;
+		int filler_sz = 0;
+		const int bs_alignment = 128;
+		struct mtk_vcodec_mem tmp_bs_buf;
+		unsigned int bs_size_hdr;
+		unsigned int bs_size_frm;
+
+		if (!inst->prepend_hdr) {
+			ret = h264_encode_frame(inst, frm_buf, bs_buf,
+						&result->bs_size);
+			if (ret)
+				goto encode_err;
+			result->is_key_frm = inst->vpu_inst.is_key_frm;
+			break;
+		}
+
+		mtk_vcodec_debug(inst, "h264_encode_frame prepend SPS/PPS");
+
+		ret = h264_encode_header(inst, bs_buf, &bs_size_hdr);
+		if (ret)
+			goto encode_err;
+
+		hdr_sz = bs_size_hdr;
+		hdr_sz_ext = (hdr_sz & (bs_alignment - 1));
+		if (hdr_sz_ext) {
+			filler_sz = bs_alignment - hdr_sz_ext;
+			if (hdr_sz_ext + H264_FILLER_MARKER_SIZE > bs_alignment)
+				filler_sz += bs_alignment;
+			h264_encode_filler(inst, bs_buf->va + hdr_sz,
+					   filler_sz);
+		}
+
+		tmp_bs_buf.va = bs_buf->va + hdr_sz + filler_sz;
+		tmp_bs_buf.dma_addr = bs_buf->dma_addr + hdr_sz + filler_sz;
+		tmp_bs_buf.size = bs_buf->size - (hdr_sz + filler_sz);
+
+		ret = h264_encode_frame(inst, frm_buf, &tmp_bs_buf,
+					&bs_size_frm);
+		if (ret)
+			goto encode_err;
+
+		result->bs_size = hdr_sz + filler_sz + bs_size_frm;
+
+		mtk_vcodec_debug(inst, "hdr %d filler %d frame %d bs %d",
+				 hdr_sz, filler_sz, bs_size_frm,
+				 result->bs_size);
+
+		inst->prepend_hdr = 0;
+		result->is_key_frm = inst->vpu_inst.is_key_frm;
+		break;
+	}
+
+	default:
+		mtk_vcodec_err(inst, "venc_start_opt %d not supported", opt);
+		ret = -EINVAL;
+		break;
+	}
+
+encode_err:
+
+	disable_irq(ctx->dev->enc_irq);
+	mtk_vcodec_debug(inst, "opt %d <-", opt);
+
+	return ret;
+}
+
+static int h264_enc_set_param(unsigned long handle,
+			      enum venc_set_param_type type,
+			      struct venc_enc_param *enc_prm)
+{
+	int ret = 0;
+	struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
+
+	mtk_vcodec_debug(inst, "->type=%d", type);
+
+	switch (type) {
+	case VENC_SET_PARAM_ENC:
+		inst->vsi->config.input_fourcc = enc_prm->input_yuv_fmt;
+		inst->vsi->config.bitrate = enc_prm->bitrate;
+		inst->vsi->config.pic_w = enc_prm->width;
+		inst->vsi->config.pic_h = enc_prm->height;
+		inst->vsi->config.buf_w = enc_prm->buf_width;
+		inst->vsi->config.buf_h = enc_prm->buf_height;
+		inst->vsi->config.gop_size = enc_prm->gop_size;
+		inst->vsi->config.framerate = enc_prm->frm_rate;
+		inst->vsi->config.intra_period = enc_prm->intra_period;
+		inst->vsi->config.profile =
+			h264_get_profile(inst, enc_prm->h264_profile);
+		inst->vsi->config.level =
+			h264_get_level(inst, enc_prm->h264_level);
+		inst->vsi->config.wfd = 0;
+		ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
+		if (ret)
+			break;
+		if (inst->work_buf_allocated) {
+			h264_enc_free_work_buf(inst);
+			inst->work_buf_allocated = false;
+		}
+		ret = h264_enc_alloc_work_buf(inst);
+		if (ret)
+			break;
+		inst->work_buf_allocated = true;
+		break;
+
+	case VENC_SET_PARAM_PREPEND_HEADER:
+		inst->prepend_hdr = 1;
+		mtk_vcodec_debug(inst, "set prepend header mode");
+		break;
+
+	default:
+		ret = vpu_enc_set_param(&inst->vpu_inst, type, enc_prm);
+		break;
+	}
+
+	mtk_vcodec_debug_leave(inst);
+
+	return ret;
+}
+
+static int h264_enc_deinit(unsigned long handle)
+{
+	int ret = 0;
+	struct venc_h264_inst *inst = (struct venc_h264_inst *)handle;
+
+	mtk_vcodec_debug_enter(inst);
+
+	ret = vpu_enc_deinit(&inst->vpu_inst);
+
+	if (inst->work_buf_allocated)
+		h264_enc_free_work_buf(inst);
+
+	mtk_vcodec_debug_leave(inst);
+	kfree(inst);
+
+	return ret;
+}
+
+static struct venc_common_if venc_h264_if = {
+	h264_enc_init,
+	h264_enc_encode,
+	h264_enc_set_param,
+	h264_enc_deinit,
+};
+
+struct venc_common_if *get_h264_enc_comm_if(void);
+
+struct venc_common_if *get_h264_enc_comm_if(void)
+{
+	return &venc_h264_if;
+}
diff --git a/drivers/media/platform/mtk-vcodec/venc_drv_if.c b/drivers/media/platform/mtk-vcodec/venc_drv_if.c
index 77c39d2..c4c83e7 100644
--- a/drivers/media/platform/mtk-vcodec/venc_drv_if.c
+++ b/drivers/media/platform/mtk-vcodec/venc_drv_if.c
@@ -26,7 +26,7 @@
 #include "mtk_vcodec_enc_pm.h"
 #include "mtk_vpu.h"
 
-
+struct venc_common_if *get_h264_enc_comm_if(void);
 struct venc_common_if *get_vp8_enc_comm_if(void);
 
 int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
@@ -38,6 +38,8 @@ int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 		ctx->enc_if = get_vp8_enc_comm_if();
 		break;
 	case V4L2_PIX_FMT_H264:
+		ctx->enc_if = get_h264_enc_comm_if();
+		break;
 	default:
 		return -EINVAL;
 	}
-- 
1.7.9.5



From p.zabel at pengutronix.de  Tue May  3 03:17:50 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Tue, 03 May 2016 12:17:50 +0200
Subject: [PATCH 1/7] reset: add devm_reset_controller_register API
In-Reply-To: <1462099023-11819-2-git-send-email-yamada.masahiro@socionext.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
 <1462099023-11819-2-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462270670.3617.49.camel@pengutronix.de>

Hi Masahiro,

Am Sonntag, den 01.05.2016, 19:36 +0900 schrieb Masahiro Yamada:
> Add a device managed API for reset_controller_register().
> 
> This helps in reducing code in .remove callbacks and sometimes
> dropping .remove callbacks entirely.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Thank you for these patches. Except for the issue with the lpc18xx patch
they all look good to me.
If you don't mind, I'll drop the lpc18xx patch for now and apply the
others.

regards
Philipp



From p.zabel at pengutronix.de  Tue May  3 03:17:53 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Tue, 03 May 2016 12:17:53 +0200
Subject: [PATCH] reset: fix Kconfig menu to include reset drivers in
 sub-menu
In-Reply-To: <1462256992-31063-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462256992-31063-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462270673.3617.50.camel@pengutronix.de>

Am Dienstag, den 03.05.2016, 15:29 +0900 schrieb Masahiro Yamada:
> In "make menuconfig", reset drivers are currently lined up together
> with the reset sub-system menu, like this:
> 
>     -*- Reset Controller Support  ----
>     < > Hi6220 Reset Driver
> 
> (It also means, the menu "Reset Controller Support" is always empty.)

Unless ARCH_HISI is enabled it still will be empty.

> "Hi6220 Reset Driver" should go into the sub-menu of the
> "Reset Controller Support".
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> ---
> 
>  drivers/reset/Kconfig     | 4 ++++
>  drivers/reset/sti/Kconfig | 1 -
>  2 files changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index df37212..6a0b24b 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -12,5 +12,9 @@ menuconfig RESET_CONTROLLER
>  
>  	  If unsure, say no.
>  
> +if RESET_CONTROLLER
> +
>  source "drivers/reset/sti/Kconfig"
>  source "drivers/reset/hisilicon/Kconfig"
> +
> +endif
> diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig
> index f8c15a3..6131785 100644
> --- a/drivers/reset/sti/Kconfig
> +++ b/drivers/reset/sti/Kconfig
> @@ -2,7 +2,6 @@ if ARCH_STI
>  
>  config STI_RESET_SYSCFG
>  	bool
> -	select RESET_CONTROLLER
>  
>  config STIH415_RESET
>  	bool

Looks good to me. ARCH_STI already selects RESET_CONTROLLER and nothing
selects COMMON_RESET_HI6220.

regards
Philipp



From ldewangan at nvidia.com  Tue May  3 03:07:47 2016
From: ldewangan at nvidia.com (Laxman Dewangan)
Date: Tue, 3 May 2016 15:37:47 +0530
Subject: [PATCH 1/7] reset: add devm_reset_controller_register API
In-Reply-To: <1462099023-11819-2-git-send-email-yamada.masahiro@socionext.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
 <1462099023-11819-2-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <57287873.7040504@nvidia.com>


On Sunday 01 May 2016 04:06 PM, Masahiro Yamada wrote:
> Add a device managed API for reset_controller_register().
>
> This helps in reducing code in .remove callbacks and sometimes
> dropping .remove callbacks entirely.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
>


I liked it.
Acked-by: Laxman Dewangan <ldewangan at nvidia.com>


From eballetbo at gmail.com  Tue May  3 03:21:25 2016
From: eballetbo at gmail.com (Enric Balletbo Serra)
Date: Tue, 3 May 2016 12:21:25 +0200
Subject: [alsa-devel] [PATCH 1/2] ASoC: rockchip: i2s: separate capture
 and playback
In-Reply-To: <20160503104318.62739a91.john@metanate.com>
References: <1449657147-26959-1-git-send-email-john@metanate.com>
 <CAFqH_52C4JKno4uyt54UdWKAJKM4FPGRiQaQQ9_H-Mz1Cr+Hqg@mail.gmail.com>
 <20160430070049.GF14612@serenity.lan>
 <57282532.7000402@rock-chips.com>
 <CAFqH_50D5PQOkpCDefds3Nyktvitoe2Wx=YcXM2POox1ooO=0g@mail.gmail.com>
 <20160503104318.62739a91.john@metanate.com>
Message-ID: <CAFqH_518WDfBATtxYSbtPTdrV1MH=Y2UDBQNeCa2xZTiMp54zw@mail.gmail.com>

Hi John,

2016-05-03 11:43 GMT+02:00 John Keeping <john at metanate.com>:
> Hi Enric,
>
> On Tue, 3 May 2016 11:16:58 +0200, Enric Balletbo Serra wrote:
>> 2016-05-03 6:12 GMT+02:00 sugar <sugar.zhang at rock-chips.com>:
>> > On 4/30/2016 15:00, John Keeping Wrote:
>> >> On Fri, Apr 29, 2016 at 04:59:27PM +0200, Enric Balletbo Serra wrote:
>> >>>
>> >>> 2015-12-09 11:32 GMT+01:00 John Keeping <john at metanate.com>:
>> >>>>
>> >>>> If we only clear the tx/rx state when both are disabled it is not
>> >>>> possible to start/stop one multiple times while the other is running.
>> >>>> Since the two are independently controlled, treat them as such and
>> >>>> remove the false dependency between capture and playback.
>> >>>>
>> >>>> Signed-off-by: John Keeping <john at metanate.com>
>> >>>> ---
>> >>>>   sound/soc/rockchip/rockchip_i2s.c | 72
>> >>>> +++++++++++++++++----------------------
>> >>>>   1 file changed, 32 insertions(+), 40 deletions(-)
>> >>>>
>> >>>> diff --git a/sound/soc/rockchip/rockchip_i2s.c
>> >>>> b/sound/soc/rockchip/rockchip_i2s.c
>> >>>> index 83b1b9c..acc6225 100644
>> >>>> --- a/sound/soc/rockchip/rockchip_i2s.c
>> >>>> +++ b/sound/soc/rockchip/rockchip_i2s.c
>> >>>> @@ -82,8 +82,8 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev
>> >>>> *i2s, int on)
>> >>>>                                     I2S_DMACR_TDE_ENABLE,
>> >>>> I2S_DMACR_TDE_ENABLE);
>> >>>>
>> >>>>                  regmap_update_bits(i2s->regmap, I2S_XFER,
>> >>>> -                                  I2S_XFER_TXS_START |
>> >>>> I2S_XFER_RXS_START,
>> >>>> -                                  I2S_XFER_TXS_START |
>> >>>> I2S_XFER_RXS_START);
>> >>>> +                                  I2S_XFER_TXS_START,
>> >>>> +                                  I2S_XFER_TXS_START);
>> >>>>
>> >>>>                  i2s->tx_start = true;
>> >>>>          } else {
>> >>>> @@ -92,27 +92,23 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev
>> >>>> *i2s, int on)
>> >>>>                  regmap_update_bits(i2s->regmap, I2S_DMACR,
>> >>>>                                     I2S_DMACR_TDE_ENABLE,
>> >>>> I2S_DMACR_TDE_DISABLE);
>> >>>>
>> >>>> -               if (!i2s->rx_start) {
>> >>>> -                       regmap_update_bits(i2s->regmap, I2S_XFER,
>> >>>> -                                          I2S_XFER_TXS_START |
>> >>>> -                                          I2S_XFER_RXS_START,
>> >>>> -                                          I2S_XFER_TXS_STOP |
>> >>>> -                                          I2S_XFER_RXS_STOP);
>> >>>> +               regmap_update_bits(i2s->regmap, I2S_XFER,
>> >>>> +                                  I2S_XFER_TXS_START,
>> >>>> +                                  I2S_XFER_TXS_STOP);
>> >>>>
>> >>>> -                       regmap_update_bits(i2s->regmap, I2S_CLR,
>> >>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC,
>> >>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC);
>> >>>> +               regmap_update_bits(i2s->regmap, I2S_CLR,
>> >>>> +                                  I2S_CLR_TXC,
>> >>>> +                                  I2S_CLR_TXC);
>> >>>>
>> >>>> -                       regmap_read(i2s->regmap, I2S_CLR, &val);
>> >>>> +               regmap_read(i2s->regmap, I2S_CLR, &val);
>> >>>>
>> >>>> -                       /* Should wait for clear operation to finish */
>> >>>> -                       while (val) {
>> >>>> -                               regmap_read(i2s->regmap, I2S_CLR, &val);
>> >>>> -                               retry--;
>> >>>> -                               if (!retry) {
>> >>>> -                                       dev_warn(i2s->dev, "fail to
>> >>>> clear\n");
>> >>>> -                                       break;
>> >>>> -                               }
>> >>>> +               /* Should wait for clear operation to finish */
>> >>>> +               while (val & I2S_CLR_TXC) {
>> >>>> +                       regmap_read(i2s->regmap, I2S_CLR, &val);
>> >>>> +                       retry--;
>> >>>> +                       if (!retry) {
>> >>>> +                               dev_warn(i2s->dev, "fail to clear\n");
>> >>>> +                               break;
>> >>>>                          }
>> >>>>                  }
>> >>>>          }
>> >>>> @@ -128,8 +124,8 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev
>> >>>> *i2s, int on)
>> >>>>                                     I2S_DMACR_RDE_ENABLE,
>> >>>> I2S_DMACR_RDE_ENABLE);
>> >>>>
>> >>>>                  regmap_update_bits(i2s->regmap, I2S_XFER,
>> >>>> -                                  I2S_XFER_TXS_START |
>> >>>> I2S_XFER_RXS_START,
>> >>>> -                                  I2S_XFER_TXS_START |
>> >>>> I2S_XFER_RXS_START);
>> >>>> +                                  I2S_XFER_RXS_START,
>> >>>> +                                  I2S_XFER_RXS_START);
>> >>>>
>> >>>>                  i2s->rx_start = true;
>> >>>>          } else {
>> >>>> @@ -138,27 +134,23 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev
>> >>>> *i2s, int on)
>> >>>>                  regmap_update_bits(i2s->regmap, I2S_DMACR,
>> >>>>                                     I2S_DMACR_RDE_ENABLE,
>> >>>> I2S_DMACR_RDE_DISABLE);
>> >>>>
>> >>>> -               if (!i2s->tx_start) {
>> >>>> -                       regmap_update_bits(i2s->regmap, I2S_XFER,
>> >>>> -                                          I2S_XFER_TXS_START |
>> >>>> -                                          I2S_XFER_RXS_START,
>> >>>> -                                          I2S_XFER_TXS_STOP |
>> >>>> -                                          I2S_XFER_RXS_STOP);
>> >>>> +               regmap_update_bits(i2s->regmap, I2S_XFER,
>> >>>> +                                  I2S_XFER_RXS_START,
>> >>>> +                                  I2S_XFER_RXS_STOP);
>> >>>>
>> >>>> -                       regmap_update_bits(i2s->regmap, I2S_CLR,
>> >>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC,
>> >>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC);
>> >>>> +               regmap_update_bits(i2s->regmap, I2S_CLR,
>> >>>> +                                  I2S_CLR_RXC,
>> >>>> +                                  I2S_CLR_RXC);
>> >>>>
>> >>>> -                       regmap_read(i2s->regmap, I2S_CLR, &val);
>> >>>> +               regmap_read(i2s->regmap, I2S_CLR, &val);
>> >>>>
>> >>>> -                       /* Should wait for clear operation to finish */
>> >>>> -                       while (val) {
>> >>>> -                               regmap_read(i2s->regmap, I2S_CLR, &val);
>> >>>> -                               retry--;
>> >>>> -                               if (!retry) {
>> >>>> -                                       dev_warn(i2s->dev, "fail to
>> >>>> clear\n");
>> >>>> -                                       break;
>> >>>> -                               }
>> >>>> +               /* Should wait for clear operation to finish */
>> >>>> +               while (val & I2S_CLR_RXC) {
>> >>>> +                       regmap_read(i2s->regmap, I2S_CLR, &val);
>> >>>> +                       retry--;
>> >>>> +                       if (!retry) {
>> >>>> +                               dev_warn(i2s->dev, "fail to clear\n");
>> >>>> +                               break;
>> >>>>                          }
>> >>>>                  }
>> >>>>          }
>> >>>> --
>> >>>> 2.6.3.462.gbe2c914
>> >>>
>> >>>
>> >>> Using my Veyron Jerry Chromebook wiht latest kernel I found that the
>> >>> speakers doesn't work. Bisect points to this patch as the offending
>> >>> commit. However your changes looks reasonable the fact is that
>> >>> reverting the patch makes the audio work again on my device. I need to
>> >>> dig a bit more into the issue, but meanwhile, any idea on what is
>> >>> happening ? Can I ask which device did you test?
>> >>
>> >>
>> >> I tested this on a Radxa Rock2 square.  This change fixed an issue I
>> >> found when running separate processes for playback and recording (I was
>> >> testing with arecord and speaker-test IIRC) but I don't think that
>> >> should be relevant.  I just read through the patch again and I can't see
>> >> anything obviously wrong so I'm afraid I don't have any idea what's
>> >> causing the problem you're seeing.
>> >>
>> > Do you have test playback/capture at the same time? I think you may
>> > reproduce this issue if you do as follows:
>> >
>> > step 1: tinyplay test.wav -D 0 -d 0 -p 1024 -n 4 &
>> > step 2: tinycap r.wav -D 0 -d 0 -p 1024 -n 4 &
>> >
>> > you will find that there is no music now.
>> >
>> > because of this problem, we enable tx/rx at the same time to WA this issue.
>> >
>>
>> I can confirm that reverting John's patch audio playback/capture at
>> the same time works on my Veyron Jerry Chromebook.
>
> Have you tried stopping one of the processes and then starting it again
> (without touching the other process)?  That's the case that was broken
> for me without this patch.
>

I  just tried that and it works on my platform. Meanwhile I reproduced
a song I recorded two wavs.

> I have had a quick look through the code I'm using and I noticed that I
> have another change that hasn't been sent upstream, which marks the
> I2S_FIFOLR register as volatile in rockchip_i2s_volatile_reg():
>

Unfortunately that didn't help, I hear nothing from the speakers :(

I have a Radxa Rock2 Square board, by chance, do you have a git tree
containing the patches to enable the i2s sound for radxa so I can
reproduce both here? At least the codec is not upstreamed, I guess.

> -- >8 --
> Subject: [PATCH] ASoC: rockchip: i2s: mark FIFOLR register volatile
>
> The FIFO levels will be updated by the device so they should not be
> cached.
>
> Signed-off-by: John Keeping <john at metanate.com>
> ---
>  sound/soc/rockchip/rockchip_i2s.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
> index d78f4c925b02..b517d8abcc40 100644
> --- a/sound/soc/rockchip/rockchip_i2s.c
> +++ b/sound/soc/rockchip/rockchip_i2s.c
> @@ -434,6 +434,7 @@ static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg)
>         switch (reg) {
>         case I2S_INTSR:
>         case I2S_CLR:
> +       case I2S_FIFOLR:
>                 return true;
>         default:
>                 return false;
> -- 8< --
>
>
> Regards,
> John


From rmk at arm.linux.org.uk  Tue May  3 03:21:18 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:21:18 +0100
Subject: [PATCH kexec-tools 03/32] kdump: actually write out the memory
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXSA-0004hB-Ix@e0050434b2927.dyn.arm.linux.org.uk>

Actually write out the memory rather than writing the notes a second
time.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kdump/kdump.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kdump/kdump.c b/kdump/kdump.c
index 99a1789..1f5b984 100644
--- a/kdump/kdump.c
+++ b/kdump/kdump.c
@@ -300,7 +300,7 @@ int main(int argc, char **argv)
 	for(i = 0; i < ehdr->e_phnum; i++) {
 		unsigned long long offset, size;
 		size_t wsize;
-		if (phdr[i].p_type != PT_NOTE) {
+		if (phdr[i].p_type == PT_NOTE) {
 			continue;
 		}
 		offset = phdr[i].p_offset;
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:21:23 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:21:23 +0100
Subject: [PATCH kexec-tools 04/32] kdump: fix kdump mapping
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXSF-0004hH-Oo@e0050434b2927.dyn.arm.linux.org.uk>

When kdump tries to map the program header, it fails to take account
of ehdr->e_phoff being an offset from the start of the ELF "file",
which causes:

Cannot mmap /dev/mem offset: 64 size: 392: Invalid argument

Ensure that we take account of the start address when mapping this.

This fix has been extracted from a larger patch by Vitaly Andrianov
adding support for Keystone 2.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kdump/kdump.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kdump/kdump.c b/kdump/kdump.c
index 1f5b984..34d2149 100644
--- a/kdump/kdump.c
+++ b/kdump/kdump.c
@@ -284,7 +284,8 @@ int main(int argc, char **argv)
 	}
 	
 	/* Get the program header */
-	phdr = map_addr(fd, sizeof(*phdr)*(ehdr->e_phnum), ehdr->e_phoff);
+	phdr = map_addr(fd, sizeof(*phdr)*(ehdr->e_phnum), 
+			start_addr + ehdr->e_phoff);
 
 	/* Collect up the notes */
 	note_bytes = 0;
-- 
1.9.1



From marc.zyngier at arm.com  Tue May  3 03:21:36 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 11:21:36 +0100
Subject: [PATCH v2 46/54] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <1461861973-26464-47-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-47-git-send-email-andre.przywara@arm.com>
Message-ID: <57287BB0.7000709@arm.com>

On 28/04/16 17:46, Andre Przywara wrote:
> Using the VMCR accessors we provide access to GIC CPU interface state
> to userland by wiring it up to the existing userland interface.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-kvm-device.c | 72 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 71 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index 38260ae..eaf5c1d 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -17,8 +17,11 @@
>  #include <kvm/vgic/vgic.h>
>  #include <linux/uaccess.h>
>  #include <asm/kvm_mmu.h>
> +#include <linux/irqchip/arm-gic.h>
>  #include "vgic.h"
>  
> +#define GICC_ARCH_VERSION_V2		0x2
> +
>  /* common helpers */
>  
>  static int vgic_ioaddr_overlap(struct kvm *kvm)
> @@ -252,6 +255,69 @@ void kvm_register_vgic_device(unsigned long type)
>  	}
>  }
>  
> +static u32 vgic_read_vcpuif(struct kvm_vcpu *vcpu, int offset)
> +{
> +	struct vgic_vmcr vmcr;
> +	u32 *field;
> +
> +	switch (offset) {
> +	case GIC_CPU_CTRL:
> +		field = &vmcr.ctlr;
> +		break;
> +	case GIC_CPU_PRIMASK:
> +		field = &vmcr.pmr;
> +		break;
> +	case GIC_CPU_BINPOINT:
> +		field = &vmcr.bpr;
> +		break;
> +	case GIC_CPU_ALIAS_BINPOINT:
> +		field = &vmcr.abpr;
> +		break;
> +	case GIC_CPU_IDENT:
> +		return (PRODUCT_ID_KVM << 20) |
> +		       (GICC_ARCH_VERSION_V2 << 16) |
> +		       (IMPLEMENTER_ARM << 0);
> +	default:
> +		return 0;
> +	}
> +
> +	vgic_get_vmcr(vcpu, &vmcr);
> +
> +	return *field;
> +}
> +
> +static bool vgic_write_vcpuif(struct kvm_vcpu *vcpu, int offset, u32 value)
> +{
> +	struct vgic_vmcr vmcr;
> +	u32 *field;
> +
> +	switch (offset) {
> +	case GIC_CPU_CTRL:
> +		field = &vmcr.ctlr;
> +		break;
> +	case GIC_CPU_PRIMASK:
> +		field = &vmcr.pmr;
> +		break;
> +	case GIC_CPU_BINPOINT:
> +		field = &vmcr.bpr;
> +		break;
> +	case GIC_CPU_ALIAS_BINPOINT:
> +		field = &vmcr.abpr;
> +		break;
> +	default:
> +		return false;
> +	}
> +
> +	vgic_get_vmcr(vcpu, &vmcr);
> +	if (*field == value)
> +		return false;
> +
> +	*field = value;
> +	vgic_set_vmcr(vcpu, &vmcr);
> +
> +	return true;
> +}
> +
>  /** vgic_attr_regs_access: allows user space to read/write VGIC registers
>   *
>   * @dev: kvm device handle
> @@ -300,7 +366,11 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
>  
>  	switch (attr->group) {
>  	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> -		ret = -EINVAL;
> +		ret = 0;
> +		if (is_write)
> +			vgic_write_vcpuif(vcpu, addr, *reg);
> +		else
> +			*reg = vgic_read_vcpuif(vcpu, addr);
>  		break;
>  	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>  		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
> 

Shouldn't we have this implemented as an MMIO table, and moved to the
vgic-v2-mmio.c file?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From rmk at arm.linux.org.uk  Tue May  3 03:21:28 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:21:28 +0100
Subject: [PATCH kexec-tools 05/32] arm: fix kdump to work on LPAE systems
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXSK-0004hN-V7@e0050434b2927.dyn.arm.linux.org.uk>

We need to use 64-bit file IO when mapping system memory and the core
dump file as we may be running on a LPAE system, otherwise we risk
mapping memory we shouldn't, and causing a kernel oops:

Unhandled fault: asynchronous external abort (0x211) at 0x00000000
pgd = edd2c740
[00000000] *pgd=82ec98003, *pmd=82dcd2003, *pte=00000000

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/Makefile | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kexec/arch/arm/Makefile b/kexec/arch/arm/Makefile
index 38137d7..60e433a 100644
--- a/kexec/arch/arm/Makefile
+++ b/kexec/arch/arm/Makefile
@@ -18,6 +18,9 @@ libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%)
 
 arm_CPPFLAGS = -I$(srcdir)/kexec/libfdt
 
+# We want 64-bit file IO for kdump to work correctly on LPAE systems
+arm_CPPFLAGS += -D_FILE_OFFSET_BITS=64
+
 arm_KEXEC_SRCS += $(libfdt_SRCS)
 
 arm_UIMAGE = kexec/kexec-uImage.c
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:21:39 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:21:39 +0100
Subject: [PATCH kexec-tools 07/32] kexec: fix warnings caused by selecting
 64-bit file IO on 32-bit platforms
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXSV-0004hZ-CH@e0050434b2927.dyn.arm.linux.org.uk>

Fix warnings caused by selecting 64-bit file IO on 32-bit platforms.

kexec/kexec.c:710:2: warning: format '%lx' expects argument of type 'long unsigned int', but argument 4 has type 'off_t' [-Wformat]
kexec/zlib.c:63:4: warning: format '%ld' expects argument of type 'long int', but argument 4 has type 'off_t' [-Wformat]
kexec/kexec-uImage.c:85:3: warning: format '%ld' expects argument of type 'long
int', but argument 2 has type 'off_t' [-Wformat]

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/kexec-uImage.c | 3 ++-
 kexec/kexec.c        | 4 ++--
 kexec/zlib.c         | 4 ++--
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/kexec/kexec-uImage.c b/kexec/kexec-uImage.c
index 9df601b..5e24629 100644
--- a/kexec/kexec-uImage.c
+++ b/kexec/kexec-uImage.c
@@ -82,7 +82,8 @@ int uImage_probe(const unsigned char *buf, off_t len, unsigned int arch)
 	if (be32_to_cpu(header.ih_size) > len - sizeof(header)) {
 		printf("uImage header claims that image has %d bytes\n",
 				be32_to_cpu(header.ih_size));
-		printf("we read only %ld bytes.\n", len - sizeof(header));
+		printf("we read only %lld bytes.\n",
+		       (long long)len - sizeof(header));
 		return -1;
 	}
 #ifdef HAVE_LIBZ
diff --git a/kexec/kexec.c b/kexec/kexec.c
index f0bd527..500e5a9 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -707,8 +707,8 @@ static int my_load(const char *type, int fileind, int argc, char **argv,
 	/* slurp in the input kernel */
 	kernel_buf = slurp_decompress_file(kernel, &kernel_size);
 
-	dbgprintf("kernel: %p kernel_size: 0x%lx\n",
-		  kernel_buf, kernel_size);
+	dbgprintf("kernel: %p kernel_size: %#llx\n",
+		  kernel_buf, (unsigned long long)kernel_size);
 
 	if (get_memory_ranges(&info.memory_range, &info.memory_ranges,
 		info.kexec_flags) < 0 || info.memory_ranges == 0) {
diff --git a/kexec/zlib.c b/kexec/zlib.c
index 7170ac3..95b6080 100644
--- a/kexec/zlib.c
+++ b/kexec/zlib.c
@@ -60,8 +60,8 @@ char *zlib_decompress_file(const char *filename, off_t *r_size)
 			if ((errno == EINTR) || (errno == EAGAIN))
 				continue;
 			_gzerror(fp, &errnum, &msg);
-			dbgprintf("Read on %s of %ld bytes failed: %s\n",
-					filename, (allocated - size) + 0UL, msg);
+			dbgprintf("Read on %s of %d bytes failed: %s\n",
+				  filename, (int)(allocated - size), msg);
 			size = 0;
 			goto fail;
 		}
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:21:44 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:21:44 +0100
Subject: [PATCH kexec-tools 08/32] kexec: add max_size to memory_ranges
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXSa-0004hf-Iz@e0050434b2927.dyn.arm.linux.org.uk>

Many implementations statically allocate the memory range array, which
therefore will have a maximum allowable size.  Add this information to
the memory_ranges structure, so we don't have to carry it around.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/kexec.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/kexec/kexec.h b/kexec/kexec.h
index c02ac8f..9194f1c 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -142,6 +142,7 @@ struct memory_range {
 
 struct memory_ranges {
         unsigned int size;
+	unsigned int max_size;
         struct memory_range *ranges;
 };
 
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:21:49 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:21:49 +0100
Subject: [PATCH kexec-tools 09/32] kexec: phys_to_virt() must take unsigned
 long long
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXSf-0004hl-PC@e0050434b2927.dyn.arm.linux.org.uk>

crashdump-elf.c passes unsigned long long addresses into phys_to_virt()
so make phys_to_virt() accept such addresses without truncating them.
This is important for ARM LPAE systems.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/phys_to_virt.c | 2 +-
 kexec/crashdump.h             | 2 +-
 kexec/phys_to_virt.c          | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/kexec/arch/arm/phys_to_virt.c b/kexec/arch/arm/phys_to_virt.c
index bcced52..c2fe2ea 100644
--- a/kexec/arch/arm/phys_to_virt.c
+++ b/kexec/arch/arm/phys_to_virt.c
@@ -14,7 +14,7 @@
  * http://lists.arm.linux.org.uk/lurker/message/20010723.185051.94ce743c.en.html
  */
 unsigned long
-phys_to_virt(struct crash_elf_info *elf_info, unsigned long paddr)
+phys_to_virt(struct crash_elf_info *elf_info, unsigned long long paddr)
 {
 	return paddr + elf_info->page_offset - phys_offset;
 }
diff --git a/kexec/crashdump.h b/kexec/crashdump.h
index 95f1f0c..96219a8 100644
--- a/kexec/crashdump.h
+++ b/kexec/crashdump.h
@@ -55,7 +55,7 @@ int crash_create_elf64_headers(struct kexec_info *info,
 unsigned long crash_architecture(struct crash_elf_info *elf_info);
 
 unsigned long phys_to_virt(struct crash_elf_info *elf_info,
-			   unsigned long paddr);
+			   unsigned long long paddr);
 
 unsigned long xen_architecture(struct crash_elf_info *elf_info);
 int xen_get_nr_phys_cpus(void);
diff --git a/kexec/phys_to_virt.c b/kexec/phys_to_virt.c
index 91b6d01..5e8c4e3 100644
--- a/kexec/phys_to_virt.c
+++ b/kexec/phys_to_virt.c
@@ -10,7 +10,7 @@
  * their own implementation.
  */
 unsigned long
-phys_to_virt(struct crash_elf_info *elf_info, unsigned long paddr)
+phys_to_virt(struct crash_elf_info *elf_info, unsigned long long paddr)
 {
 	return paddr + elf_info->page_offset;
 }
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:21:55 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:21:55 +0100
Subject: [PATCH kexec-tools 10/32] kexec: add generic helper to add to
 memory_regions
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXSl-0004hr-0T@e0050434b2927.dyn.arm.linux.org.uk>

Add a helper to add a memory range to a memory_regions array.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/Makefile      |  4 ++++
 kexec/mem_regions.c | 30 ++++++++++++++++++++++++++++++
 kexec/mem_regions.h |  9 +++++++++
 3 files changed, 43 insertions(+)
 create mode 100644 kexec/mem_regions.c
 create mode 100644 kexec/mem_regions.h

diff --git a/kexec/Makefile b/kexec/Makefile
index a758b4a..e2aee84 100644
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -69,6 +69,10 @@ dist				+= kexec/fs2dt.c kexec/fs2dt.h
 $(ARCH)_FS2DT			=
 KEXEC_SRCS			+= $($(ARCH)_FS2DT)
 
+dist				+= kexec/mem_regions.c kexec/mem_regions.h
+$(ARCH)_MEM_REGIONS		=
+KEXEC_SRCS			+= $($(ARCH)_MEM_REGIONS)
+
 include $(srcdir)/kexec/arch/alpha/Makefile
 include $(srcdir)/kexec/arch/arm/Makefile
 include $(srcdir)/kexec/arch/i386/Makefile
diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c
new file mode 100644
index 0000000..a4952ff
--- /dev/null
+++ b/kexec/mem_regions.c
@@ -0,0 +1,30 @@
+#include "kexec.h"
+#include "mem_regions.h"
+
+/**
+ * mem_regions_add() - add a memory region to a set of ranges
+ * @ranges: ranges to add the memory region to
+ * @max: maximum number of entries in memory region
+ * @base: base address of memory region
+ * @length: length of memory region in bytes
+ * @type: type of memory region
+ *
+ * Add the memory region to the set of ranges, and return %0 if successful,
+ * or %-1 if we ran out of space.
+ */
+int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
+                    unsigned long long length, int type)
+{
+	struct memory_range *range;
+
+	if (ranges->size >= ranges->max_size)
+		return -1;
+
+	range = ranges->ranges + ranges->size++;
+	range->start = base;
+	range->end = base + length - 1;
+	range->type = type;
+
+	return 0;
+}
+
diff --git a/kexec/mem_regions.h b/kexec/mem_regions.h
new file mode 100644
index 0000000..b9cfba1
--- /dev/null
+++ b/kexec/mem_regions.h
@@ -0,0 +1,9 @@
+#ifndef MEM_REGIONS_H
+#define MEM_REGIONS_H
+
+struct memory_ranges;
+
+int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
+                    unsigned long long length, int type);
+
+#endif
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:22:00 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:22:00 +0100
Subject: [PATCH kexec-tools 11/32] kexec: add mem_regions sorting
 implementation
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXSq-0004hx-8H@e0050434b2927.dyn.arm.linux.org.uk>

Add a mem_regions sorting implementation taken from the arm code.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/mem_regions.c | 27 +++++++++++++++++++++++++++
 kexec/mem_regions.h |  2 ++
 2 files changed, 29 insertions(+)

diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c
index a4952ff..804984a 100644
--- a/kexec/mem_regions.c
+++ b/kexec/mem_regions.c
@@ -1,6 +1,33 @@
+#include <stdlib.h>
+
 #include "kexec.h"
 #include "mem_regions.h"
 
+static int mem_range_cmp(const void *a1, const void *a2)
+{
+	const struct memory_range *r1 = a1;
+	const struct memory_range *r2 = a2;
+
+	if (r1->start > r2->start)
+		return 1;
+	if (r1->start < r2->start)
+		return -1;
+
+	return 0;
+}
+
+/**
+ * mem_regions_sort() - sort ranges into ascending address order
+ * @ranges: ranges to sort
+ *
+ * Sort the memory regions into ascending address order.
+ */
+void mem_regions_sort(struct memory_ranges *ranges)
+{
+	qsort(ranges->ranges, ranges->size, sizeof(ranges->ranges),
+	      mem_range_cmp);
+}
+
 /**
  * mem_regions_add() - add a memory region to a set of ranges
  * @ranges: ranges to add the memory region to
diff --git a/kexec/mem_regions.h b/kexec/mem_regions.h
index b9cfba1..da7b5e8 100644
--- a/kexec/mem_regions.h
+++ b/kexec/mem_regions.h
@@ -3,6 +3,8 @@
 
 struct memory_ranges;
 
+void mem_regions_sort(struct memory_ranges *ranges);
+
 int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
                     unsigned long long length, int type);
 
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:22:05 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:22:05 +0100
Subject: [PATCH kexec-tools 12/32] kexec: add helper to exlude a region from a
 set of memory ranges
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXSv-0004i3-Gi@e0050434b2927.dyn.arm.linux.org.uk>

Add a helper to exclude a region from a set of memory ranges.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/mem_regions.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 kexec/mem_regions.h |  4 ++++
 2 files changed, 59 insertions(+)

diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c
index 804984a..c6ba942 100644
--- a/kexec/mem_regions.c
+++ b/kexec/mem_regions.c
@@ -29,6 +29,61 @@ void mem_regions_sort(struct memory_ranges *ranges)
 }
 
 /**
+ * mem_regions_exclude() - excludes a memory region from a set of memory ranges
+ * @ranges: memory ranges to exclude the region from
+ * @range: memory range to exclude
+ *
+ * Exclude a memory region from a set of memory ranges.  We assume that
+ * the region to be excluded is either wholely located within one of the
+ * memory ranges, or not at all.
+ */
+int mem_regions_exclude(struct memory_ranges *ranges,
+			const struct memory_range *range)
+{
+	int i;
+
+	for (i = 0; i < ranges->size; i++) {
+		struct memory_range *r = ranges->ranges + i;
+
+		/*
+		 * We assume that crash area is fully contained in
+		 * some larger memory area.
+		 */
+		if (r->start <= range->start && r->end >= range->end) {
+			if (r->start == range->start) {
+				/* Shrink the start of this memory range */
+				r->start = range->end + 1;
+			} else if (r->end == range->end) {
+				/* Shrink the end of this memory range */
+				r->end = range->start - 1;
+			} else {
+				struct memory_range *new;
+
+				/*
+				 * Split this area into 2 smaller ones and
+				 * remove excluded range from between. First
+				 * create new entry for the remaining area.
+				 */
+				if (ranges->size >= ranges->max_size)
+					return -1;
+
+				new = ranges->ranges + ranges->size++;
+				new->start = range->end + 1;
+				new->end = r->end;
+
+				/*
+				 * Update this area to end before excluded
+				 * range.
+				 */
+				r->end = range->start - 1;
+				break;
+			}
+		}
+	}
+	return 0;
+}
+
+/**
  * mem_regions_add() - add a memory region to a set of ranges
  * @ranges: ranges to add the memory region to
  * @max: maximum number of entries in memory region
diff --git a/kexec/mem_regions.h b/kexec/mem_regions.h
index da7b5e8..ae9e972 100644
--- a/kexec/mem_regions.h
+++ b/kexec/mem_regions.h
@@ -2,9 +2,13 @@
 #define MEM_REGIONS_H
 
 struct memory_ranges;
+struct memory_range;
 
 void mem_regions_sort(struct memory_ranges *ranges);
 
+int mem_regions_exclude(struct memory_ranges *ranges,
+			const struct memory_range *range);
+
 int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
                     unsigned long long length, int type);
 
-- 
1.9.1



From vladimir.murzin at arm.com  Tue May  3 03:22:17 2016
From: vladimir.murzin at arm.com (Vladimir Murzin)
Date: Tue, 3 May 2016 11:22:17 +0100
Subject: [PATCH v2 0/3] ARM: nommu: R-class fixes
In-Reply-To: <1461862316-9877-1-git-send-email-vladimir.murzin@arm.com>
References: <1461862316-9877-1-git-send-email-vladimir.murzin@arm.com>
Message-ID: <57287BD9.6090907@arm.com>

On 28/04/16 17:51, Vladimir Murzin wrote:
> Small set of fixes discovered with R-class cores.
> 
> Jean-Philippe Brucker (2):
>   ARM: nommu: fix PMSAv7 setup
>   ARM: nommu: change memory reserve for the vectors
> 
> Vladimir Murzin (1):
>   ARM: domain: move {set,get}_domain under config guard
> 
>  arch/arm/include/asm/domain.h |   11 +++++++++++
>  arch/arm/kernel/head-nommu.S  |    2 +-
>  arch/arm/mm/nommu.c           |   15 ++++++++-------
>  3 files changed, 20 insertions(+), 8 deletions(-)
> 

Russell, any objection to get it into patch tracker?

Thanks
Vladimir


From rmk at arm.linux.org.uk  Tue May  3 03:22:10 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:22:10 +0100
Subject: [PATCH kexec-tools 13/32] arm: fix pointer signedness warning in
 kexec-uImage-arm.c
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXT0-0004i9-Nv@e0050434b2927.dyn.arm.linux.org.uk>

kexec/arch/arm/kexec-uImage-arm.c: In function 'uImage_arm_probe':
kexec/arch/arm/kexec-uImage-arm.c:14:2: warning: pointer targets in passing argument 1 of 'uImage_probe_kernel' differ in signedness [-Wpointer-sign]

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/kexec-uImage-arm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kexec/arch/arm/kexec-uImage-arm.c b/kexec/arch/arm/kexec-uImage-arm.c
index 03c2f4d..8e0a9ac 100644
--- a/kexec/arch/arm/kexec-uImage-arm.c
+++ b/kexec/arch/arm/kexec-uImage-arm.c
@@ -11,7 +11,8 @@
 
 int uImage_arm_probe(const char *buf, off_t len)
 {
-	return uImage_probe_kernel(buf, len, IH_ARCH_ARM);
+	return uImage_probe_kernel((const unsigned char *)buf, len,
+				   IH_ARCH_ARM);
 }
 
 int uImage_arm_load(int argc, char **argv, const char *buf, off_t len,
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:21:08 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:21:08 +0100
Subject: [PATCH kexec-tools 01/32] kdump: mmap() and munmap() only work on
 page-aligned quantites
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXS0-0004gz-5a@e0050434b2927.dyn.arm.linux.org.uk>

The man page for mmap() and munmap() says that mmap() and munmap()
only works for page-aligned addresses, sizes and offsets.  Arrange
to give these interfaces what they want.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kdump/kdump.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/kdump/kdump.c b/kdump/kdump.c
index 821ee7c..3247a54 100644
--- a/kdump/kdump.c
+++ b/kdump/kdump.c
@@ -25,22 +25,35 @@
 #define MAP_WINDOW_SIZE (64*1024*1024)
 #define DEV_MEM "/dev/mem"
 
+#define ALIGN_MASK(x,y) (((x) + (y)) & ~(y))
+#define ALIGN(x,y)	ALIGN_MASK(x, (y) - 1)
+
 static void *map_addr(int fd, unsigned long size, off_t offset)
 {
+	unsigned long page_size = getpagesize();
+	unsigned long map_offset = offset & (page_size - 1);
+	size_t len = ALIGN(size + map_offset, page_size);
 	void *result;
-	result = mmap(0, size, PROT_READ, MAP_SHARED, fd, offset);
+
+	result = mmap(0, len, PROT_READ, MAP_SHARED, fd, offset - map_offset);
 	if (result == MAP_FAILED) {
 		fprintf(stderr, "Cannot mmap " DEV_MEM " offset: %llu size: %lu: %s\n",
 			(unsigned long long)offset, size, strerror(errno));
 		exit(5);
 	}
-	return result;
+	return result + map_offset;
 }
 
 static void unmap_addr(void *addr, unsigned long size)
 {
+	unsigned long page_size = getpagesize();
+	unsigned long map_offset = (uintptr_t)addr & (page_size - 1);
+	size_t len = ALIGN(size + map_offset, page_size);
 	int ret;
-	ret = munmap(addr, size);
+
+	addr -= map_offset;
+
+	ret = munmap(addr, len);
 	if (ret < 0) {
 		fprintf(stderr, "munmap failed: %s\n",
 			strerror(errno));
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:21:13 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:21:13 +0100
Subject: [PATCH kexec-tools 02/32] kdump: fix multiple program header entries
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXS5-0004h5-Cb@e0050434b2927.dyn.arm.linux.org.uk>

generate_new_headers() forgot to increment the program header pointer
after adding each program header from the kexec template. Fix it to
increment it correctly.

Without this, the program headers contain only the last entry, which
means we will be missing most of the kernel image in the dump.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kdump/kdump.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/kdump/kdump.c b/kdump/kdump.c
index 3247a54..99a1789 100644
--- a/kdump/kdump.c
+++ b/kdump/kdump.c
@@ -192,6 +192,7 @@ static void *generate_new_headers(
 		}
 		memcpy(nphdr, &phdr[i], sizeof(*nphdr));
 		nphdr->p_offset = offset;
+		nphdr++;
 		offset += phdr[i].p_filesz;
 	}
 	
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May  3 03:25:39 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 3 May 2016 19:25:39 +0900
Subject: [PATCH 3/7] reset: lpc18xx: use devm_reset_controller_register()
In-Reply-To: <1462266344.3617.12.camel@pengutronix.de>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
 <1462099023-11819-4-git-send-email-yamada.masahiro@socionext.com>
 <1462177581.3933.7.camel@pengutronix.de>
 <CAK7LNAQ5LztGBbHCQxfLyWT7c_kWL=zpdKfkC9vsOKw95XL_Yw@mail.gmail.com>
 <1462266344.3617.12.camel@pengutronix.de>
Message-ID: <CAK7LNAQga-dCmAWevKMQx2DBzGim8DmNyeCxj4n5q-SjEapd+Q@mail.gmail.com>

Hi Philipp,

2016-05-03 18:05 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> Am Dienstag, den 03.05.2016, 00:52 +0900 schrieb Masahiro Yamada:
>> 2016-05-02 17:26 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
>> > Am Sonntag, den 01.05.2016, 19:36 +0900 schrieb Masahiro Yamada:
>> >> Use devm_reset_controller_register() for the reset controller
>> >> registration and remove the unregister call from the .remove callback.
>> >>
>> >> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
>> >> ---
>> >>
>> >>  drivers/reset/reset-lpc18xx.c | 4 +---
>> >>  1 file changed, 1 insertion(+), 3 deletions(-)
>> >>
>> >> diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c
>> >> index 3b8a4f5..dd4f27e 100644
>> >> --- a/drivers/reset/reset-lpc18xx.c
>> >> +++ b/drivers/reset/reset-lpc18xx.c
>> >> @@ -199,7 +199,7 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
>> >>
>> >>       platform_set_drvdata(pdev, rc);
>> >>
>> >> -     ret = reset_controller_register(&rc->rcdev);
>> >> +     ret = devm_reset_controller_register(&pdev->dev, &rc->rcdev);
>> >>       if (ret) {
>> >>               dev_err(&pdev->dev, "unable to register device\n");
>> >>               goto dis_clks;
>> >> @@ -229,8 +229,6 @@ static int lpc18xx_rgu_remove(struct platform_device *pdev)
>> >>       if (ret)
>> >>               dev_warn(&pdev->dev, "failed to unregister restart handler\n");
>> >>
>> >> -     reset_controller_unregister(&rc->rcdev);
>> >> -
>> >>       clk_disable_unprepare(rc->clk_delay);
>> >>       clk_disable_unprepare(rc->clk_reg);
>> >>
>> >
>> > Hmm, would this patch theoretically allow a window between the calls to
>> > clk_disable_unprepare(clk_reg) and devm_reset_controller_release() where
>> > reset_control_get() + reset_control_(de)assert() would access unclocked
>> > registers?
>>
>> This is not clear to me.
>>
>> Why reset_control_get() + reset_control_(de)assert() would happen here?
>
> I suppose on a non-SMP device, without parallel probing this can't
> really happen in practice.
> It still seems weird that suddenly we disable the clocks before
> unregistering the reset controller instead of afterwards.
>

I still do not understand what you mean.

This patch moves the reset_controller_unregister() call
after clk_disable_unprepare().


But, reset_controller_unregister() is just a manipulation of a liked list.
It does not trigger any hardware access.

Am I wrong?

void reset_controller_unregister(struct reset_controller_dev *rcdev)
{
        mutex_lock(&reset_controller_list_mutex);
        list_del(&rcdev->list);
        mutex_unlock(&reset_controller_list_mutex);
}



-- 
Best Regards
Masahiro Yamada


From k.kozlowski at samsung.com  Tue May  3 03:25:51 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 3 May 2016 12:25:51 +0200
Subject: [PATCH v9 00/20] PM / devferq: Add generic exynos bus frequency
 driver and new passive governor
In-Reply-To: <1460347078-15175-1-git-send-email-cw00.choi@samsung.com>
References: <1460347078-15175-1-git-send-email-cw00.choi@samsung.com>
Message-ID: <20160503102551.GC3956@kozik-lap>

On Mon, Apr 11, 2016 at 12:57:38PM +0900, Chanwoo Choi wrote:
> This patch-set includes the two features as following. The generic exynos bus
> frequency driver is able to support almost Exynos SoCs for bus frequency
> scaling. And the new passive governor is able to make the dependency on
> between devices for frequency/voltage scaling. I had posted the patch-set[1]
> with the similiar concept. This is is revised version for exynos bus frequency.
> - Generic exynos bus frequency driver
> - New passive governor of DEVFREQ framework
> [1] https://lkml.org/lkml/2015/1/7/872
> : [PATCHv3 0/8] devfreq: Add generic exynos memory-bus frequency driver

Applied DTS patches for late v4.7 (hopefully).

Best regards,
Krzysztof


From yamada.masahiro at socionext.com  Tue May  3 03:26:51 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 3 May 2016 19:26:51 +0900
Subject: [PATCH 1/7] reset: add devm_reset_controller_register API
In-Reply-To: <1462270670.3617.49.camel@pengutronix.de>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
 <1462099023-11819-2-git-send-email-yamada.masahiro@socionext.com>
 <1462270670.3617.49.camel@pengutronix.de>
Message-ID: <CAK7LNAR699QqYvWdFPtnBc=bLyMLvhCvnKJQCR4YHCy7HQTjUQ@mail.gmail.com>

2016-05-03 19:17 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> Hi Masahiro,
>
> Am Sonntag, den 01.05.2016, 19:36 +0900 schrieb Masahiro Yamada:
>> Add a device managed API for reset_controller_register().
>>
>> This helps in reducing code in .remove callbacks and sometimes
>> dropping .remove callbacks entirely.
>>
>> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
>
> Thank you for these patches. Except for the issue with the lpc18xx patch
> they all look good to me.
> If you don't mind, I'll drop the lpc18xx patch for now and apply the
> others.
>

It is OK with me, but I do not understand what is the problem.

Could you answer my question in the 3/7 thread?



-- 
Best Regards
Masahiro Yamada


From k.kozlowski at samsung.com  Tue May  3 03:29:22 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 3 May 2016 12:29:22 +0200
Subject: [PATCH v2 0/8] PM / devfreq: Add NoCP devfreq-event and support
 busfreq on exyno5422-odroidxu3
In-Reply-To: <1460701975-24178-1-git-send-email-cw00.choi@samsung.com>
References: <1460701975-24178-1-git-send-email-cw00.choi@samsung.com>
Message-ID: <20160503102922.GD3956@kozik-lap>

On Fri, Apr 15, 2016 at 03:32:47PM +0900, Chanwoo Choi wrote:
> This patchset support the AMBA bus frequency scaling on Exynos5422-based
> Odroid-XU3 board. But, this series only support the bus frequency scaling
> for INT (Internal) block using VDD_INT power line.
> 
> Also, to support the bus frequency scaling for Exynos542x SoC,
> Exynos542x SoC has the specific 'NoC (Network on Chip) Probe' device
> to measure the transfered data traffic on NoC (Network on Chip)
> instead of PPMU (Platform Performance Monitoring Unit). NoC Probe device
> provide the utilization for INT block of Exynos542x SoC.
> 
> The generic exynos-bus frequency driver uses the 'NoC Probe' devfreq-event
> device (drivers/devfreq/event/exynos-nocp.c) without any modification.
> Just add the phandle of 'NoC Probe' dt node to bus dt node.
> 
> Depend on:
> This patchset depends on patch[1] which support the generic exynos-bus
> frequency driver.
> [1] http://www.spinics.net/lists/arm-kernel/msg495976.html
> - [PATCH v9 00/20] PM / devferq: Add generic exynos bus frequency driver and new passive governor
> 
> 
> Changse from v1:
> (https://lkml.org/lkml/2016/4/8/28)
> - Simplify the documentation of exynos-nocp.txt
> - Check the return value of regmap function
> - Modify Device Tree node name using general device name
>  : nocp_memX_X@ nocp_memX_X -> nocp_memX_X@ nocp
> - Fix wrong node name about nocp device tree node
> - Drop the CLK_SET_RATE_PARENT flag
> - Reorder bus device tree node alpabetically
> - Add the tested-by tag from Anand Moon and Markus Reichl
> - Add the reviewed-by tag to patch5/7 from Exynos SoC Maintainer
> - Add patch2 to modify the devfreq_event_get_edev_by_phandle()
>   to get the instance of devfreq-event device by using the phandle
> 
> Chanwoo Choi (8):
>   PM / devfreq: event: Add new Exynos NoC probe driver
>   PM / devfreq: event: Find the instance of devfreq-event device by using phandle
>   PM / devfreq: exynos: Add the detailed correlation for Exynos5422 bus
>   ARM: dts: Add NoC Probe dt node for Exynos542x SoC
>   dt-bindings: clock: Add the clock id for ACLK clock of Exynos542x SoC
>   clk: samsung: exynos542x: Add the clock id for ACLK
>   ARM: dts: Add bus nodes using VDD_INT for Exynos542x SoC
>   ARM: dts: Add support of Bus frequency using VDD_INT for exynos5422-odroidxu3


Applied DTS patches for late v4.7 (hopefully).

Best regards,
Krzysztof


From rmk at arm.linux.org.uk  Tue May  3 03:22:26 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:22:26 +0100
Subject: [PATCH kexec-tools 16/32] arm: fix ELF32/ELF64 check
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXTG-0004iV-C6@e0050434b2927.dyn.arm.linux.org.uk>

Rather than using ULONG_MAX to decide whether to use the ELF64 or ELF32
core dump format, use UINT32_MAX instead - we include stdint.h, so we
might as well use a constant which is meaningful for the limits of
the 32-bit ELF format.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index a390187..fcc4d42 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -369,8 +369,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
 	if (last_ranges < 0)
 		last_ranges = 0;
 
-	if (crash_memory_ranges[last_ranges].end > ULONG_MAX) {
-
+	if (crash_memory_ranges[last_ranges].end > UINT32_MAX) {
 		/* for support LPAE enabled kernel*/
 		elf_info.class = ELFCLASS64;
 
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:22:47 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:22:47 +0100
Subject: [PATCH kexec-tools 20/32] arm: add maximum number of memory ranges
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXTb-0004it-43@e0050434b2927.dyn.arm.linux.org.uk>

Add the maximum number of memory ranges to the list of usable memory
ranges, so that we don't have to carry this around.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index 739c906..195b43f 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -46,8 +46,8 @@
  */
 static struct memory_range crash_memory_ranges[CRASH_MAX_MEMORY_RANGES];
 struct memory_ranges usablemem_rgns = {
-    .size = 0,
-    .ranges = crash_memory_ranges,
+	.max_size = CRASH_MAX_MEMORY_RANGES,
+	.ranges = crash_memory_ranges,
 };
 
 /* memory range reserved for crashkernel */
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:23:18 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:23:18 +0100
Subject: [PATCH kexec-tools 26/32] arm: rename crash_reserved_mem to
 crash_kernel_mem
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXU6-0004jU-At@e0050434b2927.dyn.arm.linux.org.uk>

Rename crash_reserved_mem to crash_kernel_mem as we want to support
multiple reserved memory ranges.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index f2e6a0d..1a6ab88 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -53,7 +53,7 @@ struct memory_ranges usablemem_rgns = {
 };
 
 /* memory range reserved for crashkernel */
-static struct memory_range crash_reserved_mem;
+static struct memory_range crash_kernel_mem;
 
 static struct crash_elf_info elf_info = {
 	.class		= ELFCLASS32,
@@ -140,7 +140,7 @@ static int get_kernel_page_offset(struct kexec_info *info,
  */
 static void crash_exclude_range(void)
 {
-	const struct memory_range *range = &crash_reserved_mem;
+	const struct memory_range *range = &crash_kernel_mem;
 	int i;
 
 	for (i = 0; i < usablemem_rgns.size; i++) {
@@ -262,8 +262,8 @@ static void dump_memory_ranges(void)
 		return;
 
 	dbgprintf("crashkernel: [%#llx - %#llx] (%ldM)\n",
-		  crash_reserved_mem.start, crash_reserved_mem.end,
-		  (unsigned long)range_size(&crash_reserved_mem) >> 20);
+		  crash_kernel_mem.start, crash_kernel_mem.end,
+		  (unsigned long)range_size(&crash_kernel_mem) >> 20);
 
 	for (i = 0; i < usablemem_rgns.size; i++) {
 		struct memory_range *r = usablemem_rgns.ranges + i;
@@ -313,10 +313,10 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
 	 * Ensure that the crash kernel memory range is sane. The crash kernel
 	 * must be located within memory which is visible during booting.
 	 */
-	if (crash_reserved_mem.end > ARM_MAX_VIRTUAL) {
+	if (crash_kernel_mem.end > ARM_MAX_VIRTUAL) {
 		fprintf(stderr,
 			"Crash kernel memory [0x%llx-0x%llx] is inaccessible at boot - unable to load crash kernel\n",
-			crash_reserved_mem.start, crash_reserved_mem.end);
+			crash_kernel_mem.start, crash_kernel_mem.end);
 		return -1;
 	}
 
@@ -349,8 +349,8 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
 	 * regions to be aligned to SECTION_SIZE.
 	 */
 	elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 1 << 20,
-					  crash_reserved_mem.start,
-					  crash_reserved_mem.end, -1, 0);
+					  crash_kernel_mem.start,
+					  crash_kernel_mem.end, -1, 0);
 
 	dbgprintf("elfcorehdr: %#lx\n", elfcorehdr);
 	cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
@@ -360,7 +360,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
 	 * prevents the dump capture kernel from using any other memory regions
 	 * which belong to the primary kernel.
 	 */
-	cmdline_add_mem(mod_cmdline, elfcorehdr - crash_reserved_mem.start);
+	cmdline_add_mem(mod_cmdline, elfcorehdr - crash_kernel_mem.start);
 
 	dump_memory_ranges();
 	dbgprintf("kernel command line: \"%s\"\n", mod_cmdline);
@@ -377,7 +377,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
  * @length: size of the memory region
  *
  * This function is called for each memory range in /proc/iomem, stores
- * the location of the crash kernel range into @crash_reserved_mem, and
+ * the location of the crash kernel range into @crash_kernel_mem, and
  * stores the system RAM into @usablemem_rgns.
  */
 static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
@@ -385,9 +385,9 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
 				unsigned long long length)
 {
 	if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) {
-		crash_reserved_mem.start = base;
-		crash_reserved_mem.end = base + length - 1;
-		crash_reserved_mem.type = RANGE_RAM;
+		crash_kernel_mem.start = base;
+		crash_kernel_mem.end = base + length - 1;
+		crash_kernel_mem.type = RANGE_RAM;
 	}
 	else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) {
 		return mem_regions_add(&usablemem_rgns,
@@ -407,5 +407,5 @@ int is_crashkernel_mem_reserved(void)
 {
 	kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL);
 
-	return crash_reserved_mem.start != crash_reserved_mem.end;
+	return crash_kernel_mem.start != crash_kernel_mem.end;
 }
-- 
1.9.1



From linux at arm.linux.org.uk  Tue May  3 03:29:59 2016
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Tue, 3 May 2016 11:29:59 +0100
Subject: [PATCH 06/12] ARM: kexec: advertise location of bootable RAM
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <E1aviF4-0000jG-MO@rmk-PC.arm.linux.org.uk>
 <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <20160503102959.GM19428@n2100.arm.linux.org.uk>

On Fri, Apr 29, 2016 at 08:26:00PM +0530, Pratyush Anand wrote:
> Can you please also share git tree path of corresponding kexec-tools changes?

On their way as a 32-patch series.  I've found the userspace tools to be
in particularly poor shape, so some of the patches are fixing that up.
I can't believe that anyone uses these userspace tools, because there
are some fundamental bugs present in this code which go back years.
However, the repository does seem to be maintained, with the latest
commit within the last two months (or day when I started working on
this.)

They're based upon 2.0.12-rc1 (93d3a617) of the

	git://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git

repository, which was the latest commit when I started working on this
back in March.  Things may have moved forwards since then - I've not
been able to check yet.  However, this set of changes should be
sufficient to get an idea of what's required on the userspace side.

Thanks.

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From john at metanate.com  Tue May  3 03:32:06 2016
From: john at metanate.com (John Keeping)
Date: Tue, 3 May 2016 11:32:06 +0100
Subject: [alsa-devel] [PATCH 1/2] ASoC: rockchip: i2s: separate capture
 and playback
In-Reply-To: <CAFqH_518WDfBATtxYSbtPTdrV1MH=Y2UDBQNeCa2xZTiMp54zw@mail.gmail.com>
References: <1449657147-26959-1-git-send-email-john@metanate.com>
 <CAFqH_52C4JKno4uyt54UdWKAJKM4FPGRiQaQQ9_H-Mz1Cr+Hqg@mail.gmail.com>
 <20160430070049.GF14612@serenity.lan>
 <57282532.7000402@rock-chips.com>
 <CAFqH_50D5PQOkpCDefds3Nyktvitoe2Wx=YcXM2POox1ooO=0g@mail.gmail.com>
 <20160503104318.62739a91.john@metanate.com>
 <CAFqH_518WDfBATtxYSbtPTdrV1MH=Y2UDBQNeCa2xZTiMp54zw@mail.gmail.com>
Message-ID: <20160503113206.0d7e3215.john@metanate.com>

Hi Enric,

On Tue, 3 May 2016 12:21:25 +0200, Enric Balletbo Serra wrote:
> 2016-05-03 11:43 GMT+02:00 John Keeping <john at metanate.com>:
> > On Tue, 3 May 2016 11:16:58 +0200, Enric Balletbo Serra wrote:  
> >> 2016-05-03 6:12 GMT+02:00 sugar <sugar.zhang at rock-chips.com>:  
> >> > On 4/30/2016 15:00, John Keeping Wrote:  
> >> >> On Fri, Apr 29, 2016 at 04:59:27PM +0200, Enric Balletbo Serra wrote:  
> >> >>>
> >> >>> 2015-12-09 11:32 GMT+01:00 John Keeping <john at metanate.com>:  
> >> >>>>
> >> >>>> If we only clear the tx/rx state when both are disabled it is not
> >> >>>> possible to start/stop one multiple times while the other is running.
> >> >>>> Since the two are independently controlled, treat them as such and
> >> >>>> remove the false dependency between capture and playback.
> >> >>>>
> >> >>>> Signed-off-by: John Keeping <john at metanate.com>
> >> >>>> ---
> >> >>>>   sound/soc/rockchip/rockchip_i2s.c | 72
> >> >>>> +++++++++++++++++----------------------
> >> >>>>   1 file changed, 32 insertions(+), 40 deletions(-)
> >> >>>>
> >> >>>> diff --git a/sound/soc/rockchip/rockchip_i2s.c
> >> >>>> b/sound/soc/rockchip/rockchip_i2s.c
> >> >>>> index 83b1b9c..acc6225 100644
> >> >>>> --- a/sound/soc/rockchip/rockchip_i2s.c
> >> >>>> +++ b/sound/soc/rockchip/rockchip_i2s.c
> >> >>>> @@ -82,8 +82,8 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev
> >> >>>> *i2s, int on)
> >> >>>>                                     I2S_DMACR_TDE_ENABLE,
> >> >>>> I2S_DMACR_TDE_ENABLE);
> >> >>>>
> >> >>>>                  regmap_update_bits(i2s->regmap, I2S_XFER,
> >> >>>> -                                  I2S_XFER_TXS_START |
> >> >>>> I2S_XFER_RXS_START,
> >> >>>> -                                  I2S_XFER_TXS_START |
> >> >>>> I2S_XFER_RXS_START);
> >> >>>> +                                  I2S_XFER_TXS_START,
> >> >>>> +                                  I2S_XFER_TXS_START);
> >> >>>>
> >> >>>>                  i2s->tx_start = true;
> >> >>>>          } else {
> >> >>>> @@ -92,27 +92,23 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev
> >> >>>> *i2s, int on)
> >> >>>>                  regmap_update_bits(i2s->regmap, I2S_DMACR,
> >> >>>>                                     I2S_DMACR_TDE_ENABLE,
> >> >>>> I2S_DMACR_TDE_DISABLE);
> >> >>>>
> >> >>>> -               if (!i2s->rx_start) {
> >> >>>> -                       regmap_update_bits(i2s->regmap, I2S_XFER,
> >> >>>> -                                          I2S_XFER_TXS_START |
> >> >>>> -                                          I2S_XFER_RXS_START,
> >> >>>> -                                          I2S_XFER_TXS_STOP |
> >> >>>> -                                          I2S_XFER_RXS_STOP);
> >> >>>> +               regmap_update_bits(i2s->regmap, I2S_XFER,
> >> >>>> +                                  I2S_XFER_TXS_START,
> >> >>>> +                                  I2S_XFER_TXS_STOP);
> >> >>>>
> >> >>>> -                       regmap_update_bits(i2s->regmap, I2S_CLR,
> >> >>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC,
> >> >>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC);
> >> >>>> +               regmap_update_bits(i2s->regmap, I2S_CLR,
> >> >>>> +                                  I2S_CLR_TXC,
> >> >>>> +                                  I2S_CLR_TXC);
> >> >>>>
> >> >>>> -                       regmap_read(i2s->regmap, I2S_CLR, &val);
> >> >>>> +               regmap_read(i2s->regmap, I2S_CLR, &val);
> >> >>>>
> >> >>>> -                       /* Should wait for clear operation to finish */
> >> >>>> -                       while (val) {
> >> >>>> -                               regmap_read(i2s->regmap, I2S_CLR, &val);
> >> >>>> -                               retry--;
> >> >>>> -                               if (!retry) {
> >> >>>> -                                       dev_warn(i2s->dev, "fail to
> >> >>>> clear\n");
> >> >>>> -                                       break;
> >> >>>> -                               }
> >> >>>> +               /* Should wait for clear operation to finish */
> >> >>>> +               while (val & I2S_CLR_TXC) {
> >> >>>> +                       regmap_read(i2s->regmap, I2S_CLR, &val);
> >> >>>> +                       retry--;
> >> >>>> +                       if (!retry) {
> >> >>>> +                               dev_warn(i2s->dev, "fail to clear\n");
> >> >>>> +                               break;
> >> >>>>                          }
> >> >>>>                  }
> >> >>>>          }
> >> >>>> @@ -128,8 +124,8 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev
> >> >>>> *i2s, int on)
> >> >>>>                                     I2S_DMACR_RDE_ENABLE,
> >> >>>> I2S_DMACR_RDE_ENABLE);
> >> >>>>
> >> >>>>                  regmap_update_bits(i2s->regmap, I2S_XFER,
> >> >>>> -                                  I2S_XFER_TXS_START |
> >> >>>> I2S_XFER_RXS_START,
> >> >>>> -                                  I2S_XFER_TXS_START |
> >> >>>> I2S_XFER_RXS_START);
> >> >>>> +                                  I2S_XFER_RXS_START,
> >> >>>> +                                  I2S_XFER_RXS_START);
> >> >>>>
> >> >>>>                  i2s->rx_start = true;
> >> >>>>          } else {
> >> >>>> @@ -138,27 +134,23 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev
> >> >>>> *i2s, int on)
> >> >>>>                  regmap_update_bits(i2s->regmap, I2S_DMACR,
> >> >>>>                                     I2S_DMACR_RDE_ENABLE,
> >> >>>> I2S_DMACR_RDE_DISABLE);
> >> >>>>
> >> >>>> -               if (!i2s->tx_start) {
> >> >>>> -                       regmap_update_bits(i2s->regmap, I2S_XFER,
> >> >>>> -                                          I2S_XFER_TXS_START |
> >> >>>> -                                          I2S_XFER_RXS_START,
> >> >>>> -                                          I2S_XFER_TXS_STOP |
> >> >>>> -                                          I2S_XFER_RXS_STOP);
> >> >>>> +               regmap_update_bits(i2s->regmap, I2S_XFER,
> >> >>>> +                                  I2S_XFER_RXS_START,
> >> >>>> +                                  I2S_XFER_RXS_STOP);
> >> >>>>
> >> >>>> -                       regmap_update_bits(i2s->regmap, I2S_CLR,
> >> >>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC,
> >> >>>> -                                          I2S_CLR_TXC | I2S_CLR_RXC);
> >> >>>> +               regmap_update_bits(i2s->regmap, I2S_CLR,
> >> >>>> +                                  I2S_CLR_RXC,
> >> >>>> +                                  I2S_CLR_RXC);
> >> >>>>
> >> >>>> -                       regmap_read(i2s->regmap, I2S_CLR, &val);
> >> >>>> +               regmap_read(i2s->regmap, I2S_CLR, &val);
> >> >>>>
> >> >>>> -                       /* Should wait for clear operation to finish */
> >> >>>> -                       while (val) {
> >> >>>> -                               regmap_read(i2s->regmap, I2S_CLR, &val);
> >> >>>> -                               retry--;
> >> >>>> -                               if (!retry) {
> >> >>>> -                                       dev_warn(i2s->dev, "fail to
> >> >>>> clear\n");
> >> >>>> -                                       break;
> >> >>>> -                               }
> >> >>>> +               /* Should wait for clear operation to finish */
> >> >>>> +               while (val & I2S_CLR_RXC) {
> >> >>>> +                       regmap_read(i2s->regmap, I2S_CLR, &val);
> >> >>>> +                       retry--;
> >> >>>> +                       if (!retry) {
> >> >>>> +                               dev_warn(i2s->dev, "fail to clear\n");
> >> >>>> +                               break;
> >> >>>>                          }
> >> >>>>                  }
> >> >>>>          }
> >> >>>> --
> >> >>>> 2.6.3.462.gbe2c914  
> >> >>>
> >> >>>
> >> >>> Using my Veyron Jerry Chromebook wiht latest kernel I found that the
> >> >>> speakers doesn't work. Bisect points to this patch as the offending
> >> >>> commit. However your changes looks reasonable the fact is that
> >> >>> reverting the patch makes the audio work again on my device. I need to
> >> >>> dig a bit more into the issue, but meanwhile, any idea on what is
> >> >>> happening ? Can I ask which device did you test?  
> >> >>
> >> >>
> >> >> I tested this on a Radxa Rock2 square.  This change fixed an issue I
> >> >> found when running separate processes for playback and recording (I was
> >> >> testing with arecord and speaker-test IIRC) but I don't think that
> >> >> should be relevant.  I just read through the patch again and I can't see
> >> >> anything obviously wrong so I'm afraid I don't have any idea what's
> >> >> causing the problem you're seeing.
> >> >>  
> >> > Do you have test playback/capture at the same time? I think you may
> >> > reproduce this issue if you do as follows:
> >> >
> >> > step 1: tinyplay test.wav -D 0 -d 0 -p 1024 -n 4 &
> >> > step 2: tinycap r.wav -D 0 -d 0 -p 1024 -n 4 &
> >> >
> >> > you will find that there is no music now.
> >> >
> >> > because of this problem, we enable tx/rx at the same time to WA this issue.
> >> >  
> >>
> >> I can confirm that reverting John's patch audio playback/capture at
> >> the same time works on my Veyron Jerry Chromebook.  
> >
> > Have you tried stopping one of the processes and then starting it again
> > (without touching the other process)?  That's the case that was broken
> > for me without this patch.
> >  
> 
> I  just tried that and it works on my platform. Meanwhile I reproduced
> a song I recorded two wavs.
> 
> > I have had a quick look through the code I'm using and I noticed that I
> > have another change that hasn't been sent upstream, which marks the
> > I2S_FIFOLR register as volatile in rockchip_i2s_volatile_reg():
> >  
> 
> Unfortunately that didn't help, I hear nothing from the speakers :(

Yeah, I looked a bit more after sending the previous mail and that
register is never referenced by the driver!

> I have a Radxa Rock2 Square board, by chance, do you have a git tree
> containing the patches to enable the i2s sound for radxa so I can
> reproduce both here? At least the codec is not upstreamed, I guess.

I've just pushed a branch to Github:

    https://github.com/johnkeeping/linux/tree/topic/audio


Regards,
John


From linux at arm.linux.org.uk  Tue May  3 03:32:37 2016
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Tue, 3 May 2016 11:32:37 +0100
Subject: [PATCH v2 0/3] ARM: nommu: R-class fixes
In-Reply-To: <57287BD9.6090907@arm.com>
References: <1461862316-9877-1-git-send-email-vladimir.murzin@arm.com>
 <57287BD9.6090907@arm.com>
Message-ID: <20160503103237.GN19428@n2100.arm.linux.org.uk>

On Tue, May 03, 2016 at 11:22:17AM +0100, Vladimir Murzin wrote:
> On 28/04/16 17:51, Vladimir Murzin wrote:
> > Small set of fixes discovered with R-class cores.
> > 
> > Jean-Philippe Brucker (2):
> >   ARM: nommu: fix PMSAv7 setup
> >   ARM: nommu: change memory reserve for the vectors
> > 
> > Vladimir Murzin (1):
> >   ARM: domain: move {set,get}_domain under config guard
> > 
> >  arch/arm/include/asm/domain.h |   11 +++++++++++
> >  arch/arm/kernel/head-nommu.S  |    2 +-
> >  arch/arm/mm/nommu.c           |   15 ++++++++-------
> >  3 files changed, 20 insertions(+), 8 deletions(-)
> > 
> 
> Russell, any objection to get it into patch tracker?

I've not had any chance to look at them yet - last weekend, I was away
from Thursday through until late Tuesday, then I spent most of Wednesday
and Thursday catching up.  Friday I was able to look at some stuff, and
then I've spent the bank holiday weekend digging out laurels in the front
garden.  I've only just today got back to looking at some kernel stuff.

So really, I've only had two days in the last week and a half to look at
anything.

Please wait a little while longer.  Thanks.

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From rmk at arm.linux.org.uk  Tue May  3 03:22:36 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:22:36 +0100
Subject: [PATCH kexec-tools 18/32] arm: report if crash kernel is out of bounds
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXTQ-0004ih-NN@e0050434b2927.dyn.arm.linux.org.uk>

Report an error if the crash kernel memory region is outside of the
boot-view memory range - this can happen with systems such as
Keystone 2.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 11 +++++++++++
 kexec/arch/arm/crashdump-arm.h |  1 +
 2 files changed, 12 insertions(+)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index fcc4d42..739c906 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -365,6 +365,17 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
 	if (get_kernel_page_offset(info, &elf_info))
 		return -1;
 
+	/*
+	 * Ensure that the crash kernel memory range is sane. The crash kernel
+	 * must be located within memory which is visible during booting.
+	 */
+	if (crash_reserved_mem.end > ARM_MAX_VIRTUAL) {
+		fprintf(stderr,
+			"Crash kernel memory [0x%llx-0x%llx] is inaccessible at boot - unable to load crash kernel\n",
+			crash_reserved_mem.start, crash_reserved_mem.end);
+		return -1;
+	}
+
 	last_ranges = usablemem_rgns.size - 1;
 	if (last_ranges < 0)
 		last_ranges = 0;
diff --git a/kexec/arch/arm/crashdump-arm.h b/kexec/arch/arm/crashdump-arm.h
index 2dbde04..7314960 100644
--- a/kexec/arch/arm/crashdump-arm.h
+++ b/kexec/arch/arm/crashdump-arm.h
@@ -9,6 +9,7 @@ extern "C" {
 #define DEFAULT_PAGE_OFFSET		(0xc0000000)
 #define KVBASE_MASK	(0x1ffffff)
 #define CRASH_MAX_MEMORY_RANGES	32
+#define ARM_MAX_VIRTUAL		UINT32_MAX
 
 
 extern struct memory_ranges usablemem_rgns;
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:22:31 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:22:31 +0100
Subject: [PATCH kexec-tools 17/32] arm: return proper error for missing crash
 kernel
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXTL-0004ib-Ho@e0050434b2927.dyn.arm.linux.org.uk>

Return the proper error code (ENOCRASHKERNEL) for a missing crash
kernel region in /proc/iomem, so the error handling in kexec.c can
print the appropriate message.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/kexec-zImage-arm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kexec/arch/arm/kexec-zImage-arm.c b/kexec/arch/arm/kexec-zImage-arm.c
index d85ab9b..4755f06 100644
--- a/kexec/arch/arm/kexec-zImage-arm.c
+++ b/kexec/arch/arm/kexec-zImage-arm.c
@@ -451,7 +451,7 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 			 * No crash kernel memory reserved. We cannot do more
 			 * but just bail out.
 			 */
-			return -1;
+			return ENOCRASHKERNEL;
 		}
 		base = start;
 	} else {
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:22:41 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:22:41 +0100
Subject: [PATCH kexec-tools 19/32] arm: add memory ranges debug
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXTV-0004in-Sw@e0050434b2927.dyn.arm.linux.org.uk>

Add the call to dbgprint_mem_range() into the ARM version of
get_memory_ranges().

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/kexec-arm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kexec/arch/arm/kexec-arm.c b/kexec/arch/arm/kexec-arm.c
index e47fc00..eeb27b4 100644
--- a/kexec/arch/arm/kexec-arm.c
+++ b/kexec/arch/arm/kexec-arm.c
@@ -70,6 +70,9 @@ int get_memory_ranges(struct memory_range **range, int *ranges,
 	fclose(fp);
 	*range = memory_range;
 	*ranges = memory_ranges;
+
+	dbgprint_mem_range("MEMORY RANGES", *range, *ranges);
+
 	return 0;
 }
 
-- 
1.9.1



From linux at arm.linux.org.uk  Tue May  3 03:36:40 2016
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Tue, 3 May 2016 11:36:40 +0100
Subject: [PATCH v2 04/13] clkdev: Add clk_hw based registration APIs
In-Reply-To: <20160503003716.GH3492@codeaurora.org>
References: <1461277324-27185-1-git-send-email-sboyd@codeaurora.org>
 <1461277324-27185-5-git-send-email-sboyd@codeaurora.org>
 <20160503003716.GH3492@codeaurora.org>
Message-ID: <20160503103640.GO19428@n2100.arm.linux.org.uk>

On Mon, May 02, 2016 at 05:37:16PM -0700, Stephen Boyd wrote:
> On 04/21, Stephen Boyd wrote:
> > Now that we have a clk registration API that doesn't return
> > struct clks, we need to have some way to hand out struct clks via
> > the clk_get() APIs that doesn't involve associating struct clk
> > pointers with a struct clk_lookup. Luckily, clkdev already
> > operates on struct clk_hw pointers, except for the registration
> > facing APIs where it converts struct clk pointers into struct
> > clk_hw pointers almost immediately.
> > 
> > Let's add clk_hw based registration APIs so that we can skip the
> > conversion step and provide a way for clk provider drivers to
> > operate exclusively on clk_hw structs. This way we clearly
> > split the API between consumers and providers.
> > 
> > Cc: Russell King <linux at arm.linux.org.uk>
> > Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
> > ---
> 
> Applied to clk-next

It would have been nice if you could wait a little longer.  As I've just
explained in another email, I've been away last weekend from Thursday
21st through until Tuesday 26th.  I then spent Wednesday and Thursday
catching up with the resulting backlog of email, and last weekend (30th
through to the 2nd May) was a bank holiday weekend in the UK.  So
there's only been _one_ day that I could have looked at your patches,
but unfortunately the little matter of doing stuff for paying customers
got in the way.

A little more patience would have been nice.

I'll try to look at them this evening.

Thanks.

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From rmk at arm.linux.org.uk  Tue May  3 03:23:33 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:23:33 +0100
Subject: [PATCH kexec-tools 29/32] arm: add debug of reserved and coredump
 memory ranges
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXUL-0004jm-W0@e0050434b2927.dyn.arm.linux.org.uk>

Add debug of the reserved and coredump memory ranges for validation.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index 25fdbe9..2dc8846 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -158,6 +158,10 @@ static int crash_get_memory_ranges(void)
 		return -1;
 	}
 
+	dbgprint_mem_range("Reserved memory ranges",
+			   crash_reserved_rgns.ranges,
+			   crash_reserved_rgns.size);
+
 	/*
 	 * Exclude all reserved memory from the usable memory regions.
 	 * We want to avoid dumping the crashkernel region itself.  Note
@@ -179,6 +183,9 @@ static int crash_get_memory_ranges(void)
 	 */
 	mem_regions_sort(&usablemem_rgns);
 
+	dbgprint_mem_range("Coredump memory ranges",
+			   usablemem_rgns.ranges, usablemem_rgns.size);
+
 	return 0;
 }
 
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:23:02 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:23:02 +0100
Subject: [PATCH kexec-tools 23/32] arm: move crash system RAM parsing earlier
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXTq-0004jC-OH@e0050434b2927.dyn.arm.linux.org.uk>

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/Makefile        |  2 ++
 kexec/arch/arm/crashdump-arm.c | 51 ++++++++----------------------------------
 2 files changed, 11 insertions(+), 42 deletions(-)

diff --git a/kexec/arch/arm/Makefile b/kexec/arch/arm/Makefile
index 60e433a..71db8c3 100644
--- a/kexec/arch/arm/Makefile
+++ b/kexec/arch/arm/Makefile
@@ -7,6 +7,8 @@ arm_FS2DT              = kexec/fs2dt.c
 arm_FS2DT_INCLUDE      = -include $(srcdir)/kexec/arch/arm/crashdump-arm.h \
                          -include $(srcdir)/kexec/arch/arm/kexec-arm.h
 
+arm_MEM_REGIONS        = kexec/mem_regions.c
+
 arm_KEXEC_SRCS=  kexec/arch/arm/kexec-elf-rel-arm.c
 arm_KEXEC_SRCS+= kexec/arch/arm/kexec-zImage-arm.c
 arm_KEXEC_SRCS+= kexec/arch/arm/kexec-uImage-arm.c
diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index d6db566..f2e6a0d 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -30,6 +30,7 @@
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 #include "../../crashdump.h"
+#include "../../mem_regions.h"
 #include "crashdump-arm.h"
 #include "iomem.h"
 
@@ -132,39 +133,6 @@ static int get_kernel_page_offset(struct kexec_info *info,
 }
 
 /**
- * crash_range_callback() - callback called for each iomem region
- * @data: not used
- * @nr: not used
- * @str: name of the memory region
- * @base: start address of the memory region
- * @length: size of the memory region
- *
- * This function is called once for each memory region found in /proc/iomem. It
- * locates system RAM and places these into @crash_memory_ranges. Number of
- * memory regions is placed in @crash_memory_nr_ranges.
- */
-static int crash_range_callback(void *UNUSED(data), int UNUSED(nr),
-				char *str, unsigned long long base,
-				unsigned long long length)
-{
-	struct memory_range *range;
-
-	if (usablemem_rgns.size >= CRASH_MAX_MEMORY_RANGES)
-		return 1;
-
-	range = usablemem_rgns.ranges + usablemem_rgns.size;
-
-	if (strncmp(str, "System RAM\n", 11) == 0) {
-		range->start = base;
-		range->end = base + length - 1;
-		range->type = RANGE_RAM;
-		usablemem_rgns.size++;
-	}
-
-	return 0;
-}
-
-/**
  * crash_exclude_range() - excludes memory region reserved for crashkernel
  *
  * Function locates where crashkernel reserved memory is and removes that region
@@ -213,12 +181,6 @@ static void crash_exclude_range(void)
  */
 static int crash_get_memory_ranges(void)
 {
-	/*
-	 * First read all memory regions that can be considered as
-	 * system memory including the crash area.
-	 */
-	kexec_iomem_for_each_line(NULL, crash_range_callback, NULL);
-
 	if (usablemem_rgns.size < 1) {
 		errno = EINVAL;
 		return -1;
@@ -414,8 +376,9 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
  * @base: start address of the memory region
  * @length: size of the memory region
  *
- * This function is called for each memory range in /proc/iomem, and stores
- * the location of the crash kernel range into @crash_reserved_mem.
+ * This function is called for each memory range in /proc/iomem, stores
+ * the location of the crash kernel range into @crash_reserved_mem, and
+ * stores the system RAM into @usablemem_rgns.
  */
 static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
 				char *str, unsigned long long base,
@@ -426,6 +389,10 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
 		crash_reserved_mem.end = base + length - 1;
 		crash_reserved_mem.type = RANGE_RAM;
 	}
+	else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) {
+		return mem_regions_add(&usablemem_rgns,
+				       base, length, RANGE_RAM);
+	}
 	return 0;
 }
 
@@ -434,7 +401,7 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
  *
  * Check for the crashkernel reserved region in /proc/iomem, and return
  * true if it is present, or false otherwise. We use this to store the
- * location of this region.
+ * location of this region, and system RAM regions.
  */
 int is_crashkernel_mem_reserved(void)
 {
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:22:57 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:22:57 +0100
Subject: [PATCH kexec-tools 22/32] arm: use generic mem_region sorting
 implementation
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXTl-0004j5-II@e0050434b2927.dyn.arm.linux.org.uk>

Use the generic mem_region sorting implementation.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 16 +---------------
 1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index 85afd9f..d6db566 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -202,19 +202,6 @@ static void crash_exclude_range(void)
 	}
 }
 
-static int range_cmp(const void *a1, const void *a2)
-{
-	const struct memory_range *r1 = a1;
-	const struct memory_range *r2 = a2;
-
-	if (r1->start > r2->start)
-		return 1;
-	if (r1->start < r2->start)
-		return -1;
-
-	return 0;
-}
-
 /**
  * crash_get_memory_ranges() - read system physical memory
  *
@@ -246,8 +233,7 @@ static int crash_get_memory_ranges(void)
 	/*
 	 * Make sure that the memory regions are sorted.
 	 */
-	qsort(usablemem_rgns.ranges, usablemem_rgns.size,
-	      sizeof(*usablemem_rgns.ranges), range_cmp);
+	mem_regions_sort(&usablemem_rgns);
 
 	return 0;
 }
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:23:44 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:23:44 +0100
Subject: [PATCH kexec-tools 31/32] arm: clean up phys/page offset debug
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXUW-0004jy-CS@e0050434b2927.dyn.arm.linux.org.uk>

Clean up the physical and page offset debug prints.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index 2589582..3b71267 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -136,7 +136,6 @@ static int get_kernel_page_offset(struct kexec_info *info,
 				user_page_offset);
 	}
 	elf_info->page_offset = stext_sym_addr & (~KVBASE_MASK);
-	dbgprintf("page_offset is set to %llx\n", elf_info->page_offset);
 	return 0;
 }
 
@@ -293,11 +292,13 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
 	 * region as PHYS_OFFSET.
 	 */
 	phys_offset = usablemem_rgns.ranges->start;
-	dbgprintf("phys_offset: %#llx\n", phys_offset);
 
 	if (get_kernel_page_offset(info, &elf_info))
 		return -1;
 
+	dbgprintf("phys offset = %#llx, page offset = %llx\n",
+		  phys_offset, elf_info.page_offset);
+
 	/*
 	 * Ensure that the crash kernel memory range is sane. The crash kernel
 	 * must be located within memory which is visible during booting.
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:21:34 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:21:34 +0100
Subject: [PATCH kexec-tools 06/32] kdump: print mmap() offset in hex
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXSQ-0004hT-54@e0050434b2927.dyn.arm.linux.org.uk>

When mmap() fails, printing a large decimal number is mostly
meaningless - it's not obvious what it means.  Printing a hex number
is more obvious, because we can see whether it's over 32-bit, or not
page aligned.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kdump/kdump.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kdump/kdump.c b/kdump/kdump.c
index 34d2149..f34727f 100644
--- a/kdump/kdump.c
+++ b/kdump/kdump.c
@@ -37,7 +37,7 @@ static void *map_addr(int fd, unsigned long size, off_t offset)
 
 	result = mmap(0, len, PROT_READ, MAP_SHARED, fd, offset - map_offset);
 	if (result == MAP_FAILED) {
-		fprintf(stderr, "Cannot mmap " DEV_MEM " offset: %llu size: %lu: %s\n",
+		fprintf(stderr, "Cannot mmap " DEV_MEM " offset: %#llx size: %lu: %s\n",
 			(unsigned long long)offset, size, strerror(errno));
 		exit(5);
 	}
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:22:21 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:22:21 +0100
Subject: [PATCH kexec-tools 15/32] arm: fix get_kernel_stext_sym() to close
 its file
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXTB-0004iP-5Y@e0050434b2927.dyn.arm.linux.org.uk>

Fix get_kernel_stext_sym() so that it closes its file once it's
finsihed with it - there's no need to leak file descriptors.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index b523e5f..a390187 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -71,25 +71,34 @@ static unsigned long long get_kernel_stext_sym(void)
 	char sym[128];
 	char line[128];
 	FILE *fp;
-	unsigned long long vaddr;
+	unsigned long long vaddr = 0;
 	char type;
 
-	fp = fopen(kallsyms, "r");	if (!fp) {
+	fp = fopen(kallsyms, "r");
+	if (!fp) {
 		fprintf(stderr, "Cannot open %s\n", kallsyms);
 		return 0;
 	}
 
 	while(fgets(line, sizeof(line), fp) != NULL) {
-		if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
+		unsigned long long addr;
+
+		if (sscanf(line, "%Lx %c %s", &addr, &type, sym) != 3)
 			continue;
+
 		if (strcmp(sym, stext) == 0) {
-			dbgprintf("kernel symbol %s vaddr = %16llx\n", stext, vaddr);
-			return vaddr;
+			dbgprintf("kernel symbol %s vaddr = %#llx\n", stext, addr);
+			vaddr = addr;
+			break;
 		}
 	}
 
-	fprintf(stderr, "Cannot get kernel %s symbol address\n", stext);
-	return 0;
+	fclose(fp);
+
+	if (vaddr == 0)
+		fprintf(stderr, "Cannot get kernel %s symbol address\n", stext);
+
+	return vaddr;
 }
 
 static int get_kernel_page_offset(struct kexec_info *info,
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:23:28 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:23:28 +0100
Subject: [PATCH kexec-tools 28/32] arm: add support for boot-time crash kernel
 resource
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXUG-0004jg-PD@e0050434b2927.dyn.arm.linux.org.uk>

Add support for detecting and using the boot-time crash kernel
resource, which is needed for systems which have special boot-time
memory views, such as Keystone 2.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index 9113f5e..25fdbe9 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -52,7 +52,7 @@ struct memory_ranges usablemem_rgns = {
 	.ranges = crash_memory_ranges,
 };
 
-/* memory range reserved for crashkernel */
+/* The boot-time physical memory range reserved for crashkernel region */
 static struct memory_range crash_kernel_mem;
 
 /* reserved regions */
@@ -366,13 +366,22 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
 				char *str, unsigned long long base,
 				unsigned long long length)
 {
-	if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) {
+	if (strncmp(str, CRASH_KERNEL_BOOT, strlen(CRASH_KERNEL_BOOT)) == 0) {
 		crash_kernel_mem.start = base;
 		crash_kernel_mem.end = base + length - 1;
 		crash_kernel_mem.type = RANGE_RAM;
 		return mem_regions_add(&crash_reserved_rgns,
 				       base, length, RANGE_RAM);
 	}
+	else if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) {
+		if (crash_kernel_mem.start == crash_kernel_mem.end) {
+			crash_kernel_mem.start = base;
+			crash_kernel_mem.end = base + length - 1;
+			crash_kernel_mem.type = RANGE_RAM;
+		}
+		return mem_regions_add(&crash_reserved_rgns,
+				       base, length, RANGE_RAM);
+	}
 	else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) {
 		return mem_regions_add(&usablemem_rgns,
 				       base, length, RANGE_RAM);
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:23:23 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:23:23 +0100
Subject: [PATCH kexec-tools 27/32] arm: add support for multiple reserved
 regions
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXUB-0004ja-JE@e0050434b2927.dyn.arm.linux.org.uk>

Add support for reserving multiple memory regions rather than just a
single region.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 66 ++++++++++++++++--------------------------
 1 file changed, 25 insertions(+), 41 deletions(-)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index 1a6ab88..9113f5e 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -55,6 +55,14 @@ struct memory_ranges usablemem_rgns = {
 /* memory range reserved for crashkernel */
 static struct memory_range crash_kernel_mem;
 
+/* reserved regions */
+#define CRASH_MAX_RESERVED_RANGES 2
+static struct memory_range crash_reserved_ranges[CRASH_MAX_RESERVED_RANGES];
+static struct memory_ranges crash_reserved_rgns = {
+	.max_size = CRASH_MAX_RESERVED_RANGES,
+	.ranges = crash_reserved_ranges,
+};
+
 static struct crash_elf_info elf_info = {
 	.class		= ELFCLASS32,
 	.data		= ELFDATANATIVE,
@@ -133,44 +141,6 @@ static int get_kernel_page_offset(struct kexec_info *info,
 }
 
 /**
- * crash_exclude_range() - excludes memory region reserved for crashkernel
- *
- * Function locates where crashkernel reserved memory is and removes that region
- * from the available memory regions.
- */
-static void crash_exclude_range(void)
-{
-	const struct memory_range *range = &crash_kernel_mem;
-	int i;
-
-	for (i = 0; i < usablemem_rgns.size; i++) {
-		struct memory_range *r = usablemem_rgns.ranges + i;
-
-		/*
-		 * We assume that crash area is fully contained in
-		 * some larger memory area.
-		 */
-		if (r->start <= range->start && r->end >= range->end) {
-			struct memory_range *new;
-			/*
-			 * Let's split this area into 2 smaller ones and
-			 * remove excluded range from between. First create
-			 * new entry for the remaining area.
-			 */
-			new = usablemem_rgns.ranges + usablemem_rgns.size;
-			new->start = range->end + 1;
-			new->end = r->end;
-			usablemem_rgns.size++;
-			/*
-			 * Next update this area to end before excluded range.
-			 */
-			r->end = range->start - 1;
-			break;
-		}
-	}
-}
-
-/**
  * crash_get_memory_ranges() - read system physical memory
  *
  * Function reads through system physical memory and stores found memory regions
@@ -181,16 +151,28 @@ static void crash_exclude_range(void)
  */
 static int crash_get_memory_ranges(void)
 {
+	int i;
+
 	if (usablemem_rgns.size < 1) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	/*
-	 * Exclude memory reserved for crashkernel (this may result a split memory
-	 * region).
+	 * Exclude all reserved memory from the usable memory regions.
+	 * We want to avoid dumping the crashkernel region itself.  Note
+	 * that this may result memory regions in usablemem_rgns being
+	 * split.
 	 */
-	crash_exclude_range();
+	for (i = 0; i < crash_reserved_rgns.size; i++) {
+		if (mem_regions_exclude(&usablemem_rgns,
+					&crash_reserved_rgns.ranges[i])) {
+			fprintf(stderr,
+				"Error: Number of crash memory ranges excedeed the max limit\n");
+			errno = ENOMEM;
+			return -1;
+		}
+	}
 
 	/*
 	 * Make sure that the memory regions are sorted.
@@ -388,6 +370,8 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
 		crash_kernel_mem.start = base;
 		crash_kernel_mem.end = base + length - 1;
 		crash_kernel_mem.type = RANGE_RAM;
+		return mem_regions_add(&crash_reserved_rgns,
+				       base, length, RANGE_RAM);
 	}
 	else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) {
 		return mem_regions_add(&usablemem_rgns,
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:23:49 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:23:49 +0100
Subject: [PATCH kexec-tools 32/32] arm: report which ELF core format we will
 use
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXUb-0004k4-LW@e0050434b2927.dyn.arm.linux.org.uk>

Report which ELF core format will be used to create the template ELF
core dump in the debug information.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index 3b71267..4a89b5e 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -315,6 +315,8 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
 		last_ranges = 0;
 
 	if (crash_memory_ranges[last_ranges].end > UINT32_MAX) {
+		dbgprintf("Using 64-bit ELF core format\n");
+
 		/* for support LPAE enabled kernel*/
 		elf_info.class = ELFCLASS64;
 
@@ -323,6 +325,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
 					 usablemem_rgns.size, &buf, &bufsz,
 					 ELF_CORE_HEADER_ALIGN);
 	} else {
+		dbgprintf("Using 32-bit ELF core format\n");
 		err = crash_create_elf32_headers(info, &elf_info,
 					 usablemem_rgns.ranges,
 					 usablemem_rgns.size, &buf, &bufsz,
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:23:39 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:23:39 +0100
Subject: [PATCH kexec-tools 30/32] arm: fix type of phys_offset
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXUR-0004js-5j@e0050434b2927.dyn.arm.linux.org.uk>

Some LPAE systems may have phys_offset above the 4GB mark.  Hence, we
need phys_offset to be a 64-bit integer.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 4 ++--
 kexec/arch/arm/crashdump-arm.h | 1 -
 kexec/arch/arm/phys_to_virt.c  | 4 +++-
 kexec/arch/arm/phys_to_virt.h  | 8 ++++++++
 4 files changed, 13 insertions(+), 4 deletions(-)
 create mode 100644 kexec/arch/arm/phys_to_virt.h

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index 2dc8846..2589582 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -33,6 +33,7 @@
 #include "../../mem_regions.h"
 #include "crashdump-arm.h"
 #include "iomem.h"
+#include "phys_to_virt.h"
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #define ELFDATANATIVE ELFDATA2LSB
@@ -70,7 +71,6 @@ static struct crash_elf_info elf_info = {
 	.page_offset	= DEFAULT_PAGE_OFFSET,
 };
 
-unsigned long phys_offset;
 extern unsigned long long user_page_offset;
 
 /* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */
@@ -293,7 +293,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
 	 * region as PHYS_OFFSET.
 	 */
 	phys_offset = usablemem_rgns.ranges->start;
-	dbgprintf("phys_offset: %#lx\n", phys_offset);
+	dbgprintf("phys_offset: %#llx\n", phys_offset);
 
 	if (get_kernel_page_offset(info, &elf_info))
 		return -1;
diff --git a/kexec/arch/arm/crashdump-arm.h b/kexec/arch/arm/crashdump-arm.h
index 7314960..6e87b13 100644
--- a/kexec/arch/arm/crashdump-arm.h
+++ b/kexec/arch/arm/crashdump-arm.h
@@ -16,7 +16,6 @@ extern struct memory_ranges usablemem_rgns;
 
 struct kexec_info;
 
-extern unsigned long phys_offset;
 extern int load_crashdump_segments(struct kexec_info *, char *);
 
 #ifdef __cplusplus
diff --git a/kexec/arch/arm/phys_to_virt.c b/kexec/arch/arm/phys_to_virt.c
index c2fe2ea..46a4f68 100644
--- a/kexec/arch/arm/phys_to_virt.c
+++ b/kexec/arch/arm/phys_to_virt.c
@@ -1,6 +1,8 @@
 #include "../../kexec.h"
 #include "../../crashdump.h"
-#include "crashdump-arm.h"
+#include "phys_to_virt.h"
+
+uint64_t phys_offset;
 
 /**
  * phys_to_virt() - translate physical address to virtual address
diff --git a/kexec/arch/arm/phys_to_virt.h b/kexec/arch/arm/phys_to_virt.h
new file mode 100644
index 0000000..b3147dd
--- /dev/null
+++ b/kexec/arch/arm/phys_to_virt.h
@@ -0,0 +1,8 @@
+#ifndef PHYS_TO_VIRT_H
+#define PHYS_TO_VIRT_H
+
+#include <stdint.h>
+
+extern uint64_t phys_offset;
+
+#endif
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:23:07 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:23:07 +0100
Subject: [PATCH kexec-tools 24/32] arm: add support for platforms with boot
 memory aliases
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXTv-0004jI-UH@e0050434b2927.dyn.arm.linux.org.uk>

The kexec API deals with boot-view addresses, rather than normal system
view addresses.  This causes problems for platforms such as Keystone 2,
where the boot view is substantially different from the normal system
view.

This is because Keystone 2 boots from a memory alias in the lower 4GiB,
before switching to a high alias at 32GiB.

We handle this in a generic way by introducing boot alias resources in
/proc/iomem:

80000000-dfffffff : System RAM (boot alias)
  9f800000-9fffffff : Crash kernel (boot alias)
800000000-85fffffff : System RAM
  800008000-800790e37 : Kernel code
  8007ec000-8008b856f : Kernel data
  81f800000-81fffffff : Crash kernel

To allow kexec to load a kernel, we need to add the boot alias of RAM
to the memory ranges returned by get_memory_ranges().  Parse the
system RAM boot alias into the memory ranges.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/iomem.h     | 2 ++
 kexec/arch/arm/kexec-arm.c | 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/kexec/arch/arm/iomem.h b/kexec/arch/arm/iomem.h
index 81c593d..85f958e 100644
--- a/kexec/arch/arm/iomem.h
+++ b/kexec/arch/arm/iomem.h
@@ -2,6 +2,8 @@
 #define IOMEM_H
 
 #define SYSTEM_RAM		"System RAM\n"
+#define SYSTEM_RAM_BOOT		"System RAM (boot alias)\n"
 #define CRASH_KERNEL		"Crash kernel\n"
+#define CRASH_KERNEL_BOOT	"Crash kernel (boot alias)\n"
 
 #endif
diff --git a/kexec/arch/arm/kexec-arm.c b/kexec/arch/arm/kexec-arm.c
index eeb27b4..2194b7c 100644
--- a/kexec/arch/arm/kexec-arm.c
+++ b/kexec/arch/arm/kexec-arm.c
@@ -18,6 +18,7 @@
 #include "kexec-arm.h"
 #include <arch/options.h>
 #include "../../fs2dt.h"
+#include "iomem.h"
 
 #define MAX_MEMORY_RANGES 64
 #define MAX_LINE 160
@@ -52,7 +53,8 @@ int get_memory_ranges(struct memory_range **range, int *ranges,
 			continue;
 		str = line + consumed;
 
-		if (memcmp(str, "System RAM\n", 11) == 0) {
+		if (memcmp(str, SYSTEM_RAM_BOOT, strlen(SYSTEM_RAM_BOOT)) == 0 ||
+		    memcmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) {
 			type = RANGE_RAM;
 		}
 		else if (memcmp(str, "reserved\n", 9) == 0) {
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:23:13 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:23:13 +0100
Subject: [PATCH kexec-tools 25/32] arm: crashdump needs boot alias of crash
 kernel region
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXU1-0004jO-4q@e0050434b2927.dyn.arm.linux.org.uk>

When crashdumping, we need the boot memory alias of the crash kernel
region rather than the system view.  Arrange to check for the boot
alias of the crash kernel region first, and if found, use it instead
of the main alias.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/kexec-zImage-arm.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/kexec/arch/arm/kexec-zImage-arm.c b/kexec/arch/arm/kexec-zImage-arm.c
index 4755f06..fdd2910 100644
--- a/kexec/arch/arm/kexec-zImage-arm.c
+++ b/kexec/arch/arm/kexec-zImage-arm.c
@@ -20,6 +20,7 @@
 #include "kexec-arm.h"
 #include "../../fs2dt.h"
 #include "crashdump-arm.h"
+#include "iomem.h"
 
 #define BOOT_PARAMS_SIZE 1536
 
@@ -446,7 +447,8 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 		 * We put the dump capture kernel at the start of crashkernel
 		 * reserved memory.
 		 */
-		if (parse_iomem_single("Crash kernel\n", &start, &end)) {
+		if (parse_iomem_single(CRASH_KERNEL_BOOT, &start, &end) &&
+		    parse_iomem_single(CRASH_KERNEL, &start, &end)) {
 			/*
 			 * No crash kernel memory reserved. We cannot do more
 			 * but just bail out.
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:22:52 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:22:52 +0100
Subject: [PATCH kexec-tools 21/32] arm: parse crash_reserved_mem early
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXTg-0004iz-CQ@e0050434b2927.dyn.arm.linux.org.uk>

We parse the crash kernel memory region in several locations in the
kexec tools - once to check that there's a region, another time for
real when we're locating the memory regions to dump, and another
while loading the image.

Move the real parsing step to is_crashkernel_mem_reserved(), which
matches what x86 is doing.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/crashdump-arm.c | 47 +++++++++++++++++++++++++++++++-----------
 kexec/arch/arm/iomem.h         |  7 +++++++
 2 files changed, 42 insertions(+), 12 deletions(-)
 create mode 100644 kexec/arch/arm/iomem.h

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index 195b43f..85afd9f 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -31,6 +31,7 @@
 #include "../../kexec-elf.h"
 #include "../../crashdump.h"
 #include "crashdump-arm.h"
+#include "iomem.h"
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #define ELFDATANATIVE ELFDATA2LSB
@@ -139,9 +140,8 @@ static int get_kernel_page_offset(struct kexec_info *info,
  * @length: size of the memory region
  *
  * This function is called once for each memory region found in /proc/iomem. It
- * locates system RAM and crashkernel reserved memory and places these to
- * variables: @crash_memory_ranges and @crash_reserved_mem. Number of memory
- * regions is placed in @crash_memory_nr_ranges.
+ * locates system RAM and places these into @crash_memory_ranges. Number of
+ * memory regions is placed in @crash_memory_nr_ranges.
  */
 static int crash_range_callback(void *UNUSED(data), int UNUSED(nr),
 				char *str, unsigned long long base,
@@ -159,10 +159,6 @@ static int crash_range_callback(void *UNUSED(data), int UNUSED(nr),
 		range->end = base + length - 1;
 		range->type = RANGE_RAM;
 		usablemem_rgns.size++;
-	} else if (strncmp(str, "Crash kernel\n", 13) == 0) {
-		crash_reserved_mem.start = base;
-		crash_reserved_mem.end = base + length - 1;
-		crash_reserved_mem.type = RANGE_RAM;
 	}
 
 	return 0;
@@ -424,12 +420,39 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
 	return 0;
 }
 
-int is_crashkernel_mem_reserved(void)
+/**
+ * iomem_range_callback() - callback called for each iomem region
+ * @data: not used
+ * @nr: not used
+ * @str: name of the memory region (not NULL terminated)
+ * @base: start address of the memory region
+ * @length: size of the memory region
+ *
+ * This function is called for each memory range in /proc/iomem, and stores
+ * the location of the crash kernel range into @crash_reserved_mem.
+ */
+static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
+				char *str, unsigned long long base,
+				unsigned long long length)
 {
-	uint64_t start, end;
+	if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) {
+		crash_reserved_mem.start = base;
+		crash_reserved_mem.end = base + length - 1;
+		crash_reserved_mem.type = RANGE_RAM;
+	}
+	return 0;
+}
 
-	if (parse_iomem_single("Crash kernel\n", &start, &end) == 0)
-		return start != end;
+/**
+ * is_crashkernel_mem_reserved() - check for the crashkernel reserved region
+ *
+ * Check for the crashkernel reserved region in /proc/iomem, and return
+ * true if it is present, or false otherwise. We use this to store the
+ * location of this region.
+ */
+int is_crashkernel_mem_reserved(void)
+{
+	kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL);
 
-	return 0;
+	return crash_reserved_mem.start != crash_reserved_mem.end;
 }
diff --git a/kexec/arch/arm/iomem.h b/kexec/arch/arm/iomem.h
new file mode 100644
index 0000000..81c593d
--- /dev/null
+++ b/kexec/arch/arm/iomem.h
@@ -0,0 +1,7 @@
+#ifndef IOMEM_H
+#define IOMEM_H
+
+#define SYSTEM_RAM		"System RAM\n"
+#define CRASH_KERNEL		"Crash kernel\n"
+
+#endif
-- 
1.9.1



From rmk at arm.linux.org.uk  Tue May  3 03:22:15 2016
From: rmk at arm.linux.org.uk (Russell King)
Date: Tue, 03 May 2016 11:22:15 +0100
Subject: [PATCH kexec-tools 14/32] arm: fix off-by-one on memory end
In-Reply-To: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
Message-ID: <E1axXT5-0004iJ-VX@e0050434b2927.dyn.arm.linux.org.uk>

The memory range end is inclusive, not exclusive (see x86).  We should
not be adding one to the value parsed from the /proc/iomem resources.

Signed-off-by: Russell King <rmk at arm.linux.org.uk>
---
 kexec/arch/arm/kexec-arm.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/kexec/arch/arm/kexec-arm.c b/kexec/arch/arm/kexec-arm.c
index 4e90e69..e47fc00 100644
--- a/kexec/arch/arm/kexec-arm.c
+++ b/kexec/arch/arm/kexec-arm.c
@@ -51,7 +51,6 @@ int get_memory_ranges(struct memory_range **range, int *ranges,
 		if (count != 2)
 			continue;
 		str = line + consumed;
-		end = end + 1;
 
 		if (memcmp(str, "System RAM\n", 11) == 0) {
 			type = RANGE_RAM;
-- 
1.9.1



From vladimir.murzin at arm.com  Tue May  3 03:41:51 2016
From: vladimir.murzin at arm.com (Vladimir Murzin)
Date: Tue, 3 May 2016 11:41:51 +0100
Subject: [PATCH v2 0/3] ARM: nommu: R-class fixes
In-Reply-To: <20160503103237.GN19428@n2100.arm.linux.org.uk>
References: <1461862316-9877-1-git-send-email-vladimir.murzin@arm.com>
 <57287BD9.6090907@arm.com> <20160503103237.GN19428@n2100.arm.linux.org.uk>
Message-ID: <5728806F.7000208@arm.com>

On 03/05/16 11:32, Russell King - ARM Linux wrote:
> On Tue, May 03, 2016 at 11:22:17AM +0100, Vladimir Murzin wrote:
>> On 28/04/16 17:51, Vladimir Murzin wrote:
>>> Small set of fixes discovered with R-class cores.
>>>
>>> Jean-Philippe Brucker (2):
>>>   ARM: nommu: fix PMSAv7 setup
>>>   ARM: nommu: change memory reserve for the vectors
>>>
>>> Vladimir Murzin (1):
>>>   ARM: domain: move {set,get}_domain under config guard
>>>
>>>  arch/arm/include/asm/domain.h |   11 +++++++++++
>>>  arch/arm/kernel/head-nommu.S  |    2 +-
>>>  arch/arm/mm/nommu.c           |   15 ++++++++-------
>>>  3 files changed, 20 insertions(+), 8 deletions(-)
>>>
>>
>> Russell, any objection to get it into patch tracker?
> 
> I've not had any chance to look at them yet - last weekend, I was away
> from Thursday through until late Tuesday, then I spent most of Wednesday
> and Thursday catching up.  Friday I was able to look at some stuff, and
> then I've spent the bank holiday weekend digging out laurels in the front
> garden.  I've only just today got back to looking at some kernel stuff.
> 
> So really, I've only had two days in the last week and a half to look at
> anything.
> 
> Please wait a little while longer.  Thanks.

Thanks for prompt reply! I wasn't aware you've been off, patches can wait.

Cheers
Vladimir



From marc.zyngier at arm.com  Tue May  3 03:47:37 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 11:47:37 +0100
Subject: [PATCH v2 50/54] KVM: arm/arm64: vgic-new: vgic_init: implement
 map_resources
In-Reply-To: <1461861973-26464-51-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-51-git-send-email-andre.przywara@arm.com>
Message-ID: <572881C9.300@arm.com>

On 28/04/16 17:46, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> map_resources is the last initialization step. It is executed on
> 1st VCPU run. At that stage the code checks the userspace has provided
> the base addresses for the relevant VGIC regions, which depend on
> the type of VGIC that is exposed to the guest.
> 
> The function also forces the vgic_init if it has not been executed yet
> (only allowed for VGIC v2).
> 
> for GICv2, The VGIC CPU interface is mapped onto the GIC virtual CPU
> interface.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  include/kvm/vgic/vgic.h       |  1 +
>  virt/kvm/arm/vgic/vgic-init.c | 27 +++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v2.c   | 47 +++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c   | 44 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h      | 16 +++++++++++++++
>  5 files changed, 135 insertions(+)

[...]

> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 444210f..f970e3e 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -43,6 +43,9 @@ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v2_enable(struct kvm_vcpu *vcpu);
>  int vgic_v2_probe(struct device_node *vgic_node);
> +int vgic_v2_map_resources(struct kvm *kvm);
> +int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
> +			     enum vgic_type);
>  
>  #ifdef CONFIG_KVM_ARM_VGIC_V3
>  void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
> @@ -54,6 +57,8 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v3_enable(struct kvm_vcpu *vcpu);
>  int vgic_v3_probe(struct device_node *vgic_node);
> +int vgic_v3_map_resources(struct kvm *kvm);
> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
>  #else
>  static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
>  {
> @@ -94,6 +99,17 @@ static inline int vgic_v3_probe(struct device_node *vgic_node)
>  {
>  	return -ENODEV;
>  }
> +
> +static inline int vgic_v3_map_resources(struct kvm *kvm)
> +{
> +	return -ENODEV;
> +}
> +
> +static inline int vgic_register_redist_iodevs(struct kvm *kvm,
> +					      gpa_t dist_base_address)
> +{
> +	return -ENODEV;
> +}

It would make sense to move this stub to patch 32, where the non-stub
implementation is.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From cw00.choi at samsung.com  Tue May  3 03:48:24 2016
From: cw00.choi at samsung.com (Chanwoo Choi)
Date: Tue, 03 May 2016 19:48:24 +0900
Subject: [PATCH v2 0/8] PM / devfreq: Add NoCP devfreq-event and support
 busfreq on exyno5422-odroidxu3
In-Reply-To: <20160503102922.GD3956@kozik-lap>
References: <1460701975-24178-1-git-send-email-cw00.choi@samsung.com>
 <20160503102922.GD3956@kozik-lap>
Message-ID: <572881F8.3020701@samsung.com>

Hi Krzysztof,

On 2016? 05? 03? 19:29, Krzysztof Kozlowski wrote:
> On Fri, Apr 15, 2016 at 03:32:47PM +0900, Chanwoo Choi wrote:
>> This patchset support the AMBA bus frequency scaling on Exynos5422-based
>> Odroid-XU3 board. But, this series only support the bus frequency scaling
>> for INT (Internal) block using VDD_INT power line.
>>
>> Also, to support the bus frequency scaling for Exynos542x SoC,
>> Exynos542x SoC has the specific 'NoC (Network on Chip) Probe' device
>> to measure the transfered data traffic on NoC (Network on Chip)
>> instead of PPMU (Platform Performance Monitoring Unit). NoC Probe device
>> provide the utilization for INT block of Exynos542x SoC.
>>
>> The generic exynos-bus frequency driver uses the 'NoC Probe' devfreq-event
>> device (drivers/devfreq/event/exynos-nocp.c) without any modification.
>> Just add the phandle of 'NoC Probe' dt node to bus dt node.
>>
>> Depend on:
>> This patchset depends on patch[1] which support the generic exynos-bus
>> frequency driver.
>> [1] http://www.spinics.net/lists/arm-kernel/msg495976.html
>> - [PATCH v9 00/20] PM / devferq: Add generic exynos bus frequency driver and new passive governor
>>
>>
>> Changse from v1:
>> (https://lkml.org/lkml/2016/4/8/28)
>> - Simplify the documentation of exynos-nocp.txt
>> - Check the return value of regmap function
>> - Modify Device Tree node name using general device name
>>  : nocp_memX_X@ nocp_memX_X -> nocp_memX_X@ nocp
>> - Fix wrong node name about nocp device tree node
>> - Drop the CLK_SET_RATE_PARENT flag
>> - Reorder bus device tree node alpabetically
>> - Add the tested-by tag from Anand Moon and Markus Reichl
>> - Add the reviewed-by tag to patch5/7 from Exynos SoC Maintainer
>> - Add patch2 to modify the devfreq_event_get_edev_by_phandle()
>>   to get the instance of devfreq-event device by using the phandle
>>
>> Chanwoo Choi (8):
>>   PM / devfreq: event: Add new Exynos NoC probe driver
>>   PM / devfreq: event: Find the instance of devfreq-event device by using phandle
>>   PM / devfreq: exynos: Add the detailed correlation for Exynos5422 bus
>>   ARM: dts: Add NoC Probe dt node for Exynos542x SoC
>>   dt-bindings: clock: Add the clock id for ACLK clock of Exynos542x SoC
>>   clk: samsung: exynos542x: Add the clock id for ACLK
>>   ARM: dts: Add bus nodes using VDD_INT for Exynos542x SoC
>>   ARM: dts: Add support of Bus frequency using VDD_INT for exynos5422-odroidxu3
> 
> 
> Applied DTS patches for late v4.7 (hopefully).

Thanks for your review and apply.

Best Regards,
Chanwoo Choi



From dongas86 at gmail.com  Tue May  3 03:50:21 2016
From: dongas86 at gmail.com (Dong Aisheng)
Date: Tue, 3 May 2016 18:50:21 +0800
Subject: [PATCH] clk: imx: fix ahb clock mux 1
In-Reply-To: <20160503083253.GC5874@tiger>
References: <1461877623-26838-1-git-send-email-stefan@agner.ch>
 <20160503083253.GC5874@tiger>
Message-ID: <CAA+hA=Rkfii=Mi-NuESpX8E3W37+PnCxa464yOAe5dYMgpt43g@mail.gmail.com>

Hi Shawn,

On Tue, May 3, 2016 at 4:32 PM, Shawn Guo <shawnguo at kernel.org> wrote:
> On Thu, Apr 28, 2016 at 02:07:03PM -0700, Stefan Agner wrote:
>> The clock parent of the AHB root clock when using mux option 1
>> is the SYS PLL 270MHz clock. This is specified in  Table 5-11
>> Clock Root Table of the i.MX 7Dual Applications Processor
>> Reference Manual.
>>
>> While it could be a documentation error, the 270MHz parent is
>> also mentioned in the boot ROM configuration in Table 6-28: The
>> clock is by default at 135MHz due to a POST_PODF value of 1
>> (=> divider of 2).
>>
>> Signed-off-by: Stefan Agner <stefan at agner.ch>
>
> Anson, Frank,
>
> Can you guys confirm this change is correct?
>

I just checked the doc,
it's correct the parent should be SYS_PLL_PFD2(270Mhz).
It's a documentation error of early version and it's already fixed
in latest internal doc.

Regards
Dong Aisheng

> Shawn
>
>> ---
>> Hi Shawn,
>>
>> I did not found a clock which was based on this clock which I
>> could measure externally... But the change is backed by the
>> documentation.
>>
>> --
>> Stefan
>>
>>  drivers/clk/imx/clk-imx7d.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
>> index 7912be8..5229968 100644
>> --- a/drivers/clk/imx/clk-imx7d.c
>> +++ b/drivers/clk/imx/clk-imx7d.c
>> @@ -56,7 +56,7 @@ static const char *nand_usdhc_bus_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
>>       "pll_sys_pfd2_135m_clk", "pll_sys_pfd6_clk", "pll_enet_250m_clk",
>>       "pll_audio_main_clk", };
>>
>> -static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
>> +static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
>>       "pll_dram_533m_clk", "pll_sys_pfd0_392m_clk",
>>       "pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_main_clk",
>>       "pll_video_main_clk", };
>> --
>> 2.8.0
>>
>>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From lorenzo.pieralisi at arm.com  Tue May  3 04:02:25 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Tue, 3 May 2016 12:02:25 +0100
Subject: [PATCH V6 02/13] pci, acpi: Provide generic way to assign bus
 domain number.
In-Reply-To: <CAKc_7PU1AszF4y0OjZ3KVGaTEx9OL1cuT5YgOxQKhAQgQom7tA@mail.gmail.com>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-3-git-send-email-tn@semihalf.com>
 <20160427022649.GD6789@localhost> <20160427111758.GA6234@red-moon>
 <57274B8C.5030304@semihalf.com>
 <CAKc_7PU1AszF4y0OjZ3KVGaTEx9OL1cuT5YgOxQKhAQgQom7tA@mail.gmail.com>
Message-ID: <20160503110225.GA1055@red-moon>

On Mon, May 02, 2016 at 06:56:13PM +0530, Jayachandran C wrote:
> On Mon, May 2, 2016 at 6:13 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> > On 04/27/2016 01:17 PM, Lorenzo Pieralisi wrote:
> >>
> >> On Tue, Apr 26, 2016 at 09:26:49PM -0500, Bjorn Helgaas wrote:
> >>>
> >>> On Fri, Apr 15, 2016 at 07:06:37PM +0200, Tomasz Nowicki wrote:
> >
> > [...]
> >
> >>>   +int acpi_pci_bus_domain_nr(struct device *parent)
> >>> +{
> >>> +       struct acpi_device *acpi_dev = to_acpi_device(parent);
> >>> +       unsigned long long segment = 0;
> >>> +       acpi_status status;
> >>> +
> >>> +       /*
> >>> +        * If _SEG method does not exist, following ACPI spec (6.5.6)
> >>> +        * all PCI buses belong to domain 0.
> >>> +        */
> >>> +       status = acpi_evaluate_integer(acpi_dev->handle,
> >>> METHOD_NAME__SEG, NULL,
> >>> +                                      &segment);
> >>> We already have code in acpi_pci_root_add() to evaluate _SEG.  We
> >>> don't want to evaluate it *twice*, do we?
> >>>
> >>> I was sort of expecting that if you added it here, we'd remove the
> >>> existing call, but it looks like you're keeping both?
> >>
> >> We can't remove the existing call, since it is used on X86 and IA64
> >> to store the segment number that, in the process, is used in their
> >> pci_domain_nr() arch specific callback to retrieve the domain nr.
> >>
> >> On ARM64, that selects PCI_DOMAINS_GENERIC, we have to find a way
> >> to retrieve the domain number that is not arch dependent, since
> >> this is generic code, we can't rely on any bus->sysdata format (unless
> >> we do something like JC did below), therefore the only way is to call
> >> the _SEG method *again* here, which also forced Tomasz to go through
> >> the ACPI_COMPANION setting song and dance and pass the parent pointer
> >> to pci_create_root_bus() (see patch 1), which BTW is a source of
> >> trouble on its own as you noticed.
> >
> > What trouble in patch 1 do you mean? I may miss something.
> >
> > I agree that patch 1 is not necessary if we decide to use sysdata or rework
> > root bus scanning to move domain to host bridge. Nevertheless, patch 1 is
> > still a cleanup IMO.
> 
> In this case, getting the domain should be trivial since the ACPI
> companion on parent is already set, this should work
> 
> int acpi_pci_bus_domain_nr(struct device *parent)
> {
>         struct acpi_device *acpi_dev = to_acpi_device(parent);
>         struct acpi_pci_root *root = acpi_dev->driver_data;
> 
>         return root->segment;
> }
> 
> Or am I missing something here?

Well, I thought that the whole idea behind this exercise was to move
the domain number into struct pci_host_bridge (Arnd did not do it with
his first set but this does not mean we can't add it as Bjorn suggested),
so that the domain number could be read from there straight away in an
arch (and FW) independent manner, right ?

Lorenzo


From stefan.wahren at i2se.com  Tue May  3 04:07:32 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Tue, 3 May 2016 13:07:32 +0200
Subject: [PATCH 1/3] iio: mxs-lradc: Add regulators for current sources
In-Reply-To: <1461333147-11873-2-git-send-email-harald@ccbib.org>
References: <1461333147-11873-1-git-send-email-harald@ccbib.org>
 <1461333147-11873-2-git-send-email-harald@ccbib.org>
Message-ID: <57288674.9050601@i2se.com>

Hi Harald,

Am 22.04.2016 um 15:52 schrieb Harald Geyer:
> The hardware has two current sources ISRC0 and ISRC1 to allow measuring
> resistors without additional circuitry. This commit makes them available
> as regulators.
>
> Tested on an imx233-olinuxino board.
>
> Signed-off-by: Harald Geyer <harald at ccbib.org>
> ---
> The current regulator API doesn't fit this type of device very well: Typically
> consumers will want to set a defined current, ie. min_uA == max_uA, but they
> can't without help from configuration data, because the valid values aren't
> reported by the API for current regulators. I have been thinking about
> extending the API, but currently AFAIK no such consumers exist and most
> users, like myself, will force the regulator to a defined value in
> devicetree anyway.
>
>  .../bindings/staging/iio/adc/mxs-lradc.txt         |  29 ++++
>  drivers/iio/adc/Kconfig                            |   1 +
>  drivers/iio/adc/mxs-lradc.c                        | 152 +++++++++++++++++++++
>  3 files changed, 182 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
> index 555fb11..983952c 100644
> --- a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
> +++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
> @@ -19,6 +19,15 @@ Optional properties:
>  - fsl,settling: delay between plate switch to next sample. Allowed value is
>                  1 ... 2047. It counts at 2 kHz and its default is
>                  10 (= 5 ms)
> +- ISRC0: A node describing the regulator of internal current source 0
> +- ISRC1: A node describing the regulator of internal current source 1
> +
> +Required properties for the ISRCx sub-nodes:
> +- regulator-max-microamp: See standard regulator binding documentation.
> +                          Valid values are from 0 to 300 in steps of 20.
> +
> +Optional properties for the ISRCx sub-nodes:
> +Any standard regulator properties that apply to current regulators.
>  
>  Example for i.MX23 SoC:
>  
> @@ -31,6 +40,16 @@ Example for i.MX23 SoC:
>  		fsl,ave-ctrl = <4>;
>  		fsl,ave-delay = <2>;
>  		fsl,settling = <10>;
> +
> +		isrc_lradc0: ISRC0 {
> +			regulator-max-microamp = <300>;
> +		};
> +
> +		isrc_lradc1: ISRC1 {
> +			regulator-max-microamp = <120>;
> +			regulator-min-microamp = <120>;
> +			regulator-always-on;
> +		};

IMHO the binding should represent the direct connection between the
current source and the physical channel. I think a node label isn't
enough. Unfortunately i don't have an idea to do it the "right way".

>  	};
>  
>  Example for i.MX28 SoC:
> @@ -44,4 +63,14 @@ Example for i.MX28 SoC:
>  		fsl,ave-ctrl = <4>;
>  		fsl,ave-delay = <2>;
>  		fsl,settling = <10>;
> +
> +		isrc_lradc0: ISRC0 {
> +			regulator-max-microamp = <300>;
> +		};
> +
> +		isrc_lradc6: ISRC1 {
> +			regulator-max-microamp = <120>;
> +			regulator-min-microamp = <120>;
> +			regulator-always-on;
> +		};
>  	};
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 5937030..1968d1c 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -319,6 +319,7 @@ config MXS_LRADC
>          tristate "Freescale i.MX23/i.MX28 LRADC"
>          depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM
>          depends on INPUT
> +        depends on REGULATOR

Any chance to avoid this dependency for an optional feature?

Stefan

>          select STMP_DEVICE
>          select IIO_BUFFER
>          select IIO_TRIGGERED_BUFFER



From p.zabel at pengutronix.de  Tue May  3 04:08:10 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Tue, 03 May 2016 13:08:10 +0200
Subject: [PATCH 3/7] reset: lpc18xx: use devm_reset_controller_register()
In-Reply-To: <CAK7LNAQga-dCmAWevKMQx2DBzGim8DmNyeCxj4n5q-SjEapd+Q@mail.gmail.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
 <1462099023-11819-4-git-send-email-yamada.masahiro@socionext.com>
 <1462177581.3933.7.camel@pengutronix.de>
 <CAK7LNAQ5LztGBbHCQxfLyWT7c_kWL=zpdKfkC9vsOKw95XL_Yw@mail.gmail.com>
 <1462266344.3617.12.camel@pengutronix.de>
 <CAK7LNAQga-dCmAWevKMQx2DBzGim8DmNyeCxj4n5q-SjEapd+Q@mail.gmail.com>
Message-ID: <1462273690.3617.56.camel@pengutronix.de>

Am Dienstag, den 03.05.2016, 19:25 +0900 schrieb Masahiro Yamada:
> Hi Philipp,
> 
> 2016-05-03 18:05 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> > Am Dienstag, den 03.05.2016, 00:52 +0900 schrieb Masahiro Yamada:
> >> 2016-05-02 17:26 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> >> > Am Sonntag, den 01.05.2016, 19:36 +0900 schrieb Masahiro Yamada:
> >> >> Use devm_reset_controller_register() for the reset controller
> >> >> registration and remove the unregister call from the .remove callback.
> >> >>
> >> >> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> >> >> ---
> >> >>
> >> >>  drivers/reset/reset-lpc18xx.c | 4 +---
> >> >>  1 file changed, 1 insertion(+), 3 deletions(-)
> >> >>
> >> >> diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c
> >> >> index 3b8a4f5..dd4f27e 100644
> >> >> --- a/drivers/reset/reset-lpc18xx.c
> >> >> +++ b/drivers/reset/reset-lpc18xx.c
> >> >> @@ -199,7 +199,7 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
> >> >>
> >> >>       platform_set_drvdata(pdev, rc);
> >> >>
> >> >> -     ret = reset_controller_register(&rc->rcdev);
> >> >> +     ret = devm_reset_controller_register(&pdev->dev, &rc->rcdev);
> >> >>       if (ret) {
> >> >>               dev_err(&pdev->dev, "unable to register device\n");
> >> >>               goto dis_clks;
> >> >> @@ -229,8 +229,6 @@ static int lpc18xx_rgu_remove(struct platform_device *pdev)
> >> >>       if (ret)
> >> >>               dev_warn(&pdev->dev, "failed to unregister restart handler\n");
> >> >>
> >> >> -     reset_controller_unregister(&rc->rcdev);
> >> >> -
> >> >>       clk_disable_unprepare(rc->clk_delay);
> >> >>       clk_disable_unprepare(rc->clk_reg);
> >> >>
> >> >
> >> > Hmm, would this patch theoretically allow a window between the calls to
> >> > clk_disable_unprepare(clk_reg) and devm_reset_controller_release() where
> >> > reset_control_get() + reset_control_(de)assert() would access unclocked
> >> > registers?
> >>
> >> This is not clear to me.
> >>
> >> Why reset_control_get() + reset_control_(de)assert() would happen here?
> >
> > I suppose on a non-SMP device, without parallel probing this can't
> > really happen in practice.
> > It still seems weird that suddenly we disable the clocks before
> > unregistering the reset controller instead of afterwards.
> >
> 
> I still do not understand what you mean.
> 
> This patch moves the reset_controller_unregister() call
> after clk_disable_unprepare().

And so the register access is made impossible before the reset
controller device actually vanishes from the publicly visible list.

> But, reset_controller_unregister() is just a manipulation of a liked list.
> It does not trigger any hardware access.
> 
> Am I wrong?

No, you are perfectly right. I don't see how this can be a real problem
unless at the same time another driver could try to request the still
available reset control.

regards
Philipp



From bamvor.zhangjian at huawei.com  Tue May  3 04:07:12 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Tue, 3 May 2016 19:07:12 +0800
Subject: [PATCH 24/25] arm64:ilp32: add vdso-ilp32 and use for signal
 return
In-Reply-To: <3846428.6xx69KGEja@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1554541.oDP7Ro5zB2@wuerfel>
 <20160503090045.GB10733@e104818-lin.cambridge.arm.com>
 <3846428.6xx69KGEja@wuerfel>
Message-ID: <57288660.9030607@huawei.com>



On 2016/5/3 17:05, Arnd Bergmann wrote:
> On Tuesday 03 May 2016 10:00:45 Catalin Marinas wrote:
>> On Fri, Apr 29, 2016 at 07:30:19PM +0200, Arnd Bergmann wrote:
>>> On Friday 29 April 2016 17:01:55 Catalin Marinas wrote:
>>>> On Wed, Apr 06, 2016 at 01:08:46AM +0300, Yury Norov wrote:
>>>>> ILP32 VDSO exports next symbols:
>>>>>   __kernel_rt_sigreturn;
>>>>>   __kernel_gettimeofday;
>>>>>   __kernel_clock_gettime;
>>>>>   __kernel_clock_getres;
>>>>
>>>> [...]
>>>>
>>>>> +$(obj)/gettimeofday-ilp32.o: $(src)/../vdso/gettimeofday.S
>>>>> + $(call if_changed_dep,vdso-ilp32as)
>>>>
>>>> Are struct timeval and timespec the same between ILP32 and LP64? For
>>>> example, __kernel_gettimeofday() assumes TVAL_TV_SEC offset defined in
>>>> asm-offsets.c based on the LP64 timeval.
>>>
>>> No, ilp32 uses the generic 32-bit data structures, which have a 32-bit
>>> time_t. I guess that means it can work for little-endian but not
>>> big-endian, right?
>>
>> I don't think it works for little-endian either. The LP64 struct timeval
>> is 16 bytes while the ILP32 one is 8 bytes. The VDSO gettimeofday is
>> storing 16 bytes (stp x10, x11, [x0, #TVAL_TV_SEC])
>
> You are right. Yury asked pointed out the same thing on IRC as well.
> Using the 64-bit gettimeofday() will put the right number in the
> .tv_sec member on little-endian, but will write zeroes to tv_nsec
> and corrupt the memory following it.
>
> Yury also tried it out and noticed that for a (so far) unknown reason,
> the vdso gets never used by his glibc build, so it has not triggered
> any test case failures.
We found this issue too. And it is because the version is different from
the glibc wanted. We define 2.6.39 for lp64 but 2.6 for ilp32 in vdso
in kernel:
+VERSION
+{
+	LINUX_2.6 {
+	global:
+		__kernel_rt_sigreturn;
+		__kernel_gettimeofday;
+		__kernel_clock_gettime;
+		__kernel_clock_getres;
+	local: *;
+	};
+}
If I change 2.6 to 2.6.39, the ilp32 application will call vdso instead
of syscall. But the result is wrong as Catalin mentioned before.

Should we set this version to 4.6 or higher version? We will need to update
the version in "sysdeps/unix/sysv/linux/aarch64/init-first.c" too:
static inline void
_libc_vdso_platform_setup (void)
{
   PREPARE_VERSION (linux2639, "LINUX_2.6.39", 123718537);

   void *p = _dl_vdso_vsym ("__kernel_gettimeofday", &linux2639);
   PTR_MANGLE (p);
   VDSO_SYMBOL(gettimeofday) = p;

   p = _dl_vdso_vsym ("__kernel_clock_gettime", &linux2639);
   PTR_MANGLE (p);
   VDSO_SYMBOL(clock_gettime) = p;

   p = _dl_vdso_vsym ("__kernel_clock_getres", &linux2639);
   PTR_MANGLE (p);
   VDSO_SYMBOL(clock_getres) = p;
}

Regards

Bamvor

>
> 	Arnd
>



From tixy at linaro.org  Tue May  3 04:13:33 2016
From: tixy at linaro.org (Jon Medhurst (Tixy))
Date: Tue, 03 May 2016 12:13:33 +0100
Subject: [RFC PATCH] arm64: Make arch_randomize_brk avoid stack area
In-Reply-To: <CAGXu5jJKDE_pLCxy-FF7PN5+YC7wyvpQ_9DTDGqHuk+tb1mvJA@mail.gmail.com>
References: <1461848638.2848.19.camel@linaro.org>
 <1461853042.2848.24.camel@linaro.org>
 <CAGXu5jJKDE_pLCxy-FF7PN5+YC7wyvpQ_9DTDGqHuk+tb1mvJA@mail.gmail.com>
Message-ID: <1462274013.2862.46.camel@linaro.org>

On Mon, 2016-05-02 at 12:34 -0700, Kees Cook wrote:
> On Thu, Apr 28, 2016 at 7:17 AM, Jon Medhurst (Tixy) <tixy at linaro.org> wrote:
[...]

> >  arch/arm64/kernel/process.c | 24 ++++++++++++++++++------
> >  1 file changed, 18 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> > index 07c4c53..7e0f404 100644
> > --- a/arch/arm64/kernel/process.c
> > +++ b/arch/arm64/kernel/process.c
> > @@ -434,13 +434,25 @@ unsigned long arch_align_stack(unsigned long sp)
> >         return sp & ~0xf;
> >  }
> >
> > -static unsigned long randomize_base(unsigned long base)
> > +unsigned long arch_randomize_brk(struct mm_struct *mm)
> >  {
> > +       unsigned long base = mm->brk;
> >         unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
> 
> This looks wrong. Shouldn't it be (STACK_RND_MASK + 1) << PAGE_SHIFT ?

That value is the same as before my changes and it matches the gap left
for stack randomisation in arch/arm64/mm/mmap.c

> 
> STACK_RND_MASK is 0x7ff (32-bit) or 0x3ffff (64-bit):
> 
> #define STACK_RND_MASK                  (test_thread_flag(TIF_32BIT) ? \
>                                                 0x7ff >> (PAGE_SHIFT - 12) : \
>                                                 0x3ffff >> (PAGE_SHIFT - 12))
> 
> (4K paged PAGE_SHIFT is 12)
> 
> So the correct offset max would be 0x800000 (32-bit) and 0x40000000
> (64-bit), instead of
> 0x7ff0001 and 0x3ffff0001.

It seems to me there isn't a 'correct' and 'incorrect' range to use here
and that randomising brk is not directly related to stack randomisation,
they just have similar requirements and constraints.

Anyway, for stack randomisation, in fs/binfmt_elf.c,
randomize_stack_top() has

		random_variable = get_random_long();
		random_variable &= STACK_RND_MASK;
		random_variable <<= PAGE_SHIFT;

so stack top can be randomised by adding a number from zero to
(STACK_RND_MASK << PAGE_SHIFT) inclusive. As the end value passed to
randomize_range() is exclusive, then adding one to the last permissible
value seems the like the right, I.e. arm64's usage of

  (STACK_RND_MASK << PAGE_SHIFT) + 1

for brk is 'correct' in that it's consistent with what happens to the
stack. Though the different functions align values to pages at different
stages, so possibly neither that nor 

  (STACK_RND_MASK + 1)  << PAGE_SHIFT

when used for brk, would be the same as the stack code.


> Even with that correction, this looks wrong for 32-bit, which uses
> 0x2000000 natively:
> 
> unsigned long arch_randomize_brk(struct mm_struct *mm)
> {
>         unsigned long range_end = mm->brk + 0x02000000;
>         return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
> }
> 
> Seems like arm64 compat is using 4 times less entropy than native arm?
> (Note that STACK_RND_MASK is correct for arm64 compat: this matches
> the default in fs/binfmt_elf.c that arm uses. It just seems like the
> brk randomization is accidentally too small on arm64 compat since arm
> uses a fixed value unrelated to stack randomization.)
> 
> 0x02000000 arm native
> 0x00800000 arm64 compat  <- bug?
> 0x40000000 arm64

Well, it's a difference for which there probably isn't a good reason,
don't know if people would call it a bug.

As changing the range of values used for randomisation seems like a
separate issue I won't include any changes for that in my patch for
getting brk to avoid the stack.

-- 
Tixy



From robin.murphy at arm.com  Tue May  3 04:15:52 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 3 May 2016 12:15:52 +0100
Subject: [PATCH] iommu/arm-smmu: clear cache lock bit of ACR
In-Reply-To: <1462270527-17074-1-git-send-email-van.freenix@gmail.com>
References: <1462270527-17074-1-git-send-email-van.freenix@gmail.com>
Message-ID: <57288868.9020908@arm.com>

On 03/05/16 11:15, Peng Fan wrote:
> According MMU-500 TRM, section 3.7.1 Auxiliary Control registers,
> You can modify ACTLR only when the ACR.CACHE_LOCK bit is 0.
>
> So before clearing ARM_MMU500_ACTLR_CPRE of each context bank,
> need clear CACHE_LOCK bit of ACR register first.

Ah, good catch - I think I misread CACHE_LOCK as resetting to 0, and 
proceeded to forget about it. However, it's only present in MMU-500r2 
onwards, so we'd also want to check IDR7 before touching ACR.

Thanks,
Robin.

> Signed-off-by: Peng Fan <van.freenix at gmail.com>
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: Robin Murphy <robin.murphy at arm.com>
> ---
>
> Hi Will,
>
>   Patch based on iommu/devel branch.
>
>
>   drivers/iommu/arm-smmu.c | 15 +++++++++++++++
>   1 file changed, 15 insertions(+)
>
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index acff332..d094a5a 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -98,6 +98,9 @@
>   #define sCR0_BSU_SHIFT			14
>   #define sCR0_BSU_MASK			0x3
>
> +/* Auxiliary Configuration register */
> +#define ARM_SMMU_GR0_sACR		0x10
> +
>   /* Identification registers */
>   #define ARM_SMMU_GR0_ID0		0x20
>   #define ARM_SMMU_GR0_ID1		0x24
> @@ -235,6 +238,8 @@
>
>   #define ARM_MMU500_ACTLR_CPRE		(1 << 1)
>
> +#define ARM_MMU500_ACR_CACHE_LOCK	(1 << 26)
> +
>   #define CB_PAR_F			(1 << 0)
>
>   #define ATSR_ACTIVE			(1 << 0)
> @@ -1506,6 +1511,16 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
>   		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(i));
>   	}
>
> +	/*
> +	 * Before clearing ARM_MMU500_ACTLR_CPRE, need to
> +	 * clear CACHE_LOCK bit of ACR first.
> +	 */
> +	if (smmu->model == ARM_MMU500) {
> +		reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sACR);
> +		reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
> +		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sACR);
> +	}
> +
>   	/* Make sure all context banks are disabled and clear CB_FSR  */
>   	for (i = 0; i < smmu->num_context_banks; ++i) {
>   		cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, i);
>



From harald at ccbib.org  Tue May  3 04:22:55 2016
From: harald at ccbib.org (Harald Geyer)
Date: Tue, 03 May 2016 13:22:55 +0200
Subject: [PATCH 1/3] iio: mxs-lradc: Add regulators for current sources
In-Reply-To: <57288674.9050601@i2se.com>
References: <1461333147-11873-1-git-send-email-harald@ccbib.org>
 <1461333147-11873-2-git-send-email-harald@ccbib.org>
 <57288674.9050601@i2se.com>
Message-ID: <6cdd4f858dacf72e192a292f29c12feb@ccbib.org>

Hi Stefan!

On 03.05.2016 13:07, Stefan Wahren wrote:
> Am 22.04.2016 um 15:52 schrieb Harald Geyer:
>> The hardware has two current sources ISRC0 and ISRC1 to allow 
>> measuring
>> resistors without additional circuitry. This commit makes them 
>> available
>> as regulators.
>>
>> Tested on an imx233-olinuxino board.
>>
>> Signed-off-by: Harald Geyer <harald at ccbib.org>
>> ---
>> The current regulator API doesn't fit this type of device very well: 
>> Typically
>> consumers will want to set a defined current, ie. min_uA == max_uA, 
>> but they
>> can't without help from configuration data, because the valid values 
>> aren't
>> reported by the API for current regulators. I have been thinking 
>> about
>> extending the API, but currently AFAIK no such consumers exist and 
>> most
>> users, like myself, will force the regulator to a defined value in
>> devicetree anyway.
>>
>>  .../bindings/staging/iio/adc/mxs-lradc.txt         |  29 ++++
>>  drivers/iio/adc/Kconfig                            |   1 +
>>  drivers/iio/adc/mxs-lradc.c                        | 152 
>> +++++++++++++++++++++
>>  3 files changed, 182 insertions(+)
>>
>> diff --git 
>> a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt 
>> b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
>> index 555fb11..983952c 100644
>> --- 
>> a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
>> +++ 
>> b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
>> @@ -19,6 +19,15 @@ Optional properties:
>>  - fsl,settling: delay between plate switch to next sample. Allowed 
>> value is
>>                  1 ... 2047. It counts at 2 kHz and its default is
>>                  10 (= 5 ms)
>> +- ISRC0: A node describing the regulator of internal current source 
>> 0
>> +- ISRC1: A node describing the regulator of internal current source 
>> 1
>> +
>> +Required properties for the ISRCx sub-nodes:
>> +- regulator-max-microamp: See standard regulator binding 
>> documentation.
>> +                          Valid values are from 0 to 300 in steps 
>> of 20.
>> +
>> +Optional properties for the ISRCx sub-nodes:
>> +Any standard regulator properties that apply to current regulators.
>>
>>  Example for i.MX23 SoC:
>>
>> @@ -31,6 +40,16 @@ Example for i.MX23 SoC:
>>  		fsl,ave-ctrl = <4>;
>>  		fsl,ave-delay = <2>;
>>  		fsl,settling = <10>;
>> +
>> +		isrc_lradc0: ISRC0 {
>> +			regulator-max-microamp = <300>;
>> +		};
>> +
>> +		isrc_lradc1: ISRC1 {
>> +			regulator-max-microamp = <120>;
>> +			regulator-min-microamp = <120>;
>> +			regulator-always-on;
>> +		};
>
> IMHO the binding should represent the direct connection between the
> current source and the physical channel. I think a node label isn't
> enough. Unfortunately i don't have an idea to do it the "right way".

I strictly followed the names of the data sheet here: imx23 and imx28
reference manuals both call the current sources ISRC0 and ISRC1 even
if they are attached to different channels of the ADC. I think
inventing some ISRC6 for imx28 would do more harm then good.

>>  	};
>>
>>  Example for i.MX28 SoC:
>> @@ -44,4 +63,14 @@ Example for i.MX28 SoC:
>>  		fsl,ave-ctrl = <4>;
>>  		fsl,ave-delay = <2>;
>>  		fsl,settling = <10>;
>> +
>> +		isrc_lradc0: ISRC0 {
>> +			regulator-max-microamp = <300>;
>> +		};
>> +
>> +		isrc_lradc6: ISRC1 {
>> +			regulator-max-microamp = <120>;
>> +			regulator-min-microamp = <120>;
>> +			regulator-always-on;
>> +		};
>>  	};
>> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
>> index 5937030..1968d1c 100644
>> --- a/drivers/iio/adc/Kconfig
>> +++ b/drivers/iio/adc/Kconfig
>> @@ -319,6 +319,7 @@ config MXS_LRADC
>>          tristate "Freescale i.MX23/i.MX28 LRADC"
>>          depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM
>>          depends on INPUT
>> +        depends on REGULATOR
>
> Any chance to avoid this dependency for an optional feature?

I haven't looked into it yet, but I expect that that the mfd
conversion will avoid this neatly.

Thanks,
Harald

> Stefan
>
>>          select STMP_DEVICE
>>          select IIO_BUFFER
>>          select IIO_TRIGGERED_BUFFER

-- 
If you want to support my work:
see http://friends.ccbib.org/harald/supporting/
or donate via peercoin to P98LRdhit3gZbHDBe7ta5jtXrMJUms4p7w
or bitcoin 1FUtd8T9jRN1rFz63vZz7s2fDtB6d6A7aS


From marex at denx.de  Tue May  3 03:44:23 2016
From: marex at denx.de (Marek Vasut)
Date: Tue, 03 May 2016 12:44:23 +0200
Subject: [PATCH] ARM: mx5: dts: Enable USB OTG on M53EVK
In-Reply-To: <1461105361-6742-1-git-send-email-marex@denx.de>
References: <1461105361-6742-1-git-send-email-marex@denx.de>
Message-ID: <57288107.4000908@denx.de>

On 04/20/2016 12:36 AM, Marek Vasut wrote:
> Add USB OTG support to M53EVK instead of just USB gadget.
> 
> Signed-off-by: Marek Vasut <marex at denx.de>
> Cc: Shawn Guo <shawn.guo at linaro.org>

Bump ?

btw. Shawn, is the @k.org the address I should use now ?

> ---
>  arch/arm/boot/dts/imx53-m53evk.dts | 21 ++++++++++++++++++++-
>  1 file changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/imx53-m53evk.dts b/arch/arm/boot/dts/imx53-m53evk.dts
> index 53f4088..dcee1e0f 100644
> --- a/arch/arm/boot/dts/imx53-m53evk.dts
> +++ b/arch/arm/boot/dts/imx53-m53evk.dts
> @@ -84,6 +84,15 @@
>  			regulator-max-microvolt = <5000000>;
>  			gpio = <&gpio1 2 0>;
>  		};
> +
> +		reg_usb_otg_vbus: regulator at 4 {
> +			compatible = "regulator-fixed";
> +			reg = <4>;
> +			regulator-name = "usb_otg_vbus";
> +			regulator-min-microvolt = <5000000>;
> +			regulator-max-microvolt = <5000000>;
> +			gpio = <&gpio1 4 0>;
> +		};
>  	};
>  
>  	sound {
> @@ -168,6 +177,12 @@
>  			>;
>  		};
>  
> +		pinctrl_usbotg: usbotggrp {
> +			fsl,pins = <
> +				MX53_PAD_GPIO_4__GPIO1_4		0x000b0
> +			>;
> +		};
> +
>  		led_pin_gpio: led_gpio at 0 {
>  			fsl,pins = <
>  				MX53_PAD_PATA_DATA8__GPIO2_8		0x80000000
> @@ -351,6 +366,10 @@
>  };
>  
>  &usbotg {
> -	dr_mode = "peripheral";
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_usbotg>;
> +	dr_mode = "otg";
> +	vbus-supply = <&reg_usb_otg_vbus>;
> +	disable-over-current;
>  	status = "okay";
>  };
> 


-- 
Best regards,
Marek Vasut


From yamada.masahiro at socionext.com  Tue May  3 04:40:49 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 3 May 2016 20:40:49 +0900
Subject: [PATCH 3/7] reset: lpc18xx: use devm_reset_controller_register()
In-Reply-To: <1462273690.3617.56.camel@pengutronix.de>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
 <1462099023-11819-4-git-send-email-yamada.masahiro@socionext.com>
 <1462177581.3933.7.camel@pengutronix.de>
 <CAK7LNAQ5LztGBbHCQxfLyWT7c_kWL=zpdKfkC9vsOKw95XL_Yw@mail.gmail.com>
 <1462266344.3617.12.camel@pengutronix.de>
 <CAK7LNAQga-dCmAWevKMQx2DBzGim8DmNyeCxj4n5q-SjEapd+Q@mail.gmail.com>
 <1462273690.3617.56.camel@pengutronix.de>
Message-ID: <CAK7LNAR13Ox1pbRFmxKJfhNNRKJo+4XcQfvuCNZF6oyUF75Jkg@mail.gmail.com>

2016-05-03 20:08 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> Am Dienstag, den 03.05.2016, 19:25 +0900 schrieb Masahiro Yamada:
>> Hi Philipp,
>>
>> 2016-05-03 18:05 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
>> > Am Dienstag, den 03.05.2016, 00:52 +0900 schrieb Masahiro Yamada:
>> >> 2016-05-02 17:26 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
>> >> > Am Sonntag, den 01.05.2016, 19:36 +0900 schrieb Masahiro Yamada:
>> >> >> Use devm_reset_controller_register() for the reset controller
>> >> >> registration and remove the unregister call from the .remove callback.
>> >> >>
>> >> >> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
>> >> >> ---
>> >> >>
>> >> >>  drivers/reset/reset-lpc18xx.c | 4 +---
>> >> >>  1 file changed, 1 insertion(+), 3 deletions(-)
>> >> >>
>> >> >> diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c
>> >> >> index 3b8a4f5..dd4f27e 100644
>> >> >> --- a/drivers/reset/reset-lpc18xx.c
>> >> >> +++ b/drivers/reset/reset-lpc18xx.c
>> >> >> @@ -199,7 +199,7 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
>> >> >>
>> >> >>       platform_set_drvdata(pdev, rc);
>> >> >>
>> >> >> -     ret = reset_controller_register(&rc->rcdev);
>> >> >> +     ret = devm_reset_controller_register(&pdev->dev, &rc->rcdev);
>> >> >>       if (ret) {
>> >> >>               dev_err(&pdev->dev, "unable to register device\n");
>> >> >>               goto dis_clks;
>> >> >> @@ -229,8 +229,6 @@ static int lpc18xx_rgu_remove(struct platform_device *pdev)
>> >> >>       if (ret)
>> >> >>               dev_warn(&pdev->dev, "failed to unregister restart handler\n");
>> >> >>
>> >> >> -     reset_controller_unregister(&rc->rcdev);
>> >> >> -
>> >> >>       clk_disable_unprepare(rc->clk_delay);
>> >> >>       clk_disable_unprepare(rc->clk_reg);
>> >> >>
>> >> >
>> >> > Hmm, would this patch theoretically allow a window between the calls to
>> >> > clk_disable_unprepare(clk_reg) and devm_reset_controller_release() where
>> >> > reset_control_get() + reset_control_(de)assert() would access unclocked
>> >> > registers?
>> >>
>> >> This is not clear to me.
>> >>
>> >> Why reset_control_get() + reset_control_(de)assert() would happen here?
>> >
>> > I suppose on a non-SMP device, without parallel probing this can't
>> > really happen in practice.
>> > It still seems weird that suddenly we disable the clocks before
>> > unregistering the reset controller instead of afterwards.
>> >
>>
>> I still do not understand what you mean.
>>
>> This patch moves the reset_controller_unregister() call
>> after clk_disable_unprepare().
>
> And so the register access is made impossible before the reset
> controller device actually vanishes from the publicly visible list.
>
>> But, reset_controller_unregister() is just a manipulation of a liked list.
>> It does not trigger any hardware access.
>>
>> Am I wrong?
>
> No, you are perfectly right. I don't see how this can be a real problem
> unless at the same time another driver could try to request the still
> available reset control.


Ah, now I understood.
Thanks!



-- 
Best Regards
Masahiro Yamada


From yamada.masahiro at socionext.com  Tue May  3 04:41:49 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 3 May 2016 20:41:49 +0900
Subject: [PATCH 1/7] reset: add devm_reset_controller_register API
In-Reply-To: <CAK7LNAR699QqYvWdFPtnBc=bLyMLvhCvnKJQCR4YHCy7HQTjUQ@mail.gmail.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
 <1462099023-11819-2-git-send-email-yamada.masahiro@socionext.com>
 <1462270670.3617.49.camel@pengutronix.de>
 <CAK7LNAR699QqYvWdFPtnBc=bLyMLvhCvnKJQCR4YHCy7HQTjUQ@mail.gmail.com>
Message-ID: <CAK7LNAT-fK9zMSov4h8CaG0nbqq=N466zBGFOnZA5LWuxgwDOg@mail.gmail.com>

2016-05-03 19:26 GMT+09:00 Masahiro Yamada <yamada.masahiro at socionext.com>:
> 2016-05-03 19:17 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
>> Hi Masahiro,
>>
>> Am Sonntag, den 01.05.2016, 19:36 +0900 schrieb Masahiro Yamada:
>>> Add a device managed API for reset_controller_register().
>>>
>>> This helps in reducing code in .remove callbacks and sometimes
>>> dropping .remove callbacks entirely.
>>>
>>> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
>>
>> Thank you for these patches. Except for the issue with the lpc18xx patch
>> they all look good to me.
>> If you don't mind, I'll drop the lpc18xx patch for now and apply the
>> others.
>>
>
> It is OK with me, but I do not understand what is the problem.
>
> Could you answer my question in the 3/7 thread?


Now I am convinced.

I leave 3/7 to your decision.



-- 
Best Regards
Masahiro Yamada


From broonie at kernel.org  Tue May  3 04:51:59 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 3 May 2016 12:51:59 +0100
Subject: [RFC PATCH 1/7] ALSA: ac97: split out the generic ac97 registers
In-Reply-To: <1462050939-27940-2-git-send-email-robert.jarzmik@free.fr>
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-2-git-send-email-robert.jarzmik@free.fr>
Message-ID: <20160503115159.GP6292@sirena.org.uk>

On Sat, Apr 30, 2016 at 11:15:33PM +0200, Robert Jarzmik wrote:
> Split out from the ac97_codec.h the ac97 generic registers, which can be
> used by a codec, typically a generic ac97 codec, and by the ac97 bus, to
> scan an ac97 AC-Link.

I don't entirely see the value in this one but equally it does no harm.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160503/bbd13938/attachment.sig>

From timur at codeaurora.org  Tue May  3 05:12:04 2016
From: timur at codeaurora.org (Timur Tabi)
Date: Tue, 3 May 2016 07:12:04 -0500
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
Message-ID: <57289594.3050801@codeaurora.org>

Pratyush Anand wrote:
> + * Note: This watchdog timer has two stages. If action is 0, first stage is
> + * determined by directly programming WCV and second by WOR. When first
> + * timeout is reached, WS0 is triggered and WCV is reloaded with value in
> + * WOR. WS0 interrupt will be ignored, then the second watch period starts;
> + * when second timeout is reached, then WS1 is triggered, system resets. WCV
> + * and WOR are programmed in such a way that total time corresponding to
> + * WCV+WOR becomes equivalent to user programmed "timeout".
> + * If action is 1, then we expect to call panic() at user programmed
> + * "timeout". Therefore, we program both first and second stage using WCV
> + * only.

So I'm not sure I understand how this works yet, but there was an 
earlier version of Fu's driver that did something similar.  It depended 
on being able to reprogram the hardware during the WS0 interrupt, and 
that was rejected by the community.

How is what you are doing different?

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.


From marc.zyngier at arm.com  Tue May  3 05:15:44 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 13:15:44 +0100
Subject: [PATCH v2 05/54] KVM: arm/arm64: Remove the IRQ field from struct
 irq_phys_map
In-Reply-To: <1461861973-26464-6-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-6-git-send-email-andre.przywara@arm.com>
Message-ID: <57289670.6030405@arm.com>

On 28/04/16 17:45, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> The communication of a Linux IRQ number from outside the VGIC to the
> vgic was a leftover from the day when the vgic code cared about how a
> particular device injects virtual interrupts mapped to a physical
> interrupt.
> 
> We can safely remove this notion, leaving all physical IRQ handling to
> be done in the device driver (the arch timer in this case), which makes
> room for a saner API for the new VGIC.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Reviewed-by: Eric Auger <eric.auger at linaro.org>
> ---
> Changelog v1 .. v2:
> - update kerneldoc comments on kvm_vgic_map_phys_irq()
> 
>  include/kvm/arm_vgic.h    |  3 +--
>  virt/kvm/arm/arch_timer.c | 22 ++++++++++++++++++++--
>  virt/kvm/arm/vgic.c       | 28 ++++++----------------------
>  3 files changed, 27 insertions(+), 26 deletions(-)
> 
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 43eeb18..49c559e 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -157,7 +157,6 @@ struct vgic_io_device {
>  struct irq_phys_map {
>  	u32			virt_irq;
>  	u32			phys_irq;
> -	u32			irq;
>  };
>  
>  struct irq_phys_map_entry {
> @@ -345,7 +344,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
>  void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
>  int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
>  struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
> -					   int virt_irq, int irq);
> +					   int virt_irq, int phys_irq);
>  int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
>  bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
>  
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index 58b2439..b470632 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -301,7 +301,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
>  	if (timer->active_cleared_last && !phys_active)
>  		return;
>  
> -	ret = irq_set_irqchip_state(timer->map->irq,
> +	ret = irq_set_irqchip_state(host_vtimer_irq,
>  				    IRQCHIP_STATE_ACTIVE,
>  				    phys_active);
>  	WARN_ON(ret);
> @@ -334,6 +334,9 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
>  {
>  	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
>  	struct irq_phys_map *map;
> +	struct irq_desc *desc;
> +	struct irq_data *data;
> +	int phys_irq;
>  
>  	/*
>  	 * The vcpu timer irq number cannot be determined in
> @@ -353,10 +356,25 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
>  	kvm_timer_update_state(vcpu);
>  
>  	/*
> +	 * Find the physical IRQ number corresponding to the host_vtimer_irq
> +	 */
> +	desc = irq_to_desc(host_vtimer_irq);

Consider adding a #include <linux/irq.h> at the top of this file. Things
do break once the linux/of_irq.h include is removed with the KVM/ACPI
patches.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From javier at osg.samsung.com  Tue May  3 05:17:45 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 3 May 2016 08:17:45 -0400
Subject: [PATCH v2] s5p-mfc: Don't try to put pm->clock if lookup failed
In-Reply-To: <20160503101509.GB3956@kozik-lap>
References: <1462216462-32665-1-git-send-email-javier@osg.samsung.com>
 <20160503101509.GB3956@kozik-lap>
Message-ID: <6290517d-3d9a-c512-875e-6b1871a2ebba@osg.samsung.com>

Hello Krzysztof,

On 05/03/2016 06:15 AM, Krzysztof Kozlowski wrote:
> On Mon, May 02, 2016 at 03:14:22PM -0400, Javier Martinez Canillas wrote:
>> Failing to get the struct s5p_mfc_pm .clock is a non-fatal error so the
>> clock field can have a errno pointer value. But s5p_mfc_final_pm() only
>> checks if .clock is not NULL before attempting to unprepare and put it.
>>
>> This leads to the following warning in clk_put() due s5p_mfc_final_pm():
>>
>> WARNING: CPU: 3 PID: 1023 at drivers/clk/clk.c:2814 s5p_mfc_final_pm+0x48/0x74 [s5p_mfc]
>> CPU: 3 PID: 1023 Comm: rmmod Tainted: G        W       4.6.0-rc6-next-20160502-00005-g5a15a49106bc #9
>> Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>> [<c010e1bc>] (unwind_backtrace) from [<c010af28>] (show_stack+0x10/0x14)
>> [<c010af28>] (show_stack) from [<c032485c>] (dump_stack+0x88/0x9c)
>> [<c032485c>] (dump_stack) from [<c011b8e8>] (__warn+0xe8/0x100)
>> [<c011b8e8>] (__warn) from [<c011b9b0>] (warn_slowpath_null+0x20/0x28)
>> [<c011b9b0>] (warn_slowpath_null) from [<bf16004c>] (s5p_mfc_final_pm+0x48/0x74 [s5p_mfc])
>> [<bf16004c>] (s5p_mfc_final_pm [s5p_mfc]) from [<bf157414>] (s5p_mfc_remove+0x8c/0x94 [s5p_mfc])
>> [<bf157414>] (s5p_mfc_remove [s5p_mfc]) from [<c03fe1f8>] (platform_drv_remove+0x24/0x3c)
>> [<c03fe1f8>] (platform_drv_remove) from [<c03fcc70>] (__device_release_driver+0x84/0x110)
>> [<c03fcc70>] (__device_release_driver) from [<c03fcdd8>] (driver_detach+0xac/0xb0)
>> [<c03fcdd8>] (driver_detach) from [<c03fbff8>] (bus_remove_driver+0x4c/0xa0)
>> [<c03fbff8>] (bus_remove_driver) from [<c01886a8>] (SyS_delete_module+0x174/0x1b8)
>> [<c01886a8>] (SyS_delete_module) from [<c01078c0>] (ret_fast_syscall+0x0/0x3c)
>>
>> Assign the pointer to NULL in case of a lookup failure to fix the issue.
>>
>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>
>> ---
>>
>> Changes in v2:
>> - Set the clock pointer to NULL instead of checking for !IS_ERR_OR_NULL().
>>   Suggested by Arnd Bergmann.
>>
>>  drivers/media/platform/s5p-mfc/s5p_mfc_pm.c | 1 +
>>  1 file changed, 1 insertion(+)
> 
> This is a fix for bug, so for statistics:
> Fixes: d19f405a5a8d ("[media] s5p-mfc: Fix selective sclk_mfc init")
> 
> ... and although not fatal, but annoying so I think this deserves:
> Cc: <stable at vger.kernel.org>
>

Indeed, sorry for missing those.
 
> Anyway:
> Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>

Thanks a lot for your feedback.
 
> Best regards,
> Krzysztof
> 

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From eric.auger at linaro.org  Tue May  3 05:27:08 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 3 May 2016 14:27:08 +0200
Subject: [PATCH v8 6/8] iommu/msi-iommu: iommu_msi_domain
In-Reply-To: <20160502142328.2d97f7a4@t450s.home>
References: <1461831323-5480-1-git-send-email-eric.auger@linaro.org>
 <1461831323-5480-7-git-send-email-eric.auger@linaro.org>
 <20160428162740.28db4b8d@t450s.home> <572776BD.2080503@linaro.org>
 <20160502142328.2d97f7a4@t450s.home>
Message-ID: <5728991C.5060807@linaro.org>

Hi Alex,
On 05/02/2016 10:23 PM, Alex Williamson wrote:
> Hi Eric,
> 
> On Mon, 2 May 2016 17:48:13 +0200
> Eric Auger <eric.auger at linaro.org> wrote:
> 
>> Hi Alex,
>> On 04/29/2016 12:27 AM, Alex Williamson wrote:
>>> On Thu, 28 Apr 2016 08:15:21 +0000
>>> Eric Auger <eric.auger at linaro.org> wrote:
>>>   
>>>> This function checks whether
>>>> - the device belongs to a non default iommu domain
>>>> - this iommu domain requires the MSI address to be mapped.
>>>>
>>>> If those conditions are met, the function returns the iommu domain
>>>> to be used for mapping the MSI doorbell; else it returns NULL.
>>>>
>>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>>>
>>>> ---
>>>>
>>>> v7 -> v8:
>>>> - renamed  iommu_msi_mapping_desc_to_domain to iommu_msi_domain
>>>> - the function now takes a struct device *
>>>> - use DOMAIN_ATTR_MSI_GEOMETRY attribute
>>>> ---
>>>>  drivers/iommu/msi-iommu.c | 17 +++++++++++++++++
>>>>  include/linux/msi-iommu.h | 14 ++++++++++++++
>>>>  2 files changed, 31 insertions(+)
>>>>
>>>> diff --git a/drivers/iommu/msi-iommu.c b/drivers/iommu/msi-iommu.c
>>>> index 203e86e..023ff17 100644
>>>> --- a/drivers/iommu/msi-iommu.c
>>>> +++ b/drivers/iommu/msi-iommu.c
>>>> @@ -243,3 +243,20 @@ unlock:
>>>>  	}
>>>>  }
>>>>  EXPORT_SYMBOL_GPL(iommu_msi_put_doorbell_iova);
>>>> +
>>>> +struct iommu_domain *iommu_msi_domain(struct device *dev)
>>>> +{
>>>> +	struct iommu_domain *d = iommu_get_domain_for_dev(dev);
>>>> +	struct iommu_domain_msi_geometry msi_geometry;
>>>> +
>>>> +	if (!d || (d->type == IOMMU_DOMAIN_DMA))
>>>> +		return NULL;
>>>> +
>>>> +	iommu_domain_get_attr(d, DOMAIN_ATTR_MSI_GEOMETRY, &msi_geometry);
>>>> +	if (!msi_geometry.programmable)  
>>>
>>> It feels like we're conflating ideas with using the "programmable" flag
>>> in this way.  AIUI the IOMMU API consumer is supposed to see the
>>> invalid MSI geometry with the programmable feature set and know to call
>>> iommu_msi_set_aperture().  Looking for the msi_cookie would tell us if
>>> that had been done, but that doesn't tell us if it should have been
>>> done.  iommu_msi_msg_pa_to_va() handles this later, if we return
>>> NULL here that function returns success otherwise it goes on to fail if
>>> the iova or msi cookie is not set.  So really what we're trying to flag
>>> is that the MSI geometry participates in the IOMMU-MSI API you've
>>> created and we should pick a feature name that says that rather than
>>> something as vague a "programmable".  Perhaps simply iommu_msi_api
>>> rather than programmable.  
>> Yes I had the same questioning too when I wrote this code. So if my
>> understanding is correct we would have
>> - programmable: tells whether the MSI range is fixed or pogrammable and,
>> - mapping_required (new boolean field): indicating whether MSIs need to
>> be mapped in the IOMMU
> 
> Let's say we had a flag "iommu_msi_supported", doesn't that already
> tell us whether the MSI range is programmable and the API to use to do
> it?  Can't we figure out if mapping is required based on whether
> iommu_msi_supported is set and aperture_start and aperture_end indicate
> a valid range?  It seems like what we want on this code path is to
> simply know whether the IOMMU domain is relevant to the IOMMU MSI API,
> which would be abundantly clear with such a flag.
OK I now get your point. Thanks for the clarification. I renamed
programmable into iommu_msi_supported.
> 
>>>
>>> BTW, I don't see that you ever set aperture_start/end once
>>> iommu_msi_set_aperture() has been called.  It seems like doing so would
>>> add some consistency to that MSI geometry attribute.  
>> Indeed currently I mentionned:
>> /* In case the aperture is programmable, start/end are set to 0 */
> 
> Which is confusing, if a user sets an aperture, I would think they'd
> like to see the MSI geometry updated to reflect that.
> 
>> If I set start/end in iommu_msi_set_aperture then I think I should also
>> return the actual values in iommu_domain_get_attr. I thought the extra
>> care to handle the possible race between the set_aperture (msi_iommu)
>> and the get_attr (iommu) was maybe not worth the benefits:
>> is_aperture_set is not visible to get_attr so I would be forced to
>> introduce a mutex at iommu_domain level or call an msi-iommu function
>> from iommu implementation. So I preferred to keep start/end as read-only
>> info initialized by the iommu driver.
> 
> Seems like a race between iommu_msi_set_aperture() and
> iommu_domain_get_attr() is the caller's problem.  We can always define
> that start >= end is invalid and set them in the right order that
> iommu_domain_get_attr() may get different versions of invalid, but it
> will always be invalid or valid.  A helper function could tell us if we
> have a valid range rather than using is_aperture_set.  Thanks,


Agreed; I added an iommu_domain_msi_aperture_valid helper function.

Thanks!

Eric
> 
> Alex
> 



From shawnguo at kernel.org  Tue May  3 05:36:33 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 20:36:33 +0800
Subject: [PATCH] clk: imx: fix ahb clock mux 1
In-Reply-To: <20160429081901.GU7946@pengutronix.de>
References: <1461877623-26838-1-git-send-email-stefan@agner.ch>
 <20160429081901.GU7946@pengutronix.de>
Message-ID: <20160503123633.GF5874@tiger>

On Fri, Apr 29, 2016 at 10:19:01AM +0200, Uwe Kleine-K?nig wrote:
> Hello,
> 
> $Subject ~= s/imx/imx7/

Updated the subject and applied the patch.

Shawn


From shawnguo at kernel.org  Tue May  3 05:37:19 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 20:37:19 +0800
Subject: [PATCH] clk: imx: fix ahb clock mux 1
In-Reply-To: <CAA+hA=Rkfii=Mi-NuESpX8E3W37+PnCxa464yOAe5dYMgpt43g@mail.gmail.com>
References: <1461877623-26838-1-git-send-email-stefan@agner.ch>
 <20160503083253.GC5874@tiger>
 <CAA+hA=Rkfii=Mi-NuESpX8E3W37+PnCxa464yOAe5dYMgpt43g@mail.gmail.com>
Message-ID: <20160503123718.GG5874@tiger>

On Tue, May 03, 2016 at 06:50:21PM +0800, Dong Aisheng wrote:
> Hi Shawn,
> 
> On Tue, May 3, 2016 at 4:32 PM, Shawn Guo <shawnguo at kernel.org> wrote:
> > On Thu, Apr 28, 2016 at 02:07:03PM -0700, Stefan Agner wrote:
> >> The clock parent of the AHB root clock when using mux option 1
> >> is the SYS PLL 270MHz clock. This is specified in  Table 5-11
> >> Clock Root Table of the i.MX 7Dual Applications Processor
> >> Reference Manual.
> >>
> >> While it could be a documentation error, the 270MHz parent is
> >> also mentioned in the boot ROM configuration in Table 6-28: The
> >> clock is by default at 135MHz due to a POST_PODF value of 1
> >> (=> divider of 2).
> >>
> >> Signed-off-by: Stefan Agner <stefan at agner.ch>
> >
> > Anson, Frank,
> >
> > Can you guys confirm this change is correct?
> >
> 
> I just checked the doc,
> it's correct the parent should be SYS_PLL_PFD2(270Mhz).
> It's a documentation error of early version and it's already fixed
> in latest internal doc.

Thanks for the confirmation.

Shawn


From oliver at schinagl.nl  Tue May  3 05:42:06 2016
From: oliver at schinagl.nl (Olliver Schinagl)
Date: Tue,  3 May 2016 14:42:06 +0200
Subject: [PATCHv2] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
Message-ID: <1462279326-9852-1-git-send-email-oliver@schinagl.nl>

There are 3 kinds of OLinuXino Lime2 boards.
One without any on board storage, one with NAND storage and one with
eMMC storage. This patch adds the eMMC variant of boards.

eMMC storage is different from a regular SD card in that it is soldered
on the board and cannot be changed. Additionally, it shares pins with
the NAND module and with the second SPI port.

Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>
---
 .../boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts    | 64 ++++++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts

diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
new file mode 100644
index 0000000..b49aafe
--- /dev/null
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
@@ -0,0 +1,64 @@
+ /*
+ * Copyright 2015 - Ultimaker B.V.
+ * Author Olliver Schinagl <oliver at schinagl.nl>
+ *
+ * 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.
+ */
+
+#include "sun7i-a20-olinuxino-lime2.dts"
+
+/ {
+	model = "Olimex A20-OLinuXino-LIME2-eMMC";
+};
+
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins_a>;
+	vmmc-supply = <&reg_vcc3v3>;
+	vqmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+
+	emmc: emmc at 0 {
+		reg = <0>;
+		compatible = "mmc-card";
+		broken-hpi;
+	};
+};
-- 
2.8.1



From shawnguo at kernel.org  Tue May  3 05:42:03 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 20:42:03 +0800
Subject: mx6ul: Finding a good place to configure SAI2_MCLK
In-Reply-To: <CAOMZO5CvT1rcHFPm6KoCBBgM1UACByLUQcJ_zDxY9ucbxCpgYA@mail.gmail.com>
References: <CAOMZO5CvT1rcHFPm6KoCBBgM1UACByLUQcJ_zDxY9ucbxCpgYA@mail.gmail.com>
Message-ID: <20160503124203.GH5874@tiger>

On Mon, May 02, 2016 at 08:59:17PM -0300, Fabio Estevam wrote:
> Hi,
> 
> In order to get audio working on imx6ul-evk board we need to enable
> the SAI2 MCLK clock by setting bit 20 (SAI2_MCLK_DIR) of the
> IOMUXC_GPR_GPR1 register.
> 
> I am not sure where is the appropriate place to set this bit.
> 
> Doing like this works fine:
> 
> --- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
> +++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
> @@ -447,5 +447,6 @@
>  #define IMX6UL_GPR1_ENET2_CLK_OUTPUT           (0x1 << 18)
>  #define IMX6UL_GPR1_ENET_CLK_DIR               (0x3 << 17)
>  #define IMX6UL_GPR1_ENET_CLK_OUTPUT            (0x3 << 17)
> +#define IMX6UL_GPR1_SAI2_MCLK_DIR              (0x1 << 20)
> 
> index a38b16b..92cfb0f 100644
> --- a/arch/arm/mach-imx/mach-imx6ul.c
> +++ b/arch/arm/mach-imx/mach-imx6ul.c
> @@ -56,6 +56,19 @@ static inline void imx6ul_enet_init(void)
>         imx6ul_enet_phy_init();
>  }
> 
> +static void __init imx6ul_mclk_init(void)
> +{
> +       struct regmap *gpr;
> +
> +       gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr");
> +       if (!IS_ERR(gpr))
> +               regmap_update_bits(gpr, IOMUXC_GPR1, IMX6UL_GPR1_SAI2_MCLK_DIR,
> +                                  IMX6UL_GPR1_SAI2_MCLK_DIR);
> +       else
> +               pr_err("failed to find fsl,imx6ul-iomux-gpr regmap\n");
> +
> +}
> +
>  static void __init imx6ul_init_machine(void)
>  {
>         struct device *parent;
> @@ -68,6 +81,7 @@ static void __init imx6ul_init_machine(void)
>         imx6ul_enet_init();
>         imx_anatop_init();
>         imx6ul_pm_init();
> +       imx6ul_mclk_init();
>  }
> 
> but it does not seem correct as this should be board specific. Should
> we call it only if the compatible string matches imx6sl-14x14-evk
> string? Looks like that will not scale as well.
> 
> Currently in arch/arm/mach-imx/mach-imx6ul.c we also have
> imx6ul_enet_clk_init() function which sets the ENET_CLK in the GPR1
> register.
> 
> IMHO this is not correct because not all mx6ul boards need such clock
> and then we need to change this too.
> 
> So where should we set the SAI2_MCLK_DIR bit of GPR1? Inside the SAI driver?

To me, it's the best if we can handle this in SAI driver.

Shawn

> 
> Appreciate some feedback.
> 
> Thanks,
> 
> Fabio Estevam
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From shawnguo at kernel.org  Tue May  3 05:43:10 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 20:43:10 +0800
Subject: [PATCH] ARM: dts: imx6qdl: Remove unneeded unit-addresses
In-Reply-To: <1461969585-17784-1-git-send-email-festevam@gmail.com>
References: <1461969585-17784-1-git-send-email-festevam@gmail.com>
Message-ID: <20160503124309.GI5874@tiger>

On Fri, Apr 29, 2016 at 07:39:45PM -0300, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam at nxp.com>
> 
> The following build warnings are seen when building with 'W=1' option:
> 
> Warning (unit_address_vs_reg): Node /soc/aips-bus at 02000000/anatop at 020c8000/regulator-1p1 at 110 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /soc/aips-bus at 02000000/anatop at 020c8000/regulator-3p0 at 120 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /soc/aips-bus at 02000000/anatop at 020c8000/regulator-2p5 at 130 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /soc/aips-bus at 02000000/anatop at 020c8000/regulator-vddcore at 140 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /soc/aips-bus at 02000000/anatop at 020c8000/regulator-vddpu at 140 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /soc/aips-bus at 02000000/anatop at 020c8000/regulator-vddsoc at 140 has a unit name, but no reg property
> 
> Fix them by removing the unneeded unit-addresses.
> 
> Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>

Applied, thanks.


From jason at lakedaemon.net  Tue May  3 05:46:18 2016
From: jason at lakedaemon.net (Jason Cooper)
Date: Tue, 3 May 2016 12:46:18 +0000
Subject: [PATCH v6 00/10] arm64: Add support for KVM with ACPI
In-Reply-To: <20160503082124.GA17923@cbox>
References: <1460388780-914-1-git-send-email-julien.grall@arm.com>
 <57220C73.7010900@arm.com>
 <20160502125414.GR27057@io.lakedaemon.net>
 <20160503082124.GA17923@cbox>
Message-ID: <20160503124618.GW27057@io.lakedaemon.net>

On Tue, May 03, 2016 at 10:21:24AM +0200, Christoffer Dall wrote:
> On Mon, May 02, 2016 at 12:54:14PM +0000, Jason Cooper wrote:
> > On Thu, Apr 28, 2016 at 02:13:23PM +0100, Marc Zyngier wrote:
> > > [+ Thomas, Jason]
> > > 
> > > Do you have any objection against this going through the KVM tree? The
> > > dependencies are rather intricate, and Daniel gave us his green light
> > > already for the clocksource part.
> > > 
> > > If you'd rather maintain the usual flow, please let us know and we'll
> > > deal with it.
> > 
> > I've no objection.
> > 
> > Acked-by: Jason Cooper <jason at lakedaemon.net>
> > 
> Just to be clear, that's on all the irqchip patches, right?

Correct.

thx,

Jason.


From bamvor.zhangjian at huawei.com  Tue May  3 05:41:25 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Tue, 3 May 2016 20:41:25 +0800
Subject: [PATCH 24/25] arm64:ilp32: add vdso-ilp32 and use for signal
 return
In-Reply-To: <57288660.9030607@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1554541.oDP7Ro5zB2@wuerfel>
 <20160503090045.GB10733@e104818-lin.cambridge.arm.com>
 <3846428.6xx69KGEja@wuerfel> <57288660.9030607@huawei.com>
Message-ID: <57289C75.50904@huawei.com>

Hi, all

On 2016/5/3 19:07, Zhangjian (Bamvor) wrote:
>
>
> On 2016/5/3 17:05, Arnd Bergmann wrote:
>> On Tuesday 03 May 2016 10:00:45 Catalin Marinas wrote:
>>> On Fri, Apr 29, 2016 at 07:30:19PM +0200, Arnd Bergmann wrote:
>>>> On Friday 29 April 2016 17:01:55 Catalin Marinas wrote:
>>>>> On Wed, Apr 06, 2016 at 01:08:46AM +0300, Yury Norov wrote:
>>>>>> ILP32 VDSO exports next symbols:
>>>>>>   __kernel_rt_sigreturn;
>>>>>>   __kernel_gettimeofday;
>>>>>>   __kernel_clock_gettime;
>>>>>>   __kernel_clock_getres;
>>>>>
>>>>> [...]
>>>>>
>>>>>> +$(obj)/gettimeofday-ilp32.o: $(src)/../vdso/gettimeofday.S
>>>>>> + $(call if_changed_dep,vdso-ilp32as)
>>>>>
>>>>> Are struct timeval and timespec the same between ILP32 and LP64? For
>>>>> example, __kernel_gettimeofday() assumes TVAL_TV_SEC offset defined in
>>>>> asm-offsets.c based on the LP64 timeval.
>>>>
>>>> No, ilp32 uses the generic 32-bit data structures, which have a 32-bit
>>>> time_t. I guess that means it can work for little-endian but not
>>>> big-endian, right?
>>>
>>> I don't think it works for little-endian either. The LP64 struct timeval
>>> is 16 bytes while the ILP32 one is 8 bytes. The VDSO gettimeofday is
>>> storing 16 bytes (stp x10, x11, [x0, #TVAL_TV_SEC])
>>
>> You are right. Yury asked pointed out the same thing on IRC as well.
>> Using the 64-bit gettimeofday() will put the right number in the
>> .tv_sec member on little-endian, but will write zeroes to tv_nsec
>> and corrupt the memory following it.
>>
>> Yury also tried it out and noticed that for a (so far) unknown reason,
>> the vdso gets never used by his glibc build, so it has not triggered
>> any test case failures.
> We found this issue too. And it is because the version is different from
> the glibc wanted. We define 2.6.39 for lp64 but 2.6 for ilp32 in vdso
> in kernel:
> +VERSION
> +{
> +    LINUX_2.6 {
> +    global:
> +        __kernel_rt_sigreturn;
> +        __kernel_gettimeofday;
> +        __kernel_clock_gettime;
> +        __kernel_clock_getres;
> +    local: *;
> +    };
> +}
> If I change 2.6 to 2.6.39, the ilp32 application will call vdso instead
> of syscall. But the result is wrong as Catalin mentioned before.
>
> Should we set this version to 4.6 or higher version? We will need to update
> the version in "sysdeps/unix/sysv/linux/aarch64/init-first.c" too:
> static inline void
> _libc_vdso_platform_setup (void)
> {
>    PREPARE_VERSION (linux2639, "LINUX_2.6.39", 123718537);
>
>    void *p = _dl_vdso_vsym ("__kernel_gettimeofday", &linux2639);
>    PTR_MANGLE (p);
>    VDSO_SYMBOL(gettimeofday) = p;
>
>    p = _dl_vdso_vsym ("__kernel_clock_gettime", &linux2639);
>    PTR_MANGLE (p);
>    VDSO_SYMBOL(clock_gettime) = p;
>
>    p = _dl_vdso_vsym ("__kernel_clock_getres", &linux2639);
>    PTR_MANGLE (p);
>    VDSO_SYMBOL(clock_getres) = p;
> }

After apply this patch with my small testcase, the vsyscall of gettimeofday in
ilp32 works in both big endian and small endian. In this patch, I use the
different register and offset for ilp32 and lp64. Actually, the
COMPAT_TVAL_TV_SEC is same as TVAL_TV_SEC(so as to COMPAT_TSPEC_TV_SEC and
TSPEC_TV_SEC). I add it to keep the logic clear. I also change the version
of vdso to 4.6. It should change to 2.6.39 if glibc is not update.

diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 574081f..c8e32eb 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -101,6 +101,11 @@ int main(void)
    DEFINE(TSPEC_TV_SEC,		offsetof(struct timespec, tv_sec));
    DEFINE(TSPEC_TV_NSEC,		offsetof(struct timespec, tv_nsec));
    BLANK();
+  DEFINE(COMPAT_TVAL_TV_SEC,	offsetof(struct compat_timeval, tv_sec));
+  DEFINE(COMPAT_TVAL_TV_USEC,	offsetof(struct compat_timeval, tv_usec));
+  DEFINE(COMPAT_TSPEC_TV_SEC,	offsetof(struct compat_timespec, tv_sec));
+  DEFINE(COMPAT_TSPEC_TV_NSEC,	offsetof(struct compat_timespec, tv_nsec));
+  BLANK();
    DEFINE(TZ_MINWEST,		offsetof(struct timezone, tz_minuteswest));
    DEFINE(TZ_DSTTIME,		offsetof(struct timezone, tz_dsttime));
    BLANK();
diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
index ddc63fd..d182a8d 100644
--- a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
+++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
@@ -79,7 +79,7 @@ PHDRS
   */
  VERSION
  {
-	LINUX_2.6 {
+	LINUX_4.6 {
  	global:
  		__kernel_rt_sigreturn;
  		__kernel_gettimeofday;
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index efa79e8..4551f55 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -25,6 +25,14 @@
  #define NSEC_PER_SEC_LO16	0xca00
  #define NSEC_PER_SEC_HI16	0x3b9a

+#ifdef __LP64__
+#define PTR_REG(n)      x##n
+#define OFFSET(n)	n
+#else
+#define PTR_REG(n)      w##n
+#define OFFSET(n)	COMPAT_##n
+#endif
+
  vdso_data	.req	x6
  use_syscall	.req	w7
  seqcnt		.req	w8
@@ -68,7 +76,7 @@ ENTRY(__kernel_gettimeofday)
  	mov	x13, #1000
  	lsl	x13, x13, x12
  	udiv	x11, x11, x13
-	stp	x10, x11, [x0, #TVAL_TV_SEC]
+	stp	PTR_REG(10), PTR_REG(11), [x0, #OFFSET(TVAL_TV_SEC)]
  2:
  	/* If tz is NULL, return 0. */
  	cbz	x1, 3f
@@ -159,7 +167,7 @@ ENTRY(__kernel_clock_gettime)

  6:	/* Store to the user timespec. */
  	lsr	x11, x11, x12
-	stp	x10, x11, [x1, #TSPEC_TV_SEC]
+	stp	PTR_REG(10), PTR_REG(11), [x1, #OFFSET(TSPEC_TV_SEC)]
  	mov	x0, xzr
  	ret
  7:
-- 
1.8.4.5

I am not sure if I should merge above patch into original one. If I
merge it with another patch I send in 13, April, The overall patch is
as follows. I could resend the following patch to this thread if
needed:

 From b0a74395cbf18643f3f5b410be425df85d8d68d1 Mon Sep 17 00:00:00 2001
From: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
Date: Wed, 6 Apr 2016 01:08:46 +0300
Subject: [PATCH] arm64:ilp32: add vdso-ilp32 and use for signal return

ILP32 VDSO exports next symbols:
  __kernel_rt_sigreturn;
  __kernel_gettimeofday;
  __kernel_clock_gettime;
  __kernel_clock_getres;

What shared object to use, kernel selects depending on result of
is_ilp32_compat_task() in arch/arm64/kernel/vdso.c, so it substitutes
correct pages and spec.

Adjusted to move the move data page before code pages in sync with
commit 601255ae3c98fdeeee3a8bb4696425e4f868b4f1

Care must be taken when we update time to user space for ilp32.
Because the size of time struct(timeval, timespec) is different from
lp64.

Signed-off-by: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
Signed-off-by: Christoph Muellner <christoph.muellner at theobroma-systems.com>
Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
Signed-off-by: Bamvor Jian Zhang <bamvor.zhangjian at huawei.com>
---
  arch/arm64/include/asm/vdso.h                 |  6 ++
  arch/arm64/kernel/Makefile                    |  7 ++
  arch/arm64/kernel/asm-offsets.c               |  5 ++
  arch/arm64/kernel/signal.c                    |  2 +
  arch/arm64/kernel/vdso-ilp32/.gitignore       |  2 +
  arch/arm64/kernel/vdso-ilp32/Makefile         | 72 ++++++++++++++++++++
  arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S     | 33 ++++++++++
  arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 95 +++++++++++++++++++++++++++
  arch/arm64/kernel/vdso.c                      | 61 ++++++++++++++---
  arch/arm64/kernel/vdso/gettimeofday.S         | 12 +++-
  10 files changed, 283 insertions(+), 12 deletions(-)
  create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore
  create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile
  create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
  create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S

diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
index 839ce00..649a9a4 100644
--- a/arch/arm64/include/asm/vdso.h
+++ b/arch/arm64/include/asm/vdso.h
@@ -29,6 +29,12 @@

  #include <generated/vdso-offsets.h>

+#ifdef CONFIG_ARM64_ILP32
+#include <generated/vdso-ilp32-offsets.h>
+#else
+#define vdso_offset_sigtramp_ilp32
+#endif
+
  #define VDSO_SYMBOL(base, name)						   \
  ({									   \
  	(void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 09e4373..0f27a10 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -50,6 +50,7 @@ arm64-obj-$(CONFIG_PARAVIRT)		+= paravirt.o
  arm64-obj-$(CONFIG_RANDOMIZE_BASE)	+= kaslr.o

  obj-y					+= $(arm64-obj-y) vdso/
+obj-$(CONFIG_ARM64_ILP32)		+= vdso-ilp32/
  obj-m					+= $(arm64-obj-m)
  head-y					:= head.o
  extra-y					+= $(head-y) vmlinux.lds
@@ -57,3 +58,9 @@ extra-y					+= $(head-y) vmlinux.lds
  # vDSO - this must be built first to generate the symbol offsets
  $(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h
  $(obj)/vdso/vdso-offsets.h: $(obj)/vdso
+
+# vDSO - this must be built first to generate the symbol offsets
+ifeq ($(CONFIG_ARM64_ILP32),y)
+$(call objectify,$(arm64-obj-y)): $(obj)/vdso-ilp32/vdso-ilp32-offsets.h
+$(obj)/vdso-ilp32/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32
+endif
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index e229525..e5db887 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -101,6 +101,11 @@ int main(void)
    DEFINE(TSPEC_TV_SEC,		offsetof(struct timespec, tv_sec));
    DEFINE(TSPEC_TV_NSEC,		offsetof(struct timespec, tv_nsec));
    BLANK();
+  DEFINE(COMPAT_TVAL_TV_SEC,	offsetof(struct compat_timeval, tv_sec));
+  DEFINE(COMPAT_TVAL_TV_USEC,	offsetof(struct compat_timeval, tv_usec));
+  DEFINE(COMPAT_TSPEC_TV_SEC,	offsetof(struct compat_timespec, tv_sec));
+  DEFINE(COMPAT_TSPEC_TV_NSEC,	offsetof(struct compat_timespec, tv_nsec));
+  BLANK();
    DEFINE(TZ_MINWEST,		offsetof(struct timezone, tz_minuteswest));
    DEFINE(TZ_DSTTIME,		offsetof(struct timezone, tz_dsttime));
    BLANK();
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 45bcd96..933cdcf 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -264,6 +264,8 @@ void setup_return(struct pt_regs *regs, struct k_sigaction *ka,

  	if (ka->sa.sa_flags & SA_RESTORER)
  		sigtramp = ka->sa.sa_restorer;
+	else if (is_ilp32_compat_task())
+		sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp_ilp32);
  	else
  		sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);

diff --git a/arch/arm64/kernel/vdso-ilp32/.gitignore b/arch/arm64/kernel/vdso-ilp32/.gitignore
new file mode 100644
index 0000000..61806c3
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/.gitignore
@@ -0,0 +1,2 @@
+vdso-ilp32.lds
+vdso-ilp32-offsets.h
diff --git a/arch/arm64/kernel/vdso-ilp32/Makefile b/arch/arm64/kernel/vdso-ilp32/Makefile
new file mode 100644
index 0000000..c8f5472
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/Makefile
@@ -0,0 +1,72 @@
+#
+# Building a vDSO image for AArch64.
+#
+# Author: Will Deacon <will.deacon at arm.com>
+# Heavily based on the vDSO Makefiles for other archs.
+#
+
+obj-ilp32-vdso := gettimeofday-ilp32.o note-ilp32.o sigreturn-ilp32.o
+
+# Build rules
+targets := $(obj-ilp32-vdso) vdso-ilp32.so vdso-ilp32.so.dbg
+obj-ilp32-vdso := $(addprefix $(obj)/, $(obj-ilp32-vdso))
+
+ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-ilp32-vdso.so.1 \
+		$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+
+obj-y += vdso-ilp32.o
+extra-y += vdso-ilp32.lds vdso-ilp32-offsets.h
+CPPFLAGS_vdso-ilp32.lds += -P -C -U$(ARCH) -mabi=ilp32
+
+# Force dependency (incbin is bad)
+$(obj)/vdso-ilp32.o : $(obj)/vdso-ilp32.so
+
+# Link rule for the .so file, .lds has to be first
+$(obj)/vdso-ilp32.so.dbg: $(src)/vdso-ilp32.lds $(obj-ilp32-vdso)
+	$(call if_changed,vdso-ilp32ld)
+
+# Strip rule for the .so file
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+	$(call if_changed,objcopy)
+
+# Generate VDSO offsets using helper script
+gen-vdsosym := $(srctree)/$(src)/../vdso/gen_vdso_offsets.sh
+quiet_cmd_vdsosym = VDSOSYM $@
+define cmd_vdsosym
+	$(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ && \
+	cp $@ include/generated/
+endef
+
+$(obj)/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32.so.dbg FORCE
+	$(call if_changed,vdsosym)
+
+# Assembly rules for the .S files
+#$(obj-ilp32-vdso): %.o: $(src)/../vdso/$(subst -ilp32,,%.S)
+#	$(call if_changed_dep,vdso-ilp32as)
+
+$(obj)/gettimeofday-ilp32.o: $(src)/../vdso/gettimeofday.S
+	$(call if_changed_dep,vdso-ilp32as)
+
+$(obj)/note-ilp32.o: $(src)/../vdso/note.S
+	$(call if_changed_dep,vdso-ilp32as)
+
+$(obj)/sigreturn-ilp32.o: $(src)/../vdso/sigreturn.S
+	$(call if_changed_dep,vdso-ilp32as)
+
+# Actual build commands
+quiet_cmd_vdso-ilp32ld = VDSOILP32L $@
+      cmd_vdso-ilp32ld = $(CC) $(c_flags) -mabi=ilp32  -Wl,-n -Wl,-T $^ -o $@
+quiet_cmd_vdso-ilp32as = VDSOILP32A $@
+      cmd_vdso-ilp32as = $(CC) $(a_flags) -mabi=ilp32 -c -o $@ $<
+
+# Install commands for the unstripped file
+quiet_cmd_vdso_install = INSTALL $@
+      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+
+vdso-ilp32.so: $(obj)/vdso-ilp32.so.dbg
+	@mkdir -p $(MODLIB)/vdso
+	$(call cmd,vdso_install)
+
+vdso_install: vdso-ilp32.so
diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
new file mode 100644
index 0000000..46ac072
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon at arm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/const.h>
+#include <asm/page.h>
+
+	__PAGE_ALIGNED_DATA
+
+	.globl vdso_ilp32_start, vdso_ilp32_end
+	.balign PAGE_SIZE
+vdso_ilp32_start:
+	.incbin "arch/arm64/kernel/vdso-ilp32/vdso-ilp32.so"
+	.balign PAGE_SIZE
+vdso_ilp32_end:
+
+	.previous
diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
new file mode 100644
index 0000000..d182a8d
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
@@ -0,0 +1,95 @@
+/*
+ * GNU linker script for the VDSO library.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon at arm.com>
+ * Heavily based on the vDSO linker scripts for other archs.
+ */
+
+#include <linux/const.h>
+#include <asm/page.h>


+#include <asm/vdso.h>
+
+SECTIONS
+{
+	PROVIDE(_vdso_data = . - PAGE_SIZE);
+	. = VDSO_LBASE + SIZEOF_HEADERS;
+
+	.hash		: { *(.hash) }			:text
+	.gnu.hash	: { *(.gnu.hash) }
+	.dynsym		: { *(.dynsym) }
+	.dynstr		: { *(.dynstr) }
+	.gnu.version	: { *(.gnu.version) }
+	.gnu.version_d	: { *(.gnu.version_d) }
+	.gnu.version_r	: { *(.gnu.version_r) }
+
+	.note		: { *(.note.*) }		:text	:note
+
+	. = ALIGN(16);
+
+	.text		: { *(.text*) }			:text	=0xd503201f
+	PROVIDE (__etext = .);
+	PROVIDE (_etext = .);
+	PROVIDE (etext = .);
+
+	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
+	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
+
+	.dynamic	: { *(.dynamic) }		:text	:dynamic
+
+	.rodata		: { *(.rodata*) }		:text
+
+	_end = .;
+	PROVIDE(end = .);
+
+	/DISCARD/	: {
+		*(.note.GNU-stack)
+		*(.data .data.* .gnu.linkonce.d.* .sdata*)
+		*(.bss .sbss .dynbss .dynsbss)
+	}
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
+	note		PT_NOTE		FLAGS(4);		/* PF_R */
+	eh_frame_hdr	PT_GNU_EH_FRAME;
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+	LINUX_4.6 {
+	global:
+		__kernel_rt_sigreturn;
+		__kernel_gettimeofday;
+		__kernel_clock_gettime;
+		__kernel_clock_getres;
+	local: *;
+	};
+}
+
+/*
+ * Make the sigreturn code visible to the kernel.
+ */
+VDSO_sigtramp_ilp32		= __kernel_rt_sigreturn;
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 26352a6..521a8e4 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -40,6 +40,12 @@ extern char vdso_start, vdso_end;
  static unsigned long vdso_pages;
  static struct page **vdso_pagelist;

+#ifdef CONFIG_ARM64_ILP32
+extern char vdso_ilp32_start, vdso_ilp32_end;
+static unsigned long vdso_ilp32_pages;
+static struct page **vdso_ilp32_pagelist;
+#endif
+
  /*
   * The vDSO data page.
   */
@@ -109,24 +115,29 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
  }
  #endif /* CONFIG_AARCH32_EL0 */

-static struct vm_special_mapping vdso_spec[2];
-
-static int __init vdso_init(void)
+static int __init vdso_init_common(char *vdso_start, char *vdso_end,
+					  unsigned long *vdso_pagesp,
+					  struct page ***vdso_pagelistp,
+					  struct vm_special_mapping* vdso_spec)
  {
  	int i;
+	unsigned long vdso_pages;
+	struct page **vdso_pagelist;

-	if (memcmp(&vdso_start, "\177ELF", 4)) {
+	if (memcmp(vdso_start, "\177ELF", 4)) {
  		pr_err("vDSO is not a valid ELF object!\n");
  		return -EINVAL;
  	}

-	vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
+	vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
+	*vdso_pagesp = vdso_pages;
  	pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
-		vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data);
+		vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data);

  	/* Allocate the vDSO pagelist, plus a page for the data. */
  	vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
  				GFP_KERNEL);
+	*vdso_pagelistp = vdso_pagelist;
  	if (vdso_pagelist == NULL)
  		return -ENOMEM;

@@ -135,7 +146,7 @@ static int __init vdso_init(void)

  	/* Grab the vDSO code pages. */
  	for (i = 0; i < vdso_pages; i++)
-		vdso_pagelist[i + 1] = virt_to_page(&vdso_start + i * PAGE_SIZE);
+		vdso_pagelist[i + 1] = virt_to_page(vdso_start + i * PAGE_SIZE);

  	/* Populate the special mapping structures */
  	vdso_spec[0] = (struct vm_special_mapping) {
@@ -150,16 +161,46 @@ static int __init vdso_init(void)

  	return 0;
  }
+
+static struct vm_special_mapping vdso_spec[2];
+
+static int __init vdso_init(void)
+{
+	return vdso_init_common(&vdso_start, &vdso_end,
+				&vdso_pages, &vdso_pagelist,
+				vdso_spec);
+}
  arch_initcall(vdso_init);

+#ifdef CONFIG_ARM64_ILP32
+static struct vm_special_mapping vdso_ilp32_spec[2];
+
+static int __init vdso_ilp32_init(void)
+{
+	return vdso_init_common(&vdso_ilp32_start, &vdso_ilp32_end,
+				&vdso_ilp32_pages, &vdso_ilp32_pagelist,
+				vdso_ilp32_spec);
+}
+arch_initcall(vdso_ilp32_init);
+#endif
+
  int arch_setup_additional_pages(struct linux_binprm *bprm,
  				int uses_interp)
  {
  	struct mm_struct *mm = current->mm;
  	unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
  	void *ret;
+	unsigned long pages = vdso_pages;
+	struct vm_special_mapping *spec = vdso_spec;
+
+#ifdef CONFIG_ARM64_ILP32
+	if (is_ilp32_compat_task()) {
+	        pages = vdso_ilp32_pages;
+	        spec = vdso_ilp32_spec;
+	}
+#endif

-	vdso_text_len = vdso_pages << PAGE_SHIFT;
+	vdso_text_len = pages << PAGE_SHIFT;
  	/* Be sure to map the data page */
  	vdso_mapping_len = vdso_text_len + PAGE_SIZE;

@@ -171,7 +212,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
  	}
  	ret = _install_special_mapping(mm, vdso_base, PAGE_SIZE,
  				       VM_READ|VM_MAYREAD,
-				       &vdso_spec[0]);
+				       &spec[0]);
  	if (IS_ERR(ret))
  		goto up_fail;

@@ -180,7 +221,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
  	ret = _install_special_mapping(mm, vdso_base, vdso_text_len,
  				       VM_READ|VM_EXEC|
  				       VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
-				       &vdso_spec[1]);
+				       &spec[1]);
  	if (IS_ERR(ret))
  		goto up_fail;

diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index efa79e8..4551f55 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -25,6 +25,14 @@
  #define NSEC_PER_SEC_LO16	0xca00
  #define NSEC_PER_SEC_HI16	0x3b9a

+#ifdef __LP64__
+#define PTR_REG(n)      x##n
+#define OFFSET(n)	n
+#else
+#define PTR_REG(n)      w##n
+#define OFFSET(n)	COMPAT_##n
+#endif
+
  vdso_data	.req	x6
  use_syscall	.req	w7
  seqcnt		.req	w8
@@ -68,7 +76,7 @@ ENTRY(__kernel_gettimeofday)
  	mov	x13, #1000
  	lsl	x13, x13, x12
  	udiv	x11, x11, x13
-	stp	x10, x11, [x0, #TVAL_TV_SEC]
+	stp	PTR_REG(10), PTR_REG(11), [x0, #OFFSET(TVAL_TV_SEC)]
  2:
  	/* If tz is NULL, return 0. */
  	cbz	x1, 3f
@@ -159,7 +167,7 @@ ENTRY(__kernel_clock_gettime)

  6:	/* Store to the user timespec. */
  	lsr	x11, x11, x12
-	stp	x10, x11, [x1, #TSPEC_TV_SEC]
+	stp	PTR_REG(10), PTR_REG(11), [x1, #OFFSET(TSPEC_TV_SEC)]
  	mov	x0, xzr
  	ret
  7:
-- 
1.8.4.5

Regads

Bamvor
> Regards
>
> Bamvor
>
>>
>>     Arnd
>>
>



From shawnguo at kernel.org  Tue May  3 05:48:54 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 20:48:54 +0800
Subject: [PATCH] ARM: dts: imx6ul-14x14-evk: Add audio support
In-Reply-To: <1462233386-23185-1-git-send-email-festevam@gmail.com>
References: <1462233386-23185-1-git-send-email-festevam@gmail.com>
Message-ID: <20160503124854.GJ5874@tiger>

On Mon, May 02, 2016 at 08:56:26PM -0300, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam at nxp.com>
> 
> imx6ul-14x14-evk has a wm8960 codec connected via SAI2 port.
> 
> Add support for it.
> 
> Thanks to Petr Kulhavy <brain at jikos.cz> for the hint on initializing
> the PLL4 frequency to get a correct MCLK.
> 
> Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>

Applied, thanks.


From bamvor.zhangjian at huawei.com  Tue May  3 05:49:02 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Tue, 3 May 2016 20:49:02 +0800
Subject: [PATCH 24/25] arm64:ilp32: add vdso-ilp32 and use for signal
 return
In-Reply-To: <20160413155540.GA23856@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1459894127-17698-25-git-send-email-ynorov@caviumnetworks.com>
 <570E0F20.1020101@huawei.com> <20160413155540.GA23856@yury-N73SV>
Message-ID: <57289E3E.6010300@huawei.com>

Hi, yury

On 2016/4/13 23:55, Yury Norov wrote:
> Hi Bamvor,
>
> On Wed, Apr 13, 2016 at 05:19:28PM +0800, Zhangjian (Bamvor) wrote:
>> Hi, Yury and Philipp
>>
>> There is a small fix for this patch. Othervise our tools of living
>> patch could not work.
>>
>> Regards
>>
>> Bamvor
>>
>>  From e05770efca9f040e0039a4a9c4e0d7d3b2bd13e8 Mon Sep 17 00:00:00 2001
>> From: Bamvor Jian Zhang <bamvor.zhangjian at huawei.com>
>> Date: Wed, 13 Apr 2016 15:46:28 +0800
>> Subject: [PATCH] arm64: ilp32: do not check vdso-ilp32-offsets.h when ILP32
>>   disabled
>>
>> vdso-ilp32-offsets.h is the dependency of all the arm64-obj-y. And
>> it does not exist when CONFIG_ARM64_ILP32 is disable which lead to
>> all the arm64-obj-y are re-built unnecessarily.
>>
>> Such rebuild may confuse the sofware(e.g. tools of living patch)
>> which need to know exactly which file(s) is(are) updated.
>>
>> This patch fix this issue by adding the config checker.
>
> It looks reasonable and correct.
>
> I'll apply your patch in next submission (if it will be needed),
> otherwise I think, Arnd may apply it.
>
> Though, I don't understand much, what 'tools of living patch' means.
> Could you explain in details what you do, and what goes wrong?
Our tools need to monitor the what *.o is changed after recompile.
But without this patch, all the object in arch/arm64/kernel is
recompiled. Because the vdso-ilp32-offsets.h is dependency of
these files, reference this line of patch:
+$(call objectify,$(arm64-obj-y)): $(obj)/vdso-ilp32/vdso-ilp32-offsets.h

Regards

Bamvor
>
> Nevertheless, thank you for your attention to this patchset.
>
> Yury.
>
>>
>> Signed-off-by: Bamvor Jian Zhang <bamvor.zhangjian at huawei.com>
>> ---
>>   arch/arm64/kernel/Makefile | 2 ++
>>   1 file changed, 2 insertions(+)
>>
>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>> index b43ff12..0f27a10 100644
>> --- a/arch/arm64/kernel/Makefile
>> +++ b/arch/arm64/kernel/Makefile
>> @@ -60,5 +60,7 @@ $(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h
>>   $(obj)/vdso/vdso-offsets.h: $(obj)/vdso
>>
>>   # vDSO - this must be built first to generate the symbol offsets
>> +ifeq ($(CONFIG_ARM64_ILP32),y)
>>   $(call objectify,$(arm64-obj-y)): $(obj)/vdso-ilp32/vdso-ilp32-offsets.h
>>   $(obj)/vdso-ilp32/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32
>> +endif
>> --
>> 1.8.4.5
>>
>> On 2016/4/6 6:08, Yury Norov wrote:
>>> From: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
>>>
>>> ILP32 VDSO exports next symbols:
>>>   __kernel_rt_sigreturn;
>>>   __kernel_gettimeofday;
>>>   __kernel_clock_gettime;
>>>   __kernel_clock_getres;
>>>
>>> What shared object to use, kernel selects depending on result of
>>> is_ilp32_compat_task() in arch/arm64/kernel/vdso.c, so it substitutes
>>> correct pages and spec.
>>>
>>> Adjusted to move the move data page before code pages in sync with
>>> commit 601255ae3c98fdeeee3a8bb4696425e4f868b4f1
>>>
>>> Signed-off-by: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
>>> Signed-off-by: Christoph Muellner <christoph.muellner at theobroma-systems.com>
>>> Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
>>> ---
>>>   arch/arm64/include/asm/vdso.h                 |  6 ++
>>>   arch/arm64/kernel/Makefile                    |  5 ++
>>>   arch/arm64/kernel/signal.c                    |  2 +
>>>   arch/arm64/kernel/vdso-ilp32/.gitignore       |  2 +
>>>   arch/arm64/kernel/vdso-ilp32/Makefile         | 72 ++++++++++++++++++++
>>>   arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S     | 33 ++++++++++
>>>   arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 95 +++++++++++++++++++++++++++
>>>   arch/arm64/kernel/vdso.c                      | 61 ++++++++++++++---
>>>   8 files changed, 266 insertions(+), 10 deletions(-)
>>>   create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore
>>>   create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile
>>>   create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
>>>   create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
>>>
>>> diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
>>> index 839ce00..649a9a4 100644
>>> --- a/arch/arm64/include/asm/vdso.h
>>> +++ b/arch/arm64/include/asm/vdso.h
>>> @@ -29,6 +29,12 @@
>>>
>>>   #include <generated/vdso-offsets.h>
>>>
>>> +#ifdef CONFIG_ARM64_ILP32
>>> +#include <generated/vdso-ilp32-offsets.h>
>>> +#else
>>> +#define vdso_offset_sigtramp_ilp32
>>> +#endif
>>> +
>>>   #define VDSO_SYMBOL(base, name)						   \
>>>   ({									   \
>>>   	(void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \
>>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>>> index 09e4373..b43ff12 100644
>>> --- a/arch/arm64/kernel/Makefile
>>> +++ b/arch/arm64/kernel/Makefile
>>> @@ -50,6 +50,7 @@ arm64-obj-$(CONFIG_PARAVIRT)		+= paravirt.o
>>>   arm64-obj-$(CONFIG_RANDOMIZE_BASE)	+= kaslr.o
>>>
>>>   obj-y					+= $(arm64-obj-y) vdso/
>>> +obj-$(CONFIG_ARM64_ILP32)		+= vdso-ilp32/
>>>   obj-m					+= $(arm64-obj-m)
>>>   head-y					:= head.o
>>>   extra-y					+= $(head-y) vmlinux.lds
>>> @@ -57,3 +58,7 @@ extra-y					+= $(head-y) vmlinux.lds
>>>   # vDSO - this must be built first to generate the symbol offsets
>>>   $(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h
>>>   $(obj)/vdso/vdso-offsets.h: $(obj)/vdso
>>> +
>>> +# vDSO - this must be built first to generate the symbol offsets
>>> +$(call objectify,$(arm64-obj-y)): $(obj)/vdso-ilp32/vdso-ilp32-offsets.h
>>> +$(obj)/vdso-ilp32/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32
>>> diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
>>> index 45bcd96..933cdcf 100644
>>> --- a/arch/arm64/kernel/signal.c
>>> +++ b/arch/arm64/kernel/signal.c
>>> @@ -264,6 +264,8 @@ void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
>>>
>>>   	if (ka->sa.sa_flags & SA_RESTORER)
>>>   		sigtramp = ka->sa.sa_restorer;
>>> +	else if (is_ilp32_compat_task())
>>> +		sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp_ilp32);
>>>   	else
>>>   		sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
>>>
>>> diff --git a/arch/arm64/kernel/vdso-ilp32/.gitignore b/arch/arm64/kernel/vdso-ilp32/.gitignore
>>> new file mode 100644
>>> index 0000000..61806c3
>>> --- /dev/null
>>> +++ b/arch/arm64/kernel/vdso-ilp32/.gitignore
>>> @@ -0,0 +1,2 @@
>>> +vdso-ilp32.lds
>>> +vdso-ilp32-offsets.h
>>> diff --git a/arch/arm64/kernel/vdso-ilp32/Makefile b/arch/arm64/kernel/vdso-ilp32/Makefile
>>> new file mode 100644
>>> index 0000000..c8f5472
>>> --- /dev/null
>>> +++ b/arch/arm64/kernel/vdso-ilp32/Makefile
>>> @@ -0,0 +1,72 @@
>>> +#
>>> +# Building a vDSO image for AArch64.
>>> +#
>>> +# Author: Will Deacon <will.deacon at arm.com>
>>> +# Heavily based on the vDSO Makefiles for other archs.
>>> +#
>>> +
>>> +obj-ilp32-vdso := gettimeofday-ilp32.o note-ilp32.o sigreturn-ilp32.o
>>> +
>>> +# Build rules
>>> +targets := $(obj-ilp32-vdso) vdso-ilp32.so vdso-ilp32.so.dbg
>>> +obj-ilp32-vdso := $(addprefix $(obj)/, $(obj-ilp32-vdso))
>>> +
>>> +ccflags-y := -shared -fno-common -fno-builtin
>>> +ccflags-y += -nostdlib -Wl,-soname=linux-ilp32-vdso.so.1 \
>>> +		$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
>>> +
>>> +obj-y += vdso-ilp32.o
>>> +extra-y += vdso-ilp32.lds vdso-ilp32-offsets.h
>>> +CPPFLAGS_vdso-ilp32.lds += -P -C -U$(ARCH) -mabi=ilp32
>>> +
>>> +# Force dependency (incbin is bad)
>>> +$(obj)/vdso-ilp32.o : $(obj)/vdso-ilp32.so
>>> +
>>> +# Link rule for the .so file, .lds has to be first
>>> +$(obj)/vdso-ilp32.so.dbg: $(src)/vdso-ilp32.lds $(obj-ilp32-vdso)
>>> +	$(call if_changed,vdso-ilp32ld)
>>> +
>>> +# Strip rule for the .so file
>>> +$(obj)/%.so: OBJCOPYFLAGS := -S
>>> +$(obj)/%.so: $(obj)/%.so.dbg FORCE
>>> +	$(call if_changed,objcopy)
>>> +
>>> +# Generate VDSO offsets using helper script
>>> +gen-vdsosym := $(srctree)/$(src)/../vdso/gen_vdso_offsets.sh
>>> +quiet_cmd_vdsosym = VDSOSYM $@
>>> +define cmd_vdsosym
>>> +	$(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ && \
>>> +	cp $@ include/generated/
>>> +endef
>>> +
>>> +$(obj)/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32.so.dbg FORCE
>>> +	$(call if_changed,vdsosym)
>>> +
>>> +# Assembly rules for the .S files
>>> +#$(obj-ilp32-vdso): %.o: $(src)/../vdso/$(subst -ilp32,,%.S)
>>> +#	$(call if_changed_dep,vdso-ilp32as)
>>> +
>>> +$(obj)/gettimeofday-ilp32.o: $(src)/../vdso/gettimeofday.S
>>> +	$(call if_changed_dep,vdso-ilp32as)
>>> +
>>> +$(obj)/note-ilp32.o: $(src)/../vdso/note.S
>>> +	$(call if_changed_dep,vdso-ilp32as)
>>> +
>>> +$(obj)/sigreturn-ilp32.o: $(src)/../vdso/sigreturn.S
>>> +	$(call if_changed_dep,vdso-ilp32as)
>>> +
>>> +# Actual build commands
>>> +quiet_cmd_vdso-ilp32ld = VDSOILP32L $@
>>> +      cmd_vdso-ilp32ld = $(CC) $(c_flags) -mabi=ilp32  -Wl,-n -Wl,-T $^ -o $@
>>> +quiet_cmd_vdso-ilp32as = VDSOILP32A $@
>>> +      cmd_vdso-ilp32as = $(CC) $(a_flags) -mabi=ilp32 -c -o $@ $<
>>> +
>>> +# Install commands for the unstripped file
>>> +quiet_cmd_vdso_install = INSTALL $@
>>> +      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
>>> +
>>> +vdso-ilp32.so: $(obj)/vdso-ilp32.so.dbg
>>> +	@mkdir -p $(MODLIB)/vdso
>>> +	$(call cmd,vdso_install)
>>> +
>>> +vdso_install: vdso-ilp32.so
>>> diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
>>> new file mode 100644
>>> index 0000000..46ac072
>>> --- /dev/null
>>> +++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
>>> @@ -0,0 +1,33 @@
>>> +/*
>>> + * Copyright (C) 2012 ARM Limited
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>> + *
>>> + * Author: Will Deacon <will.deacon at arm.com>
>>> + */
>>> +
>>> +#include <linux/init.h>
>>> +#include <linux/linkage.h>
>>> +#include <linux/const.h>
>>> +#include <asm/page.h>
>>> +
>>> +	__PAGE_ALIGNED_DATA
>>> +
>>> +	.globl vdso_ilp32_start, vdso_ilp32_end
>>> +	.balign PAGE_SIZE
>>> +vdso_ilp32_start:
>>> +	.incbin "arch/arm64/kernel/vdso-ilp32/vdso-ilp32.so"
>>> +	.balign PAGE_SIZE
>>> +vdso_ilp32_end:
>>> +
>>> +	.previous
>>> diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
>>> new file mode 100644
>>> index 0000000..ddc63fd
>>> --- /dev/null
>>> +++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
>>> @@ -0,0 +1,95 @@
>>> +/*
>>> + * GNU linker script for the VDSO library.
>>> + *
>>> + * Copyright (C) 2012 ARM Limited
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>> + *
>>> + * Author: Will Deacon <will.deacon at arm.com>
>>> + * Heavily based on the vDSO linker scripts for other archs.
>>> + */
>>> +
>>> +#include <linux/const.h>
>>> +#include <asm/page.h>
>>> +#include <asm/vdso.h>
>>> +
>>> +SECTIONS
>>> +{
>>> +	PROVIDE(_vdso_data = . - PAGE_SIZE);
>>> +	. = VDSO_LBASE + SIZEOF_HEADERS;
>>> +
>>> +	.hash		: { *(.hash) }			:text
>>> +	.gnu.hash	: { *(.gnu.hash) }
>>> +	.dynsym		: { *(.dynsym) }
>>> +	.dynstr		: { *(.dynstr) }
>>> +	.gnu.version	: { *(.gnu.version) }
>>> +	.gnu.version_d	: { *(.gnu.version_d) }
>>> +	.gnu.version_r	: { *(.gnu.version_r) }
>>> +
>>> +	.note		: { *(.note.*) }		:text	:note
>>> +
>>> +	. = ALIGN(16);
>>> +
>>> +	.text		: { *(.text*) }			:text	=0xd503201f
>>> +	PROVIDE (__etext = .);
>>> +	PROVIDE (_etext = .);
>>> +	PROVIDE (etext = .);
>>> +
>>> +	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
>>> +	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
>>> +
>>> +	.dynamic	: { *(.dynamic) }		:text	:dynamic
>>> +
>>> +	.rodata		: { *(.rodata*) }		:text
>>> +
>>> +	_end = .;
>>> +	PROVIDE(end = .);
>>> +
>>> +	/DISCARD/	: {
>>> +		*(.note.GNU-stack)
>>> +		*(.data .data.* .gnu.linkonce.d.* .sdata*)
>>> +		*(.bss .sbss .dynbss .dynsbss)
>>> +	}
>>> +}
>>> +
>>> +/*
>>> + * We must supply the ELF program headers explicitly to get just one
>>> + * PT_LOAD segment, and set the flags explicitly to make segments read-only.
>>> + */
>>> +PHDRS
>>> +{
>>> +	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
>>> +	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
>>> +	note		PT_NOTE		FLAGS(4);		/* PF_R */
>>> +	eh_frame_hdr	PT_GNU_EH_FRAME;
>>> +}
>>> +
>>> +/*
>>> + * This controls what symbols we export from the DSO.
>>> + */
>>> +VERSION
>>> +{
>>> +	LINUX_2.6 {
>>> +	global:
>>> +		__kernel_rt_sigreturn;
>>> +		__kernel_gettimeofday;
>>> +		__kernel_clock_gettime;
>>> +		__kernel_clock_getres;
>>> +	local: *;
>>> +	};
>>> +}
>>> +
>>> +/*
>>> + * Make the sigreturn code visible to the kernel.
>>> + */
>>> +VDSO_sigtramp_ilp32		= __kernel_rt_sigreturn;
>>> diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
>>> index 26352a6..521a8e4 100644
>>> --- a/arch/arm64/kernel/vdso.c
>>> +++ b/arch/arm64/kernel/vdso.c
>>> @@ -40,6 +40,12 @@ extern char vdso_start, vdso_end;
>>>   static unsigned long vdso_pages;
>>>   static struct page **vdso_pagelist;
>>>
>>> +#ifdef CONFIG_ARM64_ILP32
>>> +extern char vdso_ilp32_start, vdso_ilp32_end;
>>> +static unsigned long vdso_ilp32_pages;
>>> +static struct page **vdso_ilp32_pagelist;
>>> +#endif
>>> +
>>>   /*
>>>    * The vDSO data page.
>>>    */
>>> @@ -109,24 +115,29 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
>>>   }
>>>   #endif /* CONFIG_AARCH32_EL0 */
>>>
>>> -static struct vm_special_mapping vdso_spec[2];
>>> -
>>> -static int __init vdso_init(void)
>>> +static int __init vdso_init_common(char *vdso_start, char *vdso_end,
>>> +					  unsigned long *vdso_pagesp,
>>> +					  struct page ***vdso_pagelistp,
>>> +					  struct vm_special_mapping* vdso_spec)
>>>   {
>>>   	int i;
>>> +	unsigned long vdso_pages;
>>> +	struct page **vdso_pagelist;
>>>
>>> -	if (memcmp(&vdso_start, "\177ELF", 4)) {
>>> +	if (memcmp(vdso_start, "\177ELF", 4)) {
>>>   		pr_err("vDSO is not a valid ELF object!\n");
>>>   		return -EINVAL;
>>>   	}
>>>
>>> -	vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
>>> +	vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
>>> +	*vdso_pagesp = vdso_pages;
>>>   	pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
>>> -		vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data);
>>> +		vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data);
>>>
>>>   	/* Allocate the vDSO pagelist, plus a page for the data. */
>>>   	vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
>>>   				GFP_KERNEL);
>>> +	*vdso_pagelistp = vdso_pagelist;
>>>   	if (vdso_pagelist == NULL)
>>>   		return -ENOMEM;
>>>
>>> @@ -135,7 +146,7 @@ static int __init vdso_init(void)
>>>
>>>   	/* Grab the vDSO code pages. */
>>>   	for (i = 0; i < vdso_pages; i++)
>>> -		vdso_pagelist[i + 1] = virt_to_page(&vdso_start + i * PAGE_SIZE);
>>> +		vdso_pagelist[i + 1] = virt_to_page(vdso_start + i * PAGE_SIZE);
>>>
>>>   	/* Populate the special mapping structures */
>>>   	vdso_spec[0] = (struct vm_special_mapping) {
>>> @@ -150,16 +161,46 @@ static int __init vdso_init(void)
>>>
>>>   	return 0;
>>>   }
>>> +
>>> +static struct vm_special_mapping vdso_spec[2];
>>> +
>>> +static int __init vdso_init(void)
>>> +{
>>> +	return vdso_init_common(&vdso_start, &vdso_end,
>>> +				&vdso_pages, &vdso_pagelist,
>>> +				vdso_spec);
>>> +}
>>>   arch_initcall(vdso_init);
>>>
>>> +#ifdef CONFIG_ARM64_ILP32
>>> +static struct vm_special_mapping vdso_ilp32_spec[2];
>>> +
>>> +static int __init vdso_ilp32_init(void)
>>> +{
>>> +	return vdso_init_common(&vdso_ilp32_start, &vdso_ilp32_end,
>>> +				&vdso_ilp32_pages, &vdso_ilp32_pagelist,
>>> +				vdso_ilp32_spec);
>>> +}
>>> +arch_initcall(vdso_ilp32_init);
>>> +#endif
>>> +
>>>   int arch_setup_additional_pages(struct linux_binprm *bprm,
>>>   				int uses_interp)
>>>   {
>>>   	struct mm_struct *mm = current->mm;
>>>   	unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
>>>   	void *ret;
>>> +	unsigned long pages = vdso_pages;
>>> +	struct vm_special_mapping *spec = vdso_spec;
>>> +
>>> +#ifdef CONFIG_ARM64_ILP32
>>> +	if (is_ilp32_compat_task()) {
>>> +	        pages = vdso_ilp32_pages;
>>> +	        spec = vdso_ilp32_spec;
>>> +	}
>>> +#endif
>>>
>>> -	vdso_text_len = vdso_pages << PAGE_SHIFT;
>>> +	vdso_text_len = pages << PAGE_SHIFT;
>>>   	/* Be sure to map the data page */
>>>   	vdso_mapping_len = vdso_text_len + PAGE_SIZE;
>>>
>>> @@ -171,7 +212,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
>>>   	}
>>>   	ret = _install_special_mapping(mm, vdso_base, PAGE_SIZE,
>>>   				       VM_READ|VM_MAYREAD,
>>> -				       &vdso_spec[0]);
>>> +				       &spec[0]);
>>>   	if (IS_ERR(ret))
>>>   		goto up_fail;
>>>
>>> @@ -180,7 +221,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
>>>   	ret = _install_special_mapping(mm, vdso_base, vdso_text_len,
>>>   				       VM_READ|VM_EXEC|
>>>   				       VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
>>> -				       &vdso_spec[1]);
>>> +				       &spec[1]);
>>>   	if (IS_ERR(ret))
>>>   		goto up_fail;
>>>
>>>



From van.freenix at gmail.com  Tue May  3 05:50:43 2016
From: van.freenix at gmail.com (Peng Fan)
Date: Tue, 3 May 2016 20:50:43 +0800
Subject: [PATCH] iommu/arm-smmu: clear cache lock bit of ACR
In-Reply-To: <57288868.9020908@arm.com>
References: <1462270527-17074-1-git-send-email-van.freenix@gmail.com>
 <57288868.9020908@arm.com>
Message-ID: <20160503125041.GA18127@linux-7smt.suse>

Hi Robin,

On Tue, May 03, 2016 at 12:15:52PM +0100, Robin Murphy wrote:
>On 03/05/16 11:15, Peng Fan wrote:
>>According MMU-500 TRM, section 3.7.1 Auxiliary Control registers,
>>You can modify ACTLR only when the ACR.CACHE_LOCK bit is 0.
>>
>>So before clearing ARM_MMU500_ACTLR_CPRE of each context bank,
>>need clear CACHE_LOCK bit of ACR register first.
>
>Ah, good catch - I think I misread CACHE_LOCK as resetting to 0, and
>proceeded to forget about it. However, it's only present in MMU-500r2
>onwards, so we'd also want to check IDR7 before touching ACR.

Thanks for comments. I'll add code to check IDR7 and send out V2.

Thanks,
Peng.

>
>Thanks,
>Robin.
>
>>Signed-off-by: Peng Fan <van.freenix at gmail.com>
>>Cc: Will Deacon <will.deacon at arm.com>
>>Cc: Robin Murphy <robin.murphy at arm.com>
>>---
>>
>>Hi Will,
>>
>>  Patch based on iommu/devel branch.
>>
>>
>>  drivers/iommu/arm-smmu.c | 15 +++++++++++++++
>>  1 file changed, 15 insertions(+)
>>
>>diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
>>index acff332..d094a5a 100644
>>--- a/drivers/iommu/arm-smmu.c
>>+++ b/drivers/iommu/arm-smmu.c
>>@@ -98,6 +98,9 @@
>>  #define sCR0_BSU_SHIFT			14
>>  #define sCR0_BSU_MASK			0x3
>>
>>+/* Auxiliary Configuration register */
>>+#define ARM_SMMU_GR0_sACR		0x10
>>+
>>  /* Identification registers */
>>  #define ARM_SMMU_GR0_ID0		0x20
>>  #define ARM_SMMU_GR0_ID1		0x24
>>@@ -235,6 +238,8 @@
>>
>>  #define ARM_MMU500_ACTLR_CPRE		(1 << 1)
>>
>>+#define ARM_MMU500_ACR_CACHE_LOCK	(1 << 26)
>>+
>>  #define CB_PAR_F			(1 << 0)
>>
>>  #define ATSR_ACTIVE			(1 << 0)
>>@@ -1506,6 +1511,16 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
>>  		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(i));
>>  	}
>>
>>+	/*
>>+	 * Before clearing ARM_MMU500_ACTLR_CPRE, need to
>>+	 * clear CACHE_LOCK bit of ACR first.
>>+	 */
>>+	if (smmu->model == ARM_MMU500) {
>>+		reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sACR);
>>+		reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
>>+		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sACR);
>>+	}
>>+
>>  	/* Make sure all context banks are disabled and clear CB_FSR  */
>>  	for (i = 0; i < smmu->num_context_banks; ++i) {
>>  		cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, i);
>>
>


From shawnguo at kernel.org  Tue May  3 05:52:22 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 20:52:22 +0800
Subject: [PATCH] ARM: dts: imx6ul-14x14-evk: Add audio support
In-Reply-To: <1462233386-23185-1-git-send-email-festevam@gmail.com>
References: <1462233386-23185-1-git-send-email-festevam@gmail.com>
Message-ID: <20160503125222.GK5874@tiger>

On Mon, May 02, 2016 at 08:56:26PM -0300, Fabio Estevam wrote:
> @@ -86,6 +139,17 @@
>  	};
>  };
>  
> +&sai2 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_sai2>;
> +

Forgot to mention that I dropped this newline when applying.

Shawn

> +	assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
> +			  <&clks IMX6UL_CLK_SAI2>;
> +	assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
> +	assigned-clock-rates = <0>, <12288000>;
> +	status = "okay";
> +};
> +
>  &snvs_poweroff {
>  	status = "okay";
>  };
> @@ -272,6 +336,17 @@
>  		>;
>  	};
>  
> +	pinctrl_sai2: sai2grp {
> +		fsl,pins = <
> +			MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK	0x17088
> +			MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC	0x17088
> +			MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA	0x11088
> +			MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA	0x11088
> +			MX6UL_PAD_JTAG_TMS__SAI2_MCLK		0x17088
> +			MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04	0x17059
> +		>;
> +	};
> +
>  	pinctrl_pwm1: pwm1grp {
>  		fsl,pins = <
>  			MX6UL_PAD_GPIO1_IO08__PWM1_OUT   0x110b0
> -- 
> 1.9.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From bhe at redhat.com  Tue May  3 05:56:49 2016
From: bhe at redhat.com (Baoquan He)
Date: Tue, 3 May 2016 20:56:49 +0800
Subject: [PATCH 10/12] kexec: arrange for paddr_vmcoreinfo_note() to
 return phys_addr_t
In-Reply-To: <20160503101258.GL19428@n2100.arm.linux.org.uk>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <E1aviFP-0000je-5t@rmk-PC.arm.linux.org.uk>
 <CAHB_Gur-6oyEheN-Pom7OwivdvrQpCBaXvM1V2H0JPFRCFZthA@mail.gmail.com>
 <20160429151639.GC23726@leverpostej>
 <CAHB_GurwYqPbccLU9UHppLxbBr4Cfs47myKAer-RJicT=T7uBw@mail.gmail.com>
 <20160503042441.GA2518@x1.redhat.com>
 <20160503101258.GL19428@n2100.arm.linux.org.uk>
Message-ID: <20160503125649.GA2656@x1.redhat.com>

On 05/03/16 at 11:12am, Russell King - ARM Linux wrote:
> On Tue, May 03, 2016 at 12:24:41PM +0800, Baoquan He wrote:
> > Could you please help tell why arm PAE kernel can be put above 4G?
> > Since the change is related to common code, I am curious about how
> > it's so different with other ARCHs.
> 
> This is explained in the covering email to the series.
> 
> The explanation given by Pratyush was incomplete.

Yeah, he said non LPAE also has PHYS_OFFSET later to me. In fact this
patch is totally unharmful to other ARCHes, I just can't stand the
curiosity. Sorry about this.

> 
> -- 
> RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.


From shawnguo at kernel.org  Tue May  3 05:58:38 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 20:58:38 +0800
Subject: [PATCH 1/2] ARM: imx_v6_v7_defconfig: add CONFIG_I2C_GPIO
In-Reply-To: <1461962419-4715-1-git-send-email-marcel.ziswiler@toradex.com>
References: <1461962419-4715-1-git-send-email-marcel.ziswiler@toradex.com>
Message-ID: <20160503125838.GL5874@tiger>

On Fri, Apr 29, 2016 at 10:40:18PM +0200, Marcel Ziswiler wrote:
> The GPIO-based bitbanging I2C driver is required to make HDMI work on
> the Apalis iMX6 module plugged into a Ixora carrier board featuring a
> DDC channel to read a screen's EDID being hooked up to regular GPIOs.
> 
> Signed-off-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>

Applied both, thanks.


From festevam at gmail.com  Tue May  3 05:59:34 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Tue, 3 May 2016 09:59:34 -0300
Subject: [PATCH] ARM: dts: imx6ul-14x14-evk: Add audio support
In-Reply-To: <20160503125222.GK5874@tiger>
References: <1462233386-23185-1-git-send-email-festevam@gmail.com>
 <20160503125222.GK5874@tiger>
Message-ID: <CAOMZO5Dkci6EmHkg4WSHHaESGW0z0YbNVMoEO5Tcc2N1mY16Pw@mail.gmail.com>

On Tue, May 3, 2016 at 9:52 AM, Shawn Guo <shawnguo at kernel.org> wrote:
> On Mon, May 02, 2016 at 08:56:26PM -0300, Fabio Estevam wrote:
>> @@ -86,6 +139,17 @@
>>       };
>>  };
>>
>> +&sai2 {
>> +     pinctrl-names = "default";
>> +     pinctrl-0 = <&pinctrl_sai2>;
>> +
>
> Forgot to mention that I dropped this newline when applying.

Thanks, Shawn!


From shawnguo at kernel.org  Tue May  3 06:11:58 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 21:11:58 +0800
Subject: [PATCH] ARM: mx5: dts: Enable USB OTG on M53EVK
In-Reply-To: <57288107.4000908@denx.de>
References: <1461105361-6742-1-git-send-email-marex@denx.de>
 <57288107.4000908@denx.de>
Message-ID: <20160503131157.GM5874@tiger>

On Tue, May 03, 2016 at 12:44:23PM +0200, Marek Vasut wrote:
> On 04/20/2016 12:36 AM, Marek Vasut wrote:
> > Add USB OTG support to M53EVK instead of just USB gadget.
> > 
> > Signed-off-by: Marek Vasut <marex at denx.de>
> > Cc: Shawn Guo <shawn.guo at linaro.org>
> 
> Bump ?

Applied, thanks.

> 
> btw. Shawn, is the @k.org the address I should use now ?

Yes.

Shawn


From marex at denx.de  Tue May  3 06:14:22 2016
From: marex at denx.de (Marek Vasut)
Date: Tue, 03 May 2016 15:14:22 +0200
Subject: [PATCH] ARM: mx5: dts: Enable USB OTG on M53EVK
In-Reply-To: <20160503131157.GM5874@tiger>
References: <1461105361-6742-1-git-send-email-marex@denx.de>
 <57288107.4000908@denx.de> <20160503131157.GM5874@tiger>
Message-ID: <5728A42E.9060100@denx.de>

On 05/03/2016 03:11 PM, Shawn Guo wrote:
> On Tue, May 03, 2016 at 12:44:23PM +0200, Marek Vasut wrote:
>> On 04/20/2016 12:36 AM, Marek Vasut wrote:
>>> Add USB OTG support to M53EVK instead of just USB gadget.
>>>
>>> Signed-off-by: Marek Vasut <marex at denx.de>
>>> Cc: Shawn Guo <shawn.guo at linaro.org>
>>
>> Bump ?
> 
> Applied, thanks.
> 
>>
>> btw. Shawn, is the @k.org the address I should use now ?
> 
> Yes.
> 
> Shawn
> 
OK, will be careful next time. Thanks!

-- 
Best regards,
Marek Vasut


From maxime.ripard at free-electrons.com  Tue May  3 06:14:37 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Tue, 3 May 2016 15:14:37 +0200
Subject: [PATCH 1/1] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <f3da30a6-9ac0-4d5e-8611-ebb80cb3589e@googlegroups.com>
References: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
 <f3da30a6-9ac0-4d5e-8611-ebb80cb3589e@googlegroups.com>
Message-ID: <20160503131437.GV17159@lukather>

Hi,

On Tue, May 03, 2016 at 12:12:06AM -0700, christo.radev at gmail.com wrote:
> Hi to All,
> 
> I have already solved and tested this issue on Armbian build.  Find
> patches for both legacy (3.4.111) and mainline (4.5.2) kernels on:
> http://forum.armbian.com/index.php/topic/853-armbian-customization/page-2#entry7494
> There it is also described how to do eMMC bootable and much more.
> 
> About the board - Olimex already sold all 3 kinds after migration to
> their HW rev. E. One have to specify Lime2-eMMC as
> A20-Olinuxino-Lime2-eMMC instead of their old 2 options
> A20-Olinuxino-Lime2(-4GB).

Interesting, you have a link to that device?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160503/22f02f0f/attachment.sig>

From panand at redhat.com  Tue May  3 06:24:39 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 3 May 2016 18:54:39 +0530
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <57289594.3050801@codeaurora.org>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <57289594.3050801@codeaurora.org>
Message-ID: <20160503132439.GC13045@dhcppc6.redhat.com>

On 03/05/2016:07:12:04 AM, Timur Tabi wrote:
> Pratyush Anand wrote:
> >+ * Note: This watchdog timer has two stages. If action is 0, first stage is
> >+ * determined by directly programming WCV and second by WOR. When first
> >+ * timeout is reached, WS0 is triggered and WCV is reloaded with value in
> >+ * WOR. WS0 interrupt will be ignored, then the second watch period starts;
> >+ * when second timeout is reached, then WS1 is triggered, system resets. WCV
> >+ * and WOR are programmed in such a way that total time corresponding to
> >+ * WCV+WOR becomes equivalent to user programmed "timeout".
> >+ * If action is 1, then we expect to call panic() at user programmed
> >+ * "timeout". Therefore, we program both first and second stage using WCV
> >+ * only.
> 
> So I'm not sure I understand how this works yet, but there was an earlier
> version of Fu's driver that did something similar.  It depended on being
> able to reprogram the hardware during the WS0 interrupt, and that was
> rejected by the community.
> 
> How is what you are doing different?

* Following was the comment for Fu Wei's primitive version of patch [1], because
* of which community rejected it.

> The triggering of the hardware reset should never depend on an interrupt being
> handled properly.  You should always program WCV correctly in advance.

Now, there are couple of things different:

(1) There is an important difference in upstreamed version than the version [1]
which was rejected on above ground. In upstreamed version,  there would be no
interrupt handler when we are in normal mode ie action=0.  So, there is no
possibility of doing any thing in ISR for all normal usage of this timer. In
this mode WCV is always programmed well in advance now.

(2)action=1 mechanism was introduced to implement a dump saving mechanism if
watchdog timeout expires before next kick. So, the current upstream version
calls panic() in ISR. When action=1, then we do write WCV now in ISR, but there
too some precaution have been taken. 

When action=1, and we land into isr handler sbsa_gwdt_interrupt() we can not
trust watchdog data structure any more. That might have been corrupted.
(i) So it might happen that gwdt or wdd pointers have a corrupted value and as
soon as we access gwdt->wdd or wdd->timeout, kernel panics. *No harm*, just
panic() is called a bit early, which dump saving mechanism would be able to
find. So, in fact it will give an extra information to dump saving mechanism
that watchdog structure was corrupted as well.
(ii) Another case, It might happen that wdd->timeout has been corrupted with
large values. This patch does a protection while programming WCV in ISR. It
checks wdd->timeout against MAX_TIMEOUT value and reprograms WCV only when
wdd->timeout is lesser than MAX_TIMEOUT. So, here too, there would be watchdog
reset for sure if dump saving mechanism hangs.

~Pratyush

[1] https://lists.linaro.org/pipermail/linaro-acpi/2015-June/004956.html


From linux at roeck-us.net  Tue May  3 06:29:39 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 3 May 2016 06:29:39 -0700
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
Message-ID: <5728A7C3.4010001@roeck-us.net>

On 05/03/2016 01:20 AM, Pratyush Anand wrote:
> Currently only WOR is used to program both first and second stage which
> provided very limited range of timeout.
>
> This patch uses WCV as well to achieve higher range of timeout. This patch
> programs max_timeout as 255, but that can be increased further as well.
>
> Following testing shows that we can happily achieve 40 second default timeout.
>
>   # modprobe sbsa_gwdt action=1
>   [  131.187562] sbsa-gwdt sbsa-gwdt.0: Initialized with 40s timeout @ 250000000 Hz, action=1.
>   # cd /sys/class/watchdog/watchdog0/
>   # cat state
>   inactive
>   # cat /dev/watchdog0
>   cat: /dev/watchdog0: Invalid argument
>   [  161.710593] watchdog: watchdog0: watchdog did not stop!
>   # cat state
>   active
>   # cat timeout
>   40
>   # cat timeleft
>   38
>   # cat timeleft
>   25
>   # cat /dev/watchdog0
>   cat: /dev/watchdog0: Invalid argument
>   [  184.931030] watchdog: watchdog0: watchdog did not stop!
>   # cat timeleft
>   37
>   # cat timeleft
>   21
>   ...
>   ...
>   # cat timeleft
>   1
>
> panic() is called upon timeout of 40s. See timestamp of last kick (cat) and
> next panic() message.
>
>   [  224.939065] Kernel panic - not syncing: SBSA Watchdog timeout
>
> Signed-off-by: Pratyush Anand <panand at redhat.com>

You could also use the new infrastructure (specify max_hw_heartbeat_ms instead
of max_timeout), and not depend on the correct implementation of WCV.

Overall this adds a lot of complexity for something that could by now easily
be handled by the infrastructure. Is this really necessary ?

Guenter

> ---
>   drivers/watchdog/sbsa_gwdt.c | 83 +++++++++++++++++++++++++++++++++-----------
>   1 file changed, 62 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
> index ad383f6f15fc..529dd5e99fcd 100644
> --- a/drivers/watchdog/sbsa_gwdt.c
> +++ b/drivers/watchdog/sbsa_gwdt.c
> @@ -35,17 +35,23 @@
>    *
>    * SBSA GWDT:
>    * if action is 1 (the two stages mode):
> - * |--------WOR-------WS0--------WOR-------WS1
> + * |--------WCV-------WS0--------WCV-------WS1
>    * |----timeout-----(panic)----timeout-----reset
>    *
>    * if action is 0 (the single stage mode):
> - * |------WOR-----WS0(ignored)-----WOR------WS1
> + * |------WCV-----WS0(ignored)-----WOR------WS1
>    * |--------------timeout-------------------reset
>    *
> - * Note: Since this watchdog timer has two stages, and each stage is determined
> - * by WOR, in the single stage mode, the timeout is (WOR * 2); in the two
> - * stages mode, the timeout is WOR. The maximum timeout in the two stages mode
> - * is half of that in the single stage mode.
> + * Note: This watchdog timer has two stages. If action is 0, first stage is
> + * determined by directly programming WCV and second by WOR. When first
> + * timeout is reached, WS0 is triggered and WCV is reloaded with value in
> + * WOR. WS0 interrupt will be ignored, then the second watch period starts;
> + * when second timeout is reached, then WS1 is triggered, system resets. WCV
> + * and WOR are programmed in such a way that total time corresponding to
> + * WCV+WOR becomes equivalent to user programmed "timeout".
> + * If action is 1, then we expect to call panic() at user programmed
> + * "timeout". Therefore, we program both first and second stage using WCV
> + * only.
>    *
>    */
>
> @@ -95,7 +101,17 @@ struct sbsa_gwdt {
>   	void __iomem		*control_base;
>   };
>
> -#define DEFAULT_TIMEOUT		10 /* seconds */
> +/*
> + * Max Timeout Can be in days, but 255 seconds seems reasonable for all use
> + * cases
> + */
> +#define MAX_TIMEOUT		255

We don't usually define such arbitrary limits.

> +
> +/* Default timeout is 40 seconds, which is the 1st + 2nd watch periods when
> + * action is 0. When action is 1 then both 1st and 2nd watch periods will
> + * be of 40 seconds.
> + */
> +#define DEFAULT_TIMEOUT		40 /* seconds */
>
>   static unsigned int timeout;
>   module_param(timeout, uint, 0);
> @@ -127,20 +143,21 @@ static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
>   				 unsigned int timeout)
>   {
>   	struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
> +	u64 timeout_1, timeout_2;
>
>   	wdd->timeout = timeout;
>
>   	if (action)
> -		writel(gwdt->clk * timeout,
> -		       gwdt->control_base + SBSA_GWDT_WOR);
> +		timeout_1 = (u64)gwdt->clk * timeout;
>   	else
> -		/*
> -		 * In the single stage mode, The first signal (WS0) is ignored,
> -		 * the timeout is (WOR * 2), so the WOR should be configured
> -		 * to half value of timeout.
> -		 */
> -		writel(gwdt->clk / 2 * timeout,
> -		       gwdt->control_base + SBSA_GWDT_WOR);
> +		timeout_1 = (u64)gwdt->clk * (timeout - wdd->min_timeout);
> +
> +	/* when action=1, timeout_2 will be overwritten in ISR */
> +	timeout_2 = (u64)gwdt->clk * wdd->min_timeout;
> +
Why min_timeout ? Also, where is it overwritten in the interrupt handler,
and to which value ?

> +	writel(timeout_2, gwdt->control_base + SBSA_GWDT_WOR);
> +	writeq(timeout_1 + arch_counter_get_cntvct(),
> +		gwdt->control_base + SBSA_GWDT_WCV);
>
>   	return 0;
>   }
> @@ -172,12 +189,17 @@ static int sbsa_gwdt_keepalive(struct watchdog_device *wdd)
>   	struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
>
>   	/*
> -	 * Writing WRR for an explicit watchdog refresh.
> -	 * You can write anyting (like 0).
> +	 * play safe: program WOR with max value so that we have sufficient
> +	 * time to overwrite them after explicit refresh
>   	 */
> +	writel(U32_MAX, gwdt->control_base + SBSA_GWDT_WOR);
> +	/*
> +	* Writing WRR for an explicit watchdog refresh.
> +	* You can write anyting (like 0).
> +	*/

Please stick with standard multi-line comments.

>   	writel(0, gwdt->refresh_base + SBSA_GWDT_WRR);
>
> -	return 0;
> +	return sbsa_gwdt_set_timeout(wdd, wdd->timeout);;
>   }
>
>   static unsigned int sbsa_gwdt_status(struct watchdog_device *wdd)
> @@ -193,10 +215,15 @@ static int sbsa_gwdt_start(struct watchdog_device *wdd)
>   {
>   	struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
>
> +	/*
> +	 * play safe: program WOR with max value so that we have sufficient
> +	 * time to overwrite them after explicit refresh
> +	 */
> +	writel(U32_MAX, gwdt->control_base + SBSA_GWDT_WOR);
>   	/* writing WCS will cause an explicit watchdog refresh */
>   	writel(SBSA_GWDT_WCS_EN, gwdt->control_base + SBSA_GWDT_WCS);
>
> -	return 0;
> +	return sbsa_gwdt_set_timeout(wdd, wdd->timeout);;
>   }
>
>   static int sbsa_gwdt_stop(struct watchdog_device *wdd)
> @@ -211,6 +238,20 @@ static int sbsa_gwdt_stop(struct watchdog_device *wdd)
>
>   static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
>   {
> +	struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
> +	struct watchdog_device *wdd = &gwdt->wdd;
> +	u64 timeout_2 = (u64)gwdt->clk * wdd->timeout;
> +
> +	/*
> +	 * Since we can not trust system at this moment, therefore re-write
> +	 * WCV only if wdd->timeout <= MAX_TIMEOUT to avoid a corner
> +	 * scenario when we might have corrupted wdd->timeout values at
> +	 * this point.
> +	 */

This is quite vague. What is this corner scenario where wdd->timeout
would be corrupted ? How can wdd->timeout ever be larger than MAX_TIMEOUT ?

> +	if (wdd->timeout <= MAX_TIMEOUT)
> +		writeq(timeout_2 + arch_counter_get_cntvct(),
> +			gwdt->control_base + SBSA_GWDT_WCV);
> +
>   	panic(WATCHDOG_NAME " timeout");
>
>   	return IRQ_HANDLED;
> @@ -273,7 +314,7 @@ static int sbsa_gwdt_probe(struct platform_device *pdev)
>   	wdd->info = &sbsa_gwdt_info;
>   	wdd->ops = &sbsa_gwdt_ops;
>   	wdd->min_timeout = 1;
> -	wdd->max_timeout = U32_MAX / gwdt->clk;
> +	wdd->max_timeout = MAX_TIMEOUT;
>   	wdd->timeout = DEFAULT_TIMEOUT;
>   	watchdog_set_drvdata(wdd, gwdt);
>   	watchdog_set_nowayout(wdd, nowayout);
>



From Linux.HWI at garmin.com  Tue May  3 06:31:11 2016
From: Linux.HWI at garmin.com (J.D. Schroeder)
Date: Tue, 3 May 2016 08:31:11 -0500
Subject: [PATCH v2 2/3] ARM: DRA7x: dts: Update the OSC_32K_CLK frequency
In-Reply-To: <57285E66.2000708@ti.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
 <1462209123-7332-3-git-send-email-Linux.HWI@garmin.com>
 <57285E66.2000708@ti.com>
Message-ID: <5728A81F.4050906@garmin.com>

On 05/03/2016 03:16 AM, Tero Kristo wrote:
> On 02/05/16 20:12, J.D. Schroeder wrote:
>> From: "J.D. Schroeder" <jay.schroeder at garmin.com>
>>
>> This commit updates the OSC_32K_CLK (secure_32k_clk_src_ck) frequency
>> from the precise 32kHz frequency (i.e., 32.768 kHz) to a more
>> accurate frequency of ~34.6 kHz. Actual measured frequencies of the
>> clock vary from processor to processor anywhere from 34.4 kHz up to
>> 34.8 kHz. Note that the ~34 kHz frequency clock is generated
>> internally by the processor, not an input to the processor. This
>> change makes it more clear that the consumer of the
>> secure_32k_clk_src_ck will not get a precise 32.768 kHz frequency
>> output.
>>
>> Signed-off-by: J.D. Schroeder <jay.schroeder at garmin.com>
>> Reviewed-by: Trenton Andres <trenton.andres at garmin.com>
>> ---
>>   arch/arm/boot/dts/dra7xx-clocks.dtsi | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi
>> b/arch/arm/boot/dts/dra7xx-clocks.dtsi
>> index 3f0c61d..f7ec976 100644
>> --- a/arch/arm/boot/dts/dra7xx-clocks.dtsi
>> +++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi
>> @@ -95,7 +95,7 @@
>>       secure_32k_clk_src_ck: secure_32k_clk_src_ck {
>>           #clock-cells = <0>;
>>           compatible = "fixed-clock";
>> -        clock-frequency = <32768>;
>> +        clock-frequency = <34600>; /* approximate frequency */
>>       };
>>
>>       sys_clk32_crystal_ck: sys_clk32_crystal_ck {
>>
> 
> I still don't agree with this patch. The actual frequency can drift much more,
> you are just seeing this number at your setup.

Yes, it can drift significantly from processor to processor. Do you agree that
this frequency is closer to what can be expected than 32768 Hz?

Like I said, I would have renamed the clock also but I opted to go the less
obtrusive route while still helping others that might think they can
reasonably use this clock in their design as a 32768 Hz clock source. Perhaps
my comment and selection of the approximate frequency is not the best (I'm
open for suggestions). However, I do think this change is an improvement and
clarifying change to what is currently present in the clock description.

-JD



From aford173 at gmail.com  Tue May  3 06:35:13 2016
From: aford173 at gmail.com (Adam Ford)
Date: Tue, 3 May 2016 08:35:13 -0500
Subject: (v4.4/v4.5)-stable-queue build and qemu failures
 (arm:allmodconfig, arm:pxa_defconfig, arm:omap2plus_defconfig)
In-Reply-To: <20160429201914.GA27596@roeck-us.net>
References: <20160429201914.GA27596@roeck-us.net>
Message-ID: <CAHCN7xJ0vS9GHWmg__z5SQtHKfdCDGKD6m0_=zewbY65Jyf9PA@mail.gmail.com>

On Fri, Apr 29, 2016 at 3:19 PM, Guenter Roeck <linux at roeck-us.net> wrote:
> v4.4 (arm:allmodconfig):
>
> drivers/mtd/nand/pxa3xx_nand.c: In function 'alloc_nand_resource':
> drivers/mtd/nand/pxa3xx_nand.c:1753:7: error: 'np' undeclared
>
> v4.5 (arm:allmodconfig, arm:pxa_defconfig):
>
> drivers/dma/pxa_dma.c: In function 'pxad_probe':
> drivers/dma/pxa_dma.c:1421:24: error: 'struct mmp_dma_platdata' has no member named 'nb_requestors'
>
> There is also a qemu runtime failure with omap2plus_defconfig in v4.4.
>
> [    2.412322] omap_i2c 48070000.i2c: bus 0 rev3.3 at 2600 kHz
> [    2.417541] omap_i2c 48060000.i2c: bus 2 rev3.3 at 100 kHz
> [    2.429443]
> [    2.429534] =====================================
> [    2.429718] [ BUG: bad unlock balance detected! ]
> [    2.429962] 4.4.8-00025-gcd58757 #1 Not tainted
> [    2.430145] -------------------------------------
> [    2.430328] kworker/u2:0/6 is trying to release lock (&rdev->mutex) at:
> [    2.430694] [<c03b40e4>] regulator_set_voltage+0x40/0x54
> [    2.430877] but there are no more locks to release!
>

I am also seeing this in 4.4.8 on an DM3730.  I didn't see it in
4.4.3.  I can also help bisect if it helps.
-adam

> See logs at http://kerneltests.org/builders for details.
> Please let me know if I need to bisect.
>
> Thanks,
> Guenter
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From daniel.lezcano at linaro.org  Tue May  3 06:36:03 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 3 May 2016 15:36:03 +0200
Subject: [PATCH v2 04/11] clocksource/moxart: Generalise timer for use on
 other socs
In-Reply-To: <CACPK8XfgDPPYG=ON-Z+gEKSg1fe4PuqRWoMz8P-9oCMvgQKmhw@mail.gmail.com>
References: <1461225849-28074-1-git-send-email-joel@jms.id.au>
 <1461225849-28074-5-git-send-email-joel@jms.id.au>
 <571A5FBA.9010204@linaro.org>
 <CACPK8XfgDPPYG=ON-Z+gEKSg1fe4PuqRWoMz8P-9oCMvgQKmhw@mail.gmail.com>
Message-ID: <20160503133603.GA19298@linaro.org>

On Tue, May 03, 2016 at 03:26:33PM +0930, Joel Stanley wrote:
> Hey Daniel,
> 
> Thanks for the review.
> 
> On Sat, Apr 23, 2016 at 3:00 AM, Daniel Lezcano
> <daniel.lezcano at linaro.org> wrote:
> > On 04/21/2016 10:04 AM, Joel Stanley wrote:
> >>
> >> The moxart timer IP is shared with another soc made by Aspeed.
> >> Generalise the registers that differ so the same driver can be used for
> >> both.
> >>
> >> As we now depend on CLKSRC_MMIO, create a Kconfig symbol for the driver
> >> so we can express this dependency.
> >>
> >> Signed-off-by: Joel Stanley <joel at jms.id.au>
> >> ---
> >
> >
> > In the future, please Cc the maintainers.
> 
> Sure.
> 
> >
> > You probably can remove all the unused macro definition here for both MOXART
> > and ASPEED to have something just a couple of definition.
> 
> I agree with Ben; we're helping out by documenting the hardware in
> lieu of a public datasheet. I'd prefer to keep this here.

Ok, let's keep it.
 
> >>   static void __iomem *base;
> >>   static unsigned int clock_count_per_tick;
> >> +static unsigned int t1_disable_val, t1_enable_val;
> >
> >
> > It will be cleaner to:
> >
> > 1. Factor out:
> >         writel(TIMER1_DISABLE, base + TIMER_CR);
> >         writel(TIMER1_ENABLE, base + TIMER_CR);
> 
> I considered this myself but went with the minimal change. I'm not
> fussed, so I will rework it as you suggest.
> 
> From the register layout I suspect this IP block is a Faraday Tech
> FTTMR010[1], but I don't have any other evidence.

Apparently, it could be the fttmr010 [2].

May be Jonas Jensen can confirm that.

> Would you take a
> patch to change the name or would you prefer leaving it as moxart?

If Jonas can confirm the moxart SoC is using the faraday timer, then it 
would make much more sense to rename it to timer-fttmr010.c and have the 
different instance of this timer to set it up with the platform specific 
bits.

> [1] https://lists.nongnu.org/archive/html/qemu-devel/2013-03/msg04333.html

[2] 
http://git.denx.de/?p=u-boot.git;a=blob;f=include/faraday/fttmr010.h;h=2ab68d10218ed8241e5d2c916437c5918c17173d;hb=HEAD


From shawnguo at kernel.org  Tue May  3 06:36:05 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 21:36:05 +0800
Subject: [GIT PULL] i.MX clock fixes for 4.6, take 2
Message-ID: <20160503133605.GN5874@tiger>

The following changes since commit 7196c52c9377df0175b510ff5896bda524f7345e:

  clk: imx6q: fix typo in CAN clock definition (2016-04-13 15:27:15 +0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-clk-fixes-4.6-2

for you to fetch changes up to 3397c2c45b1b6f54834dfeae30a73046f33ca943:

  ARM: dts: imx35: restore existing used clock enumeration (2016-04-18 12:37:21 +0800)

----------------------------------------------------------------
The i.MX clock fixes for 4.6, take 2:
 - Fix the commit 3713e3f5e927 ("clk: imx35: define two clocks for rtc")
   which messed up the clock enumeration when adding new clock.

----------------------------------------------------------------
Alexander Kurz (1):
      ARM: dts: imx35: restore existing used clock enumeration

 Documentation/devicetree/bindings/clock/imx35-clock.txt | 1 +
 drivers/clk/imx/clk-imx35.c                             | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)


From shawnguo at kernel.org  Tue May  3 06:43:57 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue, 3 May 2016 21:43:57 +0800
Subject: [GIT PULL] i.MX clock updates for 4.7, take 2
Message-ID: <20160503134356.GO5874@tiger>

The following changes since commit 69c542e8022ca53c5fee664548163809eb1777c3:

  clk: imx: vf610: fix whitespace in vf610-clock.h (2016-04-12 09:31:08 +0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-clk-4.7-2

for you to fetch changes up to 92a847e3609a8d00bcbe8bdfacbcbbca03135410:

  clk: imx7d: fix ahb clock mux 1 (2016-05-03 20:35:38 +0800)

----------------------------------------------------------------
The i.MX clock updates for 4.7, take 2:
 - Update clk-pllv3 driver to get it return correct frequency for
   Ethernet PLL on i.MX7D.
 - Correct ahb clock mux settings for i.MX7D per latest hardware
   document.

----------------------------------------------------------------
Stefan Agner (2):
      clk: imx: return correct frequency for Ethernet PLL
      clk: imx7d: fix ahb clock mux 1

 drivers/clk/imx/clk-imx7d.c | 2 +-
 drivers/clk/imx/clk-pllv3.c | 9 ++++++++-
 2 files changed, 9 insertions(+), 2 deletions(-)


From linux at roeck-us.net  Tue May  3 06:47:12 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 3 May 2016 06:47:12 -0700
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <20160503132439.GC13045@dhcppc6.redhat.com>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <57289594.3050801@codeaurora.org> <20160503132439.GC13045@dhcppc6.redhat.com>
Message-ID: <5728ABE0.5040000@roeck-us.net>

On 05/03/2016 06:24 AM, Pratyush Anand wrote:
> On 03/05/2016:07:12:04 AM, Timur Tabi wrote:
>> Pratyush Anand wrote:
>>> + * Note: This watchdog timer has two stages. If action is 0, first stage is
>>> + * determined by directly programming WCV and second by WOR. When first
>>> + * timeout is reached, WS0 is triggered and WCV is reloaded with value in
>>> + * WOR. WS0 interrupt will be ignored, then the second watch period starts;
>>> + * when second timeout is reached, then WS1 is triggered, system resets. WCV
>>> + * and WOR are programmed in such a way that total time corresponding to
>>> + * WCV+WOR becomes equivalent to user programmed "timeout".
>>> + * If action is 1, then we expect to call panic() at user programmed
>>> + * "timeout". Therefore, we program both first and second stage using WCV
>>> + * only.
>>
>> So I'm not sure I understand how this works yet, but there was an earlier
>> version of Fu's driver that did something similar.  It depended on being
>> able to reprogram the hardware during the WS0 interrupt, and that was
>> rejected by the community.
>>
>> How is what you are doing different?
>
> * Following was the comment for Fu Wei's primitive version of patch [1], because
> * of which community rejected it.
>
>> The triggering of the hardware reset should never depend on an interrupt being
>> handled properly.  You should always program WCV correctly in advance.
>
> Now, there are couple of things different:
>
> (1) There is an important difference in upstreamed version than the version [1]
> which was rejected on above ground. In upstreamed version,  there would be no
> interrupt handler when we are in normal mode ie action=0.  So, there is no
> possibility of doing any thing in ISR for all normal usage of this timer. In
> this mode WCV is always programmed well in advance now.
>
> (2)action=1 mechanism was introduced to implement a dump saving mechanism if
> watchdog timeout expires before next kick. So, the current upstream version
> calls panic() in ISR. When action=1, then we do write WCV now in ISR, but there
> too some precaution have been taken.
>
> When action=1, and we land into isr handler sbsa_gwdt_interrupt() we can not
> trust watchdog data structure any more. That might have been corrupted.

Why ?

> (i) So it might happen that gwdt or wdd pointers have a corrupted value and as
> soon as we access gwdt->wdd or wdd->timeout, kernel panics. *No harm*, just
> panic() is called a bit early, which dump saving mechanism would be able to
> find. So, in fact it will give an extra information to dump saving mechanism
> that watchdog structure was corrupted as well.
> (ii) Another case, It might happen that wdd->timeout has been corrupted with
> large values. This patch does a protection while programming WCV in ISR. It

How would wdd->timeout be corrupted ?

If what you are say is correct, the interrupt handler can not be trusted, period,
and should be disabled entirely.

Guenter

> checks wdd->timeout against MAX_TIMEOUT value and reprograms WCV only when
> wdd->timeout is lesser than MAX_TIMEOUT. So, here too, there would be watchdog
> reset for sure if dump saving mechanism hangs.
>
> ~Pratyush
>
> [1] https://lists.linaro.org/pipermail/linaro-acpi/2015-June/004956.html
>



From van.freenix at gmail.com  Tue May  3 06:50:30 2016
From: van.freenix at gmail.com (Peng Fan)
Date: Tue,  3 May 2016 21:50:30 +0800
Subject: [PATCH V2] iommu/arm-smmu: clear cache lock bit of ACR
Message-ID: <1462283430-9559-1-git-send-email-van.freenix@gmail.com>

According MMU-500r2 TRM, section 3.7.1 Auxiliary Control registers,
You can modify ACTLR only when the ACR.CACHE_LOCK bit is 0.

So before clearing ARM_MMU500_ACTLR_CPRE of each context bank,
need clear CACHE_LOCK bit of ACR register first.

Since CACHE_LOCK bit is only present in MMU-500r2 onwards,
need to check the major number of IDR7.

Signed-off-by: Peng Fan <van.freenix at gmail.com>
Cc: Will Deacon <will.deacon at arm.com>
Cc: Robin Murphy <robin.murphy at arm.com>
---

V2:
 Following Robin's comments, need to check IDR7 before clearing
 CACHE_LOCK bit of ACR.

V1:
 Patch based on iommu/devel

 drivers/iommu/arm-smmu.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index acff332..c7ad23e 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -98,6 +98,9 @@
 #define sCR0_BSU_SHIFT			14
 #define sCR0_BSU_MASK			0x3
 
+/* Auxiliary Configuration register */
+#define ARM_SMMU_GR0_sACR		0x10
+
 /* Identification registers */
 #define ARM_SMMU_GR0_ID0		0x20
 #define ARM_SMMU_GR0_ID1		0x24
@@ -144,6 +147,9 @@
 #define ID2_PTFS_64K			(1 << 14)
 #define ID2_VMID16			(1 << 15)
 
+#define ID7_MAJOR_SHIFT			4
+#define ID7_MAJOR_MASK			0xf
+
 /* Global TLB invalidation */
 #define ARM_SMMU_GR0_TLBIVMID		0x64
 #define ARM_SMMU_GR0_TLBIALLNSNH	0x68
@@ -235,6 +241,8 @@
 
 #define ARM_MMU500_ACTLR_CPRE		(1 << 1)
 
+#define ARM_MMU500_ACR_CACHE_LOCK	(1 << 26)
+
 #define CB_PAR_F			(1 << 0)
 
 #define ATSR_ACTIVE			(1 << 0)
@@ -1493,7 +1501,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
 	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
 	void __iomem *cb_base;
 	int i = 0;
-	u32 reg;
+	u32 reg, major;
 
 	/* clear global FSR */
 	reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
@@ -1506,6 +1514,19 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
 		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(i));
 	}
 
+	/*
+	 * Before clearing ARM_MMU500_ACTLR_CPRE, need to
+	 * clear CACHE_LOCK bit of ACR first. And, CACHE_LOCK
+	 * bit is only present in MMU-500r2 onwards.
+	 */
+	reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID7);
+	major = (reg >> ID7_MAJOR_SHIFT) & ID7_MAJOR_MASK;
+	if ((smmu->model == ARM_MMU500) && (major >= 2)) {
+		reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sACR);
+		reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
+		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sACR);
+	}
+
 	/* Make sure all context banks are disabled and clear CB_FSR  */
 	for (i = 0; i < smmu->num_context_banks; ++i) {
 		cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, i);
-- 
2.6.2



From linux at roeck-us.net  Tue May  3 06:53:47 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 3 May 2016 06:53:47 -0700
Subject: (v4.4/v4.5)-stable-queue build and qemu failures
 (arm:allmodconfig, arm:pxa_defconfig, arm:omap2plus_defconfig)
In-Reply-To: <CAHCN7xJ0vS9GHWmg__z5SQtHKfdCDGKD6m0_=zewbY65Jyf9PA@mail.gmail.com>
References: <20160429201914.GA27596@roeck-us.net>
 <CAHCN7xJ0vS9GHWmg__z5SQtHKfdCDGKD6m0_=zewbY65Jyf9PA@mail.gmail.com>
Message-ID: <5728AD6B.5020106@roeck-us.net>

On 05/03/2016 06:35 AM, Adam Ford wrote:
> On Fri, Apr 29, 2016 at 3:19 PM, Guenter Roeck <linux at roeck-us.net> wrote:
>> v4.4 (arm:allmodconfig):
>>
>> drivers/mtd/nand/pxa3xx_nand.c: In function 'alloc_nand_resource':
>> drivers/mtd/nand/pxa3xx_nand.c:1753:7: error: 'np' undeclared
>>
>> v4.5 (arm:allmodconfig, arm:pxa_defconfig):
>>
>> drivers/dma/pxa_dma.c: In function 'pxad_probe':
>> drivers/dma/pxa_dma.c:1421:24: error: 'struct mmp_dma_platdata' has no member named 'nb_requestors'
>>
>> There is also a qemu runtime failure with omap2plus_defconfig in v4.4.
>>
>> [    2.412322] omap_i2c 48070000.i2c: bus 0 rev3.3 at 2600 kHz
>> [    2.417541] omap_i2c 48060000.i2c: bus 2 rev3.3 at 100 kHz
>> [    2.429443]
>> [    2.429534] =====================================
>> [    2.429718] [ BUG: bad unlock balance detected! ]
>> [    2.429962] 4.4.8-00025-gcd58757 #1 Not tainted
>> [    2.430145] -------------------------------------
>> [    2.430328] kworker/u2:0/6 is trying to release lock (&rdev->mutex) at:
>> [    2.430694] [<c03b40e4>] regulator_set_voltage+0x40/0x54
>> [    2.430877] but there are no more locks to release!
>>
>
> I am also seeing this in 4.4.8 on an DM3730.  I didn't see it in
> 4.4.3.  I can also help bisect if it helps.
> -adam
>

I ended up bisecting it [1]. The problem is seen in 4.4.7 and 4.4.8
(I originally thought 4.4.6 was affected as well, but it was introduced
in 4.4.7). It will be fixed in 4.4.9; the necessary patches are already
in the queue.

Guenter

---
[1] http://thread.gmane.org/gmane.linux.kernel.stable/176811


From fabio.estevam at nxp.com  Tue May  3 06:57:31 2016
From: fabio.estevam at nxp.com (Fabio Estevam)
Date: Tue, 3 May 2016 10:57:31 -0300
Subject: [PATCH] ARM: dts: imx: Remove unneeded unit-addresses
Message-ID: <1462283851-10820-1-git-send-email-fabio.estevam@nxp.com>

Building with W=1 option leads to several warnings like:

Warning (unit_address_vs_reg): Node /soc/aips-bus at 02000000/anatop at 020c8000/regulator-1p1 at 110 has a unit name, but no reg property

Fix them by removing the unneeded unit-addresses.

Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
---
 arch/arm/boot/dts/imx6sl.dtsi | 12 ++++++------
 arch/arm/boot/dts/imx6sx.dtsi | 12 ++++++------
 arch/arm/boot/dts/imx6ul.dtsi |  6 +++---
 arch/arm/boot/dts/imx7d.dtsi  |  2 +-
 4 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index d12b250..224c0d0 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -461,7 +461,7 @@
 					     <0 54 IRQ_TYPE_LEVEL_HIGH>,
 					     <0 127 IRQ_TYPE_LEVEL_HIGH>;
 
-				regulator-1p1 at 110 {
+				regulator-1p1 {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vdd1p1";
 					regulator-min-microvolt = <800000>;
@@ -475,7 +475,7 @@
 					anatop-max-voltage = <1375000>;
 				};
 
-				regulator-3p0 at 120 {
+				regulator-3p0 {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vdd3p0";
 					regulator-min-microvolt = <2800000>;
@@ -489,7 +489,7 @@
 					anatop-max-voltage = <3400000>;
 				};
 
-				regulator-2p5 at 130 {
+				regulator-2p5 {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vdd2p5";
 					regulator-min-microvolt = <2100000>;
@@ -503,7 +503,7 @@
 					anatop-max-voltage = <2850000>;
 				};
 
-				reg_arm: regulator-vddcore at 140 {
+				reg_arm: regulator-vddcore {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vddarm";
 					regulator-min-microvolt = <725000>;
@@ -520,7 +520,7 @@
 					anatop-max-voltage = <1450000>;
 				};
 
-				reg_pu: regulator-vddpu at 140 {
+				reg_pu: regulator-vddpu {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vddpu";
 					regulator-min-microvolt = <725000>;
@@ -537,7 +537,7 @@
 					anatop-max-voltage = <1450000>;
 				};
 
-				reg_soc: regulator-vddsoc at 140 {
+				reg_soc: regulator-vddsoc {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vddsoc";
 					regulator-min-microvolt = <725000>;
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index 6a993bfda..2863c52 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -547,7 +547,7 @@
 					     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
 					     <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
 
-				regulator-1p1 at 110 {
+				regulator-1p1 {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vdd1p1";
 					regulator-min-microvolt = <800000>;
@@ -561,7 +561,7 @@
 					anatop-max-voltage = <1375000>;
 				};
 
-				regulator-3p0 at 120 {
+				regulator-3p0 {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vdd3p0";
 					regulator-min-microvolt = <2800000>;
@@ -575,7 +575,7 @@
 					anatop-max-voltage = <3400000>;
 				};
 
-				regulator-2p5 at 130 {
+				regulator-2p5 {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vdd2p5";
 					regulator-min-microvolt = <2100000>;
@@ -589,7 +589,7 @@
 					anatop-max-voltage = <2875000>;
 				};
 
-				reg_arm: regulator-vddcore at 140 {
+				reg_arm: regulator-vddcore {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vddarm";
 					regulator-min-microvolt = <725000>;
@@ -606,7 +606,7 @@
 					anatop-max-voltage = <1450000>;
 				};
 
-				reg_pcie: regulator-vddpcie at 140 {
+				reg_pcie: regulator-vddpcie {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vddpcie";
 					regulator-min-microvolt = <725000>;
@@ -622,7 +622,7 @@
 					anatop-max-voltage = <1450000>;
 				};
 
-				reg_soc: regulator-vddsoc at 140 {
+				reg_soc: regulator-vddsoc {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vddsoc";
 					regulator-min-microvolt = <725000>;
diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
index 4356b65..b15ed37 100644
--- a/arch/arm/boot/dts/imx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul.dtsi
@@ -512,7 +512,7 @@
 					     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
 					     <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
 
-				reg_3p0: regulator-3p0 at 120 {
+				reg_3p0: regulator-3p0 {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vdd3p0";
 					regulator-min-microvolt = <2625000>;
@@ -526,7 +526,7 @@
 					anatop-enable-bit = <0>;
 				};
 
-				reg_arm: regulator-vddcore at 140 {
+				reg_arm: regulator-vddcore {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "cpu";
 					regulator-min-microvolt = <725000>;
@@ -543,7 +543,7 @@
 					anatop-max-voltage = <1450000>;
 				};
 
-				reg_soc: regulator-vddsoc at 140 {
+				reg_soc: regulator-vddsoc {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vddsoc";
 					regulator-min-microvolt = <725000>;
diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi
index 6b3faa2..d70d55d 100644
--- a/arch/arm/boot/dts/imx7d.dtsi
+++ b/arch/arm/boot/dts/imx7d.dtsi
@@ -522,7 +522,7 @@
 				interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
 					<GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
 
-				reg_1p0d: regulator-vdd1p0d at 210 {
+				reg_1p0d: regulator-vdd1p0d {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vdd1p0d";
 					regulator-min-microvolt = <800000>;
-- 
1.9.1



From mbrugger at suse.com  Tue May  3 07:05:07 2016
From: mbrugger at suse.com (Matthias Brugger)
Date: Tue,  3 May 2016 16:05:07 +0200
Subject: [PATCH] drivers: net: xgene: Fix error handling
Message-ID: <1462284307-15401-1-git-send-email-mbrugger@suse.com>

When probe bails out with an error, we try to unregister the
netdev before we have even registered it. Fix the goto statements
for that.

Signed-off-by: Matthias Brugger <mbrugger at suse.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 8d4c1ad..99d7e58 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1595,21 +1595,22 @@ static int xgene_enet_probe(struct platform_device *pdev)
 
 	ret = xgene_enet_init_hw(pdata);
 	if (ret)
-		goto err;
+		goto err_netdev;
 
 	mac_ops = pdata->mac_ops;
 	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
 		ret = xgene_enet_mdio_config(pdata);
 		if (ret)
-			goto err;
+			goto err_netdev;
 	} else {
 		INIT_DELAYED_WORK(&pdata->link_work, mac_ops->link_state);
 	}
 
 	xgene_enet_napi_add(pdata);
 	return 0;
-err:
+err_netdev:
 	unregister_netdev(ndev);
+err:
 	free_netdev(ndev);
 	return ret;
 }
-- 
2.6.6



From marc.zyngier at arm.com  Tue May  3 07:17:04 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue,  3 May 2016 15:17:04 +0100
Subject: [PATCH] KVM: arm/arm64: vgic-new: Switch to firmware-independent
 probing
Message-ID: <1462285024-3801-1-git-send-email-marc.zyngier@arm.com>

As we did for the legacy code, switch the new VGIC implementation
the firmware-independent probing, giving us ACPI support for free.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
This patch of course relies on Julien's previous series.
I've tested it on Mustang (v2) and LS2080 (v3).

 virt/kvm/arm/vgic/vgic-init.c | 37 ++++++++++----------
 virt/kvm/arm/vgic/vgic-v2.c   | 79 +++++++++++++++----------------------------
 virt/kvm/arm/vgic/vgic-v3.c   | 38 +++++----------------
 virt/kvm/arm/vgic/vgic.h      |  6 ++--
 4 files changed, 61 insertions(+), 99 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 27b21c4..4c8e448 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -387,14 +387,6 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static const struct of_device_id vgic_ids[] = {
-	{ .compatible = "arm,cortex-a15-gic",	.data = vgic_v2_probe, },
-	{ .compatible = "arm,cortex-a7-gic",	.data = vgic_v2_probe, },
-	{ .compatible = "arm,gic-400",		.data = vgic_v2_probe, },
-	{ .compatible = "arm,gic-v3",		.data = vgic_v3_probe, },
-	{},
-};
-
 /**
  * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable
  * according to the host GIC model. Accordingly calls either
@@ -403,23 +395,33 @@ static const struct of_device_id vgic_ids[] = {
  */
 int kvm_vgic_hyp_init(void)
 {
-	const struct of_device_id *matched_id;
-	const int (*vgic_probe)(struct device_node *);
-	struct device_node *vgic_node;
+	const struct gic_kvm_info *gic_kvm_info;
 	int ret;
 
-	vgic_node = of_find_matching_node_and_match(NULL,
-						    vgic_ids, &matched_id);
-	if (!vgic_node) {
-		kvm_err("error: no compatible GIC node found\n");
+	gic_kvm_info = gic_get_kvm_info();
+	if (!gic_kvm_info)
 		return -ENODEV;
+
+	if (!gic_kvm_info->maint_irq) {
+		kvm_err("No vgic maintenance irq\n");
+		return -ENXIO;
 	}
 
-	vgic_probe = matched_id->data;
-	ret = vgic_probe(vgic_node);
+	switch (gic_kvm_info->type) {
+	case GIC_V2:
+		ret = vgic_v2_probe(gic_kvm_info);
+		break;
+	case GIC_V3:
+		ret = vgic_v3_probe(gic_kvm_info);
+		break;
+	default:
+		ret = -ENODEV;
+	};
+
 	if (ret)
 		return ret;
 
+	kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
 	ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
 				 vgic_maintenance_handler,
 				 "vgic", kvm_get_running_vcpus());
@@ -437,6 +439,7 @@ int kvm_vgic_hyp_init(void)
 
 	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
 
+	kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq);
 	return 0;
 
 out_free_irq:
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index b8bfece..5f09c90 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -278,81 +278,58 @@ out:
  *
  * Returns 0 if a GICv2 has been found, returns an error code otherwise
  */
-int vgic_v2_probe(struct device_node *vgic_node)
+int vgic_v2_probe(const struct gic_kvm_info *info)
 {
 	int ret;
-	struct resource vctrl_res;
-	struct resource vcpu_res;
 
-	kvm_vgic_global_state.maint_irq = irq_of_parse_and_map(vgic_node, 0);
-	if (!kvm_vgic_global_state.maint_irq) {
-		kvm_err("error getting vgic maintenance irq from DT\n");
-		ret = -ENXIO;
-		goto out;
+	if (!info->vctrl.start) {
+		kvm_err("GICH not present in the firmware table\n");
+		return -ENXIO;
 	}
 
-	ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
-	if (ret) {
-		kvm_err("Cannot obtain GICH resource\n");
-		goto out;
+	if (!PAGE_ALIGNED(info->vcpu.start)) {
+		kvm_err("GICV physical address 0x%llx not page aligned\n",
+			(unsigned long long)info->vcpu.start);
+		return -ENXIO;
+	}
+
+	if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
+		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+			(unsigned long long)resource_size(&info->vcpu),
+			PAGE_SIZE);
+		return -ENXIO;
 	}
 
-	kvm_vgic_global_state.vctrl_base = of_iomap(vgic_node, 2);
+	kvm_vgic_global_state.vctrl_base = ioremap(info->vctrl.start,
+						   resource_size(&info->vctrl));
 	if (!kvm_vgic_global_state.vctrl_base) {
 		kvm_err("Cannot ioremap GICH\n");
-		ret = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
 
 	kvm_vgic_global_state.nr_lr =
 		readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
-	kvm_vgic_global_state.nr_lr = (kvm_vgic_global_state.nr_lr & 0x3f) + 1;
+	kvm_vgic_global_state.nr_lr &= 0x3f;
+	kvm_vgic_global_state.nr_lr += 1;
 
 	ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
 				     kvm_vgic_global_state.vctrl_base +
-					 resource_size(&vctrl_res),
-				     vctrl_res.start);
+					 resource_size(&info->vctrl),
+				     info->vctrl.start);
 	if (ret) {
 		kvm_err("Cannot map VCTRL into hyp\n");
-		goto out_unmap;
-	}
-
-	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
-		kvm_err("Cannot obtain GICV resource\n");
-		ret = -ENXIO;
-		goto out_unmap;
-	}
-
-	if (!PAGE_ALIGNED(vcpu_res.start)) {
-		kvm_err("GICV physical address 0x%llx not page aligned\n",
-			(unsigned long long)vcpu_res.start);
-		ret = -ENXIO;
-		goto out_unmap;
-	}
-
-	if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
-		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
-			(unsigned long long)resource_size(&vcpu_res),
-			PAGE_SIZE);
-		ret = -ENXIO;
-		goto out_unmap;
+		iounmap(kvm_vgic_global_state.vctrl_base);
+		return ret;
 	}
 
 	kvm_vgic_global_state.can_emulate_gicv2 = true;
 	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
 
-	kvm_vgic_global_state.vcpu_base = vcpu_res.start;
-
-	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
-		 vctrl_res.start, kvm_vgic_global_state.maint_irq);
-
+	kvm_vgic_global_state.vcpu_base = info->vcpu.start;
 	kvm_vgic_global_state.type = VGIC_V2;
 	kvm_vgic_global_state.max_gic_vcpus = VGIC_V2_MAX_CPUS;
-	goto out;
 
-out_unmap:
-	iounmap(kvm_vgic_global_state.vctrl_base);
-out:
-	of_node_put(vgic_node);
-	return ret;
+	kvm_info("vgic-v2@%llx\n", info->vctrl.start);
+
+	return 0;
 }
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index e975a33..014a14f 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -274,19 +274,8 @@ out:
  *
  * Returns 0 if a GICv3 has been found, returns an error code otherwise
  */
-int vgic_v3_probe(struct device_node *vgic_node)
+int vgic_v3_probe(const struct gic_kvm_info *info)
 {
-	int ret = 0;
-	u32 gicv_idx;
-	struct resource vcpu_res;
-
-	kvm_vgic_global_state.maint_irq = irq_of_parse_and_map(vgic_node, 0);
-	if (!kvm_vgic_global_state.maint_irq) {
-		kvm_err("error getting vgic maintenance irq from DT\n");
-		ret = -ENXIO;
-		goto out;
-	}
-
 	ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
 
 	/*
@@ -296,27 +285,23 @@ int vgic_v3_probe(struct device_node *vgic_node)
 	kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
 	kvm_vgic_global_state.can_emulate_gicv2 = false;
 
-	if (of_property_read_u32(vgic_node, "#redistributor-regions",
-				 &gicv_idx))
-		gicv_idx = 1;
-
-	gicv_idx += 3; /* Also skip GICD, GICC, GICH */
-	if (of_address_to_resource(vgic_node, gicv_idx, &vcpu_res)) {
+	if (!info->vcpu.start) {
 		kvm_info("GICv3: no GICV resource entry\n");
 		kvm_vgic_global_state.vcpu_base = 0;
-	} else if (!PAGE_ALIGNED(vcpu_res.start)) {
+	} else if (!PAGE_ALIGNED(info->vcpu.start)) {
 		pr_warn("GICV physical address 0x%llx not page aligned\n",
-			(unsigned long long)vcpu_res.start);
+			(unsigned long long)info->vcpu.start);
 		kvm_vgic_global_state.vcpu_base = 0;
-	} else if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
+	} else if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
 		pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
-			(unsigned long long)resource_size(&vcpu_res),
+			(unsigned long long)resource_size(&info->vcpu),
 			PAGE_SIZE);
 		kvm_vgic_global_state.vcpu_base = 0;
 	} else {
-		kvm_vgic_global_state.vcpu_base = vcpu_res.start;
+		kvm_vgic_global_state.vcpu_base = info->vcpu.start;
 		kvm_vgic_global_state.can_emulate_gicv2 = true;
 		kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+		kvm_info("vgic-v2@%llx\n", info->vcpu.start);
 	}
 	if (kvm_vgic_global_state.vcpu_base == 0)
 		kvm_info("disabling GICv2 emulation\n");
@@ -326,10 +311,5 @@ int vgic_v3_probe(struct device_node *vgic_node)
 	kvm_vgic_global_state.type = VGIC_V3;
 	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
 
-	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
-		 vcpu_res.start, kvm_vgic_global_state.maint_irq);
-
-out:
-	of_node_put(vgic_node);
-	return ret;
+	return 0;
 }
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index f970e3e..6d2cede 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,6 +16,8 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#include <linux/irqchip/arm-gic-common.h>
+
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
@@ -42,7 +44,7 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_enable(struct kvm_vcpu *vcpu);
-int vgic_v2_probe(struct device_node *vgic_node);
+int vgic_v2_probe(const struct gic_kvm_info *info);
 int vgic_v2_map_resources(struct kvm *kvm);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
@@ -56,7 +58,7 @@ void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_enable(struct kvm_vcpu *vcpu);
-int vgic_v3_probe(struct device_node *vgic_node);
+int vgic_v3_probe(const struct gic_kvm_info *info);
 int vgic_v3_map_resources(struct kvm *kvm);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
-- 
2.1.4



From panand at redhat.com  Tue May  3 07:17:17 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 3 May 2016 19:47:17 +0530
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <5728ABE0.5040000@roeck-us.net>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <57289594.3050801@codeaurora.org>
 <20160503132439.GC13045@dhcppc6.redhat.com>
 <5728ABE0.5040000@roeck-us.net>
Message-ID: <20160503141717.GD13045@dhcppc6.redhat.com>

Hi Guenter,

On 03/05/2016:06:47:12 AM, Guenter Roeck wrote:
> On 05/03/2016 06:24 AM, Pratyush Anand wrote:
> >On 03/05/2016:07:12:04 AM, Timur Tabi wrote:
> >>Pratyush Anand wrote:
> >>>+ * Note: This watchdog timer has two stages. If action is 0, first stage is
> >>>+ * determined by directly programming WCV and second by WOR. When first
> >>>+ * timeout is reached, WS0 is triggered and WCV is reloaded with value in
> >>>+ * WOR. WS0 interrupt will be ignored, then the second watch period starts;
> >>>+ * when second timeout is reached, then WS1 is triggered, system resets. WCV
> >>>+ * and WOR are programmed in such a way that total time corresponding to
> >>>+ * WCV+WOR becomes equivalent to user programmed "timeout".
> >>>+ * If action is 1, then we expect to call panic() at user programmed
> >>>+ * "timeout". Therefore, we program both first and second stage using WCV
> >>>+ * only.
> >>
> >>So I'm not sure I understand how this works yet, but there was an earlier
> >>version of Fu's driver that did something similar.  It depended on being
> >>able to reprogram the hardware during the WS0 interrupt, and that was
> >>rejected by the community.
> >>
> >>How is what you are doing different?
> >
> >* Following was the comment for Fu Wei's primitive version of patch [1], because
> >* of which community rejected it.
> >
> >>The triggering of the hardware reset should never depend on an interrupt being
> >>handled properly.  You should always program WCV correctly in advance.
> >
> >Now, there are couple of things different:
> >
> >(1) There is an important difference in upstreamed version than the version [1]
> >which was rejected on above ground. In upstreamed version,  there would be no
> >interrupt handler when we are in normal mode ie action=0.  So, there is no
> >possibility of doing any thing in ISR for all normal usage of this timer. In
> >this mode WCV is always programmed well in advance now.
> >
> >(2)action=1 mechanism was introduced to implement a dump saving mechanism if
> >watchdog timeout expires before next kick. So, the current upstream version
> >calls panic() in ISR. When action=1, then we do write WCV now in ISR, but there
> >too some precaution have been taken.
> >
> >When action=1, and we land into isr handler sbsa_gwdt_interrupt() we can not
> >trust watchdog data structure any more. That might have been corrupted.
> 
> Why ?
> 
> >(i) So it might happen that gwdt or wdd pointers have a corrupted value and as
> >soon as we access gwdt->wdd or wdd->timeout, kernel panics. *No harm*, just
> >panic() is called a bit early, which dump saving mechanism would be able to
> >find. So, in fact it will give an extra information to dump saving mechanism
> >that watchdog structure was corrupted as well.
> >(ii) Another case, It might happen that wdd->timeout has been corrupted with
> >large values. This patch does a protection while programming WCV in ISR. It
> 
> How would wdd->timeout be corrupted ?

Most likely it will not be corrupted. But, if ISR has been called it means
something went wrong, and watchdog was not kicked for the time programmed as
"timeout". So, probably we should be extra careful.

Anyway, there is no side effect of checking wdd->timeout against MAX_TIMEOUT.

Moreover, I was unable to envisage any regression with this patch other than
that it introduces a bit complexity. But, then it gives us an advantage of
having any timeout value.

> If what you are say is correct, the interrupt handler can not be trusted, period,
> and should be disabled entirely.

Yes, When system is hang, then probably we can not trust even interrupt handler.
We can not be 100% sure that handler will be called, but that is the case with
existing upstream code as well. In such situation upstream code will also
misbehave. There is little we can do for such cases.

If one wants to be fully assured for a hardware watchdog reset then the choice
is action=0. Even after current patch, action=0 will ensure that there would be
a hardware reset upon timeout.

~Pratyush


From broonie at kernel.org  Tue May  3 07:17:23 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 3 May 2016 15:17:23 +0100
Subject: next-20160503 build: 1 failures 12 warnings (next-20160503)
In-Reply-To: <E1axZpG-000664-AK@optimist>
References: <E1axZpG-000664-AK@optimist>
Message-ID: <20160503141723.GR6292@sirena.org.uk>

On Tue, May 03, 2016 at 01:53:18PM +0100, Build bot for Mark Brown wrote:

Today's -next fails to build an ARM allmodconfig due to:

> 	arm-allmodconfig
> ../drivers/pinctrl/bcm/pinctrl-ns2-mux.c:540:17: error: 'pinctrl_utils_dt_free_map' undeclared here (not in a function)

caused by b5aa1006e4a93 (pinctrl: ns2: add pinmux driver support for
Broadcom NS2 SoC) - presumably just a missing dependency.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160503/33e6ab74/attachment.sig>

From p.zabel at pengutronix.de  Tue May  3 07:20:42 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Tue, 03 May 2016 16:20:42 +0200
Subject: [PATCH 1/7] reset: add devm_reset_controller_register API
In-Reply-To: <CAK7LNAT-fK9zMSov4h8CaG0nbqq=N466zBGFOnZA5LWuxgwDOg@mail.gmail.com>
References: <1462099023-11819-1-git-send-email-yamada.masahiro@socionext.com>
 <1462099023-11819-2-git-send-email-yamada.masahiro@socionext.com>
 <1462270670.3617.49.camel@pengutronix.de>
 <CAK7LNAR699QqYvWdFPtnBc=bLyMLvhCvnKJQCR4YHCy7HQTjUQ@mail.gmail.com>
 <CAK7LNAT-fK9zMSov4h8CaG0nbqq=N466zBGFOnZA5LWuxgwDOg@mail.gmail.com>
Message-ID: <1462285242.3617.74.camel@pengutronix.de>

Am Dienstag, den 03.05.2016, 20:41 +0900 schrieb Masahiro Yamada:
> 2016-05-03 19:26 GMT+09:00 Masahiro Yamada <yamada.masahiro at socionext.com>:
> > 2016-05-03 19:17 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> >> Hi Masahiro,
> >>
> >> Am Sonntag, den 01.05.2016, 19:36 +0900 schrieb Masahiro Yamada:
> >>> Add a device managed API for reset_controller_register().
> >>>
> >>> This helps in reducing code in .remove callbacks and sometimes
> >>> dropping .remove callbacks entirely.
> >>>
> >>> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> >>
> >> Thank you for these patches. Except for the issue with the lpc18xx patch
> >> they all look good to me.
> >> If you don't mind, I'll drop the lpc18xx patch for now and apply the
> >> others.
> >>
> >
> > It is OK with me, but I do not understand what is the problem.
> >
> > Could you answer my question in the 3/7 thread?
>
> Now I am convinced.
> 
> I leave 3/7 to your decision.

Ok, I applied all but 3/7 to my reset/next branch.

thanks
Philipp



From dinguyen at opensource.altera.com  Tue May  3 07:13:58 2016
From: dinguyen at opensource.altera.com (dinguyen at opensource.altera.com)
Date: Tue, 3 May 2016 09:13:58 -0500
Subject: [PATCH] ARM: dts: socfpga: add ethernet alias on Arria10
Message-ID: <1462284838-14852-1-git-send-email-dinguyen@opensource.altera.com>

From: Dinh Nguyen <dinguyen at opensource.altera.com>

Without having an ethernet alias, ethernet will have a random MAC address,
versus take an address that was provided from the bootloader.

Signed-off-by: Dinh Nguyen <dinguyen at opensource.altera.com>
---
 arch/arm/boot/dts/socfpga_arria10_socdk.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi b/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
index 567df98..ab33ee3 100644
--- a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
+++ b/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
@@ -20,6 +20,10 @@
 	model = "Altera SOCFPGA Arria 10";
 	compatible = "altr,socfpga-arria10", "altr,socfpga";
 
+	aliases {
+		ethernet0 = &gmac0;
+	};
+
 	chosen {
 		bootargs = "earlyprintk";
 		stdout-path = "serial1:115200n8";
-- 
2.6.2



From jchandra at broadcom.com  Tue May  3 07:22:52 2016
From: jchandra at broadcom.com (Jayachandran C)
Date: Tue, 3 May 2016 19:52:52 +0530
Subject: [PATCH V6 02/13] pci, acpi: Provide generic way to assign bus
 domain number.
In-Reply-To: <20160503110225.GA1055@red-moon>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-3-git-send-email-tn@semihalf.com>
 <20160427022649.GD6789@localhost>
 <20160427111758.GA6234@red-moon> <57274B8C.5030304@semihalf.com>
 <CAKc_7PU1AszF4y0OjZ3KVGaTEx9OL1cuT5YgOxQKhAQgQom7tA@mail.gmail.com>
 <20160503110225.GA1055@red-moon>
Message-ID: <CAKc_7PXBrVduNkdVr13argTNekvhV+XJFB7XD6aYOnP1CY6A6w@mail.gmail.com>

On Tue, May 3, 2016 at 4:32 PM, Lorenzo Pieralisi
<lorenzo.pieralisi at arm.com> wrote:
> On Mon, May 02, 2016 at 06:56:13PM +0530, Jayachandran C wrote:
>> On Mon, May 2, 2016 at 6:13 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
>> > On 04/27/2016 01:17 PM, Lorenzo Pieralisi wrote:
>> >>
>> >> On Tue, Apr 26, 2016 at 09:26:49PM -0500, Bjorn Helgaas wrote:
>> >>>
>> >>> On Fri, Apr 15, 2016 at 07:06:37PM +0200, Tomasz Nowicki wrote:
>> >
>> > [...]
>> >
>> >>>   +int acpi_pci_bus_domain_nr(struct device *parent)
>> >>> +{
>> >>> +       struct acpi_device *acpi_dev = to_acpi_device(parent);
>> >>> +       unsigned long long segment = 0;
>> >>> +       acpi_status status;
>> >>> +
>> >>> +       /*
>> >>> +        * If _SEG method does not exist, following ACPI spec (6.5.6)
>> >>> +        * all PCI buses belong to domain 0.
>> >>> +        */
>> >>> +       status = acpi_evaluate_integer(acpi_dev->handle,
>> >>> METHOD_NAME__SEG, NULL,
>> >>> +                                      &segment);
>> >>> We already have code in acpi_pci_root_add() to evaluate _SEG.  We
>> >>> don't want to evaluate it *twice*, do we?
>> >>>
>> >>> I was sort of expecting that if you added it here, we'd remove the
>> >>> existing call, but it looks like you're keeping both?
>> >>
>> >> We can't remove the existing call, since it is used on X86 and IA64
>> >> to store the segment number that, in the process, is used in their
>> >> pci_domain_nr() arch specific callback to retrieve the domain nr.
>> >>
>> >> On ARM64, that selects PCI_DOMAINS_GENERIC, we have to find a way
>> >> to retrieve the domain number that is not arch dependent, since
>> >> this is generic code, we can't rely on any bus->sysdata format (unless
>> >> we do something like JC did below), therefore the only way is to call
>> >> the _SEG method *again* here, which also forced Tomasz to go through
>> >> the ACPI_COMPANION setting song and dance and pass the parent pointer
>> >> to pci_create_root_bus() (see patch 1), which BTW is a source of
>> >> trouble on its own as you noticed.
>> >
>> > What trouble in patch 1 do you mean? I may miss something.
>> >
>> > I agree that patch 1 is not necessary if we decide to use sysdata or rework
>> > root bus scanning to move domain to host bridge. Nevertheless, patch 1 is
>> > still a cleanup IMO.
>>
>> In this case, getting the domain should be trivial since the ACPI
>> companion on parent is already set, this should work
>>
>> int acpi_pci_bus_domain_nr(struct device *parent)
>> {
>>         struct acpi_device *acpi_dev = to_acpi_device(parent);
>>         struct acpi_pci_root *root = acpi_dev->driver_data;
>>
>>         return root->segment;
>> }
>>
>> Or am I missing something here?
>
> Well, I thought that the whole idea behind this exercise was to move
> the domain number into struct pci_host_bridge (Arnd did not do it with
> his first set but this does not mean we can't add it as Bjorn suggested),
> so that the domain number could be read from there straight away in an
> arch (and FW) independent manner, right ?

The original issue was using _SEG call again instead of using
the value from acpi_pci_root, and the solution for that problem
is very simple.

The pci host bridge work is of course very useful, but creating a
dependency with that work for an issue that can be so easily solved
is unnecessary.

JC.


From panand at redhat.com  Tue May  3 07:38:56 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 3 May 2016 20:08:56 +0530
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <5728A7C3.4010001@roeck-us.net>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <5728A7C3.4010001@roeck-us.net>
Message-ID: <20160503143856.GE13045@dhcppc6.redhat.com>

Hi Guenter,

On 03/05/2016:06:29:39 AM, Guenter Roeck wrote:
> On 05/03/2016 01:20 AM, Pratyush Anand wrote:
> >Currently only WOR is used to program both first and second stage which
> >provided very limited range of timeout.
> >
> >This patch uses WCV as well to achieve higher range of timeout. This patch
> >programs max_timeout as 255, but that can be increased further as well.
> >
> >Following testing shows that we can happily achieve 40 second default timeout.
> >
> >  # modprobe sbsa_gwdt action=1
> >  [  131.187562] sbsa-gwdt sbsa-gwdt.0: Initialized with 40s timeout @ 250000000 Hz, action=1.
> >  # cd /sys/class/watchdog/watchdog0/
> >  # cat state
> >  inactive
> >  # cat /dev/watchdog0
> >  cat: /dev/watchdog0: Invalid argument
> >  [  161.710593] watchdog: watchdog0: watchdog did not stop!
> >  # cat state
> >  active
> >  # cat timeout
> >  40
> >  # cat timeleft
> >  38
> >  # cat timeleft
> >  25
> >  # cat /dev/watchdog0
> >  cat: /dev/watchdog0: Invalid argument
> >  [  184.931030] watchdog: watchdog0: watchdog did not stop!
> >  # cat timeleft
> >  37
> >  # cat timeleft
> >  21
> >  ...
> >  ...
> >  # cat timeleft
> >  1
> >
> >panic() is called upon timeout of 40s. See timestamp of last kick (cat) and
> >next panic() message.
> >
> >  [  224.939065] Kernel panic - not syncing: SBSA Watchdog timeout
> >
> >Signed-off-by: Pratyush Anand <panand at redhat.com>
> 
> You could also use the new infrastructure (specify max_hw_heartbeat_ms instead
> of max_timeout), and not depend on the correct implementation of WCV.

Thanks for pointing to max_hw_heartbeat_ms. Just gone through it. Certainly it
would be helpful, and some part of this patch will go away. 

In fact after supporting max_hw_heartbeat_ms, there should be no change for
action=0 functionally. However, we would still need some changes for action=1.

When action=1, isr is called, which calls panic(). Calling panic() will further
trigger a dump saving mechanism, which can cause to execute a secondary kernel.
Now, it might happen that with the limited timeout (max_hw_heartbeat_ms)
programmed in first kernel, we land into a reset before secondary kernel could
start kicking it again or would complete dump save. 
So, in my opinion:
(1) We should use max_hw_heartbeat_ms.
(2) Then we should overwrite WCV in ISR so that it ensures a timeout of user
programmed "timeout" value for hardware reset.

~Pratyush


From linux at roeck-us.net  Tue May  3 07:46:23 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 3 May 2016 07:46:23 -0700
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <20160503141717.GD13045@dhcppc6.redhat.com>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <57289594.3050801@codeaurora.org> <20160503132439.GC13045@dhcppc6.redhat.com>
 <5728ABE0.5040000@roeck-us.net> <20160503141717.GD13045@dhcppc6.redhat.com>
Message-ID: <5728B9BF.8050501@roeck-us.net>

On 05/03/2016 07:17 AM, Pratyush Anand wrote:
> Hi Guenter,
>
> On 03/05/2016:06:47:12 AM, Guenter Roeck wrote:
>> On 05/03/2016 06:24 AM, Pratyush Anand wrote:
>>> On 03/05/2016:07:12:04 AM, Timur Tabi wrote:
>>>> Pratyush Anand wrote:
>>>>> + * Note: This watchdog timer has two stages. If action is 0, first stage is
>>>>> + * determined by directly programming WCV and second by WOR. When first
>>>>> + * timeout is reached, WS0 is triggered and WCV is reloaded with value in
>>>>> + * WOR. WS0 interrupt will be ignored, then the second watch period starts;
>>>>> + * when second timeout is reached, then WS1 is triggered, system resets. WCV
>>>>> + * and WOR are programmed in such a way that total time corresponding to
>>>>> + * WCV+WOR becomes equivalent to user programmed "timeout".
>>>>> + * If action is 1, then we expect to call panic() at user programmed
>>>>> + * "timeout". Therefore, we program both first and second stage using WCV
>>>>> + * only.
>>>>
>>>> So I'm not sure I understand how this works yet, but there was an earlier
>>>> version of Fu's driver that did something similar.  It depended on being
>>>> able to reprogram the hardware during the WS0 interrupt, and that was
>>>> rejected by the community.
>>>>
>>>> How is what you are doing different?
>>>
>>> * Following was the comment for Fu Wei's primitive version of patch [1], because
>>> * of which community rejected it.
>>>
>>>> The triggering of the hardware reset should never depend on an interrupt being
>>>> handled properly.  You should always program WCV correctly in advance.
>>>
>>> Now, there are couple of things different:
>>>
>>> (1) There is an important difference in upstreamed version than the version [1]
>>> which was rejected on above ground. In upstreamed version,  there would be no
>>> interrupt handler when we are in normal mode ie action=0.  So, there is no
>>> possibility of doing any thing in ISR for all normal usage of this timer. In
>>> this mode WCV is always programmed well in advance now.
>>>
>>> (2)action=1 mechanism was introduced to implement a dump saving mechanism if
>>> watchdog timeout expires before next kick. So, the current upstream version
>>> calls panic() in ISR. When action=1, then we do write WCV now in ISR, but there
>>> too some precaution have been taken.
>>>
>>> When action=1, and we land into isr handler sbsa_gwdt_interrupt() we can not
>>> trust watchdog data structure any more. That might have been corrupted.
>>
>> Why ?
>>
>>> (i) So it might happen that gwdt or wdd pointers have a corrupted value and as
>>> soon as we access gwdt->wdd or wdd->timeout, kernel panics. *No harm*, just
>>> panic() is called a bit early, which dump saving mechanism would be able to
>>> find. So, in fact it will give an extra information to dump saving mechanism
>>> that watchdog structure was corrupted as well.
>>> (ii) Another case, It might happen that wdd->timeout has been corrupted with
>>> large values. This patch does a protection while programming WCV in ISR. It
>>
>> How would wdd->timeout be corrupted ?
>
> Most likely it will not be corrupted. But, if ISR has been called it means
> something went wrong, and watchdog was not kicked for the time programmed as
> "timeout". So, probably we should be extra careful.
>
This logic would apply to _every_ watchdog driver implementing interrupts.
Actually, it would apply to _all_ kernel code, and the logic could be used
to introduce hyper-defensive programming all over the place, bloat the kernel
and ultimately make it all but unusable. I do not believe in such programming
in an operating system kernel.

On top of that, the assumption that the kernel would be still sane enough
to call the interrupt handler, but not sane enough to actually execute it,
seems to be a bit far-fetched.

> Anyway, there is no side effect of checking wdd->timeout against MAX_TIMEOUT.
>
The side effect is increased code size.

> Moreover, I was unable to envisage any regression with this patch other than
> that it introduces a bit complexity. But, then it gives us an advantage of
> having any timeout value.
>
>> If what you are say is correct, the interrupt handler can not be trusted, period,
>> and should be disabled entirely.
>
> Yes, When system is hang, then probably we can not trust even interrupt handler.
> We can not be 100% sure that handler will be called, but that is the case with
> existing upstream code as well. In such situation upstream code will also
> misbehave. There is little we can do for such cases.
>
... other than wait for the hard reset, which will be just fine, at least
with the current code.

> If one wants to be fully assured for a hardware watchdog reset then the choice
> is action=0. Even after current patch, action=0 will ensure that there would be
> a hardware reset upon timeout.
>
Sorry, I don't buy into this. You'll have to convince Wim, or simply
change the driver to use the infrastructure to achieve larger timeouts.

Thanks,
Guenter



From lorenzo.pieralisi at arm.com  Tue May  3 07:55:12 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Tue, 3 May 2016 15:55:12 +0100
Subject: [PATCH V6 02/13] pci, acpi: Provide generic way to assign bus
 domain number.
In-Reply-To: <CAKc_7PXBrVduNkdVr13argTNekvhV+XJFB7XD6aYOnP1CY6A6w@mail.gmail.com>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-3-git-send-email-tn@semihalf.com>
 <20160427022649.GD6789@localhost> <20160427111758.GA6234@red-moon>
 <57274B8C.5030304@semihalf.com>
 <CAKc_7PU1AszF4y0OjZ3KVGaTEx9OL1cuT5YgOxQKhAQgQom7tA@mail.gmail.com>
 <20160503110225.GA1055@red-moon>
 <CAKc_7PXBrVduNkdVr13argTNekvhV+XJFB7XD6aYOnP1CY6A6w@mail.gmail.com>
Message-ID: <20160503145512.GA2429@red-moon>

On Tue, May 03, 2016 at 07:52:52PM +0530, Jayachandran C wrote:
> On Tue, May 3, 2016 at 4:32 PM, Lorenzo Pieralisi
> <lorenzo.pieralisi at arm.com> wrote:
> > On Mon, May 02, 2016 at 06:56:13PM +0530, Jayachandran C wrote:
> >> On Mon, May 2, 2016 at 6:13 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> >> > On 04/27/2016 01:17 PM, Lorenzo Pieralisi wrote:
> >> >>
> >> >> On Tue, Apr 26, 2016 at 09:26:49PM -0500, Bjorn Helgaas wrote:
> >> >>>
> >> >>> On Fri, Apr 15, 2016 at 07:06:37PM +0200, Tomasz Nowicki wrote:
> >> >
> >> > [...]
> >> >
> >> >>>   +int acpi_pci_bus_domain_nr(struct device *parent)
> >> >>> +{
> >> >>> +       struct acpi_device *acpi_dev = to_acpi_device(parent);
> >> >>> +       unsigned long long segment = 0;
> >> >>> +       acpi_status status;
> >> >>> +
> >> >>> +       /*
> >> >>> +        * If _SEG method does not exist, following ACPI spec (6.5.6)
> >> >>> +        * all PCI buses belong to domain 0.
> >> >>> +        */
> >> >>> +       status = acpi_evaluate_integer(acpi_dev->handle,
> >> >>> METHOD_NAME__SEG, NULL,
> >> >>> +                                      &segment);
> >> >>> We already have code in acpi_pci_root_add() to evaluate _SEG.  We
> >> >>> don't want to evaluate it *twice*, do we?
> >> >>>
> >> >>> I was sort of expecting that if you added it here, we'd remove the
> >> >>> existing call, but it looks like you're keeping both?
> >> >>
> >> >> We can't remove the existing call, since it is used on X86 and IA64
> >> >> to store the segment number that, in the process, is used in their
> >> >> pci_domain_nr() arch specific callback to retrieve the domain nr.
> >> >>
> >> >> On ARM64, that selects PCI_DOMAINS_GENERIC, we have to find a way
> >> >> to retrieve the domain number that is not arch dependent, since
> >> >> this is generic code, we can't rely on any bus->sysdata format (unless
> >> >> we do something like JC did below), therefore the only way is to call
> >> >> the _SEG method *again* here, which also forced Tomasz to go through
> >> >> the ACPI_COMPANION setting song and dance and pass the parent pointer
> >> >> to pci_create_root_bus() (see patch 1), which BTW is a source of
> >> >> trouble on its own as you noticed.
> >> >
> >> > What trouble in patch 1 do you mean? I may miss something.
> >> >
> >> > I agree that patch 1 is not necessary if we decide to use sysdata or rework
> >> > root bus scanning to move domain to host bridge. Nevertheless, patch 1 is
> >> > still a cleanup IMO.
> >>
> >> In this case, getting the domain should be trivial since the ACPI
> >> companion on parent is already set, this should work
> >>
> >> int acpi_pci_bus_domain_nr(struct device *parent)
> >> {
> >>         struct acpi_device *acpi_dev = to_acpi_device(parent);
> >>         struct acpi_pci_root *root = acpi_dev->driver_data;
> >>
> >>         return root->segment;
> >> }
> >>
> >> Or am I missing something here?
> >
> > Well, I thought that the whole idea behind this exercise was to move
> > the domain number into struct pci_host_bridge (Arnd did not do it with
> > his first set but this does not mean we can't add it as Bjorn suggested),
> > so that the domain number could be read from there straight away in an
> > arch (and FW) independent manner, right ?
> 
> The original issue was using _SEG call again instead of using
> the value from acpi_pci_root, and the solution for that problem
> is very simple.
> 
> The pci host bridge work is of course very useful, but creating a
> dependency with that work for an issue that can be so easily solved
> is unnecessary.

It can be easily solved if we do not drop patch 1 (I understood the
additional call to _SEG was only part of the problem). If we keep patch
1 the code above is fine by me, if we have to drop patch 1 (IIRC by
passing the parent pointer to pci_create_root_bus() we are affecting
IA64 and X86 code, if that's acceptable that's fine by me) I do not
think we can use the code above anymore, that's what my comment was
all about because Bjorn was concerned about the fragility of the code
setting the ACPI companion.

Lorenzo


From jonathanh at nvidia.com  Tue May  3 07:58:44 2016
From: jonathanh at nvidia.com (Jon Hunter)
Date: Tue, 3 May 2016 15:58:44 +0100
Subject: Tegra baseline test results for v4.6-rc6
Message-ID: <5728BCA4.6000201@nvidia.com>

Here are some basic Tegra test results for Linux v4.6-rc6.
Logs and other details at:

    https://nvtb.github.io//linux/test_v4.6-rc6/20160503073103/


Test summary
------------

Build: zImage:
    Pass: ( 2/ 2): multi_v7_defconfig, tegra_defconfig

Build: Image:
    Pass: ( 1/ 1): defconfig

Boot to userspace: defconfig:
    Pass: ( 3/ 3): qemu-vexpress64, tegra132-norrin,
		   tegra210-p2371-0000

Boot to userspace: multi_v7_defconfig:
    Pass: ( 4/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra20-trimslice, tegra30-beaver

Boot to userspace: tegra_defconfig:
    Pass: ( 4/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra20-trimslice, tegra30-beaver

PM: System suspend: multi_v7_defconfig:
    Pass: ( 4/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra20-trimslice, tegra30-beaver

PM: System suspend: tegra_defconfig:
    Pass: ( 4/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra20-trimslice, tegra30-beaver


vmlinux object size
(delta in bytes from test_v4.6-rc5 (02da2d72174c61988eb4456b53f405e3ebdebce4)):
   text     data      bss    total  kernel
      0        0        0        0  defconfig
   +136        0        0     +136  multi_v7_defconfig
   +568      +64        0     +632  tegra_defconfig


Boot-time memory difference
(delta in bytes from test_v4.6-rc5 (02da2d72174c61988eb4456b53f405e3ebdebce4))
    avail    rsrvd     high    freed                board              kconfig                  dtb
        .        .        .        .      qemu-vexpress64            defconfig           __internal
        .        .        .        . tegra114-dalmore-a04   multi_v7_defconfig     tegra114-dalmore
        .        .        .        . tegra114-dalmore-a04      tegra_defconfig     tegra114-dalmore
        .        .        .        .  tegra124-jetson-tk1   multi_v7_defconfig  tegra124-jetson-tk1
        .        .        .        .  tegra124-jetson-tk1      tegra_defconfig  tegra124-jetson-tk1
        .        .        .        .      tegra132-norrin            defconfig      tegra132-norrin
        .        .        .        .    tegra20-trimslice   multi_v7_defconfig    tegra20-trimslice
        .        .        .        .    tegra20-trimslice      tegra_defconfig    tegra20-trimslice
        .        .        .        .  tegra210-p2371-0000            defconfig  tegra210-p2371-0000
        .        .        .        .       tegra30-beaver   multi_v7_defconfig       tegra30-beaver
        .        .        .        .       tegra30-beaver      tegra_defconfig       tegra30-beaver


From christo.radev at gmail.com  Tue May  3 08:02:12 2016
From: christo.radev at gmail.com (christo.radev at gmail.com)
Date: Tue, 3 May 2016 08:02:12 -0700 (PDT)
Subject: [PATCH 1/1] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <20160503131437.GV17159@lukather>
References: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
 <f3da30a6-9ac0-4d5e-8611-ebb80cb3589e@googlegroups.com>
 <20160503131437.GV17159@lukather>
Message-ID: <66e4c452-1e34-474b-8973-2d57d9f036d0@googlegroups.com>

On Tuesday, May 3, 2016 at 4:14:41 PM UTC+3, Maxime Ripard wrote:
> Hi,
> 
> On Tue, May 03, 2016 at 4:12:06 PM UTC+3, Christo Radev wrote:
> > Hi to All,
> > 
> > I have already solved and tested this issue on Armbian build.  Find
> > patches for both legacy (3.4.111) and mainline (4.5.2) kernels on:
> > http://forum.armbian.com/index.php/topic/853-armbian-customization/page-2#entry7494
> > There it is also described how to do eMMC bootable and much more.
> > 
> > About the board - Olimex already sold all 3 kinds after migration to
> > their HW rev. E. One have to specify Lime2-eMMC as
> > A20-Olinuxino-Lime2-eMMC instead of their old 2 options
> > A20-Olinuxino-Lime2(-4GB).
> 
> Interesting, you have a link to that device?
> 
> Thanks,
> Maxime
> 
> -- 
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com

I have really 2 boards delivered by their local distributor.

Unfortunately, they do not update their site. Use the link for NAND option:
https://www.olimex.com/Products/OLinuXino/A20/A20-OLinuXIno-LIME2-4GB/open-source-hardware
There you can find Users Manual where it is described that eMMC option is available from HW rev. D. The schematic for HW rev. E is also available on their repository:
https://github.com/OLIMEX/OLINUXINO/tree/master/HARDWARE/A20-OLinuXino-LIME2

On the board both 4GB NAND and eMMC Flash chips can be placed alternatively on the same place. There is difference in some other components as well.

If one want to order it from the site probably has to order A20-Olinuxino-Lime2-4GB with note that eMMC option is required. The price is the same.

From arnd at arndb.de  Tue May  3 08:02:39 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 03 May 2016 17:02:39 +0200
Subject: next-20160503 build: 1 failures 12 warnings (next-20160503)
In-Reply-To: <20160503141723.GR6292@sirena.org.uk>
References: <E1axZpG-000664-AK@optimist> <20160503141723.GR6292@sirena.org.uk>
Message-ID: <2280495.M9rYajvqUJ@wuerfel>

On Tuesday 03 May 2016 15:17:23 Mark Brown wrote:
> On Tue, May 03, 2016 at 01:53:18PM +0100, Build bot for Mark Brown wrote:
> 
> Today's -next fails to build an ARM allmodconfig due to:
> 
> >       arm-allmodconfig
> > ../drivers/pinctrl/bcm/pinctrl-ns2-mux.c:540:17: error: 'pinctrl_utils_dt_free_map' undeclared here (not in a function)
> 
> caused by b5aa1006e4a93 (pinctrl: ns2: add pinmux driver support for
> Broadcom NS2 SoC) - presumably just a missing dependency.
> 

No, the function got renamed in another patch. I already prepared a fix
yesterday, but haven't gotten around to submit the patches for the last
two days, I'll try to send it out today, but it might end up being
tomorrow, or Linus could fix this one himself first.

	Arnd


From marc.zyngier at arm.com  Tue May  3 08:02:57 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 16:02:57 +0100
Subject: [PATCH v2 47/54] KVM: arm/arm64: vgic-new: vgic_init: implement
 kvm_vgic_hyp_init
In-Reply-To: <1461861973-26464-48-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-48-git-send-email-andre.przywara@arm.com>
Message-ID: <5728BDA1.7050002@arm.com>

On 28/04/16 17:46, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> Implements kvm_vgic_hyp_init and vgic_probe function.
> 
> The vgic_global struct is enriched with new fields populated
> by those functions.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - rename vgic_init.c to vgic-init.c
> 
>  include/kvm/vgic/vgic.h       |   1 +
>  virt/kvm/arm/vgic/vgic-init.c | 122 ++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v2.c   |  90 +++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c   |  74 +++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h      |   6 +++
>  5 files changed, 293 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-init.c
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index cfc3640..d144e3d 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -202,6 +202,7 @@ struct vgic_cpu {
>  };
>  
>  int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
> +int kvm_vgic_hyp_init(void);
>  
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  			bool level);
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> new file mode 100644
> index 0000000..d7c50bb
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -0,0 +1,122 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * 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/uaccess.h>
> +#include <linux/interrupt.h>
> +#include <linux/cpu.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/vgic/vgic.h>
> +#include <asm/kvm_mmu.h>
> +#include "vgic.h"
> +
> +/* GENERIC PROBE */
> +
> +static void vgic_init_maintenance_interrupt(void *info)
> +{
> +	enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0);
> +}
> +
> +static int vgic_cpu_notify(struct notifier_block *self,
> +			   unsigned long action, void *cpu)
> +{
> +	switch (action) {
> +	case CPU_STARTING:
> +	case CPU_STARTING_FROZEN:
> +		vgic_init_maintenance_interrupt(NULL);
> +		break;
> +	case CPU_DYING:
> +	case CPU_DYING_FROZEN:
> +		disable_percpu_irq(kvm_vgic_global_state.maint_irq);
> +		break;
> +	}
> +
> +	return NOTIFY_OK;
> +}
> +
> +static struct notifier_block vgic_cpu_nb = {
> +	.notifier_call = vgic_cpu_notify,
> +};
> +
> +static irqreturn_t vgic_maintenance_handler(int irq, void *data)
> +{
> +	/*
> +	 * We cannot rely on the vgic maintenance interrupt to be
> +	 * delivered synchronously. This means we can only use it to
> +	 * exit the VM, and we perform the handling of EOIed
> +	 * interrupts on the exit path (see vgic_process_maintenance).
> +	 */
> +	return IRQ_HANDLED;
> +}
> +
> +static const struct of_device_id vgic_ids[] = {
> +	{ .compatible = "arm,cortex-a15-gic",	.data = vgic_v2_probe, },
> +	{ .compatible = "arm,cortex-a7-gic",	.data = vgic_v2_probe, },
> +	{ .compatible = "arm,gic-400",		.data = vgic_v2_probe, },
> +	{ .compatible = "arm,gic-v3",		.data = vgic_v3_probe, },
> +	{},
> +};
> +
> +/**
> + * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable
> + * according to the host GIC model. Accordingly calls either
> + * vgic_v2/v3_probe which registers the KVM_DEVICE that can be
> + * instantiated by a guest later on .
> + */
> +int kvm_vgic_hyp_init(void)
> +{
> +	const struct of_device_id *matched_id;
> +	const int (*vgic_probe)(struct device_node *);
> +	struct device_node *vgic_node;
> +	int ret;
> +
> +	vgic_node = of_find_matching_node_and_match(NULL,
> +						    vgic_ids, &matched_id);
> +	if (!vgic_node) {
> +		kvm_err("error: no compatible GIC node found\n");
> +		return -ENODEV;
> +	}
> +
> +	vgic_probe = matched_id->data;
> +	ret = vgic_probe(vgic_node);
> +	if (ret)
> +		return ret;
> +
> +	ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
> +				 vgic_maintenance_handler,
> +				 "vgic", kvm_get_running_vcpus());
> +	if (ret) {
> +		kvm_err("Cannot register interrupt %d\n",
> +			kvm_vgic_global_state.maint_irq);
> +		return ret;
> +	}
> +
> +	ret = __register_cpu_notifier(&vgic_cpu_nb);
> +	if (ret) {
> +		kvm_err("Cannot register vgic CPU notifier\n");
> +		goto out_free_irq;
> +	}
> +
> +	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
> +
> +	return 0;
> +
> +out_free_irq:
> +	free_percpu_irq(kvm_vgic_global_state.maint_irq,
> +			kvm_get_running_vcpus());
> +	return ret;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> index 70cac63..00dc166 100644
> --- a/virt/kvm/arm/vgic/vgic-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -17,6 +17,11 @@
>  #include <linux/irqchip/arm-gic.h>
>  #include <linux/kvm.h>
>  #include <linux/kvm_host.h>
> +#include <kvm/vgic/vgic.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <asm/kvm_mmu.h>
>  
>  #include "vgic.h"
>  
> @@ -205,3 +210,88 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>  	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
>  			GICH_VMCR_PRIMASK_SHIFT;
>  }
> +
> +/**
> + * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
> + * @node:	pointer to the DT node
> + *
> + * Returns 0 if a GICv2 has been found, returns an error code otherwise
> + */
> +int vgic_v2_probe(struct device_node *vgic_node)
> +{
> +	int ret;
> +	struct resource vctrl_res;
> +	struct resource vcpu_res;
> +
> +	kvm_vgic_global_state.maint_irq = irq_of_parse_and_map(vgic_node, 0);
> +	if (!kvm_vgic_global_state.maint_irq) {
> +		kvm_err("error getting vgic maintenance irq from DT\n");
> +		ret = -ENXIO;
> +		goto out;
> +	}
> +
> +	ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
> +	if (ret) {
> +		kvm_err("Cannot obtain GICH resource\n");
> +		goto out;
> +	}
> +
> +	kvm_vgic_global_state.vctrl_base = of_iomap(vgic_node, 2);
> +	if (!kvm_vgic_global_state.vctrl_base) {
> +		kvm_err("Cannot ioremap GICH\n");
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	kvm_vgic_global_state.nr_lr =
> +		readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
> +	kvm_vgic_global_state.nr_lr = (kvm_vgic_global_state.nr_lr & 0x3f) + 1;
> +
> +	ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
> +				     kvm_vgic_global_state.vctrl_base +
> +					 resource_size(&vctrl_res),
> +				     vctrl_res.start);
> +	if (ret) {
> +		kvm_err("Cannot map VCTRL into hyp\n");
> +		goto out_unmap;
> +	}
> +
> +	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
> +		kvm_err("Cannot obtain GICV resource\n");
> +		ret = -ENXIO;
> +		goto out_unmap;
> +	}
> +
> +	if (!PAGE_ALIGNED(vcpu_res.start)) {
> +		kvm_err("GICV physical address 0x%llx not page aligned\n",
> +			(unsigned long long)vcpu_res.start);
> +		ret = -ENXIO;
> +		goto out_unmap;
> +	}
> +
> +	if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
> +		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
> +			(unsigned long long)resource_size(&vcpu_res),
> +			PAGE_SIZE);
> +		ret = -ENXIO;
> +		goto out_unmap;
> +	}
> +
> +	kvm_vgic_global_state.can_emulate_gicv2 = true;
> +	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
> +
> +	kvm_vgic_global_state.vcpu_base = vcpu_res.start;
> +
> +	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
> +		 vctrl_res.start, kvm_vgic_global_state.maint_irq);
> +
> +	kvm_vgic_global_state.type = VGIC_V2;
> +	kvm_vgic_global_state.max_gic_vcpus = VGIC_V2_MAX_CPUS;
> +	goto out;
> +
> +out_unmap:
> +	iounmap(kvm_vgic_global_state.vctrl_base);
> +out:
> +	of_node_put(vgic_node);
> +	return ret;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 2c55bd5..a2026c2 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -16,9 +16,17 @@
>  #include <linux/kvm.h>
>  #include <linux/kvm_host.h>
>  #include <linux/irqchip/arm-gic.h>
> +#include <kvm/vgic/vgic.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <asm/kvm_mmu.h>
> +#include <asm/kvm_asm.h>
>  
>  #include "vgic.h"
>  
> +static u32 ich_vtr_el2;
> +

This can be dropped...

>  void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
>  {
>  	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
> @@ -189,3 +197,69 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>  	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
>  	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
>  }
> +
> +/**
> + * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
> + * @node:	pointer to the DT node
> + *
> + * Returns 0 if a GICv3 has been found, returns an error code otherwise
> + */
> +int vgic_v3_probe(struct device_node *vgic_node)
> +{
> +	int ret = 0;
> +	u32 gicv_idx;
> +	struct resource vcpu_res;

and defined here (no need for a global variable anymore now that we have
a global state).

> +
> +	kvm_vgic_global_state.maint_irq = irq_of_parse_and_map(vgic_node, 0);
> +	if (!kvm_vgic_global_state.maint_irq) {
> +		kvm_err("error getting vgic maintenance irq from DT\n");
> +		ret = -ENXIO;
> +		goto out;
> +	}
> +
> +	ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
> +
> +	/*
> +	 * The ListRegs field is 5 bits, but there is a architectural
> +	 * maximum of 16 list registers. Just ignore bit 4...
> +	 */
> +	kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
> +	kvm_vgic_global_state.can_emulate_gicv2 = false;
> +
> +	if (of_property_read_u32(vgic_node, "#redistributor-regions",
> +				 &gicv_idx))
> +		gicv_idx = 1;
> +
> +	gicv_idx += 3; /* Also skip GICD, GICC, GICH */
> +	if (of_address_to_resource(vgic_node, gicv_idx, &vcpu_res)) {
> +		kvm_info("GICv3: no GICV resource entry\n");
> +		kvm_vgic_global_state.vcpu_base = 0;
> +	} else if (!PAGE_ALIGNED(vcpu_res.start)) {
> +		pr_warn("GICV physical address 0x%llx not page aligned\n",
> +			(unsigned long long)vcpu_res.start);
> +		kvm_vgic_global_state.vcpu_base = 0;
> +	} else if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
> +		pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
> +			(unsigned long long)resource_size(&vcpu_res),
> +			PAGE_SIZE);
> +		kvm_vgic_global_state.vcpu_base = 0;
> +	} else {
> +		kvm_vgic_global_state.vcpu_base = vcpu_res.start;
> +		kvm_vgic_global_state.can_emulate_gicv2 = true;
> +		kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
> +	}
> +	if (kvm_vgic_global_state.vcpu_base == 0)
> +		kvm_info("disabling GICv2 emulation\n");
> +	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V3);
> +
> +	kvm_vgic_global_state.vctrl_base = NULL;
> +	kvm_vgic_global_state.type = VGIC_V3;
> +	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
> +
> +	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
> +		 vcpu_res.start, kvm_vgic_global_state.maint_irq);
> +
> +out:
> +	of_node_put(vgic_node);
> +	return ret;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index ea72f32..d6fe7b4 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -41,6 +41,7 @@ int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
>  void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +int vgic_v2_probe(struct device_node *vgic_node);
>  
>  #ifdef CONFIG_KVM_ARM_VGIC_V3
>  void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
> @@ -50,6 +51,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
>  void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +int vgic_v3_probe(struct device_node *vgic_node);
>  #else
>  static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
>  {
> @@ -82,6 +84,10 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
>  {
>  }
>  
> +static inline int vgic_v3_probe(struct device_node *vgic_node)
> +{
> +	return -ENODEV;
> +}
>  #endif
>  
>  void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> 

Depending on the merge order with Julien's series, it could be worth
squashing my rework into this patch.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From timur at codeaurora.org  Tue May  3 08:04:59 2016
From: timur at codeaurora.org (Timur Tabi)
Date: Tue, 3 May 2016 10:04:59 -0500
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <5728B9BF.8050501@roeck-us.net>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <57289594.3050801@codeaurora.org> <20160503132439.GC13045@dhcppc6.redhat.com>
 <5728ABE0.5040000@roeck-us.net> <20160503141717.GD13045@dhcppc6.redhat.com>
 <5728B9BF.8050501@roeck-us.net>
Message-ID: <5728BE1B.5010904@codeaurora.org>

Guenter Roeck wrote:
>> Most likely it will not be corrupted. But, if ISR has been called it
>> means
>> something went wrong, and watchdog was not kicked for the time
>> programmed as
>> "timeout". So, probably we should be extra careful.
>>
> This logic would apply to _every_ watchdog driver implementing interrupts.
> Actually, it would apply to _all_ kernel code, and the logic could be used
> to introduce hyper-defensive programming all over the place, bloat the
> kernel
> and ultimately make it all but unusable. I do not believe in such
> programming
> in an operating system kernel.
>
> On top of that, the assumption that the kernel would be still sane enough
> to call the interrupt handler, but not sane enough to actually execute it,
> seems to be a bit far-fetched.

Agreed.  Pratyush, have you ever seen any watchdog register get 
corrupted, like you describe?  It just seems like you're imagining a 
problem that has never occurred.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum, a Linux Foundation collaborative project.


From timur at codeaurora.org  Tue May  3 08:07:48 2016
From: timur at codeaurora.org (Timur Tabi)
Date: Tue, 3 May 2016 10:07:48 -0500
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <20160503143856.GE13045@dhcppc6.redhat.com>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <5728A7C3.4010001@roeck-us.net> <20160503143856.GE13045@dhcppc6.redhat.com>
Message-ID: <5728BEC4.6050603@codeaurora.org>

Pratyush Anand wrote:
> In fact after supporting max_hw_heartbeat_ms, there should be no change for
> action=0 functionally. However, we would still need some changes for action=1.

IMHO, action=1 is more of a debugging option, and not something that 
would be used normally.  I would need to see some evidence that real 
users want to have action=1 and a longer timeout.

I've never been a fan of the action=1 option, and I'm certainly not keen 
any patches that make action=1 more complicated than it already is.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum, a Linux Foundation collaborative project.


From arnd at arndb.de  Tue May  3 08:16:19 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue,  3 May 2016 17:16:19 +0200
Subject: [PATCH 0/3] HSI: omap-ssi: regressions against yesterday's linux-next
Message-ID: <1462288586-584690-1-git-send-email-arnd@arndb.de>

Hi Sebastian,

One patch you added yesterday unfortunately caused (at least) three
separate build problems with 32-bit ARM randconfig builds.

These three patches should make it all work again.

        Arnd




From arnd at arndb.de  Tue May  3 08:16:20 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue,  3 May 2016 17:16:20 +0200
Subject: [PATCH 1/3] HSI: omap-ssi: add COMMON_CLK dependency
In-Reply-To: <1462288586-584690-1-git-send-email-arnd@arndb.de>
References: <1462288586-584690-1-git-send-email-arnd@arndb.de>
Message-ID: <1462288586-584690-2-git-send-email-arnd@arndb.de>

Enabling the omap ssi driver without COMMON_CLK results in a build failure:

drivers/hsi/controllers/omap_ssi_core.c: In function 'ssi_clk_event':
drivers/hsi/controllers/omap_ssi_core.c:304:7: error: 'PRE_RATE_CHANGE' undeclared (first use in this function)

This adds a Kconfig dependency to avoid the invalid configuration.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 4bcf7414528a ("HSI: omap-ssi: add clk change support")
---
 drivers/hsi/controllers/Kconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/hsi/controllers/Kconfig b/drivers/hsi/controllers/Kconfig
index 084ec97eec64..48e4eda186cc 100644
--- a/drivers/hsi/controllers/Kconfig
+++ b/drivers/hsi/controllers/Kconfig
@@ -5,7 +5,8 @@ comment "HSI controllers"
 
 config OMAP_SSI
 	tristate "OMAP SSI hardware driver"
-	depends on HSI && OF && (ARCH_OMAP3 || (ARM && COMPILE_TEST))
+	depends on HSI && OF && ARM && COMMON_CLK
+	depends on ARCH_OMAP3 || COMPILE_TEST
 	---help---
 	  SSI is a legacy version of HSI. It is usually used to connect
 	  an application engine with a cellular modem.
-- 
2.7.0



From arnd at arndb.de  Tue May  3 08:16:21 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue,  3 May 2016 17:16:21 +0200
Subject: [PATCH 2/3] HSI: omap-ssi: include pinctrl header files
In-Reply-To: <1462288586-584690-1-git-send-email-arnd@arndb.de>
References: <1462288586-584690-1-git-send-email-arnd@arndb.de>
Message-ID: <1462288586-584690-3-git-send-email-arnd@arndb.de>

The driver now uses some pinctrl functions, but fails
to build if PINCTRL is disabled because the respective
header files are only included indirectly:

drivers/hsi/controllers/omap_ssi_core.c: In function 'ssi_clk_event':
drivers/hsi/controllers/omap_ssi_core.c:317:4: error: implicit declaration of function 'pinctrl_pm_select_idle_state' [-Werror=implicit-function-declaration]
drivers/hsi/controllers/omap_ssi_core.c:339:4: error: implicit declaration of function 'pinctrl_pm_select_default_state' [-Werror=implicit-function-declaration]
drivers/hsi/controllers/omap_ssi_port.c: In function 'ssi_flush':
drivers/hsi/controllers/omap_ssi_port.c:520:2: error: implicit declaration of function 'pinctrl_pm_select_idle_state' [-Werror=implicit-function-declaration]

This includes the headers from the files that call the functions,
which works even if pinctrl is turned off.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 4bcf7414528a ("HSI: omap-ssi: add clk change support")
---
 drivers/hsi/controllers/omap_ssi_core.c | 1 +
 drivers/hsi/controllers/omap_ssi_port.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c
index 15b2a600d77b..a3e0febfb64a 100644
--- a/drivers/hsi/controllers/omap_ssi_core.c
+++ b/drivers/hsi/controllers/omap_ssi_core.c
@@ -35,6 +35,7 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/debugfs.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/of_platform.h>
 #include <linux/hsi/hsi.h>
diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c
index 98b22e88085c..ca7139eaaa1d 100644
--- a/drivers/hsi/controllers/omap_ssi_port.c
+++ b/drivers/hsi/controllers/omap_ssi_port.c
@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 
 #include <linux/gpio/consumer.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/debugfs.h>
 
 #include "omap_ssi_regs.h"
-- 
2.7.0



From arnd at arndb.de  Tue May  3 08:16:22 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue,  3 May 2016 17:16:22 +0200
Subject: [PATCH 3/3] HSI: omap-ssi: move omap_ssi_port_update_fclk
In-Reply-To: <1462288586-584690-1-git-send-email-arnd@arndb.de>
References: <1462288586-584690-1-git-send-email-arnd@arndb.de>
Message-ID: <1462288586-584690-4-git-send-email-arnd@arndb.de>

After the clk change support, the ssi omap ssi core driver
now calls into the port driver to change fclk. This function
was previously inside of an #ifdef, because it was only used
when CONFIG_PM is enabled. Now it also gets used without
power management support:

drivers/hsi/built-in.o: In function `ssi_clk_event':
omap_ssi_port.c:(.text+0x1bf8): undefined reference to `omap_ssi_port_update_fclk'

This moves the function outside of the CONFIG_PM guard.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 4bcf7414528a ("HSI: omap-ssi: add clk change support")
---
 drivers/hsi/controllers/omap_ssi_port.c | 35 ++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c
index ca7139eaaa1d..6b8f7739768a 100644
--- a/drivers/hsi/controllers/omap_ssi_port.c
+++ b/drivers/hsi/controllers/omap_ssi_port.c
@@ -1253,6 +1253,23 @@ static int ssi_port_remove(struct platform_device *pd)
 	return 0;
 }
 
+static int ssi_restore_divisor(struct omap_ssi_port *omap_port)
+{
+	writel_relaxed(omap_port->sst.divisor,
+				omap_port->sst_base + SSI_SST_DIVISOR_REG);
+
+	return 0;
+}
+
+void omap_ssi_port_update_fclk(struct hsi_controller *ssi,
+			       struct omap_ssi_port *omap_port)
+{
+	/* update divisor */
+	u32 div = ssi_calculate_div(ssi);
+	omap_port->sst.divisor = div;
+	ssi_restore_divisor(omap_port);
+}
+
 #ifdef CONFIG_PM
 static int ssi_save_port_ctx(struct omap_ssi_port *omap_port)
 {
@@ -1305,24 +1322,6 @@ static int ssi_restore_port_mode(struct omap_ssi_port *omap_port)
 	return 0;
 }
 
-static int ssi_restore_divisor(struct omap_ssi_port *omap_port)
-{
-	writel_relaxed(omap_port->sst.divisor,
-				omap_port->sst_base + SSI_SST_DIVISOR_REG);
-
-	return 0;
-}
-
-void omap_ssi_port_update_fclk(struct hsi_controller *ssi,
-			       struct omap_ssi_port *omap_port)
-{
-	/* update divisor */
-	u32 div = ssi_calculate_div(ssi);
-	omap_port->sst.divisor = div;
-	ssi_restore_divisor(omap_port);
-}
-EXPORT_SYMBOL_GPL(omap_ssi_port_update_fclk);
-
 static int omap_ssi_port_runtime_suspend(struct device *dev)
 {
 	struct hsi_port *port = dev_get_drvdata(dev);
-- 
2.7.0



From arnd at arndb.de  Tue May  3 08:23:28 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue,  3 May 2016 17:23:28 +0200
Subject: [PATCH] drm: sun4i: print DMA address correctly
Message-ID: <1462289020-774976-1-git-send-email-arnd@arndb.de>

The newly added sun4i drm driver prints a dma address using the %x
format string, which cannot work when dma_addr_t is 64 bit,
and gcc warns about this configuration:

drm/sun4i/sun4i_backend.c: In function 'sun4i_backend_update_layer_buffer':
drm/sun4i/sun4i_backend.c:193:84: error: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'dma_addr_t {aka long long unsigned int}' [-Werror=format=]
  DRM_DEBUG_DRIVER("Using GEM @ 0x%x\n", gem->paddr);
drm/sun4i/sun4i_backend.c:201:84: error: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'dma_addr_t {aka long long unsigned int}' [-Werror=format=]
  DRM_DEBUG_DRIVER("Setting buffer address to 0x%x\n", paddr);

This changes the code to use the explicit %pad format string, which
always prints the right length.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/gpu/drm/sun4i/sun4i_backend.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index f7a15c1a93bf..3ab560450a82 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -190,7 +190,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
 	/* Get the physical address of the buffer in memory */
 	gem = drm_fb_cma_get_gem_obj(fb, 0);
 
-	DRM_DEBUG_DRIVER("Using GEM @ 0x%x\n", gem->paddr);
+	DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
 
 	/* Compute the start of the displayed memory */
 	bpp = drm_format_plane_cpp(fb->pixel_format, 0);
@@ -198,7 +198,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
 	paddr += (state->src_x >> 16) * bpp;
 	paddr += (state->src_y >> 16) * fb->pitches[0];
 
-	DRM_DEBUG_DRIVER("Setting buffer address to 0x%x\n", paddr);
+	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
 
 	/* Write the 32 lower bits of the address (in bits) */
 	lo_paddr = paddr << 3;
-- 
2.7.0



From arnd at arndb.de  Tue May  3 08:26:53 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue,  3 May 2016 17:26:53 +0200
Subject: [PATCH 1/2] pinctrl: nomadik: hide nmk_gpio_get_mode when unused
Message-ID: <1462289221-861102-1-git-send-email-arnd@arndb.de>

nmk_gpio_get_mode is only used in one place, and that is conditionally
compiled if DEBUG_FS is enabled. A recent cleanup has marked the
definition 'static', which now leads to a warning:

drivers/pinctrl/nomadik/pinctrl-nomadik.c:614:12: error: 'nmk_gpio_get_mode' defined but not used [-Werror=unused-function]
 static int nmk_gpio_get_mode(struct nmk_gpio_chip *nmk_chip, int offset)
            ^~~~~~~~~~~~~~~~~

Moving the function itself inside the #ifdef shuts it up again.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 5e81e0a0913c ("pinctrl: nomadik: use BIT() with offsets consequently")
---
 drivers/pinctrl/nomadik/pinctrl-nomadik.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
index e5c71acd9506..ccbfc325c778 100644
--- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
@@ -611,20 +611,6 @@ static int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev,
 	return NMK_GPIO_ALT_C;
 }
 
-static int nmk_gpio_get_mode(struct nmk_gpio_chip *nmk_chip, int offset)
-{
-	u32 afunc, bfunc;
-
-	clk_enable(nmk_chip->clk);
-
-	afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & BIT(offset);
-	bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & BIT(offset);
-
-	clk_disable(nmk_chip->clk);
-
-	return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
-}
-
 /* IRQ functions */
 
 static void nmk_gpio_irq_ack(struct irq_data *d)
@@ -929,6 +915,19 @@ static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
 }
 
 #ifdef CONFIG_DEBUG_FS
+static int nmk_gpio_get_mode(struct nmk_gpio_chip *nmk_chip, int offset)
+{
+	u32 afunc, bfunc;
+
+	clk_enable(nmk_chip->clk);
+
+	afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & BIT(offset);
+	bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & BIT(offset);
+
+	clk_disable(nmk_chip->clk);
+
+	return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
+}
 
 #include <linux/seq_file.h>
 
-- 
2.7.0



From marc.zyngier at arm.com  Tue May  3 08:32:51 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 16:32:51 +0100
Subject: [PATCH v2 21/54] KVM: arm/arm64: vgic-new: Add GICv2 MMIO
 handling framework
In-Reply-To: <1461861973-26464-22-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-22-git-send-email-andre.przywara@arm.com>
Message-ID: <5728C4A3.10708@arm.com>

On 28/04/16 17:45, Andre Przywara wrote:
> Create vgic-mmio-v2.c to describe GICv2 emulation specific handlers
> using the initializer macros provided by the VGIC MMIO framework.
> Provide a function to register the GICv2 distributor registers to
> the kvm_io_bus framework.
> The actual handler functions are still stubs in this patch.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
> Changelog v1 .. v2:
> - new patch, split out from the generic MMIO framework patch
> - use a separate file to hold GICv2 emulation specific handlers
> - replace _nyi stub functions with raz/wi versions
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.c    | 26 +++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h    |  2 ++
>  3 files changed, 90 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v2.c
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> new file mode 100644
> index 0000000..afee778
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -0,0 +1,62 @@
> +/*
> + * VGICv2 MMIO handling functions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/irqchip/arm-gic.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/iodev.h>
> +#include <kvm/vgic/vgic.h>

Please use kvm/arm_vgic.h so that it doesn't break once we rename
kvm/vgic/vgic.h.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From marc.zyngier at arm.com  Tue May  3 08:34:32 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 16:34:32 +0100
Subject: [PATCH v2 32/54] KVM: arm/arm64: vgic-new: Add GICv3 MMIO
 handling framework
In-Reply-To: <1461861973-26464-33-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-33-git-send-email-andre.przywara@arm.com>
Message-ID: <5728C508.7060406@arm.com>

On 28/04/16 17:45, Andre Przywara wrote:
> Create a new file called vgic-mmio-v3.c and describe the GICv3
> distributor and redistributor registers there.
> This adds a special macro to deal with the split of SGI/PPI in the
> redistributor and SPIs in the distributor, which allows us to reuse
> the existing GICv2 handlers for those registers which are compatible.
> Also we provide a function to deal with the registration of the two
> separate redistributor frames per VCPU.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - adapt to new MMIO registration approach:
>   register one device for the distributor and two for each VCPU
> - implement special handling for private interrupts
> - remove empty stub functions
> - make IGROUPR return RAO
> 
> Changelog v1 .. v2:
> - adapt to new framework, introduce vgic-mmio-v3.c
> - remove userland register access functions (for now)
> - precompute .len when describing a VGIC register
> - add missed pointer incrementation on registering redist regions
> - replace _nyi stub functions with raz/wi versions
> 
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
>  virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
>  virt/kvm/arm/vgic/vgic.h         |   3 +
>  4 files changed, 201 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> new file mode 100644
> index 0000000..c6765d4
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -0,0 +1,191 @@
> +/*
> + * VGICv3 MMIO handling functions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/irqchip/arm-gic-v3.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/iodev.h>
> +#include <kvm/vgic/vgic.h>

Same remark about the use of this include file instead of kvm/arm_vgic.h.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From marc.zyngier at arm.com  Tue May  3 08:35:49 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 16:35:49 +0100
Subject: [PATCH v2 47/54] KVM: arm/arm64: vgic-new: vgic_init: implement
 kvm_vgic_hyp_init
In-Reply-To: <1461861973-26464-48-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-48-git-send-email-andre.przywara@arm.com>
Message-ID: <5728C555.3080008@arm.com>

On 28/04/16 17:46, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> Implements kvm_vgic_hyp_init and vgic_probe function.
> 
> The vgic_global struct is enriched with new fields populated
> by those functions.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - rename vgic_init.c to vgic-init.c
> 
>  include/kvm/vgic/vgic.h       |   1 +
>  virt/kvm/arm/vgic/vgic-init.c | 122 ++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v2.c   |  90 +++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c   |  74 +++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h      |   6 +++
>  5 files changed, 293 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-init.c
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index cfc3640..d144e3d 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -202,6 +202,7 @@ struct vgic_cpu {
>  };
>  
>  int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
> +int kvm_vgic_hyp_init(void);
>  
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  			bool level);
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> new file mode 100644
> index 0000000..d7c50bb
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -0,0 +1,122 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * 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/uaccess.h>
> +#include <linux/interrupt.h>
> +#include <linux/cpu.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/vgic/vgic.h>

Same issue here as well.

	M.
-- 
Jazz is not dead. It just smells funny...


From robh at kernel.org  Tue May  3 08:37:19 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 3 May 2016 10:37:19 -0500
Subject: [PATCH] ARM: dts: imx: Remove unneeded unit-addresses
In-Reply-To: <1462283851-10820-1-git-send-email-fabio.estevam@nxp.com>
References: <1462283851-10820-1-git-send-email-fabio.estevam@nxp.com>
Message-ID: <CAL_JsqKv_7ufFG7DSkxqp9QOEjLEDVofyYMoudtJjqBA78ahcA@mail.gmail.com>

On Tue, May 3, 2016 at 8:57 AM, Fabio Estevam <fabio.estevam at nxp.com> wrote:
> Building with W=1 option leads to several warnings like:
>
> Warning (unit_address_vs_reg): Node /soc/aips-bus at 02000000/anatop at 020c8000/regulator-1p1 at 110 has a unit name, but no reg property
>
> Fix them by removing the unneeded unit-addresses.
>
> Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
> ---
>  arch/arm/boot/dts/imx6sl.dtsi | 12 ++++++------
>  arch/arm/boot/dts/imx6sx.dtsi | 12 ++++++------
>  arch/arm/boot/dts/imx6ul.dtsi |  6 +++---
>  arch/arm/boot/dts/imx7d.dtsi  |  2 +-
>  4 files changed, 16 insertions(+), 16 deletions(-)
>
> diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
> index d12b250..224c0d0 100644
> --- a/arch/arm/boot/dts/imx6sl.dtsi
> +++ b/arch/arm/boot/dts/imx6sl.dtsi
> @@ -461,7 +461,7 @@
>                                              <0 54 IRQ_TYPE_LEVEL_HIGH>,
>                                              <0 127 IRQ_TYPE_LEVEL_HIGH>;
>
> -                               regulator-1p1 at 110 {
> +                               regulator-1p1 {

Presumably these are register offsets which could be useful to have
even if the Linux driver doesn't use them. But either way is fine with
me.

Rob


From festevam at gmail.com  Tue May  3 08:42:50 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Tue, 3 May 2016 12:42:50 -0300
Subject: [PATCH] ARM: dts: imx: Remove unneeded unit-addresses
In-Reply-To: <CAL_JsqKv_7ufFG7DSkxqp9QOEjLEDVofyYMoudtJjqBA78ahcA@mail.gmail.com>
References: <1462283851-10820-1-git-send-email-fabio.estevam@nxp.com>
 <CAL_JsqKv_7ufFG7DSkxqp9QOEjLEDVofyYMoudtJjqBA78ahcA@mail.gmail.com>
Message-ID: <CAOMZO5AO15UmNJARS9aL-U=CjYnUq0D9S38NYHC8w2DLwOeR_A@mail.gmail.com>

On Tue, May 3, 2016 at 12:37 PM, Rob Herring <robh at kernel.org> wrote:

> Presumably these are register offsets which could be useful to have
> even if the Linux driver doesn't use them. But either way is fine with
> me.

Yes, these are register offsets.

                reg_3p0: regulator-3p0 {
                    compatible = "fsl,anatop-regulator";
                    regulator-name = "vdd3p0";
                    regulator-min-microvolt = <2625000>;
                    regulator-max-microvolt = <3400000>;
                    anatop-reg-offset = <0x120>;


From festevam at gmail.com  Tue May  3 08:45:07 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Tue, 3 May 2016 12:45:07 -0300
Subject: [PATCH] ARM: dts: imx: Remove unneeded unit-addresses
In-Reply-To: <CAOMZO5AO15UmNJARS9aL-U=CjYnUq0D9S38NYHC8w2DLwOeR_A@mail.gmail.com>
References: <1462283851-10820-1-git-send-email-fabio.estevam@nxp.com>
 <CAL_JsqKv_7ufFG7DSkxqp9QOEjLEDVofyYMoudtJjqBA78ahcA@mail.gmail.com>
 <CAOMZO5AO15UmNJARS9aL-U=CjYnUq0D9S38NYHC8w2DLwOeR_A@mail.gmail.com>
Message-ID: <CAOMZO5BXFL47p=WTPDDRFGq38yktmB1FnbOTWJ37mrWsKkeUSQ@mail.gmail.com>

On Tue, May 3, 2016 at 12:42 PM, Fabio Estevam <festevam at gmail.com> wrote:
> On Tue, May 3, 2016 at 12:37 PM, Rob Herring <robh at kernel.org> wrote:
>
>> Presumably these are register offsets which could be useful to have
>> even if the Linux driver doesn't use them. But either way is fine with
>> me.
>
> Yes, these are register offsets.
>
>                 reg_3p0: regulator-3p0 {
>                     compatible = "fsl,anatop-regulator";
>                     regulator-name = "vdd3p0";
>                     regulator-min-microvolt = <2625000>;
>                     regulator-max-microvolt = <3400000>;
>                     anatop-reg-offset = <0x120>;

Sorry, pressed the 'send' button too quickly.

There is a "anatop-reg-offset = <0x120>;" property that is used to
pass the offset to the anatop regulator driver, so that's why I
preferred to remove the unneeded unit-address.

Thanks


From arnaud.pouliquen at st.com  Tue May  3 08:46:00 2016
From: arnaud.pouliquen at st.com (Arnaud Pouliquen)
Date: Tue, 3 May 2016 17:46:00 +0200
Subject: [PATCH 09/18] ASoC: sti: Update DT example to match the driver
 code
In-Reply-To: <20160426110229.GA5374@griffinp-ThinkPad-X1-Carbon-2nd>
References: <1461236675-10176-1-git-send-email-peter.griffin@linaro.org>
 <1461236675-10176-10-git-send-email-peter.griffin@linaro.org>
 <20160421155753.GS3217@sirena.org.uk>
 <20160426110229.GA5374@griffinp-ThinkPad-X1-Carbon-2nd>
Message-ID: <5728C7B8.5050903@st.com>



On 04/26/2016 01:02 PM, Peter Griffin wrote:
> Hi Mark,
> 
> On Thu, 21 Apr 2016, Mark Brown wrote:
> 
>> On Thu, Apr 21, 2016 at 12:04:26PM +0100, Peter Griffin wrote:
>>> uniperiph-id, version and mode are ST specific bindings and
>>> need the 'st,' prefix. Update the examples, as otherwise copying
>>> them yields a runtime error parsing the DT node.
>>
>> I'm not sure what connection this or the other ASoC documentation update
>> have to the rest of the series?
> 
> The ASoC DT bindings are missing upstream as the ASoC driver depends on the
> fdma driver. So this series adds the fdma driver, fdma dt bindings,
> and also the missing ASoC dt bindings.
> 
> Whilst doing this and getting it working I noticed a few discrepencies
> in the ASoC dt binding documentation versus the driver so also fixed that.
> 
> Once this whole series is applied the end result is working
> audio upstream for STi platforms (as ASoC is the only upstream driver
> using fdma currently).

Hi Peter,
I also noticed the error in bindings, i'm planning to correct it with
DTS upstream for STI ASoC after FDMA has been accepted.
So if you estimate that it is simplier for FDMA upstream, you can drop
ASoC patches in you next version.

Regards,
Arnaud




From panand at redhat.com  Tue May  3 08:51:41 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 3 May 2016 21:21:41 +0530
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <5728BEC4.6050603@codeaurora.org>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <5728A7C3.4010001@roeck-us.net>
 <20160503143856.GE13045@dhcppc6.redhat.com>
 <5728BEC4.6050603@codeaurora.org>
Message-ID: <20160503155141.GF13045@dhcppc6.redhat.com>

On 03/05/2016:10:07:48 AM, Timur Tabi wrote:
> Pratyush Anand wrote:
> >In fact after supporting max_hw_heartbeat_ms, there should be no change for
> >action=0 functionally. However, we would still need some changes for action=1.
> 
> IMHO, action=1 is more of a debugging option, and not something that would
> be used normally.  I would need to see some evidence that real users want to
> have action=1 and a longer timeout.
> 
If action=1 need to be used effectively, then we should have something which
would help to increase timeout values.

Currently you have only 10 second to execute secondary kernel, which might not
be sufficient.

> I've never been a fan of the action=1 option, and I'm certainly not keen any
> patches that make action=1 more complicated than it already is.

I think, with max_hw_heartbeat_ms it would be far more simpler. Will attempt and
send another RFC.

~Pratyush


From oliver at schinagl.nl  Tue May  3 08:52:09 2016
From: oliver at schinagl.nl (Olliver Schinagl)
Date: Tue, 3 May 2016 17:52:09 +0200
Subject: [PATCH 1/1] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <66e4c452-1e34-474b-8973-2d57d9f036d0@googlegroups.com>
References: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
 <f3da30a6-9ac0-4d5e-8611-ebb80cb3589e@googlegroups.com>
 <20160503131437.GV17159@lukather>
 <66e4c452-1e34-474b-8973-2d57d9f036d0@googlegroups.com>
Message-ID: <5728C929.3040709@schinagl.nl>

Hey all,

On 03-05-16 17:02, christo.radev at gmail.com wrote:
> On Tuesday, May 3, 2016 at 4:14:41 PM UTC+3, Maxime Ripard wrote:
>> Hi,
>>
>> On Tue, May 03, 2016 at 4:12:06 PM UTC+3, Christo Radev wrote:
>>> Hi to All,
>>>
>>> I have already solved and tested this issue on Armbian build.  Find
>>> patches for both legacy (3.4.111) and mainline (4.5.2) kernels on:
>>> http://forum.armbian.com/index.php/topic/853-armbian-customization/page-2#entry7494
>>> There it is also described how to do eMMC bootable and much more.
>>>
>>> About the board - Olimex already sold all 3 kinds after migration to
>>> their HW rev. E. One have to specify Lime2-eMMC as
>>> A20-Olinuxino-Lime2-eMMC instead of their old 2 options
>>> A20-Olinuxino-Lime2(-4GB).
>> Interesting, you have a link to that device?
>>
>> Thanks,
>> Maxime
>>
>> -- 
>> Maxime Ripard, Free Electrons
>> Embedded Linux, Kernel and Android engineering
>> http://free-electrons.com
> I have really 2 boards delivered by their local distributor.
>
> Unfortunately, they do not update their site. Use the link for NAND option:
> https://www.olimex.com/Products/OLinuXino/A20/A20-OLinuXIno-LIME2-4GB/open-source-hardware
> There you can find Users Manual where it is described that eMMC option is available from HW rev. D. The schematic for HW rev. E is also available on their repository:
> https://github.com/OLIMEX/OLINUXINO/tree/master/HARDWARE/A20-OLinuXino-LIME2
>
> On the board both 4GB NAND and eMMC Flash chips can be placed alternatively on the same place. There is difference in some other components as well.
>
> If one want to order it from the site probably has to order A20-Olinuxino-Lime2-4GB with note that eMMC option is required. The price is the same.
Sorry for the late reply, but yeah the board exists, we asked Olimex to 
develop the eMMC variant for us. I currently have a dozen or so on my 
desk :)

I don't know when Olimex will update their webshop with the new designs, 
but they simply might not have enough eMMC chips available yet?



From fcooper at ti.com  Tue May  3 08:56:46 2016
From: fcooper at ti.com (Franklin S Cooper Jr)
Date: Tue,  3 May 2016 10:56:46 -0500
Subject: [PATCH v8 0/9] ARM: dts: DRA7: Add dt nodes for PWMSS
Message-ID: <1462291015-1919-1-git-send-email-fcooper@ti.com>

This patch series adds support for PWM for DRA7. The IP is the same as the
one present in AM33XX and AM437XX.

However, before doing so remove unnecessary hwmod entries for eCAP, ePWM
and eQEP.

The following are the biggest changes from v7 to v8:
Insure DT unit address matches reg property address

The following are the biggest changes from v6 to v7:
* Several patches to document previously undocumented bindings.
* Fix minor issues in binding documents.

The following are the biggest changes from v5 to v6:
* Created two new bindings to allow ECAP and PWM to grab their functional
clock from DT rather than depending on PWMSS parent.
* Pull in a couple of patches from the "Correct PWM bindings" series. This
makes it a bit easier to understand.

>From the two patchsets a handful of patches have already been pulled in by
maintainers and have already made it to linux-next. Therefore, this
patch series is built ontop of the latest linux-next.

Tested on:
AM335x, AM437x and X15 + lcd w/backlight

Franklin S Cooper Jr (8):
  clk: ti: am335x/am4372: Add tbclk to pwm node
  ARM: dts: am437x: Add missing compatibles to PWM binding documents
  pwm: pwm-tiehrpwm: Update dt binding document to use generic node name
  pwm: pwm-tiecap: Update dt binding document to use proper unit address
  ARM: dts: am437x/am33xx/da850: Add new ECAP and EPWM bindings
  pwms: pwm-ti*: Get the clock from the PWMSS parent when using old
    bindings
  ARM: dts: am437x/am33xx: Remove hwmod entries for ECAP and EPWM nodes
  ARM: AM335x/AM437x: hwmod: Remove eQEP, ePWM and eCAP hwmod entries

Vignesh R (1):
  ARM: dts: DRA7: Add dt nodes for PWMSS

 .../devicetree/bindings/pwm/pwm-tiecap.txt         | 38 ++++++---
 .../devicetree/bindings/pwm/pwm-tiehrpwm.txt       | 38 ++++++---
 .../devicetree/bindings/pwm/pwm-tipwmss.txt        | 33 +++++++-
 arch/arm/boot/dts/am33xx.dtsi                      | 36 ++++++---
 arch/arm/boot/dts/am4372.dtsi                      | 63 ++++++++++-----
 arch/arm/boot/dts/da850.dtsi                       | 15 ++--
 arch/arm/boot/dts/dra7.dtsi                        | 90 ++++++++++++++++++++++
 .../mach-omap2/omap_hwmod_33xx_43xx_common_data.h  | 18 -----
 .../omap_hwmod_33xx_43xx_interconnect_data.c       | 64 ---------------
 .../mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c | 84 --------------------
 arch/arm/mach-omap2/omap_hwmod_33xx_data.c         |  9 ---
 arch/arm/mach-omap2/omap_hwmod_43xx_data.c         | 54 -------------
 drivers/clk/ti/clk-33xx.c                          |  3 +
 drivers/clk/ti/clk-43xx.c                          |  6 ++
 drivers/pwm/pwm-tiecap.c                           |  7 ++
 drivers/pwm/pwm-tiehrpwm.c                         |  7 ++
 16 files changed, 281 insertions(+), 284 deletions(-)

-- 
2.7.0



From fcooper at ti.com  Tue May  3 08:56:48 2016
From: fcooper at ti.com (Franklin S Cooper Jr)
Date: Tue,  3 May 2016 10:56:48 -0500
Subject: [PATCH v8 2/9] ARM: dts: am437x: Add missing compatibles to PWM
 binding documents
In-Reply-To: <1462291015-1919-1-git-send-email-fcooper@ti.com>
References: <1462291015-1919-1-git-send-email-fcooper@ti.com>
Message-ID: <1462291015-1919-3-git-send-email-fcooper@ti.com>

There are several SOC specific compatibles for ECAP, EHRPWM and PWMMS
that are in use but aren't properly documented. Therefore, fix this
by adding the compatibles to the appropriate binding documents.

While at it make minor corrections to the binding document.

Signed-off-by: Franklin S Cooper Jr <fcooper at ti.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/pwm/pwm-tiecap.txt          | 12 ++++++++++--
 .../devicetree/bindings/pwm/pwm-tiehrpwm.txt        | 12 ++++++++++--
 .../devicetree/bindings/pwm/pwm-tipwmss.txt         | 21 +++++++++++++++++++--
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
index fb81179..788da6c 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
@@ -2,8 +2,9 @@ TI SOC ECAP based APWM controller
 
 Required properties:
 - compatible: Must be "ti,<soc>-ecap".
-  for am33xx - compatible = "ti,am33xx-ecap";
-  for da850  - compatible = "ti,da850-ecap", "ti,am33xx-ecap";
+  for am33xx  - compatible = "ti,am33xx-ecap";
+  for am4372  - compatible = "ti,am4372-ecap", "ti,am33xx-ecap";
+  for da850   - compatible = "ti,da850-ecap", "ti,am33xx-ecap";
 - #pwm-cells: should be 3. See pwm.txt in this directory for a description of
   the cells format. The PWM channel index ranges from 0 to 4. The only third
   cell flag supported by this binding is PWM_POLARITY_INVERTED.
@@ -22,6 +23,13 @@ ecap0: ecap at 0 { /* ECAP on am33xx */
 	ti,hwmods = "ecap0";
 };
 
+ecap0: ecap at 0 { /* ECAP on am4372 */
+	compatible = "ti,am4372-ecap", "ti,am33xx-ecap";
+	#pwm-cells = <3>;
+	reg = <0x48300100 0x80>;
+	ti,hwmods = "ecap0";
+};
+
 ecap0: ecap at 0 { /* ECAP on da850 */
 	compatible = "ti,da850-ecap", "ti,am33xx-ecap";
 	#pwm-cells = <3>;
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
index 9c100b2..99b544f 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
@@ -2,8 +2,9 @@ TI SOC EHRPWM based PWM controller
 
 Required properties:
 - compatible: Must be "ti,<soc>-ehrpwm".
-  for am33xx - compatible = "ti,am33xx-ehrpwm";
-  for da850  - compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm";
+  for am33xx  - compatible = "ti,am33xx-ehrpwm";
+  for am4372  - compatible = "ti,am4372-ehrpwm", "ti,am33xx-ehrpwm";
+  for da850   - compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm";
 - #pwm-cells: should be 3. See pwm.txt in this directory for a description of
   the cells format. The only third cell flag supported by this binding is
   PWM_POLARITY_INVERTED.
@@ -22,6 +23,13 @@ ehrpwm0: ehrpwm at 0 { /* EHRPWM on am33xx */
 	ti,hwmods = "ehrpwm0";
 };
 
+ehrpwm0: ehrpwm at 0 { /* EHRPWM on am4372 */
+	compatible = "ti,am4372-ehrpwm", "ti,am33xx-ehrpwm";
+	#pwm-cells = <3>;
+	reg = <0x48300200 0x80>;
+	ti,hwmods = "ehrpwm0";
+};
+
 ehrpwm0: ehrpwm at 0 { /* EHRPWM on da850 */
 	compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm";
 	#pwm-cells = <3>;
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt b/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt
index f7eae77..fd8e87c 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt
@@ -1,7 +1,10 @@
 TI SOC based PWM Subsystem
 
 Required properties:
-- compatible: Must be "ti,am33xx-pwmss";
+- compatible: Must be "ti,<soc>-pwmss".
+  for am33xx  - compatible = "ti,am33xx-pwmss";
+  for am4372  - compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+
 - reg: physical base address and size of the registers map.
 - address-cells: Specify the number of u32 entries needed in child nodes.
 		  Should set to 1.
@@ -16,7 +19,7 @@ Required properties:
 Also child nodes should also populated under PWMSS DT node.
 
 Example:
-pwmss0: pwmss at 48300000 {
+epwmss0: epwmss at 48300000 { /* PWMSS for am33xx */
 	compatible = "ti,am33xx-pwmss";
 	reg = <0x48300000 0x10>;
 	ti,hwmods = "epwmss0";
@@ -29,3 +32,17 @@ pwmss0: pwmss at 48300000 {
 
 	/* child nodes go here */
 };
+
+epwmss0: epwmss at 48300000 { /* PWMSS for am4372 */
+	compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"
+	reg = <0x48300000 0x10>;
+	ti,hwmods = "epwmss0";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	status = "disabled";
+	ranges = <0x48300100 0x48300100 0x80   /* ECAP */
+		  0x48300180 0x48300180 0x80   /* EQEP */
+		  0x48300200 0x48300200 0x80>; /* EHRPWM */
+
+	/* child nodes go here */
+};
-- 
2.7.0



From fcooper at ti.com  Tue May  3 08:56:50 2016
From: fcooper at ti.com (Franklin S Cooper Jr)
Date: Tue,  3 May 2016 10:56:50 -0500
Subject: [PATCH v8 4/9] pwm: pwm-tiecap: Update dt binding document to use
 proper unit address
In-Reply-To: <1462291015-1919-1-git-send-email-fcooper@ti.com>
References: <1462291015-1919-1-git-send-email-fcooper@ti.com>
Message-ID: <1462291015-1919-5-git-send-email-fcooper@ti.com>

Replace unit address from 0 to the proper physical address. Also insure
that the unit address matches the reg property address.

Signed-off-by: Franklin S Cooper Jr <fcooper at ti.com>
---
 Documentation/devicetree/bindings/pwm/pwm-tiecap.txt | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
index 788da6c..0d47354 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
@@ -16,22 +16,22 @@ Optional properties:
 
 Example:
 
-ecap0: ecap at 0 { /* ECAP on am33xx */
+ecap0: ecap at 48300100 { /* ECAP on am33xx */
 	compatible = "ti,am33xx-ecap";
 	#pwm-cells = <3>;
 	reg = <0x48300100 0x80>;
 	ti,hwmods = "ecap0";
 };
 
-ecap0: ecap at 0 { /* ECAP on am4372 */
+ecap0: ecap at 48300100 { /* ECAP on am4372 */
 	compatible = "ti,am4372-ecap", "ti,am33xx-ecap";
 	#pwm-cells = <3>;
 	reg = <0x48300100 0x80>;
 	ti,hwmods = "ecap0";
 };
 
-ecap0: ecap at 0 { /* ECAP on da850 */
+ecap0: ecap at 1f06000 { /* ECAP on da850 */
 	compatible = "ti,da850-ecap", "ti,am33xx-ecap";
 	#pwm-cells = <3>;
-	reg = <0x306000 0x80>;
+	reg = <0x1f06000 0x80>;
 };
-- 
2.7.0



From fcooper at ti.com  Tue May  3 08:56:47 2016
From: fcooper at ti.com (Franklin S Cooper Jr)
Date: Tue,  3 May 2016 10:56:47 -0500
Subject: [PATCH v8 1/9] clk: ti: am335x/am4372: Add tbclk to pwm node
In-Reply-To: <1462291015-1919-1-git-send-email-fcooper@ti.com>
References: <1462291015-1919-1-git-send-email-fcooper@ti.com>
Message-ID: <1462291015-1919-2-git-send-email-fcooper@ti.com>

Add tblck to the pwm nodes. This insures that the ehrpwm driver has access
to the time-based clk.

Do not remove similar entries for ehrpwm node. Later patches will switch
from using ehrpwm node name to pwm. But to maintain ABI compatibility we
shouldn't remove the old entries.

Signed-off-by: Franklin S Cooper Jr <fcooper at ti.com>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Acked-by: Tero Kristo <t-kristo at ti.com>
---
 drivers/clk/ti/clk-33xx.c | 3 +++
 drivers/clk/ti/clk-43xx.c | 6 ++++++
 2 files changed, 9 insertions(+)

diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c
index ef2ec64..0e47d95 100644
--- a/drivers/clk/ti/clk-33xx.c
+++ b/drivers/clk/ti/clk-33xx.c
@@ -108,6 +108,9 @@ static struct ti_dt_clk am33xx_clks[] = {
 	DT_CLK("48300200.ehrpwm", "tbclk", "ehrpwm0_tbclk"),
 	DT_CLK("48302200.ehrpwm", "tbclk", "ehrpwm1_tbclk"),
 	DT_CLK("48304200.ehrpwm", "tbclk", "ehrpwm2_tbclk"),
+	DT_CLK("48300200.pwm", "tbclk", "ehrpwm0_tbclk"),
+	DT_CLK("48302200.pwm", "tbclk", "ehrpwm1_tbclk"),
+	DT_CLK("48304200.pwm", "tbclk", "ehrpwm2_tbclk"),
 	{ .node_name = NULL },
 };
 
diff --git a/drivers/clk/ti/clk-43xx.c b/drivers/clk/ti/clk-43xx.c
index 097fc90..7255aa8 100644
--- a/drivers/clk/ti/clk-43xx.c
+++ b/drivers/clk/ti/clk-43xx.c
@@ -115,6 +115,12 @@ static struct ti_dt_clk am43xx_clks[] = {
 	DT_CLK("48306200.ehrpwm", "tbclk", "ehrpwm3_tbclk"),
 	DT_CLK("48308200.ehrpwm", "tbclk", "ehrpwm4_tbclk"),
 	DT_CLK("4830a200.ehrpwm", "tbclk", "ehrpwm5_tbclk"),
+	DT_CLK("48300200.pwm", "tbclk", "ehrpwm0_tbclk"),
+	DT_CLK("48302200.pwm", "tbclk", "ehrpwm1_tbclk"),
+	DT_CLK("48304200.pwm", "tbclk", "ehrpwm2_tbclk"),
+	DT_CLK("48306200.pwm", "tbclk", "ehrpwm3_tbclk"),
+	DT_CLK("48308200.pwm", "tbclk", "ehrpwm4_tbclk"),
+	DT_CLK("4830a200.pwm", "tbclk", "ehrpwm5_tbclk"),
 	{ .node_name = NULL },
 };
 
-- 
2.7.0



From fcooper at ti.com  Tue May  3 08:56:49 2016
From: fcooper at ti.com (Franklin S Cooper Jr)
Date: Tue,  3 May 2016 10:56:49 -0500
Subject: [PATCH v8 3/9] pwm: pwm-tiehrpwm: Update dt binding document to use
 generic node name
In-Reply-To: <1462291015-1919-1-git-send-email-fcooper@ti.com>
References: <1462291015-1919-1-git-send-email-fcooper@ti.com>
Message-ID: <1462291015-1919-4-git-send-email-fcooper@ti.com>

Now that the node name has been changed from ehrpwm to pwm the document
should show this proper usage. Change the unit address in the example
from 0 to the proper physical address value that should be used. Also
insure that the unit address matches to the reg property.

Signed-off-by: Franklin S Cooper Jr <fcooper at ti.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
index 99b544f..f3bc09e 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
@@ -16,22 +16,22 @@ Optional properties:
 
 Example:
 
-ehrpwm0: ehrpwm at 0 { /* EHRPWM on am33xx */
+ehrpwm0: pwm at 48300200 { /* EHRPWM on am33xx */
 	compatible = "ti,am33xx-ehrpwm";
 	#pwm-cells = <3>;
 	reg = <0x48300200 0x100>;
 	ti,hwmods = "ehrpwm0";
 };
 
-ehrpwm0: ehrpwm at 0 { /* EHRPWM on am4372 */
+ehrpwm0: pwm at 48300200 { /* EHRPWM on am4372 */
 	compatible = "ti,am4372-ehrpwm", "ti,am33xx-ehrpwm";
 	#pwm-cells = <3>;
 	reg = <0x48300200 0x80>;
 	ti,hwmods = "ehrpwm0";
 };
 
-ehrpwm0: ehrpwm at 0 { /* EHRPWM on da850 */
+ehrpwm0: pwm at 1f00000 { /* EHRPWM on da850 */
 	compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm";
 	#pwm-cells = <3>;
-	reg = <0x300000 0x2000>;
+	reg = <0x1f00000 0x2000>;
 };
-- 
2.7.0



From fcooper at ti.com  Tue May  3 08:56:51 2016
From: fcooper at ti.com (Franklin S Cooper Jr)
Date: Tue,  3 May 2016 10:56:51 -0500
Subject: [PATCH v8 5/9] ARM: dts: am437x/am33xx/da850: Add new ECAP and EPWM
 bindings
In-Reply-To: <1462291015-1919-1-git-send-email-fcooper@ti.com>
References: <1462291015-1919-1-git-send-email-fcooper@ti.com>
Message-ID: <1462291015-1919-6-git-send-email-fcooper@ti.com>

Switch to a new ECAP and EPWM bindings that doesn't depend on hwmod to
provide the various required clocks.

For AM437 and AM335x, add the required clocks explicitly to DT. The
hwmod entries for ECAP and EPWM will be removed and this will prevent
anything from breaking.

Signed-off-by: Franklin S Cooper Jr <fcooper at ti.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/pwm/pwm-tiecap.txt         | 18 +++++---
 .../devicetree/bindings/pwm/pwm-tiehrpwm.txt       | 18 +++++---
 arch/arm/boot/dts/am33xx.dtsi                      | 30 +++++++++---
 arch/arm/boot/dts/am4372.dtsi                      | 54 ++++++++++++++++++----
 arch/arm/boot/dts/da850.dtsi                       | 15 ++++--
 5 files changed, 103 insertions(+), 32 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
index 0d47354..ee0a8bd 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
@@ -2,9 +2,9 @@ TI SOC ECAP based APWM controller
 
 Required properties:
 - compatible: Must be "ti,<soc>-ecap".
-  for am33xx  - compatible = "ti,am33xx-ecap";
-  for am4372  - compatible = "ti,am4372-ecap", "ti,am33xx-ecap";
-  for da850   - compatible = "ti,da850-ecap", "ti,am33xx-ecap";
+  for am33xx - compatible = "ti,am3352-ecap", "ti,am33xx-ecap";
+  for am4372 - compatible = "ti,am4372-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
+  for da850  - compatible = "ti,da850-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
 - #pwm-cells: should be 3. See pwm.txt in this directory for a description of
   the cells format. The PWM channel index ranges from 0 to 4. The only third
   cell flag supported by this binding is PWM_POLARITY_INVERTED.
@@ -13,25 +13,31 @@ Required properties:
 Optional properties:
 - ti,hwmods: Name of the hwmod associated to the ECAP:
   "ecap<x>", <x> being the 0-based instance number from the HW spec
+- clocks: Handle to the ECAP's functional clock.
+- clock-names: Must be set to "fck".
 
 Example:
 
 ecap0: ecap at 48300100 { /* ECAP on am33xx */
-	compatible = "ti,am33xx-ecap";
+	compatible = "ti,am3352-ecap", "ti,am33xx-ecap";
 	#pwm-cells = <3>;
 	reg = <0x48300100 0x80>;
 	ti,hwmods = "ecap0";
+	clocks = <&l4ls_gclk>;
+	clock-names = "fck";
 };
 
 ecap0: ecap at 48300100 { /* ECAP on am4372 */
-	compatible = "ti,am4372-ecap", "ti,am33xx-ecap";
+	compatible = "ti,am4372-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
 	#pwm-cells = <3>;
 	reg = <0x48300100 0x80>;
 	ti,hwmods = "ecap0";
+	clocks = <&l4ls_gclk>;
+	clock-names = "fck";
 };
 
 ecap0: ecap at 1f06000 { /* ECAP on da850 */
-	compatible = "ti,da850-ecap", "ti,am33xx-ecap";
+	compatible = "ti,da850-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
 	#pwm-cells = <3>;
 	reg = <0x1f06000 0x80>;
 };
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
index f3bc09e..e9a156b 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
@@ -2,9 +2,9 @@ TI SOC EHRPWM based PWM controller
 
 Required properties:
 - compatible: Must be "ti,<soc>-ehrpwm".
-  for am33xx  - compatible = "ti,am33xx-ehrpwm";
-  for am4372  - compatible = "ti,am4372-ehrpwm", "ti,am33xx-ehrpwm";
-  for da850   - compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm";
+  for am33xx  - compatible = "ti,am3352-ehrpwm", "ti,am33xx-ehrpwm";
+  for am4372  - compatible = "ti,am4372-ehrpwm", "ti-am3352-ehrpwm", "ti,am33xx-ehrpwm";
+  for da850   - compatible = "ti,da850-ehrpwm", "ti-am3352-ehrpwm", "ti,am33xx-ehrpwm";
 - #pwm-cells: should be 3. See pwm.txt in this directory for a description of
   the cells format. The only third cell flag supported by this binding is
   PWM_POLARITY_INVERTED.
@@ -13,25 +13,31 @@ Required properties:
 Optional properties:
 - ti,hwmods: Name of the hwmod associated to the EHRPWM:
   "ehrpwm<x>", <x> being the 0-based instance number from the HW spec
+- clocks: Handle to the PWM's time-base and functional clock.
+- clock-names: Must be set to "tbclk" and "fck".
 
 Example:
 
 ehrpwm0: pwm at 48300200 { /* EHRPWM on am33xx */
-	compatible = "ti,am33xx-ehrpwm";
+	compatible = "ti,am3352-ehrpwm", "ti,am33xx-ehrpwm";
 	#pwm-cells = <3>;
 	reg = <0x48300200 0x100>;
+	clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>;
+	clock-names = "tbclk", "fck";
 	ti,hwmods = "ehrpwm0";
 };
 
 ehrpwm0: pwm at 48300200 { /* EHRPWM on am4372 */
-	compatible = "ti,am4372-ehrpwm", "ti,am33xx-ehrpwm";
+	compatible = "ti,am4372-ehrpwm", "ti,am3352-ehrpwm", "ti,am33xx-ehrpwm";
 	#pwm-cells = <3>;
 	reg = <0x48300200 0x80>;
+	clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>;
+	clock-names = "tbclk", "fck";
 	ti,hwmods = "ehrpwm0";
 };
 
 ehrpwm0: pwm at 1f00000 { /* EHRPWM on da850 */
-	compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm";
+	compatible = "ti,da850-ehrpwm", "ti,am3352-ehrpwm", "ti,am33xx-ehrpwm";
 	#pwm-cells = <3>;
 	reg = <0x1f00000 0x2000>;
 };
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 52be48b..999ba2f 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -679,9 +679,12 @@
 				  0x48300200 0x48300200 0x80>; /* EHRPWM */
 
 			ecap0: ecap at 48300100 {
-				compatible = "ti,am33xx-ecap";
+				compatible = "ti,am3352-ecap",
+					     "ti,am33xx-ecap";
 				#pwm-cells = <3>;
 				reg = <0x48300100 0x80>;
+				clocks = <&l4ls_gclk>;
+				clock-names = "fck";
 				interrupts = <31>;
 				interrupt-names = "ecap0";
 				ti,hwmods = "ecap0";
@@ -689,10 +692,13 @@
 			};
 
 			ehrpwm0: pwm at 48300200 {
-				compatible = "ti,am33xx-ehrpwm";
+				compatible = "ti,am3352-ehrpwm",
+					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48300200 0x80>;
 				ti,hwmods = "ehrpwm0";
+				clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>;
+				clock-names = "tbclk", "fck";
 				status = "disabled";
 			};
 		};
@@ -709,9 +715,12 @@
 				  0x48302200 0x48302200 0x80>; /* EHRPWM */
 
 			ecap1: ecap at 48302100 {
-				compatible = "ti,am33xx-ecap";
+				compatible = "ti,am3352-ecap",
+					     "ti,am33xx-ecap";
 				#pwm-cells = <3>;
 				reg = <0x48302100 0x80>;
+				clocks = <&l4ls_gclk>;
+				clock-names = "fck";
 				interrupts = <47>;
 				interrupt-names = "ecap1";
 				ti,hwmods = "ecap1";
@@ -719,10 +728,13 @@
 			};
 
 			ehrpwm1: pwm at 48302200 {
-				compatible = "ti,am33xx-ehrpwm";
+				compatible = "ti,am3352-ehrpwm",
+					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48302200 0x80>;
 				ti,hwmods = "ehrpwm1";
+				clocks = <&ehrpwm1_tbclk>, <&l4ls_gclk>;
+				clock-names = "tbclk", "fck";
 				status = "disabled";
 			};
 		};
@@ -739,9 +751,12 @@
 				  0x48304200 0x48304200 0x80>; /* EHRPWM */
 
 			ecap2: ecap at 48304100 {
-				compatible = "ti,am33xx-ecap";
+				compatible = "ti,am3352-ecap",
+					     "ti,am33xx-ecap";
 				#pwm-cells = <3>;
 				reg = <0x48304100 0x80>;
+				clocks = <&l4ls_gclk>;
+				clock-names = "fck";
 				interrupts = <61>;
 				interrupt-names = "ecap2";
 				ti,hwmods = "ecap2";
@@ -749,10 +764,13 @@
 			};
 
 			ehrpwm2: pwm at 48304200 {
-				compatible = "ti,am33xx-ehrpwm";
+				compatible = "ti,am3352-ehrpwm",
+					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48304200 0x80>;
 				ti,hwmods = "ehrpwm2";
+				clocks = <&ehrpwm2_tbclk>, <&l4ls_gclk>;
+				clock-names = "tbclk", "fck";
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index 12fcde4..e858460 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -672,18 +672,26 @@
 			status = "disabled";
 
 			ecap0: ecap at 48300100 {
-				compatible = "ti,am4372-ecap","ti,am33xx-ecap";
+				compatible = "ti,am4372-ecap",
+					     "ti,am3352-ecap",
+					     "ti,am33xx-ecap";
 				#pwm-cells = <3>;
 				reg = <0x48300100 0x80>;
 				ti,hwmods = "ecap0";
+				clocks = <&l4ls_gclk>;
+				clock-names = "fck";
 				status = "disabled";
 			};
 
 			ehrpwm0: pwm at 48300200 {
-				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				compatible = "ti,am4372-ehrpwm",
+					     "ti,am3352-ehrpwm",
+					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48300200 0x80>;
 				ti,hwmods = "ehrpwm0";
+				clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>;
+				clock-names = "tbclk", "fck";
 				status = "disabled";
 			};
 		};
@@ -698,18 +706,26 @@
 			status = "disabled";
 
 			ecap1: ecap at 48302100 {
-				compatible = "ti,am4372-ecap","ti,am33xx-ecap";
+				compatible = "ti,am4372-ecap",
+					     "ti,am3352-ecap",
+					     "ti,am33xx-ecap";
 				#pwm-cells = <3>;
 				reg = <0x48302100 0x80>;
 				ti,hwmods = "ecap1";
+				clocks = <&l4ls_gclk>;
+				clock-names = "fck";
 				status = "disabled";
 			};
 
 			ehrpwm1: pwm at 48302200 {
-				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				compatible = "ti,am4372-ehrpwm",
+					     "ti,am3352-ehrpwm",
+					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48302200 0x80>;
 				ti,hwmods = "ehrpwm1";
+				clocks = <&ehrpwm1_tbclk>, <&l4ls_gclk>;
+				clock-names = "tbclk", "fck";
 				status = "disabled";
 			};
 		};
@@ -724,18 +740,26 @@
 			status = "disabled";
 
 			ecap2: ecap at 48304100 {
-				compatible = "ti,am4372-ecap","ti,am33xx-ecap";
+				compatible = "ti,am4372-ecap",
+					     "ti,am3352-ecap",
+					     "ti,am33xx-ecap";
 				#pwm-cells = <3>;
 				reg = <0x48304100 0x80>;
+				clocks = <&l4ls_gclk>;
+				clock-names = "fck";
 				ti,hwmods = "ecap2";
 				status = "disabled";
 			};
 
 			ehrpwm2: pwm at 48304200 {
-				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				compatible = "ti,am4372-ehrpwm",
+					     "ti,am3352-ehrpwm",
+					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48304200 0x80>;
 				ti,hwmods = "ehrpwm2";
+				clocks = <&ehrpwm2_tbclk>, <&l4ls_gclk>;
+				clock-names = "tbclk", "fck";
 				status = "disabled";
 			};
 		};
@@ -750,10 +774,14 @@
 			status = "disabled";
 
 			ehrpwm3: pwm at 48306200 {
-				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				compatible = "ti,am4372-ehrpwm",
+					     "ti,am3352-ehrpwm",
+					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48306200 0x80>;
 				ti,hwmods = "ehrpwm3";
+				clocks = <&ehrpwm3_tbclk>, <&l4ls_gclk>;
+				clock-names = "tbclk", "fck";
 				status = "disabled";
 			};
 		};
@@ -768,10 +796,14 @@
 			status = "disabled";
 
 			ehrpwm4: pwm at 48308200 {
-				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				compatible = "ti,am4372-ehrpwm",
+					     "ti,am3352-ehrpwm",
+					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48308200 0x80>;
 				ti,hwmods = "ehrpwm4";
+				clocks = <&ehrpwm4_tbclk>, <&l4ls_gclk>;
+				clock-names = "tbclk", "fck";
 				status = "disabled";
 			};
 		};
@@ -786,9 +818,13 @@
 			status = "disabled";
 
 			ehrpwm5: pwm at 4830a200 {
-				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				compatible = "ti,am4372-ehrpwm",
+					     "ti,am3352-ehrpwm",
+					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x4830a200 0x80>;
+				clocks = <&ehrpwm5_tbclk>, <&l4ls_gclk>;
+				clock-names = "tbclk", "fck";
 				ti,hwmods = "ehrpwm5";
 				status = "disabled";
 			};
diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index c3910e2..28a1064 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -248,31 +248,36 @@
 			status = "disabled";
 		};
 		ehrpwm0: pwm at 01f00000 {
-			compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm";
+			compatible = "ti,da850-ehrpwm", "ti,am3352-ehrpwm",
+				     "ti,am33xx-ehrpwm";
 			#pwm-cells = <3>;
 			reg = <0x300000 0x2000>;
 			status = "disabled";
 		};
 		ehrpwm1: pwm at 01f02000 {
-			compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm";
+			compatible = "ti,da850-ehrpwm", "ti,am3352-ehrpwm",
+				     "ti,am33xx-ehrpwm";
 			#pwm-cells = <3>;
 			reg = <0x302000 0x2000>;
 			status = "disabled";
 		};
 		ecap0: ecap at 01f06000 {
-			compatible = "ti,da850-ecap", "ti,am33xx-ecap";
+			compatible = "ti,da850-ecap", "ti,am3352-ecap",
+				     "ti,am33xx-ecap";
 			#pwm-cells = <3>;
 			reg = <0x306000 0x80>;
 			status = "disabled";
 		};
 		ecap1: ecap at 01f07000 {
-			compatible = "ti,da850-ecap", "ti,am33xx-ecap";
+			compatible = "ti,da850-ecap", "ti,am3352-ecap",
+				     "ti,am33xx-ecap";
 			#pwm-cells = <3>;
 			reg = <0x307000 0x80>;
 			status = "disabled";
 		};
 		ecap2: ecap at 01f08000 {
-			compatible = "ti,da850-ecap", "ti,am33xx-ecap";
+			compatible = "ti,da850-ecap", "ti,am3352-ecap",
+				     "ti,am33xx-ecap";
 			#pwm-cells = <3>;
 			reg = <0x308000 0x80>;
 			status = "disabled";
-- 
2.7.0



From fcooper at ti.com  Tue May  3 08:56:52 2016
From: fcooper at ti.com (Franklin S Cooper Jr)
Date: Tue,  3 May 2016 10:56:52 -0500
Subject: [PATCH v8 6/9] pwms: pwm-ti*: Get the clock from the PWMSS parent
 when using old bindings
In-Reply-To: <1462291015-1919-1-git-send-email-fcooper@ti.com>
References: <1462291015-1919-1-git-send-email-fcooper@ti.com>
Message-ID: <1462291015-1919-7-git-send-email-fcooper@ti.com>

When using the old eCAP and ePWM bindings for AM335x and AM437x the clock
can be retrieved from the PWMSS parent. Newer bindings will insure that
this clock is provided via device tree.

Therefore, update this driver to support the newer and older bindings. In
the case of the older binding being used give a warning.

Signed-off-by: Franklin S Cooper Jr <fcooper at ti.com>
---
 drivers/pwm/pwm-tiecap.c   | 7 +++++++
 drivers/pwm/pwm-tiehrpwm.c | 7 +++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index 616af76..a0833c8 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -195,6 +195,7 @@ static const struct pwm_ops ecap_pwm_ops = {
 };
 
 static const struct of_device_id ecap_of_match[] = {
+	{ .compatible	= "ti,am3352-ecap" },
 	{ .compatible	= "ti,am33xx-ecap" },
 	{},
 };
@@ -213,6 +214,12 @@ static int ecap_pwm_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	clk = devm_clk_get(&pdev->dev, "fck");
+
+	if (IS_ERR(clk) && of_device_is_compatible(pdev->dev.of_node, "ti,am33xx-ecap")) {
+		dev_warn(&pdev->dev, "Binding is obsolete.\n");
+		clk = devm_clk_get(pdev->dev.parent, "fck");
+	}
+
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clock\n");
 		return PTR_ERR(clk);
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index 6a41e66..cee29a2 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -426,6 +426,7 @@ static const struct pwm_ops ehrpwm_pwm_ops = {
 };
 
 static const struct of_device_id ehrpwm_of_match[] = {
+	{ .compatible	= "ti,am3352-ehrpwm" },
 	{ .compatible	= "ti,am33xx-ehrpwm" },
 	{},
 };
@@ -444,6 +445,12 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	clk = devm_clk_get(&pdev->dev, "fck");
+
+	if (IS_ERR(clk) && of_device_is_compatible(pdev->dev.of_node, "ti,am33xx-ecap")) {
+		dev_warn(&pdev->dev, "Binding is obsolete.\n");
+		clk = devm_clk_get(pdev->dev.parent, "fck");
+	}
+
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clock\n");
 		return PTR_ERR(clk);
-- 
2.7.0



From fcooper at ti.com  Tue May  3 08:56:53 2016
From: fcooper at ti.com (Franklin S Cooper Jr)
Date: Tue,  3 May 2016 10:56:53 -0500
Subject: [PATCH v8 7/9] ARM: dts: am437x/am33xx: Remove hwmod entries for ECAP
 and EPWM nodes
In-Reply-To: <1462291015-1919-1-git-send-email-fcooper@ti.com>
References: <1462291015-1919-1-git-send-email-fcooper@ti.com>
Message-ID: <1462291015-1919-8-git-send-email-fcooper@ti.com>

Previous patches switched the ECAP and EPWM to use the new bindings.
These bindings explicitly adds the various required clocks via DT rather
than depending on hwmod.

Therefore, it is safe to remove the hwmod entries since they are no longer
needed.

Signed-off-by: Franklin S Cooper Jr <fcooper at ti.com>
Acked-by: Rob Herring <robh at kernel.org>
Acked-by: Paul Walmsley <paul at pwsan.com>
---
 Documentation/devicetree/bindings/pwm/pwm-tiecap.txt   | 3 ---
 Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt | 3 ---
 arch/arm/boot/dts/am33xx.dtsi                          | 6 ------
 arch/arm/boot/dts/am4372.dtsi                          | 9 ---------
 4 files changed, 21 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
index ee0a8bd..f2a9a7c 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
@@ -11,8 +11,6 @@ Required properties:
 - reg: physical base address and size of the registers map.
 
 Optional properties:
-- ti,hwmods: Name of the hwmod associated to the ECAP:
-  "ecap<x>", <x> being the 0-based instance number from the HW spec
 - clocks: Handle to the ECAP's functional clock.
 - clock-names: Must be set to "fck".
 
@@ -22,7 +20,6 @@ ecap0: ecap at 48300100 { /* ECAP on am33xx */
 	compatible = "ti,am3352-ecap", "ti,am33xx-ecap";
 	#pwm-cells = <3>;
 	reg = <0x48300100 0x80>;
-	ti,hwmods = "ecap0";
 	clocks = <&l4ls_gclk>;
 	clock-names = "fck";
 };
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
index e9a156b..41a2bd4 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
@@ -11,8 +11,6 @@ Required properties:
 - reg: physical base address and size of the registers map.
 
 Optional properties:
-- ti,hwmods: Name of the hwmod associated to the EHRPWM:
-  "ehrpwm<x>", <x> being the 0-based instance number from the HW spec
 - clocks: Handle to the PWM's time-base and functional clock.
 - clock-names: Must be set to "tbclk" and "fck".
 
@@ -24,7 +22,6 @@ ehrpwm0: pwm at 48300200 { /* EHRPWM on am33xx */
 	reg = <0x48300200 0x100>;
 	clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>;
 	clock-names = "tbclk", "fck";
-	ti,hwmods = "ehrpwm0";
 };
 
 ehrpwm0: pwm at 48300200 { /* EHRPWM on am4372 */
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 999ba2f..2661acc 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -687,7 +687,6 @@
 				clock-names = "fck";
 				interrupts = <31>;
 				interrupt-names = "ecap0";
-				ti,hwmods = "ecap0";
 				status = "disabled";
 			};
 
@@ -696,7 +695,6 @@
 					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48300200 0x80>;
-				ti,hwmods = "ehrpwm0";
 				clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>;
 				clock-names = "tbclk", "fck";
 				status = "disabled";
@@ -723,7 +721,6 @@
 				clock-names = "fck";
 				interrupts = <47>;
 				interrupt-names = "ecap1";
-				ti,hwmods = "ecap1";
 				status = "disabled";
 			};
 
@@ -732,7 +729,6 @@
 					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48302200 0x80>;
-				ti,hwmods = "ehrpwm1";
 				clocks = <&ehrpwm1_tbclk>, <&l4ls_gclk>;
 				clock-names = "tbclk", "fck";
 				status = "disabled";
@@ -759,7 +755,6 @@
 				clock-names = "fck";
 				interrupts = <61>;
 				interrupt-names = "ecap2";
-				ti,hwmods = "ecap2";
 				status = "disabled";
 			};
 
@@ -768,7 +763,6 @@
 					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48304200 0x80>;
-				ti,hwmods = "ehrpwm2";
 				clocks = <&ehrpwm2_tbclk>, <&l4ls_gclk>;
 				clock-names = "tbclk", "fck";
 				status = "disabled";
diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index e858460..cfdd4b7 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -677,7 +677,6 @@
 					     "ti,am33xx-ecap";
 				#pwm-cells = <3>;
 				reg = <0x48300100 0x80>;
-				ti,hwmods = "ecap0";
 				clocks = <&l4ls_gclk>;
 				clock-names = "fck";
 				status = "disabled";
@@ -689,7 +688,6 @@
 					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48300200 0x80>;
-				ti,hwmods = "ehrpwm0";
 				clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>;
 				clock-names = "tbclk", "fck";
 				status = "disabled";
@@ -711,7 +709,6 @@
 					     "ti,am33xx-ecap";
 				#pwm-cells = <3>;
 				reg = <0x48302100 0x80>;
-				ti,hwmods = "ecap1";
 				clocks = <&l4ls_gclk>;
 				clock-names = "fck";
 				status = "disabled";
@@ -723,7 +720,6 @@
 					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48302200 0x80>;
-				ti,hwmods = "ehrpwm1";
 				clocks = <&ehrpwm1_tbclk>, <&l4ls_gclk>;
 				clock-names = "tbclk", "fck";
 				status = "disabled";
@@ -747,7 +743,6 @@
 				reg = <0x48304100 0x80>;
 				clocks = <&l4ls_gclk>;
 				clock-names = "fck";
-				ti,hwmods = "ecap2";
 				status = "disabled";
 			};
 
@@ -757,7 +752,6 @@
 					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48304200 0x80>;
-				ti,hwmods = "ehrpwm2";
 				clocks = <&ehrpwm2_tbclk>, <&l4ls_gclk>;
 				clock-names = "tbclk", "fck";
 				status = "disabled";
@@ -779,7 +773,6 @@
 					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48306200 0x80>;
-				ti,hwmods = "ehrpwm3";
 				clocks = <&ehrpwm3_tbclk>, <&l4ls_gclk>;
 				clock-names = "tbclk", "fck";
 				status = "disabled";
@@ -801,7 +794,6 @@
 					     "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48308200 0x80>;
-				ti,hwmods = "ehrpwm4";
 				clocks = <&ehrpwm4_tbclk>, <&l4ls_gclk>;
 				clock-names = "tbclk", "fck";
 				status = "disabled";
@@ -825,7 +817,6 @@
 				reg = <0x4830a200 0x80>;
 				clocks = <&ehrpwm5_tbclk>, <&l4ls_gclk>;
 				clock-names = "tbclk", "fck";
-				ti,hwmods = "ehrpwm5";
 				status = "disabled";
 			};
 		};
-- 
2.7.0



From fcooper at ti.com  Tue May  3 08:56:55 2016
From: fcooper at ti.com (Franklin S Cooper Jr)
Date: Tue,  3 May 2016 10:56:55 -0500
Subject: [PATCH v8 9/9] ARM: dts: DRA7: Add dt nodes for PWMSS
In-Reply-To: <1462291015-1919-1-git-send-email-fcooper@ti.com>
References: <1462291015-1919-1-git-send-email-fcooper@ti.com>
Message-ID: <1462291015-1919-10-git-send-email-fcooper@ti.com>

From: Vignesh R <vigneshr at ti.com>

Add PWMSS device tree nodes for DRA7 SoC family and add documentation
for dt bindings.

Signed-off-by: Vignesh R <vigneshr at ti.com>
[fcooper at ti.com: Add eCAP and use updated bindings for PWMSS and ePWM]
Signed-off-by: Franklin S Cooper Jr <fcooper at ti.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/pwm/pwm-tiecap.txt         |  9 +++
 .../devicetree/bindings/pwm/pwm-tiehrpwm.txt       |  9 +++
 .../devicetree/bindings/pwm/pwm-tipwmss.txt        | 12 +++
 arch/arm/boot/dts/dra7.dtsi                        | 90 ++++++++++++++++++++++
 4 files changed, 120 insertions(+)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
index f2a9a7c..8007e83 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
@@ -5,6 +5,7 @@ Required properties:
   for am33xx - compatible = "ti,am3352-ecap", "ti,am33xx-ecap";
   for am4372 - compatible = "ti,am4372-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
   for da850  - compatible = "ti,da850-ecap", "ti,am3352-ecap", "ti,am33xx-ecap";
+  for dra746 - compatible = "ti,dra746-ecap", "ti,am3352-ecap";
 - #pwm-cells: should be 3. See pwm.txt in this directory for a description of
   the cells format. The PWM channel index ranges from 0 to 4. The only third
   cell flag supported by this binding is PWM_POLARITY_INVERTED.
@@ -38,3 +39,11 @@ ecap0: ecap at 1f06000 { /* ECAP on da850 */
 	#pwm-cells = <3>;
 	reg = <0x1f06000 0x80>;
 };
+
+ecap0: ecap at 4843e100 {
+	compatible = "ti,dra746-ecap", "ti,am3352-ecap";
+	#pwm-cells = <3>;
+	reg = <0x4843e100 0x80>;
+	clocks = <&l4_root_clk_div>;
+	clock-names = "fck";
+};
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
index 41a2bd4..944fe35 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tiehrpwm.txt
@@ -5,6 +5,7 @@ Required properties:
   for am33xx  - compatible = "ti,am3352-ehrpwm", "ti,am33xx-ehrpwm";
   for am4372  - compatible = "ti,am4372-ehrpwm", "ti-am3352-ehrpwm", "ti,am33xx-ehrpwm";
   for da850   - compatible = "ti,da850-ehrpwm", "ti-am3352-ehrpwm", "ti,am33xx-ehrpwm";
+  for dra746 - compatible = "ti,dra746-ehrpwm", "ti-am3352-ehrpwm";
 - #pwm-cells: should be 3. See pwm.txt in this directory for a description of
   the cells format. The only third cell flag supported by this binding is
   PWM_POLARITY_INVERTED.
@@ -38,3 +39,11 @@ ehrpwm0: pwm at 1f00000 { /* EHRPWM on da850 */
 	#pwm-cells = <3>;
 	reg = <0x1f00000 0x2000>;
 };
+
+ehrpwm0: pwm at 4843e200 { /* EHRPWM on dra746 */
+	compatible = "ti,dra746-ehrpwm", "ti,am3352-ehrpwm";
+	#pwm-cells = <3>;
+	reg = <0x4843e200 0x80>;
+	clocks = <&ehrpwm0_tbclk>, <&l4_root_clk_div>;
+	clock-names = "tbclk", "fck";
+};
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt b/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt
index fd8e87c..1a5d7b7 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-tipwmss.txt
@@ -4,6 +4,7 @@ Required properties:
 - compatible: Must be "ti,<soc>-pwmss".
   for am33xx  - compatible = "ti,am33xx-pwmss";
   for am4372  - compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+  for dra746 - compatible = "ti,dra746-pwmss", "ti,am33xx-pwmss"
 
 - reg: physical base address and size of the registers map.
 - address-cells: Specify the number of u32 entries needed in child nodes.
@@ -46,3 +47,14 @@ epwmss0: epwmss at 48300000 { /* PWMSS for am4372 */
 
 	/* child nodes go here */
 };
+
+epwmss0: epwmss at 4843e000 { /* PWMSS for DRA7xx */
+	compatible = "ti,dra746-pwmss", "ti,am33xx-pwmss";
+	reg = <0x4843e000 0x30>;
+	ti,hwmods = "epwmss0";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	/* child nodes go here */
+};
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index e007401..5a21e46 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -1743,6 +1743,96 @@
 				clock-names = "fck", "sys_clk";
 			};
 		};
+
+		epwmss0: epwmss at 4843e000 {
+			compatible = "ti,dra746-pwmss", "ti,am33xx-pwmss";
+			reg = <0x4843e000 0x30>;
+			ti,hwmods = "epwmss0";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+			ranges;
+
+			ehrpwm0: pwm at 4843e200 {
+				compatible = "ti,dra746-ehrpwm",
+					     "ti,am3352-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x4843e200 0x80>;
+				clocks = <&ehrpwm0_tbclk>, <&l4_root_clk_div>;
+				clock-names = "tbclk", "fck";
+				status = "disabled";
+			};
+
+			ecap0: ecap at 4843e100 {
+				compatible = "ti,dra746-ecap",
+					     "ti,am3352-ecap";
+				#pwm-cells = <3>;
+				reg = <0x4843e100 0x80>;
+				clocks = <&l4_root_clk_div>;
+				clock-names = "fck";
+				status = "disabled";
+			};
+		};
+
+		epwmss1: epwmss at 48440000 {
+			compatible = "ti,dra746-pwmss", "ti,am33xx-pwmss";
+			reg = <0x48440000 0x30>;
+			ti,hwmods = "epwmss1";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+			ranges;
+
+			ehrpwm1: pwm at 48440200 {
+				compatible = "ti,dra746-ehrpwm",
+					     "ti,am3352-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48440200 0x80>;
+				clocks = <&ehrpwm1_tbclk>, <&l4_root_clk_div>;
+				clock-names = "tbclk", "fck";
+				status = "disabled";
+			};
+
+			ecap1: ecap at 48440100 {
+				compatible = "ti,dra746-ecap",
+					     "ti,am3352-ecap";
+				#pwm-cells = <3>;
+				reg = <0x48440100 0x80>;
+				clocks = <&l4_root_clk_div>;
+				clock-names = "fck";
+				status = "disabled";
+			};
+		};
+
+		epwmss2: epwmss at 48442000 {
+			compatible = "ti,dra746-pwmss", "ti,am33xx-pwmss";
+			reg = <0x48442000 0x30>;
+			ti,hwmods = "epwmss2";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+			ranges;
+
+			ehrpwm2: pwm at 48442200 {
+				compatible = "ti,dra746-ehrpwm",
+					     "ti,am3352-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48442200 0x80>;
+				clocks = <&ehrpwm2_tbclk>, <&l4_root_clk_div>;
+				clock-names = "tbclk", "fck";
+				status = "disabled";
+			};
+
+			ecap2: ecap at 48442100 {
+				compatible = "ti,dra746-ecap",
+					     "ti,am3352-ecap";
+				#pwm-cells = <3>;
+				reg = <0x48442100 0x80>;
+				clocks = <&l4_root_clk_div>;
+				clock-names = "fck";
+				status = "disabled";
+			};
+		};
 	};
 
 	thermal_zones: thermal-zones {
-- 
2.7.0



From fcooper at ti.com  Tue May  3 08:56:54 2016
From: fcooper at ti.com (Franklin S Cooper Jr)
Date: Tue,  3 May 2016 10:56:54 -0500
Subject: [PATCH v8 8/9] ARM: AM335x/AM437x: hwmod: Remove eQEP,
 ePWM and eCAP hwmod entries
In-Reply-To: <1462291015-1919-1-git-send-email-fcooper@ti.com>
References: <1462291015-1919-1-git-send-email-fcooper@ti.com>
Message-ID: <1462291015-1919-9-git-send-email-fcooper@ti.com>

Devices that utilize the OCP registers and/or PRCM registers and
register bit fields should be modeled using hwmod. Since eQEP, ePWM and
eCAP don't fall under this category, remove their hwmod entries.

Instead these clocks simply use the clock that is passed through by its
parent PWMSS. Therefore, PWMSS handles the clock for itself and its
subdevices.

Signed-off-by: Franklin S Cooper Jr <fcooper at ti.com>
Acked-by: Paul Walmsley <paul at pwsan.com>
---
 .../mach-omap2/omap_hwmod_33xx_43xx_common_data.h  | 18 -----
 .../omap_hwmod_33xx_43xx_interconnect_data.c       | 64 -----------------
 .../mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c | 84 ----------------------
 arch/arm/mach-omap2/omap_hwmod_33xx_data.c         |  9 ---
 arch/arm/mach-omap2/omap_hwmod_43xx_data.c         | 54 --------------
 5 files changed, 229 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h
index 7f73796..d3e61d1 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h
@@ -36,17 +36,8 @@ extern struct omap_hwmod_ocp_if am33xx_l4_per__gpio3;
 extern struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__elm;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss0;
-extern struct omap_hwmod_ocp_if am33xx_epwmss0__ecap0;
-extern struct omap_hwmod_ocp_if am33xx_epwmss0__eqep0;
-extern struct omap_hwmod_ocp_if am33xx_epwmss0__ehrpwm0;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss1;
-extern struct omap_hwmod_ocp_if am33xx_epwmss1__ecap1;
-extern struct omap_hwmod_ocp_if am33xx_epwmss1__eqep1;
-extern struct omap_hwmod_ocp_if am33xx_epwmss1__ehrpwm1;
 extern struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss2;
-extern struct omap_hwmod_ocp_if am33xx_epwmss2__ecap2;
-extern struct omap_hwmod_ocp_if am33xx_epwmss2__eqep2;
-extern struct omap_hwmod_ocp_if am33xx_epwmss2__ehrpwm2;
 extern struct omap_hwmod_ocp_if am33xx_l3_s__gpmc;
 extern struct omap_hwmod_ocp_if am33xx_l4_per__i2c2;
 extern struct omap_hwmod_ocp_if am33xx_l4_per__i2c3;
@@ -98,17 +89,8 @@ extern struct omap_hwmod am33xx_dcan0_hwmod;
 extern struct omap_hwmod am33xx_dcan1_hwmod;
 extern struct omap_hwmod am33xx_elm_hwmod;
 extern struct omap_hwmod am33xx_epwmss0_hwmod;
-extern struct omap_hwmod am33xx_ecap0_hwmod;
-extern struct omap_hwmod am33xx_eqep0_hwmod;
-extern struct omap_hwmod am33xx_ehrpwm0_hwmod;
 extern struct omap_hwmod am33xx_epwmss1_hwmod;
-extern struct omap_hwmod am33xx_ecap1_hwmod;
-extern struct omap_hwmod am33xx_eqep1_hwmod;
-extern struct omap_hwmod am33xx_ehrpwm1_hwmod;
 extern struct omap_hwmod am33xx_epwmss2_hwmod;
-extern struct omap_hwmod am33xx_ecap2_hwmod;
-extern struct omap_hwmod am33xx_eqep2_hwmod;
-extern struct omap_hwmod am33xx_ehrpwm2_hwmod;
 extern struct omap_hwmod am33xx_gpio1_hwmod;
 extern struct omap_hwmod am33xx_gpio2_hwmod;
 extern struct omap_hwmod am33xx_gpio3_hwmod;
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c
index 1c210cb..10dff2f 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c
@@ -176,28 +176,6 @@ struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss0 = {
 	.user		= OCP_USER_MPU,
 };
 
-struct omap_hwmod_ocp_if am33xx_epwmss0__ecap0 = {
-	.master		= &am33xx_epwmss0_hwmod,
-	.slave		= &am33xx_ecap0_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-struct omap_hwmod_ocp_if am33xx_epwmss0__eqep0 = {
-	.master		= &am33xx_epwmss0_hwmod,
-	.slave		= &am33xx_eqep0_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-struct omap_hwmod_ocp_if am33xx_epwmss0__ehrpwm0 = {
-	.master		= &am33xx_epwmss0_hwmod,
-	.slave		= &am33xx_ehrpwm0_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-
 static struct omap_hwmod_addr_space am33xx_epwmss1_addr_space[] = {
 	{
 		.pa_start	= 0x48302000,
@@ -215,27 +193,6 @@ struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss1 = {
 	.user		= OCP_USER_MPU,
 };
 
-struct omap_hwmod_ocp_if am33xx_epwmss1__ecap1 = {
-	.master		= &am33xx_epwmss1_hwmod,
-	.slave		= &am33xx_ecap1_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-struct omap_hwmod_ocp_if am33xx_epwmss1__eqep1 = {
-	.master		= &am33xx_epwmss1_hwmod,
-	.slave		= &am33xx_eqep1_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-struct omap_hwmod_ocp_if am33xx_epwmss1__ehrpwm1 = {
-	.master		= &am33xx_epwmss1_hwmod,
-	.slave		= &am33xx_ehrpwm1_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
 static struct omap_hwmod_addr_space am33xx_epwmss2_addr_space[] = {
 	{
 		.pa_start	= 0x48304000,
@@ -253,27 +210,6 @@ struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss2 = {
 	.user		= OCP_USER_MPU,
 };
 
-struct omap_hwmod_ocp_if am33xx_epwmss2__ecap2 = {
-	.master		= &am33xx_epwmss2_hwmod,
-	.slave		= &am33xx_ecap2_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-struct omap_hwmod_ocp_if am33xx_epwmss2__eqep2 = {
-	.master		= &am33xx_epwmss2_hwmod,
-	.slave		= &am33xx_eqep2_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-struct omap_hwmod_ocp_if am33xx_epwmss2__ehrpwm2 = {
-	.master		= &am33xx_epwmss2_hwmod,
-	.slave		= &am33xx_ehrpwm2_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
 /* l3s cfg -> gpmc */
 struct omap_hwmod_ocp_if am33xx_l3_s__gpmc = {
 	.master		= &am33xx_l3_s_hwmod,
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
index aed3362..6a73b6c 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
@@ -449,18 +449,6 @@ struct omap_hwmod_class am33xx_epwmss_hwmod_class = {
 	.sysc		= &am33xx_epwmss_sysc,
 };
 
-static struct omap_hwmod_class am33xx_ecap_hwmod_class = {
-	.name		= "ecap",
-};
-
-static struct omap_hwmod_class am33xx_eqep_hwmod_class = {
-	.name		= "eqep",
-};
-
-struct omap_hwmod_class am33xx_ehrpwm_hwmod_class = {
-	.name		= "ehrpwm",
-};
-
 /* epwmss0 */
 struct omap_hwmod am33xx_epwmss0_hwmod = {
 	.name		= "epwmss0",
@@ -474,30 +462,6 @@ struct omap_hwmod am33xx_epwmss0_hwmod = {
 	},
 };
 
-/* ecap0 */
-struct omap_hwmod am33xx_ecap0_hwmod = {
-	.name		= "ecap0",
-	.class		= &am33xx_ecap_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* eqep0 */
-struct omap_hwmod am33xx_eqep0_hwmod = {
-	.name		= "eqep0",
-	.class		= &am33xx_eqep_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* ehrpwm0 */
-struct omap_hwmod am33xx_ehrpwm0_hwmod = {
-	.name		= "ehrpwm0",
-	.class		= &am33xx_ehrpwm_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
 /* epwmss1 */
 struct omap_hwmod am33xx_epwmss1_hwmod = {
 	.name		= "epwmss1",
@@ -511,30 +475,6 @@ struct omap_hwmod am33xx_epwmss1_hwmod = {
 	},
 };
 
-/* ecap1 */
-struct omap_hwmod am33xx_ecap1_hwmod = {
-	.name		= "ecap1",
-	.class		= &am33xx_ecap_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* eqep1 */
-struct omap_hwmod am33xx_eqep1_hwmod = {
-	.name		= "eqep1",
-	.class		= &am33xx_eqep_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* ehrpwm1 */
-struct omap_hwmod am33xx_ehrpwm1_hwmod = {
-	.name		= "ehrpwm1",
-	.class		= &am33xx_ehrpwm_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
 /* epwmss2 */
 struct omap_hwmod am33xx_epwmss2_hwmod = {
 	.name		= "epwmss2",
@@ -548,30 +488,6 @@ struct omap_hwmod am33xx_epwmss2_hwmod = {
 	},
 };
 
-/* ecap2 */
-struct omap_hwmod am33xx_ecap2_hwmod = {
-	.name		= "ecap2",
-	.class		= &am33xx_ecap_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* eqep2 */
-struct omap_hwmod am33xx_eqep2_hwmod = {
-	.name		= "eqep2",
-	.class		= &am33xx_eqep_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* ehrpwm2 */
-struct omap_hwmod am33xx_ehrpwm2_hwmod = {
-	.name		= "ehrpwm2",
-	.class		= &am33xx_ehrpwm_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
 /*
  * 'gpio' class: for gpio 0,1,2,3
  */
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
index cc0791d..e1c2025 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
@@ -593,17 +593,8 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
 	&am33xx_l4_ls__spinlock,
 	&am33xx_l4_ls__elm,
 	&am33xx_l4_ls__epwmss0,
-	&am33xx_epwmss0__ecap0,
-	&am33xx_epwmss0__eqep0,
-	&am33xx_epwmss0__ehrpwm0,
 	&am33xx_l4_ls__epwmss1,
-	&am33xx_epwmss1__ecap1,
-	&am33xx_epwmss1__eqep1,
-	&am33xx_epwmss1__ehrpwm1,
 	&am33xx_l4_ls__epwmss2,
-	&am33xx_epwmss2__ecap2,
-	&am33xx_epwmss2__eqep2,
-	&am33xx_epwmss2__ehrpwm2,
 	&am33xx_l3_s__gpmc,
 	&am33xx_l3_main__lcdc,
 	&am33xx_l4_ls__mcspi0,
diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
index 97fd399..61f2f30 100644
--- a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
@@ -202,13 +202,6 @@ static struct omap_hwmod am43xx_epwmss3_hwmod = {
 	},
 };
 
-static struct omap_hwmod am43xx_ehrpwm3_hwmod = {
-	.name		= "ehrpwm3",
-	.class		= &am33xx_ehrpwm_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
 static struct omap_hwmod am43xx_epwmss4_hwmod = {
 	.name		= "epwmss4",
 	.class		= &am33xx_epwmss_hwmod_class,
@@ -222,13 +215,6 @@ static struct omap_hwmod am43xx_epwmss4_hwmod = {
 	},
 };
 
-static struct omap_hwmod am43xx_ehrpwm4_hwmod = {
-	.name		= "ehrpwm4",
-	.class		= &am33xx_ehrpwm_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
 static struct omap_hwmod am43xx_epwmss5_hwmod = {
 	.name		= "epwmss5",
 	.class		= &am33xx_epwmss_hwmod_class,
@@ -242,13 +228,6 @@ static struct omap_hwmod am43xx_epwmss5_hwmod = {
 	},
 };
 
-static struct omap_hwmod am43xx_ehrpwm5_hwmod = {
-	.name		= "ehrpwm5",
-	.class		= &am33xx_ehrpwm_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
 static struct omap_hwmod am43xx_spi2_hwmod = {
 	.name		= "spi2",
 	.class		= &am33xx_spi_hwmod_class,
@@ -744,13 +723,6 @@ static struct omap_hwmod_ocp_if am43xx_l4_ls__epwmss3 = {
 	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_ocp_if am43xx_epwmss3__ehrpwm3 = {
-	.master		= &am43xx_epwmss3_hwmod,
-	.slave		= &am43xx_ehrpwm3_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
 static struct omap_hwmod_ocp_if am43xx_l4_ls__epwmss4 = {
 	.master		= &am33xx_l4_ls_hwmod,
 	.slave		= &am43xx_epwmss4_hwmod,
@@ -758,13 +730,6 @@ static struct omap_hwmod_ocp_if am43xx_l4_ls__epwmss4 = {
 	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_ocp_if am43xx_epwmss4__ehrpwm4 = {
-	.master		= &am43xx_epwmss4_hwmod,
-	.slave		= &am43xx_ehrpwm4_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
 static struct omap_hwmod_ocp_if am43xx_l4_ls__epwmss5 = {
 	.master		= &am33xx_l4_ls_hwmod,
 	.slave		= &am43xx_epwmss5_hwmod,
@@ -772,13 +737,6 @@ static struct omap_hwmod_ocp_if am43xx_l4_ls__epwmss5 = {
 	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_ocp_if am43xx_epwmss5__ehrpwm5 = {
-	.master		= &am43xx_epwmss5_hwmod,
-	.slave		= &am43xx_ehrpwm5_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
 static struct omap_hwmod_ocp_if am43xx_l4_ls__mcspi2 = {
 	.master		= &am33xx_l4_ls_hwmod,
 	.slave		= &am43xx_spi2_hwmod,
@@ -919,11 +877,8 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
 	&am43xx_l4_ls__timer10,
 	&am43xx_l4_ls__timer11,
 	&am43xx_l4_ls__epwmss3,
-	&am43xx_epwmss3__ehrpwm3,
 	&am43xx_l4_ls__epwmss4,
-	&am43xx_epwmss4__ehrpwm4,
 	&am43xx_l4_ls__epwmss5,
-	&am43xx_epwmss5__ehrpwm5,
 	&am43xx_l4_ls__mcspi2,
 	&am43xx_l4_ls__mcspi3,
 	&am43xx_l4_ls__mcspi4,
@@ -982,17 +937,8 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
 	&am33xx_l4_ls__spinlock,
 	&am33xx_l4_ls__elm,
 	&am33xx_l4_ls__epwmss0,
-	&am33xx_epwmss0__ecap0,
-	&am33xx_epwmss0__eqep0,
-	&am33xx_epwmss0__ehrpwm0,
 	&am33xx_l4_ls__epwmss1,
-	&am33xx_epwmss1__ecap1,
-	&am33xx_epwmss1__eqep1,
-	&am33xx_epwmss1__ehrpwm1,
 	&am33xx_l4_ls__epwmss2,
-	&am33xx_epwmss2__ecap2,
-	&am33xx_epwmss2__eqep2,
-	&am33xx_epwmss2__ehrpwm2,
 	&am33xx_l3_s__gpmc,
 	&am33xx_l4_ls__mcspi0,
 	&am33xx_l4_ls__mcspi1,
-- 
2.7.0



From shawnguo at kernel.org  Tue May  3 08:58:01 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue,  3 May 2016 23:58:01 +0800
Subject: [GIT PULL 1/6] i.MX soc updates for 4.7
Message-ID: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-soc-4.7

for you to fetch changes up to acc98009b87a811f9f815650274a1044474cd167:

  ARM: imx: always use TWD on IMX6Q (2016-04-12 15:56:55 +0800)

----------------------------------------------------------------
The i.MX SoC updates for 4.7:
 - Allow TWD to be used on UP kernel, as the PREEMPT-RT and cyclictest
   shows that TWD has a slightly better performance than i.MX timer.

----------------------------------------------------------------
Sebastian Andrzej Siewior (1):
      ARM: imx: always use TWD on IMX6Q

 arch/arm/mach-imx/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


From shawnguo at kernel.org  Tue May  3 08:58:02 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue,  3 May 2016 23:58:02 +0800
Subject: [GIT PULL 2/6] i.MX device tree updates for 4.7, with new clocks
In-Reply-To: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
References: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
Message-ID: <1462291086-19925-2-git-send-email-shawnguo@kernel.org>

Hi arm-soc folks,

As per request from Arnd, I collected the device tree updates with new
clock ID dependency on a separate branch imx/dt-clkdep.  The dependant
clock changes has been pulled by clk folks.

Please pull, thanks.

Shawn


The following changes since commit 7b5ca4533f1ac023a16e44a2a1680121272723f9:

  Merge tag 'imx-clk-4.7' into imx/dt-clkdep (2016-04-13 17:36:03 +0800)

are available in the git repository at:


  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-dt-clkdep-4.7

for you to fetch changes up to 77f0862d0d6874a73f83032b7ffd6d204fc8646c:

  ARM: dts: vf610-colibri: enable display controller (2016-04-13 17:42:47 +0800)

----------------------------------------------------------------
The i.MX device tree updates with new clocks for 4.7:
 - Add LCDIF and FlexCAN device support for i.MX7D
 - New support i.MX7D based Nitrogen7 board from Boundary Devices
 - Add display support for vf610-colibri board

----------------------------------------------------------------
Gary Bisson (3):
      ARM: dts: imx7d: add lcdif support
      ARM: dts: imx7d: add flexcan support
      ARM: dts: imx: add Boundary Devices Nitrogen7 board

Stefan Agner (2):
      ARM: dts: vf610: add display nodes
      ARM: dts: vf610-colibri: enable display controller

 arch/arm/boot/dts/Makefile                |   1 +
 arch/arm/boot/dts/imx7d-nitrogen7.dts     | 745 ++++++++++++++++++++++++++++++
 arch/arm/boot/dts/imx7d.dtsi              |  31 ++
 arch/arm/boot/dts/vf-colibri-eval-v3.dtsi |  16 +
 arch/arm/boot/dts/vf-colibri.dtsi         |  33 ++
 arch/arm/boot/dts/vfxxx.dtsi              |  19 +
 6 files changed, 845 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx7d-nitrogen7.dts


From shawnguo at kernel.org  Tue May  3 08:58:03 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue,  3 May 2016 23:58:03 +0800
Subject: [GIT PULL 3/6] i.MX device tree updates for 4.7, take 2
In-Reply-To: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
References: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
Message-ID: <1462291086-19925-3-git-send-email-shawnguo@kernel.org>

Hi arm-soc folks,

This is the second round of my imx/dt branch pull request.  It's based
on the first take [1], which has been pulled some days ago.

Please pull, thanks.

Shawn

[1] http://thread.gmane.org/gmane.linux.ports.arm.kernel/493365


The following changes since commit 880e1509db9732d5696d2a092e9bd61d80ad00be:

  ARM: dts: imx6qdl-udoo: add 7 inch LCD touchscreen panel support (2016-04-18 12:54:21 +0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-dt-4.7-2

for you to fetch changes up to 194521f72380d0e78caa71013e9e7de1703d8c85:

  ARM: mx5: dts: Enable USB OTG on M53EVK (2016-05-03 21:10:11 +0800)

----------------------------------------------------------------
The i.MX device tree updates for 4.7, take 2:
 - Update display clock configuration for imx6q-b850v3 board
 - Use watchdog external reset for imx6q-ba16 board
 - Update operating points settings for i.MX6UL/SX/DL
 - New board support: imx6ul-pico-hobbit and imx6q-marsboard
 - Add SAI audio support for imx6ul-14x14-evk board
 - Enable USB OTG support for M53EVK board
 - A couple of fixes on DTC warnings

----------------------------------------------------------------
Akshay Bhat (4):
      ARM: dts: imx6q-b850v3: Remove ldb panel
      ARM: dts: imx6q-b850v3: Update display clock source
      ARM: dts: imx: b450/b650v3: Move ldb_di clk assignment
      ARM: dts: imx6q-ba16: use wdog external reset

Fabio Estevam (9):
      ARM: dts: imx6ul: Fix operating points
      ARM: dts: imx6sx: Add 198MHz operating point
      ARM: dts: imx6dl: Fix the VDD_ARM_CAP voltage for 396MHz operation
      ARM: dts: imx6: Do not hardcode the CLKO clock
      ARM: dts: imx6ul-pico-hobbit: Add initial support
      ARM: dts: imx28-m28: Remove unneeded partition nodes
      ARM: dts: imx6sx-sdb: Add 198MHz operational point
      ARM: dts: imx6qdl: Remove unneeded unit-addresses
      ARM: dts: imx6ul-14x14-evk: Add audio support

Joshua Clayton (1):
      ARM: dts: imx6: fix dtc warnings for ipu endpoints

Marcel Ziswiler (1):
      ARM: dts: imx6: apalis: parallel lcd display support on ixora

Marek Vasut (1):
      ARM: mx5: dts: Enable USB OTG on M53EVK

Sergio Prado (1):
      ARM: dts: imx6: Add dts for Embest MarS Board

 arch/arm/boot/dts/Makefile                   |   2 +
 arch/arm/boot/dts/imx28-m28.dtsi             |  26 --
 arch/arm/boot/dts/imx53-m53evk.dts           |  21 +-
 arch/arm/boot/dts/imx6dl-riotboard.dts       |   2 +-
 arch/arm/boot/dts/imx6dl.dtsi                |   2 +-
 arch/arm/boot/dts/imx6q-apalis-ixora.dts     |  45 +++
 arch/arm/boot/dts/imx6q-b450v3.dts           |   5 +-
 arch/arm/boot/dts/imx6q-b650v3.dts           |   5 +-
 arch/arm/boot/dts/imx6q-b850v3.dts           |  33 +-
 arch/arm/boot/dts/imx6q-ba16.dtsi            |   1 +
 arch/arm/boot/dts/imx6q-gw5400-a.dts         |   2 +-
 arch/arm/boot/dts/imx6q-marsboard.dts        | 403 +++++++++++++++++++++
 arch/arm/boot/dts/imx6q-tbs2910.dts          |   2 +-
 arch/arm/boot/dts/imx6q.dtsi                 |  18 +-
 arch/arm/boot/dts/imx6qdl-apalis.dtsi        |   2 +-
 arch/arm/boot/dts/imx6qdl-apf6dev.dtsi       |   2 +-
 arch/arm/boot/dts/imx6qdl-gw52xx.dtsi        |   2 +-
 arch/arm/boot/dts/imx6qdl-gw53xx.dtsi        |   2 +-
 arch/arm/boot/dts/imx6qdl-gw54xx.dtsi        |   2 +-
 arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi     |   2 +-
 arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi |   2 +-
 arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi    |   2 +-
 arch/arm/boot/dts/imx6qdl-rex.dtsi           |   2 +-
 arch/arm/boot/dts/imx6qdl-sabrelite.dtsi     |   2 +-
 arch/arm/boot/dts/imx6qdl-udoo.dtsi          |   2 +-
 arch/arm/boot/dts/imx6qdl-wandboard.dtsi     |   2 +-
 arch/arm/boot/dts/imx6qdl.dtsi               |  32 +-
 arch/arm/boot/dts/imx6sx-sdb.dts             |   2 +
 arch/arm/boot/dts/imx6sx.dtsi                |   2 +
 arch/arm/boot/dts/imx6ul-14x14-evk.dts       |  74 ++++
 arch/arm/boot/dts/imx6ul-pico-hobbit.dts     | 516 +++++++++++++++++++++++++++
 arch/arm/boot/dts/imx6ul.dtsi                |  12 +-
 32 files changed, 1130 insertions(+), 99 deletions(-)
 create mode 100644 arch/arm/boot/dts/imx6q-marsboard.dts
 create mode 100644 arch/arm/boot/dts/imx6ul-pico-hobbit.dts


From shawnguo at kernel.org  Tue May  3 08:58:04 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue,  3 May 2016 23:58:04 +0800
Subject: [GIT PULL 4/6] Freescale/NXP arm64 device tree updates for 4.7
In-Reply-To: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
References: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
Message-ID: <1462291086-19925-4-git-send-email-shawnguo@kernel.org>

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-dt64-4.7

for you to fetch changes up to bb4b4e93febc139003e2af2f36e438df58b4803c:

  arm64: dts: ls2080a: fsl-mc dt node updates (2016-04-26 11:25:44 +0800)

----------------------------------------------------------------
The Freescale/NXP arm64 device tree updates for 4.7:
 - New board support of LS1043a-QDS from Freescale/NXP
 - Add new compatible for LS1043A and LS2080A GPIO devices
 - Update device tree bindings and sources for LS2080A fsl-mc device
 - Update QSPI and DSPI support on LS1043A and LS2080A

----------------------------------------------------------------
Hou Zhiqiang (1):
      Documentation: DT: Add entry for Freescale LS1043a-QDS board

Liu Gang (2):
      arm64: dts: ls1043a: Add compatible "fsl,qoriq-gpio" for ls1043a gpio nodes
      arm64: dts: ls2080a: Add compatible "fsl,ls2080a-gpio" for ls2080a gpio nodes

Shaohui Xie (1):
      arm64: dts: add LS1043a-QDS board support

Stuart Yoder (2):
      Documentation: fsl-mc: binding updates for MSIs, ranges, PHYs
      arm64: dts: ls2080a: fsl-mc dt node updates

Yuan Yao (4):
      Documentation: fsl: dspi: Add fsl,ls2080a-dspi compatible string
      arm64: dts: ls2080a: update the DTS for QSPI and DSPI support
      Documentation: fsl-quadspi: Add fsl,ls1043a-qspi compatible string
      arm64: dts: ls1043a: add the DTS node for QSPI support

Yunhui Cui (1):
      arm64: dts: ls1043a-rdb: add the DTS for DSPI support

 Documentation/devicetree/bindings/arm/fsl.txt      |   4 +
 .../devicetree/bindings/misc/fsl,qoriq-mc.txt      |  81 ++++++++-
 .../devicetree/bindings/mtd/fsl-quadspi.txt        |   3 +-
 .../devicetree/bindings/spi/spi-fsl-dspi.txt       |   5 +-
 arch/arm64/boot/dts/freescale/Makefile             |   3 +-
 arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts  | 181 +++++++++++++++++++++
 arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts  |  13 ++
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi     |  22 ++-
 arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts  |   9 +-
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi     | 110 ++++++++++++-
 10 files changed, 416 insertions(+), 15 deletions(-)
 create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts


From shawnguo at kernel.org  Tue May  3 08:58:05 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue,  3 May 2016 23:58:05 +0800
Subject: [GIT PULL 5/6] i.MX defconfig updates for 4.7
In-Reply-To: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
References: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
Message-ID: <1462291086-19925-5-git-send-email-shawnguo@kernel.org>

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-defconfig-4.7

for you to fetch changes up to 2ead04d9d69ebded61da063cb5a8ade72da6c8f5:

  ARM: imx_v6_v7_defconfig: add CONFIG_MICREL_PHY (2016-05-03 20:58:07 +0800)

----------------------------------------------------------------
The i.MX defconfig updates for 4.7:
 - Update multi_v5_defconfig for i.MX21/27 and systemd support
 - Update imx_v6_v7_defconfig to support devices found on various i.MX6
   board: FT5x06 and TSC2004 touch, I2C GPIO, MICREL PHY and M41T80 RTC

----------------------------------------------------------------
Gary Bisson (3):
      ARM: imx_v6_v7_defconfig: add FT5x06 and TSC2004 touch support
      ARM: imx_v6_v7_defconfig: add CONFIG_I2C_MUX_GPIO
      ARM: imx_v6_v7_defconfig: add CONFIG_RTC_DRV_M41T80

Jan Luebbe (2):
      ARM: multi_v5_defconfig: Enable support for MX21/MX27
      ARM: multi_v5_defconfig: Enable recommended options for systemd

Marcel Ziswiler (2):
      ARM: imx_v6_v7_defconfig: add CONFIG_I2C_GPIO
      ARM: imx_v6_v7_defconfig: add CONFIG_MICREL_PHY

 arch/arm/configs/imx_v6_v7_defconfig |  6 ++++++
 arch/arm/configs/multi_v5_defconfig  | 21 ++++++++++++++++++---
 2 files changed, 24 insertions(+), 3 deletions(-)


From shawnguo at kernel.org  Tue May  3 08:58:06 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Tue,  3 May 2016 23:58:06 +0800
Subject: [GIT PULL 6/6] Freescale/NXP arm64 defconfig updates for 4.7
In-Reply-To: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
References: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
Message-ID: <1462291086-19925-6-git-send-email-shawnguo@kernel.org>

Hi arm-soc folks,

Different from above 5 pull requests that start off 4.6-rc1, this one
is based on 4.6-rc2, because commit 431597bb9556 ("arm64: defconfig:
updates for 4.6") changes arch/arm64/configs/defconfig dramatically
and went into 4.6-rc2.  I have to base my branch onto 4.6-rc2 to avoid
manual merging.

Please pull, thanks.

Shawn


The following changes since commit 9735a22799b9214d17d3c231fe377fc852f042e9:

  Linux 4.6-rc2 (2016-04-03 09:09:40 -0500)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-defconfig64-4.7

for you to fetch changes up to 3892132c2716e2747e562dd9a4c025387c19c329:

  arm64: defconfig: enable freescale/nxp config options (2016-04-27 10:12:34 +0800)

----------------------------------------------------------------
The arm64 defconfig update for Freescale/NXP support:
 - Clean up defconfig with savedefconfig
 - Enable 48-bit virtual address support
 - Enable driver support for various Freescale/NXP devices

----------------------------------------------------------------
Stuart Yoder (3):
      arm64: defconfig: cleanup the defconfig
      arm64: defconfig: enable 48-bit virtual addresses
      arm64: defconfig: enable freescale/nxp config options

 arch/arm64/configs/defconfig | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)


From andre.przywara at arm.com  Tue May  3 09:07:29 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue,  3 May 2016 17:07:29 +0100
Subject: [PATCH] KVM: arm/arm64: new-vgic: add proper GICv2 CPU interface
 userland access
In-Reply-To: <57287A89.9010809@arm.com>
References: <57287A89.9010809@arm.com>
Message-ID: <1462291649-9906-1-git-send-email-andre.przywara@arm.com>

Although the actual register access was wired, the availability check
for the GICv2 CPU interface register interface was not - leading to
any attempt of saving or restoring GICv2 CPU i/f registers to fail.

This patch fixes this by modelling the CPU i/f registers similarily to
the distributor registers, thereby piggy backing on the existing
distributor save/restore code to do the heavy lifting.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Hi,

this is a fix for the missing CPU i/f migration that Marc spotted.
In a repost I will merge this somehow into the existing patches, but
for now this goes on top of the series.
Can any of you have a look whether this is the right way to go?

Cheers,
Andre.

 virt/kvm/arm/vgic/vgic-kvm-device.c |  71 +--------------------
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 122 +++++++++++++++++++++++++++++++++---
 virt/kvm/arm/vgic/vgic.h            |   2 +
 3 files changed, 115 insertions(+), 80 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index eaf5c1d..657552d 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -20,8 +20,6 @@
 #include <linux/irqchip/arm-gic.h>
 #include "vgic.h"
 
-#define GICC_ARCH_VERSION_V2		0x2
-
 /* common helpers */
 
 static int vgic_ioaddr_overlap(struct kvm *kvm)
@@ -255,69 +253,6 @@ void kvm_register_vgic_device(unsigned long type)
 	}
 }
 
-static u32 vgic_read_vcpuif(struct kvm_vcpu *vcpu, int offset)
-{
-	struct vgic_vmcr vmcr;
-	u32 *field;
-
-	switch (offset) {
-	case GIC_CPU_CTRL:
-		field = &vmcr.ctlr;
-		break;
-	case GIC_CPU_PRIMASK:
-		field = &vmcr.pmr;
-		break;
-	case GIC_CPU_BINPOINT:
-		field = &vmcr.bpr;
-		break;
-	case GIC_CPU_ALIAS_BINPOINT:
-		field = &vmcr.abpr;
-		break;
-	case GIC_CPU_IDENT:
-		return (PRODUCT_ID_KVM << 20) |
-		       (GICC_ARCH_VERSION_V2 << 16) |
-		       (IMPLEMENTER_ARM << 0);
-	default:
-		return 0;
-	}
-
-	vgic_get_vmcr(vcpu, &vmcr);
-
-	return *field;
-}
-
-static bool vgic_write_vcpuif(struct kvm_vcpu *vcpu, int offset, u32 value)
-{
-	struct vgic_vmcr vmcr;
-	u32 *field;
-
-	switch (offset) {
-	case GIC_CPU_CTRL:
-		field = &vmcr.ctlr;
-		break;
-	case GIC_CPU_PRIMASK:
-		field = &vmcr.pmr;
-		break;
-	case GIC_CPU_BINPOINT:
-		field = &vmcr.bpr;
-		break;
-	case GIC_CPU_ALIAS_BINPOINT:
-		field = &vmcr.abpr;
-		break;
-	default:
-		return false;
-	}
-
-	vgic_get_vmcr(vcpu, &vmcr);
-	if (*field == value)
-		return false;
-
-	*field = value;
-	vgic_set_vmcr(vcpu, &vmcr);
-
-	return true;
-}
-
 /** vgic_attr_regs_access: allows user space to read/write VGIC registers
  *
  * @dev: kvm device handle
@@ -366,11 +301,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		ret = 0;
-		if (is_write)
-			vgic_write_vcpuif(vcpu, addr, *reg);
-		else
-			*reg = vgic_read_vcpuif(vcpu, addr);
+		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
 		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index f2a8efe..276c3a0 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -206,6 +206,74 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
 	}
 }
 
+#define GICC_ARCH_VERSION_V2	0x2
+
+/* These are for userland accesses only, there is no guest-facing emulation. */
+static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
+					   gpa_t addr, unsigned int len)
+{
+	struct vgic_vmcr vmcr;
+	u32 *field;
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		field = &vmcr.ctlr;
+		break;
+	case GIC_CPU_PRIMASK:
+		field = &vmcr.pmr;
+		break;
+	case GIC_CPU_BINPOINT:
+		field = &vmcr.bpr;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		field = &vmcr.abpr;
+		break;
+	case GIC_CPU_IDENT:
+		return extract_bytes((PRODUCT_ID_KVM << 20) |
+				     (GICC_ARCH_VERSION_V2 << 16) |
+				     (IMPLEMENTER_ARM << 0),
+				     addr & 3, len);
+	default:
+		return 0;
+	}
+
+	vgic_get_vmcr(vcpu, &vmcr);
+
+	return extract_bytes(*field, addr & 3, len);
+}
+
+static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
+				   gpa_t addr, unsigned int len,
+				   unsigned long val)
+{
+	struct vgic_vmcr vmcr;
+	u32 *field;
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		field = &vmcr.ctlr;
+		break;
+	case GIC_CPU_PRIMASK:
+		field = &vmcr.pmr;
+		break;
+	case GIC_CPU_BINPOINT:
+		field = &vmcr.bpr;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		field = &vmcr.abpr;
+		break;
+	default:
+		return;
+	}
+
+	vgic_get_vmcr(vcpu, &vmcr);
+	if (*field == val)
+		return;
+
+	*field = val;
+	vgic_set_vmcr(vcpu, &vmcr);
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
@@ -237,6 +305,21 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16),
 };
 
+static const struct vgic_register_region vgic_v2_cpu_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_CTRL,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_PRIMASK,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ALIAS_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ACTIVEPRIO,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_IDENT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+};
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
 {
 	dev->regions = vgic_v2_dist_registers;
@@ -253,23 +336,18 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
  * have to set up a buffer similar to what would have happened if a guest MMIO
  * access occurred, including doing endian conversions on BE systems.
  */
-int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
-			int offset, u32 *val)
+static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
+			bool is_write, int offset, u32 *val)
 {
 	unsigned int len = 4;
 	u8 buf[4];
 	int ret;
 
-	struct vgic_io_device dev = {
-		.regions = vgic_v2_dist_registers,
-		.nr_regions = ARRAY_SIZE(vgic_v2_dist_registers),
-	};
-
 	if (is_write) {
 		vgic_data_host_to_mmio_bus(buf, len, *val);
-		ret = kvm_io_gic_ops.write(vcpu, &dev.dev, offset, len, buf);
+		ret = kvm_io_gic_ops.write(vcpu, &dev->dev, offset, len, buf);
 	} else {
-		ret = kvm_io_gic_ops.read(vcpu, &dev.dev, offset, len, buf);
+		ret = kvm_io_gic_ops.read(vcpu, &dev->dev, offset, len, buf);
 		if (!ret)
 			*val = vgic_data_mmio_bus_to_host(buf, len);
 	}
@@ -277,6 +355,28 @@ int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 	return ret;
 }
 
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_cpu_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
+
+int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			 int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_dist_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_dist_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
+
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 {
 	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
@@ -292,7 +392,9 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		return -ENXIO;		/* TODO: describe CPU i/f regs also */
+		regions = vgic_v2_cpu_registers;
+		nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers);
+		break;
 	default:
 		return -ENXIO;
 	}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index f970e3e..d1de87f 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -38,6 +38,8 @@ void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val);
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
-- 
2.7.3



From robh at kernel.org  Tue May  3 09:14:01 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 3 May 2016 11:14:01 -0500
Subject: [PATCH net v3 4/5] dt: cpsw: phy-handle, phy_id, and fixed-link
 are mutually exclusive
In-Reply-To: <1461807767-4563-1-git-send-email-drivshin.allworx@gmail.com>
References: <1461805808-4102-1-git-send-email-drivshin.allworx@gmail.com>
 <1461807767-4563-1-git-send-email-drivshin.allworx@gmail.com>
Message-ID: <20160503161401.GA32607@rob-hp-laptop>

On Wed, Apr 27, 2016 at 09:42:47PM -0400, David Rivshin (Allworx) wrote:
> From: David Rivshin <drivshin at allworx.com>
> 
> The phy-handle, phy_id, and fixed-link properties are mutually exclusive,
> and only one need be specified. Make this clear in the binding doc.
> 
> Also mark the phy_id property as deprecated, as phy-handle should be
> used instead.
> 
> Signed-off-by: David Rivshin <drivshin at allworx.com>
> ---
> 
> Changes since v2 [1]:
> - split from previous patch 2
> - marked the phy_id property as deprecated [3]
> - removed Rob Herring's Acked-by due to above change
> 
> Changes since v1 [2]:
> - Rebased (no conflicts)
> - Added Tested-by from Nicolas Chauvet
> - Added Acked-by from Rob Herring for the binding change
> 
> [1] http://patchwork.ozlabs.org/patch/613260/
> [2] http://patchwork.ozlabs.org/patch/560324/
> [3] https://lkml.org/lkml/2016/4/22/494
> 
> 
>  Documentation/devicetree/bindings/net/cpsw.txt | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

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


From marc.zyngier at arm.com  Tue May  3 09:16:28 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 17:16:28 +0100
Subject: [PATCH v2 18/54] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <1461861973-26464-19-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-19-git-send-email-andre.przywara@arm.com>
Message-ID: <5728CEDC.9080308@arm.com>

On 28/04/16 17:45, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> As the GICv3 virtual interface registers differ from their GICv2
> siblings, we need different handlers for processing maintenance
> interrupts and reading/writing to the LRs.
> Implement the respective handler functions and connect them to
> existing code to be called if the host is using a GICv3.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - remove outdated comment about the dist_lock
> - add WARN_ON about LR_STATE not being 0 in maintenance interrupts
> 
> Changelog v1 .. v2:
> - inject the IRQ priority into the list register
> 
>  include/linux/irqchip/arm-gic-v3.h |   1 +
>  virt/kvm/arm/vgic/vgic-v3.c        | 169 +++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.c           |  25 ++++--
>  virt/kvm/arm/vgic/vgic.h           |  29 +++++++
>  4 files changed, 219 insertions(+), 5 deletions(-)
>  create mode 100644 virt/kvm/arm/vgic/vgic-v3.c
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index d5d798b..56fd2c5 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -275,6 +275,7 @@
>  #define ICH_LR_ACTIVE_BIT		(1ULL << 63)
>  #define ICH_LR_PHYS_ID_SHIFT		32
>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
> +#define ICH_LR_PRIORITY_SHIFT		48
>  
>  #define ICH_MISR_EOI			(1 << 0)
>  #define ICH_MISR_U			(1 << 1)
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> new file mode 100644
> index 0000000..461229b
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -0,0 +1,169 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * 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/irqchip/arm-gic-v3.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <linux/irqchip/arm-gic.h>

This last line is definitely a (copy-paste) bug. We should never include
both GIC headers in the same file. Can you please drop that line and
have the following hunk instead?

+/* These are for GICv2 emulation only */
+#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
+#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
+#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
+#define ICH_LR_VIRTUALID_MASK		(BIT_ULL(32) - 1)
+

which is similar to what we have in the old implementation, for the
exact same reason.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From robh at kernel.org  Tue May  3 09:24:44 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 3 May 2016 11:24:44 -0500
Subject: [PATCH net-next 0/4] net: hns: update DT properties according to
 Rob's comments
In-Reply-To: <20160429.133949.1719521222260369497.davem@davemloft.net>
References: <1461827344-52230-1-git-send-email-Yisen.Zhuang@huawei.com>
 <20160429.133949.1719521222260369497.davem@davemloft.net>
Message-ID: <20160503162444.GA4087@rob-hp-laptop>

On Fri, Apr 29, 2016 at 01:39:49PM -0400, David Miller wrote:
> From: Yisen Zhuang <Yisen.Zhuang at huawei.com>
> Date: Thu, 28 Apr 2016 15:09:00 +0800
> 
> > There are some inappropriate properties definition in hns DT. We update the definition
> > according to Rob's review comments and fix some typos in binding.
> > 
> > For more details, please see individual patches.
> 
> Series applied, thanks.

It would be nice to review patches addressing my comments before they 
get applied. Can you please give series with DT bindings a few more days 
for review before applying.

Rob


From broonie at kernel.org  Tue May  3 09:29:38 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 3 May 2016 17:29:38 +0100
Subject: [RFC PATCH 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
Message-ID: <20160503162938.GT6292@sirena.org.uk>

On Sat, Apr 30, 2016 at 11:15:34PM +0200, Robert Jarzmik wrote:
> AC97 is a bus for sound usage. It enables for a AC97 AC-Link to link one
> controller to 0 to 4 AC97 codecs.

> The goal of this new implementation is to implement a device/driver
> model for AC97, with an automatic scan of the bus and automatic
> discovery of AC97 codec devices.

I think this is basically what I was thinking of, yes.  One thing we'll
need to do is work out how to handle systems that need some explicit
action to start clocks for the bus clock, though they were never very
common and it's entirely possible nobody cares any more so perhaps we
just punt and see if anyone notices for now.

> +int ac97_digital_controller_register(const struct ac97_controller_ops *ops,
> +				     struct device *dev);
> +int ac97_digital_controller_unregister(const struct device *dev);

Why "digital"? 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160503/22fb87c5/attachment.sig>

From davem at davemloft.net  Tue May  3 09:37:50 2016
From: davem at davemloft.net (David Miller)
Date: Tue, 03 May 2016 12:37:50 -0400 (EDT)
Subject: [PATCH net-next 0/4] net: hns: update DT properties according
 to Rob's comments
In-Reply-To: <20160503162444.GA4087@rob-hp-laptop>
References: <1461827344-52230-1-git-send-email-Yisen.Zhuang@huawei.com>
 <20160429.133949.1719521222260369497.davem@davemloft.net>
 <20160503162444.GA4087@rob-hp-laptop>
Message-ID: <20160503.123750.1357220927373693471.davem@davemloft.net>

From: Rob Herring <robh at kernel.org>
Date: Tue, 3 May 2016 11:24:44 -0500

> On Fri, Apr 29, 2016 at 01:39:49PM -0400, David Miller wrote:
>> From: Yisen Zhuang <Yisen.Zhuang at huawei.com>
>> Date: Thu, 28 Apr 2016 15:09:00 +0800
>> 
>> > There are some inappropriate properties definition in hns DT. We update the definition
>> > according to Rob's review comments and fix some typos in binding.
>> > 
>> > For more details, please see individual patches.
>> 
>> Series applied, thanks.
> 
> It would be nice to review patches addressing my comments before they 
> get applied. Can you please give series with DT bindings a few more days 
> for review before applying.

I can't go more than a day or so days, I refuse to let patches rot in
my backlog for more than that.  I get sometimes a hundred new patch
submissions a day and what you are asking me to do would make maintainence
untenable for everyone, sorry.

Just be quicker on the review, then there are no problems.


From robh at kernel.org  Tue May  3 09:40:19 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 3 May 2016 11:40:19 -0500
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
Message-ID: <20160503164019.GA1604@rob-hp-laptop>

On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:
> The EBI (External Bus Interface) is used to access external peripherals
> (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
> Each device is assigned a CS line and an address range and can have its
> own configuration (timings, access mode, bus width, ...).
> This driver provides a generic DT binding to configure a device according
> to its requirements.
> For specific device controllers (like the NAND one) the SMC timings
> should be configured by the controller driver through the matrix and smc
> syscon regmaps.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> ---
>  .../bindings/memory-controllers/atmel,ebi.txt      | 136 +++++++++++++++++++++
>  1 file changed, 136 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> 
> diff --git a/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> new file mode 100644
> index 0000000..a6dca5c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> @@ -0,0 +1,136 @@
> +* Device tree bindings for Atmel EBI
> +
> +The External Bus Interface (EBI) controller is a bus where you can connect
> +asynchronous (NAND, NOR, SRAM, ....) and synchronous memories (SDR/DDR SDRAMs).
> +The EBI provides a glue-less interface to asynchronous memories through the SMC
> +(Static Memory Controller).
> +
> +Required properties:
> +
> +- compatible:		"atmel,at91sam9260-ebi"
> +			"atmel,at91sam9261-ebi"
> +			"atmel,at91sam9263-ebi0"
> +			"atmel,at91sam9263-ebi1"

What are the differences between 0 and 1?

> +			"atmel,at91sam9rl-ebi"
> +			"atmel,at91sam9g45-ebi"
> +			"atmel,at91sam9x5-ebi"
> +			"atmel,sama5d3-ebi"
> +
> +- reg:			Contains offset/length value for EBI memory mapping.
> +			This property might contain several entries if the EBI
> +			memory range is not contiguous
> +
> +- #address-cells:	Must be 2.
> +			The first cell encodes the CS.
> +			The second cell encode the offset into the CS memory
> +			range.
> +
> +- #size-cells:		Must be set to 1.
> +
> +- ranges:		Encodes CS to memory region association.
> +
> +- clocks:		Clock feeding the EBI controller.
> +			See clock-bindings.txt
> +
> +Children device nodes are representing device connected to the EBI bus.
> +
> +Required device node properties:
> +
> +- #reg:			Contains the chip-select id, the offset and the length

s/#reg/reg/

> +			of the memory region requested by the device.
> +
> +EBI bus configuration associated with specific chip-select will be defined in
> +the configs subnode. This configs node will in turn contain several subnodes
> +named config-<cs-id>, each of them containing the following properties.

This is a bit unusual. Why not just part of the child device nodes?

> +
> +Optional config-<cs-id> node properties:
> +
> +- atmel,bus-width:		width of the asynchronous device's data bus
> +				8, 16 or 32.
> +				Default to 8 when undefined.
> +
> +- atmel,byte-access-type	"write" or "select" (see Atmel datasheet).
> +				Default to "select" when undefined.
> +
> +- atmel,read-mode		"nrd" or "ncs".
> +				Default to "ncs" when undefined.
> +
> +- atmel,write-mode		"nwe" or "ncs".
> +				Default to "ncs" when undefined.
> +
> +- atmel,exnw-mode		"disabled", "frozen" or "ready".
> +				Default to "disabled" when undefined.
> +
> +- atmel,page-mode		enable page mode if present. The provided value
> +				defines the page size (supported values: 4, 8,
> +				16 and 32).
> +
> +- atmel,tdf-mode:		"normal" or "optimized". When set to

This should be boolean.

> +				"optimized" the data float time is optimized
> +				depending on the next device being accessed
> +				(next device setup time is subtracted to the
> +				current device data float time).
> +				Default to "normal" when undefined.
> +
> +Mandatory timings expressed in nanoseconds (see Atmel datasheet for a full
> +description).

Required first, then optional properties please.

> +
> +- atmel,ncs-rd-setup-ns
> +- atmel,nrd-setup-ns
> +- atmel,ncs-wr-setup-ns
> +- atmel,nwe-setup-ns
> +- atmel,ncs-rd-pulse-ns
> +- atmel,nrd-pulse-ns
> +- atmel,ncs-wr-pulse-ns
> +- atmel,nwe-pulse-ns
> +- atmel,nwe-cycle-ns
> +- atmel,nrd-cycle-ns
> +- atmel,tdf-ns
> +
> +Example:
> +
> +	ebi: ebi at 10000000 {
> +		compatible = "atmel,sama5d3-ebi";
> +		#address-cells = <2>;
> +		#size-cells = <1>;

> +		atmel,smc = <&hsmc>;
> +		atmel,matrix = <&matrix>;

What are these? 

> +		reg = <0x10000000 0x10000000
> +		       0x40000000 0x30000000>;
> +		ranges = <0x0 0x0 0x10000000 0x10000000
> +			  0x1 0x0 0x40000000 0x10000000
> +			  0x2 0x0 0x50000000 0x10000000
> +			  0x3 0x0 0x60000000 0x10000000>;
> +		clocks = <&mck>;
> +
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_ebi_addr>;

Not documented.

> +
> +		configs {
> +			config-0 {
> +				atmel,read-mode = "nrd";
> +				atmel,write-mode = "nwe";
> +				atmel,bus-width = <16>;
> +				atmel,ncs-rd-setup-ns = <0>;
> +				atmel,ncs-wr-setup-ns = <0>;
> +				atmel,nwe-setup-ns = <8>;
> +				atmel,nrd-setup-ns = <16>;
> +				atmel,ncs-rd-pulse-ns = <84>;
> +				atmel,ncs-wr-pulse-ns = <84>;
> +				atmel,nrd-pulse-ns = <76>;
> +				atmel,nwe-pulse-ns = <76>;
> +				atmel,nrd-cycle-ns = <107>;
> +				atmel,nwe-cycle-ns = <84>;
> +				atmel,tdf-ns = <16>;
> +			};
> +		};
> +
> +		nor: flash at 0,0 {
> +			compatible = "cfi-flash";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			reg = <0x0 0x0 0x1000000>;
> +			bank-width = <2>;
> +		};
> +	};
> +
> -- 
> 2.7.4
> 


From tony at atomide.com  Tue May  3 09:43:23 2016
From: tony at atomide.com (Tony Lindgren)
Date: Tue, 3 May 2016 09:43:23 -0700
Subject: [PATCH v2 2/3] ARM: DRA7x: dts: Update the OSC_32K_CLK frequency
In-Reply-To: <5728A81F.4050906@garmin.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
 <1462209123-7332-3-git-send-email-Linux.HWI@garmin.com>
 <57285E66.2000708@ti.com> <5728A81F.4050906@garmin.com>
Message-ID: <20160503164323.GN5995@atomide.com>

* J.D. Schroeder <Linux.HWI at garmin.com> [160503 06:32]:
> On 05/03/2016 03:16 AM, Tero Kristo wrote:
> > On 02/05/16 20:12, J.D. Schroeder wrote:
> >> From: "J.D. Schroeder" <jay.schroeder at garmin.com>
> >>
> >> This commit updates the OSC_32K_CLK (secure_32k_clk_src_ck) frequency
> >> from the precise 32kHz frequency (i.e., 32.768 kHz) to a more
> >> accurate frequency of ~34.6 kHz. Actual measured frequencies of the
> >> clock vary from processor to processor anywhere from 34.4 kHz up to
> >> 34.8 kHz. Note that the ~34 kHz frequency clock is generated
> >> internally by the processor, not an input to the processor. This
> >> change makes it more clear that the consumer of the
> >> secure_32k_clk_src_ck will not get a precise 32.768 kHz frequency
> >> output.
> >>
> >> Signed-off-by: J.D. Schroeder <jay.schroeder at garmin.com>
> >> Reviewed-by: Trenton Andres <trenton.andres at garmin.com>
> >> ---
> >>   arch/arm/boot/dts/dra7xx-clocks.dtsi | 2 +-
> >>   1 file changed, 1 insertion(+), 1 deletion(-)
> >>
> >> diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi
> >> b/arch/arm/boot/dts/dra7xx-clocks.dtsi
> >> index 3f0c61d..f7ec976 100644
> >> --- a/arch/arm/boot/dts/dra7xx-clocks.dtsi
> >> +++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi
> >> @@ -95,7 +95,7 @@
> >>       secure_32k_clk_src_ck: secure_32k_clk_src_ck {
> >>           #clock-cells = <0>;
> >>           compatible = "fixed-clock";
> >> -        clock-frequency = <32768>;
> >> +        clock-frequency = <34600>; /* approximate frequency */
> >>       };
> >>
> >>       sys_clk32_crystal_ck: sys_clk32_crystal_ck {
> >>
> > 
> > I still don't agree with this patch. The actual frequency can drift much more,
> > you are just seeing this number at your setup.
> 
> Yes, it can drift significantly from processor to processor. Do you agree that
> this frequency is closer to what can be expected than 32768 Hz?
> 
> Like I said, I would have renamed the clock also but I opted to go the less
> obtrusive route while still helping others that might think they can
> reasonably use this clock in their design as a 32768 Hz clock source. Perhaps
> my comment and selection of the approximate frequency is not the best (I'm
> open for suggestions). However, I do think this change is an improvement and
> clarifying change to what is currently present in the clock description.

Does a fixed divider calculation of input * (32768 / 0x27e6) make sense
here too as pointed out earlier by Matthijs for the ti81xx?

Regards,

Tony


From mike at mikebwilliams.com  Tue May  3 09:44:21 2016
From: mike at mikebwilliams.com (Mike Williams)
Date: Tue,  3 May 2016 12:44:21 -0400
Subject: [PATCH 0/3] ARM: at91/dt: add SAMA5 trng nodes
Message-ID: <1462293864-32551-1-git-send-email-mike@mikebwilliams.com>

Adds support for the true hardware random number generator.

Tested on a SAMA5D3 Xplained board.

Mike Williams (3):
  ARM: at91/dt: sama5d2: add trng node
  ARM: at91/dt: sama5d3: add trng node
  ARM: at91/dt: sama5d4: add trng node

 arch/arm/boot/dts/sama5d2.dtsi | 7 +++++++
 arch/arm/boot/dts/sama5d3.dtsi | 7 +++++++
 arch/arm/boot/dts/sama5d4.dtsi | 7 +++++++
 3 files changed, 21 insertions(+)

-- 
2.5.0



From mike at mikebwilliams.com  Tue May  3 09:44:22 2016
From: mike at mikebwilliams.com (Mike Williams)
Date: Tue,  3 May 2016 12:44:22 -0400
Subject: [PATCH 1/3] ARM: at91/dt: sama5d2: add trng node
In-Reply-To: <1462293864-32551-1-git-send-email-mike@mikebwilliams.com>
References: <1462293864-32551-1-git-send-email-mike@mikebwilliams.com>
Message-ID: <1462293864-32551-2-git-send-email-mike@mikebwilliams.com>

Add node to support SAMA5D2 hardware random number generator.
---
 arch/arm/boot/dts/sama5d2.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 78996bd..af9a5f8 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -1127,6 +1127,13 @@
 				status = "disabled";
 			};
 
+			trng at fc01c000 {
+				compatible = "atmel,at91sam9g45-trng";
+				reg = <0xfc01c000 0x4000>;
+				interrupts = <47 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&trng_clk>;
+			};
+
 			aic: interrupt-controller at fc020000 {
 				#interrupt-cells = <3>;
 				compatible = "atmel,sama5d2-aic";
-- 
2.5.0



From mike at mikebwilliams.com  Tue May  3 09:44:23 2016
From: mike at mikebwilliams.com (Mike Williams)
Date: Tue,  3 May 2016 12:44:23 -0400
Subject: [PATCH 2/3] ARM: at91/dt: sama5d3: add trng node
In-Reply-To: <1462293864-32551-1-git-send-email-mike@mikebwilliams.com>
References: <1462293864-32551-1-git-send-email-mike@mikebwilliams.com>
Message-ID: <1462293864-32551-3-git-send-email-mike@mikebwilliams.com>

Add node to support SAMA5D3 hardware random number generator.
---
 arch/arm/boot/dts/sama5d3.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index a532791..c346aa9 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -426,6 +426,13 @@
 				clock-names = "tdes_clk";
 			};
 
+			trng at f8040000 {
+				compatible = "atmel,at91sam9g45-trng";
+				reg = <0xf8040000 0x4000>;
+				interrupts = <45 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&trng_clk>;
+			};
+
 			dma0: dma-controller at ffffe600 {
 				compatible = "atmel,at91sam9g45-dma";
 				reg = <0xffffe600 0x200>;
-- 
2.5.0



From mike at mikebwilliams.com  Tue May  3 09:44:24 2016
From: mike at mikebwilliams.com (Mike Williams)
Date: Tue,  3 May 2016 12:44:24 -0400
Subject: [PATCH 3/3] ARM: at91/dt: sama5d4: add trng node
In-Reply-To: <1462293864-32551-1-git-send-email-mike@mikebwilliams.com>
References: <1462293864-32551-1-git-send-email-mike@mikebwilliams.com>
Message-ID: <1462293864-32551-4-git-send-email-mike@mikebwilliams.com>

Add node to support SAMA5D4 hardware random number generator.
---
 arch/arm/boot/dts/sama5d4.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi
index db1151c..a95eb36 100644
--- a/arch/arm/boot/dts/sama5d4.dtsi
+++ b/arch/arm/boot/dts/sama5d4.dtsi
@@ -1202,6 +1202,13 @@
 				status = "disabled";
 			};
 
+			trng at fc030000 {
+				compatible = "atmel,at91sam9g45-trng";
+				reg = <0xfc030000 0x4000>;
+				interrupts = <53 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&trng_clk>;
+			};
+
 			adc0: adc at fc034000 {
 				compatible = "atmel,at91sam9x5-adc";
 				reg = <0xfc034000 0x100>;
-- 
2.5.0



From robin.murphy at arm.com  Tue May  3 09:50:19 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 3 May 2016 17:50:19 +0100
Subject: [PATCH V2] iommu/arm-smmu: clear cache lock bit of ACR
In-Reply-To: <1462283430-9559-1-git-send-email-van.freenix@gmail.com>
References: <1462283430-9559-1-git-send-email-van.freenix@gmail.com>
Message-ID: <5728D6CB.3010003@arm.com>

On 03/05/16 14:50, Peng Fan wrote:
> According MMU-500r2 TRM, section 3.7.1 Auxiliary Control registers,
> You can modify ACTLR only when the ACR.CACHE_LOCK bit is 0.
>
> So before clearing ARM_MMU500_ACTLR_CPRE of each context bank,
> need clear CACHE_LOCK bit of ACR register first.
>
> Since CACHE_LOCK bit is only present in MMU-500r2 onwards,
> need to check the major number of IDR7.
>
> Signed-off-by: Peng Fan <van.freenix at gmail.com>
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: Robin Murphy <robin.murphy at arm.com>
> ---
>
> V2:
>   Following Robin's comments, need to check IDR7 before clearing
>   CACHE_LOCK bit of ACR.
>
> V1:
>   Patch based on iommu/devel
>
>   drivers/iommu/arm-smmu.c | 23 ++++++++++++++++++++++-
>   1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index acff332..c7ad23e 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -98,6 +98,9 @@
>   #define sCR0_BSU_SHIFT			14
>   #define sCR0_BSU_MASK			0x3
>
> +/* Auxiliary Configuration register */
> +#define ARM_SMMU_GR0_sACR		0x10
> +
>   /* Identification registers */
>   #define ARM_SMMU_GR0_ID0		0x20
>   #define ARM_SMMU_GR0_ID1		0x24
> @@ -144,6 +147,9 @@
>   #define ID2_PTFS_64K			(1 << 14)
>   #define ID2_VMID16			(1 << 15)
>
> +#define ID7_MAJOR_SHIFT			4
> +#define ID7_MAJOR_MASK			0xf
> +
>   /* Global TLB invalidation */
>   #define ARM_SMMU_GR0_TLBIVMID		0x64
>   #define ARM_SMMU_GR0_TLBIALLNSNH	0x68
> @@ -235,6 +241,8 @@
>
>   #define ARM_MMU500_ACTLR_CPRE		(1 << 1)
>
> +#define ARM_MMU500_ACR_CACHE_LOCK	(1 << 26)
> +
>   #define CB_PAR_F			(1 << 0)
>
>   #define ATSR_ACTIVE			(1 << 0)
> @@ -1493,7 +1501,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
>   	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
>   	void __iomem *cb_base;
>   	int i = 0;
> -	u32 reg;
> +	u32 reg, major;
>
>   	/* clear global FSR */
>   	reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
> @@ -1506,6 +1514,19 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
>   		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(i));
>   	}
>
> +	/*
> +	 * Before clearing ARM_MMU500_ACTLR_CPRE, need to
> +	 * clear CACHE_LOCK bit of ACR first. And, CACHE_LOCK
> +	 * bit is only present in MMU-500r2 onwards.
> +	 */
> +	reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID7);
> +	major = (reg >> ID7_MAJOR_SHIFT) & ID7_MAJOR_MASK;
> +	if ((smmu->model == ARM_MMU500) && (major >= 2)) {
> +		reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sACR);
> +		reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
> +		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sACR);
> +	}
> +

I'd have been inclined to make the ID reg read conditional on ARM_MMU500 
as well, but this way is marginally more compact, and it's not like 
we're in a frequently-used hot path anyway.

Reviewed-by: Robin Murphy <robin.murphy at arm.com>

Thanks,
Robin.

>   	/* Make sure all context banks are disabled and clear CB_FSR  */
>   	for (i = 0; i < smmu->num_context_banks; ++i) {
>   		cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, i);
>



From boris.brezillon at free-electrons.com  Tue May  3 09:51:53 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 3 May 2016 18:51:53 +0200
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <20160503164019.GA1604@rob-hp-laptop>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop>
Message-ID: <20160503185153.5cfddc32@bbrezillon>

Hi Rob,

On Tue, 3 May 2016 11:40:19 -0500
Rob Herring <robh at kernel.org> wrote:

> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:
> > The EBI (External Bus Interface) is used to access external peripherals
> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
> > Each device is assigned a CS line and an address range and can have its
> > own configuration (timings, access mode, bus width, ...).
> > This driver provides a generic DT binding to configure a device according
> > to its requirements.
> > For specific device controllers (like the NAND one) the SMC timings
> > should be configured by the controller driver through the matrix and smc
> > syscon regmaps.
> > 
> > Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> > ---
> >  .../bindings/memory-controllers/atmel,ebi.txt      | 136 +++++++++++++++++++++
> >  1 file changed, 136 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> > new file mode 100644
> > index 0000000..a6dca5c
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> > @@ -0,0 +1,136 @@
> > +* Device tree bindings for Atmel EBI
> > +
> > +The External Bus Interface (EBI) controller is a bus where you can connect
> > +asynchronous (NAND, NOR, SRAM, ....) and synchronous memories (SDR/DDR SDRAMs).
> > +The EBI provides a glue-less interface to asynchronous memories through the SMC
> > +(Static Memory Controller).
> > +
> > +Required properties:
> > +
> > +- compatible:		"atmel,at91sam9260-ebi"
> > +			"atmel,at91sam9261-ebi"
> > +			"atmel,at91sam9263-ebi0"
> > +			"atmel,at91sam9263-ebi1"  
> 
> What are the differences between 0 and 1?

Because this SoC has 2 EBI busses with different capabilities.

> 
> > +			"atmel,at91sam9rl-ebi"
> > +			"atmel,at91sam9g45-ebi"
> > +			"atmel,at91sam9x5-ebi"
> > +			"atmel,sama5d3-ebi"
> > +
> > +- reg:			Contains offset/length value for EBI memory mapping.
> > +			This property might contain several entries if the EBI
> > +			memory range is not contiguous
> > +
> > +- #address-cells:	Must be 2.
> > +			The first cell encodes the CS.
> > +			The second cell encode the offset into the CS memory
> > +			range.
> > +
> > +- #size-cells:		Must be set to 1.
> > +
> > +- ranges:		Encodes CS to memory region association.
> > +
> > +- clocks:		Clock feeding the EBI controller.
> > +			See clock-bindings.txt
> > +
> > +Children device nodes are representing device connected to the EBI bus.
> > +
> > +Required device node properties:
> > +
> > +- #reg:			Contains the chip-select id, the offset and the length  
> 
> s/#reg/reg/

Will fix that.

> 
> > +			of the memory region requested by the device.
> > +
> > +EBI bus configuration associated with specific chip-select will be defined in
> > +the configs subnode. This configs node will in turn contain several subnodes
> > +named config-<cs-id>, each of them containing the following properties.  
> 
> This is a bit unusual. Why not just part of the child device nodes?

Oh, come on! I reworked the binding because Mark complained about the
previous binding which was doing exactly what you're suggesting. Can
you please be consistent in your reviews... 


> 
> > +
> > +Optional config-<cs-id> node properties:
> > +
> > +- atmel,bus-width:		width of the asynchronous device's data bus
> > +				8, 16 or 32.
> > +				Default to 8 when undefined.
> > +
> > +- atmel,byte-access-type	"write" or "select" (see Atmel datasheet).
> > +				Default to "select" when undefined.
> > +
> > +- atmel,read-mode		"nrd" or "ncs".
> > +				Default to "ncs" when undefined.
> > +
> > +- atmel,write-mode		"nwe" or "ncs".
> > +				Default to "ncs" when undefined.
> > +
> > +- atmel,exnw-mode		"disabled", "frozen" or "ready".
> > +				Default to "disabled" when undefined.
> > +
> > +- atmel,page-mode		enable page mode if present. The provided value
> > +				defines the page size (supported values: 4, 8,
> > +				16 and 32).
> > +
> > +- atmel,tdf-mode:		"normal" or "optimized". When set to  
> 
> This should be boolean.

It was a formerly defined as a boolean, and when it's done like that we
have no way to identify whether the property was forgotten or
intentionally set to normal mode. What's the problem with this approach?

> 
> > +				"optimized" the data float time is optimized
> > +				depending on the next device being accessed
> > +				(next device setup time is subtracted to the
> > +				current device data float time).
> > +				Default to "normal" when undefined.
> > +
> > +Mandatory timings expressed in nanoseconds (see Atmel datasheet for a full
> > +description).  
> 
> Required first, then optional properties please.

Okay.

> 
> > +
> > +- atmel,ncs-rd-setup-ns
> > +- atmel,nrd-setup-ns
> > +- atmel,ncs-wr-setup-ns
> > +- atmel,nwe-setup-ns
> > +- atmel,ncs-rd-pulse-ns
> > +- atmel,nrd-pulse-ns
> > +- atmel,ncs-wr-pulse-ns
> > +- atmel,nwe-pulse-ns
> > +- atmel,nwe-cycle-ns
> > +- atmel,nrd-cycle-ns
> > +- atmel,tdf-ns
> > +
> > +Example:
> > +
> > +	ebi: ebi at 10000000 {
> > +		compatible = "atmel,sama5d3-ebi";
> > +		#address-cells = <2>;
> > +		#size-cells = <1>;  
> 
> > +		atmel,smc = <&hsmc>;
> > +		atmel,matrix = <&matrix>;  
> 
> What are these? 
> 
> > +		reg = <0x10000000 0x10000000
> > +		       0x40000000 0x30000000>;
> > +		ranges = <0x0 0x0 0x10000000 0x10000000
> > +			  0x1 0x0 0x40000000 0x10000000
> > +			  0x2 0x0 0x50000000 0x10000000
> > +			  0x3 0x0 0x60000000 0x10000000>;
> > +		clocks = <&mck>;
> > +
> > +		pinctrl-names = "default";
> > +		pinctrl-0 = <&pinctrl_ebi_addr>;  
> 
> Not documented.

Will document those properties.

Regards,

Boris


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


From robh at kernel.org  Tue May  3 09:53:57 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 3 May 2016 11:53:57 -0500
Subject: [PATCH v3 3/3] leds: gpio: Support the "panic-indicator"
 firmware property
In-Reply-To: <1461881020-13964-4-git-send-email-ezequiel@vanguardiasur.com.ar>
References: <1461881020-13964-1-git-send-email-ezequiel@vanguardiasur.com.ar>
 <1461881020-13964-4-git-send-email-ezequiel@vanguardiasur.com.ar>
Message-ID: <20160503165357.GA10505@rob-hp-laptop>

On Thu, Apr 28, 2016 at 07:03:40PM -0300, Ezequiel Garcia wrote:
> Calling a GPIO LEDs is quite likely to work even if the kernel
> has paniced, so they are ideal to blink in this situation.
> This commit adds support for the new "panic-indicator"
> firmware property, allowing to mark a given LED to blink on
> a kernel panic.
> 
> Signed-off-by: Ezequiel Garcia <ezequiel at vanguardiasur.com.ar>
> ---
>  Documentation/devicetree/bindings/leds/leds-gpio.txt | 2 ++

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

>  drivers/leds/leds-gpio.c                             | 4 ++++
>  include/linux/leds.h                                 | 1 +
>  3 files changed, 7 insertions(+)


From marc.zyngier at arm.com  Tue May  3 10:00:26 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 18:00:26 +0100
Subject: [PATCH] KVM: arm/arm64: new-vgic: add proper GICv2 CPU interface
 userland access
In-Reply-To: <1462291649-9906-1-git-send-email-andre.przywara@arm.com>
References: <57287A89.9010809@arm.com>
 <1462291649-9906-1-git-send-email-andre.przywara@arm.com>
Message-ID: <5728D92A.9010503@arm.com>

On 03/05/16 17:07, Andre Przywara wrote:
> Although the actual register access was wired, the availability check
> for the GICv2 CPU interface register interface was not - leading to
> any attempt of saving or restoring GICv2 CPU i/f registers to fail.
> 
> This patch fixes this by modelling the CPU i/f registers similarily to
> the distributor registers, thereby piggy backing on the existing
> distributor save/restore code to do the heavy lifting.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Hi,
> 
> this is a fix for the missing CPU i/f migration that Marc spotted.
> In a repost I will merge this somehow into the existing patches, but
> for now this goes on top of the series.
> Can any of you have a look whether this is the right way to go?

The whole VMCR story feels very convoluted. It caters for GICv3 (which
has no way to use it), has global symbols where it should be static,
and indirections that serve no apparent purpose. And the vgic_vmcr
structure should really per implementation. </rant> ;-)

So here's my take on this particular patch:

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 64aca0c..2a6fa99 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -172,13 +172,6 @@ struct vgic_v3_cpu_if {
 #endif
 };
 
-struct vgic_vmcr {
-	u32	ctlr;
-	u32	abpr;
-	u32	bpr;
-	u32	pmr;
-};
-
 struct vgic_cpu {
 	/* CPU vif control registers for world switch */
 	union {
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index eaf5c1d..657552d 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -20,8 +20,6 @@
 #include <linux/irqchip/arm-gic.h>
 #include "vgic.h"
 
-#define GICC_ARCH_VERSION_V2		0x2
-
 /* common helpers */
 
 static int vgic_ioaddr_overlap(struct kvm *kvm)
@@ -255,69 +253,6 @@ void kvm_register_vgic_device(unsigned long type)
 	}
 }
 
-static u32 vgic_read_vcpuif(struct kvm_vcpu *vcpu, int offset)
-{
-	struct vgic_vmcr vmcr;
-	u32 *field;
-
-	switch (offset) {
-	case GIC_CPU_CTRL:
-		field = &vmcr.ctlr;
-		break;
-	case GIC_CPU_PRIMASK:
-		field = &vmcr.pmr;
-		break;
-	case GIC_CPU_BINPOINT:
-		field = &vmcr.bpr;
-		break;
-	case GIC_CPU_ALIAS_BINPOINT:
-		field = &vmcr.abpr;
-		break;
-	case GIC_CPU_IDENT:
-		return (PRODUCT_ID_KVM << 20) |
-		       (GICC_ARCH_VERSION_V2 << 16) |
-		       (IMPLEMENTER_ARM << 0);
-	default:
-		return 0;
-	}
-
-	vgic_get_vmcr(vcpu, &vmcr);
-
-	return *field;
-}
-
-static bool vgic_write_vcpuif(struct kvm_vcpu *vcpu, int offset, u32 value)
-{
-	struct vgic_vmcr vmcr;
-	u32 *field;
-
-	switch (offset) {
-	case GIC_CPU_CTRL:
-		field = &vmcr.ctlr;
-		break;
-	case GIC_CPU_PRIMASK:
-		field = &vmcr.pmr;
-		break;
-	case GIC_CPU_BINPOINT:
-		field = &vmcr.bpr;
-		break;
-	case GIC_CPU_ALIAS_BINPOINT:
-		field = &vmcr.abpr;
-		break;
-	default:
-		return false;
-	}
-
-	vgic_get_vmcr(vcpu, &vmcr);
-	if (*field == value)
-		return false;
-
-	*field = value;
-	vgic_set_vmcr(vcpu, &vmcr);
-
-	return true;
-}
-
 /** vgic_attr_regs_access: allows user space to read/write VGIC registers
  *
  * @dev: kvm device handle
@@ -366,11 +301,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		ret = 0;
-		if (is_write)
-			vgic_write_vcpuif(vcpu, addr, *reg);
-		else
-			*reg = vgic_read_vcpuif(vcpu, addr);
+		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
 		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index f2a8efe..9598426 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -206,6 +206,104 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
 	}
 }
 
+struct vgic_vmcr {
+	u32	ctlr;
+	u32	abpr;
+	u32	bpr;
+	u32	pmr;
+};
+
+static void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr;
+
+	vmcr  = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK;
+	vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) &
+		GICH_VMCR_ALIAS_BINPOINT_MASK;
+	vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) &
+		GICH_VMCR_BINPOINT_MASK;
+	vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) &
+		GICH_VMCR_PRIMASK_MASK;
+
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = vmcr;
+}
+
+static void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr;
+
+	vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >>
+			GICH_VMCR_CTRL_SHIFT;
+	vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >>
+			GICH_VMCR_ALIAS_BINPOINT_SHIFT;
+	vmcrp->bpr  = (vmcr & GICH_VMCR_BINPOINT_MASK) >>
+			GICH_VMCR_BINPOINT_SHIFT;
+	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
+			GICH_VMCR_PRIMASK_SHIFT;
+}
+
+#define GICC_ARCH_VERSION_V2	0x2
+
+/* These are for userland accesses only, there is no guest-facing emulation. */
+static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
+					   gpa_t addr, unsigned int len)
+{
+	struct vgic_vmcr vmcr;
+	u32 val;
+
+	vgic_v2_get_vmcr(vcpu, &vmcr);
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		val = vmcr.ctlr;
+		break;
+	case GIC_CPU_PRIMASK:
+		val = vmcr.pmr;
+		break;
+	case GIC_CPU_BINPOINT:
+		val = vmcr.bpr;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		val = vmcr.abpr;
+		break;
+	case GIC_CPU_IDENT:
+		val = ((PRODUCT_ID_KVM << 20) |
+		       (GICC_ARCH_VERSION_V2 << 16) |
+		       IMPLEMENTER_ARM);
+		break;
+	default:
+		return 0;
+	}
+
+	return extract_bytes(val, addr & 3, len);
+}
+
+static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
+				   gpa_t addr, unsigned int len,
+				   unsigned long val)
+{
+	struct vgic_vmcr vmcr;
+
+	vgic_v2_get_vmcr(vcpu, &vmcr);
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		vmcr.ctlr = val;
+		break;
+	case GIC_CPU_PRIMASK:
+		vmcr.pmr = val;
+		break;
+	case GIC_CPU_BINPOINT:
+		vmcr.bpr = val;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		vmcr.abpr = val;
+		break;
+	}
+
+	vgic_v2_set_vmcr(vcpu, &vmcr);
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
@@ -237,6 +335,21 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16),
 };
 
+static const struct vgic_register_region vgic_v2_cpu_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_CTRL,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_PRIMASK,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ALIAS_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ACTIVEPRIO,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_IDENT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+};
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
 {
 	dev->regions = vgic_v2_dist_registers;
@@ -253,23 +366,18 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
  * have to set up a buffer similar to what would have happened if a guest MMIO
  * access occurred, including doing endian conversions on BE systems.
  */
-int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
-			int offset, u32 *val)
+static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
+			bool is_write, int offset, u32 *val)
 {
 	unsigned int len = 4;
 	u8 buf[4];
 	int ret;
 
-	struct vgic_io_device dev = {
-		.regions = vgic_v2_dist_registers,
-		.nr_regions = ARRAY_SIZE(vgic_v2_dist_registers),
-	};
-
 	if (is_write) {
 		vgic_data_host_to_mmio_bus(buf, len, *val);
-		ret = kvm_io_gic_ops.write(vcpu, &dev.dev, offset, len, buf);
+		ret = kvm_io_gic_ops.write(vcpu, &dev->dev, offset, len, buf);
 	} else {
-		ret = kvm_io_gic_ops.read(vcpu, &dev.dev, offset, len, buf);
+		ret = kvm_io_gic_ops.read(vcpu, &dev->dev, offset, len, buf);
 		if (!ret)
 			*val = vgic_data_mmio_bus_to_host(buf, len);
 	}
@@ -277,6 +385,28 @@ int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 	return ret;
 }
 
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_cpu_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
+
+int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			 int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_dist_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_dist_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
+
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 {
 	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
@@ -292,7 +422,9 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		return -ENXIO;		/* TODO: describe CPU i/f regs also */
+		regions = vgic_v2_cpu_registers;
+		nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers);
+		break;
 	default:
 		return -ENXIO;
 	}
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index b8bfece..862fb0f 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -182,35 +182,6 @@ void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
 	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
 }
 
-void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
-{
-	u32 vmcr;
-
-	vmcr  = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK;
-	vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) &
-		GICH_VMCR_ALIAS_BINPOINT_MASK;
-	vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) &
-		GICH_VMCR_BINPOINT_MASK;
-	vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) &
-		GICH_VMCR_PRIMASK_MASK;
-
-	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = vmcr;
-}
-
-void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
-{
-	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr;
-
-	vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >>
-			GICH_VMCR_CTRL_SHIFT;
-	vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >>
-			GICH_VMCR_ALIAS_BINPOINT_SHIFT;
-	vmcrp->bpr  = (vmcr & GICH_VMCR_BINPOINT_MASK) >>
-			GICH_VMCR_BINPOINT_SHIFT;
-	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
-			GICH_VMCR_PRIMASK_SHIFT;
-}
-
 void vgic_v2_enable(struct kvm_vcpu *vcpu)
 {
 	/*
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index e975a33..ed85bbc 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -176,28 +176,6 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
 }
 
-void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
-{
-	u32 vmcr;
-
-	vmcr  = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK;
-	vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
-	vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
-	vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
-
-	vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
-}
-
-void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
-{
-	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
-
-	vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT;
-	vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
-	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
-	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
-}
-
 void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
 	struct vgic_v3_cpu_if *vgic_v3 = &vcpu->arch.vgic_cpu.vgic_v3;
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 5f21742..b22e2ac 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -482,22 +482,6 @@ static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
 		vgic_v3_set_underflow(vcpu);
 }
 
-void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
-{
-	if (kvm_vgic_global_state.type == VGIC_V2)
-		vgic_v2_set_vmcr(vcpu, vmcr);
-	else
-		vgic_v3_set_vmcr(vcpu, vmcr);
-}
-
-void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
-{
-	if (kvm_vgic_global_state.type == VGIC_V2)
-		vgic_v2_get_vmcr(vcpu, vmcr);
-	else
-		vgic_v3_get_vmcr(vcpu, vmcr);
-}
-
 static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
 {
 	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index f970e3e..9072b8c 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -38,9 +38,9 @@ void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val);
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
-void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
-void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_enable(struct kvm_vcpu *vcpu);
 int vgic_v2_probe(struct device_node *vgic_node);
 int vgic_v2_map_resources(struct kvm *kvm);
@@ -53,8 +53,6 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
-void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
-void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_enable(struct kvm_vcpu *vcpu);
 int vgic_v3_probe(struct device_node *vgic_node);
 int vgic_v3_map_resources(struct kvm *kvm);
@@ -81,16 +79,6 @@ static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 }
 
-static inline
-void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
-{
-}
-
-static inline
-void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
-{
-}
-
 static inline void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
 }
@@ -112,9 +100,6 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 }
 #endif
 
-void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
-void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
-
 int vgic_lazy_init(struct kvm *kvm);
 int vgic_init(struct kvm *kvm);
 void kvm_register_vgic_device(unsigned long type);


Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From davem at davemloft.net  Tue May  3 10:03:23 2016
From: davem at davemloft.net (David Miller)
Date: Tue, 03 May 2016 13:03:23 -0400 (EDT)
Subject: [PATCH] VSOCK: constify vsock_transport structure
In-Reply-To: <1462106955-22131-1-git-send-email-Julia.Lawall@lip6.fr>
References: <1462106955-22131-1-git-send-email-Julia.Lawall@lip6.fr>
Message-ID: <20160503.130323.1929865256655720740.davem@davemloft.net>

From: Julia Lawall <Julia.Lawall at lip6.fr>
Date: Sun,  1 May 2016 14:49:15 +0200

> The vsock_transport structure is never modified, so declare it as const.
> 
> Done with the help of Coccinelle.
> 
> Signed-off-by: Julia Lawall <Julia.Lawall at lip6.fr>

Applied.


From plaes at plaes.org  Tue May  3 10:14:19 2016
From: plaes at plaes.org (Priit Laes)
Date: Tue,  3 May 2016 20:14:19 +0300
Subject: [PATCH 2/2] ARM: sun7i: dt: Add pll3 and pll7 clocks
In-Reply-To: <1462295659-6945-1-git-send-email-plaes@plaes.org>
References: <1462295659-6945-1-git-send-email-plaes@plaes.org>
Message-ID: <1462295659-6945-3-git-send-email-plaes@plaes.org>

Enable pll3 and pll7 clocks that are needed by display clocks.
---
 arch/arm/boot/dts/sun7i-a20.dtsi | 41 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index bf5d056..2688512 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -187,6 +187,15 @@
 			clock-output-names = "osc24M";
 		};
 
+		osc3M: osc3M_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clock-div = <8>;
+			clock-mult = <1>;
+			clocks = <&osc24M>;
+			clock-output-names = "osc3M";
+		};
+
 		osc32k: clk at 0 {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -211,6 +220,22 @@
 					     "pll2-4x", "pll2-8x";
 		};
 
+		pll3: clk at 01c20010 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-pll3-clk";
+			reg = <0x01c20010 0x4>;
+			clock = <&osc3M>;
+			clock-output-names = "pll3";
+};
+
+		pll3x2: pll3x2_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clock-div = <1>;
+			clock-mult = <2>;
+			clock-output-names = "pll3-2x";
+		};
+
 		pll4: clk at 01c20018 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun7i-a20-pll4-clk";
@@ -236,6 +261,22 @@
 					     "pll6_div_4";
 		};
 
+		pll7: clk at 01c20030 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-pll3-clk";
+			reg = <0x01c20030 0x4>;
+			clock = <&osc3M>;
+			clock-output-names = "pll7";
+};
+
+		pll7x2: pll7x2_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clock-div = <1>;
+			clock-mult = <2>;
+			clock-output-names = "pll7-2x";
+		};
+
 		pll8: clk at 01c20040 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun7i-a20-pll4-clk";
-- 
2.8.1



From plaes at plaes.org  Tue May  3 10:14:18 2016
From: plaes at plaes.org (Priit Laes)
Date: Tue,  3 May 2016 20:14:18 +0300
Subject: [PATCH 1/2] ARM: sun4i: dt: Add pll3 and pll7 clocks
In-Reply-To: <1462295659-6945-1-git-send-email-plaes@plaes.org>
References: <1462295659-6945-1-git-send-email-plaes@plaes.org>
Message-ID: <1462295659-6945-2-git-send-email-plaes@plaes.org>

Enable pll3 and pll7 clocks that are needed to drive display clocks.

Signed-off-by: Priit Laes <plaes at plaes.org>
---
 arch/arm/boot/dts/sun4i-a10.dtsi | 44 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 268a150..c893744 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -184,6 +184,15 @@
 			clock-output-names = "osc24M";
 		};
 
+		osc3M: osc3M_clk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <8>;
+			clock-mult = <1>;
+			clocks = <&osc24M>;
+			clock-output-names = "osc3M";
+		};
+
 		osc32k: clk at 0 {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -208,6 +217,24 @@
 					     "pll2-4x", "pll2-8x";
 		};
 
+		pll3: clk at 01c20010 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-pll3-clk";
+			reg = <0x01c20010 0x4>;
+			clocks = <&osc3M>;
+			clock-output-names = "pll3";
+		};
+
+		pll3x2: pll3x2_clk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <2>;
+			clocks = <&pll3>;
+			clock-output-names = "pll3-x2";
+		};
+
+
 		pll4: clk at 01c20018 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-pll1-clk";
@@ -232,6 +259,23 @@
 			clock-output-names = "pll6_sata", "pll6_other", "pll6";
 		};
 
+		pll7: clk at 01c20030 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-pll3-clk";
+			reg = <0x01c20030 0x4>;
+			clocks = <&osc3M>;
+			clock-output-names = "pll7";
+		};
+
+		pll7x2: pll7x2_clk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <2>;
+			clocks = <&pll7>;
+			clock-output-names = "pll7-2x";
+		};
+
 		/* dummy is 200M */
 		cpu: cpu at 01c20054 {
 			#clock-cells = <0>;
-- 
2.8.1



From plaes at plaes.org  Tue May  3 10:14:17 2016
From: plaes at plaes.org (Priit Laes)
Date: Tue,  3 May 2016 20:14:17 +0300
Subject: [PATCH 0/2] ARM: dts: sunxi: Add pll3 and pll7 clock to sun[47]i.dtsi
Message-ID: <1462295659-6945-1-git-send-email-plaes@plaes.org>

Enable the pll3 and pll7 clocks in the DT that are used to drive the
display-related clocks.

Priit Laes (2):
  ARM: sun4i: dt: Add pll3 and pll7 clocks
  ARM: sun7i: dt: Add pll3 and pll7 clocks

 arch/arm/boot/dts/sun4i-a10.dtsi | 44 ++++++++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/sun7i-a20.dtsi | 41 +++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

-- 
2.8.1



From linux at roeck-us.net  Tue May  3 10:16:02 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 3 May 2016 10:16:02 -0700
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <20160503155141.GF13045@dhcppc6.redhat.com>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <5728A7C3.4010001@roeck-us.net>
 <20160503143856.GE13045@dhcppc6.redhat.com>
 <5728BEC4.6050603@codeaurora.org>
 <20160503155141.GF13045@dhcppc6.redhat.com>
Message-ID: <20160503171602.GA2518@roeck-us.net>

On Tue, May 03, 2016 at 09:21:41PM +0530, Pratyush Anand wrote:
> On 03/05/2016:10:07:48 AM, Timur Tabi wrote:
> > Pratyush Anand wrote:
> > >In fact after supporting max_hw_heartbeat_ms, there should be no change for
> > >action=0 functionally. However, we would still need some changes for action=1.
> > 
> > IMHO, action=1 is more of a debugging option, and not something that would
> > be used normally.  I would need to see some evidence that real users want to
> > have action=1 and a longer timeout.
> > 
> If action=1 need to be used effectively, then we should have something which
> would help to increase timeout values.
> 
> Currently you have only 10 second to execute secondary kernel, which might not
> be sufficient.
> 
Previously the argument was that the 10 seconds (assuming the clock runs at
maximum speed) would not be sufficient to load the watchdog application. Now it
seems the 10 seconds are deemed insufficient to load the watchdog driver (since
the infrastructure can handle the heartbeats). Is there actual evidence that
this is the case ?

Guenter

> > I've never been a fan of the action=1 option, and I'm certainly not keen any
> > patches that make action=1 more complicated than it already is.
> 
> I think, with max_hw_heartbeat_ms it would be far more simpler. Will attempt and
> send another RFC.
> 
> ~Pratyush


From keescook at chromium.org  Tue May  3 10:26:52 2016
From: keescook at chromium.org (Kees Cook)
Date: Tue, 3 May 2016 10:26:52 -0700
Subject: [RFC PATCH] arm64: Make arch_randomize_brk avoid stack area
In-Reply-To: <1462274013.2862.46.camel@linaro.org>
References: <1461848638.2848.19.camel@linaro.org>
 <1461853042.2848.24.camel@linaro.org>
 <CAGXu5jJKDE_pLCxy-FF7PN5+YC7wyvpQ_9DTDGqHuk+tb1mvJA@mail.gmail.com>
 <1462274013.2862.46.camel@linaro.org>
Message-ID: <CAGXu5jLjPZRxgiudps0rTj2KRbTPZGhWsGjYdDDSL6B5RhXktg@mail.gmail.com>

On Tue, May 3, 2016 at 4:13 AM, Jon Medhurst (Tixy) <tixy at linaro.org> wrote:
> On Mon, 2016-05-02 at 12:34 -0700, Kees Cook wrote:
>> On Thu, Apr 28, 2016 at 7:17 AM, Jon Medhurst (Tixy) <tixy at linaro.org> wrote:
> [...]
>
>> >  arch/arm64/kernel/process.c | 24 ++++++++++++++++++------
>> >  1 file changed, 18 insertions(+), 6 deletions(-)
>> >
>> > diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
>> > index 07c4c53..7e0f404 100644
>> > --- a/arch/arm64/kernel/process.c
>> > +++ b/arch/arm64/kernel/process.c
>> > @@ -434,13 +434,25 @@ unsigned long arch_align_stack(unsigned long sp)
>> >         return sp & ~0xf;
>> >  }
>> >
>> > -static unsigned long randomize_base(unsigned long base)
>> > +unsigned long arch_randomize_brk(struct mm_struct *mm)
>> >  {
>> > +       unsigned long base = mm->brk;
>> >         unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
>>
>> This looks wrong. Shouldn't it be (STACK_RND_MASK + 1) << PAGE_SHIFT ?
>
> That value is the same as before my changes and it matches the gap left
> for stack randomisation in arch/arm64/mm/mmap.c

True, I didn't mean it was part of your patch. It just jumped out at
me as something that didn't look right that should probably get fixed
too.

>> STACK_RND_MASK is 0x7ff (32-bit) or 0x3ffff (64-bit):
>>
>> #define STACK_RND_MASK                  (test_thread_flag(TIF_32BIT) ? \
>>                                                 0x7ff >> (PAGE_SHIFT - 12) : \
>>                                                 0x3ffff >> (PAGE_SHIFT - 12))
>>
>> (4K paged PAGE_SHIFT is 12)
>>
>> So the correct offset max would be 0x800000 (32-bit) and 0x40000000
>> (64-bit), instead of
>> 0x7ff0001 and 0x3ffff0001.
>
> It seems to me there isn't a 'correct' and 'incorrect' range to use here
> and that randomising brk is not directly related to stack randomisation,
> they just have similar requirements and constraints.

Well, I think it's a typo. The code seemed to be wanting to convert a
mask to a range, but when adding PAGE_SHIFT, it went in the wrong
place.

> Anyway, for stack randomisation, in fs/binfmt_elf.c,
> randomize_stack_top() has
>
>                 random_variable = get_random_long();
>                 random_variable &= STACK_RND_MASK;
>                 random_variable <<= PAGE_SHIFT;
>
> so stack top can be randomised by adding a number from zero to
> (STACK_RND_MASK << PAGE_SHIFT) inclusive. As the end value passed to
> randomize_range() is exclusive, then adding one to the last permissible

Well, no, this is using the mask correctly. It removes keeps the bits
it's interested in and then promotes them above the page size.

> value seems the like the right, I.e. arm64's usage of
>
>   (STACK_RND_MASK << PAGE_SHIFT) + 1
>
> for brk is 'correct' in that it's consistent with what happens to the
> stack. Though the different functions align values to pages at different
> stages, so possibly neither that nor
>
>   (STACK_RND_MASK + 1)  << PAGE_SHIFT
>
> when used for brk, would be the same as the stack code.

Anyway, this can be a separate fix. Your changes should make sense in
either place (well, it should be a no-op for current kernel, but
that's fine).

>> Even with that correction, this looks wrong for 32-bit, which uses
>> 0x2000000 natively:
>>
>> unsigned long arch_randomize_brk(struct mm_struct *mm)
>> {
>>         unsigned long range_end = mm->brk + 0x02000000;
>>         return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
>> }
>>
>> Seems like arm64 compat is using 4 times less entropy than native arm?
>> (Note that STACK_RND_MASK is correct for arm64 compat: this matches
>> the default in fs/binfmt_elf.c that arm uses. It just seems like the
>> brk randomization is accidentally too small on arm64 compat since arm
>> uses a fixed value unrelated to stack randomization.)
>>
>> 0x02000000 arm native
>> 0x00800000 arm64 compat  <- bug?
>> 0x40000000 arm64
>
> Well, it's a difference for which there probably isn't a good reason,
> don't know if people would call it a bug.

It's a behavioral change between native and compat which reduces the
entropy of brk randomization, so I'm comfortable to call it a bug. :)

> As changing the range of values used for randomisation seems like a
> separate issue I won't include any changes for that in my patch for
> getting brk to avoid the stack.

Sounds fine. Can you resend your change as a v2 with the changelog, etc?

Thanks!

-Kees

>
> --
> Tixy
>



-- 
Kees Cook
Chrome OS & Brillo Security


From dhaab at luxul.com  Tue May  3 10:28:16 2016
From: dhaab at luxul.com (Dan Haab)
Date: Tue, 3 May 2016 11:28:16 -0600
Subject: [PATCH] ARM: BCM5301X: Add DT for Luxul XAP-1510
Message-ID: <1462296501-5209-1-git-send-email-dhaab@luxul.com>

Luxul XAP-1510 is an AP device based on BCM4708 SoC. It uses flash
memory connected to the SPI controller.

Signed-off-by: Dan Haab <dhaab at luxul.com>
---
 arch/arm/boot/dts/Makefile                   |    1 +
 arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts |   67 ++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)
 create mode 100644 arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 95c1923..c499d09 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -71,6 +71,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
 	bcm4708-asus-rt-ac56u.dtb \
 	bcm4708-asus-rt-ac68u.dtb \
 	bcm4708-buffalo-wzr-1750dhp.dtb \
+	bcm4708-luxul-xap-1510.dtb \
 	bcm4708-luxul-xwc-1000.dtb \
 	bcm4708-netgear-r6250.dtb \
 	bcm4708-netgear-r6300-v2.dtb \
diff --git a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
new file mode 100644
index 0000000..f4460b5
--- /dev/null
+++ b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
@@ -0,0 +1,67 @@
+/*
+ * Broadcom BCM470X / BCM5301X ARM platform code.
+ * DTS for Luxul XAP-1510
+ *
+ * Copyright 2015 Luxul Inc.
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+/dts-v1/;
+
+#include "bcm4708.dtsi"
+
+/ {
+	compatible = "luxul,xap-1510v1", "brcm,bcm4708";
+	model = "Luxul XAP-1510 V1";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlycon";
+	};
+
+	memory {
+		reg = <0x00000000 0x08000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		5ghz {
+			label = "bcm53xx:blue:5ghz";
+			gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		2ghz {
+			label = "bcm53xx:blue:2ghz";
+			gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		status {
+			label = "bcm53xx:green:status";
+			gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "timer";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		restart {
+			label = "Reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi_nor {
+	status = "okay";
+};
-- 
1.7.9.5



From t-kristo at ti.com  Tue May  3 10:32:44 2016
From: t-kristo at ti.com (Tero Kristo)
Date: Tue, 3 May 2016 20:32:44 +0300
Subject: [PATCH v2 2/3] ARM: DRA7x: dts: Update the OSC_32K_CLK frequency
In-Reply-To: <20160503164323.GN5995@atomide.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
 <1462209123-7332-3-git-send-email-Linux.HWI@garmin.com>
 <57285E66.2000708@ti.com> <5728A81F.4050906@garmin.com>
 <20160503164323.GN5995@atomide.com>
Message-ID: <5728E0BC.3080509@ti.com>

On 03/05/16 19:43, Tony Lindgren wrote:
> * J.D. Schroeder <Linux.HWI at garmin.com> [160503 06:32]:
>> On 05/03/2016 03:16 AM, Tero Kristo wrote:
>>> On 02/05/16 20:12, J.D. Schroeder wrote:
>>>> From: "J.D. Schroeder" <jay.schroeder at garmin.com>
>>>>
>>>> This commit updates the OSC_32K_CLK (secure_32k_clk_src_ck) frequency
>>>> from the precise 32kHz frequency (i.e., 32.768 kHz) to a more
>>>> accurate frequency of ~34.6 kHz. Actual measured frequencies of the
>>>> clock vary from processor to processor anywhere from 34.4 kHz up to
>>>> 34.8 kHz. Note that the ~34 kHz frequency clock is generated
>>>> internally by the processor, not an input to the processor. This
>>>> change makes it more clear that the consumer of the
>>>> secure_32k_clk_src_ck will not get a precise 32.768 kHz frequency
>>>> output.
>>>>
>>>> Signed-off-by: J.D. Schroeder <jay.schroeder at garmin.com>
>>>> Reviewed-by: Trenton Andres <trenton.andres at garmin.com>
>>>> ---
>>>>    arch/arm/boot/dts/dra7xx-clocks.dtsi | 2 +-
>>>>    1 file changed, 1 insertion(+), 1 deletion(-)
>>>>
>>>> diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi
>>>> b/arch/arm/boot/dts/dra7xx-clocks.dtsi
>>>> index 3f0c61d..f7ec976 100644
>>>> --- a/arch/arm/boot/dts/dra7xx-clocks.dtsi
>>>> +++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi
>>>> @@ -95,7 +95,7 @@
>>>>        secure_32k_clk_src_ck: secure_32k_clk_src_ck {
>>>>            #clock-cells = <0>;
>>>>            compatible = "fixed-clock";
>>>> -        clock-frequency = <32768>;
>>>> +        clock-frequency = <34600>; /* approximate frequency */
>>>>        };
>>>>
>>>>        sys_clk32_crystal_ck: sys_clk32_crystal_ck {
>>>>
>>>
>>> I still don't agree with this patch. The actual frequency can drift much more,
>>> you are just seeing this number at your setup.
>>
>> Yes, it can drift significantly from processor to processor. Do you agree that
>> this frequency is closer to what can be expected than 32768 Hz?
>>
>> Like I said, I would have renamed the clock also but I opted to go the less
>> obtrusive route while still helping others that might think they can
>> reasonably use this clock in their design as a 32768 Hz clock source. Perhaps
>> my comment and selection of the approximate frequency is not the best (I'm
>> open for suggestions). However, I do think this change is an improvement and
>> clarifying change to what is currently present in the clock description.
>
> Does a fixed divider calculation of input * (32768 / 0x27e6) make sense
> here too as pointed out earlier by Matthijs for the ti81xx?

Not really, the hardware setup for this clock is not like that. Also, as 
it is security related, this is kind of sensitive area to discuss 
publicly. Personally I would not recommend using this clock for any 
timing sensitive applications. May I ask why you are interested in the 
exact clock rate of this clock anyway?

-Tero

>
> Regards,
>
> Tony
>



From mathieu.poirier at linaro.org  Tue May  3 10:33:34 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:34 -0600
Subject: [PATCH 00/27] coresight: next v4.6-rc6 
Message-ID: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>

Good morning Greg,

Here's the other wave of CoreSight enhancement that I would like
so see going in for the 4.7 cycle.  The set applies cleanly on your
current 'char-misc-next' (0a19f129d71f) branch. 

Get back to me if you have any concerns.

Thanks,
Mathieu

Alexander Shishkin (1):
  stm class: Support devices that override software assigned masters

Mathieu Poirier (22):
  coresight: adding path for STM device
  coresight: stm: Bindings for System Trace Macrocell
  coresight: etb10: fixing the right amount of words to read
  coresight: tmc: adding sysFS management entries
  coresight: tmc: modifying naming convention
  coresight: tmc: waiting for TMCReady bit before programming
  coresight: tmc: re-implementing tmc_read_prepare/unprepare() functions
  coresight: tmc: clearly define number of transfers per burst
  coresight: tmc: introducing new header file
  coresight: tmc: cleaning up header file
  coresight: tmc: splitting driver in ETB/ETF and ETR components
  coresight: tmc: making prepare/unprepare functions generic
  coresight: tmc: allocating memory when needed
  coresight: tmc: getting rid of multiple read access
  coresight: tmc: adding mode of operation for link/sinks
  coresight: tmc: dump system memory content only when needed
  coresight: tmc: make sysFS and Perf mode mutually exclusive
  coresight: tmc: keep track of memory width
  coresight: moving struct cs_buffers to header file
  coresight: tmc: implementing TMC-ETF AUX space API
  coresight: configuring ETF in FIFO mode when acting as link
  coresight: etb10: adjust read pointer only when needed

Pratik Patel (1):
  coresight: stm: adding driver for CoreSight STM component

lipengcheng (3):
  coresight: no need to do the forced type conversion
  coresight: etm4x: modify q_support type
  coresight: etm4x: add tracer ID for A72 Maia processor.

 .../ABI/testing/sysfs-bus-coresight-devices-stm    |  53 ++
 .../ABI/testing/sysfs-bus-coresight-devices-tmc    |  77 ++
 Documentation/ABI/testing/sysfs-class-stm          |  10 +
 .../devicetree/bindings/arm/coresight.txt          |  28 +
 Documentation/trace/coresight.txt                  |  37 +-
 drivers/hwtracing/coresight/Kconfig                |  11 +
 drivers/hwtracing/coresight/Makefile               |   5 +-
 drivers/hwtracing/coresight/coresight-etb10.c      |  25 +-
 drivers/hwtracing/coresight/coresight-etm4x.c      |   5 +
 drivers/hwtracing/coresight/coresight-etm4x.h      |   2 +-
 drivers/hwtracing/coresight/coresight-priv.h       |  20 +
 drivers/hwtracing/coresight/coresight-stm.c        | 920 +++++++++++++++++++++
 drivers/hwtracing/coresight/coresight-tmc-etf.c    | 604 ++++++++++++++
 drivers/hwtracing/coresight/coresight-tmc-etr.c    | 329 ++++++++
 drivers/hwtracing/coresight/coresight-tmc.c        | 603 +++-----------
 drivers/hwtracing/coresight/coresight-tmc.h        | 140 ++++
 drivers/hwtracing/coresight/coresight.c            | 142 +++-
 drivers/hwtracing/stm/core.c                       |  15 +
 include/linux/coresight-stm.h                      |   6 +
 include/linux/stm.h                                |   3 +
 include/uapi/linux/coresight-stm.h                 |  21 +
 21 files changed, 2513 insertions(+), 543 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-stm
 create mode 100644 drivers/hwtracing/coresight/coresight-stm.c
 create mode 100644 drivers/hwtracing/coresight/coresight-tmc-etf.c
 create mode 100644 drivers/hwtracing/coresight/coresight-tmc-etr.c
 create mode 100644 drivers/hwtracing/coresight/coresight-tmc.h
 create mode 100644 include/linux/coresight-stm.h
 create mode 100644 include/uapi/linux/coresight-stm.h

-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:36 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:36 -0600
Subject: [PATCH 02/27] coresight: etm4x: modify q_support type
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-3-git-send-email-mathieu.poirier@linaro.org>

From: lipengcheng <lipengcheng8 at huawei.com>

Because this operation exceed the range of boolean,
so we should modify q_support to unit8 bit.
drvdata->q_support = BMVAL(etmidr0, 15, 16)

Signed-off-by: Li Pengcheng <lipengcheng8 at huawei.com>
Signed-off-by: Li Zhong <lizhong11 at hisilicon.com>
Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
---
 drivers/hwtracing/coresight/coresight-etm4x.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index a291d4cc8bd8..5359c5197c1d 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -372,6 +372,7 @@ struct etmv4_drvdata {
 	u8				ccitmin;
 	u8				s_ex_level;
 	u8				ns_ex_level;
+	u8				q_support;
 	bool				sticky_enable;
 	bool				boot_enable;
 	bool				os_unlock;
@@ -380,7 +381,6 @@ struct etmv4_drvdata {
 	bool				trccond;
 	bool				retstack;
 	bool				trccci;
-	bool				q_support;
 	bool				trc_error;
 	bool				syncpr;
 	bool				stallctl;
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:35 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:35 -0600
Subject: [PATCH 01/27] coresight: no need to do the forced type conversion
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-2-git-send-email-mathieu.poirier@linaro.org>

From: lipengcheng <lipengcheng8 at huawei.com>

activated and enable are already unsigned type,
no need to change them to unsigned.

Signed-off-by: Li Pengcheng <lipengcheng8 at huawei.com>
Signed-off-by: Li Zhong <lizhong11 at hisilicon.com>
Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
---
 drivers/hwtracing/coresight/coresight.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 2ea5961092c1..945bc31f0ec5 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -514,7 +514,7 @@ static ssize_t enable_sink_show(struct device *dev,
 {
 	struct coresight_device *csdev = to_coresight_device(dev);
 
-	return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->activated);
+	return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->activated);
 }
 
 static ssize_t enable_sink_store(struct device *dev,
@@ -544,7 +544,7 @@ static ssize_t enable_source_show(struct device *dev,
 {
 	struct coresight_device *csdev = to_coresight_device(dev);
 
-	return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->enable);
+	return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->enable);
 }
 
 static ssize_t enable_source_store(struct device *dev,
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:37 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:37 -0600
Subject: [PATCH 03/27] stm class: Support devices that override software
 assigned masters
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-4-git-send-email-mathieu.poirier@linaro.org>

From: Alexander Shishkin <alexander.shishkin at linux.intel.com>

Some STM devices adjust software assigned master numbers depending on
the trace source and its runtime state and whatnot. This patch adds
a sysfs attribute to inform the trace-side software that master numbers
assigned to software sources will not match those in the STP stream,
so that, for example, master/channel allocation policy can be adjusted
accordingly.

Signed-off-by: Alexander Shishkin <alexander.shishkin at linux.intel.com>
---
 Documentation/ABI/testing/sysfs-class-stm | 10 ++++++++++
 drivers/hwtracing/stm/core.c              | 15 +++++++++++++++
 include/linux/stm.h                       |  3 +++
 3 files changed, 28 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-stm b/Documentation/ABI/testing/sysfs-class-stm
index c9aa4f3fc9a7..77ed3da0f68e 100644
--- a/Documentation/ABI/testing/sysfs-class-stm
+++ b/Documentation/ABI/testing/sysfs-class-stm
@@ -12,3 +12,13 @@ KernelVersion:	4.3
 Contact:	Alexander Shishkin <alexander.shishkin at linux.intel.com>
 Description:
 		Shows the number of channels per master on this STM device.
+
+What:		/sys/class/stm/<stm>/hw_override
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Alexander Shishkin <alexander.shishkin at linux.intel.com>
+Description:
+		Reads as 0 if master numbers in the STP stream produced by
+		this stm device will match the master numbers assigned by
+		the software or 1 if the stm hardware overrides software
+		assigned masters.
diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index 2591442e2c5b..ff31108b066f 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -67,9 +67,24 @@ static ssize_t channels_show(struct device *dev,
 
 static DEVICE_ATTR_RO(channels);
 
+static ssize_t hw_override_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct stm_device *stm = to_stm_device(dev);
+	int ret;
+
+	ret = sprintf(buf, "%u\n", stm->data->hw_override);
+
+	return ret;
+}
+
+static DEVICE_ATTR_RO(hw_override);
+
 static struct attribute *stm_attrs[] = {
 	&dev_attr_masters.attr,
 	&dev_attr_channels.attr,
+	&dev_attr_hw_override.attr,
 	NULL,
 };
 
diff --git a/include/linux/stm.h b/include/linux/stm.h
index 1a79ed8e43da..8369d8a8cabd 100644
--- a/include/linux/stm.h
+++ b/include/linux/stm.h
@@ -50,6 +50,8 @@ struct stm_device;
  * @sw_end:		last STP master available to software
  * @sw_nchannels:	number of STP channels per master
  * @sw_mmiosz:		size of one channel's IO space, for mmap, optional
+ * @hw_override:	masters in the STP stream will not match the ones
+ *			assigned by software, but are up to the STM hardware
  * @packet:		callback that sends an STP packet
  * @mmio_addr:		mmap callback, optional
  * @link:		called when a new stm_source gets linked to us, optional
@@ -85,6 +87,7 @@ struct stm_data {
 	unsigned int		sw_end;
 	unsigned int		sw_nchannels;
 	unsigned int		sw_mmiosz;
+	unsigned int		hw_override;
 	ssize_t			(*packet)(struct stm_data *, unsigned int,
 					  unsigned int, unsigned int,
 					  unsigned int, unsigned int,
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:38 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:38 -0600
Subject: [PATCH 04/27] coresight: adding path for STM device
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-5-git-send-email-mathieu.poirier@linaro.org>

>From a core framework point of view an STM device is a source that is
treated the same way as any other tracers.  Unlike tracers though STM
devices are not associated with a CPU.  As such it doesn't make sense
to associate the path from an STM device to its sink with a per-cpu
variable as it is done for tracers.

This patch simply adds another global variable to keep STM paths and the
processing in coresight_enable/disable() is updated to deal with STM
devices properly.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Signed-off-by: Chunyan Zhang <zhang.chunyan at linaro.org>
---
 drivers/hwtracing/coresight/coresight.c | 106 ++++++++++++++++++++++++--------
 1 file changed, 82 insertions(+), 24 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 945bc31f0ec5..0995df8f85bc 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -43,7 +43,15 @@ struct coresight_node {
  * When operating Coresight drivers from the sysFS interface, only a single
  * path can exist from a tracer (associated to a CPU) to a sink.
  */
-static DEFINE_PER_CPU(struct list_head *, sysfs_path);
+static DEFINE_PER_CPU(struct list_head *, tracer_path);
+
+/*
+ * As of this writing only a single STM can be found in CS topologies.  Since
+ * there is no way to know if we'll ever see more and what kind of
+ * configuration they will enact, for the time being only define a single path
+ * for STM.
+ */
+static struct list_head *stm_path;
 
 static int coresight_id_match(struct device *dev, void *data)
 {
@@ -432,18 +440,45 @@ void coresight_release_path(struct list_head *path)
 	path = NULL;
 }
 
+/** coresight_validate_source - make sure a source has the right credentials
+ *  @csdev:	the device structure for a source.
+ *  @function:	the function this was called from.
+ *
+ * Assumes the coresight_mutex is held.
+ */
+static int coresight_validate_source(struct coresight_device *csdev,
+				     const char *function)
+{
+	u32 type, subtype;
+
+	type = csdev->type;
+	subtype = csdev->subtype.source_subtype;
+
+	if (type != CORESIGHT_DEV_TYPE_SOURCE) {
+		dev_err(&csdev->dev, "wrong device type in %s\n", function);
+		return -EINVAL;
+	}
+
+	if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC &&
+	    subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE) {
+		dev_err(&csdev->dev, "wrong device subtype in %s\n", function);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 int coresight_enable(struct coresight_device *csdev)
 {
-	int ret = 0;
-	int cpu;
+	int cpu, ret = 0;
 	struct list_head *path;
 
 	mutex_lock(&coresight_mutex);
-	if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
-		ret = -EINVAL;
-		dev_err(&csdev->dev, "wrong device type in %s\n", __func__);
+
+	ret = coresight_validate_source(csdev, __func__);
+	if (ret)
 		goto out;
-	}
+
 	if (csdev->enable)
 		goto out;
 
@@ -461,15 +496,25 @@ int coresight_enable(struct coresight_device *csdev)
 	if (ret)
 		goto err_source;
 
-	/*
-	 * When working from sysFS it is important to keep track
-	 * of the paths that were created so that they can be
-	 * undone in 'coresight_disable()'.  Since there can only
-	 * be a single session per tracer (when working from sysFS)
-	 * a per-cpu variable will do just fine.
-	 */
-	cpu = source_ops(csdev)->cpu_id(csdev);
-	per_cpu(sysfs_path, cpu) = path;
+	switch (csdev->subtype.source_subtype) {
+	case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
+		/*
+		 * When working from sysFS it is important to keep track
+		 * of the paths that were created so that they can be
+		 * undone in 'coresight_disable()'.  Since there can only
+		 * be a single session per tracer (when working from sysFS)
+		 * a per-cpu variable will do just fine.
+		 */
+		cpu = source_ops(csdev)->cpu_id(csdev);
+		per_cpu(tracer_path, cpu) = path;
+		break;
+	case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
+		stm_path = path;
+		break;
+	default:
+		/* We can't be here */
+		break;
+	}
 
 out:
 	mutex_unlock(&coresight_mutex);
@@ -486,23 +531,36 @@ EXPORT_SYMBOL_GPL(coresight_enable);
 
 void coresight_disable(struct coresight_device *csdev)
 {
-	int cpu;
-	struct list_head *path;
+	int cpu, ret;
+	struct list_head *path = NULL;
 
 	mutex_lock(&coresight_mutex);
-	if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
-		dev_err(&csdev->dev, "wrong device type in %s\n", __func__);
+
+	ret = coresight_validate_source(csdev, __func__);
+	if (ret)
 		goto out;
-	}
+
 	if (!csdev->enable)
 		goto out;
 
-	cpu = source_ops(csdev)->cpu_id(csdev);
-	path = per_cpu(sysfs_path, cpu);
+	switch (csdev->subtype.source_subtype) {
+	case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
+		cpu = source_ops(csdev)->cpu_id(csdev);
+		path = per_cpu(tracer_path, cpu);
+		per_cpu(tracer_path, cpu) = NULL;
+		break;
+	case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
+		path = stm_path;
+		stm_path = NULL;
+		break;
+	default:
+		/* We can't be here */
+		break;
+	}
+
 	coresight_disable_source(csdev);
 	coresight_disable_path(path);
 	coresight_release_path(path);
-	per_cpu(sysfs_path, cpu) = NULL;
 
 out:
 	mutex_unlock(&coresight_mutex);
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:39 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:39 -0600
Subject: [PATCH 05/27] coresight: stm: Bindings for System Trace Macrocell
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-6-git-send-email-mathieu.poirier@linaro.org>

The System Trace Macrocell (STM) is an IP block falling under the
CoreSight umbrella.  It's main purpose it so expose stimulus channels
to any system component for the purpose of information logging.

Bindings for this IP block adds a couple of items to the current
mandatory definition for CoreSight components.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Acked-by: Rob Herring <robh at kernel.org>
Signed-off-by: Chunyan Zhang <zhang.chunyan at linaro.org>
---
 .../devicetree/bindings/arm/coresight.txt          | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
index 62938eb9697f..93147c0c8a0e 100644
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -19,6 +19,7 @@ its hardware characteristcs.
 		- "arm,coresight-etm3x", "arm,primecell";
 		- "arm,coresight-etm4x", "arm,primecell";
 		- "qcom,coresight-replicator1x", "arm,primecell";
+		- "arm,coresight-stm", "arm,primecell"; [1]
 
 	* reg: physical base address and length of the register
 	  set(s) of the component.
@@ -36,6 +37,14 @@ its hardware characteristcs.
 	  layout using the generic DT graph presentation found in
 	  "bindings/graph.txt".
 
+* Additional required properties for System Trace Macrocells (STM):
+	* reg: along with the physical base address and length of the register
+	  set as described above, another entry is required to describe the
+	  mapping of the extended stimulus port area.
+
+	* reg-names: the only acceptable values are "stm-base" and
+	  "stm-stimulus-base", each corresponding to the areas defined in "reg".
+
 * Required properties for devices that don't show up on the AMBA bus, such as
   non-configurable replicators:
 
@@ -202,3 +211,22 @@ Example:
 			};
 		};
 	};
+
+4. STM
+	stm at 20100000 {
+		compatible = "arm,coresight-stm", "arm,primecell";
+		reg = <0 0x20100000 0 0x1000>,
+		      <0 0x28000000 0 0x180000>;
+		reg-names = "stm-base", "stm-stimulus-base";
+
+		clocks = <&soc_smc50mhz>;
+		clock-names = "apb_pclk";
+		port {
+			stm_out_port: endpoint {
+				remote-endpoint = <&main_funnel_in_port2>;
+			};
+		};
+	};
+
+[1]. There is currently two version of STM: STM32 and STM500.  Both
+have the same HW interface and as such don't need an explicit binding name.
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:41 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:41 -0600
Subject: [PATCH 07/27] coresight: etb10: fixing the right amount of words to
 read
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-8-git-send-email-mathieu.poirier@linaro.org>

This patch rectifies the amount of words to read when the internal
buffer is deemed bigger than the amount of space available in the
perf ring buffer.

The amount to read is set to the amount of space in the perf ring
buffer rather than being subtracted by it.

Reported-by: Suzuki K Poulose <Suzuki.Poulose at arm.com>
Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
---
 drivers/hwtracing/coresight/coresight-etb10.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 2461d5c8c157..b0d402dbfeae 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -440,7 +440,7 @@ static void etb_update_buffer(struct coresight_device *csdev,
 		u32 mask = ~(ETB_FRAME_SIZE_WORDS - 1);
 
 		/* The new read pointer must be frame size aligned */
-		to_read -= handle->size & mask;
+		to_read = handle->size & mask;
 		/*
 		 * Move the RAM read pointer up, keeping in mind that
 		 * everything is in frame size units.
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:43 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:43 -0600
Subject: [PATCH 09/27] coresight: tmc: adding sysFS management entries
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-10-git-send-email-mathieu.poirier@linaro.org>

Adding management registers that convey implementation
specific characteristics.  Those are useful for trace
configuration and collection along with general trouble
shooting.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
---
 .../ABI/testing/sysfs-bus-coresight-devices-tmc    |  77 +++++++++++++++
 drivers/hwtracing/coresight/coresight-tmc.c        | 107 +++++++++------------
 2 files changed, 120 insertions(+), 64 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc
index f38cded5fa22..4fe677ed1305 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc
@@ -6,3 +6,80 @@ Description:	(RW) Disables write access to the Trace RAM by stopping the
 		formatter after a defined number of words have been stored
 		following the trigger event. Additional interface for this
 		driver are expected to be added as it matures.
+
+What:           /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/rsz
+Date:           March 2016
+KernelVersion:  4.7
+Contact:        Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:    (R) Defines the size, in 32-bit words, of the local RAM buffer.
+                The value is read directly from HW register RSZ, 0x004.
+
+What:           /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/sts
+Date:           March 2016
+KernelVersion:  4.7
+Contact:        Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(R) Shows the value held by the TMC status register.  The value
+                is read directly from HW register STS, 0x00C.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/rrp
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(R) Shows the value held by the TMC RAM Read Pointer register
+		that is used to read entries from the Trace RAM over the APB
+		interface.  The value is read directly from HW register RRP,
+		0x014.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/rwp
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(R) Shows the value held by the TMC RAM Write Pointer register
+		that is used to sets the write pointer to write entries from
+		the CoreSight bus into the Trace RAM. The value is read directly
+		from HW register RWP, 0x018.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/trg
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(R) Similar to "trigger_cntr" above except that this value is
+		read directly from HW register TRG, 0x01C.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/ctl
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(R) Shows the value held by the TMC Control register. The value
+		is read directly from HW register CTL, 0x020.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/ffsr
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(R) Shows the value held by the TMC Formatter and Flush Status
+		register.  The value is read directly from HW register FFSR,
+		0x300.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/ffcr
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(R) Shows the value held by the TMC Formatter and Flush Control
+		register.  The value is read directly from HW register FFCR,
+		0x304.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/mode
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(R) Shows the value held by the TMC Mode register, which
+		indicate the mode the device has been configured to enact.  The
+		The value is read directly from the MODE register, 0x028.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/devid
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(R) Indicates the capabilities of the Coresight TMC.
+		The value is read directly from the DEVID register, 0xFC8,
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 0a4db1ac52ae..2b42ecbd8831 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -556,56 +556,38 @@ static const struct file_operations tmc_fops = {
 	.llseek		= no_llseek,
 };
 
-static ssize_t status_show(struct device *dev,
-			   struct device_attribute *attr, char *buf)
-{
-	unsigned long flags;
-	u32 tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg;
-	u32 tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr;
-	u32 devid;
-	struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	pm_runtime_get_sync(drvdata->dev);
-	spin_lock_irqsave(&drvdata->spinlock, flags);
-	CS_UNLOCK(drvdata->base);
-
-	tmc_rsz = readl_relaxed(drvdata->base + TMC_RSZ);
-	tmc_sts = readl_relaxed(drvdata->base + TMC_STS);
-	tmc_rrp = readl_relaxed(drvdata->base + TMC_RRP);
-	tmc_rwp = readl_relaxed(drvdata->base + TMC_RWP);
-	tmc_trg = readl_relaxed(drvdata->base + TMC_TRG);
-	tmc_ctl = readl_relaxed(drvdata->base + TMC_CTL);
-	tmc_ffsr = readl_relaxed(drvdata->base + TMC_FFSR);
-	tmc_ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
-	tmc_mode = readl_relaxed(drvdata->base + TMC_MODE);
-	tmc_pscr = readl_relaxed(drvdata->base + TMC_PSCR);
-	devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
-
-	CS_LOCK(drvdata->base);
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
-	pm_runtime_put(drvdata->dev);
-
-	return sprintf(buf,
-		       "Depth:\t\t0x%x\n"
-		       "Status:\t\t0x%x\n"
-		       "RAM read ptr:\t0x%x\n"
-		       "RAM wrt ptr:\t0x%x\n"
-		       "Trigger cnt:\t0x%x\n"
-		       "Control:\t0x%x\n"
-		       "Flush status:\t0x%x\n"
-		       "Flush ctrl:\t0x%x\n"
-		       "Mode:\t\t0x%x\n"
-		       "PSRC:\t\t0x%x\n"
-		       "DEVID:\t\t0x%x\n",
-			tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg,
-			tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr, devid);
-
-	return -EINVAL;
-}
-static DEVICE_ATTR_RO(status);
+#define coresight_tmc_simple_func(name, offset)			\
+	coresight_simple_func(struct tmc_drvdata, name, offset)
+
+coresight_tmc_simple_func(rsz, TMC_RSZ);
+coresight_tmc_simple_func(sts, TMC_STS);
+coresight_tmc_simple_func(rrp, TMC_RRP);
+coresight_tmc_simple_func(rwp, TMC_RWP);
+coresight_tmc_simple_func(trg, TMC_TRG);
+coresight_tmc_simple_func(ctl, TMC_CTL);
+coresight_tmc_simple_func(ffsr, TMC_FFSR);
+coresight_tmc_simple_func(ffcr, TMC_FFCR);
+coresight_tmc_simple_func(mode, TMC_MODE);
+coresight_tmc_simple_func(pscr, TMC_PSCR);
+coresight_tmc_simple_func(devid, CORESIGHT_DEVID);
+
+static struct attribute *coresight_tmc_mgmt_attrs[] = {
+	&dev_attr_rsz.attr,
+	&dev_attr_sts.attr,
+	&dev_attr_rrp.attr,
+	&dev_attr_rwp.attr,
+	&dev_attr_trg.attr,
+	&dev_attr_ctl.attr,
+	&dev_attr_ffsr.attr,
+	&dev_attr_ffcr.attr,
+	&dev_attr_mode.attr,
+	&dev_attr_pscr.attr,
+	&dev_attr_devid.attr,
+	NULL,
+};
 
-static ssize_t trigger_cntr_show(struct device *dev,
-			    struct device_attribute *attr, char *buf)
+ssize_t trigger_cntr_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
 {
 	struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->trigger_cntr;
@@ -630,26 +612,25 @@ static ssize_t trigger_cntr_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(trigger_cntr);
 
-static struct attribute *coresight_etb_attrs[] = {
+static struct attribute *coresight_tmc_attrs[] = {
 	&dev_attr_trigger_cntr.attr,
-	&dev_attr_status.attr,
 	NULL,
 };
-ATTRIBUTE_GROUPS(coresight_etb);
 
-static struct attribute *coresight_etr_attrs[] = {
-	&dev_attr_trigger_cntr.attr,
-	&dev_attr_status.attr,
-	NULL,
+static const struct attribute_group coresight_tmc_group = {
+	.attrs = coresight_tmc_attrs,
 };
-ATTRIBUTE_GROUPS(coresight_etr);
 
-static struct attribute *coresight_etf_attrs[] = {
-	&dev_attr_trigger_cntr.attr,
-	&dev_attr_status.attr,
+static const struct attribute_group coresight_tmc_mgmt_group = {
+	.attrs = coresight_tmc_mgmt_attrs,
+	.name = "mgmt",
+};
+
+const struct attribute_group *coresight_tmc_groups[] = {
+	&coresight_tmc_group,
+	&coresight_tmc_mgmt_group,
 	NULL,
 };
-ATTRIBUTE_GROUPS(coresight_etf);
 
 static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 {
@@ -725,20 +706,18 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 	desc->pdata = pdata;
 	desc->dev = dev;
 	desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+	desc->groups = coresight_tmc_groups;
 
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
 		desc->type = CORESIGHT_DEV_TYPE_SINK;
 		desc->ops = &tmc_etb_cs_ops;
-		desc->groups = coresight_etb_groups;
 	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
 		desc->type = CORESIGHT_DEV_TYPE_SINK;
 		desc->ops = &tmc_etr_cs_ops;
-		desc->groups = coresight_etr_groups;
 	} else {
 		desc->type = CORESIGHT_DEV_TYPE_LINKSINK;
 		desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
 		desc->ops = &tmc_etf_cs_ops;
-		desc->groups = coresight_etf_groups;
 	}
 
 	drvdata->csdev = coresight_register(desc);
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:42 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:42 -0600
Subject: [PATCH 08/27] coresight: etm4x: add tracer ID for A72 Maia processor.
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-9-git-send-email-mathieu.poirier@linaro.org>

From: lipengcheng <lipengcheng8 at huawei.com>

This patch adds a cellID for the ETMv4 tracer found on
HiSillicon's A72 Maia processor.

Signed-off-by: Li Pengcheng <lipengcheng8 at huawei.com>
Signed-off-by: Li Zhong <lizhong11 at hisilicon.com>
Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
---
 drivers/hwtracing/coresight/coresight-etm4x.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index 6396b28993da..462f0dc15757 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -825,6 +825,11 @@ static struct amba_id etm4_ids[] = {
 		.mask	= 0x000fffff,
 		.data	= "ETM 4.0",
 	},
+	{       /* ETM 4.0 - A72, Maia, HiSilicon */
+		.id = 0x000bb95a,
+		.mask = 0x000fffff,
+		.data = "ETM 4.0",
+	},
 	{ 0, 0},
 };
 
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:40 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:40 -0600
Subject: [PATCH 06/27] coresight: stm: adding driver for CoreSight STM
 component
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-7-git-send-email-mathieu.poirier@linaro.org>

From: Pratik Patel <pratikp at codeaurora.org>

This driver adds support for the STM CoreSight IP block, allowing any
system compoment (HW or SW) to log and aggregate messages via a
single entity.

The CoreSight STM exposes an application defined number of channels
called stimulus port.  Configuration is done using entries in sysfs
and channels made available to userspace via configfs.

Signed-off-by: Pratik Patel <pratikp at codeaurora.org>
Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Michael Williams <michael.williams at arm.com>
Signed-off-by: Chunyan Zhang <zhang.chunyan at linaro.org>
---
 .../ABI/testing/sysfs-bus-coresight-devices-stm    |  53 ++
 Documentation/trace/coresight.txt                  |  37 +-
 drivers/hwtracing/coresight/Kconfig                |  11 +
 drivers/hwtracing/coresight/Makefile               |   1 +
 drivers/hwtracing/coresight/coresight-stm.c        | 920 +++++++++++++++++++++
 include/linux/coresight-stm.h                      |   6 +
 include/uapi/linux/coresight-stm.h                 |  21 +
 7 files changed, 1047 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-stm
 create mode 100644 drivers/hwtracing/coresight/coresight-stm.c
 create mode 100644 include/linux/coresight-stm.h
 create mode 100644 include/uapi/linux/coresight-stm.h

diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-stm b/Documentation/ABI/testing/sysfs-bus-coresight-devices-stm
new file mode 100644
index 000000000000..1dffabe7f48d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-stm
@@ -0,0 +1,53 @@
+What:		/sys/bus/coresight/devices/<memory_map>.stm/enable_source
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(RW) Enable/disable tracing on this specific trace macrocell.
+		Enabling the trace macrocell implies it has been configured
+		properly and a sink has been identified for it.  The path
+		of coresight components linking the source to the sink is
+		configured and managed automatically by the coresight framework.
+
+What:		/sys/bus/coresight/devices/<memory_map>.stm/hwevent_enable
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(RW) Provides access to the HW event enable register, used in
+		conjunction with HW event bank select register.
+
+What:		/sys/bus/coresight/devices/<memory_map>.stm/hwevent_select
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(RW) Gives access to the HW event block select register
+		(STMHEBSR) in order to configure up to 256 channels.  Used in
+		conjunction with "hwevent_enable" register as described above.
+
+What:		/sys/bus/coresight/devices/<memory_map>.stm/port_enable
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(RW) Provides access to the stimulus port enable register
+		(STMSPER).  Used in conjunction with "port_select" described
+		below.
+
+What:		/sys/bus/coresight/devices/<memory_map>.stm/port_select
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(RW) Used to determine which bank of stimulus port bit in
+		register STMSPER (see above) apply to.
+
+What:		/sys/bus/coresight/devices/<memory_map>.stm/status
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(R) List various control and status registers.  The specific
+		layout and content is driver specific.
+
+What:		/sys/bus/coresight/devices/<memory_map>.stm/traceid
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier at linaro.org>
+Description:	(RW) Holds the trace ID that will appear in the trace stream
+		coming from this trace entity.
diff --git a/Documentation/trace/coresight.txt b/Documentation/trace/coresight.txt
index 0a5c3290e732..a33c88cd5d1d 100644
--- a/Documentation/trace/coresight.txt
+++ b/Documentation/trace/coresight.txt
@@ -190,8 +190,8 @@ expected to be accessed and controlled using those entries.
 Last but not least, "struct module *owner" is expected to be set to reflect
 the information carried in "THIS_MODULE".
 
-How to use
-----------
+How to use the tracer modules
+-----------------------------
 
 Before trace collection can start, a coresight sink needs to be identify.
 There is no limit on the amount of sinks (nor sources) that can be enabled at
@@ -297,3 +297,36 @@ Info                                    Tracing enabled
 Instruction     13570831        0x8026B584      E28DD00C        false   ADD      sp,sp,#0xc
 Instruction     0       0x8026B588      E8BD8000        true    LDM      sp!,{pc}
 Timestamp                                       Timestamp: 17107041535
+
+How to use the STM module
+-------------------------
+
+Using the System Trace Macrocell module is the same as the tracers - the only
+difference is that clients are driving the trace capture rather
+than the program flow through the code.
+
+As with any other CoreSight component, specifics about the STM tracer can be
+found in sysfs with more information on each entry being found in [1]:
+
+root at genericarmv8:~# ls /sys/bus/coresight/devices/20100000.stm
+enable_source   hwevent_select  port_enable     subsystem       uevent
+hwevent_enable  mgmt            port_select     traceid
+root at genericarmv8:~#
+
+Like any other source a sink needs to be identified and the STM enabled before
+being used:
+
+root at genericarmv8:~# echo 1 > /sys/bus/coresight/devices/20010000.etf/enable_sink
+root at genericarmv8:~# echo 1 > /sys/bus/coresight/devices/20100000.stm/enable_source
+
+From there user space applications can request and use channels using the devfs
+interface provided for that purpose by the generic STM API:
+
+root at genericarmv8:~# ls -l /dev/20100000.stm
+crw-------    1 root     root       10,  61 Jan  3 18:11 /dev/20100000.stm
+root at genericarmv8:~#
+
+Details on how to use the generic STM API can be found here [2].
+
+[1]. Documentation/ABI/testing/sysfs-bus-coresight-devices-stm
+[2]. Documentation/trace/stm.txt
diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index db0541031c72..130cb2114059 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -78,4 +78,15 @@ config CORESIGHT_QCOM_REPLICATOR
 	  programmable ATB replicator sends the ATB trace stream from the
 	  ETB/ETF to the TPIUi and ETR.
 
+config CORESIGHT_STM
+	bool "CoreSight System Trace Macrocell driver"
+	depends on (ARM && !(CPU_32v3 || CPU_32v4 || CPU_32v4T)) || ARM64
+	select CORESIGHT_LINKS_AND_SINKS
+	select STM
+	help
+	  This driver provides support for hardware assisted software
+	  instrumentation based tracing. This is primarily used for
+	  logging useful software events or data coming from various entities
+	  in the system, possibly running different OSs
+
 endif
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 1d0e32c7dbe4..c6f84b57f52a 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o coresight-etm-cp14.o \
 obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \
 					coresight-etm4x-sysfs.o
 obj-$(CONFIG_CORESIGHT_QCOM_REPLICATOR) += coresight-replicator-qcom.o
+obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
new file mode 100644
index 000000000000..73be58a11e4f
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -0,0 +1,920 @@
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * Description: CoreSight System Trace Macrocell 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Initial implementation by Pratik Patel
+ * (C) 2014-2015 Pratik Patel <pratikp at codeaurora.org>
+ *
+ * Serious refactoring, code cleanup and upgrading to the Coresight upstream
+ * framework by Mathieu Poirier
+ * (C) 2015-2016 Mathieu Poirier <mathieu.poirier at linaro.org>
+ *
+ * Guaranteed timing and support for various packet type coming from the
+ * generic STM API by Chunyan Zhang
+ * (C) 2015-2016 Chunyan Zhang <zhang.chunyan at linaro.org>
+ */
+#include <asm/local.h>
+#include <linux/amba/bus.h>
+#include <linux/bitmap.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
+#include <linux/coresight-stm.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/of_address.h>
+#include <linux/perf_event.h>
+#include <linux/pm_runtime.h>
+#include <linux/stm.h>
+
+#include "coresight-priv.h"
+
+#define STMDMASTARTR			0xc04
+#define STMDMASTOPR			0xc08
+#define STMDMASTATR			0xc0c
+#define STMDMACTLR			0xc10
+#define STMDMAIDR			0xcfc
+#define STMHEER				0xd00
+#define STMHETER			0xd20
+#define STMHEBSR			0xd60
+#define STMHEMCR			0xd64
+#define STMHEMASTR			0xdf4
+#define STMHEFEAT1R			0xdf8
+#define STMHEIDR			0xdfc
+#define STMSPER				0xe00
+#define STMSPTER			0xe20
+#define STMPRIVMASKR			0xe40
+#define STMSPSCR			0xe60
+#define STMSPMSCR			0xe64
+#define STMSPOVERRIDER			0xe68
+#define STMSPMOVERRIDER			0xe6c
+#define STMSPTRIGCSR			0xe70
+#define STMTCSR				0xe80
+#define STMTSSTIMR			0xe84
+#define STMTSFREQR			0xe8c
+#define STMSYNCR			0xe90
+#define STMAUXCR			0xe94
+#define STMSPFEAT1R			0xea0
+#define STMSPFEAT2R			0xea4
+#define STMSPFEAT3R			0xea8
+#define STMITTRIGGER			0xee8
+#define STMITATBDATA0			0xeec
+#define STMITATBCTR2			0xef0
+#define STMITATBID			0xef4
+#define STMITATBCTR0			0xef8
+
+#define STM_32_CHANNEL			32
+#define BYTES_PER_CHANNEL		256
+#define STM_TRACE_BUF_SIZE		4096
+#define STM_SW_MASTER_END		127
+
+/* Register bit definition */
+#define STMTCSR_BUSY_BIT		23
+/* Reserve the first 10 channels for kernel usage */
+#define STM_CHANNEL_OFFSET		0
+
+enum stm_pkt_type {
+	STM_PKT_TYPE_DATA	= 0x98,
+	STM_PKT_TYPE_FLAG	= 0xE8,
+	STM_PKT_TYPE_TRIG	= 0xF8,
+};
+
+#define stm_channel_addr(drvdata, ch)	(drvdata->chs.base +	\
+					(ch * BYTES_PER_CHANNEL))
+#define stm_channel_off(type, opts)	(type & ~opts)
+
+static int boot_nr_channel;
+
+/*
+ * Not really modular but using module_param is the easiest way to
+ * remain consistent with existing use cases for now.
+ */
+module_param_named(
+	boot_nr_channel, boot_nr_channel, int, S_IRUGO
+);
+
+/**
+ * struct channel_space - central management entity for extended ports
+ * @base:		memory mapped base address where channels start.
+ * @guaraneed:		is the channel delivery guaranteed.
+ */
+struct channel_space {
+	void __iomem		*base;
+	unsigned long		*guaranteed;
+};
+
+/**
+ * struct stm_drvdata - specifics associated to an STM component
+ * @base:		memory mapped base address for this component.
+ * @dev:		the device entity associated to this component.
+ * @atclk:		optional clock for the core parts of the STM.
+ * @csdev:		component vitals needed by the framework.
+ * @spinlock:		only one at a time pls.
+ * @chs:		the channels accociated to this STM.
+ * @stm:		structure associated to the generic STM interface.
+ * @mode:		this tracer's mode, i.e sysFS, or disabled.
+ * @traceid:		value of the current ID for this component.
+ * @write_bytes:	Maximus bytes this STM can write at a time.
+ * @stmsper:		settings for register STMSPER.
+ * @stmspscr:		settings for register STMSPSCR.
+ * @numsp:		the total number of stimulus port support by this STM.
+ * @stmheer:		settings for register STMHEER.
+ * @stmheter:		settings for register STMHETER.
+ * @stmhebsr:		settings for register STMHEBSR.
+ */
+struct stm_drvdata {
+	void __iomem		*base;
+	struct device		*dev;
+	struct clk		*atclk;
+	struct coresight_device	*csdev;
+	spinlock_t		spinlock;
+	struct channel_space	chs;
+	struct stm_data		stm;
+	local_t			mode;
+	u8			traceid;
+	u32			write_bytes;
+	u32			stmsper;
+	u32			stmspscr;
+	u32			numsp;
+	u32			stmheer;
+	u32			stmheter;
+	u32			stmhebsr;
+};
+
+static void stm_hwevent_enable_hw(struct stm_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	writel_relaxed(drvdata->stmhebsr, drvdata->base + STMHEBSR);
+	writel_relaxed(drvdata->stmheter, drvdata->base + STMHETER);
+	writel_relaxed(drvdata->stmheer, drvdata->base + STMHEER);
+	writel_relaxed(0x01 |	/* Enable HW event tracing */
+		       0x04,	/* Error detection on event tracing */
+		       drvdata->base + STMHEMCR);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void stm_port_enable_hw(struct stm_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+	/* ATB trigger enable on direct writes to TRIG locations */
+	writel_relaxed(0x10,
+		       drvdata->base + STMSPTRIGCSR);
+	writel_relaxed(drvdata->stmspscr, drvdata->base + STMSPSCR);
+	writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void stm_enable_hw(struct stm_drvdata *drvdata)
+{
+	if (drvdata->stmheer)
+		stm_hwevent_enable_hw(drvdata);
+
+	stm_port_enable_hw(drvdata);
+
+	CS_UNLOCK(drvdata->base);
+
+	/* 4096 byte between synchronisation packets */
+	writel_relaxed(0xFFF, drvdata->base + STMSYNCR);
+	writel_relaxed((drvdata->traceid << 16 | /* trace id */
+			0x02 |			 /* timestamp enable */
+			0x01),			 /* global STM enable */
+			drvdata->base + STMTCSR);
+
+	CS_LOCK(drvdata->base);
+}
+
+static int stm_enable(struct coresight_device *csdev,
+		      struct perf_event_attr *attr, u32 mode)
+{
+	u32 val;
+	struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	if (mode != CS_MODE_SYSFS)
+		return -EINVAL;
+
+	val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);
+
+	/* Someone is already using the tracer */
+	if (val)
+		return -EBUSY;
+
+	pm_runtime_get_sync(drvdata->dev);
+
+	spin_lock(&drvdata->spinlock);
+	stm_enable_hw(drvdata);
+	spin_unlock(&drvdata->spinlock);
+
+	dev_info(drvdata->dev, "STM tracing enabled\n");
+	return 0;
+}
+
+static void stm_hwevent_disable_hw(struct stm_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	writel_relaxed(0x0, drvdata->base + STMHEMCR);
+	writel_relaxed(0x0, drvdata->base + STMHEER);
+	writel_relaxed(0x0, drvdata->base + STMHETER);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void stm_port_disable_hw(struct stm_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	writel_relaxed(0x0, drvdata->base + STMSPER);
+	writel_relaxed(0x0, drvdata->base + STMSPTRIGCSR);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void stm_disable_hw(struct stm_drvdata *drvdata)
+{
+	u32 val;
+
+	CS_UNLOCK(drvdata->base);
+
+	val = readl_relaxed(drvdata->base + STMTCSR);
+	val &= ~0x1; /* clear global STM enable [0] */
+	writel_relaxed(val, drvdata->base + STMTCSR);
+
+	CS_LOCK(drvdata->base);
+
+	stm_port_disable_hw(drvdata);
+	if (drvdata->stmheer)
+		stm_hwevent_disable_hw(drvdata);
+}
+
+static void stm_disable(struct coresight_device *csdev)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	/*
+	 * For as long as the tracer isn't disabled another entity can't
+	 * change its status.  As such we can read the status here without
+	 * fearing it will change under us.
+	 */
+	if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
+		spin_lock(&drvdata->spinlock);
+		stm_disable_hw(drvdata);
+		spin_unlock(&drvdata->spinlock);
+
+		/* Wait until the engine has completely stopped */
+		coresight_timeout(drvdata, STMTCSR, STMTCSR_BUSY_BIT, 0);
+
+		pm_runtime_put(drvdata->dev);
+
+		local_set(&drvdata->mode, CS_MODE_DISABLED);
+		dev_info(drvdata->dev, "STM tracing disabled\n");
+	}
+}
+
+static int stm_trace_id(struct coresight_device *csdev)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	return drvdata->traceid;
+}
+
+static const struct coresight_ops_source stm_source_ops = {
+	.trace_id	= stm_trace_id,
+	.enable		= stm_enable,
+	.disable	= stm_disable,
+};
+
+static const struct coresight_ops stm_cs_ops = {
+	.source_ops	= &stm_source_ops,
+};
+
+static inline bool stm_addr_unaligned(const void *addr, u8 write_bytes)
+{
+	return ((unsigned long)addr & (write_bytes - 1));
+}
+
+static void stm_send(void *addr, const void *data, u32 size, u8 write_bytes)
+{
+	u8 paload[8];
+
+	if (stm_addr_unaligned(data, write_bytes)) {
+		memcpy(paload, data, size);
+		data = paload;
+	}
+
+	/* now we are 64bit/32bit aligned */
+	switch (size) {
+#ifdef CONFIG_64BIT
+	case 8:
+		writeq_relaxed(*(u64 *)data, addr);
+		break;
+#endif
+	case 4:
+		writel_relaxed(*(u32 *)data, addr);
+		break;
+	case 2:
+		writew_relaxed(*(u16 *)data, addr);
+		break;
+	case 1:
+		writeb_relaxed(*(u8 *)data, addr);
+		break;
+	default:
+		break;
+	}
+}
+
+static int stm_generic_link(struct stm_data *stm_data,
+			    unsigned int master,  unsigned int channel)
+{
+	struct stm_drvdata *drvdata = container_of(stm_data,
+						   struct stm_drvdata, stm);
+	if (!drvdata || !drvdata->csdev)
+		return -EINVAL;
+
+	return coresight_enable(drvdata->csdev);
+}
+
+static void stm_generic_unlink(struct stm_data *stm_data,
+			       unsigned int master,  unsigned int channel)
+{
+	struct stm_drvdata *drvdata = container_of(stm_data,
+						   struct stm_drvdata, stm);
+	if (!drvdata || !drvdata->csdev)
+		return;
+
+	stm_disable(drvdata->csdev);
+}
+
+static long stm_generic_set_options(struct stm_data *stm_data,
+				    unsigned int master,
+				    unsigned int channel,
+				    unsigned int nr_chans,
+				    unsigned long options)
+{
+	struct stm_drvdata *drvdata = container_of(stm_data,
+						   struct stm_drvdata, stm);
+	if (!(drvdata && local_read(&drvdata->mode)))
+		return -EINVAL;
+
+	if (channel >= drvdata->numsp)
+		return -EINVAL;
+
+	switch (options) {
+	case STM_OPTION_GUARANTEED:
+		set_bit(channel, drvdata->chs.guaranteed);
+		break;
+
+	case STM_OPTION_INVARIANT:
+		clear_bit(channel, drvdata->chs.guaranteed);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static ssize_t stm_generic_packet(struct stm_data *stm_data,
+				  unsigned int master,
+				  unsigned int channel,
+				  unsigned int packet,
+				  unsigned int flags,
+				  unsigned int size,
+				  const unsigned char *payload)
+{
+	unsigned long ch_addr;
+	struct stm_drvdata *drvdata = container_of(stm_data,
+						   struct stm_drvdata, stm);
+
+	if (!(drvdata && local_read(&drvdata->mode)))
+		return 0;
+
+	if (channel >= drvdata->numsp)
+		return 0;
+
+	ch_addr = (unsigned long)stm_channel_addr(drvdata, channel);
+
+	flags = (flags == STP_PACKET_TIMESTAMPED) ? STM_FLAG_TIMESTAMPED : 0;
+	flags |= test_bit(channel, drvdata->chs.guaranteed) ?
+			   STM_FLAG_GUARANTEED : 0;
+
+	if (size > drvdata->write_bytes)
+		size = drvdata->write_bytes;
+	else
+		size = rounddown_pow_of_two(size);
+
+	switch (packet) {
+	case STP_PACKET_FLAG:
+		ch_addr |= stm_channel_off(STM_PKT_TYPE_FLAG, flags);
+
+		/*
+		 * The generic STM core sets a size of '0' on flag packets.
+		 * As such send a flag packet of size '1' and tell the
+		 * core we did so.
+		 */
+		stm_send((void *)ch_addr, payload, 1, drvdata->write_bytes);
+		size = 1;
+		break;
+
+	case STP_PACKET_DATA:
+		ch_addr |= stm_channel_off(STM_PKT_TYPE_DATA, flags);
+		stm_send((void *)ch_addr, payload, size,
+				drvdata->write_bytes);
+		break;
+
+	default:
+		return -ENOTSUPP;
+	}
+
+	return size;
+}
+
+static ssize_t hwevent_enable_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val = drvdata->stmheer;
+
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t hwevent_enable_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t size)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+	int ret = 0;
+
+	ret = kstrtoul(buf, 16, &val);
+	if (ret)
+		return -EINVAL;
+
+	drvdata->stmheer = val;
+	/* HW event enable and trigger go hand in hand */
+	drvdata->stmheter = val;
+
+	return size;
+}
+static DEVICE_ATTR_RW(hwevent_enable);
+
+static ssize_t hwevent_select_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val = drvdata->stmhebsr;
+
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t hwevent_select_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t size)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+	int ret = 0;
+
+	ret = kstrtoul(buf, 16, &val);
+	if (ret)
+		return -EINVAL;
+
+	drvdata->stmhebsr = val;
+
+	return size;
+}
+static DEVICE_ATTR_RW(hwevent_select);
+
+static ssize_t port_select_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+
+	if (!local_read(&drvdata->mode)) {
+		val = drvdata->stmspscr;
+	} else {
+		spin_lock(&drvdata->spinlock);
+		val = readl_relaxed(drvdata->base + STMSPSCR);
+		spin_unlock(&drvdata->spinlock);
+	}
+
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t port_select_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t size)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val, stmsper;
+	int ret = 0;
+
+	ret = kstrtoul(buf, 16, &val);
+	if (ret)
+		return ret;
+
+	spin_lock(&drvdata->spinlock);
+	drvdata->stmspscr = val;
+
+	if (local_read(&drvdata->mode)) {
+		CS_UNLOCK(drvdata->base);
+		/* Process as per ARM's TRM recommendation */
+		stmsper = readl_relaxed(drvdata->base + STMSPER);
+		writel_relaxed(0x0, drvdata->base + STMSPER);
+		writel_relaxed(drvdata->stmspscr, drvdata->base + STMSPSCR);
+		writel_relaxed(stmsper, drvdata->base + STMSPER);
+		CS_LOCK(drvdata->base);
+	}
+	spin_unlock(&drvdata->spinlock);
+
+	return size;
+}
+static DEVICE_ATTR_RW(port_select);
+
+static ssize_t port_enable_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+
+	if (!local_read(&drvdata->mode)) {
+		val = drvdata->stmsper;
+	} else {
+		spin_lock(&drvdata->spinlock);
+		val = readl_relaxed(drvdata->base + STMSPER);
+		spin_unlock(&drvdata->spinlock);
+	}
+
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t port_enable_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t size)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+	int ret = 0;
+
+	ret = kstrtoul(buf, 16, &val);
+	if (ret)
+		return ret;
+
+	spin_lock(&drvdata->spinlock);
+	drvdata->stmsper = val;
+
+	if (local_read(&drvdata->mode)) {
+		CS_UNLOCK(drvdata->base);
+		writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER);
+		CS_LOCK(drvdata->base);
+	}
+	spin_unlock(&drvdata->spinlock);
+
+	return size;
+}
+static DEVICE_ATTR_RW(port_enable);
+
+static ssize_t traceid_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	unsigned long val;
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = drvdata->traceid;
+	return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t traceid_store(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t size)
+{
+	int ret;
+	unsigned long val;
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	ret = kstrtoul(buf, 16, &val);
+	if (ret)
+		return ret;
+
+	/* traceid field is 7bit wide on STM32 */
+	drvdata->traceid = val & 0x7f;
+	return size;
+}
+static DEVICE_ATTR_RW(traceid);
+
+#define coresight_stm_simple_func(name, offset)	\
+	coresight_simple_func(struct stm_drvdata, name, offset)
+
+coresight_stm_simple_func(tcsr, STMTCSR);
+coresight_stm_simple_func(tsfreqr, STMTSFREQR);
+coresight_stm_simple_func(syncr, STMSYNCR);
+coresight_stm_simple_func(sper, STMSPER);
+coresight_stm_simple_func(spter, STMSPTER);
+coresight_stm_simple_func(privmaskr, STMPRIVMASKR);
+coresight_stm_simple_func(spscr, STMSPSCR);
+coresight_stm_simple_func(spmscr, STMSPMSCR);
+coresight_stm_simple_func(spfeat1r, STMSPFEAT1R);
+coresight_stm_simple_func(spfeat2r, STMSPFEAT2R);
+coresight_stm_simple_func(spfeat3r, STMSPFEAT3R);
+coresight_stm_simple_func(devid, CORESIGHT_DEVID);
+
+static struct attribute *coresight_stm_attrs[] = {
+	&dev_attr_hwevent_enable.attr,
+	&dev_attr_hwevent_select.attr,
+	&dev_attr_port_enable.attr,
+	&dev_attr_port_select.attr,
+	&dev_attr_traceid.attr,
+	NULL,
+};
+
+static struct attribute *coresight_stm_mgmt_attrs[] = {
+	&dev_attr_tcsr.attr,
+	&dev_attr_tsfreqr.attr,
+	&dev_attr_syncr.attr,
+	&dev_attr_sper.attr,
+	&dev_attr_spter.attr,
+	&dev_attr_privmaskr.attr,
+	&dev_attr_spscr.attr,
+	&dev_attr_spmscr.attr,
+	&dev_attr_spfeat1r.attr,
+	&dev_attr_spfeat2r.attr,
+	&dev_attr_spfeat3r.attr,
+	&dev_attr_devid.attr,
+	NULL,
+};
+
+static const struct attribute_group coresight_stm_group = {
+	.attrs = coresight_stm_attrs,
+};
+
+static const struct attribute_group coresight_stm_mgmt_group = {
+	.attrs = coresight_stm_mgmt_attrs,
+	.name = "mgmt",
+};
+
+static const struct attribute_group *coresight_stm_groups[] = {
+	&coresight_stm_group,
+	&coresight_stm_mgmt_group,
+	NULL,
+};
+
+static int stm_get_resource_byname(struct device_node *np,
+				   char *ch_base, struct resource *res)
+{
+	const char *name = NULL;
+	int index = 0, found = 0;
+
+	while (!of_property_read_string_index(np, "reg-names", index, &name)) {
+		if (strcmp(ch_base, name)) {
+			index++;
+			continue;
+		}
+
+		/* We have a match and @index is where it's at */
+		found = 1;
+		break;
+	}
+
+	if (!found)
+		return -EINVAL;
+
+	return of_address_to_resource(np, index, res);
+}
+
+static u32 stm_fundamental_data_size(struct stm_drvdata *drvdata)
+{
+	u32 stmspfeat2r;
+
+	if (!IS_ENABLED(CONFIG_64BIT))
+		return 4;
+
+	stmspfeat2r = readl_relaxed(drvdata->base + STMSPFEAT2R);
+
+	/*
+	 * bit[15:12] represents the fundamental data size
+	 * 0 - 32-bit data
+	 * 1 - 64-bit data
+	 */
+	return BMVAL(stmspfeat2r, 12, 15) ? 8 : 4;
+}
+
+static u32 stm_num_stimulus_port(struct stm_drvdata *drvdata)
+{
+	u32 numsp;
+
+	numsp = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
+	/*
+	 * NUMPS in STMDEVID is 17 bit long and if equal to 0x0,
+	 * 32 stimulus ports are supported.
+	 */
+	numsp &= 0x1ffff;
+	if (!numsp)
+		numsp = STM_32_CHANNEL;
+	return numsp;
+}
+
+static void stm_init_default_data(struct stm_drvdata *drvdata)
+{
+	/* Don't use port selection */
+	drvdata->stmspscr = 0x0;
+	/*
+	 * Enable all channel regardless of their number.  When port
+	 * selection isn't used (see above) STMSPER applies to all
+	 * 32 channel group available, hence setting all 32 bits to 1
+	 */
+	drvdata->stmsper = ~0x0;
+
+	/*
+	 * The trace ID value for *ETM* tracers start at CPU_ID * 2 + 0x10 and
+	 * anything equal to or higher than 0x70 is reserved.  Since 0x00 is
+	 * also reserved the STM trace ID needs to be higher than 0x00 and
+	 * lowner than 0x10.
+	 */
+	drvdata->traceid = 0x1;
+
+	/* Set invariant transaction timing on all channels */
+	bitmap_clear(drvdata->chs.guaranteed, 0, drvdata->numsp);
+}
+
+static void stm_init_generic_data(struct stm_drvdata *drvdata)
+{
+	drvdata->stm.name = dev_name(drvdata->dev);
+
+	/*
+	 * MasterIDs are assigned at HW design phase. As such the core is
+	 * using a single master for interaction with this device.
+	 */
+	drvdata->stm.sw_start = 1;
+	drvdata->stm.sw_end = 1;
+	drvdata->stm.hw_override = true;
+	drvdata->stm.sw_nchannels = drvdata->numsp;
+	drvdata->stm.packet = stm_generic_packet;
+	drvdata->stm.link = stm_generic_link;
+	drvdata->stm.unlink = stm_generic_unlink;
+	drvdata->stm.set_options = stm_generic_set_options;
+}
+
+static int stm_probe(struct amba_device *adev, const struct amba_id *id)
+{
+	int ret;
+	void __iomem *base;
+	unsigned long *guaranteed;
+	struct device *dev = &adev->dev;
+	struct coresight_platform_data *pdata = NULL;
+	struct stm_drvdata *drvdata;
+	struct resource *res = &adev->res;
+	struct resource ch_res;
+	size_t res_size, bitmap_size;
+	struct coresight_desc *desc;
+	struct device_node *np = adev->dev.of_node;
+
+	if (np) {
+		pdata = of_get_coresight_platform_data(dev, np);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		adev->dev.platform_data = pdata;
+	}
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+
+	drvdata->dev = &adev->dev;
+	drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
+	if (!IS_ERR(drvdata->atclk)) {
+		ret = clk_prepare_enable(drvdata->atclk);
+		if (ret)
+			return ret;
+	}
+	dev_set_drvdata(dev, drvdata);
+
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+	drvdata->base = base;
+
+	ret = stm_get_resource_byname(np, "stm-stimulus-base", &ch_res);
+	if (ret)
+		return ret;
+
+	base = devm_ioremap_resource(dev, &ch_res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+	drvdata->chs.base = base;
+
+	drvdata->write_bytes = stm_fundamental_data_size(drvdata);
+
+	if (boot_nr_channel) {
+		drvdata->numsp = boot_nr_channel;
+		res_size = min((resource_size_t)(boot_nr_channel *
+				  BYTES_PER_CHANNEL), resource_size(res));
+	} else {
+		drvdata->numsp = stm_num_stimulus_port(drvdata);
+		res_size = min((resource_size_t)(drvdata->numsp *
+				 BYTES_PER_CHANNEL), resource_size(res));
+	}
+	bitmap_size = BITS_TO_LONGS(drvdata->numsp) * sizeof(long);
+
+	guaranteed = devm_kzalloc(dev, bitmap_size, GFP_KERNEL);
+	if (!guaranteed)
+		return -ENOMEM;
+	drvdata->chs.guaranteed = guaranteed;
+
+	spin_lock_init(&drvdata->spinlock);
+
+	stm_init_default_data(drvdata);
+	stm_init_generic_data(drvdata);
+
+	if (stm_register_device(dev, &drvdata->stm, THIS_MODULE)) {
+		dev_info(dev,
+			 "stm_register_device failed, probing deffered\n");
+		return -EPROBE_DEFER;
+	}
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc) {
+		ret = -ENOMEM;
+		goto stm_unregister;
+	}
+
+	desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+	desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE;
+	desc->ops = &stm_cs_ops;
+	desc->pdata = pdata;
+	desc->dev = dev;
+	desc->groups = coresight_stm_groups;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev)) {
+		ret = PTR_ERR(drvdata->csdev);
+		goto stm_unregister;
+	}
+
+	pm_runtime_put(&adev->dev);
+
+	dev_info(dev, "%s initialized\n", (char *)id->data);
+	return 0;
+
+stm_unregister:
+	stm_unregister_device(&drvdata->stm);
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int stm_runtime_suspend(struct device *dev)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev);
+
+	if (drvdata && !IS_ERR(drvdata->atclk))
+		clk_disable_unprepare(drvdata->atclk);
+
+	return 0;
+}
+
+static int stm_runtime_resume(struct device *dev)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev);
+
+	if (drvdata && !IS_ERR(drvdata->atclk))
+		clk_prepare_enable(drvdata->atclk);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops stm_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(stm_runtime_suspend, stm_runtime_resume, NULL)
+};
+
+static struct amba_id stm_ids[] = {
+	{
+		.id     = 0x0003b962,
+		.mask   = 0x0003ffff,
+		.data	= "STM32",
+	},
+	{ 0, 0},
+};
+
+static struct amba_driver stm_driver = {
+	.drv = {
+		.name   = "coresight-stm",
+		.owner	= THIS_MODULE,
+		.pm	= &stm_dev_pm_ops,
+		.suppress_bind_attrs = true,
+	},
+	.probe          = stm_probe,
+	.id_table	= stm_ids,
+};
+
+builtin_amba_driver(stm_driver);
diff --git a/include/linux/coresight-stm.h b/include/linux/coresight-stm.h
new file mode 100644
index 000000000000..a978bb85599a
--- /dev/null
+++ b/include/linux/coresight-stm.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_CORESIGHT_STM_H_
+#define __LINUX_CORESIGHT_STM_H_
+
+#include <uapi/linux/coresight-stm.h>
+
+#endif
diff --git a/include/uapi/linux/coresight-stm.h b/include/uapi/linux/coresight-stm.h
new file mode 100644
index 000000000000..7e4272cf1fb2
--- /dev/null
+++ b/include/uapi/linux/coresight-stm.h
@@ -0,0 +1,21 @@
+#ifndef __UAPI_CORESIGHT_STM_H_
+#define __UAPI_CORESIGHT_STM_H_
+
+#define STM_FLAG_TIMESTAMPED   BIT(3)
+#define STM_FLAG_GUARANTEED    BIT(7)
+
+/*
+ * The CoreSight STM supports guaranteed and invariant timing
+ * transactions.  Guaranteed transactions are guaranteed to be
+ * traced, this might involve stalling the bus or system to
+ * ensure the transaction is accepted by the STM.  While invariant
+ * timing transactions are not guaranteed to be traced, they
+ * will take an invariant amount of time regardless of the
+ * state of the STM.
+ */
+enum {
+	STM_OPTION_GUARANTEED = 0,
+	STM_OPTION_INVARIANT,
+};
+
+#endif
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:44 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:44 -0600
Subject: [PATCH 10/27] coresight: tmc: modifying naming convention
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-11-git-send-email-mathieu.poirier@linaro.org>

According to the TMC architectural state machine, the 'stopped'
state is reached when bit 2 (TMCReady) of the TMC Status register
turns to '1'.  The code is correct but the naming convention isn't.

The 'Triggered' bit occupies position '1' of the TMC Status register
and has nothing to do with the indication of the TMC entering the
stopped state. As such renaming function "tmc_wait_for_triggered()"
and changing the #define to reflect what the code is really doing.

This patch has no effect other than clarifying the semantic.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 2b42ecbd8831..3f646e29a99b 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -77,7 +77,7 @@
 #define TMC_FFCR_TRIGON_TRIGIN	BIT(8)
 #define TMC_FFCR_STOP_ON_FLUSH	BIT(12)
 
-#define TMC_STS_TRIGGERED_BIT	2
+#define TMC_STS_TMCREADY_BIT	2
 #define TMC_FFCR_FLUSHMAN_BIT	6
 
 enum tmc_config_type {
@@ -132,11 +132,11 @@ struct tmc_drvdata {
 	u32			trigger_cntr;
 };
 
-static void tmc_wait_for_ready(struct tmc_drvdata *drvdata)
+static void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
 {
 	/* Ensure formatter, unformatter and hardware fifo are empty */
 	if (coresight_timeout(drvdata->base,
-			      TMC_STS, TMC_STS_TRIGGERED_BIT, 1)) {
+			      TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
 		dev_err(drvdata->dev,
 			"timeout observed when probing at offset %#x\n",
 			TMC_STS);
@@ -160,7 +160,7 @@ static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
 			TMC_FFCR);
 	}
 
-	tmc_wait_for_ready(drvdata);
+	tmc_wait_for_tmcready(drvdata);
 }
 
 static void tmc_enable_hw(struct tmc_drvdata *drvdata)
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:45 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:45 -0600
Subject: [PATCH 11/27] coresight: tmc: waiting for TMCReady bit before
 programming
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-12-git-send-email-mathieu.poirier@linaro.org>

According to the TRM before programming the TMC in circular
buffer mode (and that for any configuration, ETB, ETR, ETF),
the TMCReady bit in the status register has to be set.

This patch adds a check to make sure the state machine is in
a state where it can be configured, and complains otherwise.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 3f646e29a99b..66fa7736d12f 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -180,6 +180,9 @@ static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
 
 	CS_UNLOCK(drvdata->base);
 
+	/* Wait for TMCSReady bit to be set */
+	tmc_wait_for_tmcready(drvdata);
+
 	writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
 	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
 		       TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
@@ -201,6 +204,9 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
 
 	CS_UNLOCK(drvdata->base);
 
+	/* Wait for TMCSReady bit to be set */
+	tmc_wait_for_tmcready(drvdata);
+
 	writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
 	writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
 
@@ -230,6 +236,9 @@ static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
 {
 	CS_UNLOCK(drvdata->base);
 
+	/* Wait for TMCSReady bit to be set */
+	tmc_wait_for_tmcready(drvdata);
+
 	writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
 	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
 		       drvdata->base + TMC_FFCR);
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:46 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:46 -0600
Subject: [PATCH 12/27] coresight: tmc: re-implementing
 tmc_read_prepare/unprepare() functions
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-13-git-send-email-mathieu.poirier@linaro.org>

In their current implementation the tmc_read_prepare/unprepare()
are a lump of if/else that is difficult to read.  This patch is
alleviating that by using a switch statement.  The latter also
allows for a better control on the error path.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc.c | 56 ++++++++++++++++++-----------
 1 file changed, 36 insertions(+), 20 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 66fa7736d12f..d211aeec49f8 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -431,7 +431,7 @@ static const struct coresight_ops tmc_etf_cs_ops = {
 
 static int tmc_read_prepare(struct tmc_drvdata *drvdata)
 {
-	int ret;
+	int ret = 0;
 	unsigned long flags;
 	enum tmc_mode mode;
 
@@ -439,25 +439,31 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata)
 	if (!drvdata->enable)
 		goto out;
 
-	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+	switch (drvdata->config_type) {
+	case TMC_CONFIG_TYPE_ETB:
 		tmc_etb_disable_hw(drvdata);
-	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		tmc_etr_disable_hw(drvdata);
-	} else {
+		break;
+	case TMC_CONFIG_TYPE_ETF:
+		/* There is no point in reading a TMC in HW FIFO mode */
 		mode = readl_relaxed(drvdata->base + TMC_MODE);
-		if (mode == TMC_MODE_CIRCULAR_BUFFER) {
-			tmc_etb_disable_hw(drvdata);
-		} else {
-			ret = -ENODEV;
+		if (mode != TMC_MODE_CIRCULAR_BUFFER) {
+			ret = -EINVAL;
 			goto err;
 		}
+
+		tmc_etb_disable_hw(drvdata);
+		break;
+	case TMC_CONFIG_TYPE_ETR:
+		tmc_etr_disable_hw(drvdata);
+		break;
+	default:
+		ret = -EINVAL;
+		goto err;
 	}
+
 out:
 	drvdata->reading = true;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
 	dev_info(drvdata->dev, "TMC read start\n");
-	return 0;
 err:
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return ret;
@@ -472,20 +478,30 @@ static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
 	if (!drvdata->enable)
 		goto out;
 
-	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+	switch (drvdata->config_type) {
+	case TMC_CONFIG_TYPE_ETB:
 		tmc_etb_enable_hw(drvdata);
-	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		tmc_etr_enable_hw(drvdata);
-	} else {
+		break;
+	case TMC_CONFIG_TYPE_ETF:
+		/* Make sure we don't re-enable a TMC in HW FIFO mode */
 		mode = readl_relaxed(drvdata->base + TMC_MODE);
-		if (mode == TMC_MODE_CIRCULAR_BUFFER)
-			tmc_etb_enable_hw(drvdata);
+		if (mode != TMC_MODE_CIRCULAR_BUFFER)
+			goto err;
+
+		tmc_etb_enable_hw(drvdata);
+		break;
+	case TMC_CONFIG_TYPE_ETR:
+		tmc_etr_disable_hw(drvdata);
+		break;
+	default:
+		goto err;
 	}
+
 out:
 	drvdata->reading = false;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
 	dev_info(drvdata->dev, "TMC read end\n");
+err:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 }
 
 static int tmc_open(struct inode *inode, struct file *file)
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:47 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:47 -0600
Subject: [PATCH 13/27] coresight: tmc: clearly define number of transfers per
 burst
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-14-git-send-email-mathieu.poirier@linaro.org>

This patch makes the name of the define reflect the amount of
data tranfers per burst, in this case 16.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index d211aeec49f8..8751d53fa078 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -67,7 +67,7 @@
 #define TMC_AXICTL_PROT_CTL_B0	BIT(0)
 #define TMC_AXICTL_PROT_CTL_B1	BIT(1)
 #define TMC_AXICTL_SCT_GAT_MODE	BIT(7)
-#define TMC_AXICTL_WR_BURST_LEN 0xF00
+#define TMC_AXICTL_WR_BURST_16	0xF00
 /* TMC_FFCR - 0x304 */
 #define TMC_FFCR_EN_FMT		BIT(0)
 #define TMC_FFCR_EN_TI		BIT(1)
@@ -211,7 +211,7 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
 	writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
 
 	axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
-	axictl |= TMC_AXICTL_WR_BURST_LEN;
+	axictl |= TMC_AXICTL_WR_BURST_16;
 	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
 	axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
 	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:48 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:48 -0600
Subject: [PATCH 14/27] coresight: tmc: introducing new header file
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-15-git-send-email-mathieu.poirier@linaro.org>

The amount of #define, enumeration and structure definition
is big enough to justify moving them to a new header file.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc.c | 102 +----------------------
 drivers/hwtracing/coresight/coresight-tmc.h | 122 ++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+), 101 deletions(-)
 create mode 100644 drivers/hwtracing/coresight/coresight-tmc.h

diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 8751d53fa078..f9a6624ab531 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -30,107 +30,7 @@
 #include <linux/amba/bus.h>
 
 #include "coresight-priv.h"
-
-#define TMC_RSZ			0x004
-#define TMC_STS			0x00c
-#define TMC_RRD			0x010
-#define TMC_RRP			0x014
-#define TMC_RWP			0x018
-#define TMC_TRG			0x01c
-#define TMC_CTL			0x020
-#define TMC_RWD			0x024
-#define TMC_MODE		0x028
-#define TMC_LBUFLEVEL		0x02c
-#define TMC_CBUFLEVEL		0x030
-#define TMC_BUFWM		0x034
-#define TMC_RRPHI		0x038
-#define TMC_RWPHI		0x03c
-#define TMC_AXICTL		0x110
-#define TMC_DBALO		0x118
-#define TMC_DBAHI		0x11c
-#define TMC_FFSR		0x300
-#define TMC_FFCR		0x304
-#define TMC_PSCR		0x308
-#define TMC_ITMISCOP0		0xee0
-#define TMC_ITTRFLIN		0xee8
-#define TMC_ITATBDATA0		0xeec
-#define TMC_ITATBCTR2		0xef0
-#define TMC_ITATBCTR1		0xef4
-#define TMC_ITATBCTR0		0xef8
-
-/* register description */
-/* TMC_CTL - 0x020 */
-#define TMC_CTL_CAPT_EN		BIT(0)
-/* TMC_STS - 0x00C */
-#define TMC_STS_TRIGGERED	BIT(1)
-/* TMC_AXICTL - 0x110 */
-#define TMC_AXICTL_PROT_CTL_B0	BIT(0)
-#define TMC_AXICTL_PROT_CTL_B1	BIT(1)
-#define TMC_AXICTL_SCT_GAT_MODE	BIT(7)
-#define TMC_AXICTL_WR_BURST_16	0xF00
-/* TMC_FFCR - 0x304 */
-#define TMC_FFCR_EN_FMT		BIT(0)
-#define TMC_FFCR_EN_TI		BIT(1)
-#define TMC_FFCR_FON_FLIN	BIT(4)
-#define TMC_FFCR_FON_TRIG_EVT	BIT(5)
-#define TMC_FFCR_FLUSHMAN	BIT(6)
-#define TMC_FFCR_TRIGON_TRIGIN	BIT(8)
-#define TMC_FFCR_STOP_ON_FLUSH	BIT(12)
-
-#define TMC_STS_TMCREADY_BIT	2
-#define TMC_FFCR_FLUSHMAN_BIT	6
-
-enum tmc_config_type {
-	TMC_CONFIG_TYPE_ETB,
-	TMC_CONFIG_TYPE_ETR,
-	TMC_CONFIG_TYPE_ETF,
-};
-
-enum tmc_mode {
-	TMC_MODE_CIRCULAR_BUFFER,
-	TMC_MODE_SOFTWARE_FIFO,
-	TMC_MODE_HARDWARE_FIFO,
-};
-
-enum tmc_mem_intf_width {
-	TMC_MEM_INTF_WIDTH_32BITS	= 0x2,
-	TMC_MEM_INTF_WIDTH_64BITS	= 0x3,
-	TMC_MEM_INTF_WIDTH_128BITS	= 0x4,
-	TMC_MEM_INTF_WIDTH_256BITS	= 0x5,
-};
-
-/**
- * struct tmc_drvdata - specifics associated to an TMC component
- * @base:	memory mapped base address for this component.
- * @dev:	the device entity associated to this component.
- * @csdev:	component vitals needed by the framework.
- * @miscdev:	specifics to handle "/dev/xyz.tmc" entry.
- * @spinlock:	only one at a time pls.
- * @read_count:	manages preparation of buffer for reading.
- * @buf:	area of memory where trace data get sent.
- * @paddr:	DMA start location in RAM.
- * @vaddr:	virtual representation of @paddr.
- * @size:	@buf size.
- * @enable:	this TMC is being used.
- * @config_type: TMC variant, must be of type @tmc_config_type.
- * @trigger_cntr: amount of words to store after a trigger.
- */
-struct tmc_drvdata {
-	void __iomem		*base;
-	struct device		*dev;
-	struct coresight_device	*csdev;
-	struct miscdevice	miscdev;
-	spinlock_t		spinlock;
-	int			read_count;
-	bool			reading;
-	char			*buf;
-	dma_addr_t		paddr;
-	void			*vaddr;
-	u32			size;
-	bool			enable;
-	enum tmc_config_type	config_type;
-	u32			trigger_cntr;
-};
+#include "coresight-tmc.h"
 
 static void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
 {
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
new file mode 100644
index 000000000000..49718b4a9788
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier at linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CORESIGHT_TMC_H
+#define _CORESIGHT_TMC_H
+
+#define TMC_RSZ			0x004
+#define TMC_STS			0x00c
+#define TMC_RRD			0x010
+#define TMC_RRP			0x014
+#define TMC_RWP			0x018
+#define TMC_TRG			0x01c
+#define TMC_CTL			0x020
+#define TMC_RWD			0x024
+#define TMC_MODE		0x028
+#define TMC_LBUFLEVEL		0x02c
+#define TMC_CBUFLEVEL		0x030
+#define TMC_BUFWM		0x034
+#define TMC_RRPHI		0x038
+#define TMC_RWPHI		0x03c
+#define TMC_AXICTL		0x110
+#define TMC_DBALO		0x118
+#define TMC_DBAHI		0x11c
+#define TMC_FFSR		0x300
+#define TMC_FFCR		0x304
+#define TMC_PSCR		0x308
+#define TMC_ITMISCOP0		0xee0
+#define TMC_ITTRFLIN		0xee8
+#define TMC_ITATBDATA0		0xeec
+#define TMC_ITATBCTR2		0xef0
+#define TMC_ITATBCTR1		0xef4
+#define TMC_ITATBCTR0		0xef8
+
+/* register description */
+/* TMC_CTL - 0x020 */
+#define TMC_CTL_CAPT_EN		BIT(0)
+/* TMC_STS - 0x00C */
+#define TMC_STS_TRIGGERED	BIT(1)
+/* TMC_AXICTL - 0x110 */
+#define TMC_AXICTL_PROT_CTL_B0	BIT(0)
+#define TMC_AXICTL_PROT_CTL_B1	BIT(1)
+#define TMC_AXICTL_SCT_GAT_MODE	BIT(7)
+#define TMC_AXICTL_WR_BURST_16	0xF00
+/* TMC_FFCR - 0x304 */
+#define TMC_FFCR_EN_FMT		BIT(0)
+#define TMC_FFCR_EN_TI		BIT(1)
+#define TMC_FFCR_FON_FLIN	BIT(4)
+#define TMC_FFCR_FON_TRIG_EVT	BIT(5)
+#define TMC_FFCR_FLUSHMAN	BIT(6)
+#define TMC_FFCR_TRIGON_TRIGIN	BIT(8)
+#define TMC_FFCR_STOP_ON_FLUSH	BIT(12)
+
+#define TMC_STS_TMCREADY_BIT	2
+#define TMC_FFCR_FLUSHMAN_BIT	6
+
+enum tmc_config_type {
+	TMC_CONFIG_TYPE_ETB,
+	TMC_CONFIG_TYPE_ETR,
+	TMC_CONFIG_TYPE_ETF,
+};
+
+enum tmc_mode {
+	TMC_MODE_CIRCULAR_BUFFER,
+	TMC_MODE_SOFTWARE_FIFO,
+	TMC_MODE_HARDWARE_FIFO,
+};
+
+enum tmc_mem_intf_width {
+	TMC_MEM_INTF_WIDTH_32BITS	= 0x2,
+	TMC_MEM_INTF_WIDTH_64BITS	= 0x3,
+	TMC_MEM_INTF_WIDTH_128BITS	= 0x4,
+	TMC_MEM_INTF_WIDTH_256BITS	= 0x5,
+};
+
+/**
+ * struct tmc_drvdata - specifics associated to an TMC component
+ * @base:	memory mapped base address for this component.
+ * @dev:	the device entity associated to this component.
+ * @csdev:	component vitals needed by the framework.
+ * @miscdev:	specifics to handle "/dev/xyz.tmc" entry.
+ * @spinlock:	only one at a time pls.
+ * @read_count:	manages preparation of buffer for reading.
+ * @buf:	area of memory where trace data get sent.
+ * @paddr:	DMA start location in RAM.
+ * @vaddr:	virtual representation of @paddr.
+ * @size:	@buf size.
+ * @enable:	this TMC is being used.
+ * @config_type: TMC variant, must be of type @tmc_config_type.
+ * @trigger_cntr: amount of words to store after a trigger.
+ */
+struct tmc_drvdata {
+	void __iomem		*base;
+	struct device		*dev;
+	struct coresight_device	*csdev;
+	struct miscdevice	miscdev;
+	spinlock_t		spinlock;
+	int			read_count;
+	bool			reading;
+	char			*buf;
+	dma_addr_t		paddr;
+	void __iomem		*vaddr;
+	u32			size;
+	bool			enable;
+	enum tmc_config_type	config_type;
+	u32			trigger_cntr;
+};
+
+#endif
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:49 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:49 -0600
Subject: [PATCH 15/27] coresight: tmc: cleaning up header file
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-16-git-send-email-mathieu.poirier@linaro.org>

This patch first move the TMC_STS_TMCREADY_BIT and
TMC_FFCR_FLUSHMAN_BIT defines to their respective section.
It also removes TMC_FFCR_FLUSHMAN, since the same result
can easily be obtained using the BIT() macro.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc.c | 2 +-
 drivers/hwtracing/coresight/coresight-tmc.h | 5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index f9a6624ab531..07e2809d832b 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -50,7 +50,7 @@ static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
 	ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
 	ffcr |= TMC_FFCR_STOP_ON_FLUSH;
 	writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
-	ffcr |= TMC_FFCR_FLUSHMAN;
+	ffcr |= BIT(TMC_FFCR_FLUSHMAN_BIT);
 	writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
 	/* Ensure flush completes */
 	if (coresight_timeout(drvdata->base,
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 49718b4a9788..5a60830c8db5 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -49,6 +49,7 @@
 /* TMC_CTL - 0x020 */
 #define TMC_CTL_CAPT_EN		BIT(0)
 /* TMC_STS - 0x00C */
+#define TMC_STS_TMCREADY_BIT	2
 #define TMC_STS_TRIGGERED	BIT(1)
 /* TMC_AXICTL - 0x110 */
 #define TMC_AXICTL_PROT_CTL_B0	BIT(0)
@@ -56,16 +57,14 @@
 #define TMC_AXICTL_SCT_GAT_MODE	BIT(7)
 #define TMC_AXICTL_WR_BURST_16	0xF00
 /* TMC_FFCR - 0x304 */
+#define TMC_FFCR_FLUSHMAN_BIT	6
 #define TMC_FFCR_EN_FMT		BIT(0)
 #define TMC_FFCR_EN_TI		BIT(1)
 #define TMC_FFCR_FON_FLIN	BIT(4)
 #define TMC_FFCR_FON_TRIG_EVT	BIT(5)
-#define TMC_FFCR_FLUSHMAN	BIT(6)
 #define TMC_FFCR_TRIGON_TRIGIN	BIT(8)
 #define TMC_FFCR_STOP_ON_FLUSH	BIT(12)
 
-#define TMC_STS_TMCREADY_BIT	2
-#define TMC_FFCR_FLUSHMAN_BIT	6
 
 enum tmc_config_type {
 	TMC_CONFIG_TYPE_ETB,
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:52 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:52 -0600
Subject: [PATCH 18/27] coresight: tmc: allocating memory when needed
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-19-git-send-email-mathieu.poirier@linaro.org>

In it's current form the TMC probe() function allocates
trace buffer memory at boot time, event if coresight isn't
used.  This is highly inefficient since trace buffers can
occupy a lot of memory that could be used otherwised.

This patch allocates trace buffers on the fly, when the
coresight subsystem is solicited.  Allocated buffers are
released when traces are read using the device descriptors
under /dev.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc-etf.c | 90 +++++++++++++++++++++---
 drivers/hwtracing/coresight/coresight-tmc-etr.c | 93 +++++++++++++++++++++++--
 drivers/hwtracing/coresight/coresight-tmc.c     | 14 ----
 3 files changed, 170 insertions(+), 27 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 91e43572ce9f..6eb1665cfc9c 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -16,14 +16,12 @@
  */
 
 #include <linux/coresight.h>
+#include <linux/slab.h>
 #include "coresight-priv.h"
 #include "coresight-tmc.h"
 
 void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
 {
-	/* Zero out the memory to help with debug */
-	memset(drvdata->buf, 0, drvdata->size);
-
 	CS_UNLOCK(drvdata->base);
 
 	/* Wait for TMCSReady bit to be set */
@@ -110,21 +108,67 @@ static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
 
 static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
 {
+	int ret = 0;
+	bool used = false;
+	char *buf = NULL;
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
+	 /* This shouldn't be happening */
+	if (WARN_ON(mode != CS_MODE_SYSFS))
+		return -EINVAL;
+
+	/*
+	 * If we don't have a buffer release the lock and allocate memory.
+	 * Otherwise keep the lock and move along.
+	 */
 	spin_lock_irqsave(&drvdata->spinlock, flags);
-	if (drvdata->reading) {
+	if (!drvdata->buf) {
 		spin_unlock_irqrestore(&drvdata->spinlock, flags);
-		return -EBUSY;
+
+		/* Allocating the memory here while outside of the spinlock */
+		buf = kzalloc(drvdata->size, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+
+		/* Let's try again */
+		spin_lock_irqsave(&drvdata->spinlock, flags);
+	}
+
+	if (drvdata->reading) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/*
+	 * If drvdata::buf isn't NULL, memory was allocated for a previous
+	 * trace run but wasn't read.  If so simply zero-out the memory.
+	 * Otherwise use the memory allocated above.
+	 *
+	 * The memory is freed when users read the buffer using the
+	 * /dev/xyz.{etf|etb} interface.  See tmc_read_unprepare_etf() for
+	 * details.
+	 */
+	if (drvdata->buf) {
+		memset(drvdata->buf, 0, drvdata->size);
+	} else {
+		used = true;
+		drvdata->buf = buf;
 	}
 
 	tmc_etb_enable_hw(drvdata);
 	drvdata->enable = true;
+out:
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
-	dev_info(drvdata->dev, "TMC-ETB/ETF enabled\n");
-	return 0;
+	/* Free memory outside the spinlock if need be */
+	if (!used && buf)
+		kfree(buf);
+
+	if (!ret)
+		dev_info(drvdata->dev, "TMC-ETB/ETF enabled\n");
+
+	return ret;
 }
 
 static void tmc_disable_etf_sink(struct coresight_device *csdev)
@@ -223,6 +267,12 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
 		goto out;
 	}
 
+	/* If drvdata::buf is NULL the trace data has been read already */
+	if (drvdata->buf == NULL) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	/* Disable the TMC if need be */
 	if (drvdata->enable)
 		tmc_etb_disable_hw(drvdata);
@@ -236,6 +286,7 @@ out:
 
 int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
 {
+	char *buf = NULL;
 	enum tmc_mode mode;
 	unsigned long flags;
 
@@ -254,11 +305,34 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
 	}
 
 	/* Re-enable the TMC if need be */
-	if (drvdata->enable)
+	if (drvdata->enable) {
+		/*
+		 * The trace run will continue with the same allocated trace
+		 * buffer. As such zero-out the buffer so that we don't end
+		 * up with stale data.
+		 *
+		 * Since the tracer is still enabled drvdata::buf
+		 * can't be NULL.
+		 */
+		memset(drvdata->buf, 0, drvdata->size);
 		tmc_etb_enable_hw(drvdata);
+	} else {
+		/*
+		 * The ETB/ETF is not tracing and the buffer was just read.
+		 * As such prepare to free the trace buffer.
+		 */
+		buf = drvdata->buf;
+		drvdata->buf = NULL;
+	}
 
 	drvdata->reading = false;
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
+	/*
+	 * Free allocated memory outside of the spinlock.  There is no need
+	 * to assert the validity of 'buf' since calling kfree(NULL) is safe.
+	 */
+	kfree(buf);
+
 	return 0;
 }
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 3483d139a4ac..ac37bf904fb7 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -16,6 +16,7 @@
  */
 
 #include <linux/coresight.h>
+#include <linux/dma-mapping.h>
 #include "coresight-priv.h"
 #include "coresight-tmc.h"
 
@@ -83,21 +84,71 @@ static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
 
 static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
 {
+	int ret = 0;
+	bool used = false;
 	unsigned long flags;
+	void __iomem *vaddr = NULL;
+	dma_addr_t paddr;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
+	 /* This shouldn't be happening */
+	if (WARN_ON(mode != CS_MODE_SYSFS))
+		return -EINVAL;
+
+	/*
+	 * If we don't have a buffer release the lock and allocate memory.
+	 * Otherwise keep the lock and move along.
+	 */
 	spin_lock_irqsave(&drvdata->spinlock, flags);
-	if (drvdata->reading) {
+	if (!drvdata->vaddr) {
 		spin_unlock_irqrestore(&drvdata->spinlock, flags);
-		return -EBUSY;
+
+		/*
+		 * Contiguous  memory can't be allocated while a spinlock is
+		 * held.  As such allocate memory here and free it if a buffer
+		 * has already been allocated (from a previous session).
+		 */
+		vaddr = dma_alloc_coherent(drvdata->dev, drvdata->size,
+					   &paddr, GFP_KERNEL);
+		if (!vaddr)
+			return -ENOMEM;
+
+		/* Let's try again */
+		spin_lock_irqsave(&drvdata->spinlock, flags);
+	}
+
+	if (drvdata->reading) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/*
+	 * If drvdata::buf == NULL, use the memory allocated above.
+	 * Otherwise a buffer still exists from a previous session, so
+	 * simply use that.
+	 */
+	if (drvdata->buf == NULL) {
+		used = true;
+		drvdata->vaddr = vaddr;
+		drvdata->paddr = paddr;
+		drvdata->buf = drvdata->vaddr;
 	}
 
+	memset(drvdata->vaddr, 0, drvdata->size);
+
 	tmc_etr_enable_hw(drvdata);
 	drvdata->enable = true;
+out:
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
-	dev_info(drvdata->dev, "TMC-ETR enabled\n");
-	return 0;
+	/* Free memory outside the spinlock if need be */
+	if (!used && vaddr)
+		dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);
+
+	if (!ret)
+		dev_info(drvdata->dev, "TMC-ETR enabled\n");
+
+	return ret;
 }
 
 static void tmc_disable_etr_sink(struct coresight_device *csdev)
@@ -129,6 +180,7 @@ const struct coresight_ops tmc_etr_cs_ops = {
 
 int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 {
+	int ret = 0;
 	unsigned long flags;
 
 	/* config types are set a boot time and never change */
@@ -137,11 +189,18 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 
+	/* If drvdata::buf is NULL the trace data has been read already */
+	if (drvdata->buf == NULL) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	/* Disable the TMC if need be */
 	if (drvdata->enable)
 		tmc_etr_disable_hw(drvdata);
 
 	drvdata->reading = true;
+out:
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	return 0;
@@ -150,6 +209,8 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
 {
 	unsigned long flags;
+	dma_addr_t paddr;
+	void __iomem *vaddr = NULL;
 
 	/* config types are set a boot time and never change */
 	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
@@ -158,11 +219,33 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* RE-enable the TMC if need be */
-	if (drvdata->enable)
+	if (drvdata->enable) {
+		/*
+		 * The trace run will continue with the same allocated trace
+		 * buffer. As such zero-out the buffer so that we don't end
+		 * up with stale data.
+		 *
+		 * Since the tracer is still enabled drvdata::buf
+		 * can't be NULL.
+		 */
+		memset(drvdata->buf, 0, drvdata->size);
 		tmc_etr_enable_hw(drvdata);
+	} else {
+		/*
+		 * The ETR is not tracing and the buffer was just read.
+		 * As such prepare to free the trace buffer.
+		 */
+		vaddr = drvdata->vaddr;
+		paddr = drvdata->paddr;
+		drvdata->buf = NULL;
+	}
 
 	drvdata->reading = false;
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
+	/* Free allocated memory out side of the spinlock */
+	if (vaddr)
+		dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);
+
 	return 0;
 }
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 63f8e55116a6..e8e12a9b917a 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -319,20 +319,6 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 
 	pm_runtime_put(&adev->dev);
 
-	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		drvdata->vaddr = dma_alloc_coherent(dev, drvdata->size,
-						&drvdata->paddr, GFP_KERNEL);
-		if (!drvdata->vaddr)
-			return -ENOMEM;
-
-		memset(drvdata->vaddr, 0, drvdata->size);
-		drvdata->buf = drvdata->vaddr;
-	} else {
-		drvdata->buf = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
-		if (!drvdata->buf)
-			return -ENOMEM;
-	}
-
 	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
 	if (!desc) {
 		ret = -ENOMEM;
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:50 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:50 -0600
Subject: [PATCH 16/27] coresight: tmc: splitting driver in ETB/ETF and ETR
 components
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-17-git-send-email-mathieu.poirier@linaro.org>

The TMC block can operate in 3 modes (ETB, ETF and ETR) and accessed
via two interfaces (sysFS and Perf).  That makes 6 mode to cover, which
is way too much coupling for a single file.

This patch splits the original TMC driver in 2 halves, one for ETB/ETF
and another one for ETR mode.  A common core is kept for functionality
common to all 3 modes.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/Makefile            |   4 +-
 drivers/hwtracing/coresight/coresight-tmc-etf.c | 204 ++++++++++++++++++
 drivers/hwtracing/coresight/coresight-tmc-etr.c | 128 ++++++++++++
 drivers/hwtracing/coresight/coresight-tmc.c     | 264 +-----------------------
 drivers/hwtracing/coresight/coresight-tmc.h     |  18 ++
 5 files changed, 357 insertions(+), 261 deletions(-)
 create mode 100644 drivers/hwtracing/coresight/coresight-tmc-etf.c
 create mode 100644 drivers/hwtracing/coresight/coresight-tmc-etr.c

diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index c6f84b57f52a..af480d9c1441 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -3,7 +3,9 @@
 #
 obj-$(CONFIG_CORESIGHT) += coresight.o coresight-etm-perf.o
 obj-$(CONFIG_OF) += of_coresight.o
-obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
+obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o \
+					     coresight-tmc-etf.o \
+					     coresight-tmc-etr.o
 obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
 obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
 obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
new file mode 100644
index 000000000000..467d19221f7b
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright(C) 2016 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier at linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * 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/coresight.h>
+#include "coresight-priv.h"
+#include "coresight-tmc.h"
+
+void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
+{
+	/* Zero out the memory to help with debug */
+	memset(drvdata->buf, 0, drvdata->size);
+
+	CS_UNLOCK(drvdata->base);
+
+	/* Wait for TMCSReady bit to be set */
+	tmc_wait_for_tmcready(drvdata);
+
+	writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
+	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
+		       TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
+		       TMC_FFCR_TRIGON_TRIGIN,
+		       drvdata->base + TMC_FFCR);
+
+	writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
+	tmc_enable_hw(drvdata);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
+{
+	enum tmc_mem_intf_width memwidth;
+	u8 memwords;
+	char *bufp;
+	u32 read_data;
+	int i;
+
+	memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
+	if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
+		memwords = 1;
+	else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
+		memwords = 2;
+	else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
+		memwords = 4;
+	else
+		memwords = 8;
+
+	bufp = drvdata->buf;
+	while (1) {
+		for (i = 0; i < memwords; i++) {
+			read_data = readl_relaxed(drvdata->base + TMC_RRD);
+			if (read_data == 0xFFFFFFFF)
+				return;
+			memcpy(bufp, &read_data, 4);
+			bufp += 4;
+		}
+	}
+}
+
+void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	tmc_flush_and_stop(drvdata);
+	tmc_etb_dump_hw(drvdata);
+	tmc_disable_hw(drvdata);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	/* Wait for TMCSReady bit to be set */
+	tmc_wait_for_tmcready(drvdata);
+
+	writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
+	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
+		       drvdata->base + TMC_FFCR);
+	writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
+	tmc_enable_hw(drvdata);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	tmc_flush_and_stop(drvdata);
+	tmc_disable_hw(drvdata);
+
+	CS_LOCK(drvdata->base);
+}
+
+static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
+{
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		return -EBUSY;
+	}
+
+	tmc_etb_enable_hw(drvdata);
+	drvdata->enable = true;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC-ETB/ETF enabled\n");
+	return 0;
+}
+
+static void tmc_disable_etf_sink(struct coresight_device *csdev)
+{
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		return;
+	}
+
+	tmc_etb_disable_hw(drvdata);
+	drvdata->enable = false;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC-ETB/ETF disabled\n");
+}
+
+static int tmc_enable_etf_link(struct coresight_device *csdev,
+			       int inport, int outport)
+{
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		return -EBUSY;
+	}
+
+	tmc_etf_enable_hw(drvdata);
+	drvdata->enable = true;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC-ETF enabled\n");
+	return 0;
+}
+
+static void tmc_disable_etf_link(struct coresight_device *csdev,
+				 int inport, int outport)
+{
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		return;
+	}
+
+	tmc_etf_disable_hw(drvdata);
+	drvdata->enable = false;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC disabled\n");
+}
+
+static const struct coresight_ops_sink tmc_etf_sink_ops = {
+	.enable		= tmc_enable_etf_sink,
+	.disable	= tmc_disable_etf_sink,
+};
+
+static const struct coresight_ops_link tmc_etf_link_ops = {
+	.enable		= tmc_enable_etf_link,
+	.disable	= tmc_disable_etf_link,
+};
+
+const struct coresight_ops tmc_etb_cs_ops = {
+	.sink_ops	= &tmc_etf_sink_ops,
+};
+
+const struct coresight_ops tmc_etf_cs_ops = {
+	.sink_ops	= &tmc_etf_sink_ops,
+	.link_ops	= &tmc_etf_link_ops,
+};
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
new file mode 100644
index 000000000000..5d9333ec49ae
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright(C) 2016 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier at linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * 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/coresight.h>
+#include "coresight-priv.h"
+#include "coresight-tmc.h"
+
+void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
+{
+	u32 axictl;
+
+	/* Zero out the memory to help with debug */
+	memset(drvdata->vaddr, 0, drvdata->size);
+
+	CS_UNLOCK(drvdata->base);
+
+	/* Wait for TMCSReady bit to be set */
+	tmc_wait_for_tmcready(drvdata);
+
+	writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
+	writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
+
+	axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
+	axictl |= TMC_AXICTL_WR_BURST_16;
+	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+	axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
+	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+	axictl = (axictl &
+		  ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
+		  TMC_AXICTL_PROT_CTL_B1;
+	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+
+	writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
+	writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
+	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
+		       TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
+		       TMC_FFCR_TRIGON_TRIGIN,
+		       drvdata->base + TMC_FFCR);
+	writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
+	tmc_enable_hw(drvdata);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
+{
+	u32 rwp, val;
+
+	rwp = readl_relaxed(drvdata->base + TMC_RWP);
+	val = readl_relaxed(drvdata->base + TMC_STS);
+
+	/* How much memory do we still have */
+	if (val & BIT(0))
+		drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
+	else
+		drvdata->buf = drvdata->vaddr;
+}
+
+void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	tmc_flush_and_stop(drvdata);
+	tmc_etr_dump_hw(drvdata);
+	tmc_disable_hw(drvdata);
+
+	CS_LOCK(drvdata->base);
+}
+
+static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
+{
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		return -EBUSY;
+	}
+
+	tmc_etr_enable_hw(drvdata);
+	drvdata->enable = true;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC-ETR enabled\n");
+	return 0;
+}
+
+static void tmc_disable_etr_sink(struct coresight_device *csdev)
+{
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		return;
+	}
+
+	tmc_etr_disable_hw(drvdata);
+	drvdata->enable = false;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC-ETR disabled\n");
+}
+
+static const struct coresight_ops_sink tmc_etr_sink_ops = {
+	.enable		= tmc_enable_etr_sink,
+	.disable	= tmc_disable_etr_sink,
+};
+
+const struct coresight_ops tmc_etr_cs_ops = {
+	.sink_ops	= &tmc_etr_sink_ops,
+};
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 07e2809d832b..8d7f6d54c9b0 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -32,7 +32,7 @@
 #include "coresight-priv.h"
 #include "coresight-tmc.h"
 
-static void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
+void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
 {
 	/* Ensure formatter, unformatter and hardware fifo are empty */
 	if (coresight_timeout(drvdata->base,
@@ -43,7 +43,7 @@ static void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
 	}
 }
 
-static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
+void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
 {
 	u32 ffcr;
 
@@ -63,272 +63,16 @@ static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
 	tmc_wait_for_tmcready(drvdata);
 }
 
-static void tmc_enable_hw(struct tmc_drvdata *drvdata)
+void tmc_enable_hw(struct tmc_drvdata *drvdata)
 {
 	writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
 }
 
-static void tmc_disable_hw(struct tmc_drvdata *drvdata)
+void tmc_disable_hw(struct tmc_drvdata *drvdata)
 {
 	writel_relaxed(0x0, drvdata->base + TMC_CTL);
 }
 
-static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
-{
-	/* Zero out the memory to help with debug */
-	memset(drvdata->buf, 0, drvdata->size);
-
-	CS_UNLOCK(drvdata->base);
-
-	/* Wait for TMCSReady bit to be set */
-	tmc_wait_for_tmcready(drvdata);
-
-	writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
-	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
-		       TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
-		       TMC_FFCR_TRIGON_TRIGIN,
-		       drvdata->base + TMC_FFCR);
-
-	writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
-	tmc_enable_hw(drvdata);
-
-	CS_LOCK(drvdata->base);
-}
-
-static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
-{
-	u32 axictl;
-
-	/* Zero out the memory to help with debug */
-	memset(drvdata->vaddr, 0, drvdata->size);
-
-	CS_UNLOCK(drvdata->base);
-
-	/* Wait for TMCSReady bit to be set */
-	tmc_wait_for_tmcready(drvdata);
-
-	writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
-	writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
-
-	axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
-	axictl |= TMC_AXICTL_WR_BURST_16;
-	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-	axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
-	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-	axictl = (axictl &
-		  ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
-		  TMC_AXICTL_PROT_CTL_B1;
-	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-
-	writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
-	writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
-	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
-		       TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
-		       TMC_FFCR_TRIGON_TRIGIN,
-		       drvdata->base + TMC_FFCR);
-	writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
-	tmc_enable_hw(drvdata);
-
-	CS_LOCK(drvdata->base);
-}
-
-static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
-{
-	CS_UNLOCK(drvdata->base);
-
-	/* Wait for TMCSReady bit to be set */
-	tmc_wait_for_tmcready(drvdata);
-
-	writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
-	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
-		       drvdata->base + TMC_FFCR);
-	writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
-	tmc_enable_hw(drvdata);
-
-	CS_LOCK(drvdata->base);
-}
-
-static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&drvdata->spinlock, flags);
-	if (drvdata->reading) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
-		return -EBUSY;
-	}
-
-	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-		tmc_etb_enable_hw(drvdata);
-	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		tmc_etr_enable_hw(drvdata);
-	} else {
-		if (mode == TMC_MODE_CIRCULAR_BUFFER)
-			tmc_etb_enable_hw(drvdata);
-		else
-			tmc_etf_enable_hw(drvdata);
-	}
-	drvdata->enable = true;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-	dev_info(drvdata->dev, "TMC enabled\n");
-	return 0;
-}
-
-static int tmc_enable_sink(struct coresight_device *csdev, u32 mode)
-{
-	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-	return tmc_enable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
-}
-
-static int tmc_enable_link(struct coresight_device *csdev, int inport,
-			   int outport)
-{
-	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-	return tmc_enable(drvdata, TMC_MODE_HARDWARE_FIFO);
-}
-
-static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
-{
-	enum tmc_mem_intf_width memwidth;
-	u8 memwords;
-	char *bufp;
-	u32 read_data;
-	int i;
-
-	memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
-	if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
-		memwords = 1;
-	else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
-		memwords = 2;
-	else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
-		memwords = 4;
-	else
-		memwords = 8;
-
-	bufp = drvdata->buf;
-	while (1) {
-		for (i = 0; i < memwords; i++) {
-			read_data = readl_relaxed(drvdata->base + TMC_RRD);
-			if (read_data == 0xFFFFFFFF)
-				return;
-			memcpy(bufp, &read_data, 4);
-			bufp += 4;
-		}
-	}
-}
-
-static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
-{
-	CS_UNLOCK(drvdata->base);
-
-	tmc_flush_and_stop(drvdata);
-	tmc_etb_dump_hw(drvdata);
-	tmc_disable_hw(drvdata);
-
-	CS_LOCK(drvdata->base);
-}
-
-static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
-{
-	u32 rwp, val;
-
-	rwp = readl_relaxed(drvdata->base + TMC_RWP);
-	val = readl_relaxed(drvdata->base + TMC_STS);
-
-	/* How much memory do we still have */
-	if (val & BIT(0))
-		drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
-	else
-		drvdata->buf = drvdata->vaddr;
-}
-
-static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
-{
-	CS_UNLOCK(drvdata->base);
-
-	tmc_flush_and_stop(drvdata);
-	tmc_etr_dump_hw(drvdata);
-	tmc_disable_hw(drvdata);
-
-	CS_LOCK(drvdata->base);
-}
-
-static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
-{
-	CS_UNLOCK(drvdata->base);
-
-	tmc_flush_and_stop(drvdata);
-	tmc_disable_hw(drvdata);
-
-	CS_LOCK(drvdata->base);
-}
-
-static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&drvdata->spinlock, flags);
-	if (drvdata->reading)
-		goto out;
-
-	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-		tmc_etb_disable_hw(drvdata);
-	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		tmc_etr_disable_hw(drvdata);
-	} else {
-		if (mode == TMC_MODE_CIRCULAR_BUFFER)
-			tmc_etb_disable_hw(drvdata);
-		else
-			tmc_etf_disable_hw(drvdata);
-	}
-out:
-	drvdata->enable = false;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-	dev_info(drvdata->dev, "TMC disabled\n");
-}
-
-static void tmc_disable_sink(struct coresight_device *csdev)
-{
-	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-	tmc_disable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
-}
-
-static void tmc_disable_link(struct coresight_device *csdev, int inport,
-			     int outport)
-{
-	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-	tmc_disable(drvdata, TMC_MODE_HARDWARE_FIFO);
-}
-
-static const struct coresight_ops_sink tmc_sink_ops = {
-	.enable		= tmc_enable_sink,
-	.disable	= tmc_disable_sink,
-};
-
-static const struct coresight_ops_link tmc_link_ops = {
-	.enable		= tmc_enable_link,
-	.disable	= tmc_disable_link,
-};
-
-static const struct coresight_ops tmc_etb_cs_ops = {
-	.sink_ops	= &tmc_sink_ops,
-};
-
-static const struct coresight_ops tmc_etr_cs_ops = {
-	.sink_ops	= &tmc_sink_ops,
-};
-
-static const struct coresight_ops tmc_etf_cs_ops = {
-	.sink_ops	= &tmc_sink_ops,
-	.link_ops	= &tmc_link_ops,
-};
-
 static int tmc_read_prepare(struct tmc_drvdata *drvdata)
 {
 	int ret = 0;
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 5a60830c8db5..b3017e115c4d 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -18,6 +18,8 @@
 #ifndef _CORESIGHT_TMC_H
 #define _CORESIGHT_TMC_H
 
+#include <linux/miscdevice.h>
+
 #define TMC_RSZ			0x004
 #define TMC_STS			0x00c
 #define TMC_RRD			0x010
@@ -118,4 +120,20 @@ struct tmc_drvdata {
 	u32			trigger_cntr;
 };
 
+/* Generic functions */
+void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata);
+void tmc_flush_and_stop(struct tmc_drvdata *drvdata);
+void tmc_enable_hw(struct tmc_drvdata *drvdata);
+void tmc_disable_hw(struct tmc_drvdata *drvdata);
+
+/* ETB/ETF functions */
+void tmc_etb_enable_hw(struct tmc_drvdata *drvdata);
+void tmc_etb_disable_hw(struct tmc_drvdata *drvdata);
+extern const struct coresight_ops tmc_etb_cs_ops;
+extern const struct coresight_ops tmc_etf_cs_ops;
+
+/* ETR functions */
+void tmc_etr_enable_hw(struct tmc_drvdata *drvdata);
+void tmc_etr_disable_hw(struct tmc_drvdata *drvdata);
+extern const struct coresight_ops tmc_etr_cs_ops;
 #endif
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:51 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:51 -0600
Subject: [PATCH 17/27] coresight: tmc: making prepare/unprepare functions
 generic
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-18-git-send-email-mathieu.poirier@linaro.org>

Dealing with HW related matters in tmc_read_prepare/unprepare
becomes convoluted when many cases need to be handled distinctively.

As such moving processing related to HW setup to individual driver
files and keep the core driver generic.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc-etf.c | 62 ++++++++++++++++++++++++-
 drivers/hwtracing/coresight/coresight-tmc-etr.c | 42 ++++++++++++++++-
 drivers/hwtracing/coresight/coresight-tmc.c     | 55 +++++-----------------
 drivers/hwtracing/coresight/coresight-tmc.h     |  8 ++--
 4 files changed, 117 insertions(+), 50 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 467d19221f7b..91e43572ce9f 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -71,7 +71,7 @@ static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
 	}
 }
 
-void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
+static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
 {
 	CS_UNLOCK(drvdata->base);
 
@@ -202,3 +202,63 @@ const struct coresight_ops tmc_etf_cs_ops = {
 	.sink_ops	= &tmc_etf_sink_ops,
 	.link_ops	= &tmc_etf_link_ops,
 };
+
+int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
+{
+	enum tmc_mode mode;
+	int ret = 0;
+	unsigned long flags;
+
+	/* config types are set a boot time and never change */
+	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETB &&
+			 drvdata->config_type != TMC_CONFIG_TYPE_ETF))
+		return -EINVAL;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+
+	/* There is no point in reading a TMC in HW FIFO mode */
+	mode = readl_relaxed(drvdata->base + TMC_MODE);
+	if (mode != TMC_MODE_CIRCULAR_BUFFER) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Disable the TMC if need be */
+	if (drvdata->enable)
+		tmc_etb_disable_hw(drvdata);
+
+	drvdata->reading = true;
+out:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	return ret;
+}
+
+int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
+{
+	enum tmc_mode mode;
+	unsigned long flags;
+
+	/* config types are set a boot time and never change */
+	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETB &&
+			 drvdata->config_type != TMC_CONFIG_TYPE_ETF))
+		return -EINVAL;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+
+	/* There is no point in reading a TMC in HW FIFO mode */
+	mode = readl_relaxed(drvdata->base + TMC_MODE);
+	if (mode != TMC_MODE_CIRCULAR_BUFFER) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		return -EINVAL;
+	}
+
+	/* Re-enable the TMC if need be */
+	if (drvdata->enable)
+		tmc_etb_enable_hw(drvdata);
+
+	drvdata->reading = false;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	return 0;
+}
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 5d9333ec49ae..3483d139a4ac 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -70,7 +70,7 @@ static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
 		drvdata->buf = drvdata->vaddr;
 }
 
-void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
+static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
 {
 	CS_UNLOCK(drvdata->base);
 
@@ -126,3 +126,43 @@ static const struct coresight_ops_sink tmc_etr_sink_ops = {
 const struct coresight_ops tmc_etr_cs_ops = {
 	.sink_ops	= &tmc_etr_sink_ops,
 };
+
+int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
+{
+	unsigned long flags;
+
+	/* config types are set a boot time and never change */
+	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
+		return -EINVAL;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+
+	/* Disable the TMC if need be */
+	if (drvdata->enable)
+		tmc_etr_disable_hw(drvdata);
+
+	drvdata->reading = true;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	return 0;
+}
+
+int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
+{
+	unsigned long flags;
+
+	/* config types are set a boot time and never change */
+	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
+		return -EINVAL;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+
+	/* RE-enable the TMC if need be */
+	if (drvdata->enable)
+		tmc_etr_enable_hw(drvdata);
+
+	drvdata->reading = false;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	return 0;
+}
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 8d7f6d54c9b0..63f8e55116a6 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -76,76 +76,43 @@ void tmc_disable_hw(struct tmc_drvdata *drvdata)
 static int tmc_read_prepare(struct tmc_drvdata *drvdata)
 {
 	int ret = 0;
-	unsigned long flags;
-	enum tmc_mode mode;
-
-	spin_lock_irqsave(&drvdata->spinlock, flags);
-	if (!drvdata->enable)
-		goto out;
 
 	switch (drvdata->config_type) {
 	case TMC_CONFIG_TYPE_ETB:
-		tmc_etb_disable_hw(drvdata);
-		break;
 	case TMC_CONFIG_TYPE_ETF:
-		/* There is no point in reading a TMC in HW FIFO mode */
-		mode = readl_relaxed(drvdata->base + TMC_MODE);
-		if (mode != TMC_MODE_CIRCULAR_BUFFER) {
-			ret = -EINVAL;
-			goto err;
-		}
-
-		tmc_etb_disable_hw(drvdata);
+		ret = tmc_read_prepare_etb(drvdata);
 		break;
 	case TMC_CONFIG_TYPE_ETR:
-		tmc_etr_disable_hw(drvdata);
+		ret = tmc_read_prepare_etr(drvdata);
 		break;
 	default:
 		ret = -EINVAL;
-		goto err;
 	}
 
-out:
-	drvdata->reading = true;
-	dev_info(drvdata->dev, "TMC read start\n");
-err:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	if (!ret)
+		dev_info(drvdata->dev, "TMC read start\n");
+
 	return ret;
 }
 
 static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
 {
-	unsigned long flags;
-	enum tmc_mode mode;
-
-	spin_lock_irqsave(&drvdata->spinlock, flags);
-	if (!drvdata->enable)
-		goto out;
+	int ret = 0;
 
 	switch (drvdata->config_type) {
 	case TMC_CONFIG_TYPE_ETB:
-		tmc_etb_enable_hw(drvdata);
-		break;
 	case TMC_CONFIG_TYPE_ETF:
-		/* Make sure we don't re-enable a TMC in HW FIFO mode */
-		mode = readl_relaxed(drvdata->base + TMC_MODE);
-		if (mode != TMC_MODE_CIRCULAR_BUFFER)
-			goto err;
-
-		tmc_etb_enable_hw(drvdata);
+		ret = tmc_read_unprepare_etb(drvdata);
 		break;
 	case TMC_CONFIG_TYPE_ETR:
-		tmc_etr_disable_hw(drvdata);
+		ret = tmc_read_unprepare_etr(drvdata);
 		break;
 	default:
-		goto err;
+		ret = -EINVAL;
 	}
 
-out:
-	drvdata->reading = false;
-	dev_info(drvdata->dev, "TMC read end\n");
-err:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	if (!ret)
+		dev_info(drvdata->dev, "TMC read end\n");
 }
 
 static int tmc_open(struct inode *inode, struct file *file)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index b3017e115c4d..df661903f83c 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -127,13 +127,13 @@ void tmc_enable_hw(struct tmc_drvdata *drvdata);
 void tmc_disable_hw(struct tmc_drvdata *drvdata);
 
 /* ETB/ETF functions */
-void tmc_etb_enable_hw(struct tmc_drvdata *drvdata);
-void tmc_etb_disable_hw(struct tmc_drvdata *drvdata);
+int tmc_read_prepare_etb(struct tmc_drvdata *drvdata);
+int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata);
 extern const struct coresight_ops tmc_etb_cs_ops;
 extern const struct coresight_ops tmc_etf_cs_ops;
 
 /* ETR functions */
-void tmc_etr_enable_hw(struct tmc_drvdata *drvdata);
-void tmc_etr_disable_hw(struct tmc_drvdata *drvdata);
+int tmc_read_prepare_etr(struct tmc_drvdata *drvdata);
+int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata);
 extern const struct coresight_ops tmc_etr_cs_ops;
 #endif
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:53 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:53 -0600
Subject: [PATCH 19/27] coresight: tmc: getting rid of multiple read access
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-20-git-send-email-mathieu.poirier@linaro.org>

Allowing multiple readers to access the trace data simultaniously
via sysFS provides no shortage of opportunity for race condition,
mandates two variable to be maintained (drvdata::read_count and
drvdata::reading), makes the code complex and provide little
advantages, if any.

This patch streamlines the read process by restricting trace data
access to a single user.  That way drvdata::read_count can
be eliminated and race conditions (along with faulty error handling)
in function tmc_open() and tmc_release() eliminated.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc-etf.c |  5 +++++
 drivers/hwtracing/coresight/coresight-tmc-etr.c |  4 ++++
 drivers/hwtracing/coresight/coresight-tmc.c     | 24 +++++++++---------------
 drivers/hwtracing/coresight/coresight-tmc.h     |  2 --
 4 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 6eb1665cfc9c..60edf4d1968f 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -260,6 +260,11 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
 
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 
+	if (drvdata->reading) {
+		ret = -EBUSY;
+		goto out;
+	}
+
 	/* There is no point in reading a TMC in HW FIFO mode */
 	mode = readl_relaxed(drvdata->base + TMC_MODE);
 	if (mode != TMC_MODE_CIRCULAR_BUFFER) {
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index ac37bf904fb7..d6999b457fb8 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -188,6 +188,10 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 		return -EINVAL;
 
 	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		ret = -EBUSY;
+		goto out;
+	}
 
 	/* If drvdata::buf is NULL the trace data has been read already */
 	if (drvdata->buf == NULL) {
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index e8e12a9b917a..ae7525a2b94a 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -95,7 +95,7 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata)
 	return ret;
 }
 
-static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
+static int tmc_read_unprepare(struct tmc_drvdata *drvdata)
 {
 	int ret = 0;
 
@@ -113,21 +113,20 @@ static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
 
 	if (!ret)
 		dev_info(drvdata->dev, "TMC read end\n");
+
+	return ret;
 }
 
 static int tmc_open(struct inode *inode, struct file *file)
 {
+	int ret;
 	struct tmc_drvdata *drvdata = container_of(file->private_data,
 						   struct tmc_drvdata, miscdev);
-	int ret = 0;
-
-	if (drvdata->read_count++)
-		goto out;
 
 	ret = tmc_read_prepare(drvdata);
 	if (ret)
 		return ret;
-out:
+
 	nonseekable_open(inode, file);
 
 	dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
@@ -167,19 +166,14 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
 
 static int tmc_release(struct inode *inode, struct file *file)
 {
+	int ret;
 	struct tmc_drvdata *drvdata = container_of(file->private_data,
 						   struct tmc_drvdata, miscdev);
 
-	if (--drvdata->read_count) {
-		if (drvdata->read_count < 0) {
-			dev_err(drvdata->dev, "mismatched close\n");
-			drvdata->read_count = 0;
-		}
-		goto out;
-	}
+	ret = tmc_read_unprepare(drvdata);
+	if (ret)
+		return ret;
 
-	tmc_read_unprepare(drvdata);
-out:
 	dev_dbg(drvdata->dev, "%s: released\n", __func__);
 	return 0;
 }
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index df661903f83c..592eb149fe3a 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -94,7 +94,6 @@ enum tmc_mem_intf_width {
  * @csdev:	component vitals needed by the framework.
  * @miscdev:	specifics to handle "/dev/xyz.tmc" entry.
  * @spinlock:	only one at a time pls.
- * @read_count:	manages preparation of buffer for reading.
  * @buf:	area of memory where trace data get sent.
  * @paddr:	DMA start location in RAM.
  * @vaddr:	virtual representation of @paddr.
@@ -109,7 +108,6 @@ struct tmc_drvdata {
 	struct coresight_device	*csdev;
 	struct miscdevice	miscdev;
 	spinlock_t		spinlock;
-	int			read_count;
 	bool			reading;
 	char			*buf;
 	dma_addr_t		paddr;
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:54 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:54 -0600
Subject: [PATCH 20/27] coresight: tmc: adding mode of operation for link/sinks
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-21-git-send-email-mathieu.poirier@linaro.org>

Moving tmc_drvdata::enable to a local_t mode.  That way the
sink interface is aware of it's orgin and the foundation for
mutual exclusion between the sysFS and Perf interface can be
laid out.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc-etf.c | 27 ++++++++++++++++++-------
 drivers/hwtracing/coresight/coresight-tmc-etr.c | 23 ++++++++++++++++-----
 drivers/hwtracing/coresight/coresight-tmc.h     |  4 ++--
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 60edf4d1968f..bc0efc1e5b49 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -111,6 +111,7 @@ static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
 	int ret = 0;
 	bool used = false;
 	char *buf = NULL;
+	long val;
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
@@ -140,6 +141,15 @@ static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
 		goto out;
 	}
 
+	val = local_xchg(&drvdata->mode, mode);
+	/*
+	 * In sysFS mode we can have multiple writers per sink.  Since this
+	 * sink is already enabled no memory is needed and the HW need not be
+	 * touched.
+	 */
+	if (val == CS_MODE_SYSFS)
+		goto out;
+
 	/*
 	 * If drvdata::buf isn't NULL, memory was allocated for a previous
 	 * trace run but wasn't read.  If so simply zero-out the memory.
@@ -157,7 +167,6 @@ static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
 	}
 
 	tmc_etb_enable_hw(drvdata);
-	drvdata->enable = true;
 out:
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
@@ -173,6 +182,7 @@ out:
 
 static void tmc_disable_etf_sink(struct coresight_device *csdev)
 {
+	long val;
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
@@ -182,8 +192,11 @@ static void tmc_disable_etf_sink(struct coresight_device *csdev)
 		return;
 	}
 
-	tmc_etb_disable_hw(drvdata);
-	drvdata->enable = false;
+	val = local_xchg(&drvdata->mode, CS_MODE_DISABLED);
+	/* Disable the TMC only if it needs to */
+	if (val != CS_MODE_DISABLED)
+		tmc_etb_disable_hw(drvdata);
+
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_info(drvdata->dev, "TMC-ETB/ETF disabled\n");
@@ -202,7 +215,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,
 	}
 
 	tmc_etf_enable_hw(drvdata);
-	drvdata->enable = true;
+	local_set(&drvdata->mode, CS_MODE_SYSFS);
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_info(drvdata->dev, "TMC-ETF enabled\n");
@@ -222,7 +235,7 @@ static void tmc_disable_etf_link(struct coresight_device *csdev,
 	}
 
 	tmc_etf_disable_hw(drvdata);
-	drvdata->enable = false;
+	local_set(&drvdata->mode, CS_MODE_DISABLED);
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_info(drvdata->dev, "TMC disabled\n");
@@ -279,7 +292,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
 	}
 
 	/* Disable the TMC if need be */
-	if (drvdata->enable)
+	if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
 		tmc_etb_disable_hw(drvdata);
 
 	drvdata->reading = true;
@@ -310,7 +323,7 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
 	}
 
 	/* Re-enable the TMC if need be */
-	if (drvdata->enable) {
+	if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
 		/*
 		 * The trace run will continue with the same allocated trace
 		 * buffer. As such zero-out the buffer so that we don't end
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index d6999b457fb8..0c107811a232 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -86,6 +86,7 @@ static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
 {
 	int ret = 0;
 	bool used = false;
+	long val;
 	unsigned long flags;
 	void __iomem *vaddr = NULL;
 	dma_addr_t paddr;
@@ -122,6 +123,15 @@ static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
 		goto out;
 	}
 
+	val = local_xchg(&drvdata->mode, mode);
+	/*
+	 * In sysFS mode we can have multiple writers per sink.  Since this
+	 * sink is already enabled no memory is needed and the HW need not be
+	 * touched.
+	 */
+	if (val == CS_MODE_SYSFS)
+		goto out;
+
 	/*
 	 * If drvdata::buf == NULL, use the memory allocated above.
 	 * Otherwise a buffer still exists from a previous session, so
@@ -137,7 +147,6 @@ static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
 	memset(drvdata->vaddr, 0, drvdata->size);
 
 	tmc_etr_enable_hw(drvdata);
-	drvdata->enable = true;
 out:
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
@@ -153,6 +162,7 @@ out:
 
 static void tmc_disable_etr_sink(struct coresight_device *csdev)
 {
+	long val;
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
@@ -162,8 +172,11 @@ static void tmc_disable_etr_sink(struct coresight_device *csdev)
 		return;
 	}
 
-	tmc_etr_disable_hw(drvdata);
-	drvdata->enable = false;
+	val = local_xchg(&drvdata->mode, CS_MODE_DISABLED);
+	/* Disable the TMC only if it needs to */
+	if (val != CS_MODE_DISABLED)
+		tmc_etr_disable_hw(drvdata);
+
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_info(drvdata->dev, "TMC-ETR disabled\n");
@@ -200,7 +213,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 	}
 
 	/* Disable the TMC if need be */
-	if (drvdata->enable)
+	if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
 		tmc_etr_disable_hw(drvdata);
 
 	drvdata->reading = true;
@@ -223,7 +236,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* RE-enable the TMC if need be */
-	if (drvdata->enable) {
+	if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
 		/*
 		 * The trace run will continue with the same allocated trace
 		 * buffer. As such zero-out the buffer so that we don't end
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 592eb149fe3a..94bc034d3b98 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -98,7 +98,7 @@ enum tmc_mem_intf_width {
  * @paddr:	DMA start location in RAM.
  * @vaddr:	virtual representation of @paddr.
  * @size:	@buf size.
- * @enable:	this TMC is being used.
+ * @mode:	how this TMC is being used.
  * @config_type: TMC variant, must be of type @tmc_config_type.
  * @trigger_cntr: amount of words to store after a trigger.
  */
@@ -113,7 +113,7 @@ struct tmc_drvdata {
 	dma_addr_t		paddr;
 	void __iomem		*vaddr;
 	u32			size;
-	bool			enable;
+	local_t			mode;
 	enum tmc_config_type	config_type;
 	u32			trigger_cntr;
 };
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:55 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:55 -0600
Subject: [PATCH 21/27] coresight: tmc: dump system memory content only when
 needed
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-22-git-send-email-mathieu.poirier@linaro.org>

Calling tmc_etf/etr_dump_hw() is required only when operating from
sysFS.  When working from Perf, the system memory is harvested
from the AUX trace API.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc-etf.c | 7 ++++++-
 drivers/hwtracing/coresight/coresight-tmc-etr.c | 7 ++++++-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index bc0efc1e5b49..b5e5e6ac67eb 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -74,7 +74,12 @@ static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
 	CS_UNLOCK(drvdata->base);
 
 	tmc_flush_and_stop(drvdata);
-	tmc_etb_dump_hw(drvdata);
+	/*
+	 * When operating in sysFS mode the content of the buffer needs to be
+	 * read before the TMC is disabled.
+	 */
+	if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
+		tmc_etb_dump_hw(drvdata);
 	tmc_disable_hw(drvdata);
 
 	CS_LOCK(drvdata->base);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 0c107811a232..7208584d0da7 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -76,7 +76,12 @@ static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
 	CS_UNLOCK(drvdata->base);
 
 	tmc_flush_and_stop(drvdata);
-	tmc_etr_dump_hw(drvdata);
+	/*
+	 * When operating in sysFS mode the content of the buffer needs to be
+	 * read before the TMC is disabled.
+	 */
+	if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
+		tmc_etr_dump_hw(drvdata);
 	tmc_disable_hw(drvdata);
 
 	CS_LOCK(drvdata->base);
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:56 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:56 -0600
Subject: [PATCH 22/27] coresight: tmc: make sysFS and Perf mode mutually
 exclusive
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-23-git-send-email-mathieu.poirier@linaro.org>

The sysFS and Perf access methods can't be allowed to interfere
with one another.  As such introducing guards to access
functions that prevents moving forward if a TMC is already
being used.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc-etf.c | 60 +++++++++++++++++++++++-
 drivers/hwtracing/coresight/coresight-tmc-etr.c | 62 +++++++++++++++++++++++--
 2 files changed, 117 insertions(+), 5 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index b5e5e6ac67eb..b11c52be54a9 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -111,7 +111,7 @@ static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
 	CS_LOCK(drvdata->base);
 }
 
-static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
+static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32 mode)
 {
 	int ret = 0;
 	bool used = false;
@@ -185,6 +185,54 @@ out:
 	return ret;
 }
 
+static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, u32 mode)
+{
+	int ret = 0;
+	long val;
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	 /* This shouldn't be happening */
+	if (WARN_ON(mode != CS_MODE_PERF))
+		return -EINVAL;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	val = local_xchg(&drvdata->mode, mode);
+	/*
+	 * In Perf mode there can be only one writer per sink.  There
+	 * is also no need to continue if the ETB/ETR is already operated
+	 * from sysFS.
+	 */
+	if (val != CS_MODE_DISABLED) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	tmc_etb_enable_hw(drvdata);
+out:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	return ret;
+}
+
+static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
+{
+	switch (mode) {
+	case CS_MODE_SYSFS:
+		return tmc_enable_etf_sink_sysfs(csdev, mode);
+	case CS_MODE_PERF:
+		return tmc_enable_etf_sink_perf(csdev, mode);
+	}
+
+	/* We shouldn't be here */
+	return -EINVAL;
+}
+
 static void tmc_disable_etf_sink(struct coresight_device *csdev)
 {
 	long val;
@@ -267,6 +315,7 @@ const struct coresight_ops tmc_etf_cs_ops = {
 
 int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
 {
+	long val;
 	enum tmc_mode mode;
 	int ret = 0;
 	unsigned long flags;
@@ -290,6 +339,13 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
 		goto out;
 	}
 
+	val = local_read(&drvdata->mode);
+	/* Don't interfere if operated from Perf */
+	if (val == CS_MODE_PERF) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	/* If drvdata::buf is NULL the trace data has been read already */
 	if (drvdata->buf == NULL) {
 		ret = -EINVAL;
@@ -297,7 +353,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
 	}
 
 	/* Disable the TMC if need be */
-	if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
+	if (val == CS_MODE_SYSFS)
 		tmc_etb_disable_hw(drvdata);
 
 	drvdata->reading = true;
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 7208584d0da7..847d1b5f2c13 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -87,7 +87,7 @@ static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
 	CS_LOCK(drvdata->base);
 }
 
-static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
+static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
 {
 	int ret = 0;
 	bool used = false;
@@ -165,6 +165,54 @@ out:
 	return ret;
 }
 
+static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
+{
+	int ret = 0;
+	long val;
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	 /* This shouldn't be happening */
+	if (WARN_ON(mode != CS_MODE_PERF))
+		return -EINVAL;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	val = local_xchg(&drvdata->mode, mode);
+	/*
+	 * In Perf mode there can be only one writer per sink.  There
+	 * is also no need to continue if the ETR is already operated
+	 * from sysFS.
+	 */
+	if (val != CS_MODE_DISABLED) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	tmc_etr_enable_hw(drvdata);
+out:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	return ret;
+}
+
+static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
+{
+	switch (mode) {
+	case CS_MODE_SYSFS:
+		return tmc_enable_etr_sink_sysfs(csdev, mode);
+	case CS_MODE_PERF:
+		return tmc_enable_etr_sink_perf(csdev, mode);
+	}
+
+	/* We shouldn't be here */
+	return -EINVAL;
+}
+
 static void tmc_disable_etr_sink(struct coresight_device *csdev)
 {
 	long val;
@@ -199,6 +247,7 @@ const struct coresight_ops tmc_etr_cs_ops = {
 int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 {
 	int ret = 0;
+	long val;
 	unsigned long flags;
 
 	/* config types are set a boot time and never change */
@@ -211,6 +260,13 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 		goto out;
 	}
 
+	val = local_read(&drvdata->mode);
+	/* Don't interfere if operated from Perf */
+	if (val == CS_MODE_PERF) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	/* If drvdata::buf is NULL the trace data has been read already */
 	if (drvdata->buf == NULL) {
 		ret = -EINVAL;
@@ -218,14 +274,14 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 	}
 
 	/* Disable the TMC if need be */
-	if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
+	if (val == CS_MODE_SYSFS)
 		tmc_etr_disable_hw(drvdata);
 
 	drvdata->reading = true;
 out:
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
-	return 0;
+	return ret;
 }
 
 int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:58 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:58 -0600
Subject: [PATCH 24/27] coresight: moving struct cs_buffers to header file
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-25-git-send-email-mathieu.poirier@linaro.org>

That way we can re-use the structure in other drivers.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-etb10.c | 20 --------------------
 drivers/hwtracing/coresight/coresight-priv.h  | 20 ++++++++++++++++++++
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index b0d402dbfeae..92f942321e1e 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -71,26 +71,6 @@
 #define ETB_FRAME_SIZE_WORDS	4
 
 /**
- * struct cs_buffer - keep track of a recording session' specifics
- * @cur:	index of the current buffer
- * @nr_pages:	max number of pages granted to us
- * @offset:	offset within the current buffer
- * @data_size:	how much we collected in this run
- * @lost:	other than zero if we had a HW buffer wrap around
- * @snapshot:	is this run in snapshot mode
- * @data_pages:	a handle the ring buffer
- */
-struct cs_buffers {
-	unsigned int		cur;
-	unsigned int		nr_pages;
-	unsigned long		offset;
-	local_t			data_size;
-	local_t			lost;
-	bool			snapshot;
-	void			**data_pages;
-};
-
-/**
  * struct etb_drvdata - specifics associated to an ETB component
  * @base:	memory mapped base address for this component.
  * @dev:	the device entity associated to this component.
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 3b5dd95a3588..ad975c58080d 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -53,6 +53,26 @@ enum cs_mode {
 	CS_MODE_PERF,
 };
 
+/**
+ * struct cs_buffer - keep track of a recording session' specifics
+ * @cur:	index of the current buffer
+ * @nr_pages:	max number of pages granted to us
+ * @offset:	offset within the current buffer
+ * @data_size:	how much we collected in this run
+ * @lost:	other than zero if we had a HW buffer wrap around
+ * @snapshot:	is this run in snapshot mode
+ * @data_pages:	a handle the ring buffer
+ */
+struct cs_buffers {
+	unsigned int		cur;
+	unsigned int		nr_pages;
+	unsigned long		offset;
+	local_t			data_size;
+	local_t			lost;
+	bool			snapshot;
+	void			**data_pages;
+};
+
 static inline void CS_LOCK(void __iomem *addr)
 {
 	do {
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:57 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:57 -0600
Subject: [PATCH 23/27] coresight: tmc: keep track of memory width
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-24-git-send-email-mathieu.poirier@linaro.org>

Accessing the HW configuration register each time the memory
width is needed simply doesn't make sense.  It is much more
efficient to read the value once and keep a reference for
later use.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc-etf.c | 14 +---------
 drivers/hwtracing/coresight/coresight-tmc.c     | 34 +++++++++++++++++++++++++
 drivers/hwtracing/coresight/coresight-tmc.h     | 10 +++++---
 3 files changed, 41 insertions(+), 17 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index b11c52be54a9..ba3384781f71 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -41,25 +41,13 @@ void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
 
 static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
 {
-	enum tmc_mem_intf_width memwidth;
-	u8 memwords;
 	char *bufp;
 	u32 read_data;
 	int i;
 
-	memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
-	if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
-		memwords = 1;
-	else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
-		memwords = 2;
-	else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
-		memwords = 4;
-	else
-		memwords = 8;
-
 	bufp = drvdata->buf;
 	while (1) {
-		for (i = 0; i < memwords; i++) {
+		for (i = 0; i < drvdata->memwidth; i++) {
 			read_data = readl_relaxed(drvdata->base + TMC_RRD);
 			if (read_data == 0xFFFFFFFF)
 				return;
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index ae7525a2b94a..9e02ac963cd0 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -186,6 +186,39 @@ static const struct file_operations tmc_fops = {
 	.llseek		= no_llseek,
 };
 
+static enum tmc_mem_intf_width tmc_get_memwidth(u32 devid)
+{
+	enum tmc_mem_intf_width memwidth;
+
+	/*
+	 * Excerpt from the TRM:
+	 *
+	 * DEVID::MEMWIDTH[10:8]
+	 * 0x2 Memory interface databus is 32 bits wide.
+	 * 0x3 Memory interface databus is 64 bits wide.
+	 * 0x4 Memory interface databus is 128 bits wide.
+	 * 0x5 Memory interface databus is 256 bits wide.
+	 */
+	switch (BMVAL(devid, 8, 10)) {
+	case 0x2:
+		memwidth = TMC_MEM_INTF_WIDTH_32BITS;
+		break;
+	case 0x3:
+		memwidth = TMC_MEM_INTF_WIDTH_64BITS;
+		break;
+	case 0x4:
+		memwidth = TMC_MEM_INTF_WIDTH_128BITS;
+		break;
+	case 0x5:
+		memwidth = TMC_MEM_INTF_WIDTH_256BITS;
+		break;
+	default:
+		memwidth = 0;
+	}
+
+	return memwidth;
+}
+
 #define coresight_tmc_simple_func(name, offset)			\
 	coresight_simple_func(struct tmc_drvdata, name, offset)
 
@@ -299,6 +332,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 
 	devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
 	drvdata->config_type = BMVAL(devid, 6, 7);
+	drvdata->memwidth = tmc_get_memwidth(devid);
 
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
 		if (np)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 94bc034d3b98..c5d06fd57fa8 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -81,10 +81,10 @@ enum tmc_mode {
 };
 
 enum tmc_mem_intf_width {
-	TMC_MEM_INTF_WIDTH_32BITS	= 0x2,
-	TMC_MEM_INTF_WIDTH_64BITS	= 0x3,
-	TMC_MEM_INTF_WIDTH_128BITS	= 0x4,
-	TMC_MEM_INTF_WIDTH_256BITS	= 0x5,
+	TMC_MEM_INTF_WIDTH_32BITS	= 1,
+	TMC_MEM_INTF_WIDTH_64BITS	= 2,
+	TMC_MEM_INTF_WIDTH_128BITS	= 4,
+	TMC_MEM_INTF_WIDTH_256BITS	= 8,
 };
 
 /**
@@ -100,6 +100,7 @@ enum tmc_mem_intf_width {
  * @size:	@buf size.
  * @mode:	how this TMC is being used.
  * @config_type: TMC variant, must be of type @tmc_config_type.
+ * @memwidth:	width of the memory interface databus, in bytes.
  * @trigger_cntr: amount of words to store after a trigger.
  */
 struct tmc_drvdata {
@@ -115,6 +116,7 @@ struct tmc_drvdata {
 	u32			size;
 	local_t			mode;
 	enum tmc_config_type	config_type;
+	enum tmc_mem_intf_width	memwidth;
 	u32			trigger_cntr;
 };
 
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:34:01 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:34:01 -0600
Subject: [PATCH 27/27] coresight: etb10: adjust read pointer only when needed
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-28-git-send-email-mathieu.poirier@linaro.org>

The read pointer (read_ptr) needs to be adjusted only if its value
has gone beyond the length of the memory buffer.

Reported-by: Suzuki K Poulose <suzuki.poulose at arm.com>
Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
---
 drivers/hwtracing/coresight/coresight-etb10.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 92f942321e1e..4d20b0be0c0b 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -428,7 +428,8 @@ static void etb_update_buffer(struct coresight_device *csdev,
 		read_ptr = (write_ptr + drvdata->buffer_depth) -
 					to_read / ETB_FRAME_SIZE_WORDS;
 		/* Wrap around if need be*/
-		read_ptr &= ~(drvdata->buffer_depth - 1);
+		if (read_ptr > (drvdata->buffer_depth - 1))
+			read_ptr -= drvdata->buffer_depth;
 		/* let the decoder know we've skipped ahead */
 		local_inc(&buf->lost);
 	}
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:34:00 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:34:00 -0600
Subject: [PATCH 26/27] coresight: configuring ETF in FIFO mode when acting as
 link
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-27-git-send-email-mathieu.poirier@linaro.org>

When part of a path but not identified as a sink, the EFT has to
be configured as a link and placed in HW FIFO mode.  As such when
enabling a path, call the right configuration function based on
the role the ETF if playing in this trace run.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight.c | 32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 0995df8f85bc..5443d03a1eec 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -265,15 +265,27 @@ static void coresight_disable_source(struct coresight_device *csdev)
 
 void coresight_disable_path(struct list_head *path)
 {
+	u32 type;
 	struct coresight_node *nd;
 	struct coresight_device *csdev, *parent, *child;
 
 	list_for_each_entry(nd, path, link) {
 		csdev = nd->csdev;
+		type = csdev->type;
 
-		switch (csdev->type) {
+		/*
+		 * ETF devices are tricky... They can be a link or a sink,
+		 * depending on how they are configured.  If an ETF has been
+		 * "activated" it will be configured as a sink, otherwise
+		 * go ahead with the link configuration.
+		 */
+		if (type == CORESIGHT_DEV_TYPE_LINKSINK)
+			type = (csdev == coresight_get_sink(path)) ?
+						CORESIGHT_DEV_TYPE_SINK :
+						CORESIGHT_DEV_TYPE_LINK;
+
+		switch (type) {
 		case CORESIGHT_DEV_TYPE_SINK:
-		case CORESIGHT_DEV_TYPE_LINKSINK:
 			coresight_disable_sink(csdev);
 			break;
 		case CORESIGHT_DEV_TYPE_SOURCE:
@@ -294,15 +306,27 @@ int coresight_enable_path(struct list_head *path, u32 mode)
 {
 
 	int ret = 0;
+	u32 type;
 	struct coresight_node *nd;
 	struct coresight_device *csdev, *parent, *child;
 
 	list_for_each_entry_reverse(nd, path, link) {
 		csdev = nd->csdev;
+		type = csdev->type;
+
+		/*
+		 * ETF devices are tricky... They can be a link or a sink,
+		 * depending on how they are configured.  If an ETF has been
+		 * "activated" it will be configured as a sink, otherwise
+		 * go ahead with the link configuration.
+		 */
+		if (type == CORESIGHT_DEV_TYPE_LINKSINK)
+			type = (csdev == coresight_get_sink(path)) ?
+						CORESIGHT_DEV_TYPE_SINK :
+						CORESIGHT_DEV_TYPE_LINK;
 
-		switch (csdev->type) {
+		switch (type) {
 		case CORESIGHT_DEV_TYPE_SINK:
-		case CORESIGHT_DEV_TYPE_LINKSINK:
 			ret = coresight_enable_sink(csdev, mode);
 			if (ret)
 				goto err;
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May  3 10:33:59 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue,  3 May 2016 11:33:59 -0600
Subject: [PATCH 25/27] coresight: tmc: implementing TMC-ETF AUX space API
In-Reply-To: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1462296841-12327-26-git-send-email-mathieu.poirier@linaro.org>

This patch implement the AUX area interfaces required to
use the TMC (configured as an ETF) from the Perf sub-system.

The heuristic is heavily borrowed from the ETB10 implementation.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc-etf.c | 199 ++++++++++++++++++++++++
 drivers/hwtracing/coresight/coresight-tmc.h     |   1 +
 2 files changed, 200 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index ba3384781f71..466af86fd76f 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -15,7 +15,9 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/circ_buf.h>
 #include <linux/coresight.h>
+#include <linux/perf_event.h>
 #include <linux/slab.h>
 #include "coresight-priv.h"
 #include "coresight-tmc.h"
@@ -282,9 +284,206 @@ static void tmc_disable_etf_link(struct coresight_device *csdev,
 	dev_info(drvdata->dev, "TMC disabled\n");
 }
 
+static void *tmc_alloc_etf_buffer(struct coresight_device *csdev, int cpu,
+				  void **pages, int nr_pages, bool overwrite)
+{
+	int node;
+	struct cs_buffers *buf;
+
+	if (cpu == -1)
+		cpu = smp_processor_id();
+	node = cpu_to_node(cpu);
+
+	/* Allocate memory structure for interaction with Perf */
+	buf = kzalloc_node(sizeof(struct cs_buffers), GFP_KERNEL, node);
+	if (!buf)
+		return NULL;
+
+	buf->snapshot = overwrite;
+	buf->nr_pages = nr_pages;
+	buf->data_pages = pages;
+
+	return buf;
+}
+
+static void tmc_free_etf_buffer(void *config)
+{
+	struct cs_buffers *buf = config;
+
+	kfree(buf);
+}
+
+static int tmc_set_etf_buffer(struct coresight_device *csdev,
+			      struct perf_output_handle *handle,
+			      void *sink_config)
+{
+	int ret = 0;
+	unsigned long head;
+	struct cs_buffers *buf = sink_config;
+
+	/* wrap head around to the amount of space we have */
+	head = handle->head & ((buf->nr_pages << PAGE_SHIFT) - 1);
+
+	/* find the page to write to */
+	buf->cur = head / PAGE_SIZE;
+
+	/* and offset within that page */
+	buf->offset = head % PAGE_SIZE;
+
+	local_set(&buf->data_size, 0);
+
+	return ret;
+}
+
+static unsigned long tmc_reset_etf_buffer(struct coresight_device *csdev,
+					  struct perf_output_handle *handle,
+					  void *sink_config, bool *lost)
+{
+	long size = 0;
+	struct cs_buffers *buf = sink_config;
+
+	if (buf) {
+		/*
+		 * In snapshot mode ->data_size holds the new address of the
+		 * ring buffer's head.  The size itself is the whole address
+		 * range since we want the latest information.
+		 */
+		if (buf->snapshot)
+			handle->head = local_xchg(&buf->data_size,
+						  buf->nr_pages << PAGE_SHIFT);
+		/*
+		 * Tell the tracer PMU how much we got in this run and if
+		 * something went wrong along the way.  Nobody else can use
+		 * this cs_buffers instance until we are done.  As such
+		 * resetting parameters here and squaring off with the ring
+		 * buffer API in the tracer PMU is fine.
+		 */
+		*lost = !!local_xchg(&buf->lost, 0);
+		size = local_xchg(&buf->data_size, 0);
+	}
+
+	return size;
+}
+
+static void tmc_update_etf_buffer(struct coresight_device *csdev,
+				  struct perf_output_handle *handle,
+				  void *sink_config)
+{
+	int i, cur;
+	u32 *buf_ptr;
+	u32 read_ptr, write_ptr;
+	u32 status, to_read;
+	unsigned long offset;
+	struct cs_buffers *buf = sink_config;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	if (!buf)
+		return;
+
+	/* This shouldn't happen */
+	if (WARN_ON_ONCE(local_read(&drvdata->mode) != CS_MODE_PERF))
+		return;
+
+	CS_UNLOCK(drvdata->base);
+
+	tmc_flush_and_stop(drvdata);
+
+	read_ptr = readl_relaxed(drvdata->base + TMC_RRP);
+	write_ptr = readl_relaxed(drvdata->base + TMC_RWP);
+
+	/*
+	 * Get a hold of the status register and see if a wrap around
+	 * has occurred.  If so adjust things accordingly.
+	 */
+	status = readl_relaxed(drvdata->base + TMC_STS);
+	if (status & TMC_STS_FULL) {
+		local_inc(&buf->lost);
+		to_read = drvdata->size;
+	} else {
+		to_read = CIRC_CNT(write_ptr, read_ptr, drvdata->size);
+	}
+
+	/*
+	 * The TMC RAM buffer may be bigger than the space available in the
+	 * perf ring buffer (handle->size).  If so advance the RRP so that we
+	 * get the latest trace data.
+	 */
+	if (to_read > handle->size) {
+		u32 mask = 0;
+
+		/*
+		 * The value written to RRP must be byte-address aligned to
+		 * the width of the trace memory databus _and_ to a frame
+		 * boundary (16 byte), whichever is the biggest. For example,
+		 * for 32-bit, 64-bit and 128-bit wide trace memory, the four
+		 * LSBs must be 0s. For 256-bit wide trace memory, the five
+		 * LSBs must be 0s.
+		 */
+		switch (drvdata->memwidth) {
+		case TMC_MEM_INTF_WIDTH_32BITS:
+		case TMC_MEM_INTF_WIDTH_64BITS:
+		case TMC_MEM_INTF_WIDTH_128BITS:
+			mask = GENMASK(31, 5);
+			break;
+		case TMC_MEM_INTF_WIDTH_256BITS:
+			mask = GENMASK(31, 6);
+			break;
+		}
+
+		/*
+		 * Make sure the new size is aligned in accordance with the
+		 * requirement explained above.
+		 */
+		to_read = handle->size & mask;
+		/* Move the RAM read pointer up */
+		read_ptr = (write_ptr + drvdata->size) - to_read;
+		/* Make sure we are still within our limits */
+		if (read_ptr > (drvdata->size - 1))
+			read_ptr -= drvdata->size;
+		/* Tell the HW */
+		writel_relaxed(read_ptr, drvdata->base + TMC_RRP);
+		local_inc(&buf->lost);
+	}
+
+	cur = buf->cur;
+	offset = buf->offset;
+
+	/* for every byte to read */
+	for (i = 0; i < to_read; i += 4) {
+		buf_ptr = buf->data_pages[cur] + offset;
+		*buf_ptr = readl_relaxed(drvdata->base + TMC_RRD);
+
+		offset += 4;
+		if (offset >= PAGE_SIZE) {
+			offset = 0;
+			cur++;
+			/* wrap around at the end of the buffer */
+			cur &= buf->nr_pages - 1;
+		}
+	}
+
+	/*
+	 * In snapshot mode all we have to do is communicate to
+	 * perf_aux_output_end() the address of the current head.  In full
+	 * trace mode the same function expects a size to move rb->aux_head
+	 * forward.
+	 */
+	if (buf->snapshot)
+		local_set(&buf->data_size, (cur * PAGE_SIZE) + offset);
+	else
+		local_add(to_read, &buf->data_size);
+
+	CS_LOCK(drvdata->base);
+}
+
 static const struct coresight_ops_sink tmc_etf_sink_ops = {
 	.enable		= tmc_enable_etf_sink,
 	.disable	= tmc_disable_etf_sink,
+	.alloc_buffer	= tmc_alloc_etf_buffer,
+	.free_buffer	= tmc_free_etf_buffer,
+	.set_buffer	= tmc_set_etf_buffer,
+	.reset_buffer	= tmc_reset_etf_buffer,
+	.update_buffer	= tmc_update_etf_buffer,
 };
 
 static const struct coresight_ops_link tmc_etf_link_ops = {
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index c5d06fd57fa8..5c5fe2ad2ca7 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -52,6 +52,7 @@
 #define TMC_CTL_CAPT_EN		BIT(0)
 /* TMC_STS - 0x00C */
 #define TMC_STS_TMCREADY_BIT	2
+#define TMC_STS_FULL		BIT(0)
 #define TMC_STS_TRIGGERED	BIT(1)
 /* TMC_AXICTL - 0x110 */
 #define TMC_AXICTL_PROT_CTL_B0	BIT(0)
-- 
2.5.0



From dirk.behme at gmail.com  Tue May  3 10:48:32 2016
From: dirk.behme at gmail.com (Dirk Behme)
Date: Tue, 3 May 2016 19:48:32 +0200
Subject: [PATCH] arm64: dts: r8a7795: Increase the size of GIC-400 mapped
 registers
In-Reply-To: <20160429113515.333c42ef@arm.com>
References: <1461047395-6532-1-git-send-email-dirk.behme@de.bosch.com>
 <20160427233028.GA5155@verge.net.au> <5721A2A5.9010908@de.bosch.com>
 <20160428234345.GD18128@verge.net.au> <20160429113515.333c42ef@arm.com>
Message-ID: <5728E470.7050408@gmail.com>

Hi Simon,

On 29.04.2016 12:35, Marc Zyngier wrote:
> On Fri, 29 Apr 2016 09:43:45 +1000
> Simon Horman <horms at verge.net.au> wrote:
>
>> [Cc Mark Zyngier, linux-arm-kernel]
>>
>> Hi Dirk,
>>
>> On Thu, Apr 28, 2016 at 07:41:57AM +0200, Dirk Behme wrote:
>>> Hi Simon,
>>>
>>> On 28.04.2016 01:30, Simon Horman wrote:
>>>> Hi Dirk,
>>>>
>>>> I understand that there is an issue here but I'm not yet able
>>>> to convince myself that this is the correct solution.
>>>>
>>>> In revision r0p1 of the CoreLink GIC-400 Generic Interrupt Controller
>>>> Technical Reference Manual[1] I see in Section 3.2. "GIC-400 register map"
>>>> that the size of both the CPU interfaces and Virtual CPU interfaces are
>>>> 0x2000 bytes. And assuming that the hardware follows the specification it
>>>> appears that DT is correctly describing the hardware.
>>>
>>>
>>> I think you are missing the details described by ARM in
>>>
>>> http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=21550029f709072aacf3b9
>>>
>>>
>>> Maybe Julien could help if you have some more doubts?
>>
>> I guess I am confused.
>>
>> I see that there is now handling of the case where the region size is
>> 128Kbytes. But I'm still not seeing the bit which describes that the
>> GIC-400  has a region size of 128Kbytes. Perhaps the later is somehow
>> implied by the former. Or perhaps I need to check with the hw team.
>
> Please have a look at the SBSA document, and in particular the
> Appendix-F (registration and selling your soul required - only kidding):
>
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0029/index.html
>
> This requires that, in order for the two halves of GICV to be trappable
> *separately* by a hypervisor using 64kB pages at Stage-2, the two 4kB
> pages that describe that region are aliased as such:
> - the first 4kB page is aliased 16 times over a 64kB region
> - the second 4kB page is aliased 16 times over another contiguous 64kB
>    region
>
> This means that your GIC is indeed covering a 128kB region, with the
> mapping corresponding to the GICv2 memory map located at offset 0xf000
> from the base of that 128kB region. Also, this GICV requirement also
> applies to GICC (most likely because the two regions use the same
> decoding logic).
>
> The OS must of course be aware of this (see gic_check_eoimode in the
> GIC driver). Of course, almost nobody got that right (I only know of
> the APM Xgene-1 so far). If you actually did, great!
>
> Also, the ACPI spec fails to recognize this by not providing the length
> of the region, meaning that those who got it right with DT are likely
> to get it wrong with ACPI, and vice-versa.
>
> It's a wonderful world.


Could this patch be applied, then?

Best regards

Dirk



From Linux.HWI at garmin.com  Tue May  3 10:49:09 2016
From: Linux.HWI at garmin.com (J.D. Schroeder)
Date: Tue, 3 May 2016 12:49:09 -0500
Subject: [PATCH v2 2/3] ARM: DRA7x: dts: Update the OSC_32K_CLK frequency
In-Reply-To: <5728E0BC.3080509@ti.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
 <1462209123-7332-3-git-send-email-Linux.HWI@garmin.com>
 <57285E66.2000708@ti.com> <5728A81F.4050906@garmin.com>
 <20160503164323.GN5995@atomide.com> <5728E0BC.3080509@ti.com>
Message-ID: <5728E495.4010502@garmin.com>

On 05/03/2016 12:32 PM, Tero Kristo wrote:
> Personally I would not recommend using this clock for any timing sensitive
> applications. May I ask why you are interested in the exact clock rate of this
> clock anyway?

I'm not interested in using this clock and I'm not sure how anyone would use
this clock outside of the processor. See the inline comment that is part of
the change and the commit message for the change. There is no hint in my
change that this is an exact clock rate. It is a clarifying change to help
others avoid using this clock as a 32 kHz clock (which the current clock name
and frequency imply) and it more accurately represents the actual hardware
behavior.



From krzk at kernel.org  Tue May  3 10:52:18 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue,  3 May 2016 19:52:18 +0200
Subject: [RFC PATCH 01/12] dt-bindings: clock: Add license and reformat
 Exynos5410 clock IDs
In-Reply-To: <1462297949-13824-1-git-send-email-krzk@kernel.org>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
Message-ID: <1462297949-13824-2-git-send-email-krzk@kernel.org>

Add license and copyrights (file introduced in 2014) to header with
Exynos5410 clock IDs. Additionally reformat it to improve readability.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 include/dt-bindings/clock/exynos5410.h | 54 ++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 9b180f032e2d..213f19e02870 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -1,33 +1,43 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics 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.
+ *
+ * Device Tree binding constants for Exynos5421 clock controller.
+*/
+
 #ifndef _DT_BINDINGS_CLOCK_EXYNOS_5410_H
 #define _DT_BINDINGS_CLOCK_EXYNOS_5410_H
 
 /* core clocks */
-#define CLK_FIN_PLL 1
-#define CLK_FOUT_APLL 2
-#define CLK_FOUT_CPLL 3
-#define CLK_FOUT_MPLL 4
-#define CLK_FOUT_BPLL 5
-#define CLK_FOUT_KPLL 6
+#define CLK_FIN_PLL		1
+#define CLK_FOUT_APLL		2
+#define CLK_FOUT_CPLL		3
+#define CLK_FOUT_MPLL		4
+#define CLK_FOUT_BPLL		5
+#define CLK_FOUT_KPLL		6
 
 /* gate for special clocks (sclk) */
-#define CLK_SCLK_UART0 128
-#define CLK_SCLK_UART1 129
-#define CLK_SCLK_UART2 130
-#define CLK_SCLK_UART3 131
-#define CLK_SCLK_MMC0 132
-#define CLK_SCLK_MMC1 133
-#define CLK_SCLK_MMC2 134
+#define CLK_SCLK_UART0		128
+#define CLK_SCLK_UART1		129
+#define CLK_SCLK_UART2		130
+#define CLK_SCLK_UART3		131
+#define CLK_SCLK_MMC0		132
+#define CLK_SCLK_MMC1		133
+#define CLK_SCLK_MMC2		134
 
 /* gate clocks */
-#define CLK_UART0 257
-#define CLK_UART1 258
-#define CLK_UART2 259
-#define CLK_UART3 260
-#define CLK_MCT 315
-#define CLK_MMC0 351
-#define CLK_MMC1 352
-#define CLK_MMC2 353
+#define CLK_UART0		257
+#define CLK_UART1		258
+#define CLK_UART2		259
+#define CLK_UART3		260
+#define CLK_MCT			315
+#define CLK_MMC0		351
+#define CLK_MMC1		352
+#define CLK_MMC2		353
 
-#define CLK_NR_CLKS 512
+#define CLK_NR_CLKS		512
 
 #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5410_H */
-- 
2.5.0



From krzk at kernel.org  Tue May  3 10:52:17 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue,  3 May 2016 19:52:17 +0200
Subject: [RFC PATCH 00/12] ARM: dts: exynos: Reorganize before adding Odroid
 XU board
Message-ID: <1462297949-13824-1-git-send-email-krzk@kernel.org>

Hi,


I am in the middle (or beginning) of adding DTS for Odroid XU. This
patchset is a preparation for that. I still did not figure out two
things:
1. clock IDs, should we follow Exynos5420 (or maybe reuse entirely?)
   see patch 1.
2. sd0_rclk - see patch 5.


The Odroid XU board is based on Exynos5410: an octal-core design where
apparently only one cluster (big or little) could be active. The Exynos5410
is a first big.LITTLE design... with its early child issues (naughty kid).

The board itself is a mix between Odroid U3 (based on Exynos4412) and XU3.
For example it has usb3503+smsc95xx LAN as Odroid U3 so probably
same issues as U3 will happen (USB/LAN fails after TFTP boot). On the
other hand it has size, look (case) and most of components the same
as in XU3 and XU3-lite.

As for now you can boot it with Hardkernel U-Boot and SMDK5410 DTB.

Comments welcome!


BR,
Krzysztof


Krzysztof Kozlowski (12):
  dt-bindings: clock: Add license and reformat Exynos5410 clock IDs
  dt-bindings: clock: Add PWM clock ID to Exynos5410
  ARM: dts: exynos: Re-order alphabetically Exynos5420 SD0/SD1 pinctrl
    nodes
  ARM: dts: exynos: Use lowercase for Exynos5410 CPU node labels
  ARM: dts: exynos: Configure Exynos5410 pinctrl for eMMC and SD card
  ARM: dts: exynos: Split Odroid XU3 LEDs to separate DTSI
  ARM: dts: exynos: Move common nodes to exynos5.dtsi
  ARM: dts: exynos: Prepare for inclusion of exynos5.dtsi in
    exynos5410.dtsi
  ARM: dts: exynos: Use phandle to get parent node in exynos5250-snow
  ARM: dts: exynos: Move Exynos5250 and Exynos5420 nodes under soc
  ARM: dts: exynos: Include common exynos5 in exynos5410.dtsi
  ARM: dts: exynos: Enable UART3 on Exynos5410

 arch/arm/boot/dts/exynos5.dtsi                  |  171 +-
 arch/arm/boot/dts/exynos5250-snow-common.dtsi   |    2 +-
 arch/arm/boot/dts/exynos5250.dtsi               | 1718 ++++++++++---------
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi       |   87 +
 arch/arm/boot/dts/exynos5410-smdk5410.dts       |    6 +-
 arch/arm/boot/dts/exynos5410.dtsi               |  112 +-
 arch/arm/boot/dts/exynos5420-pinctrl.dtsi       |   12 +-
 arch/arm/boot/dts/exynos5420.dtsi               | 2058 +++++++++++------------
 arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts |   35 +-
 arch/arm/boot/dts/exynos5422-odroidxu3.dts      |   35 +-
 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi |   50 +
 include/dt-bindings/clock/exynos5410.h          |   56 +-
 12 files changed, 2197 insertions(+), 2145 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi

-- 
2.5.0



From krzk at kernel.org  Tue May  3 10:52:20 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue,  3 May 2016 19:52:20 +0200
Subject: [RFC PATCH 03/12] ARM: dts: exynos: Re-order alphabetically
 Exynos5420 SD0/SD1 pinctrl nodes
In-Reply-To: <1462297949-13824-1-git-send-email-krzk@kernel.org>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
Message-ID: <1462297949-13824-4-git-send-email-krzk@kernel.org>

The 'sd0_rclk' was put in the middle of SD1 nodes. Remove the confusion.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
index 130563b2ca95..14beb7e07323 100644
--- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
@@ -193,17 +193,17 @@
 		samsung,pin-drv = <3>;
 	};
 
-	sd1_clk: sd1-clk {
-		samsung,pins = "gpc1-0";
+	sd0_rclk: sd0-rclk {
+		samsung,pins = "gpc0-7";
 		samsung,pin-function = <2>;
-		samsung,pin-pud = <0>;
+		samsung,pin-pud = <1>;
 		samsung,pin-drv = <3>;
 	};
 
-	sd0_rclk: sd0-rclk {
-		samsung,pins = "gpc0-7";
+	sd1_clk: sd1-clk {
+		samsung,pins = "gpc1-0";
 		samsung,pin-function = <2>;
-		samsung,pin-pud = <1>;
+		samsung,pin-pud = <0>;
 		samsung,pin-drv = <3>;
 	};
 
-- 
2.5.0



From krzk at kernel.org  Tue May  3 10:52:19 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue,  3 May 2016 19:52:19 +0200
Subject: [RFC PATCH 02/12] dt-bindings: clock: Add PWM clock ID to Exynos5410
In-Reply-To: <1462297949-13824-1-git-send-email-krzk@kernel.org>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
Message-ID: <1462297949-13824-3-git-send-email-krzk@kernel.org>

Add ID for PWM clock to Exynos5410. Use the same number as for
Exynos5420.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>

---

A question: does it make sense to stick to same IDs?
---
 include/dt-bindings/clock/exynos5410.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 213f19e02870..8d54ba7ff570 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 Krzysztof Kozlowski
  *
  * 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
@@ -33,6 +34,7 @@
 #define CLK_UART1		258
 #define CLK_UART2		259
 #define CLK_UART3		260
+#define CLK_PWM			279
 #define CLK_MCT			315
 #define CLK_MMC0		351
 #define CLK_MMC1		352
-- 
2.5.0



From krzk at kernel.org  Tue May  3 10:52:21 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue,  3 May 2016 19:52:21 +0200
Subject: [RFC PATCH 04/12] ARM: dts: exynos: Use lowercase for Exynos5410 CPU
 node labels
In-Reply-To: <1462297949-13824-1-git-send-email-krzk@kernel.org>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
Message-ID: <1462297949-13824-5-git-send-email-krzk@kernel.org>

Fro consistency lowercase node labels are used.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 7a56aec2c5ba..8de8c644f42e 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -35,28 +35,28 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		CPU0: cpu at 0 {
+		cpu0: cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU1: cpu at 1 {
+		cpu1: cpu at 1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x1>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU2: cpu at 2 {
+		cpu2: cpu at 2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x2>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU3: cpu at 3 {
+		cpu3: cpu at 3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x3>;
-- 
2.5.0



From krzk at kernel.org  Tue May  3 10:52:22 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue,  3 May 2016 19:52:22 +0200
Subject: [RFC PATCH 05/12] ARM: dts: exynos: Configure Exynos5410 pinctrl for
 eMMC and SD card
In-Reply-To: <1462297949-13824-1-git-send-email-krzk@kernel.org>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
Message-ID: <1462297949-13824-6-git-send-email-krzk@kernel.org>

Configure the pinctrl for MMC0 (eMMC) and MMC2 (microSD card).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>

---

I am not sure about sd0_rclk. Also I wonder whether this should go to
board DTS...
---
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 87 +++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
index f9aa6bb55464..dc12a79b8b32 100644
--- a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
@@ -277,6 +277,93 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
+
+	sd0_clk: sd0-clk {
+		samsung,pins = "gpc0-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cmd: sd0-cmd {
+		samsung,pins = "gpc0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cd: sd0-cd {
+		samsung,pins = "gpc0-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus1: sd0-bus-width1 {
+		samsung,pins = "gpc0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus4: sd0-bus-width4 {
+		samsung,pins = "gpc0-4", "gpc0-5", "gpc0-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus8: sd0-bus-width8 {
+		samsung,pins = "gpc3-0", "gpc3-1", "gpc3-2", "gpc3-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	/* TODO: What's up with with rclk? On Odroid XU this is missing... */
+	/*
+	sd0_rclk: sd0-rclk {
+		samsung,pins = "gpc0-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <1>;
+		samsung,pin-drv = <3>;
+	};
+	*/
+
+	sd2_clk: sd2-clk {
+		samsung,pins = "gpc2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cmd: sd2-cmd {
+		samsung,pins = "gpc2-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cd: sd2-cd {
+		samsung,pins = "gpc2-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus1: sd2-bus-width1 {
+		samsung,pins = "gpc2-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus4: sd2-bus-width4 {
+		samsung,pins = "gpc2-4", "gpc2-5", "gpc2-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
 };
 
 &pinctrl_1 {
-- 
2.5.0



From krzk at kernel.org  Tue May  3 10:52:23 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue,  3 May 2016 19:52:23 +0200
Subject: [RFC PATCH 06/12] ARM: dts: exynos: Split Odroid XU3 LEDs to separate
 DTSI
In-Reply-To: <1462297949-13824-1-git-send-email-krzk@kernel.org>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
Message-ID: <1462297949-13824-7-git-send-email-krzk@kernel.org>

The LED nodes can be shared between Odroid XU3, XU3-Lite and XU (not yet
added) thus removing duplication.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts | 35 +----------------
 arch/arm/boot/dts/exynos5422-odroidxu3.dts      | 35 +----------------
 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi | 50 +++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 68 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi

diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
index 2ae1cf41dcb6..03fa88c45426 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
@@ -14,44 +14,11 @@
 /dts-v1/;
 #include "exynos5422-odroidxu3-common.dtsi"
 #include "exynos5422-odroidxu3-audio.dtsi"
+#include "exynos54xx-odroidxu-leds.dtsi"
 
 / {
 	model = "Hardkernel Odroid XU3 Lite";
 	compatible = "hardkernel,odroid-xu3-lite", "samsung,exynos5800", "samsung,exynos5";
-
-	pwmleds {
-		compatible = "pwm-leds";
-
-		greenled {
-			label = "green:mmc0";
-			pwms = <&pwm 1 2000000 0>;
-			pwm-names = "pwm1";
-			/*
-			 * Green LED is much brighter than the others
-			 * so limit its max brightness
-			 */
-			max_brightness = <127>;
-			linux,default-trigger = "mmc0";
-		};
-
-		blueled {
-			label = "blue:heartbeat";
-			pwms = <&pwm 2 2000000 0>;
-			pwm-names = "pwm2";
-			max_brightness = <255>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-
-	gpioleds {
-		compatible = "gpio-leds";
-		redled {
-			label = "red:microSD";
-			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
-			default-state = "off";
-			linux,default-trigger = "mmc1";
-		};
-	};
 };
 
 &pwm {
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
index 432406db85de..9ed6564acfb0 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
@@ -13,44 +13,11 @@
 /dts-v1/;
 #include "exynos5422-odroidxu3-common.dtsi"
 #include "exynos5422-odroidxu3-audio.dtsi"
+#include "exynos54xx-odroidxu-leds.dtsi"
 
 / {
 	model = "Hardkernel Odroid XU3";
 	compatible = "hardkernel,odroid-xu3", "samsung,exynos5800", "samsung,exynos5";
-
-	pwmleds {
-		compatible = "pwm-leds";
-
-		greenled {
-			label = "green:mmc0";
-			pwms = <&pwm 1 2000000 0>;
-			pwm-names = "pwm1";
-			/*
-			 * Green LED is much brighter than the others
-			 * so limit its max brightness
-			 */
-			max_brightness = <127>;
-			linux,default-trigger = "mmc0";
-		};
-
-		blueled {
-			label = "blue:heartbeat";
-			pwms = <&pwm 2 2000000 0>;
-			pwm-names = "pwm2";
-			max_brightness = <255>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-
-	gpioleds {
-		compatible = "gpio-leds";
-		redled {
-			label = "red:microSD";
-			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
-			default-state = "off";
-			linux,default-trigger = "mmc1";
-		};
-	};
 };
 
 &i2c_0 {
diff --git a/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi b/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
new file mode 100644
index 000000000000..0ed30206625c
--- /dev/null
+++ b/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
@@ -0,0 +1,50 @@
+/*
+ * Hardkernel Odroid XU/XU3 LED device tree source
+ *
+ * Copyright (c) 2015,2016 Krzysztof Kozlowski
+ * Copyright (c) 2014 Collabora Ltd.
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	pwmleds {
+		compatible = "pwm-leds";
+
+		greenled {
+			label = "green:mmc0";
+			pwms = <&pwm 1 2000000 0>;
+			pwm-names = "pwm1";
+			/*
+			 * Green LED is much brighter than the others
+			 * so limit its max brightness
+			 */
+			max_brightness = <127>;
+			linux,default-trigger = "mmc0";
+		};
+
+		blueled {
+			label = "blue:heartbeat";
+			pwms = <&pwm 2 2000000 0>;
+			pwm-names = "pwm2";
+			max_brightness = <255>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	gpioleds {
+		compatible = "gpio-leds";
+		redled {
+			label = "red:microSD";
+			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "mmc1";
+		};
+	};
+};
-- 
2.5.0



From krzk at kernel.org  Tue May  3 10:52:24 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue,  3 May 2016 19:52:24 +0200
Subject: [RFC PATCH 07/12] ARM: dts: exynos: Move common nodes to exynos5.dtsi
In-Reply-To: <1462297949-13824-1-git-send-email-krzk@kernel.org>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
Message-ID: <1462297949-13824-8-git-send-email-krzk@kernel.org>

Exynos5420 and Exynos5250 share some nodes: the PWM and syscon
(sysreg_system_controller). Move them to parent DTSI to avoid
duplication.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5.dtsi    | 12 ++++++++++++
 arch/arm/boot/dts/exynos5250.dtsi | 19 +++++--------------
 arch/arm/boot/dts/exynos5420.dtsi | 19 +++++--------------
 3 files changed, 22 insertions(+), 28 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index d5c0f18a4223..fe901152f3ea 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -63,6 +63,11 @@
 		interrupts = <1 9 0xf04>;
 	};
 
+	sysreg_system_controller: syscon at 10050000 {
+		compatible = "samsung,exynos5-sysreg", "syscon";
+		reg = <0x10050000 0x5000>;
+	};
+
 	serial_0: serial at 12C00000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C00000 0x100>;
@@ -87,6 +92,13 @@
 		interrupts = <0 54 0>;
 	};
 
+	pwm: pwm at 12DD0000 {
+		compatible = "samsung,exynos4210-pwm";
+		reg = <0x12DD0000 0x100>;
+		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
+		#pwm-cells = <3>;
+	};
+
 	rtc: rtc at 101E0000 {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x101E0000 0x100>;
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index c7158b2fb213..6762faaf12a8 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -235,11 +235,6 @@
 		interrupt-parent = <&gic>;
 	};
 
-	sysreg_system_controller: syscon at 10050000 {
-		compatible = "samsung,exynos5-sysreg", "syscon";
-		reg = <0x10050000 0x5000>;
-	};
-
 	watchdog at 101D0000 {
 		compatible = "samsung,exynos5250-wdt";
 		reg = <0x101D0000 0x100>;
@@ -662,15 +657,6 @@
 		samsung,pmureg-phandle = <&pmu_system_controller>;
 	};
 
-	pwm: pwm at 12dd0000 {
-		compatible = "samsung,exynos4210-pwm";
-		reg = <0x12dd0000 0x100>;
-		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
-		#pwm-cells = <3>;
-		clocks = <&clock CLK_PWM>;
-		clock-names = "timers";
-	};
-
 	amba {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -1070,6 +1056,11 @@
 	iommus = <&sysmmu_fimd1>;
 };
 
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
+
 &rtc {
 	clocks = <&clock CLK_RTC>;
 	clock-names = "rtc";
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 4c8523471c65..f7322d87095f 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -542,15 +542,6 @@
 		status = "disabled";
 	};
 
-	pwm: pwm at 12dd0000 {
-		compatible = "samsung,exynos4210-pwm";
-		reg = <0x12dd0000 0x100>;
-		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
-		#pwm-cells = <3>;
-		clocks = <&clock CLK_PWM>;
-		clock-names = "timers";
-	};
-
 	dp_phy: dp-video-phy {
 		compatible = "samsung,exynos5420-dp-video-phy";
 		samsung,pmu-syscon = <&pmu_system_controller>;
@@ -823,11 +814,6 @@
 		interrupt-parent = <&gic>;
 	};
 
-	sysreg_system_controller: syscon at 10050000 {
-		compatible = "samsung,exynos5-sysreg", "syscon";
-		reg = <0x10050000 0x5000>;
-	};
-
 	tmu_cpu0: tmu at 10060000 {
 		compatible = "samsung,exynos5420-tmu";
 		reg = <0x10060000 0x100>;
@@ -1207,6 +1193,11 @@
 	iommu-names = "m0", "m1";
 };
 
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
+
 &rtc {
 	clocks = <&clock CLK_RTC>;
 	clock-names = "rtc";
-- 
2.5.0



From krzk at kernel.org  Tue May  3 10:52:25 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue,  3 May 2016 19:52:25 +0200
Subject: [RFC PATCH 08/12] ARM: dts: exynos: Prepare for inclusion of
 exynos5.dtsi in exynos5410.dtsi
In-Reply-To: <1462297949-13824-1-git-send-email-krzk@kernel.org>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
Message-ID: <1462297949-13824-9-git-send-email-krzk@kernel.org>

Add 'sromc' label to SROM memory controller in common exynos5.dtsi so it
can be referenced by ihneriting DTSI.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index fe901152f3ea..7c83dc6ef972 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -31,7 +31,7 @@
 		reg = <0x10000000 0x100>;
 	};
 
-	memory-controller at 12250000 {
+	sromc: memory-controller at 12250000 {
 		compatible = "samsung,exynos4210-srom";
 		reg = <0x12250000 0x14>;
 	};
-- 
2.5.0



From krzk at kernel.org  Tue May  3 10:52:26 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue,  3 May 2016 19:52:26 +0200
Subject: [RFC PATCH 09/12] ARM: dts: exynos: Use phandle to get parent node in
 exynos5250-snow
In-Reply-To: <1462297949-13824-1-git-send-email-krzk@kernel.org>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
Message-ID: <1462297949-13824-10-git-send-email-krzk@kernel.org>

The i2c-arbitrator node in exynos5250-snow-common used absolute path to
reference other node (the i2c parent). Use phandle instead, because the
depth of the other node may be changed (like moving it under 'soc'
node).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5250-snow-common.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5250-snow-common.dtsi b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
index ddfe1f558c10..419d59da1751 100644
--- a/arch/arm/boot/dts/exynos5250-snow-common.dtsi
+++ b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
@@ -61,7 +61,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		i2c-parent = <&{/i2c at 12CA0000}>;
+		i2c-parent = <&i2c_4>;
 
 		our-claim-gpio = <&gpf0 3 GPIO_ACTIVE_LOW>;
 		their-claim-gpios = <&gpe0 4 GPIO_ACTIVE_LOW>;
-- 
2.5.0



From krzk at kernel.org  Tue May  3 10:52:28 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue,  3 May 2016 19:52:28 +0200
Subject: [RFC PATCH 11/12] ARM: dts: exynos: Include common exynos5 in
 exynos5410.dtsi
In-Reply-To: <1462297949-13824-1-git-send-email-krzk@kernel.org>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
Message-ID: <1462297949-13824-12-git-send-email-krzk@kernel.org>

The exynos5.dtsi is used for common nodes shared between Exynos5250 and
Exynos542x. Since Exynos5410 is very similar to Exynos5420 it can
include the common file as well to remove duplication and make
everything more consistent.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410-smdk5410.dts |   6 +-
 arch/arm/boot/dts/exynos5410.dtsi         | 103 ++++++++++--------------------
 2 files changed, 35 insertions(+), 74 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts
index 0f6429e1b75c..777fcf2edd79 100644
--- a/arch/arm/boot/dts/exynos5410-smdk5410.dts
+++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts
@@ -102,14 +102,14 @@
 	};
 };
 
-&uart0 {
+&serial_0 {
 	status = "okay";
 };
 
-&uart1 {
+&serial_1 {
 	status = "okay";
 };
 
-&uart2 {
+&serial_2 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 8de8c644f42e..c8f2e4881667 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -14,6 +14,7 @@
  */
 
 #include "skeleton.dtsi"
+#include "exynos5.dtsi"
 #include "exynos-syscon-restart.dtsi"
 #include <dt-bindings/clock/exynos5410.h>
 
@@ -26,9 +27,6 @@
 		pinctrl1 = &pinctrl_1;
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
-		serial0 = &uart0;
-		serial1 = &uart1;
-		serial2 = &uart2;
 	};
 
 	cpus {
@@ -70,49 +68,6 @@
 		#size-cells = <1>;
 		ranges;
 
-		combiner: interrupt-controller at 10440000 {
-			compatible = "samsung,exynos4210-combiner";
-			#interrupt-cells = <2>;
-			interrupt-controller;
-			samsung,combiner-nr = <32>;
-			reg = <0x10440000 0x1000>;
-			interrupts =	<0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
-					<0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
-					<0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
-					<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
-					<0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-					<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
-					<0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-					<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
-		};
-
-		gic: interrupt-controller at 10481000 {
-			compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
-			#interrupt-cells = <3>;
-			interrupt-controller;
-			reg =	<0x10481000 0x1000>,
-				<0x10482000 0x1000>,
-				<0x10484000 0x2000>,
-				<0x10486000 0x2000>;
-			interrupts = <1 9 0xf04>;
-		};
-
-		chipid at 10000000 {
-			compatible = "samsung,exynos4210-chipid";
-			reg = <0x10000000 0x100>;
-		};
-
-		sromc: memory-controller at 12250000 {
-			compatible = "samsung,exynos4210-srom";
-			reg = <0x12250000 0x14>;
-			#address-cells = <2>;
-			#size-cells = <1>;
-			ranges = <0 0 0x04000000 0x20000
-				  1 0 0x05000000 0x20000
-				  2 0 0x06000000 0x20000
-				  3 0 0x07000000 0x20000>;
-		};
-
 		pmu_system_controller: system-controller at 10040000 {
 			compatible = "samsung,exynos5410-pmu", "syscon";
 			reg = <0x10040000 0x5000>;
@@ -236,34 +191,40 @@
 			reg = <0x03860000 0x1000>;
 			interrupts = <0 47 0>;
 		};
+	};
+};
 
-		uart0: serial at 12C00000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C00000 0x100>;
-			interrupts = <0 51 0>;
-			clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
 
-		uart1: serial at 12C10000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C10000 0x100>;
-			interrupts = <0 52 0>;
-			clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
+&serial_0 {
+	clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
+	clock-names = "uart", "clk_uart_baud0";
+};
 
-		uart2: serial at 12C20000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C20000 0x100>;
-			interrupts = <0 53 0>;
-			clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
-	};
+&serial_1 {
+	clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
+	clock-names = "uart", "clk_uart_baud0";
+};
+
+&serial_2 {
+	clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
+	clock-names = "uart", "clk_uart_baud0";
+};
+
+&serial_3 {
+	status = "disabled";
+};
+
+&sromc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	ranges = <0 0 0x04000000 0x20000
+		  1 0 0x05000000 0x20000
+		  2 0 0x06000000 0x20000
+		  3 0 0x07000000 0x20000>;
 };
 
 #include "exynos5410-pinctrl.dtsi"
-- 
2.5.0



From krzk at kernel.org  Tue May  3 10:52:29 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue,  3 May 2016 19:52:29 +0200
Subject: [RFC PATCH 12/12] ARM: dts: exynos: Enable UART3 on Exynos5410
In-Reply-To: <1462297949-13824-1-git-send-email-krzk@kernel.org>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
Message-ID: <1462297949-13824-13-git-send-email-krzk@kernel.org>

Just like other Exynos5 family SoCs, this one has four UARTs. Configure
clocks for UART3 and enable it.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index c8f2e4881667..0edcd7022293 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -215,7 +215,8 @@
 };
 
 &serial_3 {
-	status = "disabled";
+	clocks = <&clock CLK_UART3>, <&clock CLK_SCLK_UART3>;
+	clock-names = "uart", "clk_uart_baud0";
 };
 
 &sromc {
-- 
2.5.0



From marc.zyngier at arm.com  Tue May  3 10:59:15 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 3 May 2016 18:59:15 +0100
Subject: [PATCH] KVM: arm/arm64: new-vgic: add proper GICv2 CPU interface
 userland access
In-Reply-To: <5728D92A.9010503@arm.com>
References: <57287A89.9010809@arm.com>
 <1462291649-9906-1-git-send-email-andre.przywara@arm.com>
 <5728D92A.9010503@arm.com>
Message-ID: <5728E6F3.6000801@arm.com>

On 03/05/16 18:00, Marc Zyngier wrote:
> On 03/05/16 17:07, Andre Przywara wrote:
>> Although the actual register access was wired, the availability check
>> for the GICv2 CPU interface register interface was not - leading to
>> any attempt of saving or restoring GICv2 CPU i/f registers to fail.
>>
>> This patch fixes this by modelling the CPU i/f registers similarily to
>> the distributor registers, thereby piggy backing on the existing
>> distributor save/restore code to do the heavy lifting.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Hi,
>>
>> this is a fix for the missing CPU i/f migration that Marc spotted.
>> In a repost I will merge this somehow into the existing patches, but
>> for now this goes on top of the series.
>> Can any of you have a look whether this is the right way to go?
> 
> The whole VMCR story feels very convoluted. It caters for GICv3 (which
> has no way to use it), has global symbols where it should be static,
> and indirections that serve no apparent purpose. And the vgic_vmcr
> structure should really per implementation. </rant> ;-)
> 
> So here's my take on this particular patch:

[... lots of stupid code deleted ...]

Which is completely wrong. I missed the case where we emulate GICv2 on GICv3. So, here's a much smaller patch that goes on top of yours (making the vmcr accessors static and reworking the MMIO handlers):

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index dddd8e1..1967a52 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -206,6 +206,22 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_set_vmcr(vcpu, vmcr);
+	else
+		vgic_v3_set_vmcr(vcpu, vmcr);
+}
+
+static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_get_vmcr(vcpu, vmcr);
+	else
+		vgic_v3_get_vmcr(vcpu, vmcr);
+}
+
 #define GICC_ARCH_VERSION_V2	0x2
 
 /* These are for userland accesses only, there is no guest-facing emulation. */
@@ -213,33 +229,33 @@ static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
 					   gpa_t addr, unsigned int len)
 {
 	struct vgic_vmcr vmcr;
-	u32 *field;
+	u32 val;
+
+	vgic_get_vmcr(vcpu, &vmcr);
 
 	switch (addr & 0xff) {
 	case GIC_CPU_CTRL:
-		field = &vmcr.ctlr;
+		val = vmcr.ctlr;
 		break;
 	case GIC_CPU_PRIMASK:
-		field = &vmcr.pmr;
+		val = vmcr.pmr;
 		break;
 	case GIC_CPU_BINPOINT:
-		field = &vmcr.bpr;
+		val = vmcr.bpr;
 		break;
 	case GIC_CPU_ALIAS_BINPOINT:
-		field = &vmcr.abpr;
+		val = vmcr.abpr;
 		break;
 	case GIC_CPU_IDENT:
-		return extract_bytes((PRODUCT_ID_KVM << 20) |
-				     (GICC_ARCH_VERSION_V2 << 16) |
-				     (IMPLEMENTER_ARM << 0),
-				     addr & 3, len);
+		val = ((PRODUCT_ID_KVM << 20) |
+		       (GICC_ARCH_VERSION_V2 << 16) |
+		       IMPLEMENTER_ARM);
+		break;
 	default:
 		return 0;
 	}
 
-	vgic_get_vmcr(vcpu, &vmcr);
-
-	return extract_bytes(*field, addr & 3, len);
+	return extract_bytes(val, addr & 3, len);
 }
 
 static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
@@ -247,30 +263,24 @@ static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
 				   unsigned long val)
 {
 	struct vgic_vmcr vmcr;
-	u32 *field;
+
+	vgic_get_vmcr(vcpu, &vmcr);
 
 	switch (addr & 0xff) {
 	case GIC_CPU_CTRL:
-		field = &vmcr.ctlr;
+		vmcr.ctlr = val;
 		break;
 	case GIC_CPU_PRIMASK:
-		field = &vmcr.pmr;
+		vmcr.pmr = val;
 		break;
 	case GIC_CPU_BINPOINT:
-		field = &vmcr.bpr;
+		vmcr.bpr = val;
 		break;
 	case GIC_CPU_ALIAS_BINPOINT:
-		field = &vmcr.abpr;
+		vmcr.abpr = val;
 		break;
-	default:
-		return;
 	}
 
-	vgic_get_vmcr(vcpu, &vmcr);
-	if (*field == val)
-		return;
-
-	*field = val;
 	vgic_set_vmcr(vcpu, &vmcr);
 }
 
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 5f21742..b22e2ac 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -482,22 +482,6 @@ static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
 		vgic_v3_set_underflow(vcpu);
 }
 
-void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
-{
-	if (kvm_vgic_global_state.type == VGIC_V2)
-		vgic_v2_set_vmcr(vcpu, vmcr);
-	else
-		vgic_v3_set_vmcr(vcpu, vmcr);
-}
-
-void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
-{
-	if (kvm_vgic_global_state.type == VGIC_V2)
-		vgic_v2_get_vmcr(vcpu, vmcr);
-	else
-		vgic_v3_get_vmcr(vcpu, vmcr);
-}
-
 static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
 {
 	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index c1f3751..800be90 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -116,9 +116,6 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 }
 #endif
 
-void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
-void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
-
 int vgic_lazy_init(struct kvm *kvm);
 int vgic_init(struct kvm *kvm);
 void kvm_register_vgic_device(unsigned long type);


Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From robh at kernel.org  Tue May  3 11:00:22 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 3 May 2016 13:00:22 -0500
Subject: [RFT PATCH 1/3] usb: misc: usb3503: Fix HUB mode after
 bootloader initialization
In-Reply-To: <20160502105501.GE6292@sirena.org.uk>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <1461927591-7864-2-git-send-email-k.kozlowski@samsung.com>
 <20160429113059.GX3217@sirena.org.uk>
 <57234BA2.6020304@samsung.com>
 <20160429164448.GY3217@sirena.org.uk> <57272298.50701@samsung.com>
 <20160502105501.GE6292@sirena.org.uk>
Message-ID: <20160503180022.GA3008@rob-hp-laptop>

On Mon, May 02, 2016 at 11:55:01AM +0100, Mark Brown wrote:
> On Mon, May 02, 2016 at 11:49:12AM +0200, Krzysztof Kozlowski wrote:
> 
> > This VDD regulator supply actually is not a usb3503 USB HUB regulator
> > supply... but a supply to the LAN attached to this HUB. Regulator off/on
> > is needed for LAN to show up. The hub will show up with typical reset
> > (which is also missing before my patchset btw).
> 
> > The LAN, as a USB device, is auto-probed so it cannot take the regulator
> > and play with it. The simplest idea I have is to add it as "external
> > supply"  to the parent: usb3503.
> 
> This is common enough that that just isn't going to scale well I fear
> without some generic handling, either walking child devices at the bus
> level or at the device level with a pre-probe() callback to get the
> device to power on.  The latter is more appropriate to things like
> Slimbus where the device is more likely to do active management at
> runtime, it's not clear people are building USB devices like that.

There's a new binding and support in -next (.../usb/usb-device.txt) for 
USB devices that should help here. Though, how to handle a hub on USB 
and I2C buses would need to be worked out.

Rob


From tony at atomide.com  Tue May  3 11:08:26 2016
From: tony at atomide.com (Tony Lindgren)
Date: Tue, 3 May 2016 11:08:26 -0700
Subject: [PATCH v2 2/3] ARM: DRA7x: dts: Update the OSC_32K_CLK frequency
In-Reply-To: <5728E495.4010502@garmin.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
 <1462209123-7332-3-git-send-email-Linux.HWI@garmin.com>
 <57285E66.2000708@ti.com> <5728A81F.4050906@garmin.com>
 <20160503164323.GN5995@atomide.com> <5728E0BC.3080509@ti.com>
 <5728E495.4010502@garmin.com>
Message-ID: <20160503180826.GP5995@atomide.com>

* J.D. Schroeder <Linux.HWI at garmin.com> [160503 10:50]:
> On 05/03/2016 12:32 PM, Tero Kristo wrote:
> > Personally I would not recommend using this clock for any timing sensitive
> > applications. May I ask why you are interested in the exact clock rate of this
> > clock anyway?
> 
> I'm not interested in using this clock and I'm not sure how anyone would use
> this clock outside of the processor. See the inline comment that is part of
> the change and the commit message for the change. There is no hint in my
> change that this is an exact clock rate. It is a clarifying change to help
> others avoid using this clock as a 32 kHz clock (which the current clock name
> and frequency imply) and it more accurately represents the actual hardware
> behavior.

Well if it's inaccurate, how about we just add comments to the clock?

Tony


From t-kristo at ti.com  Tue May  3 11:08:54 2016
From: t-kristo at ti.com (Tero Kristo)
Date: Tue, 3 May 2016 21:08:54 +0300
Subject: [PATCH v2 2/3] ARM: DRA7x: dts: Update the OSC_32K_CLK frequency
In-Reply-To: <5728E495.4010502@garmin.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
 <1462209123-7332-3-git-send-email-Linux.HWI@garmin.com>
 <57285E66.2000708@ti.com> <5728A81F.4050906@garmin.com>
 <20160503164323.GN5995@atomide.com> <5728E0BC.3080509@ti.com>
 <5728E495.4010502@garmin.com>
Message-ID: <5728E936.2010503@ti.com>

On 03/05/16 20:49, J.D. Schroeder wrote:
> On 05/03/2016 12:32 PM, Tero Kristo wrote:
>> Personally I would not recommend using this clock for any timing sensitive
>> applications. May I ask why you are interested in the exact clock rate of this
>> clock anyway?
>
> I'm not interested in using this clock and I'm not sure how anyone would use
> this clock outside of the processor. See the inline comment that is part of
> the change and the commit message for the change. There is no hint in my
> change that this is an exact clock rate. It is a clarifying change to help
> others avoid using this clock as a 32 kHz clock (which the current clock name
> and frequency imply) and it more accurately represents the actual hardware
> behavior.
>

Imo, if you want to clarify things up, the whole secure_32k_ck should be 
removed from linux kernel.

-Tero


From Nitin.Saxena at caviumnetworks.com  Tue May  3 11:42:31 2016
From: Nitin.Saxena at caviumnetworks.com (Saxena, Nitin)
Date: Tue, 3 May 2016 18:42:31 +0000
Subject: VFIO MSIX Query
Message-ID: <3517EB80-0AE6-4F54-AC0B-C1D0DC01158C@caviumnetworks.com>

Hi,

I am a newbie to VFIO framework and trying to use it for MSIX interrupt handling in my userspace application. My userspace application is like intel's dpdk.

My query is why vfio kernel code does not support msix masking/ unmasking i.e VFIO_SET_ACTION_TRIGGER is not implemented in kernel vfio code for MSIX but its present for legacy INTX?

Another question since MSIX interrupt masking is absent in kernel who is supposed to mask/unmask msix interrupt? does userspace needs to mask/unmask interrupt after getting notified by eventfd. Is there any usecase where MSIX handling is done via VFIO framework?

Thanks,
Nitin 


Regards,
Nitin

From robh at kernel.org  Tue May  3 12:11:04 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 3 May 2016 14:11:04 -0500
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <20160503185153.5cfddc32@bbrezillon>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop> <20160503185153.5cfddc32@bbrezillon>
Message-ID: <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>

On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
<boris.brezillon at free-electrons.com> wrote:
> Hi Rob,
>
> On Tue, 3 May 2016 11:40:19 -0500
> Rob Herring <robh at kernel.org> wrote:
>
>> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:
>> > The EBI (External Bus Interface) is used to access external peripherals
>> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
>> > Each device is assigned a CS line and an address range and can have its
>> > own configuration (timings, access mode, bus width, ...).
>> > This driver provides a generic DT binding to configure a device according
>> > to its requirements.
>> > For specific device controllers (like the NAND one) the SMC timings
>> > should be configured by the controller driver through the matrix and smc
>> > syscon regmaps.
>> >
>> > Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
>> > ---
>> >  .../bindings/memory-controllers/atmel,ebi.txt      | 136 +++++++++++++++++++++
>> >  1 file changed, 136 insertions(+)
>> >  create mode 100644 Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
>> >
>> > diff --git a/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
>> > new file mode 100644
>> > index 0000000..a6dca5c
>> > --- /dev/null
>> > +++ b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
>> > @@ -0,0 +1,136 @@
>> > +* Device tree bindings for Atmel EBI
>> > +
>> > +The External Bus Interface (EBI) controller is a bus where you can connect
>> > +asynchronous (NAND, NOR, SRAM, ....) and synchronous memories (SDR/DDR SDRAMs).
>> > +The EBI provides a glue-less interface to asynchronous memories through the SMC
>> > +(Static Memory Controller).
>> > +
>> > +Required properties:
>> > +
>> > +- compatible:              "atmel,at91sam9260-ebi"
>> > +                   "atmel,at91sam9261-ebi"
>> > +                   "atmel,at91sam9263-ebi0"
>> > +                   "atmel,at91sam9263-ebi1"
>>
>> What are the differences between 0 and 1?
>
> Because this SoC has 2 EBI busses with different capabilities.

Okay, correct answer. :)

[...]

>>
>> > +                   of the memory region requested by the device.
>> > +
>> > +EBI bus configuration associated with specific chip-select will be defined in
>> > +the configs subnode. This configs node will in turn contain several subnodes
>> > +named config-<cs-id>, each of them containing the following properties.
>>
>> This is a bit unusual. Why not just part of the child device nodes?
>
> Oh, come on! I reworked the binding because Mark complained about the
> previous binding which was doing exactly what you're suggesting. Can
> you please be consistent in your reviews...

No, Mark and I both have our opinions. Which part of this patch
explains the history? If the revision history is not in the patch, I'm
not looking at it.

My issue with it this way is that it has invented yet another way to
describe timings. I would like to be consistent across external bus
descriptions, but we're not very consistent to begin with though. The
most common seems to be the way you first did it. But I agree that it
is kind of screwy to have an intermediate node unless the controller
itself has sub-blocks within it and is not the established way to
describe a bus with chip selects. I would either put the properties
directly in the child nodes (e.g. flash at 0,0) or put your config nodes
in the device node. I'd call it timings instead of config, but that's
just bikeshedding.

memory-controller at 1000 {
  ...
  flash at 0,0 {
    timings {
      ...
    };
  };
};

>> > +
>> > +Optional config-<cs-id> node properties:
>> > +
>> > +- atmel,bus-width:         width of the asynchronous device's data bus
>> > +                           8, 16 or 32.
>> > +                           Default to 8 when undefined.
>> > +
>> > +- atmel,byte-access-type   "write" or "select" (see Atmel datasheet).
>> > +                           Default to "select" when undefined.
>> > +
>> > +- atmel,read-mode          "nrd" or "ncs".
>> > +                           Default to "ncs" when undefined.
>> > +
>> > +- atmel,write-mode         "nwe" or "ncs".
>> > +                           Default to "ncs" when undefined.
>> > +
>> > +- atmel,exnw-mode          "disabled", "frozen" or "ready".
>> > +                           Default to "disabled" when undefined.
>> > +
>> > +- atmel,page-mode          enable page mode if present. The provided value
>> > +                           defines the page size (supported values: 4, 8,
>> > +                           16 and 32).
>> > +
>> > +- atmel,tdf-mode:          "normal" or "optimized". When set to
>>
>> This should be boolean.
>
> It was a formerly defined as a boolean, and when it's done like that we
> have no way to identify whether the property was forgotten or
> intentionally set to normal mode. What's the problem with this approach?

Only preference to use boolean when that is sufficient. With your
argument, then we should never have booleans. You state that missing
means "normal", not forgotten, so all these properties should be
required with no default.

BTW, I debated the same thing on the other properties, but I could see
them being expanded to a 3rd mode. I don't see that here though.

Rob


From tpiepho at kymetacorp.com  Tue May  3 12:17:34 2016
From: tpiepho at kymetacorp.com (Trent Piepho)
Date: Tue, 3 May 2016 19:17:34 +0000
Subject: [PATCH v2 0/4] Patches to allow consistent mmc / mmcblk numbering
 w/ device tree
In-Reply-To: <20160430104832.GJ19428@n2100.arm.linux.org.uk>
References: <20160429195741.GY19428@n2100.arm.linux.org.uk>
 <CAD=FV=UGyi0r3kDmc1cpcANTP-2u+7UEgW3r9kRvF2f8qcWH+g@mail.gmail.com>
 <20160429211328.GZ19428@n2100.arm.linux.org.uk>
 <CAD=FV=V8BOsO36eUOGAcXp04xCiN13UGG0Vaf2yhh1MQn85FjA@mail.gmail.com>
 <20160429212920.GA19428@n2100.arm.linux.org.uk>
 <CAD=FV=V9V8P=d59RX1eaAdVxJgMxub1F6hzQNw1QW+7t=3POBw@mail.gmail.com>
 <20160429215017.GC19428@n2100.arm.linux.org.uk>
 <CAD=FV=VgQX_EVhUUCugzv+CZqjzTS8LwyeU5419aX9FbDnWJDg@mail.gmail.com>
 <20160429221606.GE19428@n2100.arm.linux.org.uk>
 <CABxcv==4C+RrEV1Fd+DkbMdGrLyObw36vsmo3wTGdxO=UnAa8w@mail.gmail.com>
 <20160430104832.GJ19428@n2100.arm.linux.org.uk>
Message-ID: <1462303111.9103.225.camel@rtred1test09.kymeta.local>

On Sat, 2016-04-30 at 11:48 +0100, Russell King - ARM Linux wrote:
> On Fri, Apr 29, 2016 at 06:42:35PM -0400, Javier Martinez Canillas wrote:
> > Maybe a third opinion could make this conversation constructive again.

And maybe a forth.

> > I think Doug's point is that using a UUID or labels for consistency is
> > orthogonal to having a deterministic numbering for MMC devices. And I
> > agree with his point of view for what is worth.
> 
> Yes, it may be orthogonal, but there are two issues here:
> 
> 1. How does the system know which MMC device to mount for its rootfs.
> 
> This is the point that I've picked up on, which has been solved for
> years, and actually pre-dates MMC support in the kernel, and that is
> mount by UUID.

What about eMMC boot blocks and replay protected memory block?  These
are special sub-device like features of eMMC that provide storage from
different areas than the normal flash.  The kernel names them something
like "/dev/mmcblk0boot0" and "/dev/mmcblk1rpmb".

They typically don't have partition tables and in fact the kernel
xplicitly does not scan them for a partition table.  So how can they
have a UUID?

Suppose your device has two SD slots, neither with an SD card inserted
in it, one external and one internal behind a locked access panel.  They
serve different purposes.  How do you determine which is which via UUID
when they have no media?

> The kernel itself has no support for mount-by-label, which is normally
> solved by using an initramfs, which contains programs such as mount
> etc which will scan the block devices looking for an appropriately
> labelled filesystem.  Label has slightly more issues since its possible

But what is faster, using an initramfs that loads a working userspace
into RAM, scans the flash device for partition labels, determines the
device ID, and then switches to the real rootfs.  Or having the
bootloader, which already knows the partition the rootfs is in, tell the
kernel what device to mount from the beginning?

Which brings me to another reason for providing device enumeration
information via the device tree that isn't just about mounting the root
filesystem.

The bootloader will create an enumeration of devices so that it can
access them.  The kernel will also create an enumeration of the same
devices.  Should these enumerations be the same, or should they be
different?

Clearly there are advantages to the enumeration being the same.  It's
easier on users if device IDs can be the same between the two
environments, bootloader and kernel, the device can be accessed from.

It also makes it easier if information about a device needs to be passed
from the bootloader to the kernel.  This could be the root filesystem,
but that's not the only thing.  Console serial port is another.  But we
could also want to kernel to know which of the SoC's ports is connected
to the blank eMMC chip it should create a partition table on and format,
and which is connected to the SD card it should store logging data to.

I can't think of any advantage of the enumerations being different.

So if identical enumerations are desirable, how to achieve it?

One way would be to have the bootloader create its enumeration and then
throw it away when the kernel boots.  The the kernel creates a new
enumeration from scratch, using a different system with different code
and a different design, that happens to create the same enumeration that
the bootloader did.  This seems like a bad design to me.  Two different
code bases will need to kept in sync, to always to the same thing in a
different way.  It will be hard to avoid bugs from corner cases that
fail to produce the same enumerations.

Another way would be to have the bootloader tell the kernel what it
enumerated and then have the kernel use this enumeration.  This avoids
the need to keep two code bases in sync.  It avoids bugs where they fail
to produce the same enumeration.

And how to do this pass the enumeration from the bootloader to the
kernel?  The same way all other information from the bootloader is
passed to the kernel, via the device tree.

The alias system that already exists allows the bootloader to tell the
kernel about enumerations it has already created, which it must do since
it runs before the kernel, and would like the kernel to continue to use.

So this isn't just about finding the root filesystem.  It's about
passing enumeration information from the bootloader to the kernel.


From robert.jarzmik at free.fr  Tue May  3 12:22:05 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Tue, 03 May 2016 21:22:05 +0200
Subject: [RFC PATCH 1/7] ALSA: ac97: split out the generic ac97 registers
In-Reply-To: <20160503115159.GP6292@sirena.org.uk> (Mark Brown's message of
 "Tue, 3 May 2016 12:51:59 +0100")
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-2-git-send-email-robert.jarzmik@free.fr>
 <20160503115159.GP6292@sirena.org.uk>
Message-ID: <87y47roski.fsf@belgarion.home>

Mark Brown <broonie at kernel.org> writes:

> On Sat, Apr 30, 2016 at 11:15:33PM +0200, Robert Jarzmik wrote:
>> Split out from the ac97_codec.h the ac97 generic registers, which can be
>> used by a codec, typically a generic ac97 codec, and by the ac97 bus, to
>> scan an ac97 AC-Link.
>
> I don't entirely see the value in this one but equally it does no harm.
Oh that's to have the defines AC97_VENDOR_ID1 and AC97_VENDOR_ID2, but without
including ac97_codec.h in sound/ac97/bus.c.

Cheers.

-- 
Robert


From robert.jarzmik at free.fr  Tue May  3 12:43:20 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Tue, 03 May 2016 21:43:20 +0200
Subject: [RFC PATCH 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <20160503162938.GT6292@sirena.org.uk> (Mark Brown's message of
 "Tue, 3 May 2016 17:29:38 +0100")
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
 <20160503162938.GT6292@sirena.org.uk>
Message-ID: <87twiforl3.fsf@belgarion.home>

Mark Brown <broonie at kernel.org> writes:

> On Sat, Apr 30, 2016 at 11:15:34PM +0200, Robert Jarzmik wrote:
>> AC97 is a bus for sound usage. It enables for a AC97 AC-Link to link one
>> controller to 0 to 4 AC97 codecs.
>
>> The goal of this new implementation is to implement a device/driver
>> model for AC97, with an automatic scan of the bus and automatic
>> discovery of AC97 codec devices.
>
> I think this is basically what I was thinking of, yes.  One thing we'll
> need to do is work out how to handle systems that need some explicit
> action to start clocks for the bus clock, though they were never very
> common and it's entirely possible nobody cares any more so perhaps we
> just punt and see if anyone notices for now.
You probably mean the BITCLK clock.

What is a bit pesky about this clock is that it can either be mastered by
digital controller and the codec is a slave, or the other way around.

So we had either the BITCLK provided by :
 - the controller
   => this could be passed in ac97_digital_controller_register()
 - the codec
   => this is trouble, I don't really know how to handle this case

If the bus code has this clock, it can indeed prepare and enable it.

>> +int ac97_digital_controller_register(const struct ac97_controller_ops *ops,
>> +				     struct device *dev);
>> +int ac97_digital_controller_unregister(const struct device *dev);
>
> Why "digital"?
I copy-pasted this from Audio Codec '97 Revision 2.3, where in several places
they call the controller a "digital controller".

Quoting chapter 1.4:
    The digital link that connects the AC ?97 Digital Controller to the AC ?97
    Codec, referred to as AC-link, is a bi- directional, 5-wire, serial time
    domain multiplexed (TDM) format interface. AC-link supports connections
    between a single Controller and up to 4 CODECs on a circuit board and/or
    riser card.

Now if you prefer "ac97_controller" or something like that, that's as you wish,
the name does not matter that much to me ;)

Cheers.

-- 
Robert


From nicoleotsuka at gmail.com  Tue May  3 12:52:31 2016
From: nicoleotsuka at gmail.com (Nicolin Chen)
Date: Tue, 3 May 2016 12:52:31 -0700
Subject: mx6ul: Finding a good place to configure SAI2_MCLK
In-Reply-To: <20160503124203.GH5874@tiger>
References: <CAOMZO5CvT1rcHFPm6KoCBBgM1UACByLUQcJ_zDxY9ucbxCpgYA@mail.gmail.com>
 <20160503124203.GH5874@tiger>
Message-ID: <20160503195230.GA25881@Asurada-Nvidia>

On Tue, May 03, 2016 at 08:42:03PM +0800, Shawn Guo wrote:
> On Mon, May 02, 2016 at 08:59:17PM -0300, Fabio Estevam wrote:
> > Hi,
> > 
> > In order to get audio working on imx6ul-evk board we need to enable
> > the SAI2 MCLK clock by setting bit 20 (SAI2_MCLK_DIR) of the
> > IOMUXC_GPR_GPR1 register.
> > 
> > I am not sure where is the appropriate place to set this bit.
> > 
> > Doing like this works fine:
> > 
> > --- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
> > +++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
> > @@ -447,5 +447,6 @@
> >  #define IMX6UL_GPR1_ENET2_CLK_OUTPUT           (0x1 << 18)
> >  #define IMX6UL_GPR1_ENET_CLK_DIR               (0x3 << 17)
> >  #define IMX6UL_GPR1_ENET_CLK_OUTPUT            (0x3 << 17)
> > +#define IMX6UL_GPR1_SAI2_MCLK_DIR              (0x1 << 20)
> > 
> > index a38b16b..92cfb0f 100644
> > --- a/arch/arm/mach-imx/mach-imx6ul.c
> > +++ b/arch/arm/mach-imx/mach-imx6ul.c
> > @@ -56,6 +56,19 @@ static inline void imx6ul_enet_init(void)
> >         imx6ul_enet_phy_init();
> >  }
> > 
> > +static void __init imx6ul_mclk_init(void)
> > +{
> > +       struct regmap *gpr;
> > +
> > +       gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr");
> > +       if (!IS_ERR(gpr))
> > +               regmap_update_bits(gpr, IOMUXC_GPR1, IMX6UL_GPR1_SAI2_MCLK_DIR,
> > +                                  IMX6UL_GPR1_SAI2_MCLK_DIR);
> > +       else
> > +               pr_err("failed to find fsl,imx6ul-iomux-gpr regmap\n");
> > +
> > +}
> > +
> >  static void __init imx6ul_init_machine(void)
> >  {
> >         struct device *parent;
> > @@ -68,6 +81,7 @@ static void __init imx6ul_init_machine(void)
> >         imx6ul_enet_init();
> >         imx_anatop_init();
> >         imx6ul_pm_init();
> > +       imx6ul_mclk_init();
> >  }
> > 
> > but it does not seem correct as this should be board specific. Should
> > we call it only if the compatible string matches imx6sl-14x14-evk
> > string? Looks like that will not scale as well.
> > 
> > Currently in arch/arm/mach-imx/mach-imx6ul.c we also have
> > imx6ul_enet_clk_init() function which sets the ENET_CLK in the GPR1
> > register.
> > 
> > IMHO this is not correct because not all mx6ul boards need such clock
> > and then we need to change this too.
> > 
> > So where should we set the SAI2_MCLK_DIR bit of GPR1? Inside the SAI driver?
> 
> To me, it's the best if we can handle this in SAI driver.

Since the clock relationships are being handled by DT now, I feel
plausible to put this GPR hack in an audio driver, SAI or machine.

For SAI driver, it requires a DT property to indicate whether the
controller has the capability of getting/driving the MCLK from/to
the pad because it may not have this GPR hack, SAI1 for example.
Meanwhile, ASoC has a set_dai_sysclk() to configure the direction
of sysclk (MCLK).

> 
> Shawn
> 
> > 
> > Appreciate some feedback.
> > 
> > Thanks,
> > 
> > Fabio Estevam
> > 
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From alex.williamson at redhat.com  Tue May  3 13:02:49 2016
From: alex.williamson at redhat.com (Alex Williamson)
Date: Tue, 3 May 2016 14:02:49 -0600
Subject: VFIO MSIX Query
In-Reply-To: <CAB995Mu0==PJ0iU4h_3oAMGo-VYDFrjOg_BO757M=PDWgMWtCw@mail.gmail.com>
References: <CAB995Mu0==PJ0iU4h_3oAMGo-VYDFrjOg_BO757M=PDWgMWtCw@mail.gmail.com>
Message-ID: <20160503140249.4edaf3cc@t450s.home>

Hi,

On Tue, 3 May 2016 23:56:38 +0530
Nitin Saxena <nitin.lnx at gmail.com> wrote:

> Hi,
> 
> I am a newbie to VFIO framework and trying to use it for MSIX interrupt
> handling in my userspace application. My userspace application is like
> intel's dpdk.
> 
> My query is why vfio kernel code does not support msix masking/ unmasking
> i.e VFIO_SET_ACTION_TRIGGER is not implemented in kernel vfio code for MSIX
> but its present for legacy INTX?

I think you mean VFIO_IRQ_SET_ACTION_MASK and
VFIO_IRQ_SET_ACTION_UNMASK are not implemented for MSI/X,
VFIO_IRQ_SET_ACTION_TRIGGER is the only one that is implemented.  It
mostly comes down to it hasn't been needed.  We would just need to
verify that disable_irq() and enable_irq() do the right thing and
enable the features through the existing VFIO API.  The reason we have
these for INTx is that INTx is level triggered and we must mask the
interrupt on the host while it's serviced by the user because the
interrupt will continue to assert and we have no service guarantees
from the user.  MSI/X is of course edge triggered, so doesn't have this
problem.  The device would need to continue to re-assert the
interrupt.  In cases like a QEMU user, we might want to continue to
receive guest masked interrupts to QEMU for emulating the pending bits
array, so even if we had VFIO masking support for these interrupts, QEMU
probably would not use it.  If MSI/X masking is useful for you vs simply
ignoring the eventfd, patches welcome.

> Another question since MSIX interrupt masking is absent in kernel who is
> supposed to mask/unmask msix interrupt? does userspace needs to mask/unmask
> interrupt after getting notified by eventfd. Is there any usecase where
> MSIX handling is done via VFIO framework?

MSI/X is edge triggered and VFIO does not set the AUTOMASKED flag on
them, so there is simply no masking of them at all aside from fully
disabling them.  QEMU has full support for MSI/X through VFIO that you
can use for reference.  Thanks,

Alex


From pku.leo at gmail.com  Tue May  3 13:05:33 2016
From: pku.leo at gmail.com (Leo Li)
Date: Tue, 3 May 2016 15:05:33 -0500
Subject: [v8, 6/7] MAINTAINERS: add entry for Freescale SoC specific driver
In-Reply-To: <HE1PR04MB088907CD90586FC83D058003F8630@HE1PR04MB0889.eurprd04.prod.outlook.com>
References: <1461306464-19521-1-git-send-email-yangbo.lu@nxp.com>
 <1461306464-19521-7-git-send-email-yangbo.lu@nxp.com>
 <1461367352.32510.218.camel@buserror.net>
 <HE1PR04MB088907CD90586FC83D058003F8630@HE1PR04MB0889.eurprd04.prod.outlook.com>
Message-ID: <CADRPPNQaLVHp_HnEcHvZE7ebcmhYKf4K8CeWHErRk-0Xv8cU3A@mail.gmail.com>

On Mon, Apr 25, 2016 at 10:12 PM, Yangbo Lu <yangbo.lu at nxp.com> wrote:
> Hi Scott and Leo,
>
>
>> -----Original Message-----
>> From: linux-mmc-owner at vger.kernel.org [mailto:linux-mmc-
>> owner at vger.kernel.org] On Behalf Of Scott Wood
>> Sent: Saturday, April 23, 2016 7:23 AM
>> To: Yangbo Lu; linux-mmc at vger.kernel.org; linuxppc-dev at lists.ozlabs.org;
>> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
>> Cc: ulf.hansson at linaro.org; Zhao Qiang; Russell King; Bhupesh Sharma;
>> Scott Wood; Claudiu Manoil; Kumar Gala; Yang-Leo Li; Xiaobo Xie; Michael
>> Ellerman
>> Subject: Re: [v8, 6/7] MAINTAINERS: add entry for Freescale SoC specific
>> driver
>>
>> On Fri, 2016-04-22 at 14:27 +0800, Yangbo Lu wrote:
>> > Add maintainer entry for Freescale SoC specific driver including the
>> > QE library and the GUTS driver. Also add entry for GUTS driver and add
>> > maintainer for QE library.
>> >
>> > Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
>> > ---
>> > Changes for v8:
>> >     - Added this patch
>> > ---
>> >  MAINTAINERS | 16 +++++++++++++++-
>> >  1 file changed, 15 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/MAINTAINERS b/MAINTAINERS index 1d5b4be..d20aeb6 100644
>> > --- a/MAINTAINERS
>> > +++ b/MAINTAINERS
>> > @@ -4622,13 +4622,27 @@ F:  drivers/net/ethernet/freescale/fec_ptp.c
>> >  F: drivers/net/ethernet/freescale/fec.h
>> >  F: Documentation/devicetree/bindings/net/fsl-fec.txt
>> >
>> > +FREESCALE SOC SPECIFIC DRIVER
>>
>> FREESCALE SOC DRIVERS
>
> [Lu Yangbo-B47093] Ok, will change it to 'FREESCALE SOC DRIVERS'.
>
>>
>> > +M: Scott Wood <oss at buserror.net>
>>
>> Please CC me at this address, not the NXP address that you sent this to...
>
> [Lu Yangbo-B47093] Sorry for mistaking your email. Will send the one you said.
>
>>
>> > +L: linuxppc-dev at lists.ozlabs.org
>> > +S: Maintained
>> > +F: drivers/soc/fsl/
>> > +F: include/linux/fsl/
>>
>> This directory will contain drivers that work on PPC and ARM... I'm not
>> sure what to put here in terms of mailing lists (we could put both, but
>> people probably shouldn't spam both lists if only one arch is relevant to
>> the patch), and whom to make pull requests to.
>
> [Lu Yangbo-B47093] But sooner or later we need to do this for files in fsl/ ...
> :)
>
> Hi Leo, do you have any idea?

I think it would be ok to put both linuxppc and linux-arm mailing
lists here.  Driver doesn't fall into any of the functional based
sub-systems would very likely be platform stuff.  And if patch author
has the knowledge that a patch only impacts one arch, he can remove
the other list to reduce the spam.

>
>
>>
>> > +FREESCALE GUTS DRIVER
>> > +M: Yangbo Lu <yangbo.lu at nxp.com>
>> > +L: linuxppc-dev at lists.ozlabs.org
>> > +S: Maintained
>> > +F: drivers/soc/fsl/guts.c
>>
>> What about the header?
>>
>> Does guts really need a separate maintainer from drivers/soc/fsl?
>
> [Lu Yangbo-B47093] I was hesitating to add the maintainer...
> And I was not so familiar with it. Let me leave it to the fsl/ directory and remove this...
>
>>
>> -Scott
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majordomo at vger.kernel.org More majordomo info at
>> http://vger.kernel.org/majordomo-info.html
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev



-- 
- Leo


From arnd at arndb.de  Tue May  3 13:12:23 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 03 May 2016 22:12:23 +0200
Subject: [PATCH V4 0/2] vfio, platform: add ACPI support
In-Reply-To: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>
References: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>
Message-ID: <3322250.xDEDujoeAM@wuerfel>

On Sunday 01 May 2016 17:07:50 Sinan Kaya wrote:
> The patchset makes three different changes.
> 1. Add support for probing ACPI platform devices.
> 2. Add support for ACPI _RST method support during reset
> 3. Make reset driver a requirement by default with an optional
>    kernel command line override

Looks nice, thanks for rewriting this!

For future submissions, it would help to have a list of changes
compared to the previous versions a the patch set in the cover
letter to help reviewers, but this time my memory was still fresh
enough.

	Arnd


From javier at osg.samsung.com  Tue May  3 13:27:16 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue,  3 May 2016 16:27:16 -0400
Subject: [PATCH 1/3] [media] s5p-mfc: Set device name for reserved memory
 region devs
In-Reply-To: <1462307238-21815-1-git-send-email-javier@osg.samsung.com>
References: <1462307238-21815-1-git-send-email-javier@osg.samsung.com>
Message-ID: <1462307238-21815-2-git-send-email-javier@osg.samsung.com>

The devices don't have a name set, so makes dev_name() returns NULL which
makes harder to identify the devices that are causing issues, for example:

WARNING: CPU: 2 PID: 616 at drivers/base/core.c:251 device_release+0x8c/0x90
Device '(null)' does not have a release() function, it is broken and must be fixed.

And after setting the device name:

WARNING: CPU: 0 PID: 591 at drivers/base/core.c:251 device_release+0x8c/0x90
Device 's5p-mfc-l' does not have a release() function, it is broken and must be fixed.

Cc: <stable at vger.kernel.org>
Fixes: 6e83e6e25eb4 ("[media] s5p-mfc: Fix kernel warning on memory init")
Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

 drivers/media/platform/s5p-mfc/s5p_mfc.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index b16466fe35ee..8fc1fd4ee2ed 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1062,6 +1062,8 @@ static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
 		mfc_err("Not enough memory\n");
 		return -ENOMEM;
 	}
+
+	dev_set_name(dev->mem_dev_l, "%s", "s5p-mfc-l");
 	device_initialize(dev->mem_dev_l);
 	of_property_read_u32_array(dev->plat_dev->dev.of_node,
 			"samsung,mfc-l", mem_info, 2);
@@ -1079,6 +1081,8 @@ static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
 		mfc_err("Not enough memory\n");
 		return -ENOMEM;
 	}
+
+	dev_set_name(dev->mem_dev_r, "%s", "s5p-mfc-r");
 	device_initialize(dev->mem_dev_r);
 	of_property_read_u32_array(dev->plat_dev->dev.of_node,
 			"samsung,mfc-r", mem_info, 2);
-- 
2.5.5



From javier at osg.samsung.com  Tue May  3 13:27:15 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue,  3 May 2016 16:27:15 -0400
Subject: [PATCH 0/3] [media] s5p-mfc: Fixes for issues when module is removed
Message-ID: <1462307238-21815-1-git-send-email-javier@osg.samsung.com>

Hello,

This patch series fixes some issues that I noticed when trying to remove
the s5p-mfc driver when built as a module.

Some of these issues will be fixed once Marek's patches to convert the
custom memory region reservation code is replaced by a generic one that
supports named memory region reservation [0]. But the fixes are trivial
so we can fix the current code until his rework patch lands.

[0]: https://patchwork.linuxtv.org/patch/32287/

Best regards,
Javier


Javier Martinez Canillas (3):
  [media] s5p-mfc: Set device name for reserved memory region devs
  [media] s5p-mfc: Add release callback for memory region devs
  [media] s5p-mfc: Fix race between s5p_mfc_probe() and s5p_mfc_open()

 drivers/media/platform/s5p-mfc/s5p_mfc.c | 50 ++++++++++++++++++++------------
 1 file changed, 32 insertions(+), 18 deletions(-)

-- 
2.5.5



From javier at osg.samsung.com  Tue May  3 13:27:17 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue,  3 May 2016 16:27:17 -0400
Subject: [PATCH 2/3] [media] s5p-mfc: Add release callback for memory region
 devs
In-Reply-To: <1462307238-21815-1-git-send-email-javier@osg.samsung.com>
References: <1462307238-21815-1-git-send-email-javier@osg.samsung.com>
Message-ID: <1462307238-21815-3-git-send-email-javier@osg.samsung.com>

When s5p_mfc_remove() calls put_device() for the reserved memory region
devs, the driver core warns that the dev doesn't have a release callback:

WARNING: CPU: 0 PID: 591 at drivers/base/core.c:251 device_release+0x8c/0x90
Device 's5p-mfc-l' does not have a release() function, it is broken and must be fixed.

Also, the declared DMA memory using dma_declare_coherent_memory() isn't
relased so add a dev .release that calls dma_release_declared_memory().

Cc: <stable at vger.kernel.org>
Fixes: 6e83e6e25eb4 ("[media] s5p-mfc: Fix kernel warning on memory init")
Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

 drivers/media/platform/s5p-mfc/s5p_mfc.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 8fc1fd4ee2ed..beb4fd5bd326 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1050,6 +1050,11 @@ static int match_child(struct device *dev, void *data)
 	return !strcmp(dev_name(dev), (char *)data);
 }
 
+static void s5p_mfc_memdev_release(struct device *dev)
+{
+	dma_release_declared_memory(dev);
+}
+
 static void *mfc_get_drv_data(struct platform_device *pdev);
 
 static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
@@ -1064,6 +1069,7 @@ static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
 	}
 
 	dev_set_name(dev->mem_dev_l, "%s", "s5p-mfc-l");
+	dev->mem_dev_l->release = s5p_mfc_memdev_release;
 	device_initialize(dev->mem_dev_l);
 	of_property_read_u32_array(dev->plat_dev->dev.of_node,
 			"samsung,mfc-l", mem_info, 2);
@@ -1083,6 +1089,7 @@ static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
 	}
 
 	dev_set_name(dev->mem_dev_r, "%s", "s5p-mfc-r");
+	dev->mem_dev_r->release = s5p_mfc_memdev_release;
 	device_initialize(dev->mem_dev_r);
 	of_property_read_u32_array(dev->plat_dev->dev.of_node,
 			"samsung,mfc-r", mem_info, 2);
-- 
2.5.5



From javier at osg.samsung.com  Tue May  3 13:27:18 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue,  3 May 2016 16:27:18 -0400
Subject: [PATCH 3/3] [media] s5p-mfc: Fix race between s5p_mfc_probe() and
 s5p_mfc_open()
In-Reply-To: <1462307238-21815-1-git-send-email-javier@osg.samsung.com>
References: <1462307238-21815-1-git-send-email-javier@osg.samsung.com>
Message-ID: <1462307238-21815-4-git-send-email-javier@osg.samsung.com>

The s5p_mfc_probe() function registers the video devices before all the
resources needed by s5p_mfc_open() are correctly initalized.

So if s5p_mfc_open() function is called before s5p_mfc_probe() finishes
(since the video dev is already registered), a NULL pointer dereference
will happen due s5p_mfc_open() accessing uninitialized vars such as the
struct s5p_mfc_dev .watchdog_timer and .mfc_ops fields.

An example is following BUG caused by add_timer() getting a NULL pointer:

[   45.765374] kernel BUG at kernel/time/timer.c:790!
[   45.765381] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM
...
[   45.766149] [<c016fdf4>] (mod_timer) from [<bf181d18>] (s5p_mfc_open+0x274/0x4d4 [s5p_mfc])
[   45.766416] [<bf181d18>] (s5p_mfc_open [s5p_mfc]) from [<bf0214a0>] (v4l2_open+0x9c/0x100 [videodev])
[   45.766547] [<bf0214a0>] (v4l2_open [videodev]) from [<c01e355c>] (chrdev_open+0x9c/0x178)
[   45.766575] [<c01e355c>] (chrdev_open) from [<c01dceb4>] (do_dentry_open+0x1e0/0x300)
[   45.766595] [<c01dceb4>] (do_dentry_open) from [<c01ec2f0>] (path_openat+0x800/0x10d4)
[   45.766610] [<c01ec2f0>] (path_openat) from [<c01ed8b8>] (do_filp_open+0x5c/0xc0)
[   45.766624] [<c01ed8b8>] (do_filp_open) from [<c01de218>] (do_sys_open+0x10c/0x1bc)
[   45.766642] [<c01de218>] (do_sys_open) from [<c01078c0>] (ret_fast_syscall+0x0/0x3c)
[   45.766655] Code: eaffffe3 e3a00001 e28dd008 e8bd81f0 (e7f001f2)

Fix it by registering the video devs as the last step in s5p_mfc_probe().

Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

 drivers/media/platform/s5p-mfc/s5p_mfc.c | 39 +++++++++++++++++---------------
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index beb4fd5bd326..501d822cad6b 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1212,14 +1212,6 @@ static int s5p_mfc_probe(struct platform_device *pdev)
 	vfd->vfl_dir	= VFL_DIR_M2M;
 	snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME);
 	dev->vfd_dec	= vfd;
-	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
-	if (ret) {
-		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
-		video_device_release(vfd);
-		goto err_dec_reg;
-	}
-	v4l2_info(&dev->v4l2_dev,
-		  "decoder registered as /dev/video%d\n", vfd->num);
 	video_set_drvdata(vfd, dev);
 
 	/* encoder */
@@ -1237,14 +1229,6 @@ static int s5p_mfc_probe(struct platform_device *pdev)
 	vfd->vfl_dir	= VFL_DIR_M2M;
 	snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
 	dev->vfd_enc	= vfd;
-	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
-	if (ret) {
-		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
-		video_device_release(vfd);
-		goto err_enc_reg;
-	}
-	v4l2_info(&dev->v4l2_dev,
-		  "encoder registered as /dev/video%d\n", vfd->num);
 	video_set_drvdata(vfd, dev);
 	platform_set_drvdata(pdev, dev);
 
@@ -1261,15 +1245,34 @@ static int s5p_mfc_probe(struct platform_device *pdev)
 	s5p_mfc_init_hw_cmds(dev);
 	s5p_mfc_init_regs(dev);
 
+	/* Register decoder and encoder */
+	ret = video_register_device(dev->vfd_dec, VFL_TYPE_GRABBER, 0);
+	if (ret) {
+		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+		video_device_release(dev->vfd_dec);
+		goto err_dec_reg;
+	}
+	v4l2_info(&dev->v4l2_dev,
+		  "decoder registered as /dev/video%d\n", dev->vfd_dec->num);
+
+	ret = video_register_device(dev->vfd_enc, VFL_TYPE_GRABBER, 0);
+	if (ret) {
+		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+		video_device_release(dev->vfd_enc);
+		goto err_enc_reg;
+	}
+	v4l2_info(&dev->v4l2_dev,
+		  "encoder registered as /dev/video%d\n", dev->vfd_enc->num);
+
 	pr_debug("%s--\n", __func__);
 	return 0;
 
 /* Deinit MFC if probe had failed */
 err_enc_reg:
-	video_device_release(dev->vfd_enc);
-err_enc_alloc:
 	video_unregister_device(dev->vfd_dec);
 err_dec_reg:
+	video_device_release(dev->vfd_enc);
+err_enc_alloc:
 	video_device_release(dev->vfd_dec);
 err_dec_alloc:
 	v4l2_device_unregister(&dev->v4l2_dev);
-- 
2.5.5



From linux at arm.linux.org.uk  Tue May  3 13:44:19 2016
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Tue, 3 May 2016 21:44:19 +0100
Subject: [PATCH v2 0/3] ARM: nommu: R-class fixes
In-Reply-To: <5728806F.7000208@arm.com>
References: <1461862316-9877-1-git-send-email-vladimir.murzin@arm.com>
 <57287BD9.6090907@arm.com>
 <20160503103237.GN19428@n2100.arm.linux.org.uk>
 <5728806F.7000208@arm.com>
Message-ID: <20160503204419.GP19428@n2100.arm.linux.org.uk>

On Tue, May 03, 2016 at 11:41:51AM +0100, Vladimir Murzin wrote:
> On 03/05/16 11:32, Russell King - ARM Linux wrote:
> > On Tue, May 03, 2016 at 11:22:17AM +0100, Vladimir Murzin wrote:
> >> On 28/04/16 17:51, Vladimir Murzin wrote:
> >>> Small set of fixes discovered with R-class cores.
> >>>
> >>> Jean-Philippe Brucker (2):
> >>>   ARM: nommu: fix PMSAv7 setup
> >>>   ARM: nommu: change memory reserve for the vectors
> >>>
> >>> Vladimir Murzin (1):
> >>>   ARM: domain: move {set,get}_domain under config guard
> >>>
> >>>  arch/arm/include/asm/domain.h |   11 +++++++++++
> >>>  arch/arm/kernel/head-nommu.S  |    2 +-
> >>>  arch/arm/mm/nommu.c           |   15 ++++++++-------
> >>>  3 files changed, 20 insertions(+), 8 deletions(-)
> >>>
> >>
> >> Russell, any objection to get it into patch tracker?
> > 
> > I've not had any chance to look at them yet - last weekend, I was away
> > from Thursday through until late Tuesday, then I spent most of Wednesday
> > and Thursday catching up.  Friday I was able to look at some stuff, and
> > then I've spent the bank holiday weekend digging out laurels in the front
> > garden.  I've only just today got back to looking at some kernel stuff.
> > 
> > So really, I've only had two days in the last week and a half to look at
> > anything.
> > 
> > Please wait a little while longer.  Thanks.
> 
> Thanks for prompt reply! I wasn't aware you've been off, patches can wait.

Thanks for waiting, I've now looked through them and they look fine to me.

Please put them in the patch system, thanks.

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From okaya at codeaurora.org  Tue May  3 13:46:29 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Tue, 3 May 2016 16:46:29 -0400
Subject: [PATCH V4 0/2] vfio, platform: add ACPI support
In-Reply-To: <3322250.xDEDujoeAM@wuerfel>
References: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>
 <3322250.xDEDujoeAM@wuerfel>
Message-ID: <57290E25.7010501@codeaurora.org>

On 5/3/2016 4:12 PM, Arnd Bergmann wrote:
> On Sunday 01 May 2016 17:07:50 Sinan Kaya wrote:
>> The patchset makes three different changes.
>> 1. Add support for probing ACPI platform devices.
>> 2. Add support for ACPI _RST method support during reset
>> 3. Make reset driver a requirement by default with an optional
>>    kernel command line override
> 
> Looks nice, thanks for rewriting this!
> 
> For future submissions, it would help to have a list of changes
> compared to the previous versions a the patch set in the cover
> letter to help reviewers, but this time my memory was still fresh
> enough.
> 
> 	Arnd
> 

Sure, will do. I asked Rafael to review the ACPI code. 

+		ret = vfio_platform_call_reset(vdev);

This is the only problem I'm seeing in the code. I tested the ACPI path only. 
I'm wondering if Eric could test the device tree version.

+		if (ret)
+			goto err_irq;
 
I'll get rid of this line on the first patch and move it to second
patch along with reset_required check.

-- 
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


From peter at hurleysoftware.com  Tue May  3 14:01:51 2016
From: peter at hurleysoftware.com (Peter Hurley)
Date: Tue, 3 May 2016 14:01:51 -0700
Subject: Bunch of serial warnings in next at least with omap-serial
In-Reply-To: <20160503203930.GQ5995@atomide.com>
References: <20160503203930.GQ5995@atomide.com>
Message-ID: <572911BF.8000803@hurleysoftware.com>

Hi Tony,

On 05/03/2016 01:39 PM, Tony Lindgren wrote:
> Hi Peter,
> 
> Looks like probably commit 4047b37122d1 ("serial: core: Prevent unsafe
> uart port access, part 1") in Linux next causes tons of warnings with at
> least omap-serial. It does not revert cleanly I have not tested with that
> reverted. Any ideas? Dmesg output of the errors below.

Thanks for the report.
Patch below should fix that.

--- >% ---
Subject: [PATCH] serial: core: Fix port mutex assert if lockdep disabled

commit 4047b37122d1 ("serial: core: Prevent unsafe uart port access,
part 1") added lockdep assertion for port mutex but fails to check
if debug_locks has disabled lockdep (so lock state is no longer
reliable).

Use lockdep_assert_held() instead, which properly checks lockdep
state as well.

Reported-by: Tony Lindgren <tony at atomide.com>
Signed-off-by: Peter Hurley <peter at hurleysoftware.com>
---
 drivers/tty/serial/serial_core.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 0e66923..b88a054 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -95,9 +95,7 @@ static inline void uart_port_deref(struct uart_port *uport)
 
 static inline struct uart_port *uart_port_check(struct uart_state *state)
 {
-#ifdef CONFIG_LOCKDEP
-	WARN_ON(!lockdep_is_held(&state->port.mutex));
-#endif
+	lockdep_assert_held(&state->port.mutex);
 	return state->uart_port;
 }
 
-- 
2.8.2




From dev at blino.org  Tue May  3 14:35:45 2016
From: dev at blino.org (Olivier Blin)
Date: Tue, 03 May 2016 23:35:45 +0200
Subject: [PATCH v5] ARM: bcm2835: dt: Add the ethernet to the device trees
In-Reply-To: <1462172811-24206-1-git-send-email-lkundrak@v3.sk> (Lubomir
 Rintel's message of "Mon, 2 May 2016 09:06:51 +0200")
References: <1462172811-24206-1-git-send-email-lkundrak@v3.sk>
Message-ID: <m3lh3qrfim.fsf@euphor.blino.org>

Lubomir Rintel <lkundrak at v3.sk> writes:

> The hub and the ethernet in its port 1 are hardwired on the board.
>
> Compared to the adapters that can be plugged into the USB ports, this
> one has no serial EEPROM to store its MAC. Nevertheless, the Raspberry Pi
> has the MAC address for this adapter in its ROM, accessible from its
> firmware.
>
> U-Boot can read out the address and set the local-mac-address property of the
> node with "ethernet" alias. Let's add the node so that U-Boot can do its
> business.
>
> Model B rev2 and Model B+ entries were verified by me, the hierarchy and
> pid/vid pair for the Version 2 was provided by Peter Chen. Original
> Model B is a blind shot, though very likely correct.
>
> Signed-off-by: Lubomir Rintel <lkundrak at v3.sk>
> Acked-by: Stephen Warren <swarren at wwwdotorg.org>

Tested-by: Olivier Blin <dev at blino.org>

Though, I still need the following patch for this DT patch to be useful:
net/smscx5xx: use the device tree for mac address

Thanks for the update Lubomir

-- 
Olivier Blin - blino


From cov at codeaurora.org  Tue May  3 14:37:25 2016
From: cov at codeaurora.org (Christopher Covington)
Date: Tue, 3 May 2016 17:37:25 -0400
Subject: VDSO unmap and remap support for additional architectures
In-Reply-To: <572367B7.6030105@virtuozzo.com>
References: <20151202121918.GA4523@arm.com>
 <1461856737-17071-1-git-send-email-cov@codeaurora.org>
 <2ce7203f-305c-6edf-0ef9-448c141cb103@kernel.org>
 <57236003.5060804@codeaurora.org> <572367B7.6030105@virtuozzo.com>
Message-ID: <57291A15.8010105@codeaurora.org>

On 04/29/2016 09:55 AM, Dmitry Safonov wrote:
> On 04/29/2016 04:22 PM, Christopher Covington wrote:
>> On 04/28/2016 02:53 PM, Andy Lutomirski wrote:
>>> Also, at some point, possibly quite soon, x86 will want a way for
>>> user code to ask the kernel to map a specific vdso variant at a specific
>>> address. Could we perhaps add a new pair of syscalls:
>>>
>>> struct vdso_info {
>>>      unsigned long space_needed_before;
>>>      unsigned long space_needed_after;
>>>      unsigned long alignment;
>>> };
>>>
>>> long vdso_get_info(unsigned int vdso_type, struct vdso_info *info);
>>>
>>> long vdso_remap(unsigned int vdso_type, unsigned long addr, unsigned
>>> int flags);
>>>
>>> #define VDSO_X86_I386 0
>>> #define VDSO_X86_64 1
>>> #define VDSO_X86_X32 2
>>> // etc.
>>>
>>> vdso_remap will map the vdso of the chosen type such at
>>> AT_SYSINFO_EHDR lines up with addr. It will use up to
>>> space_needed_before bytes before that address and space_needed_after
>>> after than address. It will also unmap the old vdso (or maybe only do
>>> that if some flag is set).
>>>
>>> On x86, mremap is *not* sufficient for everything that's needed,
>>> because some programs will need to change the vdso type.
>> I don't I understand. Why can't people just exec() the ELF type that
>> corresponds to the VDSO they want?
> 
> I may say about my needs in it: to not lose all the existing
> information in application.
> Imagine you're restoring a container with 64-bit and 32-bit
> applications (in compatible mode). So you need somehow
> switch vdso type in restorer for a 32-bit application.
> Yes, you may exec() and then - all already restored application
> properties will got lost. You will need to transpher information
> about mappings, make protocol between restorer binary
> and main criu application, finally you'll end up with some
> really much more difficult architecture than it is now.
> And it'll be slower.

Perhaps a more modest exec based strategy would be for x86_64 criu to
handle all of the x86_64 restores as usual but exec i386 and/or x32 criu
service daemons and use them for restoring applications needing those ABIs.

Regards,
Christopher Covington

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


From f.fainelli at gmail.com  Tue May  3 14:45:40 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Tue, 3 May 2016 14:45:40 -0700
Subject: [PATCH 0/3] Fixup Broadcom CPU enable method
In-Reply-To: <1461866399-1725-1-git-send-email-chris.brand@broadcom.com>
References: <1461866399-1725-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <57291C04.9010300@gmail.com>

On 28/04/16 10:59, Chris Brand wrote:
> This is preparation for supporting the quad-core BCM23550 chip.
> 
> Documentation/devicetree/bindings/arm/cpus.txt states that "enable-method"
> should be a property of the "cpu" node rather than the "cpus" node.
> 
> Commit 84320e1a635fcf90cff4185f029ce9e31bf1d4a7
> ("ARM: BCM: Clean up SMP support for Broadcom Kona") moved the 
> "secondary-boot-reg" property from the "cpus" node to the individual "cpu"
> nodes but negelected to actually support multiple "secondary-boot-reg"
> properties.
> 
> This patchset moves the enable-method property to the correct place,
> adds the missing enable-method to the binding documentation, and actually
> supports setting the "enable-method" property on multiple CPU nodes.
> 
> Without this change, "secondary-boot-reg" on even-numbered CPUs is ignored,
> and the value specified on the last odd-numbered CPU to be processed
> overrides any earlier values.
> 
> Behaviour is slightly changed by this patchset, in that the
> "secondary-boot-reg" property is only examined when the CPU is being enabled.
> This means that the omission of that property will be reported slightly later,
> or never if the CPU in question is never brought online. It also means that
> the omission in one CPU has no effect on other CPUs, whereas previously
> omitting it from one CPU would force the system into single-core mode.

Series applied to devicetree/next, thanks Chris!
-- 
Florian


From gregkh at linuxfoundation.org  Tue May  3 14:58:20 2016
From: gregkh at linuxfoundation.org (Greg KH)
Date: Tue, 3 May 2016 14:58:20 -0700
Subject: [PATCH 01/27] coresight: no need to do the forced type conversion
In-Reply-To: <1462296841-12327-2-git-send-email-mathieu.poirier@linaro.org>
References: <1462296841-12327-1-git-send-email-mathieu.poirier@linaro.org>
 <1462296841-12327-2-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <20160503215820.GA21470@kroah.com>

On Tue, May 03, 2016 at 11:33:35AM -0600, Mathieu Poirier wrote:
> From: lipengcheng <lipengcheng8 at huawei.com>

That name, doesn't match:

> 
> activated and enable are already unsigned type,
> no need to change them to unsigned.
> 
> Signed-off-by: Li Pengcheng <lipengcheng8 at huawei.com>

That name :(

Please be more careful here.

I'll edit this by hand this time :(



From tony at atomide.com  Tue May  3 14:58:21 2016
From: tony at atomide.com (Tony Lindgren)
Date: Tue, 3 May 2016 14:58:21 -0700
Subject: Bunch of serial warnings in next at least with omap-serial
In-Reply-To: <572911BF.8000803@hurleysoftware.com>
References: <20160503203930.GQ5995@atomide.com>
 <572911BF.8000803@hurleysoftware.com>
Message-ID: <20160503215821.GR5995@atomide.com>

* Peter Hurley <peter at hurleysoftware.com> [160503 14:03]:
> Hi Tony,
> 
> On 05/03/2016 01:39 PM, Tony Lindgren wrote:
> > Hi Peter,
> > 
> > Looks like probably commit 4047b37122d1 ("serial: core: Prevent unsafe
> > uart port access, part 1") in Linux next causes tons of warnings with at
> > least omap-serial. It does not revert cleanly I have not tested with that
> > reverted. Any ideas? Dmesg output of the errors below.
> 
> Thanks for the report.
> Patch below should fix that.

Yes thanks that fixes it:

Tested-by: Tony Lindgren <tony at atomide.com>


From thomas.hanson at linaro.org  Tue May  3 15:22:37 2016
From: thomas.hanson at linaro.org (Tom Hanson)
Date: Tue, 3 May 2016 16:22:37 -0600
Subject: [PATCH v2 07/54] KVM: arm/arm64: vgic: Remove irq_phys_map from
 interface
In-Reply-To: <1461861973-26464-8-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-8-git-send-email-andre.przywara@arm.com>
Message-ID: <572924AD.9050902@linaro.org>

On 04/28/2016 10:45 AM, Andre Przywara wrote:
...
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index 3a74b17..9475000 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -333,10 +333,10 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
...
> +	ret = kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
> +	if (ret)
> +		return ret;
>
>   	return 0;
>   }

This isn't wrong, but it is overly complicated.  I'd recommend either:
     ret = kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
     return ret;
OR
     return kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);



From nm at ti.com  Tue May  3 16:17:38 2016
From: nm at ti.com (Nishanth Menon)
Date: Tue, 3 May 2016 18:17:38 -0500
Subject: [PATCH v2 2/3] ARM: DRA7x: dts: Update the OSC_32K_CLK frequency
In-Reply-To: <5728E936.2010503@ti.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
 <1462209123-7332-3-git-send-email-Linux.HWI@garmin.com>
 <57285E66.2000708@ti.com> <5728A81F.4050906@garmin.com>
 <20160503164323.GN5995@atomide.com> <5728E0BC.3080509@ti.com>
 <5728E495.4010502@garmin.com> <5728E936.2010503@ti.com>
Message-ID: <57293192.7060802@ti.com>

On 05/03/2016 01:08 PM, Tero Kristo wrote:
> On 03/05/16 20:49, J.D. Schroeder wrote:
>> On 05/03/2016 12:32 PM, Tero Kristo wrote:
>>> Personally I would not recommend using this clock for any timing sensitive
>>> applications. May I ask why you are interested in the exact clock rate of this
>>> clock anyway?
>>
>> I'm not interested in using this clock and I'm not sure how anyone would use
>> this clock outside of the processor. See the inline comment that is part of
>> the change and the commit message for the change. There is no hint in my
>> change that this is an exact clock rate. It is a clarifying change to help
>> others avoid using this clock as a 32 kHz clock (which the current clock name
>> and frequency imply) and it more accurately represents the actual hardware
>> behavior.
>>
> 
> Imo, if you want to clarify things up, the whole secure_32k_ck should be 
> removed from linux kernel.

This is actually the RC oscillator clock[1] which also happens to
source the secure_32k_clk. Jay is right that this is not an accurate
32k clock, however the actual range of this internal clock source is
pretty wide (I am trying to get that information into public domain
TRM - but that will take some time - since this patch just started the
internal thread on the topic). since it is infact an accurate clock
source from inside the SoC, how do we model that (a clock with a
frequency range with nominal frequency expected to be around 32k - but
not exactly 32k?). I think having a rename makes sense and modelling
it as an in-accurate clock source is probably the need.

[1] Search for "On-die 32K RC Osc" in http://www.ti.com/lit/pdf/spruhz6
-- 
Regards,
Nishanth Menon


From thomas.hanson at linaro.org  Tue May  3 16:46:12 2016
From: thomas.hanson at linaro.org (Tom Hanson)
Date: Tue, 3 May 2016 17:46:12 -0600
Subject: [PATCH v2 14/54] KVM: arm/arm64: vgic-new: Implement virtual IRQ
 injection
In-Reply-To: <1461861973-26464-15-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-15-git-send-email-andre.przywara@arm.com>
Message-ID: <57293844.1060802@linaro.org>

On 04/28/2016 10:45 AM, Andre Przywara wrote:
...
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index fb45537..92b78a0 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -19,8 +19,31 @@
...  
> +/*
> + * Locking order is always:
> + *   vgic_cpu->ap_list_lock
> + *     vgic_irq->irq_lock
> + *
> + * (that is, always take the ap_list_lock before the struct vgic_irq lock).
> + *
> + * When taking more than one ap_list_lock at the same time, always take the
> + * lowest numbered VCPU's ap_list_lock first, so:
> + *   vcpuX->vcpu_id < vcpuY->vcpu_id:
> + *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
> + *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
> + */

The code would be safer and easier to maintain in the long run if there were functions provided which implement these 2 rules.  Something along the line of:

   void vgic_lock_aplist_irq(spinlock_t ap_list_lock, spinlock_t irq_lock){
       spin_lock(ap_list_lock);
       spin_lock(irq_lock);
   }

and  (borrowing from patch 16/54):

   void vgic_lock_cpu_aplist_pair(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2){
       struct kvm_vcpu *vcpuA, *vcpuB;
       /*
        * Ensure locking order by always locking the smallest
        * ID first.
        */
      if (vcpu1->vcpu_id < vcpu2->vcpu_id) {
           vcpuA = vcpu1;
           vcpuB = vcpu2;
       } else {
           vcpuA = vcpu2;
           vcpuB = vcpu1;
       }

       spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
       spin_lock(&vcpuB->arch.vgic_cpu.ap_list_lock);
   }

With, of course the matching unlock functions.

Then, as long as new code calls the correct function, the order is always correct.  Easy to write, easy to review.  And beats the heck out of chasing a deadlock at some point in the future.


From ray.jui at broadcom.com  Tue May  3 16:47:24 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Tue,  3 May 2016 16:47:24 -0700
Subject: [PATCH 1/2] dt-bindings: arm, gic: Indtroduce optional property 'arm,
 msi-offset-spi' for gicv2m
In-Reply-To: <1462319245-32532-1-git-send-email-ray.jui@broadcom.com>
References: <1462319245-32532-1-git-send-email-ray.jui@broadcom.com>
Message-ID: <1462319245-32532-2-git-send-email-ray.jui@broadcom.com>

Update the GICv2m binding document by adding an optional property
'arm,msi-offset-spi'.

Some implementations of gicv2m have an erratum where the MSI data is
the SPI number subtracted by an offset. This is required for the
correct MSI interrupt to be triggered.

Signed-off-by: Ray Jui <ray.jui at broadcom.com>
---
 Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
index 793c20f..550960f 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
@@ -140,6 +140,12 @@ Optional properties:
   		      value, this property should contain the number of
 		      SPIs assigned to the frame, overriding the HW value.
 
+- arm,msi-offset-spi: Some implementations of gicv2m have an erratum where
+		      the MSI data is the SPI number subtracted by an offset.
+		      This is required for the correct MSI interrupt to be
+		      triggered. This property should contain the required
+		      offset.
+
 Example:
 
 	interrupt-controller at e1101000 {
-- 
2.1.4



From ray.jui at broadcom.com  Tue May  3 16:47:23 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Tue,  3 May 2016 16:47:23 -0700
Subject: [PATCH 0/2] Add DT based gicv2m spi offset support
Message-ID: <1462319245-32532-1-git-send-email-ray.jui@broadcom.com>

Alex Barba <alex.barba at broadcom.com> discovered Broadcom NS2 GICv2m
implementation has an erratum where the MSI data needs to be the SPI number
subtracted by an offset of 32, for the correct MSI interrupt to be triggered.
    
We are aware that APM X-Gene GICv2m has a similar erratum where the MSI data
needs to be the offset from the spi_start. While APM's workaround is triggered
based on readings from the MSI_IIDR register, this patch series contains a more
general solution by allowing this offset to be specified with an optional DT
property 'arm,msi-offset-spi'. This patch series also maintains compatibility
with existing APM platforms

Kindly let us know if it's preferred for Broadcom's workaround to be also based
on the readings from the MSI_IIDR register.

Patch series is developed based on Linux v4.6-rc1 and available at:
https://github.com/Broadcom/arm64-linux/tree/gicv2m-iproc-v1

Ray Jui (2):
  dt-bindings: arm,gic: Indtroduce optional property
    'arm,msi-offset-spi'     for gicv2m
  irqchip/gic-v2m: Add workaround for Broadcom NS2 GICv2m erratum

 .../bindings/interrupt-controller/arm,gic.txt      |  6 ++++
 drivers/irqchip/irq-gic-v2m.c                      | 35 ++++++++++++++++++----
 2 files changed, 35 insertions(+), 6 deletions(-)

-- 
2.1.4



From ray.jui at broadcom.com  Tue May  3 16:47:25 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Tue,  3 May 2016 16:47:25 -0700
Subject: [PATCH 2/2] irqchip/gic-v2m: Add workaround for Broadcom NS2 GICv2m
 erratum
In-Reply-To: <1462319245-32532-1-git-send-email-ray.jui@broadcom.com>
References: <1462319245-32532-1-git-send-email-ray.jui@broadcom.com>
Message-ID: <1462319245-32532-3-git-send-email-ray.jui@broadcom.com>

Alex Barba <alex.barba at broadcom.com> discovered Broadcom NS2 GICv2m
implementation has an erratum where the MSI data needs to be the SPI
number subtracted by an offset of 32, for the correct MSI interrupt to
be triggered.

We are aware that APM X-Gene GICv2m has a similar erratum where the
MSI data needs to be the offset from the spi_start. While APM's workaround
is triggered based on readings from the MSI_IIDR register, this patch
contains a more general solution by allowing this offset to be
specified with an optional DT property 'arm,msi-offset-spi'. This patch
also maintains compatibility with existing APM platforms

Reported-by: Alex Barba <alex.barba at broadcom.com>
Signed-off-by: Ray Jui <ray.jui at broadcom.com>
Reviewed-by: Alex Barba <alex.barba at broadcom.com>
---
 drivers/irqchip/irq-gic-v2m.c | 35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 28f047c..7f58b87 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -62,6 +62,7 @@ struct v2m_data {
 	void __iomem *base;	/* GICv2m virt address */
 	u32 spi_start;		/* The SPI number that MSIs start */
 	u32 nr_spis;		/* The number of SPIs for MSIs */
+	u32 spi_offset;		/* offset to be subtracted from SPI number */
 	unsigned long *bm;	/* MSI vector bitmap */
 	u32 flags;		/* v2m flags for specific implementation */
 };
@@ -102,7 +103,7 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 	msg->data = data->hwirq;
 
 	if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET)
-		msg->data -= v2m->spi_start;
+		msg->data -= v2m->spi_offset;
 }
 
 static struct irq_chip gicv2m_irq_chip = {
@@ -294,7 +295,7 @@ static int gicv2m_allocate_domains(struct irq_domain *parent)
 }
 
 static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
-				  u32 spi_start, u32 nr_spis,
+				  u32 spi_start, u32 nr_spis, u32 spi_offset,
 				  struct resource *res)
 {
 	int ret;
@@ -341,8 +342,24 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
 	 * the MSI data is the absolute value within the range from
 	 * spi_start to (spi_start + num_spis).
 	 */
-	if (readl_relaxed(v2m->base + V2M_MSI_IIDR) == XGENE_GICV2M_MSI_IIDR)
+	if (readl_relaxed(v2m->base + V2M_MSI_IIDR) == XGENE_GICV2M_MSI_IIDR) {
 		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
+		v2m->spi_offset = v2m->spi_start;
+	}
+
+	/*
+	 * Various GICv2m implementations may require the MSI data to be the SPI
+	 * number subtracted by an offset, in order to trigger the correct MSI
+	 * interrupt. This offset can be different depending on how gicv2m is
+	 * integrated into an SoC.
+	 *
+	 * 'spi_offset' becomes non-zero here if optional DT property
+	 * 'arm,msi-offset-spi' is specified (with an non-zero offset)
+	 */
+	if (spi_offset) {
+		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
+		v2m->spi_offset = spi_offset;
+	}
 
 	v2m->bm = kzalloc(sizeof(long) * BITS_TO_LONGS(v2m->nr_spis),
 			  GFP_KERNEL);
@@ -378,7 +395,7 @@ static int __init gicv2m_of_init(struct fwnode_handle *parent_handle,
 
 	for (child = of_find_matching_node(node, gicv2m_device_id); child;
 	     child = of_find_matching_node(child, gicv2m_device_id)) {
-		u32 spi_start = 0, nr_spis = 0;
+		u32 spi_start = 0, nr_spis = 0, spi_offset = 0;
 		struct resource res;
 
 		if (!of_find_property(child, "msi-controller", NULL))
@@ -396,7 +413,13 @@ static int __init gicv2m_of_init(struct fwnode_handle *parent_handle,
 			pr_info("DT overriding V2M MSI_TYPER (base:%u, num:%u)\n",
 				spi_start, nr_spis);
 
-		ret = gicv2m_init_one(&child->fwnode, spi_start, nr_spis, &res);
+		if (!of_property_read_u32(child, "arm,msi-offset-spi",
+					  &spi_offset))
+			pr_info("DT configuring V2M spi offset:%u\n",
+				spi_offset);
+
+		ret = gicv2m_init_one(&child->fwnode, spi_start, nr_spis,
+				      spi_offset, &res);
 		if (ret) {
 			of_node_put(child);
 			break;
@@ -460,7 +483,7 @@ acpi_parse_madt_msi(struct acpi_subtable_header *header,
 		return -EINVAL;
 	}
 
-	ret = gicv2m_init_one(fwnode, spi_start, nr_spis, &res);
+	ret = gicv2m_init_one(fwnode, spi_start, nr_spis, 0, &res);
 	if (ret)
 		irq_domain_free_fwnode(fwnode);
 
-- 
2.1.4



From festevam at gmail.com  Tue May  3 18:12:00 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Tue,  3 May 2016 22:12:00 -0300
Subject: [PATCH 1/2] ARM: dts: imx6ul: Specify the SAI index
Message-ID: <1462324321-11060-1-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam at nxp.com>

Introduce the "sai-index" property to indicate the index of the SAI port.

This is useful for enabling the SAI_MCLK output as we need to write
to bits 19, 20 and 21 of register GPR1 for enabling SAI1, SAI2 and SAI3,
respectively.

Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
---
 arch/arm/boot/dts/imx6ul.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
index 4356b65..b11d5a8 100644
--- a/arch/arm/boot/dts/imx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul.dtsi
@@ -281,6 +281,7 @@
 					dmas = <&sdma 35 24 0>,
 					       <&sdma 36 24 0>;
 					dma-names = "rx", "tx";
+					sai-index = <1>;
 					status = "disabled";
 				};
 
@@ -296,6 +297,7 @@
 					dmas = <&sdma 37 24 0>,
 					       <&sdma 38 24 0>;
 					dma-names = "rx", "tx";
+					sai-index = <2>;
 					status = "disabled";
 				};
 
@@ -311,6 +313,7 @@
 					dmas = <&sdma 39 24 0>,
 					       <&sdma 40 24 0>;
 					dma-names = "rx", "tx";
+					sai-index = <3>;
 					status = "disabled";
 				};
 			};
-- 
1.9.1



From festevam at gmail.com  Tue May  3 18:12:01 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Tue,  3 May 2016 22:12:01 -0300
Subject: [PATCH 2/2] ARM: dts: imx6ul-14x14-evk: Enable SAI2_MCLK
In-Reply-To: <1462324321-11060-1-git-send-email-festevam@gmail.com>
References: <1462324321-11060-1-git-send-email-festevam@gmail.com>
Message-ID: <1462324321-11060-2-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam at nxp.com>

Pass the "gpr" and "fsl,sai-enable-mclk" to the sai2 node, so that
we can enable the SAI2_MCLK.

Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
---
 arch/arm/boot/dts/imx6ul-14x14-evk.dts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dts b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
index 668a729..21c66bb 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk.dts
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
@@ -146,6 +146,8 @@
 			  <&clks IMX6UL_CLK_SAI2>;
 	assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
 	assigned-clock-rates = <0>, <12288000>;
+	gpr = <&gpr>;
+	fsl,sai-enable-mclk;
 	status = "okay";
 };
 
-- 
1.9.1



From chunfeng.yun at mediatek.com  Tue May  3 18:21:13 2016
From: chunfeng.yun at mediatek.com (chunfeng yun)
Date: Wed, 4 May 2016 09:21:13 +0800
Subject: [PATCH] usb: xhci-mtk: fixup mouse wakeup failure during system
 suspend
In-Reply-To: <87mvo7fpuc.fsf@intel.com>
References: <1461204293-18243-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462261458.11651.7.camel@mhfsdcap03> <87vb2vfujq.fsf@intel.com>
 <1462266591.11651.34.camel@mhfsdcap03> <87mvo7fpuc.fsf@intel.com>
Message-ID: <1462324873.11651.57.camel@mhfsdcap03>

On Tue, 2016-05-03 at 12:33 +0300, Felipe Balbi wrote:
> Hi,
> 
> chunfeng yun <chunfeng.yun at mediatek.com> writes:
> >> chunfeng yun <chunfeng.yun at mediatek.com> writes:
> >> > On Thu, 2016-04-21 at 10:04 +0800, Chunfeng Yun wrote:
> >> >> Click mouse after xhci suspend completion but before system suspend
> >> >> completion, system will not be waken up by mouse if the duration of
> >> >> them is larger than 20ms which is the device UFP's resume signaling
> >> 
> >> what is "them" here ? The duration of what is longer than 20ms ?
> > They are "xhci suspend completion" and "system suspend completion";
> >
> > It's time duration
> 
> okay. So if xhci suspend takes longer than 20ms your SPM doesn't see a
> wakeup ?
It is not the time of xhci suspend consumed, but is the time of duration
from xhci suspend completion to system suspend completion(after BOOT-CPU
is turned off, SPM will be enabled to receive wakeup event)

> 
> >> >> lasted. Another reason is that the SPM is not enabled before system
> >> 
> >> what's SPM ?
> > It is System Power Management which is powered off when system is
> > running in normal mode, and is powered on when system enters suspend
> > mode. It is used to wakeup system when some wakeup sources, such as
> > bluetooth or powerkey etc, tigger wakeup event.
> 
> okay, thanks
> 
> >> >> suspend compeltion, this causes SPM also not notice the resume signal.
> >>            ^^^^^^^^^^
> >>            completion
> >> 
> >> >> So in order to reduce the duration less than 20ms, make use of
> >> >> syscore's suspend/resume interface.
> >> 
> >> no, this is the wrong approach
> > But it seems only one workable approach from software side
> 
> I wouldn't say that. It seems to me SPM should be enabled earlier.
Yes, but normally SPM should be enabled after all CPUS are turned off,
so it's difficult to do that, I mean enable SPM before turning off CPUS
> 
> >> >> Because the syscore runs on irq disabled context, and xhci's
> >> >> suspend/resume calls some sleeping functions, enable local irq
> >> >> and then disable it during suspend/resume. This may be not a problem,
> >> >> since only boot CPU is runing.
> >> 
> >> another problem :) calling local_irq_{enable,disable}() is an indication
> >> that something's wrong.
> > Oh!
> >
> > BTW: There will be warning logs if they are not called.
> 
> yeah, I got that :-) But it's still wrong to use
> local_irq_{enable,disable}() the way you're using them :-)
Yes

Thank you very much.
> 




From andrew at lunn.ch  Tue May  3 18:32:12 2016
From: andrew at lunn.ch (Andrew Lunn)
Date: Wed, 4 May 2016 03:32:12 +0200
Subject: [PATCH 02/12] eeprom: at24: remove nvmem regmap dependency
In-Reply-To: <20160502073254.GA2015@tetsubishi>
References: <1461526096-29584-1-git-send-email-srinivas.kandagatla@linaro.org>
 <1461526096-29584-3-git-send-email-srinivas.kandagatla@linaro.org>
 <20160502073254.GA2015@tetsubishi>
Message-ID: <20160504013212.GA7972@lunn.ch>

On Mon, May 02, 2016 at 09:32:54AM +0200, Wolfram Sang wrote:
> On Sun, Apr 24, 2016 at 08:28:06PM +0100, Srinivas Kandagatla wrote:
> > This patch moves to nvmem support in the driver to use callback instead
> > of regmap.
> > 
> > Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
> 
> Andrew, since you did the NVMEM implementation, could you have a look at
> this? That would be awesome. Thanks!
> 
> > ---
> >  drivers/misc/eeprom/Kconfig |   1 -
> >  drivers/misc/eeprom/at24.c  | 103 ++++++++++----------------------------------
> >  2 files changed, 22 insertions(+), 82 deletions(-)
> > 
> > diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
> > index cfc493c..2d70464 100644
> > --- a/drivers/misc/eeprom/Kconfig
> > +++ b/drivers/misc/eeprom/Kconfig
> > @@ -3,7 +3,6 @@ menu "EEPROM support"
> >  config EEPROM_AT24
> >  	tristate "I2C EEPROMs / RAMs / ROMs from most vendors"
> >  	depends on I2C && SYSFS
> > -	select REGMAP
> >  	select NVMEM
> >  	help
> >  	  Enable this driver to get read/write support to most I2C EEPROMs
> > diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
> > index 089d694..de550a6 100644
> > --- a/drivers/misc/eeprom/at24.c
> > +++ b/drivers/misc/eeprom/at24.c
> > @@ -23,7 +23,6 @@
> >  #include <linux/acpi.h>
> >  #include <linux/i2c.h>
> >  #include <linux/nvmem-provider.h>
> > -#include <linux/regmap.h>
> >  #include <linux/platform_data/at24.h>
> >  
> >  /*
> > @@ -69,7 +68,6 @@ struct at24_data {
> >  	unsigned write_max;
> >  	unsigned num_addresses;
> >  
> > -	struct regmap_config regmap_config;
> >  	struct nvmem_config nvmem_config;
> >  	struct nvmem_device *nvmem;
> >  
> > @@ -252,10 +250,10 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
> >  	return -ETIMEDOUT;
> >  }
> >  
> > -static ssize_t at24_read(struct at24_data *at24,
> > -		char *buf, loff_t off, size_t count)
> > +static int at24_read(void *priv, unsigned int off, void *val, size_t count)
> >  {
> > -	ssize_t retval = 0;
> > +	struct at24_data *at24 = priv;
> > +	char *buf = val;
> >  
> >  	if (unlikely(!count))
> >  		return count;
> > @@ -267,23 +265,21 @@ static ssize_t at24_read(struct at24_data *at24,
> >  	mutex_lock(&at24->lock);
> >  
> >  	while (count) {
> > -		ssize_t	status;
> > +		int	status;
> >  
> >  		status = at24_eeprom_read(at24, buf, off, count);

Since the patch replaces ssize_t with int here, it would also make
sense to do the same to at24_eeprom_read and at24_eeprom_write. Either
use ssize_t everywhere or nowhere.

      Andrew


From Nitin.Saxena at caviumnetworks.com  Tue May  3 19:12:30 2016
From: Nitin.Saxena at caviumnetworks.com (Saxena, Nitin)
Date: Wed, 4 May 2016 02:12:30 +0000
Subject: VFIO MSIX Query
In-Reply-To: <20160503140249.4edaf3cc@t450s.home>
References: <CAB995Mu0==PJ0iU4h_3oAMGo-VYDFrjOg_BO757M=PDWgMWtCw@mail.gmail.com>,
 <20160503140249.4edaf3cc@t450s.home>
Message-ID: <53EA6B5E-2D73-47C1-A912-1D05AB5D9E02@caviumnetworks.com>

Got it. Thanks Alex. I may have future queries as well on this. Will get back to you.

Thanks,
Nitin

> On 04-May-2016, at 01:33, Alex Williamson <alex.williamson at redhat.com> wrote:
> 
> Hi,
> 
> On Tue, 3 May 2016 23:56:38 +0530
> Nitin Saxena <nitin.lnx at gmail.com> wrote:
> 
>> Hi,
>> 
>> I am a newbie to VFIO framework and trying to use it for MSIX interrupt
>> handling in my userspace application. My userspace application is like
>> intel's dpdk.
>> 
>> My query is why vfio kernel code does not support msix masking/ unmasking
>> i.e VFIO_SET_ACTION_TRIGGER is not implemented in kernel vfio code for MSIX
>> but its present for legacy INTX?
> 
> I think you mean VFIO_IRQ_SET_ACTION_MASK and
> VFIO_IRQ_SET_ACTION_UNMASK are not implemented for MSI/X,
> VFIO_IRQ_SET_ACTION_TRIGGER is the only one that is implemented.  It
> mostly comes down to it hasn't been needed.  We would just need to
> verify that disable_irq() and enable_irq() do the right thing and
> enable the features through the existing VFIO API.  The reason we have
> these for INTx is that INTx is level triggered and we must mask the
> interrupt on the host while it's serviced by the user because the
> interrupt will continue to assert and we have no service guarantees
> from the user.  MSI/X is of course edge triggered, so doesn't have this
> problem.  The device would need to continue to re-assert the
> interrupt.  In cases like a QEMU user, we might want to continue to
> receive guest masked interrupts to QEMU for emulating the pending bits
> array, so even if we had VFIO masking support for these interrupts, QEMU
> probably would not use it.  If MSI/X masking is useful for you vs simply
> ignoring the eventfd, patches welcome.
> 
>> Another question since MSIX interrupt masking is absent in kernel who is
>> supposed to mask/unmask msix interrupt? does userspace needs to mask/unmask
>> interrupt after getting notified by eventfd. Is there any usecase where
>> MSIX handling is done via VFIO framework?
> 
> MSI/X is edge triggered and VFIO does not set the AUTOMASKED flag on
> them, so there is simply no masking of them at all aside from fully
> disabling them.  QEMU has full support for MSI/X through VFIO that you
> can use for reference.  Thanks,
> 
> Alex


From robh at kernel.org  Tue May  3 19:22:10 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 3 May 2016 21:22:10 -0500
Subject: [RFC v6 1/3] gpio: dt-bindings: add wd,mbl-gpio bindings
In-Reply-To: <103bf8fceb426a9c3b09641ea989955e3ec1c7d4.1462104492.git.chunkeey@googlemail.com>
References: <cover.1462104492.git.chunkeey@googlemail.com>
 <103bf8fceb426a9c3b09641ea989955e3ec1c7d4.1462104492.git.chunkeey@googlemail.com>
Message-ID: <20160504022210.GA9913@rob-hp-laptop>

On Sun, May 01, 2016 at 02:18:37PM +0200, Christian Lamparter wrote:
> This patch adds the device tree bindings for the Western Digital's
> MyBook Live memory-mapped GPIO controllers.
> 
> The gpios will be supported by gpio-mmio code of the
> GPIO generic library.
> 
> Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
> ---
>  .../devicetree/bindings/gpio/wd,mbl-gpio.txt       | 38 ++++++++++++++++++++++
>  1 file changed, 38 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
> 
> diff --git a/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
> new file mode 100644
> index 0000000..038c3a6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
> @@ -0,0 +1,38 @@
> +Bindings for the Western Digital's MyBook Live memory-mapped GPIO controllers.

Are these really product level GPIOs rather than some SOC's GPIOs 
(APM?)?

> +
> +The Western Digital MyBook Live has two memory-mapped GPIO controllers.
> +Both GPIO controller only have a single 8-bit data register, where GPIO
> +state can be read and/or written.
> +
> +Required properties:
> +	- compatible: should be "wd,mbl-gpio"
> +	- reg-names: must contain
> +		"dat" - data register
> +	- reg: address + size pairs describing the GPIO register sets;
> +		order must correspond with the order of entries in reg-names
> +	- #gpio-cells: must be set to 2. The first cell is the pin number and
> +			the second cell is used to specify the gpio polarity:
> +			0 = active high
> +			1 = active low
> +	- gpio-controller: Marks the device node as a gpio controller.
> +
> +Optional properties:
> +	- no-output: GPIOs are read-only.
> +
> +Examples:
> +	gpio0: gpio0 at e0000000 {
> +		compatible = "wd,mbl-gpio";
> +		reg-names = "dat";
> +		reg = <0xe0000000 0x1>;
> +		#gpio-cells = <2>;
> +		gpio-controller;
> +	};
> +
> +	gpio1: gpio1 at e0100000 {
> +		compatible = "wd,mbl-gpio";
> +		reg-names = "dat";
> +		reg = <0xe0100000 0x1>;
> +		#gpio-cells = <2>;
> +		gpio-controller;
> +		no-output;
> +	};
> -- 
> 2.8.1
> 


From robh at kernel.org  Tue May  3 19:24:37 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 3 May 2016 21:24:37 -0500
Subject: [PATCH V3 2/7] documentation: iommu: Add bindings for
 msm,iommu-v0 ip
In-Reply-To: <1462128875-20988-3-git-send-email-sricharan@codeaurora.org>
References: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
 <1462128875-20988-3-git-send-email-sricharan@codeaurora.org>
Message-ID: <20160504022437.GA4110@rob-hp-laptop>

On Mon, May 02, 2016 at 12:24:30AM +0530, Sricharan R wrote:
> The MSM IOMMU is an implementation compatible with the ARM VMSA short
> descriptor page tables. It provides address translation for bus masters outside
> of the CPU, each connected to the IOMMU through a port called micro-TLB.
> Adding the DT bindings for the same.
> 
> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> ---
>  .../devicetree/bindings/iommu/msm,iommu-v0.txt     | 62 ++++++++++++++++++++++
>  1 file changed, 62 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
> 
> diff --git a/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
> new file mode 100644
> index 0000000..63b4f96
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
> @@ -0,0 +1,62 @@
> +* MSM IOMMU
> +
> +The MSM IOMMU is an implementation compatible with the ARM VMSA short
> +descriptor page tables. It provides address translation for bus masters outside
> +of the CPU, each connected to the IOMMU through a port called micro-TLB.
> +
> +Required Properties:
> +
> +  - compatible: Must contain "msm,iommu-v0".

SOC specific compatible strings please.

> +  - reg: Base address and size of the IOMMU registers.
> +  - interrupts: Specifiers for the MMU fault interrupts. For instances that
> +    support secure mode two interrupts must be specified, for non-secure and
> +    secure mode, in that order. For instances that don't support secure mode a
> +    single interrupt must be specified.
> +  - #iommu-cells: The number of cells needed to specify the stream id. This
> +		  is always 1.
> +  - qcom,ncb:	  The total number of context banks in the IOMMU.
> +  - clocks	: List of clocks to be used during SMMU register access. See
> +		  Documentation/devicetree/bindings/clock/clock-bindings.txt
> +		  for information about the format. For each clock specified
> +		  here, there must be a corresponding entry in clock-names
> +		  (see below).
> +
> +  - clock-names	: List of clock names corresponding to the clocks specified in
> +		  the "clocks" property (above). See
> +		  Documentation/devicetree/bindings/clock/clock-bindings.txt
> +		  for more info.

You must define how many clocks, their order and their names.

> +
> +Each bus master connected to an IOMMU must reference the IOMMU in its device
> +node with the following property:
> +
> +  - iommus: A reference to the IOMMU in multiple cells. The first cell is a
> +	    phandle to the IOMMU and the second cell is the stream id.
> +	    A single master device can be connected to more than one iommu
> +	    and multiple contexts in each of the iommu. So multiple entries
> +	    are required to list all the iommus and the stream ids that the
> +	    master is connected to.
> +
> +Example: mdp iommu and its bus master
> +
> +                mdp_port0: iommu at 7500000 {
> +			compatible = "msm,iommu-v0";
> +			#iommu-cells = <1>;
> +			clock-names =
> +			    "smmu_pclk",
> +			    "iommu_clk";
> +			clocks =
> +			    <&mmcc SMMU_AHB_CLK>,
> +			    <&mmcc MDP_AXI_CLK>;
> +			reg = <0x07500000 0x100000>;
> +			interrupts =
> +			    <GIC_SPI 63 0>,
> +			    <GIC_SPI 64 0>;
> +			qcom,ncb = <2>;
> +		};
> +
> +		mdp: qcom,mdp at 5100000 {
> +			compatible = "qcom,mdp";
> +			...
> +			iommus = <&mdp_port0 0
> +				  &mdp_port0 2>;
> +		};
> -- 
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From robh at kernel.org  Tue May  3 19:30:26 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 3 May 2016 21:30:26 -0500
Subject: [PATCH v2 5/5] vf610-soc: Add Vybrid SoC device tree binding
 documentation
In-Reply-To: <65f3a7bd7a9faf1b390644d7c599c69683c753c4.1462171990.git.maitysanchayan@gmail.com>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
 <65f3a7bd7a9faf1b390644d7c599c69683c753c4.1462171990.git.maitysanchayan@gmail.com>
Message-ID: <20160504023026.GB5382@rob-hp-laptop>

On Mon, May 02, 2016 at 12:35:04PM +0530, Sanchayan Maity wrote:
> Add device tree binding documentation for Vybrid SoC.
> 
> Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
> ---
>  .../bindings/arm/freescale/fsl,vf610-soc.txt       | 35 ++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> new file mode 100644
> index 0000000..bdd95e8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> @@ -0,0 +1,35 @@
> +Vybrid System-on-Chip
> +---------------------
> +
> +Required properties:
> +
> +- #address-cells: must be 1
> +- #size-cells: must be 1
> +- compatible: "fsl,vf610-soc-bus", "simple-bus"

If this is a bus, put the file in bindings/bus/...

> +- interrupt-parent: phandle to the MSCM interrupt router node
> +- ranges
> +- fsl,rom-revision: phandle to the on-chip ROM node and address of rom
> +  revision register

Why is this needed here? Can't you search the tree for the ROM node and 
get this info.

> +- fsl,cpu-count: phandle to the MSCM CPU configuration node and address of
> +  CPU count register
> +- fsl,l2-size: phandle to the MSCM CPU configuration node and address of
> +  L2 cache size register
> +- nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
> +- nvmem-cell-names: should contain string names "cfg0" and "cfg1"

How are all these properties used?

> +
> +Example:
> +
> +	soc {
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		compatible = "fsl,vf610-soc-bus", "simple-bus";
> +		interrupt-parent = <&mscm_ir>;
> +		ranges;
> +		fsl,rom-revision = <&ocrom 0x80>;
> +		fsl,cpu-count = <&mscm_cpucfg 0x2C>;
> +		fsl,l2-size = <&mscm_cpucfg 0x14>;
> +		nvmem-cells = <&ocotp_cfg0>, <&ocotp_cfg1>;
> +		nvmem-cell-names = "cfg0", "cfg1";
> +
> +		...
> +	};
> -- 
> 2.8.2
> 


From robh at kernel.org  Tue May  3 19:31:15 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 3 May 2016 21:31:15 -0500
Subject: [PATCH v2 2/4] documentation: Add compatibles for Amlogic Meson
 GXBB pin controllers
In-Reply-To: <1462176138-29433-3-git-send-email-carlo@caione.org>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
 <1462176138-29433-3-git-send-email-carlo@caione.org>
Message-ID: <20160504023115.GA8507@rob-hp-laptop>

On Mon, May 02, 2016 at 10:02:16AM +0200, Carlo Caione wrote:
> From: Carlo Caione <carlo at endlessm.com>
> 
> Add the two new compatibles for the Amlogic Meson GXBB pin controllers.
> 
> Signed-off-by: Carlo Caione <carlo at endlessm.com>
> ---
>  Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt | 2 ++
>  1 file changed, 2 insertions(+)

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


From yangbo.lu at nxp.com  Tue May  3 20:24:02 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Wed, 4 May 2016 03:24:02 +0000
Subject: [v8, 6/7] MAINTAINERS: add entry for Freescale SoC specific driver
In-Reply-To: <CADRPPNQaLVHp_HnEcHvZE7ebcmhYKf4K8CeWHErRk-0Xv8cU3A@mail.gmail.com>
References: <1461306464-19521-1-git-send-email-yangbo.lu@nxp.com>
 <1461306464-19521-7-git-send-email-yangbo.lu@nxp.com>
 <1461367352.32510.218.camel@buserror.net>
 <HE1PR04MB088907CD90586FC83D058003F8630@HE1PR04MB0889.eurprd04.prod.outlook.com>
 <CADRPPNQaLVHp_HnEcHvZE7ebcmhYKf4K8CeWHErRk-0Xv8cU3A@mail.gmail.com>
Message-ID: <HE1PR04MB0889087BDB60357796424CAAF87B0@HE1PR04MB0889.eurprd04.prod.outlook.com>

Hi Leo and Scott,

> -----Original Message-----
> From: Leo Li [mailto:pku.leo at gmail.com]
> Sent: Wednesday, May 04, 2016 4:06 AM
> To: Yangbo Lu
> Cc: Scott Wood; Yang-Leo Li; linux-mmc at vger.kernel.org; linuxppc-
> dev at lists.ozlabs.org; linux-arm-kernel at lists.infradead.org; linux-
> kernel at vger.kernel.org; ulf.hansson at linaro.org; Zhao Qiang; Russell King;
> Bhupesh Sharma; Xiaobo Xie; Scott Wood; Claudiu Manoil; Kumar Gala
> Subject: Re: [v8, 6/7] MAINTAINERS: add entry for Freescale SoC specific
> driver
> 
> On Mon, Apr 25, 2016 at 10:12 PM, Yangbo Lu <yangbo.lu at nxp.com> wrote:
> > Hi Scott and Leo,
> >
> >
> >> -----Original Message-----
> >> From: linux-mmc-owner at vger.kernel.org [mailto:linux-mmc-
> >> owner at vger.kernel.org] On Behalf Of Scott Wood
> >> Sent: Saturday, April 23, 2016 7:23 AM
> >> To: Yangbo Lu; linux-mmc at vger.kernel.org;
> >> linuxppc-dev at lists.ozlabs.org; linux-arm-kernel at lists.infradead.org;
> >> linux-kernel at vger.kernel.org
> >> Cc: ulf.hansson at linaro.org; Zhao Qiang; Russell King; Bhupesh Sharma;
> >> Scott Wood; Claudiu Manoil; Kumar Gala; Yang-Leo Li; Xiaobo Xie;
> >> Michael Ellerman
> >> Subject: Re: [v8, 6/7] MAINTAINERS: add entry for Freescale SoC
> >> specific driver
> >>
> >> On Fri, 2016-04-22 at 14:27 +0800, Yangbo Lu wrote:
> >> > Add maintainer entry for Freescale SoC specific driver including
> >> > the QE library and the GUTS driver. Also add entry for GUTS driver
> >> > and add maintainer for QE library.
> >> >
> >> > Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
> >> > ---
> >> > Changes for v8:
> >> >     - Added this patch
> >> > ---
> >> >  MAINTAINERS | 16 +++++++++++++++-
> >> >  1 file changed, 15 insertions(+), 1 deletion(-)
> >> >
> >> > diff --git a/MAINTAINERS b/MAINTAINERS index 1d5b4be..d20aeb6
> >> > 100644
> >> > --- a/MAINTAINERS
> >> > +++ b/MAINTAINERS
> >> > @@ -4622,13 +4622,27 @@ F:
> >> > drivers/net/ethernet/freescale/fec_ptp.c
> >> >  F: drivers/net/ethernet/freescale/fec.h
> >> >  F: Documentation/devicetree/bindings/net/fsl-fec.txt
> >> >
> >> > +FREESCALE SOC SPECIFIC DRIVER
> >>
> >> FREESCALE SOC DRIVERS
> >
> > [Lu Yangbo-B47093] Ok, will change it to 'FREESCALE SOC DRIVERS'.
> >
> >>
> >> > +M: Scott Wood <oss at buserror.net>
> >>
> >> Please CC me at this address, not the NXP address that you sent this
> to...
> >
> > [Lu Yangbo-B47093] Sorry for mistaking your email. Will send the one
> you said.
> >
> >>
> >> > +L: linuxppc-dev at lists.ozlabs.org
> >> > +S: Maintained
> >> > +F: drivers/soc/fsl/
> >> > +F: include/linux/fsl/
> >>
> >> This directory will contain drivers that work on PPC and ARM... I'm
> >> not sure what to put here in terms of mailing lists (we could put
> >> both, but people probably shouldn't spam both lists if only one arch
> >> is relevant to the patch), and whom to make pull requests to.
> >
> > [Lu Yangbo-B47093] But sooner or later we need to do this for files in
> fsl/ ...
> > :)
> >
> > Hi Leo, do you have any idea?
> 
> I think it would be ok to put both linuxppc and linux-arm mailing lists
> here.  Driver doesn't fall into any of the functional based sub-systems
> would very likely be platform stuff.  And if patch author has the
> knowledge that a patch only impacts one arch, he can remove the other
> list to reduce the spam.
> 

[Lu Yangbo-B47093] Thanks a lot. I will update the patchset later adding the two mailing lists.

> >
> >
> >>
> >> > +FREESCALE GUTS DRIVER
> >> > +M: Yangbo Lu <yangbo.lu at nxp.com>
> >> > +L: linuxppc-dev at lists.ozlabs.org
> >> > +S: Maintained
> >> > +F: drivers/soc/fsl/guts.c
> >>
> >> What about the header?
> >>
> >> Does guts really need a separate maintainer from drivers/soc/fsl?
> >
> > [Lu Yangbo-B47093] I was hesitating to add the maintainer...
> > And I was not so familiar with it. Let me leave it to the fsl/
> directory and remove this...
> >
> >>
> >> -Scott
> >>
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-mmc"
> >> in the body of a message to majordomo at vger.kernel.org More majordomo
> >> info at http://vger.kernel.org/majordomo-info.html
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev at lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
> 
> 
> 
> --
> - Leo

From yangbo.lu at nxp.com  Tue May  3 20:24:28 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Wed, 4 May 2016 11:24:28 +0800
Subject: [v9, 1/7] Documentation: DT: update Freescale DCFG compatible
In-Reply-To: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
References: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462332274-13744-2-git-send-email-yangbo.lu@nxp.com>

Update Freescale DCFG compatible with 'fsl,<chip>-dcfg' instead
of 'fsl,ls1021a-dcfg' to include more chips such as ls1021a,
ls1043a, and ls2080a.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
---
Changes for v8:
	- Added this patch
Changes for v9:
	- Added a list for the possible compatibles
---
 Documentation/devicetree/bindings/arm/fsl.txt | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
index 752a685..465cba1 100644
--- a/Documentation/devicetree/bindings/arm/fsl.txt
+++ b/Documentation/devicetree/bindings/arm/fsl.txt
@@ -119,7 +119,11 @@ Freescale DCFG
 configuration and status for the device. Such as setting the secondary
 core start address and release the secondary core from holdoff and startup.
   Required properties:
-  - compatible: should be "fsl,ls1021a-dcfg"
+  - compatible: should be "fsl,<chip>-dcfg"
+    Possible compatibles:
+	"fsl,ls1021a-dcfg"
+	"fsl,ls1043a-dcfg"
+	"fsl,ls2080a-dcfg"
   - reg : should contain base address and length of DCFG memory-mapped registers
 
 Example:
-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Tue May  3 20:24:27 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Wed, 4 May 2016 11:24:27 +0800
Subject: [v9, 0/7] Fix eSDHC host version register bug
Message-ID: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>

This patchset is used to fix a host version register bug in the T4240-R1.0-R2.0
eSDHC controller. To get the SoC version and revision, it's needed to add the
GUTS driver to access the global utilities registers.

So, the first four patches are to add the GUTS driver.
The following patches except the updating MAINTAINERS patch are to enable
GUTS driver support to get SVR in eSDHC driver and fix host version for T4240.

Yangbo Lu (7):
  Documentation: DT: update Freescale DCFG compatible
  ARM64: dts: ls2080a: add device configuration node
  soc: fsl: add GUTS driver for QorIQ platforms
  dt: move guts devicetree doc out of powerpc directory
  powerpc/fsl: move mpc85xx.h to include/linux/fsl
  MAINTAINERS: add entry for Freescale SoC driver
  mmc: sdhci-of-esdhc: fix host version for T4240-R1.0-R2.0

 Documentation/devicetree/bindings/arm/fsl.txt      |   6 +-
 .../bindings/{powerpc => soc}/fsl/guts.txt         |   3 +
 MAINTAINERS                                        |  11 +-
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi     |   6 +
 arch/powerpc/kernel/cpu_setup_fsl_booke.S          |   2 +-
 drivers/clk/clk-qoriq.c                            |   3 +-
 drivers/i2c/busses/i2c-mpc.c                       |   2 +-
 drivers/iommu/fsl_pamu.c                           |   3 +-
 drivers/mmc/host/Kconfig                           |   1 +
 drivers/mmc/host/sdhci-of-esdhc.c                  |  23 ++++
 drivers/net/ethernet/freescale/gianfar.c           |   2 +-
 drivers/soc/Kconfig                                |   2 +-
 drivers/soc/fsl/Kconfig                            |   8 ++
 drivers/soc/fsl/Makefile                           |   1 +
 drivers/soc/fsl/guts.c                             | 119 +++++++++++++++++++
 include/linux/fsl/guts.h                           | 126 +++++++++++++--------
 .../asm/mpc85xx.h => include/linux/fsl/svr.h       |   4 +-
 17 files changed, 262 insertions(+), 60 deletions(-)
 rename Documentation/devicetree/bindings/{powerpc => soc}/fsl/guts.txt (91%)
 create mode 100644 drivers/soc/fsl/Kconfig
 create mode 100644 drivers/soc/fsl/guts.c
 rename arch/powerpc/include/asm/mpc85xx.h => include/linux/fsl/svr.h (97%)

-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Tue May  3 20:24:29 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Wed, 4 May 2016 11:24:29 +0800
Subject: [v9, 2/7] ARM64: dts: ls2080a: add device configuration node
In-Reply-To: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
References: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462332274-13744-3-git-send-email-yangbo.lu@nxp.com>

Add the dts node for device configuration unit that provides
general purpose configuration and status for the device.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
Acked-by: Scott Wood <oss at buserror.net>
---
Changes for v5:
	- Added this patch
Changes for v6:
	- None
Changes for v7:
	- None
Changes for v8:
	- Added 'Acked-by: Scott Wood'
Changes for v9:
	- None
---
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index 9d746c6..8724cf1 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -191,6 +191,12 @@
 			clocks = <&sysclk>;
 		};
 
+		dcfg: dcfg at 1e00000 {
+			compatible = "fsl,ls2080a-dcfg", "syscon";
+			reg = <0x0 0x1e00000 0x0 0x10000>;
+			little-endian;
+		};
+
 		serial0: serial at 21c0500 {
 			compatible = "fsl,ns16550", "ns16550a";
 			reg = <0x0 0x21c0500 0x0 0x100>;
-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Tue May  3 20:24:30 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Wed, 4 May 2016 11:24:30 +0800
Subject: [v9, 3/7] soc: fsl: add GUTS driver for QorIQ platforms
In-Reply-To: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
References: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462332274-13744-4-git-send-email-yangbo.lu@nxp.com>

The global utilities block controls power management, I/O device
enabling, power-onreset(POR) configuration monitoring, alternate
function selection for multiplexed signals,and clock control.

This patch adds GUTS driver to manage and access global utilities
block.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
Acked-by: Scott Wood <oss at buserror.net>
---
Changes for v4:
	- Added this patch
Changes for v5:
	- Modified copyright info
	- Changed MODULE_LICENSE to GPL
	- Changed EXPORT_SYMBOL_GPL to EXPORT_SYMBOL
	- Made FSL_GUTS user-invisible
	- Added a complete compatible list for GUTS
	- Stored guts info in file-scope variable
	- Added mfspr() getting SVR
	- Redefined GUTS APIs
	- Called fsl_guts_init rather than using platform driver
	- Removed useless parentheses
	- Removed useless 'extern' key words
Changes for v6:
	- Made guts thread safe in fsl_guts_init
Changes for v7:
	- Removed 'ifdef' for function declaration in guts.h
Changes for v8:
	- Fixes lines longer than 80 characters checkpatch issue
	- Added 'Acked-by: Scott Wood'
Changes for v9:
	- None
---
 drivers/soc/Kconfig      |   2 +-
 drivers/soc/fsl/Kconfig  |   8 +++
 drivers/soc/fsl/Makefile |   1 +
 drivers/soc/fsl/guts.c   | 119 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fsl/guts.h | 126 +++++++++++++++++++++++++++++------------------
 5 files changed, 207 insertions(+), 49 deletions(-)
 create mode 100644 drivers/soc/fsl/Kconfig
 create mode 100644 drivers/soc/fsl/guts.c

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cb58ef0..7106463 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -2,7 +2,7 @@ menu "SOC (System On Chip) specific Drivers"
 
 source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/brcmstb/Kconfig"
-source "drivers/soc/fsl/qe/Kconfig"
+source "drivers/soc/fsl/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/rockchip/Kconfig"
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
new file mode 100644
index 0000000..b313759
--- /dev/null
+++ b/drivers/soc/fsl/Kconfig
@@ -0,0 +1,8 @@
+#
+# Freescale SOC drivers
+#
+
+source "drivers/soc/fsl/qe/Kconfig"
+
+config FSL_GUTS
+	bool
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index 203307f..02afb7f 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_QUICC_ENGINE)		+= qe/
 obj-$(CONFIG_CPM)			+= qe/
+obj-$(CONFIG_FSL_GUTS)			+= guts.o
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
new file mode 100644
index 0000000..fa155e6
--- /dev/null
+++ b/drivers/soc/fsl/guts.c
@@ -0,0 +1,119 @@
+/*
+ * Freescale QorIQ Platforms GUTS Driver
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/fsl/guts.h>
+
+struct guts {
+	struct ccsr_guts __iomem *regs;
+	bool little_endian;
+};
+
+static struct guts *guts;
+static DEFINE_MUTEX(guts_lock);
+
+u32 fsl_guts_get_svr(void)
+{
+	u32 svr = 0;
+
+	if (!guts || !guts->regs) {
+#ifdef CONFIG_PPC
+		svr =  mfspr(SPRN_SVR);
+#endif
+		return svr;
+	}
+
+	if (guts->little_endian)
+		svr = ioread32(&guts->regs->svr);
+	else
+		svr = ioread32be(&guts->regs->svr);
+
+	return svr;
+}
+EXPORT_SYMBOL(fsl_guts_get_svr);
+
+/*
+ * Table for matching compatible strings, for device tree
+ * guts node, for Freescale QorIQ SOCs.
+ */
+static const struct of_device_id guts_of_match[] = {
+	/* For T4 & B4 Series SOCs */
+	{ .compatible = "fsl,qoriq-device-config-1.0", },
+	/* For P Series SOCs */
+	{ .compatible = "fsl,qoriq-device-config-2.0", },
+	{ .compatible = "fsl,p1010-guts", },
+	{ .compatible = "fsl,p1020-guts", },
+	{ .compatible = "fsl,p1021-guts", },
+	{ .compatible = "fsl,p1022-guts", },
+	{ .compatible = "fsl,p1023-guts", },
+	{ .compatible = "fsl,p2020-guts", },
+	/* For BSC Series SOCs */
+	{ .compatible = "fsl,bsc9131-guts", },
+	{ .compatible = "fsl,bsc9132-guts", },
+	/* For MPC85xx Series SOCs */
+	{ .compatible = "fsl,mpc8536-guts", },
+	{ .compatible = "fsl,mpc8544-guts", },
+	{ .compatible = "fsl,mpc8548-guts", },
+	{ .compatible = "fsl,mpc8568-guts", },
+	{ .compatible = "fsl,mpc8569-guts", },
+	{ .compatible = "fsl,mpc8572-guts", },
+	/* For Layerscape Series SOCs */
+	{ .compatible = "fsl,ls1021a-dcfg", },
+	{ .compatible = "fsl,ls1043a-dcfg", },
+	{ .compatible = "fsl,ls2080a-dcfg", },
+	{}
+};
+
+int fsl_guts_init(void)
+{
+	struct device_node *np;
+	int ret;
+
+	mutex_lock(&guts_lock);
+	/* Initialize guts only once */
+	if (guts) {
+		ret = guts->regs ? 0 : -ENOMEM;
+		goto out;
+	}
+
+	np = of_find_matching_node(NULL, guts_of_match);
+	if (!np) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	guts = kzalloc(sizeof(*guts), GFP_KERNEL);
+	if (!guts) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	guts->little_endian = of_property_read_bool(np, "little-endian");
+
+	guts->regs = of_iomap(np, 0);
+	if (!guts->regs) {
+		ret = -ENOMEM;
+		kfree(guts);
+		goto out;
+	}
+
+	of_node_put(np);
+	ret = 0;
+out:
+	mutex_unlock(&guts_lock);
+	return ret;
+}
+EXPORT_SYMBOL(fsl_guts_init);
diff --git a/include/linux/fsl/guts.h b/include/linux/fsl/guts.h
index 649e917..7e1e22b 100644
--- a/include/linux/fsl/guts.h
+++ b/include/linux/fsl/guts.h
@@ -29,83 +29,113 @@
  * #ifdefs.
  */
 struct ccsr_guts {
-	__be32	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */
-	__be32	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */
-	__be32	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and Control Register */
-	__be32	pordevsr;	/* 0x.000c - POR I/O Device Status Register */
-	__be32	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */
-	__be32	pordevsr2;	/* 0x.0014 - POR device status register 2 */
+	u32	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */
+	u32	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */
+	u32	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and
+				 *           Control Register
+				 */
+	u32	pordevsr;	/* 0x.000c - POR I/O Device Status Register */
+	u32	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */
+	u32	pordevsr2;	/* 0x.0014 - POR device status register 2 */
 	u8	res018[0x20 - 0x18];
-	__be32	porcir;		/* 0x.0020 - POR Configuration Information Register */
+	u32	porcir;		/* 0x.0020 - POR Configuration Information
+				 *           Register
+				 */
 	u8	res024[0x30 - 0x24];
-	__be32	gpiocr;		/* 0x.0030 - GPIO Control Register */
+	u32	gpiocr;		/* 0x.0030 - GPIO Control Register */
 	u8	res034[0x40 - 0x34];
-	__be32	gpoutdr;	/* 0x.0040 - General-Purpose Output Data Register */
+	u32	gpoutdr;	/* 0x.0040 - General-Purpose Output Data
+				 *           Register
+				 */
 	u8	res044[0x50 - 0x44];
-	__be32	gpindr;		/* 0x.0050 - General-Purpose Input Data Register */
+	u32	gpindr;		/* 0x.0050 - General-Purpose Input Data
+				 *           Register
+				 */
 	u8	res054[0x60 - 0x54];
-	__be32	pmuxcr;		/* 0x.0060 - Alternate Function Signal Multiplex Control */
-        __be32  pmuxcr2;	/* 0x.0064 - Alternate function signal multiplex control 2 */
-        __be32  dmuxcr;		/* 0x.0068 - DMA Mux Control Register */
+	u32	pmuxcr;		/* 0x.0060 - Alternate Function Signal
+				 *           Multiplex Control
+				 */
+	u32	pmuxcr2;	/* 0x.0064 - Alternate function signal
+				 *           multiplex control 2
+				 */
+	u32	dmuxcr;		/* 0x.0068 - DMA Mux Control Register */
         u8	res06c[0x70 - 0x6c];
-	__be32	devdisr;	/* 0x.0070 - Device Disable Control */
+	u32	devdisr;	/* 0x.0070 - Device Disable Control */
 #define CCSR_GUTS_DEVDISR_TB1	0x00001000
 #define CCSR_GUTS_DEVDISR_TB0	0x00004000
-	__be32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */
+	u32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */
 	u8	res078[0x7c - 0x78];
-	__be32  pmjcr;		/* 0x.007c - 4 Power Management Jog Control Register */
-	__be32	powmgtcsr;	/* 0x.0080 - Power Management Status and Control Register */
-	__be32  pmrccr;		/* 0x.0084 - Power Management Reset Counter Configuration Register */
-	__be32  pmpdccr;	/* 0x.0088 - Power Management Power Down Counter Configuration Register */
-	__be32  pmcdr;		/* 0x.008c - 4Power management clock disable register */
-	__be32	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
-	__be32	rstrscr;	/* 0x.0094 - Reset Request Status and Control Register */
-	__be32  ectrstcr;	/* 0x.0098 - Exception reset control register */
-	__be32  autorstsr;	/* 0x.009c - Automatic reset status register */
-	__be32	pvr;		/* 0x.00a0 - Processor Version Register */
-	__be32	svr;		/* 0x.00a4 - System Version Register */
+	u32	pmjcr;		/* 0x.007c - 4 Power Management Jog Control
+				 *           Register
+				 */
+	u32	powmgtcsr;	/* 0x.0080 - Power Management Status and
+				 *           Control Register
+				 */
+	u32	pmrccr;		/* 0x.0084 - Power Management Reset Counter
+				 *           Configuration Register
+				 */
+	u32	pmpdccr;	/* 0x.0088 - Power Management Power Down Counter
+				 *           Configuration Register
+				 */
+	u32	pmcdr;		/* 0x.008c - 4Power management clock disable
+				 *           register
+				 */
+	u32	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
+	u32	rstrscr;	/* 0x.0094 - Reset Request Status and
+				 *           Control Register
+				 */
+	u32	ectrstcr;	/* 0x.0098 - Exception reset control register */
+	u32	autorstsr;	/* 0x.009c - Automatic reset status register */
+	u32	pvr;		/* 0x.00a0 - Processor Version Register */
+	u32	svr;		/* 0x.00a4 - System Version Register */
 	u8	res0a8[0xb0 - 0xa8];
-	__be32	rstcr;		/* 0x.00b0 - Reset Control Register */
+	u32	rstcr;		/* 0x.00b0 - Reset Control Register */
 	u8	res0b4[0xc0 - 0xb4];
-	__be32  iovselsr;	/* 0x.00c0 - I/O voltage select status register
+	u32	iovselsr;	/* 0x.00c0 - I/O voltage select status register
 					     Called 'elbcvselcr' on 86xx SOCs */
 	u8	res0c4[0x100 - 0xc4];
-	__be32	rcwsr[16];	/* 0x.0100 - Reset Control Word Status registers
+	u32	rcwsr[16];	/* 0x.0100 - Reset Control Word Status registers
 					     There are 16 registers */
 	u8	res140[0x224 - 0x140];
-	__be32  iodelay1;	/* 0x.0224 - IO delay control register 1 */
-	__be32  iodelay2;	/* 0x.0228 - IO delay control register 2 */
+	u32	iodelay1;	/* 0x.0224 - IO delay control register 1 */
+	u32	iodelay2;	/* 0x.0228 - IO delay control register 2 */
 	u8	res22c[0x604 - 0x22c];
-	__be32	pamubypenr; 	/* 0x.604 - PAMU bypass enable register */
+	u32	pamubypenr;	/* 0x.604 - PAMU bypass enable register */
 	u8	res608[0x800 - 0x608];
-	__be32	clkdvdr;	/* 0x.0800 - Clock Divide Register */
+	u32	clkdvdr;	/* 0x.0800 - Clock Divide Register */
 	u8	res804[0x900 - 0x804];
-	__be32	ircr;		/* 0x.0900 - Infrared Control Register */
+	u32	ircr;		/* 0x.0900 - Infrared Control Register */
 	u8	res904[0x908 - 0x904];
-	__be32	dmacr;		/* 0x.0908 - DMA Control Register */
+	u32	dmacr;		/* 0x.0908 - DMA Control Register */
 	u8	res90c[0x914 - 0x90c];
-	__be32	elbccr;		/* 0x.0914 - eLBC Control Register */
+	u32	elbccr;		/* 0x.0914 - eLBC Control Register */
 	u8	res918[0xb20 - 0x918];
-	__be32	ddr1clkdr;	/* 0x.0b20 - DDR1 Clock Disable Register */
-	__be32	ddr2clkdr;	/* 0x.0b24 - DDR2 Clock Disable Register */
-	__be32	ddrclkdr;	/* 0x.0b28 - DDR Clock Disable Register */
+	u32	ddr1clkdr;	/* 0x.0b20 - DDR1 Clock Disable Register */
+	u32	ddr2clkdr;	/* 0x.0b24 - DDR2 Clock Disable Register */
+	u32	ddrclkdr;	/* 0x.0b28 - DDR Clock Disable Register */
 	u8	resb2c[0xe00 - 0xb2c];
-	__be32	clkocr;		/* 0x.0e00 - Clock Out Select Register */
+	u32	clkocr;		/* 0x.0e00 - Clock Out Select Register */
 	u8	rese04[0xe10 - 0xe04];
-	__be32	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
+	u32	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
 	u8	rese14[0xe20 - 0xe14];
-	__be32	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
-	__be32  cpfor;		/* 0x.0e24 - L2 charge pump fuse override register */
+	u32	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
+	u32	cpfor;		/* 0x.0e24 - L2 charge pump fuse override
+				 *           register
+				 */
 	u8	rese28[0xf04 - 0xe28];
-	__be32	srds1cr0;	/* 0x.0f04 - SerDes1 Control Register 0 */
-	__be32	srds1cr1;	/* 0x.0f08 - SerDes1 Control Register 0 */
+	u32	srds1cr0;	/* 0x.0f04 - SerDes1 Control Register 0 */
+	u32	srds1cr1;	/* 0x.0f08 - SerDes1 Control Register 0 */
 	u8	resf0c[0xf2c - 0xf0c];
-	__be32  itcr;		/* 0x.0f2c - Internal transaction control register */
+	u32	itcr;		/* 0x.0f2c - Internal transaction control
+				 *           register
+				 */
 	u8	resf30[0xf40 - 0xf30];
-	__be32	srds2cr0;	/* 0x.0f40 - SerDes2 Control Register 0 */
-	__be32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */
+	u32	srds2cr0;	/* 0x.0f40 - SerDes2 Control Register 0 */
+	u32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */
 } __attribute__ ((packed));
 
+u32 fsl_guts_get_svr(void);
+int fsl_guts_init(void);
 
 /* Alternate function signal multiplex control */
 #define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Tue May  3 20:24:31 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Wed, 4 May 2016 11:24:31 +0800
Subject: [v9, 4/7] dt: move guts devicetree doc out of powerpc directory
In-Reply-To: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
References: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462332274-13744-5-git-send-email-yangbo.lu@nxp.com>

Move guts devicetree doc to Documentation/devicetree/bindings/soc/fsl/
since it's used by not only PowerPC but also ARM. And add a specification
for 'little-endian' property.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
Acked-by: Scott Wood <oss at buserror.net>
Acked-by: Rob Herring <robh at kernel.org>
---
Changes for v4:
	- Added this patch
Changes for v5:
	- Modified the description for little-endian property
Changes for v6:
	- None
Changes for v7:
	- None
Changes for v8:
	- Added 'Acked-by: Scott Wood'
	- Added 'Acked-by: Rob Herring'
Changes for v9:
	- None
---
 Documentation/devicetree/bindings/{powerpc => soc}/fsl/guts.txt | 3 +++
 1 file changed, 3 insertions(+)
 rename Documentation/devicetree/bindings/{powerpc => soc}/fsl/guts.txt (91%)

diff --git a/Documentation/devicetree/bindings/powerpc/fsl/guts.txt b/Documentation/devicetree/bindings/soc/fsl/guts.txt
similarity index 91%
rename from Documentation/devicetree/bindings/powerpc/fsl/guts.txt
rename to Documentation/devicetree/bindings/soc/fsl/guts.txt
index b71b203..07adca9 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/guts.txt
+++ b/Documentation/devicetree/bindings/soc/fsl/guts.txt
@@ -25,6 +25,9 @@ Recommended properties:
  - fsl,liodn-bits : Indicates the number of defined bits in the LIODN
    registers, for those SOCs that have a PAMU device.
 
+ - little-endian : Indicates that the global utilities block is little
+   endian. The default is big endian.
+
 Examples:
 	global-utilities at e0000 {	/* global utilities block */
 		compatible = "fsl,mpc8548-guts";
-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Tue May  3 20:24:32 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Wed, 4 May 2016 11:24:32 +0800
Subject: [v9, 5/7] powerpc/fsl: move mpc85xx.h to include/linux/fsl
In-Reply-To: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
References: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462332274-13744-6-git-send-email-yangbo.lu@nxp.com>

Move mpc85xx.h to include/linux/fsl and rename it to svr.h as
a common header file. It has been used for mpc85xx and it will
be used for ARM-based SoC as well.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
Acked-by: Wolfram Sang <wsa at the-dreams.de>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Acked-by: Scott Wood <oss at buserror.net>
Acked-by: Joerg Roedel <jroedel at suse.de>
---
Changes for v2:
	- None
Changes for v3:
	- None
Changes for v4:
	- None
Changes for v5:
	- Changed to Move mpc85xx.h to include/linux/fsl/
	- Adjusted '#include <linux/fsl/svr.h>' position in file
Changes for v6:
	- None
Changes for v7:
	- Added 'Acked-by: Wolfram Sang' for I2C part
	- Also applied to arch/powerpc/kernel/cpu_setup_fsl_booke.S
Changes for v8:
	- Added 'Acked-by: Stephen Boyd' for clk part
	- Added 'Acked-by: Scott Wood'
	- Added 'Acked-by: Joerg Roedel' for iommu part
Changes for v9:
	- None
---
 arch/powerpc/kernel/cpu_setup_fsl_booke.S                     | 2 +-
 drivers/clk/clk-qoriq.c                                       | 3 +--
 drivers/i2c/busses/i2c-mpc.c                                  | 2 +-
 drivers/iommu/fsl_pamu.c                                      | 3 +--
 drivers/net/ethernet/freescale/gianfar.c                      | 2 +-
 arch/powerpc/include/asm/mpc85xx.h => include/linux/fsl/svr.h | 4 ++--
 6 files changed, 7 insertions(+), 9 deletions(-)
 rename arch/powerpc/include/asm/mpc85xx.h => include/linux/fsl/svr.h (97%)

diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
index 462aed9..2b0284e 100644
--- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
@@ -13,13 +13,13 @@
  *
  */
 
+#include <linux/fsl/svr.h>
 #include <asm/page.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/ppc_asm.h>
 #include <asm/mmu-book3e.h>
 #include <asm/asm-offsets.h>
-#include <asm/mpc85xx.h>
 
 _GLOBAL(__e500_icache_setup)
 	mfspr	r0, SPRN_L1CSR1
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 7bc1c45..fc7f722 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -13,6 +13,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/fsl/guts.h>
+#include <linux/fsl/svr.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -1148,8 +1149,6 @@ bad_args:
 }
 
 #ifdef CONFIG_PPC
-#include <asm/mpc85xx.h>
-
 static const u32 a4510_svrs[] __initconst = {
 	(SVR_P2040 << 8) | 0x10,	/* P2040 1.0 */
 	(SVR_P2040 << 8) | 0x11,	/* P2040 1.1 */
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 48ecffe..600704c 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -27,9 +27,9 @@
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/fsl/svr.h>
 
 #include <asm/mpc52xx.h>
-#include <asm/mpc85xx.h>
 #include <sysdev/fsl_soc.h>
 
 #define DRV_NAME "mpc-i2c"
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index a34355f..af8fb27 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -21,11 +21,10 @@
 #include "fsl_pamu.h"
 
 #include <linux/fsl/guts.h>
+#include <linux/fsl/svr.h>
 #include <linux/interrupt.h>
 #include <linux/genalloc.h>
 
-#include <asm/mpc85xx.h>
-
 /* define indexes for each operation mapping scenario */
 #define OMI_QMAN        0x00
 #define OMI_FMAN        0x01
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index d2f917a..2224b10 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -86,11 +86,11 @@
 #include <linux/udp.h>
 #include <linux/in.h>
 #include <linux/net_tstamp.h>
+#include <linux/fsl/svr.h>
 
 #include <asm/io.h>
 #ifdef CONFIG_PPC
 #include <asm/reg.h>
-#include <asm/mpc85xx.h>
 #endif
 #include <asm/irq.h>
 #include <asm/uaccess.h>
diff --git a/arch/powerpc/include/asm/mpc85xx.h b/include/linux/fsl/svr.h
similarity index 97%
rename from arch/powerpc/include/asm/mpc85xx.h
rename to include/linux/fsl/svr.h
index 213f3a8..8d13836 100644
--- a/arch/powerpc/include/asm/mpc85xx.h
+++ b/include/linux/fsl/svr.h
@@ -9,8 +9,8 @@
  * (at your option) any later version.
  */
 
-#ifndef __ASM_PPC_MPC85XX_H
-#define __ASM_PPC_MPC85XX_H
+#ifndef FSL_SVR_H
+#define FSL_SVR_H
 
 #define SVR_REV(svr)	((svr) & 0xFF)		/* SOC design resision */
 #define SVR_MAJ(svr)	(((svr) >>  4) & 0xF)	/* Major revision field*/
-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Tue May  3 20:24:33 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Wed, 4 May 2016 11:24:33 +0800
Subject: [v9, 6/7] MAINTAINERS: add entry for Freescale SoC driver
In-Reply-To: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
References: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462332274-13744-7-git-send-email-yangbo.lu@nxp.com>

Add maintainer entry for Freescale SoC driver including
the QE library and the GUTS driver now. Also add maintainer
for QE library.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
---
Changes for v8:
	- Added this patch
Changes for v9:
	- Added linux-arm mail list
	- Removed GUTS driver entry
---
 MAINTAINERS | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 42e65d1..ce91db7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4622,9 +4622,18 @@ F:	drivers/net/ethernet/freescale/fec_ptp.c
 F:	drivers/net/ethernet/freescale/fec.h
 F:	Documentation/devicetree/bindings/net/fsl-fec.txt
 
+FREESCALE SOC DRIVER
+M:	Scott Wood <oss at buserror.net>
+L:	linuxppc-dev at lists.ozlabs.org
+L:	linux-arm-kernel at lists.infradead.org
+S:	Maintained
+F:	drivers/soc/fsl/
+F:	include/linux/fsl/
+
 FREESCALE QUICC ENGINE LIBRARY
+M:	Qiang Zhao <qiang.zhao at nxp.com>
 L:	linuxppc-dev at lists.ozlabs.org
-S:	Orphan
+S:	Maintained
 F:	drivers/soc/fsl/qe/
 F:	include/soc/fsl/*qe*.h
 F:	include/soc/fsl/*ucc*.h
-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Tue May  3 20:24:34 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Wed, 4 May 2016 11:24:34 +0800
Subject: [v9, 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-R1.0-R2.0
In-Reply-To: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
References: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462332274-13744-8-git-send-email-yangbo.lu@nxp.com>

The eSDHC of T4240-R1.0-R2.0 has incorrect vender version and spec version.
Acturally the right version numbers should be VVN=0x13 and SVN = 0x1.
This patch adds the GUTS driver support for eSDHC driver to get SVR(System
version register). And fix host version to avoid that incorrect version
numbers break down the ADMA data transfer.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
Acked-by: Ulf Hansson <ulf.hansson at linaro.org>
Acked-by: Scott Wood <oss at buserror.net>
---
Changes for v2:
	- Got SVR through iomap instead of dts
Changes for v3:
	- Managed GUTS through syscon instead of iomap in eSDHC driver
Changes for v4:
	- Got SVR by GUTS driver instead of SYSCON
Changes for v5:
	- Changed to get SVR through API fsl_guts_get_svr()
	- Combined patch 4, patch 5 and patch 6 into one
Changes for v6:
	- Added 'Acked-by: Ulf Hansson'
Changes for v7:
	- None
Changes for v8:
	- Added 'Acked-by: Scott Wood'
Changes for v9:
	- None
---
 drivers/mmc/host/Kconfig          |  1 +
 drivers/mmc/host/sdhci-of-esdhc.c | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 0aa484c..e15e836 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -143,6 +143,7 @@ config MMC_SDHCI_OF_ESDHC
 	depends on MMC_SDHCI_PLTFM
 	depends on PPC || ARCH_MXC || ARCH_LAYERSCAPE
 	select MMC_SDHCI_IO_ACCESSORS
+	select FSL_GUTS
 	help
 	  This selects the Freescale eSDHC controller support.
 
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 3f34d35..68cc020 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -18,6 +18,8 @@
 #include <linux/of.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/fsl/svr.h>
+#include <linux/fsl/guts.h>
 #include <linux/mmc/host.h>
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
@@ -28,6 +30,8 @@
 struct sdhci_esdhc {
 	u8 vendor_ver;
 	u8 spec_ver;
+	u32 soc_ver;
+	u8 soc_rev;
 };
 
 /**
@@ -73,6 +77,8 @@ static u32 esdhc_readl_fixup(struct sdhci_host *host,
 static u16 esdhc_readw_fixup(struct sdhci_host *host,
 				     int spec_reg, u32 value)
 {
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
 	u16 ret;
 	int shift = (spec_reg & 0x2) * 8;
 
@@ -80,6 +86,13 @@ static u16 esdhc_readw_fixup(struct sdhci_host *host,
 		ret = value & 0xffff;
 	else
 		ret = (value >> shift) & 0xffff;
+
+	/* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect
+	 * vendor version and spec version information.
+	 */
+	if ((spec_reg == SDHCI_HOST_VERSION) &&
+	    (esdhc->soc_ver == SVR_T4240) && (esdhc->soc_rev <= 0x20))
+		ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200;
 	return ret;
 }
 
@@ -567,10 +580,20 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_esdhc *esdhc;
 	u16 host_ver;
+	u32 svr;
 
 	pltfm_host = sdhci_priv(host);
 	esdhc = sdhci_pltfm_priv(pltfm_host);
 
+	fsl_guts_init();
+	svr = fsl_guts_get_svr();
+	if (svr) {
+		esdhc->soc_ver = SVR_SOC_VER(svr);
+		esdhc->soc_rev = SVR_REV(svr);
+	} else {
+		dev_err(&pdev->dev, "Failed to get SVR value!\n");
+	}
+
 	host_ver = sdhci_readw(host, SDHCI_HOST_VERSION);
 	esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >>
 			     SDHCI_VENDOR_VER_SHIFT;
-- 
2.1.0.27.g96db324



From chunkeey at googlemail.com  Tue May  3 21:53:50 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Wed, 04 May 2016 06:53:50 +0200
Subject: [RFC v6 1/3] gpio: dt-bindings: add wd,mbl-gpio bindings
In-Reply-To: <20160504022210.GA9913@rob-hp-laptop>
References: <cover.1462104492.git.chunkeey@googlemail.com>
 <103bf8fceb426a9c3b09641ea989955e3ec1c7d4.1462104492.git.chunkeey@googlemail.com>
 <20160504022210.GA9913@rob-hp-laptop>
Message-ID: <4330813.s9mxBLCsXA@debian64>

On Tuesday, May 03, 2016 09:22:10 PM Rob Herring wrote:
> On Sun, May 01, 2016 at 02:18:37PM +0200, Christian Lamparter wrote:
> > This patch adds the device tree bindings for the Western Digital's
> > MyBook Live memory-mapped GPIO controllers.
> > 
> > The gpios will be supported by gpio-mmio code of the
> > GPIO generic library.
> > 
> > +++ b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
> > @@ -0,0 +1,38 @@
> > +Bindings for the Western Digital's MyBook Live memory-mapped GPIO controllers.
> 
> Are these really product level GPIOs rather than some SOC's GPIOs 
> (APM?)?
> 
Ah, that's a good point. 

In a nutshell: The APM82181 SoC has two proper/normal GPIO controllers
which have a dt-binding and a kernel driver ready to go.
However Western Digital went with their own GPIO controller for
the MyBook Live [7].

Long version:
I know this SoC does have proper GPIO controllers [0].
For reference: I've helped making a OpenWRT port for the Cisco Meraki MR24
which uses it/them [1], [2]. Here's the GPIO extract from the MR24 DTS [3]:

--- MR24 DTS ---
	GPIO0: gpio at ef600b00 {
   		compatible = "ibm,ppc4xx-gpio";
       reg = <0xef600b00 0x00000048>; 
       #gpio-cells = <2>;
       gpio-controller;
    };
--- snap ---

The driver for the "ibm,ppc4xx-gpio" is located under: 
arch/powerpc/sysdev/ppc4xx_gpio.c [4].
I can't find a dt binding text for it, if you want I can write one >later<.
The "ppc4xx" moniker is a strong indication that these GPIO controllers 
were carried over from the ppc46x/44x/40x series. 
The address (but not the range): 0x00000004 ef600b00 does match with the
System Memory Map of the PPC460EX (See GPIO0 Controller on page 8 [5]).

Now for the MyBook Live: The GPIO situation is completely different.
Unlike the MR24, there are two GPIOs. The first one is on address
0x4e0000000. It drives the 3-color LED, Ethernet PHY Reset, USB-Core Power,
SATA Port0 and Port1 Power, NOR Flash Switch and the reset button driver.

The second GPIO only has one input connected. It BIT2 represents the state
of the reset button. It is located at 0x4e0100000. (The 0x4e0xxxxx address
puts the GPIO devices on the EBC (aka External Peripheral Bus Controller).
The EBC is normally used for "direct attachment of memory devices such as
ROM, SRAM, ...")

Western Digital did release their version of the GPIO driver: apollo3g-gpio.c
as part of their GPL sources [6]. (I found a mostly untouched version of the
apollo3g-gpio.c driver on github [7] (AFAICT he added the "porting to kernel 
3.2.64 by night_ghost at ..."  string, other than that it should be pretty much
identical to what's inside the GPL.tar.gz).

So, I think the MyBook Live's GPIO controller is definitively something WD
cooked up by themselves in their labs. But I have no idea why they didn't
use the SoC's GPIO like Cisco... But sadly they really didn't...

Note:
If someone wants to look and play with this curiosity. I have a small
stack of DIY "MyBook Live kits", so I can sent one or two away easily.
For assembling a kit: one need a working 3.5" SATA HDD and a 12v 1.25A
PSU with a standard 5.5mm x 2.1mm power jack. I made a Debian image for 
development (download). So, if someone is interested: PM me.

Regards,
Christian

[0] <https://c1170156.ssl.cf3.rackcdn.com/UK_AMC_APM82181-SKE1000T_DS.pdf>
[1] <https://wikidevi.com/wiki/Cisco_Meraki_MR24>
[2] <https://forum.openwrt.org/viewtopic.php?pid=316793#p316793>
[3] <https://github.com/riptidewave93/Openwrt-MR24/blob/master/overlay/target/linux/apm821xx/dts/MR24.dts#L251>
[4] <https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/powerpc/sysdev/ppc4xx_gpio.c>
[5] <http://datasheet.octopart.com/PPC460EX-NUB800T-AMCC-datasheet-11553412.pdf>
[6] <http://support.wdc.com/downloads.aspx?p=132&lang=en>
[7] <https://github.com/MyBookLive/kernel-4.0.x/blob/master/03_enable_leds.patch>

> +The Western Digital MyBook Live has two memory-mapped GPIO controllers.
> +Both GPIO controller only have a single 8-bit data register, where GPIO
> +state can be read and/or written.
> +
> +Required properties:
> +     - compatible: should be "wd,mbl-gpio"
> +     - reg-names: must contain
> +             "dat" - data register
> +     - reg: address + size pairs describing the GPIO register sets;
> +             order must correspond with the order of entries in reg-names
> +     - #gpio-cells: must be set to 2. The first cell is the pin number and
> +                     the second cell is used to specify the gpio polarity:
> +                     0 = active high
> +                     1 = active low
> +     - gpio-controller: Marks the device node as a gpio controller.
> +
> +Optional properties:
> +     - no-output: GPIOs are read-only.
> +
> +Examples:
> +     gpio0: gpio0 at e0000000 {
> +             compatible = "wd,mbl-gpio";
> +             reg-names = "dat";
> +             reg = <0xe0000000 0x1>;
> +             #gpio-cells = <2>;
> +             gpio-controller;
> +     };
> +
> +     gpio1: gpio1 at e0100000 {
> +             compatible = "wd,mbl-gpio";
> +             reg-names = "dat";
> +             reg = <0xe0100000 0x1>;
> +             #gpio-cells = <2>;
> +             gpio-controller;
> +             no-output;
> +     };
> -- 
> 2.8.1
> 


From plaes at plaes.org  Tue May  3 22:13:01 2016
From: plaes at plaes.org (Priit Laes)
Date: Wed, 04 May 2016 08:13:01 +0300
Subject: [linux-sunxi] Re: [PATCH 1/1] ARM: dts: sunxi: Add a
 olinuxino-lime2-emmc
In-Reply-To: <5728C929.3040709@schinagl.nl>
References: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
 <f3da30a6-9ac0-4d5e-8611-ebb80cb3589e@googlegroups.com>
 <20160503131437.GV17159@lukather>
 <66e4c452-1e34-474b-8973-2d57d9f036d0@googlegroups.com>
 <5728C929.3040709@schinagl.nl>
Message-ID: <1462338781.15404.0.camel@plaes.org>

On Tue, 2016-05-03 at 17:52 +0200, Olliver Schinagl wrote:
> Hey all,
> 
> On 03-05-16 17:02, christo.radev at gmail.com wrote:
> > On Tuesday, May 3, 2016 at 4:14:41 PM UTC+3, Maxime Ripard wrote:
> > > Hi,
> > > 
> > > On Tue, May 03, 2016 at 4:12:06 PM UTC+3, Christo Radev wrote:
> > > > Hi to All,
> > > > 
> > > > I have already solved and tested this issue on Armbian build. 
> > > >  Find
> > > > patches for both legacy (3.4.111) and mainline (4.5.2) kernels
> > > > on:
> > > > http://forum.armbian.com/index.php/topic/853-armbian-customizat
> > > > ion/page-2#entry7494
> > > > There it is also described how to do eMMC bootable and much
> > > > more.
> > > > 
> > > > About the board - Olimex already sold all 3 kinds after
> > > > migration to
> > > > their HW rev. E. One have to specify Lime2-eMMC as
> > > > A20-Olinuxino-Lime2-eMMC instead of their old 2 options
> > > > A20-Olinuxino-Lime2(-4GB).
> > > Interesting, you have a link to that device?

I guess, it is this one:

https://www.olimex.com/Products/OLinuXino/A20/A20-OLinuXino-LIME2-eMMC/
open-source-hardware

> > > 
> > > Thanks,
> > > Maxime
> > > 
> > > -- 
> > > Maxime Ripard, Free Electrons
> > > Embedded Linux, Kernel and Android engineering
> > > http://free-electrons.com
> > I have really 2 boards delivered by their local distributor.
> > 
> > Unfortunately, they do not update their site. Use the link for NAND
> > option:
> > https://www.olimex.com/Products/OLinuXino/A20/A20-OLinuXIno-LIME2-4
> > GB/open-source-hardware
> > There you can find Users Manual where it is described that eMMC
> > option is available from HW rev. D. The schematic for HW rev. E is
> > also available on their repository:
> > https://github.com/OLIMEX/OLINUXINO/tree/master/HARDWARE/A20-OLinuX
> > ino-LIME2
> > 
> > On the board both 4GB NAND and eMMC Flash chips can be placed
> > alternatively on the same place. There is difference in some other
> > components as well.
> > 
> > If one want to order it from the site probably has to order A20
> > -Olinuxino-Lime2-4GB with note that eMMC option is required. The
> > price is the same.
> Sorry for the late reply, but yeah the board exists, we asked Olimex
> to 
> develop the eMMC variant for us. I currently have a dozen or so on my
> desk :)
> 
> I don't know when Olimex will update their webshop with the new
> designs, 
> but they simply might not have enough eMMC chips available yet?
> 


From chaotian.jing at mediatek.com  Tue May  3 23:54:32 2016
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Wed, 4 May 2016 14:54:32 +0800
Subject: [PATCH] mmc: mmc: do not use CMD13 to get status after speed mode
 switch
Message-ID: <1462344872-6448-1-git-send-email-chaotian.jing@mediatek.com>

Per JEDEC spec, it is not recommended to use CMD13 to get card status
after speed mode switch. below are two reason about this:
1. CMD13 cannot be guaranteed due to the asynchronous operation.
Therefore it is not recommended to use CMD13 to check busy completion
of the timing change indication.
2. After switch to HS200, CMD13 will get response of 0x800, and even the
busy signal gets de-asserted, the response of CMD13 is aslo 0x800.

this patch drops CMD13 when doing speed mode switch, if host do not
support MMC_CAP_WAIT_WHILE_BUSY and there is no ops->card_busy(),
then the only way is to wait a fixed timeout.

Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
---
 drivers/mmc/core/mmc.c     |   82 ++++++++++++++++----------------------------
 drivers/mmc/core/mmc_ops.c |   25 +++++++++-----
 2 files changed, 45 insertions(+), 62 deletions(-)

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 4dbe3df..03ee7a4 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -962,7 +962,7 @@ static int mmc_select_hs(struct mmc_card *card)
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
 			   card->ext_csd.generic_cmd6_time,
-			   true, true, true);
+			   true, false, true);
 	if (!err)
 		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
 
@@ -1056,7 +1056,6 @@ static int mmc_switch_status(struct mmc_card *card)
 static int mmc_select_hs400(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	bool send_status = true;
 	unsigned int max_dtr;
 	int err = 0;
 	u8 val;
@@ -1068,9 +1067,6 @@ static int mmc_select_hs400(struct mmc_card *card)
 	      host->ios.bus_width == MMC_BUS_WIDTH_8))
 		return 0;
 
-	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-		send_status = false;
-
 	/* Reduce frequency to HS frequency */
 	max_dtr = card->ext_csd.hs_max_dtr;
 	mmc_set_clock(host, max_dtr);
@@ -1080,7 +1076,7 @@ static int mmc_select_hs400(struct mmc_card *card)
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, val,
 			   card->ext_csd.generic_cmd6_time,
-			   true, send_status, true);
+			   true, false, true);
 	if (err) {
 		pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
 			mmc_hostname(host), err);
@@ -1090,11 +1086,9 @@ static int mmc_select_hs400(struct mmc_card *card)
 	/* Set host controller to HS timing */
 	mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	/* Switch card to DDR */
 	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1113,7 +1107,7 @@ static int mmc_select_hs400(struct mmc_card *card)
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, val,
 			   card->ext_csd.generic_cmd6_time,
-			   true, send_status, true);
+			   true, false, true);
 	if (err) {
 		pr_err("%s: switch to hs400 failed, err:%d\n",
 			 mmc_hostname(host), err);
@@ -1124,11 +1118,9 @@ static int mmc_select_hs400(struct mmc_card *card)
 	mmc_set_timing(host, MMC_TIMING_MMC_HS400);
 	mmc_set_bus_speed(card);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	return 0;
 
@@ -1146,14 +1138,10 @@ int mmc_hs200_to_hs400(struct mmc_card *card)
 int mmc_hs400_to_hs200(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	bool send_status = true;
 	unsigned int max_dtr;
 	int err;
 	u8 val;
 
-	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-		send_status = false;
-
 	/* Reduce frequency to HS */
 	max_dtr = card->ext_csd.hs_max_dtr;
 	mmc_set_clock(host, max_dtr);
@@ -1162,49 +1150,43 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
 	val = EXT_CSD_TIMING_HS;
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
 			   val, card->ext_csd.generic_cmd6_time,
-			   true, send_status, true);
+			   true, false, true);
 	if (err)
 		goto out_err;
 
 	mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	/* Switch HS DDR to HS */
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
 			   EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time,
-			   true, send_status, true);
+			   true, false, true);
 	if (err)
 		goto out_err;
 
 	mmc_set_timing(host, MMC_TIMING_MMC_HS);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	/* Switch HS to HS200 */
 	val = EXT_CSD_TIMING_HS200 |
 	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
 			   val, card->ext_csd.generic_cmd6_time, true,
-			   send_status, true);
+			   false, true);
 	if (err)
 		goto out_err;
 
 	mmc_set_timing(host, MMC_TIMING_MMC_HS200);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	mmc_set_bus_speed(card);
 
@@ -1243,7 +1225,6 @@ static void mmc_select_driver_type(struct mmc_card *card)
 static int mmc_select_hs200(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	bool send_status = true;
 	unsigned int old_timing;
 	int err = -EINVAL;
 	u8 val;
@@ -1260,9 +1241,6 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	mmc_select_driver_type(card);
 
-	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-		send_status = false;
-
 	/*
 	 * Set the bus width(4 or 8) with host's support and
 	 * switch to HS200 mode if bus width is set successfully.
@@ -1274,20 +1252,18 @@ static int mmc_select_hs200(struct mmc_card *card)
 		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 				   EXT_CSD_HS_TIMING, val,
 				   card->ext_csd.generic_cmd6_time,
-				   true, send_status, true);
+				   true, false, true);
 		if (err)
 			goto err;
 		old_timing = host->ios.timing;
 		mmc_set_timing(host, MMC_TIMING_MMC_HS200);
-		if (!send_status) {
-			err = mmc_switch_status(card);
-			/*
-			 * mmc_select_timing() assumes timing has not changed if
-			 * it is a switch error.
-			 */
-			if (err == -EBADMSG)
-				mmc_set_timing(host, old_timing);
-		}
+		err = mmc_switch_status(card);
+		/*
+		 * mmc_select_timing() assumes timing has not changed if
+		 * it is a switch error.
+		 */
+		if (err == -EBADMSG)
+			mmc_set_timing(host, old_timing);
 	}
 err:
 	if (err)
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 62355bd..32de144 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -480,6 +480,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 	u32 status = 0;
 	bool use_r1b_resp = use_busy_signal;
 	bool expired = false;
+	bool busy = false;
 
 	mmc_retune_hold(host);
 
@@ -535,19 +536,24 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 	/* Must check status to be sure of no errors. */
 	timeout = jiffies + msecs_to_jiffies(timeout_ms);
 	do {
+		/*
+		 * Due to the possibility of being preempted after
+		 * sending the status command, check the expiration
+		 * time first.
+		 */
+		expired = time_after(jiffies, timeout);
 		if (send_status) {
-			/*
-			 * Due to the possibility of being preempted after
-			 * sending the status command, check the expiration
-			 * time first.
-			 */
-			expired = time_after(jiffies, timeout);
 			err = __mmc_send_status(card, &status, ignore_crc);
 			if (err)
 				goto out;
 		}
 		if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
 			break;
+		if (host->ops->card_busy) {
+			if (!host->ops->card_busy(host))
+				break;
+			busy = true;
+		}
 		if (mmc_host_is_spi(host))
 			break;
 
@@ -556,19 +562,20 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 		 * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
 		 * rely on waiting for the stated timeout to be sufficient.
 		 */
-		if (!send_status) {
+		if (!send_status && !host->ops->card_busy) {
 			mmc_delay(timeout_ms);
 			goto out;
 		}
 
 		/* Timeout if the device never leaves the program state. */
-		if (expired && R1_CURRENT_STATE(status) == R1_STATE_PRG) {
+		if (expired &&
+		    (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy)) {
 			pr_err("%s: Card stuck in programming state! %s\n",
 				mmc_hostname(host), __func__);
 			err = -ETIMEDOUT;
 			goto out;
 		}
-	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
+	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy);
 
 	err = mmc_switch_status_error(host, status);
 out:
-- 
1.7.9.5



From jic23 at kernel.org  Wed May  4 00:15:30 2016
From: jic23 at kernel.org (Jonathan Cameron)
Date: Wed, 4 May 2016 08:15:30 +0100
Subject: [PATCH 1/3] iio: mxs-lradc: Add regulators for current sources
In-Reply-To: <6cdd4f858dacf72e192a292f29c12feb@ccbib.org>
References: <1461333147-11873-1-git-send-email-harald@ccbib.org>
 <1461333147-11873-2-git-send-email-harald@ccbib.org>
 <57288674.9050601@i2se.com> <6cdd4f858dacf72e192a292f29c12feb@ccbib.org>
Message-ID: <1e7d5f3a-22c1-94d4-9620-7aa112602e39@kernel.org>

On 03/05/16 12:22, Harald Geyer wrote:
> Hi Stefan!
> 
> On 03.05.2016 13:07, Stefan Wahren wrote:
>> Am 22.04.2016 um 15:52 schrieb Harald Geyer:
>>> The hardware has two current sources ISRC0 and ISRC1 to allow measuring
>>> resistors without additional circuitry. This commit makes them available
>>> as regulators.
>>>
>>> Tested on an imx233-olinuxino board.
>>>
>>> Signed-off-by: Harald Geyer <harald at ccbib.org>
>>> ---
>>> The current regulator API doesn't fit this type of device very well: Typically
>>> consumers will want to set a defined current, ie. min_uA == max_uA, but they
>>> can't without help from configuration data, because the valid values aren't
>>> reported by the API for current regulators. I have been thinking about
>>> extending the API, but currently AFAIK no such consumers exist and most
>>> users, like myself, will force the regulator to a defined value in
>>> devicetree anyway.
>>>
>>>  .../bindings/staging/iio/adc/mxs-lradc.txt         |  29 ++++
>>>  drivers/iio/adc/Kconfig                            |   1 +
>>>  drivers/iio/adc/mxs-lradc.c                        | 152 +++++++++++++++++++++
>>>  3 files changed, 182 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
>>> index 555fb11..983952c 100644
>>> --- a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
>>> +++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
>>> @@ -19,6 +19,15 @@ Optional properties:
>>>  - fsl,settling: delay between plate switch to next sample. Allowed value is
>>>                  1 ... 2047. It counts at 2 kHz and its default is
>>>                  10 (= 5 ms)
>>> +- ISRC0: A node describing the regulator of internal current source 0
>>> +- ISRC1: A node describing the regulator of internal current source 1
>>> +
>>> +Required properties for the ISRCx sub-nodes:
>>> +- regulator-max-microamp: See standard regulator binding documentation.
>>> +                          Valid values are from 0 to 300 in steps of 20.
>>> +
>>> +Optional properties for the ISRCx sub-nodes:
>>> +Any standard regulator properties that apply to current regulators.
>>>
>>>  Example for i.MX23 SoC:
>>>
>>> @@ -31,6 +40,16 @@ Example for i.MX23 SoC:
>>>          fsl,ave-ctrl = <4>;
>>>          fsl,ave-delay = <2>;
>>>          fsl,settling = <10>;
>>> +
>>> +        isrc_lradc0: ISRC0 {
>>> +            regulator-max-microamp = <300>;
>>> +        };
>>> +
>>> +        isrc_lradc1: ISRC1 {
>>> +            regulator-max-microamp = <120>;
>>> +            regulator-min-microamp = <120>;
>>> +            regulator-always-on;
>>> +        };
>>
>> IMHO the binding should represent the direct connection between the
>> current source and the physical channel. I think a node label isn't
>> enough. Unfortunately i don't have an idea to do it the "right way".
> 
> I strictly followed the names of the data sheet here: imx23 and imx28
> reference manuals both call the current sources ISRC0 and ISRC1 even
> if they are attached to different channels of the ADC. I think
> inventing some ISRC6 for imx28 would do more harm then good.
So just to check... These two current sources are effectively
pushing current out of the ADC input pin?  Assumption being that
this causes an appropriate voltage across a component between there
and 0V?

I wonder if we are better off not treating these as regulators at
all - whilst you could in theory use them for general purposes, it
would be a bit nuts and sometimes the 'it is nuts argument' is
enough to mean we don't support something :)

I wouldn't have any problem with an additional attribute for the
adc channels - maybe something like...

in_voltage6_sourcecurrent?  Then the control could be pushed to
userspace. 

Or if it only makes sense to do it as a fixed value in DT then
define optional child nodes for the individual channels, with
the relevant ones have current-source-microamp or
something like that as an parameter.

What do you think?

Jonathan

> 
>>>      };
>>>
>>>  Example for i.MX28 SoC:
>>> @@ -44,4 +63,14 @@ Example for i.MX28 SoC:
>>>          fsl,ave-ctrl = <4>;
>>>          fsl,ave-delay = <2>;
>>>          fsl,settling = <10>;
>>> +
>>> +        isrc_lradc0: ISRC0 {
>>> +            regulator-max-microamp = <300>;
>>> +        };
>>> +
>>> +        isrc_lradc6: ISRC1 {
>>> +            regulator-max-microamp = <120>;
>>> +            regulator-min-microamp = <120>;
>>> +            regulator-always-on;
>>> +        };
>>>      };
>>> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
>>> index 5937030..1968d1c 100644
>>> --- a/drivers/iio/adc/Kconfig
>>> +++ b/drivers/iio/adc/Kconfig
>>> @@ -319,6 +319,7 @@ config MXS_LRADC
>>>          tristate "Freescale i.MX23/i.MX28 LRADC"
>>>          depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM
>>>          depends on INPUT
>>> +        depends on REGULATOR
>>
>> Any chance to avoid this dependency for an optional feature?
> 
> I haven't looked into it yet, but I expect that that the mfd
> conversion will avoid this neatly.
> 
> Thanks,
> Harald
> 
>> Stefan
>>
>>>          select STMP_DEVICE
>>>          select IIO_BUFFER
>>>          select IIO_TRIGGERED_BUFFER
> 



From pavel at ucw.cz  Wed May  4 00:18:01 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Wed, 4 May 2016 09:18:01 +0200
Subject: [PATCH v2 0/4] Patches to allow consistent mmc / mmcblk
 numbering w/ device tree
In-Reply-To: <20160429181248.GW19428@n2100.arm.linux.org.uk>
References: <1461951139-6109-1-git-send-email-dianders@chromium.org>
 <20160429181248.GW19428@n2100.arm.linux.org.uk>
Message-ID: <20160504071801.GA17045@amd>

On Fri 2016-04-29 19:12:48, Russell King - ARM Linux wrote:
> On Fri, Apr 29, 2016 at 10:32:15AM -0700, Douglas Anderson wrote:
> > This series picks patches from various different places to produce what
> > I consider the best solution to getting consistent mmc and mmcblk
> > ordering.
> > 
> > Why consistent ordering and why not just use UUIDs?  IMHO consistent
> > ordering solves a few different problems:
> 
> NAK.  Really.  Use UUIDs, that's the proper solution here.

Except that UUIDs do not solve the problem.

You have just booted of nfsroot, and you want to format u-SD card in
the external slot. How do you do that?
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From hverkuil at xs4all.nl  Wed May  4 00:32:14 2016
From: hverkuil at xs4all.nl (Hans Verkuil)
Date: Wed, 4 May 2016 09:32:14 +0200
Subject: [PATCH v10 0/8] Add MT8173 Video Encoder Driver and VPU Driver
In-Reply-To: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
References: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <5729A57E.1080505@xs4all.nl>

Hi Tiffany,

On 05/03/2016 12:11 PM, Tiffany Lin wrote:
> ==============
>  Introduction
> ==============
> 
> The purpose of this series is to add the driver for video codec hw embedded in the Mediatek's MT8173 SoCs.
> Mediatek Video Codec is able to handle video encoding of in a range of formats.
> 
> This patch series also include VPU driver. Mediatek Video Codec driver rely on VPU driver to load,
> communicate with VPU.
> 
> Internally the driver uses videobuf2 framework and MTK IOMMU and MTK SMI both have been merged in v4.6-rc1.
> This patch series need [PATCH v15 8/8] memory: mtk-smi: export mtk_smi_larb_get/put[1] to build as module
> 
> [1]http://lists.infradead.org/pipermail/linux-mediatek/2016-April/005173.html
> 
> ==================
>  Device interface
> ==================
> 
> In principle the driver bases on v4l2 memory-to-memory framework:
> it provides a single video node and each opened file handle gets its own private context with separate
> buffer queues. Each context consist of 2 buffer queues: OUTPUT (for source buffers, i.e. raw video
> frames) and CAPTURE (for destination buffers, i.e. encoded video frames).
> 
> ==============================
>  VPU (Video Processor Unit)
> ==============================
> The VPU driver for hw video codec embedded in Mediatek's MT8173 SOCs.
> It is able to handle video decoding/encoding in a range of formats.
> The driver provides with VPU firmware download, memory management and the communication interface between CPU and VPU.
> For VPU initialization, it will create virtual memory for CPU access and physical address for VPU hw device access. 
> When a decode/encode instance opens a device node, vpu driver will download vpu firmware to the device.
> A decode/encode instant will decode/encode a frame using VPU interface to interrupt vpu to handle decoding/encoding jobs.
> 
> Please have a look at the code and comments will be very much appreciated.
> 
> Change in v10:
> 1. Fix smatch/sparse error message
> 2. Add depends on ARM || ARM64 and MTK_IOMMU in Kconfig

I don't like the ARM or ARM64 dependency since that makes COMPILE_TEST harder.

I removed it here and for the VPU and everything still compiles fine with
sparse and smatch. So I'll drop those dependencies.

Why is the MTK_IOMMU dependency needed? Just curious.

Note that sparse still complains about this:

media-git/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c:261:24: warning: incorrect type in assignment (different base types)

I think this code should be rewritten. Something like this would work
(if I understand the code correctly):

u32 tag = (bs_hdr_len << 5) | 0x10 | not_key;

ac_tag[0] = tag & 0xff;
ac_tag[1] = (tag >> 8) & 0xff;
ac_tag[2] = (tag >> 16) & 0xff;

It's perhaps a bit more verbose, but a lot easier to understand.

I'm accepting this driver but I'll remove the ARM || ARM64 dependency. Can
you post a follow-up patch for this sparse warning?

Regards,

	Hans


> 
> VPU part
> 1. Fix smatch/sparse error message
> 2. Use totalram_pages instead of max_pfn to decide VPU 4GB mode
> 3. Protect variable "fw_load"
> 4. Add depends on ARM || ARM64 in Kconfig
> 
> Change in v9:
> 1. Rename idx in mtk_vcodec_ctx to id and curr_max_idx in mtk_vcodec_dev to id_counter.
> 2. Refine fops_vcodec_open
> 
> VPU part
> Merge Julia Lawall's fixes to "[PATCH v9 2/8] [media] VPU: mediatek: support Mediatek VPU"
> 1.[PATCH] VPU: mediatek: fix simple_open.cocci warnings 
> 2.[PATCH] VPU: mediatek: fix platform_no_drv_owner.cocci warnings
> 
> Change in v8:
> 1. Refine indentation
> 2. Refine colorspace information process vidioc_try_fmt_vid_out_mplane
> 3. Remove instance_mask in mtk_vcodec_dev, use curr_max_idx for instance index
> 4. Use kzalloc to allocate ctx
> 5. Refine fops_vcodec_open
> 
> VPU Part
> 1. Refine vpu_load_firmware
> 
> Change in v7:
> 1. Rebase against the master branch of git://linuxtv.org/media_tree.git
> 2. Add ycbcr_enc, quantization and xfer_func in try_fmt, g_fmt, s_fmt
> 3. Merge h264_enc and vp8_enc to venc directory
> 
> Change in v6:
> 1. Add synchronization access protect between irq handler and work thread
> 2. Add DMA_ATTR_ALLOC_SINGLE_PAGES support
> 3. S_FMT will return coded_width, coded_height, so user space could allocate correct size memory that HW required
> 4. merge h264/vp8 enc ap and md32 ipi msg
> 5. separate h264/vp8 enc gop_size and intra_period handle
> 6. remove sizeimage relative code in work buffer function
> 7. Refine makefile to build as an module
> 8. Code clean up
> 
> VPU Part
> 1. export symbols for building VPU as an module
> 2. change function from "wait_event_interruptible_timeout" to "wait_event_timeout" since
>    CPU needs to wait for ACK from VPU even if it was interrupted by a signal
> 
> v4l2-compliance test output:
> localhost Encode # ./v4l2-compliance -d /dev/video1
> Driver Info:
>         Driver name   : mtk-vcodec-enc
>         Card type     : platform:mt8173
>         Bus info      : platform:mt8173
>         Driver version: 4.4.0
>         Capabilities  : 0x84204000
>                 Video Memory-to-Memory Multiplanar
>                 Streaming
>                 Extended Pix Format
>                 Device Capabilities
>         Device Caps   : 0x04204000
>                 Video Memory-to-Memory Multiplanar
>                 Streaming
>                 Extended Pix Format
> 
> Compliance test for device /dev/video1 (not using libv4l2):
> 
> Required ioctls:
>         test VIDIOC_QUERYCAP: OK
> 
> Allow for multiple opens:
>         test second video open: OK
>         test VIDIOC_QUERYCAP: OK
>         test VIDIOC_G/S_PRIORITY: OK
> 
> Debug ioctls:
>         test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
>         test VIDIOC_LOG_STATUS: OK (Not Supported)
> 
> Input ioctls:
>         test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
>         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>         test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
>         test VIDIOC_ENUMAUDIO: OK (Not Supported)
>         test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
>         test VIDIOC_G/S_AUDIO: OK (Not Supported)
>         Inputs: 0 Audio Inputs: 0 Tuners: 0
> 
> Output ioctls:
>         test VIDIOC_G/S_MODULATOR: OK (Not Supported)
>         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>         test VIDIOC_ENUMAUDOUT: OK (Not Supported)
>         test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
>         test VIDIOC_G/S_AUDOUT: OK (Not Supported)
>         Outputs: 0 Audio Outputs: 0 Modulators: 0
> 
> Input/Output configuration ioctls:
>         test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
>         test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
>         test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
>         test VIDIOC_G/S_EDID: OK (Not Supported)
> 
>         Control ioctls:
>                 test VIDIOC_QUERYCTRL/MENU: OK
>                 test VIDIOC_G/S_CTRL: OK
>                 test VIDIOC_G/S/TRY_EXT_CTRLS: OK
>                 test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
>                 test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>                 Standard Controls: 12 Private Controls: 0
> 
>         Format ioctls:
>                 test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
>                 test VIDIOC_G/S_PARM: OK
>                 test VIDIOC_G_FBUF: OK (Not Supported)
>                 test VIDIOC_G_FMT: OK
>                 test VIDIOC_TRY_FMT: OK
>                 test VIDIOC_S_FMT: OK
>                 test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> 
>         Codec ioctls:
>                 test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
>                 test VIDIOC_G_ENC_INDEX: OK (Not Supported)
>                 test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
> 
>         Buffer ioctls:
>                 test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
>                 test VIDIOC_EXPBUF: OK
> Total: 38, Succeeded: 38, Failed: 0, Warnings: 0
> 
> 
> v4l2-compliance test output:
> localhost ~ # /usr/bin/v4l2-compliance -d /dev/video1
>  
> Change in v5:
> Vcodec Part
> 1. Pass checkpatch and v4l2-compliance test
> 2. Remove unused g/s_selection for now
> 3. add vidioc_g_parm support
> 4. add vidioc_create_bufs and vidioc_prepare_buf support
> 5. Remove instance check in fops_vcodec_open
> 6. Fix comments for data structure and code
> 7. Refine venc, venc_lt clock source name in devicetree and binding document
> 8. Fix Author information and copyright information
> 9. Refine code according to review comments
> 
> VPU Part
> 
> v4l2-compliance test output:
> localhost ~ # /usr/bin/v4l2-compliance -d /dev/video1
> Driver Info:
>         Driver name   : mtk-vcodec-enc
>         Card type     : platform:mt8173
>         Bus info      : platform:mt8173
>         Driver version: 4.4.0
>         Capabilities  : 0x84204000
>                 Video Memory-to-Memory Multiplanar
>                 Streaming
>                 Extended Pix Format
>                 Device Capabilities
>         Device Caps   : 0x04204000
>                 Video Memory-to-Memory Multiplanar
>                 Streaming
>                 Extended Pix Format
> 
> Compliance test for device /dev/video1 (not using libv4l2):
> 
> Required ioctls:
>         test VIDIOC_QUERYCAP: OK
> 
> Allow for multiple opens:
>         test second video open: OK
>         test VIDIOC_QUERYCAP: OK
>         test VIDIOC_G/S_PRIORITY: OK
> 
> Debug ioctls:
>         test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
>         test VIDIOC_LOG_STATUS: OK (Not Supported)
> 
> Input ioctls:
>         test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
>         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>         test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
>         test VIDIOC_ENUMAUDIO: OK (Not Supported)
>         test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
>         test VIDIOC_G/S_AUDIO: OK (Not Supported)
>         Inputs: 0 Audio Inputs: 0 Tuners: 0
> 
> Output ioctls:
>         test VIDIOC_G/S_MODULATOR: OK (Not Supported)
>         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>         test VIDIOC_ENUMAUDOUT: OK (Not Supported)
>         test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
>         test VIDIOC_G/S_AUDOUT: OK (Not Supported)
>         Outputs: 0 Audio Outputs: 0 Modulators: 0
> 
> Input/Output configuration ioctls:
>         test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
>         test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
>         test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
>         test VIDIOC_G/S_EDID: OK (Not Supported)
> 
>         Control ioctls:
>                 test VIDIOC_QUERYCTRL/MENU: OK
>                 test VIDIOC_G/S_CTRL: OK
>                 test VIDIOC_G/S/TRY_EXT_CTRLS: OK
>                 test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
>                 test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>                 Standard Controls: 12 Private Controls: 0
> 
>         Format ioctls:
>                 test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
>                 test VIDIOC_G/S_PARM: OK
>                 test VIDIOC_G_FBUF: OK (Not Supported)
>                 test VIDIOC_G_FMT: OK
>                 test VIDIOC_TRY_FMT: OK
>                 test VIDIOC_S_FMT: OK
>                 test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> 
>         Codec ioctls:
>                 test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
>                 test VIDIOC_G_ENC_INDEX: OK (Not Supported)
>                 test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
> 
>         Buffer ioctls:
>                 test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
>                 test VIDIOC_EXPBUF: OK
> 
> 
> Total: 38, Succeeded: 38, Failed: 0, Warnings: 0
> 
> 
> Change in v4:
> Vcodec Part
> 1. Remove MTK_ENCODE_PARAM_SKIP_FRAME support
> 2. Remove MTK_ENCODE_PARAM_FRAME_TYPE and change to use V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME[3]
> 3. Refine Encoder HW clock source
> 4. Refine debug log
> 5. Add watchdog support
> 6. With patch "media: v4l2-compat-ioctl32: fix missing length copy in put_v4l2_buffer32"[4],
> v4l2-compliance test passed[5] in v4.4-rc5 
> 
> VPU Part
> 1. These two patches were Acked-by: Rob Herring <robh <at> kernel.org> in v3
>    [PATCH v3 1/8] dt-bindings: Add a binding for Mediatek Video Processor
>    [PATCH v3 3/8] arm64: dts: mediatek: Add node for Mediatek Video Processor Unit
>    Because we were wrong about how the hardware works, there is no connection between VPU and IOMMU HW
>    We remove VPU attaching to IOMMU
> 2. Support VPU running on 4GB DRAM system
> 3. Support VPU watchdog reset
> 4. Refine for coding style 
> 
> [3]https://patchwork.linuxtv.org/patch/32670/
> [4] https://patchwork.linuxtv.org/patch/32631/
> [5]localhost ~ # /usr/bin/v4l2-compliance -d /dev/video1
> Driver Info:
>         Driver name   : mtk-vcodec-en
>         Card type     : platform:mt817
>         Bus info      : platform:mt817
>         Driver version: 4.4.0
>         Capabilities  : 0x84204000
>                 Video Memory-to-Memory Multiplanar
>                 Streaming
>                 Extended Pix Format
>                 Device Capabilities
>         Device Caps   : 0x04204000
>                 Video Memory-to-Memory Multiplanar
>                 Streaming
>                 Extended Pix Format
> 
> Compliance test for device /dev/video1 (not using libv4l2):
> 
> Required ioctls:
>         test VIDIOC_QUERYCAP: OK
> 
> Allow for multiple opens:
>         test second video open: OK
>         test VIDIOC_QUERYCAP: OK
>         test VIDIOC_G/S_PRIORITY: OK
> 
> Debug ioctls:
>         test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
>         test VIDIOC_LOG_STATUS: OK (Not Supported)
> 
> Input ioctls:
>         test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
>         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>         test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
>         test VIDIOC_ENUMAUDIO: OK (Not Supported)
>         test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
>         test VIDIOC_G/S_AUDIO: OK (Not Supported)
>         Inputs: 0 Audio Inputs: 0 Tuners: 0
> 
> Output ioctls:
>         test VIDIOC_G/S_MODULATOR: OK (Not Supported)
>         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>         test VIDIOC_ENUMAUDOUT: OK (Not Supported)
>         test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
>         test VIDIOC_G/S_AUDOUT: OK (Not Supported)
>         Outputs: 0 Audio Outputs: 0 Modulators: 0
> 
> Input/Output configuration ioctls:
>         test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
>         test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
>         test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
>         test VIDIOC_G/S_EDID: OK (Not Supported)
> 
>         Control ioctls:
>                 test VIDIOC_QUERYCTRL/MENU: OK
>                 test VIDIOC_G/S_CTRL: OK
>                 test VIDIOC_G/S/TRY_EXT_CTRLS: OK
>                 test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
>                 test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>                 Standard Controls: 12 Private Controls: 0
> 
>         Format ioctls:
>                 test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
>                 test VIDIOC_G/S_PARM: OK (Not Supported)
>                 test VIDIOC_G_FBUF: OK (Not Supported)
>                 test VIDIOC_G_FMT: OK
>                 test VIDIOC_TRY_FMT: OK
>                 test VIDIOC_S_FMT: OK
>                 test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> 
>         Codec ioctls:
>                 test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
>                 test VIDIOC_G_ENC_INDEX: OK (Not Supported)
>                 test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
> 
>         Buffer ioctls:
>                 warn: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(475):
> VIDIOC_CREATE_BUFS not supported
>                 warn: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(475):
> VIDIOC_CREATE_BUFS not supported
>                 test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
>                 test VIDIOC_EXPBUF: OK
> 
> Total: 38, Succeeded: 38, Failed: 0, Warnings: 2
> 
> Change in v3:
> 1.Refine code to pass v4l2-compliance test, now it still has 2 issues 2.Refine code according to latest MTK
> IOMMU patches[1] 3.Remove MFC51 specific CIDs and add MTK specific CIDs for for keyframe and
>   skip I-frame
> 4.Refine code according to review comments
> 
> Below is the v1.6 version v4l2-compliance report for the mt8173 encoder driver.
> Now there are still 2 test fail in v1.6.
> For VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF, we directly use v4l2_m2m_ioctl_* functions, but it still
> fail. It pass in kernel 3.18 but fail in kernel 4.4.
> We will try v1.8 in next version.
> VIDIOC_EXPBUF is becuase we support all three memory types VB2_DMABUF, VB2_MMAP and VB2_USERPTR.
> VIDIOC_EXPBUF only allowed when only VB2_MMAP supported.
> localhost ~ # /usr/bin/v4l2-compliance -d /dev/video1 Driver Info:
>         Driver name   : mtk-vcodec-en
>         Card type     : platform:mt817
>         Bus info      : platform:mt817
>         Driver version: 4.4.0
>         Capabilities  : 0x84204000
>                 Video Memory-to-Memory Multiplanar
>                 Streaming
>                 Extended Pix Format
>                 Device Capabilities
>         Device Caps   : 0x04204000
>                 Video Memory-to-Memory Multiplanar
>                 Streaming
>                 Extended Pix Format
> 
> Compliance test for device /dev/video1 (not using libv4l2):
> 
> Required ioctls:
>         test VIDIOC_QUERYCAP: OK
> 
> Allow for multiple opens:
>         test second video open: OK
>         test VIDIOC_QUERYCAP: OK
>         test VIDIOC_G/S_PRIORITY: OK
> 
> Debug ioctls:
>         test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
>         test VIDIOC_LOG_STATUS: OK (Not Supported)
> 
> Input ioctls:
>         test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
>         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>         test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
>         test VIDIOC_ENUMAUDIO: OK (Not Supported)
>         test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
>         test VIDIOC_G/S_AUDIO: OK (Not Supported)
>         Inputs: 0 Audio Inputs: 0 Tuners: 0
> 
> Output ioctls:
>         test VIDIOC_G/S_MODULATOR: OK (Not Supported)
>         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>         test VIDIOC_ENUMAUDOUT: OK (Not Supported)
>         test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
>         test VIDIOC_G/S_AUDOUT: OK (Not Supported)
>         Outputs: 0 Audio Outputs: 0 Modulators: 0
> 
> Input/Output configuration ioctls:
>         test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
>         test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
>         test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
>         test VIDIOC_G/S_EDID: OK (Not Supported)
> 
>         Control ioctls:
>                 test VIDIOC_QUERYCTRL/MENU: OK
>                 test VIDIOC_G/S_CTRL: OK
>                 test VIDIOC_G/S/TRY_EXT_CTRLS: OK
>                 test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
>                 test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>                 Standard Controls: 11 Private Controls: 2
> 
>         Format ioctls:
>                 test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
>                 test VIDIOC_G/S_PARM: OK (Not Supported)
>                 test VIDIOC_G_FBUF: OK (Not Supported)
>                 test VIDIOC_G_FMT: OK
>                 test VIDIOC_TRY_FMT: OK
>                 test VIDIOC_S_FMT: OK
>                 test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> 
>         Codec ioctls:
>                 test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
>                 test VIDIOC_G_ENC_INDEX: OK (Not Supported)
>                 test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
> 
>         Buffer ioctls:
>                 fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(266): vp->length
> == 0
>                 fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(335):
> buf.check(Unqueued, i)
>                 fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(420):
> testQueryBuf(node, i, q.g_buffers())
>                 test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: FAIL
>                 fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(500): q.has_expbuf(node)
>                 test VIDIOC_EXPBUF: FAIL
> Total: 38, Succeeded: 36, Failed: 2, Warnings: 0
> 
> Change in v2:
> Vcodec Part
> 1.Remove common and include directory in mtk-vcodec 2.Refine vb2ops_venc_start_streaming and
> vb2ops_venc_stop_streaming and state machine 3.Remove venc_if_init and venc_if_deinit 4.Refine
> debug message 5.Refine lab and vpu decription in mediatek-vcodec.txt
> 
> VPU Part
> 1. Modify VPU Kconfig
> 2. Move encoder header files to other patch sets 3. Remove marcos for extended virtual/iova address 4.
> Change register and variable names 5. Add a reference counter for VPU watchdog 6. Remove one busy waiting
> in function vpu_ipi_send 7. Operate VPU clock in VPU driver (not called by encoder drivers) 8. Refine
> memory mapping, firmware download and extended memory allocation/free functions 9. Release more
> allocated resources in driver remove function
> 
> Andrew-CT Chen (3):
>   dt-bindings: Add a binding for Mediatek Video Processor
>   VPU: mediatek: support Mediatek VPU
>   arm64: dts: mediatek: Add node for Mediatek Video Processor Unit
> 
> Tiffany Lin (5):
>   dt-bindings: Add a binding for Mediatek Video Encoder
>   vcodec: mediatek: Add Mediatek V4L2 Video Encoder Driver
>   vcodec: mediatek: Add Mediatek VP8 Video Encoder Driver
>   vcodec: mediatek: Add Mediatek H264 Video Encoder Driver
>   arm64: dts: mediatek: Add Video Encoder for MT8173
> 
>  .../devicetree/bindings/media/mediatek-vcodec.txt  |   59 +
>  .../devicetree/bindings/media/mediatek-vpu.txt     |   31 +
>  arch/arm64/boot/dts/mediatek/mt8173.dtsi           |   62 +
>  drivers/media/platform/Kconfig                     |   32 +
>  drivers/media/platform/Makefile                    |    4 +
>  drivers/media/platform/mtk-vcodec/Makefile         |   19 +
>  drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h |  338 +++++
>  drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 1288 ++++++++++++++++++++
>  drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h |   58 +
>  .../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c |  454 +++++++
>  .../media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c  |  137 +++
>  .../media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h  |   26 +
>  .../media/platform/mtk-vcodec/mtk_vcodec_intr.c    |   55 +
>  .../media/platform/mtk-vcodec/mtk_vcodec_intr.h    |   27 +
>  .../media/platform/mtk-vcodec/mtk_vcodec_util.c    |   94 ++
>  .../media/platform/mtk-vcodec/mtk_vcodec_util.h    |   87 ++
>  .../media/platform/mtk-vcodec/venc/venc_h264_if.c  |  679 +++++++++++
>  .../media/platform/mtk-vcodec/venc/venc_vp8_if.c   |  481 ++++++++
>  drivers/media/platform/mtk-vcodec/venc_drv_base.h  |   62 +
>  drivers/media/platform/mtk-vcodec/venc_drv_if.c    |  113 ++
>  drivers/media/platform/mtk-vcodec/venc_drv_if.h    |  163 +++
>  drivers/media/platform/mtk-vcodec/venc_ipi_msg.h   |  210 ++++
>  drivers/media/platform/mtk-vcodec/venc_vpu_if.c    |  237 ++++
>  drivers/media/platform/mtk-vcodec/venc_vpu_if.h    |   61 +
>  drivers/media/platform/mtk-vpu/Makefile            |    3 +
>  drivers/media/platform/mtk-vpu/mtk_vpu.c           |  950 +++++++++++++++
>  drivers/media/platform/mtk-vpu/mtk_vpu.h           |  162 +++
>  27 files changed, 5892 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/media/mediatek-vcodec.txt
>  create mode 100644 Documentation/devicetree/bindings/media/mediatek-vpu.txt
>  create mode 100644 drivers/media/platform/mtk-vcodec/Makefile
>  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
>  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
>  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
>  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
>  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
>  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
>  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c
>  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h
>  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
>  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
>  create mode 100644 drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
>  create mode 100644 drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c
>  create mode 100644 drivers/media/platform/mtk-vcodec/venc_drv_base.h
>  create mode 100644 drivers/media/platform/mtk-vcodec/venc_drv_if.c
>  create mode 100644 drivers/media/platform/mtk-vcodec/venc_drv_if.h
>  create mode 100644 drivers/media/platform/mtk-vcodec/venc_ipi_msg.h
>  create mode 100644 drivers/media/platform/mtk-vcodec/venc_vpu_if.c
>  create mode 100644 drivers/media/platform/mtk-vcodec/venc_vpu_if.h
>  create mode 100644 drivers/media/platform/mtk-vpu/Makefile
>  create mode 100644 drivers/media/platform/mtk-vpu/mtk_vpu.c
>  create mode 100644 drivers/media/platform/mtk-vpu/mtk_vpu.h
> 


From linus.walleij at linaro.org  Wed May  4 00:38:50 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 4 May 2016 09:38:50 +0200
Subject: [GIT PULL] Device Tree updated for Ux500 for v4.7
Message-ID: <CACRpkdbjdM=L4DEUZ5fuDPRumXdiztqht1h+zu+UZoJKk1dXoA@mail.gmail.com>

Hi ARM SoC folks,

I guess I should have gotten this out the door earlier, especially
since the patches were around since forever.

Anyways this is a few cleanups of DTS files (use proper includes)
and the assignment of the accelerometers as open drain so they
actually work.

Please pull it in!

Yours,
Linus Walleij

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
tags/ux500-armsoc-v4.7

for you to fetch changes up to 7ba5dd530072d383f713a0fe1e4ffcdc5523ae37:

  ARM: dts: ux500: configure the accelerometers open drain (2016-05-04
09:33:25 +0200)

----------------------------------------------------------------
Devicetree updates for v4.7:
- Use generic include files
- Make accelerometers open drain on the TVK board

----------------------------------------------------------------
Linus Walleij (3):
      ARM: dts: ux500: use the GPIO DT header
      ARM: dts: ux500: use the GIC include header
      ARM: dts: ux500: configure the accelerometers open drain

 arch/arm/boot/dts/ste-ccu9540.dts          |  2 +-
 arch/arm/boot/dts/ste-dbx5x0.dtsi          | 92 +++++++++++++++---------------
 arch/arm/boot/dts/ste-href-stuib.dtsi      |  4 +-
 arch/arm/boot/dts/ste-href-tvk1281618.dtsi | 16 +++---
 arch/arm/boot/dts/ste-hrefprev60.dtsi      |  8 +--
 arch/arm/boot/dts/ste-hrefv60plus.dtsi     |  6 +-
 arch/arm/boot/dts/ste-snowball.dts         | 19 +++---
 7 files changed, 75 insertions(+), 72 deletions(-)


From ulf.hansson at linaro.org  Wed May  4 00:43:38 2016
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Wed, 4 May 2016 09:43:38 +0200
Subject: [v9, 6/7] MAINTAINERS: add entry for Freescale SoC driver
In-Reply-To: <1462332274-13744-7-git-send-email-yangbo.lu@nxp.com>
References: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
 <1462332274-13744-7-git-send-email-yangbo.lu@nxp.com>
Message-ID: <CAPDyKFoh7mfmMYxVxjG6jrRr6CuGKkuxdeON4yxX3yXFEamikg@mail.gmail.com>

On 4 May 2016 at 05:24, Yangbo Lu <yangbo.lu at nxp.com> wrote:
> Add maintainer entry for Freescale SoC driver including
> the QE library and the GUTS driver now. Also add maintainer
> for QE library.
>
> Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>

So I need an ack from Scott and Qiang for this one, then I intend to
queue up the series.

Kind regards
Uffe

> ---
> Changes for v8:
>         - Added this patch
> Changes for v9:
>         - Added linux-arm mail list
>         - Removed GUTS driver entry
> ---
>  MAINTAINERS | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 42e65d1..ce91db7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4622,9 +4622,18 @@ F:       drivers/net/ethernet/freescale/fec_ptp.c
>  F:     drivers/net/ethernet/freescale/fec.h
>  F:     Documentation/devicetree/bindings/net/fsl-fec.txt
>
> +FREESCALE SOC DRIVER
> +M:     Scott Wood <oss at buserror.net>
> +L:     linuxppc-dev at lists.ozlabs.org
> +L:     linux-arm-kernel at lists.infradead.org
> +S:     Maintained
> +F:     drivers/soc/fsl/
> +F:     include/linux/fsl/
> +
>  FREESCALE QUICC ENGINE LIBRARY
> +M:     Qiang Zhao <qiang.zhao at nxp.com>
>  L:     linuxppc-dev at lists.ozlabs.org
> -S:     Orphan
> +S:     Maintained
>  F:     drivers/soc/fsl/qe/
>  F:     include/soc/fsl/*qe*.h
>  F:     include/soc/fsl/*ucc*.h
> --
> 2.1.0.27.g96db324
>


From marc.zyngier at arm.com  Wed May  4 00:49:55 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 4 May 2016 08:49:55 +0100
Subject: [PATCH 2/2] irqchip/gic-v2m: Add workaround for Broadcom NS2
 GICv2m erratum
In-Reply-To: <1462319245-32532-3-git-send-email-ray.jui@broadcom.com>
References: <1462319245-32532-1-git-send-email-ray.jui@broadcom.com>
 <1462319245-32532-3-git-send-email-ray.jui@broadcom.com>
Message-ID: <5729A9A3.6070207@arm.com>

On 04/05/16 00:47, Ray Jui wrote:
> Alex Barba <alex.barba at broadcom.com> discovered Broadcom NS2 GICv2m
> implementation has an erratum where the MSI data needs to be the SPI
> number subtracted by an offset of 32, for the correct MSI interrupt to
> be triggered.
> 
> We are aware that APM X-Gene GICv2m has a similar erratum where the
> MSI data needs to be the offset from the spi_start. While APM's workaround
> is triggered based on readings from the MSI_IIDR register, this patch
> contains a more general solution by allowing this offset to be
> specified with an optional DT property 'arm,msi-offset-spi'. This patch
> also maintains compatibility with existing APM platforms

It may be more generic, but it also fails to deal with less capable
firmware implementations. In contrast, reading MSI_IIDR is always
possible (assuming you have a unique ID for this v2m implementation).

If you cannot uniquely identify it using an ID register, the usual
alternative is to have a new "compatible" string identifying the
defective part, and set the offset based on this string. This still
fails the ACPI test, but is the least invasive DT-wise.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From arnaud.pouliquen at st.com  Wed May  4 00:52:19 2016
From: arnaud.pouliquen at st.com (Arnaud Pouliquen)
Date: Wed, 4 May 2016 09:52:19 +0200
Subject: [PATCH 09/18] ASoC: sti: Update DT example to match the driver
 code
In-Reply-To: <5608365.uloflbeuqO@wuerfel>
References: <1461236675-10176-1-git-send-email-peter.griffin@linaro.org>
 <6161197.8XCk69TI60@wuerfel>
 <20160426111532.GA5457@griffinp-ThinkPad-X1-Carbon-2nd>
 <5608365.uloflbeuqO@wuerfel>
Message-ID: <5729AA33.6020305@st.com>

hello Arnd, peter,

On 04/26/2016 01:44 PM, Arnd Bergmann wrote:
> On Tuesday 26 April 2016 12:15:32 Peter Griffin wrote:
>>>
>>>> If not what would you recommend instead? 
>>>
>>> It's still not clear to me what that bit in the syscfg register
>>> is for. Given the error message about "sti-audio-clk-glue",
>>> I suspect that this is actually a clock controller and that
>>> it should be using the clock binding with a separate driver
>>> instead of manipulating the regmap directly from the audio driver.
>>
>> Luckily I do have the datasheet for the audio-glue sysconf register.
>>
>> It says: -
>>
>> [11:8] PCM_CLK_SEL: Selects the frequency synthesizer clock or the external
>> PCM clock for each channel.
>>
>> The driver only ever sets this to 1 which selects the frequency synthesizer
>> clock. So the bitfield of the register which the driver is using (PCM_CLK_SEL)
>> is a clock mux.
> 
> Ok, that sounds like it could be either a really simple clock driver
> with just a few lines, or integrated into an existing clock driver
> if you already have one for this syscon node.
> 
> 	Arnd
> 
FYI, Name of this glue is related to the register name. But it does not
concern only clock...
 This glue register is used to :
- select clock source ( clock framework or external clock from GPIO)
=> one bit field per IP instance (player->clk_sel)
- select uniperiph player IP instance for PCM out.
(http://www.spinics.net/lists/alsa-devel/msg49034.html)

Regards
Arnaud


From kernel at martin.sperl.org  Wed May  4 00:53:05 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Wed,  4 May 2016 07:53:05 +0000
Subject: [PATCH V5] clk: bcm2835: mark enabled clocks and pll with
 CLK_ENABLE_HAND_OFF
Message-ID: <1462348385-16167-1-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

The bcm2835 firmware enables several clocks and plls before
booting the linux kernel.

These plls should never get disabled as it may result in a
stopped system clock and more.

So during probing we check if the clock and plls are enabled
and if it is then mark that clock/pll with CLK_ENABLE_HAND_OFF.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 drivers/clk/bcm/clk-bcm2835.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

Note: This requires the CLK_ENABLE_HAND_OFF patch to be applied.

diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 0fc71cb..0663b6c 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1211,6 +1211,15 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
 	divider->cprman = cprman;
 	divider->data = data;
 
+	/* if the pll-divider is running, then enable CLK_ENABLE_HAND_OFF */
+	if ((cprman_read(cprman, data->a2w_reg) &
+	     A2W_PLL_CHANNEL_DISABLE) == 0) {
+		dev_dbg(cprman->dev,
+			"found firmware enabled pll_div %s - enabling hand off\n",
+			data->name);
+		init.flags |= CLK_ENABLE_HAND_OFF;
+	}
+
 	clk = devm_clk_register(cprman->dev, &divider->div.hw);
 	if (IS_ERR(clk))
 		return clk;
@@ -1262,6 +1271,14 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
 		init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
 	}
 
+	/* if the clock is running, then enable CLK_ENABLE_HAND_OFF */
+	if (cprman_read(cprman, data->ctl_reg) & CM_ENABLE) {
+		dev_dbg(cprman->dev,
+			"found firmware enabled clock %s - enabling hand off\n",
+			data->name);
+		init.flags |= CLK_ENABLE_HAND_OFF;
+	}
+
 	clock = devm_kzalloc(cprman->dev, sizeof(*clock), GFP_KERNEL);
 	if (!clock)
 		return NULL;
-- 
2.1.4



From felipe.balbi at linux.intel.com  Wed May  4 01:03:03 2016
From: felipe.balbi at linux.intel.com (Felipe Balbi)
Date: Wed, 04 May 2016 11:03:03 +0300
Subject: [PATCH] usb: xhci-mtk: fixup mouse wakeup failure during system
 suspend
In-Reply-To: <1462324873.11651.57.camel@mhfsdcap03>
References: <1461204293-18243-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462261458.11651.7.camel@mhfsdcap03> <87vb2vfujq.fsf@intel.com>
 <1462266591.11651.34.camel@mhfsdcap03> <87mvo7fpuc.fsf@intel.com>
 <1462324873.11651.57.camel@mhfsdcap03>
Message-ID: <871t5ifdxk.fsf@intel.com>


Hi,

chunfeng yun <chunfeng.yun at mediatek.com> writes:
> On Tue, 2016-05-03 at 12:33 +0300, Felipe Balbi wrote:
>> Hi,
>> 
>> chunfeng yun <chunfeng.yun at mediatek.com> writes:
>> >> chunfeng yun <chunfeng.yun at mediatek.com> writes:
>> >> > On Thu, 2016-04-21 at 10:04 +0800, Chunfeng Yun wrote:
>> >> >> Click mouse after xhci suspend completion but before system suspend
>> >> >> completion, system will not be waken up by mouse if the duration of
>> >> >> them is larger than 20ms which is the device UFP's resume signaling
>> >> 
>> >> what is "them" here ? The duration of what is longer than 20ms ?
>> > They are "xhci suspend completion" and "system suspend completion";
>> >
>> > It's time duration
>> 
>> okay. So if xhci suspend takes longer than 20ms your SPM doesn't see a
>> wakeup ?
> It is not the time of xhci suspend consumed, but is the time of duration
> from xhci suspend completion to system suspend completion(after BOOT-CPU
> is turned off, SPM will be enabled to receive wakeup event)

Okay, so SPM will be the entity actually handling wakeups, right ? I'm
assuming something like this happens:

echo mem > /sys/power/state
 /* start suspending devices */
  xhci_suspend()
 /* all devices suspended */
 enable_spm()

so, if a mouse button is pressed after xhci_suspend() returns but before
enable_spm() runs, then we're gonna miss that event, am I right ?

I can't think of any way to sort this out. Let's ask on linux-pm (I've
added linux-pm to Cc list)

>> >> >> lasted. Another reason is that the SPM is not enabled before system
>> >> 
>> >> what's SPM ?
>> > It is System Power Management which is powered off when system is
>> > running in normal mode, and is powered on when system enters suspend
>> > mode. It is used to wakeup system when some wakeup sources, such as
>> > bluetooth or powerkey etc, tigger wakeup event.
>> 
>> okay, thanks
>> 
>> >> >> suspend compeltion, this causes SPM also not notice the resume signal.
>> >>            ^^^^^^^^^^
>> >>            completion
>> >> 
>> >> >> So in order to reduce the duration less than 20ms, make use of
>> >> >> syscore's suspend/resume interface.
>> >> 
>> >> no, this is the wrong approach
>> > But it seems only one workable approach from software side
>> 
>> I wouldn't say that. It seems to me SPM should be enabled earlier.
> Yes, but normally SPM should be enabled after all CPUS are turned off,
> so it's difficult to do that, I mean enable SPM before turning off CPUS

is it a requirement that SPM should be enabled only after all CPUs are
turned off ? If that's the case, then any device in the system might
have missed wakeups. This doesn't seem like a good design to me; unless
I'm missing something...

>> >> >> Because the syscore runs on irq disabled context, and xhci's
>> >> >> suspend/resume calls some sleeping functions, enable local irq
>> >> >> and then disable it during suspend/resume. This may be not a problem,
>> >> >> since only boot CPU is runing.
>> >> 
>> >> another problem :) calling local_irq_{enable,disable}() is an indication
>> >> that something's wrong.
>> > Oh!
>> >
>> > BTW: There will be warning logs if they are not called.
>> 
>> yeah, I got that :-) But it's still wrong to use
>> local_irq_{enable,disable}() the way you're using them :-)
> Yes
>
> Thank you very much.
>> 
>
>

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/43c16e2f/attachment-0001.sig>

From tn at semihalf.com  Wed May  4 01:10:58 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Wed, 4 May 2016 10:10:58 +0200
Subject: [PATCH V6 01/13] pci, acpi, x86, ia64: Move ACPI host bridge
 device companion assignment to core code.
In-Reply-To: <20160427024537.GH6789@localhost>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-2-git-send-email-tn@semihalf.com>
 <20160427024537.GH6789@localhost>
Message-ID: <5729AE92.2090106@semihalf.com>

On 27.04.2016 04:45, Bjorn Helgaas wrote:
> [question for Rafael below]
>
> On Fri, Apr 15, 2016 at 07:06:36PM +0200, Tomasz Nowicki wrote:
>> Currently we have two platforms (x86 & ia64) capable of PCI ACPI host
>> bridge initialization. They both use arch-specific sysdata to pass down
>> parent device reference and both rely on NULL parent in pci_create_root_bus()
>> to validate sysdata content.
>>
>> It looks hacky and prevents us from getting some firmware specific
>> info for PCI host controller based on its acpi_device structure
>> in generic pci_create_root_bus() function. However, we overcome that
>> blocker by passing down parent device via pci_create_root_bus parameter
>> (as the ACPI device type). Then we use ACPI_COMPANION_SET in core code
>> for ACPI boot method only. ACPI_COMPANION_SET is safe to run for all
>> cases DT, ACPI and DT&ACPI.
>>
>> Since now PCI core code is setting ACPI companion device for us,
>> x86 & ia64 specific ACPI companion device setting turns out to be dead now.
>> We can get rid of it, including related companion reference from
>> PCI sysdata structure. Aslo, PCI_CONTROLLER macro cannot return valid
>> companion device anymore. Therefore we need to convert its usage to
>> ACPI_COMPANION.
>>
>> Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
>> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
>> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
>> Tested-by: Duc Dang <dhdang at apm.com>
>> Tested-by: Dongdong Liu <liudongdong3 at huawei.com>
>> Tested-by: Hanjun Guo <hanjun.guo at linaro.org>
>> Tested-by: Graeme Gregory <graeme.gregory at linaro.org>
>> Tested-by: Sinan Kaya <okaya at codeaurora.org>
>> ---
>>   arch/ia64/hp/common/sba_iommu.c    |  2 +-
>>   arch/ia64/include/asm/pci.h        |  1 -
>>   arch/ia64/pci/pci.c                | 16 ----------------
>>   arch/ia64/sn/kernel/io_acpi_init.c |  4 ++--
>>   arch/x86/include/asm/pci.h         |  3 ---
>>   arch/x86/pci/acpi.c                | 17 -----------------
>>   drivers/acpi/pci_root.c            |  7 ++++++-
>>   drivers/pci/probe.c                |  2 ++
>>   8 files changed, 11 insertions(+), 41 deletions(-)
>>
>> diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
>> index a6d6190..78e4444 100644
>> --- a/arch/ia64/hp/common/sba_iommu.c
>> +++ b/arch/ia64/hp/common/sba_iommu.c
>> @@ -1981,7 +1981,7 @@ sba_connect_bus(struct pci_bus *bus)
>>   	if (PCI_CONTROLLER(bus)->iommu)
>>   		return;
>>
>> -	handle = acpi_device_handle(PCI_CONTROLLER(bus)->companion);
>> +	handle = acpi_device_handle(ACPI_COMPANION(bus->bridge));
>>   	if (!handle)
>>   		return;
>>
>> diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
>> index c0835b0..12423f4 100644
>> --- a/arch/ia64/include/asm/pci.h
>> +++ b/arch/ia64/include/asm/pci.h
>> @@ -63,7 +63,6 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
>>   #define pci_legacy_write platform_pci_legacy_write
>>
>>   struct pci_controller {
>> -	struct acpi_device *companion;
>>   	void *iommu;
>>   	int segment;
>>   	int node;		/* nearest node with memory or NUMA_NO_NODE for global allocation */
>> diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
>> index 8f6ac2f..978d6af 100644
>> --- a/arch/ia64/pci/pci.c
>> +++ b/arch/ia64/pci/pci.c
>> @@ -301,28 +301,12 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>>   	}
>>
>>   	info->controller.segment = root->segment;
>> -	info->controller.companion = device;
>>   	info->controller.node = acpi_get_node(device->handle);
>>   	INIT_LIST_HEAD(&info->io_resources);
>>   	return acpi_pci_root_create(root, &pci_acpi_root_ops,
>>   				    &info->common, &info->controller);
>>   }
>>
>> -int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
>> -{
>> -	/*
>> -	 * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL
>> -	 * here, pci_create_root_bus() has been called by someone else and
>> -	 * sysdata is likely to be different from what we expect.  Let it go in
>> -	 * that case.
>> -	 */
>> -	if (!bridge->dev.parent) {
>> -		struct pci_controller *controller = bridge->bus->sysdata;
>> -		ACPI_COMPANION_SET(&bridge->dev, controller->companion);
>> -	}
>> -	return 0;
>> -}
>> -
>>   void pcibios_fixup_device_resources(struct pci_dev *dev)
>>   {
>>   	int idx;
>> diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c
>> index 231234c..e454492 100644
>> --- a/arch/ia64/sn/kernel/io_acpi_init.c
>> +++ b/arch/ia64/sn/kernel/io_acpi_init.c
>> @@ -132,7 +132,7 @@ sn_get_bussoft_ptr(struct pci_bus *bus)
>>   	struct acpi_resource_vendor_typed *vendor;
>>
>>
>> -	handle = acpi_device_handle(PCI_CONTROLLER(bus)->companion);
>> +	handle = acpi_device_handle(ACPI_COMPANION(bus->bridge));
>>   	status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
>>   					  &sn_uuid, &buffer);
>>   	if (ACPI_FAILURE(status)) {
>> @@ -360,7 +360,7 @@ sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
>>   	acpi_status status;
>>   	struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>>
>> -	rootbus_handle = acpi_device_handle(PCI_CONTROLLER(dev)->companion);
>> +	rootbus_handle = acpi_device_handle(ACPI_COMPANION(dev->bus->bridge));
>>           status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL,
>>                                          &segment);
>>           if (ACPI_SUCCESS(status)) {
>> diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
>> index 9ab7507..24de07d 100644
>> --- a/arch/x86/include/asm/pci.h
>> +++ b/arch/x86/include/asm/pci.h
>> @@ -14,9 +14,6 @@
>>   struct pci_sysdata {
>>   	int		domain;		/* PCI domain */
>>   	int		node;		/* NUMA node */
>> -#ifdef CONFIG_ACPI
>> -	struct acpi_device *companion;	/* ACPI companion device */
>> -#endif
>>   #ifdef CONFIG_X86_64
>>   	void		*iommu;		/* IOMMU private data */
>>   #endif
>> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
>> index 3cd6983..f4ca17a 100644
>> --- a/arch/x86/pci/acpi.c
>> +++ b/arch/x86/pci/acpi.c
>> @@ -340,7 +340,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>>   		struct pci_sysdata sd = {
>>   			.domain = domain,
>>   			.node = node,
>> -			.companion = root->device
>>   		};
>>
>>   		memcpy(bus->sysdata, &sd, sizeof(sd));
>> @@ -355,7 +354,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>>   		else {
>>   			info->sd.domain = domain;
>>   			info->sd.node = node;
>> -			info->sd.companion = root->device;
>>   			bus = acpi_pci_root_create(root, &acpi_pci_root_ops,
>>   						   &info->common, &info->sd);
>>   		}
>> @@ -373,21 +371,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>>   	return bus;
>>   }
>>
>> -int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
>> -{
>> -	/*
>> -	 * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL
>> -	 * here, pci_create_root_bus() has been called by someone else and
>> -	 * sysdata is likely to be different from what we expect.  Let it go in
>> -	 * that case.
>> -	 */
>> -	if (!bridge->dev.parent) {
>> -		struct pci_sysdata *sd = bridge->bus->sysdata;
>> -		ACPI_COMPANION_SET(&bridge->dev, sd->companion);
>> -	}
>> -	return 0;
>> -}
>> -
>>   int __init pci_acpi_init(void)
>>   {
>>   	struct pci_dev *dev = NULL;
>> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
>> index ae3fe4e..4581e0e 100644
>> --- a/drivers/acpi/pci_root.c
>> +++ b/drivers/acpi/pci_root.c
>> @@ -564,6 +564,11 @@ static int acpi_pci_root_add(struct acpi_device *device,
>>   		}
>>   	}
>>
>> +	/*
>> +	 * pci_create_root_bus() needs to detect the parent device type,
>> +	 * so initialize its companion data accordingly.
>> +	 */
>> +	ACPI_COMPANION_SET(&device->dev, device);
>>   	root->device = device;
>>   	root->segment = segment & 0xFFFF;
>>   	strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
>> @@ -846,7 +851,7 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
>>
>>   	pci_acpi_root_add_resources(info);
>>   	pci_add_resource(&info->resources, &root->secondary);
>> -	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
>> +	bus = pci_create_root_bus(&device->dev, busnum, ops->pci_ops,
>>   				  sysdata, &info->resources);
>
> "device" here is a struct acpi_device *.  Rafael, is that the right
> thing to do?  I dimly recall proposing something similar long ago and
> that it turned out to be a bad idea.
>

Joining Bjorn's question. Rafael, do you recall what was the issue here 
from the past?

Thanks,
Tomasz


From tiffany.lin at mediatek.com  Wed May  4 01:19:47 2016
From: tiffany.lin at mediatek.com (tiffany lin)
Date: Wed, 4 May 2016 16:19:47 +0800
Subject: [PATCH v10 0/8] Add MT8173 Video Encoder Driver and VPU Driver
In-Reply-To: <5729A57E.1080505@xs4all.nl>
References: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
 <5729A57E.1080505@xs4all.nl>
Message-ID: <1462349987.1891.5.camel@mtksdaap41>

Hi Hans,

On Wed, 2016-05-04 at 09:32 +0200, Hans Verkuil wrote:
> Hi Tiffany,
> 
> On 05/03/2016 12:11 PM, Tiffany Lin wrote:
> > ==============
> >  Introduction
> > ==============
> > 
> > The purpose of this series is to add the driver for video codec hw embedded in the Mediatek's MT8173 SoCs.
> > Mediatek Video Codec is able to handle video encoding of in a range of formats.
> > 
> > This patch series also include VPU driver. Mediatek Video Codec driver rely on VPU driver to load,
> > communicate with VPU.
> > 
> > Internally the driver uses videobuf2 framework and MTK IOMMU and MTK SMI both have been merged in v4.6-rc1.
> > This patch series need [PATCH v15 8/8] memory: mtk-smi: export mtk_smi_larb_get/put[1] to build as module
> > 
> > [1]http://lists.infradead.org/pipermail/linux-mediatek/2016-April/005173.html
> > 
> > ==================
> >  Device interface
> > ==================
> > 
> > In principle the driver bases on v4l2 memory-to-memory framework:
> > it provides a single video node and each opened file handle gets its own private context with separate
> > buffer queues. Each context consist of 2 buffer queues: OUTPUT (for source buffers, i.e. raw video
> > frames) and CAPTURE (for destination buffers, i.e. encoded video frames).
> > 
> > ==============================
> >  VPU (Video Processor Unit)
> > ==============================
> > The VPU driver for hw video codec embedded in Mediatek's MT8173 SOCs.
> > It is able to handle video decoding/encoding in a range of formats.
> > The driver provides with VPU firmware download, memory management and the communication interface between CPU and VPU.
> > For VPU initialization, it will create virtual memory for CPU access and physical address for VPU hw device access. 
> > When a decode/encode instance opens a device node, vpu driver will download vpu firmware to the device.
> > A decode/encode instant will decode/encode a frame using VPU interface to interrupt vpu to handle decoding/encoding jobs.
> > 
> > Please have a look at the code and comments will be very much appreciated.
> > 
> > Change in v10:
> > 1. Fix smatch/sparse error message
> > 2. Add depends on ARM || ARM64 and MTK_IOMMU in Kconfig
> 
> I don't like the ARM or ARM64 dependency since that makes COMPILE_TEST harder.
> 
> I removed it here and for the VPU and everything still compiles fine with
> sparse and smatch. So I'll drop those dependencies.
> 
> Why is the MTK_IOMMU dependency needed? Just curious.
> 
This is because we need MTK_IOMMU module to get dma continuous memory
for HW.

> Note that sparse still complains about this:
> 
> media-git/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c:261:24: warning: incorrect type in assignment (different base types)
> 
> I think this code should be rewritten. Something like this would work
> (if I understand the code correctly):
> 
> u32 tag = (bs_hdr_len << 5) | 0x10 | not_key;
> 
> ac_tag[0] = tag & 0xff;
> ac_tag[1] = (tag >> 8) & 0xff;
> ac_tag[2] = (tag >> 16) & 0xff;
> 
> It's perhaps a bit more verbose, but a lot easier to understand.
> 

> I'm accepting this driver but I'll remove the ARM || ARM64 dependency. Can
> you post a follow-up patch for this sparse warning?
> 

Got it. We will provide a patch to fix this.
I was curious why my sparse do not show this warning.
Is there any parameter I need to set except C=1?

best regards,
Tiffany

> Regards,
> 
> 	Hans
> 
> 
> > 
> > VPU part
> > 1. Fix smatch/sparse error message
> > 2. Use totalram_pages instead of max_pfn to decide VPU 4GB mode
> > 3. Protect variable "fw_load"
> > 4. Add depends on ARM || ARM64 in Kconfig
> > 
> > Change in v9:
> > 1. Rename idx in mtk_vcodec_ctx to id and curr_max_idx in mtk_vcodec_dev to id_counter.
> > 2. Refine fops_vcodec_open
> > 
> > VPU part
> > Merge Julia Lawall's fixes to "[PATCH v9 2/8] [media] VPU: mediatek: support Mediatek VPU"
> > 1.[PATCH] VPU: mediatek: fix simple_open.cocci warnings 
> > 2.[PATCH] VPU: mediatek: fix platform_no_drv_owner.cocci warnings
> > 
> > Change in v8:
> > 1. Refine indentation
> > 2. Refine colorspace information process vidioc_try_fmt_vid_out_mplane
> > 3. Remove instance_mask in mtk_vcodec_dev, use curr_max_idx for instance index
> > 4. Use kzalloc to allocate ctx
> > 5. Refine fops_vcodec_open
> > 
> > VPU Part
> > 1. Refine vpu_load_firmware
> > 
> > Change in v7:
> > 1. Rebase against the master branch of git://linuxtv.org/media_tree.git
> > 2. Add ycbcr_enc, quantization and xfer_func in try_fmt, g_fmt, s_fmt
> > 3. Merge h264_enc and vp8_enc to venc directory
> > 
> > Change in v6:
> > 1. Add synchronization access protect between irq handler and work thread
> > 2. Add DMA_ATTR_ALLOC_SINGLE_PAGES support
> > 3. S_FMT will return coded_width, coded_height, so user space could allocate correct size memory that HW required
> > 4. merge h264/vp8 enc ap and md32 ipi msg
> > 5. separate h264/vp8 enc gop_size and intra_period handle
> > 6. remove sizeimage relative code in work buffer function
> > 7. Refine makefile to build as an module
> > 8. Code clean up
> > 
> > VPU Part
> > 1. export symbols for building VPU as an module
> > 2. change function from "wait_event_interruptible_timeout" to "wait_event_timeout" since
> >    CPU needs to wait for ACK from VPU even if it was interrupted by a signal
> > 
> > v4l2-compliance test output:
> > localhost Encode # ./v4l2-compliance -d /dev/video1
> > Driver Info:
> >         Driver name   : mtk-vcodec-enc
> >         Card type     : platform:mt8173
> >         Bus info      : platform:mt8173
> >         Driver version: 4.4.0
> >         Capabilities  : 0x84204000
> >                 Video Memory-to-Memory Multiplanar
> >                 Streaming
> >                 Extended Pix Format
> >                 Device Capabilities
> >         Device Caps   : 0x04204000
> >                 Video Memory-to-Memory Multiplanar
> >                 Streaming
> >                 Extended Pix Format
> > 
> > Compliance test for device /dev/video1 (not using libv4l2):
> > 
> > Required ioctls:
> >         test VIDIOC_QUERYCAP: OK
> > 
> > Allow for multiple opens:
> >         test second video open: OK
> >         test VIDIOC_QUERYCAP: OK
> >         test VIDIOC_G/S_PRIORITY: OK
> > 
> > Debug ioctls:
> >         test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
> >         test VIDIOC_LOG_STATUS: OK (Not Supported)
> > 
> > Input ioctls:
> >         test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
> >         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> >         test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
> >         test VIDIOC_ENUMAUDIO: OK (Not Supported)
> >         test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
> >         test VIDIOC_G/S_AUDIO: OK (Not Supported)
> >         Inputs: 0 Audio Inputs: 0 Tuners: 0
> > 
> > Output ioctls:
> >         test VIDIOC_G/S_MODULATOR: OK (Not Supported)
> >         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> >         test VIDIOC_ENUMAUDOUT: OK (Not Supported)
> >         test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
> >         test VIDIOC_G/S_AUDOUT: OK (Not Supported)
> >         Outputs: 0 Audio Outputs: 0 Modulators: 0
> > 
> > Input/Output configuration ioctls:
> >         test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
> >         test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
> >         test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
> >         test VIDIOC_G/S_EDID: OK (Not Supported)
> > 
> >         Control ioctls:
> >                 test VIDIOC_QUERYCTRL/MENU: OK
> >                 test VIDIOC_G/S_CTRL: OK
> >                 test VIDIOC_G/S/TRY_EXT_CTRLS: OK
> >                 test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
> >                 test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> >                 Standard Controls: 12 Private Controls: 0
> > 
> >         Format ioctls:
> >                 test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
> >                 test VIDIOC_G/S_PARM: OK
> >                 test VIDIOC_G_FBUF: OK (Not Supported)
> >                 test VIDIOC_G_FMT: OK
> >                 test VIDIOC_TRY_FMT: OK
> >                 test VIDIOC_S_FMT: OK
> >                 test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> > 
> >         Codec ioctls:
> >                 test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
> >                 test VIDIOC_G_ENC_INDEX: OK (Not Supported)
> >                 test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
> > 
> >         Buffer ioctls:
> >                 test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
> >                 test VIDIOC_EXPBUF: OK
> > Total: 38, Succeeded: 38, Failed: 0, Warnings: 0
> > 
> > 
> > v4l2-compliance test output:
> > localhost ~ # /usr/bin/v4l2-compliance -d /dev/video1
> >  
> > Change in v5:
> > Vcodec Part
> > 1. Pass checkpatch and v4l2-compliance test
> > 2. Remove unused g/s_selection for now
> > 3. add vidioc_g_parm support
> > 4. add vidioc_create_bufs and vidioc_prepare_buf support
> > 5. Remove instance check in fops_vcodec_open
> > 6. Fix comments for data structure and code
> > 7. Refine venc, venc_lt clock source name in devicetree and binding document
> > 8. Fix Author information and copyright information
> > 9. Refine code according to review comments
> > 
> > VPU Part
> > 
> > v4l2-compliance test output:
> > localhost ~ # /usr/bin/v4l2-compliance -d /dev/video1
> > Driver Info:
> >         Driver name   : mtk-vcodec-enc
> >         Card type     : platform:mt8173
> >         Bus info      : platform:mt8173
> >         Driver version: 4.4.0
> >         Capabilities  : 0x84204000
> >                 Video Memory-to-Memory Multiplanar
> >                 Streaming
> >                 Extended Pix Format
> >                 Device Capabilities
> >         Device Caps   : 0x04204000
> >                 Video Memory-to-Memory Multiplanar
> >                 Streaming
> >                 Extended Pix Format
> > 
> > Compliance test for device /dev/video1 (not using libv4l2):
> > 
> > Required ioctls:
> >         test VIDIOC_QUERYCAP: OK
> > 
> > Allow for multiple opens:
> >         test second video open: OK
> >         test VIDIOC_QUERYCAP: OK
> >         test VIDIOC_G/S_PRIORITY: OK
> > 
> > Debug ioctls:
> >         test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
> >         test VIDIOC_LOG_STATUS: OK (Not Supported)
> > 
> > Input ioctls:
> >         test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
> >         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> >         test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
> >         test VIDIOC_ENUMAUDIO: OK (Not Supported)
> >         test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
> >         test VIDIOC_G/S_AUDIO: OK (Not Supported)
> >         Inputs: 0 Audio Inputs: 0 Tuners: 0
> > 
> > Output ioctls:
> >         test VIDIOC_G/S_MODULATOR: OK (Not Supported)
> >         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> >         test VIDIOC_ENUMAUDOUT: OK (Not Supported)
> >         test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
> >         test VIDIOC_G/S_AUDOUT: OK (Not Supported)
> >         Outputs: 0 Audio Outputs: 0 Modulators: 0
> > 
> > Input/Output configuration ioctls:
> >         test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
> >         test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
> >         test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
> >         test VIDIOC_G/S_EDID: OK (Not Supported)
> > 
> >         Control ioctls:
> >                 test VIDIOC_QUERYCTRL/MENU: OK
> >                 test VIDIOC_G/S_CTRL: OK
> >                 test VIDIOC_G/S/TRY_EXT_CTRLS: OK
> >                 test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
> >                 test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> >                 Standard Controls: 12 Private Controls: 0
> > 
> >         Format ioctls:
> >                 test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
> >                 test VIDIOC_G/S_PARM: OK
> >                 test VIDIOC_G_FBUF: OK (Not Supported)
> >                 test VIDIOC_G_FMT: OK
> >                 test VIDIOC_TRY_FMT: OK
> >                 test VIDIOC_S_FMT: OK
> >                 test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> > 
> >         Codec ioctls:
> >                 test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
> >                 test VIDIOC_G_ENC_INDEX: OK (Not Supported)
> >                 test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
> > 
> >         Buffer ioctls:
> >                 test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
> >                 test VIDIOC_EXPBUF: OK
> > 
> > 
> > Total: 38, Succeeded: 38, Failed: 0, Warnings: 0
> > 
> > 
> > Change in v4:
> > Vcodec Part
> > 1. Remove MTK_ENCODE_PARAM_SKIP_FRAME support
> > 2. Remove MTK_ENCODE_PARAM_FRAME_TYPE and change to use V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME[3]
> > 3. Refine Encoder HW clock source
> > 4. Refine debug log
> > 5. Add watchdog support
> > 6. With patch "media: v4l2-compat-ioctl32: fix missing length copy in put_v4l2_buffer32"[4],
> > v4l2-compliance test passed[5] in v4.4-rc5 
> > 
> > VPU Part
> > 1. These two patches were Acked-by: Rob Herring <robh <at> kernel.org> in v3
> >    [PATCH v3 1/8] dt-bindings: Add a binding for Mediatek Video Processor
> >    [PATCH v3 3/8] arm64: dts: mediatek: Add node for Mediatek Video Processor Unit
> >    Because we were wrong about how the hardware works, there is no connection between VPU and IOMMU HW
> >    We remove VPU attaching to IOMMU
> > 2. Support VPU running on 4GB DRAM system
> > 3. Support VPU watchdog reset
> > 4. Refine for coding style 
> > 
> > [3]https://patchwork.linuxtv.org/patch/32670/
> > [4] https://patchwork.linuxtv.org/patch/32631/
> > [5]localhost ~ # /usr/bin/v4l2-compliance -d /dev/video1
> > Driver Info:
> >         Driver name   : mtk-vcodec-en
> >         Card type     : platform:mt817
> >         Bus info      : platform:mt817
> >         Driver version: 4.4.0
> >         Capabilities  : 0x84204000
> >                 Video Memory-to-Memory Multiplanar
> >                 Streaming
> >                 Extended Pix Format
> >                 Device Capabilities
> >         Device Caps   : 0x04204000
> >                 Video Memory-to-Memory Multiplanar
> >                 Streaming
> >                 Extended Pix Format
> > 
> > Compliance test for device /dev/video1 (not using libv4l2):
> > 
> > Required ioctls:
> >         test VIDIOC_QUERYCAP: OK
> > 
> > Allow for multiple opens:
> >         test second video open: OK
> >         test VIDIOC_QUERYCAP: OK
> >         test VIDIOC_G/S_PRIORITY: OK
> > 
> > Debug ioctls:
> >         test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
> >         test VIDIOC_LOG_STATUS: OK (Not Supported)
> > 
> > Input ioctls:
> >         test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
> >         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> >         test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
> >         test VIDIOC_ENUMAUDIO: OK (Not Supported)
> >         test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
> >         test VIDIOC_G/S_AUDIO: OK (Not Supported)
> >         Inputs: 0 Audio Inputs: 0 Tuners: 0
> > 
> > Output ioctls:
> >         test VIDIOC_G/S_MODULATOR: OK (Not Supported)
> >         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> >         test VIDIOC_ENUMAUDOUT: OK (Not Supported)
> >         test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
> >         test VIDIOC_G/S_AUDOUT: OK (Not Supported)
> >         Outputs: 0 Audio Outputs: 0 Modulators: 0
> > 
> > Input/Output configuration ioctls:
> >         test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
> >         test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
> >         test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
> >         test VIDIOC_G/S_EDID: OK (Not Supported)
> > 
> >         Control ioctls:
> >                 test VIDIOC_QUERYCTRL/MENU: OK
> >                 test VIDIOC_G/S_CTRL: OK
> >                 test VIDIOC_G/S/TRY_EXT_CTRLS: OK
> >                 test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
> >                 test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> >                 Standard Controls: 12 Private Controls: 0
> > 
> >         Format ioctls:
> >                 test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
> >                 test VIDIOC_G/S_PARM: OK (Not Supported)
> >                 test VIDIOC_G_FBUF: OK (Not Supported)
> >                 test VIDIOC_G_FMT: OK
> >                 test VIDIOC_TRY_FMT: OK
> >                 test VIDIOC_S_FMT: OK
> >                 test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> > 
> >         Codec ioctls:
> >                 test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
> >                 test VIDIOC_G_ENC_INDEX: OK (Not Supported)
> >                 test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
> > 
> >         Buffer ioctls:
> >                 warn: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(475):
> > VIDIOC_CREATE_BUFS not supported
> >                 warn: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(475):
> > VIDIOC_CREATE_BUFS not supported
> >                 test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
> >                 test VIDIOC_EXPBUF: OK
> > 
> > Total: 38, Succeeded: 38, Failed: 0, Warnings: 2
> > 
> > Change in v3:
> > 1.Refine code to pass v4l2-compliance test, now it still has 2 issues 2.Refine code according to latest MTK
> > IOMMU patches[1] 3.Remove MFC51 specific CIDs and add MTK specific CIDs for for keyframe and
> >   skip I-frame
> > 4.Refine code according to review comments
> > 
> > Below is the v1.6 version v4l2-compliance report for the mt8173 encoder driver.
> > Now there are still 2 test fail in v1.6.
> > For VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF, we directly use v4l2_m2m_ioctl_* functions, but it still
> > fail. It pass in kernel 3.18 but fail in kernel 4.4.
> > We will try v1.8 in next version.
> > VIDIOC_EXPBUF is becuase we support all three memory types VB2_DMABUF, VB2_MMAP and VB2_USERPTR.
> > VIDIOC_EXPBUF only allowed when only VB2_MMAP supported.
> > localhost ~ # /usr/bin/v4l2-compliance -d /dev/video1 Driver Info:
> >         Driver name   : mtk-vcodec-en
> >         Card type     : platform:mt817
> >         Bus info      : platform:mt817
> >         Driver version: 4.4.0
> >         Capabilities  : 0x84204000
> >                 Video Memory-to-Memory Multiplanar
> >                 Streaming
> >                 Extended Pix Format
> >                 Device Capabilities
> >         Device Caps   : 0x04204000
> >                 Video Memory-to-Memory Multiplanar
> >                 Streaming
> >                 Extended Pix Format
> > 
> > Compliance test for device /dev/video1 (not using libv4l2):
> > 
> > Required ioctls:
> >         test VIDIOC_QUERYCAP: OK
> > 
> > Allow for multiple opens:
> >         test second video open: OK
> >         test VIDIOC_QUERYCAP: OK
> >         test VIDIOC_G/S_PRIORITY: OK
> > 
> > Debug ioctls:
> >         test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
> >         test VIDIOC_LOG_STATUS: OK (Not Supported)
> > 
> > Input ioctls:
> >         test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
> >         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> >         test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
> >         test VIDIOC_ENUMAUDIO: OK (Not Supported)
> >         test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
> >         test VIDIOC_G/S_AUDIO: OK (Not Supported)
> >         Inputs: 0 Audio Inputs: 0 Tuners: 0
> > 
> > Output ioctls:
> >         test VIDIOC_G/S_MODULATOR: OK (Not Supported)
> >         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
> >         test VIDIOC_ENUMAUDOUT: OK (Not Supported)
> >         test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
> >         test VIDIOC_G/S_AUDOUT: OK (Not Supported)
> >         Outputs: 0 Audio Outputs: 0 Modulators: 0
> > 
> > Input/Output configuration ioctls:
> >         test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
> >         test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
> >         test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
> >         test VIDIOC_G/S_EDID: OK (Not Supported)
> > 
> >         Control ioctls:
> >                 test VIDIOC_QUERYCTRL/MENU: OK
> >                 test VIDIOC_G/S_CTRL: OK
> >                 test VIDIOC_G/S/TRY_EXT_CTRLS: OK
> >                 test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
> >                 test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
> >                 Standard Controls: 11 Private Controls: 2
> > 
> >         Format ioctls:
> >                 test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
> >                 test VIDIOC_G/S_PARM: OK (Not Supported)
> >                 test VIDIOC_G_FBUF: OK (Not Supported)
> >                 test VIDIOC_G_FMT: OK
> >                 test VIDIOC_TRY_FMT: OK
> >                 test VIDIOC_S_FMT: OK
> >                 test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
> > 
> >         Codec ioctls:
> >                 test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
> >                 test VIDIOC_G_ENC_INDEX: OK (Not Supported)
> >                 test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
> > 
> >         Buffer ioctls:
> >                 fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(266): vp->length
> > == 0
> >                 fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(335):
> > buf.check(Unqueued, i)
> >                 fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(420):
> > testQueryBuf(node, i, q.g_buffers())
> >                 test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: FAIL
> >                 fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(500): q.has_expbuf(node)
> >                 test VIDIOC_EXPBUF: FAIL
> > Total: 38, Succeeded: 36, Failed: 2, Warnings: 0
> > 
> > Change in v2:
> > Vcodec Part
> > 1.Remove common and include directory in mtk-vcodec 2.Refine vb2ops_venc_start_streaming and
> > vb2ops_venc_stop_streaming and state machine 3.Remove venc_if_init and venc_if_deinit 4.Refine
> > debug message 5.Refine lab and vpu decription in mediatek-vcodec.txt
> > 
> > VPU Part
> > 1. Modify VPU Kconfig
> > 2. Move encoder header files to other patch sets 3. Remove marcos for extended virtual/iova address 4.
> > Change register and variable names 5. Add a reference counter for VPU watchdog 6. Remove one busy waiting
> > in function vpu_ipi_send 7. Operate VPU clock in VPU driver (not called by encoder drivers) 8. Refine
> > memory mapping, firmware download and extended memory allocation/free functions 9. Release more
> > allocated resources in driver remove function
> > 
> > Andrew-CT Chen (3):
> >   dt-bindings: Add a binding for Mediatek Video Processor
> >   VPU: mediatek: support Mediatek VPU
> >   arm64: dts: mediatek: Add node for Mediatek Video Processor Unit
> > 
> > Tiffany Lin (5):
> >   dt-bindings: Add a binding for Mediatek Video Encoder
> >   vcodec: mediatek: Add Mediatek V4L2 Video Encoder Driver
> >   vcodec: mediatek: Add Mediatek VP8 Video Encoder Driver
> >   vcodec: mediatek: Add Mediatek H264 Video Encoder Driver
> >   arm64: dts: mediatek: Add Video Encoder for MT8173
> > 
> >  .../devicetree/bindings/media/mediatek-vcodec.txt  |   59 +
> >  .../devicetree/bindings/media/mediatek-vpu.txt     |   31 +
> >  arch/arm64/boot/dts/mediatek/mt8173.dtsi           |   62 +
> >  drivers/media/platform/Kconfig                     |   32 +
> >  drivers/media/platform/Makefile                    |    4 +
> >  drivers/media/platform/mtk-vcodec/Makefile         |   19 +
> >  drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h |  338 +++++
> >  drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 1288 ++++++++++++++++++++
> >  drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h |   58 +
> >  .../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c |  454 +++++++
> >  .../media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c  |  137 +++
> >  .../media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h  |   26 +
> >  .../media/platform/mtk-vcodec/mtk_vcodec_intr.c    |   55 +
> >  .../media/platform/mtk-vcodec/mtk_vcodec_intr.h    |   27 +
> >  .../media/platform/mtk-vcodec/mtk_vcodec_util.c    |   94 ++
> >  .../media/platform/mtk-vcodec/mtk_vcodec_util.h    |   87 ++
> >  .../media/platform/mtk-vcodec/venc/venc_h264_if.c  |  679 +++++++++++
> >  .../media/platform/mtk-vcodec/venc/venc_vp8_if.c   |  481 ++++++++
> >  drivers/media/platform/mtk-vcodec/venc_drv_base.h  |   62 +
> >  drivers/media/platform/mtk-vcodec/venc_drv_if.c    |  113 ++
> >  drivers/media/platform/mtk-vcodec/venc_drv_if.h    |  163 +++
> >  drivers/media/platform/mtk-vcodec/venc_ipi_msg.h   |  210 ++++
> >  drivers/media/platform/mtk-vcodec/venc_vpu_if.c    |  237 ++++
> >  drivers/media/platform/mtk-vcodec/venc_vpu_if.h    |   61 +
> >  drivers/media/platform/mtk-vpu/Makefile            |    3 +
> >  drivers/media/platform/mtk-vpu/mtk_vpu.c           |  950 +++++++++++++++
> >  drivers/media/platform/mtk-vpu/mtk_vpu.h           |  162 +++
> >  27 files changed, 5892 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/media/mediatek-vcodec.txt
> >  create mode 100644 Documentation/devicetree/bindings/media/mediatek-vpu.txt
> >  create mode 100644 drivers/media/platform/mtk-vcodec/Makefile
> >  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
> >  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
> >  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.h
> >  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
> >  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
> >  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.h
> >  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c
> >  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h
> >  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
> >  create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
> >  create mode 100644 drivers/media/platform/mtk-vcodec/venc/venc_h264_if.c
> >  create mode 100644 drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c
> >  create mode 100644 drivers/media/platform/mtk-vcodec/venc_drv_base.h
> >  create mode 100644 drivers/media/platform/mtk-vcodec/venc_drv_if.c
> >  create mode 100644 drivers/media/platform/mtk-vcodec/venc_drv_if.h
> >  create mode 100644 drivers/media/platform/mtk-vcodec/venc_ipi_msg.h
> >  create mode 100644 drivers/media/platform/mtk-vcodec/venc_vpu_if.c
> >  create mode 100644 drivers/media/platform/mtk-vcodec/venc_vpu_if.h
> >  create mode 100644 drivers/media/platform/mtk-vpu/Makefile
> >  create mode 100644 drivers/media/platform/mtk-vpu/mtk_vpu.c
> >  create mode 100644 drivers/media/platform/mtk-vpu/mtk_vpu.h
> > 




From hverkuil at xs4all.nl  Wed May  4 01:25:47 2016
From: hverkuil at xs4all.nl (Hans Verkuil)
Date: Wed, 4 May 2016 10:25:47 +0200
Subject: [PATCH v10 0/8] Add MT8173 Video Encoder Driver and VPU Driver
In-Reply-To: <1462349987.1891.5.camel@mtksdaap41>
References: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
 <5729A57E.1080505@xs4all.nl> <1462349987.1891.5.camel@mtksdaap41>
Message-ID: <5729B20B.6090006@xs4all.nl>



On 05/04/2016 10:19 AM, tiffany lin wrote:
> Hi Hans,
> 
> On Wed, 2016-05-04 at 09:32 +0200, Hans Verkuil wrote:
>> Hi Tiffany,
>>
>> On 05/03/2016 12:11 PM, Tiffany Lin wrote:
>>> ==============
>>>  Introduction
>>> ==============
>>>
>>> The purpose of this series is to add the driver for video codec hw embedded in the Mediatek's MT8173 SoCs.
>>> Mediatek Video Codec is able to handle video encoding of in a range of formats.
>>>
>>> This patch series also include VPU driver. Mediatek Video Codec driver rely on VPU driver to load,
>>> communicate with VPU.
>>>
>>> Internally the driver uses videobuf2 framework and MTK IOMMU and MTK SMI both have been merged in v4.6-rc1.
>>> This patch series need [PATCH v15 8/8] memory: mtk-smi: export mtk_smi_larb_get/put[1] to build as module
>>>
>>> [1]http://lists.infradead.org/pipermail/linux-mediatek/2016-April/005173.html
>>>
>>> ==================
>>>  Device interface
>>> ==================
>>>
>>> In principle the driver bases on v4l2 memory-to-memory framework:
>>> it provides a single video node and each opened file handle gets its own private context with separate
>>> buffer queues. Each context consist of 2 buffer queues: OUTPUT (for source buffers, i.e. raw video
>>> frames) and CAPTURE (for destination buffers, i.e. encoded video frames).
>>>
>>> ==============================
>>>  VPU (Video Processor Unit)
>>> ==============================
>>> The VPU driver for hw video codec embedded in Mediatek's MT8173 SOCs.
>>> It is able to handle video decoding/encoding in a range of formats.
>>> The driver provides with VPU firmware download, memory management and the communication interface between CPU and VPU.
>>> For VPU initialization, it will create virtual memory for CPU access and physical address for VPU hw device access. 
>>> When a decode/encode instance opens a device node, vpu driver will download vpu firmware to the device.
>>> A decode/encode instant will decode/encode a frame using VPU interface to interrupt vpu to handle decoding/encoding jobs.
>>>
>>> Please have a look at the code and comments will be very much appreciated.
>>>
>>> Change in v10:
>>> 1. Fix smatch/sparse error message
>>> 2. Add depends on ARM || ARM64 and MTK_IOMMU in Kconfig
>>
>> I don't like the ARM or ARM64 dependency since that makes COMPILE_TEST harder.
>>
>> I removed it here and for the VPU and everything still compiles fine with
>> sparse and smatch. So I'll drop those dependencies.
>>
>> Why is the MTK_IOMMU dependency needed? Just curious.
>>
> This is because we need MTK_IOMMU module to get dma continuous memory
> for HW.
> 
>> Note that sparse still complains about this:
>>
>> media-git/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c:261:24: warning: incorrect type in assignment (different base types)
>>
>> I think this code should be rewritten. Something like this would work
>> (if I understand the code correctly):
>>
>> u32 tag = (bs_hdr_len << 5) | 0x10 | not_key;
>>
>> ac_tag[0] = tag & 0xff;
>> ac_tag[1] = (tag >> 8) & 0xff;
>> ac_tag[2] = (tag >> 16) & 0xff;
>>
>> It's perhaps a bit more verbose, but a lot easier to understand.
>>
> 
>> I'm accepting this driver but I'll remove the ARM || ARM64 dependency. Can
>> you post a follow-up patch for this sparse warning?
>>
> 
> Got it. We will provide a patch to fix this.
> I was curious why my sparse do not show this warning.
> Is there any parameter I need to set except C=1?

I'm running it with these parameters: C=2 CF="-D__CHECK_ENDIAN__"

I suspect it is the CHECK_ENDIAN flag that does it.

Regards,

	Hans


From arnd at arndb.de  Wed May  4 02:05:03 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 04 May 2016 11:05:03 +0200
Subject: [PATCH 09/18] ASoC: sti: Update DT example to match the driver
 code
In-Reply-To: <5729AA33.6020305@st.com>
References: <1461236675-10176-1-git-send-email-peter.griffin@linaro.org>
 <5608365.uloflbeuqO@wuerfel> <5729AA33.6020305@st.com>
Message-ID: <7856280.FvxMcUZr6e@wuerfel>

On Wednesday 04 May 2016 09:52:19 Arnaud Pouliquen wrote:
> hello Arnd, peter,
> 
> On 04/26/2016 01:44 PM, Arnd Bergmann wrote:
> > On Tuesday 26 April 2016 12:15:32 Peter Griffin wrote:
> >>>
> >>>> If not what would you recommend instead? 
> >>>
> >>> It's still not clear to me what that bit in the syscfg register
> >>> is for. Given the error message about "sti-audio-clk-glue",
> >>> I suspect that this is actually a clock controller and that
> >>> it should be using the clock binding with a separate driver
> >>> instead of manipulating the regmap directly from the audio driver.
> >>
> >> Luckily I do have the datasheet for the audio-glue sysconf register.
> >>
> >> It says: -
> >>
> >> [11:8] PCM_CLK_SEL: Selects the frequency synthesizer clock or the external
> >> PCM clock for each channel.
> >>
> >> The driver only ever sets this to 1 which selects the frequency synthesizer
> >> clock. So the bitfield of the register which the driver is using (PCM_CLK_SEL)
> >> is a clock mux.
> > 
> > Ok, that sounds like it could be either a really simple clock driver
> > with just a few lines, or integrated into an existing clock driver
> > if you already have one for this syscon node.
> > 
> >       Arnd
> > 
> FYI, Name of this glue is related to the register name. But it does not
> concern only clock...
>  This glue register is used to :
> - select clock source ( clock framework or external clock from GPIO)
> => one bit field per IP instance (player->clk_sel)
> - select uniperiph player IP instance for PCM out.
> (http://www.spinics.net/lists/alsa-devel/msg49034.html)

Ok, I see. This is of course again the STi platform being a bit different
from everyone else, and whatever we do to hide it won't give us a nice
abstraction. Having just a clock driver for the register won't do the
job here as you say, so I guess the original patch was already the
least awkward way to handle it.

	Arnd


From broonie at kernel.org  Wed May  4 02:07:02 2016
From: broonie at kernel.org (Mark Brown)
Date: Wed, 4 May 2016 10:07:02 +0100
Subject: [RFC PATCH 1/7] ALSA: ac97: split out the generic ac97 registers
In-Reply-To: <87y47roski.fsf@belgarion.home>
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-2-git-send-email-robert.jarzmik@free.fr>
 <20160503115159.GP6292@sirena.org.uk>
 <87y47roski.fsf@belgarion.home>
Message-ID: <20160504090702.GV6292@sirena.org.uk>

On Tue, May 03, 2016 at 09:22:05PM +0200, Robert Jarzmik wrote:
> Mark Brown <broonie at kernel.org> writes:

> > On Sat, Apr 30, 2016 at 11:15:33PM +0200, Robert Jarzmik wrote:

> >> Split out from the ac97_codec.h the ac97 generic registers, which can be
> >> used by a codec, typically a generic ac97 codec, and by the ac97 bus, to
> >> scan an ac97 AC-Link.

> > I don't entirely see the value in this one but equally it does no harm.

> Oh that's to have the defines AC97_VENDOR_ID1 and AC97_VENDOR_ID2, but without
> including ac97_codec.h in sound/ac97/bus.c.

I see that, I just don't know why that helps.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/dd7af245/attachment.sig>

From tiffany.lin at mediatek.com  Wed May  4 02:21:22 2016
From: tiffany.lin at mediatek.com (tiffany lin)
Date: Wed, 4 May 2016 17:21:22 +0800
Subject: [PATCH v10 0/8] Add MT8173 Video Encoder Driver and VPU Driver
In-Reply-To: <5729B20B.6090006@xs4all.nl>
References: <1462270287-11374-1-git-send-email-tiffany.lin@mediatek.com>
 <5729A57E.1080505@xs4all.nl> <1462349987.1891.5.camel@mtksdaap41>
 <5729B20B.6090006@xs4all.nl>
Message-ID: <1462353682.1891.7.camel@mtksdaap41>

Hi Hans,

On Wed, 2016-05-04 at 10:25 +0200, Hans Verkuil wrote:
> 
> On 05/04/2016 10:19 AM, tiffany lin wrote:
> > Hi Hans,
> > 
> > On Wed, 2016-05-04 at 09:32 +0200, Hans Verkuil wrote:
> >> Hi Tiffany,
> >>
> >> On 05/03/2016 12:11 PM, Tiffany Lin wrote:
> >>> ==============
> >>>  Introduction
> >>> ==============
> >>>
> >>> The purpose of this series is to add the driver for video codec hw embedded in the Mediatek's MT8173 SoCs.
> >>> Mediatek Video Codec is able to handle video encoding of in a range of formats.
> >>>
> >>> This patch series also include VPU driver. Mediatek Video Codec driver rely on VPU driver to load,
> >>> communicate with VPU.
> >>>
> >>> Internally the driver uses videobuf2 framework and MTK IOMMU and MTK SMI both have been merged in v4.6-rc1.
> >>> This patch series need [PATCH v15 8/8] memory: mtk-smi: export mtk_smi_larb_get/put[1] to build as module
> >>>
> >>> [1]http://lists.infradead.org/pipermail/linux-mediatek/2016-April/005173.html
> >>>
> >>> ==================
> >>>  Device interface
> >>> ==================
> >>>
> >>> In principle the driver bases on v4l2 memory-to-memory framework:
> >>> it provides a single video node and each opened file handle gets its own private context with separate
> >>> buffer queues. Each context consist of 2 buffer queues: OUTPUT (for source buffers, i.e. raw video
> >>> frames) and CAPTURE (for destination buffers, i.e. encoded video frames).
> >>>
> >>> ==============================
> >>>  VPU (Video Processor Unit)
> >>> ==============================
> >>> The VPU driver for hw video codec embedded in Mediatek's MT8173 SOCs.
> >>> It is able to handle video decoding/encoding in a range of formats.
> >>> The driver provides with VPU firmware download, memory management and the communication interface between CPU and VPU.
> >>> For VPU initialization, it will create virtual memory for CPU access and physical address for VPU hw device access. 
> >>> When a decode/encode instance opens a device node, vpu driver will download vpu firmware to the device.
> >>> A decode/encode instant will decode/encode a frame using VPU interface to interrupt vpu to handle decoding/encoding jobs.
> >>>
> >>> Please have a look at the code and comments will be very much appreciated.
> >>>
> >>> Change in v10:
> >>> 1. Fix smatch/sparse error message
> >>> 2. Add depends on ARM || ARM64 and MTK_IOMMU in Kconfig
> >>
> >> I don't like the ARM or ARM64 dependency since that makes COMPILE_TEST harder.
> >>
> >> I removed it here and for the VPU and everything still compiles fine with
> >> sparse and smatch. So I'll drop those dependencies.
> >>
> >> Why is the MTK_IOMMU dependency needed? Just curious.
> >>
> > This is because we need MTK_IOMMU module to get dma continuous memory
> > for HW.
> > 
> >> Note that sparse still complains about this:
> >>
> >> media-git/drivers/media/platform/mtk-vcodec/venc/venc_vp8_if.c:261:24: warning: incorrect type in assignment (different base types)
> >>
> >> I think this code should be rewritten. Something like this would work
> >> (if I understand the code correctly):
> >>
> >> u32 tag = (bs_hdr_len << 5) | 0x10 | not_key;
> >>
> >> ac_tag[0] = tag & 0xff;
> >> ac_tag[1] = (tag >> 8) & 0xff;
> >> ac_tag[2] = (tag >> 16) & 0xff;
> >>
> >> It's perhaps a bit more verbose, but a lot easier to understand.
> >>
> > 
> >> I'm accepting this driver but I'll remove the ARM || ARM64 dependency. Can
> >> you post a follow-up patch for this sparse warning?
> >>
> > 
> > Got it. We will provide a patch to fix this.
> > I was curious why my sparse do not show this warning.
> > Is there any parameter I need to set except C=1?
> 
> I'm running it with these parameters: C=2 CF="-D__CHECK_ENDIAN__"
> 
> I suspect it is the CHECK_ENDIAN flag that does it.
> 
Got it, thanks for the information.

best regards,
Tiffany
> Regards,
> 
> 	Hans




From Suzuki.Poulose at arm.com  Wed May  4 02:37:16 2016
From: Suzuki.Poulose at arm.com (Suzuki K Poulose)
Date: Wed, 4 May 2016 10:37:16 +0100
Subject: [PATCH] [for 4.7] arm-ccn: Enable building as module
In-Reply-To: <1461855901-23794-1-git-send-email-suzuki.poulose@arm.com>
References: <1461855901-23794-1-git-send-email-suzuki.poulose@arm.com>
Message-ID: <5729C2CC.7030806@arm.com>

On 28/04/16 16:05, Suzuki K Poulose wrote:
> arm-ccn driver uses irq_set_affinity, which is not exported and
> hence cannot be built as a module, eventhough we have all the
> bits ready. This patch makes use of the exported helper
> irq_set_affinity_hint() instead. Also, the __free_irq expects
> the affinity_hint to be NULL when we free the irq. So set the
> affinity_hint to NULL at clean up.
>
> Now that we can build it as a module, update the Kconfig to
> reflect the change.
>
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Paul Gortmaker <paul.gortmaker at windriver.com>
> Acked-by: Pawel Moll <pawel.moll at arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>

Hi,

Could you please pull this for 4.7 ?

Thanks
Suzuki

> ---
>   drivers/bus/Kconfig   |    2 +-
>   drivers/bus/arm-ccn.c |    7 ++++---
>   2 files changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
> index d4a3a31..3efc996 100644
> --- a/drivers/bus/Kconfig
> +++ b/drivers/bus/Kconfig
> @@ -48,7 +48,7 @@ config ARM_CCI5xx_PMU
>   	  If unsure, say Y
>
>   config ARM_CCN
> -	bool "ARM CCN driver support"
> +	tristate "ARM CCN driver support"
>   	depends on ARM || ARM64
>   	depends on PERF_EVENTS
>   	help
> diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c
> index 7082c72..acc3eb5 100644
> --- a/drivers/bus/arm-ccn.c
> +++ b/drivers/bus/arm-ccn.c
> @@ -1189,7 +1189,7 @@ static int arm_ccn_pmu_cpu_notifier(struct notifier_block *nb,
>   		perf_pmu_migrate_context(&dt->pmu, cpu, target);
>   		cpumask_set_cpu(target, &dt->cpu);
>   		if (ccn->irq)
> -			WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0);
> +			WARN_ON(irq_set_affinity_hint(ccn->irq, &dt->cpu) != 0);
>   	default:
>   		break;
>   	}
> @@ -1278,7 +1278,7 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn)
>
>   	/* Also make sure that the overflow interrupt is handled by this CPU */
>   	if (ccn->irq) {
> -		err = irq_set_affinity(ccn->irq, &ccn->dt.cpu);
> +		err = irq_set_affinity_hint(ccn->irq, &ccn->dt.cpu);
>   		if (err) {
>   			dev_err(ccn->dev, "Failed to set interrupt affinity!\n");
>   			goto error_set_affinity;
> @@ -1306,7 +1306,8 @@ static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn)
>   {
>   	int i;
>
> -	irq_set_affinity(ccn->irq, cpu_possible_mask);
> +	if (ccn->irq)
> +		irq_set_affinity_hint(ccn->irq, NULL);
>   	unregister_cpu_notifier(&ccn->dt.cpu_nb);
>   	for (i = 0; i < ccn->num_xps; i++)
>   		writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL);
>



From vladimir.murzin at arm.com  Wed May  4 02:40:48 2016
From: vladimir.murzin at arm.com (Vladimir Murzin)
Date: Wed, 4 May 2016 10:40:48 +0100
Subject: [PATCH v2 0/3] ARM: nommu: R-class fixes
In-Reply-To: <20160503204419.GP19428@n2100.arm.linux.org.uk>
References: <1461862316-9877-1-git-send-email-vladimir.murzin@arm.com>
 <57287BD9.6090907@arm.com> <20160503103237.GN19428@n2100.arm.linux.org.uk>
 <5728806F.7000208@arm.com> <20160503204419.GP19428@n2100.arm.linux.org.uk>
Message-ID: <5729C3A0.2080506@arm.com>

On 03/05/16 21:44, Russell King - ARM Linux wrote:
> On Tue, May 03, 2016 at 11:41:51AM +0100, Vladimir Murzin wrote:
>> On 03/05/16 11:32, Russell King - ARM Linux wrote:
>>> On Tue, May 03, 2016 at 11:22:17AM +0100, Vladimir Murzin wrote:
>>>> On 28/04/16 17:51, Vladimir Murzin wrote:
>>>>> Small set of fixes discovered with R-class cores.
>>>>>
>>>>> Jean-Philippe Brucker (2):
>>>>>   ARM: nommu: fix PMSAv7 setup
>>>>>   ARM: nommu: change memory reserve for the vectors
>>>>>
>>>>> Vladimir Murzin (1):
>>>>>   ARM: domain: move {set,get}_domain under config guard
>>>>>
>>>>>  arch/arm/include/asm/domain.h |   11 +++++++++++
>>>>>  arch/arm/kernel/head-nommu.S  |    2 +-
>>>>>  arch/arm/mm/nommu.c           |   15 ++++++++-------
>>>>>  3 files changed, 20 insertions(+), 8 deletions(-)
>>>>>
>>>>
>>>> Russell, any objection to get it into patch tracker?
>>>
>>> I've not had any chance to look at them yet - last weekend, I was away
>>> from Thursday through until late Tuesday, then I spent most of Wednesday
>>> and Thursday catching up.  Friday I was able to look at some stuff, and
>>> then I've spent the bank holiday weekend digging out laurels in the front
>>> garden.  I've only just today got back to looking at some kernel stuff.
>>>
>>> So really, I've only had two days in the last week and a half to look at
>>> anything.
>>>
>>> Please wait a little while longer.  Thanks.
>>
>> Thanks for prompt reply! I wasn't aware you've been off, patches can wait.
> 
> Thanks for waiting, I've now looked through them and they look fine to me.
> 
> Please put them in the patch system, thanks.
> 

Thanks for your time! Patches in the patch system now.

Cheers
Vladimir



From boris.brezillon at free-electrons.com  Wed May  4 02:38:52 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Wed, 4 May 2016 11:38:52 +0200
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop>
 <20160503185153.5cfddc32@bbrezillon>
 <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
Message-ID: <20160504113852.10a2dd84@bbrezillon>

Hi Rob,

On Tue, 3 May 2016 14:11:04 -0500
Rob Herring <robh at kernel.org> wrote:

> On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
> <boris.brezillon at free-electrons.com> wrote:
> > Hi Rob,
> >
> > On Tue, 3 May 2016 11:40:19 -0500
> > Rob Herring <robh at kernel.org> wrote:
> >
> >> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:
> >> > The EBI (External Bus Interface) is used to access external peripherals
> >> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
> >> > Each device is assigned a CS line and an address range and can have its
> >> > own configuration (timings, access mode, bus width, ...).
> >> > This driver provides a generic DT binding to configure a device according
> >> > to its requirements.
> >> > For specific device controllers (like the NAND one) the SMC timings
> >> > should be configured by the controller driver through the matrix and smc
> >> > syscon regmaps.
> >> >
> >> > Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> >> > ---
> >> >  .../bindings/memory-controllers/atmel,ebi.txt      | 136 +++++++++++++++++++++
> >> >  1 file changed, 136 insertions(+)
> >> >  create mode 100644 Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> >> >
> >> > diff --git a/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> >> > new file mode 100644
> >> > index 0000000..a6dca5c
> >> > --- /dev/null
> >> > +++ b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> >> > @@ -0,0 +1,136 @@
> >> > +* Device tree bindings for Atmel EBI
> >> > +
> >> > +The External Bus Interface (EBI) controller is a bus where you can connect
> >> > +asynchronous (NAND, NOR, SRAM, ....) and synchronous memories (SDR/DDR SDRAMs).
> >> > +The EBI provides a glue-less interface to asynchronous memories through the SMC
> >> > +(Static Memory Controller).
> >> > +
> >> > +Required properties:
> >> > +
> >> > +- compatible:              "atmel,at91sam9260-ebi"
> >> > +                   "atmel,at91sam9261-ebi"
> >> > +                   "atmel,at91sam9263-ebi0"
> >> > +                   "atmel,at91sam9263-ebi1"
> >>
> >> What are the differences between 0 and 1?
> >
> > Because this SoC has 2 EBI busses with different capabilities.
> 
> Okay, correct answer. :)
> 
> [...]
> 
> >>
> >> > +                   of the memory region requested by the device.
> >> > +
> >> > +EBI bus configuration associated with specific chip-select will be defined in
> >> > +the configs subnode. This configs node will in turn contain several subnodes
> >> > +named config-<cs-id>, each of them containing the following properties.
> >>
> >> This is a bit unusual. Why not just part of the child device nodes?
> >
> > Oh, come on! I reworked the binding because Mark complained about the
> > previous binding which was doing exactly what you're suggesting. Can
> > you please be consistent in your reviews...
> 
> No, Mark and I both have our opinions. Which part of this patch
> explains the history?

Hm, it's in patch 1/2 (just dropped the cover letter, which might not
be such a good idea).

> If the revision history is not in the patch, I'm
> not looking at it.
> 
> My issue with it this way is that it has invented yet another way to
> describe timings. I would like to be consistent across external bus
> descriptions, but we're not very consistent to begin with though. The
> most common seems to be the way you first did it. But I agree that it
> is kind of screwy to have an intermediate node unless the controller
> itself has sub-blocks within it and is not the established way to
> describe a bus with chip selects. I would either put the properties
> directly in the child nodes (e.g. flash at 0,0) or put your config nodes
> in the device node. I'd call it timings instead of config, but that's
> just bikeshedding.

Well, it's not only describing timings (see atmel,bus-width,
atmel,byte-access-type, ...), but I'm fine with either names :).

> 
> memory-controller at 1000 {
>   ...
>   flash at 0,0 {
>     timings {
>       ...
>     };
>   };
> };

Okay. Mark, what do you think of this approach?

Note that one of my previous version was defining timings directly in
the EBI device node, and Arnd noted that doing so may cause problems
if one of the EBI property (or the config/timing node name) conflict
with the sub-device binding, which is why I decided to put the EBI
config definitions in a separate subnode.

> 
> >> > +
> >> > +Optional config-<cs-id> node properties:
> >> > +
> >> > +- atmel,bus-width:         width of the asynchronous device's data bus
> >> > +                           8, 16 or 32.
> >> > +                           Default to 8 when undefined.
> >> > +
> >> > +- atmel,byte-access-type   "write" or "select" (see Atmel datasheet).
> >> > +                           Default to "select" when undefined.
> >> > +
> >> > +- atmel,read-mode          "nrd" or "ncs".
> >> > +                           Default to "ncs" when undefined.
> >> > +
> >> > +- atmel,write-mode         "nwe" or "ncs".
> >> > +                           Default to "ncs" when undefined.
> >> > +
> >> > +- atmel,exnw-mode          "disabled", "frozen" or "ready".
> >> > +                           Default to "disabled" when undefined.
> >> > +
> >> > +- atmel,page-mode          enable page mode if present. The provided value
> >> > +                           defines the page size (supported values: 4, 8,
> >> > +                           16 and 32).
> >> > +
> >> > +- atmel,tdf-mode:          "normal" or "optimized". When set to
> >>
> >> This should be boolean.
> >
> > It was a formerly defined as a boolean, and when it's done like that we
> > have no way to identify whether the property was forgotten or
> > intentionally set to normal mode. What's the problem with this approach?
> 
> Only preference to use boolean when that is sufficient. With your
> argument, then we should never have booleans. You state that missing
> means "normal", not forgotten, so all these properties should be
> required with no default.
> 
> BTW, I debated the same thing on the other properties, but I could see
> them being expanded to a 3rd mode. I don't see that here though.

Well, another reason I switched to a string property is because I
implemented hardware readout in v4, and decided to retrieve the current
state from the hardware and only overload the config with what was
defined in the DT. In this case, if we move to a boolean property we
can't know whether the property is missing because we want to put the
bus in "normal" mode or because we want to keep this config unchanged
(keep the bootloader/bootstrap config).

This is not true in v5, so maybe we should go back to the boolean
atmel,tdf-optimized property.

Thanks,

Boris

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


From u.kleine-koenig at pengutronix.de  Wed May  4 02:43:15 2016
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Wed,  4 May 2016 11:43:15 +0200
Subject: [PATCH v2 0/3] video: fbdev: imxfb: make it work again
Message-ID: <1462354998-5792-1-git-send-email-u.kleine-koenig@pengutronix.de>

Hello,

this is v2 of the series which addresses the review comments I got vor
(implicit) v1.

For patch 2 the question is still open if this is the right fix, but
without this the display doesn't stay on. Patches 1 and 3 should be
applicable independant of patch 2.

Best regards
Uwe

Uwe Kleine-K?nig (3):
  video: fbdev: imxfb: fix semantic of .get_power and .set_power
  video: fbdev: imxfb: enable lcd regulator in .probe
  video: fbdev: imxfb: add some error handling

 drivers/video/fbdev/imxfb.c | 53 +++++++++++++++++++++++++++++++++++----------
 1 file changed, 41 insertions(+), 12 deletions(-)

-- 
2.8.0.rc3



From u.kleine-koenig at pengutronix.de  Wed May  4 02:43:16 2016
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Wed,  4 May 2016 11:43:16 +0200
Subject: [PATCH v2 1/3] video: fbdev: imxfb: fix semantic of .get_power and
 .set_power
In-Reply-To: <1462354998-5792-1-git-send-email-u.kleine-koenig@pengutronix.de>
References: <1462354998-5792-1-git-send-email-u.kleine-koenig@pengutronix.de>
Message-ID: <1462354998-5792-2-git-send-email-u.kleine-koenig@pengutronix.de>

.set_power gets passed an FB_BLANK_XXX value, not a bool. So 0 signals
on; and >1 means off. The same applies for return values of .get_power.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---

Changes since (implicit) v1, sent with
Message-Id: 1457380425-20244-2-git-send-email-u.kleine-koenig at pengutronix.de

 - Make it explicit that we're working on FB_BLANK_XXX values,
   suggested by Philipp Zabel.

 drivers/video/fbdev/imxfb.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c
index 76b6a7784b06..6d402c1a0f2b 100644
--- a/drivers/video/fbdev/imxfb.c
+++ b/drivers/video/fbdev/imxfb.c
@@ -758,10 +758,11 @@ static int imxfb_lcd_get_power(struct lcd_device *lcddev)
 {
 	struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
 
-	if (!IS_ERR(fbi->lcd_pwr))
-		return regulator_is_enabled(fbi->lcd_pwr);
+	if (!IS_ERR(fbi->lcd_pwr) &&
+	    !regulator_is_enabled(fbi->lcd_pwr))
+		return FB_BLANK_POWERDOWN;
 
-	return 1;
+	return FB_BLANK_UNBLANK;
 }
 
 static int imxfb_lcd_set_power(struct lcd_device *lcddev, int power)
@@ -769,7 +770,7 @@ static int imxfb_lcd_set_power(struct lcd_device *lcddev, int power)
 	struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev);
 
 	if (!IS_ERR(fbi->lcd_pwr)) {
-		if (power)
+		if (power == FB_BLANK_UNBLANK)
 			return regulator_enable(fbi->lcd_pwr);
 		else
 			return regulator_disable(fbi->lcd_pwr);
-- 
2.8.0.rc3



From u.kleine-koenig at pengutronix.de  Wed May  4 02:43:17 2016
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Wed,  4 May 2016 11:43:17 +0200
Subject: [PATCH v2 2/3] video: fbdev: imxfb: enable lcd regulator in .probe
In-Reply-To: <1462354998-5792-1-git-send-email-u.kleine-koenig@pengutronix.de>
References: <1462354998-5792-1-git-send-email-u.kleine-koenig@pengutronix.de>
Message-ID: <1462354998-5792-3-git-send-email-u.kleine-koenig@pengutronix.de>

This asserts that the display is on after the driver is initialized.
Otherwise, depending on how the boot loader handled the display, it is
either disabled as the regulator doesn't seem in use, or it stays off.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---

No changes since (implicit) v1, sent with
Message-Id: 1457380425-20244-3-git-send-email-u.kleine-koenig at pengutronix.de

 drivers/video/fbdev/imxfb.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c
index 6d402c1a0f2b..18388ca178a2 100644
--- a/drivers/video/fbdev/imxfb.c
+++ b/drivers/video/fbdev/imxfb.c
@@ -995,8 +995,17 @@ static int imxfb_probe(struct platform_device *pdev)
 	imxfb_enable_controller(fbi);
 	fbi->pdev = pdev;
 
+	if (!IS_ERR(fbi->lcd_pwr)) {
+		ret = regulator_enable(fbi->lcd_pwr);
+		if (ret)
+			goto failed_regulator;
+	}
+
 	return 0;
 
+failed_regulator:
+	imxfb_disable_controller(fbi);
+
 failed_lcd:
 	unregister_framebuffer(info);
 
-- 
2.8.0.rc3



From u.kleine-koenig at pengutronix.de  Wed May  4 02:43:18 2016
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Wed,  4 May 2016 11:43:18 +0200
Subject: [PATCH v2 3/3] video: fbdev: imxfb: add some error handling
In-Reply-To: <1462354998-5792-1-git-send-email-u.kleine-koenig@pengutronix.de>
References: <1462354998-5792-1-git-send-email-u.kleine-koenig@pengutronix.de>
Message-ID: <1462354998-5792-4-git-send-email-u.kleine-koenig@pengutronix.de>

clk_prepare_enable can fail and if it does the controller must not be
considered enabled. So check for errors, properly unwind and give the
error code back to the caller.

While touching the clock code also enable the clocks in the same
direction and disable in reverse order.

Reviewed-by: Philipp Zabel <p.zabel at pengutronix.de>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---

Changes since (implicit) v1, sent with
Message-Id: 1457380425-20244-4-git-send-email-u.kleine-koenig at pengutronix.de

 - Some simplifications suggested and Reviewed-by Philipp Zabel
 - Rework goto labels to have them at the end of the function
   (Tomi Valkeinen).

 drivers/video/fbdev/imxfb.c | 35 +++++++++++++++++++++++++++--------
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c
index 18388ca178a2..23a623688f1e 100644
--- a/drivers/video/fbdev/imxfb.c
+++ b/drivers/video/fbdev/imxfb.c
@@ -473,11 +473,12 @@ static int imxfb_set_par(struct fb_info *info)
 	return 0;
 }
 
-static void imxfb_enable_controller(struct imxfb_info *fbi)
+static int imxfb_enable_controller(struct imxfb_info *fbi)
 {
+	int ret;
 
 	if (fbi->enabled)
-		return;
+		return 0;
 
 	pr_debug("Enabling LCD controller\n");
 
@@ -496,10 +497,29 @@ static void imxfb_enable_controller(struct imxfb_info *fbi)
 	 */
 	writel(RMCR_LCDC_EN_MX1, fbi->regs + LCDC_RMCR);
 
-	clk_prepare_enable(fbi->clk_ipg);
-	clk_prepare_enable(fbi->clk_ahb);
-	clk_prepare_enable(fbi->clk_per);
+	ret = clk_prepare_enable(fbi->clk_ipg);
+	if (ret)
+		goto err_enable_ipg;
+
+	ret = clk_prepare_enable(fbi->clk_ahb);
+	if (ret)
+		goto err_enable_ahb;
+
+	ret = clk_prepare_enable(fbi->clk_per);
+	if (ret)
+		goto err_enable_per;
+
 	fbi->enabled = true;
+	return 0;
+
+err_enable_per:
+	clk_disable_unprepare(fbi->clk_ahb);
+err_enable_ahb:
+	clk_disable_unprepare(fbi->clk_ipg);
+err_enable_ipg:
+	writel(0, fbi->regs + LCDC_RMCR);
+
+	return ret;
 }
 
 static void imxfb_disable_controller(struct imxfb_info *fbi)
@@ -510,8 +530,8 @@ static void imxfb_disable_controller(struct imxfb_info *fbi)
 	pr_debug("Disabling LCD controller\n");
 
 	clk_disable_unprepare(fbi->clk_per);
-	clk_disable_unprepare(fbi->clk_ipg);
 	clk_disable_unprepare(fbi->clk_ahb);
+	clk_disable_unprepare(fbi->clk_ipg);
 	fbi->enabled = false;
 
 	writel(0, fbi->regs + LCDC_RMCR);
@@ -532,8 +552,7 @@ static int imxfb_blank(int blank, struct fb_info *info)
 		break;
 
 	case FB_BLANK_UNBLANK:
-		imxfb_enable_controller(fbi);
-		break;
+		return imxfb_enable_controller(fbi);
 	}
 	return 0;
 }
-- 
2.8.0.rc3



From jjhiblot at traphandler.com  Wed May  4 03:06:43 2016
From: jjhiblot at traphandler.com (Jean-Jacques Hiblot)
Date: Wed, 4 May 2016 12:06:43 +0200
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop> <20160503185153.5cfddc32@bbrezillon>
 <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
Message-ID: <CACh+v5O2XpJyYWz70pVgtU5-g9td6J7EdmNtJwk0s5SUkAywaQ@mail.gmail.com>

2016-05-03 21:11 GMT+02:00 Rob Herring <robh at kernel.org>:
> On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
> <boris.brezillon at free-electrons.com> wrote:
>> Hi Rob,
>>
>> On Tue, 3 May 2016 11:40:19 -0500
>> Rob Herring <robh at kernel.org> wrote:
>>
>>> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:
>>> > The EBI (External Bus Interface) is used to access external peripherals
>>> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
>>> > Each device is assigned a CS line and an address range and can have its
>>> > own configuration (timings, access mode, bus width, ...).
>>> > This driver provides a generic DT binding to configure a device according
>>> > to its requirements.
>>> > For specific device controllers (like the NAND one) the SMC timings
>>> > should be configured by the controller driver through the matrix and smc
>>> > syscon regmaps.
>>> >
>>> > Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
>>> > ---
>>> >  .../bindings/memory-controllers/atmel,ebi.txt      | 136 +++++++++++++++++++++
>>> >  1 file changed, 136 insertions(+)
>>> >  create mode 100644 Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
>>> >
>>> > diff --git a/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
>>> > new file mode 100644
>>> > index 0000000..a6dca5c
>>> > --- /dev/null
>>> > +++ b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
>>> > @@ -0,0 +1,136 @@
>>> > +* Device tree bindings for Atmel EBI
>>> > +
>>> > +The External Bus Interface (EBI) controller is a bus where you can connect
>>> > +asynchronous (NAND, NOR, SRAM, ....) and synchronous memories (SDR/DDR SDRAMs).
>>> > +The EBI provides a glue-less interface to asynchronous memories through the SMC
>>> > +(Static Memory Controller).
>>> > +
>>> > +Required properties:
>>> > +
>>> > +- compatible:              "atmel,at91sam9260-ebi"
>>> > +                   "atmel,at91sam9261-ebi"
>>> > +                   "atmel,at91sam9263-ebi0"
>>> > +                   "atmel,at91sam9263-ebi1"
>>>
>>> What are the differences between 0 and 1?
>>
>> Because this SoC has 2 EBI busses with different capabilities.
>
> Okay, correct answer. :)
>
> [...]
>
>>>
>>> > +                   of the memory region requested by the device.
>>> > +
>>> > +EBI bus configuration associated with specific chip-select will be defined in
>>> > +the configs subnode. This configs node will in turn contain several subnodes
>>> > +named config-<cs-id>, each of them containing the following properties.
>>>
>>> This is a bit unusual. Why not just part of the child device nodes?
>>
>> Oh, come on! I reworked the binding because Mark complained about the
>> previous binding which was doing exactly what you're suggesting. Can
>> you please be consistent in your reviews...
>
> No, Mark and I both have our opinions. Which part of this patch
> explains the history? If the revision history is not in the patch, I'm
> not looking at it.
>
> My issue with it this way is that it has invented yet another way to
> describe timings. I would like to be consistent across external bus
> descriptions, but we're not very consistent to begin with though. The
> most common seems to be the way you first did it. But I agree that it
> is kind of screwy to have an intermediate node unless the controller
> itself has sub-blocks within it and is not the established way to
> describe a bus with chip selects. I would either put the properties
> directly in the child nodes (e.g. flash at 0,0) or put your config nodes
> in the device node. I'd call it timings instead of config, but that's
> just bikeshedding.
>
> memory-controller at 1000 {
>   ...
>   flash at 0,0 {
>     timings {
>       ...
>     };
>   };
> };
>

I don't think the timings belong in the child node as they really are
for the chip select and the chip select may select several devices at
once. I'm thinking (again) of a FPGA here that could implement or
example 4 serial ports at different addresses.

JJ

>>> > +
>>> > +Optional config-<cs-id> node properties:
>>> > +
>>> > +- atmel,bus-width:         width of the asynchronous device's data bus
>>> > +                           8, 16 or 32.
>>> > +                           Default to 8 when undefined.
>>> > +
>>> > +- atmel,byte-access-type   "write" or "select" (see Atmel datasheet).
>>> > +                           Default to "select" when undefined.
>>> > +
>>> > +- atmel,read-mode          "nrd" or "ncs".
>>> > +                           Default to "ncs" when undefined.
>>> > +
>>> > +- atmel,write-mode         "nwe" or "ncs".
>>> > +                           Default to "ncs" when undefined.
>>> > +
>>> > +- atmel,exnw-mode          "disabled", "frozen" or "ready".
>>> > +                           Default to "disabled" when undefined.
>>> > +
>>> > +- atmel,page-mode          enable page mode if present. The provided value
>>> > +                           defines the page size (supported values: 4, 8,
>>> > +                           16 and 32).
>>> > +
>>> > +- atmel,tdf-mode:          "normal" or "optimized". When set to
>>>
>>> This should be boolean.
>>
>> It was a formerly defined as a boolean, and when it's done like that we
>> have no way to identify whether the property was forgotten or
>> intentionally set to normal mode. What's the problem with this approach?
>
> Only preference to use boolean when that is sufficient. With your
> argument, then we should never have booleans. You state that missing
> means "normal", not forgotten, so all these properties should be
> required with no default.
>
> BTW, I debated the same thing on the other properties, but I could see
> them being expanded to a 3rd mode. I don't see that here though.
>
> Rob


From hramrach at gmail.com  Wed May  4 03:25:33 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: Wed, 4 May 2016 12:25:33 +0200
Subject: [linux-sunxi] [PATCH] musb: sunxi: Ignore VBus errors in
 host-only mode
In-Reply-To: <20150914202533.GF4684@lukather>
References: <1438723553-4136-1-git-send-email-hdegoede@redhat.com>
 <55C31963.2010701@schinagl.nl> <55C3709C.4080609@redhat.com>
 <55C47041.3000603@schinagl.nl> <55E93D8C.9020804@schinagl.nl>
 <55F1CA9B.3070204@redhat.com> <20150910183017.GN9885@lukather>
 <55F1CE2E.7010409@redhat.com> <20150914202533.GF4684@lukather>
Message-ID: <CAOMqctTa7Q-_dSf_4HaGt34=+YF4Sct=WvHjzp-n67J72zyLrA@mail.gmail.com>

On 14 September 2015 at 22:25, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> On Thu, Sep 10, 2015 at 08:38:38PM +0200, Hans de Goede wrote:
>> Hi,
>>
>> On 10-09-15 20:30, Maxime Ripard wrote:
>> >On Thu, Sep 10, 2015 at 08:23:23PM +0200, Hans de Goede wrote:
>> >>Hi,
>> >>
>> >>On 04-09-15 08:43, Olliver Schinagl wrote:
>> >>>Hey Hans,
>> >>>
>> >>>On 07-08-15 10:45, Olliver Schinagl wrote:
>> >>>><snip>
>> >>>>>If you change the dr_mode to host then you _must_ also remove any id_det and vbus_det
>> >>>>>gpio settings from the usb_phy node in the dts, as the sun4i phy code detects
>> >>>>>host vs otg mode by checking for the presence of these.
>> >>>>Yes, this fixes it and makes it work. Thanks.
>> >>>>
>> >>>I've been going back to this and am wondering if this is something I can look into to fix properly? E.g. if the dts sets dr_mode = host, can we simply ignore the pins and treat them as unset?
>> >>
>> >>AFAIK you cannot unset something in dts. The only solution I
>> >>can comeup with is to add a dr_mode argument to the phy like
>> >>we already have for the otg controller itself.
>> >>
>> >>This is something which we likely need to do anyways to add
>> >>support for peripheral only mode, which we seem to need for
>> >>some "hdmi sticks".
>> >
>> >I haven't really followed the rest of the discussion, so sorry if you
>> >already talked about that, but why can't you just set the dr_mode to
>> >peripheral in such a case?
>>
>> This is about the usbphy code not the musb-controller code, which are
>> 2 different dts nodes, atm only the musb-controller node has a
>> dr_mode property, and the phy code decides between host-only
>> and otg mode based on whether an id pin is assigned or not.
>>
>> My proposal is to get rid of the id-pin hack to determine the mode
>> and add a dr_mode property to the usbphy dts node.
>
> I agree that we should get rid of that hack, especially since a lack
> of an ID pin might also be used on a peripheral-only device.
>
> However, we already have that information in the musb node, and
> duplicating the info seems error prone. We already have a custom
> function, maybe that's a case for another one, and that would allow to
> handle "hard" cases more easily (like CONFIG_USB_MUSB_HOST selected,
> with the otg node set to otg).
>

Hello,

was this solved somehow?

What problem is there with referencing the phy node?

Just like pinmux setting nodes and whatnot it can be named and
referenced by name.

Thanks

Michal


From andre.przywara at arm.com  Wed May  4 03:37:51 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 4 May 2016 11:37:51 +0100
Subject: [PATCH v2 06/54] KVM: arm/arm64: arch_timer: Remove irq_phys_map
In-Reply-To: <572783E2.30204@linaro.org>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-7-git-send-email-andre.przywara@arm.com>
 <572783E2.30204@linaro.org>
Message-ID: <5729D0FF.1030604@arm.com>

Hi Eric,

On 02/05/16 17:44, Eric Auger wrote:
> On 04/28/2016 06:45 PM, Andre Przywara wrote:
>> Now that the interface between the arch timer and the VGIC does not
>> require passing the irq_phys_map entry pointer anymore, let's remove
>> it from the virtual arch timer and use the virtual IRQ number instead
>> directly.
>> The remaining pointer returned by kvm_vgic_map_phys_irq() will be
>> removed in the following patch.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog v1 .. v2:
>> - remove extra virt_irq member from struct, instead use irq.irq directly
>>
>>  include/kvm/arm_arch_timer.h |  3 ---
>>  virt/kvm/arm/arch_timer.c    | 11 +++++------
>>  2 files changed, 5 insertions(+), 9 deletions(-)
>>
>> diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
>> index b651aed..a47b7de 100644
>> --- a/include/kvm/arm_arch_timer.h
>> +++ b/include/kvm/arm_arch_timer.h
>> @@ -53,9 +53,6 @@ struct arch_timer_cpu {
>>  	/* Timer IRQ */
>>  	struct kvm_irq_level		irq;
>>  
>> -	/* VGIC mapping */
>> -	struct irq_phys_map		*map;
>> -
>>  	/* Active IRQ state caching */
>>  	bool				active_cleared_last;
>>  };
>> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
>> index b470632..3a74b17 100644
>> --- a/virt/kvm/arm/arch_timer.c
>> +++ b/virt/kvm/arm/arch_timer.c
>> @@ -175,10 +175,10 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
>>  
>>  	timer->active_cleared_last = false;
>>  	timer->irq.level = new_level;
>> -	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
>> +	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
>>  				   timer->irq.level);
>>  	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
>> -					 timer->map->virt_irq,
>> +					 timer->irq.irq,
>>  					 timer->irq.level);
>>  	WARN_ON(ret);
>>  }
>> @@ -276,7 +276,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
>>  	* exit.
>>  	*/
>>  	phys_active = timer->irq.level ||
>> -			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
>> +			kvm_vgic_map_is_active(vcpu, timer->irq.irq);
>>  
>>  	/*
>>  	 * We want to avoid hitting the (re)distributor as much as
>> @@ -378,7 +378,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
>>  	if (WARN_ON(IS_ERR(map)))
>>  		return PTR_ERR(map);
>>  
>> -	timer->map = map;
>>  	return 0;
>>  }
>>  
>> @@ -521,8 +520,8 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
>>  	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
>>  
>>  	timer_disarm(timer);
>> -	if (timer->map)
>> -		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
>> +	if (timer->irq.irq)
>> +		kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq);
> thought you agreed to always unmap. Is it an oversight or did you change
> your mind?

I wasn't sure about it. So for the old VGIC implementation having an
illegal IRQ number seems to be fine (just nothing will be found in the
map search), but on the new VGIC it will trigger a BUG_ON, so I was
wondering if we should play safe here and also mimic the current code,
which does this safety check for some reason.

But looking at the (current) callers again, it looks like there is
always "27" passed in here anyways, so I guess we are safe to remove it.

So if no-one intervenes, I will remove the check.

Cheers,
Andre.

> Besides Reviewed-by: Eric Auger <eric.auger at linaro.org>
> 
> Cheers
> 
> Eric
>>  }
>>  
>>  void kvm_timer_enable(struct kvm *kvm)
>>
> 


From suzuki.poulose at arm.com  Wed May  4 03:41:24 2016
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Wed,  4 May 2016 11:41:24 +0100
Subject: [PATCH] coresight: Handle build path error
Message-ID: <1462358484-9342-1-git-send-email-suzuki.poulose@arm.com>

Enabling a component via sysfs (echo 1 > enable_source), would
trigger building a path from the enabled sources to the sink.
If there is an error in the process (e.g, sink not enabled or
the device (CPU corresponding to ETM) is not online), we never report
failure, except for leaving a message in the dmesg.

Do proper error checking for the build path and return the error.

Before:
 $ echo 0 > /sys/devices/system/cpu/cpu2/online
 $ echo 1 > /sys/devices/cs_etm/cpu2/enable_source
 $ echo $?
 0

After:
 $ echo 0 > /sys/devices/system/cpu/cpu2/online
 $ echo 1 > /sys/devices/cs_etm/cpu2/enable_source
 -bash: echo: write error: No such device or address

Cc: Mathie Porier <mathieu.poirier at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 2ea5961..e0c5166 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -393,6 +393,7 @@ out:
 struct list_head *coresight_build_path(struct coresight_device *csdev)
 {
 	struct list_head *path;
+	int rc;
 
 	path = kzalloc(sizeof(struct list_head), GFP_KERNEL);
 	if (!path)
@@ -400,9 +401,10 @@ struct list_head *coresight_build_path(struct coresight_device *csdev)
 
 	INIT_LIST_HEAD(path);
 
-	if (_coresight_build_path(csdev, path)) {
+	rc = _coresight_build_path(csdev, path);
+	if (rc) {
 		kfree(path);
-		path = NULL;
+		return ERR_PTR(rc);
 	}
 
 	return path;
@@ -448,8 +450,9 @@ int coresight_enable(struct coresight_device *csdev)
 		goto out;
 
 	path = coresight_build_path(csdev);
-	if (!path) {
+	if (IS_ERR(path)) {
 		pr_err("building path(s) failed\n");
+		ret = PTR_ERR(path);
 		goto out;
 	}
 
-- 
1.7.9.5



From andre.przywara at arm.com  Wed May  4 03:44:48 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 4 May 2016 11:44:48 +0100
Subject: [PATCH v3] sunxi-irq: Fix Kconfig dependency on GENERIC_IRQ_CHIP
In-Reply-To: <20160502064854.GL17159@lukather>
References: <1461546292-21110-1-git-send-email-andre.przywara@arm.com>
 <20160502064854.GL17159@lukather>
Message-ID: <5729D2A0.70900@arm.com>

Hi Maxime,

On 02/05/16 07:48, Maxime Ripard wrote:
> Hi,
> 
> On Mon, Apr 25, 2016 at 02:04:52AM +0100, Andre Przywara wrote:
>> The Allwinner NMI irqchip driver requires GENERIC_IRQ_CHIP, but
>> we can't select it directly, because there is no specific Kconfig entry
>> for the driver. Compiling this NMI driver with certain arm64
>> configurations thus fails due to the missing dependency:
>>
>> drivers/built-in.o: In function `sunxi_sc_nmi_set_type':
>> drivers/irqchip/irq-sunxi-nmi.c:114: undefined reference to `irq_setup_alt_chip'
>> drivers/built-in.o: In function `irq_domain_add_linear':
>> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
>> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
>> drivers/built-in.o: In function `sunxi_sc_nmi_irq_init':
>> drivers/irqchip/irq-sunxi-nmi.c:146: undefined reference to `irq_alloc_domain_generic_chips'
>> drivers/irqchip/irq-sunxi-nmi.c:161: undefined reference to `irq_get_domain_generic_chip'
>> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
>> drivers/irqchip/irq-sunxi-nmi.c:171: undefined reference to `irq_gc_mask_set_bit'
>> drivers/irqchip/irq-sunxi-nmi.c:172: undefined reference to `irq_gc_ack_set_bit'
>> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
>>
>> Add separate Kconfig options for both Allwinner specific irqchip
>> drivers and select GENERIC_IRQ_CHIP for the NMI driver.
>> The older sun4i IRQ driver only gets selected when support for these
>> specific SoCs is compiled, while the NMI driver is selected for all
>> Allwinner SoCs (copying the current behaviour and covering future SoCs
>> automatically).
>>
>> Reported-by: Suzuki K Poulose <Suzuki.Poulose at arm.com>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Hi,
>>
>> this is a new approach to the problem that Suzuki tried to address
>> already.
>> It separates the sun4i IRQ controller driver and the NMI driver as
>> Maxime requested.
>> While there should be no difference for the NMI driver, the sun4i
>> driver now only gets selected for certain SoCs, which is admittedly
>> a bold call for -rc5. If people find this too risky, I can bring the
>> sun4i in line with the NMI driver (selected for all ARCH_SUNXI) for
>> this release and re-create the more selective dependency as a merge
>> window patch, so that it gets more testing.
>> Please let me know.
>>
>> Cheers,
>> Andre.
>>
>>  arch/arm/mach-sunxi/Kconfig | 3 ++-
>>  drivers/irqchip/Kconfig     | 8 ++++++++
>>  drivers/irqchip/Makefile    | 4 ++--
>>  3 files changed, 12 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
>> index c124d65..c092bc2 100644
>> --- a/arch/arm/mach-sunxi/Kconfig
>> +++ b/arch/arm/mach-sunxi/Kconfig
>> @@ -4,7 +4,6 @@ menuconfig ARCH_SUNXI
>>  	select ARCH_REQUIRE_GPIOLIB
>>  	select ARCH_HAS_RESET_CONTROLLER
>>  	select CLKSRC_MMIO
>> -	select GENERIC_IRQ_CHIP
>>  	select PINCTRL
>>  	select SUN4I_TIMER
>>  	select RESET_CONTROLLER
>> @@ -14,11 +13,13 @@ if ARCH_SUNXI
>>  config MACH_SUN4I
>>  	bool "Allwinner A10 (sun4i) SoCs support"
>>  	default ARCH_SUNXI
>> +	select SUN4I_IRQCHIP
>>  
>>  config MACH_SUN5I
>>  	bool "Allwinner A10s / A13 (sun5i) SoCs support"
>>  	default ARCH_SUNXI
>>  	select SUN5I_HSTIMER
>> +	select SUN4I_IRQCHIP
>>  
>>  config MACH_SUN6I
>>  	bool "Allwinner A31 (sun6i) SoCs support"
>> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
>> index 3e12479..94f3f42 100644
>> --- a/drivers/irqchip/Kconfig
>> +++ b/drivers/irqchip/Kconfig
>> @@ -165,6 +165,14 @@ config ST_IRQCHIP
>>  	help
>>  	  Enables SysCfg Controlled IRQs on STi based platforms.
>>  
>> +config SUN4I_IRQCHIP
>> +	bool
>> +
>> +config SUNXI_NMI
>> +	bool "Allwinner SoC NMI controller"
>> +	default ARCH_SUNXI
>> +	select GENERIC_IRQ_CHIP
> 
> This one is only used on SUN6I, SUN7I and SUN8I. There's no need to
> enable it for all the SoCs.

But it is enabled for all SoCs at the moment - and as it is actually a
fix (-rc1 does not compile for certain arm64 configs) I'd really like to
not take chances here.
As mentioned I am happy to send a follow up patch to restrict it further
- given that it gets more testing, but at the moment I'd really like to
just fix the arm64 build without accidentally breaking existing arm(32)
boards.

Also as you mention sun8i here: AFAIK the H3, which I consider the
32-bit sibling of the A64, is an sun8i, so it will include the code, but
the A64 does not (atm) - which is a bit strange.
As I don't plan to have MACH_SUN<n>I defines for arm64 unless
desperately necessary, I'd really like to keep in on ARCH_SUNXI as it is
in the moment.

So how do we proceed from here?
Is this too late for 4.6 now? That would be a pity as this qualifies as
a fix. If not, I'd rather take this conservative patch for now and put a
more fine grained selection into -next (or 4.7-rc1).

Cheers,
Andre.


From chunfeng.yun at mediatek.com  Wed May  4 03:54:21 2016
From: chunfeng.yun at mediatek.com (chunfeng yun)
Date: Wed, 4 May 2016 18:54:21 +0800
Subject: [PATCH] usb: xhci-mtk: fixup mouse wakeup failure during system
 suspend
In-Reply-To: <871t5ifdxk.fsf@intel.com>
References: <1461204293-18243-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462261458.11651.7.camel@mhfsdcap03> <87vb2vfujq.fsf@intel.com>
 <1462266591.11651.34.camel@mhfsdcap03> <87mvo7fpuc.fsf@intel.com>
 <1462324873.11651.57.camel@mhfsdcap03> <871t5ifdxk.fsf@intel.com>
Message-ID: <1462359261.11651.69.camel@mhfsdcap03>

Hi,

On Wed, 2016-05-04 at 11:03 +0300, Felipe Balbi wrote:
> Hi,
> 
> chunfeng yun <chunfeng.yun at mediatek.com> writes:
> > On Tue, 2016-05-03 at 12:33 +0300, Felipe Balbi wrote:
> >> Hi,
> >> 
> >> chunfeng yun <chunfeng.yun at mediatek.com> writes:
> >> >> chunfeng yun <chunfeng.yun at mediatek.com> writes:
> >> >> > On Thu, 2016-04-21 at 10:04 +0800, Chunfeng Yun wrote:
> >> >> >> Click mouse after xhci suspend completion but before system suspend
> >> >> >> completion, system will not be waken up by mouse if the duration of
> >> >> >> them is larger than 20ms which is the device UFP's resume signaling
> >> >> 
> >> >> what is "them" here ? The duration of what is longer than 20ms ?
> >> > They are "xhci suspend completion" and "system suspend completion";
> >> >
> >> > It's time duration
> >> 
> >> okay. So if xhci suspend takes longer than 20ms your SPM doesn't see a
> >> wakeup ?
> > It is not the time of xhci suspend consumed, but is the time of duration
> > from xhci suspend completion to system suspend completion(after BOOT-CPU
> > is turned off, SPM will be enabled to receive wakeup event)
> 
> Okay, so SPM will be the entity actually handling wakeups, right ? I'm
> assuming something like this happens:
> 
> echo mem > /sys/power/state
>  /* start suspending devices */
>   xhci_suspend()
>  /* all devices suspended */
>  enable_spm()
> 
> so, if a mouse button is pressed after xhci_suspend() returns but before
> enable_spm() runs, then we're gonna miss that event, am I right ?
Yes, you are right.
> 
> I can't think of any way to sort this out. Let's ask on linux-pm (I've
> added linux-pm to Cc list)
Thanks
> 
> >> >> >> lasted. Another reason is that the SPM is not enabled before system
> >> >> 
> >> >> what's SPM ?
> >> > It is System Power Management which is powered off when system is
> >> > running in normal mode, and is powered on when system enters suspend
> >> > mode. It is used to wakeup system when some wakeup sources, such as
> >> > bluetooth or powerkey etc, tigger wakeup event.
> >> 
> >> okay, thanks
> >> 
> >> >> >> suspend compeltion, this causes SPM also not notice the resume signal.
> >> >>            ^^^^^^^^^^
> >> >>            completion
> >> >> 
> >> >> >> So in order to reduce the duration less than 20ms, make use of
> >> >> >> syscore's suspend/resume interface.
> >> >> 
> >> >> no, this is the wrong approach
> >> > But it seems only one workable approach from software side
> >> 
> >> I wouldn't say that. It seems to me SPM should be enabled earlier.
> > Yes, but normally SPM should be enabled after all CPUS are turned off,
> > so it's difficult to do that, I mean enable SPM before turning off CPUS
> 
> is it a requirement that SPM should be enabled only after all CPUs are
> turned off ? If that's the case, then any device in the system might
> have missed wakeups. This doesn't seem like a good design to me; unless
> I'm missing something...
Yes, it's a requirement.

If the wakeup source is level trigger, and will keep it until SPM notice
it. Although USB wakeup is level trigger, but it just last at most 20ms
and clear itself automatically.

> 
> >> >> >> Because the syscore runs on irq disabled context, and xhci's
> >> >> >> suspend/resume calls some sleeping functions, enable local irq
> >> >> >> and then disable it during suspend/resume. This may be not a problem,
> >> >> >> since only boot CPU is runing.
> >> >> 
> >> >> another problem :) calling local_irq_{enable,disable}() is an indication
> >> >> that something's wrong.
> >> > Oh!
> >> >
> >> > BTW: There will be warning logs if they are not called.
> >> 
> >> yeah, I got that :-) But it's still wrong to use
> >> local_irq_{enable,disable}() the way you're using them :-)
> > Yes
> >
> > Thank you very much.
> >> 
> >
> >
> 




From stefan.wahren at i2se.com  Wed May  4 04:03:04 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Wed, 4 May 2016 13:03:04 +0200
Subject: [PATCH v3 2/2] nvmem: mxs-ocotp: remove nvmem regmap dependency
In-Reply-To: <1462214174-469-3-git-send-email-srinivas.kandagatla@linaro.org>
References: <1462214174-469-1-git-send-email-srinivas.kandagatla@linaro.org>
 <1462214174-469-3-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <5729D6E8.8060808@i2se.com>

Am 02.05.2016 um 20:36 schrieb Srinivas Kandagatla:
> Regmap raw accessors are bus specific implementations, using regmap raw
> apis in nvmem breaks nvmem providers based on regmap mmio.
> This patch moves to nvmem support in the driver to use callback
> instead of regmap, which is what the nvmem core supports now.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
> ---

Acked-by: Stefan Wahren <stefan.wahren at i2se.com>


From p.zabel at pengutronix.de  Wed May  4 04:13:23 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Wed, 04 May 2016 13:13:23 +0200
Subject: [PATCH v2 1/3] video: fbdev: imxfb: fix semantic of .get_power
 and .set_power
In-Reply-To: <1462354998-5792-2-git-send-email-u.kleine-koenig@pengutronix.de>
References: <1462354998-5792-1-git-send-email-u.kleine-koenig@pengutronix.de>
 <1462354998-5792-2-git-send-email-u.kleine-koenig@pengutronix.de>
Message-ID: <1462360403.3536.2.camel@pengutronix.de>

Am Mittwoch, den 04.05.2016, 11:43 +0200 schrieb Uwe Kleine-K?nig:
> .set_power gets passed an FB_BLANK_XXX value, not a bool. So 0 signals
> on; and >1 means off. The same applies for return values of .get_power.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>

Reviewed-by: Philipp Zabel <p.zabel at pengutronix.de>

regards
Philipp



From yehuday at marvell.com  Wed May  4 04:17:44 2016
From: yehuday at marvell.com (Yehuda Yitschak)
Date: Wed, 4 May 2016 11:17:44 +0000
Subject: [PATCH v8 0/7] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part
 3/3: vfio changes
In-Reply-To: <1461832118-5668-1-git-send-email-eric.auger@linaro.org>
References: <1461832118-5668-1-git-send-email-eric.auger@linaro.org>
Message-ID: <43c26d74c99f40d4b85347c71aa37b1d@IL-EXCH02.marvell.com>


Tested-by: Yehuda Yitschak <yehuday at marvell.com>

Tested on Armada-7040 using an intel IXGBE (82599ES). 

> -----Original Message-----
> From: linux-arm-kernel [mailto:linux-arm-kernel-
> bounces at lists.infradead.org] On Behalf Of Eric Auger
> Sent: Thursday, April 28, 2016 11:29
> To: eric.auger at st.com; eric.auger at linaro.org; robin.murphy at arm.com;
> alex.williamson at redhat.com; will.deacon at arm.com; joro at 8bytes.org;
> tglx at linutronix.de; jason at lakedaemon.net; marc.zyngier at arm.com;
> christoffer.dall at linaro.org; linux-arm-kernel at lists.infradead.org
> Cc: julien.grall at arm.com; patches at linaro.org; Jean-
> Philippe.Brucker at arm.com; p.fedin at samsung.com; linux-
> kernel at vger.kernel.org; Bharat.Bhushan at freescale.com;
> iommu at lists.linux-foundation.org; pranav.sawargaonkar at gmail.com
> Subject: [PATCH v8 0/7] KVM PCIe/MSI passthrough on ARM/ARM64: kernel
> part 3/3: vfio changes
> 
> This series allows the user-space to register a reserved IOVA domain.
> This completes the kernel integration of the whole functionality on top of
> part 1 & 2.
> 
> It also depends on [PATCH 1/3] iommu: Add MMIO mapping type series,
> http://comments.gmane.org/gmane.linux.kernel.iommu/12869
> 
> We reuse the VFIO DMA MAP ioctl with a new flag to bridge to the msi-
> iommu API. The need for provisioning such MSI IOVA range is reported
> through the VFIO_IOMMU_GET_INFO iotcl.
> 
> vfio_iommu_type1 checks if the MSI mapping is safe when attaching the vfio
> group to the container (allow_unsafe_interrupts modality).
> 
> On ARM/ARM64, the IOMMU does not astract IRQ remapping. the modality
> is abstracted on MSI controller side. The GICv3 ITS is the first controller
> advertising the modality.
> 
> More details & context can be found at:
> http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-
> armarm64/
> 
> Best Regards
> 
> Eric
> 
> Testing:
> - functional on ARM64 AMD Overdrive HW (single GICv2m frame) with
>   Intel X540-T2 (SR-IOV capable)
> - Not tested: ARM GICv3 ITS
> 
> References:
> [1] [RFC 0/2] VFIO: Add virtual MSI doorbell support
>     (https://lkml.org/lkml/2015/7/24/135)
> [2] [RFC PATCH 0/6] vfio: Add interface to map MSI pages
>     (https://lists.cs.columbia.edu/pipermail/kvmarm/2015-
> September/016607.html)
> [3] [PATCH v2 0/3] Introduce MSI hardware mapping for VFIO
> 
> (http://permalink.gmane.org/gmane.comp.emulators.kvm.arm.devel/3858)
> 
> Git: complete series available at
> https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-
> rc5-pcie-passthrough-v8
> 
> previous version at
> https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-
> rc4-pcie-passthrough-v7
> 
> QEMU Integration:
> [RFC v2 0/8] KVM PCI/MSI passthrough with mach-virt
> (http://lists.gnu.org/archive/html/qemu-arm/2016-01/msg00444.html)
> https://git.linaro.org/people/eric.auger/qemu.git/shortlog/refs/heads/v2.5.
> 0-pci-passthrough-rfc-v2
> 
> History:
> v7 -> v8:
> - use renamed msi-iommu API
> - VFIO only responsible for setting the IOVA aperture
> - use new DOMAIN_ATTR_MSI_GEOMETRY iommu domain attribute
> 
> v6 -> v7:
> - vfio_find_dma now accepts a dma_type argument.
> - should have recovered the capability to unmap the whole user IOVA range
> - remove computation of nb IOVA pages -> will post a separate RFC for that
>   while respinning the QEMU part
> 
> RFC v5 -> patch v6:
> - split to ease the review process
> 
> RFC v4 -> RFC v5:
> - take into account Thomas' comments on MSI related patches
>   - split "msi: IOMMU map the doorbell address when needed"
>   - increase readability and add comments
>   - fix style issues
>  - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
>  - platform ITS now advertises IOMMU_CAP_INTR_REMAP
>  - fix compilation issue with CONFIG_IOMMU API unset
>  - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING
> 
> RFC v3 -> v4:
> - Move doorbell mapping/unmapping in msi.c
> - fix ref count issue on set_affinity: in case of a change in the address
>   the previous address is decremented
> - doorbell map/unmap now is done on msi composition. Should allow the use
>   case for platform MSI controllers
> - create dma-reserved-iommu.h/c exposing/implementing a new API
> dedicated
>   to reserved IOVA management (looking like dma-iommu glue)
> - series reordering to ease the review:
>   - first part is related to IOMMU
>   - second related to MSI sub-system
>   - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP
> removal)
> - expose the number of requested IOVA pages through
> VFIO_IOMMU_GET_INFO
>   [this partially addresses Marc's comments on
> iommu_get/put_single_reserved
>    size/alignment problematic - which I did not ignore - but I don't know
>    how much I can do at the moment]
> 
> RFC v2 -> RFC v3:
> - should fix wrong handling of some CONFIG combinations:
>   CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
> - fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)
> 
> PATCH v1 -> RFC v2:
> - reverted to RFC since it looks more reasonable ;-) the code is split
>   between VFIO, IOMMU, MSI controller and I am not sure I did the right
>   choices. Also API need to be further discussed.
> - iova API usage in arm-smmu.c.
> - MSI controller natively programs the MSI addr with either the PA or IOVA.
>   This is not done anymore in vfio-pci driver as suggested by Alex.
> - check irq remapping capability of the group
> 
> RFC v1 [2] -> PATCH v1:
> - use the existing dma map/unmap ioctl interface with a flag to register a
>   reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
> - a single reserved IOVA contiguous region now is allowed
> - use of an RB tree indexed by PA to store allocated reserved slots
> - use of a vfio_domain iova_domain to manage iova allocation within the
>   window provided by the userspace
> - vfio alloc_map/unmap_free take a vfio_group handle
> - vfio_group handle is cached in vfio_pci_device
> - add ref counting to bindings
> - user modality enabled at the end of the series
> 
> 
> Eric Auger (7):
>   vfio: introduce a vfio_dma type field
>   vfio/type1: vfio_find_dma accepting a type argument
>   vfio/type1: bypass unmap/unpin and replay for VFIO_IOVA_RESERVED slots
>   vfio: allow reserved msi iova registration
>   vfio/type1: also check IRQ remapping capability at msi domain
>   iommu/arm-smmu: do not advertise IOMMU_CAP_INTR_REMAP
>   vfio/type1: return MSI mapping requirements with
> VFIO_IOMMU_GET_INFO
> 
>  drivers/iommu/arm-smmu-v3.c     |   3 +-
>  drivers/iommu/arm-smmu.c        |   3 +-
>  drivers/vfio/vfio_iommu_type1.c | 227
> +++++++++++++++++++++++++++++++++++++---
>  include/uapi/linux/vfio.h       |  14 ++-
>  4 files changed, 230 insertions(+), 17 deletions(-)
> 
> --
> 1.9.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From eric.auger at linaro.org  Wed May  4 04:29:25 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed, 4 May 2016 13:29:25 +0200
Subject: [PATCH v8 0/7] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part
 3/3: vfio changes
In-Reply-To: <43c26d74c99f40d4b85347c71aa37b1d@IL-EXCH02.marvell.com>
References: <1461832118-5668-1-git-send-email-eric.auger@linaro.org>
 <43c26d74c99f40d4b85347c71aa37b1d@IL-EXCH02.marvell.com>
Message-ID: <5729DD15.1010509@linaro.org>

Hi Yehuda,
On 05/04/2016 01:17 PM, Yehuda Yitschak wrote:
> 
> Tested-by: Yehuda Yitschak <yehuday at marvell.com>
Many thanks for the T-b!

I'am about to submit a small update on part I & III today (v9), taking
into account Alex' last comments. MSI layer part (II) is left unchanged
(v8).

The way I am going to report the need for MSI mapping on user-side
changes and I will respin the QEMU part accordingly. Besides, this info
was not yet used in the QEMU integration.

Best Regards

Eric
> 
> Tested on Armada-7040 using an intel IXGBE (82599ES). 
> 
>> -----Original Message-----
>> From: linux-arm-kernel [mailto:linux-arm-kernel-
>> bounces at lists.infradead.org] On Behalf Of Eric Auger
>> Sent: Thursday, April 28, 2016 11:29
>> To: eric.auger at st.com; eric.auger at linaro.org; robin.murphy at arm.com;
>> alex.williamson at redhat.com; will.deacon at arm.com; joro at 8bytes.org;
>> tglx at linutronix.de; jason at lakedaemon.net; marc.zyngier at arm.com;
>> christoffer.dall at linaro.org; linux-arm-kernel at lists.infradead.org
>> Cc: julien.grall at arm.com; patches at linaro.org; Jean-
>> Philippe.Brucker at arm.com; p.fedin at samsung.com; linux-
>> kernel at vger.kernel.org; Bharat.Bhushan at freescale.com;
>> iommu at lists.linux-foundation.org; pranav.sawargaonkar at gmail.com
>> Subject: [PATCH v8 0/7] KVM PCIe/MSI passthrough on ARM/ARM64: kernel
>> part 3/3: vfio changes
>>
>> This series allows the user-space to register a reserved IOVA domain.
>> This completes the kernel integration of the whole functionality on top of
>> part 1 & 2.
>>
>> It also depends on [PATCH 1/3] iommu: Add MMIO mapping type series,
>> http://comments.gmane.org/gmane.linux.kernel.iommu/12869
>>
>> We reuse the VFIO DMA MAP ioctl with a new flag to bridge to the msi-
>> iommu API. The need for provisioning such MSI IOVA range is reported
>> through the VFIO_IOMMU_GET_INFO iotcl.
>>
>> vfio_iommu_type1 checks if the MSI mapping is safe when attaching the vfio
>> group to the container (allow_unsafe_interrupts modality).
>>
>> On ARM/ARM64, the IOMMU does not astract IRQ remapping. the modality
>> is abstracted on MSI controller side. The GICv3 ITS is the first controller
>> advertising the modality.
>>
>> More details & context can be found at:
>> http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-
>> armarm64/
>>
>> Best Regards
>>
>> Eric
>>
>> Testing:
>> - functional on ARM64 AMD Overdrive HW (single GICv2m frame) with
>>   Intel X540-T2 (SR-IOV capable)
>> - Not tested: ARM GICv3 ITS
>>
>> References:
>> [1] [RFC 0/2] VFIO: Add virtual MSI doorbell support
>>     (https://lkml.org/lkml/2015/7/24/135)
>> [2] [RFC PATCH 0/6] vfio: Add interface to map MSI pages
>>     (https://lists.cs.columbia.edu/pipermail/kvmarm/2015-
>> September/016607.html)
>> [3] [PATCH v2 0/3] Introduce MSI hardware mapping for VFIO
>>
>> (http://permalink.gmane.org/gmane.comp.emulators.kvm.arm.devel/3858)
>>
>> Git: complete series available at
>> https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-
>> rc5-pcie-passthrough-v8
>>
>> previous version at
>> https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-
>> rc4-pcie-passthrough-v7
>>
>> QEMU Integration:
>> [RFC v2 0/8] KVM PCI/MSI passthrough with mach-virt
>> (http://lists.gnu.org/archive/html/qemu-arm/2016-01/msg00444.html)
>> https://git.linaro.org/people/eric.auger/qemu.git/shortlog/refs/heads/v2.5.
>> 0-pci-passthrough-rfc-v2
>>
>> History:
>> v7 -> v8:
>> - use renamed msi-iommu API
>> - VFIO only responsible for setting the IOVA aperture
>> - use new DOMAIN_ATTR_MSI_GEOMETRY iommu domain attribute
>>
>> v6 -> v7:
>> - vfio_find_dma now accepts a dma_type argument.
>> - should have recovered the capability to unmap the whole user IOVA range
>> - remove computation of nb IOVA pages -> will post a separate RFC for that
>>   while respinning the QEMU part
>>
>> RFC v5 -> patch v6:
>> - split to ease the review process
>>
>> RFC v4 -> RFC v5:
>> - take into account Thomas' comments on MSI related patches
>>   - split "msi: IOMMU map the doorbell address when needed"
>>   - increase readability and add comments
>>   - fix style issues
>>  - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
>>  - platform ITS now advertises IOMMU_CAP_INTR_REMAP
>>  - fix compilation issue with CONFIG_IOMMU API unset
>>  - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING
>>
>> RFC v3 -> v4:
>> - Move doorbell mapping/unmapping in msi.c
>> - fix ref count issue on set_affinity: in case of a change in the address
>>   the previous address is decremented
>> - doorbell map/unmap now is done on msi composition. Should allow the use
>>   case for platform MSI controllers
>> - create dma-reserved-iommu.h/c exposing/implementing a new API
>> dedicated
>>   to reserved IOVA management (looking like dma-iommu glue)
>> - series reordering to ease the review:
>>   - first part is related to IOMMU
>>   - second related to MSI sub-system
>>   - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP
>> removal)
>> - expose the number of requested IOVA pages through
>> VFIO_IOMMU_GET_INFO
>>   [this partially addresses Marc's comments on
>> iommu_get/put_single_reserved
>>    size/alignment problematic - which I did not ignore - but I don't know
>>    how much I can do at the moment]
>>
>> RFC v2 -> RFC v3:
>> - should fix wrong handling of some CONFIG combinations:
>>   CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
>> - fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)
>>
>> PATCH v1 -> RFC v2:
>> - reverted to RFC since it looks more reasonable ;-) the code is split
>>   between VFIO, IOMMU, MSI controller and I am not sure I did the right
>>   choices. Also API need to be further discussed.
>> - iova API usage in arm-smmu.c.
>> - MSI controller natively programs the MSI addr with either the PA or IOVA.
>>   This is not done anymore in vfio-pci driver as suggested by Alex.
>> - check irq remapping capability of the group
>>
>> RFC v1 [2] -> PATCH v1:
>> - use the existing dma map/unmap ioctl interface with a flag to register a
>>   reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
>> - a single reserved IOVA contiguous region now is allowed
>> - use of an RB tree indexed by PA to store allocated reserved slots
>> - use of a vfio_domain iova_domain to manage iova allocation within the
>>   window provided by the userspace
>> - vfio alloc_map/unmap_free take a vfio_group handle
>> - vfio_group handle is cached in vfio_pci_device
>> - add ref counting to bindings
>> - user modality enabled at the end of the series
>>
>>
>> Eric Auger (7):
>>   vfio: introduce a vfio_dma type field
>>   vfio/type1: vfio_find_dma accepting a type argument
>>   vfio/type1: bypass unmap/unpin and replay for VFIO_IOVA_RESERVED slots
>>   vfio: allow reserved msi iova registration
>>   vfio/type1: also check IRQ remapping capability at msi domain
>>   iommu/arm-smmu: do not advertise IOMMU_CAP_INTR_REMAP
>>   vfio/type1: return MSI mapping requirements with
>> VFIO_IOMMU_GET_INFO
>>
>>  drivers/iommu/arm-smmu-v3.c     |   3 +-
>>  drivers/iommu/arm-smmu.c        |   3 +-
>>  drivers/vfio/vfio_iommu_type1.c | 227
>> +++++++++++++++++++++++++++++++++++++---
>>  include/uapi/linux/vfio.h       |  14 ++-
>>  4 files changed, 230 insertions(+), 17 deletions(-)
>>
>> --
>> 1.9.1
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



From harald at ccbib.org  Wed May  4 04:38:25 2016
From: harald at ccbib.org (Harald Geyer)
Date: Wed, 04 May 2016 13:38:25 +0200
Subject: [PATCH 1/3] iio: mxs-lradc: Add regulators for current sources
In-Reply-To: <1e7d5f3a-22c1-94d4-9620-7aa112602e39@kernel.org>
References: <1461333147-11873-1-git-send-email-harald@ccbib.org>
 <1461333147-11873-2-git-send-email-harald@ccbib.org>
 <57288674.9050601@i2se.com> <6cdd4f858dacf72e192a292f29c12feb@ccbib.org>
 <1e7d5f3a-22c1-94d4-9620-7aa112602e39@kernel.org>
Message-ID: <0e2b0d54b37d5c780b7b81b64b4e9743@ccbib.org>

On 04.05.2016 09:15, Jonathan Cameron wrote:
> On 03/05/16 12:22, Harald Geyer wrote:
>> On 03.05.2016 13:07, Stefan Wahren wrote:
>>> Am 22.04.2016 um 15:52 schrieb Harald Geyer:
>>>> The hardware has two current sources ISRC0 and ISRC1 to allow 
>>>> measuring
>>>> resistors without additional circuitry. This commit makes them 
>>>> available
>>>> as regulators.
>>>>
>>>> Tested on an imx233-olinuxino board.
>>>>
>>>> Signed-off-by: Harald Geyer <harald at ccbib.org>
>>>> ---
>>>> The current regulator API doesn't fit this type of device very 
>>>> well: Typically
>>>> consumers will want to set a defined current, ie. min_uA == 
>>>> max_uA, but they
>>>> can't without help from configuration data, because the valid 
>>>> values aren't
>>>> reported by the API for current regulators. I have been thinking 
>>>> about
>>>> extending the API, but currently AFAIK no such consumers exist and 
>>>> most
>>>> users, like myself, will force the regulator to a defined value in
>>>> devicetree anyway.
>>>>
>>>>  .../bindings/staging/iio/adc/mxs-lradc.txt         |  29 ++++
>>>>  drivers/iio/adc/Kconfig                            |   1 +
>>>>  drivers/iio/adc/mxs-lradc.c                        | 152 
>>>> +++++++++++++++++++++
>>>>  3 files changed, 182 insertions(+)
>>>>
>>>> diff --git 
>>>> a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt 
>>>> b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
>>>> index 555fb11..983952c 100644
>>>> --- 
>>>> a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
>>>> +++ 
>>>> b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
>>>> @@ -19,6 +19,15 @@ Optional properties:
>>>>  - fsl,settling: delay between plate switch to next sample. 
>>>> Allowed value is
>>>>                  1 ... 2047. It counts at 2 kHz and its default is
>>>>                  10 (= 5 ms)
>>>> +- ISRC0: A node describing the regulator of internal current 
>>>> source 0
>>>> +- ISRC1: A node describing the regulator of internal current 
>>>> source 1
>>>> +
>>>> +Required properties for the ISRCx sub-nodes:
>>>> +- regulator-max-microamp: See standard regulator binding 
>>>> documentation.
>>>> +                          Valid values are from 0 to 300 in steps 
>>>> of 20.
>>>> +
>>>> +Optional properties for the ISRCx sub-nodes:
>>>> +Any standard regulator properties that apply to current 
>>>> regulators.
>>>>
>>>>  Example for i.MX23 SoC:
>>>>
>>>> @@ -31,6 +40,16 @@ Example for i.MX23 SoC:
>>>>          fsl,ave-ctrl = <4>;
>>>>          fsl,ave-delay = <2>;
>>>>          fsl,settling = <10>;
>>>> +
>>>> +        isrc_lradc0: ISRC0 {
>>>> +            regulator-max-microamp = <300>;
>>>> +        };
>>>> +
>>>> +        isrc_lradc1: ISRC1 {
>>>> +            regulator-max-microamp = <120>;
>>>> +            regulator-min-microamp = <120>;
>>>> +            regulator-always-on;
>>>> +        };
>>>
>>> IMHO the binding should represent the direct connection between the
>>> current source and the physical channel. I think a node label isn't
>>> enough. Unfortunately i don't have an idea to do it the "right 
>>> way".
>>
>> I strictly followed the names of the data sheet here: imx23 and 
>> imx28
>> reference manuals both call the current sources ISRC0 and ISRC1 even
>> if they are attached to different channels of the ADC. I think
>> inventing some ISRC6 for imx28 would do more harm then good.
> So just to check... These two current sources are effectively
> pushing current out of the ADC input pin?  Assumption being that
> this causes an appropriate voltage across a component between there
> and 0V?

Exactly.

> I wonder if we are better off not treating these as regulators at
> all - whilst you could in theory use them for general purposes, it
> would be a bit nuts and sometimes the 'it is nuts argument' is
> enough to mean we don't support something :)

Yeah, it would be some funny 4-bit DAC ...

> I wouldn't have any problem with an additional attribute for the
> adc channels - maybe something like...
>
> in_voltage6_sourcecurrent?  Then the control could be pushed to
> userspace.

I'm very open to that idea. Not having yet an other subsystem
involved would simplify some things a lot.

> Or if it only makes sense to do it as a fixed value in DT then
> define optional child nodes for the individual channels, with
> the relevant ones have current-source-microamp or
> something like that as an parameter.

My research in thermistors is still ongoing (so I don't have
a kernel driver yet) but I think for thermistors with
exponential temperature dependence dynamic setting of the
current source will be necessary to get high resolution across
the whole temperature range.

Of course many applications wont need this. For checks like
"Is my battery over-heating?" a simple fixed current from DT
will to well, so I guess we should support both.

> What do you think?

As I already stated in an other subthread, I'm not entirely
happy with the regulator approach. Having everything inside
iio would make supporting complex use cases easier in the
future, I guess.

Also IIO devices are much easier to control from user space
then regulators, which might be desired for this type of
device.

OTOH I'm not sure how many other devices out there have a
similar feature. I'd rather not invent a new API for just
very few devices. IMO iio already suffers from the
complexity of the sysfs API. Maybe somebody with a good
overview of ADCs available on the market can provide some
input here.

Also of course there are lots of ADCs out there without
internal current source and those could be used with
thermistors too but would need a regulator anyway.
So maybe eventually we would end up with both solutions
supported, which I'd avoid if at all possible. (I guess
we could work around the last issue by providing some
generic driver to pull an iio channel and a regulator
together - do we like that level of abstraction?)

If we start our own API to control current sources we
might end up pretty much reimplementing the regulator
API for the single consumer case.

I'd like to have input from more people on the above
points before going one way or the other.

Thanks,
Harald

> Jonathan
>
>>
>>>>      };
>>>>
>>>>  Example for i.MX28 SoC:
>>>> @@ -44,4 +63,14 @@ Example for i.MX28 SoC:
>>>>          fsl,ave-ctrl = <4>;
>>>>          fsl,ave-delay = <2>;
>>>>          fsl,settling = <10>;
>>>> +
>>>> +        isrc_lradc0: ISRC0 {
>>>> +            regulator-max-microamp = <300>;
>>>> +        };
>>>> +
>>>> +        isrc_lradc6: ISRC1 {
>>>> +            regulator-max-microamp = <120>;
>>>> +            regulator-min-microamp = <120>;
>>>> +            regulator-always-on;
>>>> +        };
>>>>      };
>>>> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
>>>> index 5937030..1968d1c 100644
>>>> --- a/drivers/iio/adc/Kconfig
>>>> +++ b/drivers/iio/adc/Kconfig
>>>> @@ -319,6 +319,7 @@ config MXS_LRADC
>>>>          tristate "Freescale i.MX23/i.MX28 LRADC"
>>>>          depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM
>>>>          depends on INPUT
>>>> +        depends on REGULATOR
>>>
>>> Any chance to avoid this dependency for an optional feature?
>>
>> I haven't looked into it yet, but I expect that that the mfd
>> conversion will avoid this neatly.
>>
>> Thanks,
>> Harald
>>
>>> Stefan
>>>
>>>>          select STMP_DEVICE
>>>>          select IIO_BUFFER
>>>>          select IIO_TRIGGERED_BUFFER
>>

-- 
If you want to support my work:
see http://friends.ccbib.org/harald/supporting/
or donate via peercoin to P98LRdhit3gZbHDBe7ta5jtXrMJUms4p7w
or bitcoin 1FUtd8T9jRN1rFz63vZz7s2fDtB6d6A7aS


From eric.auger at linaro.org  Wed May  4 04:40:01 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:40:01 +0000
Subject: [PATCH v9 2/8] iommu/arm-smmu: initialize the msi geometry and
 advertise iommu-msi support
In-Reply-To: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
References: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362007-2753-3-git-send-email-eric.auger@linaro.org>

On ARM, MSI write transactions from device upstream to the smmu
are conveyed through the iommu. Therefore target physical addresses
must be mapped and DOMAIN_ATTR_MSI_GEOMETRY advertises the support of
the IOMMU-MSI API.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v8 -> v9:
- reword the title and patch description

v7 -> v8:
- use DOMAIN_ATTR_MSI_GEOMETRY

v4 -> v5:
- don't handle fsl_pamu_domain anymore
- handle arm-smmu-v3
---
 drivers/iommu/arm-smmu-v3.c | 2 ++
 drivers/iommu/arm-smmu.c    | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 4ff73ff..bf222b5 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1396,6 +1396,7 @@ static bool arm_smmu_capable(enum iommu_cap cap)
 static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
 {
 	struct arm_smmu_domain *smmu_domain;
+	struct iommu_domain_msi_geometry msi_geometry = {0, 0, true};
 
 	if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
 		return NULL;
@@ -1414,6 +1415,7 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
 		kfree(smmu_domain);
 		return NULL;
 	}
+	smmu_domain->domain.msi_geometry = msi_geometry;
 
 	mutex_init(&smmu_domain->init_mutex);
 	spin_lock_init(&smmu_domain->pgtbl_lock);
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 7c39ac4..55f429d 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -976,6 +976,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
 static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
 {
 	struct arm_smmu_domain *smmu_domain;
+	struct iommu_domain_msi_geometry msi_geometry = {0, 0, true};
 
 	if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
 		return NULL;
@@ -994,6 +995,8 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
 		return NULL;
 	}
 
+	smmu_domain->domain.msi_geometry = msi_geometry;
+
 	mutex_init(&smmu_domain->init_mutex);
 	spin_lock_init(&smmu_domain->pgtbl_lock);
 
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:39:59 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:39:59 +0000
Subject: [PATCH v9 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part
 1/3: iommu changes
Message-ID: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>

This series introduces the msi-iommu api used to:

- allocate/free resources for MSI IOMMU mapping
- set the MSI iova window aperture
- map/unmap physical addresses onto MSI IOVAs.
- determine whether an msi needs to be iommu mapped
- overwrite an msi_msg PA address with its pre-allocated/mapped IOVA

Also a new iommu domain attribute, DOMAIN_ATTR_MSI_GEOMETRY is introduced
to report the MSI iova window geometry (aperture and iommu-msi API support).

Currently:
- iommu driver is supposed to allocate/free MSI mapping resources
- VFIO subsystem is supposed to set the MSI IOVA aperture.
- The MSI layer is supposed to allocate/free iova mappings and overwrite
  msi_msg with IOVA at composition time

More details & context can be found at:
http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/

Best Regards

Eric

Git: complete series available at
https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc6-pcie-passthrough-v9

History:

v8 -> v9:
- rename iommu_domain_msi_geometry programmable flag into iommu_msi_supported
- introduce msi_apperture_valid helper and use this instead of is_aperture_set

v7 -> v8:
- The API is retargetted for MSI: renamed msi-iommu
  all "dma-reserved" namings removed
- now implemented upon dma-iommu (get, put, init), ie. reuse iova_cookie,
  and iova API
- msi mapping resources now are guaranteed to exist during the whole iommu
  domain's lifetime. No need to lock to garantee the cookie integrity
- removed alloc/free_reserved_reserved_iova_domain. We now have a single
  function that sets the aperture, looking like iommu_dma_init_domain.
- we now use a list instead of an RB-tree
- prot is not propagated anymore at domain creation due to the retargetting
  for MSI
- iommu_domain pointer removed from doorbell_mapping struct
- replaced DOMAIN_ATTR_MSI_MAPPING by DOMAIN_ATTR_MSI_GEOMETRY

v6 -> v7:
- fixed known lock bugs and multiple page sized slots matching
  (I only have a single MSI frame made of a single page)
- reserved_iova_cookie now pointing to a struct that encapsulates the
  iova domain handle + protection attribute passed from VFIO (Alex' req)
- 2 new functions exposed: iommu_msi_mapping_translate_msg,
  iommu_msi_mapping_desc_to_domain: not sure this is the right location/proto
  though
- iommu_put_reserved_iova now takes a phys_addr_t
- everything now is cleanup on iommu_domain destruction

RFC v5 -> patch v6:
- split to ease the review process
- in dma-reserved-api use a spin lock instead of a mutex (reported by
  Jean-Philippe)
- revisit iommu_get_reserved_iova API to pass a size parameter upon
  Marc's request
- Consistently use the page order passed when creating the iova domain.
- init reserved_binding_list (reported by Julien)

RFC v4 -> RFC v5:
- take into account Thomas' comments on MSI related patches
  - split "msi: IOMMU map the doorbell address when needed"
  - increase readability and add comments
  - fix style issues
 - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
 - platform ITS now advertises IOMMU_CAP_INTR_REMAP
 - fix compilation issue with CONFIG_IOMMU API unset
 - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING

RFC v3 -> v4:
- Move doorbell mapping/unmapping in msi.c
- fix ref count issue on set_affinity: in case of a change in the address
  the previous address is decremented
- doorbell map/unmap now is done on msi composition. Should allow the use
  case for platform MSI controllers
- create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
  to reserved IOVA management (looking like dma-iommu glue)
- series reordering to ease the review:
  - first part is related to IOMMU
  - second related to MSI sub-system
  - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
- expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
  [this partially addresses Marc's comments on iommu_get/put_single_reserved
   size/alignment problematic - which I did not ignore - but I don't know
   how much I can do at the moment]

RFC v2 -> RFC v3:
- should fix wrong handling of some CONFIG combinations:
  CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
- fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)

PATCH v1 -> RFC v2:
- reverted to RFC since it looks more reasonable ;-) the code is split
  between VFIO, IOMMU, MSI controller and I am not sure I did the right
  choices. Also API need to be further discussed.
- iova API usage in arm-smmu.c.
- MSI controller natively programs the MSI addr with either the PA or IOVA.
  This is not done anymore in vfio-pci driver as suggested by Alex.
- check irq remapping capability of the group

RFC v1 [2] -> PATCH v1:
- use the existing dma map/unmap ioctl interface with a flag to register a
  reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
- a single reserved IOVA contiguous region now is allowed
- use of an RB tree indexed by PA to store allocated reserved slots
- use of a vfio_domain iova_domain to manage iova allocation within the
  window provided by the userspace
- vfio alloc_map/unmap_free take a vfio_group handle
- vfio_group handle is cached in vfio_pci_device
- add ref counting to bindings
- user modality enabled at the end of the series


Eric Auger (8):
  iommu: Add iommu_domain_msi_geometry and DOMAIN_ATTR_MSI_GEOMETRY
  iommu/arm-smmu: initialize the msi geometry and advertise iommu-msi
    support
  iommu: introduce an msi cookie
  iommu/msi-iommu: initialization
  iommu/msi-iommu: iommu_msi_[get,put]_doorbell_iova
  iommu/msi-iommu: iommu_msi_domain
  iommu/msi-iommu: iommu_msi_msg_pa_to_va
  iommu/arm-smmu: get/put the msi cookie

 drivers/iommu/Kconfig       |   7 +
 drivers/iommu/Makefile      |   1 +
 drivers/iommu/arm-smmu-v3.c |  18 ++-
 drivers/iommu/arm-smmu.c    |  18 ++-
 drivers/iommu/iommu.c       |   5 +
 drivers/iommu/msi-iommu.c   | 319 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/iommu.h       |  15 +++
 include/linux/msi-iommu.h   | 144 ++++++++++++++++++++
 8 files changed, 519 insertions(+), 8 deletions(-)
 create mode 100644 drivers/iommu/msi-iommu.c
 create mode 100644 include/linux/msi-iommu.h

-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:40:00 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:40:00 +0000
Subject: [PATCH v9 1/8] iommu: Add iommu_domain_msi_geometry and
 DOMAIN_ATTR_MSI_GEOMETRY
In-Reply-To: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
References: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362007-2753-2-git-send-email-eric.auger@linaro.org>

Introduce a new DOMAIN_ATTR_MSI_GEOMETRY domain attribute. It enables
to query the aperture of the IOVA window dedicated to MSIs and
test whether the MSIs must be mapped with the IOMMU-MSI API.

x86 IOMMUs will typically expose an MSI aperture matching the 1MB
region [FEE0_0000h - FEF0_000h] corresponding to the the APIC
configuration space and no support of the IOMMU-MSI API.

On ARM, the support of the IOMMU-MSI API will be advertised. Aperture
will refect the setting performed with the IOMMU-MSI API.

A helper function is added to allow testing if the aperture is valid.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Suggested-by: Alex Williamson <alex.williamson at redhat.com>

---
v8 -> v9:
- rename programmable into iommu_msi_supported
- add iommu_domain_msi_aperture_valid

v8: creation
- deprecates DOMAIN_ATTR_MSI_MAPPING flag
---
 drivers/iommu/iommu.c |  5 +++++
 include/linux/iommu.h | 14 ++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index b9df141..71ed58f 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1498,6 +1498,7 @@ int iommu_domain_get_attr(struct iommu_domain *domain,
 			  enum iommu_attr attr, void *data)
 {
 	struct iommu_domain_geometry *geometry;
+	struct iommu_domain_msi_geometry *msi_geometry;
 	bool *paging;
 	int ret = 0;
 	u32 *count;
@@ -1508,6 +1509,10 @@ int iommu_domain_get_attr(struct iommu_domain *domain,
 		*geometry = domain->geometry;
 
 		break;
+	case DOMAIN_ATTR_MSI_GEOMETRY:
+		msi_geometry  = data;
+		*msi_geometry = domain->msi_geometry;
+		break;
 	case DOMAIN_ATTR_PAGING:
 		paging  = data;
 		*paging = (domain->ops->pgsize_bitmap != 0UL);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 62a5eae..021b659 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -52,6 +52,12 @@ struct iommu_domain_geometry {
 	bool force_aperture;       /* DMA only allowed in mappable range? */
 };
 
+struct iommu_domain_msi_geometry {
+	dma_addr_t aperture_start; /* First address used for MSI IOVA    */
+	dma_addr_t aperture_end;   /* Last address used for MSI IOVA     */
+	bool iommu_msi_supported;  /* Is MSI mapping supported?		 */
+};
+
 /* Domain feature flags */
 #define __IOMMU_DOMAIN_PAGING	(1U << 0)  /* Support for iommu_map/unmap */
 #define __IOMMU_DOMAIN_DMA_API	(1U << 1)  /* Domain for use in DMA-API
@@ -82,6 +88,7 @@ struct iommu_domain {
 	iommu_fault_handler_t handler;
 	void *handler_token;
 	struct iommu_domain_geometry geometry;
+	struct iommu_domain_msi_geometry msi_geometry;
 	void *iova_cookie;
 };
 
@@ -107,6 +114,7 @@ enum iommu_cap {
 
 enum iommu_attr {
 	DOMAIN_ATTR_GEOMETRY,
+	DOMAIN_ATTR_MSI_GEOMETRY,
 	DOMAIN_ATTR_PAGING,
 	DOMAIN_ATTR_WINDOWS,
 	DOMAIN_ATTR_FSL_PAMU_STASH,
@@ -329,6 +337,12 @@ extern struct iommu_group *pci_device_group(struct device *dev);
 /* Generic device grouping function */
 extern struct iommu_group *generic_device_group(struct device *dev);
 
+static inline bool iommu_domain_msi_aperture_valid(struct iommu_domain *domain)
+{
+	return (domain->msi_geometry.aperture_end >
+		domain->msi_geometry.aperture_start);
+}
+
 #else /* CONFIG_IOMMU_API */
 
 struct iommu_ops {};
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:40:02 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:40:02 +0000
Subject: [PATCH v9 3/8] iommu: introduce an msi cookie
In-Reply-To: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
References: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362007-2753-4-git-send-email-eric.auger@linaro.org>

This opaque pointer will enable to store information about msi
iommu mappings.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v7 -> v8:
remove spinlock and RB tree

v5 -> v6:
- initialize reserved_binding_list
- use a spinlock instead of a mutex
---
 include/linux/iommu.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 021b659..09fba4c 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -90,6 +90,7 @@ struct iommu_domain {
 	struct iommu_domain_geometry geometry;
 	struct iommu_domain_msi_geometry msi_geometry;
 	void *iova_cookie;
+	void *msi_cookie;
 };
 
 enum iommu_cap {
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:40:03 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:40:03 +0000
Subject: [PATCH v9 4/8] iommu/msi-iommu: initialization
In-Reply-To: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
References: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362007-2753-5-git-send-email-eric.auger@linaro.org>

iommu_get/put_msi_cookie allocates/frees the resource used to store
and ref count the MSI doorbell mappings. iommu_msi_set_aperture
initializes the iova domain used for MSI IOVA allocation and sets the
iommu domain's msi geometry.

The implementation relies on dma-iommu API and iova API.

New msi functions are fully implemented if CONFIG_IOMMU_MSI is set.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v9:
- remove is_aperture_set and use iommu_domain_msi_aperture_valid helper
  instead
- set iommu domain's msi geometry

v8:
- new design where msi-iommu relies on dma-iommu
- remove the iommu_domain * from the doorbell_mapping struct
- added is_aperture_set

v7:
- fix locking
- add iova_cache_get/put
- static inline functions when CONFIG_IOMMU_DMA_RESERVED is not set
- introduce struct reserved_iova_domain to encapsulate prot info &
  add prot parameter in alloc_reserved_iova_domain

v5 -> v6:
- use spin lock instead of mutex

v3 -> v4:
- formerly in "iommu/arm-smmu: implement alloc/free_reserved_iova_domain" &
  "iommu: add alloc/free_reserved_iova_domain"

v2 -> v3:
- remove iommu_alloc_reserved_iova_domain & iommu_free_reserved_iova_domain
  static implementation in case CONFIG_IOMMU_API is not set

v1 -> v2:
- moved from vfio API to IOMMU API
---
 drivers/iommu/Kconfig     |  7 ++++
 drivers/iommu/Makefile    |  1 +
 drivers/iommu/msi-iommu.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/msi-iommu.h | 65 +++++++++++++++++++++++++++++++
 4 files changed, 170 insertions(+)
 create mode 100644 drivers/iommu/msi-iommu.c
 create mode 100644 include/linux/msi-iommu.h

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index dd1dc39..0078b72 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -74,6 +74,11 @@ config IOMMU_DMA
 	select IOMMU_IOVA
 	select NEED_SG_DMA_LENGTH
 
+# IOMMU MSI mapping
+config IOMMU_MSI
+	bool
+	select IOMMU_DMA
+
 config FSL_PAMU
 	bool "Freescale IOMMU support"
 	depends on PPC32
@@ -307,6 +312,7 @@ config SPAPR_TCE_IOMMU
 config ARM_SMMU
 	bool "ARM Ltd. System MMU (SMMU) Support"
 	depends on (ARM64 || ARM) && MMU
+	select IOMMU_MSI
 	select IOMMU_API
 	select IOMMU_IO_PGTABLE_LPAE
 	select ARM_DMA_USE_IOMMU if ARM
@@ -320,6 +326,7 @@ config ARM_SMMU
 config ARM_SMMU_V3
 	bool "ARM Ltd. System MMU Version 3 (SMMUv3) Support"
 	depends on ARM64 && PCI
+	select IOMMU_MSI
 	select IOMMU_API
 	select IOMMU_IO_PGTABLE_LPAE
 	select GENERIC_MSI_IRQ_DOMAIN
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index c6edb31..a381e66 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_IOMMU_API) += iommu.o
 obj-$(CONFIG_IOMMU_API) += iommu-traces.o
 obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
 obj-$(CONFIG_IOMMU_DMA) += dma-iommu.o
+obj-$(CONFIG_IOMMU_MSI) += msi-iommu.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
diff --git a/drivers/iommu/msi-iommu.c b/drivers/iommu/msi-iommu.c
new file mode 100644
index 0000000..4292957
--- /dev/null
+++ b/drivers/iommu/msi-iommu.c
@@ -0,0 +1,97 @@
+/*
+ * Reserved IOVA Management
+ *
+ * Copyright (c) 2015 Linaro Ltd.
+ *              www.linaro.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/iommu.h>
+#include <linux/dma-iommu.h>
+#include <linux/msi-iommu.h>
+#include <linux/spinlock.h>
+#include <linux/iova.h>
+
+struct doorbell_mapping {
+	struct kref		kref;
+	struct list_head	next;
+	phys_addr_t		addr;
+	dma_addr_t		iova;
+	size_t			size;
+};
+
+struct doorbell_mapping_info {
+	struct list_head list; /* list of doorbell mapping entries */
+	spinlock_t lock;
+};
+
+int iommu_get_msi_cookie(struct iommu_domain *domain)
+{
+	struct doorbell_mapping_info *dmi;
+	int ret;
+
+	if (domain->msi_cookie || domain->iova_cookie)
+		return -EINVAL;
+
+	ret = iommu_get_dma_cookie(domain);
+	if (ret)
+		return ret;
+
+	dmi = kzalloc(sizeof(*dmi), GFP_KERNEL);
+
+	INIT_LIST_HEAD(&dmi->list);
+	spin_lock_init(&dmi->lock);
+	iova_cache_get();
+
+	domain->msi_cookie = dmi;
+
+	return dmi ? 0 : -ENOMEM;
+}
+EXPORT_SYMBOL(iommu_get_msi_cookie);
+
+void iommu_put_msi_cookie(struct iommu_domain *domain)
+{
+	struct doorbell_mapping_info *dmi = domain->msi_cookie;
+
+	if (!dmi)
+		return;
+
+	domain->msi_cookie = NULL;
+
+	WARN_ON(!list_empty(&dmi->list));
+
+	kfree(dmi);
+	iommu_put_dma_cookie(domain);
+	iova_cache_put();
+}
+EXPORT_SYMBOL(iommu_put_msi_cookie);
+
+int iommu_msi_set_aperture(struct iommu_domain *domain,
+			   dma_addr_t start, dma_addr_t end)
+{
+	struct doorbell_mapping_info *dmi = domain->msi_cookie;
+	int ret;
+
+	if (!dmi || iommu_domain_msi_aperture_valid(domain))
+		return -ENODEV;
+
+	ret = iommu_dma_init_domain(domain, start, end - start + 1);
+
+	if (!ret) {
+		domain->msi_geometry.aperture_start = start;
+		domain->msi_geometry.aperture_end = end;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_msi_set_aperture);
+
diff --git a/include/linux/msi-iommu.h b/include/linux/msi-iommu.h
new file mode 100644
index 0000000..392aa6f
--- /dev/null
+++ b/include/linux/msi-iommu.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ *              www.linaro.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __MSI_IOMMU_H
+#define __MSI_IOMMU_H
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+struct iommu_domain;
+
+#ifdef CONFIG_IOMMU_MSI
+
+/**
+ * iommu_get_msi_cookie - Acquire MSI mapping resources for a domain
+ * @domain: IOMMU domain to prepare for MSI mapping
+ *
+ * IOMMU drivers which require MSI mapping should normally call this
+ * from their domain_alloc callback when domain->type ==
+ * IOMMU_DOMAIN_UNMANAGED.
+ */
+int iommu_get_msi_cookie(struct iommu_domain *domain);
+
+/**
+ * iommu_put_msi_cookie - Release a domain's MSI mapping resources
+ * @domain: IOMMU domain previously prepared by iommu_get_msi_cookie()
+ *
+ * IOMMU drivers requesting MSI mapping should normally call this from
+ * their domain_free callback.
+ */
+void iommu_put_msi_cookie(struct iommu_domain *domain);
+
+/**
+ * iommu_msi_set_aperture: allocate the msi iova domain
+ * according to the specified start/end IOVAs
+ *
+ * @domain: iommu domain handle
+ * @start: MSI iova start address
+ * @end: MSI iova end address
+ */
+int iommu_msi_set_aperture(struct iommu_domain *domain,
+			   dma_addr_t start, dma_addr_t end);
+
+#else
+
+static inline int
+iommu_msi_set_aperture(struct iommu_domain *domain,
+		       dma_addr_t start, dma_addr_t end)
+{
+	return -ENOENT;
+}
+
+#endif	/* CONFIG_IOMMU_MSI */
+#endif	/* __MSI_IOMMU_H */
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:40:05 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:40:05 +0000
Subject: [PATCH v9 6/8] iommu/msi-iommu: iommu_msi_domain
In-Reply-To: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
References: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362007-2753-7-git-send-email-eric.auger@linaro.org>

This function checks whether
- the device belongs to a non default iommu domain
- this iommu domain requires the MSI address to be mapped.

If those conditions are met, the function returns the iommu domain
to be used for mapping the MSI doorbell; else it returns NULL.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v8 -> v9:
- use iommu_msi_supported

v7 -> v8:
- renamed  iommu_msi_mapping_desc_to_domain to iommu_msi_domain
- the function now takes a struct device *
- use DOMAIN_ATTR_MSI_GEOMETRY attribute
---
 drivers/iommu/msi-iommu.c | 17 +++++++++++++++++
 include/linux/msi-iommu.h | 14 ++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/drivers/iommu/msi-iommu.c b/drivers/iommu/msi-iommu.c
index ec97f49..6d52985 100644
--- a/drivers/iommu/msi-iommu.c
+++ b/drivers/iommu/msi-iommu.c
@@ -245,3 +245,20 @@ unlock:
 	}
 }
 EXPORT_SYMBOL_GPL(iommu_msi_put_doorbell_iova);
+
+struct iommu_domain *iommu_msi_domain(struct device *dev)
+{
+	struct iommu_domain *d = iommu_get_domain_for_dev(dev);
+	struct iommu_domain_msi_geometry msi_geometry;
+
+	if (!d || (d->type == IOMMU_DOMAIN_DMA))
+		return NULL;
+
+	iommu_domain_get_attr(d, DOMAIN_ATTR_MSI_GEOMETRY, &msi_geometry);
+	if (!msi_geometry.iommu_msi_supported)
+		return NULL;
+
+	return d;
+}
+EXPORT_SYMBOL_GPL(iommu_msi_domain);
+
diff --git a/include/linux/msi-iommu.h b/include/linux/msi-iommu.h
index 1cd115f..114bd69 100644
--- a/include/linux/msi-iommu.h
+++ b/include/linux/msi-iommu.h
@@ -81,6 +81,15 @@ int iommu_msi_get_doorbell_iova(struct iommu_domain *domain,
  */
 void iommu_msi_put_doorbell_iova(struct iommu_domain *domain, phys_addr_t addr);
 
+/**
+ * iommu_msi_domain: in case the device is upstream to an IOMMU and this IOMMU
+ * translates the MSI transaction, returns the iommu domain the MSI doorbell
+ * address must be mapped in; else returns NULL.
+ *
+ * @dev: device handle
+ */
+struct iommu_domain *iommu_msi_domain(struct device *dev);
+
 #else
 
 static inline int
@@ -100,5 +109,10 @@ static inline int iommu_msi_get_doorbell_iova(struct iommu_domain *domain,
 static inline void iommu_msi_put_doorbell_iova(struct iommu_domain *domain,
 					       phys_addr_t addr) {}
 
+static inline struct iommu_domain *iommu_msi_domain(struct device *dev)
+{
+	return NULL;
+}
+
 #endif	/* CONFIG_IOMMU_MSI */
 #endif	/* __MSI_IOMMU_H */
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:40:04 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:40:04 +0000
Subject: [PATCH v9 5/8] iommu/msi-iommu: iommu_msi_[get,put]_doorbell_iova
In-Reply-To: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
References: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362007-2753-6-git-send-email-eric.auger@linaro.org>

iommu_msi_get_doorbell_iova allows to iommu map an MSI doorbell contiguous
physical region onto a reserved contiguous IOVA region. The physical
region base address does not need to be iommu page size aligned. iova
pages are allocated and mapped so that they cover all the physical region.
This mapping is tracked as a whole (and cannot be split).

In case a mapping already exists for the physical pages, the IOVA mapped
to the PA base is directly returned.

Each time the get succeeds a binding ref count is incremented.

iommu_put_reserved_iova decrements the ref count and when this latter
is null, the mapping is destroyed and the IOVAs are released.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v9:
- use iommu_domain_msi_aperture_valid

v8:
- function renaming
- new design based on the assumption the iova domain cannot disappear
- free_iova outside of doorbell_mapping_release (iommu_domain * was
  removed from doorbell_mapping)

v7:
- change title and rework commit message with new name of the functions
  and size parameter
- fix locking
- rework header doc comments
- put now takes a phys_addr_t
- check prot argument against reserved_iova_domain prot flags

v5 -> v6:
- revisit locking with spin_lock instead of mutex
- do not kref_get on 1st get
- add size parameter to the get function following Marc's request
- use the iova domain shift instead of using the smallest supported page siz

v3 -> v4:
- formerly in iommu: iommu_get/put_single_reserved &
  iommu/arm-smmu: implement iommu_get/put_single_reserved
- Attempted to address Marc's doubts about missing size/alignment
  at VFIO level (user-space knows the IOMMU page size and the number
  of IOVA pages to provision)

v2 -> v3:
- remove static implementation of iommu_get_single_reserved &
  iommu_put_single_reserved when CONFIG_IOMMU_API is not set

v1 -> v2:
- previously a VFIO API, named vfio_alloc_map/unmap_free_reserved_iova
---
 drivers/iommu/msi-iommu.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/msi-iommu.h |  39 ++++++++++++
 2 files changed, 189 insertions(+)

diff --git a/drivers/iommu/msi-iommu.c b/drivers/iommu/msi-iommu.c
index 4292957..ec97f49 100644
--- a/drivers/iommu/msi-iommu.c
+++ b/drivers/iommu/msi-iommu.c
@@ -95,3 +95,153 @@ int iommu_msi_set_aperture(struct iommu_domain *domain,
 }
 EXPORT_SYMBOL_GPL(iommu_msi_set_aperture);
 
+/* called with info->lock held */
+static struct doorbell_mapping *
+search_msi_doorbell_mapping(struct doorbell_mapping_info *info,
+			    phys_addr_t addr, size_t size)
+{
+	struct doorbell_mapping *mapping;
+
+	list_for_each_entry(mapping, &info->list, next) {
+		if ((addr >= mapping->addr) &&
+		    (addr + size <= mapping->addr + mapping->size))
+			return mapping;
+	}
+	return NULL;
+}
+
+int iommu_msi_get_doorbell_iova(struct iommu_domain *domain,
+				phys_addr_t addr, size_t size, int prot,
+				dma_addr_t *iova)
+{
+	struct doorbell_mapping_info *dmi = domain->msi_cookie;
+	struct iova_domain *iovad = domain->iova_cookie;
+	struct doorbell_mapping *new_mapping, *mapping;
+	phys_addr_t aligned_base, offset;
+	size_t binding_size;
+	struct iova *p_iova;
+	dma_addr_t new_iova;
+	int ret = -EINVAL;
+	bool unmap = false;
+
+	if (!dmi)
+		return -ENODEV;
+
+	if (!iommu_domain_msi_aperture_valid(domain))
+		return -EINVAL;
+
+	offset = iova_offset(iovad, addr);
+	aligned_base = addr - offset;
+	binding_size = iova_align(iovad, size + offset);
+
+	spin_lock(&dmi->lock);
+
+	mapping = search_msi_doorbell_mapping(dmi, aligned_base, binding_size);
+	if (mapping) {
+		*iova = mapping->iova + offset + aligned_base - mapping->addr;
+		kref_get(&mapping->kref);
+		ret = 0;
+		goto unlock;
+	}
+
+	spin_unlock(&dmi->lock);
+
+	new_mapping = kzalloc(sizeof(*new_mapping), GFP_KERNEL);
+	if (!new_mapping)
+		return -ENOMEM;
+
+	p_iova = alloc_iova(iovad, binding_size >> iova_shift(iovad),
+			    iovad->dma_32bit_pfn, true);
+	if (!p_iova) {
+		kfree(new_mapping);
+		return -ENOMEM;
+	}
+
+	new_iova = iova_dma_addr(iovad, p_iova);
+	*iova = new_iova;
+
+	/* iommu_map is not supposed to be atomic */
+	ret = iommu_map(domain, *iova, aligned_base, binding_size, prot);
+
+	spin_lock(&dmi->lock);
+
+	if (ret)
+		goto free_iova;
+	/*
+	 * check again the doorbell mapping was not added while the lock
+	 * was released
+	 */
+	mapping = search_msi_doorbell_mapping(dmi, aligned_base, binding_size);
+	if (mapping) {
+		*iova = mapping->iova + offset + aligned_base - mapping->addr;
+		kref_get(&mapping->kref);
+		ret = 0;
+		unmap = true;
+		goto free_iova;
+	}
+
+	kref_init(&new_mapping->kref);
+	new_mapping->addr = aligned_base;
+	new_mapping->iova = *iova;
+	new_mapping->size = binding_size;
+
+	list_add(&new_mapping->next, &dmi->list);
+
+	*iova += offset;
+	goto unlock;
+free_iova:
+	free_iova(iovad, p_iova->pfn_lo);
+	kfree(new_mapping);
+unlock:
+	spin_unlock(&dmi->lock);
+	if (unmap)
+		iommu_unmap(domain, new_iova, binding_size);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_msi_get_doorbell_iova);
+
+static void doorbell_mapping_release(struct kref *kref)
+{
+	struct doorbell_mapping *mapping =
+		container_of(kref, struct doorbell_mapping, kref);
+
+	list_del(&mapping->next);
+	kfree(mapping);
+}
+
+void iommu_msi_put_doorbell_iova(struct iommu_domain *domain, phys_addr_t addr)
+{
+	struct doorbell_mapping_info *dmi = domain->msi_cookie;
+	struct iova_domain *iovad = domain->iova_cookie;
+	phys_addr_t aligned_addr, page_size, offset;
+	struct doorbell_mapping *mapping;
+	dma_addr_t iova;
+	size_t size;
+	int ret = 0;
+
+	if (!dmi)
+		return;
+
+	page_size = (uint64_t)1 << iova_shift(iovad);
+	offset = iova_offset(iovad, addr);
+	aligned_addr = addr - offset;
+
+	spin_lock(&dmi->lock);
+
+	mapping = search_msi_doorbell_mapping(dmi, aligned_addr, page_size);
+	if (!mapping)
+		goto unlock;
+
+	iova = mapping->iova;
+	size = mapping->size;
+
+	ret = kref_put(&mapping->kref, doorbell_mapping_release);
+
+unlock:
+	spin_unlock(&dmi->lock);
+	if (ret) {
+		iommu_unmap(domain, iova, size);
+		free_iova(iovad, iova_pfn(iovad, iova));
+	}
+}
+EXPORT_SYMBOL_GPL(iommu_msi_put_doorbell_iova);
diff --git a/include/linux/msi-iommu.h b/include/linux/msi-iommu.h
index 392aa6f..1cd115f 100644
--- a/include/linux/msi-iommu.h
+++ b/include/linux/msi-iommu.h
@@ -52,6 +52,35 @@ void iommu_put_msi_cookie(struct iommu_domain *domain);
 int iommu_msi_set_aperture(struct iommu_domain *domain,
 			   dma_addr_t start, dma_addr_t end);
 
+/**
+ * iommu_msi_get_doorbell_iova: allocate a contiguous set of iova pages and
+ * map them to the MSI doorbell's physical range defined by @addr and @size.
+ *
+ * @domain: iommu domain handle
+ * @addr: physical address to bind
+ * @size: size of the binding
+ * @prot: mapping protection attribute
+ * @iova: returned iova
+ *
+ * Mapped physical pfns are within [@addr >> order, (@addr + size -1) >> order]
+ * where order corresponds to the iova domain order.
+ * This mapping is tracked and reference counted with the minimal granularity
+ * of @size.
+ */
+int iommu_msi_get_doorbell_iova(struct iommu_domain *domain,
+				phys_addr_t addr, size_t size, int prot,
+				dma_addr_t *iova);
+
+/**
+ * iommu_msi_put_doorbell_iova: decrement a ref count of the doorbell's mapping
+ *
+ * @domain: iommu domain handle
+ * @addr: physical address whose binding ref count is decremented
+ *
+ * if the binding ref count is null, destroy the MSI doorbell's mapping
+ */
+void iommu_msi_put_doorbell_iova(struct iommu_domain *domain, phys_addr_t addr);
+
 #else
 
 static inline int
@@ -61,5 +90,15 @@ iommu_msi_set_aperture(struct iommu_domain *domain,
 	return -ENOENT;
 }
 
+static inline int iommu_msi_get_doorbell_iova(struct iommu_domain *domain,
+					      phys_addr_t addr, size_t size,
+					      int prot, dma_addr_t *iova)
+{
+	return -ENOENT;
+}
+
+static inline void iommu_msi_put_doorbell_iova(struct iommu_domain *domain,
+					       phys_addr_t addr) {}
+
 #endif	/* CONFIG_IOMMU_MSI */
 #endif	/* __MSI_IOMMU_H */
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:40:06 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:40:06 +0000
Subject: [PATCH v9 7/8] iommu/msi-iommu: iommu_msi_msg_pa_to_va
In-Reply-To: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
References: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362007-2753-8-git-send-email-eric.auger@linaro.org>

Introduce iommu_msi_msg_pa_to_va whose role consists in
detecting whether the device's MSIs must to be mapped into an IOMMU.
It case it must, the function overrides the MSI msg originally composed
and replaces the doorbell's PA by a pre-allocated and pre-mapped reserved
IOVA. In case the corresponding PA region is not found, the function
returns an error.

This function is likely to be called in some code that cannot sleep. This
is the reason why the allocation/mapping is done separately.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v7 -> v8:
- renamed from iommu_msi_mapping_translate_msg to iommu_msi_msg_pa_to_va
  and now takes a struct device * as parameter

v7: creation
---
 drivers/iommu/msi-iommu.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/msi-iommu.h | 26 ++++++++++++++++++++++
 2 files changed, 81 insertions(+)

diff --git a/drivers/iommu/msi-iommu.c b/drivers/iommu/msi-iommu.c
index 6d52985..d71e164 100644
--- a/drivers/iommu/msi-iommu.c
+++ b/drivers/iommu/msi-iommu.c
@@ -20,6 +20,14 @@
 #include <linux/msi-iommu.h>
 #include <linux/spinlock.h>
 #include <linux/iova.h>
+#include <linux/msi.h>
+
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+#define msg_to_phys_addr(msg) \
+	(((phys_addr_t)((msg)->address_hi) << 32) | (msg)->address_lo)
+#else
+#define msg_to_phys_addr(msg)	((msg)->address_lo)
+#endif
 
 struct doorbell_mapping {
 	struct kref		kref;
@@ -262,3 +270,50 @@ struct iommu_domain *iommu_msi_domain(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(iommu_msi_domain);
 
+static dma_addr_t iommu_msi_find_iova(struct iommu_domain *domain,
+				      phys_addr_t addr, size_t size)
+{
+	struct doorbell_mapping_info *dmi = domain->msi_cookie;
+	struct iova_domain *iovad = domain->iova_cookie;
+	struct doorbell_mapping *mapping;
+	dma_addr_t iova = DMA_ERROR_CODE;
+	phys_addr_t aligned_base, offset;
+	size_t binding_size;
+
+	if (!iovad || !dmi)
+		return iova;
+
+	offset = iova_offset(iovad, addr);
+	aligned_base = addr - offset;
+	binding_size = iova_align(iovad, size + offset);
+
+	spin_lock(&dmi->lock);
+
+	mapping = search_msi_doorbell_mapping(dmi, addr, size);
+	if (mapping)
+		iova = mapping->iova + offset + aligned_base - mapping->addr;
+
+	spin_unlock(&dmi->lock);
+	return iova;
+}
+
+int iommu_msi_msg_pa_to_va(struct device *dev, struct msi_msg *msg)
+{
+	struct iommu_domain *d = iommu_msi_domain(dev);
+	dma_addr_t iova;
+
+	if (!d)
+		return 0;
+
+	iova = iommu_msi_find_iova(d, msg_to_phys_addr(msg),
+				   sizeof(phys_addr_t));
+
+	if (iova == DMA_ERROR_CODE)
+		return -EINVAL;
+
+	msg->address_lo = lower_32_bits(iova);
+	msg->address_hi = upper_32_bits(iova);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iommu_msi_msg_pa_to_va);
+
diff --git a/include/linux/msi-iommu.h b/include/linux/msi-iommu.h
index 114bd69..c1c9bd5 100644
--- a/include/linux/msi-iommu.h
+++ b/include/linux/msi-iommu.h
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 
 struct iommu_domain;
+struct msi_msg;
 
 #ifdef CONFIG_IOMMU_MSI
 
@@ -90,6 +91,25 @@ void iommu_msi_put_doorbell_iova(struct iommu_domain *domain, phys_addr_t addr);
  */
 struct iommu_domain *iommu_msi_domain(struct device *dev);
 
+/**
+ * iommu_msi_msg_pa_to_va: in case a device's MSI transaction is translated
+ * by an IOMMU, the msg address must be an IOVA instead of a physical address.
+ * This function overwrites the original MSI message containing the doorbell's
+ * physical address with the doorbell's pre-allocated IOVA, if any.
+ *
+ * The doorbell physical address must be bound previously to an IOVA using
+ * iommu_msi_get_doorbell_iova
+ *
+ * @dev: device emitting the MSI
+ * @msg: original MSI message containing the PA to be overwritten with the IOVA
+ *
+ * return 0 if the MSI does not need to be mapped or when the PA/IOVA
+ * were successfully swapped; return -EINVAL if the addresses need
+ * to be swapped but not IOMMU binding is found
+ */
+int iommu_msi_msg_pa_to_va(struct device *dev, struct msi_msg *msg);
+
+
 #else
 
 static inline int
@@ -114,5 +134,11 @@ static inline struct iommu_domain *iommu_msi_domain(struct device *dev)
 	return NULL;
 }
 
+static inline int iommu_msi_msg_pa_to_va(struct device *dev,
+					 struct msi_msg *msg)
+{
+	return 0;
+}
+
 #endif	/* CONFIG_IOMMU_MSI */
 #endif	/* __MSI_IOMMU_H */
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:40:07 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:40:07 +0000
Subject: [PATCH v9 8/8] iommu/arm-smmu: get/put the msi cookie
In-Reply-To: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
References: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362007-2753-9-git-send-email-eric.auger@linaro.org>

For IOMMU_DOMAIN_UNMANAGED type we now also get the msi
cookie in both arm-smmu and arm-smmu-v3. This initializes
resources for MSI doorbell mapping.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
---
 drivers/iommu/arm-smmu-v3.c | 16 ++++++++++++----
 drivers/iommu/arm-smmu.c    | 15 +++++++++++----
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index bf222b5..b5d9826 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -22,6 +22,7 @@
 
 #include <linux/delay.h>
 #include <linux/dma-iommu.h>
+#include <linux/msi-iommu.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/iommu.h>
@@ -1411,15 +1412,21 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
 		return NULL;
 
 	if (type == IOMMU_DOMAIN_DMA &&
-	    iommu_get_dma_cookie(&smmu_domain->domain)) {
-		kfree(smmu_domain);
-		return NULL;
-	}
+	    iommu_get_dma_cookie(&smmu_domain->domain))
+		goto err;
+
+	if (type == IOMMU_DOMAIN_UNMANAGED &&
+		iommu_get_msi_cookie(&smmu_domain->domain))
+		goto err;
+
 	smmu_domain->domain.msi_geometry = msi_geometry;
 
 	mutex_init(&smmu_domain->init_mutex);
 	spin_lock_init(&smmu_domain->pgtbl_lock);
 	return &smmu_domain->domain;
+err:
+	kfree(smmu_domain);
+	return NULL;
 }
 
 static int arm_smmu_bitmap_alloc(unsigned long *map, int span)
@@ -1445,6 +1452,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
 	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
 	struct arm_smmu_device *smmu = smmu_domain->smmu;
 
+	iommu_put_msi_cookie(domain);
 	iommu_put_dma_cookie(domain);
 	free_io_pgtable_ops(smmu_domain->pgtbl_ops);
 
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 55f429d..0908985 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -30,6 +30,7 @@
 
 #include <linux/delay.h>
 #include <linux/dma-iommu.h>
+#include <linux/msi-iommu.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
@@ -990,10 +991,12 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
 		return NULL;
 
 	if (type == IOMMU_DOMAIN_DMA &&
-	    iommu_get_dma_cookie(&smmu_domain->domain)) {
-		kfree(smmu_domain);
-		return NULL;
-	}
+	    iommu_get_dma_cookie(&smmu_domain->domain))
+		goto err;
+
+	if (type == IOMMU_DOMAIN_UNMANAGED &&
+		iommu_get_msi_cookie(&smmu_domain->domain))
+		goto err;
 
 	smmu_domain->domain.msi_geometry = msi_geometry;
 
@@ -1001,6 +1004,9 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
 	spin_lock_init(&smmu_domain->pgtbl_lock);
 
 	return &smmu_domain->domain;
+err:
+	kfree(smmu_domain);
+	return NULL;
 }
 
 static void arm_smmu_domain_free(struct iommu_domain *domain)
@@ -1011,6 +1017,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
 	 * Free the domain resources. We assume that all devices have
 	 * already been detached.
 	 */
+	iommu_put_msi_cookie(domain);
 	iommu_put_dma_cookie(domain);
 	arm_smmu_destroy_domain_context(domain);
 	kfree(smmu_domain);
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:54:11 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:54:11 +0000
Subject: [PATCH v9 0/7] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part
 3/3: vfio changes
Message-ID: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>

This series allows the user-space to register a reserved IOVA domain.
This completes the kernel integration of the whole functionality on top
of part 1 (v9) & 2 (v8).

It also depends on [PATCH 1/3] iommu: Add MMIO mapping type series,
http://comments.gmane.org/gmane.linux.kernel.iommu/12869

We reuse the VFIO DMA MAP ioctl with a new flag to bridge to the
msi-iommu API. The need for provisioning such MSI IOVA range is reported
through capability chain, using VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY.

vfio_iommu_type1 checks if the MSI mapping is safe when attaching the
vfio group to the container (allow_unsafe_interrupts modality).

On ARM/ARM64, the IOMMU does not astract IRQ remapping. the modality is
abstracted on MSI controller side. The GICv3 ITS is the first controller
advertising the modality.

More details & context can be found at:
http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/

Best Regards

Eric

Testing:
- functional on ARM64 AMD Overdrive HW (single GICv2m frame) with
  Intel X540-T2 (SR-IOV capable)
- also tested on Armada-7040 using an intel IXGBE (82599ES) by
  Yehuda Yitschak (v8)
- Not tested: ARM GICv3 ITS

References:
[1] [RFC 0/2] VFIO: Add virtual MSI doorbell support
    (https://lkml.org/lkml/2015/7/24/135)
[2] [RFC PATCH 0/6] vfio: Add interface to map MSI pages
    (https://lists.cs.columbia.edu/pipermail/kvmarm/2015-September/016607.html)
[3] [PATCH v2 0/3] Introduce MSI hardware mapping for VFIO
    (http://permalink.gmane.org/gmane.comp.emulators.kvm.arm.devel/3858)

Git: complete series available at
https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc6-pcie-passthrough-v9

previous version at
https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc5-pcie-passthrough-v8

History:
v8 -> v9:
- report MSI geometry through capability chain (last patch only);
  with the current limitation that an arbitrary number of 16 page
  requirement is reported. To be improved later on.


v7 -> v8:
- use renamed msi-iommu API
- VFIO only responsible for setting the IOVA aperture
- use new DOMAIN_ATTR_MSI_GEOMETRY iommu domain attribute

v6 -> v7:
- vfio_find_dma now accepts a dma_type argument.
- should have recovered the capability to unmap the whole user IOVA range
- remove computation of nb IOVA pages -> will post a separate RFC for that
  while respinning the QEMU part

RFC v5 -> patch v6:
- split to ease the review process

RFC v4 -> RFC v5:
- take into account Thomas' comments on MSI related patches
  - split "msi: IOMMU map the doorbell address when needed"
  - increase readability and add comments
  - fix style issues
 - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
 - platform ITS now advertises IOMMU_CAP_INTR_REMAP
 - fix compilation issue with CONFIG_IOMMU API unset
 - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING

RFC v3 -> v4:
- Move doorbell mapping/unmapping in msi.c
- fix ref count issue on set_affinity: in case of a change in the address
  the previous address is decremented
- doorbell map/unmap now is done on msi composition. Should allow the use
  case for platform MSI controllers
- create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
  to reserved IOVA management (looking like dma-iommu glue)
- series reordering to ease the review:
  - first part is related to IOMMU
  - second related to MSI sub-system
  - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
- expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
  [this partially addresses Marc's comments on iommu_get/put_single_reserved
   size/alignment problematic - which I did not ignore - but I don't know
   how much I can do at the moment]

RFC v2 -> RFC v3:
- should fix wrong handling of some CONFIG combinations:
  CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
- fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)

PATCH v1 -> RFC v2:
- reverted to RFC since it looks more reasonable ;-) the code is split
  between VFIO, IOMMU, MSI controller and I am not sure I did the right
  choices. Also API need to be further discussed.
- iova API usage in arm-smmu.c.
- MSI controller natively programs the MSI addr with either the PA or IOVA.
  This is not done anymore in vfio-pci driver as suggested by Alex.
- check irq remapping capability of the group

RFC v1 [2] -> PATCH v1:
- use the existing dma map/unmap ioctl interface with a flag to register a
  reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
- a single reserved IOVA contiguous region now is allowed
- use of an RB tree indexed by PA to store allocated reserved slots
- use of a vfio_domain iova_domain to manage iova allocation within the
  window provided by the userspace
- vfio alloc_map/unmap_free take a vfio_group handle
- vfio_group handle is cached in vfio_pci_device
- add ref counting to bindings
- user modality enabled at the end of the series


Eric Auger (7):
  vfio: introduce a vfio_dma type field
  vfio/type1: vfio_find_dma accepting a type argument
  vfio/type1: bypass unmap/unpin and replay for VFIO_IOVA_RESERVED slots
  vfio: allow reserved msi iova registration
  vfio/type1: also check IRQ remapping capability at msi domain
  iommu/arm-smmu: do not advertise IOMMU_CAP_INTR_REMAP
  vfio/type1: return MSI geometry through VFIO_IOMMU_GET_INFO capability
    chains

 drivers/iommu/arm-smmu-v3.c     |   3 +-
 drivers/iommu/arm-smmu.c        |   3 +-
 drivers/vfio/vfio_iommu_type1.c | 270 +++++++++++++++++++++++++++++++++++++---
 include/uapi/linux/vfio.h       |  40 +++++-
 4 files changed, 298 insertions(+), 18 deletions(-)

-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:54:12 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:54:12 +0000
Subject: [PATCH v9 1/7] vfio: introduce a vfio_dma type field
In-Reply-To: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362858-2925-2-git-send-email-eric.auger@linaro.org>

We introduce a vfio_dma type since we will need to discriminate
different types of dma slots:
- VFIO_IOVA_USER: IOVA region used to map user vaddr
- VFIO_IOVA_RESERVED: IOVA region reserved to map host device PA such
  as MSI doorbells

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---

v6 -> v7:
- add VFIO_IOVA_ANY
- do not introduce yet any VFIO_IOVA_RESERVED handling
---
 drivers/vfio/vfio_iommu_type1.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 75b24e9..aaf5a6c 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -53,6 +53,16 @@ module_param_named(disable_hugepages,
 MODULE_PARM_DESC(disable_hugepages,
 		 "Disable VFIO IOMMU support for IOMMU hugepages.");
 
+enum vfio_iova_type {
+	VFIO_IOVA_USER = 0,	/* standard IOVA used to map user vaddr */
+	/*
+	 * IOVA reserved to map special host physical addresses,
+	 * MSI frames for instance
+	 */
+	VFIO_IOVA_RESERVED,
+	VFIO_IOVA_ANY,		/* matches any IOVA type */
+};
+
 struct vfio_iommu {
 	struct list_head	domain_list;
 	struct mutex		lock;
@@ -75,6 +85,7 @@ struct vfio_dma {
 	unsigned long		vaddr;		/* Process virtual addr */
 	size_t			size;		/* Map size (bytes) */
 	int			prot;		/* IOMMU_READ/WRITE */
+	enum vfio_iova_type	type;		/* type of IOVA */
 };
 
 struct vfio_group {
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:54:13 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:54:13 +0000
Subject: [PATCH v9 2/7] vfio/type1: vfio_find_dma accepting a type argument
In-Reply-To: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362858-2925-3-git-send-email-eric.auger@linaro.org>

In our RB-tree we now have slots of different types (USER and RESERVED).
It becomes useful to be able to search for dma slots of a specific type or
any type. This patch proposes an implementation for that modality and also
changes the existing callers using the USER type.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
---
 drivers/vfio/vfio_iommu_type1.c | 63 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 53 insertions(+), 10 deletions(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index aaf5a6c..2d769d4 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -98,23 +98,64 @@ struct vfio_group {
  * into DMA'ble space using the IOMMU
  */
 
-static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
-				      dma_addr_t start, size_t size)
+/**
+ * vfio_find_dma_from_node: looks for a dma slot intersecting a window
+ * from a given rb tree node
+ * @top: top rb tree node where the search starts (including this node)
+ * @start: window start
+ * @size: window size
+ * @type: window type
+ */
+static struct vfio_dma *vfio_find_dma_from_node(struct rb_node *top,
+						dma_addr_t start, size_t size,
+						enum vfio_iova_type type)
 {
-	struct rb_node *node = iommu->dma_list.rb_node;
+	struct rb_node *node = top;
+	struct vfio_dma *dma;
 
 	while (node) {
-		struct vfio_dma *dma = rb_entry(node, struct vfio_dma, node);
-
+		dma = rb_entry(node, struct vfio_dma, node);
 		if (start + size <= dma->iova)
 			node = node->rb_left;
 		else if (start >= dma->iova + dma->size)
 			node = node->rb_right;
 		else
+			break;
+	}
+	if (!node)
+		return NULL;
+
+	/* a dma slot intersects our window, check the type also matches */
+	if (type == VFIO_IOVA_ANY || dma->type == type)
+		return dma;
+
+	/* restart 2 searches skipping the current node */
+	if (start < dma->iova) {
+		dma = vfio_find_dma_from_node(node->rb_left, start,
+					      size, type);
+		if (dma)
 			return dma;
 	}
+	if (start + size > dma->iova + dma->size)
+		dma = vfio_find_dma_from_node(node->rb_right, start,
+					      size, type);
+	return dma;
+}
+
+/**
+ * vfio_find_dma: find a dma slot intersecting a given window
+ * @iommu: vfio iommu handle
+ * @start: window base iova
+ * @size: window size
+ * @type: window type
+ */
+static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
+				      dma_addr_t start, size_t size,
+				      enum vfio_iova_type type)
+{
+	struct rb_node *top_node = iommu->dma_list.rb_node;
 
-	return NULL;
+	return vfio_find_dma_from_node(top_node, start, size, type);
 }
 
 static void vfio_link_dma(struct vfio_iommu *iommu, struct vfio_dma *new)
@@ -488,19 +529,21 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
 	 * mappings within the range.
 	 */
 	if (iommu->v2) {
-		dma = vfio_find_dma(iommu, unmap->iova, 0);
+		dma = vfio_find_dma(iommu, unmap->iova, 0, VFIO_IOVA_USER);
 		if (dma && dma->iova != unmap->iova) {
 			ret = -EINVAL;
 			goto unlock;
 		}
-		dma = vfio_find_dma(iommu, unmap->iova + unmap->size - 1, 0);
+		dma = vfio_find_dma(iommu, unmap->iova + unmap->size - 1, 0,
+				    VFIO_IOVA_USER);
 		if (dma && dma->iova + dma->size != unmap->iova + unmap->size) {
 			ret = -EINVAL;
 			goto unlock;
 		}
 	}
 
-	while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size))) {
+	while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size,
+				    VFIO_IOVA_USER))) {
 		if (!iommu->v2 && unmap->iova > dma->iova)
 			break;
 		unmapped += dma->size;
@@ -604,7 +647,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
 
 	mutex_lock(&iommu->lock);
 
-	if (vfio_find_dma(iommu, iova, size)) {
+	if (vfio_find_dma(iommu, iova, size, VFIO_IOVA_ANY)) {
 		mutex_unlock(&iommu->lock);
 		return -EEXIST;
 	}
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:54:14 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:54:14 +0000
Subject: [PATCH v9 3/7] vfio/type1: bypass unmap/unpin and replay for
 VFIO_IOVA_RESERVED slots
In-Reply-To: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362858-2925-4-git-send-email-eric.auger@linaro.org>

Before allowing the end-user to create VFIO_IOVA_RESERVED dma slots,
let's implement the expected behavior for removal and replay. As opposed
to user dma slots, IOVAs are not systematically bound to PAs and PAs are
not pinned. VFIO just initializes the IOVA "aperture". IOVAs are allocated
outside of the VFIO framework, typically the MSI layer which is
responsible to free and unmap them. The MSI mapping resources are freeed
by the IOMMU driver on domain destruction.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---

v7 -> v8:
- do no destroy anything anymore, just bypass unmap/unpin and iommu_map
  on replay
---
 drivers/vfio/vfio_iommu_type1.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 2d769d4..94a9916 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -391,7 +391,7 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
 	struct vfio_domain *domain, *d;
 	long unlocked = 0;
 
-	if (!dma->size)
+	if (!dma->size || dma->type != VFIO_IOVA_USER)
 		return;
 	/*
 	 * We use the IOMMU to track the physical addresses, otherwise we'd
@@ -727,6 +727,9 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
 		dma = rb_entry(n, struct vfio_dma, node);
 		iova = dma->iova;
 
+		if (dma->type == VFIO_IOVA_RESERVED)
+			continue;
+
 		while (iova < dma->iova + dma->size) {
 			phys_addr_t phys = iommu_iova_to_phys(d->domain, iova);
 			size_t size;
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:54:15 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:54:15 +0000
Subject: [PATCH v9 4/7] vfio: allow reserved msi iova registration
In-Reply-To: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362858-2925-5-git-send-email-eric.auger@linaro.org>

The user is allowed to register a reserved MSI IOVA range by using the
DMA MAP API and setting the new flag: VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA.
This region is stored in the vfio_dma rb tree. At that point the iova
range is not mapped to any target address yet. The host kernel will use
those iova when needed, typically when MSIs are allocated.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Bharat Bhushan <Bharat.Bhushan at freescale.com>

---
v7 -> v8:
- use iommu_msi_set_aperture function. There is no notion of
  unregistration anymore since the reserved msi slot remains
  until the container gets closed.

v6 -> v7:
- use iommu_free_reserved_iova_domain
- convey prot attributes downto dma-reserved-iommu iova domain creation
- reserved bindings teardown now performed on iommu domain destruction
- rename VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA into
         VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA
- change title
- pass the protection attribute to dma-reserved-iommu API

v3 -> v4:
- use iommu_alloc/free_reserved_iova_domain exported by dma-reserved-iommu
- protect vfio_register_reserved_iova_range implementation with
  CONFIG_IOMMU_DMA_RESERVED
- handle unregistration by user-space and on vfio_iommu_type1 release

v1 -> v2:
- set returned value according to alloc_reserved_iova_domain result
- free the iova domains in case any error occurs

RFC v1 -> v1:
- takes into account Alex comments, based on
  [RFC PATCH 1/6] vfio: Add interface for add/del reserved iova region:
- use the existing dma map/unmap ioctl interface with a flag to register
  a reserved IOVA range. A single reserved iova region is allowed.
---
 drivers/vfio/vfio_iommu_type1.c | 78 ++++++++++++++++++++++++++++++++++++++++-
 include/uapi/linux/vfio.h       | 10 +++++-
 2 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 94a9916..4d3a6f1 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -36,6 +36,7 @@
 #include <linux/uaccess.h>
 #include <linux/vfio.h>
 #include <linux/workqueue.h>
+#include <linux/msi-iommu.h>
 
 #define DRIVER_VERSION  "0.2"
 #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson at redhat.com>"
@@ -445,6 +446,20 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
 	vfio_lock_acct(-unlocked);
 }
 
+static int vfio_set_msi_aperture(struct vfio_iommu *iommu,
+				dma_addr_t iova, size_t size)
+{
+	struct vfio_domain *d;
+	int ret = 0;
+
+	list_for_each_entry(d, &iommu->domain_list, next) {
+		ret = iommu_msi_set_aperture(d->domain, iova, iova + size - 1);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
 static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
 {
 	vfio_unmap_unpin(iommu, dma);
@@ -693,6 +708,63 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
 	return ret;
 }
 
+static int vfio_register_msi_range(struct vfio_iommu *iommu,
+				   struct vfio_iommu_type1_dma_map *map)
+{
+	dma_addr_t iova = map->iova;
+	size_t size = map->size;
+	int ret = 0;
+	struct vfio_dma *dma;
+	unsigned long order;
+	uint64_t mask;
+
+	/* Verify that none of our __u64 fields overflow */
+	if (map->size != size || map->iova != iova)
+		return -EINVAL;
+
+	order =  __ffs(vfio_pgsize_bitmap(iommu));
+	mask = ((uint64_t)1 << order) - 1;
+
+	WARN_ON(mask & PAGE_MASK);
+
+	if (!size || (size | iova) & mask)
+		return -EINVAL;
+
+	/* Don't allow IOVA address wrap */
+	if (iova + size - 1 < iova)
+		return -EINVAL;
+
+	mutex_lock(&iommu->lock);
+
+	if (vfio_find_dma(iommu, iova, size, VFIO_IOVA_ANY)) {
+		ret =  -EEXIST;
+		goto unlock;
+	}
+
+	dma = kzalloc(sizeof(*dma), GFP_KERNEL);
+	if (!dma) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	dma->iova = iova;
+	dma->size = size;
+	dma->type = VFIO_IOVA_RESERVED;
+
+	ret = vfio_set_msi_aperture(iommu, iova, size);
+	if (ret)
+		goto free_unlock;
+
+	vfio_link_dma(iommu, dma);
+	goto unlock;
+
+free_unlock:
+	kfree(dma);
+unlock:
+	mutex_unlock(&iommu->lock);
+	return ret;
+}
+
 static int vfio_bus_type(struct device *dev, void *data)
 {
 	struct bus_type **bus = data;
@@ -1062,7 +1134,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 	} else if (cmd == VFIO_IOMMU_MAP_DMA) {
 		struct vfio_iommu_type1_dma_map map;
 		uint32_t mask = VFIO_DMA_MAP_FLAG_READ |
-				VFIO_DMA_MAP_FLAG_WRITE;
+				VFIO_DMA_MAP_FLAG_WRITE |
+				VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA;
 
 		minsz = offsetofend(struct vfio_iommu_type1_dma_map, size);
 
@@ -1072,6 +1145,9 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 		if (map.argsz < minsz || map.flags & ~mask)
 			return -EINVAL;
 
+		if (map.flags & VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA)
+			return vfio_register_msi_range(iommu, &map);
+
 		return vfio_dma_do_map(iommu, &map);
 
 	} else if (cmd == VFIO_IOMMU_UNMAP_DMA) {
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 255a211..4a9dbc2 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -498,12 +498,19 @@ struct vfio_iommu_type1_info {
  *
  * Map process virtual addresses to IO virtual addresses using the
  * provided struct vfio_dma_map. Caller sets argsz. READ &/ WRITE required.
+ *
+ * In case RESERVED_MSI_IOVA flag is set, the API only aims at registering an
+ * IOVA region that will be used on some platforms to map the host MSI frames.
+ * In that specific case, vaddr is ignored. Once registered, an MSI reserved
+ * IOVA region stays until the container is closed.
  */
 struct vfio_iommu_type1_dma_map {
 	__u32	argsz;
 	__u32	flags;
 #define VFIO_DMA_MAP_FLAG_READ (1 << 0)		/* readable from device */
 #define VFIO_DMA_MAP_FLAG_WRITE (1 << 1)	/* writable from device */
+/* reserved iova for MSI vectors*/
+#define VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA (1 << 2)
 	__u64	vaddr;				/* Process virtual address */
 	__u64	iova;				/* IO virtual address */
 	__u64	size;				/* Size of mapping (bytes) */
@@ -519,7 +526,8 @@ struct vfio_iommu_type1_dma_map {
  * Caller sets argsz.  The actual unmapped size is returned in the size
  * field.  No guarantee is made to the user that arbitrary unmaps of iova
  * or size different from those used in the original mapping call will
- * succeed.
+ * succeed. Once registered, an MSI region cannot be unmapped and stays
+ * until the container is closed.
  */
 struct vfio_iommu_type1_dma_unmap {
 	__u32	argsz;
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:54:16 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:54:16 +0000
Subject: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability at msi
 domain
In-Reply-To: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362858-2925-6-git-send-email-eric.auger@linaro.org>

On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is abstracted
by the msi controller. vfio_safe_irq_domain allows to check whether
interrupts are "safe" for a given device. They are if the device does
not use MSI or if the device uses MSI and the msi-parent controller
supports IRQ remapping.

Then we check at group level if all devices have safe interrupts: if not,
we only allow the group to be attached if allow_unsafe_interrupts is set.

At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP. This is
changed in next patch.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v3 -> v4:
- rename vfio_msi_parent_irq_remapping_capable into vfio_safe_irq_domain
  and irq_remapping into safe_irq_domains

v2 -> v3:
- protect vfio_msi_parent_irq_remapping_capable with
  CONFIG_GENERIC_MSI_IRQ_DOMAIN
---
 drivers/vfio/vfio_iommu_type1.c | 44 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 4d3a6f1..2fc8197 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -37,6 +37,8 @@
 #include <linux/vfio.h>
 #include <linux/workqueue.h>
 #include <linux/msi-iommu.h>
+#include <linux/irqdomain.h>
+#include <linux/msi.h>
 
 #define DRIVER_VERSION  "0.2"
 #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson at redhat.com>"
@@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev, void *data)
 	return 0;
 }
 
+/**
+ * vfio_safe_irq_domain: returns whether the irq domain
+ * the device is attached to is safe with respect to MSI isolation.
+ * If the irq domain is not an MSI domain, we return it is safe.
+ *
+ * @dev: device handle
+ * @data: unused
+ * returns 0 if the irq domain is safe, -1 if not.
+ */
+static int vfio_safe_irq_domain(struct device *dev, void *data)
+{
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	struct irq_domain *domain;
+	struct msi_domain_info *info;
+
+	domain = dev_get_msi_domain(dev);
+	if (!domain)
+		return 0;
+
+	info = msi_get_domain_info(domain);
+
+	if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
+		return -1;
+#endif
+	return 0;
+}
+
 static int vfio_iommu_replay(struct vfio_iommu *iommu,
 			     struct vfio_domain *domain)
 {
@@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
 	struct vfio_group *group, *g;
 	struct vfio_domain *domain, *d;
 	struct bus_type *bus = NULL;
-	int ret;
+	int ret, safe_irq_domains;
 
 	mutex_lock(&iommu->lock);
 
@@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
 
 	group->iommu_group = iommu_group;
 
+	/*
+	 * Determine if all the devices of the group have a safe irq domain
+	 * with respect to MSI isolation
+	 */
+	safe_irq_domains = !iommu_group_for_each_dev(iommu_group, &bus,
+				       vfio_safe_irq_domain);
+
 	/* Determine bus_type in order to allocate a domain */
 	ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type);
 	if (ret)
@@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
 	INIT_LIST_HEAD(&domain->group_list);
 	list_add(&group->next, &domain->group_list);
 
+	/*
+	 * to advertise safe interrupts either the IOMMU or the MSI controllers
+	 * must support IRQ remapping/interrupt translation
+	 */
 	if (!allow_unsafe_interrupts &&
-	    !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
+	    (!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) && !safe_irq_domains)) {
 		pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",
 		       __func__);
 		ret = -EPERM;
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:54:17 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:54:17 +0000
Subject: [PATCH v9 6/7] iommu/arm-smmu: do not advertise IOMMU_CAP_INTR_REMAP
In-Reply-To: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362858-2925-7-git-send-email-eric.auger@linaro.org>

Do not advertise IOMMU_CAP_INTR_REMAP for arm-smmu(-v3). Indeed the
irq_remapping capability is abstracted on irqchip side for ARM as
opposed to Intel IOMMU featuring IRQ remapping HW.

So to check IRQ remapping capability, the msi domain needs to be
checked instead.

This commit needs to be applied after "vfio/type1: also check IRQ
remapping capability at msi domain" else the legacy interrupt
assignment gets broken with arm-smmu.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
---
 drivers/iommu/arm-smmu-v3.c | 3 ++-
 drivers/iommu/arm-smmu.c    | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index b5d9826..778212c 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1386,7 +1386,8 @@ static bool arm_smmu_capable(enum iommu_cap cap)
 	case IOMMU_CAP_CACHE_COHERENCY:
 		return true;
 	case IOMMU_CAP_INTR_REMAP:
-		return true; /* MSIs are just memory writes */
+		/* interrupt translation handled at MSI controller level */
+		return false;
 	case IOMMU_CAP_NOEXEC:
 		return true;
 	default:
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 0908985..e7c9e89 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1320,7 +1320,8 @@ static bool arm_smmu_capable(enum iommu_cap cap)
 		 */
 		return true;
 	case IOMMU_CAP_INTR_REMAP:
-		return true; /* MSIs are just memory writes */
+		/* interrupt translation handled at MSI controller level */
+		return false;
 	case IOMMU_CAP_NOEXEC:
 		return true;
 	default:
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 04:54:18 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 11:54:18 +0000
Subject: [PATCH v9 7/7] vfio/type1: return MSI geometry through
 VFIO_IOMMU_GET_INFO capability chains
In-Reply-To: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462362858-2925-8-git-send-email-eric.auger@linaro.org>

This patch allows the user-space to retrieve the MSI geometry. The
implementation is based on capability chains, now also added to
VFIO_IOMMU_GET_INFO.

The returned info comprise:
- whether the MSI IOVA are constrained to a reserved range (x86 case) and
  in the positive, the start/end of the aperture,
- or whether the IOVA aperture need to be set by the userspace. In that
  case, the size and alignment of the IOVA region to be provided are
  returned.

In case the userspace must provide the IOVA range, we currently return
an arbitrary number of IOVA pages (16), supposed to fulfill the needs of
current ARM platforms. This may be deprecated by a more sophisticated
computation later on.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v8 -> v9:
- use iommu_msi_supported flag instead of programmable
- replace IOMMU_INFO_REQUIRE_MSI_MAP flag by a more sophisticated
  capability chain, reporting the MSI geometry

v7 -> v8:
- use iommu_domain_msi_geometry

v6 -> v7:
- remove the computation of the number of IOVA pages to be provisionned.
  This number depends on the domain/group/device topology which can
  dynamically change. Let's rely instead rely on an arbitrary max depending
  on the system

v4 -> v5:
- move msi_info and ret declaration within the conditional code

v3 -> v4:
- replace former vfio_domains_require_msi_mapping by
  more complex computation of MSI mapping requirements, especially the
  number of pages to be provided by the user-space.
- reword patch title

RFC v1 -> v1:
- derived from
  [RFC PATCH 3/6] vfio: Extend iommu-info to return MSIs automap state
- renamed allow_msi_reconfig into require_msi_mapping
- fixed VFIO_IOMMU_GET_INFO
---
 drivers/vfio/vfio_iommu_type1.c | 69 +++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/vfio.h       | 30 +++++++++++++++++-
 2 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 2fc8197..841360b 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -1134,6 +1134,50 @@ static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu)
 	return ret;
 }
 
+static int compute_msi_geometry_caps(struct vfio_iommu *iommu,
+				     struct vfio_info_cap *caps)
+{
+	struct vfio_iommu_type1_info_cap_msi_geometry *vfio_msi_geometry;
+	struct iommu_domain_msi_geometry msi_geometry;
+	struct vfio_info_cap_header *header;
+	struct vfio_domain *d;
+	bool mapping_required;
+	size_t size;
+
+	mutex_lock(&iommu->lock);
+	/* All domains have same require_msi_map property, pick first */
+	d = list_first_entry(&iommu->domain_list, struct vfio_domain, next);
+	iommu_domain_get_attr(d->domain, DOMAIN_ATTR_MSI_GEOMETRY,
+			      &msi_geometry);
+	mapping_required = msi_geometry.iommu_msi_supported;
+
+	mutex_unlock(&iommu->lock);
+
+	size = sizeof(*vfio_msi_geometry);
+	header = vfio_info_cap_add(caps, size,
+				   VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY, 1);
+
+	if (IS_ERR(header))
+		return PTR_ERR(header);
+
+	vfio_msi_geometry = container_of(header,
+				struct vfio_iommu_type1_info_cap_msi_geometry,
+				header);
+
+	vfio_msi_geometry->reserved = !mapping_required;
+	if (vfio_msi_geometry->reserved) {
+		vfio_msi_geometry->aperture_start = msi_geometry.aperture_start;
+		vfio_msi_geometry->aperture_end = msi_geometry.aperture_end;
+		return 0;
+	}
+
+	vfio_msi_geometry->alignment = 1 << __ffs(vfio_pgsize_bitmap(iommu));
+	/* we currently report the need for an arbitray number of 16 pages */
+	vfio_msi_geometry->size = 16 * vfio_msi_geometry->alignment;
+
+	return 0;
+}
+
 static long vfio_iommu_type1_ioctl(void *iommu_data,
 				   unsigned int cmd, unsigned long arg)
 {
@@ -1155,6 +1199,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 		}
 	} else if (cmd == VFIO_IOMMU_GET_INFO) {
 		struct vfio_iommu_type1_info info;
+		struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
+		int ret;
 
 		minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes);
 
@@ -1168,6 +1214,29 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 
 		info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
 
+		ret = compute_msi_geometry_caps(iommu, &caps);
+		if (ret)
+			return ret;
+
+		if (caps.size) {
+			info.flags |= VFIO_IOMMU_INFO_CAPS;
+			if (info.argsz < sizeof(info) + caps.size) {
+				info.argsz = sizeof(info) + caps.size;
+				info.cap_offset = 0;
+			} else {
+				vfio_info_cap_shift(&caps, sizeof(info));
+				if (copy_to_user((void __user *)arg +
+						sizeof(info), caps.buf,
+						caps.size)) {
+					kfree(caps.buf);
+					return -EFAULT;
+				}
+				info.cap_offset = sizeof(info);
+			}
+
+			kfree(caps.buf);
+		}
+
 		return copy_to_user((void __user *)arg, &info, minsz) ?
 			-EFAULT : 0;
 
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 4a9dbc2..0ff6a8d 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -488,7 +488,33 @@ struct vfio_iommu_type1_info {
 	__u32	argsz;
 	__u32	flags;
 #define VFIO_IOMMU_INFO_PGSIZES (1 << 0)	/* supported page sizes info */
-	__u64	iova_pgsizes;		/* Bitmap of supported page sizes */
+#define VFIO_IOMMU_INFO_CAPS	(1 << 1)	/* Info supports caps */
+	__u32   cap_offset;	/* Offset within info struct of first cap */
+	__u64	iova_pgsizes;	/* Bitmap of supported page sizes */
+};
+
+#define VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY	1
+
+/*
+ * The MSI geometry capability allows to report the MSI IOVA geometry:
+ * - either the MSI IOVAs are constrained within a reserved IOVA aperture
+ *   whose boundaries are given by [@aperture_start, @aperture_end].
+ *   this is typically the case on x86 host. The userspace is not allowed
+ *   to map userspace memory at IOVAs intersecting this range using
+ *   VFIO_IOMMU_MAP_DMA.
+ * - or the MSI IOVAs are not requested to belong to any reserved range;
+ *   in that case the userspace must provide an IOVA window characterized by
+ *   @size and @alignment using VFIO_IOMMU_MAP_DMA with RESERVED_MSI_IOVA flag.
+ */
+struct vfio_iommu_type1_info_cap_msi_geometry {
+	struct vfio_info_cap_header header;
+	bool reserved; /* Are MSI IOVAs within a reserved aperture? */
+	/* reserved */
+	__u64 aperture_start;
+	__u64 aperture_end;
+	/* not reserved */
+	__u64 size; /* IOVA aperture size in bytes the userspace must provide */
+	__u64 alignment; /* alignment of the window, in bytes */
 };
 
 #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
@@ -503,6 +529,8 @@ struct vfio_iommu_type1_info {
  * IOVA region that will be used on some platforms to map the host MSI frames.
  * In that specific case, vaddr is ignored. Once registered, an MSI reserved
  * IOVA region stays until the container is closed.
+ * The requirement for provisioning such reserved IOVA range can be checked by
+ * checking the VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY capability.
  */
 struct vfio_iommu_type1_dma_map {
 	__u32	argsz;
-- 
1.9.1



From felipe.balbi at linux.intel.com  Wed May  4 04:56:34 2016
From: felipe.balbi at linux.intel.com (Felipe Balbi)
Date: Wed, 04 May 2016 14:56:34 +0300
Subject: [PATCH] usb: xhci-mtk: fixup mouse wakeup failure during system
 suspend
In-Reply-To: <1462359261.11651.69.camel@mhfsdcap03>
References: <1461204293-18243-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462261458.11651.7.camel@mhfsdcap03> <87vb2vfujq.fsf@intel.com>
 <1462266591.11651.34.camel@mhfsdcap03> <87mvo7fpuc.fsf@intel.com>
 <1462324873.11651.57.camel@mhfsdcap03> <871t5ifdxk.fsf@intel.com>
 <1462359261.11651.69.camel@mhfsdcap03>
Message-ID: <87mvo6dojx.fsf@intel.com>


Hi,

chunfeng yun <chunfeng.yun at mediatek.com> writes:
>> chunfeng yun <chunfeng.yun at mediatek.com> writes:
>> > On Tue, 2016-05-03 at 12:33 +0300, Felipe Balbi wrote:
>> >> Hi,
>> >> 
>> >> chunfeng yun <chunfeng.yun at mediatek.com> writes:
>> >> >> chunfeng yun <chunfeng.yun at mediatek.com> writes:
>> >> >> > On Thu, 2016-04-21 at 10:04 +0800, Chunfeng Yun wrote:
>> >> >> >> Click mouse after xhci suspend completion but before system suspend
>> >> >> >> completion, system will not be waken up by mouse if the duration of
>> >> >> >> them is larger than 20ms which is the device UFP's resume signaling
>> >> >> 
>> >> >> what is "them" here ? The duration of what is longer than 20ms ?
>> >> > They are "xhci suspend completion" and "system suspend completion";
>> >> >
>> >> > It's time duration
>> >> 
>> >> okay. So if xhci suspend takes longer than 20ms your SPM doesn't see a
>> >> wakeup ?
>> > It is not the time of xhci suspend consumed, but is the time of duration
>> > from xhci suspend completion to system suspend completion(after BOOT-CPU
>> > is turned off, SPM will be enabled to receive wakeup event)
>> 
>> Okay, so SPM will be the entity actually handling wakeups, right ? I'm
>> assuming something like this happens:
>> 
>> echo mem > /sys/power/state
>>  /* start suspending devices */
>>   xhci_suspend()
>>  /* all devices suspended */
>>  enable_spm()
>> 
>> so, if a mouse button is pressed after xhci_suspend() returns but before
>> enable_spm() runs, then we're gonna miss that event, am I right ?
> Yes, you are right.
>> 
>> I can't think of any way to sort this out. Let's ask on linux-pm (I've
>> added linux-pm to Cc list)
> Thanks
>> 
>> >> >> >> lasted. Another reason is that the SPM is not enabled before system
>> >> >> 
>> >> >> what's SPM ?
>> >> > It is System Power Management which is powered off when system is
>> >> > running in normal mode, and is powered on when system enters suspend
>> >> > mode. It is used to wakeup system when some wakeup sources, such as
>> >> > bluetooth or powerkey etc, tigger wakeup event.
>> >> 
>> >> okay, thanks
>> >> 
>> >> >> >> suspend compeltion, this causes SPM also not notice the resume signal.
>> >> >>            ^^^^^^^^^^
>> >> >>            completion
>> >> >> 
>> >> >> >> So in order to reduce the duration less than 20ms, make use of
>> >> >> >> syscore's suspend/resume interface.
>> >> >> 
>> >> >> no, this is the wrong approach
>> >> > But it seems only one workable approach from software side
>> >> 
>> >> I wouldn't say that. It seems to me SPM should be enabled earlier.
>> > Yes, but normally SPM should be enabled after all CPUS are turned off,
>> > so it's difficult to do that, I mean enable SPM before turning off CPUS
>> 
>> is it a requirement that SPM should be enabled only after all CPUs are
>> turned off ? If that's the case, then any device in the system might
>> have missed wakeups. This doesn't seem like a good design to me; unless
>> I'm missing something...
> Yes, it's a requirement.
>
> If the wakeup source is level trigger, and will keep it until SPM notice
> it. Although USB wakeup is level trigger, but it just last at most 20ms
> and clear itself automatically.

who's clearing USB wakeup after 20ms ? Sure, it's a requirement by the
USB spec that host should drive reset for *at least* 20ms, but I don't
remember the exact wordings WRT remote wakeup

/me reads

Okay, here it is, section 7.1.7.7 of USB 2.0 Spec states:

	"The remote wakeup device must hold the resume signaling for at
        least 1 ms but for no more than 15 ms (TDRSMUP). At the end of
        this period, the device stops driving the bus (puts its drivers
        into the high-impedance state and does not drive the bus to the
        J state)."

IOW, the mouse is not at fault here. Remote wakeup can last anywhere
between 1ms and 15ms. If your system can't cope with it, then I'd say
it's a problem with your system and you shouldn't allow XHCI to go to
such deep power states until SPM is enabled.

I really tried finding the correct piece of code which does this for PCI
devices, but basically it's treated as an IRQ and as long as
enable_irq_wake() or the sysfs file is set to true, then PME gets
enabled (hopefully PCI folks can confirm this statement).

Very recently Tony Lindgren added proper handling of wakeup signals as
IRQs for non-PCI systems too (see 4990d4fe327b PM / Wakeirq: Add
automated device wake IRQ handling), wonder if you could treat SPM
similarly.

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/bec02f4f/attachment.sig>

From k.kozlowski at samsung.com  Wed May  4 05:01:57 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 04 May 2016 14:01:57 +0200
Subject: [RFT PATCH 1/3] usb: misc: usb3503: Fix HUB mode after bootloader
 initialization
In-Reply-To: <20160503180022.GA3008@rob-hp-laptop>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <1461927591-7864-2-git-send-email-k.kozlowski@samsung.com>
 <20160429113059.GX3217@sirena.org.uk> <57234BA2.6020304@samsung.com>
 <20160429164448.GY3217@sirena.org.uk> <57272298.50701@samsung.com>
 <20160502105501.GE6292@sirena.org.uk> <20160503180022.GA3008@rob-hp-laptop>
Message-ID: <5729E4B5.2090702@samsung.com>

On 05/03/2016 08:00 PM, Rob Herring wrote:
> On Mon, May 02, 2016 at 11:55:01AM +0100, Mark Brown wrote:
>> On Mon, May 02, 2016 at 11:49:12AM +0200, Krzysztof Kozlowski wrote:
>>
>>> This VDD regulator supply actually is not a usb3503 USB HUB regulator
>>> supply... but a supply to the LAN attached to this HUB. Regulator off/on
>>> is needed for LAN to show up. The hub will show up with typical reset
>>> (which is also missing before my patchset btw).
>>
>>> The LAN, as a USB device, is auto-probed so it cannot take the regulator
>>> and play with it. The simplest idea I have is to add it as "external
>>> supply"  to the parent: usb3503.
>>
>> This is common enough that that just isn't going to scale well I fear
>> without some generic handling, either walking child devices at the bus
>> level or at the device level with a pre-probe() callback to get the
>> device to power on.  The latter is more appropriate to things like
>> Slimbus where the device is more likely to do active management at
>> runtime, it's not clear people are building USB devices like that.
> 
> There's a new binding and support in -next (.../usb/usb-device.txt) for 
> USB devices that should help here. Though, how to handle a hub on USB 
> and I2C buses would need to be worked out.

This binding might help, especially with other idea we have - usage of
pwrseq for the USB hub.

The USB hub, without toggling the regulator off/on, appears as USB
device only sometimes. Apparently there is some timing or other
behavior. not yet known to me.

When playing with regulator, the USB hub and child USB device (LAN) will
appear correctly.

This looks like pwrseq for MMC devices so the idea is to:
1. Move drivers/mmc/core/pwrseq* to separate directory
(drivers/power/pwrseq ?)
2. Add support for pwrseq to USB core,
3. Add new pwrseq driver (or extend existing one): toggling the regulator.
4. Add pwrseq phandle to the DT node of USB hub (to the binding
mentioned by Rob?).


Does it look sensible?

Best regards,
Krzysztof



From marc.zyngier at arm.com  Wed May  4 05:02:12 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 4 May 2016 13:02:12 +0100
Subject: [PATCH v3] sunxi-irq: Fix Kconfig dependency on GENERIC_IRQ_CHIP
In-Reply-To: <5729D2A0.70900@arm.com>
References: <1461546292-21110-1-git-send-email-andre.przywara@arm.com>
 <20160502064854.GL17159@lukather> <5729D2A0.70900@arm.com>
Message-ID: <5729E4C4.60500@arm.com>

On 04/05/16 11:44, Andre Przywara wrote:
> Hi Maxime,
> 
> On 02/05/16 07:48, Maxime Ripard wrote:
>> Hi,
>>
>> On Mon, Apr 25, 2016 at 02:04:52AM +0100, Andre Przywara wrote:
>>> The Allwinner NMI irqchip driver requires GENERIC_IRQ_CHIP, but
>>> we can't select it directly, because there is no specific Kconfig entry
>>> for the driver. Compiling this NMI driver with certain arm64
>>> configurations thus fails due to the missing dependency:
>>>
>>> drivers/built-in.o: In function `sunxi_sc_nmi_set_type':
>>> drivers/irqchip/irq-sunxi-nmi.c:114: undefined reference to `irq_setup_alt_chip'
>>> drivers/built-in.o: In function `irq_domain_add_linear':
>>> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
>>> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
>>> drivers/built-in.o: In function `sunxi_sc_nmi_irq_init':
>>> drivers/irqchip/irq-sunxi-nmi.c:146: undefined reference to `irq_alloc_domain_generic_chips'
>>> drivers/irqchip/irq-sunxi-nmi.c:161: undefined reference to `irq_get_domain_generic_chip'
>>> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
>>> drivers/irqchip/irq-sunxi-nmi.c:171: undefined reference to `irq_gc_mask_set_bit'
>>> drivers/irqchip/irq-sunxi-nmi.c:172: undefined reference to `irq_gc_ack_set_bit'
>>> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
>>>
>>> Add separate Kconfig options for both Allwinner specific irqchip
>>> drivers and select GENERIC_IRQ_CHIP for the NMI driver.
>>> The older sun4i IRQ driver only gets selected when support for these
>>> specific SoCs is compiled, while the NMI driver is selected for all
>>> Allwinner SoCs (copying the current behaviour and covering future SoCs
>>> automatically).
>>>
>>> Reported-by: Suzuki K Poulose <Suzuki.Poulose at arm.com>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>> Hi,
>>>
>>> this is a new approach to the problem that Suzuki tried to address
>>> already.
>>> It separates the sun4i IRQ controller driver and the NMI driver as
>>> Maxime requested.
>>> While there should be no difference for the NMI driver, the sun4i
>>> driver now only gets selected for certain SoCs, which is admittedly
>>> a bold call for -rc5. If people find this too risky, I can bring the
>>> sun4i in line with the NMI driver (selected for all ARCH_SUNXI) for
>>> this release and re-create the more selective dependency as a merge
>>> window patch, so that it gets more testing.
>>> Please let me know.
>>>
>>> Cheers,
>>> Andre.
>>>
>>>  arch/arm/mach-sunxi/Kconfig | 3 ++-
>>>  drivers/irqchip/Kconfig     | 8 ++++++++
>>>  drivers/irqchip/Makefile    | 4 ++--
>>>  3 files changed, 12 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
>>> index c124d65..c092bc2 100644
>>> --- a/arch/arm/mach-sunxi/Kconfig
>>> +++ b/arch/arm/mach-sunxi/Kconfig
>>> @@ -4,7 +4,6 @@ menuconfig ARCH_SUNXI
>>>  	select ARCH_REQUIRE_GPIOLIB
>>>  	select ARCH_HAS_RESET_CONTROLLER
>>>  	select CLKSRC_MMIO
>>> -	select GENERIC_IRQ_CHIP
>>>  	select PINCTRL
>>>  	select SUN4I_TIMER
>>>  	select RESET_CONTROLLER
>>> @@ -14,11 +13,13 @@ if ARCH_SUNXI
>>>  config MACH_SUN4I
>>>  	bool "Allwinner A10 (sun4i) SoCs support"
>>>  	default ARCH_SUNXI
>>> +	select SUN4I_IRQCHIP
>>>  
>>>  config MACH_SUN5I
>>>  	bool "Allwinner A10s / A13 (sun5i) SoCs support"
>>>  	default ARCH_SUNXI
>>>  	select SUN5I_HSTIMER
>>> +	select SUN4I_IRQCHIP
>>>  
>>>  config MACH_SUN6I
>>>  	bool "Allwinner A31 (sun6i) SoCs support"
>>> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
>>> index 3e12479..94f3f42 100644
>>> --- a/drivers/irqchip/Kconfig
>>> +++ b/drivers/irqchip/Kconfig
>>> @@ -165,6 +165,14 @@ config ST_IRQCHIP
>>>  	help
>>>  	  Enables SysCfg Controlled IRQs on STi based platforms.
>>>  
>>> +config SUN4I_IRQCHIP
>>> +	bool
>>> +
>>> +config SUNXI_NMI
>>> +	bool "Allwinner SoC NMI controller"
>>> +	default ARCH_SUNXI
>>> +	select GENERIC_IRQ_CHIP
>>
>> This one is only used on SUN6I, SUN7I and SUN8I. There's no need to
>> enable it for all the SoCs.
> 
> But it is enabled for all SoCs at the moment - and as it is actually a
> fix (-rc1 does not compile for certain arm64 configs) I'd really like to
> not take chances here.

If there is an arm64 config that breaks, let's revert the patch that
introduces the breakage (ce3dd55), because it doesn't look like we're
making forward progress on this (and given that we're -rc6, that's
probably a suitable course of action).

We can always merge the fixed patch when the interested parties have
settled on a suitable shade of green for the shed...

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From eric.auger at linaro.org  Wed May  4 05:06:19 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed, 4 May 2016 14:06:19 +0200
Subject: [PATCH v9 7/7] vfio/type1: return MSI geometry through
 VFIO_IOMMU_GET_INFO capability chains
In-Reply-To: <1462362858-2925-8-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-8-git-send-email-eric.auger@linaro.org>
Message-ID: <5729E5BB.1030101@linaro.org>

Hi Alex,
On 05/04/2016 01:54 PM, Eric Auger wrote:
> This patch allows the user-space to retrieve the MSI geometry. The
> implementation is based on capability chains, now also added to
> VFIO_IOMMU_GET_INFO.

If you prefer we could consider this patch outside of the main series
since it brings extra functionalities (MSI geometry reporting). In a
first QEMU integration we would live without knowing the MSI geometry I
think, all the more so I currently report an arbitrary number of
requested IOVA pages. The computation of the exact number of doorbells
to map brings extra complexity and I did not address this issue yet.

It sketches a possible user API to report the MSI geometry based on the
capability chains, as you suggested some time ago. I am currently busy
drafting a QEMU integration.

Best Regards

Eric
> 
> The returned info comprise:
> - whether the MSI IOVA are constrained to a reserved range (x86 case) and
>   in the positive, the start/end of the aperture,
> - or whether the IOVA aperture need to be set by the userspace. In that
>   case, the size and alignment of the IOVA region to be provided are
>   returned.
> 
> In case the userspace must provide the IOVA range, we currently return
> an arbitrary number of IOVA pages (16), supposed to fulfill the needs of
> current ARM platforms. This may be deprecated by a more sophisticated
> computation later on.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> 
> ---
> v8 -> v9:
> - use iommu_msi_supported flag instead of programmable
> - replace IOMMU_INFO_REQUIRE_MSI_MAP flag by a more sophisticated
>   capability chain, reporting the MSI geometry
> 
> v7 -> v8:
> - use iommu_domain_msi_geometry
> 
> v6 -> v7:
> - remove the computation of the number of IOVA pages to be provisionned.
>   This number depends on the domain/group/device topology which can
>   dynamically change. Let's rely instead rely on an arbitrary max depending
>   on the system
> 
> v4 -> v5:
> - move msi_info and ret declaration within the conditional code
> 
> v3 -> v4:
> - replace former vfio_domains_require_msi_mapping by
>   more complex computation of MSI mapping requirements, especially the
>   number of pages to be provided by the user-space.
> - reword patch title
> 
> RFC v1 -> v1:
> - derived from
>   [RFC PATCH 3/6] vfio: Extend iommu-info to return MSIs automap state
> - renamed allow_msi_reconfig into require_msi_mapping
> - fixed VFIO_IOMMU_GET_INFO
> ---
>  drivers/vfio/vfio_iommu_type1.c | 69 +++++++++++++++++++++++++++++++++++++++++
>  include/uapi/linux/vfio.h       | 30 +++++++++++++++++-
>  2 files changed, 98 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 2fc8197..841360b 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -1134,6 +1134,50 @@ static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu)
>  	return ret;
>  }
>  
> +static int compute_msi_geometry_caps(struct vfio_iommu *iommu,
> +				     struct vfio_info_cap *caps)
> +{
> +	struct vfio_iommu_type1_info_cap_msi_geometry *vfio_msi_geometry;
> +	struct iommu_domain_msi_geometry msi_geometry;
> +	struct vfio_info_cap_header *header;
> +	struct vfio_domain *d;
> +	bool mapping_required;
> +	size_t size;
> +
> +	mutex_lock(&iommu->lock);
> +	/* All domains have same require_msi_map property, pick first */
> +	d = list_first_entry(&iommu->domain_list, struct vfio_domain, next);
> +	iommu_domain_get_attr(d->domain, DOMAIN_ATTR_MSI_GEOMETRY,
> +			      &msi_geometry);
> +	mapping_required = msi_geometry.iommu_msi_supported;
> +
> +	mutex_unlock(&iommu->lock);
> +
> +	size = sizeof(*vfio_msi_geometry);
> +	header = vfio_info_cap_add(caps, size,
> +				   VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY, 1);
> +
> +	if (IS_ERR(header))
> +		return PTR_ERR(header);
> +
> +	vfio_msi_geometry = container_of(header,
> +				struct vfio_iommu_type1_info_cap_msi_geometry,
> +				header);
> +
> +	vfio_msi_geometry->reserved = !mapping_required;
> +	if (vfio_msi_geometry->reserved) {
> +		vfio_msi_geometry->aperture_start = msi_geometry.aperture_start;
> +		vfio_msi_geometry->aperture_end = msi_geometry.aperture_end;
> +		return 0;
> +	}
> +
> +	vfio_msi_geometry->alignment = 1 << __ffs(vfio_pgsize_bitmap(iommu));
> +	/* we currently report the need for an arbitray number of 16 pages */
> +	vfio_msi_geometry->size = 16 * vfio_msi_geometry->alignment;
> +
> +	return 0;
> +}
> +
>  static long vfio_iommu_type1_ioctl(void *iommu_data,
>  				   unsigned int cmd, unsigned long arg)
>  {
> @@ -1155,6 +1199,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>  		}
>  	} else if (cmd == VFIO_IOMMU_GET_INFO) {
>  		struct vfio_iommu_type1_info info;
> +		struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
> +		int ret;
>  
>  		minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes);
>  
> @@ -1168,6 +1214,29 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>  
>  		info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
>  
> +		ret = compute_msi_geometry_caps(iommu, &caps);
> +		if (ret)
> +			return ret;
> +
> +		if (caps.size) {
> +			info.flags |= VFIO_IOMMU_INFO_CAPS;
> +			if (info.argsz < sizeof(info) + caps.size) {
> +				info.argsz = sizeof(info) + caps.size;
> +				info.cap_offset = 0;
> +			} else {
> +				vfio_info_cap_shift(&caps, sizeof(info));
> +				if (copy_to_user((void __user *)arg +
> +						sizeof(info), caps.buf,
> +						caps.size)) {
> +					kfree(caps.buf);
> +					return -EFAULT;
> +				}
> +				info.cap_offset = sizeof(info);
> +			}
> +
> +			kfree(caps.buf);
> +		}
> +
>  		return copy_to_user((void __user *)arg, &info, minsz) ?
>  			-EFAULT : 0;
>  
> diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
> index 4a9dbc2..0ff6a8d 100644
> --- a/include/uapi/linux/vfio.h
> +++ b/include/uapi/linux/vfio.h
> @@ -488,7 +488,33 @@ struct vfio_iommu_type1_info {
>  	__u32	argsz;
>  	__u32	flags;
>  #define VFIO_IOMMU_INFO_PGSIZES (1 << 0)	/* supported page sizes info */
> -	__u64	iova_pgsizes;		/* Bitmap of supported page sizes */
> +#define VFIO_IOMMU_INFO_CAPS	(1 << 1)	/* Info supports caps */
> +	__u32   cap_offset;	/* Offset within info struct of first cap */
> +	__u64	iova_pgsizes;	/* Bitmap of supported page sizes */
> +};
> +
> +#define VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY	1
> +
> +/*
> + * The MSI geometry capability allows to report the MSI IOVA geometry:
> + * - either the MSI IOVAs are constrained within a reserved IOVA aperture
> + *   whose boundaries are given by [@aperture_start, @aperture_end].
> + *   this is typically the case on x86 host. The userspace is not allowed
> + *   to map userspace memory at IOVAs intersecting this range using
> + *   VFIO_IOMMU_MAP_DMA.
> + * - or the MSI IOVAs are not requested to belong to any reserved range;
> + *   in that case the userspace must provide an IOVA window characterized by
> + *   @size and @alignment using VFIO_IOMMU_MAP_DMA with RESERVED_MSI_IOVA flag.
> + */
> +struct vfio_iommu_type1_info_cap_msi_geometry {
> +	struct vfio_info_cap_header header;
> +	bool reserved; /* Are MSI IOVAs within a reserved aperture? */
> +	/* reserved */
> +	__u64 aperture_start;
> +	__u64 aperture_end;
> +	/* not reserved */
> +	__u64 size; /* IOVA aperture size in bytes the userspace must provide */
> +	__u64 alignment; /* alignment of the window, in bytes */
>  };
>  
>  #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
> @@ -503,6 +529,8 @@ struct vfio_iommu_type1_info {
>   * IOVA region that will be used on some platforms to map the host MSI frames.
>   * In that specific case, vaddr is ignored. Once registered, an MSI reserved
>   * IOVA region stays until the container is closed.
> + * The requirement for provisioning such reserved IOVA range can be checked by
> + * checking the VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY capability.
>   */
>  struct vfio_iommu_type1_dma_map {
>  	__u32	argsz;
> 



From linux at arm.linux.org.uk  Wed May  4 05:15:41 2016
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Wed, 4 May 2016 13:15:41 +0100
Subject: Loss of zeniv.linux.org.uk - my git tree now, potentially email, and
 more
Message-ID: <20160504121541.GQ19428@n2100.arm.linux.org.uk>

Things are going to be particularly difficult for the upcoming merge
window for me.

Right now, the machine which I host my git tree became partially
unresponsive in the early hours of Monday morning - the kernel was
up and running, but userspace was completely dead.  The machine would
ping, and accept tcp connections, but that was all.

While requesting on-site engineers to reset/power cycle the box, it
turns out that the (three year old) power supply has developed an
identical fault to the previous power supply, where the machine only
stays powered on for less than a second before power collapses and it
cycles.

In theory, this is a simple matter of either getting the power supply
replaced, or getting access to the hosting site.  However, it appears
that despite the machine owner and myself being able to get access
three years ago, Vodafone (the hosting company) are now telling is that
we are not permitted physical access to the machine.  That makes repair
or replacement rather difficult.

It sounds like Vodafone have lost part of their customer database.

The latest update this morning is that we've supplied Vodafone with the
necessary details, and we're waiting for their response before we
re-submit our physical access request.

The long and short of it is... my git tree in linux-next is currently
frozen in its -rc4 state, and is currently inaccessible until we get
this resolved, and we have no timescale for its resolution at present.
While I can point git.arm.linux.org.uk elsewhere at the moment, there's
another issue lurking (see below.)

Since we are currently at -rc6, and either -rc7 next week or the
merge window opening, this is going to be a problem.

Another thing to bring up is that I've mentioned to Alan Cox about his
linux.org.uk domain.  Obviously, my arm.linux.org.uk is dependent on
Alan's linux.org.uk domain.  The primary name server was this failed
machine, and the domain appears to have an unusually short expiry
of just one week.

I've discussed with Alan, and he has migrated it to his ISP, but his
ISP doesn't do sub-domains, this may present me with a problem.  To
preempt problems, while this email address is still working, I now
have in place armlinux.org.uk, and I will be transitioning everything
over to this new domain in the coming days/weeks.  Hence, expect me
to start sending email from @armlinux.org.uk addresses.

Obviously, this also means git pulls will (eventually) start coming
from git.armlinux.org.uk as well.

However, I hope to keep at least arm.linux.org.uk email active for a
while yet.

-- 
RMK's Patch system: http://www.arm.linux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From robh+dt at kernel.org  Wed May  4 05:25:42 2016
From: robh+dt at kernel.org (Rob Herring)
Date: Wed, 4 May 2016 07:25:42 -0500
Subject: [PATCH v2 0/4] Patches to allow consistent mmc / mmcblk numbering
 w/ device tree
In-Reply-To: <20160504071801.GA17045@amd>
References: <1461951139-6109-1-git-send-email-dianders@chromium.org>
 <20160429181248.GW19428@n2100.arm.linux.org.uk> <20160504071801.GA17045@amd>
Message-ID: <CAL_JsqJ4Pzuip9VUpwryy_xK6XSZ6E+kus3wD=T4wcTHav=9iA@mail.gmail.com>

On Wed, May 4, 2016 at 2:18 AM, Pavel Machek <pavel at ucw.cz> wrote:
> On Fri 2016-04-29 19:12:48, Russell King - ARM Linux wrote:
>> On Fri, Apr 29, 2016 at 10:32:15AM -0700, Douglas Anderson wrote:
>> > This series picks patches from various different places to produce what
>> > I consider the best solution to getting consistent mmc and mmcblk
>> > ordering.
>> >
>> > Why consistent ordering and why not just use UUIDs?  IMHO consistent
>> > ordering solves a few different problems:
>>
>> NAK.  Really.  Use UUIDs, that's the proper solution here.
>
> Except that UUIDs do not solve the problem.
>
> You have just booted of nfsroot, and you want to format u-SD card in
> the external slot. How do you do that?

The same way you format a USB stick when you insert it.

If you have built-in versus removable, then we should expose that
information to userspace rather than some arbitrary encoding in DT
that 0 means built-in and 1 means removable. Or if you have multiple
slots, then use "label" to provide meaningful slot names.

Rob


From radoslav.kolev at embedlynx.com  Wed May  4 05:30:39 2016
From: radoslav.kolev at embedlynx.com (Radoslav Kolev)
Date: Wed, 4 May 2016 15:30:39 +0300
Subject: [PATCH 1/1] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <CAGb2v66r9m7qVW6BszeT2wqs0KyEr4x5ivTJYqu2Fes=R9-Ltw@mail.gmail.com>
References: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
 <CAGb2v66E2TuN3+tYaAbniV3q67waDZOfqKAW14VJz6xZFomZ=Q@mail.gmail.com>
 <57285162.2000704@schinagl.nl>
 <CAGb2v66r9m7qVW6BszeT2wqs0KyEr4x5ivTJYqu2Fes=R9-Ltw@mail.gmail.com>
Message-ID: <CANCTEQgjiuQXcaw=3Dr5kUsTPc3nsDQf2odwzs4nHvrkREAqrg@mail.gmail.com>

2016-05-03 10:25 GMT+03:00 Chen-Yu Tsai <wens at csie.org>:
> On Tue, May 3, 2016 at 3:21 PM, Olliver Schinagl <oliver at schinagl.nl> wrote:
>>>> +       bus-width = <4>;
>>>
>>> Only 4 bits? We normally see eMMC with 8 bits. 4 bits are some kind of
>>> embedded SD card.
>>
>> On A20 as well? Our investigations so far have concluded that the A10 and
>> A20 have those pins not mapped out to pads. The IP does support it however
>> we assume.
>
> You're right. My bad. First time A10/A20 sees eMMC support.

I can't say anything about A10/A20, but I have a board with A13 and
the same eMMC chip and it works fine in 8 bit mode.

Regards,
Radoslav


From robh at kernel.org  Wed May  4 05:32:02 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 4 May 2016 07:32:02 -0500
Subject: [RFC v6 1/3] gpio: dt-bindings: add wd,mbl-gpio bindings
In-Reply-To: <4330813.s9mxBLCsXA@debian64>
References: <cover.1462104492.git.chunkeey@googlemail.com>
 <103bf8fceb426a9c3b09641ea989955e3ec1c7d4.1462104492.git.chunkeey@googlemail.com>
 <20160504022210.GA9913@rob-hp-laptop> <4330813.s9mxBLCsXA@debian64>
Message-ID: <CAL_JsqLQV-k9O9SjaTnHG5G_JhYqn69xHzLWrqXJAJvGAc=2Og@mail.gmail.com>

On Tue, May 3, 2016 at 11:53 PM, Christian Lamparter
<chunkeey at googlemail.com> wrote:
> On Tuesday, May 03, 2016 09:22:10 PM Rob Herring wrote:
>> On Sun, May 01, 2016 at 02:18:37PM +0200, Christian Lamparter wrote:
>> > This patch adds the device tree bindings for the Western Digital's
>> > MyBook Live memory-mapped GPIO controllers.
>> >
>> > The gpios will be supported by gpio-mmio code of the
>> > GPIO generic library.
>> >
>> > +++ b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
>> > @@ -0,0 +1,38 @@
>> > +Bindings for the Western Digital's MyBook Live memory-mapped GPIO controllers.
>>
>> Are these really product level GPIOs rather than some SOC's GPIOs
>> (APM?)?
>>
> Ah, that's a good point.
>
> In a nutshell: The APM82181 SoC has two proper/normal GPIO controllers
> which have a dt-binding and a kernel driver ready to go.
> However Western Digital went with their own GPIO controller for
> the MyBook Live [7].

Okay, just making sure. It's a little strange to have external (to an
SOC) memory mapped GPIOs is why I asked.

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

Rob

P.S. By v6, you should drop RFC.


From hs.liao at mediatek.com  Wed May  4 05:32:13 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Wed, 4 May 2016 20:32:13 +0800
Subject: [RFC v5 0/4] Mediatek MT8173 CMDQ support
Message-ID: <1462365137-715-1-git-send-email-hs.liao@mediatek.com>


Hi,

This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used
to help read/write registers with critical time limitation, such as
updating display configuration during the vblank. It controls Global
Command Engine (GCE) hardware to achieve this requirement.

These patches have a build dependency on top of v4.6-rc1.

Changes since v4:
 - fix bug of kmem_cache usage
 - print more meaningful log in suspend/resume flow
 - cascade all tasks into one vsync for display
 - merge cmdq_handle_done() and cmdq_handle_done_internal()
 - remove TASK_STATE_START_ERROR and its related flow
 - merge cmdq_rec_append_write() into cmdq_rec_append_command()
 - simplify some functions, such as cmdq_task_insert_into_thread(),
   cmdq_remove(), cmdq_task_acquire(), and cmdq_rec_append_command()
 - refine in program comments

Best regards,
HS Liao

HS Liao (4):
  dt-bindings: soc: Add documentation for the MediaTek GCE unit
  CMDQ: Mediatek CMDQ driver
  arm64: dts: mt8173: Add GCE node
  CMDQ: suspend/resume protection

 .../devicetree/bindings/soc/mediatek/gce.txt       |   34 +
 arch/arm64/boot/dts/mediatek/mt8173.dtsi           |    8 +
 drivers/soc/mediatek/Kconfig                       |   10 +
 drivers/soc/mediatek/Makefile                      |    1 +
 drivers/soc/mediatek/mtk-cmdq.c                    | 1708 ++++++++++++++++++++
 include/soc/mediatek/cmdq.h                        |  197 +++
 6 files changed, 1958 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/gce.txt
 create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
 create mode 100644 include/soc/mediatek/cmdq.h

-- 
1.9.1



From hs.liao at mediatek.com  Wed May  4 05:32:14 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Wed, 4 May 2016 20:32:14 +0800
Subject: [RFC v5 1/4] dt-bindings: soc: Add documentation for the MediaTek GCE
 unit
In-Reply-To: <1462365137-715-1-git-send-email-hs.liao@mediatek.com>
References: <1462365137-715-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1462365137-715-2-git-send-email-hs.liao@mediatek.com>

This adds documentation for the MediaTek Global Command Engine (GCE) unit
found in MT8173 SoCs.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/soc/mediatek/gce.txt       | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/gce.txt

diff --git a/Documentation/devicetree/bindings/soc/mediatek/gce.txt b/Documentation/devicetree/bindings/soc/mediatek/gce.txt
new file mode 100644
index 0000000..eff07e2
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/gce.txt
@@ -0,0 +1,34 @@
+MediaTek GCE
+===============
+
+The Global Command Engine (GCE) is used to help read/write registers with
+critical time limitation, such as updating display configuration during the
+vblank. The GCE can be used to implement the Command Queue (CMDQ) driver.
+
+Required properties:
+- compatible: Must be "mediatek,mt8173-gce"
+- reg: Address range of the GCE unit
+- interrupts: The interrupt signal from the GCE block
+- clock: Clocks according to the common clock binding
+- clock-names: Must be "gce" to stand for GCE clock
+
+Required properties for a client device:
+- mediatek,gce: Should point to the respective GCE block
+
+Example:
+
+	gce: gce at 10212000 {
+		compatible = "mediatek,mt8173-gce";
+		reg = <0 0x10212000 0 0x1000>;
+		interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&infracfg CLK_INFRA_GCE>;
+		clock-names = "gce";
+	};
+
+Example for a client device:
+
+	mmsys: clock-controller at 14000000 {
+		compatible = "mediatek,mt8173-mmsys";
+		mediatek,gce = <&gce>;
+		...
+	};
-- 
1.9.1



From hs.liao at mediatek.com  Wed May  4 05:32:15 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Wed, 4 May 2016 20:32:15 +0800
Subject: [RFC v5 2/4] CMDQ: Mediatek CMDQ driver
In-Reply-To: <1462365137-715-1-git-send-email-hs.liao@mediatek.com>
References: <1462365137-715-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1462365137-715-3-git-send-email-hs.liao@mediatek.com>

This patch is first version of Mediatek Command Queue(CMDQ) driver. The
CMDQ is used to help read/write registers with critical time limitation,
such as updating display configuration during the vblank. It controls
Global Command Engine (GCE) hardware to achieve this requirement.
Currently, CMDQ only supports display related hardwares, but we expect
it can be extended to other hardwares for future requirements.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
---
 drivers/soc/mediatek/Kconfig    |   10 +
 drivers/soc/mediatek/Makefile   |    1 +
 drivers/soc/mediatek/mtk-cmdq.c | 1425 +++++++++++++++++++++++++++++++++++++++
 include/soc/mediatek/cmdq.h     |  197 ++++++
 4 files changed, 1633 insertions(+)
 create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
 create mode 100644 include/soc/mediatek/cmdq.h

diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 0a4ea80..c4ad75c 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -1,6 +1,16 @@
 #
 # MediaTek SoC drivers
 #
+config MTK_CMDQ
+	bool "MediaTek CMDQ Support"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	select MTK_INFRACFG
+	help
+	  Say yes here to add support for the MediaTek Command Queue (CMDQ)
+	  driver. The CMDQ is used to help read/write registers with critical
+	  time limitation, such as updating display configuration during the
+	  vblank.
+
 config MTK_INFRACFG
 	bool "MediaTek INFRACFG Support"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index 12998b0..f7397ef 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq.o
 obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
 obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
 obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
new file mode 100644
index 0000000..d3e9a4c
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-cmdq.c
@@ -0,0 +1,1425 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/suspend.h>
+#include <linux/workqueue.h>
+#include <soc/mediatek/cmdq.h>
+
+#define CMDQ_MAX_THREAD_COUNT		3 /* general, main, sub */
+#define CMDQ_MAX_TASK_IN_THREAD		20
+
+#define CMDQ_INITIAL_CMD_BLOCK_SIZE	PAGE_SIZE
+#define CMDQ_INST_SIZE			8 /* instruction is 64-bit */
+
+/*
+ * cmdq_thread cookie value is from 0 to CMDQ_MAX_COOKIE_VALUE.
+ * And, this value also be used as MASK.
+ */
+#define CMDQ_MAX_COOKIE_VALUE		0xffff
+#define CMDQ_COOKIE_MASK		CMDQ_MAX_COOKIE_VALUE
+
+#define CMDQ_DEFAULT_TIMEOUT_MS		1000
+#define CMDQ_ACQUIRE_THREAD_TIMEOUT_MS	5000
+
+#define CMDQ_DRIVER_DEVICE_NAME		"mtk_cmdq"
+#define CMDQ_CLK_NAME			"gce"
+
+#define CMDQ_CURR_IRQ_STATUS_OFFSET	0x010
+#define CMDQ_THR_SLOT_CYCLES_OFFSET	0x030
+
+#define CMDQ_THR_BASE			0x100
+#define CMDQ_THR_SHIFT			0x080
+#define CMDQ_THR_WARM_RESET_OFFSET	0x00
+#define CMDQ_THR_ENABLE_TASK_OFFSET	0x04
+#define CMDQ_THR_SUSPEND_TASK_OFFSET	0x08
+#define CMDQ_THR_CURR_STATUS_OFFSET	0x0c
+#define CMDQ_THR_IRQ_STATUS_OFFSET	0x10
+#define CMDQ_THR_IRQ_ENABLE_OFFSET	0x14
+#define CMDQ_THR_CURR_ADDR_OFFSET	0x20
+#define CMDQ_THR_END_ADDR_OFFSET	0x24
+#define CMDQ_THR_EXEC_CNT_OFFSET	0x28
+#define CMDQ_THR_CFG_OFFSET		0x40
+#define CMDQ_THR_INST_CYCLES_OFFSET	0x50
+
+#define CMDQ_SYNC_TOKEN_SET		BIT(16)
+#define CMDQ_IRQ_MASK			0xffff
+
+#define CMDQ_THR_ENABLED		0x1
+#define CMDQ_THR_DISABLED		0x0
+#define CMDQ_THR_SUSPEND		0x1
+#define CMDQ_THR_RESUME			0x0
+#define CMDQ_THR_STATUS_SUSPENDED	BIT(1)
+#define CMDQ_THR_WARM_RESET		BIT(0)
+#define CMDQ_THR_SLOT_CYCLES		0x3200
+#define CMDQ_THR_NO_TIMEOUT		0x0
+#define CMDQ_THR_PRIORITY		3
+#define CMDQ_THR_IRQ_DONE		0x1
+#define CMDQ_THR_IRQ_ERROR		0x12
+#define CMDQ_THR_IRQ_EN			0x13 /* done + error */
+#define CMDQ_THR_IRQ_MASK		0x13
+#define CMDQ_THR_EXECUTING		BIT(31)
+
+#define CMDQ_ARG_A_MASK			0xffffff
+#define CMDQ_ARG_A_WRITE_MASK		0xffff
+#define CMDQ_ARG_A_SUBSYS_MASK		0x1f0000
+#define CMDQ_SUBSYS_MASK		0x1f
+
+#define CMDQ_OP_CODE_SHIFT		24
+#define CMDQ_SUBSYS_SHIFT		16
+
+#define CMDQ_JUMP_BY_OFFSET		0x10000000
+#define CMDQ_JUMP_BY_PA			0x10000001
+#define CMDQ_JUMP_PASS			CMDQ_INST_SIZE
+
+#define CMDQ_WFE_UPDATE			BIT(31)
+#define CMDQ_WFE_WAIT			BIT(15)
+#define CMDQ_WFE_WAIT_VALUE		0x1
+
+#define CMDQ_EOC_IRQ_EN			BIT(0)
+
+#define CMDQ_ENABLE_MASK		BIT(0)
+
+#define CMDQ_OP_CODE_MASK		0xff000000
+
+struct cmdq_command {
+	struct cmdq	*cmdq;
+	u64		engine_flag;
+	void		*base; /* command buffer pointer */
+	size_t		size; /* command buffer size (bytes) */
+};
+
+/*
+ * CMDQ_CODE_MOVE:
+ *   move value into internal register as mask
+ *   format: op mask
+ * CMDQ_CODE_WRITE:
+ *   write value into target register
+ *   format: op subsys address value
+ * CMDQ_CODE_JUMP:
+ *   jump by offset
+ *   format: op offset
+ * CMDQ_CODE_WFE:
+ *   wait for event and clear
+ *   it is just clear if no wait
+ *   format: [wait]  op event update:1 to_wait:1 wait:1
+ *           [clear] op event update:1 to_wait:0 wait:0
+ * CMDQ_CODE_EOC:
+ *   end of command
+ *   format: op irq_flag
+ */
+enum cmdq_code {
+	CMDQ_CODE_MOVE = 0x02,
+	CMDQ_CODE_WRITE = 0x04,
+	CMDQ_CODE_JUMP = 0x10,
+	CMDQ_CODE_WFE = 0x20,
+	CMDQ_CODE_EOC = 0x40,
+};
+
+enum cmdq_task_state {
+	TASK_STATE_IDLE,	/* free task */
+	TASK_STATE_BUSY,	/* task running on a thread */
+	TASK_STATE_ERROR,	/* task execution error */
+	TASK_STATE_DONE,	/* task finished */
+	TASK_STATE_WAITING,	/* allocated but waiting for available thread */
+};
+
+struct cmdq_task_cb {
+	cmdq_async_flush_cb	cb;
+	void			*data;
+};
+
+struct cmdq_thread;
+
+struct cmdq_task {
+	struct cmdq		*cmdq;
+	struct list_head	list_entry;
+	enum cmdq_task_state	task_state;
+	void			*va_base; /* va */
+	dma_addr_t		mva_base; /* pa */
+	u64			engine_flag;
+	size_t			command_size;
+	u32			num_cmd; /* 2 * number of commands */
+	struct cmdq_thread	*thread;
+	struct cmdq_task_cb	cb; /* callback */
+	/* work item when auto release is used */
+	struct work_struct	auto_release_work;
+};
+
+struct cmdq_thread {
+	int			id;
+	void __iomem		*base;
+	u32			task_count;
+	u32			wait_cookie;
+	u32			next_cookie;
+	struct cmdq_task	*cur_task[CMDQ_MAX_TASK_IN_THREAD];
+	wait_queue_head_t	wait_queue; /* wait task done */
+};
+
+struct cmdq {
+	struct device		*dev;
+	void __iomem		*base;
+	u32			irq;
+
+	/*
+	 * task_cache: struct cmdq_task object cache
+	 * task_active_list: active tasks
+	 * task_consume_wait_queue_item: task consuming work
+	 * task_consume_wq: task consuming workqueue
+	 * task_auto_release_wq: auto-release workqueue
+	 */
+	struct kmem_cache	*task_cache;
+	struct list_head	task_active_list;
+	struct list_head	task_wait_list;
+	struct work_struct	task_consume_wait_queue_item;
+	struct workqueue_struct	*task_consume_wq;
+	struct workqueue_struct	*task_auto_release_wq;
+
+	struct cmdq_thread	thread[CMDQ_MAX_THREAD_COUNT];
+	struct mutex		task_mutex;	/* for task list */
+	spinlock_t		exec_lock;	/* for exec task */
+	wait_queue_head_t	thread_dispatch_queue;
+	struct clk		*clock;
+};
+
+struct cmdq_subsys {
+	u32	base_addr;
+	int	id;
+};
+
+static const struct cmdq_subsys g_subsys[] = {
+	{0x1400, 1},
+	{0x1401, 2},
+	{0x1402, 3},
+};
+
+static int cmdq_clk_enable(struct cmdq *cmdq)
+{
+	struct device *dev = cmdq->dev;
+	int err;
+
+	err = clk_prepare_enable(cmdq->clock);
+	if (err < 0) {
+		dev_err(dev, "prepare and enable clk:%s fail\n",
+			CMDQ_CLK_NAME);
+		return err;
+	}
+	return 0;
+}
+
+static void cmdq_clk_disable(struct cmdq *cmdq)
+{
+	clk_disable_unprepare(cmdq->clock);
+}
+
+static int cmdq_subsys_base_addr_to_id(u32 base_addr)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(g_subsys); i++)
+		if (g_subsys[i].base_addr == base_addr)
+			return g_subsys[i].id;
+	return -EFAULT;
+}
+
+static int cmdq_eng_get_thread(u64 flag)
+{
+	if (flag & BIT_ULL(CMDQ_ENG_DISP_DSI0))
+		return 0;
+	else if (flag & BIT_ULL(CMDQ_ENG_DISP_DPI0))
+		return 1;
+	else
+		return 2;
+}
+
+static void cmdq_task_free_command_buffer(struct cmdq_task *task)
+{
+	if (!task->va_base)
+		return;
+
+	dma_free_coherent(task->cmdq->dev, task->command_size, task->va_base,
+			  task->mva_base);
+	task->va_base = NULL;
+	task->mva_base = 0;
+	task->command_size = 0;
+	task->num_cmd = 0;
+}
+
+/* allocate and initialize struct cmdq_task and its command buffer */
+static struct cmdq_task *cmdq_task_create(struct cmdq *cmdq, size_t size)
+{
+	struct device *dev = cmdq->dev;
+	struct cmdq_task *task;
+
+	mutex_lock(&cmdq->task_mutex);
+	task = kmem_cache_zalloc(cmdq->task_cache, GFP_KERNEL);
+	INIT_LIST_HEAD(&task->list_entry);
+	task->task_state = TASK_STATE_IDLE;
+	task->cmdq = cmdq;
+	task->command_size = size;
+	task->va_base = dma_alloc_coherent(dev, size, &task->mva_base,
+					   GFP_KERNEL);
+	if (!task->va_base) {
+		dev_err(dev, "allocate command buffer failed\n");
+		kmem_cache_free(cmdq->task_cache, task);
+		task = NULL;
+	}
+	mutex_unlock(&cmdq->task_mutex);
+	return task;
+}
+
+static void cmdq_task_release_internal(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+
+	mutex_lock(&cmdq->task_mutex);
+	cmdq_task_free_command_buffer(task);
+	list_del(&task->list_entry);
+	kmem_cache_free(cmdq->task_cache, task);
+	mutex_unlock(&cmdq->task_mutex);
+}
+
+/* After dropping error task, we have to reorder remaining valid tasks. */
+static void cmdq_thread_reorder_task_array(struct cmdq_thread *thread,
+					   int prev_id)
+{
+	int to_id, from_id;
+	struct cmdq_task *task;
+	u32 *task_base;
+
+	to_id = (prev_id + 1) % CMDQ_MAX_TASK_IN_THREAD;
+	if (thread->cur_task[to_id])
+		return;
+
+	thread->next_cookie--;
+	from_id = (to_id + 1) % CMDQ_MAX_TASK_IN_THREAD;
+	for (; from_id != prev_id;
+	     from_id = (from_id + 1) % CMDQ_MAX_TASK_IN_THREAD) {
+		if (!thread->cur_task[from_id]) {
+			thread->next_cookie--;
+			continue;
+		}
+		thread->cur_task[to_id] = thread->cur_task[from_id];
+		thread->cur_task[from_id] = NULL;
+		task = thread->cur_task[to_id];
+		task_base = task->va_base;
+		if ((task_base[task->num_cmd - 1] == CMDQ_JUMP_BY_OFFSET) &&
+		    (task_base[task->num_cmd - 2] == CMDQ_JUMP_PASS)) {
+			break; /* reach the last task */
+		}
+		to_id = (to_id + 1) % CMDQ_MAX_TASK_IN_THREAD;
+	}
+}
+
+static struct cmdq_task *cmdq_task_acquire(struct cmdq_command *command,
+					   struct cmdq_task_cb *cb)
+{
+	struct cmdq *cmdq = command->cmdq;
+	struct device *dev = cmdq->dev;
+	struct cmdq_task *task;
+
+	task = cmdq_task_create(cmdq, command->size);
+	if (!task) {
+		dev_err(dev, "can't acquire task info\n");
+		return NULL;
+	}
+	task->engine_flag = command->engine_flag;
+	task->task_state = TASK_STATE_WAITING;
+	if (cb)
+		task->cb = *cb;
+	else
+		memset(&task->cb, 0, sizeof(task->cb));
+
+	/* copy commands */
+	memcpy(task->va_base, command->base, command->size);
+	task->num_cmd = task->command_size / sizeof(u32);
+
+	/* insert into task waiting list */
+	mutex_lock(&cmdq->task_mutex);
+	list_add_tail(&task->list_entry, &cmdq->task_wait_list);
+	mutex_unlock(&cmdq->task_mutex);
+
+	return task;
+}
+
+static void cmdq_thread_writel(struct cmdq_thread *thread, u32 value,
+			       u32 offset)
+{
+	writel(value, thread->base + offset);
+}
+
+static u32 cmdq_thread_readl(struct cmdq_thread *thread, u32 offset)
+{
+	return readl(thread->base + offset);
+}
+
+static u32 cmdq_thread_get_cookie(struct cmdq_thread *thread)
+{
+	return cmdq_thread_readl(thread, CMDQ_THR_EXEC_CNT_OFFSET) &
+				 CMDQ_COOKIE_MASK;
+}
+
+static struct cmdq_thread *cmdq_thread_get(struct cmdq *cmdq, u64 flag)
+{
+	int tid = cmdq_eng_get_thread(flag);
+	struct cmdq_thread *thread = &cmdq->thread[tid];
+	u32 next_cookie;
+
+	next_cookie = thread->next_cookie % CMDQ_MAX_TASK_IN_THREAD;
+	if (thread->cur_task[next_cookie])
+		return NULL;
+	cmdq_clk_enable(cmdq);
+	return thread;
+}
+
+static void cmdq_thread_put(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	if (WARN_ON(thread == NULL))
+		return;
+	cmdq_clk_disable(cmdq);
+}
+
+static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	u32 enabled;
+	u32 status;
+
+	/* write suspend bit */
+	cmdq_thread_writel(thread, CMDQ_THR_SUSPEND,
+			   CMDQ_THR_SUSPEND_TASK_OFFSET);
+
+	/* If already disabled, treat as suspended successful. */
+	enabled = cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK_OFFSET);
+	if (!(enabled & CMDQ_THR_ENABLED))
+		return 0;
+
+	/* poll suspended status */
+	if (readl_poll_timeout_atomic(thread->base +
+				      CMDQ_THR_CURR_STATUS_OFFSET,
+				      status,
+				      status & CMDQ_THR_STATUS_SUSPENDED,
+				      0, 10)) {
+		dev_err(cmdq->dev, "Suspend HW thread 0x%x failed\n",
+			(u32)(thread->base - cmdq->base));
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static void cmdq_thread_resume(struct cmdq_thread *thread)
+{
+	cmdq_thread_writel(thread, CMDQ_THR_RESUME,
+			   CMDQ_THR_SUSPEND_TASK_OFFSET);
+}
+
+static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	void __iomem *gce_base = cmdq->base;
+	u32 warm_reset;
+
+	cmdq_thread_writel(thread, CMDQ_THR_WARM_RESET,
+			   CMDQ_THR_WARM_RESET_OFFSET);
+	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET_OFFSET,
+				      warm_reset,
+				      !(warm_reset & CMDQ_THR_WARM_RESET),
+				      0, 10)) {
+		dev_err(cmdq->dev, "Reset HW thread 0x%x failed\n",
+			(u32)(thread->base - cmdq->base));
+		return -EFAULT;
+	}
+	writel(CMDQ_THR_SLOT_CYCLES, gce_base + CMDQ_THR_SLOT_CYCLES_OFFSET);
+	return 0;
+}
+
+static void cmdq_thread_disable(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	cmdq_thread_reset(cmdq, thread);
+	cmdq_thread_writel(thread, CMDQ_THR_DISABLED,
+			   CMDQ_THR_ENABLE_TASK_OFFSET);
+}
+
+static void cmdq_thread_insert_task_by_cookie(struct cmdq_thread *thread,
+					      struct cmdq_task *task,
+					      int cookie)
+{
+	thread->wait_cookie = cookie;
+	thread->next_cookie = cookie + 1;
+	if (thread->next_cookie > CMDQ_MAX_COOKIE_VALUE)
+		thread->next_cookie = 0;
+	thread->task_count = 1; /* fist task */
+	thread->cur_task[cookie % CMDQ_MAX_TASK_IN_THREAD] = task;
+}
+
+static int cmdq_thread_remove_task_by_index(struct cmdq_thread *thread,
+		int index, enum cmdq_task_state new_state)
+{
+	struct cmdq_task *task;
+
+	task = thread->cur_task[index];
+	if (!task) {
+		pr_err("%s: remove fail, task:%d on thread:0x%p is NULL\n",
+		       __func__, index, thread);
+		return -EINVAL;
+	}
+	task->task_state = new_state;
+	thread->cur_task[index] = NULL;
+	thread->task_count--;
+	return 0;
+}
+
+static struct cmdq_task *cmdq_thread_search_task_by_pc(
+		const struct cmdq_thread *thread, u32 pc)
+{
+	struct cmdq_task *task;
+	int i;
+
+	for (i = 0; i < CMDQ_MAX_TASK_IN_THREAD; i++) {
+		task = thread->cur_task[i];
+		if (task &&
+		    pc >= task->mva_base &&
+		    pc < task->mva_base + task->command_size)
+			break;
+	}
+	return task;
+}
+
+/* notify GCE to re-fetch commands by setting HW thread PC */
+static void cmdq_thread_invalidate_fetched_data(struct cmdq_thread *thread)
+{
+	cmdq_thread_writel(thread,
+			   cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR_OFFSET),
+			   CMDQ_THR_CURR_ADDR_OFFSET);
+}
+
+static int cmdq_task_insert_into_thread(struct cmdq_task *task)
+{
+	struct cmdq_thread *thread = task->thread;
+	struct cmdq_task *prev_task;
+	int prev, curr;
+	u32 *prev_task_base;
+
+	/* find previous task */
+	curr = thread->next_cookie % CMDQ_MAX_TASK_IN_THREAD;
+	prev = (curr + CMDQ_MAX_TASK_IN_THREAD - 1) % CMDQ_MAX_TASK_IN_THREAD;
+	prev_task = thread->cur_task[prev];
+
+	/* cmdq_thread_reorder_task_array() should prevent this error */
+	if (WARN_ON(prev_task == NULL))
+		return -EFAULT;
+
+	/* insert task, and let previous task jump to this task */
+	thread->cur_task[curr] = task;
+	prev_task_base = prev_task->va_base;
+	prev_task_base[prev_task->num_cmd - 1] = CMDQ_JUMP_BY_PA;
+	prev_task_base[prev_task->num_cmd - 2] = task->mva_base;
+
+	/* re-fetch command buffer */
+	cmdq_thread_invalidate_fetched_data(thread);
+
+	return 0;
+}
+
+/* we assume tasks in the same display thread are waiting the same event. */
+static void cmdq_task_remove_wfe(struct cmdq_task *task)
+{
+	u32 wfe_option = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
+	u32 wfe_op = CMDQ_CODE_WFE << CMDQ_OP_CODE_SHIFT;
+	u32 *base = task->va_base;
+	int i;
+
+	for (i = 0; i < task->num_cmd; i += 2) {
+		if (base[i] == wfe_option &&
+		    (base[i + 1] & CMDQ_OP_CODE_MASK) == wfe_op) {
+			base[i] = CMDQ_JUMP_PASS;
+			base[i + 1] = CMDQ_JUMP_BY_OFFSET;
+		}
+	}
+}
+
+static int cmdq_task_exec_async(struct cmdq_task *task,
+				struct cmdq_thread *thread)
+{
+	struct cmdq *cmdq = task->cmdq;
+	struct device *dev = cmdq->dev;
+	unsigned long flags;
+	int minimum;
+	int cookie;
+
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+	task->thread = thread;
+	task->task_state = TASK_STATE_BUSY;
+	if (thread->task_count <= 0) {
+		if (WARN_ON(cmdq_thread_reset(cmdq, thread) < 0)) {
+			spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+			return -EFAULT;
+		}
+
+		cmdq_thread_writel(thread, CMDQ_THR_NO_TIMEOUT,
+				   CMDQ_THR_INST_CYCLES_OFFSET);
+		cmdq_thread_writel(thread, task->mva_base,
+				   CMDQ_THR_CURR_ADDR_OFFSET);
+		cmdq_thread_writel(thread, task->mva_base + task->command_size,
+				   CMDQ_THR_END_ADDR_OFFSET);
+		cmdq_thread_writel(thread, CMDQ_THR_PRIORITY,
+				   CMDQ_THR_CFG_OFFSET);
+		cmdq_thread_writel(thread, CMDQ_THR_IRQ_EN,
+				   CMDQ_THR_IRQ_ENABLE_OFFSET);
+
+		minimum = cmdq_thread_get_cookie(thread);
+		cmdq_thread_insert_task_by_cookie(
+				thread, task, (minimum + 1));
+
+		/* enable HW thread */
+		cmdq_thread_writel(thread, CMDQ_THR_ENABLED,
+				   CMDQ_THR_ENABLE_TASK_OFFSET);
+	} else {
+		unsigned long curr_pa, end_pa;
+		int err;
+
+		err = cmdq_thread_suspend(cmdq, thread);
+		if (WARN_ON(err < 0)) {
+			spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+			return err;
+		}
+
+		cmdq_thread_writel(thread, CMDQ_THR_NO_TIMEOUT,
+				   CMDQ_THR_INST_CYCLES_OFFSET);
+		cookie = thread->next_cookie;
+
+		/*
+		 * check boundary condition
+		 * PC = END - 8, EOC is executed
+		 * PC = END - 0, all CMDs are executed
+		 */
+		curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR_OFFSET);
+		end_pa = cmdq_thread_readl(thread, CMDQ_THR_END_ADDR_OFFSET);
+		if ((curr_pa == end_pa - 8) || (curr_pa == end_pa - 0)) {
+			/* set to task directly */
+			cmdq_thread_writel(thread, task->mva_base,
+					   CMDQ_THR_CURR_ADDR_OFFSET);
+			cmdq_thread_writel(thread,
+					   task->mva_base + task->command_size,
+					   CMDQ_THR_END_ADDR_OFFSET);
+			thread->cur_task[cookie % CMDQ_MAX_TASK_IN_THREAD] =
+					task;
+			thread->task_count++;
+		} else {
+			err = cmdq_task_insert_into_thread(task);
+			if (err < 0) {
+				cmdq_thread_resume(thread);
+				spin_unlock_irqrestore(
+						&cmdq->exec_lock, flags);
+				dev_err(dev, "insert task failed\n");
+				return err;
+			}
+
+			if (thread == &cmdq->thread[0] ||
+			    thread == &cmdq->thread[1])
+				cmdq_task_remove_wfe(task);
+
+			smp_mb(); /* modify jump before enable thread */
+			cmdq_thread_writel(thread,
+					   task->mva_base + task->command_size,
+					   CMDQ_THR_END_ADDR_OFFSET);
+			thread->task_count++;
+		}
+
+		thread->next_cookie = (thread->next_cookie + 1) %
+				      CMDQ_MAX_COOKIE_VALUE;
+		cmdq_thread_resume(thread);
+	}
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+	return 0;
+}
+
+static void cmdq_handle_done(struct cmdq *cmdq, struct cmdq_thread *thread,
+			     int cookie)
+{
+	int i, new_wait_cookie;
+	struct cmdq_task *task;
+	struct cmdq_cb_data cmdq_cb_data;
+
+	new_wait_cookie = (cookie + 1) % (CMDQ_MAX_COOKIE_VALUE + 1);
+	for (i = thread->wait_cookie % CMDQ_MAX_TASK_IN_THREAD;
+	     i != new_wait_cookie % CMDQ_MAX_TASK_IN_THREAD;
+	     i = (i + 1) % CMDQ_MAX_TASK_IN_THREAD) {
+		if (thread->cur_task[i]) {
+			task = thread->cur_task[i];
+			if (task->cb.cb) {
+				cmdq_cb_data.err = false;
+				cmdq_cb_data.data = task->cb.data;
+				task->cb.cb(cmdq_cb_data);
+			}
+			cmdq_thread_remove_task_by_index(
+					thread, i, TASK_STATE_DONE);
+		}
+	}
+	thread->wait_cookie = new_wait_cookie;
+	wake_up(&thread->wait_queue);
+}
+
+static void cmdq_handle_error(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	struct device *dev = cmdq->dev;
+	u32 curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR_OFFSET);
+	u32 end_pa = cmdq_thread_readl(thread, CMDQ_THR_END_ADDR_OFFSET);
+	int cookie = cmdq_thread_get_cookie(thread);
+
+	dev_err(dev, "IRQ: error thread=0x%x\n",
+		(u32)(thread->base - cmdq->base));
+	dev_err(dev, "IRQ: Thread PC: 0x%08x, End PC:0x%08x\n",
+		curr_pa, end_pa);
+
+	/*
+	 * We assume error happens BEFORE EOC
+	 * because it wouldn't be error if this interrupt is issued by EOC.
+	 * So, we should add 1 to locate "current" task.
+	 */
+	cookie++;
+
+	/* set the issued task to error state */
+	if (thread->cur_task[cookie % CMDQ_MAX_TASK_IN_THREAD]) {
+		struct cmdq_task *task;
+		struct cmdq_cb_data cmdq_cb_data;
+
+		task = thread->cur_task[cookie % CMDQ_MAX_TASK_IN_THREAD];
+		/* still call cb to prevent lock */
+		if (task->cb.cb) {
+			cmdq_cb_data.err = true;
+			cmdq_cb_data.data = task->cb.data;
+			task->cb.cb(cmdq_cb_data);
+		}
+		cmdq_thread_remove_task_by_index(
+				thread, cookie % CMDQ_MAX_TASK_IN_THREAD,
+				TASK_STATE_ERROR);
+	} else {
+		dev_err(dev,
+			"IRQ: can not find task in %s, pc:0x%08x, end_pc:0x%08x\n",
+			__func__, curr_pa, end_pa);
+		if (thread->task_count <= 0) {
+			/*
+			 * suspend HW thread first,
+			 * so that we work in a consistent state
+			 * outer function should acquire spinlock:
+			 *   cmdq->exec_lock
+			 */
+			if (cmdq_thread_suspend(cmdq, thread) < 0)
+				dev_err(dev, "IRQ: suspend HW thread failed!");
+
+			cmdq_thread_disable(cmdq, thread);
+			dev_err(dev,
+				"IRQ: there is no task for thread (0x%x)\n",
+				(u32)(thread->base - cmdq->base));
+		}
+	}
+
+	/* set the remained tasks to done state */
+	cmdq_handle_done(cmdq, thread, cookie);
+}
+
+static void cmdq_handle_irq(struct cmdq *cmdq, int tid)
+{
+	struct device *dev = cmdq->dev;
+	struct cmdq_thread *thread = &cmdq->thread[tid];
+	unsigned long flags = 0L;
+	int value;
+	int enabled;
+
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+
+	/*
+	 * it is possible for another CPU core
+	 * to run "release task" right before we acquire the spin lock
+	 * and thus reset / disable this HW thread
+	 * so we check both the IRQ flag and the enable bit of this thread
+	 */
+	value = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS_OFFSET);
+	if (!(value & CMDQ_THR_IRQ_MASK)) {
+		dev_err(dev,
+			"IRQ: thread 0x%x got interrupt but IRQ flag=0x%x\n",
+			(u32)(thread->base - cmdq->base), value);
+		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+		return;
+	}
+
+	enabled = cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK_OFFSET);
+	if (!(enabled & CMDQ_THR_ENABLED)) {
+		dev_err(dev,
+			"IRQ: thread 0x%x got interrupt but enabled=0x%x\n",
+			(u32)(thread->base - cmdq->base), enabled);
+		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+		return;
+	}
+
+	/*
+	 * Move the reset IRQ before read HW cookie
+	 * to prevent race condition and save the cost of suspend
+	 */
+	cmdq_thread_writel(thread, ~value, CMDQ_THR_IRQ_STATUS_OFFSET);
+
+	if (value & CMDQ_THR_IRQ_ERROR)
+		cmdq_handle_error(cmdq, thread);
+	else if (value & CMDQ_THR_IRQ_DONE)
+		cmdq_handle_done(cmdq, thread, cmdq_thread_get_cookie(thread));
+
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+}
+
+static void cmdq_consume_waiting_list(struct work_struct *work)
+{
+	struct cmdq *cmdq = container_of(work, struct cmdq,
+					 task_consume_wait_queue_item);
+	struct device *dev = cmdq->dev;
+	struct cmdq_task *task, *tmp;
+
+	mutex_lock(&cmdq->task_mutex);
+
+	if (list_empty(&cmdq->task_wait_list)) {
+		mutex_unlock(&cmdq->task_mutex);
+		return;
+	}
+
+	list_for_each_entry_safe(task, tmp, &cmdq->task_wait_list, list_entry) {
+		struct cmdq_thread *thread = NULL;
+		int err;
+
+		thread = cmdq_thread_get(cmdq, task->engine_flag);
+		if (!thread) {
+			dev_warn(dev, "acquire thread fail. wait\n");
+			continue;
+		}
+		err = cmdq_task_exec_async(task, thread);
+		if (err < 0) {
+			dev_warn(dev, "start task fail. wait\n");
+			continue;
+		} else {
+			list_move_tail(&task->list_entry,
+				       &cmdq->task_active_list);
+		}
+	}
+
+	/*
+	 * Wake up waiting task(s) whether success or not
+	 * because wake up condition will check task's thread.
+	 * (cmdq_task_wait_and_release)
+	 */
+	wake_up_all(&cmdq->thread_dispatch_queue);
+
+	mutex_unlock(&cmdq->task_mutex);
+}
+
+static int cmdq_task_submit_async(struct cmdq_command *command,
+				  struct cmdq_task **task_out,
+				  struct cmdq_task_cb *cb)
+{
+	struct cmdq *cmdq = command->cmdq;
+
+	/* creates a new task and put into tail of waiting list */
+	*task_out = cmdq_task_acquire(command, cb);
+	if (!(*task_out))
+		return -EFAULT;
+	/* Do consumption here to gain some time if HW thread is available. */
+	cmdq_consume_waiting_list(&cmdq->task_consume_wait_queue_item);
+	return 0;
+}
+
+static int cmdq_task_handle_error_result(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+	struct device *dev = cmdq->dev;
+	struct cmdq_thread *thread = task->thread;
+	int err, i, cookie;
+	struct cmdq_task *next_task;
+	unsigned long thread_pc;
+	u32 *prev_va, *curr_va;
+	u32 irq_flag;
+
+	dev_err(dev,
+		"task(0x%p) state is not TASK_STATE_DONE, but %d.\n",
+		task, task->task_state);
+
+	/* suspend HW thread to ensure consistency */
+	err = cmdq_thread_suspend(cmdq, thread);
+	if (WARN_ON(err < 0))
+		return err;
+
+	/* The cookie of the task currently being processed */
+	cookie = cmdq_thread_get_cookie(thread) + 1;
+	thread_pc = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR_OFFSET);
+
+	/*
+	 * Although IRQ is disabled, GCE continues to execute.
+	 * It may have pending IRQ before HW thread is suspended,
+	 * so check this condition again.
+	 */
+	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS_OFFSET);
+	if (irq_flag & CMDQ_THR_IRQ_ERROR)
+		cmdq_handle_error(cmdq, thread);
+	else if (irq_flag & CMDQ_THR_IRQ_DONE)
+		cmdq_handle_done(cmdq, thread, cmdq_thread_get_cookie(thread));
+	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS_OFFSET);
+
+	if (task->task_state == TASK_STATE_DONE)
+		return 0; /* success after handling pending irq */
+
+	dev_err(dev, "task 0x%p timeout or killed\n", task);
+
+	/* If task is running, force to remove it. */
+	if (task->task_state == TASK_STATE_BUSY) {
+		for (i = 0; i < ARRAY_SIZE(thread->cur_task); i++) {
+			if (thread->cur_task[i] == task) {
+				cmdq_thread_remove_task_by_index(
+						thread, i, TASK_STATE_ERROR);
+				break;
+			}
+		}
+	}
+
+	/* find task's jump destination or no next task*/
+	next_task = NULL;
+	curr_va = task->va_base;
+	if (curr_va[task->num_cmd - 1] == CMDQ_JUMP_BY_PA)
+		next_task = cmdq_thread_search_task_by_pc(
+				thread, curr_va[task->num_cmd - 2]);
+
+	/* remove task from the chain of thread->cur_task. */
+	if (task->num_cmd && thread_pc >= task->mva_base &&
+	    thread_pc < (task->mva_base + task->command_size)) {
+		if (next_task) {
+			/* cookie already +1 */
+			cmdq_thread_writel(thread, cookie,
+					   CMDQ_THR_EXEC_CNT_OFFSET);
+			thread->wait_cookie = cookie + 1;
+			cmdq_thread_writel(thread, next_task->mva_base,
+					   CMDQ_THR_CURR_ADDR_OFFSET);
+		}
+	} else {
+		for (i = 0; i < CMDQ_MAX_TASK_IN_THREAD; i++) {
+			struct cmdq_task *prev_task;
+			u32 prev_num, curr_num;
+
+			prev_task = thread->cur_task[i];
+			if (!prev_task)
+				continue;
+
+			prev_va = prev_task->va_base;
+			prev_num = prev_task->num_cmd;
+
+			curr_va = task->va_base;
+			curr_num = task->num_cmd;
+
+			/* find which task JUMP into task */
+			if (prev_va[prev_num - 2] == task->mva_base &&
+			    prev_va[prev_num - 1] == CMDQ_JUMP_BY_PA) {
+				/* copy JUMP instruction */
+				prev_va[prev_num - 2] = curr_va[curr_num - 2];
+				prev_va[prev_num - 1] = curr_va[curr_num - 1];
+				/* reorder task array to prevent empty slot */
+				if (next_task)
+					cmdq_thread_reorder_task_array(
+							thread, i);
+				/* re-fetch command */
+				cmdq_thread_invalidate_fetched_data(thread);
+				break;
+			}
+		}
+	}
+	return -ECANCELED;
+}
+
+static int cmdq_task_wait_result(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+	struct cmdq_thread *thread = task->thread;
+	int err = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+	if (task->task_state != TASK_STATE_DONE)
+		err = cmdq_task_handle_error_result(task);
+	if (thread->task_count <= 0)
+		cmdq_thread_disable(cmdq, thread);
+	else
+		cmdq_thread_resume(thread);
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+	return err;
+}
+
+static int cmdq_task_wait_done(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+	struct device *dev = cmdq->dev;
+	int wait_q;
+	unsigned long timeout = msecs_to_jiffies(
+			CMDQ_ACQUIRE_THREAD_TIMEOUT_MS);
+
+	/* wait for acquiring thread (cmdq_consume_waiting_list) */
+	wait_q = wait_event_timeout(
+			cmdq->thread_dispatch_queue,
+			task->thread, timeout);
+	if (!wait_q) {
+		mutex_lock(&cmdq->task_mutex);
+		/* Check if task was just consumed. */
+		if (!task->thread) {
+			dev_err(dev,
+				"task(0x%p) timeout with invalid thread\n",
+				task);
+			/*
+			 * Remove from waiting list,
+			 * so it won't be consumed in the future.
+			 */
+			list_del_init(&task->list_entry);
+			mutex_unlock(&cmdq->task_mutex);
+			return -EINVAL;
+		}
+		/* valid thread, so we keep going */
+		mutex_unlock(&cmdq->task_mutex);
+	}
+
+	/* wait for execution */
+	wait_q = wait_event_timeout(task->thread->wait_queue,
+				    (task->task_state != TASK_STATE_BUSY &&
+				     task->task_state != TASK_STATE_WAITING),
+				    msecs_to_jiffies(CMDQ_DEFAULT_TIMEOUT_MS));
+	if (!wait_q)
+		dev_dbg(dev, "timeout!\n");
+
+	/* wake up and continue */
+	return cmdq_task_wait_result(task);
+}
+
+static int cmdq_task_wait_and_release(struct cmdq_task *task)
+{
+	int err = cmdq_task_wait_done(task);
+
+	/* release regardless of success or not */
+	cmdq_thread_put(task->cmdq, task->thread);
+	cmdq_task_release_internal(task);
+	return err;
+}
+
+static void cmdq_auto_release(struct work_struct *work_item)
+{
+	struct cmdq_task *task = container_of(work_item, struct cmdq_task,
+					      auto_release_work);
+	struct cmdq *cmdq = task->cmdq;
+	struct cmdq_task_cb cb = task->cb;
+	int err = cmdq_task_wait_and_release(task);
+	struct cmdq_cb_data cmdq_cb_data;
+
+	/* isr fail, so call cb here to prevent lock */
+	if (err < 0 && cb.cb) {
+		cmdq_cb_data.err = true;
+		cmdq_cb_data.data = cb.data;
+		cb.cb(cmdq_cb_data);
+	}
+
+	/* prevent no more flush or interrupt to consume waiting tasks */
+	if (err < 0)
+		queue_work(cmdq->task_consume_wq,
+			   &cmdq->task_consume_wait_queue_item);
+}
+
+static void cmdq_task_auto_release(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+
+	/*
+	 * the work item is embeded in task already
+	 * but we need to initialized it
+	 */
+	INIT_WORK(&task->auto_release_work, cmdq_auto_release);
+	queue_work(cmdq->task_auto_release_wq, &task->auto_release_work);
+}
+
+static int cmdq_task_submit(struct cmdq_command *command)
+{
+	struct device *dev = command->cmdq->dev;
+	int err;
+	struct cmdq_task *task;
+
+	err = cmdq_task_submit_async(command, &task, NULL);
+	if (err < 0) {
+		dev_err(dev, "cmdq_task_submit_async failed=%d\n", err);
+		return err;
+	}
+	err = cmdq_task_wait_and_release(task);
+	if (err < 0)
+		dev_err(dev, "task(0x%p) wait fail\n", task);
+	return err;
+}
+
+static int cmdq_remove(struct platform_device *pdev)
+{
+	struct cmdq *cmdq = platform_get_drvdata(pdev);
+	struct cmdq_task *task, *tmp;
+
+	/* Destroy work queue safely, so task_active_list must be empty. */
+	destroy_workqueue(cmdq->task_consume_wq);
+	cmdq->task_consume_wq = NULL;
+	destroy_workqueue(cmdq->task_auto_release_wq);
+	cmdq->task_auto_release_wq = NULL;
+
+	/* release task_wait_list */
+	list_for_each_entry_safe(task, tmp, &cmdq->task_wait_list, list_entry) {
+		cmdq_task_free_command_buffer(task);
+		list_del(&task->list_entry);
+		kmem_cache_free(cmdq->task_cache, task);
+	}
+
+	kmem_cache_destroy(cmdq->task_cache);
+	cmdq->task_cache = NULL;
+	return 0;
+}
+
+static irqreturn_t cmdq_irq_handler(int irq, void *dev)
+{
+	struct cmdq *cmdq = dev;
+	u32 irq_status;
+	int i;
+
+	irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS_OFFSET);
+	irq_status &= CMDQ_IRQ_MASK;
+	irq_status ^= CMDQ_IRQ_MASK;
+
+	if (!irq_status)
+		return IRQ_NONE;
+
+	while (irq_status) {
+		i = ffs(irq_status) - 1;
+		irq_status &= ~BIT(i);
+		cmdq_handle_irq(cmdq, i);
+	}
+
+	queue_work(cmdq->task_consume_wq, &cmdq->task_consume_wait_queue_item);
+	return IRQ_HANDLED;
+}
+
+static int cmdq_initialize(struct cmdq *cmdq)
+{
+	int i;
+
+	mutex_init(&cmdq->task_mutex);
+	spin_lock_init(&cmdq->exec_lock);
+	init_waitqueue_head(&cmdq->thread_dispatch_queue);
+	cmdq->task_cache = kmem_cache_create(
+			CMDQ_DRIVER_DEVICE_NAME "_task",
+			sizeof(struct cmdq_task), __alignof__(struct cmdq_task),
+			SLAB_POISON | SLAB_HWCACHE_ALIGN | SLAB_RED_ZONE, NULL);
+	INIT_LIST_HEAD(&cmdq->task_active_list);
+	INIT_LIST_HEAD(&cmdq->task_wait_list);
+	INIT_WORK(&cmdq->task_consume_wait_queue_item,
+		  cmdq_consume_waiting_list);
+	cmdq->task_auto_release_wq = alloc_ordered_workqueue(
+			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI, "cmdq_auto_release");
+	cmdq->task_consume_wq = alloc_ordered_workqueue(
+			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI, "cmdq_task");
+
+	/* initialize cmdq thread */
+	for (i = 0; i < ARRAY_SIZE(cmdq->thread) ; i++) {
+		cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
+				CMDQ_THR_SHIFT * i;
+		init_waitqueue_head(&cmdq->thread[i].wait_queue);
+	}
+
+	return 0;
+}
+
+static int cmdq_rec_realloc_cmd_buffer(struct cmdq_rec *rec, size_t size)
+{
+	void *new_buf = krealloc(rec->buf, size, GFP_KERNEL | __GFP_ZERO);
+
+	if (!new_buf)
+		return -ENOMEM;
+	rec->buf = new_buf;
+	rec->buf_size = size;
+	return 0;
+}
+
+struct cmdq_base *cmdq_register_device(struct device *dev)
+{
+	struct cmdq_base *cmdq_base;
+	struct resource res;
+	int subsys;
+	u32 base;
+
+	if (of_address_to_resource(dev->of_node, 0, &res))
+		return NULL;
+	base = (u32)res.start;
+
+	subsys = cmdq_subsys_base_addr_to_id(base >> 16);
+	if (subsys < 0)
+		return NULL;
+
+	cmdq_base = devm_kmalloc(dev, sizeof(*cmdq_base), GFP_KERNEL);
+	if (!cmdq_base)
+		return NULL;
+	cmdq_base->subsys = subsys;
+	cmdq_base->base = base;
+
+	return cmdq_base;
+}
+EXPORT_SYMBOL(cmdq_register_device);
+
+int cmdq_rec_create(struct device *dev, u64 engine_flag,
+		    struct cmdq_rec **rec_ptr)
+{
+	struct cmdq_rec *rec;
+	int err;
+
+	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
+	if (!rec)
+		return -ENOMEM;
+	rec->cmdq = dev_get_drvdata(dev);
+	rec->engine_flag = engine_flag;
+	err = cmdq_rec_realloc_cmd_buffer(rec, CMDQ_INITIAL_CMD_BLOCK_SIZE);
+	if (err < 0) {
+		kfree(rec);
+		return err;
+	}
+	*rec_ptr = rec;
+	return 0;
+}
+EXPORT_SYMBOL(cmdq_rec_create);
+
+static int cmdq_rec_append_command(struct cmdq_rec *rec, enum cmdq_code code,
+				   u32 arg_a, u32 arg_b)
+{
+	u32 *cmd_ptr;
+	int err;
+
+	if (WARN_ON(rec->finalized))
+		return -EBUSY;
+	if (code < CMDQ_CODE_MOVE || code > CMDQ_CODE_EOC)
+		return -EINVAL;
+	if (unlikely(rec->command_size + CMDQ_INST_SIZE > rec->buf_size)) {
+		err = cmdq_rec_realloc_cmd_buffer(rec, rec->buf_size * 2);
+		if (err < 0)
+			return err;
+	}
+	cmd_ptr = (u32 *)(rec->buf + rec->command_size);
+	cmd_ptr[0] = arg_b;
+	cmd_ptr[1] = (code << CMDQ_OP_CODE_SHIFT) | arg_a;
+	rec->command_size += CMDQ_INST_SIZE;
+	return 0;
+}
+
+int cmdq_rec_write(struct cmdq_rec *rec, u32 value, struct cmdq_base *base,
+		   u32 offset)
+{
+	u32 arg_a = ((base->base + offset) & CMDQ_ARG_A_WRITE_MASK) |
+		    ((base->subsys & CMDQ_SUBSYS_MASK) << CMDQ_SUBSYS_SHIFT);
+
+	return cmdq_rec_append_command(rec, CMDQ_CODE_WRITE, arg_a, value);
+}
+EXPORT_SYMBOL(cmdq_rec_write);
+
+int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
+			struct cmdq_base *base, u32 offset, u32 mask)
+{
+	u32 offset_mask = offset;
+	int err;
+
+	if (mask != 0xffffffff) {
+		err = cmdq_rec_append_command(rec, CMDQ_CODE_MOVE, 0, ~mask);
+		if (err < 0)
+			return err;
+		offset_mask |= CMDQ_ENABLE_MASK;
+	}
+	return cmdq_rec_write(rec, value, base, offset_mask);
+}
+EXPORT_SYMBOL(cmdq_rec_write_mask);
+
+int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event)
+{
+	u32 arg_b;
+
+	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
+		return -EINVAL;
+
+	/*
+	 * bit 0-11: wait value
+	 * bit 15: 1 - wait, 0 - no wait
+	 * bit 16-27: update value
+	 * bit 31: 1 - update, 0 - no update
+	 */
+	arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
+	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event, arg_b);
+}
+EXPORT_SYMBOL(cmdq_rec_wfe);
+
+int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event)
+{
+	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
+		return -EINVAL;
+
+	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event,
+				       CMDQ_WFE_UPDATE);
+}
+EXPORT_SYMBOL(cmdq_rec_clear_event);
+
+static int cmdq_rec_fill_command(struct cmdq_rec *rec,
+				 struct cmdq_command *command)
+{
+	if (!rec->finalized) {
+		int err;
+
+		/* insert EOC and generate IRQ for each command iteration */
+		err = cmdq_rec_append_command(rec, CMDQ_CODE_EOC, 0,
+					      CMDQ_EOC_IRQ_EN);
+		if (err < 0)
+			return err;
+
+		/* JUMP to end */
+		err = cmdq_rec_append_command(rec, CMDQ_CODE_JUMP, 0,
+					      CMDQ_JUMP_PASS);
+		if (err < 0)
+			return err;
+
+		rec->finalized = true;
+	}
+
+	command->cmdq = rec->cmdq;
+	command->engine_flag = rec->engine_flag;
+	command->base = rec->buf;
+	command->size = rec->command_size;
+	return 0;
+}
+
+int cmdq_rec_flush(struct cmdq_rec *rec)
+{
+	int err;
+	struct cmdq_command command;
+
+	err = cmdq_rec_fill_command(rec, &command);
+	if (err < 0)
+		return err;
+	return cmdq_task_submit(&command);
+}
+EXPORT_SYMBOL(cmdq_rec_flush);
+
+int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
+			 void *data)
+{
+	int err;
+	struct cmdq_command command;
+	struct cmdq_task *task;
+	struct cmdq_task_cb task_cb;
+
+	err = cmdq_rec_fill_command(rec, &command);
+	if (err < 0)
+		return err;
+	task_cb.cb = cb;
+	task_cb.data = data;
+	err = cmdq_task_submit_async(&command, &task, &task_cb);
+	if (err < 0)
+		return err;
+	cmdq_task_auto_release(task);
+	return 0;
+}
+EXPORT_SYMBOL(cmdq_rec_flush_async);
+
+void cmdq_rec_destroy(struct cmdq_rec *rec)
+{
+	kfree(rec->buf);
+	kfree(rec);
+}
+EXPORT_SYMBOL(cmdq_rec_destroy);
+
+static int cmdq_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct resource *res;
+	struct cmdq *cmdq;
+	int err;
+
+	cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
+	if (!cmdq)
+		return -ENOMEM;
+	cmdq->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	cmdq->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(cmdq->base)) {
+		dev_err(dev, "failed to ioremap gce\n");
+		return PTR_ERR(cmdq->base);
+	}
+
+	cmdq->irq = irq_of_parse_and_map(node, 0);
+	if (!cmdq->irq) {
+		dev_err(dev, "failed to get irq\n");
+		return -EINVAL;
+	}
+
+	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
+		dev, cmdq->base, cmdq->irq);
+
+	/* init cmdq and save to device private data */
+	err = cmdq_initialize(cmdq);
+	if (err < 0) {
+		dev_err(dev, "failed to init cmdq\n");
+		return err;
+	}
+	platform_set_drvdata(pdev, cmdq);
+
+	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
+			       CMDQ_DRIVER_DEVICE_NAME, cmdq);
+	if (err < 0) {
+		dev_err(dev, "failed to register ISR (%d)\n", err);
+		goto fail;
+	}
+
+	cmdq->clock = devm_clk_get(dev, CMDQ_CLK_NAME);
+	if (IS_ERR(cmdq->clock)) {
+		dev_err(dev, "failed to get clk:%s\n", CMDQ_CLK_NAME);
+		err = PTR_ERR(cmdq->clock);
+		goto fail;
+	}
+	return 0;
+fail:
+	cmdq_remove(pdev);
+	return err;
+}
+
+static const struct of_device_id cmdq_of_ids[] = {
+	{.compatible = "mediatek,mt8173-gce",},
+	{}
+};
+
+static struct platform_driver cmdq_drv = {
+	.probe = cmdq_probe,
+	.remove = cmdq_remove,
+	.driver = {
+		.name = CMDQ_DRIVER_DEVICE_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = cmdq_of_ids,
+	}
+};
+
+builtin_platform_driver(cmdq_drv);
diff --git a/include/soc/mediatek/cmdq.h b/include/soc/mediatek/cmdq.h
new file mode 100644
index 0000000..60eef3d
--- /dev/null
+++ b/include/soc/mediatek/cmdq.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_CMDQ_H__
+#define __MTK_CMDQ_H__
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+enum cmdq_eng {
+	CMDQ_ENG_DISP_AAL,
+	CMDQ_ENG_DISP_COLOR0,
+	CMDQ_ENG_DISP_COLOR1,
+	CMDQ_ENG_DISP_DPI0,
+	CMDQ_ENG_DISP_DSI0,
+	CMDQ_ENG_DISP_DSI1,
+	CMDQ_ENG_DISP_GAMMA,
+	CMDQ_ENG_DISP_OD,
+	CMDQ_ENG_DISP_OVL0,
+	CMDQ_ENG_DISP_OVL1,
+	CMDQ_ENG_DISP_PWM0,
+	CMDQ_ENG_DISP_PWM1,
+	CMDQ_ENG_DISP_RDMA0,
+	CMDQ_ENG_DISP_RDMA1,
+	CMDQ_ENG_DISP_RDMA2,
+	CMDQ_ENG_DISP_UFOE,
+	CMDQ_ENG_DISP_WDMA0,
+	CMDQ_ENG_DISP_WDMA1,
+	CMDQ_ENG_MAX,
+};
+
+/* events for CMDQ and display */
+enum cmdq_event {
+	/* Display start of frame(SOF) events */
+	CMDQ_EVENT_DISP_OVL0_SOF = 11,
+	CMDQ_EVENT_DISP_OVL1_SOF = 12,
+	CMDQ_EVENT_DISP_RDMA0_SOF = 13,
+	CMDQ_EVENT_DISP_RDMA1_SOF = 14,
+	CMDQ_EVENT_DISP_RDMA2_SOF = 15,
+	CMDQ_EVENT_DISP_WDMA0_SOF = 16,
+	CMDQ_EVENT_DISP_WDMA1_SOF = 17,
+	/* Display end of frame(EOF) events */
+	CMDQ_EVENT_DISP_OVL0_EOF = 39,
+	CMDQ_EVENT_DISP_OVL1_EOF = 40,
+	CMDQ_EVENT_DISP_RDMA0_EOF = 41,
+	CMDQ_EVENT_DISP_RDMA1_EOF = 42,
+	CMDQ_EVENT_DISP_RDMA2_EOF = 43,
+	CMDQ_EVENT_DISP_WDMA0_EOF = 44,
+	CMDQ_EVENT_DISP_WDMA1_EOF = 45,
+	/* Mutex end of frame(EOF) events */
+	CMDQ_EVENT_MUTEX0_STREAM_EOF = 53,
+	CMDQ_EVENT_MUTEX1_STREAM_EOF = 54,
+	CMDQ_EVENT_MUTEX2_STREAM_EOF = 55,
+	CMDQ_EVENT_MUTEX3_STREAM_EOF = 56,
+	CMDQ_EVENT_MUTEX4_STREAM_EOF = 57,
+	/* Display underrun events */
+	CMDQ_EVENT_DISP_RDMA0_UNDERRUN = 63,
+	CMDQ_EVENT_DISP_RDMA1_UNDERRUN = 64,
+	CMDQ_EVENT_DISP_RDMA2_UNDERRUN = 65,
+	/* Keep this at the end of HW events */
+	CMDQ_MAX_HW_EVENT_COUNT = 260,
+};
+
+struct cmdq_cb_data {
+	bool	err;
+	void	*data;
+};
+
+typedef int (*cmdq_async_flush_cb)(struct cmdq_cb_data data);
+
+struct cmdq_task;
+struct cmdq;
+
+struct cmdq_rec {
+	struct cmdq		*cmdq;
+	u64			engine_flag;
+	size_t			command_size;
+	void			*buf;
+	size_t			buf_size;
+	bool			finalized;
+};
+
+struct cmdq_base {
+	int	subsys;
+	u32	base;
+};
+
+/**
+ * cmdq_register_device() - register device which needs CMDQ
+ * @dev:		device
+ *
+ * Return: cmdq_base pointer or NULL for failed
+ */
+struct cmdq_base *cmdq_register_device(struct device *dev);
+
+/**
+ * cmdq_rec_create() - create command queue record
+ * @dev:		device
+ * @engine_flag:	command queue engine flag
+ * @rec_ptr:		command queue record pointer to retrieve cmdq_rec
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_create(struct device *dev, u64 engine_flag,
+		    struct cmdq_rec **rec_ptr);
+
+/**
+ * cmdq_rec_write() - append write command to the command queue record
+ * @rec:	the command queue record
+ * @value:	the specified target register value
+ * @base:	the command queue base
+ * @offset:	register offset from module base
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_write(struct cmdq_rec *rec, u32 value,
+		   struct cmdq_base *base, u32 offset);
+
+/**
+ * cmdq_rec_write_mask() - append write command with mask to the command
+ *			   queue record
+ * @rec:	the command queue record
+ * @value:	the specified target register value
+ * @base:	the command queue base
+ * @offset:	register offset from module base
+ * @mask:	the specified target register mask
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
+			struct cmdq_base *base, u32 offset, u32 mask);
+
+/**
+ * cmdq_rec_wfe() - append wait for event command to the command queue record
+ * @rec:	the command queue record
+ * @event:	the desired event type to "wait and CLEAR"
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event);
+
+/**
+ * cmdq_rec_clear_event() - append clear event command to the command queue
+ *			    record
+ * @rec:	the command queue record
+ * @event:	the desired event to be cleared
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event);
+
+/**
+ * cmdq_rec_flush() - trigger CMDQ to execute the recorded commands
+ * @rec:	the command queue record
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ * Trigger CMDQ to execute the recorded commands. Note that this is a
+ * synchronous flush function. When the function returned, the recorded
+ * commands have been done.
+ */
+int cmdq_rec_flush(struct cmdq_rec *rec);
+
+/**
+ * cmdq_rec_flush_async() - trigger CMDQ to asynchronously execute the recorded
+ *			    commands and call back after ISR is finished
+ * @rec:	the command queue record
+ * @cb:		called in the end of CMDQ ISR
+ * @data:	this data will pass back to cb
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ * Trigger CMDQ to asynchronously execute the recorded commands and call back
+ * after ISR is finished. Note that this is an ASYNC function. When the function
+ * returned, it may or may not be finished. The ISR callback function is called
+ * in the end of ISR.
+ */
+int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
+			 void *data);
+
+/**
+ * cmdq_rec_destroy() - destroy command queue record
+ * @rec:	the command queue record
+ */
+void cmdq_rec_destroy(struct cmdq_rec *rec);
+
+#endif	/* __MTK_CMDQ_H__ */
-- 
1.9.1



From hs.liao at mediatek.com  Wed May  4 05:32:17 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Wed, 4 May 2016 20:32:17 +0800
Subject: [RFC v5 4/4] CMDQ: suspend/resume protection
In-Reply-To: <1462365137-715-1-git-send-email-hs.liao@mediatek.com>
References: <1462365137-715-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1462365137-715-5-git-send-email-hs.liao@mediatek.com>

Add suspend/resume protection mechanism to prevent active task(s) in
suspend.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
---
 drivers/soc/mediatek/mtk-cmdq.c | 295 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 289 insertions(+), 6 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
index d3e9a4c..7599a5b 100644
--- a/drivers/soc/mediatek/mtk-cmdq.c
+++ b/drivers/soc/mediatek/mtk-cmdq.c
@@ -50,6 +50,7 @@
 #define CMDQ_CLK_NAME			"gce"
 
 #define CMDQ_CURR_IRQ_STATUS_OFFSET	0x010
+#define CMDQ_CURR_LOADED_THR_OFFSET	0x018
 #define CMDQ_THR_SLOT_CYCLES_OFFSET	0x030
 
 #define CMDQ_THR_BASE			0x100
@@ -143,6 +144,7 @@ enum cmdq_code {
 enum cmdq_task_state {
 	TASK_STATE_IDLE,	/* free task */
 	TASK_STATE_BUSY,	/* task running on a thread */
+	TASK_STATE_KILLED,	/* task process being killed */
 	TASK_STATE_ERROR,	/* task execution error */
 	TASK_STATE_DONE,	/* task finished */
 	TASK_STATE_WAITING,	/* allocated but waiting for available thread */
@@ -182,6 +184,8 @@ struct cmdq_thread {
 
 struct cmdq {
 	struct device		*dev;
+	struct notifier_block	pm_notifier;
+
 	void __iomem		*base;
 	u32			irq;
 
@@ -201,9 +205,12 @@ struct cmdq {
 
 	struct cmdq_thread	thread[CMDQ_MAX_THREAD_COUNT];
 	struct mutex		task_mutex;	/* for task list */
+	atomic_t		thread_usage;
 	spinlock_t		exec_lock;	/* for exec task */
 	wait_queue_head_t	thread_dispatch_queue;
 	struct clk		*clock;
+	atomic_t		suspending;
+	bool			suspended;
 };
 
 struct cmdq_subsys {
@@ -292,14 +299,24 @@ static struct cmdq_task *cmdq_task_create(struct cmdq *cmdq, size_t size)
 	return task;
 }
 
-static void cmdq_task_release_internal(struct cmdq_task *task)
+static void cmdq_task_release_unlocked(struct cmdq_task *task)
 {
 	struct cmdq *cmdq = task->cmdq;
 
-	mutex_lock(&cmdq->task_mutex);
+	/* This func should be inside cmdq->task_mutex mutex */
+	lockdep_assert_held(&cmdq->task_mutex);
+
 	cmdq_task_free_command_buffer(task);
 	list_del(&task->list_entry);
 	kmem_cache_free(cmdq->task_cache, task);
+}
+
+static void cmdq_task_release_internal(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+
+	mutex_lock(&cmdq->task_mutex);
+	cmdq_task_release_unlocked(task);
 	mutex_unlock(&cmdq->task_mutex);
 }
 
@@ -393,6 +410,7 @@ static struct cmdq_thread *cmdq_thread_get(struct cmdq *cmdq, u64 flag)
 	if (thread->cur_task[next_cookie])
 		return NULL;
 	cmdq_clk_enable(cmdq);
+	atomic_inc(&cmdq->thread_usage);
 	return thread;
 }
 
@@ -401,6 +419,7 @@ static void cmdq_thread_put(struct cmdq *cmdq, struct cmdq_thread *thread)
 	if (WARN_ON(thread == NULL))
 		return;
 	cmdq_clk_disable(cmdq);
+	atomic_dec(&cmdq->thread_usage);
 }
 
 static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
@@ -492,6 +511,80 @@ static int cmdq_thread_remove_task_by_index(struct cmdq_thread *thread,
 	return 0;
 }
 
+static int cmdq_thread_force_remove_task(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+	struct cmdq_thread *thread = task->thread;
+	int err;
+	int cookie;
+	struct cmdq_task *exec_task;
+
+	err = cmdq_thread_suspend(cmdq, thread);
+
+	cmdq_thread_writel(thread, CMDQ_THR_NO_TIMEOUT,
+			   CMDQ_THR_INST_CYCLES_OFFSET);
+
+	/* The cookie of the task currently being processed */
+	cookie = cmdq_thread_get_cookie(thread) + 1;
+
+	exec_task = thread->cur_task[cookie % CMDQ_MAX_TASK_IN_THREAD];
+	if (exec_task == task) {
+		dma_addr_t eoc_pa = task->mva_base + task->command_size - 16;
+
+		/* The task is executed now, set the PC to EOC for bypass */
+		cmdq_thread_writel(thread, eoc_pa, CMDQ_THR_CURR_ADDR_OFFSET);
+
+		thread->cur_task[cookie % CMDQ_MAX_TASK_IN_THREAD] = NULL;
+		task->task_state = TASK_STATE_KILLED;
+	} else {
+		int i, j;
+		u32 *task_base, *exec_task_base;
+
+		j = thread->task_count;
+		for (i = cookie; j > 0; j--, i++) {
+			i %= CMDQ_MAX_TASK_IN_THREAD;
+
+			exec_task = thread->cur_task[i];
+			if (!exec_task)
+				continue;
+
+			task_base = task->va_base;
+			exec_task_base = exec_task->va_base;
+			if ((exec_task_base[exec_task->num_cmd - 1] ==
+			     CMDQ_JUMP_BY_OFFSET) &&
+			    (exec_task_base[exec_task->num_cmd - 2] ==
+			     CMDQ_JUMP_PASS)) {
+				/* reached the last task */
+				break;
+			}
+
+			if (exec_task_base[exec_task->num_cmd - 2] ==
+			    task->mva_base) {
+				/* fake EOC command */
+				exec_task_base[exec_task->num_cmd - 2] =
+					CMDQ_EOC_IRQ_EN;
+				exec_task_base[exec_task->num_cmd - 1] =
+					CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT;
+
+				/* bypass the task */
+				exec_task_base[exec_task->num_cmd] =
+					task_base[task->num_cmd - 2];
+				exec_task_base[exec_task->num_cmd + 1] =
+					task_base[task->num_cmd - 1];
+
+				i = (i + 1) % CMDQ_MAX_TASK_IN_THREAD;
+
+				thread->cur_task[i] = NULL;
+				task->task_state = TASK_STATE_KILLED;
+				err = 0;
+				break;
+			}
+		}
+	}
+
+	return err;
+}
+
 static struct cmdq_task *cmdq_thread_search_task_by_pc(
 		const struct cmdq_thread *thread, u32 pc)
 {
@@ -790,6 +883,18 @@ static void cmdq_handle_irq(struct cmdq *cmdq, int tid)
 	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
 }
 
+static int cmdq_resumed_notifier(struct cmdq *cmdq)
+{
+	/*
+	 * during suspended, there may be queued tasks.
+	 * we should process them if any.
+	 */
+	queue_work(cmdq->task_consume_wq,
+		   &cmdq->task_consume_wait_queue_item);
+
+	return 0;
+}
+
 static void cmdq_consume_waiting_list(struct work_struct *work)
 {
 	struct cmdq *cmdq = container_of(work, struct cmdq,
@@ -797,6 +902,12 @@ static void cmdq_consume_waiting_list(struct work_struct *work)
 	struct device *dev = cmdq->dev;
 	struct cmdq_task *task, *tmp;
 
+	/* do not execute any task after suspended */
+	if (cmdq->suspended) {
+		dev_warn(dev, "task is consumed after suspended\n");
+		return;
+	}
+
 	mutex_lock(&cmdq->task_mutex);
 
 	if (list_empty(&cmdq->task_wait_list)) {
@@ -960,6 +1071,14 @@ static int cmdq_task_wait_result(struct cmdq_task *task)
 	unsigned long flags;
 
 	spin_lock_irqsave(&cmdq->exec_lock, flags);
+
+	/* suspend, so just return */
+	if (atomic_read(&cmdq->suspending) &&
+	    task->task_state == TASK_STATE_KILLED) {
+		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+		return 0;
+	}
+
 	if (task->task_state != TASK_STATE_DONE)
 		err = cmdq_task_handle_error_result(task);
 	if (thread->task_count <= 0)
@@ -1019,7 +1138,8 @@ static int cmdq_task_wait_and_release(struct cmdq_task *task)
 
 	/* release regardless of success or not */
 	cmdq_thread_put(task->cmdq, task->thread);
-	cmdq_task_release_internal(task);
+	if (!atomic_read(&task->cmdq->suspending))
+		cmdq_task_release_internal(task);
 	return err;
 }
 
@@ -1074,7 +1194,7 @@ static int cmdq_task_submit(struct cmdq_command *command)
 	return err;
 }
 
-static int cmdq_remove(struct platform_device *pdev)
+static void cmdq_deinitialize(struct platform_device *pdev)
 {
 	struct cmdq *cmdq = platform_get_drvdata(pdev);
 	struct cmdq_task *task, *tmp;
@@ -1094,7 +1214,6 @@ static int cmdq_remove(struct platform_device *pdev)
 
 	kmem_cache_destroy(cmdq->task_cache);
 	cmdq->task_cache = NULL;
-	return 0;
 }
 
 static irqreturn_t cmdq_irq_handler(int irq, void *dev)
@@ -1316,6 +1435,13 @@ int cmdq_rec_flush(struct cmdq_rec *rec)
 	int err;
 	struct cmdq_command command;
 
+	/* do not allow flush after suspended */
+	if (rec->cmdq->suspended) {
+		dev_err(rec->cmdq->dev,
+			"%s is called after suspended\n", __func__);
+		return -EPERM;
+	}
+
 	err = cmdq_rec_fill_command(rec, &command);
 	if (err < 0)
 		return err;
@@ -1331,6 +1457,13 @@ int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
 	struct cmdq_task *task;
 	struct cmdq_task_cb task_cb;
 
+	/* do not allow flush after suspended */
+	if (rec->cmdq->suspended) {
+		dev_err(rec->cmdq->dev,
+			"%s is called after suspended\n", __func__);
+		return -EPERM;
+	}
+
 	err = cmdq_rec_fill_command(rec, &command);
 	if (err < 0)
 		return err;
@@ -1351,6 +1484,127 @@ void cmdq_rec_destroy(struct cmdq_rec *rec)
 }
 EXPORT_SYMBOL(cmdq_rec_destroy);
 
+static int cmdq_pm_notifier_cb(struct notifier_block *nb, unsigned long event,
+			       void *ptr)
+{
+	struct cmdq *cmdq = container_of(nb, struct cmdq, pm_notifier);
+
+	switch (event) {
+	case PM_SUSPEND_PREPARE:
+		/*
+		 * Going to suspend the system
+		 * The next stage is freeze process.
+		 * We will queue all request in suspend callback,
+		 * so don't care this stage
+		 */
+		return NOTIFY_DONE;
+	case PM_POST_SUSPEND:
+		/*
+		 * processes had resumed in previous stage
+		 * (system resume callback)
+		 * resume CMDQ driver to execute.
+		 */
+		cmdq_resumed_notifier(cmdq);
+		return NOTIFY_OK;
+	default:
+		return NOTIFY_DONE;
+	}
+	return NOTIFY_DONE;
+}
+
+static int cmdq_suspend(struct device *dev)
+{
+	struct cmdq *cmdq = dev_get_drvdata(dev);
+	u32 exec_threads = readl(cmdq->base + CMDQ_CURR_LOADED_THR_OFFSET);
+	int ref_count;
+	unsigned long flags;
+
+	/*
+	 * lock to prevent cmdq_core_consume_waiting_list() and
+	 * cmdq_core_acquire_task(), i.e. no new active tasks
+	 */
+	mutex_lock(&cmdq->task_mutex);
+
+	ref_count = atomic_read(&cmdq->thread_usage);
+	atomic_set(&cmdq->suspending, 1);
+
+	if (ref_count > 0 || exec_threads & CMDQ_THR_EXECUTING) {
+		struct cmdq_task *task, *tmp;
+		int i;
+
+		dev_err(dev, "suspend: other running, kill tasks.\n");
+		dev_err(dev, "threads:0x%08x, ref:%d, AL empty:%d, base:0x%p\n",
+			exec_threads, ref_count,
+			list_empty(&cmdq->task_active_list), cmdq->base);
+
+		/*
+		 * We need to ensure the system is ready to suspend,
+		 * so kill all running CMDQ tasks and release HW engines.
+		 */
+
+		/* remove all active task from thread */
+		list_for_each_entry_safe(task, tmp, &cmdq->task_active_list,
+					 list_entry) {
+			bool already_done = false;
+
+			if (!task->thread)
+				continue;
+
+			spin_lock_irqsave(&cmdq->exec_lock, flags);
+			if (task->task_state == TASK_STATE_BUSY) {
+				/* still wait_event */
+				cmdq_thread_force_remove_task(task);
+				task->task_state = TASK_STATE_KILLED;
+			} else {
+				/* almost finish its work */
+				already_done = true;
+			}
+			spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+
+			/*
+			 * TASK_STATE_KILLED will unlock
+			 * wait_event_timeout in cmdq_task_wait_done(),
+			 * so flush_work to wait auto release flow.
+			 *
+			 * We don't know processes running order,
+			 * so call cmdq_task_release_unlocked() here to
+			 * prevent releasing task before flush_work, and
+			 * also to prevent deadlock of task_mutex.
+			 */
+			if (!already_done) {
+				flush_work(&task->auto_release_work);
+				cmdq_task_release_unlocked(task);
+			}
+		}
+		dev_err(dev, "suspend: AL empty:%d\n",
+			list_empty(&cmdq->task_active_list));
+
+		/* disable all HW thread */
+		dev_err(dev, "suspend: disable all HW threads\n");
+		for (i = 0; i < CMDQ_MAX_THREAD_COUNT; i++)
+			cmdq_thread_disable(cmdq, &cmdq->thread[i]);
+
+		/* reset all cmdq_thread */
+		memset(&cmdq->thread[0], 0, sizeof(cmdq->thread));
+	}
+
+	cmdq->suspended = true;
+	atomic_set(&cmdq->suspending, 0);
+
+	mutex_unlock(&cmdq->task_mutex);
+
+	/* ALWAYS allow suspend */
+	return 0;
+}
+
+static int cmdq_resume(struct device *dev)
+{
+	struct cmdq *cmdq = dev_get_drvdata(dev);
+
+	cmdq->suspended = false;
+	return 0;
+}
+
 static int cmdq_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -1401,12 +1655,40 @@ static int cmdq_probe(struct platform_device *pdev)
 		err = PTR_ERR(cmdq->clock);
 		goto fail;
 	}
+
+	/* hibernation and suspend events */
+	cmdq->pm_notifier.notifier_call = cmdq_pm_notifier_cb;
+	cmdq->pm_notifier.priority = 5;
+	err = register_pm_notifier(&cmdq->pm_notifier);
+	if (err < 0) {
+		dev_err(dev, "failed to register cmdq pm notifier\n");
+		goto fail;
+	}
+
 	return 0;
 fail:
-	cmdq_remove(pdev);
+	cmdq_deinitialize(pdev);
 	return err;
 }
 
+static int cmdq_remove(struct platform_device *pdev)
+{
+	struct cmdq *cmdq = platform_get_drvdata(pdev);
+	int err;
+
+	err = unregister_pm_notifier(&cmdq->pm_notifier);
+	if (err < 0)
+		dev_err(&pdev->dev, "unregister pm notifier failed\n");
+
+	cmdq_deinitialize(pdev);
+	return 0;
+}
+
+static const struct dev_pm_ops cmdq_pm_ops = {
+	.suspend = cmdq_suspend,
+	.resume = cmdq_resume,
+};
+
 static const struct of_device_id cmdq_of_ids[] = {
 	{.compatible = "mediatek,mt8173-gce",},
 	{}
@@ -1418,6 +1700,7 @@ static struct platform_driver cmdq_drv = {
 	.driver = {
 		.name = CMDQ_DRIVER_DEVICE_NAME,
 		.owner = THIS_MODULE,
+		.pm = &cmdq_pm_ops,
 		.of_match_table = cmdq_of_ids,
 	}
 };
-- 
1.9.1



From hs.liao at mediatek.com  Wed May  4 05:32:16 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Wed, 4 May 2016 20:32:16 +0800
Subject: [RFC v5 3/4] arm64: dts: mt8173: Add GCE node
In-Reply-To: <1462365137-715-1-git-send-email-hs.liao@mediatek.com>
References: <1462365137-715-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1462365137-715-4-git-send-email-hs.liao@mediatek.com>

This patch adds the device node of the GCE hardware for CMDQ module.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index eab7efc..63d1718 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -300,6 +300,14 @@
 			#clock-cells = <1>;
 		};
 
+		gce: gce at 10212000 {
+			compatible = "mediatek,mt8173-gce";
+			reg = <0 0x10212000 0 0x1000>;
+			interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>;
+			clocks = <&infracfg CLK_INFRA_GCE>;
+			clock-names = "gce";
+		};
+
 		gic: interrupt-controller at 10220000 {
 			compatible = "arm,gic-400";
 			#interrupt-cells = <3>;
-- 
1.9.1



From robh at kernel.org  Wed May  4 05:43:18 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 4 May 2016 07:43:18 -0500
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <CACh+v5O2XpJyYWz70pVgtU5-g9td6J7EdmNtJwk0s5SUkAywaQ@mail.gmail.com>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop> <20160503185153.5cfddc32@bbrezillon>
 <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
 <CACh+v5O2XpJyYWz70pVgtU5-g9td6J7EdmNtJwk0s5SUkAywaQ@mail.gmail.com>
Message-ID: <CAL_JsqKe2q+k7XEHA0QDs7cj_nkRQj3ZKPEd5Y56Npk1uDi1hA@mail.gmail.com>

On Wed, May 4, 2016 at 5:06 AM, Jean-Jacques Hiblot
<jjhiblot at traphandler.com> wrote:
> 2016-05-03 21:11 GMT+02:00 Rob Herring <robh at kernel.org>:
>> On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
>> <boris.brezillon at free-electrons.com> wrote:
>>> Hi Rob,
>>>
>>> On Tue, 3 May 2016 11:40:19 -0500
>>> Rob Herring <robh at kernel.org> wrote:
>>>
>>>> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:
>>>> > The EBI (External Bus Interface) is used to access external peripherals
>>>> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
>>>> > Each device is assigned a CS line and an address range and can have its
>>>> > own configuration (timings, access mode, bus width, ...).
>>>> > This driver provides a generic DT binding to configure a device according
>>>> > to its requirements.
>>>> > For specific device controllers (like the NAND one) the SMC timings
>>>> > should be configured by the controller driver through the matrix and smc
>>>> > syscon regmaps.
>>>> >
>>>> > Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
>>>> > ---
>>>> >  .../bindings/memory-controllers/atmel,ebi.txt      | 136 +++++++++++++++++++++
>>>> >  1 file changed, 136 insertions(+)
>>>> >  create mode 100644 Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
>>>> >
>>>> > diff --git a/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
>>>> > new file mode 100644
>>>> > index 0000000..a6dca5c
>>>> > --- /dev/null
>>>> > +++ b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
>>>> > @@ -0,0 +1,136 @@
>>>> > +* Device tree bindings for Atmel EBI
>>>> > +
>>>> > +The External Bus Interface (EBI) controller is a bus where you can connect
>>>> > +asynchronous (NAND, NOR, SRAM, ....) and synchronous memories (SDR/DDR SDRAMs).
>>>> > +The EBI provides a glue-less interface to asynchronous memories through the SMC
>>>> > +(Static Memory Controller).
>>>> > +
>>>> > +Required properties:
>>>> > +
>>>> > +- compatible:              "atmel,at91sam9260-ebi"
>>>> > +                   "atmel,at91sam9261-ebi"
>>>> > +                   "atmel,at91sam9263-ebi0"
>>>> > +                   "atmel,at91sam9263-ebi1"
>>>>
>>>> What are the differences between 0 and 1?
>>>
>>> Because this SoC has 2 EBI busses with different capabilities.
>>
>> Okay, correct answer. :)
>>
>> [...]
>>
>>>>
>>>> > +                   of the memory region requested by the device.
>>>> > +
>>>> > +EBI bus configuration associated with specific chip-select will be defined in
>>>> > +the configs subnode. This configs node will in turn contain several subnodes
>>>> > +named config-<cs-id>, each of them containing the following properties.
>>>>
>>>> This is a bit unusual. Why not just part of the child device nodes?
>>>
>>> Oh, come on! I reworked the binding because Mark complained about the
>>> previous binding which was doing exactly what you're suggesting. Can
>>> you please be consistent in your reviews...
>>
>> No, Mark and I both have our opinions. Which part of this patch
>> explains the history? If the revision history is not in the patch, I'm
>> not looking at it.
>>
>> My issue with it this way is that it has invented yet another way to
>> describe timings. I would like to be consistent across external bus
>> descriptions, but we're not very consistent to begin with though. The
>> most common seems to be the way you first did it. But I agree that it
>> is kind of screwy to have an intermediate node unless the controller
>> itself has sub-blocks within it and is not the established way to
>> describe a bus with chip selects. I would either put the properties
>> directly in the child nodes (e.g. flash at 0,0) or put your config nodes
>> in the device node. I'd call it timings instead of config, but that's
>> just bikeshedding.
>>
>> memory-controller at 1000 {
>>   ...
>>   flash at 0,0 {
>>     timings {
>>       ...
>>     };
>>   };
>> };
>>
>
> I don't think the timings belong in the child node as they really are
> for the chip select and the chip select may select several devices at
> once. I'm thinking (again) of a FPGA here that could implement or
> example 4 serial ports at different addresses.

It is an established pattern already in i.MX WEIM and OMAP GPMC
bindings. The timings are a function of the device attached, so having
them in the device's node makes some sense. Arguably we should define
the timings in a generic way, but that's hard and no one wants to do
that.

Rob


From k.kozlowski at samsung.com  Wed May  4 05:44:00 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 04 May 2016 14:44:00 +0200
Subject: [PATCH v3 3/3] ARM: dts: exynos: Lower SD card interface voltage to
 2.8 V on Odroid X/X2/U3
In-Reply-To: <1462365840-27406-1-git-send-email-k.kozlowski@samsung.com>
References: <1462365840-27406-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462365840-27406-3-git-send-email-k.kozlowski@samsung.com>

Odroid X/X2/U3 schematics say that SD card vmmc regulator
(LDO21/TFLASH) operates on 2.8 V. Mainline U-Boot uses that value as
well and 2.8 V is common on Exynos-based boards. Additionally use some
descriptive name for this regulator.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

---
Changes since v2:
1. Add Javier's tag.

Changes since v1:
1. None
---
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
index 7485ce8a6fb3..14e653e32e0f 100644
--- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -341,9 +341,9 @@
 			};
 
 			ldo21_reg: LDO21 {
-				regulator-name = "LDO21_3.3V";
-				regulator-min-microvolt = <3300000>;
-				regulator-max-microvolt = <3300000>;
+				regulator-name = "TFLASH_2.8V";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
 				regulator-boot-on;
 			};
 
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May  4 05:43:59 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 04 May 2016 14:43:59 +0200
Subject: [PATCH v3 2/3] ARM: dts: exynos: Define vqmmc for eMMC card on Odroid
 X/X2/U3
In-Reply-To: <1462365840-27406-1-git-send-email-k.kozlowski@samsung.com>
References: <1462365840-27406-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462365840-27406-2-git-send-email-k.kozlowski@samsung.com>

The eMMC card vmmc-supply contained incorrectly two regulators: LDO20
and buck8. The second one is ignored. Additionally the buck8 is a vqmmc
supply only on X and X2. On U3 the buck8 is providing power to the LAN
(SMSC95xx) so instead the LDO22 should be used.

Fix this by defining proper vmmc and vqmmc supplies for respective
boards.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

Changes since v2:
1. Add Javier's tag.
2. Apply Javier's feedback: remove the regulator constraints (min/max
   volts) from common DTS.

Changes since v1:
1. buck8 is used on X/X2 so differentiate the configuration (hint by
   Tobias Jakobi).
---
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 17 ++++++++++++++---
 arch/arm/boot/dts/exynos4412-odroidu3.dts       | 18 ++++++++++++++++++
 arch/arm/boot/dts/exynos4412-odroidx.dts        | 11 +++++++++++
 arch/arm/boot/dts/exynos4412-odroidx2.dts       | 11 +++++++++++
 4 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
index 3d0d44581fbd..7485ce8a6fb3 100644
--- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -347,6 +347,15 @@
 				regulator-boot-on;
 			};
 
+			ldo22_reg: LDO22 {
+				/*
+				 * Only U3 uses it, so let it define the
+				 * constraints
+				 */
+				regulator-name = "LDO22";
+				regulator-boot-on;
+			};
+
 			ldo25_reg: LDO25 {
 				regulator-name = "VDDQ_LCD_1.8V";
 				regulator-min-microvolt = <1800000>;
@@ -410,9 +419,11 @@
 			};
 
 			buck8_reg: BUCK8 {
+				/*
+				 * Constraints set by specific board: X,
+				 * X2 and U3.
+				 */
 				regulator-name = "BUCK8_2.8V";
-				regulator-min-microvolt = <2800000>;
-				regulator-max-microvolt = <2800000>;
 			};
 		};
 	};
@@ -456,7 +467,7 @@
 &mshc_0 {
 	pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
 	pinctrl-names = "default";
-	vmmc-supply = <&ldo20_reg &buck8_reg>;
+	vmmc-supply = <&ldo20_reg>;
 	mmc-pwrseq = <&emmc_pwrseq>;
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/exynos4412-odroidu3.dts b/arch/arm/boot/dts/exynos4412-odroidu3.dts
index dd89f7b37c9f..d73aa6c58fe3 100644
--- a/arch/arm/boot/dts/exynos4412-odroidu3.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidu3.dts
@@ -69,6 +69,24 @@
 	};
 };
 
+/* Supply for LAN9730/SMSC95xx */
+&buck8_reg {
+	regulator-name = "BUCK8_P3V3";
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+};
+
+/* VDDQ for MSHC (eMMC card) */
+&ldo22_reg {
+	regulator-name = "LDO22_VDDQ_MMC4_2.8V";
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+};
+
+&mshc_0 {
+	vqmmc-supply = <&ldo22_reg>;
+};
+
 &pwm {
 	pinctrl-0 = <&pwm0_out>;
 	pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts
index bf7b21b817e4..2af235151301 100644
--- a/arch/arm/boot/dts/exynos4412-odroidx.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidx.dts
@@ -63,12 +63,23 @@
 	};
 };
 
+/* VDDQ for MSHC (eMMC card) */
+&buck8_reg {
+	regulator-name = "BUCK8_VDDQ_MMC4_2.8V";
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+};
+
 &ehci {
 	port at 1 {
 		status = "okay";
 	};
 };
 
+&mshc_0 {
+	vqmmc-supply = <&buck8_reg>;
+};
+
 &pinctrl_1 {
 	gpio_home_key: home_key {
 		samsung,pins = "gpx2-2";
diff --git a/arch/arm/boot/dts/exynos4412-odroidx2.dts b/arch/arm/boot/dts/exynos4412-odroidx2.dts
index 6e33678562ae..3e3584270e00 100644
--- a/arch/arm/boot/dts/exynos4412-odroidx2.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidx2.dts
@@ -22,6 +22,17 @@
 	};
 };
 
+/* VDDQ for MSHC (eMMC card) */
+&buck8_reg {
+	regulator-name = "BUCK8_VDDQ_MMC4_2.8V";
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+};
+
+&mshc_0 {
+	vqmmc-supply = <&buck8_reg>;
+};
+
 &sound {
 	simple-audio-card,name = "Odroid-X2";
 	simple-audio-card,widgets =
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May  4 05:43:58 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 04 May 2016 14:43:58 +0200
Subject: [PATCH v3 1/3] ARM: dts: exynos: Define vqmmc for SD card and allow
 disabling regulators on Odroid X/X2/U3
Message-ID: <1462365840-27406-1-git-send-email-k.kozlowski@samsung.com>

The SD-card vmmc-supply contained incorrectly two regulators. The second
one is ignored. Fix this by defining proper vmmc and vqmmc supplies.
Additionally these regulators do not have to be always on, so allow
disabling them to reduce energy consumption.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

Changes since v2:
1. Add Javier's tag.

Changes since v1:
1. None
---
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
index cab0f07d7d28..3d0d44581fbd 100644
--- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -249,7 +249,6 @@
 				regulator-name = "VDDQ_MMC2_2.8V";
 				regulator-min-microvolt = <2800000>;
 				regulator-max-microvolt = <2800000>;
-				regulator-always-on;
 				regulator-boot-on;
 			};
 
@@ -345,7 +344,6 @@
 				regulator-name = "LDO21_3.3V";
 				regulator-min-microvolt = <3300000>;
 				regulator-max-microvolt = <3300000>;
-				regulator-always-on;
 				regulator-boot-on;
 			};
 
@@ -482,7 +480,8 @@
 	bus-width = <4>;
 	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
 	pinctrl-names = "default";
-	vmmc-supply = <&ldo4_reg &ldo21_reg>;
+	vmmc-supply = <&ldo21_reg>;
+	vqmmc-supply = <&ldo4_reg>;
 	cd-gpios = <&gpk2 2 GPIO_ACTIVE_HIGH>;
 	cd-inverted;
 	status = "okay";
-- 
1.9.1



From pavel at ucw.cz  Wed May  4 05:46:53 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Wed, 4 May 2016 14:46:53 +0200
Subject: [PATCH v2 0/4] Patches to allow consistent mmc / mmcblk
 numbering w/ device tree
In-Reply-To: <CAL_JsqJ4Pzuip9VUpwryy_xK6XSZ6E+kus3wD=T4wcTHav=9iA@mail.gmail.com>
References: <1461951139-6109-1-git-send-email-dianders@chromium.org>
 <20160429181248.GW19428@n2100.arm.linux.org.uk>
 <20160504071801.GA17045@amd>
 <CAL_JsqJ4Pzuip9VUpwryy_xK6XSZ6E+kus3wD=T4wcTHav=9iA@mail.gmail.com>
Message-ID: <20160504124653.GA23838@amd>

On Wed 2016-05-04 07:25:42, Rob Herring wrote:
> On Wed, May 4, 2016 at 2:18 AM, Pavel Machek <pavel at ucw.cz> wrote:
> > On Fri 2016-04-29 19:12:48, Russell King - ARM Linux wrote:
> >> On Fri, Apr 29, 2016 at 10:32:15AM -0700, Douglas Anderson wrote:
> >> > This series picks patches from various different places to produce what
> >> > I consider the best solution to getting consistent mmc and mmcblk
> >> > ordering.
> >> >
> >> > Why consistent ordering and why not just use UUIDs?  IMHO consistent
> >> > ordering solves a few different problems:
> >>
> >> NAK.  Really.  Use UUIDs, that's the proper solution here.
> >
> > Except that UUIDs do not solve the problem.
> >
> > You have just booted of nfsroot, and you want to format u-SD card in
> > the external slot. How do you do that?
> 
> The same way you format a USB stick when you insert it.

Well, and that actually brings related question "how do you format the
right USB stick if you have 5 of them connected". PCs don't have good
solution, but that does not mean it can't be solved.

And no, its not really the same. At least in N900 case, I'm not really
sure if you are expected to manipulate the u-SD card while the system
is on. It is under battery cover.

> If you have built-in versus removable, then we should expose that
> information to userspace rather than some arbitrary encoding in DT
> that 0 means built-in and 1 means removable. Or if you have multiple
> slots, then use "label" to provide meaningful slot names.

Yes, labels would be nice. Plus the slot numbers should be stable, so
that booting does not randomly break.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From javier at osg.samsung.com  Wed May  4 05:51:25 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 4 May 2016 08:51:25 -0400
Subject: [PATCH v3 3/3] ARM: dts: exynos: Lower SD card interface voltage
 to 2.8 V on Odroid X/X2/U3
In-Reply-To: <1462365840-27406-3-git-send-email-k.kozlowski@samsung.com>
References: <1462365840-27406-1-git-send-email-k.kozlowski@samsung.com>
 <1462365840-27406-3-git-send-email-k.kozlowski@samsung.com>
Message-ID: <764fb4d7-873f-0e59-446b-e9652151512d@osg.samsung.com>

Hello Krzysztof,

On 05/04/2016 08:44 AM, Krzysztof Kozlowski wrote:
> Odroid X/X2/U3 schematics say that SD card vmmc regulator
> (LDO21/TFLASH) operates on 2.8 V. Mainline U-Boot uses that value as
> well and 2.8 V is common on Exynos-based boards. Additionally use some
> descriptive name for this regulator.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> 
> ---
> Changes since v2:
> 1. Add Javier's tag.
> 

It's missing though :)

Adding the tag again so it can be picked by patchwork:

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From oliver at schinagl.nl  Wed May  4 05:52:12 2016
From: oliver at schinagl.nl (Olliver Schinagl)
Date: Wed, 4 May 2016 14:52:12 +0200
Subject: [PATCH 1/1] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <CANCTEQgjiuQXcaw=3Dr5kUsTPc3nsDQf2odwzs4nHvrkREAqrg@mail.gmail.com>
References: <1461827998-12192-1-git-send-email-oliver@schinagl.nl>
 <CAGb2v66E2TuN3+tYaAbniV3q67waDZOfqKAW14VJz6xZFomZ=Q@mail.gmail.com>
 <57285162.2000704@schinagl.nl>
 <CAGb2v66r9m7qVW6BszeT2wqs0KyEr4x5ivTJYqu2Fes=R9-Ltw@mail.gmail.com>
 <CANCTEQgjiuQXcaw=3Dr5kUsTPc3nsDQf2odwzs4nHvrkREAqrg@mail.gmail.com>
Message-ID: <5729F07C.3080308@schinagl.nl>

Hey Radoslav,

On 04-05-16 14:30, Radoslav Kolev wrote:
> 2016-05-03 10:25 GMT+03:00 Chen-Yu Tsai <wens at csie.org>:
>> On Tue, May 3, 2016 at 3:21 PM, Olliver Schinagl <oliver at schinagl.nl> wrote:
>>>>> +       bus-width = <4>;
>>>> Only 4 bits? We normally see eMMC with 8 bits. 4 bits are some kind of
>>>> embedded SD card.
>>> On A20 as well? Our investigations so far have concluded that the A10 and
>>> A20 have those pins not mapped out to pads. The IP does support it however
>>> we assume.
>> You're right. My bad. First time A10/A20 sees eMMC support.
> I can't say anything about A10/A20, but I have a board with A13 and
> the same eMMC chip and it works fine in 8 bit mode.
Yep, sun5i actually brings them all out to pads, the A20 however does 
not :( We first thought that the A20 would also be an 8bitter, because 
the mmc IP appears to be the same as sun5i, but initial tests show it is 
not. As for A10, it has older IP and it might not even support 8 bit 
mode, let alone bring out the pins.

But with A20's + eMMC being available via the lime2, others may repeat 
my experiments! The lime2 is 8 bit connected.

Olliver
>
> Regards,
> Radoslav



From marc.zyngier at arm.com  Wed May  4 05:57:30 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 4 May 2016 13:57:30 +0100
Subject: [PATCH v8 5/8] genirq/irq: introduce msi_doorbell_info
In-Reply-To: <1461831730-5575-6-git-send-email-eric.auger@linaro.org>
References: <1461831730-5575-1-git-send-email-eric.auger@linaro.org>
 <1461831730-5575-6-git-send-email-eric.auger@linaro.org>
Message-ID: <5729F1BA.6060306@arm.com>

On 28/04/16 09:22, Eric Auger wrote:
> The purpose is to be able to retrieve the MSI doorbells of an irqchip.
> This is now needed since on some platforms those doorbells must be
> iommu mapped (in case the MSIs transit through an IOMMU that do not
> bypass those transactions).
> 
> The assumption is there is a maximum of one doorbell region per cpu.
> 
> A doorbell region is characterized by its physical address base, size and
> IOMMU protection flag. Those 2 last characteristics are shared among all
> doorbells.
> 
> irq_chip msi_doorbell_info callback enables to retrieve the doorbells of
> the irqchip.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> 
> ---
> v7 -> v8:
> - size and prot now are shared among all doorbells
> - doorbells now directly points to a percpu phys_addr_t
> 
> v7: creation
> ---
>  include/linux/irq.h | 17 ++++++++++++++++-
>  1 file changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/irq.h b/include/linux/irq.h
> index c4de623..5dbb26d 100644
> --- a/include/linux/irq.h
> +++ b/include/linux/irq.h
> @@ -312,6 +312,19 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
>  	return d->hwirq;
>  }
>  
> +/*
> + * Describe all the MSI doorbell regions for an irqchip.
> + * A single doorbell region per cpu is assumed.
> + * In case a single doorbell is supported for the whole irqchip,
> + * the region is described in as cpu #0's one
> + */
> +struct irq_chip_msi_doorbell_info {
> +	phys_addr_t __percpu *percpu_doorbells; /* per cpu base address */

Here's an idea: you could turn this field into a union:

	union {
		phys_addr_t __percpu *percpu_doorbells;
		phys_addr_t global_doorbell;
	};

> +	size_t size;				/* size of a each doorbell */
> +	int prot;				/* iommu protection flag */
> +	int nb_doorbells;

And this can be turned into a boolean:

	bool doorbell_is_percpu;

This allows you to avoid allocating a bunch of percpu doorbells for a
MSI controller that only has a global one. And the number of doorbells
is always either 1 or the number of CPUs anyway.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From marc.zyngier at arm.com  Wed May  4 06:02:23 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 4 May 2016 14:02:23 +0100
Subject: [PATCH v8 6/8] irqchip/gicv2m: implement msi_doorbell_info
 callback
In-Reply-To: <1461831730-5575-7-git-send-email-eric.auger@linaro.org>
References: <1461831730-5575-1-git-send-email-eric.auger@linaro.org>
 <1461831730-5575-7-git-send-email-eric.auger@linaro.org>
Message-ID: <5729F2DF.80908@arm.com>

On 28/04/16 09:22, Eric Auger wrote:
> This patch implements the msi_doorbell_info callback in the
> gicv2m driver.
> 
> The driver now is able to return its doorbell characteristics
> (base, size, prot). A single doorbell is exposed.
> 
> This will allow the msi layer to iommu_map this doorbell when
> requested.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> 
> ---
> 
> v7 -> v8:
> - gicv2m_msi_doorbell_info does not return a pointer to const
> - remove spurious !v2m check
> - add IOMMU_MMIO flag
> 
> v7: creation
> ---
>  drivers/irqchip/irq-gic-v2m.c | 30 +++++++++++++++++++++++++++++-
>  1 file changed, 29 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
> index 28f047c..a1ea40c 100644
> --- a/drivers/irqchip/irq-gic-v2m.c
> +++ b/drivers/irqchip/irq-gic-v2m.c
> @@ -24,6 +24,8 @@
>  #include <linux/of_pci.h>
>  #include <linux/slab.h>
>  #include <linux/spinlock.h>
> +#include <linux/percpu.h>
> +#include <linux/iommu.h>
>  
>  /*
>  * MSI_TYPER:
> @@ -64,6 +66,7 @@ struct v2m_data {
>  	u32 nr_spis;		/* The number of SPIs for MSIs */
>  	unsigned long *bm;	/* MSI vector bitmap */
>  	u32 flags;		/* v2m flags for specific implementation */
> +	struct irq_chip_msi_doorbell_info doorbell_info;
>  };
>  
>  static void gicv2m_mask_msi_irq(struct irq_data *d)
> @@ -105,6 +108,14 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
>  		msg->data -= v2m->spi_start;
>  }
>  
> +static inline struct irq_chip_msi_doorbell_info *

You do not need an inline here, specially given that you're assigning
its pointer to a structure just below.

> +gicv2m_msi_doorbell_info(struct irq_data *data)
> +{
> +	struct v2m_data *v2m = irq_data_get_irq_chip_data(data);
> +
> +	return &v2m->doorbell_info;
> +}
> +
>  static struct irq_chip gicv2m_irq_chip = {
>  	.name			= "GICv2m",
>  	.irq_mask		= irq_chip_mask_parent,
> @@ -112,6 +123,7 @@ static struct irq_chip gicv2m_irq_chip = {
>  	.irq_eoi		= irq_chip_eoi_parent,
>  	.irq_set_affinity	= irq_chip_set_affinity_parent,
>  	.irq_compose_msi_msg	= gicv2m_compose_msi_msg,
> +	.msi_doorbell_info	= gicv2m_msi_doorbell_info,
>  };
>  
>  static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
> @@ -247,6 +259,7 @@ static void gicv2m_teardown(void)
>  
>  	list_for_each_entry_safe(v2m, tmp, &v2m_nodes, entry) {
>  		list_del(&v2m->entry);
> +		free_percpu(v2m->doorbell_info.percpu_doorbells);
>  		kfree(v2m->bm);
>  		iounmap(v2m->base);
>  		of_node_put(to_of_node(v2m->fwnode));
> @@ -299,6 +312,7 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
>  {
>  	int ret;
>  	struct v2m_data *v2m;
> +	phys_addr_t __percpu *doorbell;
>  
>  	v2m = kzalloc(sizeof(struct v2m_data), GFP_KERNEL);
>  	if (!v2m) {
> @@ -311,11 +325,23 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
>  
>  	memcpy(&v2m->res, res, sizeof(struct resource));
>  
> +	v2m->doorbell_info.percpu_doorbells =
> +		alloc_percpu(phys_addr_t);
> +	if (WARN_ON(!v2m->doorbell_info.percpu_doorbells)) {
> +		ret = -ENOMEM;
> +		goto err_free_v2m;
> +	}
> +	doorbell = per_cpu_ptr(v2m->doorbell_info.percpu_doorbells, 0);
> +	*doorbell = v2m->res.start;
> +	v2m->doorbell_info.size = 4;
> +	v2m->doorbell_info.prot = IOMMU_WRITE | IOMMU_MMIO;
> +	v2m->doorbell_info.nb_doorbells = 1;


So if you take my earlier suggestion, this becomes:

	v2m->doorbell_info.global_doorbell = v2m->res.start;
	v2m->doorbell_info.size = sizeof(u32);
	v2m->doorbell_info.doorbell_is_percpu = false;

a bit nicer.

> +
>  	v2m->base = ioremap(v2m->res.start, resource_size(&v2m->res));
>  	if (!v2m->base) {
>  		pr_err("Failed to map GICv2m resource\n");
>  		ret = -ENOMEM;
> -		goto err_free_v2m;
> +		goto err_free_v2m_doorbells;
>  	}
>  
>  	if (spi_start && nr_spis) {
> @@ -359,6 +385,8 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
>  
>  err_iounmap:
>  	iounmap(v2m->base);
> +err_free_v2m_doorbells:
> +	free_percpu(v2m->doorbell_info.percpu_doorbells);
>  err_free_v2m:
>  	kfree(v2m);
>  	return ret;
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From k.kozlowski at samsung.com  Wed May  4 06:05:36 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 04 May 2016 15:05:36 +0200
Subject: [GIT PULL] ARM: dts: exynos: Devfreq for v4.7
Message-ID: <1462367136-28627-1-git-send-email-k.kozlowski@samsung.com>

Hi,


Topic branch with DTS changes for v4.7, adding nodes for new generic
devfreq driver. The devfreq driver will support Exynos3250, 4210, 4212,
4412 and 542x.

This is a long work of Chanwoo Choi, recently merged (including
documentation of bindings) by devfreq maintainer, MyungJoo Ham:
http://permalink.gmane.org/gmane.linux.power-management.general/75599


This pull request includes dependency: changes coming from clk tree
with a clk-v4.7-exynos542x tag.

Below you will find full log. At the end - only commits existing
in my tree.


Best regards,
Krzysztof

Cc: myungjoo.ham at samsung.com
Cc: cw00.choi at samsung.com
Cc: linux-pm at vger.kernel.org
Cc: rjw at rjwysocki.net


The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git tags/samsung-dt-devfreq-4.7

for you to fetch changes up to 3f2129fd0daeaf9e60a51f9ebd2d9faabb437308:

  ARM: dts: exynos: Add support of Bus frequency using VDD_INT for exynos5422-odroidxu3 (2016-05-03 12:27:52 +0200)

----------------------------------------------------------------
Topic branch for Device Tree changes adding new generic devfreq driver, for
v4.7:
1. Add bus nodes for Exynos3250, Exynos4x12, Exynos4210 and Exynos542x.
2. Split out common PPMU (Performance Monitoring Unit) nodes into separate
   DTSI. The PPMU provides performance data for devfreq.
3. Add NoCP (Network on Chip Probe) node for Exynos542x. On this SoC, like PPMU
   on older designs, provides performance data for devfreq.
4. Enable DFVS (Dynamic Voltage and Frequency Scaling) on boards:
   - Exynos3250 Rinato,
   - Exynos4412 Odroid-X/X2/U3 and Trats2,
   - Exynos5422 Odroid XU3/XU3-Lite/XU4.

----------------------------------------------------------------
Chanwoo Choi (15):
      dt-bindings: clock: Add the clock id for ACLK clock of Exynos542x SoC
      clk: samsung: exynos542x: Add the clock id for ACLK
      ARM: dts: exynos: Add DMC bus node for Exynos3250
      ARM: dts: exynos: Add DMC bus frequency for exynos3250-rinato/monk
      ARM: dts: exynos: Add bus nodes using VDD_INT for Exynos3250
      ARM: dts: exynos: Add bus nodes using VDD_MIF for Exynos4x12
      ARM: dts: exynos: Add bus nodes using VDD_INT for Exynos4x12
      ARM: dts: exynos: Add bus nodes using VDD_MIF for Exynos4210
      ARM: dts: exynos: Add exynos4412-ppmu-common dtsi to delete duplicate PPMU nodes
      ARM: dts: exynos: Add support of bus frequency using VDD_INT for exynos3250-rinato
      ARM: dts: exynos: Expand the voltage range of buck1/3 regulator for exynos4412-odroidu3
      ARM: dts: exynos: Add support of bus frequency for exynos4412-trats/odroidu3
      ARM: dts: exynos: Add NoC Probe dt node for Exynos542x SoC
      ARM: dts: exynos: Add bus nodes using VDD_INT for Exynos542x SoC
      ARM: dts: exynos: Add support of Bus frequency using VDD_INT for exynos5422-odroidxu3

Krzysztof Kozlowski (1):
      Merge tag 'clk-v4.7-exynos542x' of git://linuxtv.org/snawrocki/samsung into for-v4.7-late/dts-exynos-devfreq

 arch/arm/boot/dts/exynos3250-monk.dts              |  47 +--
 arch/arm/boot/dts/exynos3250-rinato.dts            |  88 +++--
 arch/arm/boot/dts/exynos3250.dtsi                  | 181 +++++++++
 arch/arm/boot/dts/exynos4210.dtsi                  | 159 ++++++++
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi    |  56 ++-
 arch/arm/boot/dts/exynos4412-ppmu-common.dtsi      |  50 +++
 arch/arm/boot/dts/exynos4412-trats2.dts            |  88 +++--
 arch/arm/boot/dts/exynos4x12.dtsi                  | 174 +++++++++
 arch/arm/boot/dts/exynos5420.dtsi                  | 407 +++++++++++++++++++++
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |  99 +++++
 drivers/clk/samsung/clk-exynos5420.c               |  77 ++--
 include/dt-bindings/clock/exynos5420.h             |  24 +-
 12 files changed, 1295 insertions(+), 155 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos4412-ppmu-common.dtsi

----------------------------------------------------------------


Commits only in samsung-soc:
----------------------------------------------------------------
Chanwoo Choi (13):
      ARM: dts: exynos: Add DMC bus node for Exynos3250
      ARM: dts: exynos: Add DMC bus frequency for exynos3250-rinato/monk
      ARM: dts: exynos: Add bus nodes using VDD_INT for Exynos3250
      ARM: dts: exynos: Add bus nodes using VDD_MIF for Exynos4x12
      ARM: dts: exynos: Add bus nodes using VDD_INT for Exynos4x12
      ARM: dts: exynos: Add bus nodes using VDD_MIF for Exynos4210
      ARM: dts: exynos: Add exynos4412-ppmu-common dtsi to delete duplicate PPMU nodes
      ARM: dts: exynos: Add support of bus frequency using VDD_INT for exynos3250-rinato
      ARM: dts: exynos: Expand the voltage range of buck1/3 regulator for exynos4412-odroidu3
      ARM: dts: exynos: Add support of bus frequency for exynos4412-trats/odroidu3
      ARM: dts: exynos: Add NoC Probe dt node for Exynos542x SoC
      ARM: dts: exynos: Add bus nodes using VDD_INT for Exynos542x SoC
      ARM: dts: exynos: Add support of Bus frequency using VDD_INT for exynos5422-odroidxu3

 arch/arm/boot/dts/exynos3250-monk.dts              |  47 +--
 arch/arm/boot/dts/exynos3250-rinato.dts            |  88 +++--
 arch/arm/boot/dts/exynos3250.dtsi                  | 181 +++++++++
 arch/arm/boot/dts/exynos4210.dtsi                  | 159 ++++++++
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi    |  56 ++-
 arch/arm/boot/dts/exynos4412-ppmu-common.dtsi      |  50 +++
 arch/arm/boot/dts/exynos4412-trats2.dts            |  88 +++--
 arch/arm/boot/dts/exynos4x12.dtsi                  | 174 +++++++++
 arch/arm/boot/dts/exynos5420.dtsi                  | 407 +++++++++++++++++++++
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |  99 +++++
 10 files changed, 1225 insertions(+), 124 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos4412-ppmu-common.dtsi


From robh at kernel.org  Wed May  4 06:06:10 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 4 May 2016 08:06:10 -0500
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <20160504113852.10a2dd84@bbrezillon>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop> <20160503185153.5cfddc32@bbrezillon>
 <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
 <20160504113852.10a2dd84@bbrezillon>
Message-ID: <CAL_Jsq+4aL5znA3zOKdcJb+pEXhVOQthkFF6DN2+P6U37t2o6g@mail.gmail.com>

On Wed, May 4, 2016 at 4:38 AM, Boris Brezillon
<boris.brezillon at free-electrons.com> wrote:
> Hi Rob,
>
> On Tue, 3 May 2016 14:11:04 -0500
> Rob Herring <robh at kernel.org> wrote:
>
>> On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
>> <boris.brezillon at free-electrons.com> wrote:
>> > Hi Rob,
>> >
>> > On Tue, 3 May 2016 11:40:19 -0500
>> > Rob Herring <robh at kernel.org> wrote:
>> >
>> >> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:
>> >> > The EBI (External Bus Interface) is used to access external peripherals
>> >> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
>> >> > Each device is assigned a CS line and an address range and can have its
>> >> > own configuration (timings, access mode, bus width, ...).
>> >> > This driver provides a generic DT binding to configure a device according
>> >> > to its requirements.
>> >> > For specific device controllers (like the NAND one) the SMC timings
>> >> > should be configured by the controller driver through the matrix and smc
>> >> > syscon regmaps.

[...]

>> >> > +EBI bus configuration associated with specific chip-select will be defined in
>> >> > +the configs subnode. This configs node will in turn contain several subnodes
>> >> > +named config-<cs-id>, each of them containing the following properties.
>> >>
>> >> This is a bit unusual. Why not just part of the child device nodes?
>> >
>> > Oh, come on! I reworked the binding because Mark complained about the
>> > previous binding which was doing exactly what you're suggesting. Can
>> > you please be consistent in your reviews...
>>
>> No, Mark and I both have our opinions. Which part of this patch
>> explains the history?
>
> Hm, it's in patch 1/2 (just dropped the cover letter, which might not
> be such a good idea).
>
>> If the revision history is not in the patch, I'm
>> not looking at it.
>>
>> My issue with it this way is that it has invented yet another way to
>> describe timings. I would like to be consistent across external bus
>> descriptions, but we're not very consistent to begin with though. The
>> most common seems to be the way you first did it. But I agree that it
>> is kind of screwy to have an intermediate node unless the controller
>> itself has sub-blocks within it and is not the established way to
>> describe a bus with chip selects. I would either put the properties
>> directly in the child nodes (e.g. flash at 0,0) or put your config nodes
>> in the device node. I'd call it timings instead of config, but that's
>> just bikeshedding.
>
> Well, it's not only describing timings (see atmel,bus-width,
> atmel,byte-access-type, ...), but I'm fine with either names :).
>
>>
>> memory-controller at 1000 {
>>   ...
>>   flash at 0,0 {
>>     timings {
>>       ...
>>     };
>>   };
>> };
>
> Okay. Mark, what do you think of this approach?
>
> Note that one of my previous version was defining timings directly in
> the EBI device node, and Arnd noted that doing so may cause problems
> if one of the EBI property (or the config/timing node name) conflict
> with the sub-device binding, which is why I decided to put the EBI
> config definitions in a separate subnode.

You have vendor prefixes on all the properties so I don't think a
collision is really a problem. It's also an established pattern in
i.MX WEIM and OMAP GPMC (which are hiding in bindings/bus/) and I
prefer consistency.

>> >> > +
>> >> > +Optional config-<cs-id> node properties:
>> >> > +
>> >> > +- atmel,bus-width:         width of the asynchronous device's data bus
>> >> > +                           8, 16 or 32.
>> >> > +                           Default to 8 when undefined.
>> >> > +
>> >> > +- atmel,byte-access-type   "write" or "select" (see Atmel datasheet).
>> >> > +                           Default to "select" when undefined.
>> >> > +
>> >> > +- atmel,read-mode          "nrd" or "ncs".
>> >> > +                           Default to "ncs" when undefined.
>> >> > +
>> >> > +- atmel,write-mode         "nwe" or "ncs".
>> >> > +                           Default to "ncs" when undefined.
>> >> > +
>> >> > +- atmel,exnw-mode          "disabled", "frozen" or "ready".
>> >> > +                           Default to "disabled" when undefined.
>> >> > +
>> >> > +- atmel,page-mode          enable page mode if present. The provided value
>> >> > +                           defines the page size (supported values: 4, 8,
>> >> > +                           16 and 32).
>> >> > +
>> >> > +- atmel,tdf-mode:          "normal" or "optimized". When set to
>> >>
>> >> This should be boolean.
>> >
>> > It was a formerly defined as a boolean, and when it's done like that we
>> > have no way to identify whether the property was forgotten or
>> > intentionally set to normal mode. What's the problem with this approach?
>>
>> Only preference to use boolean when that is sufficient. With your
>> argument, then we should never have booleans. You state that missing
>> means "normal", not forgotten, so all these properties should be
>> required with no default.
>>
>> BTW, I debated the same thing on the other properties, but I could see
>> them being expanded to a 3rd mode. I don't see that here though.
>
> Well, another reason I switched to a string property is because I
> implemented hardware readout in v4, and decided to retrieve the current
> state from the hardware and only overload the config with what was
> defined in the DT. In this case, if we move to a boolean property we
> can't know whether the property is missing because we want to put the
> bus in "normal" mode or because we want to keep this config unchanged
> (keep the bootloader/bootstrap config).

Now you are giving yet another definition of what missing means.
Please pick and document one:
- Error, property missing
- Normal mode
- Retain firmware/bootloader settings (this should probably apply to
all or none)

The last is really the only reason I agree with for not doing a boolean.

Rob


From k.kozlowski at samsung.com  Wed May  4 06:06:45 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 04 May 2016 15:06:45 +0200
Subject: [PATCH v3 3/3] ARM: dts: exynos: Lower SD card interface voltage
 to 2.8 V on Odroid X/X2/U3
In-Reply-To: <764fb4d7-873f-0e59-446b-e9652151512d@osg.samsung.com>
References: <1462365840-27406-1-git-send-email-k.kozlowski@samsung.com>
 <1462365840-27406-3-git-send-email-k.kozlowski@samsung.com>
 <764fb4d7-873f-0e59-446b-e9652151512d@osg.samsung.com>
Message-ID: <5729F3E5.4010702@samsung.com>

On 05/04/2016 02:51 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/04/2016 08:44 AM, Krzysztof Kozlowski wrote:
>> Odroid X/X2/U3 schematics say that SD card vmmc regulator
>> (LDO21/TFLASH) operates on 2.8 V. Mainline U-Boot uses that value as
>> well and 2.8 V is common on Exynos-based boards. Additionally use some
>> descriptive name for this regulator.
>>
>> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>>
>> ---
>> Changes since v2:
>> 1. Add Javier's tag.
>>
> 
> It's missing though :)
> 
> Adding the tag again so it can be picked by patchwork:
> 
> Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

D'oh!

Thanks for spotting,
Krzysztof



From oliver at schinagl.nl  Wed May  4 06:17:33 2016
From: oliver at schinagl.nl (Olliver Schinagl)
Date: Wed,  4 May 2016 15:17:33 +0200
Subject: [PATCHv3] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
Message-ID: <1462367853-29912-1-git-send-email-oliver@schinagl.nl>

There are 3 kinds of OLinuXino Lime2 boards.
One without any on board storage, one with NAND storage and one with
eMMC storage. This patch adds the eMMC variant of boards.

eMMC storage is different from a regular SD card in that it is soldered
on the board and cannot be changed. Additionally, it shares pins with
the NAND module and with the second SPI port.

Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>
---
 .../boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts    | 81 ++++++++++++++++++++++
 1 file changed, 81 insertions(+)
 create mode 100644 arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts

diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
new file mode 100644
index 0000000..9680fcb
--- /dev/null
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
@@ -0,0 +1,81 @@
+ /*
+ * Copyright 2015 - Ultimaker B.V.
+ * Author Olliver Schinagl <oliver at schinagl.nl>
+ *
+ * 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.
+ */
+
+#include "sun7i-a20-olinuxino-lime2.dts"
+
+/ {
+	model = "Olimex A20-OLinuXino-LIME2-eMMC";
+
+	mmc2_pwrseq: pwrseq {
+		pinctrl-0 = <&mmc2_pins_nrst>;
+		pinctrl-names = "default";
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&pio 2 16 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&pio {
+	mmc2_pins_nrst: mmc2 at 0 {
+		allwinner,pins = "PC16";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins_a>;
+	vmmc-supply = <&reg_vcc3v3>;
+	vqmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	non-removable;
+	mmc-pwrseq = <&mmc2_pwrseq>;
+	status = "okay";
+
+	emmc: emmc at 0 {
+		reg = <0>;
+		compatible = "mmc-card";
+		broken-hpi;
+	};
+};
-- 
2.8.1



From marc.zyngier at arm.com  Wed May  4 06:21:26 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 4 May 2016 14:21:26 +0100
Subject: [PATCH v8 7/8] genirq/msi: map/unmap the MSI doorbells on
 msi_domain_alloc/free_irqs
In-Reply-To: <1461831730-5575-8-git-send-email-eric.auger@linaro.org>
References: <1461831730-5575-1-git-send-email-eric.auger@linaro.org>
 <1461831730-5575-8-git-send-email-eric.auger@linaro.org>
Message-ID: <5729F756.7060500@arm.com>

On 28/04/16 09:22, Eric Auger wrote:
> This patch handles the iommu mapping of MSI doorbells that require to
> be mapped in an iommu domain. This happens on msi_domain_alloc/free_irqs
> since this is called in code that can sleep (pci_enable/disable_msi):
> iommu_map/unmap is not stated as atomic. On msi_domain_(de)activate and
> msi_domain_set_affinity, which must be atomic, we just lookup for this
> pre-allocated/mapped IOVA.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> 
> ---
> v7 -> v8:
> - new percpu pointer type
> - exit from the irq domain hierarchy parsing on first map/unmap success
> - reset desc->irq to 0 on mapping failure
> 
> v7: creation
> ---
>  kernel/irq/msi.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 79 insertions(+), 8 deletions(-)
> 
> diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
> index 72bf4d6..d5f95e6 100644
> --- a/kernel/irq/msi.c
> +++ b/kernel/irq/msi.c
> @@ -14,6 +14,8 @@
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/msi.h>
> +#include <linux/msi-iommu.h>
> +#include <linux/iommu.h>
>  
>  /* Temparory solution for building, will be removed later */
>  #include <linux/pci.h>
> @@ -322,6 +324,56 @@ int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
>  }
>  
>  /**
> + * msi_handle_doorbell_mappings: in case the irq data corresponds to an
> + * MSI that requires iommu mapping, traverse the irq domain hierarchy
> + * to retrieve the doorbells to handle and iommu_map/unmap them according
> + * to @map boolean.
> + *
> + * @data: irq data handle
> + * @map: mapping if true, unmapping if false
> + */
> +static int msi_handle_doorbell_mappings(struct irq_data *data, bool map)
> +{
> +	for (; data; data = data->parent_data) {
> +		struct device *dev =
> +			msi_desc_to_dev(irq_data_get_msi_desc(data));
> +		struct irq_chip *chip = irq_data_get_irq_chip(data);
> +		const struct irq_chip_msi_doorbell_info *dbinfo;
> +		struct iommu_domain *domain;
> +		phys_addr_t __percpu *db_addr;
> +		dma_addr_t iova;
> +		int ret = 0, i;
> +
> +		domain = iommu_msi_domain(dev);
> +		if (!domain)
> +			continue;
> +
> +		if (!chip->msi_doorbell_info)
> +			continue;
> +
> +		dbinfo = chip->msi_doorbell_info(data);
> +		if (!dbinfo)
> +			return -EINVAL;
> +
> +		for (i = 0; i < dbinfo->nb_doorbells; i++) {
> +			db_addr = per_cpu_ptr(dbinfo->percpu_doorbells, i);
> +			if (map) {
> +				ret = iommu_msi_get_doorbell_iova(domain,
> +								  *db_addr,
> +								  dbinfo->size,
> +								  dbinfo->prot,
> +								  &iova);
> +				if (ret)
> +					return ret;
> +			} else
> +				iommu_msi_put_doorbell_iova(domain, *db_addr);
> +		}
> +		break;
> +	}
> +	return 0;
> +}

I'm really not fond of this whole loop. Could you try to decouple the
irq_data parsing (looking for a msi_doorbell_info method) from the
actual mapping/unmapping? This would make it a lot more readable.
Something along the lines of:

	struct device *dev;
	struct irq_chip *chip;
	struct iommu_domain *domain;
	const struct irq_chip_msi_doorbell_info *dbinfo;

	while (data) {
		dev = msi_desc_to_dev(irq_data_get_msi_desc(data));
		domain = iommu_msi_domain(dev);
		if (!domain)
			continue;

		chip = irq_data_get_irq_chip(data);
		if (chip->msi_doorbell_info)
			break;

		data = data->parent;
	}

	if (!data)
		return 0;

	dbinfo = chip->msi_doorbell_info(data);
	if (!dbinfo)
		return -EINVAL;

	[... handle mapping/unmapping here ...]

> +
> +/**
>   * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain
>   * @domain:	The domain to allocate from
>   * @dev:	Pointer to device struct of the device for which the interrupts
> @@ -352,17 +404,26 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
>  
>  		virq = __irq_domain_alloc_irqs(domain, virq, desc->nvec_used,
>  					       dev_to_node(dev), &arg, false);
> -		if (virq < 0) {
> -			ret = -ENOSPC;
> -			if (ops->handle_error)
> -				ret = ops->handle_error(domain, desc, ret);
> -			if (ops->msi_finish)
> -				ops->msi_finish(&arg, ret);
> -			return ret;
> -		}
> +		if (virq < 0)
> +			goto error;
>  
>  		for (i = 0; i < desc->nvec_used; i++)
>  			irq_set_msi_desc_off(virq, i, desc);
> +
> +		for (i = 0; i < desc->nvec_used; i++) {
> +			ret = msi_handle_doorbell_mappings(
> +				irq_get_irq_data(virq + i), true);

Do not be afraid of longer lines. Or if you are, create an intermediate
variable. But this kind of construct makes my brain work harder, and I
hate the feeling... ;-)

> +			if (ret)
> +				break;
> +		}
> +		if (ret) {
> +			for (; i >= 0; i--)
> +				msi_handle_doorbell_mappings(
> +					irq_get_irq_data(virq + i), false);
> +			irq_domain_free_irqs(virq, desc->nvec_used);
> +			desc->irq = 0;
> +			goto error;
> +		}
>  	}
>  
>  	if (ops->msi_finish)
> @@ -377,6 +438,13 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
>  	}
>  
>  	return 0;
> +error:
> +	ret = -ENOSPC;
> +	if (ops->handle_error)
> +		ret = ops->handle_error(domain, desc, ret);
> +	if (ops->msi_finish)
> +		ops->msi_finish(&arg, ret);
> +	return ret;
>  }
>  
>  /**
> @@ -396,6 +464,9 @@ void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
>  		 * entry. If that's the case, don't do anything.
>  		 */
>  		if (desc->irq) {
> +			msi_handle_doorbell_mappings(
> +				irq_get_irq_data(desc->irq),
> +				false);
>  			irq_domain_free_irqs(desc->irq, desc->nvec_used);
>  			desc->irq = 0;
>  		}
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From marc.zyngier at arm.com  Wed May  4 06:23:00 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 4 May 2016 14:23:00 +0100
Subject: [PATCH v8 8/8] genirq/msi: use the MSI doorbell's IOVA when
 requested
In-Reply-To: <1461831730-5575-9-git-send-email-eric.auger@linaro.org>
References: <1461831730-5575-1-git-send-email-eric.auger@linaro.org>
 <1461831730-5575-9-git-send-email-eric.auger@linaro.org>
Message-ID: <5729F7B4.7020401@arm.com>

On 28/04/16 09:22, Eric Auger wrote:
> On MSI message composition we now use the MSI doorbell's IOVA in
> place of the doorbell's PA in case the device is upstream to an
> IOMMU that requires MSI addresses to be mapped. The doorbell's
> allocation and mapping happened on an early stage (pci_enable_msi).
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> 
> ---
> v7 -> v8:
> - use iommu_msi_msg_pa_to_va
> - add WARN_ON
> 
> v6 -> v7:
> - allocation/mapping is done at an earlier stage. We now just perform
>   the iova lookup. So it is safe now to be called in a code that cannot
>   sleep. iommu_msi_set_doorbell_iova is moved in the dma-reserved-iommu
>   API: I think it cleans things up with respect to various #ifdef CONFIGS.
> 
> v5:
> - use macros to increase the readability
> - add comments
> - fix a typo that caused a compilation error if CONFIG_IOMMU_API
>   is not set
> ---
>  kernel/irq/msi.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
> index d5f95e6..835938b 100644
> --- a/kernel/irq/msi.c
> +++ b/kernel/irq/msi.c
> @@ -64,8 +64,16 @@ static int msi_compose(struct irq_data *irq_data,
>  
>  	if (erase)
>  		memset(msg, 0, sizeof(*msg));
> -	else

Nit: Braces on both sides of the 'else'.

> +	else {
> +		struct device *dev;
> +
>  		ret = irq_chip_compose_msi_msg(irq_data, msg);
> +		if (ret)
> +			return ret;
> +
> +		dev = msi_desc_to_dev(irq_data_get_msi_desc(irq_data));
> +		WARN_ON(iommu_msi_msg_pa_to_va(dev, msg));
> +	}
>  
>  	return ret;
>  }
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From andre.przywara at arm.com  Wed May  4 06:30:34 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 4 May 2016 14:30:34 +0100
Subject: [PATCH v2 18/54] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <5728CEDC.9080308@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-19-git-send-email-andre.przywara@arm.com>
 <5728CEDC.9080308@arm.com>
Message-ID: <5729F97A.1090909@arm.com>

Hi,

On 03/05/16 17:16, Marc Zyngier wrote:
> On 28/04/16 17:45, Andre Przywara wrote:
>> From: Marc Zyngier <marc.zyngier at arm.com>
>>
>> As the GICv3 virtual interface registers differ from their GICv2
>> siblings, we need different handlers for processing maintenance
>> interrupts and reading/writing to the LRs.
>> Implement the respective handler functions and connect them to
>> existing code to be called if the host is using a GICv3.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - remove outdated comment about the dist_lock
>> - add WARN_ON about LR_STATE not being 0 in maintenance interrupts
>>
>> Changelog v1 .. v2:
>> - inject the IRQ priority into the list register
>>
>>  include/linux/irqchip/arm-gic-v3.h |   1 +
>>  virt/kvm/arm/vgic/vgic-v3.c        | 169 +++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic.c           |  25 ++++--
>>  virt/kvm/arm/vgic/vgic.h           |  29 +++++++
>>  4 files changed, 219 insertions(+), 5 deletions(-)
>>  create mode 100644 virt/kvm/arm/vgic/vgic-v3.c
>>
>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>> index d5d798b..56fd2c5 100644
>> --- a/include/linux/irqchip/arm-gic-v3.h
>> +++ b/include/linux/irqchip/arm-gic-v3.h
>> @@ -275,6 +275,7 @@
>>  #define ICH_LR_ACTIVE_BIT		(1ULL << 63)
>>  #define ICH_LR_PHYS_ID_SHIFT		32
>>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
>> +#define ICH_LR_PRIORITY_SHIFT		48
>>  
>>  #define ICH_MISR_EOI			(1 << 0)
>>  #define ICH_MISR_U			(1 << 1)
>> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
>> new file mode 100644
>> index 0000000..461229b
>> --- /dev/null
>> +++ b/virt/kvm/arm/vgic/vgic-v3.c
>> @@ -0,0 +1,169 @@
>> +/*
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * 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/irqchip/arm-gic-v3.h>
>> +#include <linux/kvm.h>
>> +#include <linux/kvm_host.h>
>> +#include <linux/irqchip/arm-gic.h>
> 
> This last line is definitely a (copy-paste) bug. We should never include
> both GIC headers in the same file. Can you please drop that line and
> have the following hunk instead?
> 
> +/* These are for GICv2 emulation only */
> +#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
> +#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
> +#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
> +#define ICH_LR_VIRTUALID_MASK		(BIT_ULL(32) - 1)
> +

What about including those lines (except the last one) in arm-gic-v3.h
then? In fact they describe a property of an _GICv3_ LR, even if it is
only a compatibility feature.
That would be cleaner IMHO than repeating the definitions here in a .c
file and we would automatically get the right definitions by just
including arm-gic-v3.h.

This just compiled fine for me for both the old and new VGIC.
I can send the patch (needs to be a separate patch because it touches
the old VGIC as well) if you agree on that idea.

Cheers,
Andre.

> 
> which is similar to what we have in the old implementation, for the
> exact same reason.
> 
> Thanks,
> 
> 	M.
> 


From boris.brezillon at free-electrons.com  Wed May  4 06:35:47 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Wed, 4 May 2016 15:35:47 +0200
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <CAL_Jsq+4aL5znA3zOKdcJb+pEXhVOQthkFF6DN2+P6U37t2o6g@mail.gmail.com>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop>
 <20160503185153.5cfddc32@bbrezillon>
 <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
 <20160504113852.10a2dd84@bbrezillon>
 <CAL_Jsq+4aL5znA3zOKdcJb+pEXhVOQthkFF6DN2+P6U37t2o6g@mail.gmail.com>
Message-ID: <20160504153547.60d736bb@bbrezillon>

On Wed, 4 May 2016 08:06:10 -0500
Rob Herring <robh at kernel.org> wrote:

> On Wed, May 4, 2016 at 4:38 AM, Boris Brezillon
> <boris.brezillon at free-electrons.com> wrote:
> > Hi Rob,
> >
> > On Tue, 3 May 2016 14:11:04 -0500
> > Rob Herring <robh at kernel.org> wrote:
> >  
> >> On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
> >> <boris.brezillon at free-electrons.com> wrote:  
> >> > Hi Rob,
> >> >
> >> > On Tue, 3 May 2016 11:40:19 -0500
> >> > Rob Herring <robh at kernel.org> wrote:
> >> >  
> >> >> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:  
> >> >> > The EBI (External Bus Interface) is used to access external peripherals
> >> >> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
> >> >> > Each device is assigned a CS line and an address range and can have its
> >> >> > own configuration (timings, access mode, bus width, ...).
> >> >> > This driver provides a generic DT binding to configure a device according
> >> >> > to its requirements.
> >> >> > For specific device controllers (like the NAND one) the SMC timings
> >> >> > should be configured by the controller driver through the matrix and smc
> >> >> > syscon regmaps.  
> 
> [...]
> 
> >> >> > +EBI bus configuration associated with specific chip-select will be defined in
> >> >> > +the configs subnode. This configs node will in turn contain several subnodes
> >> >> > +named config-<cs-id>, each of them containing the following properties.  
> >> >>
> >> >> This is a bit unusual. Why not just part of the child device nodes?  
> >> >
> >> > Oh, come on! I reworked the binding because Mark complained about the
> >> > previous binding which was doing exactly what you're suggesting. Can
> >> > you please be consistent in your reviews...  
> >>
> >> No, Mark and I both have our opinions. Which part of this patch
> >> explains the history?  
> >
> > Hm, it's in patch 1/2 (just dropped the cover letter, which might not
> > be such a good idea).
> >  
> >> If the revision history is not in the patch, I'm
> >> not looking at it.
> >>
> >> My issue with it this way is that it has invented yet another way to
> >> describe timings. I would like to be consistent across external bus
> >> descriptions, but we're not very consistent to begin with though. The
> >> most common seems to be the way you first did it. But I agree that it
> >> is kind of screwy to have an intermediate node unless the controller
> >> itself has sub-blocks within it and is not the established way to
> >> describe a bus with chip selects. I would either put the properties
> >> directly in the child nodes (e.g. flash at 0,0) or put your config nodes
> >> in the device node. I'd call it timings instead of config, but that's
> >> just bikeshedding.  
> >
> > Well, it's not only describing timings (see atmel,bus-width,
> > atmel,byte-access-type, ...), but I'm fine with either names :).
> >  
> >>
> >> memory-controller at 1000 {
> >>   ...
> >>   flash at 0,0 {
> >>     timings {
> >>       ...
> >>     };
> >>   };
> >> };  
> >
> > Okay. Mark, what do you think of this approach?
> >
> > Note that one of my previous version was defining timings directly in
> > the EBI device node, and Arnd noted that doing so may cause problems
> > if one of the EBI property (or the config/timing node name) conflict
> > with the sub-device binding, which is why I decided to put the EBI
> > config definitions in a separate subnode.  
> 
> You have vendor prefixes on all the properties so I don't think a
> collision is really a problem. It's also an established pattern in
> i.MX WEIM and OMAP GPMC (which are hiding in bindings/bus/) and I
> prefer consistency.

So let's summarize that.

memory-controller at 1000 {
	...
	flash at 0,0 {
		atmel,<ebi-prop-name> = <value>;
		...
		<flash-device-prop> = <value>;
	};
};

Would everyone agree on this representation?

With this approach, it's a bit more complicated to detect the case
where we want to keep bootloader/firmware config, but it should be
doable (it's much more easier to test for the presence of a
config/timing node than verifying that either all or none of the
mandatory properties are here).

Still remains the problem mentioned by Jean-Jacques: what if the
sub-device takes 2 CS lines. Should we apply the same setting to those
slots?

> 
> >> >> > +
> >> >> > +Optional config-<cs-id> node properties:
> >> >> > +
> >> >> > +- atmel,bus-width:         width of the asynchronous device's data bus
> >> >> > +                           8, 16 or 32.
> >> >> > +                           Default to 8 when undefined.
> >> >> > +
> >> >> > +- atmel,byte-access-type   "write" or "select" (see Atmel datasheet).
> >> >> > +                           Default to "select" when undefined.
> >> >> > +
> >> >> > +- atmel,read-mode          "nrd" or "ncs".
> >> >> > +                           Default to "ncs" when undefined.
> >> >> > +
> >> >> > +- atmel,write-mode         "nwe" or "ncs".
> >> >> > +                           Default to "ncs" when undefined.
> >> >> > +
> >> >> > +- atmel,exnw-mode          "disabled", "frozen" or "ready".
> >> >> > +                           Default to "disabled" when undefined.
> >> >> > +
> >> >> > +- atmel,page-mode          enable page mode if present. The provided value
> >> >> > +                           defines the page size (supported values: 4, 8,
> >> >> > +                           16 and 32).
> >> >> > +
> >> >> > +- atmel,tdf-mode:          "normal" or "optimized". When set to  
> >> >>
> >> >> This should be boolean.  
> >> >
> >> > It was a formerly defined as a boolean, and when it's done like that we
> >> > have no way to identify whether the property was forgotten or
> >> > intentionally set to normal mode. What's the problem with this approach?  
> >>
> >> Only preference to use boolean when that is sufficient. With your
> >> argument, then we should never have booleans. You state that missing
> >> means "normal", not forgotten, so all these properties should be
> >> required with no default.
> >>
> >> BTW, I debated the same thing on the other properties, but I could see
> >> them being expanded to a 3rd mode. I don't see that here though.  
> >
> > Well, another reason I switched to a string property is because I
> > implemented hardware readout in v4, and decided to retrieve the current
> > state from the hardware and only overload the config with what was
> > defined in the DT. In this case, if we move to a boolean property we
> > can't know whether the property is missing because we want to put the
> > bus in "normal" mode or because we want to keep this config unchanged
> > (keep the bootloader/bootstrap config).  
> 
> Now you are giving yet another definition of what missing means.
> Please pick and document one:
> - Error, property missing
> - Normal mode
> - Retain firmware/bootloader settings (this should probably apply to
> all or none)

As I said, this has changed in v5. In v4 we were first retrieving the
config from the hardware and then overloading this config with the
properties defined in the DT.
This ambiguity has gone along with the approach of putting the timings
directly in the sub-device node. In this version, EBI configs are
defined directly in configs/config-X nodes, which means that
- if configs/config-X exists, then all mandatory properties should be
  defined (otherwise -EINVAL is returned), and we can fallback to
  default values for optional properties.
- if configs/config-X does not exist, we retrieve the config directly
  from the hardware

So, with this assumption, we could definitely switch to a boolean
property. The only reason I did not change that is because I find it
clearer to have both modes clearly named than having a property called
atmel,tdf-optimized.

Anyway that's not something I'm particularly attached to, so let's
switch back to a boolean property.


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


From mark.rutland at arm.com  Wed May  4 06:44:20 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 4 May 2016 14:44:20 +0100
Subject: [PATCH] perf/core / arm_pmu: special-case hetereogeneous CPUs
In-Reply-To: <20160426103346.GA20836@leverpostej>
References: <20160425175837.GB3141@leverpostej>
 <20160425190334.GK3448@twins.programming.kicks-ass.net>
 <20160426103346.GA20836@leverpostej>
Message-ID: <20160504134419.GA15849@leverpostej>

Hi,

On Tue, Apr 26, 2016 at 11:33:46AM +0100, Mark Rutland wrote:
> On Mon, Apr 25, 2016 at 09:03:34PM +0200, Peter Zijlstra wrote:
> > On Mon, Apr 25, 2016 at 06:58:37PM +0100, Mark Rutland wrote:
> > > Hi,
> > > 
> > > When booting an arm64 defconfig linux-next (next-20160422) on an ARM
> > > Juno system, I hit a WARN_ON_ONCE in perf_pmu_register (see backtrace at
> > > the end of this email).
> > > 
> > > This was introduced by commit 26657848502b7847 ("perf/core: Verify we
> > > have a single perf_hw_context PMU") where we forcefully prevent multiple
> > > PMUs from sharing perf_hw_context (with a warning), and force additional
> > > PMUs to use perf_invalid_context.
> 
> > > Are you happy to revert 26657848502b787 for the timebeing? Or to somehow
> > > predicate the check such that it doesn't adversely affect those HW PMUs?
> > 
> > I'm happy with a chicken bit for now, its already found two real issues,
> > so I'd like to keep it.
> 
> Ok, how about the below? (based on next-20160422).

Peter, any thoughts?

This is still an issue for us in next-20160504 (to which the patch still
applies).

Will, I assume that you're ok with the change to drivers/perf/arm_pmu.c.

Thanks,
Mark.

> It looks like 26657848502b7847 was on a stable branch, so I guess we
> can't fold this in. It probably makes sense for this to go the same path
> as 26657848502b7847, assuming people are happy with that and there are
> no conflicts.
> 
> Mark.
> 
> ---->8----
> From 7b1007f86d30bfed1dde21218224f119b6ad547f Mon Sep 17 00:00:00 2001
> From: Mark Rutland <mark.rutland at arm.com>
> Date: Tue, 26 Apr 2016 11:17:51 +0100
> Subject: [PATCH] perf/core / arm_pmu: special-case hetereogeneous CPUs
> 
> Commit 26657848502b7847 ("perf/core: Verify we have a single
> perf_hw_context PMU") forcefully prevents multiple PMUs from sharing
> perf_hw_context, as this generally doesn't make sense. It is a common
> bug for uncore PMUs to use perf_hw_context rather than
> perf_invalid_context, which this detects.
> 
> However, systems exist with heterogeneous CPUs (and hence heterogeneous
> HW PMUs), for which sharing perf_hw_context is necessary, and possible
> in some limited cases. To make this work we have to perform some
> gymnastics, as we did in commit 66eb579e66ecfea5 ("perf: allow for
> PMU-specific event filtering") and c904e32a69b7c779 ("arm: perf: filter
> unschedulable events").
> 
> To allow those systems to work, we must allow PMUs for heterogeneous
> CPUs to share perf_hw_context, though we must still disallow sharing
> otherwise to detect the common misuse of perf_hw_context.
> 
> This patch adds a new PERF_PMU_CAP_HETEROGENEOUS_CPUS for this, updates
> the core logic to account for this, and makes use of it in the arm_pmu
> code that is used for systems with heterogeneous CPUs. Comments are
> added to make the rationale clear and hopefully avoid accidental abuse.
> 
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> CC: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Ingo Molnar <mingo at redhat.com>
> Cc: Peter Zijlstra <peterz at infradead.org>
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-kernel at vger.kernel.org
> ---
>  drivers/perf/arm_pmu.c     | 8 ++++++++
>  include/linux/perf_event.h | 1 +
>  kernel/events/core.c       | 8 +++++++-
>  3 files changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
> index 32346b5..bbf827a 100644
> --- a/drivers/perf/arm_pmu.c
> +++ b/drivers/perf/arm_pmu.c
> @@ -836,6 +836,14 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
>  	if (!platform_get_irq(cpu_pmu->plat_device, 0))
>  		cpu_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
>  
> +	/*
> +	 * This is a CPU PMU potentially in a heterogeneous configuration (e.g.
> +	 * big.LITTLE). This is not an uncore PMU, and we have taken ctx
> +	 * sharing into account (e.g. with our pmu::filter_match callback and
> +	 * pmu::event_init group validation).
> +	 */
> +	cpu_pmu->pmu.capabilities |= PERF_PMU_CAP_HETEROGENEOUS_CPUS;
> +
>  	return 0;
>  
>  out_unregister:
> diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
> index 342cb92..18d19d6 100644
> --- a/include/linux/perf_event.h
> +++ b/include/linux/perf_event.h
> @@ -216,6 +216,7 @@ struct perf_event;
>  #define PERF_PMU_CAP_AUX_SW_DOUBLEBUF		0x08
>  #define PERF_PMU_CAP_EXCLUSIVE			0x10
>  #define PERF_PMU_CAP_ITRACE			0x20
> +#define PERF_PMU_CAP_HETEROGENEOUS_CPUS		0x40
>  
>  /**
>   * struct pmu - generic performance monitoring unit
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 1e0f117..796ee56 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -7855,7 +7855,13 @@ skip_type:
>  	if (pmu->task_ctx_nr == perf_hw_context) {
>  		static int hw_context_taken = 0;
>  
> -		if (WARN_ON_ONCE(hw_context_taken))
> +		/*
> +		 * Other than systems with heterogeneous CPUs, it never makes
> +		 * sense for two PMUs to share perf_hw_context. PMUs which are
> +		 * uncore must use perf_invalid_context.
> +		 */
> +		if (WARN_ON_ONCE(hw_context_taken &&
> +		    !(pmu->capabilities & PERF_PMU_CAP_HETEROGENEOUS_CPUS)))
>  			pmu->task_ctx_nr = perf_invalid_context;
>  
>  		hw_context_taken = 1;
> -- 
> 1.9.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


From will.deacon at arm.com  Wed May  4 06:45:31 2016
From: will.deacon at arm.com (Will Deacon)
Date: Wed, 4 May 2016 14:45:31 +0100
Subject: [GIT PULL] iommu/arm-smmu: Updates for 4.7
Message-ID: <20160504134531.GA31744@arm.com>

Hi Joerg,

Please pull the following arm-smmu updates for 4.7. The highlights are:

  * Support for 64k pages with SMMUv1 implementations (e.g MMU-401)
  * Remove open-coded 64-bit MMIO accessors
  * Initial support for 16-bit VMIDs, as supported by some ThunderX
    SMMU implementations
  * A couple of errata workarounds for silicon in the field

As a result of the MMIO accessor rework, there is an asm-generic change
here, but it has been Acked-by Arnd.

Thanks,

Will

--->8

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git for-joerg/arm-smmu/updates

for you to fetch changes up to 3ca3712a42f9e632eb41da94ca4eab4f1fb06fcb:

  iommu/arm-smmu: Clear cache lock bit of ACR (2016-05-03 18:23:04 +0100)

----------------------------------------------------------------
Peng Fan (1):
      iommu/arm-smmu: Clear cache lock bit of ACR

Robin Murphy (7):
      iommu/arm-smmu: Differentiate specific implementations
      iommu/arm-smmu: Convert ThunderX workaround to new method
      iommu/arm-smmu: Work around MMU-500 prefetch errata
      io-64-nonatomic: Add relaxed accessor variants
      iommu/arm-smmu: Tidy up 64-bit/atomic I/O accesses
      iommu/arm-smmu: Decouple context format from kernel config
      iommu/arm-smmu: Support SMMUv1 64KB supplement

Tirumalesh Chalamarla (2):
      iommu/arm-smmu: Add support for 16 bit VMID
      iommu/arm-smmu: Workaround for ThunderX erratum #27704

 Documentation/arm64/silicon-errata.txt             |   2 +
 .../devicetree/bindings/iommu/arm,smmu.txt         |   1 +
 drivers/iommu/arm-smmu.c                           | 291 +++++++++++++++------
 include/asm-generic/io.h                           |   4 +-
 include/linux/io-64-nonatomic-hi-lo.h              |  25 ++
 include/linux/io-64-nonatomic-lo-hi.h              |  25 ++
 6 files changed, 265 insertions(+), 83 deletions(-)


From will.deacon at arm.com  Wed May  4 06:46:42 2016
From: will.deacon at arm.com (Will Deacon)
Date: Wed, 4 May 2016 14:46:42 +0100
Subject: [PATCH] perf/core / arm_pmu: special-case hetereogeneous CPUs
In-Reply-To: <20160504134419.GA15849@leverpostej>
References: <20160425175837.GB3141@leverpostej>
 <20160425190334.GK3448@twins.programming.kicks-ass.net>
 <20160426103346.GA20836@leverpostej>
 <20160504134419.GA15849@leverpostej>
Message-ID: <20160504134641.GB31744@arm.com>

On Wed, May 04, 2016 at 02:44:20PM +0100, Mark Rutland wrote:
> Hi,
> 
> On Tue, Apr 26, 2016 at 11:33:46AM +0100, Mark Rutland wrote:
> > On Mon, Apr 25, 2016 at 09:03:34PM +0200, Peter Zijlstra wrote:
> > > On Mon, Apr 25, 2016 at 06:58:37PM +0100, Mark Rutland wrote:
> > > > Hi,
> > > > 
> > > > When booting an arm64 defconfig linux-next (next-20160422) on an ARM
> > > > Juno system, I hit a WARN_ON_ONCE in perf_pmu_register (see backtrace at
> > > > the end of this email).
> > > > 
> > > > This was introduced by commit 26657848502b7847 ("perf/core: Verify we
> > > > have a single perf_hw_context PMU") where we forcefully prevent multiple
> > > > PMUs from sharing perf_hw_context (with a warning), and force additional
> > > > PMUs to use perf_invalid_context.
> > 
> > > > Are you happy to revert 26657848502b787 for the timebeing? Or to somehow
> > > > predicate the check such that it doesn't adversely affect those HW PMUs?
> > > 
> > > I'm happy with a chicken bit for now, its already found two real issues,
> > > so I'd like to keep it.
> > 
> > Ok, how about the below? (based on next-20160422).
> 
> Peter, any thoughts?
> 
> This is still an issue for us in next-20160504 (to which the patch still
> applies).
> 
> Will, I assume that you're ok with the change to drivers/perf/arm_pmu.c.

Yes, they're pretty straighforward.

Will


From robh at kernel.org  Wed May  4 06:47:03 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 4 May 2016 08:47:03 -0500
Subject: [PATCH v8 4/9] pwm: pwm-tiecap: Update dt binding document to
 use proper unit address
In-Reply-To: <1462291015-1919-5-git-send-email-fcooper@ti.com>
References: <1462291015-1919-1-git-send-email-fcooper@ti.com>
 <1462291015-1919-5-git-send-email-fcooper@ti.com>
Message-ID: <20160504134703.GA4194@rob-hp-laptop>

On Tue, May 03, 2016 at 10:56:50AM -0500, Franklin S Cooper Jr wrote:
> Replace unit address from 0 to the proper physical address. Also insure
> that the unit address matches the reg property address.
> 
> Signed-off-by: Franklin S Cooper Jr <fcooper at ti.com>
> ---
>  Documentation/devicetree/bindings/pwm/pwm-tiecap.txt | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)

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

> 
> diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
> index 788da6c..0d47354 100644
> --- a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
> +++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt
> @@ -16,22 +16,22 @@ Optional properties:
>  
>  Example:
>  
> -ecap0: ecap at 0 { /* ECAP on am33xx */
> +ecap0: ecap at 48300100 { /* ECAP on am33xx */
>  	compatible = "ti,am33xx-ecap";
>  	#pwm-cells = <3>;
>  	reg = <0x48300100 0x80>;
>  	ti,hwmods = "ecap0";
>  };
>  
> -ecap0: ecap at 0 { /* ECAP on am4372 */
> +ecap0: ecap at 48300100 { /* ECAP on am4372 */
>  	compatible = "ti,am4372-ecap", "ti,am33xx-ecap";
>  	#pwm-cells = <3>;
>  	reg = <0x48300100 0x80>;
>  	ti,hwmods = "ecap0";
>  };
>  
> -ecap0: ecap at 0 { /* ECAP on da850 */
> +ecap0: ecap at 1f06000 { /* ECAP on da850 */
>  	compatible = "ti,da850-ecap", "ti,am33xx-ecap";
>  	#pwm-cells = <3>;
> -	reg = <0x306000 0x80>;
> +	reg = <0x1f06000 0x80>;
>  };
> -- 
> 2.7.0
> 


From marc.zyngier at arm.com  Wed May  4 06:54:33 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 4 May 2016 14:54:33 +0100
Subject: [PATCH v2 18/54] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <5729F97A.1090909@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-19-git-send-email-andre.przywara@arm.com>
 <5728CEDC.9080308@arm.com> <5729F97A.1090909@arm.com>
Message-ID: <5729FF19.3030205@arm.com>

On 04/05/16 14:30, Andre Przywara wrote:
> Hi,
> 
> On 03/05/16 17:16, Marc Zyngier wrote:
>> On 28/04/16 17:45, Andre Przywara wrote:
>>> From: Marc Zyngier <marc.zyngier at arm.com>
>>>
>>> As the GICv3 virtual interface registers differ from their GICv2
>>> siblings, we need different handlers for processing maintenance
>>> interrupts and reading/writing to the LRs.
>>> Implement the respective handler functions and connect them to
>>> existing code to be called if the host is using a GICv3.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>> Changelog RFC..v1:
>>> - remove outdated comment about the dist_lock
>>> - add WARN_ON about LR_STATE not being 0 in maintenance interrupts
>>>
>>> Changelog v1 .. v2:
>>> - inject the IRQ priority into the list register
>>>
>>>  include/linux/irqchip/arm-gic-v3.h |   1 +
>>>  virt/kvm/arm/vgic/vgic-v3.c        | 169 +++++++++++++++++++++++++++++++++++++
>>>  virt/kvm/arm/vgic/vgic.c           |  25 ++++--
>>>  virt/kvm/arm/vgic/vgic.h           |  29 +++++++
>>>  4 files changed, 219 insertions(+), 5 deletions(-)
>>>  create mode 100644 virt/kvm/arm/vgic/vgic-v3.c
>>>
>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>> index d5d798b..56fd2c5 100644
>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>> @@ -275,6 +275,7 @@
>>>  #define ICH_LR_ACTIVE_BIT		(1ULL << 63)
>>>  #define ICH_LR_PHYS_ID_SHIFT		32
>>>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
>>> +#define ICH_LR_PRIORITY_SHIFT		48
>>>  
>>>  #define ICH_MISR_EOI			(1 << 0)
>>>  #define ICH_MISR_U			(1 << 1)
>>> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
>>> new file mode 100644
>>> index 0000000..461229b
>>> --- /dev/null
>>> +++ b/virt/kvm/arm/vgic/vgic-v3.c
>>> @@ -0,0 +1,169 @@
>>> +/*
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * 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/irqchip/arm-gic-v3.h>
>>> +#include <linux/kvm.h>
>>> +#include <linux/kvm_host.h>
>>> +#include <linux/irqchip/arm-gic.h>
>>
>> This last line is definitely a (copy-paste) bug. We should never include
>> both GIC headers in the same file. Can you please drop that line and
>> have the following hunk instead?
>>
>> +/* These are for GICv2 emulation only */
>> +#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
>> +#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
>> +#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
>> +#define ICH_LR_VIRTUALID_MASK		(BIT_ULL(32) - 1)
>> +
> 
> What about including those lines (except the last one) in arm-gic-v3.h
> then? In fact they describe a property of an _GICv3_ LR, even if it is
> only a compatibility feature.
> That would be cleaner IMHO than repeating the definitions here in a .c
> file and we would automatically get the right definitions by just
> including arm-gic-v3.h.
> 
> This just compiled fine for me for both the old and new VGIC.
> I can send the patch (needs to be a separate patch because it touches
> the old VGIC as well) if you agree on that idea.

Sure, send the patch.

	M.
-- 
Jazz is not dead. It just smells funny...


From tixy at linaro.org  Wed May  4 07:09:54 2016
From: tixy at linaro.org (Jon Medhurst (Tixy))
Date: Wed, 04 May 2016 15:09:54 +0100
Subject: [PATCH] arm64: Make arch_randomize_brk avoid stack area
In-Reply-To: <1461848638.2848.19.camel@linaro.org>
References: <1461848638.2848.19.camel@linaro.org>
Message-ID: <1462370994.2895.11.camel@linaro.org>

When a process is created, various address randomisations could end up
colluding to place the address of brk in the stack memory. This would
mean processes making small heap based memory allocations are in danger
of having them overwriting, or overwritten by, the stack.

Another consequence, is that even for processes that make no use of
brk, the output of /proc/*/maps may show the stack area listed as
'[heap]' rather than '[stack]'. Apart from being misleading this causes
fatal errors with the Android run-time like:
"No [stack] line found in /proc/self/task/*/maps"

To prevent this problem pick a limit for brk that allows for the stack's
memory. At the same time we remove randomize_base() as that was only
used by arch_randomize_brk().

Note, in practice, since commit d1fd836dcf00 ("mm: split ET_DYN ASLR
from mmap ASLR") this problem shouldn't occur because the address chosen
for loading binaries is well clear of the stack, however, prior to that
the problem does occur because of the following...

The memory layout of a task is determined by arch_pick_mmap_layout. If
address randomisation is enabled (task has flag PF_RANDOMIZE) this sets
mmap_base to a random address at the top of task memory just below a
region calculated to allow for a stack which itself may have a random
base address. Any mmap operations that then happen which require an
address allocating will use the topdown allocation method, i.e. the
first allocated memory will be at the top of memory, just below the
area set aside for the stack.

When a relocatable binary is loaded into a new process by
load_elf_binary and randomised address are enabled, it uses a
'load_bias' of zero, so that when mmap is called to create a memory
region for it, a new address is picked (address zero not being
available). As this is the first memory region in the task, it gets the
region just below the stack, as described previously.

The loader then set's brk to the end of the elf data section, which will
be near the end of the loaded binary and then it calls
arch_randomize_brk. As this currently stands, this adds a random amount
to brk, which unfortunately may take it into the address range where the
stack lies.

Testing:

These changes have been tested on Linux v4.6-rc4 using 100000
invocations of a program [1] that can display the offset of a process's
brk...

$for i in $(seq 100000); do ./aslr --report brk ; done

This shows values of brk are evenly distributed over a 1GB range, both
before and after this change.

With Linux version 3.18 (where the collision of brk and stack can happen
and this change limits brk to avoid that) the distribution of brk values
after the change shows a slope where lower values for brk are more
common and upper values have about half the frequency of those.

[1] http://bazaar.launchpad.net/~ubuntu-bugcontrol/qa-regression-testing/master/files/2499/scripts/kernel-security/aslr/

Signed-off-by: Jon Medhurst <tixy at linaro.org>
Cc: <stable at vger.kernel.org> # 4.0 and earlier

---

Changes since RFC.
- Fixed compilation errors (finger trouble preparing original email)
- Updated commit message to included notes on testing
- Added CC stable for Linux '4.0 and earlier'

 arch/arm64/kernel/process.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 8062482..26429a0 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -382,13 +382,25 @@ unsigned long arch_align_stack(unsigned long sp)
 	return sp & ~0xf;
 }
 
-static unsigned long randomize_base(unsigned long base)
+unsigned long arch_randomize_brk(struct mm_struct *mm)
 {
+	unsigned long base = mm->brk;
 	unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
-	return randomize_range(base, range_end, 0) ? : base;
-}
+	unsigned long max_stack, range_limit;
 
-unsigned long arch_randomize_brk(struct mm_struct *mm)
-{
-	return randomize_base(mm->brk);
+	/*
+	 * Determine how much room we need to leave available for the stack.
+	 * We limit this to a reasonable value, because extremely large or
+	 * unlimited stacks are always going to bump up against brk at some
+	 * point and we don't want to fail to randomise brk in those cases.
+	 */
+	max_stack = rlimit(RLIMIT_STACK);
+	if (max_stack > SZ_128M)
+		max_stack = SZ_128M;
+
+	range_limit = mm->start_stack - max_stack - 1;
+	if (range_end > range_limit)
+		range_end = range_limit;
+
+	return randomize_range(base, range_end, 0) ? : base;
 }
-- 
2.1.4




From matthijsvanduin at gmail.com  Wed May  4 07:09:40 2016
From: matthijsvanduin at gmail.com (Matthijs van Duin)
Date: Wed, 4 May 2016 16:09:40 +0200
Subject: [PATCH v2 2/3] ARM: DRA7x: dts: Update the OSC_32K_CLK frequency
In-Reply-To: <5728E0BC.3080509@ti.com>
References: <20160427171658.GA5995@atomide.com>
 <1462209123-7332-1-git-send-email-Linux.HWI@garmin.com>
 <1462209123-7332-3-git-send-email-Linux.HWI@garmin.com>
 <57285E66.2000708@ti.com>
 <5728A81F.4050906@garmin.com> <20160503164323.GN5995@atomide.com>
 <5728E0BC.3080509@ti.com>
Message-ID: <CAALWOA_4bqWo-izirjQUKb-YjiyBJwAdek_z60kjnEnj74Er7w@mail.gmail.com>

On 3 May 2016 at 18:43, Tony Lindgren <tony at atomide.com> wrote:
> Does a fixed divider calculation of input * (32768 / 27e6) make sense
> here too as pointed out earlier by Matthijs for the ti81xx?

That was an actual fractional divider, i.e. the output clock would be
exactly that ratio of the input clock, which would therefore yield
32768 Hz if the default crystal is used for the main osc.

It makes no sense to use it to describe a wobbly RC osc.


On 3 May 2016 at 19:32, Tero Kristo <t-kristo at ti.com> wrote:
> Also, as it is security related, this is kind of sensitive area to discuss publicly.

Don't be silly. The only sense in which this clock is "security
related" is because it's used for the secure watchdog, and the reason
to use it despite its inaccuracy is completely obvious: an internal rc
osc can't be easily manipulated by an external attacker. I see no
reason to act all cloak-and-dagger about this.

(This seems to be a general theme to conceal "security related" things
from public documentation. If I were an HS customer I'd actually be
concerned about such behaviour since it would seem to indicate a lack
of confidence in one's security architecture.)

Matthijs


From david.wu at rock-chips.com  Wed May  4 07:13:05 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed,  4 May 2016 22:13:05 +0800
Subject: [PATCH v7 0/9] add i2c driver supported for rk3399
Message-ID: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>

There are two points differert from others:
 - new method to caculate i2c timings for rk3399
 - pclk and function clk are separated at rk3399

David Wu (9):
  i2c: rk3x: add documentation to fields in "struct rk3x_i2c"
  i2c: rk3x: use struct "rk3x_i2c_calced_timings"
  i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd()
  i2c: rk3x: Move setting STATE_START and add STATE_SETUP
  i2c: rk3x: Change SoC data to not use array
  i2c: rk3x: Move spec timing data to "static const" structs
  dt-bindings: i2c: rk3x: add support for rk3399
  i2c: rk3x: add i2c support for rk3399 soc
  i2c: rk3x: support fast-mode plus for rk3399

 Documentation/devicetree/bindings/i2c/i2c-rk3x.txt |  16 +-
 drivers/i2c/busses/i2c-rk3x.c                      | 482 +++++++++++++++++----
 2 files changed, 419 insertions(+), 79 deletions(-)

-- 
1.9.1




From david.wu at rock-chips.com  Wed May  4 07:13:06 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed,  4 May 2016 22:13:06 +0800
Subject: [PATCH v7 1/9] i2c: rk3x: add documentation to fields in "struct
 rk3x_i2c"
In-Reply-To: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462371194-5809-2-git-send-email-david.wu@rock-chips.com>

Signed-off-by: David Wu <david.wu at rock-chips.com>
---
Change in v7:
- none

 drivers/i2c/busses/i2c-rk3x.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 80bed02..7e45d51 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -90,6 +90,26 @@ struct rk3x_i2c_soc_data {
 	int grf_offset;
 };
 
+/**
+ * struct rk3x_i2c - private data of the controller
+ * @adap: corresponding I2C adapter
+ * @dev: device for this controller
+ * @soc_data: related soc data struct
+ * @regs: virtual memory area
+ * @clk: clock of i2c bus
+ * @clk_rate_nb: i2c clk rate change notify
+ * @t: I2C known timing information
+ * @lock: spinlock for the i2c bus
+ * @wait: the waitqueue to wait for i2c transfer
+ * @busy: the condition for the event to wait for
+ * @msg: current i2c message
+ * @addr: addr of i2c slave device
+ * @mode: mode of i2c transfer
+ * @is_last_msg: flag determines whether it is the last msg in this transfer
+ * @state: state of i2c transfer
+ * @processed: byte length which has been send or received
+ * @error: error code for i2c transfer
+ */
 struct rk3x_i2c {
 	struct i2c_adapter adap;
 	struct device *dev;
@@ -116,7 +136,7 @@ struct rk3x_i2c {
 
 	/* I2C state machine */
 	enum rk3x_i2c_state state;
-	unsigned int processed; /* sent/received bytes */
+	unsigned int processed;
 	int error;
 };
 
-- 
1.9.1




From david.wu at rock-chips.com  Wed May  4 07:13:07 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed,  4 May 2016 22:13:07 +0800
Subject: [PATCH v7 2/9] i2c: rk3x: use struct "rk3x_i2c_calced_timings"
In-Reply-To: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462371194-5809-3-git-send-email-david.wu@rock-chips.com>

Signed-off-by: David Wu <david.wu at rock-chips.com>
---
Change in v7:
- none

 drivers/i2c/busses/i2c-rk3x.c | 55 +++++++++++++++++++++++++------------------
 1 file changed, 32 insertions(+), 23 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 7e45d51..1e2677a 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -75,6 +75,16 @@ enum {
 #define WAIT_TIMEOUT      1000 /* ms */
 #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */
 
+/**
+ * struct rk3x_i2c_calced_timings:
+ * @div_low: Divider output for low
+ * @div_high: Divider output for high
+ */
+struct rk3x_i2c_calced_timings {
+	unsigned long div_low;
+	unsigned long div_high;
+};
+
 enum rk3x_i2c_state {
 	STATE_IDLE,
 	STATE_START,
@@ -454,9 +464,8 @@ out:
  * Calculate divider values for desired SCL frequency
  *
  * @clk_rate: I2C input clock rate
- * @t: Known I2C timing information.
- * @div_low: Divider output for low
- * @div_high: Divider output for high
+ * @t: Known I2C timing information
+ * @t_calc: Caculated rk3x private timings that would be written into regs
  *
  * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
  * a best-effort divider value is returned in divs. If the target rate is
@@ -464,8 +473,7 @@ out:
  */
 static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 			      struct i2c_timings *t,
-			      unsigned long *div_low,
-			      unsigned long *div_high)
+			      struct rk3x_i2c_calced_timings *t_calc)
 {
 	unsigned long spec_min_low_ns, spec_min_high_ns;
 	unsigned long spec_setup_start, spec_max_data_hold_ns;
@@ -572,8 +580,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 		 * Time needed to meet hold requirements is important.
 		 * Just use that.
 		 */
-		*div_low = min_low_div;
-		*div_high = min_high_div;
+		t_calc->div_low = min_low_div;
+		t_calc->div_high = min_high_div;
 	} else {
 		/*
 		 * We've got to distribute some time among the low and high
@@ -602,25 +610,25 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 
 		/* Give low the "ideal" and give high whatever extra is left */
 		extra_low_div = ideal_low_div - min_low_div;
-		*div_low = ideal_low_div;
-		*div_high = min_high_div + (extra_div - extra_low_div);
+		t_calc->div_low = ideal_low_div;
+		t_calc->div_high = min_high_div + (extra_div - extra_low_div);
 	}
 
 	/*
 	 * Adjust to the fact that the hardware has an implicit "+1".
 	 * NOTE: Above calculations always produce div_low > 0 and div_high > 0.
 	 */
-	*div_low = *div_low - 1;
-	*div_high = *div_high - 1;
+	t_calc->div_low--;
+	t_calc->div_high--;
 
 	/* Maximum divider supported by hw is 0xffff */
-	if (*div_low > 0xffff) {
-		*div_low = 0xffff;
+	if (t_calc->div_low > 0xffff) {
+		t_calc->div_low = 0xffff;
 		ret = -EINVAL;
 	}
 
-	if (*div_high > 0xffff) {
-		*div_high = 0xffff;
+	if (t_calc->div_high > 0xffff) {
+		t_calc->div_high = 0xffff;
 		ret = -EINVAL;
 	}
 
@@ -630,19 +638,21 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
 {
 	struct i2c_timings *t = &i2c->t;
-	unsigned long div_low, div_high;
+	struct rk3x_i2c_calced_timings calc;
 	u64 t_low_ns, t_high_ns;
 	int ret;
 
-	ret = rk3x_i2c_calc_divs(clk_rate, t, &div_low, &div_high);
+	ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
 	WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
 
 	clk_enable(i2c->clk);
-	i2c_writel(i2c, (div_high << 16) | (div_low & 0xffff), REG_CLKDIV);
+	i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
+		   REG_CLKDIV);
 	clk_disable(i2c->clk);
 
-	t_low_ns = div_u64(((u64)div_low + 1) * 8 * 1000000000, clk_rate);
-	t_high_ns = div_u64(((u64)div_high + 1) * 8 * 1000000000, clk_rate);
+	t_low_ns = div_u64(((u64)calc.div_low + 1) * 8 * 1000000000, clk_rate);
+	t_high_ns = div_u64(((u64)calc.div_high + 1) * 8 * 1000000000,
+			    clk_rate);
 	dev_dbg(i2c->dev,
 		"CLK %lukhz, Req %uns, Act low %lluns high %lluns\n",
 		clk_rate / 1000,
@@ -672,12 +682,11 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
 {
 	struct clk_notifier_data *ndata = data;
 	struct rk3x_i2c *i2c = container_of(nb, struct rk3x_i2c, clk_rate_nb);
-	unsigned long div_low, div_high;
+	struct rk3x_i2c_calced_timings calc;
 
 	switch (event) {
 	case PRE_RATE_CHANGE:
-		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t,
-				       &div_low, &div_high) != 0)
+		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &calc) != 0)
 			return NOTIFY_STOP;
 
 		/* scale up */
-- 
1.9.1




From david.wu at rock-chips.com  Wed May  4 07:13:09 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed,  4 May 2016 22:13:09 +0800
Subject: [PATCH v7 4/9] i2c: rk3x: Move setting STATE_START and add STATE_SETUP
In-Reply-To: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462371194-5809-5-git-send-email-david.wu@rock-chips.com>

Signed-off-by: David Wu <david.wu at rock-chips.com>
---
Change in v7:
- none

 drivers/i2c/busses/i2c-rk3x.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 9eeb4e5..0838fcf 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -87,6 +87,7 @@ struct rk3x_i2c_calced_timings {
 
 enum rk3x_i2c_state {
 	STATE_IDLE,
+	STATE_SETUP,
 	STATE_START,
 	STATE_READ,
 	STATE_WRITE,
@@ -174,6 +175,7 @@ static void rk3x_i2c_start(struct rk3x_i2c *i2c)
 {
 	u32 val;
 
+	i2c->state = STATE_START;
 	i2c_writel(i2c, REG_INT_START, REG_IEN);
 
 	/* enable adapter with correct mode, send START condition */
@@ -451,6 +453,7 @@ static irqreturn_t rk3x_i2c_irq(int irqno, void *dev_id)
 		rk3x_i2c_handle_stop(i2c, ipd);
 		break;
 	case STATE_IDLE:
+	case STATE_SETUP:
 		break;
 	}
 
@@ -781,7 +784,7 @@ static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num)
 
 	i2c->addr = msgs[0].addr;
 	i2c->busy = true;
-	i2c->state = STATE_START;
+	i2c->state = STATE_SETUP;
 	i2c->processed = 0;
 	i2c->error = 0;
 
-- 
1.9.1




From david.wu at rock-chips.com  Wed May  4 07:13:08 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed,  4 May 2016 22:13:08 +0800
Subject: [PATCH v7 3/9] i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd()
In-Reply-To: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462371194-5809-4-git-send-email-david.wu@rock-chips.com>

Call rk3x_i2c_setup() before rk3x_i2c_start()
and the last thing in setup was to clean the IPD,
so no reason to do it at the beginning of start.

Signed-off-by: David Wu <david.wu at rock-chips.com>
---
Change in v7:
- none

 drivers/i2c/busses/i2c-rk3x.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 1e2677a..9eeb4e5 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -174,7 +174,6 @@ static void rk3x_i2c_start(struct rk3x_i2c *i2c)
 {
 	u32 val;
 
-	rk3x_i2c_clean_ipd(i2c);
 	i2c_writel(i2c, REG_INT_START, REG_IEN);
 
 	/* enable adapter with correct mode, send START condition */
-- 
1.9.1




From panand at redhat.com  Wed May  4 07:14:49 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 4 May 2016 19:44:49 +0530
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <20160503171602.GA2518@roeck-us.net>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <5728A7C3.4010001@roeck-us.net>
 <20160503143856.GE13045@dhcppc6.redhat.com>
 <5728BEC4.6050603@codeaurora.org>
 <20160503155141.GF13045@dhcppc6.redhat.com>
 <20160503171602.GA2518@roeck-us.net>
Message-ID: <20160504141449.GG13045@dhcppc6.redhat.com>

Hi Guenter,

On 03/05/2016:10:16:02 AM, Guenter Roeck wrote:
> On Tue, May 03, 2016 at 09:21:41PM +0530, Pratyush Anand wrote:
> > On 03/05/2016:10:07:48 AM, Timur Tabi wrote:
> > > Pratyush Anand wrote:
> > > >In fact after supporting max_hw_heartbeat_ms, there should be no change for
> > > >action=0 functionally. However, we would still need some changes for action=1.
> > > 
> > > IMHO, action=1 is more of a debugging option, and not something that would
> > > be used normally.  I would need to see some evidence that real users want to
> > > have action=1 and a longer timeout.
> > > 
> > If action=1 need to be used effectively, then we should have something which
> > would help to increase timeout values.
> > 
> > Currently you have only 10 second to execute secondary kernel, which might not
> > be sufficient.
> > 
> Previously the argument was that the 10 seconds (assuming the clock runs at
> maximum speed) would not be sufficient to load the watchdog application. Now it

May be you meant "would be sufficient". OK..let me clarify on it.

Currently it takes 7-8 second from the point 1st kernel panics to the point
second kernel boots. (Given, we have D-cache enabled in kexec-tools, for which
community is not yet agreed), anyway..so, it is safe for me as of now. But,
there is only 2-3 second margin. So, I am not sure if all sort of secondary
kernel will be able to make it in that time.

Following minimal code will be able to extend timeout for secondary kernel, and
I do not see anything wrong in it. We are anyway, panicking in ISR, so what
could be disadvantage if we write a wdt register just before panicking?

--- a/drivers/watchdog/sbsa_gwdt.c
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -221,6 +221,13 @@ static int sbsa_gwdt_stop(struct watchdog_device *wdd)
 
static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
{
+    struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
+    struct watchdog_device *wdd = &gwdt->wdd;
+    u64 timeout = (u64)gwdt->clk * wdd->timeout;
+
+    writeq(timeout + arch_counter_get_cntvct(),
+                    gwdt->control_base + SBSA_GWDT_WCV);
+
     panic(WATCHDOG_NAME " timeout");
      
             return IRQ_HANDLED;

~Pratyush


From andre.przywara at arm.com  Wed May  4 07:21:29 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed,  4 May 2016 15:21:29 +0100
Subject: [PATCH] KVM: arm/arm64: move GICv2 emulation defines into arm-gic-v3.h
In-Reply-To: <5729FF19.3030205@arm.com>
References: <5729FF19.3030205@arm.com>
Message-ID: <1462371689-26046-1-git-send-email-andre.przywara@arm.com>

As (some) GICv3 hosts can emulate a GICv2, some GICv2 specific masks
for the list register definition also apply to GICv3 LRs.
At the moment we have those definitions in the KVM VGICv3
implementation, so let's move them into the GICv3 header file to
have them automatically defined.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
... and then just remove the #include <arm-gic.h> from vgic/vgic-v3.c.

Does that make sense?

Cheers,
Andre.

 include/linux/irqchip/arm-gic-v3.h | 5 +++++
 virt/kvm/arm/vgic-v3.c             | 8 +-------
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 56fd2c5..35e93cf 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -277,6 +277,11 @@
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
 #define ICH_LR_PRIORITY_SHIFT		48
 
+/* These are for GICv2 emulation only */
+#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
+#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
+#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
+
 #define ICH_MISR_EOI			(1 << 0)
 #define ICH_MISR_U			(1 << 1)
 
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index 999bdc6..9c5cfc2 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -31,12 +31,6 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmu.h>
 
-/* These are for GICv2 emulation only */
-#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
-#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
-#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
-#define ICH_LR_VIRTUALID_MASK		(BIT_ULL(32) - 1)
-
 static u32 ich_vtr_el2;
 
 static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
@@ -45,7 +39,7 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
 	u64 val = vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr];
 
 	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
-		lr_desc.irq = val & ICH_LR_VIRTUALID_MASK;
+		lr_desc.irq = val & ICH_LR_VIRTUAL_ID_MASK;
 	else
 		lr_desc.irq = val & GICH_LR_VIRTUALID;
 
-- 
2.7.3



From timur at codeaurora.org  Wed May  4 07:21:43 2016
From: timur at codeaurora.org (Timur Tabi)
Date: Wed, 4 May 2016 09:21:43 -0500
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <20160504141449.GG13045@dhcppc6.redhat.com>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <5728A7C3.4010001@roeck-us.net> <20160503143856.GE13045@dhcppc6.redhat.com>
 <5728BEC4.6050603@codeaurora.org> <20160503155141.GF13045@dhcppc6.redhat.com>
 <20160503171602.GA2518@roeck-us.net>
 <20160504141449.GG13045@dhcppc6.redhat.com>
Message-ID: <572A0577.1070000@codeaurora.org>

Pratyush Anand wrote:
> static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
> {
> +    struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
> +    struct watchdog_device *wdd = &gwdt->wdd;
> +    u64 timeout = (u64)gwdt->clk * wdd->timeout;
> +
> +    writeq(timeout + arch_counter_get_cntvct(),
> +                    gwdt->control_base + SBSA_GWDT_WCV);
> +
>       panic(WATCHDOG_NAME " timeout");

I'm on the fence about this.

On one hand, I have always opposed the idea that the interrupt handler 
needs to function properly in order for the timeout to be correct.  Fu's 
original patch required this for every timeout.

The current code, however, only uses the interrupt when action=1.  In 
this case, WCV is only reprogrammed in order to prevent the system from 
resetting during the kexec.  Technically, the watchdog timeout has 
already been handled.

However, this should be unnecessary, because it can't be a problem 
that's unique to the SBSA watchdog.  Every system that kexecs another 
kernel needs to be able to handle a watchdog timeout.  Shouldn't the 
kexec code already ping or disable the watchdog?  We need a 
cross-platform solution.  Drivers should not need to do this.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.


From marc.zyngier at arm.com  Wed May  4 07:28:25 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 4 May 2016 15:28:25 +0100
Subject: [PATCH] KVM: arm/arm64: move GICv2 emulation defines into
 arm-gic-v3.h
In-Reply-To: <1462371689-26046-1-git-send-email-andre.przywara@arm.com>
References: <5729FF19.3030205@arm.com>
 <1462371689-26046-1-git-send-email-andre.przywara@arm.com>
Message-ID: <572A0709.9070000@arm.com>

On 04/05/16 15:21, Andre Przywara wrote:
> As (some) GICv3 hosts can emulate a GICv2, some GICv2 specific masks
> for the list register definition also apply to GICv3 LRs.
> At the moment we have those definitions in the KVM VGICv3
> implementation, so let's move them into the GICv3 header file to
> have them automatically defined.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Acked-by: Marc Zyngier <marc.zyngier at arm.com>

	M.

> ---
> ... and then just remove the #include <arm-gic.h> from vgic/vgic-v3.c.
> 
> Does that make sense?

Definitely.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From david.wu at rock-chips.com  Wed May  4 07:33:38 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed,  4 May 2016 22:33:38 +0800
Subject: [PATCH v7 5/9] i2c: rk3x: Change SoC data to not use array
In-Reply-To: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462372418-6349-1-git-send-email-david.wu@rock-chips.com>

Signed-off-by: David Wu <david.wu at rock-chips.com>
---
 drivers/i2c/busses/i2c-rk3x.c | 38 ++++++++++++++++++++++++++++++--------
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 0838fcf..9686c81 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -867,17 +867,39 @@ static const struct i2c_algorithm rk3x_i2c_algorithm = {
 	.functionality		= rk3x_i2c_func,
 };
 
-static struct rk3x_i2c_soc_data soc_data[3] = {
-	{ .grf_offset = 0x154 }, /* rk3066 */
-	{ .grf_offset = 0x0a4 }, /* rk3188 */
-	{ .grf_offset = -1 },    /* no I2C switching needed */
+static const struct rk3x_i2c_soc_data rk3066_soc_data = {
+	.grf_offset = 0x154,
+};
+
+static const struct rk3x_i2c_soc_data rk3188_soc_data = {
+	.grf_offset = 0x0a4,
+};
+
+static const struct rk3x_i2c_soc_data rk3228_soc_data = {
+	.grf_offset = -1,
+};
+
+static const struct rk3x_i2c_soc_data rk3288_soc_data = {
+	.grf_offset = -1,
 };
 
 static const struct of_device_id rk3x_i2c_match[] = {
-	{ .compatible = "rockchip,rk3066-i2c", .data = (void *)&soc_data[0] },
-	{ .compatible = "rockchip,rk3188-i2c", .data = (void *)&soc_data[1] },
-	{ .compatible = "rockchip,rk3228-i2c", .data = (void *)&soc_data[2] },
-	{ .compatible = "rockchip,rk3288-i2c", .data = (void *)&soc_data[2] },
+	{
+		.compatible = "rockchip,rk3066-i2c",
+		.data = (void *)&rk3066_soc_data
+	},
+	{
+		.compatible = "rockchip,rk3188-i2c",
+		.data = (void *)&rk3188_soc_data
+	},
+	{
+		.compatible = "rockchip,rk3228-i2c",
+		.data = (void *)&rk3228_soc_data
+	},
+	{
+		.compatible = "rockchip,rk3288-i2c",
+		.data = (void *)&rk3288_soc_data
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, rk3x_i2c_match);
-- 
1.9.1




From david.wu at rock-chips.com  Wed May  4 07:34:32 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed,  4 May 2016 22:34:32 +0800
Subject: [PATCH v7 6/9] i2c: rk3x: Move spec timing data to "static const"
 structs
In-Reply-To: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462372472-6396-1-git-send-email-david.wu@rock-chips.com>

Signed-off-by: David Wu <david.wu at rock-chips.com>
---
 drivers/i2c/busses/i2c-rk3x.c | 100 ++++++++++++++++++++++++++++++------------
 1 file changed, 72 insertions(+), 28 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 9686c81..408f9ab 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -76,6 +76,51 @@ enum {
 #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */
 
 /**
+ * struct i2c_spec_values:
+ * @min_hold_start_ns: min hold time (repeated) START condition
+ * @min_low_ns: min LOW period of the SCL clock
+ * @min_high_ns: min HIGH period of the SCL cloc
+ * @min_setup_start_ns: min set-up time for a repeated START conditio
+ * @max_data_hold_ns: max data hold time
+ * @min_data_setup_ns: min data set-up time
+ * @min_setup_stop_ns: min set-up time for STOP condition
+ * @min_hold_buffer_ns: min bus free time between a STOP and
+ * START condition
+ */
+struct i2c_spec_values {
+	unsigned long min_hold_start_ns;
+	unsigned long min_low_ns;
+	unsigned long min_high_ns;
+	unsigned long min_setup_start_ns;
+	unsigned long max_data_hold_ns;
+	unsigned long min_data_setup_ns;
+	unsigned long min_setup_stop_ns;
+	unsigned long min_hold_buffer_ns;
+};
+
+static const struct i2c_spec_values standard_mode_spec = {
+	.min_hold_start_ns = 4000,
+	.min_low_ns = 4700,
+	.min_high_ns = 4000,
+	.min_setup_start_ns = 4700,
+	.max_data_hold_ns = 3450,
+	.min_data_setup_ns = 250,
+	.min_setup_stop_ns = 4000,
+	.min_hold_buffer_ns = 4700,
+};
+
+static const struct i2c_spec_values fast_mode_spec = {
+	.min_hold_start_ns = 600,
+	.min_low_ns = 1300,
+	.min_high_ns = 600,
+	.min_setup_start_ns = 600,
+	.max_data_hold_ns = 900,
+	.min_data_setup_ns = 100,
+	.min_setup_stop_ns = 600,
+	.min_hold_buffer_ns = 1300,
+};
+
+/**
  * struct rk3x_i2c_calced_timings:
  * @div_low: Divider output for low
  * @div_high: Divider output for high
@@ -463,6 +508,21 @@ out:
 }
 
 /**
+ * Get timing values of I2C specification
+ *
+ * @speed: Desired SCL frequency
+ *
+ * Returns: Matched i2c spec values.
+ */
+static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
+{
+	if (speed <= 100000)
+		return &standard_mode_spec;
+	else
+		return &fast_mode_spec;
+}
+
+/**
  * Calculate divider values for desired SCL frequency
  *
  * @clk_rate: I2C input clock rate
@@ -477,10 +537,6 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 			      struct i2c_timings *t,
 			      struct rk3x_i2c_calced_timings *t_calc)
 {
-	unsigned long spec_min_low_ns, spec_min_high_ns;
-	unsigned long spec_setup_start, spec_max_data_hold_ns;
-	unsigned long data_hold_buffer_ns;
-
 	unsigned long min_low_ns, min_high_ns;
 	unsigned long max_low_ns, min_total_ns;
 
@@ -492,6 +548,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	unsigned long min_div_for_hold, min_total_div;
 	unsigned long extra_div, extra_low_div, ideal_low_div;
 
+	unsigned long data_hold_buffer_ns = 50;
+	const struct i2c_spec_values *spec;
 	int ret = 0;
 
 	/* Only support standard-mode and fast-mode */
@@ -514,22 +572,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	 *	 This is because the i2c host on Rockchip holds the data line
 	 *	 for half the low time.
 	 */
-	if (t->bus_freq_hz <= 100000) {
-		/* Standard-mode */
-		spec_min_low_ns = 4700;
-		spec_setup_start = 4700;
-		spec_min_high_ns = 4000;
-		spec_max_data_hold_ns = 3450;
-		data_hold_buffer_ns = 50;
-	} else {
-		/* Fast-mode */
-		spec_min_low_ns = 1300;
-		spec_setup_start = 600;
-		spec_min_high_ns = 600;
-		spec_max_data_hold_ns = 900;
-		data_hold_buffer_ns = 50;
-	}
-	min_high_ns = t->scl_rise_ns + spec_min_high_ns;
+	spec = rk3x_i2c_get_spec(t->bus_freq_hz);
+	min_high_ns = t->scl_rise_ns + spec->min_high_ns;
 
 	/*
 	 * Timings for repeated start:
@@ -539,14 +583,14 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	 * We need to account for those rules in picking our "high" time so
 	 * we meet tSU;STA and tHD;STA times.
 	 */
-	min_high_ns = max(min_high_ns,
-		DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start) * 1000, 875));
-	min_high_ns = max(min_high_ns,
-		DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start +
-			      t->sda_fall_ns + spec_min_high_ns), 2));
-
-	min_low_ns = t->scl_fall_ns + spec_min_low_ns;
-	max_low_ns = spec_max_data_hold_ns * 2 - data_hold_buffer_ns;
+	min_high_ns = max(min_high_ns, DIV_ROUND_UP(
+		(t->scl_rise_ns + spec->min_setup_start_ns) * 1000, 875));
+	min_high_ns = max(min_high_ns, DIV_ROUND_UP(
+		(t->scl_rise_ns + spec->min_setup_start_ns + t->sda_fall_ns +
+		spec->min_high_ns), 2));
+
+	min_low_ns = t->scl_fall_ns + spec->min_low_ns;
+	max_low_ns =  spec->max_data_hold_ns * 2 - data_hold_buffer_ns;
 	min_total_ns = min_low_ns + min_high_ns;
 
 	/* Adjust to avoid overflow */
-- 
1.9.1




From david.wu at rock-chips.com  Wed May  4 07:35:23 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed,  4 May 2016 22:35:23 +0800
Subject: [PATCH v7 7/9] dt-bindings: i2c: rk3x: add support for rk3399
In-Reply-To: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462372523-6444-1-git-send-email-david.wu@rock-chips.com>

The bus clock and function clock are separated at rk3399,
and others use one clock as the bus clock and function clock.

Signed-off-by: David Wu <david.wu at rock-chips.com>
---
 Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
index 0b4a85f..82b6f6b 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
@@ -6,10 +6,20 @@ RK3xxx SoCs.
 Required properties :
 
  - reg : Offset and length of the register set for the device
- - compatible : should be "rockchip,rk3066-i2c", "rockchip,rk3188-i2c",
-		"rockchip,rk3228-i2c" or "rockchip,rk3288-i2c".
+ - compatible: should be one of the followings
+   - "rockchip,rk3066-i2c": for rk3066
+   - "rockchip,rk3188-i2c": for rk3188
+   - "rockchip,rk3228-i2c": for rk3228
+   - "rockchip,rk3288-i2c": for rk3288
+   - "rockchip,rk3399-i2c": for rk3399
  - interrupts : interrupt number
- - clocks : parent clock
+ - clocks: See ../clock/clock-bindings.txt
+   - For older hardware (rk3066, rk3188, rk3228, rk3288):
+     - There is one clock that's used both to derive the functional clock
+       for the device and as the bus clock.  REQUIRED.
+   - For newer hardware (rk3399): specify by name
+     - "i2c": REQUIRED. This is used to derive the functional clock.
+     - "pclk": REQUIRED. This is the bus clock.equired on RK3066, RK3188 :
 
 Required on RK3066, RK3188 :
 
-- 
1.9.1




From david.wu at rock-chips.com  Wed May  4 07:36:49 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed,  4 May 2016 22:36:49 +0800
Subject: [PATCH v7 8/9] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462372609-6535-1-git-send-email-david.wu@rock-chips.com>

- new method to caculate i2c timings for rk3399:
  There was an timing issue about "repeated start" time at the I2C
  controller of version0, controller appears to drop SDA at .875x (7/8)
  programmed clk high. On version 1 of the controller, the rule(.875x)
  isn't enough to meet tSU;STA
  requirements on 100k's Standard-mode. To resolve this issue,
  sda_update_config, start_setup_config and stop_setup_config for I2C
  timing information are added, new rules are designed to calculate
  the timing information at new v1.
- pclk and function clk are separated at rk3399

Signed-off-by: David Wu <david.wu at rock-chips.com>
---
Changes in v7:
- transform into a 9 series patches (Doug)
- drop highspeed with mastercode, and support fast-mode plus (Doug)

Changes in v6:
- add master code send for HS mode
- use assigned-clocks mechanism for clock rate set form DT (Heiko)

Changes in v5:
- use compatible to seperate from different version
- can caculate highspeed clk rate

Changes in v4:
- pclk and sclk are treated individually
- use switch-case to seperate from different version (Andy)
- fix dead loop form Julia's notice

Change in v3:
- Too many arguments for ops func, use struct for them (Andy)

 drivers/i2c/busses/i2c-rk3x.c | 266 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 243 insertions(+), 23 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 408f9ab..47368c4 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -58,6 +58,10 @@ enum {
 #define REG_CON_LASTACK   BIT(5) /* 1: send NACK after last received byte */
 #define REG_CON_ACTACK    BIT(6) /* 1: stop if NACK is received */
 
+#define REG_CON_SDA_CFG(cfg) ((cfg) << 8)
+#define REG_CON_STA_CFG(cfg) ((cfg) << 12)
+#define REG_CON_STO_CFG(cfg) ((cfg) << 14)
+
 /* REG_MRXADDR bits */
 #define REG_MRXADDR_VALID(x) BIT(24 + (x)) /* [x*8+7:x*8] of MRX[R]ADDR valid */
 
@@ -124,10 +128,15 @@ static const struct i2c_spec_values fast_mode_spec = {
  * struct rk3x_i2c_calced_timings:
  * @div_low: Divider output for low
  * @div_high: Divider output for high
+ * @tuning: Used to adjust setup/hold data time,
+ * setup/hold start time and setup stop time for
+ * v1's calc_timings, the tuning should all be 0
+ * for old hardware anyone using v0's calc_timings.
  */
 struct rk3x_i2c_calced_timings {
 	unsigned long div_low;
 	unsigned long div_high;
+	unsigned int tuning;
 };
 
 enum rk3x_i2c_state {
@@ -141,9 +150,12 @@ enum rk3x_i2c_state {
 
 /**
  * @grf_offset: offset inside the grf regmap for setting the i2c type
+ * @calc_timings: Callback function for i2c timing information calculated
  */
 struct rk3x_i2c_soc_data {
 	int grf_offset;
+	int (*calc_timings)(unsigned long, struct i2c_timings *,
+			    struct rk3x_i2c_calced_timings *);
 };
 
 /**
@@ -152,9 +164,11 @@ struct rk3x_i2c_soc_data {
  * @dev: device for this controller
  * @soc_data: related soc data struct
  * @regs: virtual memory area
- * @clk: clock of i2c bus
+ * @clk: function clk for rk3399 or function & Bus clks for others
+ * @pclk: Bus clk for rk3399
  * @clk_rate_nb: i2c clk rate change notify
  * @t: I2C known timing information
+ * @t_calc: I2C timing information need to be calculated
  * @lock: spinlock for the i2c bus
  * @wait: the waitqueue to wait for i2c transfer
  * @busy: the condition for the event to wait for
@@ -174,10 +188,12 @@ struct rk3x_i2c {
 	/* Hardware resources */
 	void __iomem *regs;
 	struct clk *clk;
+	struct clk *pclk;
 	struct notifier_block clk_rate_nb;
 
 	/* Settings */
 	struct i2c_timings t;
+	struct rk3x_i2c_calced_timings t_calc;
 
 	/* Synchronization & notification */
 	spinlock_t lock;
@@ -218,13 +234,13 @@ static inline void rk3x_i2c_clean_ipd(struct rk3x_i2c *i2c)
  */
 static void rk3x_i2c_start(struct rk3x_i2c *i2c)
 {
-	u32 val;
+	u32 val = i2c->t_calc.tuning;
 
 	i2c->state = STATE_START;
 	i2c_writel(i2c, REG_INT_START, REG_IEN);
 
 	/* enable adapter with correct mode, send START condition */
-	val = REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START;
+	val |= REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START;
 
 	/* if we want to react to NACK, set ACTACK bit */
 	if (!(i2c->msg->flags & I2C_M_IGNORE_NAK))
@@ -533,9 +549,9 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
  * a best-effort divider value is returned in divs. If the target rate is
  * too high, we silently use the highest possible rate.
  */
-static int rk3x_i2c_calc_divs(unsigned long clk_rate,
-			      struct i2c_timings *t,
-			      struct rk3x_i2c_calced_timings *t_calc)
+static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate,
+				    struct i2c_timings *t,
+				    struct rk3x_i2c_calced_timings *t_calc)
 {
 	unsigned long min_low_ns, min_high_ns;
 	unsigned long max_low_ns, min_total_ns;
@@ -681,23 +697,189 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	return ret;
 }
 
+/**
+ * Calculate timing values for desired SCL frequency
+ *
+ * @clk_rate: I2C input clock rate
+ * @t: Known I2C timing information
+ * @t_calc: Caculated rk3x private timings that would be written into regs
+
+ * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
+ * a best-effort divider value is returned in divs. If the target rate is
+ * too high, we silently use the highest possible rate.
+ * The following formulas are v1's method to calculate timings.
+ *
+ * l = divl + 1;
+ * h = divh + 1;
+ * s = sda_update_config + 1;
+ * u = start_setup_config + 1;
+ * p = stop_setup_config + 1;
+ * T = Tclk_i2c;
+
+ * tHigh = 8 * h * T;
+ * tLow = 8 * l * T;
+
+ * tHD;sda = (l * s + 1) * T;
+ * tSU;sda = [(8 - s) * l + 1] * T;
+ * tI2C = 8 * (l + h) * T;
+
+ * tSU;sta = (8h * u + 1) * T;
+ * tHD;sta = [8h * (u + 1) - 1] * T;
+ * tSU;sto = (8h * p + 1) * T;
+ */
+static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
+				    struct i2c_timings *t,
+				    struct rk3x_i2c_calced_timings *t_calc)
+{
+	unsigned long min_low_ns, min_high_ns, min_total_ns;
+	unsigned long min_setup_start_ns, min_setup_data_ns;
+	unsigned long min_setup_stop_ns, max_hold_data_ns;
+
+	unsigned long clk_rate_khz, scl_rate_khz;
+
+	unsigned long min_low_div, min_high_div;
+
+	unsigned long min_div_for_hold, min_total_div;
+	unsigned long extra_div, extra_low_div;
+	unsigned long sda_update_cfg, stp_sta_cfg, stp_sto_cfg;
+
+	const struct i2c_spec_values *spec;
+	int ret = 0;
+
+	/* Support standard-mode and fast-mode */
+	if (WARN_ON(t->bus_freq_hz > 400000))
+		t->bus_freq_hz = 400000;
+
+	/* prevent scl_rate_khz from becoming 0 */
+	if (WARN_ON(t->bus_freq_hz < 1000))
+		t->bus_freq_hz = 1000;
+
+	/*
+	 * min_low_ns: The minimum number of ns we need to hold low to
+	 *	       meet I2C specification, should include fall time.
+	 * min_high_ns: The minimum number of ns we need to hold high to
+	 *	        meet I2C specification, should include rise time.
+	 */
+	spec = rk3x_i2c_get_spec(t->bus_freq_hz);
+
+	/* calculate min-divh and min-divl */
+	clk_rate_khz = DIV_ROUND_UP(clk_rate, 1000);
+	scl_rate_khz = t->bus_freq_hz / 1000;
+	min_total_div = DIV_ROUND_UP(clk_rate_khz, scl_rate_khz * 8);
+
+	min_high_ns = t->scl_rise_ns + spec->min_high_ns;
+	min_high_div = DIV_ROUND_UP(clk_rate_khz * min_high_ns, 8 * 1000000);
+
+	min_low_ns = t->scl_fall_ns + spec->min_low_ns;
+	min_low_div = DIV_ROUND_UP(clk_rate_khz * min_low_ns, 8 * 1000000);
+
+	/* Final divh and divl must be greater than 0, otherwise the
+	 * hardware would not output the i2c clk.
+	 */
+	min_high_div = (min_high_div < 1) ? 2 : min_high_div;
+	min_low_div = (min_low_div < 1) ? 2 : min_low_div;
+
+	/* These are the min dividers needed for min hold times. */
+	min_div_for_hold = (min_low_div + min_high_div);
+	min_total_ns = min_low_ns + min_high_ns;
+
+	/*
+	 * This is the maximum divider so we don't go over the maximum.
+	 * We don't round up here (we round down) since this is a maximum.
+	 */
+	 if (min_div_for_hold >= min_total_div) {
+		/*
+		 * Time needed to meet hold requirements is important.
+		 * Just use that.
+		 */
+		t_calc->div_low = min_low_div;
+		t_calc->div_high = min_high_div;
+	} else {
+		/*
+		 * We've got to distribute some time among the low and high
+		 * so we don't run too fast.
+		 * We'll try to split things up by the scale of min_low_div and
+		 * min_high_div, biasing slightly towards having a higher div
+		 * for low (spend more time low).
+		 */
+		extra_div = min_total_div - min_div_for_hold;
+		extra_low_div = DIV_ROUND_UP(min_low_div * extra_div,
+					     min_div_for_hold);
+
+		t_calc->div_low = min_low_div + extra_low_div;
+		t_calc->div_high = min_high_div + (extra_div - extra_low_div);
+	}
+
+	/*
+	 * calculate sda data hold count by the rules, data_upd_st:3
+	 * is a appropriate value to reduce calculated times.
+	 */
+	for (sda_update_cfg = 3; sda_update_cfg > 0; sda_update_cfg--) {
+		max_hold_data_ns =  DIV_ROUND_UP((sda_update_cfg
+						 * (t_calc->div_low) + 1)
+						 * 1000000, clk_rate_khz);
+		min_setup_data_ns =  DIV_ROUND_UP(((8 - sda_update_cfg)
+						 * (t_calc->div_low) + 1)
+						 * 1000000, clk_rate_khz);
+		if ((max_hold_data_ns < spec->max_data_hold_ns) &&
+		    (min_setup_data_ns > spec->min_data_setup_ns))
+			break;
+	}
+
+	/* calculate setup start config */
+	min_setup_start_ns = t->scl_rise_ns + spec->min_setup_start_ns;
+	stp_sta_cfg = DIV_ROUND_UP(clk_rate_khz * min_setup_start_ns
+			   - 1000000, 8 * 1000000 * (t_calc->div_high));
+
+	/* calculate setup stop config */
+	min_setup_stop_ns = t->scl_rise_ns + spec->min_setup_stop_ns;
+	stp_sto_cfg = DIV_ROUND_UP(clk_rate_khz * min_setup_stop_ns
+			   - 1000000, 8 * 1000000 * (t_calc->div_high));
+
+	t_calc->tuning = REG_CON_SDA_CFG(--sda_update_cfg) |
+			 REG_CON_STA_CFG(--stp_sta_cfg) |
+			 REG_CON_STO_CFG(--stp_sto_cfg);
+
+	t_calc->div_low--;
+	t_calc->div_high--;
+
+	/* Maximum divider supported by hw is 0xffff */
+	if (t_calc->div_low > 0xffff) {
+		t_calc->div_low = 0xffff;
+		ret = -EINVAL;
+	}
+
+	if (t_calc->div_high > 0xffff) {
+		t_calc->div_high = 0xffff;
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
 static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
 {
 	struct i2c_timings *t = &i2c->t;
-	struct rk3x_i2c_calced_timings calc;
+	struct rk3x_i2c_calced_timings *calc = &i2c->t_calc;
 	u64 t_low_ns, t_high_ns;
 	int ret;
 
-	ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
+	ret = i2c->soc_data->calc_timings(clk_rate, t, calc);
 	WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
 
-	clk_enable(i2c->clk);
-	i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
+	if (i2c->pclk)
+		clk_enable(i2c->pclk);
+	else
+		clk_enable(i2c->clk);
+	i2c_writel(i2c, (calc->div_high << 16) | (calc->div_low & 0xffff),
 		   REG_CLKDIV);
-	clk_disable(i2c->clk);
+	if (i2c->pclk)
+		clk_disable(i2c->pclk);
+	else
+		clk_disable(i2c->clk);
 
-	t_low_ns = div_u64(((u64)calc.div_low + 1) * 8 * 1000000000, clk_rate);
-	t_high_ns = div_u64(((u64)calc.div_high + 1) * 8 * 1000000000,
+	t_low_ns = div_u64(((u64)calc->div_low + 1) * 8 * 1000000000, clk_rate);
+	t_high_ns = div_u64(((u64)calc->div_high + 1) * 8 * 1000000000,
 			    clk_rate);
 	dev_dbg(i2c->dev,
 		"CLK %lukhz, Req %uns, Act low %lluns high %lluns\n",
@@ -728,11 +910,11 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
 {
 	struct clk_notifier_data *ndata = data;
 	struct rk3x_i2c *i2c = container_of(nb, struct rk3x_i2c, clk_rate_nb);
-	struct rk3x_i2c_calced_timings calc;
 
 	switch (event) {
 	case PRE_RATE_CHANGE:
-		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &calc) != 0)
+		if (i2c->soc_data->calc_timings(ndata->new_rate, &i2c->t,
+						&i2c->t_calc) != 0)
 			return NOTIFY_STOP;
 
 		/* scale up */
@@ -847,6 +1029,8 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
 
 	spin_lock_irqsave(&i2c->lock, flags);
 
+	if (i2c->pclk)
+		clk_enable(i2c->pclk);
 	clk_enable(i2c->clk);
 
 	i2c->is_last_msg = false;
@@ -881,7 +1065,8 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
 
 			/* Force a STOP condition without interrupt */
 			i2c_writel(i2c, 0, REG_IEN);
-			i2c_writel(i2c, REG_CON_EN | REG_CON_STOP, REG_CON);
+			i2c_writel(i2c, i2c->t_calc.tuning | REG_CON_EN |
+				   REG_CON_STOP, REG_CON);
 
 			i2c->state = STATE_IDLE;
 
@@ -896,6 +1081,8 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
 	}
 
 	clk_disable(i2c->clk);
+	if (i2c->pclk)
+		clk_disable(i2c->pclk);
 	spin_unlock_irqrestore(&i2c->lock, flags);
 
 	return ret < 0 ? ret : num;
@@ -913,18 +1100,27 @@ static const struct i2c_algorithm rk3x_i2c_algorithm = {
 
 static const struct rk3x_i2c_soc_data rk3066_soc_data = {
 	.grf_offset = 0x154,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
 };
 
 static const struct rk3x_i2c_soc_data rk3188_soc_data = {
 	.grf_offset = 0x0a4,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
 };
 
 static const struct rk3x_i2c_soc_data rk3228_soc_data = {
 	.grf_offset = -1,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
 };
 
 static const struct rk3x_i2c_soc_data rk3288_soc_data = {
 	.grf_offset = -1,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
+};
+
+static const struct rk3x_i2c_soc_data rk3399_soc_data = {
+	.grf_offset = -1,
+	.calc_timings = rk3x_i2c_v1_calc_timings,
 };
 
 static const struct of_device_id rk3x_i2c_match[] = {
@@ -944,6 +1140,10 @@ static const struct of_device_id rk3x_i2c_match[] = {
 		.compatible = "rockchip,rk3288-i2c",
 		.data = (void *)&rk3288_soc_data
 	},
+	{
+		.compatible = "rockchip,rk3399-i2c",
+		.data = (void *)&rk3399_soc_data
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, rk3x_i2c_match);
@@ -983,12 +1183,6 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 	spin_lock_init(&i2c->lock);
 	init_waitqueue_head(&i2c->wait);
 
-	i2c->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(i2c->clk)) {
-		dev_err(&pdev->dev, "cannot get clock\n");
-		return PTR_ERR(i2c->clk);
-	}
-
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	i2c->regs = devm_ioremap_resource(&pdev->dev, mem);
 	if (IS_ERR(i2c->regs))
@@ -1042,17 +1236,38 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, i2c);
 
+	i2c->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(i2c->clk)) {
+		dev_err(&pdev->dev, "cannot get clock\n");
+		return PTR_ERR(i2c->clk);
+	}
+
 	ret = clk_prepare(i2c->clk);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Could not prepare clock\n");
 		return ret;
 	}
 
+	if (i2c->soc_data->calc_timings == rk3x_i2c_v1_calc_timings) {
+		i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
+		if (IS_ERR(i2c->pclk)) {
+			dev_err(i2c->dev, "Could not get i2c pclk\n");
+			ret = PTR_ERR(i2c->pclk);
+			goto err_clk;
+		}
+
+		ret = clk_prepare(i2c->pclk);
+		if (ret) {
+			dev_err(i2c->dev, "Could not prepare pclk\n");
+			goto err_clk;
+		}
+	}
+
 	i2c->clk_rate_nb.notifier_call = rk3x_i2c_clk_notifier_cb;
 	ret = clk_notifier_register(i2c->clk, &i2c->clk_rate_nb);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Unable to register clock notifier\n");
-		goto err_clk;
+		goto err_pclk;
 	}
 
 	clk_rate = clk_get_rate(i2c->clk);
@@ -1070,6 +1285,9 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 
 err_clk_notifier:
 	clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb);
+err_pclk:
+	if (i2c->pclk)
+		clk_unprepare(i2c->pclk);
 err_clk:
 	clk_unprepare(i2c->clk);
 	return ret;
@@ -1082,6 +1300,8 @@ static int rk3x_i2c_remove(struct platform_device *pdev)
 	i2c_del_adapter(&i2c->adap);
 
 	clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb);
+	if (i2c->pclk)
+		clk_unprepare(i2c->pclk);
 	clk_unprepare(i2c->clk);
 
 	return 0;
-- 
1.9.1




From jic23 at kernel.org  Wed May  4 02:38:31 2016
From: jic23 at kernel.org (Jonathan Cameron)
Date: Wed, 4 May 2016 10:38:31 +0100
Subject: [PATCH V3 1/3] iio: mxs-lradc: simplify TS registration
In-Reply-To: <20160425210006.GA26059@dtor-ws>
References: <1461441479-23218-1-git-send-email-stefan.wahren@i2se.com>
 <1461441479-23218-2-git-send-email-stefan.wahren@i2se.com>
 <20160425210006.GA26059@dtor-ws>
Message-ID: <7cb1766c-a3c2-891a-9bb8-df8f7b7c3407@kernel.org>

On 25/04/16 22:00, Dmitry Torokhov wrote:
> On Sat, Apr 23, 2016 at 07:57:57PM +0000, Stefan Wahren wrote:
>> This patch simplifies the TS registration of mxs-lradc by
>> using devm_input_allocate_device.
>>
>> Signed-off-by: Stefan Wahren <stefan.wahren at i2se.com>
>> Reviewed-by: Marek Vasut <marex at denx.de>
> 
> Acked-by: Dmitry Torokhov <dmitry.torokhov at gmail.com>
Applied to the togreg branch of iio.git - initially going
to be pushed out as testing though may not be until the weekend.

Jonathan
> 
>> ---
>>  drivers/iio/adc/mxs-lradc.c |   10 ++--------
>>  1 file changed, 2 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/iio/adc/mxs-lradc.c b/drivers/iio/adc/mxs-lradc.c
>> index ad26da1..3d1d370 100644
>> --- a/drivers/iio/adc/mxs-lradc.c
>> +++ b/drivers/iio/adc/mxs-lradc.c
>> @@ -1120,18 +1120,16 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
>>  {
>>  	struct input_dev *input;
>>  	struct device *dev = lradc->dev;
>> -	int ret;
>>  
>>  	if (!lradc->use_touchscreen)
>>  		return 0;
>>  
>> -	input = input_allocate_device();
>> +	input = devm_input_allocate_device(dev);
>>  	if (!input)
>>  		return -ENOMEM;
>>  
>>  	input->name = DRIVER_NAME;
>>  	input->id.bustype = BUS_HOST;
>> -	input->dev.parent = dev;
>>  	input->open = mxs_lradc_ts_open;
>>  	input->close = mxs_lradc_ts_close;
>>  
>> @@ -1146,11 +1144,8 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
>>  
>>  	lradc->ts_input = input;
>>  	input_set_drvdata(input, lradc);
>> -	ret = input_register_device(input);
>> -	if (ret)
>> -		input_free_device(lradc->ts_input);
>>  
>> -	return ret;
>> +	return input_register_device(input);
>>  }
>>  
>>  static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc)
>> @@ -1159,7 +1154,6 @@ static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc)
>>  		return;
>>  
>>  	mxs_lradc_disable_ts(lradc);
>> -	input_unregister_device(lradc->ts_input);
>>  }
>>  
>>  /*
>> -- 
>> 1.7.9.5
>>
> 



From jic23 at kernel.org  Wed May  4 02:39:19 2016
From: jic23 at kernel.org (Jonathan Cameron)
Date: Wed, 4 May 2016 10:39:19 +0100
Subject: [PATCH V3 2/3] iio: mxs-lradc: remove mxs_lradc_ts_unregister
In-Reply-To: <20160425210041.GB26059@dtor-ws>
References: <1461441479-23218-1-git-send-email-stefan.wahren@i2se.com>
 <1461441479-23218-3-git-send-email-stefan.wahren@i2se.com>
 <20160425210041.GB26059@dtor-ws>
Message-ID: <e1309837-633e-60db-3368-eaad6373dc35@kernel.org>

On 25/04/16 22:00, Dmitry Torokhov wrote:
> On Sat, Apr 23, 2016 at 07:57:58PM +0000, Stefan Wahren wrote:
>> After using devm_input_allocate_device for registration
>> the function mxs_lradc_ts_unregister isn't necessary anymore
>> since mxs_lradc_ts_close already does the job.
>>
>> Signed-off-by: Stefan Wahren <stefan.wahren at i2se.com>
>> Suggested-by: Dmitry Torokhov <dmitry.torokhov at gmail.com>
> 
> Acked-by: Dmitry Torokhov <dmitry.torokhov at gmail.com>
Applied.
> 
>> ---
>>  drivers/iio/adc/mxs-lradc.c |   13 +------------
>>  1 file changed, 1 insertion(+), 12 deletions(-)
>>
>> diff --git a/drivers/iio/adc/mxs-lradc.c b/drivers/iio/adc/mxs-lradc.c
>> index 3d1d370..90242ba 100644
>> --- a/drivers/iio/adc/mxs-lradc.c
>> +++ b/drivers/iio/adc/mxs-lradc.c
>> @@ -1148,14 +1148,6 @@ static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
>>  	return input_register_device(input);
>>  }
>>  
>> -static void mxs_lradc_ts_unregister(struct mxs_lradc *lradc)
>> -{
>> -	if (!lradc->use_touchscreen)
>> -		return;
>> -
>> -	mxs_lradc_disable_ts(lradc);
>> -}
>> -
>>  /*
>>   * IRQ Handling
>>   */
>> @@ -1715,13 +1707,11 @@ static int mxs_lradc_probe(struct platform_device *pdev)
>>  	ret = iio_device_register(iio);
>>  	if (ret) {
>>  		dev_err(dev, "Failed to register IIO device\n");
>> -		goto err_ts;
>> +		return ret;
>>  	}
>>  
>>  	return 0;
>>  
>> -err_ts:
>> -	mxs_lradc_ts_unregister(lradc);
>>  err_ts_register:
>>  	mxs_lradc_hw_stop(lradc);
>>  err_dev:
>> @@ -1739,7 +1729,6 @@ static int mxs_lradc_remove(struct platform_device *pdev)
>>  	struct mxs_lradc *lradc = iio_priv(iio);
>>  
>>  	iio_device_unregister(iio);
>> -	mxs_lradc_ts_unregister(lradc);
>>  	mxs_lradc_hw_stop(lradc);
>>  	mxs_lradc_trigger_remove(iio);
>>  	iio_triggered_buffer_cleanup(iio);
>> -- 
>> 1.7.9.5
>>
> 



From jic23 at kernel.org  Wed May  4 02:39:52 2016
From: jic23 at kernel.org (Jonathan Cameron)
Date: Wed, 4 May 2016 10:39:52 +0100
Subject: [PATCH V3 3/3] iio: mxs-lradc: disable only masked channels in
 mxs_lradc_hw_stop
In-Reply-To: <1461441479-23218-4-git-send-email-stefan.wahren@i2se.com>
References: <1461441479-23218-1-git-send-email-stefan.wahren@i2se.com>
 <1461441479-23218-4-git-send-email-stefan.wahren@i2se.com>
Message-ID: <240d09cb-8df3-01dd-ee84-6f5dd8cad64a@kernel.org>

On 23/04/16 20:57, Stefan Wahren wrote:
> Disabling of the touchscreen IRQs should be done in
> mxs_lradc_disable_ts. So disable only the masked virtual channels
> in mxs_lradc_hw_stop and finally remove the unused function
> mxs_lradc_irq_en_mask.
> 
> Signed-off-by: Stefan Wahren <stefan.wahren at i2se.com>
> Reviewed-by: Marek Vasut <marex at denx.de>
> Tested-by: Marek Vasut <marex at denx.de>
Applied to the togreg branch of iio.git

Thanks,

Jonathan
> ---
>  drivers/iio/adc/mxs-lradc.c |   11 +++--------
>  1 file changed, 3 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/iio/adc/mxs-lradc.c b/drivers/iio/adc/mxs-lradc.c
> index 90242ba..b84d37c 100644
> --- a/drivers/iio/adc/mxs-lradc.c
> +++ b/drivers/iio/adc/mxs-lradc.c
> @@ -373,13 +373,6 @@ static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc)
>  	return LRADC_CTRL0_MX28_PLATE_MASK;
>  }
>  
> -static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc)
> -{
> -	if (lradc->soc == IMX23_LRADC)
> -		return LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK;
> -	return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK;
> -}
> -
>  static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc)
>  {
>  	if (lradc->soc == IMX23_LRADC)
> @@ -1496,7 +1489,9 @@ static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
>  {
>  	int i;
>  
> -	mxs_lradc_reg_clear(lradc, mxs_lradc_irq_en_mask(lradc), LRADC_CTRL1);
> +	mxs_lradc_reg_clear(lradc,
> +		lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET,
> +		LRADC_CTRL1);
>  
>  	for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++)
>  		mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i));
> 



From david.wu at rock-chips.com  Wed May  4 07:37:48 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed,  4 May 2016 22:37:48 +0800
Subject: [PATCH v7 9/9] i2c: rk3x: support fast-mode plus for rk3399
In-Reply-To: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462372668-6583-1-git-send-email-david.wu@rock-chips.com>

Signed-off-by: David Wu <david.wu at rock-chips.com>
---
 drivers/i2c/busses/i2c-rk3x.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 47368c4..c66cc39 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -124,6 +124,17 @@ static const struct i2c_spec_values fast_mode_spec = {
 	.min_hold_buffer_ns = 1300,
 };
 
+static const struct i2c_spec_values fast_mode_plus_spec = {
+	.min_hold_start_ns = 260,
+	.min_low_ns = 500,
+	.min_high_ns = 260,
+	.min_setup_start_ns = 260,
+	.max_data_hold_ns = 400,
+	.min_data_setup_ns = 50,
+	.min_setup_stop_ns = 260,
+	.min_hold_buffer_ns = 500,
+};
+
 /**
  * struct rk3x_i2c_calced_timings:
  * @div_low: Divider output for low
@@ -534,8 +545,10 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
 {
 	if (speed <= 100000)
 		return &standard_mode_spec;
-	else
+	else if (speed <= 400000)
 		return &fast_mode_spec;
+	else
+		return &fast_mode_plus_spec;
 }
 
 /**
@@ -746,9 +759,9 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
 	const struct i2c_spec_values *spec;
 	int ret = 0;
 
-	/* Support standard-mode and fast-mode */
-	if (WARN_ON(t->bus_freq_hz > 400000))
-		t->bus_freq_hz = 400000;
+	/* Support standard-mode, fast-mode and fast-mode plus */
+	if (WARN_ON(t->bus_freq_hz > 1000000))
+		t->bus_freq_hz = 1000000;
 
 	/* prevent scl_rate_khz from becoming 0 */
 	if (WARN_ON(t->bus_freq_hz < 1000))
-- 
1.9.1




From jic23 at kernel.org  Wed May  4 02:40:08 2016
From: jic23 at kernel.org (Jonathan Cameron)
Date: Wed, 4 May 2016 10:40:08 +0100
Subject: [PATCH V3 0/3] iio: mxs-lradc: simplify TS handling
In-Reply-To: <CAL7P5jJF9EL4Zk-AC9csyadfrmUp4R+6ceVAN_kNm7dKgo+ZgQ@mail.gmail.com>
References: <1461441479-23218-1-git-send-email-stefan.wahren@i2se.com>
 <500c5874-4ef8-b37b-e12f-80fd5205c172@kernel.org>
 <CAL7P5jJF9EL4Zk-AC9csyadfrmUp4R+6ceVAN_kNm7dKgo+ZgQ@mail.gmail.com>
Message-ID: <e0989150-8f22-4f36-fea7-65a86973833d@kernel.org>

On 02/05/16 07:06, Ksenija Stanojevi? wrote:
> Hi Jonathan,
> 
> On Sun, May 1, 2016 at 10:08 PM, Jonathan Cameron <jic23 at kernel.org> wrote:
>> Ksenija,
>>
>> How would you prefer we handle this interaction of this set and your series.
>> Options are:
>>
>> 1. I apply these now and you rebase on top of the result.
>> 2. You pull these into your series, probably after the driver split making sure these
>>    improvements end up in the new drivers.
>> 3. We ask Stephan to re roll them at a later date (least preferred option as that adds
>> another person we need to chase down to get to the end of this process!)
>>
>> No immediate rush on any of the above as we've probably missed this cycle now anyway.
>> I've been cut off today so not sure what Linus has said today.
> 
> My understanding was that you will take this patch series so I already included
> changes made by this patch set in touchscreen part, I will check if I missed
> something.
> I think the best is to apply these now.
Cool - that's even easier ;)

Jonathan
> 
> Thanks,
> Ksenija
> 
>> Jonathan
>> On 23/04/16 20:57, Stefan Wahren wrote:
>>> This patch series simplifies TS handling of mxs-lradc.
>>>
>>> These patches has been tested with i.MX23 and i.MX28 but without
>>> a touchscreen. I added only a bogus touchscreen in devicetree.
>>>
>>> It would be nice if someone with a real touchscreen could test it.
>>>
>>> Changes in V3:
>>> - remove dev.parent assignment as suggested by Dimitry
>>> - add new patch to remove mxs_lradc_ts_unregister
>>> - remove PM implementation from series in order to wait until
>>>   Ksenija has split the driver
>>>
>>> Changes in V2:
>>> - rebase on iio/testing since patch 2 and 3 from V1 has been applied
>>> - also remove input_unregister_device in patch 1
>>> - use mask of virtual channels for IRQ disabling in patch 2
>>>
>>> Stefan Wahren (3):
>>>   iio: mxs-lradc: simplify TS registration
>>>   iio: mxs-lradc: remove mxs_lradc_ts_unregister
>>>   iio: mxs-lradc: disable only masked channels in
>>>     mxs_lradc_hw_stop
>>>
>>>  drivers/iio/adc/mxs-lradc.c |   34 ++++++----------------------------
>>>  1 file changed, 6 insertions(+), 28 deletions(-)
>>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 



From john at metanate.com  Wed May  4 07:54:45 2016
From: john at metanate.com (John Keeping)
Date: Wed,  4 May 2016 15:54:45 +0100
Subject: [PATCH 1/2] Revert "ASoC: rockchip: i2s: remove unused variables"
Message-ID: <1462373686-21794-1-git-send-email-john@metanate.com>

This reverts commit 5938448b99275cba95167c3f9d39ca9225fdad38.

It turns out that the commit that made these variables unused is wrong
so we're about to revert it.  Bring back the variables in prepration.

Signed-off-by: John Keeping <john at metanate.com>
---
 sound/soc/rockchip/rockchip_i2s.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 2f8e20416bd3..34743ec61c49 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -34,6 +34,13 @@ struct rk_i2s_dev {
 
 	struct regmap *regmap;
 
+/*
+ * Used to indicate the tx/rx status.
+ * I2S controller hopes to start the tx and rx together,
+ * also to stop them when they are both try to stop.
+*/
+	bool tx_start;
+	bool rx_start;
 	bool is_master_mode;
 };
 
@@ -77,7 +84,11 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
 		regmap_update_bits(i2s->regmap, I2S_XFER,
 				   I2S_XFER_TXS_START,
 				   I2S_XFER_TXS_START);
+
+		i2s->tx_start = true;
 	} else {
+		i2s->tx_start = false;
+
 		regmap_update_bits(i2s->regmap, I2S_DMACR,
 				   I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
 
@@ -115,7 +126,11 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
 		regmap_update_bits(i2s->regmap, I2S_XFER,
 				   I2S_XFER_RXS_START,
 				   I2S_XFER_RXS_START);
+
+		i2s->rx_start = true;
 	} else {
+		i2s->rx_start = false;
+
 		regmap_update_bits(i2s->regmap, I2S_DMACR,
 				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
 
-- 
2.8.0.rc4.238.g874082a



From john at metanate.com  Wed May  4 07:54:46 2016
From: john at metanate.com (John Keeping)
Date: Wed,  4 May 2016 15:54:46 +0100
Subject: [PATCH 2/2] Revert "ASoC: rockchip: i2s: separate capture and
 playback"
In-Reply-To: <1462373686-21794-1-git-send-email-john@metanate.com>
References: <1462373686-21794-1-git-send-email-john@metanate.com>
Message-ID: <1462373686-21794-2-git-send-email-john@metanate.com>

This reverts commit eba65d179c1149cf79e68608d452631f33d7f017.

This broke audio on Veyron Jerry Chromebooks and I now cannot reproduce
the problem I was trying to fix even with this commit reverted, so it
seems that this was completely the wrong thing to do.

Reported-by: Enric Balletbo Serra <eballetbo at gmail.com>
Signed-off-by: John Keeping <john at metanate.com>
---
 sound/soc/rockchip/rockchip_i2s.c | 72 ++++++++++++++++++++++-----------------
 1 file changed, 40 insertions(+), 32 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 34743ec61c49..574c6af28c06 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -82,8 +82,8 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
 				   I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
 
 		regmap_update_bits(i2s->regmap, I2S_XFER,
-				   I2S_XFER_TXS_START,
-				   I2S_XFER_TXS_START);
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START);
 
 		i2s->tx_start = true;
 	} else {
@@ -92,23 +92,27 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
 		regmap_update_bits(i2s->regmap, I2S_DMACR,
 				   I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
 
-		regmap_update_bits(i2s->regmap, I2S_XFER,
-				   I2S_XFER_TXS_START,
-				   I2S_XFER_TXS_STOP);
-
-		regmap_update_bits(i2s->regmap, I2S_CLR,
-				   I2S_CLR_TXC,
-				   I2S_CLR_TXC);
+		if (!i2s->rx_start) {
+			regmap_update_bits(i2s->regmap, I2S_XFER,
+					   I2S_XFER_TXS_START |
+					   I2S_XFER_RXS_START,
+					   I2S_XFER_TXS_STOP |
+					   I2S_XFER_RXS_STOP);
 
-		regmap_read(i2s->regmap, I2S_CLR, &val);
+			regmap_update_bits(i2s->regmap, I2S_CLR,
+					   I2S_CLR_TXC | I2S_CLR_RXC,
+					   I2S_CLR_TXC | I2S_CLR_RXC);
 
-		/* Should wait for clear operation to finish */
-		while (val & I2S_CLR_TXC) {
 			regmap_read(i2s->regmap, I2S_CLR, &val);
-			retry--;
-			if (!retry) {
-				dev_warn(i2s->dev, "fail to clear\n");
-				break;
+
+			/* Should wait for clear operation to finish */
+			while (val) {
+				regmap_read(i2s->regmap, I2S_CLR, &val);
+				retry--;
+				if (!retry) {
+					dev_warn(i2s->dev, "fail to clear\n");
+					break;
+				}
 			}
 		}
 	}
@@ -124,8 +128,8 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
 				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
 
 		regmap_update_bits(i2s->regmap, I2S_XFER,
-				   I2S_XFER_RXS_START,
-				   I2S_XFER_RXS_START);
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START);
 
 		i2s->rx_start = true;
 	} else {
@@ -134,23 +138,27 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
 		regmap_update_bits(i2s->regmap, I2S_DMACR,
 				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
 
-		regmap_update_bits(i2s->regmap, I2S_XFER,
-				   I2S_XFER_RXS_START,
-				   I2S_XFER_RXS_STOP);
-
-		regmap_update_bits(i2s->regmap, I2S_CLR,
-				   I2S_CLR_RXC,
-				   I2S_CLR_RXC);
+		if (!i2s->tx_start) {
+			regmap_update_bits(i2s->regmap, I2S_XFER,
+					   I2S_XFER_TXS_START |
+					   I2S_XFER_RXS_START,
+					   I2S_XFER_TXS_STOP |
+					   I2S_XFER_RXS_STOP);
 
-		regmap_read(i2s->regmap, I2S_CLR, &val);
+			regmap_update_bits(i2s->regmap, I2S_CLR,
+					   I2S_CLR_TXC | I2S_CLR_RXC,
+					   I2S_CLR_TXC | I2S_CLR_RXC);
 
-		/* Should wait for clear operation to finish */
-		while (val & I2S_CLR_RXC) {
 			regmap_read(i2s->regmap, I2S_CLR, &val);
-			retry--;
-			if (!retry) {
-				dev_warn(i2s->dev, "fail to clear\n");
-				break;
+
+			/* Should wait for clear operation to finish */
+			while (val) {
+				regmap_read(i2s->regmap, I2S_CLR, &val);
+				retry--;
+				if (!retry) {
+					dev_warn(i2s->dev, "fail to clear\n");
+					break;
+				}
 			}
 		}
 	}
-- 
2.8.0.rc4.238.g874082a



From eballetbo at gmail.com  Wed May  4 08:04:42 2016
From: eballetbo at gmail.com (Enric Balletbo Serra)
Date: Wed, 4 May 2016 17:04:42 +0200
Subject: [PATCH 1/2] Revert "ASoC: rockchip: i2s: remove unused variables"
In-Reply-To: <1462373686-21794-1-git-send-email-john@metanate.com>
References: <1462373686-21794-1-git-send-email-john@metanate.com>
Message-ID: <CAFqH_51KuNv+mypL0n5E1aOicqt+sr_S-Egm0eocrj82XF9X-w@mail.gmail.com>

Hi John,

Thanks for the patches.

2016-05-04 16:54 GMT+02:00 John Keeping <john at metanate.com>:
> This reverts commit 5938448b99275cba95167c3f9d39ca9225fdad38.
>
> It turns out that the commit that made these variables unused is wrong
> so we're about to revert it.  Bring back the variables in prepration.
>
> Signed-off-by: John Keeping <john at metanate.com>
> ---
>  sound/soc/rockchip/rockchip_i2s.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
>
> diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
> index 2f8e20416bd3..34743ec61c49 100644
> --- a/sound/soc/rockchip/rockchip_i2s.c
> +++ b/sound/soc/rockchip/rockchip_i2s.c
> @@ -34,6 +34,13 @@ struct rk_i2s_dev {
>
>         struct regmap *regmap;
>
> +/*
> + * Used to indicate the tx/rx status.
> + * I2S controller hopes to start the tx and rx together,
> + * also to stop them when they are both try to stop.
> +*/
> +       bool tx_start;
> +       bool rx_start;
>         bool is_master_mode;
>  };
>
> @@ -77,7 +84,11 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
>                 regmap_update_bits(i2s->regmap, I2S_XFER,
>                                    I2S_XFER_TXS_START,
>                                    I2S_XFER_TXS_START);
> +
> +               i2s->tx_start = true;
>         } else {
> +               i2s->tx_start = false;
> +
>                 regmap_update_bits(i2s->regmap, I2S_DMACR,
>                                    I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
>
> @@ -115,7 +126,11 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
>                 regmap_update_bits(i2s->regmap, I2S_XFER,
>                                    I2S_XFER_RXS_START,
>                                    I2S_XFER_RXS_START);
> +
> +               i2s->rx_start = true;
>         } else {
> +               i2s->rx_start = false;
> +
>                 regmap_update_bits(i2s->regmap, I2S_DMACR,
>                                    I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
>
> --
> 2.8.0.rc4.238.g874082a
>

Apart from these two patches, to get audio working on Veyron device
I've some other fixes, If it's ok I would like to include these
patches into my series, so we have a patch series that fixes the audio
for veyron.

Best regards,
 Enric


From peterz at infradead.org  Wed May  4 08:08:48 2016
From: peterz at infradead.org (Peter Zijlstra)
Date: Wed, 4 May 2016 17:08:48 +0200
Subject: [PATCH] perf/core / arm_pmu: special-case hetereogeneous CPUs
In-Reply-To: <20160504134419.GA15849@leverpostej>
References: <20160425175837.GB3141@leverpostej>
 <20160425190334.GK3448@twins.programming.kicks-ass.net>
 <20160426103346.GA20836@leverpostej>
 <20160504134419.GA15849@leverpostej>
Message-ID: <20160504150848.GS3430@twins.programming.kicks-ass.net>

On Wed, May 04, 2016 at 02:44:20PM +0100, Mark Rutland wrote:
> > Ok, how about the below? (based on next-20160422).
> 
> Peter, any thoughts?
> 

Right, I have it queued, should hopefully hit tip tomorrow someplace.

Thanks!


From broonie at kernel.org  Wed May  4 08:10:28 2016
From: broonie at kernel.org (Mark Brown)
Date: Wed, 4 May 2016 16:10:28 +0100
Subject: [PATCH 1/2] Revert "ASoC: rockchip: i2s: remove unused variables"
In-Reply-To: <1462373686-21794-1-git-send-email-john@metanate.com>
References: <1462373686-21794-1-git-send-email-john@metanate.com>
Message-ID: <20160504151028.GW6292@sirena.org.uk>

On Wed, May 04, 2016 at 03:54:45PM +0100, John Keeping wrote:
> This reverts commit 5938448b99275cba95167c3f9d39ca9225fdad38.
> 
> It turns out that the commit that made these variables unused is wrong
> so we're about to revert it.  Bring back the variables in prepration.

Please submit patches using subject lines reflecting the style for the
subsystem.  This makes it easier for people to identify relevant
patches.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/532607aa/attachment.sig>

From eric.auger at linaro.org  Wed May  4 08:18:06 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 15:18:06 +0000
Subject: [PATCH v9 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part
 2/3: msi changes
Message-ID: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>

This series implements the MSI address mapping/unmapping in the MSI layer.
IOMMU binding happens on pci_enable_msi since this function can sleep and
return errors. On msi_domain_set_affinity, msi_domain_(de)activate, which
are not allowed to sleep, we simply look for the already existing binding.

A new MSI domain info flag value is introduced to report whether the msi
domain implements IRQ remapping. GIC v3 ITS is the first MSI controller
advertising it. This flag value will be used by VFIO subsystem to
determine whether MSI forwarding is safe.

More details & context can be found at:
http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/

Best Regards

Eric

Applies on top of PART 1/3. Also depends on
[PATCH 1/3] iommu: Add MMIO mapping type,
http://comments.gmane.org/gmane.linux.kernel.iommu/12869

Git: complete series available at
https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc6-pcie-passthrough-v9-msi-v9

This branch contains all parts in v9.

History:

v8 -> v9:
- use a union in irq_chip_msi_doorbell_info + boolean telling whether the
  doorbell is percpu
- decouple irq_data parsing from the actual mapping/unmapping in
  msi_handle_doorbell_mappings
- fix misc style issues

v7 -> v8:
take into account Marc's comments:
- use iommu_msi_msg_pa_to_va with new proto
- change in irq_chip_msi_doorbell_info struct definition:
  prot and size became shared between all doorbells and phys_addr_t __percpu
- cleanups in v2m irqchip
- eventually did not touch MSI_FLAG_IRQ_REMAPPING naming
- On msi_handle_doorbell_mappings, stop on the first irqchip where doorbells
  can be found
- fix resource deallocation on mapping failure in msi_domain_alloc_irqs

v6 -> v7:
- do alloc/map handling on pci_enable_msi and search on msi_(de)domain_activate
- add msi_doorbell_info callback in irq-chip to retrieve the characteristics
  of doorbells

RFC v5 -> patch v6:
- split to ease the review process
- rebase on default iommu domain code (irq_data_to_msi_mapping_domain
  checks IOMMU_DOMAIN_DMA type)
- fix unmap sequence on msi_domain_set_affinity (reported by Marc):
  unmap the previous doorbell when the new one has been mapped & written to
  the device, ie. irq_chip_write_msi_msg.
- "msi: msi_compose wrapper removed" following change above
- add size parameter to iommu_get_reserved_iova API following Marc's request

RFC v4 -> RFC v5:
- take into account Thomas' comments on MSI related patches
  - split "msi: IOMMU map the doorbell address when needed"
  - increase readability and add comments
  - fix style issues
 - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
 - platform ITS now advertises IOMMU_CAP_INTR_REMAP
 - fix compilation issue with CONFIG_IOMMU API unset
 - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING

RFC v3 -> v4:
- Move doorbell mapping/unmapping in msi.c
- fix ref count issue on set_affinity: in case of a change in the address
  the previous address is decremented
- doorbell map/unmap now is done on msi composition. Should allow the use
  case for platform MSI controllers
- create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
  to reserved IOVA management (looking like dma-iommu glue)
- series reordering to ease the review:
  - first part is related to IOMMU
  - second related to MSI sub-system
  - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
- expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
  [this partially addresses Marc's comments on iommu_get/put_single_reserved
   size/alignment problematic - which I did not ignore - but I don't know
   how much I can do at the moment]

RFC v2 -> RFC v3:
- should fix wrong handling of some CONFIG combinations:
  CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
- fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)

PATCH v1 -> RFC v2:
- reverted to RFC since it looks more reasonable ;-) the code is split
  between VFIO, IOMMU, MSI controller and I am not sure I did the right
  choices. Also API need to be further discussed.
- iova API usage in arm-smmu.c.
- MSI controller natively programs the MSI addr with either the PA or IOVA.
  This is not done anymore in vfio-pci driver as suggested by Alex.
- check irq remapping capability of the group

RFC v1 [2] -> PATCH v1:
- use the existing dma map/unmap ioctl interface with a flag to register a
  reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
- a single reserved IOVA contiguous region now is allowed
- use of an RB tree indexed by PA to store allocated reserved slots
- use of a vfio_domain iova_domain to manage iova allocation within the
  window provided by the userspace
- vfio alloc_map/unmap_free take a vfio_group handle
- vfio_group handle is cached in vfio_pci_device
- add ref counting to bindings
- user modality enabled at the end of the series


Eric Auger (8):
  genirq/msi: Add a new MSI_FLAG_IRQ_REMAPPING flag
  irqchip/gic-v3-its: ITS advertises MSI_FLAG_IRQ_REMAPPING
  genirq/msi: export msi_get_domain_info
  genirq/msi: msi_compose wrapper
  genirq/irq: introduce msi_doorbell_info
  irqchip/gicv2m: implement msi_doorbell_info callback
  genirq/msi: map/unmap the MSI doorbells on msi_domain_alloc/free_irqs
  genirq/msi: use the MSI doorbell's IOVA when requested

 drivers/irqchip/irq-gic-v2m.c                 |  16 +++
 drivers/irqchip/irq-gic-v3-its-pci-msi.c      |   3 +-
 drivers/irqchip/irq-gic-v3-its-platform-msi.c |   3 +-
 include/linux/irq.h                           |  15 ++-
 include/linux/msi.h                           |   2 +
 kernel/irq/msi.c                              | 136 +++++++++++++++++++++++---
 6 files changed, 161 insertions(+), 14 deletions(-)

-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 08:18:07 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 15:18:07 +0000
Subject: [PATCH v9 1/8] genirq/msi: Add a new MSI_FLAG_IRQ_REMAPPING flag
In-Reply-To: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462375094-2390-2-git-send-email-eric.auger@linaro.org>

Let's introduce a new msi_domain_info flag value, MSI_FLAG_IRQ_REMAPPING
meant to tell the domain supports IRQ REMAPPING, also known as Interrupt
Translation Service. On Intel HW this IRQ remapping capability is
abstracted on IOMMU side while on ARM it is abstracted on MSI controller
side. This flag will be used to know whether the MSI passthrough is
safe.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---

v4 -> v5:
- seperate flag introduction from first user addition (ITS)
---
 include/linux/msi.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/msi.h b/include/linux/msi.h
index 8b425c6..08441b1 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -270,6 +270,8 @@ enum {
 	MSI_FLAG_MULTI_PCI_MSI		= (1 << 3),
 	/* Support PCI MSIX interrupts */
 	MSI_FLAG_PCI_MSIX		= (1 << 4),
+	/* Support MSI IRQ remapping service */
+	MSI_FLAG_IRQ_REMAPPING		= (1 << 5),
 };
 
 int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 08:18:08 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 15:18:08 +0000
Subject: [PATCH v9 2/8] irqchip/gic-v3-its: ITS advertises
 MSI_FLAG_IRQ_REMAPPING
In-Reply-To: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462375094-2390-3-git-send-email-eric.auger@linaro.org>

The ITS is the first ARM MSI controller advertising the new
MSI_FLAG_IRQ_REMAPPING flag. It does so because it supports
interrupt translation service. This HW support offers isolation
of MSIs, feature used when using KVM device passthrough.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---

v5: new
---
 drivers/irqchip/irq-gic-v3-its-pci-msi.c      | 3 ++-
 drivers/irqchip/irq-gic-v3-its-platform-msi.c | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index aee60ed..8223765 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -96,7 +96,8 @@ static struct msi_domain_ops its_pci_msi_ops = {
 
 static struct msi_domain_info its_pci_msi_domain_info = {
 	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-		   MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX),
+		   MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX |
+		   MSI_FLAG_IRQ_REMAPPING),
 	.ops	= &its_pci_msi_ops,
 	.chip	= &its_msi_irq_chip,
 };
diff --git a/drivers/irqchip/irq-gic-v3-its-platform-msi.c b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
index 470b4aa..8c0d69d 100644
--- a/drivers/irqchip/irq-gic-v3-its-platform-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
@@ -63,7 +63,8 @@ static struct msi_domain_ops its_pmsi_ops = {
 };
 
 static struct msi_domain_info its_pmsi_domain_info = {
-	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
+	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+		   MSI_FLAG_IRQ_REMAPPING),
 	.ops	= &its_pmsi_ops,
 	.chip	= &its_pmsi_irq_chip,
 };
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 08:18:09 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 15:18:09 +0000
Subject: [PATCH v9 3/8] genirq/msi: export msi_get_domain_info
In-Reply-To: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462375094-2390-4-git-send-email-eric.auger@linaro.org>

We plan to use msi_get_domain_info in VFIO module so let's export it.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---

v2 -> v3:
- remove static implementation in case CONFIG_PCI_MSI_IRQ_DOMAIN is not set
---
 kernel/irq/msi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 38e89ce..9b0ba4a 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -400,5 +400,6 @@ struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain)
 {
 	return (struct msi_domain_info *)domain->host_data;
 }
+EXPORT_SYMBOL_GPL(msi_get_domain_info);
 
 #endif /* CONFIG_GENERIC_MSI_IRQ_DOMAIN */
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 08:18:10 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 15:18:10 +0000
Subject: [PATCH v9 4/8] genirq/msi: msi_compose wrapper
In-Reply-To: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462375094-2390-5-git-send-email-eric.auger@linaro.org>

Currently the MSI message is composed by directly calling
irq_chip_compose_msi_msg and erased by setting the memory to zero.

On some platforms, we will need to complexify this composition to
properly handle MSI emission through IOMMU. Also we will need to track
when the MSI message is erased.

We propose to introduce a common wrapper for actual composition and
erasure, msi_compose.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v4 -> v5:
- just introduce the msi-compose wrapper without adding new
  functionalities

v3 -> v4:
- that code was formely in irq-gic-common.c
  "irqchip/gicv2m/v3-its-pci-msi: IOMMU map the MSI frame when needed"
  also the [un]mapping was done in irq_write_msi_msg; now done on compose

v2 -> v3:
- protect iova/addr manipulation with CONFIG_ARCH_DMA_ADDR_T_64BIT and
  CONFIG_PHYS_ADDR_T_64BIT
- only expose gic_pci_msi_domain_write_msg in case CONFIG_IOMMU_API &
  CONFIG_PCI_MSI_IRQ_DOMAIN are set.
- gic_set/unset_msi_addr duly become static
---
 kernel/irq/msi.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 9b0ba4a..72bf4d6 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -55,6 +55,19 @@ static inline void irq_chip_write_msi_msg(struct irq_data *data,
 	data->chip->irq_write_msi_msg(data, msg);
 }
 
+static int msi_compose(struct irq_data *irq_data,
+		       struct msi_msg *msg, bool erase)
+{
+	int ret = 0;
+
+	if (erase)
+		memset(msg, 0, sizeof(*msg));
+	else
+		ret = irq_chip_compose_msi_msg(irq_data, msg);
+
+	return ret;
+}
+
 /**
  * msi_domain_set_affinity - Generic affinity setter function for MSI domains
  * @irq_data:	The irq data associated to the interrupt
@@ -73,7 +86,7 @@ int msi_domain_set_affinity(struct irq_data *irq_data,
 
 	ret = parent->chip->irq_set_affinity(parent, mask, force);
 	if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) {
-		BUG_ON(irq_chip_compose_msi_msg(irq_data, &msg));
+		BUG_ON(msi_compose(irq_data, &msg, false));
 		irq_chip_write_msi_msg(irq_data, &msg);
 	}
 
@@ -85,7 +98,7 @@ static void msi_domain_activate(struct irq_domain *domain,
 {
 	struct msi_msg msg;
 
-	BUG_ON(irq_chip_compose_msi_msg(irq_data, &msg));
+	BUG_ON(msi_compose(irq_data, &msg, false));
 	irq_chip_write_msi_msg(irq_data, &msg);
 }
 
@@ -94,7 +107,7 @@ static void msi_domain_deactivate(struct irq_domain *domain,
 {
 	struct msi_msg msg;
 
-	memset(&msg, 0, sizeof(msg));
+	msi_compose(irq_data, &msg, true);
 	irq_chip_write_msi_msg(irq_data, &msg);
 }
 
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 08:18:11 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 15:18:11 +0000
Subject: [PATCH v9 5/8] genirq/irq: introduce msi_doorbell_info
In-Reply-To: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462375094-2390-6-git-send-email-eric.auger@linaro.org>

The purpose is to be able to retrieve the MSI doorbells of an irqchip.
This is now needed since on some platforms those doorbells must be
iommu mapped (in case the MSIs transit through an IOMMU that do not
bypass those transactions).

The assumption is there is a maximum of one doorbell region per cpu.
Sometimes a single doorbell is supported, hence the union.

A doorbell region is characterized by its physical address base, size and
IOMMU protection flag. Those 2 last characteristics are shared among all
doorbells.

irq_chip msi_doorbell_info callback enables to retrieve the doorbells of
the irqchip.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v8 -> v9:
- use a union and doorbell_is_percpu boolean

v7 -> v8:
- size and prot now are shared among all doorbells
- doorbells now directly points to a percpu phys_addr_t

v7: creation
---
 include/linux/irq.h | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index c4de623..4b4e479 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -312,6 +312,17 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
 	return d->hwirq;
 }
 
+/* Describe all the MSI doorbell regions for an irqchip */
+struct irq_chip_msi_doorbell_info {
+	union {
+		phys_addr_t __percpu *percpu_doorbells;
+		phys_addr_t global_doorbell;
+	};
+	bool doorbell_is_percpu;
+	size_t size;	/* size of a each doorbell */
+	int prot;	/* iommu protection flag */
+};
+
 /**
  * struct irq_chip - hardware interrupt chip descriptor
  *
@@ -349,6 +360,7 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
  * @irq_get_irqchip_state:	return the internal state of an interrupt
  * @irq_set_irqchip_state:	set the internal state of a interrupt
  * @irq_set_vcpu_affinity:	optional to target a vCPU in a virtual machine
+ * @msi_doorbell_info:	return the MSI doorbell info
  * @ipi_send_single:	send a single IPI to destination cpus
  * @ipi_send_mask:	send an IPI to destination cpus in cpumask
  * @flags:		chip specific flags
@@ -394,7 +406,8 @@ struct irq_chip {
 	int		(*irq_set_irqchip_state)(struct irq_data *data, enum irqchip_irq_state which, bool state);
 
 	int		(*irq_set_vcpu_affinity)(struct irq_data *data, void *vcpu_info);
-
+	struct irq_chip_msi_doorbell_info *(*msi_doorbell_info)(
+							struct irq_data *data);
 	void		(*ipi_send_single)(struct irq_data *data, unsigned int cpu);
 	void		(*ipi_send_mask)(struct irq_data *data, const struct cpumask *dest);
 
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 08:18:12 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 15:18:12 +0000
Subject: [PATCH v9 6/8] irqchip/gicv2m: implement msi_doorbell_info callback
In-Reply-To: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462375094-2390-7-git-send-email-eric.auger@linaro.org>

This patch implements the msi_doorbell_info callback in the
gicv2m driver.

The driver now is able to return its doorbell characteristics
(base, size, prot). A single doorbell is exposed.

This will allow the msi layer to iommu_map this doorbell when
requested.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v8 -> v9:
- use global_doorbell instead of percpu_doorbells

v7 -> v8:
- gicv2m_msi_doorbell_info does not return a pointer to const
- remove spurious !v2m check
- add IOMMU_MMIO flag

v7: creation
---
 drivers/irqchip/irq-gic-v2m.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 28f047c..c77c41f 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -24,6 +24,7 @@
 #include <linux/of_pci.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/iommu.h>
 
 /*
 * MSI_TYPER:
@@ -64,6 +65,7 @@ struct v2m_data {
 	u32 nr_spis;		/* The number of SPIs for MSIs */
 	unsigned long *bm;	/* MSI vector bitmap */
 	u32 flags;		/* v2m flags for specific implementation */
+	struct irq_chip_msi_doorbell_info doorbell_info;
 };
 
 static void gicv2m_mask_msi_irq(struct irq_data *d)
@@ -105,6 +107,14 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 		msg->data -= v2m->spi_start;
 }
 
+static struct irq_chip_msi_doorbell_info *
+gicv2m_msi_doorbell_info(struct irq_data *data)
+{
+	struct v2m_data *v2m = irq_data_get_irq_chip_data(data);
+
+	return &v2m->doorbell_info;
+}
+
 static struct irq_chip gicv2m_irq_chip = {
 	.name			= "GICv2m",
 	.irq_mask		= irq_chip_mask_parent,
@@ -112,6 +122,7 @@ static struct irq_chip gicv2m_irq_chip = {
 	.irq_eoi		= irq_chip_eoi_parent,
 	.irq_set_affinity	= irq_chip_set_affinity_parent,
 	.irq_compose_msi_msg	= gicv2m_compose_msi_msg,
+	.msi_doorbell_info	= gicv2m_msi_doorbell_info,
 };
 
 static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
@@ -311,6 +322,11 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
 
 	memcpy(&v2m->res, res, sizeof(struct resource));
 
+	v2m->doorbell_info.global_doorbell = v2m->res.start;
+	v2m->doorbell_info.doorbell_is_percpu = false;
+	v2m->doorbell_info.size = sizeof(u32);
+	v2m->doorbell_info.prot = IOMMU_WRITE | IOMMU_MMIO;
+
 	v2m->base = ioremap(v2m->res.start, resource_size(&v2m->res));
 	if (!v2m->base) {
 		pr_err("Failed to map GICv2m resource\n");
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 08:18:13 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 15:18:13 +0000
Subject: [PATCH v9 7/8] genirq/msi: map/unmap the MSI doorbells on
 msi_domain_alloc/free_irqs
In-Reply-To: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462375094-2390-8-git-send-email-eric.auger@linaro.org>

This patch handles the iommu mapping of MSI doorbells that require to
be mapped in an iommu domain. This happens on msi_domain_alloc/free_irqs
since this is called in code that can sleep (pci_enable/disable_msi):
iommu_map/unmap is not stated as atomic. On msi_domain_(de)activate and
msi_domain_set_affinity, which must be atomic, we just lookup for this
pre-allocated/mapped IOVA.

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v8 -> v9:
- decouple irq_data parsing from the actual mapping/unmapping

v7 -> v8:
- new percpu pointer type
- exit from the irq domain hierarchy parsing on first map/unmap success
- reset desc->irq to 0 on mapping failure

v7: creation
---
 kernel/irq/msi.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 100 insertions(+), 8 deletions(-)

diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 72bf4d6..d654524 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -14,6 +14,8 @@
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/msi.h>
+#include <linux/msi-iommu.h>
+#include <linux/iommu.h>
 
 /* Temparory solution for building, will be removed later */
 #include <linux/pci.h>
@@ -322,6 +324,74 @@ int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
 }
 
 /**
+ * msi_handle_doorbell_mappings: in case the irq data corresponds to an
+ * MSI that requires iommu mapping, traverse the irq domain hierarchy
+ * to retrieve the doorbells to handle and iommu_map/unmap them according
+ * to @map boolean.
+ *
+ * @data: irq data handle
+ * @map: mapping if true, unmapping if false
+ */
+static int msi_handle_doorbell_mappings(struct irq_data *data, bool map)
+{
+	const struct irq_chip_msi_doorbell_info *dbinfo;
+	struct iommu_domain *domain;
+	struct irq_chip *chip;
+	struct device *dev;
+	dma_addr_t iova;
+	int ret = 0, cpu;
+
+	while (data) {
+		dev = msi_desc_to_dev(irq_data_get_msi_desc(data));
+		domain = iommu_msi_domain(dev);
+		if (domain) {
+			chip = irq_data_get_irq_chip(data);
+			if (chip->msi_doorbell_info)
+				break;
+		}
+		data = data->parent_data;
+	}
+
+	if (!data)
+		return 0;
+
+	dbinfo = chip->msi_doorbell_info(data);
+	if (!dbinfo)
+		return -EINVAL;
+
+	if (!dbinfo->doorbell_is_percpu) {
+		if (!map) {
+			iommu_msi_put_doorbell_iova(domain,
+						    dbinfo->global_doorbell);
+			return 0;
+		}
+		return iommu_msi_get_doorbell_iova(domain,
+						   dbinfo->global_doorbell,
+						   dbinfo->size, dbinfo->prot,
+						   &iova);
+	}
+
+	/* percpu doorbells */
+	for_each_possible_cpu(cpu) {
+		phys_addr_t __percpu *db_addr =
+			per_cpu_ptr(dbinfo->percpu_doorbells, cpu);
+
+		if (!map) {
+			iommu_msi_put_doorbell_iova(domain, *db_addr);
+		} else {
+
+			ret = iommu_msi_get_doorbell_iova(domain, *db_addr,
+							  dbinfo->size,
+							  dbinfo->prot, &iova);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
  * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain
  * @domain:	The domain to allocate from
  * @dev:	Pointer to device struct of the device for which the interrupts
@@ -352,17 +422,29 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
 
 		virq = __irq_domain_alloc_irqs(domain, virq, desc->nvec_used,
 					       dev_to_node(dev), &arg, false);
-		if (virq < 0) {
-			ret = -ENOSPC;
-			if (ops->handle_error)
-				ret = ops->handle_error(domain, desc, ret);
-			if (ops->msi_finish)
-				ops->msi_finish(&arg, ret);
-			return ret;
-		}
+		if (virq < 0)
+			goto error;
 
 		for (i = 0; i < desc->nvec_used; i++)
 			irq_set_msi_desc_off(virq, i, desc);
+
+		for (i = 0; i < desc->nvec_used; i++) {
+			struct irq_data *d = irq_get_irq_data(virq + i);
+
+			ret = msi_handle_doorbell_mappings(d, true);
+			if (ret)
+				break;
+		}
+		if (ret) {
+			for (; i >= 0; i--) {
+				struct irq_data *d = irq_get_irq_data(virq + i);
+
+				msi_handle_doorbell_mappings(d, false);
+			}
+			irq_domain_free_irqs(virq, desc->nvec_used);
+			desc->irq = 0;
+			goto error;
+		}
 	}
 
 	if (ops->msi_finish)
@@ -377,6 +459,13 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
 	}
 
 	return 0;
+error:
+	ret = -ENOSPC;
+	if (ops->handle_error)
+		ret = ops->handle_error(domain, desc, ret);
+	if (ops->msi_finish)
+		ops->msi_finish(&arg, ret);
+	return ret;
 }
 
 /**
@@ -396,6 +485,9 @@ void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
 		 * entry. If that's the case, don't do anything.
 		 */
 		if (desc->irq) {
+			msi_handle_doorbell_mappings(
+				irq_get_irq_data(desc->irq),
+				false);
 			irq_domain_free_irqs(desc->irq, desc->nvec_used);
 			desc->irq = 0;
 		}
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 08:18:14 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed,  4 May 2016 15:18:14 +0000
Subject: [PATCH v9 8/8] genirq/msi: use the MSI doorbell's IOVA when requested
In-Reply-To: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
Message-ID: <1462375094-2390-9-git-send-email-eric.auger@linaro.org>

On MSI message composition we now use the MSI doorbell's IOVA in
place of the doorbell's PA in case the device is upstream to an
IOMMU that requires MSI addresses to be mapped. The doorbell's
allocation and mapping happened on an early stage (pci_enable_msi).

Signed-off-by: Eric Auger <eric.auger at linaro.org>

---
v8 -> v9:
- Braces on both sides of the 'else' in msi_compose

v7 -> v8:
- use iommu_msi_msg_pa_to_va
- add WARN_ON

v6 -> v7:
- allocation/mapping is done at an earlier stage. We now just perform
  the iova lookup. So it is safe now to be called in a code that cannot
  sleep. iommu_msi_set_doorbell_iova is moved in the dma-reserved-iommu
  API: I think it cleans things up with respect to various #ifdef CONFIGS.

v5:
- use macros to increase the readability
- add comments
- fix a typo that caused a compilation error if CONFIG_IOMMU_API
  is not set
---
 kernel/irq/msi.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index d654524..082e6de 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -62,10 +62,18 @@ static int msi_compose(struct irq_data *irq_data,
 {
 	int ret = 0;
 
-	if (erase)
+	if (erase) {
 		memset(msg, 0, sizeof(*msg));
-	else
+	} else {
+		struct device *dev;
+
 		ret = irq_chip_compose_msi_msg(irq_data, msg);
+		if (ret)
+			return ret;
+
+		dev = msi_desc_to_dev(irq_data_get_msi_desc(irq_data));
+		WARN_ON(iommu_msi_msg_pa_to_va(dev, msg));
+	}
 
 	return ret;
 }
-- 
1.9.1



From eric.auger at linaro.org  Wed May  4 08:22:19 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed, 4 May 2016 17:22:19 +0200
Subject: [PATCH v8 7/8] genirq/msi: map/unmap the MSI doorbells on
 msi_domain_alloc/free_irqs
In-Reply-To: <5729F756.7060500@arm.com>
References: <1461831730-5575-1-git-send-email-eric.auger@linaro.org>
 <1461831730-5575-8-git-send-email-eric.auger@linaro.org>
 <5729F756.7060500@arm.com>
Message-ID: <572A13AB.6000208@linaro.org>

Hi Marc,
On 05/04/2016 03:21 PM, Marc Zyngier wrote:
> On 28/04/16 09:22, Eric Auger wrote:
>> This patch handles the iommu mapping of MSI doorbells that require to
>> be mapped in an iommu domain. This happens on msi_domain_alloc/free_irqs
>> since this is called in code that can sleep (pci_enable/disable_msi):
>> iommu_map/unmap is not stated as atomic. On msi_domain_(de)activate and
>> msi_domain_set_affinity, which must be atomic, we just lookup for this
>> pre-allocated/mapped IOVA.
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>
>> ---
>> v7 -> v8:
>> - new percpu pointer type
>> - exit from the irq domain hierarchy parsing on first map/unmap success
>> - reset desc->irq to 0 on mapping failure
>>
>> v7: creation
>> ---
>>  kernel/irq/msi.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++------
>>  1 file changed, 79 insertions(+), 8 deletions(-)
>>
>> diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
>> index 72bf4d6..d5f95e6 100644
>> --- a/kernel/irq/msi.c
>> +++ b/kernel/irq/msi.c
>> @@ -14,6 +14,8 @@
>>  #include <linux/irq.h>
>>  #include <linux/irqdomain.h>
>>  #include <linux/msi.h>
>> +#include <linux/msi-iommu.h>
>> +#include <linux/iommu.h>
>>  
>>  /* Temparory solution for building, will be removed later */
>>  #include <linux/pci.h>
>> @@ -322,6 +324,56 @@ int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
>>  }
>>  
>>  /**
>> + * msi_handle_doorbell_mappings: in case the irq data corresponds to an
>> + * MSI that requires iommu mapping, traverse the irq domain hierarchy
>> + * to retrieve the doorbells to handle and iommu_map/unmap them according
>> + * to @map boolean.
>> + *
>> + * @data: irq data handle
>> + * @map: mapping if true, unmapping if false
>> + */
>> +static int msi_handle_doorbell_mappings(struct irq_data *data, bool map)
>> +{
>> +	for (; data; data = data->parent_data) {
>> +		struct device *dev =
>> +			msi_desc_to_dev(irq_data_get_msi_desc(data));
>> +		struct irq_chip *chip = irq_data_get_irq_chip(data);
>> +		const struct irq_chip_msi_doorbell_info *dbinfo;
>> +		struct iommu_domain *domain;
>> +		phys_addr_t __percpu *db_addr;
>> +		dma_addr_t iova;
>> +		int ret = 0, i;
>> +
>> +		domain = iommu_msi_domain(dev);
>> +		if (!domain)
>> +			continue;
>> +
>> +		if (!chip->msi_doorbell_info)
>> +			continue;
>> +
>> +		dbinfo = chip->msi_doorbell_info(data);
>> +		if (!dbinfo)
>> +			return -EINVAL;
>> +
>> +		for (i = 0; i < dbinfo->nb_doorbells; i++) {
>> +			db_addr = per_cpu_ptr(dbinfo->percpu_doorbells, i);
>> +			if (map) {
>> +				ret = iommu_msi_get_doorbell_iova(domain,
>> +								  *db_addr,
>> +								  dbinfo->size,
>> +								  dbinfo->prot,
>> +								  &iova);
>> +				if (ret)
>> +					return ret;
>> +			} else
>> +				iommu_msi_put_doorbell_iova(domain, *db_addr);
>> +		}
>> +		break;
>> +	}
>> +	return 0;
>> +}
> 
> I'm really not fond of this whole loop. Could you try to decouple the
> irq_data parsing (looking for a msi_doorbell_info method) from the
> actual mapping/unmapping? This would make it a lot more readable.
> Something along the lines of:
Just sent v9 where I addressed all your comments. Please let me know
whether this looks better.
> 
> 	struct device *dev;
> 	struct irq_chip *chip;
> 	struct iommu_domain *domain;
> 	const struct irq_chip_msi_doorbell_info *dbinfo;
> 
> 	while (data) {
> 		dev = msi_desc_to_dev(irq_data_get_msi_desc(data));
> 		domain = iommu_msi_domain(dev);
> 		if (!domain)
> 			continue;
> 
> 		chip = irq_data_get_irq_chip(data);
> 		if (chip->msi_doorbell_info)
> 			break;
> 
> 		data = data->parent;
> 	}
> 
> 	if (!data)
> 		return 0;
> 
> 	dbinfo = chip->msi_doorbell_info(data);
> 	if (!dbinfo)
> 		return -EINVAL;
> 
> 	[... handle mapping/unmapping here ...]
> 
>> +
>> +/**
>>   * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain
>>   * @domain:	The domain to allocate from
>>   * @dev:	Pointer to device struct of the device for which the interrupts
>> @@ -352,17 +404,26 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
>>  
>>  		virq = __irq_domain_alloc_irqs(domain, virq, desc->nvec_used,
>>  					       dev_to_node(dev), &arg, false);
>> -		if (virq < 0) {
>> -			ret = -ENOSPC;
>> -			if (ops->handle_error)
>> -				ret = ops->handle_error(domain, desc, ret);
>> -			if (ops->msi_finish)
>> -				ops->msi_finish(&arg, ret);
>> -			return ret;
>> -		}
>> +		if (virq < 0)
>> +			goto error;
>>  
>>  		for (i = 0; i < desc->nvec_used; i++)
>>  			irq_set_msi_desc_off(virq, i, desc);
>> +
>> +		for (i = 0; i < desc->nvec_used; i++) {
>> +			ret = msi_handle_doorbell_mappings(
>> +				irq_get_irq_data(virq + i), true);
> 
> Do not be afraid of longer lines. Or if you are, create an intermediate
> variable. But this kind of construct makes my brain work harder, and I
> hate the feeling... ;-)
Yes I am afraid of checkpatch and I do my utmost to abide by its law ;-)
Well, let me know if the v9 is of any relief for your brain ;-)

Thanks for your time!

Eric
> 
>> +			if (ret)
>> +				break;
>> +		}
>> +		if (ret) {
>> +			for (; i >= 0; i--)
>> +				msi_handle_doorbell_mappings(
>> +					irq_get_irq_data(virq + i), false);
>> +			irq_domain_free_irqs(virq, desc->nvec_used);
>> +			desc->irq = 0;
>> +			goto error;
>> +		}
>>  	}
>>  
>>  	if (ops->msi_finish)
>> @@ -377,6 +438,13 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
>>  	}
>>  
>>  	return 0;
>> +error:
>> +	ret = -ENOSPC;
>> +	if (ops->handle_error)
>> +		ret = ops->handle_error(domain, desc, ret);
>> +	if (ops->msi_finish)
>> +		ops->msi_finish(&arg, ret);
>> +	return ret;
>>  }
>>  
>>  /**
>> @@ -396,6 +464,9 @@ void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
>>  		 * entry. If that's the case, don't do anything.
>>  		 */
>>  		if (desc->irq) {
>> +			msi_handle_doorbell_mappings(
>> +				irq_get_irq_data(desc->irq),
>> +				false);
>>  			irq_domain_free_irqs(desc->irq, desc->nvec_used);
>>  			desc->irq = 0;
>>  		}
>>
> 
> Thanks,
> 
> 	M.
> 



From mark.rutland at arm.com  Wed May  4 08:26:01 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 4 May 2016 16:26:01 +0100
Subject: [PATCH] perf/core / arm_pmu: special-case hetereogeneous CPUs
In-Reply-To: <20160504150848.GS3430@twins.programming.kicks-ass.net>
References: <20160425175837.GB3141@leverpostej>
 <20160425190334.GK3448@twins.programming.kicks-ass.net>
 <20160426103346.GA20836@leverpostej>
 <20160504134419.GA15849@leverpostej>
 <20160504150848.GS3430@twins.programming.kicks-ass.net>
Message-ID: <20160504152601.GA15086@leverpostej>

On Wed, May 04, 2016 at 05:08:48PM +0200, Peter Zijlstra wrote:
> On Wed, May 04, 2016 at 02:44:20PM +0100, Mark Rutland wrote:
> > > Ok, how about the below? (based on next-20160422).
> > 
> > Peter, any thoughts?
> > 
> 
> Right, I have it queued, should hopefully hit tip tomorrow someplace.

Cheers, that's much appreciated!

Mark.


From robin.murphy at arm.com  Wed May  4 08:33:11 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed, 4 May 2016 16:33:11 +0100
Subject: [PATCH RESEND] iommu/dma: Implement scatterlist segment merging
In-Reply-To: <b87bf47e79febb3ca904140db09cf095238b2817.1460373907.git.robin.murphy@arm.com>
References: <b87bf47e79febb3ca904140db09cf095238b2817.1460373907.git.robin.murphy@arm.com>
Message-ID: <572A1637.7000509@arm.com>

Hi Joerg,

On 11/04/16 12:32, Robin Murphy wrote:
> Stop wasting IOVA space by over-aligning scatterlist segments for a
> theoretical worst-case segment boundary mask, and instead take the real
> limits into account to merge consecutive segments wherever appropriate,
> so our callers can benefit from getting back nicely simplified lists.
>
> This also represents the last piece of functionality wanted by users of
> the current arch/arm implementation, thus brings us a small step closer
> to converting that over to the common code.
>
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
>
> As requested, reposting rebased onto -rc3.

Just checking whether this has slipped through the cracks? It would be 
nice to tick it off for 4.7 (even if the video folks seem to have gone 
quiet lately).

Thanks,
Robin.

>   drivers/iommu/dma-iommu.c | 84 ++++++++++++++++++++++++++++++++++-------------
>   1 file changed, 61 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 58f2fe6..886cb3a 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -389,26 +389,58 @@ void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
>
>   /*
>    * Prepare a successfully-mapped scatterlist to give back to the caller.
> - * Handling IOVA concatenation can come later, if needed
> + *
> + * At this point the segments are already laid out by iommu_dma_map_sg() to
> + * avoid individually crossing any boundaries, so we merely need to check a
> + * segment's start address to avoid concatenating across one.
>    */
>   static int __finalise_sg(struct device *dev, struct scatterlist *sg, int nents,
>   		dma_addr_t dma_addr)
>   {
> -	struct scatterlist *s;
> -	int i;
> +	struct scatterlist *s, *cur = sg;
> +	unsigned long seg_mask = dma_get_seg_boundary(dev);
> +	unsigned int cur_len = 0, max_len = dma_get_max_seg_size(dev);
> +	int i, count = 0;
>
>   	for_each_sg(sg, s, nents, i) {
> -		/* Un-swizzling the fields here, hence the naming mismatch */
> -		unsigned int s_offset = sg_dma_address(s);
> +		/* Restore this segment's original unaligned fields first */
> +		unsigned int s_iova_off = sg_dma_address(s);
>   		unsigned int s_length = sg_dma_len(s);
> -		unsigned int s_dma_len = s->length;
> +		unsigned int s_iova_len = s->length;
>
> -		s->offset += s_offset;
> +		s->offset += s_iova_off;
>   		s->length = s_length;
> -		sg_dma_address(s) = dma_addr + s_offset;
> -		dma_addr += s_dma_len;
> +		sg_dma_address(s) = DMA_ERROR_CODE;
> +		sg_dma_len(s) = 0;
> +
> +		/*
> +		 * Now fill in the real DMA data. If...
> +		 * - there is a valid output segment to append to
> +		 * - and this segment starts on an IOVA page boundary
> +		 * - but doesn't fall at a segment boundary
> +		 * - and wouldn't make the resulting output segment too long
> +		 */
> +		if (cur_len && !s_iova_off && (dma_addr & seg_mask) &&
> +		    (cur_len + s_length <= max_len)) {
> +			/* ...then concatenate it with the previous one */
> +			cur_len += s_length;
> +		} else {
> +			/* Otherwise start the next output segment */
> +			if (i > 0)
> +				cur = sg_next(cur);
> +			cur_len = s_length;
> +			count++;
> +
> +			sg_dma_address(cur) = dma_addr + s_iova_off;
> +		}
> +
> +		sg_dma_len(cur) = cur_len;
> +		dma_addr += s_iova_len;
> +
> +		if (s_length + s_iova_off < s_iova_len)
> +			cur_len = 0;
>   	}
> -	return i;
> +	return count;
>   }
>
>   /*
> @@ -446,34 +478,40 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
>   	struct scatterlist *s, *prev = NULL;
>   	dma_addr_t dma_addr;
>   	size_t iova_len = 0;
> +	unsigned long mask = dma_get_seg_boundary(dev);
>   	int i;
>
>   	/*
>   	 * Work out how much IOVA space we need, and align the segments to
>   	 * IOVA granules for the IOMMU driver to handle. With some clever
>   	 * trickery we can modify the list in-place, but reversibly, by
> -	 * hiding the original data in the as-yet-unused DMA fields.
> +	 * stashing the unaligned parts in the as-yet-unused DMA fields.
>   	 */
>   	for_each_sg(sg, s, nents, i) {
> -		size_t s_offset = iova_offset(iovad, s->offset);
> +		size_t s_iova_off = iova_offset(iovad, s->offset);
>   		size_t s_length = s->length;
> +		size_t pad_len = (mask - iova_len + 1) & mask;
>
> -		sg_dma_address(s) = s_offset;
> +		sg_dma_address(s) = s_iova_off;
>   		sg_dma_len(s) = s_length;
> -		s->offset -= s_offset;
> -		s_length = iova_align(iovad, s_length + s_offset);
> +		s->offset -= s_iova_off;
> +		s_length = iova_align(iovad, s_length + s_iova_off);
>   		s->length = s_length;
>
>   		/*
> -		 * The simple way to avoid the rare case of a segment
> -		 * crossing the boundary mask is to pad the previous one
> -		 * to end at a naturally-aligned IOVA for this one's size,
> -		 * at the cost of potentially over-allocating a little.
> +		 * Due to the alignment of our single IOVA allocation, we can
> +		 * depend on these assumptions about the segment boundary mask:
> +		 * - If mask size >= IOVA size, then the IOVA range cannot
> +		 *   possibly fall across a boundary, so we don't care.
> +		 * - If mask size < IOVA size, then the IOVA range must start
> +		 *   exactly on a boundary, therefore we can lay things out
> +		 *   based purely on segment lengths without needing to know
> +		 *   the actual addresses beforehand.
> +		 * - The mask must be a power of 2, so pad_len == 0 if
> +		 *   iova_len == 0, thus we cannot dereference prev the first
> +		 *   time through here (i.e. before it has a meaningful value).
>   		 */
> -		if (prev) {
> -			size_t pad_len = roundup_pow_of_two(s_length);
> -
> -			pad_len = (pad_len - iova_len) & (pad_len - 1);
> +		if (pad_len && pad_len < s_length - 1) {
>   			prev->length += pad_len;
>   			iova_len += pad_len;
>   		}
>



From chris.brand at broadcom.com  Wed May  4 08:57:06 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Wed, 4 May 2016 08:57:06 -0700
Subject: [PATCH 1/2] dt-bindings: arm,gic: Indtroduce optional property
 'arm,msi-offset-spi' for gicv2m
In-Reply-To: <1462319245-32532-2-git-send-email-ray.jui@broadcom.com>
References: <1462319245-32532-1-git-send-email-ray.jui@broadcom.com>
 <1462319245-32532-2-git-send-email-ray.jui@broadcom.com>
Message-ID: <CAMsMSK_jwd6OMMJ8DfAckVJgav9U6p-oz9YcinUinaqj2xdwAA@mail.gmail.com>

You have a typo in the subject line - "Indtroduce".

Chris

On Tue, May 3, 2016 at 4:47 PM, Ray Jui <ray.jui at broadcom.com> wrote:
> Update the GICv2m binding document by adding an optional property
> 'arm,msi-offset-spi'.
>
> Some implementations of gicv2m have an erratum where the MSI data is
> the SPI number subtracted by an offset. This is required for the
> correct MSI interrupt to be triggered.
>
> Signed-off-by: Ray Jui <ray.jui at broadcom.com>
> ---
>  Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
> index 793c20f..550960f 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
> +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
> @@ -140,6 +140,12 @@ Optional properties:
>                       value, this property should contain the number of
>                       SPIs assigned to the frame, overriding the HW value.
>
> +- arm,msi-offset-spi: Some implementations of gicv2m have an erratum where
> +                     the MSI data is the SPI number subtracted by an offset.
> +                     This is required for the correct MSI interrupt to be
> +                     triggered. This property should contain the required
> +                     offset.
> +
>  Example:
>
>         interrupt-controller at e1101000 {
> --
> 2.1.4
>


From panand at redhat.com  Wed May  4 08:59:32 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 4 May 2016 21:29:32 +0530
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <572A0577.1070000@codeaurora.org>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <5728A7C3.4010001@roeck-us.net>
 <20160503143856.GE13045@dhcppc6.redhat.com>
 <5728BEC4.6050603@codeaurora.org>
 <20160503155141.GF13045@dhcppc6.redhat.com>
 <20160503171602.GA2518@roeck-us.net>
 <20160504141449.GG13045@dhcppc6.redhat.com>
 <572A0577.1070000@codeaurora.org>
Message-ID: <20160504155932.GH13045@dhcppc6.redhat.com>

+Dave

Hi Timur,

On 04/05/2016:09:21:43 AM, Timur Tabi wrote:
> Pratyush Anand wrote:
> >static irqreturn_t sbsa_gwdt_interrupt(int irq, void *dev_id)
> >{
> >+    struct sbsa_gwdt *gwdt = (struct sbsa_gwdt *)dev_id;
> >+    struct watchdog_device *wdd = &gwdt->wdd;
> >+    u64 timeout = (u64)gwdt->clk * wdd->timeout;
> >+
> >+    writeq(timeout + arch_counter_get_cntvct(),
> >+                    gwdt->control_base + SBSA_GWDT_WCV);
> >+
> >      panic(WATCHDOG_NAME " timeout");
> 
> I'm on the fence about this.
> 
> On one hand, I have always opposed the idea that the interrupt handler needs
> to function properly in order for the timeout to be correct.  Fu's original
> patch required this for every timeout.
> 
> The current code, however, only uses the interrupt when action=1.  In this
> case, WCV is only reprogrammed in order to prevent the system from resetting
> during the kexec.  Technically, the watchdog timeout has already been
> handled.

Yes.

> 
> However, this should be unnecessary, because it can't be a problem that's
> unique to the SBSA watchdog.  Every system that kexecs another kernel needs
> to be able to handle a watchdog timeout.  Shouldn't the kexec code already
> ping or disable the watchdog?  We need a cross-platform solution.  Drivers
> should not need to do this.

Its unique to SBSA because you have very little timeout here. kexec-tools
upstream does not have any mechanism to handle watchdog timeout. Lets say even
if we implement a framework there, the best it can do is to ping the watchdog
again. Disabling should not be an option in kexec-tools, because in that case if
kexec-tools or secondary kernel stuck, we won't have a way out.
Now, even if we ping it once in kexec tools, we will have to make sure that
watchdog driver's probe is called before timeout. Therefore, user must have a
way to specify this timeout, so that if a particular kernel take more time to
boot then he can increase the timeout. Given, these variable conditions I do not
see much advantage of implementing it in kexec-tools.

However fedora/rhel kedumpctl mechanism does some  best case correction. It
makes sure that watchdog module is loaded in second kernel if watchdog was
active during first kernel, and loaded as early as possible [1].

~Pratyush

[1] https://github.com/pratyushanand/kexec-tools/commits/watchdog_fmaster


From ray.jui at broadcom.com  Wed May  4 09:11:58 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Wed, 4 May 2016 09:11:58 -0700
Subject: [PATCH 1/2] dt-bindings: arm,gic: Indtroduce optional property
 'arm,msi-offset-spi' for gicv2m
In-Reply-To: <CAMsMSK_jwd6OMMJ8DfAckVJgav9U6p-oz9YcinUinaqj2xdwAA@mail.gmail.com>
References: <1462319245-32532-1-git-send-email-ray.jui@broadcom.com>
 <1462319245-32532-2-git-send-email-ray.jui@broadcom.com>
 <CAMsMSK_jwd6OMMJ8DfAckVJgav9U6p-oz9YcinUinaqj2xdwAA@mail.gmail.com>
Message-ID: <3997ed69-760a-9bc1-a451-d07323a6e163@broadcom.com>



On 5/4/2016 8:57 AM, Chris Brand wrote:
> You have a typo in the subject line - "Indtroduce".

Thanks, but now this patch will be gone based on review comments from 
Marc on PATCH 2/2.

>
> Chris
>
> On Tue, May 3, 2016 at 4:47 PM, Ray Jui <ray.jui at broadcom.com> wrote:
>> Update the GICv2m binding document by adding an optional property
>> 'arm,msi-offset-spi'.
>>
>> Some implementations of gicv2m have an erratum where the MSI data is
>> the SPI number subtracted by an offset. This is required for the
>> correct MSI interrupt to be triggered.
>>
>> Signed-off-by: Ray Jui <ray.jui at broadcom.com>
>> ---
>>  Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt | 6 ++++++
>>  1 file changed, 6 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
>> index 793c20f..550960f 100644
>> --- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
>> +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
>> @@ -140,6 +140,12 @@ Optional properties:
>>                       value, this property should contain the number of
>>                       SPIs assigned to the frame, overriding the HW value.
>>
>> +- arm,msi-offset-spi: Some implementations of gicv2m have an erratum where
>> +                     the MSI data is the SPI number subtracted by an offset.
>> +                     This is required for the correct MSI interrupt to be
>> +                     triggered. This property should contain the required
>> +                     offset.
>> +
>>  Example:
>>
>>         interrupt-controller at e1101000 {
>> --
>> 2.1.4
>>


From timur at codeaurora.org  Wed May  4 09:17:29 2016
From: timur at codeaurora.org (Timur Tabi)
Date: Wed, 4 May 2016 11:17:29 -0500
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <20160504155932.GH13045@dhcppc6.redhat.com>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <5728A7C3.4010001@roeck-us.net> <20160503143856.GE13045@dhcppc6.redhat.com>
 <5728BEC4.6050603@codeaurora.org> <20160503155141.GF13045@dhcppc6.redhat.com>
 <20160503171602.GA2518@roeck-us.net>
 <20160504141449.GG13045@dhcppc6.redhat.com> <572A0577.1070000@codeaurora.org>
 <20160504155932.GH13045@dhcppc6.redhat.com>
Message-ID: <572A2099.4070901@codeaurora.org>

Pratyush Anand wrote:
> Its unique to SBSA because you have very little timeout here. kexec-tools
> upstream does not have any mechanism to handle watchdog timeout. Lets say even
> if we implement a framework there, the best it can do is to ping the watchdog
> again.

Ok, so it's more accurate to say that kexec has a minimum watchdog 
timeout requirement.  What happens if the system admin sets the timeout 
to 5 seconds arbitrarily?  The system will reset during kexec, no matter 
which hardware is used.

This still sounds like a band-aid to me.  We're just assuming that we 
need a timeout of at least 20 seconds to support kexec.  Frankly, this 
still sounds like a problem the kexec developers needs to acknowledge 
and deal with.

Still I'm okay with a patch that extends the timeout by programming WCV, 
but it has to be commented as a hack specifically to support kexec 
because the timeout might be too short.  Then Wim can decide whether he 
supports such changes.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum, a Linux Foundation collaborative project.


From ray.jui at broadcom.com  Wed May  4 09:20:51 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Wed, 4 May 2016 09:20:51 -0700
Subject: [PATCH 2/2] irqchip/gic-v2m: Add workaround for Broadcom NS2
 GICv2m erratum
In-Reply-To: <5729A9A3.6070207@arm.com>
References: <1462319245-32532-1-git-send-email-ray.jui@broadcom.com>
 <1462319245-32532-3-git-send-email-ray.jui@broadcom.com>
 <5729A9A3.6070207@arm.com>
Message-ID: <964ae899-2fd1-baa4-521d-a31326281aa0@broadcom.com>

Hi Marc,

On 5/4/2016 12:49 AM, Marc Zyngier wrote:
> On 04/05/16 00:47, Ray Jui wrote:
>> Alex Barba <alex.barba at broadcom.com> discovered Broadcom NS2 GICv2m
>> implementation has an erratum where the MSI data needs to be the SPI
>> number subtracted by an offset of 32, for the correct MSI interrupt to
>> be triggered.
>>
>> We are aware that APM X-Gene GICv2m has a similar erratum where the
>> MSI data needs to be the offset from the spi_start. While APM's workaround
>> is triggered based on readings from the MSI_IIDR register, this patch
>> contains a more general solution by allowing this offset to be
>> specified with an optional DT property 'arm,msi-offset-spi'. This patch
>> also maintains compatibility with existing APM platforms
>
> It may be more generic, but it also fails to deal with less capable
> firmware implementations. In contrast, reading MSI_IIDR is always
> possible (assuming you have a unique ID for this v2m implementation).
>
> If you cannot uniquely identify it using an ID register, the usual
> alternative is to have a new "compatible" string identifying the
> defective part, and set the offset based on this string. This still
> fails the ACPI test, but is the least invasive DT-wise.

Okay. We do seem to have an ID. The JEP code looks a bit weird as the 
IIDR register reads 0x13f. We were just a bit concerned that there's 
another chip from Broadcom that may happen to have the same ID but may 
already have this offset issue fixed (or made worse with a different 
offset, :) ). Since that chip has not even taped out yet, we can wait 
till later to confirm. If a compatible string is needed in the future, 
we'll add that.

For now, I'm going to submit another patch to deal with this offset 
based on IIDR reading 0x13f.

>
> Thanks,
>
> 	M.
>

Thanks,

Ray


From john at metanate.com  Wed May  4 09:21:57 2016
From: john at metanate.com (John Keeping)
Date: Wed,  4 May 2016 17:21:57 +0100
Subject: [PATCH v2 2/2] ASoC: rockchip: Revert "ASoC: rockchip: i2s: separate
 capture and playback"
In-Reply-To: <1462378917-24135-1-git-send-email-john@metanate.com>
References: <1462378917-24135-1-git-send-email-john@metanate.com>
Message-ID: <1462378917-24135-2-git-send-email-john@metanate.com>

This reverts commit eba65d179c1149cf79e68608d452631f33d7f017.

This broke audio on Veyron Jerry Chromebooks and I now cannot reproduce
the problem I was trying to fix even with this commit reverted, so it
seems that this was completely the wrong thing to do.

Reported-by: Enric Balletbo Serra <eballetbo at gmail.com>
Signed-off-by: John Keeping <john at metanate.com>
---
v2: Add "ASoC: rockchip: " prefix to subject

 sound/soc/rockchip/rockchip_i2s.c | 72 ++++++++++++++++++++++-----------------
 1 file changed, 40 insertions(+), 32 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 34743ec61c49..574c6af28c06 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -82,8 +82,8 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
 				   I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
 
 		regmap_update_bits(i2s->regmap, I2S_XFER,
-				   I2S_XFER_TXS_START,
-				   I2S_XFER_TXS_START);
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START);
 
 		i2s->tx_start = true;
 	} else {
@@ -92,23 +92,27 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
 		regmap_update_bits(i2s->regmap, I2S_DMACR,
 				   I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
 
-		regmap_update_bits(i2s->regmap, I2S_XFER,
-				   I2S_XFER_TXS_START,
-				   I2S_XFER_TXS_STOP);
-
-		regmap_update_bits(i2s->regmap, I2S_CLR,
-				   I2S_CLR_TXC,
-				   I2S_CLR_TXC);
+		if (!i2s->rx_start) {
+			regmap_update_bits(i2s->regmap, I2S_XFER,
+					   I2S_XFER_TXS_START |
+					   I2S_XFER_RXS_START,
+					   I2S_XFER_TXS_STOP |
+					   I2S_XFER_RXS_STOP);
 
-		regmap_read(i2s->regmap, I2S_CLR, &val);
+			regmap_update_bits(i2s->regmap, I2S_CLR,
+					   I2S_CLR_TXC | I2S_CLR_RXC,
+					   I2S_CLR_TXC | I2S_CLR_RXC);
 
-		/* Should wait for clear operation to finish */
-		while (val & I2S_CLR_TXC) {
 			regmap_read(i2s->regmap, I2S_CLR, &val);
-			retry--;
-			if (!retry) {
-				dev_warn(i2s->dev, "fail to clear\n");
-				break;
+
+			/* Should wait for clear operation to finish */
+			while (val) {
+				regmap_read(i2s->regmap, I2S_CLR, &val);
+				retry--;
+				if (!retry) {
+					dev_warn(i2s->dev, "fail to clear\n");
+					break;
+				}
 			}
 		}
 	}
@@ -124,8 +128,8 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
 				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
 
 		regmap_update_bits(i2s->regmap, I2S_XFER,
-				   I2S_XFER_RXS_START,
-				   I2S_XFER_RXS_START);
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START);
 
 		i2s->rx_start = true;
 	} else {
@@ -134,23 +138,27 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
 		regmap_update_bits(i2s->regmap, I2S_DMACR,
 				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
 
-		regmap_update_bits(i2s->regmap, I2S_XFER,
-				   I2S_XFER_RXS_START,
-				   I2S_XFER_RXS_STOP);
-
-		regmap_update_bits(i2s->regmap, I2S_CLR,
-				   I2S_CLR_RXC,
-				   I2S_CLR_RXC);
+		if (!i2s->tx_start) {
+			regmap_update_bits(i2s->regmap, I2S_XFER,
+					   I2S_XFER_TXS_START |
+					   I2S_XFER_RXS_START,
+					   I2S_XFER_TXS_STOP |
+					   I2S_XFER_RXS_STOP);
 
-		regmap_read(i2s->regmap, I2S_CLR, &val);
+			regmap_update_bits(i2s->regmap, I2S_CLR,
+					   I2S_CLR_TXC | I2S_CLR_RXC,
+					   I2S_CLR_TXC | I2S_CLR_RXC);
 
-		/* Should wait for clear operation to finish */
-		while (val & I2S_CLR_RXC) {
 			regmap_read(i2s->regmap, I2S_CLR, &val);
-			retry--;
-			if (!retry) {
-				dev_warn(i2s->dev, "fail to clear\n");
-				break;
+
+			/* Should wait for clear operation to finish */
+			while (val) {
+				regmap_read(i2s->regmap, I2S_CLR, &val);
+				retry--;
+				if (!retry) {
+					dev_warn(i2s->dev, "fail to clear\n");
+					break;
+				}
 			}
 		}
 	}
-- 
2.8.0.rc4.238.g874082a



From john at metanate.com  Wed May  4 09:21:56 2016
From: john at metanate.com (John Keeping)
Date: Wed,  4 May 2016 17:21:56 +0100
Subject: [PATCH v2 1/2] ASoC: rockchip: Revert "ASoC: rockchip: i2s: remove
 unused variables"
Message-ID: <1462378917-24135-1-git-send-email-john@metanate.com>

This reverts commit 5938448b99275cba95167c3f9d39ca9225fdad38.

It turns out that the commit that made these variables unused is wrong
so we're about to revert it.  Bring back the variables in prepration.

Signed-off-by: John Keeping <john at metanate.com>
---
v2: Add "ASoC: rockchip: " prefix to subject

 sound/soc/rockchip/rockchip_i2s.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 2f8e20416bd3..34743ec61c49 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -34,6 +34,13 @@ struct rk_i2s_dev {
 
 	struct regmap *regmap;
 
+/*
+ * Used to indicate the tx/rx status.
+ * I2S controller hopes to start the tx and rx together,
+ * also to stop them when they are both try to stop.
+*/
+	bool tx_start;
+	bool rx_start;
 	bool is_master_mode;
 };
 
@@ -77,7 +84,11 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
 		regmap_update_bits(i2s->regmap, I2S_XFER,
 				   I2S_XFER_TXS_START,
 				   I2S_XFER_TXS_START);
+
+		i2s->tx_start = true;
 	} else {
+		i2s->tx_start = false;
+
 		regmap_update_bits(i2s->regmap, I2S_DMACR,
 				   I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
 
@@ -115,7 +126,11 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
 		regmap_update_bits(i2s->regmap, I2S_XFER,
 				   I2S_XFER_RXS_START,
 				   I2S_XFER_RXS_START);
+
+		i2s->rx_start = true;
 	} else {
+		i2s->rx_start = false;
+
 		regmap_update_bits(i2s->regmap, I2S_DMACR,
 				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
 
-- 
2.8.0.rc4.238.g874082a



From broonie at kernel.org  Wed May  4 09:22:00 2016
From: broonie at kernel.org (Mark Brown)
Date: Wed, 4 May 2016 17:22:00 +0100
Subject: [RFC PATCH 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <87twiforl3.fsf@belgarion.home>
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
 <20160503162938.GT6292@sirena.org.uk>
 <87twiforl3.fsf@belgarion.home>
Message-ID: <20160504162200.GX6292@sirena.org.uk>

On Tue, May 03, 2016 at 09:43:20PM +0200, Robert Jarzmik wrote:

> You probably mean the BITCLK clock.

> What is a bit pesky about this clock is that it can either be mastered by
> digital controller and the codec is a slave, or the other way around.

That's a bit surprising - I've never encountered a system that
impelemnts this, it may be permitted by the spec but it's always the
CODEC.  The master clock from the CODEC is often provided by the SoC but
I've not seen systems where anything other than the CODEC drives the
actual AC'97 bus.

> >> +int ac97_digital_controller_register(const struct ac97_controller_ops *ops,
> >> +				     struct device *dev);
> >> +int ac97_digital_controller_unregister(const struct device *dev);

> > Why "digital"?

> I copy-pasted this from Audio Codec '97 Revision 2.3, where in several places
> they call the controller a "digital controller".

It's not really adding anything though, it's just clumsy wording on
their part - it's not like we need to distinguish this from analogue
or any other type of AC'97 controllers.

> Now if you prefer "ac97_controller" or something like that, that's as you wish,
> the name does not matter that much to me ;)

Yes.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/59b0edd1/attachment-0001.sig>

From broonie at kernel.org  Wed May  4 09:43:06 2016
From: broonie at kernel.org (Mark Brown)
Date: Wed, 4 May 2016 17:43:06 +0100
Subject: [alsa-devel] [PATCH 1/7] ASoC: mediatek: Refine mt8173 driver
 and change config option
In-Reply-To: <1461934848-60011-2-git-send-email-garlic.tseng@mediatek.com>
References: <1461934848-60011-1-git-send-email-garlic.tseng@mediatek.com>
 <1461934848-60011-2-git-send-email-garlic.tseng@mediatek.com>
Message-ID: <20160504164306.GA6292@sirena.org.uk>

On Fri, Apr 29, 2016 at 09:00:42PM +0800, Garlic Tseng wrote:

>  .../{mtk-afe-pcm.c => mt8173/mt8173-afe-pcm.c}     | 488 ++++++++++-----------

So there's going to be no code sharing at all between this and any other
Mediatek chips?  That seems very surprising, it'd suggest that the
hardware designers were creating a new design completely from scratch
each time which doesn't seem all that likely.  This is an unusual way of
organizing things and we need a much clearer explanation of what's going
on here.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/c512c785/attachment.sig>

From f.fainelli at gmail.com  Wed May  4 10:10:47 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Wed, 4 May 2016 10:10:47 -0700
Subject: [PATCH 1/1] arm64: dts: Enable GPIO for Broadcom NS2 SoC
In-Reply-To: <1457087010-26306-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1457087010-26306-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <572A2D17.8000802@gmail.com>

On 04/03/16 02:23, Yendapally Reddy Dhananjaya Reddy wrote:
> This enables the GPIO support for Broadcom NS2 SoC
> 
> Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>

Applied to devicetree-arm64/next, thanks and sorry about the lag, this
one fell through the cracks.
-- 
Florian


From horia.geanta at nxp.com  Wed May  4 10:16:30 2016
From: horia.geanta at nxp.com (=?UTF-8?q?Horia=20Geant=C4=83?=)
Date: Wed, 4 May 2016 20:16:30 +0300
Subject: [PATCH 2/7] arm64: add io{read,write}64be accessors
Message-ID: <1462382190-11937-1-git-send-email-horia.geanta@nxp.com>

This will allow device drivers to consistently use io{read,write}XXbe
also for 64-bit accesses.

Signed-off-by: Alex Porosanu <alexandru.porosanu at nxp.com>
Signed-off-by: Horia Geant? <horia.geanta at nxp.com>
---
 arch/arm64/include/asm/io.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 44be1e03ed65..9b6e408cfa51 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -174,13 +174,15 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
 #define iounmap				__iounmap
 
 /*
- * io{read,write}{16,32}be() macros
+ * io{read,write}{16,32,64}be() macros
  */
 #define ioread16be(p)		({ __u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
 #define ioread32be(p)		({ __u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })
+#define ioread64be(p)		({ __u64 __v = be64_to_cpu((__force __be64)__raw_readq(p)); __iormb(); __v; })
 
 #define iowrite16be(v,p)	({ __iowmb(); __raw_writew((__force __u16)cpu_to_be16(v), p); })
 #define iowrite32be(v,p)	({ __iowmb(); __raw_writel((__force __u32)cpu_to_be32(v), p); })
+#define iowrite64be(v,p)	({ __iowmb(); __raw_writeq((__force __u64)cpu_to_be64(v), p); })
 
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
-- 
2.4.4



From keescook at chromium.org  Wed May  4 10:20:01 2016
From: keescook at chromium.org (Kees Cook)
Date: Wed, 4 May 2016 10:20:01 -0700
Subject: [PATCH] arm64: Make arch_randomize_brk avoid stack area
In-Reply-To: <1462370994.2895.11.camel@linaro.org>
References: <1461848638.2848.19.camel@linaro.org>
 <1462370994.2895.11.camel@linaro.org>
Message-ID: <CAGXu5jKDh+B7ZzecHtqqHCqGbqs9fXvNAAw7kpTjPCdmQTd7KA@mail.gmail.com>

On Wed, May 4, 2016 at 7:09 AM, Jon Medhurst (Tixy) <tixy at linaro.org> wrote:
> When a process is created, various address randomisations could end up
> colluding to place the address of brk in the stack memory. This would
> mean processes making small heap based memory allocations are in danger
> of having them overwriting, or overwritten by, the stack.
>
> Another consequence, is that even for processes that make no use of
> brk, the output of /proc/*/maps may show the stack area listed as
> '[heap]' rather than '[stack]'. Apart from being misleading this causes
> fatal errors with the Android run-time like:
> "No [stack] line found in /proc/self/task/*/maps"
>
> To prevent this problem pick a limit for brk that allows for the stack's
> memory. At the same time we remove randomize_base() as that was only
> used by arch_randomize_brk().
>
> Note, in practice, since commit d1fd836dcf00 ("mm: split ET_DYN ASLR
> from mmap ASLR") this problem shouldn't occur because the address chosen
> for loading binaries is well clear of the stack, however, prior to that
> the problem does occur because of the following...
>
> The memory layout of a task is determined by arch_pick_mmap_layout. If
> address randomisation is enabled (task has flag PF_RANDOMIZE) this sets
> mmap_base to a random address at the top of task memory just below a
> region calculated to allow for a stack which itself may have a random
> base address. Any mmap operations that then happen which require an
> address allocating will use the topdown allocation method, i.e. the
> first allocated memory will be at the top of memory, just below the
> area set aside for the stack.
>
> When a relocatable binary is loaded into a new process by
> load_elf_binary and randomised address are enabled, it uses a
> 'load_bias' of zero, so that when mmap is called to create a memory
> region for it, a new address is picked (address zero not being
> available). As this is the first memory region in the task, it gets the
> region just below the stack, as described previously.
>
> The loader then set's brk to the end of the elf data section, which will
> be near the end of the loaded binary and then it calls
> arch_randomize_brk. As this currently stands, this adds a random amount
> to brk, which unfortunately may take it into the address range where the
> stack lies.
>
> Testing:
>
> These changes have been tested on Linux v4.6-rc4 using 100000
> invocations of a program [1] that can display the offset of a process's
> brk...
>
> $for i in $(seq 100000); do ./aslr --report brk ; done
>
> This shows values of brk are evenly distributed over a 1GB range, both
> before and after this change.
>
> With Linux version 3.18 (where the collision of brk and stack can happen
> and this change limits brk to avoid that) the distribution of brk values
> after the change shows a slope where lower values for brk are more
> common and upper values have about half the frequency of those.
>
> [1] http://bazaar.launchpad.net/~ubuntu-bugcontrol/qa-regression-testing/master/files/2499/scripts/kernel-security/aslr/
>
> Signed-off-by: Jon Medhurst <tixy at linaro.org>
> Cc: <stable at vger.kernel.org> # 4.0 and earlier

Acked-by: Kees Cook <keescook at chromium.org>

-Kees

>
> ---
>
> Changes since RFC.
> - Fixed compilation errors (finger trouble preparing original email)
> - Updated commit message to included notes on testing
> - Added CC stable for Linux '4.0 and earlier'
>
>  arch/arm64/kernel/process.c | 24 ++++++++++++++++++------
>  1 file changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> index 8062482..26429a0 100644
> --- a/arch/arm64/kernel/process.c
> +++ b/arch/arm64/kernel/process.c
> @@ -382,13 +382,25 @@ unsigned long arch_align_stack(unsigned long sp)
>         return sp & ~0xf;
>  }
>
> -static unsigned long randomize_base(unsigned long base)
> +unsigned long arch_randomize_brk(struct mm_struct *mm)
>  {
> +       unsigned long base = mm->brk;
>         unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
> -       return randomize_range(base, range_end, 0) ? : base;
> -}
> +       unsigned long max_stack, range_limit;
>
> -unsigned long arch_randomize_brk(struct mm_struct *mm)
> -{
> -       return randomize_base(mm->brk);
> +       /*
> +        * Determine how much room we need to leave available for the stack.
> +        * We limit this to a reasonable value, because extremely large or
> +        * unlimited stacks are always going to bump up against brk at some
> +        * point and we don't want to fail to randomise brk in those cases.
> +        */
> +       max_stack = rlimit(RLIMIT_STACK);
> +       if (max_stack > SZ_128M)
> +               max_stack = SZ_128M;
> +
> +       range_limit = mm->start_stack - max_stack - 1;
> +       if (range_end > range_limit)
> +               range_end = range_limit;
> +
> +       return randomize_range(base, range_end, 0) ? : base;
>  }
> --
> 2.1.4
>
>



-- 
Kees Cook
Chrome OS & Brillo Security


From marc.zyngier at arm.com  Wed May  4 10:25:56 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 4 May 2016 18:25:56 +0100
Subject: [PATCH 2/2] irqchip/gic-v2m: Add workaround for Broadcom NS2
 GICv2m erratum
In-Reply-To: <964ae899-2fd1-baa4-521d-a31326281aa0@broadcom.com>
References: <1462319245-32532-1-git-send-email-ray.jui@broadcom.com>
 <1462319245-32532-3-git-send-email-ray.jui@broadcom.com>
 <5729A9A3.6070207@arm.com>
 <964ae899-2fd1-baa4-521d-a31326281aa0@broadcom.com>
Message-ID: <572A30A4.2060806@arm.com>

Hi Ray,

On 04/05/16 17:20, Ray Jui wrote:
> Hi Marc,
> 
> On 5/4/2016 12:49 AM, Marc Zyngier wrote:
>> On 04/05/16 00:47, Ray Jui wrote:
>>> Alex Barba <alex.barba at broadcom.com> discovered Broadcom NS2 GICv2m
>>> implementation has an erratum where the MSI data needs to be the SPI
>>> number subtracted by an offset of 32, for the correct MSI interrupt to
>>> be triggered.
>>>
>>> We are aware that APM X-Gene GICv2m has a similar erratum where the
>>> MSI data needs to be the offset from the spi_start. While APM's workaround
>>> is triggered based on readings from the MSI_IIDR register, this patch
>>> contains a more general solution by allowing this offset to be
>>> specified with an optional DT property 'arm,msi-offset-spi'. This patch
>>> also maintains compatibility with existing APM platforms
>>
>> It may be more generic, but it also fails to deal with less capable
>> firmware implementations. In contrast, reading MSI_IIDR is always
>> possible (assuming you have a unique ID for this v2m implementation).
>>
>> If you cannot uniquely identify it using an ID register, the usual
>> alternative is to have a new "compatible" string identifying the
>> defective part, and set the offset based on this string. This still
>> fails the ACPI test, but is the least invasive DT-wise.
> 
> Okay. We do seem to have an ID. The JEP code looks a bit weird as the 
> IIDR register reads 0x13f. We were just a bit concerned that there's 

Ah, people get creative sometimes...

> another chip from Broadcom that may happen to have the same ID but may 
> already have this offset issue fixed (or made worse with a different 
> offset, :) ). Since that chip has not even taped out yet, we can wait 
> till later to confirm. If a compatible string is needed in the future, 
> we'll add that.

OK. It'd be good to make sure that this ID register is changed. I don't
mind handling a different ID for the same quirk, but being unable to
distinguish a quirky part from a fixed one would be pretty dumb.

> For now, I'm going to submit another patch to deal with this offset 
> based on IIDR reading 0x13f.

Sounds good.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From tony at atomide.com  Wed May  4 10:26:35 2016
From: tony at atomide.com (Tony Lindgren)
Date: Wed, 4 May 2016 10:26:35 -0700
Subject: [PATCH] ARM: dts: omap5-igep0050: Correct hdmi regulator
In-Reply-To: <6ee9d67a-e907-715a-f3f5-d90a470314c3@ti.com>
References: <1461925297-9734-1-git-send-email-peter.ujfalusi@ti.com>
 <6ee9d67a-e907-715a-f3f5-d90a470314c3@ti.com>
Message-ID: <20160504172634.GS5995@atomide.com>

Hi,

Adding Nishanth to Cc.

* Peter Ujfalusi <peter.ujfalusi at ti.com> [160429 05:15]:
> ldo7_reg, obviously ;)
> 
> > 	status = "okay";
> > 	regulator-min-microvolt = <1800000>;
> > 	regulator-max-microvolt = <1800000>;
> > };

It really seems to be ldo7, otherwise there's no HDMI output. I don't
have the schematics either.

But it seems we have at least two other regressions in Linux next that
prevent me from testing this properly:

1. On igepv5, I get this for the MMC regulator

ldo9: bypassed regulator has no supply!
ldo9: failed to get the current voltage(-517)
palmas-pmic 48070000.i2c:palmas at 48:palmas_pmic: failed to register 48070000.i2c:palmar

I'm pretty sure it really is using the ldo9 for MMC just like
omap5-uevm.. Nishanth suggested it may use something else, but
why would it as ldo9 has a nice voltage range?

2. On both omap5-uevm and igepv5, NFSroot hangs

It seems that NFSroot boots to the point where PM runtime now
just shuts down some regulator affecting the USB connected
smsc Ethernet adapter?

Regards,

Tony




From tony at atomide.com  Wed May  4 10:31:53 2016
From: tony at atomide.com (Tony Lindgren)
Date: Wed, 4 May 2016 10:31:53 -0700
Subject: [GIT PULL] omap legacy boot vs dt boot fixes for v4.7 merge window
Message-ID: <20160504173153.GT5995@atomide.com>

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v4.7/legacy-signed

for you to fetch changes up to 10c1f7d32bf451d4309850c15ab1fdadccf92620:

  ARM: OMAP2+: n900 needs MMC slot names for legacy user space (2016-04-28 14:26:33 -0700)

----------------------------------------------------------------
Legacy booting vs device tree booting fixes for omaps for
v4.7 merge window. These are not considered urgent fixes enough
for the v4.6-rc cycle, but we need them in v4.7 in order to drop
the last remaining board-*.c files for omap3 for v4.8 merge window.

On Nokia N900, we need to pass the MMC slot names for the legacy
user space to work. Let's do that using auxdata as the driver is
setting up things already with the pdata for legacy booting. Then
we can later on discuss if we may want to have some generic binding
describing where the MMC slots are on the device.

N900 also has had the ir-rx51 device driver unusable with multiarch
for a long time. Let's pass the dmtimer data in pdata for the driver
to get it going again. Then once things are working, we can eventually
change the driver to use just hrtimer and PWM framework. The driver
changes will be queued separately.

----------------------------------------------------------------
Tony Lindgren (2):
      ARM: OMAP2+: Add more functions to pwm pdata for ir-rx51
      ARM: OMAP2+: n900 needs MMC slot names for legacy user space

 arch/arm/mach-omap2/board-rx51-peripherals.c   | 35 ++++++++++++++++++++--
 arch/arm/mach-omap2/pdata-quirks.c             | 40 +++++++++++++++++++++++++-
 include/linux/platform_data/media/ir-rx51.h    |  1 +
 include/linux/platform_data/pwm_omap_dmtimer.h | 21 ++++++++++++++
 4 files changed, 94 insertions(+), 3 deletions(-)


From oss at buserror.net  Wed May  4 10:35:08 2016
From: oss at buserror.net (Scott Wood)
Date: Wed, 04 May 2016 12:35:08 -0500
Subject: [v9, 6/7] MAINTAINERS: add entry for Freescale SoC driver
In-Reply-To: <1462332274-13744-7-git-send-email-yangbo.lu@nxp.com>
References: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
 <1462332274-13744-7-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462383308.16584.43.camel@buserror.net>

On Wed, 2016-05-04 at 11:24 +0800, Yangbo Lu wrote:
> Add maintainer entry for Freescale SoC driver including
> the QE library and the GUTS driver now. Also add maintainer
> for QE library.
> 
> Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
> ---
> Changes for v8:
> 	- Added this patch
> Changes for v9:
> 	- Added linux-arm mail list
> 	- Removed GUTS driver entry
> ---
>  MAINTAINERS | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 42e65d1..ce91db7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4622,9 +4622,18 @@ F:	drivers/net/ethernet/freescale/fec_ptp.c
>  F:	drivers/net/ethernet/freescale/fec.h
>  F:	Documentation/devicetree/bindings/net/fsl-fec.txt
>  
> +FREESCALE SOC DRIVER
> +M:	Scott Wood <oss at buserror.net>
> +L:	linuxppc-dev at lists.ozlabs.org
> +L:	linux-arm-kernel at lists.infradead.org
> +S:	Maintained
> +F:	drivers/soc/fsl/
> +F:	include/linux/fsl/
> +
>  FREESCALE QUICC ENGINE LIBRARY
> +M:	Qiang Zhao <qiang.zhao at nxp.com>
>  L:	linuxppc-dev at lists.ozlabs.org
> -S:	Orphan
> +S:	Maintained
>  F:	drivers/soc/fsl/qe/
>  F:	include/soc/fsl/*qe*.h
>  F:	include/soc/fsl/*ucc*.h

s/DRIVER/DRIVERS/

There's more than one.

Otherwise:
Acked-by: Scott Wood <oss at buserror.net>

-Scott

> 


From fcooper at ti.com  Wed May  4 10:43:55 2016
From: fcooper at ti.com (Franklin S Cooper Jr)
Date: Wed,  4 May 2016 12:43:55 -0500
Subject: [PATCH] ARM: dts: dra7: Add gpmc dma channel
Message-ID: <1462383835-10839-1-git-send-email-fcooper@ti.com>

Add dma channel information to the gpmc.

Signed-off-by: Franklin S Cooper Jr <fcooper at ti.com>
Signed-off-by: Sekhar Nori <nsekhar at ti.com>
---
This patch is based on top of linux-next where EDMA support for DRA7 has
been added.

 arch/arm/boot/dts/dra7.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index e007401..3a8f397 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -1451,6 +1451,8 @@
 			ti,hwmods = "gpmc";
 			reg = <0x50000000 0x37c>;      /* device IO registers */
 			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&edma_xbar 4 0>;
+			dma-names = "rxtx";
 			gpmc,num-cs = <8>;
 			gpmc,num-waitpins = <2>;
 			#address-cells = <2>;
-- 
2.7.0



From tony at atomide.com  Wed May  4 10:53:07 2016
From: tony at atomide.com (Tony Lindgren)
Date: Wed, 4 May 2016 10:53:07 -0700
Subject: [GIT PULL] non urgent auxdata fix for v4.7 merge window
Message-ID: <20160504175306.GU5995@atomide.com>

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v4.7/auxdata-signed

for you to fetch changes up to d4f414e559caf36d811213e56b56e9b6957caab1:

  ARM: OMAP2+: Simplify auxdata by using the generic match (2016-04-15 08:47:07 -0700)

----------------------------------------------------------------
Device tree auxdata handling fix that allows a match based on the
compatible string if no exact match based on the IO address is found.

This leaves out the need to patch auxdata for each driver when adding
new SoCs. And it also reprotedly fixes the issue of passing auxdata
to a child if the parent instantiates the child from DT as discussed
in the "[PATCH] of/platform: Allow secondary compatible match in
of_dev_lookup" mailing list thread.

As a minimal use case, let's also convert omap pinctrl auxdatato
use a generic match.

There is no need to get this in to the v4.6-rc cycle and it can wait
for v4.7 merge window. Note that these changes have now been sitting
in Linux next for about two weeks so far as I wanted to make sure no
new issues are popping up.

----------------------------------------------------------------
Tony Lindgren (2):
      of/platform: Allow secondary compatible match in of_dev_lookup
      ARM: OMAP2+: Simplify auxdata by using the generic match

 arch/arm/mach-omap2/pdata-quirks.c | 17 ++---------------
 drivers/of/platform.c              | 28 +++++++++++++++++++++++-----
 2 files changed, 25 insertions(+), 20 deletions(-)


From nm at ti.com  Wed May  4 11:01:33 2016
From: nm at ti.com (Nishanth Menon)
Date: Wed, 4 May 2016 13:01:33 -0500
Subject: [PATCH] ARM: dts: omap5-igep0050: Correct hdmi regulator
In-Reply-To: <20160504172634.GS5995@atomide.com>
References: <1461925297-9734-1-git-send-email-peter.ujfalusi@ti.com>
 <6ee9d67a-e907-715a-f3f5-d90a470314c3@ti.com>
 <20160504172634.GS5995@atomide.com>
Message-ID: <572A38FD.9050801@ti.com>

On 05/04/2016 12:26 PM, Tony Lindgren wrote:
> Hi,
> 
> Adding Nishanth to Cc.
> 
> * Peter Ujfalusi <peter.ujfalusi at ti.com> [160429 05:15]:
>> ldo7_reg, obviously ;)
>>
>>> 	status = "okay";
>>> 	regulator-min-microvolt = <1800000>;
>>> 	regulator-max-microvolt = <1800000>;
>>> };
> 
> It really seems to be ldo7, otherwise there's no HDMI output. I don't
> have the schematics either.
> 
> But it seems we have at least two other regressions in Linux next that
> prevent me from testing this properly:
> 
> 1. On igepv5, I get this for the MMC regulator
> 
> ldo9: bypassed regulator has no supply!
> ldo9: failed to get the current voltage(-517)
> palmas-pmic 48070000.i2c:palmas at 48:palmas_pmic: failed to register 48070000.i2c:palmar
> 
> I'm pretty sure it really is using the ldo9 for MMC just like
> omap5-uevm.. Nishanth suggested it may use something else, but
> why would it as ldo9 has a nice voltage range?
> 
> 2. On both omap5-uevm and igepv5, NFSroot hangs
> 
> It seems that NFSroot boots to the point where PM runtime now
> just shuts down some regulator affecting the USB connected
> smsc Ethernet adapter?
> 
> Regards,

This one is interesting..
BayLibre uEVM:
https://storage.kernelci.org/next/next-20160504/arm-omap2plus_defconfig/lab-baylibre-seattle/boot-omap5-uevm_rootfs:mmc.txt

My uEVM:
https://github.com/nmenon/kernel-test-logs/blob/next-20160504/omap2plus_defconfig/omap5-evm.txt

Mine boots, but BayLibre one does not. So, that got me started
thinking it was bootloader... but then I realize it could be SDCard
since they are dual voltage. U-boot starting v2013.07-rc1 included
code that would set to bypass or program voltage for LDO9 based on
card voltage needed. It is possible (since my card seems to need 3.0v,
not 3.3v), that bypass to VCC_3v3_SDIO was never needed - but the
cards that Baylibre board could probably be setup in bypass.

I will send in a patch assuming (without access to igev5 schematics -
based on how it seems to be booting), that sdio path.


-- 
Regards,
Nishanth Menon


From maxime.ripard at free-electrons.com  Wed May  4 11:01:43 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 4 May 2016 20:01:43 +0200
Subject: [PATCH v4 00/11] drm: Add Allwinner A10 display engine support
In-Reply-To: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <20160504180143.GA17159@lukather>

On Mon, Apr 25, 2016 at 03:22:41PM +0200, Maxime Ripard wrote:
> Hi everyone,
> 
> The Allwinner SoCs (except for the very latest ones) all share the
> same set of controllers, loosely coupled together to form the display
> pipeline.
> 
> Depending on the SoC, the number of instances of the controller will
> change (2 instances of each in the A10, only one in the A13, for
> example), and the output availables will change too (HDMI, composite,
> VGA on the A20, none of them on the A13).
> 
> On most featured SoCs, it looks like that:
> 
> +--------------------------------------------+
> |                    RAM                     |
> +--------------------------------------------+
>       |            |      |            |
>       v            |      |            v
> +----------------+ |      | +----------------+
> |    Frontend    | |      | |    Frontend    |
> +----------------+ |      | +----------------+
>         |          |      |         |
>         v          |      |         v
> +----------------+ |      | +----------------+
> |    Backend     |<+      +>|    Backend     |
> +----------------+          +----------------+
>         |                           |
>         v                           v
> +----------------+          +----------------+---> LVDS
> |      TCON      |          |      TCON      |---> RGB
> +----------------+          +----------------+
>       |       +---+       +---+          |
>       |           |       |              |
>       v           v       v              v
> +------------+  +------------+  +------------+---> VGA
> | TV Encoder |  |    HDMI    |  | TV Encoder |---> Composite
> +------------+  +------------+  +------------+
> 
> The current code only assumes that there is a single instance of all
> the controllers. It also supports only the RGB and Composite
> interfaces.
> 
> Let me know what you think,
> Maxime
> 
> Changes from v3:
>   - Fixed a circular dependency issue found when building as a module
>   - Changed a bit the mode_valid checks
>   - Fixed an issue with the timings generated by the display engine
> 
>   - Changed the DT bindings according to Rob feedback (removed the
>     allwinner,panel property, documented the endpoints indices, always
>     use the frontend as the pipeline entrypoint)
> 
>   - Changed the display clocks according to Stephen comments (marked
>     structures as const, changed a variable name)
> 
> Changes from v2:
>   - Rebased on top of next-20160318
> 
>   - Dropped the generic clock regmap conversion and implemented a
>     custom clock for our pixel clock, backed by a regmap
>   - Added the reset bits for the tcon channel 0 and display clocks
>   - Used the new generic gates compatible for the DRAM gates
>   - Few clock fixes (missing iounmap, return error checks, etc)
>   - Found out that the TCON channel 1 clock was not operating properly
>     because of some weird rounding down and up between the various
>     generic clocks involved. Rewrote it using custom operations
> 
>   - Removed some TODO that were still there
>   - Converted our panel DT description to the OF graph instead of a
>     custom property
>   - Tested the driver on a setup where U-Boot was not initialising the
>     display, or initialising it on a different output, and fixed a
>     number of associated bugs (mostly related to missing
>     initialisation bits, missing reset handles, and so on)
>   - Fixed the layer code that was assuming that the X and Y
>     coordinates were in pixels, leading to a miscalculation of the
>     buffer address when those coordinates where set.
>   - Added the missing EXPORT_SYMBOL calls
> 
>   - Fixed our VBLANK interrupt code that was completely broken (and
>     not usable, which is why it was unnoticed)
> 
> Changes from v1:
>   - Rebased on top of 4.4
> 
>   - Merged the clock drivers for the display and TCON channel 0 clocks
>   - Replaced the container_of calls in the display reset clocks to an
>     inline function
>   - Checked the return code of of_clk_parent_fill in the clocks
>     drivers
>   - Checked the return code of of_clk_add_provider in the tcon-ch1 and
>     PLL3 clocks
>   - Added missing clocks headers
>   - Created a composite clock unregister function
> 
>   - Moved the binding documentation to
>     Documentation/devicetree/bindings/display
>   - Added the clocks binding documentation
>   - Added the Olimex vendor to the list of DT vendors
>   - Moved to the OF graph representation and the component framework
> 
>   - Moved the reset cells count check into the reset framework to
>     avoid duplicating the code in every xlate implementation.
>   - Made the reset_ops const
> 
>   - Reworked the DRM cmdline mode parsing code to allow named mode
>   - Fixed the TV mode lookup when the mode name is not present (for
>     example because it was given by the userspace)
> 
>   - Made the driver outputs optional (to avoid crashing when a board
>     doesn't have either a panel or a composite output enabled)
>   - Added multiple plane support with transparency
>   - Moved the backend registers writes commit in the CRTC atomic_flush
>     callback
>   - Removed the load / unload functions
>   - Removed the enabled booleans in my private structure and removed
>     the implicit call to disable_unused_functions in the DRM core to
>     push it in the drivers.
>   - Fixed a few bitmasks on some bitfields definition
>   - Fixed the RGB connector mode validation that was not testing the
>     right values				  

Applied the DT patches.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/797aca40/attachment.sig>

From davem at davemloft.net  Wed May  4 11:02:37 2016
From: davem at davemloft.net (David Miller)
Date: Wed, 04 May 2016 14:02:37 -0400 (EDT)
Subject: [PATCH] drivers: net: xgene: Fix error handling
In-Reply-To: <1462284307-15401-1-git-send-email-mbrugger@suse.com>
References: <1462284307-15401-1-git-send-email-mbrugger@suse.com>
Message-ID: <20160504.140237.1301311847350900607.davem@davemloft.net>

From: Matthias Brugger <mbrugger at suse.com>
Date: Tue,  3 May 2016 16:05:07 +0200

> When probe bails out with an error, we try to unregister the
> netdev before we have even registered it. Fix the goto statements
> for that.
> 
> Signed-off-by: Matthias Brugger <mbrugger at suse.com>

Applied.


From martinayotte at gmail.com  Wed May  4 11:15:55 2016
From: martinayotte at gmail.com (martinayotte at gmail.com)
Date: Wed, 4 May 2016 11:15:55 -0700 (PDT)
Subject: [PATCH v2 1/1] add missing UARTs pins and I2C entriesfor
 AllWinner H3 DTSI
In-Reply-To: <20160502064645.GK17159@lukather>
References: <CAKQ8BtjPhfJC+njOUvo-4ZQ+Oj==LqQEhJ1LQROjY85hswE9Mg@mail.gmail.com>
 <20160502064645.GK17159@lukather>
Message-ID: <c17544c6-2b49-44cc-b2f9-537d94f276ef@googlegroups.com>

Bonjour Maxime,

On Monday, May 2, 2016 at 2:46:57 AM UTC-4, Maxime Ripard wrote:
> Hi,
> 
> On Tue, Apr 19, 2016 at 03:50:39PM -0400, Martin Ayotte wrote:
> > Hi everyone,
> > 
> > This patch is submit to provide endusers access to additional UARTs on
> > AllWinner H3 SoC along with I2C ports.
> 
> Unfortunately, your patch cannot be applied in its current form, both
> because of process and technical reasons:
> 
>   * Every commits should have a commit title and log. While you do
>     have a title, you used the log to store your cover letter. This is
>     an issue, because that will be kept in the git history, which is
>     obviously something we don't want.
>     If you want to make a cover letter, you can either send it as a
>     separate mail, or after the "---" below that will be ignored when
>     applying the mails.
>     On the other hand, the commit log should be used to say why ?our
>     doing this patch and why it was needed.
> 
>   * You do not have a Signed-off-by tag in your commit log. This and
>     the point above is documented in Documentation/SubmittingPatches,
>     please make sure to read that first.
> 
>   * Your mailer completely corrupted the patch when you sent it,
>     replacing all tabs by spaces, and wrapping the longer lines. That
>     means that the patch cannot be applied anymore. Please fix your
>     mailer, or use one that just works, like git send-email.
> 
>   * Finally, like Chen-Yu already told you, you're doing several
>     different things here in a single patch, while you should have
>     done separate patches. From what I can see, you're adding pinctrl
>     groups for the uart and i2c pins, and adding the i2c controller
>     nodes. That should have been ideally 3 patches: 1 for the uart
>     pinctrl groups, 1 for the i2c pinctrl groups, 1 for the i2c
>     controller nodes. We also don't take pinctrl groups that are not
>     enabled on any boards to keep the DT size as small as possible.
> 
> Thanks,
> Maxime
> 
> -- 
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com

Thanks for your help and make me understanding more the process.

I've now prepared a new v3 for that, and just send it.
Strangely, it seems that the 3 patches been sent separately. 
I will try to figure out what happened.

Regards,
Martin.


From broonie at kernel.org  Wed May  4 11:25:55 2016
From: broonie at kernel.org (Mark Brown)
Date: Wed, 4 May 2016 19:25:55 +0100
Subject: [RFT PATCH 1/3] usb: misc: usb3503: Fix HUB mode after
 bootloader initialization
In-Reply-To: <5729E4B5.2090702@samsung.com>
References: <1461927591-7864-1-git-send-email-k.kozlowski@samsung.com>
 <1461927591-7864-2-git-send-email-k.kozlowski@samsung.com>
 <20160429113059.GX3217@sirena.org.uk>
 <57234BA2.6020304@samsung.com>
 <20160429164448.GY3217@sirena.org.uk> <57272298.50701@samsung.com>
 <20160502105501.GE6292@sirena.org.uk>
 <20160503180022.GA3008@rob-hp-laptop>
 <5729E4B5.2090702@samsung.com>
Message-ID: <20160504182555.GE6292@sirena.org.uk>

On Wed, May 04, 2016 at 02:01:57PM +0200, Krzysztof Kozlowski wrote:

> This looks like pwrseq for MMC devices so the idea is to:
> 1. Move drivers/mmc/core/pwrseq* to separate directory
> (drivers/power/pwrseq ?)
> 2. Add support for pwrseq to USB core,
> 3. Add new pwrseq driver (or extend existing one): toggling the regulator.
> 4. Add pwrseq phandle to the DT node of USB hub (to the binding
> mentioned by Rob?).

> Does it look sensible?

It certainly seems like a similar problem space, USB seems very much
like MMC in both the spec and the way it tends to get used.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/c430248f/attachment.sig>

From maxime.ripard at free-electrons.com  Wed May  4 11:32:06 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 4 May 2016 20:32:06 +0200
Subject: [PATCH 1/2] ARM: sun4i: dt: Add pll3 and pll7 clocks
In-Reply-To: <1462295659-6945-2-git-send-email-plaes@plaes.org>
References: <1462295659-6945-1-git-send-email-plaes@plaes.org>
 <1462295659-6945-2-git-send-email-plaes@plaes.org>
Message-ID: <20160504183206.GC17159@lukather>

Hi,

On Tue, May 03, 2016 at 08:14:18PM +0300, Priit Laes wrote:
> Enable pll3 and pll7 clocks that are needed to drive display clocks.
> 
> Signed-off-by: Priit Laes <plaes at plaes.org>
> ---
>  arch/arm/boot/dts/sun4i-a10.dtsi | 44 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 44 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
> index 268a150..c893744 100644
> --- a/arch/arm/boot/dts/sun4i-a10.dtsi
> +++ b/arch/arm/boot/dts/sun4i-a10.dtsi
> @@ -184,6 +184,15 @@
>  			clock-output-names = "osc24M";
>  		};
>  
> +		osc3M: osc3M_clk {
> +			compatible = "fixed-factor-clock";
> +			#clock-cells = <0>;
> +			clock-div = <8>;
> +			clock-mult = <1>;
> +			clocks = <&osc24M>;
> +			clock-output-names = "osc3M";
> +		};
> +
>  		osc32k: clk at 0 {
>  			#clock-cells = <0>;
>  			compatible = "fixed-clock";
> @@ -208,6 +217,24 @@
>  					     "pll2-4x", "pll2-8x";
>  		};
>  
> +		pll3: clk at 01c20010 {
> +			#clock-cells = <0>;
> +			compatible = "allwinner,sun4i-a10-pll3-clk";
> +			reg = <0x01c20010 0x4>;
> +			clocks = <&osc3M>;
> +			clock-output-names = "pll3";
> +		};
> +
> +		pll3x2: pll3x2_clk {
> +			compatible = "fixed-factor-clock";
> +			#clock-cells = <0>;
> +			clock-div = <1>;
> +			clock-mult = <2>;
> +			clocks = <&pll3>;
> +			clock-output-names = "pll3-x2";

We usually call them -2x

> +		};
> +
> +

One newline too many.

Fixed it and applied the patch.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/7f876d71/attachment-0001.sig>

From maxime.ripard at free-electrons.com  Wed May  4 11:32:55 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 4 May 2016 20:32:55 +0200
Subject: [PATCH 2/2] ARM: sun7i: dt: Add pll3 and pll7 clocks
In-Reply-To: <1462295659-6945-3-git-send-email-plaes@plaes.org>
References: <1462295659-6945-1-git-send-email-plaes@plaes.org>
 <1462295659-6945-3-git-send-email-plaes@plaes.org>
Message-ID: <20160504183255.GD17159@lukather>

Hi,

On Tue, May 03, 2016 at 08:14:19PM +0300, Priit Laes wrote:
> Enable pll3 and pll7 clocks that are needed by display clocks.

Missing signed-off-by

> ---
>  arch/arm/boot/dts/sun7i-a20.dtsi | 41 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
> index bf5d056..2688512 100644
> --- a/arch/arm/boot/dts/sun7i-a20.dtsi
> +++ b/arch/arm/boot/dts/sun7i-a20.dtsi
> @@ -187,6 +187,15 @@
>  			clock-output-names = "osc24M";
>  		};
>  
> +		osc3M: osc3M_clk {
> +			#clock-cells = <0>;
> +			compatible = "fixed-factor-clock";
> +			clock-div = <8>;
> +			clock-mult = <1>;
> +			clocks = <&osc24M>;
> +			clock-output-names = "osc3M";
> +		};
> +
>  		osc32k: clk at 0 {
>  			#clock-cells = <0>;
>  			compatible = "fixed-clock";
> @@ -211,6 +220,22 @@
>  					     "pll2-4x", "pll2-8x";
>  		};
>  
> +		pll3: clk at 01c20010 {
> +			#clock-cells = <0>;
> +			compatible = "allwinner,sun4i-a10-pll3-clk";
> +			reg = <0x01c20010 0x4>;
> +			clock = <&osc3M>;
> +			clock-output-names = "pll3";
> +};

The indentation is off.

> +
> +		pll3x2: pll3x2_clk {
> +			#clock-cells = <0>;
> +			compatible = "fixed-factor-clock";
> +			clock-div = <1>;
> +			clock-mult = <2>;
> +			clock-output-names = "pll3-2x";
> +		};
> +
>  		pll4: clk at 01c20018 {
>  			#clock-cells = <0>;
>  			compatible = "allwinner,sun7i-a20-pll4-clk";
> @@ -236,6 +261,22 @@
>  					     "pll6_div_4";
>  		};
>  
> +		pll7: clk at 01c20030 {
> +			#clock-cells = <0>;
> +			compatible = "allwinner,sun4i-a10-pll3-clk";
> +			reg = <0x01c20030 0x4>;
> +			clock = <&osc3M>;
> +			clock-output-names = "pll7";
> +};

Ditto.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/0ee7c91f/attachment.sig>

From maxime.ripard at free-electrons.com  Wed May  4 11:33:47 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 4 May 2016 20:33:47 +0200
Subject: [PATCH] drm/sun4i: add COMMON_CLK dependency
In-Reply-To: <1462186805-2211918-1-git-send-email-arnd@arndb.de>
References: <1462186805-2211918-1-git-send-email-arnd@arndb.de>
Message-ID: <20160504183347.GE17159@lukather>

Hi,

On Mon, May 02, 2016 at 12:59:48PM +0200, Arnd Bergmann wrote:
> The sun4i drm driver uses the clk-provider interfaces, which are not available
> when CONFIG_COMMON_CLK is disabled:
> 
> drivers/gpu/drm/sun4i/sun4i_dotclock.c:19:16: error: field 'hw' has incomplete type
>   struct clk_hw hw;
> In file included from ../include/asm-generic/bug.h:13:0,
>                  from ../arch/arm/include/asm/bug.h:59,
>                  from ../include/linux/bug.h:4,
>                  from ../include/linux/io.h:23,
>                  from ../include/linux/clk-provider.h:14,
>                  from ../drivers/gpu/drm/sun4i/sun4i_dotclock.c:13:
> drivers/gpu/drm/sun4i/sun4i_dotclock.c: In function 'hw_to_dclk':
> include/linux/kernel.h:831:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
> ...
> 
> This adds a Kconfig dependency to prevent the driver from being enabled
> in this case.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")

Applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/4e0a095f/attachment.sig>

From maxime.ripard at free-electrons.com  Wed May  4 11:34:17 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 4 May 2016 20:34:17 +0200
Subject: [PATCH] drm: sun4i: print DMA address correctly
In-Reply-To: <1462289020-774976-1-git-send-email-arnd@arndb.de>
References: <1462289020-774976-1-git-send-email-arnd@arndb.de>
Message-ID: <20160504183417.GF17159@lukather>

On Tue, May 03, 2016 at 05:23:28PM +0200, Arnd Bergmann wrote:
> The newly added sun4i drm driver prints a dma address using the %x
> format string, which cannot work when dma_addr_t is 64 bit,
> and gcc warns about this configuration:
> 
> drm/sun4i/sun4i_backend.c: In function 'sun4i_backend_update_layer_buffer':
> drm/sun4i/sun4i_backend.c:193:84: error: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'dma_addr_t {aka long long unsigned int}' [-Werror=format=]
>   DRM_DEBUG_DRIVER("Using GEM @ 0x%x\n", gem->paddr);
> drm/sun4i/sun4i_backend.c:201:84: error: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'dma_addr_t {aka long long unsigned int}' [-Werror=format=]
>   DRM_DEBUG_DRIVER("Setting buffer address to 0x%x\n", paddr);
> 
> This changes the code to use the explicit %pad format string, which
> always prints the right length.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>

Applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/459377c2/attachment.sig>

From maxime.ripard at free-electrons.com  Wed May  4 11:35:50 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 4 May 2016 20:35:50 +0200
Subject: [PATCHv3] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <1462367853-29912-1-git-send-email-oliver@schinagl.nl>
References: <1462367853-29912-1-git-send-email-oliver@schinagl.nl>
Message-ID: <20160504183550.GG17159@lukather>

On Wed, May 04, 2016 at 03:17:33PM +0200, Olliver Schinagl wrote:
> There are 3 kinds of OLinuXino Lime2 boards.
> One without any on board storage, one with NAND storage and one with
> eMMC storage. This patch adds the eMMC variant of boards.
> 
> eMMC storage is different from a regular SD card in that it is soldered
> on the board and cannot be changed. Additionally, it shares pins with
> the NAND module and with the second SPI port.
> 
> Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>

As a general comment, having a log of the changes helps a lot,
especially when you roll new versions quiclky.

> ---
>  .../boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts    | 81 ++++++++++++++++++++++
>  1 file changed, 81 insertions(+)
>  create mode 100644 arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
> 
> diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
> new file mode 100644
> index 0000000..9680fcb
> --- /dev/null
> +++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
> @@ -0,0 +1,81 @@
> + /*
> + * Copyright 2015 - Ultimaker B.V.
> + * Author Olliver Schinagl <oliver at schinagl.nl>
> + *
> + * 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.
> + */
> +
> +#include "sun7i-a20-olinuxino-lime2.dts"
> +
> +/ {
> +	model = "Olimex A20-OLinuXino-LIME2-eMMC";

You should have a compatible here too.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160504/d5f52f03/attachment.sig>

From yang.shi at linaro.org  Wed May  4 11:14:27 2016
From: yang.shi at linaro.org (Yang Shi)
Date: Wed,  4 May 2016 11:14:27 -0700
Subject: [PATCH] arm64: mm: remove unnecessary EXPORT_SYMBOL_GPL
Message-ID: <1462385667-21022-1-git-send-email-yang.shi@linaro.org>

arch_pick_mmap_layout is only called by fs/exec.c which is always built into
kernel, it looks the EXPORT_SYMBOL_GPL is pointless and no architectures export
it other than ARM64.

Signed-off-by: Yang Shi <yang.shi at linaro.org>
---
 arch/arm64/mm/mmap.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
index 232f787..01c1717 100644
--- a/arch/arm64/mm/mmap.c
+++ b/arch/arm64/mm/mmap.c
@@ -95,8 +95,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
 	}
 }
-EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
-
 
 /*
  * You really shouldn't be using read() or write() on /dev/mem.  This might go
-- 
2.0.2



From f.fainelli at gmail.com  Wed May  4 11:53:50 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Wed, 4 May 2016 11:53:50 -0700
Subject: [PATCH] ARM: BCM5301X: Add DT for Luxul XAP-1510
In-Reply-To: <1462296501-5209-1-git-send-email-dhaab@luxul.com>
References: <1462296501-5209-1-git-send-email-dhaab@luxul.com>
Message-ID: <572A453E.6010000@gmail.com>

On 03/05/16 10:28, Dan Haab wrote:
> Luxul XAP-1510 is an AP device based on BCM4708 SoC. It uses flash
> memory connected to the SPI controller.

Looks fine, except one nit:

> diff --git a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
> new file mode 100644
> index 0000000..f4460b5
> --- /dev/null
> +++ b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
> @@ -0,0 +1,67 @@
> +/*
> + * Broadcom BCM470X / BCM5301X ARM platform code.
> + * DTS for Luxul XAP-1510
> + *
> + * Copyright 2015 Luxul Inc.
> + *
> + * Licensed under the GNU/GPL. See COPYING for details.

The ARM SoC maintainer have been asking to utilize a license which is
also BSD compatible, so something along the lines of this one:

arch/arm/boot/dts/bcm911360k.dts

Do you mind respining the patch to include that kind of license header?
Thanks!
-- 
Florian


From nm at ti.com  Wed May  4 12:20:18 2016
From: nm at ti.com (Nishanth Menon)
Date: Wed, 4 May 2016 14:20:18 -0500
Subject: [PATCH] ARM: dts: omap5-board-common: Describe the voltage supply
 mapping accurately
Message-ID: <1462389618-28860-1-git-send-email-nm@ti.com>

OMAP5uEVM[1] based platforms share a similar voltage rail map. This
should be properly described in device tree, without this regulator core
will be unable to determine the source voltage of LDOs such as LDO9 and
SMPS10 which could be configured for bypass depending on the voltage
requested of them. This results in conditions such as

[    4.207853] ldo9: bypassed regulator has no supply!
[    4.212982] ldo9: failed to get the current voltage(-517)
[    4.218662] palmas-pmic 48070000.i2c:palmas at 48:palmas_pmic: failed to register 48070000.i2c:palmas at 48:palmas_pmic regulator

NOTE: I do not have access to omap5-igep0050 schematics, but based on
test behavior for LDO9 by Tony, I am assuming to be the same map as
OMAP5uEVM.

Reference schematics document: 750-2628-103-SCH
rev D (Access to schematics requires NDA as per
https://e2e.ti.com/support/omap/f/885/t/282560)

[1] https://svtronics.com/5432

Reported-by: Tony Lindgren <tony at atomide.com>
Signed-off-by: Nishanth Menon <nm at ti.com>
---

Based on next-20160504

This should fix regression reported for mmcsd such as that seen in:
https://storage.kernelci.org/next/next-20160504/arm-omap2plus_defconfig/lab-baylibre-seattle/boot-omap5-uevm_rootfs:mmc.txt

http://pastebin.ubuntu.com/16223856/
NFS data transfer test however failed on linux-next
next-20160504 - this could be a second order issue to be identified.

 arch/arm/boot/dts/omap5-board-common.dtsi | 42 +++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi
index dc759a3028b7..56eb4f1a6bf0 100644
--- a/arch/arm/boot/dts/omap5-board-common.dtsi
+++ b/arch/arm/boot/dts/omap5-board-common.dtsi
@@ -14,6 +14,29 @@
 		display0 = &hdmi0;
 	};
 
+	vmain: fixedregulator-vmain {
+		compatible = "regulator-fixed";
+		regulator-name = "vmain";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	vsys_cobra: fixedregulator-vsys_cobra {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_cobra";
+		vin-supply = <&vmain>;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	vdds_1v8_main: fixedregulator-vdds_1v8_main {
+		compatible = "regulator-fixed";
+		regulator-name = "vdds_1v8_main";
+		vin-supply = <&smps7_reg>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
 	vmmcsd_fixed: fixedregulator-mmcsd {
 		compatible = "regulator-fixed";
 		regulator-name = "vmmcsd_fixed";
@@ -413,6 +436,7 @@
 				smps123_reg: smps123 {
 					/* VDD_OPP_MPU */
 					regulator-name = "smps123";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = < 600000>;
 					regulator-max-microvolt = <1500000>;
 					regulator-always-on;
@@ -422,6 +446,7 @@
 				smps45_reg: smps45 {
 					/* VDD_OPP_MM */
 					regulator-name = "smps45";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = < 600000>;
 					regulator-max-microvolt = <1310000>;
 					regulator-always-on;
@@ -431,6 +456,7 @@
 				smps6_reg: smps6 {
 					/* VDD_DDR3 - over VDD_SMPS6 */
 					regulator-name = "smps6";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-always-on;
@@ -440,6 +466,7 @@
 				smps7_reg: smps7 {
 					/* VDDS_1v8_OMAP over VDDS_1v8_MAIN */
 					regulator-name = "smps7";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 					regulator-always-on;
@@ -449,6 +476,7 @@
 				smps8_reg: smps8 {
 					/* VDD_OPP_CORE */
 					regulator-name = "smps8";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = < 600000>;
 					regulator-max-microvolt = <1310000>;
 					regulator-always-on;
@@ -458,6 +486,7 @@
 				smps9_reg: smps9 {
 					/* VDDA_2v1_AUD over VDD_2v1 */
 					regulator-name = "smps9";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = <2100000>;
 					regulator-max-microvolt = <2100000>;
 					ti,smps-range = <0x80>;
@@ -466,6 +495,7 @@
 				smps10_out2_reg: smps10_out2 {
 					/* VBUS_5V_OTG */
 					regulator-name = "smps10_out2";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = <5000000>;
 					regulator-max-microvolt = <5000000>;
 					regulator-always-on;
@@ -475,6 +505,7 @@
 				smps10_out1_reg: smps10_out1 {
 					/* VBUS_5V_OTG */
 					regulator-name = "smps10_out1";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = <5000000>;
 					regulator-max-microvolt = <5000000>;
 				};
@@ -482,6 +513,7 @@
 				ldo1_reg: ldo1 {
 					/* VDDAPHY_CAM: vdda_csiport */
 					regulator-name = "ldo1";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
@@ -489,6 +521,7 @@
 				ldo2_reg: ldo2 {
 					/* VCC_2V8_DISP: Does not go anywhere */
 					regulator-name = "ldo2";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = <2800000>;
 					regulator-max-microvolt = <2800000>;
 					/* Unused */
@@ -498,6 +531,7 @@
 				ldo3_reg: ldo3 {
 					/* VDDAPHY_MDM: vdda_lli */
 					regulator-name = "ldo3";
+					vin-supply = <&vdds_1v8_main>;
 					regulator-min-microvolt = <1500000>;
 					regulator-max-microvolt = <1500000>;
 					regulator-boot-on;
@@ -508,6 +542,7 @@
 				ldo4_reg: ldo4 {
 					/* VDDAPHY_DISP: vdda_dsiport/hdmi */
 					regulator-name = "ldo4";
+					vin-supply = <&vdds_1v8_main>;
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 				};
@@ -515,6 +550,7 @@
 				ldo5_reg: ldo5 {
 					/* VDDA_1V8_PHY: usb/sata/hdmi.. */
 					regulator-name = "ldo5";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 					regulator-always-on;
@@ -524,6 +560,7 @@
 				ldo6_reg: ldo6 {
 					/* VDDS_1V2_WKUP: hsic/ldo_emu_wkup */
 					regulator-name = "ldo6";
+					vin-supply = <&vdds_1v8_main>;
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
 					regulator-always-on;
@@ -533,6 +570,7 @@
 				ldo7_reg: ldo7 {
 					/* VDD_VPP: vpp1 */
 					regulator-name = "ldo7";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = <2000000>;
 					regulator-max-microvolt = <2000000>;
 					/* Only for efuse reprograming! */
@@ -542,6 +580,7 @@
 				ldo8_reg: ldo8 {
 					/* VDD_3v0: Does not go anywhere */
 					regulator-name = "ldo8";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = <3000000>;
 					regulator-max-microvolt = <3000000>;
 					regulator-boot-on;
@@ -551,6 +590,8 @@
 
 				ldo9_reg: ldo9 {
 					/* VCC_DV_SDIO: vdds_sdcard */
+					vin-supply = <&vmmcsdio_fixed>;
+
 					regulator-name = "ldo9";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <3000000>;
@@ -569,6 +610,7 @@
 				ldousb_reg: ldousb {
 					/* VDDA_3V_USB: VDDA_USBHS33 */
 					regulator-name = "ldousb";
+					vin-supply = <&vsys_cobra>;
 					regulator-min-microvolt = <3250000>;
 					regulator-max-microvolt = <3250000>;
 					regulator-always-on;
-- 
2.8.0



From f.fainelli at gmail.com  Wed May  4 12:36:17 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Wed, 4 May 2016 12:36:17 -0700
Subject: [PATCH 2/2] pci: host: Add Broadcom STB PCIE RC controller
In-Reply-To: <2339405.90vXV1p6zU@wuerfel>
References: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>
 <1462238749-19715-3-git-send-email-f.fainelli@gmail.com>
 <2339405.90vXV1p6zU@wuerfel>
Message-ID: <572A4F31.8010802@gmail.com>

On 03/05/16 02:57, Arnd Bergmann wrote:
>> +static const struct pcie_cfg_data generic_cfg = {
>> +	.offsets	= pcie_offsets,
>> +	.type		= GENERIC,
>> +};
> 
> The way you access the config space here seems very indirect. I'd
> suggest instead writing two sets of pci_ops, with hardcoded registers
> offsets in them, and a function pointer to access the RGR1_SW_INIT_1
> register.

How about introducing helper functions but keeping the same set of
read/write pci_ops instead, would that seem more acceptable? I agree
that the macros are not the friendliest thing.

> 
>> +struct brcm_msi {
>> +	struct irq_domain *domain;
>> +	struct irq_chip irq_chip;
>> +	struct msi_controller chip;
>> +	struct mutex lock;
>> +	int irq;
>> +	/* intr_base is the base pointer for interrupt status/set/clr regs */
>> +	void __iomem *intr_base;
>> +	/* intr_legacy_mask indicates how many bits are MSI interrupts */
>> +	u32 intr_legacy_mask;
>> +	/* intr_legacy_offset indicates bit position of MSI_01 */
>> +	u32 intr_legacy_offset;
>> +	/* used indicates which MSI interrupts have been alloc'd */
>> +	unsigned long used;
>> +	/* working indicates that on boot we have brought up MSI */
>> +	bool working;
>> +};
> 
> I'd move the MSI controller stuff into a separate file, and add a way to
> override it. It's likely that at some point the same PCIe implementation
> will be used with a modern GICv3 or GICv2m, so you should be able to
> look up the msi controller from a property.

Good point, let's do that, though all controllers actually do support
MSI, so I wonder.

> 
>> +struct brcm_window {
>> +	u64 size;
>> +	u64 cpu_addr;
>> +	struct resource pcie_iomem_res;
>> +};
> 
> This appears to duplicate things we already have. Try to get rid of
> the structure and use what is already there.

OK, the resource is probably good enough here.

> 
>> +struct brcm_dev_pwr_supply {
>> +	struct list_head node;
>> +	char name[32];
>> +	struct regulator *regulator;
>> +};
> 
> Same here: Just get all the regulators you know about by name
> and put them into the main structure.

OK, I will drop the regulator support for now, see below for a more
elaborate answer.

> 
>> +/* Internal Bus Controller Information.*/
>> +struct brcm_pcie {
>> +	struct list_head	list;
>> +	void __iomem		*base;
>> +	char			name[8];
>> +	bool			suspended;
>> +	struct clk		*clk;
>> +	struct device_node	*dn;
>> +	int			pcie_irq[4];
>> +	int			irq;
>> +	int			num_out_wins;
>> +	bool			ssc;
>> +	int			gen;
>> +	int			scb_size_vals[BRCM_MAX_SCB];
>> +	struct brcm_window	out_wins[BRCM_NUM_PCI_OUT_WINS];
>> +	struct pci_bus		*bus;
>> +	struct device		*dev;
>> +	struct list_head	resource;
>> +	struct list_head	pwr_supplies;
>> +	struct brcm_msi		msi;
>> +	unsigned int		rev;
>> +	unsigned int		num;
>> +	bool			bridge_setup_done;
>> +	const int		*reg_offsets;
>> +	enum pcie_type		type;
>> +};
>> +
>> +static int brcm_num_pci_controllers;
>> +static int num_memc;
> 
> Remove the globals.

OK.

> 
>> +
>> +/*
>> + * MIPS endianness is configured by boot strap, which also reverses all
>> + * bus endianness (i.e., big-endian CPU + big endian bus ==> native
>> + * endian I/O).
>> + *
>> + * Other architectures (e.g., ARM) either do not support big endian, or
>> + * else leave I/O in little endian mode.
>> + */
>> +static inline u32 bpcie_readl(void __iomem *base)
>> +{
>> +	if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
>> +		return __raw_readl(base);
>> +	else
>> +		return readl_relaxed(base);
>> +}
> 
> I think it would make more sense to only make this depend on the
> architecture, not on endianess: If the __raw_ version works on MIPS
> in big-endian mode, you should be able to also use it in little-endian
> mode.
> 
> For the default (ARM) version, please use the non-relaxed accessor
> by default, unless you can show a difference in performance and prove
> that you don't need the implied barriers.

Our busing makes it so that the __raw_readl() (or _relaxed) I/O access
is going to have the same guarantees as if we were adding a barrier,
that is, writes are not going to be re-ordered with each other by the
bus, nor the CPU (since it maps the space as device memory), and on
MIPS, well, it's all through unmapped, uncached space, but I can
definitively switch that for readl(), should not make a huge performance
difference, if noticeable.

> 
>> +/* negative return value indicates error */
>> +static int mdio_read(void __iomem *base, u8 phyad, u8 regad)
>> +{
>> +	u32 data = ((phyad & 0xf) << 16)
>> +		| (regad & 0x1f)
>> +		| 0x100000;
>> +
>> +	bpcie_writel(data, base + PCIE_RC_DL_MDIO_ADDR);
>> +	bpcie_readl(base + PCIE_RC_DL_MDIO_ADDR);
>> +
>> +	data = bpcie_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
>> +	if (!(data & 0x80000000)) {
>> +		mdelay(1);
> 
> Try to restructure the code so this is never called with spinlocks
> held and then replace the mdelay() with an msleep().

I cannot really think of a reason why we did not use msleep() all along,
so thanks for spotting that.

>> +
>> +	/* set up 4GB PCIE->SCB memory window on BAR2 */
>> +	bpcie_writel(0x00000011, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
>> +	bpcie_writel(0x00000000, base + PCIE_MISC_RC_BAR2_CONFIG_HI);
> 
> Where does this window come from? It's not in the DT as far as I can see.

This is an architectural maximum value which is baked into the PCIE Root
Complex hardware, on all generations that this driver supports. We
configure the largest address match rang size here, just to be safe,
AFAICT there is no point in looking at the inbound or outbound window
sizes to re-program that differently.


>> +	INIT_LIST_HEAD(&pcie->pwr_supplies);
>> +	INIT_LIST_HEAD(&pcie->resource);
>> +
>> +	supplies = of_property_count_strings(dn, "supply-names");
>> +	if (supplies <= 0)
>> +		supplies = 0;
>> +
>> +	for (i = 0; i < supplies; i++) {
>> +		if (of_property_read_string_index(dn, "supply-names", i,
>> +						  &name))
>> +			continue;
>> +		supply = devm_kzalloc(&pdev->dev, sizeof(*supply), GFP_KERNEL);
>> +		if (!supply)
>> +			return -ENOMEM;
>> +
>> +		strncpy(supply->name, name, sizeof(supply->name));
>> +		supply->name[sizeof(supply->name) - 1] = '\0';
>> +		supply->regulator = devm_regulator_get(&pdev->dev, name);
>> +		if (IS_ERR(supply->regulator)) {
>> +			dev_err(&pdev->dev, "Unable to get %s supply, err=%d\n",
>> +				name, (int)PTR_ERR(supply->regulator));
>> +			continue;
>> +		}
>> +
>> +		if (regulator_enable(supply->regulator))
>> +			dev_err(&pdev->dev, "Unable to enable %s supply.\n",
>> +				name);
>> +		list_add_tail(&supply->node, &pcie->pwr_supplies);
>> +	}
> 
> Don't parse the regulator properties yourself here, use the proper APIs.

I will probably drop this for now, and  add it later, there are only a
handful of boards which requires this, and ultimately, I think we should
be seaking for a more generic solutions, we can't be the only ones doing
that.

> 
>> +	/* 'num_memc' will be set only by the first controller, and all
>> +	 * other controllers will use the value set by the first.
>> +	 */
>> +	if (num_memc == 0)
>> +		for_each_compatible_node(mdn, NULL, "brcm,brcmstb-memc")
>> +			if (of_device_is_available(mdn))
>> +				num_memc++;
> 
> Why is this?

This is so we do not end-up programming the PCIe RC which is agnostic of
the number of

> 
>> +	resource_list_for_each_entry(win, &res) {
>> +		struct brcm_window *w = &pcie->out_wins[i];
>> +
>> +		r = win->res;
>> +
>> +		if (!r->flags)
>> +			continue;
>> +
>> +		switch (resource_type(r)) {
>> +		case IORESOURCE_MEM:
>> +			w->cpu_addr = r->start;
>> +			w->size = resource_size(r);
>> +			w->pcie_iomem_res.name  = "External PCIe MEM";
>> +			w->pcie_iomem_res.flags = r->flags;
>> +			w->pcie_iomem_res.start = r->start;
>> +			w->pcie_iomem_res.end   = r->end;
>> +			pcie->num_out_wins++;
>> +			i++;
>> +			/* Request memory region resources. */
>> +			ret = devm_request_resource(&pdev->dev,
>> +						    &iomem_resource,
>> +						    &w->pcie_iomem_res);
>> +			if (ret) {
>> +				dev_err(&pdev->dev,
>> +					"request PCIe memory resource failed\n");
>> +				goto out_err_clk;
>> +			}
>> +			break;
>> +
>> +		default:
>> +			continue;
>> +		}
>> +	}
> 
> What about IORESOURCE_IO?

We do not support I/O space on this controller AFAIR. Our downstream
driver does insert a fake bogus I/O range, but I cannot really remember
why that was needed now, Jim do you remember?
-- 
Florian


From nm at ti.com  Wed May  4 12:50:36 2016
From: nm at ti.com (Nishanth Menon)
Date: Wed, 4 May 2016 14:50:36 -0500
Subject: [PATCH] ARM: dts: omap5-board-common: Describe the voltage supply
 mapping accurately
In-Reply-To: <1462389618-28860-1-git-send-email-nm@ti.com>
References: <1462389618-28860-1-git-send-email-nm@ti.com>
Message-ID: <572A528C.4090302@ti.com>

On 05/04/2016 02:20 PM, Nishanth Menon wrote:
[...]

> @@ -551,6 +590,8 @@
>  
>  				ldo9_reg: ldo9 {
>  					/* VCC_DV_SDIO: vdds_sdcard */
> +					vin-supply = <&vmmcsdio_fixed>;
> +

There is an extra white space here, and vmmcsd_fixed is the regulator
to be used, looks like vmmcsdio_fixed should ideally been vwlan_fixed
or something.. the actual rail to LDO9_IN was called vmmc_3v3_SDIO..

Sorry for the confusion. Unfortunately, I can not recreate the fail on
my board, but this sounded like the closest fix I can think of.




-- 
Regards,
Nishanth Menon


From arnd at arndb.de  Wed May  4 12:56:58 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 04 May 2016 21:56:58 +0200
Subject: [PATCH 2/2] pci: host: Add Broadcom STB PCIE RC controller
In-Reply-To: <572A4F31.8010802@gmail.com>
References: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>
 <2339405.90vXV1p6zU@wuerfel> <572A4F31.8010802@gmail.com>
Message-ID: <4199321.vpfzMt0zhT@wuerfel>

On Wednesday 04 May 2016 12:36:17 Florian Fainelli wrote:
> On 03/05/16 02:57, Arnd Bergmann wrote:
> >> +static const struct pcie_cfg_data generic_cfg = {
> >> +	.offsets	= pcie_offsets,
> >> +	.type		= GENERIC,
> >> +};
> > 
> > The way you access the config space here seems very indirect. I'd
> > suggest instead writing two sets of pci_ops, with hardcoded registers
> > offsets in them, and a function pointer to access the RGR1_SW_INIT_1
> > register.
> 
> How about introducing helper functions but keeping the same set of
> read/write pci_ops instead, would that seem more acceptable? I agree
> that the macros are not the friendliest thing.

I can't think of how that would look right now. My impression was that
the macros here are mainly used to implement pci_ops, so I suggested
having two copies of those. Of course the two copies could call the
same implementation and just pass in some constant that the compiler
can then optimize again in any possible way.

> >> +struct brcm_msi {
> >> +	struct irq_domain *domain;
> >> +	struct irq_chip irq_chip;
> >> +	struct msi_controller chip;
> >> +	struct mutex lock;
> >> +	int irq;
> >> +	/* intr_base is the base pointer for interrupt status/set/clr regs */
> >> +	void __iomem *intr_base;
> >> +	/* intr_legacy_mask indicates how many bits are MSI interrupts */
> >> +	u32 intr_legacy_mask;
> >> +	/* intr_legacy_offset indicates bit position of MSI_01 */
> >> +	u32 intr_legacy_offset;
> >> +	/* used indicates which MSI interrupts have been alloc'd */
> >> +	unsigned long used;
> >> +	/* working indicates that on boot we have brought up MSI */
> >> +	bool working;
> >> +};
> > 
> > I'd move the MSI controller stuff into a separate file, and add a way to
> > override it. It's likely that at some point the same PCIe implementation
> > will be used with a modern GICv3 or GICv2m, so you should be able to
> > look up the msi controller from a property.
> 
> Good point, let's do that, though all controllers actually do support
> MSI, so I wonder.

The point is more that you might have more than one MSI implementation
in a future SoC, if you have both a GICv3 and this PCIe block, you
could use either one of them, but presumably using the GIC will be more
efficient because it actually allows doing IRQ affinity and having
low-latency interrupts when you don't need an expensive readl().

> >> +
> >> +	/* set up 4GB PCIE->SCB memory window on BAR2 */
> >> +	bpcie_writel(0x00000011, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
> >> +	bpcie_writel(0x00000000, base + PCIE_MISC_RC_BAR2_CONFIG_HI);
> > 
> > Where does this window come from? It's not in the DT as far as I can see.
> 
> This is an architectural maximum value which is baked into the PCIE Root
> Complex hardware, on all generations that this driver supports. We
> configure the largest address match rang size here, just to be safe,
> AFAICT there is no point in looking at the inbound or outbound window
> sizes to re-program that differently.

Ok, makes sense. In theory you could limit this to isolate PCI
bus masters from doing things you don't want them to (e.g. for
a hypervisor that assigns the entire PCI host bridge to a VM),
but I can't think of a use case for Linux here.

> >> +	INIT_LIST_HEAD(&pcie->pwr_supplies);
> >> +	INIT_LIST_HEAD(&pcie->resource);
> >> +
> >> +	supplies = of_property_count_strings(dn, "supply-names");
> >> +	if (supplies <= 0)
> >> +		supplies = 0;
> >> +
> >> +	for (i = 0; i < supplies; i++) {
> >> +		if (of_property_read_string_index(dn, "supply-names", i,
> >> +						  &name))
> >> +			continue;
> >> +		supply = devm_kzalloc(&pdev->dev, sizeof(*supply), GFP_KERNEL);
> >> +		if (!supply)
> >> +			return -ENOMEM;
> >> +
> >> +		strncpy(supply->name, name, sizeof(supply->name));
> >> +		supply->name[sizeof(supply->name) - 1] = '\0';
> >> +		supply->regulator = devm_regulator_get(&pdev->dev, name);
> >> +		if (IS_ERR(supply->regulator)) {
> >> +			dev_err(&pdev->dev, "Unable to get %s supply, err=%d\n",
> >> +				name, (int)PTR_ERR(supply->regulator));
> >> +			continue;
> >> +		}
> >> +
> >> +		if (regulator_enable(supply->regulator))
> >> +			dev_err(&pdev->dev, "Unable to enable %s supply.\n",
> >> +				name);
> >> +		list_add_tail(&supply->node, &pcie->pwr_supplies);
> >> +	}
> > 
> > Don't parse the regulator properties yourself here, use the proper APIs.
> 
> I will probably drop this for now, and  add it later, there are only a
> handful of boards which requires this, and ultimately, I think we should
> be seaking for a more generic solutions, we can't be the only ones doing
> that.

So is this the supply for the slots attached to the PCI host rather than
the host bridge itself?

> > 
> >> +	/* 'num_memc' will be set only by the first controller, and all
> >> +	 * other controllers will use the value set by the first.
> >> +	 */
> >> +	if (num_memc == 0)
> >> +		for_each_compatible_node(mdn, NULL, "brcm,brcmstb-memc")
> >> +			if (of_device_is_available(mdn))
> >> +				num_memc++;
> > 
> > Why is this?
> 
> This is so we do not end-up programming the PCIe RC which is agnostic of
> the number of

You didn't complete this sentence, but I think I've gotten a better
idea of what is going on from the code now. It looks like this
is used to program a set of default DMA ranges into the host
bridge, so there are now three ways of finding out what it
should be:

a) count the memory controllers, assume that each one has 1GB of
   address space
b) read the "brcm,log2-scb-sizes" property to find out the
   actual sizes
c) interpret the dma-ranges property

The first two seem to things in a rather nonstandard way (the binding
mentions neither of them), while the third is not implemented yet.
I think we have to improve this.

	Arnd


From f.fainelli at gmail.com  Wed May  4 13:07:20 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Wed, 4 May 2016 13:07:20 -0700
Subject: [PATCH 2/2] pci: host: Add Broadcom STB PCIE RC controller
In-Reply-To: <4199321.vpfzMt0zhT@wuerfel>
References: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>
 <2339405.90vXV1p6zU@wuerfel> <572A4F31.8010802@gmail.com>
 <4199321.vpfzMt0zhT@wuerfel>
Message-ID: <572A5678.7020603@gmail.com>

On 04/05/16 12:56, Arnd Bergmann wrote:
> On Wednesday 04 May 2016 12:36:17 Florian Fainelli wrote:
>> On 03/05/16 02:57, Arnd Bergmann wrote:
>>>> +static const struct pcie_cfg_data generic_cfg = {
>>>> +	.offsets	= pcie_offsets,
>>>> +	.type		= GENERIC,
>>>> +};
>>>
>>> The way you access the config space here seems very indirect. I'd
>>> suggest instead writing two sets of pci_ops, with hardcoded registers
>>> offsets in them, and a function pointer to access the RGR1_SW_INIT_1
>>> register.
>>
>> How about introducing helper functions but keeping the same set of
>> read/write pci_ops instead, would that seem more acceptable? I agree
>> that the macros are not the friendliest thing.
> 
> I can't think of how that would look right now. My impression was that
> the macros here are mainly used to implement pci_ops, so I suggested
> having two copies of those. Of course the two copies could call the
> same implementation and just pass in some constant that the compiler
> can then optimize again in any possible way.

Providing separate copies for read_config and write_config makes sense,
what I wanted to avoid was 3 sets of brcm_pcie_read_config and
brcm_pcie_write_config, because that would be duplicating quite some
code, working on that now.

> 
>>>> +struct brcm_msi {
>>>> +	struct irq_domain *domain;
>>>> +	struct irq_chip irq_chip;
>>>> +	struct msi_controller chip;
>>>> +	struct mutex lock;
>>>> +	int irq;
>>>> +	/* intr_base is the base pointer for interrupt status/set/clr regs */
>>>> +	void __iomem *intr_base;
>>>> +	/* intr_legacy_mask indicates how many bits are MSI interrupts */
>>>> +	u32 intr_legacy_mask;
>>>> +	/* intr_legacy_offset indicates bit position of MSI_01 */
>>>> +	u32 intr_legacy_offset;
>>>> +	/* used indicates which MSI interrupts have been alloc'd */
>>>> +	unsigned long used;
>>>> +	/* working indicates that on boot we have brought up MSI */
>>>> +	bool working;
>>>> +};
>>>
>>> I'd move the MSI controller stuff into a separate file, and add a way to
>>> override it. It's likely that at some point the same PCIe implementation
>>> will be used with a modern GICv3 or GICv2m, so you should be able to
>>> look up the msi controller from a property.
>>
>> Good point, let's do that, though all controllers actually do support
>> MSI, so I wonder.
> 
> The point is more that you might have more than one MSI implementation
> in a future SoC, if you have both a GICv3 and this PCIe block, you
> could use either one of them, but presumably using the GIC will be more
> efficient because it actually allows doing IRQ affinity and having
> low-latency interrupts when you don't need an expensive readl().

OK, I have actually stated doing just that.

> 
>>>> +
>>>> +	/* set up 4GB PCIE->SCB memory window on BAR2 */
>>>> +	bpcie_writel(0x00000011, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
>>>> +	bpcie_writel(0x00000000, base + PCIE_MISC_RC_BAR2_CONFIG_HI);
>>>
>>> Where does this window come from? It's not in the DT as far as I can see.
>>
>> This is an architectural maximum value which is baked into the PCIE Root
>> Complex hardware, on all generations that this driver supports. We
>> configure the largest address match rang size here, just to be safe,
>> AFAICT there is no point in looking at the inbound or outbound window
>> sizes to re-program that differently.
> 
> Ok, makes sense. In theory you could limit this to isolate PCI
> bus masters from doing things you don't want them to (e.g. for
> a hypervisor that assigns the entire PCI host bridge to a VM),
> but I can't think of a use case for Linux here.

Exactly.

> 
>>>> +	INIT_LIST_HEAD(&pcie->pwr_supplies);
>>>> +	INIT_LIST_HEAD(&pcie->resource);
>>>> +
>>>> +	supplies = of_property_count_strings(dn, "supply-names");
>>>> +	if (supplies <= 0)
>>>> +		supplies = 0;
>>>> +
>>>> +	for (i = 0; i < supplies; i++) {
>>>> +		if (of_property_read_string_index(dn, "supply-names", i,
>>>> +						  &name))
>>>> +			continue;
>>>> +		supply = devm_kzalloc(&pdev->dev, sizeof(*supply), GFP_KERNEL);
>>>> +		if (!supply)
>>>> +			return -ENOMEM;
>>>> +
>>>> +		strncpy(supply->name, name, sizeof(supply->name));
>>>> +		supply->name[sizeof(supply->name) - 1] = '\0';
>>>> +		supply->regulator = devm_regulator_get(&pdev->dev, name);
>>>> +		if (IS_ERR(supply->regulator)) {
>>>> +			dev_err(&pdev->dev, "Unable to get %s supply, err=%d\n",
>>>> +				name, (int)PTR_ERR(supply->regulator));
>>>> +			continue;
>>>> +		}
>>>> +
>>>> +		if (regulator_enable(supply->regulator))
>>>> +			dev_err(&pdev->dev, "Unable to enable %s supply.\n",
>>>> +				name);
>>>> +		list_add_tail(&supply->node, &pcie->pwr_supplies);
>>>> +	}
>>>
>>> Don't parse the regulator properties yourself here, use the proper APIs.
>>
>> I will probably drop this for now, and  add it later, there are only a
>> handful of boards which requires this, and ultimately, I think we should
>> be seaking for a more generic solutions, we can't be the only ones doing
>> that.
> 
> So is this the supply for the slots attached to the PCI host rather than
> the host bridge itself?

Technically yes, there are for the attached PCI slots, not the hsost
bridge, so their are misplaced, we need to rework that, and I would
prefer if there was a way to make it pre-scan type of operation offered
by the core PCI code itself, but then there is a chicken and egg
problem: you cannot get regulators for device_nodes that have not been
created yet, and you can't create pci_device and their corresponding
device_nodes until you have turned them on...

> 
>>>
>>>> +	/* 'num_memc' will be set only by the first controller, and all
>>>> +	 * other controllers will use the value set by the first.
>>>> +	 */
>>>> +	if (num_memc == 0)
>>>> +		for_each_compatible_node(mdn, NULL, "brcm,brcmstb-memc")
>>>> +			if (of_device_is_available(mdn))
>>>> +				num_memc++;
>>>
>>> Why is this?
>>
>> This is so we do not end-up programming the PCIe RC which is agnostic of
>> the number of
> 
> You didn't complete this sentence, but I think I've gotten a better
> idea of what is going on from the code now. It looks like this
> is used to program a set of default DMA ranges into the host
> bridge, so there are now three ways of finding out what it
> should be:
> 
> a) count the memory controllers, assume that each one has 1GB of
>    address space
> b) read the "brcm,log2-scb-sizes" property to find out the
>    actual sizes
> c) interpret the dma-ranges property
> 
> The first two seem to things in a rather nonstandard way (the binding
> mentions neither of them), while the third is not implemented yet.
> I think we have to improve this.

What I meant to say is that we want to avoid programming a SCB window
(SCB equals memory controller for the sake of making things simple here)
which does not have a baking memory controller, because, well, guess
what happens, the PCIe RC could be trying to access non existent memory,
and just stall doing so because no error reporting, I can't remember
which chips had this problem exactly, but there were definitively some,
so the concern is real.

The "brcm,log2-scb-sizes" should be correctly populated all the time in
our Device Tree blobs, but we are not quite making a use of them here.

"dma-ranges" seems like an appropriate solution, but sorts of forces us
to reinforce the same information that is available somewhere in the
Device Tree within the memory controllers nodes themselves.

Let me think about this some more.
-- 
Florian


From arnd at arndb.de  Wed May  4 13:56:34 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 04 May 2016 22:56:34 +0200
Subject: [PATCH 2/2] pci: host: Add Broadcom STB PCIE RC controller
In-Reply-To: <572A5678.7020603@gmail.com>
References: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>
 <4199321.vpfzMt0zhT@wuerfel> <572A5678.7020603@gmail.com>
Message-ID: <246366157.3SALjN7m5a@wuerfel>

On Wednesday 04 May 2016 13:07:20 Florian Fainelli wrote:
> On 04/05/16 12:56, Arnd Bergmann wrote:
> > On Wednesday 04 May 2016 12:36:17 Florian Fainelli wrote:
> >> On 03/05/16 02:57, Arnd Bergmann wrote:
> >> How about introducing helper functions but keeping the same set of
> >> read/write pci_ops instead, would that seem more acceptable? I agree
> >> that the macros are not the friendliest thing.
> > 
> > I can't think of how that would look right now. My impression was that
> > the macros here are mainly used to implement pci_ops, so I suggested
> > having two copies of those. Of course the two copies could call the
> > same implementation and just pass in some constant that the compiler
> > can then optimize again in any possible way.
> 
> Providing separate copies for read_config and write_config makes sense,
> what I wanted to avoid was 3 sets of brcm_pcie_read_config and
> brcm_pcie_write_config, because that would be duplicating quite some
> code, working on that now.

Ok, good.


> >>> Don't parse the regulator properties yourself here, use the proper APIs.
> >>
> >> I will probably drop this for now, and  add it later, there are only a
> >> handful of boards which requires this, and ultimately, I think we should
> >> be seaking for a more generic solutions, we can't be the only ones doing
> >> that.
> > 
> > So is this the supply for the slots attached to the PCI host rather than
> > the host bridge itself?
> 
> Technically yes, there are for the attached PCI slots, not the hsost
> bridge, so their are misplaced, we need to rework that, and I would
> prefer if there was a way to make it pre-scan type of operation offered
> by the core PCI code itself, but then there is a chicken and egg
> problem: you cannot get regulators for device_nodes that have not been
> created yet, and you can't create pci_device and their corresponding
> device_nodes until you have turned them on...

Ah, I can see how that is doable but rather tricky to get done right.

Are there actually any legacy PCI slots that need this, or are they PCIe
ports? If we are lucky, they are all PCIe ports that have a standard
port device, so we can could add support for a regulator supply
in drivers/pci/pcie/portdrv_pci.c: The port device will should always be
present as a child of the root node, but the actual device connected
to the port is what needs the regulator.

> > You didn't complete this sentence, but I think I've gotten a better
> > idea of what is going on from the code now. It looks like this
> > is used to program a set of default DMA ranges into the host
> > bridge, so there are now three ways of finding out what it
> > should be:
> > 
> > a) count the memory controllers, assume that each one has 1GB of
> >    address space
> > b) read the "brcm,log2-scb-sizes" property to find out the
> >    actual sizes
> > c) interpret the dma-ranges property
> > 
> > The first two seem to things in a rather nonstandard way (the binding
> > mentions neither of them), while the third is not implemented yet.
> > I think we have to improve this.
> 
> What I meant to say is that we want to avoid programming a SCB window
> (SCB equals memory controller for the sake of making things simple here)
> which does not have a baking memory controller, because, well, guess
> what happens, the PCIe RC could be trying to access non existent memory,
> and just stall doing so because no error reporting, I can't remember
> which chips had this problem exactly, but there were definitively some,
> so the concern is real.
> 
> The "brcm,log2-scb-sizes" should be correctly populated all the time in
> our Device Tree blobs, but we are not quite making a use of them here.
> 
> "dma-ranges" seems like an appropriate solution, but sorts of forces us
> to reinforce the same information that is available somewhere in the
> Device Tree within the memory controllers nodes themselves.
> 
> Let me think about this some more.

Maybe a property that contains a tuple of <&mc-phandle start-addr size>
instead of "brcm,log2-scb-sizes" would be better here?

	Arnd


From rjw at rjwysocki.net  Wed May  4 14:20:28 2016
From: rjw at rjwysocki.net (Rafael J. Wysocki)
Date: Wed, 04 May 2016 23:20:28 +0200
Subject: [PATCH] ARM: cpuidle: Pass on arm_cpuidle_suspend()'s return value
In-Reply-To: <20160428082023.GA10216@linaro.org>
References: <1461669301-30834-1-git-send-email-james.morse@arm.com>
 <20160427091434.GA4303@red-moon> <20160428082023.GA10216@linaro.org>
Message-ID: <13315467.gEDWYxNU10@vostro.rjw.lan>

On Thursday, April 28, 2016 10:20:23 AM Daniel Lezcano wrote:
> On Wed, Apr 27, 2016 at 10:14:34AM +0100, Lorenzo Pieralisi wrote:
> > [+ Lina]
> > 
> > On Tue, Apr 26, 2016 at 09:05:57PM +0200, Rafael J. Wysocki wrote:
> > > On Tue, Apr 26, 2016 at 1:31 PM, Lorenzo Pieralisi
> > > <lorenzo.pieralisi at arm.com> wrote:
> > > > On Tue, Apr 26, 2016 at 12:15:01PM +0100, James Morse wrote:
> > > >> arm_cpuidle_suspend() may return -EOPNOTSUPP, or any value returned
> > > >> by the cpu_ops/cpuidle_ops suspend call. arm_enter_idle_state() doesn't
> > > >> update 'ret' with this value, meaning we always signal success to
> > > >> cpuidle_enter_state(), causing it to update the usage counters as if we
> > > >> succeeded.
> > > >>
> > > >> Fixes: 191de17aa3c1 ("ARM64: cpuidle: Replace cpu_suspend by the common ARM/ARM64 function")
> > > >> Signed-off-by: James Morse <james.morse at arm.com>
> > > >> ---
> > > >>  drivers/cpuidle/cpuidle-arm.c | 2 +-
> > > >>  1 file changed, 1 insertion(+), 1 deletion(-)
> > > >
> > > > Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
> 
> Acked-by: Daniel Lezcano <daniel.lezcano at linaro.org>

OK, applied, tagged for -stable (4.1+).

Thanks everybody!



From cov at codeaurora.org  Wed May  4 14:21:18 2016
From: cov at codeaurora.org (Christopher Covington)
Date: Wed, 4 May 2016 17:21:18 -0400
Subject: [RFC 1/5] powerpc: Rename context.vdso_base to context.vdso
In-Reply-To: <5726A7D5.7030305@gmail.com>
References: <20151202121918.GA4523@arm.com>
 <1461856737-17071-1-git-send-email-cov@codeaurora.org>
 <1461856737-17071-2-git-send-email-cov@codeaurora.org>
 <5726A7D5.7030305@gmail.com>
Message-ID: <572A67CE.4010109@codeaurora.org>

Hi Balbir,

On 05/01/2016 09:05 PM, Balbir Singh wrote:
> On 29/04/16 01:18, Christopher Covington wrote:
>> In order to share remap and unmap support for the VDSO with other
>> architectures without duplicating the code, we need a common name and type
>> for the address of the VDSO. An informal survey of the architectures
>> indicates unsigned long vdso is popular. Change the variable name in
>> powerpc from mm->context.vdso_base to simply mm->context.vdso.
> 
> Could you please provide additional details on why the remap/unmap operations are required?

The goal is to make checkpointing and restoring processes work on
several different architectures and ABIs, in the face of Address Space
Layout Randomization (ASLR) and other factors that might change the VDSO
virtual address from one exec() to the next.

Here's the patch adding PowerPC support:

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=83d3f0e90c6c8f833e3da91917c243a916fda69e

> This patch does rename, but should it abstract via a function acesss
> to vmap field using arch_* operations? Not sure

I'm sorry, but I don't understand this question. Are you saying ARM,
Power etc. need VDSO unmap and remap log that behave differently? So far
I've found the differences to be stylistic rather than really affecting
generated code behavior.

Thanks,
Christopher Covington

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


From festevam at gmail.com  Wed May  4 14:43:47 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Wed,  4 May 2016 18:43:47 -0300
Subject: [PATCH v2 1/2] ARM: dts: imx6ul: Specify the SAI index
Message-ID: <1462398228-24447-1-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam at nxp.com>

Introduce the "sai-index" property to indicate the index of the SAI port.

This is useful for configuring the SAI_MCLK output as we need to write
to bits 19, 20 and 21 of register GPR1 for SAI1, SAI2 and SAI3,
respectively.

Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
---
Change since v1:
- None

 arch/arm/boot/dts/imx6ul.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
index 4356b65..b11d5a8 100644
--- a/arch/arm/boot/dts/imx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul.dtsi
@@ -281,6 +281,7 @@
 					dmas = <&sdma 35 24 0>,
 					       <&sdma 36 24 0>;
 					dma-names = "rx", "tx";
+					sai-index = <1>;
 					status = "disabled";
 				};
 
@@ -296,6 +297,7 @@
 					dmas = <&sdma 37 24 0>,
 					       <&sdma 38 24 0>;
 					dma-names = "rx", "tx";
+					sai-index = <2>;
 					status = "disabled";
 				};
 
@@ -311,6 +313,7 @@
 					dmas = <&sdma 39 24 0>,
 					       <&sdma 40 24 0>;
 					dma-names = "rx", "tx";
+					sai-index = <3>;
 					status = "disabled";
 				};
 			};
-- 
1.9.1



From festevam at gmail.com  Wed May  4 14:43:48 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Wed,  4 May 2016 18:43:48 -0300
Subject: [PATCH v2 2/2] ARM: dts: imx6ul-14x14-evk: Pass "fsl,
 sai-mclk-direction-output"
In-Reply-To: <1462398228-24447-1-git-send-email-festevam@gmail.com>
References: <1462398228-24447-1-git-send-email-festevam@gmail.com>
Message-ID: <1462398228-24447-2-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam at nxp.com>

Pass "fsl,sai-mclk-direction-output" to the sai2 node, so that the
SAI2_MCLK can be an output.

Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
---
Changes since v1:
- Drop gpr node
- Use "fsl,sai-mclk-direction-output"

 arch/arm/boot/dts/imx6ul-14x14-evk.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dts b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
index 668a729..918c7c8 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk.dts
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
@@ -146,6 +146,7 @@
 			  <&clks IMX6UL_CLK_SAI2>;
 	assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
 	assigned-clock-rates = <0>, <12288000>;
+	fsl,sai-mclk-direction-output;
 	status = "okay";
 };
 
-- 
1.9.1



From ynorov at caviumnetworks.com  Wed May  4 14:49:49 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 5 May 2016 00:49:49 +0300
Subject: [PATCH 24/25] arm64:ilp32: add vdso-ilp32 and use for signal
 return
In-Reply-To: <57289C75.50904@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1554541.oDP7Ro5zB2@wuerfel>
 <20160503090045.GB10733@e104818-lin.cambridge.arm.com>
 <3846428.6xx69KGEja@wuerfel> <57288660.9030607@huawei.com>
 <57289C75.50904@huawei.com>
Message-ID: <20160504214949.GA28217@yury-N73SV>

On Tue, May 03, 2016 at 08:41:25PM +0800, Zhangjian (Bamvor) wrote:
> Hi, all
> 
> After apply this patch with my small testcase, the vsyscall of gettimeofday in
> ilp32 works in both big endian and small endian. In this patch, I use the
> different register and offset for ilp32 and lp64. Actually, the
> COMPAT_TVAL_TV_SEC is same as TVAL_TV_SEC(so as to COMPAT_TSPEC_TV_SEC and
> TSPEC_TV_SEC). I add it to keep the logic clear. I also change the version
> of vdso to 4.6. It should change to 2.6.39 if glibc is not update.
> 

[...]

Hi Bamvor,

It works for me as well. Thank you.
I'll incorporate it in next submission.

Yury.


From festevam at gmail.com  Wed May  4 15:33:17 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Wed,  4 May 2016 19:33:17 -0300
Subject: [PATCH v3 1/2] ARM: dts: imx6ul: Add SAI alias
Message-ID: <1462401198-931-1-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam at nxp.com>

Add SAI alias entries, which makes it possibe for the SAI driver
to retrieve the port instance.

Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
---
Changes since v1:
- Newly introduced in this series.

 arch/arm/boot/dts/imx6ul.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
index 4356b65..6d1c317 100644
--- a/arch/arm/boot/dts/imx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul.dtsi
@@ -36,6 +36,9 @@
 		serial5 = &uart6;
 		serial6 = &uart7;
 		serial7 = &uart8;
+		sai1 = &sai1;
+		sai2 = &sai2;
+		sai3 = &sai3;
 		spi0 = &ecspi1;
 		spi1 = &ecspi2;
 		spi2 = &ecspi3;
-- 
1.9.1



From festevam at gmail.com  Wed May  4 15:33:18 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Wed,  4 May 2016 19:33:18 -0300
Subject: [PATCH v3 2/2] ARM: dts: imx6ul-14x14-evk: Pass "fsl,
 sai-mclk-direction-output"
In-Reply-To: <1462401198-931-1-git-send-email-festevam@gmail.com>
References: <1462401198-931-1-git-send-email-festevam@gmail.com>
Message-ID: <1462401198-931-2-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam at nxp.com>

Pass "fsl,sai-mclk-direction-output" to the sai2 node, so that the
SAI2_MCLK can be an output.

Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
---
 arch/arm/boot/dts/imx6ul-14x14-evk.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dts b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
index 668a729..918c7c8 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk.dts
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
@@ -146,6 +146,7 @@
 			  <&clks IMX6UL_CLK_SAI2>;
 	assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
 	assigned-clock-rates = <0>, <12288000>;
+	fsl,sai-mclk-direction-output;
 	status = "okay";
 };
 
-- 
1.9.1



From zajec5 at gmail.com  Wed May  4 15:36:24 2016
From: zajec5 at gmail.com (=?UTF-8?B?UmFmYcWCIE1pxYJlY2tp?=)
Date: Thu, 5 May 2016 00:36:24 +0200
Subject: [PATCH] ARM: BCM5301X: Add DT for Luxul XAP-1510
In-Reply-To: <572A453E.6010000@gmail.com>
References: <1462296501-5209-1-git-send-email-dhaab@luxul.com>
 <572A453E.6010000@gmail.com>
Message-ID: <CACna6ryWGsOwBhhauJTROi2BPbmgGn_4oYnKc-L8-3Joy+5M7g@mail.gmail.com>

On 4 May 2016 at 20:53, Florian Fainelli <f.fainelli at gmail.com> wrote:
> On 03/05/16 10:28, Dan Haab wrote:
>> Luxul XAP-1510 is an AP device based on BCM4708 SoC. It uses flash
>> memory connected to the SPI controller.
>
> Looks fine, except one nit:
>
>> diff --git a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
>> new file mode 100644
>> index 0000000..f4460b5
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
>> @@ -0,0 +1,67 @@
>> +/*
>> + * Broadcom BCM470X / BCM5301X ARM platform code.
>> + * DTS for Luxul XAP-1510
>> + *
>> + * Copyright 2015 Luxul Inc.
>> + *
>> + * Licensed under the GNU/GPL. See COPYING for details.
>
> The ARM SoC maintainer have been asking to utilize a license which is
> also BSD compatible, so something along the lines of this one:
>
> arch/arm/boot/dts/bcm911360k.dts
>
> Do you mind respining the patch to include that kind of license header?

I wasn't aware of this neither. Shall we re-license existing DTS files
as well? I'm fine with changing them to BSD compatible.

I'm a bit confused by using BSD license only. Kernel is licensed under
GNU GPL version 2 and if there are some BSD compatible modules, they
use dual licensing model (BSD/GPL). Shouldn't we use BSD/GPL in DTS
files as well then?

-- 
Rafa?


From andy.gross at linaro.org  Wed May  4 15:50:38 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed,  4 May 2016 17:50:38 -0500
Subject: [Patch v3 1/8] dt/bindings: firmware: Add Qualcomm SCM binding
In-Reply-To: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
References: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462402245-18295-2-git-send-email-andy.gross@linaro.org>

This patch adds the device tree support for the Qualcomm SCM firmware.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 .../devicetree/bindings/firmware/qcom,scm.txt      | 26 ++++++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/qcom,scm.txt

diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
new file mode 100644
index 0000000..ee7cd12
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
@@ -0,0 +1,26 @@
+QCOM Secure Channel Manager (SCM)
+
+Qualcomm processors include an interface to communicate to the secure firmware.
+This interface allows for clients to request different types of actions.  These
+can include CPU power up/down, HDCP requests, loading of firmware, and other
+assorted actions.
+
+Required properties:
+- compatible: must contain one of the following:
+ * "qcom,scm-a-family" for A family Qualcomm processors (APQ8064, MSM8960, etc)
+ * "qcom,scm" for B family and later processors (MSM8916, APQ8084, MSM8974, etc)
+- clocks: One to three clocks may be required based on compatible.
+ * Only core clock required for "qcom,scm-apq8064"
+ * Core, iface, and bus clocks required for "qcom,scm"
+- clock-names: Must contain "core" for the core clock, "iface" for the interface
+  clock and "bus" for the bus clock per the requirements of the compatible.
+
+Example for MSM8916:
+
+	firmware {
+		scm {
+			compatible = "qcom,scm";
+			clocks = <&gcc GCC_CRYPTO_CLK> , <&gcc GCC_CRYPTO_AXI_CLK>, <&gcc GCC_CRYPTO_AHB_CLK>;
+			clock-names = "core", "bus", "iface";
+		};
+	};
-- 
1.9.1



From andy.gross at linaro.org  Wed May  4 15:50:37 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed,  4 May 2016 17:50:37 -0500
Subject: [Patch v3 0/8] Qualcomm SCM Rework
Message-ID: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>

The following set of patches does a bit of rework on the existing
Qualcomm SCM firmware.  The first couple of patches deals with turning
the current SCM into a platform driver.  The next couple are cleanups
that make adding the 64 support a little easier.  I added in a patch to
convert the scm-32 to use DMA streaming APIs.

I took Kumar's 64 bit support patch and modified it to use the arm_smccc
calls.  This simplified things quite a bit.

Lastly, there are a few DT patches to add the firmware node for a couple of the
supported platforms.

Changes from v2:
  * Added use of streaming DMA APIs for scm-32.
  * Changed DT binding to simplify compats.
  * Removed Kconfig.platform change that selected QCOM_SCM for ARM64
  * Fixed misc comments
  * Changed init function to populate the device differently.
  * Fixed missing of_node_put

Changes from v1:
  * Changed binding to reflect proper firmware node usage
  * Added arch_initcall to populate the firmware device, if present
  * Fixed various review comments
  * Removed extraneous includes from SCM 64 file.

Andy Gross (7):
  dt/bindings: firmware: Add Qualcomm SCM binding
  firmware: qcom: scm: Convert SCM to platform driver
  firmware: qcom: scm: Use atomic SCM for cold boot
  firmware: qcom: scm: Generalize shared error map
  firmware: qcom: scm: Convert to streaming DMA APIS
  dts: qcom: apq8084: Add SCM firmware node
  arm64: dts: msm8916: Add SCM firmware node

Kumar Gala (1):
  firmware: qcom: scm: Add support for ARM64 SoCs

 .../devicetree/bindings/firmware/qcom,scm.txt      |  26 +++
 arch/arm/boot/dts/qcom-apq8084.dtsi                |   8 +
 arch/arm64/boot/dts/qcom/msm8916.dtsi              |   8 +
 drivers/firmware/qcom_scm-32.c                     | 234 +++++++++------------
 drivers/firmware/qcom_scm-64.c                     | 208 +++++++++++++++++-
 drivers/firmware/qcom_scm.c                        | 169 ++++++++++++++-
 drivers/firmware/qcom_scm.h                        |  31 ++-
 7 files changed, 522 insertions(+), 162 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/firmware/qcom,scm.txt

-- 
1.9.1



From andy.gross at linaro.org  Wed May  4 15:50:39 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed,  4 May 2016 17:50:39 -0500
Subject: [Patch v3 2/8] firmware: qcom: scm: Convert SCM to platform driver
In-Reply-To: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
References: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462402245-18295-3-git-send-email-andy.gross@linaro.org>

This patch converts the Qualcomm SCM firmware driver into a platform
driver.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm.c | 163 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 154 insertions(+), 9 deletions(-)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 45c008d..63a2bfa 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -10,19 +10,61 @@
  * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
  */
-
+#include <linux/platform_device.h>
+#include <linux/module.h>
 #include <linux/cpumask.h>
 #include <linux/export.h>
 #include <linux/types.h>
 #include <linux/qcom_scm.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
 
 #include "qcom_scm.h"
 
+struct qcom_scm {
+	struct device *dev;
+	struct clk *core_clk;
+	struct clk *iface_clk;
+	struct clk *bus_clk;
+};
+
+static struct qcom_scm *__scm;
+
+static int qcom_scm_clk_enable(void)
+{
+	int ret;
+
+	ret = clk_prepare_enable(__scm->core_clk);
+	if (ret)
+		goto bail;
+
+	ret = clk_prepare_enable(__scm->iface_clk);
+	if (ret)
+		goto disable_core;
+
+	ret = clk_prepare_enable(__scm->bus_clk);
+	if (ret)
+		goto disable_iface;
+
+	return 0;
+
+disable_iface:
+	clk_disable_unprepare(__scm->iface_clk);
+disable_core:
+	clk_disable_unprepare(__scm->core_clk);
+bail:
+	return ret;
+}
+
+static void qcom_scm_clk_disable(void)
+{
+	clk_disable_unprepare(__scm->core_clk);
+	clk_disable_unprepare(__scm->iface_clk);
+	clk_disable_unprepare(__scm->bus_clk);
+}
+
 /**
  * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
  * @entry: Entry point function for the cpus
@@ -72,12 +114,17 @@ EXPORT_SYMBOL(qcom_scm_cpu_power_down);
  */
 bool qcom_scm_hdcp_available(void)
 {
-	int ret;
+	int ret = qcom_scm_clk_enable();
+
+	if (ret)
+		return ret;
 
 	ret = __qcom_scm_is_call_available(QCOM_SCM_SVC_HDCP,
-		QCOM_SCM_CMD_HDCP);
+						QCOM_SCM_CMD_HDCP);
+
+	qcom_scm_clk_disable();
 
-	return (ret > 0) ? true : false;
+	return ret > 0 ? true : false;
 }
 EXPORT_SYMBOL(qcom_scm_hdcp_available);
 
@@ -91,6 +138,104 @@ EXPORT_SYMBOL(qcom_scm_hdcp_available);
  */
 int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
 {
-	return __qcom_scm_hdcp_req(req, req_cnt, resp);
+	int ret = qcom_scm_clk_enable();
+
+	if (ret)
+		return ret;
+
+	ret = __qcom_scm_hdcp_req(req, req_cnt, resp);
+	qcom_scm_clk_disable();
+	return ret;
 }
 EXPORT_SYMBOL(qcom_scm_hdcp_req);
+
+static int qcom_scm_probe(struct platform_device *pdev)
+{
+	struct qcom_scm *scm;
+	int ret;
+
+	scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL);
+	if (!scm)
+		return -ENOMEM;
+
+	scm->core_clk = devm_clk_get(&pdev->dev, "core");
+	if (IS_ERR(scm->core_clk)) {
+		if (PTR_ERR(scm->core_clk) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "failed to acquire core clk\n");
+		return PTR_ERR(scm->core_clk);
+	}
+
+	if (!of_device_is_compatible(pdev->dev.of_node, "qcom,scm-apq8064")) {
+		scm->iface_clk = devm_clk_get(&pdev->dev, "iface");
+		if (IS_ERR(scm->iface_clk)) {
+			if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER)
+				dev_err(&pdev->dev, "failed to acquire iface clk\n");
+			return PTR_ERR(scm->iface_clk);
+		}
+
+		scm->bus_clk = devm_clk_get(&pdev->dev, "bus");
+		if (IS_ERR(scm->bus_clk)) {
+			if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER)
+				dev_err(&pdev->dev, "failed to acquire bus clk\n");
+			return PTR_ERR(scm->bus_clk);
+		}
+	}
+
+	/* vote for max clk rate for highest performance */
+	ret = clk_set_rate(scm->core_clk, INT_MAX);
+	if (ret)
+		return ret;
+
+	__scm = scm;
+	__scm->dev = &pdev->dev;
+
+	return 0;
+}
+
+static const struct of_device_id qcom_scm_dt_match[] = {
+	{ .compatible = "qcom,scm-a-family",},
+	{ .compatible = "qcom,scm",},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, qcom_scm_dt_match);
+
+static struct platform_driver qcom_scm_driver = {
+	.driver = {
+		.name	= "qcom_scm",
+		.of_match_table = qcom_scm_dt_match,
+	},
+	.probe = qcom_scm_probe,
+};
+
+static int __init qcom_scm_init(void)
+{
+	struct device_node *np, *parent;
+	int ret;
+
+	np = of_find_matching_node_and_match(NULL, qcom_scm_dt_match, NULL);
+
+	if (!np)
+		return -ENODEV;
+
+	parent = of_get_next_parent(np);
+	ret = of_platform_populate(parent, qcom_scm_dt_match, NULL, NULL);
+
+	of_node_put(parent);
+
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&qcom_scm_driver);
+}
+
+arch_initcall(qcom_scm_init);
+
+static void __exit qcom_scm_exit(void)
+{
+	platform_driver_unregister(&qcom_scm_driver);
+}
+module_exit(qcom_scm_exit);
+
+MODULE_DESCRIPTION("Qualcomm SCM driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1



From andy.gross at linaro.org  Wed May  4 15:50:40 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed,  4 May 2016 17:50:40 -0500
Subject: [Patch v3 3/8] firmware: qcom: scm: Use atomic SCM for cold boot
In-Reply-To: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
References: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462402245-18295-4-git-send-email-andy.gross@linaro.org>

This patch changes the cold_set_boot_addr function to use atomic SCM
calls.  cold_set_boot_addr required adding qcom_scm_call_atomic2 to
support the two arguments going to the smc call.  Using atomic removes
the need for memory allocation and instead places all arguments in
registers.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm-32.c | 63 ++++++++++++++++++++++++++++++------------
 1 file changed, 45 insertions(+), 18 deletions(-)

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 0883292..5be6a12 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -342,6 +342,41 @@ static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
 	return r0;
 }
 
+/**
+ * qcom_scm_call_atomic2() - Send an atomic SCM command with two arguments
+ * @svc_id:	service identifier
+ * @cmd_id:	command identifier
+ * @arg1:	first argument
+ * @arg2:	second argument
+ *
+ * This shall only be used with commands that are guaranteed to be
+ * uninterruptable, atomic and SMP safe.
+ */
+static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2)
+{
+	int context_id;
+
+	register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 2);
+	register u32 r1 asm("r1") = (u32)&context_id;
+	register u32 r2 asm("r2") = arg1;
+	register u32 r3 asm("r3") = arg2;
+
+	asm volatile(
+			__asmeq("%0", "r0")
+			__asmeq("%1", "r0")
+			__asmeq("%2", "r1")
+			__asmeq("%3", "r2")
+			__asmeq("%4", "r3")
+#ifdef REQUIRES_SEC
+			".arch_extension sec\n"
+#endif
+			"smc    #0      @ switch to secure world\n"
+			: "=r" (r0)
+			: "r" (r0), "r" (r1), "r" (r2), "r" (r3)
+			);
+	return r0;
+}
+
 u32 qcom_scm_get_version(void)
 {
 	int context_id;
@@ -378,22 +413,6 @@ u32 qcom_scm_get_version(void)
 }
 EXPORT_SYMBOL(qcom_scm_get_version);
 
-/*
- * Set the cold/warm boot address for one of the CPU cores.
- */
-static int qcom_scm_set_boot_addr(u32 addr, int flags)
-{
-	struct {
-		__le32 flags;
-		__le32 addr;
-	} cmd;
-
-	cmd.addr = cpu_to_le32(addr);
-	cmd.flags = cpu_to_le32(flags);
-	return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
-			&cmd, sizeof(cmd), NULL, 0);
-}
-
 /**
  * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
  * @entry: Entry point function for the cpus
@@ -423,7 +442,8 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
 			set_cpu_present(cpu, false);
 	}
 
-	return qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
+	return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
+				    flags, virt_to_phys(entry));
 }
 
 /**
@@ -439,6 +459,10 @@ int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
 	int ret;
 	int flags = 0;
 	int cpu;
+	struct {
+		__le32 flags;
+		__le32 addr;
+	} cmd;
 
 	/*
 	 * Reassign only if we are switching from hotplug entry point
@@ -454,7 +478,10 @@ int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
 	if (!flags)
 		return 0;
 
-	ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
+	cmd.addr = cpu_to_le32(virt_to_phys(entry));
+	cmd.flags = cpu_to_le32(flags);
+	ret = qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
+			    &cmd, sizeof(cmd), NULL, 0);
 	if (!ret) {
 		for_each_cpu(cpu, cpus)
 			qcom_scm_wb[cpu].entry = entry;
-- 
1.9.1



From andy.gross at linaro.org  Wed May  4 15:50:41 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed,  4 May 2016 17:50:41 -0500
Subject: [Patch v3 4/8] firmware: qcom: scm: Generalize shared error map
In-Reply-To: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
References: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462402245-18295-5-git-send-email-andy.gross@linaro.org>

This patch moves the qcom_scm_remap_error function to the include file
where can be used by both the 32 and 64 bit versions of the code.

Reviewed-by: Stephen Boyd <sboyd at codeaurora.org>
Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>
Signed-off-by: Andy Gross <agross at codeaurora.org>
Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm-32.c | 17 -----------------
 drivers/firmware/qcom_scm.h    | 16 ++++++++++++++++
 2 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 5be6a12..4388d13 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -168,23 +168,6 @@ static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response
 	return (void *)rsp + le32_to_cpu(rsp->buf_offset);
 }
 
-static int qcom_scm_remap_error(int err)
-{
-	pr_err("qcom_scm_call failed with error code %d\n", err);
-	switch (err) {
-	case QCOM_SCM_ERROR:
-		return -EIO;
-	case QCOM_SCM_EINVAL_ADDR:
-	case QCOM_SCM_EINVAL_ARG:
-		return -EINVAL;
-	case QCOM_SCM_EOPNOTSUPP:
-		return -EOPNOTSUPP;
-	case QCOM_SCM_ENOMEM:
-		return -ENOMEM;
-	}
-	return -EINVAL;
-}
-
 static u32 smc(u32 cmd_addr)
 {
 	int context_id;
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index 2cce75c..7dcc733 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -44,4 +44,20 @@ extern int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
 #define QCOM_SCM_ERROR		-1
 #define QCOM_SCM_INTERRUPTED	1
 
+static inline int qcom_scm_remap_error(int err)
+{
+	switch (err) {
+	case QCOM_SCM_ERROR:
+		return -EIO;
+	case QCOM_SCM_EINVAL_ADDR:
+	case QCOM_SCM_EINVAL_ARG:
+		return -EINVAL;
+	case QCOM_SCM_EOPNOTSUPP:
+		return -EOPNOTSUPP;
+	case QCOM_SCM_ENOMEM:
+		return -ENOMEM;
+	}
+	return -EINVAL;
+}
+
 #endif
-- 
1.9.1



From andy.gross at linaro.org  Wed May  4 15:50:42 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed,  4 May 2016 17:50:42 -0500
Subject: [Patch v3 5/8] firmware: qcom: scm: Convert to streaming DMA APIS
In-Reply-To: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
References: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462402245-18295-6-git-send-email-andy.gross@linaro.org>

This patch converts the Qualcomm SCM driver to use the streaming DMA APIs
for communication buffers.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm-32.c | 152 +++++++++++++----------------------------
 drivers/firmware/qcom_scm.c    |   6 +-
 drivers/firmware/qcom_scm.h    |  10 +--
 3 files changed, 58 insertions(+), 110 deletions(-)

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 4388d13..3e71aec 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -23,8 +23,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/qcom_scm.h>
-
-#include <asm/cacheflush.h>
+#include <linux/dma-mapping.h>
 
 #include "qcom_scm.h"
 
@@ -97,44 +96,6 @@ struct qcom_scm_response {
 };
 
 /**
- * alloc_qcom_scm_command() - Allocate an SCM command
- * @cmd_size: size of the command buffer
- * @resp_size: size of the response buffer
- *
- * Allocate an SCM command, including enough room for the command
- * and response headers as well as the command and response buffers.
- *
- * Returns a valid &qcom_scm_command on success or %NULL if the allocation fails.
- */
-static struct qcom_scm_command *alloc_qcom_scm_command(size_t cmd_size, size_t resp_size)
-{
-	struct qcom_scm_command *cmd;
-	size_t len = sizeof(*cmd) + sizeof(struct qcom_scm_response) + cmd_size +
-		resp_size;
-	u32 offset;
-
-	cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
-	if (cmd) {
-		cmd->len = cpu_to_le32(len);
-		offset = offsetof(struct qcom_scm_command, buf);
-		cmd->buf_offset = cpu_to_le32(offset);
-		cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
-	}
-	return cmd;
-}
-
-/**
- * free_qcom_scm_command() - Free an SCM command
- * @cmd: command to free
- *
- * Free an SCM command.
- */
-static inline void free_qcom_scm_command(struct qcom_scm_command *cmd)
-{
-	kfree(cmd);
-}
-
-/**
  * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response
  * @cmd: command
  *
@@ -168,7 +129,7 @@ static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response
 	return (void *)rsp + le32_to_cpu(rsp->buf_offset);
 }
 
-static u32 smc(u32 cmd_addr)
+static u32 smc(dma_addr_t cmd_addr)
 {
 	int context_id;
 	register u32 r0 asm("r0") = 1;
@@ -192,51 +153,15 @@ static u32 smc(u32 cmd_addr)
 	return r0;
 }
 
-static int __qcom_scm_call(const struct qcom_scm_command *cmd)
-{
-	int ret;
-	u32 cmd_addr = virt_to_phys(cmd);
-
-	/*
-	 * Flush the command buffer so that the secure world sees
-	 * the correct data.
-	 */
-	secure_flush_area(cmd, cmd->len);
-
-	ret = smc(cmd_addr);
-	if (ret < 0)
-		ret = qcom_scm_remap_error(ret);
-
-	return ret;
-}
-
-static void qcom_scm_inv_range(unsigned long start, unsigned long end)
-{
-	u32 cacheline_size, ctr;
-
-	asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
-	cacheline_size = 4 << ((ctr >> 16) & 0xf);
-
-	start = round_down(start, cacheline_size);
-	end = round_up(end, cacheline_size);
-	outer_inv_range(start, end);
-	while (start < end) {
-		asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
-		     : "memory");
-		start += cacheline_size;
-	}
-	dsb();
-	isb();
-}
-
 /**
  * qcom_scm_call() - Send an SCM command
- * @svc_id: service identifier
- * @cmd_id: command identifier
- * @cmd_buf: command buffer
- * @cmd_len: length of the command buffer
- * @resp_buf: response buffer
- * @resp_len: length of the response buffer
+ * @dev:	struct device
+ * @svc_id:	service identifier
+ * @cmd_id:	command identifier
+ * @cmd_buf:	command buffer
+ * @cmd_len:	length of the command buffer
+ * @resp_buf:	response buffer
+ * @resp_len:	length of the response buffer
  *
  * Sends a command to the SCM and waits for the command to finish processing.
  *
@@ -247,42 +172,60 @@ static void qcom_scm_inv_range(unsigned long start, unsigned long end)
  * and response buffers is taken care of by qcom_scm_call; however, callers are
  * responsible for any other cached buffers passed over to the secure world.
  */
-static int qcom_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf,
-			size_t cmd_len, void *resp_buf, size_t resp_len)
+static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
+			 const void *cmd_buf, size_t cmd_len, void *resp_buf,
+			 size_t resp_len)
 {
 	int ret;
 	struct qcom_scm_command *cmd;
 	struct qcom_scm_response *rsp;
-	unsigned long start, end;
+	size_t alloc_len = sizeof(*cmd) + sizeof(struct qcom_scm_response) +
+			   cmd_len + resp_len;
+	dma_addr_t cmd_phys;
+	u32 offset;
 
-	cmd = alloc_qcom_scm_command(cmd_len, resp_len);
+	cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
 	if (!cmd)
 		return -ENOMEM;
 
+	cmd->len = cpu_to_le32(alloc_len);
+	offset = offsetof(struct qcom_scm_command, buf);
+	cmd->buf_offset = cpu_to_le32(offset);
+	cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_len);
+
 	cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
 	if (cmd_buf)
 		memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len);
 
+	cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, cmd_phys)) {
+		kfree(cmd);
+		return -ENOMEM;
+	}
+
 	mutex_lock(&qcom_scm_lock);
-	ret = __qcom_scm_call(cmd);
+	ret = smc(cmd_phys);
+	if (ret < 0)
+		ret = qcom_scm_remap_error(ret);
 	mutex_unlock(&qcom_scm_lock);
 	if (ret)
 		goto out;
 
 	rsp = qcom_scm_command_to_response(cmd);
-	start = (unsigned long)rsp;
 
 	do {
-		qcom_scm_inv_range(start, start + sizeof(*rsp));
+		dma_sync_single_for_cpu(dev, cmd_phys + cmd_len + offset,
+					sizeof(*rsp), DMA_FROM_DEVICE);
 	} while (!rsp->is_complete);
 
-	end = (unsigned long)qcom_scm_get_response_buffer(rsp) + resp_len;
-	qcom_scm_inv_range(start, end);
-
-	if (resp_buf)
+	if (resp_buf) {
+		dma_sync_single_for_cpu(dev, cmd_phys + alloc_len - resp_len,
+					resp_len, DMA_FROM_DEVICE);
 		memcpy(resp_buf, qcom_scm_get_response_buffer(rsp), resp_len);
+	}
 out:
-	free_qcom_scm_command(cmd);
+	dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE);
+	kfree(cmd);
 	return ret;
 }
 
@@ -437,7 +380,8 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
  * Set the Linux entry point for the SCM to transfer control to when coming
  * out of a power down. CPU power down may be executed on cpuidle or hotplug.
  */
-int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
+int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
+				  const cpumask_t *cpus)
 {
 	int ret;
 	int flags = 0;
@@ -463,7 +407,7 @@ int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
 
 	cmd.addr = cpu_to_le32(virt_to_phys(entry));
 	cmd.flags = cpu_to_le32(flags);
-	ret = qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
+	ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
 			    &cmd, sizeof(cmd), NULL, 0);
 	if (!ret) {
 		for_each_cpu(cpu, cpus)
@@ -487,25 +431,27 @@ void __qcom_scm_cpu_power_down(u32 flags)
 			flags & QCOM_SCM_FLUSH_FLAG_MASK);
 }
 
-int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
+int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
 {
 	int ret;
 	__le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id);
 	__le32 ret_val = 0;
 
-	ret = qcom_scm_call(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, &svc_cmd,
-			sizeof(svc_cmd), &ret_val, sizeof(ret_val));
+	ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD,
+			    &svc_cmd, sizeof(svc_cmd), &ret_val,
+			    sizeof(ret_val));
 	if (ret)
 		return ret;
 
 	return le32_to_cpu(ret_val);
 }
 
-int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
+int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
+			u32 req_cnt, u32 *resp)
 {
 	if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
 		return -ERANGE;
 
-	return qcom_scm_call(QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
+	return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
 		req, req_cnt * sizeof(*req), resp, sizeof(*resp));
 }
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 63a2bfa..9166cbb 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -89,7 +89,7 @@ EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
  */
 int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
 {
-	return __qcom_scm_set_warm_boot_addr(entry, cpus);
+	return __qcom_scm_set_warm_boot_addr(__scm->dev, entry, cpus);
 }
 EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
 
@@ -119,7 +119,7 @@ bool qcom_scm_hdcp_available(void)
 	if (ret)
 		return ret;
 
-	ret = __qcom_scm_is_call_available(QCOM_SCM_SVC_HDCP,
+	ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP,
 						QCOM_SCM_CMD_HDCP);
 
 	qcom_scm_clk_disable();
@@ -143,7 +143,7 @@ int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
 	if (ret)
 		return ret;
 
-	ret = __qcom_scm_hdcp_req(req, req_cnt, resp);
+	ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp);
 	qcom_scm_clk_disable();
 	return ret;
 }
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index 7dcc733..afe6676 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -19,7 +19,8 @@
 #define QCOM_SCM_FLAG_HLOS		0x01
 #define QCOM_SCM_FLAG_COLDBOOT_MC	0x02
 #define QCOM_SCM_FLAG_WARMBOOT_MC	0x04
-extern int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus);
+extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
+		const cpumask_t *cpus);
 extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);
 
 #define QCOM_SCM_CMD_TERMINATE_PC	0x2
@@ -29,12 +30,13 @@ extern void __qcom_scm_cpu_power_down(u32 flags);
 
 #define QCOM_SCM_SVC_INFO		0x6
 #define QCOM_IS_CALL_AVAIL_CMD		0x1
-extern int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id);
+extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
+		u32 cmd_id);
 
 #define QCOM_SCM_SVC_HDCP		0x11
 #define QCOM_SCM_CMD_HDCP		0x01
-extern int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
-		u32 *resp);
+extern int __qcom_scm_hdcp_req(struct device *dev,
+		struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);
 
 /* common error codes */
 #define QCOM_SCM_ENOMEM		-5
-- 
1.9.1



From andy.gross at linaro.org  Wed May  4 15:50:43 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed,  4 May 2016 17:50:43 -0500
Subject: [Patch v3 6/8] firmware: qcom: scm: Add support for ARM64 SoCs
In-Reply-To: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
References: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462402245-18295-7-git-send-email-andy.gross@linaro.org>

From: Kumar Gala <galak at codeaurora.org>

Add an implementation of the SCM interface that works on ARM64 SoCs.  This
is used by things like determine if we have HDCP support or not on the
system.

Signed-off-by: Kumar Gala <galak at codeaurora.org>
Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm-32.c |   4 +
 drivers/firmware/qcom_scm-64.c | 208 +++++++++++++++++++++++++++++++++++++++--
 drivers/firmware/qcom_scm.c    |   2 +
 drivers/firmware/qcom_scm.h    |   5 +
 4 files changed, 209 insertions(+), 10 deletions(-)

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 3e71aec..5c290e7 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -455,3 +455,7 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
 	return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
 		req, req_cnt * sizeof(*req), resp, sizeof(*resp));
 }
+
+void __qcom_scm_init(void)
+{
+}
diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c
index bb6555f..b57468e 100644
--- a/drivers/firmware/qcom_scm-64.c
+++ b/drivers/firmware/qcom_scm-64.c
@@ -12,12 +12,148 @@
 
 #include <linux/io.h>
 #include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
 #include <linux/qcom_scm.h>
+#include <linux/arm-smccc.h>
+#include <linux/dma-mapping.h>
+
+#include "qcom_scm.h"
+
+#define QCOM_SCM_FNID(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF))
+
+#define MAX_QCOM_SCM_ARGS 10
+#define MAX_QCOM_SCM_RETS 3
+
+#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\
+			   (((a) & 0xff) << 4) | \
+			   (((b) & 0xff) << 6) | \
+			   (((c) & 0xff) << 8) | \
+			   (((d) & 0xff) << 10) | \
+			   (((e) & 0xff) << 12) | \
+			   (((f) & 0xff) << 14) | \
+			   (((g) & 0xff) << 16) | \
+			   (((h) & 0xff) << 18) | \
+			   (((i) & 0xff) << 20) | \
+			   (((j) & 0xff) << 22) | \
+			   (num & 0xffff))
+
+#define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+
+/**
+ * struct qcom_scm_desc
+ * @arginfo:	Metadata describing the arguments in args[]
+ * @args:	The array of arguments for the secure syscall
+ * @res:	The values returned by the secure syscall
+ */
+struct qcom_scm_desc {
+	u32 arginfo;
+	u64 args[MAX_QCOM_SCM_ARGS];
+	struct arm_smccc_res res;
+};
+
+static u64 qcom_smccc_convention = -1;
+static DEFINE_MUTEX(qcom_scm_lock);
+
+#define QCOM_SCM_EBUSY_WAIT_MS 30
+#define QCOM_SCM_EBUSY_MAX_RETRY 20
+
+#define N_EXT_QCOM_SCM_ARGS 7
+#define FIRST_EXT_ARG_IDX 3
+#define N_REGISTER_ARGS (MAX_QCOM_SCM_ARGS - N_EXT_QCOM_SCM_ARGS + 1)
+
+/**
+ * qcom_scm_call() - Invoke a syscall in the secure world
+ * @dev:	device
+ * @svc_id:	service identifier
+ * @cmd_id:	command identifier
+ * @fn_id:	The function ID for this syscall
+ * @desc:	Descriptor structure containing arguments and return values
+ *
+ * Sends a command to the SCM and waits for the command to finish processing.
+ * This should *only* be called in pre-emptible context.
+*/
+static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
+			 struct qcom_scm_desc *desc)
+{
+	int arglen = desc->arginfo & 0xf;
+	int ret, retry_count = 0, i;
+	u32 fn_id = QCOM_SCM_FNID(svc_id, cmd_id);
+	u64 cmd, x5 = desc->args[FIRST_EXT_ARG_IDX];
+	dma_addr_t args_phys = 0;
+	void *args_virt = NULL;
+	size_t alloc_len;
+
+	if (unlikely(arglen > N_REGISTER_ARGS)) {
+		alloc_len = N_EXT_QCOM_SCM_ARGS * sizeof(u64);
+		args_virt = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
+
+		if (!args_virt)
+			return qcom_scm_remap_error(-ENOMEM);
+
+		if (qcom_smccc_convention == ARM_SMCCC_SMC_32) {
+			__le32 *args = args_virt;
+
+			for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
+				args[i] = cpu_to_le32(desc->args[i +
+						      FIRST_EXT_ARG_IDX]);
+		} else {
+			__le64 *args = args_virt;
+
+			for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
+				args[i] = cpu_to_le64(desc->args[i +
+						      FIRST_EXT_ARG_IDX]);
+		}
+
+		args_phys = dma_map_single(dev, args_virt, alloc_len,
+					   DMA_TO_DEVICE);
+
+		if (dma_mapping_error(dev, args_phys)) {
+			kfree(args_virt);
+			return qcom_scm_remap_error(-ENOMEM);
+		}
+
+		x5 = args_phys;
+	}
+
+	do {
+		mutex_lock(&qcom_scm_lock);
+
+		cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL,
+					 qcom_smccc_convention,
+					 ARM_SMCCC_OWNER_SIP, fn_id);
+
+		do {
+			arm_smccc_smc(cmd, arglen, desc->args[0], desc->args[1],
+				      desc->args[2], x5, 0, 0, &desc->res);
+		} while (desc->res.a0 == QCOM_SCM_INTERRUPTED);
+
+		mutex_unlock(&qcom_scm_lock);
+
+		if (desc->res.a0 == QCOM_SCM_V2_EBUSY) {
+			if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY)
+				break;
+			msleep(QCOM_SCM_EBUSY_WAIT_MS);
+		}
+	}  while (desc->res.a0 == QCOM_SCM_V2_EBUSY);
+
+	if (args_virt) {
+		dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE);
+		kfree(args_virt);
+	}
+
+	if (desc->res.a0 < 0)
+		return qcom_scm_remap_error(ret);
+
+	return 0;
+}
 
 /**
  * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
- * @entry: Entry point function for the cpus
- * @cpus: The cpumask of cpus that will use the entry point
+ * @entry:	Entry point function for the cpus
+ * @cpus:	The cpumask of cpus that will use the entry point
  *
  * Set the cold boot address of the cpus. Any cpu outside the supported
  * range would be removed from the cpu present mask.
@@ -29,20 +165,21 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
 
 /**
  * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
- * @entry: Entry point function for the cpus
- * @cpus: The cpumask of cpus that will use the entry point
+ * @entry:	Entry point function for the cpus
+ * @cpus:	The cpumask of cpus that will use the entry point
  *
  * Set the Linux entry point for the SCM to transfer control to when coming
  * out of a power down. CPU power down may be executed on cpuidle or hotplug.
  */
-int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
+int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
+				  const cpumask_t *cpus)
 {
 	return -ENOTSUPP;
 }
 
 /**
  * qcom_scm_cpu_power_down() - Power down the cpu
- * @flags - Flags to flush cache
+ * @flags:	Flags to flush cache
  *
  * This is an end point to power down cpu. If there was a pending interrupt,
  * the control would return from this function, otherwise, the cpu jumps to the
@@ -52,12 +189,63 @@ void __qcom_scm_cpu_power_down(u32 flags)
 {
 }
 
-int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
+int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
 {
-	return -ENOTSUPP;
+	int ret;
+	struct qcom_scm_desc desc = {0};
+
+	desc.arginfo = QCOM_SCM_ARGS(1);
+	desc.args[0] = QCOM_SCM_FNID(svc_id, cmd_id) |
+			(ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT);
+
+	ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD,
+			    &desc);
+
+	return ret ? : desc.res.a1;
 }
 
-int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
+int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
+			u32 req_cnt, u32 *resp)
 {
-	return -ENOTSUPP;
+	int ret;
+	struct qcom_scm_desc desc = {0};
+
+	if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
+		return -ERANGE;
+
+	desc.args[0] = req[0].addr;
+	desc.args[1] = req[0].val;
+	desc.args[2] = req[1].addr;
+	desc.args[3] = req[1].val;
+	desc.args[4] = req[2].addr;
+	desc.args[5] = req[2].val;
+	desc.args[6] = req[3].addr;
+	desc.args[7] = req[3].val;
+	desc.args[8] = req[4].addr;
+	desc.args[9] = req[4].val;
+	desc.arginfo = QCOM_SCM_ARGS(10);
+
+	ret = qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP, &desc);
+	*resp = desc.res.a1;
+
+	return ret;
+}
+
+void __qcom_scm_init(void)
+{
+	u64 cmd;
+	struct arm_smccc_res res;
+	u32 function = QCOM_SCM_FNID(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD);
+
+	/* First try a SMC64 call */
+	cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64,
+				 ARM_SMCCC_OWNER_SIP, function);
+
+	arm_smccc_smc(cmd, QCOM_SCM_ARGS(1), cmd & (~BIT(ARM_SMCCC_TYPE_SHIFT)),
+		      0, 0, 0, 0, 0, &res);
+
+	if (!res.a0 && res.a1)
+		qcom_smccc_convention = ARM_SMCCC_SMC_64;
+	else
+		qcom_smccc_convention = ARM_SMCCC_SMC_32;
 }
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 9166cbb..f68deba 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -189,6 +189,8 @@ static int qcom_scm_probe(struct platform_device *pdev)
 	__scm = scm;
 	__scm->dev = &pdev->dev;
 
+	__qcom_scm_init();
+
 	return 0;
 }
 
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index afe6676..0ea55d7 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -38,7 +38,10 @@ extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
 extern int __qcom_scm_hdcp_req(struct device *dev,
 		struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);
 
+extern void __qcom_scm_init(void);
+
 /* common error codes */
+#define QCOM_SCM_V2_EBUSY	-12
 #define QCOM_SCM_ENOMEM		-5
 #define QCOM_SCM_EOPNOTSUPP	-4
 #define QCOM_SCM_EINVAL_ADDR	-3
@@ -58,6 +61,8 @@ static inline int qcom_scm_remap_error(int err)
 		return -EOPNOTSUPP;
 	case QCOM_SCM_ENOMEM:
 		return -ENOMEM;
+	case QCOM_SCM_V2_EBUSY:
+		return -EBUSY;
 	}
 	return -EINVAL;
 }
-- 
1.9.1



From andy.gross at linaro.org  Wed May  4 15:50:44 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed,  4 May 2016 17:50:44 -0500
Subject: [Patch v3 7/8] dts: qcom: apq8084: Add SCM firmware node
In-Reply-To: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
References: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462402245-18295-8-git-send-email-andy.gross@linaro.org>

This patch adds the firmware node for the SCM

Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>
Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 arch/arm/boot/dts/qcom-apq8084.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-apq8084.dtsi b/arch/arm/boot/dts/qcom-apq8084.dtsi
index a33a09f..7c2df06 100644
--- a/arch/arm/boot/dts/qcom-apq8084.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8084.dtsi
@@ -86,6 +86,14 @@
 		};
 	};
 
+	firmware {
+		scm {
+			compatible = "qcom,scm";
+			clocks = <&gcc GCC_CE1_CLK> , <&gcc GCC_CE1_AXI_CLK>, <&gcc GCC_CE1_AHB_CLK>;
+			clock-names = "core", "bus", "iface";
+		};
+	};
+
 	cpu-pmu {
 		compatible = "qcom,krait-pmu";
 		interrupts = <1 7 0xf04>;
-- 
1.9.1



From andy.gross at linaro.org  Wed May  4 15:50:45 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed,  4 May 2016 17:50:45 -0500
Subject: [Patch v3 8/8] arm64: dts: msm8916: Add SCM firmware node
In-Reply-To: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
References: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462402245-18295-9-git-send-email-andy.gross@linaro.org>

This adds the devicetree node for the SCM firmware.

Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>
Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 arch/arm64/boot/dts/qcom/msm8916.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 9681200..01c7b0c 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -122,6 +122,14 @@
 		hwlocks = <&tcsr_mutex 3>;
 	};
 
+	firmware {
+		scm {
+			compatible = "qcom,scm";
+			clocks = <&gcc GCC_CRYPTO_CLK>, <&gcc GCC_CRYPTO_AXI_CLK>, <&gcc GCC_CRYPTO_AHB_CLK>;
+			clock-names = "core", "bus", "iface";
+		};
+	};
+
 	soc: soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
-- 
1.9.1



From pinskia at gmail.com  Wed May  4 16:23:13 2016
From: pinskia at gmail.com (Andrew Pinski)
Date: Wed, 4 May 2016 16:23:13 -0700
Subject: [PATCH 24/25] arm64:ilp32: add vdso-ilp32 and use for signal
 return
In-Reply-To: <20160504214949.GA28217@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1554541.oDP7Ro5zB2@wuerfel>
 <20160503090045.GB10733@e104818-lin.cambridge.arm.com>
 <3846428.6xx69KGEja@wuerfel> <57288660.9030607@huawei.com>
 <57289C75.50904@huawei.com> <20160504214949.GA28217@yury-N73SV>
Message-ID: <CA+=Sn1ngpaJWHpGDmU+kXBkz56SO+XDW2qzMMLAbbBWnaB0eqw@mail.gmail.com>

On Wed, May 4, 2016 at 2:49 PM, Yury Norov <ynorov at caviumnetworks.com> wrote:
> On Tue, May 03, 2016 at 08:41:25PM +0800, Zhangjian (Bamvor) wrote:
>> Hi, all
>>
>> After apply this patch with my small testcase, the vsyscall of gettimeofday in
>> ilp32 works in both big endian and small endian. In this patch, I use the
>> different register and offset for ilp32 and lp64. Actually, the
>> COMPAT_TVAL_TV_SEC is same as TVAL_TV_SEC(so as to COMPAT_TSPEC_TV_SEC and
>> TSPEC_TV_SEC). I add it to keep the logic clear. I also change the version
>> of vdso to 4.6. It should change to 2.6.39 if glibc is not update.
>>
>
> [...]
>
> Hi Bamvor,
>
> It works for me as well. Thank you.
> I'll incorporate it in next submission.

We should add the following so we are complaint to the ILP32 ABI
dealing with pointers don't have to be zero extended for arguments,
Note ZERO should most likely be ZERO_PTR or something to do that
effect, I am not so good with names.
#ifdef __LP64__
#define ZERO(n)
#else
#define ZERO(n)         mov     w##n, w##n
#endif

...
ENTRY(__kernel_gettimeofday)
        .cfi_startproc
        ZERO(0)
        ZERO(1)
...
ENTRY(__kernel_clock_gettime)
        .cfi_startproc
        ZERO(1)
...
ENTRY(__kernel_clock_getres)
        .cfi_startproc
        ZERO(1)

Thanks,
Andrew Pinski

>
> Yury.


From dianders at chromium.org  Wed May  4 16:36:25 2016
From: dianders at chromium.org (Douglas Anderson)
Date: Wed,  4 May 2016 16:36:25 -0700
Subject: [PATCH] clk: rockchip: fix the rk3399 sdmmc sample / drv name
Message-ID: <1462404985-27957-1-git-send-email-dianders@chromium.org>

The rk3399 clock table had a simple typo in it, calling the SDMMC sample
and drive clocks by the wrong name.  Fix this minor typo.

Signed-off-by: Douglas Anderson <dianders at chromium.org>
---
 drivers/clk/rockchip/clk-rk3399.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
index 5248726af86d..291543f52caa 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -894,8 +894,8 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
 			RK3399_CLKSEL_CON(16), 8, 3, MFLAGS, 0, 7, DFLAGS,
 			RK3399_CLKGATE_CON(6), 1, GFLAGS),
 
-	MMC(SCLK_SDMMC_DRV,     "emmc_drv",    "clk_sdmmc", RK3399_SDMMC_CON0, 1),
-	MMC(SCLK_SDMMC_SAMPLE,  "emmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 1),
+	MMC(SCLK_SDMMC_DRV,     "sdmmc_drv",    "clk_sdmmc", RK3399_SDMMC_CON0, 1),
+	MMC(SCLK_SDMMC_SAMPLE,  "sdmmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 1),
 
 	MMC(SCLK_SDIO_DRV,      "sdio_drv",    "clk_sdio",  RK3399_SDIO_CON0,  1),
 	MMC(SCLK_SDIO_SAMPLE,   "sdio_sample", "clk_sdio",  RK3399_SDIO_CON1,  1),
-- 
2.8.0.rc3.226.g39d4020



From dianders at chromium.org  Wed May  4 16:45:59 2016
From: dianders at chromium.org (Doug Anderson)
Date: Wed, 4 May 2016 16:45:59 -0700
Subject: [PATCH v7 1/9] i2c: rk3x: add documentation to fields in "struct
 rk3x_i2c"
In-Reply-To: <1462371194-5809-2-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462371194-5809-2-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=VyAie7NcO3q4qQWEdHaiUUHbRN-6iWV3y+kvgSYPpkEg@mail.gmail.com>

David,

On Wed, May 4, 2016 at 7:13 AM, David Wu <david.wu at rock-chips.com> wrote:
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> ---
> Change in v7:
> - none
>
>  drivers/i2c/busses/i2c-rk3x.c | 22 +++++++++++++++++++++-
>  1 file changed, 21 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> index 80bed02..7e45d51 100644
> --- a/drivers/i2c/busses/i2c-rk3x.c
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -90,6 +90,26 @@ struct rk3x_i2c_soc_data {
>         int grf_offset;
>  };
>
> +/**
> + * struct rk3x_i2c - private data of the controller
> + * @adap: corresponding I2C adapter
> + * @dev: device for this controller
> + * @soc_data: related soc data struct
> + * @regs: virtual memory area
> + * @clk: clock of i2c bus
> + * @clk_rate_nb: i2c clk rate change notify
> + * @t: I2C known timing information

You're a little ahead of yourself.  The @t element doesn't exist as of
this patch.  Instead all the sub-elements are there.  This in this
patch you need to document scl_frequency, scl_rise_ns, ....  In a
later patch you'd change it to t.


-Doug


From ray.jui at broadcom.com  Wed May  4 16:47:14 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Wed,  4 May 2016 16:47:14 -0700
Subject: [PATCH v2] Workaround for Broadcom NS2 gicv2m implementation
Message-ID: <1462405635-27864-1-git-send-email-ray.jui@broadcom.com>

Alex Barba <alex.barba at broadcom.com> discovered Broadcom NS2 GICv2m
implementation has an erratum where the MSI data needs to be the SPI number
subtracted by an offset of 32, for the correct MSI interrupt to be triggered.

We are now implementating the workaround based on readings from the MSI_IIDR
register.

Patch series is developed based on Linux v4.6-rc1 and available at:
https://github.com/Broadcom/arm64-linux/tree/gicv2m-iproc-v2

Changes from v1:
 - Changed from DT based approach to the approch similar to APM that is based
on readings from the MSI_IIDR register

Ray Jui (1):
  irqchip/gic-v2m: Add workaround for Broadcom NS2 GICv2m erratum

 drivers/irqchip/irq-gic-v2m.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

-- 
2.1.4



From ray.jui at broadcom.com  Wed May  4 16:47:15 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Wed,  4 May 2016 16:47:15 -0700
Subject: [PATCH v2] irqchip/gic-v2m: Add workaround for Broadcom NS2 GICv2m
 erratum
In-Reply-To: <1462405635-27864-1-git-send-email-ray.jui@broadcom.com>
References: <1462405635-27864-1-git-send-email-ray.jui@broadcom.com>
Message-ID: <1462405635-27864-2-git-send-email-ray.jui@broadcom.com>

Alex Barba <alex.barba at broadcom.com> discovered Broadcom NS2 GICv2m
implementation has an erratum where the MSI data needs to be the SPI
number subtracted by an offset of 32, for the correct MSI interrupt
to be triggered.

Here we are adding the workaround based on readings from the MSI_IIDR
register, which contains a value unique to Broadcom NS2 GICv2m

Reported-by: Alex Barba <alex.barba at broadcom.com>
Signed-off-by: Ray Jui <ray.jui at broadcom.com>
---
 drivers/irqchip/irq-gic-v2m.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 28f047c..4c89e27 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -49,6 +49,9 @@
 /* APM X-Gene with GICv2m MSI_IIDR register value */
 #define XGENE_GICV2M_MSI_IIDR		0x06000170
 
+/* Broadcom NS2 GICv2m MSI_IIDR register value */
+#define BCM_NS2_GICV2M_MSI_IIDR		0x0000013f
+
 /* List of flags for specific v2m implementation */
 #define GICV2M_NEEDS_SPI_OFFSET		0x00000001
 
@@ -62,6 +65,7 @@ struct v2m_data {
 	void __iomem *base;	/* GICv2m virt address */
 	u32 spi_start;		/* The SPI number that MSIs start */
 	u32 nr_spis;		/* The number of SPIs for MSIs */
+	u32 spi_offset;		/* offset to be subtracted from SPI number */
 	unsigned long *bm;	/* MSI vector bitmap */
 	u32 flags;		/* v2m flags for specific implementation */
 };
@@ -102,7 +106,7 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 	msg->data = data->hwirq;
 
 	if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET)
-		msg->data -= v2m->spi_start;
+		msg->data -= v2m->spi_offset;
 }
 
 static struct irq_chip gicv2m_irq_chip = {
@@ -340,9 +344,18 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
 	 * different from the standard GICv2m implementation where
 	 * the MSI data is the absolute value within the range from
 	 * spi_start to (spi_start + num_spis).
+	 *
+	 * Broadom NS2 GICv2m implementation has an erratum where the MSI data
+	 * is 'spi_number - 32'
 	 */
-	if (readl_relaxed(v2m->base + V2M_MSI_IIDR) == XGENE_GICV2M_MSI_IIDR)
+	if (readl_relaxed(v2m->base + V2M_MSI_IIDR) == XGENE_GICV2M_MSI_IIDR) {
+		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
+		v2m->spi_offset = v2m->spi_start;
+	} else if (readl_relaxed(v2m->base + V2M_MSI_IIDR) ==
+		   BCM_NS2_GICV2M_MSI_IIDR) {
 		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
+		v2m->spi_offset = 32;
+	}
 
 	v2m->bm = kzalloc(sizeof(long) * BITS_TO_LONGS(v2m->nr_spis),
 			  GFP_KERNEL);
-- 
2.1.4



From dianders at chromium.org  Wed May  4 16:50:25 2016
From: dianders at chromium.org (Doug Anderson)
Date: Wed, 4 May 2016 16:50:25 -0700
Subject: [PATCH v7 1/9] i2c: rk3x: add documentation to fields in "struct
 rk3x_i2c"
In-Reply-To: <CAD=FV=VyAie7NcO3q4qQWEdHaiUUHbRN-6iWV3y+kvgSYPpkEg@mail.gmail.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462371194-5809-2-git-send-email-david.wu@rock-chips.com>
 <CAD=FV=VyAie7NcO3q4qQWEdHaiUUHbRN-6iWV3y+kvgSYPpkEg@mail.gmail.com>
Message-ID: <CAD=FV=VUaq6-_NNy-K2BrTDHY1pzJGA6wGtPTvc8H1ABgDqf0w@mail.gmail.com>

David,

On Wed, May 4, 2016 at 4:45 PM, Doug Anderson <dianders at chromium.org> wrote:
> David,
>
> On Wed, May 4, 2016 at 7:13 AM, David Wu <david.wu at rock-chips.com> wrote:
>> Signed-off-by: David Wu <david.wu at rock-chips.com>
>> ---
>> Change in v7:
>> - none
>>
>>  drivers/i2c/busses/i2c-rk3x.c | 22 +++++++++++++++++++++-
>>  1 file changed, 21 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
>> index 80bed02..7e45d51 100644
>> --- a/drivers/i2c/busses/i2c-rk3x.c
>> +++ b/drivers/i2c/busses/i2c-rk3x.c
>> @@ -90,6 +90,26 @@ struct rk3x_i2c_soc_data {
>>         int grf_offset;
>>  };
>>
>> +/**
>> + * struct rk3x_i2c - private data of the controller
>> + * @adap: corresponding I2C adapter
>> + * @dev: device for this controller
>> + * @soc_data: related soc data struct
>> + * @regs: virtual memory area
>> + * @clk: clock of i2c bus
>> + * @clk_rate_nb: i2c clk rate change notify
>> + * @t: I2C known timing information
>
> You're a little ahead of yourself.  The @t element doesn't exist as of
> this patch.  Instead all the sub-elements are there.  This in this
> patch you need to document scl_frequency, scl_rise_ns, ....  In a
> later patch you'd change it to t.

Or I'm an idiot and applied to the wrong branch.  Your patch is fine.

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


From briannorris at chromium.org  Wed May  4 18:11:12 2016
From: briannorris at chromium.org (Brian Norris)
Date: Wed, 4 May 2016 18:11:12 -0700
Subject: [PATCH] ARM: dts: rockchip: move rk3288 edp phy under the GRF
In-Reply-To: <4275673.EbRsbqkhH8@diego>
References: <1640976.sZtsTTlDpl@diego>
 <4275673.EbRsbqkhH8@diego>
Message-ID: <20160505011112.GA131923@google.com>

On Fri, Apr 22, 2016 at 03:56:27PM +0200, Heiko Stuebner wrote:
> Am Samstag, 16. April 2016, 02:49:14 schrieb Heiko St?bner:
> > The edp-phy control is a part of the General Register Files and
> > with a recent patch in 4.6 the phy driver can now also handle this
> > correctly, so move the dts node under the GRF as well.
> > 
> > Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> 
> the change in the phy-driver has made it into Greg's usb tree as fix for 4.6, 
> so I've picked this patch for 4.7 now.

Not sure if it's intentional, but the phy binding change (which is in
4.6) broke the DP support in 4.6/rk3288.dtsi, and this patch is
necessary to bring it back. Shouldn't this DTS change have gone to 4.7
too? Or (when convincing ourselves we're not breaking the DT ABI here),
could we just claim that eDP wasn't supported in 4.6, and 4.7 will just
be bug-fixing the rk3288 DTS?

Brian


From briannorris at chromium.org  Wed May  4 18:16:21 2016
From: briannorris at chromium.org (Brian Norris)
Date: Wed, 4 May 2016 18:16:21 -0700
Subject: [PATCH] ARM: dts: rockchip: move rk3288 edp phy under the GRF
In-Reply-To: <20160505011112.GA131923@google.com>
References: <1640976.sZtsTTlDpl@diego> <4275673.EbRsbqkhH8@diego>
 <20160505011112.GA131923@google.com>
Message-ID: <20160505011621.GA44327@google.com>

On Wed, May 04, 2016 at 06:11:12PM -0700, Brian Norris wrote:
> On Fri, Apr 22, 2016 at 03:56:27PM +0200, Heiko Stuebner wrote:
> > Am Samstag, 16. April 2016, 02:49:14 schrieb Heiko St?bner:
> > > The edp-phy control is a part of the General Register Files and
> > > with a recent patch in 4.6 the phy driver can now also handle this
> > > correctly, so move the dts node under the GRF as well.
> > > 
> > > Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> > 
> > the change in the phy-driver has made it into Greg's usb tree as fix for 4.6, 
> > so I've picked this patch for 4.7 now.
> 
> Not sure if it's intentional, but the phy binding change (which is in
> 4.6) broke the DP support in 4.6/rk3288.dtsi, and this patch is
> necessary to bring it back. Shouldn't this DTS change have gone to 4.7
> too? Or (when convincing ourselves we're not breaking the DT ABI here),
> could we just claim that eDP wasn't supported in 4.6, and 4.7 will just
> be bug-fixing the rk3288 DTS?

Oops, my bad. The eDP PHY didn't show up at all in the v4.6/rk3288.dtsi.
So no breakage. Sorry for the false alarm.

Brian


From bamvor.zhangjian at huawei.com  Wed May  4 19:24:18 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Thu, 5 May 2016 10:24:18 +0800
Subject: [PATCH 24/25] arm64:ilp32: add vdso-ilp32 and use for signal
 return
In-Reply-To: <CA+=Sn1ngpaJWHpGDmU+kXBkz56SO+XDW2qzMMLAbbBWnaB0eqw@mail.gmail.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1554541.oDP7Ro5zB2@wuerfel>
 <20160503090045.GB10733@e104818-lin.cambridge.arm.com>
 <3846428.6xx69KGEja@wuerfel> <57288660.9030607@huawei.com>
 <57289C75.50904@huawei.com> <20160504214949.GA28217@yury-N73SV>
 <CA+=Sn1ngpaJWHpGDmU+kXBkz56SO+XDW2qzMMLAbbBWnaB0eqw@mail.gmail.com>
Message-ID: <572AAED2.7050604@huawei.com>

Hi,

On 2016/5/5 7:23, Andrew Pinski wrote:
> On Wed, May 4, 2016 at 2:49 PM, Yury Norov <ynorov at caviumnetworks.com> wrote:
>> On Tue, May 03, 2016 at 08:41:25PM +0800, Zhangjian (Bamvor) wrote:
>>> Hi, all
>>>
>>> After apply this patch with my small testcase, the vsyscall of gettimeofday in
>>> ilp32 works in both big endian and small endian. In this patch, I use the
>>> different register and offset for ilp32 and lp64. Actually, the
>>> COMPAT_TVAL_TV_SEC is same as TVAL_TV_SEC(so as to COMPAT_TSPEC_TV_SEC and
>>> TSPEC_TV_SEC). I add it to keep the logic clear. I also change the version
>>> of vdso to 4.6. It should change to 2.6.39 if glibc is not update.
>>>
>>
>> [...]
>>
>> Hi Bamvor,
>>
>> It works for me as well. Thank you.
>> I'll incorporate it in next submission.
>
> We should add the following so we are complaint to the ILP32 ABI
> dealing with pointers don't have to be zero extended for arguments,
> Note ZERO should most likely be ZERO_PTR or something to do that
> effect, I am not so good with names.
> #ifdef __LP64__
> #define ZERO(n)
> #else
> #define ZERO(n)         mov     w##n, w##n
> #endif
>
> ...
> ENTRY(__kernel_gettimeofday)
>          .cfi_startproc
>          ZERO(0)
>          ZERO(1)
> ...
> ENTRY(__kernel_clock_gettime)
>          .cfi_startproc
>          ZERO(1)
> ...
> ENTRY(__kernel_clock_getres)
>          .cfi_startproc
>          ZERO(1)
Thanks. I will test and send a new version.

Thanks.

Bamvor
> Thanks,
> Andrew Pinski
>
>>
>> Yury.



From qiang.zhao at nxp.com  Wed May  4 19:31:27 2016
From: qiang.zhao at nxp.com (Qiang Zhao)
Date: Thu, 5 May 2016 02:31:27 +0000
Subject: [v9, 6/7] MAINTAINERS: add entry for Freescale SoC driver
In-Reply-To: <1462332274-13744-7-git-send-email-yangbo.lu@nxp.com>
References: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
 <1462332274-13744-7-git-send-email-yangbo.lu@nxp.com>
Message-ID: <AM3PR04MB1185B5352C395FE8951CA5A5917C0@AM3PR04MB1185.eurprd04.prod.outlook.com>

On Wed, 2016-05-04 at 11:24 +0800, Yangbo Lu wrote:
> -----Original Message-----
> From: Yangbo Lu [mailto:yangbo.lu at nxp.com]
> Sent: Wednesday, May 04, 2016 11:25 AM
> To: linux-mmc at vger.kernel.org; linuxppc-dev at lists.ozlabs.org;
> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-
> kernel at vger.kernel.org; linux-clk at vger.kernel.org; linux-i2c at vger.kernel.org;
> iommu at lists.linux-foundation.org; netdev at vger.kernel.org
> Cc: ulf.hansson at linaro.org; Scott Wood <oss at buserror.net>; Mark Rutland
> <mark.rutland at arm.com>; Rob Herring <robh+dt at kernel.org>; Russell King
> <linux at arm.linux.org.uk>; Jochen Friedrich <jochen at scram.de>; Joerg Roedel
> <joro at 8bytes.org>; Claudiu Manoil <claudiu.manoil at freescale.com>; Bhupesh
> Sharma <bhupesh.sharma at freescale.com>; Qiang Zhao
> <qiang.zhao at nxp.com>; Kumar Gala <galak at codeaurora.org>; Santosh
> Shilimkar <ssantosh at kernel.org>; Yang-Leo Li <leoyang.li at nxp.com>; Xiaobo
> Xie <xiaobo.xie at nxp.com>; Yangbo Lu <yangbo.lu at nxp.com>
> Subject: [v9, 6/7] MAINTAINERS: add entry for Freescale SoC driver
> 
> Add maintainer entry for Freescale SoC driver including the QE library and the
> GUTS driver now. Also add maintainer for QE library.
> 
> Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
> ---
> Changes for v8:
> 	- Added this patch
> Changes for v9:
> 	- Added linux-arm mail list
> 	- Removed GUTS driver entry
> ---
>  MAINTAINERS | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 42e65d1..ce91db7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4622,9 +4622,18 @@ F:	drivers/net/ethernet/freescale/fec_ptp.c
>  F:	drivers/net/ethernet/freescale/fec.h
>  F:	Documentation/devicetree/bindings/net/fsl-fec.txt
> 
> +FREESCALE SOC DRIVER
> +M:	Scott Wood <oss at buserror.net>
> +L:	linuxppc-dev at lists.ozlabs.org
> +L:	linux-arm-kernel at lists.infradead.org
> +S:	Maintained
> +F:	drivers/soc/fsl/
> +F:	include/linux/fsl/
> +
>  FREESCALE QUICC ENGINE LIBRARY
> +M:	Qiang Zhao <qiang.zhao at nxp.com>
>  L:	linuxppc-dev at lists.ozlabs.org
> -S:	Orphan
> +S:	Maintained
>  F:	drivers/soc/fsl/qe/
>  F:	include/soc/fsl/*qe*.h
>  F:	include/soc/fsl/*ucc*.h
> --
> 2.1.0.27.g96db324

I am ok!

-Zhao Qiang



From garlic.tseng at mediatek.com  Wed May  4 19:45:42 2016
From: garlic.tseng at mediatek.com (Garlic Tseng)
Date: Thu, 5 May 2016 10:45:42 +0800
Subject: [alsa-devel] [PATCH 1/7] ASoC: mediatek: Refine mt8173 driver
 and change config option
In-Reply-To: <20160504164306.GA6292@sirena.org.uk>
References: <1461934848-60011-1-git-send-email-garlic.tseng@mediatek.com>
 <1461934848-60011-2-git-send-email-garlic.tseng@mediatek.com>
 <20160504164306.GA6292@sirena.org.uk>
Message-ID: <1462416342.25179.36.camel@mtksdaap41>

On Wed, 2016-05-04 at 17:43 +0100, Mark Brown wrote:
> On Fri, Apr 29, 2016 at 09:00:42PM +0800, Garlic Tseng wrote:
> 
> >  .../{mtk-afe-pcm.c => mt8173/mt8173-afe-pcm.c}     | 488 ++++++++++-----------
> 
> So there's going to be no code sharing at all between this and any other
> Mediatek chips?  That seems very surprising, it'd suggest that the
> hardware designers were creating a new design completely from scratch
> each time which doesn't seem all that likely.  This is an unusual way of
> organizing things and we need a much clearer explanation of what's going
> on here.

MT8173 and MT2701 are from different product lines so the register
control sequences are very different. If another driver for 8173-like
(or 2701-like) chip go upstream it shall share some common code with the
relatively driver indeed. However I think MT8173 and MT2701 can't share
the platform driver or a lot of "if MT8173 else MT2701" will mess up the
code.


However, several (maybe 2 or 3) tiny functions for the two driver code
are very similar indeed. For example, pointer callback functions of
platform driver are very similar. It reads the cursor and return. But
I'm not sure if it is better to share the function. It is too trivial
for me.



From yangbo.lu at nxp.com  Wed May  4 20:21:04 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Thu, 5 May 2016 03:21:04 +0000
Subject: [v9, 6/7] MAINTAINERS: add entry for Freescale SoC driver
In-Reply-To: <1462383308.16584.43.camel@buserror.net>
References: <1462332274-13744-1-git-send-email-yangbo.lu@nxp.com>
 <1462332274-13744-7-git-send-email-yangbo.lu@nxp.com>
 <1462383308.16584.43.camel@buserror.net>
Message-ID: <HE1PR04MB0889AA66ABC718111D7EF41FF87C0@HE1PR04MB0889.eurprd04.prod.outlook.com>

Thanks a lot, Scott and Qiang.
Will change 'DRIVER' to 'DRIVERS' and update the patchset with your acts.


Best regards,
Yangbo Lu

> -----Original Message-----
> From: linux-mmc-owner at vger.kernel.org [mailto:linux-mmc-
> owner at vger.kernel.org] On Behalf Of Scott Wood
> Sent: Thursday, May 05, 2016 1:35 AM
> To: Yangbo Lu; linux-mmc at vger.kernel.org; linuxppc-dev at lists.ozlabs.org;
> devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-
> kernel at vger.kernel.org; linux-clk at vger.kernel.org; linux-
> i2c at vger.kernel.org; iommu at lists.linux-foundation.org;
> netdev at vger.kernel.org
> Cc: ulf.hansson at linaro.org; Mark Rutland; Rob Herring; Russell King;
> Jochen Friedrich; Joerg Roedel; Claudiu Manoil; Bhupesh Sharma; Qiang
> Zhao; Kumar Gala; Santosh Shilimkar; Yang-Leo Li; Xiaobo Xie
> Subject: Re: [v9, 6/7] MAINTAINERS: add entry for Freescale SoC driver
> 
> On Wed, 2016-05-04 at 11:24 +0800, Yangbo Lu wrote:
> > Add maintainer entry for Freescale SoC driver including the QE library
> > and the GUTS driver now. Also add maintainer for QE library.
> >
> > Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
> > ---
> > Changes for v8:
> > 	- Added this patch
> > Changes for v9:
> > 	- Added linux-arm mail list
> > 	- Removed GUTS driver entry
> > ---
> >  MAINTAINERS | 11 ++++++++++-
> >  1 file changed, 10 insertions(+), 1 deletion(-)
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS index 42e65d1..ce91db7 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -4622,9 +4622,18 @@ F:	drivers/net/ethernet/freescale/fec_ptp.c
> >  F:	drivers/net/ethernet/freescale/fec.h
> >  F:	Documentation/devicetree/bindings/net/fsl-fec.txt
> >
> > +FREESCALE SOC DRIVER
> > +M:	Scott Wood <oss at buserror.net>
> > +L:	linuxppc-dev at lists.ozlabs.org
> > +L:	linux-arm-kernel at lists.infradead.org
> > +S:	Maintained
> > +F:	drivers/soc/fsl/
> > +F:	include/linux/fsl/
> > +
> >  FREESCALE QUICC ENGINE LIBRARY
> > +M:	Qiang Zhao <qiang.zhao at nxp.com>
> >  L:	linuxppc-dev at lists.ozlabs.org
> > -S:	Orphan
> > +S:	Maintained
> >  F:	drivers/soc/fsl/qe/
> >  F:	include/soc/fsl/*qe*.h
> >  F:	include/soc/fsl/*ucc*.h
> 
> s/DRIVER/DRIVERS/
> 
> There's more than one.
> 
> Otherwise:
> Acked-by: Scott Wood <oss at buserror.net>
> 
> -Scott
> 
> >
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html

From yangbo.lu at nxp.com  Wed May  4 20:12:23 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Thu, 5 May 2016 11:12:23 +0800
Subject: [v10, 0/7] Fix eSDHC host version register bug
Message-ID: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>

This patchset is used to fix a host version register bug in the T4240-R1.0-R2.0
eSDHC controller. To get the SoC version and revision, it's needed to add the
GUTS driver to access the global utilities registers.

So, the first four patches are to add the GUTS driver.
The following patches except the updating MAINTAINERS patch are to enable
GUTS driver support to get SVR in eSDHC driver and fix host version for T4240.

Yangbo Lu (7):
  Documentation: DT: update Freescale DCFG compatible
  ARM64: dts: ls2080a: add device configuration node
  soc: fsl: add GUTS driver for QorIQ platforms
  dt: move guts devicetree doc out of powerpc directory
  powerpc/fsl: move mpc85xx.h to include/linux/fsl
  MAINTAINERS: add entry for Freescale SoC drivers
  mmc: sdhci-of-esdhc: fix host version for T4240-R1.0-R2.0

 Documentation/devicetree/bindings/arm/fsl.txt      |   6 +-
 .../bindings/{powerpc => soc}/fsl/guts.txt         |   3 +
 MAINTAINERS                                        |  11 +-
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi     |   6 +
 arch/powerpc/kernel/cpu_setup_fsl_booke.S          |   2 +-
 drivers/clk/clk-qoriq.c                            |   3 +-
 drivers/i2c/busses/i2c-mpc.c                       |   2 +-
 drivers/iommu/fsl_pamu.c                           |   3 +-
 drivers/mmc/host/Kconfig                           |   1 +
 drivers/mmc/host/sdhci-of-esdhc.c                  |  23 ++++
 drivers/net/ethernet/freescale/gianfar.c           |   2 +-
 drivers/soc/Kconfig                                |   2 +-
 drivers/soc/fsl/Kconfig                            |   8 ++
 drivers/soc/fsl/Makefile                           |   1 +
 drivers/soc/fsl/guts.c                             | 119 +++++++++++++++++++
 include/linux/fsl/guts.h                           | 126 +++++++++++++--------
 .../asm/mpc85xx.h => include/linux/fsl/svr.h       |   4 +-
 17 files changed, 262 insertions(+), 60 deletions(-)
 rename Documentation/devicetree/bindings/{powerpc => soc}/fsl/guts.txt (91%)
 create mode 100644 drivers/soc/fsl/Kconfig
 create mode 100644 drivers/soc/fsl/guts.c
 rename arch/powerpc/include/asm/mpc85xx.h => include/linux/fsl/svr.h (97%)

-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Wed May  4 20:12:24 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Thu, 5 May 2016 11:12:24 +0800
Subject: [v10, 1/7] Documentation: DT: update Freescale DCFG compatible
In-Reply-To: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462417950-46796-2-git-send-email-yangbo.lu@nxp.com>

Update Freescale DCFG compatible with 'fsl,<chip>-dcfg' instead
of 'fsl,ls1021a-dcfg' to include more chips such as ls1021a,
ls1043a, and ls2080a.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
---
Changes for v8:
	- Added this patch
Changes for v9:
	- Added a list for the possible compatibles
Changes for v10:
	- None
---
 Documentation/devicetree/bindings/arm/fsl.txt | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
index 752a685..465cba1 100644
--- a/Documentation/devicetree/bindings/arm/fsl.txt
+++ b/Documentation/devicetree/bindings/arm/fsl.txt
@@ -119,7 +119,11 @@ Freescale DCFG
 configuration and status for the device. Such as setting the secondary
 core start address and release the secondary core from holdoff and startup.
   Required properties:
-  - compatible: should be "fsl,ls1021a-dcfg"
+  - compatible: should be "fsl,<chip>-dcfg"
+    Possible compatibles:
+	"fsl,ls1021a-dcfg"
+	"fsl,ls1043a-dcfg"
+	"fsl,ls2080a-dcfg"
   - reg : should contain base address and length of DCFG memory-mapped registers
 
 Example:
-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Wed May  4 20:12:25 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Thu, 5 May 2016 11:12:25 +0800
Subject: [v10, 2/7] ARM64: dts: ls2080a: add device configuration node
In-Reply-To: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462417950-46796-3-git-send-email-yangbo.lu@nxp.com>

Add the dts node for device configuration unit that provides
general purpose configuration and status for the device.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
Acked-by: Scott Wood <oss at buserror.net>
---
Changes for v5:
	- Added this patch
Changes for v6:
	- None
Changes for v7:
	- None
Changes for v8:
	- Added 'Acked-by: Scott Wood'
Changes for v9:
	- None
Changes for v10:
	- None
---
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index 9d746c6..8724cf1 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -191,6 +191,12 @@
 			clocks = <&sysclk>;
 		};
 
+		dcfg: dcfg at 1e00000 {
+			compatible = "fsl,ls2080a-dcfg", "syscon";
+			reg = <0x0 0x1e00000 0x0 0x10000>;
+			little-endian;
+		};
+
 		serial0: serial at 21c0500 {
 			compatible = "fsl,ns16550", "ns16550a";
 			reg = <0x0 0x21c0500 0x0 0x100>;
-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Wed May  4 20:12:27 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Thu, 5 May 2016 11:12:27 +0800
Subject: [v10, 4/7] dt: move guts devicetree doc out of powerpc directory
In-Reply-To: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462417950-46796-5-git-send-email-yangbo.lu@nxp.com>

Move guts devicetree doc to Documentation/devicetree/bindings/soc/fsl/
since it's used by not only PowerPC but also ARM. And add a specification
for 'little-endian' property.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
Acked-by: Scott Wood <oss at buserror.net>
Acked-by: Rob Herring <robh at kernel.org>
---
Changes for v4:
	- Added this patch
Changes for v5:
	- Modified the description for little-endian property
Changes for v6:
	- None
Changes for v7:
	- None
Changes for v8:
	- Added 'Acked-by: Scott Wood'
	- Added 'Acked-by: Rob Herring'
Changes for v9:
	- None
Changes for v10:
	- None
---
 Documentation/devicetree/bindings/{powerpc => soc}/fsl/guts.txt | 3 +++
 1 file changed, 3 insertions(+)
 rename Documentation/devicetree/bindings/{powerpc => soc}/fsl/guts.txt (91%)

diff --git a/Documentation/devicetree/bindings/powerpc/fsl/guts.txt b/Documentation/devicetree/bindings/soc/fsl/guts.txt
similarity index 91%
rename from Documentation/devicetree/bindings/powerpc/fsl/guts.txt
rename to Documentation/devicetree/bindings/soc/fsl/guts.txt
index b71b203..07adca9 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/guts.txt
+++ b/Documentation/devicetree/bindings/soc/fsl/guts.txt
@@ -25,6 +25,9 @@ Recommended properties:
  - fsl,liodn-bits : Indicates the number of defined bits in the LIODN
    registers, for those SOCs that have a PAMU device.
 
+ - little-endian : Indicates that the global utilities block is little
+   endian. The default is big endian.
+
 Examples:
 	global-utilities at e0000 {	/* global utilities block */
 		compatible = "fsl,mpc8548-guts";
-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Wed May  4 20:12:26 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Thu, 5 May 2016 11:12:26 +0800
Subject: [v10, 3/7] soc: fsl: add GUTS driver for QorIQ platforms
In-Reply-To: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462417950-46796-4-git-send-email-yangbo.lu@nxp.com>

The global utilities block controls power management, I/O device
enabling, power-onreset(POR) configuration monitoring, alternate
function selection for multiplexed signals,and clock control.

This patch adds GUTS driver to manage and access global utilities
block.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
Acked-by: Scott Wood <oss at buserror.net>
---
Changes for v4:
	- Added this patch
Changes for v5:
	- Modified copyright info
	- Changed MODULE_LICENSE to GPL
	- Changed EXPORT_SYMBOL_GPL to EXPORT_SYMBOL
	- Made FSL_GUTS user-invisible
	- Added a complete compatible list for GUTS
	- Stored guts info in file-scope variable
	- Added mfspr() getting SVR
	- Redefined GUTS APIs
	- Called fsl_guts_init rather than using platform driver
	- Removed useless parentheses
	- Removed useless 'extern' key words
Changes for v6:
	- Made guts thread safe in fsl_guts_init
Changes for v7:
	- Removed 'ifdef' for function declaration in guts.h
Changes for v8:
	- Fixes lines longer than 80 characters checkpatch issue
	- Added 'Acked-by: Scott Wood'
Changes for v9:
	- None
Changes for v10:
	- None
---
 drivers/soc/Kconfig      |   2 +-
 drivers/soc/fsl/Kconfig  |   8 +++
 drivers/soc/fsl/Makefile |   1 +
 drivers/soc/fsl/guts.c   | 119 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fsl/guts.h | 126 +++++++++++++++++++++++++++++------------------
 5 files changed, 207 insertions(+), 49 deletions(-)
 create mode 100644 drivers/soc/fsl/Kconfig
 create mode 100644 drivers/soc/fsl/guts.c

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cb58ef0..7106463 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -2,7 +2,7 @@ menu "SOC (System On Chip) specific Drivers"
 
 source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/brcmstb/Kconfig"
-source "drivers/soc/fsl/qe/Kconfig"
+source "drivers/soc/fsl/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/rockchip/Kconfig"
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
new file mode 100644
index 0000000..b313759
--- /dev/null
+++ b/drivers/soc/fsl/Kconfig
@@ -0,0 +1,8 @@
+#
+# Freescale SOC drivers
+#
+
+source "drivers/soc/fsl/qe/Kconfig"
+
+config FSL_GUTS
+	bool
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index 203307f..02afb7f 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_QUICC_ENGINE)		+= qe/
 obj-$(CONFIG_CPM)			+= qe/
+obj-$(CONFIG_FSL_GUTS)			+= guts.o
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
new file mode 100644
index 0000000..fa155e6
--- /dev/null
+++ b/drivers/soc/fsl/guts.c
@@ -0,0 +1,119 @@
+/*
+ * Freescale QorIQ Platforms GUTS Driver
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/fsl/guts.h>
+
+struct guts {
+	struct ccsr_guts __iomem *regs;
+	bool little_endian;
+};
+
+static struct guts *guts;
+static DEFINE_MUTEX(guts_lock);
+
+u32 fsl_guts_get_svr(void)
+{
+	u32 svr = 0;
+
+	if (!guts || !guts->regs) {
+#ifdef CONFIG_PPC
+		svr =  mfspr(SPRN_SVR);
+#endif
+		return svr;
+	}
+
+	if (guts->little_endian)
+		svr = ioread32(&guts->regs->svr);
+	else
+		svr = ioread32be(&guts->regs->svr);
+
+	return svr;
+}
+EXPORT_SYMBOL(fsl_guts_get_svr);
+
+/*
+ * Table for matching compatible strings, for device tree
+ * guts node, for Freescale QorIQ SOCs.
+ */
+static const struct of_device_id guts_of_match[] = {
+	/* For T4 & B4 Series SOCs */
+	{ .compatible = "fsl,qoriq-device-config-1.0", },
+	/* For P Series SOCs */
+	{ .compatible = "fsl,qoriq-device-config-2.0", },
+	{ .compatible = "fsl,p1010-guts", },
+	{ .compatible = "fsl,p1020-guts", },
+	{ .compatible = "fsl,p1021-guts", },
+	{ .compatible = "fsl,p1022-guts", },
+	{ .compatible = "fsl,p1023-guts", },
+	{ .compatible = "fsl,p2020-guts", },
+	/* For BSC Series SOCs */
+	{ .compatible = "fsl,bsc9131-guts", },
+	{ .compatible = "fsl,bsc9132-guts", },
+	/* For MPC85xx Series SOCs */
+	{ .compatible = "fsl,mpc8536-guts", },
+	{ .compatible = "fsl,mpc8544-guts", },
+	{ .compatible = "fsl,mpc8548-guts", },
+	{ .compatible = "fsl,mpc8568-guts", },
+	{ .compatible = "fsl,mpc8569-guts", },
+	{ .compatible = "fsl,mpc8572-guts", },
+	/* For Layerscape Series SOCs */
+	{ .compatible = "fsl,ls1021a-dcfg", },
+	{ .compatible = "fsl,ls1043a-dcfg", },
+	{ .compatible = "fsl,ls2080a-dcfg", },
+	{}
+};
+
+int fsl_guts_init(void)
+{
+	struct device_node *np;
+	int ret;
+
+	mutex_lock(&guts_lock);
+	/* Initialize guts only once */
+	if (guts) {
+		ret = guts->regs ? 0 : -ENOMEM;
+		goto out;
+	}
+
+	np = of_find_matching_node(NULL, guts_of_match);
+	if (!np) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	guts = kzalloc(sizeof(*guts), GFP_KERNEL);
+	if (!guts) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	guts->little_endian = of_property_read_bool(np, "little-endian");
+
+	guts->regs = of_iomap(np, 0);
+	if (!guts->regs) {
+		ret = -ENOMEM;
+		kfree(guts);
+		goto out;
+	}
+
+	of_node_put(np);
+	ret = 0;
+out:
+	mutex_unlock(&guts_lock);
+	return ret;
+}
+EXPORT_SYMBOL(fsl_guts_init);
diff --git a/include/linux/fsl/guts.h b/include/linux/fsl/guts.h
index 649e917..7e1e22b 100644
--- a/include/linux/fsl/guts.h
+++ b/include/linux/fsl/guts.h
@@ -29,83 +29,113 @@
  * #ifdefs.
  */
 struct ccsr_guts {
-	__be32	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */
-	__be32	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */
-	__be32	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and Control Register */
-	__be32	pordevsr;	/* 0x.000c - POR I/O Device Status Register */
-	__be32	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */
-	__be32	pordevsr2;	/* 0x.0014 - POR device status register 2 */
+	u32	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */
+	u32	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */
+	u32	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and
+				 *           Control Register
+				 */
+	u32	pordevsr;	/* 0x.000c - POR I/O Device Status Register */
+	u32	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */
+	u32	pordevsr2;	/* 0x.0014 - POR device status register 2 */
 	u8	res018[0x20 - 0x18];
-	__be32	porcir;		/* 0x.0020 - POR Configuration Information Register */
+	u32	porcir;		/* 0x.0020 - POR Configuration Information
+				 *           Register
+				 */
 	u8	res024[0x30 - 0x24];
-	__be32	gpiocr;		/* 0x.0030 - GPIO Control Register */
+	u32	gpiocr;		/* 0x.0030 - GPIO Control Register */
 	u8	res034[0x40 - 0x34];
-	__be32	gpoutdr;	/* 0x.0040 - General-Purpose Output Data Register */
+	u32	gpoutdr;	/* 0x.0040 - General-Purpose Output Data
+				 *           Register
+				 */
 	u8	res044[0x50 - 0x44];
-	__be32	gpindr;		/* 0x.0050 - General-Purpose Input Data Register */
+	u32	gpindr;		/* 0x.0050 - General-Purpose Input Data
+				 *           Register
+				 */
 	u8	res054[0x60 - 0x54];
-	__be32	pmuxcr;		/* 0x.0060 - Alternate Function Signal Multiplex Control */
-        __be32  pmuxcr2;	/* 0x.0064 - Alternate function signal multiplex control 2 */
-        __be32  dmuxcr;		/* 0x.0068 - DMA Mux Control Register */
+	u32	pmuxcr;		/* 0x.0060 - Alternate Function Signal
+				 *           Multiplex Control
+				 */
+	u32	pmuxcr2;	/* 0x.0064 - Alternate function signal
+				 *           multiplex control 2
+				 */
+	u32	dmuxcr;		/* 0x.0068 - DMA Mux Control Register */
         u8	res06c[0x70 - 0x6c];
-	__be32	devdisr;	/* 0x.0070 - Device Disable Control */
+	u32	devdisr;	/* 0x.0070 - Device Disable Control */
 #define CCSR_GUTS_DEVDISR_TB1	0x00001000
 #define CCSR_GUTS_DEVDISR_TB0	0x00004000
-	__be32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */
+	u32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */
 	u8	res078[0x7c - 0x78];
-	__be32  pmjcr;		/* 0x.007c - 4 Power Management Jog Control Register */
-	__be32	powmgtcsr;	/* 0x.0080 - Power Management Status and Control Register */
-	__be32  pmrccr;		/* 0x.0084 - Power Management Reset Counter Configuration Register */
-	__be32  pmpdccr;	/* 0x.0088 - Power Management Power Down Counter Configuration Register */
-	__be32  pmcdr;		/* 0x.008c - 4Power management clock disable register */
-	__be32	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
-	__be32	rstrscr;	/* 0x.0094 - Reset Request Status and Control Register */
-	__be32  ectrstcr;	/* 0x.0098 - Exception reset control register */
-	__be32  autorstsr;	/* 0x.009c - Automatic reset status register */
-	__be32	pvr;		/* 0x.00a0 - Processor Version Register */
-	__be32	svr;		/* 0x.00a4 - System Version Register */
+	u32	pmjcr;		/* 0x.007c - 4 Power Management Jog Control
+				 *           Register
+				 */
+	u32	powmgtcsr;	/* 0x.0080 - Power Management Status and
+				 *           Control Register
+				 */
+	u32	pmrccr;		/* 0x.0084 - Power Management Reset Counter
+				 *           Configuration Register
+				 */
+	u32	pmpdccr;	/* 0x.0088 - Power Management Power Down Counter
+				 *           Configuration Register
+				 */
+	u32	pmcdr;		/* 0x.008c - 4Power management clock disable
+				 *           register
+				 */
+	u32	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
+	u32	rstrscr;	/* 0x.0094 - Reset Request Status and
+				 *           Control Register
+				 */
+	u32	ectrstcr;	/* 0x.0098 - Exception reset control register */
+	u32	autorstsr;	/* 0x.009c - Automatic reset status register */
+	u32	pvr;		/* 0x.00a0 - Processor Version Register */
+	u32	svr;		/* 0x.00a4 - System Version Register */
 	u8	res0a8[0xb0 - 0xa8];
-	__be32	rstcr;		/* 0x.00b0 - Reset Control Register */
+	u32	rstcr;		/* 0x.00b0 - Reset Control Register */
 	u8	res0b4[0xc0 - 0xb4];
-	__be32  iovselsr;	/* 0x.00c0 - I/O voltage select status register
+	u32	iovselsr;	/* 0x.00c0 - I/O voltage select status register
 					     Called 'elbcvselcr' on 86xx SOCs */
 	u8	res0c4[0x100 - 0xc4];
-	__be32	rcwsr[16];	/* 0x.0100 - Reset Control Word Status registers
+	u32	rcwsr[16];	/* 0x.0100 - Reset Control Word Status registers
 					     There are 16 registers */
 	u8	res140[0x224 - 0x140];
-	__be32  iodelay1;	/* 0x.0224 - IO delay control register 1 */
-	__be32  iodelay2;	/* 0x.0228 - IO delay control register 2 */
+	u32	iodelay1;	/* 0x.0224 - IO delay control register 1 */
+	u32	iodelay2;	/* 0x.0228 - IO delay control register 2 */
 	u8	res22c[0x604 - 0x22c];
-	__be32	pamubypenr; 	/* 0x.604 - PAMU bypass enable register */
+	u32	pamubypenr;	/* 0x.604 - PAMU bypass enable register */
 	u8	res608[0x800 - 0x608];
-	__be32	clkdvdr;	/* 0x.0800 - Clock Divide Register */
+	u32	clkdvdr;	/* 0x.0800 - Clock Divide Register */
 	u8	res804[0x900 - 0x804];
-	__be32	ircr;		/* 0x.0900 - Infrared Control Register */
+	u32	ircr;		/* 0x.0900 - Infrared Control Register */
 	u8	res904[0x908 - 0x904];
-	__be32	dmacr;		/* 0x.0908 - DMA Control Register */
+	u32	dmacr;		/* 0x.0908 - DMA Control Register */
 	u8	res90c[0x914 - 0x90c];
-	__be32	elbccr;		/* 0x.0914 - eLBC Control Register */
+	u32	elbccr;		/* 0x.0914 - eLBC Control Register */
 	u8	res918[0xb20 - 0x918];
-	__be32	ddr1clkdr;	/* 0x.0b20 - DDR1 Clock Disable Register */
-	__be32	ddr2clkdr;	/* 0x.0b24 - DDR2 Clock Disable Register */
-	__be32	ddrclkdr;	/* 0x.0b28 - DDR Clock Disable Register */
+	u32	ddr1clkdr;	/* 0x.0b20 - DDR1 Clock Disable Register */
+	u32	ddr2clkdr;	/* 0x.0b24 - DDR2 Clock Disable Register */
+	u32	ddrclkdr;	/* 0x.0b28 - DDR Clock Disable Register */
 	u8	resb2c[0xe00 - 0xb2c];
-	__be32	clkocr;		/* 0x.0e00 - Clock Out Select Register */
+	u32	clkocr;		/* 0x.0e00 - Clock Out Select Register */
 	u8	rese04[0xe10 - 0xe04];
-	__be32	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
+	u32	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
 	u8	rese14[0xe20 - 0xe14];
-	__be32	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
-	__be32  cpfor;		/* 0x.0e24 - L2 charge pump fuse override register */
+	u32	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
+	u32	cpfor;		/* 0x.0e24 - L2 charge pump fuse override
+				 *           register
+				 */
 	u8	rese28[0xf04 - 0xe28];
-	__be32	srds1cr0;	/* 0x.0f04 - SerDes1 Control Register 0 */
-	__be32	srds1cr1;	/* 0x.0f08 - SerDes1 Control Register 0 */
+	u32	srds1cr0;	/* 0x.0f04 - SerDes1 Control Register 0 */
+	u32	srds1cr1;	/* 0x.0f08 - SerDes1 Control Register 0 */
 	u8	resf0c[0xf2c - 0xf0c];
-	__be32  itcr;		/* 0x.0f2c - Internal transaction control register */
+	u32	itcr;		/* 0x.0f2c - Internal transaction control
+				 *           register
+				 */
 	u8	resf30[0xf40 - 0xf30];
-	__be32	srds2cr0;	/* 0x.0f40 - SerDes2 Control Register 0 */
-	__be32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */
+	u32	srds2cr0;	/* 0x.0f40 - SerDes2 Control Register 0 */
+	u32	srds2cr1;	/* 0x.0f44 - SerDes2 Control Register 0 */
 } __attribute__ ((packed));
 
+u32 fsl_guts_get_svr(void);
+int fsl_guts_init(void);
 
 /* Alternate function signal multiplex control */
 #define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x))
-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Wed May  4 20:12:28 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Thu, 5 May 2016 11:12:28 +0800
Subject: [v10, 5/7] powerpc/fsl: move mpc85xx.h to include/linux/fsl
In-Reply-To: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462417950-46796-6-git-send-email-yangbo.lu@nxp.com>

Move mpc85xx.h to include/linux/fsl and rename it to svr.h as
a common header file. It has been used for mpc85xx and it will
be used for ARM-based SoC as well.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
Acked-by: Wolfram Sang <wsa at the-dreams.de>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Acked-by: Scott Wood <oss at buserror.net>
Acked-by: Joerg Roedel <jroedel at suse.de>
---
Changes for v2:
	- None
Changes for v3:
	- None
Changes for v4:
	- None
Changes for v5:
	- Changed to Move mpc85xx.h to include/linux/fsl/
	- Adjusted '#include <linux/fsl/svr.h>' position in file
Changes for v6:
	- None
Changes for v7:
	- Added 'Acked-by: Wolfram Sang' for I2C part
	- Also applied to arch/powerpc/kernel/cpu_setup_fsl_booke.S
Changes for v8:
	- Added 'Acked-by: Stephen Boyd' for clk part
	- Added 'Acked-by: Scott Wood'
	- Added 'Acked-by: Joerg Roedel' for iommu part
Changes for v9:
	- None
Changes for v10:
	- None
---
 arch/powerpc/kernel/cpu_setup_fsl_booke.S                     | 2 +-
 drivers/clk/clk-qoriq.c                                       | 3 +--
 drivers/i2c/busses/i2c-mpc.c                                  | 2 +-
 drivers/iommu/fsl_pamu.c                                      | 3 +--
 drivers/net/ethernet/freescale/gianfar.c                      | 2 +-
 arch/powerpc/include/asm/mpc85xx.h => include/linux/fsl/svr.h | 4 ++--
 6 files changed, 7 insertions(+), 9 deletions(-)
 rename arch/powerpc/include/asm/mpc85xx.h => include/linux/fsl/svr.h (97%)

diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
index 462aed9..2b0284e 100644
--- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
@@ -13,13 +13,13 @@
  *
  */
 
+#include <linux/fsl/svr.h>
 #include <asm/page.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/ppc_asm.h>
 #include <asm/mmu-book3e.h>
 #include <asm/asm-offsets.h>
-#include <asm/mpc85xx.h>
 
 _GLOBAL(__e500_icache_setup)
 	mfspr	r0, SPRN_L1CSR1
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 7bc1c45..fc7f722 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -13,6 +13,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/fsl/guts.h>
+#include <linux/fsl/svr.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -1148,8 +1149,6 @@ bad_args:
 }
 
 #ifdef CONFIG_PPC
-#include <asm/mpc85xx.h>
-
 static const u32 a4510_svrs[] __initconst = {
 	(SVR_P2040 << 8) | 0x10,	/* P2040 1.0 */
 	(SVR_P2040 << 8) | 0x11,	/* P2040 1.1 */
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 48ecffe..600704c 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -27,9 +27,9 @@
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/fsl/svr.h>
 
 #include <asm/mpc52xx.h>
-#include <asm/mpc85xx.h>
 #include <sysdev/fsl_soc.h>
 
 #define DRV_NAME "mpc-i2c"
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index a34355f..af8fb27 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -21,11 +21,10 @@
 #include "fsl_pamu.h"
 
 #include <linux/fsl/guts.h>
+#include <linux/fsl/svr.h>
 #include <linux/interrupt.h>
 #include <linux/genalloc.h>
 
-#include <asm/mpc85xx.h>
-
 /* define indexes for each operation mapping scenario */
 #define OMI_QMAN        0x00
 #define OMI_FMAN        0x01
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index d2f917a..2224b10 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -86,11 +86,11 @@
 #include <linux/udp.h>
 #include <linux/in.h>
 #include <linux/net_tstamp.h>
+#include <linux/fsl/svr.h>
 
 #include <asm/io.h>
 #ifdef CONFIG_PPC
 #include <asm/reg.h>
-#include <asm/mpc85xx.h>
 #endif
 #include <asm/irq.h>
 #include <asm/uaccess.h>
diff --git a/arch/powerpc/include/asm/mpc85xx.h b/include/linux/fsl/svr.h
similarity index 97%
rename from arch/powerpc/include/asm/mpc85xx.h
rename to include/linux/fsl/svr.h
index 213f3a8..8d13836 100644
--- a/arch/powerpc/include/asm/mpc85xx.h
+++ b/include/linux/fsl/svr.h
@@ -9,8 +9,8 @@
  * (at your option) any later version.
  */
 
-#ifndef __ASM_PPC_MPC85XX_H
-#define __ASM_PPC_MPC85XX_H
+#ifndef FSL_SVR_H
+#define FSL_SVR_H
 
 #define SVR_REV(svr)	((svr) & 0xFF)		/* SOC design resision */
 #define SVR_MAJ(svr)	(((svr) >>  4) & 0xF)	/* Major revision field*/
-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Wed May  4 20:12:29 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Thu, 5 May 2016 11:12:29 +0800
Subject: [v10, 6/7] MAINTAINERS: add entry for Freescale SoC drivers
In-Reply-To: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462417950-46796-7-git-send-email-yangbo.lu@nxp.com>

Add maintainer entry for Freescale SoC drivers including
the QE library and the GUTS driver now. Also add maintainer
for QE library.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
Acked-by: Scott Wood <oss at buserror.net>
Acked-by: Qiang Zhao <qiang.zhao at nxp.com>
---
Changes for v8:
	- Added this patch
Changes for v9:
	- Added linux-arm mail list
	- Removed GUTS driver entry
Changes for v10:
	- Changed 'DRIVER' to 'DRIVERS'
	- Added 'Acked-by' of Scott and Qiang
---
 MAINTAINERS | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 42e65d1..85c4b8b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4622,9 +4622,18 @@ F:	drivers/net/ethernet/freescale/fec_ptp.c
 F:	drivers/net/ethernet/freescale/fec.h
 F:	Documentation/devicetree/bindings/net/fsl-fec.txt
 
+FREESCALE SOC DRIVERS
+M:	Scott Wood <oss at buserror.net>
+L:	linuxppc-dev at lists.ozlabs.org
+L:	linux-arm-kernel at lists.infradead.org
+S:	Maintained
+F:	drivers/soc/fsl/
+F:	include/linux/fsl/
+
 FREESCALE QUICC ENGINE LIBRARY
+M:	Qiang Zhao <qiang.zhao at nxp.com>
 L:	linuxppc-dev at lists.ozlabs.org
-S:	Orphan
+S:	Maintained
 F:	drivers/soc/fsl/qe/
 F:	include/soc/fsl/*qe*.h
 F:	include/soc/fsl/*ucc*.h
-- 
2.1.0.27.g96db324



From yangbo.lu at nxp.com  Wed May  4 20:12:30 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Thu, 5 May 2016 11:12:30 +0800
Subject: [v10, 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-R1.0-R2.0
In-Reply-To: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
Message-ID: <1462417950-46796-8-git-send-email-yangbo.lu@nxp.com>

The eSDHC of T4240-R1.0-R2.0 has incorrect vender version and spec version.
Acturally the right version numbers should be VVN=0x13 and SVN = 0x1.
This patch adds the GUTS driver support for eSDHC driver to get SVR(System
version register). And fix host version to avoid that incorrect version
numbers break down the ADMA data transfer.

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
Acked-by: Ulf Hansson <ulf.hansson at linaro.org>
Acked-by: Scott Wood <oss at buserror.net>
---
Changes for v2:
	- Got SVR through iomap instead of dts
Changes for v3:
	- Managed GUTS through syscon instead of iomap in eSDHC driver
Changes for v4:
	- Got SVR by GUTS driver instead of SYSCON
Changes for v5:
	- Changed to get SVR through API fsl_guts_get_svr()
	- Combined patch 4, patch 5 and patch 6 into one
Changes for v6:
	- Added 'Acked-by: Ulf Hansson'
Changes for v7:
	- None
Changes for v8:
	- Added 'Acked-by: Scott Wood'
Changes for v9:
	- None
Changes for v10:
	- None
---
 drivers/mmc/host/Kconfig          |  1 +
 drivers/mmc/host/sdhci-of-esdhc.c | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 0aa484c..e15e836 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -143,6 +143,7 @@ config MMC_SDHCI_OF_ESDHC
 	depends on MMC_SDHCI_PLTFM
 	depends on PPC || ARCH_MXC || ARCH_LAYERSCAPE
 	select MMC_SDHCI_IO_ACCESSORS
+	select FSL_GUTS
 	help
 	  This selects the Freescale eSDHC controller support.
 
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 3f34d35..68cc020 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -18,6 +18,8 @@
 #include <linux/of.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/fsl/svr.h>
+#include <linux/fsl/guts.h>
 #include <linux/mmc/host.h>
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
@@ -28,6 +30,8 @@
 struct sdhci_esdhc {
 	u8 vendor_ver;
 	u8 spec_ver;
+	u32 soc_ver;
+	u8 soc_rev;
 };
 
 /**
@@ -73,6 +77,8 @@ static u32 esdhc_readl_fixup(struct sdhci_host *host,
 static u16 esdhc_readw_fixup(struct sdhci_host *host,
 				     int spec_reg, u32 value)
 {
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
 	u16 ret;
 	int shift = (spec_reg & 0x2) * 8;
 
@@ -80,6 +86,13 @@ static u16 esdhc_readw_fixup(struct sdhci_host *host,
 		ret = value & 0xffff;
 	else
 		ret = (value >> shift) & 0xffff;
+
+	/* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect
+	 * vendor version and spec version information.
+	 */
+	if ((spec_reg == SDHCI_HOST_VERSION) &&
+	    (esdhc->soc_ver == SVR_T4240) && (esdhc->soc_rev <= 0x20))
+		ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200;
 	return ret;
 }
 
@@ -567,10 +580,20 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_esdhc *esdhc;
 	u16 host_ver;
+	u32 svr;
 
 	pltfm_host = sdhci_priv(host);
 	esdhc = sdhci_pltfm_priv(pltfm_host);
 
+	fsl_guts_init();
+	svr = fsl_guts_get_svr();
+	if (svr) {
+		esdhc->soc_ver = SVR_SOC_VER(svr);
+		esdhc->soc_rev = SVR_REV(svr);
+	} else {
+		dev_err(&pdev->dev, "Failed to get SVR value!\n");
+	}
+
 	host_ver = sdhci_readw(host, SDHCI_HOST_VERSION);
 	esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >>
 			     SDHCI_VENDOR_VER_SHIFT;
-- 
2.1.0.27.g96db324



From rnayak at codeaurora.org  Wed May  4 21:46:57 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu, 05 May 2016 10:16:57 +0530
Subject: [PATCH v5 00/11] qcom: Add support for TSENS driver
In-Reply-To: <20160428000309.GD2590@localhost.localdomain>
References: <1460626319-14516-1-git-send-email-rnayak@codeaurora.org>
 <20160428000309.GD2590@localhost.localdomain>
Message-ID: <572AD041.8050906@codeaurora.org>


On 04/28/2016 05:33 AM, Eduardo Valentin wrote:
> On Thu, Apr 14, 2016 at 03:01:48PM +0530, Rajendra Nayak wrote:
>> Current set of patches apply on 4.6-rc3. nvmem apis are currently
>> broken and hence need to pull in the fixes for it as proposed here [1]
> 
> From a glance overview of your series, looks good to me, but before I
> start triggering my local scripts to check them, I want to know what is
> the path for merging this.

Hey Eduardo, sorry for the delayed response, was out a few days.
So 1/11 to 6/11 would need to go through you, and the rest (dts changes)
via Andy's tree.

> 
> If I understand correctly the above statement, merging this right now,
> means merging a non-functional driver, right?

So I see Srini has pushed fixes [1] for nvmem and Greg has them pulled in in his
-next [2]

[1] https://lkml.org/lkml/2016/4/24/103
[2] git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git char-misc-next

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation


From rnayak at codeaurora.org  Wed May  4 21:47:26 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu, 05 May 2016 10:17:26 +0530
Subject: [PATCH v5 04/11] thermal: core: export apis to get slope and
 offset
In-Reply-To: <20160428000813.GA17932@localhost.localdomain>
References: <1460626319-14516-1-git-send-email-rnayak@codeaurora.org>
 <1460626319-14516-5-git-send-email-rnayak@codeaurora.org>
 <20160428000813.GA17932@localhost.localdomain>
Message-ID: <572AD05E.3060303@codeaurora.org>


On 04/28/2016 05:38 AM, Eduardo Valentin wrote:
> On Thu, Apr 14, 2016 at 03:01:52PM +0530, Rajendra Nayak wrote:
>> Add apis for platform thermal drivers to query for slope and offset
>> attributes, which might be needed for temperature calculations.
>>
>> Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
>> ---
>>  drivers/thermal/thermal_core.c | 16 ++++++++++++++++
>>  include/linux/thermal.h        |  8 ++++++++
>>  2 files changed, 24 insertions(+)
>>
>> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
>> index d4b5465..7d72aad 100644
>> --- a/drivers/thermal/thermal_core.c
>> +++ b/drivers/thermal/thermal_core.c
>> @@ -2065,6 +2065,22 @@ exit:
>>  }
>>  EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
>>  
>> +int thermal_zone_get_slope(struct thermal_zone_device *tz)
>> +{
>> +	if (tz && tz->tzp)
>> +		return tz->tzp->slope;
>> +	return 1;
>> +}
>> +EXPORT_SYMBOL_GPL(thermal_zone_get_slope);
>> +
>> +int thermal_zone_get_offset(struct thermal_zone_device *tz)
>> +{
>> +	if (tz && tz->tzp)
>> +		return tz->tzp->offset;
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(thermal_zone_get_offset);
> 
> 
> Please include kernel doc entries for the exported functions. Updating
> sysfs-api.txt would be also appreciated.

Sure, will update and repost.

> 
> Thanks for adding this.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation


From rnayak at codeaurora.org  Wed May  4 21:47:51 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu, 05 May 2016 10:17:51 +0530
Subject: [PATCH v5 11/11] arm64: dts: msm8996: Add thermal zones, tsens
 and qfprom nodes
In-Reply-To: <20160428000346.GE2590@localhost.localdomain>
References: <1460626319-14516-1-git-send-email-rnayak@codeaurora.org>
 <1460626319-14516-12-git-send-email-rnayak@codeaurora.org>
 <20160428000346.GE2590@localhost.localdomain>
Message-ID: <572AD077.507@codeaurora.org>


On 04/28/2016 05:33 AM, Eduardo Valentin wrote:
> On Thu, Apr 14, 2016 at 03:01:59PM +0530, Rajendra Nayak wrote:
>> Add thermal zones, tsens and qfprom nodes
>>
>> Cc: Andy Gross <agross at codeaurora.org>
>> Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
>> ---
>>  arch/arm64/boot/dts/qcom/msm8996.dtsi | 92 +++++++++++++++++++++++++++++++++++
>>  1 file changed, 92 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
>> index 0506fb8..4b36929 100644
>> --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
>> +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
>> @@ -97,6 +97,92 @@
>>  		};
>>  	};
>>  
>> +	thermal-zones {
>> +		cpu-thermal0 {
>> +			polling-delay-passive = <250>;
>> +			polling-delay = <1000>;
>> +
>> +			thermal-sensors = <&tsens0 3>;
>> +
>> +			trips {
>> +				cpu_alert0: trip at 0 {
>> +					temperature = <75000>;
>> +					hysteresis = <2000>;
>> +					type = "passive";
>> +				};
>> +
>> +				cpu_crit0: trip at 1 {
>> +					temperature = <110000>;
>> +					hysteresis = <2000>;
>> +					type = "critical";
>> +				};
> 
> 
> cooling devices?

We are still missing cpufreq support for these devices upstream

> 

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation


From rnayak at codeaurora.org  Wed May  4 21:48:59 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu, 05 May 2016 10:18:59 +0530
Subject: [PATCH v5 05/11] thermal: qcom: tsens-8960: Add support for 8960
 family of SoCs
In-Reply-To: <20160428001055.GB17932@localhost.localdomain>
References: <1460626319-14516-1-git-send-email-rnayak@codeaurora.org>
 <1460626319-14516-6-git-send-email-rnayak@codeaurora.org>
 <20160428001055.GB17932@localhost.localdomain>
Message-ID: <572AD0BB.5050900@codeaurora.org>



On 04/28/2016 05:40 AM, Eduardo Valentin wrote:
> On Thu, Apr 14, 2016 at 03:01:53PM +0530, Rajendra Nayak wrote:
>> 8960 family of SoCs have the TSENS device as part of GCC, hence
>> the driver probes the virtual child device created by GCC and
>> uses the parent to extract all DT properties and reuses the GCC
>> regmap.
>>
>> Also GCC/TSENS are part of a  domain thats not always ON.
>> Hence add .suspend and .resume hooks to save and restore some of
>> the inited register context.
>>
>> Also 8960 family have some of the TSENS init sequence thats
>> required to be done by the HLOS driver (some later versions of TSENS
>> do not export these registers to non-secure world, and hence need
>> these initializations to be done by secure bootloaders)
>>
>> 8660 from the same family has just one sensor and hence some register
>> offset/layout differences which need special handling in the driver.
>>
>> Based on the original code from Siddartha Mohanadoss, Stephen Boyd and
>> Narendran Rajan.
>>
>> Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
>> ---
>>  drivers/thermal/qcom/Makefile     |   2 +-
>>  drivers/thermal/qcom/tsens-8960.c | 293 ++++++++++++++++++++++++++++++++++++++
>>  drivers/thermal/qcom/tsens.c      |   8 +-
>>  drivers/thermal/qcom/tsens.h      |   2 +-
>>  4 files changed, 299 insertions(+), 6 deletions(-)
>>  create mode 100644 drivers/thermal/qcom/tsens-8960.c
>>
>> diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
>> index a471100..f3cefd1 100644
>> --- a/drivers/thermal/qcom/Makefile
>> +++ b/drivers/thermal/qcom/Makefile
>> @@ -1,2 +1,2 @@
>>  obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
>> -qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o
>> +qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o
>> diff --git a/drivers/thermal/qcom/tsens-8960.c b/drivers/thermal/qcom/tsens-8960.c
>> new file mode 100644
>> index 0000000..a5976ec3
>> --- /dev/null
>> +++ b/drivers/thermal/qcom/tsens-8960.c
>> @@ -0,0 +1,293 @@
>> +/*
>> + * Copyright (c) 2015, The Linux Foundation. All rights reserved.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 and
>> + * only version 2 as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + */
>> +
>> +#include <linux/platform_device.h>
>> +#include <linux/delay.h>
>> +#include <linux/bitops.h>
>> +#include <linux/regmap.h>
>> +#include <linux/thermal.h>
>> +#include "tsens.h"
>> +
>> +#define CAL_MDEGC		30000
>> +
>> +#define CONFIG_ADDR		0x3640
>> +#define CONFIG_ADDR_8660	0x3620
>> +/* CONFIG_ADDR bitmasks */
>> +#define CONFIG			0x9b
>> +#define CONFIG_MASK		0xf
>> +#define CONFIG_8660		1
>> +#define CONFIG_SHIFT_8660	28
>> +#define CONFIG_MASK_8660	(3 << CONFIG_SHIFT_8660)
>> +
>> +#define STATUS_CNTL_ADDR_8064	0x3660
>> +#define CNTL_ADDR		0x3620
>> +/* CNTL_ADDR bitmasks */
>> +#define EN			BIT(0)
>> +#define SW_RST			BIT(1)
>> +#define SENSOR0_EN		BIT(3)
>> +#define SLP_CLK_ENA		BIT(26)
>> +#define SLP_CLK_ENA_8660	BIT(24)
>> +#define MEASURE_PERIOD		1
>> +#define SENSOR0_SHIFT		3
>> +
>> +/* INT_STATUS_ADDR bitmasks */
>> +#define MIN_STATUS_MASK		BIT(0)
>> +#define LOWER_STATUS_CLR	BIT(1)
>> +#define UPPER_STATUS_CLR	BIT(2)
>> +#define MAX_STATUS_MASK		BIT(3)
>> +
>> +#define THRESHOLD_ADDR		0x3624
>> +/* THRESHOLD_ADDR bitmasks */
>> +#define THRESHOLD_MAX_LIMIT_SHIFT	24
>> +#define THRESHOLD_MIN_LIMIT_SHIFT	16
>> +#define THRESHOLD_UPPER_LIMIT_SHIFT	8
>> +#define THRESHOLD_LOWER_LIMIT_SHIFT	0
>> +
>> +/* Initial temperature threshold values */
>> +#define LOWER_LIMIT_TH		0x50
>> +#define UPPER_LIMIT_TH		0xdf
>> +#define MIN_LIMIT_TH		0x0
>> +#define MAX_LIMIT_TH		0xff
>> +
>> +#define S0_STATUS_ADDR		0x3628
>> +#define INT_STATUS_ADDR		0x363c
>> +#define TRDY_MASK		BIT(7)
>> +#define TIMEOUT_US		100
>> +
>> +static int suspend_8960(struct tsens_device *tmdev)
>> +{
>> +	int ret;
>> +	unsigned int mask;
>> +	struct regmap *map = tmdev->map;
>> +
>> +	ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if (tmdev->num_sensors > 1)
>> +		mask = SLP_CLK_ENA | EN;
>> +	else
>> +		mask = SLP_CLK_ENA_8660 | EN;
>> +
>> +	ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static int resume_8960(struct tsens_device *tmdev)
>> +{
>> +	int ret;
>> +	struct regmap *map = tmdev->map;
>> +
>> +	ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/*
>> +	 * Separate CONFIG restore is not needed only for 8660 as
>> +	 * config is part of CTRL Addr and its restored as such
>> +	 */
>> +	if (tmdev->num_sensors > 1) {
>> +		ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static int enable_8960(struct tsens_device *tmdev, int id)
>> +{
>> +	int ret;
>> +	u32 reg, mask;
>> +
>> +	ret = regmap_read(tmdev->map, CNTL_ADDR, &reg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	mask = BIT(id + SENSOR0_SHIFT);
>> +	ret = regmap_write(tmdev->map, CNTL_ADDR, reg | SW_RST);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if (tmdev->num_sensors > 1)
>> +		reg |= mask | SLP_CLK_ENA | EN;
>> +	else
>> +		reg |= mask | SLP_CLK_ENA_8660 | EN;
>> +
>> +	ret = regmap_write(tmdev->map, CNTL_ADDR, reg);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static void disable_8960(struct tsens_device *tmdev)
>> +{
>> +	int ret;
>> +	u32 reg_cntl;
>> +	u32 mask;
>> +
>> +	mask = GENMASK(tmdev->num_sensors - 1, 0);
>> +	mask <<= SENSOR0_SHIFT;
>> +	mask |= EN;
>> +
>> +	ret = regmap_read(tmdev->map, CNTL_ADDR, &reg_cntl);
>> +	if (ret)
>> +		return;
>> +
>> +	reg_cntl &= ~mask;
>> +
>> +	if (tmdev->num_sensors > 1)
>> +		reg_cntl &= ~SLP_CLK_ENA;
>> +	else
>> +		reg_cntl &= ~SLP_CLK_ENA_8660;
>> +
>> +	regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
>> +}
>> +
>> +static int init_8960(struct tsens_device *tmdev)
>> +{
>> +	int ret, i;
>> +	u32 reg_cntl;
>> +
>> +	tmdev->map = dev_get_regmap(tmdev->dev, NULL);
>> +	if (!tmdev->map)
>> +		return -ENODEV;
>> +
>> +	/*
>> +	 * The status registers for each sensor are discontiguous
>> +	 * because some SoCs have 5 sensors while others have more
>> +	 * but the control registers stay in the same place, i.e
>> +	 * directly after the first 5 status registers.
>> +	 */
>> +	for (i = 0; i < tmdev->num_sensors; i++) {
>> +		if (i >= 5)
>> +			tmdev->sensor[i].status = S0_STATUS_ADDR + 40;
>> +		tmdev->sensor[i].status += i * 4;
>> +	}
>> +
>> +	reg_cntl = SW_RST;
>> +	ret = regmap_update_bits(tmdev->map, CNTL_ADDR, SW_RST, reg_cntl);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if (tmdev->num_sensors > 1) {
>> +		reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18);
>> +		reg_cntl &= ~SW_RST;
>> +		ret = regmap_update_bits(tmdev->map, CONFIG_ADDR,
>> +					 CONFIG_MASK, CONFIG);
>> +	} else {
>> +		reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16);
>> +		reg_cntl &= ~CONFIG_MASK_8660;
>> +		reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660;
>> +	}
>> +
>> +	reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT;
>> +	ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
>> +	if (ret)
>> +		return ret;
>> +
>> +	reg_cntl |= EN;
>> +	ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static int calibrate_8960(struct tsens_device *tmdev)
>> +{
>> +	int i;
>> +	char *data;
>> +
>> +	ssize_t num_read = tmdev->num_sensors;
>> +	struct tsens_sensor *s = tmdev->sensor;
>> +
>> +	data = qfprom_read(tmdev->dev, "calib");
>> +	if (IS_ERR(data))
>> +		data = qfprom_read(tmdev->dev, "calib_backup");
>> +	if (IS_ERR(data))
>> +		return PTR_ERR(data);
>> +
>> +	for (i = 0; i < num_read; i++, s++)
>> +		s->offset = data[i];
>> +
>> +	return 0;
>> +}
>> +
>> +/* Temperature on y axis and ADC-code on x-axis */
>> +static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s)
>> +{
>> +	u32 slope;
> 
> why unsigned?
> 
>> +	int offset;
>> +
>> +	slope = thermal_zone_get_slope(s->tzd);;
> 
> Please use one single ;

Will fix both when I repost.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation


From rnayak at codeaurora.org  Wed May  4 21:50:41 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu, 05 May 2016 10:20:41 +0530
Subject: [PATCH v5 01/11] thermal: qcom: tsens: Add a skeletal TSENS
 drivers
In-Reply-To: <20160428002040.GA18496@localhost.localdomain>
References: <1460626319-14516-1-git-send-email-rnayak@codeaurora.org>
 <1460626319-14516-2-git-send-email-rnayak@codeaurora.org>
 <20160428002040.GA18496@localhost.localdomain>
Message-ID: <572AD121.8040503@codeaurora.org>



On 04/28/2016 05:50 AM, Eduardo Valentin wrote:
> On Thu, Apr 14, 2016 at 03:01:49PM +0530, Rajendra Nayak wrote:
>> TSENS is Qualcomms' thermal temperature sensor device. It
>> supports reading temperatures from multiple thermal sensors
>> present on various QCOM SoCs.
>> Calibration data is generally read from a non-volatile memory
>> (eeprom) device.
>>
>> Add a skeleton driver with all the necessary abstractions so
>> a variety of qcom device families which support TSENS can
>> add driver extensions.
>>
>> Also add the required device tree bindings which can be used
>> to describe the TSENS device in DT.
>>
>> Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
>> Reviewed-by: Lina Iyer <lina.iyer at linaro.org>
>> ---
[]..

>> @@ -0,0 +1,135 @@
>> +/*
>> + * Copyright (c) 2015, The Linux Foundation. All rights reserved.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 and
>> + * only version 2 as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + */
>> +
>> +#include <linux/err.h>
>> +#include <linux/io.h>
>> +#include <linux/nvmem-consumer.h>
>> +#include <linux/of_address.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regmap.h>
>> +#include "tsens.h"
>> +
>> +#define S0_ST_ADDR		0x1030
>> +#define SN_ADDR_OFFSET		0x4
>> +#define SN_ST_TEMP_MASK		0x3ff
>> +#define CAL_DEGC_PT1		30
>> +#define CAL_DEGC_PT2		120
>> +#define SLOPE_FACTOR		1000
>> +#define SLOPE_DEFAULT		3200
>> +
>> +char *qfprom_read(struct device *dev, const char *cname)
>> +{
>> +	struct nvmem_cell *cell;
>> +	ssize_t data;
>> +	char *ret;
>> +
>> +	cell = nvmem_cell_get(dev, cname);
>> +	if (IS_ERR(cell))
>> +		return ERR_CAST(cell);
>> +
>> +	ret = nvmem_cell_read(cell, &data);
>> +	nvmem_cell_put(cell);
>> +
>> +	return ret;
>> +}
>> +
>> +void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
>> +			     u32 *p2, u32 mode)
>> +{
> 
> Could you please add a comment explaining the cases that this function
> is used instead of tz->tzp->slope,offset?

sure, will do.

> 
>> +	int i;
>> +	int num, den;
>> +
>> +	for (i = 0; i < tmdev->num_sensors; i++) {
>> +		dev_dbg(tmdev->dev,
>> +			"sensor%d - data_point1:%#x data_point2:%#x\n",
>> +			i, p1[i], p2[i]);
>> +
>> +		tmdev->sensor[i].slope = SLOPE_DEFAULT;
>> +		if (mode == TWO_PT_CALIB) {
>> +			/*
>> +			 * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
>> +			 *	temp_120_degc - temp_30_degc (x2 - x1)
>> +			 */
>> +			num = p2[i] - p1[i];
>> +			num *= SLOPE_FACTOR;
>> +			den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
>> +			tmdev->sensor[i].slope = num / den;
>> +		}
>> +
>> +		tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
>> +				(CAL_DEGC_PT1 *
>> +				tmdev->sensor[i].slope);
>> +		dev_dbg(tmdev->dev, "offset:%d\n", tmdev->sensor[i].offset);
>> +	}
>> +}
[]..
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation


From sricharan at codeaurora.org  Wed May  4 22:10:00 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Thu, 5 May 2016 10:40:00 +0530
Subject: [PATCH V3 2/7] documentation: iommu: Add bindings for msm,
 iommu-v0 ip
In-Reply-To: <20160504022437.GA4110@rob-hp-laptop>
References: <1462128875-20988-1-git-send-email-sricharan@codeaurora.org>
 <1462128875-20988-3-git-send-email-sricharan@codeaurora.org>
 <20160504022437.GA4110@rob-hp-laptop>
Message-ID: <000001d1a68c$648e3a90$2daaafb0$@codeaurora.org>

Hi,

> > The MSM IOMMU is an implementation compatible with the ARM VMSA
> short
> > descriptor page tables. It provides address translation for bus
> > masters outside of the CPU, each connected to the IOMMU through a port
> called micro-TLB.
> > Adding the DT bindings for the same.
> >
> > Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> > ---
> >  .../devicetree/bindings/iommu/msm,iommu-v0.txt     | 62
> ++++++++++++++++++++++
> >  1 file changed, 62 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
> >
> > diff --git a/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
> > b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
> > new file mode 100644
> > index 0000000..63b4f96
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
> > @@ -0,0 +1,62 @@
> > +* MSM IOMMU
> > +
> > +The MSM IOMMU is an implementation compatible with the ARM VMSA
> short
> > +descriptor page tables. It provides address translation for bus
> > +masters outside of the CPU, each connected to the IOMMU through a
> port called micro-TLB.
> > +
> > +Required Properties:
> > +
> > +  - compatible: Must contain "msm,iommu-v0".
> 
> SOC specific compatible strings please.
  Ok sure. I think I missed being explicit here last time.

> 
> > +  - reg: Base address and size of the IOMMU registers.
> > +  - interrupts: Specifiers for the MMU fault interrupts. For instances
that
> > +    support secure mode two interrupts must be specified, for
non-secure
> and
> > +    secure mode, in that order. For instances that don't support secure
> mode a
> > +    single interrupt must be specified.
> > +  - #iommu-cells: The number of cells needed to specify the stream id.
This
> > +		  is always 1.
> > +  - qcom,ncb:	  The total number of context banks in the IOMMU.
> > +  - clocks	: List of clocks to be used during SMMU register access. See
> > +		  Documentation/devicetree/bindings/clock/clock-
> bindings.txt
> > +		  for information about the format. For each clock specified
> > +		  here, there must be a corresponding entry in clock-names
> > +		  (see below).
> > +
> > +  - clock-names	: List of clock names corresponding to the clocks
> specified in
> > +		  the "clocks" property (above). See
> > +		  Documentation/devicetree/bindings/clock/clock-
> bindings.txt
> > +		  for more info.
> 
> You must define how many clocks, their order and their names.
 Ok, will update this and repost

Regards,
 Sricharan



From raveendra.padasalagi at broadcom.com  Wed May  4 22:47:00 2016
From: raveendra.padasalagi at broadcom.com (Raveendra Padasalagi)
Date: Thu, 5 May 2016 11:17:00 +0530
Subject: [PATCH v4 3/3] ARM: dts: use syscon in cygnus touchscreen dt node
In-Reply-To: <CAGVrzcbCZn6RYFwJTkffkct1DiiG+tBJnKELDn32T38_s5mjOg@mail.gmail.com>
References: <1456556396-4759-1-git-send-email-raveendra.padasalagi@broadcom.com>
 <1456556396-4759-4-git-send-email-raveendra.padasalagi@broadcom.com>
 <20160406173140.GB38452@dtor-ws>
 <CAGVrzcbCZn6RYFwJTkffkct1DiiG+tBJnKELDn32T38_s5mjOg@mail.gmail.com>
Message-ID: <CAAFb_vp+oxHc6YD24zPr0o6Pt9Jt1_LsT14VUQGBKXBpvNAj_Q@mail.gmail.com>

Thanks Dmitry and Florian.

Hi Dmitry,

I understand the dts changes are really needed for the touch screen
driver changes made in this patch. But currently there are no deployed
systems/customer's using this driver. So please pull the driver changes
and I will follow up to make sure dts changes also goes in.

Below is the latest patch set pushed.

https://lkml.org/lkml/2016/3/24/45


Thanks ,
Raveendra

On Thu, Apr 7, 2016 at 1:55 AM, Florian Fainelli <f.fainelli at gmail.com> wrote:
> 2016-04-06 10:31 GMT-07:00 Dmitry Torokhov <dmitry.torokhov at gmail.com>:
>> On Sat, Feb 27, 2016 at 12:29:56PM +0530, Raveendra Padasalagi wrote:
>>> In Cygnus SOC touch screen controller registers are shared
>>> with ADC and flex timer. Using readl/writel could lead to
>>> race condition. So touchscreen driver is enhanced to support
>>> syscon based register access to take care of mutually exclusive
>>> access.
>>>
>>> This patch enables syscon support in touchscreen driver
>>> by adding necessary properties in touchscreen dt node and
>>> in addition to this renamed existing "tsc" touchscreen node
>>> name to "touchscreen".
>>>
>>> Signed-off-by: Raveendra Padasalagi <raveendra.padasalagi at broadcom.com>
>>> Reviewed-by: Ray Jui <ray.jui at broadcom.com>
>>> Reviewed-by: Scott Branden <scott.branden at broadcom.com>
>>
>> OK, since the new dts is really needed for the driver I'll be folding
>> this into the touchscreen driver patch unless I hear someone yelling at
>> me.
>
> Works for me:
>
> Acked-by: Florian Fainelli <f.fainelli at gmail.com>
> --
> Florian


From pinskia at gmail.com  Wed May  4 23:40:44 2016
From: pinskia at gmail.com (Andrew Pinski)
Date: Wed, 4 May 2016 23:40:44 -0700
Subject: [PATCH 24/25] arm64:ilp32: add vdso-ilp32 and use for signal
 return
In-Reply-To: <572AAED2.7050604@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1554541.oDP7Ro5zB2@wuerfel>
 <20160503090045.GB10733@e104818-lin.cambridge.arm.com>
 <3846428.6xx69KGEja@wuerfel> <57288660.9030607@huawei.com>
 <57289C75.50904@huawei.com> <20160504214949.GA28217@yury-N73SV>
 <CA+=Sn1ngpaJWHpGDmU+kXBkz56SO+XDW2qzMMLAbbBWnaB0eqw@mail.gmail.com>
 <572AAED2.7050604@huawei.com>
Message-ID: <CA+=Sn1mNdd+Xy5QL5ScRyZOCWwKkG6o1Pb50sFPuiKX=0Z2B1w@mail.gmail.com>

On Wed, May 4, 2016 at 7:24 PM, Zhangjian (Bamvor)
<bamvor.zhangjian at huawei.com> wrote:
> Hi,
>
>
> On 2016/5/5 7:23, Andrew Pinski wrote:
>>
>> On Wed, May 4, 2016 at 2:49 PM, Yury Norov <ynorov at caviumnetworks.com>
>> wrote:
>>>
>>> On Tue, May 03, 2016 at 08:41:25PM +0800, Zhangjian (Bamvor) wrote:
>>>>
>>>> Hi, all
>>>>
>>>> After apply this patch with my small testcase, the vsyscall of
>>>> gettimeofday in
>>>> ilp32 works in both big endian and small endian. In this patch, I use
>>>> the
>>>> different register and offset for ilp32 and lp64. Actually, the
>>>> COMPAT_TVAL_TV_SEC is same as TVAL_TV_SEC(so as to COMPAT_TSPEC_TV_SEC
>>>> and
>>>> TSPEC_TV_SEC). I add it to keep the logic clear. I also change the
>>>> version
>>>> of vdso to 4.6. It should change to 2.6.39 if glibc is not update.
>>>>
>>>
>>> [...]
>>>
>>> Hi Bamvor,
>>>
>>> It works for me as well. Thank you.
>>> I'll incorporate it in next submission.
>>
>>
>> We should add the following so we are complaint to the ILP32 ABI
>> dealing with pointers don't have to be zero extended for arguments,
>> Note ZERO should most likely be ZERO_PTR or something to do that
>> effect, I am not so good with names.
>> #ifdef __LP64__
>> #define ZERO(n)
>> #else
>> #define ZERO(n)         mov     w##n, w##n
>> #endif
>>
>> ...
>> ENTRY(__kernel_gettimeofday)
>>          .cfi_startproc
>>          ZERO(0)
>>          ZERO(1)
>> ...
>> ENTRY(__kernel_clock_gettime)
>>          .cfi_startproc
>>          ZERO(1)
>> ...
>> ENTRY(__kernel_clock_getres)
>>          .cfi_startproc
>>          ZERO(1)
>
> Thanks. I will test and send a new version.


Note there is one more patch needed to __kernel_clock_getres to store
using 32bit rather than 64bit too.
@@ -213,7 +213,7 @@ ENTRY(__kernel_clock_getres)
        ldr     x2, 6f
 2:
        cbz     w1, 3f
-       stp     xzr, x2, [x1]
+       stp     PTR_REG(zr), PTR_REG(2), [x1]

 3:     /* res == NULL. */
        mov     w0, wzr


Thanks,
Andrew

>
> Thanks.
>
> Bamvor
>>
>> Thanks,
>> Andrew Pinski
>>
>>>
>>> Yury.
>
>


From marc.zyngier at arm.com  Thu May  5 00:38:18 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 5 May 2016 08:38:18 +0100
Subject: [PATCH v2] irqchip/gic-v2m: Add workaround for Broadcom NS2
 GICv2m erratum
In-Reply-To: <1462405635-27864-2-git-send-email-ray.jui@broadcom.com>
References: <1462405635-27864-1-git-send-email-ray.jui@broadcom.com>
 <1462405635-27864-2-git-send-email-ray.jui@broadcom.com>
Message-ID: <572AF86A.1090000@arm.com>

On 05/05/16 00:47, Ray Jui wrote:
> Alex Barba <alex.barba at broadcom.com> discovered Broadcom NS2 GICv2m
> implementation has an erratum where the MSI data needs to be the SPI
> number subtracted by an offset of 32, for the correct MSI interrupt
> to be triggered.
> 
> Here we are adding the workaround based on readings from the MSI_IIDR
> register, which contains a value unique to Broadcom NS2 GICv2m
> 
> Reported-by: Alex Barba <alex.barba at broadcom.com>
> Signed-off-by: Ray Jui <ray.jui at broadcom.com>
> ---
>  drivers/irqchip/irq-gic-v2m.c | 17 +++++++++++++++--
>  1 file changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
> index 28f047c..4c89e27 100644
> --- a/drivers/irqchip/irq-gic-v2m.c
> +++ b/drivers/irqchip/irq-gic-v2m.c
> @@ -49,6 +49,9 @@
>  /* APM X-Gene with GICv2m MSI_IIDR register value */
>  #define XGENE_GICV2M_MSI_IIDR		0x06000170
>  
> +/* Broadcom NS2 GICv2m MSI_IIDR register value */
> +#define BCM_NS2_GICV2M_MSI_IIDR		0x0000013f
> +
>  /* List of flags for specific v2m implementation */
>  #define GICV2M_NEEDS_SPI_OFFSET		0x00000001
>  
> @@ -62,6 +65,7 @@ struct v2m_data {
>  	void __iomem *base;	/* GICv2m virt address */
>  	u32 spi_start;		/* The SPI number that MSIs start */
>  	u32 nr_spis;		/* The number of SPIs for MSIs */
> +	u32 spi_offset;		/* offset to be subtracted from SPI number */
>  	unsigned long *bm;	/* MSI vector bitmap */
>  	u32 flags;		/* v2m flags for specific implementation */
>  };
> @@ -102,7 +106,7 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
>  	msg->data = data->hwirq;
>  
>  	if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET)
> -		msg->data -= v2m->spi_start;
> +		msg->data -= v2m->spi_offset;
>  }
>  
>  static struct irq_chip gicv2m_irq_chip = {
> @@ -340,9 +344,18 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
>  	 * different from the standard GICv2m implementation where
>  	 * the MSI data is the absolute value within the range from
>  	 * spi_start to (spi_start + num_spis).
> +	 *
> +	 * Broadom NS2 GICv2m implementation has an erratum where the MSI data
> +	 * is 'spi_number - 32'
>  	 */
> -	if (readl_relaxed(v2m->base + V2M_MSI_IIDR) == XGENE_GICV2M_MSI_IIDR)
> +	if (readl_relaxed(v2m->base + V2M_MSI_IIDR) == XGENE_GICV2M_MSI_IIDR) {
> +		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
> +		v2m->spi_offset = v2m->spi_start;
> +	} else if (readl_relaxed(v2m->base + V2M_MSI_IIDR) ==
> +		   BCM_NS2_GICV2M_MSI_IIDR) {
>  		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
> +		v2m->spi_offset = 32;
> +	}

Can we make this a bit less ugly?

	switch (readl_relaxed(v2m->base + V2M_MSI_IIDR)) {
	case XGENE_GICV2M_MSI_IIDR:
		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
		v2m->spi_offset = v2m->spi_start;
		break;
	case BCM_NS2_GICV2M_MSI_IIDR:
		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
		v2m->spi_offset = 32;
		break;
	}

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From ynorov at caviumnetworks.com  Thu May  5 01:22:37 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 5 May 2016 11:22:37 +0300
Subject: [PATCH 24/25] arm64:ilp32: add vdso-ilp32 and use for signal
 return
In-Reply-To: <57289C75.50904@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1554541.oDP7Ro5zB2@wuerfel>
 <20160503090045.GB10733@e104818-lin.cambridge.arm.com>
 <3846428.6xx69KGEja@wuerfel> <57288660.9030607@huawei.com>
 <57289C75.50904@huawei.com>
Message-ID: <20160505082237.GA32190@yury-N73SV>

On Tue, May 03, 2016 at 08:41:25PM +0800, Zhangjian (Bamvor) wrote:
[...]

> After apply this patch with my small testcase, the vsyscall of gettimeofday in
> ilp32 works in both big endian and small endian. In this patch, I use the
> different register and offset for ilp32 and lp64. Actually, the
> COMPAT_TVAL_TV_SEC is same as TVAL_TV_SEC(so as to COMPAT_TSPEC_TV_SEC and
> TSPEC_TV_SEC). I add it to keep the logic clear. I also change the version
> of vdso to 4.6. It should change to 2.6.39 if glibc is not update.
> 
> diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
> index 574081f..c8e32eb 100644
> --- a/arch/arm64/kernel/asm-offsets.c
> +++ b/arch/arm64/kernel/asm-offsets.c
> @@ -101,6 +101,11 @@ int main(void)
>    DEFINE(TSPEC_TV_SEC,		offsetof(struct timespec, tv_sec));
>    DEFINE(TSPEC_TV_NSEC,		offsetof(struct timespec, tv_nsec));
>    BLANK();
> +  DEFINE(COMPAT_TVAL_TV_SEC,	offsetof(struct compat_timeval, tv_sec));
> +  DEFINE(COMPAT_TVAL_TV_USEC,	offsetof(struct compat_timeval, tv_usec));
> +  DEFINE(COMPAT_TSPEC_TV_SEC,	offsetof(struct compat_timespec, tv_sec));
> +  DEFINE(COMPAT_TSPEC_TV_NSEC,	offsetof(struct compat_timespec, tv_nsec));
> +  BLANK();

Hi Bamvor,

We just found this lines break build if ILP32 is disabled. I think we
need to wrap them with #ifdef CONFIG_ARM64_ILP32

Yury


From arnd at arndb.de  Thu May  5 01:31:36 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 05 May 2016 10:31:36 +0200
Subject: [v10,
 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-R1.0-R2.0
In-Reply-To: <1462417950-46796-8-git-send-email-yangbo.lu@nxp.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <1462417950-46796-8-git-send-email-yangbo.lu@nxp.com>
Message-ID: <4448030.Zs8fVnr3nm@wuerfel>

On Thursday 05 May 2016 11:12:30 Yangbo Lu wrote:
> 
> +       fsl_guts_init();
> +       svr = fsl_guts_get_svr();
> +       if (svr) {
> +               esdhc->soc_ver = SVR_SOC_VER(svr);
> +               esdhc->soc_rev = SVR_REV(svr);
> +       } else {
> +               dev_err(&pdev->dev, "Failed to get SVR value!\n");
> +       }
> +
> 


Sorry for jumping in again after not participating in the discussion for the
past few versions.

What happened to my suggestion of making this a platform-independent interface
to avoid the link time dependency?

Specifically, why not add an exported function to drivers/base/soc.c that
uses glob_match() for comparing a string in the device driver to the ID
of the SoC that is set by whatever SoC identifying driver the platform
has?

	Arnd


From matthias.bgg at gmail.com  Thu May  5 01:32:17 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Thu, 5 May 2016 10:32:17 +0200
Subject: [alsa-devel] [PATCH 1/7] ASoC: mediatek: Refine mt8173 driver and
 change config option
In-Reply-To: <1462416342.25179.36.camel@mtksdaap41>
References: <1461934848-60011-1-git-send-email-garlic.tseng@mediatek.com>
 <1461934848-60011-2-git-send-email-garlic.tseng@mediatek.com>
 <20160504164306.GA6292@sirena.org.uk> <1462416342.25179.36.camel@mtksdaap41>
Message-ID: <572B0511.80701@gmail.com>



On 05/05/16 04:45, Garlic Tseng wrote:
> On Wed, 2016-05-04 at 17:43 +0100, Mark Brown wrote:
>> On Fri, Apr 29, 2016 at 09:00:42PM +0800, Garlic Tseng wrote:
>>
>>>   .../{mtk-afe-pcm.c => mt8173/mt8173-afe-pcm.c}     | 488 ++++++++++-----------
>>
>> So there's going to be no code sharing at all between this and any other
>> Mediatek chips?  That seems very surprising, it'd suggest that the
>> hardware designers were creating a new design completely from scratch
>> each time which doesn't seem all that likely.  This is an unusual way of
>> organizing things and we need a much clearer explanation of what's going
>> on here.
>
> MT8173 and MT2701 are from different product lines so the register
> control sequences are very different. If another driver for 8173-like
> (or 2701-like) chip go upstream it shall share some common code with the
> relatively driver indeed. However I think MT8173 and MT2701 can't share
> the platform driver or a lot of "if MT8173 else MT2701" will mess up the
> code.
>

What about the other SoCs we have some minimal support for: mt6589, 
mt8135, mt6592, mt6580, mt7323, mt8127?

A quick glance at the datasheets showed me, that mt6589 and at least 
mt8127 have quite similar register offsets. So I suppose there is some 
common code actually.

Regards,
Matthias


From maitysanchayan at gmail.com  Thu May  5 01:27:58 2016
From: maitysanchayan at gmail.com (maitysanchayan at gmail.com)
Date: Thu, 5 May 2016 13:57:58 +0530
Subject: [PATCH v2 5/5] vf610-soc: Add Vybrid SoC device tree binding
 documentation
In-Reply-To: <20160504023026.GB5382@rob-hp-laptop>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
 <65f3a7bd7a9faf1b390644d7c599c69683c753c4.1462171990.git.maitysanchayan@gmail.com>
 <20160504023026.GB5382@rob-hp-laptop>
Message-ID: <20160505082758.GB18151@Sanchayan-Arch.localdomain>

Hello Rob,

On 16-05-03 21:30:26, Rob Herring wrote:
> On Mon, May 02, 2016 at 12:35:04PM +0530, Sanchayan Maity wrote:
> > Add device tree binding documentation for Vybrid SoC.
> > 
> > Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
> > ---
> >  .../bindings/arm/freescale/fsl,vf610-soc.txt       | 35 ++++++++++++++++++++++
> >  1 file changed, 35 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> > new file mode 100644
> > index 0000000..bdd95e8
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> > @@ -0,0 +1,35 @@
> > +Vybrid System-on-Chip
> > +---------------------
> > +
> > +Required properties:
> > +
> > +- #address-cells: must be 1
> > +- #size-cells: must be 1
> > +- compatible: "fsl,vf610-soc-bus", "simple-bus"
> 
> If this is a bus, put the file in bindings/bus/...

The fsl,vf610-soc-bus binding is used to bind the driver in question with
an appropriate compatible node.

Basically being a standalone platform driver, there was need of a compatible
property to bind on. Introducing a separate device tree node for it's sake
didn't seem appropriate so the alteration to SoC node's compatible.

> 
> > +- interrupt-parent: phandle to the MSCM interrupt router node
> > +- ranges
> > +- fsl,rom-revision: phandle to the on-chip ROM node and address of rom
> > +  revision register
> 
> Why is this needed here? Can't you search the tree for the ROM node and 
> get this info.

Strictly per say this and next two can be specified in their respective nodes
of ocrom and mscm cpucfg, however they would then require the use of syscon_
regmap_lookup_by_compatible and this seems clean along with the introduction
of new syscon_regmap_read_from_offset function used with SoC node.

> 
> > +- fsl,cpu-count: phandle to the MSCM CPU configuration node and address of
> > +  CPU count register
> > +- fsl,l2-size: phandle to the MSCM CPU configuration node and address of
> > +  L2 cache size register
> > +- nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
> > +- nvmem-cell-names: should contain string names "cfg0" and "cfg1"
> 
> How are all these properties used?

All the above five are used to get the relevant values from the registers and
expose the information for SoC sysfs device.
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-soc

nvmem are consumer nodes which are accessed using the NVMEM consumer API's
leveraging the NVMEM framework and NVMEM vf610 ocotp driver.

Regards,
Sanchayan.

> 
> > +
> > +Example:
> > +
> > +	soc {
> > +		#address-cells = <1>;
> > +		#size-cells = <1>;
> > +		compatible = "fsl,vf610-soc-bus", "simple-bus";
> > +		interrupt-parent = <&mscm_ir>;
> > +		ranges;
> > +		fsl,rom-revision = <&ocrom 0x80>;
> > +		fsl,cpu-count = <&mscm_cpucfg 0x2C>;
> > +		fsl,l2-size = <&mscm_cpucfg 0x14>;
> > +		nvmem-cells = <&ocotp_cfg0>, <&ocotp_cfg1>;
> > +		nvmem-cell-names = "cfg0", "cfg1";
> > +
> > +		...
> > +	};
> > -- 
> > 2.8.2
> > 


From rnayak at codeaurora.org  Thu May  5 01:51:38 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu,  5 May 2016 14:21:38 +0530
Subject: [PATCH v6 00/11] qcom: Add support for TSENS driver
Message-ID: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>

Current set of patches apply on 4.6-rc6. Fixes for the nvmem apis
are now posted [1] and queued in -next [2]
Patches [1-6] will need to be merged via thermal tree/Eduardo.
Patches [7-11] will need to go via qcom-msm tree/Andy.

Changes since v5:
* Minor review fixes from Eduardo

Changes since v4:
* dropped qcom,tsens-slopes binding, used coefficients instead
* dropped qcom,sensor-id binding
* Added support for msm8996 family
* Other minor review fixes from v4

Changes since v3:
* Dropped 'clk: qcom: create virtual child device for TSENS' which
is picked up by Stephen
* Updated GCC bindings with optional TSENS properties

Changes since v2:
* Minor review fixes from Stephen/Punit and rebase on 4.3-rc4

Changes since v1:
* Created virtual tsens device from gcc driver for 8960,
with DT having a single node for gcc and tsens
* Minor fixes with rebasing on 4.3-rc1

Changes since RFC:
* Added support for 8916 and 8084
* Based off the latest nvmem framework patches [1]
* Minor review fixes for comments mostly from Lina

This is an attempt to have a single TSENS driver for
the different versions of the TSENS IP that exist, on
different qcom msm/apq SoCs'
Support is added for msm8916, msm8960, msm8974 and msm8996 families.

A lot of the work is based of original code from Stephen Boyd
and Siddartha Mohanadoss. I have also picked some of what
Narendran Rajan did in his attempt to upstream the support
for 8960 family. I could not keep the original authorship on
any of the patches because I ended up moving the code around
quite a bit in an effort to have a single driver for the
various devices. I would be glad to change the authorship
for any of the patches if needed.

[1] https://lkml.org/lkml/2016/4/24/103
[2] git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git char-misc-next

Rajendra Nayak (11):
  thermal: qcom: tsens: Add a skeletal TSENS drivers
  thermal: qcom: tsens-8916: Add support for 8916 family of SoCs
  thermal: qcom: tsens-8974: Add support for 8974 family of SoCs
  thermal: core: export apis to get slope and offset
  thermal: qcom: tsens-8960: Add support for 8960 family of SoCs
  thermal: qcom: tsens-8996: Add support for 8996 family of SoCs
  arm: dts: msm8974: Add thermal zones, tsens and qfprom nodes
  arm: dts: apq8064: Add thermal zones, tsens and qfprom nodes
  arm: dts: apq8084: Add thermal zones, tsens and qfprom nodes
  arm64: dts: msm8916: Add thermal zones, tsens and qfprom nodes
  arm64: dts: msm8996: Add thermal zones, tsens and qfprom nodes

 .../devicetree/bindings/clock/qcom,gcc.txt         |  18 ++
 .../devicetree/bindings/thermal/qcom-tsens.txt     |  21 ++
 Documentation/thermal/sysfs-api.txt                |  12 +
 arch/arm/boot/dts/qcom-apq8064.dtsi                | 103 ++++++++
 arch/arm/boot/dts/qcom-apq8084.dtsi                | 103 ++++++++
 arch/arm/boot/dts/qcom-msm8974.dtsi                | 103 ++++++++
 arch/arm64/boot/dts/qcom/msm8916.dtsi              |  64 +++++
 arch/arm64/boot/dts/qcom/msm8996.dtsi              |  92 +++++++
 drivers/thermal/Kconfig                            |   5 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/qcom/Kconfig                       |  11 +
 drivers/thermal/qcom/Makefile                      |   2 +
 drivers/thermal/qcom/tsens-8916.c                  | 113 ++++++++
 drivers/thermal/qcom/tsens-8960.c                  | 292 +++++++++++++++++++++
 drivers/thermal/qcom/tsens-8974.c                  | 244 +++++++++++++++++
 drivers/thermal/qcom/tsens-8996.c                  |  84 ++++++
 drivers/thermal/qcom/tsens-common.c                | 141 ++++++++++
 drivers/thermal/qcom/tsens.c                       | 200 ++++++++++++++
 drivers/thermal/qcom/tsens.h                       |  92 +++++++
 drivers/thermal/thermal_core.c                     |  30 +++
 include/linux/thermal.h                            |   8 +
 21 files changed, 1739 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/qcom-tsens.txt
 create mode 100644 drivers/thermal/qcom/Kconfig
 create mode 100644 drivers/thermal/qcom/Makefile
 create mode 100644 drivers/thermal/qcom/tsens-8916.c
 create mode 100644 drivers/thermal/qcom/tsens-8960.c
 create mode 100644 drivers/thermal/qcom/tsens-8974.c
 create mode 100644 drivers/thermal/qcom/tsens-8996.c
 create mode 100644 drivers/thermal/qcom/tsens-common.c
 create mode 100644 drivers/thermal/qcom/tsens.c
 create mode 100644 drivers/thermal/qcom/tsens.h

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



From rnayak at codeaurora.org  Thu May  5 01:51:39 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu,  5 May 2016 14:21:39 +0530
Subject: [PATCH v6 01/11] thermal: qcom: tsens: Add a skeletal TSENS drivers
In-Reply-To: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
References: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
Message-ID: <1462438309-11196-2-git-send-email-rnayak@codeaurora.org>

TSENS is Qualcomms' thermal temperature sensor device. It
supports reading temperatures from multiple thermal sensors
present on various QCOM SoCs.
Calibration data is generally read from a non-volatile memory
(eeprom) device.

Add a skeleton driver with all the necessary abstractions so
a variety of qcom device families which support TSENS can
add driver extensions.

Also add the required device tree bindings which can be used
to describe the TSENS device in DT.

Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
Reviewed-by: Lina Iyer <lina.iyer at linaro.org>
---
 .../devicetree/bindings/thermal/qcom-tsens.txt     |  21 +++
 drivers/thermal/Kconfig                            |   5 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/qcom/Kconfig                       |  11 ++
 drivers/thermal/qcom/Makefile                      |   2 +
 drivers/thermal/qcom/tsens-common.c                | 141 +++++++++++++++
 drivers/thermal/qcom/tsens.c                       | 195 +++++++++++++++++++++
 drivers/thermal/qcom/tsens.h                       |  90 ++++++++++
 8 files changed, 466 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/qcom-tsens.txt
 create mode 100644 drivers/thermal/qcom/Kconfig
 create mode 100644 drivers/thermal/qcom/Makefile
 create mode 100644 drivers/thermal/qcom/tsens-common.c
 create mode 100644 drivers/thermal/qcom/tsens.c
 create mode 100644 drivers/thermal/qcom/tsens.h

diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
new file mode 100644
index 0000000..292ed89
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
@@ -0,0 +1,21 @@
+* QCOM SoC Temperature Sensor (TSENS)
+
+Required properties:
+- compatible :
+ - "qcom,msm8916-tsens" : For 8916 Family of SoCs
+ - "qcom,msm8974-tsens" : For 8974 Family of SoCs
+ - "qcom,msm8996-tsens" : For 8996 Family of SoCs
+
+- reg: Address range of the thermal registers
+- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
+- Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify
+nvmem cells
+
+Example:
+tsens: thermal-sensor at 900000 {
+		compatible = "qcom,msm8916-tsens";
+		reg = <0x4a8000 0x2000>;
+		nvmem-cells = <&tsens_caldata>, <&tsens_calsel>;
+		nvmem-cell-names = "caldata", "calsel";
+		#thermal-sensor-cells = <1>;
+	};
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 3c3dc4a..04d562d 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -410,4 +410,9 @@ config QCOM_SPMI_TEMP_ALARM
 	  real time die temperature if an ADC is present or an estimate of the
 	  temperature based upon the over temperature stage value.
 
+menu "Qualcomm thermal drivers"
+depends on (ARCH_QCOM && OF) || COMPILE_TEST
+source "drivers/thermal/qcom/Kconfig"
+endmenu
+
 endif
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 8e9cbc3..3f3e72c 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_TI_SOC_THERMAL)	+= ti-soc-thermal/
 obj-$(CONFIG_INT340X_THERMAL)  += int340x_thermal/
 obj-$(CONFIG_INTEL_PCH_THERMAL)	+= intel_pch_thermal.o
 obj-$(CONFIG_ST_THERMAL)	+= st/
+obj-$(CONFIG_QCOM_TSENS)	+= qcom/
 obj-$(CONFIG_TEGRA_SOCTHERM)	+= tegra_soctherm.o
 obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
 obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig
new file mode 100644
index 0000000..be32e5a
--- /dev/null
+++ b/drivers/thermal/qcom/Kconfig
@@ -0,0 +1,11 @@
+config QCOM_TSENS
+	tristate "Qualcomm TSENS Temperature Alarm"
+	depends on THERMAL
+	depends on QCOM_QFPROM
+	depends on ARCH_QCOM || COMPILE_TEST
+	help
+	  This enables the thermal sysfs driver for the TSENS device. It shows
+	  up in Sysfs as a thermal zone with multiple trip points. Disabling the
+	  thermal zone device via the mode file results in disabling the sensor.
+	  Also able to set threshold temperature for both hot and cold and update
+	  when a threshold is reached.
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
new file mode 100644
index 0000000..2e800c5
--- /dev/null
+++ b/drivers/thermal/qcom/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
+qcom_tsens-y			+= tsens.o tsens-common.o
diff --git a/drivers/thermal/qcom/tsens-common.c b/drivers/thermal/qcom/tsens-common.c
new file mode 100644
index 0000000..4a1af15
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-common.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include "tsens.h"
+
+#define S0_ST_ADDR		0x1030
+#define SN_ADDR_OFFSET		0x4
+#define SN_ST_TEMP_MASK		0x3ff
+#define CAL_DEGC_PT1		30
+#define CAL_DEGC_PT2		120
+#define SLOPE_FACTOR		1000
+#define SLOPE_DEFAULT		3200
+
+char *qfprom_read(struct device *dev, const char *cname)
+{
+	struct nvmem_cell *cell;
+	ssize_t data;
+	char *ret;
+
+	cell = nvmem_cell_get(dev, cname);
+	if (IS_ERR(cell))
+		return ERR_CAST(cell);
+
+	ret = nvmem_cell_read(cell, &data);
+	nvmem_cell_put(cell);
+
+	return ret;
+}
+
+/*
+ * Use this function on devices where slope and offset calculations
+ * depend on calibration data read from qfprom. On others the slope
+ * and offset values are derived from tz->tzp->slope and tz->tzp->offset
+ * resp.
+ */
+void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
+			     u32 *p2, u32 mode)
+{
+	int i;
+	int num, den;
+
+	for (i = 0; i < tmdev->num_sensors; i++) {
+		dev_dbg(tmdev->dev,
+			"sensor%d - data_point1:%#x data_point2:%#x\n",
+			i, p1[i], p2[i]);
+
+		tmdev->sensor[i].slope = SLOPE_DEFAULT;
+		if (mode == TWO_PT_CALIB) {
+			/*
+			 * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
+			 *	temp_120_degc - temp_30_degc (x2 - x1)
+			 */
+			num = p2[i] - p1[i];
+			num *= SLOPE_FACTOR;
+			den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
+			tmdev->sensor[i].slope = num / den;
+		}
+
+		tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
+				(CAL_DEGC_PT1 *
+				tmdev->sensor[i].slope);
+		dev_dbg(tmdev->dev, "offset:%d\n", tmdev->sensor[i].offset);
+	}
+}
+
+static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
+{
+	int degc, num, den;
+
+	num = (adc_code * SLOPE_FACTOR) - s->offset;
+	den = s->slope;
+
+	if (num > 0)
+		degc = num + (den / 2);
+	else if (num < 0)
+		degc = num - (den / 2);
+	else
+		degc = num;
+
+	degc /= den;
+
+	return degc;
+}
+
+int get_temp_common(struct tsens_device *tmdev, int id, int *temp)
+{
+	struct tsens_sensor *s = &tmdev->sensor[id];
+	u32 code;
+	unsigned int sensor_addr;
+	int last_temp = 0, ret;
+
+	sensor_addr = S0_ST_ADDR + s->hw_id * SN_ADDR_OFFSET;
+	ret = regmap_read(tmdev->map, sensor_addr, &code);
+	if (ret)
+		return ret;
+	last_temp = code & SN_ST_TEMP_MASK;
+
+	*temp = code_to_degc(last_temp, s) * 1000;
+
+	return 0;
+}
+
+static const struct regmap_config tsens_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+};
+
+int __init init_common(struct tsens_device *tmdev)
+{
+	void __iomem *base;
+
+	base = of_iomap(tmdev->dev->of_node, 0);
+	if (IS_ERR(base))
+		return -EINVAL;
+
+	tmdev->map = devm_regmap_init_mmio(tmdev->dev, base, &tsens_config);
+	if (!tmdev->map) {
+		iounmap(base);
+		return -ENODEV;
+	}
+
+	return 0;
+}
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
new file mode 100644
index 0000000..17d7b55
--- /dev/null
+++ b/drivers/thermal/qcom/tsens.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/thermal.h>
+#include "tsens.h"
+
+static int tsens_get_temp(void *data, int *temp)
+{
+	const struct tsens_sensor *s = data;
+	struct tsens_device *tmdev = s->tmdev;
+
+	return tmdev->ops->get_temp(tmdev, s->id, temp);
+}
+
+static int tsens_get_trend(void *data, long *temp)
+{
+	const struct tsens_sensor *s = data;
+	struct tsens_device *tmdev = s->tmdev;
+
+	if (tmdev->ops->get_trend)
+		return tmdev->ops->get_trend(tmdev, s->id, temp);
+
+	return -ENOTSUPP;
+}
+
+static int tsens_suspend(struct device *dev)
+{
+	struct tsens_device *tmdev = dev_get_drvdata(dev);
+
+	if (tmdev->ops && tmdev->ops->suspend)
+		return tmdev->ops->suspend(tmdev);
+
+	return 0;
+}
+
+static int tsens_resume(struct device *dev)
+{
+	struct tsens_device *tmdev = dev_get_drvdata(dev);
+
+	if (tmdev->ops && tmdev->ops->resume)
+		return tmdev->ops->resume(tmdev);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume);
+
+static const struct of_device_id tsens_table[] = {
+	{
+		.compatible = "qcom,msm8916-tsens",
+	}, {
+		.compatible = "qcom,msm8974-tsens",
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, tsens_table);
+
+static const struct thermal_zone_of_device_ops tsens_of_ops = {
+	.get_temp = tsens_get_temp,
+	.get_trend = tsens_get_trend,
+};
+
+static int tsens_register(struct tsens_device *tmdev)
+{
+	int i;
+	struct thermal_zone_device *tzd;
+	u32 *hw_id, n = tmdev->num_sensors;
+
+	hw_id = devm_kcalloc(tmdev->dev, n, sizeof(u32), GFP_KERNEL);
+	if (!hw_id)
+		return -ENOMEM;
+
+	for (i = 0;  i < tmdev->num_sensors; i++) {
+		tmdev->sensor[i].tmdev = tmdev;
+		tmdev->sensor[i].id = i;
+		tzd = devm_thermal_zone_of_sensor_register(tmdev->dev, i,
+							   &tmdev->sensor[i],
+							   &tsens_of_ops);
+		if (IS_ERR(tzd))
+			continue;
+		tmdev->sensor[i].tzd = tzd;
+		if (tmdev->ops->enable)
+			tmdev->ops->enable(tmdev, i);
+	}
+	return 0;
+}
+
+static int tsens_probe(struct platform_device *pdev)
+{
+	int ret, i;
+	struct device *dev;
+	struct device_node *np;
+	struct tsens_sensor *s;
+	struct tsens_device *tmdev;
+	const struct tsens_data *data;
+	const struct of_device_id *id;
+
+	if (pdev->dev.of_node)
+		dev = &pdev->dev;
+	else
+		dev = pdev->dev.parent;
+
+	np = dev->of_node;
+
+	id = of_match_node(tsens_table, np);
+	if (!id)
+		return -EINVAL;
+
+	data = id->data;
+
+	if (data->num_sensors <= 0) {
+		dev_err(dev, "invalid number of sensors\n");
+		return -EINVAL;
+	}
+
+	tmdev = devm_kzalloc(dev, sizeof(*tmdev) +
+			     data->num_sensors * sizeof(*s), GFP_KERNEL);
+	if (!tmdev)
+		return -ENOMEM;
+
+	tmdev->dev = dev;
+	tmdev->num_sensors = data->num_sensors;
+	tmdev->ops = data->ops;
+	for (i = 0;  i < tmdev->num_sensors; i++) {
+		if (data->hw_ids)
+			tmdev->sensor[i].hw_id = data->hw_ids[i];
+		else
+			tmdev->sensor[i].hw_id = i;
+	}
+
+	if (!tmdev->ops || !tmdev->ops->init || !tmdev->ops->get_temp)
+		return -EINVAL;
+
+	ret = tmdev->ops->init(tmdev);
+	if (ret < 0) {
+		dev_err(dev, "tsens init failed\n");
+		return ret;
+	}
+
+	if (tmdev->ops->calibrate) {
+		ret = tmdev->ops->calibrate(tmdev);
+		if (ret < 0) {
+			dev_err(dev, "tsens calibration failed\n");
+			return ret;
+		}
+	}
+
+	ret = tsens_register(tmdev);
+
+	platform_set_drvdata(pdev, tmdev);
+
+	return ret;
+}
+
+static int tsens_remove(struct platform_device *pdev)
+{
+	struct tsens_device *tmdev = platform_get_drvdata(pdev);
+
+	if (tmdev->ops->disable)
+		tmdev->ops->disable(tmdev);
+
+	return 0;
+}
+
+static struct platform_driver tsens_driver = {
+	.probe = tsens_probe,
+	.remove = tsens_remove,
+	.driver = {
+		.name = "qcom-tsens",
+		.pm	= &tsens_pm_ops,
+		.of_match_table = tsens_table,
+	},
+};
+module_platform_driver(tsens_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("QCOM Temperature Sensor driver");
+MODULE_ALIAS("platform:qcom-tsens");
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
new file mode 100644
index 0000000..3b1b6ae
--- /dev/null
+++ b/drivers/thermal/qcom/tsens.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __QCOM_TSENS_H__
+#define __QCOM_TSENS_H__
+
+#define ONE_PT_CALIB		0x1
+#define ONE_PT_CALIB2		0x2
+#define TWO_PT_CALIB		0x3
+
+struct tsens_device;
+
+struct tsens_sensor {
+	struct tsens_device		*tmdev;
+	struct thermal_zone_device	*tzd;
+	int				offset;
+	int				id;
+	int				hw_id;
+	int				slope;
+	u32				status;
+};
+
+/**
+ * struct tsens_ops - operations as supported by the tsens device
+ * @init: Function to initialize the tsens device
+ * @calibrate: Function to calibrate the tsens device
+ * @get_temp: Function which returns the temp in millidegC
+ * @enable: Function to enable (clocks/power) tsens device
+ * @disable: Function to disable the tsens device
+ * @suspend: Function to suspend the tsens device
+ * @resume: Function to resume the tsens device
+ * @get_trend: Function to get the thermal/temp trend
+ */
+struct tsens_ops {
+	/* mandatory callbacks */
+	int (*init)(struct tsens_device *);
+	int (*calibrate)(struct tsens_device *);
+	int (*get_temp)(struct tsens_device *, int, int *);
+	/* optional callbacks */
+	int (*enable)(struct tsens_device *, int);
+	void (*disable)(struct tsens_device *);
+	int (*suspend)(struct tsens_device *);
+	int (*resume)(struct tsens_device *);
+	int (*get_trend)(struct tsens_device *, int, long *);
+};
+
+/**
+ * struct tsens_data - tsens instance specific data
+ * @num_sensors: Max number of sensors supported by platform
+ * @ops: operations the tsens instance supports
+ * @hw_ids: Subset of sensors ids supported by platform, if not the first n
+ */
+struct tsens_data {
+	const u32		num_sensors;
+	const struct tsens_ops	*ops;
+	unsigned int		*hw_ids;
+};
+
+/* Registers to be saved/restored across a context loss */
+struct tsens_context {
+	int	threshold;
+	int	control;
+};
+
+struct tsens_device {
+	struct device			*dev;
+	u32				num_sensors;
+	struct regmap			*map;
+	struct regmap_field		*status_field;
+	struct tsens_context		ctx;
+	bool				trdy;
+	const struct tsens_ops		*ops;
+	struct tsens_sensor		sensor[0];
+};
+
+char *qfprom_read(struct device *, const char *);
+void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
+int init_common(struct tsens_device *);
+int get_temp_common(struct tsens_device *, int, int *);
+
+#endif /* __QCOM_TSENS_H__ */
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



From rnayak at codeaurora.org  Thu May  5 01:51:40 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu,  5 May 2016 14:21:40 +0530
Subject: [PATCH v6 02/11] thermal: qcom: tsens-8916: Add support for 8916
 family of SoCs
In-Reply-To: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
References: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
Message-ID: <1462438309-11196-3-git-send-email-rnayak@codeaurora.org>

Add support to calibrate sensors on 8916 family and also add common
functions to read temperature from sensors (This can be reused on
other SoCs having similar TSENS device)
The calibration data is read from eeprom using the generic nvmem
framework apis.

Based on the original code by Siddartha Mohanadoss and Stephen Boyd.

Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
---
 drivers/thermal/qcom/Makefile     |   2 +-
 drivers/thermal/qcom/tsens-8916.c | 113 ++++++++++++++++++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c      |   1 +
 drivers/thermal/qcom/tsens.h      |   2 +
 4 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 drivers/thermal/qcom/tsens-8916.c

diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index 2e800c5..05c98e4 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
-qcom_tsens-y			+= tsens.o tsens-common.o
+qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o
diff --git a/drivers/thermal/qcom/tsens-8916.c b/drivers/thermal/qcom/tsens-8916.c
new file mode 100644
index 0000000..beb3afa
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-8916.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include "tsens.h"
+
+/* eeprom layout data for 8916 */
+#define BASE0_MASK	0x0000007f
+#define BASE1_MASK	0xfe000000
+#define BASE0_SHIFT	0
+#define BASE1_SHIFT	25
+
+#define S0_P1_MASK	0x00000f80
+#define S1_P1_MASK	0x003e0000
+#define S2_P1_MASK	0xf8000000
+#define S3_P1_MASK	0x000003e0
+#define S4_P1_MASK	0x000f8000
+
+#define S0_P2_MASK	0x0001f000
+#define S1_P2_MASK	0x07c00000
+#define S2_P2_MASK	0x0000001f
+#define S3_P2_MASK	0x00007c00
+#define S4_P2_MASK	0x01f00000
+
+#define S0_P1_SHIFT	7
+#define S1_P1_SHIFT	17
+#define S2_P1_SHIFT	27
+#define S3_P1_SHIFT	5
+#define S4_P1_SHIFT	15
+
+#define S0_P2_SHIFT	12
+#define S1_P2_SHIFT	22
+#define S2_P2_SHIFT	0
+#define S3_P2_SHIFT	10
+#define S4_P2_SHIFT	20
+
+#define CAL_SEL_MASK	0xe0000000
+#define CAL_SEL_SHIFT	29
+
+static int calibrate_8916(struct tsens_device *tmdev)
+{
+	int base0 = 0, base1 = 0, i;
+	u32 p1[5], p2[5];
+	int mode = 0;
+	u32 *qfprom_cdata, *qfprom_csel;
+
+	qfprom_cdata = (u32 *)qfprom_read(tmdev->dev, "calib");
+	if (IS_ERR(qfprom_cdata))
+		return PTR_ERR(qfprom_cdata);
+
+	qfprom_csel = (u32 *)qfprom_read(tmdev->dev, "calib_sel");
+	if (IS_ERR(qfprom_csel))
+		return PTR_ERR(qfprom_csel);
+
+	mode = (qfprom_csel[0] & CAL_SEL_MASK) >> CAL_SEL_SHIFT;
+	dev_dbg(tmdev->dev, "calibration mode is %d\n", mode);
+
+	switch (mode) {
+	case TWO_PT_CALIB:
+		base1 = (qfprom_cdata[1] & BASE1_MASK) >> BASE1_SHIFT;
+		p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT;
+		p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT;
+		p2[2] = (qfprom_cdata[1] & S2_P2_MASK) >> S2_P2_SHIFT;
+		p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT;
+		p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT;
+		for (i = 0; i < tmdev->num_sensors; i++)
+			p2[i] = ((base1 + p2[i]) << 3);
+		/* Fall through */
+	case ONE_PT_CALIB2:
+		base0 = (qfprom_cdata[0] & BASE0_MASK);
+		p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT;
+		p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT;
+		p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT;
+		p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT;
+		p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT;
+		for (i = 0; i < tmdev->num_sensors; i++)
+			p1[i] = (((base0) + p1[i]) << 3);
+		break;
+	default:
+		for (i = 0; i < tmdev->num_sensors; i++) {
+			p1[i] = 500;
+			p2[i] = 780;
+		}
+		break;
+	}
+
+	compute_intercept_slope(tmdev, p1, p2, mode);
+
+	return 0;
+}
+
+const struct tsens_ops ops_8916 = {
+	.init		= init_common,
+	.calibrate	= calibrate_8916,
+	.get_temp	= get_temp_common,
+};
+
+const struct tsens_data data_8916 = {
+	.num_sensors	= 5,
+	.ops		= &ops_8916,
+	.hw_ids		= (unsigned int []){0, 1, 2, 4, 5 },
+};
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 17d7b55..7f3dfa1 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -65,6 +65,7 @@ static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume);
 static const struct of_device_id tsens_table[] = {
 	{
 		.compatible = "qcom,msm8916-tsens",
+		.data = &data_8916,
 	}, {
 		.compatible = "qcom,msm8974-tsens",
 	},
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 3b1b6ae..e767ad5 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -87,4 +87,6 @@ void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
 int init_common(struct tsens_device *);
 int get_temp_common(struct tsens_device *, int, int *);
 
+extern const struct tsens_data data_8916;
+
 #endif /* __QCOM_TSENS_H__ */
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



From rnayak at codeaurora.org  Thu May  5 01:51:41 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu,  5 May 2016 14:21:41 +0530
Subject: [PATCH v6 03/11] thermal: qcom: tsens-8974: Add support for 8974
 family of SoCs
In-Reply-To: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
References: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
Message-ID: <1462438309-11196-4-git-send-email-rnayak@codeaurora.org>

Add .calibrate support for 8974 family as part of tsens_ops.

Based on the original code by Siddartha Mohanadoss and Stephen Boyd.

Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
---
 drivers/thermal/qcom/Makefile     |   2 +-
 drivers/thermal/qcom/tsens-8974.c | 244 ++++++++++++++++++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c      |   1 +
 drivers/thermal/qcom/tsens.h      |   2 +-
 4 files changed, 247 insertions(+), 2 deletions(-)
 create mode 100644 drivers/thermal/qcom/tsens-8974.c

diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index 05c98e4..a471100 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
-qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o
+qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o
diff --git a/drivers/thermal/qcom/tsens-8974.c b/drivers/thermal/qcom/tsens-8974.c
new file mode 100644
index 0000000..da3ca4c
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-8974.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include "tsens.h"
+
+/* eeprom layout data for 8974 */
+#define BASE1_MASK		0xff
+#define S0_P1_MASK		0x3f00
+#define S1_P1_MASK		0xfc000
+#define S2_P1_MASK		0x3f00000
+#define S3_P1_MASK		0xfc000000
+#define S4_P1_MASK		0x3f
+#define S5_P1_MASK		0xfc0
+#define S6_P1_MASK		0x3f000
+#define S7_P1_MASK		0xfc0000
+#define S8_P1_MASK		0x3f000000
+#define S8_P1_MASK_BKP		0x3f
+#define S9_P1_MASK		0x3f
+#define S9_P1_MASK_BKP		0xfc0
+#define S10_P1_MASK		0xfc0
+#define S10_P1_MASK_BKP		0x3f000
+#define CAL_SEL_0_1		0xc0000000
+#define CAL_SEL_2		0x40000000
+#define CAL_SEL_SHIFT		30
+#define CAL_SEL_SHIFT_2		28
+
+#define S0_P1_SHIFT		8
+#define S1_P1_SHIFT		14
+#define S2_P1_SHIFT		20
+#define S3_P1_SHIFT		26
+#define S5_P1_SHIFT		6
+#define S6_P1_SHIFT		12
+#define S7_P1_SHIFT		18
+#define S8_P1_SHIFT		24
+#define S9_P1_BKP_SHIFT		6
+#define S10_P1_SHIFT		6
+#define S10_P1_BKP_SHIFT	12
+
+#define BASE2_SHIFT		12
+#define BASE2_BKP_SHIFT		18
+#define S0_P2_SHIFT		20
+#define S0_P2_BKP_SHIFT		26
+#define S1_P2_SHIFT		26
+#define S2_P2_BKP_SHIFT		6
+#define S3_P2_SHIFT		6
+#define S3_P2_BKP_SHIFT		12
+#define S4_P2_SHIFT		12
+#define S4_P2_BKP_SHIFT		18
+#define S5_P2_SHIFT		18
+#define S5_P2_BKP_SHIFT		24
+#define S6_P2_SHIFT		24
+#define S7_P2_BKP_SHIFT		6
+#define S8_P2_SHIFT		6
+#define S8_P2_BKP_SHIFT		12
+#define S9_P2_SHIFT		12
+#define S9_P2_BKP_SHIFT		18
+#define S10_P2_SHIFT		18
+#define S10_P2_BKP_SHIFT	24
+
+#define BASE2_MASK		0xff000
+#define BASE2_BKP_MASK		0xfc0000
+#define S0_P2_MASK		0x3f00000
+#define S0_P2_BKP_MASK		0xfc000000
+#define S1_P2_MASK		0xfc000000
+#define S1_P2_BKP_MASK		0x3f
+#define S2_P2_MASK		0x3f
+#define S2_P2_BKP_MASK		0xfc0
+#define S3_P2_MASK		0xfc0
+#define S3_P2_BKP_MASK		0x3f000
+#define S4_P2_MASK		0x3f000
+#define S4_P2_BKP_MASK		0xfc0000
+#define S5_P2_MASK		0xfc0000
+#define S5_P2_BKP_MASK		0x3f000000
+#define S6_P2_MASK		0x3f000000
+#define S6_P2_BKP_MASK		0x3f
+#define S7_P2_MASK		0x3f
+#define S7_P2_BKP_MASK		0xfc0
+#define S8_P2_MASK		0xfc0
+#define S8_P2_BKP_MASK		0x3f000
+#define S9_P2_MASK		0x3f000
+#define S9_P2_BKP_MASK		0xfc0000
+#define S10_P2_MASK		0xfc0000
+#define S10_P2_BKP_MASK		0x3f000000
+
+#define BKP_SEL			0x3
+#define BKP_REDUN_SEL		0xe0000000
+#define BKP_REDUN_SHIFT		29
+
+#define BIT_APPEND		0x3
+
+static int calibrate_8974(struct tsens_device *tmdev)
+{
+	int base1 = 0, base2 = 0, i;
+	u32 p1[11], p2[11];
+	int mode = 0;
+	u32 *calib, *bkp;
+	u32 calib_redun_sel;
+
+	calib = (u32 *)qfprom_read(tmdev->dev, "calib");
+	if (IS_ERR(calib))
+		return PTR_ERR(calib);
+
+	bkp = (u32 *)qfprom_read(tmdev->dev, "calib_backup");
+	if (IS_ERR(bkp))
+		return PTR_ERR(bkp);
+
+	calib_redun_sel =  bkp[1] & BKP_REDUN_SEL;
+	calib_redun_sel >>= BKP_REDUN_SHIFT;
+
+	if (calib_redun_sel == BKP_SEL) {
+		mode = (calib[4] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
+		mode |= (calib[5] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
+
+		switch (mode) {
+		case TWO_PT_CALIB:
+			base2 = (bkp[2] & BASE2_BKP_MASK) >> BASE2_BKP_SHIFT;
+			p2[0] = (bkp[2] & S0_P2_BKP_MASK) >> S0_P2_BKP_SHIFT;
+			p2[1] = (bkp[3] & S1_P2_BKP_MASK);
+			p2[2] = (bkp[3] & S2_P2_BKP_MASK) >> S2_P2_BKP_SHIFT;
+			p2[3] = (bkp[3] & S3_P2_BKP_MASK) >> S3_P2_BKP_SHIFT;
+			p2[4] = (bkp[3] & S4_P2_BKP_MASK) >> S4_P2_BKP_SHIFT;
+			p2[5] = (calib[4] & S5_P2_BKP_MASK) >> S5_P2_BKP_SHIFT;
+			p2[6] = (calib[5] & S6_P2_BKP_MASK);
+			p2[7] = (calib[5] & S7_P2_BKP_MASK) >> S7_P2_BKP_SHIFT;
+			p2[8] = (calib[5] & S8_P2_BKP_MASK) >> S8_P2_BKP_SHIFT;
+			p2[9] = (calib[5] & S9_P2_BKP_MASK) >> S9_P2_BKP_SHIFT;
+			p2[10] = (calib[5] & S10_P2_BKP_MASK) >> S10_P2_BKP_SHIFT;
+			/* Fall through */
+		case ONE_PT_CALIB:
+		case ONE_PT_CALIB2:
+			base1 = bkp[0] & BASE1_MASK;
+			p1[0] = (bkp[0] & S0_P1_MASK) >> S0_P1_SHIFT;
+			p1[1] = (bkp[0] & S1_P1_MASK) >> S1_P1_SHIFT;
+			p1[2] = (bkp[0] & S2_P1_MASK) >> S2_P1_SHIFT;
+			p1[3] = (bkp[0] & S3_P1_MASK) >> S3_P1_SHIFT;
+			p1[4] = (bkp[1] & S4_P1_MASK);
+			p1[5] = (bkp[1] & S5_P1_MASK) >> S5_P1_SHIFT;
+			p1[6] = (bkp[1] & S6_P1_MASK) >> S6_P1_SHIFT;
+			p1[7] = (bkp[1] & S7_P1_MASK) >> S7_P1_SHIFT;
+			p1[8] = (bkp[2] & S8_P1_MASK_BKP) >> S8_P1_SHIFT;
+			p1[9] = (bkp[2] & S9_P1_MASK_BKP) >> S9_P1_BKP_SHIFT;
+			p1[10] = (bkp[2] & S10_P1_MASK_BKP) >> S10_P1_BKP_SHIFT;
+			break;
+		}
+	} else {
+		mode = (calib[1] & CAL_SEL_0_1) >> CAL_SEL_SHIFT;
+		mode |= (calib[3] & CAL_SEL_2) >> CAL_SEL_SHIFT_2;
+
+		switch (mode) {
+		case TWO_PT_CALIB:
+			base2 = (calib[2] & BASE2_MASK) >> BASE2_SHIFT;
+			p2[0] = (calib[2] & S0_P2_MASK) >> S0_P2_SHIFT;
+			p2[1] = (calib[2] & S1_P2_MASK) >> S1_P2_SHIFT;
+			p2[2] = (calib[3] & S2_P2_MASK);
+			p2[3] = (calib[3] & S3_P2_MASK) >> S3_P2_SHIFT;
+			p2[4] = (calib[3] & S4_P2_MASK) >> S4_P2_SHIFT;
+			p2[5] = (calib[3] & S5_P2_MASK) >> S5_P2_SHIFT;
+			p2[6] = (calib[3] & S6_P2_MASK) >> S6_P2_SHIFT;
+			p2[7] = (calib[4] & S7_P2_MASK);
+			p2[8] = (calib[4] & S8_P2_MASK) >> S8_P2_SHIFT;
+			p2[9] = (calib[4] & S9_P2_MASK) >> S9_P2_SHIFT;
+			p2[10] = (calib[4] & S10_P2_MASK) >> S10_P2_SHIFT;
+			/* Fall through */
+		case ONE_PT_CALIB:
+		case ONE_PT_CALIB2:
+			base1 = calib[0] & BASE1_MASK;
+			p1[0] = (calib[0] & S0_P1_MASK) >> S0_P1_SHIFT;
+			p1[1] = (calib[0] & S1_P1_MASK) >> S1_P1_SHIFT;
+			p1[2] = (calib[0] & S2_P1_MASK) >> S2_P1_SHIFT;
+			p1[3] = (calib[0] & S3_P1_MASK) >> S3_P1_SHIFT;
+			p1[4] = (calib[1] & S4_P1_MASK);
+			p1[5] = (calib[1] & S5_P1_MASK) >> S5_P1_SHIFT;
+			p1[6] = (calib[1] & S6_P1_MASK) >> S6_P1_SHIFT;
+			p1[7] = (calib[1] & S7_P1_MASK) >> S7_P1_SHIFT;
+			p1[8] = (calib[1] & S8_P1_MASK) >> S8_P1_SHIFT;
+			p1[9] = (calib[2] & S9_P1_MASK);
+			p1[10] = (calib[2] & S10_P1_MASK) >> S10_P1_SHIFT;
+			break;
+		}
+	}
+
+	switch (mode) {
+	case ONE_PT_CALIB:
+		for (i = 0; i < tmdev->num_sensors; i++)
+			p1[i] += (base1 << 2) | BIT_APPEND;
+		break;
+	case TWO_PT_CALIB:
+		for (i = 0; i < tmdev->num_sensors; i++) {
+			p2[i] += base2;
+			p2[i] <<= 2;
+			p2[i] |= BIT_APPEND;
+		}
+		/* Fall through */
+	case ONE_PT_CALIB2:
+		for (i = 0; i < tmdev->num_sensors; i++) {
+			p1[i] += base1;
+			p1[i] <<= 2;
+			p1[i] |= BIT_APPEND;
+		}
+		break;
+	default:
+		for (i = 0; i < tmdev->num_sensors; i++)
+			p2[i] = 780;
+		p1[0] = 502;
+		p1[1] = 509;
+		p1[2] = 503;
+		p1[3] = 509;
+		p1[4] = 505;
+		p1[5] = 509;
+		p1[6] = 507;
+		p1[7] = 510;
+		p1[8] = 508;
+		p1[9] = 509;
+		p1[10] = 508;
+		break;
+	}
+
+	compute_intercept_slope(tmdev, p1, p2, mode);
+
+	return 0;
+}
+
+const struct tsens_ops ops_8974 = {
+	.init		= init_common,
+	.calibrate	= calibrate_8974,
+	.get_temp	= get_temp_common,
+};
+
+const struct tsens_data data_8974 = {
+	.num_sensors	= 11,
+	.ops		= &ops_8974,
+};
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 7f3dfa1..5f206e3 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -68,6 +68,7 @@ static const struct of_device_id tsens_table[] = {
 		.data = &data_8916,
 	}, {
 		.compatible = "qcom,msm8974-tsens",
+		.data = &data_8974,
 	},
 	{}
 };
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index e767ad5..8ab9997 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -87,6 +87,6 @@ void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
 int init_common(struct tsens_device *);
 int get_temp_common(struct tsens_device *, int, int *);
 
-extern const struct tsens_data data_8916;
+extern const struct tsens_data data_8916, data_8974;
 
 #endif /* __QCOM_TSENS_H__ */
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



From rnayak at codeaurora.org  Thu May  5 01:51:42 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu,  5 May 2016 14:21:42 +0530
Subject: [PATCH v6 04/11] thermal: core: export apis to get slope and offset
In-Reply-To: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
References: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
Message-ID: <1462438309-11196-5-git-send-email-rnayak@codeaurora.org>

Add apis for platform thermal drivers to query for slope and offset
attributes, which might be needed for temperature calculations.

Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
---
 Documentation/thermal/sysfs-api.txt | 12 ++++++++++++
 drivers/thermal/thermal_core.c      | 30 ++++++++++++++++++++++++++++++
 include/linux/thermal.h             |  8 ++++++++
 3 files changed, 50 insertions(+)

diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index ed419d6..3450cb0 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -140,6 +140,18 @@ temperature) and throttle appropriate devices.
 	Normally this function will not need to be called and the resource
 	management code will ensure that the resource is freed.
 
+1.1.7 int thermal_zone_get_slope(struct thermal_zone_device *tz)
+
+	This interface is used to read the slope attribute value
+	for the thermal zone device, which might be useful for platform
+	drivers for temperature calculations.
+
+1.1.8 int thermal_zone_get_offset(struct thermal_zone_device *tz)
+
+	This interface is used to read the offset attribute value
+	for the thermal zone device, which might be useful for platform
+	drivers for temperature calculations.
+
 1.2 thermal cooling device interface
 1.2.1 struct thermal_cooling_device *thermal_cooling_device_register(char *name,
 		void *devdata, struct thermal_cooling_device_ops *)
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 5133cd1..b118aae 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -2065,6 +2065,36 @@ exit:
 }
 EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
 
+/**
+ * thermal_zone_get_slope - return the slope attribute of the thermal zone
+ * @tz: thermal zone device with the slope attribute
+ *
+ * Return: If the thermal zone device has a slope attribute, return it, else
+ * return 1.
+ */
+int thermal_zone_get_slope(struct thermal_zone_device *tz)
+{
+	if (tz && tz->tzp)
+		return tz->tzp->slope;
+	return 1;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_slope);
+
+/**
+ * thermal_zone_get_offset - return the offset attribute of the thermal zone
+ * @tz: thermal zone device with the offset attribute
+ *
+ * Return: If the thermal zone device has a offset attribute, return it, else
+ * return 0.
+ */
+int thermal_zone_get_offset(struct thermal_zone_device *tz)
+{
+	if (tz && tz->tzp)
+		return tz->tzp->offset;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_get_offset);
+
 #ifdef CONFIG_NET
 static const struct genl_multicast_group thermal_event_mcgrps[] = {
 	{ .name = THERMAL_GENL_MCAST_GROUP_NAME, },
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 1b8a5a7..fd206b9 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -432,6 +432,8 @@ thermal_of_cooling_device_register(struct device_node *np, char *, void *,
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
 int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
+int thermal_zone_get_slope(struct thermal_zone_device *tz);
+int thermal_zone_get_offset(struct thermal_zone_device *tz);
 
 int get_tz_trend(struct thermal_zone_device *, int);
 struct thermal_instance *get_thermal_instance(struct thermal_zone_device *,
@@ -489,6 +491,12 @@ static inline struct thermal_zone_device *thermal_zone_get_zone_by_name(
 static inline int thermal_zone_get_temp(
 		struct thermal_zone_device *tz, int *temp)
 { return -ENODEV; }
+static inline int thermal_zone_get_slope(
+		struct thermal_zone_device *tz)
+{ return -ENODEV; }
+static inline int thermal_zone_get_offset(
+		struct thermal_zone_device *tz)
+{ return -ENODEV; }
 static inline int get_tz_trend(struct thermal_zone_device *tz, int trip)
 { return -ENODEV; }
 static inline struct thermal_instance *
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



From rnayak at codeaurora.org  Thu May  5 01:51:43 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu,  5 May 2016 14:21:43 +0530
Subject: [PATCH v6 05/11] thermal: qcom: tsens-8960: Add support for 8960
 family of SoCs
In-Reply-To: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
References: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
Message-ID: <1462438309-11196-6-git-send-email-rnayak@codeaurora.org>

8960 family of SoCs have the TSENS device as part of GCC, hence
the driver probes the virtual child device created by GCC and
uses the parent to extract all DT properties and reuses the GCC
regmap.

Also GCC/TSENS are part of a  domain thats not always ON.
Hence add .suspend and .resume hooks to save and restore some of
the inited register context.

Also 8960 family have some of the TSENS init sequence thats
required to be done by the HLOS driver (some later versions of TSENS
do not export these registers to non-secure world, and hence need
these initializations to be done by secure bootloaders)

8660 from the same family has just one sensor and hence some register
offset/layout differences which need special handling in the driver.

Based on the original code from Siddartha Mohanadoss, Stephen Boyd and
Narendran Rajan.

Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
---
 drivers/thermal/qcom/Makefile     |   2 +-
 drivers/thermal/qcom/tsens-8960.c | 292 ++++++++++++++++++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c      |   8 +-
 drivers/thermal/qcom/tsens.h      |   2 +-
 4 files changed, 298 insertions(+), 6 deletions(-)
 create mode 100644 drivers/thermal/qcom/tsens-8960.c

diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index a471100..f3cefd1 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
-qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o
+qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o
diff --git a/drivers/thermal/qcom/tsens-8960.c b/drivers/thermal/qcom/tsens-8960.c
new file mode 100644
index 0000000..1d60916
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-8960.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <linux/thermal.h>
+#include "tsens.h"
+
+#define CAL_MDEGC		30000
+
+#define CONFIG_ADDR		0x3640
+#define CONFIG_ADDR_8660	0x3620
+/* CONFIG_ADDR bitmasks */
+#define CONFIG			0x9b
+#define CONFIG_MASK		0xf
+#define CONFIG_8660		1
+#define CONFIG_SHIFT_8660	28
+#define CONFIG_MASK_8660	(3 << CONFIG_SHIFT_8660)
+
+#define STATUS_CNTL_ADDR_8064	0x3660
+#define CNTL_ADDR		0x3620
+/* CNTL_ADDR bitmasks */
+#define EN			BIT(0)
+#define SW_RST			BIT(1)
+#define SENSOR0_EN		BIT(3)
+#define SLP_CLK_ENA		BIT(26)
+#define SLP_CLK_ENA_8660	BIT(24)
+#define MEASURE_PERIOD		1
+#define SENSOR0_SHIFT		3
+
+/* INT_STATUS_ADDR bitmasks */
+#define MIN_STATUS_MASK		BIT(0)
+#define LOWER_STATUS_CLR	BIT(1)
+#define UPPER_STATUS_CLR	BIT(2)
+#define MAX_STATUS_MASK		BIT(3)
+
+#define THRESHOLD_ADDR		0x3624
+/* THRESHOLD_ADDR bitmasks */
+#define THRESHOLD_MAX_LIMIT_SHIFT	24
+#define THRESHOLD_MIN_LIMIT_SHIFT	16
+#define THRESHOLD_UPPER_LIMIT_SHIFT	8
+#define THRESHOLD_LOWER_LIMIT_SHIFT	0
+
+/* Initial temperature threshold values */
+#define LOWER_LIMIT_TH		0x50
+#define UPPER_LIMIT_TH		0xdf
+#define MIN_LIMIT_TH		0x0
+#define MAX_LIMIT_TH		0xff
+
+#define S0_STATUS_ADDR		0x3628
+#define INT_STATUS_ADDR		0x363c
+#define TRDY_MASK		BIT(7)
+#define TIMEOUT_US		100
+
+static int suspend_8960(struct tsens_device *tmdev)
+{
+	int ret;
+	unsigned int mask;
+	struct regmap *map = tmdev->map;
+
+	ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control);
+	if (ret)
+		return ret;
+
+	if (tmdev->num_sensors > 1)
+		mask = SLP_CLK_ENA | EN;
+	else
+		mask = SLP_CLK_ENA_8660 | EN;
+
+	ret = regmap_update_bits(map, CNTL_ADDR, mask, 0);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int resume_8960(struct tsens_device *tmdev)
+{
+	int ret;
+	struct regmap *map = tmdev->map;
+
+	ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST);
+	if (ret)
+		return ret;
+
+	/*
+	 * Separate CONFIG restore is not needed only for 8660 as
+	 * config is part of CTRL Addr and its restored as such
+	 */
+	if (tmdev->num_sensors > 1) {
+		ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG);
+		if (ret)
+			return ret;
+	}
+
+	ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold);
+	if (ret)
+		return ret;
+
+	ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int enable_8960(struct tsens_device *tmdev, int id)
+{
+	int ret;
+	u32 reg, mask;
+
+	ret = regmap_read(tmdev->map, CNTL_ADDR, &reg);
+	if (ret)
+		return ret;
+
+	mask = BIT(id + SENSOR0_SHIFT);
+	ret = regmap_write(tmdev->map, CNTL_ADDR, reg | SW_RST);
+	if (ret)
+		return ret;
+
+	if (tmdev->num_sensors > 1)
+		reg |= mask | SLP_CLK_ENA | EN;
+	else
+		reg |= mask | SLP_CLK_ENA_8660 | EN;
+
+	ret = regmap_write(tmdev->map, CNTL_ADDR, reg);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void disable_8960(struct tsens_device *tmdev)
+{
+	int ret;
+	u32 reg_cntl;
+	u32 mask;
+
+	mask = GENMASK(tmdev->num_sensors - 1, 0);
+	mask <<= SENSOR0_SHIFT;
+	mask |= EN;
+
+	ret = regmap_read(tmdev->map, CNTL_ADDR, &reg_cntl);
+	if (ret)
+		return;
+
+	reg_cntl &= ~mask;
+
+	if (tmdev->num_sensors > 1)
+		reg_cntl &= ~SLP_CLK_ENA;
+	else
+		reg_cntl &= ~SLP_CLK_ENA_8660;
+
+	regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
+}
+
+static int init_8960(struct tsens_device *tmdev)
+{
+	int ret, i;
+	u32 reg_cntl;
+
+	tmdev->map = dev_get_regmap(tmdev->dev, NULL);
+	if (!tmdev->map)
+		return -ENODEV;
+
+	/*
+	 * The status registers for each sensor are discontiguous
+	 * because some SoCs have 5 sensors while others have more
+	 * but the control registers stay in the same place, i.e
+	 * directly after the first 5 status registers.
+	 */
+	for (i = 0; i < tmdev->num_sensors; i++) {
+		if (i >= 5)
+			tmdev->sensor[i].status = S0_STATUS_ADDR + 40;
+		tmdev->sensor[i].status += i * 4;
+	}
+
+	reg_cntl = SW_RST;
+	ret = regmap_update_bits(tmdev->map, CNTL_ADDR, SW_RST, reg_cntl);
+	if (ret)
+		return ret;
+
+	if (tmdev->num_sensors > 1) {
+		reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18);
+		reg_cntl &= ~SW_RST;
+		ret = regmap_update_bits(tmdev->map, CONFIG_ADDR,
+					 CONFIG_MASK, CONFIG);
+	} else {
+		reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16);
+		reg_cntl &= ~CONFIG_MASK_8660;
+		reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660;
+	}
+
+	reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT;
+	ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
+	if (ret)
+		return ret;
+
+	reg_cntl |= EN;
+	ret = regmap_write(tmdev->map, CNTL_ADDR, reg_cntl);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int calibrate_8960(struct tsens_device *tmdev)
+{
+	int i;
+	char *data;
+
+	ssize_t num_read = tmdev->num_sensors;
+	struct tsens_sensor *s = tmdev->sensor;
+
+	data = qfprom_read(tmdev->dev, "calib");
+	if (IS_ERR(data))
+		data = qfprom_read(tmdev->dev, "calib_backup");
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	for (i = 0; i < num_read; i++, s++)
+		s->offset = data[i];
+
+	return 0;
+}
+
+/* Temperature on y axis and ADC-code on x-axis */
+static inline int code_to_mdegC(u32 adc_code, const struct tsens_sensor *s)
+{
+	int slope, offset;
+
+	slope = thermal_zone_get_slope(s->tzd);
+	offset = CAL_MDEGC - slope * s->offset;
+
+	return adc_code * slope + offset;
+}
+
+static int get_temp_8960(struct tsens_device *tmdev, int id, int *temp)
+{
+	int ret;
+	u32 code, trdy;
+	const struct tsens_sensor *s = &tmdev->sensor[id];
+	unsigned long timeout;
+
+	timeout = jiffies + usecs_to_jiffies(TIMEOUT_US);
+	do {
+		ret = regmap_read(tmdev->map, INT_STATUS_ADDR, &trdy);
+		if (ret)
+			return ret;
+		if (!(trdy & TRDY_MASK))
+			continue;
+		ret = regmap_read(tmdev->map, s->status, &code);
+		if (ret)
+			return ret;
+		*temp = code_to_mdegC(code, s);
+		return 0;
+	} while (time_before(jiffies, timeout));
+
+	return -ETIMEDOUT;
+}
+
+const struct tsens_ops ops_8960 = {
+	.init		= init_8960,
+	.calibrate	= calibrate_8960,
+	.get_temp	= get_temp_8960,
+	.enable		= enable_8960,
+	.disable	= disable_8960,
+	.suspend	= suspend_8960,
+	.resume		= resume_8960,
+};
+
+const struct tsens_data data_8960 = {
+	.num_sensors	= 11,
+	.ops		= &ops_8960,
+};
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 5f206e3..cef86c3 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -122,10 +122,10 @@ static int tsens_probe(struct platform_device *pdev)
 	np = dev->of_node;
 
 	id = of_match_node(tsens_table, np);
-	if (!id)
-		return -EINVAL;
-
-	data = id->data;
+	if (id)
+		data = id->data;
+	else
+		data = &data_8960;
 
 	if (data->num_sensors <= 0) {
 		dev_err(dev, "invalid number of sensors\n");
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 8ab9997..42071a4 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -87,6 +87,6 @@ void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
 int init_common(struct tsens_device *);
 int get_temp_common(struct tsens_device *, int, int *);
 
-extern const struct tsens_data data_8916, data_8974;
+extern const struct tsens_data data_8916, data_8974, data_8960;
 
 #endif /* __QCOM_TSENS_H__ */
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



From rnayak at codeaurora.org  Thu May  5 01:51:44 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu,  5 May 2016 14:21:44 +0530
Subject: [PATCH v6 06/11] thermal: qcom: tsens-8996: Add support for 8996
 family of SoCs
In-Reply-To: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
References: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
Message-ID: <1462438309-11196-7-git-send-email-rnayak@codeaurora.org>

The TSENS controller in 8996 family of SoCs is capable of converting the
ADC code outputs to real temperature values (in decidegree Celsius).
It can also be programmed to provide raw ADC code, but the secure software
on 8996 programs it to provide real temperatures and also does the needed
calibrations.

We check the valid bit to ensure valid data is read by the AHB master.
And the spec recommends the below algorithm to read data 3 consecutive
times, which takes care of the worst case delay taken to propagate the
updated data to the register.

Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
---
 drivers/thermal/qcom/Makefile     |  2 +-
 drivers/thermal/qcom/tsens-8996.c | 84 +++++++++++++++++++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c      |  3 ++
 drivers/thermal/qcom/tsens.h      |  2 +-
 4 files changed, 89 insertions(+), 2 deletions(-)
 create mode 100644 drivers/thermal/qcom/tsens-8996.c

diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index f3cefd1..2cc2193 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
-qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o
+qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-8996.o
diff --git a/drivers/thermal/qcom/tsens-8996.c b/drivers/thermal/qcom/tsens-8996.c
new file mode 100644
index 0000000..e2e1274
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-8996.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include "tsens.h"
+
+#define STATUS_OFFSET	0x10a0
+#define LAST_TEMP_MASK	0xfff
+#define STATUS_VALID_BIT	BIT(21)
+#define CODE_SIGN_BIT		BIT(11)
+
+static int get_temp_8996(struct tsens_device *tmdev, int id, int *temp)
+{
+	struct tsens_sensor *s = &tmdev->sensor[id];
+	u32 code;
+	unsigned int sensor_addr;
+	int last_temp = 0, last_temp2 = 0, last_temp3 = 0, ret;
+
+	sensor_addr = STATUS_OFFSET + s->hw_id * 4;
+	ret = regmap_read(tmdev->map, sensor_addr, &code);
+	if (ret)
+		return ret;
+	last_temp = code & LAST_TEMP_MASK;
+	if (code & STATUS_VALID_BIT)
+		goto done;
+
+	/* Try a second time */
+	ret = regmap_read(tmdev->map, sensor_addr, &code);
+	if (ret)
+		return ret;
+	if (code & STATUS_VALID_BIT) {
+		last_temp = code & LAST_TEMP_MASK;
+		goto done;
+	} else {
+		last_temp2 = code & LAST_TEMP_MASK;
+	}
+
+	/* Try a third/last time */
+	ret = regmap_read(tmdev->map, sensor_addr, &code);
+	if (ret)
+		return ret;
+	if (code & STATUS_VALID_BIT) {
+		last_temp = code & LAST_TEMP_MASK;
+		goto done;
+	} else {
+		last_temp3 = code & LAST_TEMP_MASK;
+	}
+
+	if (last_temp == last_temp2)
+		last_temp = last_temp2;
+	else if (last_temp2 == last_temp3)
+		last_temp = last_temp3;
+done:
+	/* Code sign bit is the sign extension for a negative value */
+	if (last_temp & CODE_SIGN_BIT)
+		last_temp |= ~CODE_SIGN_BIT;
+
+	/* Temperatures are in deciCelicius */
+	*temp = last_temp * 100;
+
+	return 0;
+}
+
+const struct tsens_ops ops_8996 = {
+	.init		= init_common,
+	.get_temp	= get_temp_8996,
+};
+
+const struct tsens_data data_8996 = {
+	.num_sensors	= 13,
+	.ops		= &ops_8996,
+};
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index cef86c3..b182272 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -69,6 +69,9 @@ static const struct of_device_id tsens_table[] = {
 	}, {
 		.compatible = "qcom,msm8974-tsens",
 		.data = &data_8974,
+	}, {
+		.compatible = "qcom,msm8996-tsens",
+		.data = &data_8996,
 	},
 	{}
 };
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 42071a4..b0f8c47 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -87,6 +87,6 @@ void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32);
 int init_common(struct tsens_device *);
 int get_temp_common(struct tsens_device *, int, int *);
 
-extern const struct tsens_data data_8916, data_8974, data_8960;
+extern const struct tsens_data data_8916, data_8974, data_8960, data_8996;
 
 #endif /* __QCOM_TSENS_H__ */
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



From rnayak at codeaurora.org  Thu May  5 01:51:45 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu,  5 May 2016 14:21:45 +0530
Subject: [PATCH v6 07/11] arm: dts: msm8974: Add thermal zones,
 tsens and qfprom nodes
In-Reply-To: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
References: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
Message-ID: <1462438309-11196-8-git-send-email-rnayak@codeaurora.org>

Add thermal zones, tsens and qfprom nodes

Cc: Andy Gross <agross at codeaurora.org>
Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
---
 arch/arm/boot/dts/qcom-msm8974.dtsi | 103 ++++++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index 8193139..3a7a63b 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -126,6 +126,88 @@
 		};
 	};
 
+	thermal-zones {
+		cpu-thermal0 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 5>;
+
+			trips {
+				cpu_alert0: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit0: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal1 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 6>;
+
+			trips {
+				cpu_alert1: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit1: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal2 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 7>;
+
+			trips {
+				cpu_alert2: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit2: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal3 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 8>;
+
+			trips {
+				cpu_alert3: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit3: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+	};
+
 	cpu-pmu {
 		compatible = "qcom,krait-pmu";
 		interrupts = <1 7 0xf04>;
@@ -249,6 +331,27 @@
 			reg = <0xf9011000 0x1000>;
 		};
 
+		qfprom: qfprom at fc4bc000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qfprom";
+			reg = <0xfc4bc000 0x1000>;
+			tsens_calib: calib at d0 {
+				reg = <0xd0 0x18>;
+			};
+			tsens_backup: backup at 440 {
+				reg = <0x440 0x10>;
+			};
+		};
+
+		tsens: thermal-sensor at fc4a8000 {
+			compatible = "qcom,msm8974-tsens";
+			reg = <0xfc4a8000 0x2000>;
+			nvmem-cells = <&tsens_calib>, <&tsens_backup>;
+			nvmem-cell-names = "calib", "calib_backup";
+			#thermal-sensor-cells = <1>;
+		};
+
 		timer at f9020000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



From rnayak at codeaurora.org  Thu May  5 01:51:46 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu,  5 May 2016 14:21:46 +0530
Subject: [PATCH v6 08/11] arm: dts: apq8064: Add thermal zones,
 tsens and qfprom nodes
In-Reply-To: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
References: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
Message-ID: <1462438309-11196-9-git-send-email-rnayak@codeaurora.org>

TSENS is part of GCC, hence add TSENS properties as part of GCC node.
Also add thermal zones and qfprom nodes.
Update GCC bindings doc to mention the possibility of optional TSENS
properties that can be part of GCC node.

Cc: Andy Gross <agross at codeaurora.org>
Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
---
 .../devicetree/bindings/clock/qcom,gcc.txt         |  18 ++++
 arch/arm/boot/dts/qcom-apq8064.dtsi                | 103 +++++++++++++++++++++
 2 files changed, 121 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
index 9a60fde..16e2f84 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
@@ -23,6 +23,13 @@ Required properties :
 Optional properties :
 - #power-domain-cells : shall contain 1
 
+Optional properties:
+- Qualcomm TSENS (thermal sensor device) on some devices can
+be part of GCC and hence the TSENS properties can also be
+part of the GCC/clock-controller node.
+For more details on the TSENS properties please refer
+Documentation/devicetree/bindings/thermal/qcom-tsens.txt
+
 Example:
 	clock-controller at 900000 {
 		compatible = "qcom,gcc-msm8960";
@@ -31,3 +38,14 @@ Example:
 		#reset-cells = <1>;
 		#power-domain-cells = <1>;
 	};
+
+Example of GCC with TSENS properties:
+	clock-controller at 900000 {
+		compatible = "qcom,gcc-apq8064";
+		reg = <0x00900000 0x4000>;
+		nvmem-cells = <&tsens_calib>, <&tsens_backup>;
+		nvmem-cell-names = "calib", "calib_backup";
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+		#thermal-sensor-cells = <1>;
+	};
diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index 65d0e8d..4f839b0 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -86,6 +86,92 @@
 		};
 	};
 
+	thermal-zones {
+		cpu-thermal0 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&gcc 7>;
+			coefficients = <1199 0>;
+
+			trips {
+				cpu_alert0: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit0: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal1 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&gcc 8>;
+			coefficients = <1132 0>;
+
+			trips {
+				cpu_alert1: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit1: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal2 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&gcc 9>;
+			coefficients = <1199 0>;
+
+			trips {
+				cpu_alert2: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit2: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal3 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&gcc 10>;
+			coefficients = <1132 0>;
+
+			trips {
+				cpu_alert3: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit3: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+	};
+
 	cpu-pmu {
 		compatible = "qcom,krait-pmu";
 		interrupts = <1 10 0x304>;
@@ -481,11 +567,28 @@
 			};
 		};
 
+		qfprom: qfprom at 00700000 {
+			compatible	= "qcom,qfprom";
+			reg		= <0x00700000 0x1000>;
+			#address-cells	= <1>;
+			#size-cells	= <1>;
+			ranges;
+			tsens_calib: calib {
+				reg = <0x404 0x10>;
+			};
+			tsens_backup: backup_calib {
+				reg = <0x414 0x10>;
+			};
+		};
+
 		gcc: clock-controller at 900000 {
 			compatible = "qcom,gcc-apq8064";
 			reg = <0x00900000 0x4000>;
+			nvmem-cells = <&tsens_calib>, <&tsens_backup>;
+			nvmem-cell-names = "calib", "calib_backup";
 			#clock-cells = <1>;
 			#reset-cells = <1>;
+			#thermal-sensor-cells = <1>;
 		};
 
 		lcc: clock-controller at 28000000 {
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



From rnayak at codeaurora.org  Thu May  5 01:51:47 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu,  5 May 2016 14:21:47 +0530
Subject: [PATCH v6 09/11] arm: dts: apq8084: Add thermal zones,
 tsens and qfprom nodes
In-Reply-To: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
References: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
Message-ID: <1462438309-11196-10-git-send-email-rnayak@codeaurora.org>

Add thermal zones, tsens and qfprom nodes

Cc: Andy Gross <agross at codeaurora.org>
Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
---
 arch/arm/boot/dts/qcom-apq8084.dtsi | 103 ++++++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-apq8084.dtsi b/arch/arm/boot/dts/qcom-apq8084.dtsi
index a33a09f..5284709 100644
--- a/arch/arm/boot/dts/qcom-apq8084.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8084.dtsi
@@ -86,6 +86,88 @@
 		};
 	};
 
+	thermal-zones {
+		cpu-thermal0 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 5>;
+
+			trips {
+				cpu_alert0: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit0: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal1 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 6>;
+
+			trips {
+				cpu_alert1: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit1: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal2 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 7>;
+
+			trips {
+				cpu_alert2: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit2: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal3 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 8>;
+
+			trips {
+				cpu_alert3: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit3: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+	};
+
 	cpu-pmu {
 		compatible = "qcom,krait-pmu";
 		interrupts = <1 7 0xf04>;
@@ -142,6 +224,27 @@
 			reg = <0xf9011000 0x1000>;
 		};
 
+		qfprom: qfprom at fc4bc000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qfprom";
+			reg = <0xfc4bc000 0x1000>;
+			tsens_calib: calib at d0 {
+				reg = <0xd0 0x18>;
+			};
+			tsens_backup: backup at 440 {
+				reg = <0x440 0x10>;
+			};
+		};
+
+		tsens: thermal-sensor at fc4a8000 {
+			compatible = "qcom,msm8974-tsens";
+			reg = <0xfc4a8000 0x2000>;
+			nvmem-cells = <&tsens_calib>, <&tsens_backup>;
+			nvmem-cell-names = "calib", "calib_backup";
+			#thermal-sensor-cells = <1>;
+		};
+
 		timer at f9020000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



From rnayak at codeaurora.org  Thu May  5 01:51:48 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu,  5 May 2016 14:21:48 +0530
Subject: [PATCH v6 10/11] arm64: dts: msm8916: Add thermal zones,
 tsens and qfprom nodes
In-Reply-To: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
References: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
Message-ID: <1462438309-11196-11-git-send-email-rnayak@codeaurora.org>

Add thermal zones, tsens and qfprom nodes

Cc: Andy Gross <agross at codeaurora.org>
Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
---
 arch/arm64/boot/dts/qcom/msm8916.dtsi | 64 +++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index af25110..505cf3a 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -98,6 +98,49 @@
 		};
 	};
 
+	thermal-zones {
+		cpu-thermal0 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 4>;
+
+			trips {
+				cpu_alert0: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit0: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal1 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens 3>;
+
+			trips {
+				cpu_alert1: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit1: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -544,6 +587,27 @@
 			clocks = <&gcc GCC_PRNG_AHB_CLK>;
 			clock-names = "core";
 		};
+
+		qfprom: qfprom at 5c000 {
+			compatible = "qcom,qfprom";
+			reg = <0x5c000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			tsens_caldata: caldata at d0 {
+				reg = <0xd0 0x8>;
+			};
+			tsens_calsel: calsel at ec {
+				reg = <0xec 0x4>;
+			};
+		};
+
+		tsens: thermal-sensor at 4a8000 {
+			compatible = "qcom,msm8916-tsens";
+			reg = <0x4a8000 0x2000>;
+			nvmem-cells = <&tsens_caldata>, <&tsens_calsel>;
+			nvmem-cell-names = "calib", "calib_sel";
+			#thermal-sensor-cells = <1>;
+		};
 	};
 
 	smd {
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



From rnayak at codeaurora.org  Thu May  5 01:51:49 2016
From: rnayak at codeaurora.org (Rajendra Nayak)
Date: Thu,  5 May 2016 14:21:49 +0530
Subject: [PATCH v6 11/11] arm64: dts: msm8996: Add thermal zones,
 tsens and qfprom nodes
In-Reply-To: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
References: <1462438309-11196-1-git-send-email-rnayak@codeaurora.org>
Message-ID: <1462438309-11196-12-git-send-email-rnayak@codeaurora.org>

Add thermal zones, tsens and qfprom nodes

Cc: Andy Gross <agross at codeaurora.org>
Signed-off-by: Rajendra Nayak <rnayak at codeaurora.org>
---
 arch/arm64/boot/dts/qcom/msm8996.dtsi | 92 +++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 0506fb8..4b36929 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -97,6 +97,92 @@
 		};
 	};
 
+	thermal-zones {
+		cpu-thermal0 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens0 3>;
+
+			trips {
+				cpu_alert0: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				cpu_crit0: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal1 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens0 5>;
+
+			trips {
+				cpu_alert1: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				cpu_crit1: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal2 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens0 8>;
+
+			trips {
+				cpu_alert2: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				cpu_crit2: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+
+		cpu-thermal3 {
+			polling-delay-passive = <250>;
+			polling-delay = <1000>;
+
+			thermal-sensors = <&tsens0 10>;
+
+			trips {
+				cpu_alert3: trip at 0 {
+					temperature = <75000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				cpu_crit3: trip at 1 {
+					temperature = <110000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -151,6 +237,12 @@
 			reg = <0x300000 0x90000>;
 		};
 
+		tsens0: thermal-sensor at 4a8000 {
+			compatible = "qcom,msm8996-tsens";
+			reg = <0x4a8000 0x2000>;
+			#thermal-sensor-cells = <1>;
+		};
+
 		blsp2_uart1: serial at 75b0000 {
 			compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
 			reg = <0x75b0000 0x1000>;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation



From oliver at schinagl.nl  Thu May  5 02:08:52 2016
From: oliver at schinagl.nl (Olliver Schinagl)
Date: Thu,  5 May 2016 11:08:52 +0200
Subject: [PATCHv4] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
Message-ID: <1462439332-26215-1-git-send-email-oliver@schinagl.nl>

There are 3 kinds of OLinuXino Lime2 boards.
One without any on board storage, one with NAND storage and one with
eMMC storage. This patch adds the eMMC variant of boards.

eMMC storage is different from a regular SD card in that it is soldered
on the board and cannot be changed. Additionally, it shares pins with
the NAND module and with the second SPI port.

Changeslog:

v4:
  Add board compatibles

v3:
  Add pwr-seq-emmc with the reset gpio

v2:
  Remove unsupported no-1.8-v property, add vqmmc property

v1:
  Initial bare bone version

Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>
---
 .../boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts    | 82 ++++++++++++++++++++++
 1 file changed, 82 insertions(+)
 create mode 100644 arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts

diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
new file mode 100644
index 0000000..5ea4915
--- /dev/null
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
@@ -0,0 +1,82 @@
+ /*
+ * Copyright 2015 - Ultimaker B.V.
+ * Author Olliver Schinagl <oliver at schinagl.nl>
+ *
+ * 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.
+ */
+
+#include "sun7i-a20-olinuxino-lime2.dts"
+
+/ {
+	model = "Olimex A20-OLinuXino-LIME2-eMMC";
+	compatible = "olimex,a20-olinuxino-lime2-emmc", "allwinner,sun7i-a20";
+
+	mmc2_pwrseq: pwrseq {
+		pinctrl-0 = <&mmc2_pins_nrst>;
+		pinctrl-names = "default";
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&pio 2 16 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&pio {
+	mmc2_pins_nrst: mmc2 at 0 {
+		allwinner,pins = "PC16";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins_a>;
+	vmmc-supply = <&reg_vcc3v3>;
+	vqmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	non-removable;
+	mmc-pwrseq = <&mmc2_pwrseq>;
+	status = "okay";
+
+	emmc: emmc at 0 {
+		reg = <0>;
+		compatible = "mmc-card";
+		broken-hpi;
+	};
+};
-- 
2.8.1



From jchandra at broadcom.com  Thu May  5 02:24:20 2016
From: jchandra at broadcom.com (Jayachandran C)
Date: Thu, 5 May 2016 14:54:20 +0530
Subject: [PATCH V6 07/13] PCI: Provide common functions for ECAM mapping
In-Reply-To: <CAKc_7PUJQsUrCuOg1iafZ9amANk=E9eu0MrF=UOrVEVbseMz2w@mail.gmail.com>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-8-git-send-email-tn@semihalf.com>
 <20160428214749.GF25125@localhost>
 <CAKc_7PUJQsUrCuOg1iafZ9amANk=E9eu0MrF=UOrVEVbseMz2w@mail.gmail.com>
Message-ID: <CAKc_7PXG5QxaN=b0oZA7E=a-LhSg0q+FqmaVhViYnRfK4Z8jfQ@mail.gmail.com>

On Fri, Apr 29, 2016 at 1:31 PM, Jayachandran C <jchandra at broadcom.com> wrote:
> On Fri, Apr 29, 2016 at 3:17 AM, Bjorn Helgaas <helgaas at kernel.org> wrote:
>> On Fri, Apr 15, 2016 at 07:06:42PM +0200, Tomasz Nowicki wrote:
>>> From: Jayachandran C <jchandra at broadcom.com>
>>>
>>> Add config option PCI_GENERIC_ECAM and file drivers/pci/ecam.c to
>>> provide generic functions for accessing memory mapped PCI config space.
>>>
>>> The API is defined in drivers/pci/ecam.h and is written to replace the
>>> API in drivers/pci/host/pci-host-common.h. The file defines a new
>>> 'struct pci_config_window' to hold the information related to a PCI
>>> config area and its mapping. This structure is expected to be used as
>>> sysdata for controllers that have ECAM based mapping.
>>>
>>> Helper functions are provided to setup the mapping, free the mapping
>>> and to implement the map_bus method in 'struct pci_ops'
>>
>> Spec reference: PCI Express Base Specification, rev 3.0, sec 7.2.2.
>>
>>> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
>>> ---
>>>  drivers/pci/Kconfig  |   3 ++
>>>  drivers/pci/Makefile |   2 +
>>>  drivers/pci/ecam.c   | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>>  drivers/pci/ecam.h   |  61 +++++++++++++++++++++++
>>>  4 files changed, 203 insertions(+)
>>>  create mode 100644 drivers/pci/ecam.c
>>>  create mode 100644 drivers/pci/ecam.h
>>>
>>> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
>>> index 209292e..e930d62 100644
>>> --- a/drivers/pci/Kconfig
>>> +++ b/drivers/pci/Kconfig
>>> @@ -83,6 +83,9 @@ config HT_IRQ
>>>  config PCI_ATS
>>>       bool
>>>
>>> +config PCI_GENERIC_ECAM
>>> +     bool
>>
>> "PCI_ECAM" is enough, I think.  It's defined by and required by the
>> spec unless there's some arch-specific interface.  Plus, if I
>
> Ok. Looking at the comments I think I have to take out generic from
> all the names - will do this in next version.
>
>> understand correctly, this infrastructure supports non-generic ECAM
>> implementations as well, since the caller supplies "struct
>> pci_generic_ecam_ops *ops".
>
> Yes, the idea was to support ECAM with quirks (and CAM) on both
> 32 and 64 bit, otherwise it would be too trivial to have a separate
> implementation.
>
>>>  config PCI_IOV
>>>       bool "PCI IOV support"
>>>       depends on PCI
>>> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
>>> index 2154092..810aec8 100644
>>> --- a/drivers/pci/Makefile
>>> +++ b/drivers/pci/Makefile
>>> @@ -55,6 +55,8 @@ obj-$(CONFIG_PCI_SYSCALL) += syscall.o
>>>
>>>  obj-$(CONFIG_PCI_STUB) += pci-stub.o
>>>
>>> +obj-$(CONFIG_PCI_GENERIC_ECAM) += ecam.o
>>> +
>>>  obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
>>>
>>>  obj-$(CONFIG_OF) += of.o
>>> diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
>>> new file mode 100644
>>> index 0000000..ff04c01
>>> --- /dev/null
>>> +++ b/drivers/pci/ecam.c
>>> @@ -0,0 +1,137 @@
>>> +/*
>>> + * Copyright 2016 Broadcom
>>> + *
>>> + * 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 (the "GPL").
>>> + *
>>> + * 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 version 2 (GPLv2) for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * version 2 (GPLv2) along with this source code.
>>> + */
>>> +
>>> +#include <linux/device.h>
>>> +#include <linux/io.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/module.h>
>>> +#include <linux/pci.h>
>>> +#include <linux/slab.h>
>>> +
>>> +#include "ecam.h"
>>> +
>>> +/*
>>> + * On 64 bit systems, we do a single ioremap for the whole config space
>>> + * since we have enough virtual address range available. On 32 bit, do an
>>> + * ioremap per bus.
>>> + */
>>> +static const bool per_bus_mapping = !config_enabled(CONFIG_64BIT);
>>> +
>>> +/*
>>> + * Create a PCI config space window
>>> + *  - reserve mem region
>>> + *  - alloc struct pci_config_window with space for all mappings
>>> + *  - ioremap the config space
>>> + */
>>> +struct pci_config_window *pci_generic_ecam_create(struct device *dev,
>>> +                             phys_addr_t addr, u8 bus_start, u8 bus_end,
>>
>> Can you take pointers to struct resources here instead of addr,
>> bus_start, and bus_end?  The caller probably has them already, and
>> then you could add a useful printk like:
>>
>>   dev_info(dev, "ECAM for %pR at %pR\n", busn_res, mmio_res);
>>
>> Would have to be careful about the struct resource lifetimes though.
>
> Yes, I had thought of this. The reason I did not go down that path was
> that we are using request_mem_region() which takes the address
> and creates a resource .internally.
>
> Beyond that, as you noted, the ownership and lifetime is slightly
> more complex. Either the calling code has to allocate the
> resource and handoff, or the ecam code has to make a copy of
> the resource. I would go with copy since it is much more simple
> to use.
>
> Since resource based API seems to be preferred, I will switch
> to passing bus and mmio resource and will use
> request_resource_conflict() to allocate the ECAM mem region,
>
>> If you had the MMIO resource here, you could also do the range
>> checking you currently have in gen_pci_init() here instead, so all
>> callers could benefit.
>
> Ok.
>
>>> +                             struct pci_generic_ecam_ops *ops)
>>> +{
>>> +     struct pci_config_window *cfg;
>>> +     unsigned int bus_shift, bus_range, bsz, mapsz;
>>> +     int i, nidx;
>>> +     int err = -ENOMEM;
>>> +
>>> +     if (bus_end < bus_start)
>>> +             return ERR_PTR(-EINVAL);
>>> +
>>> +     bus_shift = ops->bus_shift;
>>> +     bus_range = bus_end - bus_start + 1;
>>> +     bsz = 1 << bus_shift;
>>> +     nidx = per_bus_mapping ? bus_range : 1;
>>> +     mapsz = per_bus_mapping ? bsz : bus_range * bsz;
>>> +     cfg = kzalloc(sizeof(*cfg) + nidx * sizeof(cfg->win[0]), GFP_KERNEL);
>>> +     if (!cfg)
>>> +             return ERR_PTR(-ENOMEM);
>>> +
>>> +     cfg->bus_start = bus_start;
>>> +     cfg->bus_end = bus_end;
>>> +     cfg->ops = ops;
>>> +
>>> +     if (!request_mem_region(addr, bus_range * bsz, "Configuration Space"))
>>> +             goto err_exit;
>>> +
>>> +     /* cfgaddr has to be set after request_mem_region */
>>> +     cfg->cfgaddr = addr;
>>> +
>>> +     for (i = 0; i < nidx; i++) {
>>> +             cfg->win[i] = ioremap(addr + i * mapsz, mapsz);
>>> +             if (!cfg->win[i])
>>> +                     goto err_exit;
>>> +     }
>>> +
>>> +     if (cfg->ops->init) {
>>> +             err = cfg->ops->init(dev, cfg);
>>> +             if (err)
>>> +                     goto err_exit;
>>> +     }
>>> +     return cfg;
>>> +
>>> +err_exit:
>>> +     pci_generic_ecam_free(cfg);
>>> +     return ERR_PTR(err);
>>> +}
>>> +
>>> +/*
>>> + * Free a config space mapping
>>> + */
>>
>> Superfluous comment.
>
> Ok, will trim comments to keep the ones that are useful.
>
>>> +void pci_generic_ecam_free(struct pci_config_window *cfg)
>>> +{
>>> +     unsigned int bus_range;
>>> +     int i, nidx;
>>> +
>>> +     bus_range = cfg->bus_end - cfg->bus_start + 1;
>>> +     nidx = per_bus_mapping ? bus_range : 1;
>>> +     for (i = 0; i < nidx; i++)
>>> +             if (cfg->win[i])
>>> +                     iounmap(cfg->win[i]);
>>> +     if (cfg->cfgaddr)
>>> +             release_mem_region(cfg->cfgaddr,
>>> +                                bus_range << cfg->ops->bus_shift);
>>> +     kfree(cfg);
>>> +}
>>> +
>>> +/*
>>> + * Function to implement the pci_ops ->map_bus method
>>> + */
>>> +void __iomem *pci_generic_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
>>> +                                    int where)
>>> +{
>>> +     struct pci_config_window *cfg = bus->sysdata;
>>
>> I don't really like the use of bus->sysdata here, because sysdata is
>> explicitly arch-specific.
>>
>> But I guess we're in a bind right now: it'd be nice to save the cfg
>> pointer in struct pci_host_bridge, but you have to call
>> pci_generic_ecam_create() before the struct pci_host_bridge has been
>> allocated, and you have to pass the pointer into pci_scan_root_bus(),
>> and there's no generic way to do that yet.
>>
>> So I guess this will have to do for now.
>
> I could call the structure pci_ecam_sysdata instead of pci_config_window
> to make it clear that it is to be used as sysdata for ECAM based PCI host
> controllers.
>
> The current push (at least on ARM/ARM64) seems to be to make
> bus->sysdata controller specific and avoid arch specific sysdata.
>
>>> +     unsigned int devfn_shift = cfg->ops->bus_shift - 8;
>>> +     unsigned int busn = bus->number;
>>> +     void __iomem *base;
>>> +
>>> +     if (busn < cfg->bus_start || busn > cfg->bus_end)
>>> +             return NULL;
>>> +
>>> +     busn -= cfg->bus_start;
>>> +     if (per_bus_mapping)
>>> +             base = cfg->win[busn];
>>> +     else
>>> +             base = cfg->win[0] + (busn << cfg->ops->bus_shift);
>>> +     return base + (devfn << devfn_shift) + where;
>>> +}
>>> +
>>> +/* default ECAM ops */
>>> +struct pci_generic_ecam_ops pci_generic_ecam_default_ops = {
>>
>> Using both "generic" and "default" seems overkill.  Maybe just:
>>
>>   struct pci_ecam_ops pci_generic_ecam_ops = { ... ?
>
> Ok.
>
>>> +     .bus_shift      = 20,
>>> +     .pci_ops                = {
>>> +             .map_bus        = pci_generic_ecam_map_bus,
>>> +             .read           = pci_generic_config_read,
>>> +             .write          = pci_generic_config_write,
>>> +     }
>>> +};
>>> diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
>>> new file mode 100644
>>> index 0000000..34c0aba
>>> --- /dev/null
>>> +++ b/drivers/pci/ecam.h
>>> @@ -0,0 +1,61 @@
>>> +/*
>>> + * Copyright 2016 Broadcom
>>> + *
>>> + * 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 (the "GPL").
>>> + *
>>> + * 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 version 2 (GPLv2) for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * version 2 (GPLv2) along with this source code.
>>> + */
>>> +#ifndef DRIVERS_PCI_ECAM_H
>>> +#define DRIVERS_PCI_ECAM_H
>>> +
>>> +#include <linux/kernel.h>
>>> +#include <linux/platform_device.h>
>>> +
>>> +/*
>>> + * struct to hold pci ops and bus shift of the config window
>>> + * for a PCI controller.
>>> + */
>>> +struct pci_config_window;
>>> +struct pci_generic_ecam_ops {
>>
>> "struct pci_ecam_ops"
>
> Ok.
>
>>> +     unsigned int                    bus_shift;
>>> +     struct pci_ops                  pci_ops;
>>> +     int                             (*init)(struct device *,
>>> +                                             struct pci_config_window *);
>>> +};
>>> +
>>> +/*
>>> + * struct to hold the mappings of a config space window. This
>>> + * will be allocated with enough entries in win[] to hold all
>>> + * the mappings for the bus range.
>>> + */
>>> +struct pci_config_window {
>>> +     phys_addr_t                     cfgaddr;
>>> +     u16                             domain;
>>> +     u8                              bus_start;
>>> +     u8                              bus_end;
>>> +     void                            *priv;
>>> +     struct pci_generic_ecam_ops     *ops;
>>> +     void __iomem                    *win[0];
>>> +};
>>> +
>>> +/* create and free for pci_config_window */
>>
>> Superfluous comment.
>>
>>> +struct pci_config_window *pci_generic_ecam_create(struct device *dev,
>>> +                             phys_addr_t addr, u8 bus_start, u8 bus_end,
>>> +                             struct pci_generic_ecam_ops *ops);
>>> +void pci_generic_ecam_free(struct pci_config_window *cfg);
>>
>> "pci_ecam_create" and "pci_ecam_free"?  I suspect you're going to call
>> these for flavors of ECAM that are definitely not "generic".
>>
>>> +/* map_bus when ->sysdata is an instance of pci_config_window */
>>> +void __iomem *pci_generic_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
>>> +                                    int where);
>>> +/* default ECAM ops, bus shift 20, generic read and write */
>>> +extern struct pci_generic_ecam_ops pci_generic_ecam_default_ops;
>>> +
>>> +#endif
>
> Thanks for the review. The ECAM patchset can be merged separately
> if you do not want to tie it the ACPI changes.
>
> Please let me know how you want to proceed. Depending on that, I will
> either post it as a separate patchset or ask Tomasz to pick up my
> changes and post the ACPI patchset. again.

I have made the changes suggested here, and added one more
change to move from 'void __iomem *win[0]' to a union for
pci_config_window so that it can be embedded in other structures[1].

The changes are at https://github.com/jchandra-brcm/linux branch
arm64-acpi-pci-v4 so that Tomasz can add it to v7 of the ACPI/PCI
patches. I am not posting the changes here to avoid the impression
that there are clashing ACPI/PCI patchsets.

The branch also has an example patch for ACPI generic PCI root
using the new ECAM code. This also has the simpler domain
setting code for ACPI as well as fix for the ECAM address
calculation which came up during the earlier discussion.

JC.
[1] Minor API changes will be needed for embedding now.
    This change will make it easier to merge with Arnd's host bridge
    changes when that goes in.


From tomeu.vizoso at collabora.com  Thu May  5 02:34:26 2016
From: tomeu.vizoso at collabora.com (Tomeu Vizoso)
Date: Thu, 5 May 2016 11:34:26 +0200
Subject: [PATCH 1/2] drm/rockchip: vop: Do check if an update is pending
 during disable
In-Reply-To: <CAAObsKCmPZBaSudVJy8BPThhoZw8VVqxicqsmc8diApajD57nA@mail.gmail.com>
References: <1459937686-9142-1-git-send-email-tomeu.vizoso@collabora.com>
 <5707043D.6060706@rock-chips.com>
 <CAAObsKAeAjUP1retiZqo5geOK2OkVjKvSB6g6nvGTh_rdNiFJQ@mail.gmail.com>
 <570AFAC2.8080907@rock-chips.com>
 <CAAObsKCmPZBaSudVJy8BPThhoZw8VVqxicqsmc8diApajD57nA@mail.gmail.com>
Message-ID: <CAAObsKBXxb8ZS3CqLy4qsDRWLvT=w2ACANCcDLE5B47nRKtvBw@mail.gmail.com>

On 20 April 2016 at 16:23, Tomeu Vizoso <tomeu.vizoso at collabora.com> wrote:
> On 11 April 2016 at 03:15, Mark yao <mark.yao at rock-chips.com> wrote:
>> On 2016?04?08? 18:54, Tomeu Vizoso wrote:
>>>
>>> On 8 April 2016 at 03:07, Mark yao <mark.yao at rock-chips.com> wrote:
>>>>
>>>> On 2016?04?06? 18:14, Tomeu Vizoso wrote:
>>>>
>>>> When a plane is being disabled but it's still enabled, do check if the
>>>> previous update has been completed by reading yrgb_mst back.
>>>>
>>>> Otherwise, pending pageflips would remain pending after a CRTC is
>>>> disabled.
>>>>
>>>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>
>>>> ---
>>>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +++--
>>>>   1 file changed, 3 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>> index a9b1e8b5ac85..f46b1fd1887b 100644
>>>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>> @@ -1064,8 +1064,9 @@ static bool vop_win_pending_is_complete(struct
>>>> vop_win
>>>> *vop_win)
>>>>    struct vop_plane_state *state = to_vop_plane_state(plane->state);
>>>>    dma_addr_t yrgb_mst;
>>>>
>>>> - if (!state->enable)
>>>> - return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;
>>>> + if (!state->enable &&
>>>> +    VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0)
>>>> + return true;
>>>>
>>>>
>>>> It is wrong, the patch would cause a bug.
>>>>
>>>> when state->enable is 0, check yrgb_mst == state->yrgb_mst always be
>>>> true,
>>>> because state->yrgb_mst not update on plane disabled funtion, that would
>>>> cause iommu crash.
>>>
>>> Sorry, but I don't understand where's the bug and what could cause
>>> that crash. What the existing code was doing is saying that a pageflip
>>> event is still pending if we have told the plane to disable but for
>>> some reason it hasn't yet.
>>>
>>> With this modification, if we read back that it's already disabled, we
>>> return true as before. But if we read back that it isn't disabled yet,
>>> then we still check the fb pointers and compare them.
>>>
>>> The iommu mapping is removed when the _CRTC_ is disabled, and what
>>> this series does is to wait for the pending pageflip to finish before
>>> conitnuing with CRTC disablement.
>>
>>
>> the iommu mapping will unmap after plane disabled, we need sure that the
>> plane really disabled before unmap, if not, the unmap may call before plane
>> really disable, vop may access unmap address, then would get iommu page
>> fault.
>
> Sorry, but I still don't see the error condition that you are
> describing. AFAICS, the unmap will happen after the last pageflip has
> completed.
>
>>>> About pending pageflips would remain pending, can you  describe more info
>>>> about it? I think those pending pageflips should be ignore when CRTC is
>>>> disabled.
>>>
>>> Well, right now in rockchip-drm pending pageflips won't be ignored
>>> when a CRTC is disabled, but will be delivered when it's re-enabled.
>>>
>>> If they would be to be ignored (understanding that as dropped), that
>>> would require modifications to clients so they keep track of which fbs
>>> were used in a particular crtc and destroy them when the crtc is
>>> disabled, but that would be incorrect when using the i915 DRM driver
>>> (I also assume others do the same). Given that the pageflip ioctl
>>> isn't driver-specific, I think there cannot be such a difference in
>>> behavior between drivers.
>>>
>>> With the current behavior (pending pageflip events being delayed until
>>> the CRTC is enabled again), compositors and other clients will be
>>> holding on to the fb in the pending pageflip until an arbitrary point
>>> in the future that may not ever come. To me that sounds like a serious
>>> modification of the assumptions on fb lifecycle that might not be
>>> warranted.
>>>
>>> So in summary, even if I haven't found any explicit documentation on
>>> this, I think the ABI is that any pending pageflips are to be
>>> delivered when that CRTC is being disabled and not later.
>>
>>
>> on drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>>
>> drm_atomic_helper_commit_planes(dev, state, true);
>> rockchip_atomic_wait_for_complete(dev, state);
>>
>> We set active_only = true, I think planes can only update when crtc is
>> active. and rockchip_atomic_wait_for_complete only wait when crtc is active.
>
> That's fine, but if a pageflip is pending when the client requests the
> CRTC to be disabled, we need to wait for the event to be emitted
> before we actually disable the HW.

Hi Mark,

could you tell me if you agree that there's a bug that needs to be
solved, and if so, what do you think we should do about it?

Thanks,

Tomeu

> Regards,
>
> Tomeu
>
>> Thanks.
>>
>>> Thanks,
>>>
>>> Tomeu
>>>
>>>> Thanks.
>>>>
>>>>
>>>>    yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);
>>>>
>>>>
>>>>
>>>> --
>>>> ?ark Yao
>>>>
>>>>
>>>> _______________________________________________
>>>> dri-devel mailing list
>>>> dri-devel at lists.freedesktop.org
>>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>>>>
>>>
>>>
>>
>>
>> --
>> ?ark Yao
>>
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel


From yangbo.lu at nxp.com  Thu May  5 02:41:32 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Thu, 5 May 2016 09:41:32 +0000
Subject: [v10, 7/7] mmc: sdhci-of-esdhc: fix host version for
 T4240-R1.0-R2.0
In-Reply-To: <4448030.Zs8fVnr3nm@wuerfel>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <1462417950-46796-8-git-send-email-yangbo.lu@nxp.com>
 <4448030.Zs8fVnr3nm@wuerfel>
Message-ID: <HE1PR04MB0889B52134A43C0E7A452B7BF87C0@HE1PR04MB0889.eurprd04.prod.outlook.com>

Hi Arnd,


> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: Thursday, May 05, 2016 4:32 PM
> To: linuxppc-dev at lists.ozlabs.org
> Cc: Yangbo Lu; linux-mmc at vger.kernel.org; devicetree at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> linux-clk at vger.kernel.org; linux-i2c at vger.kernel.org; iommu at lists.linux-
> foundation.org; netdev at vger.kernel.org; Mark Rutland;
> ulf.hansson at linaro.org; Russell King; Bhupesh Sharma; Joerg Roedel;
> Santosh Shilimkar; Yang-Leo Li; Scott Wood; Rob Herring; Claudiu Manoil;
> Kumar Gala; Xiaobo Xie; Qiang Zhao
> Subject: Re: [v10, 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-
> R1.0-R2.0
> 
> On Thursday 05 May 2016 11:12:30 Yangbo Lu wrote:
> >
> > +       fsl_guts_init();
> > +       svr = fsl_guts_get_svr();
> > +       if (svr) {
> > +               esdhc->soc_ver = SVR_SOC_VER(svr);
> > +               esdhc->soc_rev = SVR_REV(svr);
> > +       } else {
> > +               dev_err(&pdev->dev, "Failed to get SVR value!\n");
> > +       }
> > +
> >
> 
> 
> Sorry for jumping in again after not participating in the discussion for
> the past few versions.
> 
> What happened to my suggestion of making this a platform-independent
> interface to avoid the link time dependency?
> 
> Specifically, why not add an exported function to drivers/base/soc.c that
> uses glob_match() for comparing a string in the device driver to the ID
> of the SoC that is set by whatever SoC identifying driver the platform
> has?
> 
> 	Arnd

[Lu Yangbo-B47093] I think this has been discussed in v6.
You can find Scott's comments about this in below link.
https://patchwork.kernel.org/patch/8544501/

Thanks.



From andre.przywara at arm.com  Thu May  5 02:44:18 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu,  5 May 2016 10:44:18 +0100
Subject: [PATCH] arm64: defconfig: Add Juno SATA controller
Message-ID: <1462441458-24387-1-git-send-email-andre.przywara@arm.com>

The ARM Juno (r1 and r2) boards feature a SATA controller soldered
on the board and connected to the PCI bus.
Add the respective driver to defconfig to get hard disks supported out
of the box on the Junos.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index a44ef99..c7f4202 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -103,6 +103,7 @@ CONFIG_AHCI_CEVA=y
 CONFIG_AHCI_MVEBU=y
 CONFIG_AHCI_XGENE=y
 CONFIG_SATA_RCAR=y
+CONFIG_SATA_SIL24=y
 CONFIG_PATA_PLATFORM=y
 CONFIG_PATA_OF_PLATFORM=y
 CONFIG_NETDEVICES=y
-- 
2.7.3



From catalin.marinas at arm.com  Thu May  5 02:43:58 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu,  5 May 2016 10:43:58 +0100
Subject: [PATCH 0/4] arm64: pmd accessor fixes
Message-ID: <1462441442-6996-1-git-send-email-catalin.marinas@arm.com>

The first two patches are follow-ups on the hardware AF/DBM support, so
they should go in as fixes (on top of current arm64 for-next/core
branch). The third patch is a minor clean-up while the last one
implements pmd_present() following recent discussions around
pmd_mknotpresent() (and it's also a cc stable).

Catalin Marinas (4):
  arm64: Fix typo in the pmdp_huge_get_and_clear() definition
  arm64: Implement pmdp_set_access_flags() for hardware AF/DBM
  arm64: Replace hard-coded values in the pmd/pud_bad() macros
  arm64: Ensure pmd_present() returns false after pmd_mknotpresent()

 arch/arm64/include/asm/pgtable-hwdef.h |  1 -
 arch/arm64/include/asm/pgtable.h       | 26 ++++++++++++++++++--------
 2 files changed, 18 insertions(+), 9 deletions(-)



From catalin.marinas at arm.com  Thu May  5 02:43:59 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu,  5 May 2016 10:43:59 +0100
Subject: [PATCH 1/4] arm64: Fix typo in the pmdp_huge_get_and_clear()
 definition
In-Reply-To: <1462441442-6996-1-git-send-email-catalin.marinas@arm.com>
References: <1462441442-6996-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <1462441442-6996-2-git-send-email-catalin.marinas@arm.com>

With hardware AF/DBM support, pmd modifications (transparent huge pages)
should be performed atomically using load/store exclusive. The initial
patches defined the get-and-clear function and __HAVE_ARCH_* macro
without the "huge" word, leaving the pmdp_huge_get_and_clear() to the
default, non-atomic implementation.

Fixes: 2f4b829c625e ("arm64: Add support for hardware updates of the access and dirty pte bits")
Cc: <stable at vger.kernel.org> # 4.3+
Reviewed-by: Will Deacon <will.deacon at arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---
 arch/arm64/include/asm/pgtable.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index e021cbf11043..5237331e97f4 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -605,9 +605,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
-#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
-static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
-				       unsigned long address, pmd_t *pmdp)
+#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
+static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
+					    unsigned long address, pmd_t *pmdp)
 {
 	return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
 }


From catalin.marinas at arm.com  Thu May  5 02:44:00 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu,  5 May 2016 10:44:00 +0100
Subject: [PATCH 2/4] arm64: Implement pmdp_set_access_flags() for hardware
 AF/DBM
In-Reply-To: <1462441442-6996-1-git-send-email-catalin.marinas@arm.com>
References: <1462441442-6996-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <1462441442-6996-3-git-send-email-catalin.marinas@arm.com>

The update to the accessed or dirty states for block mappings must be
done atomically on hardware with support for automatic AF/DBM. The
ptep_set_access_flags() function has been fixed as part of commit
66dbd6e61a52 ("arm64: Implement ptep_set_access_flags() for hardware
AF/DBM"). This patch brings pmdp_set_access_flags() in line with the pte
counterpart.

Fixes: 2f4b829c625e ("arm64: Add support for hardware updates of the access and dirty pte bits")
Cc: <stable at vger.kernel.org> # 4.4.x: 66dbd6e61a52: arm64: Implement ptep_set_access_flags() for hardware AF/DBM
Cc: <stable at vger.kernel.org> # 4.3+
Reviewed-by: Will Deacon <will.deacon at arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---
 arch/arm64/include/asm/pgtable.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 5237331e97f4..bdfbaf96b426 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -553,6 +553,16 @@ extern int ptep_set_access_flags(struct vm_area_struct *vma,
 				 unsigned long address, pte_t *ptep,
 				 pte_t entry, int dirty);
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
+static inline int pmdp_set_access_flags(struct vm_area_struct *vma,
+					unsigned long address, pmd_t *pmdp,
+					pmd_t entry, int dirty)
+{
+	return ptep_set_access_flags(vma, address, (pte_t *)pmdp, pmd_pte(entry), dirty);
+}
+#endif
+
 /*
  * Atomic pte/pmd modifications.
  */


From catalin.marinas at arm.com  Thu May  5 02:44:01 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu,  5 May 2016 10:44:01 +0100
Subject: [PATCH 3/4] arm64: Replace hard-coded values in the pmd/pud_bad()
 macros
In-Reply-To: <1462441442-6996-1-git-send-email-catalin.marinas@arm.com>
References: <1462441442-6996-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <1462441442-6996-4-git-send-email-catalin.marinas@arm.com>

This patch replaces the hard-coded value 2 with PMD_TABLE_BIT in the
pmd/pud_bad() macros. Note that using these macros on pmd_trans_huge()
entries is giving incorrect results
(pmd_none_or_trans_huge_or_clear_bad() correctly checks for
pmd_trans_huge before pmd_bad).

Additionally, white-space clean-up for pmd_mkclean().

Reviewed-by: Will Deacon <will.deacon at arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---
 arch/arm64/include/asm/pgtable.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index bdfbaf96b426..a8b8f4eb7bff 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -305,7 +305,7 @@ static inline int pmd_protnone(pmd_t pmd)
 #define pmd_wrprotect(pmd)	pte_pmd(pte_wrprotect(pmd_pte(pmd)))
 #define pmd_mkold(pmd)		pte_pmd(pte_mkold(pmd_pte(pmd)))
 #define pmd_mkwrite(pmd)	pte_pmd(pte_mkwrite(pmd_pte(pmd)))
-#define pmd_mkclean(pmd)       pte_pmd(pte_mkclean(pmd_pte(pmd)))
+#define pmd_mkclean(pmd)	pte_pmd(pte_mkclean(pmd_pte(pmd)))
 #define pmd_mkdirty(pmd)	pte_pmd(pte_mkdirty(pmd_pte(pmd)))
 #define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
 #define pmd_mknotpresent(pmd)	(__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK))
@@ -349,7 +349,7 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 #define pmd_none(pmd)		(!pmd_val(pmd))
 #define pmd_present(pmd)	(pmd_val(pmd))
 
-#define pmd_bad(pmd)		(!(pmd_val(pmd) & 2))
+#define pmd_bad(pmd)		(!(pmd_val(pmd) & PMD_TABLE_BIT))
 
 #define pmd_table(pmd)		((pmd_val(pmd) & PMD_TYPE_MASK) == \
 				 PMD_TYPE_TABLE)
@@ -415,7 +415,7 @@ static inline phys_addr_t pmd_page_paddr(pmd_t pmd)
 #define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd))
 
 #define pud_none(pud)		(!pud_val(pud))
-#define pud_bad(pud)		(!(pud_val(pud) & 2))
+#define pud_bad(pud)		(!(pud_val(pud) & PUD_TABLE_BIT))
 #define pud_present(pud)	(pud_val(pud))
 
 static inline void set_pud(pud_t *pudp, pud_t pud)


From catalin.marinas at arm.com  Thu May  5 02:44:02 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu,  5 May 2016 10:44:02 +0100
Subject: [PATCH 4/4] arm64: Ensure pmd_present() returns false after
 pmd_mknotpresent()
In-Reply-To: <1462441442-6996-1-git-send-email-catalin.marinas@arm.com>
References: <1462441442-6996-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <1462441442-6996-5-git-send-email-catalin.marinas@arm.com>

Currently, pmd_present() only checks for a non-zero value, returning
true even after pmd_mknotpresent() (which only clears the type bits).
This patch converts pmd_present() to using pte_present(), similar to the
other pmd_*() checks. As a side effect, it will return true for
PROT_NONE mappings, though they are not yet used by the kernel with
transparent huge pages.

For consistency, also change pmd_mknotpresent() to only clear the
PMD_SECT_VALID bit, even though the PMD_TABLE_BIT is already 0 for block
mappings (no functional change). The unused PMD_SECT_PROT_NONE
definition is removed as transparent huge pages use the pte page prot
values.

Fixes: 9c7e535fcc17 ("arm64: mm: Route pmd thp functions through pte equivalents")
Cc: <stable at vger.kernel.org> # 3.15+
Reviewed-by: Will Deacon <will.deacon at arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---
 arch/arm64/include/asm/pgtable-hwdef.h | 1 -
 arch/arm64/include/asm/pgtable.h       | 4 ++--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 5c25b831273d..9786f770088d 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -133,7 +133,6 @@
  * Section
  */
 #define PMD_SECT_VALID		(_AT(pmdval_t, 1) << 0)
-#define PMD_SECT_PROT_NONE	(_AT(pmdval_t, 1) << 58)
 #define PMD_SECT_USER		(_AT(pmdval_t, 1) << 6)		/* AP[1] */
 #define PMD_SECT_RDONLY		(_AT(pmdval_t, 1) << 7)		/* AP[2] */
 #define PMD_SECT_S		(_AT(pmdval_t, 3) << 8)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index a8b8f4eb7bff..7b2806812d95 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -300,6 +300,7 @@ static inline int pmd_protnone(pmd_t pmd)
 #define pmd_trans_huge(pmd)	(pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
+#define pmd_present(pmd)	pte_present(pmd_pte(pmd))
 #define pmd_dirty(pmd)		pte_dirty(pmd_pte(pmd))
 #define pmd_young(pmd)		pte_young(pmd_pte(pmd))
 #define pmd_wrprotect(pmd)	pte_pmd(pte_wrprotect(pmd_pte(pmd)))
@@ -308,7 +309,7 @@ static inline int pmd_protnone(pmd_t pmd)
 #define pmd_mkclean(pmd)	pte_pmd(pte_mkclean(pmd_pte(pmd)))
 #define pmd_mkdirty(pmd)	pte_pmd(pte_mkdirty(pmd_pte(pmd)))
 #define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
-#define pmd_mknotpresent(pmd)	(__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK))
+#define pmd_mknotpresent(pmd)	(__pmd(pmd_val(pmd) & ~PMD_SECT_VALID))
 
 #define __HAVE_ARCH_PMD_WRITE
 #define pmd_write(pmd)		pte_write(pmd_pte(pmd))
@@ -347,7 +348,6 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 				     unsigned long size, pgprot_t vma_prot);
 
 #define pmd_none(pmd)		(!pmd_val(pmd))
-#define pmd_present(pmd)	(pmd_val(pmd))
 
 #define pmd_bad(pmd)		(!(pmd_val(pmd) & PMD_TABLE_BIT))
 


From tn at semihalf.com  Thu May  5 03:38:54 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Thu, 5 May 2016 12:38:54 +0200
Subject: [PATCH V6 07/13] PCI: Provide common functions for ECAM mapping
In-Reply-To: <CAKc_7PXG5QxaN=b0oZA7E=a-LhSg0q+FqmaVhViYnRfK4Z8jfQ@mail.gmail.com>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-8-git-send-email-tn@semihalf.com>
 <20160428214749.GF25125@localhost>
 <CAKc_7PUJQsUrCuOg1iafZ9amANk=E9eu0MrF=UOrVEVbseMz2w@mail.gmail.com>
 <CAKc_7PXG5QxaN=b0oZA7E=a-LhSg0q+FqmaVhViYnRfK4Z8jfQ@mail.gmail.com>
Message-ID: <572B22BE.3010501@semihalf.com>

On 05.05.2016 11:24, Jayachandran C wrote:
> On Fri, Apr 29, 2016 at 1:31 PM, Jayachandran C <jchandra at broadcom.com> wrote:
>> On Fri, Apr 29, 2016 at 3:17 AM, Bjorn Helgaas <helgaas at kernel.org> wrote:
>>> On Fri, Apr 15, 2016 at 07:06:42PM +0200, Tomasz Nowicki wrote:
>>>> From: Jayachandran C <jchandra at broadcom.com>
>>>>
>>>> Add config option PCI_GENERIC_ECAM and file drivers/pci/ecam.c to
>>>> provide generic functions for accessing memory mapped PCI config space.
>>>>
>>>> The API is defined in drivers/pci/ecam.h and is written to replace the
>>>> API in drivers/pci/host/pci-host-common.h. The file defines a new
>>>> 'struct pci_config_window' to hold the information related to a PCI
>>>> config area and its mapping. This structure is expected to be used as
>>>> sysdata for controllers that have ECAM based mapping.
>>>>
>>>> Helper functions are provided to setup the mapping, free the mapping
>>>> and to implement the map_bus method in 'struct pci_ops'
>>>
>>> Spec reference: PCI Express Base Specification, rev 3.0, sec 7.2.2.
>>>
>>>> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
>>>> ---
>>>>   drivers/pci/Kconfig  |   3 ++
>>>>   drivers/pci/Makefile |   2 +
>>>>   drivers/pci/ecam.c   | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>>>   drivers/pci/ecam.h   |  61 +++++++++++++++++++++++
>>>>   4 files changed, 203 insertions(+)
>>>>   create mode 100644 drivers/pci/ecam.c
>>>>   create mode 100644 drivers/pci/ecam.h
>>>>
>>>> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
>>>> index 209292e..e930d62 100644
>>>> --- a/drivers/pci/Kconfig
>>>> +++ b/drivers/pci/Kconfig
>>>> @@ -83,6 +83,9 @@ config HT_IRQ
>>>>   config PCI_ATS
>>>>        bool
>>>>
>>>> +config PCI_GENERIC_ECAM
>>>> +     bool
>>>
>>> "PCI_ECAM" is enough, I think.  It's defined by and required by the
>>> spec unless there's some arch-specific interface.  Plus, if I
>>
>> Ok. Looking at the comments I think I have to take out generic from
>> all the names - will do this in next version.
>>
>>> understand correctly, this infrastructure supports non-generic ECAM
>>> implementations as well, since the caller supplies "struct
>>> pci_generic_ecam_ops *ops".
>>
>> Yes, the idea was to support ECAM with quirks (and CAM) on both
>> 32 and 64 bit, otherwise it would be too trivial to have a separate
>> implementation.
>>
>>>>   config PCI_IOV
>>>>        bool "PCI IOV support"
>>>>        depends on PCI
>>>> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
>>>> index 2154092..810aec8 100644
>>>> --- a/drivers/pci/Makefile
>>>> +++ b/drivers/pci/Makefile
>>>> @@ -55,6 +55,8 @@ obj-$(CONFIG_PCI_SYSCALL) += syscall.o
>>>>
>>>>   obj-$(CONFIG_PCI_STUB) += pci-stub.o
>>>>
>>>> +obj-$(CONFIG_PCI_GENERIC_ECAM) += ecam.o
>>>> +
>>>>   obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
>>>>
>>>>   obj-$(CONFIG_OF) += of.o
>>>> diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
>>>> new file mode 100644
>>>> index 0000000..ff04c01
>>>> --- /dev/null
>>>> +++ b/drivers/pci/ecam.c
>>>> @@ -0,0 +1,137 @@
>>>> +/*
>>>> + * Copyright 2016 Broadcom
>>>> + *
>>>> + * 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 (the "GPL").
>>>> + *
>>>> + * 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 version 2 (GPLv2) for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU General Public License
>>>> + * version 2 (GPLv2) along with this source code.
>>>> + */
>>>> +
>>>> +#include <linux/device.h>
>>>> +#include <linux/io.h>
>>>> +#include <linux/kernel.h>
>>>> +#include <linux/module.h>
>>>> +#include <linux/pci.h>
>>>> +#include <linux/slab.h>
>>>> +
>>>> +#include "ecam.h"
>>>> +
>>>> +/*
>>>> + * On 64 bit systems, we do a single ioremap for the whole config space
>>>> + * since we have enough virtual address range available. On 32 bit, do an
>>>> + * ioremap per bus.
>>>> + */
>>>> +static const bool per_bus_mapping = !config_enabled(CONFIG_64BIT);
>>>> +
>>>> +/*
>>>> + * Create a PCI config space window
>>>> + *  - reserve mem region
>>>> + *  - alloc struct pci_config_window with space for all mappings
>>>> + *  - ioremap the config space
>>>> + */
>>>> +struct pci_config_window *pci_generic_ecam_create(struct device *dev,
>>>> +                             phys_addr_t addr, u8 bus_start, u8 bus_end,
>>>
>>> Can you take pointers to struct resources here instead of addr,
>>> bus_start, and bus_end?  The caller probably has them already, and
>>> then you could add a useful printk like:
>>>
>>>    dev_info(dev, "ECAM for %pR at %pR\n", busn_res, mmio_res);
>>>
>>> Would have to be careful about the struct resource lifetimes though.
>>
>> Yes, I had thought of this. The reason I did not go down that path was
>> that we are using request_mem_region() which takes the address
>> and creates a resource .internally.
>>
>> Beyond that, as you noted, the ownership and lifetime is slightly
>> more complex. Either the calling code has to allocate the
>> resource and handoff, or the ecam code has to make a copy of
>> the resource. I would go with copy since it is much more simple
>> to use.
>>
>> Since resource based API seems to be preferred, I will switch
>> to passing bus and mmio resource and will use
>> request_resource_conflict() to allocate the ECAM mem region,
>>
>>> If you had the MMIO resource here, you could also do the range
>>> checking you currently have in gen_pci_init() here instead, so all
>>> callers could benefit.
>>
>> Ok.
>>
>>>> +                             struct pci_generic_ecam_ops *ops)
>>>> +{
>>>> +     struct pci_config_window *cfg;
>>>> +     unsigned int bus_shift, bus_range, bsz, mapsz;
>>>> +     int i, nidx;
>>>> +     int err = -ENOMEM;
>>>> +
>>>> +     if (bus_end < bus_start)
>>>> +             return ERR_PTR(-EINVAL);
>>>> +
>>>> +     bus_shift = ops->bus_shift;
>>>> +     bus_range = bus_end - bus_start + 1;
>>>> +     bsz = 1 << bus_shift;
>>>> +     nidx = per_bus_mapping ? bus_range : 1;
>>>> +     mapsz = per_bus_mapping ? bsz : bus_range * bsz;
>>>> +     cfg = kzalloc(sizeof(*cfg) + nidx * sizeof(cfg->win[0]), GFP_KERNEL);
>>>> +     if (!cfg)
>>>> +             return ERR_PTR(-ENOMEM);
>>>> +
>>>> +     cfg->bus_start = bus_start;
>>>> +     cfg->bus_end = bus_end;
>>>> +     cfg->ops = ops;
>>>> +
>>>> +     if (!request_mem_region(addr, bus_range * bsz, "Configuration Space"))
>>>> +             goto err_exit;
>>>> +
>>>> +     /* cfgaddr has to be set after request_mem_region */
>>>> +     cfg->cfgaddr = addr;
>>>> +
>>>> +     for (i = 0; i < nidx; i++) {
>>>> +             cfg->win[i] = ioremap(addr + i * mapsz, mapsz);
>>>> +             if (!cfg->win[i])
>>>> +                     goto err_exit;
>>>> +     }
>>>> +
>>>> +     if (cfg->ops->init) {
>>>> +             err = cfg->ops->init(dev, cfg);
>>>> +             if (err)
>>>> +                     goto err_exit;
>>>> +     }
>>>> +     return cfg;
>>>> +
>>>> +err_exit:
>>>> +     pci_generic_ecam_free(cfg);
>>>> +     return ERR_PTR(err);
>>>> +}
>>>> +
>>>> +/*
>>>> + * Free a config space mapping
>>>> + */
>>>
>>> Superfluous comment.
>>
>> Ok, will trim comments to keep the ones that are useful.
>>
>>>> +void pci_generic_ecam_free(struct pci_config_window *cfg)
>>>> +{
>>>> +     unsigned int bus_range;
>>>> +     int i, nidx;
>>>> +
>>>> +     bus_range = cfg->bus_end - cfg->bus_start + 1;
>>>> +     nidx = per_bus_mapping ? bus_range : 1;
>>>> +     for (i = 0; i < nidx; i++)
>>>> +             if (cfg->win[i])
>>>> +                     iounmap(cfg->win[i]);
>>>> +     if (cfg->cfgaddr)
>>>> +             release_mem_region(cfg->cfgaddr,
>>>> +                                bus_range << cfg->ops->bus_shift);
>>>> +     kfree(cfg);
>>>> +}
>>>> +
>>>> +/*
>>>> + * Function to implement the pci_ops ->map_bus method
>>>> + */
>>>> +void __iomem *pci_generic_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
>>>> +                                    int where)
>>>> +{
>>>> +     struct pci_config_window *cfg = bus->sysdata;
>>>
>>> I don't really like the use of bus->sysdata here, because sysdata is
>>> explicitly arch-specific.
>>>
>>> But I guess we're in a bind right now: it'd be nice to save the cfg
>>> pointer in struct pci_host_bridge, but you have to call
>>> pci_generic_ecam_create() before the struct pci_host_bridge has been
>>> allocated, and you have to pass the pointer into pci_scan_root_bus(),
>>> and there's no generic way to do that yet.
>>>
>>> So I guess this will have to do for now.
>>
>> I could call the structure pci_ecam_sysdata instead of pci_config_window
>> to make it clear that it is to be used as sysdata for ECAM based PCI host
>> controllers.
>>
>> The current push (at least on ARM/ARM64) seems to be to make
>> bus->sysdata controller specific and avoid arch specific sysdata.
>>
>>>> +     unsigned int devfn_shift = cfg->ops->bus_shift - 8;
>>>> +     unsigned int busn = bus->number;
>>>> +     void __iomem *base;
>>>> +
>>>> +     if (busn < cfg->bus_start || busn > cfg->bus_end)
>>>> +             return NULL;
>>>> +
>>>> +     busn -= cfg->bus_start;
>>>> +     if (per_bus_mapping)
>>>> +             base = cfg->win[busn];
>>>> +     else
>>>> +             base = cfg->win[0] + (busn << cfg->ops->bus_shift);
>>>> +     return base + (devfn << devfn_shift) + where;
>>>> +}
>>>> +
>>>> +/* default ECAM ops */
>>>> +struct pci_generic_ecam_ops pci_generic_ecam_default_ops = {
>>>
>>> Using both "generic" and "default" seems overkill.  Maybe just:
>>>
>>>    struct pci_ecam_ops pci_generic_ecam_ops = { ... ?
>>
>> Ok.
>>
>>>> +     .bus_shift      = 20,
>>>> +     .pci_ops                = {
>>>> +             .map_bus        = pci_generic_ecam_map_bus,
>>>> +             .read           = pci_generic_config_read,
>>>> +             .write          = pci_generic_config_write,
>>>> +     }
>>>> +};
>>>> diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
>>>> new file mode 100644
>>>> index 0000000..34c0aba
>>>> --- /dev/null
>>>> +++ b/drivers/pci/ecam.h
>>>> @@ -0,0 +1,61 @@
>>>> +/*
>>>> + * Copyright 2016 Broadcom
>>>> + *
>>>> + * 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 (the "GPL").
>>>> + *
>>>> + * 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 version 2 (GPLv2) for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU General Public License
>>>> + * version 2 (GPLv2) along with this source code.
>>>> + */
>>>> +#ifndef DRIVERS_PCI_ECAM_H
>>>> +#define DRIVERS_PCI_ECAM_H
>>>> +
>>>> +#include <linux/kernel.h>
>>>> +#include <linux/platform_device.h>
>>>> +
>>>> +/*
>>>> + * struct to hold pci ops and bus shift of the config window
>>>> + * for a PCI controller.
>>>> + */
>>>> +struct pci_config_window;
>>>> +struct pci_generic_ecam_ops {
>>>
>>> "struct pci_ecam_ops"
>>
>> Ok.
>>
>>>> +     unsigned int                    bus_shift;
>>>> +     struct pci_ops                  pci_ops;
>>>> +     int                             (*init)(struct device *,
>>>> +                                             struct pci_config_window *);
>>>> +};
>>>> +
>>>> +/*
>>>> + * struct to hold the mappings of a config space window. This
>>>> + * will be allocated with enough entries in win[] to hold all
>>>> + * the mappings for the bus range.
>>>> + */
>>>> +struct pci_config_window {
>>>> +     phys_addr_t                     cfgaddr;
>>>> +     u16                             domain;
>>>> +     u8                              bus_start;
>>>> +     u8                              bus_end;
>>>> +     void                            *priv;
>>>> +     struct pci_generic_ecam_ops     *ops;
>>>> +     void __iomem                    *win[0];
>>>> +};
>>>> +
>>>> +/* create and free for pci_config_window */
>>>
>>> Superfluous comment.
>>>
>>>> +struct pci_config_window *pci_generic_ecam_create(struct device *dev,
>>>> +                             phys_addr_t addr, u8 bus_start, u8 bus_end,
>>>> +                             struct pci_generic_ecam_ops *ops);
>>>> +void pci_generic_ecam_free(struct pci_config_window *cfg);
>>>
>>> "pci_ecam_create" and "pci_ecam_free"?  I suspect you're going to call
>>> these for flavors of ECAM that are definitely not "generic".
>>>
>>>> +/* map_bus when ->sysdata is an instance of pci_config_window */
>>>> +void __iomem *pci_generic_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
>>>> +                                    int where);
>>>> +/* default ECAM ops, bus shift 20, generic read and write */
>>>> +extern struct pci_generic_ecam_ops pci_generic_ecam_default_ops;
>>>> +
>>>> +#endif
>>
>> Thanks for the review. The ECAM patchset can be merged separately
>> if you do not want to tie it the ACPI changes.
>>
>> Please let me know how you want to proceed. Depending on that, I will
>> either post it as a separate patchset or ask Tomasz to pick up my
>> changes and post the ACPI patchset. again.
>
> I have made the changes suggested here, and added one more
> change to move from 'void __iomem *win[0]' to a union for
> pci_config_window so that it can be embedded in other structures[1].
>
> The changes are at https://github.com/jchandra-brcm/linux branch
> arm64-acpi-pci-v4 so that Tomasz can add it to v7 of the ACPI/PCI
> patches. I am not posting the changes here to avoid the impression
> that there are clashing ACPI/PCI patchsets.
>
> The branch also has an example patch for ACPI generic PCI root
> using the new ECAM code. This also has the simpler domain
> setting code for ACPI as well as fix for the ECAM address
> calculation which came up during the earlier discussion.
>
> JC.
> [1] Minor API changes will be needed for embedding now.
>      This change will make it easier to merge with Arnd's host bridge
>      changes when that goes in.
>

Thanks JC!

Tomasz


From garlic.tseng at mediatek.com  Thu May  5 03:39:32 2016
From: garlic.tseng at mediatek.com (Garlic Tseng)
Date: Thu, 5 May 2016 18:39:32 +0800
Subject: [alsa-devel] [PATCH 1/7] ASoC: mediatek: Refine mt8173 driver
 and change config option
In-Reply-To: <572B0511.80701@gmail.com>
References: <1461934848-60011-1-git-send-email-garlic.tseng@mediatek.com>
 <1461934848-60011-2-git-send-email-garlic.tseng@mediatek.com>
 <20160504164306.GA6292@sirena.org.uk>
 <1462416342.25179.36.camel@mtksdaap41> <572B0511.80701@gmail.com>
Message-ID: <1462444772.2873.70.camel@mtksdaap41>

On Thu, 2016-05-05 at 10:32 +0200, Matthias Brugger wrote:
> 
> On 05/05/16 04:45, Garlic Tseng wrote:
> > On Wed, 2016-05-04 at 17:43 +0100, Mark Brown wrote:
> >> On Fri, Apr 29, 2016 at 09:00:42PM +0800, Garlic Tseng wrote:
> >>
> >>>   .../{mtk-afe-pcm.c => mt8173/mt8173-afe-pcm.c}     | 488 ++++++++++-----------
> >>
> >> So there's going to be no code sharing at all between this and any other
> >> Mediatek chips?  That seems very surprising, it'd suggest that the
> >> hardware designers were creating a new design completely from scratch
> >> each time which doesn't seem all that likely.  This is an unusual way of
> >> organizing things and we need a much clearer explanation of what's going
> >> on here.
> >
> > MT8173 and MT2701 are from different product lines so the register
> > control sequences are very different. If another driver for 8173-like
> > (or 2701-like) chip go upstream it shall share some common code with the
> > relatively driver indeed. However I think MT8173 and MT2701 can't share
> > the platform driver or a lot of "if MT8173 else MT2701" will mess up the
> > code.
> >
> 
> What about the other SoCs we have some minimal support for: mt6589, 
> mt8135, mt6592, mt6580, mt7323, mt8127?
> 
> A quick glance at the datasheets showed me, that mt6589 and at least 
> mt8127 have quite similar register offsets. So I suppose there is some 
> common code actually.

Well, the last ASoC driver only support mt8173, and we try to add the
support for mt2701. As I mentioned, the ASoCs of the two chips have very
different control sequence, so make the platform driver common will mess
up the code. If there are some chips we want to support in the future
and the ASoC part is similar with mt8173 (or mt2701), then it shall
share some common code with the relative driver.

The ASoC hardwares has lots of differences between mt8173 and mt2701.

Mt8173 only support 2ch memory interface, whereas mt2701 has different
hardware to support four memory interface, which can group together as a
8-ch memory interface, separate as four 2-ch memory interfaces, or
function as one 4-ch memory interface and two 2-ch memory interfaces.
That makes the control sequence different and the FE dais can't share.

Mt8173 only support 2ch i2s playback/capture separately, but mt2701 has
different i2s hardware so that four i2s can sync together to preform 8ch
playback/capture. Same as the memory interface, the i2s can separate as
2ch i2s and works simultaneously. The i2s hardware has a limitation that
when i2s-in enable, i2s-out must be enable to function well. The i2s
hardware is so different that we can't share BE-dai code.

The connection between FE and BE also differ between the two chips.
Mt2701 has much more port then mt8173. However mt2701 can still fit in
DAPM structure (just control a register bit to connect/disconnect two
ports).

The irq and the clock are also different. Mt2701 support higher rate irq
than mt8173; mt2701 has too many memory interface so it needs to
dynamically request irq when needed; the clock structure also different
between them.

As mentioned above, the difference of the ASoCs between the two chips
are too large that we have a hard time sharing the driver code.

> Regards,
> Matthias




From arnd at arndb.de  Thu May  5 04:10:31 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 05 May 2016 13:10:31 +0200
Subject: [v10,
 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-R1.0-R2.0
In-Reply-To: <HE1PR04MB0889B52134A43C0E7A452B7BF87C0@HE1PR04MB0889.eurprd04.prod.outlook.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <4448030.Zs8fVnr3nm@wuerfel>
 <HE1PR04MB0889B52134A43C0E7A452B7BF87C0@HE1PR04MB0889.eurprd04.prod.outlook.com>
Message-ID: <5159406.HOFrj7pRfW@wuerfel>

On Thursday 05 May 2016 09:41:32 Yangbo Lu wrote:
> > -----Original Message-----
> > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > Sent: Thursday, May 05, 2016 4:32 PM
> > To: linuxppc-dev at lists.ozlabs.org
> > Cc: Yangbo Lu; linux-mmc at vger.kernel.org; devicetree at vger.kernel.org;
> > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> > linux-clk at vger.kernel.org; linux-i2c at vger.kernel.org; iommu at lists.linux-
> > foundation.org; netdev at vger.kernel.org; Mark Rutland;
> > ulf.hansson at linaro.org; Russell King; Bhupesh Sharma; Joerg Roedel;
> > Santosh Shilimkar; Yang-Leo Li; Scott Wood; Rob Herring; Claudiu Manoil;
> > Kumar Gala; Xiaobo Xie; Qiang Zhao
> > Subject: Re: [v10, 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-
> > R1.0-R2.0
> > 
> > On Thursday 05 May 2016 11:12:30 Yangbo Lu wrote:
> > >
> > > +       fsl_guts_init();
> > > +       svr = fsl_guts_get_svr();
> > > +       if (svr) {
> > > +               esdhc->soc_ver = SVR_SOC_VER(svr);
> > > +               esdhc->soc_rev = SVR_REV(svr);
> > > +       } else {
> > > +               dev_err(&pdev->dev, "Failed to get SVR value!\n");
> > > +       }
> > > +
> > >
> > 
> > 
> > Sorry for jumping in again after not participating in the discussion for
> > the past few versions.
> > 
> > What happened to my suggestion of making this a platform-independent
> > interface to avoid the link time dependency?
> > 
> > Specifically, why not add an exported function to drivers/base/soc.c that
> > uses glob_match() for comparing a string in the device driver to the ID
> > of the SoC that is set by whatever SoC identifying driver the platform
> > has?
> 
> [Lu Yangbo-B47093] I think this has been discussed in v6.
> You can find Scott's comments about this in below link.
> https://patchwork.kernel.org/patch/8544501/

Ah, thanks for bearing with me and digging this out again. Let me follow
up on Scott's older replies here then:

> >> IIRC, it is the same IP block as i.MX and Arnd's point is this won't
> >> even compile on !PPC. It is things like this that prevent sharing the
> >> driver.
> 
> The whole point of using the MMIO SVR instead of the PPC SPR is so that
> it will work on ARM...  The guts driver should build on any platform as
> long as OF is enabled, and if it doesn't find a node to bind to it will
> return 0 for SVR, and the eSDHC driver will continue (after printing an
> error that should be removed) without the ability to test for errata
> based on SVR.

It feels like a bad design to have to come up with a different
method for each SoC type here when they all do the same thing
and want to identify some variant of the chip to do device
specific quirks.

As far as I'm concerned, every driver in drivers/soc that needs to
export a symbol to be used by a device driver is an indication that
we don't have the right set of abstractions yet. There are cases
that are not worth abstracting because the functionality is rather
obscure and only a couple of drivers for one particular chip
ever need it.

Finding out the version of the SoC does not look like this case.

> > I think the first four patches take care of building for ARM,
> > but the problem remains if you want to enable COMPILE_TEST as
> > we need for certain automated checking.
> 
> What specific problem is there with COMPILE_TEST?

COMPILE_TEST is solvable here and the way it is implemented in this
case (selecting FSL_GUTS from the driver) indeed looks like it works
correctly, but it's still awkward that this means building the
SoC specific ID stuff into the vmlinux binary for any driver that
uses something like that for a particular SoC.

> >> Dealing with Si revs is a common problem. We should have a
> >> common solution. There is soc_device for this purpose.
> > 
> > Exactly. The last time this came up, I think we agreed to implement a
> > helper using glob_match() on the soc_device strings. Unfortunately
> > this hasn't happened then, but I'd still prefer that over yet another
> > vendor-specific way of dealing with the generic issue.
> 
> soc_device would require encoding the SVR as a string and then decoding
> the string, which is more complicated and error prone than having
> platform-specific code test a platform-specific number. 

You already need to encode it as a string to register the soc_device,
and the driver just needs to pass a glob string, so the only part that
is missing is the generic function that takes the string from the
driver and passes that to glob_match for the soc_device.

> And when would it get registered on arm64, which doesn't have
> platform code?

Whenever the soc driver is loaded, as is the case now. The match
function can return -EPROBE_DEFER if no SoC device is registered
yet.

	Arnd


From andre.przywara at arm.com  Thu May  5 04:24:56 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 5 May 2016 12:24:56 +0100
Subject: [PATCH v2 14/54] KVM: arm/arm64: vgic-new: Implement virtual IRQ
 injection
In-Reply-To: <57293844.1060802@linaro.org>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-15-git-send-email-andre.przywara@arm.com>
 <57293844.1060802@linaro.org>
Message-ID: <572B2D88.3050504@arm.com>

Hi Tom,

thanks for looking at the patches!

On 04/05/16 00:46, Tom Hanson wrote:
> On 04/28/2016 10:45 AM, Andre Przywara wrote:
> ...
>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>> index fb45537..92b78a0 100644
>> --- a/virt/kvm/arm/vgic/vgic.c
>> +++ b/virt/kvm/arm/vgic/vgic.c
>> @@ -19,8 +19,31 @@
> ... 
>> +/*
>> + * Locking order is always:
>> + *   vgic_cpu->ap_list_lock
>> + *     vgic_irq->irq_lock
>> + *
>> + * (that is, always take the ap_list_lock before the struct vgic_irq
>> lock).
>> + *
>> + * When taking more than one ap_list_lock at the same time, always
>> take the
>> + * lowest numbered VCPU's ap_list_lock first, so:
>> + *   vcpuX->vcpu_id < vcpuY->vcpu_id:
>> + *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
>> + *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
>> + */
> 
> The code would be safer and easier to maintain in the long run if there
> were functions provided which implement these 2 rules.  Something along
> the line of:
> 
>   void vgic_lock_aplist_irq(spinlock_t ap_list_lock, spinlock_t irq_lock){
>       spin_lock(ap_list_lock);
>       spin_lock(irq_lock);
>   }

The idea isn't too bad indeed.
I see that we could use that in vgic_queue_irq_unlock() and
vgic_mmio_write_sactive().
But as Marc mentioned in a conversation yesterday we will have a mixture
of wrapped locks and open coded lock sequences. See for instance
vgic_prune_ap_list(), where we have the sequence, but we can't use
vgic_lock_aplist_irq() because the IRQ lock is taken inside the loop
while the ap_list_lock is taken once outside of it.

Marc, Christoffer, what is your opinion here?

> and  (borrowing from patch 16/54):
> 
>   void vgic_lock_cpu_aplist_pair(struct kvm_vcpu *vcpu1, struct kvm_vcpu
> *vcpu2){
>       struct kvm_vcpu *vcpuA, *vcpuB;
>       /*
>        * Ensure locking order by always locking the smallest
>        * ID first.
>        */
>      if (vcpu1->vcpu_id < vcpu2->vcpu_id) {
>           vcpuA = vcpu1;
>           vcpuB = vcpu2;
>       } else {
>           vcpuA = vcpu2;
>           vcpuB = vcpu1;
>       }
> 
>       spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
>       spin_lock(&vcpuB->arch.vgic_cpu.ap_list_lock);
>   }

I am not sure this is worth it. We have exactly one user of this
sequence, so I'd rather keep it and the comments there.
Also the use case is probably confined to the core VGIC code.

Cheers,
Andre.

> 
> With, of course the matching unlock functions.
> 
> Then, as long as new code calls the correct function, the order is
> always correct.  Easy to write, easy to review.  And beats the heck out
> of chasing a deadlock at some point in the future.
> 


From k.kozlowski at samsung.com  Thu May  5 05:34:16 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:16 +0200
Subject: [RFC v2 03/13] MAINTAINERS: Retain Ulf Hansson as the same maintainer
 of pwrseq
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-4-git-send-email-k.kozlowski@samsung.com>

Before moving pwrseq drivers from drivers/mmc/core/ to drivers/power/,
they were maintained by Ulf Hansson.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index b016f447c6c9..2c501b795d18 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8874,6 +8874,14 @@ F:	include/linux/power_supply.h
 F:	drivers/power/
 X:	drivers/power/avs/
 
+POWER SEQ CORE and DRIVERS
+M:	Ulf Hansson <ulf.hansson at linaro.org>
+L:	linux-mmc at vger.kernel.org
+T:	git git://git.linaro.org/people/ulf.hansson/mmc.git
+S:	Maintained
+F:	drivers/power/pwrseq/
+F:	include/linux/pwrseq.h
+
 POWER STATE COORDINATION INTERFACE (PSCI)
 M:	Mark Rutland <mark.rutland at arm.com>
 M:	Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:22 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:22 +0200
Subject: [RFC v2 09/13] power: pwrseq: Add support for USB hubs with external
 power
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-10-git-send-email-k.kozlowski@samsung.com>

Some USB devices on embedded boards have external power supply which has
to be reset in certain conditions. Add pwrseq interface for this.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/power/pwrseq/pwrseq.c | 44 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/pwrseq.h        |  8 ++++++++
 2 files changed, 52 insertions(+)

diff --git a/drivers/power/pwrseq/pwrseq.c b/drivers/power/pwrseq/pwrseq.c
index 495a19d3c30b..306265f55a10 100644
--- a/drivers/power/pwrseq/pwrseq.c
+++ b/drivers/power/pwrseq/pwrseq.c
@@ -52,6 +52,43 @@ int mmc_pwrseq_alloc(struct mmc_host *host)
 }
 EXPORT_SYMBOL_GPL(mmc_pwrseq_alloc);
 
+struct pwrseq *pwrseq_alloc(struct device *dev)
+{
+	struct device_node *np;
+	struct pwrseq *p, *ret = NULL;
+
+	np = of_parse_phandle(dev->of_node, "usb-pwrseq", 0);
+	if (!np)
+		return NULL;
+
+	mutex_lock(&pwrseq_list_mutex);
+	list_for_each_entry(p, &pwrseq_list, pwrseq_node) {
+		if (p->dev->of_node == np) {
+			if (!try_module_get(p->owner))
+				dev_err(dev,
+					"increasing module refcount failed\n");
+			else
+				ret = p;
+
+			break;
+		}
+	}
+
+	of_node_put(np);
+	mutex_unlock(&pwrseq_list_mutex);
+
+	/* FIXME: this path can be simplified... */
+	if (!ret) {
+		dev_info(dev, "usb-pwrseq defer\n");
+		return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	dev_info(dev, "allocated usb-pwrseq\n");
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pwrseq_alloc);
+
 void pwrseq_pre_power_on(struct pwrseq *pwrseq)
 {
 	if (pwrseq && pwrseq->ops->pre_power_on)
@@ -84,6 +121,13 @@ void mmc_pwrseq_free(struct mmc_host *host)
 }
 EXPORT_SYMBOL_GPL(mmc_pwrseq_free);
 
+void pwrseq_free(const struct pwrseq *pwrseq)
+{
+	if (pwrseq)
+		module_put(pwrseq->owner);
+}
+EXPORT_SYMBOL_GPL(pwrseq_free);
+
 int pwrseq_register(struct pwrseq *pwrseq)
 {
 	if (!pwrseq || !pwrseq->ops || !pwrseq->dev)
diff --git a/include/linux/pwrseq.h b/include/linux/pwrseq.h
index fcc8fd855d4c..c3c91f50e4cb 100644
--- a/include/linux/pwrseq.h
+++ b/include/linux/pwrseq.h
@@ -31,9 +31,13 @@ void pwrseq_unregister(struct pwrseq *pwrseq);
 void pwrseq_pre_power_on(struct pwrseq *pwrseq);
 void pwrseq_post_power_on(struct pwrseq *pwrseq);
 void pwrseq_power_off(struct pwrseq *pwrseq);
+
 int mmc_pwrseq_alloc(struct mmc_host *host);
 void mmc_pwrseq_free(struct mmc_host *host);
 
+struct pwrseq *pwrseq_alloc(struct device *dev);
+void pwrseq_free(const struct pwrseq *pwrseq);
+
 #else /* CONFIG_POWER_SEQ */
 
 static inline int pwrseq_register(struct pwrseq *pwrseq)
@@ -44,9 +48,13 @@ static inline void pwrseq_unregister(struct pwrseq *pwrseq) {}
 static inline void pwrseq_pre_power_on(struct pwrseq *pwrseq) {}
 static inline void pwrseq_post_power_on(struct pwrseq *pwrseq) {}
 static inline void pwrseq_power_off(struct pwrseq *pwrseq) {}
+
 static inline int mmc_pwrseq_alloc(struct mmc_host *host) { return 0; }
 static inline void mmc_pwrseq_free(struct mmc_host *host) {}
 
+static inline struct pwrseq *pwrseq_alloc(struct device *dev) { return NULL; }
+static inline void pwrseq_free(const struct pwrseq *pwrseq) {}
+
 #endif /* CONFIG_POWER_SEQ */
 
 #endif /* _LINUX_PWRSEQ_H */
-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:14 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:14 +0200
Subject: [RFC v2 01/13] usb: misc: usb3503: Clean up on driver unbind
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-2-git-send-email-k.kozlowski@samsung.com>

The driver should clean up after itself by unpreparing the clock when it
is unbound.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/usb/misc/usb3503.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index b45cb77c0744..a464636675a6 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -330,6 +330,19 @@ static int usb3503_i2c_probe(struct i2c_client *i2c,
 	return usb3503_probe(hub);
 }
 
+static int usb3503_i2c_remove(struct i2c_client *i2c)
+{
+	struct usb3503 *hub;
+
+	hub = i2c_get_clientdata(i2c);
+	if (hub) {
+		if (hub->clk)
+			clk_disable_unprepare(hub->clk);
+	}
+
+	return 0;
+}
+
 static int usb3503_platform_probe(struct platform_device *pdev)
 {
 	struct usb3503 *hub;
@@ -342,6 +355,19 @@ static int usb3503_platform_probe(struct platform_device *pdev)
 	return usb3503_probe(hub);
 }
 
+static int usb3503_platform_remove(struct platform_device *pdev)
+{
+	struct usb3503 *hub;
+
+	hub = platform_get_drvdata(pdev);
+	if (hub) {
+		if (hub->clk)
+			clk_disable_unprepare(hub->clk);
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int usb3503_i2c_suspend(struct device *dev)
 {
@@ -395,6 +421,7 @@ static struct i2c_driver usb3503_i2c_driver = {
 		.of_match_table = of_match_ptr(usb3503_of_match),
 	},
 	.probe		= usb3503_i2c_probe,
+	.remove		= usb3503_i2c_remove,
 	.id_table	= usb3503_id,
 };
 
@@ -404,6 +431,7 @@ static struct platform_driver usb3503_platform_driver = {
 		.of_match_table = of_match_ptr(usb3503_of_match),
 	},
 	.probe		= usb3503_platform_probe,
+	.remove		= usb3503_platform_remove,
 };
 
 static int __init usb3503_init(void)
-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:24 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:24 +0200
Subject: [RFC v2 11/13] usb: port: Parse pwrseq phandle from Device Tree
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-12-git-send-email-k.kozlowski@samsung.com>

Parse usb-pwrseq property from Device Tree to get the phandle to pwrseq
device. The pwrseq device will be used by USB hub to cycle the power
before activating ports.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/usb/core/hub.h  |  3 +++
 drivers/usb/core/port.c | 15 +++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 34c1a7e22aae..68ca89780d26 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -24,6 +24,8 @@
 #include <linux/usb/hcd.h>
 #include "usb.h"
 
+struct pwrseq;
+
 struct usb_hub {
 	struct device		*intfdev;	/* the "interface" device */
 	struct usb_device	*hdev;
@@ -101,6 +103,7 @@ struct usb_port {
 	struct usb_dev_state *port_owner;
 	struct usb_port *peer;
 	struct dev_pm_qos_request *req;
+	struct pwrseq *pwrseq;
 	enum usb_port_connect_type connect_type;
 	usb_port_location_t location;
 	struct mutex status_lock;
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index 14718a9ffcfb..a875bd342452 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -18,6 +18,8 @@
 
 #include <linux/slab.h>
 #include <linux/pm_qos.h>
+#include <linux/pwrseq.h>
+#include <linux/usb/of.h>
 
 #include "hub.h"
 
@@ -532,6 +534,14 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
 		return retval;
 	}
 
+	port_dev->dev.of_node = usb_of_get_child_node(hub->hdev->dev.of_node, port1);
+	port_dev->pwrseq = pwrseq_alloc(&port_dev->dev);
+	if (IS_ERR(port_dev->pwrseq)) {
+		device_unregister(&port_dev->dev);
+		/* TODO: what about EPROBE_DEFER? */
+		return PTR_ERR(port_dev->pwrseq);
+	}
+
 	find_and_link_peer(hub, port1);
 
 	/*
@@ -573,8 +583,13 @@ void usb_hub_remove_port_device(struct usb_hub *hub, int port1)
 	struct usb_port *port_dev = hub->ports[port1 - 1];
 	struct usb_port *peer;
 
+	pwrseq_power_off(port_dev->pwrseq);
+
 	peer = port_dev->peer;
 	if (peer)
 		unlink_peers(port_dev, peer);
+
+	pwrseq_free(port_dev->pwrseq);
+	port_dev->pwrseq = NULL;
 	device_unregister(&port_dev->dev);
 }
-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:20 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:20 +0200
Subject: [RFC v2 07/13] power: pwrseq: simple: Add support for toggling
 regulator
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-8-git-send-email-k.kozlowski@samsung.com>

Some devices need real hard-reset by cutting the power.  During power
sequence turn off and on the regulator, if it is provided.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 .../devicetree/bindings/mmc/mmc-pwrseq-simple.txt  |  2 +
 drivers/power/pwrseq/pwrseq_simple.c               | 50 ++++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
index ce0e76749671..176ff831e7f1 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
@@ -16,6 +16,7 @@ Optional properties:
   See ../clocks/clock-bindings.txt for details.
 - clock-names : Must include the following entry:
   "ext_clock" (External clock provided to the card).
+- ext-supply : External regulator supply
 
 Example:
 
@@ -24,4 +25,5 @@ Example:
 		reset-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
 		clocks = <&clk_32768_ck>;
 		clock-names = "ext_clock";
+		ext-supply = <&buck8>;
 	}
diff --git a/drivers/power/pwrseq/pwrseq_simple.c b/drivers/power/pwrseq/pwrseq_simple.c
index ab0098412690..4d5ea53d3ead 100644
--- a/drivers/power/pwrseq/pwrseq_simple.c
+++ b/drivers/power/pwrseq/pwrseq_simple.c
@@ -16,7 +16,9 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
 #include <linux/pwrseq.h>
+#include <linux/delay.h>
 
 #include <linux/mmc/host.h>
 
@@ -25,6 +27,7 @@ struct mmc_pwrseq_simple {
 	bool clk_enabled;
 	struct clk *ext_clk;
 	struct gpio_descs *reset_gpios;
+	struct regulator *ext_reg;
 };
 
 #define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq)
@@ -62,6 +65,13 @@ static void mmc_pwrseq_simple_post_power_on(struct pwrseq *_pwrseq)
 {
 	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(_pwrseq);
 
+	if (pwrseq->ext_reg) {
+		int err;
+
+		err = regulator_enable(pwrseq->ext_reg);
+		WARN_ON_ONCE(err);
+	}
+
 	mmc_pwrseq_simple_set_gpios_value(pwrseq, 0);
 }
 
@@ -75,6 +85,13 @@ static void mmc_pwrseq_simple_power_off(struct pwrseq *_pwrseq)
 		clk_disable_unprepare(pwrseq->ext_clk);
 		pwrseq->clk_enabled = false;
 	}
+
+	if (pwrseq->ext_reg) {
+		int err;
+
+		err = regulator_disable(pwrseq->ext_reg);
+		WARN_ON_ONCE(err);
+	}
 }
 
 static const struct pwrseq_ops mmc_pwrseq_simple_ops = {
@@ -102,6 +119,32 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
 	if (IS_ERR(pwrseq->ext_clk) && PTR_ERR(pwrseq->ext_clk) != -ENOENT)
 		return PTR_ERR(pwrseq->ext_clk);
 
+	/* FIXME: regulator_get_exclusive? */
+	pwrseq->ext_reg = devm_regulator_get_optional(dev, "ext");
+	if (IS_ERR(pwrseq->ext_reg)) {
+		if (PTR_ERR(pwrseq->ext_reg) == -ENODEV)
+			pwrseq->ext_reg = NULL;
+		else
+			return PTR_ERR(pwrseq->ext_reg);
+	} else {
+		int err;
+		/*
+		 * Be sure that regulator is off, before the driver will start
+		 * power sequence. It is likely that regulator is on by default
+		 * and it without toggling it here, it would be disabled much
+		 * later by the core.
+		 */
+
+		err = regulator_enable(pwrseq->ext_reg);
+		WARN_ON_ONCE(err);
+
+		/* FIXME: handle this in a more sensible way */
+		mdelay(10);
+
+		err = regulator_disable(pwrseq->ext_reg);
+		WARN_ON_ONCE(err);
+	}
+
 	pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset",
 							GPIOD_OUT_HIGH);
 	if (IS_ERR(pwrseq->reset_gpios) &&
@@ -124,6 +167,13 @@ static int mmc_pwrseq_simple_remove(struct platform_device *pdev)
 
 	pwrseq_unregister(&pwrseq->pwrseq);
 
+	if (pwrseq->ext_reg) {
+		int err;
+
+		err = regulator_disable(pwrseq->ext_reg);
+		WARN_ON_ONCE(err);
+	}
+
 	return 0;
 }
 
-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:13 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:13 +0200
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
Message-ID: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>

Hi,

This is a different, second try to fix usb3503+lan on Odroid U3 board
if it was initialized by bootloader (e.g. for TFTP boot).

First version:
http://www.spinics.net/lists/linux-usb/msg140042.html


Problem
=======
When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
the usb3503 and LAN smsc95xx do not show up in "lsusb". Hard-reset
is required, e.g. by suspend to RAM. The actual TFTP boot does
not have to happen. Just "usb start" from U-Boot is sufficient.

>From the schematics, the regulator is a supply only to LAN, however
without toggling it off/on, the usb3503 hub won appear neither.


Solution
========
This is very similar to the MMC pwrseq behavior so the idea is to:
1. Move MMC pwrseq drivers to generic place,
2. Extend the pwrseq-simple with regulator toggling,
3. Add support to USB hub and port core for pwrseq,
4. Toggle the regulator when needed.


Issues
======
I am not familiar with USB subsystem, so please kindly guide me
where USB related code should be placed.

In the code there are still some issues to solve (FIXME/TODO notes).
If the approach is okay, I will improve the patchset. However at this
point - IT WORKS, which is nice. :)


Best regards,
Krzysztof

Krzysztof Kozlowski (13):
  usb: misc: usb3503: Clean up on driver unbind
  power/mmc: Move pwrseq drivers to power/pwrseq
  MAINTAINERS: Retain Ulf Hansson as the same maintainer of pwrseq
  power: pwrseq: Enable COMPILE_TEST for drivers
  power: pwrseq: Remove mmc prefix from mmc_pwrseq
  power: pwrseq: Generalize mmc_pwrseq operations by removing mmc prefix
  power: pwrseq: simple: Add support for toggling regulator
  usb: hub: Handle deferred probe
  power: pwrseq: Add support for USB hubs with external power
  usb: hub: Power sequence the ports on activation
  usb: port: Parse pwrseq phandle from Device Tree
  ARM: dts: exynos: Switch the buck8 to GPIO mode on Odroid U3
  ARM: dts: exynos: Fix LAN and HUB after bootloader initialization on
    Odroid U3

 .../devicetree/bindings/mmc/mmc-pwrseq-simple.txt  |  2 +
 MAINTAINERS                                        |  8 +++
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi    |  2 +-
 arch/arm/boot/dts/exynos4412-odroidu3.dts          |  7 ++
 drivers/mmc/Kconfig                                |  2 -
 drivers/mmc/core/Makefile                          |  3 -
 drivers/mmc/core/core.c                            |  8 +--
 drivers/mmc/core/host.c                            |  2 +-
 drivers/mmc/core/pwrseq.h                          | 52 --------------
 drivers/power/Kconfig                              |  1 +
 drivers/power/Makefile                             |  1 +
 drivers/{mmc/core => power/pwrseq}/Kconfig         | 21 ++++--
 drivers/power/pwrseq/Makefile                      |  3 +
 drivers/{mmc/core => power/pwrseq}/pwrseq.c        | 80 +++++++++++++++++-----
 drivers/{mmc/core => power/pwrseq}/pwrseq_emmc.c   | 15 ++--
 drivers/{mmc/core => power/pwrseq}/pwrseq_simple.c | 73 ++++++++++++++++----
 drivers/usb/core/hub.c                             | 17 ++++-
 drivers/usb/core/hub.h                             |  3 +
 drivers/usb/core/port.c                            | 15 ++++
 drivers/usb/misc/usb3503.c                         | 28 ++++++++
 include/linux/mmc/host.h                           |  4 +-
 include/linux/pwrseq.h                             | 60 ++++++++++++++++
 22 files changed, 294 insertions(+), 113 deletions(-)
 delete mode 100644 drivers/mmc/core/pwrseq.h
 rename drivers/{mmc/core => power/pwrseq}/Kconfig (65%)
 create mode 100644 drivers/power/pwrseq/Makefile
 rename drivers/{mmc/core => power/pwrseq}/pwrseq.c (50%)
 rename drivers/{mmc/core => power/pwrseq}/pwrseq_emmc.c (89%)
 rename drivers/{mmc/core => power/pwrseq}/pwrseq_simple.c (64%)
 create mode 100644 include/linux/pwrseq.h

-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:26 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:26 +0200
Subject: [RFC v2 13/13] ARM: dts: exynos: Fix LAN and HUB after bootloader
 initialization on Odroid U3
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-14-git-send-email-k.kozlowski@samsung.com>

On Odroid U3 (Exynos4412-based) board if USB was initialized by
bootloader (in U-Boot "usb start" before tftpboot), the HUB (usb3503)
and LAN (smsc95xx) after after successful probing were not visible in the
system ("lsusb").

In such case the devices had to be fully reset before configuring.
Reset by GPIO (called RESET_N pin) and by RESET field in STCD register
in usb3503 HUB are not sufficient. Instead full reset has to be done by
disabling and enabling regulator.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi | 2 +-
 arch/arm/boot/dts/exynos4412-odroidu3.dts       | 6 ++++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
index 14e653e32e0f..efa204a85c83 100644
--- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -67,7 +67,7 @@
 		};
 	};
 
-	emmc_pwrseq: pwrseq {
+	emmc_pwrseq: pwrseq1 {
 		pinctrl-0 = <&sd1_cd>;
 		pinctrl-names = "default";
 		compatible = "mmc-pwrseq-emmc";
diff --git a/arch/arm/boot/dts/exynos4412-odroidu3.dts b/arch/arm/boot/dts/exynos4412-odroidu3.dts
index 31cdc036fda4..3da0e6b3c32a 100644
--- a/arch/arm/boot/dts/exynos4412-odroidu3.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidu3.dts
@@ -41,6 +41,11 @@
 		cooling-levels = <0 102 170 230>;
 	};
 
+	lan_pwrseq: pwrseq2 {
+		compatible = "mmc-pwrseq-simple";
+		ext-supply = <&buck8_reg>;
+	};
+
 	thermal-zones {
 		cpu_thermal: cpu-thermal {
 			cooling-maps {
@@ -104,6 +109,7 @@
 &ehci {
 	port at 1 {
 		status = "okay";
+		usb-pwrseq = <&lan_pwrseq>;
 	};
 	port at 2 {
 		status = "okay";
-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:17 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:17 +0200
Subject: [RFC v2 04/13] power: pwrseq: Enable COMPILE_TEST for drivers
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-5-git-send-email-k.kozlowski@samsung.com>

Allow build testing for power sequence drivers.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/power/pwrseq/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/power/pwrseq/Kconfig b/drivers/power/pwrseq/Kconfig
index b5d2d6c65f28..4731ba01a958 100644
--- a/drivers/power/pwrseq/Kconfig
+++ b/drivers/power/pwrseq/Kconfig
@@ -9,7 +9,7 @@ if POWER_SEQ
 config POWER_SEQ_EMMC
 	tristate "HW reset support for eMMC"
 	default y
-	depends on OF
+	depends on OF || COMPILE_TEST
 	help
 	  This selects Hardware reset support aka pwrseq-emmc for eMMC
 	  devices. By default this option is set to y.
@@ -20,7 +20,7 @@ config POWER_SEQ_EMMC
 config POWER_SEQ_SIMPLE
 	tristate "Simple HW reset support for MMC"
 	default y
-	depends on OF
+	depends on OF || COMPILE_TEST
 	help
 	  This selects simple hardware reset support aka pwrseq-simple for MMC
 	  devices. By default this option is set to y.
-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:15 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:15 +0200
Subject: [RFC v2 02/13] power/mmc: Move pwrseq drivers to power/pwrseq
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-3-git-send-email-k.kozlowski@samsung.com>

The MMC power sequence drivers are useful also outside of MMC world: for
USB devices needed a hard-reset before probing. Before extending and
re-using pwrseq drivers, move them to a new place.

The commit does not introduce significant changes in the pwrseq drivers
code so still all the functions are prefixed with "mmc_pwrseq". However
the MMC-specific pwrseq functions has to be now exported and everything
is hidden not by CONFIG_OF but by new CONFIG_POWER_SEQ option.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/mmc/Kconfig                                |  2 --
 drivers/mmc/core/Makefile                          |  3 ---
 drivers/mmc/core/core.c                            |  2 +-
 drivers/mmc/core/host.c                            |  2 +-
 drivers/power/Kconfig                              |  1 +
 drivers/power/Makefile                             |  1 +
 drivers/{mmc/core => power/pwrseq}/Kconfig         | 17 ++++++++++++-----
 drivers/power/pwrseq/Makefile                      |  3 +++
 drivers/{mmc/core => power/pwrseq}/pwrseq.c        |  8 ++++++--
 drivers/{mmc/core => power/pwrseq}/pwrseq_emmc.c   |  3 +--
 drivers/{mmc/core => power/pwrseq}/pwrseq_simple.c |  3 +--
 {drivers/mmc/core => include/linux}/pwrseq.h       |  6 +++---
 12 files changed, 30 insertions(+), 21 deletions(-)
 rename drivers/{mmc/core => power/pwrseq}/Kconfig (71%)
 create mode 100644 drivers/power/pwrseq/Makefile
 rename drivers/{mmc/core => power/pwrseq}/pwrseq.c (90%)
 rename drivers/{mmc/core => power/pwrseq}/pwrseq_emmc.c (99%)
 rename drivers/{mmc/core => power/pwrseq}/pwrseq_simple.c (99%)
 rename {drivers/mmc/core => include/linux}/pwrseq.h (94%)

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index f2eeb38efa65..7ade379e0634 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -21,8 +21,6 @@ config MMC_DEBUG
 
 if MMC
 
-source "drivers/mmc/core/Kconfig"
-
 source "drivers/mmc/card/Kconfig"
 
 source "drivers/mmc/host/Kconfig"
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index f007151dfdc6..a901d3cd09d3 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -8,7 +8,4 @@ mmc_core-y			:= core.o bus.o host.o \
 				   sdio.o sdio_ops.o sdio_bus.o \
 				   sdio_cis.o sdio_io.o sdio_irq.o \
 				   quirks.o slot-gpio.o
-mmc_core-$(CONFIG_OF)		+= pwrseq.o
-obj-$(CONFIG_PWRSEQ_SIMPLE)	+= pwrseq_simple.o
-obj-$(CONFIG_PWRSEQ_EMMC)	+= pwrseq_emmc.o
 mmc_core-$(CONFIG_DEBUG_FS)	+= debugfs.o
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 99275e40bf2f..0f145ff6e4f1 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -25,6 +25,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/pm_wakeup.h>
 #include <linux/suspend.h>
+#include <linux/pwrseq.h>
 #include <linux/fault-inject.h>
 #include <linux/random.h>
 #include <linux/slab.h>
@@ -43,7 +44,6 @@
 #include "bus.h"
 #include "host.h"
 #include "sdio_bus.h"
-#include "pwrseq.h"
 
 #include "mmc_ops.h"
 #include "sd_ops.h"
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index e0a3ee16c0d3..98164a352dfb 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -21,6 +21,7 @@
 #include <linux/export.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
+#include <linux/pwrseq.h>
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
@@ -29,7 +30,6 @@
 #include "core.h"
 #include "host.h"
 #include "slot-gpio.h"
-#include "pwrseq.h"
 
 #define cls_dev_to_mmc_host(d)	container_of(d, struct mmc_host, class_dev)
 
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 421770ddafa3..2702aca6cd2c 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -511,5 +511,6 @@ config AXP20X_POWER
 
 endif # POWER_SUPPLY
 
+source "drivers/power/pwrseq/Kconfig"
 source "drivers/power/reset/Kconfig"
 source "drivers/power/avs/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index e46b75d448a5..02f9d5da2e76 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_POWER_AVS)		+= avs/
 obj-$(CONFIG_CHARGER_SMB347)	+= smb347-charger.o
 obj-$(CONFIG_CHARGER_TPS65090)	+= tps65090-charger.o
 obj-$(CONFIG_CHARGER_TPS65217)	+= tps65217_charger.o
+obj-$(CONFIG_POWER_SEQ)		+= pwrseq/
 obj-$(CONFIG_POWER_RESET)	+= reset/
 obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
 obj-$(CONFIG_AXP288_CHARGER)	+= axp288_charger.o
diff --git a/drivers/mmc/core/Kconfig b/drivers/power/pwrseq/Kconfig
similarity index 71%
rename from drivers/mmc/core/Kconfig
rename to drivers/power/pwrseq/Kconfig
index 250f223aaa80..b5d2d6c65f28 100644
--- a/drivers/mmc/core/Kconfig
+++ b/drivers/power/pwrseq/Kconfig
@@ -1,7 +1,12 @@
-#
-# MMC core configuration
-#
-config PWRSEQ_EMMC
+menuconfig POWER_SEQ
+	default y if OF
+	bool "Hardware reset support for specific devices"
+	help
+	  Provides drivers which reset the specific device before...
+
+if POWER_SEQ
+
+config POWER_SEQ_EMMC
 	tristate "HW reset support for eMMC"
 	default y
 	depends on OF
@@ -12,7 +17,7 @@ config PWRSEQ_EMMC
 	  This driver can also be built as a module. If so, the module
 	  will be called pwrseq_emmc.
 
-config PWRSEQ_SIMPLE
+config POWER_SEQ_SIMPLE
 	tristate "Simple HW reset support for MMC"
 	default y
 	depends on OF
@@ -22,3 +27,5 @@ config PWRSEQ_SIMPLE
 
 	  This driver can also be built as a module. If so, the module
 	  will be called pwrseq_simple.
+
+endif
diff --git a/drivers/power/pwrseq/Makefile b/drivers/power/pwrseq/Makefile
new file mode 100644
index 000000000000..9e40e4b9068b
--- /dev/null
+++ b/drivers/power/pwrseq/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_POWER_SEQ)		+= pwrseq.o
+obj-$(CONFIG_POWER_SEQ_SIMPLE)	+= pwrseq_simple.o
+obj-$(CONFIG_POWER_SEQ_EMMC)	+= pwrseq_emmc.o
diff --git a/drivers/mmc/core/pwrseq.c b/drivers/power/pwrseq/pwrseq.c
similarity index 90%
rename from drivers/mmc/core/pwrseq.c
rename to drivers/power/pwrseq/pwrseq.c
index 9386c4771814..66310d7643cc 100644
--- a/drivers/mmc/core/pwrseq.c
+++ b/drivers/power/pwrseq/pwrseq.c
@@ -11,11 +11,10 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/pwrseq.h>
 
 #include <linux/mmc/host.h>
 
-#include "pwrseq.h"
-
 static DEFINE_MUTEX(pwrseq_list_mutex);
 static LIST_HEAD(pwrseq_list);
 
@@ -51,6 +50,7 @@ int mmc_pwrseq_alloc(struct mmc_host *host)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(mmc_pwrseq_alloc);
 
 void mmc_pwrseq_pre_power_on(struct mmc_host *host)
 {
@@ -59,6 +59,7 @@ void mmc_pwrseq_pre_power_on(struct mmc_host *host)
 	if (pwrseq && pwrseq->ops->pre_power_on)
 		pwrseq->ops->pre_power_on(host);
 }
+EXPORT_SYMBOL_GPL(mmc_pwrseq_pre_power_on);
 
 void mmc_pwrseq_post_power_on(struct mmc_host *host)
 {
@@ -67,6 +68,7 @@ void mmc_pwrseq_post_power_on(struct mmc_host *host)
 	if (pwrseq && pwrseq->ops->post_power_on)
 		pwrseq->ops->post_power_on(host);
 }
+EXPORT_SYMBOL_GPL(mmc_pwrseq_post_power_on);
 
 void mmc_pwrseq_power_off(struct mmc_host *host)
 {
@@ -75,6 +77,7 @@ void mmc_pwrseq_power_off(struct mmc_host *host)
 	if (pwrseq && pwrseq->ops->power_off)
 		pwrseq->ops->power_off(host);
 }
+EXPORT_SYMBOL_GPL(mmc_pwrseq_power_off);
 
 void mmc_pwrseq_free(struct mmc_host *host)
 {
@@ -85,6 +88,7 @@ void mmc_pwrseq_free(struct mmc_host *host)
 		host->pwrseq = NULL;
 	}
 }
+EXPORT_SYMBOL_GPL(mmc_pwrseq_free);
 
 int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq)
 {
diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/power/pwrseq/pwrseq_emmc.c
similarity index 99%
rename from drivers/mmc/core/pwrseq_emmc.c
rename to drivers/power/pwrseq/pwrseq_emmc.c
index adc9c0c614fb..a0583ed46d7f 100644
--- a/drivers/mmc/core/pwrseq_emmc.c
+++ b/drivers/power/pwrseq/pwrseq_emmc.c
@@ -17,11 +17,10 @@
 #include <linux/err.h>
 #include <linux/gpio/consumer.h>
 #include <linux/reboot.h>
+#include <linux/pwrseq.h>
 
 #include <linux/mmc/host.h>
 
-#include "pwrseq.h"
-
 struct mmc_pwrseq_emmc {
 	struct mmc_pwrseq pwrseq;
 	struct notifier_block reset_nb;
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/power/pwrseq/pwrseq_simple.c
similarity index 99%
rename from drivers/mmc/core/pwrseq_simple.c
rename to drivers/power/pwrseq/pwrseq_simple.c
index 450d907c6e6c..786f1db53a3f 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/power/pwrseq/pwrseq_simple.c
@@ -16,11 +16,10 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/gpio/consumer.h>
+#include <linux/pwrseq.h>
 
 #include <linux/mmc/host.h>
 
-#include "pwrseq.h"
-
 struct mmc_pwrseq_simple {
 	struct mmc_pwrseq pwrseq;
 	bool clk_enabled;
diff --git a/drivers/mmc/core/pwrseq.h b/include/linux/pwrseq.h
similarity index 94%
rename from drivers/mmc/core/pwrseq.h
rename to include/linux/pwrseq.h
index d69e751f148b..e230670c1d8d 100644
--- a/drivers/mmc/core/pwrseq.h
+++ b/include/linux/pwrseq.h
@@ -23,7 +23,7 @@ struct mmc_pwrseq {
 	struct module *owner;
 };
 
-#ifdef CONFIG_OF
+#ifdef CONFIG_POWER_SEQ
 
 int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq);
 void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq);
@@ -34,7 +34,7 @@ void mmc_pwrseq_post_power_on(struct mmc_host *host);
 void mmc_pwrseq_power_off(struct mmc_host *host);
 void mmc_pwrseq_free(struct mmc_host *host);
 
-#else
+#else /* CONFIG_POWER_SEQ */
 
 static inline int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq)
 {
@@ -47,6 +47,6 @@ static inline void mmc_pwrseq_post_power_on(struct mmc_host *host) {}
 static inline void mmc_pwrseq_power_off(struct mmc_host *host) {}
 static inline void mmc_pwrseq_free(struct mmc_host *host) {}
 
-#endif
+#endif /* CONFIG_POWER_SEQ */
 
 #endif
-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:21 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:21 +0200
Subject: [RFC v2 08/13] usb: hub: Handle deferred probe
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-9-git-send-email-k.kozlowski@samsung.com>

Add support for deferred probing to the usb hub. Currently EPROBE_DEFER
does not exist in usb hub path but future patches will add it on the
port level.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/usb/core/hub.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 38cc4bae0a82..1c82fcc448f5 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1731,6 +1731,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_device *hdev;
 	struct usb_hub *hub;
+	int ret;
 
 	desc = intf->cur_altsetting;
 	hdev = interface_to_usbdev(intf);
@@ -1850,11 +1851,12 @@ descriptor_error:
 	if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND)
 		hub->quirk_check_port_auto_suspend = 1;
 
-	if (hub_configure(hub, endpoint) >= 0)
+	ret = hub_configure(hub, endpoint);
+	if (ret >= 0)
 		return 0;
 
 	hub_disconnect(intf);
-	return -ENODEV;
+	return ret;
 }
 
 static int
-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:25 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:25 +0200
Subject: [RFC v2 12/13] ARM: dts: exynos: Switch the buck8 to GPIO mode on
 Odroid U3
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-13-git-send-email-k.kozlowski@samsung.com>

Switch the control of buck8 to GPIO mode. It is faster than I2C/register
mode and it is the easiest way to disable it (regulator state is a
logical OR state of GPIO and register value).

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm/boot/dts/exynos4412-odroidu3.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/exynos4412-odroidu3.dts b/arch/arm/boot/dts/exynos4412-odroidu3.dts
index d73aa6c58fe3..31cdc036fda4 100644
--- a/arch/arm/boot/dts/exynos4412-odroidu3.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidu3.dts
@@ -74,6 +74,7 @@
 	regulator-name = "BUCK8_P3V3";
 	regulator-min-microvolt = <3300000>;
 	regulator-max-microvolt = <3300000>;
+	maxim,ena-gpios = <&gpa1 1 GPIO_ACTIVE_HIGH>;
 };
 
 /* VDDQ for MSHC (eMMC card) */
-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:18 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:18 +0200
Subject: [RFC v2 05/13] power: pwrseq: Remove mmc prefix from mmc_pwrseq
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-6-git-send-email-k.kozlowski@samsung.com>

The "mmc" prefix is no longer needed after moving the pwrseq core code
from mmc/ to power/.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/power/pwrseq/pwrseq.c        | 18 +++++++++---------
 drivers/power/pwrseq/pwrseq_emmc.c   |  8 ++++----
 drivers/power/pwrseq/pwrseq_simple.c |  8 ++++----
 include/linux/mmc/host.h             |  4 ++--
 include/linux/pwrseq.h               | 20 ++++++++++----------
 5 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/drivers/power/pwrseq/pwrseq.c b/drivers/power/pwrseq/pwrseq.c
index 66310d7643cc..9c665821f890 100644
--- a/drivers/power/pwrseq/pwrseq.c
+++ b/drivers/power/pwrseq/pwrseq.c
@@ -21,7 +21,7 @@ static LIST_HEAD(pwrseq_list);
 int mmc_pwrseq_alloc(struct mmc_host *host)
 {
 	struct device_node *np;
-	struct mmc_pwrseq *p;
+	struct pwrseq *p;
 
 	np = of_parse_phandle(host->parent->of_node, "mmc-pwrseq", 0);
 	if (!np)
@@ -54,7 +54,7 @@ EXPORT_SYMBOL_GPL(mmc_pwrseq_alloc);
 
 void mmc_pwrseq_pre_power_on(struct mmc_host *host)
 {
-	struct mmc_pwrseq *pwrseq = host->pwrseq;
+	struct pwrseq *pwrseq = host->pwrseq;
 
 	if (pwrseq && pwrseq->ops->pre_power_on)
 		pwrseq->ops->pre_power_on(host);
@@ -63,7 +63,7 @@ EXPORT_SYMBOL_GPL(mmc_pwrseq_pre_power_on);
 
 void mmc_pwrseq_post_power_on(struct mmc_host *host)
 {
-	struct mmc_pwrseq *pwrseq = host->pwrseq;
+	struct pwrseq *pwrseq = host->pwrseq;
 
 	if (pwrseq && pwrseq->ops->post_power_on)
 		pwrseq->ops->post_power_on(host);
@@ -72,7 +72,7 @@ EXPORT_SYMBOL_GPL(mmc_pwrseq_post_power_on);
 
 void mmc_pwrseq_power_off(struct mmc_host *host)
 {
-	struct mmc_pwrseq *pwrseq = host->pwrseq;
+	struct pwrseq *pwrseq = host->pwrseq;
 
 	if (pwrseq && pwrseq->ops->power_off)
 		pwrseq->ops->power_off(host);
@@ -81,7 +81,7 @@ EXPORT_SYMBOL_GPL(mmc_pwrseq_power_off);
 
 void mmc_pwrseq_free(struct mmc_host *host)
 {
-	struct mmc_pwrseq *pwrseq = host->pwrseq;
+	struct pwrseq *pwrseq = host->pwrseq;
 
 	if (pwrseq) {
 		module_put(pwrseq->owner);
@@ -90,7 +90,7 @@ void mmc_pwrseq_free(struct mmc_host *host)
 }
 EXPORT_SYMBOL_GPL(mmc_pwrseq_free);
 
-int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq)
+int pwrseq_register(struct pwrseq *pwrseq)
 {
 	if (!pwrseq || !pwrseq->ops || !pwrseq->dev)
 		return -EINVAL;
@@ -101,9 +101,9 @@ int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(mmc_pwrseq_register);
+EXPORT_SYMBOL_GPL(pwrseq_register);
 
-void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq)
+void pwrseq_unregister(struct pwrseq *pwrseq)
 {
 	if (pwrseq) {
 		mutex_lock(&pwrseq_list_mutex);
@@ -111,4 +111,4 @@ void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq)
 		mutex_unlock(&pwrseq_list_mutex);
 	}
 }
-EXPORT_SYMBOL_GPL(mmc_pwrseq_unregister);
+EXPORT_SYMBOL_GPL(pwrseq_unregister);
diff --git a/drivers/power/pwrseq/pwrseq_emmc.c b/drivers/power/pwrseq/pwrseq_emmc.c
index a0583ed46d7f..a68ac9a68e04 100644
--- a/drivers/power/pwrseq/pwrseq_emmc.c
+++ b/drivers/power/pwrseq/pwrseq_emmc.c
@@ -22,7 +22,7 @@
 #include <linux/mmc/host.h>
 
 struct mmc_pwrseq_emmc {
-	struct mmc_pwrseq pwrseq;
+	struct pwrseq pwrseq;
 	struct notifier_block reset_nb;
 	struct gpio_desc *reset_gpio;
 };
@@ -54,7 +54,7 @@ static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this,
 	return NOTIFY_DONE;
 }
 
-static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = {
+static const struct pwrseq_ops mmc_pwrseq_emmc_ops = {
 	.post_power_on = mmc_pwrseq_emmc_reset,
 };
 
@@ -85,7 +85,7 @@ static int mmc_pwrseq_emmc_probe(struct platform_device *pdev)
 	pwrseq->pwrseq.owner = THIS_MODULE;
 	platform_set_drvdata(pdev, pwrseq);
 
-	return mmc_pwrseq_register(&pwrseq->pwrseq);
+	return pwrseq_register(&pwrseq->pwrseq);
 }
 
 static int mmc_pwrseq_emmc_remove(struct platform_device *pdev)
@@ -93,7 +93,7 @@ static int mmc_pwrseq_emmc_remove(struct platform_device *pdev)
 	struct mmc_pwrseq_emmc *pwrseq = platform_get_drvdata(pdev);
 
 	unregister_restart_handler(&pwrseq->reset_nb);
-	mmc_pwrseq_unregister(&pwrseq->pwrseq);
+	pwrseq_unregister(&pwrseq->pwrseq);
 
 	return 0;
 }
diff --git a/drivers/power/pwrseq/pwrseq_simple.c b/drivers/power/pwrseq/pwrseq_simple.c
index 786f1db53a3f..d5fbd653153e 100644
--- a/drivers/power/pwrseq/pwrseq_simple.c
+++ b/drivers/power/pwrseq/pwrseq_simple.c
@@ -21,7 +21,7 @@
 #include <linux/mmc/host.h>
 
 struct mmc_pwrseq_simple {
-	struct mmc_pwrseq pwrseq;
+	struct pwrseq pwrseq;
 	bool clk_enabled;
 	struct clk *ext_clk;
 	struct gpio_descs *reset_gpios;
@@ -77,7 +77,7 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host)
 	}
 }
 
-static const struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = {
+static const struct pwrseq_ops mmc_pwrseq_simple_ops = {
 	.pre_power_on = mmc_pwrseq_simple_pre_power_on,
 	.post_power_on = mmc_pwrseq_simple_post_power_on,
 	.power_off = mmc_pwrseq_simple_power_off,
@@ -115,14 +115,14 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
 	pwrseq->pwrseq.owner = THIS_MODULE;
 	platform_set_drvdata(pdev, pwrseq);
 
-	return mmc_pwrseq_register(&pwrseq->pwrseq);
+	return pwrseq_register(&pwrseq->pwrseq);
 }
 
 static int mmc_pwrseq_simple_remove(struct platform_device *pdev)
 {
 	struct mmc_pwrseq_simple *pwrseq = platform_get_drvdata(pdev);
 
-	mmc_pwrseq_unregister(&pwrseq->pwrseq);
+	pwrseq_unregister(&pwrseq->pwrseq);
 
 	return 0;
 }
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 85800b48241f..ad281bb3475f 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -203,7 +203,7 @@ struct mmc_context_info {
 };
 
 struct regulator;
-struct mmc_pwrseq;
+struct pwrseq;
 
 struct mmc_supply {
 	struct regulator *vmmc;		/* Card power supply */
@@ -215,7 +215,7 @@ struct mmc_host {
 	struct device		class_dev;
 	int			index;
 	const struct mmc_host_ops *ops;
-	struct mmc_pwrseq	*pwrseq;
+	struct pwrseq		*pwrseq;
 	unsigned int		f_min;
 	unsigned int		f_max;
 	unsigned int		f_init;
diff --git a/include/linux/pwrseq.h b/include/linux/pwrseq.h
index e230670c1d8d..6d2d2a44ad35 100644
--- a/include/linux/pwrseq.h
+++ b/include/linux/pwrseq.h
@@ -5,19 +5,19 @@
  *
  * License terms: GNU General Public License (GPL) version 2
  */
-#ifndef _MMC_CORE_PWRSEQ_H
-#define _MMC_CORE_PWRSEQ_H
+#ifndef _LINUX_PWRSEQ_H
+#define _LINUX_PWRSEQ_H
 
 #include <linux/mmc/host.h>
 
-struct mmc_pwrseq_ops {
+struct pwrseq_ops {
 	void (*pre_power_on)(struct mmc_host *host);
 	void (*post_power_on)(struct mmc_host *host);
 	void (*power_off)(struct mmc_host *host);
 };
 
-struct mmc_pwrseq {
-	const struct mmc_pwrseq_ops *ops;
+struct pwrseq {
+	const struct pwrseq_ops *ops;
 	struct device *dev;
 	struct list_head pwrseq_node;
 	struct module *owner;
@@ -25,8 +25,8 @@ struct mmc_pwrseq {
 
 #ifdef CONFIG_POWER_SEQ
 
-int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq);
-void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq);
+int pwrseq_register(struct pwrseq *pwrseq);
+void pwrseq_unregister(struct pwrseq *pwrseq);
 
 int mmc_pwrseq_alloc(struct mmc_host *host);
 void mmc_pwrseq_pre_power_on(struct mmc_host *host);
@@ -36,11 +36,11 @@ void mmc_pwrseq_free(struct mmc_host *host);
 
 #else /* CONFIG_POWER_SEQ */
 
-static inline int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq)
+static inline int pwrseq_register(struct pwrseq *pwrseq)
 {
 	return -ENOSYS;
 }
-static inline void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq) {}
+static inline void pwrseq_unregister(struct pwrseq *pwrseq) {}
 static inline int mmc_pwrseq_alloc(struct mmc_host *host) { return 0; }
 static inline void mmc_pwrseq_pre_power_on(struct mmc_host *host) {}
 static inline void mmc_pwrseq_post_power_on(struct mmc_host *host) {}
@@ -49,4 +49,4 @@ static inline void mmc_pwrseq_free(struct mmc_host *host) {}
 
 #endif /* CONFIG_POWER_SEQ */
 
-#endif
+#endif /* _LINUX_PWRSEQ_H */
-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:19 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:19 +0200
Subject: [RFC v2 06/13] power: pwrseq: Generalize mmc_pwrseq operations by
 removing mmc prefix
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-7-git-send-email-k.kozlowski@samsung.com>

The power sequence hooks (mmc_pwrseq_pre_power_on(),
mmc_pwrseq_post_power_on() and mmc_pwrseq_power_off()) can be made more
generic to allow re-use in other subsystems. They do not need to take
pointer to struct mmc_host but instead the struct pwrseq should be
sufficient.

Remove the "mmc" prefix and use the pointer to struct pwrseq as
argument.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/mmc/core/core.c              |  6 +++---
 drivers/power/pwrseq/pwrseq.c        | 24 +++++++++---------------
 drivers/power/pwrseq/pwrseq_emmc.c   |  4 ++--
 drivers/power/pwrseq/pwrseq_simple.c | 12 ++++++------
 include/linux/pwrseq.h               | 18 +++++++++---------
 5 files changed, 29 insertions(+), 35 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 0f145ff6e4f1..dfc4681054a8 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1719,7 +1719,7 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
 	if (host->ios.power_mode == MMC_POWER_ON)
 		return;
 
-	mmc_pwrseq_pre_power_on(host);
+	pwrseq_pre_power_on(host->pwrseq);
 
 	host->ios.vdd = fls(ocr) - 1;
 	host->ios.power_mode = MMC_POWER_UP;
@@ -1740,7 +1740,7 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
 	 */
 	mmc_delay(10);
 
-	mmc_pwrseq_post_power_on(host);
+	pwrseq_post_power_on(host->pwrseq);
 
 	host->ios.clock = host->f_init;
 
@@ -1759,7 +1759,7 @@ void mmc_power_off(struct mmc_host *host)
 	if (host->ios.power_mode == MMC_POWER_OFF)
 		return;
 
-	mmc_pwrseq_power_off(host);
+	pwrseq_power_off(host->pwrseq);
 
 	host->ios.clock = 0;
 	host->ios.vdd = 0;
diff --git a/drivers/power/pwrseq/pwrseq.c b/drivers/power/pwrseq/pwrseq.c
index 9c665821f890..495a19d3c30b 100644
--- a/drivers/power/pwrseq/pwrseq.c
+++ b/drivers/power/pwrseq/pwrseq.c
@@ -52,32 +52,26 @@ int mmc_pwrseq_alloc(struct mmc_host *host)
 }
 EXPORT_SYMBOL_GPL(mmc_pwrseq_alloc);
 
-void mmc_pwrseq_pre_power_on(struct mmc_host *host)
+void pwrseq_pre_power_on(struct pwrseq *pwrseq)
 {
-	struct pwrseq *pwrseq = host->pwrseq;
-
 	if (pwrseq && pwrseq->ops->pre_power_on)
-		pwrseq->ops->pre_power_on(host);
+		pwrseq->ops->pre_power_on(pwrseq);
 }
-EXPORT_SYMBOL_GPL(mmc_pwrseq_pre_power_on);
+EXPORT_SYMBOL_GPL(pwrseq_pre_power_on);
 
-void mmc_pwrseq_post_power_on(struct mmc_host *host)
+void pwrseq_post_power_on(struct pwrseq *pwrseq)
 {
-	struct pwrseq *pwrseq = host->pwrseq;
-
 	if (pwrseq && pwrseq->ops->post_power_on)
-		pwrseq->ops->post_power_on(host);
+		pwrseq->ops->post_power_on(pwrseq);
 }
-EXPORT_SYMBOL_GPL(mmc_pwrseq_post_power_on);
+EXPORT_SYMBOL_GPL(pwrseq_post_power_on);
 
-void mmc_pwrseq_power_off(struct mmc_host *host)
+void pwrseq_power_off(struct pwrseq *pwrseq)
 {
-	struct pwrseq *pwrseq = host->pwrseq;
-
 	if (pwrseq && pwrseq->ops->power_off)
-		pwrseq->ops->power_off(host);
+		pwrseq->ops->power_off(pwrseq);
 }
-EXPORT_SYMBOL_GPL(mmc_pwrseq_power_off);
+EXPORT_SYMBOL_GPL(pwrseq_power_off);
 
 void mmc_pwrseq_free(struct mmc_host *host)
 {
diff --git a/drivers/power/pwrseq/pwrseq_emmc.c b/drivers/power/pwrseq/pwrseq_emmc.c
index a68ac9a68e04..82327d0223f2 100644
--- a/drivers/power/pwrseq/pwrseq_emmc.c
+++ b/drivers/power/pwrseq/pwrseq_emmc.c
@@ -37,9 +37,9 @@ static void __mmc_pwrseq_emmc_reset(struct mmc_pwrseq_emmc *pwrseq)
 	udelay(200);
 }
 
-static void mmc_pwrseq_emmc_reset(struct mmc_host *host)
+static void mmc_pwrseq_emmc_reset(struct pwrseq *_pwrseq)
 {
-	struct mmc_pwrseq_emmc *pwrseq =  to_pwrseq_emmc(host->pwrseq);
+	struct mmc_pwrseq_emmc *pwrseq = to_pwrseq_emmc(_pwrseq);
 
 	__mmc_pwrseq_emmc_reset(pwrseq);
 }
diff --git a/drivers/power/pwrseq/pwrseq_simple.c b/drivers/power/pwrseq/pwrseq_simple.c
index d5fbd653153e..ab0098412690 100644
--- a/drivers/power/pwrseq/pwrseq_simple.c
+++ b/drivers/power/pwrseq/pwrseq_simple.c
@@ -46,9 +46,9 @@ static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq,
 	}
 }
 
-static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host)
+static void mmc_pwrseq_simple_pre_power_on(struct pwrseq *_pwrseq)
 {
-	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
+	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(_pwrseq);
 
 	if (!IS_ERR(pwrseq->ext_clk) && !pwrseq->clk_enabled) {
 		clk_prepare_enable(pwrseq->ext_clk);
@@ -58,16 +58,16 @@ static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host)
 	mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
 }
 
-static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host)
+static void mmc_pwrseq_simple_post_power_on(struct pwrseq *_pwrseq)
 {
-	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
+	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(_pwrseq);
 
 	mmc_pwrseq_simple_set_gpios_value(pwrseq, 0);
 }
 
-static void mmc_pwrseq_simple_power_off(struct mmc_host *host)
+static void mmc_pwrseq_simple_power_off(struct pwrseq *_pwrseq)
 {
-	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
+	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(_pwrseq);
 
 	mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
 
diff --git a/include/linux/pwrseq.h b/include/linux/pwrseq.h
index 6d2d2a44ad35..fcc8fd855d4c 100644
--- a/include/linux/pwrseq.h
+++ b/include/linux/pwrseq.h
@@ -11,9 +11,9 @@
 #include <linux/mmc/host.h>
 
 struct pwrseq_ops {
-	void (*pre_power_on)(struct mmc_host *host);
-	void (*post_power_on)(struct mmc_host *host);
-	void (*power_off)(struct mmc_host *host);
+	void (*pre_power_on)(struct pwrseq *pwrseq);
+	void (*post_power_on)(struct pwrseq *pwrseq);
+	void (*power_off)(struct pwrseq *pwrseq);
 };
 
 struct pwrseq {
@@ -28,10 +28,10 @@ struct pwrseq {
 int pwrseq_register(struct pwrseq *pwrseq);
 void pwrseq_unregister(struct pwrseq *pwrseq);
 
+void pwrseq_pre_power_on(struct pwrseq *pwrseq);
+void pwrseq_post_power_on(struct pwrseq *pwrseq);
+void pwrseq_power_off(struct pwrseq *pwrseq);
 int mmc_pwrseq_alloc(struct mmc_host *host);
-void mmc_pwrseq_pre_power_on(struct mmc_host *host);
-void mmc_pwrseq_post_power_on(struct mmc_host *host);
-void mmc_pwrseq_power_off(struct mmc_host *host);
 void mmc_pwrseq_free(struct mmc_host *host);
 
 #else /* CONFIG_POWER_SEQ */
@@ -41,10 +41,10 @@ static inline int pwrseq_register(struct pwrseq *pwrseq)
 	return -ENOSYS;
 }
 static inline void pwrseq_unregister(struct pwrseq *pwrseq) {}
+static inline void pwrseq_pre_power_on(struct pwrseq *pwrseq) {}
+static inline void pwrseq_post_power_on(struct pwrseq *pwrseq) {}
+static inline void pwrseq_power_off(struct pwrseq *pwrseq) {}
 static inline int mmc_pwrseq_alloc(struct mmc_host *host) { return 0; }
-static inline void mmc_pwrseq_pre_power_on(struct mmc_host *host) {}
-static inline void mmc_pwrseq_post_power_on(struct mmc_host *host) {}
-static inline void mmc_pwrseq_power_off(struct mmc_host *host) {}
 static inline void mmc_pwrseq_free(struct mmc_host *host) {}
 
 #endif /* CONFIG_POWER_SEQ */
-- 
1.9.1



From k.kozlowski at samsung.com  Thu May  5 05:34:23 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 05 May 2016 14:34:23 +0200
Subject: [RFC v2 10/13] usb: hub: Power sequence the ports on activation
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462451666-17945-11-git-send-email-k.kozlowski@samsung.com>

The autodetection of attached USB device might not work on certain
boards where the power is delivered externally. These devices also might
require a hard reset. Use pwrseq for that in USB hub.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/usb/core/hub.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 1c82fcc448f5..0fddaacc62bf 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -26,6 +26,7 @@
 #include <linux/mutex.h>
 #include <linux/random.h>
 #include <linux/pm_qos.h>
+#include <linux/pwrseq.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -1661,7 +1662,17 @@ static int hub_configure(struct usb_hub *hub,
 
 	usb_hub_adjust_deviceremovable(hdev, hub->descriptor);
 
+	/* FIXME: When do the pre-power-on? */
+	/*
+	for (i = 0; i < maxchild; i++)
+		pwrseq_pre_power_on(hub->ports[i]->pwrseq);
+	*/
+
+	for (i = 0; i < maxchild; i++)
+		pwrseq_post_power_on(hub->ports[i]->pwrseq);
+
 	hub_activate(hub, HUB_INIT);
+
 	return 0;
 
 fail:
-- 
1.9.1



From maxime.ripard at free-electrons.com  Thu May  5 06:21:46 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Thu, 5 May 2016 15:21:46 +0200
Subject: [PATCH v3] sunxi-irq: Fix Kconfig dependency on GENERIC_IRQ_CHIP
In-Reply-To: <5729D2A0.70900@arm.com>
References: <1461546292-21110-1-git-send-email-andre.przywara@arm.com>
 <20160502064854.GL17159@lukather> <5729D2A0.70900@arm.com>
Message-ID: <20160505132146.GH17159@lukather>

On Wed, May 04, 2016 at 11:44:48AM +0100, Andre Przywara wrote:
> Hi Maxime,
> 
> On 02/05/16 07:48, Maxime Ripard wrote:
> > Hi,
> > 
> > On Mon, Apr 25, 2016 at 02:04:52AM +0100, Andre Przywara wrote:
> >> The Allwinner NMI irqchip driver requires GENERIC_IRQ_CHIP, but
> >> we can't select it directly, because there is no specific Kconfig entry
> >> for the driver. Compiling this NMI driver with certain arm64
> >> configurations thus fails due to the missing dependency:
> >>
> >> drivers/built-in.o: In function `sunxi_sc_nmi_set_type':
> >> drivers/irqchip/irq-sunxi-nmi.c:114: undefined reference to `irq_setup_alt_chip'
> >> drivers/built-in.o: In function `irq_domain_add_linear':
> >> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
> >> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
> >> drivers/built-in.o: In function `sunxi_sc_nmi_irq_init':
> >> drivers/irqchip/irq-sunxi-nmi.c:146: undefined reference to `irq_alloc_domain_generic_chips'
> >> drivers/irqchip/irq-sunxi-nmi.c:161: undefined reference to `irq_get_domain_generic_chip'
> >> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
> >> drivers/irqchip/irq-sunxi-nmi.c:171: undefined reference to `irq_gc_mask_set_bit'
> >> drivers/irqchip/irq-sunxi-nmi.c:172: undefined reference to `irq_gc_ack_set_bit'
> >> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
> >>
> >> Add separate Kconfig options for both Allwinner specific irqchip
> >> drivers and select GENERIC_IRQ_CHIP for the NMI driver.
> >> The older sun4i IRQ driver only gets selected when support for these
> >> specific SoCs is compiled, while the NMI driver is selected for all
> >> Allwinner SoCs (copying the current behaviour and covering future SoCs
> >> automatically).
> >>
> >> Reported-by: Suzuki K Poulose <Suzuki.Poulose at arm.com>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >> Hi,
> >>
> >> this is a new approach to the problem that Suzuki tried to address
> >> already.
> >> It separates the sun4i IRQ controller driver and the NMI driver as
> >> Maxime requested.
> >> While there should be no difference for the NMI driver, the sun4i
> >> driver now only gets selected for certain SoCs, which is admittedly
> >> a bold call for -rc5. If people find this too risky, I can bring the
> >> sun4i in line with the NMI driver (selected for all ARCH_SUNXI) for
> >> this release and re-create the more selective dependency as a merge
> >> window patch, so that it gets more testing.
> >> Please let me know.
> >>
> >> Cheers,
> >> Andre.
> >>
> >>  arch/arm/mach-sunxi/Kconfig | 3 ++-
> >>  drivers/irqchip/Kconfig     | 8 ++++++++
> >>  drivers/irqchip/Makefile    | 4 ++--
> >>  3 files changed, 12 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> >> index c124d65..c092bc2 100644
> >> --- a/arch/arm/mach-sunxi/Kconfig
> >> +++ b/arch/arm/mach-sunxi/Kconfig
> >> @@ -4,7 +4,6 @@ menuconfig ARCH_SUNXI
> >>  	select ARCH_REQUIRE_GPIOLIB
> >>  	select ARCH_HAS_RESET_CONTROLLER
> >>  	select CLKSRC_MMIO
> >> -	select GENERIC_IRQ_CHIP
> >>  	select PINCTRL
> >>  	select SUN4I_TIMER
> >>  	select RESET_CONTROLLER
> >> @@ -14,11 +13,13 @@ if ARCH_SUNXI
> >>  config MACH_SUN4I
> >>  	bool "Allwinner A10 (sun4i) SoCs support"
> >>  	default ARCH_SUNXI
> >> +	select SUN4I_IRQCHIP
> >>  
> >>  config MACH_SUN5I
> >>  	bool "Allwinner A10s / A13 (sun5i) SoCs support"
> >>  	default ARCH_SUNXI
> >>  	select SUN5I_HSTIMER
> >> +	select SUN4I_IRQCHIP
> >>  
> >>  config MACH_SUN6I
> >>  	bool "Allwinner A31 (sun6i) SoCs support"
> >> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> >> index 3e12479..94f3f42 100644
> >> --- a/drivers/irqchip/Kconfig
> >> +++ b/drivers/irqchip/Kconfig
> >> @@ -165,6 +165,14 @@ config ST_IRQCHIP
> >>  	help
> >>  	  Enables SysCfg Controlled IRQs on STi based platforms.
> >>  
> >> +config SUN4I_IRQCHIP
> >> +	bool
> >> +
> >> +config SUNXI_NMI
> >> +	bool "Allwinner SoC NMI controller"
> >> +	default ARCH_SUNXI
> >> +	select GENERIC_IRQ_CHIP
> > 
> > This one is only used on SUN6I, SUN7I and SUN8I. There's no need to
> > enable it for all the SoCs.
> 
> But it is enabled for all SoCs at the moment - and as it is actually a
> fix (-rc1 does not compile for certain arm64 configs) I'd really like to
> not take chances here.
> As mentioned I am happy to send a follow up patch to restrict it further
> - given that it gets more testing, but at the moment I'd really like to
> just fix the arm64 build without accidentally breaking existing arm(32)
> boards.

Then at least be consistent and do the same thing for the A10 irq
controller too.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160505/f9ed910f/attachment.sig>

From lee.jones at linaro.org  Thu May  5 06:29:38 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Thu,  5 May 2016 14:29:38 +0100
Subject: [PATCH 0/5] remoteproc: A few important improvements
Message-ID: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>

This set contains some extensions which allow greater interoperability
with other heavily used subsystems/booting mechanisms already in the
kernel.  This includes; Device Tree (OF) support, fix possible race
between remoteproc and rpmsg/virtio, remotely (from a client) set the
firmware name, introduction of a nice way to handle shared (between
subsystems) memory and automatic carveout clipping.

Lee Jones (5):
  remoteproc: core: Task sync during rproc_fw_boot()
  remoteproc: core: Add rproc OF look-up functions
  remoteproc: core: Add ability to select a firmware from the client
  remoteproc: core: Supply framework to request, declare and fetch
    shared memory
  remoteproc: core: Clip carveout if it's too big

 drivers/remoteproc/remoteproc_core.c     | 371 ++++++++++++++++++++++++++++++-
 drivers/remoteproc/remoteproc_internal.h |   1 +
 drivers/remoteproc/remoteproc_virtio.c   |   2 +-
 include/linux/remoteproc.h               |  16 ++
 4 files changed, 379 insertions(+), 11 deletions(-)

-- 
2.8.0



From lee.jones at linaro.org  Thu May  5 06:29:40 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Thu,  5 May 2016 14:29:40 +0100
Subject: [PATCH 2/5] remoteproc: core: Add rproc OF look-up functions
In-Reply-To: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
Message-ID: <1462454983-13168-3-git-send-email-lee.jones@linaro.org>

- of_rproc_byindex(): look-up and obtain a reference to a rproc
  		      using the DT phandle "rprocs" and a index.

- of_rproc_byname():  lookup and obtain a reference to a rproc
  		      using the DT phandle "rprocs" and "rproc-names".

Signed-off-by: Ludovic Barre <ludovic.barre at st.com>
Signed-off-by: Lee Jones <lee.jones at linaro.org>
---
 drivers/remoteproc/remoteproc_core.c | 96 +++++++++++++++++++++++++++++++++++-
 include/linux/remoteproc.h           |  3 ++
 2 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 7db2818..85e5fd8 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -41,12 +41,19 @@
 #include <linux/virtio_ids.h>
 #include <linux/virtio_ring.h>
 #include <asm/byteorder.h>
+#include <linux/klist.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 
 #include "remoteproc_internal.h"
 
 static DEFINE_MUTEX(rproc_list_mutex);
 static LIST_HEAD(rproc_list);
 
+static void klist_rproc_get(struct klist_node *n);
+static void klist_rproc_put(struct klist_node *n);
+static DEFINE_KLIST(rprocs, klist_rproc_get, klist_rproc_put);
+
 typedef int (*rproc_handle_resources_t)(struct rproc *rproc,
 				struct resource_table *table, int len);
 typedef int (*rproc_handle_resource_t)(struct rproc *rproc,
@@ -1196,6 +1203,87 @@ out:
 }
 EXPORT_SYMBOL(rproc_shutdown);
 
+/* will be called when an rproc is added to the rprocs klist */
+static void klist_rproc_get(struct klist_node *n)
+{
+	struct rproc *rproc = container_of(n, struct rproc, klist);
+
+	get_device(&rproc->dev);
+}
+
+/* will be called when an rproc is removed from the rprocs klist */
+static void klist_rproc_put(struct klist_node *n)
+{
+	struct rproc *rproc = container_of(n, struct rproc, klist);
+
+	put_device(&rproc->dev);
+}
+
+static struct rproc *next_rproc(struct klist_iter *i)
+{
+	struct klist_node *n;
+
+	n = klist_next(i);
+	if (!n)
+		return NULL;
+
+	return container_of(n, struct rproc, klist);
+}
+
+/**
+ * of_rproc_by_index() - lookup and obtain a reference to an rproc
+ * @np: node to search for rproc
+ * @index: index into the phandle list
+ *
+ * Returns the rproc driver on success and an appropriate error code otherwise.
+ */
+struct rproc *of_rproc_byindex(struct device_node *np, int index)
+{
+	struct rproc *rproc;
+	struct device_node *rproc_node;
+	struct platform_device *pdev;
+	struct klist_iter i;
+
+	if (index < 0)
+		return ERR_PTR(-EINVAL);
+
+	rproc_node = of_parse_phandle(np, "rprocs", index);
+	if (!rproc_node)
+		return ERR_PTR(-ENODEV);
+
+	pdev = of_find_device_by_node(rproc_node);
+	if (!pdev)
+		return ERR_PTR(-ENODEV);
+
+	klist_iter_init(&rprocs, &i);
+	while ((rproc = next_rproc(&i)) != NULL)
+		if (rproc->dev.parent == &pdev->dev)
+			break;
+	klist_iter_exit(&i);
+
+	return rproc;
+}
+EXPORT_SYMBOL(of_rproc_byindex);
+
+/**
+ * of_rproc_byname() - lookup and obtain a reference to an rproc
+ * @np: node to search for rproc
+ * @name: name of the remoteproc from device's point of view
+ *
+ * Returns the rproc driver on success and an appropriate error code otherwise.
+ */
+struct rproc *of_rproc_byname(struct device_node *np, const char *name)
+{
+	int index;
+
+	if (unlikely(!name))
+		return ERR_PTR(-EINVAL);
+
+	index = of_property_match_string(np, "rproc-names", name);
+	return of_rproc_byindex(np, index);
+}
+EXPORT_SYMBOL(of_rproc_byname);
+
 /**
  * rproc_get_by_phandle() - find a remote processor by phandle
  * @phandle: phandle to the rproc
@@ -1282,7 +1370,13 @@ int rproc_add(struct rproc *rproc)
 	/* create debugfs entries */
 	rproc_create_debug_dir(rproc);
 
-	return rproc_add_virtio_devices(rproc);
+	ret = rproc_add_virtio_devices(rproc);
+	if (ret < 0)
+		klist_remove(&rproc->klist);
+	else
+		klist_add_tail(&rproc->klist, &rprocs);
+
+	return ret;
 }
 EXPORT_SYMBOL(rproc_add);
 
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 9c4e138..4c96e78 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -410,6 +410,7 @@ enum rproc_crash_type {
  */
 struct rproc {
 	struct list_head node;
+	struct klist_node klist;
 	struct iommu_domain *domain;
 	const char *name;
 	const char *firmware;
@@ -494,6 +495,8 @@ int rproc_del(struct rproc *rproc);
 int rproc_boot(struct rproc *rproc);
 void rproc_shutdown(struct rproc *rproc);
 void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type);
+struct rproc *of_rproc_byindex(struct device_node *np, int index);
+struct rproc *of_rproc_byname(struct device_node *np, const char *name);
 
 static inline struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev)
 {
-- 
2.8.0



From lee.jones at linaro.org  Thu May  5 06:29:39 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Thu,  5 May 2016 14:29:39 +0100
Subject: [PATCH 1/5] remoteproc: core: Task sync during rproc_fw_boot()
In-Reply-To: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
Message-ID: <1462454983-13168-2-git-send-email-lee.jones@linaro.org>

By default, rproc_fw_boot() needs to wait for rproc to be configured,
but a race may occur when using rpmsg/virtio.  In this case, it can
be called locally in a safe manor.

This patch represents two usecases:

 - External call (via exported rproc_boot()), which waits
 - Internal call can use 'nowait' version of rproc_boot()

Signed-off-by: Fabrice Gasnier <fabrice.gasnier at st.com>
Signed-off-by: Lee Jones <lee.jones at linaro.org>
---
 drivers/remoteproc/remoteproc_core.c     | 29 +++++++++++++++++++++++++++--
 drivers/remoteproc/remoteproc_internal.h |  1 +
 drivers/remoteproc/remoteproc_virtio.c   |  2 +-
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index ee44df5..7db2818 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1033,8 +1033,9 @@ static void rproc_crash_handler_work(struct work_struct *work)
 }
 
 /**
- * rproc_boot() - boot a remote processor
+ * __rproc_boot() - boot a remote processor
  * @rproc: handle of a remote processor
+ * @wait: wait for rproc registration completion
  *
  * Boot a remote processor (i.e. load its firmware, power it on, ...).
  *
@@ -1043,7 +1044,7 @@ static void rproc_crash_handler_work(struct work_struct *work)
  *
  * Returns 0 on success, and an appropriate error value otherwise.
  */
-int rproc_boot(struct rproc *rproc)
+static int __rproc_boot(struct rproc *rproc, bool wait)
 {
 	const struct firmware *firmware_p;
 	struct device *dev;
@@ -1091,6 +1092,10 @@ int rproc_boot(struct rproc *rproc)
 		goto downref_rproc;
 	}
 
+	/* if rproc virtio is not yet configured, wait */
+	if (wait)
+		wait_for_completion(&rproc->firmware_loading_complete);
+
 	ret = rproc_fw_boot(rproc, firmware_p);
 
 	release_firmware(firmware_p);
@@ -1104,9 +1109,29 @@ unlock_mutex:
 	mutex_unlock(&rproc->lock);
 	return ret;
 }
+
+/**
+ * rproc_boot() - boot a remote processor
+ * @rproc: handle of a remote processor
+ */
+int rproc_boot(struct rproc *rproc)
+{
+	return __rproc_boot(rproc, true);
+}
 EXPORT_SYMBOL(rproc_boot);
 
 /**
+ * rproc_boot_nowait() - boot a remote processor
+ * @rproc: handle of a remote processor
+ *
+ * Same as rproc_boot() but don't wait for rproc registration completion
+ */
+int rproc_boot_nowait(struct rproc *rproc)
+{
+	return __rproc_boot(rproc, false);
+}
+
+/**
  * rproc_shutdown() - power off the remote processor
  * @rproc: the remote processor
  *
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 8041b95..57e1de5 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -48,6 +48,7 @@ struct rproc_fw_ops {
 /* from remoteproc_core.c */
 void rproc_release(struct kref *kref);
 irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
+int rproc_boot_nowait(struct rproc *rproc);
 
 /* from remoteproc_virtio.c */
 int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id);
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index ff30684..106d9e4 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -175,7 +175,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 	}
 
 	/* now that the vqs are all set, boot the remote processor */
-	ret = rproc_boot(rproc);
+	ret = rproc_boot_nowait(rproc);
 	if (ret) {
 		dev_err(&rproc->dev, "rproc_boot() failed %d\n", ret);
 		goto error;
-- 
2.8.0



From lee.jones at linaro.org  Thu May  5 06:29:42 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Thu,  5 May 2016 14:29:42 +0100
Subject: [PATCH 4/5] remoteproc: core: Supply framework to request,
 declare and fetch shared memory
In-Reply-To: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
Message-ID: <1462454983-13168-5-git-send-email-lee.jones@linaro.org>

Normally used for management of; carveout, devmem and trace memory.

Signed-off-by: Lee Jones <lee.jones at linaro.org>
---
 drivers/remoteproc/remoteproc_core.c | 174 +++++++++++++++++++++++++++++++++--
 1 file changed, 167 insertions(+), 7 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 03720c0..3d9798c 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -209,6 +209,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
 {
 	struct rproc *rproc = rvdev->rproc;
 	struct device *dev = &rproc->dev;
+	struct device *dma_dev;
 	struct rproc_vring *rvring = &rvdev->vring[i];
 	struct fw_rsc_vdev *rsc;
 	dma_addr_t dma;
@@ -222,7 +223,8 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
 	 * Allocate non-cacheable memory for the vring. In the future
 	 * this call will also configure the IOMMU for us
 	 */
-	va = dma_alloc_coherent(dev->parent, size, &dma, GFP_KERNEL);
+	dma_dev = rproc_subdev_lookup(rproc, "vring");
+	va = dma_alloc_coherent(dma_dev, size, &dma, GFP_KERNEL);
 	if (!va) {
 		dev_err(dev->parent, "dma_alloc_coherent failed\n");
 		return -EINVAL;
@@ -236,7 +238,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
 	ret = idr_alloc(&rproc->notifyids, rvring, 0, 0, GFP_KERNEL);
 	if (ret < 0) {
 		dev_err(dev, "idr_alloc failed: %d\n", ret);
-		dma_free_coherent(dev->parent, size, va, dma);
+		dma_free_coherent(dma_dev, size, va, dma);
 		return ret;
 	}
 	notifyid = ret;
@@ -297,8 +299,10 @@ void rproc_free_vring(struct rproc_vring *rvring)
 	struct rproc *rproc = rvring->rvdev->rproc;
 	int idx = rvring->rvdev->vring - rvring;
 	struct fw_rsc_vdev *rsc;
+	struct device *dma_dev;
 
-	dma_free_coherent(rproc->dev.parent, size, rvring->va, rvring->dma);
+	dma_dev = rproc_subdev_lookup(rproc, "vring");
+	dma_free_coherent(dma_dev, size, rvring->va, rvring->dma);
 	idr_remove(&rproc->notifyids, rvring->notifyid);
 
 	/* reset resource entry info */
@@ -572,6 +576,7 @@ static int rproc_handle_carveout(struct rproc *rproc,
 {
 	struct rproc_mem_entry *carveout, *mapping;
 	struct device *dev = &rproc->dev;
+	struct device *dma_dev;
 	dma_addr_t dma;
 	void *va;
 	int ret;
@@ -594,7 +599,8 @@ static int rproc_handle_carveout(struct rproc *rproc,
 	if (!carveout)
 		return -ENOMEM;
 
-	va = dma_alloc_coherent(dev->parent, rsc->len, &dma, GFP_KERNEL);
+	dma_dev = rproc_subdev_lookup(rproc, "carveout");
+	va = dma_alloc_coherent(dma_dev, rsc->len, &dma, GFP_KERNEL);
 	if (!va) {
 		dev_err(dev->parent, "dma_alloc_coherent err: %d\n", rsc->len);
 		ret = -ENOMEM;
@@ -682,7 +688,7 @@ static int rproc_handle_carveout(struct rproc *rproc,
 free_mapping:
 	kfree(mapping);
 dma_free:
-	dma_free_coherent(dev->parent, rsc->len, va, dma);
+	dma_free_coherent(dma_dev, rsc->len, va, dma);
 free_carv:
 	kfree(carveout);
 	return ret;
@@ -766,6 +772,7 @@ static void rproc_resource_cleanup(struct rproc *rproc)
 {
 	struct rproc_mem_entry *entry, *tmp;
 	struct device *dev = &rproc->dev;
+	struct device *dma_dev;
 
 	/* clean up debugfs trace entries */
 	list_for_each_entry_safe(entry, tmp, &rproc->traces, node) {
@@ -791,9 +798,9 @@ static void rproc_resource_cleanup(struct rproc *rproc)
 	}
 
 	/* clean up carveout allocations */
+	dma_dev = rproc_subdev_lookup(rproc, "carveout");
 	list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) {
-		dma_free_coherent(dev->parent, entry->len, entry->va,
-				  entry->dma);
+		dma_free_coherent(dma_dev, entry->len, entry->va, entry->dma);
 		list_del(&entry->node);
 		kfree(entry);
 	}
@@ -1329,6 +1336,156 @@ struct rproc *rproc_get_by_phandle(phandle phandle)
 #endif
 EXPORT_SYMBOL(rproc_get_by_phandle);
 
+/*
+ * resource structure of rproc_subdev is used for identify the right subdevice
+ * that has the dma coherent memory.
+ */
+static int rproc_subdev_match(struct device *dev, void *data)
+{
+	char *sub_name;
+
+	if (!dev_name(dev))
+		return 0;
+
+	sub_name = strpbrk(dev_name(dev), "#");
+	if (!sub_name)
+		return 0;
+
+	return !strcmp(++sub_name, (char *)data);
+}
+
+/*
+ * find the subdevice child dma coherent memory that match with name region
+ * the rproc parent is the default device, if there is no match
+ */
+struct device *rproc_subdev_lookup(struct rproc *rproc, const char *name)
+{
+	struct device *dev;
+
+	dev = device_find_child(rproc->dev.parent, (void *)name,
+				rproc_subdev_match);
+	if (dev) {
+		/* decrement the matched device's refcount back */
+		put_device(dev);
+		return dev;
+	}
+
+	return rproc->dev.parent;
+}
+EXPORT_SYMBOL(rproc_subdev_lookup);
+
+/**
+ * rproc_subdev_release() - release the existence of a subdevice
+ *
+ * @dev: the subdevice's dev
+ */
+static void rproc_subdev_release(struct device *dev)
+{
+	struct rproc_subdev *sub = to_subdevice(dev);
+
+	kfree(sub);
+}
+
+/**
+ * rproc_subdev_unregister() - unregister sub-device of remote processor
+ *
+ * @dev: rproc sub-device
+ * @data: Not use (just to be compliant with device_for_each_child)
+ *
+ * This function is called by device_for_each_child function when unregister
+ * remote processor.
+ */
+static int rproc_subdev_unregister(struct device *dev, void *data)
+{
+	struct rproc_subdev *sub = to_subdevice(dev);
+	struct rproc *rproc = data;
+
+	if (dev != &(rproc->dev))
+		rproc_subdev_del(sub);
+	return 0;
+}
+
+/**
+ * rproc_subdev_add() - add a sub-device on remote processor
+ *
+ * @rproc: the parent remote processor
+ * @res: resource allow to define the dma coherent memory of sub-device
+ *
+ * This function add a sub-device child on rproc parent. This sub-device allow
+ * to define a new dma coherent memory area. when the rproc would alloc a
+ * dma coherent memory it's find the subdevice that match with physical memory
+ * asked (if there is no children that match, the rproc is the default device)
+ *
+ * Returns the sub-device handle on success, and error on failure.
+ */
+struct rproc_subdev *rproc_subdev_add(struct rproc *rproc, struct resource *res)
+{
+	struct rproc_subdev *sub;
+	int ret;
+
+	if (!res || res->flags != IORESOURCE_MEM || res->name == NULL) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	sub = kzalloc(sizeof(*sub), GFP_KERNEL);
+	if (!sub) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	sub->rproc = rproc;
+	sub->res = res;
+	sub->dev.parent = rproc->dev.parent;
+	sub->dev.release = rproc_subdev_release;
+	dev_set_name(&sub->dev, "%s#%s", dev_name(sub->dev.parent), res->name);
+	dev_set_drvdata(&sub->dev, sub);
+
+	ret = device_register(&sub->dev);
+	if (ret)
+		goto err_dev;
+
+	if (!devm_request_mem_region(&sub->dev, res->start,
+				     resource_size(res),
+				     dev_name(&sub->dev))) {
+		dev_err(&rproc->dev, "failed to get memory region\n");
+		ret = -EINVAL;
+		goto err_dev;
+	}
+
+	ret = dmam_declare_coherent_memory(&sub->dev,
+					   res->start, res->start,
+					   resource_size(res),
+					   DMA_MEMORY_MAP |
+					   DMA_MEMORY_EXCLUSIVE);
+	if (ret < 0)
+		goto err_dev;
+
+	return sub;
+
+err_dev:
+	put_device(&sub->dev);
+err:
+	dev_err(&rproc->dev, "unable to register subdev %s, err = %d\n",
+		(res && res->name) ? res->name : "unnamed", ret);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(rproc_subdev_add);
+
+/**
+ * rproc_subdev_del() - delete a sub-device of remote processor
+ *
+ * @subdev: rproc sub-device
+ */
+void rproc_subdev_del(struct rproc_subdev *subdev)
+{
+	if (get_device(&subdev->dev)) {
+		device_unregister(&subdev->dev);
+		put_device(&subdev->dev);
+	}
+}
+EXPORT_SYMBOL(rproc_subdev_del);
+
 /**
  * rproc_set_fw_name() - change rproc fw name
  * @rproc: rproc handle
@@ -1618,6 +1775,9 @@ int rproc_del(struct rproc *rproc)
 	kfree(rproc->cached_table);
 	rproc->cached_table = NULL;
 
+	device_for_each_child(rproc->dev.parent, rproc,
+			      rproc_subdev_unregister);
+
 	/* the rproc is downref'ed as soon as it's removed from the klist */
 	mutex_lock(&rproc_list_mutex);
 	list_del(&rproc->node);
-- 
2.8.0



From lee.jones at linaro.org  Thu May  5 06:29:41 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Thu,  5 May 2016 14:29:41 +0100
Subject: [PATCH 3/5] remoteproc: core: Add ability to select a firmware from
 the client
In-Reply-To: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
Message-ID: <1462454983-13168-4-git-send-email-lee.jones@linaro.org>

ST Co-Processors can be loaded with different firmwares to execute
specific tasks without the need for unloading the rproc module.

This patch provides a function which can update the firmware name.

NB: This can only happen if the rproc is offline.

Signed-off-by: Ludovic Barre <ludovic.barre at st.com>
Signed-off-by: Lee Jones <lee.jones at linaro.org>
---
 drivers/remoteproc/remoteproc_core.c | 63 ++++++++++++++++++++++++++++++++++++
 include/linux/remoteproc.h           | 13 ++++++++
 2 files changed, 76 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 85e5fd8..03720c0 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1004,6 +1004,7 @@ int rproc_trigger_recovery(struct rproc *rproc)
 
 	/* Free the copy of the resource table */
 	kfree(rproc->cached_table);
+	rproc->cached_table = NULL;
 
 	return rproc_add_virtio_devices(rproc);
 }
@@ -1329,6 +1330,66 @@ struct rproc *rproc_get_by_phandle(phandle phandle)
 EXPORT_SYMBOL(rproc_get_by_phandle);
 
 /**
+ * rproc_set_fw_name() - change rproc fw name
+ * @rproc: rproc handle
+ * @firmware: name of firmware file to load
+ *
+ * set a new firmware name for rproc handle
+ * firmware name can be updated only if the rproc is offline
+ * if firmware name is NULL the fw name is set on default name
+ *
+ * this function can wait, if the old fw config virtio is not yet finish
+ * (fw config request is asynchronous)
+ *
+ * Returns 0 on success and an appropriate error code otherwise.
+ */
+int rproc_set_fw_name(struct rproc *rproc, const char *firmware)
+{
+	struct rproc_vdev *rvdev, *rvtmp;
+
+	if (!rproc)
+		return -EINVAL;
+
+	/* if rproc is just being registered, wait */
+	wait_for_completion(&rproc->firmware_loading_complete);
+
+	mutex_lock(&rproc->lock);
+
+	if (rproc->state != RPROC_OFFLINE) {
+		mutex_unlock(&rproc->lock);
+		return -EBUSY;
+	}
+
+	if (rproc->firmware && rproc->firmware != rproc->orig_firmware)
+		kfree(rproc->firmware);
+
+	/* restore original fw name */
+	if (!firmware) {
+		rproc->firmware = rproc->orig_firmware;
+	} else {
+		rproc->firmware = kstrdup(firmware, GFP_KERNEL);
+		if (!rproc->firmware)
+			rproc->firmware = rproc->orig_firmware;
+	}
+
+	dev_info(&rproc->dev, "%s, fw name updated with:%s\n",
+		 rproc->name, rproc->firmware);
+
+	mutex_unlock(&rproc->lock);
+
+	/* clean up remote vdev entries */
+	list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node)
+		rproc_remove_virtio_dev(rvdev);
+
+	/* Free the copy of the resource table */
+	kfree(rproc->cached_table);
+	rproc->cached_table = NULL;
+
+	return rproc_add_virtio_devices(rproc);
+}
+EXPORT_SYMBOL(rproc_set_fw_name);
+
+/**
  * rproc_add() - register a remote processor
  * @rproc: the remote processor handle to register
  *
@@ -1467,6 +1528,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
 	}
 
 	rproc->firmware = p;
+	rproc->orig_firmware = p;
 	rproc->name = name;
 	rproc->ops = ops;
 	rproc->priv = &rproc[1];
@@ -1554,6 +1616,7 @@ int rproc_del(struct rproc *rproc)
 
 	/* Free the copy of the resource table */
 	kfree(rproc->cached_table);
+	rproc->cached_table = NULL;
 
 	/* the rproc is downref'ed as soon as it's removed from the klist */
 	mutex_lock(&rproc_list_mutex);
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 4c96e78..978e866 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -414,6 +414,7 @@ struct rproc {
 	struct iommu_domain *domain;
 	const char *name;
 	const char *firmware;
+	const char *orig_firmware;
 	void *priv;
 	const struct rproc_ops *ops;
 	struct device dev;
@@ -484,6 +485,18 @@ struct rproc_vdev {
 	u32 rsc_offset;
 };
 
+struct rproc_subdev {
+	struct device dev;
+	struct rproc *rproc;
+	struct resource *res;
+};
+
+#define to_subdevice(d) container_of(d, struct rproc_subdev, dev)
+struct rproc_subdev *rproc_subdev_add(struct rproc *rproc,
+				      struct resource *res);
+void rproc_subdev_del(struct rproc_subdev *subdev);
+struct device *rproc_subdev_lookup(struct rproc *rproc, const char *name);
+int rproc_set_fw_name(struct rproc *rproc, const char *firmware);
 struct rproc *rproc_get_by_phandle(phandle phandle);
 struct rproc *rproc_alloc(struct device *dev, const char *name,
 				const struct rproc_ops *ops,
-- 
2.8.0



From lee.jones at linaro.org  Thu May  5 06:29:43 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Thu,  5 May 2016 14:29:43 +0100
Subject: [PATCH 5/5] remoteproc: core: Clip carveout if it's too big
In-Reply-To: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
Message-ID: <1462454983-13168-6-git-send-email-lee.jones@linaro.org>

Carveout size is primarily extracted from the firmware binary.  However,
DT can over-ride this by providing a different (smaller) size.  We're
adding protection here to ensure the we only allocate the smaller of the
two provided sizes in order to decrease the risk of clashes.

Signed-off-by: Lee Jones <lee.jones at linaro.org>
---
 drivers/remoteproc/remoteproc_core.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 3d9798c..c3cad708 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -577,6 +577,7 @@ static int rproc_handle_carveout(struct rproc *rproc,
 	struct rproc_mem_entry *carveout, *mapping;
 	struct device *dev = &rproc->dev;
 	struct device *dma_dev;
+	struct rproc_subdev *sub;
 	dma_addr_t dma;
 	void *va;
 	int ret;
@@ -600,6 +601,14 @@ static int rproc_handle_carveout(struct rproc *rproc,
 		return -ENOMEM;
 
 	dma_dev = rproc_subdev_lookup(rproc, "carveout");
+	sub = dev_get_drvdata(dma_dev);
+
+	if (rsc->len > resource_size(sub->res)) {
+		dev_warn(dev, "carveout too big (0x%x): clipping to 0x%x\n",
+			 rsc->len, resource_size(sub->res));
+		rsc->len = resource_size(sub->res);
+	}
+
 	va = dma_alloc_coherent(dma_dev, rsc->len, &dma, GFP_KERNEL);
 	if (!va) {
 		dev_err(dev->parent, "dma_alloc_coherent err: %d\n", rsc->len);
-- 
2.8.0



From stern at rowland.harvard.edu  Thu May  5 07:09:47 2016
From: stern at rowland.harvard.edu (Alan Stern)
Date: Thu, 5 May 2016 10:09:47 -0400 (EDT)
Subject: [RFC v2 10/13] usb: hub: Power sequence the ports on activation
In-Reply-To: <1462451666-17945-11-git-send-email-k.kozlowski@samsung.com>
Message-ID: <Pine.LNX.4.44L0.1605051007040.2008-100000@iolanthe.rowland.org>

On Thu, 5 May 2016, Krzysztof Kozlowski wrote:

> The autodetection of attached USB device might not work on certain
> boards where the power is delivered externally. These devices also might
> require a hard reset. Use pwrseq for that in USB hub.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---
>  drivers/usb/core/hub.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 1c82fcc448f5..0fddaacc62bf 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -26,6 +26,7 @@
>  #include <linux/mutex.h>
>  #include <linux/random.h>
>  #include <linux/pm_qos.h>
> +#include <linux/pwrseq.h>
>  
>  #include <asm/uaccess.h>
>  #include <asm/byteorder.h>
> @@ -1661,7 +1662,17 @@ static int hub_configure(struct usb_hub *hub,
>  
>  	usb_hub_adjust_deviceremovable(hdev, hub->descriptor);
>  
> +	/* FIXME: When do the pre-power-on? */

It's hard to answer this without knowing what pre-power-on involves.

Why not create a pwrseq_power_on() routine that does pre_power_on 
followed by post_power_on?

> +	/*
> +	for (i = 0; i < maxchild; i++)
> +		pwrseq_pre_power_on(hub->ports[i]->pwrseq);
> +	*/
> +
> +	for (i = 0; i < maxchild; i++)
> +		pwrseq_post_power_on(hub->ports[i]->pwrseq);

This is patch 10/13.  hub->ports[i]->pwrseq doesn't get added until 
11/13.  Obviously you never tried compiling each patch in the series.

> +
>  	hub_activate(hub, HUB_INIT);
> +

Unnecessary blank line added.

>  	return 0;
>  
>  fail:

Alan Stern



From andre.przywara at arm.com  Thu May  5 07:16:44 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 5 May 2016 15:16:44 +0100
Subject: [PATCH v3] sunxi-irq: Fix Kconfig dependency on GENERIC_IRQ_CHIP
In-Reply-To: <20160505132146.GH17159@lukather>
References: <1461546292-21110-1-git-send-email-andre.przywara@arm.com>
 <20160502064854.GL17159@lukather> <5729D2A0.70900@arm.com>
 <20160505132146.GH17159@lukather>
Message-ID: <572B55CC.7080603@arm.com>

Hi Maxime,

On 05/05/16 14:21, Maxime Ripard wrote:
> On Wed, May 04, 2016 at 11:44:48AM +0100, Andre Przywara wrote:
>> Hi Maxime,
>>
>> On 02/05/16 07:48, Maxime Ripard wrote:
>>> Hi,
>>>
>>> On Mon, Apr 25, 2016 at 02:04:52AM +0100, Andre Przywara wrote:
>>>> The Allwinner NMI irqchip driver requires GENERIC_IRQ_CHIP, but
>>>> we can't select it directly, because there is no specific Kconfig entry
>>>> for the driver. Compiling this NMI driver with certain arm64
>>>> configurations thus fails due to the missing dependency:
>>>>
>>>> drivers/built-in.o: In function `sunxi_sc_nmi_set_type':
>>>> drivers/irqchip/irq-sunxi-nmi.c:114: undefined reference to `irq_setup_alt_chip'
>>>> drivers/built-in.o: In function `irq_domain_add_linear':
>>>> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
>>>> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
>>>> drivers/built-in.o: In function `sunxi_sc_nmi_irq_init':
>>>> drivers/irqchip/irq-sunxi-nmi.c:146: undefined reference to `irq_alloc_domain_generic_chips'
>>>> drivers/irqchip/irq-sunxi-nmi.c:161: undefined reference to `irq_get_domain_generic_chip'
>>>> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
>>>> drivers/irqchip/irq-sunxi-nmi.c:171: undefined reference to `irq_gc_mask_set_bit'
>>>> drivers/irqchip/irq-sunxi-nmi.c:172: undefined reference to `irq_gc_ack_set_bit'
>>>> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
>>>>
>>>> Add separate Kconfig options for both Allwinner specific irqchip
>>>> drivers and select GENERIC_IRQ_CHIP for the NMI driver.
>>>> The older sun4i IRQ driver only gets selected when support for these
>>>> specific SoCs is compiled, while the NMI driver is selected for all
>>>> Allwinner SoCs (copying the current behaviour and covering future SoCs
>>>> automatically).
>>>>
>>>> Reported-by: Suzuki K Poulose <Suzuki.Poulose at arm.com>
>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>> ---
>>>> Hi,
>>>>
>>>> this is a new approach to the problem that Suzuki tried to address
>>>> already.
>>>> It separates the sun4i IRQ controller driver and the NMI driver as
>>>> Maxime requested.
>>>> While there should be no difference for the NMI driver, the sun4i
>>>> driver now only gets selected for certain SoCs, which is admittedly
>>>> a bold call for -rc5. If people find this too risky, I can bring the
>>>> sun4i in line with the NMI driver (selected for all ARCH_SUNXI) for
>>>> this release and re-create the more selective dependency as a merge
>>>> window patch, so that it gets more testing.
>>>> Please let me know.
>>>>
>>>> Cheers,
>>>> Andre.
>>>>
>>>>  arch/arm/mach-sunxi/Kconfig | 3 ++-
>>>>  drivers/irqchip/Kconfig     | 8 ++++++++
>>>>  drivers/irqchip/Makefile    | 4 ++--
>>>>  3 files changed, 12 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
>>>> index c124d65..c092bc2 100644
>>>> --- a/arch/arm/mach-sunxi/Kconfig
>>>> +++ b/arch/arm/mach-sunxi/Kconfig
>>>> @@ -4,7 +4,6 @@ menuconfig ARCH_SUNXI
>>>>  	select ARCH_REQUIRE_GPIOLIB
>>>>  	select ARCH_HAS_RESET_CONTROLLER
>>>>  	select CLKSRC_MMIO
>>>> -	select GENERIC_IRQ_CHIP
>>>>  	select PINCTRL
>>>>  	select SUN4I_TIMER
>>>>  	select RESET_CONTROLLER
>>>> @@ -14,11 +13,13 @@ if ARCH_SUNXI
>>>>  config MACH_SUN4I
>>>>  	bool "Allwinner A10 (sun4i) SoCs support"
>>>>  	default ARCH_SUNXI
>>>> +	select SUN4I_IRQCHIP
>>>>  
>>>>  config MACH_SUN5I
>>>>  	bool "Allwinner A10s / A13 (sun5i) SoCs support"
>>>>  	default ARCH_SUNXI
>>>>  	select SUN5I_HSTIMER
>>>> +	select SUN4I_IRQCHIP
>>>>  
>>>>  config MACH_SUN6I
>>>>  	bool "Allwinner A31 (sun6i) SoCs support"
>>>> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
>>>> index 3e12479..94f3f42 100644
>>>> --- a/drivers/irqchip/Kconfig
>>>> +++ b/drivers/irqchip/Kconfig
>>>> @@ -165,6 +165,14 @@ config ST_IRQCHIP
>>>>  	help
>>>>  	  Enables SysCfg Controlled IRQs on STi based platforms.
>>>>  
>>>> +config SUN4I_IRQCHIP
>>>> +	bool
>>>> +
>>>> +config SUNXI_NMI
>>>> +	bool "Allwinner SoC NMI controller"
>>>> +	default ARCH_SUNXI
>>>> +	select GENERIC_IRQ_CHIP
>>>
>>> This one is only used on SUN6I, SUN7I and SUN8I. There's no need to
>>> enable it for all the SoCs.
>>
>> But it is enabled for all SoCs at the moment - and as it is actually a
>> fix (-rc1 does not compile for certain arm64 configs) I'd really like to
>> not take chances here.
>> As mentioned I am happy to send a follow up patch to restrict it further
>> - given that it gets more testing, but at the moment I'd really like to
>> just fix the arm64 build without accidentally breaking existing arm(32)
>> boards.
> 
> Then at least be consistent and do the same thing for the A10 irq
> controller too.

Which is basically what Suzuki proposed with v2:
https://lkml.org/lkml/2016/4/13/592

This patch also has been acked by Marc, so can't we just take that for
4.6 and I'll send a patch on top of that to make a more fine grained
selection for the next release?

Cheers,
Andre.


From js07.lee at gmail.com  Thu May  5 07:33:10 2016
From: js07.lee at gmail.com (Jungseung Lee)
Date: Thu,  5 May 2016 23:33:10 +0900
Subject: [PATCH] ARM: iop: Fix indentation
Message-ID: <1462458790-5927-1-git-send-email-js07.lee@gmail.com>

Fix indentation in iop_3xx_std_desc

Signed-off-by: Jungseung Lee <js07.lee at gmail.com>
---
 arch/arm/plat-iop/setup.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/plat-iop/setup.c b/arch/arm/plat-iop/setup.c
index 5b217f4..8151bde 100644
--- a/arch/arm/plat-iop/setup.c
+++ b/arch/arm/plat-iop/setup.c
@@ -20,12 +20,12 @@
  * the IOP3xx OCCDR must be mapped uncached and unbuffered.
  */
 static struct map_desc iop3xx_std_desc[] __initdata = {
-	 {	/* mem mapped registers */
+	{	/* mem mapped registers */
 		.virtual	= IOP3XX_PERIPHERAL_VIRT_BASE,
 		.pfn		= __phys_to_pfn(IOP3XX_PERIPHERAL_PHYS_BASE),
 		.length		= IOP3XX_PERIPHERAL_SIZE,
 		.type		= MT_UNCACHED,
-	 },
+	},
 };
 
 void __init iop3xx_map_io(void)
-- 
1.9.1



From cov at codeaurora.org  Thu May  5 07:42:12 2016
From: cov at codeaurora.org (Christopher Covington)
Date: Thu, 5 May 2016 10:42:12 -0400
Subject: [PATCH v1] builddeb: fix missing headers in linux-headers package
In-Reply-To: <1459445479-10948-1-git-send-email-asamson@codeaurora.org>
References: <1459445479-10948-1-git-send-email-asamson@codeaurora.org>
Message-ID: <572B5BC4.7080402@codeaurora.org>

On 03/31/2016 01:31 PM, Azriel Samson wrote:
> The kernel headers package (linux-headers) doesn't include
> header files from other architectures required to build
> out-of-tree modules.
> 
> For e.g. on ARM64, opcodes.h includes the same file from ARM
> which causes the following error:
> ./arch/arm64/include/asm/opcodes.h:1:43: fatal error:
> ../../arm/include/asm/opcodes.h: No such file or directory
> compilation terminated.
> 
> Signed-off-by: Azriel Samson <asamson at codeaurora.org>
> ---
>  scripts/package/builddeb | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/scripts/package/builddeb b/scripts/package/builddeb
> index 6c3b038..06ba0d9 100755
> --- a/scripts/package/builddeb
> +++ b/scripts/package/builddeb
> @@ -322,7 +322,7 @@ fi
>  
>  # Build kernel header package
>  (cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles"
> -(cd $srctree; find arch/$SRCARCH/include include scripts -type f) >> "$objtree/debian/hdrsrcfiles"
> +(cd $srctree; find arch/*/include include scripts -type f) >> "$objtree/debian/hdrsrcfiles"
>  (cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles"
>  (cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles"
>  (cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f) >> "$objtree/debian/hdrobjfiles"

Any feedback on this? Michal, do you think this would be appropriate to
include in 4.7?

Thanks,
Christopher Covington

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


From marc.zyngier at arm.com  Thu May  5 07:43:28 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 5 May 2016 15:43:28 +0100
Subject: [PATCH v2 14/54] KVM: arm/arm64: vgic-new: Implement virtual IRQ
 injection
In-Reply-To: <572B2D88.3050504@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-15-git-send-email-andre.przywara@arm.com>
 <57293844.1060802@linaro.org> <572B2D88.3050504@arm.com>
Message-ID: <572B5C10.4040900@arm.com>

On 05/05/16 12:24, Andre Przywara wrote:
> Hi Tom,
> 
> thanks for looking at the patches!
> 
> On 04/05/16 00:46, Tom Hanson wrote:
>> On 04/28/2016 10:45 AM, Andre Przywara wrote:
>> ...
>>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>>> index fb45537..92b78a0 100644
>>> --- a/virt/kvm/arm/vgic/vgic.c
>>> +++ b/virt/kvm/arm/vgic/vgic.c
>>> @@ -19,8 +19,31 @@
>> ... 
>>> +/*
>>> + * Locking order is always:
>>> + *   vgic_cpu->ap_list_lock
>>> + *     vgic_irq->irq_lock
>>> + *
>>> + * (that is, always take the ap_list_lock before the struct vgic_irq
>>> lock).
>>> + *
>>> + * When taking more than one ap_list_lock at the same time, always
>>> take the
>>> + * lowest numbered VCPU's ap_list_lock first, so:
>>> + *   vcpuX->vcpu_id < vcpuY->vcpu_id:
>>> + *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
>>> + *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
>>> + */
>>
>> The code would be safer and easier to maintain in the long run if there
>> were functions provided which implement these 2 rules.  Something along
>> the line of:
>>
>>   void vgic_lock_aplist_irq(spinlock_t ap_list_lock, spinlock_t irq_lock){
>>       spin_lock(ap_list_lock);
>>       spin_lock(irq_lock);
>>   }
> 
> The idea isn't too bad indeed.
> I see that we could use that in vgic_queue_irq_unlock() and
> vgic_mmio_write_sactive().
> But as Marc mentioned in a conversation yesterday we will have a mixture
> of wrapped locks and open coded lock sequences. See for instance
> vgic_prune_ap_list(), where we have the sequence, but we can't use
> vgic_lock_aplist_irq() because the IRQ lock is taken inside the loop
> while the ap_list_lock is taken once outside of it.
> 
> Marc, Christoffer, what is your opinion here?

I don't mind switching to these more "high level" primitives, but I'm
slightly worried that whoever starts using them will not consider that
they are quite heavy and not always required.

But maybe it is worth a try.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From marc.zyngier at arm.com  Thu May  5 07:49:59 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 5 May 2016 15:49:59 +0100
Subject: [PATCH v3 0/2] irqchip/mbigen: fix the IO remap problem in mbigen
 driver.
In-Reply-To: <56F0B7C3.8070001@huawei.com>
References: <1458203641-17172-1-git-send-email-majun258@huawei.com>
 <alpine.DEB.2.11.1603211124450.3978@nanos> <56F0B7C3.8070001@huawei.com>
Message-ID: <572B5D97.4090004@arm.com>

On 22/03/16 03:10, majun (F) wrote:
> 
> 
> ? 2016/3/21 18:29, Thomas Gleixner ??:
>> On Thu, 17 Mar 2016, MaJun wrote:
>>> This patch set is used to fix the problem of remap a set of registers
>>> repeatedly in current mbigen driver.
>>>
>>>   irqchip/mbigen:Change the mbigen node definition in dt binding file
>>>   irqchip/mbigen:Change the mbigen driver based on the new mbigen node definition
>>
>> These subject lines are still horrible as they tell nothing about the nature
>> of the change. I fixed them up along with the changelogs and applied them to
>> irq/urgent. Can you spot the difference?
> 
> Yes, after you changing, the subject and change log clearly show why we need to
> do this change.
> I have learned a lot from you :)
> 
>>
>> While at it. The config switch for this driver is horrible. It's just in the
>> middle of the device driver configs. Why is this configurable by the user at
>> all? It simply should be selected by arm64 or some subarch configuration
>> there. Please clean that up.
>>
> will do.

So what's the status of this? Do you still plan to respin it?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From horia.geanta at nxp.com  Thu May  5 08:36:04 2016
From: horia.geanta at nxp.com (=?UTF-8?q?Horia=20Geant=C4=83?=)
Date: Thu, 5 May 2016 18:36:04 +0300
Subject: [PATCH v2 3/8] arm64: add io{read,write}64be accessors
In-Reply-To: <1462462435-27403-1-git-send-email-horia.geanta@nxp.com>
References: <1462462435-27403-1-git-send-email-horia.geanta@nxp.com>
Message-ID: <1462462564-27731-1-git-send-email-horia.geanta@nxp.com>

This will allow device drivers to consistently use io{read,write}XXbe
also for 64-bit accesses.

Signed-off-by: Alex Porosanu <alexandru.porosanu at nxp.com>
Signed-off-by: Horia Geant? <horia.geanta at nxp.com>
---
 arch/arm64/include/asm/io.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 44be1e03ed65..9b6e408cfa51 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -174,13 +174,15 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
 #define iounmap				__iounmap
 
 /*
- * io{read,write}{16,32}be() macros
+ * io{read,write}{16,32,64}be() macros
  */
 #define ioread16be(p)		({ __u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
 #define ioread32be(p)		({ __u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })
+#define ioread64be(p)		({ __u64 __v = be64_to_cpu((__force __be64)__raw_readq(p)); __iormb(); __v; })
 
 #define iowrite16be(v,p)	({ __iowmb(); __raw_writew((__force __u16)cpu_to_be16(v), p); })
 #define iowrite32be(v,p)	({ __iowmb(); __raw_writel((__force __u32)cpu_to_be32(v), p); })
+#define iowrite64be(v,p)	({ __iowmb(); __raw_writeq((__force __u64)cpu_to_be64(v), p); })
 
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
-- 
2.4.4



From kernel at martin.sperl.org  Thu May  5 08:53:23 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu,  5 May 2016 15:53:23 +0000
Subject: [PATCH 0/5] clk: bcm2835: add flags for mash and parent clocks
Message-ID: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Allow flags to be set on a per clock index basis, which control:
* the parent clocks selected when not setting clocks explicitly
* the clock mode with regards to integer only or higher order mash

These flags can also get set via the device tree.

Default flags:
* avoid the use of testdebug clocks for all clocks
* avoid pllc_* for per clocks
* allow fractional clocks, but not higher order mash

Other flags can easily get added if the need arrises.

Martin Sperl (5):
  dt: bindings: add means to control flags of specific clocks
  clk: bcm2835: expose the parent clocks via include/dt-bindings
  clk: bcm2835: enable default filtering for parent clocks
  clk: bcm2835: allow setting clocks flags via the dt
  clk: bcm2835: add support for BCM2835_CLOCK_FLAG_USE_MASH/INTEGER

 .../bindings/clock/brcm,bcm2835-cprman.txt         |  14 ++
 drivers/clk/bcm/clk-bcm2835.c                      | 202 +++++++++++++++++----
 include/dt-bindings/clock/bcm2835.h                |  33 ++++
 3 files changed, 216 insertions(+), 33 deletions(-)

--
2.1.4


From kernel at martin.sperl.org  Thu May  5 08:53:24 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu,  5 May 2016 15:53:24 +0000
Subject: [PATCH 1/5] dt: bindings: add means to control flags of specific
 clocks
In-Reply-To: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
References: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1462463608-22940-2-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add documentation for "brcm,clock-index" and "brcm,clock-flags"
which allows to set flags to enable the use of parent clocks
that may be different from the default.

In the future this may also contain flags that would allow
enabling higher order mash dividers.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 .../devicetree/bindings/clock/brcm,bcm2835-cprman.txt      | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt
index e56a1df..cbcca56 100644
--- a/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt
+++ b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt
@@ -18,6 +18,15 @@ Required properties:
 - reg:		Specifies base physical address and size of the registers
 - clocks:	The external oscillator clock phandle

+Optional properties:
+- brcm,clock-index: clock id to which the corresponding brcm,clock-flags
+		      value applies
+- brcm,clock-flags: flags for the specific clock id given in
+		      brcm,clock-index - the bits are defined in
+		      include/dt-bindings/clock/bcm2835.h
+		      of which the bottom 16 bits are reserved for
+		      parent clock selection.
+
 Example:

 	clk_osc: clock at 3 {
@@ -33,7 +42,11 @@ Example:
 		#clock-cells = <1>;
 		reg = <0x7e101000 0x2000>;
 		clocks = <&clk_osc>;
+		/* the pcm clock should use the non-standard pllc-per parent */
+		brcm,clock-index = <BCM2835_CLOCK_PCM>;
+		brcm,clock-flags = <((1 <<BCM2835_PER_PARENT_GND)|
+				     (1 <<BCM2835_PER_PARENT_OSC)|
+				     (1 <<BCM2835_PER_PARENT_PLLC))>;
 	};

 	i2c0: i2c at 7e205000 {
--
2.1.4


From kernel at martin.sperl.org  Thu May  5 08:53:25 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu,  5 May 2016 15:53:25 +0000
Subject: [PATCH 2/5] clk: bcm2835: expose the parent clocks via
 include/dt-bindings
In-Reply-To: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
References: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1462463608-22940-3-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Expose the parent clocks via include/dt-bindings,
so that they can easily get referred to in the device tree.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 drivers/clk/bcm/clk-bcm2835.c       | 45 ++++++++++++++++++-------------------
 include/dt-bindings/clock/bcm2835.h | 26 +++++++++++++++++++++
 2 files changed, 48 insertions(+), 23 deletions(-)

diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index c19b99c9..1b1657d 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1303,10 +1303,10 @@ struct bcm2835_clk_desc {
 
 /* main oscillator parent mux */
 static const char *const bcm2835_clock_osc_parents[] = {
-	"gnd",
-	"xosc",
-	"testdebug0",
-	"testdebug1"
+	[BCM2835_OSC_PARENT_GND]	= "gnd",
+	[BCM2835_OSC_PARENT_OSC]	= "xosc",
+	[BCM2835_OSC_PARENT_TESTDEBUG0]	= "testdebug0",
+	[BCM2835_OSC_PARENT_TESTDEBUG1]	= "testdebug1",
 };
 
 #define REGISTER_OSC_CLK(...)	REGISTER_CLK(				\
@@ -1316,14 +1316,14 @@ static const char *const bcm2835_clock_osc_parents[] = {
 
 /* main peripherial parent mux */
 static const char *const bcm2835_clock_per_parents[] = {
-	"gnd",
-	"xosc",
-	"testdebug0",
-	"testdebug1",
-	"plla_per",
-	"pllc_per",
-	"plld_per",
-	"pllh_aux",
+	[BCM2835_PER_PARENT_GND]	= "gnd",
+	[BCM2835_PER_PARENT_OSC]	= "xosc",
+	[BCM2835_PER_PARENT_TESTDEBUG0]	= "testdebug0",
+	[BCM2835_PER_PARENT_TESTDEBUG1]	= "testdebug1",
+	[BCM2835_PER_PARENT_PLLA_PER]	= "plla_per",
+	[BCM2835_PER_PARENT_PLLC_PER]	= "pllc_per",
+	[BCM2835_PER_PARENT_PLLD_PER]	= "plld_per",
+	[BCM2835_PER_PARENT_PLLH_AUX]	= "pllh_aux",
 };
 
 #define REGISTER_PER_CLK(...)	REGISTER_CLK(				\
@@ -1333,18 +1333,17 @@ static const char *const bcm2835_clock_per_parents[] = {
 
 /* main vpu parent mux */
 static const char *const bcm2835_clock_vpu_parents[] = {
-	"gnd",
-	"xosc",
-	"testdebug0",
-	"testdebug1",
-	"plla_core",
-	"pllc_core0",
-	"plld_core",
-	"pllh_aux",
-	"pllc_core1",
-	"pllc_core2",
+	[BCM2835_VPU_PARENT_GND]	= "gnd",
+	[BCM2835_VPU_PARENT_OSC]	= "xosc",
+	[BCM2835_VPU_PARENT_TESTDEBUG0]	= "testdebug0",
+	[BCM2835_VPU_PARENT_TESTDEBUG1]	= "testdebug1",
+	[BCM2835_VPU_PARENT_PLLA_CORE]	= "plla_core",
+	[BCM2835_VPU_PARENT_PLLC_CORE0]	= "pllc_core0",
+	[BCM2835_VPU_PARENT_PLLD_CORE]	= "plld_core",
+	[BCM2835_VPU_PARENT_PLLH_AUX]	= "pllh_aux",
+	[BCM2835_VPU_PARENT_PLLC_CORE1]	= "pllc_core1",
+	[BCM2835_VPU_PARENT_PLLC_CORE2]	= "pllc_core2",
 };
-
 #define REGISTER_VPU_CLK(...)	REGISTER_CLK(				\
 	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),	\
 	.parents = bcm2835_clock_vpu_parents,				\
diff --git a/include/dt-bindings/clock/bcm2835.h b/include/dt-bindings/clock/bcm2835.h
index 360e00c..e5396fe 100644
--- a/include/dt-bindings/clock/bcm2835.h
+++ b/include/dt-bindings/clock/bcm2835.h
@@ -64,3 +64,29 @@
 #define BCM2835_CLOCK_CAM1		46
 #define BCM2835_CLOCK_DSI0E		47
 #define BCM2835_CLOCK_DSI1E		48
+
+/* the parent clock for different clock types */
+#define BCM2835_OSC_PARENT_GND		0
+#define BCM2835_OSC_PARENT_OSC		1
+#define BCM2835_OSC_PARENT_TESTDEBUG0	2
+#define BCM2835_OSC_PARENT_TESTDEBUG1	3
+
+#define BCM2835_PER_PARENT_GND		0
+#define BCM2835_PER_PARENT_OSC		1
+#define BCM2835_PER_PARENT_TESTDEBUG0	2
+#define BCM2835_PER_PARENT_TESTDEBUG1	3
+#define BCM2835_PER_PARENT_PLLA_PER	4
+#define BCM2835_PER_PARENT_PLLC_PER	5
+#define BCM2835_PER_PARENT_PLLD_PER	6
+#define BCM2835_PER_PARENT_PLLH_AUX	7
+
+#define BCM2835_VPU_PARENT_GND		0
+#define BCM2835_VPU_PARENT_OSC		1
+#define BCM2835_VPU_PARENT_TESTDEBUG0	2
+#define BCM2835_VPU_PARENT_TESTDEBUG1	3
+#define BCM2835_VPU_PARENT_PLLA_CORE	4
+#define BCM2835_VPU_PARENT_PLLC_CORE0	5
+#define BCM2835_VPU_PARENT_PLLD_CORE	6
+#define BCM2835_VPU_PARENT_PLLH_AUX	7
+#define BCM2835_VPU_PARENT_PLLC_CORE1	8
+#define BCM2835_VPU_PARENT_PLLC_CORE2	9
-- 
2.1.4



From kernel at martin.sperl.org  Thu May  5 08:53:26 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu,  5 May 2016 15:53:26 +0000
Subject: [PATCH 3/5] clk: bcm2835: enable default filtering for parent clocks
In-Reply-To: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
References: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1462463608-22940-4-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Depending on the type of clock define a default set of
parent clocks that are uses during parent clock selection.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 drivers/clk/bcm/clk-bcm2835.c | 47 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 1b1657d..8a44ebf 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -836,6 +836,7 @@ struct bcm2835_clock {
 	struct clk_hw hw;
 	struct bcm2835_cprman *cprman;
 	const struct bcm2835_clock_data *data;
+	u32 flags;
 };
 
 static struct bcm2835_clock *bcm2835_clock_from_hw(struct clk_hw *hw)
@@ -1023,6 +1024,8 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
 		parent = clk_hw_get_parent_by_index(hw, i);
 		if (!parent)
 			continue;
+		if (!(clock->flags & BIT(i)))
+			continue;
 		prate = clk_hw_get_rate(parent);
 		div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
 		rate = bcm2835_clock_rate_from_divisor(clock, prate, div);
@@ -1216,6 +1219,10 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
 	return clk;
 }
 
+static u32 bcm2835_register_clock_default_parents(
+	struct device *dev,
+	const struct bcm2835_clock_data *data);
+
 static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
 					  const struct bcm2835_clock_data *data)
 {
@@ -1263,6 +1270,8 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
 	clock->cprman = cprman;
 	clock->data = data;
 	clock->hw.init = &init;
+	clock->flags = bcm2835_register_clock_default_parents(
+		cprman->dev, data);
 
 	return devm_clk_register(cprman->dev, &clock->hw);
 }
@@ -1349,6 +1358,44 @@ static const char *const bcm2835_clock_vpu_parents[] = {
 	.parents = bcm2835_clock_vpu_parents,				\
 	__VA_ARGS__)
 
+/* calc the default flags for different clocks based on the parent array */
+static u32 bcm2835_register_clock_default_parents(
+	struct device *dev,
+	const struct bcm2835_clock_data *data)
+{
+	/* by default we disable the testdebug clocks for all known types */
+	if (data->parents == bcm2835_clock_osc_parents)
+		return
+			BIT(BCM2835_OSC_PARENT_GND) |
+			BIT(BCM2835_OSC_PARENT_OSC);
+	if (data->parents == bcm2835_clock_vpu_parents)
+		return
+			BIT(BCM2835_VPU_PARENT_GND) |
+			BIT(BCM2835_VPU_PARENT_OSC) |
+			BIT(BCM2835_VPU_PARENT_PLLA_CORE) |
+			BIT(BCM2835_VPU_PARENT_PLLC_CORE0) |
+			BIT(BCM2835_VPU_PARENT_PLLD_CORE) |
+			BIT(BCM2835_VPU_PARENT_PLLH_AUX) |
+			BIT(BCM2835_VPU_PARENT_PLLC_CORE1) |
+			BIT(BCM2835_VPU_PARENT_PLLC_CORE2);
+	if (data->parents == bcm2835_clock_per_parents)
+		return
+			BIT(BCM2835_PER_PARENT_GND) |
+			BIT(BCM2835_PER_PARENT_OSC) |
+			BIT(BCM2835_PER_PARENT_PLLA_PER) |
+			/* by default do not use PLLC_PER */
+			BIT(BCM2835_PER_PARENT_PLLD_PER) |
+			BIT(BCM2835_PER_PARENT_PLLH_AUX);
+
+	/* warn about unknown parents */
+	dev_warn(dev,
+		 "unknown clock parents for clock %s - enabling all %d parents\n",
+		 data->name, data->num_mux_parents);
+
+	/* return enable all clocks */
+	return BIT(data->num_mux_parents) - 1;
+}
+
 /*
  * the real definition of all the pll, pll_dividers and clocks
  * these make use of the above REGISTER_* macros
-- 
2.1.4



From kernel at martin.sperl.org  Thu May  5 08:53:27 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu,  5 May 2016 15:53:27 +0000
Subject: [PATCH 4/5] clk: bcm2835: allow setting clocks flags via the dt
In-Reply-To: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
References: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1462463608-22940-5-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Allow setting flags for each clock via the device tree.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 drivers/clk/bcm/clk-bcm2835.c | 57 +++++++++++++++++++++++++++++++++++--------
 1 file changed, 47 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 8a44ebf..c80487e 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1125,7 +1125,8 @@ static const struct clk_ops bcm2835_vpu_clock_clk_ops = {
 };
 
 static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman,
-					const struct bcm2835_pll_data *data)
+					const struct bcm2835_pll_data *data,
+					u32 flags)
 {
 	struct bcm2835_pll *pll;
 	struct clk_init_data init;
@@ -1152,7 +1153,8 @@ static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman,
 
 static struct clk *
 bcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
-			     const struct bcm2835_pll_divider_data *data)
+			     const struct bcm2835_pll_divider_data *data,
+			     u32 flags)
 {
 	struct bcm2835_pll_divider *divider;
 	struct clk_init_data init;
@@ -1223,8 +1225,10 @@ static u32 bcm2835_register_clock_default_parents(
 	struct device *dev,
 	const struct bcm2835_clock_data *data);
 
-static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
-					  const struct bcm2835_clock_data *data)
+static struct clk *
+bcm2835_register_clock(struct bcm2835_cprman *cprman,
+		       const struct bcm2835_clock_data *data,
+		       u32 flags)
 {
 	struct bcm2835_clock *clock;
 	struct clk_init_data init;
@@ -1270,14 +1274,19 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
 	clock->cprman = cprman;
 	clock->data = data;
 	clock->hw.init = &init;
-	clock->flags = bcm2835_register_clock_default_parents(
-		cprman->dev, data);
+
+	clock->flags = flags;
+	if ((clock->flags & (BIT(data->num_mux_parents) - 1)) == 0)
+		clock->flags |= bcm2835_register_clock_default_parents(
+			cprman->dev, data);
 
 	return devm_clk_register(cprman->dev, &clock->hw);
 }
 
-static struct clk *bcm2835_register_gate(struct bcm2835_cprman *cprman,
-					 const struct bcm2835_gate_data *data)
+static struct clk *
+bcm2835_register_gate(struct bcm2835_cprman *cprman,
+		      const struct bcm2835_gate_data *data,
+		      u32 flags)
 {
 	return clk_register_gate(cprman->dev, data->name, data->parent,
 				 CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
@@ -1286,7 +1295,7 @@ static struct clk *bcm2835_register_gate(struct bcm2835_cprman *cprman,
 }
 
 typedef struct clk *(*bcm2835_clk_register)(struct bcm2835_cprman *cprman,
-					    const void *data);
+					    const void *data, int flags);
 struct bcm2835_clk_desc {
 	bcm2835_clk_register clk_register;
 	const void *data;
@@ -1861,6 +1870,10 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
 	struct resource *res;
 	const struct bcm2835_clk_desc *desc;
 	const size_t asize = ARRAY_SIZE(clk_desc_array);
+	u32 flags[asize], index;
+	struct property *prop;
+	const __be32 *cur;
+	int ret;
 	size_t i;
 
 	cprman = devm_kzalloc(dev,
@@ -1869,6 +1882,29 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
 	if (!cprman)
 		return -ENOMEM;
 
+	/* fill in flags from dt */
+	memset(flags, 0, sizeof(flags));
+	i = 0;
+	of_property_for_each_u32(dev->of_node, "brcm,clock-index",
+				 prop, cur, index) {
+		if (index >= asize) {
+			dev_err(dev,
+				"clock-index %d in \"brcm,clock-index\" is out of bounds at position %d\n",
+				index, i);
+		} else {
+			ret = of_property_read_u32_index(dev->of_node,
+							 "brcm,clock-flags",
+							 i, &flags[index]);
+			if (ret) {
+				dev_err(dev,
+					"no value at position %d in \"brcm,clock-flags\" - %d\n",
+					i, ret);
+			}
+		}
+		/* increment index */
+		i++;
+	}
+
 	spin_lock_init(&cprman->regs_lock);
 	cprman->dev = dev;
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1889,7 +1925,8 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
 	for (i = 0; i < asize; i++) {
 		desc = &clk_desc_array[i];
 		if (desc->clk_register && desc->data)
-			clks[i] = desc->clk_register(cprman, desc->data);
+			clks[i] = desc->clk_register(cprman, desc->data,
+				flags[i]);
 	}
 
 	return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
-- 
2.1.4



From kernel at martin.sperl.org  Thu May  5 08:53:28 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu,  5 May 2016 15:53:28 +0000
Subject: [PATCH 5/5] clk: bcm2835: add support for
 BCM2835_CLOCK_FLAG_USE_MASH/INTEGER
In-Reply-To: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
References: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1462463608-22940-6-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Allow the use of higher order mash fractional divider modes
and also allow to force the use of integer dividers.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 drivers/clk/bcm/clk-bcm2835.c       | 57 +++++++++++++++++++++++++++++++++++--
 include/dt-bindings/clock/bcm2835.h |  7 +++++
 2 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index c80487e..08140ad 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -130,6 +130,7 @@
 # define CM_BUSY			BIT(7)
 # define CM_BUSYD			BIT(8)
 # define CM_FRAC			BIT(9)
+# define CM_MASH			BIT(10)
 # define CM_SRC_SHIFT			0
 # define CM_SRC_BITS			4
 # define CM_SRC_MASK			0xf
@@ -888,6 +889,24 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
 				 CM_DIV_FRAC_BITS - data->frac_bits);
 	}
 
+	/* based on flags modify settings */
+	switch (clock->flags & BCM2835_CLOCK_FLAG_USE_MASK) {
+	case BCM2835_CLOCK_FLAG_USE_FRAC:
+			break;
+	case BCM2835_CLOCK_FLAG_USE_INTEGER:
+		div &= GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
+			       CM_DIV_FRAC_BITS);
+		break;
+	case BCM2835_CLOCK_FLAG_USE_MASH2:
+		mindiv += 2 << CM_DIV_FRAC_BITS;
+		maxdiv -= 1 << CM_DIV_FRAC_BITS;
+		break;
+	case BCM2835_CLOCK_FLAG_USE_MASH3:
+		mindiv += 4 << CM_DIV_FRAC_BITS;
+		maxdiv -= 3 << CM_DIV_FRAC_BITS;
+		break;
+	}
+
 	/* apply the clamping  limits */
 	div = max_t(u32, div, mindiv);
 	div = min_t(u32, div, maxdiv);
@@ -996,8 +1015,26 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw,
 	 * clock this requirement should be take care of by the
 	 * clk-framework.
 	 */
-	ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC;
-	ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
+	ctl = cprman_read(cprman, data->ctl_reg) & ~(CM_FRAC | CM_MASH);
+	if (div & CM_DIV_FRAC_MASK) {
+		/*
+		 * we never get to *MASH* for non-mash clock,
+		 * as it is filtered in bcm2835_register_clock
+		 * USE_INTEGER forces already choose_clock_div
+		 * to apply the mask so that we do not get here
+		 */
+		switch (clock->flags & BCM2835_CLOCK_FLAG_USE_MASK) {
+		case BCM2835_CLOCK_FLAG_USE_FRAC:
+			ctl |= CM_FRAC;
+			break;
+		case BCM2835_CLOCK_FLAG_USE_MASH2:
+			ctl |= CM_MASH;
+			break;
+		case BCM2835_CLOCK_FLAG_USE_MASH3:
+			ctl |= CM_MASH | CM_FRAC;
+			break;
+		}
+	}
 	cprman_write(cprman, data->ctl_reg, ctl);
 
 	cprman_write(cprman, data->div_reg, div);
@@ -1280,6 +1317,22 @@ bcm2835_register_clock(struct bcm2835_cprman *cprman,
 		clock->flags |= bcm2835_register_clock_default_parents(
 			cprman->dev, data);
 
+	/* check for MASH flags when the clock is not a mash clock */
+	if (!data->is_mash_clock) {
+		switch (clock->flags & BCM2835_CLOCK_FLAG_USE_MASK) {
+		case BCM2835_CLOCK_FLAG_USE_MASH2:
+		case BCM2835_CLOCK_FLAG_USE_MASH3:
+			dev_warn(cprman->dev,
+				 "found mash2/mash3 flag for clock %s, which does not support mash\n",
+				 data->name);
+			clock->flags &= BCM2835_CLOCK_FLAG_USE_MASK;
+			clock->flags |= BCM2835_CLOCK_FLAG_USE_FRAC;
+			break;
+		default:
+			break;
+		}
+	}
+
 	return devm_clk_register(cprman->dev, &clock->hw);
 }
 
diff --git a/include/dt-bindings/clock/bcm2835.h b/include/dt-bindings/clock/bcm2835.h
index e5396fe..5591bd1 100644
--- a/include/dt-bindings/clock/bcm2835.h
+++ b/include/dt-bindings/clock/bcm2835.h
@@ -90,3 +90,10 @@
 #define BCM2835_VPU_PARENT_PLLH_AUX	7
 #define BCM2835_VPU_PARENT_PLLC_CORE1	8
 #define BCM2835_VPU_PARENT_PLLC_CORE2	9
+
+/* additional clock flags */
+#define BCM2835_CLOCK_FLAG_USE_FRAC	((0 << 31) | (0 << 30))
+#define BCM2835_CLOCK_FLAG_USE_INTEGER	((0 << 31) | (1 << 30))
+#define BCM2835_CLOCK_FLAG_USE_MASH2	((1 << 31) | (0 << 30))
+#define BCM2835_CLOCK_FLAG_USE_MASH3	((1 << 31) | (1 << 30))
+#define BCM2835_CLOCK_FLAG_USE_MASK	((1 << 31) | (1 << 30))
-- 
2.1.4



From broonie at kernel.org  Thu May  5 08:56:23 2016
From: broonie at kernel.org (Mark Brown)
Date: Thu, 05 May 2016 16:56:23 +0100
Subject: Applied "ASoC: rockchip: Revert "ASoC: rockchip: i2s: remove unused
 variables"" to the asoc tree
In-Reply-To: <1462373686-21794-1-git-send-email-john@metanate.com>
Message-ID: <E1ayLdX-0004kH-IJ@debutante>

The patch

   ASoC: rockchip: Revert "ASoC: rockchip: i2s: remove unused variables"

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From a6e806c49e3265494ac6fe6ec88ed5c010652e0d Mon Sep 17 00:00:00 2001
From: John Keeping <john at metanate.com>
Date: Wed, 4 May 2016 17:21:56 +0100
Subject: [PATCH] ASoC: rockchip: Revert "ASoC: rockchip: i2s: remove unused
 variables"

This reverts commit 5938448b99275cba95167c3f9d39ca9225fdad38.

It turns out that the commit that made these variables unused is wrong
so we're about to revert it.  Bring back the variables in prepration.

Signed-off-by: John Keeping <john at metanate.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 sound/soc/rockchip/rockchip_i2s.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 2f8e20416bd3..34743ec61c49 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -34,6 +34,13 @@ struct rk_i2s_dev {
 
 	struct regmap *regmap;
 
+/*
+ * Used to indicate the tx/rx status.
+ * I2S controller hopes to start the tx and rx together,
+ * also to stop them when they are both try to stop.
+*/
+	bool tx_start;
+	bool rx_start;
 	bool is_master_mode;
 };
 
@@ -77,7 +84,11 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
 		regmap_update_bits(i2s->regmap, I2S_XFER,
 				   I2S_XFER_TXS_START,
 				   I2S_XFER_TXS_START);
+
+		i2s->tx_start = true;
 	} else {
+		i2s->tx_start = false;
+
 		regmap_update_bits(i2s->regmap, I2S_DMACR,
 				   I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
 
@@ -115,7 +126,11 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
 		regmap_update_bits(i2s->regmap, I2S_XFER,
 				   I2S_XFER_RXS_START,
 				   I2S_XFER_RXS_START);
+
+		i2s->rx_start = true;
 	} else {
+		i2s->rx_start = false;
+
 		regmap_update_bits(i2s->regmap, I2S_DMACR,
 				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
 
-- 
2.8.1



From broonie at kernel.org  Thu May  5 08:56:20 2016
From: broonie at kernel.org (Mark Brown)
Date: Thu, 05 May 2016 16:56:20 +0100
Subject: Applied "ASoC: rockchip: Revert "ASoC: rockchip: i2s: separate
 capture and playback"" to the asoc tree
In-Reply-To: <1462373686-21794-2-git-send-email-john@metanate.com>
Message-ID: <E1ayLdU-0004jH-K0@debutante>

The patch

   ASoC: rockchip: Revert "ASoC: rockchip: i2s: separate capture and playback"

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 7e885d211f023dfd201fad8246bbf3c3bd126c61 Mon Sep 17 00:00:00 2001
From: John Keeping <john at metanate.com>
Date: Wed, 4 May 2016 17:21:57 +0100
Subject: [PATCH] ASoC: rockchip: Revert "ASoC: rockchip: i2s: separate capture
 and playback"

This reverts commit eba65d179c1149cf79e68608d452631f33d7f017.

This broke audio on Veyron Jerry Chromebooks and I now cannot reproduce
the problem I was trying to fix even with this commit reverted, so it
seems that this was completely the wrong thing to do.

Reported-by: Enric Balletbo Serra <eballetbo at gmail.com>
Signed-off-by: John Keeping <john at metanate.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 sound/soc/rockchip/rockchip_i2s.c | 72 ++++++++++++++++++++++-----------------
 1 file changed, 40 insertions(+), 32 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 34743ec61c49..574c6af28c06 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -82,8 +82,8 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
 				   I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
 
 		regmap_update_bits(i2s->regmap, I2S_XFER,
-				   I2S_XFER_TXS_START,
-				   I2S_XFER_TXS_START);
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START);
 
 		i2s->tx_start = true;
 	} else {
@@ -92,23 +92,27 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
 		regmap_update_bits(i2s->regmap, I2S_DMACR,
 				   I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
 
-		regmap_update_bits(i2s->regmap, I2S_XFER,
-				   I2S_XFER_TXS_START,
-				   I2S_XFER_TXS_STOP);
-
-		regmap_update_bits(i2s->regmap, I2S_CLR,
-				   I2S_CLR_TXC,
-				   I2S_CLR_TXC);
+		if (!i2s->rx_start) {
+			regmap_update_bits(i2s->regmap, I2S_XFER,
+					   I2S_XFER_TXS_START |
+					   I2S_XFER_RXS_START,
+					   I2S_XFER_TXS_STOP |
+					   I2S_XFER_RXS_STOP);
 
-		regmap_read(i2s->regmap, I2S_CLR, &val);
+			regmap_update_bits(i2s->regmap, I2S_CLR,
+					   I2S_CLR_TXC | I2S_CLR_RXC,
+					   I2S_CLR_TXC | I2S_CLR_RXC);
 
-		/* Should wait for clear operation to finish */
-		while (val & I2S_CLR_TXC) {
 			regmap_read(i2s->regmap, I2S_CLR, &val);
-			retry--;
-			if (!retry) {
-				dev_warn(i2s->dev, "fail to clear\n");
-				break;
+
+			/* Should wait for clear operation to finish */
+			while (val) {
+				regmap_read(i2s->regmap, I2S_CLR, &val);
+				retry--;
+				if (!retry) {
+					dev_warn(i2s->dev, "fail to clear\n");
+					break;
+				}
 			}
 		}
 	}
@@ -124,8 +128,8 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
 				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
 
 		regmap_update_bits(i2s->regmap, I2S_XFER,
-				   I2S_XFER_RXS_START,
-				   I2S_XFER_RXS_START);
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+				   I2S_XFER_TXS_START | I2S_XFER_RXS_START);
 
 		i2s->rx_start = true;
 	} else {
@@ -134,23 +138,27 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
 		regmap_update_bits(i2s->regmap, I2S_DMACR,
 				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
 
-		regmap_update_bits(i2s->regmap, I2S_XFER,
-				   I2S_XFER_RXS_START,
-				   I2S_XFER_RXS_STOP);
-
-		regmap_update_bits(i2s->regmap, I2S_CLR,
-				   I2S_CLR_RXC,
-				   I2S_CLR_RXC);
+		if (!i2s->tx_start) {
+			regmap_update_bits(i2s->regmap, I2S_XFER,
+					   I2S_XFER_TXS_START |
+					   I2S_XFER_RXS_START,
+					   I2S_XFER_TXS_STOP |
+					   I2S_XFER_RXS_STOP);
 
-		regmap_read(i2s->regmap, I2S_CLR, &val);
+			regmap_update_bits(i2s->regmap, I2S_CLR,
+					   I2S_CLR_TXC | I2S_CLR_RXC,
+					   I2S_CLR_TXC | I2S_CLR_RXC);
 
-		/* Should wait for clear operation to finish */
-		while (val & I2S_CLR_RXC) {
 			regmap_read(i2s->regmap, I2S_CLR, &val);
-			retry--;
-			if (!retry) {
-				dev_warn(i2s->dev, "fail to clear\n");
-				break;
+
+			/* Should wait for clear operation to finish */
+			while (val) {
+				regmap_read(i2s->regmap, I2S_CLR, &val);
+				retry--;
+				if (!retry) {
+					dev_warn(i2s->dev, "fail to clear\n");
+					break;
+				}
 			}
 		}
 	}
-- 
2.8.1



From rmk+kernel at armlinux.org.uk  Thu May  5 09:12:54 2016
From: rmk+kernel at armlinux.org.uk (Russell King)
Date: Thu, 5 May 2016 17:12:54 +0100
Subject: [PATCH] maintainers: update my email address(es)
Message-ID: <20160505161254.GY19428@n2100.arm.linux.org.uk>

Update my email and web addresses in the kernel maintainers file.

Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
---
 MAINTAINERS | 48 ++++++++++++++++++++++++------------------------
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index ecbb2f6a3ba0..73141b4f46a9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -872,9 +872,9 @@ F:	drivers/perf/arm_pmu.c
 F:	include/linux/perf/arm_pmu.h
 
 ARM PORT
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-W:	http://www.arm.linux.org.uk/
+W:	http://www.armlinux.org.uk/
 S:	Maintained
 F:	arch/arm/
 
@@ -886,35 +886,35 @@ F:	arch/arm/plat-*/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git
 
 ARM PRIMECELL AACI PL041 DRIVER
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 S:	Maintained
 F:	sound/arm/aaci.*
 
 ARM PRIMECELL CLCD PL110 DRIVER
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 S:	Maintained
 F:	drivers/video/fbdev/amba-clcd.*
 
 ARM PRIMECELL KMI PL050 DRIVER
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 S:	Maintained
 F:	drivers/input/serio/ambakmi.*
 F:	include/linux/amba/kmi.h
 
 ARM PRIMECELL MMCI PL180/1 DRIVER
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 S:	Maintained
 F:	drivers/mmc/host/mmci.*
 F:	include/linux/amba/mmci.h
 
 ARM PRIMECELL UART PL010 AND PL011 DRIVERS
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 S:	Maintained
 F:	drivers/tty/serial/amba-pl01*.c
 F:	include/linux/amba/serial.h
 
 ARM PRIMECELL BUS SUPPORT
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 S:	Maintained
 F:	drivers/amba/
 F:	include/linux/amba/bus.h
@@ -1036,7 +1036,7 @@ L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 
 ARM/CLKDEV SUPPORT
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/include/asm/clkdev.h
@@ -1093,9 +1093,9 @@ F:	arch/arm/boot/dts/cx92755*
 N:	digicolor
 
 ARM/EBSA110 MACHINE SUPPORT
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-W:	http://www.arm.linux.org.uk/
+W:	http://www.armlinux.org.uk/
 S:	Maintained
 F:	arch/arm/mach-ebsa110/
 F:	drivers/net/ethernet/amd/am79c961a.*
@@ -1124,9 +1124,9 @@ T:	git git://git.berlios.de/gemini-board
 F:	arch/arm/mm/*-fa*
 
 ARM/FOOTBRIDGE ARCHITECTURE
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-W:	http://www.arm.linux.org.uk/
+W:	http://www.armlinux.org.uk/
 S:	Maintained
 F:	arch/arm/include/asm/hardware/dec21285.h
 F:	arch/arm/mach-footbridge/
@@ -1457,7 +1457,7 @@ S:	Maintained
 ARM/PT DIGITAL BOARD PORT
 M:	Stefan Eletzhofer <stefan.eletzhofer at eletztrick.de>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-W:	http://www.arm.linux.org.uk/
+W:	http://www.armlinux.org.uk/
 S:	Maintained
 
 ARM/QUALCOMM SUPPORT
@@ -1493,9 +1493,9 @@ S:	Supported
 F:	arch/arm64/boot/dts/renesas/
 
 ARM/RISCPC ARCHITECTURE
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-W:	http://www.arm.linux.org.uk/
+W:	http://www.armlinux.org.uk/
 S:	Maintained
 F:	arch/arm/include/asm/hardware/entry-macro-iomd.S
 F:	arch/arm/include/asm/hardware/ioc.h
@@ -1773,9 +1773,9 @@ F:	drivers/clk/versatile/clk-vexpress-osc.c
 F:	drivers/clocksource/versatile.c
 
 ARM/VFP SUPPORT
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-W:	http://www.arm.linux.org.uk/
+W:	http://www.armlinux.org.uk/
 S:	Maintained
 F:	arch/arm/vfp/
 
@@ -2921,7 +2921,7 @@ F:	mm/cleancache.c
 F:	include/linux/cleancache.h
 
 CLK API
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 L:	linux-clk at vger.kernel.org
 S:	Maintained
 F:	include/linux/clk.h
@@ -3354,9 +3354,9 @@ S:	Supported
 F:	drivers/net/ethernet/stmicro/stmmac/
 
 CYBERPRO FB DRIVER
-M:	Russell King <linux at arm.linux.org.uk>
+M:	Russell King <linux at armlinux.org.uk>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-W:	http://www.arm.linux.org.uk/
+W:	http://www.armlinux.org.uk/
 S:	Maintained
 F:	drivers/video/fbdev/cyber2000fb.*
 
@@ -3881,7 +3881,7 @@ F:	Documentation/devicetree/bindings/display/st,stih4xx.txt
 
 DRM DRIVERS FOR VIVANTE GPU IP
 M:	Lucas Stach <l.stach at pengutronix.de>
-R:	Russell King <linux+etnaviv at arm.linux.org.uk>
+R:	Russell King <linux+etnaviv at armlinux.org.uk>
 R:	Christian Gmeiner <christian.gmeiner at gmail.com>
 L:	dri-devel at lists.freedesktop.org
 S:	Maintained
@@ -6905,7 +6905,7 @@ L:	linux-man at vger.kernel.org
 S:	Maintained
 
 MARVELL ARMADA DRM SUPPORT
-M:	Russell King <rmk+kernel at arm.linux.org.uk>
+M:	Russell King <rmk+kernel at armlinux.org.uk>
 S:	Maintained
 F:	drivers/gpu/drm/armada/
 
@@ -7905,7 +7905,7 @@ S:	Supported
 F:	drivers/nfc/nxp-nci
 
 NXP TDA998X DRM DRIVER
-M:	Russell King <rmk+kernel at arm.linux.org.uk>
+M:	Russell King <rmk+kernel at armlinux.org.uk>
 S:	Supported
 F:	drivers/gpu/drm/i2c/tda998x_drv.c
 F:	include/drm/i2c/tda998x.h

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From robin.murphy at arm.com  Thu May  5 09:13:37 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu,  5 May 2016 17:13:37 +0100
Subject: [PATCH 1/2] drm: hdlcd: Skip PM callbacks if unbound
Message-ID: <eeb2a5540f50f5a3dd7f87861be1e9117bc4ed65.1462464611.git.robin.murphy@arm.com>

Until an encoder component is available to trigger the HDLCD's component
master bind callback, the drm_device we keep in drvdata isn't allocated.
Since it is quite possible to, say, hibernate the system without having
loaded the encoder driver, the PM callbacks need to check for a valid
drm_device before trying to take the lock and suspend/resume the crtcs,
otherwise this happens:

[   51.779092] Unable to handle kernel NULL pointer dereference at virtual address 00000200
[   51.787143] pgd = ffff800974462000
[   51.790514] [00000200] *pgd=0000000000000000
[   51.794768] Internal error: Oops: 96000004 [#1] PREEMPT SMP
[   51.800291] Modules linked in:
[   51.803325] CPU: 4 PID: 2098 Comm: systemd-sleep Not tainted 4.6.0-rc6+ #4
[   51.810140] Hardware name: ARM Juno development board (r1) (DT)
[   51.816008] task: ffff800974430000 ti: ffff80097380c000 task.ti: ffff80097380c000
[   51.823433] PC is at mutex_lock+0x14/0x60
[   51.827411] LR is at drm_modeset_lock_all+0x3c/0xe0
[   51.832246] pc : [<ffff0000087d55c4>] lr : [<ffff0000084839fc>] pstate: 40000145
[   51.839577] sp : ffff80097380faf0
[   51.842859] x29: ffff80097380faf0 x28: 0000000000000000
[   51.848132] x27: 0000000000000002 x26: ffff000008e01000
[   51.853405] x25: ffff0000084cc000 x24: ffff000008dcb408
[   51.858678] x23: ffff000008e7c000 x22: ffff8009760e8870
[   51.863962] x21: 0000000000000200 x20: 0000000000000000
[   51.869244] x19: 0000000000000200 x18: ffff800079357dd0
[   51.874527] x17: 0000ffff8a00ab88 x16: 0000000000000018
[   51.879809] x15: 0000000000000018 x14: 0000000000000000
[   51.885091] x13: 0000000000000002 x12: 0000000000000000
[   51.890374] x11: ffff0000087ff904 x10: 0000000000000840
[   51.895656] x9 : 0000000000000000 x8 : ffff800973821680
[   51.900938] x7 : 0000000000000000 x6 : 000000000000003f
[   51.906220] x5 : 0000000000000040 x4 : 0000000000000000
[   51.911502] x3 : 0000000000000004 x2 : 0000000000000000
[   51.916784] x1 : 0000000000000001 x0 : 0000000000000200
...
[   52.339406] [<ffff0000087d55c4>] mutex_lock+0x14/0x60
[   52.344425] [<ffff0000084839fc>] drm_modeset_lock_all+0x3c/0xe0
[   52.350305] [<ffff00000848a034>] hdlcd_pm_suspend+0x2c/0x90
[   52.355842] [<ffff0000084c0d14>] platform_pm_suspend+0x24/0x58
[   52.361638] [<ffff0000084cc190>] dpm_run_callback.isra.4+0x20/0x68
[   52.367778] [<ffff0000084ccad4>] __device_suspend+0xe4/0x238
[   52.373400] [<ffff0000084cdcac>] dpm_suspend+0x10c/0x240
[   52.378679] [<ffff0000084ce0b8>] dpm_suspend_start+0x70/0x80
[   52.384302] [<ffff0000080f80e4>] suspend_devices_and_enter+0x9c/0x480
[   52.390699] [<ffff0000080f8698>] pm_suspend+0x1d0/0x240
[   52.395890] [<ffff0000080f7280>] state_store+0x80/0x100
[   52.401084] [<ffff0000083503f4>] kobj_attr_store+0x14/0x28
[   52.406535] [<ffff000008238580>] sysfs_kf_write+0x48/0x58
[   52.411899] [<ffff00000823798c>] kernfs_fop_write+0xbc/0x188
[   52.417521] [<ffff0000081c71f4>] __vfs_write+0x1c/0xe0
[   52.422626] [<ffff0000081c8144>] vfs_write+0x8c/0x1a8
[   52.427644] [<ffff0000081c953c>] SyS_write+0x44/0xa0
[   52.432578] [<ffff000008084ecc>] __sys_trace_return+0x0/0x4
[   52.438114] Code: 910003fd f9000bf3 aa0003f3 f9800011 (885ffc01)
[   52.444229] ---[ end trace 34b87a5fb9453f65 ]---

Acked-by: Liviu Dudau <Liviu.Dudau at arm.com>
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 drivers/gpu/drm/arm/hdlcd_drv.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 734899c4e4bb..86a5eea4cf53 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -498,7 +498,7 @@ static int __maybe_unused hdlcd_pm_suspend(struct device *dev)
 	struct drm_device *drm = dev_get_drvdata(dev);
 	struct drm_crtc *crtc;
 
-	if (pm_runtime_suspended(dev))
+	if (pm_runtime_suspended(dev) || !drm)
 		return 0;
 
 	drm_modeset_lock_all(drm);
@@ -513,7 +513,7 @@ static int __maybe_unused hdlcd_pm_resume(struct device *dev)
 	struct drm_device *drm = dev_get_drvdata(dev);
 	struct drm_crtc *crtc;
 
-	if (!pm_runtime_suspended(dev))
+	if (!pm_runtime_suspended(dev) || !drm)
 		return 0;
 
 	drm_modeset_lock_all(drm);
-- 
2.8.1.dirty



From robin.murphy at arm.com  Thu May  5 09:13:38 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu,  5 May 2016 17:13:38 +0100
Subject: [PATCH 2/2] drm: hdlcd: Suspend/resume only active crtcs
In-Reply-To: <eeb2a5540f50f5a3dd7f87861be1e9117bc4ed65.1462464611.git.robin.murphy@arm.com>
References: <eeb2a5540f50f5a3dd7f87861be1e9117bc4ed65.1462464611.git.robin.murphy@arm.com>
Message-ID: <759fe8d3dde95091a9df83018051cba00f494e1e.1462464611.git.robin.murphy@arm.com>

The current PM ops simply unconditionally enable/disable the HDLCD,
which proves problematic when there is no display plugged in - since
without a crtc the hardware itself is still in an uninitialised state,
coming out of suspend results in it being enabled without a valid
framebuffer address, which typically results in it trying to scan out
from bus address 0 and flooding the system with error interrupts.

Fix this by checking the crtc state on resume, and only enabling the
hardware if it's actually supposed to be. For the sake of consistency,
do the same on the suspend path as well, although there it's merely a
case of skipping unnecessary work.

CC: Liviu Dudau <liviu.dudau at arm.com>
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 drivers/gpu/drm/arm/hdlcd_crtc.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index fef1b04c2aab..bf6ff5e48adc 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -296,12 +296,14 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
 
 void hdlcd_crtc_suspend(struct drm_crtc *crtc)
 {
-	hdlcd_crtc_disable(crtc);
+	if (crtc->state->active)
+		hdlcd_crtc_disable(crtc);
 }
 
 void hdlcd_crtc_resume(struct drm_crtc *crtc)
 {
-	hdlcd_crtc_enable(crtc);
+	if (crtc->state->active)
+		hdlcd_crtc_enable(crtc);
 }
 
 int hdlcd_setup_crtc(struct drm_device *drm)
-- 
2.8.1.dirty



From ray.jui at broadcom.com  Thu May  5 09:14:07 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Thu, 5 May 2016 09:14:07 -0700
Subject: [PATCH v2] irqchip/gic-v2m: Add workaround for Broadcom NS2
 GICv2m erratum
In-Reply-To: <572AF86A.1090000@arm.com>
References: <1462405635-27864-1-git-send-email-ray.jui@broadcom.com>
 <1462405635-27864-2-git-send-email-ray.jui@broadcom.com>
 <572AF86A.1090000@arm.com>
Message-ID: <7724bb0f-9b0e-ea4c-ea87-c462adac1fe9@broadcom.com>



On 5/5/2016 12:38 AM, Marc Zyngier wrote:
> On 05/05/16 00:47, Ray Jui wrote:
>> Alex Barba <alex.barba at broadcom.com> discovered Broadcom NS2 GICv2m
>> implementation has an erratum where the MSI data needs to be the SPI
>> number subtracted by an offset of 32, for the correct MSI interrupt
>> to be triggered.
>>
>> Here we are adding the workaround based on readings from the MSI_IIDR
>> register, which contains a value unique to Broadcom NS2 GICv2m
>>
>> Reported-by: Alex Barba <alex.barba at broadcom.com>
>> Signed-off-by: Ray Jui <ray.jui at broadcom.com>
>> ---
>>  drivers/irqchip/irq-gic-v2m.c | 17 +++++++++++++++--
>>  1 file changed, 15 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
>> index 28f047c..4c89e27 100644
>> --- a/drivers/irqchip/irq-gic-v2m.c
>> +++ b/drivers/irqchip/irq-gic-v2m.c
>> @@ -49,6 +49,9 @@
>>  /* APM X-Gene with GICv2m MSI_IIDR register value */
>>  #define XGENE_GICV2M_MSI_IIDR		0x06000170
>>
>> +/* Broadcom NS2 GICv2m MSI_IIDR register value */
>> +#define BCM_NS2_GICV2M_MSI_IIDR		0x0000013f
>> +
>>  /* List of flags for specific v2m implementation */
>>  #define GICV2M_NEEDS_SPI_OFFSET		0x00000001
>>
>> @@ -62,6 +65,7 @@ struct v2m_data {
>>  	void __iomem *base;	/* GICv2m virt address */
>>  	u32 spi_start;		/* The SPI number that MSIs start */
>>  	u32 nr_spis;		/* The number of SPIs for MSIs */
>> +	u32 spi_offset;		/* offset to be subtracted from SPI number */
>>  	unsigned long *bm;	/* MSI vector bitmap */
>>  	u32 flags;		/* v2m flags for specific implementation */
>>  };
>> @@ -102,7 +106,7 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
>>  	msg->data = data->hwirq;
>>
>>  	if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET)
>> -		msg->data -= v2m->spi_start;
>> +		msg->data -= v2m->spi_offset;
>>  }
>>
>>  static struct irq_chip gicv2m_irq_chip = {
>> @@ -340,9 +344,18 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
>>  	 * different from the standard GICv2m implementation where
>>  	 * the MSI data is the absolute value within the range from
>>  	 * spi_start to (spi_start + num_spis).
>> +	 *
>> +	 * Broadom NS2 GICv2m implementation has an erratum where the MSI data
>> +	 * is 'spi_number - 32'
>>  	 */
>> -	if (readl_relaxed(v2m->base + V2M_MSI_IIDR) == XGENE_GICV2M_MSI_IIDR)
>> +	if (readl_relaxed(v2m->base + V2M_MSI_IIDR) == XGENE_GICV2M_MSI_IIDR) {
>> +		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
>> +		v2m->spi_offset = v2m->spi_start;
>> +	} else if (readl_relaxed(v2m->base + V2M_MSI_IIDR) ==
>> +		   BCM_NS2_GICV2M_MSI_IIDR) {
>>  		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
>> +		v2m->spi_offset = 32;
>> +	}
>
> Can we make this a bit less ugly?
>
> 	switch (readl_relaxed(v2m->base + V2M_MSI_IIDR)) {
> 	case XGENE_GICV2M_MSI_IIDR:
> 		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
> 		v2m->spi_offset = v2m->spi_start;
> 		break;
> 	case BCM_NS2_GICV2M_MSI_IIDR:
> 		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
> 		v2m->spi_offset = 32;
> 		break;
> 	}

Okay will do that!

>
> Thanks,
>
> 	M.
>

Thanks,

Ray


From thomas.hanson at linaro.org  Thu May  5 09:23:32 2016
From: thomas.hanson at linaro.org (Tom Hanson)
Date: Thu, 5 May 2016 10:23:32 -0600
Subject: [PATCH v2 16/54] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <1461861973-26464-17-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-17-git-send-email-andre.przywara@arm.com>
Message-ID: <572B7384.2050405@linaro.org>

On 04/28/2016 10:45 AM, Andre Przywara wrote:

...

> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 4fb20fd..a656a12e5 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c

...
> +static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
> +{

...

> +		/* This interrupt looks like it has to be migrated. */
> +
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vgic_cpu->ap_list_lock);

If using the suggested (but not provided) higher level function from patch 14 this could be:
                 vgic_unlock_aplist_irq(, spinlock_t irq);
> +
> +		/*
> +		 * Ensure locking order by always locking the smallest
> +		 * ID first.
> +		 */
> +		if (vcpu->vcpu_id < target_vcpu->vcpu_id) {
> +			vcpuA = vcpu;
> +			vcpuB = target_vcpu;
> +		} else {
> +			vcpuA = target_vcpu;
> +			vcpuB = vcpu;
> +		}
> +
> +		spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
> +		spin_lock(&vcpuB->arch.vgic_cpu.ap_list_lock);

And this whole block could be replaced by:
                 vgic_lock_cpu_aplist_pair(vcpuA, vcpuB)

> +             spin_lock(&irq->irq_lock);

...

> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
> +		spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
And this could be:
                 vgic_unlock_cpu_aplist_pair(vcpuA, vcpuB)

> +		goto retry;
> +	}
> +
> +	spin_unlock(&vgic_cpu->ap_list_lock);
> +}


From ray.jui at broadcom.com  Thu May  5 09:32:00 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Thu,  5 May 2016 09:32:00 -0700
Subject: [PATCH v3] Workaround for Broadcom NS2 gicv2m implementation
Message-ID: <1462465921-3220-1-git-send-email-ray.jui@broadcom.com>

Alex Barba <alex.barba at broadcom.com> discovered Broadcom NS2 GICv2m
implementation has an erratum where the MSI data needs to be the SPI number
subtracted by an offset of 32, for the correct MSI interrupt to be triggered.

We are now implementating the workaround based on readings from the MSI_IIDR
register.

Patch series is developed based on Linux v4.6-rc1 and available at:
https://github.com/Broadcom/arm64-linux/tree/gicv2m-iproc-v3

Changes from v2:
 - Improved the logic of dealing with MSI_IIDR readings by using a switch
statement suggested by Marc Zyngier

Changes from v1:
 - Changed from DT based approach to the approch similar to APM that is based
on readings from the MSI_IIDR register

Ray Jui (1):
  irqchip/gic-v2m: Add workaround for Broadcom NS2 GICv2m erratum

 drivers/irqchip/irq-gic-v2m.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

-- 
2.1.4



From ray.jui at broadcom.com  Thu May  5 09:32:01 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Thu,  5 May 2016 09:32:01 -0700
Subject: [PATCH v3] irqchip/gic-v2m: Add workaround for Broadcom NS2 GICv2m
 erratum
In-Reply-To: <1462465921-3220-1-git-send-email-ray.jui@broadcom.com>
References: <1462465921-3220-1-git-send-email-ray.jui@broadcom.com>
Message-ID: <1462465921-3220-2-git-send-email-ray.jui@broadcom.com>

Alex Barba <alex.barba at broadcom.com> discovered Broadcom NS2 GICv2m
implementation has an erratum where the MSI data needs to be the SPI
number subtracted by an offset of 32, for the correct MSI interrupt
to be triggered.

Here we are adding the workaround based on readings from the MSI_IIDR
register, which contains a value unique to Broadcom NS2 GICv2m

Reported-by: Alex Barba <alex.barba at broadcom.com>
Signed-off-by: Ray Jui <ray.jui at broadcom.com>
---
 drivers/irqchip/irq-gic-v2m.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 28f047c..ad0d296 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -49,6 +49,9 @@
 /* APM X-Gene with GICv2m MSI_IIDR register value */
 #define XGENE_GICV2M_MSI_IIDR		0x06000170
 
+/* Broadcom NS2 GICv2m MSI_IIDR register value */
+#define BCM_NS2_GICV2M_MSI_IIDR		0x0000013f
+
 /* List of flags for specific v2m implementation */
 #define GICV2M_NEEDS_SPI_OFFSET		0x00000001
 
@@ -62,6 +65,7 @@ struct v2m_data {
 	void __iomem *base;	/* GICv2m virt address */
 	u32 spi_start;		/* The SPI number that MSIs start */
 	u32 nr_spis;		/* The number of SPIs for MSIs */
+	u32 spi_offset;		/* offset to be subtracted from SPI number */
 	unsigned long *bm;	/* MSI vector bitmap */
 	u32 flags;		/* v2m flags for specific implementation */
 };
@@ -102,7 +106,7 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 	msg->data = data->hwirq;
 
 	if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET)
-		msg->data -= v2m->spi_start;
+		msg->data -= v2m->spi_offset;
 }
 
 static struct irq_chip gicv2m_irq_chip = {
@@ -340,9 +344,20 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
 	 * different from the standard GICv2m implementation where
 	 * the MSI data is the absolute value within the range from
 	 * spi_start to (spi_start + num_spis).
+	 *
+	 * Broadom NS2 GICv2m implementation has an erratum where the MSI data
+	 * is 'spi_number - 32'
 	 */
-	if (readl_relaxed(v2m->base + V2M_MSI_IIDR) == XGENE_GICV2M_MSI_IIDR)
+	switch (readl_relaxed(v2m->base + V2M_MSI_IIDR)) {
+	case XGENE_GICV2M_MSI_IIDR:
+		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
+		v2m->spi_offset = v2m->spi_start;
+		break;
+	case BCM_NS2_GICV2M_MSI_IIDR:
 		v2m->flags |= GICV2M_NEEDS_SPI_OFFSET;
+		v2m->spi_offset = 32;
+		break;
+	}
 
 	v2m->bm = kzalloc(sizeof(long) * BITS_TO_LONGS(v2m->nr_spis),
 			  GFP_KERNEL);
-- 
2.1.4



From thomas.hanson at linaro.org  Thu May  5 09:34:48 2016
From: thomas.hanson at linaro.org (Tom Hanson)
Date: Thu, 5 May 2016 10:34:48 -0600
Subject: [PATCH v2 14/54] KVM: arm/arm64: vgic-new: Implement virtual IRQ
 injection
In-Reply-To: <572B2D88.3050504@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-15-git-send-email-andre.przywara@arm.com>
 <57293844.1060802@linaro.org> <572B2D88.3050504@arm.com>
Message-ID: <572B7628.4020608@linaro.org>

On 05/05/2016 05:24 AM, Andre Przywara wrote:
> Hi Tom,
>
> thanks for looking at the patches!
>

You're quite welcome.  It's a great way to spin-up.

> The idea isn't too bad indeed.
> I see that we could use that in vgic_queue_irq_unlock() and
> vgic_mmio_write_sactive().
> But as Marc mentioned in a conversation yesterday we will have a mixture
> of wrapped locks and open coded lock sequences. See for instance
> vgic_prune_ap_list(), where we have the sequence, but we can't use
> vgic_lock_aplist_irq() because the IRQ lock is taken inside the loop
> while the ap_list_lock is taken once outside of it.

Agreed.  I looked at a few places where it wouldn't work. Definitely not a blanket solution but every little bit helps, especially if it helps avoid a bug such as a deadlock that may take hours to track down.  Been there, done that. :-)




From briannorris at chromium.org  Thu May  5 09:37:48 2016
From: briannorris at chromium.org (Brian Norris)
Date: Thu, 5 May 2016 09:37:48 -0700
Subject: [PATCH] clk: rockchip: fix the rk3399 sdmmc sample / drv name
In-Reply-To: <1462404985-27957-1-git-send-email-dianders@chromium.org>
References: <1462404985-27957-1-git-send-email-dianders@chromium.org>
Message-ID: <20160505163748.GA97052@google.com>

On Wed, May 04, 2016 at 04:36:25PM -0700, Douglas Anderson wrote:
> The rk3399 clock table had a simple typo in it, calling the SDMMC sample
> and drive clocks by the wrong name.  Fix this minor typo.
> 
> Signed-off-by: Douglas Anderson <dianders at chromium.org>

LGTM.

Tested-by: Brian Norris <briannorris at chromium.org>
Acked-by: Brian Norris <briannorris at chromium.org>

> ---
>  drivers/clk/rockchip/clk-rk3399.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
> index 5248726af86d..291543f52caa 100644
> --- a/drivers/clk/rockchip/clk-rk3399.c
> +++ b/drivers/clk/rockchip/clk-rk3399.c
> @@ -894,8 +894,8 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
>  			RK3399_CLKSEL_CON(16), 8, 3, MFLAGS, 0, 7, DFLAGS,
>  			RK3399_CLKGATE_CON(6), 1, GFLAGS),
>  
> -	MMC(SCLK_SDMMC_DRV,     "emmc_drv",    "clk_sdmmc", RK3399_SDMMC_CON0, 1),
> -	MMC(SCLK_SDMMC_SAMPLE,  "emmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 1),
> +	MMC(SCLK_SDMMC_DRV,     "sdmmc_drv",    "clk_sdmmc", RK3399_SDMMC_CON0, 1),
> +	MMC(SCLK_SDMMC_SAMPLE,  "sdmmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 1),
>  
>  	MMC(SCLK_SDIO_DRV,      "sdio_drv",    "clk_sdio",  RK3399_SDIO_CON0,  1),
>  	MMC(SCLK_SDIO_SAMPLE,   "sdio_sample", "clk_sdio",  RK3399_SDIO_CON1,  1),
> -- 
> 2.8.0.rc3.226.g39d4020


From marc.zyngier at arm.com  Thu May  5 09:39:37 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 5 May 2016 17:39:37 +0100
Subject: [PATCH v3] irqchip/gic-v2m: Add workaround for Broadcom NS2
 GICv2m erratum
In-Reply-To: <1462465921-3220-2-git-send-email-ray.jui@broadcom.com>
References: <1462465921-3220-1-git-send-email-ray.jui@broadcom.com>
 <1462465921-3220-2-git-send-email-ray.jui@broadcom.com>
Message-ID: <572B7749.3070708@arm.com>

On 05/05/16 17:32, Ray Jui wrote:
> Alex Barba <alex.barba at broadcom.com> discovered Broadcom NS2 GICv2m
> implementation has an erratum where the MSI data needs to be the SPI
> number subtracted by an offset of 32, for the correct MSI interrupt
> to be triggered.
> 
> Here we are adding the workaround based on readings from the MSI_IIDR
> register, which contains a value unique to Broadcom NS2 GICv2m
> 
> Reported-by: Alex Barba <alex.barba at broadcom.com>
> Signed-off-by: Ray Jui <ray.jui at broadcom.com>

Acked-by: Marc Zyngier <marc.zyngier at arm.com>

I'll queue that for 4.7.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From linux at roeck-us.net  Thu May  5 09:43:00 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Thu, 5 May 2016 09:43:00 -0700
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <572A2099.4070901@codeaurora.org>
References: <20da73bb9bdf27993514c1da80fead13dc92932d.1462262900.git.panand@redhat.com>
 <5728A7C3.4010001@roeck-us.net>
 <20160503143856.GE13045@dhcppc6.redhat.com>
 <5728BEC4.6050603@codeaurora.org>
 <20160503155141.GF13045@dhcppc6.redhat.com>
 <20160503171602.GA2518@roeck-us.net>
 <20160504141449.GG13045@dhcppc6.redhat.com>
 <572A0577.1070000@codeaurora.org>
 <20160504155932.GH13045@dhcppc6.redhat.com>
 <572A2099.4070901@codeaurora.org>
Message-ID: <20160505164300.GA16914@roeck-us.net>

On Wed, May 04, 2016 at 11:17:29AM -0500, Timur Tabi wrote:
> Pratyush Anand wrote:
> >Its unique to SBSA because you have very little timeout here. kexec-tools
> >upstream does not have any mechanism to handle watchdog timeout. Lets say even
> >if we implement a framework there, the best it can do is to ping the watchdog
> >again.
> 
> Ok, so it's more accurate to say that kexec has a minimum watchdog timeout
> requirement.  What happens if the system admin sets the timeout to 5 seconds
> arbitrarily?  The system will reset during kexec, no matter which hardware
> is used.
> 
> This still sounds like a band-aid to me.  We're just assuming that we need a
> timeout of at least 20 seconds to support kexec.  Frankly, this still sounds
> like a problem the kexec developers needs to acknowledge and deal with.
> 
> Still I'm okay with a patch that extends the timeout by programming WCV, but
> it has to be commented as a hack specifically to support kexec because the
> timeout might be too short.  Then Wim can decide whether he supports such
> changes.
> 
I don't even understand how kexec-tools is involved in the first place.
kexec-tools sounds like user space, which should execute _after_ the kernel
and its modules are loaded (assuming modules are loaded from initramfs).
If kexec-tools can somehow ping the watchdog (presumably by writing into
the HW directly), I don't understand why it doesn't simply load the watchdog
driver instead and let the watchdog core handle the heartbeats.

I am really missing something here. How can kexec-tools do anything before
the kernel is loaded ?

Guenter


From thomas.hanson at linaro.org  Thu May  5 09:44:26 2016
From: thomas.hanson at linaro.org (Tom Hanson)
Date: Thu, 5 May 2016 10:44:26 -0600
Subject: [PATCH v2 16/54] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <572B7384.2050405@linaro.org>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-17-git-send-email-andre.przywara@arm.com>
 <572B7384.2050405@linaro.org>
Message-ID: <572B786A.7040705@linaro.org>

On 05/05/2016 10:23 AM, Tom Hanson wrote:
> On 04/28/2016 10:45 AM, Andre Przywara wrote:
>
> ...
>
>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>> index 4fb20fd..a656a12e5 100644
>> --- a/virt/kvm/arm/vgic/vgic.c
>> +++ b/virt/kvm/arm/vgic/vgic.c
>
> ...
>> +static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
>> +{
>
> ...
>
>> +        /* This interrupt looks like it has to be migrated. */
>> +
>> +        spin_unlock(&irq->irq_lock);
>> +        spin_unlock(&vgic_cpu->ap_list_lock);
>
> If using the suggested (but not provided) higher level function from patch 14 this could be:
>                  vgic_unlock_aplist_irq(, spinlock_t irq);

Oh, bother.  That should be:
             vgic_unlock_aplist_irq(vgic_cpu->ap_list_lock, irq->irq_lock);


From thomas.hanson at linaro.org  Thu May  5 09:48:49 2016
From: thomas.hanson at linaro.org (Tom Hanson)
Date: Thu, 5 May 2016 10:48:49 -0600
Subject: [PATCH v2 26/54] KVM: arm/arm64: vgic-new: Add ACTIVE registers
 handlers
In-Reply-To: <1461861973-26464-27-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-27-git-send-email-andre.przywara@arm.com>
Message-ID: <572B7971.1060702@linaro.org>

On 04/28/2016 10:45 AM, Andre Przywara wrote:

...

> +void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val)

...

> +		spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +		spin_lock(&irq->irq_lock);

If using the suggested higher level function from patch 14 this could be:
                 vgic_lock_aplist_irq(&vcpu->arch.vgic_cpu.ap_list_lock, &irq->irq_lock);

> +
> +		/*
> +		 * Recheck after dropping the IRQ lock to see if we should
> +		 * still care about queueing it.
> +		 */
> +		if (irq->active || irq->vcpu) {
> +			irq->active = true;
> +
> +			spin_unlock(&irq->irq_lock);
> +			spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
And this could be:
                         vgic_unlock_aplist_irq(&vcpu->arch.vgic_cpu.ap_list_lock, &irq->irq_lock);
> +
> +			continue;
> +		}
> +
> +		/* Did the target VCPU change while we had the lock dropped? */
> +		if (vcpu != irq->target_vcpu) {
> +			spin_unlock(&irq->irq_lock);
> +			spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
And this could be:
                          vgic_unlock_aplist_irq(&vcpu->arch.vgic_cpu.ap_list_lock, &irq->irq_lock);

> +
> +			goto retry;
> +		}
> +
> +		/* Now queue the IRQ to the VCPU's ap_list. */
> +		list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
> +		irq->vcpu = vcpu;
> +
> +		irq->active = true;
> +
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
And this could be:
                 vgic_unlock_aplist_irq(&vcpu->arch.vgic_cpu.ap_list_lock, &irq->irq_lock);

> +
> +		kvm_vcpu_kick(vcpu);
> +	}
> +}
> +


From liviu.dudau at arm.com  Thu May  5 09:52:33 2016
From: liviu.dudau at arm.com (liviu.dudau at arm.com)
Date: Thu, 5 May 2016 17:52:33 +0100
Subject: [PATCH 2/2] drm: hdlcd: Suspend/resume only active crtcs
In-Reply-To: <759fe8d3dde95091a9df83018051cba00f494e1e.1462464611.git.robin.murphy@arm.com>
References: <eeb2a5540f50f5a3dd7f87861be1e9117bc4ed65.1462464611.git.robin.murphy@arm.com>
 <759fe8d3dde95091a9df83018051cba00f494e1e.1462464611.git.robin.murphy@arm.com>
Message-ID: <20160505165233.GI28464@e106497-lin.cambridge.arm.com>

On Thu, May 05, 2016 at 05:13:38PM +0100, Robin Murphy wrote:
> The current PM ops simply unconditionally enable/disable the HDLCD,
> which proves problematic when there is no display plugged in - since
> without a crtc the hardware itself is still in an uninitialised state,
> coming out of suspend results in it being enabled without a valid
> framebuffer address, which typically results in it trying to scan out
> from bus address 0 and flooding the system with error interrupts.
> 
> Fix this by checking the crtc state on resume, and only enabling the
> hardware if it's actually supposed to be. For the sake of consistency,
> do the same on the suspend path as well, although there it's merely a
> case of skipping unnecessary work.
> 
> CC: Liviu Dudau <liviu.dudau at arm.com>

Acked-by: Liviu Dudau <liviu.dudau at arm.com>

Thanks for the patch, Robin!

Liviu

> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
>  drivers/gpu/drm/arm/hdlcd_crtc.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
> index fef1b04c2aab..bf6ff5e48adc 100644
> --- a/drivers/gpu/drm/arm/hdlcd_crtc.c
> +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
> @@ -296,12 +296,14 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
>  
>  void hdlcd_crtc_suspend(struct drm_crtc *crtc)
>  {
> -	hdlcd_crtc_disable(crtc);
> +	if (crtc->state->active)
> +		hdlcd_crtc_disable(crtc);
>  }
>  
>  void hdlcd_crtc_resume(struct drm_crtc *crtc)
>  {
> -	hdlcd_crtc_enable(crtc);
> +	if (crtc->state->active)
> +		hdlcd_crtc_enable(crtc);
>  }
>  
>  int hdlcd_setup_crtc(struct drm_device *drm)
> -- 
> 2.8.1.dirty
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ?\_(?)_/?


From thomas.hanson at linaro.org  Thu May  5 10:04:01 2016
From: thomas.hanson at linaro.org (Tom Hanson)
Date: Thu, 5 May 2016 11:04:01 -0600
Subject: [PATCH v2 18/54] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <1461861973-26464-19-git-send-email-andre.przywara@arm.com>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-19-git-send-email-andre.przywara@arm.com>
Message-ID: <572B7D01.50202@linaro.org>

On 04/28/2016 10:45 AM, Andre Przywara wrote:

...

> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> new file mode 100644
> index 0000000..461229b
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-v3.c

...

> +void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
> +{
> + struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
> + u32 model = vcpu->kvm->arch.vgic.vgic_model;
> + int lr;
> +
> + /* Assumes ap_list_lock held */

If truly required that ap_list_lock already be locked, then the code should enforce it. At least in dev mode. Maybe:
         DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->ap_list_lock));

...

> +/* Requires the irq to be locked already */
> +void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
> +{
> +	u32 model = vcpu->kvm->arch.vgic.vgic_model;
> +	u64 val = irq->intid;
> +

Similarly, if required then the code should enforce it.
         DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));

...



From daniel at ffwll.ch  Thu May  5 10:06:02 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Thu, 5 May 2016 19:06:02 +0200
Subject: [PATCH 2/2] drm: hdlcd: Suspend/resume only active crtcs
In-Reply-To: <759fe8d3dde95091a9df83018051cba00f494e1e.1462464611.git.robin.murphy@arm.com>
References: <eeb2a5540f50f5a3dd7f87861be1e9117bc4ed65.1462464611.git.robin.murphy@arm.com>
 <759fe8d3dde95091a9df83018051cba00f494e1e.1462464611.git.robin.murphy@arm.com>
Message-ID: <20160505170601.GP1286@phenom.ffwll.local>

On Thu, May 05, 2016 at 05:13:38PM +0100, Robin Murphy wrote:
> The current PM ops simply unconditionally enable/disable the HDLCD,
> which proves problematic when there is no display plugged in - since
> without a crtc the hardware itself is still in an uninitialised state,
> coming out of suspend results in it being enabled without a valid
> framebuffer address, which typically results in it trying to scan out
> from bus address 0 and flooding the system with error interrupts.
> 
> Fix this by checking the crtc state on resume, and only enabling the
> hardware if it's actually supposed to be. For the sake of consistency,
> do the same on the suspend path as well, although there it's merely a
> case of skipping unnecessary work.
> 
> CC: Liviu Dudau <liviu.dudau at arm.com>
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
>  drivers/gpu/drm/arm/hdlcd_crtc.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
> index fef1b04c2aab..bf6ff5e48adc 100644
> --- a/drivers/gpu/drm/arm/hdlcd_crtc.c
> +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
> @@ -296,12 +296,14 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
>  
>  void hdlcd_crtc_suspend(struct drm_crtc *crtc)
>  {
> -	hdlcd_crtc_disable(crtc);
> +	if (crtc->state->active)
> +		hdlcd_crtc_disable(crtc);
>  }
>  
>  void hdlcd_crtc_resume(struct drm_crtc *crtc)
>  {
> -	hdlcd_crtc_enable(crtc);
> +	if (crtc->state->active)
> +		hdlcd_crtc_enable(crtc);
>  }

If you use the atomic helpers to suspend/resume your entire display
pipeline these callbacks shouldn't even be needed at all. Tried just
removing them?
-Daniel

>  
>  int hdlcd_setup_crtc(struct drm_device *drm)
> -- 
> 2.8.1.dirty
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From briannorris at chromium.org  Thu May  5 10:07:52 2016
From: briannorris at chromium.org (Brian Norris)
Date: Thu, 5 May 2016 10:07:52 -0700
Subject: usb: dwc3: host: inherit dma configuration from parent dev
In-Reply-To: <1461612094-30939-1-git-send-email-grygorii.strashko@ti.com>
References: <1461612094-30939-1-git-send-email-grygorii.strashko@ti.com>
Message-ID: <20160505170752.GA118697@google.com>

On Mon, Apr 25, 2016 at 10:21:34PM +0300, Strashko, Grygorii wrote:
> Now not all DMA paremters configured properly for "xhci-hcd" platform
> device which is created manually. For example: dma_pfn_offset, dam_ops
> and iommu configuration will not corresponds "dwc3" devices
> configuration. As result, this will cause problems like wrong DMA
> addresses translation on platforms with LPAE enabled like Keystone 2.
> 
> When platform is using DT boot mode the DMA configuration will be
> parsed and applied from DT, so, to fix this issue, reuse
> of_dma_configure() API and retrieve DMA configuartion for "xhci-hcd"
> from DWC3 device node.
> 
> Cc: David Fisher <david.fisher1 at synopsys.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: "Thang Q. Nguyen" <tqnguyen at apm.com>
> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh at renesas.com>
> Signed-off-by: Grygorii Strashko <grygorii.strashko at ti.com>

Tested-by: Brian Norris <briannorris at chromium.org>

What's the status of this? I see that there was some divergent
discussion about the merits of a dma_inherit() API...

FWIW, I'll reiterate Grygorii's note that Felipe's alternative patch
does NOT resolve the problem with the creation of the xhci-hcd platform
device:

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

Brian

> ---
> drivers/usb/dwc3/host.c | 15 ++++++++++-----
>  1 file changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
> index c679f63..93c8ef9 100644
> --- a/drivers/usb/dwc3/host.c
> +++ b/drivers/usb/dwc3/host.c
> @@ -17,6 +17,7 @@
>  
>  #include <linux/platform_device.h>
>  #include <linux/usb/xhci_pdriver.h>
> +#include <linux/of_device.h>
>  
>  #include "core.h"
>  
> @@ -32,12 +33,7 @@ int dwc3_host_init(struct dwc3 *dwc)
>  		return -ENOMEM;
>  	}
>  
> -	dma_set_coherent_mask(&xhci->dev, dwc->dev->coherent_dma_mask);
> -
>  	xhci->dev.parent	= dwc->dev;
> -	xhci->dev.dma_mask	= dwc->dev->dma_mask;
> -	xhci->dev.dma_parms	= dwc->dev->dma_parms;
> -
>  	dwc->xhci = xhci;
>  
>  	ret = platform_device_add_resources(xhci, dwc->xhci_resources,
> @@ -62,6 +58,15 @@ int dwc3_host_init(struct dwc3 *dwc)
>  	phy_create_lookup(dwc->usb3_generic_phy, "usb3-phy",
>  			  dev_name(&xhci->dev));
>  
> +	if (IS_ENABLED(CONFIG_OF) && dwc->dev->of_node) {
> +		of_dma_configure(&xhci->dev, dwc->dev->of_node);
> +	} else {
> +		dma_set_coherent_mask(&xhci->dev, dwc->dev->coherent_dma_mask);
> +
> +		xhci->dev.dma_mask	= dwc->dev->dma_mask;
> +		xhci->dev.dma_parms	= dwc->dev->dma_parms;
> +	}
> +
>  	ret = platform_device_add(xhci);
>  	if (ret) {
>  		dev_err(dwc->dev, "failed to register xHCI device\n");


From tony at atomide.com  Thu May  5 10:11:19 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 5 May 2016 10:11:19 -0700
Subject: [PATCH 0/2] Fix ir-rx51 by using PWM pdata
In-Reply-To: <5724F0CB.6060807@gmail.com>
References: <1461714709-10455-1-git-send-email-tony@atomide.com>
 <57227E63.4040907@gmail.com> <20160428212748.GI5995@atomide.com>
 <5724F0CB.6060807@gmail.com>
Message-ID: <20160505171119.GZ5995@atomide.com>

* Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com> [160430 10:53]:
> Hi,
> 
> On 29.04.2016 00:27, Tony Lindgren wrote:
> >* Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com> [160428 14:21]:
> >>
> >>I didn't test legacy boot, as I don't really see any value of doing it now
> >>the end of the legacy boot is near, the driver does not function correctly,
> >>however the patchset at least allows for the driver to be build and we have
> >>something to improve on. And I am going to send a patch that fixes the
> >>problem with omap_dm_timer_request_specific(). So, for both patches, you may
> >>add:
> >>
> >>Tested-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
> >
> >OK thanks.
> >
> >Mauro, do the driver changes look OK to you?
> >
> >If so, I could queue the driver too for v4.7 because of the
> >dependency with your ack. Or I can provide you an immutable
> >branch with just the pdata changes against v4.6-rc1 if you
> >prefer that.
> >

Mauro, I've applied the pdata patch only into my omap-for-v4.7/legacy branch.
Feel free to merge immutable commit against v4.6-rc1 which is 8453c5cafd32
("ARM: OMAP2+: Add more functions to pwm pdata for ir-rx51") to your tree
also for v4.7 if you decide to apply the ir-rx51 driver changes. Else we need
to wait for v4.7-rc1 :)

> In the meanwhile I was able to make the driver functional (on top of the
> $subject series) - for that purpose I had to fix dmtimer.c - it turns out
> that PM runtime get()/put() is called in almost every function exported by
> dmtimer, which in turn slows down IR transmission to 4-5s instead of 0.5s. I
> also replaced GPT9 dmtimer with PWM framework API (pwm-omap-dmtimer needs a
> patch) and implemented some DT support.
> 
> Now, how shall I proceed with those - wait for the $subject series to be
> accepted or post the patches now?

Best to do incremental patches on what was posted to avoid confusion.

> Tony, I was unable to find the tree on kernel.org your patches are in. Which
> tree to use to base my patches on?

The pdata changes are in Linux next with omap-for-v4.7/legacy, the driver
changes I have not committed into any upstream going tree. Seems like
Mauro can take it after merging in commit 8453c5cafd32.

Regards,

Tony


From liviu.dudau at arm.com  Thu May  5 10:11:23 2016
From: liviu.dudau at arm.com (liviu.dudau at arm.com)
Date: Thu, 5 May 2016 18:11:23 +0100
Subject: [PATCH 2/2] drm: hdlcd: Suspend/resume only active crtcs
In-Reply-To: <20160505170601.GP1286@phenom.ffwll.local>
References: <eeb2a5540f50f5a3dd7f87861be1e9117bc4ed65.1462464611.git.robin.murphy@arm.com>
 <759fe8d3dde95091a9df83018051cba00f494e1e.1462464611.git.robin.murphy@arm.com>
 <20160505170601.GP1286@phenom.ffwll.local>
Message-ID: <20160505171123.GK28464@e106497-lin.cambridge.arm.com>

On Thu, May 05, 2016 at 07:06:02PM +0200, Daniel Vetter wrote:
> On Thu, May 05, 2016 at 05:13:38PM +0100, Robin Murphy wrote:
> > The current PM ops simply unconditionally enable/disable the HDLCD,
> > which proves problematic when there is no display plugged in - since
> > without a crtc the hardware itself is still in an uninitialised state,
> > coming out of suspend results in it being enabled without a valid
> > framebuffer address, which typically results in it trying to scan out
> > from bus address 0 and flooding the system with error interrupts.
> > 
> > Fix this by checking the crtc state on resume, and only enabling the
> > hardware if it's actually supposed to be. For the sake of consistency,
> > do the same on the suspend path as well, although there it's merely a
> > case of skipping unnecessary work.
> > 
> > CC: Liviu Dudau <liviu.dudau at arm.com>
> > Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> > ---
> >  drivers/gpu/drm/arm/hdlcd_crtc.c | 6 ++++--
> >  1 file changed, 4 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
> > index fef1b04c2aab..bf6ff5e48adc 100644
> > --- a/drivers/gpu/drm/arm/hdlcd_crtc.c
> > +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
> > @@ -296,12 +296,14 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
> >  
> >  void hdlcd_crtc_suspend(struct drm_crtc *crtc)
> >  {
> > -	hdlcd_crtc_disable(crtc);
> > +	if (crtc->state->active)
> > +		hdlcd_crtc_disable(crtc);
> >  }
> >  
> >  void hdlcd_crtc_resume(struct drm_crtc *crtc)
> >  {
> > -	hdlcd_crtc_enable(crtc);
> > +	if (crtc->state->active)
> > +		hdlcd_crtc_enable(crtc);
> >  }
> 
> If you use the atomic helpers to suspend/resume your entire display
> pipeline these callbacks shouldn't even be needed at all. Tried just
> removing them?

Yes, I need to cleanup the PM code in HDLCD.

Thanks,
Liviu


> -Daniel
> 
> >  
> >  int hdlcd_setup_crtc(struct drm_device *drm)
> > -- 
> > 2.8.1.dirty
> > 
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ?\_(?)_/?


From andy.gross at linaro.org  Thu May  5 10:22:19 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 5 May 2016 12:22:19 -0500
Subject: [PATCH 2/2] drivers: i2c: qup: Fix error handling
In-Reply-To: <1462166637-16778-3-git-send-email-sricharan@codeaurora.org>
References: <1462166637-16778-1-git-send-email-sricharan@codeaurora.org>
 <1462166637-16778-3-git-send-email-sricharan@codeaurora.org>
Message-ID: <20160505172219.GB6533@hector.attlocal.net>

On Mon, May 02, 2016 at 10:53:57AM +0530, Sricharan R wrote:
> Among the bus errors reported from the QUP_MASTER_STATUS register
> only NACK is considered and transfer gets suspended, while
> other errors are ignored. Correct this and suspend the transfer
> for other errors as well. This avoids unnessecary 'timeouts' which
> happens when waiting for events that would never happen when there
> is already an error condition on the bus.
> 
> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> ---
>  drivers/i2c/busses/i2c-qup.c | 34 +++++++++++++++++++++++++---------
>  1 file changed, 25 insertions(+), 9 deletions(-)

Reviewed-by: Andy Gross <andy.gross at linaro.org>

<snip>

> @@ -1227,6 +1240,9 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
>  	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
>  	int ret, len, idx = 0, use_dma = 0;
>  
> +	qup->bus_err = 0;
> +	qup->qup_err = 0;
> +

What about the initial setting of these?  Does this need to be removed from the
main xfer function?

>  	ret = pm_runtime_get_sync(qup->dev);
>  	if (ret < 0)
>  		goto out;


From catalin.marinas at arm.com  Thu May  5 10:25:52 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 5 May 2016 18:25:52 +0100
Subject: [PATCH v2 3/8] arm64: add io{read,write}64be accessors
In-Reply-To: <1462462564-27731-1-git-send-email-horia.geanta@nxp.com>
References: <1462462435-27403-1-git-send-email-horia.geanta@nxp.com>
 <1462462564-27731-1-git-send-email-horia.geanta@nxp.com>
Message-ID: <20160505172551.GG3703@e104818-lin.cambridge.arm.com>

On Thu, May 05, 2016 at 06:36:04PM +0300, Horia Geant? wrote:
> This will allow device drivers to consistently use io{read,write}XXbe
> also for 64-bit accesses.
> 
> Signed-off-by: Alex Porosanu <alexandru.porosanu at nxp.com>
> Signed-off-by: Horia Geant? <horia.geanta at nxp.com>

Acked-by: Catalin Marinas <catalin.marinas at arm.com>


From marc.zyngier at arm.com  Thu May  5 10:33:05 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 5 May 2016 18:33:05 +0100
Subject: [PATCH] kvm: arm64: Enable hardware updates of the Access Flag
 for Stage 2 page tables
In-Reply-To: <1460566657-30221-1-git-send-email-catalin.marinas@arm.com>
References: <1460566657-30221-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <572B83D1.10600@arm.com>

On 13/04/16 17:57, Catalin Marinas wrote:
> The ARMv8.1 architecture extensions introduce support for hardware
> updates of the access and dirty information in page table entries. With
> VTCR_EL2.HA enabled (bit 21), when the CPU accesses an IPA with the
> PTE_AF bit cleared in the stage 2 page table, instead of raising an
> Access Flag fault to EL2 the CPU sets the actual page table entry bit
> (10). To ensure that kernel modifications to the page table do not
> inadvertently revert a bit set by hardware updates, certain Stage 2
> software pte/pmd operations must be performed atomically.
> 
> The main user of the AF bit is the kvm_age_hva() mechanism. The
> kvm_age_hva_handler() function performs a "test and clear young" action
> on the pte/pmd. This needs to be atomic in respect of automatic hardware
> updates of the AF bit. Since the AF bit is in the same position for both
> Stage 1 and Stage 2, the patch reuses the existing
> ptep_test_and_clear_young() functionality if
> __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG is defined. Otherwise, the
> existing pte_young/pte_mkold mechanism is preserved.
> 
> The kvm_set_s2pte_readonly() (and the corresponding pmd equivalent) have
> to perform atomic modifications in order to avoid a race with updates of
> the AF bit. The arm64 implementation has been re-written using
> exclusives.
> 
> Currently, kvm_set_s2pte_writable() (and pmd equivalent) take a pointer
> argument and modify the pte/pmd in place. However, these functions are
> only used on local variables rather than actual page table entries, so
> it makes more sense to follow the pte_mkwrite() approach for stage 1
> attributes. The change to kvm_s2pte_mkwrite() makes it clear that these
> functions do not modify the actual page table entries.
> 
> The (pte|pmd)_mkyoung() uses on Stage 2 entries (setting the AF bit
> explicitly) do not need to be modified since hardware updates of the
> dirty status are not supported by KVM, so there is no possibility of
> losing such information.
> 
> Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Christoffer Dall <christoffer.dall at linaro.org>
> Cc: Marc Zyngier <marc.zyngier at arm.com>
> Cc: Paolo Bonzini <pbonzini at redhat.com>

Acked-by: Marc Zyngier <marc.zyngier at arm.com>

Christoffer: assuming you're happy with that patch, could you queue it
for 4.7?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From andy.gross at linaro.org  Thu May  5 10:33:37 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 5 May 2016 12:33:37 -0500
Subject: [PATCH 1/2] drivers: i2c: qup: Fix broken dma when
 CONFIG_DEBUG_SG is enabled
In-Reply-To: <1462166637-16778-2-git-send-email-sricharan@codeaurora.org>
References: <1462166637-16778-1-git-send-email-sricharan@codeaurora.org>
 <1462166637-16778-2-git-send-email-sricharan@codeaurora.org>
Message-ID: <20160505173337.GC6533@hector.attlocal.net>

On Mon, May 02, 2016 at 10:53:56AM +0530, Sricharan R wrote:
> With CONFIG_DEBUG_SG is enabled and when dma mode is used, below dump is seen,
> 
> ------------[ cut here ]------------
> kernel BUG at include/linux/scatterlist.h:140!
> Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
> Modules linked in:
> CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.0-00459-g9f087b9-dirty #7
> Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
> task: ffffffc036868000 ti: ffffffc036870000 task.ti: ffffffc036870000
> PC is at qup_sg_set_buf.isra.13+0x138/0x154
> LR is at qup_sg_set_buf.isra.13+0x50/0x154
> pc : [<ffffffc0005a0ed8>] lr : [<ffffffc0005a0df0>] pstate: 60000145
> sp : ffffffc0368735c0
> x29: ffffffc0368735c0 x28: ffffffc036873752
> x27: ffffffc035233018 x26: ffffffc000c4e000
> x25: 0000000000000000 x24: 0000000000000004
> x23: 0000000000000000 x22: ffffffc035233668
> x21: ffffff80004e3000 x20: ffffffc0352e0018
> x19: 0000004000000000 x18: 0000000000000028
> x17: 0000000000000004 x16: ffffffc0017a39c8
> x15: 0000000000001cdf x14: ffffffc0019929d8
> x13: ffffffc0352e0018 x12: 0000000000000000
> x11: 0000000000000001 x10: 0000000000000001
> x9 : ffffffc0012b2d70 x8 : ffffff80004e3000
> x7 : 0000000000000018 x6 : 0000000030000000
> x5 : ffffffc00199f018 x4 : ffffffc035233018
> x3 : 0000000000000004 x2 : 00000000c0000000
> x1 : 0000000000000003 x0 : 0000000000000000
> 
> Process swapper/0 (pid: 1, stack limit = 0xffffffc036870020)
> Stack: (0xffffffc0368735c0 to 0xffffffc036874000)
> 
> Change allocation of sg buffers from dma_coherent memory to kzalloc
> to fix the issue.
> 
> Signed-off-by: Sricharan R <sricharan at codeaurora.org>

Looks fine.

Reviewed-by: Andy Gross <andy.gross at linaro.org>


From k.kozlowski at samsung.com  Thu May  5 10:37:03 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 5 May 2016 19:37:03 +0200
Subject: [RFC v2 10/13] usb: hub: Power sequence the ports on activation
In-Reply-To: <Pine.LNX.4.44L0.1605051007040.2008-100000@iolanthe.rowland.org>
References: <1462451666-17945-11-git-send-email-k.kozlowski@samsung.com>
 <Pine.LNX.4.44L0.1605051007040.2008-100000@iolanthe.rowland.org>
Message-ID: <20160505173703.GA3034@kozik-lap>

On Thu, May 05, 2016 at 10:09:47AM -0400, Alan Stern wrote:
> On Thu, 5 May 2016, Krzysztof Kozlowski wrote:
> 
> > The autodetection of attached USB device might not work on certain
> > boards where the power is delivered externally. These devices also might
> > require a hard reset. Use pwrseq for that in USB hub.
> > 
> > Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> > ---
> >  drivers/usb/core/hub.c | 11 +++++++++++
> >  1 file changed, 11 insertions(+)
> > 
> > diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> > index 1c82fcc448f5..0fddaacc62bf 100644
> > --- a/drivers/usb/core/hub.c
> > +++ b/drivers/usb/core/hub.c
> > @@ -26,6 +26,7 @@
> >  #include <linux/mutex.h>
> >  #include <linux/random.h>
> >  #include <linux/pm_qos.h>
> > +#include <linux/pwrseq.h>
> >  
> >  #include <asm/uaccess.h>
> >  #include <asm/byteorder.h>
> > @@ -1661,7 +1662,17 @@ static int hub_configure(struct usb_hub *hub,
> >  
> >  	usb_hub_adjust_deviceremovable(hdev, hub->descriptor);
> >  
> > +	/* FIXME: When do the pre-power-on? */
> 
> It's hard to answer this without knowing what pre-power-on involves.

In my particular case, I want to achieve a full reset through regulator (off
and on) because the bootloader left it in initialized state. I assume
that if bootloader did not configure the device, the reset won't be
harmful.

In a MMC case, this pre-power-on on is setting the 'reset' GPIO (thus
triggering the reset) and post-power-on is clearing the 'reset'.

> Why not create a pwrseq_power_on() routine that does pre_power_on 
> followed by post_power_on?

For my purpose it seems sensible.

> 
> > +	/*
> > +	for (i = 0; i < maxchild; i++)
> > +		pwrseq_pre_power_on(hub->ports[i]->pwrseq);
> > +	*/
> > +
> > +	for (i = 0; i < maxchild; i++)
> > +		pwrseq_post_power_on(hub->ports[i]->pwrseq);
> 
> This is patch 10/13.  hub->ports[i]->pwrseq doesn't get added until 
> 11/13.  Obviously you never tried compiling each patch in the series.

Ahh yes, I forgot to reorder them. Thanks for spotting this.

> 
> > +
> >  	hub_activate(hub, HUB_INIT);
> > +
> 
> Unnecessary blank line added.

Thanks for feedback,
Krzysztof



From plaes at plaes.org  Thu May  5 10:39:04 2016
From: plaes at plaes.org (Priit Laes)
Date: Thu,  5 May 2016 20:39:04 +0300
Subject: [PATCH v2] ARM: sun7i: dt: Add pll3 and pll7 clocks
Message-ID: <1462469944-27915-1-git-send-email-plaes@plaes.org>

Enable pll3 and pll7 clocks that are needed by display clocks.

Signed-off-by: Priit Laes <plaes at plaes.org>
---
v2:
 - Fix typos in clocks property (spotted by Alexander Syring)
 - Fix indentation (spotted by Maxime Ripard)

 arch/arm/boot/dts/sun7i-a20.dtsi | 41 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index bf5d056..febdf4c 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -187,6 +187,15 @@
 			clock-output-names = "osc24M";
 		};
 
+		osc3M: osc3M_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clock-div = <8>;
+			clock-mult = <1>;
+			clocks = <&osc24M>;
+			clock-output-names = "osc3M";
+		};
+
 		osc32k: clk at 0 {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -211,6 +220,22 @@
 					     "pll2-4x", "pll2-8x";
 		};
 
+		pll3: clk at 01c20010 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-pll3-clk";
+			reg = <0x01c20010 0x4>;
+			clocks = <&osc3M>;
+			clock-output-names = "pll3";
+		};
+
+		pll3x2: pll3x2_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clock-div = <1>;
+			clock-mult = <2>;
+			clock-output-names = "pll3-2x";
+		};
+
 		pll4: clk at 01c20018 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun7i-a20-pll4-clk";
@@ -236,6 +261,22 @@
 					     "pll6_div_4";
 		};
 
+		pll7: clk at 01c20030 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-pll3-clk";
+			reg = <0x01c20030 0x4>;
+			clocks = <&osc3M>;
+			clock-output-names = "pll7";
+		};
+
+		pll7x2: pll7x2_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clock-div = <1>;
+			clock-mult = <2>;
+			clock-output-names = "pll7-2x";
+		};
+
 		pll8: clk at 01c20040 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun7i-a20-pll4-clk";
-- 
2.8.2



From Tirumalesh.Chalamarla at caviumnetworks.com  Thu May  5 10:44:24 2016
From: Tirumalesh.Chalamarla at caviumnetworks.com (Chalamarla, Tirumalesh)
Date: Thu, 5 May 2016 17:44:24 +0000
Subject: [PATCH v9 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part
 2/3: msi changes
In-Reply-To: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
Message-ID: <9C17BA6B-7304-47CA-A287-77FB41D96AD3@caviumnetworks.com>

Hi Eric,

Does this series supports gicv3-its emulation?
Do we have a tree with all the dependent patches





Thanks,
Tirumalesh. 
On 5/4/16, 8:18 AM, "linux-arm-kernel on behalf of Eric Auger" <linux-arm-kernel-bounces at lists.infradead.org on behalf of eric.auger at linaro.org> wrote:

>This series implements the MSI address mapping/unmapping in the MSI layer.
>IOMMU binding happens on pci_enable_msi since this function can sleep and
>return errors. On msi_domain_set_affinity, msi_domain_(de)activate, which
>are not allowed to sleep, we simply look for the already existing binding.
>
>A new MSI domain info flag value is introduced to report whether the msi
>domain implements IRQ remapping. GIC v3 ITS is the first MSI controller
>advertising it. This flag value will be used by VFIO subsystem to
>determine whether MSI forwarding is safe.
>
>More details & context can be found at:
>http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/
>
>Best Regards
>
>Eric
>
>Applies on top of PART 1/3. Also depends on
>[PATCH 1/3] iommu: Add MMIO mapping type,
>http://comments.gmane.org/gmane.linux.kernel.iommu/12869
>
>Git: complete series available at
>https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc6-pcie-passthrough-v9-msi-v9
>
>This branch contains all parts in v9.
>
>History:
>
>v8 -> v9:
>- use a union in irq_chip_msi_doorbell_info + boolean telling whether the
>  doorbell is percpu
>- decouple irq_data parsing from the actual mapping/unmapping in
>  msi_handle_doorbell_mappings
>- fix misc style issues
>
>v7 -> v8:
>take into account Marc's comments:
>- use iommu_msi_msg_pa_to_va with new proto
>- change in irq_chip_msi_doorbell_info struct definition:
>  prot and size became shared between all doorbells and phys_addr_t __percpu
>- cleanups in v2m irqchip
>- eventually did not touch MSI_FLAG_IRQ_REMAPPING naming
>- On msi_handle_doorbell_mappings, stop on the first irqchip where doorbells
>  can be found
>- fix resource deallocation on mapping failure in msi_domain_alloc_irqs
>
>v6 -> v7:
>- do alloc/map handling on pci_enable_msi and search on msi_(de)domain_activate
>- add msi_doorbell_info callback in irq-chip to retrieve the characteristics
>  of doorbells
>
>RFC v5 -> patch v6:
>- split to ease the review process
>- rebase on default iommu domain code (irq_data_to_msi_mapping_domain
>  checks IOMMU_DOMAIN_DMA type)
>- fix unmap sequence on msi_domain_set_affinity (reported by Marc):
>  unmap the previous doorbell when the new one has been mapped & written to
>  the device, ie. irq_chip_write_msi_msg.
>- "msi: msi_compose wrapper removed" following change above
>- add size parameter to iommu_get_reserved_iova API following Marc's request
>
>RFC v4 -> RFC v5:
>- take into account Thomas' comments on MSI related patches
>  - split "msi: IOMMU map the doorbell address when needed"
>  - increase readability and add comments
>  - fix style issues
> - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
> - platform ITS now advertises IOMMU_CAP_INTR_REMAP
> - fix compilation issue with CONFIG_IOMMU API unset
> - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING
>
>RFC v3 -> v4:
>- Move doorbell mapping/unmapping in msi.c
>- fix ref count issue on set_affinity: in case of a change in the address
>  the previous address is decremented
>- doorbell map/unmap now is done on msi composition. Should allow the use
>  case for platform MSI controllers
>- create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
>  to reserved IOVA management (looking like dma-iommu glue)
>- series reordering to ease the review:
>  - first part is related to IOMMU
>  - second related to MSI sub-system
>  - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
>- expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
>  [this partially addresses Marc's comments on iommu_get/put_single_reserved
>   size/alignment problematic - which I did not ignore - but I don't know
>   how much I can do at the moment]
>
>RFC v2 -> RFC v3:
>- should fix wrong handling of some CONFIG combinations:
>  CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
>- fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)
>
>PATCH v1 -> RFC v2:
>- reverted to RFC since it looks more reasonable ;-) the code is split
>  between VFIO, IOMMU, MSI controller and I am not sure I did the right
>  choices. Also API need to be further discussed.
>- iova API usage in arm-smmu.c.
>- MSI controller natively programs the MSI addr with either the PA or IOVA.
>  This is not done anymore in vfio-pci driver as suggested by Alex.
>- check irq remapping capability of the group
>
>RFC v1 [2] -> PATCH v1:
>- use the existing dma map/unmap ioctl interface with a flag to register a
>  reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
>- a single reserved IOVA contiguous region now is allowed
>- use of an RB tree indexed by PA to store allocated reserved slots
>- use of a vfio_domain iova_domain to manage iova allocation within the
>  window provided by the userspace
>- vfio alloc_map/unmap_free take a vfio_group handle
>- vfio_group handle is cached in vfio_pci_device
>- add ref counting to bindings
>- user modality enabled at the end of the series
>
>
>Eric Auger (8):
>  genirq/msi: Add a new MSI_FLAG_IRQ_REMAPPING flag
>  irqchip/gic-v3-its: ITS advertises MSI_FLAG_IRQ_REMAPPING
>  genirq/msi: export msi_get_domain_info
>  genirq/msi: msi_compose wrapper
>  genirq/irq: introduce msi_doorbell_info
>  irqchip/gicv2m: implement msi_doorbell_info callback
>  genirq/msi: map/unmap the MSI doorbells on msi_domain_alloc/free_irqs
>  genirq/msi: use the MSI doorbell's IOVA when requested
>
> drivers/irqchip/irq-gic-v2m.c                 |  16 +++
> drivers/irqchip/irq-gic-v3-its-pci-msi.c      |   3 +-
> drivers/irqchip/irq-gic-v3-its-platform-msi.c |   3 +-
> include/linux/irq.h                           |  15 ++-
> include/linux/msi.h                           |   2 +
> kernel/irq/msi.c                              | 136 +++++++++++++++++++++++---
> 6 files changed, 161 insertions(+), 14 deletions(-)
>
>-- 
>1.9.1
>
>
>_______________________________________________
>linux-arm-kernel mailing list
>linux-arm-kernel at lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

From jim2101024 at gmail.com  Thu May  5 10:48:53 2016
From: jim2101024 at gmail.com (Jim Quinlan)
Date: Thu, 5 May 2016 13:48:53 -0400
Subject: [PATCH 2/2] pci: host: Add Broadcom STB PCIE RC controller
In-Reply-To: <572A4F31.8010802@gmail.com>
References: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>
 <1462238749-19715-3-git-send-email-f.fainelli@gmail.com>
 <2339405.90vXV1p6zU@wuerfel> <572A4F31.8010802@gmail.com>
Message-ID: <CANCKTBuNFQFLsab2WS+BRGUOuUOTLYuoaWNuM5T9HPGihvwYCg@mail.gmail.com>

On Wed, May 4, 2016 at 3:36 PM, Florian Fainelli <f.fainelli at gmail.com> wrote:
> On 03/05/16 02:57, Arnd Bergmann wrote:
>>> +static const struct pcie_cfg_data generic_cfg = {
>>> +    .offsets        = pcie_offsets,
>>> +    .type           = GENERIC,
>>> +};
>>
>> The way you access the config space here seems very indirect. I'd
>> suggest instead writing two sets of pci_ops, with hardcoded registers
>> offsets in them, and a function pointer to access the RGR1_SW_INIT_1
>> register.
>
> How about introducing helper functions but keeping the same set of
> read/write pci_ops instead, would that seem more acceptable? I agree
> that the macros are not the friendliest thing.
>
>>
>>> +struct brcm_msi {
>>> +    struct irq_domain *domain;
>>> +    struct irq_chip irq_chip;
>>> +    struct msi_controller chip;
>>> +    struct mutex lock;
>>> +    int irq;
>>> +    /* intr_base is the base pointer for interrupt status/set/clr regs */
>>> +    void __iomem *intr_base;
>>> +    /* intr_legacy_mask indicates how many bits are MSI interrupts */
>>> +    u32 intr_legacy_mask;
>>> +    /* intr_legacy_offset indicates bit position of MSI_01 */
>>> +    u32 intr_legacy_offset;
>>> +    /* used indicates which MSI interrupts have been alloc'd */
>>> +    unsigned long used;
>>> +    /* working indicates that on boot we have brought up MSI */
>>> +    bool working;
>>> +};
>>
>> I'd move the MSI controller stuff into a separate file, and add a way to
>> override it. It's likely that at some point the same PCIe implementation
>> will be used with a modern GICv3 or GICv2m, so you should be able to
>> look up the msi controller from a property.
>
> Good point, let's do that, though all controllers actually do support
> MSI, so I wonder.
>
>>
>>> +struct brcm_window {
>>> +    u64 size;
>>> +    u64 cpu_addr;
>>> +    struct resource pcie_iomem_res;
>>> +};
>>
>> This appears to duplicate things we already have. Try to get rid of
>> the structure and use what is already there.
>
> OK, the resource is probably good enough here.
>
>>
>>> +struct brcm_dev_pwr_supply {
>>> +    struct list_head node;
>>> +    char name[32];
>>> +    struct regulator *regulator;
>>> +};
>>
>> Same here: Just get all the regulators you know about by name
>> and put them into the main structure.
>
> OK, I will drop the regulator support for now, see below for a more
> elaborate answer.
>
>>
>>> +/* Internal Bus Controller Information.*/
>>> +struct brcm_pcie {
>>> +    struct list_head        list;
>>> +    void __iomem            *base;
>>> +    char                    name[8];
>>> +    bool                    suspended;
>>> +    struct clk              *clk;
>>> +    struct device_node      *dn;
>>> +    int                     pcie_irq[4];
>>> +    int                     irq;
>>> +    int                     num_out_wins;
>>> +    bool                    ssc;
>>> +    int                     gen;
>>> +    int                     scb_size_vals[BRCM_MAX_SCB];
>>> +    struct brcm_window      out_wins[BRCM_NUM_PCI_OUT_WINS];
>>> +    struct pci_bus          *bus;
>>> +    struct device           *dev;
>>> +    struct list_head        resource;
>>> +    struct list_head        pwr_supplies;
>>> +    struct brcm_msi         msi;
>>> +    unsigned int            rev;
>>> +    unsigned int            num;
>>> +    bool                    bridge_setup_done;
>>> +    const int               *reg_offsets;
>>> +    enum pcie_type          type;
>>> +};
>>> +
>>> +static int brcm_num_pci_controllers;
>>> +static int num_memc;
>>
>> Remove the globals.
>
> OK.
>
>>
>>> +
>>> +/*
>>> + * MIPS endianness is configured by boot strap, which also reverses all
>>> + * bus endianness (i.e., big-endian CPU + big endian bus ==> native
>>> + * endian I/O).
>>> + *
>>> + * Other architectures (e.g., ARM) either do not support big endian, or
>>> + * else leave I/O in little endian mode.
>>> + */
>>> +static inline u32 bpcie_readl(void __iomem *base)
>>> +{
>>> +    if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
>>> +            return __raw_readl(base);
>>> +    else
>>> +            return readl_relaxed(base);
>>> +}
>>
>> I think it would make more sense to only make this depend on the
>> architecture, not on endianess: If the __raw_ version works on MIPS
>> in big-endian mode, you should be able to also use it in little-endian
>> mode.
>>
>> For the default (ARM) version, please use the non-relaxed accessor
>> by default, unless you can show a difference in performance and prove
>> that you don't need the implied barriers.
>
> Our busing makes it so that the __raw_readl() (or _relaxed) I/O access
> is going to have the same guarantees as if we were adding a barrier,
> that is, writes are not going to be re-ordered with each other by the
> bus, nor the CPU (since it maps the space as device memory), and on
> MIPS, well, it's all through unmapped, uncached space, but I can
> definitively switch that for readl(), should not make a huge performance
> difference, if noticeable.
>
>>
>>> +/* negative return value indicates error */
>>> +static int mdio_read(void __iomem *base, u8 phyad, u8 regad)
>>> +{
>>> +    u32 data = ((phyad & 0xf) << 16)
>>> +            | (regad & 0x1f)
>>> +            | 0x100000;
>>> +
>>> +    bpcie_writel(data, base + PCIE_RC_DL_MDIO_ADDR);
>>> +    bpcie_readl(base + PCIE_RC_DL_MDIO_ADDR);
>>> +
>>> +    data = bpcie_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
>>> +    if (!(data & 0x80000000)) {
>>> +            mdelay(1);
>>
>> Try to restructure the code so this is never called with spinlocks
>> held and then replace the mdelay() with an msleep().
>
> I cannot really think of a reason why we did not use msleep() all along,
> so thanks for spotting that.

This is an artifact of when we used to do our PCIe suspend/resume via
syscore calls and we could not sleep.

>
>>> +
>>> +    /* set up 4GB PCIE->SCB memory window on BAR2 */
>>> +    bpcie_writel(0x00000011, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
>>> +    bpcie_writel(0x00000000, base + PCIE_MISC_RC_BAR2_CONFIG_HI);
>>
>> Where does this window come from? It's not in the DT as far as I can see.
>
> This is an architectural maximum value which is baked into the PCIE Root
> Complex hardware, on all generations that this driver supports. We
> configure the largest address match rang size here, just to be safe,
> AFAICT there is no point in looking at the inbound or outbound window
> sizes to re-program that differently.

Florian, I have a subsequent commit that passes the inbound
information in the device tree; it's designed for when we have to map
the multiple inbound regions differently using dma-ranges.  I will
make it available to you offline.

>
>
>>> +    INIT_LIST_HEAD(&pcie->pwr_supplies);
>>> +    INIT_LIST_HEAD(&pcie->resource);
>>> +
>>> +    supplies = of_property_count_strings(dn, "supply-names");
>>> +    if (supplies <= 0)
>>> +            supplies = 0;
>>> +
>>> +    for (i = 0; i < supplies; i++) {
>>> +            if (of_property_read_string_index(dn, "supply-names", i,
>>> +                                              &name))
>>> +                    continue;
>>> +            supply = devm_kzalloc(&pdev->dev, sizeof(*supply), GFP_KERNEL);
>>> +            if (!supply)
>>> +                    return -ENOMEM;
>>> +
>>> +            strncpy(supply->name, name, sizeof(supply->name));
>>> +            supply->name[sizeof(supply->name) - 1] = '\0';
>>> +            supply->regulator = devm_regulator_get(&pdev->dev, name);
>>> +            if (IS_ERR(supply->regulator)) {
>>> +                    dev_err(&pdev->dev, "Unable to get %s supply, err=%d\n",
>>> +                            name, (int)PTR_ERR(supply->regulator));
>>> +                    continue;
>>> +            }
>>> +
>>> +            if (regulator_enable(supply->regulator))
>>> +                    dev_err(&pdev->dev, "Unable to enable %s supply.\n",
>>> +                            name);
>>> +            list_add_tail(&supply->node, &pcie->pwr_supplies);
>>> +    }
>>
>> Don't parse the regulator properties yourself here, use the proper APIs.
>
> I will probably drop this for now, and  add it later, there are only a
> handful of boards which requires this, and ultimately, I think we should
> be seaking for a more generic solutions, we can't be the only ones doing
> that.
>
>>
>>> +    /* 'num_memc' will be set only by the first controller, and all
>>> +     * other controllers will use the value set by the first.
>>> +     */
>>> +    if (num_memc == 0)
>>> +            for_each_compatible_node(mdn, NULL, "brcm,brcmstb-memc")
>>> +                    if (of_device_is_available(mdn))
>>> +                            num_memc++;
>>
>> Why is this?
>
> This is so we do not end-up programming the PCIe RC which is agnostic of
> the number of

I believe this code is still around for folks passing us a device tree
with lacking information.  It should be removed.

>
>>
>>> +    resource_list_for_each_entry(win, &res) {
>>> +            struct brcm_window *w = &pcie->out_wins[i];
>>> +
>>> +            r = win->res;
>>> +
>>> +            if (!r->flags)
>>> +                    continue;
>>> +
>>> +            switch (resource_type(r)) {
>>> +            case IORESOURCE_MEM:
>>> +                    w->cpu_addr = r->start;
>>> +                    w->size = resource_size(r);
>>> +                    w->pcie_iomem_res.name  = "External PCIe MEM";
>>> +                    w->pcie_iomem_res.flags = r->flags;
>>> +                    w->pcie_iomem_res.start = r->start;
>>> +                    w->pcie_iomem_res.end   = r->end;
>>> +                    pcie->num_out_wins++;
>>> +                    i++;
>>> +                    /* Request memory region resources. */
>>> +                    ret = devm_request_resource(&pdev->dev,
>>> +                                                &iomem_resource,
>>> +                                                &w->pcie_iomem_res);
>>> +                    if (ret) {
>>> +                            dev_err(&pdev->dev,
>>> +                                    "request PCIe memory resource failed\n");
>>> +                            goto out_err_clk;
>>> +                    }
>>> +                    break;
>>> +
>>> +            default:
>>> +                    continue;
>>> +            }
>>> +    }
>>
>> What about IORESOURCE_IO?
>
> We do not support I/O space on this controller AFAIR. Our downstream
> driver does insert a fake bogus I/O range, but I cannot really remember
> why that was needed now, Jim do you remember?
> --
> Florian

We added a bogus IO region because there was no other way to proceed
w/o getting an error.  Or should I say, I knew of no other way to
proceed...

Thanks,
Jim Quinlan


From andre.przywara at arm.com  Thu May  5 10:55:28 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 5 May 2016 18:55:28 +0100
Subject: [PATCH v2 32/54] KVM: arm/arm64: vgic-new: Add GICv3 MMIO
 handling framework
In-Reply-To: <57277CA6.6060804@linaro.org>
References: <1461861973-26464-1-git-send-email-andre.przywara@arm.com>
 <1461861973-26464-33-git-send-email-andre.przywara@arm.com>
 <57277CA6.6060804@linaro.org>
Message-ID: <572B8910.4030706@arm.com>

Hi Eric,

On 02/05/16 17:13, Eric Auger wrote:
> Hi Andre,
> 
> Some minor comments below.
> On 04/28/2016 06:45 PM, Andre Przywara wrote:
>> Create a new file called vgic-mmio-v3.c and describe the GICv3
>> distributor and redistributor registers there.
>> This adds a special macro to deal with the split of SGI/PPI in the
>> redistributor and SPIs in the distributor, which allows us to reuse
>> the existing GICv2 handlers for those registers which are compatible.
>> Also we provide a function to deal with the registration of the two
>> separate redistributor frames per VCPU.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - adapt to new MMIO registration approach:
>>   register one device for the distributor and two for each VCPU
>> - implement special handling for private interrupts
>> - remove empty stub functions
>> - make IGROUPR return RAO
>>
>> Changelog v1 .. v2:
>> - adapt to new framework, introduce vgic-mmio-v3.c
>> - remove userland register access functions (for now)
>> - precompute .len when describing a VGIC register
>> - add missed pointer incrementation on registering redist regions
>> - replace _nyi stub functions with raz/wi versions
>>
>>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
>>  virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
>>  virt/kvm/arm/vgic/vgic.h         |   3 +
>>  4 files changed, 201 insertions(+)
>>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> new file mode 100644
>> index 0000000..c6765d4
>> --- /dev/null
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> @@ -0,0 +1,191 @@
>> +/*
>> + * VGICv3 MMIO handling functions
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <linux/irqchip/arm-gic-v3.h>
>> +#include <linux/kvm.h>
>> +#include <linux/kvm_host.h>
>> +#include <kvm/iodev.h>
>> +#include <kvm/vgic/vgic.h>
>> +
>> +#include <asm/kvm_emulate.h>
>> +
>> +#include "vgic.h"
>> +#include "vgic-mmio.h"
>> +
>> +/*
>> + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
>> + * redistributors, while SPIs are covered by registers in the distributor
>> + * block. Trying to set private IRQs in this block gets ignored.
>> + * We take some special care here to fix the calculation of the register
>> + * offset.
>> + */
>> +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \
>> +	{								\
>> +		.reg_offset = off,					\
>> +		.bits_per_irq = bpi,					\
>> +		.len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8,		\
>> +		.read = vgic_mmio_read_raz,				\
>> +		.write = vgic_mmio_write_wi,				\
>> +	}, {								\
>> +		.reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8,	\
>> +		.bits_per_irq = bpi,					\
>> +		.len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
>> +		.read = read_ops,					\
>> +		.write = write_ops,					\
>> +	}
>> +
>> +static const struct vgic_register_region vgic_v3_dist_registers[] = {
>> +	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
>> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
>> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
>> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
>> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
>> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
>> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
>> +		vgic_mmio_read_config, vgic_mmio_write_config, 2),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 64),
>> +	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
>> +};
>> +
> would add a comment to say this corresponds to RD_base frame, to use the
> same terminology as the spec. IHI0069B.
>> +static const struct vgic_register_region vgic_v3_redist_registers[] = {
>> +	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
>> +};
>> +
> same as above: SGI_base frame. Used terminology was a bit misleading for
> me since this is also part of redist, 2d frame.

I took the freedom to just replace the variable names with
vgic_v3_rdbase_registers and vgic_v3_sgibase_registers, respectively.
Hope that does the trick for you as well.

>> +static const struct vgic_register_region vgic_v3_private_registers[] = {
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
>> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
>> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
>> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
>> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
>> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
>> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 32),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
>> +		vgic_mmio_read_config, vgic_mmio_write_config, 8),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>> +};
>> +
>> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
>> +{
>> +	dev->regions = vgic_v3_dist_registers;
>> +	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
>> +
>> +	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
>> +
>> +	return SZ_64K;
>> +}
>> +
>> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
>> +{
>> +	int nr_vcpus = atomic_read(&kvm->online_vcpus);
>> +	struct kvm_vcpu *vcpu;
>> +	struct vgic_io_device *devices, *device;
>> +	int c, ret = 0;
>> +
>> +	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
>> +			  GFP_KERNEL);
>> +	if (!devices)
>> +		return -ENOMEM;
>> +
>> +	device = devices;
>> +	kvm_for_each_vcpu(c, vcpu, kvm) {
>> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
>> +		device->base_addr = redist_base_address;
>> +		device->regions = vgic_v3_redist_registers;
>> +		device->nr_regions = ARRAY_SIZE(vgic_v3_redist_registers);
>> +		device->redist_vcpu = vcpu;
>> +
>> +		mutex_lock(&kvm->slots_lock);
>> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
>> +					      redist_base_address,
>> +					      SZ_64K, &device->dev);
>> +		mutex_unlock(&kvm->slots_lock);
>> +
>> +		if (ret)
>> +			break;
>> +
>> +		device++;
>> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
>> +		device->base_addr = redist_base_address + SZ_64K;
>> +		device->regions = vgic_v3_private_registers;
>> +		device->nr_regions = ARRAY_SIZE(vgic_v3_private_registers);
>> +		device->redist_vcpu = vcpu;
>> +
>> +		mutex_lock(&kvm->slots_lock);
>> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
>> +					      redist_base_address + SZ_64K,
>> +					      SZ_64K, &device->dev);
>> +		mutex_unlock(&kvm->slots_lock);
>> +		if (ret) {
>> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
>> +						  &devices[c * 2].dev);
>> +			break;
>> +		}
>> +		device++;
>> +		redist_base_address += 2 * SZ_64K;
>> +	}
>> +
>> +	if (ret) {
>> +		for (c--; c >= 0; c--) {
>> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
>> +						  &devices[c * 2].dev);
>> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
>> +						  &devices[c * 2 + 1].dev);
>> +		}
>> +		kfree(devices);
>> +	} else {
>> +		kvm->arch.vgic.redist_iodevs = devices;
>> +	}
>> +
>> +	return ret;
>> +}
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
>> index bf4278c..80d977e 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>> @@ -502,6 +502,11 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>>  	case VGIC_V2:
>>  		len = vgic_v2_init_dist_iodev(io_device);
>>  		break;
>> +#ifdef CONFIG_KVM_ARM_VGIC_V3
>> +	case VGIC_V3:
>> +		len = vgic_v3_init_dist_iodev(io_device);
>> +		break;
>> +#endif
>>  	default:
>>  		BUG_ON(1);
>>  	}
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
>> index 884eb71..3585ac6 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio.h
>> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
>> @@ -123,4 +123,6 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
>>  
>>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>>  
>> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
>> +
>>  #endif
>> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>> index 1ab7d97..6fe07df 100644
>> --- a/virt/kvm/arm/vgic/vgic.h
>> +++ b/virt/kvm/arm/vgic/vgic.h
>> @@ -61,6 +61,9 @@ static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
>>  static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>>  {
>>  }
>> +
>>  #endif
>>  
>> +void kvm_register_vgic_device(unsigned long type);
> I don't think this relates to this patch.

Eek, good catch.

> Besides Reviewed-by: Eric Auger <eric.auger at linaro.org>

Merci!
Andre.



From Tirumalesh.Chalamarla at caviumnetworks.com  Thu May  5 10:55:33 2016
From: Tirumalesh.Chalamarla at caviumnetworks.com (Chalamarla, Tirumalesh)
Date: Thu, 5 May 2016 17:55:33 +0000
Subject: [PATCH v4 01/12] KVM: extend struct kvm_msi to hold a 32-bit
 device ID
In-Reply-To: <1458958450-19662-2-git-send-email-andre.przywara@arm.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-2-git-send-email-andre.przywara@arm.com>
Message-ID: <4C52F859-D2C3-4837-AC04-DAA83C7E176C@caviumnetworks.com>






On 3/25/16, 7:13 PM, "kvmarm-bounces at lists.cs.columbia.edu on behalf of Andre Przywara" <kvmarm-bounces at lists.cs.columbia.edu on behalf of andre.przywara at arm.com> wrote:

>The ARM GICv3 ITS MSI controller requires a device ID to be able to
>assign the proper interrupt vector. On real hardware, this ID is
>sampled from the bus. To be able to emulate an ITS controller, extend
>the KVM MSI interface to let userspace provide such a device ID. For
>PCI devices, the device ID is simply the 16-bit bus-device-function
>triplet, which should be easily available to the userland tool.

Once VFIO is used it becomes impossible to guess the device ID.
Does the VFIO series take care of this? 
>
>Also there is a new KVM capability which advertises whether the
>current VM requires a device ID to be set along with the MSI data.
>This flag is still reported as not available everywhere, later we will
>enable it when ITS emulation is used.
>
>Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>Reviewed-by: Eric Auger <eric.auger at linaro.org>
>---
> Documentation/virtual/kvm/api.txt | 12 ++++++++++--
> include/uapi/linux/kvm.h          |  5 ++++-
> 2 files changed, 14 insertions(+), 3 deletions(-)
>
>diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
>index cb2ef0b..8f7351d 100644
>--- a/Documentation/virtual/kvm/api.txt
>+++ b/Documentation/virtual/kvm/api.txt
>@@ -2163,10 +2163,18 @@ struct kvm_msi {
> 	__u32 address_hi;
> 	__u32 data;
> 	__u32 flags;
>-	__u8  pad[16];
>+	__u32 devid;
>+	__u8  pad[12];
> };
> 
>-No flags are defined so far. The corresponding field must be 0.
>+flags: KVM_MSI_VALID_DEVID: devid contains a valid value
>+devid: If KVM_MSI_VALID_DEVID is set, contains a unique device identifier
>+       for the device that wrote the MSI message.
>+       For PCI, this is usually a BFD identifier in the lower 16 bits.
>+
>+The per-VM KVM_CAP_MSI_DEVID capability advertises the need to provide
>+the device ID. If this capability is not set, userland cannot rely on
>+the kernel to allow the KVM_MSI_VALID_DEVID flag being set.
> 
> 
> 4.71 KVM_CREATE_PIT2
>diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
>index 50f44a2..6a02871 100644
>--- a/include/uapi/linux/kvm.h
>+++ b/include/uapi/linux/kvm.h
>@@ -852,6 +852,7 @@ struct kvm_ppc_smmu_info {
> #define KVM_CAP_S390_RI 124
> #define KVM_CAP_ARM_PMU_V3 125
> #define KVM_CAP_VCPU_ATTRIBUTES 126
>+#define KVM_CAP_MSI_DEVID 127
> 
> #ifdef KVM_CAP_IRQ_ROUTING
> 
>@@ -1010,12 +1011,14 @@ struct kvm_one_reg {
> 	__u64 addr;
> };
> 
>+#define KVM_MSI_VALID_DEVID	(1U << 0)
> struct kvm_msi {
> 	__u32 address_lo;
> 	__u32 address_hi;
> 	__u32 data;
> 	__u32 flags;
>-	__u8  pad[16];
>+	__u32 devid;
>+	__u8  pad[12];
> };
> 
> struct kvm_arm_device_addr {
>-- 
>2.7.3
>
>_______________________________________________
>kvmarm mailing list
>kvmarm at lists.cs.columbia.edu
>https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

From Tirumalesh.Chalamarla at caviumnetworks.com  Thu May  5 11:00:48 2016
From: Tirumalesh.Chalamarla at caviumnetworks.com (Chalamarla, Tirumalesh)
Date: Thu, 5 May 2016 18:00:48 +0000
Subject: [PATCH v4 02/12] KVM: arm/arm64: extend arch CAP checks to allow
 per-VM capabilities
In-Reply-To: <1458958450-19662-3-git-send-email-andre.przywara@arm.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-3-git-send-email-andre.przywara@arm.com>
Message-ID: <33EF8FD5-9769-4FBA-8F70-7CF737CE732A@caviumnetworks.com>






On 3/25/16, 7:14 PM, "kvmarm-bounces at lists.cs.columbia.edu on behalf of Andre Przywara" <kvmarm-bounces at lists.cs.columbia.edu on behalf of andre.przywara at arm.com> wrote:

>KVM capabilities can be a per-VM property, though ARM/ARM64 currently
>does not pass on the VM pointer to the architecture specific
>capability handlers.
>Add a "struct kvm*" parameter to those function to later allow proper
>per-VM capability reporting.

This looks good
Reviewed-by: Tirumalesh Chalamarla <tchalamarla at caviumnetworks.com> 

>
>Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>---
> arch/arm/include/asm/kvm_host.h   | 2 +-
> arch/arm/kvm/arm.c                | 2 +-
> arch/arm64/include/asm/kvm_host.h | 2 +-
> arch/arm64/kvm/reset.c            | 2 +-
> 4 files changed, 4 insertions(+), 4 deletions(-)
>
>diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
>index 3850701..494b004 100644
>--- a/arch/arm/include/asm/kvm_host.h
>+++ b/arch/arm/include/asm/kvm_host.h
>@@ -265,7 +265,7 @@ static inline void __cpu_init_stage2(void)
> 	kvm_call_hyp(__init_stage2_translation);
> }
> 
>-static inline int kvm_arch_dev_ioctl_check_extension(long ext)
>+static inline int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
> {
> 	return 0;
> }
>diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
>index 5b9d9e3..e2e9be2 100644
>--- a/arch/arm/kvm/arm.c
>+++ b/arch/arm/kvm/arm.c
>@@ -205,7 +205,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
> 		r = KVM_MAX_VCPUS;
> 		break;
> 	default:
>-		r = kvm_arch_dev_ioctl_check_extension(ext);
>+		r = kvm_arch_dev_ioctl_check_extension(kvm, ext);
> 		break;
> 	}
> 	return r;
>diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
>index 71fa6fe..2cdd7ae 100644
>--- a/arch/arm64/include/asm/kvm_host.h
>+++ b/arch/arm64/include/asm/kvm_host.h
>@@ -46,7 +46,7 @@
> 
> int __attribute_const__ kvm_target_cpu(void);
> int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
>-int kvm_arch_dev_ioctl_check_extension(long ext);
>+int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext);
> 
> struct kvm_arch {
> 	/* The VMID generation used for the virt. memory system */
>diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
>index 9677bf0..2ba7c8d 100644
>--- a/arch/arm64/kvm/reset.c
>+++ b/arch/arm64/kvm/reset.c
>@@ -63,7 +63,7 @@ static bool cpu_has_32bit_el1(void)
>  * We currently assume that the number of HW registers is uniform
>  * across all CPUs (see cpuinfo_sanity_check).
>  */
>-int kvm_arch_dev_ioctl_check_extension(long ext)
>+int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
> {
> 	int r;
> 
>-- 
>2.7.3
>
>_______________________________________________
>kvmarm mailing list
>kvmarm at lists.cs.columbia.edu
>https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

From robin.murphy at arm.com  Thu May  5 11:01:17 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 5 May 2016 19:01:17 +0100
Subject: [PATCH 2/2] drm: hdlcd: Suspend/resume only active crtcs
In-Reply-To: <20160505170601.GP1286@phenom.ffwll.local>
References: <eeb2a5540f50f5a3dd7f87861be1e9117bc4ed65.1462464611.git.robin.murphy@arm.com>
 <759fe8d3dde95091a9df83018051cba00f494e1e.1462464611.git.robin.murphy@arm.com>
 <20160505170601.GP1286@phenom.ffwll.local>
Message-ID: <572B8A6D.40405@arm.com>

Hi Daniel,

On 05/05/16 18:06, Daniel Vetter wrote:
> On Thu, May 05, 2016 at 05:13:38PM +0100, Robin Murphy wrote:
>> The current PM ops simply unconditionally enable/disable the HDLCD,
>> which proves problematic when there is no display plugged in - since
>> without a crtc the hardware itself is still in an uninitialised state,
>> coming out of suspend results in it being enabled without a valid
>> framebuffer address, which typically results in it trying to scan out
>> from bus address 0 and flooding the system with error interrupts.
>>
>> Fix this by checking the crtc state on resume, and only enabling the
>> hardware if it's actually supposed to be. For the sake of consistency,
>> do the same on the suspend path as well, although there it's merely a
>> case of skipping unnecessary work.
>>
>> CC: Liviu Dudau <liviu.dudau at arm.com>
>> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
>> ---
>>   drivers/gpu/drm/arm/hdlcd_crtc.c | 6 ++++--
>>   1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
>> index fef1b04c2aab..bf6ff5e48adc 100644
>> --- a/drivers/gpu/drm/arm/hdlcd_crtc.c
>> +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
>> @@ -296,12 +296,14 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
>>
>>   void hdlcd_crtc_suspend(struct drm_crtc *crtc)
>>   {
>> -	hdlcd_crtc_disable(crtc);
>> +	if (crtc->state->active)
>> +		hdlcd_crtc_disable(crtc);
>>   }
>>
>>   void hdlcd_crtc_resume(struct drm_crtc *crtc)
>>   {
>> -	hdlcd_crtc_enable(crtc);
>> +	if (crtc->state->active)
>> +		hdlcd_crtc_enable(crtc);
>>   }
>
> If you use the atomic helpers to suspend/resume your entire display
> pipeline these callbacks shouldn't even be needed at all. Tried just
> removing them?

I'll have to leave that in Liviu's hands as I know literally nothing 
about the relationship between platform PM ops and DRM helpers ;)
My only motivation is for the arm64 hibernate support currently sat in 
-next for 4.7 to stop being broken on my Juno board by this.

Robin.

> -Daniel
>
>>
>>   int hdlcd_setup_crtc(struct drm_device *drm)
>> --
>> 2.8.1.dirty
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>



From Tirumalesh.Chalamarla at caviumnetworks.com  Thu May  5 11:06:59 2016
From: Tirumalesh.Chalamarla at caviumnetworks.com (Chalamarla, Tirumalesh)
Date: Thu, 5 May 2016 18:06:59 +0000
Subject: [PATCH v4 04/12] KVM: arm64: handle ITS related GICv3
 redistributor registers
In-Reply-To: <57066775.10102@arm.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-5-git-send-email-andre.przywara@arm.com>
 <57066682.5040404@arm.com> <57066775.10102@arm.com>
Message-ID: <A36F639B-9E31-4B90-958D-D050E426BDF3@caviumnetworks.com>






On 4/7/16, 6:58 AM, "kvmarm-bounces at lists.cs.columbia.edu on behalf of Marc Zyngier" <kvmarm-bounces at lists.cs.columbia.edu on behalf of marc.zyngier at arm.com> wrote:

>On 07/04/16 14:54, Marc Zyngier wrote:
>> On 26/03/16 02:14, Andre Przywara wrote:
>>> In the GICv3 redistributor there are the PENDBASER and PROPBASER
>>> registers which we did not emulate so far, as they only make sense
>>> when having an ITS. In preparation for that emulate those MMIO
>>> accesses by storing the 64-bit data written into it into a variable
>>> which we later read in the ITS emulation.
>>>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>>  include/kvm/vgic/vgic.h       |  8 ++++++++
>>>  virt/kvm/arm/vgic/vgic_mmio.c | 26 ++++++++++++++++++++++----
>>>  2 files changed, 30 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
>>> index 11344e6..8ea5dd7 100644
>>> --- a/include/kvm/vgic/vgic.h
>>> +++ b/include/kvm/vgic/vgic.h
>>> @@ -145,6 +145,14 @@ struct vgic_dist {
>>>  
>>>  	struct vgic_io_device	*dist_iodevs;
>>>  	struct vgic_io_device	*redist_iodevs;
>>> +
>>> +	/* Address of LPI configuration table shared by all redistributors */
>>> +	u64			propbaser;
>>> +
>>> +	/* Addresses of LPI pending tables per redistributor */
>>> +	u64			*pendbaser;
>> 
>> All these should probably either be phys_addr_t or gpa_t.
>
>Also: these registers are per redistributor. They really should appear
>as such, and not be shoved in vgic_dist.
>
>As for GICR_PROPBASER being shared: this is an implementation choice.
>All the architecture mandates is that the same value is programmed in
>all the redistributors.
>
>Yes, you can share the storage, but I'd really want to see a field per
>redist.
+1


>
>Thanks,
>
>	M.
>-- 
>Jazz is not dead. It just smells funny...
>_______________________________________________
>kvmarm mailing list
>kvmarm at lists.cs.columbia.edu
>https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

From Tirumalesh.Chalamarla at caviumnetworks.com  Thu May  5 11:08:51 2016
From: Tirumalesh.Chalamarla at caviumnetworks.com (Chalamarla, Tirumalesh)
Date: Thu, 5 May 2016 18:08:51 +0000
Subject: [PATCH v4 03/12] KVM: arm64: Introduce new MMIO region for the
 ITS base address
In-Reply-To: <1458958450-19662-4-git-send-email-andre.przywara@arm.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-4-git-send-email-andre.przywara@arm.com>
Message-ID: <651B7BE4-D1C9-44B2-84BE-19103C1D8CE0@caviumnetworks.com>






On 3/25/16, 7:14 PM, "kvmarm-bounces at lists.cs.columbia.edu on behalf of Andre Przywara" <kvmarm-bounces at lists.cs.columbia.edu on behalf of andre.przywara at arm.com> wrote:

>The ARM GICv3 ITS controller requires a separate register frame to
>cover ITS specific registers. Add a new VGIC address type and store
>the address in a field in the vgic_dist structure.
>Provide a function to check whether userland has provided the address,
>so ITS functionality can be guarded by that check.
>
>Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>---
> Documentation/virtual/kvm/devices/arm-vgic.txt |  9 +++++++++
> arch/arm64/include/uapi/asm/kvm.h              |  2 ++
> include/kvm/vgic/vgic.h                        |  5 +++++
> virt/kvm/arm/vgic/vgic.c                       | 10 ++++++++++
> virt/kvm/arm/vgic/vgic_init.c                  |  1 +
> virt/kvm/arm/vgic/vgic_kvm_device.c            |  7 +++++++
> 6 files changed, 34 insertions(+)
>
>diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
>index 59541d4..087e2d9 100644
>--- a/Documentation/virtual/kvm/devices/arm-vgic.txt
>+++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
>@@ -39,6 +39,15 @@ Groups:
>       Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
>       This address needs to be 64K aligned.
> 
>+    KVM_VGIC_V3_ADDR_TYPE_ITS (rw, 64-bit)
>+      Base address in the guest physical address space of the GICv3 ITS
>+      control register frame. The ITS allows MSI(-X) interrupts to be
>+      injected into guests. This extension is optional, if the kernel
>+      does not support the ITS, the call returns -ENODEV.
>+      This memory is solely for the guest to access the ITS control
>+      registers and does not cover the ITS translation register.
>+      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
>+      This address needs to be 64K aligned and the region covers 64 KByte.
> 
>   KVM_DEV_ARM_VGIC_GRP_DIST_REGS
>   Attributes:
>diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
>index f209ea1..c2b257d 100644
>--- a/arch/arm64/include/uapi/asm/kvm.h
>+++ b/arch/arm64/include/uapi/asm/kvm.h
>@@ -87,9 +87,11 @@ struct kvm_regs {
> /* Supported VGICv3 address types  */
> #define KVM_VGIC_V3_ADDR_TYPE_DIST	2
> #define KVM_VGIC_V3_ADDR_TYPE_REDIST	3
>+#define KVM_VGIC_V3_ADDR_TYPE_ITS	4
> 
> #define KVM_VGIC_V3_DIST_SIZE		SZ_64K
> #define KVM_VGIC_V3_REDIST_SIZE		(2 * SZ_64K)
>+#define KVM_VGIC_V3_ITS_SIZE		SZ_64K
> 
> #define KVM_ARM_VCPU_POWER_OFF		0 /* CPU is started in OFF state */
> #define KVM_ARM_VCPU_EL1_32BIT		1 /* CPU running a 32bit VM */
>diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
>index 7c1d145..11344e6 100644
>--- a/include/kvm/vgic/vgic.h
>+++ b/include/kvm/vgic/vgic.h
>@@ -135,6 +135,9 @@ struct vgic_dist {
> 		gpa_t			vgic_redist_base;
> 	};
> 
>+	/* The base address of the ITS control register frame */
>+	gpa_t			vgic_its_base;
>+
> 	/* distributor enabled */
> 	u32			enabled;
> 
>@@ -253,4 +256,6 @@ static inline int kvm_vgic_get_max_vcpus(void)
> 	return kvm_vgic_global_state.max_gic_vcpus;
> }
> 
>+bool vgic_has_its(struct kvm *kvm);
>+
> #endif /* __ASM_ARM_KVM_VGIC_VGIC_H */
>diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>index 65395af..1de2478 100644
>--- a/virt/kvm/arm/vgic/vgic.c
>+++ b/virt/kvm/arm/vgic/vgic.c
>@@ -612,3 +612,13 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, u32 intid)
> 
> 	return map_is_active;
> }
>+
>+bool vgic_has_its(struct kvm *kvm)
>+{
>+	struct vgic_dist *dist = &kvm->arch.vgic;
>+
>+	if (dist->vgic_model != KVM_DEV_TYPE_ARM_VGIC_V3)
>+		return false;
>+
>+	return !IS_VGIC_ADDR_UNDEF(dist->vgic_its_base);
>+}
>diff --git a/virt/kvm/arm/vgic/vgic_init.c b/virt/kvm/arm/vgic/vgic_init.c
>index ac655b5..2301e03 100644
>--- a/virt/kvm/arm/vgic/vgic_init.c
>+++ b/virt/kvm/arm/vgic/vgic_init.c
>@@ -132,6 +132,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
> 	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
> 	kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
> 	kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
>+	kvm->arch.vgic.vgic_its_base = VGIC_ADDR_UNDEF;
> 
> out_unlock:
> 	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
>diff --git a/virt/kvm/arm/vgic/vgic_kvm_device.c b/virt/kvm/arm/vgic/vgic_kvm_device.c
>index 7f78a16..3ec2ac3 100644
>--- a/virt/kvm/arm/vgic/vgic_kvm_device.c
>+++ b/virt/kvm/arm/vgic/vgic_kvm_device.c
>@@ -109,6 +109,12 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
> 		block_size = KVM_VGIC_V3_REDIST_SIZE;
> 		alignment = SZ_64K;
> 		break;
>+	case KVM_VGIC_V3_ADDR_TYPE_ITS:
>+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
>+		addr_ptr = &vgic->vgic_its_base;
>+		block_size = KVM_VGIC_V3_ITS_SIZE;
>+		alignment = SZ_64K;
>+		break;

Should there be a check based on number of vcpus? 
> #endif
> 	default:
> 		r = -ENODEV;
>@@ -495,6 +501,7 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
> 		switch (attr->attr) {
> 		case KVM_VGIC_V3_ADDR_TYPE_DIST:
> 		case KVM_VGIC_V3_ADDR_TYPE_REDIST:
>+		case KVM_VGIC_V3_ADDR_TYPE_ITS:
> 			return 0;
> 		}
> 		break;
>-- 
>2.7.3
>
>_______________________________________________
>kvmarm mailing list
>kvmarm at lists.cs.columbia.edu
>https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

From f.fainelli at gmail.com  Thu May  5 11:19:57 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Thu, 5 May 2016 11:19:57 -0700
Subject: [PATCH 2/2] pci: host: Add Broadcom STB PCIE RC controller
In-Reply-To: <CANCKTBuNFQFLsab2WS+BRGUOuUOTLYuoaWNuM5T9HPGihvwYCg@mail.gmail.com>
References: <1462238749-19715-1-git-send-email-f.fainelli@gmail.com>
 <1462238749-19715-3-git-send-email-f.fainelli@gmail.com>
 <2339405.90vXV1p6zU@wuerfel> <572A4F31.8010802@gmail.com>
 <CANCKTBuNFQFLsab2WS+BRGUOuUOTLYuoaWNuM5T9HPGihvwYCg@mail.gmail.com>
Message-ID: <572B8ECD.4070100@gmail.com>

On 05/05/16 10:48, Jim Quinlan wrote:
>>> Why is this?
>>
>> This is so we do not end-up programming the PCIe RC which is agnostic of
>> the number of
> 
> I believe this code is still around for folks passing us a device tree
> with lacking information.  It should be removed.

I have actually reworked this to utilize the brcm,log2-scb-sizes
property, since the number of elements in the property is equal to the
number of memory controllers populated on the system.

> 
>>
>>>
>>>> +    resource_list_for_each_entry(win, &res) {
>>>> +            struct brcm_window *w = &pcie->out_wins[i];
>>>> +
>>>> +            r = win->res;
>>>> +
>>>> +            if (!r->flags)
>>>> +                    continue;
>>>> +
>>>> +            switch (resource_type(r)) {
>>>> +            case IORESOURCE_MEM:
>>>> +                    w->cpu_addr = r->start;
>>>> +                    w->size = resource_size(r);
>>>> +                    w->pcie_iomem_res.name  = "External PCIe MEM";
>>>> +                    w->pcie_iomem_res.flags = r->flags;
>>>> +                    w->pcie_iomem_res.start = r->start;
>>>> +                    w->pcie_iomem_res.end   = r->end;
>>>> +                    pcie->num_out_wins++;
>>>> +                    i++;
>>>> +                    /* Request memory region resources. */
>>>> +                    ret = devm_request_resource(&pdev->dev,
>>>> +                                                &iomem_resource,
>>>> +                                                &w->pcie_iomem_res);
>>>> +                    if (ret) {
>>>> +                            dev_err(&pdev->dev,
>>>> +                                    "request PCIe memory resource failed\n");
>>>> +                            goto out_err_clk;
>>>> +                    }
>>>> +                    break;
>>>> +
>>>> +            default:
>>>> +                    continue;
>>>> +            }
>>>> +    }
>>>
>>> What about IORESOURCE_IO?
>>
>> We do not support I/O space on this controller AFAIR. Our downstream
>> driver does insert a fake bogus I/O range, but I cannot really remember
>> why that was needed now, Jim do you remember?
>> --
>> Florian
> 
> We added a bogus IO region because there was no other way to proceed
> w/o getting an error.  Or should I say, I knew of no other way to
> proceed...

AH, I found your commit doing that, I would really think that the PCI
domains logic should be able to take care of assigning non-conflicting
I/O regions these days, if not, that seems like a bug to me.

Do I need a specific board with a ton of switches/peripherals attached
to it to expose whether this is needed or not? Right now, I removed it
from this patchset, but I suppose we could add it back, would we need that?

Thanks Jim!
-- 
Florian


From panand at redhat.com  Thu May  5 11:20:31 2016
From: panand at redhat.com (Pratyush Anand)
Date: Thu, 5 May 2016 23:50:31 +0530
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <20160505164300.GA16914@roeck-us.net>
References: <5728A7C3.4010001@roeck-us.net>
 <20160503143856.GE13045@dhcppc6.redhat.com>
 <5728BEC4.6050603@codeaurora.org>
 <20160503155141.GF13045@dhcppc6.redhat.com>
 <20160503171602.GA2518@roeck-us.net>
 <20160504141449.GG13045@dhcppc6.redhat.com>
 <572A0577.1070000@codeaurora.org>
 <20160504155932.GH13045@dhcppc6.redhat.com>
 <572A2099.4070901@codeaurora.org>
 <20160505164300.GA16914@roeck-us.net>
Message-ID: <20160505182031.GB12434@dhcppc6.redhat.com>

+kexec list

Hi Guenter,

On 05/05/2016:09:43:00 AM, Guenter Roeck wrote:
> On Wed, May 04, 2016 at 11:17:29AM -0500, Timur Tabi wrote:
> > Pratyush Anand wrote:
> > >Its unique to SBSA because you have very little timeout here. kexec-tools
> > >upstream does not have any mechanism to handle watchdog timeout. Lets say even
> > >if we implement a framework there, the best it can do is to ping the watchdog
> > >again.
> > 
> > Ok, so it's more accurate to say that kexec has a minimum watchdog timeout
> > requirement.  What happens if the system admin sets the timeout to 5 seconds
> > arbitrarily?  The system will reset during kexec, no matter which hardware
> > is used.
> > 
> > This still sounds like a band-aid to me.  We're just assuming that we need a
> > timeout of at least 20 seconds to support kexec.  Frankly, this still sounds
> > like a problem the kexec developers needs to acknowledge and deal with.
> > 
> > Still I'm okay with a patch that extends the timeout by programming WCV, but
> > it has to be commented as a hack specifically to support kexec because the
> > timeout might be too short.  Then Wim can decide whether he supports such
> > changes.
> > 
> I don't even understand how kexec-tools is involved in the first place.
> kexec-tools sounds like user space, which should execute _after_ the kernel

So _after_ the 1st kernel and _before_ the second kernel. It is an application
for the 1st kernel, which creates a tiny boot loader for 2nd kernel. After the
1st kernel is loaded, kexec-tools is executed in user space, which provides a
sane 2nd kernel and initramfs to the kernel using kexec() system call. Now 1st
kernel keep these information loaded into a specific memory called "Crash
Kernel" memory. When 1st kernel crashes, kernel kexec code passes control to
kexec boot loader, which does sha verification of 2nd kernel and initramfs and
passes control to 2nd kernel.

> and its modules are loaded (assuming modules are loaded from initramfs).
> If kexec-tools can somehow ping the watchdog (presumably by writing into
> the HW directly), I don't understand why it doesn't simply load the watchdog
> driver instead and let the watchdog core handle the heartbeats.

Because that tiny boot loader (which called purgatory) does not have any
knowledge about driver.

> 
> I am really missing something here. How can kexec-tools do anything before
> the kernel is loaded ?

So, if we _do_  _not_ go with the current version of patch, probably this could
be the only available option. However, Even when we would kick watchdog once in
kexec boot loader, we will have to make sure the 2nd kernel is light enough to
load watchdog module before timeout.  I think, in the long run we must have SBSA
watchdog specification improvement to keep WOR as 64 bit.

~Pratyush


From timur at codeaurora.org  Thu May  5 11:22:10 2016
From: timur at codeaurora.org (Timur Tabi)
Date: Thu, 5 May 2016 13:22:10 -0500
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <20160505182031.GB12434@dhcppc6.redhat.com>
References: <5728A7C3.4010001@roeck-us.net>
 <20160503143856.GE13045@dhcppc6.redhat.com> <5728BEC4.6050603@codeaurora.org>
 <20160503155141.GF13045@dhcppc6.redhat.com>
 <20160503171602.GA2518@roeck-us.net>
 <20160504141449.GG13045@dhcppc6.redhat.com> <572A0577.1070000@codeaurora.org>
 <20160504155932.GH13045@dhcppc6.redhat.com> <572A2099.4070901@codeaurora.org>
 <20160505164300.GA16914@roeck-us.net>
 <20160505182031.GB12434@dhcppc6.redhat.com>
Message-ID: <572B8F52.2000709@codeaurora.org>

Pratyush Anand wrote:
> I think, in the long run we must have SBSA
> watchdog specification improvement to keep WOR as 64 bit.

I agree with this 100%.  IMHO, using a 32-bit WOR was just a bad decision.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum, a Linux Foundation collaborative project.


From javier at osg.samsung.com  Thu May  5 11:32:16 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 14:32:16 -0400
Subject: [RFC v2 01/13] usb: misc: usb3503: Clean up on driver unbind
In-Reply-To: <1462451666-17945-2-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-2-git-send-email-k.kozlowski@samsung.com>
Message-ID: <d78e8151-ee37-a003-2f8f-bc5431906512@osg.samsung.com>

Hello Krzysztof

Patch looks good to me, I just have a trivial comment below.

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> The driver should clean up after itself by unpreparing the clock when it
> is unbound.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---
>  drivers/usb/misc/usb3503.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
> index b45cb77c0744..a464636675a6 100644
> --- a/drivers/usb/misc/usb3503.c
> +++ b/drivers/usb/misc/usb3503.c
> @@ -330,6 +330,19 @@ static int usb3503_i2c_probe(struct i2c_client *i2c,
>  	return usb3503_probe(hub);
>  }
>  
> +static int usb3503_i2c_remove(struct i2c_client *i2c)
> +{
> +	struct usb3503 *hub;
> +
> +	hub = i2c_get_clientdata(i2c);
> +	if (hub) {
> +		if (hub->clk)
> +			clk_disable_unprepare(hub->clk);
> +	}

I think the following is simpler and easier to read:

if (hub && hub->clk)
	clk_disable_unprepare(hub->clk);

> +
> +	return 0;
> +}
> +
>  static int usb3503_platform_probe(struct platform_device *pdev)
>  {
>  	struct usb3503 *hub;
> @@ -342,6 +355,19 @@ static int usb3503_platform_probe(struct platform_device *pdev)
>  	return usb3503_probe(hub);
>  }
>  
> +static int usb3503_platform_remove(struct platform_device *pdev)
> +{
> +	struct usb3503 *hub;
> +
> +	hub = platform_get_drvdata(pdev);
> +	if (hub) {
> +		if (hub->clk)
> +			clk_disable_unprepare(hub->clk);
> +	}
> +

Ditto.

> +	return 0;
> +}
> +
>  #ifdef CONFIG_PM_SLEEP
>  static int usb3503_i2c_suspend(struct device *dev)
>  {
> @@ -395,6 +421,7 @@ static struct i2c_driver usb3503_i2c_driver = {
>  		.of_match_table = of_match_ptr(usb3503_of_match),
>  	},
>  	.probe		= usb3503_i2c_probe,
> +	.remove		= usb3503_i2c_remove,
>  	.id_table	= usb3503_id,
>  };
>  
> @@ -404,6 +431,7 @@ static struct platform_driver usb3503_platform_driver = {
>  		.of_match_table = of_match_ptr(usb3503_of_match),
>  	},
>  	.probe		= usb3503_platform_probe,
> +	.remove		= usb3503_platform_remove,
>  };
>  
>  static int __init usb3503_init(void)
> 

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From tony at atomide.com  Thu May  5 11:36:11 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 5 May 2016 11:36:11 -0700
Subject: [PATCH] ARM: dts: omap5-board-common: Describe the voltage
 supply mapping accurately
In-Reply-To: <572A528C.4090302@ti.com>
References: <1462389618-28860-1-git-send-email-nm@ti.com>
 <572A528C.4090302@ti.com>
Message-ID: <20160505183611.GA5995@atomide.com>

* Nishanth Menon <nm at ti.com> [160504 12:52]:
> On 05/04/2016 02:20 PM, Nishanth Menon wrote:
> [...]
> 
> > @@ -551,6 +590,8 @@
> >  
> >  				ldo9_reg: ldo9 {
> >  					/* VCC_DV_SDIO: vdds_sdcard */
> > +					vin-supply = <&vmmcsdio_fixed>;
> > +
> 
> There is an extra white space here, and vmmcsd_fixed is the regulator
> to be used, looks like vmmcsdio_fixed should ideally been vwlan_fixed
> or something.. the actual rail to LDO9_IN was called vmmc_3v3_SDIO..
> 
> Sorry for the confusion. Unfortunately, I can not recreate the fail on
> my board, but this sounded like the closest fix I can think of.

Looks like arch/arm/boot/dts/tegra114-dalmore.dts has entries like
this instead for the PMIC:

ldo9-in-supply = <&palmas_smps9_reg>:
...

Doing simlar changes for omap5-board-common.dtsi seems to fix the
issues for me:

LDO3: supplied by vdds_1v8_main
LDO4: supplied by vdds_1v8_main
ldo4: Bringing 0uV into 1800000-1800000uV
LDO5: supplied by vsys_cobra
LDO6: supplied by vdds_1v8_main
LDO7: supplied by vsys_cobra
ldo7: Bringing 0uV into 2000000-2000000uV
LDO8: supplied by vsys_cobra
LDO9: supplied by vmmcsd_fixed

See also the patch below too, and please check I got things right
based on your earlier patch :)

Now I'm wondering if the x15 related vin-supply changes are actually all
ignored? It seems that "vin" is only automatically configured for the
fixed-regulator? Maybe regulator-palmas should be updated to use the
"vin-supply" if configured to avoid confusion?

Regards,

Tony

8< -----------------
--- a/arch/arm/boot/dts/omap5-board-common.dtsi
+++ b/arch/arm/boot/dts/omap5-board-common.dtsi
@@ -14,6 +14,29 @@
 		display0 = &hdmi0;
 	};
 
+	vmain: fixedregulator-vmain {
+		compatible = "regulator-fixed";
+		regulator-name = "vmain";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	vsys_cobra: fixedregulator-vsys_cobra {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_cobra";
+		vin-supply = <&vmain>;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	vdds_1v8_main: fixedregulator-vdds_1v8_main {
+		compatible = "regulator-fixed";
+		regulator-name = "vdds_1v8_main";
+		vin-supply = <&smps7_reg>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
 	vmmcsd_fixed: fixedregulator-mmcsd {
 		compatible = "regulator-fixed";
 		regulator-name = "vmmcsd_fixed";
@@ -409,6 +432,25 @@
 
 			ti,ldo6-vibrator;
 
+			smps123-in-supply = <&vsys_cobra>;
+			smps45-in-supply = <&vsys_cobra>;
+			smps6-in-supply = <&vsys_cobra>;
+			smps7-in-supply = <&vsys_cobra>;
+			smps8-in-supply = <&vsys_cobra>;
+			smps9-in-supply = <&vsys_cobra>;
+			smps10_out2-in-supply = <&vsys_cobra>;
+			smps10_out1-in-supply = <&vsys_cobra>;
+			ldo1-in-supply = <&vsys_cobra>;
+			ldo2-in-supply = <&vsys_cobra>;
+			ldo3-in-supply = <&vdds_1v8_main>;
+			ldo4-in-supply = <&vdds_1v8_main>;
+			ldo5-in-supply = <&vsys_cobra>;
+			ldo6-in-supply = <&vdds_1v8_main>;
+			ldo7-in-supply = <&vsys_cobra>;
+			ldo8-in-supply = <&vsys_cobra>;
+			ldo9-in-supply = <&vmmcsd_fixed>;
+			ldousb-in-supply = <&vsys_cobra>;
+
 			regulators {
 				smps123_reg: smps123 {
 					/* VDD_OPP_MPU */


From dmitry.torokhov at gmail.com  Thu May  5 11:44:38 2016
From: dmitry.torokhov at gmail.com (Dmitry Torokhov)
Date: Thu, 5 May 2016 11:44:38 -0700
Subject: [PATCH v4 3/3] ARM: dts: use syscon in cygnus touchscreen dt node
In-Reply-To: <CAAFb_vp+oxHc6YD24zPr0o6Pt9Jt1_LsT14VUQGBKXBpvNAj_Q@mail.gmail.com>
References: <1456556396-4759-1-git-send-email-raveendra.padasalagi@broadcom.com>
 <1456556396-4759-4-git-send-email-raveendra.padasalagi@broadcom.com>
 <20160406173140.GB38452@dtor-ws>
 <CAGVrzcbCZn6RYFwJTkffkct1DiiG+tBJnKELDn32T38_s5mjOg@mail.gmail.com>
 <CAAFb_vp+oxHc6YD24zPr0o6Pt9Jt1_LsT14VUQGBKXBpvNAj_Q@mail.gmail.com>
Message-ID: <20160505184438.GA25689@dtor-ws>

Hi Raveendra,

On Thu, May 05, 2016 at 11:17:00AM +0530, Raveendra Padasalagi wrote:
> Thanks Dmitry and Florian.
> 
> Hi Dmitry,
> 
> I understand the dts changes are really needed for the touch screen
> driver changes made in this patch. But currently there are no deployed
> systems/customer's using this driver. So please pull the driver changes
> and I will follow up to make sure dts changes also goes in.
> 
> Below is the latest patch set pushed.
> 
> https://lkml.org/lkml/2016/3/24/45

I have the driver, binding doc changes, and changes to
arch/arm/boot/dts/bcm-cygnus.dtsi as
74813cebd678dd471b4fcd7d3019aecab9dbcedd in my 'next' branch, so it will
be merged in the next merge window.

Thanks.

-- 
Dmitry


From javier at osg.samsung.com  Thu May  5 11:44:50 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 14:44:50 -0400
Subject: [RFC v2 02/13] power/mmc: Move pwrseq drivers to power/pwrseq
In-Reply-To: <1462451666-17945-3-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-3-git-send-email-k.kozlowski@samsung.com>
Message-ID: <4532bfb4-38f9-a61d-1d80-e5af18cd3d98@osg.samsung.com>

Hello Krzysztof,

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> The MMC power sequence drivers are useful also outside of MMC world: for
> USB devices needed a hard-reset before probing. Before extending and
> re-using pwrseq drivers, move them to a new place.
> 
> The commit does not introduce significant changes in the pwrseq drivers
> code so still all the functions are prefixed with "mmc_pwrseq". However
> the MMC-specific pwrseq functions has to be now exported and everything
> is hidden not by CONFIG_OF but by new CONFIG_POWER_SEQ option.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

[snip]

> --- a/drivers/mmc/core/Kconfig
> +++ b/drivers/power/pwrseq/Kconfig
> @@ -1,7 +1,12 @@
> -#
> -# MMC core configuration
> -#
> -config PWRSEQ_EMMC
> +menuconfig POWER_SEQ
> +	default y if OF
> +	bool "Hardware reset support for specific devices"
> +	help
> +	  Provides drivers which reset the specific device before...
> +

I think this text could be improved a little bit, maybe something like:

"Provides drivers that implements specific power sequences for chips,
using the generic power sequence management interface".

The rest looks good to me.

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From tony at atomide.com  Thu May  5 11:46:09 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 5 May 2016 11:46:09 -0700
Subject: [PATCH] ARM: dts: omap5-igep0050: Correct hdmi regulator
In-Reply-To: <572A38FD.9050801@ti.com>
References: <1461925297-9734-1-git-send-email-peter.ujfalusi@ti.com>
 <6ee9d67a-e907-715a-f3f5-d90a470314c3@ti.com>
 <20160504172634.GS5995@atomide.com> <572A38FD.9050801@ti.com>
Message-ID: <20160505184609.GB5995@atomide.com>

* Nishanth Menon <nm at ti.com> [160504 11:03]:
> On 05/04/2016 12:26 PM, Tony Lindgren wrote:
> > Hi,
> > 
> > Adding Nishanth to Cc.
> > 
> > * Peter Ujfalusi <peter.ujfalusi at ti.com> [160429 05:15]:
> >> ldo7_reg, obviously ;)
> >>
> >>> 	status = "okay";
> >>> 	regulator-min-microvolt = <1800000>;
> >>> 	regulator-max-microvolt = <1800000>;
> >>> };
> > 
> > It really seems to be ldo7, otherwise there's no HDMI output. I don't
> > have the schematics either.
> > 
> > But it seems we have at least two other regressions in Linux next that
> > prevent me from testing this properly:
> > 
> > 1. On igepv5, I get this for the MMC regulator
> > 
> > ldo9: bypassed regulator has no supply!
> > ldo9: failed to get the current voltage(-517)
> > palmas-pmic 48070000.i2c:palmas at 48:palmas_pmic: failed to register 48070000.i2c:palmar

The patch I posted fixes this. Then for the HDMI see below.
I've kept it at 2V like we have in omap5-board-common.dtsi,
I wonder if it really should be 1.8V though for ldo7 in this
case?

Regards,

Tony
8< -----------------
From: Tony Lindgren <tony at atomide.com>
Date: Thu, 5 May 2016 11:29:23 -0700
Subject: [PATCH] ARM: dts: Fix ldo7 source for HDMI on igepv5

Fix ldo7 source for HDMI on igepv5.

Suggested-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
Signed-off-by: Tony Lindgren <tony at atomide.com>

diff --git a/arch/arm/boot/dts/omap5-igep0050.dts b/arch/arm/boot/dts/omap5-igep0050.dts
index 46ecb1d..72ff6a4 100644
--- a/arch/arm/boot/dts/omap5-igep0050.dts
+++ b/arch/arm/boot/dts/omap5-igep0050.dts
@@ -35,6 +35,12 @@
 	};
 };
 
+&ldo7_reg {
+	status = "okay";
+	regulator-min-microvolt = <2000000>;
+	regulator-max-microvolt = <2000000>;
+};
+
 &omap5_pmx_core {
 	i2c4_pins: pinmux_i2c4_pins {
 		pinctrl-single,pins = <


From javier at osg.samsung.com  Thu May  5 11:46:07 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 14:46:07 -0400
Subject: [RFC v2 03/13] MAINTAINERS: Retain Ulf Hansson as the same
 maintainer of pwrseq
In-Reply-To: <1462451666-17945-4-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-4-git-send-email-k.kozlowski@samsung.com>
Message-ID: <480a93a3-c8e0-7049-ff54-955d0d45aa73@osg.samsung.com>

Krzysztof,

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> Before moving pwrseq drivers from drivers/mmc/core/ to drivers/power/,
> they were maintained by Ulf Hansson.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From Tirumalesh.Chalamarla at caviumnetworks.com  Thu May  5 11:51:48 2016
From: Tirumalesh.Chalamarla at caviumnetworks.com (Chalamarla, Tirumalesh)
Date: Thu, 5 May 2016 18:51:48 +0000
Subject: [PATCH v4 06/12] KVM: arm64: implement basic ITS register handlers
In-Reply-To: <1458958450-19662-7-git-send-email-andre.przywara@arm.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-7-git-send-email-andre.przywara@arm.com>
Message-ID: <D292FA5F-F643-40EE-87C1-6BDC10AA2962@caviumnetworks.com>






On 3/25/16, 7:14 PM, "kvmarm-bounces at lists.cs.columbia.edu on behalf of Andre Przywara" <kvmarm-bounces at lists.cs.columbia.edu on behalf of andre.przywara at arm.com> wrote:

>Add emulation for some basic MMIO registers used in the ITS emulation.
>This includes:
>- GITS_{CTLR,TYPER,IIDR}
>- ID registers
>- GITS_{CBASER,CREADR,CWRITER}
>  those implement the ITS command buffer handling
>
>Most of the handlers are pretty straight forward, but CWRITER goes
>some extra miles to allow fine grained locking. The idea here
>is to let only the first instance iterate through the command ring
>buffer, CWRITER accesses on other VCPUs meanwhile will be picked up
>by that first instance and handled as well. The ITS lock is thus only
>hold for very small periods of time and is dropped before the actual
>command handler is called.
>
>Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>---
> include/kvm/vgic/vgic.h            |   3 +
> include/linux/irqchip/arm-gic-v3.h |   8 ++
> virt/kvm/arm/vgic/its-emul.c       | 272 ++++++++++++++++++++++++++++++++++++-
> virt/kvm/arm/vgic/vgic.h           |   6 +
> virt/kvm/arm/vgic/vgic_init.c      |   2 +
> 5 files changed, 284 insertions(+), 7 deletions(-)
>
>diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
>index c79bed5..bafea11 100644
>--- a/include/kvm/vgic/vgic.h
>+++ b/include/kvm/vgic/vgic.h
>@@ -115,6 +115,9 @@ struct vgic_io_device {
> struct vgic_its {
> 	bool			enabled;
> 	spinlock_t		lock;
>+	u64			cbaser;
>+	int			creadr;
>+	int			cwriter;
> };
> 
> struct vgic_dist {
>diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>index a813c3e..7011b98 100644
>--- a/include/linux/irqchip/arm-gic-v3.h
>+++ b/include/linux/irqchip/arm-gic-v3.h
>@@ -179,15 +179,23 @@
> #define GITS_BASER			0x0100
> #define GITS_IDREGS_BASE		0xffd0
> #define GITS_PIDR2			GICR_PIDR2
>+#define GITS_PIDR4			0xffd0
>+#define GITS_CIDR0			0xfff0
>+#define GITS_CIDR1			0xfff4
>+#define GITS_CIDR2			0xfff8
>+#define GITS_CIDR3			0xfffc
> 
> #define GITS_TRANSLATER			0x10040
> 
> #define GITS_CTLR_ENABLE		(1U << 0)
> #define GITS_CTLR_QUIESCENT		(1U << 31)
> 
>+#define GITS_TYPER_PLPIS		(1UL << 0)
>+#define GITS_TYPER_IDBITS_SHIFT		8
> #define GITS_TYPER_DEVBITS_SHIFT	13
> #define GITS_TYPER_DEVBITS(r)		((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
> #define GITS_TYPER_PTA			(1UL << 19)
>+#define GITS_TYPER_HWCOLLCNT_SHIFT	24
> 
> #define GITS_CBASER_VALID		(1UL << 63)
> #define GITS_CBASER_nCnB		(0UL << 59)
>diff --git a/virt/kvm/arm/vgic/its-emul.c b/virt/kvm/arm/vgic/its-emul.c
>index 49dd5e4..de8d360 100644
>--- a/virt/kvm/arm/vgic/its-emul.c
>+++ b/virt/kvm/arm/vgic/its-emul.c
>@@ -31,23 +31,263 @@
> #include "vgic.h"
> #include "vgic_mmio.h"
> 
>+#define BASER_BASE_ADDRESS(x) ((x) & 0xfffffffff000ULL)
>+
>+static int vgic_mmio_read_its_ctlr(struct kvm_vcpu *vcpu,
>+				   struct kvm_io_device *this,
>+				   gpa_t addr, int len, void *val)
>+{
>+	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>+	u32 reg;
>+
>+	reg = GITS_CTLR_QUIESCENT;
>+	if (its->enabled)
>+		reg |= GITS_CTLR_ENABLE;
>+
>+	write_mask32(reg, addr & 3, len, val);
>+
>+	return 0;
>+}
>+
>+static int vgic_mmio_write_its_ctlr(struct kvm_vcpu *vcpu,
>+				    struct kvm_io_device *this,
>+				    gpa_t addr, int len, const void *val)
>+{
>+	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>+	struct vgic_io_device *iodev = container_of(this,
>+						    struct vgic_io_device, dev);
>+
>+        if (addr - iodev->base_addr == 0)
>+		its->enabled = !!(*(u8*)val & GITS_CTLR_ENABLE);
>+
>+	return 0;
>+}
>+
>+static int vgic_mmio_read_its_typer(struct kvm_vcpu *vcpu,
>+				    struct kvm_io_device *this,
>+				    gpa_t addr, int len, void *val)
>+{
>+	u64 reg = GITS_TYPER_PLPIS;
>+
>+	/*
>+	 * We use linear CPU numbers for redistributor addressing,
>+	 * so GITS_TYPER.PTA is 0.
>+	 * To avoid memory waste on the guest side, we keep the
>+	 * number of IDBits and DevBits low for the time being.
>+	 * This could later be made configurable by userland.
>+	 * Since we have all collections in linked list, we claim
>+	 * that we can hold all of the collection tables in our
>+	 * own memory and that the ITT entry size is 1 byte (the
>+	 * smallest possible one).
>+	 */


How are you planning to handle device ids with VFIO?
Will there be a mapping between virtual and physical?
Or will it entirely based on virtual and not planning
to send the commands to corresponding physical ITS.
May be no need. 

>+	reg |= 0xff << GITS_TYPER_HWCOLLCNT_SHIFT;
>+	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
>+	reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
>+
>+	write_mask64(reg, addr & 7, len, val);
>+
>+	return 0;
>+}
>+
>+static int vgic_mmio_read_its_iidr(struct kvm_vcpu *vcpu,
>+				   struct kvm_io_device *this,
>+				   gpa_t addr, int len, void *val)
>+{
>+	u32 reg = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
>+
Hmm, no other implementor planning to support system emulation. 
>+	write_mask32(reg, addr & 3, len, val);
>+
>+	return 0;
>+}
>+
>+static int vgic_mmio_read_its_idregs(struct kvm_vcpu *vcpu,
>+				     struct kvm_io_device *this,
>+				     gpa_t addr, int len, void *val)
>+{
>+	struct vgic_io_device *iodev = container_of(this,
>+						    struct vgic_io_device, dev);
>+	u32 reg = 0;
>+	int idreg = (addr & ~3) - iodev->base_addr + GITS_IDREGS_BASE;
>+
>+	switch (idreg) {
>+	case GITS_PIDR2:
>+		reg = GIC_PIDR2_ARCH_GICv3;
>+		break;
>+	case GITS_PIDR4:
>+		/* This is a 64K software visible page */
>+		reg = 0x40;
>+		break;
>+	/* Those are the ID registers for (any) GIC. */
>+	case GITS_CIDR0:
>+		reg = 0x0d;
>+		break;
>+	case GITS_CIDR1:
>+		reg = 0xf0;
>+		break;
>+	case GITS_CIDR2:
>+		reg = 0x05;
>+		break;
>+	case GITS_CIDR3:
>+		reg = 0xb1;
>+		break;
>+	}
>+
>+	write_mask32(reg, addr & 3, len, val);
>+
>+	return 0;
>+}
>+
>+/*
>+ * This function is called with both the ITS and the distributor lock dropped,
>+ * so the actual command handlers must take the respective locks when needed.
>+ */
>+static int vits_handle_command(struct kvm_vcpu *vcpu, u64 *its_cmd)
>+{
>+	return -ENODEV;
>+}
>+
>+static int vgic_mmio_read_its_cbaser(struct kvm_vcpu *vcpu,
>+				    struct kvm_io_device *this,
>+				    gpa_t addr, int len, void *val)
>+{
>+	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>+
>+	write_mask64(its->cbaser, addr & 7, len, val);
>+
>+	return 0;
>+}
>+
>+static int vgic_mmio_write_its_cbaser(struct kvm_vcpu *vcpu,
>+				      struct kvm_io_device *this,
>+				      gpa_t addr, int len, const void *val)
>+{
>+	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>+
>+	if (its->enabled)
>+		return 0;
>+
>+	its->cbaser = mask64(its->cbaser, addr & 7, len, val);
>+	its->creadr = 0;
>+
>+	return 0;
>+}
>+
>+static int its_cmd_buffer_size(struct kvm *kvm)
>+{
>+	struct vgic_its *its = &kvm->arch.vgic.its;
>+
>+	return ((its->cbaser & 0xff) + 1) << 12;
>+}
>+
>+static gpa_t its_cmd_buffer_base(struct kvm *kvm)
>+{
>+	struct vgic_its *its = &kvm->arch.vgic.its;
>+
>+	return BASER_BASE_ADDRESS(its->cbaser);
>+}
>+
>+/*
>+ * By writing to CWRITER the guest announces new commands to be processed.
>+ * Since we cannot read from guest memory inside the ITS spinlock, we
>+ * iterate over the command buffer (with the lock dropped) until the read
>+ * pointer matches the write pointer. Other VCPUs writing this register in the
>+ * meantime will just update the write pointer, leaving the command
>+ * processing to the first instance of the function.
>+ */
>+static int vgic_mmio_write_its_cwriter(struct kvm_vcpu *vcpu,
>+				       struct kvm_io_device *this,
>+				       gpa_t addr, int len, const void *val)
>+{
>+	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>+	struct vgic_its *its = &dist->its;
>+	gpa_t cbaser = its_cmd_buffer_base(vcpu->kvm);
>+	u64 cmd_buf[4];
>+	u32 reg;
>+	bool finished;
>+
>+	reg = mask64(its->cwriter & 0xfffe0, addr & 7, len, val);
>+	reg &= 0xfffe0;
>+	if (reg > its_cmd_buffer_size(vcpu->kvm))
>+		return 0;
>+
>+	spin_lock(&its->lock);
>+
>+	/*
>+	 * If there is still another VCPU handling commands, let this
>+	 * one pick up the new CWRITER and process "our" new commands as well.
>+	 */
>+	finished = (its->cwriter != its->creadr);
>+	its->cwriter = reg;
>+
>+	spin_unlock(&its->lock);
>+
>+	while (!finished) {
>+		int ret = kvm_read_guest(vcpu->kvm, cbaser + its->creadr,
>+					 cmd_buf, 32);
>+		if (ret) {
>+			/*
>+			 * Gah, we are screwed. Reset CWRITER to that command
>+			 * that we have finished processing and return.
>+			 */
>+			spin_lock(&its->lock);
>+			its->cwriter = its->creadr;

Is this correct?
>+			spin_unlock(&its->lock);
>+			break;
>+		}
>+		vits_handle_command(vcpu, cmd_buf);
>+
>+		spin_lock(&its->lock);
>+		its->creadr += 32;
>+		if (its->creadr == its_cmd_buffer_size(vcpu->kvm))
>+			its->creadr = 0;
>+		finished = (its->creadr == its->cwriter);
>+		spin_unlock(&its->lock);
>+	}
>+
>+	return 0;
>+}
>+
>+static int vgic_mmio_read_its_cwriter(struct kvm_vcpu *vcpu,
>+				      struct kvm_io_device *this,
>+				      gpa_t addr, int len, void *val)
>+{
>+	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>+	u64 reg = its->cwriter & 0xfffe0;
>+
>+	write_mask64(reg, addr & 7, len, val);
>+
>+	return 0;
>+}
>+
>+static int vgic_mmio_read_its_creadr(struct kvm_vcpu *vcpu,
>+				     struct kvm_io_device *this,
>+				     gpa_t addr, int len, void *val)
>+{
>+	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>+	u64 reg = its->creadr & 0xfffe0;
>+
>+	write_mask64(reg, addr & 7, len, val);
>+
>+	return 0;
>+}
>+
> struct vgic_register_region its_registers[] = {
> 	REGISTER_DESC_WITH_LENGTH(GITS_CTLR,
>-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>+		vgic_mmio_read_its_ctlr, vgic_mmio_write_its_ctlr, 4),
> 	REGISTER_DESC_WITH_LENGTH(GITS_IIDR,
>-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>+		vgic_mmio_read_its_iidr, vgic_mmio_write_wi, 4),
> 	REGISTER_DESC_WITH_LENGTH(GITS_TYPER,
>-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>+		vgic_mmio_read_its_typer, vgic_mmio_write_wi, 4),
> 	REGISTER_DESC_WITH_LENGTH(GITS_CBASER,
>-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>+		vgic_mmio_read_its_cbaser, vgic_mmio_write_its_cbaser, 8),
> 	REGISTER_DESC_WITH_LENGTH(GITS_CWRITER,
>-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>+		vgic_mmio_read_its_cwriter, vgic_mmio_write_its_cwriter, 8),
> 	REGISTER_DESC_WITH_LENGTH(GITS_CREADR,
>-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>+		vgic_mmio_read_its_creadr, vgic_mmio_write_wi, 8),
> 	REGISTER_DESC_WITH_LENGTH(GITS_BASER,
> 		vgic_mmio_read_raz, vgic_mmio_write_wi, 0x40),
> 	REGISTER_DESC_WITH_LENGTH(GITS_IDREGS_BASE,
>-		vgic_mmio_read_raz, vgic_mmio_write_wi, 0x30),
>+		vgic_mmio_read_its_idregs, vgic_mmio_write_wi, 0x30),
> };
> 
> /* This is called on setting the LPI enable bit in the redistributor. */
>@@ -59,9 +299,14 @@ int vits_init(struct kvm *kvm)
> {
> 	struct vgic_dist *dist = &kvm->arch.vgic;
> 	struct vgic_its *its = &dist->its;
>+	int nr_vcpus = atomic_read(&kvm->online_vcpus);
> 	struct vgic_io_device *regions;
> 	int ret, i;
> 
>+	dist->pendbaser = kcalloc(nr_vcpus, sizeof(u64), GFP_KERNEL);
>+	if (!dist->pendbaser)
>+		return -ENOMEM;
>+
> 	spin_lock_init(&its->lock);
> 
> 	regions = kmalloc_array(ARRAY_SIZE(its_registers),
>@@ -82,3 +327,16 @@ int vits_init(struct kvm *kvm)
> 
> 	return -ENXIO;
> }
>+
>+void vits_destroy(struct kvm *kvm)
>+{
>+	struct vgic_dist *dist = &kvm->arch.vgic;
>+	struct vgic_its *its = &dist->its;
>+
>+	if (!vgic_has_its(kvm))
>+		return;
>+
>+	kfree(dist->pendbaser);
>+
>+	its->enabled = false;
>+}
>diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>index 4e7dcb8..08f97d1 100644
>--- a/virt/kvm/arm/vgic/vgic.h
>+++ b/virt/kvm/arm/vgic/vgic.h
>@@ -63,6 +63,7 @@ int vgic_register_redist_regions(struct kvm *kvm, gpa_t dist_base_address);
> 
> int vits_init(struct kvm *kvm);
> void vgic_enable_lpis(struct kvm_vcpu *vcpu);
>+void vits_destroy(struct kvm *kvm);
> #else
> static inline void vgic_v3_irq_change_affinity(struct kvm *kvm, u32 intid,
> 					       u64 mpidr)
>@@ -137,6 +138,11 @@ static inline void vgic_enable_lpis(struct kvm_vcpu *vcpu)
> {
> 	return;
> }
>+
>+static inline void vits_destroy(struct kvm *kvm)
>+{
>+	return;
>+}
> #endif
> 
> void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>diff --git a/virt/kvm/arm/vgic/vgic_init.c b/virt/kvm/arm/vgic/vgic_init.c
>index dcfb93d..e4459e3 100644
>--- a/virt/kvm/arm/vgic/vgic_init.c
>+++ b/virt/kvm/arm/vgic/vgic_init.c
>@@ -298,6 +298,8 @@ void kvm_vgic_destroy(struct kvm *kvm)
> 
> 	kvm_vgic_dist_destroy(kvm);
> 
>+	vits_destroy(kvm);
>+
> 	kvm_for_each_vcpu(i, vcpu, kvm)
> 		kvm_vgic_vcpu_destroy(vcpu);
> }
>-- 
>2.7.3
>
>_______________________________________________
>kvmarm mailing list
>kvmarm at lists.cs.columbia.edu
>https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

From tony at atomide.com  Thu May  5 11:56:21 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu,  5 May 2016 11:56:21 -0700
Subject: [PATCH] ARM: dts: Fix igepv5 audiopwon-gpio
Message-ID: <1462474581-13865-1-git-send-email-tony@atomide.com>

Playing audio works on omap5-uevm, but produces an "Unhandled fault:
imprecise external abort (0x1406) at 0x00000000" error on igepv5.

Looks like the twl6040 audpwron GPIO pin is different for these
boards. Let's fix the issue by configuring the audpwron in the
board specific dts file.

Cc: Agust? Fontquerni <af at iseebcn.com>
Cc: Eduard Gavin <egavin at iseebcn.com>
Cc: Enric Balletbo i Serra <eballetbo at iseebcn.com>
Cc: Peter Ujfalusi <peter.ujfalusi at ti.com>
Signed-off-by: Tony Lindgren <tony at atomide.com>
---
 arch/arm/boot/dts/omap5-board-common.dtsi |  3 ++-
 arch/arm/boot/dts/omap5-igep0050.dts      | 10 ++++++++++
 arch/arm/boot/dts/omap5-uevm.dts          | 10 ++++++++++
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi
index 2eea26c..23b1d7c 100644
--- a/arch/arm/boot/dts/omap5-board-common.dtsi
+++ b/arch/arm/boot/dts/omap5-board-common.dtsi
@@ -642,7 +642,8 @@
 		pinctrl-0 = <&twl6040_pins>;
 
 		interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
-		ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
+
+		/* audpwron gpio defined in the board specific dts */
 
 		vio-supply = <&smps7_reg>;
 		v2v1-supply = <&smps9_reg>;
diff --git a/arch/arm/boot/dts/omap5-igep0050.dts b/arch/arm/boot/dts/omap5-igep0050.dts
index 72ff6a4..673cdfa 100644
--- a/arch/arm/boot/dts/omap5-igep0050.dts
+++ b/arch/arm/boot/dts/omap5-igep0050.dts
@@ -58,3 +58,13 @@
 		<&gpio7 3 0>;		/* 195, SDA */
 };
 
+&twl6040 {
+	ti,audpwron-gpio = <&gpio5 16 GPIO_ACTIVE_HIGH>;  /* gpio line 144 */
+};
+
+&twl6040_pins {
+	pinctrl-single,pins = <
+		OMAP5_IOPAD(0x1c4, PIN_OUTPUT | MUX_MODE6)	/* mcspi1_somi.gpio5_144 */
+		OMAP5_IOPAD(0x1ca, PIN_OUTPUT | MUX_MODE6)	/* perslimbus2_clock.gpio5_145 */
+	>;
+};
diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts
index 60b3fbb..a51e605 100644
--- a/arch/arm/boot/dts/omap5-uevm.dts
+++ b/arch/arm/boot/dts/omap5-uevm.dts
@@ -51,3 +51,13 @@
 		<&gpio9 1 GPIO_ACTIVE_HIGH>,	/* TCA6424A P00, LS OE */
 		<&gpio7 1 GPIO_ACTIVE_HIGH>;	/* GPIO 193, HPD */
 };
+
+&twl6040 {
+	ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
+};
+
+&twl6040_pins {
+	pinctrl-single,pins = <
+		OMAP5_IOPAD(0x1be, PIN_OUTPUT | MUX_MODE6)	/* mcspi1_somi.gpio5_141 */
+	>;
+};
-- 
2.8.1



From javier at osg.samsung.com  Thu May  5 11:57:00 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 14:57:00 -0400
Subject: [RFC v2 04/13] power: pwrseq: Enable COMPILE_TEST for drivers
In-Reply-To: <1462451666-17945-5-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-5-git-send-email-k.kozlowski@samsung.com>
Message-ID: <757d6280-0e82-f570-c984-0604789419f9@osg.samsung.com>

Hello Krzysztof,

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> Allow build testing for power sequence drivers.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From Tirumalesh.Chalamarla at caviumnetworks.com  Thu May  5 11:59:10 2016
From: Tirumalesh.Chalamarla at caviumnetworks.com (Chalamarla, Tirumalesh)
Date: Thu, 5 May 2016 18:59:10 +0000
Subject: [PATCH v4 08/12] KVM: arm64: connect LPIs to the VGIC emulation
In-Reply-To: <1458958450-19662-9-git-send-email-andre.przywara@arm.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-9-git-send-email-andre.przywara@arm.com>
Message-ID: <72C09722-6D61-4131-BAA3-09C810B214CF@caviumnetworks.com>






On 3/25/16, 7:14 PM, "kvmarm-bounces at lists.cs.columbia.edu on behalf of Andre Przywara" <kvmarm-bounces at lists.cs.columbia.edu on behalf of andre.przywara at arm.com> wrote:

>LPIs are dynamically created (mapped) at guest runtime and their
>actual numbers can be quite high, but is mostly assigned using a very
>sparse allocation scheme. So arrays are not an ideal data structure
>to hold the information. We use our equivalent of the "Interrupt
>Translation Table Entry" (ITTE) to hold the vgic_irq struct for a
>virtual LPI embedded in in the ITTE.
>Connect the VGIC core code via an accessor function to help it get the
>struct vgic_irq for a certain LPI.

Reviewed-by:Tirumalesh Chalamarla<tchalamarla at caviumnetworks.com>

>
>Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>---
> virt/kvm/arm/vgic/its-emul.c | 29 +++++++++++++++++++++++++++++
> virt/kvm/arm/vgic/vgic.h     |  8 +++++++-
> 2 files changed, 36 insertions(+), 1 deletion(-)
>
>diff --git a/virt/kvm/arm/vgic/its-emul.c b/virt/kvm/arm/vgic/its-emul.c
>index c0334ff..1188e9a 100644
>--- a/virt/kvm/arm/vgic/its-emul.c
>+++ b/virt/kvm/arm/vgic/its-emul.c
>@@ -55,11 +55,29 @@ struct its_collection {
> struct its_itte {
> 	struct list_head itte_list;
> 
>+	struct vgic_irq irq;
> 	struct its_collection *collection;
> 	u32 lpi;
> 	u32 event_id;
> };
> 
>+/* To be used as an iterator this macro misses the enclosing parentheses */
>+#define for_each_lpi(dev, itte, kvm) \
>+	list_for_each_entry(dev, &(kvm)->arch.vgic.its.device_list, dev_list) \
>+		list_for_each_entry(itte, &(dev)->itt, itte_list)
>+
>+static struct its_itte *find_itte_by_lpi(struct kvm *kvm, int lpi)
>+{
>+	struct its_device *device;
>+	struct its_itte *itte;
>+
>+	for_each_lpi(device, itte, kvm) {
>+		if (itte->lpi == lpi)
>+			return itte;
>+	}
>+	return NULL;
>+}
>+
> #define BASER_BASE_ADDRESS(x) ((x) & 0xfffffffff000ULL)
> 
> static int vgic_mmio_read_its_ctlr(struct kvm_vcpu *vcpu,
>@@ -166,6 +184,17 @@ static int vgic_mmio_read_its_idregs(struct kvm_vcpu *vcpu,
> 	return 0;
> }
> 
>+struct vgic_irq *vgic_its_get_lpi(struct kvm *kvm, u32 intid)
>+{
>+	struct its_itte *itte;
>+
>+	itte = find_itte_by_lpi(kvm, intid);
>+	if (!itte)
>+		return NULL;
>+
>+	return &itte->irq;
>+}
>+
> static void its_free_itte(struct its_itte *itte)
> {
> 	list_del(&itte->itte_list);
>diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>index 08f97d1..160c511 100644
>--- a/virt/kvm/arm/vgic/vgic.h
>+++ b/virt/kvm/arm/vgic/vgic.h
>@@ -63,6 +63,7 @@ int vgic_register_redist_regions(struct kvm *kvm, gpa_t dist_base_address);
> 
> int vits_init(struct kvm *kvm);
> void vgic_enable_lpis(struct kvm_vcpu *vcpu);
>+struct vgic_irq *vgic_its_get_lpi(struct kvm *kvm, u32 intid);
> void vits_destroy(struct kvm *kvm);
> #else
> static inline void vgic_v3_irq_change_affinity(struct kvm *kvm, u32 intid,
>@@ -129,7 +130,7 @@ static inline int vgic_register_redist_regions(struct kvm *kvm,
> 	return -ENODEV;
> }
> 
>-int vits_init(struct kvm *kvm)
>+static inline int vits_init(struct kvm *kvm)
> {
> 	return 0;
> }
>@@ -139,6 +140,11 @@ static inline void vgic_enable_lpis(struct kvm_vcpu *vcpu)
> 	return;
> }
> 
>+static inline struct vgic_irq *vgic_its_get_lpi(struct kvm *kvm, u32 intid)
>+{
>+	return NULL;
>+}
>+
> static inline void vits_destroy(struct kvm *kvm)
> {
> 	return;
>-- 
>2.7.3
>
>_______________________________________________
>kvmarm mailing list
>kvmarm at lists.cs.columbia.edu
>https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

From nm at ti.com  Thu May  5 12:00:29 2016
From: nm at ti.com (Nishanth Menon)
Date: Thu, 5 May 2016 14:00:29 -0500
Subject: [PATCH] ARM: dts: omap5-board-common: Describe the voltage supply
 mapping accurately
In-Reply-To: <20160505183611.GA5995@atomide.com>
References: <1462389618-28860-1-git-send-email-nm@ti.com>
 <572A528C.4090302@ti.com> <20160505183611.GA5995@atomide.com>
Message-ID: <572B984D.10203@ti.com>

On 05/05/2016 01:36 PM, Tony Lindgren wrote:
> * Nishanth Menon <nm at ti.com> [160504 12:52]:
>> On 05/04/2016 02:20 PM, Nishanth Menon wrote:
>> [...]
>>
>>> @@ -551,6 +590,8 @@
>>>  
>>>  				ldo9_reg: ldo9 {
>>>  					/* VCC_DV_SDIO: vdds_sdcard */
>>> +					vin-supply = <&vmmcsdio_fixed>;
>>> +
>>
>> There is an extra white space here, and vmmcsd_fixed is the regulator
>> to be used, looks like vmmcsdio_fixed should ideally been vwlan_fixed
>> or something.. the actual rail to LDO9_IN was called vmmc_3v3_SDIO..
>>
>> Sorry for the confusion. Unfortunately, I can not recreate the fail on
>> my board, but this sounded like the closest fix I can think of.
> 
> Looks like arch/arm/boot/dts/tegra114-dalmore.dts has entries like
> this instead for the PMIC:
> 
> ldo9-in-supply = <&palmas_smps9_reg>:
> ...
> 
> Doing simlar changes for omap5-board-common.dtsi seems to fix the
> issues for me:
> 
> LDO3: supplied by vdds_1v8_main
> LDO4: supplied by vdds_1v8_main
> ldo4: Bringing 0uV into 1800000-1800000uV
> LDO5: supplied by vsys_cobra
> LDO6: supplied by vdds_1v8_main
> LDO7: supplied by vsys_cobra
> ldo7: Bringing 0uV into 2000000-2000000uV
> LDO8: supplied by vsys_cobra
> LDO9: supplied by vmmcsd_fixed
> 
> See also the patch below too, and please check I got things right
> based on your earlier patch :)


> 
> Now I'm wondering if the x15 related vin-supply changes are actually all
> ignored? It seems that "vin" is only automatically configured for the
> fixed-regulator? Maybe regulator-palmas should be updated to use the

ok /me goes duh!!!! ofcourse! Sorry about not catching it..
hmm.. maybe we messed up am572x-idk as well.. I can quickly fix that
up as well

> "vin-supply" if configured to avoid confusion?
regulator-palmas using vin-supply is more sensible, but i am not sure
about the argument
for this originally was -> +Mark, Keerthy and Lakshman for feedback.

[...]
> +			smps123-in-supply = <&vsys_cobra>;
> +			smps45-in-supply = <&vsys_cobra>;
> +			smps6-in-supply = <&vsys_cobra>;
> +			smps7-in-supply = <&vsys_cobra>;
> +			smps8-in-supply = <&vsys_cobra>;
> +			smps9-in-supply = <&vsys_cobra>;
> +			smps10_out2-in-supply = <&vsys_cobra>;
> +			smps10_out1-in-supply = <&vsys_cobra>;
> +			ldo1-in-supply = <&vsys_cobra>;
> +			ldo2-in-supply = <&vsys_cobra>;
> +			ldo3-in-supply = <&vdds_1v8_main>;
> +			ldo4-in-supply = <&vdds_1v8_main>;
> +			ldo5-in-supply = <&vsys_cobra>;
> +			ldo6-in-supply = <&vdds_1v8_main>;
> +			ldo7-in-supply = <&vsys_cobra>;
> +			ldo8-in-supply = <&vsys_cobra>;
> +			ldo9-in-supply = <&vmmcsd_fixed>;
> +			ldousb-in-supply = <&vsys_cobra>;
ldoln is vsys_cobra as well.. I missed that.

Others look good. we should probably get this merged to fix the
regression.

> +
>  			regulators {
>  				smps123_reg: smps123 {
>  					/* VDD_OPP_MPU */
> 


-- 
Regards,
Nishanth Menon


From tony at atomide.com  Thu May  5 12:01:29 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu,  5 May 2016 12:01:29 -0700
Subject: [PATCH] ARM: dts: Fix uart wakeirq on omap5 by removing WAKEUP_EN for
 omaps
Message-ID: <1462474889-22800-1-git-send-email-tony@atomide.com>

The padconf register WAKEUP_EN is now handled in a generic way using
Linux wakeirqs where pinctrl-single toggles the WAKEUP_EN bit when
a wakeirq is enabled or disabled.

At least omap5 gets confused if the WAKEUP_EN bit is set and the pin
is not claimed as a wakeirq. The end result is that wakeirqs don't
work properly as there is nothing handling the wakeirq.

So let's just remove the WAKEUP_EN usage from dts files.

Signed-off-by: Tony Lindgren <tony at atomide.com>
---
 arch/arm/boot/dts/omap3-evm-37xx.dts      | 2 +-
 arch/arm/boot/dts/omap3-n900.dts          | 4 ++--
 arch/arm/boot/dts/omap3-n950-n9.dtsi      | 6 +++---
 arch/arm/boot/dts/omap3-zoom3.dts         | 6 +++---
 arch/arm/boot/dts/omap5-board-common.dtsi | 2 +-
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/arm/boot/dts/omap3-evm-37xx.dts b/arch/arm/boot/dts/omap3-evm-37xx.dts
index cd11c56..792a876 100644
--- a/arch/arm/boot/dts/omap3-evm-37xx.dts
+++ b/arch/arm/boot/dts/omap3-evm-37xx.dts
@@ -85,7 +85,7 @@
 			OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_clk.sdmmc2_clk */
 			OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_cmd.sdmmc2_cmd */
 			OMAP3_CORE1_IOPAD(0x215c, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_dat0.sdmmc2_dat0 */
-			OMAP3_CORE1_IOPAD(0x215e, WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1.sdmmc2_dat1 */
+			OMAP3_CORE1_IOPAD(0x215e, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1.sdmmc2_dat1 */
 			OMAP3_CORE1_IOPAD(0x2160, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_dat2.sdmmc2_dat2 */
 			OMAP3_CORE1_IOPAD(0x2162, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_dat3.sdmmc2_dat3 */
 		>;
diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts
index d9e2d9c..2b74a81 100644
--- a/arch/arm/boot/dts/omap3-n900.dts
+++ b/arch/arm/boot/dts/omap3-n900.dts
@@ -288,7 +288,7 @@
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT_PULLUP | MUX_MODE1)	/* ssi1_rdy_tx */
 			OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE1)		/* ssi1_flag_tx */
-			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* ssi1_wake_tx (cawake) */
+			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE4)		/* ssi1_wake_tx (cawake) */
 			OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE1)		/* ssi1_dat_tx */
 			OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT | MUX_MODE1)		/* ssi1_dat_rx */
 			OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT | MUX_MODE1)		/* ssi1_flag_rx */
@@ -300,7 +300,7 @@
 	modem_pins: pinmux_modem {
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE4)		/* gpio 70 => cmt_apeslpx */
-			OMAP3_CORE1_IOPAD(0x20e0, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* gpio 72 => ape_rst_rq */
+			OMAP3_CORE1_IOPAD(0x20e0, PIN_INPUT | MUX_MODE4)		/* gpio 72 => ape_rst_rq */
 			OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE4)		/* gpio 73 => cmt_rst_rq */
 			OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE4)		/* gpio 74 => cmt_en */
 			OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE4)		/* gpio 75 => cmt_rst */
diff --git a/arch/arm/boot/dts/omap3-n950-n9.dtsi b/arch/arm/boot/dts/omap3-n950-n9.dtsi
index a00ca76..927b17f 100644
--- a/arch/arm/boot/dts/omap3-n950-n9.dtsi
+++ b/arch/arm/boot/dts/omap3-n950-n9.dtsi
@@ -97,7 +97,7 @@
 			OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE1)            /* ssi1_dat_tx */
 			OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE1)            /* ssi1_flag_tx */
 			OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT_PULLUP | MUX_MODE1)      /* ssi1_rdy_tx */
-			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* ssi1_wake_tx (cawake) */
+			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE4)	/* ssi1_wake_tx (cawake) */
 			OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT | MUX_MODE1)             /* ssi1_dat_rx */
 			OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT | MUX_MODE1)             /* ssi1_flag_rx */
 			OMAP3_CORE1_IOPAD(0x2188, PIN_OUTPUT | MUX_MODE1)            /* ssi1_rdy_rx */
@@ -110,7 +110,7 @@
 			OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE7)            /* ssi1_dat_tx */
 			OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE7)            /* ssi1_flag_tx */
 			OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT_PULLDOWN | MUX_MODE7)    /* ssi1_rdy_tx */
-			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* ssi1_wake_tx (cawake) */
+			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE4)	/* ssi1_wake_tx (cawake) */
 			OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT | MUX_MODE7)             /* ssi1_dat_rx */
 			OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT | MUX_MODE7)             /* ssi1_flag_rx */
 			OMAP3_CORE1_IOPAD(0x2188, PIN_OUTPUT | MUX_MODE4)            /* ssi1_rdy_rx */
@@ -120,7 +120,7 @@
 
 	modem_pins1: pinmux_modem_core1_pins {
 		pinctrl-single,pins = <
-			OMAP3_CORE1_IOPAD(0x207a, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* gpio_34 (ape_rst_rq) */
+			OMAP3_CORE1_IOPAD(0x207a, PIN_INPUT | MUX_MODE4)	/* gpio_34 (ape_rst_rq) */
 			OMAP3_CORE1_IOPAD(0x2100, PIN_OUTPUT | MUX_MODE4)            /* gpio_88 (cmt_rst_rq) */
 			OMAP3_CORE1_IOPAD(0x210a, PIN_OUTPUT | MUX_MODE4)            /* gpio_93 (cmt_apeslpx) */
 		>;
diff --git a/arch/arm/boot/dts/omap3-zoom3.dts b/arch/arm/boot/dts/omap3-zoom3.dts
index acb5f3c..75d4dfb 100644
--- a/arch/arm/boot/dts/omap3-zoom3.dts
+++ b/arch/arm/boot/dts/omap3-zoom3.dts
@@ -98,7 +98,7 @@
 		pinctrl-single,pins = <
                         OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart2_cts.uart2_cts */
                         OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0)		/* uart2_rts.uart2_rts */
-                        OMAP3_CORE1_IOPAD(0x217a, WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart2_rx.uart2_rx */
+                        OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)		/* uart2_rx.uart2_rx */
                         OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0)		/* uart2_tx.uart2_tx */
 		>;
 	};
@@ -107,7 +107,7 @@
 		pinctrl-single,pins = <
                         OMAP3_CORE1_IOPAD(0x219a, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* uart3_cts_rctx.uart3_cts_rctx */
                         OMAP3_CORE1_IOPAD(0x219c, PIN_OUTPUT | MUX_MODE0)		/* uart3_rts_sd.uart3_rts_sd */
-                        OMAP3_CORE1_IOPAD(0x219e, WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */
+                        OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0)		/* uart3_rx_irrx.uart3_rx_irrx */
                         OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0)		/* uart3_tx_irtx.uart3_tx_irtx */
 		>;
 	};
@@ -125,7 +125,7 @@
 		pinctrl-single,pins = <
 			OMAP3630_CORE2_IOPAD(0x25d8, PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_clk.sdmmc3_clk */
 			OMAP3630_CORE2_IOPAD(0x25e4, PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_d4.sdmmc3_dat0 */
-			OMAP3630_CORE2_IOPAD(0x25e6, WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE2) /* etk_d5.sdmmc3_dat1 */
+			OMAP3630_CORE2_IOPAD(0x25e6, PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_d5.sdmmc3_dat1 */
 			OMAP3630_CORE2_IOPAD(0x25e8, PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_d6.sdmmc3_dat2 */
 			OMAP3630_CORE2_IOPAD(0x25e2, PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_d3.sdmmc3_dat3 */
 		>;
diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi
index 23b1d7c..4bc22d2 100644
--- a/arch/arm/boot/dts/omap5-board-common.dtsi
+++ b/arch/arm/boot/dts/omap5-board-common.dtsi
@@ -332,7 +332,7 @@
 
 	wlcore_irq_pin: pinmux_wlcore_irq_pin {
 		pinctrl-single,pins = <
-			OMAP5_IOPAD(0x40, WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE6)	/* llia_wakereqin.gpio1_wk14 */
+			OMAP5_IOPAD(0x40, PIN_INPUT_PULLUP | MUX_MODE6)	/* llia_wakereqin.gpio1_wk14 */
 		>;
 	};
 };
-- 
2.8.1



From robert.jarzmik at free.fr  Thu May  5 12:06:44 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Thu, 05 May 2016 21:06:44 +0200
Subject: [RFC PATCH 1/7] ALSA: ac97: split out the generic ac97 registers
In-Reply-To: <20160504090702.GV6292@sirena.org.uk> (Mark Brown's message of
 "Wed, 4 May 2016 10:07:02 +0100")
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-2-git-send-email-robert.jarzmik@free.fr>
 <20160503115159.GP6292@sirena.org.uk> <87y47roski.fsf@belgarion.home>
 <20160504090702.GV6292@sirena.org.uk>
Message-ID: <87pot0pbnf.fsf@belgarion.home>

Mark Brown <broonie at kernel.org> writes:

> On Tue, May 03, 2016 at 09:22:05PM +0200, Robert Jarzmik wrote:
>> Mark Brown <broonie at kernel.org> writes:
>
>> > On Sat, Apr 30, 2016 at 11:15:33PM +0200, Robert Jarzmik wrote:
>
>> >> Split out from the ac97_codec.h the ac97 generic registers, which can be
>> >> used by a codec, typically a generic ac97 codec, and by the ac97 bus, to
>> >> scan an ac97 AC-Link.
>
>> > I don't entirely see the value in this one but equally it does no harm.
>
>> Oh that's to have the defines AC97_VENDOR_ID1 and AC97_VENDOR_ID2, but without
>> including ac97_codec.h in sound/ac97/bus.c.
>
> I see that, I just don't know why that helps.
Ok, so let me explain.

As you already understood, AC97_VENDOR* is needed in bus.c for the
autoscanning. The remaining is the reason why I don't want to include
ac97_codec.h in bus.c, which follows.

In order to have a clean split between former ac97 bus implementation and this
new one, I didn't want to include any former ac97 includes, excepting in
sound/ac97/compat.c.

Amongst the thing I wanted to isolate :
 - didn't want the struct snd_ac97 in sound/ac97/* (except compat.c) to see not
   be "fooled" by a definition which would come with ac97_codec.h by "chance".
 - didn't want to have snd_a97_*() functions, as they rely on struct snd_ac97.
 - didn't want the struct snd_ac97_bus_ops, there is a new one
   => the main grudge I have is the void (*write)() and unsigned short (*read)()
   prototype which prevent from returning error codes such as -EIO, etc ...

Moreover, to have a smooth transition, my plan is :
 - have this new ac97 bus
 - provide any needed function in compat.c so that previous codecs, regmap,
   ... continue to work
 - port the ac97 "pci" codec to have a generic ac97 codec so that codecs can be
   shrinked from common ac97 code.
 - port the codecs ... several monthes of work, etc ...
 - once the port is done, remove compat.c

This transition will be easier if the new ac97 code is isolated as much as
possible from the former code while providing backward compatibility ... hence
this patch.

Cheers.

-- 
Robert


From javier at osg.samsung.com  Thu May  5 12:09:52 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 15:09:52 -0400
Subject: [RFC v2 05/13] power: pwrseq: Remove mmc prefix from mmc_pwrseq
In-Reply-To: <1462451666-17945-6-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-6-git-send-email-k.kozlowski@samsung.com>
Message-ID: <48539995-2966-0df0-51db-e0c549a92880@osg.samsung.com>

Hello Krzysztof,

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> The "mmc" prefix is no longer needed after moving the pwrseq core code
> from mmc/ to power/.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

[snip]

> diff --git a/drivers/power/pwrseq/pwrseq_emmc.c b/drivers/power/pwrseq/pwrseq_emmc.c
> index a0583ed46d7f..a68ac9a68e04 100644
> --- a/drivers/power/pwrseq/pwrseq_emmc.c
> +++ b/drivers/power/pwrseq/pwrseq_emmc.c
> @@ -22,7 +22,7 @@
>  #include <linux/mmc/host.h>
> 

I don't think this header inclusion is needed. At least I didn't see anything
defined there that's used in this driver. This also applies to pwrseq_simple.

I think you could remove those in another preparatory patches before the move.

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From Tirumalesh.Chalamarla at caviumnetworks.com  Thu May  5 12:12:02 2016
From: Tirumalesh.Chalamarla at caviumnetworks.com (Chalamarla, Tirumalesh)
Date: Thu, 5 May 2016 19:12:02 +0000
Subject: [PATCH v4 10/12] KVM: arm64: implement ITS command queue command
 handlers
In-Reply-To: <1458958450-19662-11-git-send-email-andre.przywara@arm.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-11-git-send-email-andre.przywara@arm.com>
Message-ID: <3F572EDF-329A-4D6D-BA06-7E6F3B89C819@caviumnetworks.com>






On 3/25/16, 7:14 PM, "kvmarm-bounces at lists.cs.columbia.edu on behalf of Andre Przywara" <kvmarm-bounces at lists.cs.columbia.edu on behalf of andre.przywara at arm.com> wrote:

>The connection between a device, an event ID, the LPI number and the
>allocated CPU is stored in in-memory tables in a GICv3, but their
>format is not specified by the spec. Instead software uses a command
>queue in a ring buffer to let the ITS implementation use their own
>format.
>Implement handlers for the various ITS commands and let them store
>the requested relation into our own data structures.
>To avoid kmallocs inside the ITS spinlock, we preallocate possibly
>needed memory outside of the lock and free that if it turns out to
>be not needed (mostly error handling).
>Error handling is very basic at this point, as we don't have a good
>way of communicating errors to the guest (usually a SError).
>The INT command handler is missing at this point, as we gain the
>capability of actually injecting MSIs into the guest only later on.
>
>Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>---
> include/linux/irqchip/arm-gic-v3.h |  19 +-
> virt/kvm/arm/vgic/its-emul.c       | 514 ++++++++++++++++++++++++++++++++++++-
> 2 files changed, 531 insertions(+), 2 deletions(-)
>
>diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>index 7011b98..c9aa8d8 100644
>--- a/include/linux/irqchip/arm-gic-v3.h
>+++ b/include/linux/irqchip/arm-gic-v3.h
>@@ -254,7 +254,10 @@
>  */
> #define GITS_CMD_MAPD			0x08
> #define GITS_CMD_MAPC			0x09
>-#define GITS_CMD_MAPVI			0x0a
>+#define GITS_CMD_MAPTI			0x0a
>+/* older GIC documentation used MAPVI for this command */
>+#define GITS_CMD_MAPVI			GITS_CMD_MAPTI
>+#define GITS_CMD_MAPI			0x0b
> #define GITS_CMD_MOVI			0x01
> #define GITS_CMD_DISCARD		0x0f
> #define GITS_CMD_INV			0x0c
>@@ -265,6 +268,20 @@
> #define GITS_CMD_SYNC			0x05
> 
> /*
>+ * ITS error numbers
>+ */
>+#define E_ITS_MOVI_UNMAPPED_INTERRUPT           0x010107
>+#define E_ITS_MOVI_UNMAPPED_COLLECTION          0x010109
>+#define E_ITS_CLEAR_UNMAPPED_INTERRUPT          0x010507
>+#define E_ITS_MAPC_PROCNUM_OOR                  0x010902
>+#define E_ITS_MAPTI_UNMAPPED_DEVICE             0x010a04
>+#define E_ITS_MAPTI_PHYSICALID_OOR              0x010a06
>+#define E_ITS_INV_UNMAPPED_INTERRUPT            0x010c07
>+#define E_ITS_INVALL_UNMAPPED_COLLECTION        0x010d09
>+#define E_ITS_MOVALL_PROCNUM_OOR                0x010e01
>+#define E_ITS_DISCARD_UNMAPPED_INTERRUPT        0x010f07
>+
>+/*
>  * CPU interface registers
>  */
> #define ICC_CTLR_EL1_EOImode_drop_dir	(0U << 1)
>diff --git a/virt/kvm/arm/vgic/its-emul.c b/virt/kvm/arm/vgic/its-emul.c
>index d82ba9b..dcd0cac 100644
>--- a/virt/kvm/arm/vgic/its-emul.c
>+++ b/virt/kvm/arm/vgic/its-emul.c
>@@ -22,6 +22,7 @@
> #include <linux/kvm_host.h>
> #include <linux/interrupt.h>
> #include <linux/list.h>
>+#include <linux/slab.h>
> 
> #include <linux/irqchip/arm-gic-v3.h>
> 
>@@ -61,6 +62,34 @@ struct its_itte {
> 	u32 event_id;
> };
> 
>+static struct its_device *find_its_device(struct kvm *kvm, u32 device_id)
>+{
>+	struct vgic_its *its = &kvm->arch.vgic.its;
>+	struct its_device *device;
>+
>+	list_for_each_entry(device, &its->device_list, dev_list)
>+		if (device_id == device->device_id)
>+			return device;
>+
>+	return NULL;
>+}
>+
>+static struct its_itte *find_itte(struct kvm *kvm, u32 device_id, u32 event_id)
>+{
>+	struct its_device *device;
>+	struct its_itte *itte;
>+
>+	device = find_its_device(kvm, device_id);
>+	if (device == NULL)
>+		return NULL;
>+
>+	list_for_each_entry(itte, &device->itt, itte_list)
>+		if (itte->event_id == event_id)
>+			return itte;
>+
>+	return NULL;
>+}
>+
> /* To be used as an iterator this macro misses the enclosing parentheses */
> #define for_each_lpi(dev, itte, kvm) \
> 	list_for_each_entry(dev, &(kvm)->arch.vgic.its.device_list, dev_list) \
>@@ -78,6 +107,19 @@ static struct its_itte *find_itte_by_lpi(struct kvm *kvm, int lpi)
> 	return NULL;
> }
> 
>+static struct its_collection *find_collection(struct kvm *kvm, int coll_id)
>+{
>+	struct its_collection *collection;
>+
>+	list_for_each_entry(collection, &kvm->arch.vgic.its.collection_list,
>+			    coll_list) {
>+		if (coll_id == collection->collection_id)
>+			return collection;
>+	}
>+
>+	return NULL;
>+}
>+
> #define LPI_PROP_ENABLE_BIT(p)	((p) & LPI_PROP_ENABLED)
> #define LPI_PROP_PRIORITY(p)	((p) & 0xfc)
> 
>@@ -91,6 +133,29 @@ static void update_lpi_config(struct kvm *kvm, struct its_itte *itte, u8 prop)
> 	vgic_queue_irq(kvm, &itte->irq);
> }
> 
>+/*
>+ * Finds all LPIs which are mapped to this collection and updates the
>+ * struct irq's target_vcpu field accordingly.
>+ * Needs to be called whenever either the collection for a LPIs has
>+ * changed or the collection itself got retargetted.
>+ */
>+static void update_affinity(struct kvm *kvm, struct its_collection *coll)
>+{
>+	struct its_device *device;
>+	struct its_itte *itte;
>+	struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, coll->target_addr);
>+
>+	for_each_lpi(device, itte, kvm) {
>+		if (!itte->collection ||
>+		    coll->collection_id != itte->collection->collection_id)
>+			continue;
>+
>+		spin_lock(&itte->irq.irq_lock);
>+		itte->irq.target_vcpu = vcpu;
>+		spin_unlock(&itte->irq.irq_lock);
>+	}
>+}
>+
> #define GIC_LPI_OFFSET 8192
> 
> /* We scan the table in chunks the size of the smallest page size */
>@@ -323,13 +388,460 @@ static void its_free_itte(struct its_itte *itte)
> 	kfree(itte);
> }
> 
>+static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
>+{
>+	return (le64_to_cpu(its_cmd[word]) >> shift) & (BIT_ULL(size) - 1);
>+}
>+
>+#define its_cmd_get_command(cmd)	its_cmd_mask_field(cmd, 0,  0,  8)
>+#define its_cmd_get_deviceid(cmd)	its_cmd_mask_field(cmd, 0, 32, 32)
>+#define its_cmd_get_id(cmd)		its_cmd_mask_field(cmd, 1,  0, 32)
>+#define its_cmd_get_physical_id(cmd)	its_cmd_mask_field(cmd, 1, 32, 32)
>+#define its_cmd_get_collection(cmd)	its_cmd_mask_field(cmd, 2,  0, 16)
>+#define its_cmd_get_target_addr(cmd)	its_cmd_mask_field(cmd, 2, 16, 32)
>+#define its_cmd_get_validbit(cmd)	its_cmd_mask_field(cmd, 2, 63,  1)
>+
>+/* The DISCARD command frees an Interrupt Translation Table Entry (ITTE). */
>+static int vits_cmd_handle_discard(struct kvm *kvm, u64 *its_cmd)
>+{
>+	struct vgic_its *its = &kvm->arch.vgic.its;
>+	u32 device_id;
>+	u32 event_id;
>+	struct its_itte *itte;
>+	int ret = E_ITS_DISCARD_UNMAPPED_INTERRUPT;
>+
>+	device_id = its_cmd_get_deviceid(its_cmd);
>+	event_id = its_cmd_get_id(its_cmd);
>+
>+	spin_lock(&its->lock);
>+	itte = find_itte(kvm, device_id, event_id);
>+	if (itte && itte->collection) {
>+		/*
>+		 * Though the spec talks about removing the pending state, we
>+		 * don't bother here since we clear the ITTE anyway and the
>+		 * pending state is a property of the ITTE struct.
>+		 */
>+		its_free_itte(itte);
>+		ret = 0;
>+	}
>+
>+	spin_unlock(&its->lock);
>+	return ret;
>+}
>+
>+/* The MOVI command moves an ITTE to a different collection. */
>+static int vits_cmd_handle_movi(struct kvm *kvm, u64 *its_cmd)
>+{
>+	struct vgic_its *its = &kvm->arch.vgic.its;
>+	u32 device_id = its_cmd_get_deviceid(its_cmd);
>+	u32 event_id = its_cmd_get_id(its_cmd);
>+	u32 coll_id = its_cmd_get_collection(its_cmd);
>+	struct its_itte *itte;
>+	struct its_collection *collection;
>+	int ret;
>+
>+	spin_lock(&its->lock);
>+	itte = find_itte(kvm, device_id, event_id);
>+	if (!itte) {
>+		ret = E_ITS_MOVI_UNMAPPED_INTERRUPT;
>+		goto out_unlock;
>+	}
>+	if (!its_is_collection_mapped(itte->collection)) {
>+		ret = E_ITS_MOVI_UNMAPPED_COLLECTION;
>+		goto out_unlock;
>+	}
>+
>+	collection = find_collection(kvm, coll_id);
>+	if (!its_is_collection_mapped(collection)) {
>+		ret = E_ITS_MOVI_UNMAPPED_COLLECTION;
>+		goto out_unlock;
>+	}
>+
>+	itte->collection = collection;
>+	update_affinity(kvm, collection);
>+

Not planning to send this down to Physical ITS in case of VFIO for performance reasons?

>+out_unlock:
>+	spin_unlock(&its->lock);
>+	return ret;
>+}
>+
>+static void vits_init_collection(struct kvm *kvm,
>+				 struct its_collection *collection,
>+				 u32 coll_id)
>+{
>+	collection->collection_id = coll_id;
>+	collection->target_addr = COLLECTION_NOT_MAPPED;
>+
>+	list_add_tail(&collection->coll_list,
>+		&kvm->arch.vgic.its.collection_list);
>+}
>+
>+/* The MAPTI and MAPI commands map LPIs to ITTEs. */
>+static int vits_cmd_handle_mapi(struct kvm *kvm, u64 *its_cmd, u8 cmd)
>+{
>+	struct vgic_dist *dist = &kvm->arch.vgic;
>+	u32 device_id = its_cmd_get_deviceid(its_cmd);
>+	u32 event_id = its_cmd_get_id(its_cmd);
>+	u32 coll_id = its_cmd_get_collection(its_cmd);
>+	struct its_itte *itte, *new_itte;
>+	struct its_device *device;
>+	struct its_collection *collection, *new_coll;
>+	int lpi_nr;
>+	int ret = 0;
>+
>+	/* Preallocate possibly needed memory here outside of the lock */
>+	new_coll = kmalloc(sizeof(struct its_collection), GFP_KERNEL);
>+	new_itte = kzalloc(sizeof(struct its_itte), GFP_KERNEL);
>+
>+	spin_lock(&dist->its.lock);
>+
>+	device = find_its_device(kvm, device_id);
>+	if (!device) {
>+		ret = E_ITS_MAPTI_UNMAPPED_DEVICE;
>+		goto out_unlock;
>+	}
>+
>+	collection = find_collection(kvm, coll_id);
>+	if (!collection && !new_coll) {
>+		ret = -ENOMEM;
>+		goto out_unlock;
>+	}
>+
>+	if (cmd == GITS_CMD_MAPTI)
>+		lpi_nr = its_cmd_get_physical_id(its_cmd);
>+	else
>+		lpi_nr = event_id;
>+	if (lpi_nr < GIC_LPI_OFFSET ||
>+	    lpi_nr >= nr_idbits_propbase(dist->propbaser)) {
>+		ret = E_ITS_MAPTI_PHYSICALID_OOR;
>+		goto out_unlock;
>+	}
>+
>+	itte = find_itte(kvm, device_id, event_id);
>+	if (!itte) {
>+		if (!new_itte) {
>+			ret = -ENOMEM;
>+			goto out_unlock;
>+		}
>+		itte = new_itte;
>+
>+		itte->event_id	= event_id;
>+		list_add_tail(&itte->itte_list, &device->itt);
>+	} else {
>+		kfree(new_itte);
>+	}
>+
>+	if (!collection) {
>+		collection = new_coll;
>+		vits_init_collection(kvm, collection, coll_id);
>+	} else {
>+		kfree(new_coll);
>+	}
>+
>+	itte->collection = collection;
>+	itte->lpi = lpi_nr;
>+	itte->irq.intid = lpi_nr;
>+	INIT_LIST_HEAD(&itte->irq.ap_list);
>+	spin_lock_init(&itte->irq.irq_lock);
>+	itte->irq.vcpu = NULL;
>+	update_affinity(kvm, collection);
>+

Same here. 
>+out_unlock:
>+	spin_unlock(&dist->its.lock);
>+	if (ret) {
>+		kfree(new_coll);
>+		kfree(new_itte);
>+	}
>+	return ret;
>+}
>+
>+static void vits_unmap_device(struct kvm *kvm, struct its_device *device)
>+{
>+	struct its_itte *itte, *temp;
>+
>+	/*
>+	 * The spec says that unmapping a device with still valid
>+	 * ITTEs associated is UNPREDICTABLE. We remove all ITTEs,
>+	 * since we cannot leave the memory unreferenced.
>+	 */
>+	list_for_each_entry_safe(itte, temp, &device->itt, itte_list)
>+		its_free_itte(itte);
>+
>+	list_del(&device->dev_list);
>+	kfree(device);
>+}
>+
>+/* MAPD maps or unmaps a device ID to Interrupt Translation Tables (ITTs). */
>+static int vits_cmd_handle_mapd(struct kvm *kvm, u64 *its_cmd)
>+{
>+	struct vgic_its *its = &kvm->arch.vgic.its;
>+	bool valid = its_cmd_get_validbit(its_cmd);
>+	u32 device_id = its_cmd_get_deviceid(its_cmd);
>+	struct its_device *device, *new_device = NULL;
>+
>+	/* We preallocate memory outside of the lock here */
>+	if (valid) {
>+		new_device = kzalloc(sizeof(struct its_device), GFP_KERNEL);
>+		if (!new_device)
>+			return -ENOMEM;
>+	}
>+
>+	spin_lock(&its->lock);
>+
>+	device = find_its_device(kvm, device_id);
>+	if (device)
>+		vits_unmap_device(kvm, device);
>+
>+	/*
>+	 * The spec does not say whether unmapping a not-mapped device
>+	 * is an error, so we are done in any case.
>+	 */
>+	if (!valid)
>+		goto out_unlock;
>+
>+	device = new_device;
>+
>+	device->device_id = device_id;
>+	INIT_LIST_HEAD(&device->itt);
>+
>+	list_add_tail(&device->dev_list,
>+		      &kvm->arch.vgic.its.device_list);
>+
>+out_unlock:
>+	spin_unlock(&its->lock);
>+	return 0;
>+}
>+
>+/* The MAPC command maps collection IDs to redistributors. */
>+static int vits_cmd_handle_mapc(struct kvm *kvm, u64 *its_cmd)
>+{
>+	struct vgic_its *its = &kvm->arch.vgic.its;
>+	u16 coll_id;
>+	u32 target_addr;
>+	struct its_collection *collection, *new_coll = NULL;
>+	bool valid;
>+
>+	valid = its_cmd_get_validbit(its_cmd);
>+	coll_id = its_cmd_get_collection(its_cmd);
>+	target_addr = its_cmd_get_target_addr(its_cmd);
>+
>+	if (target_addr >= atomic_read(&kvm->online_vcpus))
>+		return E_ITS_MAPC_PROCNUM_OOR;
>+
>+	/* We preallocate memory outside of the lock here */
>+	if (valid) {
>+		new_coll = kmalloc(sizeof(struct its_collection), GFP_KERNEL);
>+		if (!new_coll)
>+			return -ENOMEM;
>+	}
>+
>+	spin_lock(&its->lock);
>+	collection = find_collection(kvm, coll_id);
>+
>+	if (!valid) {
>+		struct its_device *device;
>+		struct its_itte *itte;
>+		/*
>+		 * Clearing the mapping for that collection ID removes the
>+		 * entry from the list. If there wasn't any before, we can
>+		 * go home early.
>+		 */
>+		if (!collection)
>+			goto out_unlock;
>+
>+		for_each_lpi(device, itte, kvm)
>+			if (itte->collection &&
>+			    itte->collection->collection_id == coll_id)
>+				itte->collection = NULL;
>+
>+		list_del(&collection->coll_list);
>+		kfree(collection);
>+	} else {
>+		if (!collection)
>+			collection = new_coll;
>+		else
>+			kfree(new_coll);
>+
>+		vits_init_collection(kvm, collection, coll_id);
>+		collection->target_addr = target_addr;
>+		update_affinity(kvm, collection);
>+	}
>+
>+out_unlock:
>+	spin_unlock(&its->lock);
>+	return 0;
>+}
>+
>+/* The CLEAR command removes the pending state for a particular LPI. */
>+static int vits_cmd_handle_clear(struct kvm *kvm, u64 *its_cmd)
>+{
>+	struct vgic_its *its = &kvm->arch.vgic.its;
>+	u32 device_id;
>+	u32 event_id;
>+	struct its_itte *itte;
>+	int ret = 0;
>+
>+	device_id = its_cmd_get_deviceid(its_cmd);
>+	event_id = its_cmd_get_id(its_cmd);
>+
>+	spin_lock(&its->lock);
>+
>+	itte = find_itte(kvm, device_id, event_id);
>+	if (!itte) {
>+		ret = E_ITS_CLEAR_UNMAPPED_INTERRUPT;
>+		goto out_unlock;
>+	}
>+
>+	itte->irq.pending = false;
>+
>+out_unlock:
>+	spin_unlock(&its->lock);
>+	return ret;
>+}
>+
>+/* The INV command syncs the configuration bits from the memory tables. */
>+static int vits_cmd_handle_inv(struct kvm *kvm, u64 *its_cmd)
>+{
>+	struct vgic_dist *dist = &kvm->arch.vgic;
>+	u32 device_id;
>+	u32 event_id;
>+	struct its_itte *itte, *new_itte;
>+	gpa_t propbase;
>+	int ret;
>+	u8 prop;
>+
>+	device_id = its_cmd_get_deviceid(its_cmd);
>+	event_id = its_cmd_get_id(its_cmd);
>+
>+	spin_lock(&dist->its.lock);
>+	itte = find_itte(kvm, device_id, event_id);
>+	spin_unlock(&dist->its.lock);
>+	if (!itte)
>+		return E_ITS_INV_UNMAPPED_INTERRUPT;
>+
>+	/*
>+	 * We cannot read from guest memory inside the spinlock, so we
>+	 * need to re-read our tables to learn whether the LPI number we are
>+	 * using is still valid.
>+	 */
>+	do {
>+		propbase = BASER_BASE_ADDRESS(dist->propbaser);
>+		ret = kvm_read_guest(kvm, propbase + itte->lpi - GIC_LPI_OFFSET,
>+				     &prop, 1);
>+		if (ret)
>+			return ret;
>+
>+		spin_lock(&dist->its.lock);
>+		new_itte = find_itte(kvm, device_id, event_id);
>+		if (new_itte->lpi != itte->lpi) {
>+			itte = new_itte;
>+			spin_unlock(&dist->its.lock);
>+			continue;
>+		}
>+		update_lpi_config(kvm, itte, prop);
>+		spin_unlock(&dist->its.lock);

Not possible to call the function defined early and update all. How much performance gain will this be?
>+	} while (0);
>+	return 0;
>+}
>+
>+/* The INVALL command requests flushing of all IRQ data in this collection. */
>+static int vits_cmd_handle_invall(struct kvm *kvm, u64 *its_cmd)
>+{
>+	struct vgic_dist *dist = &kvm->arch.vgic;
>+	u64 prop_base_reg, pend_base_reg;
>+	u32 coll_id = its_cmd_get_collection(its_cmd);
>+	struct its_collection *collection;
>+	struct kvm_vcpu *vcpu;
>+
>+	collection = find_collection(kvm, coll_id);
>+	if (!its_is_collection_mapped(collection))
>+		return E_ITS_INVALL_UNMAPPED_COLLECTION;
>+
>+	vcpu = kvm_get_vcpu(kvm, collection->target_addr);
>+
>+	pend_base_reg = dist->pendbaser[vcpu->vcpu_id];
>+	prop_base_reg = dist->propbaser;
>+
>+	its_update_lpis_configuration(kvm, prop_base_reg);
>+	its_sync_lpi_pending_table(vcpu, pend_base_reg);
>+
>+	return 0;
>+}
>+
>+/* The MOVALL command moves all IRQs from one redistributor to another. */
>+static int vits_cmd_handle_movall(struct kvm *kvm, u64 *its_cmd)
>+{
>+	struct vgic_its *its = &kvm->arch.vgic.its;
>+	u32 target1_addr = its_cmd_get_target_addr(its_cmd);
>+	u32 target2_addr = its_cmd_mask_field(its_cmd, 3, 16, 32);
>+	struct its_collection *collection;
>+
>+	if (target1_addr >= atomic_read(&kvm->online_vcpus) ||
>+	    target2_addr >= atomic_read(&kvm->online_vcpus))
>+		return E_ITS_MOVALL_PROCNUM_OOR;
>+
>+	if (target1_addr == target2_addr)
>+		return 0;
>+
>+	spin_lock(&its->lock);
>+	list_for_each_entry(collection, &its->collection_list,
>+			    coll_list) {
>+		if (collection && collection->target_addr == target1_addr)
>+			collection->target_addr = target2_addr;
>+		update_affinity(kvm, collection);
>+	}

Not planning to send the commands down in case of VFIO? Think about NUMA systems and performance impact. 
>+
>+	spin_unlock(&its->lock);
>+	return 0;
>+}
>+
> /*
>  * This function is called with both the ITS and the distributor lock dropped,
>  * so the actual command handlers must take the respective locks when needed.
>  */
> static int vits_handle_command(struct kvm_vcpu *vcpu, u64 *its_cmd)
> {
>-	return -ENODEV;
>+	u8 cmd = its_cmd_get_command(its_cmd);
>+	int ret = -ENODEV;
>+
>+	switch (cmd) {
>+	case GITS_CMD_MAPD:
>+		ret = vits_cmd_handle_mapd(vcpu->kvm, its_cmd);
>+		break;
>+	case GITS_CMD_MAPC:
>+		ret = vits_cmd_handle_mapc(vcpu->kvm, its_cmd);
>+		break;
>+	case GITS_CMD_MAPI:
>+		ret = vits_cmd_handle_mapi(vcpu->kvm, its_cmd, cmd);
>+		break;
>+	case GITS_CMD_MAPTI:
>+		ret = vits_cmd_handle_mapi(vcpu->kvm, its_cmd, cmd);
>+		break;
>+	case GITS_CMD_MOVI:
>+		ret = vits_cmd_handle_movi(vcpu->kvm, its_cmd);
>+		break;
>+	case GITS_CMD_DISCARD:
>+		ret = vits_cmd_handle_discard(vcpu->kvm, its_cmd);
>+		break;
>+	case GITS_CMD_CLEAR:
>+		ret = vits_cmd_handle_clear(vcpu->kvm, its_cmd);
>+		break;
>+	case GITS_CMD_MOVALL:
>+		ret = vits_cmd_handle_movall(vcpu->kvm, its_cmd);
>+		break;
>+	case GITS_CMD_INV:
>+		ret = vits_cmd_handle_inv(vcpu->kvm, its_cmd);
>+		break;
>+	case GITS_CMD_INVALL:
>+		ret = vits_cmd_handle_invall(vcpu->kvm, its_cmd);
>+		break;
>+	case GITS_CMD_SYNC:
>+		/* we ignore this command: we are in sync all of the time */
>+		ret = 0;
>+		break;
>+	}
>+
>+	return ret;
> }
> 
> static int vgic_mmio_read_its_cbaser(struct kvm_vcpu *vcpu,
>-- 
>2.7.3
>
>_______________________________________________
>kvmarm mailing list
>kvmarm at lists.cs.columbia.edu
>https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

From robert.jarzmik at free.fr  Thu May  5 12:14:40 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Thu, 05 May 2016 21:14:40 +0200
Subject: [RFC PATCH 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <20160504162200.GX6292@sirena.org.uk> (Mark Brown's message of
 "Wed, 4 May 2016 17:22:00 +0100")
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
 <20160503162938.GT6292@sirena.org.uk> <87twiforl3.fsf@belgarion.home>
 <20160504162200.GX6292@sirena.org.uk>
Message-ID: <87lh3opba7.fsf@belgarion.home>

Mark Brown <broonie at kernel.org> writes:

> On Tue, May 03, 2016 at 09:43:20PM +0200, Robert Jarzmik wrote:
>
>> You probably mean the BITCLK clock.
>
>> What is a bit pesky about this clock is that it can either be mastered by
>> digital controller and the codec is a slave, or the other way around.
>
> That's a bit surprising - I've never encountered a system that
> impelemnts this, it may be permitted by the spec but it's always the
> CODEC.  The master clock from the CODEC is often provided by the SoC but
> I've not seen systems where anything other than the CODEC drives the
> actual AC'97 bus.

Ok, so let's assume a one direction. I'll have a look how I could add this clock
to the probe() exactly as amba_probe() does.

> It's not really adding anything though, it's just clumsy wording on
> their part - it's not like we need to distinguish this from analogue
> or any other type of AC'97 controllers.
>
>> Now if you prefer "ac97_controller" or something like that, that's as you wish,
>> the name does not matter that much to me ;)
>
> Yes.
Okay, let me add this to my todo list for v2.
I already have suspend/resume/pm_suspend/pm_resume.

Cheers.

-- 
Robert


From f.fainelli at gmail.com  Thu May  5 12:14:58 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Thu,  5 May 2016 12:14:58 -0700
Subject: [PATCH v2 0/2] pci: host: Broadcom STB PCIE RC controller support
Message-ID: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>

Hi all,

This patch series adds support for Broadcom STB SoC's PCIe root complex driver.

This was primarily tested on BCM7445 (ARM) and BCM7435 (MIPS).

Jim is the original author, and I picked up our downstream 4.1 driver and
updated it to utilize the non-ARM hw_pci functions as well as made some
stylistic changes.

Thanks!

Jim Quinlan (2):
  Documentation: DT: bindings: Add Broadcom STB PCIe bindings
  pci: host: Add Broadcom STB PCIE RC controller

 .../devicetree/bindings/pci/brcm,brcmstb-pcie.txt  |  98 +++
 MAINTAINERS                                        |   1 +
 drivers/pci/host/Kconfig                           |  17 +
 drivers/pci/host/Makefile                          |   2 +
 drivers/pci/host/pcie-brcmstb-msi.c                | 305 ++++++++
 drivers/pci/host/pcie-brcmstb.c                    | 772 +++++++++++++++++++++
 drivers/pci/host/pcie-brcmstb.h                    | 169 +++++
 7 files changed, 1364 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
 create mode 100644 drivers/pci/host/pcie-brcmstb-msi.c
 create mode 100644 drivers/pci/host/pcie-brcmstb.c
 create mode 100644 drivers/pci/host/pcie-brcmstb.h

-- 
2.1.0



From f.fainelli at gmail.com  Thu May  5 12:14:59 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Thu,  5 May 2016 12:14:59 -0700
Subject: [PATCH v2 1/2] Documentation: DT: bindings: Add Broadcom STB PCIe
 bindings
In-Reply-To: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1462475700-1654-2-git-send-email-f.fainelli@gmail.com>

From: Jim Quinlan <jim2101024 at gmail.com>

This patchs adds the Device Tree bindings for the Broadcom STB PCIe root
complex hardware.

Signed-off-by: Jim Quinlan <jim2101024 at gmail.com>
Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
Changes in v2:

- rewrite the binding document almost from scratch to include many more
  references to existing documents
- describe missing properties
- give better examples

 .../devicetree/bindings/pci/brcm,brcmstb-pcie.txt  | 98 ++++++++++++++++++++++
 1 file changed, 98 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt

diff --git a/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
new file mode 100644
index 000000000000..3682b0f0bc26
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
@@ -0,0 +1,98 @@
+Broadcom STB PCIe Host Controller Device Tree Bindings
+
+This document describes the binding of the PCIe Root Complex hardware found in
+Broadcom Set Top Box System-on-Chips such as BCM7425 (MIPS), BCM7435 (MIPS) and
+BCM7445 (ARMv7).
+
+Required properties:
+- compatible: must be one of: "brcm,bcm7425-pcie"
+			      "brcm,bcm7435-pcie"
+			      "brcm,bcm7445-pcie"
+
+- reg: specifies the physical base address of the controller registers and
+  its length
+
+- interrupt-parent: must be a reference (phandle) to the parent interrupt
+  controller in the system (7038-l1-intc on MIPS, GIC on ARM/ARM64)
+
+- interrrupts: first interrupt must be the Level 1 interrupt number corresponding
+  to the main PCIe RC interrupt, second interrupt must be the MSI interrupt
+  See the interrupt-parent documentation for the number of cells and their meaning:
+  MIPS: Documentation/devicetree/bindings/interrupt-controller/brcm,bcm7038-l1-intc.txt
+  ARM/ARM64: Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
+
+- interrupt-names: must be "pcie", and if present "msi"
+
+- interrupt-map: see pci.txt
+
+- interrupt-map-mask: see pci.txt
+
+- #address-cells: must be set to <3>, see pci.txt
+
+- #size-cells: must be set to <2>, see pci.txt
+
+- ranges: ranges for the PCI outbound windows, no I/O or prefetchable windows
+  must be specified here, only non-prefetchable. 32-bits windows or 64-bits
+  windows are allowed based on the host processor's capabilities (ARM w/ LPAE,
+  ARM64).
+
+- #interrupt-cells: set to <1>, see pci.txt
+
+- brcm,log2-scb-sizes: log2 size of the SCB window that is mapped to PCIe space
+  there must be exactly one value per memory controller present in the system
+  (ranges from 1 to 3)
+
+Optional properties:
+
+- msi-controller: indicates that this is a MSI controller node (when supported)
+
+- clocks: phandle to the functional clock that feeds into the PCIe RC block
+
+- clock-names: the name(s) of the clocks specified in 'clocks'.  Note
+  that if the 'clocks' property is given, 'clock-names' is mandatory,
+  and the name of the clock is expected to be "pcie".
+
+- brcm,ssc: boolean that indicates usage of spread-spectrum clocking
+
+- brcm,gen: integer that indicates desired forced generation of link: 1 => 2.5
+  Gbps, 2 => 5.0 Gbps, 3 => 8.0 Gbps. Will override the auto-negotation if
+  specified.
+
+- <*>-supply: see Documentation/devicetree/bindings/regulator/regulator.txt
+
+- <*>-supply-names: see Documentation/devicetree/bindings/regulator/regulator.txt
+
+Example Node:
+
+This example assumes that the top-level #address-cells = <2> and #size-cells =
+<2>, e.g: ARM LPAE configuration.
+
+	pcie0: pcie-controller at f0460000 {
+		reg = <0x0 0xf0460000 0x0 0x9310>;
+		interrupts = <0x0 0x33 0x4>, <0x0 0x34, 0x4>;
+		interrupt-names = "pcie", "msi";
+		compatible = "brcm,bcm7445-pcie";
+		#address-cells = <3>;
+		#size-cells = <2>;
+
+		/* Two non-prefetchable 32-bits memory space, each of 128MB
+ 		 * with the following mapping:
+		 * PCIe address		=> CPU physical address space
+		 * 0x00_0000_0000	=> 0x00_C000_0000
+		 * 0x00_0800_0000	=> 0x00_C800_0000
+		 */
+		ranges = <0x02000000 0x00000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x08000000>,
+			 <0x02000000 0x00000000 0x08000000 0x00000000 0xc8000000 0x00000000 0x08000000>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0 0 0 1 &intc 47 3
+				 0 0 0 2 &intc 48 3
+				 0 0 0 3 &intc 49 3
+				 0 0 0 4 &intc 50 3>;
+		clocks = <&pcie0>;
+		clock-names = "pcie";
+		brcm,ssc;
+		brcm,log2-scb-sizes = <0x1e 0x1e 0x1e>;
+		vreg-wifi-pwr-supply-names = "vreg-wifi-pwr";
+		vreg-wifi-pwr-supply = <&vreg-wifi-pwr>;
+	};
-- 
2.1.0



From javier at osg.samsung.com  Thu May  5 12:14:55 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 15:14:55 -0400
Subject: [RFC v2 06/13] power: pwrseq: Generalize mmc_pwrseq operations by
 removing mmc prefix
In-Reply-To: <1462451666-17945-7-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-7-git-send-email-k.kozlowski@samsung.com>
Message-ID: <2c763750-9b32-d782-e5a2-4a259c085ed0@osg.samsung.com>

Hello Krzysztof,

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> The power sequence hooks (mmc_pwrseq_pre_power_on(),
> mmc_pwrseq_post_power_on() and mmc_pwrseq_power_off()) can be made more
> generic to allow re-use in other subsystems. They do not need to take
> pointer to struct mmc_host but instead the struct pwrseq should be
> sufficient.
> 
> Remove the "mmc" prefix and use the pointer to struct pwrseq as
> argument.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From f.fainelli at gmail.com  Thu May  5 12:15:00 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Thu,  5 May 2016 12:15:00 -0700
Subject: [PATCH v2 2/2] pci: host: Add Broadcom STB PCIE RC controller
In-Reply-To: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1462475700-1654-3-git-send-email-f.fainelli@gmail.com>

From: Jim Quinlan <jim2101024 at gmail.com>

This patch adds support for Broadcom's STB SoC PCIE root complex
controller. This controller can be found in MIPS-based chips such as
BCM7425, 7429 and 7435 and ARM-based SoCs such as BCM7445.

This driver enables support for MSI, and S2/S3 suspend/resume modes.

Signed-off-by: Jim Quinlan <jim2101024 at gmail.com>
Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
Changes in v2:

- separate MSI logic into a different file
- simplify the code to utilize less bookeeping variables
- replaced fixed delays with sleeps instead
- introduce helper functions to deal with read/write config and reset
- get rid of the custom window variables, walk the resource list instead
- utilize OF aliases to determine PCIe root complex id

 MAINTAINERS                         |   1 +
 drivers/pci/host/Kconfig            |  17 +
 drivers/pci/host/Makefile           |   2 +
 drivers/pci/host/pcie-brcmstb-msi.c | 305 ++++++++++++++
 drivers/pci/host/pcie-brcmstb.c     | 769 ++++++++++++++++++++++++++++++++++++
 drivers/pci/host/pcie-brcmstb.h     | 160 ++++++++
 6 files changed, 1254 insertions(+)
 create mode 100644 drivers/pci/host/pcie-brcmstb-msi.c
 create mode 100644 drivers/pci/host/pcie-brcmstb.c
 create mode 100644 drivers/pci/host/pcie-brcmstb.h

diff --git a/MAINTAINERS b/MAINTAINERS
index ecbb2f6a3ba0..503a2a4fa4ad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2458,6 +2458,7 @@ S:	Maintained
 F:	arch/arm/mach-bcm/*brcmstb*
 F:	arch/arm/boot/dts/bcm7*.dts*
 F:	drivers/bus/brcmstb_gisb.c
+F:	drivers/pci/host/pcie-brcmstb*.[ch]
 N:	brcmstb
 
 BROADCOM BMIPS MIPS ARCHITECTURE
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 7a0780d56d2d..0964aa0d36e4 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -143,6 +143,23 @@ config PCI_VERSATILE
 	bool "ARM Versatile PB PCI controller"
 	depends on ARCH_VERSATILE
 
+config PCIE_BRCMSTB
+	tristate "Broadcom STB PCIe controller"
+	depends on OF && (ARCH_BRCMSTB || BMIPS_GENERIC)
+	default ARCH_BRCMSTB || BMIPS_GENERIC
+	help
+	  Say Y here if you want to use the Broadcom STB PCIe controller. This
+	  controller supports Broadcom's STB SoCs such a 7425, 7429, 7435 and
+	  7445 and compatible chips.
+
+config PCIE_BRCMSTB_MSI
+	bool "Broadcom STB PCIe MSI feature"
+	depends on PCIE_BRCMSTB && PCI_MSI
+	select PCI_MSI_IRQ_DOMAIN
+	default PCIE_BRCMSTB
+	help
+	  Say Y here if you want PCIe MSI support for the Broadcom STB PCIe RC.
+
 config PCIE_IPROC
 	tristate
 	help
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index d85b5faf9bbc..f51ef13454b4 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -18,6 +18,8 @@ obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
 obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
 obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
 obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
+obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
+obj-$(CONFIG_PCIE_BRCMSTB_MSI) += pcie-brcmstb-msi.o
 obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
 obj-$(CONFIG_PCIE_IPROC_MSI) += pcie-iproc-msi.o
 obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
diff --git a/drivers/pci/host/pcie-brcmstb-msi.c b/drivers/pci/host/pcie-brcmstb-msi.c
new file mode 100644
index 000000000000..5aa78a10833c
--- /dev/null
+++ b/drivers/pci/host/pcie-brcmstb-msi.c
@@ -0,0 +1,305 @@
+/*
+ * Broadcom STB PCIe root complex MSI driver
+ *
+ * Copyright (C) 2009 - 2016 Broadcom
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/msi.h>
+#include <linux/printk.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/module.h>
+#include <linux/irqdomain.h>
+#include <linux/string.h>
+#include <linux/sizes.h>
+
+#include "pcie-brcmstb.h"
+
+#define BRCM_INT_PCI_MSI_NR		32
+#define BRCM_PCIE_HW_REV_33		0x0303
+#define BRCM_MSI_TARGET_ADDR_LO		0x0
+#define BRCM_MSI_TARGET_ADDR_HI		0xffffffff
+
+struct brcm_msi {
+	struct irq_domain *domain;
+	struct irq_chip irq_chip;
+	struct msi_controller chip;
+	struct brcm_pcie *pcie;
+	struct mutex lock;
+	int irq;
+	/* intr_base is the base pointer for interrupt status/set/clr regs */
+	void __iomem *intr_base;
+	/* intr_legacy_mask indicates how many bits are MSI interrupts */
+	u32 intr_legacy_mask;
+	/* intr_legacy_offset indicates bit position of MSI_01 */
+	u32 intr_legacy_offset;
+	/* used indicates which MSI interrupts have been alloc'd */
+	unsigned long used;
+	/* working indicates that on boot we have brought up MSI */
+	bool working;
+};
+
+static inline struct brcm_msi *to_brcm_msi(struct msi_controller *chip)
+{
+	return container_of(chip, struct brcm_msi, chip);
+}
+
+static int brcm_msi_alloc(struct brcm_msi *chip)
+{
+	int msi;
+
+	mutex_lock(&chip->lock);
+	msi = ~chip->used ? ffz(chip->used) : -1;
+
+	if (msi >= 0 && msi < BRCM_INT_PCI_MSI_NR)
+		chip->used |= (1 << msi);
+	else
+		msi = -ENOSPC;
+
+	mutex_unlock(&chip->lock);
+	return msi;
+}
+
+static void brcm_msi_free(struct brcm_msi *chip, unsigned long irq)
+{
+	mutex_lock(&chip->lock);
+	chip->used &= ~(1 << irq);
+	mutex_unlock(&chip->lock);
+}
+
+static irqreturn_t brcm_pcie_msi_irq(int irq, void *data)
+{
+	struct brcm_pcie *pcie = data;
+	struct brcm_msi *msi = pcie->msi;
+	unsigned long status;
+
+	status = bpcie_readl(msi->intr_base + STATUS) & msi->intr_legacy_mask;
+
+	if (!status)
+		return IRQ_NONE;
+
+	while (status) {
+		unsigned int index = ffs(status) - 1;
+		unsigned int irq;
+
+		/* clear the interrupt */
+		bpcie_writel(1 << index, msi->intr_base + CLR);
+		status &= ~(1 << index);
+
+		/* Account for legacy interrupt offset */
+		index -= msi->intr_legacy_offset;
+
+		irq = irq_find_mapping(msi->domain, index);
+		if (irq) {
+			if (msi->used & (1 << index))
+				generic_handle_irq(irq);
+			else
+				dev_info(pcie->dev, "unhandled MSI %d\n",
+					 index);
+		} else {
+			/* Unknown MSI, just clear it */
+			dev_dbg(pcie->dev, "unexpected MSI\n");
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int brcm_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
+			      struct msi_desc *desc)
+{
+	struct brcm_msi *msi = to_brcm_msi(chip);
+	struct brcm_pcie *pcie = msi->pcie;
+	struct msi_msg msg;
+	unsigned int irq;
+	int hwirq;
+	u32 data;
+
+	hwirq = brcm_msi_alloc(msi);
+	if (hwirq < 0)
+		return hwirq;
+
+	irq = irq_create_mapping(msi->domain, hwirq);
+	if (!irq) {
+		brcm_msi_free(msi, hwirq);
+		return -EINVAL;
+	}
+
+	irq_set_msi_desc(irq, desc);
+
+	msg.address_lo = BRCM_MSI_TARGET_ADDR_LO;
+	msg.address_hi = BRCM_MSI_TARGET_ADDR_HI;
+	data = bpcie_readl(pcie->base + PCIE_MISC_MSI_DATA_CONFIG);
+	msg.data = ((data >> 16) & (data & 0xffff)) | hwirq;
+	wmb(); /* just being cautious */
+	write_msi_msg(irq, &msg);
+
+	return 0;
+}
+
+static void brcm_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
+{
+	struct brcm_msi *msi = to_brcm_msi(chip);
+	struct irq_data *d = irq_get_irq_data(irq);
+
+	brcm_msi_free(msi, d->hwirq);
+}
+
+static int brcm_msi_map(struct irq_domain *domain, unsigned int irq,
+			irq_hw_number_t hwirq)
+{
+	struct brcm_pcie *pcie = domain->host_data;
+
+	irq_set_chip_and_handler(irq, &pcie->msi->irq_chip, handle_simple_irq);
+	irq_set_chip_data(irq, domain->host_data);
+
+	return 0;
+}
+
+static const struct irq_domain_ops msi_domain_ops = {
+	.map = brcm_msi_map,
+};
+
+int brcm_pcie_enable_msi(struct brcm_pcie *pcie, int nr)
+{
+	static const char brcm_msi_name[] = "brcmstb_pcieX_msi";
+	struct brcm_msi *msi;
+	u32 data_val;
+	char *name;
+	int err;
+
+	pcie->msi = devm_kzalloc(pcie->dev, sizeof(*msi), GFP_KERNEL);
+	if (!pcie->msi)
+		return -ENODEV;
+
+	msi = pcie->msi;
+	msi->pcie = pcie;
+
+	if (!pcie->suspended) {
+		/* We are only here on cold boot */
+		mutex_init(&msi->lock);
+
+		msi->chip.dev = pcie->dev;
+		msi->chip.setup_irq = brcm_msi_setup_irq;
+		msi->chip.teardown_irq = brcm_msi_teardown_irq;
+
+		/* We have multiple RC controllers.  We may have as many
+		 * MSI controllers for them.  We want each to have a
+		 * unique name, so we go to the trouble of having an
+		 * irq_chip per RC (instead of one for all of them).
+		 */
+		name = devm_kzalloc(pcie->dev, sizeof(brcm_msi_name),
+				    GFP_KERNEL);
+		if (name) {
+			char *p;
+
+			strcpy(name, brcm_msi_name);
+			p = strchr(name, 'X');
+			if (p)
+				*p = '0' + nr;
+			msi->irq_chip.name = name;
+		} else {
+			msi->irq_chip.name = brcm_msi_name;
+		}
+
+		msi->irq_chip.irq_enable = unmask_msi_irq;
+		msi->irq_chip.irq_disable = mask_msi_irq;
+		msi->irq_chip.irq_mask = mask_msi_irq;
+		msi->irq_chip.irq_unmask = unmask_msi_irq;
+
+		msi->domain =
+			irq_domain_add_linear(pcie->dn, BRCM_INT_PCI_MSI_NR,
+					      &msi_domain_ops, pcie);
+		if (!msi->domain) {
+			dev_err(pcie->dev,
+				"failed to create IRQ domain for MSI\n");
+			return -ENOMEM;
+		}
+
+		err = devm_request_irq(pcie->dev, msi->irq, brcm_pcie_msi_irq,
+				       IRQF_SHARED, msi->irq_chip.name,
+				       pcie);
+		if (err < 0) {
+			dev_err(pcie->dev,
+				"failed to request IRQ (%d) for MSI\n",	err);
+			goto msi_en_err;
+		}
+
+		if (pcie->rev >= BRCM_PCIE_HW_REV_33) {
+			msi->intr_base = pcie->base + PCIE_MSI_INTR2_BASE;
+			/* This version of PCIe hw has only 32 intr bits
+			 * starting at bit position 0.
+			 */
+			msi->intr_legacy_mask = 0xffffffff;
+			msi->intr_legacy_offset = 0x0;
+			msi->used = 0x0;
+
+		} else {
+			msi->intr_base = pcie->base + PCIE_INTR2_CPU_BASE;
+			/* This version of PCIe hw has only 8 intr bits starting
+			 * at bit position 24.
+			 */
+			msi->intr_legacy_mask = 0xff000000;
+			msi->intr_legacy_offset = 24;
+			msi->used = 0xffffff00;
+		}
+		msi->working = true;
+	}
+
+	/* If we are here, and msi->working is false, it means that we've
+	 * already tried and failed to bring up MSI.  Just return 0
+	 * since there is nothing to be done.
+	 */
+	if (!msi->working)
+		return 0;
+
+	if (pcie->rev >= BRCM_PCIE_HW_REV_33) {
+		/* ffe0 -- least sig 5 bits are 0 indicating 32 msgs
+		 * 6540 -- this is our arbitrary unique data value
+		 */
+		data_val = 0xffe06540;
+	} else {
+		/* fff8 -- least sig 3 bits are 0 indicating 8 msgs
+		 * 6540 -- this is our arbitrary unique data value
+		 */
+		data_val = 0xfff86540;
+	}
+
+	/* Make sure we are not masking MSIs.  Note that MSIs can be masked,
+	 * but that occurs on the PCIe EP device
+	 */
+	bpcie_writel(0xffffffff & msi->intr_legacy_mask,
+		     msi->intr_base + MASK_CLR);
+
+	/* The 0 bit of BRCM_MSI_TARGET_ADDR_LO is repurposed to MSI enable,
+	 * which we set to 1.
+	 */
+	bpcie_writel(BRCM_MSI_TARGET_ADDR_LO | 1, pcie->base
+		     + PCIE_MISC_MSI_BAR_CONFIG_LO);
+	bpcie_writel(BRCM_MSI_TARGET_ADDR_HI, pcie->base
+		     + PCIE_MISC_MSI_BAR_CONFIG_HI);
+	bpcie_writel(data_val, pcie->base + PCIE_MISC_MSI_DATA_CONFIG);
+
+	return 0;
+
+msi_en_err:
+	irq_domain_remove(msi->domain);
+	return err;
+}
+
+void brcm_pcie_msi_chip_set(struct brcm_pcie *pcie)
+{
+	pcie->bus->msi = &pcie->msi->chip;
+}
diff --git a/drivers/pci/host/pcie-brcmstb.c b/drivers/pci/host/pcie-brcmstb.c
new file mode 100644
index 000000000000..57011e8e772a
--- /dev/null
+++ b/drivers/pci/host/pcie-brcmstb.c
@@ -0,0 +1,769 @@
+/*
+ * Broadcom STB PCIe root complex driver
+ *
+ * Copyright (C) 2009 - 2016 Broadcom
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/msi.h>
+#include <linux/printk.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/sizes.h>
+
+#include "pcie-brcmstb.h"
+
+static void wr_fld(void __iomem *p, u32 mask, int shift, u32 val)
+{
+	u32 reg;
+
+	reg = bpcie_readl(p);
+	reg = (reg & ~mask) | (val << shift);
+	bpcie_writel(reg, p);
+}
+
+static void wr_fld_rb(void __iomem *p, u32 mask, int shift, u32 val)
+{
+	wr_fld(p, mask, shift, val);
+	(void) bpcie_readl(p);
+}
+
+/* Helper macro to define low-level operations for read/write/reset */
+#define PCIE_LL_OPS(name, def) \
+static void name##_pcie_rgr1_sw_init(struct brcm_pcie *pcie, u32 mask,	\
+				      int shift, u32 val)		\
+{									\
+	wr_fld_rb(pcie->base + def##PCIE_RGR1_SW_INIT_1, mask, shift, val); \
+}									\
+static u32 name##_pcie_read_config(struct brcm_pcie *pcie, int cfg_idx) \
+{									\
+	bpcie_writel(cfg_idx, pcie->base + def##PCIE_EXT_CFG_INDEX);	\
+	bpcie_readl(pcie->base + def##PCIE_EXT_CFG_INDEX);		\
+	return bpcie_readl(pcie->base + def##PCIE_EXT_CFG_DATA);	\
+}									\
+static void name##_pcie_write_config(struct brcm_pcie *pcie,		\
+				     int cfg_idx, u32 val)		\
+{									\
+	bpcie_writel(cfg_idx, pcie->base + def##PCIE_EXT_CFG_INDEX);	\
+	bpcie_readl(pcie->base + def##PCIE_EXT_CFG_INDEX);		\
+	bpcie_writel(val, pcie->base + def##PCIE_EXT_CFG_DATA);		\
+	bpcie_readl(pcie->base + def##PCIE_EXT_CFG_DATA);		\
+}
+
+PCIE_LL_OPS(bcm7425, BCM7425_);
+/* Optional second argument */
+PCIE_LL_OPS(gen,);
+
+static const struct brcm_pcie_cfg_data bcm7425_cfg = {
+	.type = BCM7425,
+	.ops = {
+		.read_config = bcm7425_pcie_read_config,
+		.write_config = bcm7425_pcie_write_config,
+		.rgr1_sw_init = bcm7425_pcie_rgr1_sw_init,
+	},
+};
+
+static const struct brcm_pcie_cfg_data bcm7435_cfg = {
+	.type = BCM7435,
+	.ops = {
+		.read_config = gen_pcie_read_config,
+		.write_config = gen_pcie_write_config,
+		.rgr1_sw_init = gen_pcie_rgr1_sw_init,
+	},
+};
+
+static const struct brcm_pcie_cfg_data generic_cfg = {
+	.type = GENERIC,
+	.ops = {
+		.read_config = gen_pcie_read_config,
+		.write_config = gen_pcie_write_config,
+		.rgr1_sw_init = gen_pcie_rgr1_sw_init,
+	},
+};
+
+#if defined(__BIG_ENDIAN)
+#define	DATA_ENDIAN		2	/* PCI->DDR inbound accesses */
+#define MMIO_ENDIAN		2	/* CPU->PCI outbound accesses */
+#else
+#define	DATA_ENDIAN		0
+#define MMIO_ENDIAN		0
+#endif
+
+/* negative return value indicates error */
+static int mdio_read(void __iomem *base, u8 phyad, u8 regad)
+{
+	u32 data = ((phyad & 0xf) << 16)
+		| (regad & 0x1f)
+		| 0x100000;
+
+	bpcie_writel(data, base + PCIE_RC_DL_MDIO_ADDR);
+	bpcie_readl(base + PCIE_RC_DL_MDIO_ADDR);
+
+	data = bpcie_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
+	if (!(data & 0x80000000)) {
+		msleep(1);
+		data = bpcie_readl(base + PCIE_RC_DL_MDIO_RD_DATA);
+	}
+
+	return (data & 0x80000000) ? (data & 0xffff) : -EIO;
+}
+
+/* negative return value indicates error */
+static int mdio_write(void __iomem *base, u8 phyad, u8 regad, u16 wrdata)
+{
+	u32 data = ((phyad & 0xf) << 16) | (regad & 0x1f);
+
+	bpcie_writel(data, base + PCIE_RC_DL_MDIO_ADDR);
+	bpcie_readl(base + PCIE_RC_DL_MDIO_ADDR);
+
+	bpcie_writel(0x80000000 | wrdata, base + PCIE_RC_DL_MDIO_WR_DATA);
+	data = bpcie_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
+	if (!(data & 0x80000000)) {
+		msleep(1);
+		data = bpcie_readl(base + PCIE_RC_DL_MDIO_WR_DATA);
+	}
+
+	return (data & 0x80000000) ? 0 : -EIO;
+}
+
+/* configures device for ssc mode; negative return value indicates error */
+static int set_ssc(void __iomem *base)
+{
+	int tmp;
+	u16 wrdata;
+
+	tmp = mdio_write(base, 0, 0x1f, 0x1100);
+	if (tmp < 0)
+		return tmp;
+
+	tmp = mdio_read(base, 0, 2);
+	if (tmp < 0)
+		return tmp;
+
+	wrdata = ((u16)tmp & 0x3fff) | 0xc000;
+	tmp = mdio_write(base, 0, 2, wrdata);
+	if (tmp < 0)
+		return tmp;
+
+	msleep(1);
+	tmp = mdio_read(base, 0, 1);
+	if (tmp < 0)
+		return tmp;
+
+	return 0;
+}
+
+
+/* returns 0 if in ssc mode, 1 if not, <0 on error */
+static int is_ssc(void __iomem *base)
+{
+	int tmp = mdio_write(base, 0, 0x1f, 0x1100);
+
+	if (tmp < 0)
+		return tmp;
+	tmp = mdio_read(base, 0, 1);
+	if (tmp < 0)
+		return tmp;
+	return (tmp & 0xc00) == 0xc00 ? 0 : 1;
+}
+
+/* limits operation to a specific generation (1, 2, or 3) */
+static void set_gen(void __iomem *base, int gen)
+{
+	wr_fld(base + PCIE_RC_CFG_PCIE_LINK_CAPABILITY, 0xf, 0, gen);
+	wr_fld(base + PCIE_RC_CFG_PCIE_LINK_STATUS_CONTROL_2, 0xf, 0, gen);
+}
+
+static void set_pcie_outbound_win(void __iomem *base, unsigned int win,
+				  u64 start, u64 len)
+{
+	u32 tmp;
+
+	bpcie_writel((u32)(start) + MMIO_ENDIAN,
+		     base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + (win * 8));
+	bpcie_writel((u32)(start >> 32),
+		     base + PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + (win * 8));
+	tmp = ((((u32)start) >> 20) << 4)
+		| (((((u32)start) + ((u32)len) - 1) >> 20) << 20);
+	bpcie_writel(tmp, base +
+		     PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT + (win * 4));
+}
+
+static int is_pcie_link_up(struct brcm_pcie *pcie)
+{
+	void __iomem *base = pcie->base;
+	u32 val = bpcie_readl(base + PCIE_MISC_PCIE_STATUS);
+
+	return ((val & 0x30) == 0x30) ? 1 : 0;
+}
+
+static int brcm_pcie_setup_early(struct brcm_pcie *pcie)
+{
+	void __iomem *base = pcie->base;
+	struct resource_entry *win;
+	unsigned int scb_size_val;
+	struct resource *r;
+	int i, ret;
+
+	/* reset the bridge and the endpoint device
+	 * field: PCIE_BRIDGE_SW_INIT = 1
+	 */
+	brcm_pcie_rgr1_sw_init(pcie, 0x00000002, 1, 1);
+
+	/* field: PCIE_SW_PERST = 1 */
+	brcm_pcie_rgr1_sw_init(pcie, 0x00000001, 0, 1);
+
+	/* delay 100us */
+	usleep_range(100, 1000);
+
+	/* take the bridge out of reset
+	 * field: PCIE_BRIDGE_SW_INIT = 0
+	 */
+	brcm_pcie_rgr1_sw_init(pcie, 0x00000002, 1, 0);
+
+	/* Grab the PCIe hw revision number */
+	pcie->rev = bpcie_readl(base + PCIE_MISC_REVISION) & 0xffff;
+
+	/* enable SCB_MAX_BURST_SIZE | CSR_READ_UR_MODE | SCB_ACCESS_EN */
+	if (pcie->type == GENERIC)
+		bpcie_writel(0x81e03000, base + PCIE_MISC_MISC_CTRL);
+	else
+		bpcie_writel(0x00103000, base + PCIE_MISC_MISC_CTRL);
+
+	i = 0;
+	resource_list_for_each_entry(win, &pcie->resource) {
+		r = win->res;
+
+		if (!r->flags)
+			continue;
+
+		switch (resource_type(r)) {
+		case IORESOURCE_MEM:
+			/* Program PCIe outbound windows */
+			set_pcie_outbound_win(base, i, r->start,
+					      resource_size(r));
+			i++;
+
+			/* Request memory region resources the first time */
+			if (!pcie->bridge_setup_done) {
+				ret = devm_request_resource(pcie->dev,
+							    &iomem_resource,
+							    r);
+				if (ret)
+					return ret;
+			}
+
+			if (i == BRCM_NUM_PCI_OUT_WINS)
+				dev_warn(pcie->dev,
+					 "exceeded number of windows\n");
+			break;
+
+		default:
+			/* No support for IORESOURCE_IO or IORESOURCE_BUS */
+			continue;
+		}
+	}
+
+	/* set up 4GB PCIE->SCB memory window on BAR2 */
+	bpcie_writel(0x00000011, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
+	bpcie_writel(0x00000000, base + PCIE_MISC_RC_BAR2_CONFIG_HI);
+
+	/* field: SCB0_SIZE, default = 0xf (1 GB) */
+	scb_size_val = pcie->scb_size_vals[0] ? pcie->scb_size_vals[0] : 0xf;
+	wr_fld(base + PCIE_MISC_MISC_CTRL, 0xf8000000, 27, scb_size_val);
+
+	/* field: SCB1_SIZE, default = 0xf (1 GB) */
+	if (pcie->num_memc > 1) {
+		scb_size_val = pcie->scb_size_vals[1]
+			? pcie->scb_size_vals[1] : 0xf;
+		wr_fld(base + PCIE_MISC_MISC_CTRL, 0x07c00000,
+		       22, scb_size_val);
+	}
+
+	/* field: SCB2_SIZE, default = 0xf (1 GB) */
+	if (pcie->num_memc > 2) {
+		scb_size_val = pcie->scb_size_vals[2]
+			? pcie->scb_size_vals[2] : 0xf;
+		wr_fld(base + PCIE_MISC_MISC_CTRL, 0x0000001f,
+		       0, scb_size_val);
+	}
+
+	/* disable the PCIE->GISB memory window */
+	bpcie_writel(0x00000000, base + PCIE_MISC_RC_BAR1_CONFIG_LO);
+
+	/* disable the PCIE->SCB memory window */
+	bpcie_writel(0x00000000, base + PCIE_MISC_RC_BAR3_CONFIG_LO);
+
+	if (!pcie->suspended) {
+		/* clear any interrupts we find on boot */
+		bpcie_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + CLR);
+		(void) bpcie_readl(base + PCIE_INTR2_CPU_BASE + CLR);
+	}
+
+	/* Mask all interrupts since we are not handling any yet */
+	bpcie_writel(0xffffffff, base + PCIE_INTR2_CPU_BASE + MASK_SET);
+	(void) bpcie_readl(base + PCIE_INTR2_CPU_BASE + MASK_SET);
+
+	if (pcie->ssc)
+		if (set_ssc(base))
+			dev_err(pcie->dev, "error while configuring ssc mode\n");
+	if (pcie->gen)
+		set_gen(base, pcie->gen);
+
+	/* take the EP device out of reset */
+	/* field: PCIE_SW_PERST = 0 */
+	brcm_pcie_rgr1_sw_init(pcie, 0x00000001, 0, 0);
+
+	return 0;
+}
+
+static void brcm_pcie_turn_off(struct brcm_pcie *pcie)
+{
+	void __iomem *base = pcie->base;
+
+	/* Reset endpoint device */
+	brcm_pcie_rgr1_sw_init(pcie, 0x00000001, 0, 1);
+
+	/* deassert request for L23 in case it was asserted */
+	wr_fld_rb(base + PCIE_MISC_PCIE_CTRL, 0x1, 0, 0);
+
+	/* SERDES_IDDQ = 1 */
+	wr_fld_rb(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG, 0x08000000,
+		  27, 1);
+	/* Shutdown PCIe bridge */
+	brcm_pcie_rgr1_sw_init(pcie, 0x00000002, 1, 1);
+}
+
+static void brcm_pcie_enter_l23(struct brcm_pcie *pcie)
+{
+	void __iomem *base = pcie->base;
+	int timeout = 1000;
+	int l23;
+
+	/* assert request for L23 */
+	wr_fld_rb(base + PCIE_MISC_PCIE_CTRL, 0x1, 0, 1);
+	do {
+		/* poll L23 status */
+		l23 = bpcie_readl(base + PCIE_MISC_PCIE_STATUS) & (1 << 6);
+	} while (--timeout && !l23);
+
+	if (!timeout)
+		dev_err(pcie->dev, "failed to enter L23\n");
+}
+
+static int brcm_setup_pcie_bridge(struct brcm_pcie *pcie)
+{
+	static const char *link_speed[4] = { "???", "2.5", "5.0", "8.0" };
+	void __iomem *base = pcie->base;
+	const int limit = pcie->suspended ? 1000 : 100;
+	struct clk *clk;
+	unsigned int status;
+	int i, j, ret;
+	bool ssc_good = false;
+
+	/* Give the RC/EP time to wake up, before trying to configure RC.
+	 * Intermittently check status for link-up, up to a total of 100ms
+	 * when we don't know if the device is there, and up to 1000ms if
+	 * we do know the device is there.
+	 */
+	for (i = 1, j = 0; j < limit && !is_pcie_link_up(pcie); j += i, i = i*2)
+		msleep(i + j > limit ? limit - j : i);
+
+	if (!is_pcie_link_up(pcie)) {
+		dev_info(pcie->dev, "link down\n");
+		goto fail;
+	}
+
+	/* Attempt to enable MSI if we have an interrupt for it. */
+	if (pcie->msi_irq > 0) {
+		ret = brcm_pcie_enable_msi(pcie, pcie->num);
+		if (ret < 0) {
+			dev_err(pcie->dev, "failed to enable MSI support: %d\n",
+				ret);
+		}
+	}
+
+	/* For config space accesses on the RC, show the right class for
+	 * a PCI-PCI bridge
+	 */
+	wr_fld_rb(base + PCIE_RC_CFG_PRIV1_ID_VAL3, 0x00ffffff, 0, 0x060400);
+
+	status = bpcie_readl(base + PCIE_RC_CFG_PCIE_LINK_STATUS_CONTROL);
+
+	if (pcie->ssc) {
+		if (is_ssc(base) == 0)
+			ssc_good = true;
+		else
+			dev_err(pcie->dev, "failed to enter SSC mode\n");
+	}
+
+	dev_info(pcie->dev, "link up, %s Gbps x%u %s\n",
+		 link_speed[((status & 0x000f0000) >> 16) & 0x3],
+		 (status & 0x03f00000) >> 20, ssc_good ? "(SSC)" : "(!SSC)");
+
+	/* Enable configuration request retry (see pci_scan_device()) */
+	/* field RC_CRS_EN = 1
+	 */
+	wr_fld(base + PCIE_RC_CFG_PCIE_ROOT_CAP_CONTROL, 0x00000010, 4, 1);
+
+	/* PCIE->SCB endian mode for BAR ield ENDIAN_MODE_BAR2 = DATA_ENDIAN
+	 */
+	wr_fld_rb(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1, 0x0000000c, 2,
+		  DATA_ENDIAN);
+
+	/* Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1
+	 * is enabled =>  setting the CLKREQ_DEBUG_ENABLE field to 1.
+	 */
+	wr_fld_rb(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG, 0x00000002, 1, 1);
+
+	/* Add bogus IO resource structure so that pcibios_init_resources()
+	 * does not allocate the same IO region for different domains
+	 */
+
+	pcie->bridge_setup_done = true;
+
+	return 0;
+fail:
+	if (IS_ENABLED(CONFIG_PM))
+		brcm_pcie_turn_off(pcie);
+
+	clk = pcie->clk;
+	if (pcie->suspended)
+		clk_disable(clk);
+	else {
+		clk_disable_unprepare(clk);
+		clk_put(clk);
+	}
+
+	pcie->bridge_setup_done = false;
+
+	return -ENODEV;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int brcm_pcie_suspend(struct device *dev)
+{
+	struct brcm_pcie *pcie = dev_get_drvdata(dev);
+
+	if (!pcie->bridge_setup_done)
+		return 0;
+
+	brcm_pcie_enter_l23(pcie);
+	brcm_pcie_turn_off(pcie);
+	clk_disable(pcie->clk);
+	pcie->suspended = true;
+
+	return 0;
+}
+
+static int brcm_pcie_resume(struct device *dev)
+{
+	struct brcm_pcie *pcie = dev_get_drvdata(dev);
+
+	if (!pcie->bridge_setup_done)
+		return 0;
+
+	/* Take bridge out of reset so we can access the SERDES reg */
+	brcm_pcie_rgr1_sw_init(pcie, 0x00000002, 1, 0);
+
+	/* SERDES_IDDQ = 0 */
+	wr_fld_rb(pcie->base + PCIE_MISC_HARD_PCIE_HARD_DEBUG, 0x08000000,
+		  27, 0);
+	/* wait for serdes to be stable */
+	usleep_range(100, 1000);
+
+	brcm_pcie_setup_early(pcie);
+
+	brcm_setup_pcie_bridge(pcie);
+	pcie->suspended = false;
+
+	return 0;
+}
+
+static const struct dev_pm_ops brcm_pcie_pm_ops = {
+	.suspend_noirq = brcm_pcie_suspend,
+	.resume_noirq = brcm_pcie_resume,
+};
+#else
+#define brcm_pcie_pm_ops	NULL
+#endif /* CONFIG_PM_SLEEP */
+
+static int cfg_index(int busnr, int devfn, int reg)
+{
+	return ((PCI_SLOT(devfn) & 0x1f) << PCI_SLOT_SHIFT)
+		| ((PCI_FUNC(devfn) & 0x07) << PCI_FUNC_SHIFT)
+		| (busnr << PCI_BUSNUM_SHIFT)
+		| (reg & ~3);
+}
+
+static int brcm_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
+				  int where, int size, u32 data)
+{
+	struct brcm_pcie *pcie = bus->sysdata;
+	u32 val = 0, mask, shift;
+	void __iomem *base;
+	bool rc_access;
+	int idx;
+
+	if (!is_pcie_link_up(pcie))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	base = pcie->base;
+
+	rc_access = !!pci_is_root_bus(bus);
+
+	idx = cfg_index(bus->number, devfn, where);
+	WARN_ON(((where & 3) + size) > 4);
+
+	if (rc_access && PCI_SLOT(devfn))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (size < 4) {
+		/* partial word - read, modify, write */
+		if (rc_access)
+			val = bpcie_readl(base + (where & ~3));
+		else
+			val = brcm_pcie_ll_read_config(pcie, idx);
+	}
+
+	shift = (where & 3) << 3;
+	mask = (0xffffffff >> ((4 - size) << 3)) << shift;
+	val = (val & ~mask) | ((data << shift) & mask);
+
+	if (rc_access) {
+		bpcie_writel(val, base + (where & ~3));
+		bpcie_readl(base + (where & ~3));
+	} else {
+		brcm_pcie_ll_write_config(pcie, idx, val);
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int brcm_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 *data)
+{
+	struct brcm_pcie *pcie = bus->sysdata;
+	u32 val, mask, shift;
+	void __iomem *base;
+	bool rc_access;
+	int idx;
+
+	if (!is_pcie_link_up(pcie))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	base = pcie->base;
+
+	rc_access = !!pci_is_root_bus(bus);
+	idx = cfg_index(bus->number, devfn, where);
+	WARN_ON(((where & 3) + size) > 4);
+
+	if (rc_access && PCI_SLOT(devfn)) {
+		*data = 0xffffffff;
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+
+	if (rc_access)
+		val = bpcie_readl(base + (where & ~3));
+	else
+		val = brcm_pcie_ll_read_config(pcie, idx);
+
+	shift = (where & 3) << 3;
+	mask = (0xffffffff >> ((4 - size) << 3)) << shift;
+	*data = (val & mask) >> shift;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static const struct of_device_id brcm_pcie_match[] = {
+	{ .compatible = "brcm,bcm7425-pcie", .data = &bcm7425_cfg },
+	{ .compatible = "brcm,bcm7435-pcie", .data = &bcm7435_cfg },
+	{ .compatible = "brcm,bcm7445-pcie", .data = &generic_cfg },
+	{},
+};
+MODULE_DEVICE_TABLE(of, brcm_pcie_match);
+
+static struct pci_ops brcm_pcie_ops = {
+	.read = brcm_pcie_read_config,
+	.write = brcm_pcie_write_config,
+};
+
+static int brcm_pcie_probe(struct platform_device *pdev)
+{
+	struct device_node *dn = pdev->dev.of_node;
+	const u32 *log2_scb_sizes, *dma_ranges;
+	const struct brcm_pcie_cfg_data *data;
+	const struct of_device_id *of_id;
+	struct brcm_pcie *pcie;
+	void __iomem *base;
+	struct resource *r;
+	int i, rlen, ret;
+	u32 tmp;
+
+	pcie = devm_kzalloc(&pdev->dev, sizeof(struct brcm_pcie), GFP_KERNEL);
+	if (!pcie)
+		return -ENOMEM;
+
+	of_id = of_match_node(brcm_pcie_match, dn);
+	if (!of_id)
+		return -EINVAL;
+
+	data = of_id->data;
+	pcie->type = data->type;
+	pcie->ops = &data->ops;
+
+	platform_set_drvdata(pdev, pcie);
+
+	INIT_LIST_HEAD(&pcie->resource);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	ret = of_alias_get_id(dn, "pcie");
+	if (ret >= 0)
+		pcie->num = ret;
+
+	pcie->clk = devm_clk_get(&pdev->dev, "pcie");
+	if (IS_ERR(pcie->clk)) {
+		dev_err(&pdev->dev, "could not get clock\n");
+		pcie->clk = NULL;
+	}
+
+	ret = clk_prepare_enable(pcie->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "could not enable clock\n");
+		return ret;
+	}
+
+	pcie->dn = dn;
+	pcie->base = base;
+	pcie->dev = &pdev->dev;
+	pcie->dev->of_node = dn;
+	pcie->gen = 0;
+
+	ret = of_property_read_u32(dn, "brcm,gen", &tmp);
+	if (ret == 0) {
+		if (tmp > 0 && tmp < 3)
+			pcie->gen = (int)tmp;
+		else
+			dev_warn(pcie->dev, "bad DT value for prop 'brcm,gen");
+	} else if (ret != -EINVAL) {
+		dev_warn(pcie->dev, "error reading DT prop 'brcm,gen");
+	}
+
+	pcie->ssc = of_property_read_bool(dn, "brcm,ssc");
+
+	/* Get the value for the log2 of the scb sizes. Subtract 15 from
+	 * each because the target register field has 0==disabled and 1==6KB.
+	 */
+	log2_scb_sizes = of_get_property(dn, "brcm,log2-scb-sizes", &rlen);
+	if (log2_scb_sizes) {
+		for (i = 0; i < rlen / sizeof(u32); i++) {
+			pcie->scb_size_vals[i]
+				= (int)of_read_number(log2_scb_sizes + i, 1)
+					- 15;
+			pcie->num_memc++;
+		}
+	}
+
+	/* Look for the dma-ranges property.  If it exists, issue a warning
+	 * as PCIe drivers may not work.  This is because the identity
+	 * mapping between system memory and PCIe space is not preserved,
+	 * and we need Linux to massage the dma_addr_t values it gets
+	 * from dma memory allocation.  This functionality will be added
+	 * in the near future.
+	 */
+	dma_ranges = of_get_property(dn, "dma-ranges", &rlen);
+	if (dma_ranges != NULL)
+		dev_warn(pcie->dev, "no identity map; PCI drivers may fail");
+
+	if (IS_ENABLED(CONFIG_PCI_MSI)) {
+		ret = irq_of_parse_and_map(pdev->dev.of_node, 1);
+		if (ret == 0)
+			dev_warn(pcie->dev, "cannot get msi intr; MSI disabled\n");
+		else
+			pcie->msi_irq = ret;
+	}
+
+	ret = of_pci_get_host_bridge_resources(dn, 0, 0xff,
+					       &pcie->resource, NULL);
+	if (ret) {
+		dev_err(pcie->dev, "ranges parsing failed\n");
+		return ret;
+	}
+
+	ret = brcm_pcie_setup_early(pcie);
+	if (ret)
+		goto out_err_clk;
+
+	/* If setup bridge fails, it cleans up behind itself */
+	ret = brcm_setup_pcie_bridge(pcie);
+	if (ret)
+		goto out_err;
+
+	pcie->bus = pci_scan_root_bus(pcie->dev, pcie->num, &brcm_pcie_ops,
+				      pcie, &pcie->resource);
+	if (!pcie->bus) {
+		ret = -ENOMEM;
+		goto out_err_bus;
+	}
+
+	if (IS_ENABLED(CONFIG_PCI_MSI))
+		brcm_pcie_msi_chip_set(pcie);
+
+	pci_bus_size_bridges(pcie->bus);
+	pci_bus_assign_resources(pcie->bus);
+
+	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+	pci_bus_add_devices(pcie->bus);
+
+	return 0;
+
+out_err_bus:
+	brcm_pcie_enter_l23(pcie);
+	brcm_pcie_turn_off(pcie);
+out_err_clk:
+	clk_disable_unprepare(pcie->clk);
+out_err:
+	return ret;
+}
+
+static int brcm_pcie_remove(struct platform_device *pdev)
+{
+	return brcm_pcie_suspend(&pdev->dev);
+}
+
+static struct platform_driver brcm_pcie_driver = {
+	.probe = brcm_pcie_probe,
+	.remove = brcm_pcie_remove,
+	.driver = {
+		.name = "brcm-pcie",
+		.owner = THIS_MODULE,
+		.of_match_table = brcm_pcie_match,
+		.pm = &brcm_pcie_pm_ops,
+	},
+};
+module_platform_driver(brcm_pcie_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Broadcom STB PCIE RC driver");
+MODULE_AUTHOR("Broadcom");
diff --git a/drivers/pci/host/pcie-brcmstb.h b/drivers/pci/host/pcie-brcmstb.h
new file mode 100644
index 000000000000..b4a507423bb0
--- /dev/null
+++ b/drivers/pci/host/pcie-brcmstb.h
@@ -0,0 +1,160 @@
+#ifndef __PCIE_BRCMSTB_H
+#define __PCIE_BRCMSTB_H
+
+#include <linux/io.h>
+
+/* Broadcom PCIE Offsets */
+#define PCIE_RC_CFG_PCIE_LINK_CAPABILITY		0x00b8
+#define PCIE_RC_CFG_PCIE_LINK_STATUS_CONTROL		0x00bc
+#define PCIE_RC_CFG_PCIE_ROOT_CAP_CONTROL		0x00c8
+#define PCIE_RC_CFG_PCIE_LINK_STATUS_CONTROL_2		0x00dc
+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1		0x0188
+#define PCIE_RC_CFG_PRIV1_ID_VAL3			0x043c
+#define PCIE_RC_DL_MDIO_ADDR				0x1100
+#define PCIE_RC_DL_MDIO_WR_DATA				0x1104
+#define PCIE_RC_DL_MDIO_RD_DATA				0x1108
+#define PCIE_MISC_MISC_CTRL				0x4008
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO		0x400c
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI		0x4010
+#define PCIE_MISC_RC_BAR1_CONFIG_LO			0x402c
+#define PCIE_MISC_RC_BAR1_CONFIG_HI			0x4030
+#define PCIE_MISC_RC_BAR2_CONFIG_LO			0x4034
+#define PCIE_MISC_RC_BAR2_CONFIG_HI			0x4038
+#define PCIE_MISC_RC_BAR3_CONFIG_LO			0x403c
+#define PCIE_MISC_RC_BAR3_CONFIG_HI			0x4040
+#define PCIE_MISC_MSI_BAR_CONFIG_LO			0x4044
+#define PCIE_MISC_MSI_BAR_CONFIG_HI			0x4048
+#define PCIE_MISC_MSI_DATA_CONFIG			0x404c
+#define PCIE_MISC_PCIE_CTRL				0x4064
+#define PCIE_MISC_PCIE_STATUS				0x4068
+#define PCIE_MISC_REVISION				0x406c
+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT	0x4070
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG			0x4204
+#define PCIE_INTR2_CPU_BASE				0x4300
+#define PCIE_MSI_INTR2_BASE				0x4500
+
+#define PCIE_RGR1_SW_INIT_1				0x9210
+#define PCIE_EXT_CFG_INDEX				0x9000
+#define PCIE_EXT_CFG_DATA				0x9004
+
+/* BCM7425 specific register offsets */
+#define BCM7425_PCIE_RGR1_SW_INIT_1			0x8010
+#define BCM7425_PCIE_EXT_CFG_INDEX			0x8300
+#define BCM7425_PCIE_EXT_CFG_DATA			0x8304
+
+#define PCI_BUSNUM_SHIFT		20
+#define PCI_SLOT_SHIFT			15
+#define PCI_FUNC_SHIFT			12
+
+#define BRCM_NUM_PCI_OUT_WINS		4
+#define BRCM_MAX_SCB			4
+
+/* Offsets from PCIE_INTR2_CPU_BASE and PCIE_MSI_INTR2_BASE */
+#define STATUS				0x0
+#define SET				0x4
+#define CLR				0x8
+#define MASK_STATUS			0xc
+#define MASK_SET			0x10
+#define MASK_CLR			0x14
+
+enum brcm_pcie_type {
+	BCM7425,
+	BCM7435,
+	GENERIC,
+};
+
+struct brcm_pcie;
+
+/* Chip-specific PCIe operations (read/write config and reset) */
+struct brcm_pcie_ll_ops {
+	u32 (*read_config)(struct brcm_pcie *pcie, int cfg_idx);
+	void (*write_config)(struct brcm_pcie *pcie, int cfg_idx, u32 val);
+	void (*rgr1_sw_init)(struct brcm_pcie *pcie, u32 mask,
+			     int shift, u32 val);
+};
+
+struct brcm_pcie_cfg_data {
+	const enum brcm_pcie_type type;
+	const struct brcm_pcie_ll_ops ops;
+};
+
+struct brcm_msi;
+
+/* Internal Bus Controller Information.*/
+struct brcm_pcie {
+	void __iomem		*base;
+	bool			suspended;
+	struct clk		*clk;
+	struct device_node	*dn;
+	bool			ssc;
+	int			gen;
+	int			scb_size_vals[BRCM_MAX_SCB];
+	struct pci_bus		*bus;
+	struct device		*dev;
+	struct list_head	resource;
+	int			msi_irq;
+	struct brcm_msi		*msi;
+	unsigned int		rev;
+	unsigned int		num;
+	bool			bridge_setup_done;
+	enum brcm_pcie_type	type;
+	const struct brcm_pcie_ll_ops *ops;
+	unsigned int		num_memc;
+};
+
+/* Helper functions to access read/write config space and software init which
+ * are chip-specific
+ */
+static inline u32 brcm_pcie_ll_read_config(struct brcm_pcie *pcie, int cfg_idx)
+{
+	return pcie->ops->read_config(pcie, cfg_idx);
+}
+
+static inline void brcm_pcie_ll_write_config(struct brcm_pcie *pcie,
+					     int cfg_idx, u32 val)
+{
+	pcie->ops->write_config(pcie, cfg_idx, val);
+}
+
+static inline void brcm_pcie_rgr1_sw_init(struct brcm_pcie *pcie, u32 mask,
+					  int shift, u32 val)
+{
+	pcie->ops->rgr1_sw_init(pcie, mask, shift, val);
+}
+
+/*
+ * MIPS endianness is configured by boot strap, which also reverses all
+ * bus endianness (i.e., big-endian CPU + big endian bus ==> native
+ * endian I/O).
+ *
+ * Other architectures (e.g., ARM) either do not support big endian, or
+ * else leave I/O in little endian mode.
+ */
+static inline u32 bpcie_readl(void __iomem *base)
+{
+	if (IS_ENABLED(CONFIG_MIPS))
+		return __raw_readl(base);
+	else
+		return readl(base);
+}
+
+static inline void bpcie_writel(u32 val, void __iomem *base)
+{
+	if (IS_ENABLED(CONFIG_MIPS))
+		__raw_writel(val, base);
+	else
+		writel(val, base);
+}
+
+#ifdef CONFIG_PCIE_BRCMSTB_MSI
+int brcm_pcie_enable_msi(struct brcm_pcie *pcie, int nr);
+void brcm_pcie_msi_chip_set(struct brcm_pcie *pcie);
+#else
+static inline int brcm_pcie_enable_msi(struct brcm_pcie *pcie, int nr)
+{
+	return 0;
+}
+static inline void brcm_pcie_msi_chip_set(struct brcm_pcie *pcie) { }
+#endif
+
+#endif /* __PCIE_BRCMSTB_H */
-- 
2.1.0



From broonie at kernel.org  Thu May  5 12:17:28 2016
From: broonie at kernel.org (Mark Brown)
Date: Thu, 5 May 2016 20:17:28 +0100
Subject: [RFC PATCH 1/7] ALSA: ac97: split out the generic ac97 registers
In-Reply-To: <87pot0pbnf.fsf@belgarion.home>
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-2-git-send-email-robert.jarzmik@free.fr>
 <20160503115159.GP6292@sirena.org.uk>
 <87y47roski.fsf@belgarion.home>
 <20160504090702.GV6292@sirena.org.uk>
 <87pot0pbnf.fsf@belgarion.home>
Message-ID: <20160505191728.GK6292@sirena.org.uk>

On Thu, May 05, 2016 at 09:06:44PM +0200, Robert Jarzmik wrote:
> Mark Brown <broonie at kernel.org> writes:

> > I see that, I just don't know why that helps.

> Ok, so let me explain.

> As you already understood, AC97_VENDOR* is needed in bus.c for the
> autoscanning. The remaining is the reason why I don't want to include
> ac97_codec.h in bus.c, which follows.

> In order to have a clean split between former ac97 bus implementation and this
> new one, I didn't want to include any former ac97 includes, excepting in
> sound/ac97/compat.c.

It's probably a good idea to articulate some of this in the commit log
then!

> This transition will be easier if the new ac97 code is isolated as much as
> possible from the former code while providing backward compatibility ... hence
> this patch.

It'd probably have been clearer to me if it were splitting out all the
register definitions rather than just some of them.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160505/2dd6048c/attachment.sig>

From eric at anholt.net  Thu May  5 12:17:51 2016
From: eric at anholt.net (Eric Anholt)
Date: Thu, 05 May 2016 12:17:51 -0700
Subject: [PATCH V5] clk: bcm2835: mark enabled clocks and pll with
 CLK_ENABLE_HAND_OFF
In-Reply-To: <1462348385-16167-1-git-send-email-kernel@martin.sperl.org>
References: <1462348385-16167-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <87oa8ks49s.fsf@eliezer.anholt.net>

kernel at martin.sperl.org writes:

> From: Martin Sperl <kernel at martin.sperl.org>
>
> The bcm2835 firmware enables several clocks and plls before
> booting the linux kernel.
>
> These plls should never get disabled as it may result in a
> stopped system clock and more.
>
> So during probing we check if the clock and plls are enabled
> and if it is then mark that clock/pll with CLK_ENABLE_HAND_OFF.
>
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
> ---
>  drivers/clk/bcm/clk-bcm2835.c | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>
> Note: This requires the CLK_ENABLE_HAND_OFF patch to be applied.
>
> diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
> index 0fc71cb..0663b6c 100644
> --- a/drivers/clk/bcm/clk-bcm2835.c
> +++ b/drivers/clk/bcm/clk-bcm2835.c
> @@ -1211,6 +1211,15 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
>  	divider->cprman = cprman;
>  	divider->data = data;
>  
> +	/* if the pll-divider is running, then enable CLK_ENABLE_HAND_OFF */
> +	if ((cprman_read(cprman, data->a2w_reg) &
> +	     A2W_PLL_CHANNEL_DISABLE) == 0) {
> +		dev_dbg(cprman->dev,
> +			"found firmware enabled pll_div %s - enabling hand off\n",
> +			data->name);
> +		init.flags |= CLK_ENABLE_HAND_OFF;
> +	}

I don't think we want this on dividers.  There are very few cases where
a divider will be grabbed and prepare/enabled on its own, rather than as
a side effect of a downstream clock being needed.  So, I think the
dividers need to stay as being enabled/disabled automatically by the
downstream clocks, like in the v3 patch you had sent.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160505/063e7354/attachment.sig>

From Tirumalesh.Chalamarla at caviumnetworks.com  Thu May  5 12:22:20 2016
From: Tirumalesh.Chalamarla at caviumnetworks.com (Chalamarla, Tirumalesh)
Date: Thu, 5 May 2016 19:22:20 +0000
Subject: [PATCH v9 4/7] vfio: allow reserved msi iova registration
In-Reply-To: <1462362858-2925-5-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-5-git-send-email-eric.auger@linaro.org>
Message-ID: <F50F9BB4-1D62-4CAF-BC0E-BE97D222E5A0@caviumnetworks.com>






On 5/4/16, 4:54 AM, "linux-arm-kernel on behalf of Eric Auger" <linux-arm-kernel-bounces at lists.infradead.org on behalf of eric.auger at linaro.org> wrote:

>The user is allowed to register a reserved MSI IOVA range by using the
>DMA MAP API and setting the new flag: VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA.
>This region is stored in the vfio_dma rb tree. At that point the iova
>range is not mapped to any target address yet. The host kernel will use
>those iova when needed, typically when MSIs are allocated.
>
>Signed-off-by: Eric Auger <eric.auger at linaro.org>
>Signed-off-by: Bharat Bhushan <Bharat.Bhushan at freescale.com>
>
>---
>v7 -> v8:
>- use iommu_msi_set_aperture function. There is no notion of
>  unregistration anymore since the reserved msi slot remains
>  until the container gets closed.
>
>v6 -> v7:
>- use iommu_free_reserved_iova_domain
>- convey prot attributes downto dma-reserved-iommu iova domain creation
>- reserved bindings teardown now performed on iommu domain destruction
>- rename VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA into
>         VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA
>- change title
>- pass the protection attribute to dma-reserved-iommu API
>
>v3 -> v4:
>- use iommu_alloc/free_reserved_iova_domain exported by dma-reserved-iommu
>- protect vfio_register_reserved_iova_range implementation with
>  CONFIG_IOMMU_DMA_RESERVED
>- handle unregistration by user-space and on vfio_iommu_type1 release
>
>v1 -> v2:
>- set returned value according to alloc_reserved_iova_domain result
>- free the iova domains in case any error occurs
>
>RFC v1 -> v1:
>- takes into account Alex comments, based on
>  [RFC PATCH 1/6] vfio: Add interface for add/del reserved iova region:
>- use the existing dma map/unmap ioctl interface with a flag to register
>  a reserved IOVA range. A single reserved iova region is allowed.
>---
> drivers/vfio/vfio_iommu_type1.c | 78 ++++++++++++++++++++++++++++++++++++++++-
> include/uapi/linux/vfio.h       | 10 +++++-
> 2 files changed, 86 insertions(+), 2 deletions(-)
>
>diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
>index 94a9916..4d3a6f1 100644
>--- a/drivers/vfio/vfio_iommu_type1.c
>+++ b/drivers/vfio/vfio_iommu_type1.c
>@@ -36,6 +36,7 @@
> #include <linux/uaccess.h>
> #include <linux/vfio.h>
> #include <linux/workqueue.h>
>+#include <linux/msi-iommu.h>
> 
> #define DRIVER_VERSION  "0.2"
> #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson at redhat.com>"
>@@ -445,6 +446,20 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
> 	vfio_lock_acct(-unlocked);
> }
> 
>+static int vfio_set_msi_aperture(struct vfio_iommu *iommu,
>+				dma_addr_t iova, size_t size)
>+{
>+	struct vfio_domain *d;
>+	int ret = 0;
>+
>+	list_for_each_entry(d, &iommu->domain_list, next) {
>+		ret = iommu_msi_set_aperture(d->domain, iova, iova + size - 1);
>+		if (ret)
>+			break;
>+	}
>+	return ret;
>+}
>+
> static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
> {
> 	vfio_unmap_unpin(iommu, dma);
>@@ -693,6 +708,63 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
> 	return ret;
> }
> 
>+static int vfio_register_msi_range(struct vfio_iommu *iommu,
>+				   struct vfio_iommu_type1_dma_map *map)
>+{
>+	dma_addr_t iova = map->iova;
>+	size_t size = map->size;
>+	int ret = 0;
>+	struct vfio_dma *dma;
>+	unsigned long order;
>+	uint64_t mask;
>+
>+	/* Verify that none of our __u64 fields overflow */
>+	if (map->size != size || map->iova != iova)
>+		return -EINVAL;
>+
>+	order =  __ffs(vfio_pgsize_bitmap(iommu));
>+	mask = ((uint64_t)1 << order) - 1;
>+
>+	WARN_ON(mask & PAGE_MASK);
>+
>+	if (!size || (size | iova) & mask)
>+		return -EINVAL;
>+
>+	/* Don't allow IOVA address wrap */
>+	if (iova + size - 1 < iova)
>+		return -EINVAL;
>+
>+	mutex_lock(&iommu->lock);
>+
>+	if (vfio_find_dma(iommu, iova, size, VFIO_IOVA_ANY)) {
>+		ret =  -EEXIST;
>+		goto unlock;
>+	}
>+
>+	dma = kzalloc(sizeof(*dma), GFP_KERNEL);
>+	if (!dma) {
>+		ret = -ENOMEM;
>+		goto unlock;
>+	}
>+
>+	dma->iova = iova;
>+	dma->size = size;
>+	dma->type = VFIO_IOVA_RESERVED;
>+
>+	ret = vfio_set_msi_aperture(iommu, iova, size);
>+	if (ret)
>+		goto free_unlock;
>+
>+	vfio_link_dma(iommu, dma);
>+	goto unlock;
>+
>+free_unlock:
>+	kfree(dma);
>+unlock:
>+	mutex_unlock(&iommu->lock);
>+	return ret;
>+}
>+
> static int vfio_bus_type(struct device *dev, void *data)
> {
> 	struct bus_type **bus = data;
>@@ -1062,7 +1134,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
> 	} else if (cmd == VFIO_IOMMU_MAP_DMA) {
> 		struct vfio_iommu_type1_dma_map map;
> 		uint32_t mask = VFIO_DMA_MAP_FLAG_READ |
>-				VFIO_DMA_MAP_FLAG_WRITE;
>+				VFIO_DMA_MAP_FLAG_WRITE |
>+				VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA;
> 
> 		minsz = offsetofend(struct vfio_iommu_type1_dma_map, size);
> 
>@@ -1072,6 +1145,9 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
> 		if (map.argsz < minsz || map.flags & ~mask)
> 			return -EINVAL;
> 
>+		if (map.flags & VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA)
>+			return vfio_register_msi_range(iommu, &map);
>+

How are we getting the PA and any validation needed?
> 		return vfio_dma_do_map(iommu, &map);
> 
> 	} else if (cmd == VFIO_IOMMU_UNMAP_DMA) {
>diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
>index 255a211..4a9dbc2 100644
>--- a/include/uapi/linux/vfio.h
>+++ b/include/uapi/linux/vfio.h
>@@ -498,12 +498,19 @@ struct vfio_iommu_type1_info {
>  *
>  * Map process virtual addresses to IO virtual addresses using the
>  * provided struct vfio_dma_map. Caller sets argsz. READ &/ WRITE required.
>+ *
>+ * In case RESERVED_MSI_IOVA flag is set, the API only aims at registering an
>+ * IOVA region that will be used on some platforms to map the host MSI frames.
>+ * In that specific case, vaddr is ignored. Once registered, an MSI reserved
>+ * IOVA region stays until the container is closed.
>  */
> struct vfio_iommu_type1_dma_map {
> 	__u32	argsz;
> 	__u32	flags;
> #define VFIO_DMA_MAP_FLAG_READ (1 << 0)		/* readable from device */
> #define VFIO_DMA_MAP_FLAG_WRITE (1 << 1)	/* writable from device */
>+/* reserved iova for MSI vectors*/
>+#define VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA (1 << 2)
> 	__u64	vaddr;				/* Process virtual address */
> 	__u64	iova;				/* IO virtual address */
> 	__u64	size;				/* Size of mapping (bytes) */
>@@ -519,7 +526,8 @@ struct vfio_iommu_type1_dma_map {
>  * Caller sets argsz.  The actual unmapped size is returned in the size
>  * field.  No guarantee is made to the user that arbitrary unmaps of iova
>  * or size different from those used in the original mapping call will
>- * succeed.
>+ * succeed. Once registered, an MSI region cannot be unmapped and stays
>+ * until the container is closed.
>  */
> struct vfio_iommu_type1_dma_unmap {
> 	__u32	argsz;
>-- 
>1.9.1
>
>
>_______________________________________________
>linux-arm-kernel mailing list
>linux-arm-kernel at lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

From Tirumalesh.Chalamarla at caviumnetworks.com  Thu May  5 12:23:55 2016
From: Tirumalesh.Chalamarla at caviumnetworks.com (Chalamarla, Tirumalesh)
Date: Thu, 5 May 2016 19:23:55 +0000
Subject: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability at
 msi domain
In-Reply-To: <1462362858-2925-6-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-6-git-send-email-eric.auger@linaro.org>
Message-ID: <FFD9D7C5-B6EF-4E16-A209-BED31DAB26AA@caviumnetworks.com>






On 5/4/16, 4:54 AM, "linux-arm-kernel on behalf of Eric Auger" <linux-arm-kernel-bounces at lists.infradead.org on behalf of eric.auger at linaro.org> wrote:

>On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is abstracted
>by the msi controller. vfio_safe_irq_domain allows to check whether
>interrupts are "safe" for a given device. They are if the device does
>not use MSI or if the device uses MSI and the msi-parent controller
>supports IRQ remapping.
>
>Then we check at group level if all devices have safe interrupts: if not,
>we only allow the group to be attached if allow_unsafe_interrupts is set.
>
>At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP. This is
>changed in next patch.

Will this work in systems with multiple ITS?
>
>Signed-off-by: Eric Auger <eric.auger at linaro.org>
>
>---
>v3 -> v4:
>- rename vfio_msi_parent_irq_remapping_capable into vfio_safe_irq_domain
>  and irq_remapping into safe_irq_domains
>
>v2 -> v3:
>- protect vfio_msi_parent_irq_remapping_capable with
>  CONFIG_GENERIC_MSI_IRQ_DOMAIN
>---
> drivers/vfio/vfio_iommu_type1.c | 44 +++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 42 insertions(+), 2 deletions(-)
>
>diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
>index 4d3a6f1..2fc8197 100644
>--- a/drivers/vfio/vfio_iommu_type1.c
>+++ b/drivers/vfio/vfio_iommu_type1.c
>@@ -37,6 +37,8 @@
> #include <linux/vfio.h>
> #include <linux/workqueue.h>
> #include <linux/msi-iommu.h>
>+#include <linux/irqdomain.h>
>+#include <linux/msi.h>
> 
> #define DRIVER_VERSION  "0.2"
> #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson at redhat.com>"
>@@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev, void *data)
> 	return 0;
> }
> 
>+/**
>+ * vfio_safe_irq_domain: returns whether the irq domain
>+ * the device is attached to is safe with respect to MSI isolation.
>+ * If the irq domain is not an MSI domain, we return it is safe.
>+ *
>+ * @dev: device handle
>+ * @data: unused
>+ * returns 0 if the irq domain is safe, -1 if not.
>+ */
>+static int vfio_safe_irq_domain(struct device *dev, void *data)
>+{
>+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
>+	struct irq_domain *domain;
>+	struct msi_domain_info *info;
>+
>+	domain = dev_get_msi_domain(dev);
>+	if (!domain)
>+		return 0;
>+
>+	info = msi_get_domain_info(domain);
>+
>+	if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
>+		return -1;
>+#endif
>+	return 0;
>+}
>+
> static int vfio_iommu_replay(struct vfio_iommu *iommu,
> 			     struct vfio_domain *domain)
> {
>@@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
> 	struct vfio_group *group, *g;
> 	struct vfio_domain *domain, *d;
> 	struct bus_type *bus = NULL;
>-	int ret;
>+	int ret, safe_irq_domains;
> 
> 	mutex_lock(&iommu->lock);
> 
>@@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
> 
> 	group->iommu_group = iommu_group;
> 
>+	/*
>+	 * Determine if all the devices of the group have a safe irq domain
>+	 * with respect to MSI isolation
>+	 */
>+	safe_irq_domains = !iommu_group_for_each_dev(iommu_group, &bus,
>+				       vfio_safe_irq_domain);
>+
> 	/* Determine bus_type in order to allocate a domain */
> 	ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type);
> 	if (ret)
>@@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
> 	INIT_LIST_HEAD(&domain->group_list);
> 	list_add(&group->next, &domain->group_list);
> 
>+	/*
>+	 * to advertise safe interrupts either the IOMMU or the MSI controllers
>+	 * must support IRQ remapping/interrupt translation
>+	 */
> 	if (!allow_unsafe_interrupts &&
>-	    !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
>+	    (!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) && !safe_irq_domains)) {
> 		pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",
> 		       __func__);
> 		ret = -EPERM;
>-- 
>1.9.1
>
>
>_______________________________________________
>linux-arm-kernel mailing list
>linux-arm-kernel at lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

From tony at atomide.com  Thu May  5 12:27:32 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 5 May 2016 12:27:32 -0700
Subject: [PATCH] ARM: dts: omap5-board-common: Describe the voltage
 supply mapping accurately
In-Reply-To: <572B984D.10203@ti.com>
References: <1462389618-28860-1-git-send-email-nm@ti.com>
 <572A528C.4090302@ti.com> <20160505183611.GA5995@atomide.com>
 <572B984D.10203@ti.com>
Message-ID: <20160505192732.GC5995@atomide.com>

* Nishanth Menon <nm at ti.com> [160505 12:02]:
> On 05/05/2016 01:36 PM, Tony Lindgren wrote:
> > Now I'm wondering if the x15 related vin-supply changes are actually all
> > ignored? It seems that "vin" is only automatically configured for the
> > fixed-regulator? Maybe regulator-palmas should be updated to use the
> 
> ok /me goes duh!!!! ofcourse! Sorry about not catching it..
> hmm.. maybe we messed up am572x-idk as well.. I can quickly fix that
> up as well

OK yeah sounds like they won't do anything currently.

> ldoln is vsys_cobra as well.. I missed that.
> 
> Others look good. we should probably get this merged to fix the
> regression.

OK I'll apply the following updated version of your patch later today.
I left out the links from the description and the timestamps too.

Regards,

Tony

8< -------------------------
From: Nishanth Menon <nm at ti.com>
Date: Thu, 5 May 2016 11:12:28 -0700
Subject: [PATCH] ARM: dts: omap5-board-common: Describe the voltage supply
 mapping accurately
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

OMAP5uEVM based platforms share a similar voltage rail map. This
should be properly described in device tree, without this regulator core
will be unable to determine the source voltage of LDOs such as LDO9 and
SMPS10 which could be configured for bypass depending on the voltage
requested of them. This results in conditions such as:

ldo9: bypassed regulator has no supply!
ldo9: failed to get the current voltage(-517)
palmas-pmic 48070000.i2c:palmas at 48:palmas_pmic: failed to register
48070000.i2c:palmas at 48:palmas_pmic regulator

Cc: Agust? Fontquerni <af at iseebcn.com>
Cc: Eduard Gavin <egavin at iseebcn.com>
Cc: Enric Balletbo i Serra <eballetbo at iseebcn.com>
Cc: Peter Ujfalusi <peter.ujfalusi at ti.com>
Signed-off-by: Nishanth Menon <nm at ti.com>
[tony at atomide.com: fixed to use palmas style in-supply]
Signed-off-by: Tony Lindgren <tony at atomide.com>

--- a/arch/arm/boot/dts/omap5-board-common.dtsi
+++ b/arch/arm/boot/dts/omap5-board-common.dtsi
@@ -14,6 +14,29 @@
 		display0 = &hdmi0;
 	};
 
+	vmain: fixedregulator-vmain {
+		compatible = "regulator-fixed";
+		regulator-name = "vmain";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	vsys_cobra: fixedregulator-vsys_cobra {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_cobra";
+		vin-supply = <&vmain>;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	vdds_1v8_main: fixedregulator-vdds_1v8_main {
+		compatible = "regulator-fixed";
+		regulator-name = "vdds_1v8_main";
+		vin-supply = <&smps7_reg>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
 	vmmcsd_fixed: fixedregulator-mmcsd {
 		compatible = "regulator-fixed";
 		regulator-name = "vmmcsd_fixed";
@@ -409,6 +432,26 @@
 
 			ti,ldo6-vibrator;
 
+			smps123-in-supply = <&vsys_cobra>;
+			smps45-in-supply = <&vsys_cobra>;
+			smps6-in-supply = <&vsys_cobra>;
+			smps7-in-supply = <&vsys_cobra>;
+			smps8-in-supply = <&vsys_cobra>;
+			smps9-in-supply = <&vsys_cobra>;
+			smps10_out2-in-supply = <&vsys_cobra>;
+			smps10_out1-in-supply = <&vsys_cobra>;
+			ldo1-in-supply = <&vsys_cobra>;
+			ldo2-in-supply = <&vsys_cobra>;
+			ldo3-in-supply = <&vdds_1v8_main>;
+			ldo4-in-supply = <&vdds_1v8_main>;
+			ldo5-in-supply = <&vsys_cobra>;
+			ldo6-in-supply = <&vdds_1v8_main>;
+			ldo7-in-supply = <&vsys_cobra>;
+			ldo8-in-supply = <&vsys_cobra>;
+			ldo9-in-supply = <&vmmcsd_fixed>;
+			ldoln-in-supply = <&vsys_cobra>;
+			ldousb-in-supply = <&vsys_cobra>;
+
 			regulators {
 				smps123_reg: smps123 {
 					/* VDD_OPP_MPU */


From javier at osg.samsung.com  Thu May  5 12:31:03 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 15:31:03 -0400
Subject: [RFC v2 07/13] power: pwrseq: simple: Add support for toggling
 regulator
In-Reply-To: <1462451666-17945-8-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-8-git-send-email-k.kozlowski@samsung.com>
Message-ID: <d27c30c1-f205-973e-71f1-f5b410418d04@osg.samsung.com>

Hello Krzysztof,

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> Some devices need real hard-reset by cutting the power.  During power
> sequence turn off and on the regulator, if it is provided.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

[snip]

>  
>  #define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq)
> @@ -62,6 +65,13 @@ static void mmc_pwrseq_simple_post_power_on(struct pwrseq *_pwrseq)
>  {
>  	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(_pwrseq);
>  
> +	if (pwrseq->ext_reg) {
> +		int err;
> +
> +		err = regulator_enable(pwrseq->ext_reg);
> +		WARN_ON_ONCE(err);
> +	}
> +

Shouldn't this be in mmc_pwrseq_simple_pre_power_on() instead?

For example, a chip may need to be powered on before attempting to
toggle its reset or power pins using some GPIO lines.

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Thu May  5 12:33:38 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 15:33:38 -0400
Subject: [RFC v2 08/13] usb: hub: Handle deferred probe
In-Reply-To: <1462451666-17945-9-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-9-git-send-email-k.kozlowski@samsung.com>
Message-ID: <0a751690-a506-34b8-9435-289cf016b756@osg.samsung.com>

Hello Krzysztof,

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> Add support for deferred probing to the usb hub. Currently EPROBE_DEFER
> does not exist in usb hub path but future patches will add it on the
> port level.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From arnd at arndb.de  Thu May  5 12:36:43 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 05 May 2016 21:36:43 +0200
Subject: ARM: SoC fixes for 4.6
Message-ID: <7856724.NgjOiORdJx@wuerfel>

The following changes since commit 02da2d72174c61988eb4456b53f405e3ebdebce4:

  Linux 4.6-rc5 (2016-04-24 16:17:05 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/fixes-for-linus

for you to fetch changes up to ed19ca7fa8bd44936aa3d5284bf38f5d96a28b35:

  Merge tag 'sunxi-fixes-for-4.6' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into fixes (2016-04-29 12:04:02 -0700)

----------------------------------------------------------------
Here are a couple last-minute fixes for ARM SoCs. Most of them
are for the OMAP platforms, quoting Tony Lindgren:

    Fixes for omaps for v4.6-rc cycle. All dts fixes, mostly
    affecting voltages and pinctrl for various device drivers:

    - Regulator minimum voltage fixes for omap5
    - ISP syscon register offset fix for omap3
    - Fix regulator initial modes for n900
    - Fix omap5 pinctrl wkup instance size

The rest are all for different platforms:

- Allwinner:
   Remove incorrect constraints from a dcdc1 regulator

- Alltera SoCFPGA:
  Fix compilation in thumb2 mode

- Samsung exynos:
  Fix a potential oops in the pm-domain error handling

- Davinci:
  Avoid a link error if NVMEM is disabled

- Renesas:
  Do not mark an external uart clock as disabled, to allow
  probing the uarts

----------------------------------------------------------------
Arnd Bergmann (4):
      Merge tag 'samsung-fixes-4.6' of git://git.kernel.org/.../krzk/linux into fixes
      Merge tag 'omap-for-v4.6/fixes-rc5-signed' of git://git.kernel.org/.../tmlind/linux-omap into fixes
      Merge tag 'renesas-fixes2-for-v4.6' of git://git.kernel.org/.../horms/renesas into fixes
      ARM: davinci: only use NVMEM when available

Geert Uytterhoeven (1):
      arm64: dts: r8a7795: Don't disable referenced optional scif clock

H. Nikolaus Schaller (1):
      ARM: dts: omap5: fix range of permitted wakeup pinmux registers

Hans de Goede (1):
      ARM: dts: sun8i-q8-common: Do not set constraints on dc1sw regulator

Ivaylo Dimitrov (2):
      ARM: dts: omap3: Fix ISP syscon register offset
      ARM: dts: omap3-n900: Specify peripherals LDO regulators initial mode

Kevin Hilman (1):
      Merge tag 'sunxi-fixes-for-4.6' of https://git.kernel.org/.../mripard/linux into fixes

Krzysztof Kozlowski (1):
      ARM: EXYNOS: Properly skip unitialized parent clock in power domain on

Sascha Hauer (1):
      ARM: SoCFPGA: Fix secondary CPU startup in thumb2 kernel

Tomi Valkeinen (2):
      ARM: dts: omap5-board-common: fix ldo1_reg and ldo4_reg ranges
      ARM: dts: omap5-cm-t54: fix ldo1_reg and ldo4_reg ranges

 arch/arm/boot/dts/omap3-n900.dts           |  9 +++++++++
 arch/arm/boot/dts/omap34xx.dtsi            |  2 +-
 arch/arm/boot/dts/omap5-board-common.dtsi  |  4 ++--
 arch/arm/boot/dts/omap5-cm-t54.dts         |  4 ++--
 arch/arm/boot/dts/omap5.dtsi               |  2 +-
 arch/arm/boot/dts/r8a7791-koelsch.dts      |  1 +
 arch/arm/boot/dts/r8a7791-porter.dts       | 14 +-------------
 arch/arm/boot/dts/r8a7791.dtsi             |  5 +----
 arch/arm/boot/dts/sun8i-q8-common.dtsi     |  2 --
 arch/arm/mach-davinci/board-mityomapl138.c |  5 +++++
 arch/arm/mach-davinci/common.c             |  5 +++++
 arch/arm/mach-exynos/pm_domains.c          |  2 +-
 arch/arm/mach-shmobile/timer.c             | 28 +++++++++++-----------------
 arch/arm/mach-socfpga/headsmp.S            |  1 +
 arch/arm64/boot/dts/renesas/r8a7795.dtsi   |  1 -
 15 files changed, 41 insertions(+), 44 deletions(-)



From robert.jarzmik at free.fr  Thu May  5 12:46:10 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Thu, 05 May 2016 21:46:10 +0200
Subject: [RFC PATCH 1/7] ALSA: ac97: split out the generic ac97 registers
In-Reply-To: <20160505191728.GK6292@sirena.org.uk> (Mark Brown's message of
 "Thu, 5 May 2016 20:17:28 +0100")
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-2-git-send-email-robert.jarzmik@free.fr>
 <20160503115159.GP6292@sirena.org.uk> <87y47roski.fsf@belgarion.home>
 <20160504090702.GV6292@sirena.org.uk> <87pot0pbnf.fsf@belgarion.home>
 <20160505191728.GK6292@sirena.org.uk>
Message-ID: <87h9ecp9tp.fsf@belgarion.home>

Mark Brown <broonie at kernel.org> writes:

> On Thu, May 05, 2016 at 09:06:44PM +0200, Robert Jarzmik wrote:
>> Mark Brown <broonie at kernel.org> writes:
>
>> > I see that, I just don't know why that helps.
>> In order to have a clean split between former ac97 bus implementation and this
>> new one, I didn't want to include any former ac97 includes, excepting in
>> sound/ac97/compat.c.
>
> It's probably a good idea to articulate some of this in the commit log
> then!
Fair point, I'll improve that.

>> This transition will be easier if the new ac97 code is isolated as much as
>> possible from the former code while providing backward compatibility ... hence
>> this patch.
>
> It'd probably have been clearer to me if it were splitting out all the
> register definitions rather than just some of them.
Euh unless I'm missing something I have splitted out all the ac97 generic
registers AFAIK. The only remaining ones are chip specific which I didn't take
as they should be in codec specific code and not ac97 generic one.

Cheers.

-- 
Robert


From javier at osg.samsung.com  Thu May  5 12:52:11 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 15:52:11 -0400
Subject: [RFC v2 09/13] power: pwrseq: Add support for USB hubs with
 external power
In-Reply-To: <1462451666-17945-10-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-10-git-send-email-k.kozlowski@samsung.com>
Message-ID: <3bdf7888-5ed1-2a55-6607-ee8be70e25e7@osg.samsung.com>

Hello Krzysztof,

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> Some USB devices on embedded boards have external power supply which has
> to be reset in certain conditions. Add pwrseq interface for this.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---
>  drivers/power/pwrseq/pwrseq.c | 44 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pwrseq.h        |  8 ++++++++
>  2 files changed, 52 insertions(+)
> 
> diff --git a/drivers/power/pwrseq/pwrseq.c b/drivers/power/pwrseq/pwrseq.c
> index 495a19d3c30b..306265f55a10 100644
> --- a/drivers/power/pwrseq/pwrseq.c
> +++ b/drivers/power/pwrseq/pwrseq.c
> @@ -52,6 +52,43 @@ int mmc_pwrseq_alloc(struct mmc_host *host)
>  }
>  EXPORT_SYMBOL_GPL(mmc_pwrseq_alloc);
>  
> +struct pwrseq *pwrseq_alloc(struct device *dev)
> +{

This function is USB specific so better to call it usb_pwrseq_alloc() instead.

Although, this function has a lot of duplicated code from mmc_pwrseq_alloc()
so I think is better to keep the name generic and factorize the common code.

I expect other devices are also needing some kind of power seq in the future
so having a single alloc function instead of each for device type makes sense.

> +	struct device_node *np;
> +	struct pwrseq *p, *ret = NULL;
> +
> +	np = of_parse_phandle(dev->of_node, "usb-pwrseq", 0);

I know this is just an RFC but you should really add DT bindings for this.

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From arnd at arndb.de  Thu May  5 12:55:26 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 05 May 2016 21:55:26 +0200
Subject: ARM: SoC fixes for 4.6
In-Reply-To: <7856724.NgjOiORdJx@wuerfel>
References: <7856724.NgjOiORdJx@wuerfel>
Message-ID: <4480155.1AKdzJLtY3@wuerfel>

On Thursday 05 May 2016 21:36:43 Arnd Bergmann wrote:
> Here are a couple last-minute fixes for ARM SoCs. Most of them
> are for the OMAP platforms, quoting Tony Lindgren:
> 
>     Fixes for omaps for v4.6-rc cycle. All dts fixes, mostly
>     affecting voltages and pinctrl for various device drivers:
> 
>     - Regulator minimum voltage fixes for omap5
>     - ISP syscon register offset fix for omap3
>     - Fix regulator initial modes for n900
>     - Fix omap5 pinctrl wkup instance size
> 

Sorry for forgetting the [GIT PULL] again on both my pull requests, I'll
send you identical copies with a correct subject line right away.

	Arnd


From javier at osg.samsung.com  Thu May  5 12:56:06 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 15:56:06 -0400
Subject: [RFC v2 10/13] usb: hub: Power sequence the ports on activation
In-Reply-To: <1462451666-17945-11-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-11-git-send-email-k.kozlowski@samsung.com>
Message-ID: <dd16f94c-9a4f-c197-7ca0-e1ff402feb98@osg.samsung.com>

Hello Krzysztof,

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> The autodetection of attached USB device might not work on certain
> boards where the power is delivered externally. These devices also might
> require a hard reset. Use pwrseq for that in USB hub.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

Patch looks good to me. So after fixing the bisectability issue
pointed out by Alan Stern:

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From arnd at arndb.de  Thu May  5 12:56:33 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 05 May 2016 21:56:33 +0200
Subject: [GIT PULL] ARM SoC fixes for 4.6
Message-ID: <4719866.mossMk4AmU@wuerfel>

[resent to fix the subject line]

The following changes since commit 02da2d72174c61988eb4456b53f405e3ebdebce4:

  Linux 4.6-rc5 (2016-04-24 16:17:05 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/fixes-for-linus

for you to fetch changes up to ed19ca7fa8bd44936aa3d5284bf38f5d96a28b35:

  Merge tag 'sunxi-fixes-for-4.6' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into fixes (2016-04-29 12:04:02 -0700)

----------------------------------------------------------------
Here are a couple last-minute fixes for ARM SoCs. Most of them
are for the OMAP platforms, quoting Tony Lindgren:

    Fixes for omaps for v4.6-rc cycle. All dts fixes, mostly
    affecting voltages and pinctrl for various device drivers:

    - Regulator minimum voltage fixes for omap5
    - ISP syscon register offset fix for omap3
    - Fix regulator initial modes for n900
    - Fix omap5 pinctrl wkup instance size

The rest are all for different platforms:

- Allwinner:
   Remove incorrect constraints from a dcdc1 regulator

- Alltera SoCFPGA:
  Fix compilation in thumb2 mode

- Samsung exynos:
  Fix a potential oops in the pm-domain error handling

- Davinci:
  Avoid a link error if NVMEM is disabled

- Renesas:
  Do not mark an external uart clock as disabled, to allow
  probing the uarts

----------------------------------------------------------------

Arnd Bergmann (4):
      Merge tag 'samsung-fixes-4.6' of git://git.kernel.org/.../krzk/linux into fixes
      Merge tag 'omap-for-v4.6/fixes-rc5-signed' of git://git.kernel.org/.../tmlind/linux-omap into fixes
      Merge tag 'renesas-fixes2-for-v4.6' of git://git.kernel.org/.../horms/renesas into fixes
      ARM: davinci: only use NVMEM when available

Geert Uytterhoeven (1):
      arm64: dts: r8a7795: Don't disable referenced optional scif clock

H. Nikolaus Schaller (1):
      ARM: dts: omap5: fix range of permitted wakeup pinmux registers

Hans de Goede (1):
      ARM: dts: sun8i-q8-common: Do not set constraints on dc1sw regulator

Ivaylo Dimitrov (2):
      ARM: dts: omap3: Fix ISP syscon register offset
      ARM: dts: omap3-n900: Specify peripherals LDO regulators initial mode

Kevin Hilman (1):
      Merge tag 'sunxi-fixes-for-4.6' of https://git.kernel.org/.../mripard/linux into fixes

Krzysztof Kozlowski (1):
      ARM: EXYNOS: Properly skip unitialized parent clock in power domain on

Sascha Hauer (1):
      ARM: SoCFPGA: Fix secondary CPU startup in thumb2 kernel

Tomi Valkeinen (2):
      ARM: dts: omap5-board-common: fix ldo1_reg and ldo4_reg ranges
      ARM: dts: omap5-cm-t54: fix ldo1_reg and ldo4_reg ranges

 arch/arm/boot/dts/omap3-n900.dts           |  9 +++++++++
 arch/arm/boot/dts/omap34xx.dtsi            |  2 +-
 arch/arm/boot/dts/omap5-board-common.dtsi  |  4 ++--
 arch/arm/boot/dts/omap5-cm-t54.dts         |  4 ++--
 arch/arm/boot/dts/omap5.dtsi               |  2 +-
 arch/arm/boot/dts/r8a7791-koelsch.dts      |  1 +
 arch/arm/boot/dts/r8a7791-porter.dts       | 14 +-------------
 arch/arm/boot/dts/r8a7791.dtsi             |  5 +----
 arch/arm/boot/dts/sun8i-q8-common.dtsi     |  2 --
 arch/arm/mach-davinci/board-mityomapl138.c |  5 +++++
 arch/arm/mach-davinci/common.c             |  5 +++++
 arch/arm/mach-exynos/pm_domains.c          |  2 +-
 arch/arm/mach-shmobile/timer.c             | 28 +++++++++++-----------------
 arch/arm/mach-socfpga/headsmp.S            |  1 +
 arch/arm64/boot/dts/renesas/r8a7795.dtsi   |  1 -
 15 files changed, 41 insertions(+), 44 deletions(-)



From javier at osg.samsung.com  Thu May  5 13:10:04 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 16:10:04 -0400
Subject: [RFC v2 11/13] usb: port: Parse pwrseq phandle from Device Tree
In-Reply-To: <1462451666-17945-12-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-12-git-send-email-k.kozlowski@samsung.com>
Message-ID: <e8f310b5-4fe8-3eb2-2d17-b1d9077daea2@osg.samsung.com>

Hello Krzysztof,

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> Parse usb-pwrseq property from Device Tree to get the phandle to pwrseq
> device. The pwrseq device will be used by USB hub to cycle the power
> before activating ports.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

[snip]

>  
> @@ -532,6 +534,14 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
>  		return retval;
>  	}
>  
> +	port_dev->dev.of_node = usb_of_get_child_node(hub->hdev->dev.of_node, port1);
> +	port_dev->pwrseq = pwrseq_alloc(&port_dev->dev);
> +	if (IS_ERR(port_dev->pwrseq)) {
> +		device_unregister(&port_dev->dev);
> +		/* TODO: what about EPROBE_DEFER? */

I think it's OK since the call chain is:

hub_probe()
       hub_configure()
              usb_hub_create_port_device()

so the hub_probe() will be deferred if the usb-pwrseq was not registered yet.
Unless I misunderstood your question :)

Anyway, patch looks good to me:

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
 
Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From arnd at arndb.de  Thu May  5 13:10:52 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu,  5 May 2016 22:10:52 +0200
Subject: [PATCH] drm: sun4i: fix probe error handling
Message-ID: <1462479061-893414-1-git-send-email-arnd@arndb.de>

gcc points out a possible uninitialized variable use in
sun4i_dclk_create():

drivers/gpu/drm/sun4i/sun4i_dotclock.c: In function 'sun4i_dclk_create':
drivers/gpu/drm/sun4i/sun4i_dotclock.c:139:12: error: 'clk_name' may be used uninitialized in this function [-Werror=maybe-uninitialized]
  init.name = clk_name;

The warning only shows up when CONFIG_OF is disabled, and the
property is never filled, but the same bug can show up even
when CONFIG_OF is enabled but of_property_read_string_index
returns another error.

To fix it, this ensures that sun4i_dclk_create propagates
any error from of_property_read_string_index.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")
---
 drivers/gpu/drm/sun4i/sun4i_dotclock.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
index 3ff668cb463c..6c9c090a8006 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
@@ -127,10 +127,14 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
 	const char *clk_name, *parent_name;
 	struct clk_init_data init;
 	struct sun4i_dclk *dclk;
+	int ret;
 
 	parent_name = __clk_get_name(tcon->sclk0);
-	of_property_read_string_index(dev->of_node, "clock-output-names", 0,
-				      &clk_name);
+	ret = of_property_read_string_index(dev->of_node,
+					    "clock-output-names", 0,
+					    &clk_name);
+	if (ret)
+		return ret;
 
 	dclk = devm_kzalloc(dev, sizeof(*dclk), GFP_KERNEL);
 	if (!dclk)
-- 
2.7.0



From javier at osg.samsung.com  Thu May  5 13:11:10 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 16:11:10 -0400
Subject: [RFC v2 12/13] ARM: dts: exynos: Switch the buck8 to GPIO mode on
 Odroid U3
In-Reply-To: <1462451666-17945-13-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-13-git-send-email-k.kozlowski@samsung.com>
Message-ID: <4e8db94a-982e-06a6-82a9-f102b964c7a8@osg.samsung.com>

Hello Krzysztof,

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> Switch the control of buck8 to GPIO mode. It is faster than I2C/register
> mode and it is the easiest way to disable it (regulator state is a
> logical OR state of GPIO and register value).
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From stefan at agner.ch  Thu May  5 13:12:24 2016
From: stefan at agner.ch (Stefan Agner)
Date: Thu,  5 May 2016 13:12:24 -0700
Subject: [PATCH] ARM: dts: imx7d-pinfunc: add input mux for UART2 RX DTE mode
Message-ID: <1462479144-2481-1-git-send-email-stefan@agner.ch>

Add input mux for UART2 RX in DTE mode. This allows to use the pad
UART2_TX_DATA_ALT0 as UART2 RX. This particular input select seems
to be missing in current reference manuals (Rev. B), but when looking
at the tables and other UART input select registers (e.g. UART3) it
seems naturally that this input mux register also has a fourth pad
option for UART2_TX_DATA_ALT0. It has also been proven to be required
to use UART2 in DTE mode and the particular pads on the Colibri iMX7
platform.

Signed-off-by: Stefan Agner <stefan at agner.ch>
---
 arch/arm/boot/dts/imx7d-pinfunc.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/imx7d-pinfunc.h b/arch/arm/boot/dts/imx7d-pinfunc.h
index eeda783..3f9f0d9 100644
--- a/arch/arm/boot/dts/imx7d-pinfunc.h
+++ b/arch/arm/boot/dts/imx7d-pinfunc.h
@@ -594,7 +594,7 @@
 #define MX7D_PAD_UART2_RX_DATA__GPIO4_IO2                         0x0130 0x03A0 0x0000 0x5 0x0
 #define MX7D_PAD_UART2_RX_DATA__ENET2_MDIO                        0x0130 0x03A0 0x0000 0x6 0x0
 #define MX7D_PAD_UART2_TX_DATA__UART2_DCE_TX                      0x0134 0x03A4 0x0000 0x0 0x0
-#define MX7D_PAD_UART2_TX_DATA__UART2_DTE_RX                      0x0134 0x03A4 0x0000 0x0 0x0
+#define MX7D_PAD_UART2_TX_DATA__UART2_DTE_RX                      0x0134 0x03A4 0x06FC 0x0 0x3
 #define MX7D_PAD_UART2_TX_DATA__I2C2_SDA                          0x0134 0x03A4 0x05E0 0x1 0x0
 #define MX7D_PAD_UART2_TX_DATA__SAI3_RX_DATA0                     0x0134 0x03A4 0x06C8 0x2 0x0
 #define MX7D_PAD_UART2_TX_DATA__ECSPI1_RDY                        0x0134 0x03A4 0x0000 0x3 0x0
-- 
2.8.2



From javier at osg.samsung.com  Thu May  5 13:16:20 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 5 May 2016 16:16:20 -0400
Subject: [RFC v2 13/13] ARM: dts: exynos: Fix LAN and HUB after bootloader
 initialization on Odroid U3
In-Reply-To: <1462451666-17945-14-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-14-git-send-email-k.kozlowski@samsung.com>
Message-ID: <9dff13ae-5863-2b45-0e6a-00b345a19019@osg.samsung.com>

Hello Krzysztof,

On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
> On Odroid U3 (Exynos4412-based) board if USB was initialized by
> bootloader (in U-Boot "usb start" before tftpboot), the HUB (usb3503)
> and LAN (smsc95xx) after after successful probing were not visible in the
> system ("lsusb").
> 
> In such case the devices had to be fully reset before configuring.
> Reset by GPIO (called RESET_N pin) and by RESET field in STCD register
> in usb3503 HUB are not sufficient. Instead full reset has to be done by
> disabling and enabling regulator.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

[snip]

>  
> +	lan_pwrseq: pwrseq2 {
> +		compatible = "mmc-pwrseq-simple";

It feels strange to have a "mmc-pwrseq-simple" compatible for a USB power
sequence provider. As I mentioned in the other patch, I think there should
either be a DT binding for the USB pwrseq-simple with a "usb-pwrseq-simple"
compatible that binds to the same pwrseq-simple driver or maybe having a
generic DT binding for any device with a new "pwrseq-simple" compatible.

Patch looks good to me though, so after having a DT binding and changing
the compatible string:

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From marex at denx.de  Thu May  5 13:26:09 2016
From: marex at denx.de (Marek Vasut)
Date: Thu,  5 May 2016 22:26:09 +0200
Subject: [PATCH 2/4] ARM: mxs: dts: Add AUART2 pinmux
In-Reply-To: <1462479971-7891-1-git-send-email-marex@denx.de>
References: <1462479971-7891-1-git-send-email-marex@denx.de>
Message-ID: <1462479971-7891-2-git-send-email-marex@denx.de>

Add 2-pin pinmux settings for AUART2.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Fabio Estevam <fabio.estevam at nxp.com>
Cc: Shawn Guo <shawnguo at kernel.org>
---
 arch/arm/boot/dts/imx23.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index c70ebef..0c9a357e 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -171,6 +171,17 @@
 					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
+				auart1_2pins_a: auart1-2pins at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_GPMI_D14__AUART2_RX
+						MX23_PAD_GPMI_D15__AUART2_TX
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
 				gpmi_pins_a: gpmi-nand at 0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-- 
2.7.0



From marex at denx.de  Thu May  5 13:26:08 2016
From: marex at denx.de (Marek Vasut)
Date: Thu,  5 May 2016 22:26:08 +0200
Subject: [PATCH 1/4] ARM: mxs: dts: Add SSP2 SD mux
Message-ID: <1462479971-7891-1-git-send-email-marex@denx.de>

Add pinmux configuration for SSP2 port in SD mode, both for
the 4-bit and 8-bit case.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Fabio Estevam <fabio.estevam at nxp.com>
Cc: Shawn Guo <shawnguo at kernel.org>
---
 arch/arm/boot/dts/imx23.dtsi | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index 302d116..c70ebef 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -249,6 +249,40 @@
 					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
+				mmc1_4bit_pins_a: mmc1-4bit at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_GPMI_D00__SSP2_DATA0
+						MX23_PAD_GPMI_D01__SSP2_DATA1
+						MX23_PAD_GPMI_D02__SSP2_DATA2
+						MX23_PAD_GPMI_D03__SSP2_DATA3
+						MX23_PAD_GPMI_RDY1__SSP2_CMD
+						MX23_PAD_GPMI_WRN__SSP2_SCK
+					>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
+				};
+
+				mmc1_8bit_pins_a: mmc1-8bit at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_GPMI_D00__SSP2_DATA0
+						MX23_PAD_GPMI_D01__SSP2_DATA1
+						MX23_PAD_GPMI_D02__SSP2_DATA2
+						MX23_PAD_GPMI_D03__SSP2_DATA3
+						MX23_PAD_GPMI_D04__SSP2_DATA4
+						MX23_PAD_GPMI_D05__SSP2_DATA5
+						MX23_PAD_GPMI_D06__SSP2_DATA6
+						MX23_PAD_GPMI_D07__SSP2_DATA7
+						MX23_PAD_GPMI_RDY1__SSP2_CMD
+						MX23_PAD_GPMI_WRN__SSP2_SCK
+					>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
+				};
+
 				pwm2_pins_a: pwm2 at 0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-- 
2.7.0



From marex at denx.de  Thu May  5 13:26:10 2016
From: marex at denx.de (Marek Vasut)
Date: Thu,  5 May 2016 22:26:10 +0200
Subject: [PATCH 3/4] ARM: mxs: dts: Add Creative X-Fi3 support
In-Reply-To: <1462479971-7891-1-git-send-email-marex@denx.de>
References: <1462479971-7891-1-git-send-email-marex@denx.de>
Message-ID: <1462479971-7891-3-git-send-email-marex@denx.de>

Add support for this small MP3 player based on STMP3780 (rev.4).
Currently supported is both external microSD and internal SD-NAND
bridge, PWM and USB gadget.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Fabio Estevam <fabio.estevam at nxp.com>
Cc: Shawn Guo <shawnguo at kernel.org>
---
 arch/arm/boot/dts/Makefile       |   1 +
 arch/arm/boot/dts/imx23-xfi3.dts | 190 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 191 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx23-xfi3.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 8f9f1c2..7a79d37 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -417,6 +417,7 @@ dtb-$(CONFIG_ARCH_MXS) += \
 	imx23-evk.dtb \
 	imx23-olinuxino.dtb \
 	imx23-stmp378x_devb.dtb \
+	imx23-xfi3.dtb \
 	imx28-apf28.dtb \
 	imx28-apf28dev.dtb \
 	imx28-apx4devkit.dtb \
diff --git a/arch/arm/boot/dts/imx23-xfi3.dts b/arch/arm/boot/dts/imx23-xfi3.dts
new file mode 100644
index 0000000..d7e7cf5
--- /dev/null
+++ b/arch/arm/boot/dts/imx23-xfi3.dts
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2013-2016 Marek Vasut <marex at denx.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.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * 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 "imx23.dtsi"
+
+/ {
+	model = "Creative ZEN X-Fi3";
+	compatible = "creative,x-fi3", "fsl,imx23";
+
+	memory {
+		reg = <0x40000000 0x04000000>;
+	};
+
+	apb at 80000000 {
+		apbh at 80000000 {
+			ssp0: ssp at 80010000 {
+				compatible = "fsl,imx23-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>;
+				bus-width = <4>;
+				vmmc-supply = <&reg_vddio_sd0>;
+				cd-inverted;
+				status = "okay";
+			};
+
+			ssp1: ssp at 80034000 {
+				compatible = "fsl,imx23-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc1_4bit_pins_a>;
+				bus-width = <4>;
+				non-removable;
+				status = "okay";
+			};
+
+			pinctrl at 80018000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&hog_pins_a>;
+
+				hog_pins_a: hog at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_GPMI_D07__GPIO_0_7
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+				key_pins_a: keys at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_ROTARYA__GPIO_2_7
+						MX23_PAD_ROTARYB__GPIO_2_8
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
+			};
+		};
+
+		apbx at 80040000 {
+			i2c: i2c at 80058000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2c_pins_a>;
+				status = "okay";
+			};
+
+			pwm: pwm at 80064000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pwm2_pins_a>;
+				status = "okay";
+			};
+
+			duart: serial at 80070000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&duart_pins_a>;
+				status = "okay";
+			};
+
+			auart1: serial at 8006e000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&auart1_2pins_a>;
+				status = "okay";
+			};
+
+			usbphy0: usbphy at 8007c000 {
+				status = "okay";
+			};
+
+			lradc at 80050000 {
+				status = "okay";
+			};
+		};
+	};
+
+	ahb at 80080000 {
+		usb0: usb at 80080000 {
+			dr_mode = "peripheral";
+			status = "okay";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_vddio_sd0: vddio-sd0 {
+			compatible = "regulator-fixed";
+			regulator-name = "vddio-sd0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio0 7 0>;
+		};
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 2 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&key_pins_a>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		button at 0 {
+			label = "volume-down";
+			linux,code = <114>;
+			gpios = <&gpio2 7 0>;
+			debounce-interval = <20>;
+		};
+
+		button at 1 {
+			label = "volume-up";
+			linux,code = <115>;
+			gpios = <&gpio2 8 0>;
+			debounce-interval = <20>;
+		};
+	};
+};
-- 
2.7.0



From marex at denx.de  Thu May  5 13:26:11 2016
From: marex at denx.de (Marek Vasut)
Date: Thu,  5 May 2016 22:26:11 +0200
Subject: [PATCH 4/4] ARM: mxs: dts: Add SanDisk Sansa Fuze+ support
In-Reply-To: <1462479971-7891-1-git-send-email-marex@denx.de>
References: <1462479971-7891-1-git-send-email-marex@denx.de>
Message-ID: <1462479971-7891-4-git-send-email-marex@denx.de>

Add support for this small MP3 player based on STMP3780 (rev.3).
Currently supported are both external microSD and internal SD-NAND
bridge, PWM and USB gadget.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Fabio Estevam <fabio.estevam at nxp.com>
Cc: Shawn Guo <shawnguo at kernel.org>
---
 arch/arm/boot/dts/Makefile        |   1 +
 arch/arm/boot/dts/imx23-sansa.dts | 216 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 217 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx23-sansa.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 7a79d37..eaa8048 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -416,6 +416,7 @@ dtb-$(CONFIG_SOC_VF610) += \
 dtb-$(CONFIG_ARCH_MXS) += \
 	imx23-evk.dtb \
 	imx23-olinuxino.dtb \
+	imx23-sansa.dtb \
 	imx23-stmp378x_devb.dtb \
 	imx23-xfi3.dtb \
 	imx28-apf28.dtb \
diff --git a/arch/arm/boot/dts/imx23-sansa.dts b/arch/arm/boot/dts/imx23-sansa.dts
new file mode 100644
index 0000000..60a578c
--- /dev/null
+++ b/arch/arm/boot/dts/imx23-sansa.dts
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2013-2016 Marek Vasut <marex at denx.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.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * 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 "imx23.dtsi"
+
+/ {
+	model = "SanDisk Sansa Fuze+";
+	compatible = "sandisk,sansa_fuze_plus", "fsl,imx23";
+
+	memory {
+		reg = <0x40000000 0x04000000>;
+	};
+
+	apb at 80000000 {
+		apbh at 80000000 {
+			ssp0: ssp at 80010000 {
+				compatible = "fsl,imx23-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>;
+				bus-width = <4>;
+				vmmc-supply = <&reg_vddio_sd0>;
+				cd-inverted;
+				status = "okay";
+			};
+
+			ssp1: ssp at 80034000 {
+				compatible = "fsl,imx23-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc1_8bit_pins_a>;
+				bus-width = <8>;
+				vmmc-supply = <&reg_vddio_sd1>;
+				non-removable;
+				status = "okay";
+			};
+
+			pinctrl at 80018000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&hog_pins_a>;
+
+				hog_pins_a: hog at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_GPMI_D08__GPIO_0_8
+						MX23_PAD_PWM3__GPIO_1_29
+						MX23_PAD_AUART1_RTS__GPIO_0_27
+						MX23_PAD_AUART1_CTS__GPIO_0_26
+						MX23_PAD_I2C_SCL__I2C_SCL
+						MX23_PAD_I2C_SDA__I2C_SDA
+						MX23_PAD_LCD_DOTCK__GPIO_1_22
+						MX23_PAD_LCD_HSYNC__GPIO_1_24
+						MX23_PAD_PWM3__GPIO_1_29
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+			};
+		};
+
+		apbx at 80040000 {
+			pwm: pwm at 80064000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pwm2_pins_a>;
+				status = "okay";
+			};
+
+			duart: serial at 80070000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&duart_pins_a>;
+				status = "okay";
+			};
+
+			usbphy0: usbphy at 8007c000 {
+				status = "okay";
+			};
+
+			lradc at 80050000 {
+				status = "okay";
+			};
+		};
+	};
+
+	ahb at 80080000 {
+		usb0: usb at 80080000 {
+			dr_mode = "peripheral";
+			status = "okay";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_vddio_sd0: vddio-sd0 {
+			compatible = "regulator-fixed";
+			regulator-name = "vddio-sd0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio0 8 0>;
+		};
+
+		reg_vddio_sd1: vddio-sd1 {
+			compatible = "regulator-fixed";
+			regulator-name = "vddio-sd1";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio1 29 0>;
+		};
+
+		reg_vdd_touchpad: vdd-touchpad0 {
+			compatible = "regulator-fixed";
+			regulator-name = "vdd-touchpad0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio0 26 0>;
+			regulator-always-on;
+			enable-active-low;
+		};
+
+		reg_vdd_tuner: vdd-tuner0 {
+			compatible = "regulator-fixed";
+			regulator-name = "vdd-tuner0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio0 29 0>;
+			regulator-always-on;
+			enable-active-low;
+		};
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 2 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+
+	i2c at 0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		gpios = <
+			&gpio1 24 0		/* SDA */
+			&gpio1 22 0		/* SCL */
+		>;
+		i2c-gpio,delay-us = <2>;	/* ~100 kHz */
+	};
+
+	i2c at 1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		gpios = <
+			&gpio0 31 0		/* SDA */
+			&gpio0 30 0		/* SCL */
+		>;
+		i2c-gpio,delay-us = <2>;	/* ~100 kHz */
+
+		touch: touch at 20 {
+			compatible = "synaptics,synaptics_i2c";
+			reg = <0x20>;
+		};
+
+		eeprom: eeprom at 50 {
+			compatible = "atmel,24c64";
+			reg = <0x50>;
+			pagesize = <32>;
+		};
+	};
+
+};
-- 
2.7.0



From frank.li at nxp.com  Thu May  5 13:29:05 2016
From: frank.li at nxp.com (Frank Li)
Date: Thu, 5 May 2016 20:29:05 +0000
Subject: [PATCH] ARM: dts: imx7d-pinfunc: add input mux for UART2 RX DTE
 mode
In-Reply-To: <1462479144-2481-1-git-send-email-stefan@agner.ch>
References: <1462479144-2481-1-git-send-email-stefan@agner.ch>
Message-ID: <DBXPR04MB27100FCD4D233611E0BACED887C0@DBXPR04MB271.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: Stefan Agner [mailto:stefan at agner.ch]
> Sent: Thursday, May 05, 2016 3:12 PM
> To: shawnguo at kernel.org
> Cc: kernel at pengutronix.de; Frank.Li at freescale.com;
> aalonso at freescale.com; devicetree at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; linux-kernel at vger.kernel.org; Stefan Agner
> <stefan at agner.ch>
> Subject: [PATCH] ARM: dts: imx7d-pinfunc: add input mux for UART2 RX DTE
> mode
> 
> Add input mux for UART2 RX in DTE mode. This allows to use the pad
> UART2_TX_DATA_ALT0 as UART2 RX. This particular input select seems to be
> missing in current reference manuals (Rev. B), but when looking at the tables
> and other UART input select registers (e.g. UART3) it seems naturally that this
> input mux register also has a fourth pad option for UART2_TX_DATA_ALT0. It
> has also been proven to be required to use UART2 in DTE mode and the
> particular pads on the Colibri iMX7 platform.
> 
> Signed-off-by: Stefan Agner <stefan at agner.ch>

Acked-by: Frank Li  <Frank.Li at nxp.com>

> ---
>  arch/arm/boot/dts/imx7d-pinfunc.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/imx7d-pinfunc.h b/arch/arm/boot/dts/imx7d-
> pinfunc.h
> index eeda783..3f9f0d9 100644
> --- a/arch/arm/boot/dts/imx7d-pinfunc.h
> +++ b/arch/arm/boot/dts/imx7d-pinfunc.h
> @@ -594,7 +594,7 @@
>  #define MX7D_PAD_UART2_RX_DATA__GPIO4_IO2                         0x0130
> 0x03A0 0x0000 0x5 0x0
>  #define MX7D_PAD_UART2_RX_DATA__ENET2_MDIO                        0x0130
> 0x03A0 0x0000 0x6 0x0
>  #define MX7D_PAD_UART2_TX_DATA__UART2_DCE_TX                      0x0134
> 0x03A4 0x0000 0x0 0x0
> -#define MX7D_PAD_UART2_TX_DATA__UART2_DTE_RX                      0x0134
> 0x03A4 0x0000 0x0 0x0
> +#define MX7D_PAD_UART2_TX_DATA__UART2_DTE_RX                      0x0134
> 0x03A4 0x06FC 0x0 0x3
>  #define MX7D_PAD_UART2_TX_DATA__I2C2_SDA                          0x0134
> 0x03A4 0x05E0 0x1 0x0
>  #define MX7D_PAD_UART2_TX_DATA__SAI3_RX_DATA0                     0x0134
> 0x03A4 0x06C8 0x2 0x0
>  #define MX7D_PAD_UART2_TX_DATA__ECSPI1_RDY                        0x0134
> 0x03A4 0x0000 0x3 0x0
> --
> 2.8.2



From kernel at martin.sperl.org  Thu May  5 13:29:07 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Thu, 5 May 2016 22:29:07 +0200
Subject: [PATCH V5] clk: bcm2835: mark enabled clocks and pll with
 CLK_ENABLE_HAND_OFF
In-Reply-To: <87oa8ks49s.fsf@eliezer.anholt.net>
References: <1462348385-16167-1-git-send-email-kernel@martin.sperl.org>
 <87oa8ks49s.fsf@eliezer.anholt.net>
Message-ID: <13F43ACC-85CA-4F5F-800D-E547BBA4CC73@martin.sperl.org>



> On 05.05.2016, at 21:17, Eric Anholt <eric at anholt.net> wrote:
> 
> kernel at martin.sperl.org writes:
> 
>> From: Martin Sperl <kernel at martin.sperl.org>
>> 
>> The bcm2835 firmware enables several clocks and plls before
>> booting the linux kernel.
>> 
>> These plls should never get disabled as it may result in a
>> stopped system clock and more.
>> 
>> So during probing we check if the clock and plls are enabled
>> and if it is then mark that clock/pll with CLK_ENABLE_HAND_OFF.
>> 
>> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
>> ---
>> drivers/clk/bcm/clk-bcm2835.c | 17 +++++++++++++++++
>> 1 file changed, 17 insertions(+)
>> 
>> Note: This requires the CLK_ENABLE_HAND_OFF patch to be applied.
>> 
>> diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
>> index 0fc71cb..0663b6c 100644
>> --- a/drivers/clk/bcm/clk-bcm2835.c
>> +++ b/drivers/clk/bcm/clk-bcm2835.c
>> @@ -1211,6 +1211,15 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
>>    divider->cprman = cprman;
>>    divider->data = data;
>> 
>> +    /* if the pll-divider is running, then enable CLK_ENABLE_HAND_OFF */
>> +    if ((cprman_read(cprman, data->a2w_reg) &
>> +         A2W_PLL_CHANNEL_DISABLE) == 0) {
>> +        dev_dbg(cprman->dev,
>> +            "found firmware enabled pll_div %s - enabling hand off\n",
>> +            data->name);
>> +        init.flags |= CLK_ENABLE_HAND_OFF;
>> +    }
> 
> I don't think we want this on dividers.  There are very few cases where
> a divider will be grabbed and prepare/enabled on its own, rather than as
> a side effect of a downstream clock being needed.  So, I think the
> dividers need to stay as being enabled/disabled automatically by the
> downstream clocks, like in the v3 patch you had sent.

With dividers not handled the rmmod amba_pl011 will crash the
machine (see my other email with all those issues I have reported) - 
that is why I had to add the pll_divs as well...

There may be other scenarios that can also trigger this
kind of crash.

Only other approach might be that the firmware driver would
claim those relevant plls to keep the system stable. But the 
question is: which ones would be needed?


From marex at denx.de  Thu May  5 13:31:35 2016
From: marex at denx.de (Marek Vasut)
Date: Thu,  5 May 2016 22:31:35 +0200
Subject: [PATCH] ARM: at91: sama5: Update defconfig
Message-ID: <1462480295-8034-1-git-send-email-marex@denx.de>

Enable CGROUPS support, so we can boot userspace that uses systemd on
top of kernel configured using this defconfig. The systemd userspace
depends on cgroups and without them, it dies in mysterious ways.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Ludovic Desroches <ludovic.desroches at atmel.com>
Cc: Alexandre Belloni <alexandre.belloni at free-electrons.com>
---
 arch/arm/configs/sama5_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index afbda41..1b60be2 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -3,6 +3,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
-- 
2.7.0



From marex at denx.de  Thu May  5 13:33:14 2016
From: marex at denx.de (Marek Vasut)
Date: Thu,  5 May 2016 22:33:14 +0200
Subject: [PATCH] ARM: socfpga: Update socfpga_defconfig
Message-ID: <1462480394-8084-1-git-send-email-marex@denx.de>

Enable the following bits:

CONFIG_TOUCHSCREEN_STMPE
 - STMPE touchscreen support, needed on MCVEVK as it contains the
   chip. This also enables the STMPE MFD device and touchscreen
   input support.

CONFIG_USB_STORAGE
 - USB storage support is often used, so enable it.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Dinh Nguyen <dinguyen at opensource.altera.com>
---
 arch/arm/configs/socfpga_defconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
index e277dc6..9e1e096 100644
--- a/arch/arm/configs/socfpga_defconfig
+++ b/arch/arm/configs/socfpga_defconfig
@@ -59,6 +59,8 @@ CONFIG_NETDEVICES=y
 CONFIG_STMMAC_ETH=y
 CONFIG_MICREL_PHY=y
 CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_STMPE=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_AMBAKMI=y
 CONFIG_LEGACY_PTY_COUNT=16
@@ -78,9 +80,11 @@ CONFIG_SENSORS_LTC2978=y
 CONFIG_SENSORS_LTC2978_REGULATOR=y
 CONFIG_WATCHDOG=y
 CONFIG_DW_WATCHDOG=y
+CONFIG_MFD_STMPE=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_USB=y
+CONFIG_USB_STORAGE=y
 CONFIG_USB_DWC2=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_USB_GADGET=y
-- 
2.7.0



From chris.brand at broadcom.com  Thu May  5 13:48:48 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Thu,  5 May 2016 13:48:48 -0700
Subject: [PATCH 0/6] Support BCM23550 SoC
Message-ID: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>

This patchset introduces support for the BCM23550 SoC and the Broadcom
Sparrow development board.

It modifies the BCM21664 support slightly to share code between the two.

With this patchset, a multi-v7 kernel brings up all 4 CPUs on a Sparrow
board, and gets to a shell prompt. Many of the IP blocks that are shared
with BCM28155 and BCM21664 are also functional, although not all have
been thoroughly tested.

Chris Brand (6):
  power: Introduce Broadcom kona reset driver
  arm: bcm21664: Remove reset code
  docs: Document BCM23550 bindings
  arm: Add support for Broadcom BCM23550 SoC
  arm: BCM23550 SMP support
  arm: dt: bcm23550: Add device tree files

 .../bindings/arm/bcm/brcm,bcm23550-cpu-method.txt  |  36 ++
 .../devicetree/bindings/arm/bcm/brcm,bcm23550.txt  |  15 +
 Documentation/devicetree/bindings/arm/cpus.txt     |   1 +
 arch/arm/boot/dts/Makefile                         |   3 +-
 arch/arm/boot/dts/bcm23550-sparrow.dts             |  75 ++++
 arch/arm/boot/dts/bcm23550.dtsi                    | 419 +++++++++++++++++++++
 arch/arm/mach-bcm/Kconfig                          |  12 +-
 arch/arm/mach-bcm/Makefile                         |   5 +-
 arch/arm/mach-bcm/board_bcm21664.c                 |  42 ---
 arch/arm/mach-bcm/board_bcm23550.c                 |  25 ++
 arch/arm/mach-bcm/platsmp.c                        |  58 +++
 drivers/power/reset/Kconfig                        |  10 +
 drivers/power/reset/Makefile                       |   1 +
 drivers/power/reset/brcm-kona-reset.c              |  75 ++++
 14 files changed, 731 insertions(+), 46 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt
 create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt
 create mode 100644 arch/arm/boot/dts/bcm23550-sparrow.dts
 create mode 100644 arch/arm/boot/dts/bcm23550.dtsi
 create mode 100644 arch/arm/mach-bcm/board_bcm23550.c
 create mode 100644 drivers/power/reset/brcm-kona-reset.c

-- 
1.9.1



From chris.brand at broadcom.com  Thu May  5 13:48:50 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Thu,  5 May 2016 13:48:50 -0700
Subject: [PATCH 2/6] arm: bcm21664: Remove reset code
In-Reply-To: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
References: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <1462481334-8943-3-git-send-email-chris.brand@broadcom.com>

The kona reset driver now provides this functionality.

Signed-off-by: Chris Brand <chris.brand at broadcom.com>
---
 arch/arm/mach-bcm/board_bcm21664.c | 42 --------------------------------------
 1 file changed, 42 deletions(-)

diff --git a/arch/arm/mach-bcm/board_bcm21664.c b/arch/arm/mach-bcm/board_bcm21664.c
index 82ad5687771f..65b3db06e57a 100644
--- a/arch/arm/mach-bcm/board_bcm21664.c
+++ b/arch/arm/mach-bcm/board_bcm21664.c
@@ -11,53 +11,12 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/of_address.h>
 #include <linux/of_platform.h>
-#include <linux/io.h>
 
 #include <asm/mach/arch.h>
 
 #include "kona_l2_cache.h"
 
-#define RSTMGR_DT_STRING		"brcm,bcm21664-resetmgr"
-
-#define RSTMGR_REG_WR_ACCESS_OFFSET	0
-#define RSTMGR_REG_CHIP_SOFT_RST_OFFSET	4
-
-#define RSTMGR_WR_PASSWORD		0xa5a5
-#define RSTMGR_WR_PASSWORD_SHIFT	8
-#define RSTMGR_WR_ACCESS_ENABLE		1
-
-static void bcm21664_restart(enum reboot_mode mode, const char *cmd)
-{
-	void __iomem *base;
-	struct device_node *resetmgr;
-
-	resetmgr = of_find_compatible_node(NULL, NULL, RSTMGR_DT_STRING);
-	if (!resetmgr) {
-		pr_emerg("Couldn't find " RSTMGR_DT_STRING "\n");
-		return;
-	}
-	base = of_iomap(resetmgr, 0);
-	if (!base) {
-		pr_emerg("Couldn't map " RSTMGR_DT_STRING "\n");
-		return;
-	}
-
-	/*
-	 * A soft reset is triggered by writing a 0 to bit 0 of the soft reset
-	 * register. To write to that register we must first write the password
-	 * and the enable bit in the write access enable register.
-	 */
-	writel((RSTMGR_WR_PASSWORD << RSTMGR_WR_PASSWORD_SHIFT) |
-		RSTMGR_WR_ACCESS_ENABLE,
-		base + RSTMGR_REG_WR_ACCESS_OFFSET);
-	writel(0, base + RSTMGR_REG_CHIP_SOFT_RST_OFFSET);
-
-	/* Wait for reset */
-	while (1);
-}
-
 static void __init bcm21664_init(void)
 {
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
@@ -71,6 +30,5 @@ static const char * const bcm21664_dt_compat[] = {
 
 DT_MACHINE_START(BCM21664_DT, "BCM21664 Broadcom Application Processor")
 	.init_machine = bcm21664_init,
-	.restart = bcm21664_restart,
 	.dt_compat = bcm21664_dt_compat,
 MACHINE_END
-- 
1.9.1



From chris.brand at broadcom.com  Thu May  5 13:48:49 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Thu,  5 May 2016 13:48:49 -0700
Subject: [PATCH 1/6] power: Introduce Broadcom kona reset driver
In-Reply-To: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
References: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <1462481334-8943-2-git-send-email-chris.brand@broadcom.com>

This driver supports reset on both BCM21664 and BCM23550.
Code is being moved from arch/arm/mach-bcm/board_bcm21664.c

Signed-off-by: Chris Brand <chris.brand at broadcom.com>
---
 drivers/power/reset/Kconfig           | 10 +++++
 drivers/power/reset/Makefile          |  1 +
 drivers/power/reset/brcm-kona-reset.c | 75 +++++++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)
 create mode 100644 drivers/power/reset/brcm-kona-reset.c

diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 0a6408a39c66..1a7c49f3650a 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -38,6 +38,16 @@ config POWER_RESET_AXXIA
 
 	  Say Y if you have an Axxia family SoC.
 
+config POWER_RESET_BRCMKONA
+	bool "Broadcom Kona reset driver"
+	depends on ARM || COMPILE_TEST
+	default ARCH_BCM_MOBILE
+	help
+	  This driver provides restart support for Broadcom Kona chips.
+
+	  Say Y here if you have a Broadcom Kona-based board and you wish
+	  to have restart support.
+
 config POWER_RESET_BRCMSTB
 	bool "Broadcom STB reset driver"
 	depends on ARM || MIPS || COMPILE_TEST
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 096fa67047f6..ddb9a5b35480 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
 obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o
 obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
 obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
+obj-$(CONFIG_POWER_RESET_BRCMKONA) += brcm-kona-reset.o
 obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
 obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
diff --git a/drivers/power/reset/brcm-kona-reset.c b/drivers/power/reset/brcm-kona-reset.c
new file mode 100644
index 000000000000..d6f2070be89c
--- /dev/null
+++ b/drivers/power/reset/brcm-kona-reset.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; 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/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/reboot.h>
+
+#include <asm/mach/arch.h>
+
+#define RSTMGR_REG_WR_ACCESS_OFFSET	0
+#define RSTMGR_REG_CHIP_SOFT_RST_OFFSET	4
+
+#define RSTMGR_WR_PASSWORD		0xa5a5
+#define RSTMGR_WR_PASSWORD_SHIFT	8
+#define RSTMGR_WR_ACCESS_ENABLE		1
+
+static void __iomem *kona_reset_base;
+
+static int kona_reset_handler(struct notifier_block *this,
+				unsigned long mode, void *cmd)
+{
+	/*
+	 * A soft reset is triggered by writing a 0 to bit 0 of the soft reset
+	 * register. To write to that register we must first write the password
+	 * and the enable bit in the write access enable register.
+	 */
+	writel((RSTMGR_WR_PASSWORD << RSTMGR_WR_PASSWORD_SHIFT) |
+		RSTMGR_WR_ACCESS_ENABLE,
+		kona_reset_base + RSTMGR_REG_WR_ACCESS_OFFSET);
+	writel(0, kona_reset_base + RSTMGR_REG_CHIP_SOFT_RST_OFFSET);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block kona_reset_nb = {
+	.notifier_call = kona_reset_handler,
+	.priority = 128,
+};
+
+static int kona_reset_probe(struct platform_device *pdev)
+{
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	kona_reset_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(kona_reset_base))
+		return PTR_ERR(kona_reset_base);
+
+	return register_restart_handler(&kona_reset_nb);
+}
+
+static const struct of_device_id of_match[] = {
+	{ .compatible = "brcm,bcm21664-resetmgr" },
+	{},
+};
+
+static struct platform_driver bcm_kona_reset_driver = {
+	.probe = kona_reset_probe,
+	.driver = {
+		.name = "brcm-kona-reset",
+		.of_match_table = of_match,
+	},
+};
+
+builtin_platform_driver(bcm_kona_reset_driver);
-- 
1.9.1



From chris.brand at broadcom.com  Thu May  5 13:48:53 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Thu,  5 May 2016 13:48:53 -0700
Subject: [PATCH 5/6] arm: BCM23550 SMP support
In-Reply-To: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
References: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <1462481334-8943-6-git-send-email-chris.brand@broadcom.com>

BCM23550 has a Cluster Dormant Control IP block that holds cores
in an idle state. Support a new CPU enable method in which the CDC is
accessed to bring the core online.

Signed-off-by: Raymond Ngun <raymond.ngun at broadcom.com>
Signed-off-by: Chris Brand <chris.brand at broadcom.com>
---
 arch/arm/mach-bcm/platsmp.c | 58 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/arch/arm/mach-bcm/platsmp.c b/arch/arm/mach-bcm/platsmp.c
index cfae9c71fb74..c57fc6b1ac07 100644
--- a/arch/arm/mach-bcm/platsmp.c
+++ b/arch/arm/mach-bcm/platsmp.c
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 #include <linux/jiffies.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 
@@ -255,6 +256,57 @@ static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
 	return -ENXIO;
 }
 
+/* Cluster Dormant Control command to bring CPU into a running state */
+#define CDC_CMD			6
+#define CDC_CMD_OFFSET		0
+#define CDC_CMD_REG(cpu)	(CDC_CMD_OFFSET + 4*(cpu))
+
+/*
+ * BCM23550 has a Cluster Dormant Control block that keeps the core in
+ * idle state. A command needs to be sent to the block to bring the CPU
+ * into running state.
+ */
+static int bcm23550_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	void __iomem *cdc_base;
+	struct device_node *dn;
+	char *name;
+	int ret;
+
+	/* Make sure a CDC node exists before booting the
+	 * secondary core.
+	 */
+	name = "brcm,bcm23550-cdc";
+	dn = of_find_compatible_node(NULL, NULL, name);
+	if (!dn) {
+		pr_err("unable to find cdc node\n");
+		return -ENODEV;
+	}
+
+	cdc_base = of_iomap(dn, 0);
+	of_node_put(dn);
+
+	if (!cdc_base) {
+		pr_err("unable to remap cdc base register\n");
+		return -ENOMEM;
+	}
+
+	/* Boot the secondary core */
+	ret = kona_boot_secondary(cpu, idle);
+	if (ret)
+		goto out;
+
+	/* Bring this CPU to RUN state so that nIRQ nFIQ
+	 * signals are unblocked.
+	 */
+	writel_relaxed(CDC_CMD, cdc_base + CDC_CMD_REG(cpu));
+
+out:
+	iounmap(cdc_base);
+
+	return ret;
+}
+
 static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	int ret;
@@ -283,6 +335,12 @@ static const struct smp_operations bcm_smp_ops __initconst = {
 CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
 			&bcm_smp_ops);
 
+static const struct smp_operations bcm23550_smp_ops __initconst = {
+	.smp_boot_secondary	= bcm23550_boot_secondary,
+};
+CPU_METHOD_OF_DECLARE(bcm_smp_bcm23550, "brcm,bcm23550-cpu-method",
+			&bcm23550_smp_ops);
+
 static const struct smp_operations nsp_smp_ops __initconst = {
 	.smp_prepare_cpus	= bcm_smp_prepare_cpus,
 	.smp_boot_secondary	= nsp_boot_secondary,
-- 
1.9.1



From chris.brand at broadcom.com  Thu May  5 13:48:51 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Thu,  5 May 2016 13:48:51 -0700
Subject: [PATCH 3/6] docs: Document BCM23550 bindings
In-Reply-To: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
References: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <1462481334-8943-4-git-send-email-chris.brand@broadcom.com>

Add binding document for Broadcom BCM23550 SoC.

BCM23550 has a Cluster Dormant Control IP block that holds cores
in an idle state. Introduce a new CPU enable method in which the CDC is
accessed to bring the core online.

Signed-off-by: Chris Brand <chris.brand at broadcom.com>
---
 .../bindings/arm/bcm/brcm,bcm23550-cpu-method.txt  | 36 ++++++++++++++++++++++
 .../devicetree/bindings/arm/bcm/brcm,bcm23550.txt  | 15 +++++++++
 Documentation/devicetree/bindings/arm/cpus.txt     |  1 +
 3 files changed, 52 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt
 create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt

diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt
new file mode 100644
index 000000000000..b1b16872bbca
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt
@@ -0,0 +1,36 @@
+Broadcom Kona Family CPU Enable Method
+--------------------------------------
+This binding defines the enable method used for starting secondary
+CPUs in the following Broadcom SoCs:
+  BCM23550
+
+The enable method is specified by defining the following required
+properties in the "cpu" device tree node:
+  - enable-method = "brcm,bcm23550-cpu-method";
+  - secondary-boot-reg = <...>;
+
+The secondary-boot-reg property is a u32 value that specifies the
+physical address of the register used to request the ROM holding pen
+code release a secondary CPU.  The value written to the register is
+formed by encoding the target CPU id into the low bits of the
+physical start address it should jump to.
+
+Example:
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+			enable-method = "brcm,bcm23550-cpu-method";
+			secondary-boot-reg = <0x3500417c>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt
new file mode 100644
index 000000000000..080baad923d6
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt
@@ -0,0 +1,15 @@
+Broadcom BCM23550 device tree bindings
+--------------------------------------
+
+This document describes the device tree bindings for boards with the BCM23550
+SoC.
+
+Required root node property:
+  - compatible: brcm,bcm23550
+
+Example:
+	/ {
+		model = "BCM23550 SoC";
+		compatible = "brcm,bcm23550";
+		[...]
+	}
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index ccc62f145306..8d63711139bd 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -194,6 +194,7 @@ nodes to be present and contain the properties described below.
 			    "allwinner,sun8i-a23"
 			    "arm,psci"
 			    "arm,realview-smp"
+			    "brcm,bcm23550-cpu-method"
 			    "brcm,bcm-nsp-smp"
 			    "brcm,brahma-b15"
 			    "marvell,armada-375-smp"
-- 
1.9.1



From chris.brand at broadcom.com  Thu May  5 13:48:52 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Thu,  5 May 2016 13:48:52 -0700
Subject: [PATCH 4/6] arm: Add support for Broadcom BCM23550 SoC
In-Reply-To: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
References: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <1462481334-8943-5-git-send-email-chris.brand@broadcom.com>

BCM23550 is a quad-A7 SoC used on the Broadcom "Sparrow" board.
It shares many IP blocks with other Broadcom Kona chips.

Signed-off-by: Chris Brand <chris.brand at broadcom.com>
---
 arch/arm/mach-bcm/Kconfig          | 12 ++++++++++--
 arch/arm/mach-bcm/Makefile         |  5 ++++-
 arch/arm/mach-bcm/board_bcm23550.c | 25 +++++++++++++++++++++++++
 3 files changed, 39 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-bcm/board_bcm23550.c

diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 7ef121472cdd..cb1281f115a9 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -111,9 +111,17 @@ config ARCH_BCM_21664
 	  Enable support for the BCM21664 family, which includes
 	  BCM21663 and BCM21664 variants.
 
+config ARCH_BCM_23550
+	bool "Broadcom BCM23550 SoC"
+	depends on ARCH_MULTI_V7
+	select ARCH_BCM_MOBILE
+	select HAVE_SMP
+	help
+	  Enable support for the BCM23550.
+
 config ARCH_BCM_MOBILE_L2_CACHE
 	bool "Broadcom mobile SoC level 2 cache support"
-	depends on ARCH_BCM_MOBILE
+	depends on ARCH_BCM_281XX || ARCH_BCM_21664
 	default y
 	select CACHE_L2X0
 	select ARCH_BCM_MOBILE_SMC
@@ -128,7 +136,7 @@ config ARCH_BCM_MOBILE_SMP
 	select HAVE_ARM_SCU
 	select ARM_ERRATA_764369
 	help
-	  SMP support for the BCM281XX and BCM21664 SoC families.
+	  SMP support for the BCM281XX, BCM21664 and BCM23550 SoC families.
 	  Provided as an option so SMP support for SoCs of this type
 	  can be disabled for an SMP-enabled kernel.
 
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile
index 7d665151c772..980f5850097c 100644
--- a/arch/arm/mach-bcm/Makefile
+++ b/arch/arm/mach-bcm/Makefile
@@ -26,7 +26,10 @@ obj-$(CONFIG_ARCH_BCM_281XX)	+= board_bcm281xx.o
 # BCM21664
 obj-$(CONFIG_ARCH_BCM_21664)	+= board_bcm21664.o
 
-# BCM281XX and BCM21664 SMP support
+# BCM23550
+obj-$(CONFIG_ARCH_BCM_23550)	+= board_bcm23550.o
+
+# BCM281XX, BCM21664 and BCM23550 SMP support
 obj-$(CONFIG_ARCH_BCM_MOBILE_SMP) += platsmp.o
 
 # BCM281XX and BCM21664 L2 cache control
diff --git a/arch/arm/mach-bcm/board_bcm23550.c b/arch/arm/mach-bcm/board_bcm23550.c
new file mode 100644
index 000000000000..0ac01debd077
--- /dev/null
+++ b/arch/arm/mach-bcm/board_bcm23550.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+
+static const char * const bcm23550_dt_compat[] = {
+	"brcm,bcm23550",
+	NULL,
+};
+
+DT_MACHINE_START(BCM23550_DT, "BCM23550 Broadcom Application Processor")
+	.dt_compat = bcm23550_dt_compat,
+MACHINE_END
-- 
1.9.1



From chris.brand at broadcom.com  Thu May  5 13:48:54 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Thu,  5 May 2016 13:48:54 -0700
Subject: [PATCH 6/6] arm: dt: bcm23550: Add device tree files
In-Reply-To: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
References: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <1462481334-8943-7-git-send-email-chris.brand@broadcom.com>

Add device tree files for the Broadcom BCM23550 SoC and the
Broadcom Sparrow board.

Signed-off-by: Chris Brand <chris.brand at broadcom.com>
---
 arch/arm/boot/dts/Makefile             |   3 +-
 arch/arm/boot/dts/bcm23550-sparrow.dts |  75 ++++++
 arch/arm/boot/dts/bcm23550.dtsi        | 419 +++++++++++++++++++++++++++++++++
 3 files changed, 496 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boot/dts/bcm23550-sparrow.dts
 create mode 100644 arch/arm/boot/dts/bcm23550.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 95c1923ce6fa..72ab80fa9079 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -95,7 +95,8 @@ dtb-$(CONFIG_ARCH_BCM_CYGNUS) += \
 	bcm958305k.dtb
 dtb-$(CONFIG_ARCH_BCM_MOBILE) += \
 	bcm28155-ap.dtb \
-	bcm21664-garnet.dtb
+	bcm21664-garnet.dtb \
+	bcm23550-sparrow.dtb
 dtb-$(CONFIG_ARCH_BCM_NSP) += \
 	bcm958625k.dtb
 dtb-$(CONFIG_ARCH_BERLIN) += \
diff --git a/arch/arm/boot/dts/bcm23550-sparrow.dts b/arch/arm/boot/dts/bcm23550-sparrow.dts
new file mode 100644
index 000000000000..ed9c51592e5e
--- /dev/null
+++ b/arch/arm/boot/dts/bcm23550-sparrow.dts
@@ -0,0 +1,75 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright(c) 2016 Broadcom.  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in
+ *      the documentation and/or other materials provided with the
+ *      distribution.
+ *    * Neither the name of Broadcom Corporation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "bcm23550.dtsi"
+
+/ {
+	model = "BCM23550 Sparrow board";
+	compatible = "brcm,bcm23550-sparrow", "brcm,bcm23550";
+
+	memory {
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+};
+
+&uartb {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&sdio1 {
+	max-frequency = <48000000>;
+	status = "okay";
+};
+
+&sdio2 {
+	non-removable;
+	max-frequency = <48000000>;
+	status = "okay";
+};
+
+&sdio4 {
+	max-frequency = <48000000>;
+	cd-gpios = <&gpio 91 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/bcm23550.dtsi b/arch/arm/boot/dts/bcm23550.dtsi
new file mode 100644
index 000000000000..2287c56bd8a9
--- /dev/null
+++ b/arch/arm/boot/dts/bcm23550.dtsi
@@ -0,0 +1,419 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright(c) 2016 Broadcom.  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in
+ *      the documentation and/or other materials provided with the
+ *      distribution.
+ *    * Neither the name of Broadcom Corporation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/* BCM23550 and BCM21664 have almost identical clocks */
+#include "dt-bindings/clock/bcm21664.h"
+
+#include "skeleton.dtsi"
+
+/ {
+	model = "BCM23550 SoC";
+	compatible = "brcm,bcm23550";
+	interrupt-parent = <&gic>;
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0>;
+			clock-frequency = <1000000000>;
+		};
+
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			enable-method = "brcm,bcm23550-cpu-method";
+			secondary-boot-reg = <0x35004178>;
+			reg = <1>;
+			clock-frequency = <1000000000>;
+		};
+
+		cpu2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			enable-method = "brcm,bcm23550-cpu-method";
+			secondary-boot-reg = <0x35004178>;
+			reg = <2>;
+			clock-frequency = <1000000000>;
+		};
+
+		cpu3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			enable-method = "brcm,bcm23550-cpu-method";
+			secondary-boot-reg = <0x35004178>;
+			reg = <3>;
+			clock-frequency = <1000000000>;
+		};
+	};
+
+	/* Hub bus */
+	hub at 34000000 {
+		compatible = "simple-bus";
+		ranges = <0 0x34000000 0x102f83ac>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		smc at 4e000 {
+			compatible = "brcm,bcm23550-smc", "brcm,kona-smc";
+			reg = <0x0004e000 0x400>; /* 1 KiB in SRAM */
+		};
+
+		resetmgr: reset-controller at 1001f00 {
+			compatible = "brcm,bcm21664-resetmgr";
+			reg = <0x01001f00 0x24>;
+		};
+
+		gpio: gpio at 1003000 {
+			compatible = "brcm,bcm23550-gpio", "brcm,kona-gpio";
+			reg = <0x01003000 0x524>;
+			interrupts =
+			       <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH
+				GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH
+				GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH
+				GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+			#gpio-cells = <2>;
+			#interrupt-cells = <2>;
+			gpio-controller;
+			interrupt-controller;
+		};
+
+		timer at 1006000 {
+			compatible = "brcm,kona-timer";
+			reg = <0x01006000 0x1c>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&aon_ccu BCM21664_AON_CCU_HUB_TIMER>;
+		};
+	};
+
+	/* Slaves bus */
+	slaves at 3e000000 {
+		compatible = "simple-bus";
+		ranges = <0 0x3e000000 0x0001c070>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		uartb: serial at 0 {
+			compatible = "snps,dw-apb-uart";
+			status = "disabled";
+			reg = <0x00000000 0x118>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB>;
+			interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+		};
+
+		uartb2: serial at 1000 {
+			compatible = "snps,dw-apb-uart";
+			status = "disabled";
+			reg = <0x00001000 0x118>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB2>;
+			interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+		};
+
+		uartb3: serial at 2000 {
+			compatible = "snps,dw-apb-uart";
+			status = "disabled";
+			reg = <0x00002000 0x118>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB3>;
+			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+		};
+
+		bsc1: i2c at 16000 {
+			compatible = "brcm,kona-i2c";
+			reg = <0x00016000 0x70>;
+			interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC1>;
+			status = "disabled";
+		};
+
+		bsc2: i2c at 17000 {
+			compatible = "brcm,kona-i2c";
+			reg = <0x00017000 0x70>;
+			interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC2>;
+			status = "disabled";
+		};
+
+		bsc3: i2c at 18000 {
+			compatible = "brcm,kona-i2c";
+			reg = <0x00018000 0x70>;
+			interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC3>;
+			status = "disabled";
+		};
+
+		bsc4: i2c at 1c000 {
+			compatible = "brcm,kona-i2c";
+			reg = <0x0001c000 0x70>;
+			interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC4>;
+			status = "disabled";
+		};
+	};
+
+	/* Apps bus */
+	apps at 3e300000 {
+		compatible = "simple-bus";
+		ranges = <0 0x3e300000 0x01b77000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		usbotg: usb at e20000 {
+			compatible = "snps,dwc2";
+			reg = <0x00e20000 0x10000>;
+			interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&usb_otg_ahb_clk>;
+			clock-names = "otg";
+			phys = <&usbphy>;
+			phy-names = "usb2-phy";
+			status = "disabled";
+		};
+
+		usbphy: usb-phy at e30000 {
+			compatible = "brcm,kona-usb2-phy";
+			reg = <0x00e30000 0x28>;
+			#phy-cells = <0>;
+			status = "disabled";
+		};
+
+		sdio1: sdio at e80000 {
+			compatible = "brcm,kona-sdhci";
+			reg = <0x00e80000 0x801c>;
+			interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO1>;
+			status = "disabled";
+		};
+
+		sdio2: sdio at e90000 {
+			compatible = "brcm,kona-sdhci";
+			reg = <0x00e90000 0x801c>;
+			interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO2>;
+			status = "disabled";
+		};
+
+		sdio3: sdio at ea0000 {
+			compatible = "brcm,kona-sdhci";
+			reg = <0x00ea0000 0x801c>;
+			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO3>;
+			status = "disabled";
+		};
+
+		sdio4: sdio at eb0000 {
+			compatible = "brcm,kona-sdhci";
+			reg = <0x00eb0000 0x801c>;
+			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO4>;
+			status = "disabled";
+		};
+
+		cdc: cdc at 1b0e000 {
+			compatible = "brcm,bcm23550-cdc";
+			reg = <0x01b0e000 0x78>;
+		};
+
+		gic: interrupt-controller at 1b21000 {
+			compatible = "arm,cortex-a9-gic";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0x01b21000 0x1000>,
+			      <0x01b22000 0x1000>;
+		};
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/*
+		 * Fixed clocks are defined before CCUs whose
+		 * clocks may depend on them.
+		 */
+
+		ref_32k_clk: ref_32k {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		bbl_32k_clk: bbl_32k {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ref_13m_clk: ref_13m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <13000000>;
+		};
+
+		var_13m_clk: var_13m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <13000000>;
+		};
+
+		dft_19_5m_clk: dft_19_5m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <19500000>;
+		};
+
+		ref_crystal_clk: ref_crystal {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <26000000>;
+		};
+
+		ref_52m_clk: ref_52m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <52000000>;
+		};
+
+		var_52m_clk: var_52m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <52000000>;
+		};
+
+		usb_otg_ahb_clk: usb_otg_ahb {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <52000000>;
+		};
+
+		ref_96m_clk: ref_96m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <96000000>;
+		};
+
+		var_96m_clk: var_96m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <96000000>;
+		};
+
+		ref_104m_clk: ref_104m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <104000000>;
+		};
+
+		var_104m_clk: var_104m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <104000000>;
+		};
+
+		ref_156m_clk: ref_156m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <156000000>;
+		};
+
+		var_156m_clk: var_156m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <156000000>;
+		};
+
+		root_ccu: root_ccu {
+			compatible = BCM21664_DT_ROOT_CCU_COMPAT;
+			reg = <0x35001000 0x0f00>;
+			#clock-cells = <1>;
+			clock-output-names = "frac_1m";
+		};
+
+		aon_ccu: aon_ccu {
+			compatible = BCM21664_DT_AON_CCU_COMPAT;
+			reg = <0x35002000 0x0f00>;
+			#clock-cells = <1>;
+			clock-output-names = "hub_timer";
+		};
+
+		slave_ccu: slave_ccu {
+			compatible = BCM21664_DT_SLAVE_CCU_COMPAT;
+			reg = <0x3e011000 0x0f00>;
+			#clock-cells = <1>;
+			clock-output-names = "uartb",
+					     "uartb2",
+					     "uartb3",
+					     "bsc1",
+					     "bsc2",
+					     "bsc3",
+					     "bsc4";
+		};
+
+		master_ccu: master_ccu {
+			compatible = BCM21664_DT_MASTER_CCU_COMPAT;
+			reg = <0x3f001000 0x0f00>;
+			#clock-cells = <1>;
+			clock-output-names = "sdio1",
+					     "sdio2",
+					     "sdio3",
+					     "sdio4",
+					     "sdio1_sleep",
+					     "sdio2_sleep",
+					     "sdio3_sleep",
+					     "sdio4_sleep";
+		};
+	};
+};
-- 
1.9.1



From arnd at arndb.de  Thu May  5 14:05:04 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 05 May 2016 23:05:04 +0200
Subject: [PATCH 6/6] arm: dt: bcm23550: Add device tree files
In-Reply-To: <1462481334-8943-7-git-send-email-chris.brand@broadcom.com>
References: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
 <1462481334-8943-7-git-send-email-chris.brand@broadcom.com>
Message-ID: <9191808.kbIrFQuH7z@wuerfel>

On Thursday 05 May 2016 13:48:54 Chris Brand wrote:
> +
> +       chosen {
> +               bootargs = "console=ttyS0,115200n8";
> +       };
> +
> 

Can you move this into the .dts file, and add a stdout-path
property to make earlycon work?

	Arnd


From arnd at arndb.de  Thu May  5 14:09:38 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 05 May 2016 23:09:38 +0200
Subject: [PATCH 0/6] Support BCM23550 SoC
In-Reply-To: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
References: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <6872671.Czyv7J9iJZ@wuerfel>

On Thursday 05 May 2016 13:48:48 Chris Brand wrote:
> This patchset introduces support for the BCM23550 SoC and the Broadcom
> Sparrow development board.
> 
> It modifies the BCM21664 support slightly to share code between the two.
> 
> With this patchset, a multi-v7 kernel brings up all 4 CPUs on a Sparrow
> board, and gets to a shell prompt. Many of the IP blocks that are shared
> with BCM28155 and BCM21664 are also functional, although not all have
> been thoroughly tested.

Looks really nice overall, I only found one tiny detail I commented on
for patch 6.

I'm glad to see work on the old chips resume, are you working on new
code for it as well, or just upstreaming the patches that were already
done in the past?

	Arnd


From arnd at arndb.de  Thu May  5 14:15:16 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 05 May 2016 23:15:16 +0200
Subject: [PATCH v2 1/2] Documentation: DT: bindings: Add Broadcom STB PCIe
 bindings
In-Reply-To: <1462475700-1654-2-git-send-email-f.fainelli@gmail.com>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
 <1462475700-1654-2-git-send-email-f.fainelli@gmail.com>
Message-ID: <4513390.VWu0VVAxOl@wuerfel>

On Thursday 05 May 2016 12:14:59 Florian Fainelli wrote:
> From: Jim Quinlan <jim2101024 at gmail.com>
> 
> This patchs adds the Device Tree bindings for the Broadcom STB PCIe root
> complex hardware.
> 
> Signed-off-by: Jim Quinlan <jim2101024 at gmail.com>
> Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
> ---
> Changes in v2:
> 
> - rewrite the binding document almost from scratch to include many more
>   references to existing documents
> - describe missing properties
> - give better examples
> 
>  .../devicetree/bindings/pci/brcm,brcmstb-pcie.txt  | 98 ++++++++++++++++++++++
>  1 file changed, 98 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
> 
> diff --git a/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
> new file mode 100644
> index 000000000000..3682b0f0bc26
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
> @@ -0,0 +1,98 @@
> +Broadcom STB PCIe Host Controller Device Tree Bindings
> +
> +This document describes the binding of the PCIe Root Complex hardware found in
> +Broadcom Set Top Box System-on-Chips such as BCM7425 (MIPS), BCM7435 (MIPS) and
> +BCM7445 (ARMv7).
> +
> +Required properties:
> +- compatible: must be one of: "brcm,bcm7425-pcie"
> +			      "brcm,bcm7435-pcie"
> +			      "brcm,bcm7445-pcie"
> +
> +- reg: specifies the physical base address of the controller registers and
> +  its length
> +
> +- interrupt-parent: must be a reference (phandle) to the parent interrupt
> +  controller in the system (7038-l1-intc on MIPS, GIC on ARM/ARM64)
> +
> +- interrrupts: first interrupt must be the Level 1 interrupt number corresponding
> +  to the main PCIe RC interrupt, second interrupt must be the MSI interrupt
> +  See the interrupt-parent documentation for the number of cells and their meaning:
> +  MIPS: Documentation/devicetree/bindings/interrupt-controller/brcm,bcm7038-l1-intc.txt
> +  ARM/ARM64: Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
> +
> +- interrupt-names: must be "pcie", and if present "msi"

When I suggested splitting out the MSI support, I was thinking (but not writing)
that you'd use an msi-parent property to refer to the node that holds the
msi-controller as well.

> +- ranges: ranges for the PCI outbound windows, no I/O or prefetchable windows
> +  must be specified here, only non-prefetchable. 32-bits windows or 64-bits
> +  windows are allowed based on the host processor's capabilities (ARM w/ LPAE,
> +  ARM64).

So this supports 64-bit non-prefetchable windows? Usually 64-bit windows
are prefetchable.

> +- brcm,log2-scb-sizes: log2 size of the SCB window that is mapped to PCIe space
> +  there must be exactly one value per memory controller present in the system
> +  (ranges from 1 to 3)

I'm still not too happy with this property. I see no reason for the log2
format (rather than length in bytes, or offset/length tuples, or dma-ranges,
or phandles pointing to the memory controllers). I think we need to discuss
this some more.

> +- brcm,gen: integer that indicates desired forced generation of link: 1 => 2.5
> +  Gbps, 2 => 5.0 Gbps, 3 => 8.0 Gbps. Will override the auto-negotation if
> +  specified.

to repeat my earlier comment from v1:

Shouldn't the link generation be probed automatically?

> +- <*>-supply: see Documentation/devicetree/bindings/regulator/regulator.txt
> +
> +- <*>-supply-names: see Documentation/devicetree/bindings/regulator/regulator.txt

I don't see supply-names documented there.

	Arnd



From heiko at sntech.de  Thu May  5 14:36:49 2016
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Thu, 05 May 2016 23:36:49 +0200
Subject: [PATCH v7 5/9] i2c: rk3x: Change SoC data to not use array
In-Reply-To: <1462372418-6349-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462372418-6349-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <2061861.OMNZ1I2HYA@diego>

Am Mittwoch, 4. Mai 2016, 22:33:38 schrieb David Wu:
> Signed-off-by: David Wu <david.wu at rock-chips.com>

that makes the code look nicer (and of course prepares for you further 
changes), so

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

> ---
>  drivers/i2c/busses/i2c-rk3x.c | 38 ++++++++++++++++++++++++++++++--------
>  1 file changed, 30 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> index 0838fcf..9686c81 100644
> --- a/drivers/i2c/busses/i2c-rk3x.c
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -867,17 +867,39 @@ static const struct i2c_algorithm rk3x_i2c_algorithm =
> { .functionality		= rk3x_i2c_func,
>  };
> 
> -static struct rk3x_i2c_soc_data soc_data[3] = {
> -	{ .grf_offset = 0x154 }, /* rk3066 */
> -	{ .grf_offset = 0x0a4 }, /* rk3188 */
> -	{ .grf_offset = -1 },    /* no I2C switching needed */
> +static const struct rk3x_i2c_soc_data rk3066_soc_data = {
> +	.grf_offset = 0x154,
> +};
> +
> +static const struct rk3x_i2c_soc_data rk3188_soc_data = {
> +	.grf_offset = 0x0a4,
> +};
> +
> +static const struct rk3x_i2c_soc_data rk3228_soc_data = {
> +	.grf_offset = -1,
> +};
> +
> +static const struct rk3x_i2c_soc_data rk3288_soc_data = {
> +	.grf_offset = -1,
>  };
> 
>  static const struct of_device_id rk3x_i2c_match[] = {
> -	{ .compatible = "rockchip,rk3066-i2c", .data = (void *)&soc_data[0] },
> -	{ .compatible = "rockchip,rk3188-i2c", .data = (void *)&soc_data[1] },
> -	{ .compatible = "rockchip,rk3228-i2c", .data = (void *)&soc_data[2] },
> -	{ .compatible = "rockchip,rk3288-i2c", .data = (void *)&soc_data[2] },
> +	{
> +		.compatible = "rockchip,rk3066-i2c",
> +		.data = (void *)&rk3066_soc_data
> +	},
> +	{
> +		.compatible = "rockchip,rk3188-i2c",
> +		.data = (void *)&rk3188_soc_data
> +	},
> +	{
> +		.compatible = "rockchip,rk3228-i2c",
> +		.data = (void *)&rk3228_soc_data
> +	},
> +	{
> +		.compatible = "rockchip,rk3288-i2c",
> +		.data = (void *)&rk3288_soc_data
> +	},
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, rk3x_i2c_match);



From florian.fainelli at broadcom.com  Thu May  5 14:46:22 2016
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Thu, 5 May 2016 14:46:22 -0700
Subject: [PATCH v2 1/2] Documentation: DT: bindings: Add Broadcom STB PCIe
 bindings
In-Reply-To: <4513390.VWu0VVAxOl@wuerfel>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
 <1462475700-1654-2-git-send-email-f.fainelli@gmail.com>
 <4513390.VWu0VVAxOl@wuerfel>
Message-ID: <572BBF2E.5010606@broadcom.com>

On 05/05/16 14:15, Arnd Bergmann wrote:
> On Thursday 05 May 2016 12:14:59 Florian Fainelli wrote:
>> From: Jim Quinlan <jim2101024 at gmail.com>
>>
>> This patchs adds the Device Tree bindings for the Broadcom STB PCIe root
>> complex hardware.
>>
>> Signed-off-by: Jim Quinlan <jim2101024 at gmail.com>
>> Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
>> ---
>> Changes in v2:
>>
>> - rewrite the binding document almost from scratch to include many more
>>   references to existing documents
>> - describe missing properties
>> - give better examples
>>
>>  .../devicetree/bindings/pci/brcm,brcmstb-pcie.txt  | 98 ++++++++++++++++++++++
>>  1 file changed, 98 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
>>
>> diff --git a/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
>> new file mode 100644
>> index 000000000000..3682b0f0bc26
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
>> @@ -0,0 +1,98 @@
>> +Broadcom STB PCIe Host Controller Device Tree Bindings
>> +
>> +This document describes the binding of the PCIe Root Complex hardware found in
>> +Broadcom Set Top Box System-on-Chips such as BCM7425 (MIPS), BCM7435 (MIPS) and
>> +BCM7445 (ARMv7).
>> +
>> +Required properties:
>> +- compatible: must be one of: "brcm,bcm7425-pcie"
>> +			      "brcm,bcm7435-pcie"
>> +			      "brcm,bcm7445-pcie"
>> +
>> +- reg: specifies the physical base address of the controller registers and
>> +  its length
>> +
>> +- interrupt-parent: must be a reference (phandle) to the parent interrupt
>> +  controller in the system (7038-l1-intc on MIPS, GIC on ARM/ARM64)
>> +
>> +- interrrupts: first interrupt must be the Level 1 interrupt number corresponding
>> +  to the main PCIe RC interrupt, second interrupt must be the MSI interrupt
>> +  See the interrupt-parent documentation for the number of cells and their meaning:
>> +  MIPS: Documentation/devicetree/bindings/interrupt-controller/brcm,bcm7038-l1-intc.txt
>> +  ARM/ARM64: Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
>> +
>> +- interrupt-names: must be "pcie", and if present "msi"
> 
> When I suggested splitting out the MSI support, I was thinking (but not writing)
> that you'd use an msi-parent property to refer to the node that holds the
> msi-controller as well.

Humm fair enough.

> 
>> +- ranges: ranges for the PCI outbound windows, no I/O or prefetchable windows
>> +  must be specified here, only non-prefetchable. 32-bits windows or 64-bits
>> +  windows are allowed based on the host processor's capabilities (ARM w/ LPAE,
>> +  ARM64).
> 
> So this supports 64-bit non-prefetchable windows? Usually 64-bit windows
> are prefetchable.
> 
>> +- brcm,log2-scb-sizes: log2 size of the SCB window that is mapped to PCIe space
>> +  there must be exactly one value per memory controller present in the system
>> +  (ranges from 1 to 3)
> 
> I'm still not too happy with this property. I see no reason for the log2
> format (rather than length in bytes, or offset/length tuples, or dma-ranges,
> or phandles pointing to the memory controllers). I think we need to discuss
> this some more.

Sure, works for me.

> 
>> +- brcm,gen: integer that indicates desired forced generation of link: 1 => 2.5
>> +  Gbps, 2 => 5.0 Gbps, 3 => 8.0 Gbps. Will override the auto-negotation if
>> +  specified.
> 
> to repeat my earlier comment from v1:
> 
> Shouldn't the link generation be probed automatically?

It is, but if the property is present, we can foce the link negotiation,
We have had cases where this was desired and helpful.

> 
>> +- <*>-supply: see Documentation/devicetree/bindings/regulator/regulator.txt
>> +
>> +- <*>-supply-names: see Documentation/devicetree/bindings/regulator/regulator.txt
> 
> I don't see supply-names documented there.

Meh, I read that wrong, will fix that.

Thanks!
-- 
Florian


From hauke at hauke-m.de  Thu May  5 14:47:23 2016
From: hauke at hauke-m.de (Hauke Mehrtens)
Date: Thu, 5 May 2016 23:47:23 +0200
Subject: [PATCH] ARM: BCM5301X: Add DT for Luxul XAP-1510
In-Reply-To: <CACna6ryWGsOwBhhauJTROi2BPbmgGn_4oYnKc-L8-3Joy+5M7g@mail.gmail.com>
References: <1462296501-5209-1-git-send-email-dhaab@luxul.com>
 <572A453E.6010000@gmail.com>
 <CACna6ryWGsOwBhhauJTROi2BPbmgGn_4oYnKc-L8-3Joy+5M7g@mail.gmail.com>
Message-ID: <572BBF6B.8030207@hauke-m.de>

On 05/05/2016 12:36 AM, Rafa? Mi?ecki wrote:
> On 4 May 2016 at 20:53, Florian Fainelli <f.fainelli at gmail.com> wrote:
>> On 03/05/16 10:28, Dan Haab wrote:
>>> Luxul XAP-1510 is an AP device based on BCM4708 SoC. It uses flash
>>> memory connected to the SPI controller.
>>
>> Looks fine, except one nit:
>>
>>> diff --git a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
>>> new file mode 100644
>>> index 0000000..f4460b5
>>> --- /dev/null
>>> +++ b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
>>> @@ -0,0 +1,67 @@
>>> +/*
>>> + * Broadcom BCM470X / BCM5301X ARM platform code.
>>> + * DTS for Luxul XAP-1510
>>> + *
>>> + * Copyright 2015 Luxul Inc.
>>> + *
>>> + * Licensed under the GNU/GPL. See COPYING for details.
>>
>> The ARM SoC maintainer have been asking to utilize a license which is
>> also BSD compatible, so something along the lines of this one:
>>
>> arch/arm/boot/dts/bcm911360k.dts
>>
>> Do you mind respining the patch to include that kind of license header?
> 
> I wasn't aware of this neither. Shall we re-license existing DTS files
> as well? I'm fine with changing them to BSD compatible.
> 
> I'm a bit confused by using BSD license only. Kernel is licensed under
> GNU GPL version 2 and if there are some BSD compatible modules, they
> use dual licensing model (BSD/GPL). Shouldn't we use BSD/GPL in DTS
> files as well then?
> 

As far as I understand the License part you can take code which is
licensed under BSD license and use it in GPL code because you can comply
with the BSD license and also handle it in a way to be GPL compliant at
the same time. You can also make a change to BSD code and license this
change under the GPL, then the complete code (the old one + your change)
is now GPL.

Are the device tree files licensed under BSD license to make it easier
to integrate them into a proprietary boot loader or what is the purpose?

Hauke


From f.fainelli at gmail.com  Thu May  5 14:48:57 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Thu, 5 May 2016 14:48:57 -0700
Subject: [PATCH] ARM: BCM5301X: Add DT for Luxul XAP-1510
In-Reply-To: <572BBF6B.8030207@hauke-m.de>
References: <1462296501-5209-1-git-send-email-dhaab@luxul.com>
 <572A453E.6010000@gmail.com>
 <CACna6ryWGsOwBhhauJTROi2BPbmgGn_4oYnKc-L8-3Joy+5M7g@mail.gmail.com>
 <572BBF6B.8030207@hauke-m.de>
Message-ID: <572BBFC9.1030800@gmail.com>

On 05/05/16 14:47, Hauke Mehrtens wrote:
> On 05/05/2016 12:36 AM, Rafa? Mi?ecki wrote:
>> On 4 May 2016 at 20:53, Florian Fainelli <f.fainelli at gmail.com> wrote:
>>> On 03/05/16 10:28, Dan Haab wrote:
>>>> Luxul XAP-1510 is an AP device based on BCM4708 SoC. It uses flash
>>>> memory connected to the SPI controller.
>>>
>>> Looks fine, except one nit:
>>>
>>>> diff --git a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
>>>> new file mode 100644
>>>> index 0000000..f4460b5
>>>> --- /dev/null
>>>> +++ b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
>>>> @@ -0,0 +1,67 @@
>>>> +/*
>>>> + * Broadcom BCM470X / BCM5301X ARM platform code.
>>>> + * DTS for Luxul XAP-1510
>>>> + *
>>>> + * Copyright 2015 Luxul Inc.
>>>> + *
>>>> + * Licensed under the GNU/GPL. See COPYING for details.
>>>
>>> The ARM SoC maintainer have been asking to utilize a license which is
>>> also BSD compatible, so something along the lines of this one:
>>>
>>> arch/arm/boot/dts/bcm911360k.dts
>>>
>>> Do you mind respining the patch to include that kind of license header?
>>
>> I wasn't aware of this neither. Shall we re-license existing DTS files
>> as well? I'm fine with changing them to BSD compatible.
>>
>> I'm a bit confused by using BSD license only. Kernel is licensed under
>> GNU GPL version 2 and if there are some BSD compatible modules, they
>> use dual licensing model (BSD/GPL). Shouldn't we use BSD/GPL in DTS
>> files as well then?
>>
> 
> As far as I understand the License part you can take code which is
> licensed under BSD license and use it in GPL code because you can comply
> with the BSD license and also handle it in a way to be GPL compliant at
> the same time. You can also make a change to BSD code and license this
> change under the GPL, then the complete code (the old one + your change)
> is now GPL.
> 
> Are the device tree files licensed under BSD license to make it easier
> to integrate them into a proprietary boot loader or what is the purpose?

Yes, there could be that, or just making the license compatible with
other OSes like FreeBSD for instace.
-- 
Florian


From tony at atomide.com  Thu May  5 15:03:44 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 5 May 2016 15:03:44 -0700
Subject: NFSroot hangs with bad unlock balance in Linux next
Message-ID: <20160505220344.GE5995@atomide.com>

Hi,

Looks like Linux next with NFSroot hangs for me at some point booting
into init. Then after a while it produces "BUG: bad unlock balance
detected!".

This happens at least with omap5-uevm and igepv5. Not sure yet if it
also happens on other boards, the ones I'm seeing it happen both have
USB Ethernet controller. They usually hang after the system starts
being idle some tens of seconds into booting.

I tried to bisect it down with no luck. I do have the following
trace, does that provide any clues?

Regards,

Tony

8< --------------------------
[ BUG: bad unlock balance detected! ]
4.6.0-rc6-next-20160505+ #1252 Not tainted
-------------------------------------
kworker/0:2/112 is trying to release lock (&nfsi->rmdir_sem) at:
[<c03a7f98>] nfs_async_unlink_release+0x20/0x68
but there are no more locks to release!

other info that might help us debug this:
2 locks held by kworker/0:2/112:
 #0:  ("nfsiod"){.+.+..}, at: [<c0154774>] process_one_work+0x120/0x6bc
  #1:  ((&task->u.tk_work)#2){+.+...}, at: [<c0154774>] process_one_work+0x120/0x6bc

stack backtrace:
CPU: 0 PID: 112 Comm: kworker/0:2 Not tainted 4.6.0-rc6-next-20160505+ #1252
Hardware name: Generic OMAP5 (Flattened Device Tree)
Workqueue: nfsiod rpc_async_release
[<c0110328>] (unwind_backtrace) from [<c010c3cc>] (show_stack+0x10/0x14)
[<c010c3cc>] (show_stack) from [<c0481348>] (dump_stack+0xb0/0xe4)
[<c0481348>] (dump_stack) from [<c018d638>] (print_unlock_imbalance_bug+0xb0/0xe0)
[<c018d638>] (print_unlock_imbalance_bug) from [<c0191444>] (lock_release+0x2ec/0x4c4)
[<c0191444>] (lock_release) from [<c018abf0>] (up_read+0x18/0x58)
[<c018abf0>] (up_read) from [<c03a7f98>] (nfs_async_unlink_release+0x20/0x68)
[<c03a7f98>] (nfs_async_unlink_release) from [<c0785320>] (rpc_free_task+0x24/0x44)
[<c0785320>] (rpc_free_task) from [<c015483c>] (process_one_work+0x1e8/0x6bc)
[<c015483c>] (process_one_work) from [<c0154e54>] (worker_thread+0x144/0x4e8)
[<c0154e54>] (worker_thread) from [<c015ad0c>] (kthread+0xdc/0xf8)
[<c015ad0c>] (kthread) from [<c01078f0>] (ret_from_fork+0x14/0x24)


From robh at kernel.org  Thu May  5 15:12:12 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 5 May 2016 17:12:12 -0500
Subject: [PATCH v7 7/9] dt-bindings: i2c: rk3x: add support for rk3399
In-Reply-To: <1462372523-6444-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462372523-6444-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <20160505221212.GA26820@rob-hp-laptop>

On Wed, May 04, 2016 at 10:35:23PM +0800, David Wu wrote:
> The bus clock and function clock are separated at rk3399,
> and others use one clock as the bus clock and function clock.
> 
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> ---
>  Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 16 +++++++++++++---
>  1 file changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> index 0b4a85f..82b6f6b 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> +++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> @@ -6,10 +6,20 @@ RK3xxx SoCs.
>  Required properties :
>  
>   - reg : Offset and length of the register set for the device
> - - compatible : should be "rockchip,rk3066-i2c", "rockchip,rk3188-i2c",
> -		"rockchip,rk3228-i2c" or "rockchip,rk3288-i2c".
> + - compatible: should be one of the followings

s/followings/following:/

> +   - "rockchip,rk3066-i2c": for rk3066
> +   - "rockchip,rk3188-i2c": for rk3188
> +   - "rockchip,rk3228-i2c": for rk3228
> +   - "rockchip,rk3288-i2c": for rk3288
> +   - "rockchip,rk3399-i2c": for rk3399
>   - interrupts : interrupt number
> - - clocks : parent clock
> + - clocks: See ../clock/clock-bindings.txt
> +   - For older hardware (rk3066, rk3188, rk3228, rk3288):
> +     - There is one clock that's used both to derive the functional clock
> +       for the device and as the bus clock.  REQUIRED.

This is the required section, so REQUIRED is redundant.

> +   - For newer hardware (rk3399): specify by name
> +     - "i2c": REQUIRED. This is used to derive the functional clock.
> +     - "pclk": REQUIRED. This is the bus clock.equired on RK3066, RK3188 :

This doesn't make sense. The first line says this applies to rk3399, but 
then here it is talking about other parts.

And there's a typo.

>  
>  Required on RK3066, RK3188 :
>  
> -- 
> 1.9.1
> 
> 


From robh at kernel.org  Thu May  5 15:17:13 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 5 May 2016 17:17:13 -0500
Subject: [Patch v3 1/8] dt/bindings: firmware: Add Qualcomm SCM binding
In-Reply-To: <1462402245-18295-2-git-send-email-andy.gross@linaro.org>
References: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
 <1462402245-18295-2-git-send-email-andy.gross@linaro.org>
Message-ID: <20160505221713.GA12273@rob-hp-laptop>

On Wed, May 04, 2016 at 05:50:38PM -0500, Andy Gross wrote:
> This patch adds the device tree support for the Qualcomm SCM firmware.
> 
> Signed-off-by: Andy Gross <andy.gross at linaro.org>
> ---
>  .../devicetree/bindings/firmware/qcom,scm.txt      | 26 ++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/firmware/qcom,scm.txt
> 
> diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
> new file mode 100644
> index 0000000..ee7cd12
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
> @@ -0,0 +1,26 @@
> +QCOM Secure Channel Manager (SCM)
> +
> +Qualcomm processors include an interface to communicate to the secure firmware.
> +This interface allows for clients to request different types of actions.  These
> +can include CPU power up/down, HDCP requests, loading of firmware, and other
> +assorted actions.
> +
> +Required properties:
> +- compatible: must contain one of the following:
> + * "qcom,scm-a-family" for A family Qualcomm processors (APQ8064, MSM8960, etc)
> + * "qcom,scm" for B family and later processors (MSM8916, APQ8084, MSM8974, etc)
> +- clocks: One to three clocks may be required based on compatible.
> + * Only core clock required for "qcom,scm-apq8064"

This is not a compatible string. What happened to the chip ones. I 
thought we decided on chip specific plus one of the above ones.

Rob


From robh at kernel.org  Thu May  5 15:25:21 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 5 May 2016 17:25:21 -0500
Subject: [v10, 1/7] Documentation: DT: update Freescale DCFG compatible
In-Reply-To: <1462417950-46796-2-git-send-email-yangbo.lu@nxp.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <1462417950-46796-2-git-send-email-yangbo.lu@nxp.com>
Message-ID: <20160505222521.GA18377@rob-hp-laptop>

On Thu, May 05, 2016 at 11:12:24AM +0800, Yangbo Lu wrote:
> Update Freescale DCFG compatible with 'fsl,<chip>-dcfg' instead
> of 'fsl,ls1021a-dcfg' to include more chips such as ls1021a,
> ls1043a, and ls2080a.
> 
> Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
> ---
> Changes for v8:
> 	- Added this patch
> Changes for v9:
> 	- Added a list for the possible compatibles
> Changes for v10:
> 	- None
> ---
>  Documentation/devicetree/bindings/arm/fsl.txt | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)

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


From robh at kernel.org  Thu May  5 15:42:40 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 5 May 2016 17:42:40 -0500
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <20160505224240.GA31429@rob-hp-laptop>

On Thu, May 05, 2016 at 02:34:13PM +0200, Krzysztof Kozlowski wrote:
> Hi,
> 
> This is a different, second try to fix usb3503+lan on Odroid U3 board
> if it was initialized by bootloader (e.g. for TFTP boot).
> 
> First version:
> http://www.spinics.net/lists/linux-usb/msg140042.html
> 
> 
> Problem
> =======
> When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
> the usb3503 and LAN smsc95xx do not show up in "lsusb". Hard-reset
> is required, e.g. by suspend to RAM. The actual TFTP boot does
> not have to happen. Just "usb start" from U-Boot is sufficient.
> 
> From the schematics, the regulator is a supply only to LAN, however
> without toggling it off/on, the usb3503 hub won appear neither.
> 
> 
> Solution
> ========
> This is very similar to the MMC pwrseq behavior so the idea is to:
> 1. Move MMC pwrseq drivers to generic place,

You can do that, but I'm going to NAK any use of pwrseq bindings outside 
of MMC. I think it is the wrong way to do things. The DT should describe 
the devices. If they happen to be "simple" then the core can walk the 
tree and do any setup. For example, look for "reset-gpios" and toggle 
that GPIO. There is no need for a special node.

> 2. Extend the pwrseq-simple with regulator toggling,
> 3. Add support to USB hub and port core for pwrseq,

We discussed this for USB already[1] and is why we defined how to add 
USB child devices. The idea is not to add pwrseq to that.

Rob

[1] http://www.spinics.net/lists/linux-usb/msg134082.html


From dianders at chromium.org  Thu May  5 15:55:19 2016
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 5 May 2016 15:55:19 -0700
Subject: [PATCH v7 2/9] i2c: rk3x: use struct "rk3x_i2c_calced_timings"
In-Reply-To: <1462371194-5809-3-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462371194-5809-3-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=WAbedAB78shifxwjmZ-od8rhOiNz80rpdqfwzRsdX6WQ@mail.gmail.com>

David,

On Wed, May 4, 2016 at 7:13 AM, David Wu <david.wu at rock-chips.com> wrote:
> Signed-off-by: David Wu <david.wu at rock-chips.com>

Usually folks like a description and not just a subject line.  I'd add
a description like:

The "div_high" and "div_low" values are always used together.  Group them
into a structure to make it easier to pass them both around.  This
structure also provides a place for future calculated timings.

> ---
> Change in v7:
> - none
>
>  drivers/i2c/busses/i2c-rk3x.c | 55 +++++++++++++++++++++++++------------------
>  1 file changed, 32 insertions(+), 23 deletions(-)

Other than the description, I think this looks fine.

IMHO this can be applied any time independent of any earlier patches.

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


From dianders at chromium.org  Thu May  5 15:55:54 2016
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 5 May 2016 15:55:54 -0700
Subject: [PATCH v7 3/9] i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd()
In-Reply-To: <1462371194-5809-4-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462371194-5809-4-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=XpS4UYR5ORXUOGJXPXBr_Tpc6r87+Tm83KE654ZbkdzA@mail.gmail.com>

David,

On Wed, May 4, 2016 at 7:13 AM, David Wu <david.wu at rock-chips.com> wrote:
> Call rk3x_i2c_setup() before rk3x_i2c_start()
> and the last thing in setup was to clean the IPD,
> so no reason to do it at the beginning of start.
>
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> ---
> Change in v7:
> - none
>
>  drivers/i2c/busses/i2c-rk3x.c | 1 -
>  1 file changed, 1 deletion(-)

Looks great.  Thanks for splitting this out from other patches--makes
it much more obvious what's happening!  :)

IMHO this can be applied any time independent of any earlier patches.

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


From dianders at chromium.org  Thu May  5 15:56:45 2016
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 5 May 2016 15:56:45 -0700
Subject: [PATCH v7 4/9] i2c: rk3x: Move setting STATE_START and add
 STATE_SETUP
In-Reply-To: <1462371194-5809-5-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462371194-5809-5-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=WVKpJJbqc=UYbeObDurjte0iQOzvLL++i=wM9=TBeCDQ@mail.gmail.com>

David,

On Wed, May 4, 2016 at 7:13 AM, David Wu <david.wu at rock-chips.com> wrote:
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> ---
> Change in v7:
> - none
>
>  drivers/i2c/busses/i2c-rk3x.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)

Probably this change could be dropped now.  Switching the location of
setting START_START was much more important when you were supporting
HIGH SPEED mode.  I don't think we need it anymore, right?

...if we want to keep this change, I'd say:

1. Add a description, like maybe:

To help with debugging add a STATE_SETUP between STATE_IDLE and
STATE_START to make it more obvious that we're not actually idle but we
also haven't initiated the start bit.  This change is not expected to
have any impact but it does delay the changing of state to STATE_START.
If previously we were getting an erroneous interrupt before we actually
sent the start bit we'll now be treating that differently.  The new
behavior (catching the erroneous interrupt) should be better.

2. Change "i2c->state = STATE_SETUP" to the _start_ of
rk3x_i2c_setup().  That would have a better chance of catching a
spurious interrupt.

3. Add an error check at the start of rk3x_i2c_irq() similar to the
check for STATE_IDLE (or use the same check and modify the printk).
Specifically the justification for adding STATE_SETUP is to help with
debugging (catch interrupts that were unexpected and print more info
about our state), so we should make it useful for this.


-Doug


From dianders at chromium.org  Thu May  5 15:57:39 2016
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 5 May 2016 15:57:39 -0700
Subject: [PATCH v7 5/9] i2c: rk3x: Change SoC data to not use array
In-Reply-To: <1462372418-6349-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462372418-6349-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=UsLmiASrso1SM5aGQPmJKNSXS260E7fiiYgmFQ4t1jpA@mail.gmail.com>

Hi,

On Wed, May 4, 2016 at 7:33 AM, David Wu <david.wu at rock-chips.com> wrote:
> Signed-off-by: David Wu <david.wu at rock-chips.com>

nit: $SUBJECT should probably mention that this also constifies the SoC data.


Again, needs description, like maybe:

Specifying the i2c SoC data in an array provides very little benefit and
gets unwieldly / confusing as the array grows since the next bit of code
needs to refer to elements in the array by their raw integral index.

Let's just create a single 'static const' structure for each SoC so that
we can refer to these structures by ID.


IMHO this can be applied any time independent of any earlier patches.

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


From dianders at chromium.org  Thu May  5 15:58:47 2016
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 5 May 2016 15:58:47 -0700
Subject: [PATCH v7 6/9] i2c: rk3x: Move spec timing data to "static const"
 structs
In-Reply-To: <1462372472-6396-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462372472-6396-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=Vg+umhA73uR66AdFmaNKhpyXCYojqE9kZJqkTOsyK_Jg@mail.gmail.com>

David,

On Wed, May 4, 2016 at 7:34 AM, David Wu <david.wu at rock-chips.com> wrote:
> Signed-off-by: David Wu <david.wu at rock-chips.com>

As you can probably guess, again a description would be nice.  Like maybe:

The i2c timing specs are really just constant data.  There's no reason
to write code to init them, so move them out to structures.  This not
only is a cleaner solution but it will reduce code duplication when we
introduce a new variant of rk3x_i2c_calc_divs() in a future patch.

That helps someone reading the patch understand the motivation.


> @@ -76,6 +76,51 @@ enum {
>  #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */
>
>  /**
> + * struct i2c_spec_values:
> + * @min_hold_start_ns: min hold time (repeated) START condition
> + * @min_low_ns: min LOW period of the SCL clock
> + * @min_high_ns: min HIGH period of the SCL cloc
> + * @min_setup_start_ns: min set-up time for a repeated START conditio
> + * @max_data_hold_ns: max data hold time
> + * @min_data_setup_ns: min data set-up time
> + * @min_setup_stop_ns: min set-up time for STOP condition
> + * @min_hold_buffer_ns: min bus free time between a STOP and
> + * START condition
> + */
> +struct i2c_spec_values {
> +       unsigned long min_hold_start_ns;
> +       unsigned long min_low_ns;
> +       unsigned long min_high_ns;
> +       unsigned long min_setup_start_ns;
> +       unsigned long max_data_hold_ns;
> +       unsigned long min_data_setup_ns;
> +       unsigned long min_setup_stop_ns;
> +       unsigned long min_hold_buffer_ns;
> +};
> +
> +static const struct i2c_spec_values standard_mode_spec = {
> +       .min_hold_start_ns = 4000,
> +       .min_low_ns = 4700,
> +       .min_high_ns = 4000,
> +       .min_setup_start_ns = 4700,
> +       .max_data_hold_ns = 3450,
> +       .min_data_setup_ns = 250,
> +       .min_setup_stop_ns = 4000,
> +       .min_hold_buffer_ns = 4700,

There are more spec values than are currently used in this patch.
Personally I'm OK with that, but if you wanted to be totally clean
this patch would only include the spec values that were needed, then
introduce the additional values in the rk3399 patch.


> @@ -492,6 +548,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
>         unsigned long min_div_for_hold, min_total_div;
>         unsigned long extra_div, extra_low_div, ideal_low_div;
>
> +       unsigned long data_hold_buffer_ns = 50;

aside (feel free to ignore): Gosh, I kinda forgot what the heck this
value was for.  I guess it's not anything in the spec.  I have a
feeling it was some sort of slop value that someone felt was
necessary, but I don't quite remember.  Oh well, I guess we leave it
there since I'd rather not mess with timings on old hardware that are
apparently working for everyone.  :-P


In any case, aside from the missing description:

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

IMHO this can be applied any time independent of any earlier patches.


-Doug


From dianders at chromium.org  Thu May  5 15:59:58 2016
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 5 May 2016 15:59:58 -0700
Subject: [PATCH v7 7/9] dt-bindings: i2c: rk3x: add support for rk3399
In-Reply-To: <1462372523-6444-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462372523-6444-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=XXojzZiVFuXuChZdDeTxE6tFSJZ=8FqLpVTG2L6xWpBg@mail.gmail.com>

Hi,

On Wed, May 4, 2016 at 7:35 AM, David Wu <david.wu at rock-chips.com> wrote:
> The bus clock and function clock are separated at rk3399,
> and others use one clock as the bus clock and function clock.
>
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> ---
>  Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 16 +++++++++++++---
>  1 file changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> index 0b4a85f..82b6f6b 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> +++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> @@ -6,10 +6,20 @@ RK3xxx SoCs.
>  Required properties :
>
>   - reg : Offset and length of the register set for the device
> - - compatible : should be "rockchip,rk3066-i2c", "rockchip,rk3188-i2c",
> -               "rockchip,rk3228-i2c" or "rockchip,rk3288-i2c".
> + - compatible: should be one of the followings
> +   - "rockchip,rk3066-i2c": for rk3066
> +   - "rockchip,rk3188-i2c": for rk3188
> +   - "rockchip,rk3228-i2c": for rk3228
> +   - "rockchip,rk3288-i2c": for rk3288
> +   - "rockchip,rk3399-i2c": for rk3399
>   - interrupts : interrupt number
> - - clocks : parent clock
> + - clocks: See ../clock/clock-bindings.txt
> +   - For older hardware (rk3066, rk3188, rk3228, rk3288):
> +     - There is one clock that's used both to derive the functional clock
> +       for the device and as the bus clock.  REQUIRED.
> +   - For newer hardware (rk3399): specify by name
> +     - "i2c": REQUIRED. This is used to derive the functional clock.
> +     - "pclk": REQUIRED. This is the bus clock.equired on RK3066, RK3188 :

Looks great except that you need to delete the "equired on RK3066,
RK3188 :" part, which looks like it was leftover from some sort of
copy/paste.

Once that is done, feel free to add my Reviewed-by tag.


-Doug


From dianders at chromium.org  Thu May  5 16:00:56 2016
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 5 May 2016 16:00:56 -0700
Subject: [PATCH v7 8/9] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <1462372609-6535-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462372609-6535-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=VhMJiowNWm+0=jzzK0vajg1=3PutaWbzhGPN_BU2+19w@mail.gmail.com>

David,

On Wed, May 4, 2016 at 7:36 AM, David Wu <david.wu at rock-chips.com> wrote:
> +/**
> + * Calculate timing values for desired SCL frequency
> + *
> + * @clk_rate: I2C input clock rate
> + * @t: Known I2C timing information
> + * @t_calc: Caculated rk3x private timings that would be written into regs
> +
> + * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
> + * a best-effort divider value is returned in divs. If the target rate is
> + * too high, we silently use the highest possible rate.
> + * The following formulas are v1's method to calculate timings.
> + *
> + * l = divl + 1;
> + * h = divh + 1;
> + * s = sda_update_config + 1;
> + * u = start_setup_config + 1;
> + * p = stop_setup_config + 1;
> + * T = Tclk_i2c;
> +
> + * tHigh = 8 * h * T;
> + * tLow = 8 * l * T;
> +
> + * tHD;sda = (l * s + 1) * T;
> + * tSU;sda = [(8 - s) * l + 1] * T;
> + * tI2C = 8 * (l + h) * T;
> +
> + * tSU;sta = (8h * u + 1) * T;
> + * tHD;sta = [8h * (u + 1) - 1] * T;
> + * tSU;sto = (8h * p + 1) * T;
> + */
> +static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
> +                                   struct i2c_timings *t,
> +                                   struct rk3x_i2c_calced_timings *t_calc)
> +{

I don't think I'm going to try to understand all the math here.  I'll
trust you that this does something sane.


> +       /* Final divh and divl must be greater than 0, otherwise the
> +        * hardware would not output the i2c clk.
> +        */

nit: multiline comment style doesn't match rest of file.


>  static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
>  {
>         struct i2c_timings *t = &i2c->t;
> -       struct rk3x_i2c_calced_timings calc;
> +       struct rk3x_i2c_calced_timings *calc = &i2c->t_calc;
>         u64 t_low_ns, t_high_ns;
>         int ret;
>
> -       ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
> +       ret = i2c->soc_data->calc_timings(clk_rate, t, calc);
>         WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
>
> -       clk_enable(i2c->clk);
> -       i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
> +       if (i2c->pclk)
> +               clk_enable(i2c->pclk);
> +       else
> +               clk_enable(i2c->clk);
> +       i2c_writel(i2c, (calc->div_high << 16) | (calc->div_low & 0xffff),
>                    REG_CLKDIV);

There is a subtle bug here, though it likely doesn't manifest in any
current hardware configurations.

Specifically if you get a clock change on a device with a "v1"
controller while an i2c transaction is happening then you will likely
get i2c errors.

The clock change notifications work like this:
* Before the clock change, adjust the timings based on the faster of
the old/new clock.
* Let the clock change happen.
* If we didn't adjust the timings before, adjust them now.

With the logic above there will be a period where the i2c transaction
is happening slower than ideal, but that should be OK.  ...and you can
imagine the speed of the transaction changing midway through the
transaction--even midway through a single byte.


With v1 some of the timing information is _not_updated by
rk3x_i2c_adapt_div()--it's only set at the start of a transaction.
That breaks all the above assumptions.

So you should probably be updating the the RKI2C_CON register here by
doing a read-modify-write, like:

ctrl = i2c_readl(i2c, REG_CON);
ctrl &= ~REG_CON_TUNING_MASK;
ctrl |= i2c->t_calc.tuning;
i2c_writel(i2c, ctrl, REG_CON);


Also (optional): once you do that, there becomes much less of a reason
to store "t_calc" in "struct rk3x_i2c".  Already you're never using
the "div_low" and "div_high" that you store in the "struct rk3x_i2c".
Of course, to do that you've got to change other places not to clobber
these bits in REG_CON.


> @@ -728,11 +910,11 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
>  {
>         struct clk_notifier_data *ndata = data;
>         struct rk3x_i2c *i2c = container_of(nb, struct rk3x_i2c, clk_rate_nb);
> -       struct rk3x_i2c_calced_timings calc;
>
>         switch (event) {
>         case PRE_RATE_CHANGE:
> -               if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &calc) != 0)
> +               if (i2c->soc_data->calc_timings(ndata->new_rate, &i2c->t,
> +                                               &i2c->t_calc) != 0)

This change is incorrect.  Please change it back to being calculated
in a local variable.  Optionally also add a comment that says:

/*
 * Try the calculation (but don't store the result) ahead of
 * time to see if we need to block the clock change.  Timings
 * shouldn't actually take effect until rk3x_i2c_adapt_div().
 */

Specifically in the case that we return NOTIFY_STOP here we _don't_
want to have modified our internal timings.  We also _don't_ want to
have modified our internal timings in the case that the old_rate > the
new_rate.

BTW: Did you manage to find anyone using an old Rockchip SoC that can
test your patches?


> @@ -1042,17 +1236,38 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
>
>         platform_set_drvdata(pdev, i2c);
>
> +       i2c->clk = devm_clk_get(&pdev->dev, NULL);
> +       if (IS_ERR(i2c->clk)) {
> +               dev_err(&pdev->dev, "cannot get clock\n");
> +               return PTR_ERR(i2c->clk);
> +       }
> +
>         ret = clk_prepare(i2c->clk);
>         if (ret < 0) {
>                 dev_err(&pdev->dev, "Could not prepare clock\n");
>                 return ret;
>         }
>
> +       if (i2c->soc_data->calc_timings == rk3x_i2c_v1_calc_timings) {
> +               i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
> +               if (IS_ERR(i2c->pclk)) {
> +                       dev_err(i2c->dev, "Could not get i2c pclk\n");
> +                       ret = PTR_ERR(i2c->pclk);
> +                       goto err_clk;
> +               }
> +
> +               ret = clk_prepare(i2c->pclk);
> +               if (ret) {
> +                       dev_err(i2c->dev, "Could not prepare pclk\n");
> +                       goto err_clk;
> +               }
> +       }

This is not matching the bindings.  You are still assuming that "i2c"
clock is the first clock and "pclk" is the one named "pclk".  Said
another way, if you had the following in your device tree:

  clocks =  <&pmucru PCLK_I2C0_PMU>, <&pmucru SCLK_I2C0_PMU>;
  clock-names = "pclk", "i2c";

...you'll find that you'll get back "pclk" twice.  The first time
you'll get it because you asked for the first clock listed, the second
time because you asked for the clock named "pclk".

I'd also say that your life will probably be easier if you always
setup both "clk" and "pclk", even on old CPUs.  It's OK to call
"clk_prepare" twice and OK to call "clk_enable" twice.

Thus, I'd probably write all the code as this (untested):

  if (i2c->soc_data->calc_timings == rk3x_i2c_v0_calc_timings) {
    /* Only one clock to use for bus clock and peripheral clock */
    i2c->clk = devm_clk_get(&pdev->dev, NULL);
    i2c->pclk = i2c->clk;
  } else {
    i2c->clk = devm_clk_get(&pdev->dev, "i2c");
    i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
  }
  if (IS_ERR(i2c->clk)) {
    ret = PTR_ERR(i2c->clk);
    if (ret != -EPROBE_DEFER)
      dev_err(&pdev->dev, "Can't get bus clk: %d\n", ret);
    return ret;
  }
  if (IS_ERR(i2c->pclk)) {
    ret = PTR_ERR(i2c->pclk);
    if (ret != -EPROBE_DEFER)
      dev_err(&pdev->dev, "Can't get periph clk: %d\n", ret);
    return ret;
  }
  ret = clk_prepare(i2c->clk);
  if (ret < 0) {
    dev_err(&pdev->dev, "Can't prepare bus clk: %d\n", ret);
    return ret;
  }
  ret = clk_prepare(i2c->pclk);
  if (ret < 0) {
    dev_err(&pdev->dev, "Can't prepare periph clock: %d\n", ret);
    goto err_clk;
  }

If you take that advice, you can get rid of all of the "if
(i2c->pclk)" statements in your code.


-Doug


From dianders at chromium.org  Thu May  5 16:02:16 2016
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 5 May 2016 16:02:16 -0700
Subject: [PATCH v7 9/9] i2c: rk3x: support fast-mode plus for rk3399
In-Reply-To: <1462372668-6583-1-git-send-email-david.wu@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462372668-6583-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=UtHPDtB7LTbUpwcjOcoYwNma59-TRDU3hrt6c_2TWxxA@mail.gmail.com>

David,

On Wed, May 4, 2016 at 7:37 AM, David Wu <david.wu at rock-chips.com> wrote:
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> ---
>  drivers/i2c/busses/i2c-rk3x.c | 21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> index 47368c4..c66cc39 100644
> --- a/drivers/i2c/busses/i2c-rk3x.c
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -124,6 +124,17 @@ static const struct i2c_spec_values fast_mode_spec = {
>         .min_hold_buffer_ns = 1300,
>  };
>
> +static const struct i2c_spec_values fast_mode_plus_spec = {
> +       .min_hold_start_ns = 260,
> +       .min_low_ns = 500,
> +       .min_high_ns = 260,
> +       .min_setup_start_ns = 260,
> +       .max_data_hold_ns = 400,

I'm curious where you got the data_hold_ns.  I can't quite remember
what this parameter does / how the timing function works anymore, but
the doc I have (search for UM10204 and click the first link) shows
values for Standard-mode and Fast-mode but not Fast-mode Plus.  It
seems to imply that this is a bit of a bogus number anyway because it
only matters if we don't stretch the tLOW to go along with the longer
data hold.

As I have said in the previous patch, how all this stuff works has
totally left my brain, so if you understand it that's probably good
enough.  If you feel like I should try to re-understand this again so
I can review it more deeply, let me know.


Since I assume that you had some sane reason to include max_data_hold_ns:

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


From xow at google.com  Thu May  5 16:11:53 2016
From: xow at google.com (Xo Wang)
Date: Thu, 5 May 2016 23:11:53 +0000 (UTC)
Subject: [PATCH v2 09/11] arm/dst: Add Aspeed ast2500 device tree
References: <1461225849-28074-1-git-send-email-joel@jms.id.au>
 <1461225849-28074-10-git-send-email-joel@jms.id.au>
Message-ID: <loom.20160506T005831-472@post.gmane.org>

Joel Stanley <joel <at> jms.id.au> writes:
> +/ {
> +	model = "AST2500 EVB";
> +	compatible = "aspeed,ast2500";
> +
> +	chosen {
> +		stdout-path = &uart5;
> +		bootargs = "console=ttyS4,115200";
> +	};
> +
> +	memory {
> +		reg = < 0x80000000 0x10000000 >;

The AST2500 EVB has an SK Hynix H5AN4G6NMFR 4Gb part, so this should be 
0x20000000 for size.

> +			uart1: serial <at> 1e783000 {
> +				compatible = "ns16550a";
> +				reg = <0x1e783000 0x1000>;
> +				reg-shift = <2>;
> +				interrupts = <9>;
> +				clock-frequency = <1843200>;

The AST2500 datasheet 39.3.1 states the input clock to their 16550 IP is 
24 MHz. Their u-boot code also has #define CONFIG_SYS_NS16550_CLK 
24000000. I suspect we hit a path in the serial/8250 driver that doesn't 
change the divisor from what u-boot set, which is why this has worked.

Thanks for the porting work!

cheers
//xo




From andy.gross at linaro.org  Thu May  5 16:16:11 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 5 May 2016 18:16:11 -0500
Subject: [Patch v3 1/8] dt/bindings: firmware: Add Qualcomm SCM binding
In-Reply-To: <20160505221713.GA12273@rob-hp-laptop>
References: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
 <1462402245-18295-2-git-send-email-andy.gross@linaro.org>
 <20160505221713.GA12273@rob-hp-laptop>
Message-ID: <CAPBZ5QfYOiGniV6PGRRRgAb2sy=J2TjVSxM-+42GR+4mU-Ht9w@mail.gmail.com>

On 5 May 2016 at 17:17, Rob Herring <robh at kernel.org> wrote:
> On Wed, May 04, 2016 at 05:50:38PM -0500, Andy Gross wrote:
>> This patch adds the device tree support for the Qualcomm SCM firmware.
>>
>> Signed-off-by: Andy Gross <andy.gross at linaro.org>
>> ---
>>  .../devicetree/bindings/firmware/qcom,scm.txt      | 26 ++++++++++++++++++++++
>>  1 file changed, 26 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/firmware/qcom,scm.txt
>>
>> diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
>> new file mode 100644
>> index 0000000..ee7cd12
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
>> @@ -0,0 +1,26 @@
>> +QCOM Secure Channel Manager (SCM)
>> +
>> +Qualcomm processors include an interface to communicate to the secure firmware.
>> +This interface allows for clients to request different types of actions.  These
>> +can include CPU power up/down, HDCP requests, loading of firmware, and other
>> +assorted actions.
>> +
>> +Required properties:
>> +- compatible: must contain one of the following:
>> + * "qcom,scm-a-family" for A family Qualcomm processors (APQ8064, MSM8960, etc)
>> + * "qcom,scm" for B family and later processors (MSM8916, APQ8084, MSM8974, etc)
>> +- clocks: One to three clocks may be required based on compatible.
>> + * Only core clock required for "qcom,scm-apq8064"
>
> This is not a compatible string. What happened to the chip ones. I
> thought we decided on chip specific plus one of the above ones.

Stephen specifically didn't like the chip ones due to churn.  We'd
have to add compat tags every time we got a new chip.... which is kind
of frequent.  So I opted for defining one compat for older A family
chips that require only 1 clock.  The qcom,scm would cover the newer
chips.

And it looks like i left a reference to apq8064.  That needs to be
replaced with a-family.  Sorry for that confusion.

Regards,

Andy


From jonmason at broadcom.com  Thu May  5 16:29:31 2016
From: jonmason at broadcom.com (Jon Mason)
Date: Thu,  5 May 2016 19:29:31 -0400
Subject: [PATCH 2/3] ARM: dts: NSP: modify second CPU address
In-Reply-To: <1462490972-13566-1-git-send-email-jonmason@broadcom.com>
References: <1462490972-13566-1-git-send-email-jonmason@broadcom.com>
Message-ID: <1462490972-13566-2-git-send-email-jonmason@broadcom.com>

NSP B0 has a different address for the second core.  Since there should
not be any Ax versions in the field, it should be safe to universally
change this.

Signed-off-by: Jon Mason <jonmason at broadcom.com>
---
 arch/arm/boot/dts/bcm-nsp.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi
index a44bf29..1759e65 100644
--- a/arch/arm/boot/dts/bcm-nsp.dtsi
+++ b/arch/arm/boot/dts/bcm-nsp.dtsi
@@ -57,7 +57,7 @@
 			compatible = "arm,cortex-a9";
 			next-level-cache = <&L2>;
 			enable-method = "brcm,bcm-nsp-smp";
-			secondary-boot-reg = <0xffff042c>;
+			secondary-boot-reg = <0xffff0fec>;
 			reg = <0x1>;
 		};
 	};
-- 
1.9.1



From jonmason at broadcom.com  Thu May  5 16:29:30 2016
From: jonmason at broadcom.com (Jon Mason)
Date: Thu,  5 May 2016 19:29:30 -0400
Subject: [PATCH 1/3] ARM: dts: NSP: Add MSI support on PCI
Message-ID: <1462490972-13566-1-git-send-email-jonmason@broadcom.com>

Add MSI support to the PCI driver of the Northstar Plus SoC.  This uses
the existing pcie-iproc driver.  So, all that is needed is device tree
entries in the DTS.

Signed-off-by: Jon Mason <jonmason at broadcom.com>
---
 arch/arm/boot/dts/bcm-nsp.dtsi | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi
index def9e78..a44bf29 100644
--- a/arch/arm/boot/dts/bcm-nsp.dtsi
+++ b/arch/arm/boot/dts/bcm-nsp.dtsi
@@ -290,6 +290,18 @@
 		ranges = <0x82000000 0 0x08000000 0x08000000 0 0x8000000>;
 
 		status = "disabled";
+
+		msi-parent = <&msi0>;
+		msi0: msi at 18012000 {
+			compatible = "brcm,iproc-msi";
+			msi-controller;
+			interrupt-parent = <&gic>;
+			interrupts = <GIC_SPI 127 IRQ_TYPE_NONE>,
+				     <GIC_SPI 128 IRQ_TYPE_NONE>,
+				     <GIC_SPI 129 IRQ_TYPE_NONE>,
+				     <GIC_SPI 130 IRQ_TYPE_NONE>;
+			brcm,pcie-msi-inten;
+		};
 	};
 
 	pcie1: pcie at 18013000 {
@@ -314,6 +326,18 @@
 		ranges = <0x82000000 0 0x40000000 0x40000000 0 0x8000000>;
 
 		status = "disabled";
+
+		msi-parent = <&msi1>;
+		msi1: msi at 18013000 {
+			compatible = "brcm,iproc-msi";
+			msi-controller;
+			interrupt-parent = <&gic>;
+			interrupts = <GIC_SPI 133 IRQ_TYPE_NONE>,
+				     <GIC_SPI 134 IRQ_TYPE_NONE>,
+				     <GIC_SPI 135 IRQ_TYPE_NONE>,
+				     <GIC_SPI 136 IRQ_TYPE_NONE>;
+			brcm,pcie-msi-inten;
+		};
 	};
 
 	pcie2: pcie at 18014000 {
@@ -338,5 +362,17 @@
 		ranges = <0x82000000 0 0x48000000 0x48000000 0 0x8000000>;
 
 		status = "disabled";
+
+		msi-parent = <&msi2>;
+		msi2: msi at 18014000 {
+			compatible = "brcm,iproc-msi";
+			msi-controller;
+			interrupt-parent = <&gic>;
+			interrupts = <GIC_SPI 139 IRQ_TYPE_NONE>,
+				     <GIC_SPI 140 IRQ_TYPE_NONE>,
+				     <GIC_SPI 141 IRQ_TYPE_NONE>,
+				     <GIC_SPI 142 IRQ_TYPE_NONE>;
+			brcm,pcie-msi-inten;
+		};
 	};
 };
-- 
1.9.1



From jonmason at broadcom.com  Thu May  5 16:29:32 2016
From: jonmason at broadcom.com (Jon Mason)
Date: Thu,  5 May 2016 19:29:32 -0400
Subject: [PATCH 3/3] ARM: dts: NSP: Add new DT file for bcm958625hr
In-Reply-To: <1462490972-13566-1-git-send-email-jonmason@broadcom.com>
References: <1462490972-13566-1-git-send-email-jonmason@broadcom.com>
Message-ID: <1462490972-13566-3-git-send-email-jonmason@broadcom.com>

Create a new device tree file for the Broadcom Northstar Plus HR SVK.
This SVK is a smaller form factor, and thus only has 2 PCI slots and 1
UART.  Also, it has the ability to reboot via GPIO (instead of the
processor reset).

Signed-off-by: Jon Mason <jonmason at broadcom.com>
---
 arch/arm/boot/dts/Makefile        |   1 +
 arch/arm/boot/dts/bcm958625hr.dts | 107 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)
 create mode 100644 arch/arm/boot/dts/bcm958625hr.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 95c1923..17e185c 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -97,6 +97,7 @@ dtb-$(CONFIG_ARCH_BCM_MOBILE) += \
 	bcm28155-ap.dtb \
 	bcm21664-garnet.dtb
 dtb-$(CONFIG_ARCH_BCM_NSP) += \
+	bcm958625hr.dtb \
 	bcm958625k.dtb
 dtb-$(CONFIG_ARCH_BERLIN) += \
 	berlin2-sony-nsz-gs7.dtb \
diff --git a/arch/arm/boot/dts/bcm958625hr.dts b/arch/arm/boot/dts/bcm958625hr.dts
new file mode 100644
index 0000000..d82cc96
--- /dev/null
+++ b/arch/arm/boot/dts/bcm958625hr.dts
@@ -0,0 +1,107 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright (c) 2016 Broadcom.  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in
+ *      the documentation and/or other materials provided with the
+ *      distribution.
+ *    * Neither the name of Broadcom Corporation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+#include "bcm-nsp.dtsi"
+
+/ {
+	model = "NorthStar Plus SVK (BCM958625HR)";
+	compatible = "brcm,bcm58625", "brcm,nsp";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&nand {
+	nandcs at 0 {
+		compatible = "brcm,nandcs";
+		reg = <0>;
+		nand-on-flash-bbt;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		nand-ecc-strength = <24>;
+		nand-ecc-step-size = <1024>;
+
+		brcm,nand-oob-sector-size = <27>;
+
+		partition at 0 {
+			label = "nboot";
+			reg = <0x00000000 0x00200000>;
+			read-only;
+		};
+		partition at 200000 {
+			label = "nenv";
+			reg = <0x00200000 0x00400000>;
+		};
+		partition at 600000 {
+			label = "nsystem";
+			reg = <0x00600000 0x00a00000>;
+		};
+		partition at 1000000 {
+			label = "nrootfs";
+			reg = <0x01000000 0x03000000>;
+		};
+		partition at 4000000 {
+			label = "ncustfs";
+			reg = <0x04000000 0x3c000000>;
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
+
+&pcie1 {
+	status = "okay";
+};
+
+&pinctrl {
+	pinctrl-names = "default";
+	pinctrl-0 = <&nand_sel>;
+	nand_sel: nand_sel {
+		function = "nand";
+		groups = "nand_grp";
+	};
+};
-- 
1.9.1



From linux at roeck-us.net  Thu May  5 16:36:03 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Thu, 5 May 2016 16:36:03 -0700
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <572B8F52.2000709@codeaurora.org>
References: <5728A7C3.4010001@roeck-us.net>
 <20160503143856.GE13045@dhcppc6.redhat.com> <5728BEC4.6050603@codeaurora.org>
 <20160503155141.GF13045@dhcppc6.redhat.com>
 <20160503171602.GA2518@roeck-us.net>
 <20160504141449.GG13045@dhcppc6.redhat.com> <572A0577.1070000@codeaurora.org>
 <20160504155932.GH13045@dhcppc6.redhat.com> <572A2099.4070901@codeaurora.org>
 <20160505164300.GA16914@roeck-us.net>
 <20160505182031.GB12434@dhcppc6.redhat.com> <572B8F52.2000709@codeaurora.org>
Message-ID: <572BD8E3.4070707@roeck-us.net>

On 05/05/2016 11:22 AM, Timur Tabi wrote:
> Pratyush Anand wrote:
>> I think, in the long run we must have SBSA
>> watchdog specification improvement to keep WOR as 64 bit.
>
> I agree with this 100%.  IMHO, using a 32-bit WOR was just a bad decision.
>

A 32-bit counter is absolutely fine. Letting it run with a 400MHz clock
(or was it 200 MHz ?) is the problem. A resolution of 2.5ns for a watchdog
timer does not really make any sense.

Guenter



From timur at codeaurora.org  Thu May  5 16:38:01 2016
From: timur at codeaurora.org (Timur Tabi)
Date: Thu, 5 May 2016 18:38:01 -0500
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <572BD8E3.4070707@roeck-us.net>
References: <5728A7C3.4010001@roeck-us.net>
 <20160503143856.GE13045@dhcppc6.redhat.com> <5728BEC4.6050603@codeaurora.org>
 <20160503155141.GF13045@dhcppc6.redhat.com>
 <20160503171602.GA2518@roeck-us.net>
 <20160504141449.GG13045@dhcppc6.redhat.com> <572A0577.1070000@codeaurora.org>
 <20160504155932.GH13045@dhcppc6.redhat.com> <572A2099.4070901@codeaurora.org>
 <20160505164300.GA16914@roeck-us.net>
 <20160505182031.GB12434@dhcppc6.redhat.com> <572B8F52.2000709@codeaurora.org>
 <572BD8E3.4070707@roeck-us.net>
Message-ID: <572BD959.3090507@codeaurora.org>

Guenter Roeck wrote:
> A 32-bit counter is absolutely fine. Letting it run with a 400MHz clock
> (or was it 200 MHz ?) is the problem. A resolution of 2.5ns for a watchdog
> timer does not really make any sense.

The 10 second limit is based on a 20MHz clock.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum, a Linux Foundation collaborative project.


From timur at codeaurora.org  Thu May  5 16:45:52 2016
From: timur at codeaurora.org (Timur Tabi)
Date: Thu, 5 May 2016 18:45:52 -0500
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <572BD959.3090507@codeaurora.org>
References: <5728A7C3.4010001@roeck-us.net>
 <20160503143856.GE13045@dhcppc6.redhat.com> <5728BEC4.6050603@codeaurora.org>
 <20160503155141.GF13045@dhcppc6.redhat.com>
 <20160503171602.GA2518@roeck-us.net>
 <20160504141449.GG13045@dhcppc6.redhat.com> <572A0577.1070000@codeaurora.org>
 <20160504155932.GH13045@dhcppc6.redhat.com> <572A2099.4070901@codeaurora.org>
 <20160505164300.GA16914@roeck-us.net>
 <20160505182031.GB12434@dhcppc6.redhat.com> <572B8F52.2000709@codeaurora.org>
 <572BD8E3.4070707@roeck-us.net> <572BD959.3090507@codeaurora.org>
Message-ID: <572BDB30.9060602@codeaurora.org>

Timur Tabi wrote:
>
>> A 32-bit counter is absolutely fine. Letting it run with a 400MHz clock
>> (or was it 200 MHz ?) is the problem. A resolution of 2.5ns for a
>> watchdog
>> timer does not really make any sense.
>
> The 10 second limit is based on a 20MHz clock.

No, that's not true.  I misread the code.  I knew something was wrong, 
but it didn't click until just now.

The default timeout is 10 seconds.  The max timeout on a 20MHz system 
(which is what we're running) is over 200 seconds.

The problem is that Pratyush's system is running at a clock that's way 
too fast:

  [  131.187562] sbsa-gwdt sbsa-gwdt.0: Initialized with 40s timeout @ 
250000000 Hz, action=1.

250MHz is unreasonable.  Pratyush, why is your system counter so high? 
On our ARM64 system, it's set to 20MHz.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum, a Linux Foundation collaborative project.


From horms at verge.net.au  Thu May  5 16:49:07 2016
From: horms at verge.net.au (Simon Horman)
Date: Fri, 6 May 2016 08:49:07 +0900
Subject: [PATCH 0/3] ARM/arm64: dts: renesas: Describe RTS/CTS hardware
 flow control
In-Reply-To: <1462352278-30327-1-git-send-email-geert+renesas@glider.be>
References: <1462352278-30327-1-git-send-email-geert+renesas@glider.be>
Message-ID: <20160505234906.GD24999@verge.net.au>

Hi Geert,

On Wed, May 04, 2016 at 10:57:55AM +0200, Geert Uytterhoeven wrote:
> 	Hi Simon, Magnus,
> 
> This patch series updates the various Renesas DTSes to describe that
> some UARTS have dedicated lines for RTS/CTS hardware flow control, and
> that they are available for use (wired and enabled by pinmux
> configuration), by adding the "uart-has-rtscts" property to
> board-specific DTS files where appropriate.
> 
> While the actual DT binding updates documenting the "uart-has-rtscts"
> property for SCIF(A) UARTs ("serial: sh-sci: Update DT binding
> documentation for dedicated RTS/CTS") hasn't been accepted into tty-next
> yet, this property is part of the Generic Serial DT Bindings
> (Documentation/devicetree/bindings/serial/serial.txt), which has been
> accepted.

On the basis of the binding being present in the generic documentation
I have queued up these patches. If that was not your intention please
let me know.

> Actual enablement of RTS/CTS hardware flow control (through setting the
> CRTSCTS termios flag from userspace) depends on series "[PATCH v2 00/11]
> serial: sh-sci: Hardware Flow Control Updates"
> (http://www.spinics.net/lists/linux-serial/msg22535.html).
> Note that setting the CRTSCTS flag for a serial port that is being used
> as the kernel console is a bad idea ;-) You'll have better luck with
> UARTs on expansion connectors, cfr. the topic/renesas-overlays branch of
> https://git.kernel.org/cgit/linux/kernel/git/geert/renesas-drivers.git
> 
> Thanks!
> 
> Geert Uytterhoeven (3):
>   ARM: dts: bockw: SCIF0 supports RTS/CTS hardware flow control
>   ARM: dts: kzm9g: SCIFA4 supports RTS/CTS hardware flow control
>   arm64: dts: salvator-x: SCIF1 supports RTS/CTS hardware flow control
> 
>  arch/arm/boot/dts/r8a7778-bockw.dts                | 1 +
>  arch/arm/boot/dts/sh73a0-kzm9g.dts                 | 1 +
>  arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts | 1 +
>  3 files changed, 3 insertions(+)
> 
> -- 
> 1.9.1
> 
> 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 roeck-us.net  Thu May  5 16:51:14 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Thu, 5 May 2016 16:51:14 -0700
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <572BD959.3090507@codeaurora.org>
References: <5728A7C3.4010001@roeck-us.net>
 <20160503143856.GE13045@dhcppc6.redhat.com> <5728BEC4.6050603@codeaurora.org>
 <20160503155141.GF13045@dhcppc6.redhat.com>
 <20160503171602.GA2518@roeck-us.net>
 <20160504141449.GG13045@dhcppc6.redhat.com> <572A0577.1070000@codeaurora.org>
 <20160504155932.GH13045@dhcppc6.redhat.com> <572A2099.4070901@codeaurora.org>
 <20160505164300.GA16914@roeck-us.net>
 <20160505182031.GB12434@dhcppc6.redhat.com> <572B8F52.2000709@codeaurora.org>
 <572BD8E3.4070707@roeck-us.net> <572BD959.3090507@codeaurora.org>
Message-ID: <572BDC72.5050304@roeck-us.net>

On 05/05/2016 04:38 PM, Timur Tabi wrote:
> Guenter Roeck wrote:
>> A 32-bit counter is absolutely fine. Letting it run with a 400MHz clock
>> (or was it 200 MHz ?) is the problem. A resolution of 2.5ns for a watchdog
>> timer does not really make any sense.
>
> The 10 second limit is based on a 20MHz clock.
>
Not that a resolution of 50 ns makes sense either, but 4294967296 / 20971520 = 204,
and 20971520 * 10 = 209715200 = 0x0c800000. Where does the resolution get lost ?

Guenter



From nm at ti.com  Thu May  5 17:05:25 2016
From: nm at ti.com (Nishanth Menon)
Date: Thu, 5 May 2016 19:05:25 -0500
Subject: [PATCH] ARM: dts: am57xx-idk-common: Fix input supply names
Message-ID: <1462493125-27832-1-git-send-email-nm@ti.com>

Palmas Regulator is an exception and does not follow the standard
"vin-supply" common definitions for all regulators, as a result of this,
the input supplies are not reported to regulator framework, with the
obvious result of not being appropriately mapped. Fix the same.

Signed-off-by: Nishanth Menon <nm at ti.com>
---

Based on next-20160504
Log: http://pastebin.ubuntu.com/16248817/

 arch/arm/boot/dts/am57xx-idk-common.dtsi | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/arch/arm/boot/dts/am57xx-idk-common.dtsi b/arch/arm/boot/dts/am57xx-idk-common.dtsi
index b01a5948cdd0..65ab31118140 100644
--- a/arch/arm/boot/dts/am57xx-idk-common.dtsi
+++ b/arch/arm/boot/dts/am57xx-idk-common.dtsi
@@ -60,10 +60,26 @@
 
 		tps659038_pmic {
 			compatible = "ti,tps659038-pmic";
+
+			smps12-in-supply = <&vmain>;
+			smps3-in-supply = <&vmain>;
+			smps45-in-supply = <&vmain>;
+			smps6-in-supply = <&vmain>;
+			smps7-in-supply = <&vmain>;
+			smps8-in-supply = <&vmain>;
+			smps9-in-supply = <&vmain>;
+			ldo1-in-supply = <&vmain>;
+			ldo2-in-supply = <&vmain>;
+			ldo3-in-supply = <&vmain>;
+			ldo4-in-supply = <&vmain>;
+			ldo9-in-supply = <&vmain>;
+			ldoln-in-supply = <&vmain>;
+			ldousb-in-supply = <&vmain>;
+			ldortc-in-supply = <&vmain>;
+
 			regulators {
 				smps12_reg: smps12 {
 					/* VDD_MPU */
-					vin-supply = <&vmain>;
 					regulator-name = "smps12";
 					regulator-min-microvolt = <850000>;
 					regulator-max-microvolt = <1250000>;
@@ -73,7 +89,6 @@
 
 				smps3_reg: smps3 {
 					/* VDD_DDR EMIF1 EMIF2 */
-					vin-supply = <&vmain>;
 					regulator-name = "smps3";
 					regulator-min-microvolt = <1350000>;
 					regulator-max-microvolt = <1350000>;
@@ -84,7 +99,6 @@
 				smps45_reg: smps45 {
 					/* VDD_DSPEVE on AM572 */
 					/* VDD_IVA + VDD_DSP on AM571 */
-					vin-supply = <&vmain>;
 					regulator-name = "smps45";
 					regulator-min-microvolt = <850000>;
 					regulator-max-microvolt = <1250000>;
@@ -94,7 +108,6 @@
 
 				smps6_reg: smps6 {
 					/* VDD_GPU */
-					vin-supply = <&vmain>;
 					regulator-name = "smps6";
 					regulator-min-microvolt = <850000>;
 					regulator-max-microvolt = <1250000>;
@@ -104,7 +117,6 @@
 
 				smps7_reg: smps7 {
 					/* VDD_CORE */
-					vin-supply = <&vmain>;
 					regulator-name = "smps7";
 					regulator-min-microvolt = <850000>;
 					regulator-max-microvolt = <1150000>;
@@ -115,13 +127,11 @@
 				smps8_reg: smps8 {
 					/* 5728 - VDD_IVAHD */
 					/* 5718 - N.C. test point */
-					vin-supply = <&vmain>;
 					regulator-name = "smps8";
 				};
 
 				smps9_reg: smps9 {
 					/* VDD_3_3D */
-					vin-supply = <&vmain>;
 					regulator-name = "smps9";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
@@ -132,7 +142,6 @@
 				ldo1_reg: ldo1 {
 					/* VDDSHV8 - VSDMMC  */
 					/* NOTE: on rev 1.3a, data supply */
-					vin-supply = <&vmain>;
 					regulator-name = "ldo1";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <3300000>;
@@ -142,7 +151,6 @@
 
 				ldo2_reg: ldo2 {
 					/* VDDSH18V */
-					vin-supply = <&vmain>;
 					regulator-name = "ldo2";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
@@ -152,7 +160,6 @@
 
 				ldo3_reg: ldo3 {
 					/* R1.3a 572x V1_8PHY_LDO3: USB, SATA */
-					vin-supply = <&vmain>;
 					regulator-name = "ldo3";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
@@ -162,7 +169,6 @@
 
 				ldo4_reg: ldo4 {
 					/* R1.3a 572x V1_8PHY_LDO4: PCIE, HDMI*/
-					vin-supply = <&vmain>;
 					regulator-name = "ldo4";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
@@ -174,7 +180,6 @@
 
 				ldo9_reg: ldo9 {
 					/* VDD_RTC  */
-					vin-supply = <&vmain>;
 					regulator-name = "ldo9";
 					regulator-min-microvolt = <840000>;
 					regulator-max-microvolt = <1160000>;
@@ -184,7 +189,6 @@
 
 				ldoln_reg: ldoln {
 					/* VDDA_1V8_PLL */
-					vin-supply = <&vmain>;
 					regulator-name = "ldoln";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
@@ -194,7 +198,6 @@
 
 				ldousb_reg: ldousb {
 					/* VDDA_3V_USB: VDDA_USBHS33 */
-					vin-supply = <&vmain>;
 					regulator-name = "ldousb";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
@@ -205,7 +208,6 @@
 				ldortc_reg: ldortc {
 					/* VDDA_RTC  */
 					vin-supply = <&vmain>;
-					regulator-name = "ldortc";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
 					regulator-always-on;
-- 
2.8.0



From linux at roeck-us.net  Thu May  5 17:18:20 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Thu, 5 May 2016 17:18:20 -0700
Subject: [PATCH RFC] Watchdog: sbsa_gwdt: Enhance timeout range
In-Reply-To: <572BDB30.9060602@codeaurora.org>
References: <5728A7C3.4010001@roeck-us.net>
 <20160503143856.GE13045@dhcppc6.redhat.com> <5728BEC4.6050603@codeaurora.org>
 <20160503155141.GF13045@dhcppc6.redhat.com>
 <20160503171602.GA2518@roeck-us.net>
 <20160504141449.GG13045@dhcppc6.redhat.com> <572A0577.1070000@codeaurora.org>
 <20160504155932.GH13045@dhcppc6.redhat.com> <572A2099.4070901@codeaurora.org>
 <20160505164300.GA16914@roeck-us.net>
 <20160505182031.GB12434@dhcppc6.redhat.com> <572B8F52.2000709@codeaurora.org>
 <572BD8E3.4070707@roeck-us.net> <572BD959.3090507@codeaurora.org>
 <572BDB30.9060602@codeaurora.org>
Message-ID: <572BE2CC.4020606@roeck-us.net>

On 05/05/2016 04:45 PM, Timur Tabi wrote:
> Timur Tabi wrote:
>>
>>> A 32-bit counter is absolutely fine. Letting it run with a 400MHz clock
>>> (or was it 200 MHz ?) is the problem. A resolution of 2.5ns for a
>>> watchdog
>>> timer does not really make any sense.
>>
>> The 10 second limit is based on a 20MHz clock.
>
> No, that's not true.  I misread the code.  I knew something was wrong, but it didn't click until just now.
>
> The default timeout is 10 seconds.  The max timeout on a 20MHz system (which is what we're running) is over 200 seconds.
>
> The problem is that Pratyush's system is running at a clock that's way too fast:
>
>   [  131.187562] sbsa-gwdt sbsa-gwdt.0: Initialized with 40s timeout @ 250000000 Hz, action=1.
>
> 250MHz is unreasonable.  Pratyush, why is your system counter so high? On our ARM64 system, it's set to 20MHz.
>

Guess that answers my earlier question. Problem is that the specification
_permits_ those unreasonable frequencies, and quite obviously they are
being used, no matter if it makes sense or not.

With a (still unreasonable) maximum frequency of 100 MHz, the problem
would not exist. So, if anything, someone with influence on the standard
might suggest to reduce the maximum permitted frequency.

Guenter



From horms at verge.net.au  Thu May  5 17:21:25 2016
From: horms at verge.net.au (Simon Horman)
Date: Fri, 6 May 2016 09:21:25 +0900
Subject: [GIT PULL] Renesas ARM64 Based SoC DT PM Domain Updates for v4.7
In-Reply-To: <cover.1461730364.git.horms+renesas@verge.net.au>
References: <cover.1461730364.git.horms+renesas@verge.net.au>
Message-ID: <20160506002125.GE24999@verge.net.au>

Hi,

On Wed, Apr 27, 2016 at 02:20:10PM +1000, Simon Horman wrote:
> Hi Olof, Hi Kevin, Hi Arnd,
> 
> Please consider these Renesas ARM64 based SoC DT PM Domain updates for v4.7.
> 
> This pull requests is based on a merge of:
> 
> * "[GIT PULL] Second Round of Renesas ARM Based SoC R-Car SYSC Updates for
>   v4.7", tagged as renesas-rcar-sysc2-for-v4.7, which you have already
>   pulled
> * "[GIT PULL] Second Round of Renesas ARM64 Based SoC DT Updates for v4.7",
>   tagged as renesas-arm64-dt2-for-v4.7, which I have sent a pull request
>   for.
> 
> The reason for the somewhat tedious base on
> renesas-rcar-sysc2-for-v4.7, which provides driver changes,
> is a hard run-time dependency.
> 
> I also have a similar set of changes for ARM (32-bit) which I will send
> separately.

I am wondering if this pull-request might have slipped through the cracks.

FWIW, all other pull requests I have submitted for v4.7 have been pulled
(thanks!) including a similar pull-request for ARM (32-bit) which is
present in the next/late branch of the arm-soc tree.

I do not plan to send any more non-fix pull requests for v4.7.
And at this stage I am not aware of any fixes for v4.7.

> The following changes since commit 3238ec7c0a821915f38095752de97a424fd1d6ce:
> 
>   Merge tag 'renesas-rcar-sysc2-for-v4.7' into arm64-dt-pm-domain-for-v4.7 (2016-04-27 11:49:19 +1000)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-arm64-dt-pm-domain-for-v4.7
> 
> for you to fetch changes up to 38dbb45ee4bc7dda4aabba2178eebff2f93380d1:
> 
>   arm64: dts: r8a7795: Use SYSC "always-on" PM Domain (2016-04-27 14:10:41 +1000)
> 
> ----------------------------------------------------------------
> Renesas ARM64 Based SoC DT PM Domain Updates for v4.7
> 
> * Add SYSC PM Domains to DT of r8a7795 SoC
> 
> ----------------------------------------------------------------
> Geert Uytterhoeven (2):
>       arm64: dts: r8a7795: Add SYSC PM Domains
>       arm64: dts: r8a7795: Use SYSC "always-on" PM Domain
> 
>  arch/arm64/boot/dts/renesas/r8a7795.dtsi | 123 +++++++++++++++++--------------
>  1 file changed, 68 insertions(+), 55 deletions(-)
> 


From majun258 at huawei.com  Thu May  5 18:12:55 2016
From: majun258 at huawei.com (majun (F))
Date: Fri, 6 May 2016 09:12:55 +0800
Subject: [PATCH v3 0/2] irqchip/mbigen: fix the IO remap problem in mbigen
 driver.
In-Reply-To: <572B5D97.4090004@arm.com>
References: <1458203641-17172-1-git-send-email-majun258@huawei.com>
 <alpine.DEB.2.11.1603211124450.3978@nanos> <56F0B7C3.8070001@huawei.com>
 <572B5D97.4090004@arm.com>
Message-ID: <572BEF97.5020003@huawei.com>

Hi Marc:

? 2016/5/5 22:49, Marc Zyngier ??:
> On 22/03/16 03:10, majun (F) wrote:
>>
>>
>> ? 2016/3/21 18:29, Thomas Gleixner ??:
>>> On Thu, 17 Mar 2016, MaJun wrote:
>>>> This patch set is used to fix the problem of remap a set of registers
>>>> repeatedly in current mbigen driver.
>>>>
>>>>   irqchip/mbigen:Change the mbigen node definition in dt binding file
>>>>   irqchip/mbigen:Change the mbigen driver based on the new mbigen node definition
>>>
>>> These subject lines are still horrible as they tell nothing about the nature
>>> of the change. I fixed them up along with the changelogs and applied them to
>>> irq/urgent. Can you spot the difference?
>>
>> Yes, after you changing, the subject and change log clearly show why we need to
>> do this change.
>> I have learned a lot from you :)
>>
>>>
>>> While at it. The config switch for this driver is horrible. It's just in the
>>> middle of the device driver configs. Why is this configurable by the user at
>>> all? It simply should be selected by arm64 or some subarch configuration
>>> there. Please clean that up.
>>>
>> will do.
> 
> So what's the status of this? Do you still plan to respin it?
> 

This patch set had been ACK by Thomas.
If you mean the mbigen driver config switch problem, the patch for this problem also
had been ACK by thomas.
please see the link:
https://lkml.org/lkml/2016/3/23/76

Thanks
Ma Jun

> Thanks,
> 
> 	M.
> 



From david.wu at rock-chips.com  Thu May  5 19:12:04 2016
From: david.wu at rock-chips.com (David.Wu)
Date: Fri, 6 May 2016 10:12:04 +0800
Subject: [PATCH v7 9/9] i2c: rk3x: support fast-mode plus for rk3399
In-Reply-To: <CAD=FV=UtHPDtB7LTbUpwcjOcoYwNma59-TRDU3hrt6c_2TWxxA@mail.gmail.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462372668-6583-1-git-send-email-david.wu@rock-chips.com>
 <CAD=FV=UtHPDtB7LTbUpwcjOcoYwNma59-TRDU3hrt6c_2TWxxA@mail.gmail.com>
Message-ID: <572BFD74.9080200@rock-chips.com>

Hi Doug,

? 2016/5/6 7:02, Doug Anderson ??:
> David,
>
> On Wed, May 4, 2016 at 7:37 AM, David Wu <david.wu at rock-chips.com> wrote:
>> Signed-off-by: David Wu <david.wu at rock-chips.com>
>> ---
>>   drivers/i2c/busses/i2c-rk3x.c | 21 +++++++++++++++++----
>>   1 file changed, 17 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
>> index 47368c4..c66cc39 100644
>> --- a/drivers/i2c/busses/i2c-rk3x.c
>> +++ b/drivers/i2c/busses/i2c-rk3x.c
>> @@ -124,6 +124,17 @@ static const struct i2c_spec_values fast_mode_spec = {
>>          .min_hold_buffer_ns = 1300,
>>   };
>>
>> +static const struct i2c_spec_values fast_mode_plus_spec = {
>> +       .min_hold_start_ns = 260,
>> +       .min_low_ns = 500,
>> +       .min_high_ns = 260,
>> +       .min_setup_start_ns = 260,
>> +       .max_data_hold_ns = 400,
>
> I'm curious where you got the data_hold_ns.  I can't quite remember
> what this parameter does / how the timing function works anymore, but
> the doc I have (search for UM10204 and click the first link) shows
> values for Standard-mode and Fast-mode but not Fast-mode Plus.  It
> seems to imply that this is a bit of a bogus number anyway because it
> only matters if we don't stretch the tLOW to go along with the longer
> data hold.
>
> As I have said in the previous patch, how all this stuff works has
> totally left my brain, so if you understand it that's probably good
> enough.  If you feel like I should try to re-understand this again so
> I can review it more deeply, let me know.
>
>

Yes, I could not get the description of fast-mode plus data_hold_ns, but 
I saw that the maximum tHD;DAT must be less than the maximum of 
tVD;DATor tVD;ACKby for Standard-mode and Fast-mode.

So I think the maximum tHD;DAT for Fast-mode Plus should be less than 
the maximum of tVD;DATor tVD;ACKby too, the maximum of tVD;DATor 
tVD;ACKby is 450ns, and 400ns is my taking a conservative value.

Description form UM10204
[4] The maximum tHD;DATcould be 3.45?s and 0.9?s for Standard-mode and 
Fast-mode, but must be less than the maximum of tVD;DATor tVD;ACKby a 
transition time. This maximum must only be met if the device does not 
stretch the LOW period (tLOW) of the SCL signal. If the clock stretches 
the SCL, the data must be valid by the set-up time before it releases
the clock.

> Since I assume that you had some sane reason to include max_data_hold_ns:
>
> Reviewed-by: Douglas Anderson <dianders at chromium.org>
>
>
>



From david.wu at rock-chips.com  Thu May  5 19:19:13 2016
From: david.wu at rock-chips.com (David.Wu)
Date: Fri, 6 May 2016 10:19:13 +0800
Subject: [PATCH v7 2/9] i2c: rk3x: use struct "rk3x_i2c_calced_timings"
In-Reply-To: <CAD=FV=WAbedAB78shifxwjmZ-od8rhOiNz80rpdqfwzRsdX6WQ@mail.gmail.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462371194-5809-3-git-send-email-david.wu@rock-chips.com>
 <CAD=FV=WAbedAB78shifxwjmZ-od8rhOiNz80rpdqfwzRsdX6WQ@mail.gmail.com>
Message-ID: <572BFF21.6060500@rock-chips.com>

Hi Doug,

? 2016/5/6 6:55, Doug Anderson ??:
> David,
>
> On Wed, May 4, 2016 at 7:13 AM, David Wu <david.wu at rock-chips.com> wrote:
>> Signed-off-by: David Wu <david.wu at rock-chips.com>
>
> Usually folks like a description and not just a subject line.  I'd add
> a description like:
>
> The "div_high" and "div_low" values are always used together.  Group them
> into a structure to make it easier to pass them both around.  This
> structure also provides a place for future calculated timings.
>

Okay, i will add it in next version, thanks.

>> ---
>> Change in v7:
>> - none
>>
>>   drivers/i2c/busses/i2c-rk3x.c | 55 +++++++++++++++++++++++++------------------
>>   1 file changed, 32 insertions(+), 23 deletions(-)
>
> Other than the description, I think this looks fine.
>
> IMHO this can be applied any time independent of any earlier patches.
>
> Reviewed-by: Douglas Anderson <dianders at chromium.org>
>
>
>



From david.wu at rock-chips.com  Thu May  5 20:20:41 2016
From: david.wu at rock-chips.com (David.Wu)
Date: Fri, 6 May 2016 11:20:41 +0800
Subject: [PATCH v7 4/9] i2c: rk3x: Move setting STATE_START and add
 STATE_SETUP
In-Reply-To: <CAD=FV=WVKpJJbqc=UYbeObDurjte0iQOzvLL++i=wM9=TBeCDQ@mail.gmail.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462371194-5809-5-git-send-email-david.wu@rock-chips.com>
 <CAD=FV=WVKpJJbqc=UYbeObDurjte0iQOzvLL++i=wM9=TBeCDQ@mail.gmail.com>
Message-ID: <572C0D89.9050708@rock-chips.com>

Hi Doug,

? 2016/5/6 6:56, Doug Anderson ??:
> David,
>
> On Wed, May 4, 2016 at 7:13 AM, David Wu <david.wu at rock-chips.com> wrote:
>> Signed-off-by: David Wu <david.wu at rock-chips.com>
>> ---
>> Change in v7:
>> - none
>>
>>   drivers/i2c/busses/i2c-rk3x.c | 5 ++++-
>>   1 file changed, 4 insertions(+), 1 deletion(-)
>
> Probably this change could be dropped now.  Switching the location of
> setting START_START was much more important when you were supporting
> HIGH SPEED mode.  I don't think we need it anymore, right?
>

Yes, I would drop it next version?STATE_SETUP didn't make sense, it was
not much more important, because there was a error printk for 
rk3x_i2c_setup() called failed.

> ...if we want to keep this change, I'd say:
>
> 1. Add a description, like maybe:
>
> To help with debugging add a STATE_SETUP between STATE_IDLE and
> STATE_START to make it more obvious that we're not actually idle but we
> also haven't initiated the start bit.  This change is not expected to
> have any impact but it does delay the changing of state to STATE_START.
> If previously we were getting an erroneous interrupt before we actually
> sent the start bit we'll now be treating that differently.  The new
> behavior (catching the erroneous interrupt) should be better.
>
> 2. Change "i2c->state = STATE_SETUP" to the _start_ of
> rk3x_i2c_setup().  That would have a better chance of catching a
> spurious interrupt.
>
> 3. Add an error check at the start of rk3x_i2c_irq() similar to the
> check for STATE_IDLE (or use the same check and modify the printk).
> Specifically the justification for adding STATE_SETUP is to help with
> debugging (catch interrupts that were unexpected and print more info
> about our state), so we should make it useful for this.
>
>
> -Doug
>
>
>



From sricharan at codeaurora.org  Thu May  5 21:09:18 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Fri, 6 May 2016 09:39:18 +0530
Subject: [PATCH 2/2] drivers: i2c: qup: Fix error handling
In-Reply-To: <20160505172219.GB6533@hector.attlocal.net>
References: <1462166637-16778-1-git-send-email-sricharan@codeaurora.org>
 <1462166637-16778-3-git-send-email-sricharan@codeaurora.org>
 <20160505172219.GB6533@hector.attlocal.net>
Message-ID: <001e01d1a74d$13c716b0$3b554410$@codeaurora.org>

Hi Andy,

> -----Original Message-----
> From: Andy Gross [mailto:andy.gross at linaro.org]
> Sent: Thursday, May 05, 2016 10:52 PM
> To: Sricharan R <sricharan at codeaurora.org>
> Cc: devicetree at vger.kernel.org; architt at codeaurora.org; linux-arm-
> msm at vger.kernel.org; ntelkar at codeaurora.org; galak at codeaurora.org;
> linux-kernel at vger.kernel.org; linux-i2c at vger.kernel.org; iivanov at mm-
> sol.com; agross at codeaurora.org; dmaengine at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org
> Subject: Re: [PATCH 2/2] drivers: i2c: qup: Fix error handling
> 
> On Mon, May 02, 2016 at 10:53:57AM +0530, Sricharan R wrote:
> > Among the bus errors reported from the QUP_MASTER_STATUS register
> only
> > NACK is considered and transfer gets suspended, while other errors are
> > ignored. Correct this and suspend the transfer for other errors as
> > well. This avoids unnessecary 'timeouts' which happens when waiting
> > for events that would never happen when there is already an error
> > condition on the bus.
> >
> > Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> > ---
> >  drivers/i2c/busses/i2c-qup.c | 34 +++++++++++++++++++++++++---------
> >  1 file changed, 25 insertions(+), 9 deletions(-)
> 
> Reviewed-by: Andy Gross <andy.gross at linaro.org>
> 
 Thanks.
> <snip>
> 
> > @@ -1227,6 +1240,9 @@ static int qup_i2c_xfer_v2(struct i2c_adapter
> *adap,
> >  	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
> >  	int ret, len, idx = 0, use_dma = 0;
> >
> > +	qup->bus_err = 0;
> > +	qup->qup_err = 0;
> > +
> 
> What about the initial setting of these?  Does this need to be removed
from
> the main xfer function?
  Thanks for the catch. Will remove in bam_xfer , redundant.
  Now that there are i2x_xfer_v2 and i2c_xfer, 
   its not set in the old i2c_xfer call, where as it should be set there
   as well. I will change this and resend.

Regards,
 Sricharan



From david.wu at rock-chips.com  Thu May  5 21:55:15 2016
From: david.wu at rock-chips.com (David.Wu)
Date: Fri, 6 May 2016 12:55:15 +0800
Subject: [PATCH v7 6/9] i2c: rk3x: Move spec timing data to "static const"
 structs
In-Reply-To: <CAD=FV=Vg+umhA73uR66AdFmaNKhpyXCYojqE9kZJqkTOsyK_Jg@mail.gmail.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462372472-6396-1-git-send-email-david.wu@rock-chips.com>
 <CAD=FV=Vg+umhA73uR66AdFmaNKhpyXCYojqE9kZJqkTOsyK_Jg@mail.gmail.com>
Message-ID: <572C23B3.6090702@rock-chips.com>

Hi Doug,

? 2016/5/6 6:58, Doug Anderson ??:
> David,
>
> On Wed, May 4, 2016 at 7:34 AM, David Wu <david.wu at rock-chips.com> wrote:
>> Signed-off-by: David Wu <david.wu at rock-chips.com>
>
> As you can probably guess, again a description would be nice.  Like maybe:
>
> The i2c timing specs are really just constant data.  There's no reason
> to write code to init them, so move them out to structures.  This not
> only is a cleaner solution but it will reduce code duplication when we
> introduce a new variant of rk3x_i2c_calc_divs() in a future patch.
>
> That helps someone reading the patch understand the motivation.
>
>
>> @@ -76,6 +76,51 @@ enum {
>>   #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */
>>
>>   /**
>> + * struct i2c_spec_values:
>> + * @min_hold_start_ns: min hold time (repeated) START condition
>> + * @min_low_ns: min LOW period of the SCL clock
>> + * @min_high_ns: min HIGH period of the SCL cloc
>> + * @min_setup_start_ns: min set-up time for a repeated START conditio
>> + * @max_data_hold_ns: max data hold time
>> + * @min_data_setup_ns: min data set-up time
>> + * @min_setup_stop_ns: min set-up time for STOP condition
>> + * @min_hold_buffer_ns: min bus free time between a STOP and
>> + * START condition
>> + */
>> +struct i2c_spec_values {
>> +       unsigned long min_hold_start_ns;
>> +       unsigned long min_low_ns;
>> +       unsigned long min_high_ns;
>> +       unsigned long min_setup_start_ns;
>> +       unsigned long max_data_hold_ns;
>> +       unsigned long min_data_setup_ns;
>> +       unsigned long min_setup_stop_ns;
>> +       unsigned long min_hold_buffer_ns;
>> +};
>> +
>> +static const struct i2c_spec_values standard_mode_spec = {
>> +       .min_hold_start_ns = 4000,
>> +       .min_low_ns = 4700,
>> +       .min_high_ns = 4000,
>> +       .min_setup_start_ns = 4700,
>> +       .max_data_hold_ns = 3450,
>> +       .min_data_setup_ns = 250,
>> +       .min_setup_stop_ns = 4000,
>> +       .min_hold_buffer_ns = 4700,
>
> There are more spec values than are currently used in this patch.
> Personally I'm OK with that, but if you wanted to be totally clean
> this patch would only include the spec values that were needed, then
> introduce the additional values in the rk3399 patch.
>
>
>> @@ -492,6 +548,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
>>          unsigned long min_div_for_hold, min_total_div;
>>          unsigned long extra_div, extra_low_div, ideal_low_div;
>>
>> +       unsigned long data_hold_buffer_ns = 50;
>
> aside (feel free to ignore): Gosh, I kinda forgot what the heck this
> value was for.  I guess it's not anything in the spec.  I have a
> feeling it was some sort of slop value that someone felt was
> necessary, but I don't quite remember.  Oh well, I guess we leave it
> there since I'd rather not mess with timings on old hardware that are
> apparently working for everyone.  :-P
>
>

I thing it was a tuning value for max_t_low_ns. :-P

> In any case, aside from the missing description:
>
> Suggested-by: Douglas Anderson <dianders at chromium.org>
> Reviewed-by: Douglas Anderson <dianders at chromium.org>
>
> IMHO this can be applied any time independent of any earlier patches.
>
>
> -Doug
>
>
>



From hzpeterchen at gmail.com  Thu May  5 22:44:59 2016
From: hzpeterchen at gmail.com (Peter Chen)
Date: Fri, 6 May 2016 13:44:59 +0800
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <20160505224240.GA31429@rob-hp-laptop>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <20160505224240.GA31429@rob-hp-laptop>
Message-ID: <20160506054459.GA32359@shlinux2.ap.freescale.net>

On Thu, May 05, 2016 at 05:42:40PM -0500, Rob Herring wrote:
> On Thu, May 05, 2016 at 02:34:13PM +0200, Krzysztof Kozlowski wrote:
> > Hi,
> > 
> > This is a different, second try to fix usb3503+lan on Odroid U3 board
> > if it was initialized by bootloader (e.g. for TFTP boot).
> > 
> > First version:
> > http://www.spinics.net/lists/linux-usb/msg140042.html
> > 
> > 
> > Problem
> > =======
> > When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
> > the usb3503 and LAN smsc95xx do not show up in "lsusb". Hard-reset
> > is required, e.g. by suspend to RAM. The actual TFTP boot does
> > not have to happen. Just "usb start" from U-Boot is sufficient.
> > 
> > From the schematics, the regulator is a supply only to LAN, however
> > without toggling it off/on, the usb3503 hub won appear neither.
> > 
> > 
> > Solution
> > ========
> > This is very similar to the MMC pwrseq behavior so the idea is to:
> > 1. Move MMC pwrseq drivers to generic place,
> 
> You can do that, but I'm going to NAK any use of pwrseq bindings outside 
> of MMC. I think it is the wrong way to do things. The DT should describe 
> the devices. If they happen to be "simple" then the core can walk the 
> tree and do any setup. For example, look for "reset-gpios" and toggle 
> that GPIO. There is no need for a special node.
> 

Oh, I am doing the same thing like this patch set doing. Then, how can
we let things be generic like you mention at [1] if without common
pwrseq driver/library? The properties like "reset-gpios" under
USB child node seems can only be handled by USB driver.

> > 2. Extend the pwrseq-simple with regulator toggling,
> > 3. Add support to USB hub and port core for pwrseq,
> 
> We discussed this for USB already[1] and is why we defined how to add 
> USB child devices. The idea is not to add pwrseq to that.
> 
> Rob
> 
> [1] http://www.spinics.net/lists/linux-usb/msg134082.html

[1] http://www.spinics.net/lists/linux-usb/msg137312.html

-- 

Best Regards,
Peter Chen


From david.wu at rock-chips.com  Thu May  5 23:09:48 2016
From: david.wu at rock-chips.com (David.Wu)
Date: Fri, 6 May 2016 14:09:48 +0800
Subject: [PATCH v7 7/9] dt-bindings: i2c: rk3x: add support for rk3399
In-Reply-To: <20160505221212.GA26820@rob-hp-laptop>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462372523-6444-1-git-send-email-david.wu@rock-chips.com>
 <20160505221212.GA26820@rob-hp-laptop>
Message-ID: <572C352C.50303@rock-chips.com>

Hi Rob,

? 2016/5/6 6:12, Rob Herring ??:
> On Wed, May 04, 2016 at 10:35:23PM +0800, David Wu wrote:
>> The bus clock and function clock are separated at rk3399,
>> and others use one clock as the bus clock and function clock.
>>
>> Signed-off-by: David Wu <david.wu at rock-chips.com>
>> ---
>>   Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 16 +++++++++++++---
>>   1 file changed, 13 insertions(+), 3 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
>> index 0b4a85f..82b6f6b 100644
>> --- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
>> +++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
>> @@ -6,10 +6,20 @@ RK3xxx SoCs.
>>   Required properties :
>>
>>    - reg : Offset and length of the register set for the device
>> - - compatible : should be "rockchip,rk3066-i2c", "rockchip,rk3188-i2c",
>> -		"rockchip,rk3228-i2c" or "rockchip,rk3288-i2c".
>> + - compatible: should be one of the followings
>
> s/followings/following:/
>
>> +   - "rockchip,rk3066-i2c": for rk3066
>> +   - "rockchip,rk3188-i2c": for rk3188
>> +   - "rockchip,rk3228-i2c": for rk3228
>> +   - "rockchip,rk3288-i2c": for rk3288
>> +   - "rockchip,rk3399-i2c": for rk3399
>>    - interrupts : interrupt number
>> - - clocks : parent clock
>> + - clocks: See ../clock/clock-bindings.txt
>> +   - For older hardware (rk3066, rk3188, rk3228, rk3288):
>> +     - There is one clock that's used both to derive the functional clock
>> +       for the device and as the bus clock.  REQUIRED.
>
> This is the required section, so REQUIRED is redundant.


>
>> +   - For newer hardware (rk3399): specify by name
>> +     - "i2c": REQUIRED. This is used to derive the functional clock.
>> +     - "pclk": REQUIRED. This is the bus clock.equired on RK3066, RK3188 :
>
> This doesn't make sense. The first line says this applies to rk3399, but
> then here it is talking about other parts.
>
> And there's a typo.
>

Okay, I will remove the "equired on RK3066, RK3188 :".

>>
>>   Required on RK3066, RK3188 :
>>
>> --
>> 1.9.1
>>
>>
>
>
>



From k.kozlowski at samsung.com  Thu May  5 23:10:38 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 08:10:38 +0200
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <20160505224240.GA31429@rob-hp-laptop>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <20160505224240.GA31429@rob-hp-laptop>
Message-ID: <572C355E.7090008@samsung.com>

On 05/06/2016 12:42 AM, Rob Herring wrote:
> On Thu, May 05, 2016 at 02:34:13PM +0200, Krzysztof Kozlowski wrote:
>> Hi,
>>
>> This is a different, second try to fix usb3503+lan on Odroid U3 board
>> if it was initialized by bootloader (e.g. for TFTP boot).
>>
>> First version:
>> http://www.spinics.net/lists/linux-usb/msg140042.html
>>
>>
>> Problem
>> =======
>> When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
>> the usb3503 and LAN smsc95xx do not show up in "lsusb". Hard-reset
>> is required, e.g. by suspend to RAM. The actual TFTP boot does
>> not have to happen. Just "usb start" from U-Boot is sufficient.
>>
>> From the schematics, the regulator is a supply only to LAN, however
>> without toggling it off/on, the usb3503 hub won appear neither.
>>
>>
>> Solution
>> ========
>> This is very similar to the MMC pwrseq behavior so the idea is to:
>> 1. Move MMC pwrseq drivers to generic place,
> 
> You can do that, but I'm going to NAK any use of pwrseq bindings outside 
> of MMC. I think it is the wrong way to do things. The DT should describe 
> the devices. If they happen to be "simple" then the core can walk the 
> tree and do any setup. For example, look for "reset-gpios" and toggle 
> that GPIO. There is no need for a special node.

Okay, I got it, no node for pwrseq but parse device properties. In case
of reset-gpios it seems quite obvious but also actively used:
$ git grep reset-gpios arch/arm/boot/dts | wc -l
142

Definitely pwrseq shouldn't add itself to all of these devices.

My questions would be then:
1. An additional pwrseq compatible for device is acceptable?
2. How would you name the regulator? We shouldn't toggle off/on every
regulator but probably only some specific ones.

> 
>> 2. Extend the pwrseq-simple with regulator toggling,
>> 3. Add support to USB hub and port core for pwrseq,
> 
> We discussed this for USB already[1] and is why we defined how to add 
> USB child devices. The idea is not to add pwrseq to that.

Yes, I left it for next iteration because it would require much more
changes in USB core. As for now, these bindings are useless for USB
devices which are not yet enumerated (because power sequence has to be
done on them). Making use of these bindings would be a next step... Just
let me do it one step a time.

Best regards,
Krzysztof

> 
> Rob
> 
> [1] http://www.spinics.net/lists/linux-usb/msg134082.html
> 
> 



From k.kozlowski at samsung.com  Thu May  5 23:12:24 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 08:12:24 +0200
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <20160506054459.GA32359@shlinux2.ap.freescale.net>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <20160505224240.GA31429@rob-hp-laptop>
 <20160506054459.GA32359@shlinux2.ap.freescale.net>
Message-ID: <572C35C8.9080709@samsung.com>

On 05/06/2016 07:44 AM, Peter Chen wrote:
> On Thu, May 05, 2016 at 05:42:40PM -0500, Rob Herring wrote:
>> On Thu, May 05, 2016 at 02:34:13PM +0200, Krzysztof Kozlowski wrote:
>>> Hi,
>>>
>>> This is a different, second try to fix usb3503+lan on Odroid U3 board
>>> if it was initialized by bootloader (e.g. for TFTP boot).
>>>
>>> First version:
>>> http://www.spinics.net/lists/linux-usb/msg140042.html
>>>
>>>
>>> Problem
>>> =======
>>> When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
>>> the usb3503 and LAN smsc95xx do not show up in "lsusb". Hard-reset
>>> is required, e.g. by suspend to RAM. The actual TFTP boot does
>>> not have to happen. Just "usb start" from U-Boot is sufficient.
>>>
>>> From the schematics, the regulator is a supply only to LAN, however
>>> without toggling it off/on, the usb3503 hub won appear neither.
>>>
>>>
>>> Solution
>>> ========
>>> This is very similar to the MMC pwrseq behavior so the idea is to:
>>> 1. Move MMC pwrseq drivers to generic place,
>>
>> You can do that, but I'm going to NAK any use of pwrseq bindings outside 
>> of MMC. I think it is the wrong way to do things. The DT should describe 
>> the devices. If they happen to be "simple" then the core can walk the 
>> tree and do any setup. For example, look for "reset-gpios" and toggle 
>> that GPIO. There is no need for a special node.
>>
> 
> Oh, I am doing the same thing like this patch set doing.

Shame on me that I did not use Google before starting the work. I could
just extend your patchset. I think we can combine our efforts.

Best regards,
Krzysztof


From k.kozlowski at samsung.com  Thu May  5 23:13:28 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 08:13:28 +0200
Subject: [RFC v2 01/13] usb: misc: usb3503: Clean up on driver unbind
In-Reply-To: <d78e8151-ee37-a003-2f8f-bc5431906512@osg.samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-2-git-send-email-k.kozlowski@samsung.com>
 <d78e8151-ee37-a003-2f8f-bc5431906512@osg.samsung.com>
Message-ID: <572C3608.9060600@samsung.com>

On 05/05/2016 08:32 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof
> 
> Patch looks good to me, I just have a trivial comment below.
> 
> On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
>> The driver should clean up after itself by unpreparing the clock when it
>> is unbound.
>>
>> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>> ---
>>  drivers/usb/misc/usb3503.c | 28 ++++++++++++++++++++++++++++
>>  1 file changed, 28 insertions(+)
>>
>> diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
>> index b45cb77c0744..a464636675a6 100644
>> --- a/drivers/usb/misc/usb3503.c
>> +++ b/drivers/usb/misc/usb3503.c
>> @@ -330,6 +330,19 @@ static int usb3503_i2c_probe(struct i2c_client *i2c,
>>  	return usb3503_probe(hub);
>>  }
>>  
>> +static int usb3503_i2c_remove(struct i2c_client *i2c)
>> +{
>> +	struct usb3503 *hub;
>> +
>> +	hub = i2c_get_clientdata(i2c);
>> +	if (hub) {
>> +		if (hub->clk)
>> +			clk_disable_unprepare(hub->clk);
>> +	}
> 
> I think the following is simpler and easier to read:
> 
> if (hub && hub->clk)
> 	clk_disable_unprepare(hub->clk);
> 

Sure, thanks.

Best regards,
Krzysztof

>> +
>> +	return 0;
>> +}
>> +
>>  static int usb3503_platform_probe(struct platform_device *pdev)
>>  {
>>  	struct usb3503 *hub;
>> @@ -342,6 +355,19 @@ static int usb3503_platform_probe(struct platform_device *pdev)
>>  	return usb3503_probe(hub);
>>  }
>>  
>> +static int usb3503_platform_remove(struct platform_device *pdev)
>> +{
>> +	struct usb3503 *hub;
>> +
>> +	hub = platform_get_drvdata(pdev);
>> +	if (hub) {
>> +		if (hub->clk)
>> +			clk_disable_unprepare(hub->clk);
>> +	}
>> +
> 
> Ditto.
> 
>> +	return 0;
>> +}
>> +
>>  #ifdef CONFIG_PM_SLEEP
>>  static int usb3503_i2c_suspend(struct device *dev)
>>  {
>> @@ -395,6 +421,7 @@ static struct i2c_driver usb3503_i2c_driver = {
>>  		.of_match_table = of_match_ptr(usb3503_of_match),
>>  	},
>>  	.probe		= usb3503_i2c_probe,
>> +	.remove		= usb3503_i2c_remove,
>>  	.id_table	= usb3503_id,
>>  };
>>  
>> @@ -404,6 +431,7 @@ static struct platform_driver usb3503_platform_driver = {
>>  		.of_match_table = of_match_ptr(usb3503_of_match),
>>  	},
>>  	.probe		= usb3503_platform_probe,
>> +	.remove		= usb3503_platform_remove,
>>  };
>>  
>>  static int __init usb3503_init(void)
>>
> 
> Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
> 
> Best regards,
> 



From k.kozlowski at samsung.com  Thu May  5 23:15:03 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 08:15:03 +0200
Subject: [RFC v2 02/13] power/mmc: Move pwrseq drivers to power/pwrseq
In-Reply-To: <4532bfb4-38f9-a61d-1d80-e5af18cd3d98@osg.samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-3-git-send-email-k.kozlowski@samsung.com>
 <4532bfb4-38f9-a61d-1d80-e5af18cd3d98@osg.samsung.com>
Message-ID: <572C3667.3090002@samsung.com>

On 05/05/2016 08:44 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
>> The MMC power sequence drivers are useful also outside of MMC world: for
>> USB devices needed a hard-reset before probing. Before extending and
>> re-using pwrseq drivers, move them to a new place.
>>
>> The commit does not introduce significant changes in the pwrseq drivers
>> code so still all the functions are prefixed with "mmc_pwrseq". However
>> the MMC-specific pwrseq functions has to be now exported and everything
>> is hidden not by CONFIG_OF but by new CONFIG_POWER_SEQ option.
>>
>> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>> ---
> 
> [snip]
> 
>> --- a/drivers/mmc/core/Kconfig
>> +++ b/drivers/power/pwrseq/Kconfig
>> @@ -1,7 +1,12 @@
>> -#
>> -# MMC core configuration
>> -#
>> -config PWRSEQ_EMMC
>> +menuconfig POWER_SEQ
>> +	default y if OF
>> +	bool "Hardware reset support for specific devices"
>> +	help
>> +	  Provides drivers which reset the specific device before...
>> +
> 
> I think this text could be improved a little bit, maybe something like:
> 
> "Provides drivers that implements specific power sequences for chips,
> using the generic power sequence management interface".
> 
> The rest looks good to me.
> 
> Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Yes, I wanted to code, not to focus on descriptions, so also commit
messages should be extended.

I'll fix this in next iteration.

BR,
Krzysztof



From k.kozlowski at samsung.com  Thu May  5 23:20:15 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 08:20:15 +0200
Subject: [RFC v2 05/13] power: pwrseq: Remove mmc prefix from mmc_pwrseq
In-Reply-To: <48539995-2966-0df0-51db-e0c549a92880@osg.samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-6-git-send-email-k.kozlowski@samsung.com>
 <48539995-2966-0df0-51db-e0c549a92880@osg.samsung.com>
Message-ID: <572C379F.6030504@samsung.com>

On 05/05/2016 09:09 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
>> The "mmc" prefix is no longer needed after moving the pwrseq core code
>> from mmc/ to power/.
>>
>> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>> ---
> 
> [snip]
> 
>> diff --git a/drivers/power/pwrseq/pwrseq_emmc.c b/drivers/power/pwrseq/pwrseq_emmc.c
>> index a0583ed46d7f..a68ac9a68e04 100644
>> --- a/drivers/power/pwrseq/pwrseq_emmc.c
>> +++ b/drivers/power/pwrseq/pwrseq_emmc.c
>> @@ -22,7 +22,7 @@
>>  #include <linux/mmc/host.h>
>>
> 
> I don't think this header inclusion is needed. At least I didn't see anything
> defined there that's used in this driver. This also applies to pwrseq_simple.
> 
> I think you could remove those in another preparatory patches before the move.
>
> Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Good catch, thanks.

BR,
Krzysztof




From k.kozlowski at samsung.com  Thu May  5 23:24:32 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 08:24:32 +0200
Subject: [RFC v2 07/13] power: pwrseq: simple: Add support for toggling
 regulator
In-Reply-To: <d27c30c1-f205-973e-71f1-f5b410418d04@osg.samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-8-git-send-email-k.kozlowski@samsung.com>
 <d27c30c1-f205-973e-71f1-f5b410418d04@osg.samsung.com>
Message-ID: <572C38A0.7060707@samsung.com>

On 05/05/2016 09:31 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
>> Some devices need real hard-reset by cutting the power.  During power
>> sequence turn off and on the regulator, if it is provided.
>>
>> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>> ---
> 
> [snip]
> 
>>  
>>  #define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq)
>> @@ -62,6 +65,13 @@ static void mmc_pwrseq_simple_post_power_on(struct pwrseq *_pwrseq)
>>  {
>>  	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(_pwrseq);
>>  
>> +	if (pwrseq->ext_reg) {
>> +		int err;
>> +
>> +		err = regulator_enable(pwrseq->ext_reg);
>> +		WARN_ON_ONCE(err);
>> +	}
>> +
> 
> Shouldn't this be in mmc_pwrseq_simple_pre_power_on() instead?
> 
> For example, a chip may need to be powered on before attempting to
> toggle its reset or power pins using some GPIO lines.

Indeed this should be still sorted out but here the assumption is that
regulator is disabled (by probe()) so it should be turned on with
GPIO-reset set.

This can be done at the end of pre-power-on or here (beginning of
post-power-on). On the other hand I understand these pre/post callbacks
as one starting the reset sequence (pre) and second as finishing it
(post). In case of regulators, finishing power sequence is to turn the
regulator on.

Best regards,
Krzysztof



From k.kozlowski at samsung.com  Thu May  5 23:26:28 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 08:26:28 +0200
Subject: [RFC v2 09/13] power: pwrseq: Add support for USB hubs with
 external power
In-Reply-To: <3bdf7888-5ed1-2a55-6607-ee8be70e25e7@osg.samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-10-git-send-email-k.kozlowski@samsung.com>
 <3bdf7888-5ed1-2a55-6607-ee8be70e25e7@osg.samsung.com>
Message-ID: <572C3914.4040708@samsung.com>

On 05/05/2016 09:52 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
>> Some USB devices on embedded boards have external power supply which has
>> to be reset in certain conditions. Add pwrseq interface for this.
>>
>> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>> ---
>>  drivers/power/pwrseq/pwrseq.c | 44 +++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/pwrseq.h        |  8 ++++++++
>>  2 files changed, 52 insertions(+)
>>
>> diff --git a/drivers/power/pwrseq/pwrseq.c b/drivers/power/pwrseq/pwrseq.c
>> index 495a19d3c30b..306265f55a10 100644
>> --- a/drivers/power/pwrseq/pwrseq.c
>> +++ b/drivers/power/pwrseq/pwrseq.c
>> @@ -52,6 +52,43 @@ int mmc_pwrseq_alloc(struct mmc_host *host)
>>  }
>>  EXPORT_SYMBOL_GPL(mmc_pwrseq_alloc);
>>  
>> +struct pwrseq *pwrseq_alloc(struct device *dev)
>> +{
> 
> This function is USB specific so better to call it usb_pwrseq_alloc() instead.

Indeed it is parsing USB specific bindings so such prefix is needed.

> Although, this function has a lot of duplicated code from mmc_pwrseq_alloc()
> so I think is better to keep the name generic and factorize the common code.
> 
> I expect other devices are also needing some kind of power seq in the future
> so having a single alloc function instead of each for device type makes sense.

Yes, this can be cleaned up and unified.

> 
>> +	struct device_node *np;
>> +	struct pwrseq *p, *ret = NULL;
>> +
>> +	np = of_parse_phandle(dev->of_node, "usb-pwrseq", 0);
> 
> I know this is just an RFC but you should really add DT bindings for this.

Yep, next step.

Best regards,
Krzysztof



From k.kozlowski at samsung.com  Thu May  5 23:27:35 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 08:27:35 +0200
Subject: [RFC v2 11/13] usb: port: Parse pwrseq phandle from Device Tree
In-Reply-To: <e8f310b5-4fe8-3eb2-2d17-b1d9077daea2@osg.samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-12-git-send-email-k.kozlowski@samsung.com>
 <e8f310b5-4fe8-3eb2-2d17-b1d9077daea2@osg.samsung.com>
Message-ID: <572C3957.3010503@samsung.com>

On 05/05/2016 10:10 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
>> Parse usb-pwrseq property from Device Tree to get the phandle to pwrseq
>> device. The pwrseq device will be used by USB hub to cycle the power
>> before activating ports.
>>
>> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>> ---
> 
> [snip]
> 
>>  
>> @@ -532,6 +534,14 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
>>  		return retval;
>>  	}
>>  
>> +	port_dev->dev.of_node = usb_of_get_child_node(hub->hdev->dev.of_node, port1);
>> +	port_dev->pwrseq = pwrseq_alloc(&port_dev->dev);
>> +	if (IS_ERR(port_dev->pwrseq)) {
>> +		device_unregister(&port_dev->dev);
>> +		/* TODO: what about EPROBE_DEFER? */
> 
> I think it's OK since the call chain is:
> 
> hub_probe()
>        hub_configure()
>               usb_hub_create_port_device()
> 
> so the hub_probe() will be deferred if the usb-pwrseq was not registered yet.
> Unless I misunderstood your question :)
> 
> Anyway, patch looks good to me:
> 
> Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Yes and deferred probing works in my case. That is an older comment
actually.

Thanks for review,
Krzysztof



From k.kozlowski at samsung.com  Thu May  5 23:28:48 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 08:28:48 +0200
Subject: [RFC v2 13/13] ARM: dts: exynos: Fix LAN and HUB after bootloader
 initialization on Odroid U3
In-Reply-To: <9dff13ae-5863-2b45-0e6a-00b345a19019@osg.samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <1462451666-17945-14-git-send-email-k.kozlowski@samsung.com>
 <9dff13ae-5863-2b45-0e6a-00b345a19019@osg.samsung.com>
Message-ID: <572C39A0.8030701@samsung.com>

On 05/05/2016 10:16 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/05/2016 08:34 AM, Krzysztof Kozlowski wrote:
>> On Odroid U3 (Exynos4412-based) board if USB was initialized by
>> bootloader (in U-Boot "usb start" before tftpboot), the HUB (usb3503)
>> and LAN (smsc95xx) after after successful probing were not visible in the
>> system ("lsusb").
>>
>> In such case the devices had to be fully reset before configuring.
>> Reset by GPIO (called RESET_N pin) and by RESET field in STCD register
>> in usb3503 HUB are not sufficient. Instead full reset has to be done by
>> disabling and enabling regulator.
>>
>> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>> ---
> 
> [snip]
> 
>>  
>> +	lan_pwrseq: pwrseq2 {
>> +		compatible = "mmc-pwrseq-simple";
> 
> It feels strange to have a "mmc-pwrseq-simple" compatible for a USB power
> sequence provider. As I mentioned in the other patch, I think there should
> either be a DT binding for the USB pwrseq-simple with a "usb-pwrseq-simple"
> compatible that binds to the same pwrseq-simple driver or maybe having a
> generic DT binding for any device with a new "pwrseq-simple" compatible.
> 
> Patch looks good to me though, so after having a DT binding and changing
> the compatible string:
> 
> Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Probably this will change after Rob's feedback. :)

Best regards,
Krzysztof




From k.kozlowski at samsung.com  Fri May  6 00:21:20 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 09:21:20 +0200
Subject: [PATCH v6 0/9] mfd: max8997: Add regmap support
Message-ID: <1462519289-2356-1-git-send-email-k.kozlowski@samsung.com>

Hi,


This is a rebase and extension of old Robert Baldyga's work. [0]

Robert no longer works in Samsung.

>From the original cover letter:
"This patchset modifies max8997 driver and associated function drivers to use
register maps instead of operating directly on i2c bus. This change allowed
to simplify irq handling, and to move some initializations to individual
function drivers. Hence now when some functions are not enabled, their i2c
clients, regmaps and irqs are not registered."


My changes (since Robert's v5)
==============================
1. Rebase on v4.6-rc6.
2. Collect more acks.
3. Add few fixes:
   a. Haptic fix from Marek,
   b. Extcon and RTC fix from me,
   c. DTS fixes from Marek.

DTS changes are independent but rest of them (extcon/input/MFD) rely
on each other.

One way of merging would be to pick everything (except DTS) through
one tree. Or use tags.


Best regards,
Krzysztof

[0] http://lkml.iu.edu/hypermail//linux/kernel/1411.1/03152.html


Krzysztof Kozlowski (3):
  extcon: max8997: Fix handling error code of regmap_irq_get_virq()
  rtc: max8997: Check for ERRNO of regmap_irq_get_virq()
  extcon: max8997: Fix inconsistent indenting

Marek Szyprowski (3):
  input: max8997-haptic: Fix NULL pointer dereference
  ARM: dts: exynos: Fix regulator name to avoid forbidden character on
    exynos4210-trats
  ARM: dts: exynos: Add interrupt line to MAX8997 PMIC on
    exynos4210-trats

Robert Baldyga (3):
  mfd: max8997: Use regmap to access registers
  mfd: max8997: handle IRQs using regmap
  mfd: max8997: Change irq names to upper case

 arch/arm/boot/dts/exynos4210-trats.dts |   4 +-
 drivers/extcon/extcon-max8997.c        |  72 ++++---
 drivers/input/misc/max8997_haptic.c    |  40 ++--
 drivers/leds/leds-max8997.c            |  13 +-
 drivers/mfd/Kconfig                    |   3 +-
 drivers/mfd/Makefile                   |   2 +-
 drivers/mfd/max8997-irq.c              | 383 ---------------------------------
 drivers/mfd/max8997.c                  | 245 ++++++++++++++-------
 drivers/power/max8997_charger.c        |  33 +--
 drivers/regulator/max8997.c            |  87 ++++----
 drivers/rtc/rtc-max8997.c              |  60 +++---
 include/linux/mfd/max8997-private.h    |  82 +++++--
 12 files changed, 392 insertions(+), 632 deletions(-)
 delete mode 100644 drivers/mfd/max8997-irq.c

-- 
1.9.1



From k.kozlowski at samsung.com  Fri May  6 00:21:21 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 09:21:21 +0200
Subject: [PATCH v6 1/9] input: max8997-haptic: Fix NULL pointer dereference
In-Reply-To: <1462519289-2356-1-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>

From: Marek Szyprowski <m.szyprowski at samsung.com>

NULL pointer derefence happens when booting with DTB because the
platform data for haptic device is not set in supplied data from parent
MFD device.

The MFD device creates only platform data (from Device Tree) for itself,
not for haptic child.

Unable to handle kernel NULL pointer dereference at virtual address 0000009c
pgd = c0004000
	[0000009c] *pgd=00000000
	Internal error: Oops: 5 [#1] PREEMPT SMP ARM
	(max8997_haptic_probe) from [<c03f9cec>] (platform_drv_probe+0x4c/0xb0)
	(platform_drv_probe) from [<c03f8440>] (driver_probe_device+0x214/0x2c0)
	(driver_probe_device) from [<c03f8598>] (__driver_attach+0xac/0xb0)
	(__driver_attach) from [<c03f67ac>] (bus_for_each_dev+0x68/0x9c)
	(bus_for_each_dev) from [<c03f7a38>] (bus_add_driver+0x1a0/0x218)
	(bus_add_driver) from [<c03f8db0>] (driver_register+0x78/0xf8)
	(driver_register) from [<c0101774>] (do_one_initcall+0x90/0x1d8)
	(do_one_initcall) from [<c0a00dbc>] (kernel_init_freeable+0x15c/0x1fc)
	(kernel_init_freeable) from [<c06bb5b4>] (kernel_init+0x8/0x114)
	(kernel_init) from [<c0107938>] (ret_from_fork+0x14/0x3c)

Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
Cc: <stable at vger.kernel.org>
Fixes: 104594b01ce7 ("Input: add driver support for MAX8997-haptic")
[k.kozlowski: Write commit message, add CC-stable]
Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/input/misc/max8997_haptic.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
index a806ba3818f7..8d6326d7e7be 100644
--- a/drivers/input/misc/max8997_haptic.c
+++ b/drivers/input/misc/max8997_haptic.c
@@ -255,12 +255,14 @@ static int max8997_haptic_probe(struct platform_device *pdev)
 	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	const struct max8997_platform_data *pdata =
 					dev_get_platdata(iodev->dev);
-	const struct max8997_haptic_platform_data *haptic_pdata =
-					pdata->haptic_pdata;
+	const struct max8997_haptic_platform_data *haptic_pdata = NULL;
 	struct max8997_haptic *chip;
 	struct input_dev *input_dev;
 	int error;
 
+	if (pdata)
+		haptic_pdata = pdata->haptic_pdata;
+
 	if (!haptic_pdata) {
 		dev_err(&pdev->dev, "no haptic platform data\n");
 		return -EINVAL;
-- 
1.9.1



From hzpeterchen at gmail.com  Fri May  6 00:15:25 2016
From: hzpeterchen at gmail.com (Peter Chen)
Date: Fri, 6 May 2016 15:15:25 +0800
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <572C35C8.9080709@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <20160505224240.GA31429@rob-hp-laptop>
 <20160506054459.GA32359@shlinux2.ap.freescale.net>
 <572C35C8.9080709@samsung.com>
Message-ID: <20160506071525.GB32359@shlinux2.ap.freescale.net>

On Fri, May 06, 2016 at 08:12:24AM +0200, Krzysztof Kozlowski wrote:
> On 05/06/2016 07:44 AM, Peter Chen wrote:
> > On Thu, May 05, 2016 at 05:42:40PM -0500, Rob Herring wrote:
> >> On Thu, May 05, 2016 at 02:34:13PM +0200, Krzysztof Kozlowski wrote:
> >>> Hi,
> >>>
> >>> This is a different, second try to fix usb3503+lan on Odroid U3 board
> >>> if it was initialized by bootloader (e.g. for TFTP boot).
> >>>
> >>> First version:
> >>> http://www.spinics.net/lists/linux-usb/msg140042.html
> >>>
> >>>
> >>> Problem
> >>> =======
> >>> When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
> >>> the usb3503 and LAN smsc95xx do not show up in "lsusb". Hard-reset
> >>> is required, e.g. by suspend to RAM. The actual TFTP boot does
> >>> not have to happen. Just "usb start" from U-Boot is sufficient.
> >>>
> >>> From the schematics, the regulator is a supply only to LAN, however
> >>> without toggling it off/on, the usb3503 hub won appear neither.
> >>>
> >>>
> >>> Solution
> >>> ========
> >>> This is very similar to the MMC pwrseq behavior so the idea is to:
> >>> 1. Move MMC pwrseq drivers to generic place,
> >>
> >> You can do that, but I'm going to NAK any use of pwrseq bindings outside 
> >> of MMC. I think it is the wrong way to do things. The DT should describe 
> >> the devices. If they happen to be "simple" then the core can walk the 
> >> tree and do any setup. For example, look for "reset-gpios" and toggle 
> >> that GPIO. There is no need for a special node.
> >>
> > 
> > Oh, I am doing the same thing like this patch set doing.
> 
> Shame on me that I did not use Google before starting the work. I could
> just extend your patchset. I think we can combine our efforts.
> 

Sure :)

-- 

Best Regards,
Peter Chen


From k.kozlowski at samsung.com  Fri May  6 00:24:56 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 09:24:56 +0200
Subject: [PATCH v6 1/9] input: max8997-haptic: Fix NULL pointer dereference
In-Reply-To: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462519504-3092-1-git-send-email-k.kozlowski@samsung.com>

From: Marek Szyprowski <m.szyprowski at samsung.com>

NULL pointer derefence happens when booting with DTB because the
platform data for haptic device is not set in supplied data from parent
MFD device.

The MFD device creates only platform data (from Device Tree) for itself,
not for haptic child.

Unable to handle kernel NULL pointer dereference at virtual address 0000009c
pgd = c0004000
	[0000009c] *pgd=00000000
	Internal error: Oops: 5 [#1] PREEMPT SMP ARM
	(max8997_haptic_probe) from [<c03f9cec>] (platform_drv_probe+0x4c/0xb0)
	(platform_drv_probe) from [<c03f8440>] (driver_probe_device+0x214/0x2c0)
	(driver_probe_device) from [<c03f8598>] (__driver_attach+0xac/0xb0)
	(__driver_attach) from [<c03f67ac>] (bus_for_each_dev+0x68/0x9c)
	(bus_for_each_dev) from [<c03f7a38>] (bus_add_driver+0x1a0/0x218)
	(bus_add_driver) from [<c03f8db0>] (driver_register+0x78/0xf8)
	(driver_register) from [<c0101774>] (do_one_initcall+0x90/0x1d8)
	(do_one_initcall) from [<c0a00dbc>] (kernel_init_freeable+0x15c/0x1fc)
	(kernel_init_freeable) from [<c06bb5b4>] (kernel_init+0x8/0x114)
	(kernel_init) from [<c0107938>] (ret_from_fork+0x14/0x3c)

Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
Cc: <stable at vger.kernel.org>
Fixes: 104594b01ce7 ("Input: add driver support for MAX8997-haptic")
[k.kozlowski: Write commit message, add CC-stable]
Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/input/misc/max8997_haptic.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
index a806ba3818f7..8d6326d7e7be 100644
--- a/drivers/input/misc/max8997_haptic.c
+++ b/drivers/input/misc/max8997_haptic.c
@@ -255,12 +255,14 @@ static int max8997_haptic_probe(struct platform_device *pdev)
 	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	const struct max8997_platform_data *pdata =
 					dev_get_platdata(iodev->dev);
-	const struct max8997_haptic_platform_data *haptic_pdata =
-					pdata->haptic_pdata;
+	const struct max8997_haptic_platform_data *haptic_pdata = NULL;
 	struct max8997_haptic *chip;
 	struct input_dev *input_dev;
 	int error;
 
+	if (pdata)
+		haptic_pdata = pdata->haptic_pdata;
+
 	if (!haptic_pdata) {
 		dev_err(&pdev->dev, "no haptic platform data\n");
 		return -EINVAL;
-- 
1.9.1



From k.kozlowski at samsung.com  Fri May  6 00:27:10 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 09:27:10 +0200
Subject: [PATCH v6 3/9] mfd: max8997: handle IRQs using regmap
In-Reply-To: <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462519636-3250-2-git-send-email-k.kozlowski@samsung.com>

From: Robert Baldyga <r.baldyga at samsung.com>

This patch modifies mfd driver to use regmap for handling interrupts.
It allows to simplify irq handling process. This modifications needed
to make small changes in function drivers, which use interrupts.

Signed-off-by: Robert Baldyga <r.baldyga at samsung.com>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

[For extcon part]
Acked-by: Chanwoo Choi <cw00.choi at samsung.com>

[For the mfd part]
Acked-by: Lee Jones <lee.jones at linaro.org>
Acked-by: Alexandre Belloni <alexandre.belloni at free-electrons.com>
[k.kozlowski: Collect acks, rebase on v4.6-rc6]
Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/extcon/extcon-max8997.c     |   3 +-
 drivers/mfd/Kconfig                 |   2 +-
 drivers/mfd/Makefile                |   2 +-
 drivers/mfd/max8997-irq.c           | 369 ------------------------------------
 drivers/mfd/max8997.c               | 112 ++++++++++-
 drivers/rtc/rtc-max8997.c           |   2 +-
 include/linux/mfd/max8997-private.h |  63 +++++-
 7 files changed, 165 insertions(+), 388 deletions(-)
 delete mode 100644 drivers/mfd/max8997-irq.c

diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index fc812257bfc7..9d27cc23038f 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -662,7 +662,8 @@ static int max8997_muic_probe(struct platform_device *pdev)
 		struct max8997_muic_irq *muic_irq = &muic_irqs[i];
 		unsigned int virq = 0;
 
-		virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq);
+		virq = regmap_irq_get_virq(max8997->irq_data_muic,
+					muic_irq->irq);
 		if (!virq) {
 			ret = -EINVAL;
 			goto err_irq;
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 40eae54ba663..49b7838dac76 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -597,7 +597,7 @@ config MFD_MAX8997
 	depends on I2C=y
 	select MFD_CORE
 	select REGMAP_I2C
-	select IRQ_DOMAIN
+	select REGMAP_IRQ
 	help
 	  Say yes here to add support for Maxim Semiconductor MAX8997/8966.
 	  This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic,
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 5eaa6465d0a6..85d8ce19789f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -134,7 +134,7 @@ obj-$(CONFIG_MFD_MAX77843)	+= max77843.o
 obj-$(CONFIG_MFD_MAX8907)	+= max8907.o
 max8925-objs			:= max8925-core.o max8925-i2c.o
 obj-$(CONFIG_MFD_MAX8925)	+= max8925.o
-obj-$(CONFIG_MFD_MAX8997)	+= max8997.o max8997-irq.o
+obj-$(CONFIG_MFD_MAX8997)	+= max8997.o
 obj-$(CONFIG_MFD_MAX8998)	+= max8998.o max8998-irq.o
 
 pcf50633-objs			:= pcf50633-core.o pcf50633-irq.o
diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c
deleted file mode 100644
index 6ab5f955c510..000000000000
--- a/drivers/mfd/max8997-irq.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * max8997-irq.c - Interrupt controller support for MAX8997
- *
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * MyungJoo Ham <myungjoo.ham at samsung.com>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * This driver is based on max8998-irq.c
- */
-
-#include <linux/err.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/max8997.h>
-#include <linux/mfd/max8997-private.h>
-#include <linux/regmap.h>
-
-static const u8 max8997_mask_reg[] = {
-	[PMIC_INT1] = MAX8997_REG_INT1MSK,
-	[PMIC_INT2] = MAX8997_REG_INT2MSK,
-	[PMIC_INT3] = MAX8997_REG_INT3MSK,
-	[PMIC_INT4] = MAX8997_REG_INT4MSK,
-	[FUEL_GAUGE] = MAX8997_REG_INVALID,
-	[MUIC_INT1] = MAX8997_MUIC_REG_INTMASK1,
-	[MUIC_INT2] = MAX8997_MUIC_REG_INTMASK2,
-	[MUIC_INT3] = MAX8997_MUIC_REG_INTMASK3,
-	[GPIO_LOW] = MAX8997_REG_INVALID,
-	[GPIO_HI] = MAX8997_REG_INVALID,
-	[FLASH_STATUS] = MAX8997_REG_INVALID,
-};
-
-struct max8997_irq_data {
-	int mask;
-	enum max8997_irq_source group;
-};
-
-#define DECLARE_IRQ(idx, _group, _mask)		\
-	[(idx)] = { .group = (_group), .mask = (_mask) }
-static const struct max8997_irq_data max8997_irqs[] = {
-	DECLARE_IRQ(MAX8997_PMICIRQ_PWRONR,	PMIC_INT1, 1 << 0),
-	DECLARE_IRQ(MAX8997_PMICIRQ_PWRONF,	PMIC_INT1, 1 << 1),
-	DECLARE_IRQ(MAX8997_PMICIRQ_PWRON1SEC,	PMIC_INT1, 1 << 3),
-	DECLARE_IRQ(MAX8997_PMICIRQ_JIGONR,	PMIC_INT1, 1 << 4),
-	DECLARE_IRQ(MAX8997_PMICIRQ_JIGONF,	PMIC_INT1, 1 << 5),
-	DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT2,	PMIC_INT1, 1 << 6),
-	DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT1,	PMIC_INT1, 1 << 7),
-
-	DECLARE_IRQ(MAX8997_PMICIRQ_JIGR,	PMIC_INT2, 1 << 0),
-	DECLARE_IRQ(MAX8997_PMICIRQ_JIGF,	PMIC_INT2, 1 << 1),
-	DECLARE_IRQ(MAX8997_PMICIRQ_MR,		PMIC_INT2, 1 << 2),
-	DECLARE_IRQ(MAX8997_PMICIRQ_DVS1OK,	PMIC_INT2, 1 << 3),
-	DECLARE_IRQ(MAX8997_PMICIRQ_DVS2OK,	PMIC_INT2, 1 << 4),
-	DECLARE_IRQ(MAX8997_PMICIRQ_DVS3OK,	PMIC_INT2, 1 << 5),
-	DECLARE_IRQ(MAX8997_PMICIRQ_DVS4OK,	PMIC_INT2, 1 << 6),
-
-	DECLARE_IRQ(MAX8997_PMICIRQ_CHGINS,	PMIC_INT3, 1 << 0),
-	DECLARE_IRQ(MAX8997_PMICIRQ_CHGRM,	PMIC_INT3, 1 << 1),
-	DECLARE_IRQ(MAX8997_PMICIRQ_DCINOVP,	PMIC_INT3, 1 << 2),
-	DECLARE_IRQ(MAX8997_PMICIRQ_TOPOFFR,	PMIC_INT3, 1 << 3),
-	DECLARE_IRQ(MAX8997_PMICIRQ_CHGRSTF,	PMIC_INT3, 1 << 5),
-	DECLARE_IRQ(MAX8997_PMICIRQ_MBCHGTMEXPD,	PMIC_INT3, 1 << 7),
-
-	DECLARE_IRQ(MAX8997_PMICIRQ_RTC60S,	PMIC_INT4, 1 << 0),
-	DECLARE_IRQ(MAX8997_PMICIRQ_RTCA1,	PMIC_INT4, 1 << 1),
-	DECLARE_IRQ(MAX8997_PMICIRQ_RTCA2,	PMIC_INT4, 1 << 2),
-	DECLARE_IRQ(MAX8997_PMICIRQ_SMPL_INT,	PMIC_INT4, 1 << 3),
-	DECLARE_IRQ(MAX8997_PMICIRQ_RTC1S,	PMIC_INT4, 1 << 4),
-	DECLARE_IRQ(MAX8997_PMICIRQ_WTSR,	PMIC_INT4, 1 << 5),
-
-	DECLARE_IRQ(MAX8997_MUICIRQ_ADCError,	MUIC_INT1, 1 << 2),
-	DECLARE_IRQ(MAX8997_MUICIRQ_ADCLow,	MUIC_INT1, 1 << 1),
-	DECLARE_IRQ(MAX8997_MUICIRQ_ADC,	MUIC_INT1, 1 << 0),
-
-	DECLARE_IRQ(MAX8997_MUICIRQ_VBVolt,	MUIC_INT2, 1 << 4),
-	DECLARE_IRQ(MAX8997_MUICIRQ_DBChg,	MUIC_INT2, 1 << 3),
-	DECLARE_IRQ(MAX8997_MUICIRQ_DCDTmr,	MUIC_INT2, 1 << 2),
-	DECLARE_IRQ(MAX8997_MUICIRQ_ChgDetRun,	MUIC_INT2, 1 << 1),
-	DECLARE_IRQ(MAX8997_MUICIRQ_ChgTyp,	MUIC_INT2, 1 << 0),
-
-	DECLARE_IRQ(MAX8997_MUICIRQ_OVP,	MUIC_INT3, 1 << 2),
-};
-
-static void max8997_irq_lock(struct irq_data *data)
-{
-	struct max8997_dev *max8997 = irq_data_get_irq_chip_data(data);
-
-	mutex_lock(&max8997->irqlock);
-}
-
-static void max8997_irq_sync_unlock(struct irq_data *data)
-{
-	struct max8997_dev *max8997 = irq_data_get_irq_chip_data(data);
-	int i;
-
-	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
-		struct regmap *map;
-		u8 mask_reg = max8997_mask_reg[i];
-
-		if (i >= MUIC_INT1 && i <= MUIC_INT3)
-			map = max8997->regmap_muic;
-		else
-			map = max8997->regmap;
-
-		if (mask_reg == MAX8997_REG_INVALID ||
-				IS_ERR_OR_NULL(map))
-			continue;
-		max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i];
-
-		regmap_write(map, max8997_mask_reg[i],
-				max8997->irq_masks_cur[i]);
-	}
-
-	mutex_unlock(&max8997->irqlock);
-}
-
-static const inline struct max8997_irq_data *
-irq_to_max8997_irq(struct max8997_dev *max8997, struct irq_data *data)
-{
-	return &max8997_irqs[data->hwirq];
-}
-
-static void max8997_irq_mask(struct irq_data *data)
-{
-	struct max8997_dev *max8997 = irq_data_get_irq_chip_data(data);
-	const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
-								     data);
-
-	max8997->irq_masks_cur[irq_data->group] |= irq_data->mask;
-}
-
-static void max8997_irq_unmask(struct irq_data *data)
-{
-	struct max8997_dev *max8997 = irq_data_get_irq_chip_data(data);
-	const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
-								     data);
-
-	max8997->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
-}
-
-static struct irq_chip max8997_irq_chip = {
-	.name			= "max8997",
-	.irq_bus_lock		= max8997_irq_lock,
-	.irq_bus_sync_unlock	= max8997_irq_sync_unlock,
-	.irq_mask		= max8997_irq_mask,
-	.irq_unmask		= max8997_irq_unmask,
-};
-
-#define MAX8997_IRQSRC_PMIC		(1 << 1)
-#define MAX8997_IRQSRC_FUELGAUGE	(1 << 2)
-#define MAX8997_IRQSRC_MUIC		(1 << 3)
-#define MAX8997_IRQSRC_GPIO		(1 << 4)
-#define MAX8997_IRQSRC_FLASH		(1 << 5)
-static irqreturn_t max8997_irq_thread(int irq, void *data)
-{
-	struct max8997_dev *max8997 = data;
-	u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {};
-	unsigned int irq_src;
-	int ret;
-	int i, cur_irq;
-
-	ret = regmap_read(max8997->regmap, MAX8997_REG_INTSRC, &irq_src);
-	if (ret < 0) {
-		dev_err(max8997->dev, "Failed to read interrupt source: %d\n",
-				ret);
-		return IRQ_NONE;
-	}
-
-	if (irq_src & MAX8997_IRQSRC_PMIC) {
-		/* PMIC INT1 ~ INT4 */
-		regmap_bulk_read(max8997->regmap, MAX8997_REG_INT1,
-				&irq_reg[PMIC_INT1], 4);
-	}
-	if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
-		/*
-		 * TODO: FUEL GAUGE
-		 *
-		 * This is to be supported by Max17042 driver. When
-		 * an interrupt incurs here, it should be relayed to a
-		 * Max17042 device that is connected (probably by
-		 * platform-data). However, we do not have interrupt
-		 * handling in Max17042 driver currently. The Max17042 IRQ
-		 * driver should be ready to be used as a stand-alone device and
-		 * a Max8997-dependent device. Because it is not ready in
-		 * Max17042-side and it is not too critical in operating
-		 * Max8997, we do not implement this in initial releases.
-		 */
-		irq_reg[FUEL_GAUGE] = 0;
-	}
-	if (irq_src & MAX8997_IRQSRC_MUIC) {
-		/* MUIC INT1 ~ INT3 */
-		regmap_bulk_read(max8997->regmap_muic, MAX8997_MUIC_REG_INT1,
-				&irq_reg[MUIC_INT1], 3);
-	}
-	if (irq_src & MAX8997_IRQSRC_GPIO) {
-		/* GPIO Interrupt */
-		u8 gpio_info[MAX8997_NUM_GPIO];
-
-		irq_reg[GPIO_LOW] = 0;
-		irq_reg[GPIO_HI] = 0;
-
-		regmap_bulk_read(max8997->regmap, MAX8997_REG_GPIOCNTL1,
-				gpio_info, MAX8997_NUM_GPIO);
-		for (i = 0; i < MAX8997_NUM_GPIO; i++) {
-			bool interrupt = false;
-
-			switch (gpio_info[i] & MAX8997_GPIO_INT_MASK) {
-			case MAX8997_GPIO_INT_BOTH:
-				if (max8997->gpio_status[i] != gpio_info[i])
-					interrupt = true;
-				break;
-			case MAX8997_GPIO_INT_RISE:
-				if ((max8997->gpio_status[i] != gpio_info[i]) &&
-				    (gpio_info[i] & MAX8997_GPIO_DATA_MASK))
-					interrupt = true;
-				break;
-			case MAX8997_GPIO_INT_FALL:
-				if ((max8997->gpio_status[i] != gpio_info[i]) &&
-				    !(gpio_info[i] & MAX8997_GPIO_DATA_MASK))
-					interrupt = true;
-				break;
-			default:
-				break;
-			}
-
-			if (interrupt) {
-				if (i < 8)
-					irq_reg[GPIO_LOW] |= (1 << i);
-				else
-					irq_reg[GPIO_HI] |= (1 << (i - 8));
-			}
-
-		}
-	}
-	if (irq_src & MAX8997_IRQSRC_FLASH) {
-		/* Flash Status Interrupt */
-		unsigned int data;
-		ret = regmap_read(max8997->regmap,
-				MAX8997_REG_FLASHSTATUS, &data);
-		irq_reg[FLASH_STATUS] = data;
-	}
-
-	/* Apply masking */
-	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++)
-		irq_reg[i] &= ~max8997->irq_masks_cur[i];
-
-	/* Report */
-	for (i = 0; i < MAX8997_IRQ_NR; i++) {
-		if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) {
-			cur_irq = irq_find_mapping(max8997->irq_domain, i);
-			if (cur_irq)
-				handle_nested_irq(cur_irq);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-int max8997_irq_resume(struct max8997_dev *max8997)
-{
-	if (max8997->irq && max8997->irq_domain)
-		max8997_irq_thread(0, max8997);
-	return 0;
-}
-
-static int max8997_irq_domain_map(struct irq_domain *d, unsigned int irq,
-					irq_hw_number_t hw)
-{
-	struct max8997_dev *max8997 = d->host_data;
-
-	irq_set_chip_data(irq, max8997);
-	irq_set_chip_and_handler(irq, &max8997_irq_chip, handle_edge_irq);
-	irq_set_nested_thread(irq, 1);
-	irq_set_noprobe(irq);
-
-	return 0;
-}
-
-static const struct irq_domain_ops max8997_irq_domain_ops = {
-	.map = max8997_irq_domain_map,
-};
-
-int max8997_irq_init(struct max8997_dev *max8997)
-{
-	struct irq_domain *domain;
-	int i;
-	int ret;
-	unsigned int val;
-
-	if (!max8997->irq) {
-		dev_warn(max8997->dev, "No interrupt specified.\n");
-		return 0;
-	}
-
-	mutex_init(&max8997->irqlock);
-
-	/* Mask individual interrupt sources */
-	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
-		max8997->irq_masks_cur[i] = 0xff;
-		max8997->irq_masks_cache[i] = 0xff;
-
-		if (IS_ERR_OR_NULL(max8997->regmap))
-			continue;
-		if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
-			continue;
-
-		regmap_write(max8997->regmap, max8997_mask_reg[i], 0xff);
-	}
-
-	for (i = 0; i < MAX8997_NUM_GPIO; i++) {
-		max8997->gpio_status[i] = (regmap_read(max8997->regmap,
-						MAX8997_REG_GPIOCNTL1 + i,
-						&val)
-					& MAX8997_GPIO_DATA_MASK) ?
-					true : false;
-	}
-
-	domain = irq_domain_add_linear(NULL, MAX8997_IRQ_NR,
-					&max8997_irq_domain_ops, max8997);
-	if (!domain) {
-		dev_err(max8997->dev, "could not create irq domain\n");
-		return -ENODEV;
-	}
-	max8997->irq_domain = domain;
-
-	ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread,
-			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-			"max8997-irq", max8997);
-
-	if (ret) {
-		dev_err(max8997->dev, "Failed to request IRQ %d: %d\n",
-				max8997->irq, ret);
-		return ret;
-	}
-
-	if (!max8997->ono)
-		return 0;
-
-	ret = request_threaded_irq(max8997->ono, NULL, max8997_irq_thread,
-			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
-			IRQF_ONESHOT, "max8997-ono", max8997);
-
-	if (ret)
-		dev_err(max8997->dev, "Failed to request ono-IRQ %d: %d\n",
-				max8997->ono, ret);
-
-	return 0;
-}
-
-void max8997_irq_exit(struct max8997_dev *max8997)
-{
-	if (max8997->ono)
-		free_irq(max8997->ono, max8997);
-
-	if (max8997->irq)
-		free_irq(max8997->irq, max8997);
-}
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index f1c82110b2ab..932e22c05026 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -65,6 +65,49 @@ static const struct regmap_config max8997_regmap_config = {
 	.max_register = MAX8997_REG_PMIC_END,
 };
 
+static const struct regmap_irq max8997_irqs[] = {
+	/* PMIC_INT1 interrupts */
+	{ .reg_offset = 0, .mask = PMIC_INT1_PWRONR_MASK, },
+	{ .reg_offset = 0, .mask = PMIC_INT1_PWRONF_MASK, },
+	{ .reg_offset = 0, .mask = PMIC_INT1_PWRON1SEC_MASK, },
+	{ .reg_offset = 0, .mask = PMIC_INT1_JIGONR_MASK, },
+	{ .reg_offset = 0, .mask = PMIC_INT1_JIGONF_MASK, },
+	{ .reg_offset = 0, .mask = PMIC_INT1_LOWBAT2_MASK, },
+	{ .reg_offset = 0, .mask = PMIC_INT1_LOWBAT1_MASK, },
+	/* PMIC_INT2 interrupts */
+	{ .reg_offset = 1, .mask = PMIC_INT2_JIGR_MASK, },
+	{ .reg_offset = 1, .mask = PMIC_INT2_JIGF_MASK, },
+	{ .reg_offset = 1, .mask = PMIC_INT2_MR_MASK, },
+	{ .reg_offset = 1, .mask = PMIC_INT2_DVS1OK_MASK, },
+	{ .reg_offset = 1, .mask = PMIC_INT2_DVS2OK_MASK, },
+	{ .reg_offset = 1, .mask = PMIC_INT2_DVS3OK_MASK, },
+	{ .reg_offset = 1, .mask = PMIC_INT2_DVS4OK_MASK, },
+	/* PMIC_INT3 interrupts */
+	{ .reg_offset = 2, .mask = PMIC_INT3_CHGINS_MASK, },
+	{ .reg_offset = 2, .mask = PMIC_INT3_CHGRM_MASK, },
+	{ .reg_offset = 2, .mask = PMIC_INT3_DCINOVP_MASK, },
+	{ .reg_offset = 2, .mask = PMIC_INT3_TOPOFFR_MASK, },
+	{ .reg_offset = 2, .mask = PMIC_INT3_CHGRSTF_MASK, },
+	{ .reg_offset = 2, .mask = PMIC_INT3_MBCHGTMEXPD_MASK, },
+	/* PMIC_INT4 interrupts */
+	{ .reg_offset = 3, .mask = PMIC_INT4_RTC60S_MASK, },
+	{ .reg_offset = 3, .mask = PMIC_INT4_RTCA1_MASK, },
+	{ .reg_offset = 3, .mask = PMIC_INT4_RTCA2_MASK, },
+	{ .reg_offset = 3, .mask = PMIC_INT4_SMPL_INT_MASK, },
+	{ .reg_offset = 3, .mask = PMIC_INT4_RTC1S_MASK, },
+	{ .reg_offset = 3, .mask = PMIC_INT4_WTSR_MASK, },
+};
+
+static const struct regmap_irq_chip max8997_irq_chip = {
+	.name			= "max8997",
+	.status_base		= MAX8997_REG_INT1,
+	.mask_base		= MAX8997_REG_INT1MSK,
+	.mask_invert		= false,
+	.num_regs		= 4,
+	.irqs			= max8997_irqs,
+	.num_irqs		= ARRAY_SIZE(max8997_irqs),
+};
+
 static const struct regmap_config max8997_regmap_rtc_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -83,6 +126,31 @@ static const struct regmap_config max8997_regmap_muic_config = {
 	.max_register = MAX8997_MUIC_REG_END,
 };
 
+static const struct regmap_irq max8997_irqs_muic[] = {
+	/* MUIC_INT1 interrupts */
+	{ .reg_offset = 0, .mask = MUIC_INT1_ADC_MASK, },
+	{ .reg_offset = 0, .mask = MUIC_INT1_ADCLOW_MASK, },
+	{ .reg_offset = 0, .mask = MUIC_INT1_ADCERROR_MASK, },
+	/* MUIC_INT2 interrupts */
+	{ .reg_offset = 1, .mask = MUIC_INT2_CHGTYP_MASK, },
+	{ .reg_offset = 1, .mask = MUIC_INT2_CHGDETRUN_MASK, },
+	{ .reg_offset = 1, .mask = MUIC_INT2_DCDTMR_MASK, },
+	{ .reg_offset = 1, .mask = MUIC_INT2_DBCHG_MASK, },
+	{ .reg_offset = 1, .mask = MUIC_INT2_VBVOLT_MASK, },
+	/* MUIC_INT3 interrupts */
+	{ .reg_offset = 2, .mask = MUIC_INT3_OVP_MASK, },
+};
+
+static const struct regmap_irq_chip max8997_irq_chip_muic = {
+	.name			= "max8997-muic",
+	.status_base		= MAX8997_MUIC_REG_INT1,
+	.mask_base		= MAX8997_MUIC_REG_INTMASK1,
+	.mask_invert		= true,
+	.num_regs		= 3,
+	.irqs			= max8997_irqs_muic,
+	.num_irqs		= ARRAY_SIZE(max8997_irqs_muic),
+};
+
 /*
  * Only the common platform data elements for max8997 are parsed here from the
  * device tree. Other sub-modules of max8997 such as pmic, rtc and others have
@@ -215,9 +283,26 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
 		goto err_regmap;
 	}
 
-	pm_runtime_set_active(max8997->dev);
+	ret = regmap_add_irq_chip(max8997->regmap, max8997->irq,
+				IRQF_ONESHOT | IRQF_SHARED |
+				IRQF_TRIGGER_FALLING, 0,
+				&max8997_irq_chip, &max8997->irq_data);
+	if (ret) {
+		dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
+		goto err_regmap;
+	}
 
-	max8997_irq_init(max8997);
+	ret = regmap_add_irq_chip(max8997->regmap_muic, max8997->irq,
+				IRQF_ONESHOT | IRQF_SHARED |
+				IRQF_TRIGGER_FALLING, 0,
+				&max8997_irq_chip_muic,
+				&max8997->irq_data_muic);
+	if (ret) {
+		dev_err(max8997->dev, "failed to add irq chip: %d\n", ret);
+		goto err_irq_muic;
+	}
+
+	pm_runtime_set_active(max8997->dev);
 
 	ret = mfd_add_devices(max8997->dev, -1, max8997_devs,
 			ARRAY_SIZE(max8997_devs),
@@ -239,6 +324,9 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
 
 err_mfd:
 	mfd_remove_devices(max8997->dev);
+	regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
+err_irq_muic:
+	regmap_del_irq_chip(max8997->irq, max8997->irq_data);
 err_regmap:
 	i2c_unregister_device(max8997->muic);
 err_i2c_muic:
@@ -253,6 +341,10 @@ static int max8997_i2c_remove(struct i2c_client *i2c)
 	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
 
 	mfd_remove_devices(max8997->dev);
+
+	regmap_del_irq_chip(max8997->irq, max8997->irq_data_muic);
+	regmap_del_irq_chip(max8997->irq, max8997->irq_data);
+
 	i2c_unregister_device(max8997->muic);
 	i2c_unregister_device(max8997->haptic);
 	i2c_unregister_device(max8997->rtc);
@@ -469,8 +561,11 @@ static int max8997_suspend(struct device *dev)
 	struct i2c_client *i2c = to_i2c_client(dev);
 	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
 
-	if (device_may_wakeup(dev))
-		irq_set_irq_wake(max8997->irq, 1);
+	if (device_may_wakeup(dev)) {
+		enable_irq_wake(max8997->irq);
+		disable_irq(max8997->irq);
+	}
+
 	return 0;
 }
 
@@ -479,9 +574,12 @@ static int max8997_resume(struct device *dev)
 	struct i2c_client *i2c = to_i2c_client(dev);
 	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
 
-	if (device_may_wakeup(dev))
-		irq_set_irq_wake(max8997->irq, 0);
-	return max8997_irq_resume(max8997);
+	if (device_may_wakeup(dev)) {
+		disable_irq_wake(max8997->irq);
+		enable_irq(max8997->irq);
+	}
+
+	return 0;
 }
 
 static const struct dev_pm_ops max8997_pm = {
diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
index d017a34a9f70..4998aee0f07f 100644
--- a/drivers/rtc/rtc-max8997.c
+++ b/drivers/rtc/rtc-max8997.c
@@ -496,7 +496,7 @@ static int max8997_rtc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	virq = irq_create_mapping(max8997->irq_domain, MAX8997_PMICIRQ_RTCA1);
+	virq = regmap_irq_get_virq(max8997->irq_data, MAX8997_PMICIRQ_RTCA1);
 	if (!virq) {
 		dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n");
 		ret = -ENXIO;
diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
index ea80ef80dbf8..f42ea222988f 100644
--- a/include/linux/mfd/max8997-private.h
+++ b/include/linux/mfd/max8997-private.h
@@ -333,6 +333,48 @@ enum max8997_irq_source {
 	MAX8997_IRQ_GROUP_NR,
 };
 
+#define PMIC_INT1_PWRONR_MASK		(0x1 << 0)
+#define PMIC_INT1_PWRONF_MASK		(0x1 << 1)
+#define PMIC_INT1_PWRON1SEC_MASK	(0x1 << 3)
+#define PMIC_INT1_JIGONR_MASK		(0x1 << 4)
+#define PMIC_INT1_JIGONF_MASK		(0x1 << 5)
+#define PMIC_INT1_LOWBAT2_MASK		(0x1 << 6)
+#define PMIC_INT1_LOWBAT1_MASK		(0x1 << 7)
+
+#define PMIC_INT2_JIGR_MASK		(0x1 << 0)
+#define PMIC_INT2_JIGF_MASK		(0x1 << 1)
+#define PMIC_INT2_MR_MASK		(0x1 << 2)
+#define PMIC_INT2_DVS1OK_MASK		(0x1 << 3)
+#define PMIC_INT2_DVS2OK_MASK		(0x1 << 4)
+#define PMIC_INT2_DVS3OK_MASK		(0x1 << 5)
+#define PMIC_INT2_DVS4OK_MASK		(0x1 << 6)
+
+#define PMIC_INT3_CHGINS_MASK		(0x1 << 0)
+#define PMIC_INT3_CHGRM_MASK		(0x1 << 1)
+#define PMIC_INT3_DCINOVP_MASK		(0x1 << 2)
+#define PMIC_INT3_TOPOFFR_MASK		(0x1 << 3)
+#define PMIC_INT3_CHGRSTF_MASK		(0x1 << 5)
+#define PMIC_INT3_MBCHGTMEXPD_MASK	(0x1 << 7)
+
+#define PMIC_INT4_RTC60S_MASK		(0x1 << 0)
+#define PMIC_INT4_RTCA1_MASK		(0x1 << 1)
+#define PMIC_INT4_RTCA2_MASK		(0x1 << 2)
+#define PMIC_INT4_SMPL_INT_MASK		(0x1 << 3)
+#define PMIC_INT4_RTC1S_MASK		(0x1 << 4)
+#define PMIC_INT4_WTSR_MASK		(0x1 << 5)
+
+#define MUIC_INT1_ADC_MASK		(0x1 << 0)
+#define MUIC_INT1_ADCLOW_MASK		(0x1 << 1)
+#define MUIC_INT1_ADCERROR_MASK		(0x1 << 2)
+
+#define MUIC_INT2_CHGTYP_MASK		(0x1 << 0)
+#define MUIC_INT2_CHGDETRUN_MASK	(0x1 << 1)
+#define MUIC_INT2_DCDTMR_MASK		(0x1 << 2)
+#define MUIC_INT2_DBCHG_MASK		(0x1 << 3)
+#define MUIC_INT2_VBVOLT_MASK		(0x1 << 4)
+
+#define MUIC_INT3_OVP_MASK		(0x1 << 2)
+
 enum max8997_irq {
 	MAX8997_PMICIRQ_PWRONR,
 	MAX8997_PMICIRQ_PWRONF,
@@ -364,19 +406,23 @@ enum max8997_irq {
 	MAX8997_PMICIRQ_RTC1S,
 	MAX8997_PMICIRQ_WTSR,
 
-	MAX8997_MUICIRQ_ADCError,
-	MAX8997_MUICIRQ_ADCLow,
+	MAX8997_PMICIRQ_NR,
+};
+
+enum max8997_irq_muic {
 	MAX8997_MUICIRQ_ADC,
+	MAX8997_MUICIRQ_ADCLow,
+	MAX8997_MUICIRQ_ADCError,
 
-	MAX8997_MUICIRQ_VBVolt,
-	MAX8997_MUICIRQ_DBChg,
-	MAX8997_MUICIRQ_DCDTmr,
-	MAX8997_MUICIRQ_ChgDetRun,
 	MAX8997_MUICIRQ_ChgTyp,
+	MAX8997_MUICIRQ_ChgDetRun,
+	MAX8997_MUICIRQ_DCDTmr,
+	MAX8997_MUICIRQ_DBChg,
+	MAX8997_MUICIRQ_VBVolt,
 
 	MAX8997_MUICIRQ_OVP,
 
-	MAX8997_IRQ_NR,
+	MAX8997_MUCIRQ_NR,
 };
 
 #define MAX8997_NUM_GPIO	12
@@ -397,9 +443,10 @@ struct max8997_dev {
 	struct regmap *regmap_haptic;
 	struct regmap *regmap_muic;
 
+	struct regmap_irq_chip_data *irq_data;
+	struct regmap_irq_chip_data *irq_data_muic;
 	int irq;
 	int ono;
-	struct irq_domain *irq_domain;
 	struct mutex irqlock;
 	int irq_masks_cur[MAX8997_IRQ_GROUP_NR];
 	int irq_masks_cache[MAX8997_IRQ_GROUP_NR];
-- 
1.9.1



From k.kozlowski at samsung.com  Fri May  6 00:27:12 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 09:27:12 +0200
Subject: [PATCH v6 5/9] extcon: max8997: Fix handling error code of
 regmap_irq_get_virq()
In-Reply-To: <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462519636-3250-4-git-send-email-k.kozlowski@samsung.com>

The regmap_irq_get_virq() can return negative ERRNO, so its result
should not be stored in unsigned int because error would be ignored.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/extcon/extcon-max8997.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 68754ac2c8ea..0afa3e8b5dc3 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -660,11 +660,11 @@ static int max8997_muic_probe(struct platform_device *pdev)
 
 	for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
 		struct max8997_muic_irq *muic_irq = &muic_irqs[i];
-		unsigned int virq = 0;
+		int virq = 0;
 
 		virq = regmap_irq_get_virq(max8997->irq_data_muic,
 					muic_irq->irq);
-		if (!virq) {
+		if (virq <= 0) {
 			ret = -EINVAL;
 			goto err_irq;
 		}
-- 
1.9.1



From k.kozlowski at samsung.com  Fri May  6 00:27:14 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 09:27:14 +0200
Subject: [PATCH v6 7/9] extcon: max8997: Fix inconsistent indenting
In-Reply-To: <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462519636-3250-6-git-send-email-k.kozlowski@samsung.com>

Fix smatch warning:
	max8997_muic_probe() warn: inconsistent indenting

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/extcon/extcon-max8997.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 0afa3e8b5dc3..cf8de5be2405 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -737,7 +737,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
 	}
 
 	/* Set initial path for UART */
-	 max8997_muic_set_path(info, info->path_uart, true);
+	max8997_muic_set_path(info, info->path_uart, true);
 
 	/* Set ADC debounce time */
 	max8997_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);
-- 
1.9.1



From k.kozlowski at samsung.com  Fri May  6 00:27:11 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 09:27:11 +0200
Subject: [PATCH v6 4/9] mfd: max8997: Change irq names to upper case
In-Reply-To: <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462519636-3250-3-git-send-email-k.kozlowski@samsung.com>

From: Robert Baldyga <r.baldyga at samsung.com>

This patch changes naming convention of MUIC interrupts form CamelCase
to upper case. It makes names more readable and consistent with another
interrupt names in max8997 driver.

Signed-off-by: Robert Baldyga <r.baldyga at samsung.com>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

[For the mfd part]
Acked-by: Lee Jones <lee.jones at linaro.org>
Acked-by: Chanwoo Choi <cw00.choi at samsung.com>
Acked-by: Alexandre Belloni <alexandre.belloni at free-electrons.com>
[k.kozlowski: Collect acks, rebase on v4.6-rc6]
Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/extcon/extcon-max8997.c     | 32 ++++++++++++++++----------------
 include/linux/mfd/max8997-private.h | 16 ++++++++--------
 2 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 9d27cc23038f..68754ac2c8ea 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -46,15 +46,15 @@ struct max8997_muic_irq {
 };
 
 static struct max8997_muic_irq muic_irqs[] = {
-	{ MAX8997_MUICIRQ_ADCError,	"muic-ADCERROR" },
-	{ MAX8997_MUICIRQ_ADCLow,	"muic-ADCLOW" },
-	{ MAX8997_MUICIRQ_ADC,		"muic-ADC" },
-	{ MAX8997_MUICIRQ_VBVolt,	"muic-VBVOLT" },
-	{ MAX8997_MUICIRQ_DBChg,	"muic-DBCHG" },
-	{ MAX8997_MUICIRQ_DCDTmr,	"muic-DCDTMR" },
-	{ MAX8997_MUICIRQ_ChgDetRun,	"muic-CHGDETRUN" },
-	{ MAX8997_MUICIRQ_ChgTyp,	"muic-CHGTYP" },
-	{ MAX8997_MUICIRQ_OVP,		"muic-OVP" },
+	{ MAX8997_MUICIRQ_ADCERROR,	"MUIC-ADCERROR" },
+	{ MAX8997_MUICIRQ_ADCLOW,	"MUIC-ADCLOW" },
+	{ MAX8997_MUICIRQ_ADC,		"MUIC-ADC" },
+	{ MAX8997_MUICIRQ_VBVOLT,	"MUIC-VBVOLT" },
+	{ MAX8997_MUICIRQ_DBCHG,	"MUIC-DBCHG" },
+	{ MAX8997_MUICIRQ_DCDTMR,	"MUIC-DCDTMR" },
+	{ MAX8997_MUICIRQ_CHGDETRUN,	"MUIC-CHGDETRUN" },
+	{ MAX8997_MUICIRQ_CHGTYP,	"MUIC-CHGTYP" },
+	{ MAX8997_MUICIRQ_OVP,		"MUIC-OVP" },
 };
 
 /* Define supported cable type */
@@ -540,17 +540,17 @@ static void max8997_muic_irq_work(struct work_struct *work)
 	}
 
 	switch (irq_type) {
-	case MAX8997_MUICIRQ_ADCError:
-	case MAX8997_MUICIRQ_ADCLow:
+	case MAX8997_MUICIRQ_ADCERROR:
+	case MAX8997_MUICIRQ_ADCLOW:
 	case MAX8997_MUICIRQ_ADC:
 		/* Handle all of cable except for charger cable */
 		ret = max8997_muic_adc_handler(info);
 		break;
-	case MAX8997_MUICIRQ_VBVolt:
-	case MAX8997_MUICIRQ_DBChg:
-	case MAX8997_MUICIRQ_DCDTmr:
-	case MAX8997_MUICIRQ_ChgDetRun:
-	case MAX8997_MUICIRQ_ChgTyp:
+	case MAX8997_MUICIRQ_VBVOLT:
+	case MAX8997_MUICIRQ_DBCHG:
+	case MAX8997_MUICIRQ_DCDTMR:
+	case MAX8997_MUICIRQ_CHGDETRUN:
+	case MAX8997_MUICIRQ_CHGTYP:
 		/* Handle charger cable */
 		ret = max8997_muic_chg_handler(info);
 		break;
diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
index f42ea222988f..2817fa69383e 100644
--- a/include/linux/mfd/max8997-private.h
+++ b/include/linux/mfd/max8997-private.h
@@ -411,14 +411,14 @@ enum max8997_irq {
 
 enum max8997_irq_muic {
 	MAX8997_MUICIRQ_ADC,
-	MAX8997_MUICIRQ_ADCLow,
-	MAX8997_MUICIRQ_ADCError,
-
-	MAX8997_MUICIRQ_ChgTyp,
-	MAX8997_MUICIRQ_ChgDetRun,
-	MAX8997_MUICIRQ_DCDTmr,
-	MAX8997_MUICIRQ_DBChg,
-	MAX8997_MUICIRQ_VBVolt,
+	MAX8997_MUICIRQ_ADCLOW,
+	MAX8997_MUICIRQ_ADCERROR,
+
+	MAX8997_MUICIRQ_CHGTYP,
+	MAX8997_MUICIRQ_CHGDETRUN,
+	MAX8997_MUICIRQ_DCDTMR,
+	MAX8997_MUICIRQ_DBCHG,
+	MAX8997_MUICIRQ_VBVOLT,
 
 	MAX8997_MUICIRQ_OVP,
 
-- 
1.9.1



From k.kozlowski at samsung.com  Fri May  6 00:27:09 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 09:27:09 +0200
Subject: [PATCH v6 2/9] mfd: max8997: Use regmap to access registers
In-Reply-To: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>

From: Robert Baldyga <r.baldyga at samsung.com>

This patch modifies max8997 driver and each associated function driver,
to use regmap instead of operating directly on i2c bus. It will allow to
simplify IRQ handling using regmap-irq.

Signed-off-by: Robert Baldyga <r.baldyga at samsung.com>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

[For extcon part]
Acked-by: Chanwoo Choi <cw00.choi at samsung.com>

[For leds part]
Acked-by: Bryan Wu <cooloney at gmail.com>

[For the mfd part]
Acked-by: Lee Jones <lee.jones at linaro.org>
Acked-by: Sebastian Reichel <sre at kernel.org>
Acked-by: Dmitry Torokhov <dmitry.torokhov at gmail.com>
Acked-by: Alexandre Belloni <alexandre.belloni at free-electrons.com>
[k.kozlowski: Collect acks, rebase on v4.6-rc6]
Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/extcon/extcon-max8997.c     |  31 ++++----
 drivers/input/misc/max8997_haptic.c |  34 +++++----
 drivers/leds/leds-max8997.c         |  13 ++--
 drivers/mfd/Kconfig                 |   1 +
 drivers/mfd/max8997-irq.c           |  64 +++++++---------
 drivers/mfd/max8997.c               | 141 ++++++++++++++++--------------------
 drivers/power/max8997_charger.c     |  33 +++++----
 drivers/regulator/max8997.c         |  87 +++++++++++-----------
 drivers/rtc/rtc-max8997.c           |  56 +++++++-------
 include/linux/mfd/max8997-private.h |  17 ++---
 10 files changed, 228 insertions(+), 249 deletions(-)

diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 9a89320d09a8..fc812257bfc7 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -27,6 +27,7 @@
 #include <linux/mfd/max8997-private.h>
 #include <linux/extcon.h>
 #include <linux/irqdomain.h>
+#include <linux/regmap.h>
 
 #define	DEV_NAME			"max8997-muic"
 #define	DELAY_MS_DEFAULT		20000		/* unit: millisecond */
@@ -116,7 +117,7 @@ enum max8997_muic_charger_type {
 
 struct max8997_muic_info {
 	struct device *dev;
-	struct i2c_client *muic;
+	struct max8997_dev *max8997;
 	struct extcon_dev *edev;
 	int prev_cable_type;
 	int prev_chg_type;
@@ -174,10 +175,10 @@ static int max8997_muic_set_debounce_time(struct max8997_muic_info *info,
 	case ADC_DEBOUNCE_TIME_10MS:
 	case ADC_DEBOUNCE_TIME_25MS:
 	case ADC_DEBOUNCE_TIME_38_62MS:
-		ret = max8997_update_reg(info->muic,
+		ret = regmap_update_bits(info->max8997->regmap_muic,
 					  MAX8997_MUIC_REG_CONTROL3,
-					  time << CONTROL3_ADCDBSET_SHIFT,
-					  CONTROL3_ADCDBSET_MASK);
+					  CONTROL3_ADCDBSET_MASK,
+					  time << CONTROL3_ADCDBSET_SHIFT);
 		if (ret) {
 			dev_err(info->dev, "failed to set ADC debounce time\n");
 			return ret;
@@ -212,8 +213,8 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
 	else
 		ctrl1 = CONTROL1_SW_OPEN;
 
-	ret = max8997_update_reg(info->muic,
-			MAX8997_MUIC_REG_CONTROL1, ctrl1, COMP_SW_MASK);
+	ret = regmap_update_bits(info->max8997->regmap_muic,
+			MAX8997_MUIC_REG_CONTROL1, COMP_SW_MASK, ctrl1);
 	if (ret < 0) {
 		dev_err(info->dev, "failed to update MUIC register\n");
 		return ret;
@@ -224,9 +225,9 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
 	else
 		ctrl2 |= CONTROL2_LOWPWR_MASK;	/* LowPwr=1, CPEn=0 */
 
-	ret = max8997_update_reg(info->muic,
-			MAX8997_MUIC_REG_CONTROL2, ctrl2,
-			CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK);
+	ret = regmap_update_bits(info->max8997->regmap_muic,
+			MAX8997_MUIC_REG_CONTROL2,
+			CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK, ctrl2);
 	if (ret < 0) {
 		dev_err(info->dev, "failed to update MUIC register\n");
 		return ret;
@@ -530,8 +531,8 @@ static void max8997_muic_irq_work(struct work_struct *work)
 		if (info->irq == muic_irqs[i].virq)
 			irq_type = muic_irqs[i].irq;
 
-	ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
-				2, info->status);
+	ret = regmap_bulk_read(info->max8997->regmap_muic,
+				MAX8997_MUIC_REG_STATUS1, info->status, 2);
 	if (ret) {
 		dev_err(info->dev, "failed to read muic register\n");
 		mutex_unlock(&info->mutex);
@@ -590,8 +591,8 @@ static int max8997_muic_detect_dev(struct max8997_muic_info *info)
 	mutex_lock(&info->mutex);
 
 	/* Read STATUSx register to detect accessory */
-	ret = max8997_bulk_read(info->muic,
-			MAX8997_MUIC_REG_STATUS1, 2, info->status);
+	ret = regmap_bulk_read(info->max8997->regmap_muic,
+			MAX8997_MUIC_REG_STATUS1, info->status, 2);
 	if (ret) {
 		dev_err(info->dev, "failed to read MUIC register\n");
 		mutex_unlock(&info->mutex);
@@ -650,7 +651,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	info->dev = &pdev->dev;
-	info->muic = max8997->muic;
+	info->max8997 = max8997;
 
 	platform_set_drvdata(pdev, info);
 	mutex_init(&info->mutex);
@@ -700,7 +701,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
 
 		/* Initialize registers according to platform data */
 		for (i = 0; i < muic_pdata->num_init_data; i++) {
-			max8997_write_reg(info->muic,
+			regmap_write(info->max8997->regmap_muic,
 					muic_pdata->init_data[i].addr,
 					muic_pdata->init_data[i].data);
 		}
diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
index 8d6326d7e7be..ed274905c9de 100644
--- a/drivers/input/misc/max8997_haptic.c
+++ b/drivers/input/misc/max8997_haptic.c
@@ -31,6 +31,7 @@
 #include <linux/mfd/max8997-private.h>
 #include <linux/mfd/max8997.h>
 #include <linux/regulator/consumer.h>
+#include <linux/regmap.h>
 
 /* Haptic configuration 2 register */
 #define MAX8997_MOTOR_TYPE_SHIFT	7
@@ -45,7 +46,7 @@
 
 struct max8997_haptic {
 	struct device *dev;
-	struct i2c_client *client;
+	struct max8997_dev *max8997;
 	struct input_dev *input_dev;
 	struct regulator *regulator;
 
@@ -86,19 +87,19 @@ static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
 		}
 		switch (chip->internal_mode_pattern) {
 		case 0:
-			max8997_write_reg(chip->client,
+			regmap_write(chip->max8997->regmap_haptic,
 				MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);
 			break;
 		case 1:
-			max8997_write_reg(chip->client,
+			regmap_write(chip->max8997->regmap_haptic,
 				MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);
 			break;
 		case 2:
-			max8997_write_reg(chip->client,
+			regmap_write(chip->max8997->regmap_haptic,
 				MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);
 			break;
 		case 3:
-			max8997_write_reg(chip->client,
+			regmap_write(chip->max8997->regmap_haptic,
 				MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);
 			break;
 		default:
@@ -115,50 +116,51 @@ static void max8997_haptic_configure(struct max8997_haptic *chip)
 	value = chip->type << MAX8997_MOTOR_TYPE_SHIFT |
 		chip->enabled << MAX8997_ENABLE_SHIFT |
 		chip->mode << MAX8997_MODE_SHIFT | chip->pwm_divisor;
-	max8997_write_reg(chip->client, MAX8997_HAPTIC_REG_CONF2, value);
+	regmap_write(chip->max8997->regmap_haptic,
+		MAX8997_HAPTIC_REG_CONF2, value);
 
 	if (chip->mode == MAX8997_INTERNAL_MODE && chip->enabled) {
 		value = chip->internal_mode_pattern << MAX8997_CYCLE_SHIFT |
 			chip->internal_mode_pattern << MAX8997_SIG_PERIOD_SHIFT |
 			chip->internal_mode_pattern << MAX8997_SIG_DUTY_SHIFT |
 			chip->internal_mode_pattern << MAX8997_PWM_DUTY_SHIFT;
-		max8997_write_reg(chip->client,
+		regmap_write(chip->max8997->regmap_haptic,
 			MAX8997_HAPTIC_REG_DRVCONF, value);
 
 		switch (chip->internal_mode_pattern) {
 		case 0:
 			value = chip->pattern_cycle << 4;
-			max8997_write_reg(chip->client,
+			regmap_write(chip->max8997->regmap_haptic,
 				MAX8997_HAPTIC_REG_CYCLECONF1, value);
 			value = chip->pattern_signal_period;
-			max8997_write_reg(chip->client,
+			regmap_write(chip->max8997->regmap_haptic,
 				MAX8997_HAPTIC_REG_SIGCONF1, value);
 			break;
 
 		case 1:
 			value = chip->pattern_cycle;
-			max8997_write_reg(chip->client,
+			regmap_write(chip->max8997->regmap_haptic,
 				MAX8997_HAPTIC_REG_CYCLECONF1, value);
 			value = chip->pattern_signal_period;
-			max8997_write_reg(chip->client,
+			regmap_write(chip->max8997->regmap_haptic,
 				MAX8997_HAPTIC_REG_SIGCONF2, value);
 			break;
 
 		case 2:
 			value = chip->pattern_cycle << 4;
-			max8997_write_reg(chip->client,
+			regmap_write(chip->max8997->regmap_haptic,
 				MAX8997_HAPTIC_REG_CYCLECONF2, value);
 			value = chip->pattern_signal_period;
-			max8997_write_reg(chip->client,
+			regmap_write(chip->max8997->regmap_haptic,
 				MAX8997_HAPTIC_REG_SIGCONF3, value);
 			break;
 
 		case 3:
 			value = chip->pattern_cycle;
-			max8997_write_reg(chip->client,
+			regmap_write(chip->max8997->regmap_haptic,
 				MAX8997_HAPTIC_REG_CYCLECONF2, value);
 			value = chip->pattern_signal_period;
-			max8997_write_reg(chip->client,
+			regmap_write(chip->max8997->regmap_haptic,
 				MAX8997_HAPTIC_REG_SIGCONF4, value);
 			break;
 
@@ -279,7 +281,7 @@ static int max8997_haptic_probe(struct platform_device *pdev)
 	INIT_WORK(&chip->work, max8997_haptic_play_effect_work);
 	mutex_init(&chip->mutex);
 
-	chip->client = iodev->haptic;
+	chip->max8997 = iodev;
 	chip->dev = &pdev->dev;
 	chip->input_dev = input_dev;
 	chip->pwm_period = haptic_pdata->pwm_period;
diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
index 4edf74f1d6d4..e5f0dc2e9edf 100644
--- a/drivers/leds/leds-max8997.c
+++ b/drivers/leds/leds-max8997.c
@@ -17,6 +17,7 @@
 #include <linux/mfd/max8997.h>
 #include <linux/mfd/max8997-private.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 
 #define MAX8997_LED_FLASH_SHIFT			3
 #define MAX8997_LED_FLASH_CUR_MASK		0xf8
@@ -52,7 +53,6 @@ static void max8997_led_set_mode(struct max8997_led *led,
 			enum max8997_led_mode mode)
 {
 	int ret;
-	struct i2c_client *client = led->iodev->i2c;
 	u8 mask = 0, val;
 
 	switch (mode) {
@@ -88,8 +88,8 @@ static void max8997_led_set_mode(struct max8997_led *led,
 	}
 
 	if (mask) {
-		ret = max8997_update_reg(client, MAX8997_REG_LEN_CNTL, val,
-					 mask);
+		ret = regmap_update_bits(led->iodev->regmap,
+					MAX8997_REG_LEN_CNTL, mask, val);
 		if (ret)
 			dev_err(led->iodev->dev,
 				"failed to update register(%d)\n", ret);
@@ -101,7 +101,6 @@ static void max8997_led_set_mode(struct max8997_led *led,
 static void max8997_led_enable(struct max8997_led *led, bool enable)
 {
 	int ret;
-	struct i2c_client *client = led->iodev->i2c;
 	u8 val = 0, mask = MAX8997_LED_BOOST_ENABLE_MASK;
 
 	if (led->enabled == enable)
@@ -109,7 +108,8 @@ static void max8997_led_enable(struct max8997_led *led, bool enable)
 
 	val = enable ? MAX8997_LED_BOOST_ENABLE_MASK : 0;
 
-	ret = max8997_update_reg(client, MAX8997_REG_BOOST_CNTL, val, mask);
+	ret = regmap_update_bits(led->iodev->regmap,
+				MAX8997_REG_BOOST_CNTL, mask, val);
 	if (ret)
 		dev_err(led->iodev->dev,
 			"failed to update register(%d)\n", ret);
@@ -121,7 +121,6 @@ static void max8997_led_set_current(struct max8997_led *led,
 				enum led_brightness value)
 {
 	int ret;
-	struct i2c_client *client = led->iodev->i2c;
 	u8 val = 0, mask = 0, reg = 0;
 
 	switch (led->led_mode) {
@@ -142,7 +141,7 @@ static void max8997_led_set_current(struct max8997_led *led,
 	}
 
 	if (mask) {
-		ret = max8997_update_reg(client, reg, val, mask);
+		ret = regmap_update_bits(led->iodev->regmap, reg, mask, val);
 		if (ret)
 			dev_err(led->iodev->dev,
 				"failed to update register(%d)\n", ret);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index eea61e349e26..40eae54ba663 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -596,6 +596,7 @@ config MFD_MAX8997
 	bool "Maxim Semiconductor MAX8997/8966 PMIC Support"
 	depends on I2C=y
 	select MFD_CORE
+	select REGMAP_I2C
 	select IRQ_DOMAIN
 	help
 	  Say yes here to add support for Maxim Semiconductor MAX8997/8966.
diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c
index b95a46d79b9d..6ab5f955c510 100644
--- a/drivers/mfd/max8997-irq.c
+++ b/drivers/mfd/max8997-irq.c
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/mfd/max8997.h>
 #include <linux/mfd/max8997-private.h>
+#include <linux/regmap.h>
 
 static const u8 max8997_mask_reg[] = {
 	[PMIC_INT1] = MAX8997_REG_INT1MSK,
@@ -41,25 +42,6 @@ static const u8 max8997_mask_reg[] = {
 	[FLASH_STATUS] = MAX8997_REG_INVALID,
 };
 
-static struct i2c_client *get_i2c(struct max8997_dev *max8997,
-				enum max8997_irq_source src)
-{
-	switch (src) {
-	case PMIC_INT1 ... PMIC_INT4:
-		return max8997->i2c;
-	case FUEL_GAUGE:
-		return NULL;
-	case MUIC_INT1 ... MUIC_INT3:
-		return max8997->muic;
-	case GPIO_LOW ... GPIO_HI:
-		return max8997->i2c;
-	case FLASH_STATUS:
-		return max8997->i2c;
-	default:
-		return ERR_PTR(-EINVAL);
-	}
-}
-
 struct max8997_irq_data {
 	int mask;
 	enum max8997_irq_source group;
@@ -124,15 +106,20 @@ static void max8997_irq_sync_unlock(struct irq_data *data)
 	int i;
 
 	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
+		struct regmap *map;
 		u8 mask_reg = max8997_mask_reg[i];
-		struct i2c_client *i2c = get_i2c(max8997, i);
+
+		if (i >= MUIC_INT1 && i <= MUIC_INT3)
+			map = max8997->regmap_muic;
+		else
+			map = max8997->regmap;
 
 		if (mask_reg == MAX8997_REG_INVALID ||
-				IS_ERR_OR_NULL(i2c))
+				IS_ERR_OR_NULL(map))
 			continue;
 		max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i];
 
-		max8997_write_reg(i2c, max8997_mask_reg[i],
+		regmap_write(map, max8997_mask_reg[i],
 				max8997->irq_masks_cur[i]);
 	}
 
@@ -180,11 +167,11 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
 {
 	struct max8997_dev *max8997 = data;
 	u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {};
-	u8 irq_src;
+	unsigned int irq_src;
 	int ret;
 	int i, cur_irq;
 
-	ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src);
+	ret = regmap_read(max8997->regmap, MAX8997_REG_INTSRC, &irq_src);
 	if (ret < 0) {
 		dev_err(max8997->dev, "Failed to read interrupt source: %d\n",
 				ret);
@@ -193,8 +180,8 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
 
 	if (irq_src & MAX8997_IRQSRC_PMIC) {
 		/* PMIC INT1 ~ INT4 */
-		max8997_bulk_read(max8997->i2c, MAX8997_REG_INT1, 4,
-				&irq_reg[PMIC_INT1]);
+		regmap_bulk_read(max8997->regmap, MAX8997_REG_INT1,
+				&irq_reg[PMIC_INT1], 4);
 	}
 	if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
 		/*
@@ -214,8 +201,8 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
 	}
 	if (irq_src & MAX8997_IRQSRC_MUIC) {
 		/* MUIC INT1 ~ INT3 */
-		max8997_bulk_read(max8997->muic, MAX8997_MUIC_REG_INT1, 3,
-				&irq_reg[MUIC_INT1]);
+		regmap_bulk_read(max8997->regmap_muic, MAX8997_MUIC_REG_INT1,
+				&irq_reg[MUIC_INT1], 3);
 	}
 	if (irq_src & MAX8997_IRQSRC_GPIO) {
 		/* GPIO Interrupt */
@@ -224,8 +211,8 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
 		irq_reg[GPIO_LOW] = 0;
 		irq_reg[GPIO_HI] = 0;
 
-		max8997_bulk_read(max8997->i2c, MAX8997_REG_GPIOCNTL1,
-				MAX8997_NUM_GPIO, gpio_info);
+		regmap_bulk_read(max8997->regmap, MAX8997_REG_GPIOCNTL1,
+				gpio_info, MAX8997_NUM_GPIO);
 		for (i = 0; i < MAX8997_NUM_GPIO; i++) {
 			bool interrupt = false;
 
@@ -259,8 +246,10 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
 	}
 	if (irq_src & MAX8997_IRQSRC_FLASH) {
 		/* Flash Status Interrupt */
-		ret = max8997_read_reg(max8997->i2c, MAX8997_REG_FLASHSTATUS,
-				&irq_reg[FLASH_STATUS]);
+		unsigned int data;
+		ret = regmap_read(max8997->regmap,
+				MAX8997_REG_FLASHSTATUS, &data);
+		irq_reg[FLASH_STATUS] = data;
 	}
 
 	/* Apply masking */
@@ -308,7 +297,7 @@ int max8997_irq_init(struct max8997_dev *max8997)
 	struct irq_domain *domain;
 	int i;
 	int ret;
-	u8 val;
+	unsigned int val;
 
 	if (!max8997->irq) {
 		dev_warn(max8997->dev, "No interrupt specified.\n");
@@ -319,22 +308,19 @@ int max8997_irq_init(struct max8997_dev *max8997)
 
 	/* Mask individual interrupt sources */
 	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
-		struct i2c_client *i2c;
-
 		max8997->irq_masks_cur[i] = 0xff;
 		max8997->irq_masks_cache[i] = 0xff;
-		i2c = get_i2c(max8997, i);
 
-		if (IS_ERR_OR_NULL(i2c))
+		if (IS_ERR_OR_NULL(max8997->regmap))
 			continue;
 		if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
 			continue;
 
-		max8997_write_reg(i2c, max8997_mask_reg[i], 0xff);
+		regmap_write(max8997->regmap, max8997_mask_reg[i], 0xff);
 	}
 
 	for (i = 0; i < MAX8997_NUM_GPIO; i++) {
-		max8997->gpio_status[i] = (max8997_read_reg(max8997->i2c,
+		max8997->gpio_status[i] = (regmap_read(max8997->regmap,
 						MAX8997_REG_GPIOCNTL1 + i,
 						&val)
 					& MAX8997_GPIO_DATA_MASK) ?
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index f316348e3d98..f1c82110b2ab 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -33,6 +33,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/max8997.h>
 #include <linux/mfd/max8997-private.h>
+#include <linux/regmap.h>
 
 #define I2C_ADDR_PMIC	(0xCC >> 1)
 #define I2C_ADDR_MUIC	(0x4A >> 1)
@@ -58,81 +59,29 @@ static const struct of_device_id max8997_pmic_dt_match[] = {
 MODULE_DEVICE_TABLE(of, max8997_pmic_dt_match);
 #endif
 
-int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
-{
-	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
-	int ret;
-
-	mutex_lock(&max8997->iolock);
-	ret = i2c_smbus_read_byte_data(i2c, reg);
-	mutex_unlock(&max8997->iolock);
-	if (ret < 0)
-		return ret;
-
-	ret &= 0xff;
-	*dest = ret;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(max8997_read_reg);
-
-int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
-{
-	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
-	int ret;
-
-	mutex_lock(&max8997->iolock);
-	ret = i2c_smbus_read_i2c_block_data(i2c, reg, count, buf);
-	mutex_unlock(&max8997->iolock);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(max8997_bulk_read);
-
-int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value)
-{
-	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
-	int ret;
-
-	mutex_lock(&max8997->iolock);
-	ret = i2c_smbus_write_byte_data(i2c, reg, value);
-	mutex_unlock(&max8997->iolock);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(max8997_write_reg);
-
-int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
-{
-	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
-	int ret;
+static const struct regmap_config max8997_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = MAX8997_REG_PMIC_END,
+};
 
-	mutex_lock(&max8997->iolock);
-	ret = i2c_smbus_write_i2c_block_data(i2c, reg, count, buf);
-	mutex_unlock(&max8997->iolock);
-	if (ret < 0)
-		return ret;
+static const struct regmap_config max8997_regmap_rtc_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = MAX8997_RTC_REG_END,
+};
 
-	return 0;
-}
-EXPORT_SYMBOL_GPL(max8997_bulk_write);
+static const struct regmap_config max8997_regmap_haptic_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = MAX8997_HAPTIC_REG_END,
+};
 
-int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
-{
-	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
-	int ret;
-
-	mutex_lock(&max8997->iolock);
-	ret = i2c_smbus_read_byte_data(i2c, reg);
-	if (ret >= 0) {
-		u8 old_val = ret & 0xff;
-		u8 new_val = (val & mask) | (old_val & (~mask));
-		ret = i2c_smbus_write_byte_data(i2c, reg, new_val);
-	}
-	mutex_unlock(&max8997->iolock);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(max8997_update_reg);
+static const struct regmap_config max8997_regmap_muic_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = MAX8997_MUIC_REG_END,
+};
 
 /*
  * Only the common platform data elements for max8997 are parsed here from the
@@ -231,6 +180,41 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
 	}
 	i2c_set_clientdata(max8997->muic, max8997);
 
+	max8997->regmap = devm_regmap_init_i2c(i2c, &max8997_regmap_config);
+	if (IS_ERR(max8997->regmap)) {
+		ret = PTR_ERR(max8997->regmap);
+		dev_err(max8997->dev,
+				"failed to allocate register map: %d\n", ret);
+		return ret;
+	}
+
+	max8997->regmap_rtc = devm_regmap_init_i2c(max8997->rtc,
+					&max8997_regmap_rtc_config);
+	if (IS_ERR(max8997->regmap_rtc)) {
+		ret = PTR_ERR(max8997->regmap_rtc);
+		dev_err(max8997->dev,
+				"failed to allocate register map: %d\n", ret);
+		goto err_regmap;
+	}
+
+	max8997->regmap_haptic = devm_regmap_init_i2c(max8997->haptic,
+					&max8997_regmap_haptic_config);
+	if (IS_ERR(max8997->regmap_haptic)) {
+		ret = PTR_ERR(max8997->regmap_haptic);
+		dev_err(max8997->dev,
+				"failed to allocate register map: %d\n", ret);
+		goto err_regmap;
+	}
+
+	max8997->regmap_muic = devm_regmap_init_i2c(max8997->muic,
+					&max8997_regmap_muic_config);
+	if (IS_ERR(max8997->regmap_muic)) {
+		ret = PTR_ERR(max8997->regmap_muic);
+		dev_err(max8997->dev,
+				"failed to allocate register map: %d\n", ret);
+		goto err_regmap;
+	}
+
 	pm_runtime_set_active(max8997->dev);
 
 	max8997_irq_init(max8997);
@@ -255,6 +239,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
 
 err_mfd:
 	mfd_remove_devices(max8997->dev);
+err_regmap:
 	i2c_unregister_device(max8997->muic);
 err_i2c_muic:
 	i2c_unregister_device(max8997->haptic);
@@ -442,15 +427,15 @@ static int max8997_freeze(struct device *dev)
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++)
-		max8997_read_reg(i2c, max8997_dumpaddr_pmic[i],
+		regmap_read(max8997->regmap, max8997_dumpaddr_pmic[i],
 				&max8997->reg_dump[i]);
 
 	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++)
-		max8997_read_reg(i2c, max8997_dumpaddr_muic[i],
+		regmap_read(max8997->regmap_muic, max8997_dumpaddr_muic[i],
 				&max8997->reg_dump[i + MAX8997_REG_PMIC_END]);
 
 	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++)
-		max8997_read_reg(i2c, max8997_dumpaddr_haptic[i],
+		regmap_read(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
 				&max8997->reg_dump[i + MAX8997_REG_PMIC_END +
 				MAX8997_MUIC_REG_END]);
 
@@ -464,15 +449,15 @@ static int max8997_restore(struct device *dev)
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++)
-		max8997_write_reg(i2c, max8997_dumpaddr_pmic[i],
+		regmap_write(max8997->regmap, max8997_dumpaddr_pmic[i],
 				max8997->reg_dump[i]);
 
 	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++)
-		max8997_write_reg(i2c, max8997_dumpaddr_muic[i],
+		regmap_write(max8997->regmap_muic, max8997_dumpaddr_muic[i],
 				max8997->reg_dump[i + MAX8997_REG_PMIC_END]);
 
 	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++)
-		max8997_write_reg(i2c, max8997_dumpaddr_haptic[i],
+		regmap_write(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
 				max8997->reg_dump[i + MAX8997_REG_PMIC_END +
 				MAX8997_MUIC_REG_END]);
 
diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
index 0b2eab571528..a9f5ddcf83a8 100644
--- a/drivers/power/max8997_charger.c
+++ b/drivers/power/max8997_charger.c
@@ -26,6 +26,7 @@
 #include <linux/power_supply.h>
 #include <linux/mfd/max8997.h>
 #include <linux/mfd/max8997-private.h>
+#include <linux/regmap.h>
 
 struct charger_data {
 	struct device *dev;
@@ -45,14 +46,14 @@ static int max8997_battery_get_property(struct power_supply *psy,
 		union power_supply_propval *val)
 {
 	struct charger_data *charger = power_supply_get_drvdata(psy);
-	struct i2c_client *i2c = charger->iodev->i2c;
 	int ret;
-	u8 reg;
+	unsigned int reg;
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_STATUS:
 		val->intval = 0;
-		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
+		ret = regmap_read(charger->iodev->regmap,
+				MAX8997_REG_STATUS4, &reg);
 		if (ret)
 			return ret;
 		if ((reg & (1 << 0)) == 0x1)
@@ -61,7 +62,8 @@ static int max8997_battery_get_property(struct power_supply *psy,
 		break;
 	case POWER_SUPPLY_PROP_PRESENT:
 		val->intval = 0;
-		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
+		ret = regmap_read(charger->iodev->regmap,
+				MAX8997_REG_STATUS4, &reg);
 		if (ret)
 			return ret;
 		if ((reg & (1 << 2)) == 0x0)
@@ -70,7 +72,8 @@ static int max8997_battery_get_property(struct power_supply *psy,
 		break;
 	case POWER_SUPPLY_PROP_ONLINE:
 		val->intval = 0;
-		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
+		ret = regmap_read(charger->iodev->regmap,
+				MAX8997_REG_STATUS4, &reg);
 		if (ret)
 			return ret;
 		/* DCINOK */
@@ -111,8 +114,8 @@ static int max8997_battery_probe(struct platform_device *pdev)
 		if (val > 0xf)
 			val = 0xf;
 
-		ret = max8997_update_reg(iodev->i2c,
-				MAX8997_REG_MBCCTRL5, val, 0xf);
+		ret = regmap_update_bits(iodev->regmap,
+				MAX8997_REG_MBCCTRL5, 0xf, val);
 		if (ret < 0) {
 			dev_err(&pdev->dev, "Cannot use i2c bus.\n");
 			return ret;
@@ -121,20 +124,20 @@ static int max8997_battery_probe(struct platform_device *pdev)
 
 	switch (pdata->timeout) {
 	case 5:
-		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
-				0x2 << 4, 0x7 << 4);
+		ret = regmap_update_bits(iodev->regmap,
+				MAX8997_REG_MBCCTRL1, 0x7 << 4, 0x2 << 4);
 		break;
 	case 6:
-		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
-				0x3 << 4, 0x7 << 4);
+		ret = regmap_update_bits(iodev->regmap,
+				MAX8997_REG_MBCCTRL1, 0x7 << 4, 0x3 << 4);
 		break;
 	case 7:
-		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
-				0x4 << 4, 0x7 << 4);
+		ret = regmap_update_bits(iodev->regmap,
+				MAX8997_REG_MBCCTRL1, 0x7 << 4, 0x4 << 4);
 		break;
 	case 0:
-		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
-				0x7 << 4, 0x7 << 4);
+		ret = regmap_update_bits(iodev->regmap,
+				MAX8997_REG_MBCCTRL1, 0x7 << 4, 0x7 << 4);
 		break;
 	default:
 		dev_err(&pdev->dev, "incorrect timeout value (%d)\n",
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index ea0196d4496b..785f3c1bd0d0 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -33,6 +33,7 @@
 #include <linux/mfd/max8997.h>
 #include <linux/mfd/max8997-private.h>
 #include <linux/regulator/of_regulator.h>
+#include <linux/regmap.h>
 
 struct max8997_data {
 	struct device *dev;
@@ -50,7 +51,7 @@ struct max8997_data {
 	int buck125_gpioindex;
 	bool ignore_gpiodvs_side_effect;
 
-	u8 saved_states[MAX8997_REG_MAX];
+	unsigned int saved_states[MAX8997_REG_MAX];
 };
 
 static const unsigned int safeoutvolt[] = {
@@ -257,15 +258,14 @@ static int max8997_get_enable_register(struct regulator_dev *rdev,
 static int max8997_reg_is_enabled(struct regulator_dev *rdev)
 {
 	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
-	struct i2c_client *i2c = max8997->iodev->i2c;
 	int ret, reg, mask, pattern;
-	u8 val;
+	unsigned int val;
 
 	ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
 	if (ret)
 		return ret;
 
-	ret = max8997_read_reg(i2c, reg, &val);
+	ret = regmap_read(max8997->iodev->regmap, reg, &val);
 	if (ret)
 		return ret;
 
@@ -275,27 +275,25 @@ static int max8997_reg_is_enabled(struct regulator_dev *rdev)
 static int max8997_reg_enable(struct regulator_dev *rdev)
 {
 	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
-	struct i2c_client *i2c = max8997->iodev->i2c;
 	int ret, reg, mask, pattern;
 
 	ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
 	if (ret)
 		return ret;
 
-	return max8997_update_reg(i2c, reg, pattern, mask);
+	return regmap_update_bits(max8997->iodev->regmap, reg, mask, pattern);
 }
 
 static int max8997_reg_disable(struct regulator_dev *rdev)
 {
 	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
-	struct i2c_client *i2c = max8997->iodev->i2c;
 	int ret, reg, mask, pattern;
 
 	ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
 	if (ret)
 		return ret;
 
-	return max8997_update_reg(i2c, reg, ~pattern, mask);
+	return regmap_update_bits(max8997->iodev->regmap, reg, mask, ~pattern);
 }
 
 static int max8997_get_voltage_register(struct regulator_dev *rdev,
@@ -367,15 +365,14 @@ static int max8997_get_voltage_register(struct regulator_dev *rdev,
 static int max8997_get_voltage_sel(struct regulator_dev *rdev)
 {
 	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
-	struct i2c_client *i2c = max8997->iodev->i2c;
 	int reg, shift, mask, ret;
-	u8 val;
+	unsigned int val;
 
 	ret = max8997_get_voltage_register(rdev, &reg, &shift, &mask);
 	if (ret)
 		return ret;
 
-	ret = max8997_read_reg(i2c, reg, &val);
+	ret = regmap_read(max8997->iodev->regmap, reg, &val);
 	if (ret)
 		return ret;
 
@@ -412,7 +409,6 @@ static int max8997_set_voltage_charger_cv(struct regulator_dev *rdev,
 		int min_uV, int max_uV, unsigned *selector)
 {
 	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
-	struct i2c_client *i2c = max8997->iodev->i2c;
 	int rid = rdev_get_id(rdev);
 	int lb, ub;
 	int reg, shift = 0, mask, ret = 0;
@@ -454,7 +450,8 @@ static int max8997_set_voltage_charger_cv(struct regulator_dev *rdev,
 
 	*selector = val;
 
-	ret = max8997_update_reg(i2c, reg, val << shift, mask);
+	ret = regmap_update_bits(max8997->iodev->regmap,
+				reg, mask, val << shift);
 
 	return ret;
 }
@@ -467,7 +464,6 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
 		int min_uV, int max_uV, unsigned *selector)
 {
 	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
-	struct i2c_client *i2c = max8997->iodev->i2c;
 	const struct voltage_map_desc *desc;
 	int rid = rdev_get_id(rdev);
 	int i, reg, shift, mask, ret;
@@ -499,7 +495,8 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
 	if (ret)
 		return ret;
 
-	ret = max8997_update_reg(i2c, reg, i << shift, mask << shift);
+	ret = regmap_update_bits(max8997->iodev->regmap,
+				reg, mask << shift, i << shift);
 	*selector = i;
 
 	return ret;
@@ -709,7 +706,6 @@ static int max8997_set_voltage_safeout_sel(struct regulator_dev *rdev,
 					   unsigned selector)
 {
 	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
-	struct i2c_client *i2c = max8997->iodev->i2c;
 	int rid = rdev_get_id(rdev);
 	int reg, shift = 0, mask, ret;
 
@@ -720,13 +716,13 @@ static int max8997_set_voltage_safeout_sel(struct regulator_dev *rdev,
 	if (ret)
 		return ret;
 
-	return max8997_update_reg(i2c, reg, selector << shift, mask << shift);
+	return regmap_update_bits(max8997->iodev->regmap,
+				reg, mask << shift, selector << shift);
 }
 
 static int max8997_reg_disable_suspend(struct regulator_dev *rdev)
 {
 	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
-	struct i2c_client *i2c = max8997->iodev->i2c;
 	int ret, reg, mask, pattern;
 	int rid = rdev_get_id(rdev);
 
@@ -734,20 +730,22 @@ static int max8997_reg_disable_suspend(struct regulator_dev *rdev)
 	if (ret)
 		return ret;
 
-	max8997_read_reg(i2c, reg, &max8997->saved_states[rid]);
+	regmap_read(max8997->iodev->regmap,
+			reg, &max8997->saved_states[rid]);
 
 	if (rid == MAX8997_LDO1 ||
 			rid == MAX8997_LDO10 ||
 			rid == MAX8997_LDO21) {
 		dev_dbg(&rdev->dev, "Conditional Power-Off for %s\n",
 				rdev->desc->name);
-		return max8997_update_reg(i2c, reg, 0x40, mask);
+		return regmap_update_bits(max8997->iodev->regmap,
+				reg, mask, 0x40);
 	}
 
 	dev_dbg(&rdev->dev, "Full Power-Off for %s (%xh -> %xh)\n",
 			rdev->desc->name, max8997->saved_states[rid] & mask,
 			(~pattern) & mask);
-	return max8997_update_reg(i2c, reg, ~pattern, mask);
+	return regmap_update_bits(max8997->iodev->regmap, reg, mask, ~pattern);
 }
 
 static struct regulator_ops max8997_ldo_ops = {
@@ -1031,7 +1029,6 @@ static int max8997_pmic_probe(struct platform_device *pdev)
 	struct regulator_config config = { };
 	struct regulator_dev *rdev;
 	struct max8997_data *max8997;
-	struct i2c_client *i2c;
 	int i, ret, nr_dvs;
 	u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
 
@@ -1055,7 +1052,6 @@ static int max8997_pmic_probe(struct platform_device *pdev)
 	max8997->iodev = iodev;
 	max8997->num_regulators = pdata->num_regulators;
 	platform_set_drvdata(pdev, max8997);
-	i2c = max8997->iodev->i2c;
 
 	max8997->buck125_gpioindex = pdata->buck125_default_idx;
 	max8997->buck1_gpiodvs = pdata->buck1_gpiodvs;
@@ -1105,25 +1101,25 @@ static int max8997_pmic_probe(struct platform_device *pdev)
 
 	/* For the safety, set max voltage before setting up */
 	for (i = 0; i < 8; i++) {
-		max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
-				max_buck1, 0x3f);
-		max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
-				max_buck2, 0x3f);
-		max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
-				max_buck5, 0x3f);
+		regmap_update_bits(max8997->iodev->regmap,
+				MAX8997_REG_BUCK1DVS1 + i, 0x3f, max_buck1);
+		regmap_update_bits(max8997->iodev->regmap,
+				MAX8997_REG_BUCK2DVS1 + i, 0x3f, max_buck2);
+		regmap_update_bits(max8997->iodev->regmap,
+				MAX8997_REG_BUCK5DVS1 + i, 0x3f, max_buck5);
 	}
 
 	/* Initialize all the DVS related BUCK registers */
 	for (i = 0; i < nr_dvs; i++) {
-		max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
-				max8997->buck1_vol[i],
-				0x3f);
-		max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
-				max8997->buck2_vol[i],
-				0x3f);
-		max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
-				max8997->buck5_vol[i],
-				0x3f);
+		regmap_update_bits(max8997->iodev->regmap,
+				MAX8997_REG_BUCK1DVS1 + i,
+				0x3f, max8997->buck1_vol[i]);
+		regmap_update_bits(max8997->iodev->regmap,
+				MAX8997_REG_BUCK2DVS1 + i,
+				0x3f, max8997->buck2_vol[i]);
+		regmap_update_bits(max8997->iodev->regmap,
+				MAX8997_REG_BUCK5DVS1 + i,
+				0x3f, max8997->buck5_vol[i]);
 	}
 
 	/*
@@ -1167,16 +1163,17 @@ static int max8997_pmic_probe(struct platform_device *pdev)
 	}
 
 	/* DVS-GPIO disabled */
-	max8997_update_reg(i2c, MAX8997_REG_BUCK1CTRL, (pdata->buck1_gpiodvs) ?
-			(1 << 1) : (0 << 1), 1 << 1);
-	max8997_update_reg(i2c, MAX8997_REG_BUCK2CTRL, (pdata->buck2_gpiodvs) ?
-			(1 << 1) : (0 << 1), 1 << 1);
-	max8997_update_reg(i2c, MAX8997_REG_BUCK5CTRL, (pdata->buck5_gpiodvs) ?
-			(1 << 1) : (0 << 1), 1 << 1);
+	regmap_update_bits(max8997->iodev->regmap, MAX8997_REG_BUCK1CTRL,
+			1 << 1, (pdata->buck1_gpiodvs) ? (1 << 1) : (0 << 1));
+	regmap_update_bits(max8997->iodev->regmap, MAX8997_REG_BUCK2CTRL,
+			1 << 1, (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1));
+	regmap_update_bits(max8997->iodev->regmap, MAX8997_REG_BUCK5CTRL,
+			1 << 1, (pdata->buck5_gpiodvs) ? (1 << 1) : (0 << 1));
 
 	/* Misc Settings */
 	max8997->ramp_delay = 10; /* set 10mV/us, which is the default */
-	max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
+	regmap_write(max8997->iodev->regmap,
+			MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
 
 	for (i = 0; i < pdata->num_regulators; i++) {
 		const struct voltage_map_desc *desc;
diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
index db984d4bf952..d017a34a9f70 100644
--- a/drivers/rtc/rtc-max8997.c
+++ b/drivers/rtc/rtc-max8997.c
@@ -22,6 +22,7 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/max8997-private.h>
 #include <linux/irqdomain.h>
+#include <linux/regmap.h>
 
 /* Module parameter for WTSR function control */
 static int wtsr_en = 1;
@@ -70,7 +71,6 @@ enum {
 struct max8997_rtc_info {
 	struct device		*dev;
 	struct max8997_dev	*max8997;
-	struct i2c_client	*rtc;
 	struct rtc_device	*rtc_dev;
 	struct mutex		lock;
 	int virq;
@@ -120,8 +120,8 @@ static inline int max8997_rtc_set_update_reg(struct max8997_rtc_info *info)
 {
 	int ret;
 
-	ret = max8997_write_reg(info->rtc, MAX8997_RTC_UPDATE1,
-						RTC_UDR_MASK);
+	ret = regmap_write(info->max8997->regmap_rtc,
+				MAX8997_RTC_UPDATE1, RTC_UDR_MASK);
 	if (ret < 0)
 		dev_err(info->dev, "%s: fail to write update reg(%d)\n",
 				__func__, ret);
@@ -142,7 +142,8 @@ static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	int ret;
 
 	mutex_lock(&info->lock);
-	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data);
+	ret = regmap_bulk_read(info->max8997->regmap_rtc,
+				MAX8997_RTC_SEC, data, RTC_NR_TIME);
 	mutex_unlock(&info->lock);
 
 	if (ret < 0) {
@@ -168,7 +169,8 @@ static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm)
 
 	mutex_lock(&info->lock);
 
-	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data);
+	ret = regmap_bulk_write(info->max8997->regmap_rtc,
+				MAX8997_RTC_SEC, data, RTC_NR_TIME);
 	if (ret < 0) {
 		dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
 				ret);
@@ -185,13 +187,13 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
 	struct max8997_rtc_info *info = dev_get_drvdata(dev);
 	u8 data[RTC_NR_TIME];
-	u8 val;
+	unsigned int val;
 	int i, ret;
 
 	mutex_lock(&info->lock);
 
-	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
-			data);
+	ret = regmap_bulk_read(info->max8997->regmap_rtc,
+				MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
 	if (ret < 0) {
 		dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
 				__func__, __LINE__, ret);
@@ -209,7 +211,8 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	}
 
 	alrm->pending = 0;
-	ret = max8997_read_reg(info->max8997->i2c, MAX8997_REG_STATUS1, &val);
+	ret = regmap_read(info->max8997->regmap_rtc,
+			       MAX8997_REG_STATUS1, &val);
 	if (ret < 0) {
 		dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n",
 				__func__, __LINE__, ret);
@@ -232,8 +235,8 @@ static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info)
 	if (!mutex_is_locked(&info->lock))
 		dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
 
-	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
-				data);
+	ret = regmap_bulk_read(info->max8997->regmap_rtc,
+				MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
 	if (ret < 0) {
 		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
 				__func__, ret);
@@ -243,8 +246,8 @@ static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info)
 	for (i = 0; i < RTC_NR_TIME; i++)
 		data[i] &= ~ALARM_ENABLE_MASK;
 
-	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
-				 data);
+	ret = regmap_bulk_write(info->max8997->regmap_rtc,
+				 MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
 	if (ret < 0) {
 		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
 				__func__, ret);
@@ -264,8 +267,8 @@ static int max8997_rtc_start_alarm(struct max8997_rtc_info *info)
 	if (!mutex_is_locked(&info->lock))
 		dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
 
-	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
-				data);
+	ret = regmap_bulk_read(info->max8997->regmap_rtc,
+				MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
 	if (ret < 0) {
 		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
 				__func__, ret);
@@ -283,8 +286,8 @@ static int max8997_rtc_start_alarm(struct max8997_rtc_info *info)
 	if (data[RTC_DATE] & 0x1f)
 		data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
 
-	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
-				 data);
+	ret = regmap_bulk_write(info->max8997->regmap_rtc,
+				 MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
 	if (ret < 0) {
 		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
 				__func__, ret);
@@ -315,8 +318,8 @@ static int max8997_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	if (ret < 0)
 		goto out;
 
-	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
-				data);
+	ret = regmap_bulk_write(info->max8997->regmap_rtc,
+				 MAX8997_RTC_ALARM1_SEC, data, RTC_NR_TIME);
 	if (ret < 0) {
 		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
 				__func__, ret);
@@ -387,7 +390,8 @@ static void max8997_rtc_enable_wtsr(struct max8997_rtc_info *info, bool enable)
 	dev_info(info->dev, "%s: %s WTSR\n", __func__,
 			enable ? "enable" : "disable");
 
-	ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask);
+	ret = regmap_update_bits(info->max8997->regmap_rtc,
+				 MAX8997_RTC_WTSR_SMPL, mask, val);
 	if (ret < 0) {
 		dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
 				__func__, ret);
@@ -400,7 +404,7 @@ static void max8997_rtc_enable_wtsr(struct max8997_rtc_info *info, bool enable)
 static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
 {
 	int ret;
-	u8 val, mask;
+	unsigned int val, mask;
 
 	if (!smpl_en)
 		return;
@@ -415,7 +419,8 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
 	dev_info(info->dev, "%s: %s SMPL\n", __func__,
 			enable ? "enable" : "disable");
 
-	ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask);
+	ret = regmap_update_bits(info->max8997->regmap_rtc,
+				 MAX8997_RTC_WTSR_SMPL, mask, val);
 	if (ret < 0) {
 		dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
 				__func__, ret);
@@ -425,7 +430,8 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
 	max8997_rtc_set_update_reg(info);
 
 	val = 0;
-	max8997_read_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, &val);
+	regmap_read(info->max8997->regmap_rtc,
+			 MAX8997_RTC_WTSR_SMPL, &val);
 	pr_info("WTSR_SMPL(0x%02x)\n", val);
 }
 
@@ -440,7 +446,8 @@ static int max8997_rtc_init_reg(struct max8997_rtc_info *info)
 
 	info->rtc_24hr_mode = 1;
 
-	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_CTRLMASK, 2, data);
+	ret = regmap_bulk_write(info->max8997->regmap_rtc,
+				 MAX8997_RTC_CTRLMASK, data, 2);
 	if (ret < 0) {
 		dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
 				__func__, ret);
@@ -465,7 +472,6 @@ static int max8997_rtc_probe(struct platform_device *pdev)
 	mutex_init(&info->lock);
 	info->dev = &pdev->dev;
 	info->max8997 = max8997;
-	info->rtc = max8997->rtc;
 
 	platform_set_drvdata(pdev, info);
 
diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
index 78c76cd4d37b..ea80ef80dbf8 100644
--- a/include/linux/mfd/max8997-private.h
+++ b/include/linux/mfd/max8997-private.h
@@ -309,6 +309,8 @@ enum max8997_rtc_reg {
 	MAX8997_RTC_ALARM2_MONTH	= 0x22,
 	MAX8997_RTC_ALARM2_YEAR		= 0x23,
 	MAX8997_RTC_ALARM2_DAY_OF_MONTH	= 0x24,
+
+	MAX8997_RTC_REG_END		= 0x25,
 };
 
 enum max8997_irq_source {
@@ -390,6 +392,11 @@ struct max8997_dev {
 	unsigned long type;
 	struct platform_device *battery; /* battery control (not fuel gauge) */
 
+	struct regmap *regmap;
+	struct regmap *regmap_rtc;
+	struct regmap *regmap_haptic;
+	struct regmap *regmap_muic;
+
 	int irq;
 	int ono;
 	struct irq_domain *irq_domain;
@@ -398,7 +405,7 @@ struct max8997_dev {
 	int irq_masks_cache[MAX8997_IRQ_GROUP_NR];
 
 	/* For hibernation */
-	u8 reg_dump[MAX8997_REG_PMIC_END + MAX8997_MUIC_REG_END +
+	unsigned int reg_dump[MAX8997_REG_PMIC_END + MAX8997_MUIC_REG_END +
 		MAX8997_HAPTIC_REG_END];
 
 	bool gpio_status[MAX8997_NUM_GPIO];
@@ -413,14 +420,6 @@ extern int max8997_irq_init(struct max8997_dev *max8997);
 extern void max8997_irq_exit(struct max8997_dev *max8997);
 extern int max8997_irq_resume(struct max8997_dev *max8997);
 
-extern int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest);
-extern int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count,
-				u8 *buf);
-extern int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value);
-extern int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count,
-				u8 *buf);
-extern int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask);
-
 #define MAX8997_GPIO_INT_BOTH	(0x3 << 4)
 #define MAX8997_GPIO_INT_RISE	(0x2 << 4)
 #define MAX8997_GPIO_INT_FALL	(0x1 << 4)
-- 
1.9.1



From k.kozlowski at samsung.com  Fri May  6 00:27:16 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 09:27:16 +0200
Subject: [PATCH v6 9/9] ARM: dts: exynos: Add interrupt line to MAX8997 PMIC on
 exynos4210-trats
In-Reply-To: <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462519636-3250-8-git-send-email-k.kozlowski@samsung.com>

From: Marek Szyprowski <m.szyprowski at samsung.com>

MAX8997 PMIC requires interrupt and fails probing without it.

Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
Fixes: d105f0b1215d ("ARM: dts: Add basic dts file for Samsung Trats board")
Cc: <stable at vger.kernel.org>
[k.kozlowski: Write commit message, add CC-stable]
Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm/boot/dts/exynos4210-trats.dts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index fed5847410d3..79d983036560 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -298,6 +298,8 @@
 		compatible = "maxim,max8997-pmic";
 
 		reg = <0x66>;
+		interrupt-parent = <&gpx0>;
+		interrupts = <7 0>;
 
 		max8997,pmic-buck1-uses-gpio-dvs;
 		max8997,pmic-buck2-uses-gpio-dvs;
-- 
1.9.1



From k.kozlowski at samsung.com  Fri May  6 00:27:13 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 09:27:13 +0200
Subject: [PATCH v6 6/9] rtc: max8997: Check for ERRNO of regmap_irq_get_virq()
In-Reply-To: <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462519636-3250-5-git-send-email-k.kozlowski@samsung.com>

The regmap_irq_get_virq() can return zero or negative ERRNO, so it is
insufficient to check only for non-zero value.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/rtc/rtc-max8997.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
index 4998aee0f07f..1a06e17ebe9b 100644
--- a/drivers/rtc/rtc-max8997.c
+++ b/drivers/rtc/rtc-max8997.c
@@ -497,7 +497,7 @@ static int max8997_rtc_probe(struct platform_device *pdev)
 	}
 
 	virq = regmap_irq_get_virq(max8997->irq_data, MAX8997_PMICIRQ_RTCA1);
-	if (!virq) {
+	if (virq <= 0) {
 		dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n");
 		ret = -ENXIO;
 		goto err_out;
-- 
1.9.1



From k.kozlowski at samsung.com  Fri May  6 00:27:15 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 09:27:15 +0200
Subject: [PATCH v6 8/9] ARM: dts: exynos: Fix regulator name to avoid forbidden
 character on exynos4210-trats
In-Reply-To: <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462519636-3250-7-git-send-email-k.kozlowski@samsung.com>

From: Marek Szyprowski <m.szyprowski at samsung.com>

The usage of slash character causes failure when creating regulator
debugfs entry.

Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
[k.kozlowski: Write commit message]
Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm/boot/dts/exynos4210-trats.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index 1df2f0bc1d76..fed5847410d3 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -359,7 +359,7 @@
 			};
 
 			vusbdac_reg: LDO8 {
-			     regulator-name = "VUSB/VDAC_3.3V_C210";
+			     regulator-name = "VUSB+VDAC_3.3V_C210";
 			     regulator-min-microvolt = <3300000>;
 			     regulator-max-microvolt = <3300000>;
 			};
-- 
1.9.1



From joel at jms.id.au  Fri May  6 00:28:06 2016
From: joel at jms.id.au (Joel Stanley)
Date: Fri, 6 May 2016 16:58:06 +0930
Subject: [PATCH v2 09/11] arm/dst: Add Aspeed ast2500 device tree
In-Reply-To: <loom.20160506T005831-472@post.gmane.org>
References: <1461225849-28074-1-git-send-email-joel@jms.id.au>
 <1461225849-28074-10-git-send-email-joel@jms.id.au>
 <loom.20160506T005831-472@post.gmane.org>
Message-ID: <CACPK8Xe2jjTuMeE2kPacFcGjGFkKFSJHwxHMRgrd93G1T+FX7g@mail.gmail.com>

On Fri, May 6, 2016 at 8:41 AM, Xo Wang <xow at google.com> wrote:
> Joel Stanley <joel <at> jms.id.au> writes:
>> +/ {
>> +     model = "AST2500 EVB";
>> +     compatible = "aspeed,ast2500";
>> +
>> +     chosen {
>> +             stdout-path = &uart5;
>> +             bootargs = "console=ttyS4,115200";
>> +     };
>> +
>> +     memory {
>> +             reg = < 0x80000000 0x10000000 >;
>
> The AST2500 EVB has an SK Hynix H5AN4G6NMFR 4Gb part, so this should be
> 0x20000000 for size.

Well caught. I've got a different part on my v1.1 board, but it is also 4Gbit.

>
>> +                     uart1: serial <at> 1e783000 {
>> +                             compatible = "ns16550a";
>> +                             reg = <0x1e783000 0x1000>;
>> +                             reg-shift = <2>;
>> +                             interrupts = <9>;
>> +                             clock-frequency = <1843200>;
>
> The AST2500 datasheet 39.3.1 states the input clock to their 16550 IP is
> 24 MHz. Their u-boot code also has #define CONFIG_SYS_NS16550_CLK
> 24000000. I suspect we hit a path in the serial/8250 driver that doesn't
> change the divisor from what u-boot set, which is why this has worked.

You're correct, we are relying on uboot. There's also a tricky 'div13'
register in the SCU that we are setting in our board file for these
numbers to work out.

In V3 I've added a clk driver to take are of these details.

>
> Thanks for the porting work!

Thanks for the review. Did you manage to get these patches booting on
your board?

Cheers,

Joel


From marc.zyngier at arm.com  Fri May  6 00:32:19 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Fri, 6 May 2016 08:32:19 +0100
Subject: [PATCH v3 0/2] irqchip/mbigen: fix the IO remap problem in mbigen
 driver.
In-Reply-To: <572BEF97.5020003@huawei.com>
References: <1458203641-17172-1-git-send-email-majun258@huawei.com>
 <alpine.DEB.2.11.1603211124450.3978@nanos> <56F0B7C3.8070001@huawei.com>
 <572B5D97.4090004@arm.com> <572BEF97.5020003@huawei.com>
Message-ID: <572C4883.20106@arm.com>

On 06/05/16 02:12, majun (F) wrote:
> Hi Marc:
> 
> ? 2016/5/5 22:49, Marc Zyngier ??:
>> On 22/03/16 03:10, majun (F) wrote:
>>>
>>>
>>> ? 2016/3/21 18:29, Thomas Gleixner ??:
>>>> On Thu, 17 Mar 2016, MaJun wrote:
>>>>> This patch set is used to fix the problem of remap a set of registers
>>>>> repeatedly in current mbigen driver.
>>>>>
>>>>>   irqchip/mbigen:Change the mbigen node definition in dt binding file
>>>>>   irqchip/mbigen:Change the mbigen driver based on the new mbigen node definition
>>>>
>>>> These subject lines are still horrible as they tell nothing about the nature
>>>> of the change. I fixed them up along with the changelogs and applied them to
>>>> irq/urgent. Can you spot the difference?
>>>
>>> Yes, after you changing, the subject and change log clearly show why we need to
>>> do this change.
>>> I have learned a lot from you :)
>>>
>>>>
>>>> While at it. The config switch for this driver is horrible. It's just in the
>>>> middle of the device driver configs. Why is this configurable by the user at
>>>> all? It simply should be selected by arm64 or some subarch configuration
>>>> there. Please clean that up.
>>>>
>>> will do.
>>
>> So what's the status of this? Do you still plan to respin it?
>>
> 
> This patch set had been ACK by Thomas.

Interesting. Somehow, the ARM email server has decided not to deliver
the tip-bot messages, so I didn't see it was already in.

Sorry for the noise.

	M.
-- 
Jazz is not dead. It just smells funny...


From stefan.wahren at i2se.com  Fri May  6 00:40:38 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Fri, 6 May 2016 09:40:38 +0200 (CEST)
Subject: [PATCH 3/4] ARM: mxs: dts: Add Creative X-Fi3 support
In-Reply-To: <1462479971-7891-3-git-send-email-marex@denx.de>
References: <1462479971-7891-1-git-send-email-marex@denx.de>
 <1462479971-7891-3-git-send-email-marex@denx.de>
Message-ID: <977436072.210446.e7eef450-2262-47df-8e8e-6a44da10083c.open-xchange@email.1und1.de>

Hi Marek,

sorry for the reply format.

> Marek Vasut <marex at denx.de> hat am 5. Mai 2016 um 22:26 geschrieben:
> 
> Add support for this small MP3 player based on STMP3780 (rev.4).
> Currently supported is both external microSD and internal SD-NAND
> bridge, PWM and USB gadget.
> 
> Signed-off-by: Marek Vasut <marex at denx.de>
> Cc: Fabio Estevam <fabio.estevam at nxp.com>
> Cc: Shawn Guo <shawnguo at kernel.org>
> ---
>  arch/arm/boot/dts/Makefile | 1 +
>  arch/arm/boot/dts/imx23-xfi3.dts | 190
> +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 191 insertions(+)
>  create mode 100644 arch/arm/boot/dts/imx23-xfi3.dts
> 
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index 8f9f1c2..7a79d37 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -417,6 +417,7 @@ dtb-$(CONFIG_ARCH_MXS) += \
>  imx23-evk.dtb \
>  imx23-olinuxino.dtb \
>  imx23-stmp378x_devb.dtb \
> + imx23-xfi3.dtb \
>  imx28-apf28.dtb \
>  imx28-apf28dev.dtb \
>  imx28-apx4devkit.dtb \
> diff --git a/arch/arm/boot/dts/imx23-xfi3.dts
> b/arch/arm/boot/dts/imx23-xfi3.dts
> new file mode 100644
> index 0000000..d7e7cf5
> --- /dev/null
> +++ b/arch/arm/boot/dts/imx23-xfi3.dts
> @@ -0,0 +1,190 @@
> +/*
> + * Copyright (C) 2013-2016 Marek Vasut <marex at denx.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.
> + *
> + * You should have received a copy of the GNU General Public
> + * License along with this file; if not, write to the Free
> + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> + * MA 02110-1301 USA

AFAIK this address shouldn't be included.

> + *
> + * 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 "imx23.dtsi"
> +
> +/ {
> + model = "Creative ZEN X-Fi3";
> + compatible = "creative,x-fi3", "fsl,imx23";

Is there a pending patch to add "creative" to the vendor-prefixes.txt?

> +
> + memory {
> + reg = ;
> + };
> +
> + apb at 80000000 {
> + apbh at 80000000 {
> + ssp0: ssp at 80010000 {
> + compatible = "fsl,imx23-mmc";
> + pinctrl-names = "default";
> + pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>;
> + bus-width = ;
> + vmmc-supply = <&reg_vddio_sd0>;
> + cd-inverted;
> + status = "okay";
> + };
> +
> + ssp1: ssp at 80034000 {
> + compatible = "fsl,imx23-mmc";
> + pinctrl-names = "default";
> + pinctrl-0 = <&mmc1_4bit_pins_a>;
> + bus-width = ;
> + non-removable;
> + status = "okay";
> + };
> +
> + pinctrl at 80018000 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&hog_pins_a>;
> +
> + hog_pins_a: hog at 0 {
> + reg = ;
> + fsl,pinmux-ids = <
> + MX23_PAD_GPMI_D07__GPIO_0_7
> + >;
> + fsl,drive-strength = ;
> + fsl,voltage = ;
> + fsl,pull-up = ;
> + };
> +
> + key_pins_a: keys at 0 {
> + reg = ;
> + fsl,pinmux-ids = <
> + MX23_PAD_ROTARYA__GPIO_2_7
> + MX23_PAD_ROTARYB__GPIO_2_8
> + >;
> + fsl,drive-strength = ;
> + fsl,voltage = ;
> + fsl,pull-up = ;
> + };
> + };
> + };
> +
> + apbx at 80040000 {
> + i2c: i2c at 80058000 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&i2c_pins_a>;
> + status = "okay";
> + };
> +
> + pwm: pwm at 80064000 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&pwm2_pins_a>;
> + status = "okay";
> + };
> +
> + duart: serial at 80070000 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&duart_pins_a>;
> + status = "okay";
> + };
> +
> + auart1: serial at 8006e000 {
> + pinctrl-names = "default";
> + pinctrl-0 = <&auart1_2pins_a>;
> + status = "okay";
> + };
> +
> + usbphy0: usbphy at 8007c000 {
> + status = "okay";
> + };
> +
> + lradc at 80050000 {
> + status = "okay";
> + };
> + };
> + };
> +
> + ahb at 80080000 {
> + usb0: usb at 80080000 {
> + dr_mode = "peripheral";
> + status = "okay";
> + };
> + };
> +
> + regulators {
> + compatible = "simple-bus";
> +
> + reg_vddio_sd0: vddio-sd0 {
> + compatible = "regulator-fixed";
> + regulator-name = "vddio-sd0";
> + regulator-min-microvolt = ;
> + regulator-max-microvolt = ;
> + gpio = <&gpio0 7 0>;
> + };
> + };
> +
> + backlight {
> + compatible = "pwm-backlight";
> + pwms = <&pwm 2 5000000>;
> + brightness-levels = ;
> + default-brightness-level = ;
> + };
> +
> + gpio_keys {
> + compatible = "gpio-keys";
> + pinctrl-names = "default";
> + pinctrl-0 = <&key_pins_a>;
> + #address-cells = ;
> + #size-cells = ;
> +
> + button at 0 {
> + label = "volume-down";
> + linux,code = ;
> + gpios = <&gpio2 7 0>;
> + debounce-interval = ;
> + };

I think this would introduce new dtc warnings.

Please look at
https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/?id=f2953a461042721e9a2aca58d2b1cfc67c70d371

> +
> + button at 1 {
> + label = "volume-up";
> + linux,code = ;
> + gpios = <&gpio2 8 0>;
> + debounce-interval = ;
> + };
> + };
> +};
> -- 
> 2.7.0
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From j.anaszewski at samsung.com  Fri May  6 01:04:32 2016
From: j.anaszewski at samsung.com (Jacek Anaszewski)
Date: Fri, 06 May 2016 10:04:32 +0200
Subject: [PATCH v6 2/9] mfd: max8997: Use regmap to access registers
In-Reply-To: <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <572C5010.1090102@samsung.com>

Hi Krzysztof,

On 05/06/2016 09:27 AM, Krzysztof Kozlowski wrote:
> From: Robert Baldyga <r.baldyga at samsung.com>
>
> This patch modifies max8997 driver and each associated function driver,
> to use regmap instead of operating directly on i2c bus. It will allow to
> simplify IRQ handling using regmap-irq.
>
> Signed-off-by: Robert Baldyga <r.baldyga at samsung.com>
> Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>
> [For extcon part]
> Acked-by: Chanwoo Choi <cw00.choi at samsung.com>
>
> [For leds part]
> Acked-by: Bryan Wu <cooloney at gmail.com>
>

Since I've replaced Bryan on the position of LED subsystem maintainer
feel free to use my ack:

Acked-by: Jacek Anaszewski <j.anaszewski at samsung.com>

-- 
Best regards,
Jacek Anaszewski


From zhaoshenglong at huawei.com  Fri May  6 01:32:06 2016
From: zhaoshenglong at huawei.com (Shannon Zhao)
Date: Fri, 6 May 2016 16:32:06 +0800
Subject: [PATCH] Xen: EFI: Parse DT parameters for Xen specific UEFI
Message-ID: <1462523526-3172-1-git-send-email-zhaoshenglong@huawei.com>

From: Shannon Zhao <shannon.zhao at linaro.org>

Add a new function to parse DT parameters for Xen specific UEFI just
like the way for normal UEFI. Then it could reuse the existing codes.

If Xen supports EFI, initialize runtime services.

CC: Matt Fleming <matt at codeblueprint.co.uk>
Signed-off-by: Shannon Zhao <shannon.zhao at linaro.org>
---
Drop using of EFI_PARAVIRT. Discussion can be found from [1].
[1] https://lkml.org/lkml/2016/4/29/8
---
 arch/arm/include/asm/efi.h         |  2 +
 arch/arm/xen/enlighten.c           | 16 ++++++++
 arch/arm64/include/asm/efi.h       |  2 +
 drivers/firmware/efi/arm-runtime.c | 70 +++++++++++++++++++++++---------
 drivers/firmware/efi/efi.c         | 81 ++++++++++++++++++++++++++++++--------
 5 files changed, 137 insertions(+), 34 deletions(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index e0eea72..5ba4343 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -52,9 +52,11 @@ static inline void efi_set_pgd(struct mm_struct *mm)
 
 void efi_virtmap_load(void);
 void efi_virtmap_unload(void);
+int xen_arm_enable_runtime_services(void);
 
 #else
 #define efi_init()
+#define xen_arm_enable_runtime_services() (0)
 #endif /* CONFIG_EFI */
 
 /* arch specific definitions used by the stub code */
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 13e3e9f..3362870 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -16,6 +16,7 @@
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
 #include <asm/system_misc.h>
+#include <asm/efi.h>
 #include <linux/interrupt.h>
 #include <linux/irqreturn.h>
 #include <linux/module.h>
@@ -261,6 +262,13 @@ static int __init fdt_find_hyper_node(unsigned long node, const char *uname,
 	    !strncmp(hyper_node.prefix, s, strlen(hyper_node.prefix)))
 		hyper_node.version = s + strlen(hyper_node.prefix);
 
+	if (IS_ENABLED(CONFIG_XEN_EFI)) {
+		/* Check if Xen supports EFI */
+		if ((of_get_flat_dt_subnode_by_name(node, "uefi") > 0) &&
+		    !efi_runtime_disabled())
+			set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+	}
+
 	return 0;
 }
 
@@ -338,6 +346,7 @@ static int __init xen_guest_init(void)
 {
 	struct xen_add_to_physmap xatp;
 	struct shared_info *shared_info_page = NULL;
+	int ret;
 
 	if (!xen_domain())
 		return 0;
@@ -352,6 +361,13 @@ static int __init xen_guest_init(void)
 		return -ENODEV;
 	}
 
+	if (IS_ENABLED(CONFIG_XEN_EFI) && efi_enabled(EFI_BOOT) &&
+	    efi_enabled(EFI_RUNTIME_SERVICES)) {
+		ret = xen_arm_enable_runtime_services();
+		if (ret)
+			return ret;
+	}
+
 	shared_info_page = (struct shared_info *)get_zeroed_page(GFP_KERNEL);
 
 	if (!shared_info_page) {
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 8e88a69..574bee5 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -8,8 +8,10 @@
 
 #ifdef CONFIG_EFI
 extern void efi_init(void);
+int xen_arm_enable_runtime_services(void);
 #else
 #define efi_init()
+#define xen_arm_enable_runtime_services() (0)
 #endif
 
 int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index 6ae21e4..211ec10 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -27,6 +27,7 @@
 #include <asm/mmu.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
+#include <asm/xen/xen-ops.h>
 
 extern u64 efi_system_table;
 
@@ -39,6 +40,33 @@ static struct mm_struct efi_mm = {
 	.mmlist			= LIST_HEAD_INIT(efi_mm.mmlist),
 };
 
+static int __init efi_remap_init(void)
+{
+	u64 mapsize;
+
+	pr_info("Remapping and enabling EFI services.\n");
+
+	mapsize = memmap.map_end - memmap.map;
+	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
+						   mapsize);
+	if (!memmap.map) {
+		pr_err("Failed to remap EFI memory map\n");
+		return -ENOMEM;
+	}
+	memmap.map_end = memmap.map + mapsize;
+	efi.memmap = &memmap;
+
+	efi.systab = (__force void *)ioremap_cache(efi_system_table,
+						   sizeof(efi_system_table_t));
+	if (!efi.systab) {
+		pr_err("Failed to remap EFI System Table\n");
+		return -ENOMEM;
+	}
+	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
+
+	return 0;
+}
+
 static bool __init efi_virtmap_init(void)
 {
 	efi_memory_desc_t *md;
@@ -75,7 +103,7 @@ static bool __init efi_virtmap_init(void)
  */
 static int __init arm_enable_runtime_services(void)
 {
-	u64 mapsize;
+	int ret;
 
 	if (!efi_enabled(EFI_BOOT)) {
 		pr_info("EFI services will not be available.\n");
@@ -87,25 +115,14 @@ static int __init arm_enable_runtime_services(void)
 		return 0;
 	}
 
-	pr_info("Remapping and enabling EFI services.\n");
-
-	mapsize = memmap.map_end - memmap.map;
-	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
-						   mapsize);
-	if (!memmap.map) {
-		pr_err("Failed to remap EFI memory map\n");
-		return -ENOMEM;
+	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
+		pr_info("EFI runtime services access via paravirt.\n");
+		return 0;
 	}
-	memmap.map_end = memmap.map + mapsize;
-	efi.memmap = &memmap;
 
-	efi.systab = (__force void *)ioremap_cache(efi_system_table,
-						   sizeof(efi_system_table_t));
-	if (!efi.systab) {
-		pr_err("Failed to remap EFI System Table\n");
-		return -ENOMEM;
-	}
-	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
+	ret = efi_remap_init();
+	if (ret)
+		return ret;
 
 	if (!efi_virtmap_init()) {
 		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
@@ -122,6 +139,23 @@ static int __init arm_enable_runtime_services(void)
 }
 early_initcall(arm_enable_runtime_services);
 
+int __init xen_arm_enable_runtime_services(void)
+{
+	int ret;
+
+	ret = efi_remap_init();
+	if (ret)
+		return ret;
+
+	if (IS_ENABLED(CONFIG_XEN_EFI)) {
+		/* Set up runtime services function pointers for Xen Dom0 */
+		xen_efi_runtime_setup();
+		efi.runtime_version = efi.systab->hdr.revision;
+	}
+
+	return 0;
+}
+
 void efi_virtmap_load(void)
 {
 	preempt_disable();
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 3a69ed5..f586e1e 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -469,12 +469,14 @@ device_initcall(efi_load_efivars);
 		FIELD_SIZEOF(struct efi_fdt_params, field) \
 	}
 
-static __initdata struct {
+struct params {
 	const char name[32];
 	const char propname[32];
 	int offset;
 	int size;
-} dt_params[] = {
+};
+
+static __initdata struct params fdt_params[] = {
 	UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
 	UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
 	UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
@@ -482,44 +484,91 @@ static __initdata struct {
 	UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
 };
 
+static __initdata struct params xen_fdt_params[] = {
+	UEFI_PARAM("System Table", "xen,uefi-system-table", system_table),
+	UEFI_PARAM("MemMap Address", "xen,uefi-mmap-start", mmap),
+	UEFI_PARAM("MemMap Size", "xen,uefi-mmap-size", mmap_size),
+	UEFI_PARAM("MemMap Desc. Size", "xen,uefi-mmap-desc-size", desc_size),
+	UEFI_PARAM("MemMap Desc. Version", "xen,uefi-mmap-desc-ver", desc_ver)
+};
+
+#define EFI_FDT_PARAMS_SIZE	ARRAY_SIZE(fdt_params)
+
+static __initdata struct {
+	const char *uname;
+	const char *subnode;
+	struct params *params;
+} dt_params[] = {
+	{ "hypervisor", "uefi", xen_fdt_params },
+	{ "chosen", NULL, fdt_params },
+};
+
 struct param_info {
 	int found;
 	void *params;
+	const char *missing;
 };
 
-static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
-				       int depth, void *data)
+static int __init __find_uefi_params(unsigned long node,
+				     struct param_info *info,
+				     struct params *params)
 {
-	struct param_info *info = data;
 	const void *prop;
 	void *dest;
 	u64 val;
 	int i, len;
 
-	if (depth != 1 || strcmp(uname, "chosen") != 0)
-		return 0;
-
-	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
-		prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
-		if (!prop)
+	for (i = 0; i < EFI_FDT_PARAMS_SIZE; i++) {
+		prop = of_get_flat_dt_prop(node, params[i].propname, &len);
+		if (!prop) {
+			info->missing = params[i].name;
 			return 0;
-		dest = info->params + dt_params[i].offset;
+		}
+
+		dest = info->params + params[i].offset;
 		info->found++;
 
 		val = of_read_number(prop, len / sizeof(u32));
 
-		if (dt_params[i].size == sizeof(u32))
+		if (params[i].size == sizeof(u32))
 			*(u32 *)dest = val;
 		else
 			*(u64 *)dest = val;
 
 		if (efi_enabled(EFI_DBG))
-			pr_info("  %s: 0x%0*llx\n", dt_params[i].name,
-				dt_params[i].size * 2, val);
+			pr_info("  %s: 0x%0*llx\n", params[i].name,
+				params[i].size * 2, val);
 	}
+
 	return 1;
 }
 
+static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
+				       int depth, void *data)
+{
+	struct param_info *info = data;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
+		const char *subnode = dt_params[i].subnode;
+
+		if (depth != 1 || strcmp(uname, dt_params[i].uname) != 0) {
+			info->missing = dt_params[i].params[0].name;
+			continue;
+		}
+
+		if (subnode) {
+			node = of_get_flat_dt_subnode_by_name(node, subnode);
+			if (node < 0)
+				return 0;
+		}
+
+		return __find_uefi_params(node, info, dt_params[i].params);
+	}
+
+	return 0;
+}
+
 int __init efi_get_fdt_params(struct efi_fdt_params *params)
 {
 	struct param_info info;
@@ -535,7 +584,7 @@ int __init efi_get_fdt_params(struct efi_fdt_params *params)
 		pr_info("UEFI not found.\n");
 	else if (!ret)
 		pr_err("Can't find '%s' in device tree!\n",
-		       dt_params[info.found].name);
+		       info.missing);
 
 	return ret;
 }
-- 
2.0.4




From j.anaszewski at samsung.com  Fri May  6 02:03:42 2016
From: j.anaszewski at samsung.com (Jacek Anaszewski)
Date: Fri, 06 May 2016 11:03:42 +0200
Subject: [PATCH v3 1/3] leds: triggers: Allow to switch the trigger to
 "panic" on a kernel panic
In-Reply-To: <57230B26.9010300@samsung.com>
References: <1461881020-13964-1-git-send-email-ezequiel@vanguardiasur.com.ar>
 <1461881020-13964-2-git-send-email-ezequiel@vanguardiasur.com.ar>
 <57230B26.9010300@samsung.com>
Message-ID: <572C5DEE.3070307@samsung.com>

On 04/29/2016 09:20 AM, Jacek Anaszewski wrote:
> Hi Ezequiel,
>
> Thanks for the update. It's indeed reasonable to have all the
> switching infrastructure in ledtrig-panic.c.
>
> I've noticed two minor issues below.

Since the merge window is imminent, I've addressed those issues by
myself and applied the patch set to the for-next branch
of linux-leds.git.

Thanks,
Jacek Anaszewski

> On 04/29/2016 12:03 AM, Ezequiel Garcia wrote:
>> This commit adds a new led_cdev flag LED_PANIC_INDICATOR, which
>> allows to mark a specific LED to be switched to the "panic"
>> trigger, on a kernel panic.
>>
>> This is useful to allow the user to assign a regular trigger
>> to a given LED, and still blink that LED on a kernel panic.
>>
>> Signed-off-by: Ezequiel Garcia <ezequiel at vanguardiasur.com.ar>
>> ---
>>   drivers/leds/led-triggers.c          |  2 +-
>>   drivers/leds/leds.h                  |  1 +
>>   drivers/leds/trigger/Kconfig         |  3 +++
>>   drivers/leds/trigger/ledtrig-panic.c | 47
>> ++++++++++++++++++++++++++++++++++++
>>   include/linux/leds.h                 |  1 +
>>   5 files changed, 53 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
>> index 2181581795d3..55fa65e1ae03 100644
>> --- a/drivers/leds/led-triggers.c
>> +++ b/drivers/leds/led-triggers.c
>> @@ -26,7 +26,7 @@
>>    * Nests outside led_cdev->trigger_lock
>>    */
>>   static DECLARE_RWSEM(triggers_list_lock);
>> -static LIST_HEAD(trigger_list);
>> +LIST_HEAD(trigger_list);
>>
>>    /* Used by LED Class */
>>
>> diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
>> index db3f20da7221..7d38e6b9a740 100644
>> --- a/drivers/leds/leds.h
>> +++ b/drivers/leds/leds.h
>> @@ -30,5 +30,6 @@ void led_set_brightness_nosleep(struct led_classdev
>> *led_cdev,
>>
>>   extern struct rw_semaphore leds_list_lock;
>>   extern struct list_head leds_list;
>> +extern struct list_head trigger_list;
>>
>>   #endif    /* __LEDS_H_INCLUDED */
>> diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
>> index beac8c31c51b..4e4521c9072a 100644
>> --- a/drivers/leds/trigger/Kconfig
>> +++ b/drivers/leds/trigger/Kconfig
>> @@ -121,6 +121,9 @@ config LEDS_TRIGGER_PANIC
>>       depends on LEDS_TRIGGERS
>>       help
>>         This allows LEDs to be configured to blink on a kernel panic.
>> +      Enabling this option will allow to mark certain LEDs as
>> 'panic-indicators',
>
> s/"panic-indicators"/panic indicators/
>
> I understand that you referred here to the DT property name, but this
> is not obvious at first glance, and it is an implementation detail.
>
>> +      allowing to blink them on a kernel panic, even if they are set to
>> +      a different trigger.
>>         If unsure, say Y.
>>
>>   endif # LEDS_TRIGGERS
>> diff --git a/drivers/leds/trigger/ b/drivers/leds/trigger/ledtrig-panic.c
>> index 627b350c5ec3..3e447bd2064a 100644
>> --- a/drivers/leds/trigger/ledtrig-panic.c
>> +++ b/drivers/leds/trigger/ledtrig-panic.c
>> @@ -11,10 +11,54 @@
>>
>>   #include <linux/kernel.h>
>>   #include <linux/init.h>
>> +#include <linux/notifier.h>
>>   #include <linux/leds.h>
>> +#include "../leds.h"
>>
>>   static struct led_trigger *trigger;
>>
>> +/*
>> + * This is a called in a special context by the atomic panic
>
> s/is a/is/
>
>> + * notifier. This means the trigger can be changed without
>> + * worrying about locking.
>> + */
>> +static void led_trigger_set_panic(struct led_classdev *led_cdev)
>> +{
>> +    struct led_trigger *trig;
>> +
>> +    list_for_each_entry(trig, &trigger_list, next_trig) {
>> +        if (strcmp("panic", trig->name))
>> +            continue;
>> +        if (led_cdev->trigger)
>> +            list_del(&led_cdev->trig_list);
>> +        list_add_tail(&led_cdev->trig_list, &trig->led_cdevs);
>> +
>> +        /* Avoid the delayed blink path */
>> +        led_cdev->blink_delay_on = 0;
>> +        led_cdev->blink_delay_off = 0;
>> +
>> +        led_cdev->trigger = trig;
>> +        if (trig->activate)
>> +            trig->activate(led_cdev);
>> +        break;
>> +    }
>> +}
>> +
>> +static int led_trigger_panic_notifier(struct notifier_block *nb,
>> +                      unsigned long code, void *unused)
>> +{
>> +    struct led_classdev *led_cdev;
>> +
>> +    list_for_each_entry(led_cdev, &leds_list, node)
>> +        if (led_cdev->flags & LED_PANIC_INDICATOR)
>> +            led_trigger_set_panic(led_cdev);
>> +    return NOTIFY_DONE;
>> +}
>> +
>> +static struct notifier_block led_trigger_panic_nb = {
>> +    .notifier_call = led_trigger_panic_notifier,
>> +};
>> +
>>   static long led_panic_blink(int state)
>>   {
>>       led_trigger_event(trigger, state ? LED_FULL : LED_OFF);
>> @@ -23,6 +67,9 @@ static long led_panic_blink(int state)
>>
>>   static int __init ledtrig_panic_init(void)
>>   {
>> +    atomic_notifier_chain_register(&panic_notifier_list,
>> +                       &led_trigger_panic_nb);
>> +
>>       led_trigger_register_simple("panic", &trigger);
>>       panic_blink = led_panic_blink;
>>       return 0;
>> diff --git a/include/linux/leds.h b/include/linux/leds.h
>> index 19eb10278bea..7e9fb00e15e8 100644
>> --- a/include/linux/leds.h
>> +++ b/include/linux/leds.h
>> @@ -50,6 +50,7 @@ struct led_classdev {
>>   #define LED_SYSFS_DISABLE    (1 << 22)
>>   #define LED_DEV_CAP_FLASH    (1 << 23)
>>   #define LED_HW_PLUGGABLE    (1 << 24)
>> +#define LED_PANIC_INDICATOR    (1 << 25)
>>
>>       /* Set LED brightness level
>>        * Must not sleep. Use brightness_set_blocking for drivers
>>
>


From majun258 at huawei.com  Fri May  6 02:07:16 2016
From: majun258 at huawei.com (majun (F))
Date: Fri, 6 May 2016 17:07:16 +0800
Subject: [PATCH v3 0/2] irqchip/mbigen: fix the IO remap problem in mbigen
 driver.
In-Reply-To: <572C4883.20106@arm.com>
References: <1458203641-17172-1-git-send-email-majun258@huawei.com>
 <alpine.DEB.2.11.1603211124450.3978@nanos> <56F0B7C3.8070001@huawei.com>
 <572B5D97.4090004@arm.com> <572BEF97.5020003@huawei.com>
 <572C4883.20106@arm.com>
Message-ID: <572C5EC4.4010204@huawei.com>

Hi Marc:

? 2016/5/6 15:32, Marc Zyngier ??:
> On 06/05/16 02:12, majun (F) wrote:
>> Hi Marc:
>>
>> ? 2016/5/5 22:49, Marc Zyngier ??:
>>> On 22/03/16 03:10, majun (F) wrote:
>>>>
>>>>
>>>> ? 2016/3/21 18:29, Thomas Gleixner ??:
>>>>> On Thu, 17 Mar 2016, MaJun wrote:
>>>>>> This patch set is used to fix the problem of remap a set of registers
>>>>>> repeatedly in current mbigen driver.
>>>>>>
>>>>>>   irqchip/mbigen:Change the mbigen node definition in dt binding file
>>>>>>   irqchip/mbigen:Change the mbigen driver based on the new mbigen node definition
>>>>>
>>>>> These subject lines are still horrible as they tell nothing about the nature
>>>>> of the change. I fixed them up along with the changelogs and applied them to
>>>>> irq/urgent. Can you spot the difference?
>>>>
>>>> Yes, after you changing, the subject and change log clearly show why we need to
>>>> do this change.
>>>> I have learned a lot from you :)
>>>>
>>>>>
>>>>> While at it. The config switch for this driver is horrible. It's just in the
>>>>> middle of the device driver configs. Why is this configurable by the user at
>>>>> all? It simply should be selected by arm64 or some subarch configuration
>>>>> there. Please clean that up.
>>>>>
>>>> will do.
>>>
>>> So what's the status of this? Do you still plan to respin it?
>>>
>>
>> This patch set had been ACK by Thomas.
> 
> Interesting. Somehow, the ARM email server has decided not to deliver
> the tip-bot messages, so I didn't see it was already in.
> 
> Sorry for the noise.

Not at all. Thank you for your attention.
MaJun
Thanks!
> 
> 	M.
> 



From david.wu at rock-chips.com  Fri May  6 02:32:37 2016
From: david.wu at rock-chips.com (David.Wu)
Date: Fri, 6 May 2016 17:32:37 +0800
Subject: [PATCH v7 8/9] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <CAD=FV=VhMJiowNWm+0=jzzK0vajg1=3PutaWbzhGPN_BU2+19w@mail.gmail.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462372609-6535-1-git-send-email-david.wu@rock-chips.com>
 <CAD=FV=VhMJiowNWm+0=jzzK0vajg1=3PutaWbzhGPN_BU2+19w@mail.gmail.com>
Message-ID: <572C64B5.6080607@rock-chips.com>

Hi Doug,

? 2016/5/6 7:00, Doug Anderson ??:
> David,
>
> On Wed, May 4, 2016 at 7:36 AM, David Wu <david.wu at rock-chips.com> wrote:
>> +/**
>> + * Calculate timing values for desired SCL frequency
>> + *
>> + * @clk_rate: I2C input clock rate
>> + * @t: Known I2C timing information
>> + * @t_calc: Caculated rk3x private timings that would be written into regs
>> +
>> + * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
>> + * a best-effort divider value is returned in divs. If the target rate is
>> + * too high, we silently use the highest possible rate.
>> + * The following formulas are v1's method to calculate timings.
>> + *
>> + * l = divl + 1;
>> + * h = divh + 1;
>> + * s = sda_update_config + 1;
>> + * u = start_setup_config + 1;
>> + * p = stop_setup_config + 1;
>> + * T = Tclk_i2c;
>> +
>> + * tHigh = 8 * h * T;
>> + * tLow = 8 * l * T;
>> +
>> + * tHD;sda = (l * s + 1) * T;
>> + * tSU;sda = [(8 - s) * l + 1] * T;
>> + * tI2C = 8 * (l + h) * T;
>> +
>> + * tSU;sta = (8h * u + 1) * T;
>> + * tHD;sta = [8h * (u + 1) - 1] * T;
>> + * tSU;sto = (8h * p + 1) * T;
>> + */
>> +static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
>> +                                   struct i2c_timings *t,
>> +                                   struct rk3x_i2c_calced_timings *t_calc)
>> +{
>
> I don't think I'm going to try to understand all the math here.  I'll
> trust you that this does something sane.
>
>
>> +       /* Final divh and divl must be greater than 0, otherwise the
>> +        * hardware would not output the i2c clk.
>> +        */
>
> nit: multiline comment style doesn't match rest of file.
>
>
>>   static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
>>   {
>>          struct i2c_timings *t = &i2c->t;
>> -       struct rk3x_i2c_calced_timings calc;
>> +       struct rk3x_i2c_calced_timings *calc = &i2c->t_calc;
>>          u64 t_low_ns, t_high_ns;
>>          int ret;
>>
>> -       ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
>> +       ret = i2c->soc_data->calc_timings(clk_rate, t, calc);
>>          WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
>>
>> -       clk_enable(i2c->clk);
>> -       i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
>> +       if (i2c->pclk)
>> +               clk_enable(i2c->pclk);
>> +       else
>> +               clk_enable(i2c->clk);
>> +       i2c_writel(i2c, (calc->div_high << 16) | (calc->div_low & 0xffff),
>>                     REG_CLKDIV);
>
> There is a subtle bug here, though it likely doesn't manifest in any
> current hardware configurations.
>
> Specifically if you get a clock change on a device with a "v1"
> controller while an i2c transaction is happening then you will likely
> get i2c errors.
>
> The clock change notifications work like this:
> * Before the clock change, adjust the timings based on the faster of
> the old/new clock.
> * Let the clock change happen.
> * If we didn't adjust the timings before, adjust them now.
>
> With the logic above there will be a period where the i2c transaction
> is happening slower than ideal, but that should be OK.  ...and you can
> imagine the speed of the transaction changing midway through the
> transaction--even midway through a single byte.
>
>
> With v1 some of the timing information is _not_updated by
> rk3x_i2c_adapt_div()--it's only set at the start of a transaction.
> That breaks all the above assumptions.
>
> So you should probably be updating the the RKI2C_CON register here by
> doing a read-modify-write, like:
>
> ctrl = i2c_readl(i2c, REG_CON);
> ctrl &= ~REG_CON_TUNING_MASK;
> ctrl |= i2c->t_calc.tuning;
> i2c_writel(i2c, ctrl, REG_CON);
>
>

Yeap, it seems it is a bug when a clock changes, but not update the 
regs, it might make transfer failed. It was not enough to just store 
tuning value.

> Also (optional): once you do that, there becomes much less of a reason
> to store "t_calc" in "struct rk3x_i2c".  Already you're never using
> the "div_low" and "div_high" that you store in the "struct rk3x_i2c".
> Of course, to do that you've got to change other places not to clobber
> these bits in REG_CON.
>

So, I only just need to store tuning value in the "struct rk3x_i2c", but 
not to store the "div_low" and "div_high"?
>
>> @@ -728,11 +910,11 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
>>   {
>>          struct clk_notifier_data *ndata = data;
>>          struct rk3x_i2c *i2c = container_of(nb, struct rk3x_i2c, clk_rate_nb);
>> -       struct rk3x_i2c_calced_timings calc;
>>
>>          switch (event) {
>>          case PRE_RATE_CHANGE:
>> -               if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &calc) != 0)
>> +               if (i2c->soc_data->calc_timings(ndata->new_rate, &i2c->t,
>> +                                               &i2c->t_calc) != 0)
>
> This change is incorrect.  Please change it back to being calculated
> in a local variable.  Optionally also add a comment that says:
>
> /*
>   * Try the calculation (but don't store the result) ahead of
>   * time to see if we need to block the clock change.  Timings
>   * shouldn't actually take effect until rk3x_i2c_adapt_div().
>   */
>
> Specifically in the case that we return NOTIFY_STOP here we _don't_
> want to have modified our internal timings.  We also _don't_ want to
> have modified our internal timings in the case that the old_rate > the
> new_rate.

Okay, use &i2c->t_calc is an error here, timings shouldn't actually take 
effect until rk3x_i2c_adapt_div().

>
> BTW: Did you manage to find anyone using an old Rockchip SoC that can
> test your patches?
>

The patches we have already used in our projects, they are verified by 
the basic tests. I would ask them to do more tests. Because we didn't 
change the clock rate now, it was a fixed value when clk inited, so we 
could not find the bug here.

>
>> @@ -1042,17 +1236,38 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
>>
>>          platform_set_drvdata(pdev, i2c);
>>
>> +       i2c->clk = devm_clk_get(&pdev->dev, NULL);
>> +       if (IS_ERR(i2c->clk)) {
>> +               dev_err(&pdev->dev, "cannot get clock\n");
>> +               return PTR_ERR(i2c->clk);
>> +       }
>> +
>>          ret = clk_prepare(i2c->clk);
>>          if (ret < 0) {
>>                  dev_err(&pdev->dev, "Could not prepare clock\n");
>>                  return ret;
>>          }
>>
>> +       if (i2c->soc_data->calc_timings == rk3x_i2c_v1_calc_timings) {
>> +               i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
>> +               if (IS_ERR(i2c->pclk)) {
>> +                       dev_err(i2c->dev, "Could not get i2c pclk\n");
>> +                       ret = PTR_ERR(i2c->pclk);
>> +                       goto err_clk;
>> +               }
>> +
>> +               ret = clk_prepare(i2c->pclk);
>> +               if (ret) {
>> +                       dev_err(i2c->dev, "Could not prepare pclk\n");
>> +                       goto err_clk;
>> +               }
>> +       }
>
> This is not matching the bindings.  You are still assuming that "i2c"
> clock is the first clock and "pclk" is the one named "pclk".  Said
> another way, if you had the following in your device tree:
>
>    clocks =  <&pmucru PCLK_I2C0_PMU>, <&pmucru SCLK_I2C0_PMU>;
>    clock-names = "pclk", "i2c";
>
> ...you'll find that you'll get back "pclk" twice.  The first time
> you'll get it because you asked for the first clock listed, the second
> time because you asked for the clock named "pclk".
>
> I'd also say that your life will probably be easier if you always
> setup both "clk" and "pclk", even on old CPUs.  It's OK to call
> "clk_prepare" twice and OK to call "clk_enable" twice.
>
> Thus, I'd probably write all the code as this (untested):
>
>    if (i2c->soc_data->calc_timings == rk3x_i2c_v0_calc_timings) {
>      /* Only one clock to use for bus clock and peripheral clock */
>      i2c->clk = devm_clk_get(&pdev->dev, NULL);
>      i2c->pclk = i2c->clk;
>    } else {
>      i2c->clk = devm_clk_get(&pdev->dev, "i2c");
>      i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
>    }
>    if (IS_ERR(i2c->clk)) {
>      ret = PTR_ERR(i2c->clk);
>      if (ret != -EPROBE_DEFER)
>        dev_err(&pdev->dev, "Can't get bus clk: %d\n", ret);
>      return ret;
>    }
>    if (IS_ERR(i2c->pclk)) {
>      ret = PTR_ERR(i2c->pclk);
>      if (ret != -EPROBE_DEFER)
>        dev_err(&pdev->dev, "Can't get periph clk: %d\n", ret);
>      return ret;
>    }
>    ret = clk_prepare(i2c->clk);
>    if (ret < 0) {
>      dev_err(&pdev->dev, "Can't prepare bus clk: %d\n", ret);
>      return ret;
>    }
>    ret = clk_prepare(i2c->pclk);
>    if (ret < 0) {
>      dev_err(&pdev->dev, "Can't prepare periph clock: %d\n", ret);
>      goto err_clk;
>    }
>
> If you take that advice, you can get rid of all of the "if
> (i2c->pclk)" statements in your code.
>

It would make i2c->clk to be enabled and prepared twice when uses 
rk3x_i2c_v0_calc_timings for old hardware. But if do the opposite
disabled and unprepated twice, that is okay.

>
> -Doug
>
>
>



From zengzhaoxiu at 163.com  Fri May  6 02:42:42 2016
From: zengzhaoxiu at 163.com (zengzhaoxiu at 163.com)
Date: Fri,  6 May 2016 17:42:42 +0800
Subject: [patch V4] lib: GCD: Use binary GCD algorithm instead of Euclidean
Message-ID: <1462527763-15301-1-git-send-email-zengzhaoxiu@163.com>

From: Zhaoxiu Zeng <zhaoxiu.zeng at gmail.com>

The binary GCD algorithm is based on the following facts:
	1. If a and b are all evens, then gcd(a,b) = 2 * gcd(a/2, b/2)
	2. If a is even and b is odd, then gcd(a,b) = gcd(a/2, b)
	3. If a and b are all odds, then gcd(a,b) = gcd((a-b)/2, b) = gcd((a+b)/2, b)

Even on x86 machines with reasonable division hardware, the binary
algorithm runs about 25% faster (80% the execution time) than the
division-based Euclidian algorithm.

On platforms like Alpha and ARMv6 where division is a function call to
emulation code, it's even more significant.

There are two variants of the code here, depending on whether a
fast __ffs (find least significant set bit) instruction is available.
This allows the unpredictable branches in the bit-at-a-time shifting
loop to be eliminated.

If fast __ffs is not available, the "even/odd" GCD variant is used.

I use the following code to benchmark:

	#include <stdio.h>
	#include <stdlib.h>
	#include <stdint.h>
	#include <string.h>
	#include <time.h>
	#include <unistd.h>

	#define swap(a, b) \
		do { \
			a ^= b; \
			b ^= a; \
			a ^= b; \
		} while (0)

	unsigned long gcd0(unsigned long a, unsigned long b)
	{
		unsigned long r;

		if (a < b) {
			swap(a, b);
		}

		if (b == 0)
			return a;

		while ((r = a % b) != 0) {
			a = b;
			b = r;
		}

		return b;
	}

	unsigned long gcd1(unsigned long a, unsigned long b)
	{
		unsigned long r = a | b;

		if (!a || !b)
			return r;

		b >>= __builtin_ctzl(b);

		for (;;) {
			a >>= __builtin_ctzl(a);
			if (a == b)
				return a << __builtin_ctzl(r);

			if (a < b)
				swap(a, b);
			a -= b;
		}
	}

	unsigned long gcd2(unsigned long a, unsigned long b)
	{
		unsigned long r = a | b;

		if (!a || !b)
			return r;

		r &= -r;

		while (!(b & r))
			b >>= 1;

		for (;;) {
			while (!(a & r))
				a >>= 1;
			if (a == b)
				return a;

			if (a < b)
				swap(a, b);
			a -= b;
			a >>= 1;
			if (a & r)
				a += b;
			a >>= 1;
		}
	}

	unsigned long gcd3(unsigned long a, unsigned long b)
	{
		unsigned long r = a | b;

		if (!a || !b)
			return r;

		b >>= __builtin_ctzl(b);
		if (b == 1)
			return r & -r;

		for (;;) {
			a >>= __builtin_ctzl(a);
			if (a == 1)
				return r & -r;
			if (a == b)
				return a << __builtin_ctzl(r);

			if (a < b)
				swap(a, b);
			a -= b;
		}
	}

	unsigned long gcd4(unsigned long a, unsigned long b)
	{
		unsigned long r = a | b;

		if (!a || !b)
			return r;

		r &= -r;

		while (!(b & r))
			b >>= 1;
		if (b == r)
			return r;

		for (;;) {
			while (!(a & r))
				a >>= 1;
			if (a == r)
				return r;
			if (a == b)
				return a;

			if (a < b)
				swap(a, b);
			a -= b;
			a >>= 1;
			if (a & r)
				a += b;
			a >>= 1;
		}
	}

	static unsigned long (*gcd_func[])(unsigned long a, unsigned long b) = {
		gcd0, gcd1, gcd2, gcd3, gcd4,
	};

	#define TEST_ENTRIES (sizeof(gcd_func) / sizeof(gcd_func[0]))

	#if defined(__x86_64__)

	#define rdtscll(val) do { \
		unsigned long __a,__d; \
		__asm__ __volatile__("rdtsc" : "=a" (__a), "=d" (__d)); \
		(val) = ((unsigned long long)__a) | (((unsigned long long)__d)<<32); \
	} while(0)

	static unsigned long long benchmark_gcd_func(unsigned long (*gcd)(unsigned long, unsigned long),
								unsigned long a, unsigned long b, unsigned long *res)
	{
		unsigned long long start, end;
		unsigned long long ret;
		unsigned long gcd_res;

		rdtscll(start);
		gcd_res = gcd(a, b);
		rdtscll(end);

		if (end >= start)
			ret = end - start;
		else
			ret = ~0ULL - start + 1 + end;

		*res = gcd_res;
		return ret;
	}

	#else

	static inline struct timespec read_time(void)
	{
		struct timespec time;
		clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);
		return time;
	}

	static inline unsigned long long diff_time(struct timespec start, struct timespec end)
	{
		struct timespec temp;

		if ((end.tv_nsec - start.tv_nsec) < 0) {
			temp.tv_sec = end.tv_sec - start.tv_sec - 1;
			temp.tv_nsec = 1000000000ULL + end.tv_nsec - start.tv_nsec;
		} else {
			temp.tv_sec = end.tv_sec - start.tv_sec;
			temp.tv_nsec = end.tv_nsec - start.tv_nsec;
		}

		return temp.tv_sec * 1000000000ULL + temp.tv_nsec;
	}

	static unsigned long long benchmark_gcd_func(unsigned long (*gcd)(unsigned long, unsigned long),
								unsigned long a, unsigned long b, unsigned long *res)
	{
		struct timespec start, end;
		unsigned long gcd_res;

		start = read_time();
		gcd_res = gcd(a, b);
		end = read_time();

		*res = gcd_res;
		return diff_time(start, end);
	}

	#endif

	static inline unsigned long get_rand()
	{
		if (sizeof(long) == 8)
			return (unsigned long)rand() << 32 | rand();
		else
			return rand();
	}

	int main(int argc, char **argv)
	{
		unsigned int seed = time(0);
		int loops = 100;
		int repeats = 1000;
		unsigned long (*res)[TEST_ENTRIES];
		unsigned long long elapsed[TEST_ENTRIES];
		int i, j, k;

		for (;;) {
			int opt = getopt(argc, argv, "n:r:s:");
			/* End condition always first */
			if (opt == -1)
				break;

			switch (opt) {
			case 'n':
				loops = atoi(optarg);
				break;
			case 'r':
				repeats = atoi(optarg);
				break;
			case 's':
				seed = strtoul(optarg, NULL, 10);
				break;
			default:
				/* You won't actually get here. */
				break;
			}
		}

		res = malloc(sizeof(unsigned long) * TEST_ENTRIES * loops);
		memset(elapsed, 0, sizeof(elapsed));

		srand(seed);
		for (j = 0; j < loops; j++) {
			unsigned long a = get_rand();
			/* Do we have args? */
			unsigned long b = argc > optind ? strtoul(argv[optind], NULL, 10) : get_rand();
			unsigned long long min_elapsed[TEST_ENTRIES];
			for (k = 0; k < repeats; k++) {
				for (i = 0; i < TEST_ENTRIES; i++) {
					unsigned long long tmp = benchmark_gcd_func(gcd_func[i], a, b, &res[j][i]);
					if (k == 0 || min_elapsed[i] > tmp)
						min_elapsed[i] = tmp;
				}
			}
			for (i = 0; i < TEST_ENTRIES; i++)
				elapsed[i] += min_elapsed[i];
		}

		for (i = 0; i < TEST_ENTRIES; i++)
			printf("gcd%d: elapsed %llu\n", i, elapsed[i]);

		k = 0;
		srand(seed);
		for (j = 0; j < loops; j++) {
			unsigned long a = get_rand();
			unsigned long b = argc > optind ? strtoul(argv[optind], NULL, 10) : get_rand();
			for (i = 1; i < TEST_ENTRIES; i++) {
				if (res[j][i] != res[j][0])
					break;
			}
			if (i < TEST_ENTRIES) {
				if (k == 0) {
					k = 1;
					fprintf(stderr, "Error:\n");
				}
				fprintf(stderr, "gcd(%lu, %lu): ", a, b);
				for (i = 0; i < TEST_ENTRIES; i++)
					fprintf(stderr, "%ld%s", res[j][i], i < TEST_ENTRIES - 1 ? ", " : "\n");
			}
		}

		if (k == 0)
			fprintf(stderr, "PASS\n");

		free(res);

		return 0;
	}

Compiled with "-O2", on "VirtualBox 4.4.0-22-generic #38-Ubuntu x86_64" got:

zhaoxiuzeng at zhaoxiuzeng-VirtualBox:~/develop$ ./gcd -r 500000 -n 10
gcd0: elapsed 10174
gcd1: elapsed 2120
gcd2: elapsed 2902
gcd3: elapsed 2039
gcd4: elapsed 2812
PASS
zhaoxiuzeng at zhaoxiuzeng-VirtualBox:~/develop$ ./gcd -r 500000 -n 10
gcd0: elapsed 9309
gcd1: elapsed 2280
gcd2: elapsed 2822
gcd3: elapsed 2217
gcd4: elapsed 2710
PASS
zhaoxiuzeng at zhaoxiuzeng-VirtualBox:~/develop$ ./gcd -r 500000 -n 10
gcd0: elapsed 9589
gcd1: elapsed 2098
gcd2: elapsed 2815
gcd3: elapsed 2030
gcd4: elapsed 2718
PASS
zhaoxiuzeng at zhaoxiuzeng-VirtualBox:~/develop$ ./gcd -r 500000 -n 10
gcd0: elapsed 9914
gcd1: elapsed 2309
gcd2: elapsed 2779
gcd3: elapsed 2228
gcd4: elapsed 2709
PASS

Changes to V3:
- Fix build error
- Select CPU_NO_EFFICIENT_FFS if CONFIG_ARC && CONFIG_ISA_ARCOMPACT
- Select CPU_NO_EFFICIENT_FFS if CONFIG_S390 && !CONFIG_HAVE_MARCH_Z9_109_FEATURES
- Do new brnchmark
- Return immediately if one number becomes a power of 2
- Add comments written by George Spelvin

Changes to V2:
- Add a new Kconfig variable CPU_NO_EFFICIENT_FFS
- Separate into two versions by CPU_NO_EFFICIENT_FFS
- Return directly from the loop, rather than using break().
- Use "r &= -r" mostly because it's clearer.

Changes to V1:
- Don't touch Kconfig, remove the Euclidean algorithm implementation
- Don't use the "even-odd" variant
- Use __ffs if the CPU has efficient __ffs

Signed-off-by: Zhaoxiu Zeng <zhaoxiu.zeng at gmail.com>
Signed-off-by: George Spelvin <linux at horizon.com>
---
 arch/Kconfig                         |  3 ++
 arch/alpha/Kconfig                   |  1 +
 arch/arc/Kconfig                     |  1 +
 arch/arm/mm/Kconfig                  |  3 ++
 arch/h8300/Kconfig                   |  1 +
 arch/m32r/Kconfig                    |  1 +
 arch/m68k/Kconfig.cpu                | 11 ++++++
 arch/metag/Kconfig                   |  1 +
 arch/microblaze/Kconfig              |  1 +
 arch/mips/include/asm/cpu-features.h | 10 +++++
 arch/nios2/Kconfig                   |  1 +
 arch/openrisc/Kconfig                |  1 +
 arch/parisc/Kconfig                  |  1 +
 arch/s390/Kconfig                    |  2 +-
 arch/score/Kconfig                   |  1 +
 arch/sh/Kconfig                      |  1 +
 arch/sparc/Kconfig                   |  1 +
 lib/gcd.c                            | 77 +++++++++++++++++++++++++++++++-----
 18 files changed, 107 insertions(+), 11 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 81869a5..275f17d 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -638,4 +638,7 @@ config COMPAT_OLD_SIGACTION
 config ARCH_NO_COHERENT_DMA_MMAP
 	bool
 
+config CPU_NO_EFFICIENT_FFS
+	def_bool n
+
 source "kernel/gcov/Kconfig"
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 9d8a858..44e6f05 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -27,6 +27,7 @@ config ALPHA
 	select MODULES_USE_ELF_RELA
 	select ODD_RT_SIGACTION
 	select OLD_SIGSUSPEND
+	select CPU_NO_EFFICIENT_FFS if !ALPHA_EV67
 	help
 	  The Alpha is a 64-bit general-purpose processor designed and
 	  marketed by the Digital Equipment Corporation of blessed memory,
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index ec4791e..f41eb4c 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -101,6 +101,7 @@ choice
 
 config ISA_ARCOMPACT
 	bool "ARCompact ISA"
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  The original ARC ISA of ARC600/700 cores
 
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 5534766..cb569b6 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -421,18 +421,21 @@ config CPU_32v3
 	select CPU_USE_DOMAINS if MMU
 	select NEED_KUSER_HELPERS
 	select TLS_REG_EMUL if SMP || !MMU
+	select CPU_NO_EFFICIENT_FFS
 
 config CPU_32v4
 	bool
 	select CPU_USE_DOMAINS if MMU
 	select NEED_KUSER_HELPERS
 	select TLS_REG_EMUL if SMP || !MMU
+	select CPU_NO_EFFICIENT_FFS
 
 config CPU_32v4T
 	bool
 	select CPU_USE_DOMAINS if MMU
 	select NEED_KUSER_HELPERS
 	select TLS_REG_EMUL if SMP || !MMU
+	select CPU_NO_EFFICIENT_FFS
 
 config CPU_32v5
 	bool
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 986ea84..aa232de 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -20,6 +20,7 @@ config H8300
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_LZO
 	select HAVE_ARCH_KGDB
+	select CPU_NO_EFFICIENT_FFS
 
 config RWSEM_GENERIC_SPINLOCK
 	def_bool y
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index c82b292..3cc8498 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -17,6 +17,7 @@ config M32R
 	select ARCH_USES_GETTIMEOFFSET
 	select MODULES_USE_ELF_RELA
 	select HAVE_DEBUG_STACKOVERFLOW
+	select CPU_NO_EFFICIENT_FFS
 
 config SBUS
 	bool
diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu
index 0dfcf12..0b6efe8 100644
--- a/arch/m68k/Kconfig.cpu
+++ b/arch/m68k/Kconfig.cpu
@@ -40,6 +40,7 @@ config M68000
 	select CPU_HAS_NO_MULDIV64
 	select CPU_HAS_NO_UNALIGNED
 	select GENERIC_CSUM
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  The Freescale (was Motorola) 68000 CPU is the first generation of
 	  the well known M68K family of processors. The CPU core as well as
@@ -51,6 +52,7 @@ config MCPU32
 	bool
 	select CPU_HAS_NO_BITFIELDS
 	select CPU_HAS_NO_UNALIGNED
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  The Freescale (was then Motorola) CPU32 is a CPU core that is
 	  based on the 68020 processor. For the most part it is used in
@@ -130,6 +132,7 @@ config M5206
 	depends on !MMU
 	select COLDFIRE_SW_A7
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Motorola ColdFire 5206 processor support.
 
@@ -138,6 +141,7 @@ config M5206e
 	depends on !MMU
 	select COLDFIRE_SW_A7
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Motorola ColdFire 5206e processor support.
 
@@ -163,6 +167,7 @@ config M5249
 	depends on !MMU
 	select COLDFIRE_SW_A7
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Motorola ColdFire 5249 processor support.
 
@@ -171,6 +176,7 @@ config M525x
 	depends on !MMU
 	select COLDFIRE_SW_A7
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Freescale (Motorola) Coldfire 5251/5253 processor support.
 
@@ -189,6 +195,7 @@ config M5272
 	depends on !MMU
 	select COLDFIRE_SW_A7
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Motorola ColdFire 5272 processor support.
 
@@ -217,6 +224,7 @@ config M5307
 	select COLDFIRE_SW_A7
 	select HAVE_CACHE_CB
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Motorola ColdFire 5307 processor support.
 
@@ -242,6 +250,7 @@ config M5407
 	select COLDFIRE_SW_A7
 	select HAVE_CACHE_CB
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Motorola ColdFire 5407 processor support.
 
@@ -251,6 +260,7 @@ config M547x
 	select MMU_COLDFIRE if MMU
 	select HAVE_CACHE_CB
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support.
 
@@ -260,6 +270,7 @@ config M548x
 	select M54xx
 	select HAVE_CACHE_CB
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
 
diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig
index a0fa88d..2ac2de6 100644
--- a/arch/metag/Kconfig
+++ b/arch/metag/Kconfig
@@ -29,6 +29,7 @@ config METAG
 	select OF
 	select OF_EARLY_FLATTREE
 	select SPARSE_IRQ
+	select CPU_NO_EFFICIENT_FFS
 
 config STACKTRACE_SUPPORT
 	def_bool y
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 3d793b5..f17c3a4 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -32,6 +32,7 @@ config MICROBLAZE
 	select OF_EARLY_FLATTREE
 	select TRACING_SUPPORT
 	select VIRT_TO_BUS
+	select CPU_NO_EFFICIENT_FFS
 
 config SWAP
 	def_bool n
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index eeec8c8..e20e100 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -180,6 +180,16 @@
 #endif
 #endif
 
+/* __builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r */
+#if !((defined(cpu_has_mips32r1) && cpu_has_mips32r1) || \
+	  (defined(cpu_has_mips32r2) && cpu_has_mips32r2) || \
+	  (defined(cpu_has_mips32r6) && cpu_has_mips32r6) || \
+	  (defined(cpu_has_mips64r1) && cpu_has_mips64r1) || \
+	  (defined(cpu_has_mips64r2) && cpu_has_mips64r2) || \
+	  (defined(cpu_has_mips64r6) && cpu_has_mips64r6))
+#define CONFIG_CPU_NO_EFFICIENT_FFS 1
+#endif
+
 #ifndef cpu_has_mips_1
 # define cpu_has_mips_1		(!cpu_has_mips_r6)
 #endif
diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig
index 4375554..f10bd2c 100644
--- a/arch/nios2/Kconfig
+++ b/arch/nios2/Kconfig
@@ -16,6 +16,7 @@ config NIOS2
 	select SOC_BUS
 	select SPARSE_IRQ
 	select USB_ARCH_HAS_HCD if USB_SUPPORT
+	select CPU_NO_EFFICIENT_FFS
 
 config GENERIC_CSUM
 	def_bool y
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index e118c02..142cb05 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -25,6 +25,7 @@ config OPENRISC
 	select MODULES_USE_ELF_RELA
 	select HAVE_DEBUG_STACKOVERFLOW
 	select OR1K_PIC
+	select CPU_NO_EFFICIENT_FFS if !OPENRISC_HAVE_INST_FF1
 
 config MMU
 	def_bool y
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 88cfaa8..3d498a6 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -32,6 +32,7 @@ config PARISC
 	select HAVE_ARCH_AUDITSYSCALL
 	select HAVE_ARCH_SECCOMP_FILTER
 	select ARCH_NO_COHERENT_DMA_MMAP
+	select CPU_NO_EFFICIENT_FFS
 
 	help
 	  The PA-RISC microprocessor is designed by Hewlett-Packard and used
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index bf24ab1..9eb3932 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -164,7 +164,7 @@ config S390
 	select TTY
 	select VIRT_CPU_ACCOUNTING
 	select VIRT_TO_BUS
-
+	select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES
 
 config SCHED_OMIT_FRAME_POINTER
 	def_bool y
diff --git a/arch/score/Kconfig b/arch/score/Kconfig
index 366e1b5..507d631 100644
--- a/arch/score/Kconfig
+++ b/arch/score/Kconfig
@@ -14,6 +14,7 @@ config SCORE
 	select VIRT_TO_BUS
 	select MODULES_USE_ELF_REL
 	select CLONE_BACKWARDS
+	select CPU_NO_EFFICIENT_FFS
 
 choice
 	prompt "System type"
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 7ed20fc..56cf5e5 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -44,6 +44,7 @@ config SUPERH
 	select OLD_SIGSUSPEND
 	select OLD_SIGACTION
 	select HAVE_ARCH_AUDITSYSCALL
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  The SuperH is a RISC processor targeted for use in embedded systems
 	  and consumer electronics; it was also used in the Sega Dreamcast
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 57ffaf2..ca675ed 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -42,6 +42,7 @@ config SPARC
 	select ODD_RT_SIGACTION
 	select OLD_SIGSUSPEND
 	select ARCH_HAS_SG_CHAIN
+	select CPU_NO_EFFICIENT_FFS
 
 config SPARC32
 	def_bool !64BIT
diff --git a/lib/gcd.c b/lib/gcd.c
index 3657f12..b9fbe73 100644
--- a/lib/gcd.c
+++ b/lib/gcd.c
@@ -2,20 +2,77 @@
 #include <linux/gcd.h>
 #include <linux/export.h>
 
-/* Greatest common divisor */
+/*
+ * This implements the binary GCD algorithm. (Often attributed to Stein,
+ * but as Knuth has noted, appears in a first-century Chinese math text.)
+ *
+ * This is faster than the division-based algorithm even on x86, which
+ * has decent hardware division.
+ */
+
+#if !defined(CONFIG_CPU_NO_EFFICIENT_FFS)
+
+/* If __ffs is available, the even/odd algorithm benchmarks slower. */
 unsigned long gcd(unsigned long a, unsigned long b)
 {
-	unsigned long r;
+	unsigned long r = a | b;
+
+	if (!a || !b)
+		return r;
 
-	if (a < b)
-		swap(a, b);
+	b >>= __ffs(b);
+	if (b == 1)
+		return r & -r;
 
-	if (!b)
-		return a;
-	while ((r = a % b) != 0) {
-		a = b;
-		b = r;
+	for (;;) {
+		a >>= __ffs(a);
+		if (a == 1)
+			return r & -r;
+		if (a == b)
+			return a << __ffs(r);
+
+		if (a < b)
+			swap(a, b);
+		a -= b;
 	}
-	return b;
 }
+
+#else
+
+/* If normalization is done by loops, the even/odd algorithm is a win. */
+unsigned long gcd(unsigned long a, unsigned long b)
+{
+	unsigned long r = a | b;
+
+	if (!a || !b)
+		return r;
+
+	/* Isolate lsbit of r */
+	r &= -r;
+
+	while (!(b & r))
+		b >>= 1;
+	if (b == r)
+		return r;
+
+	for (;;) {
+		while (!(a & r))
+			a >>= 1;
+		if (a == r)
+			return r;
+		if (a == b)
+			return a;
+
+		if (a < b)
+			swap(a, b);
+		a -= b;
+		a >>= 1;
+		if (a & r)
+			a += b;
+		a >>= 1;
+	}
+}
+
+#endif
+
 EXPORT_SYMBOL_GPL(gcd);
-- 
2.7.4




From andre.przywara at arm.com  Fri May  6 03:45:14 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:14 +0100
Subject: [PATCH v3 01/55] KVM: arm/arm64: vgic: streamline
 vgic_update_irq_pending() interface
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-2-git-send-email-andre.przywara@arm.com>

We actually don't use the irq_phys_map parameter in
vgic_update_irq_pending(), so let's just remove it.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 virt/kvm/arm/vgic.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 00429b3..7282881 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1522,7 +1522,6 @@ static int vgic_validate_injection(struct kvm_vcpu *vcpu, int irq, int level)
 }
 
 static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
-				   struct irq_phys_map *map,
 				   unsigned int irq_num, bool level)
 {
 	struct vgic_dist *dist = &kvm->arch.vgic;
@@ -1661,7 +1660,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 	if (map)
 		return -EINVAL;
 
-	return vgic_update_irq_pending(kvm, cpuid, NULL, irq_num, level);
+	return vgic_update_irq_pending(kvm, cpuid, irq_num, level);
 }
 
 /**
@@ -1687,7 +1686,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 	if (ret)
 		return ret;
 
-	return vgic_update_irq_pending(kvm, cpuid, map, map->virt_irq, level);
+	return vgic_update_irq_pending(kvm, cpuid, map->virt_irq, level);
 }
 
 static irqreturn_t vgic_maintenance_handler(int irq, void *data)
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:16 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:16 +0100
Subject: [PATCH v3 03/55] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_map_is_active()
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-4-git-send-email-andre.przywara@arm.com>

For getting the active state of a mapped IRQ, we actually only need
the virtual IRQ number, not the pointer to the mapping entry.
Pass the virtual IRQ number from the arch timer to the VGIC directly.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- rewrap phys_active determination to fit in 80 characters

 include/kvm/arm_vgic.h    | 2 +-
 virt/kvm/arm/arch_timer.c | 6 ++----
 virt/kvm/arm/vgic.c       | 6 +++---
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index c4574da..5a34adc 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -347,7 +347,7 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 					   int virt_irq, int irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index ceec146..f601471 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -275,10 +275,8 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* to ensure that hardware interrupts from the timer triggers a guest
 	* exit.
 	*/
-	if (timer->irq.level || kvm_vgic_map_is_active(vcpu, timer->map))
-		phys_active = true;
-	else
-		phys_active = false;
+	phys_active = timer->irq.level ||
+			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
 
 	/*
 	 * We want to avoid hitting the (re)distributor as much as
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 9937d41..6911327 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1103,18 +1103,18 @@ static bool dist_active_irq(struct kvm_vcpu *vcpu)
 	return test_bit(vcpu->vcpu_id, dist->irq_active_on_cpu);
 }
 
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map)
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	int i;
 
 	for (i = 0; i < vcpu->arch.vgic_cpu.nr_lr; i++) {
 		struct vgic_lr vlr = vgic_get_lr(vcpu, i);
 
-		if (vlr.irq == map->virt_irq && vlr.state & LR_STATE_ACTIVE)
+		if (vlr.irq == virt_irq && vlr.state & LR_STATE_ACTIVE)
 			return true;
 	}
 
-	return vgic_irq_is_active(vcpu, map->virt_irq);
+	return vgic_irq_is_active(vcpu, virt_irq);
 }
 
 /*
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:15 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:15 +0100
Subject: [PATCH v3 02/55] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_inject_mapped_irq()
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-3-git-send-email-andre.przywara@arm.com>

When we want to inject a hardware mapped IRQ into a guest, we actually
only need the virtual IRQ number from the irq_phys_map.
So let's pass this number directly from the arch timer to the VGIC
to avoid using the map as a parameter.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 include/kvm/arm_vgic.h    | 2 +-
 virt/kvm/arm/arch_timer.c | 2 +-
 virt/kvm/arm/vgic.c       | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 281caf8..c4574da 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -341,7 +341,7 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 			bool level);
 int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
-			       struct irq_phys_map *map, bool level);
+			       unsigned int virt_irq, bool level);
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 9aaa35d..ceec146 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -178,7 +178,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
 				   timer->irq.level);
 	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->map,
+					 timer->map->virt_irq,
 					 timer->irq.level);
 	WARN_ON(ret);
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 7282881..9937d41 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1667,7 +1667,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
  * kvm_vgic_inject_mapped_irq - Inject a physically mapped IRQ to the vgic
  * @kvm:     The VM structure pointer
  * @cpuid:   The CPU for PPIs
- * @map:     Pointer to a irq_phys_map structure describing the mapping
+ * @virt_irq: The virtual IRQ to be injected
  * @level:   Edge-triggered:  true:  to trigger the interrupt
  *			      false: to ignore the call
  *	     Level-sensitive  true:  raise the input signal
@@ -1678,7 +1678,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
  * being HIGH and 0 being LOW and all devices being active-HIGH.
  */
 int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
-			       struct irq_phys_map *map, bool level)
+			       unsigned int virt_irq, bool level)
 {
 	int ret;
 
@@ -1686,7 +1686,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 	if (ret)
 		return ret;
 
-	return vgic_update_irq_pending(kvm, cpuid, map->virt_irq, level);
+	return vgic_update_irq_pending(kvm, cpuid, virt_irq, level);
 }
 
 static irqreturn_t vgic_maintenance_handler(int irq, void *data)
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:17 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:17 +0100
Subject: [PATCH v3 04/55] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_unmap_phys_irq()
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-5-git-send-email-andre.przywara@arm.com>

kvm_vgic_unmap_phys_irq() only needs the virtual IRQ number, so let's
just pass that between the arch timer and the VGIC to get rid of
the irq_phys_map pointer.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 include/kvm/arm_vgic.h    |  2 +-
 virt/kvm/arm/arch_timer.c |  2 +-
 virt/kvm/arm/vgic.c       | 11 ++++-------
 3 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 5a34adc..43eeb18 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -346,7 +346,7 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 					   int virt_irq, int irq);
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index f601471..58b2439 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -504,7 +504,7 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 
 	timer_disarm(timer);
 	if (timer->map)
-		kvm_vgic_unmap_phys_irq(vcpu, timer->map);
+		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
 }
 
 void kvm_timer_enable(struct kvm *kvm)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 6911327..2d7ae35 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1813,25 +1813,22 @@ static void vgic_free_phys_irq_map_rcu(struct rcu_head *rcu)
 /**
  * kvm_vgic_unmap_phys_irq - Remove a virtual to physical IRQ mapping
  * @vcpu: The VCPU pointer
- * @map: The pointer to a mapping obtained through kvm_vgic_map_phys_irq
+ * @virt_irq: The virtual IRQ number to be unmapped
  *
  * Remove an existing mapping between virtual and physical interrupts.
  */
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map)
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct irq_phys_map_entry *entry;
 	struct list_head *root;
 
-	if (!map)
-		return -EINVAL;
-
-	root = vgic_get_irq_phys_map_list(vcpu, map->virt_irq);
+	root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 
 	spin_lock(&dist->irq_phys_map_lock);
 
 	list_for_each_entry(entry, root, entry) {
-		if (&entry->map == map) {
+		if (entry->map.virt_irq == virt_irq) {
 			list_del_rcu(&entry->entry);
 			call_rcu(&entry->rcu, vgic_free_phys_irq_map_rcu);
 			break;
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:13 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:13 +0100
Subject: [PATCH v3 00/55] KVM: arm/arm64: Rework virtual GIC emulation
Message-ID: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>

Hi,

another week, another rework of the new-VGIC series.
Mostly minor changes this time, some moving and streamlining of patches
(move prototypes to the same patch as the definition etc.)
The most prominent change though is the rework of the GICv2 CPU
interface access functionality. It turns out that this was not properly
wired, so now we treat is very similar to the distributor registers
and declare the registers in our register structure.
Find a summary changelog below and more details in the respective patches.

As this new VGIC emulation will probably become the default very shortly,
please test it full steam on whatever setup you have access to.
Any reports are warmly welcome.

This series is still based on v4.6-rc5 as the previous version, though
a test rebase to -rc6 didn't trigger any issues.
A git tree containing this series can be found on linux-arm.org:

git://linux-arm.org/linux-ap.git	branch: vgic-new/v3
http://www.linux-arm.org/git?p=linux-ap.git;a=log;h=refs/heads/vgic-new/v3

Cheers,
Andre.

Changelog v2 .. v3:
- arch_timer: remove bogus validity check from kvm_vgic_unmap_phys_irq()
- arch_timer: simplify return in kvm_timer_vcpu_reset()
- move some code between patches to fix rebase artifacts
- add patch 12/55 to move some definitions into arm-vgic-v3.h
- replace inclusions of vgic/vgic.h with arm_vgic.h
- rename v3 redist register description variables to _rdbase_ and _sgibase_
- don't export VMCR accessor wrappers
- rework CPU i/f access from userland, moving code into vgic-mmio-v2.c
- make ich_vtr_el2 variable local

===========================
This series is a joint effort to re-implement KVM's GIC emulation.

While the current implementation is centered around providing
efficient MMIO emulation, the hot path for most guests is actually
the guest entry and exit, which currently is rather costly.
Also the existing emulation has a global distributor lock, which
quickly becomes a bottleneck once the number of VCPUs increases.
Additionally the emulation was originally designed for GICv2, adding
GICv3 ITS emulation support to this proved to be rather painful.
Last, but not least the existing code became less and less
maintainable, with many special cases handled explicitly.

The new implementation is build around a struct vgic_irq data
structure, which holds all information about a virtual interrupt.
Interruts which should be injected are held in a per-VCPU list, this
make the entry/exit path much more efficient. Also the new structure
allows to have more fine grained locking - per IRQ and per VCPU -
getting rid of the global distributor lock.
As a result of the new design ITS emulation fits in more nicely, the
respective code will be provided as a follow-up series.

This series implements the same feature set as the existing emulation,
as a goodie we now implement priorities correctly.
To allow an easy transition with good test coverage, but still maintain
stability, both implementations live side by side, selectable via a
Kconfig option. The default is the new implementation.
If this code proves to be reliable, we will later remove the current
implementation with an extra patch set.

Please have a look at the series, review it and give the code some
serious testing (and possibly debugging). All feedback is appreciated.

Cheers,
Andre.

Andre Przywara (29):
  KVM: arm/arm64: vgic: streamline vgic_update_irq_pending() interface
  KVM: arm/arm64: vgic: avoid map in kvm_vgic_inject_mapped_irq()
  KVM: arm/arm64: vgic: avoid map in kvm_vgic_map_is_active()
  KVM: arm/arm64: vgic: avoid map in kvm_vgic_unmap_phys_irq()
  KVM: arm/arm64: arch_timer: Remove irq_phys_map
  KVM: arm/arm64: vgic: Remove irq_phys_map from interface
  KVM: arm/arm64: pmu: abstract access to number of SPIs
  KVM: arm/arm64: move GICv2 emulation defines into arm-gic-v3.h
  KVM: arm/arm64: vgic-new: Add GICv2 MMIO handling framework
  KVM: arm/arm64: vgic-new: Add ENABLE registers handlers
  KVM: arm/arm64: vgic-new: Add PENDING registers handlers
  KVM: arm/arm64: vgic-new: Add ACTIVE registers handlers
  KVM: arm/arm64: vgic-new: Add PRIORITY registers handlers
  KVM: arm/arm64: vgic-new: Add CONFIG registers handlers
  KVM: arm/arm64: vgic-new: Add TARGET registers handlers
  KVM: arm/arm64: vgic-new: Add SGIR register handler
  KVM: arm/arm64: vgic-new: Add SGIPENDR register handlers
  KVM: arm/arm64: vgic-new: Add GICv3 MMIO handling framework
  KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR, TYPER handlers
  KVM: arm/arm64: vgic-new: Add GICv3 redistributor IIDR and TYPER handler
  KVM: arm/arm64: vgic-new: Add GICv3 IDREGS register handler
  KVM: arm/arm64: vgic-new: Add GICv3 IROUTER register handlers
  KVM: arm/arm64: vgic-new: Add GICv3 SGI system register trap handler
  KVM: arm/arm64: vgic-new: Add userland access to VGIC dist registers
  KVM: arm/arm64: vgic-new: Add GICH_VMCR accessors
  KVM: arm/arm64: vgic-new: Add userland GIC CPU interface access
  KVM: arm/arm64: vgic-new: Wire up irqfd injection
  KVM: arm/arm64: vgic-new: implement mapped IRQ handling
  KVM: arm/arm64: vgic-new: enable build

Christoffer Dall (9):
  KVM: arm/arm64: Remove the IRQ field from struct irq_phys_map
  KVM: arm/arm64: Get rid of vgic_cpu->nr_lr
  KVM: arm/arm64: Fix MMIO emulation data handling
  KVM: arm/arm64: Export mmio_read/write_bus
  KVM: arm/arm64: vgic-new: Add data structure definitions
  KVM: arm/arm64: vgic-new: Add acccessor to new struct vgic_irq instance
  KVM: arm/arm64: vgic-new: Implement virtual IRQ injection
  KVM: arm/arm64: vgic-new: Add IRQ sorting
  KVM: arm/arm64: vgic-new: Export register access interface

Eric Auger (12):
  KVM: arm/arm64: vgic-new: Implement kvm_vgic_vcpu_pending_irq
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM device ops registration
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_NR_IRQS
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_CTRL
  KVM: arm/arm64: vgic-new: vgic_kvm_device: implement kvm_vgic_addr
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_ADDR
  KVM: arm/arm64: vgic-new: vgic_kvm_device: access to VGIC registers
  KVM: arm/arm64: vgic-new: vgic_init: implement kvm_vgic_hyp_init
  KVM: arm/arm64: vgic-new: vgic_init: implement vgic_create
  KVM: arm/arm64: vgic-new: vgic_init: implement vgic_init
  KVM: arm/arm64: vgic-new: vgic_init: implement map_resources
  KVM: arm/arm64: vgic-new: Add vgic_v2/v3_enable

Marc Zyngier (5):
  KVM: arm/arm64: vgic-new: Add IRQ sync/flush framework
  KVM: arm/arm64: vgic-new: Add GICv2 world switch backend
  KVM: arm/arm64: vgic-new: Add GICv3 world switch backend
  KVM: arm/arm64: vgic-new: Add MMIO handling framework
  KVM: arm/arm64: vgic-new: Add CTLR, TYPER and IIDR handlers

 arch/arm/include/asm/kvm_mmio.h     |   3 +
 arch/arm/kvm/Kconfig                |   7 +
 arch/arm/kvm/Makefile               |  11 +
 arch/arm/kvm/mmio.c                 |  24 +-
 arch/arm64/include/asm/kvm_mmio.h   |   3 +
 arch/arm64/kvm/Kconfig              |   7 +
 arch/arm64/kvm/Makefile             |  12 +
 include/kvm/arm_arch_timer.h        |   3 -
 include/kvm/arm_vgic.h              |  20 +-
 include/kvm/vgic/vgic.h             | 253 +++++++++++++++
 include/linux/irqchip/arm-gic-v3.h  |   6 +
 include/linux/irqchip/arm-gic.h     |   2 +
 virt/kvm/arm/arch_timer.c           |  42 ++-
 virt/kvm/arm/hyp/vgic-v2-sr.c       |  17 +-
 virt/kvm/arm/pmu.c                  |   2 +-
 virt/kvm/arm/vgic-v2.c              |   4 +-
 virt/kvm/arm/vgic-v3.c              |   8 +-
 virt/kvm/arm/vgic.c                 |  86 ++---
 virt/kvm/arm/vgic/vgic-init.c       | 446 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-irqfd.c      |  52 +++
 virt/kvm/arm/vgic/vgic-kvm-device.c | 452 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 422 +++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio-v3.c    | 464 +++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c       | 523 ++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h       | 128 ++++++++
 virt/kvm/arm/vgic/vgic-v2.c         | 358 +++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c         | 333 +++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c            | 615 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            | 121 +++++++
 29 files changed, 4309 insertions(+), 115 deletions(-)
 create mode 100644 include/kvm/vgic/vgic.h
 create mode 100644 virt/kvm/arm/vgic/vgic-init.c
 create mode 100644 virt/kvm/arm/vgic/vgic-irqfd.c
 create mode 100644 virt/kvm/arm/vgic/vgic-kvm-device.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v2.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h
 create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
 create mode 100644 virt/kvm/arm/vgic/vgic-v3.c
 create mode 100644 virt/kvm/arm/vgic/vgic.c
 create mode 100644 virt/kvm/arm/vgic/vgic.h

-- 
2.7.3


From andre.przywara at arm.com  Fri May  6 03:45:25 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:25 +0100
Subject: [PATCH v3 12/55] KVM: arm/arm64: move GICv2 emulation defines into
 arm-gic-v3.h
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-13-git-send-email-andre.przywara@arm.com>

As (some) GICv3 hosts can emulate a GICv2, some GICv2 specific masks
for the list register definition also apply to GICv3 LRs.
At the moment we have those definitions in the KVM VGICv3
implementation, so let's move them into the GICv3 header file to
have them automatically defined.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 include/linux/irqchip/arm-gic-v3.h | 5 +++++
 virt/kvm/arm/vgic-v3.c             | 8 +-------
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index d5d798b..ec938d1 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -276,6 +276,11 @@
 #define ICH_LR_PHYS_ID_SHIFT		32
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
 
+/* These are for GICv2 emulation only */
+#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
+#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
+#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
+
 #define ICH_MISR_EOI			(1 << 0)
 #define ICH_MISR_U			(1 << 1)
 
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index 999bdc6..9c5cfc2 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -31,12 +31,6 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmu.h>
 
-/* These are for GICv2 emulation only */
-#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
-#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
-#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
-#define ICH_LR_VIRTUALID_MASK		(BIT_ULL(32) - 1)
-
 static u32 ich_vtr_el2;
 
 static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
@@ -45,7 +39,7 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
 	u64 val = vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr];
 
 	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
-		lr_desc.irq = val & ICH_LR_VIRTUALID_MASK;
+		lr_desc.irq = val & ICH_LR_VIRTUAL_ID_MASK;
 	else
 		lr_desc.irq = val & GICH_LR_VIRTUALID;
 
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:27 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:27 +0100
Subject: [PATCH v3 14/55] KVM: arm/arm64: vgic-new: Add acccessor to new
 struct vgic_irq instance
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-15-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

The new VGIC implementation centers around a struct vgic_irq instance
per virtual IRQ.
Provide a function to retrieve the right instance for a given IRQ
number and (in case of private interrupts) the right VCPU.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic.c | 41 +++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h | 22 ++++++++++++++++++++++
 2 files changed, 63 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic.c
 create mode 100644 virt/kvm/arm/vgic/vgic.h

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
new file mode 100644
index 0000000..fb45537
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
+
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
+			      u32 intid)
+{
+	/* SGIs and PPIs */
+	if (intid <= VGIC_MAX_PRIVATE)
+		return &vcpu->arch.vgic_cpu.private_irqs[intid];
+
+	/* SPIs */
+	if (intid <= VGIC_MAX_SPI)
+		return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS];
+
+	/* LPIs are not yet covered */
+	if (intid >= VGIC_MIN_LPI)
+		return NULL;
+
+	WARN(1, "Looking up struct vgic_irq for reserved INTID");
+	return NULL;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
new file mode 100644
index 0000000..61b8d22
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __KVM_ARM_VGIC_NEW_H__
+#define __KVM_ARM_VGIC_NEW_H__
+
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
+			      u32 intid);
+
+#endif
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:24 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:24 +0100
Subject: [PATCH v3 11/55] KVM: arm/arm64: pmu: abstract access to number of
 SPIs
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-12-git-send-email-andre.przywara@arm.com>

Currently the PMU uses a member of the struct vgic_dist directly,
which not only breaks abstraction, but will fail with the new VGIC.
Abstract this access in the VGIC header file.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 include/kvm/arm_vgic.h | 2 ++
 virt/kvm/arm/pmu.c     | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 452bb85..c14ff77 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -347,6 +347,8 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
 #define vgic_ready(k)		((k)->arch.vgic.ready)
+#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
+				 ((i) < (k)->arch.vgic.nr_irqs))
 
 int vgic_v2_probe(struct device_node *vgic_node,
 		  const struct vgic_ops **ops,
diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
index 575c7aa..bd2e872 100644
--- a/virt/kvm/arm/pmu.c
+++ b/virt/kvm/arm/pmu.c
@@ -477,7 +477,7 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 		 * the interrupt number is the same for all vcpus, while as an
 		 * SPI it must be a separate number per vcpu.
 		 */
-		if (irq < VGIC_NR_SGIS || irq >= vcpu->kvm->arch.vgic.nr_irqs ||
+		if (irq < VGIC_NR_SGIS || !vgic_valid_spi(vcpu->kvm, irq) ||
 		    !irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
 			return -EINVAL;
 
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:19 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:19 +0100
Subject: [PATCH v3 06/55] KVM: arm/arm64: arch_timer: Remove irq_phys_map
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-7-git-send-email-andre.przywara@arm.com>

Now that the interface between the arch timer and the VGIC does not
require passing the irq_phys_map entry pointer anymore, let's remove
it from the virtual arch timer and use the virtual IRQ number instead
directly.
The remaining pointer returned by kvm_vgic_map_phys_irq() will be
removed in the following patch.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- remove extra virt_irq member from struct, instead use irq.irq directly

Changelog v2 .. v3:
- remove bogus validity check from kvm_vgic_unmap_phys_irq()

 include/kvm/arm_arch_timer.h |  3 ---
 virt/kvm/arm/arch_timer.c    | 10 ++++------
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index b651aed..a47b7de 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -53,9 +53,6 @@ struct arch_timer_cpu {
 	/* Timer IRQ */
 	struct kvm_irq_level		irq;
 
-	/* VGIC mapping */
-	struct irq_phys_map		*map;
-
 	/* Active IRQ state caching */
 	bool				active_cleared_last;
 };
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 29d597d..f2cd188 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -176,10 +176,10 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 
 	timer->active_cleared_last = false;
 	timer->irq.level = new_level;
-	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
+	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
 				   timer->irq.level);
 	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->map->virt_irq,
+					 timer->irq.irq,
 					 timer->irq.level);
 	WARN_ON(ret);
 }
@@ -277,7 +277,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* exit.
 	*/
 	phys_active = timer->irq.level ||
-			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
+			kvm_vgic_map_is_active(vcpu, timer->irq.irq);
 
 	/*
 	 * We want to avoid hitting the (re)distributor as much as
@@ -379,7 +379,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	if (WARN_ON(IS_ERR(map)))
 		return PTR_ERR(map);
 
-	timer->map = map;
 	return 0;
 }
 
@@ -522,8 +521,7 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 
 	timer_disarm(timer);
-	if (timer->map)
-		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
+	kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq);
 }
 
 void kvm_timer_enable(struct kvm *kvm)
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:20 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:20 +0100
Subject: [PATCH v3 07/55] KVM: arm/arm64: vgic: Remove irq_phys_map from
 interface
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-8-git-send-email-andre.przywara@arm.com>

Now that the virtual arch timer does not care about the irq_phys_map
anymore, let's rework kvm_vgic_map_phys_irq() to return an error
value instead. Any reference to that mapping can later be done by
passing the correct combination of VCPU and virtual IRQ number.
This makes the irq_phys_map handling completely private to the
VGIC code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- adaptations to changes in previous patches (removal of virt_irq)

Changelog v2 .. v3:
- simplify return in kvm_timer_vcpu_reset()

 include/kvm/arm_vgic.h    |  3 +--
 virt/kvm/arm/arch_timer.c |  7 +------
 virt/kvm/arm/vgic.c       | 15 +++++++--------
 3 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 49c559e..f842d7d 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -343,8 +343,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 			       unsigned int virt_irq, bool level);
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
-struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int phys_irq);
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, int virt_irq, int phys_irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index f2cd188..ebc4616 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -334,7 +334,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 			 const struct kvm_irq_level *irq)
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-	struct irq_phys_map *map;
 	struct irq_desc *desc;
 	struct irq_data *data;
 	int phys_irq;
@@ -375,11 +374,7 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	 * Tell the VGIC that the virtual interrupt is tied to a
 	 * physical interrupt. We do that once per VCPU.
 	 */
-	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
-	if (WARN_ON(IS_ERR(map)))
-		return PTR_ERR(map);
-
-	return 0;
+	return kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
 }
 
 void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 41792c0..00386df 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1720,21 +1720,20 @@ static struct list_head *vgic_get_irq_phys_map_list(struct kvm_vcpu *vcpu,
  * the physical interrupt represented by @phys_irq. This mapping can be
  * established multiple times as long as the parameters are the same.
  *
- * Returns a valid pointer on success, and an error pointer otherwise
+ * Returns 0 on success or an error value otherwise.
  */
-struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int phys_irq)
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, int virt_irq, int phys_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct list_head *root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 	struct irq_phys_map *map;
 	struct irq_phys_map_entry *entry;
-
+	int ret = 0;
 
 	/* Create a new mapping */
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	spin_lock(&dist->irq_phys_map_lock);
 
@@ -1743,7 +1742,7 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	if (map) {
 		/* Make sure this mapping matches */
 		if (map->phys_irq != phys_irq)
-			map = ERR_PTR(-EINVAL);
+			ret = -EINVAL;
 
 		/* Found an existing, valid mapping */
 		goto out;
@@ -1759,9 +1758,9 @@ out:
 	spin_unlock(&dist->irq_phys_map_lock);
 	/* If we've found a hit in the existing list, free the useless
 	 * entry */
-	if (IS_ERR(map) || map != &entry->map)
+	if (ret || map != &entry->map)
 		kfree(entry);
-	return map;
+	return ret;
 }
 
 static struct irq_phys_map *vgic_irq_map_search(struct kvm_vcpu *vcpu,
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:22 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:22 +0100
Subject: [PATCH v3 09/55] KVM: arm/arm64: Fix MMIO emulation data handling
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-10-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

When the kernel was handling a guest MMIO read access internally, we
need to copy the emulation result into the run->mmio structure in order
for the kvm_handle_mmio_return() function to pick it up and inject the
	result back into the guest.

Currently the only user of kvm_io_bus for ARM is the VGIC, which did
this copying itself, so this was not causing issues so far.

But with the upcoming new vgic implementation we need this done
properly.

Update the kvm_handle_mmio_return description and cleanup the code to
only perform a single copying when needed.

Code and commit message inspired by Andre Przywara.

Reported-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/kvm/mmio.c | 14 +++++++-------
 virt/kvm/arm/vgic.c |  7 -------
 2 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 0f6600f..0158e9e 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -87,11 +87,10 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len)
 
 /**
  * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation
+ *			     or in-kernel IO emulation
+ *
  * @vcpu: The VCPU pointer
  * @run:  The VCPU run struct containing the mmio data
- *
- * This should only be called after returning from userspace for MMIO load
- * emulation.
  */
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
@@ -206,18 +205,19 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 	run->mmio.is_write	= is_write;
 	run->mmio.phys_addr	= fault_ipa;
 	run->mmio.len		= len;
-	if (is_write)
-		memcpy(run->mmio.data, data_buf, len);
 
 	if (!ret) {
 		/* We handled the access successfully in the kernel. */
+		if (!is_write)
+			memcpy(run->mmio.data, data_buf, len);
 		vcpu->stat.mmio_exit_kernel++;
 		kvm_handle_mmio_return(vcpu, run);
 		return 1;
-	} else {
-		vcpu->stat.mmio_exit_user++;
 	}
 
+	if (is_write)
+		memcpy(run->mmio.data, data_buf, len);
+	vcpu->stat.mmio_exit_user++;
 	run->exit_reason	= KVM_EXIT_MMIO;
 	return 0;
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 5efc298..e70cee4 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -820,7 +820,6 @@ static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct vgic_io_device *iodev = container_of(this,
 						    struct vgic_io_device, dev);
-	struct kvm_run *run = vcpu->run;
 	const struct vgic_io_range *range;
 	struct kvm_exit_mmio mmio;
 	bool updated_state;
@@ -849,12 +848,6 @@ static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
 		updated_state = false;
 	}
 	spin_unlock(&dist->lock);
-	run->mmio.is_write	= is_write;
-	run->mmio.len		= len;
-	run->mmio.phys_addr	= addr;
-	memcpy(run->mmio.data, val, len);
-
-	kvm_handle_mmio_return(vcpu, run);
 
 	if (updated_state)
 		vgic_kick_vcpus(vcpu->kvm);
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:21 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:21 +0100
Subject: [PATCH v3 08/55] KVM: arm/arm64: Get rid of vgic_cpu->nr_lr
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-9-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

The number of list registers is a property of the underlying system, not
of emulated VGIC CPU interface.

As we are about to move this variable to global state in the new vgic
for clarity, move it from the legacy implementation as well to make the
merge of the new code easier.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 include/kvm/arm_vgic.h        |  3 ---
 virt/kvm/arm/hyp/vgic-v2-sr.c | 12 +++++++-----
 virt/kvm/arm/vgic-v2.c        |  4 +++-
 virt/kvm/arm/vgic.c           | 12 ++----------
 4 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index f842d7d..452bb85 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -303,9 +303,6 @@ struct vgic_cpu {
 	unsigned long   *active_shared;
 	unsigned long   *pend_act_shared;
 
-	/* Number of list registers on this CPU */
-	int		nr_lr;
-
 	/* CPU vif control registers for world switch */
 	union {
 		struct vgic_v2_cpu_if	vgic_v2;
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index 674bdf8..caac41f 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -21,11 +21,13 @@
 
 #include <asm/kvm_hyp.h>
 
+extern struct vgic_params vgic_v2_params;
+
 static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 					    void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	u32 eisr0, eisr1;
 	int i;
 	bool expect_mi;
@@ -67,7 +69,7 @@ static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	u32 elrsr0, elrsr1;
 
 	elrsr0 = readl_relaxed(base + GICH_ELRSR0);
@@ -86,7 +88,7 @@ static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
 static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	int i;
 
 	for (i = 0; i < nr_lr; i++) {
@@ -141,13 +143,13 @@ void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
 	struct vgic_dist *vgic = &kvm->arch.vgic;
 	void __iomem *base = kern_hyp_va(vgic->vctrl_base);
-	int i, nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
+	int i;
 	u64 live_lrs = 0;
 
 	if (!base)
 		return;
 
-	nr_lr = vcpu->arch.vgic_cpu.nr_lr;
 
 	for (i = 0; i < nr_lr; i++)
 		if (cpu_if->vgic_lr[i] & GICH_LR_STATE)
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
index 67ec334..6aaf5f7 100644
--- a/virt/kvm/arm/vgic-v2.c
+++ b/virt/kvm/arm/vgic-v2.c
@@ -174,7 +174,7 @@ static const struct vgic_ops vgic_v2_ops = {
 	.enable			= vgic_v2_enable,
 };
 
-static struct vgic_params vgic_v2_params;
+struct vgic_params __section(.hyp.text) vgic_v2_params;
 
 static void vgic_cpu_init_lrs(void *params)
 {
@@ -204,6 +204,8 @@ int vgic_v2_probe(struct device_node *vgic_node,
 	struct resource vcpu_res;
 	struct vgic_params *vgic = &vgic_v2_params;
 
+	memset(vgic, 0, sizeof(*vgic));
+
 	vgic->maint_irq = irq_of_parse_and_map(vgic_node, 0);
 	if (!vgic->maint_irq) {
 		kvm_err("error getting vgic maintenance irq from DT\n");
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 00386df..5efc298 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -691,12 +691,11 @@ bool vgic_handle_cfg_reg(u32 *reg, struct kvm_exit_mmio *mmio,
  */
 void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
 {
-	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
 	u64 elrsr = vgic_get_elrsr(vcpu);
 	unsigned long *elrsr_ptr = u64_to_bitmask(&elrsr);
 	int i;
 
-	for_each_clear_bit(i, elrsr_ptr, vgic_cpu->nr_lr) {
+	for_each_clear_bit(i, elrsr_ptr, vgic->nr_lr) {
 		struct vgic_lr lr = vgic_get_lr(vcpu, i);
 
 		/*
@@ -1107,7 +1106,7 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	int i;
 
-	for (i = 0; i < vcpu->arch.vgic_cpu.nr_lr; i++) {
+	for (i = 0; i < vgic->nr_lr; i++) {
 		struct vgic_lr vlr = vgic_get_lr(vcpu, i);
 
 		if (vlr.irq == virt_irq && vlr.state & LR_STATE_ACTIVE)
@@ -1867,13 +1866,6 @@ static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
 		return -ENOMEM;
 	}
 
-	/*
-	 * Store the number of LRs per vcpu, so we don't have to go
-	 * all the way to the distributor structure to find out. Only
-	 * assembly code should use this one.
-	 */
-	vgic_cpu->nr_lr = vgic->nr_lr;
-
 	return 0;
 }
 
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:23 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:23 +0100
Subject: [PATCH v3 10/55] KVM: arm/arm64: Export mmio_read/write_bus
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-11-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Rename mmio_{read,write}_bus to kvm_mmio_{read,write}_bus and export
them out of mmio.c.
This will be needed later for the new VGIC implementation.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/include/asm/kvm_mmio.h   |  3 +++
 arch/arm/kvm/mmio.c               | 10 +++++-----
 arch/arm64/include/asm/kvm_mmio.h |  3 +++
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmio.h b/arch/arm/include/asm/kvm_mmio.h
index d8e90c8..f3a7de7 100644
--- a/arch/arm/include/asm/kvm_mmio.h
+++ b/arch/arm/include/asm/kvm_mmio.h
@@ -28,6 +28,9 @@ struct kvm_decode {
 	bool sign_extend;
 };
 
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
+
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		 phys_addr_t fault_ipa);
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 0158e9e..10f80a6 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -23,7 +23,7 @@
 
 #include "trace.h"
 
-static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data)
 {
 	void *datap = NULL;
 	union {
@@ -55,7 +55,7 @@ static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
 	memcpy(buf, datap, len);
 }
 
-static unsigned long mmio_read_buf(char *buf, unsigned int len)
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len)
 {
 	unsigned long data = 0;
 	union {
@@ -66,7 +66,7 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len)
 
 	switch (len) {
 	case 1:
-		data = buf[0];
+		data = *(u8 *)buf;
 		break;
 	case 2:
 		memcpy(&tmp.hword, buf, len);
@@ -103,7 +103,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		if (len > sizeof(unsigned long))
 			return -EINVAL;
 
-		data = mmio_read_buf(run->mmio.data, len);
+		data = kvm_mmio_read_buf(run->mmio.data, len);
 
 		if (vcpu->arch.mmio_decode.sign_extend &&
 		    len < sizeof(unsigned long)) {
@@ -189,7 +189,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 					       len);
 
 		trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data);
-		mmio_write_buf(data_buf, len, data);
+		kvm_mmio_write_buf(data_buf, len, data);
 
 		ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
 				       data_buf);
diff --git a/arch/arm64/include/asm/kvm_mmio.h b/arch/arm64/include/asm/kvm_mmio.h
index fe612a9..75ea420 100644
--- a/arch/arm64/include/asm/kvm_mmio.h
+++ b/arch/arm64/include/asm/kvm_mmio.h
@@ -30,6 +30,9 @@ struct kvm_decode {
 	bool sign_extend;
 };
 
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
+
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		 phys_addr_t fault_ipa);
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:29 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:29 +0100
Subject: [PATCH v3 16/55] KVM: arm/arm64: vgic-new: Add IRQ sorting
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-17-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Adds the sorting function to cover the case where you have more IRQs
to consider than you have LRs. We now consider priorities.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 92b78a0..4fb20fd 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -16,6 +16,7 @@
 
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <linux/list_sort.h>
 
 #include "vgic.h"
 
@@ -96,6 +97,62 @@ static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
 }
 
 /*
+ * The order of items in the ap_lists defines how we'll pack things in LRs as
+ * well, the first items in the list being the first things populated in the
+ * LRs.
+ *
+ * A hard rule is that active interrupts can never be pushed out of the LRs
+ * (and therefore take priority) since we cannot reliably trap on deactivation
+ * of IRQs and therefore they have to be present in the LRs.
+ *
+ * Otherwise things should be sorted by the priority field and the GIC
+ * hardware support will take care of preemption of priority groups etc.
+ *
+ * Return negative if "a" sorts before "b", 0 to preserve order, and positive
+ * to sort "b" before "a".
+ */
+static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+	struct vgic_irq *irqa = container_of(a, struct vgic_irq, ap_list);
+	struct vgic_irq *irqb = container_of(b, struct vgic_irq, ap_list);
+	bool penda, pendb;
+	int ret;
+
+	spin_lock(&irqa->irq_lock);
+	spin_lock(&irqb->irq_lock);
+
+	if (irqa->active || irqb->active) {
+		ret = (int)irqb->active - (int)irqa->active;
+		goto out;
+	}
+
+	penda = irqa->enabled && irqa->pending;
+	pendb = irqb->enabled && irqb->pending;
+
+	if (!penda || !pendb) {
+		ret = (int)pendb - (int)penda;
+		goto out;
+	}
+
+	/* Both pending and enabled, sort by priority */
+	ret = irqa->priority - irqb->priority;
+out:
+	spin_unlock(&irqb->irq_lock);
+	spin_unlock(&irqa->irq_lock);
+	return ret;
+}
+
+/* Must be called with the ap_list_lock held */
+static void vgic_sort_ap_list(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	list_sort(NULL, &vgic_cpu->ap_list_head, vgic_irq_cmp);
+}
+
+/*
  * Only valid injection if changing level for level-triggered IRQs or for a
  * rising edge.
  */
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:18 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:18 +0100
Subject: [PATCH v3 05/55] KVM: arm/arm64: Remove the IRQ field from struct
 irq_phys_map
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-6-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

The communication of a Linux IRQ number from outside the VGIC to the
vgic was a leftover from the day when the vgic code cared about how a
particular device injects virtual interrupts mapped to a physical
interrupt.

We can safely remove this notion, leaving all physical IRQ handling to
be done in the device driver (the arch timer in this case), which makes
room for a saner API for the new VGIC.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- update kerneldoc comments on kvm_vgic_map_phys_irq()

Changelog v2 .. v3:
- include <linux/irq.h>

 include/kvm/arm_vgic.h    |  3 +--
 virt/kvm/arm/arch_timer.c | 23 +++++++++++++++++++++--
 virt/kvm/arm/vgic.c       | 28 ++++++----------------------
 3 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 43eeb18..49c559e 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -157,7 +157,6 @@ struct vgic_io_device {
 struct irq_phys_map {
 	u32			virt_irq;
 	u32			phys_irq;
-	u32			irq;
 };
 
 struct irq_phys_map_entry {
@@ -345,7 +344,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int irq);
+					   int virt_irq, int phys_irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 58b2439..29d597d 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -21,6 +21,7 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <clocksource/arm_arch_timer.h>
 #include <asm/arch_timer.h>
@@ -301,7 +302,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	if (timer->active_cleared_last && !phys_active)
 		return;
 
-	ret = irq_set_irqchip_state(timer->map->irq,
+	ret = irq_set_irqchip_state(host_vtimer_irq,
 				    IRQCHIP_STATE_ACTIVE,
 				    phys_active);
 	WARN_ON(ret);
@@ -334,6 +335,9 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 	struct irq_phys_map *map;
+	struct irq_desc *desc;
+	struct irq_data *data;
+	int phys_irq;
 
 	/*
 	 * The vcpu timer irq number cannot be determined in
@@ -353,10 +357,25 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	kvm_timer_update_state(vcpu);
 
 	/*
+	 * Find the physical IRQ number corresponding to the host_vtimer_irq
+	 */
+	desc = irq_to_desc(host_vtimer_irq);
+	if (!desc) {
+		kvm_err("%s: no interrupt descriptor\n", __func__);
+		return -EINVAL;
+	}
+
+	data = irq_desc_get_irq_data(desc);
+	while (data->parent_data)
+		data = data->parent_data;
+
+	phys_irq = data->hwirq;
+
+	/*
 	 * Tell the VGIC that the virtual interrupt is tied to a
 	 * physical interrupt. We do that once per VCPU.
 	 */
-	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, host_vtimer_irq);
+	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
 	if (WARN_ON(IS_ERR(map)))
 		return PTR_ERR(map);
 
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 2d7ae35..41792c0 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1712,38 +1712,24 @@ static struct list_head *vgic_get_irq_phys_map_list(struct kvm_vcpu *vcpu,
 /**
  * kvm_vgic_map_phys_irq - map a virtual IRQ to a physical IRQ
  * @vcpu: The VCPU pointer
- * @virt_irq: The virtual irq number
- * @irq: The Linux IRQ number
+ * @virt_irq: The virtual IRQ number for the guest
+ * @phys_irq: The hardware IRQ number of the host
  *
  * Establish a mapping between a guest visible irq (@virt_irq) and a
- * Linux irq (@irq). On injection, @virt_irq will be associated with
- * the physical interrupt represented by @irq. This mapping can be
+ * hardware irq (@phys_irq). On injection, @virt_irq will be associated with
+ * the physical interrupt represented by @phys_irq. This mapping can be
  * established multiple times as long as the parameters are the same.
  *
  * Returns a valid pointer on success, and an error pointer otherwise
  */
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int irq)
+					   int virt_irq, int phys_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct list_head *root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 	struct irq_phys_map *map;
 	struct irq_phys_map_entry *entry;
-	struct irq_desc *desc;
-	struct irq_data *data;
-	int phys_irq;
 
-	desc = irq_to_desc(irq);
-	if (!desc) {
-		kvm_err("%s: no interrupt descriptor\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
-
-	data = irq_desc_get_irq_data(desc);
-	while (data->parent_data)
-		data = data->parent_data;
-
-	phys_irq = data->hwirq;
 
 	/* Create a new mapping */
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
@@ -1756,8 +1742,7 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	map = vgic_irq_map_search(vcpu, virt_irq);
 	if (map) {
 		/* Make sure this mapping matches */
-		if (map->phys_irq != phys_irq	||
-		    map->irq      != irq)
+		if (map->phys_irq != phys_irq)
 			map = ERR_PTR(-EINVAL);
 
 		/* Found an existing, valid mapping */
@@ -1767,7 +1752,6 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	map           = &entry->map;
 	map->virt_irq = virt_irq;
 	map->phys_irq = phys_irq;
-	map->irq      = irq;
 
 	list_add_tail_rcu(&entry->entry, root);
 
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:30 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:30 +0100
Subject: [PATCH v3 17/55] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-18-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Implement the framework for syncing IRQs between our emulation and
the list registers, which represent the guest's view of IRQs.
This is done in kvm_vgic_flush_hwstate and kvm_vgic_sync_hwstate,
which gets called on guest entry and exit.
The code talking to the actual GICv2/v3 hardware is added in the
following patches.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- split out vgic_clear_lr() from vgic_populate_lr()
- rename vgic_populate_lrs() to vgic_flush_lr_state()
- clean all LRs when the distributor is disabled
- use list_del() instead of list_del_init()
- add comments to explain the direction of sync/flush_hwstate
- remove unneeded BUG_ON(in_interrupt()

Changelog v2 .. v3:
- remove bogus v2 specific rebase leftovers

 include/kvm/vgic/vgic.h  |   4 +
 virt/kvm/arm/vgic/vgic.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h |   2 +
 3 files changed, 199 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 2bfb42c..5fae4a9 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -190,6 +190,10 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
 			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
 
+bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
+void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
+void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
+
 /**
  * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
  *
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 4fb20fd..c6f8b9b 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -305,3 +305,196 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 {
 	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
 }
+
+/**
+ * vgic_prune_ap_list - Remove non-relevant interrupts from the list
+ *
+ * @vcpu: The VCPU pointer
+ *
+ * Go over the list of "interesting" interrupts, and prune those that we
+ * won't have to consider in the near future.
+ */
+static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq, *tmp;
+
+retry:
+	spin_lock(&vgic_cpu->ap_list_lock);
+
+	list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
+		struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
+
+		spin_lock(&irq->irq_lock);
+
+		BUG_ON(vcpu != irq->vcpu);
+
+		target_vcpu = vgic_target_oracle(irq);
+
+		if (!target_vcpu) {
+			/*
+			 * We don't need to process this interrupt any
+			 * further, move it off the list.
+			 */
+			list_del(&irq->ap_list);
+			irq->vcpu = NULL;
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		if (target_vcpu == vcpu) {
+			/* We're on the right CPU */
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		/* This interrupt looks like it has to be migrated. */
+
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vgic_cpu->ap_list_lock);
+
+		/*
+		 * Ensure locking order by always locking the smallest
+		 * ID first.
+		 */
+		if (vcpu->vcpu_id < target_vcpu->vcpu_id) {
+			vcpuA = vcpu;
+			vcpuB = target_vcpu;
+		} else {
+			vcpuA = target_vcpu;
+			vcpuB = vcpu;
+		}
+
+		spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+		spin_lock(&vcpuB->arch.vgic_cpu.ap_list_lock);
+		spin_lock(&irq->irq_lock);
+
+		/*
+		 * If the affinity has been preserved, move the
+		 * interrupt around. Otherwise, it means things have
+		 * changed while the interrupt was unlocked, and we
+		 * need to replay this.
+		 *
+		 * In all cases, we cannot trust the list not to have
+		 * changed, so we restart from the beginning.
+		 */
+		if (target_vcpu == vgic_target_oracle(irq)) {
+			struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;
+
+			list_del(&irq->ap_list);
+			irq->vcpu = target_vcpu;
+			list_add_tail(&irq->ap_list, &new_cpu->ap_list_head);
+		}
+
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
+		spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+		goto retry;
+	}
+
+	spin_unlock(&vgic_cpu->ap_list_lock);
+}
+
+static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+}
+
+/* Requires the ap_list_lock and the irq_lock to be held. */
+static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
+				    struct vgic_irq *irq, int lr)
+{
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+}
+
+static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+}
+
+static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
+{
+}
+
+static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	int count = 0;
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+		/* GICv2 SGIs can count for more than one... */
+		if (vgic_irq_is_sgi(irq->intid) && irq->source)
+			count += hweight8(irq->source);
+		else
+			count++;
+		spin_unlock(&irq->irq_lock);
+	}
+	return count;
+}
+
+/* Requires the VCPU's ap_list_lock to be held. */
+static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	int count = 0;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	if (unlikely(!vcpu->kvm->arch.vgic.enabled))
+		goto out_clean;
+
+	if (compute_ap_list_depth(vcpu) > kvm_vgic_global_state.nr_lr) {
+		vgic_set_underflow(vcpu);
+		vgic_sort_ap_list(vcpu);
+	}
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+
+		if (unlikely(vgic_target_oracle(irq) != vcpu))
+			goto next;
+
+		/*
+		 * If we get an SGI with multiple sources, try to get
+		 * them in all at once.
+		 */
+		do {
+			vgic_populate_lr(vcpu, irq, count++);
+		} while (irq->source && count < kvm_vgic_global_state.nr_lr);
+
+next:
+		spin_unlock(&irq->irq_lock);
+
+		if (count == kvm_vgic_global_state.nr_lr)
+			break;
+	}
+
+out_clean:
+	vcpu->arch.vgic_cpu.used_lrs = count;
+
+	/* Nuke remaining LRs */
+	for ( ; count < kvm_vgic_global_state.nr_lr; count++)
+		vgic_clear_lr(vcpu, count);
+}
+
+/* Sync back the hardware VGIC state into our emulation after a guest's run. */
+void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
+{
+	vgic_process_maintenance_interrupt(vcpu);
+	vgic_fold_lr_state(vcpu);
+	vgic_prune_ap_list(vcpu);
+}
+
+/* Flush our emulation state into the GIC hardware before entering the guest. */
+void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
+{
+	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+	vgic_flush_lr_state(vcpu);
+	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index c625767..29b96b9 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,6 +16,8 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:33 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:33 +0100
Subject: [PATCH v3 20/55] KVM: arm/arm64: vgic-new: Implement
 kvm_vgic_vcpu_pending_irq
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-21-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

Tell KVM whether a particular VCPU has an IRQ that needs handling
in the guest. This is used to decide whether a VCPU is runnable.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- return false if distributor is disabled
- add vgic_kick_vcpus() implementations

Changelog v2 .. v3:
- remove vgic_kick_vcpus() implementation from this patch

 include/kvm/vgic/vgic.h  |  2 ++
 virt/kvm/arm/vgic/vgic.c | 25 +++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 5fae4a9..2615205 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -184,6 +184,8 @@ struct vgic_cpu {
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
 
+int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
+
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(false)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 64d5b45..c3dbcf3 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -519,3 +519,28 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 	vgic_flush_lr_state(vcpu);
 	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
 }
+
+int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	bool pending = false;
+
+	if (!vcpu->kvm->arch.vgic.enabled)
+		return false;
+
+	spin_lock(&vgic_cpu->ap_list_lock);
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+		pending = irq->pending && irq->enabled;
+		spin_unlock(&irq->irq_lock);
+
+		if (pending)
+			break;
+	}
+
+	spin_unlock(&vgic_cpu->ap_list_lock);
+
+	return pending;
+}
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:26 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:26 +0100
Subject: [PATCH v3 13/55] KVM: arm/arm64: vgic-new: Add data structure
 definitions
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-14-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Add a new header file for the new and improved GIC implementation.
The big change is that we now have a struct vgic_irq per IRQ instead
of spreading all the information over various bitmaps.

We include this new header conditionally from within the old header
file for the time being to avoid touching all the users.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changes RFC .. v1:
- adapt to 4.6-rc (adding live_lrs member)
- elaborate on ap_list usage

Changes v1 .. v2:
- change data type of dist->enabled to bool

 include/kvm/arm_vgic.h  |   5 ++
 include/kvm/vgic/vgic.h | 201 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 206 insertions(+)
 create mode 100644 include/kvm/vgic/vgic.h

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index c14ff77..d406f8e 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -19,6 +19,10 @@
 #ifndef __ASM_ARM_KVM_VGIC_H
 #define __ASM_ARM_KVM_VGIC_H
 
+#ifdef CONFIG_KVM_NEW_VGIC
+#include <kvm/vgic/vgic.h>
+#else
+
 #include <linux/kernel.h>
 #include <linux/kvm.h>
 #include <linux/irqreturn.h>
@@ -366,4 +370,5 @@ static inline int vgic_v3_probe(struct device_node *vgic_node,
 }
 #endif
 
+#endif	/* old VGIC include */
 #endif
diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
new file mode 100644
index 0000000..39933ee
--- /dev/null
+++ b/include/kvm/vgic/vgic.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_ARM_KVM_VGIC_VGIC_H
+#define __ASM_ARM_KVM_VGIC_VGIC_H
+
+#include <linux/kernel.h>
+#include <linux/kvm.h>
+#include <linux/irqreturn.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <kvm/iodev.h>
+
+#define VGIC_V3_MAX_CPUS	255
+#define VGIC_V2_MAX_CPUS	8
+#define VGIC_NR_IRQS_LEGACY     256
+#define VGIC_NR_SGIS		16
+#define VGIC_NR_PPIS		16
+#define VGIC_NR_PRIVATE_IRQS	(VGIC_NR_SGIS + VGIC_NR_PPIS)
+#define VGIC_MAX_PRIVATE	(VGIC_NR_PRIVATE_IRQS - 1)
+#define VGIC_MAX_SPI		1019
+#define VGIC_MAX_RESERVED	1023
+#define VGIC_MIN_LPI		8192
+
+enum vgic_type {
+	VGIC_V2,		/* Good ol' GICv2 */
+	VGIC_V3,		/* New fancy GICv3 */
+};
+
+/* same for all guests, as depending only on the _host's_ GIC model */
+struct vgic_global {
+	/* type of the host GIC */
+	enum vgic_type		type;
+
+	/* Physical address of vgic virtual cpu interface */
+	phys_addr_t		vcpu_base;
+
+	/* virtual control interface mapping */
+	void __iomem		*vctrl_base;
+
+	/* Number of implemented list registers */
+	int			nr_lr;
+
+	/* Maintenance IRQ number */
+	unsigned int		maint_irq;
+
+	/* maximum number of VCPUs allowed (GICv2 limits us to 8) */
+	int			max_gic_vcpus;
+
+	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
+	bool			can_emulate_gicv2;
+};
+
+extern struct vgic_global kvm_vgic_global_state;
+
+#define VGIC_V2_MAX_LRS		(1 << 6)
+#define VGIC_V3_MAX_LRS		16
+#define VGIC_V3_LR_INDEX(lr)	(VGIC_V3_MAX_LRS - 1 - lr)
+
+enum vgic_irq_config {
+	VGIC_CONFIG_EDGE = 0,
+	VGIC_CONFIG_LEVEL
+};
+
+struct vgic_irq {
+	spinlock_t irq_lock;		/* Protects the content of the struct */
+	struct list_head ap_list;
+
+	struct kvm_vcpu *vcpu;		/* SGIs and PPIs: The VCPU
+					 * SPIs and LPIs: The VCPU whose ap_list
+					 * on which this is queued.
+					 */
+
+	struct kvm_vcpu *target_vcpu;	/* The VCPU that this interrupt should
+					 * be send to, as a result of the
+					 * targets reg (v2) or the
+					 * affinity reg (v3).
+					 */
+
+	u32 intid;			/* Guest visible INTID */
+	bool pending;
+	bool line_level;		/* Level only */
+	bool soft_pending;		/* Level only */
+	bool active;			/* not used for LPIs */
+	bool enabled;
+	bool hw;			/* Tied to HW IRQ */
+	u32 hwintid;			/* HW INTID number */
+	union {
+		u8 targets;			/* GICv2 target VCPUs mask */
+		u32 mpidr;			/* GICv3 target VCPU */
+	};
+	u8 source;			/* GICv2 SGIs only */
+	u8 priority;
+	enum vgic_irq_config config;	/* Level or edge */
+};
+
+struct vgic_dist {
+	bool			in_kernel;
+	bool			ready;
+
+	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
+	u32			vgic_model;
+
+	int			nr_spis;
+
+	/* TODO: Consider moving to global state */
+	/* Virtual control interface mapping */
+	void __iomem		*vctrl_base;
+
+	/* base addresses in guest physical address space: */
+	gpa_t			vgic_dist_base;		/* distributor */
+	union {
+		/* either a GICv2 CPU interface */
+		gpa_t			vgic_cpu_base;
+		/* or a number of GICv3 redistributor regions */
+		gpa_t			vgic_redist_base;
+	};
+
+	/* distributor enabled */
+	bool			enabled;
+
+	struct vgic_irq		*spis;
+};
+
+struct vgic_v2_cpu_if {
+	u32		vgic_hcr;
+	u32		vgic_vmcr;
+	u32		vgic_misr;	/* Saved only */
+	u64		vgic_eisr;	/* Saved only */
+	u64		vgic_elrsr;	/* Saved only */
+	u32		vgic_apr;
+	u32		vgic_lr[VGIC_V2_MAX_LRS];
+};
+
+struct vgic_v3_cpu_if {
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	u32		vgic_hcr;
+	u32		vgic_vmcr;
+	u32		vgic_sre;	/* Restored only, change ignored */
+	u32		vgic_misr;	/* Saved only */
+	u32		vgic_eisr;	/* Saved only */
+	u32		vgic_elrsr;	/* Saved only */
+	u32		vgic_ap0r[4];
+	u32		vgic_ap1r[4];
+	u64		vgic_lr[VGIC_V3_MAX_LRS];
+#endif
+};
+
+struct vgic_cpu {
+	/* CPU vif control registers for world switch */
+	union {
+		struct vgic_v2_cpu_if	vgic_v2;
+		struct vgic_v3_cpu_if	vgic_v3;
+	};
+
+	unsigned int used_lrs;
+	struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
+
+	spinlock_t ap_list_lock;	/* Protects the ap_list */
+
+	/*
+	 * List of IRQs that this VCPU should consider because they are either
+	 * Active or Pending (hence the name; AP list), or because they recently
+	 * were one of the two and need to be migrated off this list to another
+	 * VCPU.
+	 */
+	struct list_head ap_list_head;
+
+	u64 live_lrs;
+};
+
+#define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
+#define vgic_initialized(k)	(false)
+#define vgic_ready(k)		((k)->arch.vgic.ready)
+#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
+			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
+
+/**
+ * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
+ *
+ * The host's GIC naturally limits the maximum amount of VCPUs a guest
+ * can use.
+ */
+static inline int kvm_vgic_get_max_vcpus(void)
+{
+	return kvm_vgic_global_state.max_gic_vcpus;
+}
+
+#endif /* __ASM_ARM_KVM_VGIC_VGIC_H */
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:40 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:40 +0100
Subject: [PATCH v3 27/55] KVM: arm/arm64: vgic-new: Add PRIORITY registers
 handlers
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-28-git-send-email-andre.przywara@arm.com>

The priority register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.
There is a corner case when we change the priority of a pending
interrupt which we don't handle at the moment.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 39 +++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  7 +++++++
 3 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 054b52d..2e17250 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -84,7 +84,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
 		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index dbf683e..d7fe9e6 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -282,6 +282,45 @@ retry:
 	}
 }
 
+unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
+				      gpa_t addr, unsigned int len)
+{
+	u32 intid = addr & 0x3ff;
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->priority << (i * 8);
+	}
+
+	return val;
+}
+
+/*
+ * We currently don't handle changing the priority of an interrupt that
+ * is already pending on a VCPU. If there is a need for this, we would
+ * need to make this VCPU exit and re-evaluate the priorities, potentially
+ * leading to this interrupt getting presented now to the guest (if it has
+ * been masked by the priority mask before).
+ */
+void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = addr & 0x3ff;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		irq->priority = (val >> (i * 8)) & 0xff;
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index fa875dc..cd04ac5 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -107,6 +107,13 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val);
 
+unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
+				      gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:36 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:36 +0100
Subject: [PATCH v3 23/55] KVM: arm/arm64: vgic-new: Add CTLR,
 TYPER and IIDR handlers
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-24-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Those three registers are v2 emulation specific, so their implementation
lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
as their implementation is pretty simple.
When the guest enables the distributor, we kick all VCPUs to get
potentially pending interrupts serviced.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- kick VCPUs is the distributor gets enabled
- improve comment

Changelog v1 .. v2:
- adapt to new MMIO framework
- use switch() statements to improve readability

Changelog v2 .. v3:
- add vgic_kick_vcpus() implementation

 include/linux/irqchip/arm-gic.h  |  1 +
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 48 +++++++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
 virt/kvm/arm/vgic/vgic.h         |  4 ++++
 4 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index be0d26f..fd05185 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -33,6 +33,7 @@
 
 #define GIC_DIST_CTRL			0x000
 #define GIC_DIST_CTR			0x004
+#define GIC_DIST_IIDR			0x008
 #define GIC_DIST_IGROUP			0x080
 #define GIC_DIST_ENABLE_SET		0x100
 #define GIC_DIST_ENABLE_CLEAR		0x180
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 2729a22..69e96f7 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -20,9 +20,55 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 value;
+
+	switch (addr & 0x0c) {
+	case GIC_DIST_CTRL:
+		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
+		break;
+	case GIC_DIST_CTR:
+		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+		value = (value >> 5) - 1;
+		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
+		break;
+	case GIC_DIST_IIDR:
+		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+		break;
+	default:
+		return 0;
+	}
+
+	return extract_bytes(value, addr & 3, len);
+}
+
+static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	switch (addr & 0x0c) {
+	case GIC_DIST_CTRL:
+		if (!(addr & 1)) {
+			struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+			bool was_enabled = dist->enabled;
+
+			dist->enabled = val & GICD_ENABLE;
+			if (!was_enabled && dist->enabled)
+				vgic_kick_vcpus(vcpu->kvm);
+		}
+		break;
+	case GIC_DIST_CTR:
+	case GIC_DIST_IIDR:
+		/* Nothing to do */
+		return;
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 12),
+		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index c3dbcf3..5355de6 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -544,3 +544,18 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 
 	return pending;
 }
+
+void vgic_kick_vcpus(struct kvm *kvm)
+{
+	struct kvm_vcpu *vcpu;
+	int c;
+
+	/*
+	 * We've injected an interrupt, time to find out who deserves
+	 * a good kick...
+	 */
+	kvm_for_each_vcpu(c, vcpu, kvm) {
+		if (kvm_vgic_vcpu_pending_irq(vcpu))
+			kvm_vcpu_kick(vcpu);
+	}
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index fd9acaa..cf62015 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,11 +16,15 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
+#define IMPLEMENTER_ARM		0x43b
+
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
+void vgic_kick_vcpus(struct kvm *kvm);
 
 void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
 void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:38 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:38 +0100
Subject: [PATCH v3 25/55] KVM: arm/arm64: vgic-new: Add PENDING registers
 handlers
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-26-git-send-email-andre.przywara@arm.com>

The pending register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be easily
referenced from the v3 emulation as well later.
For level triggered interrupts the real line level is unaffected by
this write, so we keep this state separate and combine it with the
device's level to get the actual pending state.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- remove IRQ lock from read handler
- remove TODO from clear pending handler

Changelog v1 .. v2:
- adapt to new MMIO framework

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
 virt/kvm/arm/vgic/vgic-mmio.c    | 60 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 12 ++++++++
 3 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 448d1da..4b87e0a 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -76,9 +76,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
 		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 077ae86..4df1af7 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -102,6 +102,66 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len)
+{
+	u32 intid = (addr & 0x7f) * 8;
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->pending)
+			value |= (1U << i);
+	}
+
+	return extract_bytes(value, addr & 3, len);
+}
+
+void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = (addr & 0x7f) * 8;
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			irq->soft_pending = true;
+
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
+void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = (addr & 0x7f) * 8;
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		if (irq->config == VGIC_CONFIG_LEVEL) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		} else {
+			irq->pending = false;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 188909a..d4fc029 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -85,6 +85,18 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val);
 
+unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
+void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:42 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:42 +0100
Subject: [PATCH v3 29/55] KVM: arm/arm64: vgic-new: Add TARGET registers
 handlers
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-30-git-send-email-andre.przywara@arm.com>

The target register handlers are v2 emulation specific, so their
implementation lives entirely in vgic-mmio-v2.c.
We copy the old VGIC behaviour of assigning an IRQ to the first VCPU
set in the target mask instead of making it possibly pending on
multiple VCPUs.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- remove runtime VCPU determination from this v2-only register
- fold in implementation of vgic_v2_irq_change_affinity()
- replace ffs() with __ffs()

Changelog v1 .. v2:
- adapt to new MMIO framework

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 2a953ec..888529e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -66,6 +66,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
+					   gpa_t addr, unsigned int len)
+{
+	u32 intid = addr & 0x3ff;
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->targets << (i * 8);
+	}
+
+	return val;
+}
+
+static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
+				   gpa_t addr, unsigned int len,
+				   unsigned long val)
+{
+	u32 intid = addr & 0x3ff;
+	int i;
+
+	/* GICD_ITARGETSR[0-7] are read-only */
+	if (intid < VGIC_NR_PRIVATE_IRQS)
+		return;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
+		int target;
+
+		spin_lock(&irq->irq_lock);
+
+		irq->targets = (val >> (i * 8)) & 0xff;
+		target = irq->targets ? __ffs(irq->targets) : 0;
+		irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target);
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
@@ -86,7 +127,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
 		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
+		vgic_mmio_read_target, vgic_mmio_write_target, 8),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
 		vgic_mmio_read_config, vgic_mmio_write_config, 2),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:47 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:47 +0100
Subject: [PATCH v3 34/55] KVM: arm/arm64: vgic-new: Add GICv3 redistributor
 IIDR and TYPER handler
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-35-git-send-email-andre.przywara@arm.com>

The redistributor TYPER tells the OS about the associated MPIDR,
also the LAST bit is crucial to determine the number of redistributors.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 44 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 42 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 5f4558c..d137242 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -71,6 +71,46 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
 }
 
 /*
+ * We use a compressed version of the MPIDR (all 32 bits in one 32-bit word)
+ * when we store the target MPIDR written by the guest.
+ */
+static u32 compress_mpidr(unsigned long mpidr)
+{
+	u32 ret;
+
+	ret = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+	ret |= MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8;
+	ret |= MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16;
+	ret |= MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24;
+
+	return ret;
+}
+
+static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
+					      gpa_t addr, unsigned int len)
+{
+	unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
+	int target_vcpu_id = vcpu->vcpu_id;
+	u64 value;
+
+	value = (u64)compress_mpidr(mpidr) << 32;
+	value |= ((target_vcpu_id & 0xffff) << 8);
+	if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
+		value |= GICR_TYPER_LAST;
+
+	return extract_bytes(value, addr & 7, len);
+}
+
+static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
+					     gpa_t addr, unsigned int len)
+{
+	u32 value;
+
+	value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+	return extract_bytes(value, addr & 3, len);
+}
+
+/*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
  * block. Trying to set private IRQs in this block gets ignored.
@@ -127,9 +167,9 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
 	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
+		vgic_mmio_read_v3r_iidr, vgic_mmio_write_wi, 4),
 	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
+		vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, 8),
 	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
 	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:45 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:45 +0100
Subject: [PATCH v3 32/55] KVM: arm/arm64: vgic-new: Add GICv3 MMIO handling
 framework
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-33-git-send-email-andre.przywara@arm.com>

Create a new file called vgic-mmio-v3.c and describe the GICv3
distributor and redistributor registers there.
This adds a special macro to deal with the split of SGI/PPI in the
redistributor and SPIs in the distributor, which allows us to reuse
the existing GICv2 handlers for those registers which are compatible.
Also we provide a function to deal with the registration of the two
separate redistributor frames per VCPU.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog RFC..v1:
- adapt to new MMIO registration approach:
  register one device for the distributor and two for each VCPU
- implement special handling for private interrupts
- remove empty stub functions
- make IGROUPR return RAO

Changelog v1 .. v2:
- adapt to new framework, introduce vgic-mmio-v3.c
- remove userland register access functions (for now)
- precompute .len when describing a VGIC register
- add missed pointer incrementation on registering redist regions
- replace _nyi stub functions with raz/wi versions

Changelog v2 .. v3:
- replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h
- add prototype and stub code for vgic_register_redist_iodevs
- rename register struct variables _rdbase_ and _sgibase_

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
 virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
 virt/kvm/arm/vgic/vgic.h         |   7 ++
 4 files changed, 205 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
new file mode 100644
index 0000000..06c7ec5
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -0,0 +1,191 @@
+/*
+ * VGICv3 MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irqchip/arm-gic-v3.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include <asm/kvm_emulate.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+/*
+ * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
+ * redistributors, while SPIs are covered by registers in the distributor
+ * block. Trying to set private IRQs in this block gets ignored.
+ * We take some special care here to fix the calculation of the register
+ * offset.
+ */
+#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = bpi,					\
+		.len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8,		\
+		.read = vgic_mmio_read_raz,				\
+		.write = vgic_mmio_write_wi,				\
+	}, {								\
+		.reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8,	\
+		.bits_per_irq = bpi,					\
+		.len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
+		.read = read_ops,					\
+		.write = write_ops,					\
+	}
+
+static const struct vgic_register_region vgic_v3_dist_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
+		vgic_mmio_read_config, vgic_mmio_write_config, 2),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 64),
+	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
+};
+
+static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
+	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
+	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
+	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
+	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
+	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
+};
+
+static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 4),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 4),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 4),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 4),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 4),
+	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 32),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
+		vgic_mmio_read_config, vgic_mmio_write_config, 8),
+	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
+	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
+};
+
+unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
+{
+	dev->regions = vgic_v3_dist_registers;
+	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
+
+	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
+
+	return SZ_64K;
+}
+
+int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
+{
+	int nr_vcpus = atomic_read(&kvm->online_vcpus);
+	struct kvm_vcpu *vcpu;
+	struct vgic_io_device *devices, *device;
+	int c, ret = 0;
+
+	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
+			  GFP_KERNEL);
+	if (!devices)
+		return -ENOMEM;
+
+	device = devices;
+	kvm_for_each_vcpu(c, vcpu, kvm) {
+		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
+		device->base_addr = redist_base_address;
+		device->regions = vgic_v3_rdbase_registers;
+		device->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
+		device->redist_vcpu = vcpu;
+
+		mutex_lock(&kvm->slots_lock);
+		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
+					      redist_base_address,
+					      SZ_64K, &device->dev);
+		mutex_unlock(&kvm->slots_lock);
+
+		if (ret)
+			break;
+
+		device++;
+		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
+		device->base_addr = redist_base_address + SZ_64K;
+		device->regions = vgic_v3_sgibase_registers;
+		device->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
+		device->redist_vcpu = vcpu;
+
+		mutex_lock(&kvm->slots_lock);
+		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
+					      redist_base_address + SZ_64K,
+					      SZ_64K, &device->dev);
+		mutex_unlock(&kvm->slots_lock);
+		if (ret) {
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2].dev);
+			break;
+		}
+		device++;
+		redist_base_address += 2 * SZ_64K;
+	}
+
+	if (ret) {
+		for (c--; c >= 0; c--) {
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2].dev);
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2 + 1].dev);
+		}
+		kfree(devices);
+	} else {
+		kvm->arch.vgic.redist_iodevs = devices;
+	}
+
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 19fed56..d1b88d2 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -502,6 +502,11 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 	case VGIC_V2:
 		len = vgic_v2_init_dist_iodev(io_device);
 		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case VGIC_V3:
+		len = vgic_v3_init_dist_iodev(io_device);
+		break;
+#endif
 	default:
 		BUG_ON(1);
 	}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 884eb71..3585ac6 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -123,4 +123,6 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
 
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
+unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
+
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index cf62015..39a8a65 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -40,6 +40,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
 {
@@ -61,6 +62,12 @@ static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 }
+
+static inline int vgic_register_redist_iodevs(struct kvm *kvm,
+					      gpa_t dist_base_address)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:50 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:50 +0100
Subject: [PATCH v3 37/55] KVM: arm/arm64: vgic-new: Add GICv3 SGI system
 register trap handler
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-38-git-send-email-andre.przywara@arm.com>

In contrast to GICv2 SGIs in a GICv3 implementation are not triggered
by a MMIO write, but with a system register write. KVM knows about
that register already, we just need to implement the handler and wire
it up to the core KVM/ARM code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- add comment about SGI_AFFINITY_LEVEL macro

 include/kvm/vgic/vgic.h          |   8 +++
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 106 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 4ec1270..2c43eb8 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -209,6 +209,14 @@ bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
 
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
+#else
+static inline void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
+{
+}
+#endif
+
 /**
  * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
  *
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 3bcc2c4..af12592 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -356,3 +356,109 @@ int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
 
 	return ret;
 }
+
+/*
+ * Compare a given affinity (level 1-3 and a level 0 mask, from the SGI
+ * generation register ICC_SGI1R_EL1) with a given VCPU.
+ * If the VCPU's MPIDR matches, return the level0 affinity, otherwise
+ * return -1.
+ */
+static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct kvm_vcpu *vcpu)
+{
+	unsigned long affinity;
+	int level0;
+
+	/*
+	 * Split the current VCPU's MPIDR into affinity level 0 and the
+	 * rest as this is what we have to compare against.
+	 */
+	affinity = kvm_vcpu_get_mpidr_aff(vcpu);
+	level0 = MPIDR_AFFINITY_LEVEL(affinity, 0);
+	affinity &= ~MPIDR_LEVEL_MASK;
+
+	/* bail out if the upper three levels don't match */
+	if (sgi_aff != affinity)
+		return -1;
+
+	/* Is this VCPU's bit set in the mask ? */
+	if (!(sgi_cpu_mask & BIT(level0)))
+		return -1;
+
+	return level0;
+}
+
+/*
+ * The ICC_SGI* registers encode the affinity differently from the MPIDR,
+ * so provide a wrapper to use the existing defines to isolate a certain
+ * affinity level.
+ */
+#define SGI_AFFINITY_LEVEL(reg, level) \
+	((((reg) & ICC_SGI1R_AFFINITY_## level ##_MASK) \
+	>> ICC_SGI1R_AFFINITY_## level ##_SHIFT) << MPIDR_LEVEL_SHIFT(level))
+
+/**
+ * vgic_v3_dispatch_sgi - handle SGI requests from VCPUs
+ * @vcpu: The VCPU requesting a SGI
+ * @reg: The value written into the ICC_SGI1R_EL1 register by that VCPU
+ *
+ * With GICv3 (and ARE=1) CPUs trigger SGIs by writing to a system register.
+ * This will trap in sys_regs.c and call this function.
+ * This ICC_SGI1R_EL1 register contains the upper three affinity levels of the
+ * target processors as well as a bitmask of 16 Aff0 CPUs.
+ * If the interrupt routing mode bit is not set, we iterate over all VCPUs to
+ * check for matching ones. If this bit is set, we signal all, but not the
+ * calling VCPU.
+ */
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
+{
+	struct kvm *kvm = vcpu->kvm;
+	struct kvm_vcpu *c_vcpu;
+	u16 target_cpus;
+	u64 mpidr;
+	int sgi, c;
+	int vcpu_id = vcpu->vcpu_id;
+	bool broadcast;
+
+	sgi = (reg & ICC_SGI1R_SGI_ID_MASK) >> ICC_SGI1R_SGI_ID_SHIFT;
+	broadcast = reg & BIT(ICC_SGI1R_IRQ_ROUTING_MODE_BIT);
+	target_cpus = (reg & ICC_SGI1R_TARGET_LIST_MASK) >> ICC_SGI1R_TARGET_LIST_SHIFT;
+	mpidr = SGI_AFFINITY_LEVEL(reg, 3);
+	mpidr |= SGI_AFFINITY_LEVEL(reg, 2);
+	mpidr |= SGI_AFFINITY_LEVEL(reg, 1);
+
+	/*
+	 * We iterate over all VCPUs to find the MPIDRs matching the request.
+	 * If we have handled one CPU, we clear its bit to detect early
+	 * if we are already finished. This avoids iterating through all
+	 * VCPUs when most of the times we just signal a single VCPU.
+	 */
+	kvm_for_each_vcpu(c, c_vcpu, kvm) {
+		struct vgic_irq *irq;
+
+		/* Exit early if we have dealt with all requested CPUs */
+		if (!broadcast && target_cpus == 0)
+			break;
+
+		/* Don't signal the calling VCPU */
+		if (broadcast && c == vcpu_id)
+			continue;
+
+		if (!broadcast) {
+			int level0;
+
+			level0 = match_mpidr(mpidr, target_cpus, c_vcpu);
+			if (level0 == -1)
+				continue;
+
+			/* remove this matching VCPU from the mask */
+			target_cpus &= ~BIT(level0);
+		}
+
+		irq = vgic_get_irq(vcpu->kvm, c_vcpu, sgi);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:46:04 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:46:04 +0100
Subject: [PATCH v3 51/55] KVM: arm/arm64: vgic-new: vgic_init: implement
 map_resources
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-52-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

map_resources is the last initialization step. It is executed on
1st VCPU run. At that stage the code checks the userspace has provided
the base addresses for the relevant VGIC regions, which depend on
the type of VGIC that is exposed to the guest.

The function also forces the vgic_init if it has not been executed yet
(only allowed for VGIC v2).

for GICv2, The VGIC CPU interface is mapped onto the GIC virtual CPU
interface.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 include/kvm/vgic/vgic.h       |  1 +
 virt/kvm/arm/vgic/vgic-init.c | 27 +++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   | 47 +++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c   | 44 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h      |  7 +++++++
 5 files changed, 126 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 538078a..07c3011 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -208,6 +208,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type);
 void kvm_vgic_destroy(struct kvm *kvm);
 void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
+int kvm_vgic_map_resources(struct kvm *kvm);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 3f9c137..7fefb12 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -321,6 +321,33 @@ int vgic_lazy_init(struct kvm *kvm)
 	return ret;
 }
 
+/* RESOURCE MAPPING */
+
+/**
+ * Map the MMIO regions depending on the VGIC model exposed to the guest
+ * called on the first VCPU run.
+ * Also map the virtual CPU interface into the VM.
+ * v2/v3 derivatives call vgic_init if not already done.
+ * Completion can be tested by vgic_ready
+ */
+int kvm_vgic_map_resources(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	int ret = 0;
+
+	mutex_lock(&kvm->lock);
+	if (!irqchip_in_kernel(kvm))
+		goto out;
+
+	if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+		ret = vgic_v2_map_resources(kvm);
+	else
+		ret = vgic_v3_map_resources(kvm);
+out:
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 48aa877..1e411f5 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -216,6 +216,53 @@ void vgic_v2_enable(struct kvm_vcpu *vcpu)
 {
 }
 
+int vgic_v2_map_resources(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	int ret = 0;
+
+	if (vgic_ready(kvm))
+		goto out;
+
+	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
+	    IS_VGIC_ADDR_UNDEF(dist->vgic_cpu_base)) {
+		kvm_err("Need to set vgic cpu and dist addresses first\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	/*
+	 * Initialize the vgic if this hasn't already been done on demand by
+	 * accessing the vgic state from userspace.
+	 */
+	ret = vgic_init(kvm);
+	if (ret) {
+		kvm_err("Unable to initialize VGIC dynamic data structures\n");
+		goto out;
+	}
+
+	ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V2);
+	if (ret) {
+		kvm_err("Unable to register VGIC MMIO regions\n");
+		goto out;
+	}
+
+	ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base,
+				    kvm_vgic_global_state.vcpu_base,
+				    KVM_VGIC_V2_CPU_SIZE, true);
+	if (ret) {
+		kvm_err("Unable to remap VGIC CPU to VCPU\n");
+		goto out;
+	}
+
+	dist->ready = true;
+
+out:
+	if (ret)
+		kvm_vgic_destroy(kvm);
+	return ret;
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 7cab5b9..4bfd42a 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -200,6 +200,50 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
 }
 
+int vgic_v3_map_resources(struct kvm *kvm)
+{
+	int ret = 0;
+	struct vgic_dist *dist = &kvm->arch.vgic;
+
+	if (vgic_ready(kvm))
+		goto out;
+
+	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
+	    IS_VGIC_ADDR_UNDEF(dist->vgic_redist_base)) {
+		kvm_err("Need to set vgic distributor addresses first\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	/*
+	 * For a VGICv3 we require the userland to explicitly initialize
+	 * the VGIC before we need to use it.
+	 */
+	if (!vgic_initialized(kvm)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V3);
+	if (ret) {
+		kvm_err("Unable to register VGICv3 dist MMIO regions\n");
+		goto out;
+	}
+
+	ret = vgic_register_redist_iodevs(kvm, dist->vgic_redist_base);
+	if (ret) {
+		kvm_err("Unable to register VGICv3 redist MMIO regions\n");
+		goto out;
+	}
+
+	dist->ready = true;
+
+out:
+	if (ret)
+		kvm_vgic_destroy(kvm);
+	return ret;
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index cad04eb..5c7dc99 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -45,6 +45,7 @@ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_enable(struct kvm_vcpu *vcpu);
 int vgic_v2_probe(struct device_node *vgic_node);
+int vgic_v2_map_resources(struct kvm *kvm);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -58,6 +59,7 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_enable(struct kvm_vcpu *vcpu);
 int vgic_v3_probe(struct device_node *vgic_node);
+int vgic_v3_map_resources(struct kvm *kvm);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -100,6 +102,11 @@ static inline int vgic_v3_probe(struct device_node *vgic_node)
 	return -ENODEV;
 }
 
+static inline int vgic_v3_map_resources(struct kvm *kvm)
+{
+	return -ENODEV;
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:57 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:57 +0100
Subject: [PATCH v3 44/55] KVM: arm/arm64: vgic-new: Export register access
 interface
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-45-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Userland can access the emulated GIC to save and restore its state
for initialization or migration purposes.
The kvm_io_bus API requires an absolute gpa, which does not fit the
KVM_DEV_ARM_VGIC_GRP_DIST_REGS user API, that only provides relative
offsets. So we provide a wrapper to plug into our MMIO framework and
find the respective register handler.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework
- handle endianess explicitly

Changelog v2 .. v3:
- wrap accessor function for easier reusage later
- moved from earlier in the series

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 36 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 2 files changed, 38 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index cf8fee9..c453e6f 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -280,3 +280,39 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 
 	return -ENXIO;
 }
+
+/*
+ * When userland tries to access the VGIC register handlers, we need to
+ * create a usable struct vgic_io_device to be passed to the handlers and we
+ * have to set up a buffer similar to what would have happened if a guest MMIO
+ * access occurred, including doing endian conversions on BE systems.
+ */
+static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
+			bool is_write, int offset, u32 *val)
+{
+	unsigned int len = 4;
+	u8 buf[4];
+	int ret;
+
+	if (is_write) {
+		vgic_data_host_to_mmio_bus(buf, len, *val);
+		ret = kvm_io_gic_ops.write(vcpu, &dev->dev, offset, len, buf);
+	} else {
+		ret = kvm_io_gic_ops.read(vcpu, &dev->dev, offset, len, buf);
+		if (!ret)
+			*val = vgic_data_mmio_bus_to_host(buf, len);
+	}
+
+	return ret;
+}
+
+int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			 int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_dist_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_dist_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index a4397f9..bc5750e 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -37,6 +37,8 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
+int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			 int offset, u32 *val);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:34 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:34 +0100
Subject: [PATCH v3 21/55] KVM: arm/arm64: vgic-new: Add MMIO handling framework
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-22-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Add an MMIO handling framework to the VGIC emulation:
Each register is described by its offset, size (or number of bits per
IRQ, if applicable) and the read/write handler functions. We provide
initialization macros to describe each GIC register later easily.

Separate dispatch functions for read and write accesses are connected
to the kvm_io_bus framework and binary-search for the responsible
register handler based on the offset address within the region.
We convert the incoming data (referenced by a pointer) to the host's
endianess and use pass-by-value to hand the data over to the actual
handler functions.

The register handler prototype and the endianess conversion are
courtesy of Christoffer Dall.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- rework MMIO dispatching to use only one kvm_io_bus device
- document purpose of register region macros
- rename "this" parameter to "dev"
- change IGROUPR to be RAO (returning 1 => Group1 IRQs)

Changelog v1 .. v2:
* MASSIVE rework:
- store register_region pointer in kvm_io_bus linked struct
- replace write_mask_xxx functions with extract_bytes() implementation
- change handler functions' prototypes to take and return unsigned long
- use binary search to find matching register handler
- convert endianess of input data in dispatch_mmio_xxx functions
- improve readability of register initializer macros
- remove any GICv2/GICv3 specific functions from vgic-mmio.c
- rename file from vgic_mmio.c to vgic-mmio.c

Changelog v2 .. v3:
- replace inclusion of vgic/vgic.h with arm_vgic.h

 include/kvm/vgic/vgic.h       |  13 ++++
 virt/kvm/arm/vgic/vgic-mmio.c | 171 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h |  77 +++++++++++++++++++
 3 files changed, 261 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 2615205..4ec1270 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -106,6 +106,16 @@ struct vgic_irq {
 	enum vgic_irq_config config;	/* Level or edge */
 };
 
+struct vgic_register_region;
+
+struct vgic_io_device {
+	gpa_t base_addr;
+	struct kvm_vcpu *redist_vcpu;
+	const struct vgic_register_region *regions;
+	int nr_regions;
+	struct kvm_io_device dev;
+};
+
 struct vgic_dist {
 	bool			in_kernel;
 	bool			ready;
@@ -132,6 +142,9 @@ struct vgic_dist {
 	bool			enabled;
 
 	struct vgic_irq		*spis;
+
+	struct vgic_io_device	dist_iodev;
+	struct vgic_io_device	*redist_iodevs;
 };
 
 struct vgic_v2_cpu_if {
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
new file mode 100644
index 0000000..f5628cb
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -0,0 +1,171 @@
+/*
+ * VGIC MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/bsearch.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+/* extract @num bytes at @offset bytes offset in data */
+unsigned long extract_bytes(unsigned long data,
+			    unsigned int offset, unsigned int num)
+{
+	return (data >> (offset * 8)) & GENMASK_ULL(num * 8 - 1, 0);
+}
+
+unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len)
+{
+	return 0;
+}
+
+unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len)
+{
+	return -1UL;
+}
+
+void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
+			unsigned int len, unsigned long val)
+{
+	/* Ignore */
+}
+
+static int match_region(const void *key, const void *elt)
+{
+	const unsigned int offset = (unsigned long)key;
+	const struct vgic_register_region *region = elt;
+
+	if (offset < region->reg_offset)
+		return -1;
+
+	if (offset >= region->reg_offset + region->len)
+		return 1;
+
+	return 0;
+}
+
+/* Find the proper register handler entry given a certain address offset. */
+static const struct vgic_register_region *
+vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
+		      unsigned int offset)
+{
+	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
+		       sizeof(region[0]), match_region);
+}
+
+/*
+ * kvm_mmio_read_buf() returns a value in a format where it can be converted
+ * to a byte array and be directly observed as the guest wanted it to appear
+ * in memory if it had done the store itself, which is LE for the GIC, as the
+ * guest knows the GIC is always LE.
+ *
+ * We convert this value to the CPUs native format to deal with it as a data
+ * value.
+ */
+unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len)
+{
+	unsigned long data = kvm_mmio_read_buf(val, len);
+
+	switch (len) {
+	case 1:
+		return data;
+	case 2:
+		return le16_to_cpu(data);
+	case 4:
+		return le32_to_cpu(data);
+	default:
+		return le64_to_cpu(data);
+	}
+}
+
+/*
+ * kvm_mmio_write_buf() expects a value in a format such that if converted to
+ * a byte array it is observed as the guest would see it if it could perform
+ * the load directly.  Since the GIC is LE, and the guest knows this, the
+ * guest expects a value in little endian format.
+ *
+ * We convert the data value from the CPUs native format to LE so that the
+ * value is returned in the proper format.
+ */
+void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
+				unsigned long data)
+{
+	switch (len) {
+	case 1:
+		break;
+	case 2:
+		data = cpu_to_le16(data);
+		break;
+	case 4:
+		data = cpu_to_le32(data);
+		break;
+	default:
+		data = cpu_to_le64(data);
+	}
+
+	kvm_mmio_write_buf(buf, len, data);
+}
+
+static
+struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
+{
+	return container_of(dev, struct vgic_io_device, dev);
+}
+
+static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
+			      gpa_t addr, int len, void *val)
+{
+	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
+	const struct vgic_register_region *region;
+	struct kvm_vcpu *r_vcpu;
+	unsigned long data;
+
+	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
+				       addr - iodev->base_addr);
+	if (!region)
+		return -EOPNOTSUPP;
+
+	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
+	data = region->read(r_vcpu, addr, len);
+	vgic_data_host_to_mmio_bus(val, len, data);
+	return 0;
+}
+
+static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
+			       gpa_t addr, int len, const void *val)
+{
+	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
+	const struct vgic_register_region *region;
+	struct kvm_vcpu *r_vcpu;
+	unsigned long data = vgic_data_mmio_bus_to_host(val, len);
+
+	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
+				       addr - iodev->base_addr);
+	if (!region)
+		return -EOPNOTSUPP;
+
+	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
+	region->write(r_vcpu, addr, len, data);
+	return 0;
+}
+
+struct kvm_io_device_ops kvm_io_gic_ops = {
+	.read = dispatch_mmio_read,
+	.write = dispatch_mmio_write,
+};
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
new file mode 100644
index 0000000..18d3869
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __KVM_ARM_VGIC_MMIO_H__
+#define __KVM_ARM_VGIC_MMIO_H__
+
+struct vgic_register_region {
+	unsigned int reg_offset;
+	unsigned int len;
+	unsigned int bits_per_irq;
+	unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr,
+			      unsigned int len);
+	void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
+		      unsigned long val);
+};
+
+extern struct kvm_io_device_ops kvm_io_gic_ops;
+
+/*
+ * Some VGIC registers store per-IRQ information, with a different number
+ * of bits per IRQ. For those registers this macro is used.
+ * The _WITH_LENGTH version instantiates registers with a fixed length
+ * and is mutually exclusive with the _PER_IRQ version.
+ */
+#define REGISTER_DESC_WITH_BITS_PER_IRQ(off, read_ops, write_ops, bpi)	\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = bpi,					\
+		.len = bpi * 1024 / 8,					\
+		.read = read_ops,					\
+		.write = write_ops,					\
+	}
+
+#define REGISTER_DESC_WITH_LENGTH(off, read_ops, write_ops, length)	\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = 0,					\
+		.len = length,						\
+		.read = read_ops,					\
+		.write = write_ops,					\
+	}
+
+int kvm_vgic_register_mmio_region(struct kvm *kvm, struct kvm_vcpu *vcpu,
+				  struct vgic_register_region *reg_desc,
+				  struct vgic_io_device *region,
+				  int nr_irqs, bool offset_private);
+
+unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len);
+
+void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
+				unsigned long data);
+
+unsigned long extract_bytes(unsigned long data,
+			    unsigned int offset, unsigned int num);
+
+unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len);
+
+unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
+			unsigned int len, unsigned long val);
+
+#endif
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:46 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:46 +0100
Subject: [PATCH v3 33/55] KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR,
 TYPER handlers
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-34-git-send-email-andre.przywara@arm.com>

As in the GICv2 emulation we handle those three registers in one
function.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- kick VCPUs if distributor gets enabled

Changelog v1 .. v2:
- rewrite write handler to use switch statement

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 50 +++++++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 06c7ec5..5f4558c 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -22,6 +22,54 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 value = 0;
+
+	switch (addr & 0x0c) {
+	case GICD_CTLR:
+		if (vcpu->kvm->arch.vgic.enabled)
+			value |= GICD_CTLR_ENABLE_SS_G1;
+		value |= GICD_CTLR_ARE_NS | GICD_CTLR_DS;
+		break;
+	case GICD_TYPER:
+		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+		value = (value >> 5) - 1;
+		value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19;
+		break;
+	case GICD_IIDR:
+		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+		break;
+	default:
+		return 0;
+	}
+
+	return extract_bytes(value, addr & 3, len);
+}
+
+static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	switch (addr & 0x0c) {
+	case GICD_CTLR:
+		if (!(addr & 1)) {
+			struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+			bool was_enabled = dist->enabled;
+
+			dist->enabled = val & GICD_CTLR_ENABLE_SS_G1;
+
+			if (!was_enabled && dist->enabled)
+				vgic_kick_vcpus(vcpu->kvm);
+		}
+		break;
+	case GICD_TYPER:
+	case GICD_IIDR:
+		return;
+	}
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -46,7 +94,7 @@
 
 static const struct vgic_register_region vgic_v3_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
+		vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc, 16),
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 39a8a65..635e2e2 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,8 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define INTERRUPT_ID_BITS_SPIS	10
+
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:48 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:48 +0100
Subject: [PATCH v3 35/55] KVM: arm/arm64: vgic-new: Add GICv3 IDREGS register
 handler
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-36-git-send-email-andre.przywara@arm.com>

We implement the only one ID register that is required by the
architecture, also this is the one that Linux actually checks.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index d137242..48fba9c 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -110,6 +110,22 @@ static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
 	return extract_bytes(value, addr & 3, len);
 }
 
+static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu,
+					      gpa_t addr, unsigned int len)
+{
+	u32 regnr = (addr & 0x3f) - (GICD_IDREGS & 0x3f);
+	u32 reg = 0;
+
+	switch (regnr + GICD_IDREGS) {
+	case GICD_PIDR2:
+		/* report a GICv3 compliant implementation */
+		reg = 0x3b;
+		break;
+	}
+
+	return extract_bytes(reg, addr & 3, len);
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -160,7 +176,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 64),
 	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
+		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48),
 };
 
 static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
@@ -175,7 +191,7 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
 	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
+		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48),
 };
 
 static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:49 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:49 +0100
Subject: [PATCH v3 36/55] KVM: arm/arm64: vgic-new: Add GICv3 IROUTER register
 handlers
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-37-git-send-email-andre.przywara@arm.com>

Since GICv3 supports much more than the 8 CPUs the GICv2 ITARGETSR
register can handle, the new IROUTER register covers the whole range
of possible target (V)CPUs by using the same MPIDR that the cores
report themselves.
In addition to translating this MPIDR into a vcpu pointer we store
the originally written value as well. The architecture allows to
write any values into the register, which must be read back as written.

Since we don't support affinity level 3, we don't need to take care
about the upper word of this 64-bit register, which simplifies the
handling a bit.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- fold in and simplify vgic_v3_irq_change_affinity

Changelog v1 .. v2:
- adapt to new MMIO framework

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 65 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 64 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 48fba9c..3bcc2c4 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -86,6 +86,69 @@ static u32 compress_mpidr(unsigned long mpidr)
 	return ret;
 }
 
+static unsigned long decompress_mpidr(u32 value)
+{
+	unsigned long mpidr;
+
+	mpidr  = ((value >>  0) & 0xFF) << MPIDR_LEVEL_SHIFT(0);
+	mpidr |= ((value >>  8) & 0xFF) << MPIDR_LEVEL_SHIFT(1);
+	mpidr |= ((value >> 16) & 0xFF) << MPIDR_LEVEL_SHIFT(2);
+	mpidr |= (u64)((value >> 24) & 0xFF) << MPIDR_LEVEL_SHIFT(3);
+
+	return mpidr;
+}
+
+static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	int intid = (addr & 0x1fff) / 8;
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+	unsigned long mpidr;
+
+	if (!irq)
+		return 0;
+
+	mpidr = decompress_mpidr(irq->mpidr);
+	return extract_bytes(mpidr, addr & 7, len);
+}
+
+static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	int intid = (addr & 0x1fff) / 8;
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+	unsigned long mask = 0xffffffff;	/* upper word is WI */
+	u64 mpidr;
+
+	if (!irq)
+		return;
+
+	/*
+	 * There are only two supported options:
+	 * (1) aligned 64-bit access
+	 * (2) aligned 32-bit access
+	 *
+	 * TODO: make this check generic and move it to dispatch_...()
+	 */
+	if (len != 4 && len != 8)
+		return;
+
+
+	/* The upper word is WI for us since we don't implement Aff3. */
+	if (addr & 4)
+		return;
+
+	spin_lock(&irq->irq_lock);
+
+	mpidr = decompress_mpidr(irq->mpidr);
+	mpidr = (mpidr & ~mask) | (val & mask);
+	irq->mpidr = compress_mpidr(mpidr);
+	irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, mpidr);
+
+	spin_unlock(&irq->irq_lock);
+}
+
 static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
 					      gpa_t addr, unsigned int len)
 {
@@ -174,7 +237,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 64),
+		vgic_mmio_read_irouter, vgic_mmio_write_irouter, 64),
 	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
 		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48),
 };
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:51 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:51 +0100
Subject: [PATCH v3 38/55] KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM
 device ops registration
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-39-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch introduces the skeleton for the KVM device operations
associated to KVM_DEV_TYPE_ARM_VGIC_V2 and KVM_DEV_TYPE_ARM_VGIC_V3.

At that stage kvm_vgic_create is stubbed.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- rename vgic_kvm_device.c to vgic-kvm-device.c

Changelog v2 .. v3:
- replace inclusion of vgic/vgic.h with arm_vgic.h
- add kvm_register_vgic_device() prototype to this patch

 virt/kvm/arm/vgic/vgic-kvm-device.c | 108 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |   2 +
 2 files changed, 110 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-kvm-device.c

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
new file mode 100644
index 0000000..ff332f3
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -0,0 +1,108 @@
+/*
+ * VGIC: KVM DEVICE API
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ * Author: Marc Zyngier <marc.zyngier at arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+
+/* common helpers */
+
+static int vgic_create(struct kvm_device *dev, u32 type)
+{
+	return kvm_vgic_create(dev->kvm, type);
+}
+
+static void vgic_destroy(struct kvm_device *dev)
+{
+	kfree(dev);
+}
+
+void kvm_register_vgic_device(unsigned long type)
+{
+	switch (type) {
+	case KVM_DEV_TYPE_ARM_VGIC_V2:
+		kvm_register_device_ops(&kvm_arm_vgic_v2_ops,
+					KVM_DEV_TYPE_ARM_VGIC_V2);
+		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case KVM_DEV_TYPE_ARM_VGIC_V3:
+		kvm_register_device_ops(&kvm_arm_vgic_v3_ops,
+					KVM_DEV_TYPE_ARM_VGIC_V3);
+		break;
+#endif
+	}
+}
+
+/* V2 ops */
+
+static int vgic_v2_set_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v2_get_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v2_has_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+struct kvm_device_ops kvm_arm_vgic_v2_ops = {
+	.name = "kvm-arm-vgic-v2",
+	.create = vgic_create,
+	.destroy = vgic_destroy,
+	.set_attr = vgic_v2_set_attr,
+	.get_attr = vgic_v2_get_attr,
+	.has_attr = vgic_v2_has_attr,
+};
+
+/* V3 ops */
+
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+
+static int vgic_v3_set_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v3_get_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v3_has_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+struct kvm_device_ops kvm_arm_vgic_v3_ops = {
+	.name = "kvm-arm-vgic-v3",
+	.create = vgic_create,
+	.destroy = vgic_destroy,
+	.set_attr = vgic_v3_set_attr,
+	.get_attr = vgic_v3_get_attr,
+	.has_attr = vgic_v3_has_attr,
+};
+
+#endif /* CONFIG_KVM_ARM_VGIC_V3 */
+
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 635e2e2..e7c66a5 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -72,4 +72,6 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 }
 #endif
 
+void kvm_register_vgic_device(unsigned long type);
+
 #endif
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:53 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:53 +0100
Subject: [PATCH v3 40/55] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_CTRL
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-41-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_CTRL group API
featuring KVM_DEV_ARM_VGIC_CTRL_INIT attribute. The vgic_init
function is not yet implemented though.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 05ff925..e153f12 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -23,6 +23,8 @@
 static int vgic_set_common_attr(struct kvm_device *dev,
 				struct kvm_device_attr *attr)
 {
+	int r;
+
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
@@ -55,6 +57,16 @@ static int vgic_set_common_attr(struct kvm_device *dev,
 
 		return ret;
 	}
+	case KVM_DEV_ARM_VGIC_GRP_CTRL: {
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			mutex_lock(&dev->kvm->lock);
+			r = vgic_init(dev->kvm);
+			mutex_unlock(&dev->kvm->lock);
+			return r;
+		}
+		break;
+	}
 	}
 
 	return -ENXIO;
@@ -131,6 +143,11 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
+	case KVM_DEV_ARM_VGIC_GRP_CTRL:
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			return 0;
+		}
 	}
 	return -ENXIO;
 }
@@ -166,6 +183,11 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
+	case KVM_DEV_ARM_VGIC_GRP_CTRL:
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			return 0;
+		}
 	}
 	return -ENXIO;
 }
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:55 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:55 +0100
Subject: [PATCH v3 42/55] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_ADDR
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-43-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_ADDR group which
enables to set the base address of GIC regions as seen by the guest.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 38 +++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 493e941..0189c13 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -138,6 +138,17 @@ static int vgic_set_common_attr(struct kvm_device *dev,
 	int r;
 
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 addr;
+		unsigned long type = (unsigned long)attr->attr;
+
+		if (copy_from_user(&addr, uaddr, sizeof(addr)))
+			return -EFAULT;
+
+		r = kvm_vgic_addr(dev->kvm, type, &addr, true);
+		return (r == -ENODEV) ? -ENXIO : r;
+	}
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
 		u32 val;
@@ -190,6 +201,19 @@ static int vgic_get_common_attr(struct kvm_device *dev,
 	int r = -ENXIO;
 
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 addr;
+		unsigned long type = (unsigned long)attr->attr;
+
+		r = kvm_vgic_addr(dev->kvm, type, &addr, false);
+		if (r)
+			return (r == -ENODEV) ? -ENXIO : r;
+
+		if (copy_to_user(uaddr, &addr, sizeof(addr)))
+			return -EFAULT;
+		break;
+	}
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
 
@@ -253,6 +277,13 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR:
+		switch (attr->attr) {
+		case KVM_VGIC_V2_ADDR_TYPE_DIST:
+		case KVM_VGIC_V2_ADDR_TYPE_CPU:
+			return 0;
+		}
+		break;
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
@@ -293,6 +324,13 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR:
+		switch (attr->attr) {
+		case KVM_VGIC_V3_ADDR_TYPE_DIST:
+		case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+			return 0;
+		}
+		break;
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:44 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:44 +0100
Subject: [PATCH v3 31/55] KVM: arm/arm64: vgic-new: Add SGIPENDR register
 handlers
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-32-git-send-email-andre.przywara@arm.com>

As this register is v2 specific, its implementation lives entirely
in vgic-mmio-v2.c.
This register allows setting the source mask of an IPI.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- remove IRQ lock from read handler
- update pending bit on setting the first / clearing the last bit
- queue virtual IRQ if necessary

Changelog v1 .. v2:
- adapt to new MMIO framework

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 60 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 8f8ea57..8006ac0 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -148,6 +148,64 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->source << (i * 8);
+	}
+	return val;
+}
+
+static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len,
+				     unsigned long val)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->source &= ~((val >> (i * 8)) & 0xff);
+		if (!irq->source)
+			irq->pending = false;
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len,
+				     unsigned long val)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->source |= (val >> (i * 8)) & 0xff;
+
+		if (irq->source) {
+			irq->pending = true;
+			vgic_queue_irq_unlock(vcpu->kvm, irq);
+		} else {
+			spin_unlock(&irq->irq_lock);
+		}
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
@@ -174,9 +232,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
 		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
+		vgic_mmio_read_sgipend, vgic_mmio_write_sgipendc, 16),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
+		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16),
 };
 
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:56 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:56 +0100
Subject: [PATCH v3 43/55] KVM: arm/arm64: vgic-new: vgic_kvm_device: access to
 VGIC registers
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-44-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
access VGIC registers.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 34 ++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |  1 +
 3 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 0189c13..c952f6f 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -252,6 +252,21 @@ void kvm_register_vgic_device(unsigned long type)
 	}
 }
 
+/** vgic_attr_regs_access: allows user space to read/write VGIC registers
+ *
+ * @dev: kvm device handle
+ * @attr: kvm device attribute
+ * @reg: address the value is read or written
+ * @is_write: write flag
+ *
+ */
+static int vgic_attr_regs_access(struct kvm_device *dev,
+				 struct kvm_device_attr *attr,
+				 u32 *reg, bool is_write)
+{
+	return -ENXIO;
+}
+
 /* V2 ops */
 
 static int vgic_v2_set_attr(struct kvm_device *dev,
@@ -260,8 +275,23 @@ static int vgic_v2_set_attr(struct kvm_device *dev,
 	int ret;
 
 	ret = vgic_set_common_attr(dev, attr);
-	return ret;
+	if (ret != -ENXIO)
+		return ret;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 reg;
+
+		if (get_user(reg, uaddr))
+			return -EFAULT;
 
+		return vgic_attr_regs_access(dev, attr, &reg, true);
+	}
+	}
+
+	return -ENXIO;
 }
 
 static int vgic_v2_get_attr(struct kvm_device *dev,
@@ -270,7 +300,23 @@ static int vgic_v2_get_attr(struct kvm_device *dev,
 	int ret;
 
 	ret = vgic_get_common_attr(dev, attr);
-	return ret;
+	if (ret != -ENXIO)
+		return ret;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 reg = 0;
+
+		ret = vgic_attr_regs_access(dev, attr, &reg, false);
+		if (ret)
+			return ret;
+		return put_user(reg, uaddr);
+	}
+	}
+
+	return -ENXIO;
 }
 
 static int vgic_v2_has_attr(struct kvm_device *dev,
@@ -284,6 +330,9 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 			return 0;
 		}
 		break;
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		return vgic_v2_has_attr_regs(dev, attr);
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 8006ac0..cf8fee9 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -246,3 +246,37 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
 
 	return SZ_4K;
 }
+
+int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+	const struct vgic_register_region *regions;
+	gpa_t addr;
+	int nr_regions, i, len;
+
+	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+		regions = vgic_v2_dist_registers;
+		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
+		break;
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		return -ENXIO;		/* TODO: describe CPU i/f regs also */
+	default:
+		return -ENXIO;
+	}
+
+	for (i = 0; i < nr_regions; i++) {
+		if (regions[i].bits_per_irq)
+			len = (regions[i].bits_per_irq * nr_irqs) / 8;
+		else
+			len = regions[i].len;
+
+		if (regions[i].reg_offset <= addr &&
+		    regions[i].reg_offset + len > addr)
+			return 0;
+	}
+
+	return -ENXIO;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index c44ee01..a4397f9 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -36,6 +36,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:37 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:37 +0100
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-25-git-send-email-andre.przywara@arm.com>

As the enable register handlers are shared between the v2 and v3
emulation, their implementation goes into vgic-mmio.c, to be easily
referenced from the v3 emulation as well later.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- use lower bits of address to determine IRQ number
- remove TODO, confirmed to be fine

Changelog v1 .. v2:
- adapt to new MMIO framework

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
 virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
 3 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 69e96f7..448d1da 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -72,9 +72,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 41cf4f4..077ae86 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -46,6 +46,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 	/* Ignore */
 }
 
+/*
+ * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
+ * of the enabled bit, so there is only one function for both here.
+ */
+unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = (addr & 0x7f) * 8;
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->enabled)
+			value |= (1U << i);
+	}
+
+	return extract_bytes(value, addr & 3, len);
+}
+
+void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = (addr & 0x7f) * 8;
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		irq->enabled = true;
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
+void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = (addr & 0x7f) * 8;
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->enabled = false;
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 4f4dd2b..188909a 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -74,6 +74,17 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
 void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 			unsigned int len, unsigned long val);
 
+unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
+void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:31 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:31 +0100
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-19-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Processing maintenance interrupts and accessing the list registers
are dependent on the host's GIC version.
Introduce vgic-v2.c to contain GICv2 specific functions.
Implement the GICv2 specific code for syncing the emulation state
into the VGIC registers.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- remove explicit LR_STATE clearing on maintenance interrupt handling
- improve documentation for vgic_v2_populate_lr()
- remove WARN_ON on non-edge IRQs in maintenance interrupts
- simplify multi-CPU source SGI handling

Changelog v1 .. v2:
- inject the IRQ priority into the list register

Changelog v2 .. v3:
- cleanup diff containing rebase artifacts

 include/linux/irqchip/arm-gic.h |   1 +
 virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c        |   6 ++
 virt/kvm/arm/vgic/vgic.h        |   6 ++
 4 files changed, 191 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-v2.c

diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 9c94026..be0d26f 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -76,6 +76,7 @@
 #define GICH_LR_VIRTUALID		(0x3ff << 0)
 #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
 #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
+#define GICH_LR_PRIORITY_SHIFT		23
 #define GICH_LR_STATE			(3 << 28)
 #define GICH_LR_PENDING_BIT		(1 << 28)
 #define GICH_LR_ACTIVE_BIT		(1 << 29)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
new file mode 100644
index 0000000..4cee616
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/irqchip/arm-gic.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+/*
+ * Call this function to convert a u64 value to an unsigned long * bitmask
+ * in a way that works on both 32-bit and 64-bit LE and BE platforms.
+ *
+ * Warning: Calling this function may modify *val.
+ */
+static unsigned long *u64_to_bitmask(u64 *val)
+{
+#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
+	*val = (*val >> 32) | (*val << 32);
+#endif
+	return (unsigned long *)val;
+}
+
+void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+
+	if (cpuif->vgic_misr & GICH_MISR_EOI) {
+		u64 eisr = cpuif->vgic_eisr;
+		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
+		int lr;
+
+		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
+			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
+
+			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
+
+			kvm_notify_acked_irq(vcpu->kvm, 0,
+					     intid - VGIC_NR_PRIVATE_IRQS);
+
+			cpuif->vgic_elrsr |= 1ULL << lr;
+		}
+	}
+
+	/* check and disable underflow maintenance IRQ */
+	cpuif->vgic_hcr &= ~GICH_HCR_UIE;
+
+	/*
+	 * In the next iterations of the vcpu loop, if we sync the
+	 * vgic state after flushing it, but before entering the guest
+	 * (this happens for pending signals and vmid rollovers), then
+	 * make sure we don't pick up any old maintenance interrupts
+	 * here.
+	 */
+	cpuif->vgic_eisr = 0;
+}
+
+void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+
+	cpuif->vgic_hcr |= GICH_HCR_UIE;
+}
+
+/*
+ * transfer the content of the LRs back into the corresponding ap_list:
+ * - active bit is transferred as is
+ * - pending bit is
+ *   - transferred as is in case of edge sensitive IRQs
+ *   - set to the line-level (resample time) for level sensitive IRQs
+ */
+void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+	int lr;
+
+	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
+		u32 val = cpuif->vgic_lr[lr];
+		u32 intid = val & GICH_LR_VIRTUALID;
+		struct vgic_irq *irq;
+
+		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+
+		/* Always preserve the active bit */
+		irq->active = !!(val & GICH_LR_ACTIVE_BIT);
+
+		/* Edge is the only case where we preserve the pending bit */
+		if (irq->config == VGIC_CONFIG_EDGE &&
+		    (val & GICH_LR_PENDING_BIT)) {
+			irq->pending = true;
+
+			if (vgic_irq_is_sgi(intid)) {
+				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
+
+				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+				irq->source |= (1 << cpuid);
+			}
+		}
+
+		/* Clear soft pending state when level IRQs have been acked */
+		if (irq->config == VGIC_CONFIG_LEVEL &&
+		    !(val & GICH_LR_PENDING_BIT)) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+/*
+ * Populates the particular LR with the state of a given IRQ:
+ * - for an edge sensitive IRQ the pending state is cleared in struct vgic_irq
+ * - for a level sensitive IRQ the pending state value is unchanged;
+ *   it is dictated directly by the input level
+ *
+ * If @irq describes an SGI with multiple sources, we choose the
+ * lowest-numbered source VCPU and clear that bit in the source bitmap.
+ *
+ * The irq_lock must be held by the caller.
+ */
+void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
+{
+	u32 val = irq->intid;
+
+	if (irq->pending) {
+		val |= GICH_LR_PENDING_BIT;
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			irq->pending = false;
+
+		if (vgic_irq_is_sgi(irq->intid)) {
+			u32 src = ffs(irq->source);
+
+			BUG_ON(!src);
+			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
+			irq->source &= ~(1 << (src - 1));
+			if (irq->source)
+				irq->pending = true;
+		}
+	}
+
+	if (irq->active)
+		val |= GICH_LR_ACTIVE_BIT;
+
+	if (irq->hw) {
+		val |= GICH_LR_HW;
+		val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
+	} else {
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			val |= GICH_LR_EOI;
+	}
+
+	/* The GICv2 LR only holds five bits of priority. */
+	val |= (irq->priority >> 3) << GICH_LR_PRIORITY_SHIFT;
+
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = val;
+}
+
+void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index c6f8b9b..68d885c 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -397,10 +397,12 @@ retry:
 
 static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_process_maintenance(vcpu);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_fold_lr_state(vcpu);
 }
 
 /* Requires the ap_list_lock and the irq_lock to be held. */
@@ -409,14 +411,18 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
 {
 	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
 	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+	vgic_v2_populate_lr(vcpu, irq, lr);
 }
 
 static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
+	vgic_v2_clear_lr(vcpu, lr);
 }
 
 static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_set_underflow(vcpu);
 }
 
 static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 29b96b9..0db490e 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -22,4 +22,10 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
 
+void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
+void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
+void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
+void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
+void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+
 #endif
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:58 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:58 +0100
Subject: [PATCH v3 45/55] KVM: arm/arm64: vgic-new: Add userland access to
 VGIC dist registers
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-46-git-send-email-andre.przywara@arm.com>

Userland may want to save and restore the state of the in-kernel VGIC,
so we provide the code which takes a userland request and translate
that into calls to our MMIO framework.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 50 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index c952f6f..bb33af8 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -264,7 +264,55 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 				 struct kvm_device_attr *attr,
 				 u32 *reg, bool is_write)
 {
-	return -ENXIO;
+	gpa_t addr;
+	int cpuid, ret, c;
+	struct kvm_vcpu *vcpu, *tmp_vcpu;
+
+	cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
+		 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
+	vcpu = kvm_get_vcpu(dev->kvm, cpuid);
+	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+	mutex_lock(&dev->kvm->lock);
+
+	ret = vgic_init(dev->kvm);
+	if (ret)
+		goto out;
+
+	if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Ensure that no other VCPU is running by checking the vcpu->cpu
+	 * field.  If no other VPCUs are running we can safely access the VGIC
+	 * state, because even if another VPU is run after this point, that
+	 * VCPU will not touch the vgic state, because it will block on
+	 * getting the vgic->lock in kvm_vgic_sync_hwstate().
+	 */
+	kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm) {
+		if (unlikely(tmp_vcpu->cpu != -1)) {
+			ret = -EBUSY;
+			goto out;
+		}
+	}
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		ret = -EINVAL;
+		break;
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+out:
+	mutex_unlock(&dev->kvm->lock);
+	return ret;
 }
 
 /* V2 ops */
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:43 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:43 +0100
Subject: [PATCH v3 30/55] KVM: arm/arm64: vgic-new: Add SGIR register handler
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-31-git-send-email-andre.przywara@arm.com>

Triggering an IPI via this register is v2 specific, so the
implementation lives entirely in vgic-mmio-v2.c.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- silently return on illegal TargetListFilter value (=3)

Changelog v1 .. v2:
- adapt to new MMIO framework

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 888529e..8f8ea57 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -66,6 +66,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
+				 gpa_t addr, unsigned int len,
+				 unsigned long val)
+{
+	int nr_vcpus = atomic_read(&source_vcpu->kvm->online_vcpus);
+	int intid = val & 0xf;
+	int targets = (val >> 16) & 0xff;
+	int mode = (val >> 24) & 0x03;
+	int c;
+	struct kvm_vcpu *vcpu;
+
+	switch (mode) {
+	case 0x0:		/* as specified by targets */
+		break;
+	case 0x1:
+		targets = (1U << nr_vcpus) - 1;			/* all, ... */
+		targets &= ~(1U << source_vcpu->vcpu_id);	/* but self */
+		break;
+	case 0x2:		/* this very vCPU only */
+		targets = (1U << source_vcpu->vcpu_id);
+		break;
+	case 0x3:		/* reserved */
+		return;
+	}
+
+	kvm_for_each_vcpu(c, vcpu, source_vcpu->kvm) {
+		struct vgic_irq *irq;
+
+		if (!(targets & (1U << c)))
+			continue;
+
+		irq = vgic_get_irq(source_vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+		irq->source |= 1U << source_vcpu->vcpu_id;
+
+		vgic_queue_irq_unlock(source_vcpu->kvm, irq);
+	}
+}
+
 static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
 					   gpa_t addr, unsigned int len)
 {
@@ -131,7 +172,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
 		vgic_mmio_read_config, vgic_mmio_write_config, 2),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
+		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:59 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:59 +0100
Subject: [PATCH v3 46/55] KVM: arm/arm64: vgic-new: Add GICH_VMCR accessors
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-47-git-send-email-andre.przywara@arm.com>

Since the GIC CPU interface is always virtualized by the hardware,
we don't have CPU interface state information readily available in our
emulation if userland wants to save or restore it.
Fortunately the GIC hypervisor interface provides the VMCR register to
access the required virtual CPU interface bits.
Provide wrappers for GICv2 and GICv3 hosts to have access to this
register.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v2 .. v3:
- remove exported v2/v3 selector functions (as per Marc's patch)

 include/kvm/vgic/vgic.h     |  7 +++++++
 virt/kvm/arm/vgic/vgic-v2.c | 29 +++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c | 22 ++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h    | 14 ++++++++++++++
 4 files changed, 72 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 73cab36..cfc3640 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -171,6 +171,13 @@ struct vgic_v3_cpu_if {
 #endif
 };
 
+struct vgic_vmcr {
+	u32	ctlr;
+	u32	abpr;
+	u32	bpr;
+	u32	pmr;
+};
+
 struct vgic_cpu {
 	/* CPU vif control registers for world switch */
 	union {
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 4cee616..70cac63 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -176,3 +176,32 @@ void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
 	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
 }
+
+void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr;
+
+	vmcr  = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK;
+	vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) &
+		GICH_VMCR_ALIAS_BINPOINT_MASK;
+	vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) &
+		GICH_VMCR_BINPOINT_MASK;
+	vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) &
+		GICH_VMCR_PRIMASK_MASK;
+
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = vmcr;
+}
+
+void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr;
+
+	vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >>
+			GICH_VMCR_CTRL_SHIFT;
+	vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >>
+			GICH_VMCR_ALIAS_BINPOINT_SHIFT;
+	vmcrp->bpr  = (vmcr & GICH_VMCR_BINPOINT_MASK) >>
+			GICH_VMCR_BINPOINT_SHIFT;
+	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
+			GICH_VMCR_PRIMASK_SHIFT;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 43d1dd7..dca52b3 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -166,3 +166,25 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
 	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
 }
+
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr;
+
+	vmcr  = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK;
+	vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
+	vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
+	vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
+
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
+}
+
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
+
+	vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT;
+	vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
+	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
+	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index bc5750e..5260d23 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -39,6 +39,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val);
+void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -48,6 +50,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -71,6 +75,16 @@ static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 }
 
+static inline
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+}
+
+static inline
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:52 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:52 +0100
Subject: [PATCH v3 39/55] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_NR_IRQS
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-40-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_NR_IRQS group. This
modality is supported by both VGIC V2 and V3 KVM device as will be
other groups, hence the introduction of common helpers.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 83 +++++++++++++++++++++++++++++++++++--
 1 file changed, 79 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index ff332f3..05ff925 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -15,9 +15,69 @@
  */
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
+#include <linux/uaccess.h>
+#include "vgic.h"
 
 /* common helpers */
 
+static int vgic_set_common_attr(struct kvm_device *dev,
+				struct kvm_device_attr *attr)
+{
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 val;
+		int ret = 0;
+
+		if (get_user(val, uaddr))
+			return -EFAULT;
+
+		/*
+		 * We require:
+		 * - at least 32 SPIs on top of the 16 SGIs and 16 PPIs
+		 * - at most 1024 interrupts
+		 * - a multiple of 32 interrupts
+		 */
+		if (val < (VGIC_NR_PRIVATE_IRQS + 32) ||
+		    val > VGIC_MAX_RESERVED ||
+		    (val & 31))
+			return -EINVAL;
+
+		mutex_lock(&dev->kvm->lock);
+
+		if (vgic_ready(dev->kvm) || dev->kvm->arch.vgic.nr_spis)
+			ret = -EBUSY;
+		else
+			dev->kvm->arch.vgic.nr_spis =
+				val - VGIC_NR_PRIVATE_IRQS;
+
+		mutex_unlock(&dev->kvm->lock);
+
+		return ret;
+	}
+	}
+
+	return -ENXIO;
+}
+
+static int vgic_get_common_attr(struct kvm_device *dev,
+				struct kvm_device_attr *attr)
+{
+	int r = -ENXIO;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+
+		r = put_user(dev->kvm->arch.vgic.nr_spis +
+			     VGIC_NR_PRIVATE_IRQS, uaddr);
+		break;
+	}
+	}
+
+	return r;
+}
+
 static int vgic_create(struct kvm_device *dev, u32 type)
 {
 	return kvm_vgic_create(dev->kvm, type);
@@ -49,18 +109,29 @@ void kvm_register_vgic_device(unsigned long type)
 static int vgic_v2_set_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	int ret;
+
+	ret = vgic_set_common_attr(dev, attr);
+	return ret;
+
 }
 
 static int vgic_v2_get_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	int ret;
+
+	ret = vgic_get_common_attr(dev, attr);
+	return ret;
 }
 
 static int vgic_v2_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
+		return 0;
+	}
 	return -ENXIO;
 }
 
@@ -80,18 +151,22 @@ struct kvm_device_ops kvm_arm_vgic_v2_ops = {
 static int vgic_v3_set_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	return vgic_set_common_attr(dev, attr);
 }
 
 static int vgic_v3_get_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	return vgic_get_common_attr(dev, attr);
 }
 
 static int vgic_v3_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
+		return 0;
+	}
 	return -ENXIO;
 }
 
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:32 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:32 +0100
Subject: [PATCH v3 19/55] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-20-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

As the GICv3 virtual interface registers differ from their GICv2
siblings, we need different handlers for processing maintenance
interrupts and reading/writing to the LRs.
Implement the respective handler functions and connect them to
existing code to be called if the host is using a GICv3.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- remove outdated comment about the dist_lock
- add WARN_ON about LR_STATE not being 0 in maintenance interrupts

Changelog v1 .. v2:
- inject the IRQ priority into the list register

Changelog v2 .. v3:
- remove no longer needed irqchip/arm-gic.h inclusion

 include/linux/irqchip/arm-gic-v3.h |   1 +
 virt/kvm/arm/vgic/vgic-v3.c        | 168 +++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c           |  25 ++++--
 virt/kvm/arm/vgic/vgic.h           |  29 +++++++
 4 files changed, 218 insertions(+), 5 deletions(-)
 create mode 100644 virt/kvm/arm/vgic/vgic-v3.c

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index ec938d1..35e93cf 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -275,6 +275,7 @@
 #define ICH_LR_ACTIVE_BIT		(1ULL << 63)
 #define ICH_LR_PHYS_ID_SHIFT		32
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
+#define ICH_LR_PRIORITY_SHIFT		48
 
 /* These are for GICv2 emulation only */
 #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
new file mode 100644
index 0000000..43d1dd7
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -0,0 +1,168 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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/irqchip/arm-gic-v3.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+
+	if (cpuif->vgic_misr & ICH_MISR_EOI) {
+		unsigned long eisr_bmap = cpuif->vgic_eisr;
+		int lr;
+
+		for_each_set_bit(lr, &eisr_bmap, kvm_vgic_global_state.nr_lr) {
+			u32 intid;
+			u64 val = cpuif->vgic_lr[lr];
+
+			if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+				intid = val & ICH_LR_VIRTUAL_ID_MASK;
+			else
+				intid = val & GICH_LR_VIRTUALID;
+
+			WARN_ON(cpuif->vgic_lr[lr] & ICH_LR_STATE);
+
+			kvm_notify_acked_irq(vcpu->kvm, 0,
+					     intid - VGIC_NR_PRIVATE_IRQS);
+
+			cpuif->vgic_elrsr |= 1ULL << lr;
+		}
+
+		/*
+		 * In the next iterations of the vcpu loop, if we sync
+		 * the vgic state after flushing it, but before
+		 * entering the guest (this happens for pending
+		 * signals and vmid rollovers), then make sure we
+		 * don't pick up any old maintenance interrupts here.
+		 */
+		cpuif->vgic_eisr = 0;
+	}
+
+	cpuif->vgic_hcr &= ~ICH_HCR_UIE;
+}
+
+void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+
+	cpuif->vgic_hcr |= ICH_HCR_UIE;
+}
+
+void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+	int lr;
+
+	/* Assumes ap_list_lock held */
+
+	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
+		u64 val = cpuif->vgic_lr[lr];
+		u32 intid;
+		struct vgic_irq *irq;
+
+		if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+			intid = val & ICH_LR_VIRTUAL_ID_MASK;
+		else
+			intid = val & GICH_LR_VIRTUALID;
+		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+
+		/* Always preserve the active bit */
+		irq->active = !!(val & ICH_LR_ACTIVE_BIT);
+
+		/* Edge is the only case where we preserve the pending bit */
+		if (irq->config == VGIC_CONFIG_EDGE &&
+		    (val & ICH_LR_PENDING_BIT)) {
+			irq->pending = true;
+
+			if (vgic_irq_is_sgi(intid) &&
+			    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
+
+				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+				irq->source |= (1 << cpuid);
+			}
+		}
+
+		/* Clear soft pending state when level irqs have been acked */
+		if (irq->config == VGIC_CONFIG_LEVEL &&
+		    !(val & ICH_LR_PENDING_BIT)) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+/* Requires the irq to be locked already */
+void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
+{
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+	u64 val = irq->intid;
+
+	if (irq->pending) {
+		val |= ICH_LR_PENDING_BIT;
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			irq->pending = false;
+
+		if (vgic_irq_is_sgi(irq->intid) &&
+		    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+			u32 src = ffs(irq->source);
+
+			BUG_ON(!src);
+			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
+			irq->source &= ~(1 << (src - 1));
+			if (irq->source)
+				irq->pending = true;
+		}
+	}
+
+	if (irq->active)
+		val |= ICH_LR_ACTIVE_BIT;
+
+	if (irq->hw) {
+		val |= ICH_LR_HW;
+		val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
+	} else {
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			val |= ICH_LR_EOI;
+	}
+
+	/*
+	 * Currently all guest IRQs are Group1, as Group0 would result
+	 * in a FIQ in the guest, which it wouldn't expect.
+	 * Eventually we want to make this configurable, so we may
+	 * revisit this in the future.
+	 */
+	if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+		val |= ICH_LR_GROUP;
+
+	val |= (u64)irq->priority << ICH_LR_PRIORITY_SHIFT;
+
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = val;
+}
+
+void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 68d885c..64d5b45 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -397,12 +397,18 @@ retry:
 
 static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_process_maintenance(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_process_maintenance(vcpu);
+	else
+		vgic_v3_process_maintenance(vcpu);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_fold_lr_state(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_fold_lr_state(vcpu);
+	else
+		vgic_v3_fold_lr_state(vcpu);
 }
 
 /* Requires the ap_list_lock and the irq_lock to be held. */
@@ -412,17 +418,26 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
 	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
 	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
 
-	vgic_v2_populate_lr(vcpu, irq, lr);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_populate_lr(vcpu, irq, lr);
+	else
+		vgic_v3_populate_lr(vcpu, irq, lr);
 }
 
 static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
-	vgic_v2_clear_lr(vcpu, lr);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_clear_lr(vcpu, lr);
+	else
+		vgic_v3_clear_lr(vcpu, lr);
 }
 
 static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_set_underflow(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_set_underflow(vcpu);
+	else
+		vgic_v3_set_underflow(vcpu);
 }
 
 static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 0db490e..81b1a20 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -28,4 +28,33 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
+void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
+void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
+void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
+void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+#else
+static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_v3_populate_lr(struct kvm_vcpu *vcpu,
+				       struct vgic_irq *irq, int lr)
+{
+}
+
+static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+}
+
+static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
+{
+}
+#endif
+
 #endif
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:46:02 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:46:02 +0100
Subject: [PATCH v3 49/55] KVM: arm/arm64: vgic-new: vgic_init: implement
 vgic_create
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-50-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the vgic_creation function which is
called on CREATE_IRQCHIP VM IOCTL (v2 only) or KVM_CREATE_DEVICE

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 include/kvm/vgic/vgic.h       |  1 +
 virt/kvm/arm/vgic/vgic-init.c | 84 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index d144e3d..899b7b7 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -202,6 +202,7 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+int kvm_vgic_create(struct kvm *kvm, u32 type);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index f10997b..a150363 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -24,6 +24,90 @@
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
+/* CREATION */
+
+/**
+ * kvm_vgic_create: triggered by the instantiation of the VGIC device by
+ * user space, either through the legacy ARM specific VM IOCTL (CREATE_IRQCHIP)
+ * or through the generic VM IOCTL, KVM_CREATE_DEVICE API.
+ * Completion can be tested by irqchip_in_kernel
+ */
+int kvm_vgic_create(struct kvm *kvm, u32 type)
+{
+	int i, vcpu_lock_idx = -1, ret;
+	struct kvm_vcpu *vcpu;
+
+	mutex_lock(&kvm->lock);
+
+	if (irqchip_in_kernel(kvm)) {
+		ret = -EEXIST;
+		goto out;
+	}
+
+	/*
+	 * This function is also called by the KVM_CREATE_IRQCHIP handler,
+	 * which had no chance yet to check the availability of the GICv2
+	 * emulation. So check this here again. KVM_CREATE_DEVICE does
+	 * the proper checks already.
+	 */
+	if (type == KVM_DEV_TYPE_ARM_VGIC_V2 &&
+		!kvm_vgic_global_state.can_emulate_gicv2) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/*
+	 * Any time a vcpu is run, vcpu_load is called which tries to grab the
+	 * vcpu->mutex.  By grabbing the vcpu->mutex of all VCPUs we ensure
+	 * that no other VCPUs are run while we create the vgic.
+	 */
+	ret = -EBUSY;
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		if (!mutex_trylock(&vcpu->mutex))
+			goto out_unlock;
+		vcpu_lock_idx = i;
+	}
+
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		if (vcpu->arch.has_run_once)
+			goto out_unlock;
+	}
+	ret = 0;
+
+	if (type == KVM_DEV_TYPE_ARM_VGIC_V2)
+		kvm->arch.max_vcpus = VGIC_V2_MAX_CPUS;
+	else
+		kvm->arch.max_vcpus = VGIC_V3_MAX_CPUS;
+
+	if (atomic_read(&kvm->online_vcpus) > kvm->arch.max_vcpus) {
+		ret = -E2BIG;
+		goto out_unlock;
+	}
+
+	kvm->arch.vgic.in_kernel = true;
+	kvm->arch.vgic.vgic_model = type;
+
+	/*
+	 * kvm_vgic_global_state.vctrl_base is set on vgic probe (kvm_arch_init)
+	 * it is stored in distributor struct for asm save/restore purpose
+	 */
+	kvm->arch.vgic.vctrl_base = kvm_vgic_global_state.vctrl_base;
+
+	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
+	kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
+	kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
+
+out_unlock:
+	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
+		vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
+		mutex_unlock(&vcpu->mutex);
+	}
+
+out:
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:46:01 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:46:01 +0100
Subject: [PATCH v3 48/55] KVM: arm/arm64: vgic-new: vgic_init: implement
 kvm_vgic_hyp_init
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-49-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

Implements kvm_vgic_hyp_init and vgic_probe function.

The vgic_global struct is enriched with new fields populated
by those functions.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- rename vgic_init.c to vgic-init.c

Changelog v2 .. v3:
- include kvm/arm_vgic.h instead of kvm/vgic/vgic.h
- move ich_vtr_el2 variable into probe function

 include/kvm/vgic/vgic.h       |   1 +
 virt/kvm/arm/vgic/vgic-init.c | 122 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   |  90 +++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c   |  73 +++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h      |   7 +++
 5 files changed, 293 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-init.c

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index cfc3640..d144e3d 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -202,6 +202,7 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
new file mode 100644
index 0000000..f10997b
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/cpu.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
+#include "vgic.h"
+
+/* GENERIC PROBE */
+
+static void vgic_init_maintenance_interrupt(void *info)
+{
+	enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0);
+}
+
+static int vgic_cpu_notify(struct notifier_block *self,
+			   unsigned long action, void *cpu)
+{
+	switch (action) {
+	case CPU_STARTING:
+	case CPU_STARTING_FROZEN:
+		vgic_init_maintenance_interrupt(NULL);
+		break;
+	case CPU_DYING:
+	case CPU_DYING_FROZEN:
+		disable_percpu_irq(kvm_vgic_global_state.maint_irq);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block vgic_cpu_nb = {
+	.notifier_call = vgic_cpu_notify,
+};
+
+static irqreturn_t vgic_maintenance_handler(int irq, void *data)
+{
+	/*
+	 * We cannot rely on the vgic maintenance interrupt to be
+	 * delivered synchronously. This means we can only use it to
+	 * exit the VM, and we perform the handling of EOIed
+	 * interrupts on the exit path (see vgic_process_maintenance).
+	 */
+	return IRQ_HANDLED;
+}
+
+static const struct of_device_id vgic_ids[] = {
+	{ .compatible = "arm,cortex-a15-gic",	.data = vgic_v2_probe, },
+	{ .compatible = "arm,cortex-a7-gic",	.data = vgic_v2_probe, },
+	{ .compatible = "arm,gic-400",		.data = vgic_v2_probe, },
+	{ .compatible = "arm,gic-v3",		.data = vgic_v3_probe, },
+	{},
+};
+
+/**
+ * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable
+ * according to the host GIC model. Accordingly calls either
+ * vgic_v2/v3_probe which registers the KVM_DEVICE that can be
+ * instantiated by a guest later on .
+ */
+int kvm_vgic_hyp_init(void)
+{
+	const struct of_device_id *matched_id;
+	const int (*vgic_probe)(struct device_node *);
+	struct device_node *vgic_node;
+	int ret;
+
+	vgic_node = of_find_matching_node_and_match(NULL,
+						    vgic_ids, &matched_id);
+	if (!vgic_node) {
+		kvm_err("error: no compatible GIC node found\n");
+		return -ENODEV;
+	}
+
+	vgic_probe = matched_id->data;
+	ret = vgic_probe(vgic_node);
+	if (ret)
+		return ret;
+
+	ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
+				 vgic_maintenance_handler,
+				 "vgic", kvm_get_running_vcpus());
+	if (ret) {
+		kvm_err("Cannot register interrupt %d\n",
+			kvm_vgic_global_state.maint_irq);
+		return ret;
+	}
+
+	ret = __register_cpu_notifier(&vgic_cpu_nb);
+	if (ret) {
+		kvm_err("Cannot register vgic CPU notifier\n");
+		goto out_free_irq;
+	}
+
+	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
+
+	return 0;
+
+out_free_irq:
+	free_percpu_irq(kvm_vgic_global_state.maint_irq,
+			kvm_get_running_vcpus());
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 70cac63..91b69a4 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -17,6 +17,11 @@
 #include <linux/irqchip/arm-gic.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/kvm_mmu.h>
 
 #include "vgic.h"
 
@@ -205,3 +210,88 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
 			GICH_VMCR_PRIMASK_SHIFT;
 }
+
+/**
+ * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
+ * @node:	pointer to the DT node
+ *
+ * Returns 0 if a GICv2 has been found, returns an error code otherwise
+ */
+int vgic_v2_probe(struct device_node *vgic_node)
+{
+	int ret;
+	struct resource vctrl_res;
+	struct resource vcpu_res;
+
+	kvm_vgic_global_state.maint_irq = irq_of_parse_and_map(vgic_node, 0);
+	if (!kvm_vgic_global_state.maint_irq) {
+		kvm_err("error getting vgic maintenance irq from DT\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
+	if (ret) {
+		kvm_err("Cannot obtain GICH resource\n");
+		goto out;
+	}
+
+	kvm_vgic_global_state.vctrl_base = of_iomap(vgic_node, 2);
+	if (!kvm_vgic_global_state.vctrl_base) {
+		kvm_err("Cannot ioremap GICH\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	kvm_vgic_global_state.nr_lr =
+		readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
+	kvm_vgic_global_state.nr_lr = (kvm_vgic_global_state.nr_lr & 0x3f) + 1;
+
+	ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
+				     kvm_vgic_global_state.vctrl_base +
+					 resource_size(&vctrl_res),
+				     vctrl_res.start);
+	if (ret) {
+		kvm_err("Cannot map VCTRL into hyp\n");
+		goto out_unmap;
+	}
+
+	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
+		kvm_err("Cannot obtain GICV resource\n");
+		ret = -ENXIO;
+		goto out_unmap;
+	}
+
+	if (!PAGE_ALIGNED(vcpu_res.start)) {
+		kvm_err("GICV physical address 0x%llx not page aligned\n",
+			(unsigned long long)vcpu_res.start);
+		ret = -ENXIO;
+		goto out_unmap;
+	}
+
+	if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
+		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+			(unsigned long long)resource_size(&vcpu_res),
+			PAGE_SIZE);
+		ret = -ENXIO;
+		goto out_unmap;
+	}
+
+	kvm_vgic_global_state.can_emulate_gicv2 = true;
+	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+
+	kvm_vgic_global_state.vcpu_base = vcpu_res.start;
+
+	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
+		 vctrl_res.start, kvm_vgic_global_state.maint_irq);
+
+	kvm_vgic_global_state.type = VGIC_V2;
+	kvm_vgic_global_state.max_gic_vcpus = VGIC_V2_MAX_CPUS;
+	goto out;
+
+out_unmap:
+	iounmap(kvm_vgic_global_state.vctrl_base);
+out:
+	of_node_put(vgic_node);
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index dca52b3..48b0bb7 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -15,6 +15,12 @@
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/kvm_mmu.h>
+#include <asm/kvm_asm.h>
 
 #include "vgic.h"
 
@@ -188,3 +194,70 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
+
+/**
+ * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
+ * @node:	pointer to the DT node
+ *
+ * Returns 0 if a GICv3 has been found, returns an error code otherwise
+ */
+int vgic_v3_probe(struct device_node *vgic_node)
+{
+	u32 ich_vtr_el2;
+	u32 gicv_idx;
+	int ret = 0;
+	struct resource vcpu_res;
+
+	kvm_vgic_global_state.maint_irq = irq_of_parse_and_map(vgic_node, 0);
+	if (!kvm_vgic_global_state.maint_irq) {
+		kvm_err("error getting vgic maintenance irq from DT\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
+
+	/*
+	 * The ListRegs field is 5 bits, but there is a architectural
+	 * maximum of 16 list registers. Just ignore bit 4...
+	 */
+	kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
+	kvm_vgic_global_state.can_emulate_gicv2 = false;
+
+	if (of_property_read_u32(vgic_node, "#redistributor-regions",
+				 &gicv_idx))
+		gicv_idx = 1;
+
+	gicv_idx += 3; /* Also skip GICD, GICC, GICH */
+	if (of_address_to_resource(vgic_node, gicv_idx, &vcpu_res)) {
+		kvm_info("GICv3: no GICV resource entry\n");
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else if (!PAGE_ALIGNED(vcpu_res.start)) {
+		pr_warn("GICV physical address 0x%llx not page aligned\n",
+			(unsigned long long)vcpu_res.start);
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
+		pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+			(unsigned long long)resource_size(&vcpu_res),
+			PAGE_SIZE);
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else {
+		kvm_vgic_global_state.vcpu_base = vcpu_res.start;
+		kvm_vgic_global_state.can_emulate_gicv2 = true;
+		kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+	}
+	if (kvm_vgic_global_state.vcpu_base == 0)
+		kvm_info("disabling GICv2 emulation\n");
+	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V3);
+
+	kvm_vgic_global_state.vctrl_base = NULL;
+	kvm_vgic_global_state.type = VGIC_V3;
+	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
+
+	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
+		 vcpu_res.start, kvm_vgic_global_state.maint_irq);
+
+out:
+	of_node_put(vgic_node);
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 7a69955..e49b1df 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -43,6 +43,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+int vgic_v2_probe(struct device_node *vgic_node);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -54,6 +55,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+int vgic_v3_probe(struct device_node *vgic_node);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -87,6 +89,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
 {
 }
 
+static inline int vgic_v3_probe(struct device_node *vgic_node)
+{
+	return -ENODEV;
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:54 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:54 +0100
Subject: [PATCH v3 41/55] KVM: arm/arm64: vgic-new: vgic_kvm_device: implement
 kvm_vgic_addr
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-42-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

kvm_vgic_addr is used by the userspace to set the base address of
the following register regions, as seen by the guest:
- distributor(v2 and v3),
- re-distributors (v3),
- CPU interface (v2).

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 include/kvm/vgic/vgic.h             |   2 +
 virt/kvm/arm/vgic/vgic-kvm-device.c | 112 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |   3 +
 3 files changed, 117 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 2c43eb8..73cab36 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -194,6 +194,8 @@ struct vgic_cpu {
 	u64 live_lrs;
 };
 
+int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
 
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index e153f12..493e941 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -16,10 +16,122 @@
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
 #include <linux/uaccess.h>
+#include <asm/kvm_mmu.h>
 #include "vgic.h"
 
 /* common helpers */
 
+static int vgic_ioaddr_overlap(struct kvm *kvm)
+{
+	phys_addr_t dist = kvm->arch.vgic.vgic_dist_base;
+	phys_addr_t cpu = kvm->arch.vgic.vgic_cpu_base;
+
+	if (IS_VGIC_ADDR_UNDEF(dist) || IS_VGIC_ADDR_UNDEF(cpu))
+		return 0;
+	if ((dist <= cpu && dist + KVM_VGIC_V2_DIST_SIZE > cpu) ||
+	    (cpu <= dist && cpu + KVM_VGIC_V2_CPU_SIZE > dist))
+		return -EBUSY;
+	return 0;
+}
+
+static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
+			      phys_addr_t addr, phys_addr_t size)
+{
+	int ret;
+
+	if (addr & ~KVM_PHYS_MASK)
+		return -E2BIG;
+
+	if (addr & (SZ_4K - 1))
+		return -EINVAL;
+
+	if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
+		return -EEXIST;
+	if (addr + size < addr)
+		return -EINVAL;
+
+	*ioaddr = addr;
+	ret = vgic_ioaddr_overlap(kvm);
+	if (ret)
+		*ioaddr = VGIC_ADDR_UNDEF;
+
+	return ret;
+}
+
+/**
+ * kvm_vgic_addr - set or get vgic VM base addresses
+ * @kvm:   pointer to the vm struct
+ * @type:  the VGIC addr type, one of KVM_VGIC_V[23]_ADDR_TYPE_XXX
+ * @addr:  pointer to address value
+ * @write: if true set the address in the VM address space, if false read the
+ *          address
+ *
+ * Set or get the vgic base addresses for the distributor and the virtual CPU
+ * interface in the VM physical address space.  These addresses are properties
+ * of the emulated core/SoC and therefore user space initially knows this
+ * information.
+ */
+int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
+{
+	int r = 0;
+	struct vgic_dist *vgic = &kvm->arch.vgic;
+	int type_needed;
+	phys_addr_t *addr_ptr, block_size;
+	phys_addr_t alignment;
+
+	mutex_lock(&kvm->lock);
+	switch (type) {
+	case KVM_VGIC_V2_ADDR_TYPE_DIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+		addr_ptr = &vgic->vgic_dist_base;
+		block_size = KVM_VGIC_V2_DIST_SIZE;
+		alignment = SZ_4K;
+		break;
+	case KVM_VGIC_V2_ADDR_TYPE_CPU:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+		addr_ptr = &vgic->vgic_cpu_base;
+		block_size = KVM_VGIC_V2_CPU_SIZE;
+		alignment = SZ_4K;
+		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case KVM_VGIC_V3_ADDR_TYPE_DIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+		addr_ptr = &vgic->vgic_dist_base;
+		block_size = KVM_VGIC_V3_DIST_SIZE;
+		alignment = SZ_64K;
+		break;
+	case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+		addr_ptr = &vgic->vgic_redist_base;
+		block_size = KVM_VGIC_V3_REDIST_SIZE;
+		alignment = SZ_64K;
+		break;
+#endif
+	default:
+		r = -ENODEV;
+		goto out;
+	}
+
+	if (vgic->vgic_model != type_needed) {
+		r = -ENODEV;
+		goto out;
+	}
+
+	if (write) {
+		if (!IS_ALIGNED(*addr, alignment))
+			r = -EINVAL;
+		else
+			r = vgic_ioaddr_assign(kvm, addr_ptr,
+					       *addr, block_size);
+	} else {
+		*addr = *addr_ptr;
+	}
+
+out:
+	mutex_unlock(&kvm->lock);
+	return r;
+}
+
 static int vgic_set_common_attr(struct kvm_device *dev,
 				struct kvm_device_attr *attr)
 {
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index e7c66a5..c44ee01 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,9 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define VGIC_ADDR_UNDEF		(-1)
+#define IS_VGIC_ADDR_UNDEF(_x)  ((_x) == VGIC_ADDR_UNDEF)
+
 #define INTERRUPT_ID_BITS_SPIS	10
 
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:46:05 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:46:05 +0100
Subject: [PATCH v3 52/55] KVM: arm/arm64: vgic-new: Add vgic_v2/v3_enable
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-53-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

Enable the VGIC operation by properly initialising the registers
in the hypervisor GIC interface.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic-v2.c | 11 ++++++++++-
 virt/kvm/arm/vgic/vgic-v3.c | 23 ++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 1e411f5..4493593 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -211,9 +211,18 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 			GICH_VMCR_PRIMASK_SHIFT;
 }
 
-/* not yet implemented */
 void vgic_v2_enable(struct kvm_vcpu *vcpu)
 {
+	/*
+	 * By forcing VMCR to zero, the GIC will restore the binary
+	 * points to their reset values. Anything else resets to zero
+	 * anyway.
+	 */
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = 0;
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr = ~0;
+
+	/* Get the show on the road... */
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr = GICH_HCR_EN;
 }
 
 int vgic_v2_map_resources(struct kvm *kvm)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 4bfd42a..6d7422f 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -195,9 +195,30 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
 
-/* not yet implemented */
 void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
+	struct vgic_v3_cpu_if *vgic_v3 = &vcpu->arch.vgic_cpu.vgic_v3;
+
+	/*
+	 * By forcing VMCR to zero, the GIC will restore the binary
+	 * points to their reset values. Anything else resets to zero
+	 * anyway.
+	 */
+	vgic_v3->vgic_vmcr = 0;
+	vgic_v3->vgic_elrsr = ~0;
+
+	/*
+	 * If we are emulating a GICv3, we do it in an non-GICv2-compatible
+	 * way, so we force SRE to 1 to demonstrate this to the guest.
+	 * This goes with the spec allowing the value to be RAO/WI.
+	 */
+	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+		vgic_v3->vgic_sre = ICC_SRE_EL1_SRE;
+	else
+		vgic_v3->vgic_sre = 0;
+
+	/* Get the show on the road... */
+	vgic_v3->vgic_hcr = ICH_HCR_EN;
 }
 
 int vgic_v3_map_resources(struct kvm *kvm)
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:46:03 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:46:03 +0100
Subject: [PATCH v3 50/55] KVM: arm/arm64: vgic-new: vgic_init: implement
 vgic_init
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-51-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch allocates and initializes the data structures used
to model the vgic distributor and virtual cpu interfaces. At that
stage the number of IRQs and number of virtual CPUs is frozen.

The following early_init functions are kept since they are called from
arm.c. However they may disappear in subsequent patches since
they are void.

vgic_[v2|v3]_enable still is stubbed at this stage.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- initialize v2/v3 default CPU affinities explicitly

Changelog v1 .. v2:
- move lazy_init() into vgic_update_irq_pending()

 include/kvm/vgic/vgic.h       |   7 +-
 virt/kvm/arm/vgic/vgic-init.c | 213 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   |   5 +
 virt/kvm/arm/vgic/vgic-v3.c   |   5 +
 virt/kvm/arm/vgic/vgic.c      |   4 +
 virt/kvm/arm/vgic/vgic.h      |   8 ++
 6 files changed, 241 insertions(+), 1 deletion(-)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 899b7b7..538078a 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -119,6 +119,7 @@ struct vgic_io_device {
 struct vgic_dist {
 	bool			in_kernel;
 	bool			ready;
+	bool			initialized;
 
 	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
 	u32			vgic_model;
@@ -202,7 +203,11 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+void kvm_vgic_early_init(struct kvm *kvm);
 int kvm_vgic_create(struct kvm *kvm, u32 type);
+void kvm_vgic_destroy(struct kvm *kvm);
+void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
+void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
@@ -211,7 +216,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
-#define vgic_initialized(k)	(false)
+#define vgic_initialized(k)	((k)->arch.vgic.initialized)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
 #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
 			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index a150363..3f9c137 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -24,6 +24,42 @@
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
+/*
+ * Initialization rules: there are multiple stages to the vgic
+ * initialization, both for the distributor and the CPU interfaces.
+ *
+ * Distributor:
+ *
+ * - kvm_vgic_early_init(): initialization of static data that doesn't
+ *   depend on any sizing information or emulation type. No allocation
+ *   is allowed there.
+ *
+ * - vgic_init(): allocation and initialization of the generic data
+ *   structures that depend on sizing information (number of CPUs,
+ *   number of interrupts). Also initializes the vcpu specific data
+ *   structures. Can be executed lazily for GICv2.
+ *
+ * CPU Interface:
+ *
+ * - kvm_vgic_cpu_early_init(): initialization of static data that
+ *   doesn't depend on any sizing information or emulation type. No
+ *   allocation is allowed there.
+ */
+
+/* EARLY INIT */
+
+/*
+ * Those 2 functions should not be needed anymore but they
+ * still are called from arm.c
+ */
+void kvm_vgic_early_init(struct kvm *kvm)
+{
+}
+
+void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu)
+{
+}
+
 /* CREATION */
 
 /**
@@ -108,6 +144,183 @@ out:
 	return ret;
 }
 
+/* INIT/DESTROY */
+
+/**
+ * kvm_vgic_dist_init: initialize the dist data structures
+ * @kvm: kvm struct pointer
+ * @nr_spis: number of spis, frozen by caller
+ */
+int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct kvm_vcpu *vcpu0 = kvm_get_vcpu(kvm, 0);
+	int i;
+
+	dist->spis = kcalloc(nr_spis, sizeof(struct vgic_irq), GFP_KERNEL);
+	if (!dist->spis)
+		return  -ENOMEM;
+
+	/*
+	 * In following code we do not take the irq struct lock since
+	 * no other action on irq structs can happen while the VGIC is
+	 * not initialized yet:
+	 * injection requires (VGICV3) or does (VGIC2) initialization.
+	 * MMIO access triggers init.
+	 */
+	for (i = 0; i < nr_spis; i++) {
+		struct vgic_irq *irq = &dist->spis[i];
+
+		irq->intid = i + VGIC_NR_PRIVATE_IRQS;
+		INIT_LIST_HEAD(&irq->ap_list);
+		spin_lock_init(&irq->irq_lock);
+		irq->vcpu = NULL;
+		irq->target_vcpu = vcpu0;
+		if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+			irq->targets = 0;
+		else
+			irq->mpidr = 0;
+	}
+	return 0;
+}
+
+/**
+ * kvm_vgic_vcpu_init: initialize the vcpu data structures and
+ * enable the VCPU interface
+ * @kvm: kvm struct pointer
+ */
+void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	int i;
+
+	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
+	spin_lock_init(&vgic_cpu->ap_list_lock);
+
+	/*
+	 * Enable and configure all SGIs to be edge-triggered and
+	 * configure all PPIs as level-triggered.
+	 */
+	for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
+		struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
+
+		INIT_LIST_HEAD(&irq->ap_list);
+		spin_lock_init(&irq->irq_lock);
+		irq->intid = i;
+		irq->vcpu = NULL;
+		irq->target_vcpu = vcpu;
+		irq->targets = 1U << vcpu->vcpu_id;
+		if (vgic_irq_is_sgi(i)) {
+			/* SGIs */
+			irq->enabled = 1;
+			irq->config = VGIC_CONFIG_EDGE;
+		} else {
+			/* PPIs */
+			irq->config = VGIC_CONFIG_LEVEL;
+		}
+	}
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_enable(vcpu);
+	else
+		vgic_v3_enable(vcpu);
+}
+
+/*
+ * vgic_init: allocates and initializes dist and vcpu data structures
+ * depending on two dimensioning parameters:
+ * - the number of spis
+ * - the number of vcpus
+ * The function is generally called when nr_spis has been explicitly set
+ * by the guest through the KVM DEVICE API. If not nr_spis is set to 256.
+ * Completion can be tested by vgic_initialized
+ * Must be called with kvm->lock held!
+ */
+int vgic_init(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct kvm_vcpu *vcpu;
+	int ret = 0, i;
+
+	if (vgic_initialized(kvm))
+		return 0;
+
+	/* freeze the number of spis */
+	if (!dist->nr_spis)
+		dist->nr_spis = VGIC_NR_IRQS_LEGACY - VGIC_NR_PRIVATE_IRQS;
+
+	ret = kvm_vgic_dist_init(kvm, dist->nr_spis);
+	if (ret)
+		goto out;
+
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_vgic_vcpu_init(vcpu);
+
+	dist->initialized = true;
+out:
+	return ret;
+}
+
+static void kvm_vgic_dist_destroy(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+
+	mutex_lock(&kvm->lock);
+
+	dist->ready = false;
+	dist->initialized = false;
+
+	kfree(dist->spis);
+	kfree(dist->redist_iodevs);
+	dist->nr_spis = 0;
+
+	mutex_unlock(&kvm->lock);
+}
+
+void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
+}
+
+void kvm_vgic_destroy(struct kvm *kvm)
+{
+	struct kvm_vcpu *vcpu;
+	int i;
+
+	kvm_vgic_dist_destroy(kvm);
+
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_vgic_vcpu_destroy(vcpu);
+}
+
+/**
+ * Lazy init only is allowed if the GIC exposed to the guest is a GICV2.
+ * GICV3 must be explicitly initialized by the guest using the
+ * KVM_DEV_ARM_VGIC_GRP_CTRL KVM_DEVICE group
+ */
+int vgic_lazy_init(struct kvm *kvm)
+{
+	int ret = 0;
+
+	if (unlikely(!vgic_initialized(kvm))) {
+		/*
+		 * We only provide the automatic initialization of the VGIC
+		 * for the legacy case of a GICv2. Any other type must
+		 * be explicitly initialized once setup with the respective
+		 * KVM device call.
+		 */
+		if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2)
+			return -EBUSY;
+
+		mutex_lock(&kvm->lock);
+		ret = vgic_init(kvm);
+		mutex_unlock(&kvm->lock);
+	}
+
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 91b69a4..48aa877 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -211,6 +211,11 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 			GICH_VMCR_PRIMASK_SHIFT;
 }
 
+/* not yet implemented */
+void vgic_v2_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 48b0bb7..7cab5b9 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -195,6 +195,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
 
+/* not yet implemented */
+void vgic_v3_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 5355de6..068389a 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -255,6 +255,10 @@ static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
 
 	trace_vgic_update_irq_pending(cpuid, intid, level);
 
+	ret = vgic_lazy_init(kvm);
+	if (ret)
+		return ret;
+
 	vcpu = kvm_get_vcpu(kvm, cpuid);
 	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
 		return -EINVAL;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index e49b1df..cad04eb 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -43,6 +43,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v2_enable(struct kvm_vcpu *vcpu);
 int vgic_v2_probe(struct device_node *vgic_node);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
@@ -55,6 +56,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v3_enable(struct kvm_vcpu *vcpu);
 int vgic_v3_probe(struct device_node *vgic_node);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
@@ -89,6 +91,10 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
 {
 }
 
+static inline void vgic_v3_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 static inline int vgic_v3_probe(struct device_node *vgic_node)
 {
 	return -ENODEV;
@@ -102,5 +108,7 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 #endif
 
 void kvm_register_vgic_device(unsigned long type);
+int vgic_lazy_init(struct kvm *kvm);
+int vgic_init(struct kvm *kvm);
 
 #endif
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:46:06 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:46:06 +0100
Subject: [PATCH v3 53/55] KVM: arm/arm64: vgic-new: Wire up irqfd injection
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-54-git-send-email-andre.przywara@arm.com>

Connect to the new VGIC to the irqfd framework, so that we can
inject IRQs.
GSI routing and MSI routing is not yet implemented.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic-irqfd.c | 52 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-irqfd.c

diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
new file mode 100644
index 0000000..c675513
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/kvm.h>
+#include <linux/kvm_host.h>
+#include <trace/events/kvm.h>
+
+int kvm_irq_map_gsi(struct kvm *kvm,
+		    struct kvm_kernel_irq_routing_entry *entries,
+		    int gsi)
+{
+	return 0;
+}
+
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned int irqchip,
+			 unsigned int pin)
+{
+	return pin;
+}
+
+int kvm_set_irq(struct kvm *kvm, int irq_source_id,
+		u32 irq, int level, bool line_status)
+{
+	unsigned int spi = irq + VGIC_NR_PRIVATE_IRQS;
+
+	trace_kvm_set_irq(irq, level, irq_source_id);
+
+	BUG_ON(!vgic_initialized(kvm));
+
+	return kvm_vgic_inject_irq(kvm, 0, spi, level);
+}
+
+/* MSI not implemented yet */
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
+		struct kvm *kvm, int irq_source_id,
+		int level, bool line_status)
+{
+	return 0;
+}
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:35 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:35 +0100
Subject: [PATCH v3 22/55] KVM: arm/arm64: vgic-new: Add GICv2 MMIO handling
 framework
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-23-git-send-email-andre.przywara@arm.com>

Create vgic-mmio-v2.c to describe GICv2 emulation specific handlers
using the initializer macros provided by the VGIC MMIO framework.
Provide a function to register the GICv2 distributor registers to
the kvm_io_bus framework.
The actual handler functions are still stubs in this patch.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog v1 .. v2:
- new patch, split out from the generic MMIO framework patch
- use a separate file to hold GICv2 emulation specific handlers
- replace _nyi stub functions with raz/wi versions

Changelog v2 .. v3:
- replace kvm/vgic/vgic.h with kvm/arm_vgic.h
- add vgic_register_dist_iodev() prototype

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c    | 26 +++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  2 ++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 4 files changed, 92 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v2.c

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
new file mode 100644
index 0000000..2729a22
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -0,0 +1,62 @@
+/*
+ * VGICv2 MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irqchip/arm-gic.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+static const struct vgic_register_region vgic_v2_dist_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 12),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 2),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
+};
+
+unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
+{
+	dev->regions = vgic_v2_dist_registers;
+	dev->nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
+
+	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
+
+	return SZ_4K;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index f5628cb..41cf4f4 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -169,3 +169,29 @@ struct kvm_io_device_ops kvm_io_gic_ops = {
 	.read = dispatch_mmio_read,
 	.write = dispatch_mmio_write,
 };
+
+int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
+			     enum vgic_type type)
+{
+	struct vgic_io_device *io_device = &kvm->arch.vgic.dist_iodev;
+	int ret = 0;
+	unsigned int len;
+
+	switch (type) {
+	case VGIC_V2:
+		len = vgic_v2_init_dist_iodev(io_device);
+		break;
+	default:
+		BUG_ON(1);
+	}
+
+	io_device->base_addr = dist_base_address;
+	io_device->redist_vcpu = NULL;
+
+	mutex_lock(&kvm->slots_lock);
+	ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address,
+				      len, &io_device->dev);
+	mutex_unlock(&kvm->slots_lock);
+
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 18d3869..4f4dd2b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -74,4 +74,6 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
 void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 			unsigned int len, unsigned long val);
 
+unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
+
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 81b1a20..fd9acaa 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -27,6 +27,8 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
+			     enum vgic_type);
 
 #ifdef CONFIG_KVM_ARM_VGIC_V3
 void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:39 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:39 +0100
Subject: [PATCH v3 26/55] KVM: arm/arm64: vgic-new: Add ACTIVE registers
 handlers
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-27-git-send-email-andre.przywara@arm.com>

The active register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.
Since activation/deactivation of an interrupt may happen entirely
in the guest without it ever exiting, we need some extra logic to
properly track the active state.
Putting it on an ap_list on activation is similar to the normal case
handled by vgic_queue_irq_unlock(), but differs in some details that
make a separate implementation worthwhile.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- handling queueing in write handler
- remove IRQ lock from read handler

Changelog v1 .. v2:
- adapt to new MMIO framework

 virt/kvm/arm/vgic/vgic-mmio-v2.c |   4 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 120 +++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  10 ++++
 3 files changed, 132 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 4b87e0a..054b52d 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -80,9 +80,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
 		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 4df1af7..dbf683e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -162,6 +162,126 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = (addr & 0x7f) * 8;
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->active)
+			value |= (1U << i);
+	}
+
+	return extract_bytes(value, addr & 3, len);
+}
+
+void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = (addr & 0x7f) * 8;
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->active = false;
+
+		/*
+		 * Christoffer wrote:
+		 * The question is what to do if the vcpu for this irq is
+		 * running and the LR there has the active bit set, then we'll
+		 * overwrite this change when we fold the LR state back into
+		 * the vgic_irq struct.
+		 *
+		 * Since I expect this to be extremely rare, one option is to
+		 * force irq->vcpu to exit (if non-null) and then do you
+		 * thing here after you've confirm it has exited while holding
+		 * some lock preventing it from re-entering again.
+		 * Slightly crazy.
+		 *
+		 * The alternative is to put a big fat comment nothing that
+		 * this is non-supported bad race, and wait until someone
+		 * submits a bug report relating to this...
+		 */
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = (addr & 0x7f) * 8;
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		/* As this is a special case, we can't use the
+		 * vgic_queue_irq_unlock() function to put this on a VCPU.
+		 * So deal with this here explicitly unless the IRQs was
+		 * already active, it was on a VCPU before or there is no
+		 * target VCPU assigned at the moment.
+		 */
+		if (irq->active || irq->vcpu || !irq->target_vcpu) {
+			irq->active = true;
+
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		spin_unlock(&irq->irq_lock);
+retry:
+		vcpu = irq->target_vcpu;
+
+		spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+		spin_lock(&irq->irq_lock);
+
+		/*
+		 * Recheck after dropping the IRQ lock to see if we should
+		 * still care about queueing it.
+		 */
+		if (irq->active || irq->vcpu) {
+			irq->active = true;
+
+			spin_unlock(&irq->irq_lock);
+			spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+			continue;
+		}
+
+		/* Did the target VCPU change while we had the lock dropped? */
+		if (vcpu != irq->target_vcpu) {
+			spin_unlock(&irq->irq_lock);
+			spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+			goto retry;
+		}
+
+		/* Now queue the IRQ to the VCPU's ap_list. */
+		list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
+		irq->vcpu = vcpu;
+
+		irq->active = true;
+
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+		kvm_vcpu_kick(vcpu);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index d4fc029..fa875dc 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -96,6 +96,16 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
 			      gpa_t addr, unsigned int len,
 			      unsigned long val);
 
+unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
+void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
 
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:28 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:28 +0100
Subject: [PATCH v3 15/55] KVM: arm/arm64: vgic-new: Implement virtual IRQ
 injection
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-16-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Provide a vgic_queue_irq() function which decides whether a given
IRQ needs to be queued to a VCPU's ap_list.
This should be called whenever an IRQ becomes pending or enabled,
either as a result of userspace injection, from in-kernel emulated
devices like the architected timer or from MMIO accesses to the
distributor emulation.
Also provides the necessary functions to allow userland to inject an
IRQ to a guest.
Since this is the first code that starts using our locking mechanism, we
add some (hopefully) clear documentation of our locking strategy and
requirements along with this patch.

[Andre: refactor out vgic_queue_irq_unlock()]

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- add spinlock checks protected by CONFIG_DEBUG_SPINLOCK
- add more comments to vgic_target_oracle
- remove BUG_ON() if IRQ is neither edge or level
- rename vgic_queue_irq() to vgic_queue_irq_unlock()
- simplify initial check in vgic_queue_irq_unlock()
- extend retry loop to ask the oracle again
- minor comment fixes

Changelog v1 .. v2:
- move most IRQ injection code into vgic_update_irq_pending()

 include/kvm/vgic/vgic.h  |   3 +
 virt/kvm/arm/vgic/vgic.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h |   1 +
 3 files changed, 213 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 39933ee..2bfb42c 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -181,6 +181,9 @@ struct vgic_cpu {
 	u64 live_lrs;
 };
 
+int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			bool level);
+
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(false)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index fb45537..92b78a0 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -19,8 +19,31 @@
 
 #include "vgic.h"
 
+#define CREATE_TRACE_POINTS
+#include "../trace.h"
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+#define DEBUG_SPINLOCK_BUG_ON(p) BUG_ON(p)
+#else
+#define DEBUG_SPINLOCK_BUG_ON(p)
+#endif
+
 struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
 
+/*
+ * Locking order is always:
+ *   vgic_cpu->ap_list_lock
+ *     vgic_irq->irq_lock
+ *
+ * (that is, always take the ap_list_lock before the struct vgic_irq lock).
+ *
+ * When taking more than one ap_list_lock at the same time, always take the
+ * lowest numbered VCPU's ap_list_lock first, so:
+ *   vcpuX->vcpu_id < vcpuY->vcpu_id:
+ *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
+ *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
+ */
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid)
 {
@@ -39,3 +62,189 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 	WARN(1, "Looking up struct vgic_irq for reserved INTID");
 	return NULL;
 }
+
+/**
+ * kvm_vgic_target_oracle - compute the target vcpu for an irq
+ *
+ * @irq:	The irq to route. Must be already locked.
+ *
+ * Based on the current state of the interrupt (enabled, pending,
+ * active, vcpu and target_vcpu), compute the next vcpu this should be
+ * given to. Return NULL if this shouldn't be injected at all.
+ *
+ * Requires the IRQ lock to be held.
+ */
+static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
+{
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+	/* If the interrupt is active, it must stay on the current vcpu */
+	if (irq->active)
+		return irq->vcpu;
+
+	/*
+	 * If the IRQ is not active but enabled and pending, we should direct
+	 * it to its configured target VCPU.
+	 */
+	if (irq->enabled && irq->pending)
+		return irq->target_vcpu;
+
+	/* If neither active nor pending and enabled, then this IRQ should not
+	 * be queued to any VCPU.
+	 */
+	return NULL;
+}
+
+/*
+ * Only valid injection if changing level for level-triggered IRQs or for a
+ * rising edge.
+ */
+static bool vgic_validate_injection(struct vgic_irq *irq, bool level)
+{
+	switch (irq->config) {
+	case VGIC_CONFIG_LEVEL:
+		return irq->line_level != level;
+	case VGIC_CONFIG_EDGE:
+		return level;
+	}
+
+	return false;
+}
+
+/*
+ * Check whether an IRQ needs to (and can) be queued to a VCPU's ap list.
+ * Do the queuing if necessary, taking the right locks in the right order.
+ * Returns true when the IRQ was queued, false otherwise.
+ *
+ * Needs to be entered with the IRQ lock already held, but will return
+ * with all locks dropped.
+ */
+bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq)
+{
+	struct kvm_vcpu *vcpu;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+retry:
+	vcpu = vgic_target_oracle(irq);
+	if (irq->vcpu || !vcpu) {
+		/*
+		 * If this IRQ is already on a VCPU's ap_list, then it
+		 * cannot be moved or modified and there is no more work for
+		 * us to do.
+		 *
+		 * Otherwise, if the irq is not pending and enabled, it does
+		 * not need to be inserted into an ap_list and there is also
+		 * no more work for us to do.
+		 */
+		spin_unlock(&irq->irq_lock);
+		return false;
+	}
+
+	/*
+	 * We must unlock the irq lock to take the ap_list_lock where
+	 * we are going to insert this new pending interrupt.
+	 */
+	spin_unlock(&irq->irq_lock);
+
+	/* someone can do stuff here, which we re-check below */
+
+	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+	spin_lock(&irq->irq_lock);
+
+	/*
+	 * Did something change behind our backs?
+	 *
+	 * There are two cases:
+	 * 1) The irq became pending or active behind our backs and/or
+	 *    the irq->vcpu field was set correspondingly when putting
+	 *    the irq on an ap_list. Then drop the locks and return.
+	 * 2) Someone changed the affinity on this irq behind our
+	 *    backs and we are now holding the wrong ap_list_lock.
+	 *    Then drop the locks and try the new VCPU.
+	 */
+	if (irq->vcpu || !(irq->pending && irq->enabled)) {
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+		return false;
+	}
+
+	if (irq->target_vcpu != vcpu) {
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+		spin_lock(&irq->irq_lock);
+		goto retry;
+	}
+
+	list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
+	irq->vcpu = vcpu;
+
+	spin_unlock(&irq->irq_lock);
+	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+	kvm_vcpu_kick(vcpu);
+
+	return true;
+}
+
+static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
+				   unsigned int intid, bool level,
+				   bool mapped_irq)
+{
+	struct kvm_vcpu *vcpu;
+	struct vgic_irq *irq;
+	int ret;
+
+	trace_vgic_update_irq_pending(cpuid, intid, level);
+
+	vcpu = kvm_get_vcpu(kvm, cpuid);
+	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
+		return -EINVAL;
+
+	irq = vgic_get_irq(kvm, vcpu, intid);
+	if (!irq)
+		return -EINVAL;
+
+	if (irq->hw != mapped_irq)
+		return -EINVAL;
+
+	spin_lock(&irq->irq_lock);
+
+	if (!vgic_validate_injection(irq, level)) {
+		/* Nothing to see here, move along... */
+		spin_unlock(&irq->irq_lock);
+		return 0;
+	}
+
+	if (irq->config == VGIC_CONFIG_LEVEL) {
+		irq->line_level = level;
+		irq->pending = level || irq->soft_pending;
+	} else {
+		irq->pending = true;
+	}
+
+	vgic_queue_irq_unlock(kvm, irq);
+
+	return 0;
+}
+
+/**
+ * kvm_vgic_inject_irq - Inject an IRQ from a device to the vgic
+ * @kvm:     The VM structure pointer
+ * @cpuid:   The CPU for PPIs
+ * @intid:   The INTID to inject a new state to.
+ * @level:   Edge-triggered:  true:  to trigger the interrupt
+ *			      false: to ignore the call
+ *	     Level-sensitive  true:  raise the input signal
+ *			      false: lower the input signal
+ *
+ * The VGIC is not concerned with devices being active-LOW or active-HIGH for
+ * level-sensitive interrupts.  You can think of the level parameter as 1
+ * being HIGH and 0 being LOW and all devices being active-HIGH.
+ */
+int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			bool level)
+{
+	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 61b8d22..c625767 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -18,5 +18,6 @@
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
+bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
 
 #endif
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:46:00 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:46:00 +0100
Subject: [PATCH v3 47/55] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-48-git-send-email-andre.przywara@arm.com>

Using the VMCR accessors we provide access to GIC CPU interface state
to userland by wiring it up to the existing userland interface.
[Marc: move and make VMCR accessors static, streamline MMIO handlers]

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog v2 .. v3:
- total rework, moving into vgic-mmio-v2.c
- move vmcr accessor wrapper functions into this file
- use the register description table for CPU i/f registers as well
- add RAZ/WI handling for the active priority registers
- streamline MMIO handler functions

 virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 104 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |   2 +
 3 files changed, 107 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index bb33af8..2122ff2 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -300,7 +300,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		ret = -EINVAL;
+		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
 		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index c453e6f..0060539 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -206,6 +206,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_set_vmcr(vcpu, vmcr);
+	else
+		vgic_v3_set_vmcr(vcpu, vmcr);
+}
+
+static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_get_vmcr(vcpu, vmcr);
+	else
+		vgic_v3_get_vmcr(vcpu, vmcr);
+}
+
+#define GICC_ARCH_VERSION_V2	0x2
+
+/* These are for userland accesses only, there is no guest-facing emulation. */
+static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
+					   gpa_t addr, unsigned int len)
+{
+	struct vgic_vmcr vmcr;
+	u32 val;
+
+	vgic_get_vmcr(vcpu, &vmcr);
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		val = vmcr.ctlr;
+		break;
+	case GIC_CPU_PRIMASK:
+		val = vmcr.pmr;
+		break;
+	case GIC_CPU_BINPOINT:
+		val = vmcr.bpr;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		val = vmcr.abpr;
+		break;
+	case GIC_CPU_IDENT:
+		val = ((PRODUCT_ID_KVM << 20) |
+		       (GICC_ARCH_VERSION_V2 << 16) |
+		       IMPLEMENTER_ARM);
+		break;
+	default:
+		return 0;
+	}
+
+	return extract_bytes(val, addr & 3, len);
+}
+
+static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
+				   gpa_t addr, unsigned int len,
+				   unsigned long val)
+{
+	struct vgic_vmcr vmcr;
+
+	vgic_get_vmcr(vcpu, &vmcr);
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		vmcr.ctlr = val;
+		break;
+	case GIC_CPU_PRIMASK:
+		vmcr.pmr = val;
+		break;
+	case GIC_CPU_BINPOINT:
+		vmcr.bpr = val;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		vmcr.abpr = val;
+		break;
+	}
+
+	vgic_set_vmcr(vcpu, &vmcr);
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
@@ -237,6 +315,21 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16),
 };
 
+static const struct vgic_register_region vgic_v2_cpu_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_CTRL,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_PRIMASK,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ALIAS_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ACTIVEPRIO,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_IDENT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
+};
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
 {
 	dev->regions = vgic_v2_dist_registers;
@@ -306,6 +399,17 @@ static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
 	return ret;
 }
 
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_cpu_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
+
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val)
 {
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 5260d23..7a69955 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -39,6 +39,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val);
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:46:07 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:46:07 +0100
Subject: [PATCH v3 54/55] KVM: arm/arm64: vgic-new: implement mapped IRQ
 handling
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-55-git-send-email-andre.przywara@arm.com>

We now store the mapped hardware IRQ number in our struct, so we
don't need the irq_phys_map for the new VGIC.
Implement the hardware IRQ mapping on top of the reworked arch
timer interface.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- adapt to new arch_timer mapped IRQ interface
- implement inject_mapped_irq() as a macro (since it is identical to
  the "un-mapped" IRQ implementation)

Changelog v1 .. v2:
- replace inject_mapped_irq() macro with a separate implementation,
  which only allows mapped IRQs to be injected via this interface

 include/kvm/vgic/vgic.h  |  5 +++++
 virt/kvm/arm/vgic/vgic.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 07c3011..64aca0c 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -213,6 +213,11 @@ int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
+int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			       bool level);
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq);
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 068389a..3f854c5 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -310,6 +310,44 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
 }
 
+int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			       bool level)
+{
+	return vgic_update_irq_pending(kvm, cpuid, intid, level, true);
+}
+
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+
+	BUG_ON(!irq);
+
+	spin_lock(&irq->irq_lock);
+
+	irq->hw = true;
+	irq->hwintid = phys_irq;
+
+	spin_unlock(&irq->irq_lock);
+
+	return 0;
+}
+
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+
+	BUG_ON(!irq);
+
+	spin_lock(&irq->irq_lock);
+
+	irq->hw = false;
+	irq->hwintid = 0;
+
+	spin_unlock(&irq->irq_lock);
+
+	return 0;
+}
+
 /**
  * vgic_prune_ap_list - Remove non-relevant interrupts from the list
  *
@@ -563,3 +601,15 @@ void vgic_kick_vcpus(struct kvm *kvm)
 			kvm_vcpu_kick(vcpu);
 	}
 }
+
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+	bool map_is_active;
+
+	spin_lock(&irq->irq_lock);
+	map_is_active = irq->hw && irq->active;
+	spin_unlock(&irq->irq_lock);
+
+	return map_is_active;
+}
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:46:08 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:46:08 +0100
Subject: [PATCH v3 55/55] KVM: arm/arm64: vgic-new: enable build
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-56-git-send-email-andre.przywara@arm.com>

Now that the new VGIC implementation has reached feature parity with
the old one, add the new files to the build system and add a Kconfig
option to switch between the two versions.
We set the default to the new version to get maximum test coverage,
in case people experience problems they can switch back to the old
behaviour if needed.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adjust the changed filenames in the Makefiles
- add vgic-mmio-v2.c and vgic-mmio-v3.c to the Makefiles

 arch/arm/kvm/Kconfig          |  7 +++++++
 arch/arm/kvm/Makefile         | 11 +++++++++++
 arch/arm64/kvm/Kconfig        |  7 +++++++
 arch/arm64/kvm/Makefile       | 12 ++++++++++++
 virt/kvm/arm/hyp/vgic-v2-sr.c |  5 +++++
 5 files changed, 42 insertions(+)

diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 95a0005..02abfff 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -46,6 +46,13 @@ config KVM_ARM_HOST
 	---help---
 	  Provides host support for ARM processors.
 
+config KVM_NEW_VGIC
+	bool "New VGIC implementation"
+	depends on KVM
+	default y
+	---help---
+	  uses the new VGIC implementation
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index eb1bf43..a596b58 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -21,7 +21,18 @@ obj-$(CONFIG_KVM_ARM_HOST) += hyp/
 obj-y += kvm-arm.o init.o interrupts.o
 obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
+
+ifeq ($(CONFIG_KVM_NEW_VGIC),y)
+obj-y += $(KVM)/arm/vgic/vgic.o
+obj-y += $(KVM)/arm/vgic/vgic-init.o
+obj-y += $(KVM)/arm/vgic/vgic-irqfd.o
+obj-y += $(KVM)/arm/vgic/vgic-v2.o
+obj-y += $(KVM)/arm/vgic/vgic-mmio.o
+obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
+obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
+else
 obj-y += $(KVM)/arm/vgic.o
 obj-y += $(KVM)/arm/vgic-v2.o
 obj-y += $(KVM)/arm/vgic-v2-emul.o
+endif
 obj-y += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index de7450d..3f0e1ce 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -55,6 +55,13 @@ config KVM_ARM_PMU
 	  Adds support for a virtual Performance Monitoring Unit (PMU) in
 	  virtual machines.
 
+config KVM_NEW_VGIC
+	bool "New VGIC implementation"
+	depends on KVM
+	default y
+        ---help---
+          uses the new VGIC implementation
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 122cff4..a7a958c 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -20,10 +20,22 @@ kvm-$(CONFIG_KVM_ARM_HOST) += emulate.o inject_fault.o regmap.o
 kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
 kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
 
+ifeq ($(CONFIG_KVM_NEW_VGIC),y)
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-irqfd.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
+else
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2-emul.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3-emul.o
+endif
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
 kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index caac41f..a3f12b3 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -21,7 +21,12 @@
 
 #include <asm/kvm_hyp.h>
 
+#ifdef CONFIG_KVM_NEW_VGIC
+extern struct vgic_global kvm_vgic_global_state;
+#define vgic_v2_params kvm_vgic_global_state
+#else
 extern struct vgic_params vgic_v2_params;
+#endif
 
 static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 					    void __iomem *base)
-- 
2.7.3



From andre.przywara at arm.com  Fri May  6 03:45:41 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri,  6 May 2016 11:45:41 +0100
Subject: [PATCH v3 28/55] KVM: arm/arm64: vgic-new: Add CONFIG registers
 handlers
In-Reply-To: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462531568-9799-29-git-send-email-andre.przywara@arm.com>

The config register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 46 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  7 ++++++
 3 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 2e17250..2a953ec 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -88,7 +88,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 2),
+		vgic_mmio_read_config, vgic_mmio_write_config, 2),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index d7fe9e6..19fed56 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -321,6 +321,52 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = (addr & 0xff) * 4;
+	u32 value = 0;
+	int i;
+
+	for (i = 0; i < len * 4; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			value |= (2U << (i * 2));
+	}
+
+	return extract_bytes(value, addr & 3, len);
+}
+
+void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
+			    gpa_t addr, unsigned int len,
+			    unsigned long val)
+{
+	u32 intid = (addr & 0xff) * 4;
+	int i;
+
+	for (i = 0; i < len * 4; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (intid + i < 16)
+			continue;
+
+		/*
+		 * The spec says that interrupts must be disabled before
+		 * changing the configuration to avoid UNDEFINED behaviour.
+		 */
+
+		spin_lock(&irq->irq_lock);
+		if (test_bit(i * 2 + 1, &val)) {
+			irq->config = VGIC_CONFIG_EDGE;
+		} else {
+			irq->config = VGIC_CONFIG_LEVEL;
+			irq->pending = irq->line_level | irq->soft_pending;
+		}
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index cd04ac5..884eb71 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -114,6 +114,13 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
 			      gpa_t addr, unsigned int len,
 			      unsigned long val);
 
+unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
+			    gpa_t addr, unsigned int len,
+			    unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.7.3



From chunkeey at googlemail.com  Fri May  6 04:10:18 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Fri,  6 May 2016 13:10:18 +0200
Subject: [PATCH v7 0/3] gpio: add DT support for memory-mapped GPIOs
Message-ID: <cover.1462372360.git.chunkeey@googlemail.com>

This patch series adds device tree support for generic memory-mapped GPIOs.
The GPIO library already allows drivers and architecture support code to
reuse generic code for managing a GPIO chip. Currently, a developer has
to create a platform device "basic-mmio-gpio" and attach a bgpio_pdata
platform data structure to make use of it. However, for architectures
which rely on the device tree to enumerate devices, creating custom
platform devices is another extra step that can be avoided by having
direct support via a device tree binding.

I initially came across this patch [0] from ?lvaro Fern?ndez Rojas,
while looking for an easy way to add support for the GPIO of my
WD MyBook Live [1] (APM82181). His generic approach patch allowed
me to easily get the GPIO (and the connected LEDs, buttons, gpiohogs)
up and running. Even thought, Mr. Fernandez initially developed it
for his work on the brcm63xx [2].

The drivers for gpio-clps711x, gpio-ge, gpio-moxart and gpio-ts4800
are now part of the gpio-mmio.c driver. The old driver files have
been removed and the Kconfig, Makefile entries have been updated
accordingly.

And finally, the most important stat about the series:
	>>> 333 insertions(+), 411 deletions(-) <<<
	It still removes more lines than it adds!

Thanks!

[0] <https://patchwork.ozlabs.org/patch/422121/>
[1] <https://github.com/chunkeey/MBL-openwrt>
[2] <https://wiki.openwrt.org/doc/hardware/soc/soc.broadcom.bcm63xx>

changelog:

v6 -> v7:
	- finally made a PATCH series (based on linux-gpio devel branch)
	- added Rob Herring's ACK to the dt bindings
	- cc'd clps711x, gpio-ge, moxart and ts4800 authors for driver
	  changes.

v5 -> v6:
	- rewrote bindings and driver patch to fit the wd,mbl-gpio
	- unified parser code for gpio-ge, gpio-moxart and gpio-ts4800
	- fixed gpio chip's base being overwritten with bogus "0"
	- fixed compat driver crash when reload gpio-generic.ko module
	- dropped already applied patches from the series
	- rebased code on linus' devel tree
	- moved dt bindings patch to the top of the series

v4 -> v5:
	- reverted rename of gpio-mmio.c back to gpio-generic.c
	- fixed Andy Shevchenko's comments
	- consolidated changes from clps711x, gpio-ge, gpio-moxart and
	  gpio-ts4800 into one patch.

v3 -> v4:
	- renamed gpio-generic.c to gpio-mmio.c
	- changed compat. string to "linux,gpio-mmio"
	- integrated Cirrus clps711x driver
	- integrated GE FGPA gpio-ge driver
	- integrated MOXA ART GPIO driver
	- integrated TS4800 gpio driver
	- reshuffled patches, reworded commits, fixed spelling errors, etc.

Christian Lamparter (2):
  gpio: dt-bindings: add wd,mbl-gpio bindings
  gpio: move clps711x, moxart, ts4800 and gpio-ge into gpio-mmio

?lvaro Fern?ndez Rojas (1):
  gpio: mmio: add DT support for memory-mapped GPIOs

 .../devicetree/bindings/gpio/wd,mbl-gpio.txt       |  38 +++
 drivers/gpio/Kconfig                               |  43 +--
 drivers/gpio/Makefile                              |   4 -
 drivers/gpio/gpio-clps711x.c                       |  91 -------
 drivers/gpio/gpio-ge.c                             | 114 --------
 drivers/gpio/gpio-mmio.c                           | 289 ++++++++++++++++++++-
 drivers/gpio/gpio-moxart.c                         |  84 ------
 drivers/gpio/gpio-ts4800.c                         |  81 ------
 8 files changed, 333 insertions(+), 411 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
 delete mode 100644 drivers/gpio/gpio-clps711x.c
 delete mode 100644 drivers/gpio/gpio-ge.c
 delete mode 100644 drivers/gpio/gpio-moxart.c
 delete mode 100644 drivers/gpio/gpio-ts4800.c

-- 
2.8.1



From chunkeey at googlemail.com  Fri May  6 04:10:19 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Fri,  6 May 2016 13:10:19 +0200
Subject: [PATCH v7 1/3] gpio: dt-bindings: add wd,mbl-gpio bindings
In-Reply-To: <cover.1462372360.git.chunkeey@googlemail.com>
References: <cover.1462372360.git.chunkeey@googlemail.com>
Message-ID: <9bc9349d6e13d81c6200b0cd8fa20c76263043f6.1462372360.git.chunkeey@googlemail.com>

This patch adds the device tree bindings for the Western Digital's
MyBook Live memory-mapped GPIO controllers.

The gpios will be supported by gpio-mmio code of the
GPIO generic library.

Acked-by: Rob Herring <robh at kernel.org>
Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
---
 .../devicetree/bindings/gpio/wd,mbl-gpio.txt       | 38 ++++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt

diff --git a/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
new file mode 100644
index 0000000..038c3a6
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
@@ -0,0 +1,38 @@
+Bindings for the Western Digital's MyBook Live memory-mapped GPIO controllers.
+
+The Western Digital MyBook Live has two memory-mapped GPIO controllers.
+Both GPIO controller only have a single 8-bit data register, where GPIO
+state can be read and/or written.
+
+Required properties:
+	- compatible: should be "wd,mbl-gpio"
+	- reg-names: must contain
+		"dat" - data register
+	- reg: address + size pairs describing the GPIO register sets;
+		order must correspond with the order of entries in reg-names
+	- #gpio-cells: must be set to 2. The first cell is the pin number and
+			the second cell is used to specify the GPIO polarity:
+			0 = active high
+			1 = active low
+	- gpio-controller: marks the device node as a GPIO controller.
+
+Optional properties:
+	- no-output: GPIOs are read-only.
+
+Examples:
+	GPIO0: gpio0 at e0000000 {
+		compatible = "wd,mbl-gpio";
+		reg-names = "dat";
+		reg = <0xe0000000 0x1>;
+		#gpio-cells = <2>;
+		gpio-controller;
+	};
+
+	GPIO1: gpio1 at e0100000 {
+		compatible = "wd,mbl-gpio";
+		reg-names = "dat";
+		reg = <0xe0100000 0x1>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		no-output;
+	};
-- 
2.8.1



From chunkeey at googlemail.com  Fri May  6 04:10:20 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Fri,  6 May 2016 13:10:20 +0200
Subject: [PATCH v7 2/3] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <cover.1462372360.git.chunkeey@googlemail.com>
References: <cover.1462372360.git.chunkeey@googlemail.com>
Message-ID: <50f7f506364f84effd5224677b21726fd2e511a4.1462372360.git.chunkeey@googlemail.com>

From: ?lvaro Fern?ndez Rojas <noltari at gmail.com>

This patch adds support for defining memory-mapped GPIOs which
are compatible with the existing gpio-mmio interface. The generic
library provides support for many memory-mapped GPIO controllers
that are found in various on-board FPGA and ASIC solutions that
are used to control board's switches, LEDs, chip-selects,
Ethernet/USB PHY power, etc.

For setting GPIO's there are three configurations:
	1. single input/output register resource (named "dat"),
	2. set/clear pair (named "set" and "clr"),
	3. single output register resource and single input resource
	   ("set" and dat").

The configuration is detected by which resources are present.
For the single output register, this drives a 1 by setting a bit
and a zero by clearing a bit.  For the set clr pair, this drives
a 1 by setting a bit in the set register and clears it by setting
a bit in the clear register. The configuration is detected by
which resources are present.

For setting the GPIO direction, there are three configurations:
	a. simple bidirectional GPIOs that requires no configuration.
	b. an output direction register (named "dirout")
	   where a 1 bit indicates the GPIO is an output.
	c. an input direction register (named "dirin")
	   where a 1 bit indicates the GPIO is an input.

The first user for this binding is "wd,mbl-gpio".

Signed-off-by: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
---
 drivers/gpio/gpio-mmio.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 6c1cb3b..1cfb70a 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -61,6 +61,8 @@ o        `                     ~~~~\___/~~~~    ` controller in FPGA is ,.`
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
 #include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 static void bgpio_write8(void __iomem *reg, unsigned long data)
 {
@@ -569,6 +571,89 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
 	return devm_ioremap_resource(&pdev->dev, r);
 }
 
+#ifdef CONFIG_OF
+static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
+				     struct bgpio_pdata *pdata,
+				     unsigned long *flags)
+{
+	struct device *dev = &pdev->dev;
+	int err;
+
+	pdata->base = -1;
+	/* If ngpio property is not specified, of_property_read_u32
+	 * will return -EINVAL. In this case the number of GPIOs is
+	 * automatically determined by the register width. Any
+	 * other error of of_property_read_u32 is due bad data and
+	 * needs to be dealt with.
+	 */
+	err = of_property_read_u32(dev->of_node, "ngpio", &pdata->ngpio);
+	if (err && err != -EINVAL)
+		return err;
+
+	if (of_device_is_big_endian(dev->of_node))
+		*flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
+
+	if (of_property_read_bool(dev->of_node, "unreadable-reg-set"))
+		*flags |= BGPIOF_UNREADABLE_REG_SET;
+
+	if (of_property_read_bool(dev->of_node, "unreadable-reg-dir"))
+		*flags |= BGPIOF_UNREADABLE_REG_DIR;
+
+	if (of_property_read_bool(dev->of_node, "big-endian-byte-order"))
+		*flags |= BGPIOF_BIG_ENDIAN;
+
+	if (of_property_read_bool(dev->of_node, "read-output-reg-set"))
+		*flags |= BGPIOF_READ_OUTPUT_REG_SET;
+
+	if (of_property_read_bool(dev->of_node, "no-output"))
+		*flags |= BGPIOF_NO_OUTPUT;
+	return 0;
+}
+
+#define ADD_GPIO_OF(_name, _func) { .compatible = _name, .data = _func }
+
+static const struct of_device_id bgpio_of_match[] = {
+	ADD_GPIO_OF("wd,mbl-gpio", bgpio_basic_mmio_parse_dt),
+	{ }
+};
+#undef ADD_GPIO_OF
+MODULE_DEVICE_TABLE(of, bgpio_of_match);
+
+static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
+					  unsigned long *flags)
+{
+	const int (*parse_dt)(struct platform_device *,
+			      struct bgpio_pdata *, unsigned long *);
+	const struct device_node *node = pdev->dev.of_node;
+	const struct of_device_id *of_id;
+	struct bgpio_pdata *pdata;
+	int err = -ENODEV;
+
+	of_id = of_match_node(bgpio_of_match, node);
+	if (!of_id)
+		return NULL;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata),
+			     GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	parse_dt = (const void *)of_id->data;
+	if (parse_dt)
+		err = parse_dt(pdev, pdata, flags);
+	if (err)
+		return ERR_PTR(err);
+
+	return pdata;
+}
+#else
+static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
+					  unsigned long *flags)
+{
+	return NULL;
+}
+#endif /* CONFIG_OF */
+
 static int bgpio_pdev_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -579,10 +664,19 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
 	void __iomem *dirout;
 	void __iomem *dirin;
 	unsigned long sz;
-	unsigned long flags = pdev->id_entry->driver_data;
+	unsigned long flags = 0;
 	int err;
 	struct gpio_chip *gc;
-	struct bgpio_pdata *pdata = dev_get_platdata(dev);
+	struct bgpio_pdata *pdata;
+
+	pdata = bgpio_parse_dt(pdev, &flags);
+	if (IS_ERR(pdata))
+		return PTR_ERR(pdata);
+
+	if (!pdata) {
+		pdata = dev_get_platdata(dev);
+		flags = pdev->id_entry->driver_data;
+	}
 
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
 	if (!r)
@@ -646,6 +740,7 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table);
 static struct platform_driver bgpio_driver = {
 	.driver = {
 		.name = "basic-mmio-gpio",
+		.of_match_table = of_match_ptr(bgpio_of_match),
 	},
 	.id_table = bgpio_id_table,
 	.probe = bgpio_pdev_probe,
-- 
2.8.1



From chunkeey at googlemail.com  Fri May  6 04:10:21 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Fri,  6 May 2016 13:10:21 +0200
Subject: [PATCH v7 3/3] gpio: move clps711x, moxart,
 ts4800 and gpio-ge into gpio-mmio
In-Reply-To: <cover.1462372360.git.chunkeey@googlemail.com>
References: <cover.1462372360.git.chunkeey@googlemail.com>
Message-ID: <e936c3c38deee5cd954862c5ed11f9cffa2ba6a9.1462372360.git.chunkeey@googlemail.com>

This patch integrates these GPIO drivers into gpio-mmio.

Cc: Alexander Shiyan <shc_work at mail.ru>
Cc: Julien Grossholtz <julien.grossholtz at savoirfairelinux.com>
Cc: Martyn Welch <martyn.welch at ge.com>
Cc: Jonas Jensen <jonas.jensen at gmail.com>
Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
---
 drivers/gpio/Kconfig         |  43 ++--------
 drivers/gpio/Makefile        |   4 -
 drivers/gpio/gpio-clps711x.c |  91 ---------------------
 drivers/gpio/gpio-ge.c       | 114 --------------------------
 drivers/gpio/gpio-mmio.c     | 190 +++++++++++++++++++++++++++++++++++++++++++
 drivers/gpio/gpio-moxart.c   |  84 -------------------
 drivers/gpio/gpio-ts4800.c   |  81 ------------------
 7 files changed, 198 insertions(+), 409 deletions(-)
 delete mode 100644 drivers/gpio/gpio-clps711x.c
 delete mode 100644 drivers/gpio/gpio-ge.c
 delete mode 100644 drivers/gpio/gpio-moxart.c
 delete mode 100644 drivers/gpio/gpio-ts4800.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a68d838..d3c0d00 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -151,13 +151,6 @@ config GPIO_BRCMSTB
 	help
 	  Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs.
 
-config GPIO_CLPS711X
-	tristate "CLPS711X GPIO support"
-	depends on ARCH_CLPS711X || COMPILE_TEST
-	select GPIO_GENERIC
-	help
-	  Say yes here to support GPIO on CLPS711X SoCs.
-
 config GPIO_DAVINCI
 	bool "TI Davinci/Keystone GPIO support"
 	default y if ARCH_DAVINCI
@@ -193,22 +186,18 @@ config GPIO_ETRAXFS
 	help
 	  Say yes here to support the GPIO controller on Axis ETRAX FS SoCs.
 
-config GPIO_GE_FPGA
-	bool "GE FPGA based GPIO"
-	depends on GE_FPGA
-	select GPIO_GENERIC
-	help
-	  Support for common GPIO functionality provided on some GE Single Board
-	  Computers.
-
-	  This driver provides basic support (configure as input or output, read
-	  and write pin state) for GPIO implemented in a number of GE single
-	  board computers.
-
 config GPIO_GENERIC_PLATFORM
 	tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
 	select GPIO_GENERIC
 	help
+	  Select this to support many generic memory-mapped GPIO controllers.
+
+	  This driver also includes support for the following GPIOs:
+	    CLPS711X SoCs
+	    MOXA ART SoC
+	    TS-4800 FPGA DIO blocks and compatibles.
+	    GPIOs found on some GE Single Board Computers.
+
 	  Say yes here to support basic platform_device memory-mapped GPIO controllers.
 
 config GPIO_GRGPIO
@@ -285,14 +274,6 @@ config GPIO_MM_LANTIQ
 	  (EBU) found on Lantiq SoCs. The gpios are output only as they are
 	  created by attaching a 16bit latch to the bus.
 
-config GPIO_MOXART
-	bool "MOXART GPIO support"
-	depends on ARCH_MOXART || COMPILE_TEST
-	select GPIO_GENERIC
-	help
-	  Select this option to enable GPIO driver for
-	  MOXA ART SoC devices.
-
 config GPIO_MPC5200
 	def_bool y
 	depends on PPC_MPC52xx
@@ -404,14 +385,6 @@ config GPIO_TEGRA
 	default y
 	depends on ARCH_TEGRA || COMPILE_TEST
 
-config GPIO_TS4800
-	tristate "TS-4800 DIO blocks and compatibles"
-	depends on OF_GPIO
-	depends on SOC_IMX51 || COMPILE_TEST
-	select GPIO_GENERIC
-	help
-	  This driver support TS-4800 FPGA GPIO controllers.
-
 config GPIO_TZ1090
 	bool "Toumaz Xenif TZ1090 GPIO support"
 	depends on SOC_TZ1090
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 991598e..d8d63ae 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -31,7 +31,6 @@ obj-$(CONFIG_GPIO_ATH79)	+= gpio-ath79.o
 obj-$(CONFIG_GPIO_BCM_KONA)	+= gpio-bcm-kona.o
 obj-$(CONFIG_GPIO_BRCMSTB)	+= gpio-brcmstb.o
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
-obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o
 obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o
 obj-$(CONFIG_GPIO_CRYSTAL_COVE)	+= gpio-crystalcove.o
 obj-$(CONFIG_GPIO_DA9052)	+= gpio-da9052.o
@@ -43,7 +42,6 @@ obj-$(CONFIG_GPIO_EM)		+= gpio-em.o
 obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o
 obj-$(CONFIG_GPIO_ETRAXFS)	+= gpio-etraxfs.o
 obj-$(CONFIG_GPIO_F7188X)	+= gpio-f7188x.o
-obj-$(CONFIG_GPIO_GE_FPGA)	+= gpio-ge.o
 obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o
 obj-$(CONFIG_GPIO_ICH)		+= gpio-ich.o
 obj-$(CONFIG_GPIO_IOP)		+= gpio-iop.o
@@ -68,7 +66,6 @@ obj-$(CONFIG_GPIO_MC9S08DZ60)	+= gpio-mc9s08dz60.o
 obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)	+= gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MM_LANTIQ)	+= gpio-mm-lantiq.o
-obj-$(CONFIG_GPIO_MOXART)	+= gpio-moxart.o
 obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSIC)		+= gpio-msic.o
@@ -107,7 +104,6 @@ obj-$(CONFIG_GPIO_TPS65218)	+= gpio-tps65218.o
 obj-$(CONFIG_GPIO_TPS6586X)	+= gpio-tps6586x.o
 obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
 obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
-obj-$(CONFIG_GPIO_TS4800)	+= gpio-ts4800.o
 obj-$(CONFIG_GPIO_TS5500)	+= gpio-ts5500.o
 obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
 obj-$(CONFIG_GPIO_TWL6040)	+= gpio-twl6040.o
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
deleted file mode 100644
index 5a69025..0000000
--- a/drivers/gpio/gpio-clps711x.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  CLPS711X GPIO driver
- *
- *  Copyright (C) 2012,2013 Alexander Shiyan <shc_work at mail.ru>
- *
- * 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.
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/gpio/driver.h>
-#include <linux/platform_device.h>
-
-static int clps711x_gpio_probe(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	void __iomem *dat, *dir;
-	struct gpio_chip *gc;
-	struct resource *res;
-	int err, id = np ? of_alias_get_id(np, "gpio") : pdev->id;
-
-	if ((id < 0) || (id > 4))
-		return -ENODEV;
-
-	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	dat = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dat))
-		return PTR_ERR(dat);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	dir = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dir))
-		return PTR_ERR(dir);
-
-	switch (id) {
-	case 3:
-		/* PORTD is inverted logic for direction register */
-		err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
-				 NULL, dir, 0);
-		break;
-	default:
-		err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
-				 dir, NULL, 0);
-		break;
-	}
-
-	if (err)
-		return err;
-
-	switch (id) {
-	case 4:
-		/* PORTE is 3 lines only */
-		gc->ngpio = 3;
-		break;
-	default:
-		break;
-	}
-
-	gc->base = id * 8;
-	gc->owner = THIS_MODULE;
-	platform_set_drvdata(pdev, gc);
-
-	return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
-}
-
-static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = {
-	{ .compatible = "cirrus,clps711x-gpio" },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, clps711x_gpio_ids);
-
-static struct platform_driver clps711x_gpio_driver = {
-	.driver	= {
-		.name		= "clps711x-gpio",
-		.of_match_table	= of_match_ptr(clps711x_gpio_ids),
-	},
-	.probe	= clps711x_gpio_probe,
-};
-module_platform_driver(clps711x_gpio_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Alexander Shiyan <shc_work at mail.ru>");
-MODULE_DESCRIPTION("CLPS711X GPIO driver");
-MODULE_ALIAS("platform:clps711x-gpio");
diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c
deleted file mode 100644
index 8650b29..0000000
--- a/drivers/gpio/gpio-ge.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Driver for GE FPGA based GPIO
- *
- * Author: Martyn Welch <martyn.welch at ge.com>
- *
- * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-/* TODO
- *
- * Configuration of output modes (totem-pole/open-drain)
- * Interrupt configuration - interrupts are always generated the FPGA relies on
- * the I/O interrupt controllers mask to stop them propergating
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/of_address.h>
-#include <linux/module.h>
-#include <linux/gpio/driver.h>
-
-#define GEF_GPIO_DIRECT		0x00
-#define GEF_GPIO_IN		0x04
-#define GEF_GPIO_OUT		0x08
-#define GEF_GPIO_TRIG		0x0C
-#define GEF_GPIO_POLAR_A	0x10
-#define GEF_GPIO_POLAR_B	0x14
-#define GEF_GPIO_INT_STAT	0x18
-#define GEF_GPIO_OVERRUN	0x1C
-#define GEF_GPIO_MODE		0x20
-
-static const struct of_device_id gef_gpio_ids[] = {
-	{
-		.compatible	= "gef,sbc610-gpio",
-		.data		= (void *)19,
-	}, {
-		.compatible	= "gef,sbc310-gpio",
-		.data		= (void *)6,
-	}, {
-		.compatible	= "ge,imp3a-gpio",
-		.data		= (void *)16,
-	},
-	{ }
-};
-MODULE_DEVICE_TABLE(of, gef_gpio_ids);
-
-static int __init gef_gpio_probe(struct platform_device *pdev)
-{
-	const struct of_device_id *of_id =
-		of_match_device(gef_gpio_ids, &pdev->dev);
-	struct gpio_chip *gc;
-	void __iomem *regs;
-	int ret;
-
-	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	regs = of_iomap(pdev->dev.of_node, 0);
-	if (!regs)
-		return -ENOMEM;
-
-	ret = bgpio_init(gc, &pdev->dev, 4, regs + GEF_GPIO_IN,
-			 regs + GEF_GPIO_OUT, NULL, NULL,
-			 regs + GEF_GPIO_DIRECT, BGPIOF_BIG_ENDIAN_BYTE_ORDER);
-	if (ret) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		goto err0;
-	}
-
-	/* Setup pointers to chip functions */
-	gc->label = devm_kstrdup(&pdev->dev, pdev->dev.of_node->full_name,
-				     GFP_KERNEL);
-	if (!gc->label) {
-		ret = -ENOMEM;
-		goto err0;
-	}
-
-	gc->base = -1;
-	gc->ngpio = (u16)(uintptr_t)of_id->data;
-	gc->of_gpio_n_cells = 2;
-	gc->of_node = pdev->dev.of_node;
-
-	/* This function adds a memory mapped GPIO chip */
-	ret = devm_gpiochip_add_data(&pdev->dev, gc, NULL);
-	if (ret)
-		goto err0;
-
-	return 0;
-err0:
-	iounmap(regs);
-	pr_err("%s: GPIO chip registration failed\n",
-			pdev->dev.of_node->full_name);
-	return ret;
-};
-
-static struct platform_driver gef_gpio_driver = {
-	.driver = {
-		.name		= "gef-gpio",
-		.of_match_table	= gef_gpio_ids,
-	},
-};
-module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);
-
-MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
-MODULE_AUTHOR("Martyn Welch <martyn.welch at ge.com");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 1cfb70a..f116786 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -610,10 +610,200 @@ static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
 	return 0;
 }
 
+static int clps711x_parse_dt(struct platform_device *pdev,
+			     struct bgpio_pdata *pdata,
+			     unsigned long *flags)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	const char *dir_reg_name;
+	int id = np ? of_alias_get_id(np, "gpio") : pdev->id;
+
+	if ((id < 0) || (id > 4))
+		return -ENODEV;
+
+	/* PORTE is 3 lines only */
+	pdata->ngpio = (id == 4) ? 3 : /* determined by register width */ 0;
+
+	/* PORTD is inverted logic for direction register */
+	dir_reg_name = (id == 3) ? "dirin" : "dirout",
+
+	pdata->base = id * 8;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+	if (!res->name || strcmp("dat", res->name))
+		res->name = devm_kstrdup(&pdev->dev, "dat", GFP_KERNEL);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -EINVAL;
+	if (!res->name || strcmp(dir_reg_name, res->name))
+		res->name = devm_kstrdup(&pdev->dev, dir_reg_name, GFP_KERNEL);
+
+	return 0;
+}
+
+static int ge_dt_cb(struct platform_device *pdev,
+		    struct bgpio_pdata *pdata,
+		    unsigned long *flags)
+{
+	struct device_node *np = pdev->dev.of_node;
+
+	pdata->label = devm_kstrdup(&pdev->dev, np->full_name, GFP_KERNEL);
+	if (!pdata->label)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int moxart_dt_cb(struct platform_device *pdev,
+			struct bgpio_pdata *pdata,
+			unsigned long *flags)
+{
+	pdata->base = 0;
+	pdata->label = "moxart-gpio";
+	return 0;
+}
+
+
+static int ts4800_dt_cb(struct platform_device *pdev,
+			struct bgpio_pdata *pdata,
+			unsigned long *flags)
+{
+	int err;
+
+	err = of_property_read_u32(pdev->dev.of_node, "ngpios", &pdata->ngpio);
+	if (err == -EINVAL) {
+		pdata->ngpio = 16;
+		err = 0;
+	}
+	return err;
+}
+
+struct compat_gpio_device_data {
+	unsigned int expected_resource_size;
+	unsigned int ngpio;
+	resource_size_t register_width;
+	unsigned long flags;
+	int (*call_back)(struct platform_device *pdev,
+			 struct bgpio_pdata *pdata,
+			 unsigned long *flags);
+	struct resource_replacement {
+		resource_size_t start_offset;
+		const char *name;
+	} resources[5];
+};
+
+#define ADD_COMPAT_REGISTER(_name, _offset)	\
+	{ .name = (_name), .start_offset = (_offset) }
+
+#define ADD_COMPAT_GPIO(_comp, _sz, _ngpio, _width, _cb, _f, _res...)	\
+	{ .compatible = (_comp),					\
+	  .data = &(struct compat_gpio_device_data) {			\
+		.expected_resource_size = (_sz),			\
+		.ngpio = (_ngpio),					\
+		.register_width = (_width),				\
+		.flags = (_f),						\
+		.call_back = (_cb),					\
+		.resources = { _res },					\
+	}								\
+}
+
+#define ADD_COMPAT_GE_GPIO(_name, _ngpio)				\
+	ADD_COMPAT_GPIO(_name, 0x24, _ngpio, 0x4, ge_dt_cb,		\
+		 BGPIOF_BIG_ENDIAN_BYTE_ORDER,				\
+		 ADD_COMPAT_REGISTER("dat", 0x04),			\
+		 ADD_COMPAT_REGISTER("set", 0x08),			\
+		 ADD_COMPAT_REGISTER("dirin", 0x00))			\
+
+static const struct of_device_id compat_gpio_devices[] = {
+	ADD_COMPAT_GE_GPIO("ge,imp3a-gpio", 16),
+	ADD_COMPAT_GE_GPIO("gef,sbc310-gpio", 6),
+	ADD_COMPAT_GE_GPIO("gef,sbc610-gpio", 19),
+	ADD_COMPAT_GPIO("moxa,moxart-gpio", 0xc, 0, 0x4, moxart_dt_cb,
+		 BGPIOF_READ_OUTPUT_REG_SET,
+		 ADD_COMPAT_REGISTER("dat", 0x04),
+		 ADD_COMPAT_REGISTER("set", 0x00),
+		 ADD_COMPAT_REGISTER("dirout", 0x08)),
+	ADD_COMPAT_GPIO("technologic,ts4800-gpio", 0x6, 16, 0x2, ts4800_dt_cb,
+		 0, ADD_COMPAT_REGISTER("dat", 0x00),
+		 ADD_COMPAT_REGISTER("set", 0x02),
+		 ADD_COMPAT_REGISTER("dirout", 0x04)),
+};
+
+#undef ADD_COMPAT_GE_GPIO
+#undef ADD_COMPAT_GPIO
+#undef ADD_COMPAT_REGISTER
+
+static int compat_parse_dt(struct platform_device *pdev,
+			   struct bgpio_pdata *pdata,
+			   unsigned long *flags)
+{
+	const struct device_node *node = pdev->dev.of_node;
+	const struct compat_gpio_device_data *entry;
+	const struct of_device_id *of_id;
+	struct resource *res;
+	int err;
+
+	of_id = of_match_node(compat_gpio_devices, node);
+	if (!of_id)
+		return -ENODEV;
+
+	entry = of_id->data;
+	if (!entry || !entry->resources[0].name)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	if (!res->name || strcmp(entry->resources[0].name, res->name)) {
+		struct resource nres[ARRAY_SIZE(entry->resources)];
+		int i;
+
+		if (resource_size(res) != entry->expected_resource_size)
+			return -EINVAL;
+
+		for (i = 0; i < ARRAY_SIZE(entry->resources); i++) {
+			if (!entry->resources[i].name)
+				continue;
+
+			nres[i].name = devm_kstrdup(&pdev->dev,
+				entry->resources[i].name, GFP_KERNEL);
+			nres[i].start = res->start +
+				entry->resources[i].start_offset;
+			nres[i].end = nres[i].start +
+				entry->register_width - 1;
+			nres[i].flags = IORESOURCE_MEM;
+		}
+
+		err = platform_device_add_resources(pdev, nres, i);
+		if (err)
+			return err;
+	}
+
+	pdata->base = -1;
+	pdata->ngpio = entry->ngpio;
+	*flags = entry->flags;
+
+	if (entry->call_back)
+		err = entry->call_back(pdev, pdata, flags);
+
+	return err;
+}
+
 #define ADD_GPIO_OF(_name, _func) { .compatible = _name, .data = _func }
 
 static const struct of_device_id bgpio_of_match[] = {
 	ADD_GPIO_OF("wd,mbl-gpio", bgpio_basic_mmio_parse_dt),
+	ADD_GPIO_OF("cirrus,clps711x-gpio", clps711x_parse_dt),
+	ADD_GPIO_OF("ge,imp3a-gpio", compat_parse_dt),
+	ADD_GPIO_OF("gef,sbc310-gpio", compat_parse_dt),
+	ADD_GPIO_OF("gef,sbc610-gpio", compat_parse_dt),
+	ADD_GPIO_OF("moxa,moxart-gpio", compat_parse_dt),
+	ADD_GPIO_OF("technologic,ts4800-gpio", compat_parse_dt),
 	{ }
 };
 #undef ADD_GPIO_OF
diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c
deleted file mode 100644
index d58d389..0000000
--- a/drivers/gpio/gpio-moxart.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * MOXA ART SoCs GPIO driver.
- *
- * Copyright (C) 2013 Jonas Jensen
- *
- * Jonas Jensen <jonas.jensen at gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/of_address.h>
-#include <linux/of_gpio.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/bitops.h>
-#include <linux/gpio/driver.h>
-
-#define GPIO_DATA_OUT		0x00
-#define GPIO_DATA_IN		0x04
-#define GPIO_PIN_DIRECTION	0x08
-
-static int moxart_gpio_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct resource *res;
-	struct gpio_chip *gc;
-	void __iomem *base;
-	int ret;
-
-	gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	ret = bgpio_init(gc, dev, 4, base + GPIO_DATA_IN,
-			 base + GPIO_DATA_OUT, NULL,
-			 base + GPIO_PIN_DIRECTION, NULL,
-			 BGPIOF_READ_OUTPUT_REG_SET);
-	if (ret) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		return ret;
-	}
-
-	gc->label = "moxart-gpio";
-	gc->request = gpiochip_generic_request;
-	gc->free = gpiochip_generic_free;
-	gc->base = 0;
-	gc->owner = THIS_MODULE;
-
-	ret = devm_gpiochip_add_data(dev, gc, NULL);
-	if (ret) {
-		dev_err(dev, "%s: gpiochip_add failed\n",
-			dev->of_node->full_name);
-		return ret;
-	}
-
-	return ret;
-}
-
-static const struct of_device_id moxart_gpio_match[] = {
-	{ .compatible = "moxa,moxart-gpio" },
-	{ }
-};
-
-static struct platform_driver moxart_gpio_driver = {
-	.driver	= {
-		.name		= "moxart-gpio",
-		.of_match_table	= moxart_gpio_match,
-	},
-	.probe	= moxart_gpio_probe,
-};
-builtin_platform_driver(moxart_gpio_driver);
diff --git a/drivers/gpio/gpio-ts4800.c b/drivers/gpio/gpio-ts4800.c
deleted file mode 100644
index 0c144a7..0000000
--- a/drivers/gpio/gpio-ts4800.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * GPIO driver for the TS-4800 board
- *
- * Copyright (c) 2016 - Savoir-faire Linux
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/gpio/driver.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-
-#define DEFAULT_PIN_NUMBER      16
-#define INPUT_REG_OFFSET        0x00
-#define OUTPUT_REG_OFFSET       0x02
-#define DIRECTION_REG_OFFSET    0x04
-
-static int ts4800_gpio_probe(struct platform_device *pdev)
-{
-	struct device_node *node;
-	struct gpio_chip *chip;
-	struct resource *res;
-	void __iomem *base_addr;
-	int retval;
-	u32 ngpios;
-
-	chip = devm_kzalloc(&pdev->dev, sizeof(struct gpio_chip), GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base_addr = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(base_addr))
-		return PTR_ERR(base_addr);
-
-	node = pdev->dev.of_node;
-	if (!node)
-		return -EINVAL;
-
-	retval = of_property_read_u32(node, "ngpios", &ngpios);
-	if (retval == -EINVAL)
-		ngpios = DEFAULT_PIN_NUMBER;
-	else if (retval)
-		return retval;
-
-	retval = bgpio_init(chip, &pdev->dev, 2, base_addr + INPUT_REG_OFFSET,
-			    base_addr + OUTPUT_REG_OFFSET, NULL,
-			    base_addr + DIRECTION_REG_OFFSET, NULL, 0);
-	if (retval) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		return retval;
-	}
-
-	chip->ngpio = ngpios;
-
-	platform_set_drvdata(pdev, chip);
-
-	return devm_gpiochip_add_data(&pdev->dev, chip, NULL);
-}
-
-static const struct of_device_id ts4800_gpio_of_match[] = {
-	{ .compatible = "technologic,ts4800-gpio", },
-	{},
-};
-
-static struct platform_driver ts4800_gpio_driver = {
-	.driver = {
-		   .name = "ts4800-gpio",
-		   .of_match_table = ts4800_gpio_of_match,
-		   },
-	.probe = ts4800_gpio_probe,
-};
-
-module_platform_driver_probe(ts4800_gpio_driver, ts4800_gpio_probe);
-
-MODULE_AUTHOR("Julien Grossholtz <julien.grossholtz at savoirfairelinux.com>");
-MODULE_DESCRIPTION("TS4800 FPGA GPIO driver");
-MODULE_LICENSE("GPL v2");
-- 
2.8.1



From catalin.marinas at arm.com  Fri May  6 04:19:37 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 6 May 2016 12:19:37 +0100
Subject: [PATCH] arm64: Make arch_randomize_brk avoid stack area
In-Reply-To: <1462370994.2895.11.camel@linaro.org>
References: <1461848638.2848.19.camel@linaro.org>
 <1462370994.2895.11.camel@linaro.org>
Message-ID: <20160506111937.GK20671@e104818-lin.cambridge.arm.com>

Hi Tixy,

On Wed, May 04, 2016 at 03:09:54PM +0100, Jon Medhurst (Tixy) wrote:
> Note, in practice, since commit d1fd836dcf00 ("mm: split ET_DYN ASLR
> from mmap ASLR") this problem shouldn't occur because the address chosen
> for loading binaries is well clear of the stack, however, prior to that
> the problem does occur because of the following...

[...]

> These changes have been tested on Linux v4.6-rc4 using 100000
> invocations of a program [1] that can display the offset of a process's
> brk...

[...]

> Signed-off-by: Jon Medhurst <tixy at linaro.org>
> Cc: <stable at vger.kernel.org> # 4.0 and earlier

I don't fully understand what we are supposed to do with this patch.
Should it only be applied to stable kernels prior to 4.0? Do we need it
in mainline? As you stated above, this problem does not exist in recent
kernels.

-- 
Catalin


From sricharan at codeaurora.org  Fri May  6 04:31:12 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Fri,  6 May 2016 17:01:12 +0530
Subject: [PATCH V2 0/2] drivers: i2c: qup: Some misc fixes
Message-ID: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>

One for fixing the bug with CONFIG_DEBUG_SG enabled and another
to suspend the transfer for all errors instead of just for nack.

Sricharan R (2):
  drivers: i2c: qup: Fix broken dma when CONFIG_DEBUG_SG is enabled.
  drivers: i2c: qup: Fix error handling

 drivers/i2c/busses/i2c-qup.c | 87 +++++++++++++++++++++-----------------------
 1 file changed, 42 insertions(+), 45 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Fri May  6 04:31:13 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Fri,  6 May 2016 17:01:13 +0530
Subject: [PATCH V2 1/2] drivers: i2c: qup: Fix broken dma when CONFIG_DEBUG_SG
 is enabled
In-Reply-To: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>
References: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1462534274-28925-2-git-send-email-sricharan@codeaurora.org>

With CONFIG_DEBUG_SG is enabled and when dma mode is used, below dump is seen, 

------------[ cut here ]------------ 
kernel BUG at include/linux/scatterlist.h:140! 
Internal error: Oops - BUG: 0 [#1] PREEMPT SMP 
Modules linked in: 
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.0-00459-g9f087b9-dirty #7 
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT) 
task: ffffffc036868000 ti: ffffffc036870000 task.ti: ffffffc036870000 
PC is at qup_sg_set_buf.isra.13+0x138/0x154 
LR is at qup_sg_set_buf.isra.13+0x50/0x154 
pc : [<ffffffc0005a0ed8>] lr : [<ffffffc0005a0df0>] pstate: 60000145 
sp : ffffffc0368735c0 
x29: ffffffc0368735c0 x28: ffffffc036873752 
x27: ffffffc035233018 x26: ffffffc000c4e000 
x25: 0000000000000000 x24: 0000000000000004 
x23: 0000000000000000 x22: ffffffc035233668 
x21: ffffff80004e3000 x20: ffffffc0352e0018 
x19: 0000004000000000 x18: 0000000000000028 
x17: 0000000000000004 x16: ffffffc0017a39c8 
x15: 0000000000001cdf x14: ffffffc0019929d8 
x13: ffffffc0352e0018 x12: 0000000000000000 
x11: 0000000000000001 x10: 0000000000000001 
x9 : ffffffc0012b2d70 x8 : ffffff80004e3000 
x7 : 0000000000000018 x6 : 0000000030000000 
x5 : ffffffc00199f018 x4 : ffffffc035233018 
x3 : 0000000000000004 x2 : 00000000c0000000 
x1 : 0000000000000003 x0 : 0000000000000000 

Process swapper/0 (pid: 1, stack limit = 0xffffffc036870020) 
Stack: (0xffffffc0368735c0 to 0xffffffc036874000) 

Change allocation of sg buffers from dma_coherent memory to kzalloc 
to fix the issue. 

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
Reviewed-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/i2c/busses/i2c-qup.c | 53 ++++++++++++++------------------------------
 1 file changed, 17 insertions(+), 36 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 23eaabb..8620e99 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -585,8 +585,8 @@ static void qup_i2c_bam_cb(void *data)
 }
 
 static int qup_sg_set_buf(struct scatterlist *sg, void *buf,
-			  struct qup_i2c_tag *tg, unsigned int buflen,
-			  struct qup_i2c_dev *qup, int map, int dir)
+			  unsigned int buflen, struct qup_i2c_dev *qup,
+			  int dir)
 {
 	int ret;
 
@@ -595,9 +595,6 @@ static int qup_sg_set_buf(struct scatterlist *sg, void *buf,
 	if (!ret)
 		return -EINVAL;
 
-	if (!map)
-		sg_dma_address(sg) = tg->addr + ((u8 *)buf - tg->start);
-
 	return 0;
 }
 
@@ -670,16 +667,15 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 				/* scratch buf to read the start and len tags */
 				ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
 						     &qup->brx.tag.start[0],
-						     &qup->brx.tag,
-						     2, qup, 0, 0);
+						     2, qup, DMA_FROM_DEVICE);
 
 				if (ret)
 					return ret;
 
 				ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
 						     &msg->buf[limit * i],
-						     NULL, tlen, qup,
-						     1, DMA_FROM_DEVICE);
+						     tlen, qup,
+						     DMA_FROM_DEVICE);
 				if (ret)
 					return ret;
 
@@ -688,7 +684,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 			}
 			ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
 					     &qup->start_tag.start[off],
-					     &qup->start_tag, len, qup, 0, 0);
+					     len, qup, DMA_TO_DEVICE);
 			if (ret)
 				return ret;
 
@@ -696,8 +692,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 			/* scratch buf to read the BAM EOT and FLUSH tags */
 			ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
 					     &qup->brx.tag.start[0],
-					     &qup->brx.tag, 2,
-					     qup, 0, 0);
+					     2, qup, DMA_FROM_DEVICE);
 			if (ret)
 				return ret;
 		} else {
@@ -709,17 +704,15 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 				len = qup_i2c_set_tags(tags, qup, msg, 1);
 
 				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
-						     tags,
-						     &qup->start_tag, len,
-						     qup, 0, 0);
+						     tags, len,
+						     qup, DMA_TO_DEVICE);
 				if (ret)
 					return ret;
 
 				tx_len += len;
 				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
 						     &msg->buf[limit * i],
-						     NULL, tlen, qup, 1,
-						     DMA_TO_DEVICE);
+						     tlen, qup, DMA_TO_DEVICE);
 				if (ret)
 					return ret;
 				i++;
@@ -738,8 +731,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 							QUP_BAM_FLUSH_STOP;
 				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
 						     &qup->btx.tag.start[0],
-						     &qup->btx.tag, len,
-						     qup, 0, 0);
+						     len, qup, DMA_TO_DEVICE);
 				if (ret)
 					return ret;
 				tx_nents += 1;
@@ -1268,6 +1260,8 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
 		}
 	}
 
+	idx = 0;
+
 	do {
 		if (msgs[idx].len == 0) {
 			ret = -EINVAL;
@@ -1407,27 +1401,21 @@ static int qup_i2c_probe(struct platform_device *pdev)
 
 		/* 2 tag bytes for each block + 5 for start, stop tags */
 		size = blocks * 2 + 5;
-		qup->dpool = dma_pool_create("qup_i2c-dma-pool", &pdev->dev,
-					     size, 4, 0);
 
-		qup->start_tag.start = dma_pool_alloc(qup->dpool, GFP_KERNEL,
-						      &qup->start_tag.addr);
+		qup->start_tag.start = devm_kzalloc(&pdev->dev,
+						    size, GFP_KERNEL);
 		if (!qup->start_tag.start) {
 			ret = -ENOMEM;
 			goto fail_dma;
 		}
 
-		qup->brx.tag.start = dma_pool_alloc(qup->dpool,
-						    GFP_KERNEL,
-						    &qup->brx.tag.addr);
+		qup->brx.tag.start = devm_kzalloc(&pdev->dev, 2, GFP_KERNEL);
 		if (!qup->brx.tag.start) {
 			ret = -ENOMEM;
 			goto fail_dma;
 		}
 
-		qup->btx.tag.start = dma_pool_alloc(qup->dpool,
-						    GFP_KERNEL,
-						    &qup->btx.tag.addr);
+		qup->btx.tag.start = devm_kzalloc(&pdev->dev, 2, GFP_KERNEL);
 		if (!qup->btx.tag.start) {
 			ret = -ENOMEM;
 			goto fail_dma;
@@ -1566,13 +1554,6 @@ static int qup_i2c_remove(struct platform_device *pdev)
 	struct qup_i2c_dev *qup = platform_get_drvdata(pdev);
 
 	if (qup->is_dma) {
-		dma_pool_free(qup->dpool, qup->start_tag.start,
-			      qup->start_tag.addr);
-		dma_pool_free(qup->dpool, qup->brx.tag.start,
-			      qup->brx.tag.addr);
-		dma_pool_free(qup->dpool, qup->btx.tag.start,
-			      qup->btx.tag.addr);
-		dma_pool_destroy(qup->dpool);
 		dma_release_channel(qup->btx.dma);
 		dma_release_channel(qup->brx.dma);
 	}
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Fri May  6 04:31:14 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Fri,  6 May 2016 17:01:14 +0530
Subject: [PATCH V2 2/2] drivers: i2c: qup: Fix error handling
In-Reply-To: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>
References: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1462534274-28925-3-git-send-email-sricharan@codeaurora.org>

Among the bus errors reported from the QUP_MASTER_STATUS register
only NACK is considered and transfer gets suspended, while
other errors are ignored. Correct this and suspend the transfer
for other errors as well. This avoids unnessecary 'timeouts' which
happens when waiting for events that would never happen when there
is already an error condition on the bus.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
Reviewed-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/i2c/busses/i2c-qup.c | 42 +++++++++++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 13 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 8620e99..af52a47 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -310,6 +310,7 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
 	u32 opflags;
 	u32 status;
 	u32 shift = __ffs(op);
+	int ret = 0;
 
 	len *= qup->one_byte_t;
 	/* timeout after a wait of twice the max time */
@@ -321,18 +322,31 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
 
 		if (((opflags & op) >> shift) == val) {
 			if ((op == QUP_OUT_NOT_EMPTY) && qup->is_last) {
-				if (!(status & I2C_STATUS_BUS_ACTIVE))
-					return 0;
+				if (!(status & I2C_STATUS_BUS_ACTIVE)) {
+					ret = 0;
+					goto done;
+				}
 			} else {
-				return 0;
+				ret = 0;
+				goto done;
 			}
 		}
 
-		if (time_after(jiffies, timeout))
-			return -ETIMEDOUT;
-
+		if (time_after(jiffies, timeout)) {
+			ret = -ETIMEDOUT;
+			goto done;
+		}
 		usleep_range(len, len * 2);
 	}
+
+done:
+	if (qup->bus_err || qup->qup_err) {
+		if (qup->bus_err & QUP_I2C_NACK_FLAG)
+			dev_err(qup->dev, "NACK from %x\n", qup->msg->addr);
+		ret = -EIO;
+	}
+
+	return ret;
 }
 
 static void qup_i2c_set_write_mode_v2(struct qup_i2c_dev *qup,
@@ -796,7 +810,6 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 		if (qup->bus_err & QUP_I2C_NACK_FLAG) {
 			msg--;
 			dev_err(qup->dev, "NACK from %x\n", msg->addr);
-			ret = -EIO;
 
 			if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
 				dev_err(qup->dev, "change to run state timed out");
@@ -818,6 +831,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 
 			qup_i2c_rel_dma(qup);
 		}
+		ret = -EIO;
 	}
 
 	dma_unmap_sg(qup->dev, qup->btx.sg, tx_nents, DMA_TO_DEVICE);
@@ -841,9 +855,6 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
 	if (ret)
 		goto out;
 
-	qup->bus_err = 0;
-	qup->qup_err = 0;
-
 	writel(0, qup->base + QUP_MX_INPUT_CNT);
 	writel(0, qup->base + QUP_MX_OUTPUT_CNT);
 
@@ -882,10 +893,9 @@ static int qup_i2c_wait_for_complete(struct qup_i2c_dev *qup,
 	}
 
 	if (qup->bus_err || qup->qup_err) {
-		if (qup->bus_err & QUP_I2C_NACK_FLAG) {
+		if (qup->bus_err & QUP_I2C_NACK_FLAG)
 			dev_err(qup->dev, "NACK from %x\n", msg->addr);
-			ret = -EIO;
-		}
+		ret = -EIO;
 	}
 
 	return ret;
@@ -1178,6 +1188,9 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 	if (ret < 0)
 		goto out;
 
+	qup->bus_err = 0;
+	qup->qup_err = 0;
+
 	writel(1, qup->base + QUP_SW_RESET);
 	ret = qup_i2c_poll_state(qup, QUP_RESET_STATE);
 	if (ret)
@@ -1227,6 +1240,9 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
 	int ret, len, idx = 0, use_dma = 0;
 
+	qup->bus_err = 0;
+	qup->qup_err = 0;
+
 	ret = pm_runtime_get_sync(qup->dev);
 	if (ret < 0)
 		goto out;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From andy.shevchenko at gmail.com  Fri May  6 04:44:14 2016
From: andy.shevchenko at gmail.com (Andy Shevchenko)
Date: Fri, 6 May 2016 14:44:14 +0300
Subject: [PATCH v7 2/3] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <50f7f506364f84effd5224677b21726fd2e511a4.1462372360.git.chunkeey@googlemail.com>
References: <cover.1462372360.git.chunkeey@googlemail.com>
 <50f7f506364f84effd5224677b21726fd2e511a4.1462372360.git.chunkeey@googlemail.com>
Message-ID: <CAHp75VcDPY+LbV5+j9DUMJ8Ws=O9=+KmAa9Nog-JuKkPGAM6Cw@mail.gmail.com>

On Fri, May 6, 2016 at 2:10 PM, Christian Lamparter
<chunkeey at googlemail.com> wrote:
> From: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
>
> This patch adds support for defining memory-mapped GPIOs which
> are compatible with the existing gpio-mmio interface. The generic
> library provides support for many memory-mapped GPIO controllers
> that are found in various on-board FPGA and ASIC solutions that
> are used to control board's switches, LEDs, chip-selects,
> Ethernet/USB PHY power, etc.
>
> For setting GPIO's there are three configurations:
>         1. single input/output register resource (named "dat"),
>         2. set/clear pair (named "set" and "clr"),
>         3. single output register resource and single input resource
>            ("set" and dat").
>
> The configuration is detected by which resources are present.
> For the single output register, this drives a 1 by setting a bit
> and a zero by clearing a bit.  For the set clr pair, this drives
> a 1 by setting a bit in the set register and clears it by setting
> a bit in the clear register. The configuration is detected by
> which resources are present.
>
> For setting the GPIO direction, there are three configurations:
>         a. simple bidirectional GPIOs that requires no configuration.
>         b. an output direction register (named "dirout")
>            where a 1 bit indicates the GPIO is an output.
>         c. an input direction register (named "dirin")
>            where a 1 bit indicates the GPIO is an input.
>
> The first user for this binding is "wd,mbl-gpio".

Some (mostly) style issues below.

> @@ -569,6 +571,89 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
>         return devm_ioremap_resource(&pdev->dev, r);
>  }
>
> +#ifdef CONFIG_OF
> +static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
> +                                    struct bgpio_pdata *pdata,
> +                                    unsigned long *flags)
> +{
> +       struct device *dev = &pdev->dev;
> +       int err;
> +
> +       pdata->base = -1;

+ empty line

> +       /* If ngpio property is not specified, of_property_read_u32
> +        * will return -EINVAL. In this case the number of GPIOs is
> +        * automatically determined by the register width. Any
> +        * other error of of_property_read_u32 is due bad data and
> +        * needs to be dealt with.

Couple style issues:
/*
 * First sentence starts here. func() are going with parens.
 */

> +        */
> +       err = of_property_read_u32(dev->of_node, "ngpio", &pdata->ngpio);
> +       if (err && err != -EINVAL)
> +               return err;
> +
> +       if (of_device_is_big_endian(dev->of_node))
> +               *flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
> +
> +       if (of_property_read_bool(dev->of_node, "unreadable-reg-set"))
> +               *flags |= BGPIOF_UNREADABLE_REG_SET;
> +
> +       if (of_property_read_bool(dev->of_node, "unreadable-reg-dir"))
> +               *flags |= BGPIOF_UNREADABLE_REG_DIR;
> +
> +       if (of_property_read_bool(dev->of_node, "big-endian-byte-order"))
> +               *flags |= BGPIOF_BIG_ENDIAN;
> +
> +       if (of_property_read_bool(dev->of_node, "read-output-reg-set"))
> +               *flags |= BGPIOF_READ_OUTPUT_REG_SET;
> +
> +       if (of_property_read_bool(dev->of_node, "no-output"))
> +               *flags |= BGPIOF_NO_OUTPUT;
> +       return 0;
> +}
> +
> +#define ADD_GPIO_OF(_name, _func) { .compatible = _name, .data = _func }
> +
> +static const struct of_device_id bgpio_of_match[] = {
> +       ADD_GPIO_OF("wd,mbl-gpio", bgpio_basic_mmio_parse_dt),
> +       { }
> +};
> +#undef ADD_GPIO_OF
> +MODULE_DEVICE_TABLE(of, bgpio_of_match);
> +
> +static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
> +                                         unsigned long *flags)
> +{
> +       const int (*parse_dt)(struct platform_device *,
> +                             struct bgpio_pdata *, unsigned long *);
> +       const struct device_node *node = pdev->dev.of_node;
> +       const struct of_device_id *of_id;
> +       struct bgpio_pdata *pdata;
> +       int err = -ENODEV;

(1)

> +
> +       of_id = of_match_node(bgpio_of_match, node);
> +       if (!of_id)
> +               return NULL;

(2)

Why so?

> +
> +       pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata),
> +                            GFP_KERNEL);
> +       if (!pdata)
> +               return ERR_PTR(-ENOMEM);
> +
> +       parse_dt = (const void *)of_id->data;
> +       if (parse_dt)
> +               err = parse_dt(pdev, pdata, flags);
> +       if (err)
> +               return ERR_PTR(err);
> +
> +       return pdata;
> +}
> +#else
> +static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
> +                                         unsigned long *flags)
> +{
> +       return NULL;
> +}
> +#endif /* CONFIG_OF */



-- 
With Best Regards,
Andy Shevchenko


From mark.rutland at arm.com  Fri May  6 04:50:10 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Fri, 6 May 2016 12:50:10 +0100
Subject: [PATCH v7 2/3] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <50f7f506364f84effd5224677b21726fd2e511a4.1462372360.git.chunkeey@googlemail.com>
References: <cover.1462372360.git.chunkeey@googlemail.com>
 <50f7f506364f84effd5224677b21726fd2e511a4.1462372360.git.chunkeey@googlemail.com>
Message-ID: <20160506114916.GA18053@leverpostej>

Hi,

On Fri, May 06, 2016 at 01:10:20PM +0200, Christian Lamparter wrote:
> +static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
> +				     struct bgpio_pdata *pdata,
> +				     unsigned long *flags)
> +{
> +	struct device *dev = &pdev->dev;
> +	int err;
> +
> +	pdata->base = -1;
> +	/* If ngpio property is not specified, of_property_read_u32
> +	 * will return -EINVAL. In this case the number of GPIOs is
> +	 * automatically determined by the register width. Any
> +	 * other error of of_property_read_u32 is due bad data and
> +	 * needs to be dealt with.
> +	 */
> +	err = of_property_read_u32(dev->of_node, "ngpio", &pdata->ngpio);
> +	if (err && err != -EINVAL)
> +		return err;
> +
> +	if (of_device_is_big_endian(dev->of_node))
> +		*flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
> +
> +	if (of_property_read_bool(dev->of_node, "unreadable-reg-set"))
> +		*flags |= BGPIOF_UNREADABLE_REG_SET;
> +
> +	if (of_property_read_bool(dev->of_node, "unreadable-reg-dir"))
> +		*flags |= BGPIOF_UNREADABLE_REG_DIR;
> +
> +	if (of_property_read_bool(dev->of_node, "big-endian-byte-order"))
> +		*flags |= BGPIOF_BIG_ENDIAN;
> +
> +	if (of_property_read_bool(dev->of_node, "read-output-reg-set"))
> +		*flags |= BGPIOF_READ_OUTPUT_REG_SET;
> +
> +	if (of_property_read_bool(dev->of_node, "no-output"))
> +		*flags |= BGPIOF_NO_OUTPUT;
> +	return 0;
> +}

Other than no-output, none of these are in the wd,mbl-gpio binding.

Please remove them for now. We can add them as/when other users of this
binding appear and begin to need them.

Thanks,
Mark.


From tixy at linaro.org  Fri May  6 04:51:00 2016
From: tixy at linaro.org (Jon Medhurst (Tixy))
Date: Fri, 06 May 2016 12:51:00 +0100
Subject: [PATCH] arm64: Make arch_randomize_brk avoid stack area
In-Reply-To: <20160506111937.GK20671@e104818-lin.cambridge.arm.com>
References: <1461848638.2848.19.camel@linaro.org>
 <1462370994.2895.11.camel@linaro.org>
 <20160506111937.GK20671@e104818-lin.cambridge.arm.com>
Message-ID: <1462535460.4575.3.camel@linaro.org>

On Fri, 2016-05-06 at 12:19 +0100, Catalin Marinas wrote:
> Hi Tixy,
> 
> On Wed, May 04, 2016 at 03:09:54PM +0100, Jon Medhurst (Tixy) wrote:
> > Note, in practice, since commit d1fd836dcf00 ("mm: split ET_DYN ASLR
> > from mmap ASLR") this problem shouldn't occur because the address chosen
> > for loading binaries is well clear of the stack, however, prior to that
> > the problem does occur because of the following...
> 
> [...]
> 
> > These changes have been tested on Linux v4.6-rc4 using 100000
> > invocations of a program [1] that can display the offset of a process's
> > brk...
> 
> [...]
> 
> > Signed-off-by: Jon Medhurst <tixy at linaro.org>
> > Cc: <stable at vger.kernel.org> # 4.0 and earlier
> 
> I don't fully understand what we are supposed to do with this patch.
> Should it only be applied to stable kernels prior to 4.0? Do we need it
> in mainline? As you stated above, this problem does not exist in recent
> kernels.

Well, if you think it's worthwhile defensive programming against future
changes to elf loader, then it could go into latest kernels. Otherwise,
then yes, it's for Linux 4.0 and earlier. What's the process for that,
email it to stable at vger.kernel.org direct? Is that OK without an Ack
from an arm64 maintainer?

-- 
Tixy




From andy.shevchenko at gmail.com  Fri May  6 04:53:24 2016
From: andy.shevchenko at gmail.com (Andy Shevchenko)
Date: Fri, 6 May 2016 14:53:24 +0300
Subject: [PATCH v7 3/3] gpio: move clps711x, moxart, ts4800 and gpio-ge
 into gpio-mmio
In-Reply-To: <e936c3c38deee5cd954862c5ed11f9cffa2ba6a9.1462372360.git.chunkeey@googlemail.com>
References: <cover.1462372360.git.chunkeey@googlemail.com>
 <e936c3c38deee5cd954862c5ed11f9cffa2ba6a9.1462372360.git.chunkeey@googlemail.com>
Message-ID: <CAHp75VeFjcPX+f3j+h+OL2jEpfGP+aqL78ymcsj4JwUfO0RvtA@mail.gmail.com>

On Fri, May 6, 2016 at 2:10 PM, Christian Lamparter
<chunkeey at googlemail.com> wrote:
> This patch integrates these GPIO drivers into gpio-mmio.

Would be nice to repeat a list here.

>  config GPIO_GENERIC_PLATFORM
>         tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
>         select GPIO_GENERIC
>         help
> +         Select this to support many generic memory-mapped GPIO controllers.
> +
> +         This driver also includes support for the following GPIOs:
> +           CLPS711X SoCs
> +           MOXA ART SoC
> +           TS-4800 FPGA DIO blocks and compatibles.
> +           GPIOs found on some GE Single Board Computers.
> +
>           Say yes here to support basic platform_device memory-mapped GPIO controllers.
>
>  config GPIO_GRGPIO
> @@ -285,14 +274,6 @@ config GPIO_MM_LANTIQ
>           (EBU) found on Lantiq SoCs. The gpios are output only as they are
>           created by attaching a 16bit latch to the bus.
>
> -config GPIO_MOXART
> -       bool "MOXART GPIO support"
> -       depends on ARCH_MOXART || COMPILE_TEST
> -       select GPIO_GENERIC
> -       help
> -         Select this option to enable GPIO driver for
> -         MOXA ART SoC devices.
> -

Doesn't it change behaviour? So, as a user of old .config I expect to
have driver enabled. How is it achieved now?

> --- a/drivers/gpio/gpio-mmio.c
> +++ b/drivers/gpio/gpio-mmio.c
> @@ -610,10 +610,200 @@ static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
>         return 0;
>  }
>
> +static int clps711x_parse_dt(struct platform_device *pdev,
> +                            struct bgpio_pdata *pdata,
> +                            unsigned long *flags)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +       struct resource *res;
> +       const char *dir_reg_name;
> +       int id = np ? of_alias_get_id(np, "gpio") : pdev->id;
> +
> +       if ((id < 0) || (id > 4))
> +               return -ENODEV;
> +

> +       /* PORTE is 3 lines only */
> +       pdata->ngpio = (id == 4) ? 3 : /* determined by register width */ 0;
> +
> +       /* PORTD is inverted logic for direction register */
> +       dir_reg_name = (id == 3) ? "dirin" : "dirout",

Just a nit: possible to use switch case?

> +
> +       pdata->base = id * 8;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!res)
> +               return -EINVAL;
> +       if (!res->name || strcmp("dat", res->name))
> +               res->name = devm_kstrdup(&pdev->dev, "dat", GFP_KERNEL);
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +       if (!res)
> +               return -EINVAL;
> +       if (!res->name || strcmp(dir_reg_name, res->name))
> +               res->name = devm_kstrdup(&pdev->dev, dir_reg_name, GFP_KERNEL);
> +
> +       return 0;
> +}
> +
> +static int ge_dt_cb(struct platform_device *pdev,
> +                   struct bgpio_pdata *pdata,
> +                   unsigned long *flags)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +
> +       pdata->label = devm_kstrdup(&pdev->dev, np->full_name, GFP_KERNEL);
> +       if (!pdata->label)
> +               return -ENOMEM;
> +
> +       return 0;
> +}
> +
> +static int moxart_dt_cb(struct platform_device *pdev,
> +                       struct bgpio_pdata *pdata,
> +                       unsigned long *flags)
> +{
> +       pdata->base = 0;
> +       pdata->label = "moxart-gpio";
> +       return 0;
> +}
> +
> +
> +static int ts4800_dt_cb(struct platform_device *pdev,
> +                       struct bgpio_pdata *pdata,
> +                       unsigned long *flags)
> +{
> +       int err;
> +
> +       err = of_property_read_u32(pdev->dev.of_node, "ngpios", &pdata->ngpio);
> +       if (err == -EINVAL) {
> +               pdata->ngpio = 16;
> +               err = 0;

return 0; ? (Up to you)

> +       }
> +       return err;
> +}
> +
> +struct compat_gpio_device_data {
> +       unsigned int expected_resource_size;
> +       unsigned int ngpio;
> +       resource_size_t register_width;
> +       unsigned long flags;
> +       int (*call_back)(struct platform_device *pdev,
> +                        struct bgpio_pdata *pdata,
> +                        unsigned long *flags);
> +       struct resource_replacement {
> +               resource_size_t start_offset;
> +               const char *name;
> +       } resources[5];

I would define magic number with a description what are those 5.

> +};

[...]

> +static int compat_parse_dt(struct platform_device *pdev,
> +                          struct bgpio_pdata *pdata,
> +                          unsigned long *flags)
> +{
> +       const struct device_node *node = pdev->dev.of_node;
> +       const struct compat_gpio_device_data *entry;
> +       const struct of_device_id *of_id;
> +       struct resource *res;
> +       int err;
> +
> +       of_id = of_match_node(compat_gpio_devices, node);
> +       if (!of_id)
> +               return -ENODEV;
> +
> +       entry = of_id->data;
> +       if (!entry || !entry->resources[0].name)
> +               return -EINVAL;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!res)
> +               return -EINVAL;
> +
> +       if (!res->name || strcmp(entry->resources[0].name, res->name)) {
> +               struct resource nres[ARRAY_SIZE(entry->resources)];
> +               int i;

unsigned int i; ?

> +
> +               if (resource_size(res) != entry->expected_resource_size)
> +                       return -EINVAL;
> +
> +               for (i = 0; i < ARRAY_SIZE(entry->resources); i++) {
> +                       if (!entry->resources[i].name)
> +                               continue;
> +
> +                       nres[i].name = devm_kstrdup(&pdev->dev,
> +                               entry->resources[i].name, GFP_KERNEL);
> +                       nres[i].start = res->start +
> +                               entry->resources[i].start_offset;
> +                       nres[i].end = nres[i].start +
> +                               entry->register_width - 1;
> +                       nres[i].flags = IORESOURCE_MEM;
> +               }
> +
> +               err = platform_device_add_resources(pdev, nres, i);
> +               if (err)
> +                       return err;
> +       }
> +
> +       pdata->base = -1;
> +       pdata->ngpio = entry->ngpio;
> +       *flags = entry->flags;
> +
> +       if (entry->call_back)
> +               err = entry->call_back(pdev, pdata, flags);
> +
> +       return err;
> +}

-- 
With Best Regards,
Andy Shevchenko


From bamvor.zhangjian at huawei.com  Fri May  6 05:02:20 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Fri, 6 May 2016 20:02:20 +0800
Subject: [PATCH 15/25] arm64: introduce is_a32_task and is_a32_thread (for
 AArch32 compat)
In-Reply-To: <1459894127-17698-16-git-send-email-ynorov@caviumnetworks.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1459894127-17698-16-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <572C87CC.4090709@huawei.com>

Hi,

On 2016/4/6 6:08, Yury Norov wrote:
> Based on patch of Andrew Pinski.
>
> This patch introduces is_a32_compat_task and is_a32_thread so it is
> easier to say this is a a32 specific thread or a generic compat thread/task.
> Corresponding functions are located in <asm/is_compat.h> to avoid mess in
> headers.
>
> Some files include both <linux/compat.h> and <asm/compat.h>,
> and this is wrong because <linux/compat.h> has <asm/compat.h> already
> included. It was fixed too.

1.  in "kernel/seccomp.c"
     There are different list for a32 and LP64. I do not know we
     should add a new one or align to one of them. Currently, we
     align ilp32 to a32 list.
```
/*
  * Secure computing mode 1 allows only read/write/exit/sigreturn.
  * To be fully secure this must be combined with rlimit
  * to limit the stack allocations too.
  */
static int mode1_syscalls[] = {
         __NR_seccomp_read, __NR_seccomp_write, __NR_seccomp_exit, __NR_seccomp_sigreturn,
         0, /* null terminated */
};

#ifdef CONFIG_COMPAT
static int mode1_syscalls_32[] = {
         __NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32,
         0, /* null terminated */
};
#endif

static void __secure_computing_strict(int this_syscall)
{
         int *syscall_whitelist = mode1_syscalls;
#ifdef CONFIG_COMPAT
         if (in_compat_syscall())
                 syscall_whitelist = mode1_syscalls_32;
#endif
```

2.  in "kernel/auditsc.c"
     __audit_seccomp will print if compat or not. But in the same file,
     it call syscall_get_arch() to get the architecture in which ILP32
     is same as LP64.
     And consequenly, do we need to split in_compat_syscall to
     in_a32_compat_syscall and in_ilp32 compat_syscall?

```
void __audit_seccomp(unsigned long syscall, long signr, int code)
{
         struct audit_buffer *ab;

         ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP);
         if (unlikely(!ab))
                 return;
         audit_log_task(ab);
         audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x",
                          signr, syscall_get_arch(), syscall,
                          in_compat_syscall(), KSTK_EIP(current), code);
         audit_log_end(ab);
}
```

Thanks

Bamvor



From bamvor.zhangjian at huawei.com  Fri May  6 05:16:48 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Fri, 6 May 2016 20:16:48 +0800
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <1459894127-17698-21-git-send-email-ynorov@caviumnetworks.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1459894127-17698-21-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <572C8B30.7000005@huawei.com>

Hi,

On 2016/4/6 6:08, Yury Norov wrote:
> From: Andrew Pinski <apinski at cavium.com>
>
> Add a separate syscall-table for ILP32, which dispatches either to native
> LP64 system call implementation or to compat-syscalls, as appropriate.
>
> Signed-off-by: Andrew Pinski <Andrew.Pinski at caviumnetworks.com>
> Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
> ---
>   arch/arm64/include/asm/unistd.h | 11 ++++++-
>   arch/arm64/kernel/Makefile      |  2 +-
>   arch/arm64/kernel/entry.S       | 12 +++++++-
>   arch/arm64/kernel/sys_ilp32.c   | 65 +++++++++++++++++++++++++++++++++++++++++
>   4 files changed, 87 insertions(+), 3 deletions(-)
>   create mode 100644 arch/arm64/kernel/sys_ilp32.c
>
> diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
> index 2971dea..5ea18ef 100644
> --- a/arch/arm64/include/asm/unistd.h
> +++ b/arch/arm64/include/asm/unistd.h
> @@ -13,9 +13,18 @@
>    * You should have received a copy of the GNU General Public License
>    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>    */
> +
> +#ifdef CONFIG_COMPAT
> +#define __ARCH_WANT_COMPAT_STAT64
> +#endif
> +
> +#ifdef CONFIG_ARM64_ILP32
> +#define __ARCH_WANT_COMPAT_SYS_PREADV64
> +#define __ARCH_WANT_COMPAT_SYS_PWRITEV64
> +#endif
> +
>   #ifdef CONFIG_AARCH32_EL0
>   #define __ARCH_WANT_COMPAT_SYS_GETDENTS64
> -#define __ARCH_WANT_COMPAT_STAT64
>   #define __ARCH_WANT_SYS_GETHOSTNAME
>   #define __ARCH_WANT_SYS_PAUSE
>   #define __ARCH_WANT_SYS_GETPGRP
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 9dfdf86..7aa65ea 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -28,7 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
>   arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
>   					   sys_compat.o entry32.o		\
>   					   ../../arm/kernel/opcodes.o binfmt_elf32.o
> -arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
> +arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o
>   arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
>   arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
>   arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> index cf4d1ae..1f7a145 100644
> --- a/arch/arm64/kernel/entry.S
> +++ b/arch/arm64/kernel/entry.S
> @@ -715,9 +715,13 @@ ENDPROC(ret_from_fork)
>    */
>   	.align	6
>   el0_svc:
> -	adrp	stbl, sys_call_table		// load syscall table pointer
>   	uxtw	scno, w8			// syscall number in w8
>   	mov	sc_nr, #__NR_syscalls
> +#ifdef CONFIG_ARM64_ILP32
> +	ldr	x16, [tsk, #TI_FLAGS]
> +	tbnz	x16, #TIF_32BIT_AARCH64, el0_ilp32_svc // We are using ILP32
> +#endif
> +	adrp	stbl, sys_call_table		// load syscall table pointer
>   el0_svc_naked:					// compat entry point
>   	stp	x0, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
>   	enable_dbg_and_irq
> @@ -737,6 +741,12 @@ ni_sys:
>   	b	ret_fast_syscall
>   ENDPROC(el0_svc)
>
> +#ifdef CONFIG_ARM64_ILP32
> +el0_ilp32_svc:
> +	adrp	stbl, sys_call_ilp32_table // load syscall table pointer
> +	b el0_svc_naked
> +#endif
> +
>   	/*
>   	 * This is the really slow path.  We're going to be doing context
>   	 * switches, and waiting for our parent to respond.
> diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
> new file mode 100644
> index 0000000..0996d8e
> --- /dev/null
> +++ b/arch/arm64/kernel/sys_ilp32.c
> @@ -0,0 +1,65 @@
> +/*
> + * AArch64- ILP32 specific system calls implementation
> + *
> + * Copyright (C) 2016 Cavium Inc.
> + * Author: Andrew Pinski <apinski at cavium.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * 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/compiler.h>
> +#include <linux/errno.h>
> +#include <linux/fs.h>
> +#include <linux/mm.h>
> +#include <linux/msg.h>
> +#include <linux/export.h>
> +#include <linux/sched.h>
> +#include <linux/slab.h>
> +#include <linux/syscalls.h>
> +#include <linux/compat.h>
> +#include <asm-generic/syscalls.h>
> +
> +/* Using non-compat syscalls where necessary */
> +#define compat_sys_fadvise64_64        sys_fadvise64_64
> +#define compat_sys_fallocate           sys_fallocate
> +#define compat_sys_ftruncate64         sys_ftruncate
> +#define compat_sys_lookup_dcookie      sys_lookup_dcookie
> +#define compat_sys_pread64             sys_pread64
> +#define compat_sys_pwrite64            sys_pwrite64
> +#define compat_sys_readahead           sys_readahead
> +#define compat_sys_shmat               sys_shmat
> +#define compat_sys_sync_file_range     sys_sync_file_range
> +#define compat_sys_truncate64          sys_truncate
> +#define sys_llseek                     sys_lseek
> +#define sys_mmap2		       sys_mmap
I am a little bit confused here. We wrap the mmap to mmap2 in glibc
without shift the 4096 and We map mmap2 to mmap in kernel which
means we shift with the real page size. It works unless the
application want to mmap the offset bigger then 2G. In ILP32 app,
if the offset is bigger than 2G(e.g. 0xfb000000), it is a negative
number and extend to 64bit nagetive number in kernel
(0xfffffff fb000000). I add the "COMPAT_SYSCALL_WRAP6(mmap, ...)" in
kernel/compat_wrapper.c. But it is not works. I am not sure if it is
already sign extended in userspace.

On the other hand, I read the code of mmap in arm and other
architecture. Usually, they will shift 4096 in userspace and shift
others in kernel if needed. Should we follow the similar ways or we
could call mmap_pgoff in glibc and do the shift according the real
page shift(getpages())?

Thanks

Bamvor



From broonie at kernel.org  Fri May  6 05:20:46 2016
From: broonie at kernel.org (Mark Brown)
Date: Fri, 6 May 2016 13:20:46 +0100
Subject: [alsa-devel] [PATCH 1/7] ASoC: mediatek: Refine mt8173 driver
 and change config option
In-Reply-To: <1462444772.2873.70.camel@mtksdaap41>
References: <1461934848-60011-1-git-send-email-garlic.tseng@mediatek.com>
 <1461934848-60011-2-git-send-email-garlic.tseng@mediatek.com>
 <20160504164306.GA6292@sirena.org.uk>
 <1462416342.25179.36.camel@mtksdaap41> <572B0511.80701@gmail.com>
 <1462444772.2873.70.camel@mtksdaap41>
Message-ID: <20160506122046.GR6292@sirena.org.uk>

On Thu, May 05, 2016 at 06:39:32PM +0800, Garlic Tseng wrote:

> As mentioned above, the difference of the ASoCs between the two chips
> are too large that we have a hard time sharing the driver code.

The things you're describing all sound like scaling differences rather
than fundamental changes.  I'd expect to see at least some shared code
here, we don't want to be just duplicating the entire driver every time
there's a new hardware revision.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160506/56dfd93d/attachment.sig>

From chunkeey at googlemail.com  Fri May  6 05:22:23 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Fri, 06 May 2016 14:22:23 +0200
Subject: [PATCH v7 2/3] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <CAHp75VcDPY+LbV5+j9DUMJ8Ws=O9=+KmAa9Nog-JuKkPGAM6Cw@mail.gmail.com>
References: <cover.1462372360.git.chunkeey@googlemail.com>
 <50f7f506364f84effd5224677b21726fd2e511a4.1462372360.git.chunkeey@googlemail.com>
 <CAHp75VcDPY+LbV5+j9DUMJ8Ws=O9=+KmAa9Nog-JuKkPGAM6Cw@mail.gmail.com>
Message-ID: <2264861.CW2OZaRj2L@debian64>

On Friday, May 06, 2016 02:44:14 PM Andy Shevchenko wrote:
> > +       /* If ngpio property is not specified, of_property_read_u32
> > +        * will return -EINVAL. In this case the number of GPIOs is
> > +        * automatically determined by the register width. Any
> > +        * other error of of_property_read_u32 is due bad data and
> > +        * needs to be dealt with.
> 
> Couple style issues:
> /*
>  * First sentence starts here. func() are going with parens.
>  */
Ack, I'm used to drivers/net. I have to remove the ngpio in a future
version, so the comment is removed as well.

> > +
> > +static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
> > +                                         unsigned long *flags)
> > +{
> > +       const int (*parse_dt)(struct platform_device *,
> > +                             struct bgpio_pdata *, unsigned long *);
> > +       const struct device_node *node = pdev->dev.of_node;
> > +       const struct of_device_id *of_id;
> > +       struct bgpio_pdata *pdata;
> > +       int err = -ENODEV;
> 
> (1)
> 
> > +
> > +       of_id = of_match_node(bgpio_of_match, node);
> > +       if (!of_id)
> > +               return NULL;
> 
> (2)
> 
> Why so?

This is because of existing arch code in /arch/arm/mach-clps711x/board-p720t.c.
You remember there's a driver with a device-tree binding "cirrus,clps711x-gpio"
for it. But the current kernel arch code still registers a platform_device and
it doesn't look like it has any device tree support. So this is necessary for
those partially converted archs to co-exist with the driver. I'll update the
-ENODEV to -EINVAL.

> > +
> > +       pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata),
> > +                            GFP_KERNEL);
> > +       if (!pdata)
> > +               return ERR_PTR(-ENOMEM);
> > +
> > +       parse_dt = (const void *)of_id->data;
> > +       if (parse_dt)
> > +               err = parse_dt(pdev, pdata, flags);
> > +       if (err)
> > +               return ERR_PTR(err);
> > +
> > +       return pdata;
> > +}
> > +#else
> > +static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
> > +                                         unsigned long *flags)
> > +{
> > +       return NULL;
> > +}
> > +#endif /* CONFIG_OF */


From khilman at baylibre.com  Fri May  6 05:35:24 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri, 06 May 2016 14:35:24 +0200
Subject: [PATCH v2 0/4] Amlogic: GXBB: Add pin controller
In-Reply-To: <1462176138-29433-1-git-send-email-carlo@caione.org> (Carlo
 Caione's message of "Mon, 2 May 2016 10:02:14 +0200")
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
Message-ID: <m2bn4jbbzn.fsf@baylibre.com>

Carlo Caione <carlo at caione.org> writes:

> From: Carlo Caione <carlo at endlessm.com>
>
> Patchset to add and enable the pin controller driver on a couple of Amlogic
> boards with a Meson GXBB SoC.

Reviewed-by: Kevin Hilman <khilman at baylibre.com>

I tested this series on GXBB odroid-c2 and p200 boards, along with some
additional pins (patches forthcoming)

Tested-by: Kevin Hilman <khilman at baylibre.com>

> Please note that:
> * This patch depends on http://www.spinics.net/lists/devicetree/msg120964.html
>   ([PATCH] ARM64: dts: amlogic: Add hiu and periphs buses).

Linus, with your ack, we could keep this series together, or if you
prefer, you can take patch 1, and Carlo can take the others through his
tree.

> * The platform driver is still missing a lot of muxing configurations. This is
>   because Amlogic still hasn't publicly released documentation for the GXBB.
>   Since Kevin has already this documentation under NDA, he will integrate and
>   complete this driver with a separate submission.

Coming soon...

Kevin


From ynorov at caviumnetworks.com  Fri May  6 05:37:31 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Fri, 6 May 2016 15:37:31 +0300
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <572C8B30.7000005@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1459894127-17698-21-git-send-email-ynorov@caviumnetworks.com>
 <572C8B30.7000005@huawei.com>
Message-ID: <20160506123731.GA11959@yury-N73SV>

On Fri, May 06, 2016 at 08:16:48PM +0800, Zhangjian (Bamvor) wrote:
> Hi,
> 
> On 2016/4/6 6:08, Yury Norov wrote:
> >From: Andrew Pinski <apinski at cavium.com>
> >
> >Add a separate syscall-table for ILP32, which dispatches either to native
> >LP64 system call implementation or to compat-syscalls, as appropriate.
> >
> >Signed-off-by: Andrew Pinski <Andrew.Pinski at caviumnetworks.com>
> >Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
> >---
> >  arch/arm64/include/asm/unistd.h | 11 ++++++-
> >  arch/arm64/kernel/Makefile      |  2 +-
> >  arch/arm64/kernel/entry.S       | 12 +++++++-
> >  arch/arm64/kernel/sys_ilp32.c   | 65 +++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 87 insertions(+), 3 deletions(-)
> >  create mode 100644 arch/arm64/kernel/sys_ilp32.c
> >
> >diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
> >index 2971dea..5ea18ef 100644
> >--- a/arch/arm64/include/asm/unistd.h
> >+++ b/arch/arm64/include/asm/unistd.h
> >@@ -13,9 +13,18 @@
> >   * You should have received a copy of the GNU General Public License
> >   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> >   */
> >+
> >+#ifdef CONFIG_COMPAT
> >+#define __ARCH_WANT_COMPAT_STAT64
> >+#endif
> >+
> >+#ifdef CONFIG_ARM64_ILP32
> >+#define __ARCH_WANT_COMPAT_SYS_PREADV64
> >+#define __ARCH_WANT_COMPAT_SYS_PWRITEV64
> >+#endif
> >+
> >  #ifdef CONFIG_AARCH32_EL0
> >  #define __ARCH_WANT_COMPAT_SYS_GETDENTS64
> >-#define __ARCH_WANT_COMPAT_STAT64
> >  #define __ARCH_WANT_SYS_GETHOSTNAME
> >  #define __ARCH_WANT_SYS_PAUSE
> >  #define __ARCH_WANT_SYS_GETPGRP
> >diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> >index 9dfdf86..7aa65ea 100644
> >--- a/arch/arm64/kernel/Makefile
> >+++ b/arch/arm64/kernel/Makefile
> >@@ -28,7 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
> >  arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
> >  					   sys_compat.o entry32.o		\
> >  					   ../../arm/kernel/opcodes.o binfmt_elf32.o
> >-arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
> >+arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o
> >  arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
> >  arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
> >  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
> >diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> >index cf4d1ae..1f7a145 100644
> >--- a/arch/arm64/kernel/entry.S
> >+++ b/arch/arm64/kernel/entry.S
> >@@ -715,9 +715,13 @@ ENDPROC(ret_from_fork)
> >   */
> >  	.align	6
> >  el0_svc:
> >-	adrp	stbl, sys_call_table		// load syscall table pointer
> >  	uxtw	scno, w8			// syscall number in w8
> >  	mov	sc_nr, #__NR_syscalls
> >+#ifdef CONFIG_ARM64_ILP32
> >+	ldr	x16, [tsk, #TI_FLAGS]
> >+	tbnz	x16, #TIF_32BIT_AARCH64, el0_ilp32_svc // We are using ILP32
> >+#endif
> >+	adrp	stbl, sys_call_table		// load syscall table pointer
> >  el0_svc_naked:					// compat entry point
> >  	stp	x0, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
> >  	enable_dbg_and_irq
> >@@ -737,6 +741,12 @@ ni_sys:
> >  	b	ret_fast_syscall
> >  ENDPROC(el0_svc)
> >
> >+#ifdef CONFIG_ARM64_ILP32
> >+el0_ilp32_svc:
> >+	adrp	stbl, sys_call_ilp32_table // load syscall table pointer
> >+	b el0_svc_naked
> >+#endif
> >+
> >  	/*
> >  	 * This is the really slow path.  We're going to be doing context
> >  	 * switches, and waiting for our parent to respond.
> >diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
> >new file mode 100644
> >index 0000000..0996d8e
> >--- /dev/null
> >+++ b/arch/arm64/kernel/sys_ilp32.c
> >@@ -0,0 +1,65 @@
> >+/*
> >+ * AArch64- ILP32 specific system calls implementation
> >+ *
> >+ * Copyright (C) 2016 Cavium Inc.
> >+ * Author: Andrew Pinski <apinski at cavium.com>
> >+ *
> >+ * This program is free software; you can redistribute it and/or modify
> >+ * it under the terms of the GNU General Public License version 2 as
> >+ * published by the Free Software Foundation.
> >+ *
> >+ * This program is distributed in the hope that it will be useful,
> >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >+ * GNU General Public License for more details.
> >+ *
> >+ * 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/compiler.h>
> >+#include <linux/errno.h>
> >+#include <linux/fs.h>
> >+#include <linux/mm.h>
> >+#include <linux/msg.h>
> >+#include <linux/export.h>
> >+#include <linux/sched.h>
> >+#include <linux/slab.h>
> >+#include <linux/syscalls.h>
> >+#include <linux/compat.h>
> >+#include <asm-generic/syscalls.h>
> >+
> >+/* Using non-compat syscalls where necessary */
> >+#define compat_sys_fadvise64_64        sys_fadvise64_64
> >+#define compat_sys_fallocate           sys_fallocate
> >+#define compat_sys_ftruncate64         sys_ftruncate
> >+#define compat_sys_lookup_dcookie      sys_lookup_dcookie
> >+#define compat_sys_pread64             sys_pread64
> >+#define compat_sys_pwrite64            sys_pwrite64
> >+#define compat_sys_readahead           sys_readahead
> >+#define compat_sys_shmat               sys_shmat
> >+#define compat_sys_sync_file_range     sys_sync_file_range
> >+#define compat_sys_truncate64          sys_truncate
> >+#define sys_llseek                     sys_lseek
> >+#define sys_mmap2		       sys_mmap
> I am a little bit confused here. We wrap the mmap to mmap2 in glibc
> without shift the 4096 and We map mmap2 to mmap in kernel which
> means we shift with the real page size. It works unless the
> application want to mmap the offset bigger then 2G. In ILP32 app,
> if the offset is bigger than 2G(e.g. 0xfb000000), it is a negative
> number and extend to 64bit nagetive number in kernel
> (0xfffffff fb000000). I add the "COMPAT_SYSCALL_WRAP6(mmap, ...)" in
> kernel/compat_wrapper.c. But it is not works. I am not sure if it is
> already sign extended in userspace.
> 
> On the other hand, I read the code of mmap in arm and other
> architecture. Usually, they will shift 4096 in userspace and shift
> others in kernel if needed. Should we follow the similar ways or we
> could call mmap_pgoff in glibc and do the shift according the real
> page shift(getpages())?
> 
> Thanks
> 
> Bamvor
> 
> 

Hi,

AFAIR, here we don't shift offset, as it's 64-bit both in user-
and kernel-space, and just pass it from user to kernel thru glibc
with no changes.

It definitely works, as there are many mappings made by linker and
libc in 2G+ area, and there are no problems with them. This is a
typical ILP32 application map:

00400000-00401000 r-xp 00000000 08:00 130400     /root/mykill
00410000-00411000 rwxp 00000000 08:00 130400     /root/mykill
00527000-00549000 rwxp 00000000 00:00 0          [heap]
c6278000-c6298000 rwxp 00000000 00:00 0 
c6298000-c63d0000 r-xp 00000000 08:00 135293     /root/sys-root/libilp32/libc-2.22.so
c63d0000-c63e0000 ---p 00138000 08:00 135293     /root/sys-root/libilp32/libc-2.22.so
c63e0000-c63e2000 r-xp 00138000 08:00 135293     /root/sys-root/libilp32/libc-2.22.so
c63e2000-c63e3000 rwxp 0013a000 08:00 135293     /root/sys-root/libilp32/libc-2.22.so
c63e3000-c63e6000 rwxp 00000000 00:00 0 
c63e6000-c63fc000 r-xp 00000000 08:00 135313     /root/sys-root/libilp32/libpthread-2.22.so
c63fc000-c640b000 ---p 00016000 08:00 135313     /root/sys-root/libilp32/libpthread-2.22.so
c640b000-c640c000 r-xp 00015000 08:00 135313     /root/sys-root/libilp32/libpthread-2.22.so
c640c000-c640d000 rwxp 00016000 08:00 135313     /root/sys-root/libilp32/libpthread-2.22.so
c640d000-c640f000 rwxp 00000000 00:00 0 
c640f000-c642c000 r-xp 00000000 08:00 135288     /root/sys-root/libilp32/ld-2.22.so
c6437000-c6439000 rwxp 00000000 00:00 0 
c6439000-c643a000 r--p 00000000 00:00 0          [vvar]
c643a000-c643b000 r-xp 00000000 00:00 0          [vdso]
c643b000-c643c000 r-xp 0001c000 08:00 135288     /root/sys-root/libilp32/ld-2.22.so
c643c000-c643d000 rwxp 0001d000 08:00 135288     /root/sys-root/libilp32/ld-2.22.so
ffe2d000-ffe4e000 rw-p 00000000 00:00 0          [stack]


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


From nm at ti.com  Fri May  6 05:48:12 2016
From: nm at ti.com (Nishanth Menon)
Date: Fri, 6 May 2016 07:48:12 -0500
Subject: [PATCH] ARM: dts: am57xx-idk-common: Fix input supply names
In-Reply-To: <1462493125-27832-1-git-send-email-nm@ti.com>
References: <1462493125-27832-1-git-send-email-nm@ti.com>
Message-ID: <572C928C.3080308@ti.com>

On 05/05/2016 07:05 PM, Nishanth Menon wrote:
[...]
>  				ldortc_reg: ldortc {
>  					/* VDDA_RTC  */
>  					vin-supply = <&vmain>;
> -					regulator-name = "ldortc";
I deleted the wrong line here!

Will repost. Sorry for the noise.

-- 
Regards,
Nishanth Menon


From robh at kernel.org  Fri May  6 06:01:54 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 6 May 2016 08:01:54 -0500
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <572C355E.7090008@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <20160505224240.GA31429@rob-hp-laptop> <572C355E.7090008@samsung.com>
Message-ID: <CAL_JsqJ_J=xFH8DfBwXv8Xd2HYYWX-FvCr4zO9sFhY=3keCdtw@mail.gmail.com>

On Fri, May 6, 2016 at 1:10 AM, Krzysztof Kozlowski
<k.kozlowski at samsung.com> wrote:
> On 05/06/2016 12:42 AM, Rob Herring wrote:
>> On Thu, May 05, 2016 at 02:34:13PM +0200, Krzysztof Kozlowski wrote:
>>> Hi,
>>>
>>> This is a different, second try to fix usb3503+lan on Odroid U3 board
>>> if it was initialized by bootloader (e.g. for TFTP boot).
>>>
>>> First version:
>>> http://www.spinics.net/lists/linux-usb/msg140042.html
>>>
>>>
>>> Problem
>>> =======
>>> When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
>>> the usb3503 and LAN smsc95xx do not show up in "lsusb". Hard-reset
>>> is required, e.g. by suspend to RAM. The actual TFTP boot does
>>> not have to happen. Just "usb start" from U-Boot is sufficient.
>>>
>>> From the schematics, the regulator is a supply only to LAN, however
>>> without toggling it off/on, the usb3503 hub won appear neither.
>>>
>>>
>>> Solution
>>> ========
>>> This is very similar to the MMC pwrseq behavior so the idea is to:
>>> 1. Move MMC pwrseq drivers to generic place,
>>
>> You can do that, but I'm going to NAK any use of pwrseq bindings outside
>> of MMC. I think it is the wrong way to do things. The DT should describe
>> the devices. If they happen to be "simple" then the core can walk the
>> tree and do any setup. For example, look for "reset-gpios" and toggle
>> that GPIO. There is no need for a special node.
>
> Okay, I got it, no node for pwrseq but parse device properties. In case
> of reset-gpios it seems quite obvious but also actively used:
> $ git grep reset-gpios arch/arm/boot/dts | wc -l
> 142
>
> Definitely pwrseq shouldn't add itself to all of these devices.
>
> My questions would be then:
> 1. An additional pwrseq compatible for device is acceptable?

Perhaps. The issue is whether common or driver specific code handles
this may change over time. In other words, it is purely a kernel
decision. It could move in either direction. It may be better to just
have a whitelist of devices (though it would need to be board specific
somehow).

> 2. How would you name the regulator? We shouldn't toggle off/on every
> regulator but probably only some specific ones.

I'd argue the generic case is just enable all the ones defined. If you
only need to deal with some of them or need a specific sequence, then
it is not generic.

Rob


From robh at kernel.org  Fri May  6 06:01:54 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 6 May 2016 08:01:54 -0500
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <572C355E.7090008@samsung.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <20160505224240.GA31429@rob-hp-laptop> <572C355E.7090008@samsung.com>
Message-ID: <CAL_JsqJ_J=xFH8DfBwXv8Xd2HYYWX-FvCr4zO9sFhY=3keCdtw@mail.gmail.com>

On Fri, May 6, 2016 at 1:10 AM, Krzysztof Kozlowski
<k.kozlowski at samsung.com> wrote:
> On 05/06/2016 12:42 AM, Rob Herring wrote:
>> On Thu, May 05, 2016 at 02:34:13PM +0200, Krzysztof Kozlowski wrote:
>>> Hi,
>>>
>>> This is a different, second try to fix usb3503+lan on Odroid U3 board
>>> if it was initialized by bootloader (e.g. for TFTP boot).
>>>
>>> First version:
>>> http://www.spinics.net/lists/linux-usb/msg140042.html
>>>
>>>
>>> Problem
>>> =======
>>> When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
>>> the usb3503 and LAN smsc95xx do not show up in "lsusb". Hard-reset
>>> is required, e.g. by suspend to RAM. The actual TFTP boot does
>>> not have to happen. Just "usb start" from U-Boot is sufficient.
>>>
>>> From the schematics, the regulator is a supply only to LAN, however
>>> without toggling it off/on, the usb3503 hub won appear neither.
>>>
>>>
>>> Solution
>>> ========
>>> This is very similar to the MMC pwrseq behavior so the idea is to:
>>> 1. Move MMC pwrseq drivers to generic place,
>>
>> You can do that, but I'm going to NAK any use of pwrseq bindings outside
>> of MMC. I think it is the wrong way to do things. The DT should describe
>> the devices. If they happen to be "simple" then the core can walk the
>> tree and do any setup. For example, look for "reset-gpios" and toggle
>> that GPIO. There is no need for a special node.
>
> Okay, I got it, no node for pwrseq but parse device properties. In case
> of reset-gpios it seems quite obvious but also actively used:
> $ git grep reset-gpios arch/arm/boot/dts | wc -l
> 142
>
> Definitely pwrseq shouldn't add itself to all of these devices.
>
> My questions would be then:
> 1. An additional pwrseq compatible for device is acceptable?

Perhaps. The issue is whether common or driver specific code handles
this may change over time. In other words, it is purely a kernel
decision. It could move in either direction. It may be better to just
have a whitelist of devices (though it would need to be board specific
somehow).

> 2. How would you name the regulator? We shouldn't toggle off/on every
> regulator but probably only some specific ones.

I'd argue the generic case is just enable all the ones defined. If you
only need to deal with some of them or need a specific sequence, then
it is not generic.

Rob


From ezequiel at vanguardiasur.com.ar  Fri May  6 06:05:06 2016
From: ezequiel at vanguardiasur.com.ar (Ezequiel Garcia)
Date: Fri, 6 May 2016 10:05:06 -0300
Subject: [PATCH v3 1/3] leds: triggers: Allow to switch the trigger to
 "panic" on a kernel panic
In-Reply-To: <572C5DEE.3070307@samsung.com>
References: <1461881020-13964-1-git-send-email-ezequiel@vanguardiasur.com.ar>
 <1461881020-13964-2-git-send-email-ezequiel@vanguardiasur.com.ar>
 <57230B26.9010300@samsung.com> <572C5DEE.3070307@samsung.com>
Message-ID: <CAAEAJfD_U1Z=wXQbK+DNdhZj5KEDkd3sK8mbBLNOvtKbZd1zYg@mail.gmail.com>

On 6 May 2016 at 06:03, Jacek Anaszewski <j.anaszewski at samsung.com> wrote:
> On 04/29/2016 09:20 AM, Jacek Anaszewski wrote:
>>
>> Hi Ezequiel,
>>
>> Thanks for the update. It's indeed reasonable to have all the
>> switching infrastructure in ledtrig-panic.c.
>>
>> I've noticed two minor issues below.
>
>
> Since the merge window is imminent, I've addressed those issues by
> myself and applied the patch set to the for-next branch
> of linux-leds.git.
>

Thanks a lot for taking care of this, Jacek!
-- 
Ezequiel Garc?a, VanguardiaSur
www.vanguardiasur.com.ar


From chunkeey at googlemail.com  Fri May  6 06:06:11 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Fri, 06 May 2016 15:06:11 +0200
Subject: [PATCH v7 3/3] gpio: move clps711x, moxart,
 ts4800 and gpio-ge into gpio-mmio
In-Reply-To: <CAHp75VeFjcPX+f3j+h+OL2jEpfGP+aqL78ymcsj4JwUfO0RvtA@mail.gmail.com>
References: <cover.1462372360.git.chunkeey@googlemail.com>
 <e936c3c38deee5cd954862c5ed11f9cffa2ba6a9.1462372360.git.chunkeey@googlemail.com>
 <CAHp75VeFjcPX+f3j+h+OL2jEpfGP+aqL78ymcsj4JwUfO0RvtA@mail.gmail.com>
Message-ID: <4995974.1A7SuhXPf2@debian64>

On Friday, May 06, 2016 02:53:24 PM Andy Shevchenko wrote:
> On Fri, May 6, 2016 at 2:10 PM, Christian Lamparter
> <chunkeey at googlemail.com> wrote:
> > This patch integrates these GPIO drivers into gpio-mmio.
> 
> Would be nice to repeat a list here.
Ok.
 
> > @@ -285,14 +274,6 @@ config GPIO_MM_LANTIQ
> >           (EBU) found on Lantiq SoCs. The gpios are output only as they are
> >           created by attaching a 16bit latch to the bus.
> >
> > -config GPIO_MOXART
> > -       bool "MOXART GPIO support"
> > -       depends on ARCH_MOXART || COMPILE_TEST
> > -       select GPIO_GENERIC
> > -       help
> > -         Select this option to enable GPIO driver for
> > -         MOXA ART SoC devices.
> > -
> 
> Doesn't it change behaviour? So, as a user of old .config I expect to
> have driver enabled. How is it achieved now?
Ok, I'll restore the configs and let them select GPIO_GENERIC_PLATFORM.

> > --- a/drivers/gpio/gpio-mmio.c
> > +++ b/drivers/gpio/gpio-mmio.c
> > @@ -610,10 +610,200 @@ static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
> >         return 0;
> >  }
> >
> > +static int clps711x_parse_dt(struct platform_device *pdev,
> > +                            struct bgpio_pdata *pdata,
> > +                            unsigned long *flags)
> > +{
> > +       struct device_node *np = pdev->dev.of_node;
> > +       struct resource *res;
> > +       const char *dir_reg_name;
> > +       int id = np ? of_alias_get_id(np, "gpio") : pdev->id;
> > +
> > +       if ((id < 0) || (id > 4))
> > +               return -ENODEV;
> > +
> 
> > +       /* PORTE is 3 lines only */
> > +       pdata->ngpio = (id == 4) ? 3 : /* determined by register width */ 0;
> > +
> > +       /* PORTD is inverted logic for direction register */
> > +       dir_reg_name = (id == 3) ? "dirin" : "dirout",
Actually, the , should be a ; it compiled because , is an operator.
But yes, fixed.

> Just a nit: possible to use switch case?
I think so. I've integrated the id < 0 || id > 4 check as well.
I don't know, I liked the old version more, it was shorter

diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index f116786..f71021c 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -619,14 +619,25 @@ static int clps711x_parse_dt(struct platform_device *pdev,
 	const char *dir_reg_name;
 	int id = np ? of_alias_get_id(np, "gpio") : pdev->id;
 
-	if ((id < 0) || (id > 4))
+	switch (id) {
+	case 0:
+	case 1:
+	case 2:
+		pdata->ngpio = 0; /* determined by register width */
+		dir_reg_name = "dirout";
+		break;
+	case 3:
+		pdata->ngpio = 0; /* determined by register width */
+		/* PORTD is inverted logic for direction register */
+		dir_reg_name = "dirin";
+		break;
+	case 4:
+		pdata->ngpio = 3; /* PORTE is 3 lines only */
+		dir_reg_name = "dirout";
+		break;
+	default:
 		return -ENODEV;
-
-	/* PORTE is 3 lines only */
-	pdata->ngpio = (id == 4) ? 3 : /* determined by register width */ 0;
-
-	/* PORTD is inverted logic for direction register */
-	dir_reg_name = (id == 3) ? "dirin" : "dirout",
+	}
 
 	pdata->base = id * 8;
---
  
> > +
> > +       pdata->base = id * 8;
> > +
> > +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +       if (!res)
> > +               return -EINVAL;
> > +       if (!res->name || strcmp("dat", res->name))
> > +               res->name = devm_kstrdup(&pdev->dev, "dat", GFP_KERNEL);
> > +
> > +       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> > +       if (!res)
> > +               return -EINVAL;
> > +       if (!res->name || strcmp(dir_reg_name, res->name))
> > +               res->name = devm_kstrdup(&pdev->dev, dir_reg_name, GFP_KERNEL);
> > +
> > +       return 0;
> > +}

[...]

> > +struct compat_gpio_device_data {
> > +       unsigned int expected_resource_size;
> > +       unsigned int ngpio;
> > +       resource_size_t register_width;
> > +       unsigned long flags;
> > +       int (*call_back)(struct platform_device *pdev,
> > +                        struct bgpio_pdata *pdata,
> > +                        unsigned long *flags);
> > +       struct resource_replacement {
> > +               resource_size_t start_offset;
> > +               const char *name;
> > +       } resources[5];
> 
> I would define magic number with a description what are those 5.

Difficult, these are 5 placeholders for the named resources.
There's particular order so a enum like
{
	DAT,
	SET,
	CLR,
	DIRIN,
	DIROUT,
	__NUM_RES 
}

might look nice but it has no purpose other than maybe confusing people
why the entries aren't used.

> > +};
> 
> [...]
> 
> > +static int compat_parse_dt(struct platform_device *pdev,
> > +                          struct bgpio_pdata *pdata,
> > +                          unsigned long *flags)
> > +{
> > +       const struct device_node *node = pdev->dev.of_node;
> > +       const struct compat_gpio_device_data *entry;
> > +       const struct of_device_id *of_id;
> > +       struct resource *res;
> > +       int err;
> > +
> > +       of_id = of_match_node(compat_gpio_devices, node);
> > +       if (!of_id)
> > +               return -ENODEV;
> > +
> > +       entry = of_id->data;
> > +       if (!entry || !entry->resources[0].name)
> > +               return -EINVAL;
> > +
> > +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +       if (!res)
> > +               return -EINVAL;
> > +
> > +       if (!res->name || strcmp(entry->resources[0].name, res->name)) {
> > +               struct resource nres[ARRAY_SIZE(entry->resources)];
> > +               int i;
> 
> unsigned int i; ?
yes. I think I change it to size_t. ARRAY_SIZE uses sizeof internally.
 
Regards,
Christian


From nicolas.ferre at atmel.com  Fri May  6 06:24:56 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Fri, 6 May 2016 15:24:56 +0200
Subject: [PATCH 0/3] ARM: at91/dt: add SAMA5 trng nodes
In-Reply-To: <1462293864-32551-1-git-send-email-mike@mikebwilliams.com>
References: <1462293864-32551-1-git-send-email-mike@mikebwilliams.com>
Message-ID: <572C9B28.40608@atmel.com>

Le 03/05/2016 18:44, Mike Williams a ?crit :
> Adds support for the true hardware random number generator.
> 
> Tested on a SAMA5D3 Xplained board.
> 
> Mike Williams (3):
>   ARM: at91/dt: sama5d2: add trng node
>   ARM: at91/dt: sama5d3: add trng node
>   ARM: at91/dt: sama5d4: add trng node
> 
>  arch/arm/boot/dts/sama5d2.dtsi | 7 +++++++
>  arch/arm/boot/dts/sama5d3.dtsi | 7 +++++++
>  arch/arm/boot/dts/sama5d4.dtsi | 7 +++++++
>  3 files changed, 21 insertions(+)

Oh, yes: they were missing indeed.

BTW, I reduce the size of the register memory map to 0x100 like this on
all patches (no need to re-send):

@@ -1170,7 +1170,7 @@

                        trng at fc01c000 {
                                compatible = "atmel,at91sam9g45-trng";
-                               reg = <0xfc01c000 0x4000>;
+                               reg = <0xfc01c000 0x100>;
                                interrupts = <47 IRQ_TYPE_LEVEL_HIGH 0>;
                                clocks = <&trng_clk>;
                        };


and take advantage of this to do the same on
arch/arm/boot/dts/at91sam9g45.dtsi as well.

Thanks and:
Acked-by: Nicolas Ferre <nicolas.ferre at atmel.com>

I stack the patches on top of at91-4.7-dt and build a pull-request soon.

Bye,
-- 
Nicolas Ferre


From andy.shevchenko at gmail.com  Fri May  6 06:25:49 2016
From: andy.shevchenko at gmail.com (Andy Shevchenko)
Date: Fri, 6 May 2016 16:25:49 +0300
Subject: [PATCH v7 3/3] gpio: move clps711x, moxart, ts4800 and gpio-ge
 into gpio-mmio
In-Reply-To: <4995974.1A7SuhXPf2@debian64>
References: <cover.1462372360.git.chunkeey@googlemail.com>
 <e936c3c38deee5cd954862c5ed11f9cffa2ba6a9.1462372360.git.chunkeey@googlemail.com>
 <CAHp75VeFjcPX+f3j+h+OL2jEpfGP+aqL78ymcsj4JwUfO0RvtA@mail.gmail.com>
 <4995974.1A7SuhXPf2@debian64>
Message-ID: <CAHp75Vf5AP88TMFqVHOD5197vj40QpKRaW0jkOQ9kwz2rzYdWw@mail.gmail.com>

On Fri, May 6, 2016 at 4:06 PM, Christian Lamparter
<chunkeey at googlemail.com> wrote:
> On Friday, May 06, 2016 02:53:24 PM Andy Shevchenko wrote:
>> On Fri, May 6, 2016 at 2:10 PM, Christian Lamparter
>> <chunkeey at googlemail.com> wrote:

>> Just a nit: possible to use switch case?
> I think so. I've integrated the id < 0 || id > 4 check as well.
> I don't know, I liked the old version more, it was shorter
>
> diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
> index f116786..f71021c 100644
> --- a/drivers/gpio/gpio-mmio.c
> +++ b/drivers/gpio/gpio-mmio.c
> @@ -619,14 +619,25 @@ static int clps711x_parse_dt(struct platform_device *pdev,
>         const char *dir_reg_name;
>         int id = np ? of_alias_get_id(np, "gpio") : pdev->id;
>
> -       if ((id < 0) || (id > 4))
> +       switch (id) {
> +       case 0:
> +       case 1:
> +       case 2:
> +               pdata->ngpio = 0; /* determined by register width */
> +               dir_reg_name = "dirout";
> +               break;
> +       case 3:
> +               pdata->ngpio = 0; /* determined by register width */
> +               /* PORTD is inverted logic for direction register */
> +               dir_reg_name = "dirin";
> +               break;
> +       case 4:
> +               pdata->ngpio = 3; /* PORTE is 3 lines only */
> +               dir_reg_name = "dirout";
> +               break;
> +       default:
>                 return -ENODEV;
> -
> -       /* PORTE is 3 lines only */
> -       pdata->ngpio = (id == 4) ? 3 : /* determined by register width */ 0;
> -
> -       /* PORTD is inverted logic for direction register */
> -       dir_reg_name = (id == 3) ? "dirin" : "dirout",
> +       }

For my personal taste the switch case more understandable / readable.
But i'm not totally objecting the old model, just a subject to discuss.

>> > +struct compat_gpio_device_data {
>> > +       unsigned int expected_resource_size;
>> > +       unsigned int ngpio;
>> > +       resource_size_t register_width;
>> > +       unsigned long flags;
>> > +       int (*call_back)(struct platform_device *pdev,
>> > +                        struct bgpio_pdata *pdata,
>> > +                        unsigned long *flags);
>> > +       struct resource_replacement {
>> > +               resource_size_t start_offset;
>> > +               const char *name;
>> > +       } resources[5];
>>
>> I would define magic number with a description what are those 5.
>
> Difficult, these are 5 placeholders for the named resources.
> There's particular order so a enum like
> {
>         DAT,
>         SET,
>         CLR,
>         DIRIN,
>         DIROUT,
>         __NUM_RES
> }
>
> might look nice but it has no purpose other than maybe confusing people
> why the entries aren't used.

OK, might be just

#define ?_SUPPORTED_RES_MAX 5
?
} resources[_SUPPORTED_RES_MAX];

-- 
With Best Regards,
Andy Shevchenko


From nicolas.ferre at atmel.com  Fri May  6 06:29:56 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Fri, 6 May 2016 15:29:56 +0200
Subject: [PATCH 1/3] ARM: at91/dt: sama5d2: add trng node
In-Reply-To: <1462293864-32551-2-git-send-email-mike@mikebwilliams.com>
References: <1462293864-32551-1-git-send-email-mike@mikebwilliams.com>
 <1462293864-32551-2-git-send-email-mike@mikebwilliams.com>
Message-ID: <572C9C54.5030706@atmel.com>

Le 03/05/2016 18:44, Mike Williams a ?crit :
> Add node to support SAMA5D2 hardware random number generator.

Oh, Mike, something is missing here: you Singed-off-by tag.

http://lxr.free-electrons.com/source/Documentation/SubmittingPatches#L409

Please read this and send me an email telling me if you add it to your
patches (this way you don't have to re-send them, if it's easier for you).

Bye,


> ---
>  arch/arm/boot/dts/sama5d2.dtsi | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
> index 78996bd..af9a5f8 100644
> --- a/arch/arm/boot/dts/sama5d2.dtsi
> +++ b/arch/arm/boot/dts/sama5d2.dtsi
> @@ -1127,6 +1127,13 @@
>  				status = "disabled";
>  			};
>  
> +			trng at fc01c000 {
> +				compatible = "atmel,at91sam9g45-trng";
> +				reg = <0xfc01c000 0x4000>;
> +				interrupts = <47 IRQ_TYPE_LEVEL_HIGH 0>;
> +				clocks = <&trng_clk>;
> +			};
> +
>  			aic: interrupt-controller at fc020000 {
>  				#interrupt-cells = <3>;
>  				compatible = "atmel,sama5d2-aic";
> 


-- 
Nicolas Ferre


From nicolas.ferre at atmel.com  Fri May  6 06:37:47 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Fri, 6 May 2016 15:37:47 +0200
Subject: [PATCH] ARM: dts: at91: at91sam9g45 family: reduce the trng register
 map size
Message-ID: <1462541867-7800-1-git-send-email-nicolas.ferre@atmel.com>

No need to map 0x4000 bytes for the TRNG device: reduce it to 0x100.

Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
---
 arch/arm/boot/dts/at91sam9g45.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index af8b708ac312..8837b7e4292c 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -978,7 +978,7 @@
 
 			trng at fffcc000 {
 				compatible = "atmel,at91sam9g45-trng";
-				reg = <0xfffcc000 0x4000>;
+				reg = <0xfffcc000 0x100>;
 				interrupts = <6 IRQ_TYPE_LEVEL_HIGH 0>;
 				clocks = <&trng_clk>;
 			};
-- 
2.1.3



From nm at ti.com  Fri May  6 06:37:57 2016
From: nm at ti.com (Nishanth Menon)
Date: Fri, 6 May 2016 08:37:57 -0500
Subject: [PATCH V2] ARM: dts: am57xx-idk-common: Fix input supply names
Message-ID: <1462541877-20032-1-git-send-email-nm@ti.com>

Palmas Regulator is an exception and does not follow the standard
"vin-supply" common definitions for all regulators, as a result of this,
the input supplies are not reported to regulator framework, with the
obvious result of not being appropriately mapped. Fix the same.

Signed-off-by: Nishanth Menon <nm at ti.com>
---
Changes since V1:
	- fix up fat fingered deletion of regulator name of ldortc
V1: https://patchwork.kernel.org/patch/9028201/
Based on: next-20160506

bootlog: http://pastebin.ubuntu.com/16258763/

 arch/arm/boot/dts/am57xx-idk-common.dtsi | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/arch/arm/boot/dts/am57xx-idk-common.dtsi b/arch/arm/boot/dts/am57xx-idk-common.dtsi
index b01a5948cdd0..0e63b9dff6e7 100644
--- a/arch/arm/boot/dts/am57xx-idk-common.dtsi
+++ b/arch/arm/boot/dts/am57xx-idk-common.dtsi
@@ -60,10 +60,26 @@
 
 		tps659038_pmic {
 			compatible = "ti,tps659038-pmic";
+
+			smps12-in-supply = <&vmain>;
+			smps3-in-supply = <&vmain>;
+			smps45-in-supply = <&vmain>;
+			smps6-in-supply = <&vmain>;
+			smps7-in-supply = <&vmain>;
+			smps8-in-supply = <&vmain>;
+			smps9-in-supply = <&vmain>;
+			ldo1-in-supply = <&vmain>;
+			ldo2-in-supply = <&vmain>;
+			ldo3-in-supply = <&vmain>;
+			ldo4-in-supply = <&vmain>;
+			ldo9-in-supply = <&vmain>;
+			ldoln-in-supply = <&vmain>;
+			ldousb-in-supply = <&vmain>;
+			ldortc-in-supply = <&vmain>;
+
 			regulators {
 				smps12_reg: smps12 {
 					/* VDD_MPU */
-					vin-supply = <&vmain>;
 					regulator-name = "smps12";
 					regulator-min-microvolt = <850000>;
 					regulator-max-microvolt = <1250000>;
@@ -73,7 +89,6 @@
 
 				smps3_reg: smps3 {
 					/* VDD_DDR EMIF1 EMIF2 */
-					vin-supply = <&vmain>;
 					regulator-name = "smps3";
 					regulator-min-microvolt = <1350000>;
 					regulator-max-microvolt = <1350000>;
@@ -84,7 +99,6 @@
 				smps45_reg: smps45 {
 					/* VDD_DSPEVE on AM572 */
 					/* VDD_IVA + VDD_DSP on AM571 */
-					vin-supply = <&vmain>;
 					regulator-name = "smps45";
 					regulator-min-microvolt = <850000>;
 					regulator-max-microvolt = <1250000>;
@@ -94,7 +108,6 @@
 
 				smps6_reg: smps6 {
 					/* VDD_GPU */
-					vin-supply = <&vmain>;
 					regulator-name = "smps6";
 					regulator-min-microvolt = <850000>;
 					regulator-max-microvolt = <1250000>;
@@ -104,7 +117,6 @@
 
 				smps7_reg: smps7 {
 					/* VDD_CORE */
-					vin-supply = <&vmain>;
 					regulator-name = "smps7";
 					regulator-min-microvolt = <850000>;
 					regulator-max-microvolt = <1150000>;
@@ -115,13 +127,11 @@
 				smps8_reg: smps8 {
 					/* 5728 - VDD_IVAHD */
 					/* 5718 - N.C. test point */
-					vin-supply = <&vmain>;
 					regulator-name = "smps8";
 				};
 
 				smps9_reg: smps9 {
 					/* VDD_3_3D */
-					vin-supply = <&vmain>;
 					regulator-name = "smps9";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
@@ -132,7 +142,6 @@
 				ldo1_reg: ldo1 {
 					/* VDDSHV8 - VSDMMC  */
 					/* NOTE: on rev 1.3a, data supply */
-					vin-supply = <&vmain>;
 					regulator-name = "ldo1";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <3300000>;
@@ -142,7 +151,6 @@
 
 				ldo2_reg: ldo2 {
 					/* VDDSH18V */
-					vin-supply = <&vmain>;
 					regulator-name = "ldo2";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
@@ -152,7 +160,6 @@
 
 				ldo3_reg: ldo3 {
 					/* R1.3a 572x V1_8PHY_LDO3: USB, SATA */
-					vin-supply = <&vmain>;
 					regulator-name = "ldo3";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
@@ -162,7 +169,6 @@
 
 				ldo4_reg: ldo4 {
 					/* R1.3a 572x V1_8PHY_LDO4: PCIE, HDMI*/
-					vin-supply = <&vmain>;
 					regulator-name = "ldo4";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
@@ -174,7 +180,6 @@
 
 				ldo9_reg: ldo9 {
 					/* VDD_RTC  */
-					vin-supply = <&vmain>;
 					regulator-name = "ldo9";
 					regulator-min-microvolt = <840000>;
 					regulator-max-microvolt = <1160000>;
@@ -184,7 +189,6 @@
 
 				ldoln_reg: ldoln {
 					/* VDDA_1V8_PLL */
-					vin-supply = <&vmain>;
 					regulator-name = "ldoln";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
@@ -194,7 +198,6 @@
 
 				ldousb_reg: ldousb {
 					/* VDDA_3V_USB: VDDA_USBHS33 */
-					vin-supply = <&vmain>;
 					regulator-name = "ldousb";
 					regulator-min-microvolt = <3300000>;
 					regulator-max-microvolt = <3300000>;
@@ -204,7 +207,6 @@
 
 				ldortc_reg: ldortc {
 					/* VDDA_RTC  */
-					vin-supply = <&vmain>;
 					regulator-name = "ldortc";
 					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <1800000>;
-- 
2.8.0



From shankerd at codeaurora.org  Fri May  6 06:43:36 2016
From: shankerd at codeaurora.org (Shanker Donthineni)
Date: Fri,  6 May 2016 08:43:36 -0500
Subject: [PATCH] irqchip/gicv3-its: Implement two-level(indirect) device table
 support
Message-ID: <1462542216-20952-1-git-send-email-shankerd@codeaurora.org>

Since device IDs are extremely sparse, the single, a.k.a flat table is
not sufficient for the following two reasons.

1) According to ARM-GIC spec, ITS hw can access maximum of 256(pages)*
   64K(pageszie) bytes. In the best case, it supports upto DEVid=21
   sparse with minimum device table entry size 8bytes.

2) The maximum memory size that is possible without memblock depends on
   MAX_ORDER. 4MB on 4K page size kernel with default MAX_ORDER, so it
   supports DEVid range 19bits.

The two-level device table feature brings us two advantages, the first
is a very high possibility of supporting upto 32bit sparse, and the
second one is the best utilization of memory allocation.

The feature is enabled automatically during driver probe if the flat
table is not adequate and the hardware is capable of two-level table
walk.

Signed-off-by: Shanker Donthineni <shankerd at codeaurora.org>
---

This patch is based on Marc Zyngier's branch https://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git/log/?h=irq/irqchip-4.7

 drivers/irqchip/irq-gic-v3-its.c   | 109 ++++++++++++++++++++++++++++++++-----
 include/linux/irqchip/arm-gic-v3.h |   2 +
 2 files changed, 97 insertions(+), 14 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 6bd881b..caeb105 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -55,13 +55,14 @@ struct its_collection {
 };
 
 /*
- * The ITS_BASER structure - contains memory information and cached
- * value of BASER register configuration.
+ * The ITS_BASER structure - contains memory information, cached value
+ * of BASER register configuration and ITS page size in bytes.
  */
 struct its_baser {
 	void		*base;
 	u64		val;
 	u32		order;
+	u32		psz;
 };
 
 /*
@@ -853,6 +854,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 		u64 type = GITS_BASER_TYPE(val);
 		u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
 		int order = get_order(psz);
+		bool tried_indirect = false;
+		u64 indirect = 0;
 		int alloc_pages;
 		u64 tmp;
 		void *base;
@@ -877,11 +880,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 			 */
 			order = max(get_order((1UL << ids) * entry_size),
 				    order);
-			if (order >= MAX_ORDER) {
+			if (order >= MAX_ORDER)
 				order = MAX_ORDER - 1;
-				pr_warn("%s: Device Table too large, reduce its page order to %u\n",
-					node_name, order);
-			}
 		}
 
 retry_alloc_baser:
@@ -889,8 +889,6 @@ retry_alloc_baser:
 		if (alloc_pages > GITS_BASER_PAGES_MAX) {
 			alloc_pages = GITS_BASER_PAGES_MAX;
 			order = get_order(GITS_BASER_PAGES_MAX * psz);
-			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
-				node_name, order, alloc_pages);
 		}
 
 		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
@@ -924,6 +922,7 @@ retry_baser:
 
 		val |= alloc_pages - 1;
 		its->tables[i].val = val;
+		its->tables[i].psz = psz;
 
 		writeq_relaxed(val, its->base + GITS_BASER + i * 8);
 		tmp = readq_relaxed(its->base + GITS_BASER + i * 8);
@@ -963,6 +962,49 @@ retry_baser:
 			}
 		}
 
+		/*
+		 * Attempt enabling Indirection table walk since we were unable
+		 * to allocate enough memory for flat device table to cover
+		 * whole DevID sparse that hw reporting, and ITS hardware has
+		 * capablity of supporting two-level table.
+		 */
+		if ((type == GITS_BASER_TYPE_DEVICE) &&
+		    (!tried_indirect) &&
+		    (PAGE_ORDER_TO_SIZE(order) < (entry_size << ids))) {
+
+			val |= GITS_BASER_INDIRECT;
+			writeq_relaxed(val, its->base + GITS_BASER + i * 8);
+			tmp = readq_relaxed(its->base + GITS_BASER + i * 8);
+			tried_indirect = true;
+
+			/* Does ITS HW supports Indirect table walk? */
+			if (!(tmp & GITS_BASER_INDIRECT)) {
+				pr_warn("%s: Device Table too large, reduce order to %u\n",
+					node_name, order);
+				goto retry_baser;
+			}
+
+			/*
+			 * According to GIC spec, the size of the Level2 table
+			 * is equal to ITS page size which is 'psz'. For
+			 * computing Level1 table1 size, subtract DevID bits
+			 * that covers Level2 table from 'ids' which is reported
+			 * by ITS hardware times Level1 table entry size 8bytes.
+			 *
+			 *   L2-DevIDs = ilog2(psz / entry_size)
+			 *      L1-DevIDs = ids (reported by HW) - L2-DevIDs
+			 * Table1 size = L1-DevIDs * 8Bytes
+			 */
+			ids -= ilog2(psz / entry_size);
+			order = get_order(GITS_LEVEL1_ENTRY_SIZE << ids);
+
+			/* Limit Level1 table size to MAX_ORDER-1 */
+			order = min(order, MAX_ORDER - 1);
+			indirect = GITS_BASER_INDIRECT;
+			its->tables[type].base = NULL;
+			goto retry_alloc_baser;
+		}
+
 		if (val != tmp) {
 			pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n",
 			       node_name, i,
@@ -971,10 +1013,12 @@ retry_baser:
 			goto out_free;
 		}
 
-		pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n",
-			(int)(PAGE_ORDER_TO_SIZE(order) / entry_size),
+		pr_info("ITS: allocated %d %s @%lx (%s, psz %dK, shr %d)\n",
+			(int)(PAGE_ORDER_TO_SIZE(order) /
+			(indirect ? GITS_LEVEL1_ENTRY_SIZE : entry_size)),
 			its_base_type_string[type],
 			(unsigned long)virt_to_phys(base),
+			indirect ? "indirect" : "flat",
 			psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
 	}
 
@@ -1149,6 +1193,46 @@ static struct its_device *its_find_device(struct its_node *its, u32 dev_id)
 	return its_dev;
 }
 
+static bool its_alloc_device_table(struct its_baser *baser, u32 dev_id)
+{
+	u32 entry_size = GITS_BASER_ENTRY_SIZE(baser->val);
+	u64 *table = baser->base;
+	struct page *page;
+	u32 psz = SZ_64K;
+	u32 idx;
+
+	/* Don't allow 'dev_id' that exceeds single, flat table limit */
+	if (!(baser->val & GITS_BASER_INDIRECT)) {
+		if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) / entry_size))
+			return false;
+		return true;
+	}
+
+	/* Compute Level1 table index & check if that exceeds table range */
+	idx = dev_id >> ilog2(baser->psz / entry_size);
+	if (idx >= (PAGE_ORDER_TO_SIZE(baser->order) / GITS_LEVEL1_ENTRY_SIZE))
+		return false;
+
+	/* Allocate memory for Level2 table */
+	if (!table[idx]) {
+		page = alloc_pages_exact(psz, GFP_KERNEL | __GFP_ZERO);
+		if (!page)
+			return false;
+
+		table[idx] = page_to_phys(page) | GITS_BASER_VALID;
+
+		/* Flush memory to PoC if hardware dosn't support coherency */
+		if (!(baser->val & GITS_BASER_SHAREABILITY_MASK)) {
+			__flush_dcache_area(table + idx, GITS_LEVEL1_ENTRY_SIZE);
+			__flush_dcache_area(page_address(page), psz);
+		}
+		/* Ensure updated table contents are visible to ITS hardware */
+		dsb(sy);
+	}
+
+	return true;
+}
+
 static struct its_baser *its_get_baser(struct its_node *its, u32 type)
 {
 	int i;
@@ -1176,11 +1260,8 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 	int sz;
 
 	baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
-
-	/* Don't allow 'dev_id' that exceeds single, flat table limit */
 	if (baser) {
-		if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) /
-			      GITS_BASER_ENTRY_SIZE(baser->val)))
+		if (!its_alloc_device_table(baser, dev_id))
 			return NULL;
 	} else if (ilog2(dev_id) >= its->device_ids)
 		return NULL;
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 9e6fdd3..df404ea 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -187,6 +187,7 @@
 #define GITS_TYPER_PTA			(1UL << 19)
 
 #define GITS_CBASER_VALID		(1UL << 63)
+#define GITS_BASER_INDIRECT		(1UL << 62)
 #define GITS_CBASER_nCnB		(0UL << 59)
 #define GITS_CBASER_nC			(1UL << 59)
 #define GITS_CBASER_RaWt		(2UL << 59)
@@ -238,6 +239,7 @@
 #define GITS_BASER_TYPE_RESERVED6	6
 #define GITS_BASER_TYPE_RESERVED7	7
 
+#define GITS_LEVEL1_ENTRY_SIZE		(8UL)
 /*
  * ITS commands
  */
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project



From javier at osg.samsung.com  Fri May  6 06:44:29 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Fri, 6 May 2016 09:44:29 -0400
Subject: [PATCH] ARM: dts: exynos: Add MFC memory banks for Peach boards
In-Reply-To: <1461871311-18344-1-git-send-email-javier@osg.samsung.com>
References: <1461871311-18344-1-git-send-email-javier@osg.samsung.com>
Message-ID: <cef99c21-3886-c055-05bf-cd04e3b588b3@osg.samsung.com>

Hello Krzysztof,

On 04/28/2016 03:21 PM, Javier Martinez Canillas wrote:
> The MFC nodes with the memory regions reserved for memory allocations
> are missing in the Exynos5420 Peach Pit and Exynos5800 Peach Pi DTS.
> 
> This causes the s5p-mfc driver probe to fail with the following error:
> 
> [    4.140647] s5p_mfc_alloc_memdevs:1072: Failed to declare coherent memory for MFC device
> [    4.216163] s5p-mfc: probe of 11000000.codec failed with error -12
> 
> Add the missing nodes so the driver probes and the {en,de}coder video
> nodes are registered correctly:
> 
> [    4.096277] s5p-mfc 11000000.codec: decoder registered as /dev/video4
> [    4.102282] s5p-mfc 11000000.codec: encoder registered as /dev/video5
> 
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>
> ---
> 
>  arch/arm/boot/dts/exynos5420-peach-pit.dts | 5 +++++
>  arch/arm/boot/dts/exynos5800-peach-pi.dts  | 5 +++++
>  2 files changed, 10 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
> index b644858231b6..f9d2e4f1a0e0 100644
> --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
> +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
> @@ -694,6 +694,11 @@
>  	status = "okay";
>  };
>  
> +&mfc {
> +	samsung,mfc-r = <0x43000000 0x800000>;
> +	samsung,mfc-l = <0x51000000 0x800000>;
> +};
> +
>  &mmc_0 {
>  	status = "okay";
>  	num-slots = <1>;
> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
> index 6ba9aec15485..62ceb89e073f 100644
> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
> @@ -669,6 +669,11 @@
>  	status = "okay";
>  };
>  
> +&mfc {
> +	samsung,mfc-r = <0x43000000 0x800000>;
> +	samsung,mfc-l = <0x51000000 0x800000>;
> +};
> +
>  &mmc_0 {
>  	status = "okay";
>  	num-slots = <1>;
> 

Any comments about this patch?

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From k.kozlowski at samsung.com  Fri May  6 06:58:11 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 15:58:11 +0200
Subject: [PATCH] ARM: dts: exynos: Add MFC memory banks for Peach boards
In-Reply-To: <cef99c21-3886-c055-05bf-cd04e3b588b3@osg.samsung.com>
References: <1461871311-18344-1-git-send-email-javier@osg.samsung.com>
 <cef99c21-3886-c055-05bf-cd04e3b588b3@osg.samsung.com>
Message-ID: <572CA2F3.4050407@samsung.com>

On 05/06/2016 03:44 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 04/28/2016 03:21 PM, Javier Martinez Canillas wrote:
>> The MFC nodes with the memory regions reserved for memory allocations
>> are missing in the Exynos5420 Peach Pit and Exynos5800 Peach Pi DTS.
>>
>> This causes the s5p-mfc driver probe to fail with the following error:
>>
>> [    4.140647] s5p_mfc_alloc_memdevs:1072: Failed to declare coherent memory for MFC device
>> [    4.216163] s5p-mfc: probe of 11000000.codec failed with error -12
>>
>> Add the missing nodes so the driver probes and the {en,de}coder video
>> nodes are registered correctly:
>>
>> [    4.096277] s5p-mfc 11000000.codec: decoder registered as /dev/video4
>> [    4.102282] s5p-mfc 11000000.codec: encoder registered as /dev/video5
>>
>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>
>> ---
>>
>>  arch/arm/boot/dts/exynos5420-peach-pit.dts | 5 +++++
>>  arch/arm/boot/dts/exynos5800-peach-pi.dts  | 5 +++++
>>  2 files changed, 10 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>> index b644858231b6..f9d2e4f1a0e0 100644
>> --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
>> +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>> @@ -694,6 +694,11 @@
>>  	status = "okay";
>>  };
>>  
>> +&mfc {
>> +	samsung,mfc-r = <0x43000000 0x800000>;
>> +	samsung,mfc-l = <0x51000000 0x800000>;
>> +};
>> +
>>  &mmc_0 {
>>  	status = "okay";
>>  	num-slots = <1>;
>> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>> index 6ba9aec15485..62ceb89e073f 100644
>> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
>> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>> @@ -669,6 +669,11 @@
>>  	status = "okay";
>>  };
>>  
>> +&mfc {
>> +	samsung,mfc-r = <0x43000000 0x800000>;
>> +	samsung,mfc-l = <0x51000000 0x800000>;
>> +};
>> +
>>  &mmc_0 {
>>  	status = "okay";
>>  	num-slots = <1>;
>>
> 
> Any comments about this patch?

What is up with the rush now (a week for ping)? As I understand, this
was broken for very long time on these boards (since adding DT support
in 2012?).

Best regards,
Krzysztof



From khilman at baylibre.com  Fri May  6 06:59:26 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri,  6 May 2016 06:59:26 -0700
Subject: [PATCH] MAINTAINERS: ARM/Amlogic: add co-maintainer, misc. updates
Message-ID: <1462543166-8065-1-git-send-email-khilman@baylibre.com>

Add myself as co-maintainer, update mailing list entry and add a couple
more directories.

Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 MAINTAINERS | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 42e65d128d01..31e5043653dd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -948,12 +948,15 @@ F:	drivers/clk/sunxi/
 
 ARM/Amlogic Meson SoC support
 M:	Carlo Caione <carlo at caione.org>
+M:	Kevin Hilman <khilman at baylibre.com>
 L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
-L:	linux-meson at googlegroups.com
+L:	linux-amlogic at lists.infradead.org
 W:	http://linux-meson.com/
 S:	Maintained
 F:	arch/arm/mach-meson/
 F:	arch/arm/boot/dts/meson*
+F:	arch/arm64/boot/dts/amlogic/
+F: 	drivers/pinctrl/meson/
 N:	meson
 
 ARM/Annapurna Labs ALPINE ARCHITECTURE
-- 
2.7.4



From ynorov at caviumnetworks.com  Fri May  6 07:00:22 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Fri, 6 May 2016 17:00:22 +0300
Subject: [PATCH 24/25] arm64:ilp32: add vdso-ilp32 and use for signal
 return
In-Reply-To: <CA+=Sn1mNdd+Xy5QL5ScRyZOCWwKkG6o1Pb50sFPuiKX=0Z2B1w@mail.gmail.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1554541.oDP7Ro5zB2@wuerfel>
 <20160503090045.GB10733@e104818-lin.cambridge.arm.com>
 <3846428.6xx69KGEja@wuerfel> <57288660.9030607@huawei.com>
 <57289C75.50904@huawei.com> <20160504214949.GA28217@yury-N73SV>
 <CA+=Sn1ngpaJWHpGDmU+kXBkz56SO+XDW2qzMMLAbbBWnaB0eqw@mail.gmail.com>
 <572AAED2.7050604@huawei.com>
 <CA+=Sn1mNdd+Xy5QL5ScRyZOCWwKkG6o1Pb50sFPuiKX=0Z2B1w@mail.gmail.com>
Message-ID: <20160506140022.GA18587@yury-N73SV>

Hello colleagues,

After all comments, VDSO fix looks like this for me.

Note I renamed Andrew's ZERO macro to DELOUSE, as
there already is __SC_DELOUSE which does the same,
but in C, not asm.

Like Bamvor, I'm not sure how we'd apply this patch - 
standalone or meld to VDSO. I think, VDSO patch is too
big and bad-structurized, and if I find how to refactor
it, I'll incorporate this fix.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/kernel/asm-offsets.c               |  7 +++++++
 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S |  2 +-
 arch/arm64/kernel/vdso/gettimeofday.S         | 20 +++++++++++++++++---
 3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index e229525..fcfd087 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -101,6 +101,13 @@ int main(void)
   DEFINE(TSPEC_TV_SEC,		offsetof(struct timespec, tv_sec));
   DEFINE(TSPEC_TV_NSEC,		offsetof(struct timespec, tv_nsec));
   BLANK();
+#ifdef CONFIG_ARM64_ILP32
+  DEFINE(COMPAT_TVAL_TV_SEC,	offsetof(struct compat_timeval, tv_sec));
+  DEFINE(COMPAT_TVAL_TV_USEC,	offsetof(struct compat_timeval, tv_usec));
+  DEFINE(COMPAT_TSPEC_TV_SEC,	offsetof(struct compat_timespec, tv_sec));
+  DEFINE(COMPAT_TSPEC_TV_NSEC,	offsetof(struct compat_timespec, tv_nsec));
+  BLANK();
+#endif
   DEFINE(TZ_MINWEST,		offsetof(struct timezone, tz_minuteswest));
   DEFINE(TZ_DSTTIME,		offsetof(struct timezone, tz_dsttime));
   BLANK();
diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
index ddc63fd..d182a8d 100644
--- a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
+++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
@@ -79,7 +79,7 @@ PHDRS
  */
 VERSION
 {
-	LINUX_2.6 {
+	LINUX_2.6.39 {
 	global:
 		__kernel_rt_sigreturn;
 		__kernel_gettimeofday;
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index efa79e8..a2d8a70 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -25,6 +25,16 @@
 #define NSEC_PER_SEC_LO16	0xca00
 #define NSEC_PER_SEC_HI16	0x3b9a
 
+#ifdef __LP64__
+#define PTR_REG(n)	x##n
+#define OFFSET(n)	n
+#define DELOUSE(n)
+#else
+#define PTR_REG(n)	w##n
+#define OFFSET(n)	COMPAT_##n
+#define DELOUSE(n)	mov     w##n, w##n
+#endif
+
 vdso_data	.req	x6
 use_syscall	.req	w7
 seqcnt		.req	w8
@@ -51,6 +61,8 @@ seqcnt		.req	w8
 /* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */
 ENTRY(__kernel_gettimeofday)
 	.cfi_startproc
+	DELOUSE(0)
+	DELOUSE(1)
 	mov	x2, x30
 	.cfi_register x30, x2
 
@@ -68,7 +80,7 @@ ENTRY(__kernel_gettimeofday)
 	mov	x13, #1000
 	lsl	x13, x13, x12
 	udiv	x11, x11, x13
-	stp	x10, x11, [x0, #TVAL_TV_SEC]
+	stp	PTR_REG(10), PTR_REG(11), [x0, #OFFSET(TVAL_TV_SEC)]
 2:
 	/* If tz is NULL, return 0. */
 	cbz	x1, 3f
@@ -88,6 +100,7 @@ ENDPROC(__kernel_gettimeofday)
 /* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */
 ENTRY(__kernel_clock_gettime)
 	.cfi_startproc
+	DELOUSE(1)
 	cmp	w0, #CLOCK_REALTIME
 	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
 	b.ne	2f
@@ -159,7 +172,7 @@ ENTRY(__kernel_clock_gettime)
 
 6:	/* Store to the user timespec. */
 	lsr	x11, x11, x12
-	stp	x10, x11, [x1, #TSPEC_TV_SEC]
+	stp	PTR_REG(10), PTR_REG(11), [x1, #OFFSET(TSPEC_TV_SEC)]
 	mov	x0, xzr
 	ret
 7:
@@ -174,6 +187,7 @@ ENDPROC(__kernel_clock_gettime)
 /* int __kernel_clock_getres(clockid_t clock_id, struct timespec *res); */
 ENTRY(__kernel_clock_getres)
 	.cfi_startproc
+	DELOUSE(1)
 	cmp	w0, #CLOCK_REALTIME
 	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
 	b.ne	1f
@@ -187,7 +201,7 @@ ENTRY(__kernel_clock_getres)
 	ldr	x2, 6f
 2:
 	cbz	w1, 3f
-	stp	xzr, x2, [x1]
+	stp	PTR_REG(zr), PTR_REG(2), [x1]
 
 3:	/* res == NULL. */
 	mov	w0, wzr
-- 
2.5.0



From javier at osg.samsung.com  Fri May  6 07:12:08 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Fri, 6 May 2016 10:12:08 -0400
Subject: [PATCH] ARM: dts: exynos: Add MFC memory banks for Peach boards
In-Reply-To: <572CA2F3.4050407@samsung.com>
References: <1461871311-18344-1-git-send-email-javier@osg.samsung.com>
 <cef99c21-3886-c055-05bf-cd04e3b588b3@osg.samsung.com>
 <572CA2F3.4050407@samsung.com>
Message-ID: <23883a5f-bfed-9474-51a7-14271b6c391f@osg.samsung.com>

Hello Krzysztof,

On 05/06/2016 09:58 AM, Krzysztof Kozlowski wrote:
> On 05/06/2016 03:44 PM, Javier Martinez Canillas wrote:
>> Hello Krzysztof,
>>
>> On 04/28/2016 03:21 PM, Javier Martinez Canillas wrote:
>>> The MFC nodes with the memory regions reserved for memory allocations
>>> are missing in the Exynos5420 Peach Pit and Exynos5800 Peach Pi DTS.
>>>
>>> This causes the s5p-mfc driver probe to fail with the following error:
>>>
>>> [    4.140647] s5p_mfc_alloc_memdevs:1072: Failed to declare coherent memory for MFC device
>>> [    4.216163] s5p-mfc: probe of 11000000.codec failed with error -12
>>>
>>> Add the missing nodes so the driver probes and the {en,de}coder video
>>> nodes are registered correctly:
>>>
>>> [    4.096277] s5p-mfc 11000000.codec: decoder registered as /dev/video4
>>> [    4.102282] s5p-mfc 11000000.codec: encoder registered as /dev/video5
>>>
>>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>>
>>> ---
>>>
>>>  arch/arm/boot/dts/exynos5420-peach-pit.dts | 5 +++++
>>>  arch/arm/boot/dts/exynos5800-peach-pi.dts  | 5 +++++
>>>  2 files changed, 10 insertions(+)
>>>
>>> diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>> index b644858231b6..f9d2e4f1a0e0 100644
>>> --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>> +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>> @@ -694,6 +694,11 @@
>>>  	status = "okay";
>>>  };
>>>  
>>> +&mfc {
>>> +	samsung,mfc-r = <0x43000000 0x800000>;
>>> +	samsung,mfc-l = <0x51000000 0x800000>;
>>> +};
>>> +
>>>  &mmc_0 {
>>>  	status = "okay";
>>>  	num-slots = <1>;
>>> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>> index 6ba9aec15485..62ceb89e073f 100644
>>> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>> @@ -669,6 +669,11 @@
>>>  	status = "okay";
>>>  };
>>>  
>>> +&mfc {
>>> +	samsung,mfc-r = <0x43000000 0x800000>;
>>> +	samsung,mfc-l = <0x51000000 0x800000>;
>>> +};
>>> +
>>>  &mmc_0 {
>>>  	status = "okay";
>>>  	num-slots = <1>;
>>>
>>
>> Any comments about this patch?
> 
> What is up with the rush now (a week for ping)? As I understand, this

Sorry about that... I should had waited for more time for the ping indeed.
I just thought the patch was trivial and you usually answer within days.

> was broken for very long time on these boards (since adding DT support
> in 2012?).
> 

Yes, that's correct. And in fact even the s5p-mfc driver is currently
not working in mainline. But I posted some fixes and will post more
patches from other people today to get it working. So I thought that
would be nice to have this in since one of my test machines is a Peach.

> Best regards,
> Krzysztof
>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From carlo at caione.org  Fri May  6 07:13:38 2016
From: carlo at caione.org (Carlo Caione)
Date: Fri, 6 May 2016 16:13:38 +0200
Subject: [PATCH] MAINTAINERS: ARM/Amlogic: add co-maintainer, misc. updates
In-Reply-To: <1462543166-8065-1-git-send-email-khilman@baylibre.com>
References: <1462543166-8065-1-git-send-email-khilman@baylibre.com>
Message-ID: <CAOQ7t2ZT5t+C1qRjvxP5Yj6wuGgZc3-Ti7CT1eXbpH2ZLZRxAg@mail.gmail.com>

On Fri, May 6, 2016 at 3:59 PM, Kevin Hilman <khilman at baylibre.com> wrote:
> Add myself as co-maintainer, update mailing list entry and add a couple
> more directories.
>
> Signed-off-by: Kevin Hilman <khilman at baylibre.com>

Acked-by: Carlo Caione <carlo at caione.org>

Thank you!

-- 
Carlo Caione


From k.kozlowski at samsung.com  Fri May  6 07:13:59 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 06 May 2016 16:13:59 +0200
Subject: [PATCH] ARM: dts: exynos: Add MFC memory banks for Peach boards
In-Reply-To: <23883a5f-bfed-9474-51a7-14271b6c391f@osg.samsung.com>
References: <1461871311-18344-1-git-send-email-javier@osg.samsung.com>
 <cef99c21-3886-c055-05bf-cd04e3b588b3@osg.samsung.com>
 <572CA2F3.4050407@samsung.com>
 <23883a5f-bfed-9474-51a7-14271b6c391f@osg.samsung.com>
Message-ID: <572CA6A7.1040102@samsung.com>

On 05/06/2016 04:12 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/06/2016 09:58 AM, Krzysztof Kozlowski wrote:
>> On 05/06/2016 03:44 PM, Javier Martinez Canillas wrote:
>>> Hello Krzysztof,
>>>
>>> On 04/28/2016 03:21 PM, Javier Martinez Canillas wrote:
>>>> The MFC nodes with the memory regions reserved for memory allocations
>>>> are missing in the Exynos5420 Peach Pit and Exynos5800 Peach Pi DTS.
>>>>
>>>> This causes the s5p-mfc driver probe to fail with the following error:
>>>>
>>>> [    4.140647] s5p_mfc_alloc_memdevs:1072: Failed to declare coherent memory for MFC device
>>>> [    4.216163] s5p-mfc: probe of 11000000.codec failed with error -12
>>>>
>>>> Add the missing nodes so the driver probes and the {en,de}coder video
>>>> nodes are registered correctly:
>>>>
>>>> [    4.096277] s5p-mfc 11000000.codec: decoder registered as /dev/video4
>>>> [    4.102282] s5p-mfc 11000000.codec: encoder registered as /dev/video5
>>>>
>>>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>>>
>>>> ---
>>>>
>>>>  arch/arm/boot/dts/exynos5420-peach-pit.dts | 5 +++++
>>>>  arch/arm/boot/dts/exynos5800-peach-pi.dts  | 5 +++++
>>>>  2 files changed, 10 insertions(+)
>>>>
>>>> diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>>> index b644858231b6..f9d2e4f1a0e0 100644
>>>> --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>>> +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
>>>> @@ -694,6 +694,11 @@
>>>>  	status = "okay";
>>>>  };
>>>>  
>>>> +&mfc {
>>>> +	samsung,mfc-r = <0x43000000 0x800000>;
>>>> +	samsung,mfc-l = <0x51000000 0x800000>;
>>>> +};
>>>> +
>>>>  &mmc_0 {
>>>>  	status = "okay";
>>>>  	num-slots = <1>;
>>>> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>>> index 6ba9aec15485..62ceb89e073f 100644
>>>> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>>> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>>>> @@ -669,6 +669,11 @@
>>>>  	status = "okay";
>>>>  };
>>>>  
>>>> +&mfc {
>>>> +	samsung,mfc-r = <0x43000000 0x800000>;
>>>> +	samsung,mfc-l = <0x51000000 0x800000>;
>>>> +};
>>>> +
>>>>  &mmc_0 {
>>>>  	status = "okay";
>>>>  	num-slots = <1>;
>>>>
>>>
>>> Any comments about this patch?
>>
>> What is up with the rush now (a week for ping)? As I understand, this
> 
> Sorry about that... I should had waited for more time for the ping indeed.
> I just thought the patch was trivial and you usually answer within days.
> 
>> was broken for very long time on these boards (since adding DT support
>> in 2012?).
>>
> 
> Yes, that's correct. And in fact even the s5p-mfc driver is currently
> not working in mainline. But I posted some fixes and will post more
> patches from other people today to get it working. So I thought that
> would be nice to have this in since one of my test machines is a Peach.

Okay, no problem. I have few more not-so-critical fixes. Queued for
earliest possible release.

Best regards,
Krzysztof



From khilman at baylibre.com  Fri May  6 07:21:19 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri,  6 May 2016 07:21:19 -0700
Subject: [PATCH 0/7] pinctrl: meson: Add a bunch more pins
Message-ID: <1462544486-9516-1-git-send-email-khilman@baylibre.com>

Add support for several more devices, both in the EE domain and in the
AO domain.  Also, add the pins to the corresponding DTS files.

Tested on odroid-c2 and Amlogic P200 boards, and verified with working
ethernet.

Depends on the initial GXBB pinctrl support from Carlo[1].  Also
available in my git tree[2] with all the dependencies included.

Kevin

[1] [PATCH v2 0/4] Amlogic: GXBB: Add pin controller
    http://lists.infradead.org/pipermail/linux-arm-kernel/2016-May/426718.html
[2] https://git.kernel.org/cgit/linux/kernel/git/khilman/linux.git/log/?h=amlogic/wip/pinctrl

Kevin Hilman (7):
  pinctrl: amlogic: gxbb: add UART_AO_B, I2C
  pinctrl: amlogic: gxbb: add EMMC and SD pins
  pinctrl: amlogic: gxbb: add more UART pins
  pinctrl amlogic: gxbb: add ethernet pins
  ARM64: dts: amlogic: add pins for EMMC, SD
  ARM64: dts: amlogic: gxbb: pinctrl: add/update UART
  ARM64: dts: amlogic: gxbb: add ethernet

 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts |   7 +
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |   7 +
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  97 +++++++++++-
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c         | 167 ++++++++++++++++++++-
 4 files changed, 273 insertions(+), 5 deletions(-)

-- 
2.7.4



From khilman at baylibre.com  Fri May  6 07:21:20 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri,  6 May 2016 07:21:20 -0700
Subject: [PATCH 1/7] pinctrl: amlogic: gxbb: add UART_AO_B, I2C
In-Reply-To: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
Message-ID: <1462544486-9516-2-git-send-email-khilman@baylibre.com>

Add pins for some more AO domain devices: UART_AO_B and I2C master &
slave.

Also, rename UART_AO to UART_AO_A since UART_AO_B has also been added.

Cc: Carlo Caione <carlo at endlessm.com>
Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi |  2 +-
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c  | 39 ++++++++++++++++++++++++++---
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 6dd27685e31e..35397fcc5380 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -177,7 +177,7 @@
 				uart_ao_a_pins: uart_ao_a {
 					mux {
 						groups = "uart_tx_ao_a", "uart_rx_ao_a";
-						function = "uart_ao";
+						function = "uart_ao_a";
 					};
 				};
 			};
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index eeabafbbf598..50551677b0ee 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -168,6 +168,16 @@ static const unsigned int uart_tx_ao_a_pins[]	= { PIN(GPIOAO_0, 0) };
 static const unsigned int uart_rx_ao_a_pins[]	= { PIN(GPIOAO_1, 0) };
 static const unsigned int uart_cts_ao_a_pins[]	= { PIN(GPIOAO_2, 0) };
 static const unsigned int uart_rts_ao_a_pins[]	= { PIN(GPIOAO_3, 0) };
+static const unsigned int uart_tx_ao_b_pins[]	= { PIN(GPIOAO_0, 0) };
+static const unsigned int uart_rx_ao_b_pins[]	= { PIN(GPIOAO_1, 0),
+						    PIN(GPIOAO_5, 0) };
+static const unsigned int uart_cts_ao_b_pins[]	= { PIN(GPIOAO_2, 0) };
+static const unsigned int uart_rts_ao_b_pins[]	= { PIN(GPIOAO_3, 0) };
+
+static const unsigned int i2c_sck_ao_pins[] = {PIN(GPIOAO_4, 0) };
+static const unsigned int i2c_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
+static const unsigned int i2c_slave_sck_ao_pins[] = {PIN(GPIOAO_4, 0) };
+static const unsigned int i2c_slave_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
 
 static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GPIO_GROUP(GPIOZ_0, EE_OFF),
@@ -316,10 +326,18 @@ static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
 	GPIO_GROUP(GPIOAO_13, 0),
 
 	/* bank AO */
+	GROUP(uart_tx_ao_b,	0,	26),
+	GROUP(uart_rx_ao_b,	0,	25),
 	GROUP(uart_tx_ao_a,	0,	12),
 	GROUP(uart_rx_ao_a,	0,	11),
 	GROUP(uart_cts_ao_a,	0,	10),
 	GROUP(uart_rts_ao_a,	0,	9),
+	GROUP(uart_cts_ao_b,	0,	8),
+	GROUP(uart_rts_ao_b,	0,	7),
+	GROUP(i2c_sck_ao,	0,	6),
+	GROUP(i2c_sda_ao,	0,	5),
+	GROUP(i2c_slave_sck_ao, 0,	2),
+	GROUP(i2c_slave_sda_ao, 0,	1),
 };
 
 static const char * const gpio_periphs_groups[] = {
@@ -365,8 +383,20 @@ static const char * const gpio_aobus_groups[] = {
 	"GPIOAO_10", "GPIOAO_11", "GPIOAO_12", "GPIOAO_13",
 };
 
-static const char * const uart_ao_groups[] = {
-	"uart_tx_ao_a", "uart_rx_ao_a", "uart_cts_ao_a", "uart_rts_ao_a"
+static const char * const uart_ao_a_groups[] = {
+	"uart_tx_ao_a", "uart_rx_ao_a", "uart_cts_ao_a", "uart_rts_ao_a",
+};
+
+static const char * const uart_ao_b_groups[] = {
+	"uart_tx_ao_b", "uart_rx_ao_b", "uart_cts_ao_b", "uart_rts_ao_b",
+};
+
+static const char * const i2c_ao_groups[] = {
+	"i2c_sdk_ao", "i2c_sda_ao",
+};
+
+static const char * const i2c_slave_ao_groups[] = {
+	"i2c_slave_sdk_ao", "i2c_slave_sda_ao",
 };
 
 static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
@@ -375,7 +405,10 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 
 static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
 	FUNCTION(gpio_aobus),
-	FUNCTION(uart_ao),
+	FUNCTION(uart_ao_a),
+	FUNCTION(uart_ao_b),
+	FUNCTION(i2c_ao),
+	FUNCTION(i2c_slave_ao),
 };
 
 static struct meson_bank meson_gxbb_periphs_banks[] = {
-- 
2.7.4



From khilman at baylibre.com  Fri May  6 07:21:24 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri,  6 May 2016 07:21:24 -0700
Subject: [PATCH 5/7] ARM64: dts: amlogic: add pins for EMMC, SD
In-Reply-To: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
Message-ID: <1462544486-9516-6-git-send-email-khilman@baylibre.com>

Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 35397fcc5380..7b22b9d3b9d9 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -213,6 +213,27 @@
 					gpio-controller;
 					#gpio-cells = <2>;
 				};
+
+				emmc_pins: emmc {
+					mux {
+						groups = "emmc_nand_d07",
+						       "emmc_cmd",
+						       "emmc_clk";
+						function = "emmc";
+					};
+				};
+
+				sdcard_pins: sdcard {
+					mux {
+						groups = "sdcard_d0",
+						       "sdcard_d1",
+						       "sdcard_d2",
+						       "sdcard_d3",
+						       "sdcard_cmd",
+						       "sdcard_clk";
+						function = "sdcard";
+					};
+				};
 			};
 		};
 
-- 
2.7.4



From khilman at baylibre.com  Fri May  6 07:21:21 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri,  6 May 2016 07:21:21 -0700
Subject: [PATCH 2/7] pinctrl: amlogic: gxbb: add EMMC and SD pins
In-Reply-To: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
Message-ID: <1462544486-9516-3-git-send-email-khilman@baylibre.com>

Add EE domain pins for eMMC and SD card.

Cc: Carlo Caione <carlo at endlessm.com>
Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 41 ++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index 50551677b0ee..5dc98ee35265 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -147,6 +147,22 @@ static const struct pinctrl_pin_desc meson_gxbb_periphs_pins[] = {
 	MESON_PIN(GPIO_TEST_N, EE_OFF),
 };
 
+static const unsigned int emmc_nand_d07_pins[] = {
+	PIN(BOOT_0, EE_OFF), PIN(BOOT_1, EE_OFF), PIN(BOOT_2, EE_OFF),
+	PIN(BOOT_3, EE_OFF), PIN(BOOT_4, EE_OFF), PIN(BOOT_5, EE_OFF),
+	PIN(BOOT_6, EE_OFF), PIN(BOOT_7, EE_OFF),
+};
+static const unsigned int emmc_clk_pins[] = { PIN(BOOT_8, EE_OFF) };
+static const unsigned int emmc_cmd_pins[] = { PIN(BOOT_10, EE_OFF) };
+static const unsigned int emmc_ds_pins[] = { PIN(BOOT_15, EE_OFF) };
+
+static const unsigned int sdcard_d0_pins[] = { PIN(CARD_1, EE_OFF) };
+static const unsigned int sdcard_d1_pins[] = { PIN(CARD_0, EE_OFF) };
+static const unsigned int sdcard_d2_pins[] = { PIN(CARD_5, EE_OFF) };
+static const unsigned int sdcard_d3_pins[] = { PIN(CARD_4, EE_OFF) };
+static const unsigned int sdcard_cmd_pins[] = { PIN(CARD_3, EE_OFF) };
+static const unsigned int sdcard_clk_pins[] = { PIN(CARD_2, EE_OFF) };
+
 static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
 	MESON_PIN(GPIOAO_0, 0),
 	MESON_PIN(GPIOAO_1, 0),
@@ -307,6 +323,20 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GPIO_GROUP(GPIOCLK_3, EE_OFF),
 
 	GPIO_GROUP(GPIO_TEST_N, EE_OFF),
+
+	/* Bank BOOT */
+	GROUP(emmc_nand_d07,	4,	30),
+	GROUP(emmc_clk,		4,	18),
+	GROUP(emmc_cmd,		4,	19),
+	GROUP(emmc_ds,		4,	31),
+
+	/* Bank CARD */
+	GROUP(sdcard_d1,	2,	14),
+	GROUP(sdcard_d0,	2,	15),
+	GROUP(sdcard_d3,	2,	12),
+	GROUP(sdcard_d2,	2,	13),
+	GROUP(sdcard_cmd,	2,	10),
+	GROUP(sdcard_clk,	2,	11),
 };
 
 static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
@@ -377,6 +407,15 @@ static const char * const gpio_periphs_groups[] = {
 	"GPIO_TEST_N",
 };
 
+static const char * const emmc_groups[] = {
+	"emmc_nand_d07", "emmc_clk", "emmc_cmd", "emmc_ds",
+};
+
+static const char * const sdcard_groups[] = {
+	"sdcard_d0", "sdcard_d1", "sdcard_d2", "sdcard_d3",
+	"sdcard_cmd", "sdcard_clk",
+};
+
 static const char * const gpio_aobus_groups[] = {
 	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
 	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
@@ -401,6 +440,8 @@ static const char * const i2c_slave_ao_groups[] = {
 
 static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(gpio_periphs),
+	FUNCTION(emmc),
+	FUNCTION(sdcard),
 };
 
 static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
-- 
2.7.4



From khilman at baylibre.com  Fri May  6 07:21:22 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri,  6 May 2016 07:21:22 -0700
Subject: [PATCH 3/7] pinctrl: amlogic: gxbb: add more UART pins
In-Reply-To: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
Message-ID: <1462544486-9516-4-git-send-email-khilman@baylibre.com>

Add EE domain pins for UART A, B & C.

Cc: Carlo Caione <carlo at endlessm.com>
Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 48 ++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index 5dc98ee35265..67b5af70e9e9 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -163,6 +163,21 @@ static const unsigned int sdcard_d3_pins[] = { PIN(CARD_4, EE_OFF) };
 static const unsigned int sdcard_cmd_pins[] = { PIN(CARD_3, EE_OFF) };
 static const unsigned int sdcard_clk_pins[] = { PIN(CARD_2, EE_OFF) };
 
+static const unsigned int uart_tx_a_pins[]	= { PIN(GPIOX_12, EE_OFF) };
+static const unsigned int uart_rx_a_pins[]	= { PIN(GPIOX_13, EE_OFF) };
+static const unsigned int uart_cts_a_pins[]	= { PIN(GPIOX_14, EE_OFF) };
+static const unsigned int uart_rts_a_pins[]	= { PIN(GPIOX_15, EE_OFF) };
+
+static const unsigned int uart_tx_b_pins[]	= { PIN(GPIODV_24, EE_OFF) };
+static const unsigned int uart_rx_b_pins[]	= { PIN(GPIODV_25, EE_OFF) };
+static const unsigned int uart_cts_b_pins[]	= { PIN(GPIODV_26, EE_OFF) };
+static const unsigned int uart_rts_b_pins[]	= { PIN(GPIODV_27, EE_OFF) };
+
+static const unsigned int uart_tx_c_pins[]	= { PIN(GPIOY_13, EE_OFF) };
+static const unsigned int uart_rx_c_pins[]	= { PIN(GPIOY_14, EE_OFF) };
+static const unsigned int uart_cts_c_pins[]	= { PIN(GPIOX_11, EE_OFF) };
+static const unsigned int uart_rts_c_pins[]	= { PIN(GPIOX_12, EE_OFF) };
+
 static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
 	MESON_PIN(GPIOAO_0, 0),
 	MESON_PIN(GPIOAO_1, 0),
@@ -324,6 +339,24 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 
 	GPIO_GROUP(GPIO_TEST_N, EE_OFF),
 
+	/* Bank X */
+	GROUP(uart_tx_a,	4,	13),
+	GROUP(uart_rx_a,	4,	12),
+	GROUP(uart_cts_a,	4,	11),
+	GROUP(uart_rts_a,	4,	10),
+
+	/* Bank Y */
+	GROUP(uart_cts_c,	1,	19),
+	GROUP(uart_rts_c,	1,	18),
+	GROUP(uart_tx_c,	1,	17),
+	GROUP(uart_rx_c,	1,	16),
+
+	/* Bank DV */
+	GROUP(uart_tx_b,	2,	29),
+	GROUP(uart_rx_b,	2,	28),
+	GROUP(uart_cts_b,	2,	27),
+	GROUP(uart_rts_b,	2,	26),
+
 	/* Bank BOOT */
 	GROUP(emmc_nand_d07,	4,	30),
 	GROUP(emmc_clk,		4,	18),
@@ -416,6 +449,18 @@ static const char * const sdcard_groups[] = {
 	"sdcard_cmd", "sdcard_clk",
 };
 
+static const char * const uart_a_groups[] = {
+	"uart_tx_a", "uart_rx_a", "uart_cts_a", "uart_rts_a",
+};
+
+static const char * const uart_b_groups[] = {
+	"uart_tx_b", "uart_rx_b", "uart_cts_b", "uart_rts_b",
+};
+
+static const char * const uart_c_groups[] = {
+	"uart_tx_c", "uart_rx_c", "uart_cts_c", "uart_rts_c",
+};
+
 static const char * const gpio_aobus_groups[] = {
 	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
 	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
@@ -442,6 +487,9 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(gpio_periphs),
 	FUNCTION(emmc),
 	FUNCTION(sdcard),
+	FUNCTION(uart_a),
+	FUNCTION(uart_b),
+	FUNCTION(uart_c),
 };
 
 static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
-- 
2.7.4



From khilman at baylibre.com  Fri May  6 07:21:23 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri,  6 May 2016 07:21:23 -0700
Subject: [PATCH 4/7] pinctrl amlogic: gxbb: add ethernet pins
In-Reply-To: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
Message-ID: <1462544486-9516-5-git-send-email-khilman@baylibre.com>

Add EE domain pins for ethernet interface.

Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 39 ++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index 67b5af70e9e9..360535a30625 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -178,6 +178,21 @@ static const unsigned int uart_rx_c_pins[]	= { PIN(GPIOY_14, EE_OFF) };
 static const unsigned int uart_cts_c_pins[]	= { PIN(GPIOX_11, EE_OFF) };
 static const unsigned int uart_rts_c_pins[]	= { PIN(GPIOX_12, EE_OFF) };
 
+static const unsigned int eth_mdio_pins[]	= { PIN(GPIOZ_0, EE_OFF) };
+static const unsigned int eth_mdc_pins[]	= { PIN(GPIOZ_1, EE_OFF) };
+static const unsigned int eth_clk_rx_clk_pins[]	= { PIN(GPIOZ_2, EE_OFF) };
+static const unsigned int eth_rx_dv_pins[]	= { PIN(GPIOZ_3, EE_OFF) };
+static const unsigned int eth_rxd0_pins[]	= { PIN(GPIOZ_4, EE_OFF) };
+static const unsigned int eth_rxd1_pins[]	= { PIN(GPIOZ_5, EE_OFF) };
+static const unsigned int eth_rxd2_pins[]	= { PIN(GPIOZ_6, EE_OFF) };
+static const unsigned int eth_rxd3_pins[]	= { PIN(GPIOZ_7, EE_OFF) };
+static const unsigned int eth_rgmii_tx_clk_pins[] = { PIN(GPIOZ_8, EE_OFF) };
+static const unsigned int eth_tx_en_pins[]	= { PIN(GPIOZ_9, EE_OFF) };
+static const unsigned int eth_txd0_pins[]	= { PIN(GPIOZ_10, EE_OFF) };
+static const unsigned int eth_txd1_pins[]	= { PIN(GPIOZ_11, EE_OFF) };
+static const unsigned int eth_txd2_pins[]	= { PIN(GPIOZ_12, EE_OFF) };
+static const unsigned int eth_txd3_pins[]	= { PIN(GPIOZ_13, EE_OFF) };
+
 static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
 	MESON_PIN(GPIOAO_0, 0),
 	MESON_PIN(GPIOAO_1, 0),
@@ -351,6 +366,22 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GROUP(uart_tx_c,	1,	17),
 	GROUP(uart_rx_c,	1,	16),
 
+	/* Bank Z */
+	GROUP(eth_mdio,		6,	1),
+	GROUP(eth_mdc,		6,	0),
+	GROUP(eth_clk_rx_clk,	6,	13),
+	GROUP(eth_rx_dv,	6,	12),
+	GROUP(eth_rxd0,		6,	11),
+	GROUP(eth_rxd1,		6,	10),
+	GROUP(eth_rxd2,		6,	9),
+	GROUP(eth_rxd3,		6,	8),
+	GROUP(eth_rgmii_tx_clk,	6,	7),
+	GROUP(eth_tx_en,	6,	6),
+	GROUP(eth_txd0,		6,	5),
+	GROUP(eth_txd1,		6,	4),
+	GROUP(eth_txd2,		6,	3),
+	GROUP(eth_txd3,		6,	2),
+
 	/* Bank DV */
 	GROUP(uart_tx_b,	2,	29),
 	GROUP(uart_rx_b,	2,	28),
@@ -461,6 +492,13 @@ static const char * const uart_c_groups[] = {
 	"uart_tx_c", "uart_rx_c", "uart_cts_c", "uart_rts_c",
 };
 
+static const char * const eth_groups[] = {
+	"eth_mdio", "eth_mdc", "eth_clk_rx_clk", "eth_rx_dv",
+	"eth_rxd0", "eth_rxd1", "eth_rxd2", "eth_rxd3",
+	"eth_rgmii_tx_clk", "eth_tx_en",
+	"eth_txd0", "eth_txd1", "eth_txd2", "eth_txd3",
+};
+
 static const char * const gpio_aobus_groups[] = {
 	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
 	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
@@ -490,6 +528,7 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(uart_a),
 	FUNCTION(uart_b),
 	FUNCTION(uart_c),
+	FUNCTION(eth),
 };
 
 static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
-- 
2.7.4



From khilman at baylibre.com  Fri May  6 07:21:25 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri,  6 May 2016 07:21:25 -0700
Subject: [PATCH 6/7] ARM64: dts: amlogic: gxbb: pinctrl: add/update UART
In-Reply-To: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
Message-ID: <1462544486-9516-7-git-send-email-khilman@baylibre.com>

Add DT nodes for additional UARTs (UART B & C in EE domain) and add pins
for all EE domain UARTs.

Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts |  1 +
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        | 42 +++++++++++++++++++++-
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index 41e1e669bc70..45778896bd3d 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -80,3 +80,4 @@
 	pinctrl-0 = <&uart_ao_a_pins>;
 	pinctrl-names = "default";
 };
+
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 7b22b9d3b9d9..86c41b3798db 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -132,11 +132,27 @@
 
 			uart_A: serial at 84c0 {
 				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x084c0 0x0 0x14>;
+				reg = <0x0 0x84c0 0x0 0x14>;
 				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
 				clocks = <&xtal>;
 				status = "disabled";
 			};
+
+			uart_B: serial at 84dc {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x84dc 0x0 0x14>;
+				interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			uart_C: serial at 8700 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x8700 0x0 0x14>;
+				interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
 		};
 
 		gic: interrupt-controller at c4301000 {
@@ -234,6 +250,30 @@
 						function = "sdcard";
 					};
 				};
+
+				uart_a_pins: uart_a {
+					mux {
+						groups = "uart_tx_a",
+						       "uart_rx_a";
+						function = "uart_a";
+					};
+				};
+
+				uart_b_pins: uart_b {
+					mux {
+						groups = "uart_tx_b",
+						       "uart_rx_b";
+						function = "uart_b";
+					};
+				};
+
+				uart_c_pins: uart_c {
+					mux {
+						groups = "uart_tx_c",
+						       "uart_rx_c";
+						function = "uart_c";
+					};
+				};
 			};
 		};
 
-- 
2.7.4



From khilman at baylibre.com  Fri May  6 07:21:26 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Fri,  6 May 2016 07:21:26 -0700
Subject: [PATCH 7/7] ARM64: dts: amlogic: gxbb: add ethernet
In-Reply-To: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
Message-ID: <1462544486-9516-8-git-send-email-khilman@baylibre.com>

Add node for ethernet interface and pinctrl pins.
Enable on odroid-C2 and P20x boards.

Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts |  6 ++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |  7 +++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        | 32 ++++++++++++++++++++++
 3 files changed, 45 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index 45778896bd3d..90a84c514d3d 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -81,3 +81,9 @@
 	pinctrl-names = "default";
 };
 
+&ethmac {
+	status = "okay";
+	pinctrl-0 = <&eth_pins>;
+	pinctrl-names = "default";
+};
+
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
index 22e629841a99..f4f30f674b4c 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
@@ -65,3 +65,10 @@
 	pinctrl-0 = <&uart_ao_a_pins>;
 	pinctrl-names = "default";
 };
+
+&ethmac {
+	status = "okay";
+	pinctrl-0 = <&eth_pins>;
+	pinctrl-names = "default";
+};
+
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 86c41b3798db..76b3b6d0526b 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -274,6 +274,26 @@
 						function = "uart_c";
 					};
 				};
+
+				eth_pins: eth_c {
+					mux {
+						groups = "eth_mdio",
+						       "eth_mdc",
+						       "eth_clk_rx_clk",
+						       "eth_rx_dv",
+						       "eth_rxd0",
+						       "eth_rxd1",
+						       "eth_rxd2",
+						       "eth_rxd3",
+						       "eth_rgmii_tx_clk",
+						       "eth_tx_en",
+						       "eth_txd0",
+						       "eth_txd1",
+						       "eth_txd2",
+						       "eth_txd3";
+						function = "eth";
+					};
+				};
 			};
 		};
 
@@ -292,5 +312,17 @@
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
 		};
+
+		ethmac: ethernet at c9410000 {
+			compatible = "amlogic,meson6-dwmac", "snps,dwmac";
+			reg = <0x0 0xc9410000 0x0 0x10000
+			       0x0 0xc8834540 0x0 0x4>;
+			interrupts = <0 8 1>;
+			interrupt-names = "macirq";
+			clocks = <&xtal>;
+			clock-names = "stmmaceth";
+			phy-mode = "rgmii";
+			status = "disabled";
+		};
 	};
 };
-- 
2.7.4



From marc.zyngier at arm.com  Fri May  6 07:22:47 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Fri, 6 May 2016 15:22:47 +0100
Subject: [PATCH] irqchip/gicv3-its: Implement two-level(indirect) device
 table support
In-Reply-To: <1462542216-20952-1-git-send-email-shankerd@codeaurora.org>
References: <1462542216-20952-1-git-send-email-shankerd@codeaurora.org>
Message-ID: <20160506152247.67d0881a@arm.com>

Hi Shanker,

Thanks for putting this together. Comments below:

On Fri, 6 May 2016 08:43:36 -0500
Shanker Donthineni <shankerd at codeaurora.org> wrote:

> Since device IDs are extremely sparse, the single, a.k.a flat table is
> not sufficient for the following two reasons.
> 
> 1) According to ARM-GIC spec, ITS hw can access maximum of 256(pages)*
>    64K(pageszie) bytes. In the best case, it supports upto DEVid=21
>    sparse with minimum device table entry size 8bytes.
> 
> 2) The maximum memory size that is possible without memblock depends on
>    MAX_ORDER. 4MB on 4K page size kernel with default MAX_ORDER, so it
>    supports DEVid range 19bits.
> 
> The two-level device table feature brings us two advantages, the first
> is a very high possibility of supporting upto 32bit sparse, and the
> second one is the best utilization of memory allocation.
> 
> The feature is enabled automatically during driver probe if the flat
> table is not adequate and the hardware is capable of two-level table
> walk.
> 
> Signed-off-by: Shanker Donthineni <shankerd at codeaurora.org>
> ---
> 
> This patch is based on Marc Zyngier's branch https://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git/log/?h=irq/irqchip-4.7
> 
>  drivers/irqchip/irq-gic-v3-its.c   | 109 ++++++++++++++++++++++++++++++++-----
>  include/linux/irqchip/arm-gic-v3.h |   2 +
>  2 files changed, 97 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 6bd881b..caeb105 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -55,13 +55,14 @@ struct its_collection {
>  };
>  
>  /*
> - * The ITS_BASER structure - contains memory information and cached
> - * value of BASER register configuration.
> + * The ITS_BASER structure - contains memory information, cached value
> + * of BASER register configuration and ITS page size in bytes.
>   */
>  struct its_baser {
>  	void		*base;
>  	u64		val;
>  	u32		order;
> +	u32		psz;
>  };
>  
>  /*
> @@ -853,6 +854,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
>  		u64 type = GITS_BASER_TYPE(val);
>  		u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
>  		int order = get_order(psz);
> +		bool tried_indirect = false;
> +		u64 indirect = 0;
>  		int alloc_pages;
>  		u64 tmp;
>  		void *base;
> @@ -877,11 +880,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
>  			 */
>  			order = max(get_order((1UL << ids) * entry_size),
>  				    order);
> -			if (order >= MAX_ORDER) {
> +			if (order >= MAX_ORDER)
>  				order = MAX_ORDER - 1;
> -				pr_warn("%s: Device Table too large, reduce its page order to %u\n",
> -					node_name, order);
> -			}
>  		}
>  
>  retry_alloc_baser:
> @@ -889,8 +889,6 @@ retry_alloc_baser:
>  		if (alloc_pages > GITS_BASER_PAGES_MAX) {
>  			alloc_pages = GITS_BASER_PAGES_MAX;
>  			order = get_order(GITS_BASER_PAGES_MAX * psz);
> -			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
> -				node_name, order, alloc_pages);
>  		}
>  
>  		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
> @@ -924,6 +922,7 @@ retry_baser:
>  
>  		val |= alloc_pages - 1;
>  		its->tables[i].val = val;
> +		its->tables[i].psz = psz;
>  
>  		writeq_relaxed(val, its->base + GITS_BASER + i * 8);
>  		tmp = readq_relaxed(its->base + GITS_BASER + i * 8);
> @@ -963,6 +962,49 @@ retry_baser:
>  			}
>  		}
>  
> +		/*
> +		 * Attempt enabling Indirection table walk since we were unable
> +		 * to allocate enough memory for flat device table to cover
> +		 * whole DevID sparse that hw reporting, and ITS hardware has
> +		 * capablity of supporting two-level table.
> +		 */
> +		if ((type == GITS_BASER_TYPE_DEVICE) &&
> +		    (!tried_indirect) &&
> +		    (PAGE_ORDER_TO_SIZE(order) < (entry_size << ids))) {

Why not try to use indirect tables if they are available, irrespective
of the size of the required allocation? From a memory usage point of
view, it is likely to always be a gain, unless your id space is so
small that it fits in a single page. And with PCIe, you know for sure
that the ID space is extremely sparse, hence indirect tables are an
immediate win.

Do you see any value in using the indirect table as a last resort?

> +
> +			val |= GITS_BASER_INDIRECT;
> +			writeq_relaxed(val, its->base + GITS_BASER + i * 8);
> +			tmp = readq_relaxed(its->base + GITS_BASER + i * 8);
> +			tried_indirect = true;
> +
> +			/* Does ITS HW supports Indirect table walk? */
> +			if (!(tmp & GITS_BASER_INDIRECT)) {
> +				pr_warn("%s: Device Table too large, reduce order to %u\n",
> +					node_name, order);
> +				goto retry_baser;
> +			}
> +
> +			/*
> +			 * According to GIC spec, the size of the Level2 table
> +			 * is equal to ITS page size which is 'psz'. For
> +			 * computing Level1 table1 size, subtract DevID bits
> +			 * that covers Level2 table from 'ids' which is reported
> +			 * by ITS hardware times Level1 table entry size 8bytes.
> +			 *
> +			 *   L2-DevIDs = ilog2(psz / entry_size)
> +			 *      L1-DevIDs = ids (reported by HW) - L2-DevIDs
> +			 * Table1 size = L1-DevIDs * 8Bytes
> +			 */
> +			ids -= ilog2(psz / entry_size);
> +			order = get_order(GITS_LEVEL1_ENTRY_SIZE << ids);
> +
> +			/* Limit Level1 table size to MAX_ORDER-1 */
> +			order = min(order, MAX_ORDER - 1);
> +			indirect = GITS_BASER_INDIRECT;
> +			its->tables[type].base = NULL;
> +			goto retry_alloc_baser;
> +		}
> +

Please take this opportunity to split this function into something
manageable. It is really getting out of control. Something to directly
deal with the device table seems in order.

>  		if (val != tmp) {
>  			pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n",
>  			       node_name, i,
> @@ -971,10 +1013,12 @@ retry_baser:
>  			goto out_free;
>  		}
>  
> -		pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n",
> -			(int)(PAGE_ORDER_TO_SIZE(order) / entry_size),
> +		pr_info("ITS: allocated %d %s @%lx (%s, psz %dK, shr %d)\n",
> +			(int)(PAGE_ORDER_TO_SIZE(order) /
> +			(indirect ? GITS_LEVEL1_ENTRY_SIZE : entry_size)),
>  			its_base_type_string[type],
>  			(unsigned long)virt_to_phys(base),
> +			indirect ? "indirect" : "flat",
>  			psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
>  	}
>  
> @@ -1149,6 +1193,46 @@ static struct its_device *its_find_device(struct its_node *its, u32 dev_id)
>  	return its_dev;
>  }
>  
> +static bool its_alloc_device_table(struct its_baser *baser, u32 dev_id)
> +{
> +	u32 entry_size = GITS_BASER_ENTRY_SIZE(baser->val);
> +	u64 *table = baser->base;
> +	struct page *page;
> +	u32 psz = SZ_64K;
> +	u32 idx;
> +
> +	/* Don't allow 'dev_id' that exceeds single, flat table limit */
> +	if (!(baser->val & GITS_BASER_INDIRECT)) {
> +		if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) / entry_size))
> +			return false;
> +		return true;
> +	}
> +
> +	/* Compute Level1 table index & check if that exceeds table range */
> +	idx = dev_id >> ilog2(baser->psz / entry_size);
> +	if (idx >= (PAGE_ORDER_TO_SIZE(baser->order) / GITS_LEVEL1_ENTRY_SIZE))
> +		return false;
> +
> +	/* Allocate memory for Level2 table */
> +	if (!table[idx]) {
> +		page = alloc_pages_exact(psz, GFP_KERNEL | __GFP_ZERO);
> +		if (!page)
> +			return false;
> +
> +		table[idx] = page_to_phys(page) | GITS_BASER_VALID;

Be careful, this must be written in LE format. If you're running a BE
kernel, you're in for a nasty surprise...

> +
> +		/* Flush memory to PoC if hardware dosn't support coherency */
> +		if (!(baser->val & GITS_BASER_SHAREABILITY_MASK)) {
> +			__flush_dcache_area(table + idx, GITS_LEVEL1_ENTRY_SIZE);
> +			__flush_dcache_area(page_address(page), psz);
> +		}
> +		/* Ensure updated table contents are visible to ITS hardware */
> +		dsb(sy);
> +	}
> +
> +	return true;
> +}
> +
>  static struct its_baser *its_get_baser(struct its_node *its, u32 type)
>  {
>  	int i;
> @@ -1176,11 +1260,8 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
>  	int sz;
>  
>  	baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
> -
> -	/* Don't allow 'dev_id' that exceeds single, flat table limit */
>  	if (baser) {
> -		if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) /
> -			      GITS_BASER_ENTRY_SIZE(baser->val)))
> +		if (!its_alloc_device_table(baser, dev_id))
>  			return NULL;
>  	} else if (ilog2(dev_id) >= its->device_ids)
>  		return NULL;

Please fold these checks into its_alloc_device_table so that it takes
an its_node as a first parameter instead of an its_baser. That will make
the code a bit more readable.

> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 9e6fdd3..df404ea 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -187,6 +187,7 @@
>  #define GITS_TYPER_PTA			(1UL << 19)
>  
>  #define GITS_CBASER_VALID		(1UL << 63)
> +#define GITS_BASER_INDIRECT		(1UL << 62)
>  #define GITS_CBASER_nCnB		(0UL << 59)
>  #define GITS_CBASER_nC			(1UL << 59)
>  #define GITS_CBASER_RaWt		(2UL << 59)
> @@ -238,6 +239,7 @@
>  #define GITS_BASER_TYPE_RESERVED6	6
>  #define GITS_BASER_TYPE_RESERVED7	7
>  
> +#define GITS_LEVEL1_ENTRY_SIZE		(8UL)
>  /*
>   * ITS commands
>   */


Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.


From mathieu.poirier at linaro.org  Fri May  6 07:26:38 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Fri, 6 May 2016 08:26:38 -0600
Subject: [PATCH] coresight: Handle build path error
In-Reply-To: <1462358484-9342-1-git-send-email-suzuki.poulose@arm.com>
References: <1462358484-9342-1-git-send-email-suzuki.poulose@arm.com>
Message-ID: <CANLsYkwEG-4U+hvdVNHQxoH_WuZvD_pYwDC6NSBOok9o5swNoA@mail.gmail.com>

On 4 May 2016 at 04:41, Suzuki K Poulose <suzuki.poulose at arm.com> wrote:
> Enabling a component via sysfs (echo 1 > enable_source), would
> trigger building a path from the enabled sources to the sink.
> If there is an error in the process (e.g, sink not enabled or
> the device (CPU corresponding to ETM) is not online), we never report
> failure, except for leaving a message in the dmesg.
>
> Do proper error checking for the build path and return the error.
>
> Before:
>  $ echo 0 > /sys/devices/system/cpu/cpu2/online
>  $ echo 1 > /sys/devices/cs_etm/cpu2/enable_source
>  $ echo $?
>  0
>
> After:
>  $ echo 0 > /sys/devices/system/cpu/cpu2/online
>  $ echo 1 > /sys/devices/cs_etm/cpu2/enable_source
>  -bash: echo: write error: No such device or address
>
> Cc: Mathie Porier <mathieu.poirier at linaro.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>

This patch looks good - thanks for the fix.  Due to how late we are in
the cycle I'd ask Greg to pick it up right away but there is a
(couple) of typos in my name on the CC line.  Either resend another
patch with the correct spelling or remove the CC line altogether.

Thanks,
Mathieu


> ---
>  drivers/hwtracing/coresight/coresight.c |    9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
> index 2ea5961..e0c5166 100644
> --- a/drivers/hwtracing/coresight/coresight.c
> +++ b/drivers/hwtracing/coresight/coresight.c
> @@ -393,6 +393,7 @@ out:
>  struct list_head *coresight_build_path(struct coresight_device *csdev)
>  {
>         struct list_head *path;
> +       int rc;
>
>         path = kzalloc(sizeof(struct list_head), GFP_KERNEL);
>         if (!path)
> @@ -400,9 +401,10 @@ struct list_head *coresight_build_path(struct coresight_device *csdev)
>
>         INIT_LIST_HEAD(path);
>
> -       if (_coresight_build_path(csdev, path)) {
> +       rc = _coresight_build_path(csdev, path);
> +       if (rc) {
>                 kfree(path);
> -               path = NULL;
> +               return ERR_PTR(rc);
>         }
>
>         return path;
> @@ -448,8 +450,9 @@ int coresight_enable(struct coresight_device *csdev)
>                 goto out;
>
>         path = coresight_build_path(csdev);
> -       if (!path) {
> +       if (IS_ERR(path)) {
>                 pr_err("building path(s) failed\n");
> +               ret = PTR_ERR(path);
>                 goto out;
>         }
>
> --
> 1.7.9.5
>


From nicolas.ferre at atmel.com  Fri May  6 07:30:10 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Fri, 6 May 2016 16:30:10 +0200
Subject: [PATCH] ARM: at91: sama5: Update defconfig
In-Reply-To: <1462480295-8034-1-git-send-email-marex@denx.de>
References: <1462480295-8034-1-git-send-email-marex@denx.de>
Message-ID: <572CAA72.4000107@atmel.com>

Le 05/05/2016 22:31, Marek Vasut a ?crit :
> Enable CGROUPS support, so we can boot userspace that uses systemd on
> top of kernel configured using this defconfig. The systemd userspace
> depends on cgroups and without them, it dies in mysterious ways.
> 
> Signed-off-by: Marek Vasut <marex at denx.de>
> Cc: Ludovic Desroches <ludovic.desroches at atmel.com>
> Cc: Alexandre Belloni <alexandre.belloni at free-electrons.com>

Hi Marek,

Acked-by: Nicolas Ferre <nicolas.ferre at atmel.com>

BTW, isn't it something else required to run a systemd enabled image?
I've seen that some of the option may be missing as well:

CONFIG_FHANDLE (libudev, mount and bind mount handling)
from: https://github.com/systemd/systemd/blob/master/README#L51

In the " Optional but strongly recommended:" I see interest in:
 CONFIG_AUTOFS4_FS
 CONFIG_TMPFS_XATTR
 CONFIG_{TMPFS,EXT4,XFS,BTRFS_FS,...}_POSIX_ACL

But it's maybe not so interesting for our little embedded systems.

I'm also puzzled about the need for more options about cgroups...

I add a couple of other people in Cc so we can figure out the proper
configuration set...

Thanks Marek for having started the discussion, bye,

> ---
>  arch/arm/configs/sama5_defconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
> index afbda41..1b60be2 100644
> --- a/arch/arm/configs/sama5_defconfig
> +++ b/arch/arm/configs/sama5_defconfig
> @@ -3,6 +3,7 @@
>  CONFIG_SYSVIPC=y
>  CONFIG_IRQ_DOMAIN_DEBUG=y
>  CONFIG_LOG_BUF_SHIFT=14
> +CONFIG_CGROUPS=y
>  CONFIG_BLK_DEV_INITRD=y
>  CONFIG_EMBEDDED=y
>  CONFIG_SLAB=y
> 


-- 
Nicolas Ferre


From paul.gortmaker at windriver.com  Fri May  6 07:31:49 2016
From: paul.gortmaker at windriver.com (Paul Gortmaker)
Date: Fri, 6 May 2016 10:31:49 -0400
Subject: [PATCH 0/3] Support MPS2 UART controller
In-Reply-To: <1461574068-14641-1-git-send-email-vladimir.murzin@arm.com>
References: <1461574068-14641-1-git-send-email-vladimir.murzin@arm.com>
Message-ID: <CAP=VYLopd8erCP9J9cTyZ+YubafKjWi3bHQp-swmyfyn2eZ_Ww@mail.gmail.com>

On Mon, Apr 25, 2016 at 4:47 AM, Vladimir Murzin
<vladimir.murzin at arm.com> wrote:
> Hi,
>
> These patches allow to use UART controller found on MPS2 platform.

Did you intend this driver to support being modular?  It has a bool Kconfig
(not tristate) which makes the module_exit dead code.

If it will always be builtin (with console as primary use case) then you can
see commit 89ebc27427695bfc1e769f1dd99bd243d332ac7a as a possible
update suggestion.

P.
--

>
> Following [1], please, consider to merge them into tty/serial tree.
>
> [1] https://lkml.org/lkml/2016/4/23/190
>
> Thanks!
>
> Vladimir Murzin (3):
>   dt-bindings: document the MPS2 UART bindings
>   serial: mps2-uart: add MPS2 UART driver
>   serial: mps2-uart: add support for early console
>
>  .../devicetree/bindings/serial/arm,mps2-uart.txt   |   19 +
>  drivers/tty/serial/Kconfig                         |   13 +
>  drivers/tty/serial/Makefile                        |    1 +
>  drivers/tty/serial/mps2-uart.c                     |  625 ++++++++++++++++++++
>  include/uapi/linux/serial_core.h                   |    3 +
>  5 files changed, 661 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/serial/arm,mps2-uart.txt
>  create mode 100644 drivers/tty/serial/mps2-uart.c
>
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-serial" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From Suzuki.Poulose at arm.com  Fri May  6 07:32:48 2016
From: Suzuki.Poulose at arm.com (Suzuki K Poulose)
Date: Fri, 6 May 2016 15:32:48 +0100
Subject: [PATCH] coresight: Handle build path error
In-Reply-To: <CANLsYkwEG-4U+hvdVNHQxoH_WuZvD_pYwDC6NSBOok9o5swNoA@mail.gmail.com>
References: <1462358484-9342-1-git-send-email-suzuki.poulose@arm.com>
 <CANLsYkwEG-4U+hvdVNHQxoH_WuZvD_pYwDC6NSBOok9o5swNoA@mail.gmail.com>
Message-ID: <572CAB10.7060103@arm.com>

On 06/05/16 15:26, Mathieu Poirier wrote:
> On 4 May 2016 at 04:41, Suzuki K Poulose <suzuki.poulose at arm.com> wrote:
>> Enabling a component via sysfs (echo 1 > enable_source), would
>> trigger building a path from the enabled sources to the sink.
>> If there is an error in the process (e.g, sink not enabled or
>> the device (CPU corresponding to ETM) is not online), we never report
>> failure, except for leaving a message in the dmesg.
>>
>> Do proper error checking for the build path and return the error.
>>
>> Before:
>>   $ echo 0 > /sys/devices/system/cpu/cpu2/online
>>   $ echo 1 > /sys/devices/cs_etm/cpu2/enable_source
>>   $ echo $?
>>   0
>>
>> After:
>>   $ echo 0 > /sys/devices/system/cpu/cpu2/online
>>   $ echo 1 > /sys/devices/cs_etm/cpu2/enable_source
>>   -bash: echo: write error: No such device or address
>>
>> Cc: Mathie Porier <mathieu.poirier at linaro.org>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
>
> This patch looks good - thanks for the fix.  Due to how late we are in
> the cycle I'd ask Greg to pick it up right away but there is a
> (couple) of typos in my name on the CC line.  Either resend another
> patch with the correct spelling or remove the CC line altogether.

Sorry about that. will resend it fixed.




From suzuki.poulose at arm.com  Fri May  6 07:35:50 2016
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Fri,  6 May 2016 15:35:50 +0100
Subject: [PATCH] coresight: Handle build path error
In-Reply-To: <CANLsYkwEG-4U+hvdVNHQxoH_WuZvD_pYwDC6NSBOok9o5swNoA@mail.gmail.com>
References: <CANLsYkwEG-4U+hvdVNHQxoH_WuZvD_pYwDC6NSBOok9o5swNoA@mail.gmail.com>
Message-ID: <1462545350-15970-1-git-send-email-suzuki.poulose@arm.com>

Enabling a component via sysfs (echo 1 > enable_source), would
trigger building a path from the enabled sources to the sink.
If there is an error in the process (e.g, sink not enabled or
the device (CPU corresponding to ETM) is not online), we never report
failure, except for leaving a message in the dmesg.

Do proper error checking for the build path and return the error.

Before:
 $ echo 0 > /sys/devices/system/cpu/cpu2/online
 $ echo 1 > /sys/devices/cs_etm/cpu2/enable_source
 $ echo $?
 0

After:
 $ echo 0 > /sys/devices/system/cpu/cpu2/online
 $ echo 1 > /sys/devices/cs_etm/cpu2/enable_source
 -bash: echo: write error: No such device or address

Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 2ea5961..e0c5166 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -393,6 +393,7 @@ out:
 struct list_head *coresight_build_path(struct coresight_device *csdev)
 {
 	struct list_head *path;
+	int rc;
 
 	path = kzalloc(sizeof(struct list_head), GFP_KERNEL);
 	if (!path)
@@ -400,9 +401,10 @@ struct list_head *coresight_build_path(struct coresight_device *csdev)
 
 	INIT_LIST_HEAD(path);
 
-	if (_coresight_build_path(csdev, path)) {
+	rc = _coresight_build_path(csdev, path);
+	if (rc) {
 		kfree(path);
-		path = NULL;
+		return ERR_PTR(rc);
 	}
 
 	return path;
@@ -448,8 +450,9 @@ int coresight_enable(struct coresight_device *csdev)
 		goto out;
 
 	path = coresight_build_path(csdev);
-	if (!path) {
+	if (IS_ERR(path)) {
 		pr_err("building path(s) failed\n");
+		ret = PTR_ERR(path);
 		goto out;
 	}
 
-- 
1.7.9.5



From mathieu.poirier at linaro.org  Fri May  6 07:43:23 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Fri, 6 May 2016 08:43:23 -0600
Subject: [PATCH] coresight: Handle build path error
In-Reply-To: <1462545350-15970-1-git-send-email-suzuki.poulose@arm.com>
References: <CANLsYkwEG-4U+hvdVNHQxoH_WuZvD_pYwDC6NSBOok9o5swNoA@mail.gmail.com>
 <1462545350-15970-1-git-send-email-suzuki.poulose@arm.com>
Message-ID: <CANLsYkwtSTwRD9kjqU0v60wNHoRLoXW1hTwRq3tZemO=RqnhQw@mail.gmail.com>

On 6 May 2016 at 08:35, Suzuki K Poulose <suzuki.poulose at arm.com> wrote:
> Enabling a component via sysfs (echo 1 > enable_source), would
> trigger building a path from the enabled sources to the sink.
> If there is an error in the process (e.g, sink not enabled or
> the device (CPU corresponding to ETM) is not online), we never report
> failure, except for leaving a message in the dmesg.
>
> Do proper error checking for the build path and return the error.
>
> Before:
>  $ echo 0 > /sys/devices/system/cpu/cpu2/online
>  $ echo 1 > /sys/devices/cs_etm/cpu2/enable_source
>  $ echo $?
>  0
>
> After:
>  $ echo 0 > /sys/devices/system/cpu/cpu2/online
>  $ echo 1 > /sys/devices/cs_etm/cpu2/enable_source
>  -bash: echo: write error: No such device or address
>
> Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> ---
>  drivers/hwtracing/coresight/coresight.c |    9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
> index 2ea5961..e0c5166 100644
> --- a/drivers/hwtracing/coresight/coresight.c
> +++ b/drivers/hwtracing/coresight/coresight.c
> @@ -393,6 +393,7 @@ out:
>  struct list_head *coresight_build_path(struct coresight_device *csdev)
>  {
>         struct list_head *path;
> +       int rc;
>
>         path = kzalloc(sizeof(struct list_head), GFP_KERNEL);
>         if (!path)
> @@ -400,9 +401,10 @@ struct list_head *coresight_build_path(struct coresight_device *csdev)
>
>         INIT_LIST_HEAD(path);
>
> -       if (_coresight_build_path(csdev, path)) {
> +       rc = _coresight_build_path(csdev, path);
> +       if (rc) {
>                 kfree(path);
> -               path = NULL;
> +               return ERR_PTR(rc);
>         }
>
>         return path;
> @@ -448,8 +450,9 @@ int coresight_enable(struct coresight_device *csdev)
>                 goto out;
>
>         path = coresight_build_path(csdev);
> -       if (!path) {
> +       if (IS_ERR(path)) {
>                 pr_err("building path(s) failed\n");
> +               ret = PTR_ERR(path);
>                 goto out;
>         }
>
> --
> 1.7.9.5
>

Thanks for the correction:

Acked-by: Mathieu Poirier <mathieu.poirier at linaro.org>

Greg, given how small the changes are can you pick this up?  Otherwise
I'll simply keep it in my tree.

Thanks,
Mathieu


From vladimir.murzin at arm.com  Fri May  6 07:43:24 2016
From: vladimir.murzin at arm.com (Vladimir Murzin)
Date: Fri, 6 May 2016 15:43:24 +0100
Subject: [PATCH 0/3] Support MPS2 UART controller
In-Reply-To: <CAP=VYLopd8erCP9J9cTyZ+YubafKjWi3bHQp-swmyfyn2eZ_Ww@mail.gmail.com>
References: <1461574068-14641-1-git-send-email-vladimir.murzin@arm.com>
 <CAP=VYLopd8erCP9J9cTyZ+YubafKjWi3bHQp-swmyfyn2eZ_Ww@mail.gmail.com>
Message-ID: <572CAD8C.5000102@arm.com>

On 06/05/16 15:31, Paul Gortmaker wrote:
> On Mon, Apr 25, 2016 at 4:47 AM, Vladimir Murzin
> <vladimir.murzin at arm.com> wrote:
>> Hi,
>>
>> These patches allow to use UART controller found on MPS2 platform.
> 
> Did you intend this driver to support being modular?  It has a bool Kconfig
> (not tristate) which makes the module_exit dead code.
> 
> If it will always be builtin (with console as primary use case) then you can
> see commit 89ebc27427695bfc1e769f1dd99bd243d332ac7a as a possible
> update suggestion.

Thanks for the pointer, Paul! I'll see how to update the driver and send
a patch after next merge window closed.

Cheers
Vladimir

> 
> P.
> --
> 
>>
>> Following [1], please, consider to merge them into tty/serial tree.
>>
>> [1] https://lkml.org/lkml/2016/4/23/190
>>
>> Thanks!
>>
>> Vladimir Murzin (3):
>>   dt-bindings: document the MPS2 UART bindings
>>   serial: mps2-uart: add MPS2 UART driver
>>   serial: mps2-uart: add support for early console
>>
>>  .../devicetree/bindings/serial/arm,mps2-uart.txt   |   19 +
>>  drivers/tty/serial/Kconfig                         |   13 +
>>  drivers/tty/serial/Makefile                        |    1 +
>>  drivers/tty/serial/mps2-uart.c                     |  625 ++++++++++++++++++++
>>  include/uapi/linux/serial_core.h                   |    3 +
>>  5 files changed, 661 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/serial/arm,mps2-uart.txt
>>  create mode 100644 drivers/tty/serial/mps2-uart.c
>>
>> --
>> 1.7.9.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-serial" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 



From jonas.jensen at gmail.com  Fri May  6 07:50:11 2016
From: jonas.jensen at gmail.com (Jonas Jensen)
Date: Fri, 6 May 2016 16:50:11 +0200
Subject: [PATCH v2 04/11] clocksource/moxart: Generalise timer for use on
 other socs
In-Reply-To: <20160503133603.GA19298@linaro.org>
References: <1461225849-28074-1-git-send-email-joel@jms.id.au>
 <1461225849-28074-5-git-send-email-joel@jms.id.au>
 <571A5FBA.9010204@linaro.org>
 <CACPK8XfgDPPYG=ON-Z+gEKSg1fe4PuqRWoMz8P-9oCMvgQKmhw@mail.gmail.com>
 <20160503133603.GA19298@linaro.org>
Message-ID: <CACmBeS2U62DTbGPDgcnPSRNSD180Jw8NWbV0A+6LF3QMBnczzA@mail.gmail.com>

On 3 May 2016 at 15:36, Daniel Lezcano <daniel.lezcano at linaro.org> wrote:
> Apparently, it could be the fttmr010 [2].
>
> May be Jonas Jensen can confirm that.

The best I can do is infer (if that helps).

Also I can test on UC-7112-LX Plus hardware (the patch I got from Ben
back in May 2015 was verified OK).


   Jonas


From thierry.reding at gmail.com  Fri May  6 07:54:17 2016
From: thierry.reding at gmail.com (Thierry Reding)
Date: Fri, 6 May 2016 16:54:17 +0200
Subject: [PATCH 1/2] drm: hdlcd: Skip PM callbacks if unbound
In-Reply-To: <eeb2a5540f50f5a3dd7f87861be1e9117bc4ed65.1462464611.git.robin.murphy@arm.com>
References: <eeb2a5540f50f5a3dd7f87861be1e9117bc4ed65.1462464611.git.robin.murphy@arm.com>
Message-ID: <20160506145417.GB15076@ulmo.ba.sec>

On Thu, May 05, 2016 at 05:13:37PM +0100, Robin Murphy wrote:
> Until an encoder component is available to trigger the HDLCD's component
> master bind callback, the drm_device we keep in drvdata isn't allocated.
> Since it is quite possible to, say, hibernate the system without having
> loaded the encoder driver, the PM callbacks need to check for a valid
> drm_device before trying to take the lock and suspend/resume the crtcs,
> otherwise this happens:
> 
> [   51.779092] Unable to handle kernel NULL pointer dereference at virtual address 00000200
> [   51.787143] pgd = ffff800974462000
> [   51.790514] [00000200] *pgd=0000000000000000
> [   51.794768] Internal error: Oops: 96000004 [#1] PREEMPT SMP
> [   51.800291] Modules linked in:
> [   51.803325] CPU: 4 PID: 2098 Comm: systemd-sleep Not tainted 4.6.0-rc6+ #4
> [   51.810140] Hardware name: ARM Juno development board (r1) (DT)
> [   51.816008] task: ffff800974430000 ti: ffff80097380c000 task.ti: ffff80097380c000
> [   51.823433] PC is at mutex_lock+0x14/0x60
> [   51.827411] LR is at drm_modeset_lock_all+0x3c/0xe0
> [   51.832246] pc : [<ffff0000087d55c4>] lr : [<ffff0000084839fc>] pstate: 40000145
> [   51.839577] sp : ffff80097380faf0
> [   51.842859] x29: ffff80097380faf0 x28: 0000000000000000
> [   51.848132] x27: 0000000000000002 x26: ffff000008e01000
> [   51.853405] x25: ffff0000084cc000 x24: ffff000008dcb408
> [   51.858678] x23: ffff000008e7c000 x22: ffff8009760e8870
> [   51.863962] x21: 0000000000000200 x20: 0000000000000000
> [   51.869244] x19: 0000000000000200 x18: ffff800079357dd0
> [   51.874527] x17: 0000ffff8a00ab88 x16: 0000000000000018
> [   51.879809] x15: 0000000000000018 x14: 0000000000000000
> [   51.885091] x13: 0000000000000002 x12: 0000000000000000
> [   51.890374] x11: ffff0000087ff904 x10: 0000000000000840
> [   51.895656] x9 : 0000000000000000 x8 : ffff800973821680
> [   51.900938] x7 : 0000000000000000 x6 : 000000000000003f
> [   51.906220] x5 : 0000000000000040 x4 : 0000000000000000
> [   51.911502] x3 : 0000000000000004 x2 : 0000000000000000
> [   51.916784] x1 : 0000000000000001 x0 : 0000000000000200
> ...
> [   52.339406] [<ffff0000087d55c4>] mutex_lock+0x14/0x60
> [   52.344425] [<ffff0000084839fc>] drm_modeset_lock_all+0x3c/0xe0
> [   52.350305] [<ffff00000848a034>] hdlcd_pm_suspend+0x2c/0x90
> [   52.355842] [<ffff0000084c0d14>] platform_pm_suspend+0x24/0x58
> [   52.361638] [<ffff0000084cc190>] dpm_run_callback.isra.4+0x20/0x68
> [   52.367778] [<ffff0000084ccad4>] __device_suspend+0xe4/0x238
> [   52.373400] [<ffff0000084cdcac>] dpm_suspend+0x10c/0x240
> [   52.378679] [<ffff0000084ce0b8>] dpm_suspend_start+0x70/0x80
> [   52.384302] [<ffff0000080f80e4>] suspend_devices_and_enter+0x9c/0x480
> [   52.390699] [<ffff0000080f8698>] pm_suspend+0x1d0/0x240
> [   52.395890] [<ffff0000080f7280>] state_store+0x80/0x100
> [   52.401084] [<ffff0000083503f4>] kobj_attr_store+0x14/0x28
> [   52.406535] [<ffff000008238580>] sysfs_kf_write+0x48/0x58
> [   52.411899] [<ffff00000823798c>] kernfs_fop_write+0xbc/0x188
> [   52.417521] [<ffff0000081c71f4>] __vfs_write+0x1c/0xe0
> [   52.422626] [<ffff0000081c8144>] vfs_write+0x8c/0x1a8
> [   52.427644] [<ffff0000081c953c>] SyS_write+0x44/0xa0
> [   52.432578] [<ffff000008084ecc>] __sys_trace_return+0x0/0x4
> [   52.438114] Code: 910003fd f9000bf3 aa0003f3 f9800011 (885ffc01)
> [   52.444229] ---[ end trace 34b87a5fb9453f65 ]---
> 
> Acked-by: Liviu Dudau <Liviu.Dudau at arm.com>
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
>  drivers/gpu/drm/arm/hdlcd_drv.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> index 734899c4e4bb..86a5eea4cf53 100644
> --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> @@ -498,7 +498,7 @@ static int __maybe_unused hdlcd_pm_suspend(struct device *dev)
>  	struct drm_device *drm = dev_get_drvdata(dev);
>  	struct drm_crtc *crtc;
>  
> -	if (pm_runtime_suspended(dev))
> +	if (pm_runtime_suspended(dev) || !drm)
>  		return 0;
>  
>  	drm_modeset_lock_all(drm);
> @@ -513,7 +513,7 @@ static int __maybe_unused hdlcd_pm_resume(struct device *dev)
>  	struct drm_device *drm = dev_get_drvdata(dev);
>  	struct drm_crtc *crtc;
>  
> -	if (!pm_runtime_suspended(dev))
> +	if (!pm_runtime_suspended(dev) || !drm)
>  		return 0;

Perhaps rather than this workaround you should only enable runtime PM on
this after the master has been bound?

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

From nicolas.ferre at atmel.com  Fri May  6 07:56:19 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Fri, 6 May 2016 16:56:19 +0200
Subject: [GIT PULL] at91: dt for 4.7 #3
Message-ID: <1462546579-3398-1-git-send-email-nicolas.ferre@atmel.com>

Arnd, Olof, Kevin,

Some more DT material for 4.7. The fix on the VInCo platform is due to an error
on the Ethernet driver that was not taking the gpio flag into account. As it is
about to be fixed now, I have to update the only DT that was making use of it.
Otherwise, all is about the TRNG nodes addition.

Thanks, best regards,

The following changes since commit 517550075c31917dc729d7cec0b4a0ca65294f14:

  ARM: dts: at91: sama5d2: add slow clock to watchdog node (2016-04-27 14:08:58 +0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91.git tags/at91-dt3

for you to fetch changes up to 00bf4f78b56f7d86dff5ee6242f46ef6de84f8b0:

  ARM: dts: at91: sama5d4: add trng node (2016-05-06 15:42:53 +0200)

----------------------------------------------------------------
Third batch of DT changes for 4.7:
- a fix for the VInCo platform: reset gpio specification for Ethernet
- addition of True Random Number Generator (TRNG) for all sama5 platforms
- trivial adjustment of TRNG register map size for at91sam9g45 family

----------------------------------------------------------------
Mike Williams (3):
      ARM: dts: at91: sama5d2: add trng node
      ARM: dts: at91: sama5d3: add trng node
      ARM: dts: at91: sama5d4: add trng node

Nicolas Ferre (2):
      ARM: dts: at91: VInCo: fix phy reset gpio flag
      ARM: dts: at91: at91sam9g45 family: reduce the trng register map size

 arch/arm/boot/dts/at91-vinco.dts   | 4 ++--
 arch/arm/boot/dts/at91sam9g45.dtsi | 2 +-
 arch/arm/boot/dts/sama5d2.dtsi     | 7 +++++++
 arch/arm/boot/dts/sama5d3.dtsi     | 7 +++++++
 arch/arm/boot/dts/sama5d4.dtsi     | 7 +++++++
 5 files changed, 24 insertions(+), 3 deletions(-)

-- 
Nicolas Ferre


From hch at infradead.org  Fri May  6 07:59:37 2016
From: hch at infradead.org (Christoph Hellwig)
Date: Fri, 6 May 2016 07:59:37 -0700
Subject: [PATCH] maintainers: update my email address(es)
In-Reply-To: <20160505161254.GY19428@n2100.arm.linux.org.uk>
References: <20160505161254.GY19428@n2100.arm.linux.org.uk>
Message-ID: <20160506145937.GA24095@infradead.org>

On Thu, May 05, 2016 at 05:12:54PM +0100, Russell King wrote:
> Update my email and web addresses in the kernel maintainers file.

What's up with linux.org.uk?  It also seems like Al's address at
zeniv.linux.org.uk has been bouncing for a while..


From andrea.adami at gmail.com  Fri May  6 08:27:34 2016
From: andrea.adami at gmail.com (Andrea Adami)
Date: Fri,  6 May 2016 17:27:34 +0200
Subject: [PATCH 1/1] ASoC: pxa: Fix module autoload for platform drivers
Message-ID: <1462548454-28597-1-git-send-email-andrea.adami@gmail.com>

These platform drivers are lacking MODULE_ALIAS so module autoloading
doesn't work. Tested on corgi and poodle with kernel 4.4.

Signed-off-by: Andrea Adami <andrea.adami at gmail.com>
---
 sound/soc/pxa/brownstone.c     | 1 +
 sound/soc/pxa/mioa701_wm9713.c | 1 +
 sound/soc/pxa/mmp-pcm.c        | 1 +
 sound/soc/pxa/mmp-sspa.c       | 1 +
 sound/soc/pxa/palm27x.c        | 1 +
 sound/soc/pxa/pxa-ssp.c        | 1 +
 sound/soc/pxa/pxa2xx-ac97.c    | 1 +
 sound/soc/pxa/pxa2xx-pcm.c     | 1 +
 8 files changed, 8 insertions(+)

diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c
index ec522e9..b6cb995 100644
--- a/sound/soc/pxa/brownstone.c
+++ b/sound/soc/pxa/brownstone.c
@@ -133,3 +133,4 @@ module_platform_driver(mmp_driver);
 MODULE_AUTHOR("Leo Yan <leoy at marvell.com>");
 MODULE_DESCRIPTION("ALSA SoC Brownstone");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:brownstone-audio");
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
index 5c8f9db..d1661fa 100644
--- a/sound/soc/pxa/mioa701_wm9713.c
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -207,3 +207,4 @@ module_platform_driver(mioa701_wm9713_driver);
 MODULE_AUTHOR("Robert Jarzmik (rjarzmik at free.fr)");
 MODULE_DESCRIPTION("ALSA SoC WM9713 MIO A701");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mioa701-wm9713");
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
index 51e790d..96df9b2 100644
--- a/sound/soc/pxa/mmp-pcm.c
+++ b/sound/soc/pxa/mmp-pcm.c
@@ -248,3 +248,4 @@ module_platform_driver(mmp_pcm_driver);
 MODULE_AUTHOR("Leo Yan <leoy at marvell.com>");
 MODULE_DESCRIPTION("MMP Soc Audio DMA module");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mmp-pcm-audio");
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index eca60c2..ca8b23f 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -482,3 +482,4 @@ module_platform_driver(asoc_mmp_sspa_driver);
 MODULE_AUTHOR("Leo Yan <leoy at marvell.com>");
 MODULE_DESCRIPTION("MMP SSPA SoC Interface");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mmp-sspa-dai");
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 4e74d95..bcc81e9 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -161,3 +161,4 @@ module_platform_driver(palm27x_wm9712_driver);
 MODULE_AUTHOR("Marek Vasut <marek.vasut at gmail.com>");
 MODULE_DESCRIPTION("ALSA SoC Palm T|X, T5 and LifeDrive");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:palm27x-asoc");
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index da03fad..3cad990 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -833,3 +833,4 @@ module_platform_driver(asoc_ssp_driver);
 MODULE_AUTHOR("Mark Brown <broonie at opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("PXA SSP/PCM SoC Interface");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa-ssp-dai");
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index f3de615..9615e6d 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -287,3 +287,4 @@ module_platform_driver(pxa2xx_ac97_driver);
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-ac97");
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 9f39039..410d48b 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -117,3 +117,4 @@ module_platform_driver(pxa_pcm_driver);
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa-pcm-audio");
-- 
1.9.1



From mathieu.poirier at linaro.org  Fri May  6 08:52:42 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Fri, 6 May 2016 09:52:42 -0600
Subject: [PATCH] Xen: EFI: Parse DT parameters for Xen specific UEFI
In-Reply-To: <1462523526-3172-1-git-send-email-zhaoshenglong@huawei.com>
References: <1462523526-3172-1-git-send-email-zhaoshenglong@huawei.com>
Message-ID: <CANLsYkxUyiUfdjm39SvhKSvmddPLFP3JFAeHpYuxgPyZfexw6w@mail.gmail.com>

On 6 May 2016 at 02:32, Shannon Zhao <zhaoshenglong at huawei.com> wrote:
> From: Shannon Zhao <shannon.zhao at linaro.org>
>
> Add a new function to parse DT parameters for Xen specific UEFI just
> like the way for normal UEFI. Then it could reuse the existing codes.
>
> If Xen supports EFI, initialize runtime services.
>
> CC: Matt Fleming <matt at codeblueprint.co.uk>
> Signed-off-by: Shannon Zhao <shannon.zhao at linaro.org>
> ---
> Drop using of EFI_PARAVIRT. Discussion can be found from [1].
> [1] https://lkml.org/lkml/2016/4/29/8
> ---
>  arch/arm/include/asm/efi.h         |  2 +
>  arch/arm/xen/enlighten.c           | 16 ++++++++
>  arch/arm64/include/asm/efi.h       |  2 +
>  drivers/firmware/efi/arm-runtime.c | 70 +++++++++++++++++++++++---------
>  drivers/firmware/efi/efi.c         | 81 ++++++++++++++++++++++++++++++--------
>  5 files changed, 137 insertions(+), 34 deletions(-)
>
> diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
> index e0eea72..5ba4343 100644
> --- a/arch/arm/include/asm/efi.h
> +++ b/arch/arm/include/asm/efi.h
> @@ -52,9 +52,11 @@ static inline void efi_set_pgd(struct mm_struct *mm)
>
>  void efi_virtmap_load(void);
>  void efi_virtmap_unload(void);
> +int xen_arm_enable_runtime_services(void);
>
>  #else
>  #define efi_init()
> +#define xen_arm_enable_runtime_services() (0)
>  #endif /* CONFIG_EFI */
>
>  /* arch specific definitions used by the stub code */
> diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
> index 13e3e9f..3362870 100644
> --- a/arch/arm/xen/enlighten.c
> +++ b/arch/arm/xen/enlighten.c
> @@ -16,6 +16,7 @@
>  #include <asm/xen/hypervisor.h>
>  #include <asm/xen/hypercall.h>
>  #include <asm/system_misc.h>
> +#include <asm/efi.h>
>  #include <linux/interrupt.h>
>  #include <linux/irqreturn.h>
>  #include <linux/module.h>
> @@ -261,6 +262,13 @@ static int __init fdt_find_hyper_node(unsigned long node, const char *uname,
>             !strncmp(hyper_node.prefix, s, strlen(hyper_node.prefix)))
>                 hyper_node.version = s + strlen(hyper_node.prefix);
>
> +       if (IS_ENABLED(CONFIG_XEN_EFI)) {
> +               /* Check if Xen supports EFI */
> +               if ((of_get_flat_dt_subnode_by_name(node, "uefi") > 0) &&
> +                   !efi_runtime_disabled())
> +                       set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
> +       }
> +
>         return 0;
>  }
>
> @@ -338,6 +346,7 @@ static int __init xen_guest_init(void)
>  {
>         struct xen_add_to_physmap xatp;
>         struct shared_info *shared_info_page = NULL;
> +       int ret;
>
>         if (!xen_domain())
>                 return 0;
> @@ -352,6 +361,13 @@ static int __init xen_guest_init(void)
>                 return -ENODEV;
>         }
>
> +       if (IS_ENABLED(CONFIG_XEN_EFI) && efi_enabled(EFI_BOOT) &&
> +           efi_enabled(EFI_RUNTIME_SERVICES)) {
> +               ret = xen_arm_enable_runtime_services();
> +               if (ret)
> +                       return ret;
> +       }
> +
>         shared_info_page = (struct shared_info *)get_zeroed_page(GFP_KERNEL);
>
>         if (!shared_info_page) {
> diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
> index 8e88a69..574bee5 100644
> --- a/arch/arm64/include/asm/efi.h
> +++ b/arch/arm64/include/asm/efi.h
> @@ -8,8 +8,10 @@
>
>  #ifdef CONFIG_EFI
>  extern void efi_init(void);
> +int xen_arm_enable_runtime_services(void);
>  #else
>  #define efi_init()
> +#define xen_arm_enable_runtime_services() (0)
>  #endif
>
>  int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
> diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
> index 6ae21e4..211ec10 100644
> --- a/drivers/firmware/efi/arm-runtime.c
> +++ b/drivers/firmware/efi/arm-runtime.c
> @@ -27,6 +27,7 @@
>  #include <asm/mmu.h>
>  #include <asm/pgalloc.h>
>  #include <asm/pgtable.h>
> +#include <asm/xen/xen-ops.h>
>
>  extern u64 efi_system_table;
>
> @@ -39,6 +40,33 @@ static struct mm_struct efi_mm = {
>         .mmlist                 = LIST_HEAD_INIT(efi_mm.mmlist),
>  };
>
> +static int __init efi_remap_init(void)
> +{
> +       u64 mapsize;
> +
> +       pr_info("Remapping and enabling EFI services.\n");
> +
> +       mapsize = memmap.map_end - memmap.map;
> +       memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
> +                                                  mapsize);
> +       if (!memmap.map) {
> +               pr_err("Failed to remap EFI memory map\n");
> +               return -ENOMEM;
> +       }
> +       memmap.map_end = memmap.map + mapsize;
> +       efi.memmap = &memmap;
> +
> +       efi.systab = (__force void *)ioremap_cache(efi_system_table,
> +                                                  sizeof(efi_system_table_t));
> +       if (!efi.systab) {

Is there a reason why memmap.map isn't iounmap() in the error path?
The original code didn't have it either, hence the question.

Thanks,
Mathieu

> +               pr_err("Failed to remap EFI System Table\n");
> +               return -ENOMEM;
> +       }
> +       set_bit(EFI_SYSTEM_TABLES, &efi.flags);
> +
> +       return 0;
> +}
> +
>  static bool __init efi_virtmap_init(void)
>  {
>         efi_memory_desc_t *md;
> @@ -75,7 +103,7 @@ static bool __init efi_virtmap_init(void)
>   */
>  static int __init arm_enable_runtime_services(void)
>  {
> -       u64 mapsize;
> +       int ret;
>
>         if (!efi_enabled(EFI_BOOT)) {
>                 pr_info("EFI services will not be available.\n");
> @@ -87,25 +115,14 @@ static int __init arm_enable_runtime_services(void)
>                 return 0;
>         }
>
> -       pr_info("Remapping and enabling EFI services.\n");
> -
> -       mapsize = memmap.map_end - memmap.map;
> -       memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
> -                                                  mapsize);
> -       if (!memmap.map) {
> -               pr_err("Failed to remap EFI memory map\n");
> -               return -ENOMEM;
> +       if (efi_enabled(EFI_RUNTIME_SERVICES)) {
> +               pr_info("EFI runtime services access via paravirt.\n");
> +               return 0;
>         }
> -       memmap.map_end = memmap.map + mapsize;
> -       efi.memmap = &memmap;
>
> -       efi.systab = (__force void *)ioremap_cache(efi_system_table,
> -                                                  sizeof(efi_system_table_t));
> -       if (!efi.systab) {
> -               pr_err("Failed to remap EFI System Table\n");
> -               return -ENOMEM;
> -       }
> -       set_bit(EFI_SYSTEM_TABLES, &efi.flags);
> +       ret = efi_remap_init();
> +       if (ret)
> +               return ret;
>
>         if (!efi_virtmap_init()) {
>                 pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
> @@ -122,6 +139,23 @@ static int __init arm_enable_runtime_services(void)
>  }
>  early_initcall(arm_enable_runtime_services);
>
> +int __init xen_arm_enable_runtime_services(void)
> +{
> +       int ret;
> +
> +       ret = efi_remap_init();
> +       if (ret)
> +               return ret;
> +
> +       if (IS_ENABLED(CONFIG_XEN_EFI)) {
> +               /* Set up runtime services function pointers for Xen Dom0 */
> +               xen_efi_runtime_setup();
> +               efi.runtime_version = efi.systab->hdr.revision;
> +       }
> +
> +       return 0;
> +}
> +
>  void efi_virtmap_load(void)
>  {
>         preempt_disable();
> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index 3a69ed5..f586e1e 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -469,12 +469,14 @@ device_initcall(efi_load_efivars);
>                 FIELD_SIZEOF(struct efi_fdt_params, field) \
>         }
>
> -static __initdata struct {
> +struct params {
>         const char name[32];
>         const char propname[32];
>         int offset;
>         int size;
> -} dt_params[] = {
> +};
> +
> +static __initdata struct params fdt_params[] = {
>         UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
>         UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
>         UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
> @@ -482,44 +484,91 @@ static __initdata struct {
>         UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
>  };
>
> +static __initdata struct params xen_fdt_params[] = {
> +       UEFI_PARAM("System Table", "xen,uefi-system-table", system_table),
> +       UEFI_PARAM("MemMap Address", "xen,uefi-mmap-start", mmap),
> +       UEFI_PARAM("MemMap Size", "xen,uefi-mmap-size", mmap_size),
> +       UEFI_PARAM("MemMap Desc. Size", "xen,uefi-mmap-desc-size", desc_size),
> +       UEFI_PARAM("MemMap Desc. Version", "xen,uefi-mmap-desc-ver", desc_ver)
> +};
> +
> +#define EFI_FDT_PARAMS_SIZE    ARRAY_SIZE(fdt_params)
> +
> +static __initdata struct {
> +       const char *uname;
> +       const char *subnode;
> +       struct params *params;
> +} dt_params[] = {
> +       { "hypervisor", "uefi", xen_fdt_params },
> +       { "chosen", NULL, fdt_params },
> +};
> +
>  struct param_info {
>         int found;
>         void *params;
> +       const char *missing;
>  };
>
> -static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
> -                                      int depth, void *data)
> +static int __init __find_uefi_params(unsigned long node,
> +                                    struct param_info *info,
> +                                    struct params *params)
>  {
> -       struct param_info *info = data;
>         const void *prop;
>         void *dest;
>         u64 val;
>         int i, len;
>
> -       if (depth != 1 || strcmp(uname, "chosen") != 0)
> -               return 0;
> -
> -       for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
> -               prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
> -               if (!prop)
> +       for (i = 0; i < EFI_FDT_PARAMS_SIZE; i++) {
> +               prop = of_get_flat_dt_prop(node, params[i].propname, &len);
> +               if (!prop) {
> +                       info->missing = params[i].name;
>                         return 0;
> -               dest = info->params + dt_params[i].offset;
> +               }
> +
> +               dest = info->params + params[i].offset;
>                 info->found++;
>
>                 val = of_read_number(prop, len / sizeof(u32));
>
> -               if (dt_params[i].size == sizeof(u32))
> +               if (params[i].size == sizeof(u32))
>                         *(u32 *)dest = val;
>                 else
>                         *(u64 *)dest = val;
>
>                 if (efi_enabled(EFI_DBG))
> -                       pr_info("  %s: 0x%0*llx\n", dt_params[i].name,
> -                               dt_params[i].size * 2, val);
> +                       pr_info("  %s: 0x%0*llx\n", params[i].name,
> +                               params[i].size * 2, val);
>         }
> +
>         return 1;
>  }
>
> +static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
> +                                      int depth, void *data)
> +{
> +       struct param_info *info = data;
> +       int i;
> +
> +       for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
> +               const char *subnode = dt_params[i].subnode;
> +
> +               if (depth != 1 || strcmp(uname, dt_params[i].uname) != 0) {
> +                       info->missing = dt_params[i].params[0].name;
> +                       continue;
> +               }
> +
> +               if (subnode) {
> +                       node = of_get_flat_dt_subnode_by_name(node, subnode);
> +                       if (node < 0)
> +                               return 0;
> +               }
> +
> +               return __find_uefi_params(node, info, dt_params[i].params);
> +       }
> +
> +       return 0;
> +}
> +
>  int __init efi_get_fdt_params(struct efi_fdt_params *params)
>  {
>         struct param_info info;
> @@ -535,7 +584,7 @@ int __init efi_get_fdt_params(struct efi_fdt_params *params)
>                 pr_info("UEFI not found.\n");
>         else if (!ret)
>                 pr_err("Can't find '%s' in device tree!\n",
> -                      dt_params[info.found].name);
> +                      info.missing);
>
>         return ret;
>  }
> --
> 2.0.4
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From marex at denx.de  Fri May  6 09:27:47 2016
From: marex at denx.de (Marek Vasut)
Date: Fri, 06 May 2016 18:27:47 +0200
Subject: [PATCH] ARM: at91: sama5: Update defconfig
In-Reply-To: <572CAA72.4000107@atmel.com>
References: <1462480295-8034-1-git-send-email-marex@denx.de>
 <572CAA72.4000107@atmel.com>
Message-ID: <572CC603.4000102@denx.de>

On 05/06/2016 04:30 PM, Nicolas Ferre wrote:
> Le 05/05/2016 22:31, Marek Vasut a ?crit :
>> Enable CGROUPS support, so we can boot userspace that uses systemd on
>> top of kernel configured using this defconfig. The systemd userspace
>> depends on cgroups and without them, it dies in mysterious ways.
>>
>> Signed-off-by: Marek Vasut <marex at denx.de>
>> Cc: Ludovic Desroches <ludovic.desroches at atmel.com>
>> Cc: Alexandre Belloni <alexandre.belloni at free-electrons.com>
> 
> Hi Marek,

Hi!

> Acked-by: Nicolas Ferre <nicolas.ferre at atmel.com>
> 
> BTW, isn't it something else required to run a systemd enabled image?
> I've seen that some of the option may be missing as well:
> 
> CONFIG_FHANDLE (libudev, mount and bind mount handling)
> from: https://github.com/systemd/systemd/blob/master/README#L51

This one is absolutely mandatory, but this is also enabled by default
already. Debian testing with systemd won't boot without FHANDLE too,
so this is easy to trap for me.

> In the " Optional but strongly recommended:" I see interest in:
>  CONFIG_AUTOFS4_FS
>  CONFIG_TMPFS_XATTR
>  CONFIG_{TMPFS,EXT4,XFS,BTRFS_FS,...}_POSIX_ACL
> 
> But it's maybe not so interesting for our little embedded systems.

Hm, these are disabled, but I cannot comment on their significance.

> I'm also puzzled about the need for more options about cgroups...

Enabling CONFIG_CGROUPS is enough to make systemd happy and booting.
I didn't probe further, sorry.

> I add a couple of other people in Cc so we can figure out the proper
> configuration set...

Thanks!

> Thanks Marek for having started the discussion, bye,
> 
>> ---
>>  arch/arm/configs/sama5_defconfig | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
>> index afbda41..1b60be2 100644
>> --- a/arch/arm/configs/sama5_defconfig
>> +++ b/arch/arm/configs/sama5_defconfig
>> @@ -3,6 +3,7 @@
>>  CONFIG_SYSVIPC=y
>>  CONFIG_IRQ_DOMAIN_DEBUG=y
>>  CONFIG_LOG_BUF_SHIFT=14
>> +CONFIG_CGROUPS=y
>>  CONFIG_BLK_DEV_INITRD=y
>>  CONFIG_EMBEDDED=y
>>  CONFIG_SLAB=y
>>
> 
> 


-- 
Best regards,
Marek Vasut


From broonie at kernel.org  Fri May  6 10:17:04 2016
From: broonie at kernel.org (Mark Brown)
Date: Fri, 6 May 2016 18:17:04 +0100
Subject: [RFC PATCH 1/7] ALSA: ac97: split out the generic ac97 registers
In-Reply-To: <87h9ecp9tp.fsf@belgarion.home>
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-2-git-send-email-robert.jarzmik@free.fr>
 <20160503115159.GP6292@sirena.org.uk>
 <87y47roski.fsf@belgarion.home>
 <20160504090702.GV6292@sirena.org.uk>
 <87pot0pbnf.fsf@belgarion.home>
 <20160505191728.GK6292@sirena.org.uk>
 <87h9ecp9tp.fsf@belgarion.home>
Message-ID: <20160506171704.GY6292@sirena.org.uk>

On Thu, May 05, 2016 at 09:46:10PM +0200, Robert Jarzmik wrote:
> Mark Brown <broonie at kernel.org> writes:
> > On Thu, May 05, 2016 at 09:06:44PM +0200, Robert Jarzmik wrote:
> >> Mark Brown <broonie at kernel.org> writes:

> >> This transition will be easier if the new ac97 code is isolated as much as
> >> possible from the former code while providing backward compatibility ... hence
> >> this patch.

> > It'd probably have been clearer to me if it were splitting out all the
> > register definitions rather than just some of them.

> Euh unless I'm missing something I have splitted out all the ac97 generic
> registers AFAIK. The only remaining ones are chip specific which I didn't take
> as they should be in codec specific code and not ac97 generic one.

The changelog read like it was trying to split things used by the
controller vs things used by CODEC drivers, I didn't get as far as
checking all the registers TBH.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160506/e5df7443/attachment.sig>

From nkaje at codeaurora.org  Fri May  6 10:36:17 2016
From: nkaje at codeaurora.org (Naveen Kaje)
Date: Fri, 6 May 2016 11:36:17 -0600
Subject: [V2, 1/2] drivers: i2c: qup: Fix broken dma when CONFIG_DEBUG_SG
 is enabled
In-Reply-To: <1462534274-28925-2-git-send-email-sricharan@codeaurora.org>
References: <1462534274-28925-2-git-send-email-sricharan@codeaurora.org>
Message-ID: <91a135eb-b517-a9ec-5f96-cbed60bbe710@codeaurora.org>



On 5/6/2016 5:31 AM, Sricharan R wrote:
> With CONFIG_DEBUG_SG is enabled and when dma mode is used, below dump is seen,
>
> ------------[ cut here ]------------
> kernel BUG at include/linux/scatterlist.h:140!
> Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
> Modules linked in:
> CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.0-00459-g9f087b9-dirty #7
> Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
> task: ffffffc036868000 ti: ffffffc036870000 task.ti: ffffffc036870000
> PC is at qup_sg_set_buf.isra.13+0x138/0x154
> LR is at qup_sg_set_buf.isra.13+0x50/0x154
> pc : [<ffffffc0005a0ed8>] lr : [<ffffffc0005a0df0>] pstate: 60000145
> sp : ffffffc0368735c0
> x29: ffffffc0368735c0 x28: ffffffc036873752
> x27: ffffffc035233018 x26: ffffffc000c4e000
> x25: 0000000000000000 x24: 0000000000000004
> x23: 0000000000000000 x22: ffffffc035233668
> x21: ffffff80004e3000 x20: ffffffc0352e0018
> x19: 0000004000000000 x18: 0000000000000028
> x17: 0000000000000004 x16: ffffffc0017a39c8
> x15: 0000000000001cdf x14: ffffffc0019929d8
> x13: ffffffc0352e0018 x12: 0000000000000000
> x11: 0000000000000001 x10: 0000000000000001
> x9 : ffffffc0012b2d70 x8 : ffffff80004e3000
> x7 : 0000000000000018 x6 : 0000000030000000
> x5 : ffffffc00199f018 x4 : ffffffc035233018
> x3 : 0000000000000004 x2 : 00000000c0000000
> x1 : 0000000000000003 x0 : 0000000000000000
>
> Process swapper/0 (pid: 1, stack limit = 0xffffffc036870020)
> Stack: (0xffffffc0368735c0 to 0xffffffc036874000)
>
> Change allocation of sg buffers from dma_coherent memory to kzalloc
> to fix the issue.
>
> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> Reviewed-by: Andy Gross <andy.gross at linaro.org>

Tested on QDF2432 with ACPI and SMBus support patches for regressions. 
Note that this platform does not use DMA mode.

Tested-by: Naveen Kaje <nkaje at codeaurora.org>

> ---
>   drivers/i2c/busses/i2c-qup.c | 53 ++++++++++++++------------------------------
>   1 file changed, 17 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
> index 23eaabb..8620e99 100644
> --- a/drivers/i2c/busses/i2c-qup.c
> +++ b/drivers/i2c/busses/i2c-qup.c
> @@ -585,8 +585,8 @@ static void qup_i2c_bam_cb(void *data)
>   }
>   
>   static int qup_sg_set_buf(struct scatterlist *sg, void *buf,
> -			  struct qup_i2c_tag *tg, unsigned int buflen,
> -			  struct qup_i2c_dev *qup, int map, int dir)
> +			  unsigned int buflen, struct qup_i2c_dev *qup,
> +			  int dir)
>   {
>   	int ret;
>   
> @@ -595,9 +595,6 @@ static int qup_sg_set_buf(struct scatterlist *sg, void *buf,
>   	if (!ret)
>   		return -EINVAL;
>   
> -	if (!map)
> -		sg_dma_address(sg) = tg->addr + ((u8 *)buf - tg->start);
> -
>   	return 0;
>   }
>   
> @@ -670,16 +667,15 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>   				/* scratch buf to read the start and len tags */
>   				ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
>   						     &qup->brx.tag.start[0],
> -						     &qup->brx.tag,
> -						     2, qup, 0, 0);
> +						     2, qup, DMA_FROM_DEVICE);
>   
>   				if (ret)
>   					return ret;
>   
>   				ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
>   						     &msg->buf[limit * i],
> -						     NULL, tlen, qup,
> -						     1, DMA_FROM_DEVICE);
> +						     tlen, qup,
> +						     DMA_FROM_DEVICE);
>   				if (ret)
>   					return ret;
>   
> @@ -688,7 +684,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>   			}
>   			ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
>   					     &qup->start_tag.start[off],
> -					     &qup->start_tag, len, qup, 0, 0);
> +					     len, qup, DMA_TO_DEVICE);
>   			if (ret)
>   				return ret;
>   
> @@ -696,8 +692,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>   			/* scratch buf to read the BAM EOT and FLUSH tags */
>   			ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
>   					     &qup->brx.tag.start[0],
> -					     &qup->brx.tag, 2,
> -					     qup, 0, 0);
> +					     2, qup, DMA_FROM_DEVICE);
>   			if (ret)
>   				return ret;
>   		} else {
> @@ -709,17 +704,15 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>   				len = qup_i2c_set_tags(tags, qup, msg, 1);
>   
>   				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
> -						     tags,
> -						     &qup->start_tag, len,
> -						     qup, 0, 0);
> +						     tags, len,
> +						     qup, DMA_TO_DEVICE);
>   				if (ret)
>   					return ret;
>   
>   				tx_len += len;
>   				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
>   						     &msg->buf[limit * i],
> -						     NULL, tlen, qup, 1,
> -						     DMA_TO_DEVICE);
> +						     tlen, qup, DMA_TO_DEVICE);
>   				if (ret)
>   					return ret;
>   				i++;
> @@ -738,8 +731,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>   							QUP_BAM_FLUSH_STOP;
>   				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
>   						     &qup->btx.tag.start[0],
> -						     &qup->btx.tag, len,
> -						     qup, 0, 0);
> +						     len, qup, DMA_TO_DEVICE);
>   				if (ret)
>   					return ret;
>   				tx_nents += 1;
> @@ -1268,6 +1260,8 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
>   		}
>   	}
>   
> +	idx = 0;
> +
>   	do {
>   		if (msgs[idx].len == 0) {
>   			ret = -EINVAL;
> @@ -1407,27 +1401,21 @@ static int qup_i2c_probe(struct platform_device *pdev)
>   
>   		/* 2 tag bytes for each block + 5 for start, stop tags */
>   		size = blocks * 2 + 5;
> -		qup->dpool = dma_pool_create("qup_i2c-dma-pool", &pdev->dev,
> -					     size, 4, 0);
>   
> -		qup->start_tag.start = dma_pool_alloc(qup->dpool, GFP_KERNEL,
> -						      &qup->start_tag.addr);
> +		qup->start_tag.start = devm_kzalloc(&pdev->dev,
> +						    size, GFP_KERNEL);
>   		if (!qup->start_tag.start) {
>   			ret = -ENOMEM;
>   			goto fail_dma;
>   		}
>   
> -		qup->brx.tag.start = dma_pool_alloc(qup->dpool,
> -						    GFP_KERNEL,
> -						    &qup->brx.tag.addr);
> +		qup->brx.tag.start = devm_kzalloc(&pdev->dev, 2, GFP_KERNEL);
>   		if (!qup->brx.tag.start) {
>   			ret = -ENOMEM;
>   			goto fail_dma;
>   		}
>   
> -		qup->btx.tag.start = dma_pool_alloc(qup->dpool,
> -						    GFP_KERNEL,
> -						    &qup->btx.tag.addr);
> +		qup->btx.tag.start = devm_kzalloc(&pdev->dev, 2, GFP_KERNEL);
>   		if (!qup->btx.tag.start) {
>   			ret = -ENOMEM;
>   			goto fail_dma;
> @@ -1566,13 +1554,6 @@ static int qup_i2c_remove(struct platform_device *pdev)
>   	struct qup_i2c_dev *qup = platform_get_drvdata(pdev);
>   
>   	if (qup->is_dma) {
> -		dma_pool_free(qup->dpool, qup->start_tag.start,
> -			      qup->start_tag.addr);
> -		dma_pool_free(qup->dpool, qup->brx.tag.start,
> -			      qup->brx.tag.addr);
> -		dma_pool_free(qup->dpool, qup->btx.tag.start,
> -			      qup->btx.tag.addr);
> -		dma_pool_destroy(qup->dpool);
>   		dma_release_channel(qup->btx.dma);
>   		dma_release_channel(qup->brx.dma);
>   	}



From chris.brand at broadcom.com  Fri May  6 10:49:00 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Fri, 6 May 2016 10:49:00 -0700
Subject: [PATCH 6/6] arm: dt: bcm23550: Add device tree files
In-Reply-To: <9191808.kbIrFQuH7z@wuerfel>
References: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
 <1462481334-8943-7-git-send-email-chris.brand@broadcom.com>
 <9191808.kbIrFQuH7z@wuerfel>
Message-ID: <CAMsMSK9usB6+tfrUFwhBW+WUc1rW3eNmWG-SCy5RF7JydsWRZg@mail.gmail.com>

On Thu, May 5, 2016 at 2:05 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> On Thursday 05 May 2016 13:48:54 Chris Brand wrote:
>> +
>> +       chosen {
>> +               bootargs = "console=ttyS0,115200n8";
>> +       };
>> +
>>
>
> Can you move this into the .dts file, and add a stdout-path
> property to make earlycon work?
>
>         Arnd

Will do. Thanks, Arnd.

Chris


From nkaje at codeaurora.org  Fri May  6 10:53:07 2016
From: nkaje at codeaurora.org (Naveen Kaje)
Date: Fri, 6 May 2016 11:53:07 -0600
Subject: [V2,2/2] drivers: i2c: qup: Fix error handling
In-Reply-To: <1462534274-28925-3-git-send-email-sricharan@codeaurora.org>
References: <1462534274-28925-3-git-send-email-sricharan@codeaurora.org>
Message-ID: <b2353f0e-3516-6bce-688a-2eeee2244ec8@codeaurora.org>


On 5/6/2016 5:31 AM, Sricharan R wrote:
> Among the bus errors reported from the QUP_MASTER_STATUS register
> only NACK is considered and transfer gets suspended, while
> other errors are ignored. Correct this and suspend the transfer
> for other errors as well. This avoids unnessecary 'timeouts' which
> happens when waiting for events that would never happen when there
> is already an error condition on the bus.
>
> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> Reviewed-by: Andy Gross <andy.gross at linaro.org>
Hi Sricharan,
Looks good to me. Tested on QDF2432 platform.

Reviewed-by: Naveen Kaje <nkaje at codeaurora.org>
Tested-by: Naveen Kaje <nkaje at codeaurora.org>

> ---
>   drivers/i2c/busses/i2c-qup.c | 42 +++++++++++++++++++++++++++++-------------
>   1 file changed, 29 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
> index 8620e99..af52a47 100644
> --- a/drivers/i2c/busses/i2c-qup.c
> +++ b/drivers/i2c/busses/i2c-qup.c
> @@ -310,6 +310,7 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
>   	u32 opflags;
>   	u32 status;
>   	u32 shift = __ffs(op);
> +	int ret = 0;
>   
>   	len *= qup->one_byte_t;
>   	/* timeout after a wait of twice the max time */
> @@ -321,18 +322,31 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
>   
>   		if (((opflags & op) >> shift) == val) {
>   			if ((op == QUP_OUT_NOT_EMPTY) && qup->is_last) {
> -				if (!(status & I2C_STATUS_BUS_ACTIVE))
> -					return 0;
> +				if (!(status & I2C_STATUS_BUS_ACTIVE)) {
> +					ret = 0;
> +					goto done;
> +				}
>   			} else {
> -				return 0;
> +				ret = 0;
> +				goto done;
>   			}
>   		}
>   
> -		if (time_after(jiffies, timeout))
> -			return -ETIMEDOUT;
> -
> +		if (time_after(jiffies, timeout)) {
> +			ret = -ETIMEDOUT;
> +			goto done;
> +		}
>   		usleep_range(len, len * 2);
>   	}
> +
> +done:
> +	if (qup->bus_err || qup->qup_err) {
> +		if (qup->bus_err & QUP_I2C_NACK_FLAG)
> +			dev_err(qup->dev, "NACK from %x\n", qup->msg->addr);
> +		ret = -EIO;
> +	}
> +
> +	return ret;
>   }
>   
>   static void qup_i2c_set_write_mode_v2(struct qup_i2c_dev *qup,
> @@ -796,7 +810,6 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>   		if (qup->bus_err & QUP_I2C_NACK_FLAG) {
>   			msg--;
>   			dev_err(qup->dev, "NACK from %x\n", msg->addr);
> -			ret = -EIO;
>   
>   			if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
>   				dev_err(qup->dev, "change to run state timed out");
> @@ -818,6 +831,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
>   
>   			qup_i2c_rel_dma(qup);
>   		}
> +		ret = -EIO;
>   	}
>   
>   	dma_unmap_sg(qup->dev, qup->btx.sg, tx_nents, DMA_TO_DEVICE);
> @@ -841,9 +855,6 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
>   	if (ret)
>   		goto out;
>   
> -	qup->bus_err = 0;
> -	qup->qup_err = 0;
> -
>   	writel(0, qup->base + QUP_MX_INPUT_CNT);
>   	writel(0, qup->base + QUP_MX_OUTPUT_CNT);
>   
> @@ -882,10 +893,9 @@ static int qup_i2c_wait_for_complete(struct qup_i2c_dev *qup,
>   	}
>   
>   	if (qup->bus_err || qup->qup_err) {
> -		if (qup->bus_err & QUP_I2C_NACK_FLAG) {
> +		if (qup->bus_err & QUP_I2C_NACK_FLAG)
>   			dev_err(qup->dev, "NACK from %x\n", msg->addr);
> -			ret = -EIO;
> -		}
> +		ret = -EIO;
>   	}
>   
>   	return ret;
> @@ -1178,6 +1188,9 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>   	if (ret < 0)
>   		goto out;
>   
> +	qup->bus_err = 0;
> +	qup->qup_err = 0;
> +
>   	writel(1, qup->base + QUP_SW_RESET);
>   	ret = qup_i2c_poll_state(qup, QUP_RESET_STATE);
>   	if (ret)
> @@ -1227,6 +1240,9 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
>   	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
>   	int ret, len, idx = 0, use_dma = 0;
>   
> +	qup->bus_err = 0;
> +	qup->qup_err = 0;
> +
>   	ret = pm_runtime_get_sync(qup->dev);
>   	if (ret < 0)
>   		goto out;



From dianders at chromium.org  Fri May  6 11:00:02 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 6 May 2016 11:00:02 -0700
Subject: [PATCH v7 8/9] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <572C64B5.6080607@rock-chips.com>
References: <1462371194-5809-1-git-send-email-david.wu@rock-chips.com>
 <1462372609-6535-1-git-send-email-david.wu@rock-chips.com>
 <CAD=FV=VhMJiowNWm+0=jzzK0vajg1=3PutaWbzhGPN_BU2+19w@mail.gmail.com>
 <572C64B5.6080607@rock-chips.com>
Message-ID: <CAD=FV=XOOAbKxqJsxGU4pXbNJtbq_Q4Pj2=9P48NCze5NTJyrw@mail.gmail.com>

Hi

On Fri, May 6, 2016 at 2:32 AM, David.Wu <david.wu at rock-chips.com> wrote:
>> Also (optional): once you do that, there becomes much less of a reason
>> to store "t_calc" in "struct rk3x_i2c".  Already you're never using
>> the "div_low" and "div_high" that you store in the "struct rk3x_i2c".
>> Of course, to do that you've got to change other places not to clobber
>> these bits in REG_CON.
>>
>
> So, I only just need to store tuning value in the "struct rk3x_i2c", but not
> to store the "div_low" and "div_high"?

I was suggesting not adding anything to what's stored in "struct
rk3x_i2c" (AKA don't add t_calc there).  Just set the value directly
in the register here then change all other bits of code to respect it.

That is:

In rk3x_i2c_start(), write:

  u32 val = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK;

In rk3x_i2c_xfer(), write:
  val = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK
  val |= REG_CON_EN | REG_CON_STOP, REG_CON;
  i2c_writel(i2c, val);


You could get fancy and add a new "i2c_update_bits", but that might be overkill.


> The patches we have already used in our projects, they are verified by the
> basic tests. I would ask them to do more tests. Because we didn't change the
> clock rate now, it was a fixed value when clk inited, so we could not find
> the bug here.

OK.  Presumably a rk3066 w/ DVS enabled would be a good test?  Reading
the description of commit 249051f49907 ("i2c: rk3x: handle dynamic
clock rate changes correctly"), I see:

    The i2c input clock can change dynamically, e.g. on the RK3066 where
    pclk_i2c0 and pclk_i2c1 are connected to the armclk, which changes
    rate on cpu frequency scaling.


>> If you take that advice, you can get rid of all of the "if
>> (i2c->pclk)" statements in your code.
>>
>
> It would make i2c->clk to be enabled and prepared twice when uses
> rk3x_i2c_v0_calc_timings for old hardware. But if do the opposite
> disabled and unprepated twice, that is okay.

Right.  The same clock will get an enable / prepare count of "2"
(instead of two different clocks getting a count of "1).  ...but
nothing should be hurt by that.

-Doug


From sboyd at codeaurora.org  Fri May  6 11:02:17 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Fri, 6 May 2016 11:02:17 -0700
Subject: [GIT PULL] i.MX clock fixes for 4.6, take 2
In-Reply-To: <20160503133605.GN5874@tiger>
References: <20160503133605.GN5874@tiger>
Message-ID: <20160506180217.GW3492@codeaurora.org>

On 05/03, Shawn Guo wrote:
> The following changes since commit 7196c52c9377df0175b510ff5896bda524f7345e:
> 
>   clk: imx6q: fix typo in CAN clock definition (2016-04-13 15:27:15 +0800)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-clk-fixes-4.6-2
> 
> for you to fetch changes up to 3397c2c45b1b6f54834dfeae30a73046f33ca943:
> 
>   ARM: dts: imx35: restore existing used clock enumeration (2016-04-18 12:37:21 +0800)
> 
> ----------------------------------------------------------------
> The i.MX clock fixes for 4.6, take 2:
>  - Fix the commit 3713e3f5e927 ("clk: imx35: define two clocks for rtc")
>    which messed up the clock enumeration when adding new clock.

This commit wasn't introduced in this merge window, so I'm going
to pull this into clk-next unless you have some justification.

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


From sboyd at codeaurora.org  Fri May  6 11:04:03 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Fri, 6 May 2016 11:04:03 -0700
Subject: [GIT PULL] i.MX clock updates for 4.7, take 2
In-Reply-To: <20160503134356.GO5874@tiger>
References: <20160503134356.GO5874@tiger>
Message-ID: <20160506180403.GX3492@codeaurora.org>

On 05/03, Shawn Guo wrote:
> The following changes since commit 69c542e8022ca53c5fee664548163809eb1777c3:
> 
>   clk: imx: vf610: fix whitespace in vf610-clock.h (2016-04-12 09:31:08 +0800)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-clk-4.7-2
> 
> for you to fetch changes up to 92a847e3609a8d00bcbe8bdfacbcbbca03135410:
> 
>   clk: imx7d: fix ahb clock mux 1 (2016-05-03 20:35:38 +0800)
> 
> ----------------------------------------------------------------
> The i.MX clock updates for 4.7, take 2:
>  - Update clk-pllv3 driver to get it return correct frequency for
>    Ethernet PLL on i.MX7D.
>  - Correct ahb clock mux settings for i.MX7D per latest hardware
>    document.
> 

Thanks. Pulled into clk-next.

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


From garlic.tseng at mediatek.com  Fri May  6 11:33:56 2016
From: garlic.tseng at mediatek.com (Garlic Tseng)
Date: Sat, 7 May 2016 02:33:56 +0800
Subject: [alsa-devel] [PATCH 1/7] ASoC: mediatek: Refine mt8173 driver
 and change config option
In-Reply-To: <20160506122046.GR6292@sirena.org.uk>
References: <1461934848-60011-1-git-send-email-garlic.tseng@mediatek.com>
 <1461934848-60011-2-git-send-email-garlic.tseng@mediatek.com>
 <20160504164306.GA6292@sirena.org.uk>
 <1462416342.25179.36.camel@mtksdaap41> <572B0511.80701@gmail.com>
 <1462444772.2873.70.camel@mtksdaap41> <20160506122046.GR6292@sirena.org.uk>
Message-ID: <1462559636.11805.6.camel@mtksdaap41>

On Fri, 2016-05-06 at 13:20 +0100, Mark Brown wrote:
> On Thu, May 05, 2016 at 06:39:32PM +0800, Garlic Tseng wrote:
> 
> > As mentioned above, the difference of the ASoCs between the two chips
> > are too large that we have a hard time sharing the driver code.
> 
> The things you're describing all sound like scaling differences rather
> than fundamental changes.  I'd expect to see at least some shared code
> here, we don't want to be just duplicating the entire driver every time
> there's a new hardware revision.

Oh ok, I'll do it in the next version. Thanks for comment.



From okaya at codeaurora.org  Fri May  6 11:35:45 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Fri, 6 May 2016 14:35:45 -0400
Subject: [PATCH V4 0/2] vfio, platform: add ACPI support
In-Reply-To: <57290E25.7010501@codeaurora.org>
References: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>
 <3322250.xDEDujoeAM@wuerfel> <57290E25.7010501@codeaurora.org>
Message-ID: <572CE401.4080102@codeaurora.org>

On 5/3/2016 4:46 PM, Sinan Kaya wrote:
> On 5/3/2016 4:12 PM, Arnd Bergmann wrote:
>> On Sunday 01 May 2016 17:07:50 Sinan Kaya wrote:
>>> The patchset makes three different changes.
>>> 1. Add support for probing ACPI platform devices.
>>> 2. Add support for ACPI _RST method support during reset
>>> 3. Make reset driver a requirement by default with an optional
>>>    kernel command line override
>>
>> Looks nice, thanks for rewriting this!
>>
>> For future submissions, it would help to have a list of changes
>> compared to the previous versions a the patch set in the cover
>> letter to help reviewers, but this time my memory was still fresh
>> enough.
>>
>> 	Arnd
>>
> 
> Sure, will do. I asked Rafael to review the ACPI code. 
> 
> +		ret = vfio_platform_call_reset(vdev);
> 
> This is the only problem I'm seeing in the code. I tested the ACPI path only. 
> I'm wondering if Eric could test the device tree version.
> 
> +		if (ret)
> +			goto err_irq;
>  
> I'll get rid of this line on the first patch and move it to second
> patch along with reset_required check.
> 

Before I post my next patch, I wanted to see if there is any other 
feedback. Rafael mentioned to me that this code should go through
his branch as it is ACPI specific.

Are we OK with this? Alex?

I'm hoping that Eric Auger will be able to test DT in parallel.
I haven't heart from him though.

-- 
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


From bjorn.andersson at linaro.org  Fri May  6 11:44:06 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Fri, 6 May 2016 11:44:06 -0700
Subject: [PATCH 1/5] remoteproc: core: Task sync during rproc_fw_boot()
In-Reply-To: <1462454983-13168-2-git-send-email-lee.jones@linaro.org>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
 <1462454983-13168-2-git-send-email-lee.jones@linaro.org>
Message-ID: <20160506184406.GD1256@tuxbot>

On Thu 05 May 06:29 PDT 2016, Lee Jones wrote:

> By default, rproc_fw_boot() needs to wait for rproc to be configured,
> but a race may occur when using rpmsg/virtio.  In this case, it can
> be called locally in a safe manor.
> 
> This patch represents two usecases:
> 
>  - External call (via exported rproc_boot()), which waits
>  - Internal call can use 'nowait' version of rproc_boot()
> 
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier at st.com>
> Signed-off-by: Lee Jones <lee.jones at linaro.org>

Looks good

Applied to rproc-next.

Regards,
Bjorn


From bjorn.andersson at linaro.org  Fri May  6 11:48:42 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Fri, 6 May 2016 11:48:42 -0700
Subject: [PATCH 2/5] remoteproc: core: Add rproc OF look-up functions
In-Reply-To: <1462454983-13168-3-git-send-email-lee.jones@linaro.org>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
 <1462454983-13168-3-git-send-email-lee.jones@linaro.org>
Message-ID: <20160506184842.GE1256@tuxbot>

On Thu 05 May 06:29 PDT 2016, Lee Jones wrote:

> - of_rproc_byindex(): look-up and obtain a reference to a rproc
>   		      using the DT phandle "rprocs" and a index.
> 
> - of_rproc_byname():  lookup and obtain a reference to a rproc
>   		      using the DT phandle "rprocs" and "rproc-names".
> 
> Signed-off-by: Ludovic Barre <ludovic.barre at st.com>
> Signed-off-by: Lee Jones <lee.jones at linaro.org>
> ---

I like the idea of having these helpers, but we already have
rproc_get_by_phandle() so these helpers should be built upon that rather
than adding the additional list.

Regards,
Bjorn


From bjorn.andersson at linaro.org  Fri May  6 11:59:14 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Fri, 6 May 2016 11:59:14 -0700
Subject: [PATCH 3/5] remoteproc: core: Add ability to select a firmware
 from the client
In-Reply-To: <1462454983-13168-4-git-send-email-lee.jones@linaro.org>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
 <1462454983-13168-4-git-send-email-lee.jones@linaro.org>
Message-ID: <20160506185914.GF1256@tuxbot>

On Thu 05 May 06:29 PDT 2016, Lee Jones wrote:

> ST Co-Processors can be loaded with different firmwares to execute
> specific tasks without the need for unloading the rproc module.
> 

I'm very much interested in ideas related to this and who "owns" the
life cycle of remoteprocs, do you have any code I can take a look at
that's using this interface?

> This patch provides a function which can update the firmware name.
> 
> NB: This can only happen if the rproc is offline.
> 

How is this working in the case when the remoteproc provides vdevs that
is holding references towards the rproc?

Do you unload rpmsg et al before doing this?

> Signed-off-by: Ludovic Barre <ludovic.barre at st.com>
> Signed-off-by: Lee Jones <lee.jones at linaro.org>
> ---
>  drivers/remoteproc/remoteproc_core.c | 63 ++++++++++++++++++++++++++++++++++++
>  include/linux/remoteproc.h           | 13 ++++++++
>  2 files changed, 76 insertions(+)
> 
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index 85e5fd8..03720c0 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -1004,6 +1004,7 @@ int rproc_trigger_recovery(struct rproc *rproc)
>  
>  	/* Free the copy of the resource table */
>  	kfree(rproc->cached_table);
> +	rproc->cached_table = NULL;
>  

Somewhat unrelated, but should be fixed, so let's go with it.

>  	return rproc_add_virtio_devices(rproc);
>  }
> @@ -1329,6 +1330,66 @@ struct rproc *rproc_get_by_phandle(phandle phandle)
>  EXPORT_SYMBOL(rproc_get_by_phandle);
>  
>  /**
> + * rproc_set_fw_name() - change rproc fw name
> + * @rproc: rproc handle
> + * @firmware: name of firmware file to load
> + *
> + * set a new firmware name for rproc handle
> + * firmware name can be updated only if the rproc is offline
> + * if firmware name is NULL the fw name is set on default name
> + *
> + * this function can wait, if the old fw config virtio is not yet finish
> + * (fw config request is asynchronous)
> + *
> + * Returns 0 on success and an appropriate error code otherwise.
> + */
> +int rproc_set_fw_name(struct rproc *rproc, const char *firmware)
> +{
> +	struct rproc_vdev *rvdev, *rvtmp;
> +
> +	if (!rproc)
> +		return -EINVAL;
> +
> +	/* if rproc is just being registered, wait */
> +	wait_for_completion(&rproc->firmware_loading_complete);
> +
> +	mutex_lock(&rproc->lock);
> +
> +	if (rproc->state != RPROC_OFFLINE) {
> +		mutex_unlock(&rproc->lock);
> +		return -EBUSY;
> +	}
> +
> +	if (rproc->firmware && rproc->firmware != rproc->orig_firmware)
> +		kfree(rproc->firmware);

kfree(NULL) is fine, so you can drop the first part of the expression.

> +
> +	/* restore original fw name */
> +	if (!firmware) {
> +		rproc->firmware = rproc->orig_firmware;
> +	} else {
> +		rproc->firmware = kstrdup(firmware, GFP_KERNEL);
> +		if (!rproc->firmware)
> +			rproc->firmware = rproc->orig_firmware;

In the unlikely event that kstrdup fails I we should leave
rproc->firmware unchanged and return an error here.

As this is written we will silently (with a blarg in the log if anyone
checks) switch back to the default firmware and boot that.

> +	}
> +
> +	dev_info(&rproc->dev, "%s, fw name updated with:%s\n",
> +		 rproc->name, rproc->firmware);
> +
> +	mutex_unlock(&rproc->lock);
> +
> +	/* clean up remote vdev entries */
> +	list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node)
> +		rproc_remove_virtio_dev(rvdev);
> +
> +	/* Free the copy of the resource table */
> +	kfree(rproc->cached_table);
> +	rproc->cached_table = NULL;
> +
> +	return rproc_add_virtio_devices(rproc);
> +}
> +EXPORT_SYMBOL(rproc_set_fw_name);
[..]
>  
> +struct rproc_subdev {
> +	struct device dev;
> +	struct rproc *rproc;
> +	struct resource *res;
> +};
> +
> +#define to_subdevice(d) container_of(d, struct rproc_subdev, dev)
> +struct rproc_subdev *rproc_subdev_add(struct rproc *rproc,
> +				      struct resource *res);
> +void rproc_subdev_del(struct rproc_subdev *subdev);
> +struct device *rproc_subdev_lookup(struct rproc *rproc, const char *name);
> +int rproc_set_fw_name(struct rproc *rproc, const char *firmware);

These belongs to the next patch.

Regards,
Bjorn


From thomas.hanson at linaro.org  Fri May  6 12:07:21 2016
From: thomas.hanson at linaro.org (Tom Hanson)
Date: Fri, 6 May 2016 13:07:21 -0600
Subject: [PATCH v3 19/55] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <1462531568-9799-20-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-20-git-send-email-andre.przywara@arm.com>
Message-ID: <572CEB69.8040009@linaro.org>

On 05/06/2016 04:45 AM, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
>
> As the GICv3 virtual interface registers differ from their GICv2
> siblings, we need different handlers for processing maintenance
> interrupts and reading/writing to the LRs.
> Implement the respective handler functions and connect them to
> existing code to be called if the host is using a GICv3.
>
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - remove outdated comment about the dist_lock
> - add WARN_ON about LR_STATE not being 0 in maintenance interrupts
>
> Changelog v1 .. v2:
> - inject the IRQ priority into the list register
>
> Changelog v2 .. v3:
> - remove no longer needed irqchip/arm-gic.h inclusion
>
>   include/linux/irqchip/arm-gic-v3.h |   1 +
>   virt/kvm/arm/vgic/vgic-v3.c        | 168 +++++++++++++++++++++++++++++++++++++
>   virt/kvm/arm/vgic/vgic.c           |  25 ++++--
>   virt/kvm/arm/vgic/vgic.h           |  29 +++++++
>   4 files changed, 218 insertions(+), 5 deletions(-)
>   create mode 100644 virt/kvm/arm/vgic/vgic-v3.c
>
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index ec938d1..35e93cf 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -275,6 +275,7 @@
>   #define ICH_LR_ACTIVE_BIT		(1ULL << 63)
>   #define ICH_LR_PHYS_ID_SHIFT		32
>   #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
> +#define ICH_LR_PRIORITY_SHIFT		48
>
>   /* These are for GICv2 emulation only */
>   #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> new file mode 100644
> index 0000000..43d1dd7
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-v3.c

...

> +void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
> +	u32 model = vcpu->kvm->arch.vgic.vgic_model;
> +	int lr;
> +
> +	/* Assumes ap_list_lock held */


If truly required that ap_list_lock already be locked, then the code should enforce it. At least in dev mode. Maybe:
          DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->ap_list_lock));

...

> +/* Requires the irq to be locked already */
> +void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)


Similarly, if required then the code should enforce it.
          DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));

  ...


From stillcompiling at gmail.com  Fri May  6 12:19:11 2016
From: stillcompiling at gmail.com (Joshua Clayton)
Date: Fri, 6 May 2016 12:19:11 -0700
Subject: [PATCH] ARM: dts: imx: Remove unneeded unit-addresses
In-Reply-To: <CAOMZO5BXFL47p=WTPDDRFGq38yktmB1FnbOTWJ37mrWsKkeUSQ@mail.gmail.com>
References: <1462283851-10820-1-git-send-email-fabio.estevam@nxp.com>
 <CAL_JsqKv_7ufFG7DSkxqp9QOEjLEDVofyYMoudtJjqBA78ahcA@mail.gmail.com>
 <CAOMZO5AO15UmNJARS9aL-U=CjYnUq0D9S38NYHC8w2DLwOeR_A@mail.gmail.com>
 <CAOMZO5BXFL47p=WTPDDRFGq38yktmB1FnbOTWJ37mrWsKkeUSQ@mail.gmail.com>
Message-ID: <20160506121911.04a7aa6e@jclayton-pc>

On Tue, 3 May 2016 12:45:07 -0300
Fabio Estevam <festevam at gmail.com> wrote:

> On Tue, May 3, 2016 at 12:42 PM, Fabio Estevam <festevam at gmail.com>
> wrote:
> > On Tue, May 3, 2016 at 12:37 PM, Rob Herring <robh at kernel.org>
> > wrote: 
> >> Presumably these are register offsets which could be useful to have
> >> even if the Linux driver doesn't use them. But either way is fine
> >> with me.  
> >
> > Yes, these are register offsets.
> >
> >                 reg_3p0: regulator-3p0 {
> >                     compatible = "fsl,anatop-regulator";
> >                     regulator-name = "vdd3p0";
> >                     regulator-min-microvolt = <2625000>;
> >                     regulator-max-microvolt = <3400000>;
> >                     anatop-reg-offset = <0x120>;  
> 
> Sorry, pressed the 'send' button too quickly.
> 
> There is a "anatop-reg-offset = <0x120>;" property that is used to
> pass the offset to the anatop regulator driver, so that's why I
> preferred to remove the unneeded unit-address.
> 
> Thanks
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

There are actually 2 registers (on some of them),
anatop-reg-offset, and anatop-delay-reg-offset...
Converting those to use reg and deprecating the anatop specific
items would seem like a Good Thing (tm) to me.

...wandering into less safe territory:
I know reg is usually a memory offset in bytes, but
each of the anatop memory offsets also include a bit-shift
and a bit-width item, which really narrowly defines the 
register bits that pertain to each regulator.

would it be totally inappropriate to use
#address-cells = 2 and
#size-cells =1 
where address cells would contain the byte offset and the bit shift, and
the size cell would contain the bit offset?



From rjw at rjwysocki.net  Fri May  6 12:54:26 2016
From: rjw at rjwysocki.net (Rafael J. Wysocki)
Date: Fri, 06 May 2016 21:54:26 +0200
Subject: [PATCH V4 0/2] vfio, platform: add ACPI support
In-Reply-To: <572CE401.4080102@codeaurora.org>
References: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>
 <57290E25.7010501@codeaurora.org> <572CE401.4080102@codeaurora.org>
Message-ID: <2869312.Xk2efht43x@vostro.rjw.lan>

On Friday, May 06, 2016 02:35:45 PM Sinan Kaya wrote:
> On 5/3/2016 4:46 PM, Sinan Kaya wrote:
> > On 5/3/2016 4:12 PM, Arnd Bergmann wrote:
> >> On Sunday 01 May 2016 17:07:50 Sinan Kaya wrote:
> >>> The patchset makes three different changes.
> >>> 1. Add support for probing ACPI platform devices.
> >>> 2. Add support for ACPI _RST method support during reset
> >>> 3. Make reset driver a requirement by default with an optional
> >>>    kernel command line override
> >>
> >> Looks nice, thanks for rewriting this!
> >>
> >> For future submissions, it would help to have a list of changes
> >> compared to the previous versions a the patch set in the cover
> >> letter to help reviewers, but this time my memory was still fresh
> >> enough.
> >>
> >> 	Arnd
> >>
> > 
> > Sure, will do. I asked Rafael to review the ACPI code. 
> > 
> > +		ret = vfio_platform_call_reset(vdev);
> > 
> > This is the only problem I'm seeing in the code. I tested the ACPI path only. 
> > I'm wondering if Eric could test the device tree version.
> > 
> > +		if (ret)
> > +			goto err_irq;
> >  
> > I'll get rid of this line on the first patch and move it to second
> > patch along with reset_required check.
> > 
> 
> Before I post my next patch, I wanted to see if there is any other 
> feedback. Rafael mentioned to me that this code should go through
> his branch as it is ACPI specific.

It doesn't have to, but it should be posted to linux-acpi at vger.kernel.org at
least for a review in there.

> Are we OK with this? Alex?
> 
> I'm hoping that Eric Auger will be able to test DT in parallel.
> I haven't heart from him though.

Surely heard?

Thanks,
Rafael



From okaya at codeaurora.org  Fri May  6 12:52:21 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Fri, 6 May 2016 15:52:21 -0400
Subject: [PATCH V4 0/2] vfio, platform: add ACPI support
In-Reply-To: <2869312.Xk2efht43x@vostro.rjw.lan>
References: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>
 <57290E25.7010501@codeaurora.org> <572CE401.4080102@codeaurora.org>
 <2869312.Xk2efht43x@vostro.rjw.lan>
Message-ID: <572CF5F5.3000606@codeaurora.org>

On 5/6/2016 3:54 PM, Rafael J. Wysocki wrote:
>> Before I post my next patch, I wanted to see if there is any other 
>> > feedback. Rafael mentioned to me that this code should go through
>> > his branch as it is ACPI specific.
> It doesn't have to, but it should be posted to linux-acpi at vger.kernel.org at
> least for a review in there.
> 

I'll do that on the next post.

-- 
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


From enric.balletbo at collabora.com  Fri May  6 14:02:34 2016
From: enric.balletbo at collabora.com (Enric Balletbo i Serra)
Date: Fri,  6 May 2016 23:02:34 +0200
Subject: [PATCH 2/2] ARM: dts: igep0020: Add SD card write-protect pin.
In-Reply-To: <1462568554-7868-1-git-send-email-enric.balletbo@collabora.com>
References: <1462568554-7868-1-git-send-email-enric.balletbo@collabora.com>
Message-ID: <1462568554-7868-2-git-send-email-enric.balletbo@collabora.com>

A host device that supports write protection should refuse to write to
an SD card that is designated read-only when write-protect is set. This
is an optional feature of the SD specification.

Signed-off-by: Enric Balletbo i Serra <enric.balletbo at collabora.com>
---
 arch/arm/boot/dts/omap3-igep0020-common.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-igep0020-common.dtsi b/arch/arm/boot/dts/omap3-igep0020-common.dtsi
index d6f839c..b697106 100644
--- a/arch/arm/boot/dts/omap3-igep0020-common.dtsi
+++ b/arch/arm/boot/dts/omap3-igep0020-common.dtsi
@@ -194,6 +194,12 @@
 			OMAP3630_CORE2_IOPAD(0x25f8, PIN_OUTPUT | MUX_MODE4) /* etk_d14.gpio_28 */
 		>;
 	};
+
+	mmc1_wp_pins: pinmux_mmc1_cd_pins {
+		pinctrl-single,pins = <
+			OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT | MUX_MODE4)   /* etk_d15.gpio_29 */
+		>;
+	};
 };
 
 &i2c3 {
@@ -250,3 +256,8 @@
 		};
 	};
 };
+
+&mmc1 {
+	pinctrl-0 = <&mmc1_pins &mmc1_wp_pins>;
+	wp-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;	/* gpio_29 */
+};
-- 
2.1.0



From enric.balletbo at collabora.com  Fri May  6 14:02:33 2016
From: enric.balletbo at collabora.com (Enric Balletbo i Serra)
Date: Fri,  6 May 2016 23:02:33 +0200
Subject: [PATCH 1/2] ARM: dts: igep00x0: Add SD card-detect.
Message-ID: <1462568554-7868-1-git-send-email-enric.balletbo@collabora.com>

Fix SD card remove/insert detection by adding the correct card-detect
pin. All IGEP OMAP3 based boards use the same card-detect pin.

Signed-off-by: Enric Balletbo i Serra <enric.balletbo at collabora.com>
Signed-off-by: Ladislav Michl <ladis at linux-mips.org>
---
 arch/arm/boot/dts/omap3-igep.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/omap3-igep.dtsi b/arch/arm/boot/dts/omap3-igep.dtsi
index 41f5d38..f4f2ce4 100644
--- a/arch/arm/boot/dts/omap3-igep.dtsi
+++ b/arch/arm/boot/dts/omap3-igep.dtsi
@@ -188,6 +188,7 @@
 	vmmc-supply = <&vmmc1>;
 	vmmc_aux-supply = <&vsim>;
 	bus-width = <4>;
+	cd-gpios = <&twl_gpio 0 GPIO_ACTIVE_LOW>;
 };
 
 &mmc3 {
-- 
2.1.0



From javier at dowhile0.org  Fri May  6 14:07:21 2016
From: javier at dowhile0.org (Javier Martinez Canillas)
Date: Fri, 6 May 2016 17:07:21 -0400
Subject: [PATCH 1/2] ARM: dts: igep00x0: Add SD card-detect.
In-Reply-To: <1462568554-7868-1-git-send-email-enric.balletbo@collabora.com>
References: <1462568554-7868-1-git-send-email-enric.balletbo@collabora.com>
Message-ID: <CABxcv=nZ1hjVGnNG65eKDrxAYFBcavML+GjxXtfTcVO5N83xkA@mail.gmail.com>

Hello Enric,

On Fri, May 6, 2016 at 5:02 PM, Enric Balletbo i Serra
<enric.balletbo at collabora.com> wrote:
> Fix SD card remove/insert detection by adding the correct card-detect
> pin. All IGEP OMAP3 based boards use the same card-detect pin.
>
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo at collabora.com>
> Signed-off-by: Ladislav Michl <ladis at linux-mips.org>

Shouldn't his be Suggested-by: Ladislav Michl <ladis at linux-mips.org> instead?

Or if the patch was originally from Ladis, then he should remain the
author with your S-o-B after his.

Patch looks good to me though.

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
Javier


From javier at dowhile0.org  Fri May  6 14:07:55 2016
From: javier at dowhile0.org (Javier Martinez Canillas)
Date: Fri, 6 May 2016 17:07:55 -0400
Subject: [PATCH 2/2] ARM: dts: igep0020: Add SD card write-protect pin.
In-Reply-To: <1462568554-7868-2-git-send-email-enric.balletbo@collabora.com>
References: <1462568554-7868-1-git-send-email-enric.balletbo@collabora.com>
 <1462568554-7868-2-git-send-email-enric.balletbo@collabora.com>
Message-ID: <CABxcv==70_0smsRshOP+T4GSNMV1V5aUw9S9FcNcHEgr9Vnymw@mail.gmail.com>

Hello Enric,

On Fri, May 6, 2016 at 5:02 PM, Enric Balletbo i Serra
<enric.balletbo at collabora.com> wrote:
> A host device that supports write protection should refuse to write to
> an SD card that is designated read-only when write-protect is set. This
> is an optional feature of the SD specification.
>
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo at collabora.com>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
Javier


From enric.balletbo at collabora.com  Fri May  6 14:22:24 2016
From: enric.balletbo at collabora.com (Enric Balletbo i Serra)
Date: Fri, 06 May 2016 23:22:24 +0200
Subject: [PATCH 1/2] ARM: dts: igep00x0: Add SD card-detect.
In-Reply-To: <CABxcv=nZ1hjVGnNG65eKDrxAYFBcavML+GjxXtfTcVO5N83xkA@mail.gmail.com>
References: <1462568554-7868-1-git-send-email-enric.balletbo@collabora.com>
 <CABxcv=nZ1hjVGnNG65eKDrxAYFBcavML+GjxXtfTcVO5N83xkA@mail.gmail.com>
Message-ID: <572D0B10.60908@collabora.com>

Hi Javier,

On 06/05/16 23:07, Javier Martinez Canillas wrote:
> Hello Enric,
> 
> On Fri, May 6, 2016 at 5:02 PM, Enric Balletbo i Serra
> <enric.balletbo at collabora.com> wrote:
>> Fix SD card remove/insert detection by adding the correct card-detect
>> pin. All IGEP OMAP3 based boards use the same card-detect pin.
>>
>> Signed-off-by: Enric Balletbo i Serra <enric.balletbo at collabora.com>
>> Signed-off-by: Ladislav Michl <ladis at linux-mips.org>
> 
> Shouldn't his be Suggested-by: Ladislav Michl <ladis at linux-mips.org> instead?
> 
> Or if the patch was originally from Ladis, then he should remain the
> author with your S-o-B after his.
> 

Well Ladis sent the same patch as I had in my local repository for long
time, so to be strict the correct is have two authors and two S-o-B. My bad
is not send the patch before.

> Patch looks good to me though.
> 
> Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
> 
> Best regards,
> Javier
> 


From javier at dowhile0.org  Fri May  6 14:27:17 2016
From: javier at dowhile0.org (Javier Martinez Canillas)
Date: Fri, 6 May 2016 17:27:17 -0400
Subject: [PATCH 1/2] ARM: dts: igep00x0: Add SD card-detect.
In-Reply-To: <572D0B10.60908@collabora.com>
References: <1462568554-7868-1-git-send-email-enric.balletbo@collabora.com>
 <CABxcv=nZ1hjVGnNG65eKDrxAYFBcavML+GjxXtfTcVO5N83xkA@mail.gmail.com>
 <572D0B10.60908@collabora.com>
Message-ID: <CABxcv=nqdETAJBpO-akYipuHH6F6vy5wxHX+dOt9=0CKTTkt=Q@mail.gmail.com>

Hello Enric,

On Fri, May 6, 2016 at 5:22 PM, Enric Balletbo i Serra
<enric.balletbo at collabora.com> wrote:
> Hi Javier,
>
> On 06/05/16 23:07, Javier Martinez Canillas wrote:
>> Hello Enric,
>>
>> On Fri, May 6, 2016 at 5:02 PM, Enric Balletbo i Serra
>> <enric.balletbo at collabora.com> wrote:
>>> Fix SD card remove/insert detection by adding the correct card-detect
>>> pin. All IGEP OMAP3 based boards use the same card-detect pin.
>>>
>>> Signed-off-by: Enric Balletbo i Serra <enric.balletbo at collabora.com>
>>> Signed-off-by: Ladislav Michl <ladis at linux-mips.org>
>>
>> Shouldn't his be Suggested-by: Ladislav Michl <ladis at linux-mips.org> instead?
>>
>> Or if the patch was originally from Ladis, then he should remain the
>> author with your S-o-B after his.
>>
>
> Well Ladis sent the same patch as I had in my local repository for long
> time, so to be strict the correct is have two authors and two S-o-B. My bad
> is not send the patch before.
>

Got it, then I think is correct to have both S-o-B. Thanks for the
clarification.

Best regards,
Javier


From javier at osg.samsung.com  Fri May  6 15:11:22 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Fri,  6 May 2016 18:11:22 -0400
Subject: [RESEND PATCH] [media] s5p-mfc: don't close instance after free
 OUTPUT buffers
Message-ID: <1462572682-5195-1-git-send-email-javier@osg.samsung.com>

From: ayaka <ayaka at soulik.info>

User-space applications can use the VIDIOC_REQBUFS ioctl to determine if a
memory mapped, user pointer or DMABUF based I/O is supported by the driver.

So a set of VIDIOC_REQBUFS ioctl calls will be made with count 0 and then
the real VIDIOC_REQBUFS call with count == n. But for count 0, the driver
not only frees the buffer but also closes the MFC instance and s5p_mfc_ctx
state is set to MFCINST_FREE.

The VIDIOC_REQBUFS handler for the output device checks if the s5p_mfc_ctx
state is set to MFCINST_INIT (which happens on an VIDIOC_S_FMT) and fails
otherwise. So after a VIDIOC_REQBUFS(n), future VIDIOC_REQBUFS(n) calls
will fails unless a VIDIOC_S_FMT ioctl calls happens before the reqbufs.

But applications may first set the format and then attempt to determine
the I/O methods supported by the driver (for example Gstramer does it) so
the state won't be set to MFCINST_INIT again and VIDIOC_REQBUFS will fail.

To avoid this issue, only free the buffers on VIDIOC_REQBUFS(0) but don't
close the MFC instance to allow future VIDIOC_REQBUFS(n) calls to succeed.

Signed-off-by: ayaka <ayaka at soulik.info>
[javier: Rewrote changelog to explain the problem more detailed]
Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

---
Hello,

This is a resend of a patch posted by Ayaka some time ago [0].
Without $SUBJECT, trying to decode a video using Gstramer fails
on an Exynos5422 Odroid XU4 board with following error message:

$ gst-launch-1.0 filesrc location=test.mov ! qtdemux ! h264parse ! v4l2video0dec ! videoconvert ! autovideosink

Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
[ 3947.114756] vidioc_reqbufs:576: Only V4L2_MEMORY_MAP is supported
[ 3947.114771] vidioc_reqbufs:576: Only V4L2_MEMORY_MAP is supported
[ 3947.114903] reqbufs_output:484: Reqbufs called in an invalid state
[ 3947.114913] reqbufs_output:510: Failed allocating buffers for OUTPUT queue
ERROR: from element /GstPipeline:pipeline0/v4l2video0dec:v4l2video0dec0: Failed to allocate required memory.
Additional debug info:
gstv4l2videodec.c(575): gst_v4l2_video_dec_handle_frame (): /GstPipeline:pipeline0/v4l2video0dec:v4l2video0dec0:
Buffer pool activation failed
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...

[0]: https://patchwork.linuxtv.org/patch/32794/

Best regards,
Javier

 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index f2d6376ce618..8b9467de2d6a 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -474,7 +474,6 @@ static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
 		ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
 		if (ret)
 			goto out;
-		s5p_mfc_close_mfc_inst(dev, ctx);
 		ctx->src_bufs_cnt = 0;
 		ctx->output_state = QUEUE_FREE;
 	} else if (ctx->output_state == QUEUE_FREE) {
-- 
2.5.5



From sboyd at codeaurora.org  Fri May  6 15:28:01 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Fri, 6 May 2016 15:28:01 -0700
Subject: [PATCH v5 0/5] clk: mvebu: clock drivers for Marvell Armada 7K/8K
In-Reply-To: <1460648013-31320-1-git-send-email-thomas.petazzoni@free-electrons.com>
References: <1460648013-31320-1-git-send-email-thomas.petazzoni@free-electrons.com>
Message-ID: <20160506222801.GD3492@codeaurora.org>

On 04/14, Thomas Petazzoni wrote:
> Hello,
> 
> Here is the fifth version of the clock drivers for Armada 7K/8K. The
> first two patches have already been applied by Stephen Boyd, but I'm
> still including them for completeness.
> 
> Changes since v4:
> 
>  - Remove the gatable-clock-indices from the CP110 driver, use "none"
>    when a given bit does not provide a clock. Suggested by Rob
>    Herring.
> 
>  - Update the gatable clock tree with the latest technical information
>    received.
> 
>  - Turn the clock drivers into proper platform drivers. Suggested by
>    Stephen Boyd.
> 
>  - Remove useless headers include from the clock drivers. Suggested by
>    Stephen Boyd.
> 
>  - Add proper handling in the clock driver ->probe() function.
> 

Applied the last three with this squashed in to shut up
checkpatch.

---8<---
diff --git a/drivers/clk/mvebu/ap806-system-controller.c b/drivers/clk/mvebu/ap806-system-controller.c
index ac9201c7c730..02023baf86c9 100644
--- a/drivers/clk/mvebu/ap806-system-controller.c
+++ b/drivers/clk/mvebu/ap806-system-controller.c
@@ -23,7 +23,7 @@
 #define AP806_SAR_REG			0x400
 #define AP806_SAR_CLKFREQ_MODE_MASK	0x1f
 
-#define AP806_CLK_NUM 			4
+#define AP806_CLK_NUM			4
 
 static struct clk *ap806_clks[AP806_CLK_NUM];
 
@@ -54,7 +54,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
 	}
 
 	freq_mode = reg & AP806_SAR_CLKFREQ_MODE_MASK;
-	switch(freq_mode) {
+	switch (freq_mode) {
 	case 0x0 ... 0x5:
 		cpuclk_freq = 2000;
 		break;
@@ -100,8 +100,8 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev)
 	/* Fixed clock is always 1200 Mhz */
 	of_property_read_string_index(np, "clock-output-names",
 				      2, &fixedclk_name);
-	ap806_clks[2] = clk_register_fixed_rate(&pdev->dev, fixedclk_name, NULL, 0,
-						1200 * 1000 * 1000);
+	ap806_clks[2] = clk_register_fixed_rate(&pdev->dev, fixedclk_name, NULL,
+						0, 1200 * 1000 * 1000);
 	if (IS_ERR(ap806_clks[2])) {
 		ret = PTR_ERR(ap806_clks[2]);
 		goto fail2;
@@ -147,8 +147,8 @@ static int ap806_syscon_clk_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id ap806_syscon_of_match[] = {
-        { .compatible = "marvell,ap806-system-controller", },
-        {},
+	{ .compatible = "marvell,ap806-system-controller", },
+	{ }
 };
 MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match);
 
diff --git a/drivers/clk/mvebu/cp110-system-controller.c b/drivers/clk/mvebu/cp110-system-controller.c
index f45e7cabd811..f1f41443e466 100644
--- a/drivers/clk/mvebu/cp110-system-controller.c
+++ b/drivers/clk/mvebu/cp110-system-controller.c
@@ -109,6 +109,7 @@ static int cp110_gate_enable(struct clk_hw *hw)
 static void cp110_gate_disable(struct clk_hw *hw)
 {
 	struct cp110_gate_clk *gate = to_cp110_gate_clk(hw);
+
 	regmap_update_bits(gate->regmap, CP110_PM_CLOCK_GATING_REG,
 			   BIT(gate->bit_idx), 0);
 }
@@ -129,7 +130,8 @@ static const struct clk_ops cp110_gate_ops = {
 	.is_enabled = cp110_gate_is_enabled,
 };
 
-static struct clk *cp110_register_gate(const char *name, const char *parent_name,
+static struct clk *cp110_register_gate(const char *name,
+				       const char *parent_name,
 				       struct regmap *regmap, u8 bit_idx)
 {
 	struct cp110_gate_clk *gate;
@@ -205,10 +207,10 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-        /* Register the APLL which is the root of the clk tree */
+	/* Register the APLL which is the root of the clk tree */
 	of_property_read_string_index(np, "core-clock-output-names",
                                       CP110_CORE_APLL, &apll_name);
-        clk = clk_register_fixed_rate(NULL, apll_name, NULL, 0,
+	clk = clk_register_fixed_rate(NULL, apll_name, NULL, 0,
 				      1000 * 1000 * 1000);
 	if (IS_ERR(clk)) {
 		ret = PTR_ERR(clk);
@@ -217,7 +219,7 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 
 	cp110_clks[CP110_CORE_APLL] = clk;
 
-        /* PPv2 is APLL/3 */
+	/* PPv2 is APLL/3 */
 	of_property_read_string_index(np, "core-clock-output-names",
 				      CP110_CORE_PPV2, &ppv2_name);
 	clk = clk_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3);
@@ -228,7 +230,7 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 
 	cp110_clks[CP110_CORE_PPV2] = clk;
 
-        /* EIP clock is APLL/2 */
+	/* EIP clock is APLL/2 */
 	of_property_read_string_index(np, "core-clock-output-names",
 				      CP110_CORE_EIP, &eip_name);
 	clk = clk_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2);
@@ -239,7 +241,7 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 
 	cp110_clks[CP110_CORE_EIP] = clk;
 
-        /* Core clock is EIP/2 */
+	/* Core clock is EIP/2 */
 	of_property_read_string_index(np, "core-clock-output-names",
 				      CP110_CORE_CORE, &core_name);
 	clk = clk_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2);
@@ -270,7 +272,8 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 		const char *parent, *name;
 		int ret;
 
-		ret = of_property_read_string_index(np, "gate-clock-output-names",
+		ret = of_property_read_string_index(np,
+						    "gate-clock-output-names",
 						    i, &name);
 		/* Reached the end of the list? */
 		if (ret < 0)
@@ -279,13 +282,14 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 		if (!strcmp(name, "none"))
 			continue;
 
-		switch(i) {
+		switch (i) {
 		case CP110_GATE_AUDIO:
 		case CP110_GATE_COMM_UNIT:
 		case CP110_GATE_EIP150:
 		case CP110_GATE_EIP197:
 		case CP110_GATE_SLOW_IO:
-			of_property_read_string_index(np, "gate-clock-output-names",
+			of_property_read_string_index(np,
+						      "gate-clock-output-names",
 						      CP110_GATE_MAIN, &parent);
 			break;
 		case CP110_GATE_NAND:
@@ -295,7 +299,8 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 			parent = ppv2_name;
 			break;
 		case CP110_GATE_SDIO:
-			of_property_read_string_index(np, "gate-clock-output-names",
+			of_property_read_string_index(np,
+						      "gate-clock-output-names",
 						      CP110_GATE_SDMMC, &parent);
 			break;
 		case CP110_GATE_XOR1:
@@ -303,14 +308,16 @@ static int cp110_syscon_clk_probe(struct platform_device *pdev)
 		case CP110_GATE_PCIE_X1_0:
 		case CP110_GATE_PCIE_X1_1:
 		case CP110_GATE_PCIE_X4:
-			of_property_read_string_index(np, "gate-clock-output-names",
+			of_property_read_string_index(np,
+						      "gate-clock-output-names",
 						      CP110_GATE_PCIE_XOR, &parent);
 			break;
 		case CP110_GATE_SATA:
 		case CP110_GATE_USB3H0:
 		case CP110_GATE_USB3H1:
 		case CP110_GATE_USB3DEV:
-			of_property_read_string_index(np, "gate-clock-output-names",
+			of_property_read_string_index(np,
+						      "gate-clock-output-names",
 						      CP110_GATE_SATA_USB, &parent);
 			break;
 		default:
@@ -378,8 +385,8 @@ static int cp110_syscon_clk_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id cp110_syscon_of_match[] = {
-        { .compatible = "marvell,cp110-system-controller0", },
-        {},
+	{ .compatible = "marvell,cp110-system-controller0", },
+	{ }
 };
 MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match);
 
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


From sboyd at codeaurora.org  Fri May  6 15:30:02 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Fri, 6 May 2016 15:30:02 -0700
Subject: [PATCH v4 01/11] clk: sunxi: Add display and TCON0 clocks driver
In-Reply-To: <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
References: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
 <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <20160506223002.GE3492@codeaurora.org>

On 04/25, Maxime Ripard wrote:
> The A10 SoCs and its relatives has a special clock controller to drive the
> display engines (both frontend and backend), that have a lot in common with
> the clock to drive the first TCON channel.
> 
> Add a driver to support both.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> Acked-by: Rob Herring <robh at kernel.org>
> ---

Acked-by: Stephen Boyd <sboyd at codeaurora.org>

Unless I can merge this into clk-next? Wasn't clear to me.

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


From akpm at linux-foundation.org  Fri May  6 16:00:41 2016
From: akpm at linux-foundation.org (Andrew Morton)
Date: Fri, 6 May 2016 16:00:41 -0700
Subject: [patch V4] lib: GCD: Use binary GCD algorithm instead of Euclidean
In-Reply-To: <1462527763-15301-1-git-send-email-zengzhaoxiu@163.com>
References: <1462527763-15301-1-git-send-email-zengzhaoxiu@163.com>
Message-ID: <20160506160041.2b5e47757329c288efaed4fb@linux-foundation.org>

On Fri,  6 May 2016 17:42:42 +0800 zengzhaoxiu at 163.com wrote:

> From: Zhaoxiu Zeng <zhaoxiu.zeng at gmail.com>
> 
> The binary GCD algorithm is based on the following facts:
> 	1. If a and b are all evens, then gcd(a,b) = 2 * gcd(a/2, b/2)
> 	2. If a is even and b is odd, then gcd(a,b) = gcd(a/2, b)
> 	3. If a and b are all odds, then gcd(a,b) = gcd((a-b)/2, b) = gcd((a+b)/2, b)
> 
> Even on x86 machines with reasonable division hardware, the binary
> algorithm runs about 25% faster (80% the execution time) than the
> division-based Euclidian algorithm.
> 
> On platforms like Alpha and ARMv6 where division is a function call to
> emulation code, it's even more significant.
> 
> There are two variants of the code here, depending on whether a
> fast __ffs (find least significant set bit) instruction is available.
> This allows the unpredictable branches in the bit-at-a-time shifting
> loop to be eliminated.
> 
> ...
>
> --- a/arch/alpha/Kconfig
> +++ b/arch/alpha/Kconfig
> @@ -27,6 +27,7 @@ config ALPHA
>  	select MODULES_USE_ELF_RELA
>  	select ODD_RT_SIGACTION
>  	select OLD_SIGSUSPEND
> +	select CPU_NO_EFFICIENT_FFS if !ALPHA_EV67
>  	help

argh.  Please don't always put new items at end-of-list.  That's the
perfect way of maximizing the number of patch collisions.  Insert it at
a random position. avoiding the end (if the list isn't alpha-sorted,
which it should be).

<fixes it all up>

>
> ...
>
> --- a/arch/mips/include/asm/cpu-features.h
> +++ b/arch/mips/include/asm/cpu-features.h
> @@ -180,6 +180,16 @@
>  #endif
>  #endif
>  
> +/* __builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r */
> +#if !((defined(cpu_has_mips32r1) && cpu_has_mips32r1) || \
> +	  (defined(cpu_has_mips32r2) && cpu_has_mips32r2) || \
> +	  (defined(cpu_has_mips32r6) && cpu_has_mips32r6) || \
> +	  (defined(cpu_has_mips64r1) && cpu_has_mips64r1) || \
> +	  (defined(cpu_has_mips64r2) && cpu_has_mips64r2) || \
> +	  (defined(cpu_has_mips64r6) && cpu_has_mips64r6))
> +#define CONFIG_CPU_NO_EFFICIENT_FFS 1
> +#endif

#defining a CONFIG_ variable is pretty rude - defining these is the
role of the Kconfig system, not of header files macros.

This was easy:

--- a/arch/mips/include/asm/cpu-features.h~lib-gcd-use-binary-gcd-algorithm-instead-of-euclidean-fix
+++ a/arch/mips/include/asm/cpu-features.h
@@ -187,7 +187,7 @@
 	  (defined(cpu_has_mips64r1) && cpu_has_mips64r1) || \
 	  (defined(cpu_has_mips64r2) && cpu_has_mips64r2) || \
 	  (defined(cpu_has_mips64r6) && cpu_has_mips64r6))
-#define CONFIG_CPU_NO_EFFICIENT_FFS 1
+#define CPU_NO_EFFICIENT_FFS 1
 #endif
 
 #ifndef cpu_has_mips_1
--- a/lib/gcd.c~lib-gcd-use-binary-gcd-algorithm-instead-of-euclidean-fix
+++ a/lib/gcd.c
@@ -10,7 +10,7 @@
  * has decent hardware division.
  */
 
-#if !defined(CONFIG_CPU_NO_EFFICIENT_FFS)
+#if !defined(CONFIG_CPU_NO_EFFICIENT_FFS) && !defined(CPU_NO_EFFICIENT_FFS)
 
 /* If __ffs is available, the even/odd algorithm benchmarks slower. */
 unsigned long gcd(unsigned long a, unsigned long b)
_



From sboyd at codeaurora.org  Fri May  6 16:02:14 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Fri, 6 May 2016 16:02:14 -0700
Subject: [PATCH v7 8/9] clk: mediatek: Add config options for MT2701
 subsystem clocks
In-Reply-To: <1460621514-65191-9-git-send-email-jamesjj.liao@mediatek.com>
References: <1460621514-65191-1-git-send-email-jamesjj.liao@mediatek.com>
 <1460621514-65191-9-git-send-email-jamesjj.liao@mediatek.com>
Message-ID: <20160506230214.GH3492@codeaurora.org>

On 04/14, James Liao wrote:
> MT2701 subsystem clocks are optional and should be enabled only if
> their subsystem drivers are ready to control these clocks.
> 
> Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
> ---

Why is this patch split off from the patch that introduces the
file?

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


From sboyd at codeaurora.org  Fri May  6 16:11:51 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Fri, 6 May 2016 16:11:51 -0700
Subject: [PATCH v7 4/9] clk: mediatek: Add MT2701 clock support
In-Reply-To: <1460621514-65191-5-git-send-email-jamesjj.liao@mediatek.com>
References: <1460621514-65191-1-git-send-email-jamesjj.liao@mediatek.com>
 <1460621514-65191-5-git-send-email-jamesjj.liao@mediatek.com>
Message-ID: <20160506231151.GI3492@codeaurora.org>

On 04/14, James Liao wrote:
> diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
> new file mode 100644
> index 0000000..b4db141
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mt2701.c
> +static void __init mtk_infrasys_init(struct device_node *node)
> +{
> +	struct clk_onecell_data *clk_data;
> +	int r;
> +
> +	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
> +
> +	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
> +						clk_data);
> +	mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
> +						clk_data);
> +
> +	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +	if (r)
> +		pr_err("%s(): could not register clock provider: %d\n",
> +			__func__, r);
> +}
> +CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt2701-infracfg", mtk_infrasys_init);

I'm still lost on the usage of CLK_OF_DECLARE here. What part of
these clk controllers needs to be registered to make the timer
work?

> +	GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2),
> +	GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3),
> +	GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4),
> +	GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5),
> +	GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6),
> +	GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7),
> +	GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8),
> +	GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9),
> +	GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10),
> +	GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11),
> +	GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14),
> +};

I also don't understand why we don't have different files and
drivers for all these different clock controllers? They all have
a similar probe structure, sure, but otherwise these are
different devices with different clks for them. The whole #ifdef
thing in the later patch would go away too.

> +	GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12),
> +	GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13),
> +	GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14),
> +	GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15),
> +	GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_pll340m", 16),
> +};
> +
> +static void __init mtk_bdpsys_init(struct device_node *node)

Shouldn't be __init because it's driver probe path.

> +{
> +	struct clk_onecell_data *clk_data;
> +	int r;
> +
> +	clk_data = mtk_alloc_clk_data(CLK_BDP_NR);
> +
> +	mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
> +						clk_data);
> +
> +	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +	if (r)
> +		pr_err("%s(): could not register clock provider: %d\n",
> +			__func__, r);
> +}
[...]
> +
> +static int __init clk_probe(struct platform_device *pdev)
> +{
> +	void (*clk_init)(struct device_node *);
> +	const struct of_device_id *of_id;
> +
> +	of_id = of_match_node(of_clk_match_tbl, pdev->dev.of_node);
> +	if (!of_id || !of_id->data)
> +		return -EINVAL;
> +
> +	clk_init = of_id->data;
> +	clk_init(pdev->dev.of_node);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver clk_drv = {

Please add some mtk here, 'clk_drv' is too generic.

> +	.driver = {
> +		.name = "mtk-clk",
> +		.owner = THIS_MODULE,

This is unnecessary.

> +		.of_match_table = of_match_ptr(of_clk_match_tbl),

Just drop of_match_ptr() because it's not helping. Also
of_clk_match_tbl is too generic.

> +	},
> +};
> +
> +builtin_platform_driver_probe(clk_drv, clk_probe);
> +}
> diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
> index 32d2e45..8796acc 100644
> --- a/drivers/clk/mediatek/clk-mtk.h
> +++ b/drivers/clk/mediatek/clk-mtk.h
> @@ -145,8 +146,35 @@ struct mtk_gate {
[...]
> +struct mtk_clk_divider {
> +	int id;
> +	const char *name;
> +	const char *parent_name;
> +	unsigned long flags;
> +
> +	uint32_t div_reg;

u32 is shorter

> +	unsigned char div_shift;
> +	unsigned char div_width;
> +	unsigned char clk_divider_flags;
> +	const struct clk_div_table *clk_div_table;
> +};
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


From sboyd at codeaurora.org  Fri May  6 16:12:29 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Fri, 6 May 2016 16:12:29 -0700
Subject: [PATCH v7 7/9] clk: mediatek: Enable critical clocks for MT2701
In-Reply-To: <1460621514-65191-8-git-send-email-jamesjj.liao@mediatek.com>
References: <1460621514-65191-1-git-send-email-jamesjj.liao@mediatek.com>
 <1460621514-65191-8-git-send-email-jamesjj.liao@mediatek.com>
Message-ID: <20160506231229.GJ3492@codeaurora.org>

On 04/14, James Liao wrote:
> Some system clocks should be turned on by default on MT2701.
> This patch enable these clocks when related clocks have
> been registered.
> 
> Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
> ---

critical clks got merged now (sorry I'm slowly getting back to
looking at patches). Please use that flag.

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


From sboyd at codeaurora.org  Fri May  6 16:15:32 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Fri, 6 May 2016 16:15:32 -0700
Subject: [PATCH 05/11] pwm: tegra-dfll: Add driver for Tegra DFLL PWM
 controller
In-Reply-To: <20160422125513.GJ9047@ulmo.ba.sec>
References: <1461321071-6431-1-git-send-email-pchiu@nvidia.com>
 <1461321071-6431-6-git-send-email-pchiu@nvidia.com>
 <20160422125513.GJ9047@ulmo.ba.sec>
Message-ID: <20160506231532.GK3492@codeaurora.org>

On 04/22, Thierry Reding wrote:
> On Fri, Apr 22, 2016 at 06:31:05PM +0800, Penny Chiu wrote:
> > diff --git a/Documentation/devicetree/bindings/pwm/nvidia,tegra-dfll-pwm.txt b/Documentation/devicetree/bindings/pwm/nvidia,tegra-dfll-pwm.txt
> > new file mode 100644
> > index 0000000..bd0d247
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/pwm/nvidia,tegra-dfll-pwm.txt
> > @@ -0,0 +1,48 @@
> > +Tegra SoC DFLL PWM controller
> 
> Stephen, we have in the past used tegra124 in names, even if the IP was
> already included in tegra114, but we never supported it on Tegra114 and
> hence couldn't even verify that the binding was valid. Any preference as
> to the name in this particular case?

You meant Stephen Warren right? I don't care either way.

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


From swarren at wwwdotorg.org  Fri May  6 16:21:11 2016
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Fri, 6 May 2016 17:21:11 -0600
Subject: [PATCH 05/11] pwm: tegra-dfll: Add driver for Tegra DFLL PWM
 controller
In-Reply-To: <20160506231532.GK3492@codeaurora.org>
References: <1461321071-6431-1-git-send-email-pchiu@nvidia.com>
 <1461321071-6431-6-git-send-email-pchiu@nvidia.com>
 <20160422125513.GJ9047@ulmo.ba.sec> <20160506231532.GK3492@codeaurora.org>
Message-ID: <572D26E7.2060406@wwwdotorg.org>

On 05/06/2016 05:15 PM, Stephen Boyd wrote:
> On 04/22, Thierry Reding wrote:
>> On Fri, Apr 22, 2016 at 06:31:05PM +0800, Penny Chiu wrote:
>>> diff --git a/Documentation/devicetree/bindings/pwm/nvidia,tegra-dfll-pwm.txt b/Documentation/devicetree/bindings/pwm/nvidia,tegra-dfll-pwm.txt
>>> new file mode 100644
>>> index 0000000..bd0d247
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/pwm/nvidia,tegra-dfll-pwm.txt
>>> @@ -0,0 +1,48 @@
>>> +Tegra SoC DFLL PWM controller
>>
>> Stephen, we have in the past used tegra124 in names, even if the IP was
>> already included in tegra114, but we never supported it on Tegra114 and
>> hence couldn't even verify that the binding was valid. Any preference as
>> to the name in this particular case?
>
> You meant Stephen Warren right? I don't care either way.

Sorry, I wasn't really paying attention to patches.

Yes, using "124" seems to make sense; we can always expand the binding 
to cover "114" later if there's any demand.


From nicolas.dufresne at collabora.com  Fri May  6 18:25:01 2016
From: nicolas.dufresne at collabora.com (Nicolas Dufresne)
Date: Fri, 06 May 2016 21:25:01 -0400
Subject: [RESEND PATCH] [media] s5p-mfc: don't close instance after free
 OUTPUT buffers
In-Reply-To: <1462572682-5195-1-git-send-email-javier@osg.samsung.com>
References: <1462572682-5195-1-git-send-email-javier@osg.samsung.com>
Message-ID: <1462584301.25248.40.camel@collabora.com>

Thanks for re-submitting. See inline two typos to fix in teh comment.

cheers,
Nicolas

Le vendredi 06 mai 2016 ? 18:11 -0400, Javier Martinez Canillas a ?crit?:
> From: ayaka <ayaka at soulik.info>
> 
> User-space applications can use the VIDIOC_REQBUFS ioctl to determine if a
> memory mapped, user pointer or DMABUF based I/O is supported by the driver.
> 
> So a set of VIDIOC_REQBUFS ioctl calls will be made with count 0 and then
> the real VIDIOC_REQBUFS call with count == n. But for count 0, the driver
> not only frees the buffer but also closes the MFC instance and s5p_mfc_ctx
> state is set to MFCINST_FREE.
> 
> The VIDIOC_REQBUFS handler for the output device checks if the s5p_mfc_ctx
> state is set to MFCINST_INIT (which happens on an VIDIOC_S_FMT) and fails
> otherwise. So after a VIDIOC_REQBUFS(n), future VIDIOC_REQBUFS(n) calls
> will fails unless a VIDIOC_S_FMT ioctl calls happens before the reqbufs.
> 
> But applications may first set the format and then attempt to determine
> the I/O methods supported by the driver (for example Gstramer does it) so
?* GStreamer

> the state won't be set to MFCINST_INIT again and VIDIOC_REQBUFS will fail.
> 
> To avoid this issue, only free the buffers on VIDIOC_REQBUFS(0) but don't
> close the MFC instance to allow future VIDIOC_REQBUFS(n) calls to succeed.
> 
> Signed-off-by: ayaka <ayaka at soulik.info>
> [javier: Rewrote changelog to explain the problem more detailed]
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
> 
> ---
> Hello,
> 
> This is a resend of a patch posted by Ayaka some time ago [0].
> Without $SUBJECT, trying to decode a video using Gstramer fails

* GStreamer again?

> on an Exynos5422 Odroid XU4 board with following error message:
> 
> $ gst-launch-1.0 filesrc location=test.mov ! qtdemux ! h264parse ! v4l2video0dec ! videoconvert ! autovideosink
> 
> Setting pipeline to PAUSED ...
> Pipeline is PREROLLING ...
> [ 3947.114756] vidioc_reqbufs:576: Only V4L2_MEMORY_MAP is supported
> [ 3947.114771] vidioc_reqbufs:576: Only V4L2_MEMORY_MAP is supported
> [ 3947.114903] reqbufs_output:484: Reqbufs called in an invalid state
> [ 3947.114913] reqbufs_output:510: Failed allocating buffers for OUTPUT queue
> ERROR: from element /GstPipeline:pipeline0/v4l2video0dec:v4l2video0dec0: Failed to allocate required memory.
> Additional debug info:
> gstv4l2videodec.c(575): gst_v4l2_video_dec_handle_frame (): /GstPipeline:pipeline0/v4l2video0dec:v4l2video0dec0:
> Buffer pool activation failed
> ERROR: pipeline doesn't want to preroll.
> Setting pipeline to NULL ...
> Freeing pipeline ...
> 
> [0]: https://patchwork.linuxtv.org/patch/32794/
> 
> Best regards,
> Javier
> 
> ?drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 1 -
> ?1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> index f2d6376ce618..8b9467de2d6a 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> @@ -474,7 +474,6 @@ static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
> ?		ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
> ?		if (ret)
> ?			goto out;
> -		s5p_mfc_close_mfc_inst(dev, ctx);
> ?		ctx->src_bufs_cnt = 0;
> ?		ctx->output_state = QUEUE_FREE;
> ?	} else if (ctx->output_state == QUEUE_FREE) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160506/c27b9a43/attachment-0001.sig>

From alim.akhtar at gmail.com  Fri May  6 21:53:52 2016
From: alim.akhtar at gmail.com (Alim Akhtar)
Date: Sat, 7 May 2016 10:23:52 +0530
Subject: [RFC PATCH 05/12] ARM: dts: exynos: Configure Exynos5410 pinctrl
 for eMMC and SD card
In-Reply-To: <1462297949-13824-6-git-send-email-krzk@kernel.org>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
 <1462297949-13824-6-git-send-email-krzk@kernel.org>
Message-ID: <CAGOxZ52sH9vcN0MXxhX1ee7wr9Ao6Na=5X1bXxQo+6uvvWCbJA@mail.gmail.com>

Hi Krzysztof,

On Tue, May 3, 2016 at 11:22 PM, Krzysztof Kozlowski <krzk at kernel.org> wrote:
> Configure the pinctrl for MMC0 (eMMC) and MMC2 (microSD card).
>
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
>
> ---
>
> I am not sure about sd0_rclk. Also I wonder whether this should go to
> board DTS...
> ---
>  arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 87 +++++++++++++++++++++++++++++++
>  1 file changed, 87 insertions(+)
>
> diff --git a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
> index f9aa6bb55464..dc12a79b8b32 100644
> --- a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
> +++ b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
> @@ -277,6 +277,93 @@
>                 interrupt-controller;
>                 #interrupt-cells = <2>;
>         };
> +
> +       sd0_clk: sd0-clk {
> +               samsung,pins = "gpc0-0";
> +               samsung,pin-function = <2>;
> +               samsung,pin-pud = <0>;
> +               samsung,pin-drv = <3>;
> +       };
> +
> +       sd0_cmd: sd0-cmd {
> +               samsung,pins = "gpc0-1";
> +               samsung,pin-function = <2>;
> +               samsung,pin-pud = <0>;
> +               samsung,pin-drv = <3>;
> +       };
> +
> +       sd0_cd: sd0-cd {
> +               samsung,pins = "gpc0-2";
> +               samsung,pin-function = <2>;
> +               samsung,pin-pud = <3>;
> +               samsung,pin-drv = <3>;
> +       };
> +
> +       sd0_bus1: sd0-bus-width1 {
> +               samsung,pins = "gpc0-3";
> +               samsung,pin-function = <2>;
> +               samsung,pin-pud = <3>;
> +               samsung,pin-drv = <3>;
> +       };
> +
> +       sd0_bus4: sd0-bus-width4 {
> +               samsung,pins = "gpc0-4", "gpc0-5", "gpc0-6";
> +               samsung,pin-function = <2>;
> +               samsung,pin-pud = <3>;
> +               samsung,pin-drv = <3>;
> +       };
> +
> +       sd0_bus8: sd0-bus-width8 {
> +               samsung,pins = "gpc3-0", "gpc3-1", "gpc3-2", "gpc3-3";
> +               samsung,pin-function = <2>;
> +               samsung,pin-pud = <3>;
> +               samsung,pin-drv = <3>;
> +       };
> +
> +       /* TODO: What's up with with rclk? On Odroid XU this is missing... */
> +       /*
> +       sd0_rclk: sd0-rclk {
> +               samsung,pins = "gpc0-7";
> +               samsung,pin-function = <2>;
> +               samsung,pin-pud = <1>;
> +               samsung,pin-drv = <3>;
> +       };
> +       */
> +
IF Odroid XU is populated with an eMMC5.0+ device && RCLK (Data
Strobe) is connected from AP to emmc device, THEN you should configure
this dedicated PIN.
Otherwise you can remove this TODO and uncomment the node and put a
comment saying that this feature (emmc5.0+) is not supported on this
SoC.

> +       sd2_clk: sd2-clk {
> +               samsung,pins = "gpc2-0";
> +               samsung,pin-function = <2>;
> +               samsung,pin-pud = <0>;
> +               samsung,pin-drv = <3>;
> +       };
> +
> +       sd2_cmd: sd2-cmd {
> +               samsung,pins = "gpc2-1";
> +               samsung,pin-function = <2>;
> +               samsung,pin-pud = <0>;
> +               samsung,pin-drv = <3>;
> +       };
> +
> +       sd2_cd: sd2-cd {
> +               samsung,pins = "gpc2-2";
> +               samsung,pin-function = <2>;
> +               samsung,pin-pud = <3>;
> +               samsung,pin-drv = <3>;
> +       };
> +
> +       sd2_bus1: sd2-bus-width1 {
> +               samsung,pins = "gpc2-3";
> +               samsung,pin-function = <2>;
> +               samsung,pin-pud = <3>;
> +               samsung,pin-drv = <3>;
> +       };
> +
> +       sd2_bus4: sd2-bus-width4 {
> +               samsung,pins = "gpc2-4", "gpc2-5", "gpc2-6";
> +               samsung,pin-function = <2>;
> +               samsung,pin-pud = <3>;
> +               samsung,pin-drv = <3>;
> +       };
>  };
>
>  &pinctrl_1 {
> --
> 2.5.0
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



-- 
Regards,
Alim


From ayaka at soulik.info  Fri May  6 22:05:23 2016
From: ayaka at soulik.info (ayaka)
Date: Sat,  7 May 2016 13:05:23 +0800
Subject: [RESEND PATCH] [PATCH 0/3] A few patches make s5p-mfc work with
 Gstreamer
Message-ID: <1462597526-31559-1-git-send-email-ayaka@soulik.info>

A user-space application will follow the V4l2 document, but I meet
a problem when I test it with Gstreamer. I look at the V4l2
document, the driver check the external setting which the
document not cover, so that is what the second patch do.

The first patch comes from chromium project, but I didn't
find it is merged, so I sent it again with new kernel API.
But I have not test it with 4.6-rc6, as I meet sysmmu problem
there.

But all those patches have been confirmed at Linux 4.1.16.


ayaka (3):
  [media] s5p-mfc: Add handling of buffer freeing reqbufs request
  [media] s5p-mfc: remove unnecessary check in try_fmt
  [media] s5p-mfc: fix a typo in s5p_mfc_dec

 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c |  2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 12 +++---------
 2 files changed, 4 insertions(+), 10 deletions(-)

-- 
2.5.5



From ayaka at soulik.info  Fri May  6 22:05:24 2016
From: ayaka at soulik.info (ayaka)
Date: Sat,  7 May 2016 13:05:24 +0800
Subject: [PATCH 1/3] [media] s5p-mfc: Add handling of buffer freeing reqbufs
 request
In-Reply-To: <1462597526-31559-1-git-send-email-ayaka@soulik.info>
References: <1462597526-31559-1-git-send-email-ayaka@soulik.info>
Message-ID: <1462597526-31559-2-git-send-email-ayaka@soulik.info>

The encoder forget the work to call hardware to release its buffers.
This patch came from chromium project. I just change its code
style and make the API match with new kernel.

Signed-off-by: ayaka <ayaka at soulik.info>
---
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index 034b5c1..a66a9f9 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -1144,7 +1144,10 @@ static int vidioc_reqbufs(struct file *file, void *priv,
 		return -EINVAL;
 	if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 		if (reqbufs->count == 0) {
+			mfc_debug(2, "Freeing buffers\n");
 			ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+			s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers,
+					ctx);
 			ctx->capture_state = QUEUE_FREE;
 			return ret;
 		}
-- 
2.5.5



From ayaka at soulik.info  Fri May  6 22:05:25 2016
From: ayaka at soulik.info (ayaka)
Date: Sat,  7 May 2016 13:05:25 +0800
Subject: [PATCH 2/3] [media] s5p-mfc: remove unnecessary check in try_fmt
In-Reply-To: <1462597526-31559-1-git-send-email-ayaka@soulik.info>
References: <1462597526-31559-1-git-send-email-ayaka@soulik.info>
Message-ID: <1462597526-31559-3-git-send-email-ayaka@soulik.info>

We don't need to request the sizeimage or num_planes
in try_fmt.

Signed-off-by: ayaka <ayaka at soulik.info>
---
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index a66a9f9..2f76aba 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -1043,10 +1043,6 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
 			mfc_err("failed to try output format\n");
 			return -EINVAL;
 		}
-		if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) {
-			mfc_err("must be set encoding output size\n");
-			return -EINVAL;
-		}
 		if ((dev->variant->version_bit & fmt->versions) == 0) {
 			mfc_err("Unsupported format by this MFC version.\n");
 			return -EINVAL;
@@ -1060,11 +1056,6 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
 			mfc_err("failed to try output format\n");
 			return -EINVAL;
 		}
-
-		if (fmt->num_planes != pix_fmt_mp->num_planes) {
-			mfc_err("failed to try output format\n");
-			return -EINVAL;
-		}
 		if ((dev->variant->version_bit & fmt->versions) == 0) {
 			mfc_err("Unsupported format by this MFC version.\n");
 			return -EINVAL;
-- 
2.5.5



From ayaka at soulik.info  Fri May  6 22:05:26 2016
From: ayaka at soulik.info (ayaka)
Date: Sat,  7 May 2016 13:05:26 +0800
Subject: [PATCH 3/3] [media] s5p-mfc: fix a typo in s5p_mfc_dec
In-Reply-To: <1462597526-31559-1-git-send-email-ayaka@soulik.info>
References: <1462597526-31559-1-git-send-email-ayaka@soulik.info>
Message-ID: <1462597526-31559-4-git-send-email-ayaka@soulik.info>

It is a cosmetic commit.

Signed-off-by: ayaka <ayaka at soulik.info>
---
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index f2d6376..391ed9c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -573,7 +573,7 @@ static int vidioc_reqbufs(struct file *file, void *priv,
 	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
 
 	if (reqbufs->memory != V4L2_MEMORY_MMAP) {
-		mfc_err("Only V4L2_MEMORY_MAP is supported\n");
+		mfc_err("Only V4L2_MEMORY_MMAP is supported\n");
 		return -EINVAL;
 	}
 
-- 
2.5.5



From ayaka at soulik.info  Fri May  6 22:09:01 2016
From: ayaka at soulik.info (ayaka)
Date: Sat, 7 May 2016 13:09:01 +0800
Subject: [RESEND PATCH] [media] s5p-mfc: don't close instance after free
 OUTPUT buffers
In-Reply-To: <1462572682-5195-1-git-send-email-javier@osg.samsung.com>
References: <1462572682-5195-1-git-send-email-javier@osg.samsung.com>
Message-ID: <572D786D.2040105@soulik.info>

Please also notice those patches (A few patches make s5p-mfc work with 
Gstreamer)
  I resent to mail recently.
Without them, the encoder won't work with Gstreamer either. I hope it 
will be
merged as soon as possible.

? 2016?05?07? 06:11, Javier Martinez Canillas ??:
> From: ayaka <ayaka at soulik.info>
>
> User-space applications can use the VIDIOC_REQBUFS ioctl to determine if a
> memory mapped, user pointer or DMABUF based I/O is supported by the driver.
>
> So a set of VIDIOC_REQBUFS ioctl calls will be made with count 0 and then
> the real VIDIOC_REQBUFS call with count == n. But for count 0, the driver
> not only frees the buffer but also closes the MFC instance and s5p_mfc_ctx
> state is set to MFCINST_FREE.
>
> The VIDIOC_REQBUFS handler for the output device checks if the s5p_mfc_ctx
> state is set to MFCINST_INIT (which happens on an VIDIOC_S_FMT) and fails
> otherwise. So after a VIDIOC_REQBUFS(n), future VIDIOC_REQBUFS(n) calls
> will fails unless a VIDIOC_S_FMT ioctl calls happens before the reqbufs.
>
> But applications may first set the format and then attempt to determine
> the I/O methods supported by the driver (for example Gstramer does it) so
> the state won't be set to MFCINST_INIT again and VIDIOC_REQBUFS will fail.
>
> To avoid this issue, only free the buffers on VIDIOC_REQBUFS(0) but don't
> close the MFC instance to allow future VIDIOC_REQBUFS(n) calls to succeed.
>
> Signed-off-by: ayaka <ayaka at soulik.info>
> [javier: Rewrote changelog to explain the problem more detailed]
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>
> ---
> Hello,
>
> This is a resend of a patch posted by Ayaka some time ago [0].
> Without $SUBJECT, trying to decode a video using Gstramer fails
> on an Exynos5422 Odroid XU4 board with following error message:
>
> $ gst-launch-1.0 filesrc location=test.mov ! qtdemux ! h264parse ! v4l2video0dec ! videoconvert ! autovideosink
>
> Setting pipeline to PAUSED ...
> Pipeline is PREROLLING ...
> [ 3947.114756] vidioc_reqbufs:576: Only V4L2_MEMORY_MAP is supported
> [ 3947.114771] vidioc_reqbufs:576: Only V4L2_MEMORY_MAP is supported
> [ 3947.114903] reqbufs_output:484: Reqbufs called in an invalid state
> [ 3947.114913] reqbufs_output:510: Failed allocating buffers for OUTPUT queue
> ERROR: from element /GstPipeline:pipeline0/v4l2video0dec:v4l2video0dec0: Failed to allocate required memory.
> Additional debug info:
> gstv4l2videodec.c(575): gst_v4l2_video_dec_handle_frame (): /GstPipeline:pipeline0/v4l2video0dec:v4l2video0dec0:
> Buffer pool activation failed
> ERROR: pipeline doesn't want to preroll.
> Setting pipeline to NULL ...
> Freeing pipeline ...
>
> [0]: https://patchwork.linuxtv.org/patch/32794/
>
> Best regards,
> Javier
>
>   drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 1 -
>   1 file changed, 1 deletion(-)
>
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> index f2d6376ce618..8b9467de2d6a 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> @@ -474,7 +474,6 @@ static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
>   		ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
>   		if (ret)
>   			goto out;
> -		s5p_mfc_close_mfc_inst(dev, ctx);
>   		ctx->src_bufs_cnt = 0;
>   		ctx->output_state = QUEUE_FREE;
>   	} else if (ctx->output_state == QUEUE_FREE) {



From wens at csie.org  Fri May  6 22:30:14 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Sat, 7 May 2016 13:30:14 +0800
Subject: [PATCH RFC 1/5] net: phy: sun8i-h3-ephy: Add bindings for
 Allwinner H3 Ethernet PHY
In-Reply-To: <CAGb2v662vHfYox2Ff9Mm=sXq4UHg92SQe2ihnKY9Aa4X9yss4Q@mail.gmail.com>
References: <1459786954-12649-1-git-send-email-wens@csie.org>
 <1459786954-12649-2-git-send-email-wens@csie.org> <570BF9B0.2090602@gmail.com>
 <CAGb2v662vHfYox2Ff9Mm=sXq4UHg92SQe2ihnKY9Aa4X9yss4Q@mail.gmail.com>
Message-ID: <CAGb2v65qPMieWU-1CRJYL_zZ3JpUm83+AN477jGdrWYnjjJ66g@mail.gmail.com>

Hi,

On Tue, Apr 12, 2016 at 9:38 AM, Chen-Yu Tsai <wens at csie.org> wrote:
> On Tue, Apr 12, 2016 at 3:23 AM, Florian Fainelli <f.fainelli at gmail.com> wrote:
>> On 04/04/16 09:22, Chen-Yu Tsai wrote:
>>> The Allwinner H3 SoC incorporates an Ethernet PHY. This is enabled and
>>> configured through a memory mapped hardware register.
>>>
>>> This same register also configures the MAC interface mode and TX clock
>>> source. Also covered by the register, but not supported in these bindings,
>>> are TX/RX clock delay chains and inverters, and an RMII module.
>>>
>>> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
>>> ---
>>>  .../bindings/net/allwinner,sun8i-h3-ephy.txt       | 44 ++++++++++++++++++++++
>>>  1 file changed, 44 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun8i-h3-ephy.txt
>>>
>>> diff --git a/Documentation/devicetree/bindings/net/allwinner,sun8i-h3-ephy.txt b/Documentation/devicetree/bindings/net/allwinner,sun8i-h3-ephy.txt
>>> new file mode 100644
>>> index 000000000000..146f227e6d88
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-h3-ephy.txt
>>> @@ -0,0 +1,44 @@
>>> +* Allwinner H3 E(thernet) PHY
>>> +
>>> +The Allwinner H3 integrates an MII ethernet PHY. As with external PHYs,
>>> +before it can be configured over the MDIO bus and used, certain hardware
>>> +features must be configured, such as the PHY address and LED polarity.
>>
>> Is the internal PHY address really configurable? Not that there is
>> anything wrong with it, this is good.
>
> It is. Things that are configured or provided to a discrete PHY are routed
> to registers in the SoC, things such as PHY address, clocks, resets.
>
>>> +The PHY must also be powered on and brought out of reset.
>>> +
>>> +This is accomplished with regulators and pull-up/downs for external PHYs.
>>> +For this internal PHY, a hardware register is programmed.
>>> +
>>> +The same hardware register also contains clock and interface controls
>>> +for the MAC. This is also present in earlier SoCs, and is covered by
>>> +"allwinner,sun7i-a20-gmac-clk". The controls in the H3 are slightly
>>> +different due to the inclusion of what appears to be an RMII-MII
>>> +bridge.
>>> +
>>> +Required properties:
>>> +- compatible: should be "allwinner,sun8i-h3-ephy"
>>> +- reg: address and length of the register set for the device
>>> +- clocks: A phandle to the reference clock for this device
>>> +- resets: A phandle to the reset control for this device
>>> +
>>> +Ethernet PHY related properties:
>>> +- allwinner,ephy-addr: the MDIO bus address the PHY should respond to.
>>> +                    If this is not set, the external PHY is used, and
>>> +                    everything else in this section is ignored.
>>
>> So we are going to put the same value here, and in the actual Ethernet
>> PHY device tree node that should be hanging off the EMAC/MDIO bus
>> controller, this is confusing and error prone.
>
> Yes, that would be an issue when writing the DTS.
>>
>>> +- allwinner,leds-active-low: LEDs are active low. Without this, LEDs are
>>> +                          active high.
>>> +
>>> +Ethernet MAC clock related properties:
>>> +- #clock-cells: should be 0
>>> +- clock-output-names: "mac_tx"
>>> +
>>> +Example:
>>> +
>>> +ethernet-phy at 01c00030 {
>>> +     compatible = "allwinner,sun8i-h3-ephy";
>>> +     reg = <0x01c00030 0x4>;
>>
>> Looking at this register space this looks more like an internal PHY SHIM
>> that is needed to be configured before the internal PHY can be access,
>> not a proper Ethernet PHY per-se, see replies in aptch 2.
>>
>> Should not this block be a second cell associated with the Ethernet MAC
>> block? One or the other are not going to be very useful without
>> knowledge of each other.
>
> True. However the lower half of the same register also controls the
> MAC interface mode and TX clock source and delays. This we had a clock
> driver that was used in conjuction with stmmac on earlier SoCs. I was
> hoping to keep that model with the newer EMAC. At the time it was
> argued that what seemed like a clock should be handled by a clock
> driver, instead of just a "syscon". If this is reaching too far to
> handle this new use case, I will happily just provide patches to merge
> this into the MAC.

Maxime, Hans, any thoughts?

It seems like it'd be easier to just fold this into the EMAC driver.
The register is not part of the clock controller in these new SoCs,
so it's nicer than what we had in A20/A31. It's also not just a clock
control, but a bunch of various controls.

ChenYu

> I would like to know how to deal with things like a PHY requiring
> some sort of shim driver, be it an internal one, or an external mfd
> chip that happens to have an Ethernet PHY included? How do we tie
> this into the PHY node under the MDIO bus?


From thomas.petazzoni at free-electrons.com  Fri May  6 23:22:03 2016
From: thomas.petazzoni at free-electrons.com (Thomas Petazzoni)
Date: Sat, 7 May 2016 08:22:03 +0200
Subject: [PATCH v5 0/5] clk: mvebu: clock drivers for Marvell Armada 7K/8K
In-Reply-To: <20160506222801.GD3492@codeaurora.org>
References: <1460648013-31320-1-git-send-email-thomas.petazzoni@free-electrons.com>
 <20160506222801.GD3492@codeaurora.org>
Message-ID: <20160507082203.147863e5@free-electrons.com>

Hello,

On Fri, 6 May 2016 15:28:01 -0700, Stephen Boyd wrote:

> Applied the last three with this squashed in to shut up
> checkpatch.

Thanks a lot, it all looks good!

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com


From alexandre.belloni at free-electrons.com  Fri May  6 23:48:45 2016
From: alexandre.belloni at free-electrons.com (Alexandre Belloni)
Date: Sat, 7 May 2016 08:48:45 +0200
Subject: [PATCH v6 6/9] rtc: max8997: Check for ERRNO of
 regmap_irq_get_virq()
In-Reply-To: <1462519636-3250-5-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-5-git-send-email-k.kozlowski@samsung.com>
Message-ID: <20160507064845.GD2890@piout.net>

On 06/05/2016 at 09:27:13 +0200, Krzysztof Kozlowski wrote :
> The regmap_irq_get_virq() can return zero or negative ERRNO, so it is
> insufficient to check only for non-zero value.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
Acked-by: Alexandre Belloni <alexandre.belloni at free-electrons.com>

> ---
>  drivers/rtc/rtc-max8997.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
> index 4998aee0f07f..1a06e17ebe9b 100644
> --- a/drivers/rtc/rtc-max8997.c
> +++ b/drivers/rtc/rtc-max8997.c
> @@ -497,7 +497,7 @@ static int max8997_rtc_probe(struct platform_device *pdev)
>  	}
>  
>  	virq = regmap_irq_get_virq(max8997->irq_data, MAX8997_PMICIRQ_RTCA1);
> -	if (!virq) {
> +	if (virq <= 0) {
>  		dev_err(&pdev->dev, "Failed to create mapping alarm IRQ\n");
>  		ret = -ENXIO;
>  		goto err_out;
> -- 
> 1.9.1
> 

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com


From hdegoede at redhat.com  Sat May  7 01:14:10 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 7 May 2016 10:14:10 +0200
Subject: [PATCH RFC 1/5] net: phy: sun8i-h3-ephy: Add bindings for
 Allwinner H3 Ethernet PHY
In-Reply-To: <CAGb2v65qPMieWU-1CRJYL_zZ3JpUm83+AN477jGdrWYnjjJ66g@mail.gmail.com>
References: <1459786954-12649-1-git-send-email-wens@csie.org>
 <1459786954-12649-2-git-send-email-wens@csie.org>
 <570BF9B0.2090602@gmail.com>
 <CAGb2v662vHfYox2Ff9Mm=sXq4UHg92SQe2ihnKY9Aa4X9yss4Q@mail.gmail.com>
 <CAGb2v65qPMieWU-1CRJYL_zZ3JpUm83+AN477jGdrWYnjjJ66g@mail.gmail.com>
Message-ID: <793b5915-1f14-b00f-1c3d-101e800eac3b@redhat.com>

Hi,

On 07-05-16 07:30, Chen-Yu Tsai wrote:
> Hi,
>
> On Tue, Apr 12, 2016 at 9:38 AM, Chen-Yu Tsai <wens at csie.org> wrote:
>> On Tue, Apr 12, 2016 at 3:23 AM, Florian Fainelli <f.fainelli at gmail.com> wrote:
>>> On 04/04/16 09:22, Chen-Yu Tsai wrote:
>>>> The Allwinner H3 SoC incorporates an Ethernet PHY. This is enabled and
>>>> configured through a memory mapped hardware register.
>>>>
>>>> This same register also configures the MAC interface mode and TX clock
>>>> source. Also covered by the register, but not supported in these bindings,
>>>> are TX/RX clock delay chains and inverters, and an RMII module.
>>>>
>>>> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
>>>> ---
>>>>  .../bindings/net/allwinner,sun8i-h3-ephy.txt       | 44 ++++++++++++++++++++++
>>>>  1 file changed, 44 insertions(+)
>>>>  create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun8i-h3-ephy.txt
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/net/allwinner,sun8i-h3-ephy.txt b/Documentation/devicetree/bindings/net/allwinner,sun8i-h3-ephy.txt
>>>> new file mode 100644
>>>> index 000000000000..146f227e6d88
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-h3-ephy.txt
>>>> @@ -0,0 +1,44 @@
>>>> +* Allwinner H3 E(thernet) PHY
>>>> +
>>>> +The Allwinner H3 integrates an MII ethernet PHY. As with external PHYs,
>>>> +before it can be configured over the MDIO bus and used, certain hardware
>>>> +features must be configured, such as the PHY address and LED polarity.
>>>
>>> Is the internal PHY address really configurable? Not that there is
>>> anything wrong with it, this is good.
>>
>> It is. Things that are configured or provided to a discrete PHY are routed
>> to registers in the SoC, things such as PHY address, clocks, resets.
>>
>>>> +The PHY must also be powered on and brought out of reset.
>>>> +
>>>> +This is accomplished with regulators and pull-up/downs for external PHYs.
>>>> +For this internal PHY, a hardware register is programmed.
>>>> +
>>>> +The same hardware register also contains clock and interface controls
>>>> +for the MAC. This is also present in earlier SoCs, and is covered by
>>>> +"allwinner,sun7i-a20-gmac-clk". The controls in the H3 are slightly
>>>> +different due to the inclusion of what appears to be an RMII-MII
>>>> +bridge.
>>>> +
>>>> +Required properties:
>>>> +- compatible: should be "allwinner,sun8i-h3-ephy"
>>>> +- reg: address and length of the register set for the device
>>>> +- clocks: A phandle to the reference clock for this device
>>>> +- resets: A phandle to the reset control for this device
>>>> +
>>>> +Ethernet PHY related properties:
>>>> +- allwinner,ephy-addr: the MDIO bus address the PHY should respond to.
>>>> +                    If this is not set, the external PHY is used, and
>>>> +                    everything else in this section is ignored.
>>>
>>> So we are going to put the same value here, and in the actual Ethernet
>>> PHY device tree node that should be hanging off the EMAC/MDIO bus
>>> controller, this is confusing and error prone.
>>
>> Yes, that would be an issue when writing the DTS.
>>>
>>>> +- allwinner,leds-active-low: LEDs are active low. Without this, LEDs are
>>>> +                          active high.
>>>> +
>>>> +Ethernet MAC clock related properties:
>>>> +- #clock-cells: should be 0
>>>> +- clock-output-names: "mac_tx"
>>>> +
>>>> +Example:
>>>> +
>>>> +ethernet-phy at 01c00030 {
>>>> +     compatible = "allwinner,sun8i-h3-ephy";
>>>> +     reg = <0x01c00030 0x4>;
>>>
>>> Looking at this register space this looks more like an internal PHY SHIM
>>> that is needed to be configured before the internal PHY can be access,
>>> not a proper Ethernet PHY per-se, see replies in aptch 2.
>>>
>>> Should not this block be a second cell associated with the Ethernet MAC
>>> block? One or the other are not going to be very useful without
>>> knowledge of each other.
>>
>> True. However the lower half of the same register also controls the
>> MAC interface mode and TX clock source and delays. This we had a clock
>> driver that was used in conjuction with stmmac on earlier SoCs. I was
>> hoping to keep that model with the newer EMAC. At the time it was
>> argued that what seemed like a clock should be handled by a clock
>> driver, instead of just a "syscon". If this is reaching too far to
>> handle this new use case, I will happily just provide patches to merge
>> this into the MAC.
>
> Maxime, Hans, any thoughts?
>
> It seems like it'd be easier to just fold this into the EMAC driver.
> The register is not part of the clock controller in these new SoCs,
> so it's nicer than what we had in A20/A31. It's also not just a clock
> control, but a bunch of various controls.

I don't know the emac stuff well enough to really have an opinion,
but with that said I've no objections against just folding this into
the driver. If you believe that is best, go for it.

Regards,

Hans


From linux at horizon.com  Sat May  7 01:41:29 2016
From: linux at horizon.com (George Spelvin)
Date: 7 May 2016 04:41:29 -0400
Subject: [patch V4] lib: GCD: Use binary GCD algorithm instead of Euclidean
In-Reply-To: <1462527763-15301-1-git-send-email-zengzhaoxiu@163.com>
Message-ID: <20160507084129.7284.qmail@ns.horizon.com>

Nothing critical, but a bit of kibitzing.
(That is slang in the Yiddish language for a person
who offers annoying and unwanted advice.)

> The binary GCD algorithm is based on the following facts:
> 	1. If a and b are all evens, then gcd(a,b) = 2 * gcd(a/2, b/2)
>	2. If a is even and b is odd, then gcd(a,b) = gcd(a/2, b)
>	3. If a and b are all odds, then gcd(a,b) = gcd((a-b)/2, b) = gcd((a+b)/2, b)

1) "even" and "odd" are adjectives.  In English, adjectives to not have
   plural suffixes.  Thus, "they are even" or "they are odd".
2) Although "all" is not exactly wrong, it sounds odd.  Since there are
   exactly two of them it's clearer to say "both".

If I also rephrase the last line to fit into 80 columns, you get:

  The binary GCD algorithm is based on the following facts:
- 	1. If a and b are all evens, then gcd(a,b) = 2 * gcd(a/2, b/2)
+ 	1. If a and b are both even, then gcd(a,b) = 2 * gcd(a/2, b/2)
 	2. If a is even and b is odd, then gcd(a,b) = gcd(a/2, b)
-	3. If a and b are all odds, then gcd(a,b) = gcd((a-b)/2, b) = gcd((a+b)/2, b)
+	3. If both are odd, then gcd(a,b) = gcd((a-b)/2, b) = gcd((a+b)/2, b)

3) Negative config options are always confusing.

Would it be better to call it CONFIG_INEFFICIEBNT_FFS, or even simpler
CONFIG_SLOW_FFS?

Also, you're allowed to add "help" to a non-interactive config option,
and some documentation might be useful.
E.g.

+config CPU_SLOW_FFS
+	def_bool n
+	help
+	  If n, the CPU supports a fast __ffs (__builtin_ctz) operation,
+	  either directly or via a short code sequence using a count
+	  leading zeros or population count instruction.  If y, the
+	  operation is emulated by slower software, such as an unrolled
+	  binary search.
+
+	  This is purely an optimization option; the kernel
+	  will function correctly regardless of how it is set.
+

Your benchmark code doesn't have to have a separate code path if
__x86_64__; rdtsc works on 32-bit code just as well.  paths.  And the
way you subtract the end and start times is unnecessarily complicated.
The C language guarantees that unsigned arithmetic simply wraps modulo
2^bits as expected.

Here's a simplified version:

	#include <stdio.h>
	#include <stdlib.h>
	#include <stdint.h>
	#include <string.h>
	#include <time.h>
	#include <unistd.h>

	#define swap(a, b) \
		do { \
			a ^= b; \
			b ^= a; \
			a ^= b; \
		} while (0)

	/* The Euclidean GCD algorithm */
	unsigned long gcd0(unsigned long a, unsigned long b)
	{
		if (a < b)
			swap(a, b);

		while (b != 0) {
			unsigned long r = a % b;
			a = b;
			b = r;
		}
		return a;
	}

	/* The binary GCD algorithm, using __builtin_ctzl */
	unsigned long gcd1(unsigned long a, unsigned long b)
	{
		unsigned long r = a | b;

		if (!a || !b)
			return r;

		b >>= __builtin_ctzl(b);

		do {
			a >>= __builtin_ctzl(a);

			if (a < b)
				swap(a, b);
			a -= b;
		} while (a);
		return b << __builtin_ctzl(r);
	}

	/* Binary GCD algorithm, even/odd variant, without __builtin_ctzl */
	unsigned long gcd2(unsigned long a, unsigned long b)
	{
		unsigned long r = a | b;

		if (!a || !b)
			return r;

		r &= -r;

		while (!(b & r))
			b >>= 1;

		for (;;) {
			while (!(a & r))
				a >>= 1;
			if (a < b)
				swap(a, b);
			else if (a == b)
				return a;
			a -= b;
			a >>= 1;
			if (a & r)
				a += b;
			a >>= 1;
		}
	}

	/* A variant of gcd1, with early out for gcd = 1 */
	unsigned long gcd3(unsigned long a, unsigned long b)
	{
		unsigned long r = a | b;

		if (!a || !b)
			return r;

		b >>= __builtin_ctzl(b);
		if (b == 1)
			return r & -r;

		for (;;) {
			a >>= __builtin_ctzl(a);
			if (a == b || a == 1)
				return a << __builtin_ctzl(r);

			if (a < b)
				swap(a, b);
			a -= b;
		}
	}

	unsigned long gcd4(unsigned long a, unsigned long b)
	{
		unsigned long r = a | b;

		if (!a || !b)
			return r;

		r &= -r;

		while (!(b & r))
			b >>= 1;
		if (b == r)
			return r;

		for (;;) {
			while (!(a & r))
				a >>= 1;
			if (a == b || a == r)
				return a;

			if (a < b)
				swap(a, b);
			a -= b;
			a >>= 1;
			if (a & r)
				a += b;
			a >>= 1;
		}
	}

	static unsigned long (*gcd_func[])(unsigned long a, unsigned long b) = {
		gcd0, gcd1, gcd2, gcd3, gcd4,
	};

	#define TEST_ENTRIES (int)(sizeof(gcd_func) / sizeof(gcd_func[0]))

	#define rdtscll(val) do { \
		unsigned __a,__d; \
		__asm__ __volatile__("rdtsc" : "=a" (__a), "=d" (__d)); \
		(val) = __a | (unsigned long long)__d << 32; \
	} while(0)

	static unsigned long long
	benchmark_gcd_func(unsigned long (*gcd)(unsigned long, unsigned long),
			   unsigned long a, unsigned long b, unsigned long *res)
	{
		unsigned long long start, end;
		unsigned long gcd_res;

		rdtscll(start);
		gcd_res = gcd(a, b);
		rdtscll(end);

		*res = gcd_res;
		return end - start;
	}

	static inline unsigned long get_rand()
	{
		if (sizeof(long) == 8)
			return (unsigned long)rand() << 32 | rand();
		else
			return rand();
	}

	int main(int argc, char **argv)
	{
		unsigned int seed = time(0);
		int loops = 100;
		int repeats = 1000;
		unsigned long (*res)[TEST_ENTRIES];
		unsigned long long elapsed[TEST_ENTRIES];
		int i, j, k;

		for (;;) {
			int opt = getopt(argc, argv, "n:r:s:");
			/* End condition always first */
			if (opt == -1)
				break;

			switch (opt) {
			case 'n':
				loops = atoi(optarg);
				break;
			case 'r':
				repeats = atoi(optarg);
				break;
			case 's':
				seed = strtoul(optarg, NULL, 10);
				break;
			default:
				/* You won't actually get here. */
				break;
			}
		}

		res = malloc(sizeof(unsigned long) * TEST_ENTRIES * loops);
		memset(elapsed, 0, sizeof(elapsed));

		srand(seed);
		for (j = 0; j < loops; j++) {
			unsigned long a = get_rand();
			/* Do we have args? */
			unsigned long b = argc > optind ? strtoul(argv[optind], NULL, 10) : get_rand();
			unsigned long long min_elapsed[TEST_ENTRIES];
			for (k = 0; k < repeats; k++) {
				for (i = 0; i < TEST_ENTRIES; i++) {
					unsigned long long tmp = benchmark_gcd_func(gcd_func[i], a, b, &res[j][i]);
					if (k == 0 || min_elapsed[i] > tmp)
						min_elapsed[i] = tmp;
				}
			}
			for (i = 0; i < TEST_ENTRIES; i++)
				elapsed[i] += min_elapsed[i];
		}

		for (i = 0; i < TEST_ENTRIES; i++)
			printf("gcd%d: elapsed %llu\n", i, elapsed[i]);

		k = 0;
		srand(seed);
		for (j = 0; j < loops; j++) {
			unsigned long a = get_rand();
			unsigned long b = argc > optind ? strtoul(argv[optind], NULL, 10) : get_rand();
			for (i = 1; i < TEST_ENTRIES; i++) {
				if (res[j][i] != res[j][0])
					break;
			}
			if (i < TEST_ENTRIES) {
				if (k == 0) {
					k = 1;
					fprintf(stderr, "Error:\n");
				}
				fprintf(stderr, "gcd(%lu, %lu): ", a, b);
				for (i = 0; i < TEST_ENTRIES; i++)
					fprintf(stderr, "%ld%s", res[j][i], i < TEST_ENTRIES - 1 ? ", " : "\n");
			}
		}

		if (k == 0)
			fprintf(stderr, "PASS\n");

		free(res);

		return 0;
	}

Here are some more timings, with the same flags as your tests:

First, 32 bit code:
		gcd0	gcd1	gcd2	gcd3	gcd4
Ivy Bridge	3156	1192	1740	1160	1640	PASS
AMD Phenom	7150	2564	2348	2975	2843	PASS
Core 2		4176	2592	4164	2604	3900	PASS
Pentium 4	11492	4784	7632	4852	6452	PASS

And 64-bit (longer times becuase the inputs are larger):
Ivy Bridge	10636	2496	3500	2432	3360	PASS
AMD Phenom	19482	4058	6030	5001	6845	PASS

Looking at those, I'm not sure how much better the gcd3/4 versions are
than gcd1/2.  The difference seems pretty minor and sometimes negative.


From k.kozlowski at samsung.com  Sat May  7 02:49:14 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Sat, 7 May 2016 11:49:14 +0200
Subject: [RFC PATCH 05/12] ARM: dts: exynos: Configure Exynos5410 pinctrl
 for eMMC and SD card
In-Reply-To: <CAGOxZ52sH9vcN0MXxhX1ee7wr9Ao6Na=5X1bXxQo+6uvvWCbJA@mail.gmail.com>
References: <1462297949-13824-1-git-send-email-krzk@kernel.org>
 <1462297949-13824-6-git-send-email-krzk@kernel.org>
 <CAGOxZ52sH9vcN0MXxhX1ee7wr9Ao6Na=5X1bXxQo+6uvvWCbJA@mail.gmail.com>
Message-ID: <20160507094914.GA3731@kozik-lap>

On Sat, May 07, 2016 at 10:23:52AM +0530, Alim Akhtar wrote:
> Hi Krzysztof,
> 
> On Tue, May 3, 2016 at 11:22 PM, Krzysztof Kozlowski <krzk at kernel.org> wrote:
> > Configure the pinctrl for MMC0 (eMMC) and MMC2 (microSD card).
> >
> > Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> >
> > ---
> >
> > I am not sure about sd0_rclk. Also I wonder whether this should go to
> > board DTS...
> > ---
> >  arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 87 +++++++++++++++++++++++++++++++
> >  1 file changed, 87 insertions(+)
> >
> > diff --git a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
> > index f9aa6bb55464..dc12a79b8b32 100644
> > --- a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
> > +++ b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
> > @@ -277,6 +277,93 @@
> >                 interrupt-controller;
> >                 #interrupt-cells = <2>;
> >         };
> > +
> > +       sd0_clk: sd0-clk {
> > +               samsung,pins = "gpc0-0";
> > +               samsung,pin-function = <2>;
> > +               samsung,pin-pud = <0>;
> > +               samsung,pin-drv = <3>;
> > +       };
> > +
> > +       sd0_cmd: sd0-cmd {
> > +               samsung,pins = "gpc0-1";
> > +               samsung,pin-function = <2>;
> > +               samsung,pin-pud = <0>;
> > +               samsung,pin-drv = <3>;
> > +       };
> > +
> > +       sd0_cd: sd0-cd {
> > +               samsung,pins = "gpc0-2";
> > +               samsung,pin-function = <2>;
> > +               samsung,pin-pud = <3>;
> > +               samsung,pin-drv = <3>;
> > +       };
> > +
> > +       sd0_bus1: sd0-bus-width1 {
> > +               samsung,pins = "gpc0-3";
> > +               samsung,pin-function = <2>;
> > +               samsung,pin-pud = <3>;
> > +               samsung,pin-drv = <3>;
> > +       };
> > +
> > +       sd0_bus4: sd0-bus-width4 {
> > +               samsung,pins = "gpc0-4", "gpc0-5", "gpc0-6";
> > +               samsung,pin-function = <2>;
> > +               samsung,pin-pud = <3>;
> > +               samsung,pin-drv = <3>;
> > +       };
> > +
> > +       sd0_bus8: sd0-bus-width8 {
> > +               samsung,pins = "gpc3-0", "gpc3-1", "gpc3-2", "gpc3-3";
> > +               samsung,pin-function = <2>;
> > +               samsung,pin-pud = <3>;
> > +               samsung,pin-drv = <3>;
> > +       };
> > +
> > +       /* TODO: What's up with with rclk? On Odroid XU this is missing... */
> > +       /*
> > +       sd0_rclk: sd0-rclk {
> > +               samsung,pins = "gpc0-7";
> > +               samsung,pin-function = <2>;
> > +               samsung,pin-pud = <1>;
> > +               samsung,pin-drv = <3>;
> > +       };
> > +       */
> > +
> IF Odroid XU is populated with an eMMC5.0+ device && RCLK (Data
> Strobe) is connected from AP to emmc device, THEN you should configure
> this dedicated PIN.
> Otherwise you can remove this TODO and uncomment the node and put a
> comment saying that this feature (emmc5.0+) is not supported on this
> SoC.

I double checked and:
1. Schematics say this pin is not connected,
2. Hardkernel forum confirms that altough XU could support eMMC5.0 (SoC
   supports it) but it was not tested and the pin (RCLK) should be wired
   by consumer.

With your help it seems solved. I'll remove the TODO and add a comment
about not supported emmc5.


Best regards,
Krzysztof



From schwab at linux-m68k.org  Sat May  7 03:46:11 2016
From: schwab at linux-m68k.org (Andreas Schwab)
Date: Sat, 07 May 2016 12:46:11 +0200
Subject: [patch V4] lib: GCD: Use binary GCD algorithm instead of Euclidean
In-Reply-To: <20160507084129.7284.qmail@ns.horizon.com> (George Spelvin's
 message of "7 May 2016 04:41:29 -0400")
References: <20160507084129.7284.qmail@ns.horizon.com>
Message-ID: <87d1oyrvrg.fsf@linux-m68k.org>

"George Spelvin" <linux at horizon.com> writes:

> Your benchmark code doesn't have to have a separate code path if
> __x86_64__; rdtsc works on 32-bit code just as well.

Take a look at the CC: list.

Andreas.

-- 
Andreas Schwab, schwab at linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."


From k.kozlowski at samsung.com  Sat May  7 04:10:28 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Sat,  7 May 2016 13:10:28 +0200
Subject: [GIT PULL] ARM: dts: exynos: Non-critical fixes for v4.7
Message-ID: <1462619428-13798-1-git-send-email-k.kozlowski@samsung.com>

Hi,

A bunch of fixes for things probably broken for long time (MFC, regulator
debugfs) or for stuff which will be broken in next releases (conversion
of max8997 to regmap).


Best regards,
Krzysztof


The following changes since commit a0a966b83873f33778710a4fc59240244b0734a5:

  ARM: EXYNOS: Properly skip unitialized parent clock in power domain on (2016-04-25 11:35:37 +0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git tags/samsung-fixes-non-critical-4.7

for you to fetch changes up to 330d12764e15f6e3e94ff34cda29db96d2589c24:

  ARM: dts: exynos: Add interrupt line to MAX8997 PMIC on exynos4210-trats (2016-05-06 16:01:32 +0200)

----------------------------------------------------------------
Samsung DTS non-critical fixes for v4.7:
1. Fix s5p-mfc driver probe on Exynos542x Peach boards (need to provide MFC
   memory banks). On these boards this was broken for long time but
   apparently no one enabled this driver till now.
2. Fix creation of debugfs entries for one regulator on Exynos4210
   Trats board.
3. Fix probing of max8997 MFD driver (and its children) because
   of missing interrupt. Actually the current version of the driver probes
   (just without interrupts) but after switching to regmap and regmap-irq,
   the interrupt will be mandatory.

----------------------------------------------------------------
Javier Martinez Canillas (1):
      ARM: dts: exynos: Add MFC memory banks for Peach boards

Marek Szyprowski (2):
      ARM: dts: exynos: Fix regulator name to avoid forbidden character on exynos4210-trats
      ARM: dts: exynos: Add interrupt line to MAX8997 PMIC on exynos4210-trats

 arch/arm/boot/dts/exynos4210-trats.dts     | 4 +++-
 arch/arm/boot/dts/exynos5420-peach-pit.dts | 5 +++++
 arch/arm/boot/dts/exynos5800-peach-pi.dts  | 5 +++++
 3 files changed, 13 insertions(+), 1 deletion(-)


From sam at ravnborg.org  Sat May  7 04:23:56 2016
From: sam at ravnborg.org (Sam Ravnborg)
Date: Sat, 7 May 2016 13:23:56 +0200
Subject: [patch V4] lib: GCD: Use binary GCD algorithm instead of Euclidean
In-Reply-To: <1462527763-15301-1-git-send-email-zengzhaoxiu@163.com>
References: <1462527763-15301-1-git-send-email-zengzhaoxiu@163.com>
Message-ID: <20160507112308.GA2612@ravnborg.org>

> diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
> index 57ffaf2..ca675ed 100644
> --- a/arch/sparc/Kconfig
> +++ b/arch/sparc/Kconfig
> @@ -42,6 +42,7 @@ config SPARC
>  	select ODD_RT_SIGACTION
>  	select OLD_SIGSUSPEND
>  	select ARCH_HAS_SG_CHAIN
> +	select CPU_NO_EFFICIENT_FFS
>  
>  config SPARC32
>  	def_bool !64BIT

sparc64 have an efficient ffs implementation.
We use run-time patching to use the proper version
depending on the actual sparc cpu.

As this is determinded at config time, then let the
sparc cpu that has the efficient ffs benefit from this.

In other words - select CPU_NO_EFFICIENT_FFS only for SPARC32.

	Sam


From ivo.g.dimitrov.75 at gmail.com  Sat May  7 08:21:41 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Sat,  7 May 2016 18:21:41 +0300
Subject: [PATCH 0/7] ir-rx51 driver fixes
Message-ID: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>

ir-rx51 is a driver for Nokia N900 IR transmitter. The current series
fixes the remaining problems in the driver:

 - replace GP timer 9 with PWM framework usage
 - replace pulse width timer dmtimer usage with hrtimer
 - add DT support to the driver
 - add driver to the board DTS

Pathes 2 and 5 are needed so the driver to function correctly, without
those PWM either refuses to set the needed carrier frequency (patch 2)
or there are such a delays in the PWM framework, code that transmission
duration raises to ~5s instead of half a second.

Ivaylo Dimitrov (6):
  pwm: omap-dmtimer: Allow for setting dmtimer clock source
  [media] ir-rx51: use PWM framework instead of OMAP dmtimer
  [media] ir-rx51: add DT support to driver
  ARM: OMAP: dmtimer: Do not call PM runtime functions when not needed.
  [media] ir-rx51: use hrtimer instead of dmtimer
  ARM: dts: n900: enable lirc-rx51 driver

Tony Lindgren (1):
  ir-rx51: Fix build after multiarch changes broke it

 .../devicetree/bindings/media/nokia,lirc-rx51      |  19 ++
 .../devicetree/bindings/pwm/pwm-omap-dmtimer.txt   |   4 +
 arch/arm/boot/dts/omap3-n900.dts                   |  12 ++
 arch/arm/mach-omap2/board-rx51-peripherals.c       |   5 -
 arch/arm/mach-omap2/pdata-quirks.c                 |  10 +-
 arch/arm/plat-omap/dmtimer.c                       |   9 +-
 arch/arm/plat-omap/include/plat/dmtimer.h          |   1 +
 drivers/media/rc/Kconfig                           |   2 +-
 drivers/media/rc/ir-rx51.c                         | 229 +++++++--------------
 drivers/pwm/pwm-omap-dmtimer.c                     |  12 +-
 include/linux/platform_data/media/ir-rx51.h        |   3 -
 11 files changed, 131 insertions(+), 175 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/nokia,lirc-rx51

-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Sat May  7 08:21:44 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Sat,  7 May 2016 18:21:44 +0300
Subject: [PATCH 3/7] [media] ir-rx51: use PWM framework instead of OMAP dmtimer
In-Reply-To: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1462634508-24961-4-git-send-email-ivo.g.dimitrov.75@gmail.com>

Convert driver to use PWM framework instead of calling dmtimer functions
directly for PWM timer. Remove paragraph about writing to the Free Software
Foundation's mailing address while at it.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
---
 arch/arm/mach-omap2/board-rx51-peripherals.c |  1 -
 arch/arm/mach-omap2/pdata-quirks.c           |  1 -
 drivers/media/rc/ir-rx51.c                   | 85 ++++++++++++++--------------
 include/linux/platform_data/media/ir-rx51.h  |  2 -
 4 files changed, 44 insertions(+), 45 deletions(-)

diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 9a70739..e487575 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -1242,7 +1242,6 @@ static struct pwm_omap_dmtimer_pdata __maybe_unused pwm_dmtimer_pdata = {
 #if defined(CONFIG_IR_RX51) || defined(CONFIG_IR_RX51_MODULE)
 static struct lirc_rx51_platform_data rx51_lirc_data = {
 	.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
-	.pwm_timer = 9, /* Use GPT 9 for CIR */
 #if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
 	.dmtimer = &pwm_dmtimer_pdata,
 #endif
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index ea3a7d5..af65781 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -491,7 +491,6 @@ static struct pwm_omap_dmtimer_pdata pwm_dmtimer_pdata = {
 
 static struct lirc_rx51_platform_data __maybe_unused rx51_lirc_data = {
 	.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
-	.pwm_timer = 9, /* Use GPT 9 for CIR */
 #if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
 	.dmtimer = &pwm_dmtimer_pdata,
 #endif
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index da839c3..5096ef3 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -12,13 +12,7 @@
  *  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, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
  */
-
 #include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -26,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
+#include <linux/pwm.h>
 
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
@@ -43,7 +38,7 @@
 #define TIMER_MAX_VALUE 0xffffffff
 
 struct lirc_rx51 {
-	pwm_omap_dmtimer *pwm_timer;
+	struct pwm_device *pwm;
 	pwm_omap_dmtimer *pulse_timer;
 	struct pwm_omap_dmtimer_pdata *dmtimer;
 	struct device	     *dev;
@@ -58,32 +53,28 @@ struct lirc_rx51 {
 	int		wbuf[WBUF_LEN];
 	int		wbuf_index;
 	unsigned long	device_is_open;
-	int		pwm_timer_num;
 };
 
 static void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
 {
-	lirc_rx51->dmtimer->set_pwm(lirc_rx51->pwm_timer, 0, 1,
-				PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+	pwm_enable(lirc_rx51->pwm);
 }
 
 static void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
 {
-	lirc_rx51->dmtimer->set_pwm(lirc_rx51->pwm_timer, 0, 1,
-				    PWM_OMAP_DMTIMER_TRIGGER_NONE);
+	pwm_disable(lirc_rx51->pwm);
 }
 
 static int init_timing_params(struct lirc_rx51 *lirc_rx51)
 {
-	u32 load, match;
-
-	load = -(lirc_rx51->fclk_khz * 1000 / lirc_rx51->freq);
-	match = -(lirc_rx51->duty_cycle * -load / 100);
-	lirc_rx51->dmtimer->set_load(lirc_rx51->pwm_timer, 1, load);
-	lirc_rx51->dmtimer->set_match(lirc_rx51->pwm_timer, 1, match);
-	lirc_rx51->dmtimer->write_counter(lirc_rx51->pwm_timer, TIMER_MAX_VALUE - 2);
-	lirc_rx51->dmtimer->start(lirc_rx51->pwm_timer);
+	struct pwm_device *pwm = lirc_rx51->pwm;
+	int duty, period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, lirc_rx51->freq);
+
+	duty = DIV_ROUND_CLOSEST(lirc_rx51->duty_cycle * period, 100);
 	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
+
+	pwm_config(pwm, duty, period);
+
 	lirc_rx51->dmtimer->start(lirc_rx51->pulse_timer);
 
 	lirc_rx51->match = 0;
@@ -165,7 +156,7 @@ end:
 	/* Stop TX here */
 	lirc_rx51_off(lirc_rx51);
 	lirc_rx51->wbuf_index = -1;
-	lirc_rx51->dmtimer->stop(lirc_rx51->pwm_timer);
+
 	lirc_rx51->dmtimer->stop(lirc_rx51->pulse_timer);
 	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
 	wake_up_interruptible(&lirc_rx51->wqueue);
@@ -176,13 +167,13 @@ end:
 static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 {
 	struct clk *clk_fclk;
-	int retval, pwm_timer = lirc_rx51->pwm_timer_num;
+	int retval;
 
-	lirc_rx51->pwm_timer = lirc_rx51->dmtimer->request_specific(pwm_timer);
-	if (lirc_rx51->pwm_timer == NULL) {
-		dev_err(lirc_rx51->dev, ": Error requesting GPT%d timer\n",
-			pwm_timer);
-		return -EBUSY;
+	lirc_rx51->pwm = pwm_get(lirc_rx51->dev, NULL);
+	if (IS_ERR(lirc_rx51->pwm)) {
+		retval = PTR_ERR(lirc_rx51->pwm);
+		dev_err(lirc_rx51->dev, ": pwm_get failed: %d\n", retval);
+		return retval;
 	}
 
 	lirc_rx51->pulse_timer = lirc_rx51->dmtimer->request();
@@ -192,15 +183,11 @@ static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 		goto err1;
 	}
 
-	lirc_rx51->dmtimer->set_source(lirc_rx51->pwm_timer,
-				       PWM_OMAP_DMTIMER_SRC_SYS_CLK);
 	lirc_rx51->dmtimer->set_source(lirc_rx51->pulse_timer,
 				       PWM_OMAP_DMTIMER_SRC_SYS_CLK);
-
-	lirc_rx51->dmtimer->enable(lirc_rx51->pwm_timer);
 	lirc_rx51->dmtimer->enable(lirc_rx51->pulse_timer);
-
-	lirc_rx51->irq_num = lirc_rx51->dmtimer->get_irq(lirc_rx51->pulse_timer);
+	lirc_rx51->irq_num =
+			lirc_rx51->dmtimer->get_irq(lirc_rx51->pulse_timer);
 	retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler,
 			     IRQF_SHARED, "lirc_pulse_timer", lirc_rx51);
 	if (retval) {
@@ -208,7 +195,7 @@ static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 		goto err2;
 	}
 
-	clk_fclk = lirc_rx51->dmtimer->get_fclk(lirc_rx51->pwm_timer);
+	clk_fclk = lirc_rx51->dmtimer->get_fclk(lirc_rx51->pulse_timer);
 	lirc_rx51->fclk_khz = clk_get_rate(clk_fclk) / 1000;
 
 	return 0;
@@ -216,7 +203,7 @@ static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 err2:
 	lirc_rx51->dmtimer->free(lirc_rx51->pulse_timer);
 err1:
-	lirc_rx51->dmtimer->free(lirc_rx51->pwm_timer);
+	pwm_put(lirc_rx51->pwm);
 
 	return retval;
 }
@@ -226,11 +213,10 @@ static int lirc_rx51_free_port(struct lirc_rx51 *lirc_rx51)
 	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
 	free_irq(lirc_rx51->irq_num, lirc_rx51);
 	lirc_rx51_off(lirc_rx51);
-	lirc_rx51->dmtimer->disable(lirc_rx51->pwm_timer);
 	lirc_rx51->dmtimer->disable(lirc_rx51->pulse_timer);
-	lirc_rx51->dmtimer->free(lirc_rx51->pwm_timer);
 	lirc_rx51->dmtimer->free(lirc_rx51->pulse_timer);
 	lirc_rx51->wbuf_index = -1;
+	pwm_put(lirc_rx51->pwm);
 
 	return 0;
 }
@@ -387,7 +373,6 @@ static int lirc_rx51_release(struct inode *inode, struct file *file)
 }
 
 static struct lirc_rx51 lirc_rx51 = {
-	.freq		= 38000,
 	.duty_cycle	= 50,
 	.wbuf_index	= -1,
 };
@@ -445,14 +430,34 @@ static int lirc_rx51_resume(struct platform_device *dev)
 
 static int lirc_rx51_probe(struct platform_device *dev)
 {
+	struct pwm_device *pwm;
+
 	lirc_rx51_driver.features = LIRC_RX51_DRIVER_FEATURES;
 	lirc_rx51.pdata = dev->dev.platform_data;
+
+	if (!lirc_rx51.pdata) {
+		dev_err(&dev->dev, "Platform Data is missing\n");
+		return -ENXIO;
+	}
+
 	if (!lirc_rx51.pdata->dmtimer) {
 		dev_err(&dev->dev, "no dmtimer?\n");
 		return -ENODEV;
 	}
 
-	lirc_rx51.pwm_timer_num = lirc_rx51.pdata->pwm_timer;
+	pwm = pwm_get(&dev->dev, NULL);
+	if (IS_ERR(pwm)) {
+		int err = PTR_ERR(pwm);
+
+		if (err != -EPROBE_DEFER)
+			dev_err(&dev->dev, "pwm_get failed: %d\n", err);
+		return err;
+	}
+
+	/* Use default, in case userspace does not set the carrier */
+	lirc_rx51.freq = DIV_ROUND_CLOSEST(pwm_get_period(pwm), NSEC_PER_SEC);
+	pwm_put(pwm);
+
 	lirc_rx51.dmtimer = lirc_rx51.pdata->dmtimer;
 	lirc_rx51.dev = &dev->dev;
 	lirc_rx51_driver.dev = &dev->dev;
@@ -464,8 +469,6 @@ static int lirc_rx51_probe(struct platform_device *dev)
 		       lirc_rx51_driver.minor);
 		return lirc_rx51_driver.minor;
 	}
-	dev_info(lirc_rx51.dev, "registration ok, minor: %d, pwm: %d\n",
-		 lirc_rx51_driver.minor, lirc_rx51.pwm_timer_num);
 
 	return 0;
 }
diff --git a/include/linux/platform_data/media/ir-rx51.h b/include/linux/platform_data/media/ir-rx51.h
index 3038120..6acf22d 100644
--- a/include/linux/platform_data/media/ir-rx51.h
+++ b/include/linux/platform_data/media/ir-rx51.h
@@ -2,8 +2,6 @@
 #define _LIRC_RX51_H
 
 struct lirc_rx51_platform_data {
-	int pwm_timer;
-
 	int(*set_max_mpu_wakeup_lat)(struct device *dev, long t);
 	struct pwm_omap_dmtimer_pdata *dmtimer;
 };
-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Sat May  7 08:21:43 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Sat,  7 May 2016 18:21:43 +0300
Subject: [PATCH 2/7] pwm: omap-dmtimer: Allow for setting dmtimer clock source
In-Reply-To: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1462634508-24961-3-git-send-email-ivo.g.dimitrov.75@gmail.com>

OMAP GP timers can have different input clocks that allow different PWM
frequencies. However, there is no other way of setting the clock source but
through clocks or clock-names properties of the timer itself. This limits
PWM functionality to only the frequencies allowed by the particular clock
source. Allowing setting the clock source by PWM rather than by timer
allows different PWMs to have different ranges by not hard-wiring the clock
source to the timer.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
---
 Documentation/devicetree/bindings/pwm/pwm-omap-dmtimer.txt |  4 ++++
 drivers/pwm/pwm-omap-dmtimer.c                             | 12 +++++++-----
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-omap-dmtimer.txt b/Documentation/devicetree/bindings/pwm/pwm-omap-dmtimer.txt
index 5befb53..2e53324 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-omap-dmtimer.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-omap-dmtimer.txt
@@ -9,6 +9,10 @@ Required properties:
 
 Optional properties:
 - ti,prescaler: Should be a value between 0 and 7, see the timers datasheet
+- ti,clock-source: Set dmtimer parent clock, values between 0 and 2:
+  - 0x00 - high-frequency system clock (timer_sys_ck)
+  - 0x01 - 32-kHz always-on clock (timer_32k_ck)
+  - 0x02 - external clock (timer_ext_ck, OMAP2 only)
 
 Example:
 	pwm9: dmtimer-pwm at 9 {
diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
index b7e6ecb..95964c6 100644
--- a/drivers/pwm/pwm-omap-dmtimer.c
+++ b/drivers/pwm/pwm-omap-dmtimer.c
@@ -245,7 +245,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
 	struct pwm_omap_dmtimer_chip *omap;
 	struct pwm_omap_dmtimer_pdata *pdata;
 	pwm_omap_dmtimer *dm_timer;
-	u32 prescaler;
+	u32 v;
 	int status;
 
 	pdata = dev_get_platdata(&pdev->dev);
@@ -306,10 +306,12 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
 	if (pm_runtime_active(&omap->dm_timer_pdev->dev))
 		omap->pdata->stop(omap->dm_timer);
 
-	/* setup dmtimer prescaler */
-	if (!of_property_read_u32(pdev->dev.of_node, "ti,prescaler",
-				&prescaler))
-		omap->pdata->set_prescaler(omap->dm_timer, prescaler);
+	if (!of_property_read_u32(pdev->dev.of_node, "ti,prescaler", &v))
+		omap->pdata->set_prescaler(omap->dm_timer, v);
+
+	/* setup dmtimer clock source */
+	if (!of_property_read_u32(pdev->dev.of_node, "ti,clock-source", &v))
+		omap->pdata->set_source(omap->dm_timer, v);
 
 	omap->chip.dev = &pdev->dev;
 	omap->chip.ops = &pwm_omap_dmtimer_ops;
-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Sat May  7 08:21:42 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Sat,  7 May 2016 18:21:42 +0300
Subject: [PATCH 1/7] ir-rx51: Fix build after multiarch changes broke it
In-Reply-To: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1462634508-24961-2-git-send-email-ivo.g.dimitrov.75@gmail.com>

From: Tony Lindgren <tony at atomide.com>

The ir-rx51 driver for n900 has been disabled since the multiarch
changes as plat include directory no longer is SoC specific.

Let's fix it with minimal changes to pass the dmtimer calls in
pdata. Then the following changes can be done while things can
be tested to be working for each change:

1. Change the non-pwm dmtimer to use just hrtimer if possible

2. Change the pwm dmtimer to use Linux PWM API with the new
   drivers/pwm/pwm-omap-dmtimer.c and remove the direct calls
   to dmtimer functions

3. Parse configuration from device tree and drop the pdata

Note compilation of this depends on the previous patch
"ARM: OMAP2+: Add more functions to pwm pdata for ir-rx51".

Cc: Mauro Carvalho Chehab <mchehab at osg.samsung.com>
Cc: Neil Armstrong <narmstrong at baylibre.com>
Cc: linux-media at vger.kernel.org
Signed-off-by: Tony Lindgren <tony at atomide.com>
---
 drivers/media/rc/Kconfig   |  2 +-
 drivers/media/rc/ir-rx51.c | 99 +++++++++++++++++++++++++---------------------
 2 files changed, 54 insertions(+), 47 deletions(-)

diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index bd4d685..370e16e 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -336,7 +336,7 @@ config IR_TTUSBIR
 
 config IR_RX51
 	tristate "Nokia N900 IR transmitter diode"
-	depends on OMAP_DM_TIMER && ARCH_OMAP2PLUS && LIRC && !ARCH_MULTIPLATFORM
+	depends on OMAP_DM_TIMER && PWM_OMAP_DMTIMER && ARCH_OMAP2PLUS && LIRC
 	---help---
 	   Say Y or M here if you want to enable support for the IR
 	   transmitter diode built in the Nokia N900 (RX51) device.
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 4e1711a..da839c3 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -19,6 +19,7 @@
  *
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/uaccess.h>
@@ -26,11 +27,9 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 
-#include <plat/dmtimer.h>
-#include <plat/clock.h>
-
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
+#include <linux/platform_data/pwm_omap_dmtimer.h>
 #include <linux/platform_data/media/ir-rx51.h>
 
 #define LIRC_RX51_DRIVER_FEATURES (LIRC_CAN_SET_SEND_DUTY_CYCLE |	\
@@ -44,8 +43,9 @@
 #define TIMER_MAX_VALUE 0xffffffff
 
 struct lirc_rx51 {
-	struct omap_dm_timer *pwm_timer;
-	struct omap_dm_timer *pulse_timer;
+	pwm_omap_dmtimer *pwm_timer;
+	pwm_omap_dmtimer *pulse_timer;
+	struct pwm_omap_dmtimer_pdata *dmtimer;
 	struct device	     *dev;
 	struct lirc_rx51_platform_data *pdata;
 	wait_queue_head_t     wqueue;
@@ -63,14 +63,14 @@ struct lirc_rx51 {
 
 static void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
 {
-	omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1,
-			      OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+	lirc_rx51->dmtimer->set_pwm(lirc_rx51->pwm_timer, 0, 1,
+				PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
 }
 
 static void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
 {
-	omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1,
-			      OMAP_TIMER_TRIGGER_NONE);
+	lirc_rx51->dmtimer->set_pwm(lirc_rx51->pwm_timer, 0, 1,
+				    PWM_OMAP_DMTIMER_TRIGGER_NONE);
 }
 
 static int init_timing_params(struct lirc_rx51 *lirc_rx51)
@@ -79,12 +79,12 @@ static int init_timing_params(struct lirc_rx51 *lirc_rx51)
 
 	load = -(lirc_rx51->fclk_khz * 1000 / lirc_rx51->freq);
 	match = -(lirc_rx51->duty_cycle * -load / 100);
-	omap_dm_timer_set_load(lirc_rx51->pwm_timer, 1, load);
-	omap_dm_timer_set_match(lirc_rx51->pwm_timer, 1, match);
-	omap_dm_timer_write_counter(lirc_rx51->pwm_timer, TIMER_MAX_VALUE - 2);
-	omap_dm_timer_start(lirc_rx51->pwm_timer);
-	omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
-	omap_dm_timer_start(lirc_rx51->pulse_timer);
+	lirc_rx51->dmtimer->set_load(lirc_rx51->pwm_timer, 1, load);
+	lirc_rx51->dmtimer->set_match(lirc_rx51->pwm_timer, 1, match);
+	lirc_rx51->dmtimer->write_counter(lirc_rx51->pwm_timer, TIMER_MAX_VALUE - 2);
+	lirc_rx51->dmtimer->start(lirc_rx51->pwm_timer);
+	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
+	lirc_rx51->dmtimer->start(lirc_rx51->pulse_timer);
 
 	lirc_rx51->match = 0;
 
@@ -100,15 +100,15 @@ static int pulse_timer_set_timeout(struct lirc_rx51 *lirc_rx51, int usec)
 	BUG_ON(usec < 0);
 
 	if (lirc_rx51->match == 0)
-		counter = omap_dm_timer_read_counter(lirc_rx51->pulse_timer);
+		counter = lirc_rx51->dmtimer->read_counter(lirc_rx51->pulse_timer);
 	else
 		counter = lirc_rx51->match;
 
 	counter += (u32)(lirc_rx51->fclk_khz * usec / (1000));
-	omap_dm_timer_set_match(lirc_rx51->pulse_timer, 1, counter);
-	omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer,
-				     OMAP_TIMER_INT_MATCH);
-	if (tics_after(omap_dm_timer_read_counter(lirc_rx51->pulse_timer),
+	lirc_rx51->dmtimer->set_match(lirc_rx51->pulse_timer, 1, counter);
+	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer,
+					   PWM_OMAP_DMTIMER_INT_MATCH);
+	if (tics_after(lirc_rx51->dmtimer->read_counter(lirc_rx51->pulse_timer),
 		       counter)) {
 		return 1;
 	}
@@ -120,18 +120,18 @@ static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
 	unsigned int retval;
 	struct lirc_rx51 *lirc_rx51 = ptr;
 
-	retval = omap_dm_timer_read_status(lirc_rx51->pulse_timer);
+	retval = lirc_rx51->dmtimer->read_status(lirc_rx51->pulse_timer);
 	if (!retval)
 		return IRQ_NONE;
 
-	if (retval & ~OMAP_TIMER_INT_MATCH)
+	if (retval & ~PWM_OMAP_DMTIMER_INT_MATCH)
 		dev_err_ratelimited(lirc_rx51->dev,
 				": Unexpected interrupt source: %x\n", retval);
 
-	omap_dm_timer_write_status(lirc_rx51->pulse_timer,
-				OMAP_TIMER_INT_MATCH	|
-				OMAP_TIMER_INT_OVERFLOW	|
-				OMAP_TIMER_INT_CAPTURE);
+	lirc_rx51->dmtimer->write_status(lirc_rx51->pulse_timer,
+					 PWM_OMAP_DMTIMER_INT_MATCH |
+					 PWM_OMAP_DMTIMER_INT_OVERFLOW |
+					 PWM_OMAP_DMTIMER_INT_CAPTURE);
 	if (lirc_rx51->wbuf_index < 0) {
 		dev_err_ratelimited(lirc_rx51->dev,
 				": BUG wbuf_index has value of %i\n",
@@ -165,9 +165,9 @@ end:
 	/* Stop TX here */
 	lirc_rx51_off(lirc_rx51);
 	lirc_rx51->wbuf_index = -1;
-	omap_dm_timer_stop(lirc_rx51->pwm_timer);
-	omap_dm_timer_stop(lirc_rx51->pulse_timer);
-	omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
+	lirc_rx51->dmtimer->stop(lirc_rx51->pwm_timer);
+	lirc_rx51->dmtimer->stop(lirc_rx51->pulse_timer);
+	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
 	wake_up_interruptible(&lirc_rx51->wqueue);
 
 	return IRQ_HANDLED;
@@ -178,28 +178,29 @@ static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 	struct clk *clk_fclk;
 	int retval, pwm_timer = lirc_rx51->pwm_timer_num;
 
-	lirc_rx51->pwm_timer = omap_dm_timer_request_specific(pwm_timer);
+	lirc_rx51->pwm_timer = lirc_rx51->dmtimer->request_specific(pwm_timer);
 	if (lirc_rx51->pwm_timer == NULL) {
 		dev_err(lirc_rx51->dev, ": Error requesting GPT%d timer\n",
 			pwm_timer);
 		return -EBUSY;
 	}
 
-	lirc_rx51->pulse_timer = omap_dm_timer_request();
+	lirc_rx51->pulse_timer = lirc_rx51->dmtimer->request();
 	if (lirc_rx51->pulse_timer == NULL) {
 		dev_err(lirc_rx51->dev, ": Error requesting pulse timer\n");
 		retval = -EBUSY;
 		goto err1;
 	}
 
-	omap_dm_timer_set_source(lirc_rx51->pwm_timer, OMAP_TIMER_SRC_SYS_CLK);
-	omap_dm_timer_set_source(lirc_rx51->pulse_timer,
-				OMAP_TIMER_SRC_SYS_CLK);
+	lirc_rx51->dmtimer->set_source(lirc_rx51->pwm_timer,
+				       PWM_OMAP_DMTIMER_SRC_SYS_CLK);
+	lirc_rx51->dmtimer->set_source(lirc_rx51->pulse_timer,
+				       PWM_OMAP_DMTIMER_SRC_SYS_CLK);
 
-	omap_dm_timer_enable(lirc_rx51->pwm_timer);
-	omap_dm_timer_enable(lirc_rx51->pulse_timer);
+	lirc_rx51->dmtimer->enable(lirc_rx51->pwm_timer);
+	lirc_rx51->dmtimer->enable(lirc_rx51->pulse_timer);
 
-	lirc_rx51->irq_num = omap_dm_timer_get_irq(lirc_rx51->pulse_timer);
+	lirc_rx51->irq_num = lirc_rx51->dmtimer->get_irq(lirc_rx51->pulse_timer);
 	retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler,
 			     IRQF_SHARED, "lirc_pulse_timer", lirc_rx51);
 	if (retval) {
@@ -207,28 +208,28 @@ static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 		goto err2;
 	}
 
-	clk_fclk = omap_dm_timer_get_fclk(lirc_rx51->pwm_timer);
-	lirc_rx51->fclk_khz = clk_fclk->rate / 1000;
+	clk_fclk = lirc_rx51->dmtimer->get_fclk(lirc_rx51->pwm_timer);
+	lirc_rx51->fclk_khz = clk_get_rate(clk_fclk) / 1000;
 
 	return 0;
 
 err2:
-	omap_dm_timer_free(lirc_rx51->pulse_timer);
+	lirc_rx51->dmtimer->free(lirc_rx51->pulse_timer);
 err1:
-	omap_dm_timer_free(lirc_rx51->pwm_timer);
+	lirc_rx51->dmtimer->free(lirc_rx51->pwm_timer);
 
 	return retval;
 }
 
 static int lirc_rx51_free_port(struct lirc_rx51 *lirc_rx51)
 {
-	omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
+	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
 	free_irq(lirc_rx51->irq_num, lirc_rx51);
 	lirc_rx51_off(lirc_rx51);
-	omap_dm_timer_disable(lirc_rx51->pwm_timer);
-	omap_dm_timer_disable(lirc_rx51->pulse_timer);
-	omap_dm_timer_free(lirc_rx51->pwm_timer);
-	omap_dm_timer_free(lirc_rx51->pulse_timer);
+	lirc_rx51->dmtimer->disable(lirc_rx51->pwm_timer);
+	lirc_rx51->dmtimer->disable(lirc_rx51->pulse_timer);
+	lirc_rx51->dmtimer->free(lirc_rx51->pwm_timer);
+	lirc_rx51->dmtimer->free(lirc_rx51->pulse_timer);
 	lirc_rx51->wbuf_index = -1;
 
 	return 0;
@@ -446,7 +447,13 @@ static int lirc_rx51_probe(struct platform_device *dev)
 {
 	lirc_rx51_driver.features = LIRC_RX51_DRIVER_FEATURES;
 	lirc_rx51.pdata = dev->dev.platform_data;
+	if (!lirc_rx51.pdata->dmtimer) {
+		dev_err(&dev->dev, "no dmtimer?\n");
+		return -ENODEV;
+	}
+
 	lirc_rx51.pwm_timer_num = lirc_rx51.pdata->pwm_timer;
+	lirc_rx51.dmtimer = lirc_rx51.pdata->dmtimer;
 	lirc_rx51.dev = &dev->dev;
 	lirc_rx51_driver.dev = &dev->dev;
 	lirc_rx51_driver.minor = lirc_register_driver(&lirc_rx51_driver);
-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Sat May  7 08:21:46 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Sat,  7 May 2016 18:21:46 +0300
Subject: [PATCH 5/7] ARM: OMAP: dmtimer: Do not call PM runtime functions when
 not needed.
In-Reply-To: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1462634508-24961-6-git-send-email-ivo.g.dimitrov.75@gmail.com>

once omap_dm_timer_start() is called, which calls omap_dm_timer_enable()
and thus pm_runtime_get_sync(), it doesn't make sense to call PM runtime
functions again before omap_dm_timer_stop is called(). Otherwise PM runtime
functions called in omap_dm_timer_enable/disable lead to long and unneeded
delays.

Fix that by implementing an "enabled" counter, so the PM runtime functions
get called only when really needed.

Without that patch Nokia N900 IR TX driver (ir-rx51) does not function.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
---
 arch/arm/plat-omap/dmtimer.c              | 9 ++++++++-
 arch/arm/plat-omap/include/plat/dmtimer.h | 1 +
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 7a327bd..f35a78c 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -365,6 +365,9 @@ void omap_dm_timer_enable(struct omap_dm_timer *timer)
 {
 	int c;
 
+	if (timer->enabled++)
+		return;
+
 	pm_runtime_get_sync(&timer->pdev->dev);
 
 	if (!(timer->capability & OMAP_TIMER_ALWON)) {
@@ -383,7 +386,11 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
 
 void omap_dm_timer_disable(struct omap_dm_timer *timer)
 {
-	pm_runtime_put_sync(&timer->pdev->dev);
+	if (timer->enabled == 1)
+		pm_runtime_put_sync(&timer->pdev->dev);
+
+	if (timer->enabled)
+		timer->enabled--;
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
 
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index dd79f30..fc984e1 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -114,6 +114,7 @@ struct omap_dm_timer {
 	unsigned long rate;
 	unsigned reserved:1;
 	unsigned posted:1;
+	u32 enabled;
 	struct timer_regs context;
 	int (*get_context_loss_count)(struct device *);
 	int ctx_loss_count;
-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Sat May  7 08:21:45 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Sat,  7 May 2016 18:21:45 +0300
Subject: [PATCH 4/7] [media] ir-rx51: add DT support to driver
In-Reply-To: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1462634508-24961-5-git-send-email-ivo.g.dimitrov.75@gmail.com>

With the upcoming removal of legacy boot, lets add support to one of the
last N900 drivers remaining without it. As the driver still uses omap
dmtimer, add auxdata as well.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
---
 .../devicetree/bindings/media/nokia,lirc-rx51         | 19 +++++++++++++++++++
 arch/arm/mach-omap2/pdata-quirks.c                    |  6 +-----
 drivers/media/rc/ir-rx51.c                            | 11 ++++++++++-
 3 files changed, 30 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/nokia,lirc-rx51

diff --git a/Documentation/devicetree/bindings/media/nokia,lirc-rx51 b/Documentation/devicetree/bindings/media/nokia,lirc-rx51
new file mode 100644
index 0000000..5b3081e
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/nokia,lirc-rx51
@@ -0,0 +1,19 @@
+Device-Tree bindings for LIRC TX driver for Nokia N900(RX51)
+
+Required properties:
+	- compatible: should be "nokia,lirc-rx51".
+	- pwms: specifies PWM used for IR signal transmission.
+
+Example node:
+
+	pwm9: dmtimer-pwm at 9 {
+		compatible = "ti,omap-dmtimer-pwm";
+		ti,timers = <&timer9>;
+		#pwm-cells = <3>;
+	};
+
+	ir: lirc-rx51 {
+		compatible = "nokia,lirc-rx51";
+
+		pwms = <&pwm9 0 26316 0>; /* 38000 Hz */
+	};
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index af65781..c15ccac 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -273,8 +273,6 @@ static struct platform_device omap3_rom_rng_device = {
 	},
 };
 
-static struct platform_device rx51_lirc_device;
-
 static void __init nokia_n900_legacy_init(void)
 {
 	hsmmc2_internal_input_clk();
@@ -293,10 +291,7 @@ static void __init nokia_n900_legacy_init(void)
 
 		pr_info("RX-51: Registering OMAP3 HWRNG device\n");
 		platform_device_register(&omap3_rom_rng_device);
-
 	}
-
-	platform_device_register(&rx51_lirc_device);
 }
 
 static void __init omap3_tao3530_legacy_init(void)
@@ -534,6 +529,7 @@ static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 		       &omap3_iommu_pdata),
 	OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x4809c000, "4809c000.mmc", &mmc_pdata[0]),
 	OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x480b4000, "480b4000.mmc", &mmc_pdata[1]),
+	OF_DEV_AUXDATA("nokia,lirc-rx51", 0, "lirc-rx51", &rx51_lirc_data),
 	/* Only on am3517 */
 	OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
 	OF_DEV_AUXDATA("ti,am3517-emac", 0x5c000000, "davinci_emac.0",
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 5096ef3..7a329d8 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -21,6 +21,7 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/pwm.h>
+#include <linux/of.h>
 
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
@@ -478,6 +479,14 @@ static int lirc_rx51_remove(struct platform_device *dev)
 	return lirc_unregister_driver(lirc_rx51_driver.minor);
 }
 
+static const struct of_device_id lirc_rx51_match[] = {
+	{
+		.compatible = "nokia,lirc-rx51",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, lirc_rx51_match);
+
 struct platform_driver lirc_rx51_platform_driver = {
 	.probe		= lirc_rx51_probe,
 	.remove		= lirc_rx51_remove,
@@ -485,7 +494,7 @@ struct platform_driver lirc_rx51_platform_driver = {
 	.resume		= lirc_rx51_resume,
 	.driver		= {
 		.name	= DRIVER_NAME,
-		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(lirc_rx51_match),
 	},
 };
 module_platform_driver(lirc_rx51_platform_driver);
-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Sat May  7 08:21:47 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Sat,  7 May 2016 18:21:47 +0300
Subject: [PATCH 6/7] [media] ir-rx51: use hrtimer instead of dmtimer
In-Reply-To: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1462634508-24961-7-git-send-email-ivo.g.dimitrov.75@gmail.com>

Drop dmtimer usage for pulse timer in favor of hrtimer. That allows
removing PWM dmitimer platform data usage.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
---
 arch/arm/mach-omap2/board-rx51-peripherals.c |   4 -
 arch/arm/mach-omap2/pdata-quirks.c           |   3 -
 drivers/media/rc/ir-rx51.c                   | 166 ++++++---------------------
 include/linux/platform_data/media/ir-rx51.h  |   1 -
 4 files changed, 37 insertions(+), 137 deletions(-)

diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index e487575..a5ab712 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -1242,10 +1242,6 @@ static struct pwm_omap_dmtimer_pdata __maybe_unused pwm_dmtimer_pdata = {
 #if defined(CONFIG_IR_RX51) || defined(CONFIG_IR_RX51_MODULE)
 static struct lirc_rx51_platform_data rx51_lirc_data = {
 	.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
-#if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
-	.dmtimer = &pwm_dmtimer_pdata,
-#endif
-
 };
 
 static struct platform_device rx51_lirc_device = {
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index c15ccac..8936ffc 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -486,9 +486,6 @@ static struct pwm_omap_dmtimer_pdata pwm_dmtimer_pdata = {
 
 static struct lirc_rx51_platform_data __maybe_unused rx51_lirc_data = {
 	.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
-#if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
-	.dmtimer = &pwm_dmtimer_pdata,
-#endif
 };
 
 static struct platform_device __maybe_unused rx51_lirc_device = {
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 7a329d8..9dbe0a4 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -22,10 +22,10 @@
 #include <linux/wait.h>
 #include <linux/pwm.h>
 #include <linux/of.h>
+#include <linux/hrtimer.h>
 
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
-#include <linux/platform_data/pwm_omap_dmtimer.h>
 #include <linux/platform_data/media/ir-rx51.h>
 
 #define LIRC_RX51_DRIVER_FEATURES (LIRC_CAN_SET_SEND_DUTY_CYCLE |	\
@@ -36,32 +36,26 @@
 
 #define WBUF_LEN 256
 
-#define TIMER_MAX_VALUE 0xffffffff
-
 struct lirc_rx51 {
 	struct pwm_device *pwm;
-	pwm_omap_dmtimer *pulse_timer;
-	struct pwm_omap_dmtimer_pdata *dmtimer;
+	struct hrtimer timer;
 	struct device	     *dev;
 	struct lirc_rx51_platform_data *pdata;
 	wait_queue_head_t     wqueue;
 
-	unsigned long	fclk_khz;
 	unsigned int	freq;		/* carrier frequency */
 	unsigned int	duty_cycle;	/* carrier duty cycle */
-	unsigned int	irq_num;
-	unsigned int	match;
 	int		wbuf[WBUF_LEN];
 	int		wbuf_index;
 	unsigned long	device_is_open;
 };
 
-static void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
+static inline void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
 {
 	pwm_enable(lirc_rx51->pwm);
 }
 
-static void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
+static inline void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
 {
 	pwm_disable(lirc_rx51->pwm);
 }
@@ -72,61 +66,21 @@ static int init_timing_params(struct lirc_rx51 *lirc_rx51)
 	int duty, period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, lirc_rx51->freq);
 
 	duty = DIV_ROUND_CLOSEST(lirc_rx51->duty_cycle * period, 100);
-	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
 
 	pwm_config(pwm, duty, period);
 
-	lirc_rx51->dmtimer->start(lirc_rx51->pulse_timer);
-
-	lirc_rx51->match = 0;
-
 	return 0;
 }
 
-#define tics_after(a, b) ((long)(b) - (long)(a) < 0)
-
-static int pulse_timer_set_timeout(struct lirc_rx51 *lirc_rx51, int usec)
+static enum hrtimer_restart lirc_rx51_timer_cb(struct hrtimer *timer)
 {
-	int counter;
-
-	BUG_ON(usec < 0);
-
-	if (lirc_rx51->match == 0)
-		counter = lirc_rx51->dmtimer->read_counter(lirc_rx51->pulse_timer);
-	else
-		counter = lirc_rx51->match;
-
-	counter += (u32)(lirc_rx51->fclk_khz * usec / (1000));
-	lirc_rx51->dmtimer->set_match(lirc_rx51->pulse_timer, 1, counter);
-	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer,
-					   PWM_OMAP_DMTIMER_INT_MATCH);
-	if (tics_after(lirc_rx51->dmtimer->read_counter(lirc_rx51->pulse_timer),
-		       counter)) {
-		return 1;
-	}
-	return 0;
-}
+	struct lirc_rx51 *lirc_rx51 =
+			container_of(timer, struct lirc_rx51, timer);
+	ktime_t now;
 
-static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
-{
-	unsigned int retval;
-	struct lirc_rx51 *lirc_rx51 = ptr;
-
-	retval = lirc_rx51->dmtimer->read_status(lirc_rx51->pulse_timer);
-	if (!retval)
-		return IRQ_NONE;
-
-	if (retval & ~PWM_OMAP_DMTIMER_INT_MATCH)
-		dev_err_ratelimited(lirc_rx51->dev,
-				": Unexpected interrupt source: %x\n", retval);
-
-	lirc_rx51->dmtimer->write_status(lirc_rx51->pulse_timer,
-					 PWM_OMAP_DMTIMER_INT_MATCH |
-					 PWM_OMAP_DMTIMER_INT_OVERFLOW |
-					 PWM_OMAP_DMTIMER_INT_CAPTURE);
 	if (lirc_rx51->wbuf_index < 0) {
 		dev_err_ratelimited(lirc_rx51->dev,
-				": BUG wbuf_index has value of %i\n",
+				"BUG wbuf_index has value of %i\n",
 				lirc_rx51->wbuf_index);
 		goto end;
 	}
@@ -136,6 +90,8 @@ static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
 	 * pulses until we catch up.
 	 */
 	do {
+		u64 ns;
+
 		if (lirc_rx51->wbuf_index >= WBUF_LEN)
 			goto end;
 		if (lirc_rx51->wbuf[lirc_rx51->wbuf_index] == -1)
@@ -146,80 +102,24 @@ static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
 		else
 			lirc_rx51_on(lirc_rx51);
 
-		retval = pulse_timer_set_timeout(lirc_rx51,
-					lirc_rx51->wbuf[lirc_rx51->wbuf_index]);
+		ns = 1000 * lirc_rx51->wbuf[lirc_rx51->wbuf_index];
+		hrtimer_add_expires_ns(timer, ns);
+
 		lirc_rx51->wbuf_index++;
 
-	} while (retval);
+		now = timer->base->get_time();
+
+	} while (hrtimer_get_expires_tv64(timer) < now.tv64);
 
-	return IRQ_HANDLED;
+	return HRTIMER_RESTART;
 end:
 	/* Stop TX here */
 	lirc_rx51_off(lirc_rx51);
 	lirc_rx51->wbuf_index = -1;
 
-	lirc_rx51->dmtimer->stop(lirc_rx51->pulse_timer);
-	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
 	wake_up_interruptible(&lirc_rx51->wqueue);
 
-	return IRQ_HANDLED;
-}
-
-static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
-{
-	struct clk *clk_fclk;
-	int retval;
-
-	lirc_rx51->pwm = pwm_get(lirc_rx51->dev, NULL);
-	if (IS_ERR(lirc_rx51->pwm)) {
-		retval = PTR_ERR(lirc_rx51->pwm);
-		dev_err(lirc_rx51->dev, ": pwm_get failed: %d\n", retval);
-		return retval;
-	}
-
-	lirc_rx51->pulse_timer = lirc_rx51->dmtimer->request();
-	if (lirc_rx51->pulse_timer == NULL) {
-		dev_err(lirc_rx51->dev, ": Error requesting pulse timer\n");
-		retval = -EBUSY;
-		goto err1;
-	}
-
-	lirc_rx51->dmtimer->set_source(lirc_rx51->pulse_timer,
-				       PWM_OMAP_DMTIMER_SRC_SYS_CLK);
-	lirc_rx51->dmtimer->enable(lirc_rx51->pulse_timer);
-	lirc_rx51->irq_num =
-			lirc_rx51->dmtimer->get_irq(lirc_rx51->pulse_timer);
-	retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler,
-			     IRQF_SHARED, "lirc_pulse_timer", lirc_rx51);
-	if (retval) {
-		dev_err(lirc_rx51->dev, ": Failed to request interrupt line\n");
-		goto err2;
-	}
-
-	clk_fclk = lirc_rx51->dmtimer->get_fclk(lirc_rx51->pulse_timer);
-	lirc_rx51->fclk_khz = clk_get_rate(clk_fclk) / 1000;
-
-	return 0;
-
-err2:
-	lirc_rx51->dmtimer->free(lirc_rx51->pulse_timer);
-err1:
-	pwm_put(lirc_rx51->pwm);
-
-	return retval;
-}
-
-static int lirc_rx51_free_port(struct lirc_rx51 *lirc_rx51)
-{
-	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
-	free_irq(lirc_rx51->irq_num, lirc_rx51);
-	lirc_rx51_off(lirc_rx51);
-	lirc_rx51->dmtimer->disable(lirc_rx51->pulse_timer);
-	lirc_rx51->dmtimer->free(lirc_rx51->pulse_timer);
-	lirc_rx51->wbuf_index = -1;
-	pwm_put(lirc_rx51->pwm);
-
-	return 0;
+	return HRTIMER_NORESTART;
 }
 
 static ssize_t lirc_rx51_write(struct file *file, const char *buf,
@@ -258,8 +158,9 @@ static ssize_t lirc_rx51_write(struct file *file, const char *buf,
 
 	lirc_rx51_on(lirc_rx51);
 	lirc_rx51->wbuf_index = 1;
-	pulse_timer_set_timeout(lirc_rx51, lirc_rx51->wbuf[0]);
-
+	hrtimer_start(&lirc_rx51->timer,
+		      ns_to_ktime(1000 * lirc_rx51->wbuf[0]),
+		      HRTIMER_MODE_REL);
 	/*
 	 * Don't return back to the userspace until the transfer has
 	 * finished
@@ -359,14 +260,24 @@ static int lirc_rx51_open(struct inode *inode, struct file *file)
 	if (test_and_set_bit(1, &lirc_rx51->device_is_open))
 		return -EBUSY;
 
-	return lirc_rx51_init_port(lirc_rx51);
+	lirc_rx51->pwm = pwm_get(lirc_rx51->dev, NULL);
+	if (IS_ERR(lirc_rx51->pwm)) {
+		int res = PTR_ERR(lirc_rx51->pwm);
+
+		dev_err(lirc_rx51->dev, "pwm_get failed: %d\n", res);
+		return res;
+	}
+
+	return 0;
 }
 
 static int lirc_rx51_release(struct inode *inode, struct file *file)
 {
 	struct lirc_rx51 *lirc_rx51 = file->private_data;
 
-	lirc_rx51_free_port(lirc_rx51);
+	hrtimer_cancel(&lirc_rx51->timer);
+	lirc_rx51_off(lirc_rx51);
+	pwm_put(lirc_rx51->pwm);
 
 	clear_bit(1, &lirc_rx51->device_is_open);
 
@@ -441,11 +352,6 @@ static int lirc_rx51_probe(struct platform_device *dev)
 		return -ENXIO;
 	}
 
-	if (!lirc_rx51.pdata->dmtimer) {
-		dev_err(&dev->dev, "no dmtimer?\n");
-		return -ENODEV;
-	}
-
 	pwm = pwm_get(&dev->dev, NULL);
 	if (IS_ERR(pwm)) {
 		int err = PTR_ERR(pwm);
@@ -459,7 +365,9 @@ static int lirc_rx51_probe(struct platform_device *dev)
 	lirc_rx51.freq = DIV_ROUND_CLOSEST(pwm_get_period(pwm), NSEC_PER_SEC);
 	pwm_put(pwm);
 
-	lirc_rx51.dmtimer = lirc_rx51.pdata->dmtimer;
+	hrtimer_init(&lirc_rx51.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	lirc_rx51.timer.function = lirc_rx51_timer_cb;
+
 	lirc_rx51.dev = &dev->dev;
 	lirc_rx51_driver.dev = &dev->dev;
 	lirc_rx51_driver.minor = lirc_register_driver(&lirc_rx51_driver);
diff --git a/include/linux/platform_data/media/ir-rx51.h b/include/linux/platform_data/media/ir-rx51.h
index 6acf22d..812d873 100644
--- a/include/linux/platform_data/media/ir-rx51.h
+++ b/include/linux/platform_data/media/ir-rx51.h
@@ -3,7 +3,6 @@
 
 struct lirc_rx51_platform_data {
 	int(*set_max_mpu_wakeup_lat)(struct device *dev, long t);
-	struct pwm_omap_dmtimer_pdata *dmtimer;
 };
 
 #endif
-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Sat May  7 08:21:48 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Sat,  7 May 2016 18:21:48 +0300
Subject: [PATCH 7/7] ARM: dts: n900: enable lirc-rx51 driver
In-Reply-To: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1462634508-24961-8-git-send-email-ivo.g.dimitrov.75@gmail.com>

Add the needed DT data to enable IR TX driver

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
---
 arch/arm/boot/dts/omap3-n900.dts | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts
index b3c26a9..3d1e23e 100644
--- a/arch/arm/boot/dts/omap3-n900.dts
+++ b/arch/arm/boot/dts/omap3-n900.dts
@@ -143,6 +143,18 @@
 		io-channels = <&twl_madc 0>, <&twl_madc 4>, <&twl_madc 12>;
 		io-channel-names = "temp", "bsi", "vbat";
 	};
+
+	pwm9: dmtimer-pwm at 9 {
+		compatible = "ti,omap-dmtimer-pwm";
+		#pwm-cells = <3>;
+		ti,timers = <&timer9>;
+		ti,clock-source = <0x00>; /* timer_sys_ck */
+	};
+
+	ir: lirc-rx51 {
+		compatible = "nokia,lirc-rx51";
+		pwms = <&pwm9 0 26316 0>; /* 38000 Hz */
+	};
 };
 
 &omap3_pmx_core {
-- 
1.9.1



From troy.kisky at boundarydevices.com  Sat May  7 11:56:50 2016
From: troy.kisky at boundarydevices.com (Troy Kisky)
Date: Sat, 7 May 2016 11:56:50 -0700
Subject: [PATCH net 1/1] net: fec: update dirty_tx even if no skb
In-Reply-To: <VI1PR0401MB18558325A80D252D2EC64A7BFF6F0@VI1PR0401MB1855.eurprd04.prod.outlook.com>
References: <1461290434-18462-1-git-send-email-troy.kisky@boundarydevices.com>
 <VI1PR0401MB18558325A80D252D2EC64A7BFF6F0@VI1PR0401MB1855.eurprd04.prod.outlook.com>
Message-ID: <0288eea6-9669-d763-4bd8-9438ce0c1f94@boundarydevices.com>

On 4/21/2016 10:59 PM, Fugang Duan wrote:
> From: Troy Kisky <troy.kisky at boundarydevices.com> Sent: Friday, April 22, 2016 10:01 AM
>> To: netdev at vger.kernel.org; davem at davemloft.net; Fugang Duan
>> <fugang.duan at nxp.com>; lznuaa at gmail.com
>> Cc: Fabio Estevam <fabio.estevam at nxp.com>; l.stach at pengutronix.de;
>> andrew at lunn.ch; tremyfr at gmail.com; gerg at uclinux.org; linux-arm-
>> kernel at lists.infradead.org; johannes at sipsolutions.net;
>> stillcompiling at gmail.com; sergei.shtylyov at cogentembedded.com;
>> arnd at arndb.de; holgerschurig at gmail.com; Troy Kisky
>> <troy.kisky at boundarydevices.com>
>> Subject: [PATCH net 1/1] net: fec: update dirty_tx even if no skb
>>
>> If dirty_tx isn't updated, then dma_unmap_single will be called twice.
>>
>> This fixes a
>> [   58.420980] ------------[ cut here ]------------
>> [   58.425667] WARNING: CPU: 0 PID: 377 at /home/schurig/d/mkarm/linux-
>> 4.5/lib/dma-debug.c:1096 check_unmap+0x9d0/0xab8()
>> [   58.436405] fec 2188000.ethernet: DMA-API: device driver tries to free DMA
>> memory it has not allocated [device address=0x0000000000000000] [size=66
>> bytes]
>>
>> encountered by Holger
>>
>> Signed-off-by: Troy Kisky <troy.kisky at boundarydevices.com>
>> Tested-by: <holgerschurig at gmail.com>
>> ---
>>  drivers/net/ethernet/freescale/fec_main.c | 8 +++-----
>>  1 file changed, 3 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/freescale/fec_main.c
>> b/drivers/net/ethernet/freescale/fec_main.c
>> index 08243c2..b71654c 100644
>> --- a/drivers/net/ethernet/freescale/fec_main.c
>> +++ b/drivers/net/ethernet/freescale/fec_main.c
>> @@ -1197,10 +1197,8 @@ fec_enet_tx_queue(struct net_device *ndev, u16
>> queue_id)
>>  					 fec16_to_cpu(bdp->cbd_datlen),
>>  					 DMA_TO_DEVICE);
>>  		bdp->cbd_bufaddr = cpu_to_fec32(0);
>> -		if (!skb) {
>> -			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
>> -			continue;
>> -		}
>> +		if (!skb)
>> +			goto skb_done;
>>
>>  		/* Check for errors. */
>>  		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | @@ -1239,7
>> +1237,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
>>
>>  		/* Free the sk buffer associated with this last transmit */
>>  		dev_kfree_skb_any(skb);
>> -
>> +skb_done:
>>  		/* Make sure the update to bdp and tx_skbuff are performed
>>  		 * before dirty_tx
>>  		 */
>> --
>> 2.5.0
> 
> The patch is fine for me.
> Can you review below patch that also fix the issue. It can take much effort due to less rmb() and READ_ONCE() operation that is very sensitive for duplex Gbps test for i.MX6SX/i.MX7d SOC. (i.MX6SX can reach at 1.4Gbps, i.MX7D can reach at 1.8Gbps.)
> 


Am I supposed to do anything else to get this patch into net ?



From alex.williamson at redhat.com  Sat May  7 18:50:58 2016
From: alex.williamson at redhat.com (Alex Williamson)
Date: Sat, 7 May 2016 19:50:58 -0600
Subject: VFIO MSIX Query
In-Reply-To: <CAB995MsFjv=GvHSmo029fmuTWhGiYev3-2A358orFz_dq724Fw@mail.gmail.com>
References: <CAB995Mu0==PJ0iU4h_3oAMGo-VYDFrjOg_BO757M=PDWgMWtCw@mail.gmail.com>
 <20160503140249.4edaf3cc@t450s.home>
 <CAB995MsFjv=GvHSmo029fmuTWhGiYev3-2A358orFz_dq724Fw@mail.gmail.com>
Message-ID: <20160507195058.5b00f176@ul30vt.home>

Hi Nitin,

On Sat, 7 May 2016 21:09:09 +0530
Nitin Saxena <nitin.lnx at gmail.com> wrote:

> Hi Alex,
> 
> I have specific questions related to the problem I am facing in using VFIO
> for MSIX interrupt.
> 
> My userspace program running on x86 talks to NIC connected via PCIe
> interface. Current program works fine in poll mode with no VF and SRIOV
> requirement. I am changing my app from poll mode to interrupt mode using
> VFIO NOIOMMU feature as I am interested in getting MSIX interrupts only
> (For this I have ported VFIO-NOIOMMU feature patch from kernel 4.5 to 3.10
> SL7).  After applying the patch I can see /dev/vfio/noiommu-X and I could
> assign my PCI device to /dev/vfio/noiommu-0. Seems like kernel patch
> applied from 4.5 to 3.10 working fine. Also MSIX interrupts works fine with
> another kernel application but I am facing issues in using MSIX interrupts
> with my userspace program integrated with VFIO. I am running single process
> only  with one MSIX interrupt requirement
> 
> Few Questions:
> 
> Q1) VFIO_GROUP_GET_DEVICE_FD ioctl call stops poll mode data traffic. Why?
> I used my poll mode data path loop (where I am not waiting for MSIX) with
> my vfio_init() API I found that if I call follow VFIO sequence in
> vfio_init():
> a) create container fd (b) get group_fd (c) VFIO_SET_IOMMU as NOIOMMU ==>
> then my poll mode data path works fine
> but if I call a) create container fd (b) get group_fd (c) VFIO_SET_IOMMU as
> NOIOMMU (d) VFIO_GROUP_GET_DEVICE_FD  ==> then my poll mode data path does
> not work. I don't know why

It sounds like you're trying to mix VFIO with some other access to the
device, perhaps through pci-sysfs.  This is not compatible with VFIO.
Use VFIO for all access to the device or none.  When the device is
initially opened via the GET_DEVICE_FD ioctl, we go through an
initialization sequence on the device, including a device reset.  VFIO
is not meant to only provide MSI-X on top of a some other access
mechanism.

> Q2)Does MSIX bar/table mapping required for my case. Why?
> Even if VFIO is not used in my userspace program, BAR0 and BAR1 was already
> mmapped to process but not MSIX table. Do I need to mmap MSIX table in my
> interrupt based data path as I saw this mmaping of MSIX table in QEMU and
> dpdk both but I think these software must be using VFIO_IOMMU_TYPE1 and not
> VFIO_NOIOMMU which is my case. So can you confirm is it needed for me to
> mmap MSIX table.

Again, no mixing interfaces.  Use VFIO for all access to the device or
don't use VFIO at all.  Regardless, there's no need to mmap the MSI-X
table.  VFIO does not currently allow mmap of the MSI-X table.  If at
some point it is allowed, attempting to manipulate MSI-X via the device
vector table directly is not supported.  Only the SET_IRQS ioctl is
used for configuring device interrupts.

> Q3) Does VFIO_DEVICE_RESET required, when and why ?
> My userspace program implicitly resets PCI hardware and then I call my
> vfio_init() API and then start data path. So at what point I should can
> VFIO_DEVICE_RESET?

This is wrong, VFIO is the access to the device, any combination of
other access mechanisms plus VFIO is not supported and not intended to
work.  VFIO will attempt to reset the device when opened, any other
reset is at the user driver's discretion.

> Q4) Is there any Do's and Dont's document for VFIO so that I can follow
> proper sequence.

Don't #1: Don't attempt to add VFIO only for MSI-X support, use it for
all access to the device or don't use it at all.  There's
Documentation/vfio.txt and QEMU as the de facto standard usage example,
that's it afaik.  Thanks,

Alex


From krzk at kernel.org  Sun May  8 02:24:56 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 11:24:56 +0200
Subject: [PATCH] clk: samsung: exynos5420: Remove useless check for return
 value of samsung_clk_init
Message-ID: <1462699496-16646-1-git-send-email-krzk@kernel.org>

The samsung_clk_init() cannot return NULL. Either it returns allocated
memory or it panics.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 drivers/clk/samsung/clk-exynos5420.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 92382cef9f90..770c0f007c6b 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -1356,8 +1356,6 @@ static void __init exynos5x_clk_init(struct device_node *np,
 	exynos5x_soc = soc;
 
 	ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
-	if (!ctx)
-		panic("%s: unable to allocate context.\n", __func__);
 
 	samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
-- 
2.5.0



From niklas.soderlund+renesas at ragnatech.se  Sun May  8 03:59:55 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Sun,  8 May 2016 12:59:55 +0200
Subject: [PATCH 1/2] dma-mapping: add __dma_sync_single_for_device()
In-Reply-To: <1462705196-10857-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462705196-10857-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462705196-10857-2-git-send-email-niklas.soderlund+renesas@ragnatech.se>

Some users of the DMA mapping API calls dma_sync_single_for_device()
from the dma_map_single() call path. This will cause false warning
printouts if CONFIG_DMA_API_DEBUG are enabled.

The reason for the warning are that debug_dma_sync_single_for_device()
will be called before debug_dma_map_page() so the new mapping can't be
found and are believed to be invalid. Add __dma_sync_single_for_device()
that don't call into debug_dma_sync_single_for_device() and can be used
in these situations.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
---
 include/linux/dma-mapping.h | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 9ea9aba..0e4d3a6 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -224,7 +224,7 @@ static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
 	debug_dma_sync_single_for_cpu(dev, addr, size, dir);
 }
 
-static inline void dma_sync_single_for_device(struct device *dev,
+static inline void __dma_sync_single_for_device(struct device *dev,
 					      dma_addr_t addr, size_t size,
 					      enum dma_data_direction dir)
 {
@@ -233,6 +233,13 @@ static inline void dma_sync_single_for_device(struct device *dev,
 	BUG_ON(!valid_dma_direction(dir));
 	if (ops->sync_single_for_device)
 		ops->sync_single_for_device(dev, addr, size, dir);
+}
+
+static inline void dma_sync_single_for_device(struct device *dev,
+					      dma_addr_t addr, size_t size,
+					      enum dma_data_direction dir)
+{
+	__dma_sync_single_for_device(dev, addr, size, dir);
 	debug_dma_sync_single_for_device(dev, addr, size, dir);
 }
 
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Sun May  8 03:59:56 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Sun,  8 May 2016 12:59:56 +0200
Subject: [PATCH 2/2] iommu/io-pgtable-arm: use __dma_sync_single_for_device()
In-Reply-To: <1462705196-10857-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462705196-10857-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462705196-10857-3-git-send-email-niklas.soderlund+renesas@ragnatech.se>

The call to dma_sync_single_for_device() can be reached from
dma_map_single(). If CONFIG_DMA_API_DEBUG is enabled this would result
in a check that the mapping being synced is valid. Since the call to
dma_map_single is not yet completed the mapping is not recorded in
dma-debug and the check fails and a warning is printed. Avoid this
warning by calling __dma_sync_single_for_device() which don't preform
this check.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
---
 drivers/iommu/io-pgtable-arm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index f433b51..3da8102 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -255,7 +255,7 @@ static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte,
 	*ptep = pte;
 
 	if (!selftest_running)
-		dma_sync_single_for_device(cfg->iommu_dev,
+		__dma_sync_single_for_device(cfg->iommu_dev,
 					   __arm_lpae_dma_addr(ptep),
 					   sizeof(pte), DMA_TO_DEVICE);
 }
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Sun May  8 03:59:54 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Sun,  8 May 2016 12:59:54 +0200
Subject: [PATCH 0/2] Fix incorrect warning from dma-debug
Message-ID: <1462705196-10857-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>

Hi,

While using CONFIG_DMA_API_DEBUG i came across this warning which I
think is a false positive. As shown dma_sync_single_for_device() are
called from the dma_map_single() call path. This triggers the warning
since the dma-debug code have not yet been made aware of the mapping.

I try to solve this by introducing __dma_sync_single_for_device() which
do not call into the dma-debug code. I'm no expert and this might be a
bad way of solving the problem but it allowed me to keep working.

------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at lib/dma-debug.c:1209 check_sync+0x154/0x5e4
ipmmu-vmsa e6740000.mmu: DMA-API: device driver tries to sync DMA memory it has not allocated [device address=0x000000006e89b008] [size=8 bytes]
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.6.0-rc5-00012-g52e78c1-dirty #1
Hardware name: Generic R8A7791 (Flattened Device Tree)
Backtrace:
[<c020a0a4>] (dump_backtrace) from [<c020a250>] (show_stack+0x18/0x1c)
 r7:c03ebad0 r6:00000009 r5:60000093 r4:00000000
[<c020a238>] (show_stack) from [<c03cb7e4>] (dump_stack+0x84/0xa4)
[<c03cb760>] (dump_stack) from [<c021e3ac>] (__warn+0xd0/0x100)
 r5:00000000 r4:ef05dac8
[<c021e2dc>] (__warn) from [<c021e41c>] (warn_slowpath_fmt+0x40/0x48)
 r9:00010000 r8:00000000 r7:c0c69c40 r6:c0c02754 r5:ef05db78 r4:ef222810
[<c021e3e0>] (warn_slowpath_fmt) from [<c03ebad0>] (check_sync+0x154/0x5e4)
 r3:c0945b6f r2:c0936e85
[<c03eb97c>] (check_sync) from [<c03ed594>] (debug_dma_sync_single_for_device+0x64/0x70)
 r10:00000009 r9:0000000c r8:ee89b008 r7:00000000 r6:6e89b008 r5:00000000
 r4:6e89b008
[<c03ed530>] (debug_dma_sync_single_for_device) from [<c0465298>] (__arm_lpae_set_pte.part.0+0x80/0x8c)
 r5:00000001 r4:ef222810
[<c0465218>] (__arm_lpae_set_pte.part.0) from [<c046553c>] (__arm_lpae_map+0x298/0x2f0)
 r7:00000008 r6:ef25e000 r4:ee898500
[<c04652a4>] (__arm_lpae_map) from [<c0465b18>] (arm_lpae_map+0xcc/0xe4)
 r10:c0465f40 r9:00001000 r8:40000000 r7:00000000 r6:6f25c000 r5:00000000
 r4:000008c0
[<c0465a4c>] (arm_lpae_map) from [<c0465f78>] (ipmmu_map+0x38/0x40)
 r7:40000000 r6:00000000 r5:00001000 r4:c0465a4c
[<c0465f40>] (ipmmu_map) from [<c0463d90>] (iommu_map+0xf8/0x15c)
 r4:ee895608
[<c0463c98>] (iommu_map) from [<c0213524>] (arm_coherent_iommu_map_page+0x1d4/0x2d4)
 r10:ef386940 r9:00001000 r8:00000000 r7:00000000 r6:40000000 r5:00000000
 r4:00000000
[<c0213350>] (arm_coherent_iommu_map_page) from [<c0213690>] (arm_iommu_map_page+0x6c/0x74)
 r10:c0c61f44 r9:ef19d210 r8:00000001 r7:00001000 r6:00000000 r5:ec5ddb80
 r4:00000000
[<c0213624>] (arm_iommu_map_page) from [<c04f7d64>] (sh_msiof_spi_probe+0x430/0x7b0)
 r9:00000000 r8:c0213624 r7:ef19d210 r6:ef242800 r5:ef1b4010 r4:ef242af0
[<c04f7934>] (sh_msiof_spi_probe) from [<c049fd3c>] (platform_drv_probe+0x58/0xa8)
 r10:00000000 r9:00000000 r8:c0c1f8d4 r7:c0c7e910 r6:c0c1f8d4 r5:ef1b4010
 r4:c04f7934
[<c049fce4>] (platform_drv_probe) from [<c049e788>] (driver_probe_device+0x13c/0x2a4)
 r7:c0c7e910 r6:00000000 r5:c0c7e900 r4:ef1b4010
[<c049e64c>] (driver_probe_device) from [<c049e978>] (__driver_attach+0x88/0xac)
 r9:c0c34000 r8:c0a3c010 r7:c0c1cf08 r6:c0c1f8d4 r5:ef1b4044 r4:ef1b4010
[<c049e8f0>] (__driver_attach) from [<c049ce44>] (bus_for_each_dev+0x74/0x98)
 r7:c0c1cf08 r6:c049e8f0 r5:c0c1f8d4 r4:00000000
[<c049cdd0>] (bus_for_each_dev) from [<c049ebd0>] (driver_attach+0x20/0x28)
 r6:ef1cc200 r5:00000000 r4:c0c1f8d4
[<c049ebb0>] (driver_attach) from [<c049d5d8>] (bus_add_driver+0xd4/0x1e4)
[<c049d504>] (bus_add_driver) from [<c049f2dc>] (driver_register+0xa4/0xe8)
 r7:c0a3c010 r6:00000000 r5:c0a1e400 r4:c0c1f8d4
[<c049f238>] (driver_register) from [<c04a0778>] (__platform_driver_register+0x38/0x4c)
 r5:c0a1e400 r4:ee958fc0
[<c04a0740>] (__platform_driver_register) from [<c0a1e418>] (sh_msiof_spi_drv_init+0x18/0x20)
[<c0a1e400>] (sh_msiof_spi_drv_init) from [<c0a00e1c>] (do_one_initcall+0x10c/0x1c0)
[<c0a00d10>] (do_one_initcall) from [<c0a00ff8>] (kernel_init_freeable+0x128/0x1f4)
 r9:c0c34000 r8:c0c34000 r7:c0a47e60 r6:c0a3c83c r5:000000bd r4:00000006
[<c0a00ed0>] (kernel_init_freeable) from [<c071067c>] (kernel_init+0x10/0x118)
 r9:00000000[    1.879529] ata1: link resume succeeded after 1 retries
 r8:00000000 r7:00000000 r6:00000000 r5:c071066c r4:00000000
[<c071066c>] (kernel_init) from [<c0206e08>] (ret_from_fork+0x14/0x2c)
 r5:c071066c r4:00000000
---[ end trace 6eb9a3df3009d491 ]---

Niklas S?derlund (2):
  dma-mapping: add __dma_sync_single_for_device()
  iommu/io-pgtable-arm: use __dma_sync_single_for_device()

 drivers/iommu/io-pgtable-arm.c | 2 +-
 include/linux/dma-mapping.h    | 9 ++++++++-
 2 files changed, 9 insertions(+), 2 deletions(-)

--
2.8.2



From manabian at gmail.com  Sun May  8 04:55:39 2016
From: manabian at gmail.com (Joachim Eastwood)
Date: Sun,  8 May 2016 13:55:39 +0200
Subject: [PATCH] ARM: configs: lpc18xx: enable adc and dac iio drivers
Message-ID: <1462708539-9222-1-git-send-email-manabian@gmail.com>

Enable ADC and DAC IIO drivers for LPC18xx/43xx SoCs.

Signed-off-by: Joachim Eastwood <manabian at gmail.com>
---
Hi arm-soc team,

Only one simple defconfig update for lpc18xx this cycle. So please
apply this one directly. Thanks!


regards,
Joachim Eastwood

 arch/arm/configs/lpc18xx_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/lpc18xx_defconfig b/arch/arm/configs/lpc18xx_defconfig
index 2ae00b0..2de1bf0 100644
--- a/arch/arm/configs/lpc18xx_defconfig
+++ b/arch/arm/configs/lpc18xx_defconfig
@@ -149,6 +149,8 @@ CONFIG_PWM=y
 CONFIG_PWM_LPC18XX_SCT=y
 CONFIG_IIO=y
 CONFIG_MMA7455_I2C=y
+CONFIG_LPC18XX_ADC=y
+CONFIG_LPC18XX_DAC=y
 CONFIG_IIO_SYSFS_TRIGGER=y
 CONFIG_PHY_LPC18XX_USB_OTG=y
 CONFIG_NVMEM=y
-- 
2.8.2



From zengzhaoxiu at 163.com  Sun May  8 05:52:52 2016
From: zengzhaoxiu at 163.com (Zhaoxiu Zeng)
Date: Sun, 8 May 2016 20:52:52 +0800
Subject: [patch V4] lib: GCD: Use binary GCD algorithm instead of Euclidean
In-Reply-To: <20160507084129.7284.qmail@ns.horizon.com>
References: <20160507084129.7284.qmail@ns.horizon.com>
Message-ID: <042bae7f-51d6-93e8-549d-a38bcb4c9cf5@163.com>

? 2016/5/7 16:41, George Spelvin ??:
> Nothing critical, but a bit of kibitzing.
> (That is slang in the Yiddish language for a person
> who offers annoying and unwanted advice.)
>
>> The binary GCD algorithm is based on the following facts:
>> 	1. If a and b are all evens, then gcd(a,b) = 2 * gcd(a/2, b/2)
>> 	2. If a is even and b is odd, then gcd(a,b) = gcd(a/2, b)
>> 	3. If a and b are all odds, then gcd(a,b) = gcd((a-b)/2, b) = gcd((a+b)/2, b)
> 1) "even" and "odd" are adjectives.  In English, adjectives to not have
>    plural suffixes.  Thus, "they are even" or "they are odd".
> 2) Although "all" is not exactly wrong, it sounds odd.  Since there are
>    exactly two of them it's clearer to say "both".
>
> If I also rephrase the last line to fit into 80 columns, you get:
>
>   The binary GCD algorithm is based on the following facts:
> - 	1. If a and b are all evens, then gcd(a,b) = 2 * gcd(a/2, b/2)
> + 	1. If a and b are both even, then gcd(a,b) = 2 * gcd(a/2, b/2)
>  	2. If a is even and b is odd, then gcd(a,b) = gcd(a/2, b)
> -	3. If a and b are all odds, then gcd(a,b) = gcd((a-b)/2, b) = gcd((a+b)/2, b)
> +	3. If both are odd, then gcd(a,b) = gcd((a-b)/2, b) = gcd((a+b)/2, b)
>
> 3) Negative config options are always confusing.
>
> Would it be better to call it CONFIG_INEFFICIEBNT_FFS, or even simpler
> CONFIG_SLOW_FFS?
>
> Also, you're allowed to add "help" to a non-interactive config option,
> and some documentation might be useful.
> E.g.
>
> +config CPU_SLOW_FFS
> +	def_bool n
> +	help
> +	  If n, the CPU supports a fast __ffs (__builtin_ctz) operation,
> +	  either directly or via a short code sequence using a count
> +	  leading zeros or population count instruction.  If y, the
> +	  operation is emulated by slower software, such as an unrolled
> +	  binary search.
> +
> +	  This is purely an optimization option; the kernel
> +	  will function correctly regardless of how it is set.
> +

Thanks a lot.

> Your benchmark code doesn't have to have a separate code path if
> __x86_64__; rdtsc works on 32-bit code just as well.  paths.  And the
> way you subtract the end and start times is unnecessarily complicated.
> The C language guarantees that unsigned arithmetic simply wraps modulo
> 2^bits as expected.

rdsc works on x86, the other path is prepared for other architectures.

> Here are some more timings, with the same flags as your tests:
>
> First, 32 bit code:
> 		gcd0	gcd1	gcd2	gcd3	gcd4
> Ivy Bridge	3156	1192	1740	1160	1640	PASS
> AMD Phenom	7150	2564	2348	2975	2843	PASS
> Core 2		4176	2592	4164	2604	3900	PASS
> Pentium 4	11492	4784	7632	4852	6452	PASS
>
> And 64-bit (longer times becuase the inputs are larger):
> Ivy Bridge	10636	2496	3500	2432	3360	PASS
> AMD Phenom	19482	4058	6030	5001	6845	PASS
>
> Looking at those, I'm not sure how much better the gcd3/4 versions are
> than gcd1/2.  The difference seems pretty minor and sometimes negative.
>

The worst case of binary GCD is that one number is power of 2,
for example a is 0xffffffff (0xcccccccc for the "even/odd" variant) and b is 1.

The gcd3/4 versions can handle this properly.




From chunkeey at googlemail.com  Sun May  8 06:08:22 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Sun,  8 May 2016 15:08:22 +0200
Subject: [PATCH v8 1/3] gpio: dt-bindings: add wd,mbl-gpio bindings
In-Reply-To: <cover.1462543457.git.chunkeey@googlemail.com>
References: <cover.1462543457.git.chunkeey@googlemail.com>
Message-ID: <9bc9349d6e13d81c6200b0cd8fa20c76263043f6.1462543458.git.chunkeey@googlemail.com>

This patch adds the device tree bindings for the Western Digital's
MyBook Live memory-mapped GPIO controllers.

The gpios will be supported by gpio-mmio code of the
GPIO generic library.

Acked-by: Rob Herring <robh at kernel.org>
Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
---
 .../devicetree/bindings/gpio/wd,mbl-gpio.txt       | 38 ++++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt

diff --git a/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
new file mode 100644
index 0000000..038c3a6
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
@@ -0,0 +1,38 @@
+Bindings for the Western Digital's MyBook Live memory-mapped GPIO controllers.
+
+The Western Digital MyBook Live has two memory-mapped GPIO controllers.
+Both GPIO controller only have a single 8-bit data register, where GPIO
+state can be read and/or written.
+
+Required properties:
+	- compatible: should be "wd,mbl-gpio"
+	- reg-names: must contain
+		"dat" - data register
+	- reg: address + size pairs describing the GPIO register sets;
+		order must correspond with the order of entries in reg-names
+	- #gpio-cells: must be set to 2. The first cell is the pin number and
+			the second cell is used to specify the gpio polarity:
+			0 = active high
+			1 = active low
+	- gpio-controller: Marks the device node as a gpio controller.
+
+Optional properties:
+	- no-output: GPIOs are read-only.
+
+Examples:
+	gpio0: gpio0 at e0000000 {
+		compatible = "wd,mbl-gpio";
+		reg-names = "dat";
+		reg = <0xe0000000 0x1>;
+		#gpio-cells = <2>;
+		gpio-controller;
+	};
+
+	gpio1: gpio1 at e0100000 {
+		compatible = "wd,mbl-gpio";
+		reg-names = "dat";
+		reg = <0xe0100000 0x1>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		no-output;
+	};
-- 
2.8.1



From chunkeey at googlemail.com  Sun May  8 06:08:23 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Sun,  8 May 2016 15:08:23 +0200
Subject: [PATCH v8 2/3] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <cover.1462543457.git.chunkeey@googlemail.com>
References: <cover.1462543457.git.chunkeey@googlemail.com>
Message-ID: <535f785bf6116c0fb6f46afbb77e6d4bd3ef5f60.1462543458.git.chunkeey@googlemail.com>

From: ?lvaro Fern?ndez Rojas <noltari at gmail.com>

This patch adds support for defining memory-mapped GPIOs which
are compatible with the existing gpio-mmio interface. The generic
library provides support for many memory-mapped GPIO controllers
that are found in various on-board FPGA and ASIC solutions that
are used to control board's switches, LEDs, chip-selects,
Ethernet/USB PHY power, etc.

For setting GPIO's there are three configurations:
	1. single input/output register resource (named "dat"),
	2. set/clear pair (named "set" and "clr"),
	3. single output register resource and single input resource
	   ("set" and dat").

The configuration is detected by which resources are present.
For the single output register, this drives a 1 by setting a bit
and a zero by clearing a bit.  For the set clr pair, this drives
a 1 by setting a bit in the set register and clears it by setting
a bit in the clear register. The configuration is detected by
which resources are present.

For setting the GPIO direction, there are three configurations:
	a. simple bidirectional GPIOs that requires no configuration.
	b. an output direction register (named "dirout")
	   where a 1 bit indicates the GPIO is an output.
	c. an input direction register (named "dirin")
	   where a 1 bit indicates the GPIO is an input.

The first user for this binding is "wd,mbl-gpio".

Signed-off-by: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
---
 drivers/gpio/gpio-mmio.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 74 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 6c1cb3b..4b7b74c 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -61,6 +61,8 @@ o        `                     ~~~~\___/~~~~    ` controller in FPGA is ,.`
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
 #include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 static void bgpio_write8(void __iomem *reg, unsigned long data)
 {
@@ -569,6 +571,66 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
 	return devm_ioremap_resource(&pdev->dev, r);
 }
 
+#ifdef CONFIG_OF
+static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
+				     struct bgpio_pdata *pdata,
+				     unsigned long *flags)
+{
+	struct device *dev = &pdev->dev;
+	int err;
+
+	pdata->base = -1;
+
+	if (of_property_read_bool(dev->of_node, "no-output"))
+		*flags |= BGPIOF_NO_OUTPUT;
+
+	return 0;
+}
+
+#define ADD(_name, _func) { .compatible = _name, .data = _func }
+
+static const struct of_device_id bgpio_of_match[] = {
+	ADD("wd,mbl-gpio", bgpio_basic_mmio_parse_dt),
+	{ }
+};
+#undef ADD
+MODULE_DEVICE_TABLE(of, bgpio_of_match);
+
+static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
+					  unsigned long *flags)
+{
+	const int (*parse_dt)(struct platform_device *,
+			      struct bgpio_pdata *, unsigned long *);
+	const struct device_node *node = pdev->dev.of_node;
+	const struct of_device_id *of_id;
+	struct bgpio_pdata *pdata;
+	int err = -ENODEV;
+
+	of_id = of_match_node(bgpio_of_match, node);
+	if (!of_id)
+		return NULL;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata),
+			     GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	parse_dt = (const void *)of_id->data;
+	if (parse_dt)
+		err = parse_dt(pdev, pdata, flags);
+	if (err)
+		return ERR_PTR(err);
+
+	return pdata;
+}
+#else
+static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
+					  unsigned long *flags)
+{
+	return NULL;
+}
+#endif /* CONFIG_OF */
+
 static int bgpio_pdev_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -579,10 +641,19 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
 	void __iomem *dirout;
 	void __iomem *dirin;
 	unsigned long sz;
-	unsigned long flags = pdev->id_entry->driver_data;
+	unsigned long flags = 0;
 	int err;
 	struct gpio_chip *gc;
-	struct bgpio_pdata *pdata = dev_get_platdata(dev);
+	struct bgpio_pdata *pdata;
+
+	pdata = bgpio_parse_dt(pdev, &flags);
+	if (IS_ERR(pdata))
+		return PTR_ERR(pdata);
+
+	if (!pdata) {
+		pdata = dev_get_platdata(dev);
+		flags = pdev->id_entry->driver_data;
+	}
 
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
 	if (!r)
@@ -646,6 +717,7 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table);
 static struct platform_driver bgpio_driver = {
 	.driver = {
 		.name = "basic-mmio-gpio",
+		.of_match_table = of_match_ptr(bgpio_of_match),
 	},
 	.id_table = bgpio_id_table,
 	.probe = bgpio_pdev_probe,
-- 
2.8.1



From chunkeey at googlemail.com  Sun May  8 06:08:21 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Sun,  8 May 2016 15:08:21 +0200
Subject: [PATCH v8 0/3] gpio: add DT support for memory-mapped GPIOs
Message-ID: <cover.1462543457.git.chunkeey@googlemail.com>

This patch series adds device tree support for generic memory-mapped GPIOs.
The GPIO library already allows drivers and architecture support code to
reuse generic code for managing a GPIO chip. Currently, a developer has
to create a platform device "basic-mmio-gpio" and attach a bgpio_pdata
platform data structure to make use of it. However, for architectures
which rely on the device tree to enumerate devices, creating custom
platform devices is another extra step that can be avoided by having
direct support via a device tree binding.

I initially came across this patch [0] from ?lvaro Fern?ndez Rojas,
while looking for an easy way to add support for the GPIO of my
WD MyBook Live [1] (APM82181). His generic approach patch allowed
me to easily get the GPIO (and the connected LEDs, buttons, gpiohogs)
up and running. Even thought, Mr. Fernandez initially developed it
for his work on the brcm63xx [2].

The third patch (which can be applied at a later time) moves gpio-clps711x,
gpio-ge, gpio-moxart and gpio-ts4800 into gpio-mmio.c. The old driver files
and makefile entries have been removed. The Kconfig entries for these
drivers are kept for compatibility reasons.

And finally, the most important stat about the series:
	>>> 336 insertions(+), 380 deletions(-) <<<
	It still removes more lines than it adds!

Thanks!

[0] <https://patchwork.ozlabs.org/patch/422121/>
[1] <https://github.com/chunkeey/MBL-openwrt>
[2] <https://wiki.openwrt.org/doc/hardware/soc/soc.broadcom.bcm63xx>

changelog:

v7 -> v8:
	- removed ngpio property parser and most flags parsers
	- converted clps711x to switch case for GPIO
	- retained original Kconfig syms which now select GPIO_GENERIC_PLATFORM

v6 -> v7:
	- finally made a PATCH series (based on linux-gpio devel branch)
	- added Rob Herring's ACK to the dt bindings
	- cc'd clps711x, gpio-ge, moxart and ts4800 authors for driver
	  changes.

v5 -> v6:
	- rewrote bindings and driver patch to fit the wd,mbl-gpio
	- unified parser code for gpio-ge, gpio-moxart and gpio-ts4800
	- fixed gpio chip's base being overwritten with bogus "0"
	- fixed compat driver crash when reload gpio-generic.ko module
	- dropped already applied patches from the series
	- rebased code on linus' devel tree
	- moved dt bindings patch to the top of the series

v4 -> v5:
	- reverted rename of gpio-mmio.c back to gpio-generic.c
	- fixed Andy Shevchenko's comments
	- consolidated changes from clps711x, gpio-ge, gpio-moxart and
	  gpio-ts4800 into one patch.

v3 -> v4:
	- renamed gpio-generic.c to gpio-mmio.c
	- changed compat. string to "linux,gpio-mmio"
	- integrated Cirrus clps711x driver
	- integrated GE FGPA gpio-ge driver
	- integrated MOXA ART GPIO driver
	- integrated TS4800 gpio driver
	- reshuffled patches, reworded commits, fixed spelling errors, etc.

Christian Lamparter (2):
  gpio: dt-bindings: add wd,mbl-gpio bindings
  gpio: move clps711x, moxart, ts4800 and gpio-ge into gpio-mmio

?lvaro Fern?ndez Rojas (1):
  gpio: mmio: add DT support for memory-mapped GPIOs

 .../devicetree/bindings/gpio/wd,mbl-gpio.txt       |  38 +++
 drivers/gpio/Kconfig                               |  16 +-
 drivers/gpio/Makefile                              |   4 -
 drivers/gpio/gpio-clps711x.c                       |  91 -------
 drivers/gpio/gpio-ge.c                             | 114 --------
 drivers/gpio/gpio-mmio.c                           | 288 ++++++++++++++++++++-
 drivers/gpio/gpio-moxart.c                         |  84 ------
 drivers/gpio/gpio-ts4800.c                         |  81 ------
 8 files changed, 336 insertions(+), 380 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
 delete mode 100644 drivers/gpio/gpio-clps711x.c
 delete mode 100644 drivers/gpio/gpio-ge.c
 delete mode 100644 drivers/gpio/gpio-moxart.c
 delete mode 100644 drivers/gpio/gpio-ts4800.c

-- 
2.8.1



From chunkeey at googlemail.com  Sun May  8 06:08:24 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Sun,  8 May 2016 15:08:24 +0200
Subject: [PATCH v8 3/3] gpio: move clps711x, moxart,
 ts4800 and gpio-ge into gpio-mmio
In-Reply-To: <cover.1462543457.git.chunkeey@googlemail.com>
References: <cover.1462543457.git.chunkeey@googlemail.com>
Message-ID: <efef766cdc9fa45789a6bc40123618a8782a616c.1462543458.git.chunkeey@googlemail.com>

This patch integrates the GPIO drivers for the following
boards, SoCs, etc. into gpio-mmio:
 - CLPS711X SoCs
 - MOXA ART SoC
 - TS-4800 FPGA DIO blocks and compatibles
 - GPIO controllers found on some GE Single Board Computers

Cc: Alexander Shiyan <shc_work at mail.ru>
Cc: Julien Grossholtz <julien.grossholtz at savoirfairelinux.com>
Cc: Martyn Welch <martyn.welch at ge.com>
Cc: Jonas Jensen <jonas.jensen at gmail.com>
Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
---
 drivers/gpio/Kconfig         |  16 +++-
 drivers/gpio/Makefile        |   4 -
 drivers/gpio/gpio-clps711x.c |  91 -------------------
 drivers/gpio/gpio-ge.c       | 114 -----------------------
 drivers/gpio/gpio-mmio.c     | 212 +++++++++++++++++++++++++++++++++++++++++++
 drivers/gpio/gpio-moxart.c   |  84 -----------------
 drivers/gpio/gpio-ts4800.c   |  81 -----------------
 7 files changed, 224 insertions(+), 378 deletions(-)
 delete mode 100644 drivers/gpio/gpio-clps711x.c
 delete mode 100644 drivers/gpio/gpio-ge.c
 delete mode 100644 drivers/gpio/gpio-moxart.c
 delete mode 100644 drivers/gpio/gpio-ts4800.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a68d838..e4d1065 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -154,7 +154,7 @@ config GPIO_BRCMSTB
 config GPIO_CLPS711X
 	tristate "CLPS711X GPIO support"
 	depends on ARCH_CLPS711X || COMPILE_TEST
-	select GPIO_GENERIC
+	select GPIO_GENERIC_PLATFORM
 	help
 	  Say yes here to support GPIO on CLPS711X SoCs.
 
@@ -196,7 +196,7 @@ config GPIO_ETRAXFS
 config GPIO_GE_FPGA
 	bool "GE FPGA based GPIO"
 	depends on GE_FPGA
-	select GPIO_GENERIC
+	select GPIO_GENERIC_PLATFORM
 	help
 	  Support for common GPIO functionality provided on some GE Single Board
 	  Computers.
@@ -209,6 +209,14 @@ config GPIO_GENERIC_PLATFORM
 	tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
 	select GPIO_GENERIC
 	help
+	  Select this to support many generic memory-mapped GPIO controllers.
+
+	  This driver also includes support for the following GPIOs:
+	    CLPS711X SoCs
+	    MOXA ART SoC
+	    TS-4800 FPGA DIO blocks and compatibles.
+	    GPIOs found on some GE Single Board Computers.
+
 	  Say yes here to support basic platform_device memory-mapped GPIO controllers.
 
 config GPIO_GRGPIO
@@ -288,7 +296,7 @@ config GPIO_MM_LANTIQ
 config GPIO_MOXART
 	bool "MOXART GPIO support"
 	depends on ARCH_MOXART || COMPILE_TEST
-	select GPIO_GENERIC
+	select GPIO_GENERIC_PLATFORM
 	help
 	  Select this option to enable GPIO driver for
 	  MOXA ART SoC devices.
@@ -408,7 +416,7 @@ config GPIO_TS4800
 	tristate "TS-4800 DIO blocks and compatibles"
 	depends on OF_GPIO
 	depends on SOC_IMX51 || COMPILE_TEST
-	select GPIO_GENERIC
+	select GPIO_GENERIC_PLATFORM
 	help
 	  This driver support TS-4800 FPGA GPIO controllers.
 
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 991598e..d8d63ae 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -31,7 +31,6 @@ obj-$(CONFIG_GPIO_ATH79)	+= gpio-ath79.o
 obj-$(CONFIG_GPIO_BCM_KONA)	+= gpio-bcm-kona.o
 obj-$(CONFIG_GPIO_BRCMSTB)	+= gpio-brcmstb.o
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
-obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o
 obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o
 obj-$(CONFIG_GPIO_CRYSTAL_COVE)	+= gpio-crystalcove.o
 obj-$(CONFIG_GPIO_DA9052)	+= gpio-da9052.o
@@ -43,7 +42,6 @@ obj-$(CONFIG_GPIO_EM)		+= gpio-em.o
 obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o
 obj-$(CONFIG_GPIO_ETRAXFS)	+= gpio-etraxfs.o
 obj-$(CONFIG_GPIO_F7188X)	+= gpio-f7188x.o
-obj-$(CONFIG_GPIO_GE_FPGA)	+= gpio-ge.o
 obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o
 obj-$(CONFIG_GPIO_ICH)		+= gpio-ich.o
 obj-$(CONFIG_GPIO_IOP)		+= gpio-iop.o
@@ -68,7 +66,6 @@ obj-$(CONFIG_GPIO_MC9S08DZ60)	+= gpio-mc9s08dz60.o
 obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)	+= gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MM_LANTIQ)	+= gpio-mm-lantiq.o
-obj-$(CONFIG_GPIO_MOXART)	+= gpio-moxart.o
 obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSIC)		+= gpio-msic.o
@@ -107,7 +104,6 @@ obj-$(CONFIG_GPIO_TPS65218)	+= gpio-tps65218.o
 obj-$(CONFIG_GPIO_TPS6586X)	+= gpio-tps6586x.o
 obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
 obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
-obj-$(CONFIG_GPIO_TS4800)	+= gpio-ts4800.o
 obj-$(CONFIG_GPIO_TS5500)	+= gpio-ts5500.o
 obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
 obj-$(CONFIG_GPIO_TWL6040)	+= gpio-twl6040.o
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
deleted file mode 100644
index 5a69025..0000000
--- a/drivers/gpio/gpio-clps711x.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  CLPS711X GPIO driver
- *
- *  Copyright (C) 2012,2013 Alexander Shiyan <shc_work at mail.ru>
- *
- * 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.
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/gpio/driver.h>
-#include <linux/platform_device.h>
-
-static int clps711x_gpio_probe(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	void __iomem *dat, *dir;
-	struct gpio_chip *gc;
-	struct resource *res;
-	int err, id = np ? of_alias_get_id(np, "gpio") : pdev->id;
-
-	if ((id < 0) || (id > 4))
-		return -ENODEV;
-
-	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	dat = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dat))
-		return PTR_ERR(dat);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	dir = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dir))
-		return PTR_ERR(dir);
-
-	switch (id) {
-	case 3:
-		/* PORTD is inverted logic for direction register */
-		err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
-				 NULL, dir, 0);
-		break;
-	default:
-		err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
-				 dir, NULL, 0);
-		break;
-	}
-
-	if (err)
-		return err;
-
-	switch (id) {
-	case 4:
-		/* PORTE is 3 lines only */
-		gc->ngpio = 3;
-		break;
-	default:
-		break;
-	}
-
-	gc->base = id * 8;
-	gc->owner = THIS_MODULE;
-	platform_set_drvdata(pdev, gc);
-
-	return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
-}
-
-static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = {
-	{ .compatible = "cirrus,clps711x-gpio" },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, clps711x_gpio_ids);
-
-static struct platform_driver clps711x_gpio_driver = {
-	.driver	= {
-		.name		= "clps711x-gpio",
-		.of_match_table	= of_match_ptr(clps711x_gpio_ids),
-	},
-	.probe	= clps711x_gpio_probe,
-};
-module_platform_driver(clps711x_gpio_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Alexander Shiyan <shc_work at mail.ru>");
-MODULE_DESCRIPTION("CLPS711X GPIO driver");
-MODULE_ALIAS("platform:clps711x-gpio");
diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c
deleted file mode 100644
index 8650b29..0000000
--- a/drivers/gpio/gpio-ge.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Driver for GE FPGA based GPIO
- *
- * Author: Martyn Welch <martyn.welch at ge.com>
- *
- * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-/* TODO
- *
- * Configuration of output modes (totem-pole/open-drain)
- * Interrupt configuration - interrupts are always generated the FPGA relies on
- * the I/O interrupt controllers mask to stop them propergating
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/of_address.h>
-#include <linux/module.h>
-#include <linux/gpio/driver.h>
-
-#define GEF_GPIO_DIRECT		0x00
-#define GEF_GPIO_IN		0x04
-#define GEF_GPIO_OUT		0x08
-#define GEF_GPIO_TRIG		0x0C
-#define GEF_GPIO_POLAR_A	0x10
-#define GEF_GPIO_POLAR_B	0x14
-#define GEF_GPIO_INT_STAT	0x18
-#define GEF_GPIO_OVERRUN	0x1C
-#define GEF_GPIO_MODE		0x20
-
-static const struct of_device_id gef_gpio_ids[] = {
-	{
-		.compatible	= "gef,sbc610-gpio",
-		.data		= (void *)19,
-	}, {
-		.compatible	= "gef,sbc310-gpio",
-		.data		= (void *)6,
-	}, {
-		.compatible	= "ge,imp3a-gpio",
-		.data		= (void *)16,
-	},
-	{ }
-};
-MODULE_DEVICE_TABLE(of, gef_gpio_ids);
-
-static int __init gef_gpio_probe(struct platform_device *pdev)
-{
-	const struct of_device_id *of_id =
-		of_match_device(gef_gpio_ids, &pdev->dev);
-	struct gpio_chip *gc;
-	void __iomem *regs;
-	int ret;
-
-	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	regs = of_iomap(pdev->dev.of_node, 0);
-	if (!regs)
-		return -ENOMEM;
-
-	ret = bgpio_init(gc, &pdev->dev, 4, regs + GEF_GPIO_IN,
-			 regs + GEF_GPIO_OUT, NULL, NULL,
-			 regs + GEF_GPIO_DIRECT, BGPIOF_BIG_ENDIAN_BYTE_ORDER);
-	if (ret) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		goto err0;
-	}
-
-	/* Setup pointers to chip functions */
-	gc->label = devm_kstrdup(&pdev->dev, pdev->dev.of_node->full_name,
-				     GFP_KERNEL);
-	if (!gc->label) {
-		ret = -ENOMEM;
-		goto err0;
-	}
-
-	gc->base = -1;
-	gc->ngpio = (u16)(uintptr_t)of_id->data;
-	gc->of_gpio_n_cells = 2;
-	gc->of_node = pdev->dev.of_node;
-
-	/* This function adds a memory mapped GPIO chip */
-	ret = devm_gpiochip_add_data(&pdev->dev, gc, NULL);
-	if (ret)
-		goto err0;
-
-	return 0;
-err0:
-	iounmap(regs);
-	pr_err("%s: GPIO chip registration failed\n",
-			pdev->dev.of_node->full_name);
-	return ret;
-};
-
-static struct platform_driver gef_gpio_driver = {
-	.driver = {
-		.name		= "gef-gpio",
-		.of_match_table	= gef_gpio_ids,
-	},
-};
-module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);
-
-MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
-MODULE_AUTHOR("Martyn Welch <martyn.welch at ge.com");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 4b7b74c..d1a7666 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -587,10 +587,222 @@ static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
 	return 0;
 }
 
+static int clps711x_parse_dt(struct platform_device *pdev,
+			     struct bgpio_pdata *pdata,
+			     unsigned long *flags)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	const char *dir_reg_name;
+	int id = np ? of_alias_get_id(np, "gpio") : pdev->id;
+
+	switch (id) {
+	case 0:
+	case 1:
+	case 2:
+		pdata->ngpio = 0; /* determined by register width */
+		dir_reg_name = "dirout";
+		break;
+	case 3:
+		pdata->ngpio = 0; /* determined by register width */
+		/* PORTD is inverted logic for direction register */
+		dir_reg_name = "dirin";
+		break;
+	case 4:
+		pdata->ngpio = 3; /* PORTE is 3 lines only */
+		dir_reg_name = "dirout";
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	pdata->base = id * 8;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+	if (!res->name || strcmp("dat", res->name))
+		res->name = devm_kstrdup(&pdev->dev, "dat", GFP_KERNEL);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -EINVAL;
+	if (!res->name || strcmp(dir_reg_name, res->name))
+		res->name = devm_kstrdup(&pdev->dev, dir_reg_name, GFP_KERNEL);
+
+	return 0;
+}
+
+static int ge_dt_cb(struct platform_device *pdev,
+		    struct bgpio_pdata *pdata,
+		    unsigned long *flags)
+{
+	struct device_node *np = pdev->dev.of_node;
+
+	pdata->label = devm_kstrdup(&pdev->dev, np->full_name, GFP_KERNEL);
+	if (!pdata->label)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int moxart_dt_cb(struct platform_device *pdev,
+			struct bgpio_pdata *pdata,
+			unsigned long *flags)
+{
+	pdata->base = 0;
+	pdata->label = "moxart-gpio";
+	return 0;
+}
+
+
+static int ts4800_dt_cb(struct platform_device *pdev,
+			struct bgpio_pdata *pdata,
+			unsigned long *flags)
+{
+	int err;
+
+	err = of_property_read_u32(pdev->dev.of_node, "ngpios", &pdata->ngpio);
+	if (err == -EINVAL) {
+		pdata->ngpio = 16;
+		return 0;
+	}
+
+	return err;
+}
+
+/*
+ * bgpio_init() needs up to five named mmio register resources.
+ * These currently are dat, set, clr, [dirout | dirin]. There
+ * is no particular order or predefined place for the entries.
+ * However, dirout and dirin are mutually exclusive.
+ */
+#define __NUM_COMPAT_OVERRIDE_MMIO_RESOURCES 4
+
+struct compat_gpio_device_data {
+	unsigned int expected_resource_size;
+	unsigned int ngpio;
+	resource_size_t register_width;
+	unsigned long flags;
+	int (*call_back)(struct platform_device *pdev,
+			 struct bgpio_pdata *pdata,
+			 unsigned long *flags);
+	struct resource_replacement {
+		resource_size_t start_offset;
+		const char *name;
+	} resources[__NUM_COMPAT_OVERRIDE_MMIO_RESOURCES];
+};
+#undef __NUM_COMPAT_OVERRIDE_MMIO_RESOURCES
+
+#define ADD_COMPAT_REGISTER(_name, _offset)	\
+	{ .name = (_name), .start_offset = (_offset) }
+
+#define ADD_COMPAT_GPIO(_comp, _sz, _ngpio, _width, _cb, _f, _res...)	\
+	{								\
+	  .compatible = (_comp),					\
+	  .data = &(struct compat_gpio_device_data) {			\
+		.expected_resource_size = (_sz),			\
+		.ngpio = (_ngpio),					\
+		.register_width = (_width),				\
+		.flags = (_f),						\
+		.call_back = (_cb),					\
+		.resources = { _res },					\
+	}								\
+}
+
+#define ADD_COMPAT_GE_GPIO(_name, _ngpio)				\
+	ADD_COMPAT_GPIO(_name, 0x24, _ngpio, 0x4, ge_dt_cb,		\
+		 BGPIOF_BIG_ENDIAN_BYTE_ORDER,				\
+		 ADD_COMPAT_REGISTER("dat", 0x04),			\
+		 ADD_COMPAT_REGISTER("set", 0x08),			\
+		 ADD_COMPAT_REGISTER("dirin", 0x00))			\
+
+static const struct of_device_id compat_gpio_devices[] = {
+	ADD_COMPAT_GE_GPIO("ge,imp3a-gpio", 16),
+	ADD_COMPAT_GE_GPIO("gef,sbc310-gpio", 6),
+	ADD_COMPAT_GE_GPIO("gef,sbc610-gpio", 19),
+	ADD_COMPAT_GPIO("moxa,moxart-gpio", 0xc, 0, 0x4, moxart_dt_cb,
+		 BGPIOF_READ_OUTPUT_REG_SET,
+		 ADD_COMPAT_REGISTER("dat", 0x04),
+		 ADD_COMPAT_REGISTER("set", 0x00),
+		 ADD_COMPAT_REGISTER("dirout", 0x08)),
+	ADD_COMPAT_GPIO("technologic,ts4800-gpio", 0x6, 16, 0x2, ts4800_dt_cb,
+		 0, ADD_COMPAT_REGISTER("dat", 0x00),
+		 ADD_COMPAT_REGISTER("set", 0x02),
+		 ADD_COMPAT_REGISTER("dirout", 0x04)),
+};
+
+#undef ADD_COMPAT_GE_GPIO
+#undef ADD_COMPAT_GPIO
+#undef ADD_COMPAT_REGISTER
+
+static int compat_parse_dt(struct platform_device *pdev,
+			   struct bgpio_pdata *pdata,
+			   unsigned long *flags)
+{
+	const struct device_node *node = pdev->dev.of_node;
+	const struct compat_gpio_device_data *entry;
+	const struct of_device_id *of_id;
+	struct resource *res;
+	int err;
+
+	of_id = of_match_node(compat_gpio_devices, node);
+	if (!of_id)
+		return -ENODEV;
+
+	entry = of_id->data;
+	if (!entry || !entry->resources[0].name)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	if (!res->name || strcmp(entry->resources[0].name, res->name)) {
+		struct resource nres[ARRAY_SIZE(entry->resources)];
+		size_t i;
+
+		if (resource_size(res) != entry->expected_resource_size)
+			return -EINVAL;
+
+		for (i = 0; i < ARRAY_SIZE(entry->resources); i++) {
+			if (!entry->resources[i].name)
+				continue;
+
+			nres[i].name = devm_kstrdup(&pdev->dev,
+				entry->resources[i].name, GFP_KERNEL);
+			nres[i].start = res->start +
+				entry->resources[i].start_offset;
+			nres[i].end = nres[i].start +
+				entry->register_width - 1;
+			nres[i].flags = IORESOURCE_MEM;
+		}
+
+		err = platform_device_add_resources(pdev, nres, i);
+		if (err)
+			return err;
+	}
+
+	pdata->base = -1;
+	pdata->ngpio = entry->ngpio;
+	*flags = entry->flags;
+
+	if (entry->call_back)
+		err = entry->call_back(pdev, pdata, flags);
+
+	return err;
+}
+
 #define ADD(_name, _func) { .compatible = _name, .data = _func }
 
 static const struct of_device_id bgpio_of_match[] = {
 	ADD("wd,mbl-gpio", bgpio_basic_mmio_parse_dt),
+	ADD("cirrus,clps711x-gpio", clps711x_parse_dt),
+	ADD("ge,imp3a-gpio", compat_parse_dt),
+	ADD("gef,sbc310-gpio", compat_parse_dt),
+	ADD("gef,sbc610-gpio", compat_parse_dt),
+	ADD("moxa,moxart-gpio", compat_parse_dt),
+	ADD("technologic,ts4800-gpio", compat_parse_dt),
 	{ }
 };
 #undef ADD
diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c
deleted file mode 100644
index d58d389..0000000
--- a/drivers/gpio/gpio-moxart.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * MOXA ART SoCs GPIO driver.
- *
- * Copyright (C) 2013 Jonas Jensen
- *
- * Jonas Jensen <jonas.jensen at gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/of_address.h>
-#include <linux/of_gpio.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/bitops.h>
-#include <linux/gpio/driver.h>
-
-#define GPIO_DATA_OUT		0x00
-#define GPIO_DATA_IN		0x04
-#define GPIO_PIN_DIRECTION	0x08
-
-static int moxart_gpio_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct resource *res;
-	struct gpio_chip *gc;
-	void __iomem *base;
-	int ret;
-
-	gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	ret = bgpio_init(gc, dev, 4, base + GPIO_DATA_IN,
-			 base + GPIO_DATA_OUT, NULL,
-			 base + GPIO_PIN_DIRECTION, NULL,
-			 BGPIOF_READ_OUTPUT_REG_SET);
-	if (ret) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		return ret;
-	}
-
-	gc->label = "moxart-gpio";
-	gc->request = gpiochip_generic_request;
-	gc->free = gpiochip_generic_free;
-	gc->base = 0;
-	gc->owner = THIS_MODULE;
-
-	ret = devm_gpiochip_add_data(dev, gc, NULL);
-	if (ret) {
-		dev_err(dev, "%s: gpiochip_add failed\n",
-			dev->of_node->full_name);
-		return ret;
-	}
-
-	return ret;
-}
-
-static const struct of_device_id moxart_gpio_match[] = {
-	{ .compatible = "moxa,moxart-gpio" },
-	{ }
-};
-
-static struct platform_driver moxart_gpio_driver = {
-	.driver	= {
-		.name		= "moxart-gpio",
-		.of_match_table	= moxart_gpio_match,
-	},
-	.probe	= moxart_gpio_probe,
-};
-builtin_platform_driver(moxart_gpio_driver);
diff --git a/drivers/gpio/gpio-ts4800.c b/drivers/gpio/gpio-ts4800.c
deleted file mode 100644
index 0c144a7..0000000
--- a/drivers/gpio/gpio-ts4800.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * GPIO driver for the TS-4800 board
- *
- * Copyright (c) 2016 - Savoir-faire Linux
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/gpio/driver.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-
-#define DEFAULT_PIN_NUMBER      16
-#define INPUT_REG_OFFSET        0x00
-#define OUTPUT_REG_OFFSET       0x02
-#define DIRECTION_REG_OFFSET    0x04
-
-static int ts4800_gpio_probe(struct platform_device *pdev)
-{
-	struct device_node *node;
-	struct gpio_chip *chip;
-	struct resource *res;
-	void __iomem *base_addr;
-	int retval;
-	u32 ngpios;
-
-	chip = devm_kzalloc(&pdev->dev, sizeof(struct gpio_chip), GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base_addr = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(base_addr))
-		return PTR_ERR(base_addr);
-
-	node = pdev->dev.of_node;
-	if (!node)
-		return -EINVAL;
-
-	retval = of_property_read_u32(node, "ngpios", &ngpios);
-	if (retval == -EINVAL)
-		ngpios = DEFAULT_PIN_NUMBER;
-	else if (retval)
-		return retval;
-
-	retval = bgpio_init(chip, &pdev->dev, 2, base_addr + INPUT_REG_OFFSET,
-			    base_addr + OUTPUT_REG_OFFSET, NULL,
-			    base_addr + DIRECTION_REG_OFFSET, NULL, 0);
-	if (retval) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		return retval;
-	}
-
-	chip->ngpio = ngpios;
-
-	platform_set_drvdata(pdev, chip);
-
-	return devm_gpiochip_add_data(&pdev->dev, chip, NULL);
-}
-
-static const struct of_device_id ts4800_gpio_of_match[] = {
-	{ .compatible = "technologic,ts4800-gpio", },
-	{},
-};
-
-static struct platform_driver ts4800_gpio_driver = {
-	.driver = {
-		   .name = "ts4800-gpio",
-		   .of_match_table = ts4800_gpio_of_match,
-		   },
-	.probe = ts4800_gpio_probe,
-};
-
-module_platform_driver_probe(ts4800_gpio_driver, ts4800_gpio_probe);
-
-MODULE_AUTHOR("Julien Grossholtz <julien.grossholtz at savoirfairelinux.com>");
-MODULE_DESCRIPTION("TS4800 FPGA GPIO driver");
-MODULE_LICENSE("GPL v2");
-- 
2.8.1



From andy.shevchenko at gmail.com  Sun May  8 06:19:34 2016
From: andy.shevchenko at gmail.com (Andy Shevchenko)
Date: Sun, 8 May 2016 16:19:34 +0300
Subject: [PATCH v8 0/3] gpio: add DT support for memory-mapped GPIOs
In-Reply-To: <cover.1462543457.git.chunkeey@googlemail.com>
References: <cover.1462543457.git.chunkeey@googlemail.com>
Message-ID: <CAHp75VdrbagU496qLjoUWMb7pWS3VyM4PDYwmyZFw52RgPs9=g@mail.gmail.com>

On Sun, May 8, 2016 at 4:08 PM, Christian Lamparter
<chunkeey at googlemail.com> wrote:
> This patch series adds device tree support for generic memory-mapped GPIOs.
> The GPIO library already allows drivers and architecture support code to
> reuse generic code for managing a GPIO chip. Currently, a developer has
> to create a platform device "basic-mmio-gpio" and attach a bgpio_pdata
> platform data structure to make use of it. However, for architectures
> which rely on the device tree to enumerate devices, creating custom
> platform devices is another extra step that can be avoided by having
> direct support via a device tree binding.
>
> I initially came across this patch [0] from ?lvaro Fern?ndez Rojas,
> while looking for an easy way to add support for the GPIO of my
> WD MyBook Live [1] (APM82181). His generic approach patch allowed
> me to easily get the GPIO (and the connected LEDs, buttons, gpiohogs)
> up and running. Even thought, Mr. Fernandez initially developed it
> for his work on the brcm63xx [2].
>
> The third patch (which can be applied at a later time) moves gpio-clps711x,
> gpio-ge, gpio-moxart and gpio-ts4800 into gpio-mmio.c. The old driver files
> and makefile entries have been removed. The Kconfig entries for these
> drivers are kept for compatibility reasons.
>
> And finally, the most important stat about the series:
>         >>> 336 insertions(+), 380 deletions(-) <<<
>         It still removes more lines than it adds!
>
> Thanks!
>
> [0] <https://patchwork.ozlabs.org/patch/422121/>
> [1] <https://github.com/chunkeey/MBL-openwrt>
> [2] <https://wiki.openwrt.org/doc/hardware/soc/soc.broadcom.bcm63xx>
>

FWIW:
Reviewed-by: Andy Shevchenko <andy.shevchenko at gmail.com>


> changelog:
>
> v7 -> v8:
>         - removed ngpio property parser and most flags parsers
>         - converted clps711x to switch case for GPIO
>         - retained original Kconfig syms which now select GPIO_GENERIC_PLATFORM
>
> v6 -> v7:
>         - finally made a PATCH series (based on linux-gpio devel branch)
>         - added Rob Herring's ACK to the dt bindings
>         - cc'd clps711x, gpio-ge, moxart and ts4800 authors for driver
>           changes.
>
> v5 -> v6:
>         - rewrote bindings and driver patch to fit the wd,mbl-gpio
>         - unified parser code for gpio-ge, gpio-moxart and gpio-ts4800
>         - fixed gpio chip's base being overwritten with bogus "0"
>         - fixed compat driver crash when reload gpio-generic.ko module
>         - dropped already applied patches from the series
>         - rebased code on linus' devel tree
>         - moved dt bindings patch to the top of the series
>
> v4 -> v5:
>         - reverted rename of gpio-mmio.c back to gpio-generic.c
>         - fixed Andy Shevchenko's comments
>         - consolidated changes from clps711x, gpio-ge, gpio-moxart and
>           gpio-ts4800 into one patch.
>
> v3 -> v4:
>         - renamed gpio-generic.c to gpio-mmio.c
>         - changed compat. string to "linux,gpio-mmio"
>         - integrated Cirrus clps711x driver
>         - integrated GE FGPA gpio-ge driver
>         - integrated MOXA ART GPIO driver
>         - integrated TS4800 gpio driver
>         - reshuffled patches, reworded commits, fixed spelling errors, etc.
>
> Christian Lamparter (2):
>   gpio: dt-bindings: add wd,mbl-gpio bindings
>   gpio: move clps711x, moxart, ts4800 and gpio-ge into gpio-mmio
>
> ?lvaro Fern?ndez Rojas (1):
>   gpio: mmio: add DT support for memory-mapped GPIOs
>
>  .../devicetree/bindings/gpio/wd,mbl-gpio.txt       |  38 +++
>  drivers/gpio/Kconfig                               |  16 +-
>  drivers/gpio/Makefile                              |   4 -
>  drivers/gpio/gpio-clps711x.c                       |  91 -------
>  drivers/gpio/gpio-ge.c                             | 114 --------
>  drivers/gpio/gpio-mmio.c                           | 288 ++++++++++++++++++++-
>  drivers/gpio/gpio-moxart.c                         |  84 ------
>  drivers/gpio/gpio-ts4800.c                         |  81 ------
>  8 files changed, 336 insertions(+), 380 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
>  delete mode 100644 drivers/gpio/gpio-clps711x.c
>  delete mode 100644 drivers/gpio/gpio-ge.c
>  delete mode 100644 drivers/gpio/gpio-moxart.c
>  delete mode 100644 drivers/gpio/gpio-ts4800.c
>
> --
> 2.8.1
>



-- 
With Best Regards,
Andy Shevchenko


From viro at ZenIV.linux.org.uk  Sun May  8 07:16:29 2016
From: viro at ZenIV.linux.org.uk (Al Viro)
Date: Sun, 8 May 2016 15:16:29 +0100
Subject: NFSroot hangs with bad unlock balance in Linux next
In-Reply-To: <20160505220344.GE5995@atomide.com>
References: <20160505220344.GE5995@atomide.com>
Message-ID: <20160508141629.GF2694@ZenIV.linux.org.uk>

On Thu, May 05, 2016 at 03:03:44PM -0700, Tony Lindgren wrote:
> Hi,
> 
> Looks like Linux next with NFSroot hangs for me at some point booting
> into init. Then after a while it produces "BUG: bad unlock balance
> detected!".
> 
> This happens at least with omap5-uevm and igepv5. Not sure yet if it
> also happens on other boards, the ones I'm seeing it happen both have
> USB Ethernet controller. They usually hang after the system starts
> being idle some tens of seconds into booting.
> 
> I tried to bisect it down with no luck. I do have the following
> trace, does that provide any clues?

> kworker/0:2/112 is trying to release lock (&nfsi->rmdir_sem) at:
> [<c03a7f98>] nfs_async_unlink_release+0x20/0x68
> but there are no more locks to release!

Very strange.  We grab that rwsem at the entry into nfs_call_unlink()
and then either release it there and return or call nfs_do_call_unlink().
Which arranges for eventual call of nfs_async_unlink_release() (via
->rpc_release); nfs_async_unlink_release() releases the rwsem.  Nobody else
releases it (on the read side, that is).

The only kinda-sorta possibility I see here is that the inode we are
unlocking in that nfs_async_unlink_release() is not the one we'd locked
in nfs_call_unlink() that has lead to it.  That really shouldn't happen,
though...  Just to verify whether that's what we are hitting, could you
try to reproduce that thing with the patch below on top of -next and see
if it triggers any of those WARN_ON?

diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index d367b06..dbbb4c9 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -64,6 +64,10 @@ static void nfs_async_unlink_release(void *calldata)
 	struct dentry *dentry = data->dentry;
 	struct super_block *sb = dentry->d_sb;
 
+	if (WARN_ON(data->parent != dentry->d_parent) ||
+	    WARN_ON(data->parent_inode != dentry->d_parent->d_inode)) {
+		printk(KERN_ERR "WTF2[%pd4]", dentry);
+	}
 	up_read(&NFS_I(d_inode(dentry->d_parent))->rmdir_sem);
 	d_lookup_done(dentry);
 	nfs_free_unlinkdata(data);
@@ -114,7 +118,8 @@ static void nfs_do_call_unlink(struct nfs_unlinkdata *data)
 
 static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
 {
-	struct inode *dir = d_inode(dentry->d_parent);
+	struct dentry *parent = dentry->d_parent;
+	struct inode *dir = d_inode(parent);
 	struct dentry *alias;
 
 	down_read(&NFS_I(dir)->rmdir_sem);
@@ -152,6 +157,12 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
 		return ret;
 	}
 	data->dentry = alias;
+	data->parent = parent;
+	data->parent_inode = dir;
+	if (WARN_ON(parent != alias->d_parent) ||
+	    WARN_ON(dir != parent->d_inode)) {
+		printk(KERN_ERR "WTF1[%pd4]", alias);
+	}
 	nfs_do_call_unlink(data);
 	return 1;
 }
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index ee8491d..b01a7f1 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1471,6 +1471,8 @@ struct nfs_unlinkdata {
 	struct nfs_removeargs args;
 	struct nfs_removeres res;
 	struct dentry *dentry;
+	struct dentry *parent;
+	struct inode *parent_inode;
 	wait_queue_head_t wq;
 	struct rpc_cred	*cred;
 	struct nfs_fattr dir_attr;


From boris.brezillon at free-electrons.com  Wed May  4 02:35:55 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Wed, 4 May 2016 11:35:55 +0200
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop>
 <20160503185153.5cfddc32@bbrezillon>
 <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
Message-ID: <20160504113555.20f0c622@bbrezillon>

Hi Rob,

On Tue, 3 May 2016 14:11:04 -0500
Rob Herring <robh at kernel.org> wrote:

> On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
> <boris.brezillon at free-electrons.com> wrote:
> > Hi Rob,
> >
> > On Tue, 3 May 2016 11:40:19 -0500
> > Rob Herring <robh at kernel.org> wrote:
> >
> >> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:
> >> > The EBI (External Bus Interface) is used to access external peripherals
> >> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
> >> > Each device is assigned a CS line and an address range and can have its
> >> > own configuration (timings, access mode, bus width, ...).
> >> > This driver provides a generic DT binding to configure a device according
> >> > to its requirements.
> >> > For specific device controllers (like the NAND one) the SMC timings
> >> > should be configured by the controller driver through the matrix and smc
> >> > syscon regmaps.
> >> >
> >> > Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> >> > ---
> >> >  .../bindings/memory-controllers/atmel,ebi.txt      | 136 +++++++++++++++++++++
> >> >  1 file changed, 136 insertions(+)
> >> >  create mode 100644 Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> >> >
> >> > diff --git a/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> >> > new file mode 100644
> >> > index 0000000..a6dca5c
> >> > --- /dev/null
> >> > +++ b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> >> > @@ -0,0 +1,136 @@
> >> > +* Device tree bindings for Atmel EBI
> >> > +
> >> > +The External Bus Interface (EBI) controller is a bus where you can connect
> >> > +asynchronous (NAND, NOR, SRAM, ....) and synchronous memories (SDR/DDR SDRAMs).
> >> > +The EBI provides a glue-less interface to asynchronous memories through the SMC
> >> > +(Static Memory Controller).
> >> > +
> >> > +Required properties:
> >> > +
> >> > +- compatible:              "atmel,at91sam9260-ebi"
> >> > +                   "atmel,at91sam9261-ebi"
> >> > +                   "atmel,at91sam9263-ebi0"
> >> > +                   "atmel,at91sam9263-ebi1"
> >>
> >> What are the differences between 0 and 1?
> >
> > Because this SoC has 2 EBI busses with different capabilities.
> 
> Okay, correct answer. :)
> 
> [...]
> 
> >>
> >> > +                   of the memory region requested by the device.
> >> > +
> >> > +EBI bus configuration associated with specific chip-select will be defined in
> >> > +the configs subnode. This configs node will in turn contain several subnodes
> >> > +named config-<cs-id>, each of them containing the following properties.
> >>
> >> This is a bit unusual. Why not just part of the child device nodes?
> >
> > Oh, come on! I reworked the binding because Mark complained about the
> > previous binding which was doing exactly what you're suggesting. Can
> > you please be consistent in your reviews...
> 
> No, Mark and I both have our opinions. Which part of this patch
> explains the history?

Hm, it's in patch 1/2 (just dropped the cover letter, which might not
be such a good idea).

> If the revision history is not in the patch, I'm
> not looking at it.
> 
> My issue with it this way is that it has invented yet another way to
> describe timings. I would like to be consistent across external bus
> descriptions, but we're not very consistent to begin with though. The
> most common seems to be the way you first did it. But I agree that it
> is kind of screwy to have an intermediate node unless the controller
> itself has sub-blocks within it and is not the established way to
> describe a bus with chip selects. I would either put the properties
> directly in the child nodes (e.g. flash at 0,0) or put your config nodes
> in the device node. I'd call it timings instead of config, but that's
> just bikeshedding.

Well, it's not only describing timings (see atmel,bus-width,
atmel,byte-access-type, ...), but I'm fine with either names :).

> 
> memory-controller at 1000 {
>   ...
>   flash at 0,0 {
>     timings {
>       ...
>     };
>   };
> };

Okay. Mark, what do you think of this approach?

Note that one of my previous version was defining timings directly in
the EBI device node, and Arnd noted that doing so may cause problems
if one of the EBI property (or the config/timing node name) conflict
with the sub-device binding, which is why I decided to put the EBI
config definitions in a separate subnode.

> 
> >> > +
> >> > +Optional config-<cs-id> node properties:
> >> > +
> >> > +- atmel,bus-width:         width of the asynchronous device's data bus
> >> > +                           8, 16 or 32.
> >> > +                           Default to 8 when undefined.
> >> > +
> >> > +- atmel,byte-access-type   "write" or "select" (see Atmel datasheet).
> >> > +                           Default to "select" when undefined.
> >> > +
> >> > +- atmel,read-mode          "nrd" or "ncs".
> >> > +                           Default to "ncs" when undefined.
> >> > +
> >> > +- atmel,write-mode         "nwe" or "ncs".
> >> > +                           Default to "ncs" when undefined.
> >> > +
> >> > +- atmel,exnw-mode          "disabled", "frozen" or "ready".
> >> > +                           Default to "disabled" when undefined.
> >> > +
> >> > +- atmel,page-mode          enable page mode if present. The provided value
> >> > +                           defines the page size (supported values: 4, 8,
> >> > +                           16 and 32).
> >> > +
> >> > +- atmel,tdf-mode:          "normal" or "optimized". When set to
> >>
> >> This should be boolean.
> >
> > It was a formerly defined as a boolean, and when it's done like that we
> > have no way to identify whether the property was forgotten or
> > intentionally set to normal mode. What's the problem with this approach?
> 
> Only preference to use boolean when that is sufficient. With your
> argument, then we should never have booleans. You state that missing
> means "normal", not forgotten, so all these properties should be
> required with no default.
> 
> BTW, I debated the same thing on the other properties, but I could see
> them being expanded to a 3rd mode. I don't see that here though.

Well, another reason I switched to a string property is because I
implemented hardware readout in v4, and decided to retrieve the current
state from the hardware and only overload the config with what was
defined in the DT. In this case, if we move to a boolean property we
can't know whether the property is missing because we want to put the
bus in "normal" mode or because we want to keep this config unchanged
(keep the bootloader/bootstrap config).

This is not true in v5, so maybe we should go back to the boolean
atmel,tdf-optimized property.

Thanks,

Boris

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


From shankerd at codeaurora.org  Sun May  8 10:10:01 2016
From: shankerd at codeaurora.org (Shanker Donthineni)
Date: Sun, 8 May 2016 12:10:01 -0500
Subject: [PATCH] irqchip/gicv3-its: Implement two-level(indirect) device
 table support
In-Reply-To: <20160506152247.67d0881a@arm.com>
References: <1462542216-20952-1-git-send-email-shankerd@codeaurora.org>
 <20160506152247.67d0881a@arm.com>
Message-ID: <572F72E9.3060608@codeaurora.org>

Hi Marc,


On 05/06/2016 09:22 AM, Marc Zyngier wrote:
> Hi Shanker,
>
> Thanks for putting this together. Comments below:
>
> On Fri, 6 May 2016 08:43:36 -0500
> Shanker Donthineni <shankerd at codeaurora.org> wrote:
>
>> Since device IDs are extremely sparse, the single, a.k.a flat table is
>> not sufficient for the following two reasons.
>>
>> 1) According to ARM-GIC spec, ITS hw can access maximum of 256(pages)*
>>    64K(pageszie) bytes. In the best case, it supports upto DEVid=21
>>    sparse with minimum device table entry size 8bytes.
>>
>> 2) The maximum memory size that is possible without memblock depends on
>>    MAX_ORDER. 4MB on 4K page size kernel with default MAX_ORDER, so it
>>    supports DEVid range 19bits.
>>
>> The two-level device table feature brings us two advantages, the first
>> is a very high possibility of supporting upto 32bit sparse, and the
>> second one is the best utilization of memory allocation.
>>
>> The feature is enabled automatically during driver probe if the flat
>> table is not adequate and the hardware is capable of two-level table
>> walk.
>>
>> Signed-off-by: Shanker Donthineni <shankerd at codeaurora.org>
>> ---
>>
>> This patch is based on Marc Zyngier's branch https://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git/log/?h=irq/irqchip-4.7
>>
>>  drivers/irqchip/irq-gic-v3-its.c   | 109 ++++++++++++++++++++++++++++++++-----
>>  include/linux/irqchip/arm-gic-v3.h |   2 +
>>  2 files changed, 97 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
>> index 6bd881b..caeb105 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -55,13 +55,14 @@ struct its_collection {
>>  };
>>  
>>  /*
>> - * The ITS_BASER structure - contains memory information and cached
>> - * value of BASER register configuration.
>> + * The ITS_BASER structure - contains memory information, cached value
>> + * of BASER register configuration and ITS page size in bytes.
>>   */
>>  struct its_baser {
>>  	void		*base;
>>  	u64		val;
>>  	u32		order;
>> +	u32		psz;
>>  };
>>  
>>  /*
>> @@ -853,6 +854,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
>>  		u64 type = GITS_BASER_TYPE(val);
>>  		u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
>>  		int order = get_order(psz);
>> +		bool tried_indirect = false;
>> +		u64 indirect = 0;
>>  		int alloc_pages;
>>  		u64 tmp;
>>  		void *base;
>> @@ -877,11 +880,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
>>  			 */
>>  			order = max(get_order((1UL << ids) * entry_size),
>>  				    order);
>> -			if (order >= MAX_ORDER) {
>> +			if (order >= MAX_ORDER)
>>  				order = MAX_ORDER - 1;
>> -				pr_warn("%s: Device Table too large, reduce its page order to %u\n",
>> -					node_name, order);
>> -			}
>>  		}
>>  
>>  retry_alloc_baser:
>> @@ -889,8 +889,6 @@ retry_alloc_baser:
>>  		if (alloc_pages > GITS_BASER_PAGES_MAX) {
>>  			alloc_pages = GITS_BASER_PAGES_MAX;
>>  			order = get_order(GITS_BASER_PAGES_MAX * psz);
>> -			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
>> -				node_name, order, alloc_pages);
>>  		}
>>  
>>  		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
>> @@ -924,6 +922,7 @@ retry_baser:
>>  
>>  		val |= alloc_pages - 1;
>>  		its->tables[i].val = val;
>> +		its->tables[i].psz = psz;
>>  
>>  		writeq_relaxed(val, its->base + GITS_BASER + i * 8);
>>  		tmp = readq_relaxed(its->base + GITS_BASER + i * 8);
>> @@ -963,6 +962,49 @@ retry_baser:
>>  			}
>>  		}
>>  
>> +		/*
>> +		 * Attempt enabling Indirection table walk since we were unable
>> +		 * to allocate enough memory for flat device table to cover
>> +		 * whole DevID sparse that hw reporting, and ITS hardware has
>> +		 * capablity of supporting two-level table.
>> +		 */
>> +		if ((type == GITS_BASER_TYPE_DEVICE) &&
>> +		    (!tried_indirect) &&
>> +		    (PAGE_ORDER_TO_SIZE(order) < (entry_size << ids))) {
> Why not try to use indirect tables if they are available, irrespective
> of the size of the required allocation? From a memory usage point of
> view, it is likely to always be a gain, unless your id space is so
> small that it fits in a single page. And with PCIe, you know for sure
> that the ID space is extremely sparse, hence indirect tables are an
> immediate win.
>
> Do you see any value in using the indirect table as a last resort?
As such there is no strong reason other than saving one read
cycle penalty for accessing the second level table.

I need your advice, should I enable this feature always or
if the memory (ids * entry_size) requirement is more than
some threshold?


>> +
>> +			val |= GITS_BASER_INDIRECT;
>> +			writeq_relaxed(val, its->base + GITS_BASER + i * 8);
>> +			tmp = readq_relaxed(its->base + GITS_BASER + i * 8);
>> +			tried_indirect = true;
>> +
>> +			/* Does ITS HW supports Indirect table walk? */
>> +			if (!(tmp & GITS_BASER_INDIRECT)) {
>> +				pr_warn("%s: Device Table too large, reduce order to %u\n",
>> +					node_name, order);
>> +				goto retry_baser;
>> +			}
>> +
>> +			/*
>> +			 * According to GIC spec, the size of the Level2 table
>> +			 * is equal to ITS page size which is 'psz'. For
>> +			 * computing Level1 table1 size, subtract DevID bits
>> +			 * that covers Level2 table from 'ids' which is reported
>> +			 * by ITS hardware times Level1 table entry size 8bytes.
>> +			 *
>> +			 *   L2-DevIDs = ilog2(psz / entry_size)
>> +			 *      L1-DevIDs = ids (reported by HW) - L2-DevIDs
>> +			 * Table1 size = L1-DevIDs * 8Bytes
>> +			 */
>> +			ids -= ilog2(psz / entry_size);
>> +			order = get_order(GITS_LEVEL1_ENTRY_SIZE << ids);
>> +
>> +			/* Limit Level1 table size to MAX_ORDER-1 */
>> +			order = min(order, MAX_ORDER - 1);
>> +			indirect = GITS_BASER_INDIRECT;
>> +			its->tables[type].base = NULL;
>> +			goto retry_alloc_baser;
>> +		}
>> +
> Please take this opportunity to split this function into something
> manageable. It is really getting out of control. Something to directly
> deal with the device table seems in order.

Sure, I'll post a separate patch for this change.
>>  		if (val != tmp) {
>>  			pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n",
>>  			       node_name, i,
>> @@ -971,10 +1013,12 @@ retry_baser:
>>  			goto out_free;
>>  		}
>>  
>> -		pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n",
>> -			(int)(PAGE_ORDER_TO_SIZE(order) / entry_size),
>> +		pr_info("ITS: allocated %d %s @%lx (%s, psz %dK, shr %d)\n",
>> +			(int)(PAGE_ORDER_TO_SIZE(order) /
>> +			(indirect ? GITS_LEVEL1_ENTRY_SIZE : entry_size)),
>>  			its_base_type_string[type],
>>  			(unsigned long)virt_to_phys(base),
>> +			indirect ? "indirect" : "flat",
>>  			psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
>>  	}
>>  
>> @@ -1149,6 +1193,46 @@ static struct its_device *its_find_device(struct its_node *its, u32 dev_id)
>>  	return its_dev;
>>  }
>>  
>> +static bool its_alloc_device_table(struct its_baser *baser, u32 dev_id)
>> +{
>> +	u32 entry_size = GITS_BASER_ENTRY_SIZE(baser->val);
>> +	u64 *table = baser->base;
>> +	struct page *page;
>> +	u32 psz = SZ_64K;
>> +	u32 idx;
>> +
>> +	/* Don't allow 'dev_id' that exceeds single, flat table limit */
>> +	if (!(baser->val & GITS_BASER_INDIRECT)) {
>> +		if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) / entry_size))
>> +			return false;
>> +		return true;
>> +	}
>> +
>> +	/* Compute Level1 table index & check if that exceeds table range */
>> +	idx = dev_id >> ilog2(baser->psz / entry_size);
>> +	if (idx >= (PAGE_ORDER_TO_SIZE(baser->order) / GITS_LEVEL1_ENTRY_SIZE))
>> +		return false;
>> +
>> +	/* Allocate memory for Level2 table */
>> +	if (!table[idx]) {
>> +		page = alloc_pages_exact(psz, GFP_KERNEL | __GFP_ZERO);
>> +		if (!page)
>> +			return false;
>> +
>> +		table[idx] = page_to_phys(page) | GITS_BASER_VALID;
> Be careful, this must be written in LE format. If you're running a BE
> kernel, you're in for a nasty surprise...

Sorry, I didn't think about breaking BE machines. I'll fix it.
>> +
>> +		/* Flush memory to PoC if hardware dosn't support coherency */
>> +		if (!(baser->val & GITS_BASER_SHAREABILITY_MASK)) {
>> +			__flush_dcache_area(table + idx, GITS_LEVEL1_ENTRY_SIZE);
>> +			__flush_dcache_area(page_address(page), psz);
>> +		}
>> +		/* Ensure updated table contents are visible to ITS hardware */
>> +		dsb(sy);
>> +	}
>> +
>> +	return true;
>> +}
>> +
>>  static struct its_baser *its_get_baser(struct its_node *its, u32 type)
>>  {
>>  	int i;
>> @@ -1176,11 +1260,8 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
>>  	int sz;
>>  
>>  	baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
>> -
>> -	/* Don't allow 'dev_id' that exceeds single, flat table limit */
>>  	if (baser) {
>> -		if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) /
>> -			      GITS_BASER_ENTRY_SIZE(baser->val)))
>> +		if (!its_alloc_device_table(baser, dev_id))
>>  			return NULL;
>>  	} else if (ilog2(dev_id) >= its->device_ids)
>>  		return NULL;
> Please fold these checks into its_alloc_device_table so that it takes
> an its_node as a first parameter instead of an its_baser. That will make
> the code a bit more readable.

I'll fix it in the next patch.
>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>> index 9e6fdd3..df404ea 100644
>> --- a/include/linux/irqchip/arm-gic-v3.h
>> +++ b/include/linux/irqchip/arm-gic-v3.h
>> @@ -187,6 +187,7 @@
>>  #define GITS_TYPER_PTA			(1UL << 19)
>>  
>>  #define GITS_CBASER_VALID		(1UL << 63)
>> +#define GITS_BASER_INDIRECT		(1UL << 62)
>>  #define GITS_CBASER_nCnB		(0UL << 59)
>>  #define GITS_CBASER_nC			(1UL << 59)
>>  #define GITS_CBASER_RaWt		(2UL << 59)
>> @@ -238,6 +239,7 @@
>>  #define GITS_BASER_TYPE_RESERVED6	6
>>  #define GITS_BASER_TYPE_RESERVED7	7
>>  
>> +#define GITS_LEVEL1_ENTRY_SIZE		(8UL)
>>  /*
>>   * ITS commands
>>   */
>
> Thanks,
>
> 	M.

-- 
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project



From manabian at gmail.com  Sun May  8 10:17:13 2016
From: manabian at gmail.com (Joachim Eastwood)
Date: Sun, 8 May 2016 19:17:13 +0200
Subject: [PATCH v8 2/3] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <535f785bf6116c0fb6f46afbb77e6d4bd3ef5f60.1462543458.git.chunkeey@googlemail.com>
References: <cover.1462543457.git.chunkeey@googlemail.com>
 <535f785bf6116c0fb6f46afbb77e6d4bd3ef5f60.1462543458.git.chunkeey@googlemail.com>
Message-ID: <CAGhQ9VyG6yX+g=FjfB6VP0pUNYGYXo60CHkWmSiiOisjeX20cg@mail.gmail.com>

Hi Christian,

On 8 May 2016 at 15:08, Christian Lamparter <chunkeey at googlemail.com> wrote:
> From: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
>
> This patch adds support for defining memory-mapped GPIOs which
> are compatible with the existing gpio-mmio interface. The generic
> library provides support for many memory-mapped GPIO controllers
> that are found in various on-board FPGA and ASIC solutions that
> are used to control board's switches, LEDs, chip-selects,
> Ethernet/USB PHY power, etc.
>
> For setting GPIO's there are three configurations:
>         1. single input/output register resource (named "dat"),
>         2. set/clear pair (named "set" and "clr"),
>         3. single output register resource and single input resource
>            ("set" and dat").
>
> The configuration is detected by which resources are present.
> For the single output register, this drives a 1 by setting a bit
> and a zero by clearing a bit.  For the set clr pair, this drives
> a 1 by setting a bit in the set register and clears it by setting
> a bit in the clear register. The configuration is detected by
> which resources are present.
>
> For setting the GPIO direction, there are three configurations:
>         a. simple bidirectional GPIOs that requires no configuration.
>         b. an output direction register (named "dirout")
>            where a 1 bit indicates the GPIO is an output.
>         c. an input direction register (named "dirin")
>            where a 1 bit indicates the GPIO is an input.
>
> The first user for this binding is "wd,mbl-gpio".
>
> Signed-off-by: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
> Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
> ---

> +#define ADD(_name, _func) { .compatible = _name, .data = _func }

I don't see the point in having a macro for such a simple data
structure, but since this v8 and Linus hasn't complained I guess it's
fine.

Using a macro here makes it impossible to grep for 'compatible'. Doing
'git grep compatible drivers/gpio/' is sometimes very useful to see
which hardware the driver actually supports.

> +static const struct of_device_id bgpio_of_match[] = {
> +       ADD("wd,mbl-gpio", bgpio_basic_mmio_parse_dt),
> +       { }
> +};
> +#undef ADD
> +MODULE_DEVICE_TABLE(of, bgpio_of_match);
> +
> +static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
> +                                         unsigned long *flags)
> +{
> +       const int (*parse_dt)(struct platform_device *,
> +                             struct bgpio_pdata *, unsigned long *);
> +       const struct device_node *node = pdev->dev.of_node;
> +       const struct of_device_id *of_id;
> +       struct bgpio_pdata *pdata;
> +       int err = -ENODEV;
> +
> +       of_id = of_match_node(bgpio_of_match, node);
> +       if (!of_id)
> +               return NULL;
> +
> +       pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata),
> +                            GFP_KERNEL);
> +       if (!pdata)
> +               return ERR_PTR(-ENOMEM);
> +
> +       parse_dt = (const void *)of_id->data;

You can retrieve OF match data using of_device_get_match_data(). Saves
you a couple of lines and better explains what your doing.


> +       if (parse_dt)
> +               err = parse_dt(pdev, pdata, flags);
> +       if (err)
> +               return ERR_PTR(err);
> +
> +       return pdata;
> +}


regards,
Joachim Eastwood


From serveralex at gmail.com  Sun May  8 10:59:48 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Sun,  8 May 2016 19:59:48 +0200
Subject: [PATCH] pinctrl: meson: Fix eth_tx_en bit index
Message-ID: <1462730389-10961-1-git-send-email-serveralex@gmail.com>

Fixes a bad bit index in preparation for ethernet support on ODROID-C1.

Alexander M?ller (1):
  pinctrl: meson: Fix eth_tx_en bit index

 drivers/pinctrl/meson/pinctrl-meson8b.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

-- 
2.5.0



From serveralex at gmail.com  Sun May  8 10:59:49 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Sun,  8 May 2016 19:59:49 +0200
Subject: [PATCH] pinctrl: meson: Fix eth_tx_en bit index
In-Reply-To: <1462730389-10961-1-git-send-email-serveralex@gmail.com>
References: <1462730389-10961-1-git-send-email-serveralex@gmail.com>
Message-ID: <1462730389-10961-2-git-send-email-serveralex@gmail.com>

Fix pinctrl eth_tx_en bit index according to Hardkernel ODROID-C1 datasheet.

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 drivers/pinctrl/meson/pinctrl-meson8b.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/meson/pinctrl-meson8b.c b/drivers/pinctrl/meson/pinctrl-meson8b.c
index a100bcf..874f2ed 100644
--- a/drivers/pinctrl/meson/pinctrl-meson8b.c
+++ b/drivers/pinctrl/meson/pinctrl-meson8b.c
@@ -564,7 +564,7 @@ static struct meson_pmx_group meson8b_cbus_groups[] = {
 	GROUP(eth_rx_clk,	6,	3),
 	GROUP(eth_txd0_1,	6,	4),
 	GROUP(eth_txd1_1,	6,	5),
-	GROUP(eth_tx_en,	6,	0),
+	GROUP(eth_tx_en,	6,	6),
 	GROUP(eth_ref_clk,	6,	8),
 	GROUP(eth_mdc,		6,	9),
 	GROUP(eth_mdio_en,	6,	10),
-- 
2.5.0



From maxime.ripard at free-electrons.com  Sun May  8 11:05:50 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun, 8 May 2016 20:05:50 +0200
Subject: [PATCH] drm: sun4i: fix probe error handling
In-Reply-To: <1462479061-893414-1-git-send-email-arnd@arndb.de>
References: <1462479061-893414-1-git-send-email-arnd@arndb.de>
Message-ID: <20160508180550.GB6167@lukather>

On Thu, May 05, 2016 at 10:10:52PM +0200, Arnd Bergmann wrote:
> gcc points out a possible uninitialized variable use in
> sun4i_dclk_create():
> 
> drivers/gpu/drm/sun4i/sun4i_dotclock.c: In function 'sun4i_dclk_create':
> drivers/gpu/drm/sun4i/sun4i_dotclock.c:139:12: error: 'clk_name' may be used uninitialized in this function [-Werror=maybe-uninitialized]
>   init.name = clk_name;
> 
> The warning only shows up when CONFIG_OF is disabled, and the
> property is never filled, but the same bug can show up even
> when CONFIG_OF is enabled but of_property_read_string_index
> returns another error.
> 
> To fix it, this ensures that sun4i_dclk_create propagates
> any error from of_property_read_string_index.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")

Applied, thanks

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160508/7d6efac6/attachment.sig>

From maxime.ripard at free-electrons.com  Sun May  8 11:09:41 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun, 8 May 2016 20:09:41 +0200
Subject: [PATCHv4] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <1462439332-26215-1-git-send-email-oliver@schinagl.nl>
References: <1462439332-26215-1-git-send-email-oliver@schinagl.nl>
Message-ID: <20160508180941.GC6167@lukather>

On Thu, May 05, 2016 at 11:08:52AM +0200, Olliver Schinagl wrote:
> There are 3 kinds of OLinuXino Lime2 boards.
> One without any on board storage, one with NAND storage and one with
> eMMC storage. This patch adds the eMMC variant of boards.
> 
> eMMC storage is different from a regular SD card in that it is soldered
> on the board and cannot be changed. Additionally, it shares pins with
> the NAND module and with the second SPI port.
> 
> Changeslog:
> 
> v4:
>   Add board compatibles
> 
> v3:
>   Add pwr-seq-emmc with the reset gpio
> 
> v2:
>   Remove unsupported no-1.8-v property, add vqmmc property
> 
> v1:
>   Initial bare bone version

This is not something we want in the commit log. This should go below
the --- so that it's dropped when applied.

Removed and applied.

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160508/9683f589/attachment.sig>

From chunkeey at googlemail.com  Sun May  8 11:27:24 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Sun, 08 May 2016 20:27:24 +0200
Subject: [PATCH v8 2/3] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <CAGhQ9VyG6yX+g=FjfB6VP0pUNYGYXo60CHkWmSiiOisjeX20cg@mail.gmail.com>
References: <cover.1462543457.git.chunkeey@googlemail.com>
 <535f785bf6116c0fb6f46afbb77e6d4bd3ef5f60.1462543458.git.chunkeey@googlemail.com>
 <CAGhQ9VyG6yX+g=FjfB6VP0pUNYGYXo60CHkWmSiiOisjeX20cg@mail.gmail.com>
Message-ID: <1946866.9Xyiz0Lzsg@debian64>

On Sunday, May 08, 2016 07:17:13 PM Joachim Eastwood wrote:
> > +#define ADD(_name, _func) { .compatible = _name, .data = _func }
> 
> I don't see the point in having a macro for such a simple data
> structure, but since this v8 and Linus hasn't complained I guess it's
> fine.
>
> Using a macro here makes it impossible to grep for 'compatible'. Doing
> 'git grep compatible drivers/gpio/' is sometimes very useful to see
> which hardware the driver actually supports.

Ok. I'll definitely picking it up. I'll wait until Tuesday/Wednesday
for more comments and then release a new series.
 
> > +static const struct of_device_id bgpio_of_match[] = {
> > +       ADD("wd,mbl-gpio", bgpio_basic_mmio_parse_dt),
> > +       { }
> > +};
> > +#undef ADD
> > +MODULE_DEVICE_TABLE(of, bgpio_of_match);
> > +
> > +static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
> > +                                         unsigned long *flags)
> > +{
[...]
> > +       of_id = of_match_node(bgpio_of_match, node);
> > +       if (!of_id)
> > +               return NULL;
[...]
> You can retrieve OF match data using of_device_get_match_data().
> Saves you a couple of lines and better explains what your doing.
Yes thanks that's useful too since I don't need the of_id variable
anymore.

Both improvements save a total of 8 lines. so it's 328 insertions(+)
vs 380 deletions(-).

Regards,
Christian


From krzk at kernel.org  Sun May  8 12:05:45 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:45 +0200
Subject: [PATCH v2 00/22] ARM: dts: exynos: Add initial support for Odroid XU
Message-ID: <1462734367-5619-1-git-send-email-krzk@kernel.org>


Hi,

Patchset adds necessary clocks, reorganizes existing stuff and finally
adds Odroid XU support.

Merging strategy
================
Complicated! The clock dt-bindings and driver changes can go to clock
tree. However there are three DTS patches in the middle.
a. This has to go in before adding "fin_pll_new" to clock driver:
   - [PATCH v2 03/22] ARM: dts: exynos: Add fin_pll node for clock driver

b. This should go in before renaming "fin_pll_new" back to original name:
   - [PATCH v2 05/22] ARM: dts: exynos: Switch MCT node to a new fin_pll clock
   - [PATCH v2 06/22] ARM: dts: exynos: Remove old fixed-clock provider on SMDK5410

The order of patches in the patchset is really how it should go in
to reduce any bisectability glitches.


Changes since v1
================
1. A lot of new patches.
2. Removed some TODO notes (eMMC 4.5 so no RCLK pin).
3. New clocks, more reorganization.
4. New common DTSI: exynos54xx.dtsi. I know, it is getting more
   and more complicated but this might help removing duplications
   and keeping everything under control.


Best regards,
Krzysztof


Krzysztof Kozlowski (22):
  dt-bindings: clock: Add license and reformat Exynos5410 clock IDs
  dt-bindings: clock: Add PWM and USB clock IDs to Exynos5410
  ARM: dts: exynos: Add fin_pll node for clock driver
  clk: samsung: exynos5410: Provide fin_pll external fixed clock
  ARM: dts: exynos: Switch MCT node to a new fin_pll clock
  ARM: dts: exynos: Remove old fixed-clock provider on SMDK5410
  clk: samsung: exynos5410: Rename fin_pll from temporary to regular
    name
  clk: samsung: exynos5410: Add serial3, USB and PWM clocks
  ARM: dts: exynos: Re-order alphabetically Exynos5420 SD0/SD1 pinctrl
    nodes
  ARM: dts: exynos: Use lowercase for Exynos5410 CPU node labels
  ARM: dts: exynos: Configure Exynos5410 pinctrl for eMMC and SD card
  ARM: dts: exynos: Split Odroid XU3 LEDs to separate DTSI
  ARM: dts: exynos: Move common nodes to exynos5.dtsi
  ARM: dts: exynos: Prepare for inclusion of exynos5.dtsi in
    exynos5410.dtsi
  ARM: dts: exynos: Use phandle to get parent node in exynos5250-snow
  ARM: dts: exynos: Move Exynos5250 and Exynos5420 nodes under soc
  ARM: dts: exynos: Include common exynos5 in exynos5410.dtsi
  ARM: dts: exynos: Enable UART3 on Exynos5410
  ARM: dts: exynos: MCT is not an interrupt controller and extend length
    of iomap
  ARM: dts: exynos: Move common Exynos5410/542x/5800 nodes to new DTSI
  ARM: dts: exynos: Add USB to Exynos5410
  ARM: dts: exynos: Add initial support for Odroid XU board

 .../bindings/arm/samsung/samsung-boards.txt        |    1 +
 arch/arm/boot/dts/Makefile                         |    1 +
 arch/arm/boot/dts/exynos5.dtsi                     |  171 +-
 arch/arm/boot/dts/exynos5250-snow-common.dtsi      |    2 +-
 arch/arm/boot/dts/exynos5250.dtsi                  | 1718 +++++++++--------
 arch/arm/boot/dts/exynos5410-odroidxu.dts          |  166 ++
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi          |   77 +
 arch/arm/boot/dts/exynos5410-smdk5410.dts          |   16 +-
 arch/arm/boot/dts/exynos5410.dtsi                  |  204 +-
 arch/arm/boot/dts/exynos5420-pinctrl.dtsi          |   12 +-
 arch/arm/boot/dts/exynos5420.dtsi                  | 1981 ++++++++++----------
 arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts    |   35 +-
 arch/arm/boot/dts/exynos5422-odroidxu3.dts         |   35 +-
 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi    |   50 +
 arch/arm/boot/dts/exynos54xx.dtsi                  |  142 ++
 drivers/clk/samsung/clk-exynos5410.c               |   52 +
 include/dt-bindings/clock/exynos5410.h             |   64 +-
 17 files changed, 2519 insertions(+), 2208 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos5410-odroidxu.dts
 create mode 100644 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
 create mode 100644 arch/arm/boot/dts/exynos54xx.dtsi

-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:46 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:46 +0200
Subject: [PATCH v2 01/22] dt-bindings: clock: Add license and reformat
 Exynos5410 clock IDs
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-2-git-send-email-krzk@kernel.org>

Add license and copyrights (file introduced in 2014) to header with
Exynos5410 clock IDs. Additionally reformat it to improve readability.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 include/dt-bindings/clock/exynos5410.h | 54 ++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 9b180f032e2d..213f19e02870 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -1,33 +1,43 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics 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.
+ *
+ * Device Tree binding constants for Exynos5421 clock controller.
+*/
+
 #ifndef _DT_BINDINGS_CLOCK_EXYNOS_5410_H
 #define _DT_BINDINGS_CLOCK_EXYNOS_5410_H
 
 /* core clocks */
-#define CLK_FIN_PLL 1
-#define CLK_FOUT_APLL 2
-#define CLK_FOUT_CPLL 3
-#define CLK_FOUT_MPLL 4
-#define CLK_FOUT_BPLL 5
-#define CLK_FOUT_KPLL 6
+#define CLK_FIN_PLL		1
+#define CLK_FOUT_APLL		2
+#define CLK_FOUT_CPLL		3
+#define CLK_FOUT_MPLL		4
+#define CLK_FOUT_BPLL		5
+#define CLK_FOUT_KPLL		6
 
 /* gate for special clocks (sclk) */
-#define CLK_SCLK_UART0 128
-#define CLK_SCLK_UART1 129
-#define CLK_SCLK_UART2 130
-#define CLK_SCLK_UART3 131
-#define CLK_SCLK_MMC0 132
-#define CLK_SCLK_MMC1 133
-#define CLK_SCLK_MMC2 134
+#define CLK_SCLK_UART0		128
+#define CLK_SCLK_UART1		129
+#define CLK_SCLK_UART2		130
+#define CLK_SCLK_UART3		131
+#define CLK_SCLK_MMC0		132
+#define CLK_SCLK_MMC1		133
+#define CLK_SCLK_MMC2		134
 
 /* gate clocks */
-#define CLK_UART0 257
-#define CLK_UART1 258
-#define CLK_UART2 259
-#define CLK_UART3 260
-#define CLK_MCT 315
-#define CLK_MMC0 351
-#define CLK_MMC1 352
-#define CLK_MMC2 353
+#define CLK_UART0		257
+#define CLK_UART1		258
+#define CLK_UART2		259
+#define CLK_UART3		260
+#define CLK_MCT			315
+#define CLK_MMC0		351
+#define CLK_MMC1		352
+#define CLK_MMC2		353
 
-#define CLK_NR_CLKS 512
+#define CLK_NR_CLKS		512
 
 #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5410_H */
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:47 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:47 +0200
Subject: [PATCH v2 02/22] dt-bindings: clock: Add PWM and USB clock IDs to
 Exynos5410
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-3-git-send-email-krzk@kernel.org>

Add IDs for PWM and USB clocks to Exynos5410. Use the same number as for
Exynos5420 just in case in future these drivers were merged.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 include/dt-bindings/clock/exynos5410.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 213f19e02870..34c8e96987a1 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 Krzysztof Kozlowski
  *
  * 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
@@ -27,16 +28,25 @@
 #define CLK_SCLK_MMC0		132
 #define CLK_SCLK_MMC1		133
 #define CLK_SCLK_MMC2		134
+#define CLK_SCLK_USBD300	150
+#define CLK_SCLK_USBD301	151
+#define CLK_SCLK_USBPHY300	152
+#define CLK_SCLK_USBPHY301	153
+#define CLK_SCLK_PWM		155
 
 /* gate clocks */
 #define CLK_UART0		257
 #define CLK_UART1		258
 #define CLK_UART2		259
 #define CLK_UART3		260
+#define CLK_PWM			279
 #define CLK_MCT			315
 #define CLK_MMC0		351
 #define CLK_MMC1		352
 #define CLK_MMC2		353
+#define CLK_USBH20		365
+#define CLK_USBD300		366
+#define CLK_USBD301		367
 
 #define CLK_NR_CLKS		512
 
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:48 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:48 +0200
Subject: [PATCH v2 03/22] ARM: dts: exynos: Add fin_pll node for clock driver
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-4-git-send-email-krzk@kernel.org>

For consistency between Exynos5410 and Exynos542x/5800 switch to similar
way of defining fin_pll/oscclk. Add a node early, before implementing
this in driver to preserve bisectability.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410-smdk5410.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts
index 0f6429e1b75c..d7d658deeff4 100644
--- a/arch/arm/boot/dts/exynos5410-smdk5410.dts
+++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts
@@ -31,6 +31,13 @@
 		#clock-cells = <0>;
 	};
 
+	fixed-rate-clocks {
+		oscclk {
+			compatible = "samsung,exynos5420-oscclk";
+			clock-frequency = <24000000>;
+		};
+	};
+
 	firmware at 02037000 {
 		compatible = "samsung,secure-firmware";
 		reg = <0x02037000 0x1000>;
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:49 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:49 +0200
Subject: [PATCH v2 04/22] clk: samsung: exynos5410: Provide fin_pll external
 fixed clock
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-5-git-send-email-krzk@kernel.org>

Just like clock driver for Exynos542x/5800, provide the fixed clock here
so the clock bindings and their consumers would be consistent and
similar.

However a clock named "fin_pll" is already provided by generic
fixed-clock and it is both referenced in the clock driver (by name) and
in DT (by phandle). To make the transition smooth, first introduce the
new external fixed clock here under temporary, different name and switch
internal users to it.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 drivers/clk/samsung/clk-exynos5410.c | 42 +++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 13 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index d5d5dcabc4a9..35f2cb36f7ef 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -59,23 +59,29 @@ enum exynos5410_plls {
 };
 
 /* list of all parent clocks */
-PNAME(apll_p)		= { "fin_pll", "fout_apll", };
-PNAME(bpll_p)		= { "fin_pll", "fout_bpll", };
-PNAME(cpll_p)		= { "fin_pll", "fout_cpll" };
-PNAME(mpll_p)		= { "fin_pll", "fout_mpll", };
-PNAME(kpll_p)		= { "fin_pll", "fout_kpll", };
+PNAME(apll_p)		= { "fin_pll_new", "fout_apll", };
+PNAME(bpll_p)		= { "fin_pll_new", "fout_bpll", };
+PNAME(cpll_p)		= { "fin_pll_new", "fout_cpll" };
+PNAME(mpll_p)		= { "fin_pll_new", "fout_mpll", };
+PNAME(kpll_p)		= { "fin_pll_new", "fout_kpll", };
 
 PNAME(mout_cpu_p)	= { "mout_apll", "sclk_mpll", };
 PNAME(mout_kfc_p)	= { "mout_kpll", "sclk_mpll", };
 
-PNAME(mpll_user_p)	= { "fin_pll", "sclk_mpll", };
-PNAME(bpll_user_p)	= { "fin_pll", "sclk_bpll", };
+PNAME(mpll_user_p)	= { "fin_pll_new", "sclk_mpll", };
+PNAME(bpll_user_p)	= { "fin_pll_new", "sclk_bpll", };
 PNAME(mpll_bpll_p)	= { "sclk_mpll_muxed", "sclk_bpll_muxed", };
 
-PNAME(group2_p)		= { "fin_pll", "fin_pll", "none", "none",
+PNAME(group2_p)		= { "fin_pll_new", "fin_pll_new", "none", "none",
 			"none", "none", "sclk_mpll_bpll",
 			 "none", "none", "sclk_cpll" };
 
+/* fixed rate clocks generated outside the soc */
+static struct samsung_fixed_rate_clock
+		exynos5x_fixed_rate_ext_clks[] __initdata = {
+	FRATE(CLK_FIN_PLL, "fin_pll_new", NULL, 0, 0),
+};
+
 static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
 	MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1),
 	MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
@@ -168,18 +174,24 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 };
 
 static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
-	[apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
+	[apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll_new", APLL_LOCK,
 		APLL_CON0, NULL),
-	[cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
+	[cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll_new", CPLL_LOCK,
 		CPLL_CON0, NULL),
-	[mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK,
+	[mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll_new", MPLL_LOCK,
 		MPLL_CON0, NULL),
-	[bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
+	[bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll_new", BPLL_LOCK,
 		BPLL_CON0, NULL),
-	[kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK,
+	[kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll_new", KPLL_LOCK,
 		KPLL_CON0, NULL),
 };
 
+/* Same as in Exynos5420 */
+static const struct of_device_id ext_clk_match[] __initconst = {
+	{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
+	{ },
+};
+
 /* register exynos5410 clocks */
 static void __init exynos5410_clk_init(struct device_node *np)
 {
@@ -192,6 +204,10 @@ static void __init exynos5410_clk_init(struct device_node *np)
 
 	ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
 
+	samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
+			ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
+			ext_clk_match);
+
 	samsung_clk_register_pll(ctx, exynos5410_plls,
 			ARRAY_SIZE(exynos5410_plls), reg_base);
 
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:50 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:50 +0200
Subject: [PATCH v2 05/22] ARM: dts: exynos: Switch MCT node to a new fin_pll
 clock
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-6-git-send-email-krzk@kernel.org>

The clk-exynos5410 driver now provides the "fin_pll" external fixed
clock. Switch the Multi-Core Timer to this clock.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 7a56aec2c5ba..233149abfb62 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -125,7 +125,7 @@
 			interrupts = <0>, <1>, <2>, <3>,
 				<4>, <5>, <6>, <7>,
 				<8>, <9>, <10>, <11>;
-			clocks = <&fin_pll>, <&clock CLK_MCT>;
+			clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
 			clock-names = "fin_pll", "mct";
 
 			interrupt_map: interrupt-map {
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:51 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:51 +0200
Subject: [PATCH v2 06/22] ARM: dts: exynos: Remove old fixed-clock provider on
 SMDK5410
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-7-git-send-email-krzk@kernel.org>

All "fin_pll" clock users are switched to the new one, provided by
Exynos5410 clock driver. Remove old DT node.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410-smdk5410.dts | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts
index d7d658deeff4..377a679b454b 100644
--- a/arch/arm/boot/dts/exynos5410-smdk5410.dts
+++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts
@@ -24,13 +24,6 @@
 		bootargs = "console=ttySAC2,115200";
 	};
 
-	fin_pll: xxti {
-		compatible = "fixed-clock";
-		clock-frequency = <24000000>;
-		clock-output-names = "fin_pll";
-		#clock-cells = <0>;
-	};
-
 	fixed-rate-clocks {
 		oscclk {
 			compatible = "samsung,exynos5420-oscclk";
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:52 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:52 +0200
Subject: [PATCH v2 07/22] clk: samsung: exynos5410: Rename fin_pll from
 temporary to regular name
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-8-git-send-email-krzk@kernel.org>

For smooth transition of fin_pll to clk-exynos5410.c from fixed-clock
driver, initially it was named "fin_pll_new". Fix this here.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 drivers/clk/samsung/clk-exynos5410.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index 35f2cb36f7ef..a7d714435307 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -59,27 +59,27 @@ enum exynos5410_plls {
 };
 
 /* list of all parent clocks */
-PNAME(apll_p)		= { "fin_pll_new", "fout_apll", };
-PNAME(bpll_p)		= { "fin_pll_new", "fout_bpll", };
-PNAME(cpll_p)		= { "fin_pll_new", "fout_cpll" };
-PNAME(mpll_p)		= { "fin_pll_new", "fout_mpll", };
-PNAME(kpll_p)		= { "fin_pll_new", "fout_kpll", };
+PNAME(apll_p)		= { "fin_pll", "fout_apll", };
+PNAME(bpll_p)		= { "fin_pll", "fout_bpll", };
+PNAME(cpll_p)		= { "fin_pll", "fout_cpll" };
+PNAME(mpll_p)		= { "fin_pll", "fout_mpll", };
+PNAME(kpll_p)		= { "fin_pll", "fout_kpll", };
 
 PNAME(mout_cpu_p)	= { "mout_apll", "sclk_mpll", };
 PNAME(mout_kfc_p)	= { "mout_kpll", "sclk_mpll", };
 
-PNAME(mpll_user_p)	= { "fin_pll_new", "sclk_mpll", };
-PNAME(bpll_user_p)	= { "fin_pll_new", "sclk_bpll", };
+PNAME(mpll_user_p)	= { "fin_pll", "sclk_mpll", };
+PNAME(bpll_user_p)	= { "fin_pll", "sclk_bpll", };
 PNAME(mpll_bpll_p)	= { "sclk_mpll_muxed", "sclk_bpll_muxed", };
 
-PNAME(group2_p)		= { "fin_pll_new", "fin_pll_new", "none", "none",
+PNAME(group2_p)		= { "fin_pll", "fin_pll", "none", "none",
 			"none", "none", "sclk_mpll_bpll",
 			 "none", "none", "sclk_cpll" };
 
 /* fixed rate clocks generated outside the soc */
 static struct samsung_fixed_rate_clock
 		exynos5x_fixed_rate_ext_clks[] __initdata = {
-	FRATE(CLK_FIN_PLL, "fin_pll_new", NULL, 0, 0),
+	FRATE(CLK_FIN_PLL, "fin_pll", NULL, 0, 0),
 };
 
 static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
@@ -174,15 +174,15 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 };
 
 static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
-	[apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll_new", APLL_LOCK,
+	[apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
 		APLL_CON0, NULL),
-	[cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll_new", CPLL_LOCK,
+	[cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
 		CPLL_CON0, NULL),
-	[mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll_new", MPLL_LOCK,
+	[mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK,
 		MPLL_CON0, NULL),
-	[bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll_new", BPLL_LOCK,
+	[bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
 		BPLL_CON0, NULL),
-	[kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll_new", KPLL_LOCK,
+	[kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK,
 		KPLL_CON0, NULL),
 };
 
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:53 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:53 +0200
Subject: [PATCH v2 08/22] clk: samsung: exynos5410: Add serial3,
 USB and PWM clocks
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-9-git-send-email-krzk@kernel.org>

Just like other Exynos5 family SoCs, this one has four UARTs. Add
missing UART3 clocks to the Exynso5410 clock driver.

Add clocks for USB and PWM.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 drivers/clk/samsung/clk-exynos5410.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index a7d714435307..40775f678f02 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -33,9 +33,11 @@
 #define SRC_CPERI1		0x4204
 #define DIV_TOP0		0x10510
 #define DIV_TOP1		0x10514
+#define DIV_FSYS0		0x10548
 #define DIV_FSYS1		0x1054c
 #define DIV_FSYS2		0x10550
 #define DIV_PERIC0		0x10558
+#define DIV_PERIC3		0x10564
 #define SRC_TOP0		0x10210
 #define SRC_TOP1		0x10214
 #define SRC_TOP2		0x10218
@@ -44,6 +46,8 @@
 #define SRC_MASK_FSYS		0x10340
 #define SRC_MASK_PERIC0		0x10350
 #define GATE_BUS_FSYS0		0x10740
+#define GATE_TOP_SCLK_FSYS	0x10840
+#define GATE_TOP_SCLK_PERIC	0x10850
 #define GATE_IP_FSYS		0x10944
 #define GATE_IP_PERIC		0x10950
 #define GATE_IP_PERIS		0x10960
@@ -71,6 +75,7 @@ PNAME(mout_kfc_p)	= { "mout_kpll", "sclk_mpll", };
 PNAME(mpll_user_p)	= { "fin_pll", "sclk_mpll", };
 PNAME(bpll_user_p)	= { "fin_pll", "sclk_bpll", };
 PNAME(mpll_bpll_p)	= { "sclk_mpll_muxed", "sclk_bpll_muxed", };
+PNAME(sclk_mpll_bpll_p)	= { "sclk_mpll_bpll", "fin_pll", };
 
 PNAME(group2_p)		= { "fin_pll", "fin_pll", "none", "none",
 			"none", "none", "sclk_mpll_bpll",
@@ -102,10 +107,14 @@ static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
 	MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4),
 	MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4),
 	MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4),
+	MUX(0, "mout_usbd300", sclk_mpll_bpll_p, SRC_FSYS, 28, 1),
+	MUX(0, "mout_usbd301", sclk_mpll_bpll_p, SRC_FSYS, 29, 1),
 
 	MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4),
 	MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4),
 	MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4),
+	MUX(0, "mout_uart3", group2_p, SRC_PERIC0, 12, 4),
+	MUX(0, "mout_pwm", group2_p, SRC_PERIC0, 24, 4),
 
 	MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1),
 	MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1),
@@ -127,6 +136,11 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 	DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3),
 	DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
 
+	DIV(0, "dout_usbphy300", "mout_usbd300", DIV_FSYS0, 16, 4),
+	DIV(0, "dout_usbphy301", "mout_usbd301", DIV_FSYS0, 20, 4),
+	DIV(0, "dout_usbd300", "mout_usbd300", DIV_FSYS0, 24, 4),
+	DIV(0, "dout_usbd301", "mout_usbd301", DIV_FSYS0, 28, 4),
+
 	DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
 	DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
 	DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
@@ -143,6 +157,8 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 	DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
 	DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
 
+	DIV(0, "dout_pwm", "mout_pwm", DIV_PERIC3, 0, 4),
+
 	DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
 	DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3),
 };
@@ -161,9 +177,23 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 	GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0),
 	GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0),
 
+	GATE(CLK_SCLK_USBPHY301, "sclk_usbphy301", "dout_usbphy301",
+	     GATE_TOP_SCLK_FSYS, 7, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_USBPHY300, "sclk_usbphy300", "dout_usbphy300",
+	     GATE_TOP_SCLK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_USBD300, "sclk_usbd300", "dout_usbd300",
+	     GATE_TOP_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_USBD301, "sclk_usbd301", "dout_usbd301",
+	     GATE_TOP_SCLK_FSYS, 10, CLK_SET_RATE_PARENT, 0),
+
+	GATE(CLK_SCLK_PWM, "sclk_pwm", "dout_pwm",
+	     GATE_TOP_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0),
+
 	GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
 	GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
 	GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
+	GATE(CLK_UART3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0),
+	GATE(CLK_PWM, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0),
 
 	GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
 			SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
@@ -171,6 +201,12 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 			SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
 			SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_UART3, "sclk_uart3", "div_uart3",
+			SRC_MASK_PERIC0, 12, CLK_SET_RATE_PARENT, 0),
+
+	GATE(CLK_USBH20, "usbh20", "aclk200_fsys", GATE_IP_FSYS, 18, 0, 0),
+	GATE(CLK_USBD300, "usbd300", "aclk200_fsys", GATE_IP_FSYS, 19, 0, 0),
+	GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_IP_FSYS, 20, 0, 0),
 };
 
 static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:54 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:54 +0200
Subject: [PATCH v2 09/22] ARM: dts: exynos: Re-order alphabetically Exynos5420
 SD0/SD1 pinctrl nodes
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-10-git-send-email-krzk@kernel.org>

The 'sd0_rclk' was put in the middle of SD1 nodes. Remove the confusion.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
index 130563b2ca95..14beb7e07323 100644
--- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
@@ -193,17 +193,17 @@
 		samsung,pin-drv = <3>;
 	};
 
-	sd1_clk: sd1-clk {
-		samsung,pins = "gpc1-0";
+	sd0_rclk: sd0-rclk {
+		samsung,pins = "gpc0-7";
 		samsung,pin-function = <2>;
-		samsung,pin-pud = <0>;
+		samsung,pin-pud = <1>;
 		samsung,pin-drv = <3>;
 	};
 
-	sd0_rclk: sd0-rclk {
-		samsung,pins = "gpc0-7";
+	sd1_clk: sd1-clk {
+		samsung,pins = "gpc1-0";
 		samsung,pin-function = <2>;
-		samsung,pin-pud = <1>;
+		samsung,pin-pud = <0>;
 		samsung,pin-drv = <3>;
 	};
 
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:55 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:55 +0200
Subject: [PATCH v2 10/22] ARM: dts: exynos: Use lowercase for Exynos5410 CPU
 node labels
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-11-git-send-email-krzk@kernel.org>

Fro consistency lowercase node labels are used.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 233149abfb62..58d3844ef923 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -35,28 +35,28 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		CPU0: cpu at 0 {
+		cpu0: cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU1: cpu at 1 {
+		cpu1: cpu at 1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x1>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU2: cpu at 2 {
+		cpu2: cpu at 2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x2>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU3: cpu at 3 {
+		cpu3: cpu at 3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x3>;
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:56 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:56 +0200
Subject: [PATCH v2 11/22] ARM: dts: exynos: Configure Exynos5410 pinctrl for
 eMMC and SD card
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-12-git-send-email-krzk@kernel.org>

Configure the pinctrl for MMC0 (eMMC) and MMC2 (microSD card).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 77 +++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
index f9aa6bb55464..72fc659d0637 100644
--- a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
@@ -277,6 +277,83 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
+
+	sd0_clk: sd0-clk {
+		samsung,pins = "gpc0-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cmd: sd0-cmd {
+		samsung,pins = "gpc0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cd: sd0-cd {
+		samsung,pins = "gpc0-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus1: sd0-bus-width1 {
+		samsung,pins = "gpc0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus4: sd0-bus-width4 {
+		samsung,pins = "gpc0-4", "gpc0-5", "gpc0-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus8: sd0-bus-width8 {
+		samsung,pins = "gpc3-0", "gpc3-1", "gpc3-2", "gpc3-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_clk: sd2-clk {
+		samsung,pins = "gpc2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cmd: sd2-cmd {
+		samsung,pins = "gpc2-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cd: sd2-cd {
+		samsung,pins = "gpc2-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus1: sd2-bus-width1 {
+		samsung,pins = "gpc2-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus4: sd2-bus-width4 {
+		samsung,pins = "gpc2-4", "gpc2-5", "gpc2-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
 };
 
 &pinctrl_1 {
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:57 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:57 +0200
Subject: [PATCH v2 12/22] ARM: dts: exynos: Split Odroid XU3 LEDs to separate
 DTSI
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-13-git-send-email-krzk@kernel.org>

The LED nodes can be shared between Odroid XU3, XU3-Lite and XU (not yet
added) thus removing duplication.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts | 35 +----------------
 arch/arm/boot/dts/exynos5422-odroidxu3.dts      | 35 +----------------
 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi | 50 +++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 68 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi

diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
index 2ae1cf41dcb6..03fa88c45426 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
@@ -14,44 +14,11 @@
 /dts-v1/;
 #include "exynos5422-odroidxu3-common.dtsi"
 #include "exynos5422-odroidxu3-audio.dtsi"
+#include "exynos54xx-odroidxu-leds.dtsi"
 
 / {
 	model = "Hardkernel Odroid XU3 Lite";
 	compatible = "hardkernel,odroid-xu3-lite", "samsung,exynos5800", "samsung,exynos5";
-
-	pwmleds {
-		compatible = "pwm-leds";
-
-		greenled {
-			label = "green:mmc0";
-			pwms = <&pwm 1 2000000 0>;
-			pwm-names = "pwm1";
-			/*
-			 * Green LED is much brighter than the others
-			 * so limit its max brightness
-			 */
-			max_brightness = <127>;
-			linux,default-trigger = "mmc0";
-		};
-
-		blueled {
-			label = "blue:heartbeat";
-			pwms = <&pwm 2 2000000 0>;
-			pwm-names = "pwm2";
-			max_brightness = <255>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-
-	gpioleds {
-		compatible = "gpio-leds";
-		redled {
-			label = "red:microSD";
-			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
-			default-state = "off";
-			linux,default-trigger = "mmc1";
-		};
-	};
 };
 
 &pwm {
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
index 432406db85de..9ed6564acfb0 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
@@ -13,44 +13,11 @@
 /dts-v1/;
 #include "exynos5422-odroidxu3-common.dtsi"
 #include "exynos5422-odroidxu3-audio.dtsi"
+#include "exynos54xx-odroidxu-leds.dtsi"
 
 / {
 	model = "Hardkernel Odroid XU3";
 	compatible = "hardkernel,odroid-xu3", "samsung,exynos5800", "samsung,exynos5";
-
-	pwmleds {
-		compatible = "pwm-leds";
-
-		greenled {
-			label = "green:mmc0";
-			pwms = <&pwm 1 2000000 0>;
-			pwm-names = "pwm1";
-			/*
-			 * Green LED is much brighter than the others
-			 * so limit its max brightness
-			 */
-			max_brightness = <127>;
-			linux,default-trigger = "mmc0";
-		};
-
-		blueled {
-			label = "blue:heartbeat";
-			pwms = <&pwm 2 2000000 0>;
-			pwm-names = "pwm2";
-			max_brightness = <255>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-
-	gpioleds {
-		compatible = "gpio-leds";
-		redled {
-			label = "red:microSD";
-			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
-			default-state = "off";
-			linux,default-trigger = "mmc1";
-		};
-	};
 };
 
 &i2c_0 {
diff --git a/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi b/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
new file mode 100644
index 000000000000..0ed30206625c
--- /dev/null
+++ b/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
@@ -0,0 +1,50 @@
+/*
+ * Hardkernel Odroid XU/XU3 LED device tree source
+ *
+ * Copyright (c) 2015,2016 Krzysztof Kozlowski
+ * Copyright (c) 2014 Collabora Ltd.
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	pwmleds {
+		compatible = "pwm-leds";
+
+		greenled {
+			label = "green:mmc0";
+			pwms = <&pwm 1 2000000 0>;
+			pwm-names = "pwm1";
+			/*
+			 * Green LED is much brighter than the others
+			 * so limit its max brightness
+			 */
+			max_brightness = <127>;
+			linux,default-trigger = "mmc0";
+		};
+
+		blueled {
+			label = "blue:heartbeat";
+			pwms = <&pwm 2 2000000 0>;
+			pwm-names = "pwm2";
+			max_brightness = <255>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	gpioleds {
+		compatible = "gpio-leds";
+		redled {
+			label = "red:microSD";
+			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "mmc1";
+		};
+	};
+};
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:58 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:58 +0200
Subject: [PATCH v2 13/22] ARM: dts: exynos: Move common nodes to exynos5.dtsi
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-14-git-send-email-krzk@kernel.org>

Exynos5420 and Exynos5250 share some nodes: the PWM and syscon
(sysreg_system_controller). Move them to parent DTSI to avoid
duplication.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5.dtsi    | 12 ++++++++++++
 arch/arm/boot/dts/exynos5250.dtsi | 19 +++++--------------
 arch/arm/boot/dts/exynos5420.dtsi | 19 +++++--------------
 3 files changed, 22 insertions(+), 28 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index d5c0f18a4223..fe901152f3ea 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -63,6 +63,11 @@
 		interrupts = <1 9 0xf04>;
 	};
 
+	sysreg_system_controller: syscon at 10050000 {
+		compatible = "samsung,exynos5-sysreg", "syscon";
+		reg = <0x10050000 0x5000>;
+	};
+
 	serial_0: serial at 12C00000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C00000 0x100>;
@@ -87,6 +92,13 @@
 		interrupts = <0 54 0>;
 	};
 
+	pwm: pwm at 12DD0000 {
+		compatible = "samsung,exynos4210-pwm";
+		reg = <0x12DD0000 0x100>;
+		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
+		#pwm-cells = <3>;
+	};
+
 	rtc: rtc at 101E0000 {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x101E0000 0x100>;
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index c7158b2fb213..6762faaf12a8 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -235,11 +235,6 @@
 		interrupt-parent = <&gic>;
 	};
 
-	sysreg_system_controller: syscon at 10050000 {
-		compatible = "samsung,exynos5-sysreg", "syscon";
-		reg = <0x10050000 0x5000>;
-	};
-
 	watchdog at 101D0000 {
 		compatible = "samsung,exynos5250-wdt";
 		reg = <0x101D0000 0x100>;
@@ -662,15 +657,6 @@
 		samsung,pmureg-phandle = <&pmu_system_controller>;
 	};
 
-	pwm: pwm at 12dd0000 {
-		compatible = "samsung,exynos4210-pwm";
-		reg = <0x12dd0000 0x100>;
-		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
-		#pwm-cells = <3>;
-		clocks = <&clock CLK_PWM>;
-		clock-names = "timers";
-	};
-
 	amba {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -1070,6 +1056,11 @@
 	iommus = <&sysmmu_fimd1>;
 };
 
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
+
 &rtc {
 	clocks = <&clock CLK_RTC>;
 	clock-names = "rtc";
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 4c8523471c65..f7322d87095f 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -542,15 +542,6 @@
 		status = "disabled";
 	};
 
-	pwm: pwm at 12dd0000 {
-		compatible = "samsung,exynos4210-pwm";
-		reg = <0x12dd0000 0x100>;
-		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
-		#pwm-cells = <3>;
-		clocks = <&clock CLK_PWM>;
-		clock-names = "timers";
-	};
-
 	dp_phy: dp-video-phy {
 		compatible = "samsung,exynos5420-dp-video-phy";
 		samsung,pmu-syscon = <&pmu_system_controller>;
@@ -823,11 +814,6 @@
 		interrupt-parent = <&gic>;
 	};
 
-	sysreg_system_controller: syscon at 10050000 {
-		compatible = "samsung,exynos5-sysreg", "syscon";
-		reg = <0x10050000 0x5000>;
-	};
-
 	tmu_cpu0: tmu at 10060000 {
 		compatible = "samsung,exynos5420-tmu";
 		reg = <0x10060000 0x100>;
@@ -1207,6 +1193,11 @@
 	iommu-names = "m0", "m1";
 };
 
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
+
 &rtc {
 	clocks = <&clock CLK_RTC>;
 	clock-names = "rtc";
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:05:59 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:05:59 +0200
Subject: [PATCH v2 14/22] ARM: dts: exynos: Prepare for inclusion of
 exynos5.dtsi in exynos5410.dtsi
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-15-git-send-email-krzk@kernel.org>

Add 'sromc' label to SROM memory controller in common exynos5.dtsi so it
can be referenced by inheriting DTSI.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index fe901152f3ea..7c83dc6ef972 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -31,7 +31,7 @@
 		reg = <0x10000000 0x100>;
 	};
 
-	memory-controller at 12250000 {
+	sromc: memory-controller at 12250000 {
 		compatible = "samsung,exynos4210-srom";
 		reg = <0x12250000 0x14>;
 	};
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:06:00 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:06:00 +0200
Subject: [PATCH v2 15/22] ARM: dts: exynos: Use phandle to get parent node in
 exynos5250-snow
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-16-git-send-email-krzk@kernel.org>

The i2c-arbitrator node in exynos5250-snow-common used absolute path to
reference other node (the i2c parent). Use phandle instead, because the
depth of the other node may be changed (like moving it under 'soc'
node).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5250-snow-common.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5250-snow-common.dtsi b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
index ddfe1f558c10..419d59da1751 100644
--- a/arch/arm/boot/dts/exynos5250-snow-common.dtsi
+++ b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
@@ -61,7 +61,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		i2c-parent = <&{/i2c at 12CA0000}>;
+		i2c-parent = <&i2c_4>;
 
 		our-claim-gpio = <&gpf0 3 GPIO_ACTIVE_LOW>;
 		their-claim-gpios = <&gpe0 4 GPIO_ACTIVE_LOW>;
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:06:02 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:06:02 +0200
Subject: [PATCH v2 17/22] ARM: dts: exynos: Include common exynos5 in
 exynos5410.dtsi
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-18-git-send-email-krzk@kernel.org>

The exynos5.dtsi is used for common nodes shared between Exynos5250 and
Exynos542x. Since Exynos5410 is very similar to Exynos5420 it can
include the common file as well to remove duplication and make
everything more consistent.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410-smdk5410.dts |   6 +-
 arch/arm/boot/dts/exynos5410.dtsi         | 103 ++++++++++--------------------
 2 files changed, 35 insertions(+), 74 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts
index 377a679b454b..501f776f327d 100644
--- a/arch/arm/boot/dts/exynos5410-smdk5410.dts
+++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts
@@ -102,14 +102,14 @@
 	};
 };
 
-&uart0 {
+&serial_0 {
 	status = "okay";
 };
 
-&uart1 {
+&serial_1 {
 	status = "okay";
 };
 
-&uart2 {
+&serial_2 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 58d3844ef923..c0540eb76271 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -14,6 +14,7 @@
  */
 
 #include "skeleton.dtsi"
+#include "exynos5.dtsi"
 #include "exynos-syscon-restart.dtsi"
 #include <dt-bindings/clock/exynos5410.h>
 
@@ -26,9 +27,6 @@
 		pinctrl1 = &pinctrl_1;
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
-		serial0 = &uart0;
-		serial1 = &uart1;
-		serial2 = &uart2;
 	};
 
 	cpus {
@@ -70,49 +68,6 @@
 		#size-cells = <1>;
 		ranges;
 
-		combiner: interrupt-controller at 10440000 {
-			compatible = "samsung,exynos4210-combiner";
-			#interrupt-cells = <2>;
-			interrupt-controller;
-			samsung,combiner-nr = <32>;
-			reg = <0x10440000 0x1000>;
-			interrupts =	<0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
-					<0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
-					<0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
-					<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
-					<0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-					<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
-					<0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-					<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
-		};
-
-		gic: interrupt-controller at 10481000 {
-			compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
-			#interrupt-cells = <3>;
-			interrupt-controller;
-			reg =	<0x10481000 0x1000>,
-				<0x10482000 0x1000>,
-				<0x10484000 0x2000>,
-				<0x10486000 0x2000>;
-			interrupts = <1 9 0xf04>;
-		};
-
-		chipid at 10000000 {
-			compatible = "samsung,exynos4210-chipid";
-			reg = <0x10000000 0x100>;
-		};
-
-		sromc: memory-controller at 12250000 {
-			compatible = "samsung,exynos4210-srom";
-			reg = <0x12250000 0x14>;
-			#address-cells = <2>;
-			#size-cells = <1>;
-			ranges = <0 0 0x04000000 0x20000
-				  1 0 0x05000000 0x20000
-				  2 0 0x06000000 0x20000
-				  3 0 0x07000000 0x20000>;
-		};
-
 		pmu_system_controller: system-controller at 10040000 {
 			compatible = "samsung,exynos5410-pmu", "syscon";
 			reg = <0x10040000 0x5000>;
@@ -236,34 +191,40 @@
 			reg = <0x03860000 0x1000>;
 			interrupts = <0 47 0>;
 		};
+	};
+};
 
-		uart0: serial at 12C00000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C00000 0x100>;
-			interrupts = <0 51 0>;
-			clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
 
-		uart1: serial at 12C10000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C10000 0x100>;
-			interrupts = <0 52 0>;
-			clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
+&serial_0 {
+	clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
+	clock-names = "uart", "clk_uart_baud0";
+};
 
-		uart2: serial at 12C20000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C20000 0x100>;
-			interrupts = <0 53 0>;
-			clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
-	};
+&serial_1 {
+	clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
+	clock-names = "uart", "clk_uart_baud0";
+};
+
+&serial_2 {
+	clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
+	clock-names = "uart", "clk_uart_baud0";
+};
+
+&serial_3 {
+	status = "disabled";
+};
+
+&sromc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	ranges = <0 0 0x04000000 0x20000
+		  1 0 0x05000000 0x20000
+		  2 0 0x06000000 0x20000
+		  3 0 0x07000000 0x20000>;
 };
 
 #include "exynos5410-pinctrl.dtsi"
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:06:03 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:06:03 +0200
Subject: [PATCH v2 18/22] ARM: dts: exynos: Enable UART3 on Exynos5410
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-19-git-send-email-krzk@kernel.org>

Just like other Exynos5 family SoCs, this one has four UARTs. Configure
clocks for UART3 and enable it.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index c0540eb76271..62dc3b4aef93 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -215,7 +215,8 @@
 };
 
 &serial_3 {
-	status = "disabled";
+	clocks = <&clock CLK_UART3>, <&clock CLK_SCLK_UART3>;
+	clock-names = "uart", "clk_uart_baud0";
 };
 
 &sromc {
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:06:04 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:06:04 +0200
Subject: [PATCH v2 19/22] ARM: dts: exynos: MCT is not an interrupt controller
 and extend length of iomap
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-20-git-send-email-krzk@kernel.org>

Multi-Core Timer generates interrupts but it is not really an interrupt
controller so remove the "interrupt-controller" and "interrupt-cells"
properties. Additionally extend the length of mapped memory to cover all
registers (last SFR is at 0x0A40).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5420.dtsi | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 3114cd6fb5d1..ac39e3b8b0e1 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -267,9 +267,7 @@
 
 		mct: mct at 101C0000 {
 			compatible = "samsung,exynos4210-mct";
-			reg = <0x101C0000 0x800>;
-			interrupt-controller;
-			#interrupt-cells = <1>;
+			reg = <0x101C0000 0xB00>;
 			interrupt-parent = <&mct_map>;
 			interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
 					<8>, <9>, <10>, <11>;
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:06:05 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:06:05 +0200
Subject: [PATCH v2 20/22] ARM: dts: exynos: Move common Exynos5410/542x/5800
 nodes to new DTSI
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-21-git-send-email-krzk@kernel.org>

The Exynos5410/542x/5800 are very similar designs. Create new new
DTSI with common nodes to remove DTS duplication. Although currently
only MCT and SysRAM are shared but in future more nodes will be added to
common file.

The patch should not have functional impact.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410.dtsi | 55 ++++---------------------------
 arch/arm/boot/dts/exynos5420.dtsi | 54 ++++---------------------------
 arch/arm/boot/dts/exynos54xx.dtsi | 68 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+), 97 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos54xx.dtsi

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 62dc3b4aef93..850343d3c2af 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -13,8 +13,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "skeleton.dtsi"
-#include "exynos5.dtsi"
+#include "exynos54xx.dtsi"
 #include "exynos-syscon-restart.dtsi"
 #include <dt-bindings/clock/exynos5410.h>
 
@@ -73,53 +72,6 @@
 			reg = <0x10040000 0x5000>;
 		};
 
-		mct: mct at 101C0000 {
-			compatible = "samsung,exynos4210-mct";
-			reg = <0x101C0000 0xB00>;
-			interrupt-parent = <&interrupt_map>;
-			interrupts = <0>, <1>, <2>, <3>,
-				<4>, <5>, <6>, <7>,
-				<8>, <9>, <10>, <11>;
-			clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
-			clock-names = "fin_pll", "mct";
-
-			interrupt_map: interrupt-map {
-				#interrupt-cells = <1>;
-				#address-cells = <0>;
-				#size-cells = <0>;
-				interrupt-map = <0 &combiner 23 3>,
-						<1 &combiner 23 4>,
-						<2 &combiner 25 2>,
-						<3 &combiner 25 3>,
-						<4 &gic 0 120 0>,
-						<5 &gic 0 121 0>,
-						<6 &gic 0 122 0>,
-						<7 &gic 0 123 0>,
-						<8 &gic 0 128 0>,
-						<9 &gic 0 129 0>,
-						<10 &gic 0 130 0>,
-						<11 &gic 0 131 0>;
-			};
-		};
-
-		sysram at 02020000 {
-			compatible = "mmio-sram";
-			reg = <0x02020000 0x54000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x02020000 0x54000>;
-
-			smp-sysram at 0 {
-				compatible = "samsung,exynos4210-sysram";
-				reg = <0x0 0x1000>;
-			};
-
-			smp-sysram at 53000 {
-				compatible = "samsung,exynos4210-sysram-ns";
-				reg = <0x53000 0x1000>;
-			};
-		};
-
 		clock: clock-controller at 10010000 {
 			compatible = "samsung,exynos5410-clock";
 			reg = <0x10010000 0x30000>;
@@ -194,6 +146,11 @@
 	};
 };
 
+&mct {
+	clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
+	clock-names = "fin_pll", "mct";
+};
+
 &pwm {
 	clocks = <&clock CLK_PWM>;
 	clock-names = "timers";
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index ac39e3b8b0e1..750571f838f2 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -13,9 +13,8 @@
  * published by the Free Software Foundation.
  */
 
+#include "exynos54xx.dtsi"
 #include <dt-bindings/clock/exynos5420.h>
-#include "exynos5.dtsi"
-
 #include <dt-bindings/clock/exynos-audss-clk.h>
 
 / {
@@ -185,24 +184,6 @@
 			};
 		};
 
-		sysram at 02020000 {
-			compatible = "mmio-sram";
-			reg = <0x02020000 0x54000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x02020000 0x54000>;
-
-			smp-sysram at 0 {
-				compatible = "samsung,exynos4210-sysram";
-				reg = <0x0 0x1000>;
-			};
-
-			smp-sysram at 53000 {
-				compatible = "samsung,exynos4210-sysram-ns";
-				reg = <0x53000 0x1000>;
-			};
-		};
-
 		clock: clock-controller at 10010000 {
 			compatible = "samsung,exynos5420-clock";
 			reg = <0x10010000 0x30000>;
@@ -265,34 +246,6 @@
 			status = "disabled";
 		};
 
-		mct: mct at 101C0000 {
-			compatible = "samsung,exynos4210-mct";
-			reg = <0x101C0000 0xB00>;
-			interrupt-parent = <&mct_map>;
-			interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
-					<8>, <9>, <10>, <11>;
-			clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
-			clock-names = "fin_pll", "mct";
-
-			mct_map: mct-map {
-				#interrupt-cells = <1>;
-				#address-cells = <0>;
-				#size-cells = <0>;
-				interrupt-map = <0 &combiner 23 3>,
-						<1 &combiner 23 4>,
-						<2 &combiner 25 2>,
-						<3 &combiner 25 3>,
-						<4 &gic 0 120 0>,
-						<5 &gic 0 121 0>,
-						<6 &gic 0 122 0>,
-						<7 &gic 0 123 0>,
-						<8 &gic 0 128 0>,
-						<9 &gic 0 129 0>,
-						<10 &gic 0 130 0>,
-						<11 &gic 0 131 0>;
-			};
-		};
-
 		gsc_pd: power-domain at 10044000 {
 			compatible = "samsung,exynos4210-pd";
 			reg = <0x10044000 0x20>;
@@ -1194,6 +1147,11 @@
 	iommu-names = "m0", "m1";
 };
 
+&mct {
+	clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
+	clock-names = "fin_pll", "mct";
+};
+
 &pwm {
 	clocks = <&clock CLK_PWM>;
 	clock-names = "timers";
diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi
new file mode 100644
index 000000000000..9ce625bd79c1
--- /dev/null
+++ b/arch/arm/boot/dts/exynos54xx.dtsi
@@ -0,0 +1,68 @@
+/*
+ * Samsung's Exynos54xx SoC series common device tree source
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2016 Krzysztof Kozlowski
+ *
+ * Device nodes common for Samsung Exynos5410/5420/5422/5800. Specific
+ * Exynos 54xx SoCs should include this file and customize it further
+ * (e.g. with clocks).
+ *
+ * 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 "skeleton.dtsi"
+#include "exynos5.dtsi"
+
+/ {
+	compatible = "samsung,exynos5";
+
+	soc: soc {
+		sysram at 02020000 {
+			compatible = "mmio-sram";
+			reg = <0x02020000 0x54000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x02020000 0x54000>;
+
+			smp-sysram at 0 {
+				compatible = "samsung,exynos4210-sysram";
+				reg = <0x0 0x1000>;
+			};
+
+			smp-sysram at 53000 {
+				compatible = "samsung,exynos4210-sysram-ns";
+				reg = <0x53000 0x1000>;
+			};
+		};
+
+		mct: mct at 101C0000 {
+			compatible = "samsung,exynos4210-mct";
+			reg = <0x101C0000 0xB00>;
+			interrupt-parent = <&mct_map>;
+			interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
+					<8>, <9>, <10>, <11>;
+
+			mct_map: mct-map {
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = <0 &combiner 23 3>,
+						<1 &combiner 23 4>,
+						<2 &combiner 25 2>,
+						<3 &combiner 25 3>,
+						<4 &gic 0 120 0>,
+						<5 &gic 0 121 0>,
+						<6 &gic 0 122 0>,
+						<7 &gic 0 123 0>,
+						<8 &gic 0 128 0>,
+						<9 &gic 0 129 0>,
+						<10 &gic 0 130 0>,
+						<11 &gic 0 131 0>;
+			};
+		};
+	};
+};
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:06:06 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:06:06 +0200
Subject: [PATCH v2 21/22] ARM: dts: exynos: Add USB to Exynos5410
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-22-git-send-email-krzk@kernel.org>

Move USB 3.0 DWC and 2.0 EHCI/OHCI nodes from exynos5420.dtsi to
exynos54xx.dtsi common for entire family. For Exynos542x/5800 this
should not have functional impact but for Exynos5410 this effectively
adds USB support.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>

---

TODO: lack of regulator causes errors:
	usb usb4-port1: over-current condition
?
---
 arch/arm/boot/dts/exynos5410.dtsi |  39 ++++++++++++
 arch/arm/boot/dts/exynos5420.dtsi | 131 ++++++++++++--------------------------
 arch/arm/boot/dts/exynos54xx.dtsi |  74 +++++++++++++++++++++
 3 files changed, 152 insertions(+), 92 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 850343d3c2af..dd4d6d752865 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -185,4 +185,43 @@
 		  3 0 0x07000000 0x20000>;
 };
 
+&usbdrd3_0 {
+	clocks = <&clock CLK_USBD300>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy0 {
+	clocks = <&clock CLK_USBD300>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbdrd3_1 {
+	clocks = <&clock CLK_USBD301>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy1 {
+	clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbhost1 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usbhost2 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usb2_phy {
+	clocks = <&clock CLK_USBH20>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,sysreg-phandle = <&sysreg_system_controller>;
+	samsung,pmureg-phandle = <&pmu_system_controller>;
+};
+
 #include "exynos5410-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 750571f838f2..ebf1dbec5070 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -829,98 +829,6 @@
 			clock-names = "secss";
 		};
 
-		usbdrd3_0: usb3-0 {
-			compatible = "samsung,exynos5250-dwusb3";
-			clocks = <&clock CLK_USBD300>;
-			clock-names = "usbdrd30";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
-
-			usbdrd_dwc3_0: dwc3 at 12000000 {
-				compatible = "snps,dwc3";
-				reg = <0x12000000 0x10000>;
-				interrupts = <0 72 0>;
-				phys = <&usbdrd_phy0 0>, <&usbdrd_phy0 1>;
-				phy-names = "usb2-phy", "usb3-phy";
-			};
-		};
-
-		usbdrd_phy0: phy at 12100000 {
-			compatible = "samsung,exynos5420-usbdrd-phy";
-			reg = <0x12100000 0x100>;
-			clocks = <&clock CLK_USBD300>, <&clock CLK_SCLK_USBPHY300>;
-			clock-names = "phy", "ref";
-			samsung,pmu-syscon = <&pmu_system_controller>;
-			#phy-cells = <1>;
-		};
-
-		usbdrd3_1: usb3-1 {
-			compatible = "samsung,exynos5250-dwusb3";
-			clocks = <&clock CLK_USBD301>;
-			clock-names = "usbdrd30";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
-
-			usbdrd_dwc3_1: dwc3 at 12400000 {
-				compatible = "snps,dwc3";
-				reg = <0x12400000 0x10000>;
-				interrupts = <0 73 0>;
-				phys = <&usbdrd_phy1 0>, <&usbdrd_phy1 1>;
-				phy-names = "usb2-phy", "usb3-phy";
-			};
-		};
-
-		usbdrd_phy1: phy at 12500000 {
-			compatible = "samsung,exynos5420-usbdrd-phy";
-			reg = <0x12500000 0x100>;
-			clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
-			clock-names = "phy", "ref";
-			samsung,pmu-syscon = <&pmu_system_controller>;
-			#phy-cells = <1>;
-		};
-
-		usbhost2: usb at 12110000 {
-			compatible = "samsung,exynos4210-ehci";
-			reg = <0x12110000 0x100>;
-			interrupts = <0 71 0>;
-
-			clocks = <&clock CLK_USBH20>;
-			clock-names = "usbhost";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			port at 0 {
-				reg = <0>;
-				phys = <&usb2_phy 1>;
-			};
-		};
-
-		usbhost1: usb at 12120000 {
-			compatible = "samsung,exynos4210-ohci";
-			reg = <0x12120000 0x100>;
-			interrupts = <0 71 0>;
-
-			clocks = <&clock CLK_USBH20>;
-			clock-names = "usbhost";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			port at 0 {
-				reg = <0>;
-				phys = <&usb2_phy 1>;
-			};
-		};
-
-		usb2_phy: phy at 12130000 {
-			compatible = "samsung,exynos5250-usb2-phy";
-			reg = <0x12130000 0x100>;
-			clocks = <&clock CLK_USBH20>, <&clock CLK_SCLK_USBPHY300>;
-			clock-names = "phy", "ref";
-			#phy-cells = <1>;
-			samsung,sysreg-phandle = <&sysreg_system_controller>;
-			samsung,pmureg-phandle = <&pmu_system_controller>;
-		};
-
 		sysmmu_g2dr: sysmmu at 0x10A60000 {
 			compatible = "samsung,exynos-sysmmu";
 			reg = <0x10A60000 0x1000>;
@@ -1184,4 +1092,43 @@
 	clock-names = "uart", "clk_uart_baud0";
 };
 
+&usbdrd3_0 {
+	clocks = <&clock CLK_USBD300>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy0 {
+	clocks = <&clock CLK_USBD300>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbdrd3_1 {
+	clocks = <&clock CLK_USBD301>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy1 {
+	clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbhost1 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usbhost2 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usb2_phy {
+	clocks = <&clock CLK_USBH20>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,sysreg-phandle = <&sysreg_system_controller>;
+	samsung,pmureg-phandle = <&pmu_system_controller>;
+};
+
 #include "exynos5420-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi
index 9ce625bd79c1..0f3b8735849e 100644
--- a/arch/arm/boot/dts/exynos54xx.dtsi
+++ b/arch/arm/boot/dts/exynos54xx.dtsi
@@ -64,5 +64,79 @@
 						<11 &gic 0 131 0>;
 			};
 		};
+
+		usbdrd3_0: usb3-0 {
+			compatible = "samsung,exynos5250-dwusb3";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			usbdrd_dwc3_0: dwc3 at 12000000 {
+				compatible = "snps,dwc3";
+				reg = <0x12000000 0x10000>;
+				interrupts = <0 72 0>;
+				phys = <&usbdrd_phy0 0>, <&usbdrd_phy0 1>;
+				phy-names = "usb2-phy", "usb3-phy";
+			};
+		};
+
+		usbdrd_phy0: phy at 12100000 {
+			compatible = "samsung,exynos5420-usbdrd-phy";
+			reg = <0x12100000 0x100>;
+			#phy-cells = <1>;
+		};
+
+		usbdrd3_1: usb3-1 {
+			compatible = "samsung,exynos5250-dwusb3";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			usbdrd_dwc3_1: dwc3 at 12400000 {
+				compatible = "snps,dwc3";
+				reg = <0x12400000 0x10000>;
+				interrupts = <0 73 0>;
+				phys = <&usbdrd_phy1 0>, <&usbdrd_phy1 1>;
+				phy-names = "usb2-phy", "usb3-phy";
+			};
+		};
+
+		usbdrd_phy1: phy at 12500000 {
+			compatible = "samsung,exynos5420-usbdrd-phy";
+			reg = <0x12500000 0x100>;
+			#phy-cells = <1>;
+		};
+
+		usbhost2: usb at 12110000 {
+			compatible = "samsung,exynos4210-ehci";
+			reg = <0x12110000 0x100>;
+			interrupts = <0 71 0>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port at 0 {
+				reg = <0>;
+				phys = <&usb2_phy 1>;
+			};
+		};
+
+		usbhost1: usb at 12120000 {
+			compatible = "samsung,exynos4210-ohci";
+			reg = <0x12120000 0x100>;
+			interrupts = <0 71 0>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port at 0 {
+				reg = <0>;
+				phys = <&usb2_phy 1>;
+			};
+		};
+
+		usb2_phy: phy at 12130000 {
+			compatible = "samsung,exynos5250-usb2-phy";
+			reg = <0x12130000 0x100>;
+			#phy-cells = <1>;
+		};
 	};
 };
-- 
2.5.0



From krzk at kernel.org  Sun May  8 12:06:07 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun,  8 May 2016 21:06:07 +0200
Subject: [PATCH v2 22/22] ARM: dts: exynos: Add initial support for Odroid XU
 board
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <1462734367-5619-23-git-send-email-krzk@kernel.org>

The Hardkernel's Odroid XU board was first design with big.LITTLE SoC
from Samsung: the Exynos5410. Comparing now to more popular Odroid XU3
the differences are:
1. Exynos5410 instead of 5422,
2. DisplayPort,
3. Main PMIC: Maxim 77802 instead of S2MPS11,
4. USB3503+LAN9730 instead of integrated LAN9514,
5. eMMC 4.5 instead of eMMC 5.0,

This patch adds initial support for the XU board with working basic
functions, eMMC/SD and USB (including attached ethernet adapter).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 .../bindings/arm/samsung/samsung-boards.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/exynos5410-odroidxu.dts          | 166 +++++++++++++++++++++
 3 files changed, 168 insertions(+)
 create mode 100644 arch/arm/boot/dts/exynos5410-odroidxu.dts

diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
index f5deace2b380..0ea7f14ef294 100644
--- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
+++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
@@ -47,6 +47,7 @@ Required root node properties:
 	- "hardkernel,odroid-u3"  - for Exynos4412-based Hardkernel Odroid U3.
 	- "hardkernel,odroid-x"   - for Exynos4412-based Hardkernel Odroid X.
 	- "hardkernel,odroid-x2"  - for Exynos4412-based Hardkernel Odroid X2.
+	- "hardkernel,odroid-xu"  - for Exynos5410-based Hardkernel Odroid XU.
 	- "hardkernel,odroid-xu3" - for Exynos5422-based Hardkernel Odroid XU3.
 	- "hardkernel,odroid-xu3-lite" - for Exynos5422-based Hardkernel
 					 Odroid XU3 Lite board.
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 5aeb10674370..9ed1c7abedb1 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -134,6 +134,7 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \
 	exynos5250-snow-rev5.dtb \
 	exynos5250-spring.dtb \
 	exynos5260-xyref5260.dtb \
+	exynos5410-odroidxu.dtb \
 	exynos5410-smdk5410.dtb \
 	exynos5420-arndale-octa.dtb \
 	exynos5420-peach-pit.dtb \
diff --git a/arch/arm/boot/dts/exynos5410-odroidxu.dts b/arch/arm/boot/dts/exynos5410-odroidxu.dts
new file mode 100644
index 000000000000..b0cbd53aeea9
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5410-odroidxu.dts
@@ -0,0 +1,166 @@
+/*
+ * Hardkernel Odroid XU3 board device tree source
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2016 Krzysztof Kozlowski
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include "exynos5410.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "exynos54xx-odroidxu-leds.dtsi"
+
+/ {
+	model = "Hardkernel Odroid XU";
+	compatible = "hardkernel,odroid-xu", "samsung,exynos5410", "samsung,exynos5";
+
+	memory {
+		reg = <0x40000000 0x7EA00000>;
+	};
+
+	chosen {
+		linux,stdout-path = &serial_2;
+	};
+
+	/* TODO: these will be the same as in XU3-common file */
+	emmc_pwrseq: pwrseq {
+		pinctrl-0 = <&emmc_nrst_pin>;
+		pinctrl-names = "default";
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpd1 0 GPIO_ACTIVE_LOW>;
+	};
+
+	fan0: pwm-fan {
+		compatible = "pwm-fan";
+		pwms = <&pwm 0 20972 0>;
+		cooling-min-state = <0>;
+		cooling-max-state = <3>;
+		#cooling-cells = <2>;
+		cooling-levels = <0 130 170 230>;
+	};
+
+	fixed-rate-clocks {
+		oscclk {
+			compatible = "samsung,exynos5420-oscclk";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	firmware at 02073000 {
+		compatible = "samsung,secure-firmware";
+		reg = <0x02073000 0x1000>;
+	};
+};
+
+/* TODO:
+&i2c_4 {
+	status = "okay";
+
+	ina231 at 40 {
+		compatible = "ti,ina231";
+		reg = <0x40>;
+		shunt-resistor = <10000>;
+	};
+
+	ina231 at 41 {
+		compatible = "ti,ina231";
+		reg = <0x41>;
+		shunt-resistor = <10000>;
+	};
+
+	ina231 at 44 {
+		compatible = "ti,ina231";
+		reg = <0x44>;
+		shunt-resistor = <10000>;
+	};
+
+	ina231 at 45 {
+		compatible = "ti,ina231";
+		reg = <0x45>;
+		shunt-resistor = <10000>;
+	};
+};
+*/
+
+&mmc_0 {
+	status = "okay";
+	mmc-pwrseq = <&emmc_pwrseq>;
+	cd-gpios = <&gpc0 2 GPIO_ACTIVE_LOW>;
+	card-detect-delay = <200>;
+	samsung,dw-mshc-ciu-div = <3>;
+	samsung,dw-mshc-sdr-timing = <0 4>;
+	samsung,dw-mshc-ddr-timing = <0 2>;
+	samsung,dw-mshc-hs400-timing = <0 2>;
+	samsung,read-strobe-delay = <90>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8 &sd0_cd>;
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
+	//vmmc-supply = <&ldo18_reg>; // FIXME
+	//vqmmc-supply = <&ldo3_reg>; // FIXME
+};
+
+&mmc_2 {
+	status = "okay";
+	card-detect-delay = <200>;
+	samsung,dw-mshc-ciu-div = <3>;
+	samsung,dw-mshc-sdr-timing = <0 4>;
+	samsung,dw-mshc-ddr-timing = <0 2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
+	bus-width = <4>;
+	cap-sd-highspeed;
+	//vmmc-supply = <&ldo19_reg>; // FIXME
+	//vqmmc-supply = <&ldo13_reg>; // Thats gonna be different than XU3 // FIXME
+};
+
+&pinctrl_0 {
+	emmc_nrst_pin: emmc-nrst {
+		samsung,pins = "gpd1-0";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+};
+
+&serial_0 {
+	status = "okay";
+};
+
+&serial_1 {
+	status = "okay";
+};
+
+&serial_2 {
+	status = "okay";
+};
+
+&serial_3 {
+	status = "okay";
+};
+
+&usbdrd_dwc3_0 {
+	dr_mode = "host";
+};
+
+&usbdrd_dwc3_1 {
+	dr_mode = "peripheral";
+};
+
+&usbdrd3_0 {
+//	vdd33-supply = <&ldo9_reg>;
+//	vdd10-supply = <&ldo11_reg>;
+};
+
+&usbdrd3_1 {
+//	vdd33-supply = <&ldo9_reg>;
+//	vdd10-supply = <&ldo11_reg>;
+};
-- 
2.5.0



From maxime.ripard at free-electrons.com  Sun May  8 12:09:48 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun, 8 May 2016 21:09:48 +0200
Subject: [PATCH v2] ARM: sun7i: dt: Add pll3 and pll7 clocks
In-Reply-To: <1462469944-27915-1-git-send-email-plaes@plaes.org>
References: <1462469944-27915-1-git-send-email-plaes@plaes.org>
Message-ID: <20160508190948.GD6167@lukather>

On Thu, May 05, 2016 at 08:39:04PM +0300, Priit Laes wrote:
> Enable pll3 and pll7 clocks that are needed by display clocks.
> 
> Signed-off-by: Priit Laes <plaes at plaes.org>

Applied, thanks

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160508/ea55844a/attachment.sig>

From maxime.ripard at free-electrons.com  Sun May  8 12:13:10 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun, 8 May 2016 21:13:10 +0200
Subject: [PATCH v3] sunxi-irq: Fix Kconfig dependency on GENERIC_IRQ_CHIP
In-Reply-To: <572B55CC.7080603@arm.com>
References: <1461546292-21110-1-git-send-email-andre.przywara@arm.com>
 <20160502064854.GL17159@lukather> <5729D2A0.70900@arm.com>
 <20160505132146.GH17159@lukather> <572B55CC.7080603@arm.com>
Message-ID: <20160508191310.GE6167@lukather>

On Thu, May 05, 2016 at 03:16:44PM +0100, Andre Przywara wrote:
> Hi Maxime,
> 
> On 05/05/16 14:21, Maxime Ripard wrote:
> > On Wed, May 04, 2016 at 11:44:48AM +0100, Andre Przywara wrote:
> >> Hi Maxime,
> >>
> >> On 02/05/16 07:48, Maxime Ripard wrote:
> >>> Hi,
> >>>
> >>> On Mon, Apr 25, 2016 at 02:04:52AM +0100, Andre Przywara wrote:
> >>>> The Allwinner NMI irqchip driver requires GENERIC_IRQ_CHIP, but
> >>>> we can't select it directly, because there is no specific Kconfig entry
> >>>> for the driver. Compiling this NMI driver with certain arm64
> >>>> configurations thus fails due to the missing dependency:
> >>>>
> >>>> drivers/built-in.o: In function `sunxi_sc_nmi_set_type':
> >>>> drivers/irqchip/irq-sunxi-nmi.c:114: undefined reference to `irq_setup_alt_chip'
> >>>> drivers/built-in.o: In function `irq_domain_add_linear':
> >>>> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
> >>>> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
> >>>> drivers/built-in.o: In function `sunxi_sc_nmi_irq_init':
> >>>> drivers/irqchip/irq-sunxi-nmi.c:146: undefined reference to `irq_alloc_domain_generic_chips'
> >>>> drivers/irqchip/irq-sunxi-nmi.c:161: undefined reference to `irq_get_domain_generic_chip'
> >>>> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
> >>>> drivers/irqchip/irq-sunxi-nmi.c:171: undefined reference to `irq_gc_mask_set_bit'
> >>>> drivers/irqchip/irq-sunxi-nmi.c:172: undefined reference to `irq_gc_ack_set_bit'
> >>>> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
> >>>>
> >>>> Add separate Kconfig options for both Allwinner specific irqchip
> >>>> drivers and select GENERIC_IRQ_CHIP for the NMI driver.
> >>>> The older sun4i IRQ driver only gets selected when support for these
> >>>> specific SoCs is compiled, while the NMI driver is selected for all
> >>>> Allwinner SoCs (copying the current behaviour and covering future SoCs
> >>>> automatically).
> >>>>
> >>>> Reported-by: Suzuki K Poulose <Suzuki.Poulose at arm.com>
> >>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >>>> ---
> >>>> Hi,
> >>>>
> >>>> this is a new approach to the problem that Suzuki tried to address
> >>>> already.
> >>>> It separates the sun4i IRQ controller driver and the NMI driver as
> >>>> Maxime requested.
> >>>> While there should be no difference for the NMI driver, the sun4i
> >>>> driver now only gets selected for certain SoCs, which is admittedly
> >>>> a bold call for -rc5. If people find this too risky, I can bring the
> >>>> sun4i in line with the NMI driver (selected for all ARCH_SUNXI) for
> >>>> this release and re-create the more selective dependency as a merge
> >>>> window patch, so that it gets more testing.
> >>>> Please let me know.
> >>>>
> >>>> Cheers,
> >>>> Andre.
> >>>>
> >>>>  arch/arm/mach-sunxi/Kconfig | 3 ++-
> >>>>  drivers/irqchip/Kconfig     | 8 ++++++++
> >>>>  drivers/irqchip/Makefile    | 4 ++--
> >>>>  3 files changed, 12 insertions(+), 3 deletions(-)
> >>>>
> >>>> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> >>>> index c124d65..c092bc2 100644
> >>>> --- a/arch/arm/mach-sunxi/Kconfig
> >>>> +++ b/arch/arm/mach-sunxi/Kconfig
> >>>> @@ -4,7 +4,6 @@ menuconfig ARCH_SUNXI
> >>>>  	select ARCH_REQUIRE_GPIOLIB
> >>>>  	select ARCH_HAS_RESET_CONTROLLER
> >>>>  	select CLKSRC_MMIO
> >>>> -	select GENERIC_IRQ_CHIP
> >>>>  	select PINCTRL
> >>>>  	select SUN4I_TIMER
> >>>>  	select RESET_CONTROLLER
> >>>> @@ -14,11 +13,13 @@ if ARCH_SUNXI
> >>>>  config MACH_SUN4I
> >>>>  	bool "Allwinner A10 (sun4i) SoCs support"
> >>>>  	default ARCH_SUNXI
> >>>> +	select SUN4I_IRQCHIP
> >>>>  
> >>>>  config MACH_SUN5I
> >>>>  	bool "Allwinner A10s / A13 (sun5i) SoCs support"
> >>>>  	default ARCH_SUNXI
> >>>>  	select SUN5I_HSTIMER
> >>>> +	select SUN4I_IRQCHIP
> >>>>  
> >>>>  config MACH_SUN6I
> >>>>  	bool "Allwinner A31 (sun6i) SoCs support"
> >>>> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> >>>> index 3e12479..94f3f42 100644
> >>>> --- a/drivers/irqchip/Kconfig
> >>>> +++ b/drivers/irqchip/Kconfig
> >>>> @@ -165,6 +165,14 @@ config ST_IRQCHIP
> >>>>  	help
> >>>>  	  Enables SysCfg Controlled IRQs on STi based platforms.
> >>>>  
> >>>> +config SUN4I_IRQCHIP
> >>>> +	bool
> >>>> +
> >>>> +config SUNXI_NMI
> >>>> +	bool "Allwinner SoC NMI controller"
> >>>> +	default ARCH_SUNXI
> >>>> +	select GENERIC_IRQ_CHIP
> >>>
> >>> This one is only used on SUN6I, SUN7I and SUN8I. There's no need to
> >>> enable it for all the SoCs.
> >>
> >> But it is enabled for all SoCs at the moment - and as it is actually a
> >> fix (-rc1 does not compile for certain arm64 configs) I'd really like to
> >> not take chances here.
> >> As mentioned I am happy to send a follow up patch to restrict it further
> >> - given that it gets more testing, but at the moment I'd really like to
> >> just fix the arm64 build without accidentally breaking existing arm(32)
> >> boards.
> > 
> > Then at least be consistent and do the same thing for the A10 irq
> > controller too.
> 
> Which is basically what Suzuki proposed with v2:
> https://lkml.org/lkml/2016/4/13/592

And I already told that this was the wrong approach back then. A month
down the road, we still have made no progress.

> This patch also has been acked by Marc, so can't we just take that for
> 4.6 and I'll send a patch on top of that to make a more fine grained
> selection for the next release?

I'm really not a fan of holding people hostage to get patches merged,
but yeah, go ahead. We're very close from the merge window now, so I
guess I won't even have a proper patch in 4.7... Great.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160508/c24a883e/attachment.sig>

From maxime.ripard at free-electrons.com  Sun May  8 13:01:36 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:36 +0200
Subject: [PATCH 01/16] clk: fix critical clock locking
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-2-git-send-email-maxime.ripard@free-electrons.com>

The critical clock handling in __clk_core_init isn't taking the enable lock
before calling clk_core_enable, which in turns triggers the warning in the
lockdep_assert_held call in that function when lockep is enabled.

Add the calls to clk_enable_lock/unlock to make sure it doesn't happen.

Fixes: 32b9b1096186 ("clk: Allow clocks to be marked as CRITICAL")
Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/clk.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index ce39add5a258..16a38df3c688 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2404,8 +2404,15 @@ static int __clk_core_init(struct clk_core *core)
 		core->ops->init(core->hw);
 
 	if (core->flags & CLK_IS_CRITICAL) {
+		unsigned long flags;
+
+		clk_prepare_lock();
 		clk_core_prepare(core);
+		clk_prepare_unlock();
+
+		flags = clk_enable_lock();
 		clk_core_enable(core);
+		clk_enable_unlock(flags);
 	}
 
 	kref_init(&core->ref);
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:39 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:39 +0200
Subject: [PATCH 04/16] clk: sunxi-ng: Add gate clock support
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-5-git-send-email-maxime.ripard@free-electrons.com>

Some clocks in the Allwinner SoCs clocks unit are just simple gates. Add
support for those clocks.

Since it's a feature that can also be found in more complex clocks, provide
a bunch of helpers that can be reused later on.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile   |  1 +
 drivers/clk/sunxi-ng/ccu_gate.c | 82 +++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_gate.h | 53 ++++++++++++++++++++++++++
 3 files changed, 136 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu_gate.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_gate.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index d76276736765..fc01127b3b45 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -2,3 +2,4 @@ obj-y += ccu_common.o
 obj-y += ccu_reset.o
 
 obj-y += ccu_fixed_factor.o
+obj-y += ccu_gate.o
diff --git a/drivers/clk/sunxi-ng/ccu_gate.c b/drivers/clk/sunxi-ng/ccu_gate.c
new file mode 100644
index 000000000000..1e98f8a33ac3
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_gate.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "ccu_gate.h"
+
+void ccu_gate_helper_disable(struct ccu_common *common, u32 gate)
+{
+	unsigned long flags;
+	u32 reg;
+
+	if (!(common->features & CCU_FEATURE_GATE))
+		return;
+
+	spin_lock_irqsave(common->lock, flags);
+
+	reg = readl(common->base + common->reg);
+	writel(reg & ~gate, common->base + common->reg);
+
+	spin_unlock_irqrestore(common->lock, flags);
+}
+
+static void ccu_gate_disable(struct clk_hw *hw)
+{
+	struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+	return ccu_gate_helper_disable(&cg->common, cg->enable);
+}
+
+int ccu_gate_helper_enable(struct ccu_common *common, u32 gate)
+{
+	unsigned long flags;
+	u32 reg;
+
+	if (!(common->features & CCU_FEATURE_GATE))
+		return 0;
+
+	spin_lock_irqsave(common->lock, flags);
+
+	reg = readl(common->base + common->reg);
+	writel(reg | gate, common->base + common->reg);
+
+	spin_unlock_irqrestore(common->lock, flags);
+
+	return 0;
+}
+
+static int ccu_gate_enable(struct clk_hw *hw)
+{
+	struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+	return ccu_gate_helper_enable(&cg->common, cg->enable);
+}
+
+int ccu_gate_helper_is_enabled(struct ccu_common *common, u32 gate)
+{
+	if (!(common->features & CCU_FEATURE_GATE))
+		return 1;
+
+	return readl(common->base + common->reg) & gate;
+}
+
+static int ccu_gate_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_gate *cg = hw_to_ccu_gate(hw);
+
+	return ccu_gate_helper_is_enabled(&cg->common, cg->enable);
+}
+
+const struct clk_ops ccu_gate_ops = {
+	.disable	= ccu_gate_disable,
+	.enable		= ccu_gate_enable,
+	.is_enabled	= ccu_gate_is_enabled,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_gate.h b/drivers/clk/sunxi-ng/ccu_gate.h
new file mode 100644
index 000000000000..8e15fa17bcc1
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_gate.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_GATE_H_
+#define _CCU_GATE_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+
+struct ccu_gate {
+	u32			enable;
+
+	struct ccu_common	common;
+};
+
+#define SUNXI_CCU_GATE(_struct, _name, _parent, _reg, _gate, _flags)	\
+	struct ccu_gate _struct = {					\
+		.enable	= _gate,					\
+		.common	= {						\
+			.reg		= _reg,				\
+			.features	= CCU_FEATURE_GATE,		\
+			.hw.init	= SUNXI_HW_INIT(_name,		\
+							_parent,	\
+							&ccu_gate_ops,	\
+							_flags),	\
+		}							\
+	}
+
+static inline struct ccu_gate *hw_to_ccu_gate(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_gate, common);
+}
+
+void ccu_gate_helper_disable(struct ccu_common *common, u32 gate);
+int ccu_gate_helper_enable(struct ccu_common *common, u32 gate);
+int ccu_gate_helper_is_enabled(struct ccu_common *common, u32 gate);
+
+extern const struct clk_ops ccu_gate_ops;
+
+#endif /* _CCU_GATE_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:38 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:38 +0200
Subject: [PATCH 03/16] clk: sunxi-ng: Add fixed factor clock support
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-4-git-send-email-maxime.ripard@free-electrons.com>

Some clocks in the Allwinner SoCs clock units are direct, fixed,
multipliers or dividers from their parent.

Add support for such clocks.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile           |  2 ++
 drivers/clk/sunxi-ng/ccu_fixed_factor.c | 42 +++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_fixed_factor.h | 50 +++++++++++++++++++++++++++++++++
 3 files changed, 94 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu_fixed_factor.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_fixed_factor.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index bd3461b0f38c..d76276736765 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -1,2 +1,4 @@
 obj-y += ccu_common.o
 obj-y += ccu_reset.o
+
+obj-y += ccu_fixed_factor.o
diff --git a/drivers/clk/sunxi-ng/ccu_fixed_factor.c b/drivers/clk/sunxi-ng/ccu_fixed_factor.c
new file mode 100644
index 000000000000..75df8a854db5
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_fixed_factor.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "ccu_fixed_factor.h"
+
+static unsigned long ccu_fixed_factor_recalc_rate(struct clk_hw *hw,
+						  unsigned long parent_rate)
+{
+	struct ccu_fixed_factor *fix = hw_to_ccu_fixed_factor(hw);
+
+	return parent_rate * fix->mult / fix->div;
+}
+
+static long ccu_fixed_factor_round_rate(struct clk_hw *hw,
+					unsigned long rate,
+					unsigned long *parent_rate)
+{
+	struct ccu_fixed_factor *fix = hw_to_ccu_fixed_factor(hw);
+
+	return *parent_rate / fix->div * fix->mult;
+}
+
+static int ccu_fixed_factor_set_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long parent_rate)
+{
+	return 0;
+}
+
+const struct clk_ops ccu_fixed_factor_ops = {
+	.recalc_rate	= ccu_fixed_factor_recalc_rate,
+	.round_rate	= ccu_fixed_factor_round_rate,
+	.set_rate	= ccu_fixed_factor_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_fixed_factor.h b/drivers/clk/sunxi-ng/ccu_fixed_factor.h
new file mode 100644
index 000000000000..4e53dbc9d10b
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_fixed_factor.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_FIXED_FACTOR_H_
+#define _CCU_FIXED_FACTOR_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+
+struct ccu_fixed_factor {
+	u16			div;
+	u16			mult;
+
+	struct ccu_common	common;
+};
+
+#define SUNXI_CCU_FIXED_FACTOR(_struct, _name, _parent,			\
+			       _div, _mult, _flags)			\
+	struct ccu_fixed_factor _struct = {				\
+		.div	= _div,						\
+		.mult	= _mult,					\
+		.common	= {						\
+			.hw.init	= SUNXI_HW_INIT(_name,		\
+							_parent,	\
+							&ccu_fixed_factor_ops, \
+							_flags),	\
+		},							\
+	}
+
+static inline struct ccu_fixed_factor *hw_to_ccu_fixed_factor(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_fixed_factor, common);
+}
+
+extern const struct clk_ops ccu_fixed_factor_ops;
+
+#endif /* _CCU_FIXED_FACTOR_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:35 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:35 +0200
Subject: [PATCH 00/16] clk: sunxi: introduce "modern" clock support
Message-ID: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>

Hi,

This is an attempt at introducing clock support for the Allwinner SoCs
following the current model used by pretty much all the other SoCs.

Such a conversion has been suggested on a regular basis by Mike and
Stephen, and here is a first implementation.

This new approach has a good number of advantages, some due to the new
binding itself, some due to the lessons learned with the current code
we have.

Beside from having a binding similar to the other SoCs, which helps
developper hopping from one SoC to the other, it also reduces the
amount of binding review that needs to be done, something that Rob
already complained about a few times.
Now that we are following the DT-as-an-ABI rule, the new binding will
also make our life way easier, since we reduce the exposed surface
greatly. The former binding, while making quite easy to mix and match
clocks when bringing up new SoCs, was also exposing way too much
implementation details that would hold us back when wanting to
refactor, consolidate, or fix some shortcomings in the current
implementation. In the new approach, the only thing that we're
exposing is the clock index, meaning that we can change the
implementation as much as we want.

This rewrite is also the occasion to layer things up quite differently
in our clock core.

The current code had a bunch of shortcomings. Most of the code was
relying on our clk-factor code, which was factoring away a few things
like the clock registration, ie boilerplate, but didn't factor the
logic to compute a clock rate, while the huge majority are computed
from some variation of a formula, which could actually be shared.

Which meant that every time we had to add new code to help clk-factors
compute the actual factors used, even though a clock with the same
formual was probably already supported. This eventually lead to a huge
number of clocks driver patches, and to review, which is also
something Stephen complained about.

The new approach takes a different approach by adding a bunch of clock
drivers based on the formula they use to compute their rate and / or
the features they have (mux, gate, etc.). The SoC will only have to
provide the data for the driver to know how many options it has,
without adding any extra code.

To reduce the amount of code duplication between those drivers, a
bunch of helpers have also been introduced to deal with the common
features (pre-dividers, gate, muxes, etc.). This will also be very
easy to extend to support new features missing for now (mostly the
fractional stuff as of today).

Since this is a complete rewrite, it probably has a bunch of bugs
and/or limitations not yet found. My plan would be to start using that
approach on the A64, A83T and H3 which are in their early support
stage to be the test-bed for this new framework, before switching the
older and more featureful SoCs to it eventually.

Because of the DT ABI, the older drivers will remain in-tree
obviously, otherwise things would break pretty badly.

The current code has been tested on the H3 and an Orange Pi PC,
including making sure that MMC still works, so the general approach
seems ok.

Let me know what you think,
Maxime

Maxime Ripard (16):
  clk: fix critical clock locking
  clk: sunxi-ng: Add common infrastructure
  clk: sunxi-ng: Add fixed factor clock support
  clk: sunxi-ng: Add gate clock support
  clk: sunxi-ng: Add mux clock support
  clk: sunxi-ng: Add divider table clock
  clk: sunxi-ng: Add phase clock support
  clk: sunxi-ng: Add M-factor clock support
  clk: sunxi-ng: Add P-factor clock support
  clk: sunxi-ng: Add M-P factor clock support
  clk: sunxi-ng: Add N-K-factor clock support
  clk: sunxi-ng: Add N-M-factor clock support
  clk: sunxi-ng: Add N-K-M Factor clock
  clk: sunxi-ng: Add N-K-M-P factor clock
  clk: sunxi-ng: Add H3 clocks
  ARM: dt: sun8i: switch the H3 to the new CCU driver

 arch/arm/boot/dts/sun8i-h3.dtsi         | 310 +++----------
 drivers/clk/Makefile                    |   1 +
 drivers/clk/clk.c                       |   7 +
 drivers/clk/sunxi-ng/Makefile           |  17 +
 drivers/clk/sunxi-ng/ccu-sun8i-h3.c     | 757 ++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_common.c       | 108 +++++
 drivers/clk/sunxi-ng/ccu_common.h       |  74 ++++
 drivers/clk/sunxi-ng/ccu_div_table.c    | 117 +++++
 drivers/clk/sunxi-ng/ccu_div_table.h    |  75 ++++
 drivers/clk/sunxi-ng/ccu_factor.h       |  15 +
 drivers/clk/sunxi-ng/ccu_fixed_factor.c |  42 ++
 drivers/clk/sunxi-ng/ccu_fixed_factor.h |  50 +++
 drivers/clk/sunxi-ng/ccu_gate.c         |  82 ++++
 drivers/clk/sunxi-ng/ccu_gate.h         |  53 +++
 drivers/clk/sunxi-ng/ccu_m.c            | 135 ++++++
 drivers/clk/sunxi-ng/ccu_m.h            | 101 +++++
 drivers/clk/sunxi-ng/ccu_mp.c           | 158 +++++++
 drivers/clk/sunxi-ng/ccu_mp.h           |  79 ++++
 drivers/clk/sunxi-ng/ccu_mux.c          | 187 ++++++++
 drivers/clk/sunxi-ng/ccu_mux.h          |  92 ++++
 drivers/clk/sunxi-ng/ccu_nk.c           | 147 +++++++
 drivers/clk/sunxi-ng/ccu_nk.h           |  44 ++
 drivers/clk/sunxi-ng/ccu_nkm.c          | 144 ++++++
 drivers/clk/sunxi-ng/ccu_nkm.h          |  42 ++
 drivers/clk/sunxi-ng/ccu_nkmp.c         | 157 +++++++
 drivers/clk/sunxi-ng/ccu_nkmp.h         |  43 ++
 drivers/clk/sunxi-ng/ccu_nm.c           | 103 +++++
 drivers/clk/sunxi-ng/ccu_nm.h           |  41 ++
 drivers/clk/sunxi-ng/ccu_p.c            | 141 ++++++
 drivers/clk/sunxi-ng/ccu_p.h            |  40 ++
 drivers/clk/sunxi-ng/ccu_phase.c        | 126 ++++++
 drivers/clk/sunxi-ng/ccu_phase.h        |  50 +++
 drivers/clk/sunxi-ng/ccu_reset.c        |  55 +++
 drivers/clk/sunxi-ng/ccu_reset.h        |  40 ++
 include/dt-bindings/clock/sun8i-h3.h    | 162 +++++++
 include/dt-bindings/reset/sun8i-h3.h    | 103 +++++
 36 files changed, 3646 insertions(+), 252 deletions(-)
 create mode 100644 drivers/clk/sunxi-ng/Makefile
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_common.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_common.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_div_table.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_div_table.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_factor.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_fixed_factor.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_fixed_factor.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_gate.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_gate.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_m.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_m.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_mp.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_mp.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_mux.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_mux.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_nk.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_nk.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_nkm.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_nkm.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_nkmp.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_nkmp.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_nm.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_nm.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_p.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_p.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_phase.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_phase.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_reset.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_reset.h
 create mode 100644 include/dt-bindings/clock/sun8i-h3.h
 create mode 100644 include/dt-bindings/reset/sun8i-h3.h

-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:37 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:37 +0200
Subject: [PATCH 02/16] clk: sunxi-ng: Add common infrastructure
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-3-git-send-email-maxime.ripard@free-electrons.com>

Start our new clock infrastructure by adding the registration code, common
structure and common code.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/Makefile              |   1 +
 drivers/clk/sunxi-ng/Makefile     |   2 +
 drivers/clk/sunxi-ng/ccu_common.c | 108 ++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_common.h |  74 ++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_factor.h |  15 ++++++
 drivers/clk/sunxi-ng/ccu_mux.h    |  20 +++++++
 drivers/clk/sunxi-ng/ccu_reset.c  |  55 +++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_reset.h  |  40 ++++++++++++++
 8 files changed, 315 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/Makefile
 create mode 100644 drivers/clk/sunxi-ng/ccu_common.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_common.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_factor.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_mux.h
 create mode 100644 drivers/clk/sunxi-ng/ccu_reset.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_reset.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 4ef71a13ab37..83a93cd9e21d 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -78,6 +78,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
 obj-$(CONFIG_ARCH_STI)			+= st/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
+obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
 obj-y					+= ti/
 obj-$(CONFIG_ARCH_U8500)		+= ux500/
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
new file mode 100644
index 000000000000..bd3461b0f38c
--- /dev/null
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -0,0 +1,2 @@
+obj-y += ccu_common.o
+obj-y += ccu_reset.o
diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c
new file mode 100644
index 000000000000..1d9242566fbd
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_common.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2016 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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/iopoll.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+static DEFINE_SPINLOCK(ccu_lock);
+
+void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
+{
+	u32 reg;
+
+	if (!(common->features & CCU_FEATURE_LOCK))
+		return;
+
+	WARN_ON(readl_relaxed_poll_timeout(common->base + common->reg, reg,
+					   !(reg & lock), 0, 500));
+}
+
+int sunxi_ccu_probe(struct device_node *node,
+		    const struct sunxi_ccu_desc *desc)
+{
+	struct ccu_common **cclks = desc->clks;
+	size_t num_clks = desc->num_clks;
+	struct clk_onecell_data *data;
+	struct ccu_reset *reset;
+	struct clk **clks;
+	void __iomem *reg;
+	int i, ret;
+	
+	reg = of_iomap(node, 0);
+	if (IS_ERR(reg)) {
+		pr_err("%s: Could not map the clock registers\n",
+		       of_node_full_name(node));
+		return PTR_ERR(reg);
+	}
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	clks = kcalloc(num_clks, sizeof(struct clk *), GFP_KERNEL);
+	if (!clks)
+		return -ENOMEM;
+
+	data->clks = clks;
+	data->clk_num = num_clks;
+
+	for (i = 0; i < num_clks; i++) {
+		struct ccu_common *cclk = cclks[i];
+		struct clk *clk;
+
+		if (!cclk) {
+			cclk = ERR_PTR(-ENOENT);
+			continue;
+		}
+
+		cclk->base = reg;
+		cclk->lock = &ccu_lock;
+
+		clk = clk_register(NULL, &cclk->hw);
+		if (IS_ERR(clk))
+			continue;
+
+		clks[i] = clk;
+	}
+
+	ret = of_clk_add_provider(node, of_clk_src_onecell_get, data);
+	if (ret)
+		goto err_clk_unreg;
+
+	reset = kzalloc(sizeof(*reset), GFP_KERNEL);
+	reset->rcdev.of_node = node;
+	reset->rcdev.ops = &ccu_reset_ops;
+	reset->rcdev.owner = THIS_MODULE;
+	reset->rcdev.nr_resets = desc->num_resets;
+	reset->base = reg;
+	reset->lock = &ccu_lock;
+	reset->reset_map = desc->resets;
+
+	ret = reset_controller_register(&reset->rcdev);
+	if (ret)
+		goto err_of_clk_unreg;
+
+	return 0;
+
+err_of_clk_unreg:
+err_clk_unreg:
+	return ret;
+}
diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
new file mode 100644
index 000000000000..e8b477fcd320
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include <linux/compiler.h>
+#include <linux/clk-provider.h>
+
+#define CCU_FEATURE_GATE		BIT(0)
+#define CCU_FEATURE_LOCK		BIT(1)
+#define CCU_FEATURE_FRACTIONAL		BIT(2)
+#define CCU_FEATURE_VARIABLE_PREDIV	BIT(3)
+#define CCU_FEATURE_FIXED_PREDIV	BIT(4)
+#define CCU_FEATURE_FIXED_POSTDIV	BIT(5)
+
+struct device_node;
+
+#define SUNXI_HW_INIT(_name, _parent, _ops, _flags)			\
+	&(struct clk_init_data) {					\
+		.flags		= _flags,				\
+		.name		= _name,				\
+		.parent_names	= (const char *[]) { _parent },		\
+		.num_parents	= 1,					\
+		.ops 		= _ops,					\
+	}
+
+#define SUNXI_HW_INIT_PARENTS(_name, _parents, _ops, _flags)		\
+	&(struct clk_init_data) {					\
+		.flags		= _flags,				\
+		.name		= _name,				\
+		.parent_names	= _parents,				\
+		.num_parents	= ARRAY_SIZE(_parents),			\
+		.ops 		= _ops,					\
+	}
+
+struct ccu_common {
+	void __iomem	*base;
+	unsigned long	reg;
+
+	unsigned long	features;
+	spinlock_t	*lock;
+	struct clk_hw	hw;
+};
+
+static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)
+{
+	return container_of(hw, struct ccu_common, hw);
+}
+
+struct sunxi_ccu_desc {
+	struct ccu_common	**clks;
+	unsigned long		num_clks;
+
+	struct ccu_reset_map	*resets;
+	unsigned long		num_resets;
+};
+
+void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock);
+
+int sunxi_ccu_probe(struct device_node *node,
+		    const struct sunxi_ccu_desc *desc);
+
+#endif /* _COMMON_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_factor.h b/drivers/clk/sunxi-ng/ccu_factor.h
new file mode 100644
index 000000000000..e7cc564aaea0
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_factor.h
@@ -0,0 +1,15 @@
+#ifndef _CLK_FACTOR_H_
+#define _CLK_FACTOR_H_
+
+struct ccu_factor {
+	u8	shift;
+	u8	width;
+};
+
+#define SUNXI_CLK_FACTOR(_shift, _width)	\
+	{					\
+		.shift	= _shift,		\
+		.width	= _width,		\
+	}
+
+#endif /* _CLK_FACTOR_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
new file mode 100644
index 000000000000..17cedad4e433
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_mux.h
@@ -0,0 +1,20 @@
+#ifndef _CCU_MUX_H_
+#define _CCU_MUX_H_
+
+#include "common.h"
+
+struct ccu_mux_internal {
+	u8	shift;
+	u8	width;
+
+	u8	*map;
+};
+
+#define SUNXI_CLK_MUX(_shift, _width, _map)	\
+	{					\
+		.map	= _map,			\
+		.shift	= _shift,		\
+		.width	= _width,		\
+	}
+
+#endif /* _CCU_MUX_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu_reset.c b/drivers/clk/sunxi-ng/ccu_reset.c
new file mode 100644
index 000000000000..6c31d48783a7
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_reset.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/reset-controller.h>
+
+#include "ccu_reset.h"
+
+static int ccu_reset_assert(struct reset_controller_dev *rcdev,
+			    unsigned long id)
+{
+	struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
+	const struct ccu_reset_map *map = &ccu->reset_map[id];
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(ccu->lock, flags);
+
+	reg = readl(ccu->base + map->reg);
+	writel(reg & ~map->bit, ccu->base + map->reg);
+
+	spin_unlock_irqrestore(ccu->lock, flags);
+
+	return 0;
+}
+
+static int ccu_reset_deassert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
+	const struct ccu_reset_map *map = &ccu->reset_map[id];
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(ccu->lock, flags);
+
+	reg = readl(ccu->base + map->reg);
+	writel(reg | map->bit, ccu->base + map->reg);
+
+	spin_unlock_irqrestore(ccu->lock, flags);
+
+	return 0;
+}
+
+const struct reset_control_ops ccu_reset_ops = {
+	.assert		= ccu_reset_assert,
+	.deassert	= ccu_reset_deassert,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_reset.h b/drivers/clk/sunxi-ng/ccu_reset.h
new file mode 100644
index 000000000000..36a4679210bd
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_reset.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_RESET_H_
+#define _CCU_RESET_H_
+
+#include <linux/reset-controller.h>
+
+struct ccu_reset_map {
+	u16	reg;
+	u32	bit;
+};
+
+
+struct ccu_reset {
+	void __iomem			*base;
+	struct ccu_reset_map		*reset_map;
+	spinlock_t			*lock;
+
+	struct reset_controller_dev	rcdev;
+};
+
+static inline struct ccu_reset *rcdev_to_ccu_reset(struct reset_controller_dev *rcdev)
+{
+	return container_of(rcdev, struct ccu_reset, rcdev);
+}
+
+extern const struct reset_control_ops ccu_reset_ops;
+
+#endif /* _CCU_RESET_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:47 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:47 +0200
Subject: [PATCH 12/16] clk: sunxi-ng: Add N-M-factor clock support
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-13-git-send-email-maxime.ripard@free-electrons.com>

Introduce support for clocks that multiply and divide using linear factors.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile |   1 +
 drivers/clk/sunxi-ng/ccu_nm.c | 103 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_nm.h |  41 +++++++++++++++++
 3 files changed, 145 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu_nm.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_nm.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index e29ddae99653..fba64c7f4fcd 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -8,5 +8,6 @@ obj-y += ccu_m.o
 obj-y += ccu_mp.o
 obj-y += ccu_mux.o
 obj-y += ccu_nk.o
+obj-y += ccu_nm.o
 obj-y += ccu_p.o
 obj-y += ccu_phase.o
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
new file mode 100644
index 000000000000..268637db137b
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_nm.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/rational.h>
+
+#include "ccu_gate.h"
+#include "ccu_nm.h"
+
+static void ccu_nm_disable(struct clk_hw *hw)
+{
+	struct ccu_nm *nm = hw_to_ccu_nm(hw);
+
+	return ccu_gate_helper_disable(&nm->common, nm->enable);
+}
+
+static int ccu_nm_enable(struct clk_hw *hw)
+{
+	struct ccu_nm *nm = hw_to_ccu_nm(hw);
+
+	return ccu_gate_helper_enable(&nm->common, nm->enable);
+}
+
+static int ccu_nm_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_nm *nm = hw_to_ccu_nm(hw);
+
+	return ccu_gate_helper_is_enabled(&nm->common, nm->enable);
+}
+
+static unsigned long ccu_nm_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct ccu_nm *nm = hw_to_ccu_nm(hw);
+	unsigned long n, m;
+	u32 reg;
+
+	reg = readl(nm->common.base + nm->common.reg);
+
+	n = reg >> nm->n.shift;
+	n &= (1 << nm->n.width) - 1;
+
+	m = reg >> nm->m.shift;
+	m &= (1 << nm->m.width) - 1;
+
+	return parent_rate * (n + 1) / (m + 1);
+}
+
+static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long *parent_rate)
+{
+	struct ccu_nm *nm = hw_to_ccu_nm(hw);
+	unsigned long n, m;
+
+	rational_best_approximation(rate, *parent_rate,
+				    nm->n.width, nm->m.width, &n, &m);
+
+	return *parent_rate * n / m;
+}
+
+static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long parent_rate)
+{
+	struct ccu_nm *nm = hw_to_ccu_nm(hw);
+	unsigned long flags;
+	unsigned long n, m;
+	u32 reg;
+
+	rational_best_approximation(rate, parent_rate,
+				    nm->n.width, nm->m.width, &n, &m);
+
+	spin_lock_irqsave(nm->common.lock, flags);
+
+	reg = readl(nm->common.base + nm->common.reg);
+	reg &= ~GENMASK(nm->n.width + nm->n.shift, nm->n.shift);
+	reg &= ~GENMASK(nm->m.width + nm->m.shift, nm->m.shift);
+
+	writel(reg | ((m - 1) << nm->m.shift) | ((n - 1) << nm->n.shift),
+	       nm->common.base + nm->common.reg);
+
+	spin_unlock_irqrestore(nm->common.lock, flags);
+
+	ccu_helper_wait_for_lock(&nm->common, nm->lock);
+
+	return 0;
+}
+
+const struct clk_ops ccu_nm_ops = {
+	.disable	= ccu_nm_disable,
+	.enable		= ccu_nm_enable,
+	.is_enabled	= ccu_nm_is_enabled,
+
+	.recalc_rate	= ccu_nm_recalc_rate,
+	.round_rate	= ccu_nm_round_rate,
+	.set_rate	= ccu_nm_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_nm.h b/drivers/clk/sunxi-ng/ccu_nm.h
new file mode 100644
index 000000000000..6fda3ed05cd8
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_nm.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_NM_H_
+#define _CCU_NM_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_factor.h"
+#include "ccu_common.h"
+
+struct ccu_nm {
+	u32			enable;
+	u32			lock;
+
+	struct ccu_factor	n;
+	struct ccu_factor	m;
+
+	struct ccu_common	common;
+};
+
+static inline struct ccu_nm *hw_to_ccu_nm(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_nm, common);
+}
+
+extern const struct clk_ops ccu_nm_ops;
+
+#endif /* _CCU_NM_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:44 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:44 +0200
Subject: [PATCH 09/16] clk: sunxi-ng: Add P-factor clock support
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-10-git-send-email-maxime.ripard@free-electrons.com>

Introduce support for clocks that divide using a power of two factor.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile |   1 +
 drivers/clk/sunxi-ng/ccu_p.c  | 141 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_p.h  |  40 ++++++++++++
 3 files changed, 182 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu_p.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_p.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index f41de901c607..063c50f35ad4 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -6,4 +6,5 @@ obj-y += ccu_fixed_factor.o
 obj-y += ccu_gate.o
 obj-y += ccu_m.o
 obj-y += ccu_mux.o
+obj-y += ccu_p.o
 obj-y += ccu_phase.o
diff --git a/drivers/clk/sunxi-ng/ccu_p.c b/drivers/clk/sunxi-ng/ccu_p.c
new file mode 100644
index 000000000000..4d4dbd35cead
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_p.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "ccu_gate.h"
+#include "ccu_p.h"
+
+static void ccu_p_find_best(unsigned long parent, unsigned long rate,
+			    unsigned int max_p, unsigned int *p)
+{
+	unsigned int div, _p;
+
+	div = DIV_ROUND_UP(parent, rate);
+	_p = __roundup_pow_of_two(div);
+
+	if (_p > max_p)
+		_p = max_p;
+
+	*p = _p;
+}
+
+static unsigned long ccu_p_round_rate(struct ccu_mux_internal *mux,
+				       unsigned long parent_rate,
+				       unsigned long rate,
+				       void *data)
+{
+	struct ccu_p *cp = data;
+	unsigned int p;
+
+	ccu_p_find_best(parent_rate, rate, (1 << cp->p.width) - 1, &p);
+
+	return parent_rate >> p;
+}
+
+static void ccu_p_disable(struct clk_hw *hw)
+{
+	struct ccu_p *cp = hw_to_ccu_p(hw);
+
+	return ccu_gate_helper_disable(&cp->common, cp->enable);
+}
+
+static int ccu_p_enable(struct clk_hw *hw)
+{
+	struct ccu_p *cp = hw_to_ccu_p(hw);
+
+	return ccu_gate_helper_enable(&cp->common, cp->enable);
+}
+
+static int ccu_p_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_p *cp = hw_to_ccu_p(hw);
+
+	return ccu_gate_helper_is_enabled(&cp->common, cp->enable);
+}
+
+static unsigned long ccu_p_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct ccu_p *cp = hw_to_ccu_p(hw);
+	unsigned long p;
+	u32 reg;
+
+	reg = readl(cp->common.base + cp->common.reg);
+	p = reg >> cp->p.shift;
+	p &= (1 << cp->p.width) - 1;
+
+	ccu_mux_helper_adjust_parent_for_prediv(&cp->common, &cp->mux, -1,
+						&parent_rate);
+
+	return parent_rate >> p;
+}
+
+static int ccu_p_determine_rate(struct clk_hw *hw,
+				struct clk_rate_request *req)
+{
+	struct ccu_p *cp = hw_to_ccu_p(hw);
+
+	return ccu_mux_helper_determine_rate(&cp->common, &cp->mux,
+					     req, ccu_p_round_rate, cp);
+}
+
+static int ccu_p_set_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long parent_rate)
+{
+	struct ccu_p *cp = hw_to_ccu_p(hw);
+	unsigned long flags;
+	unsigned int p;
+	u32 reg;
+
+	ccu_mux_helper_adjust_parent_for_prediv(&cp->common, &cp->mux, -1,
+						&parent_rate);
+
+	ccu_p_find_best(parent_rate, rate, (1 << cp->p.width) - 1, &p);
+
+	spin_lock_irqsave(cp->common.lock, flags);
+
+	reg = readl(cp->common.base + cp->common.reg);
+	reg &= ~GENMASK(cp->p.width + cp->p.shift, cp->p.shift);
+
+	writel(reg | (p << cp->p.shift),
+	       cp->common.base + cp->common.reg);
+
+	spin_unlock_irqrestore(cp->common.lock, flags);
+
+	return 0;
+}
+
+static u8 ccu_p_get_parent(struct clk_hw *hw)
+{
+	struct ccu_p *cp = hw_to_ccu_p(hw);
+
+	return ccu_mux_helper_get_parent(&cp->common, &cp->mux);
+}
+
+static int ccu_p_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct ccu_p *cp = hw_to_ccu_p(hw);
+
+	return ccu_mux_helper_set_parent(&cp->common, &cp->mux, index);
+}
+
+const struct clk_ops ccu_p_ops = {
+	.disable	= ccu_p_disable,
+	.enable		= ccu_p_enable,
+	.is_enabled	= ccu_p_is_enabled,
+
+	.get_parent	= ccu_p_get_parent,
+	.set_parent	= ccu_p_set_parent,
+
+	.determine_rate	= ccu_p_determine_rate,
+	.recalc_rate	= ccu_p_recalc_rate,
+	.set_rate	= ccu_p_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_p.h b/drivers/clk/sunxi-ng/ccu_p.h
new file mode 100644
index 000000000000..3cbda4ae6e72
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_p.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_P_H_
+#define _CCU_P_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+#include "ccu_factor.h"
+#include "ccu_mux.h"
+
+struct ccu_p {
+	u32			enable;
+
+	struct ccu_factor	p;
+	struct ccu_mux_internal	mux;
+	struct ccu_common	common;
+};
+
+static inline struct ccu_p *hw_to_ccu_p(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_p, common);
+}
+
+extern const struct clk_ops ccu_p_ops;
+
+#endif /* _CCU_P_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:42 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:42 +0200
Subject: [PATCH 07/16] clk: sunxi-ng: Add phase clock support
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-8-git-send-email-maxime.ripard@free-electrons.com>

Add support for the clocks in the CCU that introduce a phase shift from
their parent clock.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile    |   1 +
 drivers/clk/sunxi-ng/ccu_phase.c | 126 +++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_phase.h |  50 ++++++++++++++++
 3 files changed, 177 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu_phase.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_phase.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index f20c6c8f217c..a47a3bbdf285 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -5,3 +5,4 @@ obj-y += ccu_div_table.o
 obj-y += ccu_fixed_factor.o
 obj-y += ccu_gate.o
 obj-y += ccu_mux.o
+obj-y += ccu_phase.o
diff --git a/drivers/clk/sunxi-ng/ccu_phase.c b/drivers/clk/sunxi-ng/ccu_phase.c
new file mode 100644
index 000000000000..cf0f0b20115c
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_phase.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/spinlock.h>
+
+#include "ccu_phase.h"
+
+static int ccu_phase_get_phase(struct clk_hw *hw)
+{
+	struct ccu_phase *phase = hw_to_ccu_phase(hw);
+	struct clk_hw *parent, *pparent;
+	unsigned int parent_rate, pparent_rate;
+	u16 step, parent_div;
+	u32 reg;
+	u8 delay;
+
+	reg = readl(phase->common.base + phase->common.reg);
+	delay = (reg >> phase->shift);
+	delay &= (1 << phase->width) - 1;
+
+	if (!delay)
+		return 180;
+
+	/* Get our parent clock, it's the one that can adjust its rate */
+	parent = clk_hw_get_parent(hw);
+	if (!parent)
+		return -EINVAL;
+
+	/* And its rate */
+	parent_rate = clk_hw_get_rate(parent);
+	if (!parent_rate)
+		return -EINVAL;
+
+	/* Now, get our parent's parent (most likely some PLL) */
+	pparent = clk_hw_get_parent(parent);
+	if (!pparent)
+		return -EINVAL;
+
+	/* And its rate */
+	pparent_rate = clk_hw_get_rate(pparent);
+	if (!pparent_rate)
+		return -EINVAL;
+
+	/* Get our parent clock divider */
+	parent_div = pparent_rate / parent_rate;
+
+	step = DIV_ROUND_CLOSEST(360, parent_div);
+	return delay * step;
+}
+
+static int ccu_phase_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct ccu_phase *phase = hw_to_ccu_phase(hw);
+	struct clk_hw *parent, *pparent;
+	unsigned int parent_rate, pparent_rate;
+	unsigned long flags;
+	u32 reg;
+	u8 delay;
+
+	/* Get our parent clock, it's the one that can adjust its rate */
+	parent = clk_hw_get_parent(hw);
+	if (!parent)
+		return -EINVAL;
+
+	/* And its rate */
+	parent_rate = clk_hw_get_rate(parent);
+	if (!parent_rate)
+		return -EINVAL;
+
+	/* Now, get our parent's parent (most likely some PLL) */
+	pparent = clk_hw_get_parent(parent);
+	if (!pparent)
+		return -EINVAL;
+
+	/* And its rate */
+	pparent_rate = clk_hw_get_rate(pparent);
+	if (!pparent_rate)
+		return -EINVAL;
+
+	if (degrees != 180) {
+		u16 step, parent_div;
+
+		/* Get our parent divider */
+		parent_div = pparent_rate / parent_rate;
+
+		/*
+		 * We can only outphase the clocks by multiple of the
+		 * PLL's period.
+		 *
+		 * Since our parent clock is only a divider, and the
+		 * formula to get the outphasing in degrees is deg =
+		 * 360 * delta / period
+		 *
+		 * If we simplify this formula, we can see that the
+		 * only thing that we're concerned about is the number
+		 * of period we want to outphase our clock from, and
+		 * the divider set by our parent clock.
+		 */
+		step = DIV_ROUND_CLOSEST(360, parent_div);
+		delay = DIV_ROUND_CLOSEST(degrees, step);
+	} else {
+		delay = 0;
+	}
+
+	spin_lock_irqsave(phase->common.lock, flags);
+	reg = readl(phase->common.base + phase->common.reg);
+	reg &= ~GENMASK(phase->width + phase->shift, phase->shift);
+	writel(reg | (delay << phase->shift),
+	       phase->common.base + phase->common.reg);
+	spin_unlock_irqrestore(phase->common.lock, flags);
+
+	return 0;
+}
+
+const struct clk_ops ccu_phase_ops = {
+	.get_phase	= ccu_phase_get_phase,
+	.set_phase	= ccu_phase_set_phase,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_phase.h b/drivers/clk/sunxi-ng/ccu_phase.h
new file mode 100644
index 000000000000..e28b4e58a819
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_phase.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_PHASE_H_
+#define _CCU_PHASE_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+
+struct ccu_phase {
+	u8			shift;
+	u8			width;
+
+	struct ccu_common	common;
+};
+
+#define SUNXI_CCU_PHASE(_struct, _name, _parent, _reg, _shift, _width, _flags) \
+	struct ccu_phase _struct = {					\
+		.shift	= _shift,					\
+		.width	= _width,					\
+		.common	= {						\
+			.reg		= _reg,				\
+			.hw.init	= SUNXI_HW_INIT(_name,		\
+							_parent,	\
+							&ccu_phase_ops,	\
+							_flags),	\
+		}							\
+	}
+
+static inline struct ccu_phase *hw_to_ccu_phase(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_phase, common);
+}
+
+extern const struct clk_ops ccu_phase_ops;
+
+#endif /* _CCU_PHASE_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:41 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:41 +0200
Subject: [PATCH 06/16] clk: sunxi-ng: Add divider table clock
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-7-git-send-email-maxime.ripard@free-electrons.com>

Add support for clocks based on a divider tables.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile        |   1 +
 drivers/clk/sunxi-ng/ccu_div_table.c | 117 +++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_div_table.h |  75 ++++++++++++++++++++++
 3 files changed, 193 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu_div_table.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_div_table.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index aa5c411ff8ea..f20c6c8f217c 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -1,6 +1,7 @@
 obj-y += ccu_common.o
 obj-y += ccu_reset.o
 
+obj-y += ccu_div_table.o
 obj-y += ccu_fixed_factor.o
 obj-y += ccu_gate.o
 obj-y += ccu_mux.o
diff --git a/drivers/clk/sunxi-ng/ccu_div_table.c b/drivers/clk/sunxi-ng/ccu_div_table.c
new file mode 100644
index 000000000000..cbfff0bd47e3
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_div_table.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "ccu_div_table.h"
+#include "ccu_gate.h"
+
+static void ccu_div_table_find_best(unsigned long parent, unsigned long rate,
+				    struct ccu_div_table *ct,
+				    unsigned int *index)
+{
+	unsigned long best_rate = 0;
+	unsigned int best_index = 0;
+	unsigned int _index;
+
+	for (_index = 0; _index <= ct->num_divs; _index++) {
+		unsigned long tmp_rate = parent / ct->table[_index];
+
+		if (tmp_rate > rate)
+			continue;
+
+		if ((rate - tmp_rate) < (rate - best_rate)) {
+			best_rate = tmp_rate;
+			best_index = _index;
+		}
+	}
+
+	*index = best_index;
+}
+
+static void ccu_div_table_disable(struct clk_hw *hw)
+{
+	struct ccu_div_table *ct = hw_to_ccu_div_table(hw);
+
+	return ccu_gate_helper_disable(&ct->common, ct->enable);
+}
+
+static int ccu_div_table_enable(struct clk_hw *hw)
+{
+	struct ccu_div_table *ct = hw_to_ccu_div_table(hw);
+
+	return ccu_gate_helper_enable(&ct->common, ct->enable);
+}
+
+static int ccu_div_table_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_div_table *ct = hw_to_ccu_div_table(hw);
+
+	return ccu_gate_helper_is_enabled(&ct->common, ct->enable);
+}
+
+static unsigned long ccu_div_table_recalc_rate(struct clk_hw *hw,
+					       unsigned long parent_rate)
+{
+	struct ccu_div_table *ct = hw_to_ccu_div_table(hw);
+	unsigned long div;
+	u32 reg;
+
+	reg = readl(ct->common.base + ct->common.reg);
+
+	div = reg >> ct->div.shift;
+	div &= (1 << ct->div.width) - 1;
+
+	return parent_rate / ct->table[div];
+}
+
+static long ccu_div_table_round_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long *parent_rate)
+{
+	struct ccu_div_table *ct = hw_to_ccu_div_table(hw);
+	unsigned int index;
+	
+	ccu_div_table_find_best(*parent_rate, rate,
+				ct, &index);
+
+	return *parent_rate / ct->table[index];
+}
+
+static int ccu_div_table_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long parent_rate)
+{
+	struct ccu_div_table *ct = hw_to_ccu_div_table(hw);
+	unsigned long flags;
+	unsigned int index;
+	u32 reg;
+
+	ccu_div_table_find_best(parent_rate, rate, ct, &index);
+
+	spin_lock_irqsave(ct->common.lock, flags);
+
+	reg = readl(ct->common.base + ct->common.reg);
+	reg &= ~GENMASK(ct->div.width + ct->div.shift, ct->div.shift);
+	writel(reg | ((ct->table[index]) << ct->div.shift),
+	       ct->common.base + ct->common.reg);
+
+	spin_unlock_irqrestore(ct->common.lock, flags);
+
+	return 0;
+}
+
+const struct clk_ops ccu_div_table_ops = {
+	.disable	= ccu_div_table_disable,
+	.enable		= ccu_div_table_enable,
+	.is_enabled	= ccu_div_table_is_enabled,
+
+	.recalc_rate	= ccu_div_table_recalc_rate,
+	.round_rate	= ccu_div_table_round_rate,
+	.set_rate	= ccu_div_table_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_div_table.h b/drivers/clk/sunxi-ng/ccu_div_table.h
new file mode 100644
index 000000000000..bd7da49087ed
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_div_table.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_DIV_TABLE_H_
+#define _CCU_DIV_TABLE_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+#include "ccu_factor.h"
+
+struct ccu_div_table {
+	u32			enable;
+
+	u8			*table;
+	int			num_divs;
+
+	struct ccu_factor	div;
+	struct ccu_common	common;
+};
+
+#define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg,		\
+			    _shift, _width,				\
+			    _table, _flags)				\
+	struct ccu_div_table _struct = {				\
+		.table		= _table,				\
+		.num_divs	= ARRAY_SIZE(_table),			\
+		.div		= SUNXI_CLK_FACTOR(_shift, _width),	\
+		.common	= {						\
+			.reg		= _reg,				\
+			.hw.init	= SUNXI_HW_INIT(_name,		\
+							_parent,	\
+							&ccu_div_table_ops, \
+							_flags),	\
+		}							\
+	}
+
+#define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,	\
+				      _shift, _width,			\
+				      _table, _gate, _flags)		\
+	struct ccu_div_table _struct = {				\
+		.enable		= _gate,				\
+		.table		= _table,				\
+		.num_divs	= ARRAY_SIZE(_table),			\
+		.div		= SUNXI_CLK_FACTOR(_shift, _width),	\
+		.common	= {						\
+			.reg		= _reg,				\
+			.features	= CCU_FEATURE_GATE,		\
+			.hw.init	= SUNXI_HW_INIT(_name,		\
+							_parent,	\
+							&ccu_div_table_ops, \
+							_flags),	\
+		}							\
+	}
+
+static inline struct ccu_div_table *hw_to_ccu_div_table(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_div_table, common);
+}
+
+extern const struct clk_ops ccu_div_table_ops;
+
+#endif /* _CCU_DIV_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:45 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:45 +0200
Subject: [PATCH 10/16] clk: sunxi-ng: Add M-P factor clock support
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-11-git-send-email-maxime.ripard@free-electrons.com>

Introduce support for the clocks that combine a linear divider and a
power-of-two based one.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile |   1 +
 drivers/clk/sunxi-ng/ccu_mp.c | 158 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_mp.h |  79 +++++++++++++++++++++
 3 files changed, 238 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu_mp.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_mp.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 063c50f35ad4..09fce7467784 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -5,6 +5,7 @@ obj-y += ccu_div_table.o
 obj-y += ccu_fixed_factor.o
 obj-y += ccu_gate.o
 obj-y += ccu_m.o
+obj-y += ccu_mp.o
 obj-y += ccu_mux.o
 obj-y += ccu_p.o
 obj-y += ccu_phase.o
diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
new file mode 100644
index 000000000000..7181188deba7
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+
+static void ccu_mp_find_best(unsigned long parent, unsigned long rate,
+			     unsigned int max_m, unsigned int max_p,
+			     unsigned int *m, unsigned int *p)
+{
+	unsigned long best_rate = 0;
+	unsigned int best_m = 0, best_p = 0;
+	unsigned int _m, _p;
+
+	for (_p = 0; _p <= max_p; _p++) {
+		for (_m = 1; _m <= max_m; _m++) {
+			unsigned long tmp_rate = (parent >> _p) / _m;
+
+			if (tmp_rate > rate)
+				continue;
+
+			if ((rate - tmp_rate) < (rate - best_rate)) {
+				best_rate = tmp_rate;
+				best_m = _m;
+				best_p = _p;
+			}
+		}
+	}
+
+	*m = best_m;
+	*p = best_p;
+}
+
+static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
+				       unsigned long parent_rate,
+				       unsigned long rate,
+				       void *data)
+{
+	struct ccu_mp *cmp = data;
+	unsigned int m, p;
+
+	ccu_mp_find_best(parent_rate, rate,
+			 1 << cmp->m.width, (1 << cmp->p.width) - 1,
+			 &m, &p);
+
+	return (parent_rate >> p) / m;
+}
+
+static void ccu_mp_disable(struct clk_hw *hw)
+{
+	struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+
+	return ccu_gate_helper_disable(&cmp->common, cmp->enable);
+}
+
+static int ccu_mp_enable(struct clk_hw *hw)
+{
+	struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+
+	return ccu_gate_helper_enable(&cmp->common, cmp->enable);
+}
+
+static int ccu_mp_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+
+	return ccu_gate_helper_is_enabled(&cmp->common, cmp->enable);
+}
+
+static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+	unsigned int m, p;
+	u32 reg;
+
+	reg = readl(cmp->common.base + cmp->common.reg);
+
+	m = reg >> cmp->m.shift;
+	m &= (1 << cmp->m.width) - 1;
+
+	p = reg >> cmp->p.shift;
+	p &= (1 << cmp->p.width) - 1;
+
+	return (parent_rate >> p) / (m + 1);
+}
+
+static int ccu_mp_determine_rate(struct clk_hw *hw,
+				 struct clk_rate_request *req)
+{
+	struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+
+	return ccu_mux_helper_determine_rate(&cmp->common, &cmp->mux,
+					     req, ccu_mp_round_rate, cmp);
+}
+
+static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long parent_rate)
+{
+	struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+	unsigned long flags;
+	unsigned int m, p;
+	u32 reg;
+
+	ccu_mp_find_best(parent_rate, rate,
+			 1 << cmp->m.width, (1 << cmp->p.width) - 1,
+			 &m, &p);
+
+
+	spin_lock_irqsave(cmp->common.lock, flags);
+
+	reg = readl(cmp->common.base + cmp->common.reg);
+	reg &= ~GENMASK(cmp->m.width + cmp->m.shift, cmp->m.shift);
+	reg &= ~GENMASK(cmp->p.width + cmp->p.shift, cmp->p.shift);
+
+	writel(reg | (p << cmp->p.shift) | ((m - 1) << cmp->m.shift),
+	       cmp->common.base + cmp->common.reg);
+
+	spin_unlock_irqrestore(cmp->common.lock, flags);
+
+	return 0;
+}
+
+static u8 ccu_mp_get_parent(struct clk_hw *hw)
+{
+	struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+
+	return ccu_mux_helper_get_parent(&cmp->common, &cmp->mux);
+}
+
+static int ccu_mp_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct ccu_mp *cmp = hw_to_ccu_mp(hw);
+
+	return ccu_mux_helper_set_parent(&cmp->common, &cmp->mux, index);
+}
+
+const struct clk_ops ccu_mp_ops = {
+	.disable	= ccu_mp_disable,
+	.enable		= ccu_mp_enable,
+	.is_enabled	= ccu_mp_is_enabled,
+
+	.get_parent	= ccu_mp_get_parent,
+	.set_parent	= ccu_mp_set_parent,
+
+	.determine_rate	= ccu_mp_determine_rate,
+	.recalc_rate	= ccu_mp_recalc_rate,
+	.set_rate	= ccu_mp_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
new file mode 100644
index 000000000000..95da9c46cd4f
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_mp.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_MP_H_
+#define _CCU_MP_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+#include "ccu_factor.h"
+#include "ccu_mux.h"
+
+struct ccu_mp {
+	u32			enable;
+
+	struct ccu_factor	m;
+	struct ccu_factor	p;
+	struct ccu_mux_internal	mux;
+	struct ccu_common	common;
+};
+
+#define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg,		\
+			      _mshift, _mwidth,				\
+			      _pshift, _pwidth,				\
+			      _muxshift, _muxwidth,			\
+			      _flags)					\
+	struct ccu_mp _struct = {					\
+		.m	= SUNXI_CLK_FACTOR(_mshift, _mwidth),		\
+		.p	= SUNXI_CLK_FACTOR(_pshift, _pwidth),		\
+		.mux	= SUNXI_CLK_MUX(_muxshift, _muxwidth),		\
+		.common	= {						\
+			.reg		= _reg,				\
+			.hw.init	= SUNXI_HW_INIT_PARENTS(_name,	\
+								_parents, \
+								&ccu_mp_ops, \
+								_flags), \
+		}							\
+	}
+
+#define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
+				   _mshift, _mwidth,			\
+				   _pshift, _pwidth,			\
+				   _muxshift, _muxwidth,		\
+				   _gate, _flags)			\
+	struct ccu_mp _struct = {					\
+		.enable	= _gate,					\
+		.m	= SUNXI_CLK_FACTOR(_mshift, _mwidth),		\
+		.p	= SUNXI_CLK_FACTOR(_pshift, _pwidth),		\
+		.mux	= SUNXI_CLK_MUX(_muxshift, _muxwidth),		\
+		.common	= {						\
+			.reg		= _reg,				\
+			.features	= CCU_FEATURE_GATE,		\
+			.hw.init	= SUNXI_HW_INIT_PARENTS(_name,	\
+								_parents, \
+								&ccu_mp_ops, \
+								_flags), \
+		}							\
+	}
+
+static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_mp, common);
+}
+
+extern const struct clk_ops ccu_mp_ops;
+
+#endif /* _CCU_MP_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:48 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:48 +0200
Subject: [PATCH 13/16] clk: sunxi-ng: Add N-K-M Factor clock
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-14-git-send-email-maxime.ripard@free-electrons.com>

Introduce support for clocks that multiply and divide using two linear
multipliers and one linear divider.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile  |   1 +
 drivers/clk/sunxi-ng/ccu_nkm.c | 144 +++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_nkm.h |  42 ++++++++++++
 3 files changed, 187 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu_nkm.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_nkm.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index fba64c7f4fcd..2bb8bc22e907 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -8,6 +8,7 @@ obj-y += ccu_m.o
 obj-y += ccu_mp.o
 obj-y += ccu_mux.o
 obj-y += ccu_nk.o
+obj-y += ccu_nkm.o
 obj-y += ccu_nm.o
 obj-y += ccu_p.o
 obj-y += ccu_phase.o
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
new file mode 100644
index 000000000000..9019c7f6988c
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/rational.h>
+
+#include "ccu_gate.h"
+#include "ccu_nkm.h"
+
+void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
+		       unsigned long max_n, unsigned long max_k, unsigned long max_m,
+		       unsigned long *n, unsigned long *k, unsigned long *m)
+{
+	unsigned long best_rate = 0;
+	unsigned long best_n = 0, best_k = 0, best_m = 0;
+	unsigned long _n, _k, _m;
+
+	for (_k = 1; _k <= max_k; _k++) {
+		unsigned long tmp_rate;
+
+		rational_best_approximation(rate / _k, parent,
+					    max_n, max_m, &_n, &_m);
+
+		tmp_rate = parent * _n * _k / _m;
+
+		if (tmp_rate > rate)
+			continue;
+
+		if ((rate - tmp_rate) < (rate - best_rate)) {
+			best_rate = tmp_rate;
+			best_n = _n;
+			best_k = _k;
+			best_m = _m;
+		}
+	}
+
+	*n = best_n;
+	*k = best_k;
+	*m = best_m;
+}
+
+static void ccu_nkm_disable(struct clk_hw *hw)
+{
+	struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
+
+	return ccu_gate_helper_disable(&nkm->common, nkm->enable);
+}
+
+static int ccu_nkm_enable(struct clk_hw *hw)
+{
+	struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
+
+	return ccu_gate_helper_enable(&nkm->common, nkm->enable);
+}
+
+static int ccu_nkm_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
+
+	return ccu_gate_helper_is_enabled(&nkm->common, nkm->enable);
+}
+
+static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
+	unsigned long n, m, k;
+	u32 reg;
+
+	reg = readl(nkm->common.base + nkm->common.reg);
+
+	n = reg >> nkm->n.shift;
+	n &= (1 << nkm->n.width) - 1;
+
+	k = reg >> nkm->k.shift;
+	k &= (1 << nkm->k.width) - 1;
+
+	m = reg >> nkm->m.shift;
+	m &= (1 << nkm->m.width) - 1;
+
+	return parent_rate * (n + 1) * (k + 1) / (m + 1);
+}
+
+static long ccu_nkm_round_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long *parent_rate)
+{
+	struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
+	unsigned long n, k, m;
+
+	ccu_nkm_find_best(*parent_rate, rate, 1 << nkm->n.width,
+			  1 << nkm->k.width, 1 << nkm->m.width,
+			  &n, &k, &m);
+
+	return *parent_rate * n * k / m;
+}
+
+static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long parent_rate)
+{
+	struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
+	unsigned long n, k, m;
+	unsigned long flags;
+	u32 reg;
+
+	ccu_nkm_find_best(parent_rate, rate, 1 << nkm->n.width,
+			  1 << nkm->k.width, 1 << nkm->m.width,
+			  &n, &k, &m);
+
+	spin_lock_irqsave(nkm->common.lock, flags);
+
+	reg = readl(nkm->common.base + nkm->common.reg);
+	reg &= ~GENMASK(nkm->n.width + nkm->n.shift, nkm->n.shift);
+	reg &= ~GENMASK(nkm->k.width + nkm->k.shift, nkm->k.shift);
+	reg &= ~GENMASK(nkm->m.width + nkm->m.shift, nkm->m.shift);
+
+	reg |= (n - 1) << nkm->m.shift;
+	reg |= (k - 1) << nkm->m.shift;
+	reg |= (m - 1) << nkm->m.shift;
+
+	writel(reg, nkm->common.base + nkm->common.reg);
+
+	spin_unlock_irqrestore(nkm->common.lock, flags);
+
+	ccu_helper_wait_for_lock(&nkm->common, nkm->lock);
+
+	return 0;
+}
+
+const struct clk_ops ccu_nkm_ops = {
+	.disable	= ccu_nkm_disable,
+	.enable		= ccu_nkm_enable,
+	.is_enabled	= ccu_nkm_is_enabled,
+
+	.recalc_rate	= ccu_nkm_recalc_rate,
+	.round_rate	= ccu_nkm_round_rate,
+	.set_rate	= ccu_nkm_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
new file mode 100644
index 000000000000..1301e9f08305
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_nkm.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_NKM_H_
+#define _CCU_NKM_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_factor.h"
+#include "ccu_common.h"
+
+struct ccu_nkm {
+	u32			enable;
+	u32			lock;
+
+	struct ccu_factor	n;
+	struct ccu_factor	k;
+	struct ccu_factor	m;
+
+	struct ccu_common	common;
+};
+
+static inline struct ccu_nkm *hw_to_ccu_nkm(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_nkm, common);
+}
+
+extern const struct clk_ops ccu_nkm_ops;
+
+#endif /* _CCU_NKM_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:46 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:46 +0200
Subject: [PATCH 11/16] clk: sunxi-ng: Add N-K-factor clock support
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-12-git-send-email-maxime.ripard@free-electrons.com>

Introduce support for clocks that use a combination of two linear
multipliers.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile |   1 +
 drivers/clk/sunxi-ng/ccu_nk.c | 147 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_nk.h |  44 +++++++++++++
 3 files changed, 192 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu_nk.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_nk.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 09fce7467784..e29ddae99653 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -7,5 +7,6 @@ obj-y += ccu_gate.o
 obj-y += ccu_m.o
 obj-y += ccu_mp.o
 obj-y += ccu_mux.o
+obj-y += ccu_nk.o
 obj-y += ccu_p.o
 obj-y += ccu_phase.o
diff --git a/drivers/clk/sunxi-ng/ccu_nk.c b/drivers/clk/sunxi-ng/ccu_nk.c
new file mode 100644
index 000000000000..46eede3e986e
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_nk.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/rational.h>
+
+#include "ccu_gate.h"
+#include "ccu_nk.h"
+
+void ccu_nk_find_best(unsigned long parent, unsigned long rate,
+		      unsigned int max_n, unsigned int max_k,
+		      unsigned int *n, unsigned int *k)
+{
+	unsigned long best_rate = 0;
+	unsigned int best_k = 0, best_n =0;
+	unsigned int _k, _n;
+
+	for (_k = 0; _k <= max_k; _k++) {
+		for (_n = 0; _n <= max_n; _n++) {
+			unsigned long tmp_rate = parent * _n * _k;
+
+			if (tmp_rate > rate)
+				continue;
+
+			if ((rate - tmp_rate) < (rate - best_rate)) {
+				best_rate = tmp_rate;
+				best_k = _k;
+				best_n = _n;
+			}
+		}
+	}
+
+	*k = best_k;
+	*n = best_n;
+}
+
+static void ccu_nk_disable(struct clk_hw *hw)
+{
+	struct ccu_nk *nk = hw_to_ccu_nk(hw);
+
+	return ccu_gate_helper_disable(&nk->common, nk->enable);
+}
+
+static int ccu_nk_enable(struct clk_hw *hw)
+{
+	struct ccu_nk *nk = hw_to_ccu_nk(hw);
+
+	return ccu_gate_helper_enable(&nk->common, nk->enable);
+}
+
+static int ccu_nk_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_nk *nk = hw_to_ccu_nk(hw);
+
+	return ccu_gate_helper_is_enabled(&nk->common, nk->enable);
+}
+
+static unsigned long ccu_nk_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct ccu_nk *nk = hw_to_ccu_nk(hw);
+	unsigned long rate, n, k;
+	u32 reg;
+
+	reg = readl(nk->common.base + nk->common.reg);
+
+	n = reg >> nk->n.shift;
+	n &= (1 << nk->n.width) - 1;
+
+	k = reg >> nk->k.shift;
+	k &= (1 << nk->k.width) - 1;
+
+	rate = parent_rate * (n + 1) * (k + 1);
+
+	if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
+		rate = rate / nk->fixed_post_div;
+
+	return rate;
+}
+
+static long ccu_nk_round_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long *parent_rate)
+{
+	struct ccu_nk *nk = hw_to_ccu_nk(hw);
+	unsigned int n, k;
+
+	if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
+		rate = rate * nk->fixed_post_div;
+
+	ccu_nk_find_best(*parent_rate, rate,
+			 1 << nk->n.width, 1 << nk->k.width,
+			 &n, &k);
+
+	rate = *parent_rate * n * k;
+	if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
+		rate = rate / nk->fixed_post_div;
+
+	return rate;
+}
+
+static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long parent_rate)
+{
+	struct ccu_nk *nk = hw_to_ccu_nk(hw);
+	unsigned long flags;
+	unsigned int n, k;
+	u32 reg;
+
+	if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
+		rate = rate * nk->fixed_post_div;
+
+	ccu_nk_find_best(parent_rate, rate,
+			 1 << nk->n.width, 1 << nk->k.width,
+			 &n, &k);
+
+	spin_lock_irqsave(nk->common.lock, flags);
+
+	reg = readl(nk->common.base + nk->common.reg);
+	reg &= ~GENMASK(nk->n.width + nk->n.shift, nk->n.shift);
+	reg &= ~GENMASK(nk->k.width + nk->k.shift, nk->k.shift);
+
+	writel(reg | ((k - 1) << nk->k.shift) | ((n - 1) << nk->n.shift),
+	       nk->common.base + nk->common.reg);
+
+	spin_unlock_irqrestore(nk->common.lock, flags);
+
+	ccu_helper_wait_for_lock(&nk->common, nk->lock);
+
+	return 0;
+}
+
+const struct clk_ops ccu_nk_ops = {
+	.disable	= ccu_nk_disable,
+	.enable		= ccu_nk_enable,
+	.is_enabled	= ccu_nk_is_enabled,
+
+	.recalc_rate	= ccu_nk_recalc_rate,
+	.round_rate	= ccu_nk_round_rate,
+	.set_rate	= ccu_nk_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_nk.h b/drivers/clk/sunxi-ng/ccu_nk.h
new file mode 100644
index 000000000000..cdbbd45815c6
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_nk.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_NK_H_
+#define _CCU_NK_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+#include "ccu_factor.h"
+
+struct ccu_nk {
+	u16			reg;
+	u32			enable;
+	u32			lock;
+
+	struct ccu_factor	n;
+	struct ccu_factor	k;
+
+	unsigned int		fixed_post_div;
+
+	struct ccu_common	common;
+};
+
+static inline struct ccu_nk *hw_to_ccu_nk(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_nk, common);
+}
+
+extern const struct clk_ops ccu_nk_ops;
+
+#endif /* _CCU_NK_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:43 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:43 +0200
Subject: [PATCH 08/16] clk: sunxi-ng: Add M-factor clock support
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-9-git-send-email-maxime.ripard@free-electrons.com>

Introduce support for clocks that divide by a linear factor.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile |   1 +
 drivers/clk/sunxi-ng/ccu_m.c  | 135 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_m.h  | 101 +++++++++++++++++++++++++++++++
 3 files changed, 237 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu_m.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_m.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index a47a3bbdf285..f41de901c607 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -4,5 +4,6 @@ obj-y += ccu_reset.o
 obj-y += ccu_div_table.o
 obj-y += ccu_fixed_factor.o
 obj-y += ccu_gate.o
+obj-y += ccu_m.o
 obj-y += ccu_mux.o
 obj-y += ccu_phase.o
diff --git a/drivers/clk/sunxi-ng/ccu_m.c b/drivers/clk/sunxi-ng/ccu_m.c
new file mode 100644
index 000000000000..424eb6da0d5b
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_m.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "ccu_gate.h"
+#include "ccu_m.h"
+#include "ccu_mux.h"
+
+static void ccu_m_find_best(unsigned long parent, unsigned long rate,
+			    unsigned int max_m, unsigned int *m)
+{
+	unsigned int _m = parent / rate;
+
+	if (_m > max_m)
+		_m = max_m;
+
+	*m = _m;
+}
+
+static unsigned long ccu_m_round_rate(struct ccu_mux_internal *mux,
+				       unsigned long parent_rate,
+				       unsigned long rate,
+				       void *data)
+{
+	struct ccu_m *cm = data;
+	unsigned int m;
+
+	ccu_m_find_best(parent_rate, rate, 1 << cm->m.width, &m);
+
+	return parent_rate / m;
+}
+
+
+static void ccu_m_disable(struct clk_hw *hw)
+{
+	struct ccu_m *cm = hw_to_ccu_m(hw);
+
+	return ccu_gate_helper_disable(&cm->common, cm->enable);
+}
+
+static int ccu_m_enable(struct clk_hw *hw)
+{
+	struct ccu_m *cm = hw_to_ccu_m(hw);
+
+	return ccu_gate_helper_enable(&cm->common, cm->enable);
+}
+
+static int ccu_m_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_m *cm = hw_to_ccu_m(hw);
+
+	return ccu_gate_helper_is_enabled(&cm->common, cm->enable);
+}
+
+static unsigned long ccu_m_recalc_rate(struct clk_hw *hw,
+				       unsigned long parent_rate)
+{
+	struct ccu_m *cm = hw_to_ccu_m(hw);
+	unsigned long m;
+	u32 reg;
+
+	reg = readl(cm->common.base + cm->common.reg);
+
+	m = reg >> cm->m.shift;
+	m &= (1 << cm->m.width) - 1;
+
+	return parent_rate / (m + 1);
+}
+
+static int ccu_m_determine_rate(struct clk_hw *hw,
+				struct clk_rate_request *req)
+{
+	struct ccu_m *cm = hw_to_ccu_m(hw);
+
+	return ccu_mux_helper_determine_rate(&cm->common, &cm->mux,
+					     req, ccu_m_round_rate, cm);
+}
+
+static int ccu_m_set_rate(struct clk_hw *hw, unsigned long rate,
+			  unsigned long parent_rate)
+{
+	struct ccu_m *cm = hw_to_ccu_m(hw);
+	unsigned long flags;
+	unsigned int m;
+	u32 reg;
+
+	ccu_m_find_best(parent_rate, rate, 1 << cm->m.width, &m);
+
+	spin_lock_irqsave(cm->common.lock, flags);
+
+	reg = readl(cm->common.base + cm->common.reg);
+	reg &= ((1 << cm->m.width) - 1) << cm->m.shift;
+
+	writel(reg | ((m - 1) << cm->m.shift),
+	       cm->common.base + cm->common.reg);
+
+	spin_unlock_irqrestore(cm->common.lock, flags);
+
+	return 0;
+}
+
+static u8 ccu_m_get_parent(struct clk_hw *hw)
+{
+	struct ccu_m *cm = hw_to_ccu_m(hw);
+
+	return ccu_mux_helper_get_parent(&cm->common, &cm->mux);
+}
+
+static int ccu_m_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct ccu_m *cm = hw_to_ccu_m(hw);
+
+	return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index);
+}
+
+const struct clk_ops ccu_m_ops = {
+	.disable	= ccu_m_disable,
+	.enable		= ccu_m_enable,
+	.is_enabled	= ccu_m_is_enabled,
+
+	.get_parent	= ccu_m_get_parent,
+	.set_parent	= ccu_m_set_parent,
+
+	.determine_rate	= ccu_m_determine_rate,
+	.recalc_rate	= ccu_m_recalc_rate,
+	.set_rate	= ccu_m_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_m.h b/drivers/clk/sunxi-ng/ccu_m.h
new file mode 100644
index 000000000000..625c0a7cef43
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_m.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_M_H_
+#define _CCU_M_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
+#include "ccu_factor.h"
+#include "ccu_mux.h"
+
+struct ccu_m {
+	u32			enable;
+
+	struct ccu_factor	m;
+	struct ccu_mux_internal	mux;
+	struct ccu_common	common;
+};
+
+#define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth,	\
+		    _flags)						\
+	struct ccu_m _struct = {					\
+		.m	= SUNXI_CLK_FACTOR(_mshift, _mwidth),		\
+		.common	= {						\
+			.reg		= _reg,				\
+			.hw.init	= SUNXI_HW_INIT(_name,		\
+							_parent,	\
+							&ccu_m_ops,	\
+							_flags),	\
+		},							\
+	}
+
+#define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,		\
+			      _mshift, _mwidth,	_gate,			\
+			      _flags)					\
+	struct ccu_m _struct = {					\
+		.enable	= _gate,					\
+		.m	= SUNXI_CLK_FACTOR(_mshift, _mwidth),		\
+		.common	= {						\
+			.reg		= _reg,				\
+			.features	= CCU_FEATURE_GATE,		\
+			.hw.init	= SUNXI_HW_INIT(_name,		\
+							_parent,	\
+							&ccu_m_ops,	\
+							_flags),	\
+		},							\
+	}
+
+#define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg,		\
+			     _mshift, _mwidth, _muxshift, _muxwidth,	\
+			     _flags)					\
+	struct ccu_m _struct = {					\
+		.m	= SUNXI_CLK_FACTOR(_mshift, _mwidth),		\
+		.mux	= SUNXI_CLK_MUX(_muxshift, _muxwidth),		\
+		.common	= {						\
+			.reg		= _reg,				\
+			.hw.init	= SUNXI_HW_INIT_PARENTS(_name,	\
+								_parents, \
+								&ccu_m_ops, \
+								_flags), \
+		},							\
+	}
+
+#define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
+				  _mshift, _mwidth, _muxshift, _muxwidth, \
+				  _gate, _flags)			\
+	struct ccu_m _struct = {					\
+		.enable	= _gate,					\
+		.m	= SUNXI_CLK_FACTOR(_mshift, _mwidth),		\
+		.mux	= SUNXI_CLK_MUX(_muxshift, _muxwidth),		\
+		.common	= {						\
+			.reg		= _reg,				\
+			.features	= CCU_FEATURE_GATE,		\
+			.hw.init	= SUNXI_HW_INIT_PARENTS(_name,	\
+								_parents, \
+								&ccu_m_ops, \
+								_flags), \
+		},							\
+	}
+
+static inline struct ccu_m *hw_to_ccu_m(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_m, common);
+}
+
+extern const struct clk_ops ccu_m_ops;
+
+#endif /* _CCU_M_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:51 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:51 +0200
Subject: [PATCH 16/16] ARM: dt: sun8i: switch the H3 to the new CCU driver
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-17-git-send-email-maxime.ripard@free-electrons.com>

Now that we have a different clock representation, switch to it.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 arch/arm/boot/dts/sun8i-h3.dtsi | 310 ++++++++--------------------------------
 1 file changed, 58 insertions(+), 252 deletions(-)

diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index 4a4926b0b0ed..f6ea192abcf6 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -42,8 +42,10 @@
 
 #include "skeleton.dtsi"
 
+#include <dt-bindings/clock/sun8i-h3.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/pinctrl/sun4i-a10.h>
+#include <dt-bindings/reset/sun8i-h3.h>
 
 / {
 	interrupt-parent = <&gic>;
@@ -104,191 +106,6 @@
 			clock-output-names = "osc32k";
 		};
 
-		pll1: clk at 01c20000 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun8i-a23-pll1-clk";
-			reg = <0x01c20000 0x4>;
-			clocks = <&osc24M>;
-			clock-output-names = "pll1";
-		};
-
-		/* dummy clock until actually implemented */
-		pll5: pll5_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <0>;
-			clock-output-names = "pll5";
-		};
-
-		pll6: clk at 01c20028 {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun6i-a31-pll6-clk";
-			reg = <0x01c20028 0x4>;
-			clocks = <&osc24M>;
-			clock-output-names = "pll6", "pll6x2";
-		};
-
-		pll6d2: pll6d2_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-factor-clock";
-			clock-div = <2>;
-			clock-mult = <1>;
-			clocks = <&pll6 0>;
-			clock-output-names = "pll6d2";
-		};
-
-		/* dummy clock until pll6 can be reused */
-		pll8: pll8_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <1>;
-			clock-output-names = "pll8";
-		};
-
-		cpu: cpu_clk at 01c20050 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-cpu-clk";
-			reg = <0x01c20050 0x4>;
-			clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>;
-			clock-output-names = "cpu";
-		};
-
-		axi: axi_clk at 01c20050 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-axi-clk";
-			reg = <0x01c20050 0x4>;
-			clocks = <&cpu>;
-			clock-output-names = "axi";
-		};
-
-		ahb1: ahb1_clk at 01c20054 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun6i-a31-ahb1-clk";
-			reg = <0x01c20054 0x4>;
-			clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>;
-			clock-output-names = "ahb1";
-		};
-
-		ahb2: ahb2_clk at 01c2005c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun8i-h3-ahb2-clk";
-			reg = <0x01c2005c 0x4>;
-			clocks = <&ahb1>, <&pll6d2>;
-			clock-output-names = "ahb2";
-		};
-
-		apb1: apb1_clk at 01c20054 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-apb0-clk";
-			reg = <0x01c20054 0x4>;
-			clocks = <&ahb1>;
-			clock-output-names = "apb1";
-		};
-
-		apb2: apb2_clk at 01c20058 {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-apb1-clk";
-			reg = <0x01c20058 0x4>;
-			clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>;
-			clock-output-names = "apb2";
-		};
-
-		bus_gates: clk at 01c20060 {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun8i-h3-bus-gates-clk";
-			reg = <0x01c20060 0x14>;
-			clocks = <&ahb1>, <&ahb2>, <&apb1>, <&apb2>;
-			clock-names = "ahb1", "ahb2", "apb1", "apb2";
-			clock-indices = <5>, <6>, <8>,
-					<9>, <10>, <13>,
-					<14>, <17>, <18>,
-					<19>, <20>,
-					<21>, <23>,
-					<24>, <25>,
-					<26>, <27>,
-					<28>, <29>,
-					<30>, <31>, <32>,
-					<35>, <36>, <37>,
-					<40>, <41>, <43>,
-					<44>, <52>, <53>,
-					<54>, <64>,
-					<65>, <69>, <72>,
-					<76>, <77>, <78>,
-					<96>, <97>, <98>,
-					<112>, <113>,
-					<114>, <115>,
-					<116>, <128>, <135>;
-			clock-output-names = "bus_ce", "bus_dma", "bus_mmc0",
-					     "bus_mmc1", "bus_mmc2", "bus_nand",
-					     "bus_sdram", "bus_gmac", "bus_ts",
-					     "bus_hstimer", "bus_spi0",
-					     "bus_spi1", "bus_otg",
-					     "bus_otg_ehci0", "bus_ehci1",
-					     "bus_ehci2", "bus_ehci3",
-					     "bus_otg_ohci0", "bus_ohci1",
-					     "bus_ohci2", "bus_ohci3", "bus_ve",
-					     "bus_lcd0", "bus_lcd1", "bus_deint",
-					     "bus_csi", "bus_tve", "bus_hdmi",
-					     "bus_de", "bus_gpu", "bus_msgbox",
-					     "bus_spinlock", "bus_codec",
-					     "bus_spdif", "bus_pio", "bus_ths",
-					     "bus_i2s0", "bus_i2s1", "bus_i2s2",
-					     "bus_i2c0", "bus_i2c1", "bus_i2c2",
-					     "bus_uart0", "bus_uart1",
-					     "bus_uart2", "bus_uart3",
-					     "bus_scr", "bus_ephy", "bus_dbg";
-		};
-
-		mmc0_clk: clk at 01c20088 {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun4i-a10-mmc-clk";
-			reg = <0x01c20088 0x4>;
-			clocks = <&osc24M>, <&pll6 0>, <&pll8>;
-			clock-output-names = "mmc0",
-					     "mmc0_output",
-					     "mmc0_sample";
-		};
-
-		mmc1_clk: clk at 01c2008c {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun4i-a10-mmc-clk";
-			reg = <0x01c2008c 0x4>;
-			clocks = <&osc24M>, <&pll6 0>, <&pll8>;
-			clock-output-names = "mmc1",
-					     "mmc1_output",
-					     "mmc1_sample";
-		};
-
-		mmc2_clk: clk at 01c20090 {
-			#clock-cells = <1>;
-			compatible = "allwinner,sun4i-a10-mmc-clk";
-			reg = <0x01c20090 0x4>;
-			clocks = <&osc24M>, <&pll6 0>, <&pll8>;
-			clock-output-names = "mmc2",
-					     "mmc2_output",
-					     "mmc2_sample";
-		};
-
-		usb_clk: clk at 01c200cc {
-			#clock-cells = <1>;
-			#reset-cells = <1>;
-			compatible = "allwinner,sun8i-h3-usb-clk";
-			reg = <0x01c200cc 0x4>;
-			clocks = <&osc24M>;
-			clock-output-names = "usb_phy0", "usb_phy1",
-					     "usb_phy2", "usb_phy3",
-					     "usb_ohci0", "usb_ohci1",
-					     "usb_ohci2", "usb_ohci3";
-		};
-
-		mbus_clk: clk at 01c2015c {
-			#clock-cells = <0>;
-			compatible = "allwinner,sun8i-a23-mbus-clk";
-			reg = <0x01c2015c 0x4>;
-			clocks = <&osc24M>, <&pll6 1>, <&pll5>;
-			clock-output-names = "mbus";
-		};
-
 		apb0: apb0_clk {
 			compatible = "fixed-factor-clock";
 			#clock-cells = <0>;
@@ -327,23 +144,23 @@
 			compatible = "allwinner,sun8i-h3-dma";
 			reg = <0x01c02000 0x1000>;
 			interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bus_gates 6>;
-			resets = <&ahb_rst 6>;
+			clocks = <&ccu CLK_BUS_DMA>;
+			resets = <&ccu RST_BUS_DMA>;
 			#dma-cells = <1>;
 		};
 
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&bus_gates 8>,
-				 <&mmc0_clk 0>,
-				 <&mmc0_clk 1>,
-				 <&mmc0_clk 2>;
+			clocks = <&ccu CLK_BUS_MMC0>,
+				 <&ccu CLK_MMC0>,
+				 <&ccu CLK_MMC0_OUTPUT>,
+				 <&ccu CLK_MMC0_SAMPLE>;
 			clock-names = "ahb",
 				      "mmc",
 				      "output",
 				      "sample";
-			resets = <&ahb_rst 8>;
+			resets = <&ccu RST_BUS_MMC0>;
 			reset-names = "ahb";
 			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
@@ -354,15 +171,15 @@
 		mmc1: mmc at 01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&bus_gates 9>,
-				 <&mmc1_clk 0>,
-				 <&mmc1_clk 1>,
-				 <&mmc1_clk 2>;
+			clocks = <&ccu CLK_BUS_MMC1>,
+				 <&ccu CLK_MMC1>,
+				 <&ccu CLK_MMC1_OUTPUT>,
+				 <&ccu CLK_MMC1_SAMPLE>;
 			clock-names = "ahb",
 				      "mmc",
 				      "output",
 				      "sample";
-			resets = <&ahb_rst 9>;
+			resets = <&ccu RST_BUS_MMC1>;
 			reset-names = "ahb";
 			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
@@ -373,15 +190,15 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&bus_gates 10>,
-				 <&mmc2_clk 0>,
-				 <&mmc2_clk 1>,
-				 <&mmc2_clk 2>;
+			clocks = <&ccu CLK_BUS_MMC2>,
+				 <&ccu CLK_MMC2>,
+				 <&ccu CLK_MMC2_OUTPUT>,
+				 <&ccu CLK_MMC2_SAMPLE>;
 			clock-names = "ahb",
 				      "mmc",
 				      "output",
 				      "sample";
-			resets = <&ahb_rst 10>;
+			resets = <&ccu RST_BUS_MMC2>;
 			reset-names = "ahb";
 			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
@@ -401,18 +218,18 @@
 				    "pmu1",
 				    "pmu2",
 				    "pmu3";
-			clocks = <&usb_clk 8>,
-				 <&usb_clk 9>,
-				 <&usb_clk 10>,
-				 <&usb_clk 11>;
+			clocks = <&ccu CLK_USB_PHY0>,
+				 <&ccu CLK_USB_PHY1>,
+				 <&ccu CLK_USB_PHY2>,
+				 <&ccu CLK_USB_PHY3>;
 			clock-names = "usb0_phy",
 				      "usb1_phy",
 				      "usb2_phy",
 				      "usb3_phy";
-			resets = <&usb_clk 0>,
-				 <&usb_clk 1>,
-				 <&usb_clk 2>,
-				 <&usb_clk 3>;
+			resets = <&ccu RST_USB_PHY0>,
+				 <&ccu RST_USB_PHY1>,
+				 <&ccu RST_USB_PHY2>,
+				 <&ccu RST_USB_PHY3>;
 			reset-names = "usb0_reset",
 				      "usb1_reset",
 				      "usb2_reset",
@@ -425,8 +242,8 @@
 			compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
 			reg = <0x01c1b000 0x100>;
 			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bus_gates 25>, <&bus_gates 29>;
-			resets = <&ahb_rst 25>, <&ahb_rst 29>;
+			clocks = <&ccu CLK_BUS_EHCI1>, <&ccu CLK_BUS_OHCI1>;
+			resets = <&ccu RST_BUS_EHCI1>, <&ccu RST_BUS_OHCI1>;
 			phys = <&usbphy 1>;
 			phy-names = "usb";
 			status = "disabled";
@@ -436,9 +253,9 @@
 			compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
 			reg = <0x01c1b400 0x100>;
 			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bus_gates 29>, <&bus_gates 25>,
-				 <&usb_clk 17>;
-			resets = <&ahb_rst 29>, <&ahb_rst 25>;
+			clocks = <&ccu CLK_BUS_EHCI1>, <&ccu CLK_BUS_OHCI1>,
+				 <&ccu CLK_USB_OHCI1>;
+			resets = <&ccu RST_BUS_EHCI1>, <&ccu RST_BUS_OHCI1>;
 			phys = <&usbphy 1>;
 			phy-names = "usb";
 			status = "disabled";
@@ -448,8 +265,8 @@
 			compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
 			reg = <0x01c1c000 0x100>;
 			interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bus_gates 26>, <&bus_gates 30>;
-			resets = <&ahb_rst 26>, <&ahb_rst 30>;
+			clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>;
+			resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>;
 			phys = <&usbphy 2>;
 			phy-names = "usb";
 			status = "disabled";
@@ -459,9 +276,9 @@
 			compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
 			reg = <0x01c1c400 0x100>;
 			interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bus_gates 30>, <&bus_gates 26>,
-				 <&usb_clk 18>;
-			resets = <&ahb_rst 30>, <&ahb_rst 26>;
+			clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>,
+				 <&ccu CLK_USB_OHCI2>;
+			resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>;
 			phys = <&usbphy 2>;
 			phy-names = "usb";
 			status = "disabled";
@@ -471,8 +288,8 @@
 			compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
 			reg = <0x01c1d000 0x100>;
 			interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bus_gates 27>, <&bus_gates 31>;
-			resets = <&ahb_rst 27>, <&ahb_rst 31>;
+			clocks = <&ccu CLK_BUS_EHCI3>, <&ccu CLK_BUS_OHCI3>;
+			resets = <&ccu RST_BUS_EHCI3>, <&ccu RST_BUS_OHCI3>;
 			phys = <&usbphy 3>;
 			phy-names = "usb";
 			status = "disabled";
@@ -482,20 +299,27 @@
 			compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
 			reg = <0x01c1d400 0x100>;
 			interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bus_gates 31>, <&bus_gates 27>,
-				 <&usb_clk 19>;
-			resets = <&ahb_rst 31>, <&ahb_rst 27>;
+			clocks = <&ccu CLK_BUS_EHCI3>, <&ccu CLK_BUS_OHCI3>,
+				 <&ccu CLK_USB_OHCI3>;
+			resets = <&ccu RST_BUS_EHCI3>, <&ccu RST_BUS_OHCI3>;
 			phys = <&usbphy 3>;
 			phy-names = "usb";
 			status = "disabled";
 		};
 
+		ccu: clock at 01c20000 {
+			compatible = "allwinner,sun8i-h3-ccu";
+			reg = <0x01c20000 0x400>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
 		pio: pinctrl at 01c20800 {
 			compatible = "allwinner,sun8i-h3-pinctrl";
 			reg = <0x01c20800 0x400>;
 			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bus_gates 69>;
+			clocks = <&ccu CLK_BUS_PIO>;
 			gpio-controller;
 			#gpio-cells = <3>;
 			interrupt-controller;
@@ -542,24 +366,6 @@
 			};
 		};
 
-		ahb_rst: reset at 01c202c0 {
-			#reset-cells = <1>;
-			compatible = "allwinner,sun6i-a31-ahb1-reset";
-			reg = <0x01c202c0 0xc>;
-		};
-
-		apb1_rst: reset at 01c202d0 {
-			#reset-cells = <1>;
-			compatible = "allwinner,sun6i-a31-clock-reset";
-			reg = <0x01c202d0 0x4>;
-		};
-
-		apb2_rst: reset at 01c202d8 {
-			#reset-cells = <1>;
-			compatible = "allwinner,sun6i-a31-clock-reset";
-			reg = <0x01c202d8 0x4>;
-		};
-
 		timer at 01c20c00 {
 			compatible = "allwinner,sun4i-a10-timer";
 			reg = <0x01c20c00 0xa0>;
@@ -580,8 +386,8 @@
 			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&bus_gates 112>;
-			resets = <&apb2_rst 16>;
+			clocks = <&ccu CLK_BUS_UART0>;
+			resets = <&ccu RST_BUS_UART0>;
 			dmas = <&dma 6>, <&dma 6>;
 			dma-names = "rx", "tx";
 			status = "disabled";
@@ -593,8 +399,8 @@
 			interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&bus_gates 113>;
-			resets = <&apb2_rst 17>;
+			clocks = <&ccu CLK_BUS_UART1>;
+			resets = <&ccu RST_BUS_UART1>;
 			dmas = <&dma 7>, <&dma 7>;
 			dma-names = "rx", "tx";
 			status = "disabled";
@@ -606,8 +412,8 @@
 			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&bus_gates 114>;
-			resets = <&apb2_rst 18>;
+			clocks = <&ccu CLK_BUS_UART2>;
+			resets = <&ccu RST_BUS_UART2>;
 			dmas = <&dma 8>, <&dma 8>;
 			dma-names = "rx", "tx";
 			status = "disabled";
@@ -619,8 +425,8 @@
 			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
-			clocks = <&bus_gates 115>;
-			resets = <&apb2_rst 19>;
+			clocks = <&ccu CLK_BUS_UART3>;
+			resets = <&ccu RST_BUS_UART3>;
 			dmas = <&dma 9>, <&dma 9>;
 			dma-names = "rx", "tx";
 			status = "disabled";
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:49 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:49 +0200
Subject: [PATCH 14/16] clk: sunxi-ng: Add N-K-M-P factor clock
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-15-git-send-email-maxime.ripard@free-electrons.com>

Introduce support for clocks that use a combination of two linear
multipliers (N and K factors), one linear divider (M) and one power of two
divider (P).

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile   |   1 +
 drivers/clk/sunxi-ng/ccu_nkmp.c | 157 ++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_nkmp.h |  43 +++++++++++
 3 files changed, 201 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu_nkmp.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_nkmp.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 2bb8bc22e907..c794f57b6fb1 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -9,6 +9,7 @@ obj-y += ccu_mp.o
 obj-y += ccu_mux.o
 obj-y += ccu_nk.o
 obj-y += ccu_nkm.o
+obj-y += ccu_nkmp.o
 obj-y += ccu_nm.o
 obj-y += ccu_p.o
 obj-y += ccu_phase.o
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c
new file mode 100644
index 000000000000..b7da00773cd6
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_nkmp.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/rational.h>
+
+#include "ccu_gate.h"
+#include "ccu_nkmp.h"
+
+void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
+			unsigned long max_n, unsigned long max_k,
+			unsigned long max_m, unsigned long max_p,
+			unsigned long *n, unsigned long *k,
+			unsigned long *m, unsigned long *p)
+{
+	unsigned long best_rate = 0;
+	unsigned long best_n = 0, best_k = 0, best_m = 0, best_p = 0;
+	unsigned long _n, _k, _m, _p;
+
+	for (_k = 1; _k <= max_k; _k++) {
+		for (_p = 0; _p <= max_p; _p++) {
+			unsigned long tmp_rate;
+
+			rational_best_approximation(rate / _k, parent << _p,
+						    max_n, max_m, &_n, &_m);
+
+			tmp_rate = (parent * _n * _k >> _p) / _m;
+
+			if (tmp_rate > rate)
+				continue;
+
+			if ((rate - tmp_rate) < (rate - best_rate)) {
+				best_rate = tmp_rate;
+				best_n = _n;
+				best_k = _k;
+				best_m = _m;
+				best_p = _p;
+			}
+		}
+	}
+
+	*n = best_n;
+	*k = best_k;
+	*m = best_m;
+	*p = best_p;
+}
+
+static void ccu_nkmp_disable(struct clk_hw *hw)
+{
+	struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+
+	return ccu_gate_helper_disable(&nkmp->common, nkmp->enable);
+}
+
+static int ccu_nkmp_enable(struct clk_hw *hw)
+{
+	struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+
+	return ccu_gate_helper_enable(&nkmp->common, nkmp->enable);
+}
+
+static int ccu_nkmp_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+
+	return ccu_gate_helper_is_enabled(&nkmp->common, nkmp->enable);
+}
+
+static unsigned long ccu_nkmp_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+	unsigned long n, m, k, p;
+	u32 reg;
+
+	reg = readl(nkmp->common.base + nkmp->common.reg);
+
+	n = reg >> nkmp->n.shift;
+	n &= (1 << nkmp->n.width) - 1;
+
+	k = reg >> nkmp->k.shift;
+	k &= (1 << nkmp->k.width) - 1;
+
+	m = reg >> nkmp->m.shift;
+	m &= (1 << nkmp->m.width) - 1;
+
+	p = reg >> nkmp->p.shift;
+	p &= (1 << nkmp->p.width) - 1;
+
+	return (parent_rate * (n + 1) * (k + 1) >> p) / (m + 1);
+}
+
+static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long *parent_rate)
+{
+	struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+	unsigned long n, k, m, p;
+
+	ccu_nkmp_find_best(*parent_rate, rate,
+			   1 << nkmp->n.width, 1 << nkmp->k.width,
+			   1 << nkmp->m.width, (1 << nkmp->p.width) - 1,
+			   &n, &k, &m, &p);
+
+	return (*parent_rate * n * k >> p) / m;
+}
+
+static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long parent_rate)
+{
+	struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
+	unsigned long n, k, m, p;
+	unsigned long flags;
+	u32 reg;
+
+	ccu_nkmp_find_best(parent_rate, rate,
+			   1 << nkmp->n.width, 1 << nkmp->k.width,
+			   1 << nkmp->m.width, (1 << nkmp->p.width) - 1,
+			   &n, &k, &m, &p);
+
+	spin_lock_irqsave(nkmp->common.lock, flags);
+
+	reg = readl(nkmp->common.base + nkmp->common.reg);
+	reg &= ~GENMASK(nkmp->n.width + nkmp->n.shift, nkmp->n.shift);
+	reg &= ~GENMASK(nkmp->k.width + nkmp->k.shift, nkmp->k.shift);
+	reg &= ~GENMASK(nkmp->m.width + nkmp->m.shift, nkmp->m.shift);
+	reg &= ~GENMASK(nkmp->p.width + nkmp->p.shift, nkmp->p.shift);
+
+	reg |= (n - 1) << nkmp->m.shift;
+	reg |= (k - 1) << nkmp->m.shift;
+	reg |= (m - 1) << nkmp->m.shift;
+	reg |= p << nkmp->p.shift;
+
+	writel(reg, nkmp->common.base + nkmp->common.reg);
+
+	spin_unlock_irqrestore(nkmp->common.lock, flags);
+
+	ccu_helper_wait_for_lock(&nkmp->common, nkmp->lock);
+
+	return 0;
+}
+
+const struct clk_ops ccu_nkmp_ops = {
+	.disable	= ccu_nkmp_disable,
+	.enable		= ccu_nkmp_enable,
+	.is_enabled	= ccu_nkmp_is_enabled,
+
+	.recalc_rate	= ccu_nkmp_recalc_rate,
+	.round_rate	= ccu_nkmp_round_rate,
+	.set_rate	= ccu_nkmp_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.h b/drivers/clk/sunxi-ng/ccu_nkmp.h
new file mode 100644
index 000000000000..8a91f2c837a4
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_nkmp.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_NKMP_H_
+#define _CCU_NKMP_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_factor.h"
+#include "ccu_common.h"
+
+struct ccu_nkmp {
+	u32			enable;
+	u32			lock;
+
+	struct ccu_factor	n;
+	struct ccu_factor	k;
+	struct ccu_factor	m;
+	struct ccu_factor	p;
+
+	struct ccu_common	common;
+};
+
+static inline struct ccu_nkmp *hw_to_ccu_nkmp(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_nkmp, common);
+}
+
+extern const struct clk_ops ccu_nkmp_ops;
+
+#endif /* _CCU_NKMP_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:50 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:50 +0200
Subject: [PATCH 15/16] clk: sunxi-ng: Add H3 clocks
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>

Add the list of clocks and resets found in the H3 CCU.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile        |   2 +
 drivers/clk/sunxi-ng/ccu-sun8i-h3.c  | 757 +++++++++++++++++++++++++++++++++++
 include/dt-bindings/clock/sun8i-h3.h | 162 ++++++++
 include/dt-bindings/reset/sun8i-h3.h | 103 +++++
 4 files changed, 1024 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.c
 create mode 100644 include/dt-bindings/clock/sun8i-h3.h
 create mode 100644 include/dt-bindings/reset/sun8i-h3.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index c794f57b6fb1..67ff6a92f124 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -13,3 +13,5 @@ obj-y += ccu_nkmp.o
 obj-y += ccu_nm.o
 obj-y += ccu_p.o
 obj-y += ccu_phase.o
+
+obj-y += ccu-sun8i-h3.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
new file mode 100644
index 000000000000..5ce699e95c32
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
@@ -0,0 +1,757 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+
+#include <dt-bindings/clock/sun8i-h3.h>
+#include <dt-bindings/reset/sun8i-h3.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div_table.h"
+#include "ccu_factor.h"
+#include "ccu_fixed_factor.h"
+#include "ccu_gate.h"
+#include "ccu_m.h"
+#include "ccu_mp.h"
+#include "ccu_nk.h"
+#include "ccu_nkm.h"
+#include "ccu_nkmp.h"
+#include "ccu_nm.h"
+#include "ccu_p.h"
+#include "ccu_phase.h"
+
+static struct ccu_nkmp pll_cpux_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+
+	.m		= SUNXI_CLK_FACTOR(0, 2),
+	.k		= SUNXI_CLK_FACTOR(4, 2),
+	.n		= SUNXI_CLK_FACTOR(8, 5),
+	.p		= SUNXI_CLK_FACTOR(16, 2),
+
+	.common		= {
+		.reg		= 0x000,
+		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
+		.hw.init	= SUNXI_HW_INIT("pll-cpux",
+						"osc24M",
+						&ccu_nkmp_ops,
+						0),
+	},
+};
+
+static struct ccu_nm pll_audio_base_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+
+	.m		= SUNXI_CLK_FACTOR(0, 5),
+	.n		= SUNXI_CLK_FACTOR(8, 7),
+
+	.common		= {
+		.reg		= 0x008,
+		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
+		.hw.init	= SUNXI_HW_INIT("pll-audio-base",
+						"osc24M",
+						&ccu_nm_ops,
+						0),
+	},
+};
+
+static SUNXI_CCU_M(pll_audio_clk, "pll-audio", "pll-audio-base",
+		   0x008, 16, 4, 0);
+
+static SUNXI_CCU_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
+			      "pll-audio-base", 2, 1, 0);
+static SUNXI_CCU_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
+			      "pll-audio-base", 1, 1, 0);
+static SUNXI_CCU_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
+			      "pll-audio-base", 1, 2, 0);
+
+static struct ccu_nm pll_video_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+
+	.m		= SUNXI_CLK_FACTOR(0, 4),
+	.n		= SUNXI_CLK_FACTOR(8, 7),
+
+	.common		= {
+		.reg		= 0x010,
+		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
+		.hw.init	= SUNXI_HW_INIT("pll-video",
+						"osc24M",
+						&ccu_nm_ops,
+						0),
+	},
+};
+
+static struct ccu_nm pll_ve_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+
+	.m		= SUNXI_CLK_FACTOR(0, 4),
+	.n		= SUNXI_CLK_FACTOR(8, 7),
+
+	.common		= {
+		.reg		= 0x018,
+		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
+		.hw.init	= SUNXI_HW_INIT("pll-ve",
+						"osc24M",
+						&ccu_nm_ops,
+						0),
+	},
+};
+
+static struct ccu_nkm pll_ddr_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+
+	.n		= SUNXI_CLK_FACTOR(8, 5),
+	.k		= SUNXI_CLK_FACTOR(4, 2),
+	.m		= SUNXI_CLK_FACTOR(0, 2),
+
+	.common		= {
+		.reg		= 0x020,
+		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
+		.hw.init	= SUNXI_HW_INIT("pll-ddr",
+						"osc24M",
+						&ccu_nkm_ops,
+						0),
+	},
+};
+
+static struct ccu_nk pll_periph0_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+
+	.k		= SUNXI_CLK_FACTOR(4, 2),
+	.n		= SUNXI_CLK_FACTOR(8, 5),
+	.fixed_post_div	= 2,
+
+	.common		= {
+		.reg		= 0x028,
+		.features	= (CCU_FEATURE_GATE |
+				   CCU_FEATURE_LOCK |
+				   CCU_FEATURE_FIXED_POSTDIV),
+		.hw.init	= SUNXI_HW_INIT("pll-periph0",
+						"osc24M",
+						&ccu_nk_ops,
+						0),
+	},
+};
+
+static SUNXI_CCU_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
+			      "pll-periph0", 1, 2, 0);
+
+static struct ccu_nm pll_gpu_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+
+	.m		= SUNXI_CLK_FACTOR(0, 4),
+	.n		= SUNXI_CLK_FACTOR(8, 7),
+
+	.common		= {
+		.reg		= 0x038,
+		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
+		.hw.init	= SUNXI_HW_INIT("pll-gpu",
+						"osc24M",
+						&ccu_nm_ops,
+						0),
+	},
+};
+
+static struct ccu_nk pll_periph1_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+
+	.k		= SUNXI_CLK_FACTOR(4, 2),
+	.n		= SUNXI_CLK_FACTOR(8, 5),
+	.fixed_post_div	= 2,
+
+	.common		= {
+		.reg		= 0x044,
+		.features	= (CCU_FEATURE_GATE |
+				   CCU_FEATURE_LOCK |
+				   CCU_FEATURE_FIXED_POSTDIV),
+		.hw.init	= SUNXI_HW_INIT("pll-periph1",
+						"osc24M",
+						&ccu_nk_ops,
+						0),
+	},
+};
+
+static struct ccu_nm pll_de_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+
+	.m		= SUNXI_CLK_FACTOR(0, 4),
+	.n		= SUNXI_CLK_FACTOR(8, 7),
+
+	.common		= {
+		.reg		= 0x048,
+		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
+		.hw.init	= SUNXI_HW_INIT("pll-de",
+						"osc24M",
+						&ccu_nm_ops,
+						0),
+	},
+};
+
+static const char * const cpux_parents[] = { "osc32k", "osc24M", "pll-cpux" , "pll-cpux" };
+static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
+		     0x050, 16, 2, CLK_IS_CRITICAL);
+
+static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);
+
+static const char * const ahb1_parents[] = { "osc32k", "osc24M", "axi" , "pll-periph0" };
+static struct ccu_p ahb1_clk = {
+	.p		= SUNXI_CLK_FACTOR(4, 2),
+
+	.mux		= {
+		.shift	= 12,
+		.width	= 2,
+
+		.variable_prediv	= {
+			.index	= 3,
+			.shift	= 6,
+			.width	= 2,
+		},
+	},
+
+	.common		= {
+		.reg		= 0x054,
+		.features	= CCU_FEATURE_VARIABLE_PREDIV,
+		.hw.init	= SUNXI_HW_INIT_PARENTS("ahb1",
+							ahb1_parents,
+							&ccu_p_ops,
+							0),
+	},
+};
+
+static u8 apb1_div_table [] = { 2, 2, 4, 8 };
+static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1",
+			   0x054, 8, 2, apb1_div_table, 0);
+
+static const char * const apb2_parents[] = { "osc32k", "osc24M",
+					     "pll-periph0" , "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058,
+			     0, 5,	/* M */
+			     16, 2,	/* P */
+			     24, 2,	/* mux */
+			     0);
+
+static const char * const ahb2_parents[] = { "ahb1" , "pll-periph0" };
+static struct ccu_mux ahb2_clk = {
+	.mux		= {
+		.shift	= 0,
+		.width	= 1,
+
+		.fixed_prediv	= {
+			.index	= 1,
+			.div	= 2,
+		},
+	},
+
+	.common		= {
+		.reg		= 0x05c,
+		.features	= CCU_FEATURE_FIXED_PREDIV,
+		.hw.init	= SUNXI_HW_INIT_PARENTS("ahb2",
+							ahb2_parents,
+							&ccu_mux_ops,
+							0),
+	},
+};
+
+static SUNXI_CCU_GATE(bus_ce_clk,	"bus-ce",	"ahb1",
+		      0x060, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_dma_clk,	"bus-dma",	"ahb1",
+		      0x060, BIT(6), 0);
+static SUNXI_CCU_GATE(bus_mmc0_clk,	"bus-mmc0",	"ahb1",
+		      0x060, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_mmc1_clk,	"bus-mmc1",	"ahb1",
+		      0x060, BIT(9), 0);
+static SUNXI_CCU_GATE(bus_mmc2_clk,	"bus-mmc2",	"ahb1",
+		      0x060, BIT(10), 0);
+static SUNXI_CCU_GATE(bus_nand_clk,	"bus-nand",	"ahb1",
+		      0x060, BIT(13), 0);
+static SUNXI_CCU_GATE(bus_dram_clk,	"bus-dram",	"ahb1",
+		      0x060, BIT(14), 0);
+static SUNXI_CCU_GATE(bus_emac_clk,	"bus-emac",	"ahb2",
+		      0x060, BIT(17), 0);
+static SUNXI_CCU_GATE(bus_ts_clk,	"bus-ts",	"ahb1",
+		      0x060, BIT(18), 0);
+static SUNXI_CCU_GATE(bus_hstimer_clk,	"bus-hstimer",	"ahb1",
+		      0x060, BIT(19), 0);
+static SUNXI_CCU_GATE(bus_spi0_clk,	"bus-spi0",	"ahb1",
+		      0x060, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_spi1_clk,	"bus-spi1",	"ahb1",
+		      0x060, BIT(21), 0);
+static SUNXI_CCU_GATE(bus_otg_clk,	"bus-otg",	"ahb1",
+		      0x060, BIT(23), 0);
+static SUNXI_CCU_GATE(bus_ehci0_clk,	"bus-ehci0",	"ahb2",
+		      0x060, BIT(24), 0);
+static SUNXI_CCU_GATE(bus_ehci1_clk,	"bus-ehci1",	"ahb2",
+		      0x060, BIT(25), 0);
+static SUNXI_CCU_GATE(bus_ehci2_clk,	"bus-ehci2",	"ahb2",
+		      0x060, BIT(26), 0);
+static SUNXI_CCU_GATE(bus_ehci3_clk,	"bus-ehci3",	"ahb2",
+		      0x060, BIT(27), 0);
+static SUNXI_CCU_GATE(bus_ohci0_clk,	"bus-ohci0",	"ahb2",
+		      0x060, BIT(28), 0);
+static SUNXI_CCU_GATE(bus_ohci1_clk,	"bus-ohci1",	"ahb2",
+		      0x060, BIT(29), 0);
+static SUNXI_CCU_GATE(bus_ohci2_clk,	"bus-ohci2",	"ahb2",
+		      0x060, BIT(30), 0);
+static SUNXI_CCU_GATE(bus_ohci3_clk,	"bus-ohci3",	"ahb2",
+		      0x060, BIT(31), 0);
+
+static SUNXI_CCU_GATE(bus_ve_clk,	"bus-ve",	"ahb1",
+		      0x064, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_tcon0_clk,	"bus-tcon0",	"ahb1",
+		      0x064, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_tcon1_clk,	"bus-tcon1",	"ahb1",
+		      0x064, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_deinterlace_clk,	"bus-deinterlace",	"ahb1",
+		      0x064, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_csi_clk,	"bus-csi",	"ahb1",
+		      0x064, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_tve_clk,	"bus-tve",	"ahb1",
+		      0x064, BIT(9), 0);
+static SUNXI_CCU_GATE(bus_hdmi_clk,	"bus-hdmi",	"ahb1",
+		      0x064, BIT(11), 0);
+static SUNXI_CCU_GATE(bus_de_clk,	"bus-de",	"ahb1",
+		      0x064, BIT(12), 0);
+static SUNXI_CCU_GATE(bus_gpu_clk,	"bus-gpu",	"ahb1",
+		      0x064, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_msgbox_clk,	"bus-msgbox",	"ahb1",
+		      0x064, BIT(21), 0);
+static SUNXI_CCU_GATE(bus_spinlock_clk,	"bus-spinlock",	"ahb1",
+		      0x064, BIT(22), 0);
+
+static SUNXI_CCU_GATE(bus_codec_clk,	"bus-codec",	"apb1",
+		      0x068, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_spdif_clk,	"bus-spdif",	"apb1",
+		      0x068, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_pio_clk,	"bus-pio",	"apb1",
+		      0x068, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_ths_clk,	"bus-ths",	"apb1",
+		      0x068, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_i2s0_clk,	"bus-i2s0",	"apb1",
+		      0x068, BIT(12), 0);
+static SUNXI_CCU_GATE(bus_i2s1_clk,	"bus-i2s1",	"apb1",
+		      0x068, BIT(13), 0);
+static SUNXI_CCU_GATE(bus_i2s2_clk,	"bus-i2s2",	"apb1",
+		      0x068, BIT(14), 0);
+
+static SUNXI_CCU_GATE(bus_i2c0_clk,	"bus-i2c0",	"apb2",
+		      0x06c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c1_clk,	"bus-i2c1",	"apb2",
+		      0x06c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_i2c2_clk,	"bus-i2c2",	"apb2",
+		      0x06c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_uart0_clk,	"bus-uart0",	"apb2",
+		      0x06c, BIT(16), 0);
+static SUNXI_CCU_GATE(bus_uart1_clk,	"bus-uart1",	"apb2",
+		      0x06c, BIT(17), 0);
+static SUNXI_CCU_GATE(bus_uart2_clk,	"bus-uart2",	"apb2",
+		      0x06c, BIT(18), 0);
+static SUNXI_CCU_GATE(bus_uart3_clk,	"bus-uart3",	"apb2",
+		      0x06c, BIT(19), 0);
+static SUNXI_CCU_GATE(bus_scr_clk,	"bus-scr",	"apb2",
+		      0x06c, BIT(20), 0);
+
+static SUNXI_CCU_GATE(bus_ephy_clk,	"bus-ephy",	"ahb1",
+		      0x070, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_dbg_clk,	"bus-dbg",	"ahb1",
+		      0x070, BIT(7), 0);
+
+static u8 ths_div_table [] = { 1, 2, 4, 6 };
+static SUNXI_CCU_DIV_TABLE_WITH_GATE(ths_clk, "ths", "osc24M",
+				     0x074, 0, 2, ths_div_table, BIT(31), 0);
+
+static const char * const nand_parents[] = { "osc24M", "pll-periph0",
+					     "pll-periph1" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", nand_parents, 0x080,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const char * const mmc0_parents[] = { "osc24M", "pll-periph0",
+					     "pll-periph1" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_parents, 0x088,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0",
+		       0x088, 20, 3, 0);
+static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0",
+		       0x088, 8, 3, 0);
+
+static const char * const mmc1_parents[] = { "osc24M", "pll-periph0",
+					     "pll-periph1" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc1_parents, 0x08c,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1",
+		       0x08c, 20, 3, 0);
+static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1",
+		       0x08c, 8, 3, 0);
+
+static const char * const mmc2_parents[] = { "osc24M", "pll-periph0",
+					     "pll-periph1" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc2_parents, 0x090,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2_sample", "mmc2",
+		       0x090, 20, 3, 0);
+static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2_output", "mmc2",
+		       0x090, 8, 3, 0);
+
+static const char * const ts_parents[] = { "osc24M", "pll-periph0", };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 1,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const char * const ce_parents[] = { "osc24M", "pll-periph0",
+					   "pll-periph1" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x09c,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const char * const spi0_parents[] = { "osc24M", "pll-periph0",
+					     "pll-periph1" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", spi0_parents, 0x0a0,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const char * const spi1_parents[] = { "osc24M", "pll-periph0",
+					     "pll-periph1" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", spi1_parents, 0x0a4,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const char * const i2s0_parents[] = { "pll-audio-8x", "pll-audio-4x",
+					     "pll-audio-2x" , "pll-audio" };
+static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s0_parents,
+			       0x0b0, 16, 2, BIT(31), 0);
+
+static const char * const i2s1_parents[] = { "pll-audio-8x", "pll-audio-4x",
+					     "pll-audio-2x" , "pll-audio" };
+static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s1_parents,
+			       0x0b4, 16, 2, BIT(31), 0);
+
+static const char * const i2s2_parents[] = { "pll-audio-8x", "pll-audio-4x",
+					     "pll-audio-2x" , "pll-audio" };
+static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s2_parents,
+			       0x0b8, 16, 2, BIT(31), 0);
+
+static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
+			     0x0c0, 0, 4, BIT(31), 0);
+
+static SUNXI_CCU_GATE(usb_phy0_clk,	"usb-phy0",	"osc24M",
+		      0x0cc, BIT(8), 0);
+static SUNXI_CCU_GATE(usb_phy1_clk,	"usb-phy1",	"osc24M",
+		      0x0cc, BIT(9), 0);
+static SUNXI_CCU_GATE(usb_phy2_clk,	"usb-phy2",	"osc24M",
+		      0x0cc, BIT(10), 0);
+static SUNXI_CCU_GATE(usb_phy3_clk,	"usb-phy3",	"osc24M",
+		      0x0cc, BIT(11), 0);
+static SUNXI_CCU_GATE(usb_ohci0_clk,	"usb-ohci0",	"osc24M",
+		      0x0cc, BIT(16), 0);
+static SUNXI_CCU_GATE(usb_ohci1_clk,	"usb-ohci1",	"osc24M",
+		      0x0cc, BIT(17), 0);
+static SUNXI_CCU_GATE(usb_ohci2_clk,	"usb-ohci2",	"osc24M",
+		      0x0cc, BIT(18), 0);
+static SUNXI_CCU_GATE(usb_ohci3_clk,	"usb-ohci3",	"osc24M",
+		      0x0cc, BIT(19), 0);
+
+static const char * const dram_parents[] = { "pll-ddr", "pll-periph0-2x" };
+static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents,
+			    0x0f4, 0, 4, 20, 1, 0);
+
+static SUNXI_CCU_GATE(dram_ve_clk,	"dram-ve",	"dram",
+		      0x100, BIT(0), 0);
+static SUNXI_CCU_GATE(dram_csi_clk,	"dram-csi",	"dram",
+		      0x100, BIT(1), 0);
+static SUNXI_CCU_GATE(dram_deinterlace_clk,	"dram-deinterlace",	"dram",
+		      0x100, BIT(2), 0);
+static SUNXI_CCU_GATE(dram_ts_clk,	"dram-ts",	"dram",
+		      0x100, BIT(3), 0);
+
+static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
+static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
+				 0x104, 0, 4, 24, 1, BIT(31), 0);
+
+static SUNXI_CCU_M_WITH_GATE(tcon_clk, "tcon", "pll-video",
+			     0x118, 0, 4, BIT(31), 0);
+
+static const char * const tve_parents[] = { "pll-de", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(tve_clk, "tve", tve_parents,
+				 0x120, 0, 4, 24, 1, BIT(31), 0);
+
+static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents,
+				 0x124, 0, 4, 24, 1, BIT(31), 0);
+
+static SUNXI_CCU_GATE(csi_misc_clk,	"csi-misc",	"osc24M",
+		      0x130, BIT(31), 0);
+
+static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents,
+				 0x134, 16, 4, 24, 1, BIT(31), 0);
+
+static const char * const csi_mclk_parents[] = { "osc24M", "pll-video", "pll-periph0" };
+static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents,
+				 0x134, 0, 5, 8, 2, BIT(15), 0);
+
+static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve",
+			     0x13c, 16, 3, BIT(31), 0);
+
+static SUNXI_CCU_GATE(ac_dig_clk,	"ac-dig",	"pll-audio",
+		      0x140, BIT(31), 0);
+static SUNXI_CCU_GATE(avs_clk,		"avs",		"osc24M",
+		      0x144, BIT(31), 0);
+
+static SUNXI_CCU_M_WITH_GATE(hdmi_clk, "hdmi", "pll-video",
+			     0x150, 0, 4, BIT(31), 0);
+
+static SUNXI_CCU_GATE(hdmi_ddc_clk,	"hdmi-ddc",	"osc24M",
+		      0x154, BIT(31), 0);
+
+static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x", "pll-ddr" };
+static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
+				 0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL);
+
+static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu",
+			     0x1a0, 0, 3, BIT(31), 0);
+
+static struct ccu_common *sun8i_h3_ccu_clks[] = {
+	[CLK_PLL_CPUX]		= &pll_cpux_clk.common,
+	[CLK_PLL_AUDIO_BASE]	= &pll_audio_base_clk.common,
+	[CLK_PLL_AUDIO]		= &pll_audio_clk.common,
+	[CLK_PLL_AUDIO_2X]	= &pll_audio_2x_clk.common,
+	[CLK_PLL_AUDIO_4X]	= &pll_audio_4x_clk.common,
+	[CLK_PLL_AUDIO_8X]	= &pll_audio_8x_clk.common,
+	[CLK_PLL_VIDEO]		= &pll_video_clk.common,
+	[CLK_PLL_VE]		= &pll_ve_clk.common,
+	[CLK_PLL_DDR]		= &pll_ddr_clk.common,
+	[CLK_PLL_PERIPH0]	= &pll_periph0_clk.common,
+	[CLK_PLL_PERIPH0_2X]	= &pll_periph0_2x_clk.common,
+	[CLK_PLL_GPU]		= &pll_gpu_clk.common,
+	[CLK_PLL_PERIPH1]	= &pll_periph1_clk.common,
+	[CLK_PLL_DE]		= &pll_de_clk.common,
+	[CLK_CPUX]		= &cpux_clk.common,
+	[CLK_AXI]		= &axi_clk.common,
+	[CLK_AHB1]		= &ahb1_clk.common,
+	[CLK_APB1]		= &apb1_clk.common,
+	[CLK_APB2]		= &apb2_clk.common,
+	[CLK_AHB2]		= &ahb2_clk.common,
+	[CLK_BUS_CE]		= &bus_ce_clk.common,
+	[CLK_BUS_DMA]		= &bus_dma_clk.common,
+	[CLK_BUS_MMC0]		= &bus_mmc0_clk.common,
+	[CLK_BUS_MMC1]		= &bus_mmc1_clk.common,
+	[CLK_BUS_MMC2]		= &bus_mmc2_clk.common,
+	[CLK_BUS_NAND]		= &bus_nand_clk.common,
+	[CLK_BUS_DRAM]		= &bus_dram_clk.common,
+	[CLK_BUS_EMAC]		= &bus_emac_clk.common,
+	[CLK_BUS_TS]		= &bus_ts_clk.common,
+	[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common,
+	[CLK_BUS_SPI0]		= &bus_spi0_clk.common,
+	[CLK_BUS_SPI1]		= &bus_spi1_clk.common,
+	[CLK_BUS_OTG]		= &bus_otg_clk.common,
+	[CLK_BUS_EHCI0]		= &bus_ehci0_clk.common,
+	[CLK_BUS_EHCI1]		= &bus_ehci1_clk.common,
+	[CLK_BUS_EHCI2]		= &bus_ehci2_clk.common,
+	[CLK_BUS_EHCI3]		= &bus_ehci3_clk.common,
+	[CLK_BUS_OHCI0]		= &bus_ohci0_clk.common,
+	[CLK_BUS_OHCI1]		= &bus_ohci1_clk.common,
+	[CLK_BUS_OHCI2]		= &bus_ohci2_clk.common,
+	[CLK_BUS_OHCI3]		= &bus_ohci3_clk.common,
+	[CLK_BUS_VE]		= &bus_ve_clk.common,
+	[CLK_BUS_TCON0]		= &bus_tcon0_clk.common,
+	[CLK_BUS_TCON1]		= &bus_tcon1_clk.common,
+	[CLK_BUS_DEINTERLACE]	= &bus_deinterlace_clk.common,
+	[CLK_BUS_CSI]		= &bus_csi_clk.common,
+	[CLK_BUS_TVE]		= &bus_tve_clk.common,
+	[CLK_BUS_HDMI]		= &bus_hdmi_clk.common,
+	[CLK_BUS_DE]		= &bus_de_clk.common,
+	[CLK_BUS_GPU]		= &bus_gpu_clk.common,
+	[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common,
+	[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common,
+	[CLK_BUS_CODEC]		= &bus_codec_clk.common,
+	[CLK_BUS_SPDIF]		= &bus_spdif_clk.common,
+	[CLK_BUS_PIO]		= &bus_pio_clk.common,
+	[CLK_BUS_THS]		= &bus_ths_clk.common,
+	[CLK_BUS_I2S0]		= &bus_i2s0_clk.common,
+	[CLK_BUS_I2S1]		= &bus_i2s1_clk.common,
+	[CLK_BUS_I2S2]		= &bus_i2s2_clk.common,
+	[CLK_BUS_I2C0]		= &bus_i2c0_clk.common,
+	[CLK_BUS_I2C1]		= &bus_i2c1_clk.common,
+	[CLK_BUS_I2C2]		= &bus_i2c2_clk.common,
+	[CLK_BUS_UART0]		= &bus_uart0_clk.common,
+	[CLK_BUS_UART1]		= &bus_uart1_clk.common,
+	[CLK_BUS_UART2]		= &bus_uart2_clk.common,
+	[CLK_BUS_UART3]		= &bus_uart3_clk.common,
+	[CLK_BUS_SCR]		= &bus_scr_clk.common,
+	[CLK_BUS_EPHY]		= &bus_ephy_clk.common,
+	[CLK_BUS_DBG]		= &bus_dbg_clk.common,
+	[CLK_THS]		= &ths_clk.common,
+	[CLK_NAND]		= &nand_clk.common,
+	[CLK_MMC0]		= &mmc0_clk.common,
+	[CLK_MMC0_SAMPLE]	= &mmc0_sample_clk.common,
+	[CLK_MMC0_OUTPUT]	= &mmc0_output_clk.common,
+	[CLK_MMC1]		= &mmc1_clk.common,
+	[CLK_MMC1_SAMPLE]	= &mmc1_sample_clk.common,
+	[CLK_MMC1_OUTPUT]	= &mmc1_output_clk.common,
+	[CLK_MMC2]		= &mmc2_clk.common,
+	[CLK_MMC2_SAMPLE]	= &mmc2_sample_clk.common,
+	[CLK_MMC2_OUTPUT]	= &mmc2_output_clk.common,
+	[CLK_TS]		= &ts_clk.common,
+	[CLK_CE]		= &ce_clk.common,
+	[CLK_SPI0]		= &spi0_clk.common,
+	[CLK_SPI1]		= &spi1_clk.common,
+	[CLK_I2S0]		= &i2s0_clk.common,
+	[CLK_I2S1]		= &i2s1_clk.common,
+	[CLK_I2S2]		= &i2s2_clk.common,
+	[CLK_SPDIF]		= &spdif_clk.common,
+	[CLK_USB_PHY0]		= &usb_phy0_clk.common,
+	[CLK_USB_PHY1]		= &usb_phy1_clk.common,
+	[CLK_USB_PHY2]		= &usb_phy2_clk.common,
+	[CLK_USB_PHY3]		= &usb_phy3_clk.common,
+	[CLK_USB_OHCI0]		= &usb_ohci0_clk.common,
+	[CLK_USB_OHCI1]		= &usb_ohci1_clk.common,
+	[CLK_USB_OHCI2]		= &usb_ohci2_clk.common,
+	[CLK_USB_OHCI3]		= &usb_ohci3_clk.common,
+	[CLK_DRAM]		= &dram_clk.common,
+	[CLK_DRAM_VE]		= &dram_ve_clk.common,
+	[CLK_DRAM_CSI]		= &dram_csi_clk.common,
+	[CLK_DRAM_DEINTERLACE]	= &dram_deinterlace_clk.common,
+	[CLK_DRAM_TS]		= &dram_ts_clk.common,
+	[CLK_DE]		= &de_clk.common,
+	[CLK_TCON0]		= &tcon_clk.common,
+	[CLK_TVE]		= &tve_clk.common,
+	[CLK_DEINTERLACE]	= &deinterlace_clk.common,
+	[CLK_CSI_MISC]		= &csi_misc_clk.common,
+	[CLK_CSI_SCLK]		= &csi_sclk_clk.common,
+	[CLK_CSI_MCLK]		= &csi_mclk_clk.common,
+	[CLK_VE]		= &ve_clk.common,
+	[CLK_AC_DIG]		= &ac_dig_clk.common,
+	[CLK_AVS]		= &avs_clk.common,
+	[CLK_HDMI]		= &hdmi_clk.common,
+	[CLK_HDMI_DDC]		= &hdmi_ddc_clk.common,
+	[CLK_MBUS]		= &mbus_clk.common,
+	[CLK_GPU]		= &gpu_clk.common,
+};
+
+static struct ccu_reset_map sun8i_h3_ccu_resets[] = {
+	[RST_USB_PHY0]		=  { 0x0cc, BIT(0) },
+	[RST_USB_PHY1]		=  { 0x0cc, BIT(1) },
+	[RST_USB_PHY2]		=  { 0x0cc, BIT(2) },
+	[RST_USB_PHY3]		=  { 0x0cc, BIT(3) },
+
+	[RST_MBUS]		=  { 0x0fc, BIT(31) },
+
+	[RST_BUS_CE]		=  { 0x2c0, BIT(5) },
+	[RST_BUS_DMA]		=  { 0x2c0, BIT(6) },
+	[RST_BUS_MMC0]		=  { 0x2c0, BIT(8) },
+	[RST_BUS_MMC1]		=  { 0x2c0, BIT(9) },
+	[RST_BUS_MMC2]		=  { 0x2c0, BIT(10) },
+	[RST_BUS_NAND]		=  { 0x2c0, BIT(13) },
+	[RST_BUS_DRAM]		=  { 0x2c0, BIT(14) },
+	[RST_BUS_EMAC]		=  { 0x2c0, BIT(17) },
+	[RST_BUS_TS]		=  { 0x2c0, BIT(18) },
+	[RST_BUS_HSTIMER]	=  { 0x2c0, BIT(19) },
+	[RST_BUS_SPI0]		=  { 0x2c0, BIT(20) },
+	[RST_BUS_SPI1]		=  { 0x2c0, BIT(21) },
+	[RST_BUS_OTG]		=  { 0x2c0, BIT(23) },
+	[RST_BUS_EHCI0]		=  { 0x2c0, BIT(24) },
+	[RST_BUS_EHCI1]		=  { 0x2c0, BIT(25) },
+	[RST_BUS_EHCI2]		=  { 0x2c0, BIT(26) },
+	[RST_BUS_EHCI3]		=  { 0x2c0, BIT(27) },
+	[RST_BUS_OHCI0]		=  { 0x2c0, BIT(28) },
+	[RST_BUS_OHCI1]		=  { 0x2c0, BIT(29) },
+	[RST_BUS_OHCI2]		=  { 0x2c0, BIT(30) },
+	[RST_BUS_OHCI3]		=  { 0x2c0, BIT(31) },
+
+	[RST_BUS_VE]		=  { 0x2c4, BIT(0) },
+	[RST_BUS_TCON0]		=  { 0x2c4, BIT(3) },
+	[RST_BUS_TCON1]		=  { 0x2c4, BIT(4) },
+	[RST_BUS_DEINTERLACE]	=  { 0x2c4, BIT(5) },
+	[RST_BUS_CSI]		=  { 0x2c4, BIT(8) },
+	[RST_BUS_TVE]		=  { 0x2c4, BIT(9) },
+	[RST_BUS_HDMI0]		=  { 0x2c4, BIT(10) },
+	[RST_BUS_HDMI1]		=  { 0x2c4, BIT(11) },
+	[RST_BUS_DE]		=  { 0x2c4, BIT(12) },
+	[RST_BUS_GPU]		=  { 0x2c4, BIT(20) },
+	[RST_BUS_MSGBOX]	=  { 0x2c4, BIT(21) },
+	[RST_BUS_SPINLOCK]	=  { 0x2c4, BIT(22) },
+	[RST_BUS_DBG]		=  { 0x2c4, BIT(31) },
+
+	[RST_BUS_EPHY]		=  { 0x2c8, BIT(2) },
+
+	[RST_BUS_CODEC]		=  { 0x2d0, BIT(0) },
+	[RST_BUS_SPDIF]		=  { 0x2d0, BIT(1) },
+	[RST_BUS_THS]		=  { 0x2d0, BIT(8) },
+	[RST_BUS_I2S0]		=  { 0x2d0, BIT(12) },
+	[RST_BUS_I2S1]		=  { 0x2d0, BIT(13) },
+	[RST_BUS_I2S2]		=  { 0x2d0, BIT(14) },
+
+	[RST_BUS_I2C0]		=  { 0x2d4, BIT(0) },
+	[RST_BUS_I2C1]		=  { 0x2d4, BIT(1) },
+	[RST_BUS_I2C2]		=  { 0x2d4, BIT(2) },
+	[RST_BUS_UART0]		=  { 0x2d4, BIT(16) },
+	[RST_BUS_UART1]		=  { 0x2d4, BIT(17) },
+	[RST_BUS_UART2]		=  { 0x2d4, BIT(18) },
+	[RST_BUS_UART3]		=  { 0x2d4, BIT(19) },
+	[RST_BUS_SCR]		=  { 0x2d4, BIT(20) },
+};
+
+static const struct sunxi_ccu_desc sun8i_h3_ccu_desc = {
+	.clks		= sun8i_h3_ccu_clks,
+	.num_clks	= ARRAY_SIZE(sun8i_h3_ccu_clks),
+
+	.resets		= sun8i_h3_ccu_resets,
+	.num_resets	= ARRAY_SIZE(sun8i_h3_ccu_resets),
+};
+
+static void __init sun8i_h3_ccu_setup(struct device_node *node)
+{
+	sunxi_ccu_probe(node, &sun8i_h3_ccu_desc);
+}
+CLK_OF_DECLARE(sun8i_h3_ccu, "allwinner,sun8i-h3-ccu",
+	       sun8i_h3_ccu_setup);
diff --git a/include/dt-bindings/clock/sun8i-h3.h b/include/dt-bindings/clock/sun8i-h3.h
new file mode 100644
index 000000000000..96eced56e7a2
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-h3.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN8I_H3_H_
+#define _DT_BINDINGS_CLK_SUN8I_H3_H_
+
+#define CLK_PLL_CPUX		0
+#define CLK_PLL_AUDIO_BASE	1
+#define CLK_PLL_AUDIO		2
+#define CLK_PLL_AUDIO_2X	3
+#define CLK_PLL_AUDIO_4X	4
+#define CLK_PLL_AUDIO_8X	5
+#define CLK_PLL_VIDEO		6
+#define CLK_PLL_VE		7
+#define CLK_PLL_DDR		8
+#define CLK_PLL_PERIPH0		9
+#define CLK_PLL_PERIPH0_2X	10
+#define CLK_PLL_GPU		11
+#define CLK_PLL_PERIPH1		12
+#define CLK_PLL_DE		13
+#define CLK_CPUX		14
+#define CLK_AXI			15
+#define CLK_AHB1		16
+#define CLK_APB1		17
+#define CLK_APB2		18
+#define CLK_AHB2		19
+#define CLK_BUS_CE		20
+#define CLK_BUS_DMA		21
+#define CLK_BUS_MMC0		22
+#define CLK_BUS_MMC1		23
+#define CLK_BUS_MMC2		24
+#define CLK_BUS_NAND		25
+#define CLK_BUS_DRAM		26
+#define CLK_BUS_EMAC		27
+#define CLK_BUS_TS		28
+#define CLK_BUS_HSTIMER		29
+#define CLK_BUS_SPI0		30
+#define CLK_BUS_SPI1		31
+#define CLK_BUS_OTG		32
+#define CLK_BUS_EHCI0		33
+#define CLK_BUS_EHCI1		34
+#define CLK_BUS_EHCI2		35
+#define CLK_BUS_EHCI3		36
+#define CLK_BUS_OHCI0		37
+#define CLK_BUS_OHCI1		38
+#define CLK_BUS_OHCI2		39
+#define CLK_BUS_OHCI3		40
+#define CLK_BUS_VE		41
+#define CLK_BUS_TCON0		42
+#define CLK_BUS_TCON1		43
+#define CLK_BUS_DEINTERLACE	44
+#define CLK_BUS_CSI		45
+#define CLK_BUS_TVE		46
+#define CLK_BUS_HDMI		47
+#define CLK_BUS_DE		48
+#define CLK_BUS_GPU		49
+#define CLK_BUS_MSGBOX		50
+#define CLK_BUS_SPINLOCK	51
+#define CLK_BUS_CODEC		52
+#define CLK_BUS_SPDIF		53
+#define CLK_BUS_PIO		54
+#define CLK_BUS_THS		55
+#define CLK_BUS_I2S0		56
+#define CLK_BUS_I2S1		57
+#define CLK_BUS_I2S2		58
+#define CLK_BUS_I2C0		59
+#define CLK_BUS_I2C1		60
+#define CLK_BUS_I2C2		61
+#define CLK_BUS_UART0		62
+#define CLK_BUS_UART1		63
+#define CLK_BUS_UART2		64
+#define CLK_BUS_UART3		65
+#define CLK_BUS_SCR		66
+#define CLK_BUS_EPHY		67
+#define CLK_BUS_DBG		68
+#define CLK_THS			69
+#define CLK_NAND		70
+#define CLK_MMC0		71
+#define CLK_MMC0_SAMPLE		72
+#define CLK_MMC0_OUTPUT		73
+#define CLK_MMC1		74
+#define CLK_MMC1_SAMPLE		75
+#define CLK_MMC1_OUTPUT		76
+#define CLK_MMC2		77
+#define CLK_MMC2_SAMPLE		78
+#define CLK_MMC2_OUTPUT		79
+#define CLK_TS			80
+#define CLK_CE			81
+#define CLK_SPI0		82
+#define CLK_SPI1		83
+#define CLK_I2S0		84
+#define CLK_I2S1		85
+#define CLK_I2S2		86
+#define CLK_SPDIF		87
+#define CLK_USB_PHY0		88
+#define CLK_USB_PHY1		89
+#define CLK_USB_PHY2		90
+#define CLK_USB_PHY3		91
+#define CLK_USB_OHCI0		92
+#define CLK_USB_OHCI1		93
+#define CLK_USB_OHCI2		94
+#define CLK_USB_OHCI3		95
+#define CLK_DRAM		96
+#define CLK_DRAM_VE		97
+#define CLK_DRAM_CSI		98
+#define CLK_DRAM_DEINTERLACE	99
+#define CLK_DRAM_TS		100
+#define CLK_DE			101
+#define CLK_TCON0		102
+#define CLK_TVE			103
+#define CLK_DEINTERLACE		104
+#define CLK_CSI_MISC		105
+#define CLK_CSI_SCLK		106
+#define CLK_CSI_MCLK		107
+#define CLK_VE			108
+#define CLK_AC_DIG		109
+#define CLK_AVS			110
+#define CLK_HDMI		111
+#define CLK_HDMI_DDC		112
+#define CLK_MBUS		113
+#define CLK_GPU			114
+
+#endif /* _DT_BINDINGS_CLK_SUN8I_H3_H_ */
diff --git a/include/dt-bindings/reset/sun8i-h3.h b/include/dt-bindings/reset/sun8i-h3.h
new file mode 100644
index 000000000000..6b7af80c26ec
--- /dev/null
+++ b/include/dt-bindings/reset/sun8i-h3.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN8I_H3_H_
+#define _DT_BINDINGS_RST_SUN8I_H3_H_
+
+#define RST_USB_PHY0		0
+#define RST_USB_PHY1		1
+#define RST_USB_PHY2		2
+#define RST_USB_PHY3		3
+
+#define RST_MBUS		4
+
+#define RST_BUS_CE		5
+#define RST_BUS_DMA		6
+#define RST_BUS_MMC0		7
+#define RST_BUS_MMC1		8
+#define RST_BUS_MMC2		9
+#define RST_BUS_NAND		10
+#define RST_BUS_DRAM		11
+#define RST_BUS_EMAC		12
+#define RST_BUS_TS		13
+#define RST_BUS_HSTIMER		14
+#define RST_BUS_SPI0		15
+#define RST_BUS_SPI1		16
+#define RST_BUS_OTG		17
+#define RST_BUS_EHCI0		18
+#define RST_BUS_EHCI1		19
+#define RST_BUS_EHCI2		20
+#define RST_BUS_EHCI3		21
+#define RST_BUS_OHCI0		22
+#define RST_BUS_OHCI1		23
+#define RST_BUS_OHCI2		24
+#define RST_BUS_OHCI3		25
+#define RST_BUS_VE		26
+#define RST_BUS_TCON0		27
+#define RST_BUS_TCON1		28
+#define RST_BUS_DEINTERLACE	29
+#define RST_BUS_CSI		30
+#define RST_BUS_TVE		31
+#define RST_BUS_HDMI0		32
+#define RST_BUS_HDMI1		33
+#define RST_BUS_DE		34
+#define RST_BUS_GPU		35
+#define RST_BUS_MSGBOX		36
+#define RST_BUS_SPINLOCK	37
+#define RST_BUS_DBG		38
+#define RST_BUS_EPHY		39
+#define RST_BUS_CODEC		40
+#define RST_BUS_SPDIF		41
+#define RST_BUS_THS		42
+#define RST_BUS_I2S0		43
+#define RST_BUS_I2S1		44
+#define RST_BUS_I2S2		45
+#define RST_BUS_I2C0		46
+#define RST_BUS_I2C1		47
+#define RST_BUS_I2C2		48
+#define RST_BUS_UART0		49
+#define RST_BUS_UART1		50
+#define RST_BUS_UART2		51
+#define RST_BUS_UART3		52
+#define RST_BUS_SCR		53
+
+#endif /* _DT_BINDINGS_RST_SUN8I_H3_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:01:40 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun,  8 May 2016 22:01:40 +0200
Subject: [PATCH 05/16] clk: sunxi-ng: Add mux clock support
In-Reply-To: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1462737711-10017-6-git-send-email-maxime.ripard@free-electrons.com>

Some clocks in the Allwinner SoCs clocks unit are just muxes.

However, those muxes might also be found in some other complicated clocks
that would benefit from the code in there to deal with "advanced" features,
like pre-dividers.

Introduce a set of helpers to reduce the code duplication in such cases.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi-ng/Makefile  |   1 +
 drivers/clk/sunxi-ng/ccu_mux.c | 187 +++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_mux.h |  80 +++++++++++++++++-
 3 files changed, 264 insertions(+), 4 deletions(-)
 create mode 100644 drivers/clk/sunxi-ng/ccu_mux.c

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index fc01127b3b45..aa5c411ff8ea 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -3,3 +3,4 @@ obj-y += ccu_reset.o
 
 obj-y += ccu_fixed_factor.o
 obj-y += ccu_gate.o
+obj-y += ccu_mux.o
diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
new file mode 100644
index 000000000000..cb54a8931de3
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2016 Maxime Ripard
+ * Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "ccu_gate.h"
+#include "ccu_mux.h"
+
+void ccu_mux_helper_adjust_parent_for_prediv(struct ccu_common *common,
+					     struct ccu_mux_internal *cm,
+					     int parent_index,
+					     unsigned long *parent_rate)
+{
+	u8 prediv = 1;
+	u32 reg;
+
+	if (!((common->features & CCU_FEATURE_FIXED_PREDIV) ||
+	      (common->features & CCU_FEATURE_VARIABLE_PREDIV)))
+		return;
+
+	reg = readl(common->base + common->reg);
+	if (parent_index < 0) {
+		parent_index = reg >> cm->shift;
+		parent_index &= (1 << cm->width) - 1;
+	}
+
+	if (common->features & CCU_FEATURE_FIXED_PREDIV)
+		if (parent_index == cm->fixed_prediv.index)
+			prediv = cm->fixed_prediv.div;
+
+	if (common->features & CCU_FEATURE_VARIABLE_PREDIV)
+		if (parent_index == cm->variable_prediv.index) {
+			u8 div;
+
+			div = reg >> cm->variable_prediv.shift;
+			div &= (1 << cm->variable_prediv.width) - 1;
+			prediv = div + 1;
+		}
+
+	*parent_rate = *parent_rate / prediv;
+}
+
+int ccu_mux_helper_determine_rate(struct ccu_common *common,
+				  struct ccu_mux_internal *cm,
+				  struct clk_rate_request *req,
+				  unsigned long (*round)(struct ccu_mux_internal *,
+							 unsigned long,
+							 unsigned long,
+							 void *),
+				  void *data)
+{
+	unsigned long best_parent_rate = 0, best_rate = 0;
+	struct clk_hw *best_parent, *hw = &common->hw;
+	unsigned int i;
+
+	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+		unsigned long tmp_rate, parent_rate;
+		struct clk_hw *parent;
+
+		parent = clk_hw_get_parent_by_index(hw, i);
+		if (!parent)
+			continue;
+
+		parent_rate = clk_hw_get_rate(parent);
+		ccu_mux_helper_adjust_parent_for_prediv(common, cm, i,
+							&parent_rate);
+
+		tmp_rate = round(cm, clk_hw_get_rate(parent), req->rate, data);
+		if (tmp_rate == req->rate) {
+			best_parent = parent;
+			best_parent_rate = parent_rate;
+			best_rate = tmp_rate;
+			goto out;
+		}
+
+		if ((req->rate - tmp_rate) < (req->rate - best_rate)) {
+			best_rate = tmp_rate;
+			best_parent_rate = parent_rate;
+			best_parent = parent;
+		}
+	}
+
+	if (best_rate == 0)
+		return -EINVAL;
+
+out:
+	req->best_parent_hw = best_parent;
+	req->best_parent_rate = best_parent_rate;
+	req->rate = best_rate;
+	return 0;
+}
+
+u8 ccu_mux_helper_get_parent(struct ccu_common *common,
+			     struct ccu_mux_internal *cm)
+{
+	u32 reg;
+	u8 parent;
+
+	reg = readl(common->base + common->reg);
+	parent = reg >> cm->shift;
+	parent &= (1 << cm->width) - 1;
+
+	return parent;
+}
+
+int ccu_mux_helper_set_parent(struct ccu_common *common,
+			      struct ccu_mux_internal *cm,
+			      u8 index)
+{
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(common->lock, flags);
+
+	reg = readl(common->base + common->reg);
+	reg &= ~GENMASK(cm->width + cm->shift, cm->shift);
+	writel(reg | (index << cm->shift), common->base + common->reg);
+
+	spin_unlock_irqrestore(common->lock, flags);
+
+	return 0;
+}
+
+static void ccu_mux_disable(struct clk_hw *hw)
+{
+	struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+	return ccu_gate_helper_disable(&cm->common, cm->enable);
+}
+
+static int ccu_mux_enable(struct clk_hw *hw)
+{
+	struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+	return ccu_gate_helper_enable(&cm->common, cm->enable);
+}
+
+static int ccu_mux_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+	return ccu_gate_helper_is_enabled(&cm->common, cm->enable);
+}
+
+static u8 ccu_mux_get_parent(struct clk_hw *hw)
+{
+	struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+	return ccu_mux_helper_get_parent(&cm->common, &cm->mux);
+}
+
+static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+	return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index);
+}
+
+static unsigned long ccu_mux_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+	ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1,
+						&parent_rate);
+
+	return parent_rate;
+}
+
+const struct clk_ops ccu_mux_ops = {
+	.disable	= ccu_mux_disable,
+	.enable		= ccu_mux_enable,
+	.is_enabled	= ccu_mux_is_enabled,
+
+	.get_parent	= ccu_mux_get_parent,
+	.set_parent	= ccu_mux_set_parent,
+
+	.determine_rate	= __clk_mux_determine_rate,
+	.recalc_rate	= ccu_mux_recalc_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
index 17cedad4e433..c85707f80f68 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.h
+++ b/drivers/clk/sunxi-ng/ccu_mux.h
@@ -1,20 +1,92 @@
 #ifndef _CCU_MUX_H_
 #define _CCU_MUX_H_
 
-#include "common.h"
+#include <linux/clk-provider.h>
+
+#include "ccu_common.h"
 
 struct ccu_mux_internal {
 	u8	shift;
 	u8	width;
 
-	u8	*map;
+	struct {
+		u8	index;
+		u8	div;
+	} fixed_prediv;
+
+	struct {
+		u8	index;
+		u8	shift;
+		u8	width;
+	} variable_prediv;
 };
 
-#define SUNXI_CLK_MUX(_shift, _width, _map)	\
+#define SUNXI_CLK_MUX(_shift, _width)	\
 	{					\
-		.map	= _map,			\
 		.shift	= _shift,		\
 		.width	= _width,		\
 	}
 
+struct ccu_mux {
+	u16			reg;
+	u32			enable;
+
+	struct ccu_mux_internal	mux;
+	struct ccu_common	common;
+};
+
+#define SUNXI_CCU_MUX(_struct, _name, _parents, _reg, _shift, _width, _flags) \
+	struct ccu_mux _struct = {					\
+		.mux	= SUNXI_CLK_MUX(_shift, _width),		\
+		.common	= {						\
+			.reg		= _reg,				\
+			.hw.init	= SUNXI_HW_INIT_PARENTS(_name,	\
+								_parents, \
+								&ccu_mux_ops, \
+								_flags), \
+		}							\
+	}
+
+#define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg,		\
+				_shift, _width, _gate, _flags)		\
+	struct ccu_mux _struct = {					\
+		.enable	= _gate,					\
+		.mux	= SUNXI_CLK_MUX(_shift, _width),		\
+		.common	= {						\
+			.reg		= _reg,				\
+			.features	= CCU_FEATURE_GATE,		\
+			.hw.init	= SUNXI_HW_INIT_PARENTS(_name,	\
+								_parents, \
+								&ccu_mux_ops, \
+								_flags), \
+		}							\
+	}
+
+static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_mux, common);
+}
+
+extern const struct clk_ops ccu_mux_ops;
+
+void ccu_mux_helper_adjust_parent_for_prediv(struct ccu_common *common,
+					     struct ccu_mux_internal *cm,
+					     int parent_index,
+					     unsigned long *parent_rate);
+int ccu_mux_helper_determine_rate(struct ccu_common *common,
+				  struct ccu_mux_internal *cm,
+				  struct clk_rate_request *req,
+				  unsigned long (*round)(struct ccu_mux_internal *,
+							 unsigned long,
+							 unsigned long,
+							 void *),
+				  void *data);
+u8 ccu_mux_helper_get_parent(struct ccu_common *common,
+			     struct ccu_mux_internal *cm);
+int ccu_mux_helper_set_parent(struct ccu_common *common,
+			      struct ccu_mux_internal *cm,
+			      u8 index);
+
 #endif /* _CCU_MUX_H_ */
-- 
2.8.2



From maxime.ripard at free-electrons.com  Sun May  8 13:03:08 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun, 8 May 2016 22:03:08 +0200
Subject: [PATCH v4 01/11] clk: sunxi: Add display and TCON0 clocks driver
In-Reply-To: <20160506223002.GE3492@codeaurora.org>
References: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
 <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
 <20160506223002.GE3492@codeaurora.org>
Message-ID: <20160508200308.GF6167@lukather>

Hi Stephen,

On Fri, May 06, 2016 at 03:30:02PM -0700, Stephen Boyd wrote:
> On 04/25, Maxime Ripard wrote:
> > The A10 SoCs and its relatives has a special clock controller to drive the
> > display engines (both frontend and backend), that have a lot in common with
> > the clock to drive the first TCON channel.
> > 
> > Add a driver to support both.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > Acked-by: Rob Herring <robh at kernel.org>
> > ---
> 
> Acked-by: Stephen Boyd <sboyd at codeaurora.org>
> 
> Unless I can merge this into clk-next? Wasn't clear to me.

Yes, please do, I already sent you the bunch of patches I gathered for
4.7, and I don't have any others but this one.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160508/fe3ce1e7/attachment.sig>

From marex at denx.de  Sun May  8 13:23:39 2016
From: marex at denx.de (Marek Vasut)
Date: Sun, 08 May 2016 22:23:39 +0200
Subject: [PATCH 3/4] ARM: mxs: dts: Add Creative X-Fi3 support
In-Reply-To: <977436072.210446.e7eef450-2262-47df-8e8e-6a44da10083c.open-xchange@email.1und1.de>
References: <1462479971-7891-1-git-send-email-marex@denx.de>
 <1462479971-7891-3-git-send-email-marex@denx.de>
 <977436072.210446.e7eef450-2262-47df-8e8e-6a44da10083c.open-xchange@email.1und1.de>
Message-ID: <572FA04B.1020005@denx.de>

On 05/06/2016 09:40 AM, Stefan Wahren wrote:
> Hi Marek,

Hi!

> sorry for the reply format.

replying from a phone ? :)

>> Marek Vasut <marex at denx.de> hat am 5. Mai 2016 um 22:26 geschrieben:
>>
>> Add support for this small MP3 player based on STMP3780 (rev.4).
>> Currently supported is both external microSD and internal SD-NAND
>> bridge, PWM and USB gadget.
>>
>> Signed-off-by: Marek Vasut <marex at denx.de>
>> Cc: Fabio Estevam <fabio.estevam at nxp.com>
>> Cc: Shawn Guo <shawnguo at kernel.org>
>> ---
>>  arch/arm/boot/dts/Makefile | 1 +
>>  arch/arm/boot/dts/imx23-xfi3.dts | 190
>> +++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 191 insertions(+)
>>  create mode 100644 arch/arm/boot/dts/imx23-xfi3.dts
>>
>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>> index 8f9f1c2..7a79d37 100644
>> --- a/arch/arm/boot/dts/Makefile
>> +++ b/arch/arm/boot/dts/Makefile
>> @@ -417,6 +417,7 @@ dtb-$(CONFIG_ARCH_MXS) += \
>>  imx23-evk.dtb \
>>  imx23-olinuxino.dtb \
>>  imx23-stmp378x_devb.dtb \
>> + imx23-xfi3.dtb \
>>  imx28-apf28.dtb \
>>  imx28-apf28dev.dtb \
>>  imx28-apx4devkit.dtb \
>> diff --git a/arch/arm/boot/dts/imx23-xfi3.dts
>> b/arch/arm/boot/dts/imx23-xfi3.dts
>> new file mode 100644
>> index 0000000..d7e7cf5
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/imx23-xfi3.dts
>> @@ -0,0 +1,190 @@
>> +/*
>> + * Copyright (C) 2013-2016 Marek Vasut <marex at denx.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.
>> + *
>> + * You should have received a copy of the GNU General Public
>> + * License along with this file; if not, write to the Free
>> + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
>> + * MA 02110-1301 USA
> 
> AFAIK this address shouldn't be included.

Hmmm, some boards do include it. I'll remove it from this submission and
also for the xfi.

Shall I send patch(es) removing the address from the other boards too ?

>> + *
>> + * 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 "imx23.dtsi"
>> +
>> +/ {
>> + model = "Creative ZEN X-Fi3";
>> + compatible = "creative,x-fi3", "fsl,imx23";
> 
> Is there a pending patch to add "creative" to the vendor-prefixes.txt?

There isn't. I'll send one.

>> +
>> + memory {
>> + reg = ;
>> + };
>> +
>> + apb at 80000000 {
>> + apbh at 80000000 {
>> + ssp0: ssp at 80010000 {
>> + compatible = "fsl,imx23-mmc";
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>;
>> + bus-width = ;
>> + vmmc-supply = <&reg_vddio_sd0>;
>> + cd-inverted;
>> + status = "okay";
>> + };
>> +
>> + ssp1: ssp at 80034000 {
>> + compatible = "fsl,imx23-mmc";
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&mmc1_4bit_pins_a>;
>> + bus-width = ;
>> + non-removable;
>> + status = "okay";
>> + };
>> +
>> + pinctrl at 80018000 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&hog_pins_a>;
>> +
>> + hog_pins_a: hog at 0 {
>> + reg = ;
>> + fsl,pinmux-ids = <
>> + MX23_PAD_GPMI_D07__GPIO_0_7
>> + >;
>> + fsl,drive-strength = ;
>> + fsl,voltage = ;
>> + fsl,pull-up = ;
>> + };
>> +
>> + key_pins_a: keys at 0 {
>> + reg = ;
>> + fsl,pinmux-ids = <
>> + MX23_PAD_ROTARYA__GPIO_2_7
>> + MX23_PAD_ROTARYB__GPIO_2_8
>> + >;
>> + fsl,drive-strength = ;
>> + fsl,voltage = ;
>> + fsl,pull-up = ;
>> + };
>> + };
>> + };
>> +
>> + apbx at 80040000 {
>> + i2c: i2c at 80058000 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&i2c_pins_a>;
>> + status = "okay";
>> + };
>> +
>> + pwm: pwm at 80064000 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pwm2_pins_a>;
>> + status = "okay";
>> + };
>> +
>> + duart: serial at 80070000 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&duart_pins_a>;
>> + status = "okay";
>> + };
>> +
>> + auart1: serial at 8006e000 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&auart1_2pins_a>;
>> + status = "okay";
>> + };
>> +
>> + usbphy0: usbphy at 8007c000 {
>> + status = "okay";
>> + };
>> +
>> + lradc at 80050000 {
>> + status = "okay";
>> + };
>> + };
>> + };
>> +
>> + ahb at 80080000 {
>> + usb0: usb at 80080000 {
>> + dr_mode = "peripheral";
>> + status = "okay";
>> + };
>> + };
>> +
>> + regulators {
>> + compatible = "simple-bus";
>> +
>> + reg_vddio_sd0: vddio-sd0 {
>> + compatible = "regulator-fixed";
>> + regulator-name = "vddio-sd0";
>> + regulator-min-microvolt = ;
>> + regulator-max-microvolt = ;
>> + gpio = <&gpio0 7 0>;
>> + };
>> + };
>> +
>> + backlight {
>> + compatible = "pwm-backlight";
>> + pwms = <&pwm 2 5000000>;
>> + brightness-levels = ;
>> + default-brightness-level = ;
>> + };
>> +
>> + gpio_keys {
>> + compatible = "gpio-keys";
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&key_pins_a>;
>> + #address-cells = ;
>> + #size-cells = ;
>> +
>> + button at 0 {
>> + label = "volume-down";
>> + linux,code = ;
>> + gpios = <&gpio2 7 0>;
>> + debounce-interval = ;
>> + };
> 
> I think this would introduce new dtc warnings.
> 
> Please look at
> https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/?id=f2953a461042721e9a2aca58d2b1cfc67c70d371

Ha, fixed, thanks.

>> +
>> + button at 1 {
>> + label = "volume-up";
>> + linux,code = ;
>> + gpios = <&gpio2 8 0>;
>> + debounce-interval = ;
>> + };
>> + };
>> +};
>> -- 
>> 2.7.0
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


-- 
Best regards,
Marek Vasut


From marex at denx.de  Sun May  8 13:50:18 2016
From: marex at denx.de (Marek Vasut)
Date: Sun,  8 May 2016 22:50:18 +0200
Subject: [PATCH 1/4] ARM: mxs: dts: Add SSP2 SD mux
Message-ID: <1462740621-7557-1-git-send-email-marex@denx.de>

From: Marek Vasut <marek.vasut at gmail.com>

Add pinmux configuration for SSP2 port in SD mode, both for
the 4-bit and 8-bit case.

Signed-off-by: Marek Vasut <marek.vasut at gmail.com>
Cc: Fabio Estevam <fabio.estevam at nxp.com>
Cc: Shawn Guo <shawnguo at kernel.org>
---
 arch/arm/boot/dts/imx23.dtsi | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index 302d116..c70ebef 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -249,6 +249,40 @@
 					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
+				mmc1_4bit_pins_a: mmc1-4bit at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_GPMI_D00__SSP2_DATA0
+						MX23_PAD_GPMI_D01__SSP2_DATA1
+						MX23_PAD_GPMI_D02__SSP2_DATA2
+						MX23_PAD_GPMI_D03__SSP2_DATA3
+						MX23_PAD_GPMI_RDY1__SSP2_CMD
+						MX23_PAD_GPMI_WRN__SSP2_SCK
+					>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
+				};
+
+				mmc1_8bit_pins_a: mmc1-8bit at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_GPMI_D00__SSP2_DATA0
+						MX23_PAD_GPMI_D01__SSP2_DATA1
+						MX23_PAD_GPMI_D02__SSP2_DATA2
+						MX23_PAD_GPMI_D03__SSP2_DATA3
+						MX23_PAD_GPMI_D04__SSP2_DATA4
+						MX23_PAD_GPMI_D05__SSP2_DATA5
+						MX23_PAD_GPMI_D06__SSP2_DATA6
+						MX23_PAD_GPMI_D07__SSP2_DATA7
+						MX23_PAD_GPMI_RDY1__SSP2_CMD
+						MX23_PAD_GPMI_WRN__SSP2_SCK
+					>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
+				};
+
 				pwm2_pins_a: pwm2 at 0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-- 
2.7.0



From marex at denx.de  Sun May  8 13:50:21 2016
From: marex at denx.de (Marek Vasut)
Date: Sun,  8 May 2016 22:50:21 +0200
Subject: [PATCH V2 4/4] ARM: mxs: dts: Add SanDisk Sansa Fuze+ support
In-Reply-To: <1462740621-7557-1-git-send-email-marex@denx.de>
References: <1462740621-7557-1-git-send-email-marex@denx.de>
Message-ID: <1462740621-7557-4-git-send-email-marex@denx.de>

From: Marek Vasut <marek.vasut at gmail.com>

Add support for this small MP3 player based on STMP3780 (rev.3).
Currently supported are both external microSD and internal SD-NAND
bridge, PWM and USB gadget.

Signed-off-by: Marek Vasut <marek.vasut at gmail.com>
Cc: Fabio Estevam <fabio.estevam at nxp.com>
Cc: Shawn Guo <shawnguo at kernel.org>
---
V2: - Drop the address part from the license
---
 arch/arm/boot/dts/Makefile        |   1 +
 arch/arm/boot/dts/imx23-sansa.dts | 211 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 212 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx23-sansa.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 7a79d37..eaa8048 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -416,6 +416,7 @@ dtb-$(CONFIG_SOC_VF610) += \
 dtb-$(CONFIG_ARCH_MXS) += \
 	imx23-evk.dtb \
 	imx23-olinuxino.dtb \
+	imx23-sansa.dtb \
 	imx23-stmp378x_devb.dtb \
 	imx23-xfi3.dtb \
 	imx28-apf28.dtb \
diff --git a/arch/arm/boot/dts/imx23-sansa.dts b/arch/arm/boot/dts/imx23-sansa.dts
new file mode 100644
index 0000000..c7b0ff4
--- /dev/null
+++ b/arch/arm/boot/dts/imx23-sansa.dts
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2013-2016 Marek Vasut <marek.vasut at gmail.com>
+ *
+ * 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 "imx23.dtsi"
+
+/ {
+	model = "SanDisk Sansa Fuze+";
+	compatible = "sandisk,sansa_fuze_plus", "fsl,imx23";
+
+	memory {
+		reg = <0x40000000 0x04000000>;
+	};
+
+	apb at 80000000 {
+		apbh at 80000000 {
+			ssp0: ssp at 80010000 {
+				compatible = "fsl,imx23-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>;
+				bus-width = <4>;
+				vmmc-supply = <&reg_vddio_sd0>;
+				cd-inverted;
+				status = "okay";
+			};
+
+			ssp1: ssp at 80034000 {
+				compatible = "fsl,imx23-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc1_8bit_pins_a>;
+				bus-width = <8>;
+				vmmc-supply = <&reg_vddio_sd1>;
+				non-removable;
+				status = "okay";
+			};
+
+			pinctrl at 80018000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&hog_pins_a>;
+
+				hog_pins_a: hog at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_GPMI_D08__GPIO_0_8
+						MX23_PAD_PWM3__GPIO_1_29
+						MX23_PAD_AUART1_RTS__GPIO_0_27
+						MX23_PAD_AUART1_CTS__GPIO_0_26
+						MX23_PAD_I2C_SCL__I2C_SCL
+						MX23_PAD_I2C_SDA__I2C_SDA
+						MX23_PAD_LCD_DOTCK__GPIO_1_22
+						MX23_PAD_LCD_HSYNC__GPIO_1_24
+						MX23_PAD_PWM3__GPIO_1_29
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+			};
+		};
+
+		apbx at 80040000 {
+			pwm: pwm at 80064000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pwm2_pins_a>;
+				status = "okay";
+			};
+
+			duart: serial at 80070000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&duart_pins_a>;
+				status = "okay";
+			};
+
+			usbphy0: usbphy at 8007c000 {
+				status = "okay";
+			};
+
+			lradc at 80050000 {
+				status = "okay";
+			};
+		};
+	};
+
+	ahb at 80080000 {
+		usb0: usb at 80080000 {
+			dr_mode = "peripheral";
+			status = "okay";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_vddio_sd0: vddio-sd0 {
+			compatible = "regulator-fixed";
+			regulator-name = "vddio-sd0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio0 8 0>;
+		};
+
+		reg_vddio_sd1: vddio-sd1 {
+			compatible = "regulator-fixed";
+			regulator-name = "vddio-sd1";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio1 29 0>;
+		};
+
+		reg_vdd_touchpad: vdd-touchpad0 {
+			compatible = "regulator-fixed";
+			regulator-name = "vdd-touchpad0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio0 26 0>;
+			regulator-always-on;
+			enable-active-low;
+		};
+
+		reg_vdd_tuner: vdd-tuner0 {
+			compatible = "regulator-fixed";
+			regulator-name = "vdd-tuner0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio0 29 0>;
+			regulator-always-on;
+			enable-active-low;
+		};
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 2 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+
+	i2c at 0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		gpios = <
+			&gpio1 24 0		/* SDA */
+			&gpio1 22 0		/* SCL */
+		>;
+		i2c-gpio,delay-us = <2>;	/* ~100 kHz */
+	};
+
+	i2c at 1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		gpios = <
+			&gpio0 31 0		/* SDA */
+			&gpio0 30 0		/* SCL */
+		>;
+		i2c-gpio,delay-us = <2>;	/* ~100 kHz */
+
+		touch: touch at 20 {
+			compatible = "synaptics,synaptics_i2c";
+			reg = <0x20>;
+		};
+
+		eeprom: eeprom at 50 {
+			compatible = "atmel,24c64";
+			reg = <0x50>;
+			pagesize = <32>;
+		};
+	};
+
+};
-- 
2.7.0



From marex at denx.de  Sun May  8 13:50:19 2016
From: marex at denx.de (Marek Vasut)
Date: Sun,  8 May 2016 22:50:19 +0200
Subject: [PATCH 2/4] ARM: mxs: dts: Add AUART2 pinmux
In-Reply-To: <1462740621-7557-1-git-send-email-marex@denx.de>
References: <1462740621-7557-1-git-send-email-marex@denx.de>
Message-ID: <1462740621-7557-2-git-send-email-marex@denx.de>

From: Marek Vasut <marek.vasut at gmail.com>

Add 2-pin pinmux settings for AUART2.

Signed-off-by: Marek Vasut <marek.vasut at gmail.com>
Cc: Fabio Estevam <fabio.estevam at nxp.com>
Cc: Shawn Guo <shawnguo at kernel.org>
---
 arch/arm/boot/dts/imx23.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index c70ebef..0c9a357e 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -171,6 +171,17 @@
 					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
+				auart1_2pins_a: auart1-2pins at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_GPMI_D14__AUART2_RX
+						MX23_PAD_GPMI_D15__AUART2_TX
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
 				gpmi_pins_a: gpmi-nand at 0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-- 
2.7.0



From marex at denx.de  Sun May  8 13:50:20 2016
From: marex at denx.de (Marek Vasut)
Date: Sun,  8 May 2016 22:50:20 +0200
Subject: [PATCH V2 3/4] ARM: mxs: dts: Add Creative X-Fi3 support
In-Reply-To: <1462740621-7557-1-git-send-email-marex@denx.de>
References: <1462740621-7557-1-git-send-email-marex@denx.de>
Message-ID: <1462740621-7557-3-git-send-email-marex@denx.de>

From: Marek Vasut <marek.vasut at gmail.com>

Add support for this small MP3 player based on STMP3780 (rev.4).
Currently supported is both external microSD and internal SD-NAND
bridge, PWM and USB gadget.

Signed-off-by: Marek Vasut <marek.vasut at gmail.com>
Cc: Fabio Estevam <fabio.estevam at nxp.com>
Cc: Shawn Guo <shawnguo at kernel.org>
---
V2: - Fix the button nodes to not generate possible DT warning
    - Drop the address part from the license
---
 arch/arm/boot/dts/Makefile       |   1 +
 arch/arm/boot/dts/imx23-xfi3.dts | 183 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 184 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx23-xfi3.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 8f9f1c2..7a79d37 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -417,6 +417,7 @@ dtb-$(CONFIG_ARCH_MXS) += \
 	imx23-evk.dtb \
 	imx23-olinuxino.dtb \
 	imx23-stmp378x_devb.dtb \
+	imx23-xfi3.dtb \
 	imx28-apf28.dtb \
 	imx28-apf28dev.dtb \
 	imx28-apx4devkit.dtb \
diff --git a/arch/arm/boot/dts/imx23-xfi3.dts b/arch/arm/boot/dts/imx23-xfi3.dts
new file mode 100644
index 0000000..abf9457
--- /dev/null
+++ b/arch/arm/boot/dts/imx23-xfi3.dts
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2013-2016 Marek Vasut <marek.vasut at gmail.com>
+ *
+ * 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 "imx23.dtsi"
+
+/ {
+	model = "Creative ZEN X-Fi3";
+	compatible = "creative,x-fi3", "fsl,imx23";
+
+	memory {
+		reg = <0x40000000 0x04000000>;
+	};
+
+	apb at 80000000 {
+		apbh at 80000000 {
+			ssp0: ssp at 80010000 {
+				compatible = "fsl,imx23-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>;
+				bus-width = <4>;
+				vmmc-supply = <&reg_vddio_sd0>;
+				cd-inverted;
+				status = "okay";
+			};
+
+			ssp1: ssp at 80034000 {
+				compatible = "fsl,imx23-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc1_4bit_pins_a>;
+				bus-width = <4>;
+				non-removable;
+				status = "okay";
+			};
+
+			pinctrl at 80018000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&hog_pins_a>;
+
+				hog_pins_a: hog at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_GPMI_D07__GPIO_0_7
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+				key_pins_a: keys at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX23_PAD_ROTARYA__GPIO_2_7
+						MX23_PAD_ROTARYB__GPIO_2_8
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
+			};
+		};
+
+		apbx at 80040000 {
+			i2c: i2c at 80058000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2c_pins_a>;
+				status = "okay";
+			};
+
+			pwm: pwm at 80064000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pwm2_pins_a>;
+				status = "okay";
+			};
+
+			duart: serial at 80070000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&duart_pins_a>;
+				status = "okay";
+			};
+
+			auart1: serial at 8006e000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&auart1_2pins_a>;
+				status = "okay";
+			};
+
+			usbphy0: usbphy at 8007c000 {
+				status = "okay";
+			};
+
+			lradc at 80050000 {
+				status = "okay";
+			};
+		};
+	};
+
+	ahb at 80080000 {
+		usb0: usb at 80080000 {
+			dr_mode = "peripheral";
+			status = "okay";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_vddio_sd0: vddio-sd0 {
+			compatible = "regulator-fixed";
+			regulator-name = "vddio-sd0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio0 7 0>;
+		};
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 2 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&key_pins_a>;
+
+		voldown {
+			label = "volume-down";
+			linux,code = <114>;
+			gpios = <&gpio2 7 0>;
+			debounce-interval = <20>;
+		};
+
+		volup {
+			label = "volume-up";
+			linux,code = <115>;
+			gpios = <&gpio2 8 0>;
+			debounce-interval = <20>;
+		};
+	};
+};
-- 
2.7.0



From heiko at sntech.de  Sun May  8 13:51:14 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sun, 08 May 2016 22:51:14 +0200
Subject: [PATCH] clk: rockchip: fix the rk3399 sdmmc sample / drv name
In-Reply-To: <1462404985-27957-1-git-send-email-dianders@chromium.org>
References: <1462404985-27957-1-git-send-email-dianders@chromium.org>
Message-ID: <4645491.pfFL9jxaO2@phil>

Am Mittwoch, 4. Mai 2016, 16:36:25 schrieb Douglas Anderson:
> The rk3399 clock table had a simple typo in it, calling the SDMMC sample
> and drive clocks by the wrong name.  Fix this minor typo.
> 
> Signed-off-by: Douglas Anderson <dianders at chromium.org>

applied to my clk-branch


Thanks for catching this
Heiko


From xypron.glpk at gmx.de  Sun May  8 15:46:18 2016
From: xypron.glpk at gmx.de (Heinrich Schuchardt)
Date: Mon,  9 May 2016 00:46:18 +0200
Subject: [PATCH 1/1] net: thunderx: avoid exposing kernel stack
Message-ID: <1462747578-6147-1-git-send-email-xypron.glpk@gmx.de>

Reserved fields should be set to zero to avoid exposing
bits from the kernel stack.

Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
 drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index 8acd7c0..0ff8e60 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -533,6 +533,7 @@ static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
 		nicvf_config_vlan_stripping(nic, nic->netdev->features);
 
 	/* Enable Receive queue */
+	memset(&rq_cfg, 0, sizeof(struct rq_cfg));
 	rq_cfg.ena = 1;
 	rq_cfg.tcp_ena = 0;
 	nicvf_queue_reg_write(nic, NIC_QSET_RQ_0_7_CFG, qidx, *(u64 *)&rq_cfg);
@@ -565,6 +566,7 @@ void nicvf_cmp_queue_config(struct nicvf *nic, struct queue_set *qs,
 			      qidx, (u64)(cq->dmem.phys_base));
 
 	/* Enable Completion queue */
+	memset(&cq_cfg, 0, sizeof(struct cq_cfg));
 	cq_cfg.ena = 1;
 	cq_cfg.reset = 0;
 	cq_cfg.caching = 0;
@@ -613,6 +615,7 @@ static void nicvf_snd_queue_config(struct nicvf *nic, struct queue_set *qs,
 			      qidx, (u64)(sq->dmem.phys_base));
 
 	/* Enable send queue  & set queue size */
+	memset(&sq_cfg, 0, sizeof(struct sq_cfg));
 	sq_cfg.ena = 1;
 	sq_cfg.reset = 0;
 	sq_cfg.ldwb = 0;
@@ -649,6 +652,7 @@ static void nicvf_rbdr_config(struct nicvf *nic, struct queue_set *qs,
 
 	/* Enable RBDR  & set queue size */
 	/* Buffer size should be in multiples of 128 bytes */
+	memset(&rbdr_cfg, 0, sizeof(struct rbdr_cfg));
 	rbdr_cfg.ena = 1;
 	rbdr_cfg.reset = 0;
 	rbdr_cfg.ldwb = 0;
-- 
2.1.4



From chanho.min at lge.com  Sun May  8 16:39:05 2016
From: chanho.min at lge.com (Chanho Min)
Date: Mon, 9 May 2016 08:39:05 +0900
Subject: [PATCH] arm64: defconfig: Enable Cadence MACB/GEM support
Message-ID: <1462750745-11255-1-git-send-email-chanho.min@lge.com>

This patch enables the cadence MACB/GEM support that is needed
by lg1312 SoC.

Signed-off-by: Chanho Min <chanho.min at lge.com>
---
 arch/arm64/configs/defconfig |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 14dbe27..ed11cb6 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -105,6 +105,7 @@ CONFIG_TUN=y
 CONFIG_VIRTIO_NET=y
 CONFIG_AMD_XGBE=y
 CONFIG_NET_XGENE=y
+CONFIG_MACB=y
 CONFIG_E1000E=y
 CONFIG_IGB=y
 CONFIG_IGBVF=y
-- 
1.7.9.5



From fugang.duan at nxp.com  Sun May  8 19:00:37 2016
From: fugang.duan at nxp.com (Fugang Duan)
Date: Mon, 9 May 2016 02:00:37 +0000
Subject: [PATCH net 1/1] net: fec: update dirty_tx even if no skb
In-Reply-To: <0288eea6-9669-d763-4bd8-9438ce0c1f94@boundarydevices.com>
References: <1461290434-18462-1-git-send-email-troy.kisky@boundarydevices.com>
 <VI1PR0401MB18558325A80D252D2EC64A7BFF6F0@VI1PR0401MB1855.eurprd04.prod.outlook.com>
 <0288eea6-9669-d763-4bd8-9438ce0c1f94@boundarydevices.com>
Message-ID: <VI1PR0401MB18554C917BB5BEA7807D9DFAFF700@VI1PR0401MB1855.eurprd04.prod.outlook.com>

From: Troy Kisky <troy.kisky at boundarydevices.com> Sent: Sunday, May 08, 2016 2:57 AM
> To: Fugang Duan <fugang.duan at nxp.com>; netdev at vger.kernel.org;
> davem at davemloft.net; lznuaa at gmail.com
> Cc: Fabio Estevam <fabio.estevam at nxp.com>; l.stach at pengutronix.de;
> andrew at lunn.ch; tremyfr at gmail.com; gerg at uclinux.org; linux-arm-
> kernel at lists.infradead.org; johannes at sipsolutions.net;
> stillcompiling at gmail.com; sergei.shtylyov at cogentembedded.com;
> arnd at arndb.de; holgerschurig at gmail.com
> Subject: Re: [PATCH net 1/1] net: fec: update dirty_tx even if no skb
> 
> On 4/21/2016 10:59 PM, Fugang Duan wrote:
> > From: Troy Kisky <troy.kisky at boundarydevices.com> Sent: Friday, April
> > 22, 2016 10:01 AM
> >> To: netdev at vger.kernel.org; davem at davemloft.net; Fugang Duan
> >> <fugang.duan at nxp.com>; lznuaa at gmail.com
> >> Cc: Fabio Estevam <fabio.estevam at nxp.com>; l.stach at pengutronix.de;
> >> andrew at lunn.ch; tremyfr at gmail.com; gerg at uclinux.org; linux-arm-
> >> kernel at lists.infradead.org; johannes at sipsolutions.net;
> >> stillcompiling at gmail.com; sergei.shtylyov at cogentembedded.com;
> >> arnd at arndb.de; holgerschurig at gmail.com; Troy Kisky
> >> <troy.kisky at boundarydevices.com>
> >> Subject: [PATCH net 1/1] net: fec: update dirty_tx even if no skb
> >>
> >> If dirty_tx isn't updated, then dma_unmap_single will be called twice.
> >>
> >> This fixes a
> >> [   58.420980] ------------[ cut here ]------------
> >> [   58.425667] WARNING: CPU: 0 PID: 377 at /home/schurig/d/mkarm/linux-
> >> 4.5/lib/dma-debug.c:1096 check_unmap+0x9d0/0xab8()
> >> [   58.436405] fec 2188000.ethernet: DMA-API: device driver tries to free
> DMA
> >> memory it has not allocated [device address=0x0000000000000000]
> >> [size=66 bytes]
> >>
> >> encountered by Holger
> >>
> >> Signed-off-by: Troy Kisky <troy.kisky at boundarydevices.com>
> >> Tested-by: <holgerschurig at gmail.com>
> >> ---
> >>  drivers/net/ethernet/freescale/fec_main.c | 8 +++-----
> >>  1 file changed, 3 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/net/ethernet/freescale/fec_main.c
> >> b/drivers/net/ethernet/freescale/fec_main.c
> >> index 08243c2..b71654c 100644
> >> --- a/drivers/net/ethernet/freescale/fec_main.c
> >> +++ b/drivers/net/ethernet/freescale/fec_main.c
> >> @@ -1197,10 +1197,8 @@ fec_enet_tx_queue(struct net_device *ndev,
> u16
> >> queue_id)
> >>  					 fec16_to_cpu(bdp->cbd_datlen),
> >>  					 DMA_TO_DEVICE);
> >>  		bdp->cbd_bufaddr = cpu_to_fec32(0);
> >> -		if (!skb) {
> >> -			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
> >> -			continue;
> >> -		}
> >> +		if (!skb)
> >> +			goto skb_done;
> >>
> >>  		/* Check for errors. */
> >>  		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | @@ -1239,7
> >> +1237,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
> >>
> >>  		/* Free the sk buffer associated with this last transmit */
> >>  		dev_kfree_skb_any(skb);
> >> -
> >> +skb_done:
> >>  		/* Make sure the update to bdp and tx_skbuff are performed
> >>  		 * before dirty_tx
> >>  		 */
> >> --
> >> 2.5.0
> >
> > The patch is fine for me.
> > Can you review below patch that also fix the issue. It can take much
> > effort due to less rmb() and READ_ONCE() operation that is very
> > sensitive for duplex Gbps test for i.MX6SX/i.MX7d SOC. (i.MX6SX can
> > reach at 1.4Gbps, i.MX7D can reach at 1.8Gbps.)
> >
> 
> 
> Am I supposed to do anything else to get this patch into net ?

I will ack your patch that is fine into net tree.


From fugang.duan at nxp.com  Sun May  8 19:02:46 2016
From: fugang.duan at nxp.com (Fugang Duan)
Date: Mon, 9 May 2016 02:02:46 +0000
Subject: [PATCH net 1/1] net: fec: update dirty_tx even if no skb
In-Reply-To: <1461290434-18462-1-git-send-email-troy.kisky@boundarydevices.com>
References: <1461290434-18462-1-git-send-email-troy.kisky@boundarydevices.com>
Message-ID: <VI1PR0401MB1855159EE178BE4806E3E3B3FF700@VI1PR0401MB1855.eurprd04.prod.outlook.com>

From: Troy Kisky <troy.kisky at boundarydevices.com> Sent: Friday, April 22, 2016 10:01 AM
> To: netdev at vger.kernel.org; davem at davemloft.net; Fugang Duan
> <fugang.duan at nxp.com>; lznuaa at gmail.com
> Cc: Fabio Estevam <fabio.estevam at nxp.com>; l.stach at pengutronix.de;
> andrew at lunn.ch; tremyfr at gmail.com; gerg at uclinux.org; linux-arm-
> kernel at lists.infradead.org; johannes at sipsolutions.net;
> stillcompiling at gmail.com; sergei.shtylyov at cogentembedded.com;
> arnd at arndb.de; holgerschurig at gmail.com; Troy Kisky
> <troy.kisky at boundarydevices.com>
> Subject: [PATCH net 1/1] net: fec: update dirty_tx even if no skb
> 
> If dirty_tx isn't updated, then dma_unmap_single will be called twice.
> 
> This fixes a
> [   58.420980] ------------[ cut here ]------------
> [   58.425667] WARNING: CPU: 0 PID: 377 at /home/schurig/d/mkarm/linux-
> 4.5/lib/dma-debug.c:1096 check_unmap+0x9d0/0xab8()
> [   58.436405] fec 2188000.ethernet: DMA-API: device driver tries to free DMA
> memory it has not allocated [device address=0x0000000000000000] [size=66
> bytes]
> 
> encountered by Holger
> 
> Signed-off-by: Troy Kisky <troy.kisky at boundarydevices.com>
> Tested-by: <holgerschurig at gmail.com>
> ---
>  drivers/net/ethernet/freescale/fec_main.c | 8 +++-----
>  1 file changed, 3 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/freescale/fec_main.c
> b/drivers/net/ethernet/freescale/fec_main.c
> index 08243c2..b71654c 100644
> --- a/drivers/net/ethernet/freescale/fec_main.c
> +++ b/drivers/net/ethernet/freescale/fec_main.c
> @@ -1197,10 +1197,8 @@ fec_enet_tx_queue(struct net_device *ndev, u16
> queue_id)
>  					 fec16_to_cpu(bdp->cbd_datlen),
>  					 DMA_TO_DEVICE);
>  		bdp->cbd_bufaddr = cpu_to_fec32(0);
> -		if (!skb) {
> -			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
> -			continue;
> -		}
> +		if (!skb)
> +			goto skb_done;
> 
>  		/* Check for errors. */
>  		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | @@ -1239,7
> +1237,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
> 
>  		/* Free the sk buffer associated with this last transmit */
>  		dev_kfree_skb_any(skb);
> -
> +skb_done:
>  		/* Make sure the update to bdp and tx_skbuff are performed
>  		 * before dirty_tx
>  		 */
> --
> 2.5.0

Thanks. 
Acked-by: Fugang Duan <fugang.duan at nxp.com>


From shankerd at codeaurora.org  Sun May  8 19:14:42 2016
From: shankerd at codeaurora.org (Shanker Donthineni)
Date: Sun,  8 May 2016 21:14:42 -0500
Subject: [PATCH V2 2/2] irqchip/gicv3-its: Implement two-level(indirect)
 device table support
In-Reply-To: <1462760082-21943-1-git-send-email-shankerd@codeaurora.org>
References: <1462760082-21943-1-git-send-email-shankerd@codeaurora.org>
Message-ID: <1462760082-21943-2-git-send-email-shankerd@codeaurora.org>

Since device IDs are extremely sparse, the single, a.k.a flat table is
not sufficient for the following two reasons.

1) According to ARM-GIC spec, ITS hw can access maximum of 256(pages)*
   64K(pageszie) bytes. In the best case, it supports upto DEVid=21
   sparse with minimum device table entry size 8bytes.

2) The maximum memory size that is possible without memblock depends on
   MAX_ORDER. 4MB on 4K page size kernel with default MAX_ORDER, so it
   supports DEVid range 19bits.

The two-level device table feature brings us two advantages, the first
is a very high possibility of supporting upto 32bit sparse, and the
second one is the best utilization of memory allocation.

The feature is enabled automatically during driver probe if a single
ITS page is not adequate for flat table and the hardware is capable
of two-level table walk.

Signed-off-by: Shanker Donthineni <shankerd at codeaurora.org>
---

This patch is based on Marc Zyngier's branch https://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git/log/?h=irq/irqchip-4.7

I have tested the Indirection feature on Qualcomm Technologies QDF2XXX server platform.

Changes since v1:
  Most of this patch has been rewritten after refactoring its_alloc_tables().
  Always enable device two-level if the memory requirement is more than PAGE_SIZE.
  Fixed the coding bug that breaks on the BE machine.
  Edited the commit text.

 drivers/irqchip/irq-gic-v3-its.c | 100 ++++++++++++++++++++++++++++++++-------
 1 file changed, 83 insertions(+), 17 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index b23e00c..27be792 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -938,6 +938,18 @@ retry_baser:
 	return 0;
 }
 
+/**
+ * Find out whether an implemented baser register supports a single, flat table
+ * or a two-level table by reading bit offset at '62' after writing '1' to it.
+ */
+static u64 its_baser_check_indirect(struct its_baser *baser)
+{
+	u64 val = GITS_BASER_InnerShareable | GITS_BASER_WaWb;
+
+	writeq_relaxed(val | GITS_BASER_INDIRECT, baser->hwreg);
+	return (readq_relaxed(baser->hwreg) & GITS_BASER_INDIRECT);
+}
+
 static int its_alloc_tables(const char *node_name, struct its_node *its)
 {
 	u64 typer = readq_relaxed(its->base + GITS_TYPER);
@@ -964,6 +976,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 		u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
 		int order = get_order(psz);
 		struct its_baser *baser = its->tables + i;
+		u64 indirect = 0;
 
 		if (type == GITS_BASER_TYPE_NONE)
 			continue;
@@ -977,17 +990,27 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 		 * Allocate as many entries as required to fit the
 		 * range of device IDs that the ITS can grok... The ID
 		 * space being incredibly sparse, this results in a
-		 * massive waste of memory.
+		 * massive waste of memory if two-level device table
+		 * feature is not supported by hardware.
 		 *
 		 * For other tables, only allocate a single page.
 		 */
 		if (type == GITS_BASER_TYPE_DEVICE) {
-			/*
-			 * 'order' was initialized earlier to the default page
-			 * granule of the the ITS.  We can't have an allocation
-			 * smaller than that.  If the requested allocation
-			 * is smaller, round up to the default page granule.
-			 */
+			if ((entry_size << ids) > psz)
+				indirect = its_baser_check_indirect(baser);
+
+			if (indirect) {
+				/*
+				 * The size of the lvl2 table is equal to ITS
+				 * page size which is 'psz'. For computing lvl1
+				 * table size, subtract ID bits that sparse
+				 * lvl2 table from 'ids' which is reported by
+				 * ITS hardware times lvl1 table entry size.
+				 */
+				ids -= ilog2(psz / entry_size);
+				entry_size = GITS_LVL1_ENTRY_SIZE;
+			}
+
 			order = max(get_order(entry_size << ids), order);
 			if (order >= MAX_ORDER) {
 				order = MAX_ORDER - 1;
@@ -997,7 +1020,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 			}
 		}
 
-		err = its_baser_setup(its, baser, order, 0);
+		err = its_baser_setup(its, baser, order, indirect);
 		if (err < 0) {
 			its_free_tables(its);
 			return err;
@@ -1187,10 +1210,60 @@ static struct its_baser *its_get_baser(struct its_node *its, u32 type)
 	return NULL;
 }
 
+static bool its_alloc_device_table(struct its_node *its, u32 dev_id)
+{
+	struct its_baser *baser;
+	struct page *page;
+	u32 entry_size, idx;
+	u64 *table;
+
+	baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
+
+	/* Don't allow 'dev_id' that exceeds ITS hardware limit */
+	if (!baser && (ilog2(dev_id) >= its->device_ids))
+		return false;
+
+	/* Don't allow 'dev_id' that exceeds single, flat table limit */
+	entry_size = GITS_BASER_ENTRY_SIZE(baser->val);
+	if (!(baser->val & GITS_BASER_INDIRECT)) {
+		if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) / entry_size))
+			return false;
+		return true;
+	}
+
+	/* Compute Level1 table index & check if that exceeds table range */
+	idx = dev_id >> ilog2(baser->psz / entry_size);
+	if (idx >= (PAGE_ORDER_TO_SIZE(baser->order) / GITS_LVL1_ENTRY_SIZE))
+		return false;
+
+	table = baser->base;
+
+	/* Allocate memory for Level2 table */
+	if (!table[idx]) {
+		page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(baser->psz));
+		if (!page)
+			return false;
+
+		/* Flush memory to PoC if hardware doesn't support coherency */
+		if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
+			__flush_dcache_area(page_address(page), baser->psz);
+
+		table[idx] = cpu_to_le64(page_to_phys(page) | GITS_BASER_VALID);
+
+		/* Flush memory to PoC if hardware doesn't support coherency */
+		if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
+			__flush_dcache_area(table + idx, GITS_LVL1_ENTRY_SIZE);
+
+		/* Ensure updated table contents are visible to ITS hardware */
+		dsb(sy);
+	}
+
+	return true;
+}
+
 static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 					    int nvecs)
 {
-	struct its_baser *baser;
 	struct its_device *dev;
 	unsigned long *lpi_map;
 	unsigned long flags;
@@ -1201,14 +1274,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 	int nr_ites;
 	int sz;
 
-	baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
-
-	/* Don't allow 'dev_id' that exceeds single, flat table limit */
-	if (baser) {
-		if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) /
-			      GITS_BASER_ENTRY_SIZE(baser->val)))
-			return NULL;
-	} else if (ilog2(dev_id) >= its->device_ids)
+	if (!its_alloc_device_table(its, dev_id))
 		return NULL;
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project



From shankerd at codeaurora.org  Sun May  8 19:14:41 2016
From: shankerd at codeaurora.org (Shanker Donthineni)
Date: Sun,  8 May 2016 21:14:41 -0500
Subject: [PATCH V2 1/2] irqchip/gicv3-its: split its_alloc_tables() into two
 functions
Message-ID: <1462760082-21943-1-git-send-email-shankerd@codeaurora.org>

The function is getting out of control, it has too many goto
statements and would be too complicated for adding a feature
two-level device table. So, it is time for us to cleanup and
move some of the logic to a separate function without affecting
the existing functionality.

Signed-off-by: Shanker Donthineni <shankerd at codeaurora.org>
---

This patch is based on Marc Zyngier's branch https://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git/log/?h=irq/irqchip-4.7

 drivers/irqchip/irq-gic-v3-its.c   | 256 ++++++++++++++++++++-----------------
 include/linux/irqchip/arm-gic-v3.h |   3 +
 2 files changed, 144 insertions(+), 115 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 6bd881b..b23e00c 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -55,13 +55,15 @@ struct its_collection {
 };
 
 /*
- * The ITS_BASER structure - contains memory information and cached
- * value of BASER register configuration.
+ * The ITS_BASER structure - contains memory information, cached value
+ * of BASER register configuration, ioremaped address and page size.
  */
 struct its_baser {
+	void __iomem	*hwreg;
 	void		*base;
 	u64		val;
 	u32		order;
+	u32		psz;
 };
 
 /*
@@ -823,27 +825,135 @@ static void its_free_tables(struct its_node *its)
 	}
 }
 
+static int its_baser_setup(struct its_node *its, struct its_baser *baser,
+				  u32 order, u64 indirect)
+{
+	u64 val = readq_relaxed(baser->hwreg);
+	u64 type = GITS_BASER_TYPE(val);
+	u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
+	int psz, alloc_pages;
+	u64 cache, shr, tmp;
+	void *base;
+
+	/* Do first attempt with the requested attributes */
+	cache = baser->val & GITS_BASER_CACHEABILITY_MASK;
+	shr = baser->val & GITS_BASER_SHAREABILITY_MASK;
+	psz = baser->psz;
+
+retry_alloc_baser:
+	alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
+	if (alloc_pages > GITS_BASER_PAGES_MAX) {
+		pr_warn("ITS@%lx: %s too large, reduce ITS pages %u->%u\n",
+			its->phys_base, its_base_type_string[type],
+			alloc_pages, GITS_BASER_PAGES_MAX);
+		alloc_pages = GITS_BASER_PAGES_MAX;
+		order = get_order(GITS_BASER_PAGES_MAX * psz);
+	}
+
+	base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
+	if (!base)
+		return -ENOMEM;
+
+retry_baser:
+	val = (virt_to_phys(base)				 |
+		(type << GITS_BASER_TYPE_SHIFT)			 |
+		((entry_size - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) |
+		((alloc_pages - 1) << GITS_BASER_PAGES_SHIFT)	 |
+		cache						 |
+		shr						 |
+		indirect					 |
+		GITS_BASER_VALID);
+
+	switch (psz) {
+	case SZ_4K:
+		val |= GITS_BASER_PAGE_SIZE_4K;
+		break;
+	case SZ_16K:
+		val |= GITS_BASER_PAGE_SIZE_16K;
+		break;
+	case SZ_64K:
+		val |= GITS_BASER_PAGE_SIZE_64K;
+		break;
+	}
+
+	writeq_relaxed(val, baser->hwreg);
+	tmp = readq_relaxed(baser->hwreg);
+
+	if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
+		/*
+		 * Shareability didn't stick. Just use
+		 * whatever the read reported, which is likely
+		 * to be the only thing this redistributor
+		 * supports. If that's zero, make it
+		 * non-cacheable as well.
+		 */
+		shr = tmp & GITS_BASER_SHAREABILITY_MASK;
+		if (!shr) {
+			cache = GITS_BASER_nC;
+			__flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));
+		}
+		goto retry_baser;
+	}
+
+	if ((val ^ tmp) & GITS_BASER_PAGE_SIZE_MASK) {
+		/*
+		 * Page size didn't stick. Let's try a smaller
+		 * size and retry. If we reach 4K, then
+		 * something is horribly wrong...
+		 */
+		free_pages((unsigned long)base, order);
+		baser->base = NULL;
+
+		switch (psz) {
+		case SZ_16K:
+			psz = SZ_4K;
+			goto retry_alloc_baser;
+		case SZ_64K:
+			psz = SZ_16K;
+			goto retry_alloc_baser;
+		}
+	}
+
+	if (val != tmp) {
+		pr_err("ITS@%lx: %s doesn't stick: %lx %lx\n",
+		       its->phys_base, its_base_type_string[type],
+		       (unsigned long) val, (unsigned long) tmp);
+		free_pages((unsigned long)base, order);
+		return -ENXIO;
+	}
+
+	baser->base = base;
+	baser->order = order;
+	baser->psz = psz;
+	baser->val = val;
+	tmp = indirect ? GITS_LVL1_ENTRY_SIZE : entry_size;
+
+	pr_info("ITS@%lx: allocated %d %s @%lx (%s, esz %d, psz %dK, shr %d)\n",
+		its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / tmp),
+		its_base_type_string[type],
+		(unsigned long)virt_to_phys(base),
+		indirect ? "indirect" : "flat", (int)entry_size,
+		psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
+
+	return 0;
+}
+
 static int its_alloc_tables(const char *node_name, struct its_node *its)
 {
-	int err;
-	int i;
-	int psz = SZ_64K;
+	u64 typer = readq_relaxed(its->base + GITS_TYPER);
+	u32 ids = GITS_TYPER_DEVBITS(typer);
 	u64 shr = GITS_BASER_InnerShareable;
-	u64 cache;
-	u64 typer;
-	u32 ids;
+	u64 cache = GITS_BASER_WaWb;
+	int psz = SZ_64K;
+	int err, i;
 
 	if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_22375) {
 		/*
 		 * erratum 22375: only alloc 8MB table size
 		 * erratum 24313: ignore memory access type
 		 */
-		cache	= 0;
+		cache	= GITS_BASER_nCnB;
 		ids	= 0x14;			/* 20 bits, 8MB */
-	} else {
-		cache	= GITS_BASER_WaWb;
-		typer	= readq_relaxed(its->base + GITS_TYPER);
-		ids	= GITS_TYPER_DEVBITS(typer);
 	}
 
 	its->device_ids = ids;
@@ -853,13 +963,16 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 		u64 type = GITS_BASER_TYPE(val);
 		u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
 		int order = get_order(psz);
-		int alloc_pages;
-		u64 tmp;
-		void *base;
+		struct its_baser *baser = its->tables + i;
 
 		if (type == GITS_BASER_TYPE_NONE)
 			continue;
 
+		/* Set preferred settings for this BASERn */
+		baser->hwreg = its->base + GITS_BASER + i * 8;
+		baser->val = cache | shr;
+		baser->psz = psz;
+
 		/*
 		 * Allocate as many entries as required to fit the
 		 * range of device IDs that the ITS can grok... The ID
@@ -875,115 +988,28 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 			 * smaller than that.  If the requested allocation
 			 * is smaller, round up to the default page granule.
 			 */
-			order = max(get_order((1UL << ids) * entry_size),
-				    order);
+			order = max(get_order(entry_size << ids), order);
 			if (order >= MAX_ORDER) {
 				order = MAX_ORDER - 1;
-				pr_warn("%s: Device Table too large, reduce its page order to %u\n",
-					node_name, order);
-			}
-		}
-
-retry_alloc_baser:
-		alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
-		if (alloc_pages > GITS_BASER_PAGES_MAX) {
-			alloc_pages = GITS_BASER_PAGES_MAX;
-			order = get_order(GITS_BASER_PAGES_MAX * psz);
-			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
-				node_name, order, alloc_pages);
-		}
-
-		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
-		if (!base) {
-			err = -ENOMEM;
-			goto out_free;
-		}
-
-		its->tables[i].base = base;
-		its->tables[i].order = order;
-
-retry_baser:
-		val = (virt_to_phys(base) 				 |
-		       (type << GITS_BASER_TYPE_SHIFT)			 |
-		       ((entry_size - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) |
-		       cache						 |
-		       shr						 |
-		       GITS_BASER_VALID);
-
-		switch (psz) {
-		case SZ_4K:
-			val |= GITS_BASER_PAGE_SIZE_4K;
-			break;
-		case SZ_16K:
-			val |= GITS_BASER_PAGE_SIZE_16K;
-			break;
-		case SZ_64K:
-			val |= GITS_BASER_PAGE_SIZE_64K;
-			break;
-		}
-
-		val |= alloc_pages - 1;
-		its->tables[i].val = val;
-
-		writeq_relaxed(val, its->base + GITS_BASER + i * 8);
-		tmp = readq_relaxed(its->base + GITS_BASER + i * 8);
-
-		if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
-			/*
-			 * Shareability didn't stick. Just use
-			 * whatever the read reported, which is likely
-			 * to be the only thing this redistributor
-			 * supports. If that's zero, make it
-			 * non-cacheable as well.
-			 */
-			shr = tmp & GITS_BASER_SHAREABILITY_MASK;
-			if (!shr) {
-				cache = GITS_BASER_nC;
-				__flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));
+				ids = ilog2(PAGE_ORDER_TO_SIZE(order) / entry_size);
+				pr_warn("ITS@%lx:: Device Table too large, reduce ids %u->%u\n",
+					its->phys_base, its->device_ids, ids);
 			}
-			goto retry_baser;
 		}
 
-		if ((val ^ tmp) & GITS_BASER_PAGE_SIZE_MASK) {
-			/*
-			 * Page size didn't stick. Let's try a smaller
-			 * size and retry. If we reach 4K, then
-			 * something is horribly wrong...
-			 */
-			free_pages((unsigned long)base, order);
-			its->tables[i].base = NULL;
-
-			switch (psz) {
-			case SZ_16K:
-				psz = SZ_4K;
-				goto retry_alloc_baser;
-			case SZ_64K:
-				psz = SZ_16K;
-				goto retry_alloc_baser;
-			}
-		}
-
-		if (val != tmp) {
-			pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n",
-			       node_name, i,
-			       (unsigned long) val, (unsigned long) tmp);
-			err = -ENXIO;
-			goto out_free;
+		err = its_baser_setup(its, baser, order, 0);
+		if (err < 0) {
+			its_free_tables(its);
+			return err;
 		}
 
-		pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n",
-			(int)(PAGE_ORDER_TO_SIZE(order) / entry_size),
-			its_base_type_string[type],
-			(unsigned long)virt_to_phys(base),
-			psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
+		/* Update settings which will be used for next BASERn */
+		psz = baser->psz;
+		cache = baser->val & GITS_BASER_CACHEABILITY_MASK;
+		shr = baser->val & GITS_BASER_SHAREABILITY_MASK;
 	}
 
 	return 0;
-
-out_free:
-	its_free_tables(its);
-
-	return err;
 }
 
 static int its_alloc_collections(struct its_node *its)
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 9e6fdd3..7f917b9 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -204,6 +204,7 @@
 #define GITS_BASER_NR_REGS		8
 
 #define GITS_BASER_VALID		(1UL << 63)
+#define GITS_BASER_INDIRECT		(1UL << 62)
 #define GITS_BASER_nCnB			(0UL << 59)
 #define GITS_BASER_nC			(1UL << 59)
 #define GITS_BASER_RaWt			(2UL << 59)
@@ -228,6 +229,7 @@
 #define GITS_BASER_PAGE_SIZE_64K	(2UL << GITS_BASER_PAGE_SIZE_SHIFT)
 #define GITS_BASER_PAGE_SIZE_MASK	(3UL << GITS_BASER_PAGE_SIZE_SHIFT)
 #define GITS_BASER_PAGES_MAX		256
+#define GITS_BASER_PAGES_SHIFT		(0)
 
 #define GITS_BASER_TYPE_NONE		0
 #define GITS_BASER_TYPE_DEVICE		1
@@ -238,6 +240,7 @@
 #define GITS_BASER_TYPE_RESERVED6	6
 #define GITS_BASER_TYPE_RESERVED7	7
 
+#define GITS_LVL1_ENTRY_SIZE		(8UL)
 /*
  * ITS commands
  */
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project



From shawn.lin at rock-chips.com  Sun May  8 20:00:33 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Mon, 9 May 2016 11:00:33 +0800
Subject: [PATCH] mmc: mmc: do not use CMD13 to get status after speed mode
 switch
In-Reply-To: <1462344872-6448-1-git-send-email-chaotian.jing@mediatek.com>
References: <1462344872-6448-1-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <5fa01153-6724-5426-1f71-b7caf31bf796@rock-chips.com>

+ linux-rockchip


I just hacked my local branch to fix the issues found on rockchip
platform. The reaseon is that mmc core fail to get status
after switching from hs200 to hs. So I disabled sending status for it
just like what Chaotian does here. But I didn't deeply dig out the root
cause but I agree with Chaotian's opinion.

FYI:
My emmc deivce is KLMA62WEPD-B031.

[    1.526008] sdhci: Secure Digital Host Controller Interface driver
[    1.526558] sdhci: Copyright(c) Pierre Ossman
[    1.527899] sdhci-pltfm: SDHCI platform and OF driver helper
[    1.529967] sdhci-arasan fe330000.sdhci: No vmmc regulator found
[    1.530501] sdhci-arasan fe330000.sdhci: No vqmmc regulator found
[    1.568710] mmc0: SDHCI controller on fe330000.sdhci [fe330000.sdhci] 
using ADMA
[    1.627552] mmc0: switch to high-speed from hs200 failed, err:-84
[    1.628108] mmc0: error -84 whilst initialising MMC card


? 2016/5/4 14:54, Chaotian Jing ??:
> Per JEDEC spec, it is not recommended to use CMD13 to get card status
> after speed mode switch. below are two reason about this:
> 1. CMD13 cannot be guaranteed due to the asynchronous operation.
> Therefore it is not recommended to use CMD13 to check busy completion
> of the timing change indication.
> 2. After switch to HS200, CMD13 will get response of 0x800, and even the
> busy signal gets de-asserted, the response of CMD13 is aslo 0x800.
>
> this patch drops CMD13 when doing speed mode switch, if host do not
> support MMC_CAP_WAIT_WHILE_BUSY and there is no ops->card_busy(),
> then the only way is to wait a fixed timeout.
>
> Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
> ---
>  drivers/mmc/core/mmc.c     |   82 ++++++++++++++++----------------------------
>  drivers/mmc/core/mmc_ops.c |   25 +++++++++-----
>  2 files changed, 45 insertions(+), 62 deletions(-)
>
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 4dbe3df..03ee7a4 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -962,7 +962,7 @@ static int mmc_select_hs(struct mmc_card *card)
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>  			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
>  			   card->ext_csd.generic_cmd6_time,
> -			   true, true, true);
> +			   true, false, true);
>  	if (!err)
>  		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
>
> @@ -1056,7 +1056,6 @@ static int mmc_switch_status(struct mmc_card *card)
>  static int mmc_select_hs400(struct mmc_card *card)
>  {
>  	struct mmc_host *host = card->host;
> -	bool send_status = true;
>  	unsigned int max_dtr;
>  	int err = 0;
>  	u8 val;
> @@ -1068,9 +1067,6 @@ static int mmc_select_hs400(struct mmc_card *card)
>  	      host->ios.bus_width == MMC_BUS_WIDTH_8))
>  		return 0;
>
> -	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
> -		send_status = false;
> -
>  	/* Reduce frequency to HS frequency */
>  	max_dtr = card->ext_csd.hs_max_dtr;
>  	mmc_set_clock(host, max_dtr);
> @@ -1080,7 +1076,7 @@ static int mmc_select_hs400(struct mmc_card *card)
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>  			   EXT_CSD_HS_TIMING, val,
>  			   card->ext_csd.generic_cmd6_time,
> -			   true, send_status, true);
> +			   true, false, true);
>  	if (err) {
>  		pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
>  			mmc_hostname(host), err);
> @@ -1090,11 +1086,9 @@ static int mmc_select_hs400(struct mmc_card *card)
>  	/* Set host controller to HS timing */
>  	mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
>
> -	if (!send_status) {
> -		err = mmc_switch_status(card);
> -		if (err)
> -			goto out_err;
> -	}
> +	err = mmc_switch_status(card);
> +	if (err)
> +		goto out_err;
>
>  	/* Switch card to DDR */
>  	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> @@ -1113,7 +1107,7 @@ static int mmc_select_hs400(struct mmc_card *card)
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>  			   EXT_CSD_HS_TIMING, val,
>  			   card->ext_csd.generic_cmd6_time,
> -			   true, send_status, true);
> +			   true, false, true);
>  	if (err) {
>  		pr_err("%s: switch to hs400 failed, err:%d\n",
>  			 mmc_hostname(host), err);
> @@ -1124,11 +1118,9 @@ static int mmc_select_hs400(struct mmc_card *card)
>  	mmc_set_timing(host, MMC_TIMING_MMC_HS400);
>  	mmc_set_bus_speed(card);
>
> -	if (!send_status) {
> -		err = mmc_switch_status(card);
> -		if (err)
> -			goto out_err;
> -	}
> +	err = mmc_switch_status(card);
> +	if (err)
> +		goto out_err;
>
>  	return 0;
>
> @@ -1146,14 +1138,10 @@ int mmc_hs200_to_hs400(struct mmc_card *card)
>  int mmc_hs400_to_hs200(struct mmc_card *card)
>  {
>  	struct mmc_host *host = card->host;
> -	bool send_status = true;
>  	unsigned int max_dtr;
>  	int err;
>  	u8 val;
>
> -	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
> -		send_status = false;
> -
>  	/* Reduce frequency to HS */
>  	max_dtr = card->ext_csd.hs_max_dtr;
>  	mmc_set_clock(host, max_dtr);
> @@ -1162,49 +1150,43 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
>  	val = EXT_CSD_TIMING_HS;
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
>  			   val, card->ext_csd.generic_cmd6_time,
> -			   true, send_status, true);
> +			   true, false, true);
>  	if (err)
>  		goto out_err;
>
>  	mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
>
> -	if (!send_status) {
> -		err = mmc_switch_status(card);
> -		if (err)
> -			goto out_err;
> -	}
> +	err = mmc_switch_status(card);
> +	if (err)
> +		goto out_err;
>
>  	/* Switch HS DDR to HS */
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
>  			   EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time,
> -			   true, send_status, true);
> +			   true, false, true);
>  	if (err)
>  		goto out_err;
>
>  	mmc_set_timing(host, MMC_TIMING_MMC_HS);
>
> -	if (!send_status) {
> -		err = mmc_switch_status(card);
> -		if (err)
> -			goto out_err;
> -	}
> +	err = mmc_switch_status(card);
> +	if (err)
> +		goto out_err;
>
>  	/* Switch HS to HS200 */
>  	val = EXT_CSD_TIMING_HS200 |
>  	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
>  			   val, card->ext_csd.generic_cmd6_time, true,
> -			   send_status, true);
> +			   false, true);
>  	if (err)
>  		goto out_err;
>
>  	mmc_set_timing(host, MMC_TIMING_MMC_HS200);
>
> -	if (!send_status) {
> -		err = mmc_switch_status(card);
> -		if (err)
> -			goto out_err;
> -	}
> +	err = mmc_switch_status(card);
> +	if (err)
> +		goto out_err;
>
>  	mmc_set_bus_speed(card);
>
> @@ -1243,7 +1225,6 @@ static void mmc_select_driver_type(struct mmc_card *card)
>  static int mmc_select_hs200(struct mmc_card *card)
>  {
>  	struct mmc_host *host = card->host;
> -	bool send_status = true;
>  	unsigned int old_timing;
>  	int err = -EINVAL;
>  	u8 val;
> @@ -1260,9 +1241,6 @@ static int mmc_select_hs200(struct mmc_card *card)
>
>  	mmc_select_driver_type(card);
>
> -	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
> -		send_status = false;
> -
>  	/*
>  	 * Set the bus width(4 or 8) with host's support and
>  	 * switch to HS200 mode if bus width is set successfully.
> @@ -1274,20 +1252,18 @@ static int mmc_select_hs200(struct mmc_card *card)
>  		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>  				   EXT_CSD_HS_TIMING, val,
>  				   card->ext_csd.generic_cmd6_time,
> -				   true, send_status, true);
> +				   true, false, true);
>  		if (err)
>  			goto err;
>  		old_timing = host->ios.timing;
>  		mmc_set_timing(host, MMC_TIMING_MMC_HS200);
> -		if (!send_status) {
> -			err = mmc_switch_status(card);
> -			/*
> -			 * mmc_select_timing() assumes timing has not changed if
> -			 * it is a switch error.
> -			 */
> -			if (err == -EBADMSG)
> -				mmc_set_timing(host, old_timing);
> -		}
> +		err = mmc_switch_status(card);
> +		/*
> +		 * mmc_select_timing() assumes timing has not changed if
> +		 * it is a switch error.
> +		 */
> +		if (err == -EBADMSG)
> +			mmc_set_timing(host, old_timing);
>  	}
>  err:
>  	if (err)
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index 62355bd..32de144 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -480,6 +480,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
>  	u32 status = 0;
>  	bool use_r1b_resp = use_busy_signal;
>  	bool expired = false;
> +	bool busy = false;
>
>  	mmc_retune_hold(host);
>
> @@ -535,19 +536,24 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
>  	/* Must check status to be sure of no errors. */
>  	timeout = jiffies + msecs_to_jiffies(timeout_ms);
>  	do {
> +		/*
> +		 * Due to the possibility of being preempted after
> +		 * sending the status command, check the expiration
> +		 * time first.
> +		 */
> +		expired = time_after(jiffies, timeout);
>  		if (send_status) {
> -			/*
> -			 * Due to the possibility of being preempted after
> -			 * sending the status command, check the expiration
> -			 * time first.
> -			 */
> -			expired = time_after(jiffies, timeout);
>  			err = __mmc_send_status(card, &status, ignore_crc);
>  			if (err)
>  				goto out;
>  		}
>  		if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
>  			break;
> +		if (host->ops->card_busy) {
> +			if (!host->ops->card_busy(host))
> +				break;
> +			busy = true;
> +		}
>  		if (mmc_host_is_spi(host))
>  			break;
>
> @@ -556,19 +562,20 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
>  		 * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
>  		 * rely on waiting for the stated timeout to be sufficient.
>  		 */
> -		if (!send_status) {
> +		if (!send_status && !host->ops->card_busy) {
>  			mmc_delay(timeout_ms);
>  			goto out;
>  		}
>
>  		/* Timeout if the device never leaves the program state. */
> -		if (expired && R1_CURRENT_STATE(status) == R1_STATE_PRG) {
> +		if (expired &&
> +		    (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy)) {
>  			pr_err("%s: Card stuck in programming state! %s\n",
>  				mmc_hostname(host), __func__);
>  			err = -ETIMEDOUT;
>  			goto out;
>  		}
> -	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
> +	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy);
>
>  	err = mmc_switch_status_error(host, status);
>  out:
>


-- 
Best Regards
Shawn Lin



From shankerd at codeaurora.org  Sun May  8 21:02:46 2016
From: shankerd at codeaurora.org (Shanker Donthineni)
Date: Sun, 8 May 2016 23:02:46 -0500
Subject: [PATCH V2 2/2] irqchip/gicv3-its: Implement two-level(indirect)
 device table support
In-Reply-To: <1462760082-21943-2-git-send-email-shankerd@codeaurora.org>
References: <1462760082-21943-1-git-send-email-shankerd@codeaurora.org>
 <1462760082-21943-2-git-send-email-shankerd@codeaurora.org>
Message-ID: <57300BE6.20804@codeaurora.org>



On 05/08/2016 09:14 PM, Shanker Donthineni wrote:
> Since device IDs are extremely sparse, the single, a.k.a flat table is
> not sufficient for the following two reasons.
>
> 1) According to ARM-GIC spec, ITS hw can access maximum of 256(pages)*
>    64K(pageszie) bytes. In the best case, it supports upto DEVid=21
>    sparse with minimum device table entry size 8bytes.
>
> 2) The maximum memory size that is possible without memblock depends on
>    MAX_ORDER. 4MB on 4K page size kernel with default MAX_ORDER, so it
>    supports DEVid range 19bits.
>
> The two-level device table feature brings us two advantages, the first
> is a very high possibility of supporting upto 32bit sparse, and the
> second one is the best utilization of memory allocation.
>
> The feature is enabled automatically during driver probe if a single
> ITS page is not adequate for flat table and the hardware is capable
> of two-level table walk.
>
> Signed-off-by: Shanker Donthineni <shankerd at codeaurora.org>
> ---
>
> This patch is based on Marc Zyngier's branch https://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git/log/?h=irq/irqchip-4.7
>
> I have tested the Indirection feature on Qualcomm Technologies QDF2XXX server platform.
>
> Changes since v1:
>   Most of this patch has been rewritten after refactoring its_alloc_tables().
>   Always enable device two-level if the memory requirement is more than PAGE_SIZE.
>   Fixed the coding bug that breaks on the BE machine.
>   Edited the commit text.
>
>  drivers/irqchip/irq-gic-v3-its.c | 100 ++++++++++++++++++++++++++++++++-------
>  1 file changed, 83 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index b23e00c..27be792 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -938,6 +938,18 @@ retry_baser:
>  	return 0;
>  }
>  
> +/**
> + * Find out whether an implemented baser register supports a single, flat table
> + * or a two-level table by reading bit offset at '62' after writing '1' to it.
> + */
> +static u64 its_baser_check_indirect(struct its_baser *baser)
> +{
> +	u64 val = GITS_BASER_InnerShareable | GITS_BASER_WaWb;
> +
> +	writeq_relaxed(val | GITS_BASER_INDIRECT, baser->hwreg);
> +	return (readq_relaxed(baser->hwreg) & GITS_BASER_INDIRECT);
> +}
> +
>  static int its_alloc_tables(const char *node_name, struct its_node *its)
>  {
>  	u64 typer = readq_relaxed(its->base + GITS_TYPER);
> @@ -964,6 +976,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
>  		u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
>  		int order = get_order(psz);
>  		struct its_baser *baser = its->tables + i;
> +		u64 indirect = 0;
>  
>  		if (type == GITS_BASER_TYPE_NONE)
>  			continue;
> @@ -977,17 +990,27 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
>  		 * Allocate as many entries as required to fit the
>  		 * range of device IDs that the ITS can grok... The ID
>  		 * space being incredibly sparse, this results in a
> -		 * massive waste of memory.
> +		 * massive waste of memory if two-level device table
> +		 * feature is not supported by hardware.
>  		 *
>  		 * For other tables, only allocate a single page.
>  		 */
>  		if (type == GITS_BASER_TYPE_DEVICE) {
> -			/*
> -			 * 'order' was initialized earlier to the default page
> -			 * granule of the the ITS.  We can't have an allocation
> -			 * smaller than that.  If the requested allocation
> -			 * is smaller, round up to the default page granule.
> -			 */
> +			if ((entry_size << ids) > psz)
> +				indirect = its_baser_check_indirect(baser);
> +
> +			if (indirect) {
> +				/*
> +				 * The size of the lvl2 table is equal to ITS
> +				 * page size which is 'psz'. For computing lvl1
> +				 * table size, subtract ID bits that sparse
> +				 * lvl2 table from 'ids' which is reported by
> +				 * ITS hardware times lvl1 table entry size.
> +				 */
> +				ids -= ilog2(psz / entry_size);
> +				entry_size = GITS_LVL1_ENTRY_SIZE;
> +			}
> +
>  			order = max(get_order(entry_size << ids), order);
>  			if (order >= MAX_ORDER) {
>  				order = MAX_ORDER - 1;
> @@ -997,7 +1020,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
>  			}
>  		}
>  
> -		err = its_baser_setup(its, baser, order, 0);
> +		err = its_baser_setup(its, baser, order, indirect);
>  		if (err < 0) {
>  			its_free_tables(its);
>  			return err;
> @@ -1187,10 +1210,60 @@ static struct its_baser *its_get_baser(struct its_node *its, u32 type)
>  	return NULL;
>  }
>  
> +static bool its_alloc_device_table(struct its_node *its, u32 dev_id)
> +{
> +	struct its_baser *baser;
> +	struct page *page;
> +	u32 entry_size, idx;
> +	u64 *table;
> +
> +	baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
> +
> +	/* Don't allow 'dev_id' that exceeds ITS hardware limit */
> +	if (!baser && (ilog2(dev_id) >= its->device_ids))
> +		return false;
> +
I have missed this change, will be fixed in v3 patchset.

    if (!baser) {
        if (ilog2(dev_id) >= its->device_ids))
            return false;
        return true;
    }

> +	/* Don't allow 'dev_id' that exceeds single, flat table limit */
> +	entry_size = GITS_BASER_ENTRY_SIZE(baser->val);
> +	if (!(baser->val & GITS_BASER_INDIRECT)) {
> +		if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) / entry_size))
> +			return false;
> +		return true;
> +	}
> +
> +	/* Compute Level1 table index & check if that exceeds table range */
> +	idx = dev_id >> ilog2(baser->psz / entry_size);
> +	if (idx >= (PAGE_ORDER_TO_SIZE(baser->order) / GITS_LVL1_ENTRY_SIZE))
> +		return false;
> +
> +	table = baser->base;
> +
> +	/* Allocate memory for Level2 table */
> +	if (!table[idx]) {
> +		page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(baser->psz));
> +		if (!page)
> +			return false;
> +
> +		/* Flush memory to PoC if hardware doesn't support coherency */
> +		if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
> +			__flush_dcache_area(page_address(page), baser->psz);
> +
> +		table[idx] = cpu_to_le64(page_to_phys(page) | GITS_BASER_VALID);
> +
> +		/* Flush memory to PoC if hardware doesn't support coherency */
> +		if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
> +			__flush_dcache_area(table + idx, GITS_LVL1_ENTRY_SIZE);
> +
> +		/* Ensure updated table contents are visible to ITS hardware */
> +		dsb(sy);
> +	}
> +
> +	return true;
> +}
> +
>  static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
>  					    int nvecs)
>  {
> -	struct its_baser *baser;
>  	struct its_device *dev;
>  	unsigned long *lpi_map;
>  	unsigned long flags;
> @@ -1201,14 +1274,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
>  	int nr_ites;
>  	int sz;
>  
> -	baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
> -
> -	/* Don't allow 'dev_id' that exceeds single, flat table limit */
> -	if (baser) {
> -		if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) /
> -			      GITS_BASER_ENTRY_SIZE(baser->val)))
> -			return NULL;
> -	} else if (ilog2(dev_id) >= its->device_ids)
> +	if (!its_alloc_device_table(its, dev_id))
>  		return NULL;
>  
>  	dev = kzalloc(sizeof(*dev), GFP_KERNEL);

-- 
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project



From sricharan at codeaurora.org  Sun May  8 22:18:49 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Mon, 9 May 2016 10:48:49 +0530
Subject: [Patch v3 5/8] firmware: qcom: scm: Convert to streaming DMA APIS
In-Reply-To: <1462402245-18295-6-git-send-email-andy.gross@linaro.org>
References: <1462402245-18295-1-git-send-email-andy.gross@linaro.org>
 <1462402245-18295-6-git-send-email-andy.gross@linaro.org>
Message-ID: <000101d1a9b2$491fd1f0$db5f75d0$@codeaurora.org>

Hi,
> This patch converts the Qualcomm SCM driver to use the streaming DMA
> APIs for communication buffers.
> 
> Signed-off-by: Andy Gross <andy.gross at linaro.org>
> ---

 Reviewed-by: sricharan at codeaurora.org

Regards,
 Sricharan

>  drivers/firmware/qcom_scm-32.c | 152
+++++++++++++------------------------
> ----
>  drivers/firmware/qcom_scm.c    |   6 +-
>  drivers/firmware/qcom_scm.h    |  10 +--
>  3 files changed, 58 insertions(+), 110 deletions(-)
> 
> diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-
> 32.c index 4388d13..3e71aec 100644
> --- a/drivers/firmware/qcom_scm-32.c
> +++ b/drivers/firmware/qcom_scm-32.c
> @@ -23,8 +23,7 @@
>  #include <linux/errno.h>
>  #include <linux/err.h>
>  #include <linux/qcom_scm.h>
> -
> -#include <asm/cacheflush.h>
> +#include <linux/dma-mapping.h>
> 
>  #include "qcom_scm.h"
> 
> @@ -97,44 +96,6 @@ struct qcom_scm_response {  };
> 
>  /**
> - * alloc_qcom_scm_command() - Allocate an SCM command
> - * @cmd_size: size of the command buffer
> - * @resp_size: size of the response buffer
> - *
> - * Allocate an SCM command, including enough room for the command
> - * and response headers as well as the command and response buffers.
> - *
> - * Returns a valid &qcom_scm_command on success or %NULL if the
> allocation fails.
> - */
> -static struct qcom_scm_command *alloc_qcom_scm_command(size_t
> cmd_size, size_t resp_size) -{
> -	struct qcom_scm_command *cmd;
> -	size_t len = sizeof(*cmd) + sizeof(struct qcom_scm_response) +
> cmd_size +
> -		resp_size;
> -	u32 offset;
> -
> -	cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
> -	if (cmd) {
> -		cmd->len = cpu_to_le32(len);
> -		offset = offsetof(struct qcom_scm_command, buf);
> -		cmd->buf_offset = cpu_to_le32(offset);
> -		cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
> -	}
> -	return cmd;
> -}
> -
> -/**
> - * free_qcom_scm_command() - Free an SCM command
> - * @cmd: command to free
> - *
> - * Free an SCM command.
> - */
> -static inline void free_qcom_scm_command(struct qcom_scm_command
> *cmd) -{
> -	kfree(cmd);
> -}
> -
> -/**
>   * qcom_scm_command_to_response() - Get a pointer to a
> qcom_scm_response
>   * @cmd: command
>   *
> @@ -168,7 +129,7 @@ static inline void
> *qcom_scm_get_response_buffer(const struct qcom_scm_response
>  	return (void *)rsp + le32_to_cpu(rsp->buf_offset);  }
> 
> -static u32 smc(u32 cmd_addr)
> +static u32 smc(dma_addr_t cmd_addr)
>  {
>  	int context_id;
>  	register u32 r0 asm("r0") = 1;
> @@ -192,51 +153,15 @@ static u32 smc(u32 cmd_addr)
>  	return r0;
>  }
> 
> -static int __qcom_scm_call(const struct qcom_scm_command *cmd) -{
> -	int ret;
> -	u32 cmd_addr = virt_to_phys(cmd);
> -
> -	/*
> -	 * Flush the command buffer so that the secure world sees
> -	 * the correct data.
> -	 */
> -	secure_flush_area(cmd, cmd->len);
> -
> -	ret = smc(cmd_addr);
> -	if (ret < 0)
> -		ret = qcom_scm_remap_error(ret);
> -
> -	return ret;
> -}
> -
> -static void qcom_scm_inv_range(unsigned long start, unsigned long end) -{
> -	u32 cacheline_size, ctr;
> -
> -	asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
> -	cacheline_size = 4 << ((ctr >> 16) & 0xf);
> -
> -	start = round_down(start, cacheline_size);
> -	end = round_up(end, cacheline_size);
> -	outer_inv_range(start, end);
> -	while (start < end) {
> -		asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
> -		     : "memory");
> -		start += cacheline_size;
> -	}
> -	dsb();
> -	isb();
> -}
> -
>  /**
>   * qcom_scm_call() - Send an SCM command
> - * @svc_id: service identifier
> - * @cmd_id: command identifier
> - * @cmd_buf: command buffer
> - * @cmd_len: length of the command buffer
> - * @resp_buf: response buffer
> - * @resp_len: length of the response buffer
> + * @dev:	struct device
> + * @svc_id:	service identifier
> + * @cmd_id:	command identifier
> + * @cmd_buf:	command buffer
> + * @cmd_len:	length of the command buffer
> + * @resp_buf:	response buffer
> + * @resp_len:	length of the response buffer
>   *
>   * Sends a command to the SCM and waits for the command to finish
> processing.
>   *
> @@ -247,42 +172,60 @@ static void qcom_scm_inv_range(unsigned long
> start, unsigned long end)
>   * and response buffers is taken care of by qcom_scm_call; however,
callers
> are
>   * responsible for any other cached buffers passed over to the secure
world.
>   */
> -static int qcom_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf,
> -			size_t cmd_len, void *resp_buf, size_t resp_len)
> +static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
> +			 const void *cmd_buf, size_t cmd_len, void
> *resp_buf,
> +			 size_t resp_len)
>  {
>  	int ret;
>  	struct qcom_scm_command *cmd;
>  	struct qcom_scm_response *rsp;
> -	unsigned long start, end;
> +	size_t alloc_len = sizeof(*cmd) + sizeof(struct qcom_scm_response) +
> +			   cmd_len + resp_len;
> +	dma_addr_t cmd_phys;
> +	u32 offset;
> 
> -	cmd = alloc_qcom_scm_command(cmd_len, resp_len);
> +	cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
>  	if (!cmd)
>  		return -ENOMEM;
> 
> +	cmd->len = cpu_to_le32(alloc_len);
> +	offset = offsetof(struct qcom_scm_command, buf);
> +	cmd->buf_offset = cpu_to_le32(offset);
> +	cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_len);
> +
>  	cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
>  	if (cmd_buf)
>  		memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf,
> cmd_len);
> 
> +	cmd_phys = dma_map_single(dev, cmd, alloc_len,
> DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, cmd_phys)) {
> +		kfree(cmd);
> +		return -ENOMEM;
> +	}
> +
>  	mutex_lock(&qcom_scm_lock);
> -	ret = __qcom_scm_call(cmd);
> +	ret = smc(cmd_phys);
> +	if (ret < 0)
> +		ret = qcom_scm_remap_error(ret);
>  	mutex_unlock(&qcom_scm_lock);
>  	if (ret)
>  		goto out;
> 
>  	rsp = qcom_scm_command_to_response(cmd);
> -	start = (unsigned long)rsp;
> 
>  	do {
> -		qcom_scm_inv_range(start, start + sizeof(*rsp));
> +		dma_sync_single_for_cpu(dev, cmd_phys + cmd_len +
> offset,
> +					sizeof(*rsp), DMA_FROM_DEVICE);
>  	} while (!rsp->is_complete);
> 
> -	end = (unsigned long)qcom_scm_get_response_buffer(rsp) +
> resp_len;
> -	qcom_scm_inv_range(start, end);
> -
> -	if (resp_buf)
> +	if (resp_buf) {
> +		dma_sync_single_for_cpu(dev, cmd_phys + alloc_len -
> resp_len,
> +					resp_len, DMA_FROM_DEVICE);
>  		memcpy(resp_buf, qcom_scm_get_response_buffer(rsp),
> resp_len);
> +	}
>  out:
> -	free_qcom_scm_command(cmd);
> +	dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE);
> +	kfree(cmd);
>  	return ret;
>  }
> 
> @@ -437,7 +380,8 @@ int __qcom_scm_set_cold_boot_addr(void *entry,
> const cpumask_t *cpus)
>   * Set the Linux entry point for the SCM to transfer control to when
coming
>   * out of a power down. CPU power down may be executed on cpuidle or
> hotplug.
>   */
> -int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t
> *cpus)
> +int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
> +				  const cpumask_t *cpus)
>  {
>  	int ret;
>  	int flags = 0;
> @@ -463,7 +407,7 @@ int __qcom_scm_set_warm_boot_addr(void *entry,
> const cpumask_t *cpus)
> 
>  	cmd.addr = cpu_to_le32(virt_to_phys(entry));
>  	cmd.flags = cpu_to_le32(flags);
> -	ret = qcom_scm_call(QCOM_SCM_SVC_BOOT,
> QCOM_SCM_BOOT_ADDR,
> +	ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT,
> QCOM_SCM_BOOT_ADDR,
>  			    &cmd, sizeof(cmd), NULL, 0);
>  	if (!ret) {
>  		for_each_cpu(cpu, cpus)
> @@ -487,25 +431,27 @@ void __qcom_scm_cpu_power_down(u32 flags)
>  			flags & QCOM_SCM_FLUSH_FLAG_MASK);
>  }
> 
> -int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
> +int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32
> +cmd_id)
>  {
>  	int ret;
>  	__le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id);
>  	__le32 ret_val = 0;
> 
> -	ret = qcom_scm_call(QCOM_SCM_SVC_INFO,
> QCOM_IS_CALL_AVAIL_CMD, &svc_cmd,
> -			sizeof(svc_cmd), &ret_val, sizeof(ret_val));
> +	ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO,
> QCOM_IS_CALL_AVAIL_CMD,
> +			    &svc_cmd, sizeof(svc_cmd), &ret_val,
> +			    sizeof(ret_val));
>  	if (ret)
>  		return ret;
> 
>  	return le32_to_cpu(ret_val);
>  }
> 
> -int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
> u32 *resp)
> +int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req
> *req,
> +			u32 req_cnt, u32 *resp)
>  {
>  	if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
>  		return -ERANGE;
> 
> -	return qcom_scm_call(QCOM_SCM_SVC_HDCP,
> QCOM_SCM_CMD_HDCP,
> +	return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP,
> QCOM_SCM_CMD_HDCP,
>  		req, req_cnt * sizeof(*req), resp, sizeof(*resp));  } diff
--git
> a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index
> 63a2bfa..9166cbb 100644
> --- a/drivers/firmware/qcom_scm.c
> +++ b/drivers/firmware/qcom_scm.c
> @@ -89,7 +89,7 @@ EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
>   */
>  int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)  {
> -	return __qcom_scm_set_warm_boot_addr(entry, cpus);
> +	return __qcom_scm_set_warm_boot_addr(__scm->dev, entry,
> cpus);
>  }
>  EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
> 
> @@ -119,7 +119,7 @@ bool qcom_scm_hdcp_available(void)
>  	if (ret)
>  		return ret;
> 
> -	ret = __qcom_scm_is_call_available(QCOM_SCM_SVC_HDCP,
> +	ret = __qcom_scm_is_call_available(__scm->dev,
> QCOM_SCM_SVC_HDCP,
>  						QCOM_SCM_CMD_HDCP);
> 
>  	qcom_scm_clk_disable();
> @@ -143,7 +143,7 @@ int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req
> *req, u32 req_cnt, u32 *resp)
>  	if (ret)
>  		return ret;
> 
> -	ret = __qcom_scm_hdcp_req(req, req_cnt, resp);
> +	ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp);
>  	qcom_scm_clk_disable();
>  	return ret;
>  }
> diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
> index 7dcc733..afe6676 100644
> --- a/drivers/firmware/qcom_scm.h
> +++ b/drivers/firmware/qcom_scm.h
> @@ -19,7 +19,8 @@
>  #define QCOM_SCM_FLAG_HLOS		0x01
>  #define QCOM_SCM_FLAG_COLDBOOT_MC	0x02
>  #define QCOM_SCM_FLAG_WARMBOOT_MC	0x04
> -extern int __qcom_scm_set_warm_boot_addr(void *entry, const
> cpumask_t *cpus);
> +extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void
> *entry,
> +		const cpumask_t *cpus);
>  extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t
> *cpus);
> 
>  #define QCOM_SCM_CMD_TERMINATE_PC	0x2
> @@ -29,12 +30,13 @@ extern void __qcom_scm_cpu_power_down(u32
> flags);
> 
>  #define QCOM_SCM_SVC_INFO		0x6
>  #define QCOM_IS_CALL_AVAIL_CMD		0x1
> -extern int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id);
> +extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
> +		u32 cmd_id);
> 
>  #define QCOM_SCM_SVC_HDCP		0x11
>  #define QCOM_SCM_CMD_HDCP		0x01
> -extern int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32
> req_cnt,
> -		u32 *resp);
> +extern int __qcom_scm_hdcp_req(struct device *dev,
> +		struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);
> 
>  /* common error codes */
>  #define QCOM_SCM_ENOMEM		-5
> --
> 1.9.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



From thierry.reding at gmail.com  Sun May  8 22:19:46 2016
From: thierry.reding at gmail.com (Thierry Reding)
Date: Mon, 9 May 2016 07:19:46 +0200
Subject: [GIT PULL] clk: tegra: Changes for v4.7-rc1
In-Reply-To: <20160503000248.GB3492@codeaurora.org>
References: <1461945596-24090-1-git-send-email-thierry.reding@gmail.com>
 <20160503000248.GB3492@codeaurora.org>
Message-ID: <20160509051946.GA18753@ulmo.ba.sec>

On Mon, May 02, 2016 at 05:02:48PM -0700, Stephen Boyd wrote:
> On 04/29, Thierry Reding wrote:
> > Hi Michael, Stephen,
> > 
> > The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:
> > 
> >   Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)
> > 
> > are available in the git repository at:
> > 
> >   git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git tags/tegra-for-4.7-clk
> > 
> > for you to fetch changes up to 2690e912644e610854c4c3b23d0a0daec9d030ca:
> > 
> >   clk: tegra: dfll: Reformat CVB frequency table (2016-04-28 12:41:54 +0200)
> > 
> > Note that the first patch is this pull request is a dependency for a
> > larger series that will have to go in through the ARM-SoC tree in order
> > to properly handle the dependencies.
> > 
> 
> Thanks. Pulled.
> 
> Are there any thoughts on making that hw control stuff more
> generic? Perhaps using something like power domains to do that
> instead of having drivers cross-call to the clk driver with
> custom tegra APIs?

I'm not aware of any API that would fit in this case. Power domains
would be misleading because power management isn't involved. One other
alternative that I had thought about is to make it a "virtual" reset,
but that is equally misleading because nothing is really being reset
here.

Yet another option might be to make it a "virtual" clock, though it'd
have to be somewhat hacky because we need two steps (one to enable HW
control and another to start the HW sequencer). That could be
implemented using ->prepare() and ->enable(), respectively, but it's
really not a clock either.

I welcome any ideas on how to turn this into something generic, though.

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

From jamesjj.liao at mediatek.com  Sun May  8 22:37:26 2016
From: jamesjj.liao at mediatek.com (James Liao)
Date: Mon, 9 May 2016 13:37:26 +0800
Subject: [PATCH v7 8/9] clk: mediatek: Add config options for MT2701
 subsystem clocks
In-Reply-To: <20160506230214.GH3492@codeaurora.org>
References: <1460621514-65191-1-git-send-email-jamesjj.liao@mediatek.com>
 <1460621514-65191-9-git-send-email-jamesjj.liao@mediatek.com>
 <20160506230214.GH3492@codeaurora.org>
Message-ID: <1462772246.5344.4.camel@mtksdaap41>

HI Stephen,

On Fri, 2016-05-06 at 16:02 -0700, Stephen Boyd wrote:
> On 04/14, James Liao wrote:
> > MT2701 subsystem clocks are optional and should be enabled only if
> > their subsystem drivers are ready to control these clocks.
> > 
> > Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
> > ---
> 
> Why is this patch split off from the patch that introduces the
> file?

I was looking for comments about how to make subsystem clocks optional.
So I used a separated patch to do it. Is it an acceptable way to use
config options to enable subsystem clock support?


Best regards,

James




From jamesjj.liao at mediatek.com  Sun May  8 22:40:26 2016
From: jamesjj.liao at mediatek.com (James Liao)
Date: Mon, 9 May 2016 13:40:26 +0800
Subject: [PATCH v7 7/9] clk: mediatek: Enable critical clocks for MT2701
In-Reply-To: <20160506231229.GJ3492@codeaurora.org>
References: <1460621514-65191-1-git-send-email-jamesjj.liao@mediatek.com>
 <1460621514-65191-8-git-send-email-jamesjj.liao@mediatek.com>
 <20160506231229.GJ3492@codeaurora.org>
Message-ID: <1462772426.5344.7.camel@mtksdaap41>

Hi Stephen,

On Fri, 2016-05-06 at 16:12 -0700, Stephen Boyd wrote:
> On 04/14, James Liao wrote:
> > Some system clocks should be turned on by default on MT2701.
> > This patch enable these clocks when related clocks have
> > been registered.
> > 
> > Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
> > ---
> 
> critical clks got merged now (sorry I'm slowly getting back to
> looking at patches). Please use that flag.

I don't see critical clock support in v4.6-rc7. Is there a repo/branch
that has critical clocks merged?


Best regards,

James



From k.kozlowski at samsung.com  Sun May  8 23:19:49 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 09 May 2016 08:19:49 +0200
Subject: [PATCH] ARM: dts: exynos: Only Odroid XU3-family boards use DTSI with
 CPU thermal nodes
Message-ID: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>

Include the CPU thermal nodes directly in Odroid XU3-family common DTS
because it is the only user of it. Keeping it in separate DTSI node does
not bring benefits because:
1. It is not re-usable on other non-fan boards (fan is referenced),
2. It won't be re-used on future Odroid XU board because different
   CPU cluster behavior.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi      | 103 ---------------------
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |  94 ++++++++++++++++++-
 2 files changed, 92 insertions(+), 105 deletions(-)
 delete mode 100644 arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi

diff --git a/arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi b/arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi
deleted file mode 100644
index 3e4c4ad96d63..000000000000
--- a/arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Device tree sources for Exynos5422 thermal zone
- *
- * Copyright (c) 2015 Lukasz Majewski <l.majewski at samsung.com>
- *			Anand Moon <linux.amoon at gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <dt-bindings/thermal/thermal.h>
-
-/ {
-	thermal-zones {
-		cpu0_thermal: cpu0-thermal {
-			thermal-sensors = <&tmu_cpu0 0>;
-			polling-delay-passive = <250>;
-			polling-delay = <0>;
-			trips {
-				cpu_alert0: cpu-alert-0 {
-					temperature = <50000>; /* millicelsius */
-					hysteresis = <5000>; /* millicelsius */
-					type = "active";
-				};
-				cpu_alert1: cpu-alert-1 {
-					temperature = <60000>; /* millicelsius */
-					hysteresis = <5000>; /* millicelsius */
-					type = "active";
-				};
-				cpu_alert2: cpu-alert-2 {
-					temperature = <70000>; /* millicelsius */
-					hysteresis = <5000>; /* millicelsius */
-					type = "active";
-				};
-				cpu_crit0: cpu-crit-0 {
-					temperature = <120000>; /* millicelsius */
-					hysteresis = <0>; /* millicelsius */
-					type = "critical";
-				};
-				/*
-				 * Exyunos542x support only 4 trip-points
-				 * so for these polling mode is required.
-				 * Start polling at temperature level of last
-				 * interrupt-driven trip: cpu_alert2
-				 */
-				cpu_alert3: cpu-alert-3 {
-					temperature = <70000>; /* millicelsius */
-					hysteresis = <10000>; /* millicelsius */
-					type = "passive";
-				};
-				cpu_alert4: cpu-alert-4 {
-					temperature = <85000>; /* millicelsius */
-					hysteresis = <10000>; /* millicelsius */
-					type = "passive";
-				};
-
-			};
-			cooling-maps {
-				map0 {
-				     trip = <&cpu_alert0>;
-				     cooling-device = <&fan0 0 1>;
-				};
-				map1 {
-				     trip = <&cpu_alert1>;
-				     cooling-device = <&fan0 1 2>;
-				};
-				map2 {
-				     trip = <&cpu_alert2>;
-				     cooling-device = <&fan0 2 3>;
-				};
-				/*
-				 * When reaching cpu_alert3, reduce CPU
-				 * by 2 steps. On Exynos5422/5800 that would
-				 * be: 1500 MHz and 1100 MHz.
-				 */
-				map3 {
-				     trip = <&cpu_alert3>;
-				     cooling-device = <&cpu0 0 2>;
-				};
-				map4 {
-				     trip = <&cpu_alert3>;
-				     cooling-device = <&cpu4 0 2>;
-				};
-
-				/*
-				 * When reaching cpu_alert4, reduce CPU
-				 * further, down to 600 MHz (11 steps for big,
-				 * 7 steps for LITTLE).
-				 */
-				map5 {
-				     trip = <&cpu_alert4>;
-				     cooling-device = <&cpu0 3 7>;
-				};
-				map6 {
-				     trip = <&cpu_alert4>;
-				     cooling-device = <&cpu4 3 11>;
-				};
-			};
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
index 2a4e10bc8801..ff05041835e5 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
@@ -1,9 +1,11 @@
 /*
  * Hardkernel Odroid XU3 board device tree source
  *
- * Copyright (c) 2014 Collabora Ltd.
  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
+ * Copyright (c) 2014 Collabora Ltd.
+ * Copyright (c) 2015 Lukasz Majewski <l.majewski at samsung.com>
+ *                    Anand Moon <linux.amoon at gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -16,7 +18,6 @@
 #include <dt-bindings/sound/samsung-i2s.h>
 #include "exynos5800.dtsi"
 #include "exynos5422-cpus.dtsi"
-#include "exynos5422-cpu-thermal.dtsi"
 
 / {
 	memory {
@@ -54,6 +55,95 @@
 		#cooling-cells = <2>;
 		cooling-levels = <0 130 170 230>;
 	};
+
+	thermal-zones {
+		cpu0_thermal: cpu0-thermal {
+			thermal-sensors = <&tmu_cpu0 0>;
+			polling-delay-passive = <250>;
+			polling-delay = <0>;
+			trips {
+				cpu_alert0: cpu-alert-0 {
+					temperature = <50000>; /* millicelsius */
+					hysteresis = <5000>; /* millicelsius */
+					type = "active";
+				};
+				cpu_alert1: cpu-alert-1 {
+					temperature = <60000>; /* millicelsius */
+					hysteresis = <5000>; /* millicelsius */
+					type = "active";
+				};
+				cpu_alert2: cpu-alert-2 {
+					temperature = <70000>; /* millicelsius */
+					hysteresis = <5000>; /* millicelsius */
+					type = "active";
+				};
+				cpu_crit0: cpu-crit-0 {
+					temperature = <120000>; /* millicelsius */
+					hysteresis = <0>; /* millicelsius */
+					type = "critical";
+				};
+				/*
+				 * Exynos542x supports only 4 trip-points
+				 * so for these polling mode is required.
+				 * Start polling at temperature level of last
+				 * interrupt-driven trip: cpu_alert2
+				 */
+				cpu_alert3: cpu-alert-3 {
+					temperature = <70000>; /* millicelsius */
+					hysteresis = <10000>; /* millicelsius */
+					type = "passive";
+				};
+				cpu_alert4: cpu-alert-4 {
+					temperature = <85000>; /* millicelsius */
+					hysteresis = <10000>; /* millicelsius */
+					type = "passive";
+				};
+
+			};
+			cooling-maps {
+				map0 {
+				     trip = <&cpu_alert0>;
+				     cooling-device = <&fan0 0 1>;
+				};
+				map1 {
+				     trip = <&cpu_alert1>;
+				     cooling-device = <&fan0 1 2>;
+				};
+				map2 {
+				     trip = <&cpu_alert2>;
+				     cooling-device = <&fan0 2 3>;
+				};
+				/*
+				 * When reaching cpu_alert3, reduce CPU
+				 * by 2 steps. On Exynos5422/5800 that would
+				 * be: 1500 MHz and 1100 MHz.
+				 */
+				map3 {
+				     trip = <&cpu_alert3>;
+				     cooling-device = <&cpu0 0 2>;
+				};
+				map4 {
+				     trip = <&cpu_alert3>;
+				     cooling-device = <&cpu4 0 2>;
+				};
+
+				/*
+				 * When reaching cpu_alert4, reduce CPU
+				 * further, down to 600 MHz (11 steps for big,
+				 * 7 steps for LITTLE).
+				 */
+				map5 {
+				     trip = <&cpu_alert4>;
+				     cooling-device = <&cpu0 3 7>;
+				};
+				map6 {
+				     trip = <&cpu_alert4>;
+				     cooling-device = <&cpu4 3 11>;
+				};
+			};
+		};
+	};
+
 };
 
 &bus_wcore {
-- 
1.9.1



From jamesjj.liao at mediatek.com  Sun May  8 23:38:08 2016
From: jamesjj.liao at mediatek.com (James Liao)
Date: Mon, 9 May 2016 14:38:08 +0800
Subject: [PATCH v7 4/9] clk: mediatek: Add MT2701 clock support
In-Reply-To: <20160506231151.GI3492@codeaurora.org>
References: <1460621514-65191-1-git-send-email-jamesjj.liao@mediatek.com>
 <1460621514-65191-5-git-send-email-jamesjj.liao@mediatek.com>
 <20160506231151.GI3492@codeaurora.org>
Message-ID: <1462775888.5344.20.camel@mtksdaap41>

Hi Stephen,

On Fri, 2016-05-06 at 16:11 -0700, Stephen Boyd wrote:
> On 04/14, James Liao wrote:
> > diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
> > new file mode 100644
> > index 0000000..b4db141
> > --- /dev/null
> > +++ b/drivers/clk/mediatek/clk-mt2701.c
> > +static void __init mtk_infrasys_init(struct device_node *node)
> > +{
> > +	struct clk_onecell_data *clk_data;
> > +	int r;
> > +
> > +	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
> > +
> > +	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
> > +						clk_data);
> > +	mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
> > +						clk_data);
> > +
> > +	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> > +	if (r)
> > +		pr_err("%s(): could not register clock provider: %d\n",
> > +			__func__, r);
> > +}
> > +CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt2701-infracfg", mtk_infrasys_init);
> 
> I'm still lost on the usage of CLK_OF_DECLARE here. What part of
> these clk controllers needs to be registered to make the timer
> work?

GPT (mtk-timer.c) may need infracfg and topckgen clocks. MT8173 for
example:

	timer: timer at 10008000 {
	[...]
		clocks = <&infracfg CLK_INFRA_CLK_13M>,
			 <&topckgen CLK_TOP_RTC_SEL>;
	};

> > +	GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2),
> > +	GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3),
> > +	GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4),
> > +	GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5),
> > +	GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6),
> > +	GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7),
> > +	GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8),
> > +	GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9),
> > +	GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10),
> > +	GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11),
> > +	GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14),
> > +};
> 
> I also don't understand why we don't have different files and
> drivers for all these different clock controllers? They all have
> a similar probe structure, sure, but otherwise these are
> different devices with different clks for them. The whole #ifdef
> thing in the later patch would go away too.

Yes, you are right. So you prefer to support subsystem clocks in
separated files such as clk-mt2701-mm.c, clk-mt2701-bdp.c and so on,
right?

But even if we implement subsystem clock in separated files, we still
need a way to make them optional. So the config options and #ifdef may
not be removed.

> > +	GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12),
> > +	GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13),
> > +	GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14),
> > +	GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15),
> > +	GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_pll340m", 16),
> > +};
> > +
> > +static void __init mtk_bdpsys_init(struct device_node *node)
> 
> Shouldn't be __init because it's driver probe path.

I use builtin_platform_driver_probe(clk_drv, clk_probe) to register this
driver, and it looks can be __init.

> > +{
> > +	struct clk_onecell_data *clk_data;
> > +	int r;
> > +
> > +	clk_data = mtk_alloc_clk_data(CLK_BDP_NR);
> > +
> > +	mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
> > +						clk_data);
> > +
> > +	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> > +	if (r)
> > +		pr_err("%s(): could not register clock provider: %d\n",
> > +			__func__, r);
> > +}
> [...]
> > +
> > +static int __init clk_probe(struct platform_device *pdev)
> > +{
> > +	void (*clk_init)(struct device_node *);
> > +	const struct of_device_id *of_id;
> > +
> > +	of_id = of_match_node(of_clk_match_tbl, pdev->dev.of_node);
> > +	if (!of_id || !of_id->data)
> > +		return -EINVAL;
> > +
> > +	clk_init = of_id->data;
> > +	clk_init(pdev->dev.of_node);
> > +
> > +	return 0;
> > +}
> > +
> > +static struct platform_driver clk_drv = {
> 
> Please add some mtk here, 'clk_drv' is too generic.

OK. I'll add it in next patch.

> > +	.driver = {
> > +		.name = "mtk-clk",
> > +		.owner = THIS_MODULE,
> 
> This is unnecessary.

I'll remove it.

> > +		.of_match_table = of_match_ptr(of_clk_match_tbl),
> 
> Just drop of_match_ptr() because it's not helping. Also
> of_clk_match_tbl is too generic.

I'll change it.

> > +	},
> > +};
> > +
> > +builtin_platform_driver_probe(clk_drv, clk_probe);
> > +}
> > diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
> > index 32d2e45..8796acc 100644
> > --- a/drivers/clk/mediatek/clk-mtk.h
> > +++ b/drivers/clk/mediatek/clk-mtk.h
> > @@ -145,8 +146,35 @@ struct mtk_gate {
> [...]
> > +struct mtk_clk_divider {
> > +	int id;
> > +	const char *name;
> > +	const char *parent_name;
> > +	unsigned long flags;
> > +
> > +	uint32_t div_reg;
> 
> u32 is shorter

I'll change it.

> > +	unsigned char div_shift;
> > +	unsigned char div_width;
> > +	unsigned char clk_divider_flags;
> > +	const struct clk_div_table *clk_div_table;
> > +};




From wenyou.yang at atmel.com  Sun May  8 23:51:17 2016
From: wenyou.yang at atmel.com (Wenyou Yang)
Date: Mon, 9 May 2016 14:51:17 +0800
Subject: [PATCH 0/2] mtd: atmel_nand: remove compatible "atmel,sama5d4-nfc"
Message-ID: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>

It is a datasheet bug, for current SoCs, the RB_EDGE3(i.e. bit 27)
of HSMC_SR register does not exist, the RB_EDGE0 (i.e. bit 24) is
the ready/busy line edge status bit. So the compatible
"atmel,sama5d4-nfc" is unneeded.


Wenyou Yang (2):
  Revert "mtd: atmel_nand: Support variable RB_EDGE interrupts"
  ARM: at91/dt: use "atmel,sama5d3-nfc" compatible for nfc

 .../devicetree/bindings/mtd/atmel-nand.txt         |  2 +-
 arch/arm/boot/dts/sama5d2.dtsi                     |  2 +-
 drivers/mtd/nand/atmel_nand.c                      | 35 +++++-----------------
 drivers/mtd/nand/atmel_nand_nfc.h                  |  3 +-
 4 files changed, 11 insertions(+), 31 deletions(-)

-- 
2.7.4



From wenyou.yang at atmel.com  Sun May  8 23:51:18 2016
From: wenyou.yang at atmel.com (Wenyou Yang)
Date: Mon, 9 May 2016 14:51:18 +0800
Subject: [PATCH 1/2] Revert "mtd: atmel_nand: Support variable RB_EDGE
 interrupts"
In-Reply-To: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
References: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
Message-ID: <1462776680-5284-2-git-send-email-wenyou.yang@atmel.com>

This reverts commit 5ddc7bd43ccc ("mtd: atmel_nand: Support variable
RB_EDGE interrupts")

Because for current SoCs, the RB_EDGE3(i.e. bit 27) of HSMC_SR
register does not exist, the RB_EDGE0 (i.e. bit 24) is the ready/busy
line edge status bit. It is a datasheet bug.

Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
---

 .../devicetree/bindings/mtd/atmel-nand.txt         |  2 +-
 drivers/mtd/nand/atmel_nand.c                      | 35 +++++-----------------
 drivers/mtd/nand/atmel_nand_nfc.h                  |  3 +-
 3 files changed, 10 insertions(+), 30 deletions(-)

diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
index d53aba9..3e7ee99 100644
--- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
@@ -39,7 +39,7 @@ Optional properties:
 
 Nand Flash Controller(NFC) is an optional sub-node
 Required properties:
-- compatible : "atmel,sama5d3-nfc" or "atmel,sama5d4-nfc".
+- compatible : "atmel,sama5d3-nfc".
 - reg : should specify the address and size used for NFC command registers,
         NFC registers and NFC SRAM. NFC SRAM address and size can be absent
         if don't want to use it.
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index efc8ea2..68b9160 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -67,10 +67,6 @@ struct atmel_nand_caps {
 	uint8_t pmecc_max_correction;
 };
 
-struct atmel_nand_nfc_caps {
-	uint32_t rb_mask;
-};
-
 /*
  * oob layout for large page size
  * bad block info is on bytes 0 and 1
@@ -129,7 +125,6 @@ struct atmel_nfc {
 	/* Point to the sram bank which include readed data via NFC */
 	void			*data_in_sram;
 	bool			will_write_sram;
-	const struct atmel_nand_nfc_caps *caps;
 };
 static struct atmel_nfc	nand_nfc;
 
@@ -1715,9 +1710,9 @@ static irqreturn_t hsmc_interrupt(int irq, void *dev_id)
 		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE);
 		ret = IRQ_HANDLED;
 	}
-	if (pending & host->nfc->caps->rb_mask) {
+	if (pending & NFC_SR_RB_EDGE) {
 		complete(&host->nfc->comp_ready);
-		nfc_writel(host->nfc->hsmc_regs, IDR, host->nfc->caps->rb_mask);
+		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE);
 		ret = IRQ_HANDLED;
 	}
 	if (pending & NFC_SR_CMD_DONE) {
@@ -1735,7 +1730,7 @@ static void nfc_prepare_interrupt(struct atmel_nand_host *host, u32 flag)
 	if (flag & NFC_SR_XFR_DONE)
 		init_completion(&host->nfc->comp_xfer_done);
 
-	if (flag & host->nfc->caps->rb_mask)
+	if (flag & NFC_SR_RB_EDGE)
 		init_completion(&host->nfc->comp_ready);
 
 	if (flag & NFC_SR_CMD_DONE)
@@ -1753,7 +1748,7 @@ static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag)
 	if (flag & NFC_SR_XFR_DONE)
 		comp[index++] = &host->nfc->comp_xfer_done;
 
-	if (flag & host->nfc->caps->rb_mask)
+	if (flag & NFC_SR_RB_EDGE)
 		comp[index++] = &host->nfc->comp_ready;
 
 	if (flag & NFC_SR_CMD_DONE)
@@ -1821,7 +1816,7 @@ static int nfc_device_ready(struct mtd_info *mtd)
 		dev_err(host->dev, "Lost the interrupt flags: 0x%08x\n",
 				mask & status);
 
-	return status & host->nfc->caps->rb_mask;
+	return status & NFC_SR_RB_EDGE;
 }
 
 static void nfc_select_chip(struct mtd_info *mtd, int chip)
@@ -1994,8 +1989,8 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
 		}
 		/* fall through */
 	default:
-		nfc_prepare_interrupt(host, host->nfc->caps->rb_mask);
-		nfc_wait_interrupt(host, host->nfc->caps->rb_mask);
+		nfc_prepare_interrupt(host, NFC_SR_RB_EDGE);
+		nfc_wait_interrupt(host, NFC_SR_RB_EDGE);
 	}
 }
 
@@ -2426,11 +2421,6 @@ static int atmel_nand_nfc_probe(struct platform_device *pdev)
 		}
 	}
 
-	nfc->caps = (const struct atmel_nand_nfc_caps *)
-		of_device_get_match_data(&pdev->dev);
-	if (!nfc->caps)
-		return -ENODEV;
-
 	nfc_writel(nfc->hsmc_regs, IDR, 0xffffffff);
 	nfc_readl(nfc->hsmc_regs, SR);	/* clear the NFC_SR */
 
@@ -2459,17 +2449,8 @@ static int atmel_nand_nfc_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct atmel_nand_nfc_caps sama5d3_nfc_caps = {
-	.rb_mask = NFC_SR_RB_EDGE0,
-};
-
-static const struct atmel_nand_nfc_caps sama5d4_nfc_caps = {
-	.rb_mask = NFC_SR_RB_EDGE3,
-};
-
 static const struct of_device_id atmel_nand_nfc_match[] = {
-	{ .compatible = "atmel,sama5d3-nfc", .data = &sama5d3_nfc_caps },
-	{ .compatible = "atmel,sama5d4-nfc", .data = &sama5d4_nfc_caps },
+	{ .compatible = "atmel,sama5d3-nfc" },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match);
diff --git a/drivers/mtd/nand/atmel_nand_nfc.h b/drivers/mtd/nand/atmel_nand_nfc.h
index 0bbc1fa..4d5d262 100644
--- a/drivers/mtd/nand/atmel_nand_nfc.h
+++ b/drivers/mtd/nand/atmel_nand_nfc.h
@@ -42,8 +42,7 @@
 #define		NFC_SR_UNDEF		(1 << 21)
 #define		NFC_SR_AWB		(1 << 22)
 #define		NFC_SR_ASE		(1 << 23)
-#define		NFC_SR_RB_EDGE0		(1 << 24)
-#define		NFC_SR_RB_EDGE3		(1 << 27)
+#define		NFC_SR_RB_EDGE		(1 << 24)
 
 #define ATMEL_HSMC_NFC_IER	0x0c
 #define ATMEL_HSMC_NFC_IDR	0x10
-- 
2.7.4



From wenyou.yang at atmel.com  Sun May  8 23:51:19 2016
From: wenyou.yang at atmel.com (Wenyou Yang)
Date: Mon, 9 May 2016 14:51:19 +0800
Subject: [PATCH 2/2] ARM: at91/dt: use "atmel,sama5d3-nfc" compatible for nfc
In-Reply-To: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
References: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
Message-ID: <1462776680-5284-3-git-send-email-wenyou.yang@atmel.com>

Due to the compatible "atmel,sama5d4-nfc" removal, use
"atmel,sama5d3-nfc" for the sama5d2's nfc node.

Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
---

 arch/arm/boot/dts/sama5d2.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 78996bd..9817090 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -280,7 +280,7 @@
 			status = "disabled";
 
 			nfc at c0000000 {
-				compatible = "atmel,sama5d4-nfc";
+				compatible = "atmel,sama5d3-nfc";
 				#address-cells = <1>;
 				#size-cells = <1>;
 				reg = < /* NFC Command Registers */
-- 
2.7.4



From robin at protonic.nl  Mon May  9 00:06:15 2016
From: robin at protonic.nl (Robin van der Gracht)
Date: Mon, 9 May 2016 09:06:15 +0200
Subject: [GIT PULL] move ARM LCD display driver to auxdisplay
In-Reply-To: <5723755D.9060108@ti.com>
References: <CACRpkdbyO0axd5ergYZcXO302f2fFAPKrSNevkvreP1kRjm-vw@mail.gmail.com>
 <20160425115758.GA4874@lukather>
 <CACRpkdb=s5onVa7qND9nFUtYPw5H-Hdr7Ja5o3=-9+wxghHekQ@mail.gmail.com>
 <20160428092608.GE17159@lukather> <5723755D.9060108@ti.com>
Message-ID: <20160509090615.6272f8ca@erd979>

On Fri, 29 Apr 2016 17:53:17 +0300
Tomi Valkeinen <tomi.valkeinen at ti.com> wrote:

[...] 
> >>
> >> Small problem for me, but Robin is submitting a brand new
> >> auxdisplay driver:
> >> http://marc.info/?l=linux-kernel&m=146001950512999&w=2
> >> http://marc.info/?l=linux-kernel&m=146001988013230&w=2  
> > 
> > My understanding is that Tomi doesn't want any new fbdev drivers, so
> > I'm not sure this is the right place for those patches.  
> 
> Hmm, that one looks like an fbdev driver, not an auxdisplay driver.
> But, not relevant for this patch, of course.

If you guys feel like auxdisplay is not the right subsystem for the
driver, and would like me to move it, please share.

Regards,
Robin van der Gracht


From moinejf at free.fr  Mon May  9 00:24:21 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Mon, 9 May 2016 09:24:21 +0200
Subject: [PATCH 12/16] clk: sunxi-ng: Add N-M-factor clock support
In-Reply-To: <1462737711-10017-13-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-13-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <20160509092421.a36252139fd6b00b2cd32f24@free.fr>

On Sun,  8 May 2016 22:01:47 +0200
Maxime Ripard <maxime.ripard at free-electrons.com> wrote:

> Introduce support for clocks that multiply and divide using linear factors.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile |   1 +
>  drivers/clk/sunxi-ng/ccu_nm.c | 103 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_nm.h |  41 +++++++++++++++++
>  3 files changed, 145 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_nm.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_nm.h
	[snip]
> diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
> new file mode 100644
> index 000000000000..268637db137b
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_nm.c
> @@ -0,0 +1,103 @@
	[snip]
> +static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
> +			      unsigned long *parent_rate)
> +{
> +	struct ccu_nm *nm = hw_to_ccu_nm(hw);
> +	unsigned long n, m;
> +
> +	rational_best_approximation(rate, *parent_rate,
> +				    nm->n.width, nm->m.width, &n, &m);

Should be
			1 << nm->n.width, 1 << nm->m.width, &n, &m);

> +
> +	return *parent_rate * n / m;
> +}
> +
> +static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
> +			   unsigned long parent_rate)
> +{
> +	struct ccu_nm *nm = hw_to_ccu_nm(hw);
> +	unsigned long flags;
> +	unsigned long n, m;
> +	u32 reg;
> +
> +	rational_best_approximation(rate, parent_rate,
> +				    nm->n.width, nm->m.width, &n, &m);

Idem

> +
> +	spin_lock_irqsave(nm->common.lock, flags);
> +
> +	reg = readl(nm->common.base + nm->common.reg);
> +	reg &= ~GENMASK(nm->n.width + nm->n.shift, nm->n.shift);
> +	reg &= ~GENMASK(nm->m.width + nm->m.shift, nm->m.shift);
> +
> +	writel(reg | ((m - 1) << nm->m.shift) | ((n - 1) << nm->n.shift),
> +	       nm->common.base + nm->common.reg);
> +
> +	spin_unlock_irqrestore(nm->common.lock, flags);
> +
> +	ccu_helper_wait_for_lock(&nm->common, nm->lock);
> +
> +	return 0;
> +}
> +
> +const struct clk_ops ccu_nm_ops = {
> +	.disable	= ccu_nm_disable,
> +	.enable		= ccu_nm_enable,
> +	.is_enabled	= ccu_nm_is_enabled,
> +
> +	.recalc_rate	= ccu_nm_recalc_rate,
> +	.round_rate	= ccu_nm_round_rate,
> +	.set_rate	= ccu_nm_set_rate,
> +};
	[snip]

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From viro at ZenIV.linux.org.uk  Mon May  9 00:32:35 2016
From: viro at ZenIV.linux.org.uk (Al Viro)
Date: Mon, 9 May 2016 08:32:35 +0100
Subject: NFSroot hangs with bad unlock balance in Linux next
In-Reply-To: <20160508141629.GF2694@ZenIV.linux.org.uk>
References: <20160505220344.GE5995@atomide.com>
 <20160508141629.GF2694@ZenIV.linux.org.uk>
Message-ID: <20160509073235.GI2694@ZenIV.linux.org.uk>

On Sun, May 08, 2016 at 03:16:29PM +0100, Al Viro wrote:

> Very strange.  We grab that rwsem at the entry into nfs_call_unlink()
> and then either release it there and return or call nfs_do_call_unlink().
> Which arranges for eventual call of nfs_async_unlink_release() (via
> ->rpc_release); nfs_async_unlink_release() releases the rwsem.  Nobody else
> releases it (on the read side, that is).
> 
> The only kinda-sorta possibility I see here is that the inode we are
> unlocking in that nfs_async_unlink_release() is not the one we'd locked
> in nfs_call_unlink() that has lead to it.  That really shouldn't happen,
> though...  Just to verify whether that's what we are hitting, could you
> try to reproduce that thing with the patch below on top of -next and see
> if it triggers any of those WARN_ON?

D'oh...  Lockdep warnings are easy to trigger (and, AFAICS, bogus).
up_read/down_read in fs/nfs/unlink.c should be replaced with
up_read_non_owner/down_read_non_owner, lest the lockdep gets confused.
Hangs are different - I've no idea what's triggering those.  I've seen
something similar on that -next, but not on work.lookups.

The joy of bisecting -next...  <a couple of hours later>
9317bb69824ec8d078b0b786b6971aedb0af3d4f is the first bad commit
commit 9317bb69824ec8d078b0b786b6971aedb0af3d4f
Author: Eric Dumazet <edumazet at google.com>
Date:   Mon Apr 25 10:39:32 2016 -0700

    net: SOCKWQ_ASYNC_NOSPACE optimizations

Reverting changes to sk_set_bit/sk_clear_bit gets rid of the hangs.  Plain
revert gives a conflict, since there had been additional change in
"net: SOCKWQ_ASYNC_WAITDATA optimizations"; removing both fixed the hangs.

Note that hangs appear without any fs/nfs/unlink.c modifications being
there.  When the hang happens it affects NFS traffic; ssh session still
works fine until it steps on a filesystem operation on NFS (i.e. you
can use builtins, access procfs, etc.)


From lee.jones at linaro.org  Mon May  9 00:35:49 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Mon, 9 May 2016 08:35:49 +0100
Subject: [PATCH v6 0/9] mfd: max8997: Add regmap support
In-Reply-To: <1462519289-2356-1-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <20160509073549.GC8324@dell>

On Fri, 06 May 2016, Krzysztof Kozlowski wrote:
> This is a rebase and extension of old Robert Baldyga's work. [0]
> 
> Robert no longer works in Samsung.
> 
> From the original cover letter:
> "This patchset modifies max8997 driver and associated function drivers to use
> register maps instead of operating directly on i2c bus. This change allowed
> to simplify irq handling, and to move some initializations to individual
> function drivers. Hence now when some functions are not enabled, their i2c
> clients, regmaps and irqs are not registered."
> 
> 
> My changes (since Robert's v5)
> ==============================
> 1. Rebase on v4.6-rc6.
> 2. Collect more acks.
> 3. Add few fixes:
>    a. Haptic fix from Marek,
>    b. Extcon and RTC fix from me,
>    c. DTS fixes from Marek.
> 
> DTS changes are independent but rest of them (extcon/input/MFD) rely
> on each other.
> 
> One way of merging would be to pick everything (except DTS) through
> one tree. Or use tags.

I'd be happy to take the set, once you have collected all Acks.

> Best regards,
> Krzysztof
> 
> [0] http://lkml.iu.edu/hypermail//linux/kernel/1411.1/03152.html
> 
> 
> Krzysztof Kozlowski (3):
>   extcon: max8997: Fix handling error code of regmap_irq_get_virq()
>   rtc: max8997: Check for ERRNO of regmap_irq_get_virq()
>   extcon: max8997: Fix inconsistent indenting
> 
> Marek Szyprowski (3):
>   input: max8997-haptic: Fix NULL pointer dereference
>   ARM: dts: exynos: Fix regulator name to avoid forbidden character on
>     exynos4210-trats
>   ARM: dts: exynos: Add interrupt line to MAX8997 PMIC on
>     exynos4210-trats
> 
> Robert Baldyga (3):
>   mfd: max8997: Use regmap to access registers
>   mfd: max8997: handle IRQs using regmap
>   mfd: max8997: Change irq names to upper case
> 
>  arch/arm/boot/dts/exynos4210-trats.dts |   4 +-
>  drivers/extcon/extcon-max8997.c        |  72 ++++---
>  drivers/input/misc/max8997_haptic.c    |  40 ++--
>  drivers/leds/leds-max8997.c            |  13 +-
>  drivers/mfd/Kconfig                    |   3 +-
>  drivers/mfd/Makefile                   |   2 +-
>  drivers/mfd/max8997-irq.c              | 383 ---------------------------------
>  drivers/mfd/max8997.c                  | 245 ++++++++++++++-------
>  drivers/power/max8997_charger.c        |  33 +--
>  drivers/regulator/max8997.c            |  87 ++++----
>  drivers/rtc/rtc-max8997.c              |  60 +++---
>  include/linux/mfd/max8997-private.h    |  82 +++++--
>  12 files changed, 392 insertions(+), 632 deletions(-)
>  delete mode 100644 drivers/mfd/max8997-irq.c
> 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


From moinejf at free.fr  Mon May  9 00:39:58 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Mon, 9 May 2016 09:39:58 +0200
Subject: [PATCH 15/16] clk: sunxi-ng: Add H3 clocks
In-Reply-To: <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <20160509093958.26e9549f8ce78888c0e9586a@free.fr>

On Sun,  8 May 2016 22:01:50 +0200
Maxime Ripard <maxime.ripard at free-electrons.com> wrote:

> Add the list of clocks and resets found in the H3 CCU.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile        |   2 +
>  drivers/clk/sunxi-ng/ccu-sun8i-h3.c  | 757 +++++++++++++++++++++++++++++++++++
>  include/dt-bindings/clock/sun8i-h3.h | 162 ++++++++
>  include/dt-bindings/reset/sun8i-h3.h | 103 +++++
>  4 files changed, 1024 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.c
>  create mode 100644 include/dt-bindings/clock/sun8i-h3.h
>  create mode 100644 include/dt-bindings/reset/sun8i-h3.h
> 
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index c794f57b6fb1..67ff6a92f124 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -13,3 +13,5 @@ obj-y += ccu_nkmp.o
>  obj-y += ccu_nm.o
>  obj-y += ccu_p.o
>  obj-y += ccu_phase.o
> +
> +obj-y += ccu-sun8i-h3.o

+obj-$(CONFIG_MACH_SUN8I) += ccu-sun8i-h3.o

should be better.

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From ulf.hansson at linaro.org  Mon May  9 00:46:40 2016
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Mon, 9 May 2016 09:46:40 +0200
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <20160505224240.GA31429@rob-hp-laptop>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <20160505224240.GA31429@rob-hp-laptop>
Message-ID: <CAPDyKFqpoi03Egfuvd8qJXnn_+FBgPXAb7S4UvkxVs8BA+zwnA@mail.gmail.com>

On 6 May 2016 at 00:42, Rob Herring <robh at kernel.org> wrote:
> On Thu, May 05, 2016 at 02:34:13PM +0200, Krzysztof Kozlowski wrote:
>> Hi,
>>
>> This is a different, second try to fix usb3503+lan on Odroid U3 board
>> if it was initialized by bootloader (e.g. for TFTP boot).
>>
>> First version:
>> http://www.spinics.net/lists/linux-usb/msg140042.html
>>
>>
>> Problem
>> =======
>> When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
>> the usb3503 and LAN smsc95xx do not show up in "lsusb". Hard-reset
>> is required, e.g. by suspend to RAM. The actual TFTP boot does
>> not have to happen. Just "usb start" from U-Boot is sufficient.
>>
>> From the schematics, the regulator is a supply only to LAN, however
>> without toggling it off/on, the usb3503 hub won appear neither.
>>
>>
>> Solution
>> ========
>> This is very similar to the MMC pwrseq behavior so the idea is to:
>> 1. Move MMC pwrseq drivers to generic place,
>
> You can do that, but I'm going to NAK any use of pwrseq bindings outside
> of MMC. I think it is the wrong way to do things. The DT should describe

Huh, I didn't know that was your view of the mmc pwrseq bindings. Why
didn't you NAK them before?

> the devices. If they happen to be "simple" then the core can walk the
> tree and do any setup. For example, look for "reset-gpios" and toggle
> that GPIO. There is no need for a special node.
>
>> 2. Extend the pwrseq-simple with regulator toggling,
>> 3. Add support to USB hub and port core for pwrseq,
>
> We discussed this for USB already[1] and is why we defined how to add
> USB child devices. The idea is not to add pwrseq to that.

I am not familiar with the USB discussion.

Still, let me give you some more background to the mmc pwrseq. The
idea from the mmc pwrseq bindings comes from the power-domain DT
bindings, as I thought these things were a bit related.
In both cases they are not directly a property of the device, but more
describing a HW dependency to allow the device to work.

One could probably use a child node instead of a phandle, but that
wasn't chosen back then. Of course you are the DT expert, but could
you perhaps tell me why a child node is better for cases like this?

>
> Rob
>
> [1] http://www.spinics.net/lists/linux-usb/msg134082.html

Kind regards
Uffe


From eric.auger at linaro.org  Mon May  9 00:48:38 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 9 May 2016 09:48:38 +0200
Subject: [PATCH v9 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part
 2/3: msi changes
In-Reply-To: <9C17BA6B-7304-47CA-A287-77FB41D96AD3@caviumnetworks.com>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
 <9C17BA6B-7304-47CA-A287-77FB41D96AD3@caviumnetworks.com>
Message-ID: <573040D6.9050803@linaro.org>

Hi Chalarmala,
On 05/05/2016 07:44 PM, Chalamarla, Tirumalesh wrote:
> Hi Eric,
> 
> Does this series supports gicv3-its emulation?
> Do we have a tree with all the dependent patches
GICv3 ITS emulation support comes with:
[PATCH v4 00/12] KVM: arm64: GICv3 ITS emulation
http://permalink.gmane.org/gmane.comp.emulators.kvm.arm.devel/5738

My series just allows PCI device MSI transactions to reach the host MSI
frame through the SMMU. Only host GICv2m has been tested at the moment
with a guest exposed with a GICv2m too.

Best Regards

Eric


> 
> 
> 
> 
> 
> Thanks,
> Tirumalesh. 
> On 5/4/16, 8:18 AM, "linux-arm-kernel on behalf of Eric Auger" <linux-arm-kernel-bounces at lists.infradead.org on behalf of eric.auger at linaro.org> wrote:
> 
>> This series implements the MSI address mapping/unmapping in the MSI layer.
>> IOMMU binding happens on pci_enable_msi since this function can sleep and
>> return errors. On msi_domain_set_affinity, msi_domain_(de)activate, which
>> are not allowed to sleep, we simply look for the already existing binding.
>>
>> A new MSI domain info flag value is introduced to report whether the msi
>> domain implements IRQ remapping. GIC v3 ITS is the first MSI controller
>> advertising it. This flag value will be used by VFIO subsystem to
>> determine whether MSI forwarding is safe.
>>
>> More details & context can be found at:
>> http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/
>>
>> Best Regards
>>
>> Eric
>>
>> Applies on top of PART 1/3. Also depends on
>> [PATCH 1/3] iommu: Add MMIO mapping type,
>> http://comments.gmane.org/gmane.linux.kernel.iommu/12869
>>
>> Git: complete series available at
>> https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc6-pcie-passthrough-v9-msi-v9
>>
>> This branch contains all parts in v9.
>>
>> History:
>>
>> v8 -> v9:
>> - use a union in irq_chip_msi_doorbell_info + boolean telling whether the
>>  doorbell is percpu
>> - decouple irq_data parsing from the actual mapping/unmapping in
>>  msi_handle_doorbell_mappings
>> - fix misc style issues
>>
>> v7 -> v8:
>> take into account Marc's comments:
>> - use iommu_msi_msg_pa_to_va with new proto
>> - change in irq_chip_msi_doorbell_info struct definition:
>>  prot and size became shared between all doorbells and phys_addr_t __percpu
>> - cleanups in v2m irqchip
>> - eventually did not touch MSI_FLAG_IRQ_REMAPPING naming
>> - On msi_handle_doorbell_mappings, stop on the first irqchip where doorbells
>>  can be found
>> - fix resource deallocation on mapping failure in msi_domain_alloc_irqs
>>
>> v6 -> v7:
>> - do alloc/map handling on pci_enable_msi and search on msi_(de)domain_activate
>> - add msi_doorbell_info callback in irq-chip to retrieve the characteristics
>>  of doorbells
>>
>> RFC v5 -> patch v6:
>> - split to ease the review process
>> - rebase on default iommu domain code (irq_data_to_msi_mapping_domain
>>  checks IOMMU_DOMAIN_DMA type)
>> - fix unmap sequence on msi_domain_set_affinity (reported by Marc):
>>  unmap the previous doorbell when the new one has been mapped & written to
>>  the device, ie. irq_chip_write_msi_msg.
>> - "msi: msi_compose wrapper removed" following change above
>> - add size parameter to iommu_get_reserved_iova API following Marc's request
>>
>> RFC v4 -> RFC v5:
>> - take into account Thomas' comments on MSI related patches
>>  - split "msi: IOMMU map the doorbell address when needed"
>>  - increase readability and add comments
>>  - fix style issues
>> - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
>> - platform ITS now advertises IOMMU_CAP_INTR_REMAP
>> - fix compilation issue with CONFIG_IOMMU API unset
>> - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING
>>
>> RFC v3 -> v4:
>> - Move doorbell mapping/unmapping in msi.c
>> - fix ref count issue on set_affinity: in case of a change in the address
>>  the previous address is decremented
>> - doorbell map/unmap now is done on msi composition. Should allow the use
>>  case for platform MSI controllers
>> - create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
>>  to reserved IOVA management (looking like dma-iommu glue)
>> - series reordering to ease the review:
>>  - first part is related to IOMMU
>>  - second related to MSI sub-system
>>  - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
>> - expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
>>  [this partially addresses Marc's comments on iommu_get/put_single_reserved
>>   size/alignment problematic - which I did not ignore - but I don't know
>>   how much I can do at the moment]
>>
>> RFC v2 -> RFC v3:
>> - should fix wrong handling of some CONFIG combinations:
>>  CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
>> - fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)
>>
>> PATCH v1 -> RFC v2:
>> - reverted to RFC since it looks more reasonable ;-) the code is split
>>  between VFIO, IOMMU, MSI controller and I am not sure I did the right
>>  choices. Also API need to be further discussed.
>> - iova API usage in arm-smmu.c.
>> - MSI controller natively programs the MSI addr with either the PA or IOVA.
>>  This is not done anymore in vfio-pci driver as suggested by Alex.
>> - check irq remapping capability of the group
>>
>> RFC v1 [2] -> PATCH v1:
>> - use the existing dma map/unmap ioctl interface with a flag to register a
>>  reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
>> - a single reserved IOVA contiguous region now is allowed
>> - use of an RB tree indexed by PA to store allocated reserved slots
>> - use of a vfio_domain iova_domain to manage iova allocation within the
>>  window provided by the userspace
>> - vfio alloc_map/unmap_free take a vfio_group handle
>> - vfio_group handle is cached in vfio_pci_device
>> - add ref counting to bindings
>> - user modality enabled at the end of the series
>>
>>
>> Eric Auger (8):
>>  genirq/msi: Add a new MSI_FLAG_IRQ_REMAPPING flag
>>  irqchip/gic-v3-its: ITS advertises MSI_FLAG_IRQ_REMAPPING
>>  genirq/msi: export msi_get_domain_info
>>  genirq/msi: msi_compose wrapper
>>  genirq/irq: introduce msi_doorbell_info
>>  irqchip/gicv2m: implement msi_doorbell_info callback
>>  genirq/msi: map/unmap the MSI doorbells on msi_domain_alloc/free_irqs
>>  genirq/msi: use the MSI doorbell's IOVA when requested
>>
>> drivers/irqchip/irq-gic-v2m.c                 |  16 +++
>> drivers/irqchip/irq-gic-v3-its-pci-msi.c      |   3 +-
>> drivers/irqchip/irq-gic-v3-its-platform-msi.c |   3 +-
>> include/linux/irq.h                           |  15 ++-
>> include/linux/msi.h                           |   2 +
>> kernel/irq/msi.c                              | 136 +++++++++++++++++++++++---
>> 6 files changed, 161 insertions(+), 14 deletions(-)
>>
>> -- 
>> 1.9.1
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



From eric.auger at linaro.org  Mon May  9 00:55:24 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 9 May 2016 09:55:24 +0200
Subject: [PATCH v9 4/7] vfio: allow reserved msi iova registration
In-Reply-To: <F50F9BB4-1D62-4CAF-BC0E-BE97D222E5A0@caviumnetworks.com>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-5-git-send-email-eric.auger@linaro.org>
 <F50F9BB4-1D62-4CAF-BC0E-BE97D222E5A0@caviumnetworks.com>
Message-ID: <5730426C.4070306@linaro.org>

Hi Chalamarla,
On 05/05/2016 09:22 PM, Chalamarla, Tirumalesh wrote:
> 
> 
> 
> 
> 
> On 5/4/16, 4:54 AM, "linux-arm-kernel on behalf of Eric Auger" <linux-arm-kernel-bounces at lists.infradead.org on behalf of eric.auger at linaro.org> wrote:
> 
>> The user is allowed to register a reserved MSI IOVA range by using the
>> DMA MAP API and setting the new flag: VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA.
>> This region is stored in the vfio_dma rb tree. At that point the iova
>> range is not mapped to any target address yet. The host kernel will use
>> those iova when needed, typically when MSIs are allocated.
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>> Signed-off-by: Bharat Bhushan <Bharat.Bhushan at freescale.com>
>>
>> ---
>> v7 -> v8:
>> - use iommu_msi_set_aperture function. There is no notion of
>>  unregistration anymore since the reserved msi slot remains
>>  until the container gets closed.
>>
>> v6 -> v7:
>> - use iommu_free_reserved_iova_domain
>> - convey prot attributes downto dma-reserved-iommu iova domain creation
>> - reserved bindings teardown now performed on iommu domain destruction
>> - rename VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA into
>>         VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA
>> - change title
>> - pass the protection attribute to dma-reserved-iommu API
>>
>> v3 -> v4:
>> - use iommu_alloc/free_reserved_iova_domain exported by dma-reserved-iommu
>> - protect vfio_register_reserved_iova_range implementation with
>>  CONFIG_IOMMU_DMA_RESERVED
>> - handle unregistration by user-space and on vfio_iommu_type1 release
>>
>> v1 -> v2:
>> - set returned value according to alloc_reserved_iova_domain result
>> - free the iova domains in case any error occurs
>>
>> RFC v1 -> v1:
>> - takes into account Alex comments, based on
>>  [RFC PATCH 1/6] vfio: Add interface for add/del reserved iova region:
>> - use the existing dma map/unmap ioctl interface with a flag to register
>>  a reserved IOVA range. A single reserved iova region is allowed.
>> ---
>> drivers/vfio/vfio_iommu_type1.c | 78 ++++++++++++++++++++++++++++++++++++++++-
>> include/uapi/linux/vfio.h       | 10 +++++-
>> 2 files changed, 86 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
>> index 94a9916..4d3a6f1 100644
>> --- a/drivers/vfio/vfio_iommu_type1.c
>> +++ b/drivers/vfio/vfio_iommu_type1.c
>> @@ -36,6 +36,7 @@
>> #include <linux/uaccess.h>
>> #include <linux/vfio.h>
>> #include <linux/workqueue.h>
>> +#include <linux/msi-iommu.h>
>>
>> #define DRIVER_VERSION  "0.2"
>> #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson at redhat.com>"
>> @@ -445,6 +446,20 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
>> 	vfio_lock_acct(-unlocked);
>> }
>>
>> +static int vfio_set_msi_aperture(struct vfio_iommu *iommu,
>> +				dma_addr_t iova, size_t size)
>> +{
>> +	struct vfio_domain *d;
>> +	int ret = 0;
>> +
>> +	list_for_each_entry(d, &iommu->domain_list, next) {
>> +		ret = iommu_msi_set_aperture(d->domain, iova, iova + size - 1);
>> +		if (ret)
>> +			break;
>> +	}
>> +	return ret;
>> +}
>> +
>> static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
>> {
>> 	vfio_unmap_unpin(iommu, dma);
>> @@ -693,6 +708,63 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
>> 	return ret;
>> }
>>
>> +static int vfio_register_msi_range(struct vfio_iommu *iommu,
>> +				   struct vfio_iommu_type1_dma_map *map)
>> +{
>> +	dma_addr_t iova = map->iova;
>> +	size_t size = map->size;
>> +	int ret = 0;
>> +	struct vfio_dma *dma;
>> +	unsigned long order;
>> +	uint64_t mask;
>> +
>> +	/* Verify that none of our __u64 fields overflow */
>> +	if (map->size != size || map->iova != iova)
>> +		return -EINVAL;
>> +
>> +	order =  __ffs(vfio_pgsize_bitmap(iommu));
>> +	mask = ((uint64_t)1 << order) - 1;
>> +
>> +	WARN_ON(mask & PAGE_MASK);
>> +
>> +	if (!size || (size | iova) & mask)
>> +		return -EINVAL;
>> +
>> +	/* Don't allow IOVA address wrap */
>> +	if (iova + size - 1 < iova)
>> +		return -EINVAL;
>> +
>> +	mutex_lock(&iommu->lock);
>> +
>> +	if (vfio_find_dma(iommu, iova, size, VFIO_IOVA_ANY)) {
>> +		ret =  -EEXIST;
>> +		goto unlock;
>> +	}
>> +
>> +	dma = kzalloc(sizeof(*dma), GFP_KERNEL);
>> +	if (!dma) {
>> +		ret = -ENOMEM;
>> +		goto unlock;
>> +	}
>> +
>> +	dma->iova = iova;
>> +	dma->size = size;
>> +	dma->type = VFIO_IOVA_RESERVED;
>> +
>> +	ret = vfio_set_msi_aperture(iommu, iova, size);
>> +	if (ret)
>> +		goto free_unlock;
>> +
>> +	vfio_link_dma(iommu, dma);
>> +	goto unlock;
>> +
>> +free_unlock:
>> +	kfree(dma);
>> +unlock:
>> +	mutex_unlock(&iommu->lock);
>> +	return ret;
>> +}
>> +
>> static int vfio_bus_type(struct device *dev, void *data)
>> {
>> 	struct bus_type **bus = data;
>> @@ -1062,7 +1134,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>> 	} else if (cmd == VFIO_IOMMU_MAP_DMA) {
>> 		struct vfio_iommu_type1_dma_map map;
>> 		uint32_t mask = VFIO_DMA_MAP_FLAG_READ |
>> -				VFIO_DMA_MAP_FLAG_WRITE;
>> +				VFIO_DMA_MAP_FLAG_WRITE |
>> +				VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA;
>>
>> 		minsz = offsetofend(struct vfio_iommu_type1_dma_map, size);
>>
>> @@ -1072,6 +1145,9 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>> 		if (map.argsz < minsz || map.flags & ~mask)
>> 			return -EINVAL;
>>
>> +		if (map.flags & VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA)
>> +			return vfio_register_msi_range(iommu, &map);
>> +
> 
> How are we getting the PA and any validation needed?
Sorry I am not sure I get your question? The principle is the userspace
registers a spare Guest PA range that can be safely used by the kernel
to map host MSI frames. In QEMU integration we use platform bus unmapped
GPA to make things transparent for the virt machine.

Any validation: we currently make sure the registered GPA was not
already registered as RAM regions. The kernel also checks it is properly
aligned according to the IOMMU page size.

Please let me know if I answered your question.

Best Regards

Eric

>> 		return vfio_dma_do_map(iommu, &map);
>>
>> 	} else if (cmd == VFIO_IOMMU_UNMAP_DMA) {
>> diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
>> index 255a211..4a9dbc2 100644
>> --- a/include/uapi/linux/vfio.h
>> +++ b/include/uapi/linux/vfio.h
>> @@ -498,12 +498,19 @@ struct vfio_iommu_type1_info {
>>  *
>>  * Map process virtual addresses to IO virtual addresses using the
>>  * provided struct vfio_dma_map. Caller sets argsz. READ &/ WRITE required.
>> + *
>> + * In case RESERVED_MSI_IOVA flag is set, the API only aims at registering an
>> + * IOVA region that will be used on some platforms to map the host MSI frames.
>> + * In that specific case, vaddr is ignored. Once registered, an MSI reserved
>> + * IOVA region stays until the container is closed.
>>  */
>> struct vfio_iommu_type1_dma_map {
>> 	__u32	argsz;
>> 	__u32	flags;
>> #define VFIO_DMA_MAP_FLAG_READ (1 << 0)		/* readable from device */
>> #define VFIO_DMA_MAP_FLAG_WRITE (1 << 1)	/* writable from device */
>> +/* reserved iova for MSI vectors*/
>> +#define VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA (1 << 2)
>> 	__u64	vaddr;				/* Process virtual address */
>> 	__u64	iova;				/* IO virtual address */
>> 	__u64	size;				/* Size of mapping (bytes) */
>> @@ -519,7 +526,8 @@ struct vfio_iommu_type1_dma_map {
>>  * Caller sets argsz.  The actual unmapped size is returned in the size
>>  * field.  No guarantee is made to the user that arbitrary unmaps of iova
>>  * or size different from those used in the original mapping call will
>> - * succeed.
>> + * succeed. Once registered, an MSI region cannot be unmapped and stays
>> + * until the container is closed.
>>  */
>> struct vfio_iommu_type1_dma_unmap {
>> 	__u32	argsz;
>> -- 
>> 1.9.1
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



From honghui.zhang at mediatek.com  Mon May  9 01:00:11 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Mon, 9 May 2016 16:00:11 +0800
Subject: [PATCH 0/5] MT2701 iommu support
Message-ID: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

  Mediatek's m4u(Multimedia Memory Management Unit) and SMI(Smart
Multimedia Interface)have two generations HW. They basically sharing the
same hardware block diagram, but have some difference as below:

  Generation one m4u only support one layer, flat pagetable addressing, and
only support 4K size page mapping. While generation two m4u support 2
levels of pagetable which use the ARM short-descriptor translation table
format for address translation.
They have slight different register base and register offset.
They have very different HW ports defines.

  Generaion one SMI have additional "async" clock which transform the smi
clock into emi clock domain, this clock should be prepare and enabled for
cMI generation one HW.
The register which control the iommu need to translation the address or not
for a particular port is located at smi ao base(smi always on register
base) for generation one SMI HW, but located at each larb's register base
for generation two HW.

This patch set add mt2701 iommu support, it's based on 4.6-rc1 and James
Liao's "Add clock support for Mediatek MT2701 v7[1]" and "Mediatek MT2701
SCPSYS power domain support v6[2]" patch.

[1] http://lists.infradead.org/pipermail/linux-mediatek/2016-February/004030.html
[2] http://www.spinics.net/lists/arm-kernel/msg497028.html

Honghui Zhang (5):
  dt-bindings: mediatek: add descriptions for mediatek mt2701 iommu and
    smi
  iommu/mediatek: move the common struct into header file
  memory/mediatek: add support for mt2701
  iommu/mediatek: add support for mtk iommu generation one HW
  ARM: dts: mt2701: add iommu/smi dtsi node for mt2701

 .../devicetree/bindings/iommu/mediatek,iommu.txt   |  13 +-
 .../memory-controllers/mediatek,smi-common.txt     |  21 +-
 .../memory-controllers/mediatek,smi-larb.txt       |   4 +-
 arch/arm/boot/dts/mt2701.dtsi                      |  51 ++
 drivers/iommu/Kconfig                              |  19 +
 drivers/iommu/Makefile                             |   1 +
 drivers/iommu/mtk_iommu.c                          |  62 +-
 drivers/iommu/mtk_iommu.h                          |  94 +++
 drivers/iommu/mtk_iommu_v1.c                       | 767 +++++++++++++++++++++
 drivers/memory/mtk-smi.c                           | 168 ++++-
 include/dt-bindings/memory/mt2701-larb-port.h      |  85 +++
 11 files changed, 1197 insertions(+), 88 deletions(-)
 create mode 100644 drivers/iommu/mtk_iommu.h
 create mode 100644 drivers/iommu/mtk_iommu_v1.c
 create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h

-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Mon May  9 01:00:13 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Mon, 9 May 2016 16:00:13 +0800
Subject: [PATCH 2/5] iommu/mediatek: move the common struct into header file
In-Reply-To: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
References: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1462780816-5288-3-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

Move the struct defines of mtk iommu into a new header files for
common use.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 drivers/iommu/mtk_iommu.c | 62 +-------------------------------
 drivers/iommu/mtk_iommu.h | 90 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+), 61 deletions(-)
 create mode 100644 drivers/iommu/mtk_iommu.h

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index db74553..a6b7846 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -34,7 +34,7 @@
 #include <dt-bindings/memory/mt8173-larb-port.h>
 #include <soc/mediatek/smi.h>
 
-#include "io-pgtable.h"
+#include "mtk_iommu.h"
 
 #define REG_MMU_PT_BASE_ADDR			0x000
 
@@ -93,49 +93,8 @@
 
 #define MTK_PROTECT_PA_ALIGN			128
 
-struct mtk_iommu_suspend_reg {
-	u32				standard_axi_mode;
-	u32				dcm_dis;
-	u32				ctrl_reg;
-	u32				int_control0;
-	u32				int_main_control;
-};
-
-struct mtk_iommu_client_priv {
-	struct list_head		client;
-	unsigned int			mtk_m4u_id;
-	struct device			*m4udev;
-};
-
-struct mtk_iommu_domain {
-	spinlock_t			pgtlock; /* lock for page table */
-
-	struct io_pgtable_cfg		cfg;
-	struct io_pgtable_ops		*iop;
-
-	struct iommu_domain		domain;
-};
-
-struct mtk_iommu_data {
-	void __iomem			*base;
-	int				irq;
-	struct device			*dev;
-	struct clk			*bclk;
-	phys_addr_t			protect_base; /* protect memory base */
-	struct mtk_iommu_suspend_reg	reg;
-	struct mtk_iommu_domain		*m4u_dom;
-	struct iommu_group		*m4u_group;
-	struct mtk_smi_iommu		smi_imu;      /* SMI larb iommu info */
-	bool                            enable_4GB;
-};
-
 static struct iommu_ops mtk_iommu_ops;
 
-static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
-{
-	return container_of(dom, struct mtk_iommu_domain, domain);
-}
-
 static void mtk_iommu_tlb_flush_all(void *cookie)
 {
 	struct mtk_iommu_data *data = cookie;
@@ -552,25 +511,6 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
 	return 0;
 }
 
-static int compare_of(struct device *dev, void *data)
-{
-	return dev->of_node == data;
-}
-
-static int mtk_iommu_bind(struct device *dev)
-{
-	struct mtk_iommu_data *data = dev_get_drvdata(dev);
-
-	return component_bind_all(dev, &data->smi_imu);
-}
-
-static void mtk_iommu_unbind(struct device *dev)
-{
-	struct mtk_iommu_data *data = dev_get_drvdata(dev);
-
-	component_unbind_all(dev, &data->smi_imu);
-}
-
 static const struct component_master_ops mtk_iommu_com_ops = {
 	.bind		= mtk_iommu_bind,
 	.unbind		= mtk_iommu_unbind,
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
new file mode 100644
index 0000000..5656355
--- /dev/null
+++ b/drivers/iommu/mtk_iommu.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Yong Wu <yong.wu at mediatek.com>
+ *       : Honghui Zhang <honghui.zhang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MTK_IOMMU_H_
+#define _MTK_IOMMU_H_
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/iommu.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <soc/mediatek/smi.h>
+
+#include "io-pgtable.h"
+
+struct mtk_iommu_suspend_reg {
+	u32				standard_axi_mode;
+	u32				dcm_dis;
+	u32				ctrl_reg;
+	u32				int_control0;
+	u32				int_main_control;
+};
+
+struct mtk_iommu_client_priv {
+	struct list_head		client;
+	unsigned int			mtk_m4u_id;
+	struct device			*m4udev;
+};
+
+struct mtk_iommu_domain {
+	spinlock_t			pgtlock; /* lock for page table */
+
+	struct io_pgtable_cfg		cfg;
+	struct io_pgtable_ops		*iop;
+
+	struct iommu_domain		domain;
+};
+
+struct mtk_iommu_data {
+	void __iomem			*base;
+	int				irq;
+	struct device			*dev;
+	struct clk			*bclk;
+	phys_addr_t			protect_base; /* protect memory base */
+	struct mtk_iommu_suspend_reg	reg;
+	struct mtk_iommu_domain		*m4u_dom;
+	struct iommu_group		*m4u_group;
+	struct mtk_smi_iommu		smi_imu;      /* SMI larb iommu info */
+	bool                            enable_4GB;
+};
+
+static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
+{
+	return container_of(dom, struct mtk_iommu_domain, domain);
+}
+
+static int compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static int mtk_iommu_bind(struct device *dev)
+{
+	struct mtk_iommu_data *data = dev_get_drvdata(dev);
+
+	return component_bind_all(dev, &data->smi_imu);
+}
+
+static void mtk_iommu_unbind(struct device *dev)
+{
+	struct mtk_iommu_data *data = dev_get_drvdata(dev);
+
+	component_unbind_all(dev, &data->smi_imu);
+}
+
+#endif
-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Mon May  9 01:00:12 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Mon, 9 May 2016 16:00:12 +0800
Subject: [PATCH 1/5] dt-bindings: mediatek: add descriptions for mediatek
 mt2701 iommu and smi
In-Reply-To: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
References: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1462780816-5288-2-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

This patch defines the local arbitor port IDs for mediatek SoC MT2701 and
add descriptions of binding for mediatek generation one iommu and smi.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 .../devicetree/bindings/iommu/mediatek,iommu.txt   | 13 +++-
 .../memory-controllers/mediatek,smi-common.txt     | 21 +++++-
 .../memory-controllers/mediatek,smi-larb.txt       |  4 +-
 include/dt-bindings/memory/mt2701-larb-port.h      | 85 ++++++++++++++++++++++
 4 files changed, 115 insertions(+), 8 deletions(-)
 create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h

diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
index cd1b1cd..9a4a5b5 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
@@ -1,7 +1,9 @@
 * Mediatek IOMMU Architecture Implementation
 
-  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U) which
-uses the ARM Short-Descriptor translation table format for address translation.
+  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U), and
+this M4U have two generations of HW architecture. Generation one use flat
+pagetable, and only support 4K size page mapping. Generation two uses the
+ARM Short-Descriptor translation table format for address translation.
 
   About the M4U Hardware Block Diagram, please check below:
 
@@ -36,7 +38,9 @@ in each larb. Take a example, There are many ports like MC, PP, VLD in the
 video decode local arbiter, all these ports are according to the video HW.
 
 Required properties:
-- compatible : must be "mediatek,mt8173-m4u".
+- compatible : must be one of the following string:
+	"mediatek,mt2701-m4u" for mt2701 which use generation one m4u HW.
+	"mediatek,mt8173-m4u" for mt8173 which use generation two m4u HW.
 - reg : m4u register base and size.
 - interrupts : the interrupt of m4u.
 - clocks : must contain one entry for each clock-names.
@@ -46,7 +50,8 @@ Required properties:
 	according to the local arbiter index, like larb0, larb1, larb2...
 - iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
 	Specifies the mtk_m4u_id as defined in
-	dt-binding/memory/mt8173-larb-port.h.
+	dt-binding/memory/mt2701-larb-port.h for mt2701 and
+	dt-binding/memory/mt8173-larb-port.h for mt8173
 
 Example:
 	iommu: iommu at 10205000 {
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
index 06a83ce..80c0e22 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
@@ -2,16 +2,31 @@ SMI (Smart Multimedia Interface) Common
 
 The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
 
+Mediatek SMI have two generation HW architecture, mt8173 use the secondary
+generation of SMI HW while mt2701 use the first generation HW of SMI.
+
+There's slight differences between the two SMI, for generation 2, the
+register which control the iommu port is at each larb's register base. But
+for generation 1, the register is at smi ao base(smi always on register
+base). Besides that, the smi async clock should be prepare and enabled for
+SMI generation 1 to transform the smi clock into emi clock domain, but no
+needed for SMI generation 2.
+
 Required properties:
-- compatible : must be "mediatek,mt8173-smi-common"
+- compatible : must be one of :
+	"mediatek,mt2701-smi-common"
+	"mediatek,mt8173-smi-common"
 - reg : the register and size of the SMI block.
 - power-domains : a phandle to the power domain of this local arbiter.
 - clocks : Must contain an entry for each entry in clock-names.
-- clock-names : must contain 2 entries, as follows:
+- clock-names : must contain 3 entries for generation 1 smi HW and 2 entries
+  for generation 2 smi HW as follows:
   - "apb" : Advanced Peripheral Bus clock, It's the clock for setting
 	    the register.
   - "smi" : It's the clock for transfer data and command.
-  They may be the same if both source clocks are the same.
+	    They may be the same if both source clocks are the same.
+  - "async" : asynchronous clock, it help transform the smi clock into the emi
+	      clock domain, this clock is only needed by generation 1 smi HW.
 
 Example:
 	smi_common: smi at 14022000 {
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
index 55ff3b7..21277a5 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
@@ -3,7 +3,9 @@ SMI (Smart Multimedia Interface) Local Arbiter
 The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
 
 Required properties:
-- compatible : must be "mediatek,mt8173-smi-larb"
+- compatible : must be one of :
+		"mediatek,mt8173-smi-larb"
+		"mediatek,mt2701-smi-larb"
 - reg : the register and size of this local arbiter.
 - mediatek,smi : a phandle to the smi_common node.
 - power-domains : a phandle to the power domain of this local arbiter.
diff --git a/include/dt-bindings/memory/mt2701-larb-port.h b/include/dt-bindings/memory/mt2701-larb-port.h
new file mode 100644
index 0000000..bd5a418
--- /dev/null
+++ b/include/dt-bindings/memory/mt2701-larb-port.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Honghui Zhang <honghui.zhang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MT2701_LARB_PORT_H_
+#define _MT2701_LARB_PORT_H_
+
+/*
+ * Mediatek m4u generation 1 such as mt2701 have flat m4u port numbers,
+ * the first port's id for larb[N] would be the last port's id of larb[N - 1]
+ * plus one while larb[0]'s first port number is 0. The definition of
+ * MT2701_M4U_ID_LARBx is following HW register REG_SMI_SECUR_CON_BASE spec.
+ * But m4u generation 2 like mt8173 have different port number, it use fixed
+ * offset for each larb, the first port's id for larb[N] would be (N * 32).
+ */
+#define LARB0_PORT_OFFSET		0
+#define LARB1_PORT_OFFSET		11
+#define LARB2_PORT_OFFSET		21
+#define LARB3_PORT_OFFSET		43
+
+#define MT2701_M4U_ID_LARB0(port)	((port) + LARB0_PORT_OFFSET)
+#define MT2701_M4U_ID_LARB1(port)	((port) + LARB1_PORT_OFFSET)
+#define MT2701_M4U_ID_LARB2(port)	((port) + LARB2_PORT_OFFSET)
+
+/* Port define for larb0 */
+#define MT2701_M4U_PORT_DISP_OVL_0		MT2701_M4U_ID_LARB0(0)
+#define MT2701_M4U_PORT_DISP_RDMA1		MT2701_M4U_ID_LARB0(1)
+#define MT2701_M4U_PORT_DISP_RDMA		MT2701_M4U_ID_LARB0(2)
+#define MT2701_M4U_PORT_DISP_WDMA		MT2701_M4U_ID_LARB0(3)
+#define MT2701_M4U_PORT_MM_CMDQ			MT2701_M4U_ID_LARB0(4)
+#define MT2701_M4U_PORT_MDP_RDMA		MT2701_M4U_ID_LARB0(5)
+#define MT2701_M4U_PORT_MDP_WDMA		MT2701_M4U_ID_LARB0(6)
+#define MT2701_M4U_PORT_MDP_ROTO		MT2701_M4U_ID_LARB0(7)
+#define MT2701_M4U_PORT_MDP_ROTCO		MT2701_M4U_ID_LARB0(8)
+#define MT2701_M4U_PORT_MDP_ROTVO		MT2701_M4U_ID_LARB0(9)
+#define MT2701_M4U_PORT_MDP_RDMA1		MT2701_M4U_ID_LARB0(10)
+
+/* Port define for larb1 */
+#define MT2701_M4U_PORT_VDEC_MC_EXT		MT2701_M4U_ID_LARB1(0)
+#define MT2701_M4U_PORT_VDEC_PP_EXT		MT2701_M4U_ID_LARB1(1)
+#define MT2701_M4U_PORT_VDEC_PPWRAP_EXT		MT2701_M4U_ID_LARB1(2)
+#define MT2701_M4U_PORT_VDEC_AVC_MV_EXT		MT2701_M4U_ID_LARB1(3)
+#define MT2701_M4U_PORT_VDEC_PRED_RD_EXT	MT2701_M4U_ID_LARB1(4)
+#define MT2701_M4U_PORT_VDEC_PRED_WR_EXT	MT2701_M4U_ID_LARB1(5)
+#define MT2701_M4U_PORT_VDEC_VLD_EXT		MT2701_M4U_ID_LARB1(6)
+#define MT2701_M4U_PORT_VDEC_VLD2_EXT		MT2701_M4U_ID_LARB1(7)
+#define MT2701_M4U_PORT_VDEC_TILE_EXT		MT2701_M4U_ID_LARB1(8)
+#define MT2701_M4U_PORT_VDEC_IMG_RESZ_EXT	MT2701_M4U_ID_LARB1(9)
+
+/* Port define for larb2 */
+#define MT2701_M4U_PORT_VENC_RCPU		MT2701_M4U_ID_LARB2(0)
+#define MT2701_M4U_PORT_VENC_REC_FRM		MT2701_M4U_ID_LARB2(1)
+#define MT2701_M4U_PORT_VENC_BSDMA		MT2701_M4U_ID_LARB2(2)
+#define MT2701_M4U_PORT_JPGENC_RDMA		MT2701_M4U_ID_LARB2(3)
+#define MT2701_M4U_PORT_VENC_LT_RCPU		MT2701_M4U_ID_LARB2(4)
+#define MT2701_M4U_PORT_VENC_LT_REC_FRM		MT2701_M4U_ID_LARB2(5)
+#define MT2701_M4U_PORT_VENC_LT_BSDMA		MT2701_M4U_ID_LARB2(6)
+#define MT2701_M4U_PORT_JPGDEC_BSDMA		MT2701_M4U_ID_LARB2(7)
+#define MT2701_M4U_PORT_VENC_SV_COMV		MT2701_M4U_ID_LARB2(8)
+#define MT2701_M4U_PORT_VENC_RD_COMV		MT2701_M4U_ID_LARB2(9)
+#define MT2701_M4U_PORT_JPGENC_BSDMA		MT2701_M4U_ID_LARB2(10)
+#define MT2701_M4U_PORT_VENC_CUR_LUMA		MT2701_M4U_ID_LARB2(11)
+#define MT2701_M4U_PORT_VENC_CUR_CHROMA		MT2701_M4U_ID_LARB2(12)
+#define MT2701_M4U_PORT_VENC_REF_LUMA		MT2701_M4U_ID_LARB2(13)
+#define MT2701_M4U_PORT_VENC_REF_CHROMA		MT2701_M4U_ID_LARB2(14)
+#define MT2701_M4U_PORT_IMG_RESZ		MT2701_M4U_ID_LARB2(15)
+#define MT2701_M4U_PORT_VENC_LT_SV_COMV		MT2701_M4U_ID_LARB2(16)
+#define MT2701_M4U_PORT_VENC_LT_RD_COMV		MT2701_M4U_ID_LARB2(17)
+#define MT2701_M4U_PORT_VENC_LT_CUR_LUMA	MT2701_M4U_ID_LARB2(18)
+#define MT2701_M4U_PORT_VENC_LT_CUR_CHROMA	MT2701_M4U_ID_LARB2(19)
+#define MT2701_M4U_PORT_VENC_LT_REF_LUMA	MT2701_M4U_ID_LARB2(20)
+#define MT2701_M4U_PORT_VENC_LT_REF_CHROMA	MT2701_M4U_ID_LARB2(21)
+#define MT2701_M4U_PORT_JPGDEC_WDMA		MT2701_M4U_ID_LARB2(22)
+
+#endif
-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Mon May  9 01:00:14 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Mon, 9 May 2016 16:00:14 +0800
Subject: [PATCH 3/5] memory/mediatek: add support for mt2701
In-Reply-To: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
References: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1462780816-5288-4-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

Mediatek SMI have two generation HW architecture, mt8173 use the
secondary generation of SMI HW while mt2701 use the first generation
HW of SMI.

There's slight differences between the two generation, for generation 2,
the register which control the iommu port access PA or IOVA is at each
larb's register base. But for generation 1, the register is at smi ao
base(smi always on register base).
Besides that, the smi async clock should be prepare and enabled for SMI
generation 1 HW to transform the smi clock into emi clock domain, but no
needed for SMI generation 2.

This patch add SMI driver for mt2701 which use generation 1 SMI HW.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 drivers/memory/mtk-smi.c | 168 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 149 insertions(+), 19 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 089091f..0a47382 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -21,19 +21,50 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <soc/mediatek/smi.h>
+#include <dt-bindings/memory/mt2701-larb-port.h>
 
 #define SMI_LARB_MMU_EN		0xf00
+#define REG_SMI_SECUR_CON_BASE		0x5c0
+
+/* every register control 8 port, register offset 0x4 */
+#define REG_SMI_SECUR_CON_OFFSET(id)	(((id) >> 3) << 2)
+#define REG_SMI_SECUR_CON_ADDR(id)	\
+	(REG_SMI_SECUR_CON_BASE + REG_SMI_SECUR_CON_OFFSET(id))
+
+/*
+ * every port have 4 bit to control, bit[port + 3] control virtual or physical,
+ * bit[port + 2 : port + 1] control the domain, bit[port] control the security
+ * or non-security.
+ */
+#define SMI_SECUR_CON_VAL_MSK(id)	(~(0xf << (((id) & 0x7) << 2)))
+#define SMI_SECUR_CON_VAL_VIRT(id)	BIT((((id) & 0x7) << 2) + 3)
+/* mt2701 domain should be set to 3 */
+#define SMI_SECUR_CON_VAL_DOMAIN(id)	(0x3 << ((((id) & 0x7) << 2) + 1))
+
+struct mtk_smi_larb_gen {
+	int port_in_larb[MTK_LARB_NR_MAX + 1];
+	void (*config_port)(struct device *);
+};
 
 struct mtk_smi {
-	struct device	*dev;
-	struct clk	*clk_apb, *clk_smi;
+	struct device			*dev;
+	struct clk			*clk_apb, *clk_smi;
+	struct clk			*clk_async; /*only needed by mt2701*/
+	void __iomem			*smi_ao_base;
 };
 
 struct mtk_smi_larb { /* larb: local arbiter */
-	struct mtk_smi  smi;
-	void __iomem	*base;
-	struct device	*smi_common_dev;
-	u32		*mmu;
+	struct mtk_smi			smi;
+	void __iomem			*base;
+	struct device			*smi_common_dev;
+	const struct mtk_smi_larb_gen	*larb_gen;
+	int				larbid;
+	u32				*mmu;
+};
+
+enum mtk_smi_gen {
+	MTK_SMI_GEN1,
+	MTK_SMI_GEN2
 };
 
 static int mtk_smi_enable(const struct mtk_smi *smi)
@@ -71,6 +102,7 @@ static void mtk_smi_disable(const struct mtk_smi *smi)
 int mtk_smi_larb_get(struct device *larbdev)
 {
 	struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
+	const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
 	struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
 	int ret;
 
@@ -87,8 +119,7 @@ int mtk_smi_larb_get(struct device *larbdev)
 	}
 
 	/* Configure the iommu info for this larb */
-	writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
-
+	larb_gen->config_port(larbdev);
 	return 0;
 }
 
@@ -124,6 +155,45 @@ mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
 	return -ENODEV;
 }
 
+static void mtk_smi_larb_config_port(struct device *dev)
+{
+	struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+
+	writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
+}
+
+
+static void mtk_smi_larb_config_port_gen1(struct device *dev)
+{
+	struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+	const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
+	struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
+	int i, m4u_port_id, larb_port_num;
+	u32 sec_con_val, reg_val;
+
+	m4u_port_id = larb_gen->port_in_larb[larb->larbid];
+	larb_port_num = larb_gen->port_in_larb[larb->larbid + 1]
+			- larb_gen->port_in_larb[larb->larbid];
+
+	for (i = 0; i < larb_port_num; i++, m4u_port_id++) {
+		if (*larb->mmu & BIT(i)) {
+			/* bit[port + 3] controls the virtual or physical */
+			sec_con_val = SMI_SECUR_CON_VAL_VIRT(m4u_port_id);
+		} else {
+			/* do not need to enable m4u for this port */
+			continue;
+		}
+		reg_val = readl(common->smi_ao_base
+			+ REG_SMI_SECUR_CON_ADDR(m4u_port_id));
+		reg_val &= SMI_SECUR_CON_VAL_MSK(m4u_port_id);
+		reg_val |= sec_con_val;
+		reg_val |= SMI_SECUR_CON_VAL_DOMAIN(m4u_port_id);
+		writel(reg_val,
+			common->smi_ao_base
+			+ REG_SMI_SECUR_CON_ADDR(m4u_port_id));
+	}
+}
+
 static void
 mtk_smi_larb_unbind(struct device *dev, struct device *master, void *data)
 {
@@ -135,6 +205,31 @@ static const struct component_ops mtk_smi_larb_component_ops = {
 	.unbind = mtk_smi_larb_unbind,
 };
 
+static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = {
+	/* mt8173 do not need the port in larb */
+	.config_port = mtk_smi_larb_config_port,
+};
+
+static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
+	.port_in_larb = {
+		LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
+		LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
+	},
+	.config_port = mtk_smi_larb_config_port_gen1,
+};
+
+static const struct of_device_id mtk_smi_larb_of_ids[] = {
+	{
+		.compatible = "mediatek,mt8173-smi-larb",
+		.data = &mtk_smi_larb_mt8173
+	},
+	{
+		.compatible = "mediatek,mt2701-smi-larb",
+		.data = &mtk_smi_larb_mt2701
+	},
+	{}
+};
+
 static int mtk_smi_larb_probe(struct platform_device *pdev)
 {
 	struct mtk_smi_larb *larb;
@@ -142,14 +237,20 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct device_node *smi_node;
 	struct platform_device *smi_pdev;
+	const struct of_device_id *of_id;
 
 	if (!dev->pm_domain)
 		return -EPROBE_DEFER;
 
+	of_id = of_match_node(mtk_smi_larb_of_ids, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
 	larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
 	if (!larb)
 		return -ENOMEM;
 
+	larb->larb_gen = of_id->data;
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	larb->base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(larb->base))
@@ -189,24 +290,34 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id mtk_smi_larb_of_ids[] = {
-	{ .compatible = "mediatek,mt8173-smi-larb",},
-	{}
-};
-
 static struct platform_driver mtk_smi_larb_driver = {
 	.probe	= mtk_smi_larb_probe,
-	.remove = mtk_smi_larb_remove,
+	.remove	= mtk_smi_larb_remove,
 	.driver	= {
 		.name = "mtk-smi-larb",
 		.of_match_table = mtk_smi_larb_of_ids,
 	}
 };
 
+static const struct of_device_id mtk_smi_common_of_ids[] = {
+	{
+		.compatible = "mediatek,mt8173-smi-common",
+		.data = (void *)MTK_SMI_GEN2
+	},
+	{
+		.compatible = "mediatek,mt2701-smi-common",
+		.data = (void *)MTK_SMI_GEN1
+	},
+	{}
+};
+
 static int mtk_smi_common_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct mtk_smi *common;
+	struct resource *res;
+	const struct of_device_id *of_id;
+	enum mtk_smi_gen smi_gen;
 
 	if (!dev->pm_domain)
 		return -EPROBE_DEFER;
@@ -224,6 +335,29 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
 	if (IS_ERR(common->clk_smi))
 		return PTR_ERR(common->clk_smi);
 
+	of_id = of_match_node(mtk_smi_common_of_ids, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
+	/*
+	 * for mtk smi gen 1, we need to get the ao(always on) base to config
+	 * m4u port, and we need to enable the aync clock for transform the smi
+	 * clock into emi clock domain, but for mtk smi gen2, there's no smi ao
+	 * base.
+	 */
+	smi_gen = (enum mtk_smi_gen)of_id->data;
+	if (smi_gen == MTK_SMI_GEN1) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		common->smi_ao_base = devm_ioremap_resource(dev, res);
+		if (IS_ERR(common->smi_ao_base))
+			return PTR_ERR(common->smi_ao_base);
+
+		common->clk_async = devm_clk_get(dev, "async");
+		if (IS_ERR(common->clk_async))
+			return PTR_ERR(common->clk_async);
+
+		clk_prepare_enable(common->clk_async);
+	}
 	pm_runtime_enable(dev);
 	platform_set_drvdata(pdev, common);
 	return 0;
@@ -235,11 +369,6 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id mtk_smi_common_of_ids[] = {
-	{ .compatible = "mediatek,mt8173-smi-common", },
-	{}
-};
-
 static struct platform_driver mtk_smi_common_driver = {
 	.probe	= mtk_smi_common_probe,
 	.remove = mtk_smi_common_remove,
@@ -270,4 +399,5 @@ err_unreg_smi:
 	platform_driver_unregister(&mtk_smi_common_driver);
 	return ret;
 }
+
 subsys_initcall(mtk_smi_init);
-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Mon May  9 01:00:15 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Mon, 9 May 2016 16:00:15 +0800
Subject: [PATCH 4/5] iommu/mediatek: add support for mtk iommu generation one
 HW
In-Reply-To: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
References: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1462780816-5288-5-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

Mediatek SoC's M4U have two generations of HW architcture. Generation one
use flat, one layer pagetable, and was shipped with ARM architecture, it
only support 4K size page mapping. MT2701 SoC use this generation one
m4u HW. Generation two uses the ARM short-descriptor translation table
format for address translation, and was shipped with ARM64 architecture,
MT8173 use this generation two m4u HW. All the two generation iommu HW
only have one iommu domain, and all it's iommu clients share the same
iova address.

These two generation m4u HW have slit different register groups and
register offset, but most register names are the same. This patch add iommu
support for mediatek SoC mt2701.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 drivers/iommu/Kconfig        |  19 ++
 drivers/iommu/Makefile       |   1 +
 drivers/iommu/mtk_iommu.h    |   4 +
 drivers/iommu/mtk_iommu_v1.c | 767 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 791 insertions(+)
 create mode 100644 drivers/iommu/mtk_iommu_v1.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index dd1dc39..2e17d70 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -354,4 +354,23 @@ config MTK_IOMMU
 
 	  If unsure, say N here.
 
+config MTK_IOMMU_V1
+	bool "MTK IOMMU Version 1 (M4U gen1) Support"
+	depends on ARM || ARM64
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	select ARM_DMA_USE_IOMMU
+	select IOMMU_API
+	select IOMMU_DMA
+	select MEMORY
+	select MTK_SMI
+	select COMMON_CLK_MT2701_MMSYS
+	select COMMON_CLK_MT2701_IMGSYS
+	select COMMON_CLK_MT2701_VDECSYS
+	help
+	  Support for the M4U on certain Mediatek SoCs. M4U generation 1 HW is
+	  Multimedia Memory Managememt Unit. This option enables remapping of
+	  DMA memory accesses for the multimedia subsystem.
+
+	  if unsure, say N here.
+
 endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index c6edb31..778baf5 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
 obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
 obj-$(CONFIG_MTK_IOMMU) += mtk_iommu.o
+obj-$(CONFIG_MTK_IOMMU_V1) += mtk_iommu_v1.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
 obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 5656355..c894784 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -48,6 +48,10 @@ struct mtk_iommu_domain {
 	struct io_pgtable_ops		*iop;
 
 	struct iommu_domain		domain;
+	size_t				pgt_size;
+	void				*pgt_va;
+	dma_addr_t			pgt_pa;
+	void				*cookie;
 };
 
 struct mtk_iommu_data {
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
new file mode 100644
index 0000000..1fece92
--- /dev/null
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Yong Wu <yong.wu at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/bootmem.h>
+#include <linux/bug.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/dma-iommu.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iommu.h>
+#include <linux/iopoll.h>
+#include <linux/kmemleak.h>
+#include <linux/list.h>
+#include <linux/of_address.h>
+#include <linux/of_iommu.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/barrier.h>
+#include <asm/dma-iommu.h>
+#include <linux/module.h>
+#include <dt-bindings/memory/mt2701-larb-port.h>
+#include <soc/mediatek/smi.h>
+#include "mtk_iommu.h"
+
+#define REG_MMU_PT_BASE_ADDR			0x000
+
+#define F_ALL_INVLD				0x2
+#define F_MMU_INV_RANGE				0x1
+#define F_INVLD_EN0				BIT(0)
+#define F_INVLD_EN1				BIT(1)
+
+#define F_MMU_FAULT_VA_MSK			0xfffff000
+#define MTK_PROTECT_PA_ALIGN			128
+
+#define REG_MMU_CTRL_REG			0x210
+#define F_MMU_CTRL_COHERENT_EN			BIT(8)
+#define REG_MMU_IVRP_PADDR			0x214
+#define REG_MMU_INT_CONTROL			0x220
+#define F_INT_TRANSLATION_FAULT			BIT(0)
+#define F_INT_MAIN_MULTI_HIT_FAULT		BIT(1)
+#define F_INT_INVALID_PA_FAULT			BIT(2)
+#define F_INT_ENTRY_REPLACEMENT_FAULT		BIT(3)
+#define F_INT_TABLE_WALK_FAULT			BIT(4)
+#define F_INT_TLB_MISS_FAULT			BIT(5)
+#define F_INT_PFH_DMA_FIFO_OVERFLOW		BIT(6)
+#define F_INT_MISS_DMA_FIFO_OVERFLOW		BIT(7)
+
+#define F_MMU_TF_PROTECT_SEL(prot)		(((prot) & 0x3) << 5)
+#define F_INT_CLR_BIT				BIT(12)
+
+#define REG_MMU_FAULT_ST			0x224
+#define REG_MMU_FAULT_VA			0x228
+#define REG_MMU_INVLD_PA			0x22C
+#define REG_MMU_INT_ID				0x388
+#define REG_MMU_INVALIDATE			0x5c0
+#define REG_MMU_INVLD_START_A			0x5c4
+#define REG_MMU_INVLD_END_A			0x5c8
+
+#define REG_MMU_INV_SEL				0x5d8
+#define REG_MMU_STANDARD_AXI_MODE		0x5e8
+
+#define REG_MMU_DCM				0x5f0
+#define F_MMU_DCM_ON				BIT(1)
+#define REG_MMU_CPE_DONE			0x60c
+#define F_DESC_VALID				0x2
+#define F_DESC_NONSEC				BIT(3)
+#define MT2701_M4U_TF_LARB(TF)			(6 - (((TF) >> 13) & 0x7))
+#define MT2701_M4U_TF_PORT(TF)			(((TF) >> 8) & 0xF)
+/* MTK generation one iommu HW only support 4K size mapping */
+#define MTK_IOMMU_PAGE_SHIFT			12
+#define MTK_IOMMU_PAGE_SIZE			(1UL << MTK_IOMMU_PAGE_SHIFT)
+
+static const int mt2701_m4u_in_larb[] = {
+	LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
+	LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
+};
+
+static inline int mt2701_m4u_to_larb(int id)
+{
+	int i;
+
+	for (i = ARRAY_SIZE(mt2701_m4u_in_larb); i >= 0; i--)
+		if ((id) >= mt2701_m4u_in_larb[i])
+			return i;
+
+	return 0;
+}
+
+static inline int mt2701_m4u_to_port(int id)
+{
+	int larb = mt2701_m4u_to_larb(id);
+
+	return id - mt2701_m4u_in_larb[larb];
+}
+
+static void mtk_iommu_tlb_flush_all(void *cookie)
+{
+	struct mtk_iommu_data *data = cookie;
+
+	writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
+			data->base + REG_MMU_INV_SEL);
+	writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
+	wmb(); /* Make sure the tlb flush all done */
+}
+
+static void mtk_iommu_tlb_flush_range(void *cookie,
+				unsigned long iova, size_t size)
+{
+	struct mtk_iommu_data *data = cookie;
+	int ret;
+	u32 tmp;
+
+	writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
+		data->base + REG_MMU_INV_SEL);
+	writel_relaxed(iova & F_MMU_FAULT_VA_MSK,
+		data->base + REG_MMU_INVLD_START_A);
+	writel_relaxed((iova + size - 1) & F_MMU_FAULT_VA_MSK,
+		data->base + REG_MMU_INVLD_END_A);
+	writel_relaxed(F_MMU_INV_RANGE, data->base + REG_MMU_INVALIDATE);
+
+	ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE,
+				tmp, tmp != 0, 10, 100000);
+	if (ret) {
+		dev_warn(data->dev,
+			 "Partial TLB flush timed out, falling back to full flush\n");
+		mtk_iommu_tlb_flush_all(cookie);
+	}
+	/* Clear the CPE status */
+	writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
+}
+
+static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
+{
+	struct mtk_iommu_data *data = dev_id;
+	struct mtk_iommu_domain *dom = data->m4u_dom;
+	u32 int_state, regval, fault_iova, fault_pa;
+	unsigned int fault_larb, fault_port;
+
+	/* Read error information from registers */
+	int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST);
+	fault_iova = readl_relaxed(data->base + REG_MMU_FAULT_VA);
+
+	fault_iova &= F_MMU_FAULT_VA_MSK;
+	fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
+	regval = readl_relaxed(data->base + REG_MMU_INT_ID);
+	fault_larb = MT2701_M4U_TF_LARB(regval);
+	fault_port = MT2701_M4U_TF_PORT(regval);
+
+	/*
+	 * MTK v1 iommu HW could not determin whether the fault is read or
+	 * write fault, report as read fault.
+	 */
+	if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
+			IOMMU_FAULT_READ))
+		dev_err_ratelimited(data->dev,
+			"fault type=0x%x iova=0x%x pa=0x%x larb=%d port=%d\n",
+			int_state, fault_iova, fault_pa,
+			fault_larb, fault_port);
+
+	/* Interrupt clear */
+	regval = readl_relaxed(data->base + REG_MMU_INT_CONTROL);
+	regval |= F_INT_CLR_BIT;
+	writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL);
+
+	mtk_iommu_tlb_flush_all(data);
+
+	return IRQ_HANDLED;
+}
+
+static void mtk_iommu_config(struct mtk_iommu_data *data,
+			     struct device *dev, bool enable)
+{
+	struct mtk_iommu_client_priv *head, *cur, *next;
+	struct mtk_smi_larb_iommu    *larb_mmu;
+	unsigned int                 larbid, portid;
+
+	head = dev->archdata.iommu;
+	list_for_each_entry_safe(cur, next, &head->client, client) {
+		larbid = mt2701_m4u_to_larb(cur->mtk_m4u_id);
+		portid = mt2701_m4u_to_port(cur->mtk_m4u_id);
+		larb_mmu = &data->smi_imu.larb_imu[larbid];
+
+		dev_dbg(dev, "%s iommu port: %d\n",
+			enable ? "enable" : "disable", portid);
+
+		if (enable)
+			larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
+		else
+			larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
+	}
+}
+
+static void *mtk_iommu_alloc_pgt(struct device *dev, size_t size, gfp_t gfp)
+{
+	dma_addr_t dma;
+	void *pages = alloc_pages_exact(size, gfp | __GFP_ZERO);
+
+	if (!pages)
+		return NULL;
+
+	dma = dma_map_single(dev, pages, size, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, dma))
+		goto out_free;
+	/*
+	 * We depend on the IOMMU being able to work with any physical
+	 * address directly, so if the DMA layer suggests otherwise by
+	 * translating or truncating them, that bodes very badly...
+	 */
+	if (dma != virt_to_phys(pages))
+		goto out_unmap;
+
+	kmemleak_ignore(pages);
+	return pages;
+
+out_unmap:
+	dev_err(dev, "Cannot accommodate DMA translation for IOMMU page tables\n");
+	dma_unmap_single(dev, dma, size, DMA_TO_DEVICE);
+out_free:
+	free_pages_exact(pages, size);
+	return NULL;
+
+}
+
+static void mtk_iommu_free_pgt(struct device *dev, void *pages, size_t size)
+{
+	dma_unmap_single(dev, (dma_addr_t)virt_to_phys(pages),
+			 size, DMA_TO_DEVICE);
+	free_pages_exact(pages, size);
+}
+
+static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data)
+{
+	struct mtk_iommu_domain *dom = data->m4u_dom;
+
+	spin_lock_init(&dom->pgtlock);
+
+	dom->pgt_va = mtk_iommu_alloc_pgt(data->dev,
+				dom->pgt_size, GFP_KERNEL);
+	if (!dom->pgt_va)
+		return -ENOMEM;
+
+	dom->pgt_pa = virt_to_phys(dom->pgt_va);
+
+	writel(dom->pgt_pa, data->base + REG_MMU_PT_BASE_ADDR);
+
+	dom->cookie = (void *)data;
+
+	return 0;
+}
+
+static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type)
+{
+	struct mtk_iommu_domain *dom;
+
+	if (type != IOMMU_DOMAIN_UNMANAGED)
+		return NULL;
+
+	dom = kzalloc(sizeof(*dom), GFP_KERNEL);
+	if (!dom)
+		return NULL;
+
+	/*
+	 * MTK m4u support 4GB iova address space, and oly support 4K page
+	 * mapping. So the pagetable size should be exactly as 4M.
+	 */
+	dom->pgt_size = SZ_4M;
+
+	return &dom->domain;
+}
+
+static void mtk_iommu_domain_free(struct iommu_domain *domain)
+{
+	kfree(to_mtk_domain(domain));
+}
+
+static int mtk_iommu_attach_device(struct iommu_domain *domain,
+				   struct device *dev)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
+	struct mtk_iommu_data *data;
+	int ret;
+
+	if (!priv)
+		return -ENODEV;
+
+	data = dev_get_drvdata(priv->m4udev);
+	if (!data->m4u_dom) {
+		data->m4u_dom = dom;
+		ret = mtk_iommu_domain_finalise(data);
+		if (ret) {
+			data->m4u_dom = NULL;
+			return ret;
+		}
+	} else if (data->m4u_dom != dom) {
+		/* All the client devices should be in the same m4u domain */
+		dev_err(dev, "try to attach into the error iommu domain\n");
+		return -EPERM;
+	}
+
+	mtk_iommu_config(data, dev, true);
+	return 0;
+}
+
+static void mtk_iommu_detach_device(struct iommu_domain *domain,
+				    struct device *dev)
+{
+	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
+	struct mtk_iommu_data *data;
+
+	if (!priv)
+		return;
+
+	data = dev_get_drvdata(priv->m4udev);
+	mtk_iommu_config(data, dev, false);
+}
+
+static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
+			 phys_addr_t paddr, size_t size, int prot)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct mtk_iommu_data *data = dom->cookie;
+	unsigned int page_num = size >> MTK_IOMMU_PAGE_SHIFT;
+	unsigned long flags;
+	unsigned int i;
+	u32 *pgt_base_iova;
+	u32 pabase = (u32)paddr;
+	int map_size = 0;
+
+	spin_lock_irqsave(&dom->pgtlock, flags);
+	pgt_base_iova = dom->pgt_va + (iova  >> MTK_IOMMU_PAGE_SHIFT);
+	for (i = 0; i < page_num; i++) {
+		pgt_base_iova[i] = pabase | F_DESC_VALID | F_DESC_NONSEC;
+		pabase += MTK_IOMMU_PAGE_SIZE;
+		map_size += MTK_IOMMU_PAGE_SIZE;
+	}
+	dma_sync_single_for_device(data->dev,
+			dom->pgt_pa + (iova >> MTK_IOMMU_PAGE_SHIFT),
+			(size >> MTK_IOMMU_PAGE_SHIFT) * sizeof(u32),
+			DMA_TO_DEVICE);
+	spin_unlock_irqrestore(&dom->pgtlock, flags);
+
+	mtk_iommu_tlb_flush_range(data, iova, size);
+
+	return map_size;
+}
+
+static size_t mtk_iommu_unmap(struct iommu_domain *domain,
+			      unsigned long iova, size_t size)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct mtk_iommu_data *data = dom->cookie;
+	unsigned long flags;
+	unsigned int *pgt_base_iova;
+	unsigned int page_num = size >> MTK_IOMMU_PAGE_SHIFT;
+
+	spin_lock_irqsave(&dom->pgtlock, flags);
+	pgt_base_iova = dom->pgt_va + (iova  >> MTK_IOMMU_PAGE_SHIFT);
+	memset(pgt_base_iova, 0, page_num * sizeof(u32));
+	dma_sync_single_for_device(data->dev,
+			dom->pgt_pa + (iova >> MTK_IOMMU_PAGE_SHIFT),
+			(size >> MTK_IOMMU_PAGE_SHIFT) * sizeof(u32),
+			DMA_TO_DEVICE);
+	spin_unlock_irqrestore(&dom->pgtlock, flags);
+
+	mtk_iommu_tlb_flush_range(data, iova, size);
+
+	return size;
+}
+
+static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
+					  dma_addr_t iova)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	unsigned long flags;
+	phys_addr_t pa;
+
+	spin_lock_irqsave(&dom->pgtlock, flags);
+	pa = *((u32 *)((u32 *)dom->pgt_va + (iova >> MTK_IOMMU_PAGE_SHIFT)));
+	pa = pa & (~(MTK_IOMMU_PAGE_SIZE - 1));
+	spin_unlock_irqrestore(&dom->pgtlock, flags);
+
+	return pa;
+}
+
+/*
+ * MTK generaion one iommu HW only support one iommu domain, and all the client
+ * sharing the same iova address space.
+ */
+static int mtk_iommu_create_mapping(struct device *dev,
+				    struct of_phandle_args *args)
+{
+	struct mtk_iommu_client_priv *head, *priv, *next;
+	struct platform_device *m4updev;
+	struct dma_iommu_mapping *mtk_mapping;
+	struct device *m4udev;
+	int ret;
+
+	if (args->args_count != 1) {
+		dev_err(dev, "invalid #iommu-cells(%d) property for IOMMU\n",
+			args->args_count);
+		return -EINVAL;
+	}
+
+	if (!dev->archdata.iommu) {
+		/* Get the m4u device */
+		m4updev = of_find_device_by_node(args->np);
+		of_node_put(args->np);
+		if (WARN_ON(!m4updev))
+			return -EINVAL;
+
+		head = kzalloc(sizeof(*head), GFP_KERNEL);
+		if (!head)
+			return -ENOMEM;
+
+		dev->archdata.iommu = head;
+		INIT_LIST_HEAD(&head->client);
+		head->m4udev = &m4updev->dev;
+	} else {
+		head = dev->archdata.iommu;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto err_free_mem;
+	}
+	priv->mtk_m4u_id = args->args[0];
+	list_add_tail(&priv->client, &head->client);
+
+	m4udev = head->m4udev;
+	mtk_mapping = m4udev->archdata.iommu;
+	if (!mtk_mapping) {
+		/* MTK iommu support 4GB iova address space. */
+		mtk_mapping = arm_iommu_create_mapping(&platform_bus_type,
+						0, 1ULL << 32);
+		if (IS_ERR(mtk_mapping)) {
+			ret = PTR_ERR(mtk_mapping);
+			goto err_free_mem;
+		}
+		m4udev->archdata.iommu = mtk_mapping;
+	}
+
+	ret = arm_iommu_attach_device(dev, mtk_mapping);
+	if (ret)
+		goto err_release_mapping;
+
+	return 0;
+
+err_release_mapping:
+	arm_iommu_release_mapping(mtk_mapping);
+	m4udev->archdata.iommu = NULL;
+err_free_mem:
+	list_for_each_entry_safe(priv, next, &head->client, client)
+		kfree(priv);
+	kfree(head);
+	dev->archdata.iommu = NULL;
+	return ret;
+}
+
+static int mtk_iommu_add_device(struct device *dev)
+{
+	struct iommu_group *group;
+	struct device_node *np;
+	struct of_phandle_args iommu_spec;
+	int idx = 0;
+
+	while (!of_parse_phandle_with_args(dev->of_node, "iommus",
+				   "#iommu-cells", idx,
+				   &iommu_spec)) {
+		np = iommu_spec.np;
+		mtk_iommu_create_mapping(dev, &iommu_spec);
+
+		of_node_put(np);
+		idx++;
+	}
+
+	if (!dev->archdata.iommu) /* Not a iommu client device */
+		return -ENODEV;
+
+	group = iommu_group_get_for_dev(dev);
+	if (IS_ERR(group))
+		return PTR_ERR(group);
+
+	iommu_group_put(group);
+	return 0;
+}
+
+static void mtk_iommu_remove_device(struct device *dev)
+{
+	struct mtk_iommu_client_priv *head, *cur, *next;
+
+	head = dev->archdata.iommu;
+	if (!head)
+		return;
+
+	list_for_each_entry_safe(cur, next, &head->client, client) {
+		list_del(&cur->client);
+		kfree(cur);
+	}
+	kfree(head);
+	dev->archdata.iommu = NULL;
+
+	iommu_group_remove_device(dev);
+}
+
+static struct iommu_group *mtk_iommu_device_group(struct device *dev)
+{
+	struct mtk_iommu_data *data;
+	struct mtk_iommu_client_priv *priv;
+
+	priv = dev->archdata.iommu;
+	if (!priv)
+		return ERR_PTR(-ENODEV);
+
+	/* All the client devices are in the same m4u iommu-group */
+	data = dev_get_drvdata(priv->m4udev);
+	if (!data->m4u_group) {
+		data->m4u_group = iommu_group_alloc();
+		if (IS_ERR(data->m4u_group))
+			dev_err(dev, "Failed to allocate M4U IOMMU group\n");
+	}
+	return data->m4u_group;
+}
+
+static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
+{
+	u32 regval;
+	int ret;
+
+	ret = clk_prepare_enable(data->bclk);
+	if (ret) {
+		dev_err(data->dev, "Failed to enable iommu bclk(%d)\n", ret);
+		return ret;
+	}
+
+	regval = F_MMU_CTRL_COHERENT_EN | F_MMU_TF_PROTECT_SEL(2);
+	writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
+
+	regval = F_INT_TRANSLATION_FAULT |
+		F_INT_MAIN_MULTI_HIT_FAULT |
+		F_INT_INVALID_PA_FAULT |
+		F_INT_ENTRY_REPLACEMENT_FAULT |
+		F_INT_TABLE_WALK_FAULT |
+		F_INT_TLB_MISS_FAULT |
+		F_INT_PFH_DMA_FIFO_OVERFLOW |
+		F_INT_MISS_DMA_FIFO_OVERFLOW;
+	writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL);
+
+	/* protect memory,hw will write here while translation fault */
+	writel_relaxed(data->protect_base,
+			data->base + REG_MMU_IVRP_PADDR);
+
+	writel_relaxed(F_MMU_DCM_ON, data->base + REG_MMU_DCM);
+
+	if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
+			     dev_name(data->dev), (void *)data)) {
+		writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR);
+		clk_disable_unprepare(data->bclk);
+		dev_err(data->dev, "Failed @ IRQ-%d Request\n", data->irq);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static struct iommu_ops mtk_iommu_ops = {
+	.domain_alloc	= mtk_iommu_domain_alloc,
+	.domain_free	= mtk_iommu_domain_free,
+	.attach_dev	= mtk_iommu_attach_device,
+	.detach_dev	= mtk_iommu_detach_device,
+	.map		= mtk_iommu_map,
+	.unmap		= mtk_iommu_unmap,
+	.map_sg		= default_iommu_map_sg,
+	.iova_to_phys	= mtk_iommu_iova_to_phys,
+	.add_device	= mtk_iommu_add_device,
+	.remove_device	= mtk_iommu_remove_device,
+	.device_group	= mtk_iommu_device_group,
+	.pgsize_bitmap	= MTK_IOMMU_PAGE_SIZE,
+};
+
+static const struct of_device_id mtk_iommu_of_ids[] = {
+	{ .compatible = "mediatek,mt2701-m4u", },
+	{}
+};
+
+static const struct component_master_ops mtk_iommu_com_ops = {
+	.bind		= mtk_iommu_bind,
+	.unbind		= mtk_iommu_unbind,
+};
+
+static int mtk_iommu_probe(struct platform_device *pdev)
+{
+	struct mtk_iommu_data		*data;
+	struct device			*dev = &pdev->dev;
+	struct resource			*res;
+	struct component_match		*match = NULL;
+	void				*protect;
+	int				i, larb_nr, ret;
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->dev = dev;
+
+	/* Protect memory. HW will access here while translation fault.*/
+	protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL);
+	if (!protect)
+		return -ENOMEM;
+	data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(data->base))
+		return PTR_ERR(data->base);
+
+	data->irq = platform_get_irq(pdev, 0);
+	if (data->irq < 0)
+		return data->irq;
+
+	data->bclk = devm_clk_get(dev, "bclk");
+	if (IS_ERR(data->bclk))
+		return PTR_ERR(data->bclk);
+
+	larb_nr = of_count_phandle_with_args(dev->of_node,
+					"mediatek,larbs", NULL);
+	if (larb_nr < 0)
+		return larb_nr;
+	data->smi_imu.larb_nr = larb_nr;
+
+	for (i = 0; i < larb_nr; i++) {
+		struct device_node *larbnode;
+		struct platform_device *plarbdev;
+
+		larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
+		if (!larbnode)
+			return -EINVAL;
+
+		if (!of_device_is_available(larbnode))
+			continue;
+
+		plarbdev = of_find_device_by_node(larbnode);
+		of_node_put(larbnode);
+		if (!plarbdev) {
+			plarbdev = of_platform_device_create(
+						larbnode, NULL,
+						platform_bus_type.dev_root);
+			if (!plarbdev)
+				return -EPROBE_DEFER;
+		}
+		data->smi_imu.larb_imu[i].dev = &plarbdev->dev;
+
+		component_match_add(dev, &match, compare_of, larbnode);
+	}
+
+	platform_set_drvdata(pdev, data);
+
+	ret = mtk_iommu_hw_init(data);
+	if (ret)
+		return ret;
+
+	if (!iommu_present(&platform_bus_type))
+		bus_set_iommu(&platform_bus_type,  &mtk_iommu_ops);
+
+	return component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
+}
+
+static int mtk_iommu_remove(struct platform_device *pdev)
+{
+	struct mtk_iommu_data *data = platform_get_drvdata(pdev);
+	struct mtk_iommu_domain *dom = data->m4u_dom;
+	struct device *dev = &pdev->dev;
+
+	mtk_iommu_free_pgt(dev, dom->pgt_va, dom->pgt_size);
+
+	if (iommu_present(&platform_bus_type))
+		bus_set_iommu(&platform_bus_type, NULL);
+
+	clk_disable_unprepare(data->bclk);
+	devm_free_irq(&pdev->dev, data->irq, data);
+	component_master_del(&pdev->dev, &mtk_iommu_com_ops);
+	return 0;
+}
+
+static int __maybe_unused mtk_iommu_suspend(struct device *dev)
+{
+	struct mtk_iommu_data *data = dev_get_drvdata(dev);
+	struct mtk_iommu_suspend_reg *reg = &data->reg;
+	void __iomem *base = data->base;
+
+	reg->standard_axi_mode = readl_relaxed(base +
+					       REG_MMU_STANDARD_AXI_MODE);
+	reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM);
+	reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG);
+	reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL);
+	return 0;
+}
+
+static int __maybe_unused mtk_iommu_resume(struct device *dev)
+{
+	struct mtk_iommu_data *data = dev_get_drvdata(dev);
+	struct mtk_iommu_suspend_reg *reg = &data->reg;
+	void __iomem *base = data->base;
+
+	writel_relaxed(data->m4u_dom->pgt_pa, base + REG_MMU_PT_BASE_ADDR);
+	writel_relaxed(reg->standard_axi_mode,
+		       base + REG_MMU_STANDARD_AXI_MODE);
+	writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM);
+	writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG);
+	writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL);
+	writel_relaxed(data->protect_base, base + REG_MMU_IVRP_PADDR);
+	return 0;
+}
+
+const struct dev_pm_ops mtk_iommu_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume)
+};
+
+static struct platform_driver mtk_iommu_driver = {
+	.probe	= mtk_iommu_probe,
+	.remove	= mtk_iommu_remove,
+	.driver	= {
+		.name = "mtk-iommu",
+		.of_match_table = mtk_iommu_of_ids,
+		.pm = &mtk_iommu_pm_ops,
+	}
+};
+
+static int __init m4u_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&mtk_iommu_driver);
+	if (ret)
+		bus_set_iommu(&platform_bus_type, NULL);
+
+	return ret;
+}
+
+static void __exit m4u_exit(void)
+{
+	return platform_driver_unregister(&mtk_iommu_driver);
+}
+
+subsys_initcall(m4u_init);
+module_exit(m4u_exit);
+
+MODULE_DESCRIPTION("IOMMU API for MTK architected m4u v1 implementations");
+MODULE_AUTHOR("Honghui Zhang <honghui.zhang at mediatek.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Mon May  9 01:00:16 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Mon, 9 May 2016 16:00:16 +0800
Subject: [PATCH 5/5] ARM: dts: mt2701: add iommu/smi dtsi node for mt2701
In-Reply-To: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
References: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1462780816-5288-6-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

Add the dtsi node of iommu and smi for mt2701.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 arch/arm/boot/dts/mt2701.dtsi | 51 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 42d5a37..363de0d 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -16,6 +16,7 @@
 #include <dt-bindings/power/mt2701-power.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/memory/mt2701-larb-port.h>
 #include "skeleton64.dtsi"
 #include "mt2701-pinfunc.h"
 
@@ -160,6 +161,16 @@
 		clock-names = "system-clk", "rtc-clk";
 	};
 
+	smi_common: smi at 1000c000 {
+		compatible = "mediatek,mt2701-smi-common";
+		reg = <0 0x1000c000 0 0x1000>;
+		clocks = <&infracfg CLK_INFRA_SMI>,
+			 <&mmsys CLK_MM_SMI_COMMON>,
+			 <&infracfg CLK_INFRA_SMI>;
+		clock-names = "apb", "smi", "async";
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
+	};
+
 	sysirq: interrupt-controller at 10200100 {
 		compatible = "mediatek,mt2701-sysirq",
 			     "mediatek,mt6577-sysirq";
@@ -169,6 +180,16 @@
 		reg = <0 0x10200100 0 0x1c>;
 	};
 
+	iommu: mmsys_iommu at 10205000 {
+		compatible = "mediatek,mt2701-m4u";
+		reg = <0 0x10205000 0 0x1000>;
+		interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&infracfg CLK_INFRA_M4U>;
+		clock-names = "bclk";
+		mediatek,larbs = <&larb0 &larb1 &larb2>;
+		#iommu-cells = <1>;
+	};
+
 	apmixedsys: syscon at 10209000 {
 		compatible = "mediatek,mt2701-apmixedsys", "syscon";
 		reg = <0 0x10209000 0 0x1000>;
@@ -234,6 +255,16 @@
 		status = "disabled";
 	};
 
+	larb0: larb at 14010000 {
+		compatible = "mediatek,mt2701-smi-larb";
+		reg = <0 0x14010000 0 0x1000>;
+		mediatek,smi = <&smi_common>;
+		clocks = <&mmsys CLK_MM_SMI_LARB0>,
+			 <&mmsys CLK_MM_SMI_LARB0>;
+		clock-names = "apb", "smi";
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
+	};
+
 	imgsys: syscon at 15000000 {
 		compatible = "mediatek,mt2701-imgsys", "syscon";
 		reg = <0 0x15000000 0 0x1000>;
@@ -241,6 +272,16 @@
 		status = "disabled";
 	};
 
+	larb2: larb at 15001000 {
+		compatible = "mediatek,mt2701-smi-larb";
+		reg = <0 0x15001000 0 0x1000>;
+		mediatek,smi = <&smi_common>;
+		clocks = <&imgsys CLK_IMG_SMI_COMM>,
+			 <&imgsys CLK_IMG_SMI_COMM>;
+		clock-names = "apb", "smi";
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_ISP>;
+	};
+
 	vdecsys: syscon at 16000000 {
 		compatible = "mediatek,mt2701-vdecsys", "syscon";
 		reg = <0 0x16000000 0 0x1000>;
@@ -248,6 +289,16 @@
 		status = "disabled";
 	};
 
+	larb1: larb at 16010000 {
+		compatible = "mediatek,mt2701-smi-larb";
+		reg = <0 0x16010000 0 0x1000>;
+		mediatek,smi = <&smi_common>;
+		clocks = <&vdecsys CLK_VDEC_CKGEN>,
+			 <&vdecsys CLK_VDEC_LARB>;
+		clock-names = "apb", "smi";
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_VDEC>;
+	};
+
 	hifsys: syscon at 1a000000 {
 		compatible = "mediatek,mt2701-hifsys", "syscon";
 		reg = <0 0x1a000000 0 0x1000>;
-- 
1.8.1.1.dirty



From eric.auger at linaro.org  Mon May  9 01:05:08 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 9 May 2016 10:05:08 +0200
Subject: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability at
 msi domain
In-Reply-To: <FFD9D7C5-B6EF-4E16-A209-BED31DAB26AA@caviumnetworks.com>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-6-git-send-email-eric.auger@linaro.org>
 <FFD9D7C5-B6EF-4E16-A209-BED31DAB26AA@caviumnetworks.com>
Message-ID: <573044B4.4000905@linaro.org>

Hi Chalamarla,
On 05/05/2016 09:23 PM, Chalamarla, Tirumalesh wrote:
> 
> 
> 
> 
> 
> On 5/4/16, 4:54 AM, "linux-arm-kernel on behalf of Eric Auger" <linux-arm-kernel-bounces at lists.infradead.org on behalf of eric.auger at linaro.org> wrote:
> 
>> On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is abstracted
>> by the msi controller. vfio_safe_irq_domain allows to check whether
>> interrupts are "safe" for a given device. They are if the device does
>> not use MSI or if the device uses MSI and the msi-parent controller
>> supports IRQ remapping.
>>
>> Then we check at group level if all devices have safe interrupts: if not,
>> we only allow the group to be attached if allow_unsafe_interrupts is set.
>>
>> At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP. This is
>> changed in next patch.
> 
> Will this work in systems with multiple ITS?
Yes it should support multiple ITS.

Please note however that the series does not yet implement the
msi_doorbell_info callback in GICv3 ITS PCIe/platform irqchip. Without
that, the pci_enable is going to fail. I am going to submit a separate
RFC for that but I can't test it at the moment.

Best Regards

Eric
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>
>> ---
>> v3 -> v4:
>> - rename vfio_msi_parent_irq_remapping_capable into vfio_safe_irq_domain
>>  and irq_remapping into safe_irq_domains
>>
>> v2 -> v3:
>> - protect vfio_msi_parent_irq_remapping_capable with
>>  CONFIG_GENERIC_MSI_IRQ_DOMAIN
>> ---
>> drivers/vfio/vfio_iommu_type1.c | 44 +++++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 42 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
>> index 4d3a6f1..2fc8197 100644
>> --- a/drivers/vfio/vfio_iommu_type1.c
>> +++ b/drivers/vfio/vfio_iommu_type1.c
>> @@ -37,6 +37,8 @@
>> #include <linux/vfio.h>
>> #include <linux/workqueue.h>
>> #include <linux/msi-iommu.h>
>> +#include <linux/irqdomain.h>
>> +#include <linux/msi.h>
>>
>> #define DRIVER_VERSION  "0.2"
>> #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson at redhat.com>"
>> @@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev, void *data)
>> 	return 0;
>> }
>>
>> +/**
>> + * vfio_safe_irq_domain: returns whether the irq domain
>> + * the device is attached to is safe with respect to MSI isolation.
>> + * If the irq domain is not an MSI domain, we return it is safe.
>> + *
>> + * @dev: device handle
>> + * @data: unused
>> + * returns 0 if the irq domain is safe, -1 if not.
>> + */
>> +static int vfio_safe_irq_domain(struct device *dev, void *data)
>> +{
>> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
>> +	struct irq_domain *domain;
>> +	struct msi_domain_info *info;
>> +
>> +	domain = dev_get_msi_domain(dev);
>> +	if (!domain)
>> +		return 0;
>> +
>> +	info = msi_get_domain_info(domain);
>> +
>> +	if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
>> +		return -1;
>> +#endif
>> +	return 0;
>> +}
>> +
>> static int vfio_iommu_replay(struct vfio_iommu *iommu,
>> 			     struct vfio_domain *domain)
>> {
>> @@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>> 	struct vfio_group *group, *g;
>> 	struct vfio_domain *domain, *d;
>> 	struct bus_type *bus = NULL;
>> -	int ret;
>> +	int ret, safe_irq_domains;
>>
>> 	mutex_lock(&iommu->lock);
>>
>> @@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>>
>> 	group->iommu_group = iommu_group;
>>
>> +	/*
>> +	 * Determine if all the devices of the group have a safe irq domain
>> +	 * with respect to MSI isolation
>> +	 */
>> +	safe_irq_domains = !iommu_group_for_each_dev(iommu_group, &bus,
>> +				       vfio_safe_irq_domain);
>> +
>> 	/* Determine bus_type in order to allocate a domain */
>> 	ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type);
>> 	if (ret)
>> @@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>> 	INIT_LIST_HEAD(&domain->group_list);
>> 	list_add(&group->next, &domain->group_list);
>>
>> +	/*
>> +	 * to advertise safe interrupts either the IOMMU or the MSI controllers
>> +	 * must support IRQ remapping/interrupt translation
>> +	 */
>> 	if (!allow_unsafe_interrupts &&
>> -	    !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
>> +	    (!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) && !safe_irq_domains)) {
>> 		pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",
>> 		       __func__);
>> 		ret = -EPERM;
>> -- 
>> 1.9.1
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



From peter.ujfalusi at ti.com  Mon May  9 01:25:53 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 9 May 2016 11:25:53 +0300
Subject: [PATCH] ARM: dts: omap5-igep0050: Correct hdmi regulator
In-Reply-To: <20160505184609.GB5995@atomide.com>
References: <1461925297-9734-1-git-send-email-peter.ujfalusi@ti.com>
 <6ee9d67a-e907-715a-f3f5-d90a470314c3@ti.com>
 <20160504172634.GS5995@atomide.com> <572A38FD.9050801@ti.com>
 <20160505184609.GB5995@atomide.com>
Message-ID: <a6969765-d07d-6d0e-36df-b78b485d9644@ti.com>

Adding Tomi,

On 05/05/16 21:46, Tony Lindgren wrote:
> * Nishanth Menon <nm at ti.com> [160504 11:03]:
>> On 05/04/2016 12:26 PM, Tony Lindgren wrote:
>>> Hi,
>>>
>>> Adding Nishanth to Cc.
>>>
>>> * Peter Ujfalusi <peter.ujfalusi at ti.com> [160429 05:15]:
>>>> ldo7_reg, obviously ;)
>>>>
>>>>> 	status = "okay";
>>>>> 	regulator-min-microvolt = <1800000>;
>>>>> 	regulator-max-microvolt = <1800000>;
>>>>> };
>>>
>>> It really seems to be ldo7, otherwise there's no HDMI output. I don't
>>> have the schematics either.
>>>
>>> But it seems we have at least two other regressions in Linux next that
>>> prevent me from testing this properly:
>>>
>>> 1. On igepv5, I get this for the MMC regulator
>>>
>>> ldo9: bypassed regulator has no supply!
>>> ldo9: failed to get the current voltage(-517)
>>> palmas-pmic 48070000.i2c:palmas at 48:palmas_pmic: failed to register 48070000.i2c:palmar
> 
> The patch I posted fixes this. Then for the HDMI see below.
> I've kept it at 2V like we have in omap5-board-common.dtsi,
> I wonder if it really should be 1.8V though for ldo7 in this
> case?

AFAIK the VDDA for the HDMI needs to be 1.8V along with other VDDAs for DSS
(vdda_dsiporta, vdda_dsiportc and vdda_hdmi).

Tomi: what do you think?

According to the OMAP5 data manual the vdda_hdmi can be in 1.5V or 1.8V mode,
2V is not mentioned in the recommended operating conditions table.

Just to note: on omap5-uevm the ldo7 is connected to VPP1 of OMAP5 (eFuse
power supply), which does require 2V.


> Regards,
> 
> Tony
> 8< -----------------
> From: Tony Lindgren <tony at atomide.com>
> Date: Thu, 5 May 2016 11:29:23 -0700
> Subject: [PATCH] ARM: dts: Fix ldo7 source for HDMI on igepv5
> 
> Fix ldo7 source for HDMI on igepv5.
> 
> Suggested-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
> Signed-off-by: Tony Lindgren <tony at atomide.com>
> 
> diff --git a/arch/arm/boot/dts/omap5-igep0050.dts b/arch/arm/boot/dts/omap5-igep0050.dts
> index 46ecb1d..72ff6a4 100644
> --- a/arch/arm/boot/dts/omap5-igep0050.dts
> +++ b/arch/arm/boot/dts/omap5-igep0050.dts
> @@ -35,6 +35,12 @@
>  	};
>  };
>  
> +&ldo7_reg {
> +	status = "okay";
> +	regulator-min-microvolt = <2000000>;
> +	regulator-max-microvolt = <2000000>;

If we are not changing the default voltage set in the common dtsi file we only
need to status = "okay"

> +};
> +
>  &omap5_pmx_core {
>  	i2c4_pins: pinmux_i2c4_pins {
>  		pinctrl-single,pins = <
> 


-- 
P?ter


From stefan.wahren at i2se.com  Mon May  9 01:30:38 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Mon, 9 May 2016 10:30:38 +0200
Subject: [PATCH 3/4] ARM: mxs: dts: Add Creative X-Fi3 support
In-Reply-To: <572FA04B.1020005@denx.de>
References: <1462479971-7891-1-git-send-email-marex@denx.de>
 <1462479971-7891-3-git-send-email-marex@denx.de>
 <977436072.210446.e7eef450-2262-47df-8e8e-6a44da10083c.open-xchange@email.1und1.de>
 <572FA04B.1020005@denx.de>
Message-ID: <57304AAE.20103@i2se.com>

Hi,

Am 08.05.2016 um 22:23 schrieb Marek Vasut:
> On 05/06/2016 09:40 AM, Stefan Wahren wrote:
>> Hi Marek,
> Hi!
>
>> sorry for the reply format.
> replying from a phone ? :)

no an ugly webmailer :(

>
>>> Marek Vasut <marex at denx.de> hat am 5. Mai 2016 um 22:26 geschrieben:
>>>
>>> Add support for this small MP3 player based on STMP3780 (rev.4).
>>> Currently supported is both external microSD and internal SD-NAND
>>> bridge, PWM and USB gadget.
>>>
>>> Signed-off-by: Marek Vasut <marex at denx.de>
>>> Cc: Fabio Estevam <fabio.estevam at nxp.com>
>>> Cc: Shawn Guo <shawnguo at kernel.org>
>>> ---
>>>  arch/arm/boot/dts/Makefile | 1 +
>>>  arch/arm/boot/dts/imx23-xfi3.dts | 190
>>> +++++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 191 insertions(+)
>>>  create mode 100644 arch/arm/boot/dts/imx23-xfi3.dts
>>>
>>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>>> index 8f9f1c2..7a79d37 100644
>>> --- a/arch/arm/boot/dts/Makefile
>>> +++ b/arch/arm/boot/dts/Makefile
>>> @@ -417,6 +417,7 @@ dtb-$(CONFIG_ARCH_MXS) += \
>>>  imx23-evk.dtb \
>>>  imx23-olinuxino.dtb \
>>>  imx23-stmp378x_devb.dtb \
>>> + imx23-xfi3.dtb \
>>>  imx28-apf28.dtb \
>>>  imx28-apf28dev.dtb \
>>>  imx28-apx4devkit.dtb \
>>> diff --git a/arch/arm/boot/dts/imx23-xfi3.dts
>>> b/arch/arm/boot/dts/imx23-xfi3.dts
>>> new file mode 100644
>>> index 0000000..d7e7cf5
>>> --- /dev/null
>>> +++ b/arch/arm/boot/dts/imx23-xfi3.dts
>>> @@ -0,0 +1,190 @@
>>> +/*
>>> + * Copyright (C) 2013-2016 Marek Vasut <marex at denx.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.
>>> + *
>>> + * You should have received a copy of the GNU General Public
>>> + * License along with this file; if not, write to the Free
>>> + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
>>> + * MA 02110-1301 USA
>> AFAIK this address shouldn't be included.
> Hmmm, some boards do include it. I'll remove it from this submission and
> also for the xfi.
>
> Shall I send patch(es) removing the address from the other boards too ?

i'm not sure. Maybe Shawn has an opinion about it.

Thanks
Stefan


From peter.ujfalusi at ti.com  Mon May  9 01:31:58 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 9 May 2016 11:31:58 +0300
Subject: [PATCH] ARM: dts: Fix igepv5 audiopwon-gpio
In-Reply-To: <1462474581-13865-1-git-send-email-tony@atomide.com>
References: <1462474581-13865-1-git-send-email-tony@atomide.com>
Message-ID: <ab6e5775-949b-f83a-fc13-1c643181ec2b@ti.com>

On 05/05/16 21:56, Tony Lindgren wrote:
> Playing audio works on omap5-uevm, but produces an "Unhandled fault:
> imprecise external abort (0x1406) at 0x00000000" error on igepv5.

I assume this is coming from the McPDM driver... If the clock is missing from
the twl6040 the IP is not accessible.
I do have a driver upstream to represent the twl6040 clock to be used by the
McPDM, but did not had time to do the work for integrating that into the clock
tree. Since it is external clock and we need i2c commands to configure things
in twl6040, I'm still not sure how pm_runtime would like this...

> Looks like the twl6040 audpwron GPIO pin is different for these
> boards. Let's fix the issue by configuring the audpwron in the
> board specific dts file.

Acked-by: Peter Ujfalusi <peter.ujflausi at ti com>


> Cc: Agust? Fontquerni <af at iseebcn.com>
> Cc: Eduard Gavin <egavin at iseebcn.com>
> Cc: Enric Balletbo i Serra <eballetbo at iseebcn.com>
> Cc: Peter Ujfalusi <peter.ujfalusi at ti.com>
> Signed-off-by: Tony Lindgren <tony at atomide.com>
> ---
>  arch/arm/boot/dts/omap5-board-common.dtsi |  3 ++-
>  arch/arm/boot/dts/omap5-igep0050.dts      | 10 ++++++++++
>  arch/arm/boot/dts/omap5-uevm.dts          | 10 ++++++++++
>  3 files changed, 22 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi
> index 2eea26c..23b1d7c 100644
> --- a/arch/arm/boot/dts/omap5-board-common.dtsi
> +++ b/arch/arm/boot/dts/omap5-board-common.dtsi
> @@ -642,7 +642,8 @@
>  		pinctrl-0 = <&twl6040_pins>;
>  
>  		interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
> -		ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
> +
> +		/* audpwron gpio defined in the board specific dts */
>  
>  		vio-supply = <&smps7_reg>;
>  		v2v1-supply = <&smps9_reg>;
> diff --git a/arch/arm/boot/dts/omap5-igep0050.dts b/arch/arm/boot/dts/omap5-igep0050.dts
> index 72ff6a4..673cdfa 100644
> --- a/arch/arm/boot/dts/omap5-igep0050.dts
> +++ b/arch/arm/boot/dts/omap5-igep0050.dts
> @@ -58,3 +58,13 @@
>  		<&gpio7 3 0>;		/* 195, SDA */
>  };
>  
> +&twl6040 {
> +	ti,audpwron-gpio = <&gpio5 16 GPIO_ACTIVE_HIGH>;  /* gpio line 144 */
> +};
> +
> +&twl6040_pins {
> +	pinctrl-single,pins = <
> +		OMAP5_IOPAD(0x1c4, PIN_OUTPUT | MUX_MODE6)	/* mcspi1_somi.gpio5_144 */
> +		OMAP5_IOPAD(0x1ca, PIN_OUTPUT | MUX_MODE6)	/* perslimbus2_clock.gpio5_145 */
> +	>;
> +};
> diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts
> index 60b3fbb..a51e605 100644
> --- a/arch/arm/boot/dts/omap5-uevm.dts
> +++ b/arch/arm/boot/dts/omap5-uevm.dts
> @@ -51,3 +51,13 @@
>  		<&gpio9 1 GPIO_ACTIVE_HIGH>,	/* TCA6424A P00, LS OE */
>  		<&gpio7 1 GPIO_ACTIVE_HIGH>;	/* GPIO 193, HPD */
>  };
> +
> +&twl6040 {
> +	ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
> +};
> +
> +&twl6040_pins {
> +	pinctrl-single,pins = <
> +		OMAP5_IOPAD(0x1be, PIN_OUTPUT | MUX_MODE6)	/* mcspi1_somi.gpio5_141 */
> +	>;
> +};
> 


-- 
P?ter


From tomi.valkeinen at ti.com  Mon May  9 01:34:38 2016
From: tomi.valkeinen at ti.com (Tomi Valkeinen)
Date: Mon, 9 May 2016 11:34:38 +0300
Subject: [PATCH] ARM: dts: omap5-igep0050: Correct hdmi regulator
In-Reply-To: <a6969765-d07d-6d0e-36df-b78b485d9644@ti.com>
References: <1461925297-9734-1-git-send-email-peter.ujfalusi@ti.com>
 <6ee9d67a-e907-715a-f3f5-d90a470314c3@ti.com>
 <20160504172634.GS5995@atomide.com> <572A38FD.9050801@ti.com>
 <20160505184609.GB5995@atomide.com>
 <a6969765-d07d-6d0e-36df-b78b485d9644@ti.com>
Message-ID: <57304B9E.50201@ti.com>


On 09/05/16 11:25, Peter Ujfalusi wrote:

> Tomi: what do you think?
> 
> According to the OMAP5 data manual the vdda_hdmi can be in 1.5V or 1.8V mode,
> 2V is not mentioned in the recommended operating conditions table.

I thought vdda_hdmi should always be 1.8V, but you're right, on omap5
1.5V is allowed according to DM. On later SoCs it's only 1.8V. I suggest
we use 1.8V on all boards, as that's what's known to work.

2V is definitely wrong.

 Tomi

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160509/d962752c/attachment-0001.sig>

From peter.ujfalusi at ti.com  Mon May  9 01:34:42 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 9 May 2016 11:34:42 +0300
Subject: [PATCH] ARM: dts: Fix igepv5 audiopwon-gpio
In-Reply-To: <1462474581-13865-1-git-send-email-tony@atomide.com>
References: <1462474581-13865-1-git-send-email-tony@atomide.com>
Message-ID: <1b37fbdd-67f0-e9e3-d442-bdc0bd74397b@ti.com>

On 05/05/16 21:56, Tony Lindgren wrote:
> Playing audio works on omap5-uevm, but produces an "Unhandled fault:
> imprecise external abort (0x1406) at 0x00000000" error on igepv5.
> 
> Looks like the twl6040 audpwron GPIO pin is different for these
> boards. Let's fix the issue by configuring the audpwron in the
> board specific dts file.
> 
> Cc: Agust? Fontquerni <af at iseebcn.com>
> Cc: Eduard Gavin <egavin at iseebcn.com>
> Cc: Enric Balletbo i Serra <eballetbo at iseebcn.com>
> Cc: Peter Ujfalusi <peter.ujfalusi at ti.com>
> Signed-off-by: Tony Lindgren <tony at atomide.com>
> ---
>  arch/arm/boot/dts/omap5-board-common.dtsi |  3 ++-
>  arch/arm/boot/dts/omap5-igep0050.dts      | 10 ++++++++++
>  arch/arm/boot/dts/omap5-uevm.dts          | 10 ++++++++++
>  3 files changed, 22 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi
> index 2eea26c..23b1d7c 100644
> --- a/arch/arm/boot/dts/omap5-board-common.dtsi
> +++ b/arch/arm/boot/dts/omap5-board-common.dtsi
> @@ -642,7 +642,8 @@
>  		pinctrl-0 = <&twl6040_pins>;
>  
>  		interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
> -		ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
> +
> +		/* audpwron gpio defined in the board specific dts */
>  
>  		vio-supply = <&smps7_reg>;
>  		v2v1-supply = <&smps9_reg>;
> diff --git a/arch/arm/boot/dts/omap5-igep0050.dts b/arch/arm/boot/dts/omap5-igep0050.dts
> index 72ff6a4..673cdfa 100644
> --- a/arch/arm/boot/dts/omap5-igep0050.dts
> +++ b/arch/arm/boot/dts/omap5-igep0050.dts
> @@ -58,3 +58,13 @@
>  		<&gpio7 3 0>;		/* 195, SDA */
>  };
>  
> +&twl6040 {
> +	ti,audpwron-gpio = <&gpio5 16 GPIO_ACTIVE_HIGH>;  /* gpio line 144 */

BTW: how do you know that gpio144 is used as audpwron GPIO on igepv5?

> +};
> +
> +&twl6040_pins {
> +	pinctrl-single,pins = <
> +		OMAP5_IOPAD(0x1c4, PIN_OUTPUT | MUX_MODE6)	/* mcspi1_somi.gpio5_144 */
> +		OMAP5_IOPAD(0x1ca, PIN_OUTPUT | MUX_MODE6)	/* perslimbus2_clock.gpio5_145 */

What does the gpio145 is used for?

> +	>;
> +};
> diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts
> index 60b3fbb..a51e605 100644
> --- a/arch/arm/boot/dts/omap5-uevm.dts
> +++ b/arch/arm/boot/dts/omap5-uevm.dts
> @@ -51,3 +51,13 @@
>  		<&gpio9 1 GPIO_ACTIVE_HIGH>,	/* TCA6424A P00, LS OE */
>  		<&gpio7 1 GPIO_ACTIVE_HIGH>;	/* GPIO 193, HPD */
>  };
> +
> +&twl6040 {
> +	ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
> +};
> +
> +&twl6040_pins {
> +	pinctrl-single,pins = <
> +		OMAP5_IOPAD(0x1be, PIN_OUTPUT | MUX_MODE6)	/* mcspi1_somi.gpio5_141 */
> +	>;
> +};
> 


-- 
P?ter


From geert at linux-m68k.org  Mon May  9 01:36:41 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 9 May 2016 10:36:41 +0200
Subject: Build regressions/improvements in v4.6-rc7
In-Reply-To: <1462782250-6231-1-git-send-email-geert@linux-m68k.org>
References: <1462782250-6231-1-git-send-email-geert@linux-m68k.org>
Message-ID: <CAMuHMdWAiX03Oejt6ovLaHc6sNwX+Y5-nAASDRJEfmeMAq_4Sg@mail.gmail.com>

On Mon, May 9, 2016 at 10:24 AM, Geert Uytterhoeven
<geert at linux-m68k.org> wrote:
> JFYI, when comparing v4.6-rc7[1] to v4.6-rc6[3], the summaries are:
>   - build errors: +188/-7

For a quiet -rc7, the results are devastating:

  + /home/kisskb/slave/src/arch/sh/kernel/setup.c: error: implicit
declaration of function 'early_init_dt_scan'
[-Werror=implicit-function-declaration]:  => 256:2

sh-randconfig

  + /home/kisskb/slave/src/drivers/net/ethernet/3com/typhoon.c: error:
case label does not reduce to an integer constant:  => 1007:2, 1016:2,
1010:2, 1013:2, 1019:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192e/rtl8192e/rtl_core.c:
error: (near initialization for 'def_qos_parameters.cw_max[0]'):  =>
372:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192e/rtl8192e/rtl_core.c:
error: (near initialization for 'def_qos_parameters.cw_max[1]'):  =>
372:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192e/rtl8192e/rtl_core.c:
error: (near initialization for 'def_qos_parameters.cw_max[2]'):  =>
372:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192e/rtl8192e/rtl_core.c:
error: (near initialization for 'def_qos_parameters.cw_max[3]'):  =>
372:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192e/rtl8192e/rtl_core.c:
error: (near initialization for 'def_qos_parameters.cw_min[0]'):  =>
371:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192e/rtl8192e/rtl_core.c:
error: (near initialization for 'def_qos_parameters.cw_min[1]'):  =>
371:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192e/rtl8192e/rtl_core.c:
error: (near initialization for 'def_qos_parameters.cw_min[2]'):  =>
371:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192e/rtl8192e/rtl_core.c:
error: (near initialization for 'def_qos_parameters.cw_min[3]'):  =>
371:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192e/rtl8192e/rtl_core.c:
error: initializer element is not constant:  => 371:2, 372:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192u/r8192U_core.c:
error: (near initialization for 'def_qos_parameters.cw_max[0]'):  =>
1870:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192u/r8192U_core.c:
error: (near initialization for 'def_qos_parameters.cw_max[1]'):  =>
1870:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192u/r8192U_core.c:
error: (near initialization for 'def_qos_parameters.cw_max[2]'):  =>
1870:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192u/r8192U_core.c:
error: (near initialization for 'def_qos_parameters.cw_max[3]'):  =>
1870:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192u/r8192U_core.c:
error: (near initialization for 'def_qos_parameters.cw_min[0]'):  =>
1869:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192u/r8192U_core.c:
error: (near initialization for 'def_qos_parameters.cw_min[1]'):  =>
1869:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192u/r8192U_core.c:
error: (near initialization for 'def_qos_parameters.cw_min[2]'):  =>
1869:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192u/r8192U_core.c:
error: (near initialization for 'def_qos_parameters.cw_min[3]'):  =>
1869:2
  + /home/kisskb/slave/src/drivers/staging/rtl8192u/r8192U_core.c:
error: initializer element is not constant:  => 1869:2, 1870:2
  + /home/kisskb/slave/src/drivers/usb/chipidea/udc.c: error: (near
initialization for 'ctrl_endpt_in_desc.wMaxPacketSize'):  => 50:2
  + /home/kisskb/slave/src/drivers/usb/chipidea/udc.c: error: (near
initialization for 'ctrl_endpt_out_desc.wMaxPacketSize'):  => 40:2
  + /home/kisskb/slave/src/drivers/usb/chipidea/udc.c: error:
initializer element is not constant:  => 50:2, 40:2
  + /home/kisskb/slave/src/drivers/usb/image/mdc800.c: error: (near
initialization for 'mdc800_ed[0].wMaxPacketSize'):  => 191:3
  + /home/kisskb/slave/src/drivers/usb/image/mdc800.c: error: (near
initialization for 'mdc800_ed[1].wMaxPacketSize'):  => 201:3
  + /home/kisskb/slave/src/drivers/usb/image/mdc800.c: error: (near
initialization for 'mdc800_ed[2].wMaxPacketSize'):  => 211:3
  + /home/kisskb/slave/src/drivers/usb/image/mdc800.c: error: (near
initialization for 'mdc800_ed[3].wMaxPacketSize'):  => 221:3
  + /home/kisskb/slave/src/drivers/usb/image/mdc800.c: error:
initializer element is not constant:  => 191:3, 211:3, 221:3, 201:3
  + /home/kisskb/slave/src/fs/cifs/smb1ops.c: error: (near
initialization for 'smb1_values.lock_cmd'):  => 1110:2
  + /home/kisskb/slave/src/fs/cifs/smb1ops.c: error: initializer
element is not constant  LD      security/built-in.o:  => 1110:2
  + /home/kisskb/slave/src/fs/cifs/smb1ops.c: error: initializer
element is not constant:  => 1110:2
  + /home/kisskb/slave/src/fs/hpfs/hpfs.h: error: enumerator value for
'FNODE_anode' is not an integer constant:  => 435:7
  + /home/kisskb/slave/src/fs/hpfs/hpfs.h: error: enumerator value for
'FNODE_dir' is not an integer constant:  => 435:37
  + /home/kisskb/slave/src/fs/ntfs/dir.c: error: (near initialization
for 'I30[0]'):  => 36:1
  + /home/kisskb/slave/src/fs/ntfs/dir.c: error: (near initialization
for 'I30[1]'):  => 36:1
  + /home/kisskb/slave/src/fs/ntfs/dir.c: error: (near initialization
for 'I30[2]'):  => 37:3
  + /home/kisskb/slave/src/fs/ntfs/dir.c: error: (near initialization
for 'I30[3]'):  => 37:3
  + /home/kisskb/slave/src/fs/ntfs/dir.c: error: initializer element
is not constant:  => 36:1, 37:3
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'ATTR_COMPRESSION_MASK' is not an integer constant:  => 607:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'ATTR_IS_COMPRESSED' is not an integer constant:  => 606:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'ATTR_IS_ENCRYPTED' is not an integer constant:  => 610:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'ATTR_IS_SPARSE' is not an integer constant:  => 611:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'INDEX_ENTRY_END' is not an integer constant:  => 2184:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'INDEX_ENTRY_NODE' is not an integer constant:  => 2181:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'INDEX_ENTRY_SPACE_FILLER' is not an integer constant:  => 2188:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'MFT_RECORD_IN_USE' is not an integer constant:  => 250:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'MFT_RECORD_IS_DIRECTORY' is not an integer constant:  => 251:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_DACL_AUTO_INHERITED' is not an integer constant:  => 1708:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_DACL_AUTO_INHERIT_REQ' is not an integer constant:  => 1706:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_DACL_DEFAULTED' is not an integer constant:  => 1701:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_DACL_PRESENT' is not an integer constant:  => 1700:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_DACL_PRESENT' is not an integer constantmake[4]: :  => 1700:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_DACL_PROTECTED' is not an integer constant:  => 1711:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_GROUP_DEFAULTED' is not an integer constant:  => 1699:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_OWNER_DEFAULTED' is not an integer constant:  => 1698:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_RM_CONTROL_VALID' is not an integer constant:  => 1713:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_SACL_AUTO_INHERITED' is not an integer constant:  => 1709:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_SACL_AUTO_INHERIT_REQ' is not an integer constant:  => 1707:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_SACL_DEFAULTED' is not an integer constant:  => 1704:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_SACL_PRESENT' is not an integer constant:  => 1703:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_SACL_PROTECTED' is not an integer constant:  => 1712:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'SE_SELF_RELATIVE' is not an integer constant:  => 1715:1
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'VOLUME_CHKDSK_UNDERWAY' is not an integer constant:  => 1910:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'VOLUME_DELETE_USN_UNDERWAY' is not an integer constant:  =>
1907:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'VOLUME_FLAGS_MASK' is not an integer constant:  => 1913:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'VOLUME_IS_DIRTY' is not an integer constant:  => 1902:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'VOLUME_MODIFIED_BY_CHKDSK' is not an integer constant:  => 1911:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'VOLUME_MOUNTED_ON_NT4' is not an integer constant:  => 1905:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'VOLUME_MUST_MOUNT_RO_MASK' is not an integer constant:  => 1916:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'VOLUME_REPAIR_OBJECT_ID' is not an integer constant:  => 1908:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'VOLUME_RESIZE_LOG_FILE' is not an integer constant:  => 1903:2
  + /home/kisskb/slave/src/fs/ntfs/layout.h: error: enumerator value
for 'VOLUME_UPGRADE_ON_MOUNT' is not an integer constant:  => 1904:2
  + /home/kisskb/slave/src/fs/ocfs2/xattr.c: error: (near
initialization for 'def_xv.xv.xr_list.l_count'):  => 97:2
  + /home/kisskb/slave/src/fs/ocfs2/xattr.c: error: initializer
element is not constant:  => 97:2
  + /home/kisskb/slave/src/lib/test_bpf.c: error: (near initialization
for 'tests[206].test[0].result'):  => 4098:3
  + /home/kisskb/slave/src/lib/test_bpf.c: error: initializer element
is not constant:  => 4098:3
  + /home/kisskb/slave/src/lib/vsprintf.c: error: (near initialization
for 'decpair[0]'):  => 159:2

    [...]

  + /home/kisskb/slave/src/lib/vsprintf.c: error: (near initialization
for 'decpair[9]'):  => 159:2
  + /home/kisskb/slave/src/lib/vsprintf.c: error: initializer element
is not constant  CC      drivers/clk/clk-fixed-rate.o:  => 164:2
  + /home/kisskb/slave/src/lib/vsprintf.c: error: initializer element
is not constant:  => 160:2, 168:2, 162:2, 166:2, 167:2, 165:2, 164:2,
161:2, 163:2, 159:2
  + /home/kisskb/slave/src/net/mac80211/main.c: error: (near
initialization for 'mac80211_ht_capa_mod_mask.cap_info'):  => 452:2
  + /home/kisskb/slave/src/net/mac80211/main.c: error: (near
initialization for 'mac80211_vht_capa_mod_mask.supp_mcs.rx_mcs_map'):
=> 480:3
  + /home/kisskb/slave/src/net/mac80211/main.c: error: (near
initialization for 'mac80211_vht_capa_mod_mask.supp_mcs.tx_mcs_map'):
=> 481:3
  + /home/kisskb/slave/src/net/mac80211/main.c: error: initializer
element is not constant:  => 480:3, 481:3, 452:2
  + /home/kisskb/slave/src/net/wireless/util.c: error: case label does
not reduce to an integer constant:  => 459:2, 453:2, 493:2, 476:2

Various powerpc configs

  + error: page_ext.c: undefined reference to `mm_drop_all_locks':  =>
.text+0x1ecb8)
  + error: page_ext.c: undefined reference to `mm_take_all_locks':  =>
.text+0x1ec30)
  + error: zynq-fpga.c: undefined reference to `can_do_mlock':  =>
.text+0x384e1c)
  + error: zynq-fpga.c: undefined reference to
`get_user_pages_remote':  => .text+0x385ed8)

arm-randconfig

> [1] http://kisskb.ellerman.id.au/kisskb/head/10306/ (all 262 configs)
> [3] http://kisskb.ellerman.id.au/kisskb/head/10264/ (all 262 configs)

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 enric.balletbo at collabora.com  Mon May  9 01:39:15 2016
From: enric.balletbo at collabora.com (Enric Balletbo i Serra)
Date: Mon, 09 May 2016 10:39:15 +0200
Subject: [PATCH] ARM: dts: Fix igepv5 audiopwon-gpio
In-Reply-To: <1b37fbdd-67f0-e9e3-d442-bdc0bd74397b@ti.com>
References: <1462474581-13865-1-git-send-email-tony@atomide.com>
 <1b37fbdd-67f0-e9e3-d442-bdc0bd74397b@ti.com>
Message-ID: <57304CB3.5010601@collabora.com>



On 09/05/16 10:34, Peter Ujfalusi wrote:
> On 05/05/16 21:56, Tony Lindgren wrote:
>> Playing audio works on omap5-uevm, but produces an "Unhandled fault:
>> imprecise external abort (0x1406) at 0x00000000" error on igepv5.
>>
>> Looks like the twl6040 audpwron GPIO pin is different for these
>> boards. Let's fix the issue by configuring the audpwron in the
>> board specific dts file.
>>
>> Cc: Agust? Fontquerni <af at iseebcn.com>
>> Cc: Eduard Gavin <egavin at iseebcn.com>
>> Cc: Enric Balletbo i Serra <eballetbo at iseebcn.com>


Hey, can you change the email address for this one

Cc: Enric Balletbo i Serra <eballetbo at gmail.com>

Thanks!

>> Cc: Peter Ujfalusi <peter.ujfalusi at ti.com>
>> Signed-off-by: Tony Lindgren <tony at atomide.com>
>> ---
>>  arch/arm/boot/dts/omap5-board-common.dtsi |  3 ++-
>>  arch/arm/boot/dts/omap5-igep0050.dts      | 10 ++++++++++
>>  arch/arm/boot/dts/omap5-uevm.dts          | 10 ++++++++++
>>  3 files changed, 22 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi
>> index 2eea26c..23b1d7c 100644
>> --- a/arch/arm/boot/dts/omap5-board-common.dtsi
>> +++ b/arch/arm/boot/dts/omap5-board-common.dtsi
>> @@ -642,7 +642,8 @@
>>  		pinctrl-0 = <&twl6040_pins>;
>>  
>>  		interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
>> -		ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
>> +
>> +		/* audpwron gpio defined in the board specific dts */
>>  
>>  		vio-supply = <&smps7_reg>;
>>  		v2v1-supply = <&smps9_reg>;
>> diff --git a/arch/arm/boot/dts/omap5-igep0050.dts b/arch/arm/boot/dts/omap5-igep0050.dts
>> index 72ff6a4..673cdfa 100644
>> --- a/arch/arm/boot/dts/omap5-igep0050.dts
>> +++ b/arch/arm/boot/dts/omap5-igep0050.dts
>> @@ -58,3 +58,13 @@
>>  		<&gpio7 3 0>;		/* 195, SDA */
>>  };
>>  
>> +&twl6040 {
>> +	ti,audpwron-gpio = <&gpio5 16 GPIO_ACTIVE_HIGH>;  /* gpio line 144 */
> 
> BTW: how do you know that gpio144 is used as audpwron GPIO on igepv5?
> 
>> +};
>> +
>> +&twl6040_pins {
>> +	pinctrl-single,pins = <
>> +		OMAP5_IOPAD(0x1c4, PIN_OUTPUT | MUX_MODE6)	/* mcspi1_somi.gpio5_144 */
>> +		OMAP5_IOPAD(0x1ca, PIN_OUTPUT | MUX_MODE6)	/* perslimbus2_clock.gpio5_145 */
> 
> What does the gpio145 is used for?
> 
>> +	>;
>> +};
>> diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts
>> index 60b3fbb..a51e605 100644
>> --- a/arch/arm/boot/dts/omap5-uevm.dts
>> +++ b/arch/arm/boot/dts/omap5-uevm.dts
>> @@ -51,3 +51,13 @@
>>  		<&gpio9 1 GPIO_ACTIVE_HIGH>,	/* TCA6424A P00, LS OE */
>>  		<&gpio7 1 GPIO_ACTIVE_HIGH>;	/* GPIO 193, HPD */
>>  };
>> +
>> +&twl6040 {
>> +	ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
>> +};
>> +
>> +&twl6040_pins {
>> +	pinctrl-single,pins = <
>> +		OMAP5_IOPAD(0x1be, PIN_OUTPUT | MUX_MODE6)	/* mcspi1_somi.gpio5_141 */
>> +	>;
>> +};
>>
> 
> 


From andre.przywara at arm.com  Mon May  9 01:53:11 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 9 May 2016 09:53:11 +0100
Subject: Reverting ARCH_SUNXI arm64 support(?)
Message-ID: <57304FF7.3080909@arm.com>

Hi Will, Catalin,

Suzuki reported a build failure with certain (non-defconfig) .configs
due to the new ARCH_SUNXI support in 4.6-rc [1].
As unfortunately we couldn't agree on a solution and also the support
for the A64/Pine64 is partial in 4.6 anyway, can you please revert:
ce3dd55b99b151a90ac1701c6825f2ae2d49b54e ("arm64: Introduce Allwinner
SoC config option")
So with this revert we have the arm64 defconfig now selecting useless
symbols, it didn't complain, but I was wondering if we should revert the
defconfig patch as well then? But this looks like pain :-(

If all this reverting is too much due to conflicts, we might think about
going with Suzuki's original one-liner [1], which would be an easy fix -
though Olof opposed it back then (in favour of a more involved solution,
which is no option for 4.6 anymore).

Regardless of this the plan for the future would be:
1) Send a patch to properly express the dependencies for the sunxi IRQ
controllers - this is independent from the arm64 support. I will do this
ASAP in hope that it still reaches 4.7.
2) Investigate whether Maxime's new sunxi clock architecture[2] would be
a fit for the A64 support.
3) Use the next weeks to rework the support patches and aim for a 4.8-rc
merge - depending on the outcome and merge status of 2)

Thoughts?

Cheers,
Andre.

[1]
http://lists.infradead.org/pipermail/linux-arm-kernel/2016-March/418175.html
   with the thread continuing here:
http://lists.infradead.org/pipermail/linux-arm-kernel/2016-April/420326.html

[2]
http://lists.infradead.org/pipermail/linux-arm-kernel/2016-May/427839.html


From tiwai at suse.de  Mon May  9 02:04:15 2016
From: tiwai at suse.de (Takashi Iwai)
Date: Mon, 09 May 2016 11:04:15 +0200
Subject: [RFC PATCH 0/7] AC97 device/driver model revamp
In-Reply-To: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
Message-ID: <s5hlh3j8uwg.wl-tiwai@suse.de>

On Sat, 30 Apr 2016 23:15:32 +0200,
Robert Jarzmik wrote:
> 
> It all started in the pxa device-tree submission here :
>    https://lkml.org/lkml/2016/2/25/965
> It will be maintained in :
>    git fetch https://github.com/rjarzmik/linux.git work/ac97
> 
> And now it transformed into this RFC, which would bring a ground for AC'97
> devices closer to the linux device/driver model.
> 
> This is just an RFC to see if we understand each other Mark.
> 
> Amongst the driving ideas behind this RFC :
>  - use device/driver model for AC'97
>    device/driver binding is based on vendor_id{1,2}
>  - use auto-probe of the AC'97 bus to enumerate codecs and create devices
>  - be compatible with previous platform_data model for codecs
>    => this enables a smooth transition, where a codec (here wm9713) can
>       be used either through platform_device or automatic discovery
>  - struct snd_ac97 is not used
>    This structure is really heavy, and doesn't represent an AC97 device, but
>    rather an AC'97 codec internals IIUC.
>    I think it's right place would be in include/sound/ac97/codec.h.
>    This is also a problem for regmap adherence, hence the
>    include/sound/ac97/compat.h.
>  - a new AC'97 bus Kconfig is created
>    This was done for a smooth transition ... let's see if it's a good idea.
>  - split the AC'97 into :
>    - the codec
>    - the digital controller
>    - the bus
> 
> Amongst the things that are not all touched yet :
>  - ac97_codec.c
>    The generic AC'97 codec in sound/pci/ac97/ac97_codec.c has really a lot
>    features, which are not at all PCI related. They could be transfered to
>    sound/ac97, without the pci specific field.
>    => this deserves a deep ahead thinking, which I'll do if the current approach
>    is accepted by the communauty.
> 
> The most important patch is 2/7 "ALSA: ac97: add an ac97 bus". This is the main
> evaluation point for the serie, the others are here so that I can test it all.
> 
> Well, this is a long term effort, which might need a complete rewrite according
> to the comments it'll get. Let's expose it for comments and see how I can
> progress with it.

I think it's good in general.  The implementation looks fairly simple
and thin enough.

An open question is whether migrating the former AC97 layer into the
new bus.  I'm not sure about this.  Transition to a new layer always
brings subtle bugs, especially when the target devices are in wide
range of legacy ones...   If any, we should start just wrapping via
the new bus ops.

Some other nitpicks:
- We usually use snd_ prefix for sound stuff.  Better to keep this for
  exported symbols at least.

- I don't see much value in the usefulness of compat_* stuff.
  For example, it doesn't cover the actual reset procedure or such
  done as in the old ac97 code.  So it won't work compatibly.  If it's
  a few lines of changes, the direct call would be likely simpler in
  the end.

- The order of patches needs reconsideration.  The current patchset
  will break the build, as the hook to sound/ac97/* is done in the
  last patch, while you're already building against to the new stuff
  beforehand.


I'll comment more on each patch if any...


thanks,

Takashi


From will.deacon at arm.com  Mon May  9 02:09:52 2016
From: will.deacon at arm.com (Will Deacon)
Date: Mon, 9 May 2016 10:09:52 +0100
Subject: Reverting ARCH_SUNXI arm64 support(?)
In-Reply-To: <57304FF7.3080909@arm.com>
References: <57304FF7.3080909@arm.com>
Message-ID: <20160509090951.GC19763@arm.com>

On Mon, May 09, 2016 at 09:53:11AM +0100, Andre Przywara wrote:
> Hi Will, Catalin,

Hi Andre,

> Suzuki reported a build failure with certain (non-defconfig) .configs
> due to the new ARCH_SUNXI support in 4.6-rc [1].
> As unfortunately we couldn't agree on a solution and also the support
> for the A64/Pine64 is partial in 4.6 anyway, can you please revert:
> ce3dd55b99b151a90ac1701c6825f2ae2d49b54e ("arm64: Introduce Allwinner
> SoC config option")

Given that we (Catalin and I) didn't commit that patch, it seems weird
that we should be reverting it. Shouldn't this be handled in arm-soc or
via the sunxi subtree?

We're also a week from the merge window, so it doesn't seem like a good
time to be hacking at .config/kconfig-related issues.

Will


From b18965 at freescale.com  Mon May  9 02:06:15 2016
From: b18965 at freescale.com (Alison Wang)
Date: Mon, 9 May 2016 17:06:15 +0800
Subject: [PATCH] arm64: dts: Update address-cells and reg properties of cpu
 nodes
Message-ID: <1462784775-11684-1-git-send-email-b18965@freescale.com>

MPIDR_EL1[63:32] value is equal to 0 for the CPUs of the LS1043A and
LS2080A SoCs. The ARM CPU binding allows #address-cells to be set to 1,
since MPIDR_EL1[63:32] bits are not used for CPUs identification. Update
the #address-cells and reg properties accordingly.

Signed-off-by: Alison Wang <alison.wang at nxp.com>
---
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 10 +++++-----
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 18 +++++++++---------
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index de0323b..37614b5 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -51,7 +51,7 @@
 	#size-cells = <2>;
 
 	cpus {
-		#address-cells = <2>;
+		#address-cells = <1>;
 		#size-cells = <0>;
 
 		/*
@@ -63,28 +63,28 @@
 		cpu0: cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a53";
-			reg = <0x0 0x0>;
+			reg = <0x0>;
 			clocks = <&clockgen 1 0>;
 		};
 
 		cpu1: cpu at 1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a53";
-			reg = <0x0 0x1>;
+			reg = <0x1>;
 			clocks = <&clockgen 1 0>;
 		};
 
 		cpu2: cpu at 2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a53";
-			reg = <0x0 0x2>;
+			reg = <0x2>;
 			clocks = <&clockgen 1 0>;
 		};
 
 		cpu3: cpu at 3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a53";
-			reg = <0x0 0x3>;
+			reg = <0x3>;
 			clocks = <&clockgen 1 0>;
 		};
 	};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index 3187c82..25ff4a8 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -51,7 +51,7 @@
 	#size-cells = <2>;
 
 	cpus {
-		#address-cells = <2>;
+		#address-cells = <1>;
 		#size-cells = <0>;
 
 		/*
@@ -65,56 +65,56 @@
 		cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
-			reg = <0x0 0x0>;
+			reg = <0x0>;
 			clocks = <&clockgen 1 0>;
 		};
 
 		cpu at 1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
-			reg = <0x0 0x1>;
+			reg = <0x1>;
 			clocks = <&clockgen 1 0>;
 		};
 
 		cpu at 100 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
-			reg = <0x0 0x100>;
+			reg = <0x100>;
 			clocks = <&clockgen 1 1>;
 		};
 
 		cpu at 101 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
-			reg = <0x0 0x101>;
+			reg = <0x101>;
 			clocks = <&clockgen 1 1>;
 		};
 
 		cpu at 200 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
-			reg = <0x0 0x200>;
+			reg = <0x200>;
 			clocks = <&clockgen 1 2>;
 		};
 
 		cpu at 201 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
-			reg = <0x0 0x201>;
+			reg = <0x201>;
 			clocks = <&clockgen 1 2>;
 		};
 
 		cpu at 300 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
-			reg = <0x0 0x300>;
+			reg = <0x300>;
 			clocks = <&clockgen 1 3>;
 		};
 
 		cpu at 301 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
-			reg = <0x0 0x301>;
+			reg = <0x301>;
 			clocks = <&clockgen 1 3>;
 		};
 	};
-- 
2.1.0.27.g96db324



From tiwai at suse.de  Mon May  9 02:31:52 2016
From: tiwai at suse.de (Takashi Iwai)
Date: Mon, 09 May 2016 11:31:52 +0200
Subject: [RFC PATCH 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
Message-ID: <s5hk2j38tmf.wl-tiwai@suse.de>

On Sat, 30 Apr 2016 23:15:34 +0200,
Robert Jarzmik wrote:
> 
> diff --git a/include/sound/ac97/codec.h b/include/sound/ac97/codec.h
> new file mode 100644
> index 000000000000..4b8b3e570892
> --- /dev/null
> +++ b/include/sound/ac97/codec.h
> @@ -0,0 +1,98 @@
> +/*
> + *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
> + *
> + * 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.
> + */
> +#ifndef AC97_CODEC_H
> +#define AC97_CODEC_H

Let's be careful about the choice of the guard.


> +
> +#include <linux/device.h>
> +
> +#define AC97_ID(vendor_id1, vendor_id2) \
> +	(((vendor_id1 & 0xffff) << 16) | (vendor_id2 & 0xffff))
> +#define AC97_DRIVER_ID(vendor_id1, vendor_id2, mask_id1, mask_id2, _data) \
> +	{ .id = ((vendor_id1 & 0xffff) << 16) | (vendor_id2 & 0xffff), \
> +	  .mask = ((mask_id1 & 0xffff) << 16) | (mask_id2 & 0xffff), \
> +	  .data = _data }

Give parentheses around the macro arguments.


> +
> +#define to_ac97_device(d) container_of(d, struct ac97_codec_device, dev)
> +#define to_ac97_driver(d) container_of(d, struct ac97_codec_driver, driver)
> +
> +struct ac97_controller;
> +
> +/**
> + * struct ac97_id - matches a codec device and driver on an ac97 bus
> + * @id: The significant bits if the codec vendor ID1 and ID2
> + * @mask: Bitmask specifying which bits of the id field are significant when
> + *	  matching. A driver binds to a device when :
> + *        ((vendorID1 << 8 | vendorID2) & (mask_id1 << 8 | mask_id2)) == id.
> + * @data: Private data used by the driver.
> + */
> +struct ac97_id {
> +	unsigned int		id;
> +	unsigned int		mask;
> +	void			*data;
> +};
> +
> +/**
> + * ac97_codec_device - a ac97 codec
> + * @dev: the code device
> + * @vendor_id: the vendor_id of the codec, as sensed on the AC-link
> + * @num: the codec number, 0 is primary, 1 is first slave, etc ...
> + * @ac97_ctrl: ac97 digital controller on the same AC-link
> + *
> + * This is the device instanciated for each codec living on a AC-link. There are
> + * normally 0 to 4 codec devices per AC-link, and all of them are controlled by
> + * an AC97 digital controller.
> + */
> +struct ac97_codec_device {
> +	struct device		dev;	/* Must stay first member */

This doesn't have to be the first element as long as you use container_of().


> +	unsigned int		vendor_id;
> +	unsigned int		num;
> +	struct list_head	list;
> +	struct ac97_controller	*ac97_ctrl;
> +};
> +
> +/**
> + * ac97_codec_driver - a ac97 codec driver
> + * @driver: the device driver structure
> + * @probe: the function called when a ac97_codec_device is matched
> + * @remove: the function called when the device is unbound/removed
> + * @suspend: suspend function (might be NULL)
> + * @resume: resume function (might be NULL)
> + * @shutdown: shutdown function (might be NULL)
> + * @id_table: ac97 vendor_id match table, { } member terminated
> + */
> +struct ac97_codec_driver {
> +	struct device_driver	driver;
> +	int			(*probe)(struct ac97_codec_device *);
> +	int			(*remove)(struct ac97_codec_device *);
> +	int			(*suspend)(struct ac97_codec_device *);
> +	int			(*resume)(struct ac97_codec_device *);
> +	void			(*shutdown)(struct ac97_codec_device *);
> +	struct ac97_id		*id_table;

Missing const?

> +};
> +
> +int ac97_codec_driver_register(struct ac97_codec_driver *drv);
> +void ac97_codec_driver_unregister(struct ac97_codec_driver *drv);
> +
> +static inline struct device *
> +ac97_codec_dev2dev(const struct ac97_codec_device *adev)
> +{
> +	return (struct device *)(adev);

What's wrong with the simple &adev->dev ?  Cast looks scary.

> +}
> +
> +static inline void *ac97_get_drvdata(const struct ac97_codec_device *adev)
> +{
> +	return dev_get_drvdata(ac97_codec_dev2dev(adev));
> +}
> +
> +static inline void ac97_set_drvdata(const struct ac97_codec_device *adev,
> +				    void *data)
> +{
> +	dev_set_drvdata(ac97_codec_dev2dev(adev), data);
> +}
> +
> +#endif
> diff --git a/include/sound/ac97/compat.h b/include/sound/ac97/compat.h
> new file mode 100644
> index 000000000000..bf611f572f2d
> --- /dev/null
> +++ b/include/sound/ac97/compat.h
> @@ -0,0 +1,21 @@
> +/*
> + *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This file is for backward compatibility with snd_ac97 structure and its
> + * multiple usages, such as the snd_ac97_bus and snd_ac97_build_ops.
> + *
> + */
> +#ifndef AC97_COMPAT_H
> +#define AC97_COMPAT_H
> +
> +#include <sound/ac97_codec.h>
> +#include <sound/soc.h>
> +
> +struct snd_ac97 *compat_alloc_snd_ac97_codec(struct snd_soc_codec *codec);
> +void compat_release_snd_ac97_codec(struct snd_ac97 *ac97);
> +
> +#endif
> diff --git a/include/sound/ac97/controller.h b/include/sound/ac97/controller.h
> new file mode 100644
> index 000000000000..f1e5e645f5ef
> --- /dev/null
> +++ b/include/sound/ac97/controller.h
> @@ -0,0 +1,39 @@
> +/*
> + *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
> + *
> + * 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.
> + */
> +#ifndef AC97_CONTROLLER_H
> +#define AC97_CONTROLLER_H
> +
> +#include <linux/list.h>
> +
> +struct device;
> +struct ac97_codec_device;
> +
> +struct ac97_controller_ops {
> +	void (*reset)(struct ac97_codec_device *ac97);
> +	void (*warm_reset)(struct ac97_codec_device *ac97);
> +	int (*write)(struct ac97_codec_device *ac97, unsigned short reg,
> +		     unsigned short val);
> +	int (*read)(struct ac97_codec_device *ac97, unsigned short reg);
> +	void (*wait)(struct ac97_codec_device *ac97);
> +	void (*init)(struct ac97_codec_device *ac97);
> +};
> +
> +struct ac97_controller {
> +	const struct ac97_controller_ops *ops;
> +	struct list_head controllers;
> +	struct device *dev;
> +	int bus_idx;

What is this bus_idx for?


> +	int bound_codecs;
> +	struct list_head codecs;
> +};
> +
> +int ac97_digital_controller_register(const struct ac97_controller_ops *ops,
> +				     struct device *dev);
> +int ac97_digital_controller_unregister(const struct device *dev);
> +
> +#endif
> diff --git a/sound/ac97/Kconfig b/sound/ac97/Kconfig
> new file mode 100644
> index 000000000000..fd2c2d031e62
> --- /dev/null
> +++ b/sound/ac97/Kconfig
> @@ -0,0 +1,9 @@
> +#
> +# PCI configuration
> +#
 
Still only for PCI? :)


> +
> +config AC97
> +	bool "AC97 bus"
> +	help
> +	   Say Y here if you want to have AC97 devices, which are sound oriented
> +	   devices around an AC-Link.
> diff --git a/sound/ac97/Makefile b/sound/ac97/Makefile
> new file mode 100644
> index 000000000000..5575909d46e2
> --- /dev/null
> +++ b/sound/ac97/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# make for AC97 bus drivers
> +#
> +
> +obj-y	+= bus.o codec.o snd_ac97_compat.o

No possibility for modules?


> diff --git a/sound/ac97/ac97_core.h b/sound/ac97/ac97_core.h
> new file mode 100644
> index 000000000000..db6e27288357
> --- /dev/null
> +++ b/sound/ac97/ac97_core.h
> @@ -0,0 +1,10 @@
> +/*
> + * Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
> + *
> + * 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.
> + */
> +
> +unsigned int ac97_bus_scan_one(struct ac97_controller *ac97,
> +			       int codec_num);
> diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
> new file mode 100644
> index 000000000000..f9bf5632d4aa
> --- /dev/null
> +++ b/sound/ac97/bus.c
> @@ -0,0 +1,330 @@
> +/*
> + * Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
> + *
> + * 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/module.h>
> +#include <linux/device.h>
> +#include <linux/list.h>
> +#include <linux/mutex.h>
> +#include <linux/pm.h>
> +#include <linux/slab.h>
> +#include <sound/ac97/codec.h>
> +#include <sound/ac97/controller.h>
> +#include <sound/ac97/regs.h>
> +
> +#define AC97_BUS_MAX_CODECS 4
> +
> +/*
> + * Protects ac97_controllers and each ac97_controller structure.
> + */
> +static DEFINE_MUTEX(ac97_controllers_mutex);
> +static LIST_HEAD(ac97_controllers);
> +static int ac97_bus_idx;
> +
> +struct bus_type ac97_bus_type;
> +
> +static struct ac97_codec_device *
> +ac97_codec_find(struct ac97_controller *ac97_ctrl, int codec_num)
> +{
> +	struct ac97_codec_device *codec;
> +
> +	list_for_each_entry(codec, &ac97_ctrl->codecs, list)
> +		if (codec->num == codec_num)
> +			return codec;
> +
> +	return NULL;
> +}

It's a question whether we need to manage the codecs in the linked
list.  There can be at most 4 codecs, so it fits in an array well,
too.  Then some codes like this would be simpler. (And it'll even
reduce the footprint, too.)


> +
> +static void ac97_codec_release(struct device *dev)
> +{
> +	struct ac97_codec_device *codec;
> +
> +	codec = container_of(dev, struct ac97_codec_device, dev);
> +	list_del(&codec->list);
> +	kfree(codec);
> +}
> +
> +static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx,
> +		   unsigned int vendor_id)
> +{
> +	struct ac97_codec_device *codec;
> +	char *codec_name;
> +	int ret;
> +
> +	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
> +	if (!codec)
> +		return -ENOMEM;
> +
> +	codec->vendor_id = vendor_id;
> +	codec->dev.release = ac97_codec_release;
> +	codec->dev.bus = &ac97_bus_type;
> +	codec->dev.parent = ac97_ctrl->dev;
> +	codec->num = idx;
> +	codec->ac97_ctrl = ac97_ctrl;
> +	INIT_LIST_HEAD(&codec->list);
> +	list_move_tail(&codec->list, &ac97_ctrl->codecs);
> +
> +	codec_name = kasprintf(GFP_KERNEL, "%s:%d", dev_name(ac97_ctrl->dev),
> +			       idx);
> +	codec->dev.init_name = codec_name;
> +
> +	ret = device_register(&codec->dev);
> +	kfree(codec_name);
> +
> +	return ret;
> +}
> +
> +unsigned int ac97_bus_scan_one(struct ac97_controller *ac97,
> +				      int codec_num)
> +{
> +	struct ac97_codec_device codec;
> +	unsigned short vid1, vid2;
> +	int ret;
> +
> +	codec.dev = *ac97->dev;
> +	codec.num = codec_num;
> +	ret = ac97->ops->read(&codec, AC97_VENDOR_ID1);
> +	vid1 = (ret & 0xffff);
> +	if (ret < 0)
> +		return 0;

Hmm.  This looks pretty hackish and dangerous.



> +	ret = ac97->ops->read(&codec, AC97_VENDOR_ID2);
> +	vid2 = (ret & 0xffff);
> +	if (ret < 0)
> +		return 0;
> +
> +	dev_dbg(&codec.dev, "%s(codec_num=%d): vendor_id=0x%08x\n",
> +		__func__, codec_num, AC97_ID(vid1, vid2));
> +	return AC97_ID(vid1, vid2);
> +}
> +
> +static int ac97_bus_scan(struct ac97_controller *ac97_ctrl)
> +{
> +	int ret, i;
> +	unsigned int vendor_id;
> +
> +	for (i = 0; i < AC97_BUS_MAX_CODECS; i++) {
> +		if (ac97_codec_find(ac97_ctrl, i))
> +			continue;
> +		vendor_id = ac97_bus_scan_one(ac97_ctrl, i);
> +		if (!vendor_id)
> +			continue;
> +
> +		ret = ac97_codec_add(ac97_ctrl, i, vendor_id);
> +		if (ret < 0)
> +			return ret;

This is one of concerns: we don't know whether the device really
reacts well if you access to a non-existing slot.  At least, it'd be
safer to have the masks for the devices we already know the slots.


> +	}
> +	return 0;
> +}
> +
> +void ac97_rescan_all_controllers(void)
> +{
> +	struct ac97_controller *ac97_ctrl;
> +	int ret;
> +
> +	mutex_lock(&ac97_controllers_mutex);
> +	list_for_each_entry(ac97_ctrl, &ac97_controllers, controllers) {
> +		ret = ac97_bus_scan(ac97_ctrl);
> +		if (ret)
> +			dev_warn(ac97_ctrl->dev, "scan failed: %d\n", ret);
> +	}
> +	mutex_unlock(&ac97_controllers_mutex);
> +}
> +EXPORT_SYMBOL(ac97_rescan_all_controllers);
> +
> +static int ac97_bus_reset(struct ac97_controller *ac97_ctrl)
> +{
> +	struct ac97_codec_device codec;
> +
> +	memset(&codec, 0, sizeof(codec));
> +	codec.dev = *ac97_ctrl->dev;
> +
> +	ac97_ctrl->ops->reset(&codec);

So, this assumes that reset ops is mandatory?  Then document it at
least.


thanks,

Takashi

> +	return 0;
> +}
> +
> +/**
> + * ac97_codec_driver_register - register an AC97 codec driver
> + * @dev: AC97 driver codec to register
> + *
> + * Register an AC97 codec driver to the ac97 bus driver, aka. the AC97 digital
> + * controller.
> + *
> + * Returns 0 on success or error code
> + */
> +int ac97_codec_driver_register(struct ac97_codec_driver *drv)
> +{
> +	int ret;
> +
> +	drv->driver.bus = &ac97_bus_type;
> +
> +	ret = driver_register(&drv->driver);
> +	if (!ret)
> +		ac97_rescan_all_controllers();
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(ac97_codec_driver_register);
> +
> +/**
> + * ac97_codec_driver_unregister - unregister an AC97 codec driver
> + * @dev: AC97 codec driver to unregister
> + *
> + * Unregister a previously registered ac97 codec driver.
> + */
> +void ac97_codec_driver_unregister(struct ac97_codec_driver *drv)
> +{
> +	driver_unregister(&drv->driver);
> +}
> +EXPORT_SYMBOL(ac97_codec_driver_unregister);
> +
> +static int ac97_dc_codecs_unregister(struct ac97_controller *ac97_ctrl)
> +{
> +	struct ac97_codec_device *codec, *tmp;
> +
> +	list_for_each_entry_safe(codec, tmp, &ac97_ctrl->codecs, list)
> +		put_device(&codec->dev);
> +
> +	return 0;
> +}
> +
> +/**
> + * ac97_digital_controller_register - register an ac97 controller
> + * @ops: the ac97 bus operations
> + * @dev: the device providing the ac97 DC function
> + *
> + * Register a digital controller which can control up to 4 ac97 codecs. This is
> + * the controller side of the AC97 AC-link, while the slave side are the codecs.
> + *
> + * Returns a positive bus index upon success, negative value upon error
> + */
> +int ac97_digital_controller_register(const struct ac97_controller_ops *ops,
> +				     struct device *dev)
> +{
> +	struct ac97_controller *ac97_ctrl;
> +
> +	ac97_ctrl = kzalloc(sizeof(*ac97_ctrl), GFP_KERNEL);
> +	if (!ac97_ctrl)
> +		return -ENOMEM;
> +
> +	mutex_lock(&ac97_controllers_mutex);
> +	ac97_ctrl->ops = ops;
> +	ac97_ctrl->bus_idx = ac97_bus_idx++;
> +	ac97_ctrl->dev = dev;
> +	INIT_LIST_HEAD(&ac97_ctrl->codecs);
> +	list_add(&ac97_ctrl->controllers, &ac97_controllers);
> +	mutex_unlock(&ac97_controllers_mutex);
> +
> +	ac97_bus_reset(ac97_ctrl);
> +	ac97_bus_scan(ac97_ctrl);
> +
> +	return ac97_ctrl->bus_idx;
> +}
> +EXPORT_SYMBOL(ac97_digital_controller_register);
> +
> +/**
> + * ac97_digital_controller_unregister - unregister an ac97 controller
> + * @dev: the device previously provided to ac97_digital_controller_register()
> + *
> + * Returns 0 on success, negative upon error
> + */
> +int ac97_digital_controller_unregister(const struct device *dev)
> +{
> +	struct ac97_controller *ac97_ctrl, *tmp;
> +	int ret = -ENODEV;
> +
> +	mutex_lock(&ac97_controllers_mutex);
> +	list_for_each_entry_safe(ac97_ctrl, tmp, &ac97_controllers,
> +				 controllers) {
> +		if (ac97_ctrl->dev != dev)
> +			continue;
> +		if (ac97_ctrl->bound_codecs)
> +			ret = -EBUSY;
> +		else
> +			ret = ac97_dc_codecs_unregister(ac97_ctrl);
> +		if (!ret)
> +			list_del(&ac97_ctrl->controllers);
> +	}
> +
> +	mutex_unlock(&ac97_controllers_mutex);
> +	return ret;
> +}
> +EXPORT_SYMBOL(ac97_digital_controller_unregister);
> +
> +static const struct dev_pm_ops ac97_pm = {
> +	.suspend	= pm_generic_suspend,
> +	.resume		= pm_generic_resume,
> +	.freeze		= pm_generic_freeze,
> +	.thaw		= pm_generic_thaw,
> +	.poweroff	= pm_generic_poweroff,
> +	.restore	= pm_generic_restore,
> +};
> +
> +static ssize_t vendor_id_show(struct device *dev,
> +			      struct device_attribute *attr, char *buf)
> +{
> +	struct ac97_codec_device *codec = to_ac97_device(dev);
> +
> +	return sprintf(buf, "%08x", codec->vendor_id);
> +}
> +
> +static struct device_attribute ac97_dev_attrs[] = {
> +	__ATTR_RO(vendor_id),
> +	__ATTR_NULL,
> +};
> +
> +int ac97_bus_match(struct device *dev, struct device_driver *drv)
> +{
> +	struct ac97_codec_device *adev = to_ac97_device(dev);
> +	struct ac97_codec_driver *adrv = to_ac97_driver(drv);
> +	struct ac97_id *id = adrv->id_table;
> +
> +	if (adev->vendor_id == 0x0 || adev->vendor_id == 0xffffffff)
> +		return false;
> +
> +	do {
> +		if ((id->id & id->mask) == (adev->vendor_id & id->mask))
> +			return true;
> +	} while (++id->id);
> +
> +	return false;
> +}
> +
> +static int ac97_bus_probe(struct device *dev)
> +{
> +	struct ac97_codec_device *adev = to_ac97_device(dev);
> +	struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
> +
> +	return adrv->probe(adev);
> +}
> +
> +static int ac97_bus_remove(struct device *dev)
> +{
> +	struct ac97_codec_device *adev = to_ac97_device(dev);
> +	struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
> +
> +	return adrv->remove(adev);
> +}
> +
> +struct bus_type ac97_bus_type = {
> +	.name		= "ac97",
> +	.dev_attrs	= ac97_dev_attrs,
> +	.match		= ac97_bus_match,
> +	.pm		= &ac97_pm,
> +	.probe		= ac97_bus_probe,
> +	.remove		= ac97_bus_remove,
> +};
> +EXPORT_SYMBOL(ac97_bus_type);
> +
> +static int __init ac97_bus_init(void)
> +{
> +	return bus_register(&ac97_bus_type);
> +}
> +subsys_initcall(ac97_bus_init);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik at free.fr>");
> diff --git a/sound/ac97/codec.c b/sound/ac97/codec.c
> new file mode 100644
> index 000000000000..a835f03744bf
> --- /dev/null
> +++ b/sound/ac97/codec.c
> @@ -0,0 +1,15 @@
> +/*
> + *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
> + *
> + * 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 <sound/ac97_codec.h>
> +#include <sound/ac97/codec.h>
> +#include <sound/ac97/controller.h>
> +#include <linux/device.h>
> +#include <linux/slab.h>
> +#include <sound/soc.h>	/* For compat_ac97_* */
> +
> diff --git a/sound/ac97/snd_ac97_compat.c b/sound/ac97/snd_ac97_compat.c
> new file mode 100644
> index 000000000000..7e2f01c96fc9
> --- /dev/null
> +++ b/sound/ac97/snd_ac97_compat.c
> @@ -0,0 +1,104 @@
> +/*
> + *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
> + *
> + * 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/list.h>
> +#include <linux/slab.h>
> +#include <sound/ac97/codec.h>
> +#include <sound/ac97/controller.h>
> +#include <sound/soc.h>
> +
> +#include "ac97_core.h"
> +
> +static void compat_ac97_reset(struct snd_ac97 *ac97)
> +{
> +	struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
> +	struct ac97_controller *actrl = adev->ac97_ctrl;
> +
> +	if (actrl->ops->reset)
> +		actrl->ops->reset(adev);
> +}
> +
> +static void compat_ac97_warm_reset(struct snd_ac97 *ac97)
> +{
> +	struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
> +	struct ac97_controller *actrl = adev->ac97_ctrl;
> +
> +	if (actrl->ops->warm_reset)
> +		actrl->ops->warm_reset(adev);
> +}
> +
> +static void compat_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
> +			      unsigned short val)
> +{
> +	struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
> +	struct ac97_controller *actrl = adev->ac97_ctrl;
> +
> +	actrl->ops->write(adev, reg, val);
> +}
> +
> +static unsigned short compat_ac97_read(struct snd_ac97 *ac97,
> +				       unsigned short reg)
> +{
> +	struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
> +	struct ac97_controller *actrl = adev->ac97_ctrl;
> +
> +	return actrl->ops->read(adev, reg);
> +}
> +
> +static struct snd_ac97_bus_ops compat_snd_ac97_bus_ops = {
> +	.reset = compat_ac97_reset,
> +	.warm_reset = compat_ac97_warm_reset,
> +	.write = compat_ac97_write,
> +	.read = compat_ac97_read,
> +};
> +
> +static struct snd_ac97_bus compat_soc_ac97_bus = {
> +	.ops = &compat_snd_ac97_bus_ops,
> +};
> +
> +struct snd_ac97 *compat_alloc_snd_ac97_codec(struct snd_soc_codec *codec)
> +{
> +	struct snd_ac97 *ac97;
> +
> +	ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
> +	if (ac97 == NULL)
> +		return ERR_PTR(-ENOMEM);
> +
> +	ac97->dev = *codec->dev;
> +	ac97->private_data = codec->dev;
> +	ac97->bus = &compat_soc_ac97_bus;
> +	return ac97;
> +}
> +EXPORT_SYMBOL_GPL(compat_alloc_snd_ac97_codec);
> +
> +void compat_release_snd_ac97_codec(struct snd_ac97 *ac97)
> +{
> +	kfree(ac97);
> +}
> +EXPORT_SYMBOL_GPL(compat_release_snd_ac97_codec);
> +
> +int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
> +	unsigned int id_mask)
> +{
> +	struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
> +	struct ac97_controller *actrl = adev->ac97_ctrl;
> +
> +	if (try_warm) {
> +		compat_ac97_warm_reset(ac97);
> +		if (ac97_bus_scan_one(actrl, adev->num) == adev->vendor_id)
> +			return 1;
> +	}
> +
> +	compat_ac97_reset(ac97);
> +	compat_ac97_warm_reset(ac97);
> +	if (ac97_bus_scan_one(actrl, adev->num) == adev->vendor_id)
> +		return 0;
> +
> +	return -ENODEV;
> +}
> +EXPORT_SYMBOL_GPL(snd_ac97_reset);
> -- 
> 2.1.4
> 
> 


From will.deacon at arm.com  Mon May  9 02:35:41 2016
From: will.deacon at arm.com (Will Deacon)
Date: Mon, 9 May 2016 10:35:41 +0100
Subject: [PATCH 2/2] iommu/io-pgtable-arm: use
 __dma_sync_single_for_device()
In-Reply-To: <1462705196-10857-3-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462705196-10857-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <1462705196-10857-3-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <20160509093540.GF19763@arm.com>

On Sun, May 08, 2016 at 12:59:56PM +0200, Niklas S?derlund wrote:
> The call to dma_sync_single_for_device() can be reached from
> dma_map_single(). If CONFIG_DMA_API_DEBUG is enabled this would result
> in a check that the mapping being synced is valid. Since the call to
> dma_map_single is not yet completed the mapping is not recorded in
> dma-debug and the check fails and a warning is printed. Avoid this
> warning by calling __dma_sync_single_for_device() which don't preform
> this check.

Hmm, I don't understand why this would trigger that warning. The memory
being sync'd here is the page table memory, not the buffer being mapped.
The page table memory is "mapped" using dma_map_single in
__arm_lpae_alloc_pages, so it sounds like the issue something else.

Will


From robin.murphy at arm.com  Mon May  9 02:37:15 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Mon, 9 May 2016 10:37:15 +0100
Subject: [PATCH 0/2] Fix incorrect warning from dma-debug
In-Reply-To: <1462705196-10857-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462705196-10857-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <57305A4B.70401@arm.com>

Hi Niklas,

On 08/05/16 11:59, Niklas S?derlund wrote:
> Hi,
>
> While using CONFIG_DMA_API_DEBUG i came across this warning which I
> think is a false positive. As shown dma_sync_single_for_device() are
> called from the dma_map_single() call path. This triggers the warning
> since the dma-debug code have not yet been made aware of the mapping.

Almost right ;) The thing being mapped (the SPI device's buffer) and the 
thing being synced (the IOMMU's PTE) are entirely unrelated. Due to the 
current of_iommu_init() setup, the IOMMU is probed long before 
dma_debug_init() gets called, therefore DMA debug is missing entries for 
some of the initial page table mappings and gets confused when we update 
them later.

> I try to solve this by introducing __dma_sync_single_for_device() which
> do not call into the dma-debug code. I'm no expert and this might be a
> bad way of solving the problem but it allowed me to keep working.

The simple fix should be to just call dma_debug_init() from a 
sufficiently earlier initcall level. The best would be to sort out a 
proper device dependency order to avoid the whole early-IOMMU-creation 
thing entirely.

Robin.

> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 1 at lib/dma-debug.c:1209 check_sync+0x154/0x5e4
> ipmmu-vmsa e6740000.mmu: DMA-API: device driver tries to sync DMA memory it has not allocated [device address=0x000000006e89b008] [size=8 bytes]
> CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.6.0-rc5-00012-g52e78c1-dirty #1
> Hardware name: Generic R8A7791 (Flattened Device Tree)
> Backtrace:
> [<c020a0a4>] (dump_backtrace) from [<c020a250>] (show_stack+0x18/0x1c)
>   r7:c03ebad0 r6:00000009 r5:60000093 r4:00000000
> [<c020a238>] (show_stack) from [<c03cb7e4>] (dump_stack+0x84/0xa4)
> [<c03cb760>] (dump_stack) from [<c021e3ac>] (__warn+0xd0/0x100)
>   r5:00000000 r4:ef05dac8
> [<c021e2dc>] (__warn) from [<c021e41c>] (warn_slowpath_fmt+0x40/0x48)
>   r9:00010000 r8:00000000 r7:c0c69c40 r6:c0c02754 r5:ef05db78 r4:ef222810
> [<c021e3e0>] (warn_slowpath_fmt) from [<c03ebad0>] (check_sync+0x154/0x5e4)
>   r3:c0945b6f r2:c0936e85
> [<c03eb97c>] (check_sync) from [<c03ed594>] (debug_dma_sync_single_for_device+0x64/0x70)
>   r10:00000009 r9:0000000c r8:ee89b008 r7:00000000 r6:6e89b008 r5:00000000
>   r4:6e89b008
> [<c03ed530>] (debug_dma_sync_single_for_device) from [<c0465298>] (__arm_lpae_set_pte.part.0+0x80/0x8c)
>   r5:00000001 r4:ef222810
> [<c0465218>] (__arm_lpae_set_pte.part.0) from [<c046553c>] (__arm_lpae_map+0x298/0x2f0)
>   r7:00000008 r6:ef25e000 r4:ee898500
> [<c04652a4>] (__arm_lpae_map) from [<c0465b18>] (arm_lpae_map+0xcc/0xe4)
>   r10:c0465f40 r9:00001000 r8:40000000 r7:00000000 r6:6f25c000 r5:00000000
>   r4:000008c0
> [<c0465a4c>] (arm_lpae_map) from [<c0465f78>] (ipmmu_map+0x38/0x40)
>   r7:40000000 r6:00000000 r5:00001000 r4:c0465a4c
> [<c0465f40>] (ipmmu_map) from [<c0463d90>] (iommu_map+0xf8/0x15c)
>   r4:ee895608
> [<c0463c98>] (iommu_map) from [<c0213524>] (arm_coherent_iommu_map_page+0x1d4/0x2d4)
>   r10:ef386940 r9:00001000 r8:00000000 r7:00000000 r6:40000000 r5:00000000
>   r4:00000000
> [<c0213350>] (arm_coherent_iommu_map_page) from [<c0213690>] (arm_iommu_map_page+0x6c/0x74)
>   r10:c0c61f44 r9:ef19d210 r8:00000001 r7:00001000 r6:00000000 r5:ec5ddb80
>   r4:00000000
> [<c0213624>] (arm_iommu_map_page) from [<c04f7d64>] (sh_msiof_spi_probe+0x430/0x7b0)
>   r9:00000000 r8:c0213624 r7:ef19d210 r6:ef242800 r5:ef1b4010 r4:ef242af0
> [<c04f7934>] (sh_msiof_spi_probe) from [<c049fd3c>] (platform_drv_probe+0x58/0xa8)
>   r10:00000000 r9:00000000 r8:c0c1f8d4 r7:c0c7e910 r6:c0c1f8d4 r5:ef1b4010
>   r4:c04f7934
> [<c049fce4>] (platform_drv_probe) from [<c049e788>] (driver_probe_device+0x13c/0x2a4)
>   r7:c0c7e910 r6:00000000 r5:c0c7e900 r4:ef1b4010
> [<c049e64c>] (driver_probe_device) from [<c049e978>] (__driver_attach+0x88/0xac)
>   r9:c0c34000 r8:c0a3c010 r7:c0c1cf08 r6:c0c1f8d4 r5:ef1b4044 r4:ef1b4010
> [<c049e8f0>] (__driver_attach) from [<c049ce44>] (bus_for_each_dev+0x74/0x98)
>   r7:c0c1cf08 r6:c049e8f0 r5:c0c1f8d4 r4:00000000
> [<c049cdd0>] (bus_for_each_dev) from [<c049ebd0>] (driver_attach+0x20/0x28)
>   r6:ef1cc200 r5:00000000 r4:c0c1f8d4
> [<c049ebb0>] (driver_attach) from [<c049d5d8>] (bus_add_driver+0xd4/0x1e4)
> [<c049d504>] (bus_add_driver) from [<c049f2dc>] (driver_register+0xa4/0xe8)
>   r7:c0a3c010 r6:00000000 r5:c0a1e400 r4:c0c1f8d4
> [<c049f238>] (driver_register) from [<c04a0778>] (__platform_driver_register+0x38/0x4c)
>   r5:c0a1e400 r4:ee958fc0
> [<c04a0740>] (__platform_driver_register) from [<c0a1e418>] (sh_msiof_spi_drv_init+0x18/0x20)
> [<c0a1e400>] (sh_msiof_spi_drv_init) from [<c0a00e1c>] (do_one_initcall+0x10c/0x1c0)
> [<c0a00d10>] (do_one_initcall) from [<c0a00ff8>] (kernel_init_freeable+0x128/0x1f4)
>   r9:c0c34000 r8:c0c34000 r7:c0a47e60 r6:c0a3c83c r5:000000bd r4:00000006
> [<c0a00ed0>] (kernel_init_freeable) from [<c071067c>] (kernel_init+0x10/0x118)
>   r9:00000000[    1.879529] ata1: link resume succeeded after 1 retries
>   r8:00000000 r7:00000000 r6:00000000 r5:c071066c r4:00000000
> [<c071066c>] (kernel_init) from [<c0206e08>] (ret_from_fork+0x14/0x2c)
>   r5:c071066c r4:00000000
> ---[ end trace 6eb9a3df3009d491 ]---
>
> Niklas S?derlund (2):
>    dma-mapping: add __dma_sync_single_for_device()
>    iommu/io-pgtable-arm: use __dma_sync_single_for_device()
>
>   drivers/iommu/io-pgtable-arm.c | 2 +-
>   include/linux/dma-mapping.h    | 9 ++++++++-
>   2 files changed, 9 insertions(+), 2 deletions(-)
>
> --
> 2.8.2
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>



From oliver at schinagl.nl  Mon May  9 02:53:16 2016
From: oliver at schinagl.nl (Olliver Schinagl)
Date: Mon, 9 May 2016 11:53:16 +0200
Subject: [PATCHv4] ARM: dts: sunxi: Add a olinuxino-lime2-emmc
In-Reply-To: <20160508180941.GC6167@lukather>
References: <1462439332-26215-1-git-send-email-oliver@schinagl.nl>
 <20160508180941.GC6167@lukather>
Message-ID: <57305E0C.8040304@schinagl.nl>

Hey Maxime,

On 08-05-16 20:09, Maxime Ripard wrote:
> On Thu, May 05, 2016 at 11:08:52AM +0200, Olliver Schinagl wrote:
>> There are 3 kinds of OLinuXino Lime2 boards.
>> One without any on board storage, one with NAND storage and one with
>> eMMC storage. This patch adds the eMMC variant of boards.
>>
>> eMMC storage is different from a regular SD card in that it is soldered
>> on the board and cannot be changed. Additionally, it shares pins with
>> the NAND module and with the second SPI port.
>>
>> Changeslog:
>>
>> v4:
>>    Add board compatibles
>>
>> v3:
>>    Add pwr-seq-emmc with the reset gpio
>>
>> v2:
>>    Remove unsupported no-1.8-v property, add vqmmc property
>>
>> v1:
>>    Initial bare bone version
> This is not something we want in the commit log. This should go below
> the --- so that it's dropped when applied.
Sorry about that, I didn't know the --- trick. ChenYu reminded of it 
however, so that'll go into my toolblox.
>
> Removed and applied.
Thanks for fixing it, much appreciated :)
>
> Thanks,
> Maxime
>



From linus.walleij at linaro.org  Mon May  9 02:59:32 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 9 May 2016 11:59:32 +0200
Subject: [PATCH 1/2] pinctrl: nomadik: hide nmk_gpio_get_mode when unused
In-Reply-To: <1462289221-861102-1-git-send-email-arnd@arndb.de>
References: <1462289221-861102-1-git-send-email-arnd@arndb.de>
Message-ID: <CACRpkdaYkALuRLZ2LU-o-H97rvTLdCmqQf8Zs6sy-tjamuunnA@mail.gmail.com>

On Tue, May 3, 2016 at 5:26 PM, Arnd Bergmann <arnd at arndb.de> wrote:

> nmk_gpio_get_mode is only used in one place, and that is conditionally
> compiled if DEBUG_FS is enabled. A recent cleanup has marked the
> definition 'static', which now leads to a warning:
>
> drivers/pinctrl/nomadik/pinctrl-nomadik.c:614:12: error: 'nmk_gpio_get_mode' defined but not used [-Werror=unused-function]
>  static int nmk_gpio_get_mode(struct nmk_gpio_chip *nmk_chip, int offset)
>             ^~~~~~~~~~~~~~~~~
>
> Moving the function itself inside the #ifdef shuts it up again.
>
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Fixes: 5e81e0a0913c ("pinctrl: nomadik: use BIT() with offsets consequently")

Patch applied!

Yours,
Linus Walleij


From robin.murphy at arm.com  Mon May  9 03:00:56 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Mon, 9 May 2016 11:00:56 +0100
Subject: [PATCH 0/2] Fix incorrect warning from dma-debug
In-Reply-To: <57305A4B.70401@arm.com>
References: <1462705196-10857-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <57305A4B.70401@arm.com>
Message-ID: <57305FD8.7070006@arm.com>

On 09/05/16 10:37, Robin Murphy wrote:
> Hi Niklas,
>
> On 08/05/16 11:59, Niklas S?derlund wrote:
>> Hi,
>>
>> While using CONFIG_DMA_API_DEBUG i came across this warning which I
>> think is a false positive. As shown dma_sync_single_for_device() are
>> called from the dma_map_single() call path. This triggers the warning
>> since the dma-debug code have not yet been made aware of the mapping.
>
> Almost right ;) The thing being mapped (the SPI device's buffer) and the
> thing being synced (the IOMMU's PTE) are entirely unrelated. Due to the
> current of_iommu_init() setup, the IOMMU is probed long before
> dma_debug_init() gets called, therefore DMA debug is missing entries for
> some of the initial page table mappings and gets confused when we update
> them later.
>
>> I try to solve this by introducing __dma_sync_single_for_device() which
>> do not call into the dma-debug code. I'm no expert and this might be a
>> bad way of solving the problem but it allowed me to keep working.
>
> The simple fix should be to just call dma_debug_init() from a
> sufficiently earlier initcall level. The best would be to sort out a
> proper device dependency order to avoid the whole early-IOMMU-creation
> thing entirely.

A tangential idea, as Will just suggested to me, would be to make this 
false-positive situation more explicit, something like (untested):
---8<---
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 4a1515f4b452..e16684a4ce86 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -107,7 +107,8 @@ static bool dma_debug_initialized __read_mostly;

  static inline bool dma_debug_disabled(void)
  {
-	return global_disable || !dma_debug_initialized;
+	return global_disable || WARN_ONCE(!dma_debug_initialized,
+					   "early DMA-API call not tracked");
  }

  /* Global error count */
--->8---

but it seems like this a sufficiently rare case that it's probably not 
worth cluttering up the code for.

Robin.

>> ------------[ cut here ]------------
>> WARNING: CPU: 0 PID: 1 at lib/dma-debug.c:1209 check_sync+0x154/0x5e4
>> ipmmu-vmsa e6740000.mmu: DMA-API: device driver tries to sync DMA
>> memory it has not allocated [device address=0x000000006e89b008]
>> [size=8 bytes]
>> CPU: 0 PID: 1 Comm: swapper/0 Not tainted
>> 4.6.0-rc5-00012-g52e78c1-dirty #1
>> Hardware name: Generic R8A7791 (Flattened Device Tree)
>> Backtrace:
>> [<c020a0a4>] (dump_backtrace) from [<c020a250>] (show_stack+0x18/0x1c)
>>   r7:c03ebad0 r6:00000009 r5:60000093 r4:00000000
>> [<c020a238>] (show_stack) from [<c03cb7e4>] (dump_stack+0x84/0xa4)
>> [<c03cb760>] (dump_stack) from [<c021e3ac>] (__warn+0xd0/0x100)
>>   r5:00000000 r4:ef05dac8
>> [<c021e2dc>] (__warn) from [<c021e41c>] (warn_slowpath_fmt+0x40/0x48)
>>   r9:00010000 r8:00000000 r7:c0c69c40 r6:c0c02754 r5:ef05db78 r4:ef222810
>> [<c021e3e0>] (warn_slowpath_fmt) from [<c03ebad0>]
>> (check_sync+0x154/0x5e4)
>>   r3:c0945b6f r2:c0936e85
>> [<c03eb97c>] (check_sync) from [<c03ed594>]
>> (debug_dma_sync_single_for_device+0x64/0x70)
>>   r10:00000009 r9:0000000c r8:ee89b008 r7:00000000 r6:6e89b008
>> r5:00000000
>>   r4:6e89b008
>> [<c03ed530>] (debug_dma_sync_single_for_device) from [<c0465298>]
>> (__arm_lpae_set_pte.part.0+0x80/0x8c)
>>   r5:00000001 r4:ef222810
>> [<c0465218>] (__arm_lpae_set_pte.part.0) from [<c046553c>]
>> (__arm_lpae_map+0x298/0x2f0)
>>   r7:00000008 r6:ef25e000 r4:ee898500
>> [<c04652a4>] (__arm_lpae_map) from [<c0465b18>] (arm_lpae_map+0xcc/0xe4)
>>   r10:c0465f40 r9:00001000 r8:40000000 r7:00000000 r6:6f25c000
>> r5:00000000
>>   r4:000008c0
>> [<c0465a4c>] (arm_lpae_map) from [<c0465f78>] (ipmmu_map+0x38/0x40)
>>   r7:40000000 r6:00000000 r5:00001000 r4:c0465a4c
>> [<c0465f40>] (ipmmu_map) from [<c0463d90>] (iommu_map+0xf8/0x15c)
>>   r4:ee895608
>> [<c0463c98>] (iommu_map) from [<c0213524>]
>> (arm_coherent_iommu_map_page+0x1d4/0x2d4)
>>   r10:ef386940 r9:00001000 r8:00000000 r7:00000000 r6:40000000
>> r5:00000000
>>   r4:00000000
>> [<c0213350>] (arm_coherent_iommu_map_page) from [<c0213690>]
>> (arm_iommu_map_page+0x6c/0x74)
>>   r10:c0c61f44 r9:ef19d210 r8:00000001 r7:00001000 r6:00000000
>> r5:ec5ddb80
>>   r4:00000000
>> [<c0213624>] (arm_iommu_map_page) from [<c04f7d64>]
>> (sh_msiof_spi_probe+0x430/0x7b0)
>>   r9:00000000 r8:c0213624 r7:ef19d210 r6:ef242800 r5:ef1b4010 r4:ef242af0
>> [<c04f7934>] (sh_msiof_spi_probe) from [<c049fd3c>]
>> (platform_drv_probe+0x58/0xa8)
>>   r10:00000000 r9:00000000 r8:c0c1f8d4 r7:c0c7e910 r6:c0c1f8d4
>> r5:ef1b4010
>>   r4:c04f7934
>> [<c049fce4>] (platform_drv_probe) from [<c049e788>]
>> (driver_probe_device+0x13c/0x2a4)
>>   r7:c0c7e910 r6:00000000 r5:c0c7e900 r4:ef1b4010
>> [<c049e64c>] (driver_probe_device) from [<c049e978>]
>> (__driver_attach+0x88/0xac)
>>   r9:c0c34000 r8:c0a3c010 r7:c0c1cf08 r6:c0c1f8d4 r5:ef1b4044 r4:ef1b4010
>> [<c049e8f0>] (__driver_attach) from [<c049ce44>]
>> (bus_for_each_dev+0x74/0x98)
>>   r7:c0c1cf08 r6:c049e8f0 r5:c0c1f8d4 r4:00000000
>> [<c049cdd0>] (bus_for_each_dev) from [<c049ebd0>]
>> (driver_attach+0x20/0x28)
>>   r6:ef1cc200 r5:00000000 r4:c0c1f8d4
>> [<c049ebb0>] (driver_attach) from [<c049d5d8>]
>> (bus_add_driver+0xd4/0x1e4)
>> [<c049d504>] (bus_add_driver) from [<c049f2dc>]
>> (driver_register+0xa4/0xe8)
>>   r7:c0a3c010 r6:00000000 r5:c0a1e400 r4:c0c1f8d4
>> [<c049f238>] (driver_register) from [<c04a0778>]
>> (__platform_driver_register+0x38/0x4c)
>>   r5:c0a1e400 r4:ee958fc0
>> [<c04a0740>] (__platform_driver_register) from [<c0a1e418>]
>> (sh_msiof_spi_drv_init+0x18/0x20)
>> [<c0a1e400>] (sh_msiof_spi_drv_init) from [<c0a00e1c>]
>> (do_one_initcall+0x10c/0x1c0)
>> [<c0a00d10>] (do_one_initcall) from [<c0a00ff8>]
>> (kernel_init_freeable+0x128/0x1f4)
>>   r9:c0c34000 r8:c0c34000 r7:c0a47e60 r6:c0a3c83c r5:000000bd r4:00000006
>> [<c0a00ed0>] (kernel_init_freeable) from [<c071067c>]
>> (kernel_init+0x10/0x118)
>>   r9:00000000[    1.879529] ata1: link resume succeeded after 1 retries
>>   r8:00000000 r7:00000000 r6:00000000 r5:c071066c r4:00000000
>> [<c071066c>] (kernel_init) from [<c0206e08>] (ret_from_fork+0x14/0x2c)
>>   r5:c071066c r4:00000000
>> ---[ end trace 6eb9a3df3009d491 ]---
>>
>> Niklas S?derlund (2):
>>    dma-mapping: add __dma_sync_single_for_device()
>>    iommu/io-pgtable-arm: use __dma_sync_single_for_device()
>>
>>   drivers/iommu/io-pgtable-arm.c | 2 +-
>>   include/linux/dma-mapping.h    | 9 ++++++++-
>>   2 files changed, 9 insertions(+), 2 deletions(-)
>>
>> --
>> 2.8.2
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
> _______________________________________________
> iommu mailing list
> iommu at lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/iommu



From wens at csie.org  Mon May  9 03:01:45 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 9 May 2016 18:01:45 +0800
Subject: [PATCH 02/16] clk: sunxi-ng: Add common infrastructure
In-Reply-To: <1462737711-10017-3-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-3-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v67XWt6tjG_xXWgGatTaiN5uYQb2_Q6bgixMDUkHfVHLHg@mail.gmail.com>

On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Start our new clock infrastructure by adding the registration code, common
> structure and common code.
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/Makefile              |   1 +
>  drivers/clk/sunxi-ng/Makefile     |   2 +
>  drivers/clk/sunxi-ng/ccu_common.c | 108 ++++++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_common.h |  74 ++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_factor.h |  15 ++++++
>  drivers/clk/sunxi-ng/ccu_mux.h    |  20 +++++++
>  drivers/clk/sunxi-ng/ccu_reset.c  |  55 +++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_reset.h  |  40 ++++++++++++++
>  8 files changed, 315 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/Makefile
>  create mode 100644 drivers/clk/sunxi-ng/ccu_common.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_common.h
>  create mode 100644 drivers/clk/sunxi-ng/ccu_factor.h
>  create mode 100644 drivers/clk/sunxi-ng/ccu_mux.h
>  create mode 100644 drivers/clk/sunxi-ng/ccu_reset.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_reset.h
>
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 4ef71a13ab37..83a93cd9e21d 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -78,6 +78,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)            += socfpga/
>  obj-$(CONFIG_PLAT_SPEAR)               += spear/
>  obj-$(CONFIG_ARCH_STI)                 += st/
>  obj-$(CONFIG_ARCH_SUNXI)               += sunxi/
> +obj-$(CONFIG_ARCH_SUNXI)               += sunxi-ng/
>  obj-$(CONFIG_ARCH_TEGRA)               += tegra/
>  obj-y                                  += ti/
>  obj-$(CONFIG_ARCH_U8500)               += ux500/
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> new file mode 100644
> index 000000000000..bd3461b0f38c
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -0,0 +1,2 @@
> +obj-y += ccu_common.o
> +obj-y += ccu_reset.o
> diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c
> new file mode 100644
> index 000000000000..1d9242566fbd
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_common.c
> @@ -0,0 +1,108 @@
> +/*
> + * Copyright 2016 Maxime Ripard
> + *
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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/iopoll.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_reset.h"
> +
> +static DEFINE_SPINLOCK(ccu_lock);
> +
> +void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
> +{
> +       u32 reg;
> +
> +       if (!(common->features & CCU_FEATURE_LOCK))
> +               return;
> +
> +       WARN_ON(readl_relaxed_poll_timeout(common->base + common->reg, reg,
> +                                          !(reg & lock), 0, 500));

                                    no delay between reads? ^

> +}
> +
> +int sunxi_ccu_probe(struct device_node *node,
> +                   const struct sunxi_ccu_desc *desc)
> +{
> +       struct ccu_common **cclks = desc->clks;
> +       size_t num_clks = desc->num_clks;
> +       struct clk_onecell_data *data;
> +       struct ccu_reset *reset;
> +       struct clk **clks;
> +       void __iomem *reg;
> +       int i, ret;
> +
> +       reg = of_iomap(node, 0);

Why not of_io_request_and_map?

> +       if (IS_ERR(reg)) {

And of_iomap returns NULL on error. This is for of_io_request_and_map.

> +               pr_err("%s: Could not map the clock registers\n",
> +                      of_node_full_name(node));
> +               return PTR_ERR(reg);
> +       }
> +
> +       data = kzalloc(sizeof(*data), GFP_KERNEL);
> +       if (!data)
> +               return -ENOMEM;
> +
> +       clks = kcalloc(num_clks, sizeof(struct clk *), GFP_KERNEL);
> +       if (!clks)
> +               return -ENOMEM;
> +
> +       data->clks = clks;
> +       data->clk_num = num_clks;
> +
> +       for (i = 0; i < num_clks; i++) {
> +               struct ccu_common *cclk = cclks[i];
> +               struct clk *clk;
> +
> +               if (!cclk) {
> +                       cclk = ERR_PTR(-ENOENT);

This seems redundant, unless you intended to use it elsewhere?

> +                       continue;
> +               }
> +
> +               cclk->base = reg;
> +               cclk->lock = &ccu_lock;
> +
> +               clk = clk_register(NULL, &cclk->hw);
> +               if (IS_ERR(clk))
> +                       continue;
> +
> +               clks[i] = clk;
> +       }
> +
> +       ret = of_clk_add_provider(node, of_clk_src_onecell_get, data);
> +       if (ret)
> +               goto err_clk_unreg;
> +
> +       reset = kzalloc(sizeof(*reset), GFP_KERNEL);
> +       reset->rcdev.of_node = node;
> +       reset->rcdev.ops = &ccu_reset_ops;
> +       reset->rcdev.owner = THIS_MODULE;
> +       reset->rcdev.nr_resets = desc->num_resets;
> +       reset->base = reg;
> +       reset->lock = &ccu_lock;
> +       reset->reset_map = desc->resets;
> +
> +       ret = reset_controller_register(&reset->rcdev);
> +       if (ret)
> +               goto err_of_clk_unreg;
> +
> +       return 0;
> +
> +err_of_clk_unreg:
> +err_clk_unreg:
> +       return ret;
> +}
> diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
> new file mode 100644
> index 000000000000..e8b477fcd320
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_common.h
> @@ -0,0 +1,74 @@
> +/*
> + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _COMMON_H_
> +#define _COMMON_H_
> +
> +#include <linux/compiler.h>
> +#include <linux/clk-provider.h>
> +
> +#define CCU_FEATURE_GATE               BIT(0)
> +#define CCU_FEATURE_LOCK               BIT(1)

*_PLL_LOCK would be clearer that this implements a PLL lock indicator.
Or maybe a comment.

> +#define CCU_FEATURE_FRACTIONAL         BIT(2)
> +#define CCU_FEATURE_VARIABLE_PREDIV    BIT(3)
> +#define CCU_FEATURE_FIXED_PREDIV       BIT(4)
> +#define CCU_FEATURE_FIXED_POSTDIV      BIT(5)
> +
> +struct device_node;
> +
> +#define SUNXI_HW_INIT(_name, _parent, _ops, _flags)                    \
> +       &(struct clk_init_data) {                                       \
> +               .flags          = _flags,                               \
> +               .name           = _name,                                \
> +               .parent_names   = (const char *[]) { _parent },         \
> +               .num_parents    = 1,                                    \
> +               .ops            = _ops,                                 \
> +       }
> +
> +#define SUNXI_HW_INIT_PARENTS(_name, _parents, _ops, _flags)           \
> +       &(struct clk_init_data) {                                       \
> +               .flags          = _flags,                               \
> +               .name           = _name,                                \
> +               .parent_names   = _parents,                             \
> +               .num_parents    = ARRAY_SIZE(_parents),                 \
> +               .ops            = _ops,                                 \
> +       }
> +
> +struct ccu_common {
> +       void __iomem    *base;
> +       unsigned long   reg;

This seems quite large, considering the address space of the CCU,
and you using u16 or u32 for the same thing on the reset control side.

> +
> +       unsigned long   features;
> +       spinlock_t      *lock;
> +       struct clk_hw   hw;
> +};
> +
> +static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)
> +{
> +       return container_of(hw, struct ccu_common, hw);
> +}
> +
> +struct sunxi_ccu_desc {
> +       struct ccu_common       **clks;
> +       unsigned long           num_clks;
> +
> +       struct ccu_reset_map    *resets;
> +       unsigned long           num_resets;
> +};
> +
> +void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock);
> +
> +int sunxi_ccu_probe(struct device_node *node,
> +                   const struct sunxi_ccu_desc *desc);
> +
> +#endif /* _COMMON_H_ */
> diff --git a/drivers/clk/sunxi-ng/ccu_factor.h b/drivers/clk/sunxi-ng/ccu_factor.h
> new file mode 100644
> index 000000000000..e7cc564aaea0
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_factor.h
> @@ -0,0 +1,15 @@
> +#ifndef _CLK_FACTOR_H_
> +#define _CLK_FACTOR_H_
> +
> +struct ccu_factor {
> +       u8      shift;
> +       u8      width;
> +};
> +
> +#define SUNXI_CLK_FACTOR(_shift, _width)       \
> +       {                                       \
> +               .shift  = _shift,               \
> +               .width  = _width,               \
> +       }
> +
> +#endif /* _CLK_FACTOR_H_ */
> diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
> new file mode 100644
> index 000000000000..17cedad4e433
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_mux.h

As far as I can tell there are no users of this file within this patch or the
following patches before the mux clock support one. It'd be easier to understand
if this part was moved to the mux clock patch.

> @@ -0,0 +1,20 @@
> +#ifndef _CCU_MUX_H_
> +#define _CCU_MUX_H_
> +
> +#include "common.h"
> +
> +struct ccu_mux_internal {
> +       u8      shift;
> +       u8      width;
> +
> +       u8      *map;

I assume map is a table?

> +};
> +
> +#define SUNXI_CLK_MUX(_shift, _width, _map)    \
> +       {                                       \
> +               .map    = _map,                 \
> +               .shift  = _shift,               \
> +               .width  = _width,               \
> +       }
> +
> +#endif /* _CCU_MUX_H_ */
> diff --git a/drivers/clk/sunxi-ng/ccu_reset.c b/drivers/clk/sunxi-ng/ccu_reset.c
> new file mode 100644
> index 000000000000..6c31d48783a7
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_reset.c
> @@ -0,0 +1,55 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/reset-controller.h>
> +
> +#include "ccu_reset.h"
> +
> +static int ccu_reset_assert(struct reset_controller_dev *rcdev,
> +                           unsigned long id)
> +{
> +       struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
> +       const struct ccu_reset_map *map = &ccu->reset_map[id];
> +       unsigned long flags;
> +       u32 reg;
> +
> +       spin_lock_irqsave(ccu->lock, flags);
> +
> +       reg = readl(ccu->base + map->reg);
> +       writel(reg & ~map->bit, ccu->base + map->reg);
> +
> +       spin_unlock_irqrestore(ccu->lock, flags);
> +
> +       return 0;
> +}
> +
> +static int ccu_reset_deassert(struct reset_controller_dev *rcdev,
> +                             unsigned long id)
> +{
> +       struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
> +       const struct ccu_reset_map *map = &ccu->reset_map[id];
> +       unsigned long flags;
> +       u32 reg;
> +
> +       spin_lock_irqsave(ccu->lock, flags);
> +
> +       reg = readl(ccu->base + map->reg);
> +       writel(reg | map->bit, ccu->base + map->reg);
> +
> +       spin_unlock_irqrestore(ccu->lock, flags);
> +
> +       return 0;
> +}
> +
> +const struct reset_control_ops ccu_reset_ops = {
> +       .assert         = ccu_reset_assert,
> +       .deassert       = ccu_reset_deassert,
> +};
> diff --git a/drivers/clk/sunxi-ng/ccu_reset.h b/drivers/clk/sunxi-ng/ccu_reset.h
> new file mode 100644
> index 000000000000..36a4679210bd
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_reset.h
> @@ -0,0 +1,40 @@
> +/*
> + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _CCU_RESET_H_
> +#define _CCU_RESET_H_
> +
> +#include <linux/reset-controller.h>
> +
> +struct ccu_reset_map {
> +       u16     reg;
> +       u32     bit;
> +};
> +
> +
> +struct ccu_reset {
> +       void __iomem                    *base;
> +       struct ccu_reset_map            *reset_map;
> +       spinlock_t                      *lock;
> +
> +       struct reset_controller_dev     rcdev;
> +};
> +
> +static inline struct ccu_reset *rcdev_to_ccu_reset(struct reset_controller_dev *rcdev)
> +{
> +       return container_of(rcdev, struct ccu_reset, rcdev);
> +}
> +
> +extern const struct reset_control_ops ccu_reset_ops;
> +
> +#endif /* _CCU_RESET_H_ */

The reset control code looks good.


Regards
ChenYu

> --
> 2.8.2
>


From wens at csie.org  Mon May  9 03:05:20 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 9 May 2016 18:05:20 +0800
Subject: [PATCH 03/16] clk: sunxi-ng: Add fixed factor clock support
In-Reply-To: <1462737711-10017-4-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-4-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v65LcXnMj7B-0q2MYESM9vGd9k-yChjvFdX--EivSYdVJg@mail.gmail.com>

Hi,

On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Some clocks in the Allwinner SoCs clock units are direct, fixed,
> multipliers or dividers from their parent.
>
> Add support for such clocks.
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile           |  2 ++
>  drivers/clk/sunxi-ng/ccu_fixed_factor.c | 42 +++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_fixed_factor.h | 50 +++++++++++++++++++++++++++++++++
>  3 files changed, 94 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_fixed_factor.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_fixed_factor.h
>
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index bd3461b0f38c..d76276736765 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -1,2 +1,4 @@
>  obj-y += ccu_common.o
>  obj-y += ccu_reset.o
> +
> +obj-y += ccu_fixed_factor.o
> diff --git a/drivers/clk/sunxi-ng/ccu_fixed_factor.c b/drivers/clk/sunxi-ng/ccu_fixed_factor.c
> new file mode 100644
> index 000000000000..75df8a854db5
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_fixed_factor.c
> @@ -0,0 +1,42 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_fixed_factor.h"
> +
> +static unsigned long ccu_fixed_factor_recalc_rate(struct clk_hw *hw,
> +                                                 unsigned long parent_rate)
> +{
> +       struct ccu_fixed_factor *fix = hw_to_ccu_fixed_factor(hw);
> +
> +       return parent_rate * fix->mult / fix->div;

do_div (from include/asm-generic/div64.h) is better, since this is an
64 bit value.

> +}
> +
> +static long ccu_fixed_factor_round_rate(struct clk_hw *hw,
> +                                       unsigned long rate,
> +                                       unsigned long *parent_rate)
> +{
> +       struct ccu_fixed_factor *fix = hw_to_ccu_fixed_factor(hw);
> +
> +       return *parent_rate / fix->div * fix->mult;

Why is this the other way around? With integer math it shouldn't be
interchangeable. (Though it seems clk_fixed_factor does the same...)

Also, clk_fixed_factor handles CLK_SET_RATE_PARENT. Do we need to do the
same here?

> +}
> +
> +static int ccu_fixed_factor_set_rate(struct clk_hw *hw, unsigned long rate,
> +                                    unsigned long parent_rate)
> +{
> +       return 0;
> +}
> +
> +const struct clk_ops ccu_fixed_factor_ops = {
> +       .recalc_rate    = ccu_fixed_factor_recalc_rate,
> +       .round_rate     = ccu_fixed_factor_round_rate,
> +       .set_rate       = ccu_fixed_factor_set_rate,
> +};
> diff --git a/drivers/clk/sunxi-ng/ccu_fixed_factor.h b/drivers/clk/sunxi-ng/ccu_fixed_factor.h
> new file mode 100644
> index 000000000000..4e53dbc9d10b
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_fixed_factor.h
> @@ -0,0 +1,50 @@
> +/*
> + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _CCU_FIXED_FACTOR_H_
> +#define _CCU_FIXED_FACTOR_H_
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_common.h"
> +
> +struct ccu_fixed_factor {
> +       u16                     div;
> +       u16                     mult;
> +
> +       struct ccu_common       common;
> +};
> +
> +#define SUNXI_CCU_FIXED_FACTOR(_struct, _name, _parent,                        \
> +                              _div, _mult, _flags)                     \
> +       struct ccu_fixed_factor _struct = {                             \
> +               .div    = _div,                                         \
> +               .mult   = _mult,                                        \
> +               .common = {                                             \
> +                       .hw.init        = SUNXI_HW_INIT(_name,          \
> +                                                       _parent,        \
> +                                                       &ccu_fixed_factor_ops, \
> +                                                       _flags),        \
> +               },                                                      \
> +       }
> +
> +static inline struct ccu_fixed_factor *hw_to_ccu_fixed_factor(struct clk_hw *hw)
> +{
> +       struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +       return container_of(common, struct ccu_fixed_factor, common);
> +}
> +
> +extern const struct clk_ops ccu_fixed_factor_ops;
> +
> +#endif /* _CCU_FIXED_FACTOR_H_ */
> --
> 2.8.2
>


Regards
ChenYu


From jroedel at suse.de  Mon May  9 03:06:15 2016
From: jroedel at suse.de (Joerg Roedel)
Date: Mon, 9 May 2016 12:06:15 +0200
Subject: [GIT PULL] iommu/arm-smmu: Updates for 4.7
In-Reply-To: <20160504134531.GA31744@arm.com>
References: <20160504134531.GA31744@arm.com>
Message-ID: <20160509100615.GE9801@suse.de>

On Wed, May 04, 2016 at 02:45:31PM +0100, Will Deacon wrote:
> Peng Fan (1):
>       iommu/arm-smmu: Clear cache lock bit of ACR
> 
> Robin Murphy (7):
>       iommu/arm-smmu: Differentiate specific implementations
>       iommu/arm-smmu: Convert ThunderX workaround to new method
>       iommu/arm-smmu: Work around MMU-500 prefetch errata
>       io-64-nonatomic: Add relaxed accessor variants
>       iommu/arm-smmu: Tidy up 64-bit/atomic I/O accesses
>       iommu/arm-smmu: Decouple context format from kernel config
>       iommu/arm-smmu: Support SMMUv1 64KB supplement
> 
> Tirumalesh Chalamarla (2):
>       iommu/arm-smmu: Add support for 16 bit VMID
>       iommu/arm-smmu: Workaround for ThunderX erratum #27704
> 
>  Documentation/arm64/silicon-errata.txt             |   2 +
>  .../devicetree/bindings/iommu/arm,smmu.txt         |   1 +
>  drivers/iommu/arm-smmu.c                           | 291 +++++++++++++++------
>  include/asm-generic/io.h                           |   4 +-
>  include/linux/io-64-nonatomic-hi-lo.h              |  25 ++
>  include/linux/io-64-nonatomic-lo-hi.h              |  25 ++
>  6 files changed, 265 insertions(+), 83 deletions(-)

Pulled, thanks Will.


From marex at denx.de  Mon May  9 03:13:21 2016
From: marex at denx.de (Marek Vasut)
Date: Mon, 09 May 2016 12:13:21 +0200
Subject: [PATCH 3/4] ARM: mxs: dts: Add Creative X-Fi3 support
In-Reply-To: <57304AAE.20103@i2se.com>
References: <1462479971-7891-1-git-send-email-marex@denx.de>
 <1462479971-7891-3-git-send-email-marex@denx.de>
 <977436072.210446.e7eef450-2262-47df-8e8e-6a44da10083c.open-xchange@email.1und1.de>
 <572FA04B.1020005@denx.de> <57304AAE.20103@i2se.com>
Message-ID: <573062C1.1050000@denx.de>

On 05/09/2016 10:30 AM, Stefan Wahren wrote:
> Hi,
> 
> Am 08.05.2016 um 22:23 schrieb Marek Vasut:
>> On 05/06/2016 09:40 AM, Stefan Wahren wrote:
>>> Hi Marek,
>> Hi!
>>
>>> sorry for the reply format.
>> replying from a phone ? :)
> 
> no an ugly webmailer :(
> 
>>
>>>> Marek Vasut <marex at denx.de> hat am 5. Mai 2016 um 22:26 geschrieben:
>>>>
>>>> Add support for this small MP3 player based on STMP3780 (rev.4).
>>>> Currently supported is both external microSD and internal SD-NAND
>>>> bridge, PWM and USB gadget.
>>>>
>>>> Signed-off-by: Marek Vasut <marex at denx.de>
>>>> Cc: Fabio Estevam <fabio.estevam at nxp.com>
>>>> Cc: Shawn Guo <shawnguo at kernel.org>
>>>> ---
>>>>  arch/arm/boot/dts/Makefile | 1 +
>>>>  arch/arm/boot/dts/imx23-xfi3.dts | 190
>>>> +++++++++++++++++++++++++++++++++++++++
>>>>  2 files changed, 191 insertions(+)
>>>>  create mode 100644 arch/arm/boot/dts/imx23-xfi3.dts
>>>>
>>>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>>>> index 8f9f1c2..7a79d37 100644
>>>> --- a/arch/arm/boot/dts/Makefile
>>>> +++ b/arch/arm/boot/dts/Makefile
>>>> @@ -417,6 +417,7 @@ dtb-$(CONFIG_ARCH_MXS) += \
>>>>  imx23-evk.dtb \
>>>>  imx23-olinuxino.dtb \
>>>>  imx23-stmp378x_devb.dtb \
>>>> + imx23-xfi3.dtb \
>>>>  imx28-apf28.dtb \
>>>>  imx28-apf28dev.dtb \
>>>>  imx28-apx4devkit.dtb \
>>>> diff --git a/arch/arm/boot/dts/imx23-xfi3.dts
>>>> b/arch/arm/boot/dts/imx23-xfi3.dts
>>>> new file mode 100644
>>>> index 0000000..d7e7cf5
>>>> --- /dev/null
>>>> +++ b/arch/arm/boot/dts/imx23-xfi3.dts
>>>> @@ -0,0 +1,190 @@
>>>> +/*
>>>> + * Copyright (C) 2013-2016 Marek Vasut <marex at denx.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.
>>>> + *
>>>> + * You should have received a copy of the GNU General Public
>>>> + * License along with this file; if not, write to the Free
>>>> + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
>>>> + * MA 02110-1301 USA
>>> AFAIK this address shouldn't be included.
>> Hmmm, some boards do include it. I'll remove it from this submission and
>> also for the xfi.
>>
>> Shall I send patch(es) removing the address from the other boards too ?
> 
> i'm not sure. Maybe Shawn has an opinion about it.

I am hoping for that.

btw V2 of patches is out, feel free to review :)

-- 
Best regards,
Marek Vasut


From bamvor.zhangjian at huawei.com  Mon May  9 03:07:06 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Mon, 9 May 2016 18:07:06 +0800
Subject: [PATCH 24/25] arm64:ilp32: add vdso-ilp32 and use for signal
 return
In-Reply-To: <20160506140022.GA18587@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1554541.oDP7Ro5zB2@wuerfel>
 <20160503090045.GB10733@e104818-lin.cambridge.arm.com>
 <3846428.6xx69KGEja@wuerfel> <57288660.9030607@huawei.com>
 <57289C75.50904@huawei.com> <20160504214949.GA28217@yury-N73SV>
 <CA+=Sn1ngpaJWHpGDmU+kXBkz56SO+XDW2qzMMLAbbBWnaB0eqw@mail.gmail.com>
 <572AAED2.7050604@huawei.com>
 <CA+=Sn1mNdd+Xy5QL5ScRyZOCWwKkG6o1Pb50sFPuiKX=0Z2B1w@mail.gmail.com>
 <20160506140022.GA18587@yury-N73SV>
Message-ID: <5730614A.2000601@huawei.com>

Hi, yury

I tested successful in both little endian and big endian.
Just two comments below:

On 2016/5/6 22:00, Yury Norov wrote:
> Hello colleagues,
>
> After all comments, VDSO fix looks like this for me.
>
> Note I renamed Andrew's ZERO macro to DELOUSE, as
> there already is __SC_DELOUSE which does the same,
> but in C, not asm.
>
> Like Bamvor, I'm not sure how we'd apply this patch -
> standalone or meld to VDSO. I think, VDSO patch is too
> big and bad-structurized, and if I find how to refactor
> it, I'll incorporate this fix.
>
> Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
> ---
>   arch/arm64/kernel/asm-offsets.c               |  7 +++++++
>   arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S |  2 +-
>   arch/arm64/kernel/vdso/gettimeofday.S         | 20 +++++++++++++++++---
>   3 files changed, 25 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
> index e229525..fcfd087 100644
> --- a/arch/arm64/kernel/asm-offsets.c
> +++ b/arch/arm64/kernel/asm-offsets.c
> @@ -101,6 +101,13 @@ int main(void)
>     DEFINE(TSPEC_TV_SEC,		offsetof(struct timespec, tv_sec));
>     DEFINE(TSPEC_TV_NSEC,		offsetof(struct timespec, tv_nsec));
>     BLANK();
> +#ifdef CONFIG_ARM64_ILP32
The following structs exist in both aarch32 el0 and ilp32. How about change it to
"#ifdef CONFIG_COMPAT"?
> +  DEFINE(COMPAT_TVAL_TV_SEC,	offsetof(struct compat_timeval, tv_sec));
> +  DEFINE(COMPAT_TVAL_TV_USEC,	offsetof(struct compat_timeval, tv_usec));
> +  DEFINE(COMPAT_TSPEC_TV_SEC,	offsetof(struct compat_timespec, tv_sec));
> +  DEFINE(COMPAT_TSPEC_TV_NSEC,	offsetof(struct compat_timespec, tv_nsec));
> +  BLANK();
> +#endif
>     DEFINE(TZ_MINWEST,		offsetof(struct timezone, tz_minuteswest));
>     DEFINE(TZ_DSTTIME,		offsetof(struct timezone, tz_dsttime));
>     BLANK();
> diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
> index ddc63fd..d182a8d 100644
> --- a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
> +++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
> @@ -79,7 +79,7 @@ PHDRS
>    */
>   VERSION
>   {
> -	LINUX_2.6 {
> +	LINUX_2.6.39 {
Do we really want to this version? Maybe 4.x is better?

Regards

Bamvor

>   	global:
>   		__kernel_rt_sigreturn;
>   		__kernel_gettimeofday;
> diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
> index efa79e8..a2d8a70 100644
> --- a/arch/arm64/kernel/vdso/gettimeofday.S
> +++ b/arch/arm64/kernel/vdso/gettimeofday.S
> @@ -25,6 +25,16 @@
>   #define NSEC_PER_SEC_LO16	0xca00
>   #define NSEC_PER_SEC_HI16	0x3b9a
>
> +#ifdef __LP64__
> +#define PTR_REG(n)	x##n
> +#define OFFSET(n)	n
> +#define DELOUSE(n)
> +#else
> +#define PTR_REG(n)	w##n
> +#define OFFSET(n)	COMPAT_##n
> +#define DELOUSE(n)	mov     w##n, w##n
> +#endif
> +
>   vdso_data	.req	x6
>   use_syscall	.req	w7
>   seqcnt		.req	w8
> @@ -51,6 +61,8 @@ seqcnt		.req	w8
>   /* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */
>   ENTRY(__kernel_gettimeofday)
>   	.cfi_startproc
> +	DELOUSE(0)
> +	DELOUSE(1)
>   	mov	x2, x30
>   	.cfi_register x30, x2
>
> @@ -68,7 +80,7 @@ ENTRY(__kernel_gettimeofday)
>   	mov	x13, #1000
>   	lsl	x13, x13, x12
>   	udiv	x11, x11, x13
> -	stp	x10, x11, [x0, #TVAL_TV_SEC]
> +	stp	PTR_REG(10), PTR_REG(11), [x0, #OFFSET(TVAL_TV_SEC)]
>   2:
>   	/* If tz is NULL, return 0. */
>   	cbz	x1, 3f
> @@ -88,6 +100,7 @@ ENDPROC(__kernel_gettimeofday)
>   /* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */
>   ENTRY(__kernel_clock_gettime)
>   	.cfi_startproc
> +	DELOUSE(1)
>   	cmp	w0, #CLOCK_REALTIME
>   	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
>   	b.ne	2f
> @@ -159,7 +172,7 @@ ENTRY(__kernel_clock_gettime)
>
>   6:	/* Store to the user timespec. */
>   	lsr	x11, x11, x12
> -	stp	x10, x11, [x1, #TSPEC_TV_SEC]
> +	stp	PTR_REG(10), PTR_REG(11), [x1, #OFFSET(TSPEC_TV_SEC)]
>   	mov	x0, xzr
>   	ret
>   7:
> @@ -174,6 +187,7 @@ ENDPROC(__kernel_clock_gettime)
>   /* int __kernel_clock_getres(clockid_t clock_id, struct timespec *res); */
>   ENTRY(__kernel_clock_getres)
>   	.cfi_startproc
> +	DELOUSE(1)
>   	cmp	w0, #CLOCK_REALTIME
>   	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
>   	b.ne	1f
> @@ -187,7 +201,7 @@ ENTRY(__kernel_clock_getres)
>   	ldr	x2, 6f
>   2:
>   	cbz	w1, 3f
> -	stp	xzr, x2, [x1]
> +	stp	PTR_REG(zr), PTR_REG(2), [x1]
>
>   3:	/* res == NULL. */
>   	mov	w0, wzr
>



From alexandre.torgue at gmail.com  Mon May  9 03:31:33 2016
From: alexandre.torgue at gmail.com (Alexandre TORGUE)
Date: Mon,  9 May 2016 12:31:33 +0200
Subject: [RESEND PATCH v6 0/6]  Add Ethernet support on STM32F429
Message-ID: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>

STM32F429 Chip embeds a Synopsys 3.50a MAC IP.
This series:
 -enhance current stmmac driver to control it (code already
available) and adds basic glue for STM32F429 chip.
 -Enable basic Net config in kernel.

Changes since v5:
 -Fix typo in bindings documentation patch.
 -Change clocks names in stm32-dwmac glue driver / Documentation.
 -After rebase, stm32 ethernet node is now available. It has to be updated
according to new clocks names.

Changes since v4:
 -Fix dirty copy/past in bindings documentation patch.

Changes since v3:
 -Fix "tx-clk" and "rx-clk" as required clocks. Driver and bindings are
modified.

Changes since v2:
 -Fix alphabetic order in Kconfig and Makefile.
 -Improve code according to Joachim review.
 -Binding: remove useless entry.

Changes since v1:
 -Fix Kbuild issue in Kconfig.
 -Remove init/exit callbacks. Suspend/Resume and remove driver is no more
driven in stmmac_pltfr but directly in dwmac-stm32 glue driver.
 -Take into account Joachim review.

Regards.

Alexandre.

Alexandre TORGUE (6):
  net: ethernet: dwmac: add Ethernet glue logic for stm32 chip
  Documentation: Bindings: Add STM32 DWMAC glue
  net: ethernet: stmmac: add support of Synopsys 3.50a MAC IP
  ARM: STM32: Enable Ethernet in stm32_defconfig
  ARM: dts: stm32f429: Align Ethernet node with new bindings properties
  ARM: dts: stm32f429: Update Ethernet node on Eval board

 .../devicetree/bindings/net/stm32-dwmac.txt        |  32 ++++
 arch/arm/boot/dts/stm32429i-eval.dts               |   4 +-
 arch/arm/boot/dts/stm32f429.dtsi                   |   6 +-
 arch/arm/configs/stm32_defconfig                   |   9 +
 drivers/net/ethernet/stmicro/stmmac/Kconfig        |  12 ++
 drivers/net/ethernet/stmicro/stmmac/Makefile       |   1 +
 drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c  | 193 +++++++++++++++++++++
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |   1 +
 8 files changed, 253 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/stm32-dwmac.txt
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c

-- 
1.9.1



From alexandre.torgue at gmail.com  Mon May  9 03:31:34 2016
From: alexandre.torgue at gmail.com (Alexandre TORGUE)
Date: Mon,  9 May 2016 12:31:34 +0200
Subject: [RESEND PATCH v6 1/6] net: ethernet: dwmac: add Ethernet glue logic
 for stm32 chip
In-Reply-To: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
References: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
Message-ID: <1462789899-13153-2-git-send-email-alexandre.torgue@gmail.com>

stm324xx family chips support Synopsys MAC 3.510 IP.
This patch adds settings for logical glue logic:
-clocks
-mode selection MII or RMII.

Reviewed-by: Joachim Eastwood <manabian at gmail.com>
Acked-by: Giuseppe Cavallaro <peppe.cavallaro at st.com>
Tested-by: Maxime Coquelin <maxime.coquelin at st.com>
Signed-off-by: Alexandre TORGUE <alexandre.torgue at gmail.com>

diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index cec147d..235d679 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -104,6 +104,18 @@ config DWMAC_STI
 	  device driver. This driver is used on for the STi series
 	  SOCs GMAC ethernet controller.
 
+config DWMAC_STM32
+	tristate "STM32 DWMAC support"
+	default ARCH_STM32
+	depends on OF && HAS_IOMEM
+	select MFD_SYSCON
+	---help---
+	  Support for ethernet controller on STM32 SOCs.
+
+	  This selects STM32 SoC glue layer support for the stmmac
+	  device driver. This driver is used on for the STM32 series
+	  SOCs GMAC ethernet controller.
+
 config DWMAC_SUNXI
 	tristate "Allwinner GMAC support"
 	default ARCH_SUNXI
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 0fb362d..8828ada 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_DWMAC_MESON)	+= dwmac-meson.o
 obj-$(CONFIG_DWMAC_ROCKCHIP)	+= dwmac-rk.o
 obj-$(CONFIG_DWMAC_SOCFPGA)	+= dwmac-socfpga.o
 obj-$(CONFIG_DWMAC_STI)		+= dwmac-sti.o
+obj-$(CONFIG_DWMAC_STM32)	+= dwmac-stm32.o
 obj-$(CONFIG_DWMAC_SUNXI)	+= dwmac-sunxi.o
 obj-$(CONFIG_DWMAC_GENERIC)	+= dwmac-generic.o
 stmmac-platform-objs:= stmmac_platform.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
new file mode 100644
index 0000000..79d8b92
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
@@ -0,0 +1,193 @@
+/*
+ * dwmac-stm32.c - DWMAC Specific Glue layer for STM32 MCU
+ *
+ * Copyright (C) Alexandre Torgue 2015
+ * Author:  Alexandre Torgue <alexandre.torgue at gmail.com>
+ * License terms:  GNU General Public License (GPL), version 2
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_net.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/stmmac.h>
+
+#include "stmmac_platform.h"
+
+#define MII_PHY_SEL_MASK	BIT(23)
+
+struct stm32_dwmac {
+	struct clk *clk_tx;
+	struct clk *clk_rx;
+	u32 mode_reg;		/* MAC glue-logic mode register */
+	struct regmap *regmap;
+	u32 speed;
+};
+
+static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat)
+{
+	struct stm32_dwmac *dwmac = plat_dat->bsp_priv;
+	u32 reg = dwmac->mode_reg;
+	u32 val;
+	int ret;
+
+	val = (plat_dat->interface == PHY_INTERFACE_MODE_MII) ? 0 : 1;
+	ret = regmap_update_bits(dwmac->regmap, reg, MII_PHY_SEL_MASK, val);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(dwmac->clk_tx);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(dwmac->clk_rx);
+	if (ret)
+		clk_disable_unprepare(dwmac->clk_tx);
+
+	return ret;
+}
+
+static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac)
+{
+	clk_disable_unprepare(dwmac->clk_tx);
+	clk_disable_unprepare(dwmac->clk_rx);
+}
+
+static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac,
+				  struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	int err;
+
+	/*  Get TX/RX clocks */
+	dwmac->clk_tx = devm_clk_get(dev, "mac-clk-tx");
+	if (IS_ERR(dwmac->clk_tx)) {
+		dev_err(dev, "No tx clock provided...\n");
+		return PTR_ERR(dwmac->clk_tx);
+	}
+	dwmac->clk_rx = devm_clk_get(dev, "mac-clk-rx");
+	if (IS_ERR(dwmac->clk_rx)) {
+		dev_err(dev, "No rx clock provided...\n");
+		return PTR_ERR(dwmac->clk_rx);
+	}
+
+	/* Get mode register */
+	dwmac->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon");
+	if (IS_ERR(dwmac->regmap))
+		return PTR_ERR(dwmac->regmap);
+
+	err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->mode_reg);
+	if (err)
+		dev_err(dev, "Can't get sysconfig mode offset (%d)\n", err);
+
+	return err;
+}
+
+static int stm32_dwmac_probe(struct platform_device *pdev)
+{
+	struct plat_stmmacenet_data *plat_dat;
+	struct stmmac_resources stmmac_res;
+	struct stm32_dwmac *dwmac;
+	int ret;
+
+	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+	if (ret)
+		return ret;
+
+	plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
+	if (IS_ERR(plat_dat))
+		return PTR_ERR(plat_dat);
+
+	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
+	if (!dwmac)
+		return -ENOMEM;
+
+	ret = stm32_dwmac_parse_data(dwmac, &pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to parse OF data\n");
+		return ret;
+	}
+
+	plat_dat->bsp_priv = dwmac;
+
+	ret = stm32_dwmac_init(plat_dat);
+	if (ret)
+		return ret;
+
+	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+	if (ret)
+		stm32_dwmac_clk_disable(dwmac);
+
+	return ret;
+}
+
+static int stm32_dwmac_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct stmmac_priv *priv = netdev_priv(ndev);
+	int ret = stmmac_dvr_remove(&pdev->dev);
+
+	stm32_dwmac_clk_disable(priv->plat->bsp_priv);
+
+	return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int stm32_dwmac_suspend(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct stmmac_priv *priv = netdev_priv(ndev);
+	int ret;
+
+	ret = stmmac_suspend(dev);
+	stm32_dwmac_clk_disable(priv->plat->bsp_priv);
+
+	return ret;
+}
+
+static int stm32_dwmac_resume(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct stmmac_priv *priv = netdev_priv(ndev);
+	int ret;
+
+	ret = stm32_dwmac_init(priv->plat);
+	if (ret)
+		return ret;
+
+	ret = stmmac_resume(dev);
+
+	return ret;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+SIMPLE_DEV_PM_OPS(stm32_dwmac_pm_ops, stm32_dwmac_suspend, stm32_dwmac_resume);
+
+static const struct of_device_id stm32_dwmac_match[] = {
+	{ .compatible = "st,stm32-dwmac"},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, stm32_dwmac_match);
+
+static struct platform_driver stm32_dwmac_driver = {
+	.probe  = stm32_dwmac_probe,
+	.remove = stm32_dwmac_remove,
+	.driver = {
+		.name           = "stm32-dwmac",
+		.pm		= &stm32_dwmac_pm_ops,
+		.of_match_table = stm32_dwmac_match,
+	},
+};
+module_platform_driver(stm32_dwmac_driver);
+
+MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue at gmail.com>");
+MODULE_DESCRIPTION("STMicroelectronics MCU DWMAC Specific Glue layer");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1



From alexandre.torgue at gmail.com  Mon May  9 03:31:37 2016
From: alexandre.torgue at gmail.com (Alexandre TORGUE)
Date: Mon,  9 May 2016 12:31:37 +0200
Subject: [RESEND PATCH v6 4/6] ARM: STM32: Enable Ethernet in stm32_defconfig
In-Reply-To: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
References: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
Message-ID: <1462789899-13153-5-git-send-email-alexandre.torgue@gmail.com>

Enable basic Ethernet support (IPV4) for stm32 defconfig.

Signed-off-by: Alexandre TORGUE <alexandre.torgue at gmail.com>

diff --git a/arch/arm/configs/stm32_defconfig b/arch/arm/configs/stm32_defconfig
index 1e5ec2a..719218b 100644
--- a/arch/arm/configs/stm32_defconfig
+++ b/arch/arm/configs/stm32_defconfig
@@ -33,11 +33,20 @@ CONFIG_XIP_PHYS_ADDR=0x08008000
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_SHARED_FLAT=y
 # CONFIG_COREDUMP is not set
+CONFIG_NET=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_IPV6 is not set
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_BLK_DEV is not set
 CONFIG_EEPROM_93CX6=y
+CONFIG_NETDEVICES=y
+CONFIG_STMMAC_ETH=y
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
-- 
1.9.1



From alexandre.torgue at gmail.com  Mon May  9 03:31:38 2016
From: alexandre.torgue at gmail.com (Alexandre TORGUE)
Date: Mon,  9 May 2016 12:31:38 +0200
Subject: [RESEND PATCH v6 5/6] ARM: dts: stm32f429: Align Ethernet node with
 new bindings properties
In-Reply-To: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
References: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
Message-ID: <1462789899-13153-6-git-send-email-alexandre.torgue@gmail.com>

This patch aligns clocks names and node reference according to new
stm32-dwmac glue binding. It also renames Ethernet pinctrl phandle
(indeed there is no need to add 0 as Ethernet instance as there is only
one IP in SOC).

Signed-off-by: Alexandre TORGUE <alexandre.torgue at gmail.com>

diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index 35df462..5995998 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -304,7 +304,7 @@
 				};
 			};
 
-			ethernet0_mii: mii at 0 {
+			ethernet_mii: mii at 0 {
 				pins {
 					pinmux = <STM32F429_PG13_FUNC_ETH_MII_TXD0_ETH_RMII_TXD0>,
 						 <STM32F429_PG14_FUNC_ETH_MII_TXD1_ETH_RMII_TXD1>,
@@ -363,13 +363,13 @@
 			st,mem2mem;
 		};
 
-		ethernet0: dwmac at 40028000 {
+		mac: ethernet at 40028000 {
 			compatible = "st,stm32-dwmac", "snps,dwmac-3.50a";
 			reg = <0x40028000 0x8000>;
 			reg-names = "stmmaceth";
 			interrupts = <61>, <62>;
 			interrupt-names = "macirq", "eth_wake_irq";
-			clock-names = "stmmaceth", "tx-clk", "rx-clk";
+			clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx";
 			clocks = <&rcc 0 25>, <&rcc 0 26>, <&rcc 0 27>;
 			st,syscon = <&syscfg 0x4>;
 			snps,pbl = <8>;
-- 
1.9.1



From alexandre.torgue at gmail.com  Mon May  9 03:31:35 2016
From: alexandre.torgue at gmail.com (Alexandre TORGUE)
Date: Mon,  9 May 2016 12:31:35 +0200
Subject: [RESEND PATCH v6 2/6] Documentation: Bindings: Add STM32 DWMAC glue
In-Reply-To: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
References: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
Message-ID: <1462789899-13153-3-git-send-email-alexandre.torgue@gmail.com>

Acked-by: Rob Herring <robh at kernel.org>
Signed-off-by: Alexandre TORGUE <alexandre.torgue at gmail.com>

diff --git a/Documentation/devicetree/bindings/net/stm32-dwmac.txt b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
new file mode 100644
index 0000000..c35afb7
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/stm32-dwmac.txt
@@ -0,0 +1,32 @@
+STMicroelectronics STM32 / MCU DWMAC glue layer controller
+
+This file documents platform glue layer for stmmac.
+Please see stmmac.txt for the other unchanged properties.
+
+The device node has following properties.
+
+Required properties:
+- compatible:  Should be "st,stm32-dwmac" to select glue, and
+	       "snps,dwmac-3.50a" to select IP version.
+- clocks: Must contain a phandle for each entry in clock-names.
+- clock-names: Should be "stmmaceth" for the host clock.
+	       Should be "mac-clk-tx" for the MAC TX clock.
+	       Should be "mac-clk-rx" for the MAC RX clock.
+- st,syscon : Should be phandle/offset pair. The phandle to the syscon node which
+	      encompases the glue register, and the offset of the control register.
+Example:
+
+	ethernet at 40028000 {
+		compatible = "st,stm32-dwmac", "snps,dwmac-3.50a";
+		status = "disabled";
+		reg = <0x40028000 0x8000>;
+		reg-names = "stmmaceth";
+		interrupts = <0 61 0>, <0 62 0>;
+		interrupt-names = "macirq", "eth_wake_irq";
+		clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx";
+		clocks = <&rcc 0 25>, <&rcc 0 26>, <&rcc 0 27>;
+		st,syscon = <&syscfg 0x4>;
+		snps,pbl = <8>;
+		snps,mixed-burst;
+		dma-ranges;
+	};
-- 
1.9.1



From alexandre.torgue at gmail.com  Mon May  9 03:31:36 2016
From: alexandre.torgue at gmail.com (Alexandre TORGUE)
Date: Mon,  9 May 2016 12:31:36 +0200
Subject: [RESEND PATCH v6 3/6] net: ethernet: stmmac: add support of Synopsys
 3.50a MAC IP
In-Reply-To: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
References: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
Message-ID: <1462789899-13153-4-git-send-email-alexandre.torgue@gmail.com>

Adds support of Synopsys 3.50a MAC IP in stmmac driver.

Acked-by: Giuseppe Cavallaro <peppe.cavallaro at st.com>
Tested-by: Maxime Coquelin <maxime.coquelin at st.com>
Signed-off-by: Alexandre TORGUE <alexandre.torgue at gmail.com>

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 409db91..7718247 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -262,6 +262,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
 	 * once needed on other platforms.
 	 */
 	if (of_device_is_compatible(np, "st,spear600-gmac") ||
+		of_device_is_compatible(np, "snps,dwmac-3.50a") ||
 		of_device_is_compatible(np, "snps,dwmac-3.70a") ||
 		of_device_is_compatible(np, "snps,dwmac")) {
 		/* Note that the max-frame-size parameter as defined in the
-- 
1.9.1



From alexandre.torgue at gmail.com  Mon May  9 03:31:39 2016
From: alexandre.torgue at gmail.com (Alexandre TORGUE)
Date: Mon,  9 May 2016 12:31:39 +0200
Subject: [RESEND PATCH v6 6/6] ARM: dts: stm32f429: Update Ethernet node on
 Eval board
In-Reply-To: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
References: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
Message-ID: <1462789899-13153-7-git-send-email-alexandre.torgue@gmail.com>

Update new pinctrl phandle name and use new node name.

Signed-off-by: Alexandre TORGUE <alexandre.torgue at gmail.com>

diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts
index 6bfc595..9a72445 100644
--- a/arch/arm/boot/dts/stm32429i-eval.dts
+++ b/arch/arm/boot/dts/stm32429i-eval.dts
@@ -94,9 +94,9 @@
 	clock-frequency = <25000000>;
 };
 
-&ethernet0 {
+&mac {
 	status = "okay";
-	pinctrl-0	= <&ethernet0_mii>;
+	pinctrl-0	= <&ethernet_mii>;
 	pinctrl-names	= "default";
 	phy-mode	= "mii-id";
 	mdio0 {
-- 
1.9.1



From sfr at canb.auug.org.au  Mon May  9 03:53:15 2016
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Mon, 9 May 2016 20:53:15 +1000
Subject: next-20160503 build: 1 failures 12 warnings (next-20160503)
In-Reply-To: <2280495.M9rYajvqUJ@wuerfel>
References: <E1axZpG-000664-AK@optimist> <20160503141723.GR6292@sirena.org.uk>
 <2280495.M9rYajvqUJ@wuerfel>
Message-ID: <20160509205315.631e0c68@canb.auug.org.au>

Hi Arnd and all,

On Tue, 03 May 2016 17:02:39 +0200 Arnd Bergmann <arnd at arndb.de> wrote:
>
> On Tuesday 03 May 2016 15:17:23 Mark Brown wrote:
> > On Tue, May 03, 2016 at 01:53:18PM +0100, Build bot for Mark Brown wrote:
> > 
> > Today's -next fails to build an ARM allmodconfig due to:
> >   
> > >       arm-allmodconfig
> > > ../drivers/pinctrl/bcm/pinctrl-ns2-mux.c:540:17: error: 'pinctrl_utils_dt_free_map' undeclared here (not in a function)  
> > 
> > caused by b5aa1006e4a93 (pinctrl: ns2: add pinmux driver support for
> > Broadcom NS2 SoC) - presumably just a missing dependency.
> >   
> 
> No, the function got renamed in another patch. I already prepared a fix
> yesterday, but haven't gotten around to submit the patches for the last
> two days, I'll try to send it out today, but it might end up being
> tomorrow, or Linus could fix this one himself first.

Can we, please, get this fixed ... less than a week to the merge window
opening ...
-- 
Cheers,
Stephen Rothwell


From andre.przywara at arm.com  Mon May  9 04:15:24 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 9 May 2016 12:15:24 +0100
Subject: Reverting ARCH_SUNXI arm64 support(?)
In-Reply-To: <20160509090951.GC19763@arm.com>
References: <57304FF7.3080909@arm.com> <20160509090951.GC19763@arm.com>
Message-ID: <5730714C.7010608@arm.com>

Hi,

On 09/05/16 10:09, Will Deacon wrote:
> On Mon, May 09, 2016 at 09:53:11AM +0100, Andre Przywara wrote:
>> Hi Will, Catalin,
> 
> Hi Andre,
> 
>> Suzuki reported a build failure with certain (non-defconfig) .configs
>> due to the new ARCH_SUNXI support in 4.6-rc [1].
>> As unfortunately we couldn't agree on a solution and also the support
>> for the A64/Pine64 is partial in 4.6 anyway, can you please revert:
>> ce3dd55b99b151a90ac1701c6825f2ae2d49b54e ("arm64: Introduce Allwinner
>> SoC config option")
> 
> Given that we (Catalin and I) didn't commit that patch, it seems weird
> that we should be reverting it. Shouldn't this be handled in arm-soc or
> via the sunxi subtree?
> 
> We're also a week from the merge window, so it doesn't seem like a good
> time to be hacking at .config/kconfig-related issues.

I agree, that's why I was proposing taking Suzuki's first patch:

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index efa77c1..521b1ec 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -2,6 +2,7 @@ menu "Platform selection"

 config ARCH_SUNXI
 	bool "Allwinner sunxi 64-bit SoC Family"
+	select GENERIC_IRQ_CHIP
 	help
 	  This enables support for Allwinner sunxi based SoCs like the A64.


This is what defconfig selects anyway and also the change would be
confined to this (new) config option.

Olof, Arnd: would it be an option to take this patch still?

Cheers,
Andre.


From arnd at arndb.de  Mon May  9 04:17:19 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 13:17:19 +0200
Subject: next-20160503 build: 1 failures 12 warnings (next-20160503)
In-Reply-To: <20160509205315.631e0c68@canb.auug.org.au>
References: <E1axZpG-000664-AK@optimist> <2280495.M9rYajvqUJ@wuerfel>
 <20160509205315.631e0c68@canb.auug.org.au>
Message-ID: <4516208.OQ3mKD6WuY@wuerfel>

On Monday 09 May 2016 20:53:15 Stephen Rothwell wrote:
> Hi Arnd and all,
> 
> On Tue, 03 May 2016 17:02:39 +0200 Arnd Bergmann <arnd at arndb.de> wrote:
> >
> > On Tuesday 03 May 2016 15:17:23 Mark Brown wrote:
> > > On Tue, May 03, 2016 at 01:53:18PM +0100, Build bot for Mark Brown wrote:
> > > 
> > > Today's -next fails to build an ARM allmodconfig due to:
> > >   
> > > >       arm-allmodconfig
> > > > ../drivers/pinctrl/bcm/pinctrl-ns2-mux.c:540:17: error: 'pinctrl_utils_dt_free_map' undeclared here (not in a function)  
> > > 
> > > caused by b5aa1006e4a93 (pinctrl: ns2: add pinmux driver support for
> > > Broadcom NS2 SoC) - presumably just a missing dependency.
> > >   
> > 
> > No, the function got renamed in another patch. I already prepared a fix
> > yesterday, but haven't gotten around to submit the patches for the last
> > two days, I'll try to send it out today, but it might end up being
> > tomorrow, or Linus could fix this one himself first.
> 
> Can we, please, get this fixed ... less than a week to the merge window
> opening ...

Linus Walleij just picked up the patch I sent last week into the pinctrl tree,
so it should be fine in tomorrow's linux-next.

	Arnd


From joro at 8bytes.org  Mon May  9 04:21:38 2016
From: joro at 8bytes.org (Joerg Roedel)
Date: Mon, 9 May 2016 13:21:38 +0200
Subject: [PATCH 0/5] Introduce per-domain page sizes
In-Reply-To: <cover.1460048991.git.robin.murphy@arm.com>
References: <cover.1460048991.git.robin.murphy@arm.com>
Message-ID: <20160509112138.GB13275@8bytes.org>

On Thu, Apr 07, 2016 at 06:42:03PM +0100, Robin Murphy wrote:
> Hi all,
> 
> Since this area seems to be in vogue at the moment, here's what I was
> working on when the related patches[1][2] popped up, which happens to
> be more or less the intersection of both. As I recycled some of Will's
> old series as a starting point, I've retained the cleanup patches from
> that with their original acks - hope that's OK.
> 
> Fortunately, this already looks rather like parts of Joerg's plan[3],
> so I hope it's a suitable first step. Below is a quick hacked-up example
> of the kind of caller-controlled special use-case alluded to, using the
> SMMU/HDLCD combo on Juno - for a 'real' implementation of this we'd want
> the group-based domain allocation call so the driver could throw the
> device at that and get its own non-default DMA ops domain to play with.
> 
> Robin.
> 
> [1]:http://thread.gmane.org/gmane.linux.kernel.iommu/12774
> [2]:http://thread.gmane.org/gmane.linux.kernel.iommu/12901
> [3]:http://article.gmane.org/gmane.linux.kernel.iommu/12937
> 
> Robin Murphy (4):
>   iommu: of: enforce const-ness of struct iommu_ops
>   iommu: Allow selecting page sizes per domain
>   iommu/dma: Finish optimising higher-order allocations
>   iommu/arm-smmu: Use per-domain page sizes.
> 
> Will Deacon (1):
>   iommu: remove unused priv field from struct iommu_ops

Okay, I am still no happy that this lifts the requirements of the
iommu-api for the arm-smmu driver. But to get there we need more core
changes and this code is a step in the right direction, so I applied it.

Thanks,

	Joerg


From robin.murphy at arm.com  Mon May  9 04:45:39 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Mon, 9 May 2016 12:45:39 +0100
Subject: [PATCH 0/5] Introduce per-domain page sizes
In-Reply-To: <20160509112138.GB13275@8bytes.org>
References: <cover.1460048991.git.robin.murphy@arm.com>
 <20160509112138.GB13275@8bytes.org>
Message-ID: <57307863.1070706@arm.com>

Hi Joerg,

On 09/05/16 12:21, Joerg Roedel wrote:
> On Thu, Apr 07, 2016 at 06:42:03PM +0100, Robin Murphy wrote:
>> Hi all,
>>
>> Since this area seems to be in vogue at the moment, here's what I was
>> working on when the related patches[1][2] popped up, which happens to
>> be more or less the intersection of both. As I recycled some of Will's
>> old series as a starting point, I've retained the cleanup patches from
>> that with their original acks - hope that's OK.
>>
>> Fortunately, this already looks rather like parts of Joerg's plan[3],
>> so I hope it's a suitable first step. Below is a quick hacked-up example
>> of the kind of caller-controlled special use-case alluded to, using the
>> SMMU/HDLCD combo on Juno - for a 'real' implementation of this we'd want
>> the group-based domain allocation call so the driver could throw the
>> device at that and get its own non-default DMA ops domain to play with.
>>
>> Robin.
>>
>> [1]:http://thread.gmane.org/gmane.linux.kernel.iommu/12774
>> [2]:http://thread.gmane.org/gmane.linux.kernel.iommu/12901
>> [3]:http://article.gmane.org/gmane.linux.kernel.iommu/12937
>>
>> Robin Murphy (4):
>>    iommu: of: enforce const-ness of struct iommu_ops
>>    iommu: Allow selecting page sizes per domain
>>    iommu/dma: Finish optimising higher-order allocations
>>    iommu/arm-smmu: Use per-domain page sizes.
>>
>> Will Deacon (1):
>>    iommu: remove unused priv field from struct iommu_ops
>
> Okay, I am still no happy that this lifts the requirements of the
> iommu-api for the arm-smmu driver. But to get there we need more core
> changes and this code is a step in the right direction, so I applied it.

Thanks a lot! I was expecting to pick this up again after the merge 
window and post an updated version then; as you may already have found, 
patch 5 conflicts somewhat with the SMMUv2 context format changes in 
Will's updates branch. The correct resolution requires a bit of 
rewriting, so below is what that patch looks like when rebased on top of 
Will's branch. If you'd prefer it in actual merge resolution format, 
shout and I'll give that a go.

Thanks,
Robin.

--->8---
commit a940dae4e124523bc1cf282c8f36c79f960a0805
Author: Robin Murphy <robin.murphy at arm.com>
Date:   Mon Mar 14 14:25:07 2016 +0000

     iommu/arm-smmu: Use per-domain page sizes.

     Now that we can accurately reflect the context format we choose for 
each
     domain, do that instead of imposing the global 
lowest-common-denominator
     restriction and potentially ending up with nothing. We currently have a
     strict 1:1 correspondence between domains and context banks, so we 
don't
     need to entertain the possibility of multiple formats _within_ a 
domain.

     Signed-off-by: Will Deacon <will.deacon at arm.com>
     [rm: split from original patch, added SMMUv3]
     Signed-off-by: Robin Murphy <robin.murphy at arm.com>

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 4ff73ff64e49..ebab33e77d67 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -590,6 +590,7 @@ struct arm_smmu_device {

  	unsigned long			ias; /* IPA */
  	unsigned long			oas; /* PA */
+	unsigned long			pgsize_bitmap;

  #define ARM_SMMU_MAX_ASIDS		(1 << 16)
  	unsigned int			asid_bits;
@@ -1516,8 +1517,6 @@ static int arm_smmu_domain_finalise_s2(struct 
arm_smmu_domain *smmu_domain,
  	return 0;
  }

-static struct iommu_ops arm_smmu_ops;
-
  static int arm_smmu_domain_finalise(struct iommu_domain *domain)
  {
  	int ret;
@@ -1555,7 +1554,7 @@ static int arm_smmu_domain_finalise(struct 
iommu_domain *domain)
  	}

  	pgtbl_cfg = (struct io_pgtable_cfg) {
-		.pgsize_bitmap	= arm_smmu_ops.pgsize_bitmap,
+		.pgsize_bitmap	= smmu->pgsize_bitmap,
  		.ias		= ias,
  		.oas		= oas,
  		.tlb		= &arm_smmu_gather_ops,
@@ -1566,7 +1565,7 @@ static int arm_smmu_domain_finalise(struct 
iommu_domain *domain)
  	if (!pgtbl_ops)
  		return -ENOMEM;

-	arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
+	domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
  	smmu_domain->pgtbl_ops = pgtbl_ops;

  	ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg);
@@ -2410,7 +2409,6 @@ static int arm_smmu_device_probe(struct 
arm_smmu_device *smmu)
  {
  	u32 reg;
  	bool coherent;
-	unsigned long pgsize_bitmap = 0;

  	/* IDR0 */
  	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
@@ -2541,13 +2539,16 @@ static int arm_smmu_device_probe(struct 
arm_smmu_device *smmu)

  	/* Page sizes */
  	if (reg & IDR5_GRAN64K)
-		pgsize_bitmap |= SZ_64K | SZ_512M;
+		smmu->pgsize_bitmap |= SZ_64K | SZ_512M;
  	if (reg & IDR5_GRAN16K)
-		pgsize_bitmap |= SZ_16K | SZ_32M;
+		smmu->pgsize_bitmap |= SZ_16K | SZ_32M;
  	if (reg & IDR5_GRAN4K)
-		pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;
+		smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;

-	arm_smmu_ops.pgsize_bitmap &= pgsize_bitmap;
+	if (arm_smmu_ops.pgsize_bitmap == -1UL)
+		arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap;
+	else
+		arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap;

  	/* Output address size */
  	switch (reg & IDR5_OAS_MASK << IDR5_OAS_SHIFT) {
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 0bda956a025c..bf30490d6b18 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -343,6 +343,7 @@ struct arm_smmu_device {
  	unsigned long			va_size;
  	unsigned long			ipa_size;
  	unsigned long			pa_size;
+	unsigned long			pgsize_bitmap;

  	u32				num_global_irqs;
  	u32				num_context_irqs;
@@ -388,8 +389,6 @@ struct arm_smmu_domain {
  	struct iommu_domain		domain;
  };

-static struct iommu_ops arm_smmu_ops;
-
  static DEFINE_SPINLOCK(arm_smmu_devices_lock);
  static LIST_HEAD(arm_smmu_devices);

@@ -949,7 +948,7 @@ static int arm_smmu_init_domain_context(struct 
iommu_domain *domain,
  	}

  	pgtbl_cfg = (struct io_pgtable_cfg) {
-		.pgsize_bitmap	= arm_smmu_ops.pgsize_bitmap,
+		.pgsize_bitmap	= smmu->pgsize_bitmap,
  		.ias		= ias,
  		.oas		= oas,
  		.tlb		= &arm_smmu_gather_ops,
@@ -963,8 +962,8 @@ static int arm_smmu_init_domain_context(struct 
iommu_domain *domain,
  		goto out_clear_smmu;
  	}

-	/* Update our support page sizes to reflect the page table format */
-	arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
+	/* Update the domain's page sizes to reflect the page table format */
+	domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;

  	/* Initialise the context bank with our page table cfg */
  	arm_smmu_init_context_bank(smmu_domain, &pgtbl_cfg);
@@ -1793,19 +1792,23 @@ static int arm_smmu_device_cfg_probe(struct 
arm_smmu_device *smmu)
  	}

  	/* Now we've corralled the various formats, what'll it do? */
-	size = 0;
  	if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH32_S)
-		size |= SZ_4K | SZ_64K | SZ_1M | SZ_16M;
+		smmu->pgsize_bitmap |= SZ_4K | SZ_64K | SZ_1M | SZ_16M;
  	if (smmu->features &
  	    (ARM_SMMU_FEAT_FMT_AARCH32_L | ARM_SMMU_FEAT_FMT_AARCH64_4K))
-		size |= SZ_4K | SZ_2M | SZ_1G;
+		smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;
  	if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH64_16K)
-		size |= SZ_16K | SZ_32M;
+		smmu->pgsize_bitmap |= SZ_16K | SZ_32M;
  	if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH64_64K)
-		size |= SZ_64K | SZ_512M;
+		smmu->pgsize_bitmap |= SZ_64K | SZ_512M;
+
+	if (arm_smmu_ops.pgsize_bitmap == -1UL)
+		arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap;
+	else
+		arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap;
+	dev_notice(smmu->dev, "\tSupported page sizes: 0x%08lx\n",
+		   smmu->pgsize_bitmap);

-	arm_smmu_ops.pgsize_bitmap &= size;
-	dev_notice(smmu->dev, "\tSupported page sizes: 0x%08lx\n", size);

  	if (smmu->features & ARM_SMMU_FEAT_TRANS_S1)
  		dev_notice(smmu->dev, "\tStage-1: %lu-bit VA -> %lu-bit IPA\n",


From peng.fan at nxp.com  Mon May  9 05:20:26 2016
From: peng.fan at nxp.com (Peng Fan)
Date: Mon, 9 May 2016 12:20:26 +0000
Subject: [PATCH V2 3/3] nvmem: imx-ocotp: handling clock
In-Reply-To: <1461173177-11930-3-git-send-email-van.freenix@gmail.com>
References: <1461173177-11930-1-git-send-email-van.freenix@gmail.com>
 <1461173177-11930-3-git-send-email-van.freenix@gmail.com>
Message-ID: <HE1PR0401MB18013281F282E19BCC378B3888700@HE1PR0401MB1801.eurprd04.prod.outlook.com>

Hi,

Kindly ping..
Any comments on this patch set?

> -----Original Message-----
> From: linux-kernel-owner at vger.kernel.org [mailto:linux-kernel-
> owner at vger.kernel.org] On Behalf Of Peng Fan
> Sent: Thursday, April 21, 2016 1:26 AM
> To: shawnguo at kernel.org; srinivas.kandagatla at linaro.org;
> maxime.ripard at free-electrons.com
> Cc: linux-arm-kernel at lists.infradead.org; devicetree at vger.kernel.org; linux-
> kernel at vger.kernel.org; van.freenix at gmail.com
> Subject: [PATCH V2 3/3] nvmem: imx-ocotp: handling clock
> 
> Before access ocotp nvmem area, the clock should be enabled.
> Or, `hexdump nvmem` will hang the system. So, use such flow:
> "
>   1. clock_enable_prepare
>   2. read nvmem ocotp area
>   3. clock_disable_unprepare
> "
> 
> Signed-off-by: Peng Fan <van.freenix at gmail.com>
> Cc: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
> Cc: Maxime Ripard <maxime.ripard at free-electrons.com>
> Cc: Shawn Guo <shawnguo at kernel.org>
> ---
> 
> V2:
>  Follow Fabio's comments, check return value of clk_prepare_enable
> 
>  drivers/nvmem/imx-ocotp.c | 16 +++++++++++++++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c index
> d7796eb..3f1dd9f 100644
> --- a/drivers/nvmem/imx-ocotp.c
> +++ b/drivers/nvmem/imx-ocotp.c
> @@ -15,6 +15,7 @@
>   * http://www.gnu.org/copyleft/gpl.html
>   */
> 
> +#include <linux/clk.h>
>  #include <linux/device.h>
>  #include <linux/io.h>
>  #include <linux/module.h>
> @@ -27,6 +28,7 @@
> 
>  struct ocotp_priv {
>  	struct device *dev;
> +	struct clk *clk;
>  	void __iomem *base;
>  	unsigned int nregs;
>  };
> @@ -37,7 +39,7 @@ static int imx_ocotp_read(void *context, const void *reg,
> size_t reg_size,
>  	struct ocotp_priv *priv = context;
>  	unsigned int offset = *(u32 *)reg;
>  	unsigned int count;
> -	int i;
> +	int i, ret;
>  	u32 index;
> 
>  	index = offset >> 2;
> @@ -46,11 +48,19 @@ static int imx_ocotp_read(void *context, const void
> *reg, size_t reg_size,
>  	if (count > (priv->nregs - index))
>  		count = priv->nregs - index;
> 
> +	ret = clk_prepare_enable(priv->clk);
> +	if (ret < 0) {
> +		dev_err(priv->dev, "failed to prepare/enable ocotp clk\n");
> +		return ret;
> +	}
> +
>  	for (i = index; i < (index + count); i++) {
>  		*(u32 *)val = readl(priv->base + 0x400 + i * 0x10);
>  		val += 4;
>  	}
> 
> +	clk_disable_unprepare(priv->clk);
> +
>  	return 0;
>  }
> 
> @@ -112,6 +122,10 @@ static int imx_ocotp_probe(struct platform_device
> *pdev)
>  	if (IS_ERR(priv->base))
>  		return PTR_ERR(priv->base);
> 
> +	priv->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(priv->clk))
> +		return PTR_ERR(priv->clk);
> +
>  	of_id = of_match_device(imx_ocotp_dt_ids, dev);
>  	priv->nregs = (unsigned int)of_id->data;
>  	imx_ocotp_regmap_config.max_register = 4 * priv->nregs - 4;
> --
> 2.6.6

Thanks,
Peng.


From srinivas.kandagatla at linaro.org  Mon May  9 05:28:14 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon, 9 May 2016 13:28:14 +0100
Subject: [PATCH V2 3/3] nvmem: imx-ocotp: handling clock
In-Reply-To: <1461173177-11930-3-git-send-email-van.freenix@gmail.com>
References: <1461173177-11930-1-git-send-email-van.freenix@gmail.com>
 <1461173177-11930-3-git-send-email-van.freenix@gmail.com>
Message-ID: <5730825E.5030101@linaro.org>

Thanks for the Ping, I totally missed this thread.

On 20/04/16 18:26, Peng Fan wrote:
> Before access ocotp nvmem area, the clock should be enabled.
> Or, `hexdump nvmem` will hang the system. So, use such flow:
> "
>    1. clock_enable_prepare
>    2. read nvmem ocotp area
>    3. clock_disable_unprepare
> "
>
> Signed-off-by: Peng Fan <van.freenix at gmail.com>
> Cc: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
> Cc: Maxime Ripard <maxime.ripard at free-electrons.com>
> Cc: Shawn Guo <shawnguo at kernel.org>
> ---
>
> V2:
>   Follow Fabio's comments, check return value of clk_prepare_enable
>
>   drivers/nvmem/imx-ocotp.c | 16 +++++++++++++++-
>   1 file changed, 15 insertions(+), 1 deletion(-)

Changes to the driver looks good to me,
Only one comment, As the clock property is now made mandatory, you 
should update the dt-bindings with this info too.


thanks,
srini


From joel at jms.id.au  Mon May  9 05:29:06 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 21:59:06 +0930
Subject: [PULL REQUEST] aspeed arch changes for 4.7
Message-ID: <1462796946-13579-1-git-send-email-joel@jms.id.au>

Hello,

This is the initial pull request for the Aspeed BMC SoCs.

I put 4.7 in the subject for this and the subsequent requests but if it's a bit
late in the cycle then I understand.

Following review I got rid of the board file by pushing the functionality out
to a watchdog and clock driver, so it's just the Kconfig bits. I've also added
myself to maintainers for the Aspeed arch and drivers as I intend on looking
after them.

Please pull if it looks okay.


The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:

  Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)

are available in the git repository at:

  https://github.com/shenki/linux.git tags/aspeed-for-4.7-arch

for you to fetch changes up to 8c2ed9bcfbeb7f313b567b25e87effd75e7dc3d6:

  arm: Add Aspeed machine (2016-05-09 17:41:14 +0930)

----------------------------------------------------------------
aspeed arch tag for 4.7

----------------------------------------------------------------
Joel Stanley (1):
      arm: Add Aspeed machine

 MAINTAINERS                  |  7 +++++++
 arch/arm/Kconfig             |  2 ++
 arch/arm/mach-aspeed/Kconfig | 30 ++++++++++++++++++++++++++++++
 3 files changed, 39 insertions(+)
 create mode 100644 arch/arm/mach-aspeed/Kconfig


From joel at jms.id.au  Mon May  9 05:29:40 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 21:59:40 +0930
Subject: [PULL REQUEST] aspeed devicetree changes for 4.7
Message-ID: <1462796980-13703-1-git-send-email-joel@jms.id.au>

Hello,

This device trees for a pair of Aspeed BMC SoCs and the boards that they sit
in.

Please pull if it looks okay.

The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:

  Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)

are available in the git repository at:

  https://github.com/shenki/linux.git tags/aspeed-for-4.7-dts

for you to fetch changes up to 02440622656d26a0d68308db9e4ce1d2510f6530:

  arm/dst: Add Aspeed ast2500 device tree (2016-05-09 17:41:58 +0930)

----------------------------------------------------------------
aspeed devicetree for 4.7

----------------------------------------------------------------
Joel Stanley (3):
      doc/devicetree: Add Aspeed and Tyan to vendor-prefixes
      arm/dts: Add Aspeed ast2400 device tree
      arm/dst: Add Aspeed ast2500 device tree

 .../devicetree/bindings/vendor-prefixes.txt        |   2 +
 arch/arm/boot/dts/Makefile                         |   2 +
 arch/arm/boot/dts/aspeed-ast2500-evb.dts           |  25 +++
 arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts      |  25 +++
 arch/arm/boot/dts/aspeed-g4.dtsi                   | 161 +++++++++++++++++++
 arch/arm/boot/dts/aspeed-g5.dtsi                   | 170 +++++++++++++++++++++
 6 files changed, 385 insertions(+)
 create mode 100644 arch/arm/boot/dts/aspeed-ast2500-evb.dts
 create mode 100644 arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
 create mode 100644 arch/arm/boot/dts/aspeed-g4.dtsi
 create mode 100644 arch/arm/boot/dts/aspeed-g5.dtsi


From joel at jms.id.au  Mon May  9 05:30:07 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:00:07 +0930
Subject: [PULL REQUEST] aspeed defconfig changes for 4.7
Message-ID: <1462797007-13900-1-git-send-email-joel@jms.id.au>

Hello,

This adds configurations used for testing Aspeed BMC SoCs, as well as adding
the v5 part to the multi defconfig.

Please pull if it looks okay.

The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:

  Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)

are available in the git repository at:

  https://github.com/shenki/linux.git tags/aspeed-for-4.7-defconfig

for you to fetch changes up to d0bc3483da8774dcea1e0692586830031783f08c:

  arm/configs: Add Aspeed defconfig (2016-05-09 19:12:30 +0930)

----------------------------------------------------------------
aspeed defconfig for 4.7

----------------------------------------------------------------
Joel Stanley (2):
      arm/configs/multi_v5: Add Aspeed ast2400
      arm/configs: Add Aspeed defconfig

 arch/arm/configs/aspeed_g4_defconfig | 86 +++++++++++++++++++++++++++++++++++
 arch/arm/configs/aspeed_g5_defconfig | 88 ++++++++++++++++++++++++++++++++++++
 arch/arm/configs/multi_v5_defconfig  |  8 +++-
 3 files changed, 180 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/configs/aspeed_g4_defconfig
 create mode 100644 arch/arm/configs/aspeed_g5_defconfig


From joel at jms.id.au  Mon May  9 05:31:47 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:01:47 +0930
Subject: [PATCH 0/4] clk: Add drivers for Aspeed BMC SoCs
Message-ID: <1462797111-14271-1-git-send-email-joel@jms.id.au>

Hello,

This adds support for the Aspeed ast2400 and ast2500 BMC SoCs. The drivers are
basic in that they only create clock devices so other drivers know what
frequency they are clocked at; there is no support for modifying the clocks.

Heiko and I exchanged some mail about the structure of the drivers. Thanks for
the review Hieko! However, I still think the layout matches the hardware as we
understand it so I did not make significant changes.

Cheers,

Joel

Joel Stanley (4):
  doc/devicetree: Add Aspeed clock bindings
  drvers/clk: Support fourth generation Aspeed SoCs
  drvers/clk: Support fifth generation Aspeed SoCs
  drivers/clk: Support Aspeed UART clock divisor

 .../devicetree/bindings/clock/aspeed-clock.txt     | 156 +++++++++++++++++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/aspeed/Makefile                        |   3 +
 drivers/clk/aspeed/clk-g4.c                        | 109 ++++++++++++
 drivers/clk/aspeed/clk-g5.c                        | 189 +++++++++++++++++++++
 drivers/clk/aspeed/clk-uart.c                      |  52 ++++++
 6 files changed, 510 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/aspeed-clock.txt
 create mode 100644 drivers/clk/aspeed/Makefile
 create mode 100644 drivers/clk/aspeed/clk-g4.c
 create mode 100644 drivers/clk/aspeed/clk-g5.c
 create mode 100644 drivers/clk/aspeed/clk-uart.c

-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:31:48 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:01:48 +0930
Subject: [PATCH 1/4] doc/devicetree: Add Aspeed clock bindings
In-Reply-To: <1462797111-14271-1-git-send-email-joel@jms.id.au>
References: <1462797111-14271-1-git-send-email-joel@jms.id.au>
Message-ID: <1462797111-14271-2-git-send-email-joel@jms.id.au>

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 .../devicetree/bindings/clock/aspeed-clock.txt     | 156 +++++++++++++++++++++
 1 file changed, 156 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/aspeed-clock.txt

diff --git a/Documentation/devicetree/bindings/clock/aspeed-clock.txt b/Documentation/devicetree/bindings/clock/aspeed-clock.txt
new file mode 100644
index 000000000000..968329406435
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/aspeed-clock.txt
@@ -0,0 +1,156 @@
+Device Tree Clock bindings for the Aspeed SoCs
+
+Aspeed SoCs have a fixed frequency input osciallator is used to create the PLL
+and APB clocks. We can determine these frequencies by reading registers that
+are set according to strapping bits.
+
+Forth generation boards
+-----------------------
+
+eg, ast2400.
+
+CLKIN:
+ - compatible : Must be "fixed-clock"
+ - #clock-cells : Should be 0
+ - clock-frequency: 48e6, 25e6 or 24e6 depending on the input clock
+
+PLL:
+
+Required properties:
+ - compatible : Must be "aspeed,g4-hpll-clock"
+ - #clock-cells : Should be 0
+ - reg : Should contain registers location and length
+ - clocks : Should contain phandle + clock-specifier for the input clock (clkin)
+
+Optional properties:
+ - clock-output-names : Should contain clock name
+
+
+APB:
+
+Required properties:
+ - compatible : Must be "aspeed,g4-apb-clock"
+ - #clock-cells : Should be 0
+ - reg : Should contain registers location and length
+ - clocks : Should contain phandle + clock-specifier for the h-pll
+
+Optional properties:
+ - clock-output-names : Should contain clock name
+
+
+For example:
+
+	clk_clkin: clk_clkin {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <48000000>;
+	};
+
+	clk_hpll: clk_hpll {
+		compatible = "aspeed,g4-hpll-clock";
+		#clock-cells = <0>;
+		reg = <0x1e6e2008 0x4>;
+	};
+
+	clk_apb: clk_apb at 1e6e2008 {
+		#clock-cells = <0>;
+		compatible = "aspeed,g4-apb-clock";
+		reg = <0x1e6e2008 0x4>;
+		clocks = <&clk_hpll>;
+	};
+
+
+
+Fifth generation boards
+-----------------------
+
+eg, ast2500.
+
+CLKIN:
+Required properties:
+ - compatible : Must be "fixed-clock"
+ - #clock-cells : Should be 0
+ - clock-frequency: 25000000 or 24000000 depending on the input clock
+
+H-PLL:
+
+Required properties:
+ - compatible : Must be "aspeed,g5-hpll-clock"
+ - #clock-cells : Should be 0
+ - reg : Should contain registers location and length
+ - clocks : Should contain phandle + clock-specifier for the input clock (clkin)
+
+Optional properties:
+ - clock-output-names : Should contain clock name
+
+AHB:
+
+Required properties:
+ - compatible : Must be "aspeed,g5-ahb-clock"
+ - #clock-cells : Should be 0
+ - reg : Should contain registers location and length
+ - clocks : Should contain phandle + clock-specifier for the the h-pll
+
+Optional properties:
+ - clock-output-names : Should contain clock name
+
+APB:
+
+Required properties:
+ - compatible : Must be "aspeed,g4-apb-clock"
+ - #clock-cells : Should be 0
+ - reg : Should contain registers location and length
+ - clocks : Should contain phandle + clock-specifier for the the h-pll
+
+Optional properties:
+ - clock-output-names : Should contain clock name
+
+For example:
+	clk_clkin: clk_clkin at 1e6e2070 {
+		#clock-cells = <0>;
+		compatible = "aspeed,g5-clkin-clock";
+		reg = <0x1e6e2070 0x04>;
+	};
+
+	clk_hpll: clk_hpll at 1e6e2024 {
+		#clock-cells = <0>;
+		compatible = "aspeed,g5-hpll-clock";
+		reg = <0x1e6e2024 0x4>;
+		clocks = <&clk_clkin>;
+	};
+
+	clk_ahb: clk_ahb at 1e6e2070 {
+		#clock-cells = <0>;
+		compatible = "aspeed,g5-ahb-clock";
+		reg = <0x1e6e2070 0x4>;
+		clocks = <&clk_hpll>;
+	};
+
+	clk_apb: clk_apb at 1e6e2008 {
+		#clock-cells = <0>;
+		compatible = "aspeed,g5-apb-clock";
+		reg = <0x1e6e2008 0x4>;
+		clocks = <&clk_hpll>;
+	};
+
+Common clocks
+-------------
+
+UART:
+
+All supported boards have a uart clock that is derived from a 24MHz reference.
+We have a clock driver for it as there is a register in the SCU that controls
+weather it will be divided down by 13 or not.
+
+Required properties:
+ - compatible : Must be "aspeed,uart-clock"
+ - #clock-cells : Should be 0
+ - reg : Should contain registers location and length
+
+For example:
+
+	clk_uart: clk_uart at 1e6e2008 {
+		#clock-cells = <0>;
+		compatible = "aspeed,uart-clock";
+		reg = <0x1e6e202c 0x4>;
+	};
-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:31:49 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:01:49 +0930
Subject: [PATCH 2/4] drvers/clk: Support fourth generation Aspeed SoCs
In-Reply-To: <1462797111-14271-1-git-send-email-joel@jms.id.au>
References: <1462797111-14271-1-git-send-email-joel@jms.id.au>
Message-ID: <1462797111-14271-3-git-send-email-joel@jms.id.au>

A basic driver to create fixed rate clock devices from strapping
registers.

The clocks on the ast2400 are derived from an external oscillator and
the frequency of this can be derived from the strapping of the
processor. The frequency of internal clocks can be derived from other
registers in the SCU (System Control Unit).

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/clk/Makefile        |   1 +
 drivers/clk/aspeed/Makefile |   1 +
 drivers/clk/aspeed/clk-g4.c | 109 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 111 insertions(+)
 create mode 100644 drivers/clk/aspeed/Makefile
 create mode 100644 drivers/clk/aspeed/clk-g4.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 46869d696e4d..8eaaef013a28 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -84,3 +84,4 @@ obj-$(CONFIG_X86)			+= x86/
 obj-$(CONFIG_ARCH_ZX)			+= zte/
 obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
 obj-$(CONFIG_H8300)		+= h8300/
+obj-$(CONFIG_ARCH_ASPEED)		+= aspeed/
diff --git a/drivers/clk/aspeed/Makefile b/drivers/clk/aspeed/Makefile
new file mode 100644
index 000000000000..d3457fbe3019
--- /dev/null
+++ b/drivers/clk/aspeed/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MACH_ASPEED_G4) += clk-g4.o
diff --git a/drivers/clk/aspeed/clk-g4.c b/drivers/clk/aspeed/clk-g4.c
new file mode 100644
index 000000000000..91677e9177f5
--- /dev/null
+++ b/drivers/clk/aspeed/clk-g4.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2016 IBM Corporation
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/clkdev.h>
+
+static void __init aspeed_of_hpll_clk_init(struct device_node *node)
+{
+	struct clk *clk, *clkin_clk;
+	void __iomem *base;
+	int reg, rate, clkin;
+	const char *name = node->name;
+	const char *parent_name;
+	const int rates[][4] = {
+		{384, 360, 336, 408},
+		{400, 375, 350, 425},
+	};
+
+	of_property_read_string(node, "clock-output-names", &name);
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s: of_iomap failed\n", node->full_name);
+		return;
+	}
+	reg = readl(base);
+	iounmap(base);
+
+	clkin_clk = of_clk_get(node, 0);
+	if (IS_ERR(clkin_clk)) {
+		pr_err("%s: of_clk_get failed\n", node->full_name);
+		return;
+	}
+
+	clkin = clk_get_rate(clkin_clk);
+
+	reg = (reg >> 8) & 0x2;
+
+	if (clkin == 48000000 || clkin == 24000000)
+		rate = rates[0][reg] * 1000000;
+	else if (clkin == 25000000)
+		rate = rates[1][reg] * 1000000;
+	else {
+		pr_err("%s: unknown clkin frequency %dHz\n",
+				node->full_name, clkin);
+		WARN_ON(1);
+	}
+
+	clk = clk_register_fixed_rate(NULL, name, parent_name, 0, rate);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register clock\n", node->full_name);
+		return;
+	}
+
+	clk_register_clkdev(clk, NULL, name);
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(aspeed_hpll_clock, "aspeed,g4-hpll-clock",
+	       aspeed_of_hpll_clk_init);
+
+static void __init aspeed_of_apb_clk_init(struct device_node *node)
+{
+	struct clk *clk, *hpll_clk;
+	void __iomem *base;
+	int reg, rate;
+	const char *name = node->name;
+	const char *parent_name;
+
+	of_property_read_string(node, "clock-output-names", &name);
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s: of_iomap failed\n", node->full_name);
+		return;
+	}
+	reg = readl(base);
+	iounmap(base);
+
+	hpll_clk = of_clk_get(node, 0);
+	if (IS_ERR(hpll_clk)) {
+		pr_err("%s: of_clk_get failed\n", node->full_name);
+		return;
+	}
+
+	reg = (reg >> 23) & 0x3;
+	rate = clk_get_rate(hpll_clk) / (2 + 2 * reg);
+
+	clk = clk_register_fixed_rate(NULL, name, parent_name, 0, rate);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register clock\n", node->full_name);
+		return;
+	}
+
+	clk_register_clkdev(clk, NULL, name);
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(aspeed_apb_clock, "aspeed,g4-apb-clock",
+	       aspeed_of_apb_clk_init);
-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:31:50 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:01:50 +0930
Subject: [PATCH 3/4] drvers/clk: Support fifth generation Aspeed SoCs
In-Reply-To: <1462797111-14271-1-git-send-email-joel@jms.id.au>
References: <1462797111-14271-1-git-send-email-joel@jms.id.au>
Message-ID: <1462797111-14271-4-git-send-email-joel@jms.id.au>

A basic driver to create fixed rate clock devices from strapping
registers.

Like the ast2400, the ast2500 clocks are derived from an external
oscillator and the frequency of this can be determined from the
strapping of the processor.

The frequency of internal clocks can be derived from other registers in
the SCU (System Control Unit). The layout of the internal clocks is a
bit different to the ast2400, as are the divisor reigisters, so it has
it's own driver.

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/clk/aspeed/Makefile |   1 +
 drivers/clk/aspeed/clk-g5.c | 189 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 190 insertions(+)
 create mode 100644 drivers/clk/aspeed/clk-g5.c

diff --git a/drivers/clk/aspeed/Makefile b/drivers/clk/aspeed/Makefile
index d3457fbe3019..9ddb0f8f4356 100644
--- a/drivers/clk/aspeed/Makefile
+++ b/drivers/clk/aspeed/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_MACH_ASPEED_G4) += clk-g4.o
+obj-$(CONFIG_MACH_ASPEED_G5) += clk-g5.o
diff --git a/drivers/clk/aspeed/clk-g5.c b/drivers/clk/aspeed/clk-g5.c
new file mode 100644
index 000000000000..812fd9accf30
--- /dev/null
+++ b/drivers/clk/aspeed/clk-g5.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2016 IBM Corporation
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/clkdev.h>
+
+static void __init aspeed_of_clkin_clk_init(struct device_node *node)
+{
+	struct clk *clk;
+	void __iomem *base;
+	int reg, rate;
+	const char *name = node->name;
+
+	of_property_read_string(node, "clock-output-names", &name);
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s: of_iomap failed\n", node->full_name);
+		return;
+	}
+	/* Strap register SCU70 */
+	reg = readl(base) & BIT(23);
+	iounmap(base);
+
+	if (reg)
+		rate = 25 * 1000 * 1000;
+	else
+		rate = 24 * 1000 * 1000;
+
+	clk = clk_register_fixed_rate(NULL, name, NULL, 0, rate);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register clock\n", node->full_name);
+		return;
+	}
+
+	clk_register_clkdev(clk, NULL, name);
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(aspeed_clkin_clock, "aspeed,g5-clkin-clock",
+	       aspeed_of_clkin_clk_init);
+
+
+static void __init aspeed_of_hpll_clk_init(struct device_node *node)
+{
+	struct clk *clk, *clkin_clk;
+	void __iomem *base;
+	int reg, rate, clkin;
+	const char *name = node->name;
+	const char *parent_name;
+
+	of_property_read_string(node, "clock-output-names", &name);
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s: of_iomap failed\n", node->full_name);
+		return;
+	}
+	/* H-PLL parameter register SCU24 */
+	reg = readl(base);
+	iounmap(base);
+
+	clkin_clk = of_clk_get(node, 0);
+	if (IS_ERR(clkin_clk)) {
+		pr_err("%s: of_clk_get failed\n", node->full_name);
+		return;
+	}
+
+	clkin = clk_get_rate(clkin_clk);
+
+	if (reg & BIT(21)) {
+		rate = 0;
+	} else if (reg & BIT(20)) {
+		rate = clkin;
+	} else {
+		int p = (reg >> 13) & 0x3f;
+		int m = (reg >> 5) & 0xff;
+		int n = reg & 0x1f;
+
+		rate = clkin * ((m + 1) / (n + 1)) / (p + 1);
+	}
+
+	clk = clk_register_fixed_rate(NULL, name, parent_name, 0, rate);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register clock\n", node->full_name);
+		return;
+	}
+
+	clk_register_clkdev(clk, NULL, name);
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(aspeed_hpll_clock, "aspeed,g5-hpll-clock",
+	       aspeed_of_hpll_clk_init);
+
+
+static void __init aspeed_of_ahb_clk_init(struct device_node *node)
+{
+	struct clk *clk, *hpll_clk;
+	void __iomem *base;
+	int reg, rate, hpll;
+	const char *name = node->name;
+	const char *parent_name;
+
+	of_property_read_string(node, "clock-output-names", &name);
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	/* Strap register SCU70 */
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s: of_iomap failed\n", node->full_name);
+		return;
+	}
+	reg = (readl(base) >> 9) & 0x03;
+	iounmap(base);
+
+	/* A value of zero is undefined */
+	WARN_ON(reg == 0);
+
+	hpll_clk = of_clk_get(node, 0);
+	if (IS_ERR(hpll_clk)) {
+		pr_err("%s: of_clk_get failed\n", node->full_name);
+		return;
+	}
+
+	hpll = clk_get_rate(hpll_clk);
+
+	rate = hpll / 2 / (reg + 1);
+
+	clk = clk_register_fixed_rate(NULL, name, parent_name, 0, rate);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register clock\n", node->full_name);
+		return;
+	}
+
+	clk_register_clkdev(clk, NULL, name);
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(aspeed_ahb_clock, "aspeed,g5-ahb-clock",
+	       aspeed_of_ahb_clk_init);
+
+
+static void __init aspeed_of_apb_clk_init(struct device_node *node)
+{
+	struct clk *clk, *hpll_clk;
+	void __iomem *base;
+	int reg, rate;
+	const char *name = node->name;
+	const char *parent_name;
+
+	of_property_read_string(node, "clock-output-names", &name);
+	parent_name = of_clk_get_parent_name(node, 0);
+
+	/* Clock selection register SCU08 */
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s: of_iomap failed\n", node->full_name);
+		return;
+	}
+	reg = readl(base) >> 23 & 0x3;
+	iounmap(base);
+
+	hpll_clk = of_clk_get(node, 0);
+	if (IS_ERR(hpll_clk)) {
+		pr_err("%s: of_clk_get failed\n", node->full_name);
+		return;
+	}
+
+	rate = clk_get_rate(hpll_clk) / (4 * (reg + 1));
+
+	clk = clk_register_fixed_rate(NULL, name, parent_name, 0, rate);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register clock\n", node->full_name);
+		return;
+	}
+
+	clk_register_clkdev(clk, NULL, name);
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(aspeed_apb_clock, "aspeed,g5-apb-clock",
+	       aspeed_of_apb_clk_init);
-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:31:51 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:01:51 +0930
Subject: [PATCH 4/4] drivers/clk: Support Aspeed UART clock divisor
In-Reply-To: <1462797111-14271-1-git-send-email-joel@jms.id.au>
References: <1462797111-14271-1-git-send-email-joel@jms.id.au>
Message-ID: <1462797111-14271-5-git-send-email-joel@jms.id.au>

The Aspeed BMC SoCs have UART IP that derive their clocks from
a 24MHz reference. It's not clear where this reference comes from, so it
is hard coded in the driver.

This clock may be divided down by 13 if a certain register is set. This
driver reads this register and creates a struct clk for the UARTs to
consume.

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/clk/aspeed/Makefile   |  1 +
 drivers/clk/aspeed/clk-uart.c | 52 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+)
 create mode 100644 drivers/clk/aspeed/clk-uart.c

diff --git a/drivers/clk/aspeed/Makefile b/drivers/clk/aspeed/Makefile
index 9ddb0f8f4356..9d5754c086eb 100644
--- a/drivers/clk/aspeed/Makefile
+++ b/drivers/clk/aspeed/Makefile
@@ -1,2 +1,3 @@
+obj-y += clk-uart.o
 obj-$(CONFIG_MACH_ASPEED_G4) += clk-g4.o
 obj-$(CONFIG_MACH_ASPEED_G5) += clk-g5.o
diff --git a/drivers/clk/aspeed/clk-uart.c b/drivers/clk/aspeed/clk-uart.c
new file mode 100644
index 000000000000..8cd23a758887
--- /dev/null
+++ b/drivers/clk/aspeed/clk-uart.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016 IBM Corporation
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/clkdev.h>
+
+static void __init aspeed_of_uart_clk_init(struct device_node *node)
+{
+	struct clk *clk;
+	void __iomem *base;
+	int reg, rate;
+	const char *name = node->name;
+
+	of_property_read_string(node, "clock-output-names", &name);
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s: of_iomap failed\n", node->full_name);
+		return;
+	}
+	reg = readl(base);
+	iounmap(base);
+
+	/*
+	 * The documentation does not indicate where this 24MHz clock is
+	 * derived from.
+	 */
+	rate = 24000000;
+
+	if (reg & BIT(12))
+		rate /= 13;
+
+	clk = clk_register_fixed_rate(NULL, name, NULL, 0, rate);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register clock\n", node->full_name);
+		return;
+	}
+
+	clk_register_clkdev(clk, NULL, name);
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(aspeed_uart_clock, "aspeed,uart-clock",
+	       aspeed_of_uart_clk_init);
-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:32:45 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:02:45 +0930
Subject: [PATCH 0/4] clocksource: Add support for Aspeed timer
Message-ID: <1462797169-14512-1-git-send-email-joel@jms.id.au>

Hello All,

This adds support for the Aspeed ast2400 and ast2500 families of BMC SoCs to
the moxart driver.

I've addressed the feedback from Daniel and spent a bit of time trying to
ensure the series makes sense.

I've not included a patch that renames the driver to fttmr010, from Faraday
Tech, as I wasn't sure if we had consensus. If you would prefer I do so then
let me know.

Cheers,

Joel

Joel Stanley (4):
  drivers/clocksouree/moxart: Add kbuild symbol
  drivers/clocksource/moxart: Refactor enable/disable
  drivers/clocksource/moxart: Use struct to hold state
  drivers/clocksource/moxart: Add Aspeed support

 .../bindings/timer/moxa,moxart-timer.txt           |   4 +-
 arch/arm/mach-moxart/Kconfig                       |   2 +-
 drivers/clocksource/Kconfig                        |   9 +
 drivers/clocksource/Makefile                       |   2 +-
 drivers/clocksource/moxart_timer.c                 | 191 ++++++++++++++-------
 5 files changed, 143 insertions(+), 65 deletions(-)

-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:32:46 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:02:46 +0930
Subject: [PATCH 1/4] drivers/clocksouree/moxart: Add kbuild symbol
In-Reply-To: <1462797169-14512-1-git-send-email-joel@jms.id.au>
References: <1462797169-14512-1-git-send-email-joel@jms.id.au>
Message-ID: <1462797169-14512-2-git-send-email-joel@jms.id.au>

Add a Kconfig entry for this driver so other SoCs can select it. This
updates the moxart Kconfig in order to select the symbol.

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 arch/arm/mach-moxart/Kconfig | 2 +-
 drivers/clocksource/Kconfig  | 9 +++++++++
 drivers/clocksource/Makefile | 2 +-
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-moxart/Kconfig b/arch/arm/mach-moxart/Kconfig
index 180d9d216719..505fab683b81 100644
--- a/arch/arm/mach-moxart/Kconfig
+++ b/arch/arm/mach-moxart/Kconfig
@@ -3,9 +3,9 @@ menuconfig ARCH_MOXART
 	depends on ARCH_MULTI_V4
 	select CPU_FA526
 	select ARM_DMA_MEM_BUFFERABLE
-	select CLKSRC_MMIO
 	select GENERIC_IRQ_CHIP
 	select ARCH_REQUIRE_GPIOLIB
+	select MOXART_TIMER
 	select PHYLIB if NETDEVICES
 	help
 	  Say Y here if you want to run your kernel on hardware with a
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index c346be650892..9a54d1ce4ce7 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -411,4 +411,13 @@ config CLKSRC_ST_LPC
 	  Enable this option to use the Low Power controller timer
 	  as clocksource.
 
+config MOXART_TIMER
+	bool "Moxart timer" if COMPILE_TEST
+	depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
+	select CLKSRC_OF
+	select CLKSRC_MMIO
+	help
+	  Enables the support for the timer used in the Moxart and Aspeed
+	  system on chips.
+
 endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index dc2b8997f6e6..14fe8172c174 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -22,7 +22,7 @@ obj-$(CONFIG_ORION_TIMER)	+= time-orion.o
 obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o
 obj-$(CONFIG_ARCH_CLPS711X)	+= clps711x-timer.o
 obj-$(CONFIG_ARCH_ATLAS7)	+= timer-atlas7.o
-obj-$(CONFIG_ARCH_MOXART)	+= moxart_timer.o
+obj-$(CONFIG_MOXART_TIMER)	+= moxart_timer.o
 obj-$(CONFIG_ARCH_MXS)		+= mxs_timer.o
 obj-$(CONFIG_CLKSRC_PXA)	+= pxa_timer.o
 obj-$(CONFIG_ARCH_PRIMA2)	+= timer-prima2.o
-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:32:47 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:02:47 +0930
Subject: [PATCH 2/4] drivers/clocksource/moxart: Refactor enable/disable
In-Reply-To: <1462797169-14512-1-git-send-email-joel@jms.id.au>
References: <1462797169-14512-1-git-send-email-joel@jms.id.au>
Message-ID: <1462797169-14512-3-git-send-email-joel@jms.id.au>

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/clocksource/moxart_timer.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c
index 19857af651c1..b00b2b21e8b3 100644
--- a/drivers/clocksource/moxart_timer.c
+++ b/drivers/clocksource/moxart_timer.c
@@ -58,15 +58,25 @@
 static void __iomem *base;
 static unsigned int clock_count_per_tick;
 
-static int moxart_shutdown(struct clock_event_device *evt)
+static inline void moxart_disable(struct clock_event_device *evt)
 {
 	writel(TIMER1_DISABLE, base + TIMER_CR);
+}
+
+static inline void moxart_enable(struct clock_event_device *evt)
+{
+	writel(TIMER1_ENABLE, base + TIMER_CR);
+}
+
+static int moxart_shutdown(struct clock_event_device *evt)
+{
+	moxart_disable(evt);
 	return 0;
 }
 
 static int moxart_set_oneshot(struct clock_event_device *evt)
 {
-	writel(TIMER1_DISABLE, base + TIMER_CR);
+	moxart_disable(evt);
 	writel(~0, base + TIMER1_BASE + REG_LOAD);
 	return 0;
 }
@@ -74,21 +84,21 @@ static int moxart_set_oneshot(struct clock_event_device *evt)
 static int moxart_set_periodic(struct clock_event_device *evt)
 {
 	writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD);
-	writel(TIMER1_ENABLE, base + TIMER_CR);
+	moxart_enable(evt);
 	return 0;
 }
 
 static int moxart_clkevt_next_event(unsigned long cycles,
-				    struct clock_event_device *unused)
+				    struct clock_event_device *evt)
 {
 	u32 u;
 
-	writel(TIMER1_DISABLE, base + TIMER_CR);
+	moxart_disable(evt);
 
 	u = readl(base + TIMER1_BASE + REG_COUNT) - cycles;
 	writel(u, base + TIMER1_BASE + REG_MATCH1);
 
-	writel(TIMER1_ENABLE, base + TIMER_CR);
+	moxart_enable(evt);
 
 	return 0;
 }
-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:32:48 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:02:48 +0930
Subject: [PATCH 3/4] drivers/clocksource/moxart: Use struct to hold state
In-Reply-To: <1462797169-14512-1-git-send-email-joel@jms.id.au>
References: <1462797169-14512-1-git-send-email-joel@jms.id.au>
Message-ID: <1462797169-14512-4-git-send-email-joel@jms.id.au>

Add a struct moxart_timer to hold the driver state, including the
irqaction and struct clock_event_device.

Most importantly this holds values for enabling and disabling the timer,
so future support can be added for devices that use different bits for
enable/disable.

In preparation for future hardware support we add a MOXART prefix to the
existing values.

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/clocksource/moxart_timer.c | 143 ++++++++++++++++++++++---------------
 1 file changed, 84 insertions(+), 59 deletions(-)

diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c
index b00b2b21e8b3..d17e3eface87 100644
--- a/drivers/clocksource/moxart_timer.c
+++ b/drivers/clocksource/moxart_timer.c
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/clocksource.h>
 #include <linux/bitops.h>
+#include <linux/slab.h>
 
 #define TIMER1_BASE		0x00
 #define TIMER2_BASE		0x10
@@ -36,36 +37,51 @@
 #define TIMER_INTR_MASK		0x38
 
 /*
- * TIMER_CR flags:
+ * Moxart TIMER_CR flags:
  *
- * TIMEREG_CR_*_CLOCK	0: PCLK, 1: EXT1CLK
- * TIMEREG_CR_*_INT	overflow interrupt enable bit
+ * MOXART_CR_*_CLOCK	0: PCLK, 1: EXT1CLK
+ * MOXART_CR_*_INT	overflow interrupt enable bit
  */
-#define TIMEREG_CR_1_ENABLE	BIT(0)
-#define TIMEREG_CR_1_CLOCK	BIT(1)
-#define TIMEREG_CR_1_INT	BIT(2)
-#define TIMEREG_CR_2_ENABLE	BIT(3)
-#define TIMEREG_CR_2_CLOCK	BIT(4)
-#define TIMEREG_CR_2_INT	BIT(5)
-#define TIMEREG_CR_3_ENABLE	BIT(6)
-#define TIMEREG_CR_3_CLOCK	BIT(7)
-#define TIMEREG_CR_3_INT	BIT(8)
-#define TIMEREG_CR_COUNT_UP	BIT(9)
-
-#define TIMER1_ENABLE		(TIMEREG_CR_2_ENABLE | TIMEREG_CR_1_ENABLE)
-#define TIMER1_DISABLE		(TIMEREG_CR_2_ENABLE)
-
-static void __iomem *base;
-static unsigned int clock_count_per_tick;
+#define MOXART_CR_1_ENABLE	BIT(0)
+#define MOXART_CR_1_CLOCK	BIT(1)
+#define MOXART_CR_1_INT	BIT(2)
+#define MOXART_CR_2_ENABLE	BIT(3)
+#define MOXART_CR_2_CLOCK	BIT(4)
+#define MOXART_CR_2_INT	BIT(5)
+#define MOXART_CR_3_ENABLE	BIT(6)
+#define MOXART_CR_3_CLOCK	BIT(7)
+#define MOXART_CR_3_INT	BIT(8)
+#define MOXART_CR_COUNT_UP	BIT(9)
+
+#define MOXART_TIMER1_ENABLE	(MOXART_CR_2_ENABLE | MOXART_CR_1_ENABLE)
+#define MOXART_TIMER1_DISABLE	(MOXART_CR_2_ENABLE)
+
+struct moxart_timer {
+	void __iomem *base;
+	unsigned int t1_disable_val;
+	unsigned int t1_enable_val;
+	unsigned int count_per_tick;
+	struct clock_event_device clkevt;
+	struct irqaction act;
+};
+
+static inline struct moxart_timer *to_moxart(struct clock_event_device *evt)
+{
+	return container_of(evt, struct moxart_timer, clkevt);
+}
 
 static inline void moxart_disable(struct clock_event_device *evt)
 {
-	writel(TIMER1_DISABLE, base + TIMER_CR);
+	struct moxart_timer *timer = to_moxart(evt);
+
+	writel(timer->t1_disable_val, timer->base + TIMER_CR);
 }
 
 static inline void moxart_enable(struct clock_event_device *evt)
 {
-	writel(TIMER1_ENABLE, base + TIMER_CR);
+	struct moxart_timer *timer = to_moxart(evt);
+
+	writel(timer->t1_enable_val, timer->base + TIMER_CR);
 }
 
 static int moxart_shutdown(struct clock_event_device *evt)
@@ -77,13 +93,17 @@ static int moxart_shutdown(struct clock_event_device *evt)
 static int moxart_set_oneshot(struct clock_event_device *evt)
 {
 	moxart_disable(evt);
-	writel(~0, base + TIMER1_BASE + REG_LOAD);
+	writel(~0, to_moxart(evt)->base + TIMER1_BASE + REG_LOAD);
 	return 0;
 }
 
 static int moxart_set_periodic(struct clock_event_device *evt)
 {
-	writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD);
+	struct moxart_timer *timer = to_moxart(evt);
+
+	moxart_disable(evt);
+	writel(timer->count_per_tick, timer->base + TIMER1_BASE + REG_LOAD);
+	writel(0, timer->base + TIMER1_BASE + REG_MATCH1);
 	moxart_enable(evt);
 	return 0;
 }
@@ -91,30 +111,19 @@ static int moxart_set_periodic(struct clock_event_device *evt)
 static int moxart_clkevt_next_event(unsigned long cycles,
 				    struct clock_event_device *evt)
 {
+	struct moxart_timer *timer = to_moxart(evt);
 	u32 u;
 
 	moxart_disable(evt);
 
-	u = readl(base + TIMER1_BASE + REG_COUNT) - cycles;
-	writel(u, base + TIMER1_BASE + REG_MATCH1);
+	u = readl(timer->base + TIMER1_BASE + REG_COUNT) - cycles;
+	writel(u, timer->base + TIMER1_BASE + REG_MATCH1);
 
 	moxart_enable(evt);
 
 	return 0;
 }
 
-static struct clock_event_device moxart_clockevent = {
-	.name			= "moxart_timer",
-	.rating			= 200,
-	.features		= CLOCK_EVT_FEAT_PERIODIC |
-				  CLOCK_EVT_FEAT_ONESHOT,
-	.set_state_shutdown	= moxart_shutdown,
-	.set_state_periodic	= moxart_set_periodic,
-	.set_state_oneshot	= moxart_set_oneshot,
-	.tick_resume		= moxart_set_oneshot,
-	.set_next_event		= moxart_clkevt_next_event,
-};
-
 static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = dev_id;
@@ -122,49 +131,66 @@ static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static struct irqaction moxart_timer_irq = {
-	.name		= "moxart-timer",
-	.flags		= IRQF_TIMER,
-	.handler	= moxart_timer_interrupt,
-	.dev_id		= &moxart_clockevent,
-};
-
 static void __init moxart_timer_init(struct device_node *node)
 {
 	int ret, irq;
 	unsigned long pclk;
 	struct clk *clk;
+	struct moxart_timer *timer;
+
+	timer = kzalloc(sizeof(*timer), GFP_KERNEL);
+	if (!timer)
+		panic("Can't allocate timer struct\n");
 
-	base = of_iomap(node, 0);
-	if (!base)
+	timer->base = of_iomap(node, 0);
+	if (!timer->base)
 		panic("%s: of_iomap failed\n", node->full_name);
 
 	irq = irq_of_parse_and_map(node, 0);
 	if (irq <= 0)
 		panic("%s: irq_of_parse_and_map failed\n", node->full_name);
 
-	ret = setup_irq(irq, &moxart_timer_irq);
-	if (ret)
-		panic("%s: setup_irq failed\n", node->full_name);
-
 	clk = of_clk_get(node, 0);
 	if (IS_ERR(clk))
 		panic("%s: of_clk_get failed\n", node->full_name);
 
 	pclk = clk_get_rate(clk);
 
-	if (clocksource_mmio_init(base + TIMER2_BASE + REG_COUNT,
+	if (of_device_is_compatible(node, "moxa,moxart-timer")) {
+		timer->t1_enable_val = MOXART_TIMER1_ENABLE;
+		timer->t1_disable_val = MOXART_TIMER1_DISABLE;
+	} else
+		panic("%s: unknown platform\n", node->full_name);
+
+	timer->count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ);
+
+	timer->clkevt.name = node->name;
+	timer->clkevt.rating = 200;
+	timer->clkevt.features = CLOCK_EVT_FEAT_PERIODIC |
+					CLOCK_EVT_FEAT_ONESHOT;
+	timer->clkevt.set_state_shutdown = moxart_shutdown;
+	timer->clkevt.set_state_periodic = moxart_set_periodic;
+	timer->clkevt.set_state_oneshot = moxart_set_oneshot;
+	timer->clkevt.tick_resume = moxart_set_oneshot;
+	timer->clkevt.set_next_event = moxart_clkevt_next_event;
+	timer->clkevt.cpumask = cpumask_of(0);
+	timer->clkevt.irq = irq;
+	timer->act.name = node->name;
+	timer->act.flags = IRQF_TIMER;
+	timer->act.handler = moxart_timer_interrupt;
+	timer->act.dev_id = &timer->clkevt;
+
+	if (clocksource_mmio_init(timer->base + TIMER2_BASE + REG_COUNT,
 				  "moxart_timer", pclk, 200, 32,
 				  clocksource_mmio_readl_down))
 		panic("%s: clocksource_mmio_init failed\n", node->full_name);
 
-	clock_count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ);
-
-	writel(~0, base + TIMER2_BASE + REG_LOAD);
-	writel(TIMEREG_CR_2_ENABLE, base + TIMER_CR);
+	ret = setup_irq(irq, &timer->act);
+	if (ret)
+		panic("%s: setup_irq failed\n", node->full_name);
 
-	moxart_clockevent.cpumask = cpumask_of(0);
-	moxart_clockevent.irq = irq;
+	writel(~0, timer->base + TIMER2_BASE + REG_LOAD);
+	writel(timer->t1_disable_val, timer->base + TIMER_CR);
 
 	/*
 	 * documentation is not publicly available:
@@ -172,7 +198,6 @@ static void __init moxart_timer_init(struct device_node *node)
 	 * max_delta 0xfffffffe should be ok because count
 	 * register size is u32
 	 */
-	clockevents_config_and_register(&moxart_clockevent, pclk,
-					0x4, 0xfffffffe);
+	clockevents_config_and_register(&timer->clkevt, pclk, 0x4, 0xfffffffe);
 }
 CLOCKSOURCE_OF_DECLARE(moxart, "moxa,moxart-timer", moxart_timer_init);
-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:33:57 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:03:57 +0930
Subject: [PATCH 0/2] irqchip: Support Aspeed IRQ controller
Message-ID: <1462797239-14765-1-git-send-email-joel@jms.id.au>

Hello All,

This adds support for the IRQ controller found in the Aspeed ast2400 and
ast2500 BMC SoCs.

It's been tested on the ast2400 in an OpenPower Palmetto system, and on the
ast2500-edk developer kit.

Cheers,

Joel

Benjamin Herrenschmidt (1):
  irqchip: Add irq controller for Aspeed

Joel Stanley (1):
  doc/devicetree: Add Aspeed VIC bindings

 .../interrupt-controller/aspeed,ast2400-vic.txt    |  24 +++
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-aspeed-vic.c                   | 238 +++++++++++++++++++++
 3 files changed, 263 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
 create mode 100644 drivers/irqchip/irq-aspeed-vic.c

-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:33:58 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:03:58 +0930
Subject: [PATCH 1/2] doc/devicetree: Add Aspeed VIC bindings
In-Reply-To: <1462797239-14765-1-git-send-email-joel@jms.id.au>
References: <1462797239-14765-1-git-send-email-joel@jms.id.au>
Message-ID: <1462797239-14765-2-git-send-email-joel@jms.id.au>

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 .../interrupt-controller/aspeed,ast2400-vic.txt    | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
new file mode 100644
index 000000000000..10ed0c20ee6f
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
@@ -0,0 +1,24 @@
+Aspeed Vectored Interrupt Controller
+
+These bindings are for the Aspeed AST2400 interrupt controller register layout.
+The SoC has an legacy register layout, but this driver does not support that
+mode of operation.
+
+Required properties:
+
+- compatible : should be "aspeed,ast2400-vic".
+
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+- valid-sources : bitmask of valid irq sources
+
+Example:
+
+ vic: interrupt-controller {
+      compatible = "aspeed,ast2400-new-vic";
+      interrupt-controller;
+      #interrupt-cells = <1>;
+      valid-sources = < 0xffffffff 0x0007ffff>;
+      reg = <0x1e6c0080 0x80>;
+ };
-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:33:59 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:03:59 +0930
Subject: [PATCH 2/2] irqchip: Add irq controller for Aspeed
In-Reply-To: <1462797239-14765-1-git-send-email-joel@jms.id.au>
References: <1462797239-14765-1-git-send-email-joel@jms.id.au>
Message-ID: <1462797239-14765-3-git-send-email-joel@jms.id.au>

From: Benjamin Herrenschmidt <benh at kernel.crashing.org>

Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/irqchip/Makefile         |   1 +
 drivers/irqchip/irq-aspeed-vic.c | 238 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 239 insertions(+)
 create mode 100644 drivers/irqchip/irq-aspeed-vic.c

diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index b03cfcbbac6b..ec82e6e15a38 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -65,3 +65,4 @@ obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
 obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
 obj-$(CONFIG_PIC32_EVIC)		+= irq-pic32-evic.o
 obj-$(CONFIG_MVEBU_ODMI)		+= irq-mvebu-odmi.o
+obj-$(CONFIG_ARCH_ASPEED)		+= irq-aspeed-vic.o
diff --git a/drivers/irqchip/irq-aspeed-vic.c b/drivers/irqchip/irq-aspeed-vic.c
new file mode 100644
index 000000000000..db15fc3e831a
--- /dev/null
+++ b/drivers/irqchip/irq-aspeed-vic.c
@@ -0,0 +1,238 @@
+/*
+ *  Copyright (C) 2015 - Ben Herrenschmidt, IBM Corp.
+ *
+ *  Driver for Aspeed "new" VIC as found in SoC generation 3 and later
+ *
+ *  Based on irq-vic.c:
+ *
+ *  Copyright (C) 1999 - 2003 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * 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/export.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/syscore_ops.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+
+#include <asm/exception.h>
+#include <asm/irq.h>
+
+/* These definitions correspond to the "new mapping" of the
+ * register set that interleaves "high" and "low". The offsets
+ * below are for the "low" register, add 4 to get to the high one
+ */
+#define AVIC_IRQ_STATUS		0x00
+#define AVIC_FIQ_STATUS		0x08
+#define AVIC_RAW_STATUS		0x10
+#define AVIC_INT_SELECT		0x18
+#define AVIC_INT_ENABLE		0x20
+#define AVIC_INT_ENABLE_CLR	0x28
+#define AVIC_INT_TRIGGER	0x30
+#define AVIC_INT_TRIGGER_CLR	0x38
+#define AVIC_INT_SENSE		0x40
+#define AVIC_INT_DUAL_EDGE	0x48
+#define AVIC_INT_EVENT		0x50
+#define AVIC_EDGE_CLR		0x58
+#define AVIC_EDGE_STATUS	0x60
+
+struct aspeed_vic {
+	void __iomem		*base;
+	u32			valid_sources[2];
+	u32			edge_sources[2];
+	struct irq_domain	*dom;
+};
+static struct aspeed_vic *system_avic;
+
+static void vic_init_hw(struct aspeed_vic *vic)
+{
+	u32 sense;
+
+	/* Disable all interrupts */
+	writel(0xffffffff, vic->base + AVIC_INT_ENABLE_CLR);
+	writel(0xffffffff, vic->base + AVIC_INT_ENABLE_CLR + 4);
+
+	/* Make sure no soft trigger is on */
+	writel(0xffffffff, vic->base + AVIC_INT_TRIGGER_CLR);
+	writel(0xffffffff, vic->base + AVIC_INT_TRIGGER_CLR + 4);
+
+	/* Set everything to be IRQ */
+	writel(0, vic->base + AVIC_INT_SELECT);
+	writel(0, vic->base + AVIC_INT_SELECT + 4);
+
+	/* Some interrupts have a programable high/low level trigger
+	 * (4 GPIO direct inputs), for now we assume this was configured
+	 * by firmware. We read which ones are edge now.
+	 */
+	sense = readl(vic->base + AVIC_INT_SENSE);
+	vic->edge_sources[0] = ~sense;
+	sense = readl(vic->base + AVIC_INT_SENSE + 4);
+	vic->edge_sources[1] = ~sense;
+
+	/* Clear edge detection latches */
+	writel(0xffffffff, vic->base + AVIC_EDGE_CLR);
+	writel(0xffffffff, vic->base + AVIC_EDGE_CLR + 4);
+}
+
+static void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
+{
+	struct aspeed_vic *vic = system_avic;
+	u32 stat, irq;
+
+	for (;;) {
+		irq = 0;
+		stat = readl_relaxed(vic->base + AVIC_IRQ_STATUS);
+		if (!stat) {
+			stat = readl_relaxed(vic->base + AVIC_IRQ_STATUS + 4);
+			irq = 32;
+		}
+		if (stat == 0)
+			break;
+		irq += ffs(stat) - 1;
+		handle_domain_irq(vic->dom, irq, regs);
+	}
+}
+
+static void avic_ack_irq(struct irq_data *d)
+{
+	struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+	unsigned int sidx = d->hwirq >> 5;
+	unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+	/* Clear edge latch for edge interrupts, nop for level */
+	if (vic->edge_sources[sidx] & sbit)
+		writel(sbit, vic->base + AVIC_EDGE_CLR + sidx * 4);
+}
+
+static void avic_mask_irq(struct irq_data *d)
+{
+	struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+	unsigned int sidx = d->hwirq >> 5;
+	unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+	writel(sbit, vic->base + AVIC_INT_ENABLE_CLR + sidx * 4);
+}
+
+static void avic_unmask_irq(struct irq_data *d)
+{
+	struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+	unsigned int sidx = d->hwirq >> 5;
+	unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+	writel(sbit, vic->base + AVIC_INT_ENABLE + sidx * 4);
+}
+
+/* For level irq, faster than going through a nop "ack" and mask */
+static void avic_mask_ack_irq(struct irq_data *d)
+{
+	struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+	unsigned int sidx = d->hwirq >> 5;
+	unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+	/* First mask */
+	writel(sbit, vic->base + AVIC_INT_ENABLE_CLR + sidx * 4);
+
+	/* Then clear edge latch for edge interrupts */
+	if (vic->edge_sources[sidx] & sbit)
+		writel(sbit, vic->base + AVIC_EDGE_CLR + sidx * 4);
+}
+
+static struct irq_chip avic_chip = {
+	.name		= "AVIC",
+	.irq_ack	= avic_ack_irq,
+	.irq_mask	= avic_mask_irq,
+	.irq_unmask	= avic_unmask_irq,
+	.irq_mask_ack	= avic_mask_ack_irq,
+};
+
+static int avic_map(struct irq_domain *d, unsigned int irq,
+		    irq_hw_number_t hwirq)
+{
+	struct aspeed_vic *vic = d->host_data;
+	unsigned int sidx = hwirq >> 5;
+	unsigned int sbit = 1u << (hwirq & 0x1f);
+
+	/* Check if interrupt exists */
+	if (sidx > 1 || !(vic->valid_sources[sidx] & sbit))
+		return -EPERM;
+
+	if (vic->edge_sources[sidx] & sbit)
+		irq_set_chip_and_handler(irq, &avic_chip, handle_edge_irq);
+	else
+		irq_set_chip_and_handler(irq, &avic_chip, handle_level_irq);
+	irq_set_chip_data(irq, vic);
+	irq_set_probe(irq);
+	return 0;
+}
+
+static struct irq_domain_ops avic_dom_ops = {
+	.map = avic_map,
+	.xlate = irq_domain_xlate_onetwocell,
+};
+
+static int __init avic_of_init(struct device_node *node,
+			       struct device_node *parent)
+{
+	void __iomem *regs;
+	struct aspeed_vic *vic;
+	int nirqs;
+
+	if (WARN(parent, "non-root Aspeed VIC not supported"))
+		return -EINVAL;
+	if (WARN(system_avic, "duplicate Aspeed VIC not supported"))
+		return -EINVAL;
+
+	regs = of_iomap(node, 0);
+	if (WARN_ON(!regs))
+		return -EIO;
+
+	vic = kzalloc(sizeof(struct aspeed_vic), GFP_KERNEL);
+	if (WARN_ON(!vic)) {
+		iounmap(regs);
+		return -ENOMEM;
+	}
+	vic->base = regs;
+
+	of_property_read_u32_index(node, "valid-sources", 0,
+				   &vic->valid_sources[0]);
+	of_property_read_u32_index(node, "valid-sources", 1,
+				   &vic->valid_sources[1]);
+
+	nirqs = hweight32(vic->valid_sources[0]) +
+		hweight32(vic->valid_sources[1]);
+
+	/* Initialize soures, all masked */
+	vic_init_hw(vic);
+
+	/* Ready to receive interrupts */
+	system_avic = vic;
+	set_handle_irq(avic_handle_irq);
+
+	/* Register our domain */
+	vic->dom = irq_domain_add_simple(node, nirqs, 0,
+					 &avic_dom_ops, vic);
+
+	return 0;
+}
+
+IRQCHIP_DECLARE(aspeed_new_vic, "aspeed,ast2400-vic", avic_of_init);
-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:34:35 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:04:35 +0930
Subject: [PATCH 0/2] watchdog: Add Aspeed watchdog driver
Message-ID: <1462797277-14969-1-git-send-email-joel@jms.id.au>

These patches add support for the watchdog timer found in Aspeed ast2400 and
ast2500 BMC SoCs.

The u-boot that ships on the edk and with many systems leaves the watchdog
running when jumping to the kernel, making this driver required for operation.

It has been tested on the ast2400 in an OpenPower Palmetto, and the ast2500-edk
dev board.

Cheers,

Joel

Joel Stanley (2):
  doc/devicetree: Add Aspeed watchdog timer bindings
  watchdog: Add Aspeed watchdog driver

 .../devicetree/bindings/watchdog/aspeed-wdt.txt    |  14 ++
 drivers/watchdog/Kconfig                           |  13 ++
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/aspeed_wdt.c                      | 199 +++++++++++++++++++++
 4 files changed, 227 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
 create mode 100644 drivers/watchdog/aspeed_wdt.c

-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:34:36 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:04:36 +0930
Subject: [PATCH 1/2] doc/devicetree: Add Aspeed watchdog timer bindings
In-Reply-To: <1462797277-14969-1-git-send-email-joel@jms.id.au>
References: <1462797277-14969-1-git-send-email-joel@jms.id.au>
Message-ID: <1462797277-14969-2-git-send-email-joel@jms.id.au>

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
new file mode 100644
index 000000000000..58184b161e0d
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
@@ -0,0 +1,14 @@
+Aspeed Watchdog Timer
+
+Required properties:
+ - compatible: must be "aspeed,wdt"
+ - reg: physical base address of the controller and length of memory mapped
+   region
+
+Example:
+
+	wdt1: wdt at 1e785000 {
+		compatible = "aspeed,wdt";
+		reg = <0x1e785000 0x1c>;
+		interrupts = <27>;
+	};
-- 
2.8.1



From joel at jms.id.au  Mon May  9 05:34:37 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:04:37 +0930
Subject: [PATCH 2/2] watchdog: Add Aspeed watchdog driver
In-Reply-To: <1462797277-14969-1-git-send-email-joel@jms.id.au>
References: <1462797277-14969-1-git-send-email-joel@jms.id.au>
Message-ID: <1462797277-14969-3-git-send-email-joel@jms.id.au>

Provides generic watchdog features as well as reboot support for the
Apeed SoC.

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/watchdog/Kconfig      |  13 +++
 drivers/watchdog/Makefile     |   1 +
 drivers/watchdog/aspeed_wdt.c | 199 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 213 insertions(+)
 create mode 100644 drivers/watchdog/aspeed_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fb947655badd..4f0e2ded4785 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -661,6 +661,19 @@ config ATLAS7_WATCHDOG
 	  To compile this driver as a module, choose M here: the
 	  module will be called atlas7_wdt.
 
+config ASPEED_WATCHDOG
+	tristate "Aspeed 2400 watchdog support"
+	depends on ARCH_ASPEED || COMPILE_TEST
+	select WATCHDOG_CORE
+	help
+	  Say Y here to include support for the watchdog timer
+	  in Apseed BMC SoCs.
+
+	  This driver is required to reboot the SoC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called aspeed_wdt.
+
 # AVR32 Architecture
 
 config AT32AP700X_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index feb6270fdbde..36855375e0ce 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
 obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
 obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o
+obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
new file mode 100644
index 000000000000..46cc71963c62
--- /dev/null
+++ b/drivers/watchdog/aspeed_wdt.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2016 IBM Corporation
+ *
+ * Joel Stanley <joel at jms.id.au>
+ *
+ * Based on the qcom-watchdog driver
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/watchdog.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+struct aspeed_wdt {
+	struct watchdog_device	wdd;
+	unsigned long		rate;
+	void __iomem		*base;
+	u32			ctrl;
+};
+
+static const struct of_device_id aspeed_wdt_of_table[] = {
+	{ .compatible = "aspeed,wdt" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
+
+#define WDT_STATUS		0x00
+#define WDT_RELOAD_VALUE	0x04
+#define WDT_RESTART		0x08
+#define WDT_CTRL		0x0C
+#define   WDT_CTRL_RESET_MODE_SOC	(0x00 << 5)
+#define   WDT_CTRL_RESET_MODE_FULL_CHIP	(0x01 << 5)
+#define	  WDT_CTRL_1MHZ_CLK		BIT(4)
+#define	  WDT_CTRL_WDT_EXT		BIT(3)
+#define	  WDT_CTRL_WDT_INTR		BIT(2)
+#define   WDT_CTRL_RESET_SYSTEM		BIT(1)
+#define   WDT_CTRL_ENABLE		BIT(0)
+
+#define	WDT_RESTART_MAGIC	0x4755
+
+static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd)
+{
+	return container_of(wdd, struct aspeed_wdt, wdd);
+}
+
+
+static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
+{
+	wdt->ctrl |= WDT_CTRL_ENABLE;
+
+	writel(0, wdt->base + WDT_CTRL);
+	writel(count, wdt->base + WDT_RELOAD_VALUE);
+	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
+	writel(wdt->ctrl, wdt->base + WDT_CTRL);
+}
+
+static int aspeed_wdt_start(struct watchdog_device *wdd)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+
+	dev_dbg(wdd->parent, "starting with timeout of %d (rate %lu)\n",
+			wdd->timeout, wdt->rate);
+	aspeed_wdt_enable(wdt, wdd->timeout * wdt->rate);
+
+	return 0;
+}
+
+static int aspeed_wdt_stop(struct watchdog_device *wdd)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+
+	wdt->ctrl &= ~WDT_CTRL_ENABLE;
+	writel(wdt->ctrl, wdt->base + WDT_CTRL);
+
+	return 0;
+}
+
+static int aspeed_wdt_ping(struct watchdog_device *wdd)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+
+	dev_dbg(wdd->parent, "ping\n");
+	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
+	return 0;
+}
+
+static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
+				  unsigned int timeout)
+{
+	dev_dbg(wdd->parent, "timeout set to %u\n", timeout);
+	wdd->timeout = timeout;
+
+	return aspeed_wdt_start(wdd);
+}
+
+static int aspeed_wdt_restart(struct watchdog_device *wdd,
+			      unsigned long action, void *data)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+
+	aspeed_wdt_enable(wdt, 128 * wdt->rate / 1000);
+
+	return 0;
+}
+
+static const struct watchdog_ops aspeed_wdt_ops = {
+	.start		= aspeed_wdt_start,
+	.stop		= aspeed_wdt_stop,
+	.ping		= aspeed_wdt_ping,
+	.set_timeout	= aspeed_wdt_set_timeout,
+	.restart	= aspeed_wdt_restart,
+	.owner		= THIS_MODULE,
+};
+
+static const struct watchdog_info aspeed_wdt_info = {
+	.options	= WDIOF_KEEPALIVEPING
+			| WDIOF_MAGICCLOSE
+			| WDIOF_SETTIMEOUT,
+	.identity	= KBUILD_MODNAME,
+};
+
+static int aspeed_wdt_remove(struct platform_device *pdev)
+{
+	struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
+
+	watchdog_unregister_device(&wdt->wdd);
+
+	return 0;
+}
+
+static int aspeed_wdt_probe(struct platform_device *pdev)
+{
+	struct aspeed_wdt *wdt;
+	struct resource *res;
+	int ret;
+
+	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+	if (!wdt)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	wdt->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(wdt->base))
+		return PTR_ERR(wdt->base);
+
+	/*
+	 * The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only
+	 * runs at 1MHz. We chose to always run at 1MHz, as there's no
+	 * good reason to have a faster watchdog counter.
+	 */
+	wdt->rate = 1000000;
+	wdt->wdd.info = &aspeed_wdt_info;
+	wdt->wdd.ops = &aspeed_wdt_ops;
+	wdt->wdd.min_timeout = 1;
+	wdt->wdd.max_timeout = 0x10000000U / wdt->rate;
+	wdt->wdd.parent = &pdev->dev;
+
+	wdt->wdd.timeout = min(wdt->wdd.max_timeout, 30U);
+	watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
+
+	wdt->ctrl = WDT_CTRL_RESET_MODE_SOC |
+		WDT_CTRL_1MHZ_CLK |
+		WDT_CTRL_RESET_SYSTEM;
+
+	/* Ensure hardware is in consistent state */
+	aspeed_wdt_stop(&wdt->wdd);
+
+	ret = watchdog_register_device(&wdt->wdd);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register\n");
+		goto err;
+	}
+
+	dev_info(&pdev->dev, "rate %lu, max timeout %u, timeout %d\n",
+		 wdt->rate, wdt->wdd.max_timeout, wdt->wdd.timeout);
+
+	platform_set_drvdata(pdev, wdt);
+err:
+	return ret;
+}
+
+static struct platform_driver aspeed_watchdog_driver = {
+	.probe = aspeed_wdt_probe,
+	.remove = aspeed_wdt_remove,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.of_match_table = of_match_ptr(aspeed_wdt_of_table),
+	},
+};
+module_platform_driver(aspeed_watchdog_driver);
+
+MODULE_DESCRIPTION("Aspeed Watchdog Driver");
+MODULE_LICENSE("GPL");
-- 
2.8.1



From van.freenix at gmail.com  Mon May  9 05:41:43 2016
From: van.freenix at gmail.com (Peng Fan)
Date: Mon, 9 May 2016 20:41:43 +0800
Subject: [PATCH V2 3/3] nvmem: imx-ocotp: handling clock
In-Reply-To: <5730825E.5030101@linaro.org>
References: <1461173177-11930-1-git-send-email-van.freenix@gmail.com>
 <1461173177-11930-3-git-send-email-van.freenix@gmail.com>
 <5730825E.5030101@linaro.org>
Message-ID: <20160509124140.GA20259@linux-7smt.suse>

Hi Srinivas,

On Mon, May 09, 2016 at 01:28:14PM +0100, Srinivas Kandagatla wrote:
>Thanks for the Ping, I totally missed this thread.
>
>On 20/04/16 18:26, Peng Fan wrote:
>>Before access ocotp nvmem area, the clock should be enabled.
>>Or, `hexdump nvmem` will hang the system. So, use such flow:
>>"
>>   1. clock_enable_prepare
>>   2. read nvmem ocotp area
>>   3. clock_disable_unprepare
>>"
>>
>>Signed-off-by: Peng Fan <van.freenix at gmail.com>
>>Cc: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
>>Cc: Maxime Ripard <maxime.ripard at free-electrons.com>
>>Cc: Shawn Guo <shawnguo at kernel.org>
>>---
>>
>>V2:
>>  Follow Fabio's comments, check return value of clk_prepare_enable
>>
>>  drivers/nvmem/imx-ocotp.c | 16 +++++++++++++++-
>>  1 file changed, 15 insertions(+), 1 deletion(-)
>
>Changes to the driver looks good to me,
>Only one comment, As the clock property is now made mandatory, you should
>update the dt-bindings with this info too.

In Documentation/devicetree/bindings/nvmem/imx-ocotp.txt,
the clock property is already marked Required properties:
"
Required properties:
- compatible: should be one of
	"fsl,imx6q-ocotp" (i.MX6Q/D/DL/S),
	"fsl,imx6sl-ocotp" (i.MX6SL), or
	"fsl,imx6sx-ocotp" (i.MX6SX), followed by "syscon".
- reg: Should contain the register base and length.
- clocks: Should contain a phandle pointing to the gated peripheral clock.

Example:

	ocotp: ocotp at 021bc000 {
		compatible = "fsl,imx6q-ocotp", "syscon";
		reg = <0x021bc000 0x4000>;
		clocks = <&clks IMX6QDL_CLK_IIM>;
	};
"

I think I do not need to update it, since it's already there -:)

Thanks,
Peng.
>
>
>thanks,
>srini


From joel at jms.id.au  Mon May  9 05:41:43 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon, 9 May 2016 22:11:43 +0930
Subject: [PULL REQUEST] aspeed arch changes for 4.7
In-Reply-To: <1462796946-13579-1-git-send-email-joel@jms.id.au>
References: <1462796946-13579-1-git-send-email-joel@jms.id.au>
Message-ID: <CACPK8Xd6i0Fh79YBmF3FO--vfO+hEUxfTsTDyDxqUushhScRwg@mail.gmail.com>

On Mon, May 9, 2016 at 9:59 PM, Joel Stanley <joel at jms.id.au> wrote:
> Hello,
>
> This is the initial pull request for the Aspeed BMC SoCs.

As you can see, this being my first time and all, I chose to use the
"PULL REQUEST" tag instead of the more traditional "GIT PULL".

I'll be sure to get it correct next time.

Cheers,

Joel

>
> I put 4.7 in the subject for this and the subsequent requests but if it's a bit
> late in the cycle then I understand.
>
> Following review I got rid of the board file by pushing the functionality out
> to a watchdog and clock driver, so it's just the Kconfig bits. I've also added
> myself to maintainers for the Aspeed arch and drivers as I intend on looking
> after them.
>
> Please pull if it looks okay.
>
>
> The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:
>
>   Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)
>
> are available in the git repository at:
>
>   https://github.com/shenki/linux.git tags/aspeed-for-4.7-arch
>
> for you to fetch changes up to 8c2ed9bcfbeb7f313b567b25e87effd75e7dc3d6:
>
>   arm: Add Aspeed machine (2016-05-09 17:41:14 +0930)
>
> ----------------------------------------------------------------
> aspeed arch tag for 4.7
>
> ----------------------------------------------------------------
> Joel Stanley (1):
>       arm: Add Aspeed machine
>
>  MAINTAINERS                  |  7 +++++++
>  arch/arm/Kconfig             |  2 ++
>  arch/arm/mach-aspeed/Kconfig | 30 ++++++++++++++++++++++++++++++
>  3 files changed, 39 insertions(+)
>  create mode 100644 arch/arm/mach-aspeed/Kconfig
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From absahu at codeaurora.org  Mon May  9 05:44:29 2016
From: absahu at codeaurora.org (Abhishek Sahu)
Date: Mon,  9 May 2016 18:14:29 +0530
Subject: [PATCH 0/2] i2c: qup: Fixed the DMA transfer errors
Message-ID: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>

These patches contain the I2C QUP (Qualcomm Universal Peripheral) DMA
related fixes. The first patch cleared the error bits in ISR, which
resolves the kernel hang for I2C bus errors and DMA transfer. The
second patch fixed the DMA segments length, which resolves the issue
for I2C transfer failure over 255 bytes.

Abhishek Sahu (2):
  drivers: i2c: qup: Cleared the error bits in ISR
  drivers: i2c: qup: Fixed the DMA segments length

 drivers/i2c/busses/i2c-qup.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

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



From absahu at codeaurora.org  Mon May  9 05:44:30 2016
From: absahu at codeaurora.org (Abhishek Sahu)
Date: Mon,  9 May 2016 18:14:30 +0530
Subject: [PATCH 1/2] i2c: qup: Cleared the error bits in ISR
In-Reply-To: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
Message-ID: <1462797871-8595-2-git-send-email-absahu@codeaurora.org>

1. Current QCOM I2C driver hangs when sending data to address 0x03-0x07
in some scenarios. The QUP controller generates invalid write in this
case, since these addresses are reserved for different bus formats.

2. Also, the error handling is done by I2C QUP ISR in the case of DMA
mode. The state need to be RESET in case of any error for clearing the
available data in FIFO, which otherwise leaves the BAM DMA controller
in hang state.

This patch fixes the above two issues by clearing the error bits from
I2C and QUP status in ISR in case of I2C error, QUP error and resets
the QUP state to clear the FIFO data.

Signed-off-by: Abhishek Sahu <absahu at codeaurora.org>
---
 drivers/i2c/busses/i2c-qup.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 23eaabb..8c2f1bc 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -213,14 +213,16 @@ static irqreturn_t qup_i2c_interrupt(int irq, void *dev)
 	bus_err &= I2C_STATUS_ERROR_MASK;
 	qup_err &= QUP_STATUS_ERROR_FLAGS;
 
-	if (qup_err) {
-		/* Clear Error interrupt */
+	/* Clear the error bits in QUP_ERROR_FLAGS */
+	if (qup_err)
 		writel(qup_err, qup->base + QUP_ERROR_FLAGS);
-		goto done;
-	}
 
-	if (bus_err) {
-		/* Clear Error interrupt */
+	/* Clear the error bits in QUP_I2C_STATUS */
+	if (bus_err)
+		writel(bus_err, qup->base + QUP_I2C_STATUS);
+
+	/* Reset the QUP State in case of error */
+	if (qup_err || bus_err) {
 		writel(QUP_RESET_STATE, qup->base + QUP_STATE);
 		goto done;
 	}
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



From absahu at codeaurora.org  Mon May  9 05:44:31 2016
From: absahu at codeaurora.org (Abhishek Sahu)
Date: Mon,  9 May 2016 18:14:31 +0530
Subject: [PATCH 2/2] i2c: qup: Fixed the DMA segments length
In-Reply-To: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
Message-ID: <1462797871-8595-3-git-send-email-absahu@codeaurora.org>

1. The current QCOM I2C driver code is failing for transfer length
greater than 255. This is happening due to improper segments length
as the I2C DMA segments can be maximum of 256 bytes.

2. The transfer length tlen was being initialized with 0 for 256
bytes, which is being passed for DMA mappings resulting in improper
DMA mapping length.

This patch fixes the above said problems by initializing the block
count with the values calculated in qup_i2c_set_blk_data and calculating
the remaining length for last DMA segment. Also, the block data length
need to be decremented after each transfer. Additionally, this patch
corrects the tlen assignment for DMA mapping.

Signed-off-by: Abhishek Sahu <absahu at codeaurora.org>
---
 drivers/i2c/busses/i2c-qup.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 8c2f1bc..6d6b7dc 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -651,23 +651,24 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 	u8 *tags;
 
 	while (idx < num) {
-		blocks = (msg->len + limit) / limit;
-		rem = msg->len % limit;
 		tx_len = 0, len = 0, i = 0;
 
 		qup->is_last = (idx == (num - 1));
 
 		qup_i2c_set_blk_data(qup, msg);
 
+		blocks = qup->blk.count;
+		rem = msg->len - (blocks - 1) * limit;
+
 		if (msg->flags & I2C_M_RD) {
 			rx_nents += (blocks * 2) + 1;
 			tx_nents += 1;
 
 			while (qup->blk.pos < blocks) {
-				/* length set to '0' implies 256 bytes */
-				tlen = (i == (blocks - 1)) ? rem : 0;
+				tlen = (i == (blocks - 1)) ? rem : limit;
 				tags = &qup->start_tag.start[off + len];
 				len += qup_i2c_set_tags(tags, qup, msg, 1);
+				qup->blk.data_len -= tlen;
 
 				/* scratch buf to read the start and len tags */
 				ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
@@ -706,9 +707,10 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 			tx_nents += (blocks * 2);
 
 			while (qup->blk.pos < blocks) {
-				tlen = (i == (blocks - 1)) ? rem : 0;
+				tlen = (i == (blocks - 1)) ? rem : limit;
 				tags = &qup->start_tag.start[off + tx_len];
 				len = qup_i2c_set_tags(tags, qup, msg, 1);
+				qup->blk.data_len -= tlen;
 
 				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
 						     tags,
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



From kevin.brodsky at arm.com  Mon May  9 05:36:59 2016
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon,  9 May 2016 13:36:59 +0100
Subject: [PATCH 0/2] arm64: Add support for CLOCK_MONOTONIC_RAW in
 clock_gettime() vDSO
Message-ID: <1462797421-33103-1-git-send-email-kevin.brodsky@arm.com>

Hi,

This small series adds support for CLOCK_MONOTONIC_RAW to
clock_gettime() (and clock_getres()) in the arm64 vDSO. This should make
calls to clock_gettime() with CLOCK_MONOTONIC_RAW just as fast as
CLOCK_MONOTONIC and such, instead of falling back to the significantly
slower syscall.

Given that gettimeofday.S is already quite difficult to understand, and
directly adding MONOTONIC_RAW support makes it even more so, the first
patch refactors it to make it simpler, and save a few instructions along
the way. The second patch actually adds support for MONOTONIC_RAW, which
is made quite easy by the refactoring.

Thanks,
Kevin

Kevin Brodsky (2):
  arm64: Refactor vDSO time functions
  arm64: Add support for CLOCK_MONOTONIC_RAW in clock_gettime() vDSO

 arch/arm64/include/asm/vdso_datapage.h |   8 +-
 arch/arm64/kernel/asm-offsets.c        |   6 +-
 arch/arm64/kernel/vdso.c               |   8 +-
 arch/arm64/kernel/vdso/gettimeofday.S  | 317 ++++++++++++++++++++-------------
 4 files changed, 215 insertions(+), 124 deletions(-)

-- 
2.8.0



From kevin.brodsky at arm.com  Mon May  9 05:37:00 2016
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon,  9 May 2016 13:37:00 +0100
Subject: [PATCH 1/2] arm64: Refactor vDSO time functions
In-Reply-To: <1462797421-33103-1-git-send-email-kevin.brodsky@arm.com>
References: <1462797421-33103-1-git-send-email-kevin.brodsky@arm.com>
Message-ID: <1462797421-33103-2-git-send-email-kevin.brodsky@arm.com>

Time functions are directly implemented in assembly in arm64, and it
is desirable to keep it this way for performance reasons (everything
fits in registers, so that the stack is not used at all). However, the
current implementation is quite difficult to read and understand (even
considering it's assembly).  Additionally, due to the structure of
__kernel_clock_gettime, which heavily uses conditional branches to
share code between the different clocks, it is difficult to support a
new clock without making the branches even harder to follow.

This commit completely refactors the structure of clock_gettime (and
gettimeofday along the way) while keeping exactly the same algorithms.
We no longer try to share code; instead, macros provide common
operations. This new approach comes with a number of advantages:
- In clock_gettime, clock implementations are no longer interspersed,
  making them much more readable. Additionally, macros only use
  registers passed as arguments or reserved with .req, this way it is
  easy to make sure that registers are properly allocated. To avoid a
  large number of branches in a given execution path, a jump table is
  used; a normal execution uses 3 unconditional branches.
- __do_get_tspec has been replaced with 2 macros (get_ts_clock_mono,
  get_clock_shifted_nsec) and explicit loading of data from the vDSO
  page. Consequently, clock_gettime and gettimeofday are now leaf
  functions, and saving x30 (lr) is no longer necessary.
- Variables protected by tb_seq_count are now loaded all at once,
  allowing to merge the seqcnt_read macro into seqcnt_check.
- For CLOCK_REALTIME_COARSE, removed an unused load of the wall to
  monotonic timespec.
- For CLOCK_MONOTONIC_COARSE, removed a few shift instructions.

Obviously, the downside of sharing less code is an increase in code
size. However since the vDSO has its own code page, this does not
really matter, as long as the size of the DSO remains below 4 kB. For
now this should be all right:
                    Before  After
  vdso.so size (B)  2776    2936

Cc: Will Deacon <will.deacon at arm.com>
Cc: Dave Martin <dave.martin at arm.com>
Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 arch/arm64/kernel/vdso/gettimeofday.S | 282 +++++++++++++++++++---------------
 1 file changed, 162 insertions(+), 120 deletions(-)

diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index efa79e8d4196..caff9dd6ba78 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -26,24 +26,91 @@
 #define NSEC_PER_SEC_HI16	0x3b9a
 
 vdso_data	.req	x6
-use_syscall	.req	w7
-seqcnt		.req	w8
+seqcnt		.req	w7
+w_tmp		.req	w8
+x_tmp		.req	x8
+
+/*
+ * Conventions for macro arguments:
+ * - An argument is write-only if its name starts with "res".
+ * - All other arguments are read-only, unless otherwise specified.
+ */
 
 	.macro	seqcnt_acquire
 9999:	ldr	seqcnt, [vdso_data, #VDSO_TB_SEQ_COUNT]
 	tbnz	seqcnt, #0, 9999b
 	dmb	ishld
-	ldr	use_syscall, [vdso_data, #VDSO_USE_SYSCALL]
 	.endm
 
-	.macro	seqcnt_read, cnt
+	.macro	seqcnt_check fail
 	dmb	ishld
-	ldr	\cnt, [vdso_data, #VDSO_TB_SEQ_COUNT]
+	ldr	w_tmp, [vdso_data, #VDSO_TB_SEQ_COUNT]
+	cmp	w_tmp, seqcnt
+	b.ne	\fail
 	.endm
 
-	.macro	seqcnt_check, cnt, fail
-	cmp	\cnt, seqcnt
-	b.ne	\fail
+	.macro	syscall_check fail
+	ldr	w_tmp, [vdso_data, #VDSO_USE_SYSCALL]
+	cbnz	w_tmp, \fail
+	.endm
+
+	.macro get_nsec_per_sec res
+	mov	\res, #NSEC_PER_SEC_LO16
+	movk	\res, #NSEC_PER_SEC_HI16, lsl #16
+	.endm
+
+	/*
+	 * Returns the clock delta, in nanoseconds left-shifted by the clock
+	 * shift.
+	 */
+	.macro	get_clock_shifted_nsec res, cycle_last, mult
+	/* Read the virtual counter. */
+	isb
+	mrs	x_tmp, cntvct_el0
+	/* Calculate cycle delta and convert to ns. */
+	sub	\res, x_tmp, \cycle_last
+	/* We can only guarantee 56 bits of precision. */
+	movn	x_tmp, #0xff00, lsl #48
+	and	\res, x_tmp, \res
+	mul	\res, \res, \mult
+	.endm
+
+	/*
+	 * Returns in res_{sec,nsec} the REALTIME timespec, based on the
+	 * "wall time" (xtime) and the clock_mono delta.
+	 */
+	.macro	get_ts_realtime res_sec, res_nsec, \
+			clock_nsec, xtime_sec, xtime_nsec, nsec_to_sec
+	add	\res_nsec, \clock_nsec, \xtime_nsec
+	udiv	x_tmp, \res_nsec, \nsec_to_sec
+	add	\res_sec, \xtime_sec, x_tmp
+	msub	\res_nsec, x_tmp, \nsec_to_sec, \res_nsec
+	.endm
+
+	/* sec and nsec are modified in place. */
+	.macro add_ts sec, nsec, ts_sec, ts_nsec, nsec_to_sec
+	/* Add timespec. */
+	add	\sec, \sec, \ts_sec
+	add	\nsec, \nsec, \ts_nsec
+
+	/* Normalise the new timespec. */
+	cmp	\nsec, \nsec_to_sec
+	b.lt	9999f
+	sub	\nsec, \nsec, \nsec_to_sec
+	add	\sec, \sec, #1
+9999:
+	cmp	\nsec, #0
+	b.ge	9998f
+	add	\nsec, \nsec, \nsec_to_sec
+	sub	\sec, \sec, #1
+9998:
+	.endm
+
+	.macro jump_slot jumptable, index, label
+	.if (. - \jumptable) != 4 * (\index)
+		.error "Jump slot index mismatch"
+	.endif
+	b	\label
 	.endm
 
 	.text
@@ -51,18 +118,24 @@ seqcnt		.req	w8
 /* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */
 ENTRY(__kernel_gettimeofday)
 	.cfi_startproc
-	mov	x2, x30
-	.cfi_register x30, x2
-
-	/* Acquire the sequence counter and get the timespec. */
 	adr	vdso_data, _vdso_data
-1:	seqcnt_acquire
-	cbnz	use_syscall, 4f
-
 	/* If tv is NULL, skip to the timezone code. */
 	cbz	x0, 2f
-	bl	__do_get_tspec
-	seqcnt_check w9, 1b
+
+	/* Compute the time of day. */
+1:	seqcnt_acquire
+	syscall_check fail=4f
+	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
+	ldp	w11, w12, [vdso_data, #VDSO_CS_MULT]
+	ldp	x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
+	seqcnt_check fail=1b
+
+	get_nsec_per_sec res=x9
+	lsl	x9, x9, x12
+
+	get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
+	get_ts_realtime res_sec=x10, res_nsec=x11, \
+		clock_nsec=x15, xtime_sec=x13, xtime_nsec=x14, nsec_to_sec=x9
 
 	/* Convert ns to us. */
 	mov	x13, #1000
@@ -76,95 +149,107 @@ ENTRY(__kernel_gettimeofday)
 	stp	w4, w5, [x1, #TZ_MINWEST]
 3:
 	mov	x0, xzr
-	ret	x2
+	ret
 4:
 	/* Syscall fallback. */
 	mov	x8, #__NR_gettimeofday
 	svc	#0
-	ret	x2
+	ret
 	.cfi_endproc
 ENDPROC(__kernel_gettimeofday)
 
+#define JUMPSLOT_MAX CLOCK_MONOTONIC_COARSE
+
 /* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */
 ENTRY(__kernel_clock_gettime)
 	.cfi_startproc
-	cmp	w0, #CLOCK_REALTIME
-	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
-	b.ne	2f
+	cmp 	w0, #JUMPSLOT_MAX
+	b.hi 	syscall
+	adr	vdso_data, _vdso_data
+	adr 	x_tmp, jumptable
+	add 	x_tmp, x_tmp, w0, uxtw #2
+	br 	x_tmp
+
+jumptable:
+	jump_slot jumptable, CLOCK_REALTIME, realtime
+	jump_slot jumptable, CLOCK_MONOTONIC, monotonic
+	b 	syscall
+	b 	syscall
+	b 	syscall
+	jump_slot jumptable, CLOCK_REALTIME_COARSE, realtime_coarse
+	jump_slot jumptable, CLOCK_MONOTONIC_COARSE, monotonic_coarse
+
+	.if (. - jumptable) != 4 * (JUMPSLOT_MAX + 1)
+	.error	"Wrong jumptable size"
+	.endif
+
+realtime:
+	seqcnt_acquire
+	syscall_check fail=syscall
+	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
+	ldp	w11, w12, [vdso_data, #VDSO_CS_MULT]
+	ldp	x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
+	seqcnt_check fail=realtime
 
-	mov	x2, x30
-	.cfi_register x30, x2
+	/* All computations are done with left-shifted nsecs. */
+	get_nsec_per_sec res=x9
+	lsl	x9, x9, x12
 
-	/* Get kernel timespec. */
-	adr	vdso_data, _vdso_data
-1:	seqcnt_acquire
-	cbnz	use_syscall, 7f
+	get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
+	get_ts_realtime res_sec=x10, res_nsec=x11, \
+		clock_nsec=x15, xtime_sec=x13, xtime_nsec=x14, nsec_to_sec=x9
 
-	bl	__do_get_tspec
-	seqcnt_check w9, 1b
+	b shift_store
 
-	mov	x30, x2
+monotonic:
+	seqcnt_acquire
+	syscall_check fail=syscall
+	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
+	ldp	w11, w12, [vdso_data, #VDSO_CS_MULT]
+	ldp	x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
+	ldp	x3, x4, [vdso_data, #VDSO_WTM_CLK_SEC]
+	seqcnt_check fail=monotonic
 
-	cmp	w0, #CLOCK_MONOTONIC
-	b.ne	6f
+	/* All computations are done with left-shifted nsecs. */
+	lsl	x4, x4, x12
+	get_nsec_per_sec res=x9
+	lsl	x9, x9, x12
 
-	/* Get wtm timespec. */
-	ldp	x13, x14, [vdso_data, #VDSO_WTM_CLK_SEC]
+	get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
+	get_ts_realtime res_sec=x10, res_nsec=x11, \
+		clock_nsec=x15, xtime_sec=x13, xtime_nsec=x14, nsec_to_sec=x9
 
-	/* Check the sequence counter. */
-	seqcnt_read w9
-	seqcnt_check w9, 1b
-	b	4f
-2:
-	cmp	w0, #CLOCK_REALTIME_COARSE
-	ccmp	w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne
-	b.ne	8f
+	add_ts sec=x10, nsec=x11, ts_sec=x3, ts_nsec=x4, nsec_to_sec=x9
 
-	/* xtime_coarse_nsec is already right-shifted */
-	mov	x12, #0
+	b shift_store
 
-	/* Get coarse timespec. */
-	adr	vdso_data, _vdso_data
-3:	seqcnt_acquire
+realtime_coarse:
+	seqcnt_acquire
 	ldp	x10, x11, [vdso_data, #VDSO_XTIME_CRS_SEC]
+	seqcnt_check fail=realtime_coarse
 
-	/* Get wtm timespec. */
-	ldp	x13, x14, [vdso_data, #VDSO_WTM_CLK_SEC]
+	b store
 
-	/* Check the sequence counter. */
-	seqcnt_read w9
-	seqcnt_check w9, 3b
+monotonic_coarse:
+	seqcnt_acquire
+	ldp	x10, x11, [vdso_data, #VDSO_XTIME_CRS_SEC]
+	ldp	x13, x14, [vdso_data, #VDSO_WTM_CLK_SEC]
+	seqcnt_check fail=monotonic_coarse
 
-	cmp	w0, #CLOCK_MONOTONIC_COARSE
-	b.ne	6f
-4:
-	/* Add on wtm timespec. */
-	add	x10, x10, x13
-	lsl	x14, x14, x12
-	add	x11, x11, x14
+	/* Computations are done in (non-shifted) nsecs. */
+	get_nsec_per_sec res=x9
+	add_ts sec=x10, nsec=x11, ts_sec=x13, ts_nsec=x14, nsec_to_sec=x9
 
-	/* Normalise the new timespec. */
-	mov	x15, #NSEC_PER_SEC_LO16
-	movk	x15, #NSEC_PER_SEC_HI16, lsl #16
-	lsl	x15, x15, x12
-	cmp	x11, x15
-	b.lt	5f
-	sub	x11, x11, x15
-	add	x10, x10, #1
-5:
-	cmp	x11, #0
-	b.ge	6f
-	add	x11, x11, x15
-	sub	x10, x10, #1
+	b store
 
-6:	/* Store to the user timespec. */
+shift_store:
 	lsr	x11, x11, x12
+store:
 	stp	x10, x11, [x1, #TSPEC_TV_SEC]
 	mov	x0, xzr
 	ret
-7:
-	mov	x30, x2
-8:	/* Syscall fallback. */
+
+syscall: /* Syscall fallback. */
 	mov	x8, #__NR_clock_gettime
 	svc	#0
 	ret
@@ -203,46 +288,3 @@ ENTRY(__kernel_clock_getres)
 	.quad	CLOCK_COARSE_RES
 	.cfi_endproc
 ENDPROC(__kernel_clock_getres)
-
-/*
- * Read the current time from the architected counter.
- * Expects vdso_data to be initialised.
- * Clobbers the temporary registers (x9 - x15).
- * Returns:
- *  - w9		= vDSO sequence counter
- *  - (x10, x11)	= (ts->tv_sec, shifted ts->tv_nsec)
- *  - w12		= cs_shift
- */
-ENTRY(__do_get_tspec)
-	.cfi_startproc
-
-	/* Read from the vDSO data page. */
-	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
-	ldp	x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
-	ldp	w11, w12, [vdso_data, #VDSO_CS_MULT]
-	seqcnt_read w9
-
-	/* Read the virtual counter. */
-	isb
-	mrs	x15, cntvct_el0
-
-	/* Calculate cycle delta and convert to ns. */
-	sub	x10, x15, x10
-	/* We can only guarantee 56 bits of precision. */
-	movn	x15, #0xff00, lsl #48
-	and	x10, x15, x10
-	mul	x10, x10, x11
-
-	/* Use the kernel time to calculate the new timespec. */
-	mov	x11, #NSEC_PER_SEC_LO16
-	movk	x11, #NSEC_PER_SEC_HI16, lsl #16
-	lsl	x11, x11, x12
-	add	x15, x10, x14
-	udiv	x14, x15, x11
-	add	x10, x13, x14
-	mul	x13, x14, x11
-	sub	x11, x15, x13
-
-	ret
-	.cfi_endproc
-ENDPROC(__do_get_tspec)
-- 
2.8.0



From kevin.brodsky at arm.com  Mon May  9 05:37:01 2016
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Mon,  9 May 2016 13:37:01 +0100
Subject: [PATCH 2/2] arm64: Add support for CLOCK_MONOTONIC_RAW in
 clock_gettime() vDSO
In-Reply-To: <1462797421-33103-1-git-send-email-kevin.brodsky@arm.com>
References: <1462797421-33103-1-git-send-email-kevin.brodsky@arm.com>
Message-ID: <1462797421-33103-3-git-send-email-kevin.brodsky@arm.com>

So far the arm64 clock_gettime() vDSO implementation only supported
the following clocks, falling back to the syscall for the others:
- CLOCK_REALTIME{,_COARSE}
- CLOCK_MONOTONIC{,_COARSE}

This patch adds support for the CLOCK_MONOTONIC_RAW clock, taking
advantage of the recent refactoring of the vDSO time functions. Like
the non-_COARSE clocks, this only works when the "arch_sys_counter"
clocksource is in use (allowing us to read the current time from the
virtual counter register), otherwise we also have to fall back to the
syscall.

Most of the data is shared with CLOCK_MONOTONIC, and the algorithm is
similar. The reference implementation in kernel/time/timekeeping.c
shows that:
- CLOCK_MONOTONIC = tk->wall_to_monotonic + tk->xtime_sec +
  timekeeping_get_ns(&tk->tkr_mono)
- CLOCK_MONOTONIC_RAW = tk->raw_time + timekeeping_get_ns(&tk->tkr_raw)
- tkr_mono and tkr_raw are identical (in particular, same
  clocksource), except these members:
  * mult (only mono's multiplier is NTP-adjusted)
  * xtime_nsec (always 0 for raw)

Therefore, tk->raw_time and tkr_raw->mult are now also stored in the
vDSO data page.

Cc: Will Deacon <will.deacon at arm.com>
Cc: Dave Martin <dave.martin at arm.com>
Cc: Ali Saidi <ali.saidi at arm.com>
Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---
 arch/arm64/include/asm/vdso_datapage.h |  8 +++--
 arch/arm64/kernel/asm-offsets.c        |  6 +++-
 arch/arm64/kernel/vdso.c               |  8 ++++-
 arch/arm64/kernel/vdso/gettimeofday.S  | 57 +++++++++++++++++++++++++++-------
 4 files changed, 64 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/include/asm/vdso_datapage.h b/arch/arm64/include/asm/vdso_datapage.h
index de66199673d7..2b9a63771eda 100644
--- a/arch/arm64/include/asm/vdso_datapage.h
+++ b/arch/arm64/include/asm/vdso_datapage.h
@@ -22,6 +22,8 @@
 
 struct vdso_data {
 	__u64 cs_cycle_last;	/* Timebase at clocksource init */
+	__u64 raw_time_sec;	/* Raw time */
+	__u64 raw_time_nsec;
 	__u64 xtime_clock_sec;	/* Kernel time */
 	__u64 xtime_clock_nsec;
 	__u64 xtime_coarse_sec;	/* Coarse time */
@@ -29,8 +31,10 @@ struct vdso_data {
 	__u64 wtm_clock_sec;	/* Wall to monotonic time */
 	__u64 wtm_clock_nsec;
 	__u32 tb_seq_count;	/* Timebase sequence counter */
-	__u32 cs_mult;		/* Clocksource multiplier */
-	__u32 cs_shift;		/* Clocksource shift */
+	/* cs_* members must be adjacent and in this order (ldp accesses) */
+	__u32 cs_mono_mult;	/* NTP-adjusted clocksource multiplier */
+	__u32 cs_shift;		/* Clocksource shift (mono = raw) */
+	__u32 cs_raw_mult;	/* Raw clocksource multiplier */
 	__u32 tz_minuteswest;	/* Whacky timezone stuff */
 	__u32 tz_dsttime;
 	__u32 use_syscall;
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 3ae6b310ac9b..5ff88560e5ef 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -76,6 +76,7 @@ int main(void)
   BLANK();
   DEFINE(CLOCK_REALTIME,	CLOCK_REALTIME);
   DEFINE(CLOCK_MONOTONIC,	CLOCK_MONOTONIC);
+  DEFINE(CLOCK_MONOTONIC_RAW,	CLOCK_MONOTONIC_RAW);
   DEFINE(CLOCK_REALTIME_RES,	MONOTONIC_RES_NSEC);
   DEFINE(CLOCK_REALTIME_COARSE,	CLOCK_REALTIME_COARSE);
   DEFINE(CLOCK_MONOTONIC_COARSE,CLOCK_MONOTONIC_COARSE);
@@ -83,6 +84,8 @@ int main(void)
   DEFINE(NSEC_PER_SEC,		NSEC_PER_SEC);
   BLANK();
   DEFINE(VDSO_CS_CYCLE_LAST,	offsetof(struct vdso_data, cs_cycle_last));
+  DEFINE(VDSO_RAW_TIME_SEC,	offsetof(struct vdso_data, raw_time_sec));
+  DEFINE(VDSO_RAW_TIME_NSEC,	offsetof(struct vdso_data, raw_time_nsec));
   DEFINE(VDSO_XTIME_CLK_SEC,	offsetof(struct vdso_data, xtime_clock_sec));
   DEFINE(VDSO_XTIME_CLK_NSEC,	offsetof(struct vdso_data, xtime_clock_nsec));
   DEFINE(VDSO_XTIME_CRS_SEC,	offsetof(struct vdso_data, xtime_coarse_sec));
@@ -90,7 +93,8 @@ int main(void)
   DEFINE(VDSO_WTM_CLK_SEC,	offsetof(struct vdso_data, wtm_clock_sec));
   DEFINE(VDSO_WTM_CLK_NSEC,	offsetof(struct vdso_data, wtm_clock_nsec));
   DEFINE(VDSO_TB_SEQ_COUNT,	offsetof(struct vdso_data, tb_seq_count));
-  DEFINE(VDSO_CS_MULT,		offsetof(struct vdso_data, cs_mult));
+  DEFINE(VDSO_CS_MONO_MULT,	offsetof(struct vdso_data, cs_mono_mult));
+  DEFINE(VDSO_CS_RAW_MULT,	offsetof(struct vdso_data, cs_raw_mult));
   DEFINE(VDSO_CS_SHIFT,		offsetof(struct vdso_data, cs_shift));
   DEFINE(VDSO_TZ_MINWEST,	offsetof(struct vdso_data, tz_minuteswest));
   DEFINE(VDSO_TZ_DSTTIME,	offsetof(struct vdso_data, tz_dsttime));
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 97bc68f4c689..54f7b327fd18 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -212,10 +212,16 @@ void update_vsyscall(struct timekeeper *tk)
 	vdso_data->wtm_clock_nsec		= tk->wall_to_monotonic.tv_nsec;
 
 	if (!use_syscall) {
+		/* tkr_mono.cycle_last == tkr_raw.cycle_last */
 		vdso_data->cs_cycle_last	= tk->tkr_mono.cycle_last;
+		vdso_data->raw_time_sec		= tk->raw_time.tv_sec;
+		vdso_data->raw_time_nsec	= tk->raw_time.tv_nsec;
 		vdso_data->xtime_clock_sec	= tk->xtime_sec;
 		vdso_data->xtime_clock_nsec	= tk->tkr_mono.xtime_nsec;
-		vdso_data->cs_mult		= tk->tkr_mono.mult;
+		/* tkr_raw.xtime_nsec == 0 */
+		vdso_data->cs_mono_mult		= tk->tkr_mono.mult;
+		vdso_data->cs_raw_mult		= tk->tkr_raw.mult;
+		/* tkr_mono.shift == tkr_raw.shift */
 		vdso_data->cs_shift		= tk->tkr_mono.shift;
 	}
 
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index caff9dd6ba78..f49b6755058a 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -87,6 +87,15 @@ x_tmp		.req	x8
 	msub	\res_nsec, x_tmp, \nsec_to_sec, \res_nsec
 	.endm
 
+	/*
+	 * Returns in res_{sec,nsec} the timespec based on the clock_raw delta,
+	 * used for CLOCK_MONOTONIC_RAW.
+	 */
+	.macro	get_ts_clock_raw res_sec, res_nsec, clock_nsec, nsec_to_sec
+	udiv	\res_sec, \clock_nsec, \nsec_to_sec
+	msub	\res_nsec, \res_sec, \nsec_to_sec, \clock_nsec
+	.endm
+
 	/* sec and nsec are modified in place. */
 	.macro add_ts sec, nsec, ts_sec, ts_nsec, nsec_to_sec
 	/* Add timespec. */
@@ -126,7 +135,8 @@ ENTRY(__kernel_gettimeofday)
 1:	seqcnt_acquire
 	syscall_check fail=4f
 	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
-	ldp	w11, w12, [vdso_data, #VDSO_CS_MULT]
+	/* w11 = cs_mono_mult, w12 = cs_shift */
+	ldp	w11, w12, [vdso_data, #VDSO_CS_MONO_MULT]
 	ldp	x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
 	seqcnt_check fail=1b
 
@@ -163,19 +173,19 @@ ENDPROC(__kernel_gettimeofday)
 /* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */
 ENTRY(__kernel_clock_gettime)
 	.cfi_startproc
-	cmp 	w0, #JUMPSLOT_MAX
-	b.hi 	syscall
+	cmp	w0, #JUMPSLOT_MAX
+	b.hi	syscall
 	adr	vdso_data, _vdso_data
-	adr 	x_tmp, jumptable
-	add 	x_tmp, x_tmp, w0, uxtw #2
-	br 	x_tmp
+	adr	x_tmp, jumptable
+	add	x_tmp, x_tmp, w0, uxtw #2
+	br	x_tmp
 
 jumptable:
 	jump_slot jumptable, CLOCK_REALTIME, realtime
 	jump_slot jumptable, CLOCK_MONOTONIC, monotonic
-	b 	syscall
-	b 	syscall
-	b 	syscall
+	b	syscall
+	b	syscall
+	jump_slot jumptable, CLOCK_MONOTONIC_RAW, monotonic_raw
 	jump_slot jumptable, CLOCK_REALTIME_COARSE, realtime_coarse
 	jump_slot jumptable, CLOCK_MONOTONIC_COARSE, monotonic_coarse
 
@@ -187,7 +197,8 @@ realtime:
 	seqcnt_acquire
 	syscall_check fail=syscall
 	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
-	ldp	w11, w12, [vdso_data, #VDSO_CS_MULT]
+	/* w11 = cs_mono_mult, w12 = cs_shift */
+	ldp	w11, w12, [vdso_data, #VDSO_CS_MONO_MULT]
 	ldp	x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
 	seqcnt_check fail=realtime
 
@@ -205,7 +216,8 @@ monotonic:
 	seqcnt_acquire
 	syscall_check fail=syscall
 	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
-	ldp	w11, w12, [vdso_data, #VDSO_CS_MULT]
+	/* w11 = cs_mono_mult, w12 = cs_shift */
+	ldp	w11, w12, [vdso_data, #VDSO_CS_MONO_MULT]
 	ldp	x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
 	ldp	x3, x4, [vdso_data, #VDSO_WTM_CLK_SEC]
 	seqcnt_check fail=monotonic
@@ -223,6 +235,28 @@ monotonic:
 
 	b shift_store
 
+monotonic_raw:
+	seqcnt_acquire
+	syscall_check fail=syscall
+	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
+	/* w11 = cs_raw_mult, w12 = cs_shift */
+	ldp	w12, w11, [vdso_data, #VDSO_CS_SHIFT]
+	ldp	x13, x14, [vdso_data, #VDSO_RAW_TIME_SEC]
+	seqcnt_check fail=monotonic_raw
+
+	/* All computations are done with left-shifted nsecs. */
+	lsl	x14, x14, x12
+	get_nsec_per_sec res=x9
+	lsl	x9, x9, x12
+
+	get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
+	get_ts_clock_raw res_sec=x10, res_nsec=x11, \
+		clock_nsec=x15, nsec_to_sec=x9
+
+	add_ts sec=x10, nsec=x11, ts_sec=x13, ts_nsec=x14, nsec_to_sec=x9
+
+	b shift_store
+
 realtime_coarse:
 	seqcnt_acquire
 	ldp	x10, x11, [vdso_data, #VDSO_XTIME_CRS_SEC]
@@ -261,6 +295,7 @@ ENTRY(__kernel_clock_getres)
 	.cfi_startproc
 	cmp	w0, #CLOCK_REALTIME
 	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
+	ccmp	w0, #CLOCK_MONOTONIC_RAW, #0x4, ne
 	b.ne	1f
 
 	ldr	x2, 5f
-- 
2.8.0



From javier at osg.samsung.com  Mon May  9 05:48:16 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 08:48:16 -0400
Subject: [RESEND PATCH] [media] s5p-mfc: don't close instance after free
 OUTPUT buffers
In-Reply-To: <1462584301.25248.40.camel@collabora.com>
References: <1462572682-5195-1-git-send-email-javier@osg.samsung.com>
 <1462584301.25248.40.camel@collabora.com>
Message-ID: <ef0eb150-450b-96db-5f04-45271643f5c6@osg.samsung.com>

Hello Nicolas,

Thanks for your feedback.

On 05/06/2016 09:25 PM, Nicolas Dufresne wrote:
> Thanks for re-submitting. See inline two typos to fix in teh comment.
>

You are welcome, as we talked in IRC you needed this to make video decoding
in your Exynos4412 Odroid X2 board, so it would be great if you can provide
your Reviewed or Acked by tags.
 
> cheers,
> Nicolas
> 
> Le vendredi 06 mai 2016 ? 18:11 -0400, Javier Martinez Canillas a ?crit :
>> From: ayaka <ayaka at soulik.info>
>>
>> User-space applications can use the VIDIOC_REQBUFS ioctl to determine if a
>> memory mapped, user pointer or DMABUF based I/O is supported by the driver.
>>
>> So a set of VIDIOC_REQBUFS ioctl calls will be made with count 0 and then
>> the real VIDIOC_REQBUFS call with count == n. But for count 0, the driver
>> not only frees the buffer but also closes the MFC instance and s5p_mfc_ctx
>> state is set to MFCINST_FREE.
>>
>> The VIDIOC_REQBUFS handler for the output device checks if the s5p_mfc_ctx
>> state is set to MFCINST_INIT (which happens on an VIDIOC_S_FMT) and fails
>> otherwise. So after a VIDIOC_REQBUFS(n), future VIDIOC_REQBUFS(n) calls
>> will fails unless a VIDIOC_S_FMT ioctl calls happens before the reqbufs.
>>
>> But applications may first set the format and then attempt to determine
>> the I/O methods supported by the driver (for example Gstramer does it) so
>  * GStreamer
>

Right, sorry about that. I'll wait for other people feedback and fix in v2.

>> the state won't be set to MFCINST_INIT again and VIDIOC_REQBUFS will fail.
>>
>> To avoid this issue, only free the buffers on VIDIOC_REQBUFS(0) but don't
>> close the MFC instance to allow future VIDIOC_REQBUFS(n) calls to succeed.
>>
>> Signed-off-by: ayaka <ayaka at soulik.info>
>> [javier: Rewrote changelog to explain the problem more detailed]
>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>
>> ---
>> Hello,
>>
>> This is a resend of a patch posted by Ayaka some time ago [0].
>> Without $SUBJECT, trying to decode a video using Gstramer fails
> 
> * GStreamer again 
>

Yes, this is not that important since the comments between the --- separator
and the actual diff is stripped and doesn't end in the commit message.

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From joel at jms.id.au  Mon May  9 05:32:49 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 22:02:49 +0930
Subject: [PATCH 4/4] drivers/clocksource/moxart: Add Aspeed support
In-Reply-To: <1462797169-14512-1-git-send-email-joel@jms.id.au>
References: <1462797169-14512-1-git-send-email-joel@jms.id.au>
Message-ID: <1462797169-14512-5-git-send-email-joel@jms.id.au>

The Aspeed SoC has timer IP with a very similar register layout to the
moxart timer. This patch adds support for the fourth and fifth gen
aspeed SoCs, and has been tested on the ast2400 and ast2500.

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 .../bindings/timer/moxa,moxart-timer.txt           |  4 ++-
 drivers/clocksource/moxart_timer.c                 | 32 ++++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt
index da2d510cae47..e207c11630af 100644
--- a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt
+++ b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt
@@ -2,7 +2,9 @@ MOXA ART timer
 
 Required properties:
 
-- compatible : Must be "moxa,moxart-timer"
+- compatible : Must be one of:
+ 	- "moxa,moxart-timer"
+ 	- "aspeed,ast2400-timer"
 - reg : Should contain registers location and length
 - interrupts : Should contain the timer interrupt number
 - clocks : Should contain phandle for the clock that drives the counter
diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c
index d17e3eface87..83ffa2727699 100644
--- a/drivers/clocksource/moxart_timer.c
+++ b/drivers/clocksource/moxart_timer.c
@@ -56,6 +56,23 @@
 #define MOXART_TIMER1_ENABLE	(MOXART_CR_2_ENABLE | MOXART_CR_1_ENABLE)
 #define MOXART_TIMER1_DISABLE	(MOXART_CR_2_ENABLE)
 
+/*
+ * The ASpeed variant of the IP block has a different layout
+ * for the control register
+ */
+#define ASPEED_CR_1_ENABLE	BIT(0)
+#define ASPEED_CR_1_CLOCK	BIT(1)
+#define ASPEED_CR_1_INT		BIT(2)
+#define ASPEED_CR_2_ENABLE	BIT(4)
+#define ASPEED_CR_2_CLOCK	BIT(5)
+#define ASPEED_CR_2_INT		BIT(6)
+#define ASPEED_CR_3_ENABLE	BIT(8)
+#define ASPEED_CR_3_CLOCK	BIT(9)
+#define ASPEED_CR_3_INT		BIT(10)
+
+#define ASPEED_TIMER1_ENABLE   (ASPEED_CR_2_ENABLE | ASPEED_CR_1_ENABLE)
+#define ASPEED_TIMER1_DISABLE  (ASPEED_CR_2_ENABLE)
+
 struct moxart_timer {
 	void __iomem *base;
 	unsigned int t1_disable_val;
@@ -159,6 +176,9 @@ static void __init moxart_timer_init(struct device_node *node)
 	if (of_device_is_compatible(node, "moxa,moxart-timer")) {
 		timer->t1_enable_val = MOXART_TIMER1_ENABLE;
 		timer->t1_disable_val = MOXART_TIMER1_DISABLE;
+	} else if (of_device_is_compatible(node, "aspeed,ast2400-timer")) {
+		timer->t1_enable_val = ASPEED_TIMER1_ENABLE;
+		timer->t1_disable_val = ASPEED_TIMER1_DISABLE;
 	} else
 		panic("%s: unknown platform\n", node->full_name);
 
@@ -189,6 +209,17 @@ static void __init moxart_timer_init(struct device_node *node)
 	if (ret)
 		panic("%s: setup_irq failed\n", node->full_name);
 
+	/* Clear match registers */
+	writel(0, timer->base + TIMER1_BASE + REG_MATCH1);
+	writel(0, timer->base + TIMER1_BASE + REG_MATCH2);
+	writel(0, timer->base + TIMER2_BASE + REG_MATCH1);
+	writel(0, timer->base + TIMER2_BASE + REG_MATCH2);
+
+	/*
+	 * Start timer 2 rolling as our main wall clock source, keep timer 1
+	 * disabled
+	 */
+	writel(0, timer->base + TIMER_CR);
 	writel(~0, timer->base + TIMER2_BASE + REG_LOAD);
 	writel(timer->t1_disable_val, timer->base + TIMER_CR);
 
@@ -201,3 +232,4 @@ static void __init moxart_timer_init(struct device_node *node)
 	clockevents_config_and_register(&timer->clkevt, pclk, 0x4, 0xfffffffe);
 }
 CLOCKSOURCE_OF_DECLARE(moxart, "moxa,moxart-timer", moxart_timer_init);
+CLOCKSOURCE_OF_DECLARE(aspeed, "aspeed,ast2400-timer", moxart_timer_init);
-- 
2.8.1



From baruch at tkos.co.il  Mon May  9 05:50:00 2016
From: baruch at tkos.co.il (Baruch Siach)
Date: Mon, 9 May 2016 15:50:00 +0300
Subject: [PATCH 1/2] doc/devicetree: Add Aspeed VIC bindings
In-Reply-To: <1462797239-14765-2-git-send-email-joel@jms.id.au>
References: <1462797239-14765-1-git-send-email-joel@jms.id.au>
 <1462797239-14765-2-git-send-email-joel@jms.id.au>
Message-ID: <20160509124959.GM4414@sapphire.tkos.co.il>

Hi Joel,

On Mon, May 09, 2016 at 10:03:58PM +0930, Joel Stanley wrote:
> +Aspeed Vectored Interrupt Controller
> +
> +These bindings are for the Aspeed AST2400 interrupt controller register layout.
> +The SoC has an legacy register layout, but this driver does not support that
> +mode of operation.
> +
> +Required properties:
> +
> +- compatible : should be "aspeed,ast2400-vic".
> +
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source. The value shall be 1.
> +- valid-sources : bitmask of valid irq sources
> +
> +Example:
> +
> + vic: interrupt-controller {
> +      compatible = "aspeed,ast2400-new-vic";

That doesn't match the compatible string documented above.

> +      interrupt-controller;
> +      #interrupt-cells = <1>;
> +      valid-sources = < 0xffffffff 0x0007ffff>;
> +      reg = <0x1e6c0080 0x80>;
> + };

baruch

-- 
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -


From nicolas at ndufresne.ca  Mon May  9 05:54:08 2016
From: nicolas at ndufresne.ca (Nicolas Dufresne)
Date: Mon, 09 May 2016 08:54:08 -0400
Subject: [RESEND PATCH] [media] s5p-mfc: don't close instance after free
 OUTPUT buffers
In-Reply-To: <1462572682-5195-1-git-send-email-javier@osg.samsung.com>
References: <1462572682-5195-1-git-send-email-javier@osg.samsung.com>
Message-ID: <1462798448.9635.2.camel@ndufresne.ca>

Le vendredi 06 mai 2016 ? 18:11 -0400, Javier Martinez Canillas a
?crit?:
> From: ayaka <ayaka at soulik.info>
> 
> User-space applications can use the VIDIOC_REQBUFS ioctl to determine
> if a
> memory mapped, user pointer or DMABUF based I/O is supported by the
> driver.
> 
> So a set of VIDIOC_REQBUFS ioctl calls will be made with count 0 and
> then
> the real VIDIOC_REQBUFS call with count == n. But for count 0, the
> driver
> not only frees the buffer but also closes the MFC instance and
> s5p_mfc_ctx
> state is set to MFCINST_FREE.
> 
> The VIDIOC_REQBUFS handler for the output device checks if the
> s5p_mfc_ctx
> state is set to MFCINST_INIT (which happens on an VIDIOC_S_FMT) and
> fails
> otherwise. So after a VIDIOC_REQBUFS(n), future VIDIOC_REQBUFS(n)
> calls
> will fails unless a VIDIOC_S_FMT ioctl calls happens before the
> reqbufs.
> 
> But applications may first set the format and then attempt to
> determine
> the I/O methods supported by the driver (for example Gstramer does
> it) so
> the state won't be set to MFCINST_INIT again and VIDIOC_REQBUFS will
> fail.
> 
> To avoid this issue, only free the buffers on VIDIOC_REQBUFS(0) but
> don't
> close the MFC instance to allow future VIDIOC_REQBUFS(n) calls to
> succeed.
> 
> Signed-off-by: ayaka <ayaka at soulik.info>
> [javier: Rewrote changelog to explain the problem more detailed]
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

I just tested this change, it also seems correct.

Acked-by: Nicolas Dufresne <nicolas at collabora.com>

> 
> ---
> Hello,
> 
> This is a resend of a patch posted by Ayaka some time ago [0].
> Without $SUBJECT, trying to decode a video using Gstramer fails
> on an Exynos5422 Odroid XU4 board with following error message:
> 
> $ gst-launch-1.0 filesrc location=test.mov ! qtdemux ! h264parse !
> v4l2video0dec ! videoconvert ! autovideosink
> 
> Setting pipeline to PAUSED ...
> Pipeline is PREROLLING ...
> [ 3947.114756] vidioc_reqbufs:576: Only V4L2_MEMORY_MAP is supported
> [ 3947.114771] vidioc_reqbufs:576: Only V4L2_MEMORY_MAP is supported
> [ 3947.114903] reqbufs_output:484: Reqbufs called in an invalid state
> [ 3947.114913] reqbufs_output:510: Failed allocating buffers for
> OUTPUT queue
> ERROR: from element
> /GstPipeline:pipeline0/v4l2video0dec:v4l2video0dec0: Failed to
> allocate required memory.
> Additional debug info:
> gstv4l2videodec.c(575): gst_v4l2_video_dec_handle_frame ():
> /GstPipeline:pipeline0/v4l2video0dec:v4l2video0dec0:
> Buffer pool activation failed
> ERROR: pipeline doesn't want to preroll.
> Setting pipeline to NULL ...
> Freeing pipeline ...
> 
> [0]: https://patchwork.linuxtv.org/patch/32794/
> 
> Best regards,
> Javier
> 
> ?drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 1 -
> ?1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> index f2d6376ce618..8b9467de2d6a 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> @@ -474,7 +474,6 @@ static int reqbufs_output(struct s5p_mfc_dev
> *dev, struct s5p_mfc_ctx *ctx,
> ?		ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
> ?		if (ret)
> ?			goto out;
> -		s5p_mfc_close_mfc_inst(dev, ctx);
> ?		ctx->src_bufs_cnt = 0;
> ?		ctx->output_state = QUEUE_FREE;
> ?	} else if (ctx->output_state == QUEUE_FREE) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160509/0b3db5d0/attachment-0001.sig>

From arnd at arndb.de  Mon May  9 05:55:59 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 14:55:59 +0200
Subject: [PATCH 1/2] doc/devicetree: Add Aspeed VIC bindings
In-Reply-To: <1462797239-14765-2-git-send-email-joel@jms.id.au>
References: <1462797239-14765-1-git-send-email-joel@jms.id.au>
 <1462797239-14765-2-git-send-email-joel@jms.id.au>
Message-ID: <4320787.nfPydvIlpT@wuerfel>

On Monday 09 May 2016 22:03:58 Joel Stanley wrote:
> +
> +- compatible : should be "aspeed,ast2400-vic".
> +
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source. The value shall be 1.
> +- valid-sources : bitmask of valid irq sources
> +
> +Example:
> +
> + vic: interrupt-controller {
> +      compatible = "aspeed,ast2400-new-vic";
> 

The example doesn't match the binding regarding the compatible string,
otherwise looks ok to me.

	Arnd


From arnd at arndb.de  Mon May  9 05:58:59 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 14:58:59 +0200
Subject: [PULL REQUEST] aspeed arch changes for 4.7
In-Reply-To: <CACPK8Xd6i0Fh79YBmF3FO--vfO+hEUxfTsTDyDxqUushhScRwg@mail.gmail.com>
References: <1462796946-13579-1-git-send-email-joel@jms.id.au>
 <CACPK8Xd6i0Fh79YBmF3FO--vfO+hEUxfTsTDyDxqUushhScRwg@mail.gmail.com>
Message-ID: <4204804.jrcJPq4h9P@wuerfel>

On Monday 09 May 2016 22:11:43 Joel Stanley wrote:
> On Mon, May 9, 2016 at 9:59 PM, Joel Stanley <joel at jms.id.au> wrote:
> > Hello,
> >
> > This is the initial pull request for the Aspeed BMC SoCs.
> 
> As you can see, this being my first time and all, I chose to use the
> "PULL REQUEST" tag instead of the more traditional "GIT PULL".
> 
> I'll be sure to get it correct next time.

No worries, this sticks out enough in my inbox so I don't miss it.

I'm planning to merge the arch/arm/ bits today or tomorrow, hopefully
all the drivers can also make it in time for the merge window.

	Arnd


From marc.zyngier at arm.com  Mon May  9 06:06:37 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon,  9 May 2016 14:06:37 +0100
Subject: [PATCH] clocksource/arm_arch_timer: Force per-CPU interrupt to
 trigger on level-high
Message-ID: <1462799197-31286-1-git-send-email-marc.zyngier@arm.com>

The ARM architected timer produces level-triggered interrupts (this
is mandated by the architecture). Unfortunately, most device-trees
get this wrong, and expose an edge-triggered interrupt.

Until now, this wasn't too much an issue, as the programming of the
trigger would fail (the corresponding PPI cannot be reconfigured),
and the kernel would be happy with this. But we're about to change
this, and trust DT a lot if the driver doesn't provide its own
trigger information. In that context, the timer breaks badly.

While we do need to fix the DTs, there is also some userspace out
there (kvmtool) that generates the same kind of broken DT on the
fly, and that will completely break with newer kernels.

As a safety measure, and to keep buggy software alive as well as
buying us some time to fix DTs all over the place, let's enforce
the interrupt trigger in the timer driver. This doesn't cost
us anything, and ensures that this will work in all situations,
broken DT or not.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 drivers/clocksource/arm_arch_timer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 5152b38..fdf367ae 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -366,7 +366,7 @@ static int arch_timer_setup(struct clock_event_device *clk)
 {
 	__arch_timer_setup(ARCH_CP15_TIMER, clk);
 
-	enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0);
+	enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], IRQF_TRIGGER_HIGH);
 
 	if (arch_timer_has_nonsecure_ppi())
 		enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0);
-- 
2.1.4



From arnd at arndb.de  Mon May  9 06:10:40 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 15:10:40 +0200
Subject: [GIT PULL] Renesas ARM64 Based SoC DT PM Domain Updates for v4.7
In-Reply-To: <20160506002125.GE24999@verge.net.au>
References: <cover.1461730364.git.horms+renesas@verge.net.au>
 <20160506002125.GE24999@verge.net.au>
Message-ID: <41128314.QPDQXbTtHX@wuerfel>

On Friday 06 May 2016 09:21:25 Simon Horman wrote:
> Hi,
> 
> On Wed, Apr 27, 2016 at 02:20:10PM +1000, Simon Horman wrote:
> > Hi Olof, Hi Kevin, Hi Arnd,
> > 
> > Please consider these Renesas ARM64 based SoC DT PM Domain updates for v4.7.
> > 
> > This pull requests is based on a merge of:
> > 
> > * "[GIT PULL] Second Round of Renesas ARM Based SoC R-Car SYSC Updates for
> >   v4.7", tagged as renesas-rcar-sysc2-for-v4.7, which you have already
> >   pulled
> > * "[GIT PULL] Second Round of Renesas ARM64 Based SoC DT Updates for v4.7",
> >   tagged as renesas-arm64-dt2-for-v4.7, which I have sent a pull request
> >   for.
> > 
> > The reason for the somewhat tedious base on
> > renesas-rcar-sysc2-for-v4.7, which provides driver changes,
> > is a hard run-time dependency.
> > 
> > I also have a similar set of changes for ARM (32-bit) which I will send
> > separately.
> 
> I am wondering if this pull-request might have slipped through the cracks.
> 
> FWIW, all other pull requests I have submitted for v4.7 have been pulled
> (thanks!) including a similar pull-request for ARM (32-bit) which is
> present in the next/late branch of the arm-soc tree.
> 
> I do not plan to send any more non-fix pull requests for v4.7.
> And at this stage I am not aware of any fixes for v4.7.
> 

Indeed it did, thanks for the reminder! I've put it on my stack now
and should start doing merges later today when I'm through my mail.

	Arnd


From arnd at arndb.de  Mon May  9 06:12:12 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 15:12:12 +0200
Subject: [PATCH v2 1/2] Documentation: DT: bindings: Add Broadcom STB PCIe
 bindings
In-Reply-To: <572BBF2E.5010606@broadcom.com>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
 <4513390.VWu0VVAxOl@wuerfel> <572BBF2E.5010606@broadcom.com>
Message-ID: <20692845.Ts1cTL7t9V@wuerfel>

On Thursday 05 May 2016 14:46:22 Florian Fainelli wrote:
> 
> > 
> >> +- brcm,gen: integer that indicates desired forced generation of link: 1 => 2.5
> >> +  Gbps, 2 => 5.0 Gbps, 3 => 8.0 Gbps. Will override the auto-negotation if
> >> +  specified.
> > 
> > to repeat my earlier comment from v1:
> > 
> > Shouldn't the link generation be probed automatically?
> 
> It is, but if the property is present, we can foce the link negotiation,
> We have had cases where this was desired and helpful.
> 

Right, I missed that this is listed as 'optional', so that seems
perfectly fine.

Thanks,

	Arnd


From linus.walleij at linaro.org  Mon May  9 06:12:51 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 9 May 2016 15:12:51 +0200
Subject: next-20160503 build: 1 failures 12 warnings (next-20160503)
In-Reply-To: <20160509205315.631e0c68@canb.auug.org.au>
References: <E1axZpG-000664-AK@optimist> <20160503141723.GR6292@sirena.org.uk>
 <2280495.M9rYajvqUJ@wuerfel>
 <20160509205315.631e0c68@canb.auug.org.au>
Message-ID: <CACRpkdbuJym-7tSMo1gXyWvGCRvvuor8EeCK2bm6=Kb20vTxNA@mail.gmail.com>

On Mon, May 9, 2016 at 12:53 PM, Stephen Rothwell <sfr at canb.auug.org.au> wrote:

> Can we, please, get this fixed ... less than a week to the merge window
> opening ...

Mark poked me with a sharp stick, the patch is applied!
Sorry for missing this.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Mon May  9 06:19:26 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 9 May 2016 15:19:26 +0200
Subject: [GIT PULL] move ARM LCD display driver to auxdisplay
In-Reply-To: <20160509090615.6272f8ca@erd979>
References: <CACRpkdbyO0axd5ergYZcXO302f2fFAPKrSNevkvreP1kRjm-vw@mail.gmail.com>
 <20160425115758.GA4874@lukather>
 <CACRpkdb=s5onVa7qND9nFUtYPw5H-Hdr7Ja5o3=-9+wxghHekQ@mail.gmail.com>
 <20160428092608.GE17159@lukather> <5723755D.9060108@ti.com>
 <20160509090615.6272f8ca@erd979>
Message-ID: <CACRpkdbZmL9Cqp-ubzyxd7fWUFOVsS1DCxsfG02kSpbWu_rbZQ@mail.gmail.com>

On Mon, May 9, 2016 at 9:06 AM, Robin van der Gracht <robin at protonic.nl> wrote:

> If you guys feel like auxdisplay is not the right subsystem for the
> driver, and would like me to move it, please share.

The best would be if you volunteer to maintain it and bring
it forward.

Yours,
Linus Walleij


From marc.zyngier at arm.com  Mon May  9 06:27:12 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 9 May 2016 14:27:12 +0100
Subject: [PATCH] clocksource/arm_arch_timer: Force per-CPU interrupt to
 trigger on level-high
In-Reply-To: <1462799197-31286-1-git-send-email-marc.zyngier@arm.com>
References: <1462799197-31286-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <57309030.8040907@arm.com>

On 09/05/16 14:06, Marc Zyngier wrote:
> The ARM architected timer produces level-triggered interrupts (this
> is mandated by the architecture). Unfortunately, most device-trees
> get this wrong, and expose an edge-triggered interrupt.
> 
> Until now, this wasn't too much an issue, as the programming of the
> trigger would fail (the corresponding PPI cannot be reconfigured),
> and the kernel would be happy with this. But we're about to change
> this, and trust DT a lot if the driver doesn't provide its own
> trigger information. In that context, the timer breaks badly.
> 
> While we do need to fix the DTs, there is also some userspace out
> there (kvmtool) that generates the same kind of broken DT on the
> fly, and that will completely break with newer kernels.
> 
> As a safety measure, and to keep buggy software alive as well as
> buying us some time to fix DTs all over the place, let's enforce
> the interrupt trigger in the timer driver. This doesn't cost
> us anything, and ensures that this will work in all situations,
> broken DT or not.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
>  drivers/clocksource/arm_arch_timer.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> index 5152b38..fdf367ae 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -366,7 +366,7 @@ static int arch_timer_setup(struct clock_event_device *clk)
>  {
>  	__arch_timer_setup(ARCH_CP15_TIMER, clk);
>  
> -	enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0);
> +	enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], IRQF_TRIGGER_HIGH);

Looking at it a bit more, it looks like it is should be a TRIGGER_LOW
(the ARM GIC doesn't distinguish between levels, but other
implementations might be able to). Oh well.

I'll respin this shortly.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From javier at osg.samsung.com  Mon May  9 06:32:47 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 09:32:47 -0400
Subject: [PATCH] clk: samsung: exynos5420: Remove useless check for return
 value of samsung_clk_init
In-Reply-To: <1462699496-16646-1-git-send-email-krzk@kernel.org>
References: <1462699496-16646-1-git-send-email-krzk@kernel.org>
Message-ID: <4033d4d5-558d-898f-cdc9-07a19654ade6@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 05:24 AM, Krzysztof Kozlowski wrote:
> The samsung_clk_init() cannot return NULL. Either it returns allocated
> memory or it panics.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---
>  drivers/clk/samsung/clk-exynos5420.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
> index 92382cef9f90..770c0f007c6b 100644
> --- a/drivers/clk/samsung/clk-exynos5420.c
> +++ b/drivers/clk/samsung/clk-exynos5420.c
> @@ -1356,8 +1356,6 @@ static void __init exynos5x_clk_init(struct device_node *np,
>  	exynos5x_soc = soc;
>  
>  	ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
> -	if (!ctx)
> -		panic("%s: unable to allocate context.\n", __func__);
>

Indeed, the check is superfluous. I see that most callers [0] currently
do the same, so probably makes sense to remove those too in this patch.

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

[0]:
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-exynos5440.c
drivers/clk/samsung/clk-s3c2410.c
drivers/clk/samsung/clk-s3c2412.c
drivers/clk/samsung/clk-s3c2443.c
drivers/clk/samsung/clk-s3c64xx.c
drivers/clk/samsung/clk-s5pv210.c

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From arnd at arndb.de  Mon May  9 06:37:24 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 15:37:24 +0200
Subject: [PATCH 0/3] MAINTAINERS: add new maintainers of NXP LPC32xx SoC
In-Reply-To: <1461714919-25577-1-git-send-email-vz@mleia.com>
References: <1461714919-25577-1-git-send-email-vz@mleia.com>
Message-ID: <5625005.PZHTmOJHmX@wuerfel>

On Wednesday 27 April 2016 02:55:16 Vladimir Zapolskiy wrote:
> Roland Stigge added initial support of NXP LPC32xx SoC series and
> first boards powered by it, but for a while since v3.18-rc1 the
> SoC support is unmaintained and became stale.
> 
> Vladimir Zapolskiy and Sylvain Lemieux expressed interest in
> continuation of NXP LPC32xx maintenance, reflect this in MAINTAINERS
> record file for better communication with Linux kernel community.
> 
> The maintenance change is in agreement with Arnd Bergmann:
> 
>   http://www.spinics.net/lists/arm-kernel/msg498129.html
> 

Applied all three to next/soc, thanks!

	Arnd


From arnd at arndb.de  Mon May  9 06:40:07 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 15:40:07 +0200
Subject: [GIT PULL] Renesas ARM64 Based SoC DT PM Domain Updates for v4.7
In-Reply-To: <cover.1461730364.git.horms+renesas@verge.net.au>
References: <cover.1461730364.git.horms+renesas@verge.net.au>
Message-ID: <13082172.iWN9bWJntt@wuerfel>

On Wednesday 27 April 2016 14:20:10 Simon Horman wrote:
> Hi Olof, Hi Kevin, Hi Arnd,
> 
> Please consider these Renesas ARM64 based SoC DT PM Domain updates for v4.7.
> 
> This pull requests is based on a merge of:
> 
> * "[GIT PULL] Second Round of Renesas ARM Based SoC R-Car SYSC Updates for
>   v4.7", tagged as renesas-rcar-sysc2-for-v4.7, which you have already
>   pulled
> * "[GIT PULL] Second Round of Renesas ARM64 Based SoC DT Updates for v4.7",
>   tagged as renesas-arm64-dt2-for-v4.7, which I have sent a pull request
>   for.
> 
> The reason for the somewhat tedious base on
> renesas-rcar-sysc2-for-v4.7, which provides driver changes,
> is a hard run-time dependency.
> 
> I also have a similar set of changes for ARM (32-bit) which I will send
> separately.
> 

Pulled into next/late now along with the 32-bit branch. Thanks,

	Arnd


From arnd at arndb.de  Mon May  9 06:56:34 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 15:56:34 +0200
Subject: NXP LPC32xx Mach Updates for v4.7
In-Reply-To: <572292E4.9010209@mleia.com>
References: <572292E4.9010209@mleia.com>
Message-ID: <4494663.PrONKa9Wrp@wuerfel>

On Friday 29 April 2016 01:47:00 Vladimir Zapolskiy wrote:
> NXP LPC32xx mach updates for v4.7
> 
> This includes a few nonfunctional clean-ups for NXP LPC32xx:
> * removed leftover from restart code migration to a watchdog driver
> * removed dead code leftovers from migration to CCF driver
> * fix double const qualifier
> 

Merged into next/soc, thanks!

	Arnd


From joel at jms.id.au  Mon May  9 06:58:35 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 23:28:35 +0930
Subject: [PATCH v2 0/2] irqchip: Support Aspeed IRQ controller
In-Reply-To: <462797239-14765-1-git-send-email-joel@jms.id.au>
References: <462797239-14765-1-git-send-email-joel@jms.id.au>
Message-ID: <1462802317-27086-1-git-send-email-joel@jms.id.au>

Hello All,

This adds support for the IRQ controller found in the Aspeed ast2400 and
ast2500 BMC SoCs.

It's been tested on the ast2400 in an OpenPower Palmetto system, and on the
ast2500-edk developer kit.

V2 has a fix for the compatible string in the device tree bindings.

Cheers,

Joel

Benjamin Herrenschmidt (1):
  irqchip: Add irq controller for Aspeed

Joel Stanley (1):
  doc/devicetree: Add Aspeed VIC bindings

 .../interrupt-controller/aspeed,ast2400-vic.txt    |  24 +++
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-aspeed-vic.c                   | 238 +++++++++++++++++++++
 3 files changed, 263 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
 create mode 100644 drivers/irqchip/irq-aspeed-vic.c

-- 
2.8.1



From joel at jms.id.au  Mon May  9 06:58:36 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 23:28:36 +0930
Subject: [PATCH v2 1/2] doc/devicetree: Add Aspeed VIC bindings
In-Reply-To: <1462802317-27086-1-git-send-email-joel@jms.id.au>
References: <462797239-14765-1-git-send-email-joel@jms.id.au>
 <1462802317-27086-1-git-send-email-joel@jms.id.au>
Message-ID: <1462802317-27086-2-git-send-email-joel@jms.id.au>

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
v2:
  Fix device tree binding example, thanks Baruch and Arnd for pointing this out

 .../interrupt-controller/aspeed,ast2400-vic.txt    | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
new file mode 100644
index 000000000000..86dede1755a2
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
@@ -0,0 +1,24 @@
+Aspeed Vectored Interrupt Controller
+
+These bindings are for the Aspeed AST2400 interrupt controller register layout.
+The SoC has an legacy register layout, but this driver does not support that
+mode of operation.
+
+Required properties:
+
+- compatible : should be "aspeed,ast2400-vic".
+
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+- valid-sources : bitmask of valid irq sources
+
+Example:
+
+ vic: interrupt-controller {
+      compatible = "aspeed,ast2400-vic";
+      interrupt-controller;
+      #interrupt-cells = <1>;
+      valid-sources = < 0xffffffff 0x0007ffff>;
+      reg = <0x1e6c0080 0x80>;
+ };
-- 
2.8.1



From joel at jms.id.au  Mon May  9 06:58:37 2016
From: joel at jms.id.au (Joel Stanley)
Date: Mon,  9 May 2016 23:28:37 +0930
Subject: [PATCH v2 2/2] irqchip: Add irq controller for Aspeed
In-Reply-To: <1462802317-27086-1-git-send-email-joel@jms.id.au>
References: <462797239-14765-1-git-send-email-joel@jms.id.au>
 <1462802317-27086-1-git-send-email-joel@jms.id.au>
Message-ID: <1462802317-27086-3-git-send-email-joel@jms.id.au>

From: Benjamin Herrenschmidt <benh at kernel.crashing.org>

Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/irqchip/Makefile         |   1 +
 drivers/irqchip/irq-aspeed-vic.c | 238 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 239 insertions(+)
 create mode 100644 drivers/irqchip/irq-aspeed-vic.c

diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index b03cfcbbac6b..ec82e6e15a38 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -65,3 +65,4 @@ obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
 obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
 obj-$(CONFIG_PIC32_EVIC)		+= irq-pic32-evic.o
 obj-$(CONFIG_MVEBU_ODMI)		+= irq-mvebu-odmi.o
+obj-$(CONFIG_ARCH_ASPEED)		+= irq-aspeed-vic.o
diff --git a/drivers/irqchip/irq-aspeed-vic.c b/drivers/irqchip/irq-aspeed-vic.c
new file mode 100644
index 000000000000..db15fc3e831a
--- /dev/null
+++ b/drivers/irqchip/irq-aspeed-vic.c
@@ -0,0 +1,238 @@
+/*
+ *  Copyright (C) 2015 - Ben Herrenschmidt, IBM Corp.
+ *
+ *  Driver for Aspeed "new" VIC as found in SoC generation 3 and later
+ *
+ *  Based on irq-vic.c:
+ *
+ *  Copyright (C) 1999 - 2003 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * 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/export.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/syscore_ops.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+
+#include <asm/exception.h>
+#include <asm/irq.h>
+
+/* These definitions correspond to the "new mapping" of the
+ * register set that interleaves "high" and "low". The offsets
+ * below are for the "low" register, add 4 to get to the high one
+ */
+#define AVIC_IRQ_STATUS		0x00
+#define AVIC_FIQ_STATUS		0x08
+#define AVIC_RAW_STATUS		0x10
+#define AVIC_INT_SELECT		0x18
+#define AVIC_INT_ENABLE		0x20
+#define AVIC_INT_ENABLE_CLR	0x28
+#define AVIC_INT_TRIGGER	0x30
+#define AVIC_INT_TRIGGER_CLR	0x38
+#define AVIC_INT_SENSE		0x40
+#define AVIC_INT_DUAL_EDGE	0x48
+#define AVIC_INT_EVENT		0x50
+#define AVIC_EDGE_CLR		0x58
+#define AVIC_EDGE_STATUS	0x60
+
+struct aspeed_vic {
+	void __iomem		*base;
+	u32			valid_sources[2];
+	u32			edge_sources[2];
+	struct irq_domain	*dom;
+};
+static struct aspeed_vic *system_avic;
+
+static void vic_init_hw(struct aspeed_vic *vic)
+{
+	u32 sense;
+
+	/* Disable all interrupts */
+	writel(0xffffffff, vic->base + AVIC_INT_ENABLE_CLR);
+	writel(0xffffffff, vic->base + AVIC_INT_ENABLE_CLR + 4);
+
+	/* Make sure no soft trigger is on */
+	writel(0xffffffff, vic->base + AVIC_INT_TRIGGER_CLR);
+	writel(0xffffffff, vic->base + AVIC_INT_TRIGGER_CLR + 4);
+
+	/* Set everything to be IRQ */
+	writel(0, vic->base + AVIC_INT_SELECT);
+	writel(0, vic->base + AVIC_INT_SELECT + 4);
+
+	/* Some interrupts have a programable high/low level trigger
+	 * (4 GPIO direct inputs), for now we assume this was configured
+	 * by firmware. We read which ones are edge now.
+	 */
+	sense = readl(vic->base + AVIC_INT_SENSE);
+	vic->edge_sources[0] = ~sense;
+	sense = readl(vic->base + AVIC_INT_SENSE + 4);
+	vic->edge_sources[1] = ~sense;
+
+	/* Clear edge detection latches */
+	writel(0xffffffff, vic->base + AVIC_EDGE_CLR);
+	writel(0xffffffff, vic->base + AVIC_EDGE_CLR + 4);
+}
+
+static void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
+{
+	struct aspeed_vic *vic = system_avic;
+	u32 stat, irq;
+
+	for (;;) {
+		irq = 0;
+		stat = readl_relaxed(vic->base + AVIC_IRQ_STATUS);
+		if (!stat) {
+			stat = readl_relaxed(vic->base + AVIC_IRQ_STATUS + 4);
+			irq = 32;
+		}
+		if (stat == 0)
+			break;
+		irq += ffs(stat) - 1;
+		handle_domain_irq(vic->dom, irq, regs);
+	}
+}
+
+static void avic_ack_irq(struct irq_data *d)
+{
+	struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+	unsigned int sidx = d->hwirq >> 5;
+	unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+	/* Clear edge latch for edge interrupts, nop for level */
+	if (vic->edge_sources[sidx] & sbit)
+		writel(sbit, vic->base + AVIC_EDGE_CLR + sidx * 4);
+}
+
+static void avic_mask_irq(struct irq_data *d)
+{
+	struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+	unsigned int sidx = d->hwirq >> 5;
+	unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+	writel(sbit, vic->base + AVIC_INT_ENABLE_CLR + sidx * 4);
+}
+
+static void avic_unmask_irq(struct irq_data *d)
+{
+	struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+	unsigned int sidx = d->hwirq >> 5;
+	unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+	writel(sbit, vic->base + AVIC_INT_ENABLE + sidx * 4);
+}
+
+/* For level irq, faster than going through a nop "ack" and mask */
+static void avic_mask_ack_irq(struct irq_data *d)
+{
+	struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+	unsigned int sidx = d->hwirq >> 5;
+	unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+	/* First mask */
+	writel(sbit, vic->base + AVIC_INT_ENABLE_CLR + sidx * 4);
+
+	/* Then clear edge latch for edge interrupts */
+	if (vic->edge_sources[sidx] & sbit)
+		writel(sbit, vic->base + AVIC_EDGE_CLR + sidx * 4);
+}
+
+static struct irq_chip avic_chip = {
+	.name		= "AVIC",
+	.irq_ack	= avic_ack_irq,
+	.irq_mask	= avic_mask_irq,
+	.irq_unmask	= avic_unmask_irq,
+	.irq_mask_ack	= avic_mask_ack_irq,
+};
+
+static int avic_map(struct irq_domain *d, unsigned int irq,
+		    irq_hw_number_t hwirq)
+{
+	struct aspeed_vic *vic = d->host_data;
+	unsigned int sidx = hwirq >> 5;
+	unsigned int sbit = 1u << (hwirq & 0x1f);
+
+	/* Check if interrupt exists */
+	if (sidx > 1 || !(vic->valid_sources[sidx] & sbit))
+		return -EPERM;
+
+	if (vic->edge_sources[sidx] & sbit)
+		irq_set_chip_and_handler(irq, &avic_chip, handle_edge_irq);
+	else
+		irq_set_chip_and_handler(irq, &avic_chip, handle_level_irq);
+	irq_set_chip_data(irq, vic);
+	irq_set_probe(irq);
+	return 0;
+}
+
+static struct irq_domain_ops avic_dom_ops = {
+	.map = avic_map,
+	.xlate = irq_domain_xlate_onetwocell,
+};
+
+static int __init avic_of_init(struct device_node *node,
+			       struct device_node *parent)
+{
+	void __iomem *regs;
+	struct aspeed_vic *vic;
+	int nirqs;
+
+	if (WARN(parent, "non-root Aspeed VIC not supported"))
+		return -EINVAL;
+	if (WARN(system_avic, "duplicate Aspeed VIC not supported"))
+		return -EINVAL;
+
+	regs = of_iomap(node, 0);
+	if (WARN_ON(!regs))
+		return -EIO;
+
+	vic = kzalloc(sizeof(struct aspeed_vic), GFP_KERNEL);
+	if (WARN_ON(!vic)) {
+		iounmap(regs);
+		return -ENOMEM;
+	}
+	vic->base = regs;
+
+	of_property_read_u32_index(node, "valid-sources", 0,
+				   &vic->valid_sources[0]);
+	of_property_read_u32_index(node, "valid-sources", 1,
+				   &vic->valid_sources[1]);
+
+	nirqs = hweight32(vic->valid_sources[0]) +
+		hweight32(vic->valid_sources[1]);
+
+	/* Initialize soures, all masked */
+	vic_init_hw(vic);
+
+	/* Ready to receive interrupts */
+	system_avic = vic;
+	set_handle_irq(avic_handle_irq);
+
+	/* Register our domain */
+	vic->dom = irq_domain_add_simple(node, nirqs, 0,
+					 &avic_dom_ops, vic);
+
+	return 0;
+}
+
+IRQCHIP_DECLARE(aspeed_new_vic, "aspeed,ast2400-vic", avic_of_init);
-- 
2.8.1



From arnd at arndb.de  Mon May  9 06:59:05 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 15:59:05 +0200
Subject: [GIT PULL 1/4] DaVinci SoC updates for v4.7 (part 2)
In-Reply-To: <1461931627-27761-1-git-send-email-nsekhar@ti.com>
References: <1461931627-27761-1-git-send-email-nsekhar@ti.com>
Message-ID: <4114161.5BPvPJIkSi@wuerfel>

On Friday 29 April 2016 17:37:04 Sekhar Nori wrote:
> These patches provide ability to add non-PSC
> clocks to DaVinci clock framwork and are
> required to support USB PHY clock setting from
> USB PHY driver.
> 

Merged into next/soc, thanks!

	Arnd


From petr at barix.com  Mon May  9 06:59:48 2016
From: petr at barix.com (Petr Kulhavy)
Date: Mon,  9 May 2016 15:59:48 +0200
Subject: [PATCH] ARM: davinci: remove unused davinci-i2s pdata
Message-ID: <1462802388-25088-1-git-send-email-petr@barix.com>

The davinci-i2s driver ("davinci-mcbsp") does not use platform
data any longer. Remove the dummy pdata provided by the board
drivers dm355, dm365, dm644x and neuros-osd2.

Signed-off-by: Petr Kulhavy <petr at barix.com>
Reviewed-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/mach-davinci/board-dm355-evm.c   | 4 +---
 arch/arm/mach-davinci/board-dm365-evm.c   | 6 +-----
 arch/arm/mach-davinci/board-dm644x-evm.c  | 4 +---
 arch/arm/mach-davinci/board-neuros-osd2.c | 4 +---
 arch/arm/mach-davinci/davinci.h           | 6 +++---
 arch/arm/mach-davinci/dm355.c             | 3 +--
 arch/arm/mach-davinci/dm365.c             | 3 +--
 arch/arm/mach-davinci/dm644x.c            | 3 +--
 8 files changed, 10 insertions(+), 23 deletions(-)

diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index 1844076f6403..18296a99c4d2 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -115,8 +115,6 @@ static struct davinci_i2c_platform_data i2c_pdata = {
 	.scl_pin        = 14,
 };
 
-static struct snd_platform_data dm355_evm_snd_data;
-
 static int dm355evm_mmc_gpios = -EINVAL;
 
 static void dm355evm_mmcsd_gpios(unsigned gpio)
@@ -411,7 +409,7 @@ static __init void dm355_evm_init(void)
 			ARRAY_SIZE(dm355_evm_spi_info));
 
 	/* DM335 EVM uses ASP1; line-out is a stereo mini-jack */
-	dm355_init_asp1(ASP1_TX_EVT_EN | ASP1_RX_EVT_EN, &dm355_evm_snd_data);
+	dm355_init_asp1(ASP1_TX_EVT_EN | ASP1_RX_EVT_EN);
 }
 
 MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM")
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index f073518f621a..e832949bc767 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -176,10 +176,6 @@ static struct at24_platform_data eeprom_info = {
 	.context	= (void *)0x7f00,
 };
 
-static struct snd_platform_data dm365_evm_snd_data __maybe_unused = {
-	.asp_chan_q = EVENTQ_3,
-};
-
 static struct i2c_board_info i2c_info[] = {
 	{
 		I2C_BOARD_INFO("24c256", 0x50),
@@ -763,7 +759,7 @@ static __init void dm365_evm_init(void)
 	evm_init_cpld();
 
 #ifdef CONFIG_SND_DM365_AIC3X_CODEC
-	dm365_init_asp(&dm365_evm_snd_data);
+	dm365_init_asp();
 #elif defined(CONFIG_SND_DM365_VOICE_CODEC)
 	dm365_init_vc(&dm365_evm_snd_data);
 #endif
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 68cc09907828..96a9528e373e 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -264,8 +264,6 @@ static struct platform_device rtc_dev = {
 	.id             = -1,
 };
 
-static struct snd_platform_data dm644x_evm_snd_data;
-
 /*----------------------------------------------------------------------*/
 #ifdef CONFIG_I2C
 /*
@@ -799,7 +797,7 @@ static __init void davinci_evm_init(void)
 	dm644x_init_video(&dm644xevm_capture_cfg, &dm644xevm_display_cfg);
 
 	davinci_serial_init(dm644x_serial_device);
-	dm644x_init_asp(&dm644x_evm_snd_data);
+	dm644x_init_asp();
 
 	/* irlml6401 switches over 1A, in under 8 msec */
 	davinci_setup_usb(1000, 8);
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 8fcdcf87c47c..ad10017203c1 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -127,8 +127,6 @@ static struct platform_device davinci_fb_device = {
 	.num_resources = 0,
 };
 
-static struct snd_platform_data dm644x_ntosd2_snd_data;
-
 static struct gpio_led ntosd2_leds[] = {
 	{ .name = "led1_green", .gpio = GPIO(10), },
 	{ .name = "led1_red",   .gpio = GPIO(11), },
@@ -200,7 +198,7 @@ static __init void davinci_ntosd2_init(void)
 				ARRAY_SIZE(davinci_ntosd2_devices));
 
 	davinci_serial_init(dm644x_serial_device);
-	dm644x_init_asp(&dm644x_ntosd2_snd_data);
+	dm644x_init_asp();
 
 	soc_info->emac_pdata->phy_id = NEUROS_OSD2_PHY_ID;
 
diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h
index 4ffc37accce0..d1f8e29f1e30 100644
--- a/arch/arm/mach-davinci/davinci.h
+++ b/arch/arm/mach-davinci/davinci.h
@@ -85,13 +85,13 @@ int davinci_init_wdt(void);
 void dm355_init(void);
 void dm355_init_spi0(unsigned chipselect_mask,
 		const struct spi_board_info *info, unsigned len);
-void dm355_init_asp1(u32 evt_enable, struct snd_platform_data *pdata);
+void dm355_init_asp1(u32 evt_enable);
 int dm355_init_video(struct vpfe_config *, struct vpbe_config *);
 int dm355_gpio_register(void);
 
 /* DM365 function declarations */
 void dm365_init(void);
-void dm365_init_asp(struct snd_platform_data *pdata);
+void dm365_init_asp(void);
 void dm365_init_vc(struct snd_platform_data *pdata);
 void dm365_init_ks(struct davinci_ks_platform_data *pdata);
 void dm365_init_rtc(void);
@@ -102,7 +102,7 @@ int dm365_gpio_register(void);
 
 /* DM644x function declarations */
 void dm644x_init(void);
-void dm644x_init_asp(struct snd_platform_data *pdata);
+void dm644x_init_asp(void);
 int dm644x_init_video(struct vpfe_config *, struct vpbe_config *);
 int dm644x_gpio_register(void);
 
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index 5a19cca7ed6a..d33322ddedab 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -1035,7 +1035,7 @@ static struct davinci_soc_info davinci_soc_info_dm355 = {
 	.sram_len		= SZ_32K,
 };
 
-void __init dm355_init_asp1(u32 evt_enable, struct snd_platform_data *pdata)
+void __init dm355_init_asp1(u32 evt_enable)
 {
 	/* we don't use ASP1 IRQs, or we'd need to mux them ... */
 	if (evt_enable & ASP1_TX_EVT_EN)
@@ -1044,7 +1044,6 @@ void __init dm355_init_asp1(u32 evt_enable, struct snd_platform_data *pdata)
 	if (evt_enable & ASP1_RX_EVT_EN)
 		davinci_cfg_reg(DM355_EVT9_ASP1_RX);
 
-	dm355_asp1_device.dev.platform_data = pdata;
 	platform_device_register(&dm355_asp1_device);
 }
 
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 8aa004b02fe9..95fbfd962c79 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -1138,7 +1138,7 @@ static struct davinci_soc_info davinci_soc_info_dm365 = {
 	.sram_len		= SZ_32K,
 };
 
-void __init dm365_init_asp(struct snd_platform_data *pdata)
+void __init dm365_init_asp(void)
 {
 	davinci_cfg_reg(DM365_MCBSP0_BDX);
 	davinci_cfg_reg(DM365_MCBSP0_X);
@@ -1148,7 +1148,6 @@ void __init dm365_init_asp(struct snd_platform_data *pdata)
 	davinci_cfg_reg(DM365_MCBSP0_BFSR);
 	davinci_cfg_reg(DM365_EVT2_ASP_TX);
 	davinci_cfg_reg(DM365_EVT3_ASP_RX);
-	dm365_asp_device.dev.platform_data = pdata;
 	platform_device_register(&dm365_asp_device);
 }
 
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 0afa279ec460..b437c3730f65 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -921,10 +921,9 @@ static struct davinci_soc_info davinci_soc_info_dm644x = {
 	.sram_len		= SZ_16K,
 };
 
-void __init dm644x_init_asp(struct snd_platform_data *pdata)
+void __init dm644x_init_asp(void)
 {
 	davinci_cfg_reg(DM644X_MCBSP);
-	dm644x_asp_device.dev.platform_data = pdata;
 	platform_device_register(&dm644x_asp_device);
 }
 
-- 
1.9.1



From petr at barix.com  Mon May  9 07:00:10 2016
From: petr at barix.com (Petr Kulhavy)
Date: Mon,  9 May 2016 16:00:10 +0200
Subject: [PATCH] ARM: davinci: da850: add clocks for mcbsp0 and 1
Message-ID: <1462802410-25164-1-git-send-email-petr@barix.com>

Add clock definitions "davinci-mcbsp.0" and "davinci-mcbsp.1" in order
to make McBSP driver work on the DA850 platform.

The McBSP 0 and 1 interfaces were not defined for the DA850 platform.
Neither were the related clocks. In order to make the use of McBSP via
devicetree the clocks need to be defined.

Signed-off-by: Petr Kulhavy <petr at barix.com>
---
 arch/arm/mach-davinci/da850.c | 16 ++++++++++++++++
 arch/arm/mach-davinci/psc.h   |  2 ++
 2 files changed, 18 insertions(+)

diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 239886299968..0d046accb35b 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -326,6 +326,20 @@ static struct clk mcasp_clk = {
 	.gpsc		= 1,
 };
 
+static struct clk mcbsp0_clk = {
+	.name		= "mcbsp0",
+	.parent		= &async3_clk,
+	.lpsc		= DA850_LPSC1_McBSP0,
+	.gpsc		= 1,
+};
+
+static struct clk mcbsp1_clk = {
+	.name		= "mcbsp1",
+	.parent		= &async3_clk,
+	.lpsc		= DA850_LPSC1_McBSP1,
+	.gpsc		= 1,
+};
+
 static struct clk lcdc_clk = {
 	.name		= "lcdc",
 	.parent		= &pll0_sysclk2,
@@ -482,6 +496,8 @@ static struct clk_lookup da850_clks[] = {
 	CLK("davinci_emac.1",	NULL,		&emac_clk),
 	CLK("davinci_mdio.0",	"fck",		&emac_clk),
 	CLK("davinci-mcasp.0",	NULL,		&mcasp_clk),
+	CLK("davinci-mcbsp.0",	NULL,		&mcbsp0_clk),
+	CLK("davinci-mcbsp.1",	NULL,		&mcbsp1_clk),
 	CLK("da8xx_lcdc.0",	"fck",		&lcdc_clk),
 	CLK("da830-mmc.0",	NULL,		&mmcsd0_clk),
 	CLK("da830-mmc.1",	NULL,		&mmcsd1_clk),
diff --git a/arch/arm/mach-davinci/psc.h b/arch/arm/mach-davinci/psc.h
index 99d47cfa301f..8af9f09fc10c 100644
--- a/arch/arm/mach-davinci/psc.h
+++ b/arch/arm/mach-davinci/psc.h
@@ -171,6 +171,8 @@
 #define DA8XX_LPSC1_I2C			11
 #define DA8XX_LPSC1_UART1		12
 #define DA8XX_LPSC1_UART2		13
+#define DA850_LPSC1_McBSP0		14
+#define DA850_LPSC1_McBSP1		15
 #define DA8XX_LPSC1_LCDC		16
 #define DA8XX_LPSC1_PWM			17
 #define DA850_LPSC1_MMC_SD1		18
-- 
1.9.1



From arnd at arndb.de  Mon May  9 07:02:05 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:02:05 +0200
Subject: [GIT PULL] ARM: mvebu: soc for v4.7 (#1)
In-Reply-To: <87twikscvg.fsf@free-electrons.com>
References: <87twikscvg.fsf@free-electrons.com>
Message-ID: <5055450.VbtMz52UEg@wuerfel>

On Friday 29 April 2016 16:33:55 Gregory CLEMENT wrote:

> ----------------------------------------------------------------
> mvebu soc for 4.7
> 
> - Clock framework cleanup with the "Remove CLK_IS_ROOT" series
> 

Merged into next/soc, thanks!

	Arnd


From Suzuki.Poulose at arm.com  Mon May  9 07:04:17 2016
From: Suzuki.Poulose at arm.com (Suzuki K Poulose)
Date: Mon, 9 May 2016 15:04:17 +0100
Subject: [PATCH] [for 4.7] arm-ccn: Enable building as module
In-Reply-To: <5729C2CC.7030806@arm.com>
References: <1461855901-23794-1-git-send-email-suzuki.poulose@arm.com>
 <5729C2CC.7030806@arm.com>
Message-ID: <573098E1.5050007@arm.com>

On 04/05/16 10:37, Suzuki K Poulose wrote:
> On 28/04/16 16:05, Suzuki K Poulose wrote:
>> arm-ccn driver uses irq_set_affinity, which is not exported and
>> hence cannot be built as a module, eventhough we have all the
>> bits ready. This patch makes use of the exported helper
>> irq_set_affinity_hint() instead. Also, the __free_irq expects
>> the affinity_hint to be NULL when we free the irq. So set the
>> affinity_hint to NULL at clean up.
>>
>> Now that we can build it as a module, update the Kconfig to
>> reflect the change.
>>
>> Cc: Will Deacon <will.deacon at arm.com>
>> Cc: Mark Rutland <mark.rutland at arm.com>
>> Cc: Paul Gortmaker <paul.gortmaker at windriver.com>
>> Acked-by: Pawel Moll <pawel.moll at arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> 
> Hi,
> 
> Could you please pull this for 4.7 ?

Gentle ping...

Suzuki




From arnd at arndb.de  Mon May  9 07:10:06 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:10:06 +0200
Subject: [GIT PULL 4/4] DaVinci documentation update for v4.7
In-Reply-To: <1461931627-27761-4-git-send-email-nsekhar@ti.com>
References: <1461931627-27761-1-git-send-email-nsekhar@ti.com>
 <1461931627-27761-4-git-send-email-nsekhar@ti.com>
Message-ID: <6374776.QQHFbQ6W7m@wuerfel>

On Friday 29 April 2016 17:37:07 Sekhar Nori wrote:
> MAINTAINERS file update to fix some
> stale entries.
> 
> 

Merged into next/soc, thanks!

	Arnd


From arnd at arndb.de  Mon May  9 07:10:36 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:10:36 +0200
Subject: [GIT PULL 1/6] i.MX soc updates for 4.7
In-Reply-To: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
References: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
Message-ID: <9769216.VIYSu12p0q@wuerfel>

On Tuesday 03 May 2016 23:58:01 Shawn Guo wrote:
> The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:
> 
>   Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-soc-4.7
> 
> for you to fetch changes up to acc98009b87a811f9f815650274a1044474cd167:
> 
>   ARM: imx: always use TWD on IMX6Q (2016-04-12 15:56:55 +0800)
> 
> ----------------------------------------------------------------
> The i.MX SoC updates for 4.7:
>  - Allow TWD to be used on UP kernel, as the PREEMPT-RT and cyclictest
>    shows that TWD has a slightly better performance than i.MX timer.
> 

Pulled into next/soc, thanks!

	Arnd


From arnd at arndb.de  Mon May  9 07:12:43 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:12:43 +0200
Subject: [PATCH] MAINTAINERS: ARM/Amlogic: add co-maintainer, misc. updates
In-Reply-To: <CAOQ7t2ZT5t+C1qRjvxP5Yj6wuGgZc3-Ti7CT1eXbpH2ZLZRxAg@mail.gmail.com>
References: <1462543166-8065-1-git-send-email-khilman@baylibre.com>
 <CAOQ7t2ZT5t+C1qRjvxP5Yj6wuGgZc3-Ti7CT1eXbpH2ZLZRxAg@mail.gmail.com>
Message-ID: <4124726.3fr6tUn8yX@wuerfel>

On Friday 06 May 2016 16:13:38 Carlo Caione wrote:
> On Fri, May 6, 2016 at 3:59 PM, Kevin Hilman <khilman at baylibre.com> wrote:
> > Add myself as co-maintainer, update mailing list entry and add a couple
> > more directories.
> >
> > Signed-off-by: Kevin Hilman <khilman at baylibre.com>
> 
> Acked-by: Carlo Caione <carlo at caione.org>

Applied to next/soc, thanks!

	Arnd


From edumazet at google.com  Mon May  9 07:14:41 2016
From: edumazet at google.com (Eric Dumazet)
Date: Mon, 9 May 2016 07:14:41 -0700
Subject: NFSroot hangs with bad unlock balance in Linux next
In-Reply-To: <20160509073235.GI2694@ZenIV.linux.org.uk>
References: <20160505220344.GE5995@atomide.com>
 <20160508141629.GF2694@ZenIV.linux.org.uk>
 <20160509073235.GI2694@ZenIV.linux.org.uk>
Message-ID: <CANn89iK5H-SokYE1r+OO3sPmQ1vpGqYGbE4x1QLn44wdyvH0cw@mail.gmail.com>

On Mon, May 9, 2016 at 12:32 AM, Al Viro <viro at zeniv.linux.org.uk> wrote:
> On Sun, May 08, 2016 at 03:16:29PM +0100, Al Viro wrote:
>
>> Very strange.  We grab that rwsem at the entry into nfs_call_unlink()
>> and then either release it there and return or call nfs_do_call_unlink().
>> Which arranges for eventual call of nfs_async_unlink_release() (via
>> ->rpc_release); nfs_async_unlink_release() releases the rwsem.  Nobody else
>> releases it (on the read side, that is).
>>
>> The only kinda-sorta possibility I see here is that the inode we are
>> unlocking in that nfs_async_unlink_release() is not the one we'd locked
>> in nfs_call_unlink() that has lead to it.  That really shouldn't happen,
>> though...  Just to verify whether that's what we are hitting, could you
>> try to reproduce that thing with the patch below on top of -next and see
>> if it triggers any of those WARN_ON?
>
> D'oh...  Lockdep warnings are easy to trigger (and, AFAICS, bogus).
> up_read/down_read in fs/nfs/unlink.c should be replaced with
> up_read_non_owner/down_read_non_owner, lest the lockdep gets confused.
> Hangs are different - I've no idea what's triggering those.  I've seen
> something similar on that -next, but not on work.lookups.
>
> The joy of bisecting -next...  <a couple of hours later>
> 9317bb69824ec8d078b0b786b6971aedb0af3d4f is the first bad commit
> commit 9317bb69824ec8d078b0b786b6971aedb0af3d4f
> Author: Eric Dumazet <edumazet at google.com>
> Date:   Mon Apr 25 10:39:32 2016 -0700
>
>     net: SOCKWQ_ASYNC_NOSPACE optimizations
>
> Reverting changes to sk_set_bit/sk_clear_bit gets rid of the hangs.  Plain
> revert gives a conflict, since there had been additional change in
> "net: SOCKWQ_ASYNC_WAITDATA optimizations"; removing both fixed the hangs.
>
> Note that hangs appear without any fs/nfs/unlink.c modifications being
> there.  When the hang happens it affects NFS traffic; ssh session still
> works fine until it steps on a filesystem operation on NFS (i.e. you
> can use builtins, access procfs, etc.)

Yeah, the issue was reported last week (
http://www.spinics.net/lists/netdev/msg375777.html ),
and I could not convince myself to add a new sock flag,  like
SOCK_FASYNC_STICKY.

(Just in case NFS would ever call sock_fasync() with an empty
fasync_list, and SOCK_FASYNC would be cleared again.


From arnd at arndb.de  Mon May  9 07:16:18 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:16:18 +0200
Subject: [PULL REQUEST] aspeed arch changes for 4.7
In-Reply-To: <1462796946-13579-1-git-send-email-joel@jms.id.au>
References: <1462796946-13579-1-git-send-email-joel@jms.id.au>
Message-ID: <13157357.VTBDHVBdl8@wuerfel>

On Monday 09 May 2016 21:59:06 Joel Stanley wrote:
> This is the initial pull request for the Aspeed BMC SoCs.
> 
> I put 4.7 in the subject for this and the subsequent requests but if it's a bit
> late in the cycle then I understand.
> 
> Following review I got rid of the board file by pushing the functionality out
> to a watchdog and clock driver, so it's just the Kconfig bits. I've also added
> myself to maintainers for the Aspeed arch and drivers as I intend on looking
> after them.
> 
> Please pull if it looks okay.
> 
> 
> The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:
> 
>   Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)
> 
> are available in the git repository at:
> 
>   https://github.com/shenki/linux.git tags/aspeed-for-4.7-arch
> 
> for you to fetch changes up to 8c2ed9bcfbeb7f313b567b25e87effd75e7dc3d6:
> 
>   arm: Add Aspeed machine (2016-05-09 17:41:14 +0930)
> 
> ----------------------------------------------------------------
> aspeed arch tag for 4.7
> 
> 

Pulled into next/soc.

Please try to put a little more context into the signed tag next
time, it's what ends up in the git history. I've copied the text
from your email above for this time.

	Arnd


From robin at protonic.nl  Mon May  9 07:17:28 2016
From: robin at protonic.nl (Robin van der Gracht)
Date: Mon, 9 May 2016 16:17:28 +0200
Subject: [GIT PULL] move ARM LCD display driver to auxdisplay
In-Reply-To: <CACRpkdbZmL9Cqp-ubzyxd7fWUFOVsS1DCxsfG02kSpbWu_rbZQ@mail.gmail.com>
References: <CACRpkdbyO0axd5ergYZcXO302f2fFAPKrSNevkvreP1kRjm-vw@mail.gmail.com>
 <20160425115758.GA4874@lukather>
 <CACRpkdb=s5onVa7qND9nFUtYPw5H-Hdr7Ja5o3=-9+wxghHekQ@mail.gmail.com>
 <20160428092608.GE17159@lukather> <5723755D.9060108@ti.com>
 <20160509090615.6272f8ca@erd979>
 <CACRpkdbZmL9Cqp-ubzyxd7fWUFOVsS1DCxsfG02kSpbWu_rbZQ@mail.gmail.com>
Message-ID: <20160509161728.3aee1134@erd979>

On Mon, 9 May 2016 15:19:26 +0200
Linus Walleij <linus.walleij at linaro.org> wrote:

> On Mon, May 9, 2016 at 9:06 AM, Robin van der Gracht
> <robin at protonic.nl> wrote:
> 
> > If you guys feel like auxdisplay is not the right subsystem for the
> > driver, and would like me to move it, please share.  
> 
> The best would be if you volunteer to maintain it and bring
> it forward.

Thats fine. Would it suffice if I submit another patch adding myself
to the maintainers file?

Regards,
Robin


From arnd at arndb.de  Mon May  9 07:17:43 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:17:43 +0200
Subject: [GIT PULL 1/3] Rockchip driver updates for v4.7 - part2
In-Reply-To: <2744609.Je9E5Knv0x@diego>
References: <5544434.9tA8JHBIkp@diego> <2744609.Je9E5Knv0x@diego>
Message-ID: <7857890.rMVEHqflgb@wuerfel>

On Friday 29 April 2016 00:24:10 Heiko St?bner wrote:
> Ability to save and restore the power-domain quality of service
> settings that get lost and reset on power-domain power cycles.
> 
> 

Pulled into next/drivers, thanks!

	Arnd


From arnd at arndb.de  Mon May  9 07:20:07 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:20:07 +0200
Subject: [GIT PULL 1/4]: phy: tegra: Changes for v4.7-rc1
In-Reply-To: <1461945149-23686-2-git-send-email-thierry.reding@gmail.com>
References: <1461945149-23686-1-git-send-email-thierry.reding@gmail.com>
 <1461945149-23686-2-git-send-email-thierry.reding@gmail.com>
Message-ID: <10540638.hjT0UpUyia@wuerfel>

On Friday 29 April 2016 17:52:26 Thierry Reding wrote:
> phy: tegra: Changes for v4.7-rc1
> 
> This set of patches adds support for the Tegra XUSB pad controller. The
> controller provides a set of pads (lanes) that are used for I/O by other
> IP blocks within Tegra SoCs (PCIe, SATA and XUSB).
> 
> 

Pulled into next/drivers, thanks!

	Arnd


From arnd at arndb.de  Mon May  9 07:22:38 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:22:38 +0200
Subject: [GIT PULL 2/4]: PCI: tegra: Changes for v4.7-rc1
In-Reply-To: <1461945149-23686-3-git-send-email-thierry.reding@gmail.com>
References: <1461945149-23686-1-git-send-email-thierry.reding@gmail.com>
 <1461945149-23686-3-git-send-email-thierry.reding@gmail.com>
Message-ID: <4400263.RxsudNrSIY@wuerfel>

On Friday 29 April 2016 17:52:27 Thierry Reding wrote:
> PCI: tegra: Changes for v4.7-rc1
> 
> These patches update the Tegra PCIe host bridge controller device tree
> 

Merged into next/drivers, thanks!

	Arnd


From arnd at arndb.de  Mon May  9 07:24:37 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:24:37 +0200
Subject: [GIT PULL 3/4]: usb: host: xhci-tegra: Changes for v4.7-rc1
In-Reply-To: <1461945149-23686-4-git-send-email-thierry.reding@gmail.com>
References: <1461945149-23686-1-git-send-email-thierry.reding@gmail.com>
 <1461945149-23686-4-git-send-email-thierry.reding@gmail.com>
Message-ID: <4340481.VaHiyrToxb@wuerfel>

On Friday 29 April 2016 17:52:28 Thierry Reding wrote:
> usb: host: xhci-tegra: Changes for v4.7-rc1
> 
> This set of patches introduces a driver for the XUSB controller found on
> NVIDIA Tegra SoCs. When loaded with a firmware (available via the linux-
> firmware repository), it provides an XHCI-compatible interface.
> 

Merged into next/drivers, thanks!

	Arnd


From linus.walleij at linaro.org  Mon May  9 07:27:00 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 9 May 2016 16:27:00 +0200
Subject: [GIT PULL] move ARM LCD display driver to auxdisplay
In-Reply-To: <20160509161728.3aee1134@erd979>
References: <CACRpkdbyO0axd5ergYZcXO302f2fFAPKrSNevkvreP1kRjm-vw@mail.gmail.com>
 <20160425115758.GA4874@lukather>
 <CACRpkdb=s5onVa7qND9nFUtYPw5H-Hdr7Ja5o3=-9+wxghHekQ@mail.gmail.com>
 <20160428092608.GE17159@lukather> <5723755D.9060108@ti.com>
 <20160509090615.6272f8ca@erd979>
 <CACRpkdbZmL9Cqp-ubzyxd7fWUFOVsS1DCxsfG02kSpbWu_rbZQ@mail.gmail.com>
 <20160509161728.3aee1134@erd979>
Message-ID: <CACRpkdZwPVMx-dXVkfVwFN0juzVuyvShV7yDWbUFSXOPE=uUrw@mail.gmail.com>

On Mon, May 9, 2016 at 4:17 PM, Robin van der Gracht <robin at protonic.nl> wrote:
> On Mon, 9 May 2016 15:19:26 +0200
> Linus Walleij <linus.walleij at linaro.org> wrote:
>
>> On Mon, May 9, 2016 at 9:06 AM, Robin van der Gracht
>> <robin at protonic.nl> wrote:
>>
>> > If you guys feel like auxdisplay is not the right subsystem for the
>> > driver, and would like me to move it, please share.
>>
>> The best would be if you volunteer to maintain it and bring
>> it forward.
>
> Thats fine. Would it suffice if I submit another patch adding myself
> to the maintainers file?

That's half of it, if Miguel does not come back then his name
should be removed as the second step.

You also need to have an idea on a path to funnel accumulated
patches upstream to Torvalds. The recent patches to this
subsystem were funneled by Greg, so we should ask him how
he prefer to proceed.

Greg, what do you prefer?

Yours,
Linus Walleij


From arnd at arndb.de  Mon May  9 07:27:40 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:27:40 +0200
Subject: [GIT PULL v2 4/4]: ARM: tegra: Enable the XUSB controller
In-Reply-To: <1461946410-24940-1-git-send-email-thierry.reding@gmail.com>
References: <1461945149-23686-5-git-send-email-thierry.reding@gmail.com>
 <1461946410-24940-1-git-send-email-thierry.reding@gmail.com>
Message-ID: <4193084.2p7bAmYgJ0@wuerfel>

On Friday 29 April 2016 18:13:30 Thierry Reding wrote:
> ARM: tegra: Enable the XUSB controller
> 
> These changes add support for the XUSB controller on Tegra124. It is an
> XHCI compatible controller that replaces the existing EHCI controllers.
> Support is enabled on Venice2, Jetson TK1 and Nyan-based Chromebooks.
> 

I have merged branches 1, 2, and 3 into next/drivers, and then again
into next/late, with this one on top. We will probably send the late
branch at the same time as the others, but this keeps the dependency
sorted out. Thanks,

	Arnd


From arnd at arndb.de  Mon May  9 07:29:03 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:29:03 +0200
Subject: [GIT PULL] soc/tegra: Add generic PM domain support
In-Reply-To: <1461946869-26124-1-git-send-email-thierry.reding@gmail.com>
References: <1461946869-26124-1-git-send-email-thierry.reding@gmail.com>
Message-ID: <4251738.3YkFNHn2NH@wuerfel>

On Friday 29 April 2016 18:21:06 Thierry Reding wrote:
> soc/tegra: Add generic PM domain support
> 
> Implements generic PM domain support on top of the existing Tegra power-
> gate API. Drivers are thus allowed to move away from the Tegra-specific
> API and towards using generic power domains directly.
> 
> 

Merged into next/drivers, thanks!

	Arnd


From arnd at arndb.de  Mon May  9 07:30:36 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:30:36 +0200
Subject: [GIT PULL] ARM: mediatek soc updates for v4.7
In-Reply-To: <CABuKBeJV6bA=2Sx_apRp2HMfuyymFCV67zxaoJzBeRbRMzv0AQ@mail.gmail.com>
References: <CABuKBeJV6bA=2Sx_apRp2HMfuyymFCV67zxaoJzBeRbRMzv0AQ@mail.gmail.com>
Message-ID: <4344474.MABVc9hllp@wuerfel>

On Monday 02 May 2016 16:34:11 Matthias Brugger wrote:
> - re-organize pmic wrapper code for easier and cleaner addiont of new
> SoCs and pmic wrappers
> - add support for pmic wrapper mt6323
> - add support for SoC mt2701
> - enable gpt6 arch timer on mt7623
> 

Pulled into next/drivers, thanks!

	Arnd


From arnd at arndb.de  Mon May  9 07:31:56 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:31:56 +0200
Subject: [GIT PULL] ARM: mediatek: kconfig updates for v4.7
In-Reply-To: <CABuKBeLwgcZ10pcSoOBnOFhFOMzr9sjoj28Qbi1pqAXGt0h0GQ@mail.gmail.com>
References: <CABuKBeLwgcZ10pcSoOBnOFhFOMzr9sjoj28Qbi1pqAXGt0h0GQ@mail.gmail.com>
Message-ID: <4823418.Yj1lKNn5Uv@wuerfel>

On Monday 02 May 2016 16:35:20 Matthias Brugger wrote:
> Add mt2701 support
> 

Merged into next/soc, thanks!

	Arnd


From arnd at arndb.de  Mon May  9 07:33:59 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:33:59 +0200
Subject: [GIT PULL] Reset controller changes for v4.7: build fix and OXNAS
 driver
In-Reply-To: <1462265548.3617.6.camel@pengutronix.de>
References: <1462265548.3617.6.camel@pengutronix.de>
Message-ID: <12721898.B3zhW3DZeG@wuerfel>

On Tuesday 03 May 2016 10:52:28 Philipp Zabel wrote:
> Reset controller changes for v4.7
> 
> - add missing stub for device_reset
> - add support for OXNAS SoCs
> 
> 

Merged into next/drivers, thanks!

	Arnd


From joel at jms.id.au  Mon May  9 07:34:41 2016
From: joel at jms.id.au (Joel Stanley)
Date: Tue, 10 May 2016 00:04:41 +0930
Subject: [PULL REQUEST] aspeed arch changes for 4.7
In-Reply-To: <13157357.VTBDHVBdl8@wuerfel>
References: <1462796946-13579-1-git-send-email-joel@jms.id.au>
 <13157357.VTBDHVBdl8@wuerfel>
Message-ID: <CACPK8Xd2jKwphtF7_qzMEmbzXM=DiFJk2c8Y-Tp6M-G2kkgxmQ@mail.gmail.com>

On Mon, May 9, 2016 at 11:46 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> On Monday 09 May 2016 21:59:06 Joel Stanley wrote:
>> This is the initial pull request for the Aspeed BMC SoCs.
>> aspeed arch tag for 4.7
>>
>
> Pulled into next/soc.
>
> Please try to put a little more context into the signed tag next
> time, it's what ends up in the git history. I've copied the text
> from your email above for this time.

I didn't realise that was the case, I'll do so next time. Thanks for
your help getting these merged!

Cheers,

Joel


From petr at barix.com  Mon May  9 07:35:18 2016
From: petr at barix.com (Petr Kulhavy)
Date: Mon,  9 May 2016 16:35:18 +0200
Subject: [PATCH v5 0/4] ASoC: davinci-mcbsp: add binding for McBSP
Message-ID: <1462804522-29544-1-git-send-email-petr@barix.com>

This series of patches adds devicetree support for the davinci McBSP audio
interface.

Changes in version 5 of the patch:

* rebased to the current master of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git
* independent changes submitted separately (3/7 and 7/7 of the version 4)
* 5/7 of the version 4 removed as already applied
* corrected mcbsp0 and mcbsp1 nodes in the DTS file: using correct address and sound@ prefix


From petr at barix.com  Mon May  9 07:35:19 2016
From: petr at barix.com (Petr Kulhavy)
Date: Mon,  9 May 2016 16:35:19 +0200
Subject: [PATCH v5 1/4] ASoC: davinci-mcbsp: add binding for McBSP
In-Reply-To: <1462804522-29544-1-git-send-email-petr@barix.com>
References: <1462804522-29544-1-git-send-email-petr@barix.com>
Message-ID: <1462804522-29544-2-git-send-email-petr@barix.com>

Add devicetree binding for the TI DA850/OMAP-L138/AM18xx
MultiChannel Buffered Serial Port (McBSP)

The optional register range "dat" is not implemented at the moment.
The current driver supports only DMA into RX/TX registers but no FIFO.
Once the FIFO is implemented in the driver the "dat" range will be used.

Signed-off-by: Petr Kulhavy <petr at barix.com>
---
v1: initial
v2: add missing TC channel in dmas properties (for compatibility with the new EDMA3 binding)
    remove "-audio" postfix from the compatible string
    remove "channel-combine" property
v3: remove the index note from the "mpu" property.
    specify exactly the supported platforms in compatible string
v4: minor correction in the example ("interrupt names"), re-added index note to the "mpu" property.
v5: example updated to match da850.dtsi: using "sound@" and removed leading zeros from the reg property

 .../devicetree/bindings/sound/davinci-mcbsp.txt    | 52 ++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/davinci-mcbsp.txt

diff --git a/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt b/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt
new file mode 100644
index 000000000000..e9184ff3c2fa
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt
@@ -0,0 +1,52 @@
+Texas Instruments DaVinci McBSP module
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This binding describes the "Multi-channel Buffered Serial Port" (McBSP)
+audio interface found in some TI DaVinci processors like the OMAP-L138 or AM180x.
+
+
+Required properties:
+~~~~~~~~~~~~~~~~~~~~
+- compatible :
+        "ti,da850-mcbsp" : for DA850, AM180x and OPAM-L138 platforms
+
+- reg : physical base address and length of the controller memory mapped
+        region(s).
+- reg-names : Should contain:
+        * "mpu" for the main registers (required). For compatibility
+          with the existing software, this is required to be the first entry.
+        * "dat" for the data FIFO (optional).
+
+- dmas: three element list of DMA controller phandles, DMA request line and
+	TC channel ordered triplets.
+- dma-names: identifier string for each DMA request line in the dmas property.
+	These strings correspond 1:1 with the ordered pairs in dmas. The dma
+	identifiers must be "rx" and "tx".
+
+Optional properties:
+~~~~~~~~~~~~~~~~~~~~
+- interrupts : Interrupt numbers for McBSP
+- interrupt-names : Known interrupt names are "rx" and "tx"
+
+- pinctrl-0: Should specify pin control group used for this controller.
+- pinctrl-names: Should contain only one value - "default", for more details
+        please refer to pinctrl-bindings.txt
+
+Example (AM1808):
+~~~~~~~~~~~~~~~~~
+
+mcbsp0: sound at 110000 {
+	compatible = "ti,da850-mcbsp";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcbsp0_pins>;
+
+	reg = 	<0x110000 0x1000>,
+		<0x310000 0x1000>;
+	reg-names = "mpu", "dat";
+	interrupts = <97 98>;
+	interrupt-names = "rx", "tx";
+	dmas = <&edma0 3 1
+		&edma0 2 1>;
+	dma-names = "tx", "rx";
+	status = "okay";
+};
-- 
1.9.1



From petr at barix.com  Mon May  9 07:35:20 2016
From: petr at barix.com (Petr Kulhavy)
Date: Mon,  9 May 2016 16:35:20 +0200
Subject: [PATCH v5 2/4] ASoC: Davinci: McBSP: add device tree support for McBSP
In-Reply-To: <1462804522-29544-1-git-send-email-petr@barix.com>
References: <1462804522-29544-1-git-send-email-petr@barix.com>
Message-ID: <1462804522-29544-3-git-send-email-petr@barix.com>

This adds DT support for the TI DA8xx/OMAP-L1x/AM17xx/AM18xx McBSP driver.

Signed-off-by: Petr Kulhavy <petr at barix.com>
Reviewed-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
v1: initial
v2: remove "-audio" postfix from the compatible string
    of_match_table renamed consistently with the rest of the file (davinci_i2s_match)
    "channel-combine" property removed
    devicetree DMA configuration in probe simplified
v3: remove the unused platform data
v4: no change
v5: no change

 sound/soc/davinci/Kconfig       |  6 +++-
 sound/soc/davinci/davinci-i2s.c | 80 +++++++++++++++++++++++++++--------------
 2 files changed, 59 insertions(+), 27 deletions(-)

diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 50ca291cc225..6b732d8e5896 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -16,7 +16,11 @@ config SND_EDMA_SOC
 	  - DRA7xx family
 
 config SND_DAVINCI_SOC_I2S
-	tristate
+	tristate "DaVinci Multichannel Buffered Serial Port (McBSP) support"
+	depends on SND_EDMA_SOC
+	help
+	  Say Y or M here if you want to have support for McBSP IP found in
+	  Texas Instruments DaVinci DA850 SoCs.
 
 config SND_DAVINCI_SOC_MCASP
 	tristate "Multichannel Audio Serial Port (McASP) support"
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index ec98548a5fc9..384961651904 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -4,9 +4,15 @@
  * Author:      Vladimir Barinov, <vbarinov at embeddedalley.com>
  * Copyright:   (C) 2007 MontaVista Software, Inc., <source at mvista.com>
  *
+ * DT support	(c) 2016 Petr Kulhavy, Barix AG <petr at barix.com>
+ *		based on davinci-mcasp.c DT support
+ *
  * 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.
+ *
+ * TODO:
+ * on DA850 implement HW FIFOs instead of DMA into DXR and DRR registers
  */
 
 #include <linux/init.h>
@@ -650,13 +656,24 @@ static const struct snd_soc_component_driver davinci_i2s_component = {
 
 static int davinci_i2s_probe(struct platform_device *pdev)
 {
+	struct snd_dmaengine_dai_dma_data *dma_data;
 	struct davinci_mcbsp_dev *dev;
 	struct resource *mem, *res;
 	void __iomem *io_base;
 	int *dma;
 	int ret;
 
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
+	if (!mem) {
+		dev_warn(&pdev->dev,
+			 "\"mpu\" mem resource not found, using index 0\n");
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!mem) {
+			dev_err(&pdev->dev, "no mem resource?\n");
+			return -ENODEV;
+		}
+	}
+
 	io_base = devm_ioremap_resource(&pdev->dev, mem);
 	if (IS_ERR(io_base))
 		return PTR_ERR(io_base);
@@ -666,39 +683,43 @@ static int davinci_i2s_probe(struct platform_device *pdev)
 	if (!dev)
 		return -ENOMEM;
 
-	dev->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(dev->clk))
-		return -ENODEV;
-	clk_enable(dev->clk);
-
 	dev->base = io_base;
 
-	dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr =
-	    (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG);
+	/* setup DMA, first TX, then RX */
+	dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK];
+	dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG);
 
-	dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr =
-	    (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG);
-
-	/* first TX, then RX */
 	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "no DMA resource\n");
-		ret = -ENXIO;
-		goto err_release_clk;
+	if (res) {
+		dma = &dev->dma_request[SNDRV_PCM_STREAM_PLAYBACK];
+		*dma = res->start;
+		dma_data->filter_data = dma;
+	} else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
+		dma_data->filter_data = "tx";
+	} else {
+		dev_err(&pdev->dev, "Missing DMA tx resource\n");
+		return -ENODEV;
 	}
-	dma = &dev->dma_request[SNDRV_PCM_STREAM_PLAYBACK];
-	*dma = res->start;
-	dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = dma;
+
+	dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE];
+	dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG);
 
 	res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!res) {
-		dev_err(&pdev->dev, "no DMA resource\n");
-		ret = -ENXIO;
-		goto err_release_clk;
+	if (res) {
+		dma = &dev->dma_request[SNDRV_PCM_STREAM_CAPTURE];
+		*dma = res->start;
+		dma_data->filter_data = dma;
+	} else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
+		dma_data->filter_data = "rx";
+	} else {
+		dev_err(&pdev->dev, "Missing DMA rx resource\n");
+		return -ENODEV;
 	}
-	dma = &dev->dma_request[SNDRV_PCM_STREAM_CAPTURE];
-	*dma = res->start;
-	dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data = dma;
+
+	dev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk))
+		return -ENODEV;
+	clk_enable(dev->clk);
 
 	dev->dev = &pdev->dev;
 	dev_set_drvdata(&pdev->dev, dev);
@@ -737,11 +758,18 @@ static int davinci_i2s_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id davinci_i2s_match[] = {
+	{ .compatible = "ti,da850-mcbsp" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, davinci_i2s_match);
+
 static struct platform_driver davinci_mcbsp_driver = {
 	.probe		= davinci_i2s_probe,
 	.remove		= davinci_i2s_remove,
 	.driver		= {
 		.name	= "davinci-mcbsp",
+		.of_match_table = of_match_ptr(davinci_i2s_match),
 	},
 };
 
-- 
1.9.1



From petr at barix.com  Mon May  9 07:35:21 2016
From: petr at barix.com (Petr Kulhavy)
Date: Mon,  9 May 2016 16:35:21 +0200
Subject: [PATCH v5 3/4] ARM: davinci: da8xx-dt: add OF_DEV_AUXDATA entries for
 mcbsp0 and mcbsp1
In-Reply-To: <1462804522-29544-1-git-send-email-petr@barix.com>
References: <1462804522-29544-1-git-send-email-petr@barix.com>
Message-ID: <1462804522-29544-4-git-send-email-petr@barix.com>

Add OF_DEV_AUXDATA for mcbsp to be able to use clocks.

Signed-off-by: Petr Kulhavy <petr at barix.com>
Reviewed-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
v1: initial
v2: remove "-audio" postfix from the compatible string
v3: no change
v4: no change
v5: rebased to the current master of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git

 arch/arm/mach-davinci/da8xx-dt.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c
index 754f478110b4..ae2bf237e374 100644
--- a/arch/arm/mach-davinci/da8xx-dt.c
+++ b/arch/arm/mach-davinci/da8xx-dt.c
@@ -35,8 +35,11 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("ns16550a", 0x01d0d000, "serial8250.2", NULL),
 	OF_DEV_AUXDATA("ti,davinci_mdio", 0x01e24000, "davinci_mdio.0", NULL),
 	OF_DEV_AUXDATA("ti,davinci-dm6467-emac", 0x01e20000, "davinci_emac.1",
-		       NULL),
-	OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0", NULL),
+			NULL),
+	OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0",
+			NULL),
+	OF_DEV_AUXDATA("ti,da850-mcbsp", 0x01d10000, "davinci-mcbsp.0", NULL),
+	OF_DEV_AUXDATA("ti,da850-mcbsp", 0x01d11000, "davinci-mcbsp.1", NULL),
 	{}
 };
 
-- 
1.9.1



From petr at barix.com  Mon May  9 07:35:22 2016
From: petr at barix.com (Petr Kulhavy)
Date: Mon,  9 May 2016 16:35:22 +0200
Subject: [PATCH v5 4/4] ARM: DTS: da850: Add McBSP0 and McBSP1
In-Reply-To: <1462804522-29544-1-git-send-email-petr@barix.com>
References: <1462804522-29544-1-git-send-email-petr@barix.com>
Message-ID: <1462804522-29544-5-git-send-email-petr@barix.com>

Add SoC nodes for McBSP0 and McBSP1 as well as the corresponding pinmux
configurations.

Signed-off-by: Petr Kulhavy <petr at barix.com>
---
v1: initial
v2: add missing TC channel in dmas properties (for compatibility with the new EDMA3 binding)
    remove "-audio" postfix from the compatible string
v3: no change
v4: no change
v5: rebased to current master of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git
    using "sound@" prefix instead of "mcbsp@" prefix
    address corrected to match the reg value
    removed leading zeros from the reg values

 arch/arm/boot/dts/da850.dtsi | 45 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index cf1aad8190f1..3a4450b7ae4a 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -166,7 +166,24 @@
 					0xc 0x88888888 0xffffffff
 				>;
 			};
-
+			mcbsp0_pins: pinmux_mcbsp0_pins {
+				pinctrl-single,bits = <
+					/* PINMUX2:
+					* CLKS0, DX0, DR0, FSX0
+					* FSR0, CLKX0, CLKR0
+					*/
+					0x8 0x02222220 0xfffffff0
+				>;
+			};
+			mcbsp1_pins: pinmux_mcbsp1_pins {
+				pinctrl-single,bits = <
+					/* PINMUX1:
+					* CLKS1, DX1, DR1, FSX1,
+					* FSR1, CLKX1, CLKR1
+					*/
+					0x4 0x22222220 0xfffffff0
+				>;
+			};
 		};
 		edma0: edma at 0 {
 			compatible = "ti,edma3-tpcc";
@@ -374,6 +391,32 @@
 				<&edma0 0 1>;
 			dma-names = "tx", "rx";
 		};
+
+		mcbsp0: sound at 110000 {
+			compatible = "ti,da850-mcbsp";
+			reg =	<0x110000 0x1000>,
+				<0x310000 0x1000>;
+			reg-names = "mpu", "dat";
+			interrupts = <97 98>;
+			interrupts-names = "rx", "tx";
+			dmas = <&edma0 3 1
+				&edma0 2 1>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+		mcbsp1: sound at 111000 {
+			compatible = "ti,da850-mcbsp";
+			reg =	<0x111000 0x1000>,
+				<0x311000 0x1000>;
+			reg-names = "mpu", "dat";
+			interrupts = <99 100>;
+			interrupts-names = "rx", "tx";
+			dmas = <&edma0 5 1
+				&edma0 4 1>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
 	};
 	nand_cs3 at 62000000 {
 		compatible = "ti,davinci-nand";
-- 
1.9.1



From arnd at arndb.de  Mon May  9 07:36:54 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:36:54 +0200
Subject: [PATCH] [for 4.7] arm-ccn: Enable building as module
In-Reply-To: <573098E1.5050007@arm.com>
References: <1461855901-23794-1-git-send-email-suzuki.poulose@arm.com>
 <5729C2CC.7030806@arm.com> <573098E1.5050007@arm.com>
Message-ID: <17116806.BYbaJP9QyN@wuerfel>

On Monday 09 May 2016 15:04:17 Suzuki K Poulose wrote:
> On 04/05/16 10:37, Suzuki K Poulose wrote:
> > On 28/04/16 16:05, Suzuki K Poulose wrote:
> >> arm-ccn driver uses irq_set_affinity, which is not exported and
> >> hence cannot be built as a module, eventhough we have all the
> >> bits ready. This patch makes use of the exported helper
> >> irq_set_affinity_hint() instead. Also, the __free_irq expects
> >> the affinity_hint to be NULL when we free the irq. So set the
> >> affinity_hint to NULL at clean up.
> >>
> >> Now that we can build it as a module, update the Kconfig to
> >> reflect the change.
> >>
> >> Cc: Will Deacon <will.deacon at arm.com>
> >> Cc: Mark Rutland <mark.rutland at arm.com>
> >> Cc: Paul Gortmaker <paul.gortmaker at windriver.com>
> >> Acked-by: Pawel Moll <pawel.moll at arm.com>
> >> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> > 
> > Hi,
> > 
> > Could you please pull this for 4.7 ?
> 
> Gentle ping...
> 

Applied now, sorry for the delay and thanks for the reminders.

It was in my todo list the whole time, I just didn't get around to
do any merges last week.

	Arnd


From arnd at arndb.de  Mon May  9 07:38:48 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:38:48 +0200
Subject: [GIT PULL] ARM: dts: exynos: Non-critical fixes for v4.7
In-Reply-To: <1462619428-13798-1-git-send-email-k.kozlowski@samsung.com>
References: <1462619428-13798-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <7398428.rrnfaS9ayc@wuerfel>

On Saturday 07 May 2016 13:10:28 Krzysztof Kozlowski wrote:
> Samsung DTS non-critical fixes for v4.7:
> 1. Fix s5p-mfc driver probe on Exynos542x Peach boards (need to provide MFC
>    memory banks). On these boards this was broken for long time but
>    apparently no one enabled this driver till now.
> 2. Fix creation of debugfs entries for one regulator on Exynos4210
>    Trats board.
> 3. Fix probing of max8997 MFD driver (and its children) because
>    of missing interrupt. Actually the current version of the driver probes
>    (just without interrupts) but after switching to regmap and regmap-irq,
>    the interrupt will be mandatory.
> 
> 

Merged into next/fixes-non-critical, thanks!

	Arnd


From Suzuki.Poulose at arm.com  Mon May  9 07:40:13 2016
From: Suzuki.Poulose at arm.com (Suzuki K Poulose)
Date: Mon, 9 May 2016 15:40:13 +0100
Subject: [PATCH] [for 4.7] arm-ccn: Enable building as module
In-Reply-To: <17116806.BYbaJP9QyN@wuerfel>
References: <1461855901-23794-1-git-send-email-suzuki.poulose@arm.com>
 <5729C2CC.7030806@arm.com> <573098E1.5050007@arm.com>
 <17116806.BYbaJP9QyN@wuerfel>
Message-ID: <5730A14D.2010705@arm.com>

On 09/05/16 15:36, Arnd Bergmann wrote:
>
> Applied now, sorry for the delay and thanks for the reminders.
>
> It was in my todo list the whole time, I just didn't get around to
> do any merges last week.

No problems, Thanks Arnd.

Suzuki



From arnd at arndb.de  Mon May  9 07:41:46 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:41:46 +0200
Subject: [GIT PULL] omap legacy boot vs dt boot fixes for v4.7 merge window
In-Reply-To: <20160504173153.GT5995@atomide.com>
References: <20160504173153.GT5995@atomide.com>
Message-ID: <4944500.vQ12ELNkJC@wuerfel>

On Wednesday 04 May 2016 10:31:53 Tony Lindgren wrote:
> Legacy booting vs device tree booting fixes for omaps for
> v4.7 merge window. These are not considered urgent fixes enough
> for the v4.6-rc cycle, but we need them in v4.7 in order to drop
> the last remaining board-*.c files for omap3 for v4.8 merge window.
> 
> On Nokia N900, we need to pass the MMC slot names for the legacy
> user space to work. Let's do that using auxdata as the driver is
> setting up things already with the pdata for legacy booting. Then
> we can later on discuss if we may want to have some generic binding
> describing where the MMC slots are on the device.
> 
> N900 also has had the ir-rx51 device driver unusable with multiarch
> for a long time. Let's pass the dmtimer data in pdata for the driver
> to get it going again. Then once things are working, we can eventually
> change the driver to use just hrtimer and PWM framework. The driver
> changes will be queued separately.
> 

Good plan, merged it into next/fixes-non-critical, thanks!

	Arnd


From arnd at arndb.de  Mon May  9 07:42:46 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 09 May 2016 16:42:46 +0200
Subject: [GIT PULL] non urgent auxdata fix for v4.7 merge window
In-Reply-To: <20160504175306.GU5995@atomide.com>
References: <20160504175306.GU5995@atomide.com>
Message-ID: <6011894.DIQc11mCV6@wuerfel>

On Wednesday 04 May 2016 10:53:07 Tony Lindgren wrote:
> Device tree auxdata handling fix that allows a match based on the
> compatible string if no exact match based on the IO address is found.
> 
> This leaves out the need to patch auxdata for each driver when adding
> new SoCs. And it also reprotedly fixes the issue of passing auxdata
> to a child if the parent instantiates the child from DT as discussed
> in the "[PATCH] of/platform: Allow secondary compatible match in
> of_dev_lookup" mailing list thread.
> 
> As a minimal use case, let's also convert omap pinctrl auxdatato
> use a generic match.
> 
> There is no need to get this in to the v4.6-rc cycle and it can wait
> for v4.7 merge window. Note that these changes have now been sitting
> in Linux next for about two weeks so far as I wanted to make sure no
> new issues are popping up.
> 
> 

Merged into next/fixes-non-critical, thanks!

	Arnd


From linux at roeck-us.net  Mon May  9 07:48:25 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Mon, 9 May 2016 07:48:25 -0700
Subject: [PATCH 2/2] watchdog: Add Aspeed watchdog driver
In-Reply-To: <1462797277-14969-3-git-send-email-joel@jms.id.au>
References: <1462797277-14969-1-git-send-email-joel@jms.id.au>
 <1462797277-14969-3-git-send-email-joel@jms.id.au>
Message-ID: <5730A339.80006@roeck-us.net>

Hi Joel,

On 05/09/2016 05:34 AM, Joel Stanley wrote:
> Provides generic watchdog features as well as reboot support for the
> Apeed SoC.
>
> Signed-off-by: Joel Stanley <joel at jms.id.au>
> ---
>   drivers/watchdog/Kconfig      |  13 +++
>   drivers/watchdog/Makefile     |   1 +
>   drivers/watchdog/aspeed_wdt.c | 199 ++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 213 insertions(+)
>   create mode 100644 drivers/watchdog/aspeed_wdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index fb947655badd..4f0e2ded4785 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -661,6 +661,19 @@ config ATLAS7_WATCHDOG
>   	  To compile this driver as a module, choose M here: the
>   	  module will be called atlas7_wdt.
>
> +config ASPEED_WATCHDOG
> +	tristate "Aspeed 2400 watchdog support"
> +	depends on ARCH_ASPEED || COMPILE_TEST
> +	select WATCHDOG_CORE
> +	help
> +	  Say Y here to include support for the watchdog timer
> +	  in Apseed BMC SoCs.
> +
> +	  This driver is required to reboot the SoC.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called aspeed_wdt.
> +
>   # AVR32 Architecture
>
>   config AT32AP700X_WDT
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index feb6270fdbde..36855375e0ce 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -73,6 +73,7 @@ obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
>   obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
>   obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
>   obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o
> +obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o
>
>   # AVR32 Architecture
>   obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
> diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
> new file mode 100644
> index 000000000000..46cc71963c62
> --- /dev/null
> +++ b/drivers/watchdog/aspeed_wdt.c
> @@ -0,0 +1,199 @@
> +/*
> + * Copyright 2016 IBM Corporation
> + *
> + * Joel Stanley <joel at jms.id.au>
> + *
> + * Based on the qcom-watchdog driver
> + *
> + * 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.
> + */
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/watchdog.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +
> +struct aspeed_wdt {
> +	struct watchdog_device	wdd;
> +	unsigned long		rate;
> +	void __iomem		*base;
> +	u32			ctrl;
> +};
> +
> +static const struct of_device_id aspeed_wdt_of_table[] = {
> +	{ .compatible = "aspeed,wdt" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
> +
> +#define WDT_STATUS		0x00
> +#define WDT_RELOAD_VALUE	0x04
> +#define WDT_RESTART		0x08
> +#define WDT_CTRL		0x0C
> +#define   WDT_CTRL_RESET_MODE_SOC	(0x00 << 5)
> +#define   WDT_CTRL_RESET_MODE_FULL_CHIP	(0x01 << 5)
> +#define	  WDT_CTRL_1MHZ_CLK		BIT(4)
> +#define	  WDT_CTRL_WDT_EXT		BIT(3)
> +#define	  WDT_CTRL_WDT_INTR		BIT(2)
> +#define   WDT_CTRL_RESET_SYSTEM		BIT(1)
> +#define   WDT_CTRL_ENABLE		BIT(0)
> +
> +#define	WDT_RESTART_MAGIC	0x4755

Please don't use tabs after #define.

> +
> +static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd)
> +{
> +	return container_of(wdd, struct aspeed_wdt, wdd);
> +}
> +
> +
Please no double empty lines.

> +static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
> +{
> +	wdt->ctrl |= WDT_CTRL_ENABLE;
> +
> +	writel(0, wdt->base + WDT_CTRL);
> +	writel(count, wdt->base + WDT_RELOAD_VALUE);
> +	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
> +	writel(wdt->ctrl, wdt->base + WDT_CTRL);

Is it really necessary to write 0 into the ctrl register when enabling
the watchdog ? Problem with it is two-fold: It changes the clock rate
for a brief period of time, and it disables the watchdog while updating
the timeout. Both is undesirable unless really needed.

> +}
> +
> +static int aspeed_wdt_start(struct watchdog_device *wdd)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +
> +	dev_dbg(wdd->parent, "starting with timeout of %d (rate %lu)\n",
> +			wdd->timeout, wdt->rate);

Are those dev_dbg() really useful ?

> +	aspeed_wdt_enable(wdt, wdd->timeout * wdt->rate);
> +
> +	return 0;
> +}
> +
> +static int aspeed_wdt_stop(struct watchdog_device *wdd)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +
> +	wdt->ctrl &= ~WDT_CTRL_ENABLE;
> +	writel(wdt->ctrl, wdt->base + WDT_CTRL);
> +
> +	return 0;
> +}
> +
> +static int aspeed_wdt_ping(struct watchdog_device *wdd)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +
> +	dev_dbg(wdd->parent, "ping\n");
> +	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
> +	return 0;
> +}
> +
> +static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
> +				  unsigned int timeout)
> +{
> +	dev_dbg(wdd->parent, "timeout set to %u\n", timeout);
> +	wdd->timeout = timeout;
> +
> +	return aspeed_wdt_start(wdd);
> +}
> +
> +static int aspeed_wdt_restart(struct watchdog_device *wdd,
> +			      unsigned long action, void *data)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +
> +	aspeed_wdt_enable(wdt, 128 * wdt->rate / 1000);
> +
> +	return 0;
> +}
> +
> +static const struct watchdog_ops aspeed_wdt_ops = {
> +	.start		= aspeed_wdt_start,
> +	.stop		= aspeed_wdt_stop,
> +	.ping		= aspeed_wdt_ping,
> +	.set_timeout	= aspeed_wdt_set_timeout,
> +	.restart	= aspeed_wdt_restart,
> +	.owner		= THIS_MODULE,
> +};
> +
> +static const struct watchdog_info aspeed_wdt_info = {
> +	.options	= WDIOF_KEEPALIVEPING
> +			| WDIOF_MAGICCLOSE
> +			| WDIOF_SETTIMEOUT,
> +	.identity	= KBUILD_MODNAME,
> +};
> +
> +static int aspeed_wdt_remove(struct platform_device *pdev)
> +{
> +	struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
> +
> +	watchdog_unregister_device(&wdt->wdd);
> +
> +	return 0;
> +}
> +
> +static int aspeed_wdt_probe(struct platform_device *pdev)
> +{
> +	struct aspeed_wdt *wdt;
> +	struct resource *res;
> +	int ret;
> +
> +	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
> +	if (!wdt)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	wdt->base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(wdt->base))
> +		return PTR_ERR(wdt->base);
> +
> +	/*
> +	 * The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only
> +	 * runs at 1MHz. We chose to always run at 1MHz, as there's no
> +	 * good reason to have a faster watchdog counter.
> +	 */
> +	wdt->rate = 1000000;

Why not just use a define ?

> +	wdt->wdd.info = &aspeed_wdt_info;
> +	wdt->wdd.ops = &aspeed_wdt_ops;
> +	wdt->wdd.min_timeout = 1;
> +	wdt->wdd.max_timeout = 0x10000000U / wdt->rate;
> +	wdt->wdd.parent = &pdev->dev;
> +
> +	wdt->wdd.timeout = min(wdt->wdd.max_timeout, 30U);

Pretty much the same here. Since max_timeout is a constant,
it is well known that it is larger than 30 seconds.
Might as well use defines for max_timeout and timeout.

> +	watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
> +
> +	wdt->ctrl = WDT_CTRL_RESET_MODE_SOC |

Only reset tha SoC ? Are you sure this is what you want ?

> +		WDT_CTRL_1MHZ_CLK |
> +		WDT_CTRL_RESET_SYSTEM;
> +
> +	/* Ensure hardware is in consistent state */
> +	aspeed_wdt_stop(&wdt->wdd);
> +
An alternative might be to check if the watchdog is running, and inform
the watchdog core about it so it can generate heartbeats as required
until user space opens the watchdog device. This would ensure that the
system is protected during boot.

ctrl is really static except for the enable flag. Not really sure
if having a variable for it has any real benefits - you might as well
just read the register and update the enable flag instead as needed when
starting or stopping the watchdog. Is there a reason for not doing that ?

> +	ret = watchdog_register_device(&wdt->wdd);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to register\n");
> +		goto err;

Unnecessary goto. Just return.

> +	}
> +
> +	dev_info(&pdev->dev, "rate %lu, max timeout %u, timeout %d\n",
> +		 wdt->rate, wdt->wdd.max_timeout, wdt->wdd.timeout);
> +
> +	platform_set_drvdata(pdev, wdt);
> +err:
> +	return ret;
> +}
> +
> +static struct platform_driver aspeed_watchdog_driver = {
> +	.probe = aspeed_wdt_probe,
> +	.remove = aspeed_wdt_remove,
> +	.driver = {
> +		.name = KBUILD_MODNAME,
> +		.of_match_table = of_match_ptr(aspeed_wdt_of_table),
> +	},
> +};
> +module_platform_driver(aspeed_watchdog_driver);
> +
> +MODULE_DESCRIPTION("Aspeed Watchdog Driver");
> +MODULE_LICENSE("GPL");
>



From marc.zyngier at arm.com  Mon May  9 07:51:28 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon,  9 May 2016 15:51:28 +0100
Subject: [PATCH v2] clocksource/arm_arch_timer: Force per-CPU interrupt to be
 level-triggered
Message-ID: <1462805488-21535-1-git-send-email-marc.zyngier@arm.com>

The ARM architected timer produces level-triggered interrupts (this
is mandated by the architecture). Unfortunately, most device-trees
get this wrong, and expose an edge-triggered interrupt.

Until now, this wasn't too much an issue, as the programming of the
trigger would fail (the corresponding PPI cannot be reconfigured),
and the kernel would be happy with this. But we're about to change
this, and trust DT a lot if the driver doesn't provide its own
trigger information. In that context, the timer breaks badly.

While we do need to fix the DTs, there is also some userspace out
there (kvmtool) that generates the same kind of broken DT on the
fly, and that will completely break with newer kernels.

As a safety measure, and to keep buggy software alive as well as
buying us some time to fix DTs all over the place, let's check
what trigger configuration has been given us by the firmware.
If this is not a level configuration, then we know that the
DT/ACPI configuration is bust, and we pick some defaults which
won't be worse than the existing setup.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
- from v1: realised that there is no sane default, as we already have
  diverging configurations. Instead, test for a level interrupt, and
  force it to level low if current setting was edge. Also scream at the
  unfortunate user.

 drivers/clocksource/arm_arch_timer.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 5152b38..be8cc6d 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -8,6 +8,9 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#define pr_fmt(fmt)	"arm_arch_timer: " fmt
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
@@ -362,14 +365,32 @@ static bool arch_timer_has_nonsecure_ppi(void)
 		arch_timer_ppi[PHYS_NONSECURE_PPI]);
 }
 
+static u32 check_ppi_trigger(int irq)
+{
+	u32 flags = irq_get_trigger_type(irq);
+
+	if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) {
+		pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq);
+		pr_warn("WARNING: Please fix your firmware\n");
+		flags = IRQF_TRIGGER_LOW;
+	}
+
+	return flags;
+}
+
 static int arch_timer_setup(struct clock_event_device *clk)
 {
+	u32 flags;
+
 	__arch_timer_setup(ARCH_CP15_TIMER, clk);
 
-	enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0);
+	flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]);
+	enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags);
 
-	if (arch_timer_has_nonsecure_ppi())
-		enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0);
+	if (arch_timer_has_nonsecure_ppi()) {
+		flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]);
+		enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags);
+	}
 
 	arch_counter_set_user_access();
 	if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM))
-- 
2.1.4



From joro at 8bytes.org  Mon May  9 07:51:57 2016
From: joro at 8bytes.org (Joerg Roedel)
Date: Mon, 9 May 2016 16:51:57 +0200
Subject: [PATCH 0/5] Introduce per-domain page sizes
In-Reply-To: <57307863.1070706@arm.com>
References: <cover.1460048991.git.robin.murphy@arm.com>
 <20160509112138.GB13275@8bytes.org> <57307863.1070706@arm.com>
Message-ID: <20160509145157.GD13971@8bytes.org>

On Mon, May 09, 2016 at 12:45:39PM +0100, Robin Murphy wrote:
> Thanks a lot! I was expecting to pick this up again after the merge
> window and post an updated version then; as you may already have
> found, patch 5 conflicts somewhat with the SMMUv2 context format
> changes in Will's updates branch. The correct resolution requires a
> bit of rewriting, so below is what that patch looks like when
> rebased on top of Will's branch. If you'd prefer it in actual merge
> resolution format, shout and I'll give that a go.

Okay, hmm, but the patch does not apply here, even after fixing the line
breaks. I'll push my tree soon, can you rebase this patch on-top the
core branch then? It should already contain patches 1-4.


	Joerg



From tony at atomide.com  Mon May  9 08:12:19 2016
From: tony at atomide.com (Tony Lindgren)
Date: Mon, 9 May 2016 08:12:19 -0700
Subject: NFSroot hangs with bad unlock balance in Linux next
In-Reply-To: <CANn89iK5H-SokYE1r+OO3sPmQ1vpGqYGbE4x1QLn44wdyvH0cw@mail.gmail.com>
References: <20160505220344.GE5995@atomide.com>
 <20160508141629.GF2694@ZenIV.linux.org.uk>
 <20160509073235.GI2694@ZenIV.linux.org.uk>
 <CANn89iK5H-SokYE1r+OO3sPmQ1vpGqYGbE4x1QLn44wdyvH0cw@mail.gmail.com>
Message-ID: <20160509151219.GF5995@atomide.com>

* Eric Dumazet <edumazet at google.com> [160509 07:16]:
> On Mon, May 9, 2016 at 12:32 AM, Al Viro <viro at zeniv.linux.org.uk> wrote:
> > On Sun, May 08, 2016 at 03:16:29PM +0100, Al Viro wrote:
> >
> >> Very strange.  We grab that rwsem at the entry into nfs_call_unlink()
> >> and then either release it there and return or call nfs_do_call_unlink().
> >> Which arranges for eventual call of nfs_async_unlink_release() (via
> >> ->rpc_release); nfs_async_unlink_release() releases the rwsem.  Nobody else
> >> releases it (on the read side, that is).
> >>
> >> The only kinda-sorta possibility I see here is that the inode we are
> >> unlocking in that nfs_async_unlink_release() is not the one we'd locked
> >> in nfs_call_unlink() that has lead to it.  That really shouldn't happen,
> >> though...  Just to verify whether that's what we are hitting, could you
> >> try to reproduce that thing with the patch below on top of -next and see
> >> if it triggers any of those WARN_ON?

Thanks no warnings with that patch though.

> > D'oh...  Lockdep warnings are easy to trigger (and, AFAICS, bogus).
> > up_read/down_read in fs/nfs/unlink.c should be replaced with
> > up_read_non_owner/down_read_non_owner, lest the lockdep gets confused.
> > Hangs are different - I've no idea what's triggering those.  I've seen
> > something similar on that -next, but not on work.lookups.
> >
> > The joy of bisecting -next...  <a couple of hours later>
> > 9317bb69824ec8d078b0b786b6971aedb0af3d4f is the first bad commit
> > commit 9317bb69824ec8d078b0b786b6971aedb0af3d4f
> > Author: Eric Dumazet <edumazet at google.com>
> > Date:   Mon Apr 25 10:39:32 2016 -0700
> >
> >     net: SOCKWQ_ASYNC_NOSPACE optimizations
> >
> > Reverting changes to sk_set_bit/sk_clear_bit gets rid of the hangs.  Plain
> > revert gives a conflict, since there had been additional change in
> > "net: SOCKWQ_ASYNC_WAITDATA optimizations"; removing both fixed the hangs.
> >
> > Note that hangs appear without any fs/nfs/unlink.c modifications being
> > there.  When the hang happens it affects NFS traffic; ssh session still
> > works fine until it steps on a filesystem operation on NFS (i.e. you
> > can use builtins, access procfs, etc.)
> 
> Yeah, the issue was reported last week (
> http://www.spinics.net/lists/netdev/msg375777.html ),
> and I could not convince myself to add a new sock flag,  like
> SOCK_FASYNC_STICKY.
> 
> (Just in case NFS would ever call sock_fasync() with an empty
> fasync_list, and SOCK_FASYNC would be cleared again.

Yeah applying the test patch from the url above makes things work
for me again.

Regards,

Tony


From robin.murphy at arm.com  Mon May  9 08:18:39 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Mon, 9 May 2016 16:18:39 +0100
Subject: [PATCH 0/5] Introduce per-domain page sizes
In-Reply-To: <20160509145157.GD13971@8bytes.org>
References: <cover.1460048991.git.robin.murphy@arm.com>
 <20160509112138.GB13275@8bytes.org> <57307863.1070706@arm.com>
 <20160509145157.GD13971@8bytes.org>
Message-ID: <5730AA4F.4040303@arm.com>

On 09/05/16 15:51, Joerg Roedel wrote:
> On Mon, May 09, 2016 at 12:45:39PM +0100, Robin Murphy wrote:
>> Thanks a lot! I was expecting to pick this up again after the merge
>> window and post an updated version then; as you may already have
>> found, patch 5 conflicts somewhat with the SMMUv2 context format
>> changes in Will's updates branch. The correct resolution requires a
>> bit of rewriting, so below is what that patch looks like when
>> rebased on top of Will's branch. If you'd prefer it in actual merge
>> resolution format, shout and I'll give that a go.
>
> Okay, hmm, but the patch does not apply here, even after fixing the line
> breaks. I'll push my tree soon, can you rebase this patch on-top the
> core branch then? It should already contain patches 1-4.

Bah, I saw last week's "Merge remote-tracking branch 
'will/for-joerg/arm-smmu/updates' into HEAD" commit on that branch 
without spotting it was no longer up to date, sorry. Yes, it's probably 
safest if I rebase on top of your merge of everything else - I'll keep 
an eye out.

Thanks,
Robin.

>
>
> 	Joerg
>



From alex.williamson at redhat.com  Mon May  9 08:20:15 2016
From: alex.williamson at redhat.com (Alex Williamson)
Date: Mon, 9 May 2016 09:20:15 -0600
Subject: VFIO MSIX Query
In-Reply-To: <CAB995MvxU+mN9uxr_20nLkoezyhedUAHdFWawk-GG_bj0YjSYw@mail.gmail.com>
References: <CAB995Mu0==PJ0iU4h_3oAMGo-VYDFrjOg_BO757M=PDWgMWtCw@mail.gmail.com>
 <20160503140249.4edaf3cc@t450s.home>
 <CAB995MsFjv=GvHSmo029fmuTWhGiYev3-2A358orFz_dq724Fw@mail.gmail.com>
 <20160507195058.5b00f176@ul30vt.home>
 <CAB995MvxU+mN9uxr_20nLkoezyhedUAHdFWawk-GG_bj0YjSYw@mail.gmail.com>
Message-ID: <20160509092015.39129d56@t450s.home>

On Sun, 8 May 2016 20:45:10 +0530
Nitin Saxena <nitin.lnx at gmail.com> wrote:

> Hi Alex,
> 
> Thanks for your answer. I got the point that all access to device must be
> VFIO.
> I have few more questions.
> 
> >> When the device is initially opened via the VFIO_GET_DEVICE_FD ioctl, we  
> go through an initialization sequence on the device, including a device
> reset
> Does this mean only one process (primary in multiprocess app) can only
> perform VFIO_GROUP_GET_DEVICE_FD ioctl ? which I doubt as I saw in dpdk
> that each process (regardless primary or not) does VFIO_GROUP_GET_DEVICE_FD
> ioctl. Kindly confirm.

Users can call GET_DEVICE_FD multiple times, but note that the group
file descriptor can only be opened once, so you'd need to pass
device file descriptors off to other threads.

> >> Use VFIO for all access to the device or don't use VFIO at all.  
> I will map PCI BARS via VFIO but what about hugepages for each process.
> Since I am using VFIO_NOIOMMU do I need to call VFIO_IOMMU_MAP_DMA ioctl
> for each hugepage of each process? I think this is not needed in my case.
> Please confirm.

No-IOMMU mode does not have MAP_DMA or UNMAP_DMA ioctls.  If you want
to support a safe operating mode, with an IOMMU providing DMA
isolation, then yes, you would need to map DMA targets for the device
using those ioctls for the type1 IOMMU backend.

> Can you please also confirm about the patch I attached. Is there any thing
> missing in the patch that I needed to incorporate from kernel 4.5 to make
> VFO NOIOMMU work? Patch

I can't confirm or deny whether the backport is accurate.  Thanks,

Alex


From mark.rutland at arm.com  Mon May  9 08:20:04 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 9 May 2016 16:20:04 +0100
Subject: [PATCH 1/2] doc/devicetree: Add Aspeed VIC bindings
In-Reply-To: <1462797239-14765-2-git-send-email-joel@jms.id.au>
References: <1462797239-14765-1-git-send-email-joel@jms.id.au>
 <1462797239-14765-2-git-send-email-joel@jms.id.au>
Message-ID: <20160509152003.GA13842@leverpostej>

On Mon, May 09, 2016 at 10:03:58PM +0930, Joel Stanley wrote:
> Signed-off-by: Joel Stanley <joel at jms.id.au>
> ---
>  .../interrupt-controller/aspeed,ast2400-vic.txt    | 24 ++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
> new file mode 100644
> index 000000000000..10ed0c20ee6f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
> @@ -0,0 +1,24 @@
> +Aspeed Vectored Interrupt Controller
> +
> +These bindings are for the Aspeed AST2400 interrupt controller register layout.
> +The SoC has an legacy register layout, but this driver does not support that
> +mode of operation.
> +
> +Required properties:
> +
> +- compatible : should be "aspeed,ast2400-vic".
> +
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source. The value shall be 1.
> +- valid-sources : bitmask of valid irq sources

Generally we steer clear of this kind of bitmap encoding in DT.

Is this actually necessary? What does htis gain us?

Why can we not just register with the full set of possible interrupts?

Thanks,
Mark.

> +
> +Example:
> +
> + vic: interrupt-controller {
> +      compatible = "aspeed,ast2400-new-vic";
> +      interrupt-controller;
> +      #interrupt-cells = <1>;
> +      valid-sources = < 0xffffffff 0x0007ffff>;
> +      reg = <0x1e6c0080 0x80>;
> + };
> -- 
> 2.8.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


From tony at atomide.com  Mon May  9 08:21:38 2016
From: tony at atomide.com (Tony Lindgren)
Date: Mon, 9 May 2016 08:21:38 -0700
Subject: NFSroot hangs with bad unlock balance in Linux next
In-Reply-To: <20160509151219.GF5995@atomide.com>
References: <20160505220344.GE5995@atomide.com>
 <20160508141629.GF2694@ZenIV.linux.org.uk>
 <20160509073235.GI2694@ZenIV.linux.org.uk>
 <CANn89iK5H-SokYE1r+OO3sPmQ1vpGqYGbE4x1QLn44wdyvH0cw@mail.gmail.com>
 <20160509151219.GF5995@atomide.com>
Message-ID: <20160509152138.GG5995@atomide.com>

* Tony Lindgren <tony at atomide.com> [160509 08:15]:
> * Eric Dumazet <edumazet at google.com> [160509 07:16]:
> > On Mon, May 9, 2016 at 12:32 AM, Al Viro <viro at zeniv.linux.org.uk> wrote:
> > > On Sun, May 08, 2016 at 03:16:29PM +0100, Al Viro wrote:
> > >
> > >> Very strange.  We grab that rwsem at the entry into nfs_call_unlink()
> > >> and then either release it there and return or call nfs_do_call_unlink().
> > >> Which arranges for eventual call of nfs_async_unlink_release() (via
> > >> ->rpc_release); nfs_async_unlink_release() releases the rwsem.  Nobody else
> > >> releases it (on the read side, that is).
> > >>
> > >> The only kinda-sorta possibility I see here is that the inode we are
> > >> unlocking in that nfs_async_unlink_release() is not the one we'd locked
> > >> in nfs_call_unlink() that has lead to it.  That really shouldn't happen,
> > >> though...  Just to verify whether that's what we are hitting, could you
> > >> try to reproduce that thing with the patch below on top of -next and see
> > >> if it triggers any of those WARN_ON?
> 
> Thanks no warnings with that patch though.
> 
> > > D'oh...  Lockdep warnings are easy to trigger (and, AFAICS, bogus).
> > > up_read/down_read in fs/nfs/unlink.c should be replaced with
> > > up_read_non_owner/down_read_non_owner, lest the lockdep gets confused.
> > > Hangs are different - I've no idea what's triggering those.  I've seen
> > > something similar on that -next, but not on work.lookups.
> > >
> > > The joy of bisecting -next...  <a couple of hours later>
> > > 9317bb69824ec8d078b0b786b6971aedb0af3d4f is the first bad commit
> > > commit 9317bb69824ec8d078b0b786b6971aedb0af3d4f
> > > Author: Eric Dumazet <edumazet at google.com>
> > > Date:   Mon Apr 25 10:39:32 2016 -0700
> > >
> > >     net: SOCKWQ_ASYNC_NOSPACE optimizations
> > >
> > > Reverting changes to sk_set_bit/sk_clear_bit gets rid of the hangs.  Plain
> > > revert gives a conflict, since there had been additional change in
> > > "net: SOCKWQ_ASYNC_WAITDATA optimizations"; removing both fixed the hangs.
> > >
> > > Note that hangs appear without any fs/nfs/unlink.c modifications being
> > > there.  When the hang happens it affects NFS traffic; ssh session still
> > > works fine until it steps on a filesystem operation on NFS (i.e. you
> > > can use builtins, access procfs, etc.)
> > 
> > Yeah, the issue was reported last week (
> > http://www.spinics.net/lists/netdev/msg375777.html ),
> > and I could not convince myself to add a new sock flag,  like
> > SOCK_FASYNC_STICKY.
> > 
> > (Just in case NFS would ever call sock_fasync() with an empty
> > fasync_list, and SOCK_FASYNC would be cleared again.
> 
> Yeah applying the test patch from the url above makes things work
> for me again.

Looks like with both patches applied I still also get this eventually:

=====================================
[ BUG: bad unlock balance detected! ]
4.6.0-rc7-next-20160509+ #1264 Not tainted
-------------------------------------
kworker/0:1/18 is trying to release lock (&nfsi->rmdir_sem) at:
[<c03a894c>] nfs_async_unlink_release+0x3c/0xc0
but there are no more locks to release!

               other info that might help us debug this:
2 locks held by kworker/0:1/18:
 #0:  ("nfsiod"){.+.+..}, at: [<c015473c>] process_one_work+0x120/0x6bc
 #1:  ((&task->u.tk_work)#2){+.+...}, at: [<c015473c>] process_one_work+0x120/0x6bc

               stack backtrace:
CPU: 0 PID: 18 Comm: kworker/0:1 Not tainted 4.6.0-rc7-next-20160509+ #1264
Hardware name: Generic OMAP5 (Flattened Device Tree)
Workqueue: nfsiod rpc_async_release
[<c0110318>] (unwind_backtrace) from [<c010c3bc>] (show_stack+0x10/0x14)
[<c010c3bc>] (show_stack) from [<c0481da8>] (dump_stack+0xb0/0xe4)
[<c0481da8>] (dump_stack) from [<c018d090>] (print_unlock_imbalance_bug+0xb0/0xe0)
[<c018d090>] (print_unlock_imbalance_bug) from [<c0190e9c>] (lock_release+0x2ec/0x4c0)
[<c0190e9c>] (lock_release) from [<c018a4b8>] (up_read+0x18/0x58)
[<c018a4b8>] (up_read) from [<c03a894c>] (nfs_async_unlink_release+0x3c/0xc0)
[<c03a894c>] (nfs_async_unlink_release) from [<c07860e0>] (rpc_free_task+0x24/0x44)
[<c07860e0>] (rpc_free_task) from [<c0154804>] (process_one_work+0x1e8/0x6bc)
[<c0154804>] (process_one_work) from [<c0154e1c>] (worker_thread+0x144/0x4e8)
[<c0154e1c>] (worker_thread) from [<c015acd4>] (kthread+0xdc/0xf8)
[<c015acd4>] (kthread) from [<c01078f0>] (ret_from_fork+0x14/0x24)

After the warning, NFSroot keeps working with Eric's patch.

Regards,

Tony


From Tirumalesh.Chalamarla at cavium.com  Mon May  9 08:23:43 2016
From: Tirumalesh.Chalamarla at cavium.com (Chalamarla, Tirumalesh)
Date: Mon, 9 May 2016 15:23:43 +0000
Subject: [PATCH v9 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part
 2/3: msi changes
In-Reply-To: <573040D6.9050803@linaro.org>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
 <9C17BA6B-7304-47CA-A287-77FB41D96AD3@caviumnetworks.com>
 <573040D6.9050803@linaro.org>
Message-ID: <50F1DA1B-3760-474F-A401-43AA26A5F6B6@caviumnetworks.com>






On 5/9/16, 12:48 AM, "Eric Auger" <eric.auger at linaro.org> wrote:

>Hi Chalarmala,
>On 05/05/2016 07:44 PM, Chalamarla, Tirumalesh wrote:
>> Hi Eric,
>> 
>> Does this series supports gicv3-its emulation?
>> Do we have a tree with all the dependent patches
>GICv3 ITS emulation support comes with:
>[PATCH v4 00/12] KVM: arm64: GICv3 ITS emulation
>http://permalink.gmane.org/gmane.comp.emulators.kvm.arm.devel/5738
>
>My series just allows PCI device MSI transactions to reach the host MSI
>frame through the SMMU. Only host GICv2m has been tested at the moment
>with a guest exposed with a GICv2m too.


I wanted to test this series on Cavium Thunder, but the only mode supported is Gicv3 with ITS, is there a chance 
That I get a tree with all the dependencies?
>
>Best Regards
>
>Eric
>
>
>> 
>> 
>> 
>> 
>> 
>> Thanks,
>> Tirumalesh. 
>> On 5/4/16, 8:18 AM, "linux-arm-kernel on behalf of Eric Auger" <linux-arm-kernel-bounces at lists.infradead.org on behalf of eric.auger at linaro.org> wrote:
>> 
>>> This series implements the MSI address mapping/unmapping in the MSI layer.
>>> IOMMU binding happens on pci_enable_msi since this function can sleep and
>>> return errors. On msi_domain_set_affinity, msi_domain_(de)activate, which
>>> are not allowed to sleep, we simply look for the already existing binding.
>>>
>>> A new MSI domain info flag value is introduced to report whether the msi
>>> domain implements IRQ remapping. GIC v3 ITS is the first MSI controller
>>> advertising it. This flag value will be used by VFIO subsystem to
>>> determine whether MSI forwarding is safe.
>>>
>>> More details & context can be found at:
>>> http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/
>>>
>>> Best Regards
>>>
>>> Eric
>>>
>>> Applies on top of PART 1/3. Also depends on
>>> [PATCH 1/3] iommu: Add MMIO mapping type,
>>> http://comments.gmane.org/gmane.linux.kernel.iommu/12869
>>>
>>> Git: complete series available at
>>> https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc6-pcie-passthrough-v9-msi-v9
>>>
>>> This branch contains all parts in v9.
>>>
>>> History:
>>>
>>> v8 -> v9:
>>> - use a union in irq_chip_msi_doorbell_info + boolean telling whether the
>>>  doorbell is percpu
>>> - decouple irq_data parsing from the actual mapping/unmapping in
>>>  msi_handle_doorbell_mappings
>>> - fix misc style issues
>>>
>>> v7 -> v8:
>>> take into account Marc's comments:
>>> - use iommu_msi_msg_pa_to_va with new proto
>>> - change in irq_chip_msi_doorbell_info struct definition:
>>>  prot and size became shared between all doorbells and phys_addr_t __percpu
>>> - cleanups in v2m irqchip
>>> - eventually did not touch MSI_FLAG_IRQ_REMAPPING naming
>>> - On msi_handle_doorbell_mappings, stop on the first irqchip where doorbells
>>>  can be found
>>> - fix resource deallocation on mapping failure in msi_domain_alloc_irqs
>>>
>>> v6 -> v7:
>>> - do alloc/map handling on pci_enable_msi and search on msi_(de)domain_activate
>>> - add msi_doorbell_info callback in irq-chip to retrieve the characteristics
>>>  of doorbells
>>>
>>> RFC v5 -> patch v6:
>>> - split to ease the review process
>>> - rebase on default iommu domain code (irq_data_to_msi_mapping_domain
>>>  checks IOMMU_DOMAIN_DMA type)
>>> - fix unmap sequence on msi_domain_set_affinity (reported by Marc):
>>>  unmap the previous doorbell when the new one has been mapped & written to
>>>  the device, ie. irq_chip_write_msi_msg.
>>> - "msi: msi_compose wrapper removed" following change above
>>> - add size parameter to iommu_get_reserved_iova API following Marc's request
>>>
>>> RFC v4 -> RFC v5:
>>> - take into account Thomas' comments on MSI related patches
>>>  - split "msi: IOMMU map the doorbell address when needed"
>>>  - increase readability and add comments
>>>  - fix style issues
>>> - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
>>> - platform ITS now advertises IOMMU_CAP_INTR_REMAP
>>> - fix compilation issue with CONFIG_IOMMU API unset
>>> - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING
>>>
>>> RFC v3 -> v4:
>>> - Move doorbell mapping/unmapping in msi.c
>>> - fix ref count issue on set_affinity: in case of a change in the address
>>>  the previous address is decremented
>>> - doorbell map/unmap now is done on msi composition. Should allow the use
>>>  case for platform MSI controllers
>>> - create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
>>>  to reserved IOVA management (looking like dma-iommu glue)
>>> - series reordering to ease the review:
>>>  - first part is related to IOMMU
>>>  - second related to MSI sub-system
>>>  - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
>>> - expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
>>>  [this partially addresses Marc's comments on iommu_get/put_single_reserved
>>>   size/alignment problematic - which I did not ignore - but I don't know
>>>   how much I can do at the moment]
>>>
>>> RFC v2 -> RFC v3:
>>> - should fix wrong handling of some CONFIG combinations:
>>>  CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
>>> - fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)
>>>
>>> PATCH v1 -> RFC v2:
>>> - reverted to RFC since it looks more reasonable ;-) the code is split
>>>  between VFIO, IOMMU, MSI controller and I am not sure I did the right
>>>  choices. Also API need to be further discussed.
>>> - iova API usage in arm-smmu.c.
>>> - MSI controller natively programs the MSI addr with either the PA or IOVA.
>>>  This is not done anymore in vfio-pci driver as suggested by Alex.
>>> - check irq remapping capability of the group
>>>
>>> RFC v1 [2] -> PATCH v1:
>>> - use the existing dma map/unmap ioctl interface with a flag to register a
>>>  reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
>>> - a single reserved IOVA contiguous region now is allowed
>>> - use of an RB tree indexed by PA to store allocated reserved slots
>>> - use of a vfio_domain iova_domain to manage iova allocation within the
>>>  window provided by the userspace
>>> - vfio alloc_map/unmap_free take a vfio_group handle
>>> - vfio_group handle is cached in vfio_pci_device
>>> - add ref counting to bindings
>>> - user modality enabled at the end of the series
>>>
>>>
>>> Eric Auger (8):
>>>  genirq/msi: Add a new MSI_FLAG_IRQ_REMAPPING flag
>>>  irqchip/gic-v3-its: ITS advertises MSI_FLAG_IRQ_REMAPPING
>>>  genirq/msi: export msi_get_domain_info
>>>  genirq/msi: msi_compose wrapper
>>>  genirq/irq: introduce msi_doorbell_info
>>>  irqchip/gicv2m: implement msi_doorbell_info callback
>>>  genirq/msi: map/unmap the MSI doorbells on msi_domain_alloc/free_irqs
>>>  genirq/msi: use the MSI doorbell's IOVA when requested
>>>
>>> drivers/irqchip/irq-gic-v2m.c                 |  16 +++
>>> drivers/irqchip/irq-gic-v3-its-pci-msi.c      |   3 +-
>>> drivers/irqchip/irq-gic-v3-its-platform-msi.c |   3 +-
>>> include/linux/irq.h                           |  15 ++-
>>> include/linux/msi.h                           |   2 +
>>> kernel/irq/msi.c                              | 136 +++++++++++++++++++++++---
>>> 6 files changed, 161 insertions(+), 14 deletions(-)
>>>
>>> -- 
>>> 1.9.1
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

From lee.jones at linaro.org  Mon May  9 08:24:44 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Mon, 9 May 2016 16:24:44 +0100
Subject: [PATCH] mfd: ab8500-debugfs: trivial fix of spelling mistake on
 "between"
In-Reply-To: <1461620545-29731-1-git-send-email-colin.king@canonical.com>
References: <1461620545-29731-1-git-send-email-colin.king@canonical.com>
Message-ID: <20160509152444.GB19473@dell>

On Mon, 25 Apr 2016, Colin King wrote:

> From: Colin Ian King <colin.king at canonical.com>
> 
> fix spelling mistake, beetween -> between
> 
> Signed-off-by: Colin Ian King <colin.king at canonical.com>
> ---
>  drivers/mfd/ab8500-debugfs.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks.

> diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
> index 69d9fff..0aecd7b 100644
> --- a/drivers/mfd/ab8500-debugfs.c
> +++ b/drivers/mfd/ab8500-debugfs.c
> @@ -2563,7 +2563,7 @@ static ssize_t ab8500_gpadc_trig_timer_write(struct file *file,
>  
>  	if (user_trig_timer & ~0xFF) {
>  		dev_err(dev,
> -			"debugfs error input: should be beetween 0 to 255\n");
> +			"debugfs error input: should be between 0 to 255\n");
>  		return -EINVAL;
>  	}
>  

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


From christoffer.dall at linaro.org  Mon May  9 08:33:10 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Mon, 9 May 2016 17:33:10 +0200
Subject: [PATCH] kvm: arm64: Enable hardware updates of the Access Flag
 for Stage 2 page tables
In-Reply-To: <1460566657-30221-1-git-send-email-catalin.marinas@arm.com>
References: <1460566657-30221-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <20160509153310.GA27623@cbox>

On Wed, Apr 13, 2016 at 05:57:37PM +0100, Catalin Marinas wrote:
> The ARMv8.1 architecture extensions introduce support for hardware
> updates of the access and dirty information in page table entries. With
> VTCR_EL2.HA enabled (bit 21), when the CPU accesses an IPA with the
> PTE_AF bit cleared in the stage 2 page table, instead of raising an
> Access Flag fault to EL2 the CPU sets the actual page table entry bit
> (10). To ensure that kernel modifications to the page table do not
> inadvertently revert a bit set by hardware updates, certain Stage 2
> software pte/pmd operations must be performed atomically.
> 
> The main user of the AF bit is the kvm_age_hva() mechanism. The
> kvm_age_hva_handler() function performs a "test and clear young" action
> on the pte/pmd. This needs to be atomic in respect of automatic hardware
> updates of the AF bit. Since the AF bit is in the same position for both
> Stage 1 and Stage 2, the patch reuses the existing
> ptep_test_and_clear_young() functionality if
> __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG is defined. Otherwise, the
> existing pte_young/pte_mkold mechanism is preserved.
> 
> The kvm_set_s2pte_readonly() (and the corresponding pmd equivalent) have
> to perform atomic modifications in order to avoid a race with updates of
> the AF bit. The arm64 implementation has been re-written using
> exclusives.
> 
> Currently, kvm_set_s2pte_writable() (and pmd equivalent) take a pointer
> argument and modify the pte/pmd in place. However, these functions are
> only used on local variables rather than actual page table entries, so
> it makes more sense to follow the pte_mkwrite() approach for stage 1
> attributes. The change to kvm_s2pte_mkwrite() makes it clear that these
> functions do not modify the actual page table entries.

so if one CPU takes a permission fault and is in the process of updating
the page table, what prevents another CPU from setting the access flag
(on a read, done by HW) on that entry between us reading the old pte and
replacing it with the new pte?

Don't we loose the AF information in that case too?

> 
> The (pte|pmd)_mkyoung() uses on Stage 2 entries (setting the AF bit
> explicitly) do not need to be modified since hardware updates of the
> dirty status are not supported by KVM, so there is no possibility of
> losing such information.
> 
> Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Christoffer Dall <christoffer.dall at linaro.org>
> Cc: Marc Zyngier <marc.zyngier at arm.com>
> Cc: Paolo Bonzini <pbonzini at redhat.com>
> ---
> 
> After some digging through the KVM code, I concluded that hardware DBM
> (dirty bit management) support is not feasible for Stage 2. A potential
> user would be dirty logging but this requires a different bitmap exposed
> to Qemu and, to avoid races, the stage 2 mappings need to be mapped
> read-only on clean, writable on fault. This assumption simplifies the
> hardware Stage 2 AF support.
> 
> Tested on a model with handle_access_fault() no longer being called when
> the hardware AF is present and enabled. It needs swap enabling and light
> memory pressure to trigger the page aging.
> 
>  arch/arm/include/asm/kvm_mmu.h   | 10 +++++----
>  arch/arm/kvm/mmu.c               | 46 +++++++++++++++++++++++++---------------
>  arch/arm64/include/asm/kvm_arm.h |  2 ++
>  arch/arm64/include/asm/kvm_mmu.h | 27 +++++++++++++++++------
>  arch/arm64/include/asm/pgtable.h | 13 ++++++++----
>  arch/arm64/kvm/hyp/s2-setup.c    |  8 +++++++
>  6 files changed, 74 insertions(+), 32 deletions(-)
> 
> diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
> index da44be9db4fa..bff1ca42a97e 100644
> --- a/arch/arm/include/asm/kvm_mmu.h
> +++ b/arch/arm/include/asm/kvm_mmu.h
> @@ -105,14 +105,16 @@ static inline void kvm_clean_pte(pte_t *pte)
>  	clean_pte_table(pte);
>  }
>  
> -static inline void kvm_set_s2pte_writable(pte_t *pte)
> +static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
>  {
> -	pte_val(*pte) |= L_PTE_S2_RDWR;
> +	pte_val(pte) |= L_PTE_S2_RDWR;
> +	return pte;
>  }
>  
> -static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
> +static inline pmd_t kvm_s2pmd_mkwrite(pmd_t pmd)
>  {
> -	pmd_val(*pmd) |= L_PMD_S2_RDWR;
> +	pmd_val(pmd) |= L_PMD_S2_RDWR;
> +	return pmd;
>  }
>  
>  static inline void kvm_set_s2pte_readonly(pte_t *pte)
> diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
> index 58dbd5c439df..b6736ea85722 100644
> --- a/arch/arm/kvm/mmu.c
> +++ b/arch/arm/kvm/mmu.c
> @@ -955,6 +955,27 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
>  	return 0;
>  }
>  
> +#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
> +static int stage2_ptep_test_and_clear_young(pte_t *pte)
> +{
> +	if (pte_young(*pte)) {
> +		*pte = pte_mkold(*pte);
> +		return 1;
> +	}
> +	return 0;
> +}
> +#else
> +static int stage2_ptep_test_and_clear_young(pte_t *pte)
> +{
> +	return __ptep_test_and_clear_young(pte);
> +}
> +#endif
> +
> +static int stage2_pmdp_test_and_clear_young(pmd_t *pmd)
> +{
> +	return stage2_ptep_test_and_clear_young((pte_t *)pmd);
> +}
> +
>  /**
>   * kvm_phys_addr_ioremap - map a device range to guest IPA
>   *
> @@ -978,7 +999,7 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
>  		pte_t pte = pfn_pte(pfn, PAGE_S2_DEVICE);
>  
>  		if (writable)
> -			kvm_set_s2pte_writable(&pte);
> +			pte = kvm_s2pte_mkwrite(pte);
>  
>  		ret = mmu_topup_memory_cache(&cache, KVM_MMU_CACHE_MIN_PAGES,
>  						KVM_NR_MEM_OBJS);
> @@ -1320,7 +1341,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>  		pmd_t new_pmd = pfn_pmd(pfn, mem_type);
>  		new_pmd = pmd_mkhuge(new_pmd);
>  		if (writable) {
> -			kvm_set_s2pmd_writable(&new_pmd);
> +			new_pmd = kvm_s2pmd_mkwrite(new_pmd);
>  			kvm_set_pfn_dirty(pfn);
>  		}
>  		coherent_cache_guest_page(vcpu, pfn, PMD_SIZE, fault_ipa_uncached);
> @@ -1329,7 +1350,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>  		pte_t new_pte = pfn_pte(pfn, mem_type);
>  
>  		if (writable) {
> -			kvm_set_s2pte_writable(&new_pte);
> +			new_pte = kvm_s2pte_mkwrite(new_pte);
>  			kvm_set_pfn_dirty(pfn);
>  			mark_page_dirty(kvm, gfn);
>  		}
> @@ -1348,6 +1369,8 @@ out_unlock:
>   * Resolve the access fault by making the page young again.
>   * Note that because the faulting entry is guaranteed not to be
>   * cached in the TLB, we don't need to invalidate anything.
> + * Only the HW Access Flag updates are supported for Stage 2 (no DBM),
> + * so there is no need for atomic (pte|pmd)_mkyoung operations.
>   */
>  static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
>  {
> @@ -1588,25 +1611,14 @@ static int kvm_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
>  	if (!pmd || pmd_none(*pmd))	/* Nothing there */
>  		return 0;
>  
> -	if (kvm_pmd_huge(*pmd)) {	/* THP, HugeTLB */
> -		if (pmd_young(*pmd)) {
> -			*pmd = pmd_mkold(*pmd);
> -			return 1;
> -		}
> -
> -		return 0;
> -	}
> +	if (kvm_pmd_huge(*pmd))		/* THP, HugeTLB */
> +		return stage2_pmdp_test_and_clear_young(pmd);
>  
>  	pte = pte_offset_kernel(pmd, gpa);
>  	if (pte_none(*pte))
>  		return 0;
>  
> -	if (pte_young(*pte)) {
> -		*pte = pte_mkold(*pte);	/* Just a page... */
> -		return 1;
> -	}
> -
> -	return 0;
> +	return stage2_ptep_test_and_clear_young(pte);
>  }
>  
>  static int kvm_test_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
> diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
> index 4150fd8bae01..bbed53c2735a 100644
> --- a/arch/arm64/include/asm/kvm_arm.h
> +++ b/arch/arm64/include/asm/kvm_arm.h
> @@ -110,6 +110,8 @@
>  
>  /* VTCR_EL2 Registers bits */
>  #define VTCR_EL2_RES1		(1 << 31)
> +#define VTCR_EL2_HD		(1 << 22)
> +#define VTCR_EL2_HA		(1 << 21)
>  #define VTCR_EL2_PS_MASK	(7 << 16)
>  #define VTCR_EL2_TG0_MASK	(1 << 14)
>  #define VTCR_EL2_TG0_4K		(0 << 14)
> diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
> index 22732a5e3119..28bdf9ddaa0c 100644
> --- a/arch/arm64/include/asm/kvm_mmu.h
> +++ b/arch/arm64/include/asm/kvm_mmu.h
> @@ -121,19 +121,32 @@ static inline void kvm_clean_pmd_entry(pmd_t *pmd) {}
>  static inline void kvm_clean_pte(pte_t *pte) {}
>  static inline void kvm_clean_pte_entry(pte_t *pte) {}
>  
> -static inline void kvm_set_s2pte_writable(pte_t *pte)
> +static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
>  {
> -	pte_val(*pte) |= PTE_S2_RDWR;
> +	pte_val(pte) |= PTE_S2_RDWR;
> +	return pte;
>  }
>  
> -static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
> +static inline pmd_t kvm_s2pmd_mkwrite(pmd_t pmd)
>  {
> -	pmd_val(*pmd) |= PMD_S2_RDWR;
> +	pmd_val(pmd) |= PMD_S2_RDWR;
> +	return pmd;
>  }
>  
>  static inline void kvm_set_s2pte_readonly(pte_t *pte)
>  {
> -	pte_val(*pte) = (pte_val(*pte) & ~PTE_S2_RDWR) | PTE_S2_RDONLY;
> +	pteval_t pteval;
> +	unsigned long tmp;
> +
> +	asm volatile("//	kvm_set_s2pte_readonly\n"
> +	"	prfm	pstl1strm, %2\n"
> +	"1:	ldxr	%0, %2\n"
> +	"	and	%0, %0, %3		// clear PTE_S2_RDWR\n"
> +	"	orr	%0, %0, %4		// set PTE_S2_RDONLY\n"
> +	"	stxr	%w1, %0, %2\n"
> +	"	cbnz	%w1, 1b\n"
> +	: "=&r" (pteval), "=&r" (tmp), "+Q" (pte_val(*pte))

so the +Q means "pass the memory address of the value and by the way the
content, not the address itself, can be updated by the assembly code" ?

> +	: "L" (~PTE_S2_RDWR), "L" (PTE_S2_RDONLY));
>  }
>  
>  static inline bool kvm_s2pte_readonly(pte_t *pte)
> @@ -143,12 +156,12 @@ static inline bool kvm_s2pte_readonly(pte_t *pte)
>  
>  static inline void kvm_set_s2pmd_readonly(pmd_t *pmd)
>  {
> -	pmd_val(*pmd) = (pmd_val(*pmd) & ~PMD_S2_RDWR) | PMD_S2_RDONLY;
> +	kvm_set_s2pte_readonly((pte_t *)pmd);
>  }
>  
>  static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
>  {
> -	return (pmd_val(*pmd) & PMD_S2_RDWR) == PMD_S2_RDONLY;
> +	return kvm_s2pte_readonly((pte_t *)pmd);
>  }
>  
>  
> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
> index 989fef16d461..8d29e6eb33f7 100644
> --- a/arch/arm64/include/asm/pgtable.h
> +++ b/arch/arm64/include/asm/pgtable.h
> @@ -530,14 +530,12 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
>   * Atomic pte/pmd modifications.
>   */
>  #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
> -static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
> -					    unsigned long address,
> -					    pte_t *ptep)
> +static inline int __ptep_test_and_clear_young(pte_t *ptep)
>  {
>  	pteval_t pteval;
>  	unsigned int tmp, res;
>  
> -	asm volatile("//	ptep_test_and_clear_young\n"
> +	asm volatile("//	__ptep_test_and_clear_young\n"
>  	"	prfm	pstl1strm, %2\n"
>  	"1:	ldxr	%0, %2\n"
>  	"	ubfx	%w3, %w0, %5, #1	// extract PTE_AF (young)\n"
> @@ -550,6 +548,13 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
>  	return res;
>  }
>  
> +static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
> +					    unsigned long address,
> +					    pte_t *ptep)
> +{
> +	return __ptep_test_and_clear_young(ptep);
> +}
> +
>  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
>  #define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
>  static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
> diff --git a/arch/arm64/kvm/hyp/s2-setup.c b/arch/arm64/kvm/hyp/s2-setup.c
> index 5a9f3bf542b0..110267af0b83 100644
> --- a/arch/arm64/kvm/hyp/s2-setup.c
> +++ b/arch/arm64/kvm/hyp/s2-setup.c
> @@ -33,6 +33,14 @@ void __hyp_text __init_stage2_translation(void)
>  	val |= (read_sysreg(id_aa64mmfr0_el1) & 7) << 16;
>  
>  	/*
> +	 * Check the availability of Hardware Access Flag / Dirty Bit
> +	 * Management in ID_AA64MMFR1_EL1 and enable the feature in VTCR_EL2.
> +	 */
> +	tmp = (read_sysreg(id_aa64mmfr1_el1) >> ID_AA64MMFR1_HADBS_SHIFT) & 0xf;
> +	if (IS_ENABLED(CONFIG_ARM64_HW_AFDBM) && tmp)
> +		val |= VTCR_EL2_HA;
> +
> +	/*
>  	 * Read the VMIDBits bits from ID_AA64MMFR1_EL1 and set the VS
>  	 * bit in VTCR_EL2.
>  	 */


From viro at ZenIV.linux.org.uk  Mon May  9 08:39:33 2016
From: viro at ZenIV.linux.org.uk (Al Viro)
Date: Mon, 9 May 2016 16:39:33 +0100
Subject: NFSroot hangs with bad unlock balance in Linux next
In-Reply-To: <20160509152138.GG5995@atomide.com>
References: <20160505220344.GE5995@atomide.com>
 <20160508141629.GF2694@ZenIV.linux.org.uk>
 <20160509073235.GI2694@ZenIV.linux.org.uk>
 <CANn89iK5H-SokYE1r+OO3sPmQ1vpGqYGbE4x1QLn44wdyvH0cw@mail.gmail.com>
 <20160509151219.GF5995@atomide.com>
 <20160509152138.GG5995@atomide.com>
Message-ID: <20160509153932.GJ2694@ZenIV.linux.org.uk>

On Mon, May 09, 2016 at 08:21:38AM -0700, Tony Lindgren wrote:

> Looks like with both patches applied I still also get this eventually:
> 
> =====================================
> [ BUG: bad unlock balance detected! ]
> 4.6.0-rc7-next-20160509+ #1264 Not tainted
> -------------------------------------

Lockdep warnings are noise.  To make them STFU try the following incremental;
I'll fold it into #work.lookups and #for-next.  Note that it will do nothing
to hangs - those are completely unrelated and you need Eric's patch to deal
with them.

diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index d367b06..1868246 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -64,7 +64,7 @@ static void nfs_async_unlink_release(void *calldata)
 	struct dentry *dentry = data->dentry;
 	struct super_block *sb = dentry->d_sb;
 
-	up_read(&NFS_I(d_inode(dentry->d_parent))->rmdir_sem);
+	up_read_non_owner(&NFS_I(d_inode(dentry->d_parent))->rmdir_sem);
 	d_lookup_done(dentry);
 	nfs_free_unlinkdata(data);
 	dput(dentry);
@@ -117,10 +117,10 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
 	struct inode *dir = d_inode(dentry->d_parent);
 	struct dentry *alias;
 
-	down_read(&NFS_I(dir)->rmdir_sem);
+	down_read_non_owner(&NFS_I(dir)->rmdir_sem);
 	alias = d_alloc_parallel(dentry->d_parent, &data->args.name, &data->wq);
 	if (IS_ERR(alias)) {
-		up_read(&NFS_I(dir)->rmdir_sem);
+		up_read_non_owner(&NFS_I(dir)->rmdir_sem);
 		return 0;
 	}
 	if (!d_in_lookup(alias)) {
@@ -142,7 +142,7 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
 			ret = 0;
 		spin_unlock(&alias->d_lock);
 		dput(alias);
-		up_read(&NFS_I(dir)->rmdir_sem);
+		up_read_non_owner(&NFS_I(dir)->rmdir_sem);
 		/*
 		 * If we'd displaced old cached devname, free it.  At that
 		 * point dentry is definitely not a root, so we won't need


From marc.zyngier at arm.com  Mon May  9 08:47:20 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 9 May 2016 16:47:20 +0100
Subject: [PATCH v4 03/12] KVM: arm64: Introduce new MMIO region for the
 ITS base address
In-Reply-To: <651B7BE4-D1C9-44B2-84BE-19103C1D8CE0@caviumnetworks.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-4-git-send-email-andre.przywara@arm.com>
 <651B7BE4-D1C9-44B2-84BE-19103C1D8CE0@caviumnetworks.com>
Message-ID: <5730B108.5010009@arm.com>

On 05/05/16 19:08, Chalamarla, Tirumalesh wrote:
> 
> 
> 
> 
> 
> On 3/25/16, 7:14 PM, "kvmarm-bounces at lists.cs.columbia.edu on behalf of Andre Przywara" <kvmarm-bounces at lists.cs.columbia.edu on behalf of andre.przywara at arm.com> wrote:
> 
>> The ARM GICv3 ITS controller requires a separate register frame to
>> cover ITS specific registers. Add a new VGIC address type and store
>> the address in a field in the vgic_dist structure.
>> Provide a function to check whether userland has provided the address,
>> so ITS functionality can be guarded by that check.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Documentation/virtual/kvm/devices/arm-vgic.txt |  9 +++++++++
>> arch/arm64/include/uapi/asm/kvm.h              |  2 ++
>> include/kvm/vgic/vgic.h                        |  5 +++++
>> virt/kvm/arm/vgic/vgic.c                       | 10 ++++++++++
>> virt/kvm/arm/vgic/vgic_init.c                  |  1 +
>> virt/kvm/arm/vgic/vgic_kvm_device.c            |  7 +++++++
>> 6 files changed, 34 insertions(+)
>>
>> diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
>> index 59541d4..087e2d9 100644
>> --- a/Documentation/virtual/kvm/devices/arm-vgic.txt
>> +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
>> @@ -39,6 +39,15 @@ Groups:
>>       Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
>>       This address needs to be 64K aligned.
>>
>> +    KVM_VGIC_V3_ADDR_TYPE_ITS (rw, 64-bit)
>> +      Base address in the guest physical address space of the GICv3 ITS
>> +      control register frame. The ITS allows MSI(-X) interrupts to be
>> +      injected into guests. This extension is optional, if the kernel
>> +      does not support the ITS, the call returns -ENODEV.
>> +      This memory is solely for the guest to access the ITS control
>> +      registers and does not cover the ITS translation register.
>> +      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
>> +      This address needs to be 64K aligned and the region covers 64 KByte.
>>
>>   KVM_DEV_ARM_VGIC_GRP_DIST_REGS
>>   Attributes:
>> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
>> index f209ea1..c2b257d 100644
>> --- a/arch/arm64/include/uapi/asm/kvm.h
>> +++ b/arch/arm64/include/uapi/asm/kvm.h
>> @@ -87,9 +87,11 @@ struct kvm_regs {
>> /* Supported VGICv3 address types  */
>> #define KVM_VGIC_V3_ADDR_TYPE_DIST	2
>> #define KVM_VGIC_V3_ADDR_TYPE_REDIST	3
>> +#define KVM_VGIC_V3_ADDR_TYPE_ITS	4
>>
>> #define KVM_VGIC_V3_DIST_SIZE		SZ_64K
>> #define KVM_VGIC_V3_REDIST_SIZE		(2 * SZ_64K)
>> +#define KVM_VGIC_V3_ITS_SIZE		SZ_64K
>>
>> #define KVM_ARM_VCPU_POWER_OFF		0 /* CPU is started in OFF state */
>> #define KVM_ARM_VCPU_EL1_32BIT		1 /* CPU running a 32bit VM */
>> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
>> index 7c1d145..11344e6 100644
>> --- a/include/kvm/vgic/vgic.h
>> +++ b/include/kvm/vgic/vgic.h
>> @@ -135,6 +135,9 @@ struct vgic_dist {
>> 		gpa_t			vgic_redist_base;
>> 	};
>>
>> +	/* The base address of the ITS control register frame */
>> +	gpa_t			vgic_its_base;
>> +
>> 	/* distributor enabled */
>> 	u32			enabled;
>>
>> @@ -253,4 +256,6 @@ static inline int kvm_vgic_get_max_vcpus(void)
>> 	return kvm_vgic_global_state.max_gic_vcpus;
>> }
>>
>> +bool vgic_has_its(struct kvm *kvm);
>> +
>> #endif /* __ASM_ARM_KVM_VGIC_VGIC_H */
>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>> index 65395af..1de2478 100644
>> --- a/virt/kvm/arm/vgic/vgic.c
>> +++ b/virt/kvm/arm/vgic/vgic.c
>> @@ -612,3 +612,13 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, u32 intid)
>>
>> 	return map_is_active;
>> }
>> +
>> +bool vgic_has_its(struct kvm *kvm)
>> +{
>> +	struct vgic_dist *dist = &kvm->arch.vgic;
>> +
>> +	if (dist->vgic_model != KVM_DEV_TYPE_ARM_VGIC_V3)
>> +		return false;
>> +
>> +	return !IS_VGIC_ADDR_UNDEF(dist->vgic_its_base);
>> +}
>> diff --git a/virt/kvm/arm/vgic/vgic_init.c b/virt/kvm/arm/vgic/vgic_init.c
>> index ac655b5..2301e03 100644
>> --- a/virt/kvm/arm/vgic/vgic_init.c
>> +++ b/virt/kvm/arm/vgic/vgic_init.c
>> @@ -132,6 +132,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
>> 	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
>> 	kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
>> 	kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
>> +	kvm->arch.vgic.vgic_its_base = VGIC_ADDR_UNDEF;
>>
>> out_unlock:
>> 	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
>> diff --git a/virt/kvm/arm/vgic/vgic_kvm_device.c b/virt/kvm/arm/vgic/vgic_kvm_device.c
>> index 7f78a16..3ec2ac3 100644
>> --- a/virt/kvm/arm/vgic/vgic_kvm_device.c
>> +++ b/virt/kvm/arm/vgic/vgic_kvm_device.c
>> @@ -109,6 +109,12 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
>> 		block_size = KVM_VGIC_V3_REDIST_SIZE;
>> 		alignment = SZ_64K;
>> 		break;
>> +	case KVM_VGIC_V3_ADDR_TYPE_ITS:
>> +		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
>> +		addr_ptr = &vgic->vgic_its_base;
>> +		block_size = KVM_VGIC_V3_ITS_SIZE;
>> +		alignment = SZ_64K;
>> +		break;
> 
> Should there be a check based on number of vcpus? 

Why would the number of vcpus influence the size of the ITS?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From eric.auger at linaro.org  Mon May  9 08:47:06 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 9 May 2016 17:47:06 +0200
Subject: [PATCH V4 1/2] vfio, platform: add support for ACPI during probe
 and reset
In-Reply-To: <1462136872-17590-2-git-send-email-okaya@codeaurora.org>
References: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>
 <1462136872-17590-2-git-send-email-okaya@codeaurora.org>
Message-ID: <5730B0FA.1040303@linaro.org>

Hi Sinan,
On 05/01/2016 11:07 PM, Sinan Kaya wrote:
> The code is using the compatible DT string to associate a reset driver with
> the actual device itself. The compatible string does not exist on ACPI
> based systems. HID is the unique identifier for a device driver instead.
> 
> When ACPI is enabled, the change will query the presence of _RST method
> and will call it instead of querying an external reset driver.
> 
> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
> ---
>  drivers/vfio/platform/vfio_platform_common.c  | 176 +++++++++++++++++++++-----
>  drivers/vfio/platform/vfio_platform_private.h |   7 +-
>  2 files changed, 147 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
> index e65b142..528ec04 100644
> --- a/drivers/vfio/platform/vfio_platform_common.c
> +++ b/drivers/vfio/platform/vfio_platform_common.c
> @@ -13,6 +13,7 @@
>   */
>  
>  #include <linux/device.h>
> +#include <linux/acpi.h>
>  #include <linux/iommu.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
> @@ -41,7 +42,7 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
>  		if (!strcmp(iter->compat, compat) &&
>  			try_module_get(iter->owner)) {
>  			*module = iter->owner;
> -			reset_fn = iter->reset;
> +			reset_fn = iter->of_reset;
>  			break;
>  		}
>  	}
> @@ -49,20 +50,111 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
>  	return reset_fn;
>  }
>  
> -static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
> +
> +#ifdef CONFIG_ACPI
> +int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
> +			     struct device *dev)
>  {
> -	vdev->reset = vfio_platform_lookup_reset(vdev->compat,
> -						&vdev->reset_module);
> -	if (!vdev->reset) {
> -		request_module("vfio-reset:%s", vdev->compat);
> -		vdev->reset = vfio_platform_lookup_reset(vdev->compat,
> -							 &vdev->reset_module);
> +	struct acpi_device *adev = ACPI_COMPANION(dev);
> +
> +	if (acpi_disabled)
> +		return -ENODEV;
> +
> +	if (!adev)
> +		return -ENODEV;
> +
> +	vdev->acpihid = acpi_device_hid(adev);
> +	if (!vdev->acpihid) {
> +		pr_err("VFIO: cannot find ACPI HID for %s\n",
> +		       vdev->name);
> +		return -ENODEV;
>  	}
> +	return 0;
> +}
> +
> +static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
> +{
> +	struct device *dev = vdev->device;
> +	acpi_handle handle = ACPI_HANDLE(dev);
> +	acpi_status acpi_ret;
> +	unsigned long long val;
> +
> +	acpi_ret = acpi_evaluate_integer(handle, "_RST", NULL, &val);
> +	if (ACPI_FAILURE(acpi_ret))
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
> +{
> +	struct device *dev = vdev->device;
> +	acpi_handle handle = ACPI_HANDLE(dev);
> +
> +	if (acpi_has_method(handle, "_RST"))
> +		return 0;
Can't you directly return acpi_has_method(handle, "_RST"), hence return
a boolean?
> +
> +	return -EINVAL;
> +}
> +#else
> +int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
> +			     struct device *dev)
> +{
> +	return -EINVAL;
> +}
> +
> +static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
> +{
> +	return -EINVAL;
> +}
> +
> +static int vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
> +{
> +	return -EINVAL;
> +}
> +#endif
> +
> +static int vfio_platform_has_reset(struct vfio_platform_device *vdev)
> +{
return a boolean?
> +	if (vdev->acpihid)
> +		return vfio_platform_acpi_has_reset(vdev);
> +
> +	if (vdev->of_reset)
> +		return 0;
> +
> +	return -EINVAL;
> +}
> +
> +static int vfio_platform_get_reset(struct vfio_platform_device *vdev)
> +{
> +	int rc;
> +
> +	if (vdev->acpihid)
> +		return vfio_platform_acpi_has_reset(vdev);
> +
> +	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
> +						    &vdev->reset_module);
> +	if (vdev->of_reset)
> +		return 0;
> +
> +	rc = request_module("vfio-reset:%s", vdev->compat);
> +	if (rc)
> +		return rc;
> +
> +	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
> +						    &vdev->reset_module);
> +	if (vdev->of_reset)
> +		return 0;
> +
> +	return -EINVAL;
>  }
>  
>  static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
>  {
> -	if (vdev->reset)
> +	if (vdev->acpihid)
> +		return;
> +
> +	if (vdev->of_reset)
>  		module_put(vdev->reset_module);
>  }
>  
> @@ -134,6 +226,20 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
>  	kfree(vdev->regions);
>  }
>  
> +static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
> +{
> +	if (vdev->of_reset) {
> +		dev_info(vdev->device, "reset\n");
> +		vdev->of_reset(vdev);
return vdev->of_reset(vdev) to align with acpi reset behavior.
> +		return 0;
> +	} else if (vdev->acpihid) {
> +		return vfio_platform_acpi_call_reset(vdev);
I think it would make sense to have the same dev_info traces for dt and
acpi.
> +	}
> +
> +	dev_warn(vdev->device, "no reset function found!\n");
> +	return -EINVAL;
> +}
> +
>  static void vfio_platform_release(void *device_data)
>  {
>  	struct vfio_platform_device *vdev = device_data;
> @@ -141,12 +247,7 @@ static void vfio_platform_release(void *device_data)
>  	mutex_lock(&driver_lock);
>  
>  	if (!(--vdev->refcnt)) {
> -		if (vdev->reset) {
> -			dev_info(vdev->device, "reset\n");
> -			vdev->reset(vdev);
> -		} else {
> -			dev_warn(vdev->device, "no reset function found!\n");
> -		}
> +		vfio_platform_call_reset(vdev);
>  		vfio_platform_regions_cleanup(vdev);
>  		vfio_platform_irq_cleanup(vdev);
>  	}
> @@ -175,12 +276,9 @@ static int vfio_platform_open(void *device_data)
>  		if (ret)
>  			goto err_irq;
>  
> -		if (vdev->reset) {
> -			dev_info(vdev->device, "reset\n");
> -			vdev->reset(vdev);
> -		} else {
> -			dev_warn(vdev->device, "no reset function found!\n");
> -		}
> +		ret = vfio_platform_call_reset(vdev);
> +		if (ret)
> +			goto err_irq;
This change should be in next patch since if you fail finding a reset
function, you clean things up, mandating a reset function to exist.

Also in case the reset function fails you change the behavior which is
not detailed in the commit msg.
>  	}
>  
>  	vdev->refcnt++;
> @@ -213,7 +311,7 @@ static long vfio_platform_ioctl(void *device_data,
>  		if (info.argsz < minsz)
>  			return -EINVAL;
>  
> -		if (vdev->reset)
> +		if (!vfio_platform_has_reset(vdev))
>  			vdev->flags |= VFIO_DEVICE_FLAGS_RESET;
>  		info.flags = vdev->flags;
>  		info.num_regions = vdev->num_regions;
> @@ -312,10 +410,7 @@ static long vfio_platform_ioctl(void *device_data,
>  		return ret;
>  
>  	} else if (cmd == VFIO_DEVICE_RESET) {
> -		if (vdev->reset)
> -			return vdev->reset(vdev);
> -		else
> -			return -EINVAL;
> +		return vfio_platform_call_reset(vdev);
Here you also change the behavior: before, in case the dt reset failed
we returned an error. Now we return 0.

To me this patch would deserve to be split into 2 parts: ACPI probing
without reset and then ACPI reset. In case you change the behavior of
existing dt reset, please put that in a separate patch.

Best Regards

Eric
>  	}
>  
>  	return -ENOTTY;
> @@ -544,6 +639,21 @@ static const struct vfio_device_ops vfio_platform_ops = {
>  	.mmap		= vfio_platform_mmap,
>  };
>  
> +int vfio_platform_of_probe(struct vfio_platform_device *vdev,
> +			   struct device *dev)
> +{
> +	int ret;
> +
> +	ret = device_property_read_string(dev, "compatible",
> +					  &vdev->compat);
> +	if (ret) {
> +		pr_err("VFIO: cannot retrieve compat for %s\n",
> +			vdev->name);
> +		return ret;
> +	}
> +	return 0;
> +}
> +
>  int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>  			       struct device *dev)
>  {
> @@ -553,14 +663,14 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>  	if (!vdev)
>  		return -EINVAL;
>  
> -	ret = device_property_read_string(dev, "compatible", &vdev->compat);
> -	if (ret) {
> -		pr_err("VFIO: cannot retrieve compat for %s\n", vdev->name);
> -		return -EINVAL;
> -	}
> +	ret = vfio_platform_acpi_probe(vdev, dev);
> +	if (ret)
> +		ret = vfio_platform_of_probe(vdev, dev);
>  
> -	vdev->device = dev;
> +	if (ret)
> +		return ret;
>  
> +	vdev->device = dev;
>  	group = iommu_group_get(dev);
>  	if (!group) {
>  		pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
> @@ -611,7 +721,7 @@ void vfio_platform_unregister_reset(const char *compat,
>  
>  	mutex_lock(&driver_lock);
>  	list_for_each_entry_safe(iter, temp, &reset_list, link) {
> -		if (!strcmp(iter->compat, compat) && (iter->reset == fn)) {
> +		if (!strcmp(iter->compat, compat) && (iter->of_reset == fn)) {
>  			list_del(&iter->link);
>  			break;
>  		}
> diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
> index 42816dd..ba9e4f8 100644
> --- a/drivers/vfio/platform/vfio_platform_private.h
> +++ b/drivers/vfio/platform/vfio_platform_private.h
> @@ -58,6 +58,7 @@ struct vfio_platform_device {
>  	struct mutex			igate;
>  	struct module			*parent_module;
>  	const char			*compat;
> +	const char			*acpihid;
>  	struct module			*reset_module;
>  	struct device			*device;
>  
> @@ -71,7 +72,7 @@ struct vfio_platform_device {
>  	struct resource*
>  		(*get_resource)(struct vfio_platform_device *vdev, int i);
>  	int	(*get_irq)(struct vfio_platform_device *vdev, int i);
> -	int	(*reset)(struct vfio_platform_device *vdev);
> +	int	(*of_reset)(struct vfio_platform_device *vdev);
>  };
>  
>  typedef int (*vfio_platform_reset_fn_t)(struct vfio_platform_device *vdev);
> @@ -80,7 +81,7 @@ struct vfio_platform_reset_node {
>  	struct list_head link;
>  	char *compat;
>  	struct module *owner;
> -	vfio_platform_reset_fn_t reset;
> +	vfio_platform_reset_fn_t of_reset;
>  };
>  
>  extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
> @@ -103,7 +104,7 @@ extern void vfio_platform_unregister_reset(const char *compat,
>  static struct vfio_platform_reset_node __reset ## _node = {	\
>  	.owner = THIS_MODULE,					\
>  	.compat = __compat,					\
> -	.reset = __reset,					\
> +	.of_reset = __reset,					\
>  };								\
>  __vfio_platform_register_reset(&__reset ## _node)
>  
> 



From joro at 8bytes.org  Mon May  9 08:50:10 2016
From: joro at 8bytes.org (Joerg Roedel)
Date: Mon, 9 May 2016 17:50:10 +0200
Subject: [PATCH 0/5] Introduce per-domain page sizes
In-Reply-To: <5730AA4F.4040303@arm.com>
References: <cover.1460048991.git.robin.murphy@arm.com>
 <20160509112138.GB13275@8bytes.org> <57307863.1070706@arm.com>
 <20160509145157.GD13971@8bytes.org> <5730AA4F.4040303@arm.com>
Message-ID: <20160509155010.GE13971@8bytes.org>

On Mon, May 09, 2016 at 04:18:39PM +0100, Robin Murphy wrote:
> Bah, I saw last week's "Merge remote-tracking branch
> 'will/for-joerg/arm-smmu/updates' into HEAD" commit on that branch
> without spotting it was no longer up to date, sorry. Yes, it's
> probably safest if I rebase on top of your merge of everything else
> - I'll keep an eye out.

My tree is pushed now, you can rebase this one patch on the core branch
and resend.


Thanks,

	Joerg



From matthias.bgg at gmail.com  Mon May  9 09:06:12 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 9 May 2016 18:06:12 +0200
Subject: [PATCH v2] clocksource/arm_arch_timer: Force per-CPU interrupt to
 be level-triggered
In-Reply-To: <1462805488-21535-1-git-send-email-marc.zyngier@arm.com>
References: <1462805488-21535-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <5730B574.9060209@gmail.com>



On 09/05/16 16:51, Marc Zyngier wrote:
> The ARM architected timer produces level-triggered interrupts (this
> is mandated by the architecture). Unfortunately, most device-trees
> get this wrong, and expose an edge-triggered interrupt.
>
> Until now, this wasn't too much an issue, as the programming of the
> trigger would fail (the corresponding PPI cannot be reconfigured),
> and the kernel would be happy with this. But we're about to change
> this, and trust DT a lot if the driver doesn't provide its own
> trigger information. In that context, the timer breaks badly.
>
> While we do need to fix the DTs, there is also some userspace out
> there (kvmtool) that generates the same kind of broken DT on the
> fly, and that will completely break with newer kernels.
>
> As a safety measure, and to keep buggy software alive as well as
> buying us some time to fix DTs all over the place, let's check
> what trigger configuration has been given us by the firmware.
> If this is not a level configuration, then we know that the
> DT/ACPI configuration is bust, and we pick some defaults which
> won't be worse than the existing setup.
>
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>

Reviewed-by: Matthias Brugger <mbrugger at suse.com>

> ---
> - from v1: realised that there is no sane default, as we already have
>    diverging configurations. Instead, test for a level interrupt, and
>    force it to level low if current setting was edge. Also scream at the
>    unfortunate user.
>
>   drivers/clocksource/arm_arch_timer.c | 27 ++++++++++++++++++++++++---
>   1 file changed, 24 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> index 5152b38..be8cc6d 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -8,6 +8,9 @@
>    * it under the terms of the GNU General Public License version 2 as
>    * published by the Free Software Foundation.
>    */
> +
> +#define pr_fmt(fmt)	"arm_arch_timer: " fmt
> +
>   #include <linux/init.h>
>   #include <linux/kernel.h>
>   #include <linux/device.h>
> @@ -362,14 +365,32 @@ static bool arch_timer_has_nonsecure_ppi(void)
>   		arch_timer_ppi[PHYS_NONSECURE_PPI]);
>   }
>
> +static u32 check_ppi_trigger(int irq)
> +{
> +	u32 flags = irq_get_trigger_type(irq);
> +
> +	if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) {
> +		pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq);
> +		pr_warn("WARNING: Please fix your firmware\n");
> +		flags = IRQF_TRIGGER_LOW;
> +	}
> +
> +	return flags;
> +}
> +
>   static int arch_timer_setup(struct clock_event_device *clk)
>   {
> +	u32 flags;
> +
>   	__arch_timer_setup(ARCH_CP15_TIMER, clk);
>
> -	enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0);
> +	flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]);
> +	enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags);
>
> -	if (arch_timer_has_nonsecure_ppi())
> -		enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0);
> +	if (arch_timer_has_nonsecure_ppi()) {
> +		flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]);
> +		enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags);
> +	}
>
>   	arch_counter_set_user_access();
>   	if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM))
>


From robin.murphy at arm.com  Mon May  9 09:20:09 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Mon,  9 May 2016 17:20:09 +0100
Subject: [PATCH v2] iommu/arm-smmu: Use per-domain page sizes.
In-Reply-To: <ea520b8c72b5a72a1731bd35f6e3e50872fe6764.1460048991.git.robin.murphy@arm.com>
References: <ea520b8c72b5a72a1731bd35f6e3e50872fe6764.1460048991.git.robin.murphy@arm.com>
 <cover.1460048991.git.robin.murphy@arm.com>
Message-ID: <112fc0e5f9bbe08007778b8438b35025d8e876a4.1462810410.git.robin.murphy@arm.com>

Now that we can accurately reflect the context format we choose for each
domain, do that instead of imposing the global lowest-common-denominator
restriction and potentially ending up with nothing. We currently have a
strict 1:1 correspondence between domains and context banks, so we don't
need to entertain the possibility of multiple formats _within_ a domain.

Signed-off-by: Will Deacon <will.deacon at arm.com>
[rm: split from original patch, added SMMUv3]
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---

Changes from v1: Rebased onto iommu/core to accommodate SMMUv2 changes.

 drivers/iommu/arm-smmu-v3.c | 19 ++++++++++---------
 drivers/iommu/arm-smmu.c    | 27 +++++++++++++++------------
 2 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 4ff73ff64e49..ebab33e77d67 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -590,6 +590,7 @@ struct arm_smmu_device {
 
 	unsigned long			ias; /* IPA */
 	unsigned long			oas; /* PA */
+	unsigned long			pgsize_bitmap;
 
 #define ARM_SMMU_MAX_ASIDS		(1 << 16)
 	unsigned int			asid_bits;
@@ -1516,8 +1517,6 @@ static int arm_smmu_domain_finalise_s2(struct arm_smmu_domain *smmu_domain,
 	return 0;
 }
 
-static struct iommu_ops arm_smmu_ops;
-
 static int arm_smmu_domain_finalise(struct iommu_domain *domain)
 {
 	int ret;
@@ -1555,7 +1554,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
 	}
 
 	pgtbl_cfg = (struct io_pgtable_cfg) {
-		.pgsize_bitmap	= arm_smmu_ops.pgsize_bitmap,
+		.pgsize_bitmap	= smmu->pgsize_bitmap,
 		.ias		= ias,
 		.oas		= oas,
 		.tlb		= &arm_smmu_gather_ops,
@@ -1566,7 +1565,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
 	if (!pgtbl_ops)
 		return -ENOMEM;
 
-	arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
+	domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
 	smmu_domain->pgtbl_ops = pgtbl_ops;
 
 	ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg);
@@ -2410,7 +2409,6 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
 {
 	u32 reg;
 	bool coherent;
-	unsigned long pgsize_bitmap = 0;
 
 	/* IDR0 */
 	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
@@ -2541,13 +2539,16 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
 
 	/* Page sizes */
 	if (reg & IDR5_GRAN64K)
-		pgsize_bitmap |= SZ_64K | SZ_512M;
+		smmu->pgsize_bitmap |= SZ_64K | SZ_512M;
 	if (reg & IDR5_GRAN16K)
-		pgsize_bitmap |= SZ_16K | SZ_32M;
+		smmu->pgsize_bitmap |= SZ_16K | SZ_32M;
 	if (reg & IDR5_GRAN4K)
-		pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;
+		smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;
 
-	arm_smmu_ops.pgsize_bitmap &= pgsize_bitmap;
+	if (arm_smmu_ops.pgsize_bitmap == -1UL)
+		arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap;
+	else
+		arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap;
 
 	/* Output address size */
 	switch (reg & IDR5_OAS_MASK << IDR5_OAS_SHIFT) {
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 7cd4ad98904a..0360919a5737 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -351,6 +351,7 @@ struct arm_smmu_device {
 	unsigned long			va_size;
 	unsigned long			ipa_size;
 	unsigned long			pa_size;
+	unsigned long			pgsize_bitmap;
 
 	u32				num_global_irqs;
 	u32				num_context_irqs;
@@ -396,8 +397,6 @@ struct arm_smmu_domain {
 	struct iommu_domain		domain;
 };
 
-static struct iommu_ops arm_smmu_ops;
-
 static DEFINE_SPINLOCK(arm_smmu_devices_lock);
 static LIST_HEAD(arm_smmu_devices);
 
@@ -957,7 +956,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
 	}
 
 	pgtbl_cfg = (struct io_pgtable_cfg) {
-		.pgsize_bitmap	= arm_smmu_ops.pgsize_bitmap,
+		.pgsize_bitmap	= smmu->pgsize_bitmap,
 		.ias		= ias,
 		.oas		= oas,
 		.tlb		= &arm_smmu_gather_ops,
@@ -971,8 +970,8 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
 		goto out_clear_smmu;
 	}
 
-	/* Update our support page sizes to reflect the page table format */
-	arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
+	/* Update the domain's page sizes to reflect the page table format */
+	domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
 
 	/* Initialise the context bank with our page table cfg */
 	arm_smmu_init_context_bank(smmu_domain, &pgtbl_cfg);
@@ -1814,19 +1813,23 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
 	}
 
 	/* Now we've corralled the various formats, what'll it do? */
-	size = 0;
 	if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH32_S)
-		size |= SZ_4K | SZ_64K | SZ_1M | SZ_16M;
+		smmu->pgsize_bitmap |= SZ_4K | SZ_64K | SZ_1M | SZ_16M;
 	if (smmu->features &
 	    (ARM_SMMU_FEAT_FMT_AARCH32_L | ARM_SMMU_FEAT_FMT_AARCH64_4K))
-		size |= SZ_4K | SZ_2M | SZ_1G;
+		smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;
 	if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH64_16K)
-		size |= SZ_16K | SZ_32M;
+		smmu->pgsize_bitmap |= SZ_16K | SZ_32M;
 	if (smmu->features & ARM_SMMU_FEAT_FMT_AARCH64_64K)
-		size |= SZ_64K | SZ_512M;
+		smmu->pgsize_bitmap |= SZ_64K | SZ_512M;
+
+	if (arm_smmu_ops.pgsize_bitmap == -1UL)
+		arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap;
+	else
+		arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap;
+	dev_notice(smmu->dev, "\tSupported page sizes: 0x%08lx\n",
+		   smmu->pgsize_bitmap);
 
-	arm_smmu_ops.pgsize_bitmap &= size;
-	dev_notice(smmu->dev, "\tSupported page sizes: 0x%08lx\n", size);
 
 	if (smmu->features & ARM_SMMU_FEAT_TRANS_S1)
 		dev_notice(smmu->dev, "\tStage-1: %lu-bit VA -> %lu-bit IPA\n",
-- 
2.8.1.dirty



From dmitry.torokhov at gmail.com  Mon May  9 09:32:41 2016
From: dmitry.torokhov at gmail.com (Dmitry Torokhov)
Date: Mon, 9 May 2016 09:32:41 -0700
Subject: [PATCH v6 1/9] input: max8997-haptic: Fix NULL pointer dereference
In-Reply-To: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-1-git-send-email-k.kozlowski@samsung.com>
 <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
Message-ID: <20160509163241.GB15535@dtor-ws>

On Fri, May 06, 2016 at 09:21:21AM +0200, Krzysztof Kozlowski wrote:
> From: Marek Szyprowski <m.szyprowski at samsung.com>
> 
> NULL pointer derefence happens when booting with DTB because the
> platform data for haptic device is not set in supplied data from parent
> MFD device.
> 
> The MFD device creates only platform data (from Device Tree) for itself,
> not for haptic child.
> 
> Unable to handle kernel NULL pointer dereference at virtual address 0000009c
> pgd = c0004000
> 	[0000009c] *pgd=00000000
> 	Internal error: Oops: 5 [#1] PREEMPT SMP ARM
> 	(max8997_haptic_probe) from [<c03f9cec>] (platform_drv_probe+0x4c/0xb0)
> 	(platform_drv_probe) from [<c03f8440>] (driver_probe_device+0x214/0x2c0)
> 	(driver_probe_device) from [<c03f8598>] (__driver_attach+0xac/0xb0)
> 	(__driver_attach) from [<c03f67ac>] (bus_for_each_dev+0x68/0x9c)
> 	(bus_for_each_dev) from [<c03f7a38>] (bus_add_driver+0x1a0/0x218)
> 	(bus_add_driver) from [<c03f8db0>] (driver_register+0x78/0xf8)
> 	(driver_register) from [<c0101774>] (do_one_initcall+0x90/0x1d8)
> 	(do_one_initcall) from [<c0a00dbc>] (kernel_init_freeable+0x15c/0x1fc)
> 	(kernel_init_freeable) from [<c06bb5b4>] (kernel_init+0x8/0x114)
> 	(kernel_init) from [<c0107938>] (ret_from_fork+0x14/0x3c)
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
> Cc: <stable at vger.kernel.org>
> Fixes: 104594b01ce7 ("Input: add driver support for MAX8997-haptic")
> [k.kozlowski: Write commit message, add CC-stable]
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

Applied, thank you.

> ---
>  drivers/input/misc/max8997_haptic.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
> index a806ba3818f7..8d6326d7e7be 100644
> --- a/drivers/input/misc/max8997_haptic.c
> +++ b/drivers/input/misc/max8997_haptic.c
> @@ -255,12 +255,14 @@ static int max8997_haptic_probe(struct platform_device *pdev)
>  	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
>  	const struct max8997_platform_data *pdata =
>  					dev_get_platdata(iodev->dev);
> -	const struct max8997_haptic_platform_data *haptic_pdata =
> -					pdata->haptic_pdata;
> +	const struct max8997_haptic_platform_data *haptic_pdata = NULL;
>  	struct max8997_haptic *chip;
>  	struct input_dev *input_dev;
>  	int error;
>  
> +	if (pdata)
> +		haptic_pdata = pdata->haptic_pdata;
> +
>  	if (!haptic_pdata) {
>  		dev_err(&pdev->dev, "no haptic platform data\n");
>  		return -EINVAL;
> -- 
> 1.9.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Dmitry


From nicolas.ferre at atmel.com  Mon May  9 09:34:29 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Mon, 9 May 2016 18:34:29 +0200
Subject: [PATCH] ARM: dts: at91: sama5d2: use "atmel,
 sama5d3-nfc" compatible for nfc
In-Reply-To: <1462776680-5284-3-git-send-email-wenyou.yang@atmel.com>
References: <1462776680-5284-3-git-send-email-wenyou.yang@atmel.com>
Message-ID: <1462811669-10107-1-git-send-email-nicolas.ferre@atmel.com>

From: Wenyou Yang <wenyou.yang at atmel.com>

An error in documentation of the NAND Flash Controller (NFC) led to choose
another compatibility string for sama5d2 with an impact on the NAND flash
ready/busy information. It was producing the error message:

atmel_nand 80000000.nand: Time out to wait for interrupt: 0x08000000

and had an impact on performance.

So, switch back to the classical "atmel,sama5d3-nfc" compatibility string for
this SoC which gives the proper ready/busy bit information. The NAND flash
driver will be updated to remove the support for this different
implementation.

Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
[nicolas.ferre at atmel.com: change commit message]
Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
---
Wenyou, Romain,

I plan to send this patch for 4.6-rc as a fix tomorrow (my time). Can you
please tell me if it's okay on your side.
I revised the commit message just to justify the very late "fix" sending of
this patch...

Thanks for your help, bye.
  Nicolas.


 arch/arm/boot/dts/sama5d2.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 78996bdbd3df..9817090c1b73 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -280,7 +280,7 @@
 			status = "disabled";
 
 			nfc at c0000000 {
-				compatible = "atmel,sama5d4-nfc";
+				compatible = "atmel,sama5d3-nfc";
 				#address-cells = <1>;
 				#size-cells = <1>;
 				reg = < /* NFC Command Registers */
-- 
2.1.3



From javier at osg.samsung.com  Mon May  9 09:44:50 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 12:44:50 -0400
Subject: [PATCH] ARM: dts: exynos: Only Odroid XU3-family boards use DTSI
 with CPU thermal nodes
In-Reply-To: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>
References: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <d7e37f87-c794-f0ad-73d1-8e976c37471b@osg.samsung.com>

Hello Krzysztof,

On 05/09/2016 02:19 AM, Krzysztof Kozlowski wrote:
> Include the CPU thermal nodes directly in Odroid XU3-family common DTS
> because it is the only user of it. Keeping it in separate DTSI node does
> not bring benefits because:
> 1. It is not re-usable on other non-fan boards (fan is referenced),
> 2. It won't be re-used on future Odroid XU board because different
>    CPU cluster behavior.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

Agreed with both points and the patch looks good to me.

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From niklas.soderlund+renesas at ragnatech.se  Mon May  9 09:44:00 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Mon,  9 May 2016 18:44:00 +0200
Subject: [PATCHv6 1/8] dma-mapping: add {map,unmap}_resource to dma_map_ops
In-Reply-To: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462812247-3414-2-git-send-email-niklas.soderlund+renesas@ragnatech.se>

Add methods to handle mapping of device resources from a physical
address. This is needed for example to be able to map MMIO FIFO
registers to a IOMMU.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 include/linux/dma-mapping.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 0e4d3a6..8617fa1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -49,6 +49,12 @@ struct dma_map_ops {
 			 struct scatterlist *sg, int nents,
 			 enum dma_data_direction dir,
 			 struct dma_attrs *attrs);
+	dma_addr_t (*map_resource)(struct device *dev, phys_addr_t phys_addr,
+			       size_t size, enum dma_data_direction dir,
+			       struct dma_attrs *attrs);
+	void (*unmap_resource)(struct device *dev, dma_addr_t dma_handle,
+			   size_t size, enum dma_data_direction dir,
+			   struct dma_attrs *attrs);
 	void (*sync_single_for_cpu)(struct device *dev,
 				    dma_addr_t dma_handle, size_t size,
 				    enum dma_data_direction dir);
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Mon May  9 09:43:59 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Mon,  9 May 2016 18:43:59 +0200
Subject: [PATCHv6 0/8] dmaengine: rcar-dmac: add iommu support for slave
 transfers
Message-ID: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>

Hi,

This series tries to solve the problem with DMA with device registers
(MMIO registers) that are behind an IOMMU for the rcar-dmac driver. A
recent patch '9575632 (dmaengine: make slave address physical)'
clarifies that DMA slave address provided by clients is the physical
address. This puts the task of mapping the DMA slave address from a
phys_addr_t to a dma_addr_t on the DMA engine.

Without an IOMMU this is easy since the phys_addr_t and dma_addr_t are
the same and no special care is needed. However if you have a IOMMU you
need to map the DMA slave phys_addr_t to a dma_addr_t using something
like this.

This series is based on top of and requires the patches from Robin
Murphy in the tag 'arm/io-pgtable' from the iommu repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git

It's tested on a Koelsch with CONFIG_IPMMU_VMSA and by enabling the
ipmmu_ds node in r8a7791.dtsi. I verified operation by interacting with
/dev/mmcblk1 and the serial console which both are devices behind the
iommu.

Furthermore I have audited to the best of my ability all call paths
involved to make sure that the dma_addr_t obtained from
dma_map_resource() to is not used in a way where it would be expected
for the mapping to be RAM (have a struct page). Many thanks to Christoph
Hellwig and Laurent Pinchart for there input in this effort.

  * drivers/dma/sh/rcar-dmac.c
    Once the phys_addr_t is mapped to a dma_addr_t using
    dma_map_resource() it is only used to check that the transferee do not
    cross 4GB boundaries and then only directly written to HW registers.

  * drivers/iommu/iommu.c
    - iommu_map()
      Check that it's align to min page size or return -EINVAL then calls
      domain->ops->map()

  * drivers/iommu/ipmmu-vmsa.c
    - ipmmu_map()
      No logic only calls domain->ops->map()

  * drivers/iommu/io-pgtable-arm.c
    - arm_lpae_map()
      No logic only calls __arm_lpae_map()
    - __arm_lpae_map()
      No logic only calls arm_lpae_init_pte()
    - arm_lpae_init_pte()
      Used to get a pte:
        pte |= pfn_to_iopte(paddr >> data->pg_shift, data);

  * drivers/iommu/io-pgtable-arm-v7s.c
    - arm_v7s_map()
      No logic only calls __arm_v7s_map()
    - __arm_v7s_map()
      No logic only calls arm_v7s_init_pte()
    - arm_v7s_init_pte
      Used to get a pte:
        pte |= paddr & ARM_V7S_LVL_MASK(lvl);

  * ARM dma-mapping
    - dma_unmap_*
      Only valid unmap is dma_unmap_resource() all others are an invalid
      use case.
    - dma_sync_single_*
      Invalid use case, memory that is mapped is device memory
    - dma_common_mmap() and dma_mmap_attrs()
      Invalid use case
    - dma_common_get_sgtable() and dma_get_sgtable_attrs()
      Invalid use case, only for dma_alloc_* allocated memory,
    - dma_mapping_error()
      OK

While working on the dma-debug parts of this series I found an unrelated
issue with drivers/iommu/io-pgtable-arm.c and CONFIG_DMA_API_DEBUG on
the Koelsch. I tried to address this in the thread
https://lkml.org/lkml/2016/5/8/33 , however it turned out my solution
was not the correct one. I have not tried to address this further so
running this series with CONFIG_DMA_API_DEBUG will trigger this warning
but is unrelated to this work.

* Changes since v5
- Add dma-debug work which adds a new mapping type for the resource
  mapping which correctly can be translated to a physical address.
- Drop patches from Robin Murphy since they now are accepted in the
  iommu repository and base the series on that tree instead.
- Add a review tag from Laurent.

* Changes since v4
- Move the mapping from phys_addr_t to dma_addr_t from slave_config to the
  prepare calls. This way we know the direction of the mapping and don't have
  to use DMA_BIDIRECTIONAL. Thanks Vinod for suggesting this.
- To be clear that the data type for slave addresses are changed add a patch
  that only changes the data type to phys_addr_t.
- Fixed up commit messages.

* Changes since v3
- Folded in a fix from Robin to his patch.
- Added a check to make sure dma_map_resource can not be used to map RAM as
  pointed out by Robin. I use BUG_ON to enforce this. It might not be the best
  method but I saw no other good way since DMA_ERROR_CODE might not be defined
  on all platforms.
- Added comment about that DTS changes will disable 2 DMA channels due to a HW
  (?) but in the DMAC.
- Dropped the use of dma_attrs, no longer needed.
- Collected Acked-by and Reviewed-by from Laurent.
- Various indentation fix ups.

* Changes since v2
- Drop patch to add dma_{map,unmap}_page_attrs.
- Add dma_{map,unmap}_resource to handle the mapping without involving a
  'struct page'. Thanks Laurent and Robin for pointing this out.
- Use size instead of address to keep track of if a mapping exist or not
  since addr == 0 is valid. Thanks Laurent.
- Pick up patch from Robin with Laurents ack (hope it's OK for me to
  attach the ack?) to add IOMMU_MMIO.
- Fix bug in rcar_dmac_device_config where the error check where
  inverted.
- Use DMA_BIDIRECTIONAL in rcar_dmac_device_config since we at that
  point can't be sure what direction the mapping is going to be used.

* Changes since v1
- Add and use a dma_{map,unmap}_page_attrs to be able to map the page
  using attributes DMA_ATTR_NO_KERNEL_MAPPING and
  DMA_ATTR_SKIP_CPU_SYNC. Thanks Laurent.
- Drop check if dmac is part of a iommu group or not, let the DMA
  mapping api handle it.
- Move slave configuration data around in rcar-dmac to avoid code
  duplication.
- Fix build issue reported by 'kbuild test robot' regarding phys_to_page
  not availability on some configurations.
- Add DT information for r8a7791.

* Changes since RFC
- Switch to use the dma-mapping api instead of using the iommu_map()
  directly. Turns out the dma-mapper is much smarter then me...
- Dropped the patch to expose domain->ops->pgsize_bitmap from within the
  iommu api.
- Dropped the patch showing how I tested the RFC.

Niklas S?derlund (8):
  dma-mapping: add {map,unmap}_resource to dma_map_ops
  dma-debug: add support for resource mappings
  dma-mapping: add dma_{map,unmap}_resource
  arm: dma-mapping: add {map,unmap}_resource for iommu ops
  dmaengine: rcar-dmac: group slave configuration
  dmaengine: rcar-dmac: add iommu support for slave transfers
  ARM: dts: r8a7790: add iommus to dmac0 and dmac1
  ARM: dts: r8a7791: add iommus to dmac0 and dmac1

 Documentation/DMA-API.txt      |  22 ++++++--
 arch/arm/boot/dts/r8a7790.dtsi |  30 +++++++++++
 arch/arm/boot/dts/r8a7791.dtsi |  30 +++++++++++
 arch/arm/mm/dma-mapping.c      |  63 ++++++++++++++++++++++
 drivers/dma/sh/rcar-dmac.c     | 116 +++++++++++++++++++++++++++++++++--------
 include/linux/dma-debug.h      |  19 +++++++
 include/linux/dma-mapping.h    |  42 +++++++++++++++
 lib/dma-debug.c                |  52 +++++++++++++++++-
 8 files changed, 345 insertions(+), 29 deletions(-)

-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Mon May  9 09:44:03 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Mon,  9 May 2016 18:44:03 +0200
Subject: [PATCHv6 4/8] arm: dma-mapping: add {map,
 unmap}_resource for iommu ops
In-Reply-To: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462812247-3414-5-git-send-email-niklas.soderlund+renesas@ragnatech.se>

Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 arch/arm/mm/dma-mapping.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index deac58d..d5fe32b 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1962,6 +1962,63 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
 	__free_iova(mapping, iova, len);
 }
 
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+		phys_addr_t phys_addr, size_t size,
+		enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+	dma_addr_t dma_addr;
+	int ret, prot;
+	phys_addr_t addr = phys_addr & PAGE_MASK;
+	int offset = phys_addr & ~PAGE_MASK;
+	int len = PAGE_ALIGN(size + offset);
+
+	dma_addr = __alloc_iova(mapping, size);
+	if (dma_addr == DMA_ERROR_CODE)
+		return dma_addr;
+
+	prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+	ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+	if (ret < 0)
+		goto fail;
+
+	return dma_addr + offset;
+fail:
+	__free_iova(mapping, dma_addr, size);
+	return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+		size_t size, enum dma_data_direction dir,
+		struct dma_attrs *attrs)
+{
+	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+	dma_addr_t iova = dma_handle & PAGE_MASK;
+	int offset = dma_handle & ~PAGE_MASK;
+	int len = PAGE_ALIGN(size + offset);
+
+	if (!iova)
+		return;
+
+	iommu_unmap(mapping->domain, iova, len);
+	__free_iova(mapping, iova, len);
+}
+
 static void arm_iommu_sync_single_for_cpu(struct device *dev,
 		dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
@@ -2006,6 +2063,9 @@ struct dma_map_ops iommu_ops = {
 	.sync_sg_for_cpu	= arm_iommu_sync_sg_for_cpu,
 	.sync_sg_for_device	= arm_iommu_sync_sg_for_device,
 
+	.map_resource		= arm_iommu_map_resource,
+	.unmap_resource		= arm_iommu_unmap_resource,
+
 	.set_dma_mask		= arm_dma_set_mask,
 };
 
@@ -2021,6 +2081,9 @@ struct dma_map_ops iommu_coherent_ops = {
 	.map_sg		= arm_coherent_iommu_map_sg,
 	.unmap_sg	= arm_coherent_iommu_unmap_sg,
 
+	.map_resource	= arm_iommu_map_resource,
+	.unmap_resource	= arm_iommu_unmap_resource,
+
 	.set_dma_mask	= arm_dma_set_mask,
 };
 
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Mon May  9 09:44:02 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Mon,  9 May 2016 18:44:02 +0200
Subject: [PATCHv6 3/8] dma-mapping: add dma_{map,unmap}_resource
In-Reply-To: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462812247-3414-4-git-send-email-niklas.soderlund+renesas@ragnatech.se>

Map/Unmap a device MMIO resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
---
 Documentation/DMA-API.txt   | 22 +++++++++++++++++-----
 include/linux/dma-mapping.h | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 45ef3f2..c7e5f99 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -277,14 +277,26 @@ and <size> parameters are provided to do partial page mapping, it is
 recommended that you never use these unless you really know what the
 cache width is.
 
+dma_addr_t
+dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
+		 enum dma_data_direction dir, struct dma_attrs *attrs)
+
+void
+dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
+		   enum dma_data_direction dir, struct dma_attrs *attrs)
+
+API for mapping and unmapping for MMIO resources. All the notes and
+warnings for the other mapping APIs apply here. The API should only be
+used to map device MMIO resources, mapping of RAM is not permitted.
+
 int
 dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 
-In some circumstances dma_map_single() and dma_map_page() will fail to create
-a mapping. A driver can check for these errors by testing the returned
-DMA address with dma_mapping_error(). A non-zero return value means the mapping
-could not be created and the driver should take appropriate action (e.g.
-reduce current DMA mapping usage or delay and try again later).
+In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
+will fail to create a mapping. A driver can check for these errors by testing
+the returned DMA address with dma_mapping_error(). A non-zero return value
+means the mapping could not be created and the driver should take appropriate
+action (e.g. reduce current DMA mapping usage or delay and try again later).
 
 	int
 	dma_map_sg(struct device *dev, struct scatterlist *sg,
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 8617fa1..dd228ce 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -218,6 +218,42 @@ static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
 	debug_dma_unmap_page(dev, addr, size, dir, false);
 }
 
+static inline dma_addr_t dma_map_resource(struct device *dev,
+					  phys_addr_t phys_addr,
+					  size_t size,
+					  enum dma_data_direction dir,
+					  struct dma_attrs *attrs)
+{
+	struct dma_map_ops *ops = get_dma_ops(dev);
+	unsigned long pfn = __phys_to_pfn(phys_addr);
+	dma_addr_t addr;
+
+	BUG_ON(!valid_dma_direction(dir));
+
+	/* Don't allow RAM to be mapped */
+	BUG_ON(pfn_valid(pfn));
+
+	addr = phys_addr;
+	if (ops->map_resource)
+		addr = ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+	debug_dma_map_resource(dev, phys_addr, size, dir, addr);
+
+	return addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+				      size_t size, enum dma_data_direction dir,
+				      struct dma_attrs *attrs)
+{
+	struct dma_map_ops *ops = get_dma_ops(dev);
+
+	BUG_ON(!valid_dma_direction(dir));
+	if (ops->unmap_resource)
+		ops->unmap_resource(dev, addr, size, dir, attrs);
+	debug_dma_unmap_resource(dev, addr, size, dir);
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
 					   size_t size,
 					   enum dma_data_direction dir)
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Mon May  9 09:44:01 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Mon,  9 May 2016 18:44:01 +0200
Subject: [PATCHv6 2/8] dma-debug: add support for resource mappings
In-Reply-To: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462812247-3414-3-git-send-email-niklas.soderlund+renesas@ragnatech.se>

A MMIO mapped resource can not be represented by a struct page so a new
debug type is needed to handle this. This patch add such type and
functionality to add/remove entries and how to translate them to a
physical address.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
---
 include/linux/dma-debug.h | 19 +++++++++++++++++
 lib/dma-debug.c           | 52 +++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h
index fe8cb61..c7d844f 100644
--- a/include/linux/dma-debug.h
+++ b/include/linux/dma-debug.h
@@ -56,6 +56,13 @@ extern void debug_dma_alloc_coherent(struct device *dev, size_t size,
 extern void debug_dma_free_coherent(struct device *dev, size_t size,
 				    void *virt, dma_addr_t addr);
 
+extern void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
+				   size_t size, int direction,
+				   dma_addr_t dma_addr);
+
+extern void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
+				     size_t size, int direction);
+
 extern void debug_dma_sync_single_for_cpu(struct device *dev,
 					  dma_addr_t dma_handle, size_t size,
 					  int direction);
@@ -141,6 +148,18 @@ static inline void debug_dma_free_coherent(struct device *dev, size_t size,
 {
 }
 
+static inline void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
+					  size_t size, int direction,
+					  dma_addr_t dma_addr)
+{
+}
+
+static inline void debug_dma_unmap_resource(struct device *dev,
+					    dma_addr_t dma_addr, size_t size,
+					    int direction)
+{
+}
+
 static inline void debug_dma_sync_single_for_cpu(struct device *dev,
 						 dma_addr_t dma_handle,
 						 size_t size, int direction)
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 4a1515f..fb12d5c 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -43,6 +43,7 @@ enum {
 	dma_debug_page,
 	dma_debug_sg,
 	dma_debug_coherent,
+	dma_debug_resource,
 };
 
 enum map_err_types {
@@ -150,8 +151,9 @@ static const char *const maperr2str[] = {
 	[MAP_ERR_CHECKED] = "dma map error checked",
 };
 
-static const char *type2name[4] = { "single", "page",
-				    "scather-gather", "coherent" };
+static const char *type2name[5] = { "single", "page",
+				    "scather-gather", "coherent",
+				    "resource" };
 
 static const char *dir2name[4] = { "DMA_BIDIRECTIONAL", "DMA_TO_DEVICE",
 				   "DMA_FROM_DEVICE", "DMA_NONE" };
@@ -397,6 +399,9 @@ static void hash_bucket_del(struct dma_debug_entry *entry)
 
 static unsigned long long phys_addr(struct dma_debug_entry *entry)
 {
+	if (entry->type == dma_debug_resource)
+		return PHYS_PFN(entry->pfn) + entry->offset;
+
 	return page_to_phys(pfn_to_page(entry->pfn)) + entry->offset;
 }
 
@@ -1493,6 +1498,49 @@ void debug_dma_free_coherent(struct device *dev, size_t size,
 }
 EXPORT_SYMBOL(debug_dma_free_coherent);
 
+void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size,
+			    int direction, dma_addr_t dma_addr)
+{
+	struct dma_debug_entry *entry;
+
+	if (unlikely(dma_debug_disabled()))
+		return;
+
+	entry = dma_entry_alloc();
+	if (!entry)
+		return;
+
+	entry->type		= dma_debug_resource;
+	entry->dev		= dev;
+	entry->pfn		= __phys_to_pfn(addr);
+	entry->offset		= addr - PHYS_PFN(entry->pfn);
+	entry->size		= size;
+	entry->dev_addr		= dma_addr;
+	entry->direction	= direction;
+	entry->map_err_type	= MAP_ERR_NOT_CHECKED;
+
+	add_dma_entry(entry);
+}
+EXPORT_SYMBOL(debug_dma_map_resource);
+
+void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
+			      size_t size, int direction)
+{
+	struct dma_debug_entry ref = {
+		.type           = dma_debug_resource,
+		.dev            = dev,
+		.dev_addr       = dma_addr,
+		.size           = size,
+		.direction      = direction,
+	};
+
+	if (unlikely(dma_debug_disabled()))
+		return;
+
+	check_unmap(&ref);
+}
+EXPORT_SYMBOL(debug_dma_unmap_resource);
+
 void debug_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
 				   size_t size, int direction)
 {
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Mon May  9 09:44:06 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Mon,  9 May 2016 18:44:06 +0200
Subject: [PATCHv6 7/8] ARM: dts: r8a7790: add iommus to dmac0 and dmac1
In-Reply-To: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462812247-3414-8-git-send-email-niklas.soderlund+renesas@ragnatech.se>

A unconfirmed hardware bug prevents channel 0 and 15 to be used by the
DMAC together with the IPMMU. The DMAC driver will disable the channels
reducing the effective number of channels to 14 per DMAC.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
Acked-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 arch/arm/boot/dts/r8a7790.dtsi | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 404ef2b..2912320 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -336,6 +336,21 @@
 		power-domains = <&cpg_clocks>;
 		#dma-cells = <1>;
 		dma-channels = <15>;
+		iommus = <&ipmmu_ds 0>,
+			 <&ipmmu_ds 1>,
+			 <&ipmmu_ds 2>,
+			 <&ipmmu_ds 3>,
+			 <&ipmmu_ds 4>,
+			 <&ipmmu_ds 5>,
+			 <&ipmmu_ds 6>,
+			 <&ipmmu_ds 7>,
+			 <&ipmmu_ds 8>,
+			 <&ipmmu_ds 9>,
+			 <&ipmmu_ds 10>,
+			 <&ipmmu_ds 11>,
+			 <&ipmmu_ds 12>,
+			 <&ipmmu_ds 13>,
+			 <&ipmmu_ds 14>;
 	};
 
 	dmac1: dma-controller at e6720000 {
@@ -367,6 +382,21 @@
 		power-domains = <&cpg_clocks>;
 		#dma-cells = <1>;
 		dma-channels = <15>;
+		iommus = <&ipmmu_ds 15>,
+			 <&ipmmu_ds 16>,
+			 <&ipmmu_ds 17>,
+			 <&ipmmu_ds 18>,
+			 <&ipmmu_ds 19>,
+			 <&ipmmu_ds 20>,
+			 <&ipmmu_ds 21>,
+			 <&ipmmu_ds 22>,
+			 <&ipmmu_ds 23>,
+			 <&ipmmu_ds 24>,
+			 <&ipmmu_ds 25>,
+			 <&ipmmu_ds 26>,
+			 <&ipmmu_ds 27>,
+			 <&ipmmu_ds 28>,
+			 <&ipmmu_ds 29>;
 	};
 
 	audma0: dma-controller at ec700000 {
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Mon May  9 09:44:07 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Mon,  9 May 2016 18:44:07 +0200
Subject: [PATCHv6 8/8] ARM: dts: r8a7791: add iommus to dmac0 and dmac1
In-Reply-To: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462812247-3414-9-git-send-email-niklas.soderlund+renesas@ragnatech.se>

A unconfirmed hardware bug prevents channel 0 and 15 to be used by the
DMAC together with the IPMMU. The DMAC driver will disable the channels
reducing the effective number of channels to 14 per DMAC.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
Acked-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 arch/arm/boot/dts/r8a7791.dtsi | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 4f01b64..dc81c90 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -313,6 +313,21 @@
 		power-domains = <&cpg_clocks>;
 		#dma-cells = <1>;
 		dma-channels = <15>;
+		iommus = <&ipmmu_ds 0>,
+			 <&ipmmu_ds 1>,
+			 <&ipmmu_ds 2>,
+			 <&ipmmu_ds 3>,
+			 <&ipmmu_ds 4>,
+			 <&ipmmu_ds 5>,
+			 <&ipmmu_ds 6>,
+			 <&ipmmu_ds 7>,
+			 <&ipmmu_ds 8>,
+			 <&ipmmu_ds 9>,
+			 <&ipmmu_ds 10>,
+			 <&ipmmu_ds 11>,
+			 <&ipmmu_ds 12>,
+			 <&ipmmu_ds 13>,
+			 <&ipmmu_ds 14>;
 	};
 
 	dmac1: dma-controller at e6720000 {
@@ -344,6 +359,21 @@
 		power-domains = <&cpg_clocks>;
 		#dma-cells = <1>;
 		dma-channels = <15>;
+		iommus = <&ipmmu_ds 15>,
+			 <&ipmmu_ds 16>,
+			 <&ipmmu_ds 17>,
+			 <&ipmmu_ds 18>,
+			 <&ipmmu_ds 19>,
+			 <&ipmmu_ds 20>,
+			 <&ipmmu_ds 21>,
+			 <&ipmmu_ds 22>,
+			 <&ipmmu_ds 23>,
+			 <&ipmmu_ds 24>,
+			 <&ipmmu_ds 25>,
+			 <&ipmmu_ds 26>,
+			 <&ipmmu_ds 27>,
+			 <&ipmmu_ds 28>,
+			 <&ipmmu_ds 29>;
 	};
 
 	audma0: dma-controller at ec700000 {
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Mon May  9 09:44:04 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Mon,  9 May 2016 18:44:04 +0200
Subject: [PATCHv6 5/8] dmaengine: rcar-dmac: group slave configuration
In-Reply-To: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462812247-3414-6-git-send-email-niklas.soderlund+renesas@ragnatech.se>

Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 drivers/dma/sh/rcar-dmac.c | 38 ++++++++++++++++++++++----------------
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index dfb1792..b0c3bb2 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,22 @@ struct rcar_dmac_desc_page {
 	sizeof(struct rcar_dmac_xfer_chunk))
 
 /*
+ * struct rcar_dmac_chan_slave - Slave configuration
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+	phys_addr_t slave_addr;
+	unsigned int xfer_size;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
  * @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
  * @mid_rid: hardware MID/RID for the DMA client using this channel
  * @lock: protects the channel CHCR register and the desc members
  * @desc.free: list of free descriptors
@@ -142,10 +150,8 @@ struct rcar_dmac_chan {
 	void __iomem *iomem;
 	unsigned int index;
 
-	unsigned int src_xfer_size;
-	unsigned int dst_xfer_size;
-	dma_addr_t src_slave_addr;
-	dma_addr_t dst_slave_addr;
+	struct rcar_dmac_chan_slave src;
+	struct rcar_dmac_chan_slave dst;
 	int mid_rid;
 
 	spinlock_t lock;
@@ -793,13 +799,13 @@ static void rcar_dmac_chan_configure_desc(struct rcar_dmac_chan *chan,
 	case DMA_DEV_TO_MEM:
 		chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
 		     | RCAR_DMACHCR_RS_DMARS;
-		xfer_size = chan->src_xfer_size;
+		xfer_size = chan->src.xfer_size;
 		break;
 
 	case DMA_MEM_TO_DEV:
 		chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
 		     | RCAR_DMACHCR_RS_DMARS;
-		xfer_size = chan->dst_xfer_size;
+		xfer_size = chan->dst.xfer_size;
 		break;
 
 	case DMA_MEM_TO_MEM:
@@ -1038,7 +1044,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 	}
 
 	dev_addr = dir == DMA_DEV_TO_MEM
-		 ? rchan->src_slave_addr : rchan->dst_slave_addr;
+		 ? rchan->src.slave_addr : rchan->dst.slave_addr;
 	return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
 				      dir, flags, false);
 }
@@ -1093,7 +1099,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
 	}
 
 	dev_addr = dir == DMA_DEV_TO_MEM
-		 ? rchan->src_slave_addr : rchan->dst_slave_addr;
+		 ? rchan->src.slave_addr : rchan->dst.slave_addr;
 	desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
 				      dir, flags, true);
 
@@ -1110,10 +1116,10 @@ static int rcar_dmac_device_config(struct dma_chan *chan,
 	 * We could lock this, but you shouldn't be configuring the
 	 * channel, while using it...
 	 */
-	rchan->src_slave_addr = cfg->src_addr;
-	rchan->dst_slave_addr = cfg->dst_addr;
-	rchan->src_xfer_size = cfg->src_addr_width;
-	rchan->dst_xfer_size = cfg->dst_addr_width;
+	rchan->src.slave_addr = cfg->src_addr;
+	rchan->dst.slave_addr = cfg->dst_addr;
+	rchan->src.xfer_size = cfg->src_addr_width;
+	rchan->dst.xfer_size = cfg->dst_addr_width;
 
 	return 0;
 }
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Mon May  9 09:44:05 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Mon,  9 May 2016 18:44:05 +0200
Subject: [PATCHv6 6/8] dmaengine: rcar-dmac: add iommu support for slave
 transfers
In-Reply-To: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462812247-3414-7-git-send-email-niklas.soderlund+renesas@ragnatech.se>

Enable slave transfers to a device behind a IPMMU by mapping the slave
addresses using the dma-mapping API.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
---
 drivers/dma/sh/rcar-dmac.c | 82 +++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 74 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index b0c3bb2..8592598 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -128,6 +128,18 @@ struct rcar_dmac_chan_slave {
 };
 
 /*
+ * struct rcar_dmac_chan_map - Map of slave device phys to dma address
+ * @addr: slave dma address
+ * @dir: direction of mapping
+ * @slave: slave configuration that is mapped
+ */
+struct rcar_dmac_chan_map {
+	dma_addr_t addr;
+	enum dma_data_direction dir;
+	struct rcar_dmac_chan_slave slave;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
@@ -152,6 +164,7 @@ struct rcar_dmac_chan {
 
 	struct rcar_dmac_chan_slave src;
 	struct rcar_dmac_chan_slave dst;
+	struct rcar_dmac_chan_map map;
 	int mid_rid;
 
 	spinlock_t lock;
@@ -1027,13 +1040,65 @@ rcar_dmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,
 				      DMA_MEM_TO_MEM, flags, false);
 }
 
+static int rcar_dmac_map_slave_addr(struct dma_chan *chan,
+				    enum dma_transfer_direction dir)
+{
+	struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+	struct rcar_dmac_chan_map *map = &rchan->map;
+	phys_addr_t dev_addr;
+	size_t dev_size;
+	enum dma_data_direction dev_dir;
+
+	if (dir == DMA_DEV_TO_MEM) {
+		dev_addr = rchan->src.slave_addr;
+		dev_size = rchan->src.xfer_size;
+		dev_dir = DMA_TO_DEVICE;
+	} else {
+		dev_addr = rchan->dst.slave_addr;
+		dev_size = rchan->dst.xfer_size;
+		dev_dir = DMA_FROM_DEVICE;
+	}
+
+	/* Reuse current map if possible. */
+	if (dev_addr == map->slave.slave_addr &&
+	    dev_size == map->slave.xfer_size &&
+	    dev_dir == map->dir)
+		return 0;
+
+	/* Remove old mapping if present. */
+	if (map->slave.xfer_size)
+		dma_unmap_resource(chan->device->dev, map->addr,
+				   map->slave.xfer_size, map->dir, NULL);
+	map->slave.xfer_size = 0;
+
+	/* Create new slave address map. */
+	map->addr = dma_map_resource(chan->device->dev, dev_addr, dev_size,
+				     dev_dir, NULL);
+
+	if (dma_mapping_error(chan->device->dev, map->addr)) {
+		dev_err(chan->device->dev,
+			"chan%u: failed to map %zx@%pap", rchan->index,
+			dev_size, &dev_addr);
+		return -EIO;
+	}
+
+	dev_dbg(chan->device->dev, "chan%u: map %zx@%pap to %pad dir: %s\n",
+		rchan->index, dev_size, &dev_addr, &map->addr,
+		dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE");
+
+	map->slave.slave_addr = dev_addr;
+	map->slave.xfer_size = dev_size;
+	map->dir = dev_dir;
+
+	return 0;
+}
+
 static struct dma_async_tx_descriptor *
 rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 			unsigned int sg_len, enum dma_transfer_direction dir,
 			unsigned long flags, void *context)
 {
 	struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
-	dma_addr_t dev_addr;
 
 	/* Someone calling slave DMA on a generic channel? */
 	if (rchan->mid_rid < 0 || !sg_len) {
@@ -1043,9 +1108,10 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 		return NULL;
 	}
 
-	dev_addr = dir == DMA_DEV_TO_MEM
-		 ? rchan->src.slave_addr : rchan->dst.slave_addr;
-	return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
+	if (rcar_dmac_map_slave_addr(chan, dir))
+		return NULL;
+
+	return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, rchan->map.addr,
 				      dir, flags, false);
 }
 
@@ -1059,7 +1125,6 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
 	struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
 	struct dma_async_tx_descriptor *desc;
 	struct scatterlist *sgl;
-	dma_addr_t dev_addr;
 	unsigned int sg_len;
 	unsigned int i;
 
@@ -1071,6 +1136,9 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
 		return NULL;
 	}
 
+	if (rcar_dmac_map_slave_addr(chan, dir))
+		return NULL;
+
 	sg_len = buf_len / period_len;
 	if (sg_len > RCAR_DMAC_MAX_SG_LEN) {
 		dev_err(chan->device->dev,
@@ -1098,9 +1166,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
 		sg_dma_len(&sgl[i]) = period_len;
 	}
 
-	dev_addr = dir == DMA_DEV_TO_MEM
-		 ? rchan->src.slave_addr : rchan->dst.slave_addr;
-	desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
+	desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, rchan->map.addr,
 				      dir, flags, true);
 
 	kfree(sgl);
-- 
2.8.2



From andre.przywara at arm.com  Mon May  9 09:49:45 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon,  9 May 2016 17:49:45 +0100
Subject: [PATCH 1/6] arm64: alternatives: drop enable parameter from _else and
 _endif macro
In-Reply-To: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>
References: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462812590-4494-2-git-send-email-andre.przywara@arm.com>

Commit 77ee306c0aea9 ("arm64: alternatives: add enable parameter to
conditional asm macros") extended the alternative assembly macros.
Unfortunately this does not really work as one would expect, as the
enable parameter in fact correctly protects the alternative section
magic, but not the actual code sequences.
So if enable is false, we will have the original instruction(s) _and_
the alternative ones in the file, which is just wrong.
To make this work one would need to additionally protect the
alternative sequence with extra .if directives, which makes
the intention of the enable parameter rather pointless.
Instead users should directly guard the whole "_else; insn; _endif"
sequence with .if directives.
Add a comment describing this usage and drop the enable parameter from
the alternative_else and alternative_endif macros.

This reverts parts of commit 77ee306c0aea ("arm64: alternatives: add
enable parameter to conditional asm macros").

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm64/include/asm/alternative.h | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h
index beccbde..502c9ef 100644
--- a/arch/arm64/include/asm/alternative.h
+++ b/arch/arm64/include/asm/alternative.h
@@ -94,6 +94,8 @@ void apply_alternatives(void *start, size_t length);
  *
  * The code that follows this macro will be assembled and linked as
  * normal. There are no restrictions on this code.
+ * If you use the enable parameter, see the comments below for _else
+ * and _endif.
  */
 .macro alternative_if_not cap, enable = 1
 	.if \enable
@@ -117,23 +119,33 @@ void apply_alternatives(void *start, size_t length);
  * 2. Not contain a branch target that is used outside of the
  *    alternative sequence it is defined in (branches into an
  *    alternative sequence are not fixed up).
+ *
+ * If you used the optional enable parameter in the opening
+ * alternative_if_not macro above, please protect the whole _else
+ * branch with an .if directive:
+ *	alternative_if_not CAP_SOMETHING, condition
+ *		orig_insn
+ *	.if condition
+ *	alternative_else
+ *		repl_insn
+ *	alternative_endif
+ *	.endif
  */
-.macro alternative_else, enable = 1
-	.if \enable
+.macro alternative_else
 662:	.pushsection .altinstr_replacement, "ax"
 663:
-	.endif
 .endm
 
 /*
  * Complete an alternative code sequence.
+ *
+ * Please mind the comment at alternative_else above if you used the
+ * optional enable parameter with the opening alternative_if_not macro.
  */
-.macro alternative_endif, enable = 1
-	.if \enable
+.macro alternative_endif
 664:	.popsection
 	.org	. - (664b-663b) + (662b-661b)
 	.org	. - (662b-661b) + (664b-663b)
-	.endif
 .endm
 
 #define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...)	\
-- 
2.7.3



From andre.przywara at arm.com  Mon May  9 09:49:46 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon,  9 May 2016 17:49:46 +0100
Subject: [PATCH 2/6] arm64: fix "dc cvau" cache operation on errata-affected
 core
In-Reply-To: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>
References: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462812590-4494-3-git-send-email-andre.przywara@arm.com>

The ARM errata 819472, 826319, 827319 and 824069 for affected
Cortex-A53 cores demand to promote "dc cvau" instructions to
"dc civac" as well.
Attribute the usage of the instruction in __flush_cache_user_range
to also be covered by our alternative patching efforts.
For that we introduce an assembly macro which both deals with
alternatives while still tagging the instructions as USER.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm64/include/asm/alternative.h | 4 ++++
 arch/arm64/mm/cache.S                | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h
index 502c9ef..d4a69a9 100644
--- a/arch/arm64/include/asm/alternative.h
+++ b/arch/arm64/include/asm/alternative.h
@@ -151,6 +151,10 @@ void apply_alternatives(void *start, size_t length);
 #define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...)	\
 	alternative_insn insn1, insn2, cap, IS_ENABLED(cfg)
 
+.macro user_alt, label, oldinstr, newinstr, cond
+9999:	alternative_insn "\oldinstr", "\newinstr", \cond
+	_ASM_EXTABLE 9999b, \label
+.endm
 
 /*
  * Generate the assembly for UAO alternatives with exception table entries.
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index 6df0706..82f40bd 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -54,7 +54,7 @@ ENTRY(__flush_cache_user_range)
 	sub	x3, x2, #1
 	bic	x4, x0, x3
 1:
-USER(9f, dc	cvau, x4	)		// clean D line to PoU
+user_alt 9f, "dc cvau, x4",  "dc civac, x4",  ARM64_WORKAROUND_CLEAN_CACHE
 	add	x4, x4, x2
 	cmp	x4, x1
 	b.lo	1b
-- 
2.7.3



From andre.przywara at arm.com  Mon May  9 09:49:47 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon,  9 May 2016 17:49:47 +0100
Subject: [PATCH 3/6] arm64: include alternative handling in dcache_by_line_op
In-Reply-To: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>
References: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462812590-4494-4-git-send-email-andre.przywara@arm.com>

The newly introduced dcache_by_line_op macro is used at least in
one occassion at the moment to issue a "dc cvau" instruction,
which is affected by ARM errata 819472, 826319, 827319 and 824069.
Change the macro to allow for alternative patching in there to
protect affected Cortex-A53 cores.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm64/mm/proc-macros.S | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/proc-macros.S b/arch/arm64/mm/proc-macros.S
index e6a30e1..5786017 100644
--- a/arch/arm64/mm/proc-macros.S
+++ b/arch/arm64/mm/proc-macros.S
@@ -78,7 +78,14 @@
 	add	\size, \kaddr, \size
 	sub	\tmp2, \tmp1, #1
 	bic	\kaddr, \kaddr, \tmp2
-9998:	dc	\op, \kaddr
+9998:
+	alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE, (\op == cvau || \op == cvac)
+	dc	\op, \kaddr
+	.if	(\op == cvau || \op == cvac)
+	alternative_else
+	dc	civac, \kaddr
+	alternative_endif
+	.endif
 	add	\kaddr, \kaddr, \tmp1
 	cmp	\kaddr, \size
 	b.lo	9998b
-- 
2.7.3



From andre.przywara at arm.com  Mon May  9 09:49:48 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon,  9 May 2016 17:49:48 +0100
Subject: [PATCH 4/6] arm64: errata: Calling enable functions for CPU errata too
In-Reply-To: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>
References: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462812590-4494-5-git-send-email-andre.przywara@arm.com>

Currently we call the (optional) enable function for CPU _features_
only. As CPU _errata_ descriptions share the same data structure and
having an enable function is useful for errata as well (for instance
to set bits in SCTLR), lets call it when enumerating erratas too.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm64/include/asm/cpufeature.h | 2 ++
 arch/arm64/kernel/cpu_errata.c      | 5 +++++
 arch/arm64/kernel/cpufeature.c      | 4 ++--
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index b9b6494..cb8fb2c 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -174,7 +174,9 @@ void __init setup_cpu_features(void);
 
 void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 			    const char *info);
+void enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps);
 void check_local_cpu_errata(void);
+void __init enable_cpu_errata(void);
 
 void verify_local_cpu_capabilities(void);
 
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 06afd04..64cb71d 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -105,3 +105,8 @@ void check_local_cpu_errata(void)
 {
 	update_cpu_capabilities(arm64_errata, "enabling workaround for");
 }
+
+void __init enable_cpu_errata(void)
+{
+	enable_cpu_capabilities(arm64_errata);
+}
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 943f514..04a324f 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -835,8 +835,7 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
  * Run through the enabled capabilities and enable() it on all active
  * CPUs
  */
-static void __init
-enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
+void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 {
 	int i;
 
@@ -974,6 +973,7 @@ void __init setup_cpu_features(void)
 
 	/* Set the CPU feature capabilies */
 	setup_feature_capabilities();
+	enable_cpu_errata();
 	setup_cpu_hwcaps();
 
 	/* Advertise that we have computed the system capabilities */
-- 
2.7.3



From andre.przywara at arm.com  Mon May  9 09:49:44 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon,  9 May 2016 17:49:44 +0100
Subject: [PATCH 0/6] arm64: Extend Cortex-A53 errata workaround
Message-ID: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>

According to the errata documentation for the ARM errata 819472, 826319,
827319 and 824069, in addition to the already covered promotion of
"dc cvac" cache maintenance instructions to "dc civac"[1], we also need
to promote "dc cvau" operations.
Also as cache maintenance instructions on ARMv8 can be issued by EL0 as
well, we unfortunately have to promote them too, which is only possible
by means of trap-and-emulate.

These patches cover all in-kernel users of "dc cvau" and make sure
they are using "dc civac" if run on an affected core.
In addition if at least one core in the system has one of the above
mentioned erratas, we set the respective bit in SCTLR to trap cache
maintenance instructions from EL0 to EL1 on all CPUs, where we "emulate"
them by executing the potentially fixed instruction on behalf of userspace.

Apart from the actual patches 2/6 and 6/6, which do the main work, the
other patches are cleanups and do refactoring to make the promotion and
trapping of EL0 cache maintenance easier.

Tested on a Juno R0 with an userspace tool to issue various cache
maintenance instructions (including one with triggers a SIGSEGV) and
verified with some debugfs entries.
At least one LTP test also issues around 100 cache maintenance
instructions, which this code survived happily.

Cheers,
Andre.

[1] commit 301bcfac4289 ("arm64: add Cortex-A53 cache errata workaround")

Andre Przywara (6):
  arm64: alternatives: drop enable parameter from _else and _endif macro
  arm64: fix "dc cvau" cache operation on errata-affected core
  arm64: include alternative handling in dcache_by_line_op
  arm64: errata: Calling enable functions for CPU errata too
  arm64: consolidate signal injection on emulation errors
  arm64: trap userspace "dc cvau" cache operation on errata-affected
    core

 arch/arm64/include/asm/alternative.h |  28 +++++++--
 arch/arm64/include/asm/cpufeature.h  |   2 +
 arch/arm64/include/asm/processor.h   |   1 +
 arch/arm64/include/asm/sysreg.h      |   2 +-
 arch/arm64/include/asm/traps.h       |   3 +
 arch/arm64/kernel/armv8_deprecated.c |  13 ++--
 arch/arm64/kernel/cpu_errata.c       |   7 +++
 arch/arm64/kernel/cpufeature.c       |   4 +-
 arch/arm64/kernel/entry.S            |  12 +++-
 arch/arm64/kernel/traps.c            | 111 +++++++++++++++++++++++++++++++----
 arch/arm64/mm/cache.S                |   2 +-
 arch/arm64/mm/proc-macros.S          |   9 ++-
 12 files changed, 164 insertions(+), 30 deletions(-)

-- 
2.7.3



From andre.przywara at arm.com  Mon May  9 09:49:50 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon,  9 May 2016 17:49:50 +0100
Subject: [PATCH 6/6] arm64: trap userspace "dc cvau" cache operation on
 errata-affected core
In-Reply-To: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>
References: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462812590-4494-7-git-send-email-andre.przywara@arm.com>

The ARM errata 819472, 826319, 827319 and 824069 for affected
Cortex-A53 cores demand to promote "dc cvau" instructions to
"dc civac". Since we allow userspace to also emit those instructions,
we should make sure that "dc cvau" gets promoted there too.
So lets grasp the nettle here and actually trap every userland cache
maintenance instruction once we detect at least one affected core in
the system.
We then emulate the instruction by executing it on behalf of userland,
promoting "dc cvau" to "dc civac" on the way and injecting access
fault back into userspace.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm64/include/asm/processor.h |  1 +
 arch/arm64/include/asm/sysreg.h    |  2 +-
 arch/arm64/kernel/cpu_errata.c     |  2 ++
 arch/arm64/kernel/entry.S          | 12 ++++++-
 arch/arm64/kernel/traps.c          | 71 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index cef1cf3..ace0a96 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -192,5 +192,6 @@ static inline void spin_lock_prefetch(const void *ptr)
 
 void cpu_enable_pan(void *__unused);
 void cpu_enable_uao(void *__unused);
+void cpu_enable_cache_maint_trap(void *__unused);
 
 #endif /* __ASM_PROCESSOR_H */
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 1287416..7e0b097 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -90,7 +90,7 @@
 #define SCTLR_EL1_CP15BEN	(0x1 << 5)
 #define SCTLR_EL1_SED		(0x1 << 8)
 #define SCTLR_EL1_SPAN		(0x1 << 23)
-
+#define SCTLR_EL1_UCI		(0x1 << 26)
 
 /* id_aa64isar0 */
 #define ID_AA64ISAR0_RDM_SHIFT		28
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 64cb71d..3f54d23 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -44,6 +44,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.desc = "ARM errata 826319, 827319, 824069",
 		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
 		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
+		.enable = cpu_enable_cache_maint_trap,
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_819472
@@ -52,6 +53,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.desc = "ARM errata 819472",
 		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
 		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
+		.enable = cpu_enable_cache_maint_trap,
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_832075
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 12e8d2b..86480b4 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -451,7 +451,7 @@ el0_sync:
 	cmp	x24, #ESR_ELx_EC_FP_EXC64	// FP/ASIMD exception
 	b.eq	el0_fpsimd_exc
 	cmp	x24, #ESR_ELx_EC_SYS64		// configurable trap
-	b.eq	el0_undef
+	b.eq	el0_sys
 	cmp	x24, #ESR_ELx_EC_SP_ALIGN	// stack alignment exception
 	b.eq	el0_sp_pc
 	cmp	x24, #ESR_ELx_EC_PC_ALIGN	// pc alignment exception
@@ -579,6 +579,16 @@ el0_undef:
 	mov	x0, sp
 	bl	do_undefinstr
 	b	ret_to_user
+el0_sys:
+	/*
+	 * System instructions, for trapped cache maintenance instructions
+	 */
+	enable_dbg_and_irq
+	ct_user_exit
+	mov	x0, x25
+	mov	x1, sp
+	bl	do_sysinstr
+	b	ret_to_user
 el0_dbg:
 	/*
 	 * Debug exception handling
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 03755a4..c2a158e 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -41,6 +41,7 @@
 #include <asm/stacktrace.h>
 #include <asm/exception.h>
 #include <asm/system_misc.h>
+#include <asm/sysreg.h>
 
 static const char *handler[]= {
 	"Synchronous Abort",
@@ -419,6 +420,76 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 	force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
 }
 
+void cpu_enable_cache_maint_trap(void *__unused)
+{
+	config_sctlr_el1(SCTLR_EL1_UCI, 0);
+}
+
+#define __user_cache_maint(insn, address, res)			\
+	asm volatile (						\
+		"1:	" insn ", %1\n"				\
+		"	mov	%w0, #0\n"			\
+		"2:\n"						\
+		"	.pushsection .fixup,\"ax\"\n"		\
+		"	.align	2\n"				\
+		"3:	mov	%w0, %w2\n"			\
+		"	b	2b\n"				\
+		"	.popsection\n"				\
+		_ASM_EXTABLE(1b, 3b)				\
+		: "=r" (res)					\
+		: "r" (address), "i" (-EFAULT)			\
+		: "memory")
+
+asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs)
+{
+	unsigned long address;
+	int ret;
+
+	/* if this is a write with: Op0=1, Op2=1, Op1=3, CRn=7 */
+	if ((esr & 0x01fffc01) == 0x0012dc00) {
+		int rt = (esr >> 5) & 0x1f;
+		int crm = (esr >> 1) & 0x0f;
+
+		address = regs->regs[rt];
+
+		switch (crm) {
+		case 11:		/* DC CVAU, gets promoted */
+			__user_cache_maint("dc civac", address, ret);
+			break;
+		case 10:		/* DC CVAC, gets promoted */
+			__user_cache_maint("dc civac", address, ret);
+			break;
+		case 14:		/* DC CIVAC */
+			__user_cache_maint("dc civac", address, ret);
+			break;
+		case 5:			/* IC IVAU */
+			__user_cache_maint("ic ivau", address, ret);
+			break;
+		default:
+			force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
+			return;
+		}
+	} else {
+		force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
+		return;
+	}
+
+	if (ret) {
+		int sig_code;
+
+		down_read(&current->mm->mmap_sem);
+		if (find_vma(current->mm, address) == NULL)
+			sig_code = SEGV_MAPERR;
+		else
+			sig_code = SEGV_ACCERR;
+		up_read(&current->mm->mmap_sem);
+
+		force_signal_inject(SIGSEGV, sig_code, regs, address);
+	} else {
+		regs->pc += 4;
+	}
+}
+
 long compat_arm_syscall(struct pt_regs *regs);
 
 asmlinkage long do_ni_syscall(struct pt_regs *regs)
-- 
2.7.3



From andre.przywara at arm.com  Mon May  9 09:49:49 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon,  9 May 2016 17:49:49 +0100
Subject: [PATCH 5/6] arm64: consolidate signal injection on emulation errors
In-Reply-To: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>
References: <1462812590-4494-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1462812590-4494-6-git-send-email-andre.przywara@arm.com>

The code for injecting a signal into userland if a trapped instruction
fails emulation due to a _userland_ error (like an illegal address)
will be used more often with the next patch.
Factor out the core functionality into a separate function and use
that both for the existing trap handler and for the deprecated
instructions emulation.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm64/include/asm/traps.h       |  3 +++
 arch/arm64/kernel/armv8_deprecated.c | 13 ++++------
 arch/arm64/kernel/traps.c            | 46 ++++++++++++++++++++++++++----------
 3 files changed, 41 insertions(+), 21 deletions(-)

diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
index 0cc2f29..b20ce2f 100644
--- a/arch/arm64/include/asm/traps.h
+++ b/arch/arm64/include/asm/traps.h
@@ -34,6 +34,9 @@ struct undef_hook {
 void register_undef_hook(struct undef_hook *hook);
 void unregister_undef_hook(struct undef_hook *hook);
 
+void force_signal_inject(int signal, int code, struct pt_regs *regs,
+			 unsigned long address);
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 static inline int __in_irqentry_text(unsigned long ptr)
 {
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index c37202c..4003843 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -321,21 +321,18 @@ static void __init register_insn_emulation_sysctl(struct ctl_table *table)
  */
 static void set_segfault(struct pt_regs *regs, unsigned long addr)
 {
-	siginfo_t info;
+	int code;
 
 	down_read(&current->mm->mmap_sem);
 	if (find_vma(current->mm, addr) == NULL)
-		info.si_code = SEGV_MAPERR;
+		code = SEGV_MAPERR;
 	else
-		info.si_code = SEGV_ACCERR;
+		code = SEGV_ACCERR;
 	up_read(&current->mm->mmap_sem);
 
-	info.si_signo = SIGSEGV;
-	info.si_errno = 0;
-	info.si_addr  = (void *) instruction_pointer(regs);
-
 	pr_debug("SWP{B} emulation: access caused memory abort!\n");
-	arm64_notify_die("Illegal memory access", regs, &info, 0);
+
+	force_signal_inject(SIGSEGV, code, regs, addr);
 }
 
 static int emulate_swpX(unsigned int address, unsigned int *data,
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index c539208..03755a4 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -373,30 +373,50 @@ exit:
 	return fn ? fn(regs, instr) : 1;
 }
 
-asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
+void force_signal_inject(int signal, int code, struct pt_regs *regs,
+			 unsigned long address)
 {
 	siginfo_t info;
 	void __user *pc = (void __user *)instruction_pointer(regs);
+	const char *desc;
 
-	/* check for AArch32 breakpoint instructions */
-	if (!aarch32_break_handler(regs))
-		return;
-
-	if (call_undef_hook(regs) == 0)
-		return;
+	switch (signal) {
+	case SIGILL:
+		desc = "undefined instruction";
+		break;
+	case SIGSEGV:
+		desc = "illegal memory access";
+		break;
+	default:
+		desc = "bad mode";
+		break;
+	}
 
-	if (unhandled_signal(current, SIGILL) && show_unhandled_signals_ratelimited()) {
-		pr_info("%s[%d]: undefined instruction: pc=%p\n",
-			current->comm, task_pid_nr(current), pc);
+	if (unhandled_signal(current, signal) &&
+	    show_unhandled_signals_ratelimited()) {
+		pr_info("%s[%d]: %s: pc=%p\n",
+			current->comm, task_pid_nr(current), desc, pc);
 		dump_instr(KERN_INFO, regs);
 	}
 
-	info.si_signo = SIGILL;
+	info.si_signo = signal;
 	info.si_errno = 0;
-	info.si_code  = ILL_ILLOPC;
+	info.si_code  = code;
 	info.si_addr  = pc;
 
-	arm64_notify_die("Oops - undefined instruction", regs, &info, 0);
+	arm64_notify_die(desc, regs, &info, 0);
+}
+
+asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
+{
+	/* check for AArch32 breakpoint instructions */
+	if (!aarch32_break_handler(regs))
+		return;
+
+	if (call_undef_hook(regs) == 0)
+		return;
+
+	force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
 }
 
 long compat_arm_syscall(struct pt_regs *regs);
-- 
2.7.3



From catalin.marinas at arm.com  Mon May  9 09:50:56 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Mon, 9 May 2016 17:50:56 +0100
Subject: [PATCH] kvm: arm64: Enable hardware updates of the Access Flag
 for Stage 2 page tables
In-Reply-To: <20160509153310.GA27623@cbox>
References: <1460566657-30221-1-git-send-email-catalin.marinas@arm.com>
 <20160509153310.GA27623@cbox>
Message-ID: <20160509165056.GC20598@e104818-lin.cambridge.arm.com>

On Mon, May 09, 2016 at 05:33:10PM +0200, Christoffer Dall wrote:
> On Wed, Apr 13, 2016 at 05:57:37PM +0100, Catalin Marinas wrote:
> > The ARMv8.1 architecture extensions introduce support for hardware
> > updates of the access and dirty information in page table entries. With
> > VTCR_EL2.HA enabled (bit 21), when the CPU accesses an IPA with the
> > PTE_AF bit cleared in the stage 2 page table, instead of raising an
> > Access Flag fault to EL2 the CPU sets the actual page table entry bit
> > (10). To ensure that kernel modifications to the page table do not
> > inadvertently revert a bit set by hardware updates, certain Stage 2
> > software pte/pmd operations must be performed atomically.
> > 
> > The main user of the AF bit is the kvm_age_hva() mechanism. The
> > kvm_age_hva_handler() function performs a "test and clear young" action
> > on the pte/pmd. This needs to be atomic in respect of automatic hardware
> > updates of the AF bit. Since the AF bit is in the same position for both
> > Stage 1 and Stage 2, the patch reuses the existing
> > ptep_test_and_clear_young() functionality if
> > __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG is defined. Otherwise, the
> > existing pte_young/pte_mkold mechanism is preserved.
> > 
> > The kvm_set_s2pte_readonly() (and the corresponding pmd equivalent) have
> > to perform atomic modifications in order to avoid a race with updates of
> > the AF bit. The arm64 implementation has been re-written using
> > exclusives.
> > 
> > Currently, kvm_set_s2pte_writable() (and pmd equivalent) take a pointer
> > argument and modify the pte/pmd in place. However, these functions are
> > only used on local variables rather than actual page table entries, so
> > it makes more sense to follow the pte_mkwrite() approach for stage 1
> > attributes. The change to kvm_s2pte_mkwrite() makes it clear that these
> > functions do not modify the actual page table entries.
> 
> so if one CPU takes a permission fault and is in the process of updating
> the page table, what prevents another CPU from setting the access flag
> (on a read, done by HW) on that entry between us reading the old pte and
> replacing it with the new pte?

There isn't anything that would prevent this. However, as in the stage 1
scenarios, explicitly writing a PTE as a result of a permission fault
should also mark the entry as accessed (young, either as the default
protection in PROT_DEFAULT or explicitly via pte_mkyoung).

> Don't we loose the AF information in that case too?

Since the hardware never clears the AF bit automatically, there is no
information to lose in this race as long as the kvm_set_s2pte_writable()
sets the AF bit. AFAICT, the PAGE_S2 and PAGE_S2_DEVICE definitions
already use PROT_DEFAULT which has the AF bit set.

> >  static inline void kvm_set_s2pte_readonly(pte_t *pte)
> >  {
> > -	pte_val(*pte) = (pte_val(*pte) & ~PTE_S2_RDWR) | PTE_S2_RDONLY;
> > +	pteval_t pteval;
> > +	unsigned long tmp;
> > +
> > +	asm volatile("//	kvm_set_s2pte_readonly\n"
> > +	"	prfm	pstl1strm, %2\n"
> > +	"1:	ldxr	%0, %2\n"
> > +	"	and	%0, %0, %3		// clear PTE_S2_RDWR\n"
> > +	"	orr	%0, %0, %4		// set PTE_S2_RDONLY\n"
> > +	"	stxr	%w1, %0, %2\n"
> > +	"	cbnz	%w1, 1b\n"
> > +	: "=&r" (pteval), "=&r" (tmp), "+Q" (pte_val(*pte))
> 
> so the +Q means "pass the memory address of the value and by the way the
> content, not the address itself, can be updated by the assembly code" ?

Yes. I think "info gcc" isn't clear enough on this constraint (at least
to me) but that's something we learnt from the tools guys in the early
days of the aarch64 kernel port.

-- 
Catalin


From Tirumalesh.Chalamarla at cavium.com  Mon May  9 09:53:01 2016
From: Tirumalesh.Chalamarla at cavium.com (Chalamarla, Tirumalesh)
Date: Mon, 9 May 2016 16:53:01 +0000
Subject: [PATCH v4 03/12] KVM: arm64: Introduce new MMIO region for the
 ITS base address
In-Reply-To: <5730B108.5010009@arm.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-4-git-send-email-andre.przywara@arm.com>
 <651B7BE4-D1C9-44B2-84BE-19103C1D8CE0@caviumnetworks.com>
 <5730B108.5010009@arm.com>
Message-ID: <692F5470-73B2-467D-A5D4-58439446AC93@caviumnetworks.com>






On 5/9/16, 8:47 AM, "Marc Zyngier" <marc.zyngier at arm.com> wrote:

>On 05/05/16 19:08, Chalamarla, Tirumalesh wrote:
>> 
>> 
>> 
>> 
>> 
>> On 3/25/16, 7:14 PM, "kvmarm-bounces at lists.cs.columbia.edu on behalf of Andre Przywara" <kvmarm-bounces at lists.cs.columbia.edu on behalf of andre.przywara at arm.com> wrote:
>> 
>>> The ARM GICv3 ITS controller requires a separate register frame to
>>> cover ITS specific registers. Add a new VGIC address type and store
>>> the address in a field in the vgic_dist structure.
>>> Provide a function to check whether userland has provided the address,
>>> so ITS functionality can be guarded by that check.
>>>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>> Documentation/virtual/kvm/devices/arm-vgic.txt |  9 +++++++++
>>> arch/arm64/include/uapi/asm/kvm.h              |  2 ++
>>> include/kvm/vgic/vgic.h                        |  5 +++++
>>> virt/kvm/arm/vgic/vgic.c                       | 10 ++++++++++
>>> virt/kvm/arm/vgic/vgic_init.c                  |  1 +
>>> virt/kvm/arm/vgic/vgic_kvm_device.c            |  7 +++++++
>>> 6 files changed, 34 insertions(+)
>>>
>>> diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
>>> index 59541d4..087e2d9 100644
>>> --- a/Documentation/virtual/kvm/devices/arm-vgic.txt
>>> +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
>>> @@ -39,6 +39,15 @@ Groups:
>>>       Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
>>>       This address needs to be 64K aligned.
>>>
>>> +    KVM_VGIC_V3_ADDR_TYPE_ITS (rw, 64-bit)
>>> +      Base address in the guest physical address space of the GICv3 ITS
>>> +      control register frame. The ITS allows MSI(-X) interrupts to be
>>> +      injected into guests. This extension is optional, if the kernel
>>> +      does not support the ITS, the call returns -ENODEV.
>>> +      This memory is solely for the guest to access the ITS control
>>> +      registers and does not cover the ITS translation register.
>>> +      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
>>> +      This address needs to be 64K aligned and the region covers 64 KByte.
>>>
>>>   KVM_DEV_ARM_VGIC_GRP_DIST_REGS
>>>   Attributes:
>>> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
>>> index f209ea1..c2b257d 100644
>>> --- a/arch/arm64/include/uapi/asm/kvm.h
>>> +++ b/arch/arm64/include/uapi/asm/kvm.h
>>> @@ -87,9 +87,11 @@ struct kvm_regs {
>>> /* Supported VGICv3 address types  */
>>> #define KVM_VGIC_V3_ADDR_TYPE_DIST	2
>>> #define KVM_VGIC_V3_ADDR_TYPE_REDIST	3
>>> +#define KVM_VGIC_V3_ADDR_TYPE_ITS	4
>>>
>>> #define KVM_VGIC_V3_DIST_SIZE		SZ_64K
>>> #define KVM_VGIC_V3_REDIST_SIZE		(2 * SZ_64K)
>>> +#define KVM_VGIC_V3_ITS_SIZE		SZ_64K
>>>
>>> #define KVM_ARM_VCPU_POWER_OFF		0 /* CPU is started in OFF state */
>>> #define KVM_ARM_VCPU_EL1_32BIT		1 /* CPU running a 32bit VM */
>>> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
>>> index 7c1d145..11344e6 100644
>>> --- a/include/kvm/vgic/vgic.h
>>> +++ b/include/kvm/vgic/vgic.h
>>> @@ -135,6 +135,9 @@ struct vgic_dist {
>>> 		gpa_t			vgic_redist_base;
>>> 	};
>>>
>>> +	/* The base address of the ITS control register frame */
>>> +	gpa_t			vgic_its_base;
>>> +
>>> 	/* distributor enabled */
>>> 	u32			enabled;
>>>
>>> @@ -253,4 +256,6 @@ static inline int kvm_vgic_get_max_vcpus(void)
>>> 	return kvm_vgic_global_state.max_gic_vcpus;
>>> }
>>>
>>> +bool vgic_has_its(struct kvm *kvm);
>>> +
>>> #endif /* __ASM_ARM_KVM_VGIC_VGIC_H */
>>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>>> index 65395af..1de2478 100644
>>> --- a/virt/kvm/arm/vgic/vgic.c
>>> +++ b/virt/kvm/arm/vgic/vgic.c
>>> @@ -612,3 +612,13 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, u32 intid)
>>>
>>> 	return map_is_active;
>>> }
>>> +
>>> +bool vgic_has_its(struct kvm *kvm)
>>> +{
>>> +	struct vgic_dist *dist = &kvm->arch.vgic;
>>> +
>>> +	if (dist->vgic_model != KVM_DEV_TYPE_ARM_VGIC_V3)
>>> +		return false;
>>> +
>>> +	return !IS_VGIC_ADDR_UNDEF(dist->vgic_its_base);
>>> +}
>>> diff --git a/virt/kvm/arm/vgic/vgic_init.c b/virt/kvm/arm/vgic/vgic_init.c
>>> index ac655b5..2301e03 100644
>>> --- a/virt/kvm/arm/vgic/vgic_init.c
>>> +++ b/virt/kvm/arm/vgic/vgic_init.c
>>> @@ -132,6 +132,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
>>> 	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
>>> 	kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
>>> 	kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
>>> +	kvm->arch.vgic.vgic_its_base = VGIC_ADDR_UNDEF;
>>>
>>> out_unlock:
>>> 	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
>>> diff --git a/virt/kvm/arm/vgic/vgic_kvm_device.c b/virt/kvm/arm/vgic/vgic_kvm_device.c
>>> index 7f78a16..3ec2ac3 100644
>>> --- a/virt/kvm/arm/vgic/vgic_kvm_device.c
>>> +++ b/virt/kvm/arm/vgic/vgic_kvm_device.c
>>> @@ -109,6 +109,12 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
>>> 		block_size = KVM_VGIC_V3_REDIST_SIZE;
>>> 		alignment = SZ_64K;
>>> 		break;
>>> +	case KVM_VGIC_V3_ADDR_TYPE_ITS:
>>> +		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
>>> +		addr_ptr = &vgic->vgic_its_base;
>>> +		block_size = KVM_VGIC_V3_ITS_SIZE;
>>> +		alignment = SZ_64K;
>>> +		break;
>> 
>> Should there be a check based on number of vcpus? 
>
>Why would the number of vcpus influence the size of the ITS?

does the re-distributor per VCPU thing? I think its worth to add a check for re distributor size. 
>
>Thanks,
>
>	M.
>-- 
>Jazz is not dead. It just smells funny...

From robh at kernel.org  Mon May  9 10:00:43 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 12:00:43 -0500
Subject: [PATCH] ARM: dts: imx: Remove unneeded unit-addresses
In-Reply-To: <20160506121911.04a7aa6e@jclayton-pc>
References: <1462283851-10820-1-git-send-email-fabio.estevam@nxp.com>
 <CAL_JsqKv_7ufFG7DSkxqp9QOEjLEDVofyYMoudtJjqBA78ahcA@mail.gmail.com>
 <CAOMZO5AO15UmNJARS9aL-U=CjYnUq0D9S38NYHC8w2DLwOeR_A@mail.gmail.com>
 <CAOMZO5BXFL47p=WTPDDRFGq38yktmB1FnbOTWJ37mrWsKkeUSQ@mail.gmail.com>
 <20160506121911.04a7aa6e@jclayton-pc>
Message-ID: <CAL_JsqKp5q5oL=s6haOU8ggtst_ejL5wZx2NeqFi=izF64z6cQ@mail.gmail.com>

On Fri, May 6, 2016 at 2:19 PM, Joshua Clayton <stillcompiling at gmail.com> wrote:
> On Tue, 3 May 2016 12:45:07 -0300
> Fabio Estevam <festevam at gmail.com> wrote:
>
>> On Tue, May 3, 2016 at 12:42 PM, Fabio Estevam <festevam at gmail.com>
>> wrote:
>> > On Tue, May 3, 2016 at 12:37 PM, Rob Herring <robh at kernel.org>
>> > wrote:
>> >> Presumably these are register offsets which could be useful to have
>> >> even if the Linux driver doesn't use them. But either way is fine
>> >> with me.
>> >
>> > Yes, these are register offsets.
>> >
>> >                 reg_3p0: regulator-3p0 {
>> >                     compatible = "fsl,anatop-regulator";
>> >                     regulator-name = "vdd3p0";
>> >                     regulator-min-microvolt = <2625000>;
>> >                     regulator-max-microvolt = <3400000>;
>> >                     anatop-reg-offset = <0x120>;
>>
>> Sorry, pressed the 'send' button too quickly.
>>
>> There is a "anatop-reg-offset = <0x120>;" property that is used to
>> pass the offset to the anatop regulator driver, so that's why I
>> preferred to remove the unneeded unit-address.
>>
>> Thanks
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
> There are actually 2 registers (on some of them),
> anatop-reg-offset, and anatop-delay-reg-offset...
> Converting those to use reg and deprecating the anatop specific
> items would seem like a Good Thing (tm) to me.
>
> ...wandering into less safe territory:
> I know reg is usually a memory offset in bytes, but
> each of the anatop memory offsets also include a bit-shift
> and a bit-width item, which really narrowly defines the
> register bits that pertain to each regulator.
>
> would it be totally inappropriate to use
> #address-cells = 2 and
> #size-cells =1
> where address cells would contain the byte offset and the bit shift, and
> the size cell would contain the bit offset?

Technically that is fine. However, then the standard address
translation functions will not work.

Given it is also encoding bit offsets, I'd just keep this patch as is.
We could also debate just not putting this in the DT at all.

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

Rob


From stefan.wahren at i2se.com  Mon May  9 09:59:25 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Mon, 9 May 2016 18:59:25 +0200
Subject: [PATCH V2 3/4] ARM: mxs: dts: Add Creative X-Fi3 support
In-Reply-To: <1462740621-7557-3-git-send-email-marex@denx.de>
References: <1462740621-7557-1-git-send-email-marex@denx.de>
 <1462740621-7557-3-git-send-email-marex@denx.de>
Message-ID: <5730C1ED.5090307@i2se.com>

Am 08.05.2016 um 22:50 schrieb Marek Vasut:
> From: Marek Vasut <marek.vasut at gmail.com>
>
> Add support for this small MP3 player based on STMP3780 (rev.4).
> Currently supported is both external microSD and internal SD-NAND
> bridge, PWM and USB gadget.
>
> Signed-off-by: Marek Vasut <marek.vasut at gmail.com>
> Cc: Fabio Estevam <fabio.estevam at nxp.com>
> Cc: Shawn Guo <shawnguo at kernel.org>
> ---
> V2: - Fix the button nodes to not generate possible DT warning
>     - Drop the address part from the license
> ---

Reviewed-by: Stefan Wahren <stefan.wahren at i2se.com>

Thanks



From marc.zyngier at arm.com  Mon May  9 10:09:48 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 9 May 2016 18:09:48 +0100
Subject: [PATCH v4 03/12] KVM: arm64: Introduce new MMIO region for the
 ITS base address
In-Reply-To: <692F5470-73B2-467D-A5D4-58439446AC93@caviumnetworks.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-4-git-send-email-andre.przywara@arm.com>
 <651B7BE4-D1C9-44B2-84BE-19103C1D8CE0@caviumnetworks.com>
 <5730B108.5010009@arm.com>
 <692F5470-73B2-467D-A5D4-58439446AC93@caviumnetworks.com>
Message-ID: <5730C45C.1070808@arm.com>

On 09/05/16 17:53, Chalamarla, Tirumalesh wrote:
> 
> 
> 
> 
> 
> On 5/9/16, 8:47 AM, "Marc Zyngier" <marc.zyngier at arm.com> wrote:
> 
>> On 05/05/16 19:08, Chalamarla, Tirumalesh wrote:
>>>
>>>
>>>
>>>
>>>
>>> On 3/25/16, 7:14 PM, "kvmarm-bounces at lists.cs.columbia.edu on behalf of Andre Przywara" <kvmarm-bounces at lists.cs.columbia.edu on behalf of andre.przywara at arm.com> wrote:
>>>
>>>> The ARM GICv3 ITS controller requires a separate register frame to
>>>> cover ITS specific registers. Add a new VGIC address type and store
>>>> the address in a field in the vgic_dist structure.
>>>> Provide a function to check whether userland has provided the address,
>>>> so ITS functionality can be guarded by that check.
>>>>
>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>> ---
>>>> Documentation/virtual/kvm/devices/arm-vgic.txt |  9 +++++++++
>>>> arch/arm64/include/uapi/asm/kvm.h              |  2 ++
>>>> include/kvm/vgic/vgic.h                        |  5 +++++
>>>> virt/kvm/arm/vgic/vgic.c                       | 10 ++++++++++
>>>> virt/kvm/arm/vgic/vgic_init.c                  |  1 +
>>>> virt/kvm/arm/vgic/vgic_kvm_device.c            |  7 +++++++
>>>> 6 files changed, 34 insertions(+)
>>>>
>>>> diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
>>>> index 59541d4..087e2d9 100644
>>>> --- a/Documentation/virtual/kvm/devices/arm-vgic.txt
>>>> +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
>>>> @@ -39,6 +39,15 @@ Groups:
>>>>       Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
>>>>       This address needs to be 64K aligned.
>>>>
>>>> +    KVM_VGIC_V3_ADDR_TYPE_ITS (rw, 64-bit)
>>>> +      Base address in the guest physical address space of the GICv3 ITS
>>>> +      control register frame. The ITS allows MSI(-X) interrupts to be
>>>> +      injected into guests. This extension is optional, if the kernel
>>>> +      does not support the ITS, the call returns -ENODEV.
>>>> +      This memory is solely for the guest to access the ITS control
>>>> +      registers and does not cover the ITS translation register.
>>>> +      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
>>>> +      This address needs to be 64K aligned and the region covers 64 KByte.
>>>>
>>>>   KVM_DEV_ARM_VGIC_GRP_DIST_REGS
>>>>   Attributes:
>>>> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
>>>> index f209ea1..c2b257d 100644
>>>> --- a/arch/arm64/include/uapi/asm/kvm.h
>>>> +++ b/arch/arm64/include/uapi/asm/kvm.h
>>>> @@ -87,9 +87,11 @@ struct kvm_regs {
>>>> /* Supported VGICv3 address types  */
>>>> #define KVM_VGIC_V3_ADDR_TYPE_DIST	2
>>>> #define KVM_VGIC_V3_ADDR_TYPE_REDIST	3
>>>> +#define KVM_VGIC_V3_ADDR_TYPE_ITS	4
>>>>
>>>> #define KVM_VGIC_V3_DIST_SIZE		SZ_64K
>>>> #define KVM_VGIC_V3_REDIST_SIZE		(2 * SZ_64K)
>>>> +#define KVM_VGIC_V3_ITS_SIZE		SZ_64K
>>>>
>>>> #define KVM_ARM_VCPU_POWER_OFF		0 /* CPU is started in OFF state */
>>>> #define KVM_ARM_VCPU_EL1_32BIT		1 /* CPU running a 32bit VM */
>>>> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
>>>> index 7c1d145..11344e6 100644
>>>> --- a/include/kvm/vgic/vgic.h
>>>> +++ b/include/kvm/vgic/vgic.h
>>>> @@ -135,6 +135,9 @@ struct vgic_dist {
>>>> 		gpa_t			vgic_redist_base;
>>>> 	};
>>>>
>>>> +	/* The base address of the ITS control register frame */
>>>> +	gpa_t			vgic_its_base;
>>>> +
>>>> 	/* distributor enabled */
>>>> 	u32			enabled;
>>>>
>>>> @@ -253,4 +256,6 @@ static inline int kvm_vgic_get_max_vcpus(void)
>>>> 	return kvm_vgic_global_state.max_gic_vcpus;
>>>> }
>>>>
>>>> +bool vgic_has_its(struct kvm *kvm);
>>>> +
>>>> #endif /* __ASM_ARM_KVM_VGIC_VGIC_H */
>>>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>>>> index 65395af..1de2478 100644
>>>> --- a/virt/kvm/arm/vgic/vgic.c
>>>> +++ b/virt/kvm/arm/vgic/vgic.c
>>>> @@ -612,3 +612,13 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, u32 intid)
>>>>
>>>> 	return map_is_active;
>>>> }
>>>> +
>>>> +bool vgic_has_its(struct kvm *kvm)
>>>> +{
>>>> +	struct vgic_dist *dist = &kvm->arch.vgic;
>>>> +
>>>> +	if (dist->vgic_model != KVM_DEV_TYPE_ARM_VGIC_V3)
>>>> +		return false;
>>>> +
>>>> +	return !IS_VGIC_ADDR_UNDEF(dist->vgic_its_base);
>>>> +}
>>>> diff --git a/virt/kvm/arm/vgic/vgic_init.c b/virt/kvm/arm/vgic/vgic_init.c
>>>> index ac655b5..2301e03 100644
>>>> --- a/virt/kvm/arm/vgic/vgic_init.c
>>>> +++ b/virt/kvm/arm/vgic/vgic_init.c
>>>> @@ -132,6 +132,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
>>>> 	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
>>>> 	kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
>>>> 	kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
>>>> +	kvm->arch.vgic.vgic_its_base = VGIC_ADDR_UNDEF;
>>>>
>>>> out_unlock:
>>>> 	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
>>>> diff --git a/virt/kvm/arm/vgic/vgic_kvm_device.c b/virt/kvm/arm/vgic/vgic_kvm_device.c
>>>> index 7f78a16..3ec2ac3 100644
>>>> --- a/virt/kvm/arm/vgic/vgic_kvm_device.c
>>>> +++ b/virt/kvm/arm/vgic/vgic_kvm_device.c
>>>> @@ -109,6 +109,12 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
>>>> 		block_size = KVM_VGIC_V3_REDIST_SIZE;
>>>> 		alignment = SZ_64K;
>>>> 		break;
>>>> +	case KVM_VGIC_V3_ADDR_TYPE_ITS:
>>>> +		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
>>>> +		addr_ptr = &vgic->vgic_its_base;
>>>> +		block_size = KVM_VGIC_V3_ITS_SIZE;
>>>> +		alignment = SZ_64K;
>>>> +		break;
>>>
>>> Should there be a check based on number of vcpus? 
>>
>> Why would the number of vcpus influence the size of the ITS?
> 
> does the re-distributor per VCPU thing? I think its worth to add a
> check for re distributor size.

This patch is implementing the ITS, not the redistributors.

If you have any comment on the GICv3 implementation (of which the
redistributors are part of), please comment on the relevant patch (see
the 55 patch series that has been posted on Friday).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From robh at kernel.org  Mon May  9 10:14:27 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 12:14:27 -0500
Subject: [PATCH v2 5/5] vf610-soc: Add Vybrid SoC device tree binding
 documentation
In-Reply-To: <20160505082758.GB18151@Sanchayan-Arch.localdomain>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
 <65f3a7bd7a9faf1b390644d7c599c69683c753c4.1462171990.git.maitysanchayan@gmail.com>
 <20160504023026.GB5382@rob-hp-laptop>
 <20160505082758.GB18151@Sanchayan-Arch.localdomain>
Message-ID: <CAL_JsqL1qQu_u=6xosP8UmR3oXLawbVz=Hap0wDm7aN4mjK2GA@mail.gmail.com>

On Thu, May 5, 2016 at 3:27 AM,  <maitysanchayan at gmail.com> wrote:
> Hello Rob,
>
> On 16-05-03 21:30:26, Rob Herring wrote:
>> On Mon, May 02, 2016 at 12:35:04PM +0530, Sanchayan Maity wrote:
>> > Add device tree binding documentation for Vybrid SoC.
>> >
>> > Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
>> > ---
>> >  .../bindings/arm/freescale/fsl,vf610-soc.txt       | 35 ++++++++++++++++++++++
>> >  1 file changed, 35 insertions(+)
>> >  create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>> >
>> > diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>> > new file mode 100644
>> > index 0000000..bdd95e8
>> > --- /dev/null
>> > +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>> > @@ -0,0 +1,35 @@
>> > +Vybrid System-on-Chip
>> > +---------------------
>> > +
>> > +Required properties:
>> > +
>> > +- #address-cells: must be 1
>> > +- #size-cells: must be 1
>> > +- compatible: "fsl,vf610-soc-bus", "simple-bus"
>>
>> If this is a bus, put the file in bindings/bus/...
>
> The fsl,vf610-soc-bus binding is used to bind the driver in question with
> an appropriate compatible node.
>
> Basically being a standalone platform driver, there was need of a compatible
> property to bind on. Introducing a separate device tree node for it's sake
> didn't seem appropriate so the alteration to SoC node's compatible.

Ah, so you are designing a node around the needs of a Linux specific
driver. Don't do that. DT describes the h/w and this node is not a h/w
block.

Create a platform device based on a matching SOC compatible string
instead and make your driver find the information it needs directly
from the relevant nodes like the ROM node.

>> > +- interrupt-parent: phandle to the MSCM interrupt router node
>> > +- ranges
>> > +- fsl,rom-revision: phandle to the on-chip ROM node and address of rom
>> > +  revision register
>>
>> Why is this needed here? Can't you search the tree for the ROM node and
>> get this info.
>
> Strictly per say this and next two can be specified in their respective nodes
> of ocrom and mscm cpucfg, however they would then require the use of syscon_
> regmap_lookup_by_compatible and this seems clean along with the introduction
> of new syscon_regmap_read_from_offset function used with SoC node.

That does not make sense. You can find the ROM node by compatible
string, get the address, get an revision offset property, and read the
address. There's no need for syscon nor regmap here.

>> > +- fsl,cpu-count: phandle to the MSCM CPU configuration node and address of
>> > +  CPU count register
>> > +- fsl,l2-size: phandle to the MSCM CPU configuration node and address of
>> > +  L2 cache size register
>> > +- nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
>> > +- nvmem-cell-names: should contain string names "cfg0" and "cfg1"
>>
>> How are all these properties used?
>
> All the above five are used to get the relevant values from the registers and
> expose the information for SoC sysfs device.
> https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-soc
>
> nvmem are consumer nodes which are accessed using the NVMEM consumer API's
> leveraging the NVMEM framework and NVMEM vf610 ocotp driver.

So, please describe in the binding doc what the values contain. cfg0
and cfg1 is meaningless. But based on the above, this whole binding
should go.

Rob


From romain.izard.pro at gmail.com  Mon May  9 10:17:54 2016
From: romain.izard.pro at gmail.com (Romain Izard)
Date: Mon, 9 May 2016 19:17:54 +0200
Subject: [PATCH] ARM: dts: at91: sama5d2: use "atmel,sama5d3-nfc"
 compatible for nfc
In-Reply-To: <1462811669-10107-1-git-send-email-nicolas.ferre@atmel.com>
References: <1462776680-5284-3-git-send-email-wenyou.yang@atmel.com>
 <1462811669-10107-1-git-send-email-nicolas.ferre@atmel.com>
Message-ID: <CAGkQfmMrdOeknw=-HpjD8UfUCMsZAj7mqasjorLE6f6qbYv+sw@mail.gmail.com>

2016-05-09 18:34 GMT+02:00 Nicolas Ferre <nicolas.ferre at atmel.com>:
> From: Wenyou Yang <wenyou.yang at atmel.com>
>
> An error in documentation of the NAND Flash Controller (NFC) led to choose
> another compatibility string for sama5d2 with an impact on the NAND flash
> ready/busy information. It was producing the error message:
>
> atmel_nand 80000000.nand: Time out to wait for interrupt: 0x08000000
>
> and had an impact on performance.
>
> So, switch back to the classical "atmel,sama5d3-nfc" compatibility string for
> this SoC which gives the proper ready/busy bit information. The NAND flash
> driver will be updated to remove the support for this different
> implementation.
>
> Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> [nicolas.ferre at atmel.com: change commit message]
> Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>

Acked-by: Romain Izard <romain.izard.pro at gmail.com>

> ---
> Wenyou, Romain,
>
> I plan to send this patch for 4.6-rc as a fix tomorrow (my time). Can you
> please tell me if it's okay on your side.
> I revised the commit message just to justify the very late "fix" sending of
> this patch...
>
> Thanks for your help, bye.
>   Nicolas.
>
>
>  arch/arm/boot/dts/sama5d2.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
> index 78996bdbd3df..9817090c1b73 100644
> --- a/arch/arm/boot/dts/sama5d2.dtsi
> +++ b/arch/arm/boot/dts/sama5d2.dtsi
> @@ -280,7 +280,7 @@
>                         status = "disabled";
>
>                         nfc at c0000000 {
> -                               compatible = "atmel,sama5d4-nfc";
> +                               compatible = "atmel,sama5d3-nfc";
>                                 #address-cells = <1>;
>                                 #size-cells = <1>;
>                                 reg = < /* NFC Command Registers */
> --
> 2.1.3
>


From marc.zyngier at arm.com  Mon May  9 10:18:21 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 9 May 2016 18:18:21 +0100
Subject: [PATCH v3 32/55] KVM: arm/arm64: vgic-new: Add GICv3 MMIO
 handling framework
In-Reply-To: <1462531568-9799-33-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-33-git-send-email-andre.przywara@arm.com>
Message-ID: <5730C65D.5000609@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> Create a new file called vgic-mmio-v3.c and describe the GICv3
> distributor and redistributor registers there.
> This adds a special macro to deal with the split of SGI/PPI in the
> redistributor and SPIs in the distributor, which allows us to reuse
> the existing GICv2 handlers for those registers which are compatible.
> Also we provide a function to deal with the registration of the two
> separate redistributor frames per VCPU.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Reviewed-by: Eric Auger <eric.auger at linaro.org>
> ---
> Changelog RFC..v1:
> - adapt to new MMIO registration approach:
>   register one device for the distributor and two for each VCPU
> - implement special handling for private interrupts
> - remove empty stub functions
> - make IGROUPR return RAO
> 
> Changelog v1 .. v2:
> - adapt to new framework, introduce vgic-mmio-v3.c
> - remove userland register access functions (for now)
> - precompute .len when describing a VGIC register
> - add missed pointer incrementation on registering redist regions
> - replace _nyi stub functions with raz/wi versions
> 
> Changelog v2 .. v3:
> - replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h
> - add prototype and stub code for vgic_register_redist_iodevs
> - rename register struct variables _rdbase_ and _sgibase_
> 
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
>  virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
>  virt/kvm/arm/vgic/vgic.h         |   7 ++
>  4 files changed, 205 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> new file mode 100644
> index 0000000..06c7ec5
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -0,0 +1,191 @@
> +/*
> + * VGICv3 MMIO handling functions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/irqchip/arm-gic-v3.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/iodev.h>
> +#include <kvm/arm_vgic.h>
> +
> +#include <asm/kvm_emulate.h>
> +
> +#include "vgic.h"
> +#include "vgic-mmio.h"
> +
> +/*
> + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
> + * redistributors, while SPIs are covered by registers in the distributor
> + * block. Trying to set private IRQs in this block gets ignored.
> + * We take some special care here to fix the calculation of the register
> + * offset.
> + */
> +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \
> +	{								\
> +		.reg_offset = off,					\
> +		.bits_per_irq = bpi,					\
> +		.len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8,		\
> +		.read = vgic_mmio_read_raz,				\
> +		.write = vgic_mmio_write_wi,				\
> +	}, {								\
> +		.reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8,	\
> +		.bits_per_irq = bpi,					\
> +		.len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
> +		.read = read_ops,					\
> +		.write = write_ops,					\
> +	}
> +
> +static const struct vgic_register_region vgic_v3_dist_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
> +		vgic_mmio_read_config, vgic_mmio_write_config, 2),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 64),
> +	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
> +};
> +
> +static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
> +};
> +
> +static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 32),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
> +		vgic_mmio_read_config, vgic_mmio_write_config, 8),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +};
> +
> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
> +{
> +	dev->regions = vgic_v3_dist_registers;
> +	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
> +
> +	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
> +
> +	return SZ_64K;
> +}
> +
> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
> +{
> +	int nr_vcpus = atomic_read(&kvm->online_vcpus);
> +	struct kvm_vcpu *vcpu;
> +	struct vgic_io_device *devices, *device;
> +	int c, ret = 0;
> +
> +	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
> +			  GFP_KERNEL);
> +	if (!devices)
> +		return -ENOMEM;
> +
> +	device = devices;
> +	kvm_for_each_vcpu(c, vcpu, kvm) {
> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
> +		device->base_addr = redist_base_address;
> +		device->regions = vgic_v3_rdbase_registers;
> +		device->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
> +		device->redist_vcpu = vcpu;
> +
> +		mutex_lock(&kvm->slots_lock);
> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
> +					      redist_base_address,
> +					      SZ_64K, &device->dev);
> +		mutex_unlock(&kvm->slots_lock);
> +
> +		if (ret)
> +			break;
> +
> +		device++;
> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
> +		device->base_addr = redist_base_address + SZ_64K;
> +		device->regions = vgic_v3_sgibase_registers;
> +		device->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
> +		device->redist_vcpu = vcpu;
> +
> +		mutex_lock(&kvm->slots_lock);
> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
> +					      redist_base_address + SZ_64K,
> +					      SZ_64K, &device->dev);
> +		mutex_unlock(&kvm->slots_lock);
> +		if (ret) {
> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
> +						  &devices[c * 2].dev);
> +			break;
> +		}
> +		device++;
> +		redist_base_address += 2 * SZ_64K;
> +	}

What I fail to see here is what prevents the redistributor range from
overlapping with the distributor (or any other device). The kvm IO bus
is happy with overlapping addresses, but I'm not sure at all that this
is safe.

Care to shed some light on it?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From marc.zyngier at arm.com  Mon May  9 10:27:08 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 9 May 2016 18:27:08 +0100
Subject: [PATCH v3 47/55] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <1462531568-9799-48-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-48-git-send-email-andre.przywara@arm.com>
Message-ID: <5730C86C.1080004@arm.com>

On 06/05/16 11:46, Andre Przywara wrote:
> Using the VMCR accessors we provide access to GIC CPU interface state
> to userland by wiring it up to the existing userland interface.
> [Marc: move and make VMCR accessors static, streamline MMIO handlers]
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
> Changelog v2 .. v3:
> - total rework, moving into vgic-mmio-v2.c
> - move vmcr accessor wrapper functions into this file
> - use the register description table for CPU i/f registers as well
> - add RAZ/WI handling for the active priority registers
> - streamline MMIO handler functions
> 
>  virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 104 ++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h            |   2 +
>  3 files changed, 107 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index bb33af8..2122ff2 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -300,7 +300,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
>  
>  	switch (attr->group) {
>  	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> -		ret = -EINVAL;
> +		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
>  		break;
>  	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>  		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index c453e6f..0060539 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -206,6 +206,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> +{
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_set_vmcr(vcpu, vmcr);
> +	else
> +		vgic_v3_set_vmcr(vcpu, vmcr);
> +}
> +
> +static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> +{
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_get_vmcr(vcpu, vmcr);
> +	else
> +		vgic_v3_get_vmcr(vcpu, vmcr);
> +}
> +
> +#define GICC_ARCH_VERSION_V2	0x2
> +
> +/* These are for userland accesses only, there is no guest-facing emulation. */
> +static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
> +					   gpa_t addr, unsigned int len)
> +{
> +	struct vgic_vmcr vmcr;
> +	u32 val;
> +
> +	vgic_get_vmcr(vcpu, &vmcr);
> +
> +	switch (addr & 0xff) {
> +	case GIC_CPU_CTRL:
> +		val = vmcr.ctlr;
> +		break;
> +	case GIC_CPU_PRIMASK:
> +		val = vmcr.pmr;
> +		break;
> +	case GIC_CPU_BINPOINT:
> +		val = vmcr.bpr;
> +		break;
> +	case GIC_CPU_ALIAS_BINPOINT:
> +		val = vmcr.abpr;
> +		break;
> +	case GIC_CPU_IDENT:
> +		val = ((PRODUCT_ID_KVM << 20) |
> +		       (GICC_ARCH_VERSION_V2 << 16) |
> +		       IMPLEMENTER_ARM);
> +		break;
> +	default:
> +		return 0;
> +	}
> +
> +	return extract_bytes(val, addr & 3, len);
> +}
> +
> +static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
> +				   gpa_t addr, unsigned int len,
> +				   unsigned long val)
> +{
> +	struct vgic_vmcr vmcr;
> +
> +	vgic_get_vmcr(vcpu, &vmcr);
> +
> +	switch (addr & 0xff) {
> +	case GIC_CPU_CTRL:
> +		vmcr.ctlr = val;
> +		break;
> +	case GIC_CPU_PRIMASK:
> +		vmcr.pmr = val;
> +		break;
> +	case GIC_CPU_BINPOINT:
> +		vmcr.bpr = val;
> +		break;
> +	case GIC_CPU_ALIAS_BINPOINT:
> +		vmcr.abpr = val;
> +		break;
> +	}
> +
> +	vgic_set_vmcr(vcpu, &vmcr);
> +}
> +
>  static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
>  		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
> @@ -237,6 +315,21 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16),
>  };
>  
> +static const struct vgic_register_region vgic_v2_cpu_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_CTRL,
> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_PRIMASK,
> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_BINPOINT,
> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ALIAS_BINPOINT,
> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ACTIVEPRIO,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_IDENT,
> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
> +};
> +
>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
>  {
>  	dev->regions = vgic_v2_dist_registers;
> @@ -306,6 +399,17 @@ static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
>  	return ret;
>  }
>  
> +int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> +			  int offset, u32 *val)
> +{
> +	struct vgic_io_device dev = {
> +		.regions = vgic_v2_cpu_registers,
> +		.nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers),
> +	};
> +
> +	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
> +}
> +
>  int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  			 int offset, u32 *val)
>  {

And what about this:

+int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+       int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+       const struct vgic_register_region *regions;
+       gpa_t addr;
+       int nr_regions, i, len;
+
+       addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+       switch (attr->group) {
+       case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+               regions = vgic_v2_dist_registers;
+               nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
+               break;
+       case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+               return -ENXIO;          /* TODO: describe CPU i/f regs also */
+       default:
+               return -ENXIO;
+       }

This TODO was already in the previous version. Can you please wire it
and give save/restore a chance to work?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From krzk at kernel.org  Mon May  9 10:30:38 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 9 May 2016 19:30:38 +0200
Subject: [PATCH] clk: samsung: exynos5420: Remove useless check for
 return value of samsung_clk_init
In-Reply-To: <4033d4d5-558d-898f-cdc9-07a19654ade6@osg.samsung.com>
References: <1462699496-16646-1-git-send-email-krzk@kernel.org>
 <4033d4d5-558d-898f-cdc9-07a19654ade6@osg.samsung.com>
Message-ID: <20160509173038.GA2507@kozik-lap>

On Mon, May 09, 2016 at 09:32:47AM -0400, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/08/2016 05:24 AM, Krzysztof Kozlowski wrote:
> > The samsung_clk_init() cannot return NULL. Either it returns allocated
> > memory or it panics.
> > 
> > Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> > ---
> >  drivers/clk/samsung/clk-exynos5420.c | 2 --
> >  1 file changed, 2 deletions(-)
> > 
> > diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
> > index 92382cef9f90..770c0f007c6b 100644
> > --- a/drivers/clk/samsung/clk-exynos5420.c
> > +++ b/drivers/clk/samsung/clk-exynos5420.c
> > @@ -1356,8 +1356,6 @@ static void __init exynos5x_clk_init(struct device_node *np,
> >  	exynos5x_soc = soc;
> >  
> >  	ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
> > -	if (!ctx)
> > -		panic("%s: unable to allocate context.\n", __func__);
> >
> 
> Indeed, the check is superfluous. I see that most callers [0] currently
> do the same, so probably makes sense to remove those too in this patch.
> 
> Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Thanks, I'll change this everywhere.


Best regards,
Krzysztof



From peter.griffin at linaro.org  Mon May  9 10:30:43 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Mon, 9 May 2016 18:30:43 +0100
Subject: [PATCH 03/18] dmaengine: st_fdma: Add STMicroelectronics FDMA
 engine driver support
In-Reply-To: <20160502093015.GD2274@localhost>
References: <1461236675-10176-1-git-send-email-peter.griffin@linaro.org>
 <1461236675-10176-4-git-send-email-peter.griffin@linaro.org>
 <20160426165622.GR2274@localhost>
 <20160427125923.GA12756@griffinp-ThinkPad-X1-Carbon-2nd>
 <20160502093015.GD2274@localhost>
Message-ID: <20160509173043.GA25540@griffinp-ThinkPad-X1-Carbon-2nd>

Hi Vinod,

On Mon, 02 May 2016, Vinod Koul wrote:

> On Wed, Apr 27, 2016 at 01:59:23PM +0100, Peter Griffin wrote:
> > > bunch of this seems similar to cyclic case, can you create common setup
> > > routine for these, anyway cyclic is a special cases of slave_sg
> > 
> > In v4 I've made a st_fdma_prep_common() which abstracts out all the common
> > checks at the beginning of the *_prep*() functions.
> > 
> > In v3 fill_fw_node() is already (from one of your previous reviews)
> > abstracting out all the common parts from these loops. So everything
> > that is now left is actually differences between the two setups.
> > 
> > Is that Ok?
> 
> Sounds better
> 
> > > and you irq is still enabled and tasklets can be scheduled!!
> > > 
> > Eeek! Very good point. Also looking at some other drivers we
> > should be doing a of_dma_controller_free() and
> > dma_async_device_unregister().
> > 
> > So something like this: -
> > 
> >   st_fdma_disable(); /*disables irqs*/
> >   of_dma_controller_free(pdev->dev.of_node);
> >   dma_async_device_unregister(&priv->slave);
> >   st_fdma_clk_disable(fdev);
> 
> you can call devm_free_irq() explictyly, that will syncronize irq and
> free it up.

Ok will do/

> Also you should kill the tasklet afterwards.
> 
We aren't using a tasklet in this driver.

Peter.


From krzk at kernel.org  Mon May  9 10:32:31 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon,  9 May 2016 19:32:31 +0200
Subject: [PATCH v2] clk: samsung: Remove useless check for return value of
 samsung_clk_init
Message-ID: <1462815151-14396-1-git-send-email-krzk@kernel.org>

The samsung_clk_init() cannot return NULL. Either it returns allocated
memory or it panics.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

Changes since v1:
1. Remove the check from most of other Samsung clock drivers (suggested
   by Javier).
---
 drivers/clk/samsung/clk-exynos4.c    | 2 --
 drivers/clk/samsung/clk-exynos5250.c | 3 +--
 drivers/clk/samsung/clk-exynos5420.c | 2 --
 drivers/clk/samsung/clk-exynos5440.c | 2 --
 drivers/clk/samsung/clk-s3c2410.c    | 2 --
 drivers/clk/samsung/clk-s3c2412.c    | 2 --
 drivers/clk/samsung/clk-s3c2443.c    | 2 --
 drivers/clk/samsung/clk-s3c64xx.c    | 2 --
 drivers/clk/samsung/clk-s5pv210.c    | 2 --
 9 files changed, 1 insertion(+), 18 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 7b3d0f975987..2f458233908b 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -1450,8 +1450,6 @@ static void __init exynos4_clk_init(struct device_node *np,
 		panic("%s: failed to map registers\n", __func__);
 
 	ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
-	if (!ctx)
-		panic("%s: unable to allocate context.\n", __func__);
 
 	samsung_clk_of_register_fixed_ext(ctx, exynos4_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 837197db4ffb..d8621cf31786 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -805,8 +805,7 @@ static void __init exynos5250_clk_init(struct device_node *np)
 	}
 
 	ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
-	if (!ctx)
-		panic("%s: unable to allocate context.\n", __func__);
+
 	samsung_clk_of_register_fixed_ext(ctx, exynos5250_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
 			ext_clk_match);
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 92382cef9f90..770c0f007c6b 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -1356,8 +1356,6 @@ static void __init exynos5x_clk_init(struct device_node *np,
 	exynos5x_soc = soc;
 
 	ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
-	if (!ctx)
-		panic("%s: unable to allocate context.\n", __func__);
 
 	samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
index c57cff1e1798..22c73d4a5ee3 100644
--- a/drivers/clk/samsung/clk-exynos5440.c
+++ b/drivers/clk/samsung/clk-exynos5440.c
@@ -125,8 +125,6 @@ static void __init exynos5440_clk_init(struct device_node *np)
 	}
 
 	ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
-	if (!ctx)
-		panic("%s: unable to allocate context.\n", __func__);
 
 	samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks,
 		ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c
index d7b011c1fcf8..d7a1e772d95a 100644
--- a/drivers/clk/samsung/clk-s3c2410.c
+++ b/drivers/clk/samsung/clk-s3c2410.c
@@ -374,8 +374,6 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f,
 	}
 
 	ctx = samsung_clk_init(np, reg_base, NR_CLKS);
-	if (!ctx)
-		panic("%s: unable to allocate context.\n", __func__);
 
 	/* Register external clocks only in non-dt cases */
 	if (!np)
diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c
index effe3736ec6b..ec873ee15d37 100644
--- a/drivers/clk/samsung/clk-s3c2412.c
+++ b/drivers/clk/samsung/clk-s3c2412.c
@@ -265,8 +265,6 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
 	}
 
 	ctx = samsung_clk_init(np, reg_base, NR_CLKS);
-	if (!ctx)
-		panic("%s: unable to allocate context.\n", __func__);
 
 	/* Register external clocks only in non-dt cases */
 	if (!np)
diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c
index 37562783b25e..5e24a17e10e6 100644
--- a/drivers/clk/samsung/clk-s3c2443.c
+++ b/drivers/clk/samsung/clk-s3c2443.c
@@ -400,8 +400,6 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
 	}
 
 	ctx = samsung_clk_init(np, reg_base, NR_CLKS);
-	if (!ctx)
-		panic("%s: unable to allocate context.\n", __func__);
 
 	/* Register external clocks only in non-dt cases */
 	if (!np)
diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c
index 60aa775bd374..a48bd5f17330 100644
--- a/drivers/clk/samsung/clk-s3c64xx.c
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -471,8 +471,6 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
 	}
 
 	ctx = samsung_clk_init(np, reg_base, NR_CLKS);
-	if (!ctx)
-		panic("%s: unable to allocate context.\n", __func__);
 
 	/* Register external clocks. */
 	if (!np)
diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c
index 52302262045d..fd2725710a6f 100644
--- a/drivers/clk/samsung/clk-s5pv210.c
+++ b/drivers/clk/samsung/clk-s5pv210.c
@@ -784,8 +784,6 @@ static void __init __s5pv210_clk_init(struct device_node *np,
 	struct samsung_clk_provider *ctx;
 
 	ctx = samsung_clk_init(np, reg_base, NR_CLKS);
-	if (!ctx)
-		panic("%s: unable to allocate context.\n", __func__);
 
 	samsung_clk_register_mux(ctx, early_mux_clks,
 					ARRAY_SIZE(early_mux_clks));
-- 
2.5.0



From daniel.thompson at linaro.org  Mon May  9 10:39:26 2016
From: daniel.thompson at linaro.org (Daniel Thompson)
Date: Mon,  9 May 2016 18:39:26 +0100
Subject: [PATCH] arm64: kgdb: Match pstate size with gdbserver protocol
Message-ID: <1462815566-15086-1-git-send-email-daniel.thompson@linaro.org>

Current versions of gdb do not interoperate cleanly with kgdb on arm64
systems because gdb and kgdb do not use the same register description.
This patch modifies kgdb to work with recent releases of gdb (>= 7.8.1).

Compatibility with gdb (after the patch is applied) is as follows:

  gdb-7.6 and earlier  Ok
  gdb-7.7 series       Works if user provides custom target description
  gdb-7.8(.0)          Works if user provides custom target description
  gdb-7.8.1 and later  Ok

When commit 44679a4f142b ("arm64: KGDB: Add step debugging support") was
introduced it was paired with a gdb patch that made an incompatible
change to the gdbserver protocol. This patch was eventually merged into
the gdb sources:
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=a4d9ba85ec5597a6a556afe26b712e878374b9dd

The change to the protocol was mostly made to simplify big-endian support
inside the kernel gdb stub. Unfortunately the gdb project released
gdb-7.7.x and gdb-7.8.0 before the protocol incompatibility was identified
and reversed:
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=bdc144174bcb11e808b4e73089b850cf9620a7ee

This leaves us in a position where kgdb still uses the no-longer-used
protocol; gdb-7.8.1, which restored the original behaviour,If was
released on 2014-10-29.

I don't believe it is possible to detect/correct the protocol
incompatiblity which means the kernel must take a view about which
version of the gdb remote protocol is "correct". This patch takes the
view that the original/current version of the protocol is correct
and that version found in gdb-7.7.x and gdb-7.8.0 is anomalous.

Signed-off-by: Daniel Thompson <daniel.thompson at linaro.org>
---

Notes:
    Vijaya: I really hope I have the history lesson in the commit
            message correct! I've done a fair bit of archeology to
    	unpick things.

 arch/arm64/include/asm/kgdb.h | 13 +++++--------
 arch/arm64/kernel/kgdb.c      |  7 ++++++-
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/include/asm/kgdb.h b/arch/arm64/include/asm/kgdb.h
index f69f69c8120c..326fa8f44da5 100644
--- a/arch/arm64/include/asm/kgdb.h
+++ b/arch/arm64/include/asm/kgdb.h
@@ -43,20 +43,17 @@ extern int kgdb_fault_expected;
  * General purpose regs:
  *     r0-r30: 64 bit
  *     sp,pc : 64 bit
- *     pstate  : 64 bit
- *     Total: 34
+ *     pstate  : 32 bit
+ *     Total: 33 + 1
  * FPU regs:
  *     f0-f31: 128 bit
- *     Total: 32
- * Extra regs
  *     fpsr & fpcr: 32 bit
- *     Total: 2
- *
+ *     Total: 32 + 2
  */

-#define _GP_REGS		34
+#define _GP_REGS		33
 #define _FP_REGS		32
-#define _EXTRA_REGS		2
+#define _EXTRA_REGS		3
 /*
  * general purpose registers size in bytes.
  * pstate is only 4 bytes. subtract 4 bytes
diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
index b67531a13136..ec62a4e3c190 100644
--- a/arch/arm64/kernel/kgdb.c
+++ b/arch/arm64/kernel/kgdb.c
@@ -58,7 +58,11 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
 	{ "x30", 8, offsetof(struct pt_regs, regs[30])},
 	{ "sp", 8, offsetof(struct pt_regs, sp)},
 	{ "pc", 8, offsetof(struct pt_regs, pc)},
-	{ "pstate", 8, offsetof(struct pt_regs, pstate)},
+	{ "pstate", 4, offsetof(struct pt_regs, pstate)
+#ifdef CONFIG_CPU_BIG_ENDIAN
+							+ 4
+#endif
+	},
 	{ "v0", 16, -1 },
 	{ "v1", 16, -1 },
 	{ "v2", 16, -1 },
@@ -128,6 +132,7 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
 	memset((char *)gdb_regs, 0, NUMREGBYTES);
 	thread_regs = task_pt_regs(task);
 	memcpy((void *)gdb_regs, (void *)thread_regs->regs, GP_REG_BYTES);
+	dbg_get_reg(33, gdb_regs + GP_REG_BYTES, thread_regs);
 }

 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
--
2.5.5



From Tirumalesh.Chalamarla at cavium.com  Mon May  9 10:51:04 2016
From: Tirumalesh.Chalamarla at cavium.com (Chalamarla, Tirumalesh)
Date: Mon, 9 May 2016 17:51:04 +0000
Subject: [PATCH v3 32/55] KVM: arm/arm64: vgic-new: Add GICv3 MMIO
 handling framework
In-Reply-To: <5730C65D.5000609@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-33-git-send-email-andre.przywara@arm.com>
 <5730C65D.5000609@arm.com>
Message-ID: <9CD2D565-5046-4366-9CB5-A08C5D7B1909@caviumnetworks.com>






On 5/9/16, 10:18 AM, "kvmarm-bounces at lists.cs.columbia.edu on behalf of Marc Zyngier" <kvmarm-bounces at lists.cs.columbia.edu on behalf of marc.zyngier at arm.com> wrote:

>On 06/05/16 11:45, Andre Przywara wrote:
>> Create a new file called vgic-mmio-v3.c and describe the GICv3
>> distributor and redistributor registers there.
>> This adds a special macro to deal with the split of SGI/PPI in the
>> redistributor and SPIs in the distributor, which allows us to reuse
>> the existing GICv2 handlers for those registers which are compatible.
>> Also we provide a function to deal with the registration of the two
>> separate redistributor frames per VCPU.
>> 
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> Reviewed-by: Eric Auger <eric.auger at linaro.org>
>> ---
>> Changelog RFC..v1:
>> - adapt to new MMIO registration approach:
>>   register one device for the distributor and two for each VCPU
>> - implement special handling for private interrupts
>> - remove empty stub functions
>> - make IGROUPR return RAO
>> 
>> Changelog v1 .. v2:
>> - adapt to new framework, introduce vgic-mmio-v3.c
>> - remove userland register access functions (for now)
>> - precompute .len when describing a VGIC register
>> - add missed pointer incrementation on registering redist regions
>> - replace _nyi stub functions with raz/wi versions
>> 
>> Changelog v2 .. v3:
>> - replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h
>> - add prototype and stub code for vgic_register_redist_iodevs
>> - rename register struct variables _rdbase_ and _sgibase_
>> 
>>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
>>  virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
>>  virt/kvm/arm/vgic/vgic.h         |   7 ++
>>  4 files changed, 205 insertions(+)
>>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
>> 
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> new file mode 100644
>> index 0000000..06c7ec5
>> --- /dev/null
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> @@ -0,0 +1,191 @@
>> +/*
>> + * VGICv3 MMIO handling functions
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <linux/irqchip/arm-gic-v3.h>
>> +#include <linux/kvm.h>
>> +#include <linux/kvm_host.h>
>> +#include <kvm/iodev.h>
>> +#include <kvm/arm_vgic.h>
>> +
>> +#include <asm/kvm_emulate.h>
>> +
>> +#include "vgic.h"
>> +#include "vgic-mmio.h"
>> +
>> +/*
>> + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
>> + * redistributors, while SPIs are covered by registers in the distributor
>> + * block. Trying to set private IRQs in this block gets ignored.
>> + * We take some special care here to fix the calculation of the register
>> + * offset.
>> + */
>> +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \
>> +	{								\
>> +		.reg_offset = off,					\
>> +		.bits_per_irq = bpi,					\
>> +		.len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8,		\
>> +		.read = vgic_mmio_read_raz,				\
>> +		.write = vgic_mmio_write_wi,				\
>> +	}, {								\
>> +		.reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8,	\
>> +		.bits_per_irq = bpi,					\
>> +		.len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
>> +		.read = read_ops,					\
>> +		.write = write_ops,					\
>> +	}
>> +
>> +static const struct vgic_register_region vgic_v3_dist_registers[] = {
>> +	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
>> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
>> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
>> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
>> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
>> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
>> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
>> +		vgic_mmio_read_config, vgic_mmio_write_config, 2),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 64),
>> +	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
>> +};
>> +
>> +static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
>> +	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
>> +};
>> +
>> +static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
>> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
>> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
>> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
>> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
>> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
>> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 32),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
>> +		vgic_mmio_read_config, vgic_mmio_write_config, 8),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>> +};
>> +
>> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
>> +{
>> +	dev->regions = vgic_v3_dist_registers;
>> +	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
>> +
>> +	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
>> +
>> +	return SZ_64K;
>> +}
>> +
>> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
>> +{
>> +	int nr_vcpus = atomic_read(&kvm->online_vcpus);
>> +	struct kvm_vcpu *vcpu;
>> +	struct vgic_io_device *devices, *device;
>> +	int c, ret = 0;
>> +
>> +	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
>> +			  GFP_KERNEL);
>> +	if (!devices)
>> +		return -ENOMEM;
>> +
>> +	device = devices;
>> +	kvm_for_each_vcpu(c, vcpu, kvm) {
>> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
>> +		device->base_addr = redist_base_address;
>> +		device->regions = vgic_v3_rdbase_registers;
>> +		device->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
>> +		device->redist_vcpu = vcpu;
>> +
>> +		mutex_lock(&kvm->slots_lock);
>> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
>> +					      redist_base_address,
>> +					      SZ_64K, &device->dev);
>> +		mutex_unlock(&kvm->slots_lock);
>> +
>> +		if (ret)
>> +			break;
>> +
>> +		device++;
>> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
>> +		device->base_addr = redist_base_address + SZ_64K;
>> +		device->regions = vgic_v3_sgibase_registers;
>> +		device->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
>> +		device->redist_vcpu = vcpu;
>> +
>> +		mutex_lock(&kvm->slots_lock);
>> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
>> +					      redist_base_address + SZ_64K,
>> +					      SZ_64K, &device->dev);
>> +		mutex_unlock(&kvm->slots_lock);
>> +		if (ret) {
>> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
>> +						  &devices[c * 2].dev);
>> +			break;
>> +		}
>> +		device++;
>> +		redist_base_address += 2 * SZ_64K;
>> +	}
>
>What I fail to see here is what prevents the redistributor range from
>overlapping with the distributor (or any other device). The kvm IO bus
>is happy with overlapping addresses, but I'm not sure at all that this
>is safe.
>
>Care to shed some light on it?

Added the same question on wrong patch last week, thanks Marc. 
>
>Thanks,
>
>	M.
>-- 
>Jazz is not dead. It just smells funny...
>_______________________________________________
>kvmarm mailing list
>kvmarm at lists.cs.columbia.edu
>https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

From robh at kernel.org  Mon May  9 11:18:29 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 13:18:29 -0500
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <CAPDyKFqpoi03Egfuvd8qJXnn_+FBgPXAb7S4UvkxVs8BA+zwnA@mail.gmail.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <20160505224240.GA31429@rob-hp-laptop>
 <CAPDyKFqpoi03Egfuvd8qJXnn_+FBgPXAb7S4UvkxVs8BA+zwnA@mail.gmail.com>
Message-ID: <20160509181829.GA19687@rob-hp-laptop>

On Mon, May 09, 2016 at 09:46:40AM +0200, Ulf Hansson wrote:
> On 6 May 2016 at 00:42, Rob Herring <robh at kernel.org> wrote:
> > On Thu, May 05, 2016 at 02:34:13PM +0200, Krzysztof Kozlowski wrote:
> >> Hi,
> >>
> >> This is a different, second try to fix usb3503+lan on Odroid U3 board
> >> if it was initialized by bootloader (e.g. for TFTP boot).
> >>
> >> First version:
> >> http://www.spinics.net/lists/linux-usb/msg140042.html
> >>
> >>
> >> Problem
> >> =======
> >> When Odroid U3 (usb3503 + smsc95xx + max77686) boots from network (TFTP),
> >> the usb3503 and LAN smsc95xx do not show up in "lsusb". Hard-reset
> >> is required, e.g. by suspend to RAM. The actual TFTP boot does
> >> not have to happen. Just "usb start" from U-Boot is sufficient.
> >>
> >> From the schematics, the regulator is a supply only to LAN, however
> >> without toggling it off/on, the usb3503 hub won appear neither.
> >>
> >>
> >> Solution
> >> ========
> >> This is very similar to the MMC pwrseq behavior so the idea is to:
> >> 1. Move MMC pwrseq drivers to generic place,
> >
> > You can do that, but I'm going to NAK any use of pwrseq bindings outside
> > of MMC. I think it is the wrong way to do things. The DT should describe
> 
> Huh, I didn't know that was your view of the mmc pwrseq bindings. Why
> didn't you NAK them before?

Unfortunately, either I missed it or it was a time I couldn't spend much 
time on reviews.

> > the devices. If they happen to be "simple" then the core can walk the
> > tree and do any setup. For example, look for "reset-gpios" and toggle
> > that GPIO. There is no need for a special node.
> >
> >> 2. Extend the pwrseq-simple with regulator toggling,
> >> 3. Add support to USB hub and port core for pwrseq,
> >
> > We discussed this for USB already[1] and is why we defined how to add
> > USB child devices. The idea is not to add pwrseq to that.
> 
> I am not familiar with the USB discussion.
> 
> Still, let me give you some more background to the mmc pwrseq. The
> idea from the mmc pwrseq bindings comes from the power-domain DT
> bindings, as I thought these things were a bit related.
> In both cases they are not directly a property of the device, but more
> describing a HW dependency to allow the device to work.

I could see this as a board level power domain. However the difference 
is we are not generally exposing internal SOC details the same way as 
board level components. Perhaps we could extend power domains to board 
level, but that is not what was done here.

> One could probably use a child node instead of a phandle, but that
> wasn't chosen back then. Of course you are the DT expert, but could
> you perhaps tell me why a child node is better for cases like this?

If there is a control path hierarchy, then we try to model that in DT 
with child nodes. In cases of SDIO and USB, there is a clear hierarchy. 
Ignoring the discovery ordering problem, we already have defined ways to 
describe GPIO connections, regulators, etc. to devices. Describing those 
things separately from the device to solve a particular issue that is 
really a kernel limitation is what I don't like.

Rob


From sfr at canb.auug.org.au  Mon May  9 11:29:02 2016
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Tue, 10 May 2016 04:29:02 +1000
Subject: next-20160503 build: 1 failures 12 warnings (next-20160503)
In-Reply-To: <4516208.OQ3mKD6WuY@wuerfel>
References: <E1axZpG-000664-AK@optimist> <2280495.M9rYajvqUJ@wuerfel>
 <20160509205315.631e0c68@canb.auug.org.au>
 <4516208.OQ3mKD6WuY@wuerfel>
Message-ID: <20160510042902.26a8a59a@canb.auug.org.au>

Hi Arnd,

On Mon, 09 May 2016 13:17:19 +0200 Arnd Bergmann <arnd at arndb.de> wrote:
>
> Linus Walleij just picked up the patch I sent last week into the pinctrl tree,
> so it should be fine in tomorrow's linux-next.

Excellent, thanks.

-- 
Cheers,
Stephen Rothwell


From stefan at agner.ch  Mon May  9 11:25:40 2016
From: stefan at agner.ch (Stefan Agner)
Date: Mon, 09 May 2016 11:25:40 -0700
Subject: [PATCH v2 5/5] vf610-soc: Add Vybrid SoC device tree binding
 documentation
In-Reply-To: <CAL_JsqL1qQu_u=6xosP8UmR3oXLawbVz=Hap0wDm7aN4mjK2GA@mail.gmail.com>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
 <65f3a7bd7a9faf1b390644d7c599c69683c753c4.1462171990.git.maitysanchayan@gmail.com>
 <20160504023026.GB5382@rob-hp-laptop>
 <20160505082758.GB18151@Sanchayan-Arch.localdomain>
 <CAL_JsqL1qQu_u=6xosP8UmR3oXLawbVz=Hap0wDm7aN4mjK2GA@mail.gmail.com>
Message-ID: <4ca82be6c1d434c612868b441e9f6e1f@agner.ch>

On 2016-05-09 10:14, Rob Herring wrote:
> On Thu, May 5, 2016 at 3:27 AM,  <maitysanchayan at gmail.com> wrote:
>> Hello Rob,
>>
>> On 16-05-03 21:30:26, Rob Herring wrote:
>>> On Mon, May 02, 2016 at 12:35:04PM +0530, Sanchayan Maity wrote:
>>> > Add device tree binding documentation for Vybrid SoC.
>>> >
>>> > Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
>>> > ---
>>> >  .../bindings/arm/freescale/fsl,vf610-soc.txt       | 35 ++++++++++++++++++++++
>>> >  1 file changed, 35 insertions(+)
>>> >  create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>>> >
>>> > diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>>> > new file mode 100644
>>> > index 0000000..bdd95e8
>>> > --- /dev/null
>>> > +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>>> > @@ -0,0 +1,35 @@
>>> > +Vybrid System-on-Chip
>>> > +---------------------
>>> > +
>>> > +Required properties:
>>> > +
>>> > +- #address-cells: must be 1
>>> > +- #size-cells: must be 1
>>> > +- compatible: "fsl,vf610-soc-bus", "simple-bus"
>>>
>>> If this is a bus, put the file in bindings/bus/...
>>
>> The fsl,vf610-soc-bus binding is used to bind the driver in question with
>> an appropriate compatible node.
>>
>> Basically being a standalone platform driver, there was need of a compatible
>> property to bind on. Introducing a separate device tree node for it's sake
>> didn't seem appropriate so the alteration to SoC node's compatible.
> 
> Ah, so you are designing a node around the needs of a Linux specific
> driver. Don't do that. DT describes the h/w and this node is not a h/w
> block.
> 
> Create a platform device based on a matching SOC compatible string
> instead and make your driver find the information it needs directly
> from the relevant nodes like the ROM node.

That reads like my words a year ago:
https://lkml.org/lkml/2015/5/22/408

Initially pretty much everything was hard-coded in the driver.

Arnd then pushed to use more descriptive in the device tree.

Of course, we should not end up making up relations which are not there
in hardware. We need to find the right balance.

Here is my suggestion:
1. Add "fsl,vf610-soc-bus" as compatible string to the soc node, use it
to bind the "soc bus driver" as a platform driver located in driver/soc/
2. Add ROM as syscon device (it is not erasable ROM memory, hence eeprom
seems not to be appropriate)
3. In the new soc bus driver, search for the relevant nodes using
hardcoded strings:
   - "ocrom" to get the syscon device, read the ROM revision with the
hardcoded offset
   - "ocotp" to get the NVMEM device or "cfg0"/"cfg1" to the cells
directly, read the values using the defined cells.
   - "mscm_cpucfg" is already there as a syscon device

Arnd, Rob, does that sound reasonable?

--
Stefan




From sfr at canb.auug.org.au  Mon May  9 11:36:43 2016
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Tue, 10 May 2016 04:36:43 +1000
Subject: next-20160503 build: 1 failures 12 warnings (next-20160503)
In-Reply-To: <CACRpkdbuJym-7tSMo1gXyWvGCRvvuor8EeCK2bm6=Kb20vTxNA@mail.gmail.com>
References: <E1axZpG-000664-AK@optimist> <20160503141723.GR6292@sirena.org.uk>
 <2280495.M9rYajvqUJ@wuerfel>
 <20160509205315.631e0c68@canb.auug.org.au>
 <CACRpkdbuJym-7tSMo1gXyWvGCRvvuor8EeCK2bm6=Kb20vTxNA@mail.gmail.com>
Message-ID: <20160510043643.1a680d26@canb.auug.org.au>

Hi Linus,

On Mon, 9 May 2016 15:12:51 +0200 Linus Walleij <linus.walleij at linaro.org> wrote:
>
> On Mon, May 9, 2016 at 12:53 PM, Stephen Rothwell <sfr at canb.auug.org.au> wrote:
> 
> > Can we, please, get this fixed ... less than a week to the merge window
> > opening ...  
> 
> Mark poked me with a sharp stick, the patch is applied!
> Sorry for missing this.

Thanks.

-- 
Cheers,
Stephen Rothwell


From sunil.kovvuri at gmail.com  Mon May  9 11:57:17 2016
From: sunil.kovvuri at gmail.com (Sunil Kovvuri)
Date: Mon, 9 May 2016 11:57:17 -0700
Subject: [PATCH 1/1] net: thunderx: avoid exposing kernel stack
In-Reply-To: <1462747578-6147-1-git-send-email-xypron.glpk@gmx.de>
References: <1462747578-6147-1-git-send-email-xypron.glpk@gmx.de>
Message-ID: <CA+sq2Cd7DqDneYjy87qjMen6nMR+_wWxqo3asoQ3sddBAVL_5A@mail.gmail.com>

Thanks for fixing, changes look okay.

Sunil.

On Sun, May 8, 2016 at 3:46 PM, Heinrich Schuchardt <xypron.glpk at gmx.de> wrote:
> Reserved fields should be set to zero to avoid exposing
> bits from the kernel stack.
>
> Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
> ---
>  drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
> index 8acd7c0..0ff8e60 100644
> --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
> +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
> @@ -533,6 +533,7 @@ static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
>                 nicvf_config_vlan_stripping(nic, nic->netdev->features);
>
>         /* Enable Receive queue */
> +       memset(&rq_cfg, 0, sizeof(struct rq_cfg));
>         rq_cfg.ena = 1;
>         rq_cfg.tcp_ena = 0;
>         nicvf_queue_reg_write(nic, NIC_QSET_RQ_0_7_CFG, qidx, *(u64 *)&rq_cfg);
> @@ -565,6 +566,7 @@ void nicvf_cmp_queue_config(struct nicvf *nic, struct queue_set *qs,
>                               qidx, (u64)(cq->dmem.phys_base));
>
>         /* Enable Completion queue */
> +       memset(&cq_cfg, 0, sizeof(struct cq_cfg));
>         cq_cfg.ena = 1;
>         cq_cfg.reset = 0;
>         cq_cfg.caching = 0;
> @@ -613,6 +615,7 @@ static void nicvf_snd_queue_config(struct nicvf *nic, struct queue_set *qs,
>                               qidx, (u64)(sq->dmem.phys_base));
>
>         /* Enable send queue  & set queue size */
> +       memset(&sq_cfg, 0, sizeof(struct sq_cfg));
>         sq_cfg.ena = 1;
>         sq_cfg.reset = 0;
>         sq_cfg.ldwb = 0;
> @@ -649,6 +652,7 @@ static void nicvf_rbdr_config(struct nicvf *nic, struct queue_set *qs,
>
>         /* Enable RBDR  & set queue size */
>         /* Buffer size should be in multiples of 128 bytes */
> +       memset(&rbdr_cfg, 0, sizeof(struct rbdr_cfg));
>         rbdr_cfg.ena = 1;
>         rbdr_cfg.reset = 0;
>         rbdr_cfg.ldwb = 0;
> --
> 2.1.4
>


From davem at davemloft.net  Mon May  9 12:06:34 2016
From: davem at davemloft.net (David Miller)
Date: Mon, 09 May 2016 15:06:34 -0400 (EDT)
Subject: [RESEND PATCH v6 0/6] Add Ethernet support on STM32F429
In-Reply-To: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
References: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
Message-ID: <20160509.150634.213732321950308841.davem@davemloft.net>

From: Alexandre TORGUE <alexandre.torgue at gmail.com>
Date: Mon,  9 May 2016 12:31:33 +0200

> STM32F429 Chip embeds a Synopsys 3.50a MAC IP.
> This series:
>  -enhance current stmmac driver to control it (code already
> available) and adds basic glue for STM32F429 chip.
>  -Enable basic Net config in kernel.

I assume this will go via the ARM tree, for the networking bits:

Acked-by: David S. Miller <davem at davemloft.net>


From robh at kernel.org  Mon May  9 12:11:24 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 14:11:24 -0500
Subject: [PATCH 1/5] dt: bindings: add means to control flags of specific
 clocks
In-Reply-To: <1462463608-22940-2-git-send-email-kernel@martin.sperl.org>
References: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
 <1462463608-22940-2-git-send-email-kernel@martin.sperl.org>
Message-ID: <20160509191124.GA31621@rob-hp-laptop>

On Thu, May 05, 2016 at 03:53:24PM +0000, kernel at martin.sperl.org wrote:
> From: Martin Sperl <kernel at martin.sperl.org>
> 
> Add documentation for "brcm,clock-index" and "brcm,clock-flags"
> which allows to set flags to enable the use of parent clocks
> that may be different from the default.

assigned-clocks provides a way to do this already though that does mean 
exposing all the parents to DT. Does that not work for you?

> In the future this may also contain flags that would allow
> enabling higher order mash dividers.
> 
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
> ---
>  .../devicetree/bindings/clock/brcm,bcm2835-cprman.txt      | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt
> index e56a1df..cbcca56 100644
> --- a/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt
> +++ b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt
> @@ -18,6 +18,15 @@ Required properties:
>  - reg:		Specifies base physical address and size of the registers
>  - clocks:	The external oscillator clock phandle
> 
> +Optional properties:
> +- brcm,clock-index: clock id to which the corresponding brcm,clock-flags
> +		      value applies
> +- brcm,clock-flags: flags for the specific clock id given in
> +		      brcm,clock-index - the bits are defined in
> +		      include/dt-bindings/clock/bcm2835.h
> +		      of which the bottom 16 bits are reserved for
> +		      parent clock selection.

These are an array or single value?

I tend to think these should be generic properties or not at all. I'd 
like to hear Mike's and/or Stephen's opinion on it.

Rob


From robh at kernel.org  Mon May  9 12:26:41 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 14:26:41 -0500
Subject: [PATCH v2 1/2] Documentation: DT: bindings: Add Broadcom STB
 PCIe bindings
In-Reply-To: <1462475700-1654-2-git-send-email-f.fainelli@gmail.com>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
 <1462475700-1654-2-git-send-email-f.fainelli@gmail.com>
Message-ID: <20160509192641.GA4936@rob-hp-laptop>

On Thu, May 05, 2016 at 12:14:59PM -0700, Florian Fainelli wrote:
> From: Jim Quinlan <jim2101024 at gmail.com>
> 
> This patchs adds the Device Tree bindings for the Broadcom STB PCIe root
> complex hardware.
> 
> Signed-off-by: Jim Quinlan <jim2101024 at gmail.com>
> Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
> ---
> Changes in v2:
> 
> - rewrite the binding document almost from scratch to include many more
>   references to existing documents
> - describe missing properties
> - give better examples
> 
>  .../devicetree/bindings/pci/brcm,brcmstb-pcie.txt  | 98 ++++++++++++++++++++++
>  1 file changed, 98 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
> 
> diff --git a/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
> new file mode 100644
> index 000000000000..3682b0f0bc26
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
> @@ -0,0 +1,98 @@
> +Broadcom STB PCIe Host Controller Device Tree Bindings
> +
> +This document describes the binding of the PCIe Root Complex hardware found in
> +Broadcom Set Top Box System-on-Chips such as BCM7425 (MIPS), BCM7435 (MIPS) and
> +BCM7445 (ARMv7).
> +
> +Required properties:
> +- compatible: must be one of: "brcm,bcm7425-pcie"
> +			      "brcm,bcm7435-pcie"
> +			      "brcm,bcm7445-pcie"
> +
> +- reg: specifies the physical base address of the controller registers and
> +  its length
> +
> +- interrupt-parent: must be a reference (phandle) to the parent interrupt
> +  controller in the system (7038-l1-intc on MIPS, GIC on ARM/ARM64)
> +
> +- interrrupts: first interrupt must be the Level 1 interrupt number corresponding
> +  to the main PCIe RC interrupt, second interrupt must be the MSI interrupt
> +  See the interrupt-parent documentation for the number of cells and their meaning:
> +  MIPS: Documentation/devicetree/bindings/interrupt-controller/brcm,bcm7038-l1-intc.txt
> +  ARM/ARM64: Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
> +
> +- interrupt-names: must be "pcie", and if present "msi"
> +
> +- interrupt-map: see pci.txt
> +
> +- interrupt-map-mask: see pci.txt
> +
> +- #address-cells: must be set to <3>, see pci.txt
> +
> +- #size-cells: must be set to <2>, see pci.txt
> +
> +- ranges: ranges for the PCI outbound windows, no I/O or prefetchable windows
> +  must be specified here, only non-prefetchable. 32-bits windows or 64-bits
> +  windows are allowed based on the host processor's capabilities (ARM w/ LPAE,
> +  ARM64).
> +
> +- #interrupt-cells: set to <1>, see pci.txt
> +
> +- brcm,log2-scb-sizes: log2 size of the SCB window that is mapped to PCIe space
> +  there must be exactly one value per memory controller present in the system
> +  (ranges from 1 to 3)
> +
> +Optional properties:
> +
> +- msi-controller: indicates that this is a MSI controller node (when supported)
> +
> +- clocks: phandle to the functional clock that feeds into the PCIe RC block
> +
> +- clock-names: the name(s) of the clocks specified in 'clocks'.  Note
> +  that if the 'clocks' property is given, 'clock-names' is mandatory,
> +  and the name of the clock is expected to be "pcie".
> +
> +- brcm,ssc: boolean that indicates usage of spread-spectrum clocking

Shouldn't this be a property of the phy? Is there no separate phy to 
control?

> +
> +- brcm,gen: integer that indicates desired forced generation of link: 1 => 2.5
> +  Gbps, 2 => 5.0 Gbps, 3 => 8.0 Gbps. Will override the auto-negotation if
> +  specified.
> +
> +- <*>-supply: see Documentation/devicetree/bindings/regulator/regulator.txt
> +
> +- <*>-supply-names: see Documentation/devicetree/bindings/regulator/regulator.txt
> +
> +Example Node:
> +
> +This example assumes that the top-level #address-cells = <2> and #size-cells =
> +<2>, e.g: ARM LPAE configuration.
> +
> +	pcie0: pcie-controller at f0460000 {
> +		reg = <0x0 0xf0460000 0x0 0x9310>;
> +		interrupts = <0x0 0x33 0x4>, <0x0 0x34, 0x4>;
                                                      ^
typo

> +		interrupt-names = "pcie", "msi";
> +		compatible = "brcm,bcm7445-pcie";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +
> +		/* Two non-prefetchable 32-bits memory space, each of 128MB
> + 		 * with the following mapping:
> +		 * PCIe address		=> CPU physical address space
> +		 * 0x00_0000_0000	=> 0x00_C000_0000
> +		 * 0x00_0800_0000	=> 0x00_C800_0000
> +		 */
> +		ranges = <0x02000000 0x00000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x08000000>,
> +			 <0x02000000 0x00000000 0x08000000 0x00000000 0xc8000000 0x00000000 0x08000000>;
> +		#interrupt-cells = <1>;
> +		interrupt-map-mask = <0xf800 0 0 7>;
> +		interrupt-map = <0 0 0 1 &intc 47 3
> +				 0 0 0 2 &intc 48 3
> +				 0 0 0 3 &intc 49 3
> +				 0 0 0 4 &intc 50 3>;
> +		clocks = <&pcie0>;
> +		clock-names = "pcie";
> +		brcm,ssc;
> +		brcm,log2-scb-sizes = <0x1e 0x1e 0x1e>;
> +		vreg-wifi-pwr-supply-names = "vreg-wifi-pwr";
> +		vreg-wifi-pwr-supply = <&vreg-wifi-pwr>;

The supply for the PCIE RC is called "vreg-wifi-pwr"? Seems a bit 
strange.

Rob


From tony at atomide.com  Mon May  9 12:36:24 2016
From: tony at atomide.com (Tony Lindgren)
Date: Mon, 9 May 2016 12:36:24 -0700
Subject: [PATCH 5/7] ARM: OMAP: dmtimer: Do not call PM runtime functions
 when not needed.
In-Reply-To: <1462634508-24961-6-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <1462634508-24961-6-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <20160509193624.GH5995@atomide.com>

* Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com> [160507 08:24]:
> once omap_dm_timer_start() is called, which calls omap_dm_timer_enable()
> and thus pm_runtime_get_sync(), it doesn't make sense to call PM runtime
> functions again before omap_dm_timer_stop is called(). Otherwise PM runtime
> functions called in omap_dm_timer_enable/disable lead to long and unneeded
> delays.
> 
> Fix that by implementing an "enabled" counter, so the PM runtime functions
> get called only when really needed.
> 
> Without that patch Nokia N900 IR TX driver (ir-rx51) does not function.

We should use pm_runtime for the refcounting though and call PM runtime
unconditionally. Can you try to follow the standard PM runtime usage
like this:

init:
pm_runtime_use_autosuspend(&timer->pdev->dev);
pm_runtime_set_autosuspend_delay(&timer->pdev->dev, 200);
pm_runtime_enable(&timer->pdev->dev);
...
enable:
pm_runtime_get_sync(&timer->pdev->dev);
...
disable:
pm_runtime_mark_last_busy(&timer->pdev->dev);
pm_runtime_put_autosuspend(&timer->pdev->dev);
...
exit:
pm_runtime_dont_use_autosuspend(&timer->pdev->dev);
pm_runtime_put_sync(&timer->pdev->dev);
pm_runtime_disable(&timer->pdev->dev);

No idea what the timeout should be, maybe less than 200 ms. Also we need
to test that off idle still works with timer1, that might need special
handling.

Regards,

Tony


From javier at osg.samsung.com  Mon May  9 12:37:08 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 15:37:08 -0400
Subject: [PATCH v2 01/22] dt-bindings: clock: Add license and reformat
 Exynos5410 clock IDs
In-Reply-To: <1462734367-5619-2-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-2-git-send-email-krzk@kernel.org>
Message-ID: <93dcd991-43c5-7491-e747-654ae37e6065@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> Add license and copyrights (file introduced in 2014) to header with
> Exynos5410 clock IDs. Additionally reformat it to improve readability.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From tony at atomide.com  Mon May  9 12:40:54 2016
From: tony at atomide.com (Tony Lindgren)
Date: Mon, 9 May 2016 12:40:54 -0700
Subject: NFSroot hangs with bad unlock balance in Linux next
In-Reply-To: <20160509153932.GJ2694@ZenIV.linux.org.uk>
References: <20160505220344.GE5995@atomide.com>
 <20160508141629.GF2694@ZenIV.linux.org.uk>
 <20160509073235.GI2694@ZenIV.linux.org.uk>
 <CANn89iK5H-SokYE1r+OO3sPmQ1vpGqYGbE4x1QLn44wdyvH0cw@mail.gmail.com>
 <20160509151219.GF5995@atomide.com>
 <20160509152138.GG5995@atomide.com>
 <20160509153932.GJ2694@ZenIV.linux.org.uk>
Message-ID: <20160509194054.GI5995@atomide.com>

* Al Viro <viro at ZenIV.linux.org.uk> [160509 08:41]:
> On Mon, May 09, 2016 at 08:21:38AM -0700, Tony Lindgren wrote:
> 
> > Looks like with both patches applied I still also get this eventually:
> > 
> > =====================================
> > [ BUG: bad unlock balance detected! ]
> > 4.6.0-rc7-next-20160509+ #1264 Not tainted
> > -------------------------------------
> 
> Lockdep warnings are noise.  To make them STFU try the following incremental;
> I'll fold it into #work.lookups and #for-next.  Note that it will do nothing
> to hangs - those are completely unrelated and you need Eric's patch to deal
> with them.

OK yeah that helps thanks:

Tested-by: Tony Lindgren <tony at atomide.com>

> diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
> index d367b06..1868246 100644
> --- a/fs/nfs/unlink.c
> +++ b/fs/nfs/unlink.c
> @@ -64,7 +64,7 @@ static void nfs_async_unlink_release(void *calldata)
>  	struct dentry *dentry = data->dentry;
>  	struct super_block *sb = dentry->d_sb;
>  
> -	up_read(&NFS_I(d_inode(dentry->d_parent))->rmdir_sem);
> +	up_read_non_owner(&NFS_I(d_inode(dentry->d_parent))->rmdir_sem);
>  	d_lookup_done(dentry);
>  	nfs_free_unlinkdata(data);
>  	dput(dentry);
> @@ -117,10 +117,10 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
>  	struct inode *dir = d_inode(dentry->d_parent);
>  	struct dentry *alias;
>  
> -	down_read(&NFS_I(dir)->rmdir_sem);
> +	down_read_non_owner(&NFS_I(dir)->rmdir_sem);
>  	alias = d_alloc_parallel(dentry->d_parent, &data->args.name, &data->wq);
>  	if (IS_ERR(alias)) {
> -		up_read(&NFS_I(dir)->rmdir_sem);
> +		up_read_non_owner(&NFS_I(dir)->rmdir_sem);
>  		return 0;
>  	}
>  	if (!d_in_lookup(alias)) {
> @@ -142,7 +142,7 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
>  			ret = 0;
>  		spin_unlock(&alias->d_lock);
>  		dput(alias);
> -		up_read(&NFS_I(dir)->rmdir_sem);
> +		up_read_non_owner(&NFS_I(dir)->rmdir_sem);
>  		/*
>  		 * If we'd displaced old cached devname, free it.  At that
>  		 * point dentry is definitely not a root, so we won't need


From javier at osg.samsung.com  Mon May  9 12:41:02 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 15:41:02 -0400
Subject: [PATCH v2 02/22] dt-bindings: clock: Add PWM and USB clock IDs to
 Exynos5410
In-Reply-To: <1462734367-5619-3-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-3-git-send-email-krzk@kernel.org>
Message-ID: <b73e9ad3-6c5f-e4e1-8bcf-228cf889c05e@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> Add IDs for PWM and USB clocks to Exynos5410. Use the same number as for
> Exynos5420 just in case in future these drivers were merged.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From robh at kernel.org  Mon May  9 12:41:15 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 14:41:15 -0500
Subject: [PATCH 3/6] docs: Document BCM23550 bindings
In-Reply-To: <1462481334-8943-4-git-send-email-chris.brand@broadcom.com>
References: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
 <1462481334-8943-4-git-send-email-chris.brand@broadcom.com>
Message-ID: <20160509194115.GA11594@rob-hp-laptop>

On Thu, May 05, 2016 at 01:48:51PM -0700, Chris Brand wrote:
> Add binding document for Broadcom BCM23550 SoC.
> 
> BCM23550 has a Cluster Dormant Control IP block that holds cores
> in an idle state. Introduce a new CPU enable method in which the CDC is
> accessed to bring the core online.
> 
> Signed-off-by: Chris Brand <chris.brand at broadcom.com>
> ---
>  .../bindings/arm/bcm/brcm,bcm23550-cpu-method.txt  | 36 ++++++++++++++++++++++
>  .../devicetree/bindings/arm/bcm/brcm,bcm23550.txt  | 15 +++++++++
>  Documentation/devicetree/bindings/arm/cpus.txt     |  1 +
>  3 files changed, 52 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt
>  create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt
> new file mode 100644
> index 000000000000..b1b16872bbca
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt
> @@ -0,0 +1,36 @@
> +Broadcom Kona Family CPU Enable Method
> +--------------------------------------
> +This binding defines the enable method used for starting secondary
> +CPUs in the following Broadcom SoCs:
> +  BCM23550
> +
> +The enable method is specified by defining the following required
> +properties in the "cpu" device tree node:
> +  - enable-method = "brcm,bcm23550-cpu-method";

"-cpu-method" is a bit redundant. brcm,bc23550 is probably sufficient.

> +  - secondary-boot-reg = <...>;
> +
> +The secondary-boot-reg property is a u32 value that specifies the
> +physical address of the register used to request the ROM holding pen
> +code release a secondary CPU.  The value written to the register is
> +formed by encoding the target CPU id into the low bits of the
> +physical start address it should jump to.


From tony at atomide.com  Mon May  9 12:42:59 2016
From: tony at atomide.com (Tony Lindgren)
Date: Mon, 9 May 2016 12:42:59 -0700
Subject: [PATCH] ARM: dts: Fix igepv5 audiopwon-gpio
In-Reply-To: <57304CB3.5010601@collabora.com>
References: <1462474581-13865-1-git-send-email-tony@atomide.com>
 <1b37fbdd-67f0-e9e3-d442-bdc0bd74397b@ti.com>
 <57304CB3.5010601@collabora.com>
Message-ID: <20160509194258.GJ5995@atomide.com>

* Enric Balletbo i Serra <enric.balletbo at collabora.com> [160509 01:41]:
> 
> 
> On 09/05/16 10:34, Peter Ujfalusi wrote:
> > On 05/05/16 21:56, Tony Lindgren wrote:
> >> Playing audio works on omap5-uevm, but produces an "Unhandled fault:
> >> imprecise external abort (0x1406) at 0x00000000" error on igepv5.
> >>
> >> Looks like the twl6040 audpwron GPIO pin is different for these
> >> boards. Let's fix the issue by configuring the audpwron in the
> >> board specific dts file.
> >>
> >> Cc: Agust? Fontquerni <af at iseebcn.com>
> >> Cc: Eduard Gavin <egavin at iseebcn.com>
> >> Cc: Enric Balletbo i Serra <eballetbo at iseebcn.com>
> 
> 
> Hey, can you change the email address for this one
> 
> Cc: Enric Balletbo i Serra <eballetbo at gmail.com>

OK. Maybe you guys should send a patch for MAINTAINERS entry
for this board so it's easier to figure out who to send the
emails to?

Regards,

Tony


From tony at atomide.com  Mon May  9 12:44:32 2016
From: tony at atomide.com (Tony Lindgren)
Date: Mon, 9 May 2016 12:44:32 -0700
Subject: [PATCH] ARM: dts: Fix igepv5 audiopwon-gpio
In-Reply-To: <1b37fbdd-67f0-e9e3-d442-bdc0bd74397b@ti.com>
References: <1462474581-13865-1-git-send-email-tony@atomide.com>
 <1b37fbdd-67f0-e9e3-d442-bdc0bd74397b@ti.com>
Message-ID: <20160509194431.GK5995@atomide.com>

* Peter Ujfalusi <peter.ujfalusi at ti.com> [160509 01:36]:
> On 05/05/16 21:56, Tony Lindgren wrote:
> > Playing audio works on omap5-uevm, but produces an "Unhandled fault:
> > imprecise external abort (0x1406) at 0x00000000" error on igepv5.
> > 
> > Looks like the twl6040 audpwron GPIO pin is different for these
> > boards. Let's fix the issue by configuring the audpwron in the
> > board specific dts file.
> > 
> > Cc: Agust? Fontquerni <af at iseebcn.com>
> > Cc: Eduard Gavin <egavin at iseebcn.com>
> > Cc: Enric Balletbo i Serra <eballetbo at iseebcn.com>
> > Cc: Peter Ujfalusi <peter.ujfalusi at ti.com>
> > Signed-off-by: Tony Lindgren <tony at atomide.com>
> > ---
> >  arch/arm/boot/dts/omap5-board-common.dtsi |  3 ++-
> >  arch/arm/boot/dts/omap5-igep0050.dts      | 10 ++++++++++
> >  arch/arm/boot/dts/omap5-uevm.dts          | 10 ++++++++++
> >  3 files changed, 22 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi
> > index 2eea26c..23b1d7c 100644
> > --- a/arch/arm/boot/dts/omap5-board-common.dtsi
> > +++ b/arch/arm/boot/dts/omap5-board-common.dtsi
> > @@ -642,7 +642,8 @@
> >  		pinctrl-0 = <&twl6040_pins>;
> >  
> >  		interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
> > -		ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
> > +
> > +		/* audpwron gpio defined in the board specific dts */
> >  
> >  		vio-supply = <&smps7_reg>;
> >  		v2v1-supply = <&smps9_reg>;
> > diff --git a/arch/arm/boot/dts/omap5-igep0050.dts b/arch/arm/boot/dts/omap5-igep0050.dts
> > index 72ff6a4..673cdfa 100644
> > --- a/arch/arm/boot/dts/omap5-igep0050.dts
> > +++ b/arch/arm/boot/dts/omap5-igep0050.dts
> > @@ -58,3 +58,13 @@
> >  		<&gpio7 3 0>;		/* 195, SDA */
> >  };
> >  
> > +&twl6040 {
> > +	ti,audpwron-gpio = <&gpio5 16 GPIO_ACTIVE_HIGH>;  /* gpio line 144 */
> 
> BTW: how do you know that gpio144 is used as audpwron GPIO on igepv5?

>From looking at the ISEE git tree. But it would be best for the ISEE guys
to review the patch.

> > +};
> > +
> > +&twl6040_pins {
> > +	pinctrl-single,pins = <
> > +		OMAP5_IOPAD(0x1c4, PIN_OUTPUT | MUX_MODE6)	/* mcspi1_somi.gpio5_144 */
> > +		OMAP5_IOPAD(0x1ca, PIN_OUTPUT | MUX_MODE6)	/* perslimbus2_clock.gpio5_145 */
> 
> What does the gpio145 is used for?

No idea without seeing the schematics, also from ISEE git tree so should
be reviewed.

Regards,

Tony


From okaya at codeaurora.org  Mon May  9 12:45:13 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Mon, 9 May 2016 15:45:13 -0400
Subject: [PATCH V4 1/2] vfio, platform: add support for ACPI during probe
 and reset
In-Reply-To: <5730B0FA.1040303@linaro.org>
References: <1462136872-17590-1-git-send-email-okaya@codeaurora.org>
 <1462136872-17590-2-git-send-email-okaya@codeaurora.org>
 <5730B0FA.1040303@linaro.org>
Message-ID: <5730E8C9.8060707@codeaurora.org>

On 5/9/2016 11:47 AM, Eric Auger wrote:
> Hi Sinan,
> On 05/01/2016 11:07 PM, Sinan Kaya wrote:
>> The code is using the compatible DT string to associate a reset driver with
>> the actual device itself. The compatible string does not exist on ACPI
>> based systems. HID is the unique identifier for a device driver instead.
>>
>> When ACPI is enabled, the change will query the presence of _RST method
>> and will call it instead of querying an external reset driver.
>>
>> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
>> ---
>>  drivers/vfio/platform/vfio_platform_common.c  | 176 +++++++++++++++++++++-----
>>  drivers/vfio/platform/vfio_platform_private.h |   7 +-
>>  2 files changed, 147 insertions(+), 36 deletions(-)
>>
>> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
>> index e65b142..528ec04 100644
>> --- a/drivers/vfio/platform/vfio_platform_common.c
>> +++ b/drivers/vfio/platform/vfio_platform_common.c
>> @@ -13,6 +13,7 @@
>>   */
>>  
>>  #include <linux/device.h>
>> +#include <linux/acpi.h>
>>  #include <linux/iommu.h>
>>  #include <linux/module.h>
>>  #include <linux/mutex.h>
>> @@ -41,7 +42,7 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
>>  		if (!strcmp(iter->compat, compat) &&
>>  			try_module_get(iter->owner)) {
>>  			*module = iter->owner;
>> -			reset_fn = iter->reset;
>> +			reset_fn = iter->of_reset;
>>  			break;
>>  		}
>>  	}
>> @@ -49,20 +50,111 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
>>  	return reset_fn;
>>  }
>>  
>> -static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>> +
>> +#ifdef CONFIG_ACPI
>> +int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
>> +			     struct device *dev)
>>  {
>> -	vdev->reset = vfio_platform_lookup_reset(vdev->compat,
>> -						&vdev->reset_module);
>> -	if (!vdev->reset) {
>> -		request_module("vfio-reset:%s", vdev->compat);
>> -		vdev->reset = vfio_platform_lookup_reset(vdev->compat,
>> -							 &vdev->reset_module);
>> +	struct acpi_device *adev = ACPI_COMPANION(dev);
>> +
>> +	if (acpi_disabled)
>> +		return -ENODEV;
>> +
>> +	if (!adev)
>> +		return -ENODEV;
>> +
>> +	vdev->acpihid = acpi_device_hid(adev);
>> +	if (!vdev->acpihid) {
>> +		pr_err("VFIO: cannot find ACPI HID for %s\n",
>> +		       vdev->name);
>> +		return -ENODEV;
>>  	}
>> +	return 0;
>> +}
>> +
>> +static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
>> +{
>> +	struct device *dev = vdev->device;
>> +	acpi_handle handle = ACPI_HANDLE(dev);
>> +	acpi_status acpi_ret;
>> +	unsigned long long val;
>> +
>> +	acpi_ret = acpi_evaluate_integer(handle, "_RST", NULL, &val);
>> +	if (ACPI_FAILURE(acpi_ret))
>> +		return -EINVAL;
>> +
>> +	return 0;
>> +}
>> +
>> +static int vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
>> +{
>> +	struct device *dev = vdev->device;
>> +	acpi_handle handle = ACPI_HANDLE(dev);
>> +
>> +	if (acpi_has_method(handle, "_RST"))
>> +		return 0;
> Can't you directly return acpi_has_method(handle, "_RST"), hence return
> a boolean?

Makes sense. I'll do that on the next post. 

>> +
>> +	return -EINVAL;
>> +}
>> +#else
>> +int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
>> +			     struct device *dev)
>> +{
>> +	return -EINVAL;
>> +}
>> +
>> +static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
>> +{
>> +	return -EINVAL;
>> +}
>> +
>> +static int vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
>> +{
>> +	return -EINVAL;
>> +}
>> +#endif
>> +
>> +static int vfio_platform_has_reset(struct vfio_platform_device *vdev)
>> +{
> return a boolean?

OK

>> +	if (vdev->acpihid)
>> +		return vfio_platform_acpi_has_reset(vdev);
>> +
>> +	if (vdev->of_reset)
>> +		return 0;
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static int vfio_platform_get_reset(struct vfio_platform_device *vdev)
>> +{
>> +	int rc;
>> +
>> +	if (vdev->acpihid)
>> +		return vfio_platform_acpi_has_reset(vdev);
>> +
>> +	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
>> +						    &vdev->reset_module);
>> +	if (vdev->of_reset)
>> +		return 0;
>> +
>> +	rc = request_module("vfio-reset:%s", vdev->compat);
>> +	if (rc)
>> +		return rc;
>> +
>> +	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
>> +						    &vdev->reset_module);
>> +	if (vdev->of_reset)
>> +		return 0;
>> +
>> +	return -EINVAL;
>>  }
>>  
>>  static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
>>  {
>> -	if (vdev->reset)
>> +	if (vdev->acpihid)
>> +		return;
>> +
>> +	if (vdev->of_reset)
>>  		module_put(vdev->reset_module);
>>  }
>>  
>> @@ -134,6 +226,20 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
>>  	kfree(vdev->regions);
>>  }
>>  
>> +static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
>> +{
>> +	if (vdev->of_reset) {
>> +		dev_info(vdev->device, "reset\n");
>> +		vdev->of_reset(vdev);
> return vdev->of_reset(vdev) to align with acpi reset behavior.

OK. I didn't realize it was returning a value. 

>> +		return 0;
>> +	} else if (vdev->acpihid) {
>> +		return vfio_platform_acpi_call_reset(vdev);
> I think it would make sense to have the same dev_info traces for dt and
> acpi.
>> +	}
>> +
>> +	dev_warn(vdev->device, "no reset function found!\n");
>> +	return -EINVAL;
>> +}
>> +
>>  static void vfio_platform_release(void *device_data)
>>  {
>>  	struct vfio_platform_device *vdev = device_data;
>> @@ -141,12 +247,7 @@ static void vfio_platform_release(void *device_data)
>>  	mutex_lock(&driver_lock);
>>  
>>  	if (!(--vdev->refcnt)) {
>> -		if (vdev->reset) {
>> -			dev_info(vdev->device, "reset\n");
>> -			vdev->reset(vdev);
>> -		} else {
>> -			dev_warn(vdev->device, "no reset function found!\n");
>> -		}
>> +		vfio_platform_call_reset(vdev);
>>  		vfio_platform_regions_cleanup(vdev);
>>  		vfio_platform_irq_cleanup(vdev);
>>  	}
>> @@ -175,12 +276,9 @@ static int vfio_platform_open(void *device_data)
>>  		if (ret)
>>  			goto err_irq;
>>  
>> -		if (vdev->reset) {
>> -			dev_info(vdev->device, "reset\n");
>> -			vdev->reset(vdev);
>> -		} else {
>> -			dev_warn(vdev->device, "no reset function found!\n");
>> -		}
>> +		ret = vfio_platform_call_reset(vdev);
>> +		if (ret)
>> +			goto err_irq;
> This change should be in next patch since if you fail finding a reset
> function, you clean things up, mandating a reset function to exist.
> 
> Also in case the reset function fails you change the behavior which is
> not detailed in the commit msg.

I admitted this on another patch. Yes, I'll fix this.

>>  	}
>>  
>>  	vdev->refcnt++;
>> @@ -213,7 +311,7 @@ static long vfio_platform_ioctl(void *device_data,
>>  		if (info.argsz < minsz)
>>  			return -EINVAL;
>>  
>> -		if (vdev->reset)
>> +		if (!vfio_platform_has_reset(vdev))
>>  			vdev->flags |= VFIO_DEVICE_FLAGS_RESET;
>>  		info.flags = vdev->flags;
>>  		info.num_regions = vdev->num_regions;
>> @@ -312,10 +410,7 @@ static long vfio_platform_ioctl(void *device_data,
>>  		return ret;
>>  
>>  	} else if (cmd == VFIO_DEVICE_RESET) {
>> -		if (vdev->reset)
>> -			return vdev->reset(vdev);
>> -		else
>> -			return -EINVAL;
>> +		return vfio_platform_call_reset(vdev);
> Here you also change the behavior: before, in case the dt reset failed
> we returned an error. Now we return 0.

Yes, I'll fix it. 
> 
> To me this patch would deserve to be split into 2 parts: ACPI probing
> without reset and then ACPI reset. In case you change the behavior of
> existing dt reset, please put that in a separate patch.

Sure, I'll move vfio_platform_probe_common changes to a seperate patch.
I'll try to break it as much as I can before the post.

> 
> Best Regards
> 
> Eric
>>  	}
>>  
>>  	return -ENOTTY;
>> @@ -544,6 +639,21 @@ static const struct vfio_device_ops vfio_platform_ops = {
>>  	.mmap		= vfio_platform_mmap,
>>  };
>>  
>> +int vfio_platform_of_probe(struct vfio_platform_device *vdev,
>> +			   struct device *dev)
>> +{
>> +	int ret;
>> +
>> +	ret = device_property_read_string(dev, "compatible",
>> +					  &vdev->compat);
>> +	if (ret) {
>> +		pr_err("VFIO: cannot retrieve compat for %s\n",
>> +			vdev->name);
>> +		return ret;
>> +	}
>> +	return 0;
>> +}
>> +
>>  int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>>  			       struct device *dev)
>>  {
>> @@ -553,14 +663,14 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>>  	if (!vdev)
>>  		return -EINVAL;
>>  
>> -	ret = device_property_read_string(dev, "compatible", &vdev->compat);
>> -	if (ret) {
>> -		pr_err("VFIO: cannot retrieve compat for %s\n", vdev->name);
>> -		return -EINVAL;
>> -	}
>> +	ret = vfio_platform_acpi_probe(vdev, dev);
>> +	if (ret)
>> +		ret = vfio_platform_of_probe(vdev, dev);
>>  
>> -	vdev->device = dev;
>> +	if (ret)
>> +		return ret;
>>  
>> +	vdev->device = dev;
>>  	group = iommu_group_get(dev);
>>  	if (!group) {
>>  		pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
>> @@ -611,7 +721,7 @@ void vfio_platform_unregister_reset(const char *compat,
>>  
>>  	mutex_lock(&driver_lock);
>>  	list_for_each_entry_safe(iter, temp, &reset_list, link) {
>> -		if (!strcmp(iter->compat, compat) && (iter->reset == fn)) {
>> +		if (!strcmp(iter->compat, compat) && (iter->of_reset == fn)) {
>>  			list_del(&iter->link);
>>  			break;
>>  		}
>> diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
>> index 42816dd..ba9e4f8 100644
>> --- a/drivers/vfio/platform/vfio_platform_private.h
>> +++ b/drivers/vfio/platform/vfio_platform_private.h
>> @@ -58,6 +58,7 @@ struct vfio_platform_device {
>>  	struct mutex			igate;
>>  	struct module			*parent_module;
>>  	const char			*compat;
>> +	const char			*acpihid;
>>  	struct module			*reset_module;
>>  	struct device			*device;
>>  
>> @@ -71,7 +72,7 @@ struct vfio_platform_device {
>>  	struct resource*
>>  		(*get_resource)(struct vfio_platform_device *vdev, int i);
>>  	int	(*get_irq)(struct vfio_platform_device *vdev, int i);
>> -	int	(*reset)(struct vfio_platform_device *vdev);
>> +	int	(*of_reset)(struct vfio_platform_device *vdev);
>>  };
>>  
>>  typedef int (*vfio_platform_reset_fn_t)(struct vfio_platform_device *vdev);
>> @@ -80,7 +81,7 @@ struct vfio_platform_reset_node {
>>  	struct list_head link;
>>  	char *compat;
>>  	struct module *owner;
>> -	vfio_platform_reset_fn_t reset;
>> +	vfio_platform_reset_fn_t of_reset;
>>  };
>>  
>>  extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>> @@ -103,7 +104,7 @@ extern void vfio_platform_unregister_reset(const char *compat,
>>  static struct vfio_platform_reset_node __reset ## _node = {	\
>>  	.owner = THIS_MODULE,					\
>>  	.compat = __compat,					\
>> -	.reset = __reset,					\
>> +	.of_reset = __reset,					\
>>  };								\
>>  __vfio_platform_register_reset(&__reset ## _node)
>>  
>>
> 


-- 
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


From javier at osg.samsung.com  Mon May  9 12:53:11 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 15:53:11 -0400
Subject: [PATCH v2 03/22] ARM: dts: exynos: Add fin_pll node for clock
 driver
In-Reply-To: <1462734367-5619-4-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-4-git-send-email-krzk@kernel.org>
Message-ID: <978d6aba-e177-ee0a-2a6b-782a7e962646@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> For consistency between Exynos5410 and Exynos542x/5800 switch to similar
> way of defining fin_pll/oscclk. Add a node early, before implementing
> this in driver to preserve bisectability.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From robh at kernel.org  Mon May  9 13:01:48 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 15:01:48 -0500
Subject: [PATCH 2/7] pwm: omap-dmtimer: Allow for setting dmtimer clock
 source
In-Reply-To: <1462634508-24961-3-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <1462634508-24961-3-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <20160509200148.GA19811@rob-hp-laptop>

On Sat, May 07, 2016 at 06:21:43PM +0300, Ivaylo Dimitrov wrote:
> OMAP GP timers can have different input clocks that allow different PWM
> frequencies. However, there is no other way of setting the clock source but
> through clocks or clock-names properties of the timer itself. This limits
> PWM functionality to only the frequencies allowed by the particular clock
> source. Allowing setting the clock source by PWM rather than by timer
> allows different PWMs to have different ranges by not hard-wiring the clock
> source to the timer.
> 
> Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
> ---
>  Documentation/devicetree/bindings/pwm/pwm-omap-dmtimer.txt |  4 ++++
>  drivers/pwm/pwm-omap-dmtimer.c                             | 12 +++++++-----
>  2 files changed, 11 insertions(+), 5 deletions(-)

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


From robh at kernel.org  Mon May  9 13:06:57 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 15:06:57 -0500
Subject: [PATCH 4/7] [media] ir-rx51: add DT support to driver
In-Reply-To: <1462634508-24961-5-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <1462634508-24961-5-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <20160509200657.GA3379@rob-hp-laptop>

On Sat, May 07, 2016 at 06:21:45PM +0300, Ivaylo Dimitrov wrote:
> With the upcoming removal of legacy boot, lets add support to one of the
> last N900 drivers remaining without it. As the driver still uses omap
> dmtimer, add auxdata as well.
> 
> Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
> ---
>  .../devicetree/bindings/media/nokia,lirc-rx51         | 19 +++++++++++++++++++
>  arch/arm/mach-omap2/pdata-quirks.c                    |  6 +-----
>  drivers/media/rc/ir-rx51.c                            | 11 ++++++++++-
>  3 files changed, 30 insertions(+), 6 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/media/nokia,lirc-rx51
> 
> diff --git a/Documentation/devicetree/bindings/media/nokia,lirc-rx51 b/Documentation/devicetree/bindings/media/nokia,lirc-rx51
> new file mode 100644
> index 0000000..5b3081e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/nokia,lirc-rx51
> @@ -0,0 +1,19 @@
> +Device-Tree bindings for LIRC TX driver for Nokia N900(RX51)
> +
> +Required properties:
> +	- compatible: should be "nokia,lirc-rx51".

lirc is a Linux term. Also, nokia,rx51-... would be conventional 
ordering.

Is this anything more than a PWM LED?

> +	- pwms: specifies PWM used for IR signal transmission.
> +
> +Example node:
> +
> +	pwm9: dmtimer-pwm at 9 {
> +		compatible = "ti,omap-dmtimer-pwm";
> +		ti,timers = <&timer9>;
> +		#pwm-cells = <3>;
> +	};
> +
> +	ir: lirc-rx51 {
> +		compatible = "nokia,lirc-rx51";
> +
> +		pwms = <&pwm9 0 26316 0>; /* 38000 Hz */
> +	};


From robh at kernel.org  Mon May  9 13:09:36 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 15:09:36 -0500
Subject: [PATCH v2 22/22] ARM: dts: exynos: Add initial support for
 Odroid XU board
In-Reply-To: <1462734367-5619-23-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-23-git-send-email-krzk@kernel.org>
Message-ID: <20160509200936.GA24252@rob-hp-laptop>

On Sun, May 08, 2016 at 09:06:07PM +0200, Krzysztof Kozlowski wrote:
> The Hardkernel's Odroid XU board was first design with big.LITTLE SoC
> from Samsung: the Exynos5410. Comparing now to more popular Odroid XU3
> the differences are:
> 1. Exynos5410 instead of 5422,
> 2. DisplayPort,
> 3. Main PMIC: Maxim 77802 instead of S2MPS11,
> 4. USB3503+LAN9730 instead of integrated LAN9514,
> 5. eMMC 4.5 instead of eMMC 5.0,
> 
> This patch adds initial support for the XU board with working basic
> functions, eMMC/SD and USB (including attached ethernet adapter).
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---
>  .../bindings/arm/samsung/samsung-boards.txt        |   1 +
>  arch/arm/boot/dts/Makefile                         |   1 +
>  arch/arm/boot/dts/exynos5410-odroidxu.dts          | 166 +++++++++++++++++++++
>  3 files changed, 168 insertions(+)
>  create mode 100644 arch/arm/boot/dts/exynos5410-odroidxu.dts
> 
> diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
> index f5deace2b380..0ea7f14ef294 100644
> --- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
> +++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
> @@ -47,6 +47,7 @@ Required root node properties:
>  	- "hardkernel,odroid-u3"  - for Exynos4412-based Hardkernel Odroid U3.
>  	- "hardkernel,odroid-x"   - for Exynos4412-based Hardkernel Odroid X.
>  	- "hardkernel,odroid-x2"  - for Exynos4412-based Hardkernel Odroid X2.
> +	- "hardkernel,odroid-xu"  - for Exynos5410-based Hardkernel Odroid XU.
>  	- "hardkernel,odroid-xu3" - for Exynos5422-based Hardkernel Odroid XU3.
>  	- "hardkernel,odroid-xu3-lite" - for Exynos5422-based Hardkernel
>  					 Odroid XU3 Lite board.
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index 5aeb10674370..9ed1c7abedb1 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -134,6 +134,7 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \
>  	exynos5250-snow-rev5.dtb \
>  	exynos5250-spring.dtb \
>  	exynos5260-xyref5260.dtb \
> +	exynos5410-odroidxu.dtb \
>  	exynos5410-smdk5410.dtb \
>  	exynos5420-arndale-octa.dtb \
>  	exynos5420-peach-pit.dtb \
> diff --git a/arch/arm/boot/dts/exynos5410-odroidxu.dts b/arch/arm/boot/dts/exynos5410-odroidxu.dts
> new file mode 100644
> index 000000000000..b0cbd53aeea9
> --- /dev/null
> +++ b/arch/arm/boot/dts/exynos5410-odroidxu.dts
> @@ -0,0 +1,166 @@
> +/*
> + * Hardkernel Odroid XU3 board device tree source
> + *
> + * Copyright (c) 2013 Samsung Electronics Co., Ltd.
> + *		http://www.samsung.com
> + * Copyright (c) 2016 Krzysztof Kozlowski
> + *
> + * 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.
> + */
> +
> +/dts-v1/;
> +#include "exynos5410.dtsi"
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/interrupt-controller/irq.h>
> +#include "exynos54xx-odroidxu-leds.dtsi"
> +
> +/ {
> +	model = "Hardkernel Odroid XU";
> +	compatible = "hardkernel,odroid-xu", "samsung,exynos5410", "samsung,exynos5";
> +
> +	memory {
> +		reg = <0x40000000 0x7EA00000>;

lowercase hex please.

With that,

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


From robh at kernel.org  Mon May  9 13:13:24 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 15:13:24 -0500
Subject: [PATCH 0/2] mtd: atmel_nand: remove compatible "atmel,sama5d4-nfc"
In-Reply-To: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
References: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
Message-ID: <20160509201324.GA9845@rob-hp-laptop>

On Mon, May 09, 2016 at 02:51:17PM +0800, Wenyou Yang wrote:
> It is a datasheet bug, for current SoCs, the RB_EDGE3(i.e. bit 27)
> of HSMC_SR register does not exist, the RB_EDGE0 (i.e. bit 24) is
> the ready/busy line edge status bit. So the compatible
> "atmel,sama5d4-nfc" is unneeded.

The compatible is needed if the SOC still exists. You can list both for 
the sama5d4 if the block is the same.

Rob



From javier at osg.samsung.com  Mon May  9 13:19:46 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 16:19:46 -0400
Subject: [PATCH v2 04/22] clk: samsung: exynos5410: Provide fin_pll
 external fixed clock
In-Reply-To: <1462734367-5619-5-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-5-git-send-email-krzk@kernel.org>
Message-ID: <e805f0d3-038b-72ce-4464-ac3605e9e5bb@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> Just like clock driver for Exynos542x/5800, provide the fixed clock here
> so the clock bindings and their consumers would be consistent and
> similar.
> 
> However a clock named "fin_pll" is already provided by generic
> fixed-clock and it is both referenced in the clock driver (by name) and
> in DT (by phandle). To make the transition smooth, first introduce the
> new external fixed clock here under temporary, different name and switch
> internal users to it.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

[snip]

>  
> +/* Same as in Exynos5420 */
> +static const struct of_device_id ext_clk_match[] __initconst = {
> +	{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },

Since using designated initializers, I was about to say that there is no need
to explicitly set .data to 0 since omitted fields are implicitly initialized...

> +	{ },
> +};
> +
>  /* register exynos5410 clocks */
>  static void __init exynos5410_clk_init(struct device_node *np)
>  {
> @@ -192,6 +204,10 @@ static void __init exynos5410_clk_init(struct device_node *np)
>  
>  	ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
>  
> +	samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
> +			ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
> +			ext_clk_match);
> +

... but then I noticed that .data is used as exynos5x_fixed_rate_ext_clks
array index in samsung_clk_of_register_fixed_ext(). So makes sense to set
it explicitly to make the intent clear.

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From christoffer.dall at linaro.org  Mon May  9 13:21:16 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Mon, 9 May 2016 22:21:16 +0200
Subject: [PATCH] kvm: arm64: Enable hardware updates of the Access Flag
 for Stage 2 page tables
In-Reply-To: <20160509165056.GC20598@e104818-lin.cambridge.arm.com>
References: <1460566657-30221-1-git-send-email-catalin.marinas@arm.com>
 <20160509153310.GA27623@cbox>
 <20160509165056.GC20598@e104818-lin.cambridge.arm.com>
Message-ID: <20160509202116.GB27623@cbox>

On Mon, May 09, 2016 at 05:50:56PM +0100, Catalin Marinas wrote:
> On Mon, May 09, 2016 at 05:33:10PM +0200, Christoffer Dall wrote:
> > On Wed, Apr 13, 2016 at 05:57:37PM +0100, Catalin Marinas wrote:
> > > The ARMv8.1 architecture extensions introduce support for hardware
> > > updates of the access and dirty information in page table entries. With
> > > VTCR_EL2.HA enabled (bit 21), when the CPU accesses an IPA with the
> > > PTE_AF bit cleared in the stage 2 page table, instead of raising an
> > > Access Flag fault to EL2 the CPU sets the actual page table entry bit
> > > (10). To ensure that kernel modifications to the page table do not
> > > inadvertently revert a bit set by hardware updates, certain Stage 2
> > > software pte/pmd operations must be performed atomically.
> > > 
> > > The main user of the AF bit is the kvm_age_hva() mechanism. The
> > > kvm_age_hva_handler() function performs a "test and clear young" action
> > > on the pte/pmd. This needs to be atomic in respect of automatic hardware
> > > updates of the AF bit. Since the AF bit is in the same position for both
> > > Stage 1 and Stage 2, the patch reuses the existing
> > > ptep_test_and_clear_young() functionality if
> > > __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG is defined. Otherwise, the
> > > existing pte_young/pte_mkold mechanism is preserved.
> > > 
> > > The kvm_set_s2pte_readonly() (and the corresponding pmd equivalent) have
> > > to perform atomic modifications in order to avoid a race with updates of
> > > the AF bit. The arm64 implementation has been re-written using
> > > exclusives.
> > > 
> > > Currently, kvm_set_s2pte_writable() (and pmd equivalent) take a pointer
> > > argument and modify the pte/pmd in place. However, these functions are
> > > only used on local variables rather than actual page table entries, so
> > > it makes more sense to follow the pte_mkwrite() approach for stage 1
> > > attributes. The change to kvm_s2pte_mkwrite() makes it clear that these
> > > functions do not modify the actual page table entries.
> > 
> > so if one CPU takes a permission fault and is in the process of updating
> > the page table, what prevents another CPU from setting the access flag
> > (on a read, done by HW) on that entry between us reading the old pte and
> > replacing it with the new pte?
> 
> There isn't anything that would prevent this. However, as in the stage 1
> scenarios, explicitly writing a PTE as a result of a permission fault
> should also mark the entry as accessed (young, either as the default
> protection in PROT_DEFAULT or explicitly via pte_mkyoung).
> 
> > Don't we loose the AF information in that case too?
> 
> Since the hardware never clears the AF bit automatically, there is no
> information to lose in this race as long as the kvm_set_s2pte_writable()
> sets the AF bit. AFAICT, the PAGE_S2 and PAGE_S2_DEVICE definitions
> already use PROT_DEFAULT which has the AF bit set.

duh, yeah, I didn't consider the overall use case we're targeting.
Thanks for reminding me.

> 
> > >  static inline void kvm_set_s2pte_readonly(pte_t *pte)
> > >  {
> > > -	pte_val(*pte) = (pte_val(*pte) & ~PTE_S2_RDWR) | PTE_S2_RDONLY;
> > > +	pteval_t pteval;
> > > +	unsigned long tmp;
> > > +
> > > +	asm volatile("//	kvm_set_s2pte_readonly\n"
> > > +	"	prfm	pstl1strm, %2\n"
> > > +	"1:	ldxr	%0, %2\n"
> > > +	"	and	%0, %0, %3		// clear PTE_S2_RDWR\n"
> > > +	"	orr	%0, %0, %4		// set PTE_S2_RDONLY\n"
> > > +	"	stxr	%w1, %0, %2\n"
> > > +	"	cbnz	%w1, 1b\n"
> > > +	: "=&r" (pteval), "=&r" (tmp), "+Q" (pte_val(*pte))
> > 
> > so the +Q means "pass the memory address of the value and by the way the
> > content, not the address itself, can be updated by the assembly code" ?
> 
> Yes. I think "info gcc" isn't clear enough on this constraint (at least
> to me) but that's something we learnt from the tools guys in the early
> days of the aarch64 kernel port.
> 
Just finding anything about the meaning of this turned out to be its own
challenge.

In any case:

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>

And I have applied it to kvmarm/next.

-Christoffer


From javier at osg.samsung.com  Mon May  9 13:22:01 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 16:22:01 -0400
Subject: [PATCH v2 05/22] ARM: dts: exynos: Switch MCT node to a new
 fin_pll clock
In-Reply-To: <1462734367-5619-6-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-6-git-send-email-krzk@kernel.org>
Message-ID: <9359df26-fc41-78da-dbf8-cc336dbe80da@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> The clk-exynos5410 driver now provides the "fin_pll" external fixed
> clock. Switch the Multi-Core Timer to this clock.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From robh at kernel.org  Mon May  9 13:22:36 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 15:22:36 -0500
Subject: [PATCH 1/5] dt-bindings: mediatek: add descriptions for mediatek
 mt2701 iommu and smi
In-Reply-To: <1462780816-5288-2-git-send-email-honghui.zhang@mediatek.com>
References: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
 <1462780816-5288-2-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <20160509202236.GA23951@rob-hp-laptop>

On Mon, May 09, 2016 at 04:00:12PM +0800, honghui.zhang at mediatek.com wrote:
> From: Honghui Zhang <honghui.zhang at mediatek.com>
> 
> This patch defines the local arbitor port IDs for mediatek SoC MT2701 and
> add descriptions of binding for mediatek generation one iommu and smi.
> 
> Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
> ---
>  .../devicetree/bindings/iommu/mediatek,iommu.txt   | 13 +++-
>  .../memory-controllers/mediatek,smi-common.txt     | 21 +++++-
>  .../memory-controllers/mediatek,smi-larb.txt       |  4 +-
>  include/dt-bindings/memory/mt2701-larb-port.h      | 85 ++++++++++++++++++++++
>  4 files changed, 115 insertions(+), 8 deletions(-)
>  create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h
> 
> diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
> index cd1b1cd..9a4a5b5 100644
> --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
> +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
> @@ -1,7 +1,9 @@
>  * Mediatek IOMMU Architecture Implementation
>  
> -  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U) which
> -uses the ARM Short-Descriptor translation table format for address translation.
> +  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U), and
> +this M4U have two generations of HW architecture. Generation one use flat

s/use/uses/

> +pagetable, and only support 4K size page mapping. Generation two uses the

s/support/supports/

> +ARM Short-Descriptor translation table format for address translation.
>  
>    About the M4U Hardware Block Diagram, please check below:
>  
> @@ -36,7 +38,9 @@ in each larb. Take a example, There are many ports like MC, PP, VLD in the
>  video decode local arbiter, all these ports are according to the video HW.
>  
>  Required properties:
> -- compatible : must be "mediatek,mt8173-m4u".
> +- compatible : must be one of the following string:
> +	"mediatek,mt2701-m4u" for mt2701 which use generation one m4u HW.
> +	"mediatek,mt8173-m4u" for mt8173 which use generation two m4u HW.
>  - reg : m4u register base and size.
>  - interrupts : the interrupt of m4u.
>  - clocks : must contain one entry for each clock-names.
> @@ -46,7 +50,8 @@ Required properties:
>  	according to the local arbiter index, like larb0, larb1, larb2...
>  - iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
>  	Specifies the mtk_m4u_id as defined in
> -	dt-binding/memory/mt8173-larb-port.h.
> +	dt-binding/memory/mt2701-larb-port.h for mt2701 and
> +	dt-binding/memory/mt8173-larb-port.h for mt8173
>  
>  Example:
>  	iommu: iommu at 10205000 {
> diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
> index 06a83ce..80c0e22 100644
> --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
> +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
> @@ -2,16 +2,31 @@ SMI (Smart Multimedia Interface) Common
>  
>  The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
>  
> +Mediatek SMI have two generation HW architecture, mt8173 use the secondary

s/generation/generations of/
s/use/uses/
s/secondary/second/

> +generation of SMI HW while mt2701 use the first generation HW of SMI.

s/use/uses/

> +
> +There's slight differences between the two SMI, for generation 2, the
> +register which control the iommu port is at each larb's register base. But
> +for generation 1, the register is at smi ao base(smi always on register
> +base). Besides that, the smi async clock should be prepare and enabled for

s/prepare/prepared/

> +SMI generation 1 to transform the smi clock into emi clock domain, but no

s/no/that is not/

> +needed for SMI generation 2.
> +
>  Required properties:
> -- compatible : must be "mediatek,mt8173-smi-common"
> +- compatible : must be one of :
> +	"mediatek,mt2701-smi-common"
> +	"mediatek,mt8173-smi-common"
>  - reg : the register and size of the SMI block.
>  - power-domains : a phandle to the power domain of this local arbiter.
>  - clocks : Must contain an entry for each entry in clock-names.
> -- clock-names : must contain 2 entries, as follows:
> +- clock-names : must contain 3 entries for generation 1 smi HW and 2 entries
> +  for generation 2 smi HW as follows:
>    - "apb" : Advanced Peripheral Bus clock, It's the clock for setting
>  	    the register.
>    - "smi" : It's the clock for transfer data and command.
> -  They may be the same if both source clocks are the same.
> +	    They may be the same if both source clocks are the same.
> +  - "async" : asynchronous clock, it help transform the smi clock into the emi
> +	      clock domain, this clock is only needed by generation 1 smi HW.
>  
>  Example:
>  	smi_common: smi at 14022000 {
> diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
> index 55ff3b7..21277a5 100644
> --- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
> +++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
> @@ -3,7 +3,9 @@ SMI (Smart Multimedia Interface) Local Arbiter
>  The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
>  
>  Required properties:
> -- compatible : must be "mediatek,mt8173-smi-larb"
> +- compatible : must be one of :
> +		"mediatek,mt8173-smi-larb"
> +		"mediatek,mt2701-smi-larb"
>  - reg : the register and size of this local arbiter.
>  - mediatek,smi : a phandle to the smi_common node.
>  - power-domains : a phandle to the power domain of this local arbiter.


From javier at osg.samsung.com  Mon May  9 13:24:51 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 16:24:51 -0400
Subject: [PATCH v2 06/22] ARM: dts: exynos: Remove old fixed-clock
 provider on SMDK5410
In-Reply-To: <1462734367-5619-7-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-7-git-send-email-krzk@kernel.org>
Message-ID: <723d088c-ada7-a18f-87a2-e7caaf2c56fd@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> All "fin_pll" clock users are switched to the new one, provided by

s/are switched/were switched

> Exynos5410 clock driver. Remove old DT node.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Mon May  9 13:25:55 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 16:25:55 -0400
Subject: [PATCH v2 07/22] clk: samsung: exynos5410: Rename fin_pll from
 temporary to regular name
In-Reply-To: <1462734367-5619-8-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-8-git-send-email-krzk@kernel.org>
Message-ID: <50c533ac-9712-47b7-ef3f-87ef779be8e3@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> For smooth transition of fin_pll to clk-exynos5410.c from fixed-clock
> driver, initially it was named "fin_pll_new". Fix this here.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From maxime.ripard at free-electrons.com  Mon May  9 13:28:37 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 9 May 2016 22:28:37 +0200
Subject: [GIT PULL] Allwinner DT for 4.7, round 2
Message-ID: <20160509202837.GA19124@lukather>

Hi Arnd, Kevin, Olof,

Here's a second bunch of patches for DT, that is on top of the previous PR.

Unless something unexpected comes up, I expect it to be our last PR
for the 4.7 merge window.

Thanks!
Maxime

The following changes since commit b52e345d43cfe9214fecfa92375525a086d39581:

  ARM: dts: sun7i: Enable S/PDIF on the Cubietruck (2016-04-25 09:56:34 +0200)

are available in the git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux.git tags/sunxi-dt-for-4.7-2

for you to fetch changes up to 068655dc9b7c71c4bea25c41eeaa5125c6724a91:

  ARM: sun7i: dt: Add pll3 and pll7 clocks (2016-05-08 21:09:29 +0200)

----------------------------------------------------------------
Allwinner DT changes for 4.7, round 2

Mostly DT patches to enable the new DRM driver on the CHIP, preliminary
support for the A10 and A20, and a support for a new variant of the Olimex
A20-Olinuxino-Lime2 featuring an eMMC

----------------------------------------------------------------
Maxime Ripard (3):
      ARM: sun5i: a13: Add display and TCON clocks
      ARM: sun5i: r8: Add display blocks to the DTSI
      ARM: sun5i: chip: Enable the TV Encoder

Olliver Schinagl (1):
      ARM: dts: sunxi: Add a olinuxino-lime2-emmc

Priit Laes (2):
      ARM: sun4i: dt: Add pll3 and pll7 clocks
      ARM: sun7i: dt: Add pll3 and pll7 clocks

 arch/arm/boot/dts/sun4i-a10.dtsi                   |  43 +++++++
 arch/arm/boot/dts/sun5i-a13.dtsi                   |  39 +++++-
 arch/arm/boot/dts/sun5i-r8-chip.dts                |  12 ++
 arch/arm/boot/dts/sun5i-r8.dtsi                    | 142 ++++++++++++++++++++-
 .../boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts    |  82 ++++++++++++
 arch/arm/boot/dts/sun7i-a20.dtsi                   |  41 ++++++
 6 files changed, 355 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160509/d17318ab/attachment.sig>

From robh at kernel.org  Mon May  9 13:30:03 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 15:30:03 -0500
Subject: [PATCH 1/4] doc/devicetree: Add Aspeed clock bindings
In-Reply-To: <1462797111-14271-2-git-send-email-joel@jms.id.au>
References: <1462797111-14271-1-git-send-email-joel@jms.id.au>
 <1462797111-14271-2-git-send-email-joel@jms.id.au>
Message-ID: <20160509203003.GA24945@rob-hp-laptop>

On Mon, May 09, 2016 at 10:01:48PM +0930, Joel Stanley wrote:
> Signed-off-by: Joel Stanley <joel at jms.id.au>
> ---
>  .../devicetree/bindings/clock/aspeed-clock.txt     | 156 +++++++++++++++++++++
>  1 file changed, 156 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/aspeed-clock.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/aspeed-clock.txt b/Documentation/devicetree/bindings/clock/aspeed-clock.txt
> new file mode 100644
> index 000000000000..968329406435
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/aspeed-clock.txt
> @@ -0,0 +1,156 @@
> +Device Tree Clock bindings for the Aspeed SoCs
> +
> +Aspeed SoCs have a fixed frequency input osciallator is used to create the PLL
> +and APB clocks. We can determine these frequencies by reading registers that
> +are set according to strapping bits.
> +
> +Forth generation boards
> +-----------------------
> +
> +eg, ast2400.
> +
> +CLKIN:
> + - compatible : Must be "fixed-clock"
> + - #clock-cells : Should be 0
> + - clock-frequency: 48e6, 25e6 or 24e6 depending on the input clock
> +
> +PLL:
> +
> +Required properties:
> + - compatible : Must be "aspeed,g4-hpll-clock"
> + - #clock-cells : Should be 0
> + - reg : Should contain registers location and length
> + - clocks : Should contain phandle + clock-specifier for the input clock (clkin)
> +
> +Optional properties:
> + - clock-output-names : Should contain clock name
> +
> +
> +APB:
> +
> +Required properties:
> + - compatible : Must be "aspeed,g4-apb-clock"
> + - #clock-cells : Should be 0
> + - reg : Should contain registers location and length
> + - clocks : Should contain phandle + clock-specifier for the h-pll
> +
> +Optional properties:
> + - clock-output-names : Should contain clock name
> +
> +
> +For example:
> +
> +	clk_clkin: clk_clkin {
> +		#clock-cells = <0>;
> +		compatible = "fixed-clock";
> +		clock-frequency = <48000000>;
> +	};
> +
> +	clk_hpll: clk_hpll {
> +		compatible = "aspeed,g4-hpll-clock";
> +		#clock-cells = <0>;
> +		reg = <0x1e6e2008 0x4>;
> +	};
> +
> +	clk_apb: clk_apb at 1e6e2008 {
> +		#clock-cells = <0>;
> +		compatible = "aspeed,g4-apb-clock";
> +		reg = <0x1e6e2008 0x4>;

You have overlapping register regions which we try to avoid (it would 
through errors, but doesn't because of existing platforms).

Just define the h/w block controlling these clocks and support multiple 
clocks.

Is this really all the clocks the SOC has?

Rob


From robh at kernel.org  Mon May  9 13:36:16 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 15:36:16 -0500
Subject: [PATCH 4/4] drivers/clocksource/moxart: Add Aspeed support
In-Reply-To: <1462797169-14512-5-git-send-email-joel@jms.id.au>
References: <1462797169-14512-1-git-send-email-joel@jms.id.au>
 <1462797169-14512-5-git-send-email-joel@jms.id.au>
Message-ID: <20160509203616.GA4843@rob-hp-laptop>

On Mon, May 09, 2016 at 10:02:49PM +0930, Joel Stanley wrote:
> The Aspeed SoC has timer IP with a very similar register layout to the
> moxart timer. This patch adds support for the fourth and fifth gen
> aspeed SoCs, and has been tested on the ast2400 and ast2500.
> 
> Signed-off-by: Joel Stanley <joel at jms.id.au>
> ---
>  .../bindings/timer/moxa,moxart-timer.txt           |  4 ++-
>  drivers/clocksource/moxart_timer.c                 | 32 ++++++++++++++++++++++
>  2 files changed, 35 insertions(+), 1 deletion(-)

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


From robh at kernel.org  Mon May  9 13:38:31 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 15:38:31 -0500
Subject: [PATCH 1/2] doc/devicetree: Add Aspeed watchdog timer bindings
In-Reply-To: <1462797277-14969-2-git-send-email-joel@jms.id.au>
References: <1462797277-14969-1-git-send-email-joel@jms.id.au>
 <1462797277-14969-2-git-send-email-joel@jms.id.au>
Message-ID: <20160509203831.GA20352@rob-hp-laptop>

On Mon, May 09, 2016 at 10:04:36PM +0930, Joel Stanley wrote:
> Signed-off-by: Joel Stanley <joel at jms.id.au>
> ---
>  Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> 
> diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> new file mode 100644
> index 000000000000..58184b161e0d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> @@ -0,0 +1,14 @@
> +Aspeed Watchdog Timer
> +
> +Required properties:
> + - compatible: must be "aspeed,wdt"

This should have the specific SOCs listed.

Rob

> + - reg: physical base address of the controller and length of memory mapped
> +   region
> +
> +Example:
> +
> +	wdt1: wdt at 1e785000 {

IIRC, "watchdog at ..." is the correct generic name.

> +		compatible = "aspeed,wdt";
> +		reg = <0x1e785000 0x1c>;
> +		interrupts = <27>;
> +	};
> -- 
> 2.8.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From stefan.wahren at i2se.com  Mon May  9 13:49:36 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Mon, 9 May 2016 22:49:36 +0200 (CEST)
Subject: ARM: mxs: STI: console can't wake up from freeze
Message-ID: <1474284101.292364.2298f4ae-2c4a-4dbb-9e38-0a6190db0f92.open-xchange@email.1und1.de>

Hi,

i'm faced with the issue that on i.MX28 the console is unable to wake up from
freeze ( suspend to idle). I tested it with Linux 3.18 and 4.5 ( cmdline has
no_console_suspend=1 ) and also with a i.MX23 with the same result. The suspend
seems to work, but there is no reaction to the console after the freeze.
Strangely the suspend to RAM from console and using freeze in combination with
pm_test works without any issues.

Any ideas to narrow down the problem?

Here is the console output:

root at duckbill:~# echo freeze > /sys/power/state 
[   54.163568] PM: Syncing filesystems ... done.
[   57.916487] Freezing user space processes ... (elapsed 0.007 seconds) done.
[   57.930987] Freezing remaining freezable tasks ... (elapsed 0.004 seconds)
done.
[   57.970490] PM: suspend of devices complete after 22.813 msecs
[   57.983052] PM: late suspend of devices complete after 6.480 msecs
[   57.997832] PM: noirq suspend of devices complete after 8.500 msecs
[  240.633397] INFO: task ext4lazyinit:73 blocked for more than 120 seconds.
[  240.640245]       Not tainted 3.18.0-01974-gb2776bf #12
[  240.645639] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this
message.
[  240.653619] ext4lazyinit    D c0511a80     0    73      2 0x00000000
[  240.660147] [<c0511a80>] (__schedule) from [<c05153c0>]
(schedule_timeout+0x138/0x1e4)
[  240.668265] [<c05153c0>] (schedule_timeout) from [<c05117bc>]
(io_schedule_timeout+0x94/0xfc)
[  240.676983] [<c05117bc>] (io_schedule_timeout) from [<c0512b10>]
(T.312+0x9c/0x120)
[  240.684848] [<c0512b10>] (T.312) from [<c02a9138>]
(__blkdev_issue_zeroout+0x1f8/0x210)
[  240.693059] [<c02a9138>] (__blkdev_issue_zeroout) from [<c02a942c>]
(blkdev_issue_zeroout+0x94/0xa0)
[  240.702265] [<c02a942c>] (blkdev_issue_zeroout) from [<c017fd74>]
(ext4_init_inode_table+0x1a0/0x394)
[  240.711689] [<c017fd74>] (ext4_init_inode_table) from [<c019e050>]
(ext4_lazyinit_thread+0x100/0x2f0)
[  240.721126] [<c019e050>] (ext4_lazyinit_thread) from [<c0032fd4>]
(kthread+0xb8/0xd4)
[  240.729145] [<c0032fd4>] (kthread) from [<c0009680>]
(ret_from_fork+0x14/0x34)
[  240.736535] 4 locks held by ext4lazyinit/73:
[  240.740839]  #0:  (&eli->li_list_mtx){+.+...}, at: [<c019df90>]
ext4_lazyinit_thread+0x40/0x2f0
[  240.749815]  #1:  (sb_writers#3){.+.+.+}, at: [<c019dfdc>]
ext4_lazyinit_thread+0x8c/0x2f0
[  240.758373]  #2:  (jbd2_handle){+.+...}, at: [<c01d3880>]
start_this_handle+0x174/0x5dc
[  240.766630]  #3:  (&meta_group_info[i]->alloc_sem){++++..}, at: [<c017fc8c>]
ext4_init_inode_table+0xb8/0x394
[  240.776855] INFO: task bash:465 blocked for more than 120 seconds.
[  240.783191]       Not tainted 3.18.0-01974-gb2776bf #12
[  240.788456] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this
message.
[  240.796417] bash            D c0511a80     0   465    311 0x00000000
[  240.803062] [<c0511a80>] (__schedule) from [<c0051044>]
(suspend_devices_and_enter+0x308/0x62c)
[  240.811840] [<c0051044>] (suspend_devices_and_enter) from [<c0051648>]
(pm_suspend+0x2e0/0x400)
[  240.820729] [<c0051648>] (pm_suspend) from [<c004ff10>]
(state_store+0x80/0xcc)
[  240.828226] [<c004ff10>] (state_store) from [<c02bd950>]
(kobj_attr_store+0x18/0x1c)
[  240.836169] [<c02bd950>] (kobj_attr_store) from [<c0157d18>]
(sysfs_kf_write+0x48/0x4c)
[  240.844363] [<c0157d18>] (sysfs_kf_write) from [<c0156f10>]
(kernfs_fop_write+0xc8/0x184)
[  240.852624] [<c0156f10>] (kernfs_fop_write) from [<c00f5058>]
(vfs_write+0xb8/0x1d8)
[  240.860559] [<c00f5058>] (vfs_write) from [<c00f524c>] (SyS_write+0x44/0x88)
[  240.867783] [<c00f524c>] (SyS_write) from [<c00095c0>]
(ret_fast_syscall+0x0/0x44)
[  240.875517] 4 locks held by bash/465:
[  240.879214]  #0:  (sb_writers#4){.+.+.+}, at: [<c00f511c>]
vfs_write+0x17c/0x1d8
[  240.886898]  #1:  (&of->mutex){+.+.+.}, at: [<c0156ed4>]
kernfs_fop_write+0x8c/0x184
[  240.894883]  #2:  (s_active#39){.+.+.+}, at: [<c0156edc>]
kernfs_fop_write+0x94/0x184
[  240.902996]  #3:  (pm_mutex){+.+.+.}, at: [<c00513e8>] pm_suspend+0x80/0x400


From javier at osg.samsung.com  Mon May  9 13:50:58 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 16:50:58 -0400
Subject: [PATCH v2 08/22] clk: samsung: exynos5410: Add serial3, USB and
 PWM clocks
In-Reply-To: <1462734367-5619-9-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-9-git-send-email-krzk@kernel.org>
Message-ID: <7a1772c3-d81a-3133-d775-0e8034fcee9d@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> Just like other Exynos5 family SoCs, this one has four UARTs. Add
> missing UART3 clocks to the Exynso5410 clock driver.
> 
> Add clocks for USB and PWM.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

I don't have an Exynos5410 SoC user manual to double check all values
but assuming that are correct, the patch looks good to me.

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
 
Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From ivo.g.dimitrov.75 at gmail.com  Mon May  9 13:51:12 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Mon, 9 May 2016 23:51:12 +0300
Subject: [PATCH 5/7] ARM: OMAP: dmtimer: Do not call PM runtime functions
 when not needed.
In-Reply-To: <20160509193624.GH5995@atomide.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <1462634508-24961-6-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <20160509193624.GH5995@atomide.com>
Message-ID: <5730F840.3050807@gmail.com>

Hi,

On  9.05.2016 22:36, Tony Lindgren wrote:
> * Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com> [160507 08:24]:
>> once omap_dm_timer_start() is called, which calls omap_dm_timer_enable()
>> and thus pm_runtime_get_sync(), it doesn't make sense to call PM runtime
>> functions again before omap_dm_timer_stop is called(). Otherwise PM runtime
>> functions called in omap_dm_timer_enable/disable lead to long and unneeded
>> delays.
>>
>> Fix that by implementing an "enabled" counter, so the PM runtime functions
>> get called only when really needed.
>>
>> Without that patch Nokia N900 IR TX driver (ir-rx51) does not function.
>

Well, I just tested again, with the $subject patch reverted and 
contradictory to my own words, it worked just fine. I believe the reason 
is that I did hrtimer "migration" after I did the $subject patch. I was 
thinking the reason for the slow transmission was PWM dmtimer, but now 
it turns out it has been the "pulse" dmtimer. So, I think the $subject 
patch should be dropped.

> We should use pm_runtime for the refcounting though and call PM runtime
> unconditionally. Can you try to follow the standard PM runtime usage
> like this:
>

It works without that, but on the other hand, I finally have some 
reference on how PM runtime API should be called :).

> init:
> pm_runtime_use_autosuspend(&timer->pdev->dev);
> pm_runtime_set_autosuspend_delay(&timer->pdev->dev, 200);
> pm_runtime_enable(&timer->pdev->dev);
> ...
> enable:
> pm_runtime_get_sync(&timer->pdev->dev);
> ...
> disable:
> pm_runtime_mark_last_busy(&timer->pdev->dev);
> pm_runtime_put_autosuspend(&timer->pdev->dev);
> ...
> exit:
> pm_runtime_dont_use_autosuspend(&timer->pdev->dev);
> pm_runtime_put_sync(&timer->pdev->dev);
> pm_runtime_disable(&timer->pdev->dev);
>
> No idea what the timeout should be, maybe less than 200 ms. Also we need
> to test that off idle still works with timer1, that might need special
> handling.
>

Thanks,
Ivo


From javier at osg.samsung.com  Mon May  9 13:52:19 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 16:52:19 -0400
Subject: [PATCH v2 09/22] ARM: dts: exynos: Re-order alphabetically
 Exynos5420 SD0/SD1 pinctrl nodes
In-Reply-To: <1462734367-5619-10-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-10-git-send-email-krzk@kernel.org>
Message-ID: <30758464-a516-9066-c4cb-8d0dd82a0d80@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> The 'sd0_rclk' was put in the middle of SD1 nodes. Remove the confusion.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From ivo.g.dimitrov.75 at gmail.com  Mon May  9 13:53:14 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Mon, 9 May 2016 23:53:14 +0300
Subject: [PATCH 4/7] [media] ir-rx51: add DT support to driver
In-Reply-To: <20160509200657.GA3379@rob-hp-laptop>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <1462634508-24961-5-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <20160509200657.GA3379@rob-hp-laptop>
Message-ID: <5730F8BA.5000402@gmail.com>

Hi,

On  9.05.2016 23:06, Rob Herring wrote:
> On Sat, May 07, 2016 at 06:21:45PM +0300, Ivaylo Dimitrov wrote:
>> With the upcoming removal of legacy boot, lets add support to one of the
>> last N900 drivers remaining without it. As the driver still uses omap
>> dmtimer, add auxdata as well.
>>
>> Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
>> ---
>>   .../devicetree/bindings/media/nokia,lirc-rx51         | 19 +++++++++++++++++++
>>   arch/arm/mach-omap2/pdata-quirks.c                    |  6 +-----
>>   drivers/media/rc/ir-rx51.c                            | 11 ++++++++++-
>>   3 files changed, 30 insertions(+), 6 deletions(-)
>>   create mode 100644 Documentation/devicetree/bindings/media/nokia,lirc-rx51
>>
>> diff --git a/Documentation/devicetree/bindings/media/nokia,lirc-rx51 b/Documentation/devicetree/bindings/media/nokia,lirc-rx51
>> new file mode 100644
>> index 0000000..5b3081e
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/media/nokia,lirc-rx51
>> @@ -0,0 +1,19 @@
>> +Device-Tree bindings for LIRC TX driver for Nokia N900(RX51)
>> +
>> +Required properties:
>> +	- compatible: should be "nokia,lirc-rx51".
>
> lirc is a Linux term. Also, nokia,rx51-... would be conventional
> ordering.
>

I used the driver name ("lirc_rx51") to not bring confusion. Also, it 
registers itself through lirc_register_driver() call, so having lirc in 
its name somehow makes sense.

I am not very good in inventing names, the best compatible I can think 
of is "nokia,rx51-ir". Is that ok?

> Is this anything more than a PWM LED?
>

It is an IR LED connected through a driver to McSPI2_SIMO pin of OMAP3, 
which pin can be configured as PWM or GPIO(there are other 
configurations, but they don't make sense). In theory it could be used 
for various things (like uni-directional serial TX, or stuff like that), 
but in practice it allows N900 to be act as an IR remote controller. I 
guess that fits in "nothing more than a PWM LED", more or less.

>> +	- pwms: specifies PWM used for IR signal transmission.
>> +
>> +Example node:
>> +
>> +	pwm9: dmtimer-pwm at 9 {
>> +		compatible = "ti,omap-dmtimer-pwm";
>> +		ti,timers = <&timer9>;
>> +		#pwm-cells = <3>;
>> +	};
>> +
>> +	ir: lirc-rx51 {
>> +		compatible = "nokia,lirc-rx51";
>> +
>> +		pwms = <&pwm9 0 26316 0>; /* 38000 Hz */
>> +	};

Thanks,
Ivo


From javier at osg.samsung.com  Mon May  9 13:54:35 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 16:54:35 -0400
Subject: [PATCH v2 10/22] ARM: dts: exynos: Use lowercase for Exynos5410
 CPU node labels
In-Reply-To: <1462734367-5619-11-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-11-git-send-email-krzk@kernel.org>
Message-ID: <05d35d71-f383-307c-4c9e-24cc7afa911f@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> Fro consistency lowercase node labels are used.
>

s/Fro/For
 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From maxime.ripard at free-electrons.com  Mon May  9 13:57:16 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 9 May 2016 22:57:16 +0200
Subject: Reverting ARCH_SUNXI arm64 support(?)
In-Reply-To: <5730714C.7010608@arm.com>
References: <57304FF7.3080909@arm.com> <20160509090951.GC19763@arm.com>
 <5730714C.7010608@arm.com>
Message-ID: <20160509205716.GG3733@lukather>

On Mon, May 09, 2016 at 12:15:24PM +0100, Andre Przywara wrote:
> Hi,
> 
> On 09/05/16 10:09, Will Deacon wrote:
> > On Mon, May 09, 2016 at 09:53:11AM +0100, Andre Przywara wrote:
> >> Hi Will, Catalin,
> > 
> > Hi Andre,
> > 
> >> Suzuki reported a build failure with certain (non-defconfig) .configs
> >> due to the new ARCH_SUNXI support in 4.6-rc [1].
> >> As unfortunately we couldn't agree on a solution and also the support
> >> for the A64/Pine64 is partial in 4.6 anyway, can you please revert:
> >> ce3dd55b99b151a90ac1701c6825f2ae2d49b54e ("arm64: Introduce Allwinner
> >> SoC config option")
> > 
> > Given that we (Catalin and I) didn't commit that patch, it seems weird
> > that we should be reverting it. Shouldn't this be handled in arm-soc or
> > via the sunxi subtree?
> > 
> > We're also a week from the merge window, so it doesn't seem like a good
> > time to be hacking at .config/kconfig-related issues.
> 
> I agree, that's why I was proposing taking Suzuki's first patch:
> 
> diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
> index efa77c1..521b1ec 100644
> --- a/arch/arm64/Kconfig.platforms
> +++ b/arch/arm64/Kconfig.platforms
> @@ -2,6 +2,7 @@ menu "Platform selection"
> 
>  config ARCH_SUNXI
>  	bool "Allwinner sunxi 64-bit SoC Family"
> +	select GENERIC_IRQ_CHIP
>  	help
>  	  This enables support for Allwinner sunxi based SoCs like the A64.
> 
> 
> This is what defconfig selects anyway and also the change would be
> confined to this (new) config option.
> 
> Olof, Arnd: would it be an option to take this patch still?

FWIW, I'd be in favour for such patch as a late patch for 4.6.

We can always fix things up properly in a later patch for 4.7 or 4.8.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160509/6d3f1d45/attachment.sig>

From alex.williamson at redhat.com  Mon May  9 13:57:39 2016
From: alex.williamson at redhat.com (Alex Williamson)
Date: Mon, 9 May 2016 14:57:39 -0600
Subject: [PATCH v9 4/8] iommu/msi-iommu: initialization
In-Reply-To: <1462362007-2753-5-git-send-email-eric.auger@linaro.org>
References: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
 <1462362007-2753-5-git-send-email-eric.auger@linaro.org>
Message-ID: <20160509145739.41a19743@t450s.home>

On Wed,  4 May 2016 11:40:03 +0000
Eric Auger <eric.auger at linaro.org> wrote:

> iommu_get/put_msi_cookie allocates/frees the resource used to store
> and ref count the MSI doorbell mappings. iommu_msi_set_aperture
> initializes the iova domain used for MSI IOVA allocation and sets the
> iommu domain's msi geometry.
> 
> The implementation relies on dma-iommu API and iova API.
> 
> New msi functions are fully implemented if CONFIG_IOMMU_MSI is set.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> 
> ---
> v9:
> - remove is_aperture_set and use iommu_domain_msi_aperture_valid helper
>   instead
> - set iommu domain's msi geometry
> 
> v8:
> - new design where msi-iommu relies on dma-iommu
> - remove the iommu_domain * from the doorbell_mapping struct
> - added is_aperture_set
> 
> v7:
> - fix locking
> - add iova_cache_get/put
> - static inline functions when CONFIG_IOMMU_DMA_RESERVED is not set
> - introduce struct reserved_iova_domain to encapsulate prot info &
>   add prot parameter in alloc_reserved_iova_domain
> 
> v5 -> v6:
> - use spin lock instead of mutex
> 
> v3 -> v4:
> - formerly in "iommu/arm-smmu: implement alloc/free_reserved_iova_domain" &
>   "iommu: add alloc/free_reserved_iova_domain"
> 
> v2 -> v3:
> - remove iommu_alloc_reserved_iova_domain & iommu_free_reserved_iova_domain
>   static implementation in case CONFIG_IOMMU_API is not set
> 
> v1 -> v2:
> - moved from vfio API to IOMMU API
> ---
>  drivers/iommu/Kconfig     |  7 ++++
>  drivers/iommu/Makefile    |  1 +
>  drivers/iommu/msi-iommu.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/msi-iommu.h | 65 +++++++++++++++++++++++++++++++
>  4 files changed, 170 insertions(+)
>  create mode 100644 drivers/iommu/msi-iommu.c
>  create mode 100644 include/linux/msi-iommu.h
> 
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index dd1dc39..0078b72 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -74,6 +74,11 @@ config IOMMU_DMA
>  	select IOMMU_IOVA
>  	select NEED_SG_DMA_LENGTH
>  
> +# IOMMU MSI mapping
> +config IOMMU_MSI
> +	bool
> +	select IOMMU_DMA
> +
>  config FSL_PAMU
>  	bool "Freescale IOMMU support"
>  	depends on PPC32
> @@ -307,6 +312,7 @@ config SPAPR_TCE_IOMMU
>  config ARM_SMMU
>  	bool "ARM Ltd. System MMU (SMMU) Support"
>  	depends on (ARM64 || ARM) && MMU
> +	select IOMMU_MSI
>  	select IOMMU_API
>  	select IOMMU_IO_PGTABLE_LPAE
>  	select ARM_DMA_USE_IOMMU if ARM
> @@ -320,6 +326,7 @@ config ARM_SMMU
>  config ARM_SMMU_V3
>  	bool "ARM Ltd. System MMU Version 3 (SMMUv3) Support"
>  	depends on ARM64 && PCI
> +	select IOMMU_MSI
>  	select IOMMU_API
>  	select IOMMU_IO_PGTABLE_LPAE
>  	select GENERIC_MSI_IRQ_DOMAIN
> diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
> index c6edb31..a381e66 100644
> --- a/drivers/iommu/Makefile
> +++ b/drivers/iommu/Makefile
> @@ -2,6 +2,7 @@ obj-$(CONFIG_IOMMU_API) += iommu.o
>  obj-$(CONFIG_IOMMU_API) += iommu-traces.o
>  obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
>  obj-$(CONFIG_IOMMU_DMA) += dma-iommu.o
> +obj-$(CONFIG_IOMMU_MSI) += msi-iommu.o
>  obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
>  obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
>  obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
> diff --git a/drivers/iommu/msi-iommu.c b/drivers/iommu/msi-iommu.c
> new file mode 100644
> index 0000000..4292957
> --- /dev/null
> +++ b/drivers/iommu/msi-iommu.c
> @@ -0,0 +1,97 @@
> +/*
> + * Reserved IOVA Management
> + *
> + * Copyright (c) 2015 Linaro Ltd.
> + *              www.linaro.org
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/iommu.h>
> +#include <linux/dma-iommu.h>
> +#include <linux/msi-iommu.h>
> +#include <linux/spinlock.h>
> +#include <linux/iova.h>
> +
> +struct doorbell_mapping {
> +	struct kref		kref;
> +	struct list_head	next;
> +	phys_addr_t		addr;
> +	dma_addr_t		iova;
> +	size_t			size;
> +};
> +
> +struct doorbell_mapping_info {
> +	struct list_head list; /* list of doorbell mapping entries */
> +	spinlock_t lock;
> +};
> +
> +int iommu_get_msi_cookie(struct iommu_domain *domain)
> +{
> +	struct doorbell_mapping_info *dmi;
> +	int ret;
> +
> +	if (domain->msi_cookie || domain->iova_cookie)
> +		return -EINVAL;
> +
> +	ret = iommu_get_dma_cookie(domain);
> +	if (ret)
> +		return ret;
> +
> +	dmi = kzalloc(sizeof(*dmi), GFP_KERNEL);
> +
> +	INIT_LIST_HEAD(&dmi->list);
> +	spin_lock_init(&dmi->lock);
> +	iova_cache_get();
> +
> +	domain->msi_cookie = dmi;
> +
> +	return dmi ? 0 : -ENOMEM;
> +}
> +EXPORT_SYMBOL(iommu_get_msi_cookie);
> +
> +void iommu_put_msi_cookie(struct iommu_domain *domain)
> +{
> +	struct doorbell_mapping_info *dmi = domain->msi_cookie;
> +
> +	if (!dmi)
> +		return;
> +
> +	domain->msi_cookie = NULL;
> +
> +	WARN_ON(!list_empty(&dmi->list));
> +
> +	kfree(dmi);
> +	iommu_put_dma_cookie(domain);
> +	iova_cache_put();
> +}
> +EXPORT_SYMBOL(iommu_put_msi_cookie);
> +
> +int iommu_msi_set_aperture(struct iommu_domain *domain,
> +			   dma_addr_t start, dma_addr_t end)
> +{
> +	struct doorbell_mapping_info *dmi = domain->msi_cookie;
> +	int ret;
> +
> +	if (!dmi || iommu_domain_msi_aperture_valid(domain))
> +		return -ENODEV;


nit, the next patch splits to use different errnos for each issue,
which seems preferable.


> +
> +	ret = iommu_dma_init_domain(domain, start, end - start + 1);
> +
> +	if (!ret) {
> +		domain->msi_geometry.aperture_start = start;
> +		domain->msi_geometry.aperture_end = end;
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(iommu_msi_set_aperture);
> +
> diff --git a/include/linux/msi-iommu.h b/include/linux/msi-iommu.h
> new file mode 100644
> index 0000000..392aa6f
> --- /dev/null
> +++ b/include/linux/msi-iommu.h
> @@ -0,0 +1,65 @@
> +/*
> + * Copyright (c) 2015 Linaro Ltd.
> + *              www.linaro.org
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +#ifndef __MSI_IOMMU_H
> +#define __MSI_IOMMU_H
> +
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +
> +struct iommu_domain;
> +
> +#ifdef CONFIG_IOMMU_MSI
> +
> +/**
> + * iommu_get_msi_cookie - Acquire MSI mapping resources for a domain
> + * @domain: IOMMU domain to prepare for MSI mapping
> + *
> + * IOMMU drivers which require MSI mapping should normally call this
> + * from their domain_alloc callback when domain->type ==
> + * IOMMU_DOMAIN_UNMANAGED.
> + */
> +int iommu_get_msi_cookie(struct iommu_domain *domain);
> +
> +/**
> + * iommu_put_msi_cookie - Release a domain's MSI mapping resources
> + * @domain: IOMMU domain previously prepared by iommu_get_msi_cookie()
> + *
> + * IOMMU drivers requesting MSI mapping should normally call this from
> + * their domain_free callback.
> + */
> +void iommu_put_msi_cookie(struct iommu_domain *domain);
> +
> +/**
> + * iommu_msi_set_aperture: allocate the msi iova domain
> + * according to the specified start/end IOVAs
> + *
> + * @domain: iommu domain handle
> + * @start: MSI iova start address
> + * @end: MSI iova end address
> + */
> +int iommu_msi_set_aperture(struct iommu_domain *domain,
> +			   dma_addr_t start, dma_addr_t end);
> +
> +#else
> +
> +static inline int
> +iommu_msi_set_aperture(struct iommu_domain *domain,
> +		       dma_addr_t start, dma_addr_t end)
> +{
> +	return -ENOENT;
> +}
> +
> +#endif	/* CONFIG_IOMMU_MSI */
> +#endif	/* __MSI_IOMMU_H */



From javier at osg.samsung.com  Mon May  9 13:58:00 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 16:58:00 -0400
Subject: [PATCH v2 11/22] ARM: dts: exynos: Configure Exynos5410 pinctrl
 for eMMC and SD card
In-Reply-To: <1462734367-5619-12-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-12-git-send-email-krzk@kernel.org>
Message-ID: <ec696ee3-9a35-7a25-21f7-b0b635d7c2c4@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> Configure the pinctrl for MMC0 (eMMC) and MMC2 (microSD card).
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From shankerd at codeaurora.org  Mon May  9 13:58:24 2016
From: shankerd at codeaurora.org (Shanker Donthineni)
Date: Mon,  9 May 2016 15:58:24 -0500
Subject: [PATCH V3 0/2] Add two-level support to ITS device table
Message-ID: <1462827506-23570-1-git-send-email-shankerd@codeaurora.org>

This patchset contains necessary code changes to support two-level
(Indirection) table walk feature for device table.

Shanker Donthineni (2):
  irqchip/gicv3-its: split its_alloc_tables() into two functions
  irqchip/gicv3-its: Implement two-level(indirect) device table support

 drivers/irqchip/irq-gic-v3-its.c   | 351 +++++++++++++++++++++++--------------
 include/linux/irqchip/arm-gic-v3.h |   3 +
 2 files changed, 223 insertions(+), 131 deletions(-)

-- 

This patch is based on Marc Zyngier's branch https://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git/log/?h=irq/irqchip-4.7

I have tested the Indirection feature on Qualcomm Technologies QDF2XXX server platform.

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



From shankerd at codeaurora.org  Mon May  9 13:58:25 2016
From: shankerd at codeaurora.org (Shanker Donthineni)
Date: Mon,  9 May 2016 15:58:25 -0500
Subject: [PATCH V3 1/2] irqchip/gicv3-its: split its_alloc_tables() into two
 functions
In-Reply-To: <1462827506-23570-1-git-send-email-shankerd@codeaurora.org>
References: <1462827506-23570-1-git-send-email-shankerd@codeaurora.org>
Message-ID: <1462827506-23570-2-git-send-email-shankerd@codeaurora.org>

The function is getting out of control, it has too many goto
statements and would be too complicated for adding a feature
two-level device table. So, it is time for us to cleanup and
move some of the logic to a separate function without affecting
the existing functionality.

Signed-off-by: Shanker Donthineni <shankerd at codeaurora.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 256 ++++++++++++++++++++-----------------
 include/linux/irqchip/arm-gic-v3.h |   3 +
 2 files changed, 144 insertions(+), 115 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 6bd881b..b23e00c 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -55,13 +55,15 @@ struct its_collection {
 };
 
 /*
- * The ITS_BASER structure - contains memory information and cached
- * value of BASER register configuration.
+ * The ITS_BASER structure - contains memory information, cached value
+ * of BASER register configuration, ioremaped address and page size.
  */
 struct its_baser {
+	void __iomem	*hwreg;
 	void		*base;
 	u64		val;
 	u32		order;
+	u32		psz;
 };
 
 /*
@@ -823,27 +825,135 @@ static void its_free_tables(struct its_node *its)
 	}
 }
 
+static int its_baser_setup(struct its_node *its, struct its_baser *baser,
+				  u32 order, u64 indirect)
+{
+	u64 val = readq_relaxed(baser->hwreg);
+	u64 type = GITS_BASER_TYPE(val);
+	u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
+	int psz, alloc_pages;
+	u64 cache, shr, tmp;
+	void *base;
+
+	/* Do first attempt with the requested attributes */
+	cache = baser->val & GITS_BASER_CACHEABILITY_MASK;
+	shr = baser->val & GITS_BASER_SHAREABILITY_MASK;
+	psz = baser->psz;
+
+retry_alloc_baser:
+	alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
+	if (alloc_pages > GITS_BASER_PAGES_MAX) {
+		pr_warn("ITS@%lx: %s too large, reduce ITS pages %u->%u\n",
+			its->phys_base, its_base_type_string[type],
+			alloc_pages, GITS_BASER_PAGES_MAX);
+		alloc_pages = GITS_BASER_PAGES_MAX;
+		order = get_order(GITS_BASER_PAGES_MAX * psz);
+	}
+
+	base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
+	if (!base)
+		return -ENOMEM;
+
+retry_baser:
+	val = (virt_to_phys(base)				 |
+		(type << GITS_BASER_TYPE_SHIFT)			 |
+		((entry_size - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) |
+		((alloc_pages - 1) << GITS_BASER_PAGES_SHIFT)	 |
+		cache						 |
+		shr						 |
+		indirect					 |
+		GITS_BASER_VALID);
+
+	switch (psz) {
+	case SZ_4K:
+		val |= GITS_BASER_PAGE_SIZE_4K;
+		break;
+	case SZ_16K:
+		val |= GITS_BASER_PAGE_SIZE_16K;
+		break;
+	case SZ_64K:
+		val |= GITS_BASER_PAGE_SIZE_64K;
+		break;
+	}
+
+	writeq_relaxed(val, baser->hwreg);
+	tmp = readq_relaxed(baser->hwreg);
+
+	if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
+		/*
+		 * Shareability didn't stick. Just use
+		 * whatever the read reported, which is likely
+		 * to be the only thing this redistributor
+		 * supports. If that's zero, make it
+		 * non-cacheable as well.
+		 */
+		shr = tmp & GITS_BASER_SHAREABILITY_MASK;
+		if (!shr) {
+			cache = GITS_BASER_nC;
+			__flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));
+		}
+		goto retry_baser;
+	}
+
+	if ((val ^ tmp) & GITS_BASER_PAGE_SIZE_MASK) {
+		/*
+		 * Page size didn't stick. Let's try a smaller
+		 * size and retry. If we reach 4K, then
+		 * something is horribly wrong...
+		 */
+		free_pages((unsigned long)base, order);
+		baser->base = NULL;
+
+		switch (psz) {
+		case SZ_16K:
+			psz = SZ_4K;
+			goto retry_alloc_baser;
+		case SZ_64K:
+			psz = SZ_16K;
+			goto retry_alloc_baser;
+		}
+	}
+
+	if (val != tmp) {
+		pr_err("ITS@%lx: %s doesn't stick: %lx %lx\n",
+		       its->phys_base, its_base_type_string[type],
+		       (unsigned long) val, (unsigned long) tmp);
+		free_pages((unsigned long)base, order);
+		return -ENXIO;
+	}
+
+	baser->base = base;
+	baser->order = order;
+	baser->psz = psz;
+	baser->val = val;
+	tmp = indirect ? GITS_LVL1_ENTRY_SIZE : entry_size;
+
+	pr_info("ITS@%lx: allocated %d %s @%lx (%s, esz %d, psz %dK, shr %d)\n",
+		its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / tmp),
+		its_base_type_string[type],
+		(unsigned long)virt_to_phys(base),
+		indirect ? "indirect" : "flat", (int)entry_size,
+		psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
+
+	return 0;
+}
+
 static int its_alloc_tables(const char *node_name, struct its_node *its)
 {
-	int err;
-	int i;
-	int psz = SZ_64K;
+	u64 typer = readq_relaxed(its->base + GITS_TYPER);
+	u32 ids = GITS_TYPER_DEVBITS(typer);
 	u64 shr = GITS_BASER_InnerShareable;
-	u64 cache;
-	u64 typer;
-	u32 ids;
+	u64 cache = GITS_BASER_WaWb;
+	int psz = SZ_64K;
+	int err, i;
 
 	if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_22375) {
 		/*
 		 * erratum 22375: only alloc 8MB table size
 		 * erratum 24313: ignore memory access type
 		 */
-		cache	= 0;
+		cache	= GITS_BASER_nCnB;
 		ids	= 0x14;			/* 20 bits, 8MB */
-	} else {
-		cache	= GITS_BASER_WaWb;
-		typer	= readq_relaxed(its->base + GITS_TYPER);
-		ids	= GITS_TYPER_DEVBITS(typer);
 	}
 
 	its->device_ids = ids;
@@ -853,13 +963,16 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 		u64 type = GITS_BASER_TYPE(val);
 		u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
 		int order = get_order(psz);
-		int alloc_pages;
-		u64 tmp;
-		void *base;
+		struct its_baser *baser = its->tables + i;
 
 		if (type == GITS_BASER_TYPE_NONE)
 			continue;
 
+		/* Set preferred settings for this BASERn */
+		baser->hwreg = its->base + GITS_BASER + i * 8;
+		baser->val = cache | shr;
+		baser->psz = psz;
+
 		/*
 		 * Allocate as many entries as required to fit the
 		 * range of device IDs that the ITS can grok... The ID
@@ -875,115 +988,28 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 			 * smaller than that.  If the requested allocation
 			 * is smaller, round up to the default page granule.
 			 */
-			order = max(get_order((1UL << ids) * entry_size),
-				    order);
+			order = max(get_order(entry_size << ids), order);
 			if (order >= MAX_ORDER) {
 				order = MAX_ORDER - 1;
-				pr_warn("%s: Device Table too large, reduce its page order to %u\n",
-					node_name, order);
-			}
-		}
-
-retry_alloc_baser:
-		alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
-		if (alloc_pages > GITS_BASER_PAGES_MAX) {
-			alloc_pages = GITS_BASER_PAGES_MAX;
-			order = get_order(GITS_BASER_PAGES_MAX * psz);
-			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
-				node_name, order, alloc_pages);
-		}
-
-		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
-		if (!base) {
-			err = -ENOMEM;
-			goto out_free;
-		}
-
-		its->tables[i].base = base;
-		its->tables[i].order = order;
-
-retry_baser:
-		val = (virt_to_phys(base) 				 |
-		       (type << GITS_BASER_TYPE_SHIFT)			 |
-		       ((entry_size - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) |
-		       cache						 |
-		       shr						 |
-		       GITS_BASER_VALID);
-
-		switch (psz) {
-		case SZ_4K:
-			val |= GITS_BASER_PAGE_SIZE_4K;
-			break;
-		case SZ_16K:
-			val |= GITS_BASER_PAGE_SIZE_16K;
-			break;
-		case SZ_64K:
-			val |= GITS_BASER_PAGE_SIZE_64K;
-			break;
-		}
-
-		val |= alloc_pages - 1;
-		its->tables[i].val = val;
-
-		writeq_relaxed(val, its->base + GITS_BASER + i * 8);
-		tmp = readq_relaxed(its->base + GITS_BASER + i * 8);
-
-		if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
-			/*
-			 * Shareability didn't stick. Just use
-			 * whatever the read reported, which is likely
-			 * to be the only thing this redistributor
-			 * supports. If that's zero, make it
-			 * non-cacheable as well.
-			 */
-			shr = tmp & GITS_BASER_SHAREABILITY_MASK;
-			if (!shr) {
-				cache = GITS_BASER_nC;
-				__flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));
+				ids = ilog2(PAGE_ORDER_TO_SIZE(order) / entry_size);
+				pr_warn("ITS@%lx:: Device Table too large, reduce ids %u->%u\n",
+					its->phys_base, its->device_ids, ids);
 			}
-			goto retry_baser;
 		}
 
-		if ((val ^ tmp) & GITS_BASER_PAGE_SIZE_MASK) {
-			/*
-			 * Page size didn't stick. Let's try a smaller
-			 * size and retry. If we reach 4K, then
-			 * something is horribly wrong...
-			 */
-			free_pages((unsigned long)base, order);
-			its->tables[i].base = NULL;
-
-			switch (psz) {
-			case SZ_16K:
-				psz = SZ_4K;
-				goto retry_alloc_baser;
-			case SZ_64K:
-				psz = SZ_16K;
-				goto retry_alloc_baser;
-			}
-		}
-
-		if (val != tmp) {
-			pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n",
-			       node_name, i,
-			       (unsigned long) val, (unsigned long) tmp);
-			err = -ENXIO;
-			goto out_free;
+		err = its_baser_setup(its, baser, order, 0);
+		if (err < 0) {
+			its_free_tables(its);
+			return err;
 		}
 
-		pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n",
-			(int)(PAGE_ORDER_TO_SIZE(order) / entry_size),
-			its_base_type_string[type],
-			(unsigned long)virt_to_phys(base),
-			psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
+		/* Update settings which will be used for next BASERn */
+		psz = baser->psz;
+		cache = baser->val & GITS_BASER_CACHEABILITY_MASK;
+		shr = baser->val & GITS_BASER_SHAREABILITY_MASK;
 	}
 
 	return 0;
-
-out_free:
-	its_free_tables(its);
-
-	return err;
 }
 
 static int its_alloc_collections(struct its_node *its)
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 9e6fdd3..7f917b9 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -204,6 +204,7 @@
 #define GITS_BASER_NR_REGS		8
 
 #define GITS_BASER_VALID		(1UL << 63)
+#define GITS_BASER_INDIRECT		(1UL << 62)
 #define GITS_BASER_nCnB			(0UL << 59)
 #define GITS_BASER_nC			(1UL << 59)
 #define GITS_BASER_RaWt			(2UL << 59)
@@ -228,6 +229,7 @@
 #define GITS_BASER_PAGE_SIZE_64K	(2UL << GITS_BASER_PAGE_SIZE_SHIFT)
 #define GITS_BASER_PAGE_SIZE_MASK	(3UL << GITS_BASER_PAGE_SIZE_SHIFT)
 #define GITS_BASER_PAGES_MAX		256
+#define GITS_BASER_PAGES_SHIFT		(0)
 
 #define GITS_BASER_TYPE_NONE		0
 #define GITS_BASER_TYPE_DEVICE		1
@@ -238,6 +240,7 @@
 #define GITS_BASER_TYPE_RESERVED6	6
 #define GITS_BASER_TYPE_RESERVED7	7
 
+#define GITS_LVL1_ENTRY_SIZE		(8UL)
 /*
  * ITS commands
  */
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project



From shankerd at codeaurora.org  Mon May  9 13:58:26 2016
From: shankerd at codeaurora.org (Shanker Donthineni)
Date: Mon,  9 May 2016 15:58:26 -0500
Subject: [PATCH V3 2/2] irqchip/gicv3-its: Implement two-level(indirect)
 device table support
In-Reply-To: <1462827506-23570-1-git-send-email-shankerd@codeaurora.org>
References: <1462827506-23570-1-git-send-email-shankerd@codeaurora.org>
Message-ID: <1462827506-23570-3-git-send-email-shankerd@codeaurora.org>

Since device IDs are extremely sparse, the single, a.k.a flat table is
not sufficient for the following two reasons.

1) According to ARM-GIC spec, ITS hw can access maximum of 256(pages)*
   64K(pageszie) bytes. In the best case, it supports upto DEVid=21
   sparse with minimum device table entry size 8bytes.

2) The maximum memory size that is possible without memblock depends on
   MAX_ORDER. 4MB on 4K page size kernel with default MAX_ORDER, so it
   supports DEVid range 19bits.

The two-level device table feature brings us two advantages, the first
is a very high possibility of supporting upto 32bit sparse, and the
second one is the best utilization of memory allocation.

The feature is enabled automatically during driver probe if a single
ITS page is not adequate for flat table and the hardware is capable
of two-level table walk.

Signed-off-by: Shanker Donthineni <shankerd at codeaurora.org>
---

Changes since v2:
  Fixed a porting bug device 'id' validation check in its_alloc_device_table()

Changes since v1:
  Most of this patch has been rewritten after refactoring its_alloc_tables().
  Always enable device two-level if the memory requirement is more than PAGE_SIZE.
  Fixed the coding bug that breaks on the BE machine.
  Edited the commit text.

 drivers/irqchip/irq-gic-v3-its.c | 97 +++++++++++++++++++++++++++++++++-------
 1 file changed, 80 insertions(+), 17 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index b23e00c..60a1060 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -938,6 +938,18 @@ retry_baser:
 	return 0;
 }
 
+/**
+ * Find out whether an implemented baser register supports a single, flat table
+ * or a two-level table by reading bit offset at '62' after writing '1' to it.
+ */
+static u64 its_baser_check_indirect(struct its_baser *baser)
+{
+	u64 val = GITS_BASER_InnerShareable | GITS_BASER_WaWb;
+
+	writeq_relaxed(val | GITS_BASER_INDIRECT, baser->hwreg);
+	return (readq_relaxed(baser->hwreg) & GITS_BASER_INDIRECT);
+}
+
 static int its_alloc_tables(const char *node_name, struct its_node *its)
 {
 	u64 typer = readq_relaxed(its->base + GITS_TYPER);
@@ -964,6 +976,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 		u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
 		int order = get_order(psz);
 		struct its_baser *baser = its->tables + i;
+		u64 indirect = 0;
 
 		if (type == GITS_BASER_TYPE_NONE)
 			continue;
@@ -977,17 +990,27 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 		 * Allocate as many entries as required to fit the
 		 * range of device IDs that the ITS can grok... The ID
 		 * space being incredibly sparse, this results in a
-		 * massive waste of memory.
+		 * massive waste of memory if two-level device table
+		 * feature is not supported by hardware.
 		 *
 		 * For other tables, only allocate a single page.
 		 */
 		if (type == GITS_BASER_TYPE_DEVICE) {
-			/*
-			 * 'order' was initialized earlier to the default page
-			 * granule of the the ITS.  We can't have an allocation
-			 * smaller than that.  If the requested allocation
-			 * is smaller, round up to the default page granule.
-			 */
+			if ((entry_size << ids) > psz)
+				indirect = its_baser_check_indirect(baser);
+
+			if (indirect) {
+				/*
+				 * The size of the lvl2 table is equal to ITS
+				 * page size which is 'psz'. For computing lvl1
+				 * table size, subtract ID bits that sparse
+				 * lvl2 table from 'ids' which is reported by
+				 * ITS hardware times lvl1 table entry size.
+				 */
+				ids -= ilog2(psz / entry_size);
+				entry_size = GITS_LVL1_ENTRY_SIZE;
+			}
+
 			order = max(get_order(entry_size << ids), order);
 			if (order >= MAX_ORDER) {
 				order = MAX_ORDER - 1;
@@ -997,7 +1020,7 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 			}
 		}
 
-		err = its_baser_setup(its, baser, order, 0);
+		err = its_baser_setup(its, baser, order, indirect);
 		if (err < 0) {
 			its_free_tables(its);
 			return err;
@@ -1187,10 +1210,57 @@ static struct its_baser *its_get_baser(struct its_node *its, u32 type)
 	return NULL;
 }
 
+static bool its_alloc_device_table(struct its_node *its, u32 dev_id)
+{
+	struct its_baser *baser;
+	struct page *page;
+	u32 esz, idx;
+	u64 *table;
+
+	baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
+
+	/* Don't allow device id that exceeds ITS hardware limit */
+	if (!baser)
+		return (ilog2(dev_id) < its->device_ids);
+
+	/* Don't allow device id that exceeds single, flat table limit */
+	esz = GITS_BASER_ENTRY_SIZE(baser->val);
+	if (!(baser->val & GITS_BASER_INDIRECT))
+		return (dev_id < (PAGE_ORDER_TO_SIZE(baser->order) / esz));
+
+	/* Compute 1st level table index & check if that exceeds table limit */
+	idx = dev_id >> ilog2(baser->psz / esz);
+	if (idx >= (PAGE_ORDER_TO_SIZE(baser->order) / GITS_LVL1_ENTRY_SIZE))
+		return false;
+
+	table = baser->base;
+
+	/* Allocate memory for 2nd level table */
+	if (!table[idx]) {
+		page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(baser->psz));
+		if (!page)
+			return false;
+
+		/* Flush memory to PoC if hardware doesn't support coherency */
+		if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
+			__flush_dcache_area(page_address(page), baser->psz);
+
+		table[idx] = cpu_to_le64(page_to_phys(page) | GITS_BASER_VALID);
+
+		/* Flush memory to PoC if hardware doesn't support coherency */
+		if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
+			__flush_dcache_area(table + idx, GITS_LVL1_ENTRY_SIZE);
+
+		/* Ensure updated table contents are visible to ITS hardware */
+		dsb(sy);
+	}
+
+	return true;
+}
+
 static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 					    int nvecs)
 {
-	struct its_baser *baser;
 	struct its_device *dev;
 	unsigned long *lpi_map;
 	unsigned long flags;
@@ -1201,14 +1271,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 	int nr_ites;
 	int sz;
 
-	baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
-
-	/* Don't allow 'dev_id' that exceeds single, flat table limit */
-	if (baser) {
-		if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) /
-			      GITS_BASER_ENTRY_SIZE(baser->val)))
-			return NULL;
-	} else if (ilog2(dev_id) >= its->device_ids)
+	if (!its_alloc_device_table(its, dev_id))
 		return NULL;
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-- 
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
a Linux Foundation Collaborative Project



From javier at osg.samsung.com  Mon May  9 13:59:36 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 16:59:36 -0400
Subject: [PATCH v2 12/22] ARM: dts: exynos: Split Odroid XU3 LEDs to
 separate DTSI
In-Reply-To: <1462734367-5619-13-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-13-git-send-email-krzk@kernel.org>
Message-ID: <2188c75f-97c9-2081-9c5a-41e4198f4396@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> The LED nodes can be shared between Odroid XU3, XU3-Lite and XU (not yet
> added) thus removing duplication.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From olof at lixom.net  Mon May  9 14:03:22 2016
From: olof at lixom.net (Olof Johansson)
Date: Mon, 9 May 2016 14:03:22 -0700
Subject: Reverting ARCH_SUNXI arm64 support(?)
In-Reply-To: <20160509205716.GG3733@lukather>
References: <57304FF7.3080909@arm.com> <20160509090951.GC19763@arm.com>
 <5730714C.7010608@arm.com> <20160509205716.GG3733@lukather>
Message-ID: <CAOesGMiAeG1Sy1efAMVQxkRu-Wh7UY-awUcPPQPQ3BKswsYN5Q@mail.gmail.com>

On Mon, May 9, 2016 at 1:57 PM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> On Mon, May 09, 2016 at 12:15:24PM +0100, Andre Przywara wrote:
>> Hi,
>>
>> On 09/05/16 10:09, Will Deacon wrote:
>> > On Mon, May 09, 2016 at 09:53:11AM +0100, Andre Przywara wrote:
>> >> Hi Will, Catalin,
>> >
>> > Hi Andre,
>> >
>> >> Suzuki reported a build failure with certain (non-defconfig) .configs
>> >> due to the new ARCH_SUNXI support in 4.6-rc [1].
>> >> As unfortunately we couldn't agree on a solution and also the support
>> >> for the A64/Pine64 is partial in 4.6 anyway, can you please revert:
>> >> ce3dd55b99b151a90ac1701c6825f2ae2d49b54e ("arm64: Introduce Allwinner
>> >> SoC config option")
>> >
>> > Given that we (Catalin and I) didn't commit that patch, it seems weird
>> > that we should be reverting it. Shouldn't this be handled in arm-soc or
>> > via the sunxi subtree?
>> >
>> > We're also a week from the merge window, so it doesn't seem like a good
>> > time to be hacking at .config/kconfig-related issues.
>>
>> I agree, that's why I was proposing taking Suzuki's first patch:
>>
>> diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
>> index efa77c1..521b1ec 100644
>> --- a/arch/arm64/Kconfig.platforms
>> +++ b/arch/arm64/Kconfig.platforms
>> @@ -2,6 +2,7 @@ menu "Platform selection"
>>
>>  config ARCH_SUNXI
>>       bool "Allwinner sunxi 64-bit SoC Family"
>> +     select GENERIC_IRQ_CHIP
>>       help
>>         This enables support for Allwinner sunxi based SoCs like the A64.
>>
>>
>> This is what defconfig selects anyway and also the change would be
>> confined to this (new) config option.
>>
>> Olof, Arnd: would it be an option to take this patch still?
>
> FWIW, I'd be in favour for such patch as a late patch for 4.6.
>
> We can always fix things up properly in a later patch for 4.7 or 4.8.

+1. Please send said patch to arm at kernel.org and we can apply it (cc
Maxime so he can cc) and send up.


-Olof


From robh at kernel.org  Mon May  9 14:07:35 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 16:07:35 -0500
Subject: [PATCH 4/7] [media] ir-rx51: add DT support to driver
In-Reply-To: <5730F8BA.5000402@gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <1462634508-24961-5-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <20160509200657.GA3379@rob-hp-laptop> <5730F8BA.5000402@gmail.com>
Message-ID: <CAL_JsqJPZS1ne_xAuBFtCc5L1HKFJf0LDUJ7CRSFXhc3adkTfA@mail.gmail.com>

On Mon, May 9, 2016 at 3:53 PM, Ivaylo Dimitrov
<ivo.g.dimitrov.75 at gmail.com> wrote:
> Hi,
>
> On  9.05.2016 23:06, Rob Herring wrote:
>>
>> On Sat, May 07, 2016 at 06:21:45PM +0300, Ivaylo Dimitrov wrote:
>>>
>>> With the upcoming removal of legacy boot, lets add support to one of the
>>> last N900 drivers remaining without it. As the driver still uses omap
>>> dmtimer, add auxdata as well.
>>>
>>> Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
>>> ---
>>>   .../devicetree/bindings/media/nokia,lirc-rx51         | 19
>>> +++++++++++++++++++
>>>   arch/arm/mach-omap2/pdata-quirks.c                    |  6 +-----
>>>   drivers/media/rc/ir-rx51.c                            | 11 ++++++++++-
>>>   3 files changed, 30 insertions(+), 6 deletions(-)
>>>   create mode 100644
>>> Documentation/devicetree/bindings/media/nokia,lirc-rx51
>>>
>>> diff --git a/Documentation/devicetree/bindings/media/nokia,lirc-rx51
>>> b/Documentation/devicetree/bindings/media/nokia,lirc-rx51
>>> new file mode 100644
>>> index 0000000..5b3081e
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/media/nokia,lirc-rx51
>>> @@ -0,0 +1,19 @@
>>> +Device-Tree bindings for LIRC TX driver for Nokia N900(RX51)
>>> +
>>> +Required properties:
>>> +       - compatible: should be "nokia,lirc-rx51".
>>
>>
>> lirc is a Linux term. Also, nokia,rx51-... would be conventional
>> ordering.
>>
>
> I used the driver name ("lirc_rx51") to not bring confusion. Also, it
> registers itself through lirc_register_driver() call, so having lirc in its
> name somehow makes sense.
>
> I am not very good in inventing names, the best compatible I can think of is
> "nokia,rx51-ir". Is that ok?

Sure, but...

>> Is this anything more than a PWM LED?
>>
>
> It is an IR LED connected through a driver to McSPI2_SIMO pin of OMAP3,
> which pin can be configured as PWM or GPIO(there are other configurations,
> but they don't make sense). In theory it could be used for various things
> (like uni-directional serial TX, or stuff like that), but in practice it
> allows N900 to be act as an IR remote controller. I guess that fits in
> "nothing more than a PWM LED", more or less.

There's already a pwm-led binding that can be used. Though there may
be missing consumer IR to LED subsystem support in the kernel. You
could list both compatibles, use the rx51 IR driver now, and then move
to pwm-led driver in the future.

Rob


From sre at kernel.org  Mon May  9 14:21:19 2016
From: sre at kernel.org (Sebastian Reichel)
Date: Mon, 9 May 2016 23:21:19 +0200
Subject: [PATCH 0/3] HSI: omap-ssi: regressions against yesterday's
 linux-next
In-Reply-To: <1462288586-584690-1-git-send-email-arnd@arndb.de>
References: <1462288586-584690-1-git-send-email-arnd@arndb.de>
Message-ID: <20160509212118.GD1129@earth>

Hi Arnd,

On Tue, May 03, 2016 at 05:16:19PM +0200, Arnd Bergmann wrote:
> One patch you added yesterday unfortunately caused (at least) three
> separate build problems with 32-bit ARM randconfig builds.
> 
> These three patches should make it all work again.

Sorry for the delayed respones, I was on vacation last week and
asked Stephen to temp. disable the HSI tree. I just applied all
patches and asked him to reenable it.

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160509/b6561e5d/attachment.sig>

From javier at osg.samsung.com  Mon May  9 14:25:14 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 17:25:14 -0400
Subject: [PATCH v2 13/22] ARM: dts: exynos: Move common nodes to
 exynos5.dtsi
In-Reply-To: <1462734367-5619-14-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-14-git-send-email-krzk@kernel.org>
Message-ID: <1cee1acf-fb07-9a7f-5d18-b4824a10f5a2@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> Exynos5420 and Exynos5250 share some nodes: the PWM and syscon
> (sysreg_system_controller). Move them to parent DTSI to avoid
> duplication.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

I see that the i2c_[0-3] nodes are also the same in both DTSI. Do you
think that makes sense to also move those to exynos5.dtsi as well?

In any case that can be made as a follow-up, so:

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Mon May  9 14:27:23 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 17:27:23 -0400
Subject: [PATCH v2 14/22] ARM: dts: exynos: Prepare for inclusion of
 exynos5.dtsi in exynos5410.dtsi
In-Reply-To: <1462734367-5619-15-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-15-git-send-email-krzk@kernel.org>
Message-ID: <7527f343-c38f-71a8-0bec-5fac3105d6dd@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> Add 'sromc' label to SROM memory controller in common exynos5.dtsi so it
> can be referenced by inheriting DTSI.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Mon May  9 14:29:48 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 17:29:48 -0400
Subject: [PATCH v2 15/22] ARM: dts: exynos: Use phandle to get parent node
 in exynos5250-snow
In-Reply-To: <1462734367-5619-16-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-16-git-send-email-krzk@kernel.org>
Message-ID: <a978eba1-5dc9-0b20-d131-b180047cc143@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:06 PM, Krzysztof Kozlowski wrote:
> The i2c-arbitrator node in exynos5250-snow-common used absolute path to
> reference other node (the i2c parent). Use phandle instead, because the
> depth of the other node may be changed (like moving it under 'soc'
> node).
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Mon May  9 14:35:03 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 17:35:03 -0400
Subject: [PATCH v2 16/22] ARM: dts: exynos: Move Exynos5250 and Exynos5420
 nodes under soc
In-Reply-To: <1462734367-5619-17-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-17-git-send-email-krzk@kernel.org>
Message-ID: <4d0516dc-bed4-8017-374b-bd197a64026f@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:06 PM, Krzysztof Kozlowski wrote:
> The conventions it to put SoC devices under 'soc' node. In fact other

s/it/is

> our DTSes (like exynos3250.dtsi or exynos5410.dtsi) already follows it.
> Adjust exynos5250 and exynos5420 DTSI to follow this convention. This is
> also necessary for the upcoming change in exynos5410.dtsi to inherit
> from common exynos5.dtsi.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Mon May  9 14:39:51 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 17:39:51 -0400
Subject: [PATCH v2 17/22] ARM: dts: exynos: Include common exynos5 in
 exynos5410.dtsi
In-Reply-To: <1462734367-5619-18-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-18-git-send-email-krzk@kernel.org>
Message-ID: <89bcdacc-e404-ad55-c087-92ba87901ee4@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:06 PM, Krzysztof Kozlowski wrote:
> The exynos5.dtsi is used for common nodes shared between Exynos5250 and
> Exynos542x. Since Exynos5410 is very similar to Exynos5420 it can
> include the common file as well to remove duplication and make
> everything more consistent.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Mon May  9 14:40:51 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 17:40:51 -0400
Subject: [PATCH v2 18/22] ARM: dts: exynos: Enable UART3 on Exynos5410
In-Reply-To: <1462734367-5619-19-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-19-git-send-email-krzk@kernel.org>
Message-ID: <abd835c4-efd4-8f49-88d5-d05680e42e4f@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:06 PM, Krzysztof Kozlowski wrote:
> Just like other Exynos5 family SoCs, this one has four UARTs. Configure
> clocks for UART3 and enable it.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From d-gerlach at ti.com  Mon May  9 14:41:51 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Mon, 9 May 2016 16:41:51 -0500
Subject: [RFC PATCH 3/3] misc: SRAM: Add option to map SRAM to allow code
 execution
In-Reply-To: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
References: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
Message-ID: <1462830111-28172-4-git-send-email-d-gerlach@ti.com>

Allow option for mapping SRAM as executable. DT node can specify
"memory-exec" and "memory-exec-nocache" to also map it as non-cached.
This is useful for platforms using the sram driver that need to run
PM code from sram like several ARM platforms.

Signed-off-by: Russ Dill <Russ.Dill at ti.com>
Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 Documentation/devicetree/bindings/sram/sram.txt | 2 ++
 drivers/misc/sram.c                             | 8 ++++++++
 2 files changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/sram/sram.txt b/Documentation/devicetree/bindings/sram/sram.txt
index 227e3a341af1..1f1d0aa52703 100644
--- a/Documentation/devicetree/bindings/sram/sram.txt
+++ b/Documentation/devicetree/bindings/sram/sram.txt
@@ -29,6 +29,8 @@ Optional properties in the sram node:
 
 - no-memory-wc : the flag indicating, that SRAM memory region has not to
                  be remapped as write combining. WC is used by default.
+- memory-exec : map range to allow code execution
+- memory-exec-nocache : map range to allow code execution and also non-cached
 
 Required properties in the area nodes:
 
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index 69cdabea9c03..7f00ba574a83 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -362,6 +362,14 @@ static int sram_probe(struct platform_device *pdev)
 
 	if (of_property_read_bool(pdev->dev.of_node, "no-memory-wc"))
 		sram->virt_base = devm_ioremap(sram->dev, res->start, size);
+	else if (of_property_read_bool(pdev->dev.of_node, "memory-exec"))
+		sram->virt_base = devm_ioremap_exec(sram->dev, res->start,
+						    size);
+	else if (of_property_read_bool(pdev->dev.of_node,
+				       "memory-exec-nocache"))
+		sram->virt_base = devm_ioremap_exec_nocache(sram->dev,
+							    res->start,
+							    size);
 	else
 		sram->virt_base = devm_ioremap_wc(sram->dev, res->start, size);
 	if (IS_ERR(sram->virt_base))
-- 
2.7.3



From d-gerlach at ti.com  Mon May  9 14:41:48 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Mon, 9 May 2016 16:41:48 -0500
Subject: [RFC PATCH 0/3] Add ioremap_exec and extend drivers/misc/sram.c
Message-ID: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>

Hi,
There are several instances when one would want to execute out of on-chip
SRAM, such as PM code on ARM platforms, so once again revisiting this
series to allow that. Seems that having a solution for allowing SRAM to be
mapped as executable will help clean up PM code on several ARM platforms and
also open the door for others like TI AM335x and AM437x. This was first sent
here [1] but this is rebased and updated for v4.6-rc.

Many platforms have migrated to using the generic SRAM driver at
drivers/misc/sram.c but it doesn't seem like there is a clean solution
for the common problem of needing to map executable pages.

Currently I see several platforms (at-91, imx6, socfpga) taking the
address allocated by the genpool given by the SRAM driver and then calling
__arm_ioremap_exec on it again to get a new address that can be executed.
This doesn't seem like the cleanest solution, but maybe it works for code
that is under mach-xxx but what about code that migrates outside into the
drivers layer? Do any other architectures have a requirement for this?

I've converted omap3 PM code to use the generic SRAM driver which I'll send
in a series right after this one, and AM335x and AM437x can both make use of
this series as well and even go as far as to move a chunk of the PM
code into drivers (needs to be updated but sent long ago here [2]), but
that will be blocked if we don't have a generic way to ioremap memory as
exec, or at least a way to do it from drivers/.

If we don't want to go down this path, is there a better idea for how to
call ioremap_exec from drivers/ that we can all agree on?

Regards,
Dave

[1] https://lkml.org/lkml/2014/11/26/575
[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2014-November/306534.html

Dave Gerlach (1):
  misc: SRAM: Add option to map SRAM to allow code execution

Russ Dill (2):
  asm-generic: io: Add exec versions of ioremap
  lib: devres: Add exec and exec_nocache versions of devm_ioremap

 Documentation/devicetree/bindings/sram/sram.txt |  2 +
 arch/arm/include/asm/io.h                       |  5 +++
 arch/arm/mm/ioremap.c                           | 14 ++++++
 arch/arm/mm/nommu.c                             | 14 ++++++
 drivers/misc/sram.c                             |  8 ++++
 include/asm-generic/iomap.h                     |  5 +++
 include/linux/io.h                              |  5 +++
 lib/devres.c                                    | 58 +++++++++++++++++++++++++
 8 files changed, 111 insertions(+)

-- 
2.7.3



From d-gerlach at ti.com  Mon May  9 14:41:49 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Mon, 9 May 2016 16:41:49 -0500
Subject: [RFC PATCH 1/3] asm-generic: io: Add exec versions of ioremap
In-Reply-To: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
References: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
Message-ID: <1462830111-28172-2-git-send-email-d-gerlach@ti.com>

From: Russ Dill <russ.dill at ti.com>

If code is to be copied into and area (such as SRAM) and run,
it needs to be marked as exec. Currently only an ARM version
of this exists, but a generic version will be useful for drivers.

Signed-off-by: Russ Dill <Russ.Dill at ti.com>
Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/include/asm/io.h   |  5 +++++
 arch/arm/mm/ioremap.c       | 14 ++++++++++++++
 arch/arm/mm/nommu.c         | 14 ++++++++++++++
 include/asm-generic/iomap.h |  5 +++++
 4 files changed, 38 insertions(+)

diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 485982084fe9..7d07a02cb7bc 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -399,6 +399,11 @@ void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size);
 #define ioremap_wc ioremap_wc
 #define ioremap_wt ioremap_wc
 
+void __iomem *ioremap_exec(resource_size_t res_cookie, size_t size);
+void __iomem *ioremap_exec_nocache(resource_size_t res_cookie, size_t size);
+#define ioremap_exec ioremap_exec
+#define ioremap_exec_nocache ioremap_exec_nocache
+
 void iounmap(volatile void __iomem *iomem_cookie);
 #define iounmap iounmap
 
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 66a978d05958..c6eef3c98074 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -400,6 +400,20 @@ EXPORT_SYMBOL(ioremap_wc);
  * clocks that would affect normal memory for example. Please see
  * CONFIG_GENERIC_ALLOCATOR for allocating external memory.
  */
+void __iomem *ioremap_exec(resource_size_t res_cookie, size_t size)
+{
+	return arch_ioremap_caller(res_cookie, size, MT_MEMORY_RWX,
+				   __builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap_exec);
+
+void __iomem *ioremap_exec_nocache(resource_size_t res_cookie, size_t size)
+{
+	return arch_ioremap_caller(res_cookie, size, MT_MEMORY_RWX_NONCACHED,
+				   __builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap_exec_nocache);
+
 void __iomem *
 __arm_ioremap_exec(phys_addr_t phys_addr, size_t size, bool cached)
 {
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 1dd10936d68d..1d1d587340e6 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -380,6 +380,20 @@ void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size)
 }
 EXPORT_SYMBOL(ioremap_wc);
 
+void __iomem *ioremap_exec(resource_size_t res_cookie, size_t size)
+{
+	return __arm_ioremap_caller(res_cookie, size, 0,
+				    __builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap_exec);
+
+void __iomem *ioremap_exec_nocache(resource_size_t res_cookie, size_t size)
+{
+	return __arm_ioremap_caller(res_cookie, size, 0,
+				    __builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap_exec_nocache);
+
 void __iounmap(volatile void __iomem *addr)
 {
 }
diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h
index d8f8622fa044..a789aad509c3 100644
--- a/include/asm-generic/iomap.h
+++ b/include/asm-generic/iomap.h
@@ -70,6 +70,11 @@ extern void ioport_unmap(void __iomem *);
 #define ioremap_wt ioremap_nocache
 #endif
 
+#ifndef ARCH_HAS_IOREMAP_EXEC
+#define ioremap_exec ioremap
+#define ioremap_exec_nocache ioremap_nocache
+#endif
+
 #ifdef CONFIG_PCI
 /* Destroy a virtual mapping cookie for a PCI BAR (memory or IO) */
 struct pci_dev;
-- 
2.7.3



From d-gerlach at ti.com  Mon May  9 14:41:50 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Mon, 9 May 2016 16:41:50 -0500
Subject: [RFC PATCH 2/3] lib: devres: Add exec and exec_nocache versions of
 devm_ioremap
In-Reply-To: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
References: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
Message-ID: <1462830111-28172-3-git-send-email-d-gerlach@ti.com>

From: Russ Dill <russ.dill at ti.com>

Now that there are _exec and _exec_nocache versions of ioremap, add devm
support for them.

Signed-off-by: Russ Dill <Russ.Dill at ti.com>
Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 include/linux/io.h |  5 +++++
 lib/devres.c       | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/include/linux/io.h b/include/linux/io.h
index e2c8419278c1..1c0442e5d72c 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -79,6 +79,11 @@ void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
 				   resource_size_t size);
 void __iomem *devm_ioremap_wc(struct device *dev, resource_size_t offset,
 				   resource_size_t size);
+void __iomem *devm_ioremap_exec(struct device *dev, resource_size_t offset,
+				unsigned long size);
+void __iomem *devm_ioremap_exec_nocache(struct device *dev,
+					resource_size_t offset,
+					unsigned long size);
 void devm_iounmap(struct device *dev, void __iomem *addr);
 int check_signature(const volatile void __iomem *io_addr,
 			const unsigned char *signature, int length);
diff --git a/lib/devres.c b/lib/devres.c
index cb1464c411a2..1181a739fd49 100644
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -100,6 +100,64 @@ void __iomem *devm_ioremap_wc(struct device *dev, resource_size_t offset,
 EXPORT_SYMBOL(devm_ioremap_wc);
 
 /**
+ * devm_ioremap_exec - Managed ioremap_exec()
+ * @dev: Generic device to remap IO address for
+ * @offset: BUS offset to map
+ * @size: Size of map
+ *
+ * Managed ioremap_exec().  Map is automatically unmapped on driver detach.
+ */
+void __iomem *devm_ioremap_exec(struct device *dev, resource_size_t offset,
+				unsigned long size)
+{
+	void __iomem **ptr, *addr;
+
+	ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return NULL;
+
+	addr = ioremap_exec(offset, size);
+	if (addr) {
+		*ptr = addr;
+		devres_add(dev, ptr);
+	} else
+		devres_free(ptr);
+
+	return addr;
+}
+EXPORT_SYMBOL(devm_ioremap_exec);
+
+/**
+ * devm_ioremap_exec_nocache - Managed ioremap_exec_nocache()
+ * @dev: Generic device to remap IO address for
+ * @offset: BUS offset to map
+ * @size: Size of map
+ *
+ * Managed ioremap_exec_nocache().  Map is automatically unmapped on driver
+ * detach.
+ */
+void __iomem *devm_ioremap_exec_nocache(struct device *dev,
+					resource_size_t offset,
+					unsigned long size)
+{
+	void __iomem **ptr, *addr;
+
+	ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return NULL;
+
+	addr = ioremap_exec_nocache(offset, size);
+	if (addr) {
+		*ptr = addr;
+		devres_add(dev, ptr);
+	} else
+		devres_free(ptr);
+
+	return addr;
+}
+EXPORT_SYMBOL(devm_ioremap_exec_nocache);
+
+/**
  * devm_iounmap - Managed iounmap()
  * @dev: Generic device to unmap for
  * @addr: Address to unmap
-- 
2.7.3



From javier at osg.samsung.com  Mon May  9 14:44:54 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 17:44:54 -0400
Subject: [PATCH v2 19/22] ARM: dts: exynos: MCT is not an interrupt
 controller and extend length of iomap
In-Reply-To: <1462734367-5619-20-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-20-git-send-email-krzk@kernel.org>
Message-ID: <cd2cfef1-f9a8-0daa-e4bc-c00b0943c52e@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:06 PM, Krzysztof Kozlowski wrote:
> Multi-Core Timer generates interrupts but it is not really an interrupt
> controller so remove the "interrupt-controller" and "interrupt-cells"
> properties. Additionally extend the length of mapped memory to cover all
> registers (last SFR is at 0x0A40).
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From d-gerlach at ti.com  Mon May  9 14:49:20 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Mon, 9 May 2016 16:49:20 -0500
Subject: [PATCH 0/6] ARM: OMAP3: Convert OMAP3 PM code to use generic sram
 driver
Message-ID: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>

Hi,
This series adds support for OMAP3 platforms to use the generic SRAM driver
at drivers/misc/sram.c. It depends on the patches sent here [1], which were
sent as an RFC so if that series does not get accepted we will need to find
a different method of marking SRAM region as executable so this series will
need to change slightly.

The idea of this series is to add the ocmcram nodes to the DT files before
converting the pm34xx to use the genalloc API allocate space for the
sleep34xx.S code so that we do not break PM. After we do the conversion
we can drop the legacy mach-omap2 SRAM code for OMAP3 as we no longer will
have any dependency on it.

Tested suspend and off-mode on omap3-beaglexm and omap3-n900, cpuidle works
fine as well.

Regards,
Dave

[1] http://lkml.iu.edu/hypermail/linux/kernel/1605.1/01069.html

Dave Gerlach (6):
  Documentation: sram: ti: Add TI SRAM bindings
  ARM: dts: omap3: Add ocmcram node
  ARM: dts: omap3-n900: Add secure reserved region to ocmcram node
  ARM: OMAP2+: pm34xx: Convert to use generic sram driver for idle code
  ARM: OMAP2+: Remove legacy sram init code for omap3 platforms
  ARM: OMAP2+: sram: remove legacy OMAP3 code

 Documentation/devicetree/bindings/sram/ti-sram.txt | 47 +++++++++++
 arch/arm/boot/dts/omap3-n900.dts                   |  7 ++
 arch/arm/boot/dts/omap3.dtsi                       | 11 +++
 arch/arm/mach-omap2/pdata-quirks.c                 |  3 +-
 arch/arm/mach-omap2/pm34xx.c                       | 98 ++++++++++++++++++----
 arch/arm/mach-omap2/sram.c                         | 23 -----
 6 files changed, 147 insertions(+), 42 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sram/ti-sram.txt

-- 
2.7.3



From d-gerlach at ti.com  Mon May  9 14:49:21 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Mon, 9 May 2016 16:49:21 -0500
Subject: [PATCH 1/6] Documentation: sram: ti: Add TI SRAM bindings
In-Reply-To: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>
References: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>
Message-ID: <1462830566-28708-2-git-send-email-d-gerlach@ti.com>

Add binding document for TI use of mmio-sram driver for purposes like
mapping the region as executable or reserving space needed by secure
silicon.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 Documentation/devicetree/bindings/sram/ti-sram.txt | 47 ++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sram/ti-sram.txt

diff --git a/Documentation/devicetree/bindings/sram/ti-sram.txt b/Documentation/devicetree/bindings/sram/ti-sram.txt
new file mode 100644
index 000000000000..68c4b733c78c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sram/ti-sram.txt
@@ -0,0 +1,47 @@
+TI SRAM Node:
+-------------
+
+Many TI SoC's rely on SRAM for running low-level PM code as part of the
+suspend or cpuidle path. Because of this, regions in sram must be mapped
+as "memory-exec" or "memory-exec-nocache" in order for the region to be
+executable.
+
+Optional sub-node
+-----------------
+Some TI SoCs have secure variants that require a certain portion of
+the SRAM to be reserved for use by secure software. This can be
+marked in the parent SRAM node with a subnode as described in
+Documentation/devicetree/bindings/sram/sram.txt. This node can be
+added in two ways:
+
+- From board dts files for secure platforms to avoid adding it
+  for all SoC variants with a fixed size defined.
+- As a dummy node in the .dtsi sram node with any size that will be
+  modified by a bootloader to the correct size needed.
+
+Sub-node properties:
+- compatible : should be "ti,secure-sram"
+
+The rest of the properties should follow the generic mmio-sram discription
+found in Documentation/devicetree/bindings/sram/sram.txt
+
+Example:
+	/* In parent SoC .dtsi */
+	ocmcram: ocmcram at 40200000 {
+		compatible = "mmio-sram";
+		reg = <0x40200000 0x10000>; /* 64k */
+		memory-exec-nocache;
+		ranges = <0x0 0x40200000 0x10000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+	};
+
+	/* In board .dts where secure silicon is present */
+	&ocmcram {
+		sram-hs at 0 {
+			compatible = "ti,secure-ram";
+			reg = <0x0 0xC000>;
+		};
+	};
-- 
2.7.3



From d-gerlach at ti.com  Mon May  9 14:49:22 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Mon, 9 May 2016 16:49:22 -0500
Subject: [PATCH 2/6] ARM: dts: omap3: Add ocmcram node
In-Reply-To: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>
References: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>
Message-ID: <1462830566-28708-3-git-send-email-d-gerlach@ti.com>

Add an ocmcram node to omap3 dtsi using the mmio-sram driver to
represent the 64kb of SRAM available on omap3 and it's derivatives.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/boot/dts/omap3.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index b41d07e8e765..a267616c3c68 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -59,6 +59,7 @@
 		mpu {
 			compatible = "ti,omap3-mpu";
 			ti,hwmods = "mpu";
+			sram = <&ocmcram>;
 		};
 
 		iva: iva {
@@ -153,6 +154,16 @@
 			};
 		};
 
+		ocmcram: ocmcram at 40200000 {
+			compatible = "mmio-sram";
+			reg = <0x40200000 0x10000>; /* 64k */
+			memory-exec-nocache;
+			ranges = <0x0 0x40200000 0x10000>;
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
+
 		aes: aes at 480c5000 {
 			compatible = "ti,omap3-aes";
 			ti,hwmods = "aes";
-- 
2.7.3



From d-gerlach at ti.com  Mon May  9 14:49:23 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Mon, 9 May 2016 16:49:23 -0500
Subject: [PATCH 3/6] ARM: dts: omap3-n900: Add secure reserved region to
 ocmcram node
In-Reply-To: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>
References: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>
Message-ID: <1462830566-28708-4-git-send-email-d-gerlach@ti.com>

Platforms with secure silicon, like omap3-n900, need to mark off a
section of the ocmcram as reserved because it is used by secure
software.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/boot/dts/omap3-n900.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts
index b3c26a96a726..448452a76c23 100644
--- a/arch/arm/boot/dts/omap3-n900.dts
+++ b/arch/arm/boot/dts/omap3-n900.dts
@@ -1004,3 +1004,10 @@
 &ssi_port2 {
 	status = "disabled";
 };
+
+&ocmcram {
+	sram-hs at 0 {
+		compatible = "ti,secure-ram";
+		reg = <0x0 0xC000>;
+	};
+};
-- 
2.7.3



From d-gerlach at ti.com  Mon May  9 14:49:25 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Mon, 9 May 2016 16:49:25 -0500
Subject: [PATCH 5/6] ARM: OMAP2+: Remove legacy sram init code for omap3
 platforms
In-Reply-To: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>
References: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>
Message-ID: <1462830566-28708-6-git-send-email-d-gerlach@ti.com>

Remove omap3 platforms from using legacy sram init code in mach-omap2 as
the platforms will now use the generic mmio-sram driver like other omap
platforms already do.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/mach-omap2/pdata-quirks.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index a935d28443da..1a5b8afdb2e3 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -579,8 +579,7 @@ void __init pdata_quirks_init(const struct of_device_id *omap_dt_match_table)
 	 * We still need this for omap2420 and omap3 PM to work, others are
 	 * using drivers/misc/sram.c already.
 	 */
-	if (of_machine_is_compatible("ti,omap2420") ||
-	    of_machine_is_compatible("ti,omap3"))
+	if (of_machine_is_compatible("ti,omap2420"))
 		omap_sdrc_init(NULL, NULL);
 
 	pdata_quirks_check(auxdata_quirks);
-- 
2.7.3



From d-gerlach at ti.com  Mon May  9 14:49:24 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Mon, 9 May 2016 16:49:24 -0500
Subject: [PATCH 4/6] ARM: OMAP2+: pm34xx: Convert to use generic sram driver
 for idle code
In-Reply-To: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>
References: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>
Message-ID: <1462830566-28708-5-git-send-email-d-gerlach@ti.com>

Change to use the generic SRAM driver and genalloc framework to allocate
SRAM space for low-level ASM PM code instead of omap specific SRAM
allocator.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/mach-omap2/pm34xx.c | 82 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 81 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index d44e0e2f1106..5ebbf5c30c6e 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -24,17 +24,21 @@
 #include <linux/module.h>
 #include <linux/list.h>
 #include <linux/err.h>
+#include <linux/genalloc.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 #include <linux/omap-dma.h>
 #include <linux/omap-gpmc.h>
 #include <linux/platform_data/gpio-omap.h>
+#include <linux/sizes.h>
 
 #include <trace/events/power.h>
 
 #include <asm/fncpy.h>
+#include <asm/proc-fns.h>
 #include <asm/suspend.h>
 #include <asm/system_misc.h>
 
@@ -68,6 +72,9 @@ static LIST_HEAD(pwrst_list);
 
 static int (*_omap_save_secure_sram)(u32 *addr);
 void (*omap3_do_wfi_sram)(void);
+static struct gen_pool *sram_pool;
+static phys_addr_t ocmcram_location;
+static phys_addr_t secure_ocmcram_location;
 
 static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
@@ -179,6 +186,71 @@ static void omap34xx_save_context(u32 *save)
 	*save++ = val;
 }
 
+/*
+ * Push functions to SRAM
+ *
+ * The minimum set of functions is pushed to SRAM for execution:
+ * - omap3_do_wfi for erratum i581 WA,
+ * - save_secure_ram_context for security extensions.
+ */
+static int omap3_prepare_push_sram_idle(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "ti,omap3-mpu");
+	if (!np) {
+		pr_warn("PM: %s: Unable to find device node for mpu\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	sram_pool = of_gen_pool_get(np, "sram", 0);
+
+	if (!sram_pool) {
+		pr_warn("PM: %s: Unable to get sram pool for ocmcram\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	ocmcram_location = gen_pool_alloc(sram_pool, omap3_do_wfi_sz);
+	if (!ocmcram_location) {
+		pr_warn("PM: %s: Unable to allocate memory from ocmcram for omap3_do_wfi_sz.\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
+		secure_ocmcram_location =
+				gen_pool_alloc(sram_pool,
+					       save_secure_ram_context_sz);
+		if (!secure_ocmcram_location) {
+			pr_warn("PM: %s: Unable to allocate memory from ocmcram for save_secure_ram_context.\n",
+				__func__);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int omap3_push_sram_idle(void)
+{
+	omap3_do_wfi_sram = fncpy((void *)ocmcram_location,
+				  &omap3_do_wfi,
+				  omap3_do_wfi_sz);
+
+	return 0;
+}
+
+static int omap3_push_sram_secure_idle(void)
+{
+	if (omap_type() != OMAP2_DEVICE_TYPE_GP)
+		_omap_save_secure_sram = fncpy((void *)secure_ocmcram_location,
+					       &save_secure_ram_context,
+					       save_secure_ram_context_sz);
+	return 0;
+}
+
 static int omap34xx_do_sram_idle(unsigned long save_state)
 {
 	omap34xx_cpu_suspend(save_state);
@@ -281,7 +353,8 @@ void omap_sram_idle(void)
 	    pwrdm_read_prev_pwrst(core_pwrdm) == PWRDM_POWER_OFF) {
 		omap3_core_restore_context();
 		omap3_cm_restore_context();
-		omap3_sram_restore_context();
+		omap3_push_sram_idle();
+		omap3_push_sram_secure_idle();
 		omap2_sms_restore_context();
 	} else {
 		/*
@@ -517,6 +590,13 @@ int __init omap3_pm_init(void)
 	per_clkdm = clkdm_lookup("per_clkdm");
 	wkup_clkdm = clkdm_lookup("wkup_clkdm");
 
+	ret = omap3_prepare_push_sram_idle();
+	if (ret)
+		goto err3;
+
+	omap3_push_sram_idle();
+	omap3_push_sram_secure_idle();
+
 	omap_common_suspend_init(omap3_pm_suspend);
 
 	arm_pm_idle = omap3_pm_idle;
-- 
2.7.3



From d-gerlach at ti.com  Mon May  9 14:49:26 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Mon, 9 May 2016 16:49:26 -0500
Subject: [PATCH 6/6] ARM: OMAP2+: sram: remove legacy OMAP3 code
In-Reply-To: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>
References: <1462830566-28708-1-git-send-email-d-gerlach@ti.com>
Message-ID: <1462830566-28708-7-git-send-email-d-gerlach@ti.com>

Now that we have converted OMAP3 PM code to use generic sram driver we
no longer need to provide OMAP3 specific SRAM code for the omap SRAM
API.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/mach-omap2/pm34xx.c | 16 ----------------
 arch/arm/mach-omap2/sram.c   | 23 -----------------------
 2 files changed, 39 deletions(-)

diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 5ebbf5c30c6e..22d4c8742f99 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -502,22 +502,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
 }
 
-/*
- * Push functions to SRAM
- *
- * The minimum set of functions is pushed to SRAM for execution:
- * - omap3_do_wfi for erratum i581 WA,
- * - save_secure_ram_context for security extensions.
- */
-void omap_push_sram_idle(void)
-{
-	omap3_do_wfi_sram = omap_sram_push(omap3_do_wfi, omap3_do_wfi_sz);
-
-	if (omap_type() != OMAP2_DEVICE_TYPE_GP)
-		_omap_save_secure_sram = omap_sram_push(save_secure_ram_context,
-				save_secure_ram_context_sz);
-}
-
 static void __init pm_errata_configure(void)
 {
 	if (cpu_is_omap3630()) {
diff --git a/arch/arm/mach-omap2/sram.c b/arch/arm/mach-omap2/sram.c
index 83d0e61f49e6..7881304b5205 100644
--- a/arch/arm/mach-omap2/sram.c
+++ b/arch/arm/mach-omap2/sram.c
@@ -209,27 +209,6 @@ static inline int omap243x_sram_init(void)
 }
 #endif
 
-#ifdef CONFIG_ARCH_OMAP3
-
-void omap3_sram_restore_context(void)
-{
-	omap_sram_reset();
-
-	omap_push_sram_idle();
-}
-
-static inline int omap34xx_sram_init(void)
-{
-	omap3_sram_restore_context();
-	return 0;
-}
-#else
-static inline int omap34xx_sram_init(void)
-{
-	return 0;
-}
-#endif /* CONFIG_ARCH_OMAP3 */
-
 int __init omap_sram_init(void)
 {
 	omap_detect_sram();
@@ -239,8 +218,6 @@ int __init omap_sram_init(void)
 		omap242x_sram_init();
 	else if (cpu_is_omap2430())
 		omap243x_sram_init();
-	else if (cpu_is_omap34xx())
-		omap34xx_sram_init();
 
 	return 0;
 }
-- 
2.7.3



From javier at osg.samsung.com  Mon May  9 14:53:09 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 17:53:09 -0400
Subject: [PATCH v2 20/22] ARM: dts: exynos: Move common
 Exynos5410/542x/5800 nodes to new DTSI
In-Reply-To: <1462734367-5619-21-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-21-git-send-email-krzk@kernel.org>
Message-ID: <9e642e0d-87e1-4661-0233-acecf0082f24@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:06 PM, Krzysztof Kozlowski wrote:
> The Exynos5410/542x/5800 are very similar designs. Create new new

s/new new/a new

> DTSI with common nodes to remove DTS duplication. Although currently
> only MCT and SysRAM are shared but in future more nodes will be added to
> common file.
> 
> The patch should not have functional impact.
> 

A nice way to check this is to diff the disassembled compiled DTBs with
and without the patch and making sure that the resulted DTS is the same.

> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---
 
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Mon May  9 14:55:16 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 17:55:16 -0400
Subject: [PATCH v2 21/22] ARM: dts: exynos: Add USB to Exynos5410
In-Reply-To: <1462734367-5619-22-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-22-git-send-email-krzk@kernel.org>
Message-ID: <419e078b-a0c5-e7a6-0bea-9961147380d5@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:06 PM, Krzysztof Kozlowski wrote:
> Move USB 3.0 DWC and 2.0 EHCI/OHCI nodes from exynos5420.dtsi to
> exynos54xx.dtsi common for entire family. For Exynos542x/5800 this
> should not have functional impact but for Exynos5410 this effectively
> adds USB support.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> 

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From sboyd at codeaurora.org  Mon May  9 15:00:50 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 9 May 2016 15:00:50 -0700
Subject: [PATCH v2 00/22] ARM: dts: exynos: Add initial support for
 Odroid XU
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <20160509220050.GR3492@codeaurora.org>

On 05/08, Krzysztof Kozlowski wrote:
> 
> Hi,
> 
> Patchset adds necessary clocks, reorganizes existing stuff and finally
> adds Odroid XU support.
> 
> Merging strategy
> ================
> Complicated! The clock dt-bindings and driver changes can go to clock
> tree. However there are three DTS patches in the middle.
> a. This has to go in before adding "fin_pll_new" to clock driver:
>    - [PATCH v2 03/22] ARM: dts: exynos: Add fin_pll node for clock driver
> 
> b. This should go in before renaming "fin_pll_new" back to original name:
>    - [PATCH v2 05/22] ARM: dts: exynos: Switch MCT node to a new fin_pll clock
>    - [PATCH v2 06/22] ARM: dts: exynos: Remove old fixed-clock provider on SMDK5410
> 
> The order of patches in the patchset is really how it should go in
> to reduce any bisectability glitches.

If you want to just merge them through arm-soc then feel free to
add my Acked-by to the clk driver and clock dt-binding ones.

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


From javier at osg.samsung.com  Mon May  9 15:02:51 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 18:02:51 -0400
Subject: [PATCH v2 22/22] ARM: dts: exynos: Add initial support for Odroid
 XU board
In-Reply-To: <1462734367-5619-23-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-23-git-send-email-krzk@kernel.org>
Message-ID: <cbcb5657-8825-83cf-688f-d565ac7ecbab@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:06 PM, Krzysztof Kozlowski wrote:
> The Hardkernel's Odroid XU board was first design with big.LITTLE SoC
> from Samsung: the Exynos5410. Comparing now to more popular Odroid XU3
> the differences are:
> 1. Exynos5410 instead of 5422,
> 2. DisplayPort,
> 3. Main PMIC: Maxim 77802 instead of S2MPS11,
> 4. USB3503+LAN9730 instead of integrated LAN9514,
> 5. eMMC 4.5 instead of eMMC 5.0,
> 
> This patch adds initial support for the XU board with working basic
> functions, eMMC/SD and USB (including attached ethernet adapter).
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

This DTS has some TODO's, FIXME's and commented input supplies. Probably
this patch should had been an RFC? or you should mention about these in
the commit message to understand why are there.

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Mon May  9 15:05:47 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 9 May 2016 18:05:47 -0400
Subject: [PATCH v2 00/22] ARM: dts: exynos: Add initial support for Odroid
 XU
In-Reply-To: <1462734367-5619-1-git-send-email-krzk@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
Message-ID: <0aacc9fe-01c2-a9cd-35c7-db2c17a737c3@osg.samsung.com>

Hello Krzysztof,

On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
> 
> Hi,
> 
> Patchset adds necessary clocks, reorganizes existing stuff and finally
> adds Odroid XU support.
> 

Do you have a branch available so I can pull these patches and test in
the Exynos5 boards I've access to?

Thanks a lot and best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From ivo.g.dimitrov.75 at gmail.com  Mon May  9 15:06:18 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Tue, 10 May 2016 01:06:18 +0300
Subject: [PATCH 4/7] [media] ir-rx51: add DT support to driver
In-Reply-To: <CAL_JsqJPZS1ne_xAuBFtCc5L1HKFJf0LDUJ7CRSFXhc3adkTfA@mail.gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <1462634508-24961-5-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <20160509200657.GA3379@rob-hp-laptop> <5730F8BA.5000402@gmail.com>
 <CAL_JsqJPZS1ne_xAuBFtCc5L1HKFJf0LDUJ7CRSFXhc3adkTfA@mail.gmail.com>
Message-ID: <573109DA.9040602@gmail.com>



On 10.05.2016 00:07, Rob Herring wrote:
> On Mon, May 9, 2016 at 3:53 PM, Ivaylo Dimitrov
> <ivo.g.dimitrov.75 at gmail.com> wrote:
>> Hi,
>>
>> On  9.05.2016 23:06, Rob Herring wrote:
>>>
>>> On Sat, May 07, 2016 at 06:21:45PM +0300, Ivaylo Dimitrov wrote:
>>>>
>>>> With the upcoming removal of legacy boot, lets add support to one of the
>>>> last N900 drivers remaining without it. As the driver still uses omap
>>>> dmtimer, add auxdata as well.
>>>>
>>>> Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
>>>> ---
>>>>    .../devicetree/bindings/media/nokia,lirc-rx51         | 19
>>>> +++++++++++++++++++
>>>>    arch/arm/mach-omap2/pdata-quirks.c                    |  6 +-----
>>>>    drivers/media/rc/ir-rx51.c                            | 11 ++++++++++-
>>>>    3 files changed, 30 insertions(+), 6 deletions(-)
>>>>    create mode 100644
>>>> Documentation/devicetree/bindings/media/nokia,lirc-rx51
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/media/nokia,lirc-rx51
>>>> b/Documentation/devicetree/bindings/media/nokia,lirc-rx51
>>>> new file mode 100644
>>>> index 0000000..5b3081e
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/media/nokia,lirc-rx51
>>>> @@ -0,0 +1,19 @@
>>>> +Device-Tree bindings for LIRC TX driver for Nokia N900(RX51)
>>>> +
>>>> +Required properties:
>>>> +       - compatible: should be "nokia,lirc-rx51".
>>>
>>>
>>> lirc is a Linux term. Also, nokia,rx51-... would be conventional
>>> ordering.
>>>
>>
>> I used the driver name ("lirc_rx51") to not bring confusion. Also, it
>> registers itself through lirc_register_driver() call, so having lirc in its
>> name somehow makes sense.
>>
>> I am not very good in inventing names, the best compatible I can think of is
>> "nokia,rx51-ir". Is that ok?
>
> Sure, but...
>
>>> Is this anything more than a PWM LED?
>>>
>>
>> It is an IR LED connected through a driver to McSPI2_SIMO pin of OMAP3,
>> which pin can be configured as PWM or GPIO(there are other configurations,
>> but they don't make sense). In theory it could be used for various things
>> (like uni-directional serial TX, or stuff like that), but in practice it
>> allows N900 to be act as an IR remote controller. I guess that fits in
>> "nothing more than a PWM LED", more or less.
>
> There's already a pwm-led binding that can be used. Though there may
> be missing consumer IR to LED subsystem support in the kernel. You
> could list both compatibles, use the rx51 IR driver now, and then move
> to pwm-led driver in the future.
>

I looked at the pwm-leds (and related) code and couldn't see how it will 
do the job of controlling IR TX LED as a remote controller. So yeah, it 
seems CIR support in LEDS subsystem is non existent.

Could you elaborate on "list both compatibles", I don't really 
understand what I should do.

Ivo


From sboyd at codeaurora.org  Mon May  9 15:11:46 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 9 May 2016 15:11:46 -0700
Subject: [PATCH 01/16] clk: fix critical clock locking
In-Reply-To: <1462737711-10017-2-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-2-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <20160509221146.GS3492@codeaurora.org>

On 05/08, Maxime Ripard wrote:
> The critical clock handling in __clk_core_init isn't taking the enable lock
> before calling clk_core_enable, which in turns triggers the warning in the
> lockdep_assert_held call in that function when lockep is enabled.
> 
> Add the calls to clk_enable_lock/unlock to make sure it doesn't happen.
> 
> Fixes: 32b9b1096186 ("clk: Allow clocks to be marked as CRITICAL")
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---

Why is this patch hiding in this series?

>  drivers/clk/clk.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index ce39add5a258..16a38df3c688 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -2404,8 +2404,15 @@ static int __clk_core_init(struct clk_core *core)
>  		core->ops->init(core->hw);
>  
>  	if (core->flags & CLK_IS_CRITICAL) {
> +		unsigned long flags;
> +
> +		clk_prepare_lock();
>  		clk_core_prepare(core);
> +		clk_prepare_unlock();

It looks like we already hold the prepare lock at this point.

> +
> +		flags = clk_enable_lock();
>  		clk_core_enable(core);
> +		clk_enable_unlock(flags);

This seems correct though.

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


From sboyd at codeaurora.org  Mon May  9 15:13:21 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 9 May 2016 15:13:21 -0700
Subject: [PATCH v7 7/9] clk: mediatek: Enable critical clocks for MT2701
In-Reply-To: <1462772426.5344.7.camel@mtksdaap41>
References: <1460621514-65191-1-git-send-email-jamesjj.liao@mediatek.com>
 <1460621514-65191-8-git-send-email-jamesjj.liao@mediatek.com>
 <20160506231229.GJ3492@codeaurora.org>
 <1462772426.5344.7.camel@mtksdaap41>
Message-ID: <20160509221321.GT3492@codeaurora.org>

On 05/09, James Liao wrote:
> Hi Stephen,
> 
> On Fri, 2016-05-06 at 16:12 -0700, Stephen Boyd wrote:
> > On 04/14, James Liao wrote:
> > > Some system clocks should be turned on by default on MT2701.
> > > This patch enable these clocks when related clocks have
> > > been registered.
> > > 
> > > Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
> > > ---
> > 
> > critical clks got merged now (sorry I'm slowly getting back to
> > looking at patches). Please use that flag.
> 
> I don't see critical clock support in v4.6-rc7. Is there a repo/branch
> that has critical clocks merged?
> 

Right, it's in clk-next in the clk tree.

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


From sboyd at codeaurora.org  Mon May  9 15:13:39 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 9 May 2016 15:13:39 -0700
Subject: [PATCH v7 8/9] clk: mediatek: Add config options for MT2701
 subsystem clocks
In-Reply-To: <1462772246.5344.4.camel@mtksdaap41>
References: <1460621514-65191-1-git-send-email-jamesjj.liao@mediatek.com>
 <1460621514-65191-9-git-send-email-jamesjj.liao@mediatek.com>
 <20160506230214.GH3492@codeaurora.org>
 <1462772246.5344.4.camel@mtksdaap41>
Message-ID: <20160509221339.GU3492@codeaurora.org>

On 05/09, James Liao wrote:
> HI Stephen,
> 
> On Fri, 2016-05-06 at 16:02 -0700, Stephen Boyd wrote:
> > On 04/14, James Liao wrote:
> > > MT2701 subsystem clocks are optional and should be enabled only if
> > > their subsystem drivers are ready to control these clocks.
> > > 
> > > Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
> > > ---
> > 
> > Why is this patch split off from the patch that introduces the
> > file?
> 
> I was looking for comments about how to make subsystem clocks optional.
> So I used a separated patch to do it. Is it an acceptable way to use
> config options to enable subsystem clock support?
> 

Yes config options are fine.

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


From rjw at rjwysocki.net  Mon May  9 15:18:59 2016
From: rjw at rjwysocki.net (Rafael J. Wysocki)
Date: Tue, 10 May 2016 00:18:59 +0200
Subject: [PATCH V6 01/13] pci, acpi, x86,
 ia64: Move ACPI host bridge device companion assignment to core code.
In-Reply-To: <5729AE92.2090106@semihalf.com>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <20160427024537.GH6789@localhost> <5729AE92.2090106@semihalf.com>
Message-ID: <8183907.bBqvG1yEkP@vostro.rjw.lan>

On Wednesday, May 04, 2016 10:10:58 AM Tomasz Nowicki wrote:
> On 27.04.2016 04:45, Bjorn Helgaas wrote:
> > [question for Rafael below]
> >
> > On Fri, Apr 15, 2016 at 07:06:36PM +0200, Tomasz Nowicki wrote:
> >> Currently we have two platforms (x86 & ia64) capable of PCI ACPI host
> >> bridge initialization. They both use arch-specific sysdata to pass down
> >> parent device reference and both rely on NULL parent in pci_create_root_bus()
> >> to validate sysdata content.
> >>
> >> It looks hacky and prevents us from getting some firmware specific
> >> info for PCI host controller based on its acpi_device structure
> >> in generic pci_create_root_bus() function. However, we overcome that
> >> blocker by passing down parent device via pci_create_root_bus parameter
> >> (as the ACPI device type). Then we use ACPI_COMPANION_SET in core code
> >> for ACPI boot method only. ACPI_COMPANION_SET is safe to run for all
> >> cases DT, ACPI and DT&ACPI.
> >>
> >> Since now PCI core code is setting ACPI companion device for us,
> >> x86 & ia64 specific ACPI companion device setting turns out to be dead now.
> >> We can get rid of it, including related companion reference from
> >> PCI sysdata structure. Aslo, PCI_CONTROLLER macro cannot return valid
> >> companion device anymore. Therefore we need to convert its usage to
> >> ACPI_COMPANION.
> >>
> >> Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
> >> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> >> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
> >> Tested-by: Duc Dang <dhdang at apm.com>
> >> Tested-by: Dongdong Liu <liudongdong3 at huawei.com>
> >> Tested-by: Hanjun Guo <hanjun.guo at linaro.org>
> >> Tested-by: Graeme Gregory <graeme.gregory at linaro.org>
> >> Tested-by: Sinan Kaya <okaya at codeaurora.org>
> >> ---
> >>   arch/ia64/hp/common/sba_iommu.c    |  2 +-
> >>   arch/ia64/include/asm/pci.h        |  1 -
> >>   arch/ia64/pci/pci.c                | 16 ----------------
> >>   arch/ia64/sn/kernel/io_acpi_init.c |  4 ++--
> >>   arch/x86/include/asm/pci.h         |  3 ---
> >>   arch/x86/pci/acpi.c                | 17 -----------------
> >>   drivers/acpi/pci_root.c            |  7 ++++++-
> >>   drivers/pci/probe.c                |  2 ++
> >>   8 files changed, 11 insertions(+), 41 deletions(-)
> >>
> >> diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
> >> index a6d6190..78e4444 100644
> >> --- a/arch/ia64/hp/common/sba_iommu.c
> >> +++ b/arch/ia64/hp/common/sba_iommu.c
> >> @@ -1981,7 +1981,7 @@ sba_connect_bus(struct pci_bus *bus)
> >>   	if (PCI_CONTROLLER(bus)->iommu)
> >>   		return;
> >>
> >> -	handle = acpi_device_handle(PCI_CONTROLLER(bus)->companion);
> >> +	handle = acpi_device_handle(ACPI_COMPANION(bus->bridge));
> >>   	if (!handle)
> >>   		return;
> >>
> >> diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
> >> index c0835b0..12423f4 100644
> >> --- a/arch/ia64/include/asm/pci.h
> >> +++ b/arch/ia64/include/asm/pci.h
> >> @@ -63,7 +63,6 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
> >>   #define pci_legacy_write platform_pci_legacy_write
> >>
> >>   struct pci_controller {
> >> -	struct acpi_device *companion;
> >>   	void *iommu;
> >>   	int segment;
> >>   	int node;		/* nearest node with memory or NUMA_NO_NODE for global allocation */
> >> diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
> >> index 8f6ac2f..978d6af 100644
> >> --- a/arch/ia64/pci/pci.c
> >> +++ b/arch/ia64/pci/pci.c
> >> @@ -301,28 +301,12 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
> >>   	}
> >>
> >>   	info->controller.segment = root->segment;
> >> -	info->controller.companion = device;
> >>   	info->controller.node = acpi_get_node(device->handle);
> >>   	INIT_LIST_HEAD(&info->io_resources);
> >>   	return acpi_pci_root_create(root, &pci_acpi_root_ops,
> >>   				    &info->common, &info->controller);
> >>   }
> >>
> >> -int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> >> -{
> >> -	/*
> >> -	 * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL
> >> -	 * here, pci_create_root_bus() has been called by someone else and
> >> -	 * sysdata is likely to be different from what we expect.  Let it go in
> >> -	 * that case.
> >> -	 */
> >> -	if (!bridge->dev.parent) {
> >> -		struct pci_controller *controller = bridge->bus->sysdata;
> >> -		ACPI_COMPANION_SET(&bridge->dev, controller->companion);
> >> -	}
> >> -	return 0;
> >> -}
> >> -
> >>   void pcibios_fixup_device_resources(struct pci_dev *dev)
> >>   {
> >>   	int idx;
> >> diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c
> >> index 231234c..e454492 100644
> >> --- a/arch/ia64/sn/kernel/io_acpi_init.c
> >> +++ b/arch/ia64/sn/kernel/io_acpi_init.c
> >> @@ -132,7 +132,7 @@ sn_get_bussoft_ptr(struct pci_bus *bus)
> >>   	struct acpi_resource_vendor_typed *vendor;
> >>
> >>
> >> -	handle = acpi_device_handle(PCI_CONTROLLER(bus)->companion);
> >> +	handle = acpi_device_handle(ACPI_COMPANION(bus->bridge));
> >>   	status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
> >>   					  &sn_uuid, &buffer);
> >>   	if (ACPI_FAILURE(status)) {
> >> @@ -360,7 +360,7 @@ sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
> >>   	acpi_status status;
> >>   	struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> >>
> >> -	rootbus_handle = acpi_device_handle(PCI_CONTROLLER(dev)->companion);
> >> +	rootbus_handle = acpi_device_handle(ACPI_COMPANION(dev->bus->bridge));
> >>           status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL,
> >>                                          &segment);
> >>           if (ACPI_SUCCESS(status)) {
> >> diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
> >> index 9ab7507..24de07d 100644
> >> --- a/arch/x86/include/asm/pci.h
> >> +++ b/arch/x86/include/asm/pci.h
> >> @@ -14,9 +14,6 @@
> >>   struct pci_sysdata {
> >>   	int		domain;		/* PCI domain */
> >>   	int		node;		/* NUMA node */
> >> -#ifdef CONFIG_ACPI
> >> -	struct acpi_device *companion;	/* ACPI companion device */
> >> -#endif
> >>   #ifdef CONFIG_X86_64
> >>   	void		*iommu;		/* IOMMU private data */
> >>   #endif
> >> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
> >> index 3cd6983..f4ca17a 100644
> >> --- a/arch/x86/pci/acpi.c
> >> +++ b/arch/x86/pci/acpi.c
> >> @@ -340,7 +340,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
> >>   		struct pci_sysdata sd = {
> >>   			.domain = domain,
> >>   			.node = node,
> >> -			.companion = root->device
> >>   		};
> >>
> >>   		memcpy(bus->sysdata, &sd, sizeof(sd));
> >> @@ -355,7 +354,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
> >>   		else {
> >>   			info->sd.domain = domain;
> >>   			info->sd.node = node;
> >> -			info->sd.companion = root->device;
> >>   			bus = acpi_pci_root_create(root, &acpi_pci_root_ops,
> >>   						   &info->common, &info->sd);
> >>   		}
> >> @@ -373,21 +371,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
> >>   	return bus;
> >>   }
> >>
> >> -int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> >> -{
> >> -	/*
> >> -	 * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL
> >> -	 * here, pci_create_root_bus() has been called by someone else and
> >> -	 * sysdata is likely to be different from what we expect.  Let it go in
> >> -	 * that case.
> >> -	 */
> >> -	if (!bridge->dev.parent) {
> >> -		struct pci_sysdata *sd = bridge->bus->sysdata;
> >> -		ACPI_COMPANION_SET(&bridge->dev, sd->companion);
> >> -	}
> >> -	return 0;
> >> -}
> >> -
> >>   int __init pci_acpi_init(void)
> >>   {
> >>   	struct pci_dev *dev = NULL;
> >> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> >> index ae3fe4e..4581e0e 100644
> >> --- a/drivers/acpi/pci_root.c
> >> +++ b/drivers/acpi/pci_root.c
> >> @@ -564,6 +564,11 @@ static int acpi_pci_root_add(struct acpi_device *device,
> >>   		}
> >>   	}
> >>
> >> +	/*
> >> +	 * pci_create_root_bus() needs to detect the parent device type,
> >> +	 * so initialize its companion data accordingly.
> >> +	 */
> >> +	ACPI_COMPANION_SET(&device->dev, device);
> >>   	root->device = device;
> >>   	root->segment = segment & 0xFFFF;
> >>   	strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
> >> @@ -846,7 +851,7 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
> >>
> >>   	pci_acpi_root_add_resources(info);
> >>   	pci_add_resource(&info->resources, &root->secondary);
> >> -	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
> >> +	bus = pci_create_root_bus(&device->dev, busnum, ops->pci_ops,
> >>   				  sysdata, &info->resources);
> >
> > "device" here is a struct acpi_device *.  Rafael, is that the right
> > thing to do?  I dimly recall proposing something similar long ago and
> > that it turned out to be a bad idea.
> >
> 
> Joining Bjorn's question. Rafael, do you recall what was the issue here 
> from the past?

Yes, I do.

Anything struct acpi_device doesn't represent a real device.  It represents
a firmware object that can be associated with a device.  IOW, nothing under
LNXSYSTM\:00/ should ever be used as the parent or sibling etc with respect to
anything outside of that directory.  In fact, the entire LNXSYSTM\:00/ should
be located under /sys/firmware/acpi/ and it was a mistake to put it under
/sys/devices/.

One immediate consequence of the above change, AFAICS, would be that the whole
PCI hierarchy would now hang under /sys/devices/LNXSYSTM\:00/LNXSYBUS\:00/PNP0A08\:00/
which would not make any sense whatever, because
/sys/devices/LNXSYSTM\:00/LNXSYBUS\:00/PNP0A08\:00/physical_node already points to
/sys/devices/pci0000\:00/.

IOW, both PNP0A08\:00/ and pci0000\:00/ already represent the same thing, ie. the
host bridge.

If you want to have a parent for pci0000\:00/, you need a physical_node for
LNXSYBUS\:00 and point to that as the parent from pci0000\:00/.  That at least
will lead to a sysfs hierarchy that makes sense, although it may break user
space tools I suppose (which may be assuming that pci0000\:00/ will always be
present directly under /sys/devices/).

Thanks,
Rafael



From chris.brand at broadcom.com  Mon May  9 15:27:49 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Mon, 9 May 2016 15:27:49 -0700
Subject: [PATCH 3/6] docs: Document BCM23550 bindings
In-Reply-To: <20160509194115.GA11594@rob-hp-laptop>
References: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
 <1462481334-8943-4-git-send-email-chris.brand@broadcom.com>
 <20160509194115.GA11594@rob-hp-laptop>
Message-ID: <CAMsMSK-da2GstXrrYVpoJh2fo-Gi70gD7WFxi8TM9M=Zmqu1Rg@mail.gmail.com>

On Mon, May 9, 2016 at 12:41 PM, Rob Herring <robh at kernel.org> wrote:
> On Thu, May 05, 2016 at 01:48:51PM -0700, Chris Brand wrote:
>> Add binding document for Broadcom BCM23550 SoC.
[...]
>> +The enable method is specified by defining the following required
>> +properties in the "cpu" device tree node:
>> +  - enable-method = "brcm,bcm23550-cpu-method";
>
> "-cpu-method" is a bit redundant. brcm,bc23550 is probably sufficient.

Fair enough. Thanks, Rob!

Chris


From sboyd at codeaurora.org  Mon May  9 15:29:50 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 9 May 2016 15:29:50 -0700
Subject: [PATCH v7 4/9] clk: mediatek: Add MT2701 clock support
In-Reply-To: <1462775888.5344.20.camel@mtksdaap41>
References: <1460621514-65191-1-git-send-email-jamesjj.liao@mediatek.com>
 <1460621514-65191-5-git-send-email-jamesjj.liao@mediatek.com>
 <20160506231151.GI3492@codeaurora.org>
 <1462775888.5344.20.camel@mtksdaap41>
Message-ID: <20160509222950.GV3492@codeaurora.org>

On 05/09, James Liao wrote:
> Hi Stephen,
> 
> On Fri, 2016-05-06 at 16:11 -0700, Stephen Boyd wrote:
> > On 04/14, James Liao wrote:
> > > diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
> > > new file mode 100644
> > > index 0000000..b4db141
> > > --- /dev/null
> > > +++ b/drivers/clk/mediatek/clk-mt2701.c
> > > +static void __init mtk_infrasys_init(struct device_node *node)
> > > +{
> > > +	struct clk_onecell_data *clk_data;
> > > +	int r;
> > > +
> > > +	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
> > > +
> > > +	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
> > > +						clk_data);
> > > +	mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
> > > +						clk_data);
> > > +
> > > +	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> > > +	if (r)
> > > +		pr_err("%s(): could not register clock provider: %d\n",
> > > +			__func__, r);
> > > +}
> > > +CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt2701-infracfg", mtk_infrasys_init);
> > 
> > I'm still lost on the usage of CLK_OF_DECLARE here. What part of
> > these clk controllers needs to be registered to make the timer
> > work?
> 
> GPT (mtk-timer.c) may need infracfg and topckgen clocks. MT8173 for
> example:
> 
> 	timer: timer at 10008000 {
> 	[...]
> 		clocks = <&infracfg CLK_INFRA_CLK_13M>,
> 			 <&topckgen CLK_TOP_RTC_SEL>;
> 	};

Ok. It should be possible to only register the clk tree for these
clks in CLK_OF_DECLARE() and then register the other clks that
the clk provider provides with a regular driver probe routine.
That way we can get the advantage of the device framework, etc.
but still register the clks we need to make the timer work early
on.

> 
> > > +	GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2),
> > > +	GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3),
> > > +	GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4),
> > > +	GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5),
> > > +	GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6),
> > > +	GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7),
> > > +	GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8),
> > > +	GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9),
> > > +	GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10),
> > > +	GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11),
> > > +	GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14),
> > > +};
> > 
> > I also don't understand why we don't have different files and
> > drivers for all these different clock controllers? They all have
> > a similar probe structure, sure, but otherwise these are
> > different devices with different clks for them. The whole #ifdef
> > thing in the later patch would go away too.
> 
> Yes, you are right. So you prefer to support subsystem clocks in
> separated files such as clk-mt2701-mm.c, clk-mt2701-bdp.c and so on,
> right?
> 
> But even if we implement subsystem clock in separated files, we still
> need a way to make them optional. So the config options and #ifdef may
> not be removed.

Presumably different files could just not be compiled if the
config is disabled, thus removing any need for #ifdef.

> 
> > > +	GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12),
> > > +	GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13),
> > > +	GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14),
> > > +	GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15),
> > > +	GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_pll340m", 16),
> > > +};
> > > +
> > > +static void __init mtk_bdpsys_init(struct device_node *node)
> > 
> > Shouldn't be __init because it's driver probe path.
> 
> I use builtin_platform_driver_probe(clk_drv, clk_probe) to register this
> driver, and it looks can be __init.

Ok, but that doesn't work with deferred probe right? It may be
better to avoid it then.

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


From chris.brand at broadcom.com  Mon May  9 15:31:31 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Mon, 9 May 2016 15:31:31 -0700
Subject: [PATCH 0/6] Support BCM23550 SoC
In-Reply-To: <6872671.Czyv7J9iJZ@wuerfel>
References: <1462481334-8943-1-git-send-email-chris.brand@broadcom.com>
 <6872671.Czyv7J9iJZ@wuerfel>
Message-ID: <CAMsMSK-MwY6HDmb45vj6g2BTM9yk7+g5oP0hEm9gk6Gi7f+XjA@mail.gmail.com>

On Thu, May 5, 2016 at 2:09 PM, Arnd Bergmann <arnd at arndb.de> wrote:
[...]
> Looks really nice overall, I only found one tiny detail I commented on
> for patch 6.

Thanks!

> I'm glad to see work on the old chips resume, are you working on new
> code for it as well, or just upstreaming the patches that were already
> done in the past?


This is new work. It was actually a good testament to the value of
upstreaming that it was so easy to bring up a 4.6 kernel on this chip.

Chris


From sboyd at codeaurora.org  Mon May  9 15:32:38 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 9 May 2016 15:32:38 -0700
Subject: [PATCH v4 01/11] clk: sunxi: Add display and TCON0 clocks driver
In-Reply-To: <20160508200308.GF6167@lukather>
References: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
 <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
 <20160506223002.GE3492@codeaurora.org>
 <20160508200308.GF6167@lukather>
Message-ID: <20160509223238.GW3492@codeaurora.org>

On 05/08, Maxime Ripard wrote:
> Hi Stephen,
> 
> On Fri, May 06, 2016 at 03:30:02PM -0700, Stephen Boyd wrote:
> > On 04/25, Maxime Ripard wrote:
> > > The A10 SoCs and its relatives has a special clock controller to drive the
> > > display engines (both frontend and backend), that have a lot in common with
> > > the clock to drive the first TCON channel.
> > > 
> > > Add a driver to support both.
> > > 
> > > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > > Acked-by: Rob Herring <robh at kernel.org>
> > > ---
> > 
> > Acked-by: Stephen Boyd <sboyd at codeaurora.org>
> > 
> > Unless I can merge this into clk-next? Wasn't clear to me.
> 
> Yes, please do, I already sent you the bunch of patches I gathered for
> 4.7, and I don't have any others but this one.
> 

Ok I applied this one to clk-next.

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


From andre.przywara at arm.com  Mon May  9 15:37:35 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon,  9 May 2016 23:37:35 +0100
Subject: [PATCH] arm64/sunxi: 4.6-rc1: Add dependency on generic irq chip
Message-ID: <1462833455-27720-1-git-send-email-andre.przywara@arm.com>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Commit ce3dd55b99b1 ("arm64: Introduce Allwinner SoC config option"),
added support for ARCH_SUNXI on arm64, but failed to select
GENERIC_IRQ_CHIP, which is required for drivers/irqchip/irq-sunxi-nmi.c
and causes build failures like :

  UPD     include/generated/compile.h
  CC      init/version.o
  LD      init/built-in.o
drivers/built-in.o: In function `sunxi_sc_nmi_set_type':
drivers/irqchip/irq-sunxi-nmi.c:114: undefined reference to `irq_setup_alt_chip'
drivers/built-in.o: In function `irq_domain_add_linear':
include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
drivers/built-in.o: In function `sunxi_sc_nmi_irq_init':
drivers/irqchip/irq-sunxi-nmi.c:146: undefined reference to `irq_alloc_domain_generic_chips'
drivers/irqchip/irq-sunxi-nmi.c:161: undefined reference to `irq_get_domain_generic_chip'
drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
drivers/irqchip/irq-sunxi-nmi.c:171: undefined reference to `irq_gc_mask_set_bit'
drivers/irqchip/irq-sunxi-nmi.c:172: undefined reference to `irq_gc_ack_set_bit'
drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'

Fixes: commit ce3dd55b99b1 ("arm64: Introduce Allwinner SoC config option")
Cc: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Hi Olof, Arnd,

as agreed upon in that other mail, can you take this patch for 4.6?

Cheers,
Andre.

 arch/arm64/Kconfig.platforms | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index efa77c1..521b1ec 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -2,6 +2,7 @@ menu "Platform selection"
 
 config ARCH_SUNXI
 	bool "Allwinner sunxi 64-bit SoC Family"
+	select GENERIC_IRQ_CHIP
 	help
 	  This enables support for Allwinner sunxi based SoCs like the A64.
 
-- 
2.7.4



From sboyd at codeaurora.org  Mon May  9 15:39:24 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 9 May 2016 15:39:24 -0700
Subject: [PATCH v4 01/11] clk: sunxi: Add display and TCON0 clocks driver
In-Reply-To: <20160509223238.GW3492@codeaurora.org>
References: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
 <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
 <20160506223002.GE3492@codeaurora.org>
 <20160508200308.GF6167@lukather>
 <20160509223238.GW3492@codeaurora.org>
Message-ID: <20160509223924.GX3492@codeaurora.org>

On 05/09, Stephen Boyd wrote:
> 
> Ok I applied this one to clk-next.
> 

And I squashed this in to silence the following checker warning.

drivers/clk/sunxi/clk-sun4i-display.c:110:33: warning: Variable
length array is used.

---8<---
diff --git a/drivers/clk/sunxi/clk-sun4i-display.c b/drivers/clk/sunxi/clk-sun4i-display.c
index f02e250e64ed..f8ff6c4a5633 100644
--- a/drivers/clk/sunxi/clk-sun4i-display.c
+++ b/drivers/clk/sunxi/clk-sun4i-display.c
@@ -107,7 +107,7 @@ static int sun4i_a10_display_reset_xlate(struct reset_controller_dev *rcdev,
 static void __init sun4i_a10_display_init(struct device_node *node,
 					  const struct sun4i_a10_display_clk_data *data)
 {
-	const char *parents[data->parents];
+	const char *parents[4];
 	const char *clk_name = node->name;
 	struct reset_data *reset_data;
 	struct clk_divider *div = NULL;
@@ -126,8 +126,8 @@ static void __init sun4i_a10_display_init(struct device_node *node,
 		return;
 	}
 
-	ret = of_clk_parent_fill(node, parents, data->parents);
-	if (ret != data->parents) {
+	ret = of_clk_parent_fill(node, parents, ARRAY_SIZE(parents));
+	if (ret != ARRAY_SIZE(parents)) {
 		pr_err("%s: Could not retrieve the parents\n", clk_name);
 		goto unmap;
 	}
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


From benh at kernel.crashing.org  Mon May  9 15:04:40 2016
From: benh at kernel.crashing.org (Benjamin Herrenschmidt)
Date: Tue, 10 May 2016 08:04:40 +1000
Subject: [PATCH 1/2] doc/devicetree: Add Aspeed VIC bindings
In-Reply-To: <20160509152003.GA13842@leverpostej>
References: <1462797239-14765-1-git-send-email-joel@jms.id.au>
 <1462797239-14765-2-git-send-email-joel@jms.id.au>
 <20160509152003.GA13842@leverpostej>
Message-ID: <1462831480.20290.120.camel@kernel.crashing.org>

On Mon, 2016-05-09 at 16:20 +0100, Mark Rutland wrote:
>?
> Generally we steer clear of this kind of bitmap encoding in DT.
> 
> Is this actually necessary? What does htis gain us?
> 
> Why can we not just register with the full set of possible
> interrupts?

Trying to remember why I did that ... I think it has to do with
supporting multiple SoCs that have different possible sources...

There might also be a case of some sources routed to the internal
coldfire microcontroller or the LPC bus instead of the ARM but I'm not
100% certain.

Cheers,
Ben.



From sboyd at codeaurora.org  Mon May  9 15:42:19 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 9 May 2016 15:42:19 -0700
Subject: [GIT PULL] clk: tegra: Changes for v4.7-rc1
In-Reply-To: <20160509051946.GA18753@ulmo.ba.sec>
References: <1461945596-24090-1-git-send-email-thierry.reding@gmail.com>
 <20160503000248.GB3492@codeaurora.org>
 <20160509051946.GA18753@ulmo.ba.sec>
Message-ID: <20160509224219.GY3492@codeaurora.org>

On 05/09, Thierry Reding wrote:
>
> I'm not aware of any API that would fit in this case. Power domains
> would be misleading because power management isn't involved. One other
> alternative that I had thought about is to make it a "virtual" reset,
> but that is equally misleading because nothing is really being reset
> here.
> 
> Yet another option might be to make it a "virtual" clock, though it'd
> have to be somewhat hacky because we need two steps (one to enable HW
> control and another to start the HW sequencer). That could be
> implemented using ->prepare() and ->enable(), respectively, but it's
> really not a clock either.
> 
> I welcome any ideas on how to turn this into something generic, though.
> 

I suggested power domains because it looks like SoC glue code
that we need to do when the device is powered on and off? Unless
I totally misread how it was used. And I suppose I should have
said generic power domains (genpd) instead of power domains,
because I agree it's not actual power management, just some SoC
runtime PM stuff it seems. But who knows, I probably misread it
all.

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


From alex.williamson at redhat.com  Mon May  9 15:49:28 2016
From: alex.williamson at redhat.com (Alex Williamson)
Date: Mon, 9 May 2016 16:49:28 -0600
Subject: [PATCH v9 2/7] vfio/type1: vfio_find_dma accepting a type argument
In-Reply-To: <1462362858-2925-3-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-3-git-send-email-eric.auger@linaro.org>
Message-ID: <20160509164928.518a05a8@t450s.home>

On Wed,  4 May 2016 11:54:13 +0000
Eric Auger <eric.auger at linaro.org> wrote:

> In our RB-tree we now have slots of different types (USER and RESERVED).
> It becomes useful to be able to search for dma slots of a specific type or
> any type. This patch proposes an implementation for that modality and also
> changes the existing callers using the USER type.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> ---
>  drivers/vfio/vfio_iommu_type1.c | 63 ++++++++++++++++++++++++++++++++++-------
>  1 file changed, 53 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index aaf5a6c..2d769d4 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -98,23 +98,64 @@ struct vfio_group {
>   * into DMA'ble space using the IOMMU
>   */
>  
> -static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
> -				      dma_addr_t start, size_t size)
> +/**
> + * vfio_find_dma_from_node: looks for a dma slot intersecting a window
> + * from a given rb tree node
> + * @top: top rb tree node where the search starts (including this node)
> + * @start: window start
> + * @size: window size
> + * @type: window type
> + */
> +static struct vfio_dma *vfio_find_dma_from_node(struct rb_node *top,
> +						dma_addr_t start, size_t size,
> +						enum vfio_iova_type type)
>  {
> -	struct rb_node *node = iommu->dma_list.rb_node;
> +	struct rb_node *node = top;
> +	struct vfio_dma *dma;
>  
>  	while (node) {
> -		struct vfio_dma *dma = rb_entry(node, struct vfio_dma, node);
> -
> +		dma = rb_entry(node, struct vfio_dma, node);
>  		if (start + size <= dma->iova)
>  			node = node->rb_left;
>  		else if (start >= dma->iova + dma->size)
>  			node = node->rb_right;
>  		else
> +			break;
> +	}
> +	if (!node)
> +		return NULL;
> +
> +	/* a dma slot intersects our window, check the type also matches */
> +	if (type == VFIO_IOVA_ANY || dma->type == type)
> +		return dma;
> +
> +	/* restart 2 searches skipping the current node */
> +	if (start < dma->iova) {
> +		dma = vfio_find_dma_from_node(node->rb_left, start,
> +					      size, type);
> +		if (dma)
>  			return dma;
>  	}
> +	if (start + size > dma->iova + dma->size)
> +		dma = vfio_find_dma_from_node(node->rb_right, start,
> +					      size, type);

It might be nice to split this little bit of trickery out to a separate
patch so that you can better explain what it does.  It's really not
needed until we start creating user-type entries, so it shouldn't hurt
bisection.

> +	return dma;
> +}
> +
> +/**
> + * vfio_find_dma: find a dma slot intersecting a given window
> + * @iommu: vfio iommu handle
> + * @start: window base iova
> + * @size: window size
> + * @type: window type
> + */
> +static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
> +				      dma_addr_t start, size_t size,
> +				      enum vfio_iova_type type)
> +{
> +	struct rb_node *top_node = iommu->dma_list.rb_node;
>  
> -	return NULL;
> +	return vfio_find_dma_from_node(top_node, start, size, type);
>  }
>  
>  static void vfio_link_dma(struct vfio_iommu *iommu, struct vfio_dma *new)
> @@ -488,19 +529,21 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
>  	 * mappings within the range.
>  	 */
>  	if (iommu->v2) {
> -		dma = vfio_find_dma(iommu, unmap->iova, 0);
> +		dma = vfio_find_dma(iommu, unmap->iova, 0, VFIO_IOVA_USER);
>  		if (dma && dma->iova != unmap->iova) {
>  			ret = -EINVAL;
>  			goto unlock;
>  		}
> -		dma = vfio_find_dma(iommu, unmap->iova + unmap->size - 1, 0);
> +		dma = vfio_find_dma(iommu, unmap->iova + unmap->size - 1, 0,
> +				    VFIO_IOVA_USER);
>  		if (dma && dma->iova + dma->size != unmap->iova + unmap->size) {
>  			ret = -EINVAL;
>  			goto unlock;
>  		}
>  	}
>  
> -	while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size))) {
> +	while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size,
> +				    VFIO_IOVA_USER))) {
>  		if (!iommu->v2 && unmap->iova > dma->iova)
>  			break;
>  		unmapped += dma->size;
> @@ -604,7 +647,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
>  
>  	mutex_lock(&iommu->lock);
>  
> -	if (vfio_find_dma(iommu, iova, size)) {
> +	if (vfio_find_dma(iommu, iova, size, VFIO_IOVA_ANY)) {
>  		mutex_unlock(&iommu->lock);
>  		return -EEXIST;
>  	}



From alex.williamson at redhat.com  Mon May  9 15:49:36 2016
From: alex.williamson at redhat.com (Alex Williamson)
Date: Mon, 9 May 2016 16:49:36 -0600
Subject: [PATCH v9 3/7] vfio/type1: bypass unmap/unpin and replay for
 VFIO_IOVA_RESERVED slots
In-Reply-To: <1462362858-2925-4-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-4-git-send-email-eric.auger@linaro.org>
Message-ID: <20160509164936.1a5ae402@t450s.home>

On Wed,  4 May 2016 11:54:14 +0000
Eric Auger <eric.auger at linaro.org> wrote:

> Before allowing the end-user to create VFIO_IOVA_RESERVED dma slots,
> let's implement the expected behavior for removal and replay. As opposed
> to user dma slots, IOVAs are not systematically bound to PAs and PAs are
> not pinned. VFIO just initializes the IOVA "aperture". IOVAs are allocated
> outside of the VFIO framework, typically the MSI layer which is
> responsible to free and unmap them. The MSI mapping resources are freeed
> by the IOMMU driver on domain destruction.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> 
> ---
> 
> v7 -> v8:
> - do no destroy anything anymore, just bypass unmap/unpin and iommu_map
>   on replay
> ---
>  drivers/vfio/vfio_iommu_type1.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 2d769d4..94a9916 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -391,7 +391,7 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
>  	struct vfio_domain *domain, *d;
>  	long unlocked = 0;
>  
> -	if (!dma->size)
> +	if (!dma->size || dma->type != VFIO_IOVA_USER)
>  		return;
>  	/*
>  	 * We use the IOMMU to track the physical addresses, otherwise we'd
> @@ -727,6 +727,9 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
>  		dma = rb_entry(n, struct vfio_dma, node);
>  		iova = dma->iova;
>  
> +		if (dma->type == VFIO_IOVA_RESERVED)
> +			continue;
> +

But you do still need some sort of replay mechanism, right?  Not to
replay the IOVA to PA mapping, but to call iommu_msi_set_aperture() for
the new domain.  How will you know that this entry is an MSI reserved
range or something else?  Perhaps we can't have a generic "reserved"
type here.

>  		while (iova < dma->iova + dma->size) {
>  			phys_addr_t phys = iommu_iova_to_phys(d->domain, iova);
>  			size_t size;



From alex.williamson at redhat.com  Mon May  9 15:49:42 2016
From: alex.williamson at redhat.com (Alex Williamson)
Date: Mon, 9 May 2016 16:49:42 -0600
Subject: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability
 at msi domain
In-Reply-To: <1462362858-2925-6-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-6-git-send-email-eric.auger@linaro.org>
Message-ID: <20160509164942.5af8b30d@t450s.home>

On Wed,  4 May 2016 11:54:16 +0000
Eric Auger <eric.auger at linaro.org> wrote:

> On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is abstracted
> by the msi controller. vfio_safe_irq_domain allows to check whether
> interrupts are "safe" for a given device. They are if the device does
> not use MSI

Are we sure we're not opening a security hole here?  An MSI is simply a
DMA write, so really whether or not a device uses MSI is irrelevant.
If it can generate a DMA to the MSI doorbell then we need to be
protected and I think we pretty much need to assume that devices are
DMA capable.  Do the MSI domain checks cover this?

> or if the device uses MSI and the msi-parent controller
> supports IRQ remapping.
> 
> Then we check at group level if all devices have safe interrupts: if not,
> we only allow the group to be attached if allow_unsafe_interrupts is set.
> 
> At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP. This is
> changed in next patch.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> 
> ---
> v3 -> v4:
> - rename vfio_msi_parent_irq_remapping_capable into vfio_safe_irq_domain
>   and irq_remapping into safe_irq_domains
> 
> v2 -> v3:
> - protect vfio_msi_parent_irq_remapping_capable with
>   CONFIG_GENERIC_MSI_IRQ_DOMAIN
> ---
>  drivers/vfio/vfio_iommu_type1.c | 44 +++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 42 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 4d3a6f1..2fc8197 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -37,6 +37,8 @@
>  #include <linux/vfio.h>
>  #include <linux/workqueue.h>
>  #include <linux/msi-iommu.h>
> +#include <linux/irqdomain.h>
> +#include <linux/msi.h>
>  
>  #define DRIVER_VERSION  "0.2"
>  #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson at redhat.com>"
> @@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev, void *data)
>  	return 0;
>  }
>  
> +/**
> + * vfio_safe_irq_domain: returns whether the irq domain
> + * the device is attached to is safe with respect to MSI isolation.
> + * If the irq domain is not an MSI domain, we return it is safe.
> + *
> + * @dev: device handle
> + * @data: unused
> + * returns 0 if the irq domain is safe, -1 if not.
> + */
> +static int vfio_safe_irq_domain(struct device *dev, void *data)
> +{
> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> +	struct irq_domain *domain;
> +	struct msi_domain_info *info;
> +
> +	domain = dev_get_msi_domain(dev);
> +	if (!domain)
> +		return 0;
> +
> +	info = msi_get_domain_info(domain);
> +
> +	if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
> +		return -1;
> +#endif
> +	return 0;
> +}
> +
>  static int vfio_iommu_replay(struct vfio_iommu *iommu,
>  			     struct vfio_domain *domain)
>  {
> @@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>  	struct vfio_group *group, *g;
>  	struct vfio_domain *domain, *d;
>  	struct bus_type *bus = NULL;
> -	int ret;
> +	int ret, safe_irq_domains;
>  
>  	mutex_lock(&iommu->lock);
>  
> @@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>  
>  	group->iommu_group = iommu_group;
>  
> +	/*
> +	 * Determine if all the devices of the group have a safe irq domain
> +	 * with respect to MSI isolation
> +	 */
> +	safe_irq_domains = !iommu_group_for_each_dev(iommu_group, &bus,
> +				       vfio_safe_irq_domain);
> +
>  	/* Determine bus_type in order to allocate a domain */
>  	ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type);
>  	if (ret)
> @@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>  	INIT_LIST_HEAD(&domain->group_list);
>  	list_add(&group->next, &domain->group_list);
>  
> +	/*
> +	 * to advertise safe interrupts either the IOMMU or the MSI controllers
> +	 * must support IRQ remapping/interrupt translation
> +	 */
>  	if (!allow_unsafe_interrupts &&
> -	    !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
> +	    (!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) && !safe_irq_domains)) {
>  		pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",
>  		       __func__);
>  		ret = -EPERM;



From alex.williamson at redhat.com  Mon May  9 15:49:50 2016
From: alex.williamson at redhat.com (Alex Williamson)
Date: Mon, 9 May 2016 16:49:50 -0600
Subject: [PATCH v9 7/7] vfio/type1: return MSI geometry through
 VFIO_IOMMU_GET_INFO capability chains
In-Reply-To: <1462362858-2925-8-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-8-git-send-email-eric.auger@linaro.org>
Message-ID: <20160509164950.0b1cf9c1@t450s.home>

On Wed,  4 May 2016 11:54:18 +0000
Eric Auger <eric.auger at linaro.org> wrote:

> This patch allows the user-space to retrieve the MSI geometry. The
> implementation is based on capability chains, now also added to
> VFIO_IOMMU_GET_INFO.
> 
> The returned info comprise:
> - whether the MSI IOVA are constrained to a reserved range (x86 case) and
>   in the positive, the start/end of the aperture,
> - or whether the IOVA aperture need to be set by the userspace. In that
>   case, the size and alignment of the IOVA region to be provided are
>   returned.
> 
> In case the userspace must provide the IOVA range, we currently return
> an arbitrary number of IOVA pages (16), supposed to fulfill the needs of
> current ARM platforms. This may be deprecated by a more sophisticated
> computation later on.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> 
> ---
> v8 -> v9:
> - use iommu_msi_supported flag instead of programmable
> - replace IOMMU_INFO_REQUIRE_MSI_MAP flag by a more sophisticated
>   capability chain, reporting the MSI geometry
> 
> v7 -> v8:
> - use iommu_domain_msi_geometry
> 
> v6 -> v7:
> - remove the computation of the number of IOVA pages to be provisionned.
>   This number depends on the domain/group/device topology which can
>   dynamically change. Let's rely instead rely on an arbitrary max depending
>   on the system
> 
> v4 -> v5:
> - move msi_info and ret declaration within the conditional code
> 
> v3 -> v4:
> - replace former vfio_domains_require_msi_mapping by
>   more complex computation of MSI mapping requirements, especially the
>   number of pages to be provided by the user-space.
> - reword patch title
> 
> RFC v1 -> v1:
> - derived from
>   [RFC PATCH 3/6] vfio: Extend iommu-info to return MSIs automap state
> - renamed allow_msi_reconfig into require_msi_mapping
> - fixed VFIO_IOMMU_GET_INFO
> ---
>  drivers/vfio/vfio_iommu_type1.c | 69 +++++++++++++++++++++++++++++++++++++++++
>  include/uapi/linux/vfio.h       | 30 +++++++++++++++++-
>  2 files changed, 98 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 2fc8197..841360b 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -1134,6 +1134,50 @@ static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu)
>  	return ret;
>  }
>  
> +static int compute_msi_geometry_caps(struct vfio_iommu *iommu,
> +				     struct vfio_info_cap *caps)
> +{
> +	struct vfio_iommu_type1_info_cap_msi_geometry *vfio_msi_geometry;
> +	struct iommu_domain_msi_geometry msi_geometry;
> +	struct vfio_info_cap_header *header;
> +	struct vfio_domain *d;
> +	bool mapping_required;
> +	size_t size;
> +
> +	mutex_lock(&iommu->lock);
> +	/* All domains have same require_msi_map property, pick first */
> +	d = list_first_entry(&iommu->domain_list, struct vfio_domain, next);
> +	iommu_domain_get_attr(d->domain, DOMAIN_ATTR_MSI_GEOMETRY,
> +			      &msi_geometry);
> +	mapping_required = msi_geometry.iommu_msi_supported;
> +
> +	mutex_unlock(&iommu->lock);
> +
> +	size = sizeof(*vfio_msi_geometry);
> +	header = vfio_info_cap_add(caps, size,
> +				   VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY, 1);
> +
> +	if (IS_ERR(header))
> +		return PTR_ERR(header);
> +
> +	vfio_msi_geometry = container_of(header,
> +				struct vfio_iommu_type1_info_cap_msi_geometry,
> +				header);
> +
> +	vfio_msi_geometry->reserved = !mapping_required;
> +	if (vfio_msi_geometry->reserved) {
> +		vfio_msi_geometry->aperture_start = msi_geometry.aperture_start;
> +		vfio_msi_geometry->aperture_end = msi_geometry.aperture_end;
> +		return 0;
> +	}
> +
> +	vfio_msi_geometry->alignment = 1 << __ffs(vfio_pgsize_bitmap(iommu));
> +	/* we currently report the need for an arbitray number of 16 pages */
> +	vfio_msi_geometry->size = 16 * vfio_msi_geometry->alignment;

Hmm, that really is arbitrary.  How could we know a real value here?

> +
> +	return 0;
> +}
> +
>  static long vfio_iommu_type1_ioctl(void *iommu_data,
>  				   unsigned int cmd, unsigned long arg)
>  {
> @@ -1155,6 +1199,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>  		}
>  	} else if (cmd == VFIO_IOMMU_GET_INFO) {
>  		struct vfio_iommu_type1_info info;
> +		struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
> +		int ret;
>  
>  		minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes);
>  
> @@ -1168,6 +1214,29 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>  
>  		info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
>  
> +		ret = compute_msi_geometry_caps(iommu, &caps);
> +		if (ret)
> +			return ret;
> +
> +		if (caps.size) {
> +			info.flags |= VFIO_IOMMU_INFO_CAPS;
> +			if (info.argsz < sizeof(info) + caps.size) {
> +				info.argsz = sizeof(info) + caps.size;
> +				info.cap_offset = 0;
> +			} else {
> +				vfio_info_cap_shift(&caps, sizeof(info));
> +				if (copy_to_user((void __user *)arg +
> +						sizeof(info), caps.buf,
> +						caps.size)) {
> +					kfree(caps.buf);
> +					return -EFAULT;
> +				}
> +				info.cap_offset = sizeof(info);
> +			}
> +
> +			kfree(caps.buf);
> +		}
> +
>  		return copy_to_user((void __user *)arg, &info, minsz) ?
>  			-EFAULT : 0;
>  
> diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
> index 4a9dbc2..0ff6a8d 100644
> --- a/include/uapi/linux/vfio.h
> +++ b/include/uapi/linux/vfio.h
> @@ -488,7 +488,33 @@ struct vfio_iommu_type1_info {
>  	__u32	argsz;
>  	__u32	flags;
>  #define VFIO_IOMMU_INFO_PGSIZES (1 << 0)	/* supported page sizes info */
> -	__u64	iova_pgsizes;		/* Bitmap of supported page sizes */
> +#define VFIO_IOMMU_INFO_CAPS	(1 << 1)	/* Info supports caps */
> +	__u32   cap_offset;	/* Offset within info struct of first cap */
> +	__u64	iova_pgsizes;	/* Bitmap of supported page sizes */

This would break existing users, we can't arbitrarily change the offset
of iova_pgsizes.  We can add cap_offset to the end and I think
everything would work about above if we do that.

> +};
> +
> +#define VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY	1
> +
> +/*
> + * The MSI geometry capability allows to report the MSI IOVA geometry:
> + * - either the MSI IOVAs are constrained within a reserved IOVA aperture
> + *   whose boundaries are given by [@aperture_start, @aperture_end].
> + *   this is typically the case on x86 host. The userspace is not allowed
> + *   to map userspace memory at IOVAs intersecting this range using
> + *   VFIO_IOMMU_MAP_DMA.
> + * - or the MSI IOVAs are not requested to belong to any reserved range;
> + *   in that case the userspace must provide an IOVA window characterized by
> + *   @size and @alignment using VFIO_IOMMU_MAP_DMA with RESERVED_MSI_IOVA flag.
> + */
> +struct vfio_iommu_type1_info_cap_msi_geometry {
> +	struct vfio_info_cap_header header;
> +	bool reserved; /* Are MSI IOVAs within a reserved aperture? */

Do bools have a guaranteed user size?  Let's make this a __u32 and call
it flags with bit 0 defined as reserved.  I'm tempted to suggest we
could figure out how to make alignment fit in another __u32 so we have a
properly packed structure, otherwise we should make a reserved __u32.

> +	/* reserved */
> +	__u64 aperture_start;
> +	__u64 aperture_end;
> +	/* not reserved */
> +	__u64 size; /* IOVA aperture size in bytes the userspace must provide */
> +	__u64 alignment; /* alignment of the window, in bytes */
>  };
>  
>  #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
> @@ -503,6 +529,8 @@ struct vfio_iommu_type1_info {
>   * IOVA region that will be used on some platforms to map the host MSI frames.
>   * In that specific case, vaddr is ignored. Once registered, an MSI reserved
>   * IOVA region stays until the container is closed.
> + * The requirement for provisioning such reserved IOVA range can be checked by
> + * checking the VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY capability.
>   */
>  struct vfio_iommu_type1_dma_map {
>  	__u32	argsz;



From sboyd at codeaurora.org  Mon May  9 15:49:53 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 9 May 2016 15:49:53 -0700
Subject: [PATCH 2/4] drvers/clk: Support fourth generation Aspeed SoCs
In-Reply-To: <1462797111-14271-3-git-send-email-joel@jms.id.au>
References: <1462797111-14271-1-git-send-email-joel@jms.id.au>
 <1462797111-14271-3-git-send-email-joel@jms.id.au>
Message-ID: <20160509224953.GZ3492@codeaurora.org>

On 05/09, Joel Stanley wrote:
> diff --git a/drivers/clk/aspeed/clk-g4.c b/drivers/clk/aspeed/clk-g4.c
> new file mode 100644
> index 000000000000..91677e9177f5
> --- /dev/null
> +++ b/drivers/clk/aspeed/clk-g4.c
> @@ -0,0 +1,109 @@
> +/*
> + * Copyright 2016 IBM Corporation
> + *
> + * 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.
> + */
> +
> +#include <linux/clk.h>

Hopefully this include isn't needed.

> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/clkdev.h>
> +
> +static void __init aspeed_of_hpll_clk_init(struct device_node *node)
> +{
> +	struct clk *clk, *clkin_clk;
> +	void __iomem *base;
> +	int reg, rate, clkin;
> +	const char *name = node->name;
> +	const char *parent_name;
> +	const int rates[][4] = {
> +		{384, 360, 336, 408},
> +		{400, 375, 350, 425},
> +	};
> +
> +	of_property_read_string(node, "clock-output-names", &name);
> +	parent_name = of_clk_get_parent_name(node, 0);
> +
> +	base = of_iomap(node, 0);
> +	if (!base) {
> +		pr_err("%s: of_iomap failed\n", node->full_name);
> +		return;
> +	}
> +	reg = readl(base);
> +	iounmap(base);
> +
> +	clkin_clk = of_clk_get(node, 0);
> +	if (IS_ERR(clkin_clk)) {
> +		pr_err("%s: of_clk_get failed\n", node->full_name);
> +		return;
> +	}
> +
> +	clkin = clk_get_rate(clkin_clk);
> +
> +	reg = (reg >> 8) & 0x2;
> +
> +	if (clkin == 48000000 || clkin == 24000000)
> +		rate = rates[0][reg] * 1000000;
> +	else if (clkin == 25000000)
> +		rate = rates[1][reg] * 1000000;
> +	else {
> +		pr_err("%s: unknown clkin frequency %dHz\n",
> +				node->full_name, clkin);
> +		WARN_ON(1);
> +	}
> +
> +	clk = clk_register_fixed_rate(NULL, name, parent_name, 0, rate);

Please write a proper clk driver that sets clkin to be the parent
of this clk registered here and then calculates the frequency
based on the parent clk rate and the strapping registers via the
recalc rate callback. Also please move this to a platform driver
instead of using CLK_OF_DECLARE assuming this isn't required for
any timers in the system.

> +	if (IS_ERR(clk)) {
> +		pr_err("%s: failed to register clock\n", node->full_name);
> +		return;
> +	}
> +
> +	clk_register_clkdev(clk, NULL, name);

Do you have clkdev users? If not then please drop this.

> +	of_clk_add_provider(node, of_clk_src_simple_get, clk);
> +}
> +CLK_OF_DECLARE(aspeed_hpll_clock, "aspeed,g4-hpll-clock",
> +	       aspeed_of_hpll_clk_init);
> +
> +static void __init aspeed_of_apb_clk_init(struct device_node *node)
> +{
> +	struct clk *clk, *hpll_clk;
> +	void __iomem *base;
> +	int reg, rate;
> +	const char *name = node->name;
> +	const char *parent_name;
> +
> +	of_property_read_string(node, "clock-output-names", &name);
> +	parent_name = of_clk_get_parent_name(node, 0);
> +
> +	base = of_iomap(node, 0);
> +	if (!base) {
> +		pr_err("%s: of_iomap failed\n", node->full_name);
> +		return;
> +	}
> +	reg = readl(base);
> +	iounmap(base);
> +
> +	hpll_clk = of_clk_get(node, 0);
> +	if (IS_ERR(hpll_clk)) {
> +		pr_err("%s: of_clk_get failed\n", node->full_name);
> +		return;
> +	}
> +
> +	reg = (reg >> 23) & 0x3;
> +	rate = clk_get_rate(hpll_clk) / (2 + 2 * reg);
> +
> +	clk = clk_register_fixed_rate(NULL, name, parent_name, 0, rate);
> +	if (IS_ERR(clk)) {
> +		pr_err("%s: failed to register clock\n", node->full_name);
> +		return;
> +	}
> +
> +	clk_register_clkdev(clk, NULL, name);
> +	of_clk_add_provider(node, of_clk_src_simple_get, clk);
> +}
> +CLK_OF_DECLARE(aspeed_apb_clock, "aspeed,g4-apb-clock",
> +	       aspeed_of_apb_clk_init);

Following on Rob's comment, please combine this into one driver
instead of having different DT nodes for different clks that are
all really part of one clock controller hw block.

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


From rjw at rjwysocki.net  Mon May  9 15:56:37 2016
From: rjw at rjwysocki.net (Rafael J. Wysocki)
Date: Tue, 10 May 2016 00:56:37 +0200
Subject: [PATCH V6 01/13] pci, acpi, x86,
 ia64: Move ACPI host bridge device companion assignment to core code.
In-Reply-To: <1460740008-19489-2-git-send-email-tn@semihalf.com>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-2-git-send-email-tn@semihalf.com>
Message-ID: <292578579.uIxhMjkdfG@vostro.rjw.lan>

On Friday, April 15, 2016 07:06:36 PM Tomasz Nowicki wrote:
> Currently we have two platforms (x86 & ia64) capable of PCI ACPI host
> bridge initialization. They both use arch-specific sysdata to pass down
> parent device reference and both rely on NULL parent in pci_create_root_bus()
> to validate sysdata content.

No, this is not relied on for that.  It is just NULL, because we don't
have a physical parent device representation for the PCI host bridge.

> It looks hacky and prevents us from getting some firmware specific
> info for PCI host controller based on its acpi_device structure
> in generic pci_create_root_bus() function.

You can't get that info without adding ACPI-specific code to that function
anyway.

> However, we overcome that blocker by passing down parent device via
> pci_create_root_bus parameter (as the ACPI device type).

Which is completely wrong.

> Then we use ACPI_COMPANION_SET in core code
> for ACPI boot method only. ACPI_COMPANION_SET is safe to run for all
> cases DT, ACPI and DT&ACPI.
> 
> Since now PCI core code is setting ACPI companion device for us,
> x86 & ia64 specific ACPI companion device setting turns out to be dead now.
> We can get rid of it, including related companion reference from
> PCI sysdata structure. Aslo, PCI_CONTROLLER macro cannot return valid
> companion device anymore. Therefore we need to convert its usage to
> ACPI_COMPANION.
> 
> Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
> Tested-by: Duc Dang <dhdang at apm.com>
> Tested-by: Dongdong Liu <liudongdong3 at huawei.com>
> Tested-by: Hanjun Guo <hanjun.guo at linaro.org>
> Tested-by: Graeme Gregory <graeme.gregory at linaro.org>
> Tested-by: Sinan Kaya <okaya at codeaurora.org>
> ---
>  arch/ia64/hp/common/sba_iommu.c    |  2 +-
>  arch/ia64/include/asm/pci.h        |  1 -
>  arch/ia64/pci/pci.c                | 16 ----------------
>  arch/ia64/sn/kernel/io_acpi_init.c |  4 ++--
>  arch/x86/include/asm/pci.h         |  3 ---
>  arch/x86/pci/acpi.c                | 17 -----------------
>  drivers/acpi/pci_root.c            |  7 ++++++-
>  drivers/pci/probe.c                |  2 ++
>  8 files changed, 11 insertions(+), 41 deletions(-)
> 
> diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
> index a6d6190..78e4444 100644
> --- a/arch/ia64/hp/common/sba_iommu.c
> +++ b/arch/ia64/hp/common/sba_iommu.c
> @@ -1981,7 +1981,7 @@ sba_connect_bus(struct pci_bus *bus)
>  	if (PCI_CONTROLLER(bus)->iommu)
>  		return;
>  
> -	handle = acpi_device_handle(PCI_CONTROLLER(bus)->companion);
> +	handle = acpi_device_handle(ACPI_COMPANION(bus->bridge));
>  	if (!handle)
>  		return;
>  
> diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
> index c0835b0..12423f4 100644
> --- a/arch/ia64/include/asm/pci.h
> +++ b/arch/ia64/include/asm/pci.h
> @@ -63,7 +63,6 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
>  #define pci_legacy_write platform_pci_legacy_write
>  
>  struct pci_controller {
> -	struct acpi_device *companion;
>  	void *iommu;
>  	int segment;
>  	int node;		/* nearest node with memory or NUMA_NO_NODE for global allocation */
> diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
> index 8f6ac2f..978d6af 100644
> --- a/arch/ia64/pci/pci.c
> +++ b/arch/ia64/pci/pci.c
> @@ -301,28 +301,12 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>  	}
>  
>  	info->controller.segment = root->segment;
> -	info->controller.companion = device;
>  	info->controller.node = acpi_get_node(device->handle);
>  	INIT_LIST_HEAD(&info->io_resources);
>  	return acpi_pci_root_create(root, &pci_acpi_root_ops,
>  				    &info->common, &info->controller);
>  }
>  
> -int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> -{
> -	/*
> -	 * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL
> -	 * here, pci_create_root_bus() has been called by someone else and
> -	 * sysdata is likely to be different from what we expect.  Let it go in
> -	 * that case.
> -	 */
> -	if (!bridge->dev.parent) {
> -		struct pci_controller *controller = bridge->bus->sysdata;
> -		ACPI_COMPANION_SET(&bridge->dev, controller->companion);
> -	}
> -	return 0;
> -}
> -
>  void pcibios_fixup_device_resources(struct pci_dev *dev)
>  {
>  	int idx;
> diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c
> index 231234c..e454492 100644
> --- a/arch/ia64/sn/kernel/io_acpi_init.c
> +++ b/arch/ia64/sn/kernel/io_acpi_init.c
> @@ -132,7 +132,7 @@ sn_get_bussoft_ptr(struct pci_bus *bus)
>  	struct acpi_resource_vendor_typed *vendor;
>  
>  
> -	handle = acpi_device_handle(PCI_CONTROLLER(bus)->companion);
> +	handle = acpi_device_handle(ACPI_COMPANION(bus->bridge));
>  	status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
>  					  &sn_uuid, &buffer);
>  	if (ACPI_FAILURE(status)) {
> @@ -360,7 +360,7 @@ sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
>  	acpi_status status;
>  	struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>  
> -	rootbus_handle = acpi_device_handle(PCI_CONTROLLER(dev)->companion);
> +	rootbus_handle = acpi_device_handle(ACPI_COMPANION(dev->bus->bridge));
>          status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL,
>                                         &segment);
>          if (ACPI_SUCCESS(status)) {
> diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
> index 9ab7507..24de07d 100644
> --- a/arch/x86/include/asm/pci.h
> +++ b/arch/x86/include/asm/pci.h
> @@ -14,9 +14,6 @@
>  struct pci_sysdata {
>  	int		domain;		/* PCI domain */
>  	int		node;		/* NUMA node */
> -#ifdef CONFIG_ACPI
> -	struct acpi_device *companion;	/* ACPI companion device */
> -#endif
>  #ifdef CONFIG_X86_64
>  	void		*iommu;		/* IOMMU private data */
>  #endif
> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
> index 3cd6983..f4ca17a 100644
> --- a/arch/x86/pci/acpi.c
> +++ b/arch/x86/pci/acpi.c
> @@ -340,7 +340,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>  		struct pci_sysdata sd = {
>  			.domain = domain,
>  			.node = node,
> -			.companion = root->device
>  		};
>  
>  		memcpy(bus->sysdata, &sd, sizeof(sd));
> @@ -355,7 +354,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>  		else {
>  			info->sd.domain = domain;
>  			info->sd.node = node;
> -			info->sd.companion = root->device;
>  			bus = acpi_pci_root_create(root, &acpi_pci_root_ops,
>  						   &info->common, &info->sd);
>  		}
> @@ -373,21 +371,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
>  	return bus;
>  }
>  
> -int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> -{
> -	/*
> -	 * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL
> -	 * here, pci_create_root_bus() has been called by someone else and
> -	 * sysdata is likely to be different from what we expect.  Let it go in
> -	 * that case.
> -	 */
> -	if (!bridge->dev.parent) {
> -		struct pci_sysdata *sd = bridge->bus->sysdata;
> -		ACPI_COMPANION_SET(&bridge->dev, sd->companion);
> -	}
> -	return 0;
> -}
> -
>  int __init pci_acpi_init(void)
>  {
>  	struct pci_dev *dev = NULL;
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index ae3fe4e..4581e0e 100644
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -564,6 +564,11 @@ static int acpi_pci_root_add(struct acpi_device *device,
>  		}
>  	}
>  
> +	/*
> +	 * pci_create_root_bus() needs to detect the parent device type,
> +	 * so initialize its companion data accordingly.
> +	 */
> +	ACPI_COMPANION_SET(&device->dev, device);

This is a complete nonsense, sorry.

This just means that the ACPI firmware object will now be an ACPI companion of
itself.

Thanks,
Rafael



From robh at kernel.org  Mon May  9 15:58:42 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 9 May 2016 17:58:42 -0500
Subject: [PATCH v2 5/5] vf610-soc: Add Vybrid SoC device tree binding
 documentation
In-Reply-To: <4ca82be6c1d434c612868b441e9f6e1f@agner.ch>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
 <65f3a7bd7a9faf1b390644d7c599c69683c753c4.1462171990.git.maitysanchayan@gmail.com>
 <20160504023026.GB5382@rob-hp-laptop>
 <20160505082758.GB18151@Sanchayan-Arch.localdomain>
 <CAL_JsqL1qQu_u=6xosP8UmR3oXLawbVz=Hap0wDm7aN4mjK2GA@mail.gmail.com>
 <4ca82be6c1d434c612868b441e9f6e1f@agner.ch>
Message-ID: <CAL_JsqL7sjdONYad6sXM1KXFCjooANuN7WYg-paV9LnKnuMTnA@mail.gmail.com>

On Mon, May 9, 2016 at 1:25 PM, Stefan Agner <stefan at agner.ch> wrote:
> On 2016-05-09 10:14, Rob Herring wrote:
>> On Thu, May 5, 2016 at 3:27 AM,  <maitysanchayan at gmail.com> wrote:
>>> Hello Rob,
>>>
>>> On 16-05-03 21:30:26, Rob Herring wrote:
>>>> On Mon, May 02, 2016 at 12:35:04PM +0530, Sanchayan Maity wrote:
>>>> > Add device tree binding documentation for Vybrid SoC.
>>>> >
>>>> > Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
>>>> > ---
>>>> >  .../bindings/arm/freescale/fsl,vf610-soc.txt       | 35 ++++++++++++++++++++++
>>>> >  1 file changed, 35 insertions(+)
>>>> >  create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>>>> >
>>>> > diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>>>> > new file mode 100644
>>>> > index 0000000..bdd95e8
>>>> > --- /dev/null
>>>> > +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>>>> > @@ -0,0 +1,35 @@
>>>> > +Vybrid System-on-Chip
>>>> > +---------------------
>>>> > +
>>>> > +Required properties:
>>>> > +
>>>> > +- #address-cells: must be 1
>>>> > +- #size-cells: must be 1
>>>> > +- compatible: "fsl,vf610-soc-bus", "simple-bus"
>>>>
>>>> If this is a bus, put the file in bindings/bus/...
>>>
>>> The fsl,vf610-soc-bus binding is used to bind the driver in question with
>>> an appropriate compatible node.
>>>
>>> Basically being a standalone platform driver, there was need of a compatible
>>> property to bind on. Introducing a separate device tree node for it's sake
>>> didn't seem appropriate so the alteration to SoC node's compatible.
>>
>> Ah, so you are designing a node around the needs of a Linux specific
>> driver. Don't do that. DT describes the h/w and this node is not a h/w
>> block.
>>
>> Create a platform device based on a matching SOC compatible string
>> instead and make your driver find the information it needs directly
>> from the relevant nodes like the ROM node.
>
> That reads like my words a year ago:
> https://lkml.org/lkml/2015/5/22/408
>
> Initially pretty much everything was hard-coded in the driver.
>
> Arnd then pushed to use more descriptive in the device tree.
>
> Of course, we should not end up making up relations which are not there
> in hardware. We need to find the right balance.
>
> Here is my suggestion:
> 1. Add "fsl,vf610-soc-bus" as compatible string to the soc node, use it
> to bind the "soc bus driver" as a platform driver located in driver/soc/

I'm not convinced this is a h/w block. This keeps coming up and I
think this is a kernel problem, not a DT problem. Let's face it that
there are drivers at the SOC level which don't fit into a DT node.
They may be the exception, but they are a common exception. My
proposal for how to deal with these cases is here[1].

I also think drivers/soc is a mess because it is randomly used or not.
IMO, using it should not be at the whim of whomever does SOC support.

> 2. Add ROM as syscon device (it is not erasable ROM memory, hence eeprom
> seems not to be appropriate)

It is not a syscon. It is just memory. nvmem covers read-only memory,
so I have no issue using that.

Rob

[1] https://lkml.org/lkml/2013/10/30/27


From alex.williamson at redhat.com  Mon May  9 16:03:12 2016
From: alex.williamson at redhat.com (Alex Williamson)
Date: Mon, 9 May 2016 17:03:12 -0600
Subject: [PATCH v9 7/7] vfio/type1: return MSI geometry through
 VFIO_IOMMU_GET_INFO capability chains
In-Reply-To: <5729E5BB.1030101@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-8-git-send-email-eric.auger@linaro.org>
 <5729E5BB.1030101@linaro.org>
Message-ID: <20160509170312.06e9c4fe@t450s.home>

On Wed, 4 May 2016 14:06:19 +0200
Eric Auger <eric.auger at linaro.org> wrote:

> Hi Alex,
> On 05/04/2016 01:54 PM, Eric Auger wrote:
> > This patch allows the user-space to retrieve the MSI geometry. The
> > implementation is based on capability chains, now also added to
> > VFIO_IOMMU_GET_INFO.  
> 
> If you prefer we could consider this patch outside of the main series
> since it brings extra functionalities (MSI geometry reporting). In a
> first QEMU integration we would live without knowing the MSI geometry I
> think, all the more so I currently report an arbitrary number of
> requested IOVA pages. The computation of the exact number of doorbells
> to map brings extra complexity and I did not address this issue yet.
> 
> It sketches a possible user API to report the MSI geometry based on the
> capability chains, as you suggested some time ago. I am currently busy
> drafting a QEMU integration.

How would the user know that reserved MSI mappings are requires or
available without this?  Wouldn't the only option be for userspace to
try to map something with the reserved MSI flag set and see if the
kernel accepts it?  That's not a very desirable programming model.  The
arbitrary size is pretty ugly, but it at least makes for a consistent
user interface.  Is it a functional issue if we overestimate the size
or is it just a matter of wasting IOVA space?  Is there significant
harm in making it obscenely large, like 1MB?  The reference counting and
re-use of IOVA pages seems like we may often only be using a single
IOVA page for multiple doorbells.  I guess I'm leaning towards defining
the API even if the value is somewhat arbitrary because we'd rather have
control of this rather than having the user guess and try to rope them
back in later to use a kernel recommended value.  Thanks,

Alex


From florian.fainelli at broadcom.com  Mon May  9 16:15:05 2016
From: florian.fainelli at broadcom.com (Florian Fainelli)
Date: Mon, 9 May 2016 16:15:05 -0700
Subject: [PATCH v2 1/2] Documentation: DT: bindings: Add Broadcom STB PCIe
 bindings
In-Reply-To: <20160509192641.GA4936@rob-hp-laptop>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
 <1462475700-1654-2-git-send-email-f.fainelli@gmail.com>
 <20160509192641.GA4936@rob-hp-laptop>
Message-ID: <573119F9.3040509@broadcom.com>

On 05/09/2016 12:26 PM, Rob Herring wrote:
> On Thu, May 05, 2016 at 12:14:59PM -0700, Florian Fainelli wrote:
>> From: Jim Quinlan <jim2101024 at gmail.com>
>>
>> This patchs adds the Device Tree bindings for the Broadcom STB PCIe root
>> complex hardware.
>>
>> Signed-off-by: Jim Quinlan <jim2101024 at gmail.com>
>> Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
>> ---
>> Changes in v2:
>>
>> - rewrite the binding document almost from scratch to include many more
>>   references to existing documents
>> - describe missing properties
>> - give better examples
>>
>>  .../devicetree/bindings/pci/brcm,brcmstb-pcie.txt  | 98 ++++++++++++++++++++++
>>  1 file changed, 98 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
>>
>> diff --git a/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
>> new file mode 100644
>> index 000000000000..3682b0f0bc26
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
>> @@ -0,0 +1,98 @@
>> +Broadcom STB PCIe Host Controller Device Tree Bindings
>> +
>> +This document describes the binding of the PCIe Root Complex hardware found in
>> +Broadcom Set Top Box System-on-Chips such as BCM7425 (MIPS), BCM7435 (MIPS) and
>> +BCM7445 (ARMv7).
>> +
>> +Required properties:
>> +- compatible: must be one of: "brcm,bcm7425-pcie"
>> +			      "brcm,bcm7435-pcie"
>> +			      "brcm,bcm7445-pcie"
>> +
>> +- reg: specifies the physical base address of the controller registers and
>> +  its length
>> +
>> +- interrupt-parent: must be a reference (phandle) to the parent interrupt
>> +  controller in the system (7038-l1-intc on MIPS, GIC on ARM/ARM64)
>> +
>> +- interrrupts: first interrupt must be the Level 1 interrupt number corresponding
>> +  to the main PCIe RC interrupt, second interrupt must be the MSI interrupt
>> +  See the interrupt-parent documentation for the number of cells and their meaning:
>> +  MIPS: Documentation/devicetree/bindings/interrupt-controller/brcm,bcm7038-l1-intc.txt
>> +  ARM/ARM64: Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
>> +
>> +- interrupt-names: must be "pcie", and if present "msi"
>> +
>> +- interrupt-map: see pci.txt
>> +
>> +- interrupt-map-mask: see pci.txt
>> +
>> +- #address-cells: must be set to <3>, see pci.txt
>> +
>> +- #size-cells: must be set to <2>, see pci.txt
>> +
>> +- ranges: ranges for the PCI outbound windows, no I/O or prefetchable windows
>> +  must be specified here, only non-prefetchable. 32-bits windows or 64-bits
>> +  windows are allowed based on the host processor's capabilities (ARM w/ LPAE,
>> +  ARM64).
>> +
>> +- #interrupt-cells: set to <1>, see pci.txt
>> +
>> +- brcm,log2-scb-sizes: log2 size of the SCB window that is mapped to PCIe space
>> +  there must be exactly one value per memory controller present in the system
>> +  (ranges from 1 to 3)
>> +
>> +Optional properties:
>> +
>> +- msi-controller: indicates that this is a MSI controller node (when supported)
>> +
>> +- clocks: phandle to the functional clock that feeds into the PCIe RC block
>> +
>> +- clock-names: the name(s) of the clocks specified in 'clocks'.  Note
>> +  that if the 'clocks' property is given, 'clock-names' is mandatory,
>> +  and the name of the clock is expected to be "pcie".
>> +
>> +- brcm,ssc: boolean that indicates usage of spread-spectrum clocking
> 
> Shouldn't this be a property of the phy? Is there no separate phy to 
> control?

No, the PHY is baked into the PCIe root complex, which is why this is a
property of the root complex node since the two are conflated.

> 
>> +
>> +- brcm,gen: integer that indicates desired forced generation of link: 1 => 2.5
>> +  Gbps, 2 => 5.0 Gbps, 3 => 8.0 Gbps. Will override the auto-negotation if
>> +  specified.
>> +
>> +- <*>-supply: see Documentation/devicetree/bindings/regulator/regulator.txt
>> +
>> +- <*>-supply-names: see Documentation/devicetree/bindings/regulator/regulator.txt
>> +
>> +Example Node:
>> +
>> +This example assumes that the top-level #address-cells = <2> and #size-cells =
>> +<2>, e.g: ARM LPAE configuration.
>> +
>> +	pcie0: pcie-controller at f0460000 {
>> +		reg = <0x0 0xf0460000 0x0 0x9310>;
>> +		interrupts = <0x0 0x33 0x4>, <0x0 0x34, 0x4>;
>                                                       ^
> typo

Whoops, thanks.

> 
>> +		interrupt-names = "pcie", "msi";
>> +		compatible = "brcm,bcm7445-pcie";
>> +		#address-cells = <3>;
>> +		#size-cells = <2>;
>> +
>> +		/* Two non-prefetchable 32-bits memory space, each of 128MB
>> + 		 * with the following mapping:
>> +		 * PCIe address		=> CPU physical address space
>> +		 * 0x00_0000_0000	=> 0x00_C000_0000
>> +		 * 0x00_0800_0000	=> 0x00_C800_0000
>> +		 */
>> +		ranges = <0x02000000 0x00000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x08000000>,
>> +			 <0x02000000 0x00000000 0x08000000 0x00000000 0xc8000000 0x00000000 0x08000000>;
>> +		#interrupt-cells = <1>;
>> +		interrupt-map-mask = <0xf800 0 0 7>;
>> +		interrupt-map = <0 0 0 1 &intc 47 3
>> +				 0 0 0 2 &intc 48 3
>> +				 0 0 0 3 &intc 49 3
>> +				 0 0 0 4 &intc 50 3>;
>> +		clocks = <&pcie0>;
>> +		clock-names = "pcie";
>> +		brcm,ssc;
>> +		brcm,log2-scb-sizes = <0x1e 0x1e 0x1e>;
>> +		vreg-wifi-pwr-supply-names = "vreg-wifi-pwr";
>> +		vreg-wifi-pwr-supply = <&vreg-wifi-pwr>;
> 
> The supply for the PCIE RC is called "vreg-wifi-pwr"? Seems a bit 
> strange.

It can be called anything, this just happens to be the example, but I
can certainly drop that, since a) this is optional and b) we need to
rework that in the driver anyway.
-- 
Florian


From f.fainelli at gmail.com  Mon May  9 16:15:11 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Mon, 9 May 2016 16:15:11 -0700
Subject: [PATCH v2 1/2] Documentation: DT: bindings: Add Broadcom STB PCIe
 bindings
In-Reply-To: <20160509192641.GA4936@rob-hp-laptop>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
 <1462475700-1654-2-git-send-email-f.fainelli@gmail.com>
 <20160509192641.GA4936@rob-hp-laptop>
Message-ID: <573119FF.9000306@gmail.com>

On 05/09/2016 12:26 PM, Rob Herring wrote:
> On Thu, May 05, 2016 at 12:14:59PM -0700, Florian Fainelli wrote:
>> From: Jim Quinlan <jim2101024 at gmail.com>
>>
>> This patchs adds the Device Tree bindings for the Broadcom STB PCIe root
>> complex hardware.
>>
>> Signed-off-by: Jim Quinlan <jim2101024 at gmail.com>
>> Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
>> ---
>> Changes in v2:
>>
>> - rewrite the binding document almost from scratch to include many more
>>   references to existing documents
>> - describe missing properties
>> - give better examples
>>
>>  .../devicetree/bindings/pci/brcm,brcmstb-pcie.txt  | 98 ++++++++++++++++++++++
>>  1 file changed, 98 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
>>
>> diff --git a/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
>> new file mode 100644
>> index 000000000000..3682b0f0bc26
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
>> @@ -0,0 +1,98 @@
>> +Broadcom STB PCIe Host Controller Device Tree Bindings
>> +
>> +This document describes the binding of the PCIe Root Complex hardware found in
>> +Broadcom Set Top Box System-on-Chips such as BCM7425 (MIPS), BCM7435 (MIPS) and
>> +BCM7445 (ARMv7).
>> +
>> +Required properties:
>> +- compatible: must be one of: "brcm,bcm7425-pcie"
>> +			      "brcm,bcm7435-pcie"
>> +			      "brcm,bcm7445-pcie"
>> +
>> +- reg: specifies the physical base address of the controller registers and
>> +  its length
>> +
>> +- interrupt-parent: must be a reference (phandle) to the parent interrupt
>> +  controller in the system (7038-l1-intc on MIPS, GIC on ARM/ARM64)
>> +
>> +- interrrupts: first interrupt must be the Level 1 interrupt number corresponding
>> +  to the main PCIe RC interrupt, second interrupt must be the MSI interrupt
>> +  See the interrupt-parent documentation for the number of cells and their meaning:
>> +  MIPS: Documentation/devicetree/bindings/interrupt-controller/brcm,bcm7038-l1-intc.txt
>> +  ARM/ARM64: Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
>> +
>> +- interrupt-names: must be "pcie", and if present "msi"
>> +
>> +- interrupt-map: see pci.txt
>> +
>> +- interrupt-map-mask: see pci.txt
>> +
>> +- #address-cells: must be set to <3>, see pci.txt
>> +
>> +- #size-cells: must be set to <2>, see pci.txt
>> +
>> +- ranges: ranges for the PCI outbound windows, no I/O or prefetchable windows
>> +  must be specified here, only non-prefetchable. 32-bits windows or 64-bits
>> +  windows are allowed based on the host processor's capabilities (ARM w/ LPAE,
>> +  ARM64).
>> +
>> +- #interrupt-cells: set to <1>, see pci.txt
>> +
>> +- brcm,log2-scb-sizes: log2 size of the SCB window that is mapped to PCIe space
>> +  there must be exactly one value per memory controller present in the system
>> +  (ranges from 1 to 3)
>> +
>> +Optional properties:
>> +
>> +- msi-controller: indicates that this is a MSI controller node (when supported)
>> +
>> +- clocks: phandle to the functional clock that feeds into the PCIe RC block
>> +
>> +- clock-names: the name(s) of the clocks specified in 'clocks'.  Note
>> +  that if the 'clocks' property is given, 'clock-names' is mandatory,
>> +  and the name of the clock is expected to be "pcie".
>> +
>> +- brcm,ssc: boolean that indicates usage of spread-spectrum clocking
> 
> Shouldn't this be a property of the phy? Is there no separate phy to 
> control?

No, the PHY is baked into the PCIe root complex, which is why this is a
property of the root complex node since the two are conflated.

> 
>> +
>> +- brcm,gen: integer that indicates desired forced generation of link: 1 => 2.5
>> +  Gbps, 2 => 5.0 Gbps, 3 => 8.0 Gbps. Will override the auto-negotation if
>> +  specified.
>> +
>> +- <*>-supply: see Documentation/devicetree/bindings/regulator/regulator.txt
>> +
>> +- <*>-supply-names: see Documentation/devicetree/bindings/regulator/regulator.txt
>> +
>> +Example Node:
>> +
>> +This example assumes that the top-level #address-cells = <2> and #size-cells =
>> +<2>, e.g: ARM LPAE configuration.
>> +
>> +	pcie0: pcie-controller at f0460000 {
>> +		reg = <0x0 0xf0460000 0x0 0x9310>;
>> +		interrupts = <0x0 0x33 0x4>, <0x0 0x34, 0x4>;
>                                                       ^
> typo

Whoops, thanks.

> 
>> +		interrupt-names = "pcie", "msi";
>> +		compatible = "brcm,bcm7445-pcie";
>> +		#address-cells = <3>;
>> +		#size-cells = <2>;
>> +
>> +		/* Two non-prefetchable 32-bits memory space, each of 128MB
>> + 		 * with the following mapping:
>> +		 * PCIe address		=> CPU physical address space
>> +		 * 0x00_0000_0000	=> 0x00_C000_0000
>> +		 * 0x00_0800_0000	=> 0x00_C800_0000
>> +		 */
>> +		ranges = <0x02000000 0x00000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x08000000>,
>> +			 <0x02000000 0x00000000 0x08000000 0x00000000 0xc8000000 0x00000000 0x08000000>;
>> +		#interrupt-cells = <1>;
>> +		interrupt-map-mask = <0xf800 0 0 7>;
>> +		interrupt-map = <0 0 0 1 &intc 47 3
>> +				 0 0 0 2 &intc 48 3
>> +				 0 0 0 3 &intc 49 3
>> +				 0 0 0 4 &intc 50 3>;
>> +		clocks = <&pcie0>;
>> +		clock-names = "pcie";
>> +		brcm,ssc;
>> +		brcm,log2-scb-sizes = <0x1e 0x1e 0x1e>;
>> +		vreg-wifi-pwr-supply-names = "vreg-wifi-pwr";
>> +		vreg-wifi-pwr-supply = <&vreg-wifi-pwr>;
> 
> The supply for the PCIE RC is called "vreg-wifi-pwr"? Seems a bit 
> strange.

It can be called anything, this just happens to be the example, but I
can certainly drop that, since a) this is optional and b) we need to
rework that in the driver anyway.
-- 
Florian


From linux at armlinux.org.uk  Mon May  9 16:28:08 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Tue, 10 May 2016 00:28:08 +0100
Subject: FTP mirrors
Message-ID: <20160509232807.GG19428@n2100.arm.linux.org.uk>

Does any one know of a relatively up to date mirror of the ARM
site which was at ftp.arm.linux.org.uk?

It's needed to avoid uploading gigabytes of data over slow UK
DSL links...  All the sites I once knew appear to be dead in one
way or another.

Thanks.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From rjw at rjwysocki.net  Mon May  9 17:02:39 2016
From: rjw at rjwysocki.net (Rafael J. Wysocki)
Date: Tue, 10 May 2016 02:02:39 +0200
Subject: [PATCH v4 1/5] ACPI / processor_idle: introduce
 ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE
In-Reply-To: <1461069013-13292-2-git-send-email-sudeep.holla@arm.com>
References: <1461069013-13292-1-git-send-email-sudeep.holla@arm.com>
 <1461069013-13292-2-git-send-email-sudeep.holla@arm.com>
Message-ID: <5796685.UTMTWTestt@vostro.rjw.lan>

On Tuesday, April 19, 2016 01:30:09 PM Sudeep Holla wrote:
> ACPI 6.0 adds a new method to specify the CPU idle states(C-states)
> called Low Power Idle(LPI) states. Since new architectures like ARM64
> use only LPIs, introduce ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE to
> encapsulate all the code supporting the old style C-states(_CST)
> 
> This patch will help to extend the processor_idle module to support
> LPI.
> 
> Cc: x86 at kernel.org
> Cc: linux-ia64 at vger.kernel.org
> Cc: "Rafael J. Wysocki" <rjw at rjwysocki.net>
> Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
> ---
>  arch/ia64/Kconfig             |  1 +
>  arch/x86/Kconfig              |  1 +
>  drivers/acpi/Kconfig          |  3 ++
>  drivers/acpi/processor_idle.c | 74 +++++++++++++++++++++++++++++--------------
>  include/acpi/processor.h      |  3 +-
>  5 files changed, 57 insertions(+), 25 deletions(-)
> 
> diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
> index b534ebab36ea..717de2a146e2 100644
> --- a/arch/ia64/Kconfig
> +++ b/arch/ia64/Kconfig
> @@ -16,6 +16,7 @@ config IA64
>  	select PCI if (!IA64_HP_SIM)
>  	select ACPI if (!IA64_HP_SIM)
>  	select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
> +	select ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE if ACPI
>  	select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
>  	select HAVE_UNSTABLE_SCHED_CLOCK
>  	select HAVE_IDE
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 2dc18605831f..eb03fd0d63b9 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -37,6 +37,7 @@ config X86
>  	select ARCH_MIGHT_HAVE_ACPI_PDC		if ACPI
>  	select ARCH_MIGHT_HAVE_PC_PARPORT
>  	select ARCH_MIGHT_HAVE_PC_SERIO
> +	select ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE if ACPI
>  	select ARCH_SUPPORTS_ATOMIC_RMW
>  	select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT
>  	select ARCH_SUPPORTS_INT128		if X86_64
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index 82b96ee8624c..ec289078667c 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -48,6 +48,9 @@ config ACPI_LEGACY_TABLES_LOOKUP
>  config ARCH_MIGHT_HAVE_ACPI_PDC
>  	bool
>  
> +config ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE
> +	bool

It might be better to do

config ACPI_PROCESSOR_CST
	bool
	depends on ia64 || x86

Should it depend on ARCH_HAS_POWER_INIT too?


> +
>  config ACPI_GENERIC_GSI
>  	bool
>  
> diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
> index 444e3745c8b3..1f3fe54194b5 100644
> --- a/drivers/acpi/processor_idle.c
> +++ b/drivers/acpi/processor_idle.c
> @@ -59,6 +59,12 @@ module_param(latency_factor, uint, 0644);
>  
>  static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device);
>  
> +struct cpuidle_driver acpi_idle_driver = {
> +	.name =		"acpi_idle",
> +	.owner =	THIS_MODULE,
> +};
> +
> +#ifdef CONFIG_ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE
>  static
>  DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate);
>  
> @@ -804,11 +810,6 @@ static void acpi_idle_enter_freeze(struct cpuidle_device *dev,
>  	acpi_idle_do_entry(cx);
>  }
>  
> -struct cpuidle_driver acpi_idle_driver = {
> -	.name =		"acpi_idle",
> -	.owner =	THIS_MODULE,
> -};
> -
>  /**
>   * acpi_processor_setup_cpuidle_cx - prepares and configures CPUIDLE
>   * device i.e. per-cpu data
> @@ -925,6 +926,49 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
>  	return 0;
>  }
>  
> +static inline void acpi_processor_cstate_first_run_checks(void)
> +{
> +	static int first_run;
> +
> +	if (first_run)
> +		return;
> +	dmi_check_system(processor_power_dmi_table);
> +	max_cstate = acpi_processor_cstate_check(max_cstate);
> +	if (max_cstate < ACPI_C_STATES_MAX)
> +		pr_notice("ACPI: processor limited to max C-state %d\n",
> +			  max_cstate);
> +	first_run++;
> +
> +	if (acpi_gbl_FADT.cst_control && !nocst) {
> +		status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
> +					    acpi_gbl_FADT.cst_control, 8);
> +		if (ACPI_FAILURE(status))
> +			ACPI_EXCEPTION((AE_INFO, status,
> +					"Notifying BIOS of _CST ability failed"));
> +	}
> +}
> +#else
> +
> +static inline int disabled_by_idle_boot_param(void) { return 0; }
> +static inline void acpi_processor_cstate_first_run_checks(void) { }
> +static int acpi_processor_get_power_info(struct acpi_processor *pr)
> +{
> +	return -ENODEV;
> +}
> +
> +static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
> +					   struct cpuidle_device *dev)
> +{
> +	return -EINVAL;
> +}
> +
> +static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
> +{
> +	return -EINVAL;
> +}
> +
> +#endif

Add a comment indicating what #ifdef block ends here?

> +
>  int acpi_processor_hotplug(struct acpi_processor *pr)
>  {
>  	int ret = 0;
> @@ -1018,29 +1062,11 @@ int acpi_processor_power_init(struct acpi_processor *pr)
>  	acpi_status status;
>  	int retval;
>  	struct cpuidle_device *dev;
> -	static int first_run;
>  
>  	if (disabled_by_idle_boot_param())
>  		return 0;
>  
> -	if (!first_run) {
> -		dmi_check_system(processor_power_dmi_table);
> -		max_cstate = acpi_processor_cstate_check(max_cstate);
> -		if (max_cstate < ACPI_C_STATES_MAX)
> -			printk(KERN_NOTICE
> -			       "ACPI: processor limited to max C-state %d\n",
> -			       max_cstate);
> -		first_run++;
> -	}
> -
> -	if (acpi_gbl_FADT.cst_control && !nocst) {
> -		status =
> -		    acpi_os_write_port(acpi_gbl_FADT.smi_command, acpi_gbl_FADT.cst_control, 8);
> -		if (ACPI_FAILURE(status)) {
> -			ACPI_EXCEPTION((AE_INFO, status,
> -					"Notifying BIOS of _CST ability failed"));
> -		}
> -	}
> +	acpi_processor_cstate_first_run_checks();
>  
>  	acpi_processor_get_power_info(pr);
>  	pr->flags.power_setup_done = 1;
> diff --git a/include/acpi/processor.h b/include/acpi/processor.h
> index 6f1805dd5d3c..50f2423d31fa 100644
> --- a/include/acpi/processor.h
> +++ b/include/acpi/processor.h
> @@ -242,7 +242,8 @@ extern int acpi_processor_get_performance_info(struct acpi_processor *pr);
>  DECLARE_PER_CPU(struct acpi_processor *, processors);
>  extern struct acpi_processor_errata errata;
>  
> -#ifdef ARCH_HAS_POWER_INIT
> +#if defined(ARCH_HAS_POWER_INIT) && \
> +	defined(CONFIG_ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE)
>  void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
>  					unsigned int cpu);
>  int acpi_processor_ffh_cstate_probe(unsigned int cpu,
> 



From rjw at rjwysocki.net  Mon May  9 17:04:41 2016
From: rjw at rjwysocki.net (Rafael J. Wysocki)
Date: Tue, 10 May 2016 02:04:41 +0200
Subject: [PATCH v4 2/5] ACPI / processor_idle: Add support for Low Power
 Idle(LPI) states
In-Reply-To: <1461069013-13292-3-git-send-email-sudeep.holla@arm.com>
References: <1461069013-13292-1-git-send-email-sudeep.holla@arm.com>
 <1461069013-13292-3-git-send-email-sudeep.holla@arm.com>
Message-ID: <3339348.mi5ytyqrb0@vostro.rjw.lan>

On Tuesday, April 19, 2016 01:30:10 PM Sudeep Holla wrote:
> ACPI 6.0 introduced an optional object _LPI that provides an alternate
> method to describe Low Power Idle states. It defines the local power
> states for each node in a hierarchical processor topology. The OSPM can
> use _LPI object to select a local power state for each level of processor
> hierarchy in the system. They used to produce a composite power state
> request that is presented to the platform by the OSPM.
> 
> Since multiple processors affect the idle state for any non-leaf hierarchy
> node, coordination of idle state requests between the processors is
> required. ACPI supports two different coordination schemes: Platform
> coordinated and  OS initiated.
> 
> This patch adds initial support for Platform coordination scheme of LPI.
> 
> Cc: "Rafael J. Wysocki" <rjw at rjwysocki.net>
> Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
> ---
>  drivers/acpi/bus.c              |  11 +-
>  drivers/acpi/processor_driver.c |   2 +-
>  drivers/acpi/processor_idle.c   | 441 +++++++++++++++++++++++++++++++++++-----
>  include/acpi/processor.h        |  25 ++-
>  include/linux/acpi.h            |   4 +
>  5 files changed, 422 insertions(+), 61 deletions(-)
> 
> Hi Rafael,
> 
> Yet to be discussed(retained as in from previous version):

I somehow didn't realize that you had been waiting for my feedback.  Sorry
about that.

> - Kconfig entry removal: Need feedback on how to deal with that
>   without having to introduce dummy _CST related ARM64 callbacks
> - Didn't defer processing of LPI buffers to flattening as it
>   results in the same buffer decoded multiple times
> - ACPI_CSTATE_INTEGER : IMO it's reasonable to keep it aroundsince the
>   it's part of LPI specification(not just ARM FFH)

OK, I'll have a look tomorrow.

Thanks,
Rafael



From horms at verge.net.au  Mon May  9 17:03:48 2016
From: horms at verge.net.au (Simon Horman)
Date: Tue, 10 May 2016 09:03:48 +0900
Subject: [GIT PULL] Renesas ARM64 Based SoC DT PM Domain Updates for v4.7
In-Reply-To: <41128314.QPDQXbTtHX@wuerfel>
References: <cover.1461730364.git.horms+renesas@verge.net.au>
 <20160506002125.GE24999@verge.net.au> <41128314.QPDQXbTtHX@wuerfel>
Message-ID: <20160510000348.GC4530@verge.net.au>

On Mon, May 09, 2016 at 03:10:40PM +0200, Arnd Bergmann wrote:
> On Friday 06 May 2016 09:21:25 Simon Horman wrote:
> > Hi,
> > 
> > On Wed, Apr 27, 2016 at 02:20:10PM +1000, Simon Horman wrote:
> > > Hi Olof, Hi Kevin, Hi Arnd,
> > > 
> > > Please consider these Renesas ARM64 based SoC DT PM Domain updates for v4.7.
> > > 
> > > This pull requests is based on a merge of:
> > > 
> > > * "[GIT PULL] Second Round of Renesas ARM Based SoC R-Car SYSC Updates for
> > >   v4.7", tagged as renesas-rcar-sysc2-for-v4.7, which you have already
> > >   pulled
> > > * "[GIT PULL] Second Round of Renesas ARM64 Based SoC DT Updates for v4.7",
> > >   tagged as renesas-arm64-dt2-for-v4.7, which I have sent a pull request
> > >   for.
> > > 
> > > The reason for the somewhat tedious base on
> > > renesas-rcar-sysc2-for-v4.7, which provides driver changes,
> > > is a hard run-time dependency.
> > > 
> > > I also have a similar set of changes for ARM (32-bit) which I will send
> > > separately.
> > 
> > I am wondering if this pull-request might have slipped through the cracks.
> > 
> > FWIW, all other pull requests I have submitted for v4.7 have been pulled
> > (thanks!) including a similar pull-request for ARM (32-bit) which is
> > present in the next/late branch of the arm-soc tree.
> > 
> > I do not plan to send any more non-fix pull requests for v4.7.
> > And at this stage I am not aware of any fixes for v4.7.
> > 
> 
> Indeed it did, thanks for the reminder! I've put it on my stack now
> and should start doing merges later today when I'm through my mail.

Great, thanks! I see that it has now been pulled.


From isubramanian at apm.com  Mon May  9 17:04:10 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Mon,  9 May 2016 17:04:10 -0700
Subject: [PATCH 0/6] drivers: net: xgene: Bug fixes
Message-ID: <1462838656-22043-1-git-send-email-isubramanian@apm.com>

This patch set addresses the following bug fixes that were found during testing.

  1. IPv4 forward test crash
    - drivers: net: xgene: fix IPv4 forward crash

  2. Sharing of irqs
    - drivers: net: xgene: fix sharing of irqs

  3. Ununiform latency across queues
    - drivers: net: xgene: fix ununiform latency across queues

  4. Fix statistics counters race condition
    - drivers: net: xgene: fix statistics counters race condition

  5. TSO data corruption
    - drivers: net: xgene: Using static MSS values

  6. Correcting register offset and field lengths
    - drivers: net: xgene: fix register offset

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
---

Iyappan Subramanian (6):
  drivers: net: xgene: fix IPv4 forward crash
  drivers: net: xgene: fix sharing of irqs
  drivers: net: xgene: fix ununiform latency across queues
  drivers: net: xgene: fix statistics counters race condition
  drivers: net: xgene: Using static MSS values
  drivers: net: xgene: fix register offset

 drivers/net/ethernet/apm/xgene/xgene_enet_cle.c   |  11 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_cle.h   |   2 +
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    |  19 ++--
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    |  10 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 118 ++++++++++++++++++----
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |  24 +++--
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h |   2 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c |  20 +++-
 8 files changed, 159 insertions(+), 47 deletions(-)

-- 
1.9.1



From isubramanian at apm.com  Mon May  9 17:04:11 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Mon,  9 May 2016 17:04:11 -0700
Subject: [PATCH 1/6] drivers: net: xgene: fix IPv4 forward crash
In-Reply-To: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
References: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
Message-ID: <1462838656-22043-2-git-send-email-isubramanian@apm.com>

This patch fixes the crash observed during IPv4 forward test by
setting the drop field in the dbptr.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_cle.c | 11 ++++++-----
 drivers/net/ethernet/apm/xgene/xgene_enet_cle.h |  2 ++
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
index 6479288..472c0fb 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
@@ -43,6 +43,7 @@ static void xgene_cle_idt_to_hw(u32 dstqid, u32 fpsel,
 static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata,
 				  struct xgene_cle_dbptr *dbptr, u32 *buf)
 {
+	buf[0] = SET_VAL(CLE_DROP, dbptr->drop);
 	buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) |
 		 SET_VAL(CLE_DSTQIDL, dbptr->dstqid);
 
@@ -412,7 +413,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 			.branch = {
 				{
 					/* IPV4 */
-					.valid = 0,
+					.valid = 1,
 					.next_packet_pointer = 22,
 					.jump_bw = JMP_FW,
 					.jump_rel = JMP_ABS,
@@ -420,7 +421,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 					.next_node = PKT_PROT_NODE,
 					.next_branch = 0,
 					.data = 0x8,
-					.mask = 0xffff
+					.mask = 0x0
 				},
 				{
 					.valid = 0,
@@ -456,7 +457,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 					.next_node = RSS_IPV4_TCP_NODE,
 					.next_branch = 0,
 					.data = 0x0600,
-					.mask = 0xffff
+					.mask = 0x00ff
 				},
 				{
 					/* UDP */
@@ -468,7 +469,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 					.next_node = RSS_IPV4_UDP_NODE,
 					.next_branch = 0,
 					.data = 0x1100,
-					.mask = 0xffff
+					.mask = 0x00ff
 				},
 				{
 					.valid = 0,
@@ -642,7 +643,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 				{
 					/* TCP DST Port */
 					.valid = 0,
-					.next_packet_pointer = 256,
+					.next_packet_pointer = 258,
 					.jump_bw = JMP_FW,
 					.jump_rel = JMP_ABS,
 					.operation = EQT,
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
index 13e829a..33c5f6b 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
@@ -83,6 +83,8 @@
 #define CLE_TYPE_POS		0
 #define CLE_TYPE_LEN		2
 
+#define CLE_DROP_POS		28
+#define CLE_DROP_LEN		1
 #define CLE_DSTQIDL_POS		25
 #define CLE_DSTQIDL_LEN		7
 #define CLE_DSTQIDH_POS		0
-- 
1.9.1



From isubramanian at apm.com  Mon May  9 17:04:12 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Mon,  9 May 2016 17:04:12 -0700
Subject: [PATCH 2/6] drivers: net: xgene: fix sharing of irqs
In-Reply-To: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
References: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
Message-ID: <1462838656-22043-3-git-send-email-isubramanian@apm.com>

Since hardware doesn't allow sharing of interrupts,
this patch fixes the same by removing IRQF_SHARED flag.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index aa87049..ed90664 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -630,7 +630,7 @@ static int xgene_enet_register_irq(struct net_device *ndev)
 		ring = pdata->rx_ring[i];
 		irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
 		ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
-				       IRQF_SHARED, ring->irq_name, ring);
+				       0, ring->irq_name, ring);
 		if (ret) {
 			netdev_err(ndev, "Failed to request irq %s\n",
 				   ring->irq_name);
@@ -641,7 +641,7 @@ static int xgene_enet_register_irq(struct net_device *ndev)
 		ring = pdata->tx_ring[i]->cp_ring;
 		irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
 		ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
-				       IRQF_SHARED, ring->irq_name, ring);
+				       0, ring->irq_name, ring);
 		if (ret) {
 			netdev_err(ndev, "Failed to request irq %s\n",
 				   ring->irq_name);
-- 
1.9.1



From isubramanian at apm.com  Mon May  9 17:04:13 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Mon,  9 May 2016 17:04:13 -0700
Subject: [PATCH 3/6] drivers: net: xgene: fix ununiform latency across queues
In-Reply-To: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
References: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
Message-ID: <1462838656-22043-4-git-send-email-isubramanian@apm.com>

This patch addresses ununiform latency across queues by adding
more queues to match with, upto number of CPU cores.

Also, number of interrupts are increased and the channel numbers
are reordered.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 30 ++++++++++++++++++------
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h |  8 +++----
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index ed90664..e75d1a9 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1247,6 +1247,13 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata)
 	for (i = 0; i < max_irqs; i++) {
 		ret = platform_get_irq(pdev, i);
 		if (ret <= 0) {
+			if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
+				max_irqs = i;
+				pdata->rxq_cnt = max_irqs / 2;
+				pdata->txq_cnt = max_irqs / 2;
+				pdata->cq_cnt = max_irqs / 2;
+				break;
+			}
 			dev_err(dev, "Unable to get ENET IRQ\n");
 			ret = ret ? : -ENXIO;
 			return ret;
@@ -1450,19 +1457,28 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
 		pdata->port_ops = &xgene_xgport_ops;
 		pdata->cle_ops = &xgene_cle3in_ops;
 		pdata->rm = RM0;
-		pdata->rxq_cnt = XGENE_NUM_RX_RING;
-		pdata->txq_cnt = XGENE_NUM_TX_RING;
-		pdata->cq_cnt = XGENE_NUM_TXC_RING;
+		if (!pdata->rxq_cnt) {
+			pdata->rxq_cnt = XGENE_NUM_RX_RING;
+			pdata->txq_cnt = XGENE_NUM_TX_RING;
+			pdata->cq_cnt = XGENE_NUM_TXC_RING;
+		}
 		break;
 	}
 
 	if (pdata->enet_id == XGENE_ENET1) {
 		switch (pdata->port_id) {
 		case 0:
-			pdata->cpu_bufnum = START_CPU_BUFNUM_0;
-			pdata->eth_bufnum = START_ETH_BUFNUM_0;
-			pdata->bp_bufnum = START_BP_BUFNUM_0;
-			pdata->ring_num = START_RING_NUM_0;
+			if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
+				pdata->cpu_bufnum = X2_START_CPU_BUFNUM_0;
+				pdata->eth_bufnum = X2_START_ETH_BUFNUM_0;
+				pdata->bp_bufnum = X2_START_BP_BUFNUM_0;
+				pdata->ring_num = START_RING_NUM_0;
+			} else {
+				pdata->cpu_bufnum = START_CPU_BUFNUM_0;
+				pdata->eth_bufnum = START_ETH_BUFNUM_0;
+				pdata->bp_bufnum = START_BP_BUFNUM_0;
+				pdata->ring_num = START_RING_NUM_0;
+			}
 			break;
 		case 1:
 			if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 0a2887b..cc40c30 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -49,10 +49,10 @@
 #define XGENE_ENET_MSS	1448
 #define XGENE_MIN_ENET_FRAME_SIZE	60
 
-#define XGENE_MAX_ENET_IRQ	8
-#define XGENE_NUM_RX_RING	4
-#define XGENE_NUM_TX_RING	4
-#define XGENE_NUM_TXC_RING	4
+#define XGENE_MAX_ENET_IRQ	16
+#define XGENE_NUM_RX_RING	8
+#define XGENE_NUM_TX_RING	8
+#define XGENE_NUM_TXC_RING	8
 
 #define START_CPU_BUFNUM_0	0
 #define START_ETH_BUFNUM_0	2
-- 
1.9.1



From isubramanian at apm.com  Mon May  9 17:04:14 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Mon,  9 May 2016 17:04:14 -0700
Subject: [PATCH 4/6] drivers: net: xgene: fix statistics counters race
 condition
In-Reply-To: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
References: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
Message-ID: <1462838656-22043-5-git-send-email-isubramanian@apm.com>

This patch fixes the race condition on updating the statistics
counters by moving the counters to the ring structure.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c   | 17 +++++++----
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h   |  2 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 39 ++++++++++++++++++------
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 10 ++++++
 4 files changed, 52 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 457f745..0050878 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -223,23 +223,28 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
 
 	switch (status) {
 	case INGRESS_CRC:
-		stats->rx_crc_errors++;
+		ring->rx_crc_errors++;
+		ring->rx_dropped++;
 		break;
 	case INGRESS_CHECKSUM:
 	case INGRESS_CHECKSUM_COMPUTE:
-		stats->rx_errors++;
+		ring->rx_errors++;
+		ring->rx_dropped++;
 		break;
 	case INGRESS_TRUNC_FRAME:
-		stats->rx_frame_errors++;
+		ring->rx_frame_errors++;
+		ring->rx_dropped++;
 		break;
 	case INGRESS_PKT_LEN:
-		stats->rx_length_errors++;
+		ring->rx_length_errors++;
+		ring->rx_dropped++;
 		break;
 	case INGRESS_PKT_UNDER:
-		stats->rx_frame_errors++;
+		ring->rx_frame_errors++;
+		ring->rx_dropped++;
 		break;
 	case INGRESS_FIFO_OVERRUN:
-		stats->rx_fifo_errors++;
+		ring->rx_fifo_errors++;
 		break;
 	default:
 		break;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index ba7da98..ecfeffe 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -201,6 +201,8 @@ enum xgene_enet_rm {
 #define USERINFO_LEN			32
 #define FPQNUM_POS			32
 #define FPQNUM_LEN			12
+#define ELERR_POS                       46
+#define ELERR_LEN                       2
 #define NV_POS				50
 #define NV_LEN				1
 #define LL_POS				51
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index e75d1a9..d992ae8 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -443,8 +443,8 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
 
 	skb_tx_timestamp(skb);
 
-	pdata->stats.tx_packets++;
-	pdata->stats.tx_bytes += skb->len;
+	tx_ring->tx_packets++;
+	tx_ring->tx_bytes += skb->len;
 
 	pdata->ring_ops->wr_cmd(tx_ring, count);
 	return NETDEV_TX_OK;
@@ -483,12 +483,12 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
 	skb = buf_pool->rx_skb[skb_index];
 
 	/* checking for error */
-	status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
+	status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) ||
+		  GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
 	if (unlikely(status > 2)) {
 		dev_kfree_skb_any(skb);
 		xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
 				       status);
-		pdata->stats.rx_dropped++;
 		ret = -EIO;
 		goto out;
 	}
@@ -506,8 +506,8 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
 		xgene_enet_skip_csum(skb);
 	}
 
-	pdata->stats.rx_packets++;
-	pdata->stats.rx_bytes += datalen;
+	rx_ring->rx_packets++;
+	rx_ring->rx_bytes += datalen;
 	napi_gro_receive(&rx_ring->napi, skb);
 out:
 	if (--rx_ring->nbufpool == 0) {
@@ -1127,11 +1127,30 @@ static struct rtnl_link_stats64 *xgene_enet_get_stats64(
 {
 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
 	struct rtnl_link_stats64 *stats = &pdata->stats;
+	struct xgene_enet_desc_ring *ring;
+	int i;
+
+	memset(stats, 0, sizeof(struct rtnl_link_stats64));
+	for (i = 0; i < pdata->txq_cnt; i++) {
+		ring = pdata->tx_ring[i];
+		if (ring) {
+			stats->tx_packets += ring->tx_packets;
+			stats->tx_bytes += ring->tx_bytes;
+		}
+	}
 
-	stats->rx_errors += stats->rx_length_errors +
-			    stats->rx_crc_errors +
-			    stats->rx_frame_errors +
-			    stats->rx_fifo_errors;
+	for (i = 0; i < pdata->rxq_cnt; i++) {
+		ring = pdata->rx_ring[i];
+		if (ring) {
+			stats->rx_packets += ring->rx_packets;
+			stats->rx_bytes += ring->rx_bytes;
+			stats->rx_errors += ring->rx_length_errors +
+				ring->rx_crc_errors +
+				ring->rx_frame_errors +
+				ring->rx_fifo_errors;
+			stats->rx_dropped += ring->rx_dropped;
+		}
+	}
 	memcpy(storage, &pdata->stats, sizeof(struct rtnl_link_stats64));
 
 	return storage;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index cc40c30..092fbec 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -121,6 +121,16 @@ struct xgene_enet_desc_ring {
 		struct xgene_enet_raw_desc16 *raw_desc16;
 	};
 	__le64 *exp_bufs;
+	u64 tx_packets;
+	u64 tx_bytes;
+	u64 rx_packets;
+	u64 rx_bytes;
+	u64 rx_dropped;
+	u64 rx_errors;
+	u64 rx_length_errors;
+	u64 rx_crc_errors;
+	u64 rx_frame_errors;
+	u64 rx_fifo_errors;
 };
 
 struct xgene_mac_ops {
-- 
1.9.1



From isubramanian at apm.com  Mon May  9 17:04:15 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Mon,  9 May 2016 17:04:15 -0700
Subject: [PATCH 5/6] drivers: net: xgene: Using static MSS values
In-Reply-To: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
References: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
Message-ID: <1462838656-22043-6-git-send-email-isubramanian@apm.com>

Due to the nature of hardware design for TSO, if the MSS values that are
stored in the register, changes during TSO operation, data corruption may
occur.

This patch fixes the issue by using one of the predefined MSS values.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    |  2 -
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    |  2 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 45 ++++++++++++++++++++++-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |  6 +--
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 20 ++++++++--
 5 files changed, 66 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 0050878..2f5638f 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -219,8 +219,6 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
 			    struct xgene_enet_pdata *pdata,
 			    enum xgene_enet_err_code status)
 {
-	struct rtnl_link_stats64 *stats = &pdata->stats;
-
 	switch (status) {
 	case INGRESS_CRC:
 		ring->rx_crc_errors++;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index ecfeffe..a3c12dc 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -227,6 +227,8 @@ enum xgene_enet_rm {
 #define TCPHDR_LEN			6
 #define IPHDR_POS			6
 #define IPHDR_LEN			6
+#define MSS_POS				20
+#define MSS_LEN				2
 #define EC_POS				22	/* Enable checksum */
 #define EC_LEN				1
 #define ET_POS				23	/* Enable TSO */
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index d992ae8..af272cb 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -179,6 +179,46 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
 	return ret;
 }
 
+static void apm_enet_init_mss_values(struct net_device *ndev)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	int i;
+
+	pdata->mss_sw[0] = 64;
+	pdata->mss_sw[1] = 1024;
+	pdata->mss_sw[2] = 1400;
+	pdata->mss_sw[3] = 1446;
+
+	for (i = 0; i < NUM_MSS_REG; i++)
+		pdata->mac_ops->set_mss(pdata, pdata->mss_sw[i], i);
+}
+
+static int apm_enet_get_mss_index(struct net_device *ndev, u32 new_mss)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	int i;
+
+	for (i = NUM_MSS_REG - 1; i >= 0; i--) {
+		if (new_mss >= pdata->mss_sw[i])
+			return i;
+	}
+
+	return -1;
+}
+
+static int xgene_enet_setup_mss(struct net_device *ndev, u64 *hopinfo, u32 mss)
+{
+	int mss_index;
+
+	mss_index = apm_enet_get_mss_index(ndev, mss);
+	if (mss_index < 0)
+		return mss_index;
+
+	*hopinfo |= SET_VAL(MSS, mss_index);
+
+	return 0;
+}
+
 static u64 xgene_enet_work_msg(struct sk_buff *skb)
 {
 	struct net_device *ndev = skb->dev;
@@ -227,6 +267,9 @@ static u64 xgene_enet_work_msg(struct sk_buff *skb)
 			if (!mss || ((skb->len - hdr_len) <= mss))
 				goto out;
 
+			if (xgene_enet_setup_mss(ndev, &hopinfo, mss))
+				return 0;
+
 			hopinfo |= SET_BIT(ET);
 		}
 	} else if (iph->protocol == IPPROTO_UDP) {
@@ -1625,7 +1668,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
 
 	if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
 		ndev->features |= NETIF_F_TSO;
-		pdata->mss = XGENE_ENET_MSS;
+		apm_enet_init_mss_values(ndev);
 	}
 	ndev->hw_features = ndev->features;
 
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 092fbec..20a8b59 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -46,7 +46,7 @@
 #define NUM_PKT_BUF	64
 #define NUM_BUFPOOL	32
 #define MAX_EXP_BUFFS	256
-#define XGENE_ENET_MSS	1448
+#define NUM_MSS_REG	4
 #define XGENE_MIN_ENET_FRAME_SIZE	60
 
 #define XGENE_MAX_ENET_IRQ	16
@@ -141,7 +141,7 @@ struct xgene_mac_ops {
 	void (*tx_disable)(struct xgene_enet_pdata *pdata);
 	void (*rx_disable)(struct xgene_enet_pdata *pdata);
 	void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
-	void (*set_mss)(struct xgene_enet_pdata *pdata);
+	void (*set_mss)(struct xgene_enet_pdata *pdata, u16 mss, u8 index);
 	void (*link_state)(struct work_struct *work);
 };
 
@@ -208,7 +208,7 @@ struct xgene_enet_pdata {
 	u8 eth_bufnum;
 	u8 bp_bufnum;
 	u16 ring_num;
-	u32 mss;
+	u32 mss_sw[NUM_MSS_REG];
 	u8 tx_delay;
 	u8 rx_delay;
 };
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index ba030dc..cb9f681 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -184,9 +184,24 @@ static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata)
 	xgene_enet_wr_mac(pdata, HSTMACADR_MSW_ADDR, addr1);
 }
 
-static void xgene_xgmac_set_mss(struct xgene_enet_pdata *pdata)
+static void xgene_xgmac_set_mss(struct xgene_enet_pdata *pdata, u16 mss,
+				u8 index)
 {
-	xgene_enet_wr_csr(pdata, XG_TSIF_MSS_REG0_ADDR, pdata->mss);
+	bool reg_index;
+	u32 data;
+
+	xgene_enet_rd_csr(pdata, XG_TSIF_MSS_REG0_ADDR, &data);
+	reg_index = (index < 2) ? 0 : 1;
+
+	if (!(index & 0x1)) {
+		data &= 0xffff0000;
+		data |= mss;
+	} else {
+		data &= 0xffff;
+		data |= (mss << 16);
+	}
+
+	xgene_enet_wr_csr(pdata, XG_TSIF_MSS_REG0_ADDR + reg_index * 4, data);
 }
 
 static u32 xgene_enet_link_status(struct xgene_enet_pdata *pdata)
@@ -210,7 +225,6 @@ static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
 	xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
 
 	xgene_xgmac_set_mac_addr(pdata);
-	xgene_xgmac_set_mss(pdata);
 
 	xgene_enet_rd_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, &data);
 	data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
-- 
1.9.1



From isubramanian at apm.com  Mon May  9 17:04:16 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Mon,  9 May 2016 17:04:16 -0700
Subject: [PATCH 6/6] drivers: net: xgene: fix register offset
In-Reply-To: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
References: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
Message-ID: <1462838656-22043-7-git-send-email-isubramanian@apm.com>

This patch fixes SG_RX_DV_GATE_REG_0_ADDR register offset
and ring state field lengths.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    | 6 +++---
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index a3c12dc..a4a1d3e 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -86,7 +86,7 @@ enum xgene_enet_rm {
 #define RINGADDRL_POS		5
 #define RINGADDRL_LEN		27
 #define RINGADDRH_POS		0
-#define RINGADDRH_LEN		6
+#define RINGADDRH_LEN		7
 #define RINGSIZE_POS		23
 #define RINGSIZE_LEN		3
 #define RINGTYPE_POS		19
@@ -94,9 +94,9 @@ enum xgene_enet_rm {
 #define RINGMODE_POS		20
 #define RINGMODE_LEN		3
 #define RECOMTIMEOUTL_POS	28
-#define RECOMTIMEOUTL_LEN	3
+#define RECOMTIMEOUTL_LEN	4
 #define RECOMTIMEOUTH_POS	0
-#define RECOMTIMEOUTH_LEN	2
+#define RECOMTIMEOUTH_LEN	3
 #define NUMMSGSINQ_POS		1
 #define NUMMSGSINQ_LEN		16
 #define ACCEPTLERR		BIT(19)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
index 29a71b4..002df5a 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
@@ -33,7 +33,7 @@
 #define LINK_STATUS			BIT(2)
 #define LINK_UP				BIT(15)
 #define MPA_IDLE_WITH_QMI_EMPTY		BIT(12)
-#define SG_RX_DV_GATE_REG_0_ADDR	0x0dfc
+#define SG_RX_DV_GATE_REG_0_ADDR	0x05fc
 
 extern const struct xgene_mac_ops xgene_sgmac_ops;
 extern const struct xgene_port_ops xgene_sgport_ops;
-- 
1.9.1



From horms+renesas at verge.net.au  Mon May  9 17:14:24 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Tue, 10 May 2016 09:14:24 +0900
Subject: [PATCH] mmc: sdhci-st: correct name of sd-uhs-sdr50 property
Message-ID: <1462839264-13300-1-git-send-email-horms+renesas@verge.net.au>

Correct what appears to be a typo in the name of the sd-uhs-sdr50.

Also fix mixed tab/space indentation.

Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
---
 Documentation/devicetree/bindings/mmc/sdhci-st.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-st.txt b/Documentation/devicetree/bindings/mmc/sdhci-st.txt
index 18d950df2749..88faa91125bf 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-st.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-st.txt
@@ -38,7 +38,7 @@ Optional properties:
 - bus-width:		Number of data lines.
 			See:  Documentation/devicetree/bindings/mmc/mmc.txt.
 
-- max-frequency: 	Can be 200MHz, 100Mz or 50MHz (default) and used for
+- max-frequency:	Can be 200MHz, 100Mz or 50MHz (default) and used for
 			configuring the CCONFIG3 in the mmcss.
 			See:  Documentation/devicetree/bindings/mmc/mmc.txt.
 
@@ -48,7 +48,7 @@ Optional properties:
 - vqmmc-supply:		Phandle to the regulator dt node, mentioned as the vcc/vdd
 			supply in eMMC/SD specs.
 
-- sd-uhs--sdr50:	To enable the SDR50 in the mmcss.
+- sd-uhs-sdr50:	To enable the SDR50 in the mmcss.
 			See:  Documentation/devicetree/bindings/mmc/mmc.txt.
 
 - sd-uhs-sdr104:	To enable the SDR104 in the mmcss.
-- 
2.1.4



From sfr at canb.auug.org.au  Mon May  9 17:18:45 2016
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Tue, 10 May 2016 10:18:45 +1000
Subject: linux-next: manual merge of the net-next tree with the arm-soc tree
Message-ID: <20160510101845.380ff1b2@canb.auug.org.au>

Hi all,

Today's linux-next merge of the net-next tree got a conflict in:

  include/linux/soc/qcom/smd.h

between commit:

  b853cb9628bf ("soc: qcom: smd: Make callback pass channel reference")

from the arm-soc tree and commit:

  43315f31adc2 ("soc: qcom: smd: Introduce compile stubs")

from the net-next tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

I wasn't sure if the new functions introduced by b853cb9628bf also
needed compile stubs.
-- 
Cheers,
Stephen Rothwell

diff --cc include/linux/soc/qcom/smd.h
index cb2f81559bc0,46a984f5e3a3..000000000000
--- a/include/linux/soc/qcom/smd.h
+++ b/include/linux/soc/qcom/smd.h
@@@ -44,23 -42,42 +44,49 @@@ struct qcom_smd_driver 
  
  	int (*probe)(struct qcom_smd_device *dev);
  	void (*remove)(struct qcom_smd_device *dev);
 -	int (*callback)(struct qcom_smd_device *, const void *, size_t);
 +	qcom_smd_cb_t callback;
  };
  
+ #if IS_ENABLED(CONFIG_QCOM_SMD)
+ 
  int qcom_smd_driver_register(struct qcom_smd_driver *drv);
  void qcom_smd_driver_unregister(struct qcom_smd_driver *drv);
  
 +void *qcom_smd_get_drvdata(struct qcom_smd_channel *channel);
 +void qcom_smd_set_drvdata(struct qcom_smd_channel *channel, void *data);
 +
+ int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len);
+ 
+ #else
+ 
+ static inline int qcom_smd_driver_register(struct qcom_smd_driver *drv)
+ {
+ 	return -ENXIO;
+ }
+ 
+ static inline void qcom_smd_driver_unregister(struct qcom_smd_driver *drv)
+ {
+ 	/* This shouldn't be possible */
+ 	WARN_ON(1);
+ }
+ 
+ static inline int qcom_smd_send(struct qcom_smd_channel *channel,
+ 				const void *data, int len)
+ {
+ 	/* This shouldn't be possible */
+ 	WARN_ON(1);
+ 	return -ENXIO;
+ }
+ 
+ #endif
+ 
  #define module_qcom_smd_driver(__smd_driver) \
  	module_driver(__smd_driver, qcom_smd_driver_register, \
  		      qcom_smd_driver_unregister)
  
- int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len);
  
 +struct qcom_smd_channel *qcom_smd_open_channel(struct qcom_smd_channel *channel,
 +					       const char *name,
 +					       qcom_smd_cb_t cb);
 +
  #endif


From eric at anholt.net  Mon May  9 18:01:28 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon,  9 May 2016 18:01:28 -0700
Subject: [PATCH 1/3 v2] clk: bcm2835: Mark the VPU clock as critical
In-Reply-To: <1462842090-2017-1-git-send-email-eric@anholt.net>
References: <1462842090-2017-1-git-send-email-eric@anholt.net>
Message-ID: <1462842090-2017-2-git-send-email-eric@anholt.net>

The VPU clock is also the clock for our AXI bus, so we really can't
disable it.  This might have happened during boot if, for example,
uart1 (aux_uart clock) probed and was then disabled before the other
consumers of the VPU clock had probed.

Signed-off-by: Eric Anholt <eric at anholt.net>
---

v2: Rewrite to use a .flags in bcm2835_clock_data, since other clocks
    will need this too.

 drivers/clk/bcm/clk-bcm2835.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 7a7970865c2d..d9db03cb3fd8 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -443,6 +443,8 @@ struct bcm2835_clock_data {
 	/* Number of fractional bits in the divider */
 	u32 frac_bits;
 
+	u32 flags;
+
 	bool is_vpu_clock;
 	bool is_mash_clock;
 };
@@ -1230,7 +1232,7 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
 	init.parent_names = parents;
 	init.num_parents = data->num_mux_parents;
 	init.name = data->name;
-	init.flags = CLK_IGNORE_UNUSED;
+	init.flags = data->flags | CLK_IGNORE_UNUSED;
 
 	if (data->is_vpu_clock) {
 		init.ops = &bcm2835_vpu_clock_clk_ops;
@@ -1649,6 +1651,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
 		.div_reg = CM_VPUDIV,
 		.int_bits = 12,
 		.frac_bits = 8,
+		.flags = CLK_IS_CRITICAL,
 		.is_vpu_clock = true),
 
 	/* clocks with per parent mux */
-- 
2.8.0.rc3



From eric at anholt.net  Mon May  9 18:01:27 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon,  9 May 2016 18:01:27 -0700
Subject: [PATCH 0/3] clk: bcm2835: critical clocks and parent selection
Message-ID: <1462842090-2017-1-git-send-email-eric@anholt.net>

With the new patch 2 inserted between my previous pair, I think this
should cover Martin's bugs with clock disabling.

I tested patch 2 to be important on the downstream kernel: with the
DPI panel support added there, I was losing ethernet (my only I/O)
when the HDMI HSM hanging off of PLLD_PER got disabled due to
EPROBE_DEFER.

Eric Anholt (3):
  clk: bcm2835: Mark the VPU clock as critical
  clk: bcm2835: Mark GPIO clocks enabled at boot as critical.
  clk: bcm2835: Skip PLLC clocks when deciding on a new clock parent

 drivers/clk/bcm/clk-bcm2835.c | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

-- 
2.8.0.rc3



From eric at anholt.net  Mon May  9 18:01:30 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon,  9 May 2016 18:01:30 -0700
Subject: [PATCH 3/3] clk: bcm2835: Skip PLLC clocks when deciding on a new
 clock parent
In-Reply-To: <1462842090-2017-1-git-send-email-eric@anholt.net>
References: <1462842090-2017-1-git-send-email-eric@anholt.net>
Message-ID: <1462842090-2017-4-git-send-email-eric@anholt.net>

If the firmware had set up a clock to source from PLLC, go along with
it.  But if we're looking for a new parent, we don't want to switch it
to PLLC because the firmware will force PLLC (and thus the AXI bus
clock) to different frequencies during over-temp/under-voltage,
without notification to Linux.

On my system, this moves the Linux-enabled HDMI state machine and DSI1
escape clock over to plld_per from pllc_per.  EMMC still ends up on
pllc_per, because the firmware had set it up to use that.

Signed-off-by: Eric Anholt <eric at anholt.net>
Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks")
---

No changes, just a resend.

 drivers/clk/bcm/clk-bcm2835.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 1091012ecec6..1d8f29ea9f69 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1008,16 +1008,28 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw,
 	return 0;
 }
 
+static bool
+bcm2835_clk_is_pllc(struct clk_hw *hw)
+{
+	if (!hw)
+		return false;
+
+	return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0;
+}
+
 static int bcm2835_clock_determine_rate(struct clk_hw *hw,
 					struct clk_rate_request *req)
 {
 	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 	struct clk_hw *parent, *best_parent = NULL;
+	bool current_parent_is_pllc;
 	unsigned long rate, best_rate = 0;
 	unsigned long prate, best_prate = 0;
 	size_t i;
 	u32 div;
 
+	current_parent_is_pllc = bcm2835_clk_is_pllc(clk_hw_get_parent(hw));
+
 	/*
 	 * Select parent clock that results in the closest but lower rate
 	 */
@@ -1025,6 +1037,17 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
 		parent = clk_hw_get_parent_by_index(hw, i);
 		if (!parent)
 			continue;
+
+		/*
+		 * Don't choose a PLLC-derived clock as our parent
+		 * unless it had been manually set that way.  PLLC's
+		 * frequency gets adjusted by the firmware due to
+		 * over-temp or under-voltage conditions, without
+		 * prior notification to our clock consumer.
+		 */
+		if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc)
+			continue;
+
 		prate = clk_hw_get_rate(parent);
 		div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
 		rate = bcm2835_clock_rate_from_divisor(clock, prate, div);
-- 
2.8.0.rc3



From eric at anholt.net  Mon May  9 18:01:29 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon,  9 May 2016 18:01:29 -0700
Subject: [PATCH 2/3] clk: bcm2835: Mark GPIO clocks enabled at boot as
 critical.
In-Reply-To: <1462842090-2017-1-git-send-email-eric@anholt.net>
References: <1462842090-2017-1-git-send-email-eric@anholt.net>
Message-ID: <1462842090-2017-3-git-send-email-eric@anholt.net>

These divide off of PLLD_PER and are used for the ethernet and wifi
PHYs source PLLs.  Neither of them is currently represented by a phy
device that would grab the clock for us.

This keeps other drivers from killing the networking PHYs when they
disable their own clocks and trigger PLLD_PER's refcount going to 0.

Signed-off-by: Eric Anholt <eric at anholt.net>
---
 drivers/clk/bcm/clk-bcm2835.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index d9db03cb3fd8..1091012ecec6 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1708,13 +1708,15 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
 		.div_reg = CM_GP1DIV,
 		.int_bits = 12,
 		.frac_bits = 12,
+		.flags = CLK_IS_CRITICAL,
 		.is_mash_clock = true),
 	[BCM2835_CLOCK_GP2]	= REGISTER_PER_CLK(
 		.name = "gp2",
 		.ctl_reg = CM_GP2CTL,
 		.div_reg = CM_GP2DIV,
 		.int_bits = 12,
-		.frac_bits = 12),
+		.frac_bits = 12,
+		.flags = CLK_IS_CRITICAL),
 
 	/* HDMI state machine */
 	[BCM2835_CLOCK_HSM]	= REGISTER_PER_CLK(
-- 
2.8.0.rc3



From eric at anholt.net  Mon May  9 18:05:41 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon, 09 May 2016 18:05:41 -0700
Subject: [PATCH 0/5] clk: bcm2835: add flags for mash and parent clocks
In-Reply-To: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
References: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <87h9e6yb6i.fsf@eliezer.anholt.net>

kernel at martin.sperl.org writes:

> From: Martin Sperl <kernel at martin.sperl.org>
>
> Allow flags to be set on a per clock index basis, which control:
> * the parent clocks selected when not setting clocks explicitly

I don't think we need this other than avoiding PLLC.  What else do you
want to filter, and why?

> * the clock mode with regards to integer only or higher order mash

Please provide justification in the commit message explaining why there
is no obvious mash setting to just implement in clk-bcm2835.c, but that
that a better policy can be encoded in the DT.

Overall, I'm skeptical of this series.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160509/cfd0dcbe/attachment.sig>

From stefan at agner.ch  Mon May  9 18:13:05 2016
From: stefan at agner.ch (Stefan Agner)
Date: Mon, 09 May 2016 18:13:05 -0700
Subject: [PATCH v2 5/5] vf610-soc: Add Vybrid SoC device tree binding
 documentation
In-Reply-To: <CAL_JsqL7sjdONYad6sXM1KXFCjooANuN7WYg-paV9LnKnuMTnA@mail.gmail.com>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
 <65f3a7bd7a9faf1b390644d7c599c69683c753c4.1462171990.git.maitysanchayan@gmail.com>
 <20160504023026.GB5382@rob-hp-laptop>
 <20160505082758.GB18151@Sanchayan-Arch.localdomain>
 <CAL_JsqL1qQu_u=6xosP8UmR3oXLawbVz=Hap0wDm7aN4mjK2GA@mail.gmail.com>
 <4ca82be6c1d434c612868b441e9f6e1f@agner.ch>
 <CAL_JsqL7sjdONYad6sXM1KXFCjooANuN7WYg-paV9LnKnuMTnA@mail.gmail.com>
Message-ID: <cab9edb2184ec13341a1dae1de9c7ebc@agner.ch>

On 2016-05-09 15:58, Rob Herring wrote:
> On Mon, May 9, 2016 at 1:25 PM, Stefan Agner <stefan at agner.ch> wrote:
>> On 2016-05-09 10:14, Rob Herring wrote:
>>> On Thu, May 5, 2016 at 3:27 AM,  <maitysanchayan at gmail.com> wrote:
>>>> Hello Rob,
>>>>
>>>> On 16-05-03 21:30:26, Rob Herring wrote:
>>>>> On Mon, May 02, 2016 at 12:35:04PM +0530, Sanchayan Maity wrote:
>>>>> > Add device tree binding documentation for Vybrid SoC.
>>>>> >
>>>>> > Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
>>>>> > ---
>>>>> >  .../bindings/arm/freescale/fsl,vf610-soc.txt       | 35 ++++++++++++++++++++++
>>>>> >  1 file changed, 35 insertions(+)
>>>>> >  create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>>>>> >
>>>>> > diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>>>>> > new file mode 100644
>>>>> > index 0000000..bdd95e8
>>>>> > --- /dev/null
>>>>> > +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>>>>> > @@ -0,0 +1,35 @@
>>>>> > +Vybrid System-on-Chip
>>>>> > +---------------------
>>>>> > +
>>>>> > +Required properties:
>>>>> > +
>>>>> > +- #address-cells: must be 1
>>>>> > +- #size-cells: must be 1
>>>>> > +- compatible: "fsl,vf610-soc-bus", "simple-bus"
>>>>>
>>>>> If this is a bus, put the file in bindings/bus/...
>>>>
>>>> The fsl,vf610-soc-bus binding is used to bind the driver in question with
>>>> an appropriate compatible node.
>>>>
>>>> Basically being a standalone platform driver, there was need of a compatible
>>>> property to bind on. Introducing a separate device tree node for it's sake
>>>> didn't seem appropriate so the alteration to SoC node's compatible.
>>>
>>> Ah, so you are designing a node around the needs of a Linux specific
>>> driver. Don't do that. DT describes the h/w and this node is not a h/w
>>> block.
>>>
>>> Create a platform device based on a matching SOC compatible string
>>> instead and make your driver find the information it needs directly
>>> from the relevant nodes like the ROM node.
>>
>> That reads like my words a year ago:
>> https://lkml.org/lkml/2015/5/22/408
>>
>> Initially pretty much everything was hard-coded in the driver.
>>
>> Arnd then pushed to use more descriptive in the device tree.
>>
>> Of course, we should not end up making up relations which are not there
>> in hardware. We need to find the right balance.
>>
>> Here is my suggestion:
>> 1. Add "fsl,vf610-soc-bus" as compatible string to the soc node, use it
>> to bind the "soc bus driver" as a platform driver located in driver/soc/
> 
> I'm not convinced this is a h/w block. This keeps coming up and I
> think this is a kernel problem, not a DT problem. Let's face it that
> there are drivers at the SOC level which don't fit into a DT node.
> They may be the exception, but they are a common exception. My
> proposal for how to deal with these cases is here[1].

Probably "fsl,vf610-soc" would be better than "fsl,vf610-soc-bus".

But the SoC is definitely a h/w block! Despite all the individual
silicon in there, I can even touch the SoC ;-)

But yeah, I understand what you are saying... We model it as a
container, and do not attribute any specific thing directly to it. But
aren't there other containers where we bind to? Is it wrong to bind a
driver to a container, if that driver implements issues concerning that
level..?

The two drivers under drivers/soc/ which implement the SoC bus API and
both use a compatible string on a container level (e.g.
arm,realview-pb11mp-soc in arch/arm/boot/dts/arm-realview-pb11mp.dts).

> 
> I also think drivers/soc is a mess because it is randomly used or not.
> IMO, using it should not be at the whim of whomever does SOC support.

Are you talking about random drivers under drivers/soc/ or the ones
which implement the SoC bus API? I think that is not the same...

If SoC bus, agreed, it is a mess. Not only its adoption is sparse, the
specification is also interpreted differently across different SoC's,
which I brought up in the past:
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/333765.html

But it exports really useful information to user space, and that has
real value in practice.

--
Stefan


From cw00.choi at samsung.com  Mon May  9 18:23:45 2016
From: cw00.choi at samsung.com (Chanwoo Choi)
Date: Tue, 10 May 2016 10:23:45 +0900
Subject: [PATCH v6 5/9] extcon: max8997: Fix handling error code of
 regmap_irq_get_virq()
In-Reply-To: <1462519636-3250-4-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-4-git-send-email-k.kozlowski@samsung.com>
Message-ID: <57313821.4050309@samsung.com>

Hi Krzysztof,

On 2016? 05? 06? 16:27, Krzysztof Kozlowski wrote:
> The regmap_irq_get_virq() can return negative ERRNO, so its result
> should not be stored in unsigned int because error would be ignored.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---
>  drivers/extcon/extcon-max8997.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
> index 68754ac2c8ea..0afa3e8b5dc3 100644
> --- a/drivers/extcon/extcon-max8997.c
> +++ b/drivers/extcon/extcon-max8997.c
> @@ -660,11 +660,11 @@ static int max8997_muic_probe(struct platform_device *pdev)
>  
>  	for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
>  		struct max8997_muic_irq *muic_irq = &muic_irqs[i];
> -		unsigned int virq = 0;
> +		int virq = 0;
>  
>  		virq = regmap_irq_get_virq(max8997->irq_data_muic,
>  					muic_irq->irq);
> -		if (!virq) {
> +		if (virq <= 0) {
>  			ret = -EINVAL;
>  			goto err_irq;
>  		}
> 

Acked-by: Chanwoo Choi <cw00.choi at samsung.com>

Thanks,
Chanwoo Choi


From cw00.choi at samsung.com  Mon May  9 18:24:28 2016
From: cw00.choi at samsung.com (Chanwoo Choi)
Date: Tue, 10 May 2016 10:24:28 +0900
Subject: [PATCH v6 7/9] extcon: max8997: Fix inconsistent indenting
In-Reply-To: <1462519636-3250-6-git-send-email-k.kozlowski@samsung.com>
References: <1462519289-2356-2-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-1-git-send-email-k.kozlowski@samsung.com>
 <1462519636-3250-6-git-send-email-k.kozlowski@samsung.com>
Message-ID: <5731384C.6000209@samsung.com>

Hi Krzysztof,

On 2016? 05? 06? 16:27, Krzysztof Kozlowski wrote:
> Fix smatch warning:
> 	max8997_muic_probe() warn: inconsistent indenting
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---
>  drivers/extcon/extcon-max8997.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
> index 0afa3e8b5dc3..cf8de5be2405 100644
> --- a/drivers/extcon/extcon-max8997.c
> +++ b/drivers/extcon/extcon-max8997.c
> @@ -737,7 +737,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
>  	}
>  
>  	/* Set initial path for UART */
> -	 max8997_muic_set_path(info, info->path_uart, true);
> +	max8997_muic_set_path(info, info->path_uart, true);
>  
>  	/* Set ADC debounce time */
>  	max8997_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);
> 

Acked-by: Chanwoo Choi <cw00.choi at samsung.com>

Thanks,
Chanwoo Choi


From sfr at canb.auug.org.au  Mon May  9 18:29:05 2016
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Tue, 10 May 2016 11:29:05 +1000
Subject: linux-next: build failure after merge of the net-next tree
Message-ID: <20160510112905.5bffcad8@canb.auug.org.au>

Hi all,

After merging the net-next tree, today's linux-next build (x86_64
allmodconfig) failed like this:

net/qrtr/smd.c:106:14: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
  .callback = qcom_smd_qrtr_callback,
              ^
net/qrtr/smd.c:106:14: note: (near initialization for 'qcom_smd_qrtr_driver.callback')

Caused by commit

  bdabad3e363d ("net: Add Qualcomm IPC router")

interacting with commit

  b853cb9628bf ("soc: qcom: smd: Make callback pass channel reference")

from the arm-soc tree.

I added the following merge fix patch (and it turned out I needed the
new stubs).

From: Stephen Rothwell <sfr at canb.auug.org.au>
Date: Tue, 10 May 2016 11:14:06 +1000
Subject: [PATCH] soc: qcom: smd: fix for Qualcomm IPC router and callback API
 change

Signed-off-by: Stephen Rothwell <sfr at canb.auug.org.au>
---
 include/linux/soc/qcom/smd.h | 9 +++++++++
 net/qrtr/smd.c               | 9 ++++++---
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/include/linux/soc/qcom/smd.h b/include/linux/soc/qcom/smd.h
index 086e36d76be9..fbebbfc82ed3 100644
--- a/include/linux/soc/qcom/smd.h
+++ b/include/linux/soc/qcom/smd.h
@@ -70,6 +70,15 @@ static inline void qcom_smd_driver_unregister(struct qcom_smd_driver *drv)
 	WARN_ON(1);
 }
 
+static inline void *qcom_smd_get_drvdata(struct qcom_smd_channel *channel)
+{
+	return NULL;
+}
+
+static inline void qcom_smd_set_drvdata(struct qcom_smd_channel *channel, void *data)
+{
+}
+
 static inline int qcom_smd_send(struct qcom_smd_channel *channel,
 				const void *data, int len)
 {
diff --git a/net/qrtr/smd.c b/net/qrtr/smd.c
index 84ebce73aa23..0d11132b3370 100644
--- a/net/qrtr/smd.c
+++ b/net/qrtr/smd.c
@@ -21,13 +21,14 @@
 struct qrtr_smd_dev {
 	struct qrtr_endpoint ep;
 	struct qcom_smd_channel *channel;
+	struct device *dev;
 };
 
 /* from smd to qrtr */
-static int qcom_smd_qrtr_callback(struct qcom_smd_device *sdev,
+static int qcom_smd_qrtr_callback(struct qcom_smd_channel *channel,
 				  const void *data, size_t len)
 {
-	struct qrtr_smd_dev *qdev = dev_get_drvdata(&sdev->dev);
+	struct qrtr_smd_dev *qdev = qcom_smd_get_drvdata(channel);
 	int rc;
 
 	if (!qdev)
@@ -35,7 +36,7 @@ static int qcom_smd_qrtr_callback(struct qcom_smd_device *sdev,
 
 	rc = qrtr_endpoint_post(&qdev->ep, data, len);
 	if (rc == -EINVAL) {
-		dev_err(&sdev->dev, "invalid ipcrouter packet\n");
+		dev_err(qdev->dev, "invalid ipcrouter packet\n");
 		/* return 0 to let smd drop the packet */
 		rc = 0;
 	}
@@ -73,12 +74,14 @@ static int qcom_smd_qrtr_probe(struct qcom_smd_device *sdev)
 		return -ENOMEM;
 
 	qdev->channel = sdev->channel;
+	qdev->dev = &sdev->dev;
 	qdev->ep.xmit = qcom_smd_qrtr_send;
 
 	rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO);
 	if (rc)
 		return rc;
 
+	qcom_smd_set_drvdata(sdev->channel, qdev);
 	dev_set_drvdata(&sdev->dev, qdev);
 
 	dev_dbg(&sdev->dev, "Qualcomm SMD QRTR driver probed\n");
-- 
2.7.0

-- 
Cheers,
Stephen Rothwell


From andy.gross at linaro.org  Mon May  9 18:52:12 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Mon, 9 May 2016 20:52:12 -0500
Subject: linux-next: build failure after merge of the net-next tree
In-Reply-To: <20160510112905.5bffcad8@canb.auug.org.au>
References: <20160510112905.5bffcad8@canb.auug.org.au>
Message-ID: <CAPBZ5QcRiG0w4WsU7rDGSNogH1PSONWSjrZ6fXWb4kdc+BH3JQ@mail.gmail.com>

On 9 May 2016 at 20:29, Stephen Rothwell <sfr at canb.auug.org.au> wrote:
> Hi all,
>
> After merging the net-next tree, today's linux-next build (x86_64
> allmodconfig) failed like this:
>
> net/qrtr/smd.c:106:14: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
>   .callback = qcom_smd_qrtr_callback,
>               ^
> net/qrtr/smd.c:106:14: note: (near initialization for 'qcom_smd_qrtr_driver.callback')
>
> Caused by commit
>
>   bdabad3e363d ("net: Add Qualcomm IPC router")
>
> interacting with commit
>
>   b853cb9628bf ("soc: qcom: smd: Make callback pass channel reference")
>
> from the arm-soc tree.
>
> I added the following merge fix patch (and it turned out I needed the
> new stubs).

Thanks for fixing this up.  I'll work with Bjorn to get this resolved.
I'll have something up for tomorrow's next pull.


Regards,

Andy Gross


From helgaas at kernel.org  Mon May  9 18:53:36 2016
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 9 May 2016 20:53:36 -0500
Subject: [PATCH V6 01/13] pci, acpi, x86, ia64: Move ACPI host bridge
 device companion assignment to core code.
In-Reply-To: <292578579.uIxhMjkdfG@vostro.rjw.lan>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-2-git-send-email-tn@semihalf.com>
 <292578579.uIxhMjkdfG@vostro.rjw.lan>
Message-ID: <20160510015336.GA29582@localhost>

On Tue, May 10, 2016 at 12:56:37AM +0200, Rafael J. Wysocki wrote:
> On Friday, April 15, 2016 07:06:36 PM Tomasz Nowicki wrote:
> > Currently we have two platforms (x86 & ia64) capable of PCI ACPI host
> > bridge initialization. They both use arch-specific sysdata to pass down
> > parent device reference and both rely on NULL parent in pci_create_root_bus()
> > to validate sysdata content.
> 
> No, this is not relied on for that.  It is just NULL, because we don't
> have a physical parent device representation for the PCI host bridge.
> 
> > It looks hacky and prevents us from getting some firmware specific
> > info for PCI host controller based on its acpi_device structure
> > in generic pci_create_root_bus() function.
> 
> You can't get that info without adding ACPI-specific code to that function
> anyway.
> 
> > However, we overcome that blocker by passing down parent device via
> > pci_create_root_bus parameter (as the ACPI device type).
> 
> Which is completely wrong.
> 
> > Then we use ACPI_COMPANION_SET in core code
> > for ACPI boot method only. ACPI_COMPANION_SET is safe to run for all
> > cases DT, ACPI and DT&ACPI.
> > 
> > Since now PCI core code is setting ACPI companion device for us,
> > x86 & ia64 specific ACPI companion device setting turns out to be dead now.
> > We can get rid of it, including related companion reference from
> > PCI sysdata structure. Aslo, PCI_CONTROLLER macro cannot return valid
> > companion device anymore. Therefore we need to convert its usage to
> > ACPI_COMPANION.

I think getting rid of arch-specific sysdata is a good goal (at least
for things like the domain and ACPI companion that are really not
arch-specific).

But I'm afraid I've been guilty of allowing the perfect to be the
enemy of the good.  I think it will be more useful in the end if we
can get as much of this work in v4.7 as possible, even if there's more
polishing we'd like to do later.

What if we keep the x86 and ia64 handling of ACPI_COMPANION the way it
is today, and do it the same way for arm64?  Then later, after we
merge Arnd's work to make a generic pci_register_host() or similar, I
suspect we might be able to unify the ACPI_COMPANION stuff more
easily.  If the driver (acpi/pci_root.c) allocates the struct
pci_host_bridge, then maybe it will be able to fill in the domain and
set up the ACPI_COMPANION before it calls the scan interface.

Bjorn


From sre at kernel.org  Mon May  9 19:18:27 2016
From: sre at kernel.org (Sebastian Reichel)
Date: Tue, 10 May 2016 04:18:27 +0200
Subject: [PATCH 4/7] [media] ir-rx51: add DT support to driver
In-Reply-To: <CAL_JsqJPZS1ne_xAuBFtCc5L1HKFJf0LDUJ7CRSFXhc3adkTfA@mail.gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <1462634508-24961-5-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <20160509200657.GA3379@rob-hp-laptop> <5730F8BA.5000402@gmail.com>
 <CAL_JsqJPZS1ne_xAuBFtCc5L1HKFJf0LDUJ7CRSFXhc3adkTfA@mail.gmail.com>
Message-ID: <20160510021826.GE1129@earth>

Hi,

On Mon, May 09, 2016 at 04:07:35PM -0500, Rob Herring wrote:
> There's already a pwm-led binding that can be used. Though there
> may be missing consumer IR to LED subsystem support in the kernel.
> You could list both compatibles, use the rx51 IR driver now, and
> then move to pwm-led driver in the future.

Well from a purely HW point of view it's a PWM connected led. The
usage is completely different though. Usually PWM is used to control
the LED's brightness via the duty cycle (basic concept: enabling led
only 50% of time reduces brightness to 50%).

In the IR led's case the aim is generating a specific serial pattern
instead. For this task it uses a dmtimer in PWM mode and a second
one to reconfigure the pwm timer.

I don't know about a good name, but rx51 should be replaced with
n900 in the compatible string. So maybe "nokia,n900-infrared-diode".

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160510/b754425b/attachment.sig>

From jamesjj.liao at mediatek.com  Mon May  9 19:20:32 2016
From: jamesjj.liao at mediatek.com (James Liao)
Date: Tue, 10 May 2016 10:20:32 +0800
Subject: [PATCH v7 7/9] clk: mediatek: Enable critical clocks for MT2701
In-Reply-To: <20160509221321.GT3492@codeaurora.org>
References: <1460621514-65191-1-git-send-email-jamesjj.liao@mediatek.com>
 <1460621514-65191-8-git-send-email-jamesjj.liao@mediatek.com>
 <20160506231229.GJ3492@codeaurora.org> <1462772426.5344.7.camel@mtksdaap41>
 <20160509221321.GT3492@codeaurora.org>
Message-ID: <1462846832.23126.1.camel@mtksdaap41>

On Mon, 2016-05-09 at 15:13 -0700, Stephen Boyd wrote:
> On 05/09, James Liao wrote:
> > Hi Stephen,
> > 
> > On Fri, 2016-05-06 at 16:12 -0700, Stephen Boyd wrote:
> > > On 04/14, James Liao wrote:
> > > > Some system clocks should be turned on by default on MT2701.
> > > > This patch enable these clocks when related clocks have
> > > > been registered.
> > > > 
> > > > Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
> > > > ---
> > > 
> > > critical clks got merged now (sorry I'm slowly getting back to
> > > looking at patches). Please use that flag.
> > 
> > I don't see critical clock support in v4.6-rc7. Is there a repo/branch
> > that has critical clocks merged?
> > 
> 
> Right, it's in clk-next in the clk tree.

I got it. I'll try to use the new critical clock support.


Best regards,

James



From jamesjj.liao at mediatek.com  Mon May  9 19:30:35 2016
From: jamesjj.liao at mediatek.com (James Liao)
Date: Tue, 10 May 2016 10:30:35 +0800
Subject: [PATCH v7 4/9] clk: mediatek: Add MT2701 clock support
In-Reply-To: <20160509222950.GV3492@codeaurora.org>
References: <1460621514-65191-1-git-send-email-jamesjj.liao@mediatek.com>
 <1460621514-65191-5-git-send-email-jamesjj.liao@mediatek.com>
 <20160506231151.GI3492@codeaurora.org>
 <1462775888.5344.20.camel@mtksdaap41>
 <20160509222950.GV3492@codeaurora.org>
Message-ID: <1462847435.23126.10.camel@mtksdaap41>

Hi Stephen,

On Mon, 2016-05-09 at 15:29 -0700, Stephen Boyd wrote:
> On 05/09, James Liao wrote:
> > On Fri, 2016-05-06 at 16:11 -0700, Stephen Boyd wrote:
> > > On 04/14, James Liao wrote:
> > > > diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
> > > > new file mode 100644
> > > > index 0000000..b4db141
> > > > --- /dev/null
> > > > +++ b/drivers/clk/mediatek/clk-mt2701.c
> > > > +static void __init mtk_infrasys_init(struct device_node *node)
> > > > +{
> > > > +	struct clk_onecell_data *clk_data;
> > > > +	int r;
> > > > +
> > > > +	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
> > > > +
> > > > +	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
> > > > +						clk_data);
> > > > +	mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
> > > > +						clk_data);
> > > > +
> > > > +	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> > > > +	if (r)
> > > > +		pr_err("%s(): could not register clock provider: %d\n",
> > > > +			__func__, r);
> > > > +}
> > > > +CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt2701-infracfg", mtk_infrasys_init);
> > > 
> > > I'm still lost on the usage of CLK_OF_DECLARE here. What part of
> > > these clk controllers needs to be registered to make the timer
> > > work?
> > 
> > GPT (mtk-timer.c) may need infracfg and topckgen clocks. MT8173 for
> > example:
> > 
> > 	timer: timer at 10008000 {
> > 	[...]
> > 		clocks = <&infracfg CLK_INFRA_CLK_13M>,
> > 			 <&topckgen CLK_TOP_RTC_SEL>;
> > 	};
> 
> Ok. It should be possible to only register the clk tree for these
> clks in CLK_OF_DECLARE() and then register the other clks that
> the clk provider provides with a regular driver probe routine.
> That way we can get the advantage of the device framework, etc.
> but still register the clks we need to make the timer work early
> on.

I'll study a new way to separate clock registration of a subsystem into
CLK_OF_DECLARE() and device probe().

> > 
> > > > +	GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2),
> > > > +	GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3),
> > > > +	GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4),
> > > > +	GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5),
> > > > +	GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6),
> > > > +	GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7),
> > > > +	GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8),
> > > > +	GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9),
> > > > +	GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10),
> > > > +	GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11),
> > > > +	GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14),
> > > > +};
> > > 
> > > I also don't understand why we don't have different files and
> > > drivers for all these different clock controllers? They all have
> > > a similar probe structure, sure, but otherwise these are
> > > different devices with different clks for them. The whole #ifdef
> > > thing in the later patch would go away too.
> > 
> > Yes, you are right. So you prefer to support subsystem clocks in
> > separated files such as clk-mt2701-mm.c, clk-mt2701-bdp.c and so on,
> > right?
> > 
> > But even if we implement subsystem clock in separated files, we still
> > need a way to make them optional. So the config options and #ifdef may
> > not be removed.
> 
> Presumably different files could just not be compiled if the
> config is disabled, thus removing any need for #ifdef.

OK. I'll try to implement these subsystem clocks into separated files in
next patch.

> > 
> > > > +	GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12),
> > > > +	GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13),
> > > > +	GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14),
> > > > +	GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15),
> > > > +	GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_pll340m", 16),
> > > > +};
> > > > +
> > > > +static void __init mtk_bdpsys_init(struct device_node *node)
> > > 
> > > Shouldn't be __init because it's driver probe path.
> > 
> > I use builtin_platform_driver_probe(clk_drv, clk_probe) to register this
> > driver, and it looks can be __init.
> 
> Ok, but that doesn't work with deferred probe right? It may be
> better to avoid it then.

It may be a concern. I'll investigate a proper way to implement the init
functions.


Best regards,

James 




From liviu.dudau at arm.com  Fri May  6 09:26:13 2016
From: liviu.dudau at arm.com (liviu.dudau at arm.com)
Date: Fri, 6 May 2016 17:26:13 +0100
Subject: [PATCH 1/2] drm: hdlcd: Skip PM callbacks if unbound
In-Reply-To: <20160506145417.GB15076@ulmo.ba.sec>
References: <eeb2a5540f50f5a3dd7f87861be1e9117bc4ed65.1462464611.git.robin.murphy@arm.com>
 <20160506145417.GB15076@ulmo.ba.sec>
Message-ID: <20160506162613.GL28464@e106497-lin.cambridge.arm.com>

On Fri, May 06, 2016 at 04:54:17PM +0200, Thierry Reding wrote:
> On Thu, May 05, 2016 at 05:13:37PM +0100, Robin Murphy wrote:
> > Until an encoder component is available to trigger the HDLCD's component
> > master bind callback, the drm_device we keep in drvdata isn't allocated.
> > Since it is quite possible to, say, hibernate the system without having
> > loaded the encoder driver, the PM callbacks need to check for a valid
> > drm_device before trying to take the lock and suspend/resume the crtcs,
> > otherwise this happens:
> > 
> > [   51.779092] Unable to handle kernel NULL pointer dereference at virtual address 00000200
> > [   51.787143] pgd = ffff800974462000
> > [   51.790514] [00000200] *pgd=0000000000000000
> > [   51.794768] Internal error: Oops: 96000004 [#1] PREEMPT SMP
> > [   51.800291] Modules linked in:
> > [   51.803325] CPU: 4 PID: 2098 Comm: systemd-sleep Not tainted 4.6.0-rc6+ #4
> > [   51.810140] Hardware name: ARM Juno development board (r1) (DT)
> > [   51.816008] task: ffff800974430000 ti: ffff80097380c000 task.ti: ffff80097380c000
> > [   51.823433] PC is at mutex_lock+0x14/0x60
> > [   51.827411] LR is at drm_modeset_lock_all+0x3c/0xe0
> > [   51.832246] pc : [<ffff0000087d55c4>] lr : [<ffff0000084839fc>] pstate: 40000145
> > [   51.839577] sp : ffff80097380faf0
> > [   51.842859] x29: ffff80097380faf0 x28: 0000000000000000
> > [   51.848132] x27: 0000000000000002 x26: ffff000008e01000
> > [   51.853405] x25: ffff0000084cc000 x24: ffff000008dcb408
> > [   51.858678] x23: ffff000008e7c000 x22: ffff8009760e8870
> > [   51.863962] x21: 0000000000000200 x20: 0000000000000000
> > [   51.869244] x19: 0000000000000200 x18: ffff800079357dd0
> > [   51.874527] x17: 0000ffff8a00ab88 x16: 0000000000000018
> > [   51.879809] x15: 0000000000000018 x14: 0000000000000000
> > [   51.885091] x13: 0000000000000002 x12: 0000000000000000
> > [   51.890374] x11: ffff0000087ff904 x10: 0000000000000840
> > [   51.895656] x9 : 0000000000000000 x8 : ffff800973821680
> > [   51.900938] x7 : 0000000000000000 x6 : 000000000000003f
> > [   51.906220] x5 : 0000000000000040 x4 : 0000000000000000
> > [   51.911502] x3 : 0000000000000004 x2 : 0000000000000000
> > [   51.916784] x1 : 0000000000000001 x0 : 0000000000000200
> > ...
> > [   52.339406] [<ffff0000087d55c4>] mutex_lock+0x14/0x60
> > [   52.344425] [<ffff0000084839fc>] drm_modeset_lock_all+0x3c/0xe0
> > [   52.350305] [<ffff00000848a034>] hdlcd_pm_suspend+0x2c/0x90
> > [   52.355842] [<ffff0000084c0d14>] platform_pm_suspend+0x24/0x58
> > [   52.361638] [<ffff0000084cc190>] dpm_run_callback.isra.4+0x20/0x68
> > [   52.367778] [<ffff0000084ccad4>] __device_suspend+0xe4/0x238
> > [   52.373400] [<ffff0000084cdcac>] dpm_suspend+0x10c/0x240
> > [   52.378679] [<ffff0000084ce0b8>] dpm_suspend_start+0x70/0x80
> > [   52.384302] [<ffff0000080f80e4>] suspend_devices_and_enter+0x9c/0x480
> > [   52.390699] [<ffff0000080f8698>] pm_suspend+0x1d0/0x240
> > [   52.395890] [<ffff0000080f7280>] state_store+0x80/0x100
> > [   52.401084] [<ffff0000083503f4>] kobj_attr_store+0x14/0x28
> > [   52.406535] [<ffff000008238580>] sysfs_kf_write+0x48/0x58
> > [   52.411899] [<ffff00000823798c>] kernfs_fop_write+0xbc/0x188
> > [   52.417521] [<ffff0000081c71f4>] __vfs_write+0x1c/0xe0
> > [   52.422626] [<ffff0000081c8144>] vfs_write+0x8c/0x1a8
> > [   52.427644] [<ffff0000081c953c>] SyS_write+0x44/0xa0
> > [   52.432578] [<ffff000008084ecc>] __sys_trace_return+0x0/0x4
> > [   52.438114] Code: 910003fd f9000bf3 aa0003f3 f9800011 (885ffc01)
> > [   52.444229] ---[ end trace 34b87a5fb9453f65 ]---
> > 
> > Acked-by: Liviu Dudau <Liviu.Dudau at arm.com>
> > Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> > ---
> >  drivers/gpu/drm/arm/hdlcd_drv.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> > index 734899c4e4bb..86a5eea4cf53 100644
> > --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> > +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> > @@ -498,7 +498,7 @@ static int __maybe_unused hdlcd_pm_suspend(struct device *dev)
> >  	struct drm_device *drm = dev_get_drvdata(dev);
> >  	struct drm_crtc *crtc;
> >  
> > -	if (pm_runtime_suspended(dev))
> > +	if (pm_runtime_suspended(dev) || !drm)
> >  		return 0;
> >  
> >  	drm_modeset_lock_all(drm);
> > @@ -513,7 +513,7 @@ static int __maybe_unused hdlcd_pm_resume(struct device *dev)
> >  	struct drm_device *drm = dev_get_drvdata(dev);
> >  	struct drm_crtc *crtc;
> >  
> > -	if (!pm_runtime_suspended(dev))
> > +	if (!pm_runtime_suspended(dev) || !drm)
> >  		return 0;
> 
> Perhaps rather than this workaround you should only enable runtime PM on
> this after the master has been bound?

Yes, that is probably a better solution, even if the patch is going to be much bigger.

Best regards,
Liviu

> 
> Thierry


-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ?\_(?)_/?


From a0393675 at ti.com  Mon May  9 21:24:02 2016
From: a0393675 at ti.com (Keerthy)
Date: Tue, 10 May 2016 09:54:02 +0530
Subject: [PATCH RESEND 0/4] arm: dts: am57xx: Correct the thermal
 thresholds
In-Reply-To: <1461837949-11116-1-git-send-email-j-keerthy@ti.com>
References: <1461837949-11116-1-git-send-email-j-keerthy@ti.com>
Message-ID: <57316262.80003@ti.com>

Tony,

On Thursday 28 April 2016 03:35 PM, Keerthy wrote:
> Noticed that earlier post had a wrong list name hence resending the
> series.
>
> Currently all the am57xx versions are wrongly re-using the dra7  thermal
> threholds. Introduing the correct thermal thresholds based on industrial
> or commercial grade silicon present on the individual boards.
>
> Tested on AM57XX-BEAGLE-X15 (Commercial) and AM572X-IDK(Industrial)
> for the trip_point node sysfs temperatures.
>

A Gentle ping on this series.

> These patches are on top of:
> https://kernel.googlesource.com/pub/scm/linux/kernel/git/tmlind/linux-omap/+/omap-for-v4.7/dt
>
> Keerthy (4):
>    ARM: dts: am57xx: Introduce commercial grade thermal thresholds
>    ARM: dts: am57xx: Introduce industrial grade thermal thresholds
>    ARM: dts: am57xx: Include the commercial grade thresholds
>    ARM: dts: am57xx-idk: Include Industrial grade      thermal thresholds
>
>   arch/arm/boot/dts/am57xx-beagle-x15.dts        |  1 +
>   arch/arm/boot/dts/am57xx-commercial-grade.dtsi | 23 +++++++++++++++++++++++
>   arch/arm/boot/dts/am57xx-idk-common.dtsi       |  2 ++
>   arch/arm/boot/dts/am57xx-industrial-grade.dtsi | 23 +++++++++++++++++++++++
>   4 files changed, 49 insertions(+)
>   create mode 100644 arch/arm/boot/dts/am57xx-commercial-grade.dtsi
>   create mode 100644 arch/arm/boot/dts/am57xx-industrial-grade.dtsi
>


From Wenyou.Yang at atmel.com  Mon May  9 21:50:37 2016
From: Wenyou.Yang at atmel.com (Yang, Wenyou)
Date: Tue, 10 May 2016 04:50:37 +0000
Subject: [PATCH 0/2] mtd: atmel_nand: remove compatible "atmel,sama5d4-nfc"
In-Reply-To: <20160509201324.GA9845@rob-hp-laptop>
References: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
 <20160509201324.GA9845@rob-hp-laptop>
Message-ID: <B256D81BAE5131468A838E5D7A243641D6487F5A@penmbx01>



> -----Original Message-----
> From: Rob Herring [mailto:robh at kernel.org]
> Sent: 2016?5?10? 4:13
> To: Yang, Wenyou <Wenyou.Yang at atmel.com>
> Cc: Brian Norris <computersforpeace at gmail.com>; David Woodhouse
> <dwmw2 at infradead.org>; Pawel Moll <pawel.moll at arm.com>; Mark Brown
> <broonie at kernel.org>; Ian Campbell <ijc+devicetree at hellion.org.uk>; Kumar
> Gala <galak at codeaurora.org>; linux-kernel at vger.kernel.org; linux-
> mtd at lists.infradead.org; devicetree at vger.kernel.org; Ferre, Nicolas
> <Nicolas.FERRE at atmel.com>; Alexandre Belloni <alexandre.belloni at free-
> electrons.com>; Jean-Christophe Plagniol-Villard <plagnioj at jcrosoft.com>;
> Russell King <linux at arm.linux.org.uk>; Josh Wu <rainyfeeling at outlook.com>;
> linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 0/2] mtd: atmel_nand: remove compatible "atmel,sama5d4-
> nfc"
> 
> On Mon, May 09, 2016 at 02:51:17PM +0800, Wenyou Yang wrote:
> > It is a datasheet bug, for current SoCs, the RB_EDGE3(i.e. bit 27) of
> > HSMC_SR register does not exist, the RB_EDGE0 (i.e. bit 24) is the
> > ready/busy line edge status bit. So the compatible "atmel,sama5d4-nfc"
> > is unneeded.
> 
> The compatible is needed if the SOC still exists. You can list both for the sama5d4
> if the block is the same.

The NFC IP of SAMA5D4 is same as SAMA5D2's, SAMA5D4 hase this issue.  This compatible can be removed. 


Best Regards,
Wenyou Yang

From krzk at kernel.org  Mon May  9 22:13:52 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 07:13:52 +0200
Subject: [PATCH v2 00/22] ARM: dts: exynos: Add initial support for Odroid
 XU
In-Reply-To: <0aacc9fe-01c2-a9cd-35c7-db2c17a737c3@osg.samsung.com>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <0aacc9fe-01c2-a9cd-35c7-db2c17a737c3@osg.samsung.com>
Message-ID: <57316E10.2030300@kernel.org>

On 05/10/2016 12:05 AM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
>>
>> Hi,
>>
>> Patchset adds necessary clocks, reorganizes existing stuff and finally
>> adds Odroid XU support.
>>
> 
> Do you have a branch available so I can pull these patches and test in
> the Exynos5 boards I've access to?

Of course. It sits on my private repo, on Github:
https://github.com/krzk/linux
branch: for-next/odroid-xu-v2

Best regards,
Krzysztof


From krzk at kernel.org  Mon May  9 22:26:19 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 07:26:19 +0200
Subject: [PATCH v2 04/22] clk: samsung: exynos5410: Provide fin_pll
 external fixed clock
In-Reply-To: <e805f0d3-038b-72ce-4464-ac3605e9e5bb@osg.samsung.com>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-5-git-send-email-krzk@kernel.org>
 <e805f0d3-038b-72ce-4464-ac3605e9e5bb@osg.samsung.com>
Message-ID: <573170FB.4010808@kernel.org>

On 05/09/2016 10:19 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
>> Just like clock driver for Exynos542x/5800, provide the fixed clock here
>> so the clock bindings and their consumers would be consistent and
>> similar.
>>
>> However a clock named "fin_pll" is already provided by generic
>> fixed-clock and it is both referenced in the clock driver (by name) and
>> in DT (by phandle). To make the transition smooth, first introduce the
>> new external fixed clock here under temporary, different name and switch
>> internal users to it.
>>
>> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
>> ---
> 
> [snip]
> 
>>  
>> +/* Same as in Exynos5420 */
>> +static const struct of_device_id ext_clk_match[] __initconst = {
>> +	{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
> 
> Since using designated initializers, I was about to say that there is no need
> to explicitly set .data to 0 since omitted fields are implicitly initialized...
> 
>> +	{ },
>> +};
>> +
>>  /* register exynos5410 clocks */
>>  static void __init exynos5410_clk_init(struct device_node *np)
>>  {
>> @@ -192,6 +204,10 @@ static void __init exynos5410_clk_init(struct device_node *np)
>>  
>>  	ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
>>  
>> +	samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
>> +			ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
>> +			ext_clk_match);
>> +
> 
> ... but then I noticed that .data is used as exynos5x_fixed_rate_ext_clks
> array index in samsung_clk_of_register_fixed_ext(). So makes sense to set
> it explicitly to make the intent clear.

Yes, that is the intention here. The '(void *)0' is a hint that clock
needs frequency from DT.

Thanks for review,
Krzysztof



From yamada.masahiro at socionext.com  Mon May  9 22:27:20 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 14:27:20 +0900
Subject: [PATCH] mfd: core: check existence of enable/disable callbacks
Message-ID: <1462858040-13174-1-git-send-email-yamada.masahiro@socionext.com>

Child devices may not know if their MFD cells have enable/disable
callbacks.

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

 drivers/mfd/mfd-core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 88bd1b1..95dbf3a 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -33,7 +33,7 @@ int mfd_cell_enable(struct platform_device *pdev)
 	int err = 0;
 
 	/* only call enable hook if the cell wasn't previously enabled */
-	if (atomic_inc_return(cell->usage_count) == 1)
+	if (atomic_inc_return(cell->usage_count) == 1 && cell->enable)
 		err = cell->enable(pdev);
 
 	/* if the enable hook failed, decrement counter to allow retries */
@@ -50,7 +50,7 @@ int mfd_cell_disable(struct platform_device *pdev)
 	int err = 0;
 
 	/* only disable if no other clients are using it */
-	if (atomic_dec_return(cell->usage_count) == 0)
+	if (atomic_dec_return(cell->usage_count) == 0 && cell->disable)
 		err = cell->disable(pdev);
 
 	/* if the disable hook failed, increment to allow retries */
-- 
1.9.1



From krzk at kernel.org  Mon May  9 22:27:01 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 07:27:01 +0200
Subject: [PATCH v2 06/22] ARM: dts: exynos: Remove old fixed-clock provider
 on SMDK5410
In-Reply-To: <723d088c-ada7-a18f-87a2-e7caaf2c56fd@osg.samsung.com>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-7-git-send-email-krzk@kernel.org>
 <723d088c-ada7-a18f-87a2-e7caaf2c56fd@osg.samsung.com>
Message-ID: <57317125.5030702@kernel.org>

On 05/09/2016 10:24 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
>> All "fin_pll" clock users are switched to the new one, provided by
> 
> s/are switched/were switched

Thanks for spotting this,
Krzysztof



From krzk at kernel.org  Mon May  9 22:30:38 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 07:30:38 +0200
Subject: [PATCH v2 13/22] ARM: dts: exynos: Move common nodes to
 exynos5.dtsi
In-Reply-To: <1cee1acf-fb07-9a7f-5d18-b4824a10f5a2@osg.samsung.com>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-14-git-send-email-krzk@kernel.org>
 <1cee1acf-fb07-9a7f-5d18-b4824a10f5a2@osg.samsung.com>
Message-ID: <573171FE.6070309@kernel.org>

On 05/09/2016 11:25 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
>> Exynos5420 and Exynos5250 share some nodes: the PWM and syscon
>> (sysreg_system_controller). Move them to parent DTSI to avoid
>> duplication.
>>
>> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
>> ---
> 
> I see that the i2c_[0-3] nodes are also the same in both DTSI. Do you
> think that makes sense to also move those to exynos5.dtsi as well?

Thanks, that is a good suggestion. I didn't add the I2C and its children
to Odroid XU yet but probably having the nodes defined won't hurt.
Especially that they are disabled by default.

Best regards,
Krzysztof

> In any case that can be made as a follow-up, so:
> 
> Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
> 
> Best regards,
> 



From krzk at kernel.org  Mon May  9 22:33:06 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 07:33:06 +0200
Subject: [PATCH v2 20/22] ARM: dts: exynos: Move common
 Exynos5410/542x/5800 nodes to new DTSI
In-Reply-To: <9e642e0d-87e1-4661-0233-acecf0082f24@osg.samsung.com>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-21-git-send-email-krzk@kernel.org>
 <9e642e0d-87e1-4661-0233-acecf0082f24@osg.samsung.com>
Message-ID: <57317292.2080004@kernel.org>

On 05/09/2016 11:53 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/08/2016 03:06 PM, Krzysztof Kozlowski wrote:
>> The Exynos5410/542x/5800 are very similar designs. Create new new
> 
> s/new new/a new
> 
>> DTSI with common nodes to remove DTS duplication. Although currently
>> only MCT and SysRAM are shared but in future more nodes will be added to
>> common file.
>>
>> The patch should not have functional impact.
>>
> 
> A nice way to check this is to diff the disassembled compiled DTBs with
> and without the patch and making sure that the resulted DTS is the same.

Yes, that is what I've done. Recently there is a tool making that even
easier: dtx_diff.

Best regards,
Krzysztof



From krzk at kernel.org  Mon May  9 22:35:47 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 07:35:47 +0200
Subject: [PATCH v2 22/22] ARM: dts: exynos: Add initial support for Odroid
 XU board
In-Reply-To: <cbcb5657-8825-83cf-688f-d565ac7ecbab@osg.samsung.com>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-23-git-send-email-krzk@kernel.org>
 <cbcb5657-8825-83cf-688f-d565ac7ecbab@osg.samsung.com>
Message-ID: <57317333.5010309@kernel.org>

On 05/10/2016 12:02 AM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/08/2016 03:06 PM, Krzysztof Kozlowski wrote:
>> The Hardkernel's Odroid XU board was first design with big.LITTLE SoC
>> from Samsung: the Exynos5410. Comparing now to more popular Odroid XU3
>> the differences are:
>> 1. Exynos5410 instead of 5422,
>> 2. DisplayPort,
>> 3. Main PMIC: Maxim 77802 instead of S2MPS11,
>> 4. USB3503+LAN9730 instead of integrated LAN9514,
>> 5. eMMC 4.5 instead of eMMC 5.0,
>>
>> This patch adds initial support for the XU board with working basic
>> functions, eMMC/SD and USB (including attached ethernet adapter).
>>
>> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
>> ---
> 
> This DTS has some TODO's, FIXME's and commented input supplies. Probably
> this patch should had been an RFC? or you should mention about these in
> the commit message to understand why are there.

I have to clean it up or fix these notes. Actually I was quite surprised
that board worked fine with this basic setup.

Best regards,
Krzysztof


From sricharan at codeaurora.org  Mon May  9 23:05:55 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Tue, 10 May 2016 11:35:55 +0530
Subject: [PATCH 1/2] i2c: qup: add ACPI support
In-Reply-To: <1462317959-11632-1-git-send-email-nkaje@codeaurora.org>
References: <1462317959-11632-1-git-send-email-nkaje@codeaurora.org>
Message-ID: <000201d1aa82$07b3f680$171be380$@codeaurora.org>

+additional lists

> Add support to get the device parameters from ACPI. Assume that the clocks
> are managed by firmware.
> 
> Signed-off-by: Naveen Kaje <nkaje at codeaurora.org>
> ---
<snip>
> +	bool input_clk_ctrl = true;
> 
>  	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
>  	if (!qup)
> @@ -1372,7 +1378,14 @@ static int qup_i2c_probe(struct platform_device
> *pdev)
>  	init_completion(&qup->xfer);
>  	platform_set_drvdata(pdev, qup);
> 
> -	of_property_read_u32(node, "clock-frequency", &clk_freq);
> +	ret = device_property_read_u32(qup->dev, "clock-frequency",
> &clk_freq);
> +	if (ret) {
> +		dev_warn(qup->dev, "using default clock-frequency values");
> +		clk_freq = DEFAULT_CLK_FREQ;
> +	}
> +
> +	if (ACPI_HANDLE(qup->dev) && !node)
> +		input_clk_ctrl = false;
> 
>  	if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-
> v1.1.1")) {
>  		qup->adap.algo = &qup_i2c_algo;
> @@ -1454,20 +1467,29 @@ nodma:
>  		return qup->irq;
>  	}
> 
> -	qup->clk = devm_clk_get(qup->dev, "core");
> -	if (IS_ERR(qup->clk)) {
> -		dev_err(qup->dev, "Could not get core clock\n");
> -		return PTR_ERR(qup->clk);
> -	}
> +	if (input_clk_ctrl) {
     The above ACPI_HANDLE check can be directly used here and avoid the
variable.

> +		qup->clk = devm_clk_get(qup->dev, "core");
> +		if (IS_ERR(qup->clk)) {
> +			dev_err(qup->dev, "Could not get core clock\n");
> +			return PTR_ERR(qup->clk);
> +		}
> 
> -	qup->pclk = devm_clk_get(qup->dev, "iface");
> -	if (IS_ERR(qup->pclk)) {
> -		dev_err(qup->dev, "Could not get iface clock\n");
> -		return PTR_ERR(qup->pclk);
> +		qup->pclk = devm_clk_get(qup->dev, "iface");
> +		if (IS_ERR(qup->pclk)) {
> +			dev_err(qup->dev, "Could not get iface clock\n");
> +			return PTR_ERR(qup->pclk);
> +		}
> +		qup_i2c_enable_clocks(qup);
> +		src_clk_freq = clk_get_rate(qup->clk);
> +	} else {
> +		ret = device_property_read_u32(qup->dev,
> +				"src-clock-hz", &src_clk_freq);
> +		if (ret) {
> +			dev_warn(qup->dev, "using default src-clock-hz");
> +			src_clk_freq = DEFAULT_SRC_CLK;
> +		}
>  	}
> 
> -	qup_i2c_enable_clocks(qup);
> -
>  	/*
>  	 * Bootloaders might leave a pending interrupt on certain QUP's,
>  	 * so we reset the core before registering for interrupts.
> @@ -1514,7 +1536,6 @@ nodma:
>  	size = QUP_INPUT_FIFO_SIZE(io_mode);
>  	qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
> 
> -	src_clk_freq = clk_get_rate(qup->clk);
>  	fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
>  	hs_div = 3;
>  	qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff); @@ -1534,6 +1555,8
> @@ nodma:
>  	qup->adap.dev.parent = qup->dev;
>  	qup->adap.dev.of_node = pdev->dev.of_node;
>  	qup->is_last = true;
> +	if (ACPI_HANDLE(qup->dev))
> +		ACPI_COMPANION_SET(&qup->adap.dev,
> ACPI_COMPANION(qup->dev));
    Can we move this inside the above check.
> 
>  	strlcpy(qup->adap.name, "QUP I2C adapter", sizeof(qup-
> >adap.name));
> 
> @@ -1639,6 +1662,13 @@ static const struct of_device_id
> qup_i2c_dt_match[] = {  };  MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
> 
> +#if IS_ENABLED(CONFIG_ACPI)
> +static const struct acpi_device_id qup_i2c_acpi_match[] = {
> +	{ "QCOM8010"},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_ids); #endif
>  static struct platform_driver qup_i2c_driver = {
>  	.probe  = qup_i2c_probe,
>  	.remove = qup_i2c_remove,
> @@ -1646,6 +1676,7 @@ static struct platform_driver qup_i2c_driver = {
>  		.name = "i2c_qup",
>  		.pm = &qup_i2c_qup_pm_ops,
>  		.of_match_table = qup_i2c_dt_match,
> +		.acpi_match_table = ACPI_PTR(qup_i2c_acpi_match),
 Should this also be in #if IS_ENABLED(CONFIG_ACPI) check ?

Regards,
 Sricharan



From maxime.ripard at free-electrons.com  Mon May  9 23:36:18 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Tue, 10 May 2016 08:36:18 +0200
Subject: [PATCH v4 01/11] clk: sunxi: Add display and TCON0 clocks driver
In-Reply-To: <20160509223924.GX3492@codeaurora.org>
References: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
 <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
 <20160506223002.GE3492@codeaurora.org>
 <20160508200308.GF6167@lukather>
 <20160509223238.GW3492@codeaurora.org>
 <20160509223924.GX3492@codeaurora.org>
Message-ID: <20160510063618.GI3733@lukather>

Hi Stephen,

On Mon, May 09, 2016 at 03:39:24PM -0700, Stephen Boyd wrote:
> On 05/09, Stephen Boyd wrote:
> > 
> > Ok I applied this one to clk-next.
> > 
> 
> And I squashed this in to silence the following checker warning.
> 
> drivers/clk/sunxi/clk-sun4i-display.c:110:33: warning: Variable
> length array is used.

Thanks, just out of curiosity, which checker are you talking about?
sparse?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160510/88855f6a/attachment.sig>

From adrian.hunter at intel.com  Mon May  9 23:32:36 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 09:32:36 +0300
Subject: [PATCH 01/23] mmc: sdhci: removed unneeded function wrappers
In-Reply-To: <5719FC89.9010404@intel.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-2-git-send-email-aisheng.dong@nxp.com>
 <5719FC89.9010404@intel.com>
Message-ID: <57318084.7020107@intel.com>

On 22/04/16 13:27, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> After commit d6463f170cf0 ("mmc: sdhci: Remove redundant runtime PM calls"),
>> some of original sdhci_do_xx() function wrappers becomes meaningless,
>> so remove them.
>>
>> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
> 
> Didn't apply cleanly, otherwise:
> 
> Acked-by: Adrian Hunter <adrian.hunter at intel.com>

Ulf, will you apply this one?



From linux.amoon at gmail.com  Mon May  9 23:43:12 2016
From: linux.amoon at gmail.com (Anand Moon)
Date: Tue, 10 May 2016 12:13:12 +0530
Subject: [PATCH] ARM: dts: exynos: Only Odroid XU3-family boards use DTSI
 with CPU thermal nodes
In-Reply-To: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>
References: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <CANAwSgT9SY3kj8+beMpc1xGoC=rMBSya+2v2dyZQp6ykH+V0=g@mail.gmail.com>

Hi Krzysztof ,

On 9 May 2016 at 11:49, Krzysztof Kozlowski <k.kozlowski at samsung.com> wrote:
> Include the CPU thermal nodes directly in Odroid XU3-family common DTS
> because it is the only user of it. Keeping it in separate DTSI node does
> not bring benefits because:
> 1. It is not re-usable on other non-fan boards (fan is referenced),
> 2. It won't be re-used on future Odroid XU board because different
>    CPU cluster behavior.
>
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---
>  arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi      | 103 ---------------------
>  arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |  94 ++++++++++++++++++-
>  2 files changed, 92 insertions(+), 105 deletions(-)
>  delete mode 100644 arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi
>
> diff --git a/arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi b/arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi
> deleted file mode 100644
> index 3e4c4ad96d63..000000000000
> --- a/arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi
> +++ /dev/null
> @@ -1,103 +0,0 @@
> -/*
> - * Device tree sources for Exynos5422 thermal zone
> - *
> - * Copyright (c) 2015 Lukasz Majewski <l.majewski at samsung.com>
> - *                     Anand Moon <linux.amoon at gmail.com>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - *
> - */
> -
> -#include <dt-bindings/thermal/thermal.h>
> -
> -/ {
> -       thermal-zones {
> -               cpu0_thermal: cpu0-thermal {
> -                       thermal-sensors = <&tmu_cpu0 0>;
> -                       polling-delay-passive = <250>;
> -                       polling-delay = <0>;
> -                       trips {
> -                               cpu_alert0: cpu-alert-0 {
> -                                       temperature = <50000>; /* millicelsius */
> -                                       hysteresis = <5000>; /* millicelsius */
> -                                       type = "active";
> -                               };
> -                               cpu_alert1: cpu-alert-1 {
> -                                       temperature = <60000>; /* millicelsius */
> -                                       hysteresis = <5000>; /* millicelsius */
> -                                       type = "active";
> -                               };
> -                               cpu_alert2: cpu-alert-2 {
> -                                       temperature = <70000>; /* millicelsius */
> -                                       hysteresis = <5000>; /* millicelsius */
> -                                       type = "active";
> -                               };
> -                               cpu_crit0: cpu-crit-0 {
> -                                       temperature = <120000>; /* millicelsius */
> -                                       hysteresis = <0>; /* millicelsius */
> -                                       type = "critical";
> -                               };
> -                               /*
> -                                * Exyunos542x support only 4 trip-points
> -                                * so for these polling mode is required.
> -                                * Start polling at temperature level of last
> -                                * interrupt-driven trip: cpu_alert2
> -                                */
> -                               cpu_alert3: cpu-alert-3 {
> -                                       temperature = <70000>; /* millicelsius */
> -                                       hysteresis = <10000>; /* millicelsius */
> -                                       type = "passive";
> -                               };
> -                               cpu_alert4: cpu-alert-4 {
> -                                       temperature = <85000>; /* millicelsius */
> -                                       hysteresis = <10000>; /* millicelsius */
> -                                       type = "passive";
> -                               };
> -
> -                       };
> -                       cooling-maps {
> -                               map0 {
> -                                    trip = <&cpu_alert0>;
> -                                    cooling-device = <&fan0 0 1>;
> -                               };
> -                               map1 {
> -                                    trip = <&cpu_alert1>;
> -                                    cooling-device = <&fan0 1 2>;
> -                               };
> -                               map2 {
> -                                    trip = <&cpu_alert2>;
> -                                    cooling-device = <&fan0 2 3>;
> -                               };
> -                               /*
> -                                * When reaching cpu_alert3, reduce CPU
> -                                * by 2 steps. On Exynos5422/5800 that would
> -                                * be: 1500 MHz and 1100 MHz.
> -                                */
> -                               map3 {
> -                                    trip = <&cpu_alert3>;
> -                                    cooling-device = <&cpu0 0 2>;
> -                               };
> -                               map4 {
> -                                    trip = <&cpu_alert3>;
> -                                    cooling-device = <&cpu4 0 2>;
> -                               };
> -
> -                               /*
> -                                * When reaching cpu_alert4, reduce CPU
> -                                * further, down to 600 MHz (11 steps for big,
> -                                * 7 steps for LITTLE).
> -                                */
> -                               map5 {
> -                                    trip = <&cpu_alert4>;
> -                                    cooling-device = <&cpu0 3 7>;
> -                               };
> -                               map6 {
> -                                    trip = <&cpu_alert4>;
> -                                    cooling-device = <&cpu4 3 11>;
> -                               };
> -                       };
> -               };
> -       };
> -};
> diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
> index 2a4e10bc8801..ff05041835e5 100644
> --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
> +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
> @@ -1,9 +1,11 @@
>  /*
>   * Hardkernel Odroid XU3 board device tree source
>   *
> - * Copyright (c) 2014 Collabora Ltd.
>   * Copyright (c) 2013 Samsung Electronics Co., Ltd.
>   *             http://www.samsung.com
> + * Copyright (c) 2014 Collabora Ltd.
> + * Copyright (c) 2015 Lukasz Majewski <l.majewski at samsung.com>
> + *                    Anand Moon <linux.amoon at gmail.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -16,7 +18,6 @@
>  #include <dt-bindings/sound/samsung-i2s.h>
>  #include "exynos5800.dtsi"
>  #include "exynos5422-cpus.dtsi"
> -#include "exynos5422-cpu-thermal.dtsi"
>
>  / {
>         memory {
> @@ -54,6 +55,95 @@
>                 #cooling-cells = <2>;
>                 cooling-levels = <0 130 170 230>;
>         };
> +
> +       thermal-zones {
> +               cpu0_thermal: cpu0-thermal {
> +                       thermal-sensors = <&tmu_cpu0 0>;
> +                       polling-delay-passive = <250>;
> +                       polling-delay = <0>;
> +                       trips {
> +                               cpu_alert0: cpu-alert-0 {
> +                                       temperature = <50000>; /* millicelsius */
> +                                       hysteresis = <5000>; /* millicelsius */
> +                                       type = "active";
> +                               };
> +                               cpu_alert1: cpu-alert-1 {
> +                                       temperature = <60000>; /* millicelsius */
> +                                       hysteresis = <5000>; /* millicelsius */
> +                                       type = "active";
> +                               };
> +                               cpu_alert2: cpu-alert-2 {
> +                                       temperature = <70000>; /* millicelsius */
> +                                       hysteresis = <5000>; /* millicelsius */
> +                                       type = "active";
> +                               };
> +                               cpu_crit0: cpu-crit-0 {
> +                                       temperature = <120000>; /* millicelsius */
> +                                       hysteresis = <0>; /* millicelsius */
> +                                       type = "critical";
> +                               };
> +                               /*
> +                                * Exynos542x supports only 4 trip-points
> +                                * so for these polling mode is required.
> +                                * Start polling at temperature level of last
> +                                * interrupt-driven trip: cpu_alert2
> +                                */
> +                               cpu_alert3: cpu-alert-3 {
> +                                       temperature = <70000>; /* millicelsius */
> +                                       hysteresis = <10000>; /* millicelsius */
> +                                       type = "passive";
> +                               };
> +                               cpu_alert4: cpu-alert-4 {
> +                                       temperature = <85000>; /* millicelsius */
> +                                       hysteresis = <10000>; /* millicelsius */
> +                                       type = "passive";
> +                               };
> +
> +                       };
> +                       cooling-maps {
> +                               map0 {
> +                                    trip = <&cpu_alert0>;
> +                                    cooling-device = <&fan0 0 1>;
> +                               };
> +                               map1 {
> +                                    trip = <&cpu_alert1>;
> +                                    cooling-device = <&fan0 1 2>;
> +                               };
> +                               map2 {
> +                                    trip = <&cpu_alert2>;
> +                                    cooling-device = <&fan0 2 3>;
> +                               };
> +                               /*
> +                                * When reaching cpu_alert3, reduce CPU
> +                                * by 2 steps. On Exynos5422/5800 that would
> +                                * be: 1500 MHz and 1100 MHz.
> +                                */
> +                               map3 {
> +                                    trip = <&cpu_alert3>;
> +                                    cooling-device = <&cpu0 0 2>;
> +                               };
> +                               map4 {
> +                                    trip = <&cpu_alert3>;
> +                                    cooling-device = <&cpu4 0 2>;
> +                               };
> +
> +                               /*
> +                                * When reaching cpu_alert4, reduce CPU
> +                                * further, down to 600 MHz (11 steps for big,
> +                                * 7 steps for LITTLE).
> +                                */
> +                               map5 {
> +                                    trip = <&cpu_alert4>;
> +                                    cooling-device = <&cpu0 3 7>;
> +                               };
> +                               map6 {
> +                                    trip = <&cpu_alert4>;
> +                                    cooling-device = <&cpu4 3 11>;
> +                               };
> +                       };
> +               };
> +       };
> +
>  };
>
>  &bus_wcore {
> --
> 1.9.1
>

Could you defer this patch, during my testing with pm-qa from linaro.

git://git.linaro.org/tools/pm-qa.git

When their is running of thermal test case cpu usage reaches around
300+ percentage
and some time's the Odroid XU4 hang down.
-------------------------------------------------------------------------
[ 1028.056619] CPU4: shutdown
[ 1148.510372] IRQ54 no longer affine to CPU5
[ 1148.511864] CPU5: shutdown
[ 1268.921073] IRQ55 no longer affine to CPU6
[ 1268.922564] CPU6: shutdown
[ 1389.271930] cpu cpu4: Failed to find opp_table: -19
[ 1389.301668] IRQ56 no longer affine to CPU7
[ 1389.303132] CPU7: shutdown
[ 1510.538424] cpu cpu4: opp_list_debug_create_link: Failed to create link
[ 1510.543762] cpu cpu4: _add_opp_dev: Failed to register opp debugfs (-12)
[ 1510.550625] cpu cpu7: opp_list_debug_create_link: Failed to create link
[ 1510.557037] cpu cpu7: _add_opp_dev: Failed to register opp debugfs (-12)
[ 1510.664649] cpu cpu5: cpufreq_init: failed to get clk: -2
[ 1510.720567] cpu cpu6: cpufreq_init: failed to get clk: -2
[ 1510.788280] cpu cpu7: cpufreq_init: failed to get clk: -2
root at odroidxu4l:/home/odroid/study/linaro/pm-qa# killall heat_cpu

-------------------------------------------------------------------------
And some time I observed that the board will poweroff on reaching
temperature 120 degree C.
when I am compiling the kernel with or above. make -j8
-------------------------------------------------------------------------
root at odroidxu4l:~#  * Starting NTP server ntpd                           [ OK ]
saned disabled; edit /etc/default/saned
[ 4118.924470] thermal thermal_zone3: critical temperature reached(121
C),shutting down
[ 4119.014327] thermal thermal_zone3: critical temperature reached(121
C),shutting down

Broadcast message from root at odroidxu4l
        (unknown) at 20:41 ...

The system is going down for power off NOW!

Broadcast message from root at odroidxu4l
        (unknown) at 20:41 ...

The system is going down for power off NOW!
[ 4119.431386] thermal thermal_zone3: critical temperature reached(121
C),shutting down
[ 4120.206709] thermal thermal_zone3: critical temperature reached(120
C),shutting down

Broadcast message from root at odroidxu4l
        (unknown) at 20:41 ...

The system is going down for power off NOW!
wait-for-state stop/waiting
[ 4157.574406] reboo

U-Boot 2016.03-00665-g563d8d9-dirty (Apr 04 2016 - 22:27:07 +0930) for
ODROID-XU3

CPU:   Exynos5422 @ 800 MHz
Model: Odroid XU3 based on EXYNOS5422
Board: Odroid XU3 based on EXYNOS5422
Type:  xu4
DRAM:  2 GiB
MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
*** Warning - bad CRC, using default environment
-------------------------------------------------------------------------
Once the thermal issue is fixed we can redo this changes.

Best Regards
-Anand Moon


From adrian.hunter at intel.com  Mon May  9 23:51:31 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 09:51:31 +0300
Subject: [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during
 no data transfer
In-Reply-To: <1460741387-23815-10-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-10-git-send-email-aisheng.dong@nxp.com>
Message-ID: <573184F3.50201@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> Current code will report the wrong data interrupt got when no
> data operation in progress assumed by getting !host->data in
> sdhci_data_irq().
> 
> For a data command handling process, the driver will call
> sdhci_finish_data() and clear host->data in case any data error,
> then card finish_tasklet will do the rest controller reset work.
> 
> Before the tasklet got run, however, controllers may report the
> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
> than data CRC error and data end bit error interrupts for single
> block transfer or the last block of multiblock transfer.
> 
> Controller usually detects and generates data CRC/end bit error
> interrupts once one block on the bus is transferred completely.
> For single block transfer, since there's only one bock to transfer,
> the controller will report transfer complete interrupt as well,
> but until the data in controller FIFO has been successfully
> transferred to memory. The time gap of TC and CRC interrupt depends on
> the system busy state at that point and memory bus access speed.
> 
> So it is possible when TC interrupt generated, host->data is already
> equal to NULL due to cleared by former CRC/Data End Bit error which
> is reasonable.
> 
> Thus we DO NOT report the weird data interrupt event for this case.
> 
> Else we may easily see warning below during SD3.0 card manually tuning
> process (calling mmc_send_tuning() which is a single block transfer)
> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
> 
> The detailed command log is as follows:
> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
> [ 1657.929995] sdhci: ===========================================
> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
> [ 1657.930179] mmc0:     0 bytes transferred: -84
> 
> It shows we first have a data CRC error interrupt then a data transfer
> complete interrupt.
> Then we got the !host->data case in sdhci_data_irq().
> 
> CC: stable <stable at vger.kernel.org>
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
> ---
>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 40e3551..2eb0e34 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>  			}
>  		}
>  
> +		/*
> +		 * The "data complete" interrupt is possible to happen a bit
> +		 * later than CRC error and data end bit error interrupts
> +		 * separately for single block transfer or the last block of
> +		 * multiblock transfer. For this case, we DO NOT report the
> +		 * weird data interrupt event.
> +		 */
> +		if ((intmask & SDHCI_INT_DATA_END) &&
> +		    (host->mrq && host->mrq->data && host->mrq->data->error))
> +			return;

This could be generalized a bit more i.e. what about:

		/*
		 * After an error and before the the data circuit is reset in
		 * sdhci_tasklet_finish, we could get more interrupts, but we
		 * already have an error, so ignore them.
		 */
		if (host->mrq && host->mrq->data && host->mrq->data->error)
			return;

> +
>  		pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
>  		       mmc_hostname(host->mmc), (unsigned)intmask);
>  		sdhci_dumpregs(host);
> 



From adrian.hunter at intel.com  Mon May  9 23:55:56 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 09:55:56 +0300
Subject: [PATCH 10/23] mmc: core: disable auto retune during card
 detection process
In-Reply-To: <20160429074258.GA28427@shlinux2.ap.freescale.net>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-11-git-send-email-aisheng.dong@nxp.com>
 <571A1D85.3020200@intel.com>
 <CAA+hA=R9JfV4ScuM=OZ3VHdSiQiMO9io8mQQDNXfkTwNv7RVvg@mail.gmail.com>
 <5721B602.6010306@intel.com>
 <20160428132249.GB27560@shlinux2.ap.freescale.net>
 <57230515.9030602@intel.com>
 <20160429074258.GA28427@shlinux2.ap.freescale.net>
Message-ID: <573185FC.5060506@intel.com>

On 29/04/16 10:42, Dong Aisheng wrote:
> And IMX6DL ARD is even worser due to it's using common
> mmc_send_tuning() function.
> root at imx6qdlsolo:~# 
> root at imx6qdlsolo:~# [  129.462564] sysrq: SysRq : Changing Loglevel
> [  129.466902] sysrq: Loglevel set to 8
> [  131.616078] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
> [  131.625311] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
> [  131.632133] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
> [  131.642121] mmc0: starting CMD13 arg 59b40000 flags 00000195
> [  131.648925] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x0 ESDHC_TUNE_CTRL_STATUS 0x0
> [  131.657818] mmc0: starting CMD19 arg 00000000 flags 00000035
> [  131.663518] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
> [  131.670835] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000

You should stop here because -123 is -ENOMEDIUM



From gregkh at linuxfoundation.org  Tue May 10 00:10:04 2016
From: gregkh at linuxfoundation.org (Greg KH)
Date: Tue, 10 May 2016 09:10:04 +0200
Subject: [GIT PULL] move ARM LCD display driver to auxdisplay
In-Reply-To: <CACRpkdZwPVMx-dXVkfVwFN0juzVuyvShV7yDWbUFSXOPE=uUrw@mail.gmail.com>
References: <CACRpkdbyO0axd5ergYZcXO302f2fFAPKrSNevkvreP1kRjm-vw@mail.gmail.com>
 <20160425115758.GA4874@lukather>
 <CACRpkdb=s5onVa7qND9nFUtYPw5H-Hdr7Ja5o3=-9+wxghHekQ@mail.gmail.com>
 <20160428092608.GE17159@lukather> <5723755D.9060108@ti.com>
 <20160509090615.6272f8ca@erd979>
 <CACRpkdbZmL9Cqp-ubzyxd7fWUFOVsS1DCxsfG02kSpbWu_rbZQ@mail.gmail.com>
 <20160509161728.3aee1134@erd979>
 <CACRpkdZwPVMx-dXVkfVwFN0juzVuyvShV7yDWbUFSXOPE=uUrw@mail.gmail.com>
Message-ID: <20160510071004.GA7318@kroah.com>

On Mon, May 09, 2016 at 04:27:00PM +0200, Linus Walleij wrote:
> On Mon, May 9, 2016 at 4:17 PM, Robin van der Gracht <robin at protonic.nl> wrote:
> > On Mon, 9 May 2016 15:19:26 +0200
> > Linus Walleij <linus.walleij at linaro.org> wrote:
> >
> >> On Mon, May 9, 2016 at 9:06 AM, Robin van der Gracht
> >> <robin at protonic.nl> wrote:
> >>
> >> > If you guys feel like auxdisplay is not the right subsystem for the
> >> > driver, and would like me to move it, please share.
> >>
> >> The best would be if you volunteer to maintain it and bring
> >> it forward.
> >
> > Thats fine. Would it suffice if I submit another patch adding myself
> > to the maintainers file?
> 
> That's half of it, if Miguel does not come back then his name
> should be removed as the second step.
> 
> You also need to have an idea on a path to funnel accumulated
> patches upstream to Torvalds. The recent patches to this
> subsystem were funneled by Greg, so we should ask him how
> he prefer to proceed.
> 
> Greg, what do you prefer?

I don't care :)

I can keep doing this, sending stuff to Linus through my char/misc tree,
or it can go through someone else's tree, it doesn't bother me...

thanks,

greg k-h


From sricharan at codeaurora.org  Tue May 10 00:13:21 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Tue, 10 May 2016 12:43:21 +0530
Subject: [PATCH 2/2] i2c: qup: support SMBus block read
In-Reply-To: <1462317959-11632-2-git-send-email-nkaje@codeaurora.org>
References: <1462317959-11632-1-git-send-email-nkaje@codeaurora.org>
 <1462317959-11632-2-git-send-email-nkaje@codeaurora.org>
Message-ID: <000b01d1aa8b$7317a300$5946e900$@codeaurora.org>

+additional lists

> I2C QUP driver relies on SMBus emulation support from the framework.
> To handle SMBus block reads, the driver should check I2C_M_RECV_LEN flag
> and should read the first byte received as the message length.
> 
> The driver configures the QUP hardware to read one byte. Once the message
> length is known from this byte, the QUP hardware is configured to read the
> rest.
> 
> Signed-off-by: Naveen Kaje <nkaje at codeaurora.org>
> ---
>  drivers/i2c/busses/i2c-qup.c | 95 ++++++++++++++++++++++++++++++-------
> -------
>  1 file changed, 66 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index
> ef31b26..2658b67 100644
> --- a/drivers/i2c/busses/i2c-qup.c
> +++ b/drivers/i2c/busses/i2c-qup.c
> @@ -526,38 +526,49 @@ static int qup_i2c_set_tags(u8 *tags, struct
> qup_i2c_dev *qup,
> 
>  	int last = (qup->blk.pos == (qup->blk.count - 1)) && (qup->is_last);
> 
> -	if (qup->blk.pos == 0) {
> -		tags[len++] = QUP_TAG_V2_START;
> -		tags[len++] = addr & 0xff;
> +	/* Handle SMBus block data read */
> +	if ((msg->flags & I2C_M_RD) && (msg->flags & I2C_M_RECV_LEN)
> &&
> +	    (msg->len > 1)) {
> +		tags[len++] = QUP_TAG_V2_DATARD_STOP;
> +		data_len = qup_i2c_get_data_len(qup);
> +		tags[len++] = data_len - 1;
> +	} else {
> +		if (qup->blk.pos == 0) {
> +			tags[len++] = QUP_TAG_V2_START;
> +			tags[len++] = addr & 0xff;
> 
> -		if (msg->flags & I2C_M_TEN)
> -			tags[len++] = addr >> 8;
> -	}
> +			if (msg->flags & I2C_M_TEN)
> +				tags[len++] = addr >> 8;
> +		}
> 
> -	/* Send _STOP commands for the last block */
> -	if (last) {
> -		if (msg->flags & I2C_M_RD)
> -			tags[len++] = QUP_TAG_V2_DATARD_STOP;
> -		else
> -			tags[len++] = QUP_TAG_V2_DATAWR_STOP;
> -	} else {
> -		if (msg->flags & I2C_M_RD)
> +		/* Send _STOP commands for the last block */
> +		if ((msg->flags & I2C_M_RD)
> +			&& (msg->flags & I2C_M_RECV_LEN)) {
>  			tags[len++] = QUP_TAG_V2_DATARD;
> -		else
> -			tags[len++] = QUP_TAG_V2_DATAWR;
> -	}
> +		} else if (last) {
> +			if (msg->flags & I2C_M_RD)
> +				tags[len++] = QUP_TAG_V2_DATARD_STOP;
> +			else
> +				tags[len++] = QUP_TAG_V2_DATAWR_STOP;
> +		} else {
> +			if (msg->flags & I2C_M_RD)
> +				tags[len++] = QUP_TAG_V2_DATARD;
> +			else
> +				tags[len++] = QUP_TAG_V2_DATAWR;
> +		}
> 
> -	data_len = qup_i2c_get_data_len(qup);
> +		data_len = qup_i2c_get_data_len(qup);
> 
> -	/* 0 implies 256 bytes */
> -	if (data_len == QUP_READ_LIMIT)
> -		tags[len++] = 0;
> -	else
> -		tags[len++] = data_len;
> +		/* 0 implies 256 bytes */
> +		if (data_len == QUP_READ_LIMIT)
> +			tags[len++] = 0;
> +		else
> +			tags[len++] = data_len;
> 
> -	if ((msg->flags & I2C_M_RD) && last && is_dma) {
> -		tags[len++] = QUP_BAM_INPUT_EOT;
> -		tags[len++] = QUP_BAM_FLUSH_STOP;
> +		if ((msg->flags & I2C_M_RD) && last && is_dma) {
> +			tags[len++] = QUP_BAM_INPUT_EOT;
> +			tags[len++] = QUP_BAM_FLUSH_STOP;
> +		}
>  	}
> 
   Will it look simpler if we add a qup_i2c_set_tags_smb instead and add an
   Comment ? Here it is not clear how this is different from a normal read.

<snip..>

> +
> +		/* Handle SMBus block read length */
> +		if ((msg->flags & I2C_M_RECV_LEN) && (msg->len == 1)) {
> +			if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
> +				ret = -EPROTO;
> +				goto err;
> +			}
> +			msg->len += msg->buf[0];
> +			qup->pos = 0;
> +			qup_i2c_set_read_mode_v2(qup, msg->len);
> +			qup_i2c_issue_xfer_v2(qup, msg);
> +			ret = qup_i2c_wait_for_complete(qup, msg);
> +			if (ret)
> +				goto err;
> +			qup_i2c_set_blk_data(qup, msg);
> +		}
>  	} while (qup->blk.pos < qup->blk.count);
       
         When v2 mode is not supported this should return an error,
         in qup_i2c_xfer for msg->flags & I2C_M_RECV_LEN

Regards,
 Sricharan



From daniel.lezcano at linaro.org  Tue May 10 00:18:49 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 10 May 2016 09:18:49 +0200
Subject: [PATCH] firmware/drivers/psci: Fix unused functions when
 CONFIG_CPU_IDLE=n
Message-ID: <1462864729-11793-1-git-send-email-daniel.lezcano@linaro.org>

On the ARM64 architecture, when CPUIDLE is not set in the configuration,
the compilation raises a couple of warnings:

drivers/firmware/psci.c:70:12: warning: 'psci_pd_power_off' defined but not used [-Wunused-function]
drivers/firmware/psci.c:273:12: warning: 'psci_set_suspend_mode_osi' defined but not used [-Wunused-function]

Fix those warnings by moving the functions inside the #ifdef CONFIG_CPU_IDLE
section.

Signed-off-by: Daniel Lezcano <daniel.lezcano at linaro.org>
---
 drivers/firmware/psci.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 9c6a1f9..d7e0632 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -54,7 +54,6 @@
  */
 static int resident_cpu = -1;
 static bool psci_has_osi_pd;
-static bool psci_suspend_mode_is_osi;
 static DEFINE_PER_CPU(u32, cluster_state_id);
 
 static inline u32 psci_get_composite_state_id(u32 cpu_state)
@@ -67,13 +66,6 @@ static inline void psci_reset_composite_state_id(void)
 	this_cpu_write(cluster_state_id, 0);
 }
 
-static int psci_pd_power_off(u32 state_idx, u32 param,
-		const struct cpumask *mask)
-{
-	__this_cpu_add(cluster_state_id, param);
-	return 0;
-}
-
 bool psci_tos_resident_on(int cpu)
 {
 	return cpu == resident_cpu;
@@ -270,6 +262,11 @@ static int __init psci_features(u32 psci_func_id)
 			      psci_func_id, 0, 0);
 }
 
+#ifdef CONFIG_CPU_IDLE
+static bool psci_suspend_mode_is_osi;
+
+static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
+
 static int psci_set_suspend_mode_osi(bool enable)
 {
 	int ret;
@@ -290,8 +287,12 @@ static int psci_set_suspend_mode_osi(bool enable)
 	return psci_to_linux_errno(ret);
 }
 
-#ifdef CONFIG_CPU_IDLE
-static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
+static int psci_pd_power_off(u32 state_idx, u32 param,
+		const struct cpumask *mask)
+{
+	__this_cpu_add(cluster_state_id, param);
+	return 0;
+}
 
 static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
 {
-- 
1.9.1



From nicolas.ferre at atmel.com  Tue May 10 00:27:29 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Tue, 10 May 2016 09:27:29 +0200
Subject: [GIT PULL] at91: fixes for 4.6 #1
Message-ID: <1462865249-28552-1-git-send-email-nicolas.ferre@atmel.com>

Arnd, Olof, Kevin,

Here is a late fix for AT91. Sorry to have figure it out so late in the
development cycle but we had to confirm it was an error with the documentation
of two products.
So, as the compatibility string is in since 4.6-rc1 and that the previous one
works okay, it's a good opportunity to switch back to the one that works without
introducing a intermediary bug.
The revert on driver code and the removal of the useless additional
compatibility string will be queued for 4.7 through NAND/MTD.

Thanks, best regards,

The following changes since commit 02da2d72174c61988eb4456b53f405e3ebdebce4:

  Linux 4.6-rc5 (2016-04-24 16:17:05 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91.git tags/at91-fixes

for you to fetch changes up to b8453d4ee9e24c6590dd0eecbab1c3cc2028317f:

  ARM: dts: at91: sama5d2: use "atmel,sama5d3-nfc" compatible for nfc (2016-05-10 09:09:47 +0200)

----------------------------------------------------------------
One fix for 4.6:
- error in the documentation led to wrongly add a new NAND Flash Controller
  type. Switch back to the previous compatible one.

----------------------------------------------------------------
Wenyou Yang (1):
      ARM: dts: at91: sama5d2: use "atmel,sama5d3-nfc" compatible for nfc

 arch/arm/boot/dts/sama5d2.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

-- 
Nicolas Ferre


From eric.auger at linaro.org  Tue May 10 00:34:56 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 09:34:56 +0200
Subject: [PATCH v9 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part
 2/3: msi changes
In-Reply-To: <50F1DA1B-3760-474F-A401-43AA26A5F6B6@caviumnetworks.com>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
 <9C17BA6B-7304-47CA-A287-77FB41D96AD3@caviumnetworks.com>
 <573040D6.9050803@linaro.org>
 <50F1DA1B-3760-474F-A401-43AA26A5F6B6@caviumnetworks.com>
Message-ID: <57318F20.4010103@linaro.org>

Hi Chalamarla,
> On 5/9/16, 12:48 AM, "Eric Auger" <eric.auger at linaro.org> wrote:
> 
>> Hi Chalarmala,
>> On 05/05/2016 07:44 PM, Chalamarla, Tirumalesh wrote:
>>> Hi Eric,
>>>
>>> Does this series supports gicv3-its emulation?
>>> Do we have a tree with all the dependent patches
>> GICv3 ITS emulation support comes with:
>> [PATCH v4 00/12] KVM: arm64: GICv3 ITS emulation
>> http://permalink.gmane.org/gmane.comp.emulators.kvm.arm.devel/5738
>>
>> My series just allows PCI device MSI transactions to reach the host MSI
>> frame through the SMMU. Only host GICv2m has been tested at the moment
>> with a guest exposed with a GICv2m too.
> 
> 
> I wanted to test this series on Cavium Thunder, but the only mode supported is Gicv3 with ITS, is there a chance 
> That I get a tree with all the dependencies?
I can prepare a kernel tree with all the dependencies including ITS
patches supporting get_doorbell_info.

Then on userspace side:
- do you plan to use QEMU?
- then can you expose your guest with a GICv3 + v2m? I think this should
work.

exposing ITS to the guest requires a respin of Pavel's series:
[Qemu-devel] [RFC PATCH v3 0/5] vITS support
(https://lists.gnu.org/archive/html/qemu-devel/2015-11/msg05197.html)
and has more complex kernel dependencies.

I think exposing the guest with GICv3 + v2m should work

Best Regards

Eric
>>> Thanks,
>>> Tirumalesh. 
>>> On 5/4/16, 8:18 AM, "linux-arm-kernel on behalf of Eric Auger" <linux-arm-kernel-bounces at lists.infradead.org on behalf of eric.auger at linaro.org> wrote:
>>>
>>>> This series implements the MSI address mapping/unmapping in the MSI layer.
>>>> IOMMU binding happens on pci_enable_msi since this function can sleep and
>>>> return errors. On msi_domain_set_affinity, msi_domain_(de)activate, which
>>>> are not allowed to sleep, we simply look for the already existing binding.
>>>>
>>>> A new MSI domain info flag value is introduced to report whether the msi
>>>> domain implements IRQ remapping. GIC v3 ITS is the first MSI controller
>>>> advertising it. This flag value will be used by VFIO subsystem to
>>>> determine whether MSI forwarding is safe.
>>>>
>>>> More details & context can be found at:
>>>> http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/
>>>>
>>>> Best Regards
>>>>
>>>> Eric
>>>>
>>>> Applies on top of PART 1/3. Also depends on
>>>> [PATCH 1/3] iommu: Add MMIO mapping type,
>>>> http://comments.gmane.org/gmane.linux.kernel.iommu/12869
>>>>
>>>> Git: complete series available at
>>>> https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc6-pcie-passthrough-v9-msi-v9
>>>>
>>>> This branch contains all parts in v9.
>>>>
>>>> History:
>>>>
>>>> v8 -> v9:
>>>> - use a union in irq_chip_msi_doorbell_info + boolean telling whether the
>>>>  doorbell is percpu
>>>> - decouple irq_data parsing from the actual mapping/unmapping in
>>>>  msi_handle_doorbell_mappings
>>>> - fix misc style issues
>>>>
>>>> v7 -> v8:
>>>> take into account Marc's comments:
>>>> - use iommu_msi_msg_pa_to_va with new proto
>>>> - change in irq_chip_msi_doorbell_info struct definition:
>>>>  prot and size became shared between all doorbells and phys_addr_t __percpu
>>>> - cleanups in v2m irqchip
>>>> - eventually did not touch MSI_FLAG_IRQ_REMAPPING naming
>>>> - On msi_handle_doorbell_mappings, stop on the first irqchip where doorbells
>>>>  can be found
>>>> - fix resource deallocation on mapping failure in msi_domain_alloc_irqs
>>>>
>>>> v6 -> v7:
>>>> - do alloc/map handling on pci_enable_msi and search on msi_(de)domain_activate
>>>> - add msi_doorbell_info callback in irq-chip to retrieve the characteristics
>>>>  of doorbells
>>>>
>>>> RFC v5 -> patch v6:
>>>> - split to ease the review process
>>>> - rebase on default iommu domain code (irq_data_to_msi_mapping_domain
>>>>  checks IOMMU_DOMAIN_DMA type)
>>>> - fix unmap sequence on msi_domain_set_affinity (reported by Marc):
>>>>  unmap the previous doorbell when the new one has been mapped & written to
>>>>  the device, ie. irq_chip_write_msi_msg.
>>>> - "msi: msi_compose wrapper removed" following change above
>>>> - add size parameter to iommu_get_reserved_iova API following Marc's request
>>>>
>>>> RFC v4 -> RFC v5:
>>>> - take into account Thomas' comments on MSI related patches
>>>>  - split "msi: IOMMU map the doorbell address when needed"
>>>>  - increase readability and add comments
>>>>  - fix style issues
>>>> - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
>>>> - platform ITS now advertises IOMMU_CAP_INTR_REMAP
>>>> - fix compilation issue with CONFIG_IOMMU API unset
>>>> - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING
>>>>
>>>> RFC v3 -> v4:
>>>> - Move doorbell mapping/unmapping in msi.c
>>>> - fix ref count issue on set_affinity: in case of a change in the address
>>>>  the previous address is decremented
>>>> - doorbell map/unmap now is done on msi composition. Should allow the use
>>>>  case for platform MSI controllers
>>>> - create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
>>>>  to reserved IOVA management (looking like dma-iommu glue)
>>>> - series reordering to ease the review:
>>>>  - first part is related to IOMMU
>>>>  - second related to MSI sub-system
>>>>  - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
>>>> - expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
>>>>  [this partially addresses Marc's comments on iommu_get/put_single_reserved
>>>>   size/alignment problematic - which I did not ignore - but I don't know
>>>>   how much I can do at the moment]
>>>>
>>>> RFC v2 -> RFC v3:
>>>> - should fix wrong handling of some CONFIG combinations:
>>>>  CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
>>>> - fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)
>>>>
>>>> PATCH v1 -> RFC v2:
>>>> - reverted to RFC since it looks more reasonable ;-) the code is split
>>>>  between VFIO, IOMMU, MSI controller and I am not sure I did the right
>>>>  choices. Also API need to be further discussed.
>>>> - iova API usage in arm-smmu.c.
>>>> - MSI controller natively programs the MSI addr with either the PA or IOVA.
>>>>  This is not done anymore in vfio-pci driver as suggested by Alex.
>>>> - check irq remapping capability of the group
>>>>
>>>> RFC v1 [2] -> PATCH v1:
>>>> - use the existing dma map/unmap ioctl interface with a flag to register a
>>>>  reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
>>>> - a single reserved IOVA contiguous region now is allowed
>>>> - use of an RB tree indexed by PA to store allocated reserved slots
>>>> - use of a vfio_domain iova_domain to manage iova allocation within the
>>>>  window provided by the userspace
>>>> - vfio alloc_map/unmap_free take a vfio_group handle
>>>> - vfio_group handle is cached in vfio_pci_device
>>>> - add ref counting to bindings
>>>> - user modality enabled at the end of the series
>>>>
>>>>
>>>> Eric Auger (8):
>>>>  genirq/msi: Add a new MSI_FLAG_IRQ_REMAPPING flag
>>>>  irqchip/gic-v3-its: ITS advertises MSI_FLAG_IRQ_REMAPPING
>>>>  genirq/msi: export msi_get_domain_info
>>>>  genirq/msi: msi_compose wrapper
>>>>  genirq/irq: introduce msi_doorbell_info
>>>>  irqchip/gicv2m: implement msi_doorbell_info callback
>>>>  genirq/msi: map/unmap the MSI doorbells on msi_domain_alloc/free_irqs
>>>>  genirq/msi: use the MSI doorbell's IOVA when requested
>>>>
>>>> drivers/irqchip/irq-gic-v2m.c                 |  16 +++
>>>> drivers/irqchip/irq-gic-v3-its-pci-msi.c      |   3 +-
>>>> drivers/irqchip/irq-gic-v3-its-platform-msi.c |   3 +-
>>>> include/linux/irq.h                           |  15 ++-
>>>> include/linux/msi.h                           |   2 +
>>>> kernel/irq/msi.c                              | 136 +++++++++++++++++++++++---
>>>> 6 files changed, 161 insertions(+), 14 deletions(-)
>>>>
>>>> -- 
>>>> 1.9.1
>>>>
>>>>
>>>> _______________________________________________
>>>> linux-arm-kernel mailing list
>>>> linux-arm-kernel at lists.infradead.org
>>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>



From bamvor.zhangjian at huawei.com  Tue May 10 00:42:07 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Tue, 10 May 2016 15:42:07 +0800
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <20160506123731.GA11959@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1459894127-17698-21-git-send-email-ynorov@caviumnetworks.com>
 <572C8B30.7000005@huawei.com> <20160506123731.GA11959@yury-N73SV>
Message-ID: <573190CF.6030408@huawei.com>

Hi, Yury

On 2016/5/6 20:37, Yury Norov wrote:
> On Fri, May 06, 2016 at 08:16:48PM +0800, Zhangjian (Bamvor) wrote:
>> Hi,
>>
>> On 2016/4/6 6:08, Yury Norov wrote:
>>> From: Andrew Pinski <apinski at cavium.com>
>>>
>>> Add a separate syscall-table for ILP32, which dispatches either to native
>>> LP64 system call implementation or to compat-syscalls, as appropriate.
>>>
>>> Signed-off-by: Andrew Pinski <Andrew.Pinski at caviumnetworks.com>
>>> Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
>>> ---
>>>   arch/arm64/include/asm/unistd.h | 11 ++++++-
>>>   arch/arm64/kernel/Makefile      |  2 +-
>>>   arch/arm64/kernel/entry.S       | 12 +++++++-
>>>   arch/arm64/kernel/sys_ilp32.c   | 65 +++++++++++++++++++++++++++++++++++++++++
>>>   4 files changed, 87 insertions(+), 3 deletions(-)
>>>   create mode 100644 arch/arm64/kernel/sys_ilp32.c
>>>
>>> diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
>>> index 2971dea..5ea18ef 100644
>>> --- a/arch/arm64/include/asm/unistd.h
>>> +++ b/arch/arm64/include/asm/unistd.h
>>> @@ -13,9 +13,18 @@
>>>    * You should have received a copy of the GNU General Public License
>>>    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>>    */
>>> +
>>> +#ifdef CONFIG_COMPAT
>>> +#define __ARCH_WANT_COMPAT_STAT64
>>> +#endif
>>> +
>>> +#ifdef CONFIG_ARM64_ILP32
>>> +#define __ARCH_WANT_COMPAT_SYS_PREADV64
>>> +#define __ARCH_WANT_COMPAT_SYS_PWRITEV64
>>> +#endif
>>> +
>>>   #ifdef CONFIG_AARCH32_EL0
>>>   #define __ARCH_WANT_COMPAT_SYS_GETDENTS64
>>> -#define __ARCH_WANT_COMPAT_STAT64
>>>   #define __ARCH_WANT_SYS_GETHOSTNAME
>>>   #define __ARCH_WANT_SYS_PAUSE
>>>   #define __ARCH_WANT_SYS_GETPGRP
>>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>>> index 9dfdf86..7aa65ea 100644
>>> --- a/arch/arm64/kernel/Makefile
>>> +++ b/arch/arm64/kernel/Makefile
>>> @@ -28,7 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
>>>   arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
>>>   					   sys_compat.o entry32.o		\
>>>   					   ../../arm/kernel/opcodes.o binfmt_elf32.o
>>> -arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
>>> +arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o
>>>   arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
>>>   arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
>>>   arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
>>> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
>>> index cf4d1ae..1f7a145 100644
>>> --- a/arch/arm64/kernel/entry.S
>>> +++ b/arch/arm64/kernel/entry.S
>>> @@ -715,9 +715,13 @@ ENDPROC(ret_from_fork)
>>>    */
>>>   	.align	6
>>>   el0_svc:
>>> -	adrp	stbl, sys_call_table		// load syscall table pointer
>>>   	uxtw	scno, w8			// syscall number in w8
>>>   	mov	sc_nr, #__NR_syscalls
>>> +#ifdef CONFIG_ARM64_ILP32
>>> +	ldr	x16, [tsk, #TI_FLAGS]
>>> +	tbnz	x16, #TIF_32BIT_AARCH64, el0_ilp32_svc // We are using ILP32
>>> +#endif
>>> +	adrp	stbl, sys_call_table		// load syscall table pointer
>>>   el0_svc_naked:					// compat entry point
>>>   	stp	x0, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
>>>   	enable_dbg_and_irq
>>> @@ -737,6 +741,12 @@ ni_sys:
>>>   	b	ret_fast_syscall
>>>   ENDPROC(el0_svc)
>>>
>>> +#ifdef CONFIG_ARM64_ILP32
>>> +el0_ilp32_svc:
>>> +	adrp	stbl, sys_call_ilp32_table // load syscall table pointer
>>> +	b el0_svc_naked
>>> +#endif
>>> +
>>>   	/*
>>>   	 * This is the really slow path.  We're going to be doing context
>>>   	 * switches, and waiting for our parent to respond.
>>> diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
>>> new file mode 100644
>>> index 0000000..0996d8e
>>> --- /dev/null
>>> +++ b/arch/arm64/kernel/sys_ilp32.c
>>> @@ -0,0 +1,65 @@
>>> +/*
>>> + * AArch64- ILP32 specific system calls implementation
>>> + *
>>> + * Copyright (C) 2016 Cavium Inc.
>>> + * Author: Andrew Pinski <apinski at cavium.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * 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/compiler.h>
>>> +#include <linux/errno.h>
>>> +#include <linux/fs.h>
>>> +#include <linux/mm.h>
>>> +#include <linux/msg.h>
>>> +#include <linux/export.h>
>>> +#include <linux/sched.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/syscalls.h>
>>> +#include <linux/compat.h>
>>> +#include <asm-generic/syscalls.h>
>>> +
>>> +/* Using non-compat syscalls where necessary */
>>> +#define compat_sys_fadvise64_64        sys_fadvise64_64
>>> +#define compat_sys_fallocate           sys_fallocate
>>> +#define compat_sys_ftruncate64         sys_ftruncate
>>> +#define compat_sys_lookup_dcookie      sys_lookup_dcookie
>>> +#define compat_sys_pread64             sys_pread64
>>> +#define compat_sys_pwrite64            sys_pwrite64
>>> +#define compat_sys_readahead           sys_readahead
>>> +#define compat_sys_shmat               sys_shmat
>>> +#define compat_sys_sync_file_range     sys_sync_file_range
>>> +#define compat_sys_truncate64          sys_truncate
>>> +#define sys_llseek                     sys_lseek
>>> +#define sys_mmap2		       sys_mmap
>> I am a little bit confused here. We wrap the mmap to mmap2 in glibc
>> without shift the 4096 and We map mmap2 to mmap in kernel which
>> means we shift with the real page size. It works unless the
>> application want to mmap the offset bigger then 2G. In ILP32 app,
>> if the offset is bigger than 2G(e.g. 0xfb000000), it is a negative
>> number and extend to 64bit nagetive number in kernel
>> (0xfffffff fb000000). I add the "COMPAT_SYSCALL_WRAP6(mmap, ...)" in
>> kernel/compat_wrapper.c. But it is not works. I am not sure if it is
>> already sign extended in userspace.
>>
>> On the other hand, I read the code of mmap in arm and other
>> architecture. Usually, they will shift 4096 in userspace and shift
>> others in kernel if needed. Should we follow the similar ways or we
>> could call mmap_pgoff in glibc and do the shift according the real
>> page shift(getpages())?
>>
>> Thanks
>>
>> Bamvor
>>
>>
>
> Hi,
>
> AFAIR, here we don't shift offset, as it's 64-bit both in user-
> and kernel-space,
In your ilp32-2.22 branch, you wrapper mmap to mmap2 in which type of
offset is off_t. And off_t is 32bit in ilp32, correct?
"sysdeps/unix/sysv/linux/aarch64/ilp32/mmap64.c"
/* mmap is provided by mmap as they are the same. */
void *__mmap (void *__addr, size_t __len, int __prot,
                      int __flags, int __fd, __off_t __offset)
{
    void *result;
    result = (void *)
      INLINE_SYSCALL (mmap2, 6, __addr,
                      __len, __prot, __flags, __fd, __offset);
    return result;
}
> and just pass it from user to kernel thru glibc
> with no changes.
>
> It definitely works, as there are many mappings made by linker and
> libc in 2G+ area, and there are no problems with them. This is a
> typical ILP32 application map:
Ok, the different is I am talking about the offset in mmap. I am NOT
talking about the map result.
If I run my test case with strace:
"strace -e trace=mmap ./mmap.arm64_ilp32 0xfb000000 0x1000", here is
the part of log:

1 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7721000
2 mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7557000
3 page size<0x1000>, offset is <0xfb000000>
4 mmap(NULL, 4096, PROT_READ, MAP_SHARED, 3, 0xfffffffffb000000) = -1 EINVAL (Invalid argument)
5 mmap of mmapfile failed

As you said, line 1 and 2 show that mmap could map above 2G. But it
is NOT what I want to discussion.
As I said, when I pass the offset above 2G(e.g. 0xfb0000000), we
could find that the actual offset pass to kernel is
0xfffffffffb000000(reference line 4).
It will fail if I map in /dev/mmem. It will not fail if the fd is
a normal file. But in both of case the offset is wrong.

Regards

Bamvor

> 00400000-00401000 r-xp 00000000 08:00 130400     /root/mykill
> 00410000-00411000 rwxp 00000000 08:00 130400     /root/mykill
> 00527000-00549000 rwxp 00000000 00:00 0          [heap]
> c6278000-c6298000 rwxp 00000000 00:00 0
> c6298000-c63d0000 r-xp 00000000 08:00 135293     /root/sys-root/libilp32/libc-2.22.so
> c63d0000-c63e0000 ---p 00138000 08:00 135293     /root/sys-root/libilp32/libc-2.22.so
> c63e0000-c63e2000 r-xp 00138000 08:00 135293     /root/sys-root/libilp32/libc-2.22.so
> c63e2000-c63e3000 rwxp 0013a000 08:00 135293     /root/sys-root/libilp32/libc-2.22.so
> c63e3000-c63e6000 rwxp 00000000 00:00 0
> c63e6000-c63fc000 r-xp 00000000 08:00 135313     /root/sys-root/libilp32/libpthread-2.22.so
> c63fc000-c640b000 ---p 00016000 08:00 135313     /root/sys-root/libilp32/libpthread-2.22.so
> c640b000-c640c000 r-xp 00015000 08:00 135313     /root/sys-root/libilp32/libpthread-2.22.so
> c640c000-c640d000 rwxp 00016000 08:00 135313     /root/sys-root/libilp32/libpthread-2.22.so
> c640d000-c640f000 rwxp 00000000 00:00 0
> c640f000-c642c000 r-xp 00000000 08:00 135288     /root/sys-root/libilp32/ld-2.22.so
> c6437000-c6439000 rwxp 00000000 00:00 0
> c6439000-c643a000 r--p 00000000 00:00 0          [vvar]
> c643a000-c643b000 r-xp 00000000 00:00 0          [vdso]
> c643b000-c643c000 r-xp 0001c000 08:00 135288     /root/sys-root/libilp32/ld-2.22.so
> c643c000-c643d000 rwxp 0001d000 08:00 135288     /root/sys-root/libilp32/ld-2.22.so
> ffe2d000-ffe4e000 rw-p 00000000 00:00 0          [stack]
>
>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



From bamvor.zhangjian at huawei.com  Tue May 10 00:55:23 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Tue, 10 May 2016 15:55:23 +0800
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <573190CF.6030408@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1459894127-17698-21-git-send-email-ynorov@caviumnetworks.com>
 <572C8B30.7000005@huawei.com> <20160506123731.GA11959@yury-N73SV>
 <573190CF.6030408@huawei.com>
Message-ID: <573193EB.8040709@huawei.com>

Hi,

Sorry I forget to paste my test code:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>

#define TEMPFILE "mmapfile"

int main(int argc, char *argv[])
{
	int fd;
	void *addr;
	unsigned long offset;
	unsigned long size;

	if (argc == 3) {
		if (argv[1][0] == '0' && argv[1][1] == 'x')
			offset = strtoll(&argv[1][2], NULL, 16);
		else
			offset = atoi(argv[1]);

		if (argv[2][0] == '0' && argv[2][1] == 'x')
			size = strtoll(&argv[2][2], NULL, 16);
		else
			size = atoi(argv[2]);
	} else {
		exit(2);
	}

	printf("page size<0x%x>, offset is <0x%x>\n", size, offset);
//	if ((fd = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0) {
//		fprintf(stderr, "opening %s failed\n", TEMPFILE);
//		exit(2);
//	}
	fd = open("/dev/mem", O_RDWR | O_SYNC);
	if (-1 == fd)
	{
		printf( "open /dev/mem fail!\n" );
		return 1;
	}

	//addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, offset);
	addr = mmap(0, size, PROT_READ, MAP_FILE | MAP_SHARED, fd, offset);
	if(addr == MAP_FAILED) {
		fprintf(stderr, "mmap of %s failed\n", TEMPFILE);
		exit(2);
	}
	printf("addr: <0x%x>\n", addr);

	return 0;
}

Regards

Bamvor

On 2016/5/10 15:42, Zhangjian (Bamvor) wrote:
> Hi, Yury
>
> On 2016/5/6 20:37, Yury Norov wrote:
>> On Fri, May 06, 2016 at 08:16:48PM +0800, Zhangjian (Bamvor) wrote:
>>> Hi,
>>>
>>> On 2016/4/6 6:08, Yury Norov wrote:
>>>> From: Andrew Pinski <apinski at cavium.com>
>>>>
>>>> Add a separate syscall-table for ILP32, which dispatches either to native
>>>> LP64 system call implementation or to compat-syscalls, as appropriate.
>>>>
>>>> Signed-off-by: Andrew Pinski <Andrew.Pinski at caviumnetworks.com>
>>>> Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
>>>> ---
>>>>   arch/arm64/include/asm/unistd.h | 11 ++++++-
>>>>   arch/arm64/kernel/Makefile      |  2 +-
>>>>   arch/arm64/kernel/entry.S       | 12 +++++++-
>>>>   arch/arm64/kernel/sys_ilp32.c   | 65 +++++++++++++++++++++++++++++++++++++++++
>>>>   4 files changed, 87 insertions(+), 3 deletions(-)
>>>>   create mode 100644 arch/arm64/kernel/sys_ilp32.c
>>>>
>>>> diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
>>>> index 2971dea..5ea18ef 100644
>>>> --- a/arch/arm64/include/asm/unistd.h
>>>> +++ b/arch/arm64/include/asm/unistd.h
>>>> @@ -13,9 +13,18 @@
>>>>    * You should have received a copy of the GNU General Public License
>>>>    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>>>    */
>>>> +
>>>> +#ifdef CONFIG_COMPAT
>>>> +#define __ARCH_WANT_COMPAT_STAT64
>>>> +#endif
>>>> +
>>>> +#ifdef CONFIG_ARM64_ILP32
>>>> +#define __ARCH_WANT_COMPAT_SYS_PREADV64
>>>> +#define __ARCH_WANT_COMPAT_SYS_PWRITEV64
>>>> +#endif
>>>> +
>>>>   #ifdef CONFIG_AARCH32_EL0
>>>>   #define __ARCH_WANT_COMPAT_SYS_GETDENTS64
>>>> -#define __ARCH_WANT_COMPAT_STAT64
>>>>   #define __ARCH_WANT_SYS_GETHOSTNAME
>>>>   #define __ARCH_WANT_SYS_PAUSE
>>>>   #define __ARCH_WANT_SYS_GETPGRP
>>>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>>>> index 9dfdf86..7aa65ea 100644
>>>> --- a/arch/arm64/kernel/Makefile
>>>> +++ b/arch/arm64/kernel/Makefile
>>>> @@ -28,7 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
>>>>   arm64-obj-$(CONFIG_AARCH32_EL0)        += sys32.o kuser32.o signal32.o     \
>>>>                          sys_compat.o entry32.o        \
>>>>                          ../../arm/kernel/opcodes.o binfmt_elf32.o
>>>> -arm64-obj-$(CONFIG_ARM64_ILP32)        += binfmt_ilp32.o
>>>> +arm64-obj-$(CONFIG_ARM64_ILP32)        += binfmt_ilp32.o sys_ilp32.o
>>>>   arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>>>>   arm64-obj-$(CONFIG_MODULES)        += arm64ksyms.o module.o
>>>>   arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)    += module-plts.o
>>>> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
>>>> index cf4d1ae..1f7a145 100644
>>>> --- a/arch/arm64/kernel/entry.S
>>>> +++ b/arch/arm64/kernel/entry.S
>>>> @@ -715,9 +715,13 @@ ENDPROC(ret_from_fork)
>>>>    */
>>>>       .align    6
>>>>   el0_svc:
>>>> -    adrp    stbl, sys_call_table        // load syscall table pointer
>>>>       uxtw    scno, w8            // syscall number in w8
>>>>       mov    sc_nr, #__NR_syscalls
>>>> +#ifdef CONFIG_ARM64_ILP32
>>>> +    ldr    x16, [tsk, #TI_FLAGS]
>>>> +    tbnz    x16, #TIF_32BIT_AARCH64, el0_ilp32_svc // We are using ILP32
>>>> +#endif
>>>> +    adrp    stbl, sys_call_table        // load syscall table pointer
>>>>   el0_svc_naked:                    // compat entry point
>>>>       stp    x0, scno, [sp, #S_ORIG_X0]    // save the original x0 and syscall number
>>>>       enable_dbg_and_irq
>>>> @@ -737,6 +741,12 @@ ni_sys:
>>>>       b    ret_fast_syscall
>>>>   ENDPROC(el0_svc)
>>>>
>>>> +#ifdef CONFIG_ARM64_ILP32
>>>> +el0_ilp32_svc:
>>>> +    adrp    stbl, sys_call_ilp32_table // load syscall table pointer
>>>> +    b el0_svc_naked
>>>> +#endif
>>>> +
>>>>       /*
>>>>        * This is the really slow path.  We're going to be doing context
>>>>        * switches, and waiting for our parent to respond.
>>>> diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
>>>> new file mode 100644
>>>> index 0000000..0996d8e
>>>> --- /dev/null
>>>> +++ b/arch/arm64/kernel/sys_ilp32.c
>>>> @@ -0,0 +1,65 @@
>>>> +/*
>>>> + * AArch64- ILP32 specific system calls implementation
>>>> + *
>>>> + * Copyright (C) 2016 Cavium Inc.
>>>> + * Author: Andrew Pinski <apinski at cavium.com>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or modify
>>>> + * it under the terms of the GNU General Public License version 2 as
>>>> + * published by the Free Software Foundation.
>>>> + *
>>>> + * This program is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>> + * GNU General Public License for more details.
>>>> + *
>>>> + * 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/compiler.h>
>>>> +#include <linux/errno.h>
>>>> +#include <linux/fs.h>
>>>> +#include <linux/mm.h>
>>>> +#include <linux/msg.h>
>>>> +#include <linux/export.h>
>>>> +#include <linux/sched.h>
>>>> +#include <linux/slab.h>
>>>> +#include <linux/syscalls.h>
>>>> +#include <linux/compat.h>
>>>> +#include <asm-generic/syscalls.h>
>>>> +
>>>> +/* Using non-compat syscalls where necessary */
>>>> +#define compat_sys_fadvise64_64        sys_fadvise64_64
>>>> +#define compat_sys_fallocate           sys_fallocate
>>>> +#define compat_sys_ftruncate64         sys_ftruncate
>>>> +#define compat_sys_lookup_dcookie      sys_lookup_dcookie
>>>> +#define compat_sys_pread64             sys_pread64
>>>> +#define compat_sys_pwrite64            sys_pwrite64
>>>> +#define compat_sys_readahead           sys_readahead
>>>> +#define compat_sys_shmat               sys_shmat
>>>> +#define compat_sys_sync_file_range     sys_sync_file_range
>>>> +#define compat_sys_truncate64          sys_truncate
>>>> +#define sys_llseek                     sys_lseek
>>>> +#define sys_mmap2               sys_mmap
>>> I am a little bit confused here. We wrap the mmap to mmap2 in glibc
>>> without shift the 4096 and We map mmap2 to mmap in kernel which
>>> means we shift with the real page size. It works unless the
>>> application want to mmap the offset bigger then 2G. In ILP32 app,
>>> if the offset is bigger than 2G(e.g. 0xfb000000), it is a negative
>>> number and extend to 64bit nagetive number in kernel
>>> (0xfffffff fb000000). I add the "COMPAT_SYSCALL_WRAP6(mmap, ...)" in
>>> kernel/compat_wrapper.c. But it is not works. I am not sure if it is
>>> already sign extended in userspace.
>>>
>>> On the other hand, I read the code of mmap in arm and other
>>> architecture. Usually, they will shift 4096 in userspace and shift
>>> others in kernel if needed. Should we follow the similar ways or we
>>> could call mmap_pgoff in glibc and do the shift according the real
>>> page shift(getpages())?
>>>
>>> Thanks
>>>
>>> Bamvor
>>>
>>>
>>
>> Hi,
>>
>> AFAIR, here we don't shift offset, as it's 64-bit both in user-
>> and kernel-space,
> In your ilp32-2.22 branch, you wrapper mmap to mmap2 in which type of
> offset is off_t. And off_t is 32bit in ilp32, correct?
> "sysdeps/unix/sysv/linux/aarch64/ilp32/mmap64.c"
> /* mmap is provided by mmap as they are the same. */
> void *__mmap (void *__addr, size_t __len, int __prot,
>                       int __flags, int __fd, __off_t __offset)
> {
>     void *result;
>     result = (void *)
>       INLINE_SYSCALL (mmap2, 6, __addr,
>                       __len, __prot, __flags, __fd, __offset);
>     return result;
> }
>> and just pass it from user to kernel thru glibc
>> with no changes.
>>
>> It definitely works, as there are many mappings made by linker and
>> libc in 2G+ area, and there are no problems with them. This is a
>> typical ILP32 application map:
> Ok, the different is I am talking about the offset in mmap. I am NOT
> talking about the map result.
> If I run my test case with strace:
> "strace -e trace=mmap ./mmap.arm64_ilp32 0xfb000000 0x1000", here is
> the part of log:
>
> 1 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7721000
> 2 mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7557000
> 3 page size<0x1000>, offset is <0xfb000000>
> 4 mmap(NULL, 4096, PROT_READ, MAP_SHARED, 3, 0xfffffffffb000000) = -1 EINVAL (Invalid argument)
> 5 mmap of mmapfile failed
>
> As you said, line 1 and 2 show that mmap could map above 2G. But it
> is NOT what I want to discussion.
> As I said, when I pass the offset above 2G(e.g. 0xfb0000000), we
> could find that the actual offset pass to kernel is
> 0xfffffffffb000000(reference line 4).
> It will fail if I map in /dev/mmem. It will not fail if the fd is
> a normal file. But in both of case the offset is wrong.
>
> Regards
>
> Bamvor
>
>> 00400000-00401000 r-xp 00000000 08:00 130400     /root/mykill
>> 00410000-00411000 rwxp 00000000 08:00 130400     /root/mykill
>> 00527000-00549000 rwxp 00000000 00:00 0          [heap]
>> c6278000-c6298000 rwxp 00000000 00:00 0
>> c6298000-c63d0000 r-xp 00000000 08:00 135293     /root/sys-root/libilp32/libc-2.22.so
>> c63d0000-c63e0000 ---p 00138000 08:00 135293     /root/sys-root/libilp32/libc-2.22.so
>> c63e0000-c63e2000 r-xp 00138000 08:00 135293     /root/sys-root/libilp32/libc-2.22.so
>> c63e2000-c63e3000 rwxp 0013a000 08:00 135293     /root/sys-root/libilp32/libc-2.22.so
>> c63e3000-c63e6000 rwxp 00000000 00:00 0
>> c63e6000-c63fc000 r-xp 00000000 08:00 135313     /root/sys-root/libilp32/libpthread-2.22.so
>> c63fc000-c640b000 ---p 00016000 08:00 135313     /root/sys-root/libilp32/libpthread-2.22.so
>> c640b000-c640c000 r-xp 00015000 08:00 135313     /root/sys-root/libilp32/libpthread-2.22.so
>> c640c000-c640d000 rwxp 00016000 08:00 135313     /root/sys-root/libilp32/libpthread-2.22.so
>> c640d000-c640f000 rwxp 00000000 00:00 0
>> c640f000-c642c000 r-xp 00000000 08:00 135288     /root/sys-root/libilp32/ld-2.22.so
>> c6437000-c6439000 rwxp 00000000 00:00 0
>> c6439000-c643a000 r--p 00000000 00:00 0          [vvar]
>> c643a000-c643b000 r-xp 00000000 00:00 0          [vdso]
>> c643b000-c643c000 r-xp 0001c000 08:00 135288     /root/sys-root/libilp32/ld-2.22.so
>> c643c000-c643d000 rwxp 0001d000 08:00 135288     /root/sys-root/libilp32/ld-2.22.so
>> ffe2d000-ffe4e000 rw-p 00000000 00:00 0          [stack]
>>
>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>



From nicolas.ferre at atmel.com  Tue May 10 01:03:03 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Tue, 10 May 2016 10:03:03 +0200
Subject: [PATCH] ARM: at91/defconfig: sama5: add CONFIG_FHANDLE
In-Reply-To: <572CC603.4000102@denx.de>
References: <572CC603.4000102@denx.de>
Message-ID: <1462867383-31961-1-git-send-email-nicolas.ferre@atmel.com>

CONFIG_FHANDLE is listed as a mandatory kernel option for systemd. So
explicitly enable it to allow easy use of systemd userspace.

Reported-by: Marek Vasut <marex at denx.de>
Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
---
Hi Marek,

It seems that on my side, CONFIG_FHANDLE is not selected automatically...
So I add this patch: can you tell me your thoughts?

Bye,
   Nico.

 arch/arm/configs/sama5_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index 307f92b31e57..9cb1a85bb166 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -1,6 +1,7 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CGROUPS=y
-- 
2.1.3



From boris.brezillon at free-electrons.com  Tue May 10 01:04:48 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 10 May 2016 10:04:48 +0200
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <20160504153547.60d736bb@bbrezillon>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop>
 <20160503185153.5cfddc32@bbrezillon>
 <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
 <20160504113852.10a2dd84@bbrezillon>
 <CAL_Jsq+4aL5znA3zOKdcJb+pEXhVOQthkFF6DN2+P6U37t2o6g@mail.gmail.com>
 <20160504153547.60d736bb@bbrezillon>
Message-ID: <20160510100448.49834120@bbrezillon>

On Wed, 4 May 2016 15:35:47 +0200
Boris Brezillon <boris.brezillon at free-electrons.com> wrote:

> On Wed, 4 May 2016 08:06:10 -0500
> Rob Herring <robh at kernel.org> wrote:
> 
> > On Wed, May 4, 2016 at 4:38 AM, Boris Brezillon
> > <boris.brezillon at free-electrons.com> wrote:  
> > > Hi Rob,
> > >
> > > On Tue, 3 May 2016 14:11:04 -0500
> > > Rob Herring <robh at kernel.org> wrote:
> > >    
> > >> On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
> > >> <boris.brezillon at free-electrons.com> wrote:    
> > >> > Hi Rob,
> > >> >
> > >> > On Tue, 3 May 2016 11:40:19 -0500
> > >> > Rob Herring <robh at kernel.org> wrote:
> > >> >    
> > >> >> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:    
> > >> >> > The EBI (External Bus Interface) is used to access external peripherals
> > >> >> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
> > >> >> > Each device is assigned a CS line and an address range and can have its
> > >> >> > own configuration (timings, access mode, bus width, ...).
> > >> >> > This driver provides a generic DT binding to configure a device according
> > >> >> > to its requirements.
> > >> >> > For specific device controllers (like the NAND one) the SMC timings
> > >> >> > should be configured by the controller driver through the matrix and smc
> > >> >> > syscon regmaps.    
> > 
> > [...]
> >   
> > >> >> > +EBI bus configuration associated with specific chip-select will be defined in
> > >> >> > +the configs subnode. This configs node will in turn contain several subnodes
> > >> >> > +named config-<cs-id>, each of them containing the following properties.    
> > >> >>
> > >> >> This is a bit unusual. Why not just part of the child device nodes?    
> > >> >
> > >> > Oh, come on! I reworked the binding because Mark complained about the
> > >> > previous binding which was doing exactly what you're suggesting. Can
> > >> > you please be consistent in your reviews...    
> > >>
> > >> No, Mark and I both have our opinions. Which part of this patch
> > >> explains the history?    
> > >
> > > Hm, it's in patch 1/2 (just dropped the cover letter, which might not
> > > be such a good idea).
> > >    
> > >> If the revision history is not in the patch, I'm
> > >> not looking at it.
> > >>
> > >> My issue with it this way is that it has invented yet another way to
> > >> describe timings. I would like to be consistent across external bus
> > >> descriptions, but we're not very consistent to begin with though. The
> > >> most common seems to be the way you first did it. But I agree that it
> > >> is kind of screwy to have an intermediate node unless the controller
> > >> itself has sub-blocks within it and is not the established way to
> > >> describe a bus with chip selects. I would either put the properties
> > >> directly in the child nodes (e.g. flash at 0,0) or put your config nodes
> > >> in the device node. I'd call it timings instead of config, but that's
> > >> just bikeshedding.    
> > >
> > > Well, it's not only describing timings (see atmel,bus-width,
> > > atmel,byte-access-type, ...), but I'm fine with either names :).
> > >    
> > >>
> > >> memory-controller at 1000 {
> > >>   ...
> > >>   flash at 0,0 {
> > >>     timings {
> > >>       ...
> > >>     };
> > >>   };
> > >> };    
> > >
> > > Okay. Mark, what do you think of this approach?
> > >
> > > Note that one of my previous version was defining timings directly in
> > > the EBI device node, and Arnd noted that doing so may cause problems
> > > if one of the EBI property (or the config/timing node name) conflict
> > > with the sub-device binding, which is why I decided to put the EBI
> > > config definitions in a separate subnode.    
> > 
> > You have vendor prefixes on all the properties so I don't think a
> > collision is really a problem. It's also an established pattern in
> > i.MX WEIM and OMAP GPMC (which are hiding in bindings/bus/) and I
> > prefer consistency.  
> 
> So let's summarize that.
> 
> memory-controller at 1000 {
> 	...
> 	flash at 0,0 {
> 		atmel,<ebi-prop-name> = <value>;
> 		...
> 		<flash-device-prop> = <value>;
> 	};
> };
> 
> Would everyone agree on this representation?
> 
> With this approach, it's a bit more complicated to detect the case
> where we want to keep bootloader/firmware config, but it should be
> doable (it's much more easier to test for the presence of a
> config/timing node than verifying that either all or none of the
> mandatory properties are here).
> 
> Still remains the problem mentioned by Jean-Jacques: what if the
> sub-device takes 2 CS lines. Should we apply the same setting to those
> slots?
> 

Rob, Mark, Arnd, can you take a decision regarding this binding? This
driver is floating around for quite some time, and we were asked to
rework the binding several times (in time in an opposite direction).

For the record, here is the thread I mentioned earlier [1]. In his
answer, Arnd suggests to put timing and bus config description
outside of the sub-device node. Mark recently complained about this
representation, which led me to the configs/config-X appraoch, and now
Rob suggests to go back to the first proposal.

I'm fine doing that, but can you please all confirm that you agree on
this binding?

Thanks,

Boris

[1]http://lists.infradead.org/pipermail/linux-arm-kernel/2013-December/222438.html

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


From k.kozlowski at samsung.com  Tue May 10 01:15:58 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 10:15:58 +0200
Subject: [PATCH] ARM: dts: exynos: Only Odroid XU3-family boards use DTSI
 with CPU thermal nodes
In-Reply-To: <CANAwSgT9SY3kj8+beMpc1xGoC=rMBSya+2v2dyZQp6ykH+V0=g@mail.gmail.com>
References: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>
 <CANAwSgT9SY3kj8+beMpc1xGoC=rMBSya+2v2dyZQp6ykH+V0=g@mail.gmail.com>
Message-ID: <573198BE.6020900@samsung.com>

On 05/10/2016 08:43 AM, Anand Moon wrote:
> Hi Krzysztof ,
> 
> On 9 May 2016 at 11:49, Krzysztof Kozlowski <k.kozlowski at samsung.com> wrote:
>> Include the CPU thermal nodes directly in Odroid XU3-family common DTS
>> because it is the only user of it. Keeping it in separate DTSI node does
>> not bring benefits because:
>> 1. It is not re-usable on other non-fan boards (fan is referenced),
>> 2. It won't be re-used on future Odroid XU board because different
>>    CPU cluster behavior.
>>
>> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>> ---
>>  arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi      | 103 ---------------------
>>  arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |  94 ++++++++++++++++++-
>>  2 files changed, 92 insertions(+), 105 deletions(-)
>>  delete mode 100644 arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi
>>
>> diff --git a/arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi b/arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi
>> deleted file mode 100644
>> index 3e4c4ad96d63..000000000000
>> --- a/arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi
>> +++ /dev/null
>> @@ -1,103 +0,0 @@
>> -/*
>> - * Device tree sources for Exynos5422 thermal zone
>> - *
>> - * Copyright (c) 2015 Lukasz Majewski <l.majewski at samsung.com>
>> - *                     Anand Moon <linux.amoon at gmail.com>
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License version 2 as
>> - * published by the Free Software Foundation.
>> - *
>> - */
>> -
>> -#include <dt-bindings/thermal/thermal.h>
>> -
>> -/ {
>> -       thermal-zones {
>> -               cpu0_thermal: cpu0-thermal {
>> -                       thermal-sensors = <&tmu_cpu0 0>;
>> -                       polling-delay-passive = <250>;
>> -                       polling-delay = <0>;
>> -                       trips {
>> -                               cpu_alert0: cpu-alert-0 {
>> -                                       temperature = <50000>; /* millicelsius */
>> -                                       hysteresis = <5000>; /* millicelsius */
>> -                                       type = "active";
>> -                               };
>> -                               cpu_alert1: cpu-alert-1 {
>> -                                       temperature = <60000>; /* millicelsius */
>> -                                       hysteresis = <5000>; /* millicelsius */
>> -                                       type = "active";
>> -                               };
>> -                               cpu_alert2: cpu-alert-2 {
>> -                                       temperature = <70000>; /* millicelsius */
>> -                                       hysteresis = <5000>; /* millicelsius */
>> -                                       type = "active";
>> -                               };
>> -                               cpu_crit0: cpu-crit-0 {
>> -                                       temperature = <120000>; /* millicelsius */
>> -                                       hysteresis = <0>; /* millicelsius */
>> -                                       type = "critical";
>> -                               };
>> -                               /*
>> -                                * Exyunos542x support only 4 trip-points
>> -                                * so for these polling mode is required.
>> -                                * Start polling at temperature level of last
>> -                                * interrupt-driven trip: cpu_alert2
>> -                                */
>> -                               cpu_alert3: cpu-alert-3 {
>> -                                       temperature = <70000>; /* millicelsius */
>> -                                       hysteresis = <10000>; /* millicelsius */
>> -                                       type = "passive";
>> -                               };
>> -                               cpu_alert4: cpu-alert-4 {
>> -                                       temperature = <85000>; /* millicelsius */
>> -                                       hysteresis = <10000>; /* millicelsius */
>> -                                       type = "passive";
>> -                               };
>> -
>> -                       };
>> -                       cooling-maps {
>> -                               map0 {
>> -                                    trip = <&cpu_alert0>;
>> -                                    cooling-device = <&fan0 0 1>;
>> -                               };
>> -                               map1 {
>> -                                    trip = <&cpu_alert1>;
>> -                                    cooling-device = <&fan0 1 2>;
>> -                               };
>> -                               map2 {
>> -                                    trip = <&cpu_alert2>;
>> -                                    cooling-device = <&fan0 2 3>;
>> -                               };
>> -                               /*
>> -                                * When reaching cpu_alert3, reduce CPU
>> -                                * by 2 steps. On Exynos5422/5800 that would
>> -                                * be: 1500 MHz and 1100 MHz.
>> -                                */
>> -                               map3 {
>> -                                    trip = <&cpu_alert3>;
>> -                                    cooling-device = <&cpu0 0 2>;
>> -                               };
>> -                               map4 {
>> -                                    trip = <&cpu_alert3>;
>> -                                    cooling-device = <&cpu4 0 2>;
>> -                               };
>> -
>> -                               /*
>> -                                * When reaching cpu_alert4, reduce CPU
>> -                                * further, down to 600 MHz (11 steps for big,
>> -                                * 7 steps for LITTLE).
>> -                                */
>> -                               map5 {
>> -                                    trip = <&cpu_alert4>;
>> -                                    cooling-device = <&cpu0 3 7>;
>> -                               };
>> -                               map6 {
>> -                                    trip = <&cpu_alert4>;
>> -                                    cooling-device = <&cpu4 3 11>;
>> -                               };
>> -                       };
>> -               };
>> -       };
>> -};
>> diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
>> index 2a4e10bc8801..ff05041835e5 100644
>> --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
>> +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
>> @@ -1,9 +1,11 @@
>>  /*
>>   * Hardkernel Odroid XU3 board device tree source
>>   *
>> - * Copyright (c) 2014 Collabora Ltd.
>>   * Copyright (c) 2013 Samsung Electronics Co., Ltd.
>>   *             http://www.samsung.com
>> + * Copyright (c) 2014 Collabora Ltd.
>> + * Copyright (c) 2015 Lukasz Majewski <l.majewski at samsung.com>
>> + *                    Anand Moon <linux.amoon at gmail.com>
>>   *
>>   * This program is free software; you can redistribute it and/or modify
>>   * it under the terms of the GNU General Public License version 2 as
>> @@ -16,7 +18,6 @@
>>  #include <dt-bindings/sound/samsung-i2s.h>
>>  #include "exynos5800.dtsi"
>>  #include "exynos5422-cpus.dtsi"
>> -#include "exynos5422-cpu-thermal.dtsi"
>>
>>  / {
>>         memory {
>> @@ -54,6 +55,95 @@
>>                 #cooling-cells = <2>;
>>                 cooling-levels = <0 130 170 230>;
>>         };
>> +
>> +       thermal-zones {
>> +               cpu0_thermal: cpu0-thermal {
>> +                       thermal-sensors = <&tmu_cpu0 0>;
>> +                       polling-delay-passive = <250>;
>> +                       polling-delay = <0>;
>> +                       trips {
>> +                               cpu_alert0: cpu-alert-0 {
>> +                                       temperature = <50000>; /* millicelsius */
>> +                                       hysteresis = <5000>; /* millicelsius */
>> +                                       type = "active";
>> +                               };
>> +                               cpu_alert1: cpu-alert-1 {
>> +                                       temperature = <60000>; /* millicelsius */
>> +                                       hysteresis = <5000>; /* millicelsius */
>> +                                       type = "active";
>> +                               };
>> +                               cpu_alert2: cpu-alert-2 {
>> +                                       temperature = <70000>; /* millicelsius */
>> +                                       hysteresis = <5000>; /* millicelsius */
>> +                                       type = "active";
>> +                               };
>> +                               cpu_crit0: cpu-crit-0 {
>> +                                       temperature = <120000>; /* millicelsius */
>> +                                       hysteresis = <0>; /* millicelsius */
>> +                                       type = "critical";
>> +                               };
>> +                               /*
>> +                                * Exynos542x supports only 4 trip-points
>> +                                * so for these polling mode is required.
>> +                                * Start polling at temperature level of last
>> +                                * interrupt-driven trip: cpu_alert2
>> +                                */
>> +                               cpu_alert3: cpu-alert-3 {
>> +                                       temperature = <70000>; /* millicelsius */
>> +                                       hysteresis = <10000>; /* millicelsius */
>> +                                       type = "passive";
>> +                               };
>> +                               cpu_alert4: cpu-alert-4 {
>> +                                       temperature = <85000>; /* millicelsius */
>> +                                       hysteresis = <10000>; /* millicelsius */
>> +                                       type = "passive";
>> +                               };
>> +
>> +                       };
>> +                       cooling-maps {
>> +                               map0 {
>> +                                    trip = <&cpu_alert0>;
>> +                                    cooling-device = <&fan0 0 1>;
>> +                               };
>> +                               map1 {
>> +                                    trip = <&cpu_alert1>;
>> +                                    cooling-device = <&fan0 1 2>;
>> +                               };
>> +                               map2 {
>> +                                    trip = <&cpu_alert2>;
>> +                                    cooling-device = <&fan0 2 3>;
>> +                               };
>> +                               /*
>> +                                * When reaching cpu_alert3, reduce CPU
>> +                                * by 2 steps. On Exynos5422/5800 that would
>> +                                * be: 1500 MHz and 1100 MHz.
>> +                                */
>> +                               map3 {
>> +                                    trip = <&cpu_alert3>;
>> +                                    cooling-device = <&cpu0 0 2>;
>> +                               };
>> +                               map4 {
>> +                                    trip = <&cpu_alert3>;
>> +                                    cooling-device = <&cpu4 0 2>;
>> +                               };
>> +
>> +                               /*
>> +                                * When reaching cpu_alert4, reduce CPU
>> +                                * further, down to 600 MHz (11 steps for big,
>> +                                * 7 steps for LITTLE).
>> +                                */
>> +                               map5 {
>> +                                    trip = <&cpu_alert4>;
>> +                                    cooling-device = <&cpu0 3 7>;
>> +                               };
>> +                               map6 {
>> +                                    trip = <&cpu_alert4>;
>> +                                    cooling-device = <&cpu4 3 11>;
>> +                               };
>> +                       };
>> +               };
>> +       };
>> +
>>  };
>>
>>  &bus_wcore {
>> --
>> 1.9.1
>>
> 
> Could you defer this patch, during my testing with pm-qa from linaro.
> 
> git://git.linaro.org/tools/pm-qa.git
> 
> When their is running of thermal test case cpu usage reaches around
> 300+ percentage
> and some time's the Odroid XU4 hang down.
> -------------------------------------------------------------------------
> [ 1028.056619] CPU4: shutdown
> [ 1148.510372] IRQ54 no longer affine to CPU5
> [ 1148.511864] CPU5: shutdown
> [ 1268.921073] IRQ55 no longer affine to CPU6
> [ 1268.922564] CPU6: shutdown
> [ 1389.271930] cpu cpu4: Failed to find opp_table: -19
> [ 1389.301668] IRQ56 no longer affine to CPU7
> [ 1389.303132] CPU7: shutdown
> [ 1510.538424] cpu cpu4: opp_list_debug_create_link: Failed to create link
> [ 1510.543762] cpu cpu4: _add_opp_dev: Failed to register opp debugfs (-12)
> [ 1510.550625] cpu cpu7: opp_list_debug_create_link: Failed to create link
> [ 1510.557037] cpu cpu7: _add_opp_dev: Failed to register opp debugfs (-12)
> [ 1510.664649] cpu cpu5: cpufreq_init: failed to get clk: -2
> [ 1510.720567] cpu cpu6: cpufreq_init: failed to get clk: -2
> [ 1510.788280] cpu cpu7: cpufreq_init: failed to get clk: -2
> root at odroidxu4l:/home/odroid/study/linaro/pm-qa# killall heat_cpu
> 
> -------------------------------------------------------------------------
> And some time I observed that the board will poweroff on reaching
> temperature 120 degree C.
> when I am compiling the kernel with or above. make -j8
> -------------------------------------------------------------------------
> root at odroidxu4l:~#  * Starting NTP server ntpd                           [ OK ]
> saned disabled; edit /etc/default/saned
> [ 4118.924470] thermal thermal_zone3: critical temperature reached(121
> C),shutting down
> [ 4119.014327] thermal thermal_zone3: critical temperature reached(121
> C),shutting down
> 
> Broadcast message from root at odroidxu4l
>         (unknown) at 20:41 ...
> 
> The system is going down for power off NOW!
> 
> Broadcast message from root at odroidxu4l
>         (unknown) at 20:41 ...
> 
> The system is going down for power off NOW!
> [ 4119.431386] thermal thermal_zone3: critical temperature reached(121
> C),shutting down
> [ 4120.206709] thermal thermal_zone3: critical temperature reached(120
> C),shutting down
> 
> Broadcast message from root at odroidxu4l
>         (unknown) at 20:41 ...
> 
> The system is going down for power off NOW!
> wait-for-state stop/waiting
> [ 4157.574406] reboo
> 
> U-Boot 2016.03-00665-g563d8d9-dirty (Apr 04 2016 - 22:27:07 +0930) for
> ODROID-XU3
> 
> CPU:   Exynos5422 @ 800 MHz
> Model: Odroid XU3 based on EXYNOS5422
> Board: Odroid XU3 based on EXYNOS5422
> Type:  xu4
> DRAM:  2 GiB
> MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
> *** Warning - bad CRC, using default environment
> -------------------------------------------------------------------------
> Once the thermal issue is fixed we can redo this changes.

I am sorry but I do not understand.
1. Are you saying that my patch causes the issue?
2. Are you saying that I should not send some patches because of
conflicting work? (that would be peculiar...)
3. Are you saying that I should not apply this patch to me tree because
of conflicting work?
4. Other?

Best regards.
Krzysztof




From lorenzo.pieralisi at arm.com  Tue May 10 01:22:50 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Tue, 10 May 2016 09:22:50 +0100
Subject: [PATCH] firmware/drivers/psci: Fix unused functions when
 CONFIG_CPU_IDLE=n
In-Reply-To: <1462864729-11793-1-git-send-email-daniel.lezcano@linaro.org>
References: <1462864729-11793-1-git-send-email-daniel.lezcano@linaro.org>
Message-ID: <20160510082250.GA14662@red-moon>

On Tue, May 10, 2016 at 09:18:49AM +0200, Daniel Lezcano wrote:
> On the ARM64 architecture, when CPUIDLE is not set in the configuration,
> the compilation raises a couple of warnings:
> 
> drivers/firmware/psci.c:70:12: warning: 'psci_pd_power_off' defined but not used [-Wunused-function]
> drivers/firmware/psci.c:273:12: warning: 'psci_set_suspend_mode_osi' defined but not used [-Wunused-function]

That's not mainline code :)

Thanks,
Lorenzo

> Fix those warnings by moving the functions inside the #ifdef CONFIG_CPU_IDLE
> section.
> 
> Signed-off-by: Daniel Lezcano <daniel.lezcano at linaro.org>
> ---
>  drivers/firmware/psci.c | 21 +++++++++++----------
>  1 file changed, 11 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
> index 9c6a1f9..d7e0632 100644
> --- a/drivers/firmware/psci.c
> +++ b/drivers/firmware/psci.c
> @@ -54,7 +54,6 @@
>   */
>  static int resident_cpu = -1;
>  static bool psci_has_osi_pd;
> -static bool psci_suspend_mode_is_osi;
>  static DEFINE_PER_CPU(u32, cluster_state_id);
>  
>  static inline u32 psci_get_composite_state_id(u32 cpu_state)
> @@ -67,13 +66,6 @@ static inline void psci_reset_composite_state_id(void)
>  	this_cpu_write(cluster_state_id, 0);
>  }
>  
> -static int psci_pd_power_off(u32 state_idx, u32 param,
> -		const struct cpumask *mask)
> -{
> -	__this_cpu_add(cluster_state_id, param);
> -	return 0;
> -}
> -
>  bool psci_tos_resident_on(int cpu)
>  {
>  	return cpu == resident_cpu;
> @@ -270,6 +262,11 @@ static int __init psci_features(u32 psci_func_id)
>  			      psci_func_id, 0, 0);
>  }
>  
> +#ifdef CONFIG_CPU_IDLE
> +static bool psci_suspend_mode_is_osi;
> +
> +static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
> +
>  static int psci_set_suspend_mode_osi(bool enable)
>  {
>  	int ret;
> @@ -290,8 +287,12 @@ static int psci_set_suspend_mode_osi(bool enable)
>  	return psci_to_linux_errno(ret);
>  }
>  
> -#ifdef CONFIG_CPU_IDLE
> -static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
> +static int psci_pd_power_off(u32 state_idx, u32 param,
> +		const struct cpumask *mask)
> +{
> +	__this_cpu_add(cluster_state_id, param);
> +	return 0;
> +}
>  
>  static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
>  {
> -- 
> 1.9.1
> 


From chunfeng.yun at mediatek.com  Tue May 10 01:23:29 2016
From: chunfeng.yun at mediatek.com (Chunfeng Yun)
Date: Tue, 10 May 2016 16:23:29 +0800
Subject: [PATCH 1/6] dt-bindings: mt8173-xhci: support host side of dual-role
 mode
In-Reply-To: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <1462868614-20602-2-git-send-email-chunfeng.yun@mediatek.com>

Some resources, such as IPPC register etc, shared with device
driver are moved into common glue layer when xHCI driver is the
host side of dual-role mode and they should be changed as optional
properties if they are required ones before. For clarity, add
a new part of binding to support host side of dual-role mode.

Additionally add optional properties of pinctrl for host only mode

Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
---
 .../devicetree/bindings/usb/mt8173-xhci.txt        |   48 ++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
index b3a7ffa..542e3fa 100644
--- a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
@@ -2,6 +2,14 @@ MT8173 xHCI
 
 The device node for Mediatek SOC USB3.0 host controller
 
+There are two scenarios: the first one only supports xHCI driver;
+the second one supports dual-role mode, and the host is based on xHCI
+driver. Take account of backward compatibility, we divide bindings
+into two parts.
+
+1st: only supports xHCI driver
+------------------------------------------------------------------------
+
 Required properties:
  - compatible : should contain "mediatek,mt8173-xhci"
  - reg : specifies physical base address and size of the registers,
@@ -27,6 +35,9 @@ Optional properties:
 	control register, it depends on "mediatek,wakeup-src".
  - vbus-supply : reference to the VBUS regulator;
  - usb3-lpm-capable : supports USB3.0 LPM
+ - pinctl-names : a pinctrl state named "default" must be defined
+ - pinctrl-0 : pin control group
+	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
 
 Example:
 usb30: usb at 11270000 {
@@ -49,3 +60,40 @@ usb30: usb at 11270000 {
 	mediatek,syscon-wakeup = <&pericfg>;
 	mediatek,wakeup-src = <1>;
 };
+
+2nd: dual-role mode with xHCI driver
+------------------------------------------------------------------------
+
+In the case, xhci is added as subnode to mtu3. An example and the DT binding
+details of mtu3 can be found in:
+Documentation/devicetree/bindings/usb/mtu3.txt
+
+Required properties:
+ - compatible : should contain "mediatek,mt8173-xhci"
+ - reg : specifies physical base address and size of the registers,
+	should be only for xHCI IP registers
+ - interrupts : interrupt used by the host controller
+ - power-domains : a phandle to USB power domain node to control USB's
+	mtcmos
+ - vusb33-supply : regulator of USB avdd3.3v
+
+ - clocks : a list of phandle + clock-specifier pairs, one for each
+	entry in clock-names
+ - clock-names : must be
+	"sys_ck": for clock of xHCI MAC
+
+Optional properties:
+ - vbus-supply : reference to the VBUS regulator;
+ - usb3-lpm-capable : supports USB3.0 LPM
+
+Example:
+usb30: usb at 11270000 {
+	compatible = "mediatek,mt8173-xhci";
+	reg = <0 0x11270000 0 0x1000>;
+	interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
+	clocks = <&topckgen CLK_TOP_USB30_SEL>;
+	clock-names = "sys_ck";
+	vusb33-supply = <&mt6397_vusb_reg>;
+	usb3-lpm-capable;
+};
-- 
1.7.9.5



From chunfeng.yun at mediatek.com  Tue May 10 01:23:31 2016
From: chunfeng.yun at mediatek.com (Chunfeng Yun)
Date: Tue, 10 May 2016 16:23:31 +0800
Subject: [PATCH 3/6] dt-bindings: mtu3: add devicetree bindings
In-Reply-To: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <1462868614-20602-4-git-send-email-chunfeng.yun@mediatek.com>

add a DT binding doc for MediaTek USB3 DRD driver

Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
---
 Documentation/devicetree/bindings/usb/mtu3.txt |   86 ++++++++++++++++++++++++
 1 file changed, 86 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/mtu3.txt

diff --git a/Documentation/devicetree/bindings/usb/mtu3.txt b/Documentation/devicetree/bindings/usb/mtu3.txt
new file mode 100644
index 0000000..ff142a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/mtu3.txt
@@ -0,0 +1,86 @@
+The device node for Mediatek USB3.0 DRD controller
+
+Required properties:
+ - compatible : should be "mediatek,mt8173-mtu3"
+ - reg : specifies physical base address and size of the registers
+ - reg-names: should be "mac" for device IP and "ippc" for IP port control
+ - interrupts : interrupt used by the device IP
+ - power-domains : a phandle to USB power domain node to control USB's
+	mtcmos
+ - vusb33-supply : regulator of USB avdd3.3v
+ - clocks : a list of phandle + clock-specifier pairs, one for each
+	entry in clock-names
+ - clock-names : must contain "sys_ck" for clock of controller;
+	"wakeup_deb_p0" and "wakeup_deb_p1" are optional, they are
+	depends on "mediatek,enable-wakeup"
+ - phys : a list of phandle + phy specifier pairs
+ - dr_mode : should be one of "host", "peripheral" or "otg",
+	refer to usb/generic.txt
+
+Optional properties:
+ - #address-cells, #size-cells : should be '2' if the device has sub-nodes
+	with 'reg' property
+ - ranges : allows valid 1:1 translation between child's address space and
+	parent's address space
+ - extcon : external connector for vbus and idpin changes detection, needed
+	when supports dual-role mode.
+ - vbus-supply : reference to the VBUS regulator, needed when supports
+	dual-role mode.
+ - pinctl-names : a pinctrl state named "default" must be defined,
+	"id_float" and "id_ground" are optinal which depends on
+	"mediatek,enable-manual-drd"
+ - pinctrl-0 : pin control group
+	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+
+ - maximum-speed : valid arguments are "super-speed", "high-speed" and
+	"full-speed"; refer to usb/generic.txt
+ - mediatek,enable-wakeup : supports ip sleep wakeup used by host mode
+ - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup
+	control register, it depends on "mediatek,enable-wakeup".
+ - mediatek,enable-manual-drd : supports manual dual-role switch by sysfs
+	interface; only used when receptacle is TYPE-A and also wants to support
+	dual-role mode.
+
+Sub-nodes:
+The xhci should be added as subnode to mtu3 as shown in the following example
+if host mode is enabled. The DT binding details of xhci can be found in:
+Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+
+Example:
+ssusb: usb at 11271000 {
+	compatible = "mediatek,mt8173-mtu3";
+	reg = <0 0x11271000 0 0x3000>,
+	      <0 0x11280700 0 0x0100>;
+	reg-names = "mac", "ippc";
+	interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>;
+	phys = <&phy_port0 PHY_TYPE_USB3>,
+	       <&phy_port1 PHY_TYPE_USB2>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
+	clocks = <&topckgen CLK_TOP_USB30_SEL>,
+		 <&pericfg CLK_PERI_USB0>,
+		 <&pericfg CLK_PERI_USB1>;
+	clock-names = "sys_ck",
+		      "wakeup_deb_p0",
+		      "wakeup_deb_p1";
+	vusb33-supply = <&mt6397_vusb_reg>;
+	vbus-supply = <&usb_p0_vbus>;
+	extcon = <&extcon_usb>;
+	dr_mode = "otg";
+	mediatek,enable-wakeup;
+	mediatek,syscon-wakeup = <&pericfg>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+	ranges;
+	status = "disabled";
+
+	usb_host: xhci at 11270000 {
+		compatible = "mediatek,mt8173-xhci";
+		reg = <0 0x11270000 0 0x1000>;
+		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
+		power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
+		clocks = <&topckgen CLK_TOP_USB30_SEL>;
+		clock-names = "sys_ck";
+		vusb33-supply = <&mt6397_vusb_reg>;
+		status = "disabled";
+	};
+};
-- 
1.7.9.5



From chunfeng.yun at mediatek.com  Tue May 10 01:23:28 2016
From: chunfeng.yun at mediatek.com (Chunfeng Yun)
Date: Tue, 10 May 2016 16:23:28 +0800
Subject: Add MediaTek USB3 DRD Driver
Message-ID: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>

>From 5e3e992dc3c02eda12f5cf984a18a57f0207333d Mon Sep 17 00:00:00 2001
From: Chunfeng Yun <chunfeng.yun at mediatek.com>
Date: Tue, 10 May 2016 16:04:25 +0800
Subject: [PATCH 0/6] Add MediaTek USB3 DRD Driver

These patches introduce the MediaTek USB3 dual-role controller
driver.

The driver can be configured as Dual-Role Device (DRD),
Peripheral Only and Host Only (xHCI) modes. It works well
with Mass Storage, RNDIS and g_zero on FS/HS and SS. And it is
tested on MT8173 platform which only contains USB2.0 device IP,
and on MT6290 platform which contains USB3.0 device IP.


Chunfeng Yun (6):
  dt-bindings: mt8173-xhci: support host side of dual-role mode
  usb: xhci-mtk: make IPPC register optional
  dt-bindings: mtu3: add devicetree bindings
  usb: Add MediaTek USB3 DRD Driver
  arm64: dts: mediatek: add USB3 DRD driver
  pinctrl: mt8173: set GPIO16 to usb iddig mode

 .../devicetree/bindings/usb/mt8173-xhci.txt        |   48 ++
 Documentation/devicetree/bindings/usb/mtu3.txt     |   86 ++
 arch/arm64/boot/dts/mediatek/mt8173-evb.dts        |   46 +-
 arch/arm64/boot/dts/mediatek/mt8173.dtsi           |   28 +-
 drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h      |    2 +-
 drivers/usb/Kconfig                                |    2 +
 drivers/usb/Makefile                               |    1 +
 drivers/usb/host/xhci-mtk.c                        |   32 +-
 drivers/usb/mtu3/Kconfig                           |   47 ++
 drivers/usb/mtu3/Makefile                          |   20 +
 drivers/usb/mtu3/mtu3.h                            |  422 ++++++++++
 drivers/usb/mtu3/mtu3_core.c                       |  877 +++++++++++++++++++
 drivers/usb/mtu3/mtu3_dr.c                         |  353 ++++++++
 drivers/usb/mtu3/mtu3_dr.h                         |  108 +++
 drivers/usb/mtu3/mtu3_gadget.c                     |  735 ++++++++++++++++
 drivers/usb/mtu3/mtu3_gadget_ep0.c                 |  889 ++++++++++++++++++++
 drivers/usb/mtu3/mtu3_host.c                       |  294 +++++++
 drivers/usb/mtu3/mtu3_hw_regs.h                    |  474 +++++++++++
 drivers/usb/mtu3/mtu3_plat.c                       |  496 +++++++++++
 drivers/usb/mtu3/mtu3_qmu.c                        |  599 +++++++++++++
 drivers/usb/mtu3/mtu3_qmu.h                        |   43 +
 21 files changed, 5587 insertions(+), 15 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/mtu3.txt
 create mode 100644 drivers/usb/mtu3/Kconfig
 create mode 100644 drivers/usb/mtu3/Makefile
 create mode 100644 drivers/usb/mtu3/mtu3.h
 create mode 100644 drivers/usb/mtu3/mtu3_core.c
 create mode 100644 drivers/usb/mtu3/mtu3_dr.c
 create mode 100644 drivers/usb/mtu3/mtu3_dr.h
 create mode 100644 drivers/usb/mtu3/mtu3_gadget.c
 create mode 100644 drivers/usb/mtu3/mtu3_gadget_ep0.c
 create mode 100644 drivers/usb/mtu3/mtu3_host.c
 create mode 100644 drivers/usb/mtu3/mtu3_hw_regs.h
 create mode 100644 drivers/usb/mtu3/mtu3_plat.c
 create mode 100644 drivers/usb/mtu3/mtu3_qmu.c
 create mode 100644 drivers/usb/mtu3/mtu3_qmu.h

-- 
1.7.9.5



From chunfeng.yun at mediatek.com  Tue May 10 01:23:30 2016
From: chunfeng.yun at mediatek.com (Chunfeng Yun)
Date: Tue, 10 May 2016 16:23:30 +0800
Subject: [PATCH 2/6] usb: xhci-mtk: make IPPC register optional
In-Reply-To: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <1462868614-20602-3-git-send-email-chunfeng.yun@mediatek.com>

Make IPPC register optional to support host side of dual-role mode,
due to it is moved into common glue layer for simplification.

Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
---
 drivers/usb/host/xhci-mtk.c |   32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 79959f1..dc86832 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -94,6 +94,9 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk)
 	int ret;
 	int i;
 
+	if (ippc == NULL)
+		return 0;
+
 	/* power on host ip */
 	value = readl(&ippc->ip_pw_ctr1);
 	value &= ~CTRL1_IP_HOST_PDN;
@@ -139,6 +142,9 @@ static int xhci_mtk_host_disable(struct xhci_hcd_mtk *mtk)
 	int ret;
 	int i;
 
+	if (ippc == NULL)
+		return 0;
+
 	/* power down all u3 ports */
 	for (i = 0; i < mtk->num_u3_ports; i++) {
 		value = readl(&ippc->u3_ctrl_p[i]);
@@ -173,6 +179,9 @@ static int xhci_mtk_ssusb_config(struct xhci_hcd_mtk *mtk)
 	struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs;
 	u32 value;
 
+	if (ippc == NULL)
+		return 0;
+
 	/* reset whole ip */
 	value = readl(&ippc->ip_pw_ctr0);
 	value |= CTRL0_IP_SW_RST;
@@ -475,6 +484,7 @@ static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci)
 /* called during probe() after chip reset completes */
 static int xhci_mtk_setup(struct usb_hcd *hcd)
 {
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 	struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
 	int ret;
 
@@ -482,12 +492,21 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
 		ret = xhci_mtk_ssusb_config(mtk);
 		if (ret)
 			return ret;
+	}
+
+	ret = xhci_gen_setup(hcd, xhci_mtk_quirks);
+	if (ret)
+		return ret;
+
+	if (usb_hcd_is_primary_hcd(hcd)) {
+		mtk->num_u3_ports = xhci->num_usb3_ports;
+		mtk->num_u2_ports = xhci->num_usb2_ports;
 		ret = xhci_mtk_sch_init(mtk);
 		if (ret)
 			return ret;
 	}
 
-	return xhci_gen_setup(hcd, xhci_mtk_quirks);
+	return ret;
 }
 
 static int xhci_mtk_probe(struct platform_device *pdev)
@@ -595,11 +614,14 @@ static int xhci_mtk_probe(struct platform_device *pdev)
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_len = resource_size(res);
 
+	mtk->ippc_regs = NULL;
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	mtk->ippc_regs = devm_ioremap_resource(dev, res);
-	if (IS_ERR(mtk->ippc_regs)) {
-		ret = PTR_ERR(mtk->ippc_regs);
-		goto put_usb2_hcd;
+	if (res) {	/* ippc register is optional */
+		mtk->ippc_regs = devm_ioremap_resource(dev, res);
+		if (IS_ERR(mtk->ippc_regs)) {
+			ret = PTR_ERR(mtk->ippc_regs);
+			goto put_usb2_hcd;
+		}
 	}
 
 	for (phy_num = 0; phy_num < mtk->num_phys; phy_num++) {
-- 
1.7.9.5



From chunfeng.yun at mediatek.com  Tue May 10 01:23:33 2016
From: chunfeng.yun at mediatek.com (Chunfeng Yun)
Date: Tue, 10 May 2016 16:23:33 +0800
Subject: [PATCH 5/6] arm64: dts: mediatek: add USB3 DRD driver
In-Reply-To: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <1462868614-20602-6-git-send-email-chunfeng.yun@mediatek.com>

USB3 DRD driver is added for MT8173-EVB, and xHCI driver
becomes its subnode

Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8173-evb.dts |   46 +++++++++++++++++++++++++--
 arch/arm64/boot/dts/mediatek/mt8173.dtsi    |   28 ++++++++++++----
 2 files changed, 65 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
index 7453a47..682dfd7 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
@@ -34,6 +34,11 @@
 
 	chosen { };
 
+	extcon_usb: extcon_iddig {
+		compatible = "linux,extcon-usb-gpio";
+		id-gpio = <&pio 16 GPIO_ACTIVE_HIGH>;
+	};
+
 	usb_p1_vbus: regulator at 0 {
 		compatible = "regulator-fixed";
 		regulator-name = "usb_vbus";
@@ -42,6 +47,16 @@
 		gpio = <&pio 130 GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 	};
+
+	usb_p0_vbus: regulator at 1 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&pio 9 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
 };
 
 &i2c1 {
@@ -205,6 +220,20 @@
 			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
 		};
 	};
+
+	usb_id_pins_float: usb_iddig_pull_up {
+		pins_iddig {
+			pinmux = <MT8173_PIN_16_IDDIG__FUNC_IDDIG>;
+			bias-pull-up;
+		};
+	};
+
+	usb_id_pins_ground: usb_iddig_pull_down {
+		pins_iddig {
+			pinmux = <MT8173_PIN_16_IDDIG__FUNC_IDDIG>;
+			bias-pull-down;
+		};
+	};
 };
 
 &pwm0 {
@@ -431,12 +460,25 @@
 	status = "okay";
 };
 
+&ssusb {
+	vusb33-supply = <&mt6397_vusb_reg>;
+	vbus-supply = <&usb_p0_vbus>;
+	extcon = <&extcon_usb>;
+	dr_mode = "otg";
+	mediatek,enable-wakeup;
+	pinctrl-names = "default", "id_float", "id_ground";
+	pinctrl-0 = <&usb_id_pins_float>;
+	pinctrl-1 = <&usb_id_pins_float>;
+	pinctrl-2 = <&usb_id_pins_ground>;
+	status = "okay";
+};
+
 &uart0 {
 	status = "okay";
 };
 
-&usb30 {
+&usb_host {
 	vusb33-supply = <&mt6397_vusb_reg>;
 	vbus-supply = <&usb_p1_vbus>;
-	mediatek,wakeup-src = <1>;
+	status = "okay";
 };
diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index eab7efc..34821db 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -548,11 +548,14 @@
 			status = "disabled";
 		};
 
-		usb30: usb at 11270000 {
-			compatible = "mediatek,mt8173-xhci";
-			reg = <0 0x11270000 0 0x1000>,
+		ssusb: usb at 11271000 {
+			compatible = "mediatek,mt8173-mtu3";
+			reg = <0 0x11271000 0 0x3000>,
 			      <0 0x11280700 0 0x0100>;
-			interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
+			reg-names = "mac", "ippc";
+			interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>;
+			phys = <&phy_port0 PHY_TYPE_USB3>,
+			       <&phy_port1 PHY_TYPE_USB2>;
 			power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
 			clocks = <&topckgen CLK_TOP_USB30_SEL>,
 				 <&pericfg CLK_PERI_USB0>,
@@ -560,10 +563,21 @@
 			clock-names = "sys_ck",
 				      "wakeup_deb_p0",
 				      "wakeup_deb_p1";
-			phys = <&phy_port0 PHY_TYPE_USB3>,
-			       <&phy_port1 PHY_TYPE_USB2>;
 			mediatek,syscon-wakeup = <&pericfg>;
-			status = "okay";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+			status = "disabled";
+
+			usb_host: xhci at 11270000 {
+				compatible = "mediatek,mt8173-xhci";
+				reg = <0 0x11270000 0 0x1000>;
+				interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
+				power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
+				clocks = <&topckgen CLK_TOP_USB30_SEL>;
+				clock-names = "sys_ck";
+				status = "disabled";
+			};
 		};
 
 		u3phy: usb-phy at 11290000 {
-- 
1.7.9.5



From chunfeng.yun at mediatek.com  Tue May 10 01:23:34 2016
From: chunfeng.yun at mediatek.com (Chunfeng Yun)
Date: Tue, 10 May 2016 16:23:34 +0800
Subject: [PATCH 6/6] pinctrl: mt8173: set GPIO16 to usb iddig mode
In-Reply-To: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <1462868614-20602-7-git-send-email-chunfeng.yun@mediatek.com>

the default mode of GPIO16 pin is gpio, when set EINT16 to
IRQ_TYPE_LEVEL_HIGH, no interrupt is triggered, it can be
fixed when set its default mode as usb iddig.

Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
---
 drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h
index 13e5b68..9b018fd 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h
@@ -201,7 +201,7 @@ static const struct mtk_desc_pin mtk_pins_mt8173[] = {
 	MTK_PIN(
 		PINCTRL_PIN(16, "IDDIG"),
 		NULL, "mt8173",
-		MTK_EINT_FUNCTION(0, 16),
+		MTK_EINT_FUNCTION(1, 16),
 		MTK_FUNCTION(0, "GPIO16"),
 		MTK_FUNCTION(1, "IDDIG"),
 		MTK_FUNCTION(2, "CMFLASH"),
-- 
1.7.9.5



From daniel.lezcano at linaro.org  Tue May 10 01:28:47 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 10 May 2016 10:28:47 +0200
Subject: [PATCH] firmware/drivers/psci: Fix unused functions when
 CONFIG_CPU_IDLE=n
In-Reply-To: <20160510082250.GA14662@red-moon>
References: <1462864729-11793-1-git-send-email-daniel.lezcano@linaro.org>
 <20160510082250.GA14662@red-moon>
Message-ID: <57319BBF.7060306@linaro.org>

On 05/10/2016 10:22 AM, Lorenzo Pieralisi wrote:
> On Tue, May 10, 2016 at 09:18:49AM +0200, Daniel Lezcano wrote:
>> On the ARM64 architecture, when CPUIDLE is not set in the configuration,
>> the compilation raises a couple of warnings:
>>
>> drivers/firmware/psci.c:70:12: warning: 'psci_pd_power_off' defined but not used [-Wunused-function]
>> drivers/firmware/psci.c:273:12: warning: 'psci_set_suspend_mode_osi' defined but not used [-Wunused-function]
>
> That's not mainline code :)

Ha ha ! Sounds like my scripts are not yet ready :)

Sorry for the noise.

   -- Daniel



From kernel at martin.sperl.org  Tue May 10 01:32:09 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Tue, 10 May 2016 10:32:09 +0200
Subject: [PATCH 0/5] clk: bcm2835: add flags for mash and parent clocks
In-Reply-To: <87h9e6yb6i.fsf@eliezer.anholt.net>
References: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
 <87h9e6yb6i.fsf@eliezer.anholt.net>
Message-ID: <57319C89.7040705@martin.sperl.org>



On 10.05.2016 03:05, Eric Anholt wrote:
> kernel at martin.sperl.org writes:
>
>> From: Martin Sperl <kernel at martin.sperl.org>
>>
>> Allow flags to be set on a per clock index basis, which control:
>> * the parent clocks selected when not setting clocks explicitly
>
> I don't think we need this other than avoiding PLLC.  What else do you
> want to filter, and why?
What about potentially disabling PLLA_per or PLLH_aux?
Under some circumstances it may make sense to avoid those clocks.
(or testdebug for that matter).

One of the reasons can be to avoid low dividers - see also mash below

>
>> * the clock mode with regards to integer only or higher order mash
>
> Please provide justification in the commit message explaining why there
> is no obvious mash setting to just implement in clk-bcm2835.c, but that
> that a better policy can be encoded in the DT.

The normal fractional divider will vary the effective period length
between int(div)/Fparent and (int(div)+1)/Fparent.

So the device (say DAC or other) connected needs to support in
principle Fparent/int(div) as a clock.

But for higher order mash the HW will spread the period length between:
(int(div)-3)/Fparent and (int(div)+4)/Fparent.

This value may be outside of the frequencies supported by the attached
HW. That is why mash is not enabled by default for mash clocks - only
div.

That is also why we need to have this configurable.

Also obviously higher parent clock frequencies result in higher dividers
for the same target-frequency. So the above effect is less dramatic
when using plld_per (or pllc for that matter) compared to the main
19.2MHz oscillator, as for 32bit stereo audio at 96kHz (equivalent to
6144000Hz) in the first case we have a divider of 81.38 while for the
second (osc) case we have a divider of 3.125.

The use of mash3 is impossible for osc but the use of mash 2 would
spread the frequencies between 9.6MHz (div=2) and 3.84MHz (div=5).

For plld_per as parent using mash3 instead we get the range:
6410256.4Hz (div=78) and 5882352.9Hz (div=85), which is a much more
acceptable range and should not impact the device that much.

So enabling mash 3 by default is not in the best interest hence it is
not done.

This also shows why with some devices it may be preferable to configure
that only pllc is used and then with mash 3.

So this patchset tries to accomodate that - even if not in a
perfect way - I would have preferred to have this in the dt-node that
is claiming that clock, but I did not want to go that far (yet) adding
another method to clock_op.

To answer your comments on the patches themselves:
I had also been investigating the use of "assigned-clock-parents".
Something like this will not work:
i2s at ... {
   clock = <&preman PCM>;
   assigned-clocks = <&cprman PCM>, <&pcrman PCM>
   assigned-clock-parents = <&osc>, <&cprman PLLD_PER>;
}
because what it does it:
* call clk_set_parent(pcm, osc);
* call clk_set_parent(pcm, plld_per);

(if you add "assigned-clock-rates" into the mix then
clk_set_rate(pcm, rate) is also called separately).

So there is no way to "keep" track of the parent clocks we wanted
assigned.

As far as I can see the only thing that would work is to implement
an extension to the dt that would define "assigned-clock-flags"
and have a set_flags(struct clk_hw *, u32 flags) method in
clk_ops.

So maybe someone has some better ideas of how to solve this.

Martin

As a side note: selection of parent oscillator and corresponding mash
may have distinct noise behavior on the same device, where for
32bit*2 at 48k it is the main oscillator with mash3 while the second best
match would be pllc with mash2 - not mash3, which has the worsted SN
from all tested!

This behavior obviously changes with different "target frequencies"
so it may even be necessary to account for the different target
frequencies.

But that is for a different discussion.


From eric.auger at linaro.org  Tue May 10 01:33:40 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 10:33:40 +0200
Subject: [PATCH v3 06/55] KVM: arm/arm64: arch_timer: Remove irq_phys_map
In-Reply-To: <1462531568-9799-7-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-7-git-send-email-andre.przywara@arm.com>
Message-ID: <57319CE4.30608@linaro.org>

Hi Andre,
On 05/06/2016 12:45 PM, Andre Przywara wrote:
> Now that the interface between the arch timer and the VGIC does not
> require passing the irq_phys_map entry pointer anymore, let's remove
> it from the virtual arch timer and use the virtual IRQ number instead
> directly.
> The remaining pointer returned by kvm_vgic_map_phys_irq() will be
> removed in the following patch.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - remove extra virt_irq member from struct, instead use irq.irq directly
> 
> Changelog v2 .. v3:
> - remove bogus validity check from kvm_vgic_unmap_phys_irq()
> 
>  include/kvm/arm_arch_timer.h |  3 ---
>  virt/kvm/arm/arch_timer.c    | 10 ++++------
>  2 files changed, 4 insertions(+), 9 deletions(-)
> 
> diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
> index b651aed..a47b7de 100644
> --- a/include/kvm/arm_arch_timer.h
> +++ b/include/kvm/arm_arch_timer.h
> @@ -53,9 +53,6 @@ struct arch_timer_cpu {
>  	/* Timer IRQ */
>  	struct kvm_irq_level		irq;
>  
> -	/* VGIC mapping */
> -	struct irq_phys_map		*map;
> -
>  	/* Active IRQ state caching */
>  	bool				active_cleared_last;
>  };
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index 29d597d..f2cd188 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -176,10 +176,10 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
>  
>  	timer->active_cleared_last = false;
>  	timer->irq.level = new_level;
> -	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
> +	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
>  				   timer->irq.level);
>  	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
> -					 timer->map->virt_irq,
> +					 timer->irq.irq,
>  					 timer->irq.level);
>  	WARN_ON(ret);
>  }
> @@ -277,7 +277,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
>  	* exit.
>  	*/
>  	phys_active = timer->irq.level ||
> -			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
> +			kvm_vgic_map_is_active(vcpu, timer->irq.irq);
>  
>  	/*
>  	 * We want to avoid hitting the (re)distributor as much as
> @@ -379,7 +379,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
>  	if (WARN_ON(IS_ERR(map)))
>  		return PTR_ERR(map);
>  
> -	timer->map = map;
>  	return 0;
>  }
>  
> @@ -522,8 +521,7 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
>  	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
>  
>  	timer_disarm(timer);
> -	if (timer->map)
> -		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
> +	kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq);
Reviewed-by: Eric Auger <eric.auger at linaro.org>

Eric
>  }
>  
>  void kvm_timer_enable(struct kvm *kvm)
> 



From arnd at arndb.de  Tue May 10 01:36:40 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 10:36:40 +0200
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <573190CF.6030408@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160506123731.GA11959@yury-N73SV> <573190CF.6030408@huawei.com>
Message-ID: <9651510.pg5Vmm8vKS@wuerfel>

On Tuesday 10 May 2016 15:42:07 Zhangjian wrote:
> On 2016/5/6 20:37, Yury Norov wrote:
> > On Fri, May 06, 2016 at 08:16:48PM +0800, Zhangjian (Bamvor) wrote:
> >
> > AFAIR, here we don't shift offset, as it's 64-bit both in user-
> > and kernel-space,
> In your ilp32-2.22 branch, you wrapper mmap to mmap2 in which type of
> offset is off_t. And off_t is 32bit in ilp32, correct?
> "sysdeps/unix/sysv/linux/aarch64/ilp32/mmap64.c"
> /* mmap is provided by mmap as they are the same. */
> void *__mmap (void *__addr, size_t __len, int __prot,
>                       int __flags, int __fd, __off_t __offset)
> {
>     void *result;
>     result = (void *)
>       INLINE_SYSCALL (mmap2, 6, __addr,
>                       __len, __prot, __flags, __fd, __offset);
>     return result;
> }

__off_t should be 'long long' on new architectures, and map
to __kernel_loff_t.

Can you see how it is defined?

	Arnd


From adrian.hunter at intel.com  Tue May 10 01:35:29 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 11:35:29 +0300
Subject: [PATCH 17/23] mmc: sdhci: add standard hw auto retuning support
In-Reply-To: <1460741387-23815-18-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-18-git-send-email-aisheng.dong@nxp.com>
Message-ID: <57319D51.8030907@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> If HW supports SDHCI_TUNING_MODE_3 which is auto retuning, we won't

Since this is about tuning mode 3, could you put that in the subject e.g.
"Add support for auto re-tuning (tuning mode 3)"

> retune during runtime suspend and resume, instead we use Re-tuning
> Request signaled via SDHCI_INT_RETUNE interrupt to do retuning and
> hw auto retuning during data transfer to guarantee the signal sample
> window correction.
> 
> This can avoid a mass of repeatly retuning during small file system

repeatly -> repeatedly

> data access and improve the performance.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
> ---
>  drivers/mmc/host/sdhci.c | 18 ++++++++++++++----
>  drivers/mmc/host/sdhci.h |  3 +++
>  2 files changed, 17 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 2eb0e34..0027b87 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -252,6 +252,9 @@ static void sdhci_init(struct sdhci_host *host, int soft)
>  		    SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
>  		    SDHCI_INT_RESPONSE;
>  
> +	if (host->tuning_mode == SDHCI_TUNING_MODE_3)

Tuning mode 2 uses this as well.  Might as well add it here.

> +		host->ier |= SDHCI_INT_RETUNE;
> +
>  	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
>  	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
>  
> @@ -2477,6 +2480,9 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
>  			pr_err("%s: Card is consuming too much power!\n",
>  				mmc_hostname(host->mmc));
>  
> +		if (intmask & SDHCI_INT_RETUNE)
> +			mmc_retune_needed(host->mmc);
> +

Also need to add SDHCI_INT_RETUNE to the bits cleared further on, otherwise
it will show up in the "Unexpected interrupt" message

>  		if (intmask & SDHCI_INT_CARD_INT) {
>  			sdhci_enable_sdio_irq_nolock(host, false);
>  			host->thread_isr |= SDHCI_INT_CARD_INT;
> @@ -2575,8 +2581,10 @@ int sdhci_suspend_host(struct sdhci_host *host)
>  {
>  	sdhci_disable_card_detection(host);
>  
> -	mmc_retune_timer_stop(host->mmc);
> -	mmc_retune_needed(host->mmc);
> +	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
> +		mmc_retune_timer_stop(host->mmc);
> +		mmc_retune_needed(host->mmc);
> +	}

Probably wouldn't hurt to stop the timer always whether it's going or not.
And tuning mode 2 is not auto re-tuning, so I would still expect to need
re-tuning after power loss i.e.

	mmc_retune_timer_stop(host->mmc);
	if (host->tuning_mode != SDHCI_TUNING_MODE_3)
		mmc_retune_needed(host->mmc);

>  
>  	if (!device_may_wakeup(mmc_dev(host->mmc))) {
>  		host->ier = 0;
> @@ -2651,8 +2659,10 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
>  {
>  	unsigned long flags;
>  
> -	mmc_retune_timer_stop(host->mmc);
> -	mmc_retune_needed(host->mmc);
> +	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
> +		mmc_retune_timer_stop(host->mmc);
> +		mmc_retune_needed(host->mmc);
> +	}

Ditto

>  
>  	spin_lock_irqsave(&host->lock, flags);
>  	host->ier &= SDHCI_INT_CARD_INT;
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index afa4de8..2c2404f 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -128,6 +128,7 @@
>  #define  SDHCI_INT_CARD_INSERT	0x00000040
>  #define  SDHCI_INT_CARD_REMOVE	0x00000080
>  #define  SDHCI_INT_CARD_INT	0x00000100
> +#define  SDHCI_INT_RETUNE	0x00001000
>  #define  SDHCI_INT_ERROR	0x00008000
>  #define  SDHCI_INT_TIMEOUT	0x00010000
>  #define  SDHCI_INT_CRC		0x00020000
> @@ -514,6 +515,8 @@ struct sdhci_host {
>  	unsigned int		tuning_count;	/* Timer count for re-tuning */
>  	unsigned int		tuning_mode;	/* Re-tuning mode supported by host */
>  #define SDHCI_TUNING_MODE_1	0
> +#define SDHCI_TUNING_MODE_2	1
> +#define SDHCI_TUNING_MODE_3	2
>  
>  	unsigned long private[0] ____cacheline_aligned;
>  };
> 



From marc.zyngier at arm.com  Tue May 10 01:46:23 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 09:46:23 +0100
Subject: [PATCH v2] KVM: arm/arm64: vgic-new: Switch to firmware-independent
 probing
Message-ID: <1462869983-5410-1-git-send-email-marc.zyngier@arm.com>

As we did for the legacy code, switch the new VGIC implementation
the firmware-independent probing, giving us ACPI support for free.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
- From v1: Some additional cleanups, rebased on the lastest drop.

 virt/kvm/arm/vgic/vgic-init.c | 39 ++++++++++----------
 virt/kvm/arm/vgic/vgic-v2.c   | 82 +++++++++++++++----------------------------
 virt/kvm/arm/vgic/vgic-v3.c   | 44 ++++++-----------------
 virt/kvm/arm/vgic/vgic.h      |  8 +++--
 4 files changed, 63 insertions(+), 110 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 7fefb12..0c2c504 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -17,8 +17,6 @@
 #include <linux/uaccess.h>
 #include <linux/interrupt.h>
 #include <linux/cpu.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
 #include <asm/kvm_mmu.h>
@@ -387,14 +385,6 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static const struct of_device_id vgic_ids[] = {
-	{ .compatible = "arm,cortex-a15-gic",	.data = vgic_v2_probe, },
-	{ .compatible = "arm,cortex-a7-gic",	.data = vgic_v2_probe, },
-	{ .compatible = "arm,gic-400",		.data = vgic_v2_probe, },
-	{ .compatible = "arm,gic-v3",		.data = vgic_v3_probe, },
-	{},
-};
-
 /**
  * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable
  * according to the host GIC model. Accordingly calls either
@@ -403,23 +393,33 @@ static const struct of_device_id vgic_ids[] = {
  */
 int kvm_vgic_hyp_init(void)
 {
-	const struct of_device_id *matched_id;
-	const int (*vgic_probe)(struct device_node *);
-	struct device_node *vgic_node;
+	const struct gic_kvm_info *gic_kvm_info;
 	int ret;
 
-	vgic_node = of_find_matching_node_and_match(NULL,
-						    vgic_ids, &matched_id);
-	if (!vgic_node) {
-		kvm_err("error: no compatible GIC node found\n");
+	gic_kvm_info = gic_get_kvm_info();
+	if (!gic_kvm_info)
 		return -ENODEV;
+
+	if (!gic_kvm_info->maint_irq) {
+		kvm_err("No vgic maintenance irq\n");
+		return -ENXIO;
 	}
 
-	vgic_probe = matched_id->data;
-	ret = vgic_probe(vgic_node);
+	switch (gic_kvm_info->type) {
+	case GIC_V2:
+		ret = vgic_v2_probe(gic_kvm_info);
+		break;
+	case GIC_V3:
+		ret = vgic_v3_probe(gic_kvm_info);
+		break;
+	default:
+		ret = -ENODEV;
+	};
+
 	if (ret)
 		return ret;
 
+	kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
 	ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
 				 vgic_maintenance_handler,
 				 "vgic", kvm_get_running_vcpus());
@@ -437,6 +437,7 @@ int kvm_vgic_hyp_init(void)
 
 	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
 
+	kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq);
 	return 0;
 
 out_free_irq:
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 4493593..e88b5aa 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -18,9 +18,6 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
 #include <asm/kvm_mmu.h>
 
 #include "vgic.h"
@@ -278,81 +275,58 @@ out:
  *
  * Returns 0 if a GICv2 has been found, returns an error code otherwise
  */
-int vgic_v2_probe(struct device_node *vgic_node)
+int vgic_v2_probe(const struct gic_kvm_info *info)
 {
 	int ret;
-	struct resource vctrl_res;
-	struct resource vcpu_res;
 
-	kvm_vgic_global_state.maint_irq = irq_of_parse_and_map(vgic_node, 0);
-	if (!kvm_vgic_global_state.maint_irq) {
-		kvm_err("error getting vgic maintenance irq from DT\n");
-		ret = -ENXIO;
-		goto out;
+	if (!info->vctrl.start) {
+		kvm_err("GICH not present in the firmware table\n");
+		return -ENXIO;
 	}
 
-	ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
-	if (ret) {
-		kvm_err("Cannot obtain GICH resource\n");
-		goto out;
+	if (!PAGE_ALIGNED(info->vcpu.start)) {
+		kvm_err("GICV physical address 0x%llx not page aligned\n",
+			(unsigned long long)info->vcpu.start);
+		return -ENXIO;
+	}
+
+	if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
+		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+			(unsigned long long)resource_size(&info->vcpu),
+			PAGE_SIZE);
+		return -ENXIO;
 	}
 
-	kvm_vgic_global_state.vctrl_base = of_iomap(vgic_node, 2);
+	kvm_vgic_global_state.vctrl_base = ioremap(info->vctrl.start,
+						   resource_size(&info->vctrl));
 	if (!kvm_vgic_global_state.vctrl_base) {
 		kvm_err("Cannot ioremap GICH\n");
-		ret = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
 
 	kvm_vgic_global_state.nr_lr =
 		readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
-	kvm_vgic_global_state.nr_lr = (kvm_vgic_global_state.nr_lr & 0x3f) + 1;
+	kvm_vgic_global_state.nr_lr &= 0x3f;
+	kvm_vgic_global_state.nr_lr += 1;
 
 	ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
 				     kvm_vgic_global_state.vctrl_base +
-					 resource_size(&vctrl_res),
-				     vctrl_res.start);
+					 resource_size(&info->vctrl),
+				     info->vctrl.start);
 	if (ret) {
 		kvm_err("Cannot map VCTRL into hyp\n");
-		goto out_unmap;
-	}
-
-	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
-		kvm_err("Cannot obtain GICV resource\n");
-		ret = -ENXIO;
-		goto out_unmap;
-	}
-
-	if (!PAGE_ALIGNED(vcpu_res.start)) {
-		kvm_err("GICV physical address 0x%llx not page aligned\n",
-			(unsigned long long)vcpu_res.start);
-		ret = -ENXIO;
-		goto out_unmap;
-	}
-
-	if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
-		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
-			(unsigned long long)resource_size(&vcpu_res),
-			PAGE_SIZE);
-		ret = -ENXIO;
-		goto out_unmap;
+		iounmap(kvm_vgic_global_state.vctrl_base);
+		return ret;
 	}
 
 	kvm_vgic_global_state.can_emulate_gicv2 = true;
 	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
 
-	kvm_vgic_global_state.vcpu_base = vcpu_res.start;
-
-	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
-		 vctrl_res.start, kvm_vgic_global_state.maint_irq);
-
+	kvm_vgic_global_state.vcpu_base = info->vcpu.start;
 	kvm_vgic_global_state.type = VGIC_V2;
 	kvm_vgic_global_state.max_gic_vcpus = VGIC_V2_MAX_CPUS;
-	goto out;
 
-out_unmap:
-	iounmap(kvm_vgic_global_state.vctrl_base);
-out:
-	of_node_put(vgic_node);
-	return ret;
+	kvm_info("vgic-v2@%llx\n", info->vctrl.start);
+
+	return 0;
 }
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 6d7422f..6073f5d 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -16,9 +16,6 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
 #include <asm/kvm_mmu.h>
 #include <asm/kvm_asm.h>
 
@@ -271,21 +268,9 @@ out:
  *
  * Returns 0 if a GICv3 has been found, returns an error code otherwise
  */
-int vgic_v3_probe(struct device_node *vgic_node)
+int vgic_v3_probe(const struct gic_kvm_info *info)
 {
-	u32 ich_vtr_el2;
-	u32 gicv_idx;
-	int ret = 0;
-	struct resource vcpu_res;
-
-	kvm_vgic_global_state.maint_irq = irq_of_parse_and_map(vgic_node, 0);
-	if (!kvm_vgic_global_state.maint_irq) {
-		kvm_err("error getting vgic maintenance irq from DT\n");
-		ret = -ENXIO;
-		goto out;
-	}
-
-	ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
+	u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
 
 	/*
 	 * The ListRegs field is 5 bits, but there is a architectural
@@ -294,27 +279,23 @@ int vgic_v3_probe(struct device_node *vgic_node)
 	kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
 	kvm_vgic_global_state.can_emulate_gicv2 = false;
 
-	if (of_property_read_u32(vgic_node, "#redistributor-regions",
-				 &gicv_idx))
-		gicv_idx = 1;
-
-	gicv_idx += 3; /* Also skip GICD, GICC, GICH */
-	if (of_address_to_resource(vgic_node, gicv_idx, &vcpu_res)) {
+	if (!info->vcpu.start) {
 		kvm_info("GICv3: no GICV resource entry\n");
 		kvm_vgic_global_state.vcpu_base = 0;
-	} else if (!PAGE_ALIGNED(vcpu_res.start)) {
+	} else if (!PAGE_ALIGNED(info->vcpu.start)) {
 		pr_warn("GICV physical address 0x%llx not page aligned\n",
-			(unsigned long long)vcpu_res.start);
+			(unsigned long long)info->vcpu.start);
 		kvm_vgic_global_state.vcpu_base = 0;
-	} else if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
+	} else if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
 		pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
-			(unsigned long long)resource_size(&vcpu_res),
+			(unsigned long long)resource_size(&info->vcpu),
 			PAGE_SIZE);
 		kvm_vgic_global_state.vcpu_base = 0;
 	} else {
-		kvm_vgic_global_state.vcpu_base = vcpu_res.start;
+		kvm_vgic_global_state.vcpu_base = info->vcpu.start;
 		kvm_vgic_global_state.can_emulate_gicv2 = true;
 		kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+		kvm_info("vgic-v2@%llx\n", info->vcpu.start);
 	}
 	if (kvm_vgic_global_state.vcpu_base == 0)
 		kvm_info("disabling GICv2 emulation\n");
@@ -324,10 +305,5 @@ int vgic_v3_probe(struct device_node *vgic_node)
 	kvm_vgic_global_state.type = VGIC_V3;
 	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
 
-	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
-		 vcpu_res.start, kvm_vgic_global_state.maint_irq);
-
-out:
-	of_node_put(vgic_node);
-	return ret;
+	return 0;
 }
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 5c7dc99..83d3c48 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,6 +16,8 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#include <linux/irqchip/arm-gic-common.h>
+
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
@@ -44,7 +46,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_enable(struct kvm_vcpu *vcpu);
-int vgic_v2_probe(struct device_node *vgic_node);
+int vgic_v2_probe(const struct gic_kvm_info *info);
 int vgic_v2_map_resources(struct kvm *kvm);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
@@ -58,7 +60,7 @@ void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_enable(struct kvm_vcpu *vcpu);
-int vgic_v3_probe(struct device_node *vgic_node);
+int vgic_v3_probe(const struct gic_kvm_info *info);
 int vgic_v3_map_resources(struct kvm *kvm);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
@@ -97,7 +99,7 @@ static inline void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
 }
 
-static inline int vgic_v3_probe(struct device_node *vgic_node)
+static inline int vgic_v3_probe(const struct gic_kvm_info *info)
 {
 	return -ENODEV;
 }
-- 
2.1.4



From tomi.valkeinen at ti.com  Tue May 10 01:47:38 2016
From: tomi.valkeinen at ti.com (Tomi Valkeinen)
Date: Tue, 10 May 2016 11:47:38 +0300
Subject: [PATCH v2 0/3] video: fbdev: imxfb: make it work again
In-Reply-To: <1462354998-5792-1-git-send-email-u.kleine-koenig@pengutronix.de>
References: <1462354998-5792-1-git-send-email-u.kleine-koenig@pengutronix.de>
Message-ID: <5731A02A.2070309@ti.com>

Hi,

On 04/05/16 12:43, Uwe Kleine-K?nig wrote:
> Hello,
> 
> this is v2 of the series which addresses the review comments I got vor
> (implicit) v1.
> 
> For patch 2 the question is still open if this is the right fix, but
> without this the display doesn't stay on. Patches 1 and 3 should be
> applicable independant of patch 2.

I picked patches 1 and 3, they look fine.

I still think patch 2 is just broken, it doesn't make sense to me.

If the regulator is enabled in probe, then it's always on, and
imxfb_lcd_set_power() should be removed as it never has any effect. But
that doesn't sound correct, as presumably the imxfb_lcd_set_power() has
worked at some point.

And shouldn't the regulator be disabled at least when suspending?

 Tomi

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160510/10c1277f/attachment.sig>

From boris.brezillon at free-electrons.com  Tue May 10 01:55:49 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 10 May 2016 10:55:49 +0200
Subject: [PATCH 1/2] Revert "mtd: atmel_nand: Support variable RB_EDGE
 interrupts"
In-Reply-To: <1462776680-5284-2-git-send-email-wenyou.yang@atmel.com>
References: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
 <1462776680-5284-2-git-send-email-wenyou.yang@atmel.com>
Message-ID: <20160510105549.50b60d8c@bbrezillon>

Hi Wenyou,

Can you add NAND maintainers/reviewers in Cc next time. And since you
revert a commit, you should also add the commit author in the loop.

On Mon, 9 May 2016 14:51:18 +0800
Wenyou Yang <wenyou.yang at atmel.com> wrote:

> This reverts commit 5ddc7bd43ccc ("mtd: atmel_nand: Support variable
> RB_EDGE interrupts")
> 
> Because for current SoCs, the RB_EDGE3(i.e. bit 27) of HSMC_SR
> register does not exist, the RB_EDGE0 (i.e. bit 24) is the ready/busy
> line edge status bit. It is a datasheet bug.

Romain, I thought you had a real use case on sama5d4 where this patch
was needed to make the whole thing work. Not sure why you submitted this
patch if you couldn't test it on a real board.

Wenyou, can you confirm that none of the existing SoCs support more
than one "native" R/B pin?

Thanks,

Boris

> 
> Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> ---
> 
>  .../devicetree/bindings/mtd/atmel-nand.txt         |  2 +-
>  drivers/mtd/nand/atmel_nand.c                      | 35 +++++-----------------
>  drivers/mtd/nand/atmel_nand_nfc.h                  |  3 +-
>  3 files changed, 10 insertions(+), 30 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> index d53aba9..3e7ee99 100644
> --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> @@ -39,7 +39,7 @@ Optional properties:
>  
>  Nand Flash Controller(NFC) is an optional sub-node
>  Required properties:
> -- compatible : "atmel,sama5d3-nfc" or "atmel,sama5d4-nfc".
> +- compatible : "atmel,sama5d3-nfc".
>  - reg : should specify the address and size used for NFC command registers,
>          NFC registers and NFC SRAM. NFC SRAM address and size can be absent
>          if don't want to use it.
> diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
> index efc8ea2..68b9160 100644
> --- a/drivers/mtd/nand/atmel_nand.c
> +++ b/drivers/mtd/nand/atmel_nand.c
> @@ -67,10 +67,6 @@ struct atmel_nand_caps {
>  	uint8_t pmecc_max_correction;
>  };
>  
> -struct atmel_nand_nfc_caps {
> -	uint32_t rb_mask;
> -};
> -
>  /*
>   * oob layout for large page size
>   * bad block info is on bytes 0 and 1
> @@ -129,7 +125,6 @@ struct atmel_nfc {
>  	/* Point to the sram bank which include readed data via NFC */
>  	void			*data_in_sram;
>  	bool			will_write_sram;
> -	const struct atmel_nand_nfc_caps *caps;
>  };
>  static struct atmel_nfc	nand_nfc;
>  
> @@ -1715,9 +1710,9 @@ static irqreturn_t hsmc_interrupt(int irq, void *dev_id)
>  		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE);
>  		ret = IRQ_HANDLED;
>  	}
> -	if (pending & host->nfc->caps->rb_mask) {
> +	if (pending & NFC_SR_RB_EDGE) {
>  		complete(&host->nfc->comp_ready);
> -		nfc_writel(host->nfc->hsmc_regs, IDR, host->nfc->caps->rb_mask);
> +		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE);
>  		ret = IRQ_HANDLED;
>  	}
>  	if (pending & NFC_SR_CMD_DONE) {
> @@ -1735,7 +1730,7 @@ static void nfc_prepare_interrupt(struct atmel_nand_host *host, u32 flag)
>  	if (flag & NFC_SR_XFR_DONE)
>  		init_completion(&host->nfc->comp_xfer_done);
>  
> -	if (flag & host->nfc->caps->rb_mask)
> +	if (flag & NFC_SR_RB_EDGE)
>  		init_completion(&host->nfc->comp_ready);
>  
>  	if (flag & NFC_SR_CMD_DONE)
> @@ -1753,7 +1748,7 @@ static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag)
>  	if (flag & NFC_SR_XFR_DONE)
>  		comp[index++] = &host->nfc->comp_xfer_done;
>  
> -	if (flag & host->nfc->caps->rb_mask)
> +	if (flag & NFC_SR_RB_EDGE)
>  		comp[index++] = &host->nfc->comp_ready;
>  
>  	if (flag & NFC_SR_CMD_DONE)
> @@ -1821,7 +1816,7 @@ static int nfc_device_ready(struct mtd_info *mtd)
>  		dev_err(host->dev, "Lost the interrupt flags: 0x%08x\n",
>  				mask & status);
>  
> -	return status & host->nfc->caps->rb_mask;
> +	return status & NFC_SR_RB_EDGE;
>  }
>  
>  static void nfc_select_chip(struct mtd_info *mtd, int chip)
> @@ -1994,8 +1989,8 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
>  		}
>  		/* fall through */
>  	default:
> -		nfc_prepare_interrupt(host, host->nfc->caps->rb_mask);
> -		nfc_wait_interrupt(host, host->nfc->caps->rb_mask);
> +		nfc_prepare_interrupt(host, NFC_SR_RB_EDGE);
> +		nfc_wait_interrupt(host, NFC_SR_RB_EDGE);
>  	}
>  }
>  
> @@ -2426,11 +2421,6 @@ static int atmel_nand_nfc_probe(struct platform_device *pdev)
>  		}
>  	}
>  
> -	nfc->caps = (const struct atmel_nand_nfc_caps *)
> -		of_device_get_match_data(&pdev->dev);
> -	if (!nfc->caps)
> -		return -ENODEV;
> -
>  	nfc_writel(nfc->hsmc_regs, IDR, 0xffffffff);
>  	nfc_readl(nfc->hsmc_regs, SR);	/* clear the NFC_SR */
>  
> @@ -2459,17 +2449,8 @@ static int atmel_nand_nfc_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> -static const struct atmel_nand_nfc_caps sama5d3_nfc_caps = {
> -	.rb_mask = NFC_SR_RB_EDGE0,
> -};
> -
> -static const struct atmel_nand_nfc_caps sama5d4_nfc_caps = {
> -	.rb_mask = NFC_SR_RB_EDGE3,
> -};
> -
>  static const struct of_device_id atmel_nand_nfc_match[] = {
> -	{ .compatible = "atmel,sama5d3-nfc", .data = &sama5d3_nfc_caps },
> -	{ .compatible = "atmel,sama5d4-nfc", .data = &sama5d4_nfc_caps },
> +	{ .compatible = "atmel,sama5d3-nfc" },
>  	{ /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match);
> diff --git a/drivers/mtd/nand/atmel_nand_nfc.h b/drivers/mtd/nand/atmel_nand_nfc.h
> index 0bbc1fa..4d5d262 100644
> --- a/drivers/mtd/nand/atmel_nand_nfc.h
> +++ b/drivers/mtd/nand/atmel_nand_nfc.h
> @@ -42,8 +42,7 @@
>  #define		NFC_SR_UNDEF		(1 << 21)
>  #define		NFC_SR_AWB		(1 << 22)
>  #define		NFC_SR_ASE		(1 << 23)
> -#define		NFC_SR_RB_EDGE0		(1 << 24)
> -#define		NFC_SR_RB_EDGE3		(1 << 27)
> +#define		NFC_SR_RB_EDGE		(1 << 24)
>  
>  #define ATMEL_HSMC_NFC_IER	0x0c
>  #define ATMEL_HSMC_NFC_IDR	0x10



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


From marc.zyngier at arm.com  Tue May 10 01:57:03 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 09:57:03 +0100
Subject: [PATCH v3 09/55] KVM: arm/arm64: Fix MMIO emulation data handling
In-Reply-To: <1462531568-9799-10-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-10-git-send-email-andre.przywara@arm.com>
Message-ID: <5731A25F.4020203@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> When the kernel was handling a guest MMIO read access internally, we
> need to copy the emulation result into the run->mmio structure in order
> for the kvm_handle_mmio_return() function to pick it up and inject the
> 	result back into the guest.
> 
> Currently the only user of kvm_io_bus for ARM is the VGIC, which did
> this copying itself, so this was not causing issues so far.
> 
> But with the upcoming new vgic implementation we need this done
> properly.
> 
> Update the kvm_handle_mmio_return description and cleanup the code to
> only perform a single copying when needed.
> 
> Code and commit message inspired by Andre Przywara.
> 
> Reported-by: Andre Przywara <andre.przywara at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...


From marc.zyngier at arm.com  Tue May 10 01:59:43 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 09:59:43 +0100
Subject: [PATCH v3 10/55] KVM: arm/arm64: Export mmio_read/write_bus
In-Reply-To: <1462531568-9799-11-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-11-git-send-email-andre.przywara@arm.com>
Message-ID: <5731A2FF.5050203@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> Rename mmio_{read,write}_bus to kvm_mmio_{read,write}_bus and export
> them out of mmio.c.
> This will be needed later for the new VGIC implementation.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Acked-by: Marc Zyngier <marc.zyngier at arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...


From Wenyou.Yang at atmel.com  Tue May 10 01:59:44 2016
From: Wenyou.Yang at atmel.com (Yang, Wenyou)
Date: Tue, 10 May 2016 08:59:44 +0000
Subject: [PATCH 1/2] Revert "mtd: atmel_nand: Support variable RB_EDGE
 interrupts"
In-Reply-To: <20160510105549.50b60d8c@bbrezillon>
References: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
 <1462776680-5284-2-git-send-email-wenyou.yang@atmel.com>
 <20160510105549.50b60d8c@bbrezillon>
Message-ID: <B256D81BAE5131468A838E5D7A243641D64880F8@penmbx01>



> -----Original Message-----
> From: Boris Brezillon [mailto:boris.brezillon at free-electrons.com]
> Sent: 2016?5?10? 16:56
> To: Yang, Wenyou <Wenyou.Yang at atmel.com>; Romain Izard
> <romain.izard.pro at gmail.com>
> Cc: Brian Norris <computersforpeace at gmail.com>; David Woodhouse
> <dwmw2 at infradead.org>; Rob Herring <robh+dt at kernel.org>; Pawel Moll
> <pawel.moll at arm.com>; Mark Brown <broonie at kernel.org>; Ian Campbell
> <ijc+devicetree at hellion.org.uk>; Kumar Gala <galak at codeaurora.org>;
> devicetree at vger.kernel.org; Russell King <linux at arm.linux.org.uk>; Josh Wu
> <rainyfeeling at outlook.com>; Ferre, Nicolas <Nicolas.FERRE at atmel.com>;
> linux-kernel at vger.kernel.org; Alexandre Belloni <alexandre.belloni at free-
> electrons.com>; linux-mtd at lists.infradead.org; Jean-Christophe Plagniol-Villard
> <plagnioj at jcrosoft.com>; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 1/2] Revert "mtd: atmel_nand: Support variable RB_EDGE
> interrupts"
> 
> Hi Wenyou,
> 
> Can you add NAND maintainers/reviewers in Cc next time. And since you revert a
> commit, you should also add the commit author in the loop.
> 
> On Mon, 9 May 2016 14:51:18 +0800
> Wenyou Yang <wenyou.yang at atmel.com> wrote:
> 
> > This reverts commit 5ddc7bd43ccc ("mtd: atmel_nand: Support variable
> > RB_EDGE interrupts")
> >
> > Because for current SoCs, the RB_EDGE3(i.e. bit 27) of HSMC_SR
> > register does not exist, the RB_EDGE0 (i.e. bit 24) is the ready/busy
> > line edge status bit. It is a datasheet bug.
> 
> Romain, I thought you had a real use case on sama5d4 where this patch was
> needed to make the whole thing work. Not sure why you submitted this patch if
> you couldn't test it on a real board.
> 
> Wenyou, can you confirm that none of the existing SoCs support more than one
> "native" R/B pin?

Yes, I confirmed. 

> 
> Thanks,
> 
> Boris
> 
> >
> > Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> > ---
> >
> >  .../devicetree/bindings/mtd/atmel-nand.txt         |  2 +-
> >  drivers/mtd/nand/atmel_nand.c                      | 35 +++++-----------------
> >  drivers/mtd/nand/atmel_nand_nfc.h                  |  3 +-
> >  3 files changed, 10 insertions(+), 30 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> > b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> > index d53aba9..3e7ee99 100644
> > --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> > +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> > @@ -39,7 +39,7 @@ Optional properties:
> >
> >  Nand Flash Controller(NFC) is an optional sub-node  Required
> > properties:
> > -- compatible : "atmel,sama5d3-nfc" or "atmel,sama5d4-nfc".
> > +- compatible : "atmel,sama5d3-nfc".
> >  - reg : should specify the address and size used for NFC command registers,
> >          NFC registers and NFC SRAM. NFC SRAM address and size can be
> absent
> >          if don't want to use it.
> > diff --git a/drivers/mtd/nand/atmel_nand.c
> > b/drivers/mtd/nand/atmel_nand.c index efc8ea2..68b9160 100644
> > --- a/drivers/mtd/nand/atmel_nand.c
> > +++ b/drivers/mtd/nand/atmel_nand.c
> > @@ -67,10 +67,6 @@ struct atmel_nand_caps {
> >  	uint8_t pmecc_max_correction;
> >  };
> >
> > -struct atmel_nand_nfc_caps {
> > -	uint32_t rb_mask;
> > -};
> > -
> >  /*
> >   * oob layout for large page size
> >   * bad block info is on bytes 0 and 1 @@ -129,7 +125,6 @@ struct
> > atmel_nfc {
> >  	/* Point to the sram bank which include readed data via NFC */
> >  	void			*data_in_sram;
> >  	bool			will_write_sram;
> > -	const struct atmel_nand_nfc_caps *caps;
> >  };
> >  static struct atmel_nfc	nand_nfc;
> >
> > @@ -1715,9 +1710,9 @@ static irqreturn_t hsmc_interrupt(int irq, void *dev_id)
> >  		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE);
> >  		ret = IRQ_HANDLED;
> >  	}
> > -	if (pending & host->nfc->caps->rb_mask) {
> > +	if (pending & NFC_SR_RB_EDGE) {
> >  		complete(&host->nfc->comp_ready);
> > -		nfc_writel(host->nfc->hsmc_regs, IDR, host->nfc->caps-
> >rb_mask);
> > +		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE);
> >  		ret = IRQ_HANDLED;
> >  	}
> >  	if (pending & NFC_SR_CMD_DONE) {
> > @@ -1735,7 +1730,7 @@ static void nfc_prepare_interrupt(struct
> atmel_nand_host *host, u32 flag)
> >  	if (flag & NFC_SR_XFR_DONE)
> >  		init_completion(&host->nfc->comp_xfer_done);
> >
> > -	if (flag & host->nfc->caps->rb_mask)
> > +	if (flag & NFC_SR_RB_EDGE)
> >  		init_completion(&host->nfc->comp_ready);
> >
> >  	if (flag & NFC_SR_CMD_DONE)
> > @@ -1753,7 +1748,7 @@ static int nfc_wait_interrupt(struct atmel_nand_host
> *host, u32 flag)
> >  	if (flag & NFC_SR_XFR_DONE)
> >  		comp[index++] = &host->nfc->comp_xfer_done;
> >
> > -	if (flag & host->nfc->caps->rb_mask)
> > +	if (flag & NFC_SR_RB_EDGE)
> >  		comp[index++] = &host->nfc->comp_ready;
> >
> >  	if (flag & NFC_SR_CMD_DONE)
> > @@ -1821,7 +1816,7 @@ static int nfc_device_ready(struct mtd_info *mtd)
> >  		dev_err(host->dev, "Lost the interrupt flags: 0x%08x\n",
> >  				mask & status);
> >
> > -	return status & host->nfc->caps->rb_mask;
> > +	return status & NFC_SR_RB_EDGE;
> >  }
> >
> >  static void nfc_select_chip(struct mtd_info *mtd, int chip) @@
> > -1994,8 +1989,8 @@ static void nfc_nand_command(struct mtd_info *mtd,
> unsigned int command,
> >  		}
> >  		/* fall through */
> >  	default:
> > -		nfc_prepare_interrupt(host, host->nfc->caps->rb_mask);
> > -		nfc_wait_interrupt(host, host->nfc->caps->rb_mask);
> > +		nfc_prepare_interrupt(host, NFC_SR_RB_EDGE);
> > +		nfc_wait_interrupt(host, NFC_SR_RB_EDGE);
> >  	}
> >  }
> >
> > @@ -2426,11 +2421,6 @@ static int atmel_nand_nfc_probe(struct
> platform_device *pdev)
> >  		}
> >  	}
> >
> > -	nfc->caps = (const struct atmel_nand_nfc_caps *)
> > -		of_device_get_match_data(&pdev->dev);
> > -	if (!nfc->caps)
> > -		return -ENODEV;
> > -
> >  	nfc_writel(nfc->hsmc_regs, IDR, 0xffffffff);
> >  	nfc_readl(nfc->hsmc_regs, SR);	/* clear the NFC_SR */
> >
> > @@ -2459,17 +2449,8 @@ static int atmel_nand_nfc_remove(struct
> platform_device *pdev)
> >  	return 0;
> >  }
> >
> > -static const struct atmel_nand_nfc_caps sama5d3_nfc_caps = {
> > -	.rb_mask = NFC_SR_RB_EDGE0,
> > -};
> > -
> > -static const struct atmel_nand_nfc_caps sama5d4_nfc_caps = {
> > -	.rb_mask = NFC_SR_RB_EDGE3,
> > -};
> > -
> >  static const struct of_device_id atmel_nand_nfc_match[] = {
> > -	{ .compatible = "atmel,sama5d3-nfc", .data = &sama5d3_nfc_caps },
> > -	{ .compatible = "atmel,sama5d4-nfc", .data = &sama5d4_nfc_caps },
> > +	{ .compatible = "atmel,sama5d3-nfc" },
> >  	{ /* sentinel */ }
> >  };
> >  MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match); diff --git
> > a/drivers/mtd/nand/atmel_nand_nfc.h
> > b/drivers/mtd/nand/atmel_nand_nfc.h
> > index 0bbc1fa..4d5d262 100644
> > --- a/drivers/mtd/nand/atmel_nand_nfc.h
> > +++ b/drivers/mtd/nand/atmel_nand_nfc.h
> > @@ -42,8 +42,7 @@
> >  #define		NFC_SR_UNDEF		(1 << 21)
> >  #define		NFC_SR_AWB		(1 << 22)
> >  #define		NFC_SR_ASE		(1 << 23)
> > -#define		NFC_SR_RB_EDGE0		(1 << 24)
> > -#define		NFC_SR_RB_EDGE3		(1 << 27)
> > +#define		NFC_SR_RB_EDGE		(1 << 24)
> >
> >  #define ATMEL_HSMC_NFC_IER	0x0c
> >  #define ATMEL_HSMC_NFC_IDR	0x10
> 
> 
> 
> --
> Boris Brezillon, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com


Best Regards,
Wenyou Yang

From marc.zyngier at arm.com  Tue May 10 02:00:43 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 10:00:43 +0100
Subject: [PATCH v3 11/55] KVM: arm/arm64: pmu: abstract access to number
 of SPIs
In-Reply-To: <1462531568-9799-12-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-12-git-send-email-andre.przywara@arm.com>
Message-ID: <5731A33B.7040703@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> Currently the PMU uses a member of the struct vgic_dist directly,
> which not only breaks abstraction, but will fail with the new VGIC.
> Abstract this access in the VGIC header file.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Acked-by: Marc Zyngier <marc.zyngier at arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...


From marc.zyngier at arm.com  Tue May 10 02:02:50 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 10:02:50 +0100
Subject: [PATCH v3 12/55] KVM: arm/arm64: move GICv2 emulation defines
 into arm-gic-v3.h
In-Reply-To: <1462531568-9799-13-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-13-git-send-email-andre.przywara@arm.com>
Message-ID: <5731A3B9.4090505@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> As (some) GICv3 hosts can emulate a GICv2, some GICv2 specific masks
> for the list register definition also apply to GICv3 LRs.
> At the moment we have those definitions in the KVM VGICv3
> implementation, so let's move them into the GICv3 header file to
> have them automatically defined.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Acked-by: Marc Zyngier <marc.zyngier at arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...


From marc.zyngier at arm.com  Tue May 10 02:05:30 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 10:05:30 +0100
Subject: [PATCH v3 13/55] KVM: arm/arm64: vgic-new: Add data structure
 definitions
In-Reply-To: <1462531568-9799-14-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-14-git-send-email-andre.przywara@arm.com>
Message-ID: <5731A45A.7040309@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> Add a new header file for the new and improved GIC implementation.
> The big change is that we now have a struct vgic_irq per IRQ instead
> of spreading all the information over various bitmaps.
> 
> We include this new header conditionally from within the old header
> file for the time being to avoid touching all the users.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...


From u.kleine-koenig at pengutronix.de  Tue May 10 02:05:47 2016
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Tue, 10 May 2016 11:05:47 +0200
Subject: [PATCH v2 0/3] video: fbdev: imxfb: make it work again
In-Reply-To: <5731A02A.2070309@ti.com>
References: <1462354998-5792-1-git-send-email-u.kleine-koenig@pengutronix.de>
 <5731A02A.2070309@ti.com>
Message-ID: <20160510090547.GQ30822@pengutronix.de>

Hello Tomi,

On Tue, May 10, 2016 at 11:47:38AM +0300, Tomi Valkeinen wrote:
> On 04/05/16 12:43, Uwe Kleine-K?nig wrote:
> > this is v2 of the series which addresses the review comments I got vor
> > (implicit) v1.
> > 
> > For patch 2 the question is still open if this is the right fix, but
> > without this the display doesn't stay on. Patches 1 and 3 should be
> > applicable independant of patch 2.
> 
> I picked patches 1 and 3, they look fine.

Thanks.

> I still think patch 2 is just broken, it doesn't make sense to me.

What do you think should happen during startup? Something should call
the set_power callback to enable the device? Or should that only happen
when something writes to /dev/fb0?

> If the regulator is enabled in probe, then it's always on, and
> imxfb_lcd_set_power() should be removed as it never has any effect. But
> that doesn't sound correct, as presumably the imxfb_lcd_set_power() has
> worked at some point.

I think it worked back when unused regulators were not disabled during
boot.

> And shouldn't the regulator be disabled at least when suspending?

Yeah, but maybe the core should call set_power(off) then? (Don't know,
maybe that cannot work.)

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From marc.zyngier at arm.com  Tue May 10 02:22:44 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 10:22:44 +0100
Subject: [PATCH v3 14/55] KVM: arm/arm64: vgic-new: Add acccessor to new
 struct vgic_irq instance
In-Reply-To: <1462531568-9799-15-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-15-git-send-email-andre.przywara@arm.com>
Message-ID: <5731A864.5000109@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> The new VGIC implementation centers around a struct vgic_irq instance
> per virtual IRQ.
> Provide a function to retrieve the right instance for a given IRQ
> number and (in case of private interrupts) the right VCPU.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic.c | 41 +++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h | 22 ++++++++++++++++++++++
>  2 files changed, 63 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic.c
>  create mode 100644 virt/kvm/arm/vgic/vgic.h
> 
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> new file mode 100644
> index 0000000..fb45537
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -0,0 +1,41 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * 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/kvm.h>
> +#include <linux/kvm_host.h>
> +
> +#include "vgic.h"
> +
> +struct vgic_global __section(.hyp.text) kvm_vgic_global_state;

nit: this structure isn't referenced anywhere yet.

> +
> +struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
> +			      u32 intid)
> +{
> +	/* SGIs and PPIs */
> +	if (intid <= VGIC_MAX_PRIVATE)
> +		return &vcpu->arch.vgic_cpu.private_irqs[intid];
> +
> +	/* SPIs */
> +	if (intid <= VGIC_MAX_SPI)
> +		return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS];
> +
> +	/* LPIs are not yet covered */
> +	if (intid >= VGIC_MIN_LPI)
> +		return NULL;
> +
> +	WARN(1, "Looking up struct vgic_irq for reserved INTID");
> +	return NULL;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> new file mode 100644
> index 0000000..61b8d22
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef __KVM_ARM_VGIC_NEW_H__
> +#define __KVM_ARM_VGIC_NEW_H__
> +
> +struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
> +			      u32 intid);
> +
> +#endif
> 

Otherwise:

Acked-by: Marc Zyngier <marc.zyngier at arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...


From eric.auger at linaro.org  Tue May 10 02:25:56 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 11:25:56 +0200
Subject: [PATCH v3 15/55] KVM: arm/arm64: vgic-new: Implement virtual IRQ
 injection
In-Reply-To: <1462531568-9799-16-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-16-git-send-email-andre.przywara@arm.com>
Message-ID: <5731A924.8040805@linaro.org>

Hi,
On 05/06/2016 12:45 PM, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> Provide a vgic_queue_irq() function which decides whether a given
nit: now called vgic_queue_irq_unlock
> IRQ needs to be queued to a VCPU's ap_list.
> This should be called whenever an IRQ becomes pending or enabled,
> either as a result of userspace injection, from in-kernel emulated
> devices like the architected timer or from MMIO accesses to the
> distributor emulation.
> Also provides the necessary functions to allow userland to inject an
> IRQ to a guest.
> Since this is the first code that starts using our locking mechanism, we
> add some (hopefully) clear documentation of our locking strategy and
> requirements along with this patch.
> 
> [Andre: refactor out vgic_queue_irq_unlock()]
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - add spinlock checks protected by CONFIG_DEBUG_SPINLOCK
> - add more comments to vgic_target_oracle
> - remove BUG_ON() if IRQ is neither edge or level
> - rename vgic_queue_irq() to vgic_queue_irq_unlock()
> - simplify initial check in vgic_queue_irq_unlock()
> - extend retry loop to ask the oracle again
> - minor comment fixes
> 
> Changelog v1 .. v2:
> - move most IRQ injection code into vgic_update_irq_pending()
> 
>  include/kvm/vgic/vgic.h  |   3 +
>  virt/kvm/arm/vgic/vgic.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h |   1 +
>  3 files changed, 213 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 39933ee..2bfb42c 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -181,6 +181,9 @@ struct vgic_cpu {
>  	u64 live_lrs;
>  };
>  
> +int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
> +			bool level);
> +
>  #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
>  #define vgic_initialized(k)	(false)
>  #define vgic_ready(k)		((k)->arch.vgic.ready)
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index fb45537..92b78a0 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -19,8 +19,31 @@
>  
>  #include "vgic.h"
>  
> +#define CREATE_TRACE_POINTS
> +#include "../trace.h"
> +
> +#ifdef CONFIG_DEBUG_SPINLOCK
> +#define DEBUG_SPINLOCK_BUG_ON(p) BUG_ON(p)
> +#else
> +#define DEBUG_SPINLOCK_BUG_ON(p)
> +#endif
> +
>  struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
>  
> +/*
> + * Locking order is always:
> + *   vgic_cpu->ap_list_lock
> + *     vgic_irq->irq_lock
> + *
> + * (that is, always take the ap_list_lock before the struct vgic_irq lock).
> + *
> + * When taking more than one ap_list_lock at the same time, always take the
> + * lowest numbered VCPU's ap_list_lock first, so:
> + *   vcpuX->vcpu_id < vcpuY->vcpu_id:
> + *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
> + *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
> + */
> +
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid)
>  {
> @@ -39,3 +62,189 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  	WARN(1, "Looking up struct vgic_irq for reserved INTID");
>  	return NULL;
>  }
> +
> +/**
> + * kvm_vgic_target_oracle - compute the target vcpu for an irq
> + *
> + * @irq:	The irq to route. Must be already locked.
> + *
> + * Based on the current state of the interrupt (enabled, pending,
> + * active, vcpu and target_vcpu), compute the next vcpu this should be
> + * given to. Return NULL if this shouldn't be injected at all.
> + *
> + * Requires the IRQ lock to be held.
> + */
> +static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
> +{
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
> +
> +	/* If the interrupt is active, it must stay on the current vcpu */
> +	if (irq->active)
> +		return irq->vcpu;
> +
> +	/*
> +	 * If the IRQ is not active but enabled and pending, we should direct
> +	 * it to its configured target VCPU.
> +	 */
> +	if (irq->enabled && irq->pending)
> +		return irq->target_vcpu;
> +
> +	/* If neither active nor pending and enabled, then this IRQ should not
> +	 * be queued to any VCPU.
> +	 */
> +	return NULL;
> +}
> +
> +/*
> + * Only valid injection if changing level for level-triggered IRQs or for a
> + * rising edge.
> + */
> +static bool vgic_validate_injection(struct vgic_irq *irq, bool level)
> +{
> +	switch (irq->config) {
> +	case VGIC_CONFIG_LEVEL:
> +		return irq->line_level != level;
> +	case VGIC_CONFIG_EDGE:
> +		return level;
> +	}
> +
> +	return false;
> +}
> +
> +/*
> + * Check whether an IRQ needs to (and can) be queued to a VCPU's ap list.
> + * Do the queuing if necessary, taking the right locks in the right order.
> + * Returns true when the IRQ was queued, false otherwise.
> + *
> + * Needs to be entered with the IRQ lock already held, but will return
> + * with all locks dropped.
> + */
> +bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq)
> +{
> +	struct kvm_vcpu *vcpu;
> +
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
> +
> +retry:
> +	vcpu = vgic_target_oracle(irq);
> +	if (irq->vcpu || !vcpu) {
> +		/*
> +		 * If this IRQ is already on a VCPU's ap_list, then it
> +		 * cannot be moved or modified and there is no more work for
> +		 * us to do.
> +		 *
> +		 * Otherwise, if the irq is not pending and enabled, it does
> +		 * not need to be inserted into an ap_list and there is also
> +		 * no more work for us to do.
> +		 */
> +		spin_unlock(&irq->irq_lock);
> +		return false;
> +	}
> +
> +	/*
> +	 * We must unlock the irq lock to take the ap_list_lock where
> +	 * we are going to insert this new pending interrupt.
> +	 */
> +	spin_unlock(&irq->irq_lock);
> +
> +	/* someone can do stuff here, which we re-check below */
> +
> +	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +	spin_lock(&irq->irq_lock);
> +
> +	/*
> +	 * Did something change behind our backs?
> +	 *
> +	 * There are two cases:
> +	 * 1) The irq became pending or active behind our backs and/or
> +	 *    the irq->vcpu field was set correspondingly when putting
> +	 *    the irq on an ap_list. Then drop the locks and return.
Don't we actually implement 3 cases here:
1) the IRQ was queued in our back
2) the IRQ was disabled/turned not pending in our back
3) someone changed the affinity?
> +	 * 2) Someone changed the affinity on this irq behind our
> +	 *    backs and we are now holding the wrong ap_list_lock.
> +	 *    Then drop the locks and try the new VCPU.
> +	 */
> +	if (irq->vcpu || !(irq->pending && irq->enabled)) {
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +		return false;
> +	}
> +
> +	if (irq->target_vcpu != vcpu) {
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +
> +		spin_lock(&irq->irq_lock);
> +		goto retry;
> +	}
> +
> +	list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
> +	irq->vcpu = vcpu;
> +
> +	spin_unlock(&irq->irq_lock);
> +	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +
> +	kvm_vcpu_kick(vcpu);
> +
> +	return true;
> +}
> +
> +static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
> +				   unsigned int intid, bool level,
> +				   bool mapped_irq)
> +{
> +	struct kvm_vcpu *vcpu;
> +	struct vgic_irq *irq;
> +	int ret;
> +
> +	trace_vgic_update_irq_pending(cpuid, intid, level);
> +
> +	vcpu = kvm_get_vcpu(kvm, cpuid);
> +	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
> +		return -EINVAL;
> +
> +	irq = vgic_get_irq(kvm, vcpu, intid);
> +	if (!irq)
> +		return -EINVAL;
> +
> +	if (irq->hw != mapped_irq)
> +		return -EINVAL;
> +
> +	spin_lock(&irq->irq_lock);
> +
> +	if (!vgic_validate_injection(irq, level)) {
> +		/* Nothing to see here, move along... */
> +		spin_unlock(&irq->irq_lock);
> +		return 0;
> +	}
> +
> +	if (irq->config == VGIC_CONFIG_LEVEL) {
> +		irq->line_level = level;
> +		irq->pending = level || irq->soft_pending;
> +	} else {
> +		irq->pending = true;
> +	}
> +
> +	vgic_queue_irq_unlock(kvm, irq);
> +
> +	return 0;
> +}
> +
> +/**
> + * kvm_vgic_inject_irq - Inject an IRQ from a device to the vgic
> + * @kvm:     The VM structure pointer
> + * @cpuid:   The CPU for PPIs
> + * @intid:   The INTID to inject a new state to.
> + * @level:   Edge-triggered:  true:  to trigger the interrupt
> + *			      false: to ignore the call
> + *	     Level-sensitive  true:  raise the input signal
> + *			      false: lower the input signal
> + *
> + * The VGIC is not concerned with devices being active-LOW or active-HIGH for
> + * level-sensitive interrupts.  You can think of the level parameter as 1
> + * being HIGH and 0 being LOW and all devices being active-HIGH.
> + */
> +int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
> +			bool level)
> +{
> +	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 61b8d22..c625767 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -18,5 +18,6 @@
>  
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid);
> +bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
>  
>  #endif
> 
Reviewed-by: Eric Auger <eric.auger at linaro.org>

Eric




From linux.amoon at gmail.com  Tue May 10 02:29:27 2016
From: linux.amoon at gmail.com (Anand Moon)
Date: Tue, 10 May 2016 14:59:27 +0530
Subject: [PATCH] ARM: dts: exynos: Only Odroid XU3-family boards use DTSI
 with CPU thermal nodes
In-Reply-To: <573198BE.6020900@samsung.com>
References: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>
 <CANAwSgT9SY3kj8+beMpc1xGoC=rMBSya+2v2dyZQp6ykH+V0=g@mail.gmail.com>
 <573198BE.6020900@samsung.com>
Message-ID: <CANAwSgTy6p9AVmmOWATpSO1JqVbwE0v+y_y-RLd+32RnNJTA+Q@mail.gmail.com>

Hi Krzysztof,

On 10 May 2016 at 13:45, Krzysztof Kozlowski <k.kozlowski at samsung.com> wrote:
> On 05/10/2016 08:43 AM, Anand Moon wrote:
>> Hi Krzysztof ,
>>
>> On 9 May 2016 at 11:49, Krzysztof Kozlowski <k.kozlowski at samsung.com> wrote:
>>> Include the CPU thermal nodes directly in Odroid XU3-family common DTS
>>> because it is the only user of it. Keeping it in separate DTSI node does
>>> not bring benefits because:
>>> 1. It is not re-usable on other non-fan boards (fan is referenced),
>>> 2. It won't be re-used on future Odroid XU board because different
>>>    CPU cluster behavior.
>>>
>>> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>>> ---
>>>  arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi      | 103 ---------------------
>>>  arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |  94 ++++++++++++++++++-
>>>  2 files changed, 92 insertions(+), 105 deletions(-)
>>>  delete mode 100644 arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi
>>>
>>> diff --git a/arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi b/arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi
>>> deleted file mode 100644
>>> index 3e4c4ad96d63..000000000000
>>> --- a/arch/arm/boot/dts/exynos5422-cpu-thermal.dtsi
>>> +++ /dev/null
>>> @@ -1,103 +0,0 @@
>>> -/*
>>> - * Device tree sources for Exynos5422 thermal zone
>>> - *
>>> - * Copyright (c) 2015 Lukasz Majewski <l.majewski at samsung.com>
>>> - *                     Anand Moon <linux.amoon at gmail.com>
>>> - *
>>> - * This program is free software; you can redistribute it and/or modify
>>> - * it under the terms of the GNU General Public License version 2 as
>>> - * published by the Free Software Foundation.
>>> - *
>>> - */
>>> -
>>> -#include <dt-bindings/thermal/thermal.h>
>>> -
>>> -/ {
>>> -       thermal-zones {
>>> -               cpu0_thermal: cpu0-thermal {
>>> -                       thermal-sensors = <&tmu_cpu0 0>;
>>> -                       polling-delay-passive = <250>;
>>> -                       polling-delay = <0>;
>>> -                       trips {
>>> -                               cpu_alert0: cpu-alert-0 {
>>> -                                       temperature = <50000>; /* millicelsius */
>>> -                                       hysteresis = <5000>; /* millicelsius */
>>> -                                       type = "active";
>>> -                               };
>>> -                               cpu_alert1: cpu-alert-1 {
>>> -                                       temperature = <60000>; /* millicelsius */
>>> -                                       hysteresis = <5000>; /* millicelsius */
>>> -                                       type = "active";
>>> -                               };
>>> -                               cpu_alert2: cpu-alert-2 {
>>> -                                       temperature = <70000>; /* millicelsius */
>>> -                                       hysteresis = <5000>; /* millicelsius */
>>> -                                       type = "active";
>>> -                               };
>>> -                               cpu_crit0: cpu-crit-0 {
>>> -                                       temperature = <120000>; /* millicelsius */
>>> -                                       hysteresis = <0>; /* millicelsius */
>>> -                                       type = "critical";
>>> -                               };
>>> -                               /*
>>> -                                * Exyunos542x support only 4 trip-points
>>> -                                * so for these polling mode is required.
>>> -                                * Start polling at temperature level of last
>>> -                                * interrupt-driven trip: cpu_alert2
>>> -                                */
>>> -                               cpu_alert3: cpu-alert-3 {
>>> -                                       temperature = <70000>; /* millicelsius */
>>> -                                       hysteresis = <10000>; /* millicelsius */
>>> -                                       type = "passive";
>>> -                               };
>>> -                               cpu_alert4: cpu-alert-4 {
>>> -                                       temperature = <85000>; /* millicelsius */
>>> -                                       hysteresis = <10000>; /* millicelsius */
>>> -                                       type = "passive";
>>> -                               };
>>> -
>>> -                       };
>>> -                       cooling-maps {
>>> -                               map0 {
>>> -                                    trip = <&cpu_alert0>;
>>> -                                    cooling-device = <&fan0 0 1>;
>>> -                               };
>>> -                               map1 {
>>> -                                    trip = <&cpu_alert1>;
>>> -                                    cooling-device = <&fan0 1 2>;
>>> -                               };
>>> -                               map2 {
>>> -                                    trip = <&cpu_alert2>;
>>> -                                    cooling-device = <&fan0 2 3>;
>>> -                               };
>>> -                               /*
>>> -                                * When reaching cpu_alert3, reduce CPU
>>> -                                * by 2 steps. On Exynos5422/5800 that would
>>> -                                * be: 1500 MHz and 1100 MHz.
>>> -                                */
>>> -                               map3 {
>>> -                                    trip = <&cpu_alert3>;
>>> -                                    cooling-device = <&cpu0 0 2>;
>>> -                               };
>>> -                               map4 {
>>> -                                    trip = <&cpu_alert3>;
>>> -                                    cooling-device = <&cpu4 0 2>;
>>> -                               };
>>> -
>>> -                               /*
>>> -                                * When reaching cpu_alert4, reduce CPU
>>> -                                * further, down to 600 MHz (11 steps for big,
>>> -                                * 7 steps for LITTLE).
>>> -                                */
>>> -                               map5 {
>>> -                                    trip = <&cpu_alert4>;
>>> -                                    cooling-device = <&cpu0 3 7>;
>>> -                               };
>>> -                               map6 {
>>> -                                    trip = <&cpu_alert4>;
>>> -                                    cooling-device = <&cpu4 3 11>;
>>> -                               };
>>> -                       };
>>> -               };
>>> -       };
>>> -};
>>> diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
>>> index 2a4e10bc8801..ff05041835e5 100644
>>> --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
>>> +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
>>> @@ -1,9 +1,11 @@
>>>  /*
>>>   * Hardkernel Odroid XU3 board device tree source
>>>   *
>>> - * Copyright (c) 2014 Collabora Ltd.
>>>   * Copyright (c) 2013 Samsung Electronics Co., Ltd.
>>>   *             http://www.samsung.com
>>> + * Copyright (c) 2014 Collabora Ltd.
>>> + * Copyright (c) 2015 Lukasz Majewski <l.majewski at samsung.com>
>>> + *                    Anand Moon <linux.amoon at gmail.com>
>>>   *
>>>   * This program is free software; you can redistribute it and/or modify
>>>   * it under the terms of the GNU General Public License version 2 as
>>> @@ -16,7 +18,6 @@
>>>  #include <dt-bindings/sound/samsung-i2s.h>
>>>  #include "exynos5800.dtsi"
>>>  #include "exynos5422-cpus.dtsi"
>>> -#include "exynos5422-cpu-thermal.dtsi"
>>>
>>>  / {
>>>         memory {
>>> @@ -54,6 +55,95 @@
>>>                 #cooling-cells = <2>;
>>>                 cooling-levels = <0 130 170 230>;
>>>         };
>>> +
>>> +       thermal-zones {
>>> +               cpu0_thermal: cpu0-thermal {
>>> +                       thermal-sensors = <&tmu_cpu0 0>;
>>> +                       polling-delay-passive = <250>;
>>> +                       polling-delay = <0>;
>>> +                       trips {
>>> +                               cpu_alert0: cpu-alert-0 {
>>> +                                       temperature = <50000>; /* millicelsius */
>>> +                                       hysteresis = <5000>; /* millicelsius */
>>> +                                       type = "active";
>>> +                               };
>>> +                               cpu_alert1: cpu-alert-1 {
>>> +                                       temperature = <60000>; /* millicelsius */
>>> +                                       hysteresis = <5000>; /* millicelsius */
>>> +                                       type = "active";
>>> +                               };
>>> +                               cpu_alert2: cpu-alert-2 {
>>> +                                       temperature = <70000>; /* millicelsius */
>>> +                                       hysteresis = <5000>; /* millicelsius */
>>> +                                       type = "active";
>>> +                               };
>>> +                               cpu_crit0: cpu-crit-0 {
>>> +                                       temperature = <120000>; /* millicelsius */
>>> +                                       hysteresis = <0>; /* millicelsius */
>>> +                                       type = "critical";
>>> +                               };
>>> +                               /*
>>> +                                * Exynos542x supports only 4 trip-points
>>> +                                * so for these polling mode is required.
>>> +                                * Start polling at temperature level of last
>>> +                                * interrupt-driven trip: cpu_alert2
>>> +                                */
>>> +                               cpu_alert3: cpu-alert-3 {
>>> +                                       temperature = <70000>; /* millicelsius */
>>> +                                       hysteresis = <10000>; /* millicelsius */
>>> +                                       type = "passive";
>>> +                               };
>>> +                               cpu_alert4: cpu-alert-4 {
>>> +                                       temperature = <85000>; /* millicelsius */
>>> +                                       hysteresis = <10000>; /* millicelsius */
>>> +                                       type = "passive";
>>> +                               };
>>> +
>>> +                       };
>>> +                       cooling-maps {
>>> +                               map0 {
>>> +                                    trip = <&cpu_alert0>;
>>> +                                    cooling-device = <&fan0 0 1>;
>>> +                               };
>>> +                               map1 {
>>> +                                    trip = <&cpu_alert1>;
>>> +                                    cooling-device = <&fan0 1 2>;
>>> +                               };
>>> +                               map2 {
>>> +                                    trip = <&cpu_alert2>;
>>> +                                    cooling-device = <&fan0 2 3>;
>>> +                               };
>>> +                               /*
>>> +                                * When reaching cpu_alert3, reduce CPU
>>> +                                * by 2 steps. On Exynos5422/5800 that would
>>> +                                * be: 1500 MHz and 1100 MHz.
>>> +                                */
>>> +                               map3 {
>>> +                                    trip = <&cpu_alert3>;
>>> +                                    cooling-device = <&cpu0 0 2>;
>>> +                               };
>>> +                               map4 {
>>> +                                    trip = <&cpu_alert3>;
>>> +                                    cooling-device = <&cpu4 0 2>;
>>> +                               };
>>> +
>>> +                               /*
>>> +                                * When reaching cpu_alert4, reduce CPU
>>> +                                * further, down to 600 MHz (11 steps for big,
>>> +                                * 7 steps for LITTLE).
>>> +                                */
>>> +                               map5 {
>>> +                                    trip = <&cpu_alert4>;
>>> +                                    cooling-device = <&cpu0 3 7>;
>>> +                               };
>>> +                               map6 {
>>> +                                    trip = <&cpu_alert4>;
>>> +                                    cooling-device = <&cpu4 3 11>;
>>> +                               };
>>> +                       };
>>> +               };
>>> +       };
>>> +
>>>  };
>>>
>>>  &bus_wcore {
>>> --
>>> 1.9.1
>>>
>>
>> Could you defer this patch, during my testing with pm-qa from linaro.
>>
>> git://git.linaro.org/tools/pm-qa.git
>>
>> When their is running of thermal test case cpu usage reaches around
>> 300+ percentage
>> and some time's the Odroid XU4 hang down.
>> -------------------------------------------------------------------------
>> [ 1028.056619] CPU4: shutdown
>> [ 1148.510372] IRQ54 no longer affine to CPU5
>> [ 1148.511864] CPU5: shutdown
>> [ 1268.921073] IRQ55 no longer affine to CPU6
>> [ 1268.922564] CPU6: shutdown
>> [ 1389.271930] cpu cpu4: Failed to find opp_table: -19
>> [ 1389.301668] IRQ56 no longer affine to CPU7
>> [ 1389.303132] CPU7: shutdown
>> [ 1510.538424] cpu cpu4: opp_list_debug_create_link: Failed to create link
>> [ 1510.543762] cpu cpu4: _add_opp_dev: Failed to register opp debugfs (-12)
>> [ 1510.550625] cpu cpu7: opp_list_debug_create_link: Failed to create link
>> [ 1510.557037] cpu cpu7: _add_opp_dev: Failed to register opp debugfs (-12)
>> [ 1510.664649] cpu cpu5: cpufreq_init: failed to get clk: -2
>> [ 1510.720567] cpu cpu6: cpufreq_init: failed to get clk: -2
>> [ 1510.788280] cpu cpu7: cpufreq_init: failed to get clk: -2
>> root at odroidxu4l:/home/odroid/study/linaro/pm-qa# killall heat_cpu
>>
>> -------------------------------------------------------------------------
>> And some time I observed that the board will poweroff on reaching
>> temperature 120 degree C.
>> when I am compiling the kernel with or above. make -j8
>> -------------------------------------------------------------------------
>> root at odroidxu4l:~#  * Starting NTP server ntpd                           [ OK ]
>> saned disabled; edit /etc/default/saned
>> [ 4118.924470] thermal thermal_zone3: critical temperature reached(121
>> C),shutting down
>> [ 4119.014327] thermal thermal_zone3: critical temperature reached(121
>> C),shutting down
>>
>> Broadcast message from root at odroidxu4l
>>         (unknown) at 20:41 ...
>>
>> The system is going down for power off NOW!
>>
>> Broadcast message from root at odroidxu4l
>>         (unknown) at 20:41 ...
>>
>> The system is going down for power off NOW!
>> [ 4119.431386] thermal thermal_zone3: critical temperature reached(121
>> C),shutting down
>> [ 4120.206709] thermal thermal_zone3: critical temperature reached(120
>> C),shutting down
>>
>> Broadcast message from root at odroidxu4l
>>         (unknown) at 20:41 ...
>>
>> The system is going down for power off NOW!
>> wait-for-state stop/waiting
>> [ 4157.574406] reboo
>>
>> U-Boot 2016.03-00665-g563d8d9-dirty (Apr 04 2016 - 22:27:07 +0930) for
>> ODROID-XU3
>>
>> CPU:   Exynos5422 @ 800 MHz
>> Model: Odroid XU3 based on EXYNOS5422
>> Board: Odroid XU3 based on EXYNOS5422
>> Type:  xu4
>> DRAM:  2 GiB
>> MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
>> *** Warning - bad CRC, using default environment
>> -------------------------------------------------------------------------
>> Once the thermal issue is fixed we can redo this changes.
>
> I am sorry but I do not understand.
> 1. Are you saying that my patch causes the issue?
> 2. Are you saying that I should not send some patches because of
> conflicting work? (that would be peculiar...)
> 3. Are you saying that I should not apply this patch to me tree because
> of conflicting work?
> 4. Other?
>
> Best regards.
> Krzysztof
>
>

Sorry for the confusion it's not about you patch.
The feature is not working correctly as per my testing with the
original source code.
It need to be more tuned or some other approach to the issue need to found.

Best Regards
-Anand Moon


From eric.auger at linaro.org  Tue May 10 02:29:16 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 11:29:16 +0200
Subject: [PATCH v3 16/55] KVM: arm/arm64: vgic-new: Add IRQ sorting
In-Reply-To: <1462531568-9799-17-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-17-git-send-email-andre.przywara@arm.com>
Message-ID: <5731A9EC.8050504@linaro.org>

On 05/06/2016 12:45 PM, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> Adds the sorting function to cover the case where you have more IRQs
> to consider than you have LRs. We now consider priorities.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 57 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 92b78a0..4fb20fd 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -16,6 +16,7 @@
>  
>  #include <linux/kvm.h>
>  #include <linux/kvm_host.h>
> +#include <linux/list_sort.h>
>  
>  #include "vgic.h"
>  
> @@ -96,6 +97,62 @@ static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
>  }
>  
>  /*
> + * The order of items in the ap_lists defines how we'll pack things in LRs as
> + * well, the first items in the list being the first things populated in the
> + * LRs.
> + *
> + * A hard rule is that active interrupts can never be pushed out of the LRs
> + * (and therefore take priority) since we cannot reliably trap on deactivation
> + * of IRQs and therefore they have to be present in the LRs.
> + *
> + * Otherwise things should be sorted by the priority field and the GIC
> + * hardware support will take care of preemption of priority groups etc.
> + *
> + * Return negative if "a" sorts before "b", 0 to preserve order, and positive
> + * to sort "b" before "a".
> + */
> +static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
> +{
> +	struct vgic_irq *irqa = container_of(a, struct vgic_irq, ap_list);
> +	struct vgic_irq *irqb = container_of(b, struct vgic_irq, ap_list);
> +	bool penda, pendb;
> +	int ret;
> +
> +	spin_lock(&irqa->irq_lock);
> +	spin_lock(&irqb->irq_lock);
> +
> +	if (irqa->active || irqb->active) {
> +		ret = (int)irqb->active - (int)irqa->active;
> +		goto out;
> +	}
> +
> +	penda = irqa->enabled && irqa->pending;
> +	pendb = irqb->enabled && irqb->pending;
> +
> +	if (!penda || !pendb) {
> +		ret = (int)pendb - (int)penda;
> +		goto out;
> +	}
> +
> +	/* Both pending and enabled, sort by priority */
> +	ret = irqa->priority - irqb->priority;
> +out:
> +	spin_unlock(&irqb->irq_lock);
> +	spin_unlock(&irqa->irq_lock);
> +	return ret;
> +}
> +
> +/* Must be called with the ap_list_lock held */
> +static void vgic_sort_ap_list(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
> +
> +	list_sort(NULL, &vgic_cpu->ap_list_head, vgic_irq_cmp);
> +}
> +
> +/*
>   * Only valid injection if changing level for level-triggered IRQs or for a
>   * rising edge.
>   */
> 
Reviewed-by: Eric Auger <eric.auger at linaro.org>

Eric



From arnd at arndb.de  Tue May 10 02:30:31 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 11:30:31 +0200
Subject: [GIT PULL] at91: fixes for 4.6 #1
In-Reply-To: <1462865249-28552-1-git-send-email-nicolas.ferre@atmel.com>
References: <1462865249-28552-1-git-send-email-nicolas.ferre@atmel.com>
Message-ID: <5465950.OCrl9K6RLM@wuerfel>

On Tuesday 10 May 2016 09:27:29 Nicolas Ferre wrote:
> Here is a late fix for AT91. Sorry to have figure it out so late in the
> development cycle but we had to confirm it was an error with the documentation
> of two products.
> So, as the compatibility string is in since 4.6-rc1 and that the previous one
> works okay, it's a good opportunity to switch back to the one that works without
> introducing a intermediary bug.
> The revert on driver code and the removal of the useless additional
> compatibility string will be queued for 4.7 through NAND/MTD.

Thanks, pulled into the fixes. I ended up taking the text above as the
commit log for the merge, as it was more descriptive than the shorter
version you had in the tag.

	Arnd


From adrian.hunter at intel.com  Tue May 10 02:30:02 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 12:30:02 +0300
Subject: [PATCH 11/23] mmc: sdhci-esdhci-imx: remove
 SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
In-Reply-To: <1460741387-23815-12-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-12-git-send-email-aisheng.dong@nxp.com>
Message-ID: <5731AA1A.9000504@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> The driver has already implemented the private .set_timeout()
> callback for common SDHCI code to do correct timeout value setting,
> it does not need call sdhci_calc_timeout(), so this quirk actually
> is not working. Remove it now.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>

Pedantically, the subject needs:

	sdhci-esdhci-imx -> sdhci-esdhc-imx

Otherwise:

Acked-by: Adrian Hunter <adrian.hunter at intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 2d300d8..03980db 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1147,8 +1147,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  	if (IS_ERR(imx_data->pins_default))
>  		dev_warn(mmc_dev(host->mmc), "could not get default state\n");
>  
> -	host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
> -
>  	if (imx_data->socdata->flags & ESDHC_FLAG_ENGCM07207)
>  		/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
>  		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
> 



From adrian.hunter at intel.com  Tue May 10 02:30:16 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 12:30:16 +0300
Subject: [PATCH 13/23] mmc: sdhci-esdhc-imx: restore watermark level
 setting after resume
In-Reply-To: <1460741387-23815-14-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-14-git-send-email-aisheng.dong@nxp.com>
Message-ID: <5731AA28.9030304@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> Currently, we config the watermark_level register only in probe.
> This will cause the mmc write operation timeout issue after system
> resume back in LPSR mode. Because in LPSR mode, after system resume
> back, the watermark_level register(0x44) changes to 0x08000880, which
> set the write watermark level as 0, and set the read watermark level
> as 128. This value is incorrect.
> 
> This patch restores the setting of watermark level register after
> system resume back.

In sdhci_esdhc_imx_probe() the watermark setting is conditional on
esdhc_is_usdhc(imx_data), but in the resume it is not.  Is that intended?
If so, maybe explain that in the commit message.

Might be worth pulling out the constant 0x10401040 and #defining it since it
is used in more than one place too.

> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 6fef6bc..4c28fbb 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1261,6 +1261,11 @@ static int sdhci_esdhc_suspend(struct device *dev)
>  
>  static int sdhci_esdhc_resume(struct device *dev)
>  {
> +	struct sdhci_host *host = dev_get_drvdata(dev);
> +
> +	/* restore watermark setting in case it's lost in low power mode */
> +	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> +
>  	return sdhci_pltfm_resume(dev);
>  }
>  
> 



From eric.auger at linaro.org  Tue May 10 02:35:53 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 11:35:53 +0200
Subject: [PATCH v3 14/55] KVM: arm/arm64: vgic-new: Add acccessor to new
 struct vgic_irq instance
In-Reply-To: <1462531568-9799-15-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-15-git-send-email-andre.przywara@arm.com>
Message-ID: <5731AB79.1000908@linaro.org>

On 05/06/2016 12:45 PM, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> The new VGIC implementation centers around a struct vgic_irq instance
> per virtual IRQ.
> Provide a function to retrieve the right instance for a given IRQ
> number and (in case of private interrupts) the right VCPU.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic.c | 41 +++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h | 22 ++++++++++++++++++++++
>  2 files changed, 63 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic.c
>  create mode 100644 virt/kvm/arm/vgic/vgic.h
> 
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> new file mode 100644
> index 0000000..fb45537
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -0,0 +1,41 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * 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/kvm.h>
> +#include <linux/kvm_host.h>
> +
> +#include "vgic.h"
> +
> +struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
> +
> +struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
> +			      u32 intid)
> +{
> +	/* SGIs and PPIs */
> +	if (intid <= VGIC_MAX_PRIVATE)
> +		return &vcpu->arch.vgic_cpu.private_irqs[intid];
> +
> +	/* SPIs */
> +	if (intid <= VGIC_MAX_SPI)
> +		return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS];
> +
> +	/* LPIs are not yet covered */
> +	if (intid >= VGIC_MIN_LPI)
> +		return NULL;
> +
> +	WARN(1, "Looking up struct vgic_irq for reserved INTID");
> +	return NULL;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> new file mode 100644
> index 0000000..61b8d22
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef __KVM_ARM_VGIC_NEW_H__
> +#define __KVM_ARM_VGIC_NEW_H__
> +
> +struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
> +			      u32 intid);
> +
> +#endif
> 
Reviewed-by: Eric Auger <eric.auger at linaro.org>

Eric


From marc.zyngier at arm.com  Tue May 10 02:39:28 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 10:39:28 +0100
Subject: [PATCH v3 15/55] KVM: arm/arm64: vgic-new: Implement virtual IRQ
 injection
In-Reply-To: <1462531568-9799-16-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-16-git-send-email-andre.przywara@arm.com>
Message-ID: <5731AC50.5020809@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> Provide a vgic_queue_irq() function which decides whether a given
> IRQ needs to be queued to a VCPU's ap_list.
> This should be called whenever an IRQ becomes pending or enabled,
> either as a result of userspace injection, from in-kernel emulated
> devices like the architected timer or from MMIO accesses to the
> distributor emulation.
> Also provides the necessary functions to allow userland to inject an
> IRQ to a guest.
> Since this is the first code that starts using our locking mechanism, we
> add some (hopefully) clear documentation of our locking strategy and
> requirements along with this patch.
> 
> [Andre: refactor out vgic_queue_irq_unlock()]
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...


From adrian.hunter at intel.com  Tue May 10 02:35:44 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 12:35:44 +0300
Subject: [PATCH 12/23] mmc: sdhci-esdhc-imx: add esdhc specific suspend
 resume callback
In-Reply-To: <1460741387-23815-13-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-13-git-send-email-aisheng.dong@nxp.com>
Message-ID: <5731AB70.30009@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> It will be used for platform specific suspend/resume state save/restore
> work for some low power mode like Mega/Fast or LPSR mode.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>

Acked-by: Adrian Hunter <adrian.hunter at intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 03980db..6fef6bc 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1254,6 +1254,16 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
>  }
>  
>  #ifdef CONFIG_PM
> +static int sdhci_esdhc_suspend(struct device *dev)
> +{
> +	return sdhci_pltfm_suspend(dev);
> +}
> +
> +static int sdhci_esdhc_resume(struct device *dev)
> +{
> +	return sdhci_pltfm_resume(dev);
> +}
> +
>  static int sdhci_esdhc_runtime_suspend(struct device *dev)
>  {
>  	struct sdhci_host *host = dev_get_drvdata(dev);
> @@ -1289,7 +1299,7 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
>  #endif
>  
>  static const struct dev_pm_ops sdhci_esdhc_pmops = {
> -	SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend, sdhci_pltfm_resume)
> +	SET_SYSTEM_SLEEP_PM_OPS(sdhci_esdhc_suspend, sdhci_esdhc_resume)
>  	SET_RUNTIME_PM_OPS(sdhci_esdhc_runtime_suspend,
>  				sdhci_esdhc_runtime_resume, NULL)
>  };
> 



From joro at 8bytes.org  Tue May 10 02:45:53 2016
From: joro at 8bytes.org (Joerg Roedel)
Date: Tue, 10 May 2016 11:45:53 +0200
Subject: [PATCH v2] iommu/arm-smmu: Use per-domain page sizes.
In-Reply-To: <112fc0e5f9bbe08007778b8438b35025d8e876a4.1462810410.git.robin.murphy@arm.com>
References: <ea520b8c72b5a72a1731bd35f6e3e50872fe6764.1460048991.git.robin.murphy@arm.com>
 <cover.1460048991.git.robin.murphy@arm.com>
 <112fc0e5f9bbe08007778b8438b35025d8e876a4.1462810410.git.robin.murphy@arm.com>
Message-ID: <20160510094553.GG13971@8bytes.org>

On Mon, May 09, 2016 at 05:20:09PM +0100, Robin Murphy wrote:
> Changes from v1: Rebased onto iommu/core to accommodate SMMUv2 changes.
> 
>  drivers/iommu/arm-smmu-v3.c | 19 ++++++++++---------
>  drivers/iommu/arm-smmu.c    | 27 +++++++++++++++------------
>  2 files changed, 25 insertions(+), 21 deletions(-)

Applied, thanks.



From ulf.hansson at linaro.org  Tue May 10 02:46:40 2016
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Tue, 10 May 2016 11:46:40 +0200
Subject: [PATCH 1/3] mmc: core: fix using wrong io voltage if
 mmc_select_hs200 fails
In-Reply-To: <CAPDyKFrZW=FVd-5CNrkH4=PgHRxUkT3Vic3vDuuho0NACmziww@mail.gmail.com>
References: <1461171092-30631-1-git-send-email-aisheng.dong@nxp.com>
 <CAPDyKFrZW=FVd-5CNrkH4=PgHRxUkT3Vic3vDuuho0NACmziww@mail.gmail.com>
Message-ID: <CAPDyKFogfeCKTW030MN-yA2xSiTOjGOoVvU2x3QHsWq6brjvYw@mail.gmail.com>

On 28 April 2016 at 11:26, Ulf Hansson <ulf.hansson at linaro.org> wrote:
> On 20 April 2016 at 18:51, Dong Aisheng <aisheng.dong at nxp.com> wrote:
>> Currently MMC core will keep going if HS200/HS timing switch failed
>> with -EBADMSG error by the assumption that the old timing is still valid.
>>
>> However, for mmc_select_hs200 case, the signal voltage may have already
>> been switched. If the timing switch failed, we should fall back to
>> the old voltage in case the card is continue run with legacy timing.
>>
>> If fall back signal voltage failed, we explicitly report an EIO error
>> to force retry during the next power cycle.
>>
>> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
>> ---
>>  drivers/mmc/core/mmc.c | 11 +++++++++--
>>  1 file changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>> index b8aa12c..f6683a9 100644
>> --- a/drivers/mmc/core/mmc.c
>> +++ b/drivers/mmc/core/mmc.c
>> @@ -1245,9 +1245,11 @@ static int mmc_select_hs200(struct mmc_card *card)
>>         struct mmc_host *host = card->host;
>>         bool send_status = true;
>>         unsigned int old_timing;
>> +       unsigned int old_signal_voltage;
>
> Nitpick; you can merge this change into the line above.
>

Applied for next with a minor change dealing with the nitpick above, thanks!

Kind regards
Uffe


From ulf.hansson at linaro.org  Tue May 10 02:46:45 2016
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Tue, 10 May 2016 11:46:45 +0200
Subject: [PATCH 2/3] mmc: core: remove the invalid message in
 mmc_select_timing
In-Reply-To: <20160428145806.GF27560@shlinux2.ap.freescale.net>
References: <1461171092-30631-1-git-send-email-aisheng.dong@nxp.com>
 <1461171092-30631-2-git-send-email-aisheng.dong@nxp.com>
 <CAPDyKFqvXTtbZsaWJ1gr7gm-jTpWwL0hAYxDje+LsC4ScyF2bQ@mail.gmail.com>
 <20160428145806.GF27560@shlinux2.ap.freescale.net>
Message-ID: <CAPDyKFq-nTYtqMChTVXsCd9oZyE10p4nO67b_u-tbq_e5HGV2g@mail.gmail.com>

On 28 April 2016 at 16:58, Dong Aisheng <dongas86 at gmail.com> wrote:
> On Thu, Apr 28, 2016 at 11:24:07AM +0200, Ulf Hansson wrote:
>> On 20 April 2016 at 18:51, Dong Aisheng <aisheng.dong at nxp.com> wrote:
>> > mmc_select_hs200() and mmc_select_hs() will keep the timing
>> > as before if switch fails. So it's meaningless to print the
>> > failed switched mode outside based on the current host timing.
>> >
>> > Furthermore, the original print is wrong, it should be:
>> > pr_warn("%s: switch to %s failed\n",
>> >         mmc_hostname(card->host),
>> >         mmc_card_hs(card) ? "high-speed" :
>> >         (mmc_card_hs200(card) ? "hs200" : ""));
>> >
>> > Since we already have error message in mmc_select_hs200(),
>> > simply remove it outside.
>> >
>> > Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
>> > ---
>> >  drivers/mmc/core/mmc.c | 10 +---------
>> >  1 file changed, 1 insertion(+), 9 deletions(-)
>> >
>> > diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>> > index f6683a9..55c8201 100644
>> > --- a/drivers/mmc/core/mmc.c
>> > +++ b/drivers/mmc/core/mmc.c
>> > @@ -1321,21 +1321,13 @@ static int mmc_select_timing(struct mmc_card *card)
>> >         if (err && err != -EBADMSG)
>> >                 return err;
>> >
>> > -       if (err) {
>> > -               pr_warn("%s: switch to %s failed\n",
>> > -                       mmc_card_hs(card) ? "high-speed" :
>> > -                       (mmc_card_hs200(card) ? "hs200" : ""),
>> > -                       mmc_hostname(card->host));
>> > -               err = 0;
>> > -       }
>> > -
>>
>> No, this is not correct.
>>
>> First, in patch1/3, you change to return an error code immediately
>> when __mmc_set_signal_voltage() fails, instead of using the "goto
>> err". Thus there will be no error printed for this case any more.
>>
>
> I noticed this issue when i made up this patch.
> Why i simply return is because i want to avoid write the following code:
> static int mmc_select_hs200(struct mmc_card *card)
> {
> ...
>         err = voltage_switch();
>         /* If fails try again during next card power cycle */
>         if (err)
>                 goto err;
> ....
>                 /* swith HS TIMING */
>                 err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>                                    EXT_CSD_HS_TIMING, val,
>                                    card->ext_csd.generic_cmd6_time,
>                                    true, send_status, true);
>                 if (err)
>                         goto err2;
> ..........
>
> err2:
>         if (err) {
>                 /* fall back to the old signal voltage, if fails report error */
>                 if (__mmc_set_signal_voltage(host, old_signal_voltage))
>                         err = -EIO;
>         }
>
> err:
>         if (err)
>                 pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
>                        __func__, err);
>
>         return err;
> }
>
> Because if first signal switch fails, we don't need fall back to original
> voltage. But HS timing switch needs.
>
> goto err makes the code a bit ugly.
> So i choose to avoid it and simply return since it's not so important
> and most host driver may already implement their debug IO switch debug info.
>
> Do you think if we can accept it?

Okay.

>
>> Second, mmc_select_hs() may fail and there is no print done within
>> that function which is why above print is also needed.
>>
>
> The same as above, i think this print is not so important.
> And __mmc_switch already has a err warn.
>
> And the most important reason is the original print outside is
> meaningless because it intends to print out the speed mode it
> wants to switch, however,it actually prints out the restored
> original speed mode.
>
>> On the other hand I agree with you, it doesn't seems necessary to
>> print two messages when mmc_select_hs200() fails. One should be
>> enough. Can we change this so *only* mmc_select_timing() will deal
>> with the print at all errors?
>>
>
> Yes, i agree with your idea.
> I also thought about it before, but it seems after patch 3,
> it may not be so necessary.
> Can you help check it?
>
>> >  bus_speed:
>> >         /*
>> >          * Set the bus speed to the selected bus timing.
>> >          * If timing is not selected, backward compatible is the default.
>> >          */
>> >         mmc_set_bus_speed(card);
>> > -       return err;
>> > +       return 0;
>> >  }
>> >
>> >  /*
>> > --
>> > 1.9.1
>> >
>>
>> Kind regards
>> Uffe
>
> Regards
> Dong Aisheng

I decided to apply this as is for next. Thanks!

Kind regards
Uffe


From ulf.hansson at linaro.org  Tue May 10 02:46:53 2016
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Tue, 10 May 2016 11:46:53 +0200
Subject: [PATCH 3/3] mmc: core: support hs speed mode if hs200 mode fails
In-Reply-To: <1461171092-30631-3-git-send-email-aisheng.dong@nxp.com>
References: <1461171092-30631-1-git-send-email-aisheng.dong@nxp.com>
 <1461171092-30631-3-git-send-email-aisheng.dong@nxp.com>
Message-ID: <CAPDyKFqNqLGXDPaCtPehSCM2tUS1r1yuYdg1_XJoUxfw-bB0jA@mail.gmail.com>

On 20 April 2016 at 18:51, Dong Aisheng <aisheng.dong at nxp.com> wrote:
> Currently if mmc_select_hs200 mode switch fails, MMC core
> can only use legacy mode to run the card.
> Let's retry HS speed mode if HS200 fails.
>
> Before the fix:
> mmc0: mmc_select_hs200 failed, error -74
> : switch to mmc0 failed
> mmc0: new MMC card at address 0001
> mmcblk0: mmc0:0001 Q2J55L 7.12 GiB
> mmcblk0boot0: mmc0:0001 Q2J55L partition 1 2.00 MiB
> mmcblk0boot1: mmc0:0001 Q2J55L partition 2 2.00 MiB
> mmcblk0rpmb: mmc0:0001 Q2J55L partition 3 4.00 MiB
>  mmcblk0: p1 p2
>
> After the fix:
> mmc0: mmc_select_hs200 failed, error -74
> mmc0: new DDR MMC card at address 0001
> mmcblk0: mmc0:0001 Q2J55L 7.12 GiB
> mmcblk0boot0: mmc0:0001 Q2J55L partition 1 2.00 MiB
> mmcblk0boot1: mmc0:0001 Q2J55L partition 2 2.00 MiB
> mmcblk0rpmb: mmc0:0001 Q2J55L partition 3 4.00 MiB
>  mmcblk0: p1 p2
>
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>

Applied for next, thanks!

Kind regards
Uffe

> ---
>  drivers/mmc/core/mmc.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 55c8201..b573dc7 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -1315,7 +1315,8 @@ static int mmc_select_timing(struct mmc_card *card)
>
>         if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
>                 err = mmc_select_hs200(card);
> -       else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
> +
> +       if (err && (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS))
>                 err = mmc_select_hs(card);
>
>         if (err && err != -EBADMSG)
> --
> 1.9.1
>


From ulf.hansson at linaro.org  Tue May 10 02:46:58 2016
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Tue, 10 May 2016 11:46:58 +0200
Subject: [PATCH 01/23] mmc: sdhci: removed unneeded function wrappers
In-Reply-To: <1460741387-23815-2-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-2-git-send-email-aisheng.dong@nxp.com>
Message-ID: <CAPDyKFrr2753H=6kUOSxVJdUczsFufhhySKTpsk6VTSLy5_ULw@mail.gmail.com>

On 15 April 2016 at 19:29, Dong Aisheng <aisheng.dong at nxp.com> wrote:
> After commit d6463f170cf0 ("mmc: sdhci: Remove redundant runtime PM calls"),
> some of original sdhci_do_xx() function wrappers becomes meaningless,
> so remove them.
>
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>

Thanks, applied for next!

Kind regards
Uffe

> ---
>  drivers/mmc/host/sdhci.c | 60 ++++++++++++------------------------------------
>  1 file changed, 15 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 8e74e75..be52a3a 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -53,7 +53,7 @@ static void sdhci_finish_data(struct sdhci_host *);
>  static void sdhci_finish_command(struct sdhci_host *);
>  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
>  static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
> -static int sdhci_do_get_cd(struct sdhci_host *host);
> +static int sdhci_get_cd(struct mmc_host *mmc);
>
>  #ifdef CONFIG_PM
>  static void sdhci_runtime_pm_bus_on(struct sdhci_host *host);
> @@ -194,7 +194,7 @@ EXPORT_SYMBOL_GPL(sdhci_reset);
>  static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
>  {
>         if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
> -               if (!sdhci_do_get_cd(host))
> +               if (!sdhci_get_cd(host->mmc))
>                         return;
>         }
>
> @@ -1393,11 +1393,11 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
>  }
>  EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
>
> -static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
> +static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  {
> +       struct sdhci_host *host = mmc_priv(mmc);
>         unsigned long flags;
>         u8 ctrl;
> -       struct mmc_host *mmc = host->mmc;
>
>         spin_lock_irqsave(&host->lock, flags);
>
> @@ -1551,16 +1551,10 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
>         spin_unlock_irqrestore(&host->lock, flags);
>  }
>
> -static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> +static int sdhci_get_cd(struct mmc_host *mmc)
>  {
>         struct sdhci_host *host = mmc_priv(mmc);
> -
> -       sdhci_do_set_ios(host, ios);
> -}
> -
> -static int sdhci_do_get_cd(struct sdhci_host *host)
> -{
> -       int gpio_cd = mmc_gpio_get_cd(host->mmc);
> +       int gpio_cd = mmc_gpio_get_cd(mmc);
>
>         if (host->flags & SDHCI_DEVICE_DEAD)
>                 return 0;
> @@ -1584,13 +1578,6 @@ static int sdhci_do_get_cd(struct sdhci_host *host)
>         return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
>  }
>
> -static int sdhci_get_cd(struct mmc_host *mmc)
> -{
> -       struct sdhci_host *host = mmc_priv(mmc);
> -
> -       return sdhci_do_get_cd(host);
> -}
> -
>  static int sdhci_check_ro(struct sdhci_host *host)
>  {
>         unsigned long flags;
> @@ -1615,8 +1602,9 @@ static int sdhci_check_ro(struct sdhci_host *host)
>
>  #define SAMPLE_COUNT   5
>
> -static int sdhci_do_get_ro(struct sdhci_host *host)
> +static int sdhci_get_ro(struct mmc_host *mmc)
>  {
> +       struct sdhci_host *host = mmc_priv(mmc);
>         int i, ro_count;
>
>         if (!(host->quirks & SDHCI_QUIRK_UNSTABLE_RO_DETECT))
> @@ -1641,13 +1629,6 @@ static void sdhci_hw_reset(struct mmc_host *mmc)
>                 host->ops->hw_reset(host);
>  }
>
> -static int sdhci_get_ro(struct mmc_host *mmc)
> -{
> -       struct sdhci_host *host = mmc_priv(mmc);
> -
> -       return sdhci_do_get_ro(host);
> -}
> -
>  static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
>  {
>         if (!(host->flags & SDHCI_DEVICE_DEAD)) {
> @@ -1677,10 +1658,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
>         spin_unlock_irqrestore(&host->lock, flags);
>  }
>
> -static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> -                                               struct mmc_ios *ios)
> +static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> +                                            struct mmc_ios *ios)
>  {
> -       struct mmc_host *mmc = host->mmc;
> +       struct sdhci_host *host = mmc_priv(mmc);
>         u16 ctrl;
>         int ret;
>
> @@ -1768,17 +1749,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
>         }
>  }
>
> -static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> -       struct mmc_ios *ios)
> -{
> -       struct sdhci_host *host = mmc_priv(mmc);
> -
> -       if (host->version < SDHCI_SPEC_300)
> -               return 0;
> -
> -       return sdhci_do_start_signal_voltage_switch(host, ios);
> -}
> -
>  static int sdhci_card_busy(struct mmc_host *mmc)
>  {
>         struct sdhci_host *host = mmc_priv(mmc);
> @@ -2070,7 +2040,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
>         if (host->ops->card_event)
>                 host->ops->card_event(host);
>
> -       present = sdhci_do_get_cd(host);
> +       present = sdhci_get_cd(host->mmc);
>
>         spin_lock_irqsave(&host->lock, flags);
>
> @@ -2643,7 +2613,7 @@ int sdhci_resume_host(struct sdhci_host *host)
>                 sdhci_init(host, 0);
>                 host->pwr = 0;
>                 host->clock = 0;
> -               sdhci_do_set_ios(host, &host->mmc->ios);
> +               sdhci_set_ios(host->mmc, &host->mmc->ios);
>         } else {
>                 sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
>                 mmiowb();
> @@ -2721,8 +2691,8 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
>         /* Force clock and power re-program */
>         host->pwr = 0;
>         host->clock = 0;
> -       sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios);
> -       sdhci_do_set_ios(host, &host->mmc->ios);
> +       sdhci_start_signal_voltage_switch(host->mmc, &host->mmc->ios);
> +       sdhci_set_ios(host->mmc, &host->mmc->ios);
>
>         if ((host_flags & SDHCI_PV_ENABLED) &&
>                 !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
> --
> 1.9.1
>


From marc.zyngier at arm.com  Tue May 10 02:48:16 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 10:48:16 +0100
Subject: [PATCH v3 16/55] KVM: arm/arm64: vgic-new: Add IRQ sorting
In-Reply-To: <1462531568-9799-17-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-17-git-send-email-andre.przywara@arm.com>
Message-ID: <5731AE60.40905@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> Adds the sorting function to cover the case where you have more IRQs
> to consider than you have LRs. We now consider priorities.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...


From bamvor.zhangjian at huawei.com  Tue May 10 02:47:26 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Tue, 10 May 2016 17:47:26 +0800
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <9651510.pg5Vmm8vKS@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160506123731.GA11959@yury-N73SV> <573190CF.6030408@huawei.com>
 <9651510.pg5Vmm8vKS@wuerfel>
Message-ID: <5731AE2E.2050403@huawei.com>

Hi, Arnd

On 2016/5/10 16:36, Arnd Bergmann wrote:
> On Tuesday 10 May 2016 15:42:07 Zhangjian wrote:
>> On 2016/5/6 20:37, Yury Norov wrote:
>>> On Fri, May 06, 2016 at 08:16:48PM +0800, Zhangjian (Bamvor) wrote:
>>>
>>> AFAIR, here we don't shift offset, as it's 64-bit both in user-
>>> and kernel-space,
>> In your ilp32-2.22 branch, you wrapper mmap to mmap2 in which type of
>> offset is off_t. And off_t is 32bit in ilp32, correct?
>> "sysdeps/unix/sysv/linux/aarch64/ilp32/mmap64.c"
>> /* mmap is provided by mmap as they are the same. */
>> void *__mmap (void *__addr, size_t __len, int __prot,
>>                        int __flags, int __fd, __off_t __offset)
>> {
>>      void *result;
>>      result = (void *)
>>        INLINE_SYSCALL (mmap2, 6, __addr,
>>                        __len, __prot, __flags, __fd, __offset);
>>      return result;
>> }
>
> __off_t should be 'long long' on new architectures, and map
> to __kernel_loff_t.
>
> Can you see how it is defined?
For kernel part, in "include/uapi/asm-generic/posix_types.h":
     #ifndef __kernel_long_t
     typedef long            __kernel_long_t;
     typedef unsigned long   __kernel_ulong_t;
     #endif
     typedef __kernel_long_t __kernel_off_t;
in "include/linux/types.h":
     typedef __kernel_off_t          off_t;

"include/uapi/asm-generic/posix_types.h" is uapi, we could not check
"ARCH_32BIT_OFF_T" here. Besides, the `__kernel_long_t` is long which
mean it is 32bit in ILP32. should we define something like x32?
     ```
     diff --git a/arch/arm64/include/uapi/asm/posix_types.h b/arch/arm64/include/uapi/asm/posix_types.h
     index 7985ff6..9baa8d3 100644
     --- a/arch/arm64/include/uapi/asm/posix_types.h
     +++ b/arch/arm64/include/uapi/asm/posix_types.h
     @@ -5,6 +5,9 @@ typedef unsigned short __kernel_old_uid_t;
      typedef unsigned short __kernel_old_gid_t;
       #define __kernel_old_uid_t __kernel_old_uid_t

      +typedef long long __kernel_long_t;
      +typedef unsigned long long __kernel_ulong_t;
      +
       #include <asm-generic/posix_types.h>

       #endif /*  __ASM_POSIX_TYPES_H */u
     ```
After this definition, the following kernel types is 64bit in ILP32:
     typedef __kernel_long_t         __kernel_suseconds_t;
     typedef __kernel_long_t __kernel_ssize_t;
     typedef __kernel_long_t __kernel_ptrdiff_t;
     typedef __kernel_long_t __kernel_off_t;
     typedef __kernel_long_t __kernel_time_t;
     typedef __kernel_long_t __kernel_clock_t;
     typedef __kernel_ulong_t __kernel_ino_t;
     typedef __kernel_ulong_t __kernel_size_t;

But it is not a generic way to define off_t to 64bit if
ARCH_32BIT_OFF_T is not defined. How about this one? We need to
define `__kernel_off_t` on all the old 32bit architecture like
arm:
```
diff --git a/arch/arm/include/uapi/asm/posix_types.h b/arch/arm/include/uapi/asm/posix_types.h
index d2de9cb..f9d065c 100644
--- a/arch/arm/include/uapi/asm/posix_types.h
+++ b/arch/arm/include/uapi/asm/posix_types.h
@@ -32,6 +32,9 @@ typedef unsigned short                __kernel_gid_t;
  typedef unsigned short         __kernel_old_dev_t;
  #define __kernel_old_dev_t __kernel_old_dev_t

+typedef __kernel_long_t        __kernel_off_t;
+#define __kernel_off_t
+
  #include <asm-generic/posix_types.h>

  #endif
```
And We could change the generic posix_types.h a little bit:
```
diff --git a/include/uapi/asm-generic/posix_types.h b/include/uapi/asm-generic/posix_types.h
index fe74fcc..7bbaf04 100644
--- a/include/uapi/asm-generic/posix_types.h
+++ b/include/uapi/asm-generic/posix_types.h
@@ -80,10 +80,13 @@ typedef struct {
  } __kernel_fsid_t;
  #endif

+#ifndef __kernel_off_t
+typedef long long __kernel_off_t;
+#endif
+
  /*
   * anything below here should be completely generic
   */
-typedef __kernel_long_t        __kernel_off_t;
  typedef long long      __kernel_loff_t;
  typedef __kernel_long_t        __kernel_time_t;
  typedef __kernel_long_t        __kernel_clock_t;
```

On the other hand, glibc define it own off_t in "bits/types.h":
     __STD_TYPE __OFF_T_TYPE __off_t;        /* Type of file sizes and offsets.  */
     __STD_TYPE __OFF64_T_TYPE __off64_t;    /* Type of file sizes and offsets (LFS).  */

in "sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h":
     #define __OFF_T_TYPE            __SLONGWORD_TYPE
     #define __OFF64_T_TYPE          __SQUAD_TYPE

If we define off_t as 64bit in glibc:
     #define __OFF_T_TYPE           __SQUAD_TYPE

Should We need to align all the off_t syscall to 64bit syscall in
kernel?

Regards

Bamvor


> 	Arnd
>



From yamada.masahiro at socionext.com  Tue May 10 02:50:49 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:49 +0900
Subject: [RFC PATCH 08/21] clk: uniphier: add clock driver for UniPhier
 PH1-LD11 SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-9-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/clk/uniphier/Kconfig             |  4 ++
 drivers/clk/uniphier/Makefile            |  1 +
 drivers/clk/uniphier/clk-uniphier-ld11.c | 83 ++++++++++++++++++++++++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 drivers/clk/uniphier/clk-uniphier-ld11.c

diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
index d4a3d55..1746aea 100644
--- a/drivers/clk/uniphier/Kconfig
+++ b/drivers/clk/uniphier/Kconfig
@@ -26,4 +26,8 @@ config CLK_UNIPHIER_PXS2
 	tristate "Clock driver for UniPhier ProXstream2/PH1-LD6b SoC"
 	default ARM
 
+config CLK_UNIPHIER_LD11
+	tristate "Clock driver for UniPhier PH1-LD11 SoC"
+	default ARM64
+
 endif
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
index 20a274f..e056771 100644
--- a/drivers/clk/uniphier/Makefile
+++ b/drivers/clk/uniphier/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_CLK_UNIPHIER_PRO4)	+= clk-uniphier-pro4.o
 obj-$(CONFIG_CLK_UNIPHIER_SLD8)	+= clk-uniphier-sld8.o
 obj-$(CONFIG_CLK_UNIPHIER_PRO5)	+= clk-uniphier-pro5.o
 obj-$(CONFIG_CLK_UNIPHIER_PXS2)	+= clk-uniphier-pxs2.o
+obj-$(CONFIG_CLK_UNIPHIER_LD11)	+= clk-uniphier-ld11.o
diff --git a/drivers/clk/uniphier/clk-uniphier-ld11.c b/drivers/clk/uniphier/clk-uniphier-ld11.c
new file mode 100644
index 0000000..5b8536a
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-ld11.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "clk-uniphier.h"
+
+static const struct uniphier_clk_data uniphier_ld11_clk_data[] = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "ref",
+			.mult = 80,
+			.div = 1,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 0,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 34,
+		},
+	},
+	{
+		.name = "fi2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 1,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 50,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 7,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x200c,
+			.mask = BIT(8),
+			.enable_val = BIT(8),
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static int uniphier_ld11_clk_probe(struct platform_device *pdev)
+{
+	return uniphier_clk_probe(pdev, uniphier_ld11_clk_data);
+}
+
+static struct platform_driver uniphier_ld11_clk_driver = {
+	.probe = uniphier_ld11_clk_probe,
+	.remove = uniphier_clk_remove,
+	.driver = {
+		.name = "uniphier-ld11-clk",
+	},
+};
+module_platform_driver(uniphier_ld11_clk_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-LD11 System Clock Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:48 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:48 +0900
Subject: [RFC PATCH 07/21] clk: uniphier: add clock driver for UniPhier
 ProXstream2/PH1-LD6b SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-8-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/clk/uniphier/Kconfig             |  4 ++
 drivers/clk/uniphier/Makefile            |  1 +
 drivers/clk/uniphier/clk-uniphier-pxs2.c | 83 ++++++++++++++++++++++++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 drivers/clk/uniphier/clk-uniphier-pxs2.c

diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
index de3fada..d4a3d55 100644
--- a/drivers/clk/uniphier/Kconfig
+++ b/drivers/clk/uniphier/Kconfig
@@ -22,4 +22,8 @@ config CLK_UNIPHIER_PRO5
 	tristate "Clock driver for UniPhier PH1-Pro5 SoC"
 	default ARM
 
+config CLK_UNIPHIER_PXS2
+	tristate "Clock driver for UniPhier ProXstream2/PH1-LD6b SoC"
+	default ARM
+
 endif
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
index d1edf30..20a274f 100644
--- a/drivers/clk/uniphier/Makefile
+++ b/drivers/clk/uniphier/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_CLK_UNIPHIER_LD4)	+= clk-uniphier-ld4.o
 obj-$(CONFIG_CLK_UNIPHIER_PRO4)	+= clk-uniphier-pro4.o
 obj-$(CONFIG_CLK_UNIPHIER_SLD8)	+= clk-uniphier-sld8.o
 obj-$(CONFIG_CLK_UNIPHIER_PRO5)	+= clk-uniphier-pro5.o
+obj-$(CONFIG_CLK_UNIPHIER_PXS2)	+= clk-uniphier-pxs2.o
diff --git a/drivers/clk/uniphier/clk-uniphier-pxs2.c b/drivers/clk/uniphier/clk-uniphier-pxs2.c
new file mode 100644
index 0000000..07f7969
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-pxs2.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "clk-uniphier.h"
+
+static const struct uniphier_clk_data uniphier_pxs2_clk_data[] = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "ref",
+			.mult = 96,
+			.div = 1,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 0,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 27,
+		},
+	},
+	{
+		.name = "fi2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 1,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 48,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 7,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x2104,
+			.mask = BIT(10),
+			.enable_val = BIT(10),
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static int uniphier_pxs2_clk_probe(struct platform_device *pdev)
+{
+	return uniphier_clk_probe(pdev, uniphier_pxs2_clk_data);
+}
+
+static struct platform_driver uniphier_pxs2_clk_driver = {
+	.probe = uniphier_pxs2_clk_probe,
+	.remove = uniphier_clk_remove,
+	.driver = {
+		.name = "uniphier-pxs2-clk",
+	},
+};
+module_platform_driver(uniphier_pxs2_clk_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier ProXstream2 System Clock Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:44 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:44 +0900
Subject: [RFC PATCH 03/21] clk: uniphier: add clock driver for UniPhier
 PH1-LD4 SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-4-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/clk/uniphier/Kconfig            |   4 ++
 drivers/clk/uniphier/Makefile           |   2 +
 drivers/clk/uniphier/clk-uniphier-ld4.c | 112 ++++++++++++++++++++++++++++++++
 3 files changed, 118 insertions(+)
 create mode 100644 drivers/clk/uniphier/clk-uniphier-ld4.c

diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
index f36529a..f5a7fbb 100644
--- a/drivers/clk/uniphier/Kconfig
+++ b/drivers/clk/uniphier/Kconfig
@@ -6,4 +6,8 @@ menuconfig CLK_UNIPHIER
 
 if CLK_UNIPHIER
 
+config CLK_UNIPHIER_LD4
+	tristate "Clock driver for UniPhier PH1-LD4 SoC"
+	default ARM
+
 endif
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
index 4d6daa8..2ca2070 100644
--- a/drivers/clk/uniphier/Makefile
+++ b/drivers/clk/uniphier/Makefile
@@ -3,3 +3,5 @@ obj-y				+= clk-uniphier-fixed-factor.o
 obj-y				+= clk-uniphier-fixed-rate.o
 obj-y				+= clk-uniphier-gate.o
 obj-y				+= clk-uniphier-mux.o
+
+obj-$(CONFIG_CLK_UNIPHIER_LD4)	+= clk-uniphier-ld4.o
diff --git a/drivers/clk/uniphier/clk-uniphier-ld4.c b/drivers/clk/uniphier/clk-uniphier-ld4.c
new file mode 100644
index 0000000..229729a
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-ld4.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "clk-uniphier.h"
+
+static const struct uniphier_clk_data uniphier_ld4_clk_data[] = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "ref",
+			.mult = 65,
+			.div = 1,
+		},
+	},
+	{
+		.name = "upll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "ref",
+			.mult = 288000,
+			.div = 24576,
+		},
+	},
+	{
+		.name = "a2pll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "ref",
+			.mult = 24,
+			.div = 1,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 0,
+		.data.factor = {
+			.parent_name = "a2pll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "i2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 1,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "ehci",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 5,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 1,
+			.div = 12,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 7,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x2104,
+			.mask = BIT(10),
+			.enable_val = BIT(10),
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static int uniphier_ld4_clk_probe(struct platform_device *pdev)
+{
+	return uniphier_clk_probe(pdev, uniphier_ld4_clk_data);
+}
+
+static struct platform_driver uniphier_ld4_clk_driver = {
+	.probe = uniphier_ld4_clk_probe,
+	.remove = uniphier_clk_remove,
+	.driver = {
+		.name = "uniphier-ld4-clk",
+	},
+};
+module_platform_driver(uniphier_ld4_clk_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-LD4 System Clock Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:45 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:45 +0900
Subject: [RFC PATCH 04/21] clk: uniphier: add clock driver for UniPhier
 PH1-Pro4 SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-5-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/clk/uniphier/Kconfig             |   4 ++
 drivers/clk/uniphier/Makefile            |   1 +
 drivers/clk/uniphier/clk-uniphier-pro4.c | 112 +++++++++++++++++++++++++++++++
 3 files changed, 117 insertions(+)
 create mode 100644 drivers/clk/uniphier/clk-uniphier-pro4.c

diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
index f5a7fbb..d789e26 100644
--- a/drivers/clk/uniphier/Kconfig
+++ b/drivers/clk/uniphier/Kconfig
@@ -10,4 +10,8 @@ config CLK_UNIPHIER_LD4
 	tristate "Clock driver for UniPhier PH1-LD4 SoC"
 	default ARM
 
+config CLK_UNIPHIER_PRO4
+	tristate "Clock driver for UniPhier PH1-Pro4 SoC"
+	default ARM
+
 endif
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
index 2ca2070..ceed615 100644
--- a/drivers/clk/uniphier/Makefile
+++ b/drivers/clk/uniphier/Makefile
@@ -5,3 +5,4 @@ obj-y				+= clk-uniphier-gate.o
 obj-y				+= clk-uniphier-mux.o
 
 obj-$(CONFIG_CLK_UNIPHIER_LD4)	+= clk-uniphier-ld4.o
+obj-$(CONFIG_CLK_UNIPHIER_PRO4)	+= clk-uniphier-pro4.o
diff --git a/drivers/clk/uniphier/clk-uniphier-pro4.c b/drivers/clk/uniphier/clk-uniphier-pro4.c
new file mode 100644
index 0000000..e2ab185
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-pro4.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "clk-uniphier.h"
+
+static const struct uniphier_clk_data uniphier_pro4_clk_data[] = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "ref",
+			.mult = 64,
+			.div = 1,
+		},
+	},
+	{
+		.name = "upll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "ref",
+			.mult = 288,
+			.div = 25,
+		},
+	},
+	{
+		.name = "a2pll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 256,
+			.div = 125,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 0,
+		.data.factor = {
+			.parent_name = "a2pll",
+			.mult = 1,
+			.div = 8,
+		},
+	},
+	{
+		.name = "fi2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 1,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 32,
+		},
+	},
+	{
+		.name = "ehci",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 5,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 1,
+			.div = 12,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 7,
+		.data.gate = {
+			.parent_name = "ref",
+			.reg = 0x2104,
+			.mask = BIT(10),
+			.enable_val = BIT(10),
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static int uniphier_pro4_clk_probe(struct platform_device *pdev)
+{
+	return uniphier_clk_probe(pdev, uniphier_pro4_clk_data);
+}
+
+static struct platform_driver uniphier_pro4_clk_driver = {
+	.probe = uniphier_pro4_clk_probe,
+	.remove = uniphier_clk_remove,
+	.driver = {
+		.name = "uniphier-pro4-clk",
+	},
+};
+module_platform_driver(uniphier_pro4_clk_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-Pro4 System Clock Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:47 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:47 +0900
Subject: [RFC PATCH 06/21] clk: uniphier: add clock driver for UniPhier
 PH1-Pro5 SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-7-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/clk/uniphier/Kconfig             |   4 ++
 drivers/clk/uniphier/Makefile            |   1 +
 drivers/clk/uniphier/clk-uniphier-pro5.c | 102 +++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+)
 create mode 100644 drivers/clk/uniphier/clk-uniphier-pro5.c

diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
index 8e930c3..de3fada 100644
--- a/drivers/clk/uniphier/Kconfig
+++ b/drivers/clk/uniphier/Kconfig
@@ -18,4 +18,8 @@ config CLK_UNIPHIER_SLD8
 	tristate "Clock driver for UniPhier PH1-sLD8 SoC"
 	default ARM
 
+config CLK_UNIPHIER_PRO5
+	tristate "Clock driver for UniPhier PH1-Pro5 SoC"
+	default ARM
+
 endif
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
index c7a8390..d1edf30 100644
--- a/drivers/clk/uniphier/Makefile
+++ b/drivers/clk/uniphier/Makefile
@@ -7,3 +7,4 @@ obj-y				+= clk-uniphier-mux.o
 obj-$(CONFIG_CLK_UNIPHIER_LD4)	+= clk-uniphier-ld4.o
 obj-$(CONFIG_CLK_UNIPHIER_PRO4)	+= clk-uniphier-pro4.o
 obj-$(CONFIG_CLK_UNIPHIER_SLD8)	+= clk-uniphier-sld8.o
+obj-$(CONFIG_CLK_UNIPHIER_PRO5)	+= clk-uniphier-pro5.o
diff --git a/drivers/clk/uniphier/clk-uniphier-pro5.c b/drivers/clk/uniphier/clk-uniphier-pro5.c
new file mode 100644
index 0000000..5ce5fbc
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-pro5.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "clk-uniphier.h"
+
+static const struct uniphier_clk_data uniphier_pro5_clk_data[] = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "ref",
+			.mult = 120,
+			.div = 1,
+		},
+	},
+	{
+		.name = "dapll1",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "ref",
+			.mult = 128,
+			.div = 125,
+		},
+	},
+	{
+		.name = "dapll2",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 144,
+			.div = 5,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 0,
+		.data.factor = {
+			.parent_name = "dapll2",
+			.mult = 1,
+			.div = 8,
+		},
+	},
+	{
+		.name = "fi2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 1,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 48,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 7,
+		.data.gate = {
+			.parent_name = "stdmac-clken",
+			.reg = 0x2000,
+			.mask = BIT(10),
+			.enable_val = BIT(10),
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static int uniphier_pro5_clk_probe(struct platform_device *pdev)
+{
+	return uniphier_clk_probe(pdev, uniphier_pro5_clk_data);
+}
+
+static struct platform_driver uniphier_pro5_clk_driver = {
+	.probe = uniphier_pro5_clk_probe,
+	.remove = uniphier_clk_remove,
+	.driver = {
+		.name = "uniphier-pro5-clk",
+	},
+};
+module_platform_driver(uniphier_pro5_clk_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-Pro5 System Clock Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:50 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:50 +0900
Subject: [RFC PATCH 09/21] clk: uniphier: add clock driver for UniPhier
 PH1-LD20 SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-10-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/clk/uniphier/Kconfig             |  4 ++
 drivers/clk/uniphier/Makefile            |  1 +
 drivers/clk/uniphier/clk-uniphier-ld20.c | 83 ++++++++++++++++++++++++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 drivers/clk/uniphier/clk-uniphier-ld20.c

diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
index 1746aea..6e0a311 100644
--- a/drivers/clk/uniphier/Kconfig
+++ b/drivers/clk/uniphier/Kconfig
@@ -30,4 +30,8 @@ config CLK_UNIPHIER_LD11
 	tristate "Clock driver for UniPhier PH1-LD11 SoC"
 	default ARM64
 
+config CLK_UNIPHIER_LD20
+	tristate "Clock driver for UniPhier PH1-LD20 SoC"
+	default ARM64
+
 endif
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
index e056771..59272a6 100644
--- a/drivers/clk/uniphier/Makefile
+++ b/drivers/clk/uniphier/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_CLK_UNIPHIER_SLD8)	+= clk-uniphier-sld8.o
 obj-$(CONFIG_CLK_UNIPHIER_PRO5)	+= clk-uniphier-pro5.o
 obj-$(CONFIG_CLK_UNIPHIER_PXS2)	+= clk-uniphier-pxs2.o
 obj-$(CONFIG_CLK_UNIPHIER_LD11)	+= clk-uniphier-ld11.o
+obj-$(CONFIG_CLK_UNIPHIER_LD20)	+= clk-uniphier-ld20.o
diff --git a/drivers/clk/uniphier/clk-uniphier-ld20.c b/drivers/clk/uniphier/clk-uniphier-ld20.c
new file mode 100644
index 0000000..a15a59b
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-ld20.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "clk-uniphier.h"
+
+static const struct uniphier_clk_data uniphier_ld20_clk_data[] = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "ref",
+			.mult = 80,
+			.div = 1,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 0,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 34,
+		},
+	},
+	{
+		.name = "fi2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 1,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 50,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 7,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x200c,
+			.mask = BIT(8),
+			.enable_val = BIT(8),
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static int uniphier_ld20_clk_probe(struct platform_device *pdev)
+{
+	return uniphier_clk_probe(pdev, uniphier_ld20_clk_data);
+}
+
+static struct platform_driver uniphier_ld20_clk_driver = {
+	.probe = uniphier_ld20_clk_probe,
+	.remove = uniphier_clk_remove,
+	.driver = {
+		.name = "uniphier-ld20-clk",
+	},
+};
+module_platform_driver(uniphier_ld20_clk_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-LD20 System Clock Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:46 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:46 +0900
Subject: [RFC PATCH 05/21] clk: uniphier: add clock driver for UniPhier
 PH1-sLD8 SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-6-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/clk/uniphier/Kconfig             |   4 ++
 drivers/clk/uniphier/Makefile            |   1 +
 drivers/clk/uniphier/clk-uniphier-sld8.c | 102 +++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+)
 create mode 100644 drivers/clk/uniphier/clk-uniphier-sld8.c

diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
index d789e26..8e930c3 100644
--- a/drivers/clk/uniphier/Kconfig
+++ b/drivers/clk/uniphier/Kconfig
@@ -14,4 +14,8 @@ config CLK_UNIPHIER_PRO4
 	tristate "Clock driver for UniPhier PH1-Pro4 SoC"
 	default ARM
 
+config CLK_UNIPHIER_SLD8
+	tristate "Clock driver for UniPhier PH1-sLD8 SoC"
+	default ARM
+
 endif
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
index ceed615..c7a8390 100644
--- a/drivers/clk/uniphier/Makefile
+++ b/drivers/clk/uniphier/Makefile
@@ -6,3 +6,4 @@ obj-y				+= clk-uniphier-mux.o
 
 obj-$(CONFIG_CLK_UNIPHIER_LD4)	+= clk-uniphier-ld4.o
 obj-$(CONFIG_CLK_UNIPHIER_PRO4)	+= clk-uniphier-pro4.o
+obj-$(CONFIG_CLK_UNIPHIER_SLD8)	+= clk-uniphier-sld8.o
diff --git a/drivers/clk/uniphier/clk-uniphier-sld8.c b/drivers/clk/uniphier/clk-uniphier-sld8.c
new file mode 100644
index 0000000..74574ba
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-sld8.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "clk-uniphier.h"
+
+static const struct uniphier_clk_data uniphier_sld8_clk_data[] = {
+	{
+		.name = "spll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "ref",
+			.mult = 64,
+			.div = 1,
+		},
+	},
+	{
+		.name = "upll",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = -1,
+		.data.factor = {
+			.parent_name = "ref",
+			.mult = 288,
+			.div = 25,
+		},
+	},
+	{
+		.name = "uart",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 0,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 20,
+		},
+	},
+	{
+		.name = "i2c",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 1,
+		.data.factor = {
+			.parent_name = "spll",
+			.mult = 1,
+			.div = 16,
+		},
+	},
+	{
+		.name = "ehci",
+		.type = UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+		.output_index = 5,
+		.data.factor = {
+			.parent_name = "upll",
+			.mult = 1,
+			.div = 12,
+		},
+	},
+	{
+		.name = "stdmac",
+		.type = UNIPHIER_CLK_TYPE_GATE,
+		.output_index = 7,
+		.data.gate = {
+			.parent_name = NULL,
+			.reg = 0x2104,
+			.mask = BIT(10),
+			.enable_val = BIT(10),
+		},
+	},
+	{ /* sentinel */ }
+};
+
+static int uniphier_sld8_clk_probe(struct platform_device *pdev)
+{
+	return uniphier_clk_probe(pdev, uniphier_sld8_clk_data);
+}
+
+static struct platform_driver uniphier_sld8_clk_driver = {
+	.probe = uniphier_sld8_clk_probe,
+	.remove = uniphier_clk_remove,
+	.driver = {
+		.name = "uniphier-sld8-clk",
+	},
+};
+module_platform_driver(uniphier_sld8_clk_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-sLD8 System Clock Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:51 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:51 +0900
Subject: [RFC PATCH 10/21] clk: uniphier: add clock driver for Media I/O block
 on UniPhier SoCs
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-11-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/clk/uniphier/Kconfig            |   4 +
 drivers/clk/uniphier/Makefile           |   2 +
 drivers/clk/uniphier/clk-uniphier-mio.c | 215 ++++++++++++++++++++++++++++++++
 3 files changed, 221 insertions(+)
 create mode 100644 drivers/clk/uniphier/clk-uniphier-mio.c

diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
index 6e0a311..895c4a0 100644
--- a/drivers/clk/uniphier/Kconfig
+++ b/drivers/clk/uniphier/Kconfig
@@ -34,4 +34,8 @@ config CLK_UNIPHIER_LD20
 	tristate "Clock driver for UniPhier PH1-LD20 SoC"
 	default ARM64
 
+config CLK_UNIPHIER_MIO
+	tristate "Clock driver for UniPhier Media I/O block"
+	default y
+
 endif
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
index 59272a6..ae71f04 100644
--- a/drivers/clk/uniphier/Makefile
+++ b/drivers/clk/uniphier/Makefile
@@ -11,3 +11,5 @@ obj-$(CONFIG_CLK_UNIPHIER_PRO5)	+= clk-uniphier-pro5.o
 obj-$(CONFIG_CLK_UNIPHIER_PXS2)	+= clk-uniphier-pxs2.o
 obj-$(CONFIG_CLK_UNIPHIER_LD11)	+= clk-uniphier-ld11.o
 obj-$(CONFIG_CLK_UNIPHIER_LD20)	+= clk-uniphier-ld20.o
+
+obj-$(CONFIG_CLK_UNIPHIER_MIO)	+= clk-uniphier-mio.o
diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c
new file mode 100644
index 0000000..28691b7
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-mio.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "clk-uniphier.h"
+
+#define UNIPHIER_MIO_CLK_SD_FIXED					\
+	{								\
+		.name = "sd-44m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 44444444,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-33m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 33333333,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-50m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 50000000,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-67m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 66666666,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-100m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 100000000,			\
+		},							\
+	},								\
+	{								\
+		.name = "sd-40m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 40000000,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-25m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 25000000,				\
+		},							\
+	},								\
+	{								\
+		.name = "sd-22m",					\
+		.type = UNIPHIER_CLK_TYPE_FIXED_RATE,			\
+		.output_index = -1,					\
+		.data.rate = {						\
+			.fixed_rate = 22222222,				\
+		},							\
+	}
+
+#define UNIPHIER_MIO_CLK_SD(ch, index)					\
+	{								\
+		.name = "sd" #ch "-sel",				\
+		.type = UNIPHIER_CLK_TYPE_MUX,				\
+		.output_index = -1,					\
+		.data.mux = {						\
+			.parent_names = {				\
+				"sd-44m",				\
+				"sd-33m",				\
+				"sd-50m",				\
+				"sd-67m",				\
+				"sd-100m",				\
+				"sd-40m",				\
+				"sd-25m",				\
+				"sd-22m",				\
+			},						\
+			.num_parents = 8,				\
+			.reg = 0x30 + 0x200 * ch,			\
+			.masks = {					\
+				0x00031000,				\
+				0x00031000,				\
+				0x00031000,				\
+				0x00031000,				\
+				0x00001300,				\
+				0x00001300,				\
+				0x00001300,				\
+				0x00001300,				\
+			},						\
+			.vals = {					\
+				0x00000000,				\
+				0x00010000,				\
+				0x00020000,				\
+				0x00030000,				\
+				0x00001000,				\
+				0x00001100,				\
+				0x00001200,				\
+				0x00001300,				\
+			},						\
+		},							\
+	},								\
+	{								\
+		.name = "sd" #ch,					\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = (index),				\
+		.data.gate = {						\
+			.parent_name = "sd" #ch "-sel",			\
+			.reg = 0x20 + 0x200 * ch,			\
+			.mask = BIT(8),					\
+			.enable_val = BIT(8),				\
+		},							\
+	}
+
+#define UNIPHIER_MIO_CLK_EHCI(ch, index)				\
+	{								\
+		.name = "ehci" #ch,					\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = (index),				\
+		.data.gate = {						\
+			.parent_name = "ehci",				\
+			.reg = 0x20 + 0x200 * ch,			\
+			.mask = BIT(29) | BIT(28),			\
+			.enable_val = BIT(29) | BIT(28),		\
+		},							\
+	}
+
+#define UNIPHIER_MIO_CLK_DMAC(index)					\
+	{								\
+		.name = "miodmac",					\
+		.type = UNIPHIER_CLK_TYPE_GATE,				\
+		.output_index = (index),				\
+		.data.gate = {						\
+			.parent_name = "stdmac",			\
+			.reg = 0x20,					\
+			.mask = BIT(25),				\
+			.enable_val = BIT(25),				\
+		},							\
+	}
+
+static const struct uniphier_clk_data uniphier_ld4_mio_clk_data[] = {
+	UNIPHIER_MIO_CLK_SD_FIXED,
+	UNIPHIER_MIO_CLK_SD(0, 0),
+	UNIPHIER_MIO_CLK_SD(1, 1),
+	UNIPHIER_MIO_CLK_SD(2, 2),	/* for Pro4 */
+	UNIPHIER_MIO_CLK_DMAC(3),
+	UNIPHIER_MIO_CLK_EHCI(0, 4),
+	UNIPHIER_MIO_CLK_EHCI(1, 5),
+	UNIPHIER_MIO_CLK_EHCI(2, 6),	/* for LD4/sLD8 */
+	{ /* sentinel */ }
+};
+
+static int uniphier_ld4_mio_clk_probe(struct platform_device *pdev)
+{
+	return uniphier_clk_probe(pdev, uniphier_ld4_mio_clk_data);
+}
+
+static struct platform_driver uniphier_ld4_mio_clk_driver = {
+	.probe = uniphier_ld4_mio_clk_probe,
+	.remove = uniphier_clk_remove,
+	.driver = {
+		.name = "uniphier-ld4-mio-clk",
+	},
+};
+module_platform_driver(uniphier_ld4_mio_clk_driver);
+
+static const struct uniphier_clk_data uniphier_pro5_mio_clk_data[] = {
+	UNIPHIER_MIO_CLK_SD_FIXED,
+	UNIPHIER_MIO_CLK_SD(0, 0),
+	UNIPHIER_MIO_CLK_SD(1, 1),
+	{ /* sentinel */ }
+};
+
+static int uniphier_pro5_mio_clk_probe(struct platform_device *pdev)
+{
+	return uniphier_clk_probe(pdev, uniphier_pro5_mio_clk_data);
+}
+
+static struct platform_driver uniphier_pro5_mio_clk_driver = {
+	.probe = uniphier_pro5_mio_clk_probe,
+	.remove = uniphier_clk_remove,
+	.driver = {
+		.name = "uniphier-pro5-mio-clk",
+	},
+};
+module_platform_driver(uniphier_pro5_mio_clk_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier Media I/O Clock Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:58 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:58 +0900
Subject: [RFC PATCH 17/21] reset: uniphier: add reset driver for UniPhier
 ProXstream2/PH1-LD6b SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-18-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/reset/uniphier/Kconfig               |  4 +++
 drivers/reset/uniphier/Makefile              |  1 +
 drivers/reset/uniphier/reset-uniphier-pxs2.c | 46 ++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)
 create mode 100644 drivers/reset/uniphier/reset-uniphier-pxs2.c

diff --git a/drivers/reset/uniphier/Kconfig b/drivers/reset/uniphier/Kconfig
index 92d9a5f..022aef4 100644
--- a/drivers/reset/uniphier/Kconfig
+++ b/drivers/reset/uniphier/Kconfig
@@ -22,4 +22,8 @@ config RESET_UNIPHIER_PRO5
 	tristate "Reset driver for UniPhier PH1-Pro5 SoC"
 	default ARM
 
+config RESET_UNIPHIER_PXS2
+	tristate "Reset driver for UniPhier ProXstream2/PH1-LD6b SoC"
+	default ARM
+
 endif
diff --git a/drivers/reset/uniphier/Makefile b/drivers/reset/uniphier/Makefile
index 537e3f8..50847db 100644
--- a/drivers/reset/uniphier/Makefile
+++ b/drivers/reset/uniphier/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_RESET_UNIPHIER_LD4)	+= reset-uniphier-ld4.o
 obj-$(CONFIG_RESET_UNIPHIER_PRO4)	+= reset-uniphier-pro4.o
 obj-$(CONFIG_RESET_UNIPHIER_SLD8)	+= reset-uniphier-sld8.o
 obj-$(CONFIG_RESET_UNIPHIER_PRO5)	+= reset-uniphier-pro5.o
+obj-$(CONFIG_RESET_UNIPHIER_PXS2)	+= reset-uniphier-pxs2.o
diff --git a/drivers/reset/uniphier/reset-uniphier-pxs2.c b/drivers/reset/uniphier/reset-uniphier-pxs2.c
new file mode 100644
index 0000000..55d7273
--- /dev/null
+++ b/drivers/reset/uniphier/reset-uniphier-pxs2.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "reset-uniphier.h"
+
+static const struct uniphier_reset_data uniphier_pxs2_reset_data[] = {
+	{
+		.id = 7,
+		.reg = 0x2000,
+		.mask = BIT(10),
+		.deassert_val = BIT(10),
+	},
+	{ .id = UNIPHIER_RESET_ID_END }
+};
+
+static int uniphier_pxs2_reset_probe(struct platform_device *pdev)
+{
+	return uniphier_reset_probe(pdev, uniphier_pxs2_reset_data);
+}
+
+static struct platform_driver uniphier_pxs2_reset_driver = {
+	.probe = uniphier_pxs2_reset_probe,
+	.driver = {
+		.name = "uniphier-pxs2-reset",
+	},
+};
+module_platform_driver(uniphier_pxs2_reset_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier ProXstream2 Reset Controller Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:43 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:43 +0900
Subject: [RFC PATCH 02/21] clk: uniphier: add core support for UniPhier clock
 driver
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-3-git-send-email-yamada.masahiro@socionext.com>

The core support for the clock drivers of all UniPhier SoCs.

This part is the update from the version 2.
https://lkml.org/lkml/2016/5/2/721

After discussing Stephen and Michael, I changed various things
in this version:

  - Change to platform drivers instead of OF_CLK_DECLARE
  - Split into a core part + SoC drivers
    SoC drivers just consist of tables of SoC-specific data.
    This allows reviewer to concentrate on the core-part
  - Hard-code parent clock names for cascading

Another big change is that the clock drivers are populated
from the parent MFD.
On UniPhier SoCs, registers for clock, reset, and other system
controlling are mixed in one hardware block.  It is difficult
to have one independent clock node.
So, I chose to use MFD from which clocks and resets (and
power in the future) are populated.

This series is just for review.
Please do not apply this patch.

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

 MAINTAINERS                                      |  1 +
 drivers/clk/uniphier/Kconfig                     |  9 +++
 drivers/clk/uniphier/Makefile                    |  5 ++
 drivers/clk/uniphier/clk-uniphier-core.c         | 99 ++++++++++++++++++++++++
 drivers/clk/uniphier/clk-uniphier-fixed-factor.c | 50 ++++++++++++
 drivers/clk/uniphier/clk-uniphier-fixed-rate.c   | 49 ++++++++++++
 drivers/clk/uniphier/clk-uniphier-gate.c         | 98 +++++++++++++++++++++++
 drivers/clk/uniphier/clk-uniphier-mux.c          | 96 +++++++++++++++++++++++
 drivers/clk/uniphier/clk-uniphier.h              | 89 +++++++++++++++++++++
 9 files changed, 496 insertions(+)
 create mode 100644 drivers/clk/uniphier/Kconfig
 create mode 100644 drivers/clk/uniphier/Makefile
 create mode 100644 drivers/clk/uniphier/clk-uniphier-core.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-fixed-factor.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-fixed-rate.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-gate.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-mux.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 8c987ca..38c6bb5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1727,6 +1727,7 @@ F:	arch/arm/mach-uniphier/
 F:	arch/arm/mm/cache-uniphier.c
 F:	arch/arm64/boot/dts/socionext/
 F:	drivers/bus/uniphier-system-bus.c
+F:	drivers/clk/uniphier/
 F:	drivers/i2c/busses/i2c-uniphier*
 F:	drivers/mfd/uniphier-mfd.c
 F:	drivers/mmc/host/uniphier-sd.c
diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
new file mode 100644
index 0000000..f36529a
--- /dev/null
+++ b/drivers/clk/uniphier/Kconfig
@@ -0,0 +1,9 @@
+menuconfig CLK_UNIPHIER
+	bool "Clock drivers for UniPhier SoCs"
+	depends on (ARCH_UNIPHIER && MFD_UNIPHIER) || COMPILE_TEST
+	depends on OF && MFD_CORE && MFD_SYSCON
+	default ARCH_UNIPHIER && MFD_UNIPHIER
+
+if CLK_UNIPHIER
+
+endif
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
new file mode 100644
index 0000000..4d6daa8
--- /dev/null
+++ b/drivers/clk/uniphier/Makefile
@@ -0,0 +1,5 @@
+obj-y				+= clk-uniphier-core.o
+obj-y				+= clk-uniphier-fixed-factor.o
+obj-y				+= clk-uniphier-fixed-rate.o
+obj-y				+= clk-uniphier-gate.o
+obj-y				+= clk-uniphier-mux.o
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
new file mode 100644
index 0000000..72953a0
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-core.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "clk-uniphier.h"
+
+static struct clk_hw *uniphier_clk_register(struct device *dev,
+					    struct regmap *regmap,
+					const struct uniphier_clk_data *data)
+{
+	switch (data->type) {
+	case UNIPHIER_CLK_TYPE_FIXED_FACTOR:
+		return uniphier_clk_register_fixed_factor(dev, data->name,
+							  &data->data.factor);
+	case UNIPHIER_CLK_TYPE_FIXED_RATE:
+		return uniphier_clk_register_fixed_rate(dev, data->name,
+							&data->data.rate);
+	case UNIPHIER_CLK_TYPE_GATE:
+		return uniphier_clk_register_gate(dev, regmap, data->name,
+						  &data->data.gate);
+	case UNIPHIER_CLK_TYPE_MUX:
+		return uniphier_clk_register_mux(dev, regmap, data->name,
+						 &data->data.mux);
+	default:
+		WARN(1, "unsupported clock type\n");
+		return ERR_PTR(-EINVAL);
+	}
+}
+
+int uniphier_clk_probe(struct platform_device *pdev,
+		       const struct uniphier_clk_data *data)
+{
+	struct device *dev = &pdev->dev;
+	struct clk_hw_onecell_data *hw_data;
+	struct regmap *regmap;
+	const struct uniphier_clk_data *p;
+	int clk_num = 0;
+
+	/* parent should be MFD and syscon node */
+	regmap = syscon_node_to_regmap(dev->parent->of_node);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "failed to get regmap\n");
+		return PTR_ERR(regmap);
+	}
+
+	for (p = data; p->name; p++)
+		clk_num = max(clk_num, p->output_index + 1);
+
+	hw_data = devm_kzalloc(dev,
+			sizeof(*hw_data) + clk_num * sizeof(struct clk_hw *),
+			GFP_KERNEL);
+	if (!hw_data)
+		return -ENOMEM;
+
+	hw_data->num = clk_num;
+
+	for (p = data; p->name; p++) {
+		struct clk_hw *hw;
+
+		dev_dbg(dev, "register %s (index=%d)\n", p->name,
+			p->output_index);
+		hw = uniphier_clk_register(dev, regmap, p);
+		if (IS_ERR(hw)) {
+			dev_err(dev, "failed to register %s\n", p->name);
+			return PTR_ERR(hw);
+		}
+
+		if (p->output_index >= 0)
+			hw_data->hws[p->output_index] = hw;
+	}
+
+	return of_clk_add_hw_provider(dev->parent->of_node,
+				      of_clk_hw_onecell_get, hw_data);
+}
+EXPORT_SYMBOL_GPL(uniphier_clk_probe);
+
+int uniphier_clk_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.parent->of_node);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(uniphier_clk_remove);
diff --git a/drivers/clk/uniphier/clk-uniphier-fixed-factor.c b/drivers/clk/uniphier/clk-uniphier-fixed-factor.c
new file mode 100644
index 0000000..2a2d5bd
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-fixed-factor.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/device.h>
+
+#include "clk-uniphier.h"
+
+struct clk_hw *uniphier_clk_register_fixed_factor(struct device *dev,
+						  const char *name,
+			const struct uniphier_clk_fixed_factor_data *data)
+{
+	struct clk_fixed_factor *fix;
+	struct clk_init_data init;
+	int ret;
+
+	fix = devm_kzalloc(dev, sizeof(*fix), GFP_KERNEL);
+	if (!fix)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_fixed_factor_ops;
+	init.flags = data->parent_name ? CLK_SET_RATE_PARENT : 0;
+	init.flags |= CLK_IS_BASIC;
+	init.parent_names = data->parent_name ? &data->parent_name : NULL;
+	init.num_parents = data->parent_name ? 1 : 0;
+
+	fix->mult = data->mult;
+	fix->div = data->div;
+	fix->hw.init = &init;
+
+	ret = devm_clk_hw_register(dev, &fix->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &fix->hw;
+}
+EXPORT_SYMBOL_GPL(uniphier_clk_register_fixed_factor);
diff --git a/drivers/clk/uniphier/clk-uniphier-fixed-rate.c b/drivers/clk/uniphier/clk-uniphier-fixed-rate.c
new file mode 100644
index 0000000..1fc6258
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-fixed-rate.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/device.h>
+
+#include "clk-uniphier.h"
+
+struct clk_hw *uniphier_clk_register_fixed_rate(struct device *dev,
+						const char *name,
+				const struct uniphier_clk_fixed_rate_data *data)
+{
+	struct clk_fixed_rate *fixed;
+	struct clk_init_data init;
+	int ret;
+
+	/* allocate fixed-rate clock */
+	fixed = devm_kzalloc(dev, sizeof(*fixed), GFP_KERNEL);
+	if (!fixed)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_fixed_rate_ops;
+	init.flags = CLK_IS_BASIC;
+	init.parent_names = NULL;
+	init.num_parents = 0;
+
+	fixed->fixed_rate = data->fixed_rate;
+	fixed->hw.init = &init;
+
+	ret = devm_clk_hw_register(dev, &fixed->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &fixed->hw;
+}
+EXPORT_SYMBOL_GPL(uniphier_clk_register_fixed_rate);
diff --git a/drivers/clk/uniphier/clk-uniphier-gate.c b/drivers/clk/uniphier/clk-uniphier-gate.c
new file mode 100644
index 0000000..c42b0a8
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-gate.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/device.h>
+#include <linux/regmap.h>
+
+#include "clk-uniphier.h"
+
+struct uniphier_clk_gate {
+	struct clk_hw hw;
+	struct regmap *regmap;
+	unsigned int reg;
+	unsigned int mask;
+	unsigned int enable_val;
+};
+
+#define to_uniphier_clk_gate(_hw) \
+				container_of(_hw, struct uniphier_clk_gate, hw)
+
+static int uniphier_clk_gate_enable(struct clk_hw *hw)
+{
+	struct uniphier_clk_gate *gate = to_uniphier_clk_gate(hw);
+
+	return regmap_write_bits(gate->regmap, gate->reg, gate->mask,
+				 gate->enable_val);
+}
+
+static void uniphier_clk_gate_disable(struct clk_hw *hw)
+{
+	struct uniphier_clk_gate *gate = to_uniphier_clk_gate(hw);
+
+	if (regmap_write_bits(gate->regmap, gate->reg, gate->mask,
+			      ~gate->enable_val) < 0)
+		pr_warn("regmap_write_bits failed. clk may not be disabled\n");
+}
+
+static int uniphier_clk_gate_is_enabled(struct clk_hw *hw)
+{
+	struct uniphier_clk_gate *gate = to_uniphier_clk_gate(hw);
+	unsigned int val;
+
+	if (regmap_read(gate->regmap, gate->reg, &val) < 0)
+		pr_warn("regmap_read failed. is_enabled() may return wrong result\n");
+
+	return (val & gate->mask) == gate->enable_val;
+}
+
+static const struct clk_ops uniphier_clk_gate_ops = {
+	.enable = uniphier_clk_gate_enable,
+	.disable = uniphier_clk_gate_disable,
+	.is_enabled = uniphier_clk_gate_is_enabled,
+};
+
+struct clk_hw *uniphier_clk_register_gate(struct device *dev,
+					  struct regmap *regmap,
+					  const char *name,
+				const struct uniphier_clk_gate_data *data)
+{
+	struct uniphier_clk_gate *gate;
+	struct clk_init_data init;
+	int ret;
+
+	gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &uniphier_clk_gate_ops;
+	init.flags = data->parent_name ? CLK_SET_RATE_PARENT : 0;
+	init.parent_names = data->parent_name ? &data->parent_name : NULL;
+	init.num_parents = data->parent_name ? 1 : 0;
+
+	gate->regmap = regmap;
+	gate->reg = data->reg;
+	gate->mask = data->mask;
+	gate->enable_val = data->enable_val;
+	gate->hw.init = &init;
+
+	ret = devm_clk_hw_register(dev, &gate->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &gate->hw;
+}
+EXPORT_SYMBOL_GPL(uniphier_clk_register_gate);
diff --git a/drivers/clk/uniphier/clk-uniphier-mux.c b/drivers/clk/uniphier/clk-uniphier-mux.c
new file mode 100644
index 0000000..e18d5d3
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-mux.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/device.h>
+#include <linux/regmap.h>
+
+#include "clk-uniphier.h"
+
+struct uniphier_clk_mux {
+	struct clk_hw hw;
+	struct regmap *regmap;
+	unsigned int reg;
+	const unsigned int *masks;
+	const unsigned int *vals;
+};
+
+#define to_uniphier_clk_mux(_hw) container_of(_hw, struct uniphier_clk_mux, hw)
+
+static int uniphier_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct uniphier_clk_mux *mux = to_uniphier_clk_mux(hw);
+
+	return regmap_write_bits(mux->regmap, mux->reg, mux->masks[index],
+				 mux->vals[index]);
+}
+
+static u8 uniphier_clk_mux_get_parent(struct clk_hw *hw)
+{
+	struct uniphier_clk_mux *mux = to_uniphier_clk_mux(hw);
+	int num_parents = clk_hw_get_num_parents(hw);
+	int ret;
+	u32 val;
+	u8 i;
+
+	ret = regmap_read(mux->regmap, mux->reg, &val);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < num_parents; i++)
+		if ((mux->masks[i] & val) == mux->vals[i])
+			return i;
+
+	return -EINVAL;
+}
+
+static const struct clk_ops uniphier_clk_mux_ops = {
+	.determine_rate = __clk_mux_determine_rate,
+	.set_parent = uniphier_clk_mux_set_parent,
+	.get_parent = uniphier_clk_mux_get_parent,
+};
+
+struct clk_hw *uniphier_clk_register_mux(struct device *dev,
+					 struct regmap *regmap,
+					 const char *name,
+				const struct uniphier_clk_mux_data *data)
+{
+	struct uniphier_clk_mux *mux;
+	struct clk_init_data init;
+	int ret;
+
+	mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+	if (!mux)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &uniphier_clk_mux_ops;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = data->parent_names;
+	init.num_parents = data->num_parents,
+
+	mux->regmap = regmap;
+	mux->reg = data->reg;
+	mux->masks = data->masks;
+	mux->vals = data->vals;
+	mux->hw.init = &init;
+
+	ret = devm_clk_hw_register(dev, &mux->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &mux->hw;
+}
+EXPORT_SYMBOL_GPL(uniphier_clk_register_mux);
diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h
new file mode 100644
index 0000000..d5f3948
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __CLK_UNIPHIER_H__
+#define __CLK_UNIPHIER_H__
+
+struct clk_hw;
+struct device;
+struct platform_device;
+struct regmap;
+
+#define UNIPHIER_CLK_MUX_MAX_PARENTS	8
+
+enum uniphier_clk_type {
+	UNIPHIER_CLK_TYPE_FIXED_FACTOR,
+	UNIPHIER_CLK_TYPE_FIXED_RATE,
+	UNIPHIER_CLK_TYPE_GATE,
+	UNIPHIER_CLK_TYPE_MUX,
+};
+
+struct uniphier_clk_fixed_factor_data {
+	const char *parent_name;
+	unsigned int mult;
+	unsigned int div;
+};
+
+struct uniphier_clk_fixed_rate_data {
+	unsigned long fixed_rate;
+};
+
+struct uniphier_clk_gate_data {
+	const char *parent_name;
+	unsigned int reg;
+	unsigned int mask;
+	unsigned int enable_val;
+};
+
+struct uniphier_clk_mux_data {
+	const char *parent_names[UNIPHIER_CLK_MUX_MAX_PARENTS];
+	unsigned int num_parents;
+	unsigned int reg;
+	unsigned int masks[UNIPHIER_CLK_MUX_MAX_PARENTS];
+	unsigned int vals[UNIPHIER_CLK_MUX_MAX_PARENTS];
+};
+
+struct uniphier_clk_data {
+	const char *name;
+	enum uniphier_clk_type type;
+	int output_index;
+	union {
+		struct uniphier_clk_fixed_factor_data factor;
+		struct uniphier_clk_fixed_rate_data rate;
+		struct uniphier_clk_gate_data gate;
+		struct uniphier_clk_mux_data mux;
+	} data;
+};
+
+struct clk_hw *uniphier_clk_register_fixed_factor(struct device *dev,
+						  const char *name,
+			const struct uniphier_clk_fixed_factor_data *data);
+struct clk_hw *uniphier_clk_register_fixed_rate(struct device *dev,
+						const char *name,
+			const struct uniphier_clk_fixed_rate_data *data);
+struct clk_hw *uniphier_clk_register_gate(struct device *dev,
+					  struct regmap *regmap,
+					  const char *name,
+				const struct uniphier_clk_gate_data *data);
+struct clk_hw *uniphier_clk_register_mux(struct device *dev,
+					 struct regmap *regmap,
+					 const char *name,
+				const struct uniphier_clk_mux_data *data);
+
+int uniphier_clk_probe(struct platform_device *pdev,
+		       const struct uniphier_clk_data *data);
+int uniphier_clk_remove(struct platform_device *pdev);
+
+#endif /* __CLK_UNIPHIER_H__ */
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:57 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:57 +0900
Subject: [RFC PATCH 16/21] reset: uniphier: add reset driver for UniPhier
 PH1-Pro5 SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-17-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/reset/uniphier/Kconfig               |  4 +++
 drivers/reset/uniphier/Makefile              |  1 +
 drivers/reset/uniphier/reset-uniphier-pro5.c | 46 ++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)
 create mode 100644 drivers/reset/uniphier/reset-uniphier-pro5.c

diff --git a/drivers/reset/uniphier/Kconfig b/drivers/reset/uniphier/Kconfig
index 307d563..92d9a5f 100644
--- a/drivers/reset/uniphier/Kconfig
+++ b/drivers/reset/uniphier/Kconfig
@@ -18,4 +18,8 @@ config RESET_UNIPHIER_SLD8
 	tristate "Reset driver for UniPhier PH1-sLD8 SoC"
 	default ARM
 
+config RESET_UNIPHIER_PRO5
+	tristate "Reset driver for UniPhier PH1-Pro5 SoC"
+	default ARM
+
 endif
diff --git a/drivers/reset/uniphier/Makefile b/drivers/reset/uniphier/Makefile
index e1001c6..537e3f8 100644
--- a/drivers/reset/uniphier/Makefile
+++ b/drivers/reset/uniphier/Makefile
@@ -3,3 +3,4 @@ obj-y					+= reset-uniphier-core.o
 obj-$(CONFIG_RESET_UNIPHIER_LD4)	+= reset-uniphier-ld4.o
 obj-$(CONFIG_RESET_UNIPHIER_PRO4)	+= reset-uniphier-pro4.o
 obj-$(CONFIG_RESET_UNIPHIER_SLD8)	+= reset-uniphier-sld8.o
+obj-$(CONFIG_RESET_UNIPHIER_PRO5)	+= reset-uniphier-pro5.o
diff --git a/drivers/reset/uniphier/reset-uniphier-pro5.c b/drivers/reset/uniphier/reset-uniphier-pro5.c
new file mode 100644
index 0000000..dae6f54
--- /dev/null
+++ b/drivers/reset/uniphier/reset-uniphier-pro5.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "reset-uniphier.h"
+
+static const struct uniphier_reset_data uniphier_pro5_reset_data[] = {
+	{
+		.id = 7,
+		.reg = 0x2000,
+		.mask = BIT(10),
+		.deassert_val = BIT(10),
+	},
+	{ .id = UNIPHIER_RESET_ID_END }
+};
+
+static int uniphier_pro5_reset_probe(struct platform_device *pdev)
+{
+	return uniphier_reset_probe(pdev, uniphier_pro5_reset_data);
+}
+
+static struct platform_driver uniphier_pro5_reset_driver = {
+	.probe = uniphier_pro5_reset_probe,
+	.driver = {
+		.name = "uniphier-pro5-reset",
+	},
+};
+module_platform_driver(uniphier_pro5_reset_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-Pro5 Reset Controller Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:51:02 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:51:02 +0900
Subject: [RFC PATCH 21/21] reset: uniphier: add reset driver for Peripheral
 block on UniPhier SoCs
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-22-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/reset/uniphier/Kconfig               |   4 ++
 drivers/reset/uniphier/Makefile              |   1 +
 drivers/reset/uniphier/reset-uniphier-peri.c | 101 +++++++++++++++++++++++++++
 3 files changed, 106 insertions(+)
 create mode 100644 drivers/reset/uniphier/reset-uniphier-peri.c

diff --git a/drivers/reset/uniphier/Kconfig b/drivers/reset/uniphier/Kconfig
index a582938..d3e629e 100644
--- a/drivers/reset/uniphier/Kconfig
+++ b/drivers/reset/uniphier/Kconfig
@@ -38,4 +38,8 @@ config RESET_UNIPHIER_MIO
 	tristate "Reset driver for UniPhier Media I/O block"
 	default y
 
+config RESET_UNIPHIER_PERI
+	tristate "Reset driver for UniPhier Peripheral block"
+	default y
+
 endif
diff --git a/drivers/reset/uniphier/Makefile b/drivers/reset/uniphier/Makefile
index e83bd14..65e9d2d 100644
--- a/drivers/reset/uniphier/Makefile
+++ b/drivers/reset/uniphier/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_RESET_UNIPHIER_LD11)	+= reset-uniphier-ld11.o
 obj-$(CONFIG_RESET_UNIPHIER_LD20)	+= reset-uniphier-ld20.o
 
 obj-$(CONFIG_RESET_UNIPHIER_MIO)	+= reset-uniphier-mio.o
+obj-$(CONFIG_RESET_UNIPHIER_PERI)	+= reset-uniphier-peri.o
diff --git a/drivers/reset/uniphier/reset-uniphier-peri.c b/drivers/reset/uniphier/reset-uniphier-peri.c
new file mode 100644
index 0000000..1ec1c16
--- /dev/null
+++ b/drivers/reset/uniphier/reset-uniphier-peri.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "reset-uniphier.h"
+
+#define UNIPHIER_PERI_RESET_UART(ch, index)		\
+	{						\
+		.id = (index),				\
+		.reg = 0x114,				\
+		.mask = BIT(19 + ch),			\
+		.deassert_val = BIT(19 + ch),		\
+	}
+
+#define UNIPHIER_PERI_RESET_I2C(ch, index)		\
+	{						\
+		.id = (index),				\
+		.reg = 0x114,				\
+		.mask = BIT(5 + ch),			\
+		.deassert_val = BIT(5 + ch),		\
+	}
+
+#define UNIPHIER_PERI_RESET_FI2C(ch, index)		\
+	{						\
+		.id = (index),				\
+		.reg = 0x114,				\
+		.mask = BIT(24 + ch),			\
+		.deassert_val = BIT(24 + ch),		\
+	}
+
+static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
+	UNIPHIER_PERI_RESET_UART(0, 0),
+	UNIPHIER_PERI_RESET_UART(1, 1),
+	UNIPHIER_PERI_RESET_UART(2, 2),
+	UNIPHIER_PERI_RESET_UART(3, 3),
+	UNIPHIER_PERI_RESET_I2C(0, 4),
+	UNIPHIER_PERI_RESET_I2C(1, 5),
+	UNIPHIER_PERI_RESET_I2C(2, 6),
+	UNIPHIER_PERI_RESET_I2C(3, 7),
+	UNIPHIER_PERI_RESET_I2C(4, 8),
+	{ .id = UNIPHIER_RESET_ID_END }
+};
+
+static int uniphier_ld4_peri_reset_probe(struct platform_device *pdev)
+{
+	return uniphier_reset_probe(pdev, uniphier_ld4_peri_reset_data);
+}
+
+static struct platform_driver uniphier_ld4_peri_reset_driver = {
+	.probe = uniphier_ld4_peri_reset_probe,
+	.driver = {
+		.name = "uniphier-ld4-peri-reset",
+	},
+};
+module_platform_driver(uniphier_ld4_peri_reset_driver);
+
+static const struct uniphier_reset_data uniphier_pro5_peri_reset_data[] = {
+	UNIPHIER_PERI_RESET_UART(0, 0),
+	UNIPHIER_PERI_RESET_UART(1, 1),
+	UNIPHIER_PERI_RESET_UART(2, 2),
+	UNIPHIER_PERI_RESET_UART(3, 3),
+	UNIPHIER_PERI_RESET_FI2C(0, 4),
+	UNIPHIER_PERI_RESET_FI2C(1, 5),
+	UNIPHIER_PERI_RESET_FI2C(2, 6),
+	UNIPHIER_PERI_RESET_FI2C(3, 7),
+	UNIPHIER_PERI_RESET_FI2C(4, 8),
+	UNIPHIER_PERI_RESET_FI2C(5, 9),
+	UNIPHIER_PERI_RESET_FI2C(6, 10),
+	{ .id = UNIPHIER_RESET_ID_END }
+};
+
+static int uniphier_pro5_peri_reset_probe(struct platform_device *pdev)
+{
+	return uniphier_reset_probe(pdev, uniphier_pro5_peri_reset_data);
+}
+
+static struct platform_driver uniphier_pro5_peri_reset_driver = {
+	.probe = uniphier_pro5_peri_reset_probe,
+	.driver = {
+		.name = "uniphier-pro5-peri-reset",
+	},
+};
+module_platform_driver(uniphier_pro5_peri_reset_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier Peripheral Reset Controller Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:54 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:54 +0900
Subject: [RFC PATCH 13/21] reset: uniphier: add reset driver for UniPhier
 PH1-LD4 SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-14-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/reset/uniphier/Kconfig              |  4 +++
 drivers/reset/uniphier/Makefile             |  2 ++
 drivers/reset/uniphier/reset-uniphier-ld4.c | 46 +++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+)
 create mode 100644 drivers/reset/uniphier/reset-uniphier-ld4.c

diff --git a/drivers/reset/uniphier/Kconfig b/drivers/reset/uniphier/Kconfig
index e82f7a7..875afd9 100644
--- a/drivers/reset/uniphier/Kconfig
+++ b/drivers/reset/uniphier/Kconfig
@@ -6,4 +6,8 @@ menuconfig RESET_UNIPHIER
 
 if RESET_UNIPHIER
 
+config RESET_UNIPHIER_LD4
+	tristate "Reset driver for UniPhier PH1-LD4 SoC"
+	default ARM
+
 endif
diff --git a/drivers/reset/uniphier/Makefile b/drivers/reset/uniphier/Makefile
index ba660bc..c99a420 100644
--- a/drivers/reset/uniphier/Makefile
+++ b/drivers/reset/uniphier/Makefile
@@ -1 +1,3 @@
 obj-y					+= reset-uniphier-core.o
+
+obj-$(CONFIG_RESET_UNIPHIER_LD4)	+= reset-uniphier-ld4.o
diff --git a/drivers/reset/uniphier/reset-uniphier-ld4.c b/drivers/reset/uniphier/reset-uniphier-ld4.c
new file mode 100644
index 0000000..be6e06c
--- /dev/null
+++ b/drivers/reset/uniphier/reset-uniphier-ld4.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "reset-uniphier.h"
+
+static const struct uniphier_reset_data uniphier_ld4_reset_data[] = {
+	{
+		.id = 7,
+		.reg = 0x2000,
+		.mask = BIT(10),
+		.deassert_val = BIT(10),
+	},
+	{ .id = UNIPHIER_RESET_ID_END }
+};
+
+static int uniphier_ld4_reset_probe(struct platform_device *pdev)
+{
+	return uniphier_reset_probe(pdev, uniphier_ld4_reset_data);
+}
+
+static struct platform_driver uniphier_ld4_reset_driver = {
+	.probe = uniphier_ld4_reset_probe,
+	.driver = {
+		.name = "uniphier-ld4-reset",
+	},
+};
+module_platform_driver(uniphier_ld4_reset_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-LD4 Reset Controller Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:59 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:59 +0900
Subject: [RFC PATCH 18/21] reset: uniphier: add reset driver for UniPhier
 PH1-LD11 SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-19-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/reset/uniphier/Kconfig               |  4 +++
 drivers/reset/uniphier/Makefile              |  1 +
 drivers/reset/uniphier/reset-uniphier-ld11.c | 46 ++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)
 create mode 100644 drivers/reset/uniphier/reset-uniphier-ld11.c

diff --git a/drivers/reset/uniphier/Kconfig b/drivers/reset/uniphier/Kconfig
index 022aef4..d9a2123 100644
--- a/drivers/reset/uniphier/Kconfig
+++ b/drivers/reset/uniphier/Kconfig
@@ -26,4 +26,8 @@ config RESET_UNIPHIER_PXS2
 	tristate "Reset driver for UniPhier ProXstream2/PH1-LD6b SoC"
 	default ARM
 
+config RESET_UNIPHIER_LD11
+	tristate "Reset driver for UniPhier PH1-LD11 SoC"
+	default ARM
+
 endif
diff --git a/drivers/reset/uniphier/Makefile b/drivers/reset/uniphier/Makefile
index 50847db..f25f648 100644
--- a/drivers/reset/uniphier/Makefile
+++ b/drivers/reset/uniphier/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_RESET_UNIPHIER_PRO4)	+= reset-uniphier-pro4.o
 obj-$(CONFIG_RESET_UNIPHIER_SLD8)	+= reset-uniphier-sld8.o
 obj-$(CONFIG_RESET_UNIPHIER_PRO5)	+= reset-uniphier-pro5.o
 obj-$(CONFIG_RESET_UNIPHIER_PXS2)	+= reset-uniphier-pxs2.o
+obj-$(CONFIG_RESET_UNIPHIER_LD11)	+= reset-uniphier-ld11.o
diff --git a/drivers/reset/uniphier/reset-uniphier-ld11.c b/drivers/reset/uniphier/reset-uniphier-ld11.c
new file mode 100644
index 0000000..75cb379
--- /dev/null
+++ b/drivers/reset/uniphier/reset-uniphier-ld11.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "reset-uniphier.h"
+
+static const struct uniphier_reset_data uniphier_ld11_reset_data[] = {
+	{
+		.id = 7,
+		.reg = 0x200c,
+		.mask = BIT(8),
+		.deassert_val = BIT(8),
+	},
+	{ .id = UNIPHIER_RESET_ID_END }
+};
+
+static int uniphier_ld11_reset_probe(struct platform_device *pdev)
+{
+	return uniphier_reset_probe(pdev, uniphier_ld11_reset_data);
+}
+
+static struct platform_driver uniphier_ld11_reset_driver = {
+	.probe = uniphier_ld11_reset_probe,
+	.driver = {
+		.name = "uniphier-ld11-reset",
+	},
+};
+module_platform_driver(uniphier_ld11_reset_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-LD11 Reset Controller Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:42 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:42 +0900
Subject: [RFC PATCH 01/21] mfd: uniphier: add UniPhier MFD driver
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-2-git-send-email-yamada.masahiro@socionext.com>

This MFD driver populates child devices such clock, reset, and other
system controlling blocks.

On UniPhier SoCs, one system control block contains various registers
for clock, reset, and others in it.  So, it is not reasonable to have
separate DT nodes for different sub-systems.

This MFD approach modifies Device Tree source just once for adding
an MFD node.

This series is just for review.
Please do not apply this patch.

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

 MAINTAINERS                |   1 +
 drivers/mfd/Kconfig        |   9 ++
 drivers/mfd/Makefile       |   1 +
 drivers/mfd/uniphier-mfd.c | 214 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 225 insertions(+)
 create mode 100644 drivers/mfd/uniphier-mfd.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 87b2ddd..8c987ca 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1728,6 +1728,7 @@ F:	arch/arm/mm/cache-uniphier.c
 F:	arch/arm64/boot/dts/socionext/
 F:	drivers/bus/uniphier-system-bus.c
 F:	drivers/i2c/busses/i2c-uniphier*
+F:	drivers/mfd/uniphier-mfd.c
 F:	drivers/mmc/host/uniphier-sd.c
 F:	drivers/pinctrl/uniphier/
 F:	drivers/tty/serial/8250/8250_uniphier.c
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index eea61e3..ea85862 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -892,6 +892,15 @@ config MFD_SKY81452
 	  This driver can also be built as a module.  If so, the module
 	  will be called sky81452.
 
+config MFD_UNIPHIER
+	tristate "Socionext UniPhier MFD"
+	depends on ARCH_UNIPHIER || COMPILE_TEST
+	default ARCH_UNIPHIER
+	select MFD_CORE
+	help
+	  Support for the System Control Block, Media I/O Control Block,
+	  Peripheral Control Block available on UniPhier SoCs.
+
 config MFD_SMSC
        bool "SMSC ECE1099 series chips"
        depends on I2C=y
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 5eaa6465d..5e8c20c 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -198,6 +198,7 @@ obj-$(CONFIG_MFD_HI6421_PMIC)	+= hi6421-pmic-core.o
 obj-$(CONFIG_MFD_DLN2)		+= dln2.o
 obj-$(CONFIG_MFD_RT5033)	+= rt5033.o
 obj-$(CONFIG_MFD_SKY81452)	+= sky81452.o
+obj-$(CONFIG_MFD_UNIPHIER)	+= uniphier-mfd.o
 
 intel-soc-pmic-objs		:= intel_soc_pmic_core.o intel_soc_pmic_crc.o
 intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC)	+= intel_soc_pmic_bxtwc.o
diff --git a/drivers/mfd/uniphier-mfd.c b/drivers/mfd/uniphier-mfd.c
new file mode 100644
index 0000000..7f01d64
--- /dev/null
+++ b/drivers/mfd/uniphier-mfd.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+static const struct mfd_cell uniphier_ld4_sysctrl_cells[] = {
+	{ .name = "uniphier-ld4-clk" },
+	{ .name = "uniphier-ld4-reset" },
+	{ /* sentinel */ }
+};
+
+static const struct mfd_cell uniphier_pro4_sysctrl_cells[] = {
+	{ .name = "uniphier-pro4-clk" },
+	{ .name = "uniphier-pro4-reset" },
+	{ /* sentinel */ }
+};
+
+static const struct mfd_cell uniphier_sld8_sysctrl_cells[] = {
+	{ .name = "uniphier-sld8-clk" },
+	{ .name = "uniphier-sld8-reset" },
+	{ /* sentinel */ }
+};
+
+static const struct mfd_cell uniphier_pro5_sysctrl_cells[] = {
+	{ .name = "uniphier-pro5-clk" },
+	{ .name = "uniphier-pro5-reset" },
+	{ /* sentinel */ }
+};
+
+static const struct mfd_cell uniphier_pxs2_sysctrl_cells[] = {
+	{ .name = "uniphier-pxs2-clk" },
+	{ .name = "uniphier-pxs2-reset" },
+	{ /* sentinel */ }
+};
+
+static const struct mfd_cell uniphier_ld11_sysctrl_cells[] = {
+	{ .name = "uniphier-ld11-clk" },
+	{ .name = "uniphier-ld11-reset" },
+	{ /* sentinel */ }
+};
+
+static const struct mfd_cell uniphier_ld20_sysctrl_cells[] = {
+	{ .name = "uniphier-ld20-clk" },
+	{ .name = "uniphier-ld20-reset" },
+	{ /* sentinel */ }
+};
+
+static const struct mfd_cell uniphier_ld4_mioctrl_cells[] = {
+	{ .name = "uniphier-ld4-mio-clk" },
+	{ .name = "uniphier-ld4-mio-reset" },
+	{ /* sentinel */ }
+};
+
+static const struct mfd_cell uniphier_pro5_mioctrl_cells[] = {
+	{ .name = "uniphier-pro5-mio-clk" },
+	{ .name = "uniphier-pro5-mio-reset" },
+	{ /* sentinel */ }
+};
+
+static const struct mfd_cell uniphier_ld4_perictrl_cells[] = {
+	{ .name = "uniphier-ld4-peri-clk" },
+	{ .name = "uniphier-ld4-peri-reset" },
+	{ /* sentinel */ }
+};
+
+static const struct mfd_cell uniphier_pro4_perictrl_cells[] = {
+	{ .name = "uniphier-pro4-peri-clk" },
+	{ .name = "uniphier-pro4-peri-reset" },
+	{ /* sentinel */ }
+};
+
+static const struct of_device_id uniphier_mfd_match[] = {
+	/* System Control */
+	{
+		.compatible = "socionext,uniphier-ld4-sysctrl",
+		.data = uniphier_ld4_sysctrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-pro4-sysctrl",
+		.data = uniphier_pro4_sysctrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-sld8-sysctrl",
+		.data = uniphier_sld8_sysctrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-pro5-sysctrl",
+		.data = uniphier_pro5_sysctrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-pxs2-sysctrl",
+		.data = uniphier_pxs2_sysctrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-ld11-sysctrl",
+		.data = uniphier_ld11_sysctrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-ld20-sysctrl",
+		.data = uniphier_ld20_sysctrl_cells,
+	},
+	/* Media I/O */
+	{
+		.compatible = "socionext,uniphier-ld4-mioctrl",
+		.data = uniphier_ld4_mioctrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-pro4-mioctrl",
+		.data = uniphier_ld4_mioctrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-sld8-mioctrl",
+		.data = uniphier_ld4_mioctrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-pro5-mioctrl",
+		.data = uniphier_pro5_mioctrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-pxs2-mioctrl",
+		.data = uniphier_pro5_mioctrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-ld11-mioctrl",
+		.data = uniphier_ld4_mioctrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-ld20-mioctrl",
+		.data = uniphier_pro5_mioctrl_cells,
+	},
+	/* Peripheral Control */
+	{
+		.compatible = "socionext,uniphier-ld4-perictrl",
+		.data = uniphier_ld4_perictrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-sld8-perictrl",
+		.data = uniphier_ld4_perictrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-pro4-perictrl",
+		.data = uniphier_pro4_perictrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-pro5-perictrl",
+		.data = uniphier_pro4_perictrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-pxs2-perictrl",
+		.data = uniphier_pro4_perictrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-ld11-perictrl",
+		.data = uniphier_pro4_perictrl_cells,
+	},
+	{
+		.compatible = "socionext,uniphier-ld20-perictrl",
+		.data = uniphier_pro4_perictrl_cells,
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, uniphier_mfd_match);
+
+static int uniphier_mfd_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	const struct mfd_cell *cell;
+	int ret;
+	int n_cells = 0;
+
+	match = of_match_node(uniphier_mfd_match, pdev->dev.of_node);
+	if (!match)
+		return -ENODEV;
+
+	cell = match->data;
+
+	for (; cell->name; cell++)
+		n_cells++;
+
+	ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, match->data,
+			      n_cells, NULL, 0, NULL);
+	if (ret)
+		dev_err(&pdev->dev, "failed to add MFD devices\n");
+
+	return ret;
+}
+
+static struct platform_driver uniphier_mfd_driver = {
+	.probe = uniphier_mfd_probe,
+	.driver = {
+		.name = "uniphier-mfd",
+		.of_match_table = uniphier_mfd_match,
+	},
+};
+module_platform_driver(uniphier_mfd_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier SoC MFD Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:51:01 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:51:01 +0900
Subject: [RFC PATCH 20/21] reset: uniphier: add reset driver for Media I/O
 block on UniPhier SoCs
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-21-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/reset/uniphier/Kconfig              |   4 ++
 drivers/reset/uniphier/Makefile             |   2 +
 drivers/reset/uniphier/reset-uniphier-mio.c | 106 ++++++++++++++++++++++++++++
 3 files changed, 112 insertions(+)
 create mode 100644 drivers/reset/uniphier/reset-uniphier-mio.c

diff --git a/drivers/reset/uniphier/Kconfig b/drivers/reset/uniphier/Kconfig
index 8509e71..a582938 100644
--- a/drivers/reset/uniphier/Kconfig
+++ b/drivers/reset/uniphier/Kconfig
@@ -34,4 +34,8 @@ config RESET_UNIPHIER_LD20
 	tristate "Reset driver for UniPhier PH1-LD20 SoC"
 	default ARM64
 
+config RESET_UNIPHIER_MIO
+	tristate "Reset driver for UniPhier Media I/O block"
+	default y
+
 endif
diff --git a/drivers/reset/uniphier/Makefile b/drivers/reset/uniphier/Makefile
index a33cb0a..e83bd14 100644
--- a/drivers/reset/uniphier/Makefile
+++ b/drivers/reset/uniphier/Makefile
@@ -7,3 +7,5 @@ obj-$(CONFIG_RESET_UNIPHIER_PRO5)	+= reset-uniphier-pro5.o
 obj-$(CONFIG_RESET_UNIPHIER_PXS2)	+= reset-uniphier-pxs2.o
 obj-$(CONFIG_RESET_UNIPHIER_LD11)	+= reset-uniphier-ld11.o
 obj-$(CONFIG_RESET_UNIPHIER_LD20)	+= reset-uniphier-ld20.o
+
+obj-$(CONFIG_RESET_UNIPHIER_MIO)	+= reset-uniphier-mio.o
diff --git a/drivers/reset/uniphier/reset-uniphier-mio.c b/drivers/reset/uniphier/reset-uniphier-mio.c
new file mode 100644
index 0000000..f68a8cf
--- /dev/null
+++ b/drivers/reset/uniphier/reset-uniphier-mio.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "reset-uniphier.h"
+
+#define UNIPHIER_MIO_RESET_SD(ch, index)		\
+	{						\
+		.id = (index),				\
+		.reg = 0x110 + 0x200 * (ch),		\
+		.mask = BIT(26) | BIT(0),		\
+		.deassert_val = BIT(26) | BIT(0),	\
+	}
+
+#define UNIPHIER_MIO_RESET_EMMC_HW_RESET(ch, index)	\
+	{						\
+		.id = (index),				\
+		.reg = 0x80 + 0x200 * (ch),		\
+		.mask = BIT(0),				\
+		.deassert_val = BIT(0),			\
+	}
+
+#define UNIPHIER_MIO_RESET_EHCI(ch, index)		\
+	{						\
+		.id = (index),				\
+		.reg = 0x110 + 0x200 * (ch),		\
+		.mask = BIT(24),			\
+		.deassert_val = BIT(24),		\
+	},						\
+	{						\
+		.id = (index),				\
+		.reg = 0x114 + 0x200 * (ch),		\
+		.mask = BIT(0),				\
+		.deassert_val = BIT(0),			\
+	}
+
+#define UNIPHIER_MIO_RESET_DMAC(index)			\
+	{						\
+		.id = (index),				\
+		.reg = 0x110,				\
+		.mask = BIT(17),			\
+		.deassert_val = BIT(17),		\
+	}
+
+static const struct uniphier_reset_data uniphier_ld4_mio_reset_data[] = {
+	UNIPHIER_MIO_RESET_SD(0, 0),
+	UNIPHIER_MIO_RESET_SD(1, 1),
+	UNIPHIER_MIO_RESET_SD(2, 2),
+	UNIPHIER_MIO_RESET_DMAC(3),
+	UNIPHIER_MIO_RESET_EHCI(0, 4),
+	UNIPHIER_MIO_RESET_EHCI(1, 5),
+	UNIPHIER_MIO_RESET_EHCI(2, 6),
+	UNIPHIER_MIO_RESET_EMMC_HW_RESET(1, 9),
+	{ .id = UNIPHIER_RESET_ID_END }
+};
+
+static int uniphier_ld4_mio_reset_probe(struct platform_device *pdev)
+{
+	return uniphier_reset_probe(pdev, uniphier_ld4_mio_reset_data);
+}
+
+static struct platform_driver uniphier_ld4_mio_reset_driver = {
+	.probe = uniphier_ld4_mio_reset_probe,
+	.driver = {
+		.name = "uniphier-ld4-mio-reset",
+	},
+};
+module_platform_driver(uniphier_ld4_mio_reset_driver);
+
+static const struct uniphier_reset_data uniphier_pro5_mio_reset_data[] = {
+	UNIPHIER_MIO_RESET_SD(0, 0),
+	UNIPHIER_MIO_RESET_SD(1, 1),
+	UNIPHIER_MIO_RESET_EMMC_HW_RESET(1, 9),
+	{ .id = UNIPHIER_RESET_ID_END }
+};
+
+static int uniphier_pro5_mio_reset_probe(struct platform_device *pdev)
+{
+	return uniphier_reset_probe(pdev, uniphier_pro5_mio_reset_data);
+}
+
+static struct platform_driver uniphier_pro5_mio_reset_driver = {
+	.probe = uniphier_pro5_mio_reset_probe,
+	.driver = {
+		.name = "uniphier-mio-reset",
+	},
+};
+module_platform_driver(uniphier_pro5_mio_reset_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier Media I/O Reset Controller Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:56 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:56 +0900
Subject: [RFC PATCH 15/21] reset: uniphier: add reset driver for UniPhier
 PH1-sLD8 SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-16-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/reset/uniphier/Kconfig               |  4 +++
 drivers/reset/uniphier/Makefile              |  1 +
 drivers/reset/uniphier/reset-uniphier-sld8.c | 46 ++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)
 create mode 100644 drivers/reset/uniphier/reset-uniphier-sld8.c

diff --git a/drivers/reset/uniphier/Kconfig b/drivers/reset/uniphier/Kconfig
index 1633093..307d563 100644
--- a/drivers/reset/uniphier/Kconfig
+++ b/drivers/reset/uniphier/Kconfig
@@ -14,4 +14,8 @@ config RESET_UNIPHIER_PRO4
 	tristate "Reset driver for UniPhier PH1-Pro4 SoC"
 	default ARM
 
+config RESET_UNIPHIER_SLD8
+	tristate "Reset driver for UniPhier PH1-sLD8 SoC"
+	default ARM
+
 endif
diff --git a/drivers/reset/uniphier/Makefile b/drivers/reset/uniphier/Makefile
index d496fe8..e1001c6 100644
--- a/drivers/reset/uniphier/Makefile
+++ b/drivers/reset/uniphier/Makefile
@@ -2,3 +2,4 @@ obj-y					+= reset-uniphier-core.o
 
 obj-$(CONFIG_RESET_UNIPHIER_LD4)	+= reset-uniphier-ld4.o
 obj-$(CONFIG_RESET_UNIPHIER_PRO4)	+= reset-uniphier-pro4.o
+obj-$(CONFIG_RESET_UNIPHIER_SLD8)	+= reset-uniphier-sld8.o
diff --git a/drivers/reset/uniphier/reset-uniphier-sld8.c b/drivers/reset/uniphier/reset-uniphier-sld8.c
new file mode 100644
index 0000000..736abd0
--- /dev/null
+++ b/drivers/reset/uniphier/reset-uniphier-sld8.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "reset-uniphier.h"
+
+static const struct uniphier_reset_data uniphier_sld8_reset_data[] = {
+	{
+		.id = 7,
+		.reg = 0x2000,
+		.mask = BIT(10),
+		.deassert_val = BIT(10),
+	},
+	{ .id = UNIPHIER_RESET_ID_END }
+};
+
+static int uniphier_sld8_reset_probe(struct platform_device *pdev)
+{
+	return uniphier_reset_probe(pdev, uniphier_sld8_reset_data);
+}
+
+static struct platform_driver uniphier_sld8_reset_driver = {
+	.probe = uniphier_sld8_reset_probe,
+	.driver = {
+		.name = "uniphier-sld8-reset",
+	},
+};
+module_platform_driver(uniphier_sld8_reset_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-sLD8 Reset Controller Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:51:00 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:51:00 +0900
Subject: [RFC PATCH 19/21] reset: uniphier: add reset driver for UniPhier
 PH1-LD20 SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-20-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/reset/uniphier/Kconfig               |  4 +++
 drivers/reset/uniphier/Makefile              |  1 +
 drivers/reset/uniphier/reset-uniphier-ld20.c | 46 ++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)
 create mode 100644 drivers/reset/uniphier/reset-uniphier-ld20.c

diff --git a/drivers/reset/uniphier/Kconfig b/drivers/reset/uniphier/Kconfig
index d9a2123..8509e71 100644
--- a/drivers/reset/uniphier/Kconfig
+++ b/drivers/reset/uniphier/Kconfig
@@ -30,4 +30,8 @@ config RESET_UNIPHIER_LD11
 	tristate "Reset driver for UniPhier PH1-LD11 SoC"
 	default ARM
 
+config RESET_UNIPHIER_LD20
+	tristate "Reset driver for UniPhier PH1-LD20 SoC"
+	default ARM64
+
 endif
diff --git a/drivers/reset/uniphier/Makefile b/drivers/reset/uniphier/Makefile
index f25f648..a33cb0a 100644
--- a/drivers/reset/uniphier/Makefile
+++ b/drivers/reset/uniphier/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_RESET_UNIPHIER_SLD8)	+= reset-uniphier-sld8.o
 obj-$(CONFIG_RESET_UNIPHIER_PRO5)	+= reset-uniphier-pro5.o
 obj-$(CONFIG_RESET_UNIPHIER_PXS2)	+= reset-uniphier-pxs2.o
 obj-$(CONFIG_RESET_UNIPHIER_LD11)	+= reset-uniphier-ld11.o
+obj-$(CONFIG_RESET_UNIPHIER_LD20)	+= reset-uniphier-ld20.o
diff --git a/drivers/reset/uniphier/reset-uniphier-ld20.c b/drivers/reset/uniphier/reset-uniphier-ld20.c
new file mode 100644
index 0000000..8edda31
--- /dev/null
+++ b/drivers/reset/uniphier/reset-uniphier-ld20.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "reset-uniphier.h"
+
+static const struct uniphier_reset_data uniphier_ld20_reset_data[] = {
+	{
+		.id = 7,
+		.reg = 0x200c,
+		.mask = BIT(8),
+		.deassert_val = BIT(8),
+	},
+	{ .id = UNIPHIER_RESET_ID_END }
+};
+
+static int uniphier_ld20_reset_probe(struct platform_device *pdev)
+{
+	return uniphier_reset_probe(pdev, uniphier_ld20_reset_data);
+}
+
+static struct platform_driver uniphier_ld20_reset_driver = {
+	.probe = uniphier_ld20_reset_probe,
+	.driver = {
+		.name = "uniphier-ld20-reset",
+	},
+};
+module_platform_driver(uniphier_ld20_reset_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-LD20 Reset Controller Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:55 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:55 +0900
Subject: [RFC PATCH 14/21] reset: uniphier: add reset driver for UniPhier
 PH1-Pro4 SoC
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-15-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/reset/uniphier/Kconfig               |  4 +++
 drivers/reset/uniphier/Makefile              |  1 +
 drivers/reset/uniphier/reset-uniphier-pro4.c | 46 ++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)
 create mode 100644 drivers/reset/uniphier/reset-uniphier-pro4.c

diff --git a/drivers/reset/uniphier/Kconfig b/drivers/reset/uniphier/Kconfig
index 875afd9..1633093 100644
--- a/drivers/reset/uniphier/Kconfig
+++ b/drivers/reset/uniphier/Kconfig
@@ -10,4 +10,8 @@ config RESET_UNIPHIER_LD4
 	tristate "Reset driver for UniPhier PH1-LD4 SoC"
 	default ARM
 
+config RESET_UNIPHIER_PRO4
+	tristate "Reset driver for UniPhier PH1-Pro4 SoC"
+	default ARM
+
 endif
diff --git a/drivers/reset/uniphier/Makefile b/drivers/reset/uniphier/Makefile
index c99a420..d496fe8 100644
--- a/drivers/reset/uniphier/Makefile
+++ b/drivers/reset/uniphier/Makefile
@@ -1,3 +1,4 @@
 obj-y					+= reset-uniphier-core.o
 
 obj-$(CONFIG_RESET_UNIPHIER_LD4)	+= reset-uniphier-ld4.o
+obj-$(CONFIG_RESET_UNIPHIER_PRO4)	+= reset-uniphier-pro4.o
diff --git a/drivers/reset/uniphier/reset-uniphier-pro4.c b/drivers/reset/uniphier/reset-uniphier-pro4.c
new file mode 100644
index 0000000..57ce253
--- /dev/null
+++ b/drivers/reset/uniphier/reset-uniphier-pro4.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+
+#include "reset-uniphier.h"
+
+static const struct uniphier_reset_data uniphier_pro4_reset_data[] = {
+	{
+		.id = 7,
+		.reg = 0x2000,
+		.mask = BIT(10),
+		.deassert_val = BIT(10),
+	},
+	{ .id = UNIPHIER_RESET_ID_END }
+};
+
+static int uniphier_pro4_reset_probe(struct platform_device *pdev)
+{
+	return uniphier_reset_probe(pdev, uniphier_pro4_reset_data);
+}
+
+static struct platform_driver uniphier_pro4_reset_driver = {
+	.probe = uniphier_pro4_reset_probe,
+	.driver = {
+		.name = "uniphier-pro4-reset",
+	},
+};
+module_platform_driver(uniphier_pro4_reset_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-Pro4 Reset Controller Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:41 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:41 +0900
Subject: [RFC PATCH 00/21] mfd, clock,
 reset: add UniPhier clock/reset driver support
Message-ID: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>


This series adds support for clock and reset (and MFD to populate them)
for UniPhier SoCs.

On UniPhier SoCs, one system control block contains various registers
for clock, reset, and others in it.

I consulted Arnd for better implementation for clock/reset drivers in such a case.
https://lkml.org/lkml/2016/4/18/605

After a while, I chose MFD approach and found it is a good fit in my case.

So, here I intentionally included clock, reset, MFD in one patch series
because they are related with one another.

I have not completed this series.  Some known problems are:
 - Binding document is missing
 - I need to fill clock/reset tables a bit more.

Please do not apply this series.

But, this sereis should be enough for reviewing
if my basic approach is OK or not.

Your feedback is appreciated.



Masahiro Yamada (21):
  mfd: uniphier: add UniPhier MFD driver
  clk: uniphier: add core support for UniPhier clock driver
  clk: uniphier: add clock driver for UniPhier PH1-LD4 SoC
  clk: uniphier: add clock driver for UniPhier PH1-Pro4 SoC
  clk: uniphier: add clock driver for UniPhier PH1-sLD8 SoC
  clk: uniphier: add clock driver for UniPhier PH1-Pro5 SoC
  clk: uniphier: add clock driver for UniPhier ProXstream2/PH1-LD6b SoC
  clk: uniphier: add clock driver for UniPhier PH1-LD11 SoC
  clk: uniphier: add clock driver for UniPhier PH1-LD20 SoC
  clk: uniphier: add clock driver for Media I/O block on UniPhier SoCs
  clk: uniphier: add clock driver for Peripheral block on UniPhier SoCs
  reset: uniphier: add core support for UniPhier reset driver
  reset: uniphier: add reset driver for UniPhier PH1-LD4 SoC
  reset: uniphier: add reset driver for UniPhier PH1-Pro4 SoC
  reset: uniphier: add reset driver for UniPhier PH1-sLD8 SoC
  reset: uniphier: add reset driver for UniPhier PH1-Pro5 SoC
  reset: uniphier: add reset driver for UniPhier ProXstream2/PH1-LD6b
    SoC
  reset: uniphier: add reset driver for UniPhier PH1-LD11 SoC
  reset: uniphier: add reset driver for UniPhier PH1-LD20 SoC
  reset: uniphier: add reset driver for Media I/O block on UniPhier SoCs
  reset: uniphier: add reset driver for Peripheral block on UniPhier
    SoCs

 MAINTAINERS                                      |   3 +
 drivers/clk/uniphier/Kconfig                     |  45 +++++
 drivers/clk/uniphier/Makefile                    |  16 ++
 drivers/clk/uniphier/clk-uniphier-core.c         |  99 +++++++++++
 drivers/clk/uniphier/clk-uniphier-fixed-factor.c |  50 ++++++
 drivers/clk/uniphier/clk-uniphier-fixed-rate.c   |  49 ++++++
 drivers/clk/uniphier/clk-uniphier-gate.c         |  98 +++++++++++
 drivers/clk/uniphier/clk-uniphier-ld11.c         |  83 +++++++++
 drivers/clk/uniphier/clk-uniphier-ld20.c         |  83 +++++++++
 drivers/clk/uniphier/clk-uniphier-ld4.c          | 112 ++++++++++++
 drivers/clk/uniphier/clk-uniphier-mio.c          | 215 +++++++++++++++++++++++
 drivers/clk/uniphier/clk-uniphier-mux.c          |  96 ++++++++++
 drivers/clk/uniphier/clk-uniphier-peri.c         | 133 ++++++++++++++
 drivers/clk/uniphier/clk-uniphier-pro4.c         | 112 ++++++++++++
 drivers/clk/uniphier/clk-uniphier-pro5.c         | 102 +++++++++++
 drivers/clk/uniphier/clk-uniphier-pxs2.c         |  83 +++++++++
 drivers/clk/uniphier/clk-uniphier-sld8.c         | 102 +++++++++++
 drivers/clk/uniphier/clk-uniphier.h              |  89 ++++++++++
 drivers/mfd/Kconfig                              |   9 +
 drivers/mfd/Makefile                             |   1 +
 drivers/mfd/uniphier-mfd.c                       | 214 ++++++++++++++++++++++
 drivers/reset/Kconfig                            |   1 +
 drivers/reset/Makefile                           |   1 +
 drivers/reset/uniphier/Kconfig                   |  45 +++++
 drivers/reset/uniphier/Makefile                  |  12 ++
 drivers/reset/uniphier/reset-uniphier-core.c     | 151 ++++++++++++++++
 drivers/reset/uniphier/reset-uniphier-ld11.c     |  46 +++++
 drivers/reset/uniphier/reset-uniphier-ld20.c     |  46 +++++
 drivers/reset/uniphier/reset-uniphier-ld4.c      |  46 +++++
 drivers/reset/uniphier/reset-uniphier-mio.c      | 106 +++++++++++
 drivers/reset/uniphier/reset-uniphier-peri.c     | 101 +++++++++++
 drivers/reset/uniphier/reset-uniphier-pro4.c     |  46 +++++
 drivers/reset/uniphier/reset-uniphier-pro5.c     |  46 +++++
 drivers/reset/uniphier/reset-uniphier-pxs2.c     |  46 +++++
 drivers/reset/uniphier/reset-uniphier-sld8.c     |  46 +++++
 drivers/reset/uniphier/reset-uniphier.h          |  33 ++++
 36 files changed, 2566 insertions(+)
 create mode 100644 drivers/clk/uniphier/Kconfig
 create mode 100644 drivers/clk/uniphier/Makefile
 create mode 100644 drivers/clk/uniphier/clk-uniphier-core.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-fixed-factor.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-fixed-rate.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-gate.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-ld11.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-ld20.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-ld4.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-mio.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-mux.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-peri.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-pro4.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-pro5.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-pxs2.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier-sld8.c
 create mode 100644 drivers/clk/uniphier/clk-uniphier.h
 create mode 100644 drivers/mfd/uniphier-mfd.c
 create mode 100644 drivers/reset/uniphier/Kconfig
 create mode 100644 drivers/reset/uniphier/Makefile
 create mode 100644 drivers/reset/uniphier/reset-uniphier-core.c
 create mode 100644 drivers/reset/uniphier/reset-uniphier-ld11.c
 create mode 100644 drivers/reset/uniphier/reset-uniphier-ld20.c
 create mode 100644 drivers/reset/uniphier/reset-uniphier-ld4.c
 create mode 100644 drivers/reset/uniphier/reset-uniphier-mio.c
 create mode 100644 drivers/reset/uniphier/reset-uniphier-peri.c
 create mode 100644 drivers/reset/uniphier/reset-uniphier-pro4.c
 create mode 100644 drivers/reset/uniphier/reset-uniphier-pro5.c
 create mode 100644 drivers/reset/uniphier/reset-uniphier-pxs2.c
 create mode 100644 drivers/reset/uniphier/reset-uniphier-sld8.c
 create mode 100644 drivers/reset/uniphier/reset-uniphier.h

-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:52 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:52 +0900
Subject: [RFC PATCH 11/21] clk: uniphier: add clock driver for Peripheral
 block on UniPhier SoCs
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-12-git-send-email-yamada.masahiro@socionext.com>

This series is just for review.
Please do not apply this patch.

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

 drivers/clk/uniphier/Kconfig             |   4 +
 drivers/clk/uniphier/Makefile            |   1 +
 drivers/clk/uniphier/clk-uniphier-peri.c | 133 +++++++++++++++++++++++++++++++
 3 files changed, 138 insertions(+)
 create mode 100644 drivers/clk/uniphier/clk-uniphier-peri.c

diff --git a/drivers/clk/uniphier/Kconfig b/drivers/clk/uniphier/Kconfig
index 895c4a0..08edaf8 100644
--- a/drivers/clk/uniphier/Kconfig
+++ b/drivers/clk/uniphier/Kconfig
@@ -38,4 +38,8 @@ config CLK_UNIPHIER_MIO
 	tristate "Clock driver for UniPhier Media I/O block"
 	default y
 
+config CLK_UNIPHIER_PERI
+	tristate "Clock driver for UniPhier Peripheral block"
+	default y
+
 endif
diff --git a/drivers/clk/uniphier/Makefile b/drivers/clk/uniphier/Makefile
index ae71f04..a69d6fe 100644
--- a/drivers/clk/uniphier/Makefile
+++ b/drivers/clk/uniphier/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_CLK_UNIPHIER_LD11)	+= clk-uniphier-ld11.o
 obj-$(CONFIG_CLK_UNIPHIER_LD20)	+= clk-uniphier-ld20.o
 
 obj-$(CONFIG_CLK_UNIPHIER_MIO)	+= clk-uniphier-mio.o
+obj-$(CONFIG_CLK_UNIPHIER_PERI)	+= clk-uniphier-peri.o
diff --git a/drivers/clk/uniphier/clk-uniphier-peri.c b/drivers/clk/uniphier/clk-uniphier-peri.c
new file mode 100644
index 0000000..e5510f5
--- /dev/null
+++ b/drivers/clk/uniphier/clk-uniphier-peri.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "clk-uniphier.h"
+
+#define UNIPHIER_PERI_CLK_UART(ch, index)			\
+	{							\
+		.name = "uart" #ch,				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = (index),			\
+		.data.gate = {					\
+			.parent_name = "uart",			\
+			.reg = 0x24,				\
+			.mask = BIT(19 + ch),			\
+			.enable_val = BIT(19 + ch),		\
+		},						\
+	}
+
+#define UNIPHIER_PERI_CLK_I2C_COMMON				\
+	{							\
+		.name = "i2c-common",				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = -1,				\
+		.data.gate = {					\
+			.parent_name = "i2c",			\
+			.reg = 0x20,				\
+			.mask = BIT(1),				\
+			.enable_val = BIT(1),			\
+		},						\
+	}
+
+#define UNIPHIER_PERI_CLK_I2C(ch, index)			\
+	{							\
+		.name = "i2c" #ch,				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = (index),			\
+		.data.gate = {					\
+			.parent_name = "i2c-common",		\
+			.reg = 0x24,				\
+			.mask = BIT(5 + ch),			\
+			.enable_val = BIT(5 + ch),		\
+		},						\
+	}
+
+#define UNIPHIER_PERI_CLK_FI2C(ch, index)			\
+	{							\
+		.name = "fi2c" #ch,				\
+		.type = UNIPHIER_CLK_TYPE_GATE,			\
+		.output_index = (index),			\
+		.data.gate = {					\
+			.parent_name = "fi2c",			\
+			.reg = 0x24,				\
+			.mask = BIT(24 + ch),			\
+			.enable_val = BIT(24 + ch),		\
+		},						\
+	}
+
+static const struct uniphier_clk_data uniphier_ld4_peri_clk_data[] = {
+	UNIPHIER_PERI_CLK_UART(0, 0),
+	UNIPHIER_PERI_CLK_UART(1, 1),
+	UNIPHIER_PERI_CLK_UART(2, 2),
+	UNIPHIER_PERI_CLK_UART(3, 3),
+	UNIPHIER_PERI_CLK_I2C_COMMON,
+	UNIPHIER_PERI_CLK_I2C(0, 4),
+	UNIPHIER_PERI_CLK_I2C(1, 5),
+	UNIPHIER_PERI_CLK_I2C(2, 6),
+	UNIPHIER_PERI_CLK_I2C(3, 7),
+	UNIPHIER_PERI_CLK_I2C(4, 8),
+	{ /* sentinel */ }
+};
+
+static int uniphier_ld4_peri_clk_probe(struct platform_device *pdev)
+{
+	return uniphier_clk_probe(pdev, uniphier_ld4_peri_clk_data);
+}
+
+static struct platform_driver uniphier_ld4_peri_clk_driver = {
+	.probe = uniphier_ld4_peri_clk_probe,
+	.remove = uniphier_clk_remove,
+	.driver = {
+		.name = "uniphier-ld4-peri-clk",
+	},
+};
+module_platform_driver(uniphier_ld4_peri_clk_driver);
+
+static const struct uniphier_clk_data uniphier_pro4_peri_clk_data[] = {
+	UNIPHIER_PERI_CLK_UART(0, 0),
+	UNIPHIER_PERI_CLK_UART(1, 1),
+	UNIPHIER_PERI_CLK_UART(2, 2),
+	UNIPHIER_PERI_CLK_UART(3, 3),
+	UNIPHIER_PERI_CLK_FI2C(0, 4),
+	UNIPHIER_PERI_CLK_FI2C(1, 5),
+	UNIPHIER_PERI_CLK_FI2C(2, 6),
+	UNIPHIER_PERI_CLK_FI2C(3, 7),
+	UNIPHIER_PERI_CLK_FI2C(4, 8),
+	UNIPHIER_PERI_CLK_FI2C(5, 9),
+	UNIPHIER_PERI_CLK_FI2C(6, 10),
+	{ /* sentinel */ }
+};
+
+static int uniphier_pro4_peri_clk_probe(struct platform_device *pdev)
+{
+	return uniphier_clk_probe(pdev, uniphier_pro4_peri_clk_data);
+}
+
+static struct platform_driver uniphier_pro4_peri_clk_driver = {
+	.probe = uniphier_pro4_peri_clk_probe,
+	.remove = uniphier_clk_remove,
+	.driver = {
+		.name = "uniphier-pro4-peri-clk",
+	},
+};
+module_platform_driver(uniphier_pro4_peri_clk_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier Peripheral Clock Driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 10 02:50:53 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 10 May 2016 18:50:53 +0900
Subject: [RFC PATCH 12/21] reset: uniphier: add core support for UniPhier
 reset driver
In-Reply-To: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462873862-30940-13-git-send-email-yamada.masahiro@socionext.com>

The core support for UniPhier reset drivers.

On UniPhier SoCs, registers for clock, reset, and other system
controlling are mixed in one hardware block.  It is difficult
to have one independent reset node.
So, I chose to use MFD from which clocks and resets (and
power in the future) are populated.

This series is just for review.
Please do not apply this patch.

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

 MAINTAINERS                                  |   1 +
 drivers/reset/Kconfig                        |   1 +
 drivers/reset/Makefile                       |   1 +
 drivers/reset/uniphier/Kconfig               |   9 ++
 drivers/reset/uniphier/Makefile              |   1 +
 drivers/reset/uniphier/reset-uniphier-core.c | 151 +++++++++++++++++++++++++++
 drivers/reset/uniphier/reset-uniphier.h      |  33 ++++++
 7 files changed, 197 insertions(+)
 create mode 100644 drivers/reset/uniphier/Kconfig
 create mode 100644 drivers/reset/uniphier/Makefile
 create mode 100644 drivers/reset/uniphier/reset-uniphier-core.c
 create mode 100644 drivers/reset/uniphier/reset-uniphier.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 38c6bb5..95a4030 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1732,6 +1732,7 @@ F:	drivers/i2c/busses/i2c-uniphier*
 F:	drivers/mfd/uniphier-mfd.c
 F:	drivers/mmc/host/uniphier-sd.c
 F:	drivers/pinctrl/uniphier/
+F:	drivers/reset/uniphier/
 F:	drivers/tty/serial/8250/8250_uniphier.c
 N:	uniphier
 
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 6a0b24b..f7e5381 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -16,5 +16,6 @@ if RESET_CONTROLLER
 
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
+source "drivers/reset/uniphier/Kconfig"
 
 endif
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index a1fc8ed..e2bb8c6 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -6,5 +6,6 @@ obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o
 obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_HISI) += hisilicon/
+obj-$(CONFIG_RESET_UNIPHIER) += uniphier/
 obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
 obj-$(CONFIG_ATH79) += reset-ath79.o
diff --git a/drivers/reset/uniphier/Kconfig b/drivers/reset/uniphier/Kconfig
new file mode 100644
index 0000000..e82f7a7
--- /dev/null
+++ b/drivers/reset/uniphier/Kconfig
@@ -0,0 +1,9 @@
+menuconfig RESET_UNIPHIER
+	bool "Reset drivers for UniPhier SoCs"
+	depends on (ARCH_UNIPHIER && MFD_UNIPHIER) || COMPILE_TEST
+	depends on OF && MFD_CORE && MFD_SYSCON
+	default ARCH_UNIPHIER && MFD_UNIPHIER
+
+if RESET_UNIPHIER
+
+endif
diff --git a/drivers/reset/uniphier/Makefile b/drivers/reset/uniphier/Makefile
new file mode 100644
index 0000000..ba660bc
--- /dev/null
+++ b/drivers/reset/uniphier/Makefile
@@ -0,0 +1 @@
+obj-y					+= reset-uniphier-core.o
diff --git a/drivers/reset/uniphier/reset-uniphier-core.c b/drivers/reset/uniphier/reset-uniphier-core.c
new file mode 100644
index 0000000..95217d5
--- /dev/null
+++ b/drivers/reset/uniphier/reset-uniphier-core.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include "reset-uniphier.h"
+
+struct uniphier_reset_priv {
+	struct reset_controller_dev rcdev;
+	struct device *dev;
+	struct regmap *regmap;
+	const struct uniphier_reset_data *data;
+	unsigned int nr_ids;
+};
+
+#define to_uniphier_reset_priv(_rcdev) \
+			container_of(_rcdev, struct uniphier_reset_priv, rcdev)
+
+static int uniphier_reset_update(struct reset_controller_dev *rcdev,
+				 unsigned long id, bool assert)
+{
+	struct uniphier_reset_priv *priv = to_uniphier_reset_priv(rcdev);
+	const struct uniphier_reset_data *p;
+	bool handled = false;
+
+	for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) {
+		unsigned int val;
+		int ret;
+
+		if (p->id != id)
+			continue;
+
+		val = p->deassert_val;
+		if (assert)
+			val = ~val;
+
+		ret = regmap_write_bits(priv->regmap, p->reg, p->mask, val);
+		if (ret)
+			return ret;
+
+		handled = true;
+	}
+
+	if (!handled) {
+		dev_err(priv->dev, "reset_id=%lu was not handled\n", id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int uniphier_reset_assert(struct reset_controller_dev *rcdev,
+				 unsigned long id)
+{
+	return uniphier_reset_update(rcdev, id, true);
+}
+
+static int uniphier_reset_deassert(struct reset_controller_dev *rcdev,
+				   unsigned long id)
+{
+	return uniphier_reset_update(rcdev, id, false);
+}
+
+static int uniphier_reset_status(struct reset_controller_dev *rcdev,
+				 unsigned long id)
+{
+	struct uniphier_reset_priv *priv = to_uniphier_reset_priv(rcdev);
+	const struct uniphier_reset_data *p;
+	bool handled = false;
+
+	for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) {
+		unsigned int val;
+		int ret;
+
+		if (p->id != id)
+			continue;
+
+		ret = regmap_read(priv->regmap, p->reg, &val);
+		if (ret)
+			return ret;
+
+		if ((val & p->mask) != p->deassert_val)
+			return 1;
+
+		handled = true;
+	}
+
+	if (!handled) {
+		dev_err(priv->dev, "reset_id=%lu was not found\n", id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct reset_control_ops uniphier_reset_ops = {
+	.assert = uniphier_reset_assert,
+	.deassert = uniphier_reset_deassert,
+	.status = uniphier_reset_status,
+};
+
+int uniphier_reset_probe(struct platform_device *pdev,
+			 const struct uniphier_reset_data *data)
+{
+	struct device *dev = &pdev->dev;
+	struct uniphier_reset_priv *priv;
+	const struct uniphier_reset_data *p;
+	struct regmap *regmap;
+	unsigned int nr_resets = 0;
+
+	/* parent should be MFD and syscon node */
+	regmap = syscon_node_to_regmap(dev->parent->of_node);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "failed to get regmap\n");
+		return PTR_ERR(regmap);
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	for (p = data; p->id != UNIPHIER_RESET_ID_END; p++)
+		nr_resets = max(nr_resets, p->id + 1);
+
+	priv->rcdev.ops = &uniphier_reset_ops;
+	priv->rcdev.owner = dev->driver->owner;
+	priv->rcdev.of_node = dev->parent->of_node;
+	priv->rcdev.nr_resets = nr_resets;
+	priv->dev = dev;
+	priv->regmap = regmap;
+	priv->data = data;
+
+	return devm_reset_controller_register(&pdev->dev, &priv->rcdev);
+}
+EXPORT_SYMBOL_GPL(uniphier_reset_probe);
diff --git a/drivers/reset/uniphier/reset-uniphier.h b/drivers/reset/uniphier/reset-uniphier.h
new file mode 100644
index 0000000..1b26efd
--- /dev/null
+++ b/drivers/reset/uniphier/reset-uniphier.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __RESET_UNIPHIER_H__
+#define __RESET_UNIPHIER_H__
+
+struct platform_device;
+
+struct uniphier_reset_data {
+	unsigned int id;
+	unsigned int reg;
+	unsigned int mask;
+	unsigned int deassert_val;
+};
+
+#define UNIPHIER_RESET_ID_END		(unsigned int)(-1)
+
+int uniphier_reset_probe(struct platform_device *pdev,
+			 const struct uniphier_reset_data *data);
+
+#endif /* __RESET_UNIPHIER_H__ */
-- 
1.9.1



From eric.auger at linaro.org  Tue May 10 02:52:23 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 11:52:23 +0200
Subject: [PATCH v3 11/55] KVM: arm/arm64: pmu: abstract access to number
 of SPIs
In-Reply-To: <1462531568-9799-12-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-12-git-send-email-andre.przywara@arm.com>
Message-ID: <5731AF57.2040707@linaro.org>

Hi Andre,
On 05/06/2016 12:45 PM, Andre Przywara wrote:
> Currently the PMU uses a member of the struct vgic_dist directly,
> which not only breaks abstraction, but will fail with the new VGIC.
> Abstract this access in the VGIC header file.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  include/kvm/arm_vgic.h | 2 ++
>  virt/kvm/arm/pmu.c     | 2 +-
>  2 files changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 452bb85..c14ff77 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -347,6 +347,8 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
>  #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
>  #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
>  #define vgic_ready(k)		((k)->arch.vgic.ready)
> +#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
> +				 ((i) < (k)->arch.vgic.nr_irqs))
>  
>  int vgic_v2_probe(struct device_node *vgic_node,
>  		  const struct vgic_ops **ops,
> diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
> index 575c7aa..bd2e872 100644
> --- a/virt/kvm/arm/pmu.c
> +++ b/virt/kvm/arm/pmu.c
> @@ -477,7 +477,7 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
>  		 * the interrupt number is the same for all vcpus, while as an
>  		 * SPI it must be a separate number per vcpu.
>  		 */
> -		if (irq < VGIC_NR_SGIS || irq >= vcpu->kvm->arch.vgic.nr_irqs ||
> +		if (irq < VGIC_NR_SGIS || !vgic_valid_spi(vcpu->kvm, irq) ||
>  		    !irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
>  			return -EINVAL;
>  
> 
in case this is a PPI it will now return an error, right? I don't think
this is what we expect.

Cheers

Eric



From romain.izard.pro at gmail.com  Tue May 10 02:59:29 2016
From: romain.izard.pro at gmail.com (Romain Izard)
Date: Tue, 10 May 2016 11:59:29 +0200
Subject: [PATCH 1/2] Revert "mtd: atmel_nand: Support variable RB_EDGE
 interrupts"
In-Reply-To: <20160510105549.50b60d8c@bbrezillon>
References: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
 <1462776680-5284-2-git-send-email-wenyou.yang@atmel.com>
 <20160510105549.50b60d8c@bbrezillon>
Message-ID: <CAGkQfmPm16sgizhWJEH8onHR+4hC2an9m1k8=AqoNjsK3EeU3Q@mail.gmail.com>

Hi Boris,

2016-05-10 10:55 GMT+02:00 Boris Brezillon <boris.brezillon at free-electrons.com>:
>
> Romain, I thought you had a real use case on sama5d4 where this patch
> was needed to make the whole thing work. Not sure why you submitted
> this patch if you couldn't test it on a real board.

My target CPU is SAMA5D2, but I chose the SAMA5D4 for the compatible
string as it was the earliest design whose datasheet mentioned the
RB_EDGE3 bit.

I wrote the SAMA5D2 support in advance, as I was waiting for my board to
be ready, basing myself on what was found in the datasheet.  The changes
included both the variable RB_EDGE support, and the PMECC register
layout changes, which were a prerequisite to use the SAMA5D2 NAND
controller.

I tested the code against regressions on sama5d3xek, and Wenyou reported
that he tested it on Atmel's SAMA5D2 PTC, which was the only existing
board at that time with both a SAMA5D2 SoC and a NAND chip.
Unfortunately, as the bug is only seen when writing on the flash, and it
only affects the speed of the device, he did not notice it.

I sent the patches early because I expected the submission process to
be long, and I wanted to be able to freeze the kernel version to be used
on my board as soon as possible.

Best regards,
-- 
Romain Izard


From marc.zyngier at arm.com  Tue May 10 03:04:12 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 11:04:12 +0100
Subject: [PATCH v3 11/55] KVM: arm/arm64: pmu: abstract access to number
 of SPIs
In-Reply-To: <5731AF57.2040707@linaro.org>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-12-git-send-email-andre.przywara@arm.com>
 <5731AF57.2040707@linaro.org>
Message-ID: <5731B21C.9030205@arm.com>

On 10/05/16 10:52, Eric Auger wrote:
> Hi Andre,
> On 05/06/2016 12:45 PM, Andre Przywara wrote:
>> Currently the PMU uses a member of the struct vgic_dist directly,
>> which not only breaks abstraction, but will fail with the new VGIC.
>> Abstract this access in the VGIC header file.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>>  include/kvm/arm_vgic.h | 2 ++
>>  virt/kvm/arm/pmu.c     | 2 +-
>>  2 files changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
>> index 452bb85..c14ff77 100644
>> --- a/include/kvm/arm_vgic.h
>> +++ b/include/kvm/arm_vgic.h
>> @@ -347,6 +347,8 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
>>  #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
>>  #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
>>  #define vgic_ready(k)		((k)->arch.vgic.ready)
>> +#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
>> +				 ((i) < (k)->arch.vgic.nr_irqs))
>>  
>>  int vgic_v2_probe(struct device_node *vgic_node,
>>  		  const struct vgic_ops **ops,
>> diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
>> index 575c7aa..bd2e872 100644
>> --- a/virt/kvm/arm/pmu.c
>> +++ b/virt/kvm/arm/pmu.c
>> @@ -477,7 +477,7 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
>>  		 * the interrupt number is the same for all vcpus, while as an
>>  		 * SPI it must be a separate number per vcpu.
>>  		 */
>> -		if (irq < VGIC_NR_SGIS || irq >= vcpu->kvm->arch.vgic.nr_irqs ||
>> +		if (irq < VGIC_NR_SGIS || !vgic_valid_spi(vcpu->kvm, irq) ||
>>  		    !irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
>>  			return -EINVAL;
>>  
>>
> in case this is a PPI it will now return an error, right? I don't think
> this is what we expect.

Ouch. Good catch. I missed the ! too...

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From tomi.valkeinen at ti.com  Tue May 10 03:06:56 2016
From: tomi.valkeinen at ti.com (Tomi Valkeinen)
Date: Tue, 10 May 2016 13:06:56 +0300
Subject: [PATCH v2 0/3] video: fbdev: imxfb: make it work again
In-Reply-To: <20160510090547.GQ30822@pengutronix.de>
References: <1462354998-5792-1-git-send-email-u.kleine-koenig@pengutronix.de>
 <5731A02A.2070309@ti.com> <20160510090547.GQ30822@pengutronix.de>
Message-ID: <5731B2C0.3040404@ti.com>



On 10/05/16 12:05, Uwe Kleine-K?nig wrote:
> Hello Tomi,
> 
> On Tue, May 10, 2016 at 11:47:38AM +0300, Tomi Valkeinen wrote:
>> On 04/05/16 12:43, Uwe Kleine-K?nig wrote:
>>> this is v2 of the series which addresses the review comments I got vor
>>> (implicit) v1.
>>>
>>> For patch 2 the question is still open if this is the right fix, but
>>> without this the display doesn't stay on. Patches 1 and 3 should be
>>> applicable independant of patch 2.
>>
>> I picked patches 1 and 3, they look fine.
> 
> Thanks.
> 
>> I still think patch 2 is just broken, it doesn't make sense to me.
> 
> What do you think should happen during startup? Something should call
> the set_power callback to enable the device? Or should that only happen
> when something writes to /dev/fb0?

I think the panel should be enabled at startup, as with fbdev there's no
specific enable call. So I don't have a problem with enabling the panel
at startup, but just that the regulator enables/disables don't seem to
match.

>> If the regulator is enabled in probe, then it's always on, and
>> imxfb_lcd_set_power() should be removed as it never has any effect. But
>> that doesn't sound correct, as presumably the imxfb_lcd_set_power() has
>> worked at some point.
> 
> I think it worked back when unused regulators were not disabled during
> boot.

Is imxfb_lcd_set_power() ever called, or just not at startup? If it is
called properly later, then perhaps you just need to kick it at startup
time to enable it. Maybe imxfb_lcd_set_power(lcd, FB_BLANK_UNBLANK);

Did you try unloading the module (both when the LCD is enabled and when
it's disabled), and seeing that the regulator gets disabled when you
unload it?

 Tomi

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160510/8144c3b2/attachment.sig>

From lorenzo.pieralisi at arm.com  Tue May 10 03:07:28 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Tue, 10 May 2016 11:07:28 +0100
Subject: [PATCH V6 01/13] pci, acpi, x86, ia64: Move ACPI host bridge
 device companion assignment to core code.
In-Reply-To: <20160510015336.GA29582@localhost>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <1460740008-19489-2-git-send-email-tn@semihalf.com>
 <292578579.uIxhMjkdfG@vostro.rjw.lan>
 <20160510015336.GA29582@localhost>
Message-ID: <20160510100728.GA15552@red-moon>

On Mon, May 09, 2016 at 08:53:36PM -0500, Bjorn Helgaas wrote:
> On Tue, May 10, 2016 at 12:56:37AM +0200, Rafael J. Wysocki wrote:
> > On Friday, April 15, 2016 07:06:36 PM Tomasz Nowicki wrote:
> > > Currently we have two platforms (x86 & ia64) capable of PCI ACPI host
> > > bridge initialization. They both use arch-specific sysdata to pass down
> > > parent device reference and both rely on NULL parent in pci_create_root_bus()
> > > to validate sysdata content.
> > 
> > No, this is not relied on for that.  It is just NULL, because we don't
> > have a physical parent device representation for the PCI host bridge.
> > 
> > > It looks hacky and prevents us from getting some firmware specific
> > > info for PCI host controller based on its acpi_device structure
> > > in generic pci_create_root_bus() function.
> > 
> > You can't get that info without adding ACPI-specific code to that function
> > anyway.
> > 
> > > However, we overcome that blocker by passing down parent device via
> > > pci_create_root_bus parameter (as the ACPI device type).
> > 
> > Which is completely wrong.
> > 
> > > Then we use ACPI_COMPANION_SET in core code
> > > for ACPI boot method only. ACPI_COMPANION_SET is safe to run for all
> > > cases DT, ACPI and DT&ACPI.
> > > 
> > > Since now PCI core code is setting ACPI companion device for us,
> > > x86 & ia64 specific ACPI companion device setting turns out to be dead now.
> > > We can get rid of it, including related companion reference from
> > > PCI sysdata structure. Aslo, PCI_CONTROLLER macro cannot return valid
> > > companion device anymore. Therefore we need to convert its usage to
> > > ACPI_COMPANION.
> 
> I think getting rid of arch-specific sysdata is a good goal (at least
> for things like the domain and ACPI companion that are really not
> arch-specific).
> 
> But I'm afraid I've been guilty of allowing the perfect to be the
> enemy of the good.  I think it will be more useful in the end if we
> can get as much of this work in v4.7 as possible, even if there's more
> polishing we'd like to do later.
> 
> What if we keep the x86 and ia64 handling of ACPI_COMPANION the way it
> is today, and do it the same way for arm64?  Then later, after we
> merge Arnd's work to make a generic pci_register_host() or similar, I
> suspect we might be able to unify the ACPI_COMPANION stuff more
> easily.  If the driver (acpi/pci_root.c) allocates the struct
> pci_host_bridge, then maybe it will be able to fill in the domain and
> set up the ACPI_COMPANION before it calls the scan interface.

Ok, JC already solved that problem like this:

http://www.spinics.net/lists/arm-kernel/msg478167.html
http://www.spinics.net/lists/arm-kernel/msg478169.html

Since ARM64 relies on PCI_DOMAINS_GENERIC (DT) I do not see any other
way of pulling it off quickly (and in a really generic way), sysdata
is the only way of handling it in ACPI unless we start clutching
at straws (which we already did with the ACPI companion hacks).

Thanks,
Lorenzo


From suzuki.poulose at arm.com  Tue May 10 03:14:41 2016
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 10 May 2016 11:14:41 +0100
Subject: [PATCH] arm64: secondary_start_kernel: Remove unnecessary barrier
Message-ID: <1462875281-5063-1-git-send-email-suzuki.poulose@arm.com>

Remove the unnecessary smp_wmb(), which was added to make sure
that the update_cpu_boot_status() completes before we mark the
CPU online. But update_cpu_boot_status() already has dsb() (required
for the failing CPUs) to ensure the correct behavior.

Cc: Will Deacon <will.deacon at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Dennis Chen <dennis.chen at arm.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm64/kernel/smp.c |    2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index b2d5f4e..ec040a8 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -225,8 +225,6 @@ asmlinkage void secondary_start_kernel(void)
 	pr_info("CPU%u: Booted secondary processor [%08x]\n",
 					 cpu, read_cpuid_id());
 	update_cpu_boot_status(CPU_BOOT_SUCCESS);
-	/* Make sure the status update is visible before we complete */
-	smp_wmb();
 	set_cpu_online(cpu, true);
 	complete(&cpu_running);
 
-- 
1.7.9.5



From daniel.lezcano at linaro.org  Tue May 10 03:22:06 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 10 May 2016 12:22:06 +0200
Subject: [PATCH 0/4] clocksource: Add support for Aspeed timer
In-Reply-To: <1462797169-14512-1-git-send-email-joel@jms.id.au>
References: <1462797169-14512-1-git-send-email-joel@jms.id.au>
Message-ID: <20160510102206.GD14952@linaro.org>

On Mon, May 09, 2016 at 10:02:45PM +0930, Joel Stanley wrote:
> Hello All,
> 
> This adds support for the Aspeed ast2400 and ast2500 families of BMC SoCs to
> the moxart driver.
> 
> I've addressed the feedback from Daniel and spent a bit of time trying to
> ensure the series makes sense.
> 
> I've not included a patch that renames the driver to fttmr010, from Faraday
> Tech, as I wasn't sure if we had consensus. If you would prefer I do so then
> let me know.
> 
> Cheers,
> 
> Joel
> 
> Joel Stanley (4):
>   drivers/clocksouree/moxart: Add kbuild symbol
>   drivers/clocksource/moxart: Refactor enable/disable
>   drivers/clocksource/moxart: Use struct to hold state
>   drivers/clocksource/moxart: Add Aspeed support
> 
>  .../bindings/timer/moxa,moxart-timer.txt           |   4 +-
>  arch/arm/mach-moxart/Kconfig                       |   2 +-
>  drivers/clocksource/Kconfig                        |   9 +
>  drivers/clocksource/Makefile                       |   2 +-
>  drivers/clocksource/moxart_timer.c                 | 191 ++++++++++++++-------
>  5 files changed, 143 insertions(+), 65 deletions(-)

The changes look ok. Could you please reply to patch 2 with a changelog I 
can add.

Thanks.

  -- Daniel


From marc.zyngier at arm.com  Tue May 10 03:22:24 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 11:22:24 +0100
Subject: [PATCH v3 20/55] KVM: arm/arm64: vgic-new: Implement
 kvm_vgic_vcpu_pending_irq
In-Reply-To: <1462531568-9799-21-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-21-git-send-email-andre.przywara@arm.com>
Message-ID: <5731B660.4030400@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> Tell KVM whether a particular VCPU has an IRQ that needs handling
> in the guest. This is used to decide whether a VCPU is runnable.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...


From lorenzo.pieralisi at arm.com  Tue May 10 03:27:21 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Tue, 10 May 2016 11:27:21 +0100
Subject: [PATCH V6 01/13] pci, acpi, x86, ia64: Move ACPI host bridge
 device companion assignment to core code.
In-Reply-To: <8183907.bBqvG1yEkP@vostro.rjw.lan>
References: <1460740008-19489-1-git-send-email-tn@semihalf.com>
 <20160427024537.GH6789@localhost> <5729AE92.2090106@semihalf.com>
 <8183907.bBqvG1yEkP@vostro.rjw.lan>
Message-ID: <20160510102721.GB15552@red-moon>

On Tue, May 10, 2016 at 12:18:59AM +0200, Rafael J. Wysocki wrote:

[...]

> > >> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> > >> index ae3fe4e..4581e0e 100644
> > >> --- a/drivers/acpi/pci_root.c
> > >> +++ b/drivers/acpi/pci_root.c
> > >> @@ -564,6 +564,11 @@ static int acpi_pci_root_add(struct acpi_device *device,
> > >>   		}
> > >>   	}
> > >>
> > >> +	/*
> > >> +	 * pci_create_root_bus() needs to detect the parent device type,
> > >> +	 * so initialize its companion data accordingly.
> > >> +	 */
> > >> +	ACPI_COMPANION_SET(&device->dev, device);
> > >>   	root->device = device;
> > >>   	root->segment = segment & 0xFFFF;
> > >>   	strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
> > >> @@ -846,7 +851,7 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
> > >>
> > >>   	pci_acpi_root_add_resources(info);
> > >>   	pci_add_resource(&info->resources, &root->secondary);
> > >> -	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
> > >> +	bus = pci_create_root_bus(&device->dev, busnum, ops->pci_ops,
> > >>   				  sysdata, &info->resources);
> > >
> > > "device" here is a struct acpi_device *.  Rafael, is that the right
> > > thing to do?  I dimly recall proposing something similar long ago and
> > > that it turned out to be a bad idea.
> > >
> > 
> > Joining Bjorn's question. Rafael, do you recall what was the issue here 
> > from the past?
> 
> Yes, I do.
> 
> Anything struct acpi_device doesn't represent a real device.  It
> represents a firmware object that can be associated with a device.
> IOW, nothing under LNXSYSTM\:00/ should ever be used as the parent or
> sibling etc with respect to anything outside of that directory.  In
> fact, the entire LNXSYSTM\:00/ should be located under
> /sys/firmware/acpi/ and it was a mistake to put it under
> /sys/devices/.
> 
> One immediate consequence of the above change, AFAICS, would be that
> the whole PCI hierarchy would now hang under
> /sys/devices/LNXSYSTM\:00/LNXSYBUS\:00/PNP0A08\:00/ which would not
> make any sense whatever, because
> /sys/devices/LNXSYSTM\:00/LNXSYBUS\:00/PNP0A08\:00/physical_node
> already points to /sys/devices/pci0000\:00/.
> 
> IOW, both PNP0A08\:00/ and pci0000\:00/ already represent the same
> thing, ie. the host bridge.
> 
> If you want to have a parent for pci0000\:00/, you need a
> physical_node for LNXSYBUS\:00 and point to that as the parent from
> pci0000\:00/.  That at least will lead to a sysfs hierarchy that makes
> sense, although it may break user space tools I suppose (which may be
> assuming that pci0000\:00/ will always be present directly under
> /sys/devices/).

Ok, I have a question though. As an example, DT based host controllers
(that pass the parent pointer to pci_create_root_bus()), are already
rooted at the respective host controller platform device sysfs path, so
if user space can't cope with that, that is a problem *now* on some
systems unless I am missing something.

Anyway, thanks for clarifying the companion handling mechanism, we
decidedly have to find a proper way to handle it instead of working
around it.

Lorenzo


From marc.zyngier at arm.com  Tue May 10 03:28:26 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 11:28:26 +0100
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
Message-ID: <5731B7CA.5090308@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> As the enable register handlers are shared between the v2 and v3
> emulation, their implementation goes into vgic-mmio.c, to be easily
> referenced from the v3 emulation as well later.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...


From will.deacon at arm.com  Tue May 10 03:28:38 2016
From: will.deacon at arm.com (Will Deacon)
Date: Tue, 10 May 2016 11:28:38 +0100
Subject: [PATCH] arm64: kgdb: Match pstate size with gdbserver protocol
In-Reply-To: <1462815566-15086-1-git-send-email-daniel.thompson@linaro.org>
References: <1462815566-15086-1-git-send-email-daniel.thompson@linaro.org>
Message-ID: <20160510102838.GF22813@arm.com>

Hi Daniel,

So does kgdb do something useful after this patch?

On Mon, May 09, 2016 at 06:39:26PM +0100, Daniel Thompson wrote:
> Current versions of gdb do not interoperate cleanly with kgdb on arm64
> systems because gdb and kgdb do not use the same register description.
> This patch modifies kgdb to work with recent releases of gdb (>= 7.8.1).
> 
> Compatibility with gdb (after the patch is applied) is as follows:
> 
>   gdb-7.6 and earlier  Ok
>   gdb-7.7 series       Works if user provides custom target description
>   gdb-7.8(.0)          Works if user provides custom target description
>   gdb-7.8.1 and later  Ok
> 
> When commit 44679a4f142b ("arm64: KGDB: Add step debugging support") was
> introduced it was paired with a gdb patch that made an incompatible
> change to the gdbserver protocol. This patch was eventually merged into
> the gdb sources:
> https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=a4d9ba85ec5597a6a556afe26b712e878374b9dd
> 
> The change to the protocol was mostly made to simplify big-endian support
> inside the kernel gdb stub. Unfortunately the gdb project released
> gdb-7.7.x and gdb-7.8.0 before the protocol incompatibility was identified
> and reversed:
> https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=bdc144174bcb11e808b4e73089b850cf9620a7ee
> 
> This leaves us in a position where kgdb still uses the no-longer-used
> protocol; gdb-7.8.1, which restored the original behaviour,If was
> released on 2014-10-29.
> 
> I don't believe it is possible to detect/correct the protocol
> incompatiblity which means the kernel must take a view about which
> version of the gdb remote protocol is "correct". This patch takes the
> view that the original/current version of the protocol is correct
> and that version found in gdb-7.7.x and gdb-7.8.0 is anomalous.

Urgh, this is filthy! Still, without a time machine, I guess there's
little we can do about it. Can I ask you to respin the patch but with
the rationale as a comment in the header file, and a pointer to the
comment from the C code too, please?

The code looks incorrect after this change, so we should justify how
we've ended up in this state and not everybody looks at the git log
for that rationale.

Cheers,

Will


From ulf.hansson at linaro.org  Tue May 10 03:28:39 2016
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Tue, 10 May 2016 12:28:39 +0200
Subject: [PATCH] mmc: sdhci-st: correct name of sd-uhs-sdr50 property
In-Reply-To: <1462839264-13300-1-git-send-email-horms+renesas@verge.net.au>
References: <1462839264-13300-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <CAPDyKFovKxGDnnyKAWjpjTN=7XB5sbTe+gyh2OTSRQ=bmnJTFQ@mail.gmail.com>

On 10 May 2016 at 02:14, Simon Horman <horms+renesas at verge.net.au> wrote:
> Correct what appears to be a typo in the name of the sd-uhs-sdr50.
>
> Also fix mixed tab/space indentation.
>
> Signed-off-by: Simon Horman <horms+renesas at verge.net.au>

Thanks, applied for next!

Kind regards
Uffe

> ---
>  Documentation/devicetree/bindings/mmc/sdhci-st.txt | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/mmc/sdhci-st.txt b/Documentation/devicetree/bindings/mmc/sdhci-st.txt
> index 18d950df2749..88faa91125bf 100644
> --- a/Documentation/devicetree/bindings/mmc/sdhci-st.txt
> +++ b/Documentation/devicetree/bindings/mmc/sdhci-st.txt
> @@ -38,7 +38,7 @@ Optional properties:
>  - bus-width:           Number of data lines.
>                         See:  Documentation/devicetree/bindings/mmc/mmc.txt.
>
> -- max-frequency:       Can be 200MHz, 100Mz or 50MHz (default) and used for
> +- max-frequency:       Can be 200MHz, 100Mz or 50MHz (default) and used for
>                         configuring the CCONFIG3 in the mmcss.
>                         See:  Documentation/devicetree/bindings/mmc/mmc.txt.
>
> @@ -48,7 +48,7 @@ Optional properties:
>  - vqmmc-supply:                Phandle to the regulator dt node, mentioned as the vcc/vdd
>                         supply in eMMC/SD specs.
>
> -- sd-uhs--sdr50:       To enable the SDR50 in the mmcss.
> +- sd-uhs-sdr50:        To enable the SDR50 in the mmcss.
>                         See:  Documentation/devicetree/bindings/mmc/mmc.txt.
>
>  - sd-uhs-sdr104:       To enable the SDR104 in the mmcss.
> --
> 2.1.4
>


From robin.murphy at arm.com  Tue May 10 03:28:40 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 10 May 2016 11:28:40 +0100
Subject: [PATCH 4/5] iommu/mediatek: add support for mtk iommu generation
 one HW
In-Reply-To: <1462780816-5288-5-git-send-email-honghui.zhang@mediatek.com>
References: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
 <1462780816-5288-5-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <5731B7D8.8040304@arm.com>

On 09/05/16 09:00, honghui.zhang at mediatek.com wrote:
[...]
> +static void *mtk_iommu_alloc_pgt(struct device *dev, size_t size, gfp_t gfp)
> +{
> +	dma_addr_t dma;
> +	void *pages = alloc_pages_exact(size, gfp | __GFP_ZERO);
> +
> +	if (!pages)
> +		return NULL;
> +
> +	dma = dma_map_single(dev, pages, size, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, dma))
> +		goto out_free;
> +	/*
> +	 * We depend on the IOMMU being able to work with any physical
> +	 * address directly, so if the DMA layer suggests otherwise by
> +	 * translating or truncating them, that bodes very badly...
> +	 */
> +	if (dma != virt_to_phys(pages))
> +		goto out_unmap;

Given that you've only got a single table to allocate, and at 4MB it has 
a fair chance of failing beyond early boot time, just use 
dma_alloc_coherent() - you don't need to care about the dma <-> phys 
relationship because you don't have multi-level tables to walk. That 
way, you can get rid of all the awkward streaming DMA stuff, and also 
benefit from CMA to avoid allocation failures.

> +	kmemleak_ignore(pages);
> +	return pages;
> +
> +out_unmap:
> +	dev_err(dev, "Cannot accommodate DMA translation for IOMMU page tables\n");
> +	dma_unmap_single(dev, dma, size, DMA_TO_DEVICE);
> +out_free:
> +	free_pages_exact(pages, size);
> +	return NULL;
> +
> +}
> +
> +static void mtk_iommu_free_pgt(struct device *dev, void *pages, size_t size)
> +{
> +	dma_unmap_single(dev, (dma_addr_t)virt_to_phys(pages),
> +			 size, DMA_TO_DEVICE);
> +	free_pages_exact(pages, size);
> +}
> +
> +static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data)
> +{
> +	struct mtk_iommu_domain *dom = data->m4u_dom;
> +
> +	spin_lock_init(&dom->pgtlock);
> +
> +	dom->pgt_va = mtk_iommu_alloc_pgt(data->dev,
> +				dom->pgt_size, GFP_KERNEL);
> +	if (!dom->pgt_va)
> +		return -ENOMEM;
> +
> +	dom->pgt_pa = virt_to_phys(dom->pgt_va);
> +
> +	writel(dom->pgt_pa, data->base + REG_MMU_PT_BASE_ADDR);
> +
> +	dom->cookie = (void *)data;
> +
> +	return 0;
> +}
> +
> +static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type)
> +{
> +	struct mtk_iommu_domain *dom;
> +
> +	if (type != IOMMU_DOMAIN_UNMANAGED)
> +		return NULL;
> +
> +	dom = kzalloc(sizeof(*dom), GFP_KERNEL);
> +	if (!dom)
> +		return NULL;
> +
> +	/*
> +	 * MTK m4u support 4GB iova address space, and oly support 4K page
> +	 * mapping. So the pagetable size should be exactly as 4M.
> +	 */
> +	dom->pgt_size = SZ_4M;

If the table size is fixed, then why bother having a variable at all?

> +	return &dom->domain;
> +}
> +
> +static void mtk_iommu_domain_free(struct iommu_domain *domain)
> +{
> +	kfree(to_mtk_domain(domain));
> +}
> +

[...]

> +static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
> +			 phys_addr_t paddr, size_t size, int prot)
> +{
> +	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
> +	struct mtk_iommu_data *data = dom->cookie;
> +	unsigned int page_num = size >> MTK_IOMMU_PAGE_SHIFT;

Since you only advertise a single page size, this will always be 1, so 
you could either get rid of the loop here...

> +	unsigned long flags;
> +	unsigned int i;
> +	u32 *pgt_base_iova;
> +	u32 pabase = (u32)paddr;
> +	int map_size = 0;
> +
> +	spin_lock_irqsave(&dom->pgtlock, flags);
> +	pgt_base_iova = dom->pgt_va + (iova  >> MTK_IOMMU_PAGE_SHIFT);
> +	for (i = 0; i < page_num; i++) {
> +		pgt_base_iova[i] = pabase | F_DESC_VALID | F_DESC_NONSEC;
> +		pabase += MTK_IOMMU_PAGE_SIZE;
> +		map_size += MTK_IOMMU_PAGE_SIZE;
> +	}
> +	dma_sync_single_for_device(data->dev,
> +			dom->pgt_pa + (iova >> MTK_IOMMU_PAGE_SHIFT),
> +			(size >> MTK_IOMMU_PAGE_SHIFT) * sizeof(u32),
> +			DMA_TO_DEVICE);
> +	spin_unlock_irqrestore(&dom->pgtlock, flags);
> +
> +	mtk_iommu_tlb_flush_range(data, iova, size);
> +
> +	return map_size;
> +}

[...]

> +static struct iommu_ops mtk_iommu_ops = {
> +	.domain_alloc	= mtk_iommu_domain_alloc,
> +	.domain_free	= mtk_iommu_domain_free,
> +	.attach_dev	= mtk_iommu_attach_device,
> +	.detach_dev	= mtk_iommu_detach_device,
> +	.map		= mtk_iommu_map,
> +	.unmap		= mtk_iommu_unmap,
> +	.map_sg		= default_iommu_map_sg,
> +	.iova_to_phys	= mtk_iommu_iova_to_phys,
> +	.add_device	= mtk_iommu_add_device,
> +	.remove_device	= mtk_iommu_remove_device,
> +	.device_group	= mtk_iommu_device_group,
> +	.pgsize_bitmap	= MTK_IOMMU_PAGE_SIZE,
> +};

...or perhaps advertise .pgsize_bitmap = ~0UL << MTK_IOMMU_PAGE_SHIFT 
here, so you actually can handle multiple entries at once for larger 
mappings - given how simple the page table format is that doesn't seem 
too unreasonable, especially since it should give you a big efficiency 
win in terms of TLB maintenance.

Robin.


From srinivas.kandagatla at linaro.org  Tue May 10 03:31:45 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Tue, 10 May 2016 11:31:45 +0100
Subject: [PATCH V2 3/3] nvmem: imx-ocotp: handling clock
In-Reply-To: <20160509124140.GA20259@linux-7smt.suse>
References: <1461173177-11930-1-git-send-email-van.freenix@gmail.com>
 <1461173177-11930-3-git-send-email-van.freenix@gmail.com>
 <5730825E.5030101@linaro.org> <20160509124140.GA20259@linux-7smt.suse>
Message-ID: <5731B891.4040303@linaro.org>



On 09/05/16 13:41, Peng Fan wrote:
> Hi Srinivas,
>
> On Mon, May 09, 2016 at 01:28:14PM +0100, Srinivas Kandagatla wrote:
>> Thanks for the Ping, I totally missed this thread.
>>
>> On 20/04/16 18:26, Peng Fan wrote:
>>> Before access ocotp nvmem area, the clock should be enabled.
>>> Or, `hexdump nvmem` will hang the system. So, use such flow:
>>> "
>>>    1. clock_enable_prepare
>>>    2. read nvmem ocotp area
>>>    3. clock_disable_unprepare
>>> "
>>>
>>> Signed-off-by: Peng Fan <van.freenix at gmail.com>
>>> Cc: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
>>> Cc: Maxime Ripard <maxime.ripard at free-electrons.com>
>>> Cc: Shawn Guo <shawnguo at kernel.org>
>>> ---
>>>
>>> V2:
>>>   Follow Fabio's comments, check return value of clk_prepare_enable
>>>
>>>   drivers/nvmem/imx-ocotp.c | 16 +++++++++++++++-
>>>   1 file changed, 15 insertions(+), 1 deletion(-)
>>
>> Changes to the driver looks good to me,
>> Only one comment, As the clock property is now made mandatory, you should
>> update the dt-bindings with this info too.
>
> In Documentation/devicetree/bindings/nvmem/imx-ocotp.txt,
> the clock property is already marked Required properties:

Ok, I can take this patch, dt patch should go via the dt maintainers.

thanks,
--srini


From kernel at martin.sperl.org  Tue May 10 03:32:26 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Tue, 10 May 2016 12:32:26 +0200
Subject: [PATCH 0/3] clk: bcm2835: critical clocks and parent selection
In-Reply-To: <1462842090-2017-1-git-send-email-eric@anholt.net>
References: <1462842090-2017-1-git-send-email-eric@anholt.net>
Message-ID: <5731B8BA.30402@martin.sperl.org>

On 10.05.2016 03:01, Eric Anholt wrote:
> With the new patch 2 inserted between my previous pair, I think this
> should cover Martin's bugs with clock disabling.
>
> I tested patch 2 to be important on the downstream kernel: with the
> DPI panel support added there, I was losing ethernet (my only I/O)
> when the HDMI HSM hanging off of PLLD_PER got disabled due to
> EPROBE_DEFER.
>
> Eric Anholt (3):
>    clk: bcm2835: Mark the VPU clock as critical
>    clk: bcm2835: Mark GPIO clocks enabled at boot as critical.
>    clk: bcm2835: Skip PLLC clocks when deciding on a new clock parent
>
>   drivers/clk/bcm/clk-bcm2835.c | 32 ++++++++++++++++++++++++++++++--
>   1 file changed, 30 insertions(+), 2 deletions(-)
>
I gave it a try - with all 3 patches applied I get the following enabled 
clocks:
root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
/sys/kernel/debug/clk/aux_uart/clk_enable_count:1
/sys/kernel/debug/clk/emmc/clk_enable_count:1
/sys/kernel/debug/clk/gp1/clk_enable_count:1
/sys/kernel/debug/clk/gp2/clk_enable_count:1
/sys/kernel/debug/clk/osc/clk_enable_count:1
/sys/kernel/debug/clk/pllc/clk_enable_count:2
/sys/kernel/debug/clk/pllc_core0/clk_enable_count:1
/sys/kernel/debug/clk/pllc_per/clk_enable_count:1
/sys/kernel/debug/clk/vpu/clk_enable_count:2

At least on my compute module gp1/gp2 is enabled, but there is no rate
set - so why is it marked as critical for all devices?
So why apply patch2 for all possible devices?

Loading/unloading the amba_pl011 module does not crash the system,
but a simple stty -F /dev/ttyAMA0 does crash the system!

Here the sequence:
root at raspcm:~# dmesg -C
root at raspcm:~# modprobe amba_pl011
root at raspcm:~# dmesg -c
[  141.708453] Serial: AMBA PL011 UART driver
[  141.709158] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, 
base_baud = 0) is a PL011 rev2
root at raspcm:~# rmmod  amba_pl011
root at raspcm:~# dmesg -c
[  150.511248] Trying to free nonexistent resource 
<0000000020201000-0000000020201fff>
root at raspcm:~# modprobe amba_pl011
root at raspcm:~# dmesg -c
[  159.385002] Serial: AMBA PL011 UART driver
[  159.385714] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, 
base_baud = 0) is a PL011 rev2
root at raspcm:~# stty -F /dev/ttyAMA0
speed 9600 baud; line = 0;
-brkint -imaxbel
root at raspcm:~# Timeout, server raspcm not responding.

The reason behind this is that the firmware pre-configured uart clock
looks like this:
root at raspcm:~# cat /sys/kernel/debug/clk/uart/regdump
ctl = 0x00000296
div = 0x000a6aab
so it is configured to use plld_per (which itself is running, even if 
not enabled
in the kernel)

But as plld_per is not among the enabled clocks then plld_per
gets disabled as soon as the tty device is closed (by stty) and
this also disables plld...

Similar effect when using PCM/i2s and use speaker-test:
root at raspcm:~# dmesg -C
root at raspcm:~# modprobe snd-soc-bcm2835-i2s; modprobe snd-soc-pcm5102a; 
modprobe snd-soc-hifiberry-dac
root at raspcm:~# dmesg
[   81.968591] snd-hifiberry-dac sound: pcm5102a-hifi <-> 20203000.i2s 
mapping ok
root at raspcm:~# speaker-test -c 2 -r 44100 -F S16_LE -f 440 -t sine&
[1] 579
root at raspcm:~#
speaker-test 1.0.28

Playback device is default
Stream parameters are 44100Hz, S16_LE, 2 channels
Sine wave rate is 440.0000Hz
Rate set to 44100Hz (requested 44100Hz)
Buffer size range from 128 to 131072
Period size range from 64 to 65536
Using max buffer size 131072
Periods = 4
was set period_size = 32768
was set buffer_size = 131072
  0 - Front Left
  1 - Front Right

root at raspcm:~#
root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
/sys/kernel/debug/clk/aux_uart/clk_enable_count:1
/sys/kernel/debug/clk/emmc/clk_enable_count:1
/sys/kernel/debug/clk/gp1/clk_enable_count:1
/sys/kernel/debug/clk/gp2/clk_enable_count:1
/sys/kernel/debug/clk/osc/clk_enable_count:2
/sys/kernel/debug/clk/pcm/clk_enable_count:1
/sys/kernel/debug/clk/pllc/clk_enable_count:2
/sys/kernel/debug/clk/pllc_core0/clk_enable_count:1
/sys/kernel/debug/clk/pllc_per/clk_enable_count:1
/sys/kernel/debug/clk/plld/clk_enable_count:1
/sys/kernel/debug/clk/plld_per/clk_enable_count:1
/sys/kernel/debug/clk/vpu/clk_enable_count:2
root at raspcm:~# kill %1
root at raspcm:~# Time per period = 106.889502
Timeout, server raspcm not responding.

You see that plld gets now used and when I kill speaker-test
the machine crashes again.

So this patchset does not really solve any of the problems that
I have reported either.

That is why my patchset has taken the "HAND_OFF" approach
instead (which still just hides some of the issues), but at least
it does not crash the system on the use of plld and it allows
for custom parent and mash selection.

In reality it would require consumers of the corresponding
parent clocks in the kernel (arm, ...) and the knowledge which
clocks are really needed by the firmware - i.e plld.

Note that the sdram clock is using plld_core parent!
root at raspcm:~#  cat /sys/kernel/debug/clk/sdram/regdump
ctl = 0x00004006
div = 0x00003000
root at raspcm:~# cat /sys/kernel/debug/clk/sdram/clk_rate
166533331

and also hsm (probably hardware security module):
root at raspcm:~# cat /sys/kernel/debug/clk/hsm/regdump
ctl = 0x000002d6
div = 0x000030e0
root at raspcm:~# cat /sys/kernel/debug/clk/hsm/clk_rate
163551916

So turning plld off stops sdram and hsm - at least that is my
interpretation.

This means we need to define a clock property in firmware or
we need a ram node making use of "mmio-sram" maybe?

Marking sdram as "critical" or "hand_off" could also solve that
for the moment (but it does not solve all the other hidden
clock dependencies of the firmware)
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1655,7 +1655,8 @@ static const struct bcm2835_clk_desc 
clk_desc_array[] = {
                 .ctl_reg = CM_SDCCTL,
                 .div_reg = CM_SDCDIV,
                 .int_bits = 6,
-               .frac_bits = 0),
+               .frac_bits = 0,
+               .flags = CLK_IS_CRITICAL),
         [BCM2835_CLOCK_V3D]     = REGISTER_VPU_CLK(
                 .name = "v3d",
                 .ctl_reg = CM_V3DCTL,

with this patch the system does no longer crash for the above
cases!

Still I would say that this should actually move to the dt to
correctly describe the HW.

Martin



From mark.rutland at arm.com  Tue May 10 03:34:01 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 10 May 2016 11:34:01 +0100
Subject: [PATCH] arm64: secondary_start_kernel: Remove unnecessary barrier
In-Reply-To: <1462875281-5063-1-git-send-email-suzuki.poulose@arm.com>
References: <1462875281-5063-1-git-send-email-suzuki.poulose@arm.com>
Message-ID: <20160510103400.GG687@leverpostej>

On Tue, May 10, 2016 at 11:14:41AM +0100, Suzuki K Poulose wrote:
> Remove the unnecessary smp_wmb(), which was added to make sure
> that the update_cpu_boot_status() completes before we mark the
> CPU online. But update_cpu_boot_status() already has dsb() (required
> for the failing CPUs) to ensure the correct behavior.
> 
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Dennis Chen <dennis.chen at arm.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>

Acked-by: Mark Rutland <mark.rutland at arm.com>

Mark.

> ---
>  arch/arm64/kernel/smp.c |    2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> index b2d5f4e..ec040a8 100644
> --- a/arch/arm64/kernel/smp.c
> +++ b/arch/arm64/kernel/smp.c
> @@ -225,8 +225,6 @@ asmlinkage void secondary_start_kernel(void)
>  	pr_info("CPU%u: Booted secondary processor [%08x]\n",
>  					 cpu, read_cpuid_id());
>  	update_cpu_boot_status(CPU_BOOT_SUCCESS);
> -	/* Make sure the status update is visible before we complete */
> -	smp_wmb();
>  	set_cpu_online(cpu, true);
>  	complete(&cpu_running);
>  
> -- 
> 1.7.9.5
> 


From peter.ujfalusi at ti.com  Tue May 10 03:40:54 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Tue, 10 May 2016 13:40:54 +0300
Subject: [PATCH] dmaengine: edma: Re-evaluate errors when ccerr is triggered
 w/o error event
Message-ID: <1462876854-9190-1-git-send-email-peter.ujfalusi@ti.com>

When the ccerr handler is called but the error registers indicate no error
events we need to command eDMA to re-evaluate the errors. Otherwise we can
receive flood of error interrupts.

Reported-by: Roger Quadros <rogerq at ti.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 drivers/dma/edma.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index 10f9b992b927..7c76b558cf82 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -1540,8 +1540,17 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data)
 
 	dev_vdbg(ecc->dev, "dma_ccerr_handler\n");
 
-	if (!edma_error_pending(ecc))
+	if (!edma_error_pending(ecc)) {
+		/*
+		 * The registers indicate no pending error event but the irq
+		 * handler has been called.
+		 * Ask eDMA to re-evaluate the error registers.
+		 */
+		dev_err(ecc->dev, "%s: Error interrupt without error event!\n",
+			__func__);
+		edma_write(ecc, EDMA_EEVAL, 1);
 		return IRQ_NONE;
+	}
 
 	while (1) {
 		/* Event missed register(s) */
-- 
2.8.2



From mark.rutland at arm.com  Tue May 10 03:45:11 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 10 May 2016 11:45:11 +0100
Subject: [PATCH] arm64: kgdb: Match pstate size with gdbserver protocol
In-Reply-To: <1462815566-15086-1-git-send-email-daniel.thompson@linaro.org>
References: <1462815566-15086-1-git-send-email-daniel.thompson@linaro.org>
Message-ID: <20160510104511.GH687@leverpostej>

On Mon, May 09, 2016 at 06:39:26PM +0100, Daniel Thompson wrote:
> Current versions of gdb do not interoperate cleanly with kgdb on arm64
> systems because gdb and kgdb do not use the same register description.
> This patch modifies kgdb to work with recent releases of gdb (>= 7.8.1).
> 
> Compatibility with gdb (after the patch is applied) is as follows:
> 
>   gdb-7.6 and earlier  Ok
>   gdb-7.7 series       Works if user provides custom target description
>   gdb-7.8(.0)          Works if user provides custom target description
>   gdb-7.8.1 and later  Ok
> 
> When commit 44679a4f142b ("arm64: KGDB: Add step debugging support") was
> introduced it was paired with a gdb patch that made an incompatible
> change to the gdbserver protocol. This patch was eventually merged into
> the gdb sources:
> https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=a4d9ba85ec5597a6a556afe26b712e878374b9dd
> 
> The change to the protocol was mostly made to simplify big-endian support
> inside the kernel gdb stub.

While that was how we discovered the inconsistency, a major concern is
that SPSR_EL* (i.e. PSTATE), as accessed by MRS/MSR is a 64-bit
quantity, even if the upper 32 bits are RES0 today.

It is conceivable that the upper 32 bits could be used in future (as
happened with CLIDR_EL1), and for this reason we expose those upper 32
bits from the kernel, and treat system registers as 64-bit quantities
generally.

So this was also about ensuring the interface was consistent and to some
extent future-proof.

Thanks,
Mark.


From marc.zyngier at arm.com  Tue May 10 03:49:57 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 11:49:57 +0100
Subject: [PATCH v3 25/55] KVM: arm/arm64: vgic-new: Add PENDING registers
 handlers
In-Reply-To: <1462531568-9799-26-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-26-git-send-email-andre.przywara@arm.com>
Message-ID: <5731BCD5.4040806@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> The pending register handlers are shared between the v2 and v3
> emulation, so their implementation goes into vgic-mmio.c, to be easily
> referenced from the v3 emulation as well later.
> For level triggered interrupts the real line level is unaffected by
> this write, so we keep this state separate and combine it with the
> device's level to get the actual pending state.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>

	M.
-- 
Jazz is not dead. It just smells funny...


From andre.przywara at arm.com  Tue May 10 03:58:42 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue, 10 May 2016 11:58:42 +0100
Subject: [PATCH] KVM: arm/arm64: vgic-new: fix overlap check for device
 addresses
In-Reply-To: <5730C65D.5000609@arm.com>
References: <5730C65D.5000609@arm.com>
Message-ID: <1462877922-8743-1-git-send-email-andre.przywara@arm.com>

When userland sets the base addresses for the GIC register frames,
the kernel tries to make sure that the regions for the distributor and
the one for the CPU interface or the redistributors do not overlap.
Only that this check currently takes care of a GICv2 model only.
Rework the overlap check to take a GICv3 in account also.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Hi Marc,

this one goes on top of the new-vgic-v3 series.
Does this address your concerns about the overlap check?
I'd be grateful if you could apply some of your C wizardry on the first
function ;-)

Cheers,
Andre.

 virt/kvm/arm/vgic/vgic-kvm-device.c | 59 ++++++++++++++++++++++++++-----------
 1 file changed, 41 insertions(+), 18 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 2122ff2..fcf38ef 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -21,41 +21,63 @@
 
 /* common helpers */
 
-static int vgic_ioaddr_overlap(struct kvm *kvm)
+static phys_addr_t vgic_get_existing_region(struct kvm *kvm, phys_addr_t *addr)
 {
-	phys_addr_t dist = kvm->arch.vgic.vgic_dist_base;
-	phys_addr_t cpu = kvm->arch.vgic.vgic_cpu_base;
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	phys_addr_t cpu_addr;
+	bool is_vgicv2 = (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2);
 
-	if (IS_VGIC_ADDR_UNDEF(dist) || IS_VGIC_ADDR_UNDEF(cpu))
-		return 0;
-	if ((dist <= cpu && dist + KVM_VGIC_V2_DIST_SIZE > cpu) ||
-	    (cpu <= dist && cpu + KVM_VGIC_V2_CPU_SIZE > dist))
-		return -EBUSY;
-	return 0;
+	cpu_addr = is_vgicv2 ? dist->vgic_cpu_base : dist->vgic_redist_base;
+
+	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base)) {
+		if (IS_VGIC_ADDR_UNDEF(cpu_addr))
+			return 0;
+
+		*addr = cpu_addr;
+		if (is_vgicv2)
+			return KVM_VGIC_V2_CPU_SIZE;
+		return atomic_read(&kvm->online_vcpus) * KVM_VGIC_V3_REDIST_SIZE;
+	}
+
+	*addr = dist->vgic_dist_base;
+	return is_vgicv2 ? KVM_VGIC_V2_DIST_SIZE : KVM_VGIC_V3_DIST_SIZE;
+}
+
+static bool vgic_ioaddr_overlap(struct kvm *kvm, phys_addr_t addr,
+				phys_addr_t size)
+{
+	phys_addr_t used_addr, used_size;
+
+	used_size = vgic_get_existing_region(kvm, &used_addr);
+	if (!used_size)
+		return false;
+
+	if (addr + size <= used_addr)
+		return false;
+
+	if (used_addr + used_size <= addr)
+		return false;
+
+	return true;
 }
 
 static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
 			      phys_addr_t addr, phys_addr_t size)
 {
-	int ret;
-
 	if (addr & ~KVM_PHYS_MASK)
 		return -E2BIG;
 
-	if (addr & (SZ_4K - 1))
-		return -EINVAL;
-
 	if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
 		return -EEXIST;
 	if (addr + size < addr)
 		return -EINVAL;
 
+	if (vgic_ioaddr_overlap(kvm, addr, size))
+		return -EBUSY;
+
 	*ioaddr = addr;
-	ret = vgic_ioaddr_overlap(kvm);
-	if (ret)
-		*ioaddr = VGIC_ADDR_UNDEF;
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -104,6 +126,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
 		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
 		addr_ptr = &vgic->vgic_redist_base;
 		block_size = KVM_VGIC_V3_REDIST_SIZE;
+		block_size *= atomic_read(&kvm->online_vcpus);
 		alignment = SZ_64K;
 		break;
 #endif
-- 
2.7.3



From ulf.hansson at linaro.org  Tue May 10 04:02:08 2016
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Tue, 10 May 2016 13:02:08 +0200
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <20160509181829.GA19687@rob-hp-laptop>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <20160505224240.GA31429@rob-hp-laptop>
 <CAPDyKFqpoi03Egfuvd8qJXnn_+FBgPXAb7S4UvkxVs8BA+zwnA@mail.gmail.com>
 <20160509181829.GA19687@rob-hp-laptop>
Message-ID: <CAPDyKFq2=mqujFjvJSYxg2nVmK=OrBKLtFfb-ErNJO3Zr_LMVw@mail.gmail.com>

+ Arnd

[...]

>> >> Solution
>> >> ========
>> >> This is very similar to the MMC pwrseq behavior so the idea is to:
>> >> 1. Move MMC pwrseq drivers to generic place,
>> >
>> > You can do that, but I'm going to NAK any use of pwrseq bindings outside
>> > of MMC. I think it is the wrong way to do things. The DT should describe
>>
>> Huh, I didn't know that was your view of the mmc pwrseq bindings. Why
>> didn't you NAK them before?
>
> Unfortunately, either I missed it or it was a time I couldn't spend much
> time on reviews.

Okay, I guess it's common issue among maintainers. The problem with DT
is that it gets really hard to be fixed up later. :-)

>
>> > the devices. If they happen to be "simple" then the core can walk the
>> > tree and do any setup. For example, look for "reset-gpios" and toggle
>> > that GPIO. There is no need for a special node.
>> >
>> >> 2. Extend the pwrseq-simple with regulator toggling,
>> >> 3. Add support to USB hub and port core for pwrseq,
>> >
>> > We discussed this for USB already[1] and is why we defined how to add
>> > USB child devices. The idea is not to add pwrseq to that.
>>
>> I am not familiar with the USB discussion.
>>
>> Still, let me give you some more background to the mmc pwrseq. The
>> idea from the mmc pwrseq bindings comes from the power-domain DT
>> bindings, as I thought these things were a bit related.
>> In both cases they are not directly a property of the device, but more
>> describing a HW dependency to allow the device to work.
>
> I could see this as a board level power domain. However the difference
> is we are not generally exposing internal SOC details the same way as
> board level components. Perhaps we could extend power domains to board
> level, but that is not what was done here.
>
>> One could probably use a child node instead of a phandle, but that
>> wasn't chosen back then. Of course you are the DT expert, but could
>> you perhaps tell me why a child node is better for cases like this?
>
> If there is a control path hierarchy, then we try to model that in DT
> with child nodes. In cases of SDIO and USB, there is a clear hierarchy.
> Ignoring the discovery ordering problem, we already have defined ways to
> describe GPIO connections, regulators, etc. to devices. Describing those
> things separately from the device to solve a particular issue that is
> really a kernel limitation is what I don't like.

Okay, I see.

To move forward in trying to make mmc pwrseq a generic pwrseq, could
we perhaps allow both cases?

In the mmc case, there are already deployed bindings so we need to
cope with these by using the phandle option, but for USB etc we could
force the child node option.
As long as we agree that we keep using a compatible string for the
child node as well, both options should be able to co-exist and we
should probably be able to managed them both from a common pwrseq
driver framework.

Although, I do remember from an older conversations around some of
mine submission for the mmc pwrseq code, that some people (maybe
Arnd?) wasn't keen on adding a new framework for this. Perhaps that
has changed?

Kind regards
Uffe


From adrian.hunter at intel.com  Tue May 10 04:02:50 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 14:02:50 +0300
Subject: [PATCH 14/23] mmc: sdhci-esdhci-imx: disable DLL delay line
 settings explicitly
In-Reply-To: <1460741387-23815-15-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-15-git-send-email-aisheng.dong@nxp.com>
Message-ID: <5731BFDA.2000504@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> From: Dong Aisheng <aisheng.dong at freescale.com>
> 
> Disable DLL delay line settings explicitly during driver initialization
> in case ROM/uBoot had set an invalid delay.
> e.g. MX6DL ROM has set the default delay line(DLLCTRL) to 0x1000021,
> the uSDHC clock timing will become marginal when works on DDR mode
> due to default delay and will possibly see CRC errors in case the board
> is not perfectly designed on the eMMC chip layout.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>

Acked-by: Adrian Hunter <adrian.hunter at intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 4c28fbb..d02db66 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1186,6 +1186,9 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  		*/
>  		writel(readl(host->ioaddr + 0x6c) | BIT(7),
>  			host->ioaddr + 0x6c);
> +
> +		/* disable DLL_CTRL delay line settings */
> +		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
>  	}
>  
>  	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> 



From joel at jms.id.au  Tue May 10 04:06:50 2016
From: joel at jms.id.au (Joel Stanley)
Date: Tue, 10 May 2016 20:36:50 +0930
Subject: [PATCH 2/4] drivers/clocksource/moxart: Refactor enable/disable
In-Reply-To: <1462797169-14512-3-git-send-email-joel@jms.id.au>
References: <1462797169-14512-1-git-send-email-joel@jms.id.au>
 <1462797169-14512-3-git-send-email-joel@jms.id.au>
Message-ID: <CACPK8XfJ2e1kr-WftidvqsoYew7LqPiNo0sw7opgh8UH=3q_3A@mail.gmail.com>

Hi Daniel,

Here's a commit message for this patch. If you'd prefer me to resend
the entire series with this included then I can do that.

This patch abstracts the enable and disable register writes into their
own functions in preparation for future changes to use SoC specific
values for the writes.

> Signed-off-by: Joel Stanley <joel at jms.id.au>
> ---
>  drivers/clocksource/moxart_timer.c | 22 ++++++++++++++++------
>  1 file changed, 16 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c
> index 19857af651c1..b00b2b21e8b3 100644
> --- a/drivers/clocksource/moxart_timer.c
> +++ b/drivers/clocksource/moxart_timer.c
> @@ -58,15 +58,25 @@
>  static void __iomem *base;
>  static unsigned int clock_count_per_tick;
>
> -static int moxart_shutdown(struct clock_event_device *evt)
> +static inline void moxart_disable(struct clock_event_device *evt)
>  {
>         writel(TIMER1_DISABLE, base + TIMER_CR);
> +}
> +
> +static inline void moxart_enable(struct clock_event_device *evt)
> +{
> +       writel(TIMER1_ENABLE, base + TIMER_CR);
> +}
> +
> +static int moxart_shutdown(struct clock_event_device *evt)
> +{
> +       moxart_disable(evt);
>         return 0;
>  }
>
>  static int moxart_set_oneshot(struct clock_event_device *evt)
>  {
> -       writel(TIMER1_DISABLE, base + TIMER_CR);
> +       moxart_disable(evt);
>         writel(~0, base + TIMER1_BASE + REG_LOAD);
>         return 0;
>  }
> @@ -74,21 +84,21 @@ static int moxart_set_oneshot(struct clock_event_device *evt)
>  static int moxart_set_periodic(struct clock_event_device *evt)
>  {
>         writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD);
> -       writel(TIMER1_ENABLE, base + TIMER_CR);
> +       moxart_enable(evt);
>         return 0;
>  }
>
>  static int moxart_clkevt_next_event(unsigned long cycles,
> -                                   struct clock_event_device *unused)
> +                                   struct clock_event_device *evt)
>  {
>         u32 u;
>
> -       writel(TIMER1_DISABLE, base + TIMER_CR);
> +       moxart_disable(evt);
>
>         u = readl(base + TIMER1_BASE + REG_COUNT) - cycles;
>         writel(u, base + TIMER1_BASE + REG_MATCH1);
>
> -       writel(TIMER1_ENABLE, base + TIMER_CR);
> +       moxart_enable(evt);
>
>         return 0;
>  }
> --
> 2.8.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From mark.rutland at arm.com  Tue May 10 04:07:42 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 10 May 2016 12:07:42 +0100
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <20160510100448.49834120@bbrezillon>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop>
 <20160503185153.5cfddc32@bbrezillon>
 <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
 <20160504113852.10a2dd84@bbrezillon>
 <CAL_Jsq+4aL5znA3zOKdcJb+pEXhVOQthkFF6DN2+P6U37t2o6g@mail.gmail.com>
 <20160504153547.60d736bb@bbrezillon>
 <20160510100448.49834120@bbrezillon>
Message-ID: <20160510110742.GI687@leverpostej>

On Tue, May 10, 2016 at 10:04:48AM +0200, Boris Brezillon wrote:
> On Wed, 4 May 2016 15:35:47 +0200
> Boris Brezillon <boris.brezillon at free-electrons.com> wrote:
> 
> > On Wed, 4 May 2016 08:06:10 -0500
> > Rob Herring <robh at kernel.org> wrote:
> > 
> > > On Wed, May 4, 2016 at 4:38 AM, Boris Brezillon
> > > <boris.brezillon at free-electrons.com> wrote:  
> > > > Hi Rob,
> > > >
> > > > On Tue, 3 May 2016 14:11:04 -0500
> > > > Rob Herring <robh at kernel.org> wrote:
> > > >    
> > > >> On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
> > > >> <boris.brezillon at free-electrons.com> wrote:    
> > > >> > Hi Rob,
> > > >> >
> > > >> > On Tue, 3 May 2016 11:40:19 -0500
> > > >> > Rob Herring <robh at kernel.org> wrote:
> > > >> >    
> > > >> >> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:    
> > > >> >> > The EBI (External Bus Interface) is used to access external peripherals
> > > >> >> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
> > > >> >> > Each device is assigned a CS line and an address range and can have its
> > > >> >> > own configuration (timings, access mode, bus width, ...).
> > > >> >> > This driver provides a generic DT binding to configure a device according
> > > >> >> > to its requirements.
> > > >> >> > For specific device controllers (like the NAND one) the SMC timings
> > > >> >> > should be configured by the controller driver through the matrix and smc
> > > >> >> > syscon regmaps.    
> > > 
> > > [...]
> > >   
> > > >> >> > +EBI bus configuration associated with specific chip-select will be defined in
> > > >> >> > +the configs subnode. This configs node will in turn contain several subnodes
> > > >> >> > +named config-<cs-id>, each of them containing the following properties.    
> > > >> >>
> > > >> >> This is a bit unusual. Why not just part of the child device nodes?    
> > > >> >
> > > >> > Oh, come on! I reworked the binding because Mark complained about the
> > > >> > previous binding which was doing exactly what you're suggesting. Can
> > > >> > you please be consistent in your reviews...    
> > > >>
> > > >> No, Mark and I both have our opinions. Which part of this patch
> > > >> explains the history?    
> > > >
> > > > Hm, it's in patch 1/2 (just dropped the cover letter, which might not
> > > > be such a good idea).
> > > >    
> > > >> If the revision history is not in the patch, I'm
> > > >> not looking at it.
> > > >>
> > > >> My issue with it this way is that it has invented yet another way to
> > > >> describe timings. I would like to be consistent across external bus
> > > >> descriptions, but we're not very consistent to begin with though. The
> > > >> most common seems to be the way you first did it. But I agree that it
> > > >> is kind of screwy to have an intermediate node unless the controller
> > > >> itself has sub-blocks within it and is not the established way to
> > > >> describe a bus with chip selects. I would either put the properties
> > > >> directly in the child nodes (e.g. flash at 0,0) or put your config nodes
> > > >> in the device node. I'd call it timings instead of config, but that's
> > > >> just bikeshedding.    
> > > >
> > > > Well, it's not only describing timings (see atmel,bus-width,
> > > > atmel,byte-access-type, ...), but I'm fine with either names :).
> > > >    
> > > >>
> > > >> memory-controller at 1000 {
> > > >>   ...
> > > >>   flash at 0,0 {
> > > >>     timings {
> > > >>       ...
> > > >>     };
> > > >>   };
> > > >> };    
> > > >
> > > > Okay. Mark, what do you think of this approach?
> > > >
> > > > Note that one of my previous version was defining timings directly in
> > > > the EBI device node, and Arnd noted that doing so may cause problems
> > > > if one of the EBI property (or the config/timing node name) conflict
> > > > with the sub-device binding, which is why I decided to put the EBI
> > > > config definitions in a separate subnode.    
> > > 
> > > You have vendor prefixes on all the properties so I don't think a
> > > collision is really a problem. It's also an established pattern in
> > > i.MX WEIM and OMAP GPMC (which are hiding in bindings/bus/) and I
> > > prefer consistency.  
> > 
> > So let's summarize that.
> > 
> > memory-controller at 1000 {
> > 	...
> > 	flash at 0,0 {
> > 		atmel,<ebi-prop-name> = <value>;
> > 		...
> > 		<flash-device-prop> = <value>;
> > 	};
> > };
> > 
> > Would everyone agree on this representation?
> > 
> > With this approach, it's a bit more complicated to detect the case
> > where we want to keep bootloader/firmware config, but it should be
> > doable (it's much more easier to test for the presence of a
> > config/timing node than verifying that either all or none of the
> > mandatory properties are here).
> > 
> > Still remains the problem mentioned by Jean-Jacques: what if the
> > sub-device takes 2 CS lines. Should we apply the same setting to those
> > slots?
> > 
> 
> Rob, Mark, Arnd, can you take a decision regarding this binding? This
> driver is floating around for quite some time, and we were asked to
> rework the binding several times (in time in an opposite direction).
> 
> For the record, here is the thread I mentioned earlier [1]. In his
> answer, Arnd suggests to put timing and bus config description
> outside of the sub-device node. Mark recently complained about this
> representation, which led me to the configs/config-X appraoch, and now
> Rob suggests to go back to the first proposal.
> 
> I'm fine doing that, but can you please all confirm that you agree on
> this binding?

Sorry for the delay in getting round to this, and sorry that this
appears to be going in circles.

Please go with Rob's suggestion.

I'm not sure about the case where a device takes 2 CS lines. I would
assume that in practice that a sub-device covered my multiple CS lines
expects the same timings for all its MMIO space, and so having that
uniform makes sense. Do we have a counter-example?

Thanks,
Mark.


From joel at jms.id.au  Tue May 10 04:10:21 2016
From: joel at jms.id.au (Joel Stanley)
Date: Tue, 10 May 2016 20:40:21 +0930
Subject: [PATCH 2/2] watchdog: Add Aspeed watchdog driver
In-Reply-To: <5730A339.80006@roeck-us.net>
References: <1462797277-14969-1-git-send-email-joel@jms.id.au>
 <1462797277-14969-3-git-send-email-joel@jms.id.au>
 <5730A339.80006@roeck-us.net>
Message-ID: <CACPK8XfK4Qt2GaSL7eVoNkCawbtXqFX9bGRcgyAyq7R2yuSZkA@mail.gmail.com>

Hey Guenter,

Thanks for the review.

On Tue, May 10, 2016 at 12:18 AM, Guenter Roeck <linux at roeck-us.net> wrote:
>> +#define WDT_STATUS             0x00
>> +#define WDT_RELOAD_VALUE       0x04
>> +#define WDT_RESTART            0x08
>> +#define WDT_CTRL               0x0C
>> +#define   WDT_CTRL_RESET_MODE_SOC      (0x00 << 5)
>> +#define   WDT_CTRL_RESET_MODE_FULL_CHIP        (0x01 << 5)
>> +#define          WDT_CTRL_1MHZ_CLK             BIT(4)
>> +#define          WDT_CTRL_WDT_EXT              BIT(3)
>> +#define          WDT_CTRL_WDT_INTR             BIT(2)
>> +#define   WDT_CTRL_RESET_SYSTEM                BIT(1)
>> +#define   WDT_CTRL_ENABLE              BIT(0)
>> +
>> +#define        WDT_RESTART_MAGIC       0x4755
>
>
> Please don't use tabs after #define.

Oops, typo. Thanks.

>
>> +
>> +static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd)
>> +{
>> +       return container_of(wdd, struct aspeed_wdt, wdd);
>> +}
>> +
>> +
>
> Please no double empty lines.
>
>> +static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
>> +{
>> +       wdt->ctrl |= WDT_CTRL_ENABLE;
>> +
>> +       writel(0, wdt->base + WDT_CTRL);
>> +       writel(count, wdt->base + WDT_RELOAD_VALUE);
>> +       writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
>> +       writel(wdt->ctrl, wdt->base + WDT_CTRL);
>
>
> Is it really necessary to write 0 into the ctrl register when enabling
> the watchdog ? Problem with it is two-fold: It changes the clock rate
> for a brief period of time, and it disables the watchdog while updating
> the timeout. Both is undesirable unless really needed.

In general I agree. However, the datasheet explicitly spells out these
four steps in this order. Writing zero is a shortcut; I could write
ctrl with the enable bit set to zero.

We've been using the driver in this fashion for the past year.

>> +}
>> +
>> +static int aspeed_wdt_start(struct watchdog_device *wdd)
>> +{
>> +       struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
>> +
>> +       dev_dbg(wdd->parent, "starting with timeout of %d (rate %lu)\n",
>> +                       wdd->timeout, wdt->rate);
>
>
> Are those dev_dbg() really useful ?

I did use them in writing the driver. They can go.

>
>> +       aspeed_wdt_enable(wdt, wdd->timeout * wdt->rate);
>> +
>> +       return 0;
>> +}
>> +
>> +static int aspeed_wdt_stop(struct watchdog_device *wdd)
>> +{
>> +       struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
>> +
>> +       wdt->ctrl &= ~WDT_CTRL_ENABLE;
>> +       writel(wdt->ctrl, wdt->base + WDT_CTRL);
>> +
>> +       return 0;
>> +}
>> +
>> +static int aspeed_wdt_ping(struct watchdog_device *wdd)
>> +{
>> +       struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
>> +
>> +       dev_dbg(wdd->parent, "ping\n");
>> +       writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
>> +       return 0;
>> +}
>> +
>> +static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
>> +                                 unsigned int timeout)
>> +{
>> +       dev_dbg(wdd->parent, "timeout set to %u\n", timeout);
>> +       wdd->timeout = timeout;
>> +
>> +       return aspeed_wdt_start(wdd);
>> +}
>> +
>> +static int aspeed_wdt_restart(struct watchdog_device *wdd,
>> +                             unsigned long action, void *data)
>> +{
>> +       struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
>> +
>> +       aspeed_wdt_enable(wdt, 128 * wdt->rate / 1000);
>> +
>> +       return 0;
>> +}
>> +
>> +static const struct watchdog_ops aspeed_wdt_ops = {
>> +       .start          = aspeed_wdt_start,
>> +       .stop           = aspeed_wdt_stop,
>> +       .ping           = aspeed_wdt_ping,
>> +       .set_timeout    = aspeed_wdt_set_timeout,
>> +       .restart        = aspeed_wdt_restart,
>> +       .owner          = THIS_MODULE,
>> +};
>> +
>> +static const struct watchdog_info aspeed_wdt_info = {
>> +       .options        = WDIOF_KEEPALIVEPING
>> +                       | WDIOF_MAGICCLOSE
>> +                       | WDIOF_SETTIMEOUT,
>> +       .identity       = KBUILD_MODNAME,
>> +};
>> +
>> +static int aspeed_wdt_remove(struct platform_device *pdev)
>> +{
>> +       struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
>> +
>> +       watchdog_unregister_device(&wdt->wdd);
>> +
>> +       return 0;
>> +}
>> +
>> +static int aspeed_wdt_probe(struct platform_device *pdev)
>> +{
>> +       struct aspeed_wdt *wdt;
>> +       struct resource *res;
>> +       int ret;
>> +
>> +       wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
>> +       if (!wdt)
>> +               return -ENOMEM;
>> +
>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       wdt->base = devm_ioremap_resource(&pdev->dev, res);
>> +       if (IS_ERR(wdt->base))
>> +               return PTR_ERR(wdt->base);
>> +
>> +       /*
>> +        * The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only
>> +        * runs at 1MHz. We chose to always run at 1MHz, as there's no
>> +        * good reason to have a faster watchdog counter.
>> +        */
>> +       wdt->rate = 1000000;
>
>
> Why not just use a define ?

I will add one.

The comment is informative though for people who read the ast2400
datasheet and wonder why we don't provide the option clocking with
pclk, I will leave it in.

>> +       wdt->wdd.info = &aspeed_wdt_info;
>> +       wdt->wdd.ops = &aspeed_wdt_ops;
>> +       wdt->wdd.min_timeout = 1;
>> +       wdt->wdd.max_timeout = 0x10000000U / wdt->rate;
>> +       wdt->wdd.parent = &pdev->dev;
>> +
>> +       wdt->wdd.timeout = min(wdt->wdd.max_timeout, 30U);
>
>
> Pretty much the same here. Since max_timeout is a constant,
> it is well known that it is larger than 30 seconds.
> Might as well use defines for max_timeout and timeout.

Ok.

>
>> +       watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
>> +
>> +       wdt->ctrl = WDT_CTRL_RESET_MODE_SOC |
>
>
> Only reset tha SoC ? Are you sure this is what you want ?

I think this is left over from experiments when tracking down a reset
bug in u-boot. I will confirm and change it back to FULL_CHIP.

>
>> +               WDT_CTRL_1MHZ_CLK |
>> +               WDT_CTRL_RESET_SYSTEM;
>> +
>> +       /* Ensure hardware is in consistent state */
>> +       aspeed_wdt_stop(&wdt->wdd);
>> +
>
> An alternative might be to check if the watchdog is running, and inform
> the watchdog core about it so it can generate heartbeats as required
> until user space opens the watchdog device. This would ensure that the
> system is protected during boot.

I will implement this.

> ctrl is really static except for the enable flag. Not really sure
> if having a variable for it has any real benefits - you might as well
> just read the register and update the enable flag instead as needed when
> starting or stopping the watchdog. Is there a reason for not doing that ?

Not really. I find it cleaner to keep a copy of the register instead
of read-modify-write, but if you feel strongly about it I can change.

>
>> +       ret = watchdog_register_device(&wdt->wdd);
>> +       if (ret) {
>> +               dev_err(&pdev->dev, "failed to register\n");
>> +               goto err;
>
>
> Unnecessary goto. Just return.

Ok.

>
>
>> +       }
>> +
>> +       dev_info(&pdev->dev, "rate %lu, max timeout %u, timeout %d\n",
>> +                wdt->rate, wdt->wdd.max_timeout, wdt->wdd.timeout);
>> +
>> +       platform_set_drvdata(pdev, wdt);
>> +err:
>> +       return ret;
>> +}
>> +
>> +static struct platform_driver aspeed_watchdog_driver = {
>> +       .probe = aspeed_wdt_probe,
>> +       .remove = aspeed_wdt_remove,
>> +       .driver = {
>> +               .name = KBUILD_MODNAME,
>> +               .of_match_table = of_match_ptr(aspeed_wdt_of_table),
>> +       },
>> +};
>> +module_platform_driver(aspeed_watchdog_driver);
>> +
>> +MODULE_DESCRIPTION("Aspeed Watchdog Driver");
>> +MODULE_LICENSE("GPL");
>>
>


From wxt at rock-chips.com  Tue May 10 04:14:56 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue, 10 May 2016 19:14:56 +0800
Subject: [PATCH] pinctrl: rockchip: fix pull setting error for rk3399
Message-ID: <1462878896-28956-1-git-send-email-wxt@rock-chips.com>

From: David Wu <david.wu at rock-chips.com>

This patch fixes the pinctrl pull bias setting, since the pull up/down
setting is the contrary for gpio0.

>From the TRM said, the gpio0 pull polarity setting:
gpio0a_p (gpio0 )
GPIO0A PE/PS programmation section, every
GPIO bit corresponding to 2bits[PS:PE]
2'b00: Z(Noraml operaton);
2'b11: weak 1(pull-up);
2'b01: weak 0(pull-down);
2'b10: Z(Noraml operaton);

Then, the other gpios setting as the following:
gpio1a_p (gpio1, gpio2, gpio3...)
GPIO1A PU/PD programmation section, every
GPIO bit corresponding to 2bits
2'b00: Z(Noraml operaton);
2'b01: weak 1(pull-up);
2'b10: weak 0(pull-down);
2'b11: Repeater(Bus keeper)

For example,(rk3399evb board)
sdmmc_cd --->gpio0_a7
localhost / # io -r -4 0xff320040
ff320040: 00004d5f
In general,the value should be 0x0000cd5f since the pin set in the dts.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Linus Walleij <linus.walleij at linaro.org>
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: linux-gpio at vger.kernel.org
---

 drivers/pinctrl/pinctrl-rockchip.c | 178 ++++++++++++++++++++++++++-----------
 1 file changed, 126 insertions(+), 52 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 596b869..38be9c7 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -99,6 +99,15 @@ enum rockchip_pin_drv_type {
 };
 
 /**
+ * enum type index corresponding to rockchip_pull_list arrays index.
+ */
+enum rockchip_pin_pull_type {
+	PULL_TYPE_IO_DEFAULT = 0,
+	PULL_TYPE_IO_1V8_ONLY,
+	PULL_TYPE_MAX
+};
+
+/**
  * @drv_type: drive strength variant using rockchip_perpin_drv_type
  * @offset: if initialized to -1 it will be autocalculated, by specifying
  *	    an initial offset value the relevant source offset can be reset
@@ -123,6 +132,7 @@ struct rockchip_drv {
  * @bank_num: number of the bank, to account for holes
  * @iomux: array describing the 4 iomux sources of the bank
  * @drv: array describing the 4 drive strength sources of the bank
+ * @pull_type: array describing the 4 pull type sources of the bank
  * @valid: are all necessary informations present
  * @of_node: dt node of this bank
  * @drvdata: common pinctrl basedata
@@ -143,6 +153,7 @@ struct rockchip_pin_bank {
 	u8				bank_num;
 	struct rockchip_iomux		iomux[4];
 	struct rockchip_drv		drv[4];
+	enum rockchip_pin_pull_type	pull_type[4];
 	bool				valid;
 	struct device_node		*of_node;
 	struct rockchip_pinctrl		*drvdata;
@@ -198,6 +209,31 @@ struct rockchip_pin_bank {
 		},							\
 	}
 
+#define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1,	\
+				      drv2, drv3, pull0, pull1,		\
+				      pull2, pull3)			\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+		},							\
+		.drv		= {					\
+			{ .drv_type = drv0, .offset = -1 },		\
+			{ .drv_type = drv1, .offset = -1 },		\
+			{ .drv_type = drv2, .offset = -1 },		\
+			{ .drv_type = drv3, .offset = -1 },		\
+		},							\
+		.pull_type[0] = pull0,					\
+		.pull_type[1] = pull1,					\
+		.pull_type[2] = pull2,					\
+		.pull_type[3] = pull3,					\
+	}
+
 #define PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(id, pins, label, iom0, iom1,	\
 					iom2, iom3, drv0, drv1, drv2,	\
 					drv3, offset0, offset1,		\
@@ -220,6 +256,34 @@ struct rockchip_pin_bank {
 		},							\
 	}
 
+#define PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(id, pins,	\
+					      label, iom0, iom1, iom2,  \
+					      iom3, drv0, drv1, drv2,   \
+					      drv3, offset0, offset1,   \
+					      offset2, offset3, pull0,  \
+					      pull1, pull2, pull3)	\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .type = iom0, .offset = -1 },			\
+			{ .type = iom1, .offset = -1 },			\
+			{ .type = iom2, .offset = -1 },			\
+			{ .type = iom3, .offset = -1 },			\
+		},							\
+		.drv		= {					\
+			{ .drv_type = drv0, .offset = offset0 },	\
+			{ .drv_type = drv1, .offset = offset1 },	\
+			{ .drv_type = drv2, .offset = offset2 },	\
+			{ .drv_type = drv3, .offset = offset3 },	\
+		},							\
+		.pull_type[0] = pull0,					\
+		.pull_type[1] = pull1,					\
+		.pull_type[2] = pull2,					\
+		.pull_type[3] = pull3,					\
+	}
+
 /**
  */
 struct rockchip_pin_ctrl {
@@ -1020,12 +1084,27 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
 	return ret;
 }
 
+static int rockchip_pull_list[PULL_TYPE_MAX][4] = {
+	{
+		PIN_CONFIG_BIAS_DISABLE,
+		PIN_CONFIG_BIAS_PULL_UP,
+		PIN_CONFIG_BIAS_PULL_DOWN,
+		PIN_CONFIG_BIAS_BUS_HOLD
+	},
+	{
+		PIN_CONFIG_BIAS_DISABLE,
+		PIN_CONFIG_BIAS_PULL_DOWN,
+		PIN_CONFIG_BIAS_DISABLE,
+		PIN_CONFIG_BIAS_PULL_UP
+	},
+};
+
 static int rockchip_get_pull(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;
+	int reg, ret, pull_type;
 	u8 bit;
 	u32 data;
 
@@ -1048,22 +1127,11 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
 	case RK3288:
 	case RK3368:
 	case RK3399:
+		pull_type = bank->pull_type[pin_num / 8];
 		data >>= bit;
 		data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
 
-		switch (data) {
-		case 0:
-			return PIN_CONFIG_BIAS_DISABLE;
-		case 1:
-			return PIN_CONFIG_BIAS_PULL_UP;
-		case 2:
-			return PIN_CONFIG_BIAS_PULL_DOWN;
-		case 3:
-			return PIN_CONFIG_BIAS_BUS_HOLD;
-		}
-
-		dev_err(info->dev, "unknown pull setting\n");
-		return -EIO;
+		return rockchip_pull_list[pull_type][data];
 	default:
 		dev_err(info->dev, "unsupported pinctrl type\n");
 		return -EINVAL;
@@ -1076,7 +1144,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
 	struct rockchip_pinctrl *info = bank->drvdata;
 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
 	struct regmap *regmap;
-	int reg, ret;
+	int reg, ret, i, pull_type;
 	unsigned long flags;
 	u8 bit;
 	u32 data, rmask;
@@ -1105,30 +1173,27 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
 	case RK3288:
 	case RK3368:
 	case RK3399:
+		pull_type = bank->pull_type[pin_num / 8];
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(rockchip_pull_list[pull_type]);
+			i++) {
+			if (rockchip_pull_list[pull_type][i] == pull) {
+				ret = i;
+				break;
+			}
+		}
+
+		if (ret < 0) {
+			dev_err(info->dev, "unknown pull setting %d\n", pull);
+			return ret;
+		}
+
 		spin_lock_irqsave(&bank->slock, flags);
 
 		/* enable the write to the equivalent lower bits */
 		data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
 		rmask = data | (data >> 16);
-
-		switch (pull) {
-		case PIN_CONFIG_BIAS_DISABLE:
-			break;
-		case PIN_CONFIG_BIAS_PULL_UP:
-			data |= (1 << bit);
-			break;
-		case PIN_CONFIG_BIAS_PULL_DOWN:
-			data |= (2 << bit);
-			break;
-		case PIN_CONFIG_BIAS_BUS_HOLD:
-			data |= (3 << bit);
-			break;
-		default:
-			spin_unlock_irqrestore(&bank->slock, flags);
-			dev_err(info->dev, "unsupported pull setting %d\n",
-				pull);
-			return -EINVAL;
-		}
+		data |= (ret << bit);
 
 		ret = regmap_update_bits(regmap, reg, rmask, data);
 
@@ -2552,19 +2617,24 @@ static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
 };
 
 static struct rockchip_pin_bank rk3399_pin_banks[] = {
-	PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(0, 32, "gpio0", IOMUX_SOURCE_PMU,
-					IOMUX_SOURCE_PMU,
-					IOMUX_SOURCE_PMU,
-					IOMUX_SOURCE_PMU,
-					DRV_TYPE_IO_1V8_ONLY,
-					DRV_TYPE_IO_1V8_ONLY,
-					DRV_TYPE_IO_DEFAULT,
-					DRV_TYPE_IO_DEFAULT,
-					0x0,
-					0x8,
-					-1,
-					-1
-					),
+	PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(0, 32, "gpio0",
+							 IOMUX_SOURCE_PMU,
+							 IOMUX_SOURCE_PMU,
+							 IOMUX_SOURCE_PMU,
+							 IOMUX_SOURCE_PMU,
+							 DRV_TYPE_IO_1V8_ONLY,
+							 DRV_TYPE_IO_1V8_ONLY,
+							 DRV_TYPE_IO_DEFAULT,
+							 DRV_TYPE_IO_DEFAULT,
+							 0x0,
+							 0x8,
+							 -1,
+							 -1,
+							 PULL_TYPE_IO_1V8_ONLY,
+							 PULL_TYPE_IO_1V8_ONLY,
+							 PULL_TYPE_IO_DEFAULT,
+							 PULL_TYPE_IO_DEFAULT
+							),
 	PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU,
 					IOMUX_SOURCE_PMU,
 					IOMUX_SOURCE_PMU,
@@ -2578,11 +2648,15 @@ static struct rockchip_pin_bank rk3399_pin_banks[] = {
 					0x30,
 					0x38
 					),
-	PIN_BANK_DRV_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
-			   DRV_TYPE_IO_1V8_OR_3V0,
-			   DRV_TYPE_IO_1V8_ONLY,
-			   DRV_TYPE_IO_1V8_ONLY
-			   ),
+	PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
+				      DRV_TYPE_IO_1V8_OR_3V0,
+				      DRV_TYPE_IO_1V8_ONLY,
+				      DRV_TYPE_IO_1V8_ONLY,
+				      PULL_TYPE_IO_DEFAULT,
+				      PULL_TYPE_IO_DEFAULT,
+				      PULL_TYPE_IO_1V8_ONLY,
+				      PULL_TYPE_IO_1V8_ONLY
+				      ),
 	PIN_BANK_DRV_FLAGS(3, 32, "gpio3", DRV_TYPE_IO_3V3_ONLY,
 			   DRV_TYPE_IO_3V3_ONLY,
 			   DRV_TYPE_IO_3V3_ONLY,
-- 
1.9.1



From joel at jms.id.au  Tue May 10 04:20:11 2016
From: joel at jms.id.au (Joel Stanley)
Date: Tue, 10 May 2016 20:50:11 +0930
Subject: [PATCH 2/4] drvers/clk: Support fourth generation Aspeed SoCs
In-Reply-To: <20160509224953.GZ3492@codeaurora.org>
References: <1462797111-14271-1-git-send-email-joel@jms.id.au>
 <1462797111-14271-3-git-send-email-joel@jms.id.au>
 <20160509224953.GZ3492@codeaurora.org>
Message-ID: <CACPK8Xfq=Pfy=7GYuS7LJs-CFJOimBUoHA=Y6NHb4=DRcOnvfQ@mail.gmail.com>

On Tue, May 10, 2016 at 8:19 AM, Stephen Boyd <sboyd at codeaurora.org> wrote:
> On 05/09, Joel Stanley wrote:
>> diff --git a/drivers/clk/aspeed/clk-g4.c b/drivers/clk/aspeed/clk-g4.c
>> new file mode 100644
>> index 000000000000..91677e9177f5
>> --- /dev/null
>> +++ b/drivers/clk/aspeed/clk-g4.c
>> @@ -0,0 +1,109 @@
>> +/*
>> + * Copyright 2016 IBM Corporation
>> + *
>> + * 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.
>> + */
>> +
>> +#include <linux/clk.h>
>
> Hopefully this include isn't needed.

It was required for clk_get_rate in aspeed_of_pclk_clk_init. As I
mention below, I reworked it to avoid this.

>
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/of_address.h>
>> +#include <linux/clkdev.h>
>> +
>> +static void __init aspeed_of_hpll_clk_init(struct device_node *node)
>> +{
>> +     struct clk *clk, *clkin_clk;
>> +     void __iomem *base;
>> +     int reg, rate, clkin;
>> +     const char *name = node->name;
>> +     const char *parent_name;
>> +     const int rates[][4] = {
>> +             {384, 360, 336, 408},
>> +             {400, 375, 350, 425},
>> +     };
>> +
>> +     of_property_read_string(node, "clock-output-names", &name);
>> +     parent_name = of_clk_get_parent_name(node, 0);
>> +
>> +     base = of_iomap(node, 0);
>> +     if (!base) {
>> +             pr_err("%s: of_iomap failed\n", node->full_name);
>> +             return;
>> +     }
>> +     reg = readl(base);
>> +     iounmap(base);
>> +
>> +     clkin_clk = of_clk_get(node, 0);
>> +     if (IS_ERR(clkin_clk)) {
>> +             pr_err("%s: of_clk_get failed\n", node->full_name);
>> +             return;
>> +     }
>> +
>> +     clkin = clk_get_rate(clkin_clk);
>> +
>> +     reg = (reg >> 8) & 0x2;
>> +
>> +     if (clkin == 48000000 || clkin == 24000000)
>> +             rate = rates[0][reg] * 1000000;
>> +     else if (clkin == 25000000)
>> +             rate = rates[1][reg] * 1000000;
>> +     else {
>> +             pr_err("%s: unknown clkin frequency %dHz\n",
>> +                             node->full_name, clkin);
>> +             WARN_ON(1);
>> +     }
>> +
>> +     clk = clk_register_fixed_rate(NULL, name, parent_name, 0, rate);
>
> Please write a proper clk driver that sets clkin to be the parent
> of this clk registered here and then calculates the frequency
> based on the parent clk rate and the strapping registers via the
> recalc rate callback.

After a few goes I understood what you meant here.

Is the pclk part okay? I modified the pclk part use a fixed factor
clock instead of the fixed clock, so I could drop the pclk_get_rate
call below.

> Also please move this to a platform driver
> instead of using CLK_OF_DECLARE assuming this isn't required for
> any timers in the system.

Can you clarify here? We do use the rate of pclk (the apb clock) in
the clocksource driver to calculate our count_per_tick value.

>
>> +     if (IS_ERR(clk)) {
>> +             pr_err("%s: failed to register clock\n", node->full_name);
>> +             return;
>> +     }
>> +
>> +     clk_register_clkdev(clk, NULL, name);
>
> Do you have clkdev users? If not then please drop this.

I think the answer is no. I will drop.

>> +     of_clk_add_provider(node, of_clk_src_simple_get, clk);
>> +}
>> +CLK_OF_DECLARE(aspeed_hpll_clock, "aspeed,g4-hpll-clock",
>> +            aspeed_of_hpll_clk_init);
>> +
>> +static void __init aspeed_of_apb_clk_init(struct device_node *node)
>> +{
>> +     struct clk *clk, *hpll_clk;
>> +     void __iomem *base;
>> +     int reg, rate;
>> +     const char *name = node->name;
>> +     const char *parent_name;
>> +
>> +     of_property_read_string(node, "clock-output-names", &name);
>> +     parent_name = of_clk_get_parent_name(node, 0);
>> +
>> +     base = of_iomap(node, 0);
>> +     if (!base) {
>> +             pr_err("%s: of_iomap failed\n", node->full_name);
>> +             return;
>> +     }
>> +     reg = readl(base);
>> +     iounmap(base);
>> +
>> +     hpll_clk = of_clk_get(node, 0);
>> +     if (IS_ERR(hpll_clk)) {
>> +             pr_err("%s: of_clk_get failed\n", node->full_name);
>> +             return;
>> +     }
>> +
>> +     reg = (reg >> 23) & 0x3;
>> +     rate = clk_get_rate(hpll_clk) / (2 + 2 * reg);
>> +
>> +     clk = clk_register_fixed_rate(NULL, name, parent_name, 0, rate);
>> +     if (IS_ERR(clk)) {
>> +             pr_err("%s: failed to register clock\n", node->full_name);
>> +             return;
>> +     }
>> +
>> +     clk_register_clkdev(clk, NULL, name);
>> +     of_clk_add_provider(node, of_clk_src_simple_get, clk);
>> +}
>> +CLK_OF_DECLARE(aspeed_apb_clock, "aspeed,g4-apb-clock",
>> +            aspeed_of_apb_clk_init);
>
> Following on Rob's comment, please combine this into one driver
> instead of having different DT nodes for different clks that are
> all really part of one clock controller hw block.

Ok, I have had a go at this. In our case the clock registers are part
of the "SCU" IP; a collection of disparate functions that happen to
include clock control. Is syscon the right thing to use here?

regmap = syscon_regmap_lookup_by_compatible("aspeed,ast2400-syscon-scu");
ret = regmap_read(hpll->regmap, 0x70, &reg);

Cheers,

Joel


From adrian.hunter at intel.com  Tue May 10 04:17:22 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 14:17:22 +0300
Subject: [PATCH 15/23] mmc: sdhci-esdhc-imx: support setting tuning start
 point
In-Reply-To: <1460741387-23815-16-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-16-git-send-email-aisheng.dong@nxp.com>
Message-ID: <5731C342.5060309@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> The delay cells of some SoCs may have less delay per one cell,
> for such SoCs, user could set the start delay cell point to bypass
> the first a few meaningless tuning commands.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>

Acked-by: Adrian Hunter <adrian.hunter at intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c          | 14 +++++++++++---
>  include/linux/platform_data/mmc-esdhc-imx.h |  1 +
>  2 files changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index d02db66..9f9be3f 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -75,7 +75,8 @@
>  #define ESDHC_TUNING_CTRL		0xcc
>  #define ESDHC_STD_TUNING_EN		(1 << 24)
>  /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
> -#define ESDHC_TUNING_START_TAP		0x1
> +#define ESDHC_TUNING_START_TAP_DEFAULT	0x1
> +#define ESDHC_TUNING_START_TAP_MASK	0xff
>  #define ESDHC_TUNING_STEP_MASK		0x00070000
>  #define ESDHC_TUNING_STEP_SHIFT		16
>  
> @@ -489,7 +490,12 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
>  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
>  				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> -				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP;
> +				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
> +				if (imx_data->boarddata.tuning_start_tap) {
> +					tuning_ctrl &= ~ESDHC_TUNING_START_TAP_MASK;
> +					tuning_ctrl |= imx_data->boarddata.tuning_start_tap;
> +				}
> +
>  				if (imx_data->boarddata.tuning_step) {
>  					tuning_ctrl &= ~ESDHC_TUNING_STEP_MASK;
>  					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
> @@ -975,6 +981,8 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
>  		boarddata->wp_type = ESDHC_WP_GPIO;
>  
>  	of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step);
> +	of_property_read_u32(np, "fsl,tuning-start-tap",
> +			     &boarddata->tuning_start_tap);
>  
>  	if (of_find_property(np, "no-1-8-v", NULL))
>  		boarddata->support_vsel = false;
> @@ -1197,7 +1205,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  
>  	if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
>  		writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) |
> -			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP,
> +			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT,
>  			host->ioaddr + ESDHC_TUNING_CTRL);
>  
>  	if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
> diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
> index 95ccab3..7daa78a 100644
> --- a/include/linux/platform_data/mmc-esdhc-imx.h
> +++ b/include/linux/platform_data/mmc-esdhc-imx.h
> @@ -46,5 +46,6 @@ struct esdhc_platform_data {
>  	bool support_vsel;
>  	unsigned int delay_line;
>  	unsigned int tuning_step;       /* The delay cell steps in tuning procedure */
> +	unsigned int tuning_start_tap;	/* The start delay cell point in tuning procedure */
>  };
>  #endif /* __ASM_ARCH_IMX_ESDHC_H */
> 



From joel at jms.id.au  Tue May 10 04:24:01 2016
From: joel at jms.id.au (Joel Stanley)
Date: Tue, 10 May 2016 20:54:01 +0930
Subject: [PATCH 1/2] doc/devicetree: Add Aspeed watchdog timer bindings
In-Reply-To: <20160509203831.GA20352@rob-hp-laptop>
References: <1462797277-14969-1-git-send-email-joel@jms.id.au>
 <1462797277-14969-2-git-send-email-joel@jms.id.au>
 <20160509203831.GA20352@rob-hp-laptop>
Message-ID: <CACPK8XeAhn=h=-LKjFZJ9UibnXiYLvy5R=1=FsNZJn0Hk1O36Q@mail.gmail.com>

On Tue, May 10, 2016 at 6:08 AM, Rob Herring <robh at kernel.org> wrote:
> On Mon, May 09, 2016 at 10:04:36PM +0930, Joel Stanley wrote:
>> Signed-off-by: Joel Stanley <joel at jms.id.au>
>> ---
>>  Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt | 14 ++++++++++++++
>>  1 file changed, 14 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
>>
>> diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
>> new file mode 100644
>> index 000000000000..58184b161e0d
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
>> @@ -0,0 +1,14 @@
>> +Aspeed Watchdog Timer
>> +
>> +Required properties:
>> + - compatible: must be "aspeed,wdt"
>
> This should have the specific SOCs listed.

Thanks, I'll fix it.

In the cases where the drivers had no change in the IP between
versions of the soc I wondered if it was neater to have a generic
string. You're saying that's wrong and we prefer using multiple
strings for all the SoCs instead?

>> +     wdt1: wdt at 1e785000 {
>
> IIRC, "watchdog at ..." is the correct generic name.

Cheers,

Joel


From adrian.hunter at intel.com  Tue May 10 04:19:40 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 14:19:40 +0300
Subject: [PATCH 18/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for
 STD_TUNING
In-Reply-To: <1460741387-23815-19-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-19-git-send-email-aisheng.dong@nxp.com>
Message-ID: <5731C3CC.1000806@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> Enable HW auto retuning when set SDHCI_CTRL_EXEC_TUNING and clear it
> when clear SDHCI_CTRL_TUNED_CLK.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>

I presume this patch should wait for patch 17, but nevertheless:

Acked-by: Adrian Hunter <adrian.hunter at intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 9f9be3f..a582a83 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -44,6 +44,7 @@
>  #define  ESDHC_MIX_CTRL_AC23EN		(1 << 7)
>  #define  ESDHC_MIX_CTRL_EXE_TUNE	(1 << 22)
>  #define  ESDHC_MIX_CTRL_SMPCLK_SEL	(1 << 23)
> +#define  ESDHC_MIX_CTRL_AUTO_TUNE_EN	(1 << 24)
>  #define  ESDHC_MIX_CTRL_FBCLK_SEL	(1 << 25)
>  #define  ESDHC_MIX_CTRL_HS400_EN	(1 << 26)
>  /* Bits 3 and 6 are not SDHCI standard definitions */
> @@ -484,11 +485,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  			} else {
>  				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
>  				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
> +				m &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
>  			}
>  
>  			if (val & SDHCI_CTRL_EXEC_TUNING) {
>  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
>  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
> +				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
>  				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
>  				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
>  				if (imx_data->boarddata.tuning_start_tap) {
> 



From lee.jones at linaro.org  Tue May 10 04:26:22 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Tue, 10 May 2016 12:26:22 +0100
Subject: [RFC PATCH 01/21] mfd: uniphier: add UniPhier MFD driver
In-Reply-To: <1462873862-30940-2-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
 <1462873862-30940-2-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <20160510112622.GL19473@dell>

On Tue, 10 May 2016, Masahiro Yamada wrote:

> This MFD driver populates child devices such clock, reset, and other
> system controlling blocks.
> 
> On UniPhier SoCs, one system control block contains various registers
> for clock, reset, and others in it.  So, it is not reasonable to have
> separate DT nodes for different sub-systems.
> 
> This MFD approach modifies Device Tree source just once for adding
> an MFD node.
> 
> This series is just for review.
> Please do not apply this patch.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> ---
> 
>  MAINTAINERS                |   1 +
>  drivers/mfd/Kconfig        |   9 ++
>  drivers/mfd/Makefile       |   1 +
>  drivers/mfd/uniphier-mfd.c | 214 +++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 225 insertions(+)
>  create mode 100644 drivers/mfd/uniphier-mfd.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 87b2ddd..8c987ca 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1728,6 +1728,7 @@ F:	arch/arm/mm/cache-uniphier.c
>  F:	arch/arm64/boot/dts/socionext/
>  F:	drivers/bus/uniphier-system-bus.c
>  F:	drivers/i2c/busses/i2c-uniphier*
> +F:	drivers/mfd/uniphier-mfd.c
>  F:	drivers/mmc/host/uniphier-sd.c
>  F:	drivers/pinctrl/uniphier/
>  F:	drivers/tty/serial/8250/8250_uniphier.c
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index eea61e3..ea85862 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -892,6 +892,15 @@ config MFD_SKY81452
>  	  This driver can also be built as a module.  If so, the module
>  	  will be called sky81452.
>  
> +config MFD_UNIPHIER
> +	tristate "Socionext UniPhier MFD"
> +	depends on ARCH_UNIPHIER || COMPILE_TEST
> +	default ARCH_UNIPHIER
> +	select MFD_CORE
> +	help
> +	  Support for the System Control Block, Media I/O Control Block,
> +	  Peripheral Control Block available on UniPhier SoCs.
> +
>  config MFD_SMSC
>         bool "SMSC ECE1099 series chips"
>         depends on I2C=y
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 5eaa6465d..5e8c20c 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -198,6 +198,7 @@ obj-$(CONFIG_MFD_HI6421_PMIC)	+= hi6421-pmic-core.o
>  obj-$(CONFIG_MFD_DLN2)		+= dln2.o
>  obj-$(CONFIG_MFD_RT5033)	+= rt5033.o
>  obj-$(CONFIG_MFD_SKY81452)	+= sky81452.o
> +obj-$(CONFIG_MFD_UNIPHIER)	+= uniphier-mfd.o
>  
>  intel-soc-pmic-objs		:= intel_soc_pmic_core.o intel_soc_pmic_crc.o
>  intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC)	+= intel_soc_pmic_bxtwc.o
> diff --git a/drivers/mfd/uniphier-mfd.c b/drivers/mfd/uniphier-mfd.c
> new file mode 100644
> index 0000000..7f01d64
> --- /dev/null
> +++ b/drivers/mfd/uniphier-mfd.c
> @@ -0,0 +1,214 @@
> +/*
> + * Copyright (C) 2016 Socionext Inc.
> + *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
> + *
> + * 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/mfd/core.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +static const struct mfd_cell uniphier_ld4_sysctrl_cells[] = {
> +	{ .name = "uniphier-ld4-clk" },
> +	{ .name = "uniphier-ld4-reset" },
> +	{ /* sentinel */ }
> +};
> +
> +static const struct mfd_cell uniphier_pro4_sysctrl_cells[] = {
> +	{ .name = "uniphier-pro4-clk" },
> +	{ .name = "uniphier-pro4-reset" },
> +	{ /* sentinel */ }
> +};
> +
> +static const struct mfd_cell uniphier_sld8_sysctrl_cells[] = {
> +	{ .name = "uniphier-sld8-clk" },
> +	{ .name = "uniphier-sld8-reset" },
> +	{ /* sentinel */ }
> +};
> +
> +static const struct mfd_cell uniphier_pro5_sysctrl_cells[] = {
> +	{ .name = "uniphier-pro5-clk" },
> +	{ .name = "uniphier-pro5-reset" },
> +	{ /* sentinel */ }
> +};
> +
> +static const struct mfd_cell uniphier_pxs2_sysctrl_cells[] = {
> +	{ .name = "uniphier-pxs2-clk" },
> +	{ .name = "uniphier-pxs2-reset" },
> +	{ /* sentinel */ }
> +};
> +
> +static const struct mfd_cell uniphier_ld11_sysctrl_cells[] = {
> +	{ .name = "uniphier-ld11-clk" },
> +	{ .name = "uniphier-ld11-reset" },
> +	{ /* sentinel */ }
> +};
> +
> +static const struct mfd_cell uniphier_ld20_sysctrl_cells[] = {
> +	{ .name = "uniphier-ld20-clk" },
> +	{ .name = "uniphier-ld20-reset" },
> +	{ /* sentinel */ }
> +};
> +
> +static const struct mfd_cell uniphier_ld4_mioctrl_cells[] = {
> +	{ .name = "uniphier-ld4-mio-clk" },
> +	{ .name = "uniphier-ld4-mio-reset" },
> +	{ /* sentinel */ }
> +};
> +
> +static const struct mfd_cell uniphier_pro5_mioctrl_cells[] = {
> +	{ .name = "uniphier-pro5-mio-clk" },
> +	{ .name = "uniphier-pro5-mio-reset" },
> +	{ /* sentinel */ }
> +};
> +
> +static const struct mfd_cell uniphier_ld4_perictrl_cells[] = {
> +	{ .name = "uniphier-ld4-peri-clk" },
> +	{ .name = "uniphier-ld4-peri-reset" },
> +	{ /* sentinel */ }
> +};
> +
> +static const struct mfd_cell uniphier_pro4_perictrl_cells[] = {
> +	{ .name = "uniphier-pro4-peri-clk" },
> +	{ .name = "uniphier-pro4-peri-reset" },
> +	{ /* sentinel */ }
> +};
> +
> +static const struct of_device_id uniphier_mfd_match[] = {
> +	/* System Control */
> +	{
> +		.compatible = "socionext,uniphier-ld4-sysctrl",
> +		.data = uniphier_ld4_sysctrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-pro4-sysctrl",
> +		.data = uniphier_pro4_sysctrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-sld8-sysctrl",
> +		.data = uniphier_sld8_sysctrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-pro5-sysctrl",
> +		.data = uniphier_pro5_sysctrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-pxs2-sysctrl",
> +		.data = uniphier_pxs2_sysctrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-ld11-sysctrl",
> +		.data = uniphier_ld11_sysctrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-ld20-sysctrl",
> +		.data = uniphier_ld20_sysctrl_cells,
> +	},
> +	/* Media I/O */
> +	{
> +		.compatible = "socionext,uniphier-ld4-mioctrl",
> +		.data = uniphier_ld4_mioctrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-pro4-mioctrl",
> +		.data = uniphier_ld4_mioctrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-sld8-mioctrl",
> +		.data = uniphier_ld4_mioctrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-pro5-mioctrl",
> +		.data = uniphier_pro5_mioctrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-pxs2-mioctrl",
> +		.data = uniphier_pro5_mioctrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-ld11-mioctrl",
> +		.data = uniphier_ld4_mioctrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-ld20-mioctrl",
> +		.data = uniphier_pro5_mioctrl_cells,
> +	},
> +	/* Peripheral Control */
> +	{
> +		.compatible = "socionext,uniphier-ld4-perictrl",
> +		.data = uniphier_ld4_perictrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-sld8-perictrl",
> +		.data = uniphier_ld4_perictrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-pro4-perictrl",
> +		.data = uniphier_pro4_perictrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-pro5-perictrl",
> +		.data = uniphier_pro4_perictrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-pxs2-perictrl",
> +		.data = uniphier_pro4_perictrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-ld11-perictrl",
> +		.data = uniphier_pro4_perictrl_cells,
> +	},
> +	{
> +		.compatible = "socionext,uniphier-ld20-perictrl",
> +		.data = uniphier_pro4_perictrl_cells,
> +	},
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, uniphier_mfd_match);

NACK.  Please do not mix MFD and DT registration.

> +static int uniphier_mfd_probe(struct platform_device *pdev)
> +{
> +	const struct of_device_id *match;
> +	const struct mfd_cell *cell;
> +	int ret;
> +	int n_cells = 0;
> +
> +	match = of_match_node(uniphier_mfd_match, pdev->dev.of_node);
> +	if (!match)
> +		return -ENODEV;
> +
> +	cell = match->data;
> +
> +	for (; cell->name; cell++)
> +		n_cells++;
> +
> +	ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, match->data,
> +			      n_cells, NULL, 0, NULL);
> +	if (ret)
> +		dev_err(&pdev->dev, "failed to add MFD devices\n");
> +
> +	return ret;
> +}

This driver is not required.

I think you just need to use "simple-mfd".

> +static struct platform_driver uniphier_mfd_driver = {
> +	.probe = uniphier_mfd_probe,
> +	.driver = {
> +		.name = "uniphier-mfd",
> +		.of_match_table = uniphier_mfd_match,
> +	},
> +};
> +module_platform_driver(uniphier_mfd_driver);
> +
> +MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
> +MODULE_DESCRIPTION("UniPhier SoC MFD Driver");
> +MODULE_LICENSE("GPL");

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


From adrian.hunter at intel.com  Tue May 10 04:24:40 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 14:24:40 +0300
Subject: [PATCH 19/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for
 MAN_TUNING
In-Reply-To: <1460741387-23815-20-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-20-git-send-email-aisheng.dong@nxp.com>
Message-ID: <5731C4F8.4070604@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> Indicating hw auto retuning support for mx6qdl in the fake caps_1
> register and enable auto retuning in post_tuning process after
> tuning completes.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>

I presume this patch should wait for patch 17, but nevertheless:

Acked-by: Adrian Hunter <adrian.hunter at intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index a582a83..07b1144 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -301,7 +301,8 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
>  				/* imx6q/dl does not have cap_1 register, fake one */
>  				val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
>  					| SDHCI_SUPPORT_SDR50
> -					| SDHCI_USE_SDR50_TUNING;
> +					| SDHCI_USE_SDR50_TUNING
> +					| (SDHCI_TUNING_MODE_3 << SDHCI_RETUNING_MODE_SHIFT);
>  
>  			if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
>  				val |= SDHCI_SUPPORT_HS400;
> @@ -471,10 +472,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  		writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
>  		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
>  			new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
> -			if (val & SDHCI_CTRL_TUNED_CLK)
> +			if (val & SDHCI_CTRL_TUNED_CLK) {
>  				new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL;
> -			else
> +				new_val |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> +			} else {
>  				new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
> +				new_val &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> +			}
>  			writel(new_val , host->ioaddr + ESDHC_MIX_CTRL);
>  		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
>  			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
> @@ -760,6 +764,7 @@ static void esdhc_post_tuning(struct sdhci_host *host)
>  
>  	reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
>  	reg &= ~ESDHC_MIX_CTRL_EXE_TUNE;
> +	reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
>  	writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
>  }
>  
> 



From arnd at arndb.de  Tue May 10 04:48:06 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 13:48:06 +0200
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <5731AE2E.2050403@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <9651510.pg5Vmm8vKS@wuerfel> <5731AE2E.2050403@huawei.com>
Message-ID: <7091358.aJt1stteb5@wuerfel>

On Tuesday 10 May 2016 17:47:26 Zhangjian wrote:
> On 2016/5/10 16:36, Arnd Bergmann wrote:
> > On Tuesday 10 May 2016 15:42:07 Zhangjian wrote:
> >> On 2016/5/6 20:37, Yury Norov wrote:
> 
> "include/uapi/asm-generic/posix_types.h" is uapi, we could not check
> "ARCH_32BIT_OFF_T" here. Besides, the `__kernel_long_t` is long which
> mean it is 32bit in ILP32. should we define something like x32?
>      ```
>      diff --git a/arch/arm64/include/uapi/asm/posix_types.h b/arch/arm64/include/uapi/asm/posix_types.h
>      index 7985ff6..9baa8d3 100644
>      --- a/arch/arm64/include/uapi/asm/posix_types.h
>      +++ b/arch/arm64/include/uapi/asm/posix_types.h

glibc does not use the definition of __kernel_off_t, it has its own
copy, so changing the kernel headers would do nothing.

>      @@ -5,6 +5,9 @@ typedef unsigned short __kernel_old_uid_t;
>       typedef unsigned short __kernel_old_gid_t;
>        #define __kernel_old_uid_t __kernel_old_uid_t
> 
>       +typedef long long __kernel_long_t;
>       +typedef unsigned long long __kernel_ulong_t;
>       +
>        #include <asm-generic/posix_types.h>
> 
>        #endif /*  __ASM_POSIX_TYPES_H */u
>      ```

This would break all sorts of things, because __kernel_long_t/__kernel_ulong_t
are not just used for off_t but also other things.

> 
> On the other hand, glibc define it own off_t in "bits/types.h":
>      __STD_TYPE __OFF_T_TYPE __off_t;        /* Type of file sizes and offsets.  */
>      __STD_TYPE __OFF64_T_TYPE __off64_t;    /* Type of file sizes and offsets (LFS).  */
> 
> in "sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h":
>      #define __OFF_T_TYPE            __SLONGWORD_TYPE
>      #define __OFF64_T_TYPE          __SQUAD_TYPE
> 
> If we define off_t as 64bit in glibc:
>      #define __OFF_T_TYPE           __SQUAD_TYPE
> 
> Should We need to align all the off_t syscall to 64bit syscall in
> kernel?
> 

Yes, this is the change that I think we need to make, along with
the same change for __INO_T_TYPE and 

#define __OFF_T_MATCHES_OFF64_T        1
#define __INO_T_MATCHES_INO64_T        1

If I read the rest of the glibc headers right, that should be all we need
to ensure that both off_t and off64_t match the __kernel_loff_t based
syscalls.

	Arnd


From linus.walleij at linaro.org  Tue May 10 04:50:11 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 10 May 2016 13:50:11 +0200
Subject: [PATCH] pinctrl: stm32: Implement .pin_config_dbg_show()
In-Reply-To: <1461939943-24752-1-git-send-email-patrice.chotard@st.com>
References: <1461939943-24752-1-git-send-email-patrice.chotard@st.com>
Message-ID: <CACRpkdZ=KsPL1mBS1bLi=jYsv=Vb1QNBi8XPAJW50doPcwBuZg@mail.gmail.com>

On Fri, Apr 29, 2016 at 4:25 PM,  <patrice.chotard at st.com> wrote:

> From: Patrice Chotard <patrice.chotard at st.com>
>
> Signed-off-by: Patrice Chotard <patrice.chotard at st.com>

Patch applied! Because this gives good debuggability.

But think about refactorings:

> +static bool stm32_pconf_input_get(struct stm32_gpio_bank *bank,
> +       unsigned int offset)
> +{
> +       unsigned long flags;
> +       u32 val;
> +
> +       clk_enable(bank->clk);
> +       spin_lock_irqsave(&bank->lock, flags);
> +
> +       val = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset));
> +
> +       spin_unlock_irqrestore(&bank->lock, flags);
> +       clk_disable(bank->clk);
> +
> +       return val;
> +}
> +
> +static bool stm32_pconf_output_get(struct stm32_gpio_bank *bank,
> +       unsigned int offset)
> +{
> +       unsigned long flags;
> +       u32 val;
> +
> +       clk_enable(bank->clk);
> +       spin_lock_irqsave(&bank->lock, flags);
> +       val = !!(readl_relaxed(bank->base + STM32_GPIO_ODR) & BIT(offset));
> +
> +       spin_unlock_irqrestore(&bank->lock, flags);
> +       clk_disable(bank->clk);
> +
> +       return val;
> +}

Don't you think these two look very similar for example.

But that can be fixed later, debuggability is more important.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 10 04:52:54 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 10 May 2016 13:52:54 +0200
Subject: [RFC v5 3/4] gpio: move clps711x, moxart,
 ts4800 and gpio-ge into gpio-generic
In-Reply-To: <1518049.pLhlI1cuZi@debian64>
References: <cover.1461888822.git.chunkeey@googlemail.com>
 <9e5cc9e957144bd5d4081573ef959f931281eaaa.1461888822.git.chunkeey@googlemail.com>
 <CACRpkdaX1xeGJxV9K-GkTAh87SctqyhkJ+VN6mwUdtD19tz99g@mail.gmail.com>
 <1518049.pLhlI1cuZi@debian64>
Message-ID: <CACRpkdbXM2Bnzv_qTwz6sWkpCgx3q2ihiEMbeb+5DJj+DT+GAw@mail.gmail.com>

On Fri, Apr 29, 2016 at 9:06 PM, Christian Lamparter
<chunkeey at googlemail.com> wrote:
> On Friday, April 29, 2016 04:18:20 PM Linus Walleij wrote:

>> Very elegant. Let's wait for some feedback/ACKs from
>> the driver maintainers, but this looks very nice.

> Oh by the way: who's maintaining them? get_maintainer.pl just
> lists the usual gpio people.

I usually just git log drivers/gpio/gpio-foo.c
and see what turns up, then sift out to avoid any generic
maintenance patches and mail the remaining people who
made real functional changes and seem  to be using the
real hardware.

> Anyway, I'll rebase my patch series (without the two patches you
> had already merged)

Awesome.

>> Do you want to address Andy's optimization suggestion directly
>> or as a follow-on patch?
>
> Oh, this is a RFC. I didn't expect anything to be merged just yet.
> Of course, I'll try to integrate his suggestion. I'll do that once
> I reply to Rob/Mark/You about the "linux,gpio-mmio",
> "memory-mapped-gpio" situation etc.

True, OK no hurries, I just liked the patches a lot.

Yours,
Linus Walleij


From alexandre.belloni at free-electrons.com  Tue May 10 04:52:58 2016
From: alexandre.belloni at free-electrons.com (Alexandre Belloni)
Date: Tue, 10 May 2016 13:52:58 +0200
Subject: [PATCH 0/2] mtd: atmel_nand: remove compatible "atmel,sama5d4-nfc"
In-Reply-To: <B256D81BAE5131468A838E5D7A243641D6487F5A@penmbx01>
References: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
 <20160509201324.GA9845@rob-hp-laptop>
 <B256D81BAE5131468A838E5D7A243641D6487F5A@penmbx01>
Message-ID: <20160510115258.GS2890@piout.net>

On 10/05/2016 at 04:50:37 +0000, Yang, Wenyou wrote :
> 
> 
> > -----Original Message-----
> > From: Rob Herring [mailto:robh at kernel.org]
> > Sent: 2016?5?10? 4:13
> > To: Yang, Wenyou <Wenyou.Yang at atmel.com>
> > Cc: Brian Norris <computersforpeace at gmail.com>; David Woodhouse
> > <dwmw2 at infradead.org>; Pawel Moll <pawel.moll at arm.com>; Mark Brown
> > <broonie at kernel.org>; Ian Campbell <ijc+devicetree at hellion.org.uk>; Kumar
> > Gala <galak at codeaurora.org>; linux-kernel at vger.kernel.org; linux-
> > mtd at lists.infradead.org; devicetree at vger.kernel.org; Ferre, Nicolas
> > <Nicolas.FERRE at atmel.com>; Alexandre Belloni <alexandre.belloni at free-
> > electrons.com>; Jean-Christophe Plagniol-Villard <plagnioj at jcrosoft.com>;
> > Russell King <linux at arm.linux.org.uk>; Josh Wu <rainyfeeling at outlook.com>;
> > linux-arm-kernel at lists.infradead.org
> > Subject: Re: [PATCH 0/2] mtd: atmel_nand: remove compatible "atmel,sama5d4-
> > nfc"
> > 
> > On Mon, May 09, 2016 at 02:51:17PM +0800, Wenyou Yang wrote:
> > > It is a datasheet bug, for current SoCs, the RB_EDGE3(i.e. bit 27) of
> > > HSMC_SR register does not exist, the RB_EDGE0 (i.e. bit 24) is the
> > > ready/busy line edge status bit. So the compatible "atmel,sama5d4-nfc"
> > > is unneeded.
> > 
> > The compatible is needed if the SOC still exists. You can list both for the sama5d4
> > if the block is the same.
> 
> The NFC IP of SAMA5D4 is same as SAMA5D2's, SAMA5D4 hase this issue.  This compatible can be removed. 
> 

Well, I agree with Rob, we don't remove an existing compatible. Simply
make it do the right thing (i.e. the same as sama5d3-nfc).

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com


From linus.walleij at linaro.org  Tue May 10 04:58:26 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 10 May 2016 13:58:26 +0200
Subject: [PATCH v8 1/3] gpio: dt-bindings: add wd,mbl-gpio bindings
In-Reply-To: <9bc9349d6e13d81c6200b0cd8fa20c76263043f6.1462543458.git.chunkeey@googlemail.com>
References: <cover.1462543457.git.chunkeey@googlemail.com>
 <9bc9349d6e13d81c6200b0cd8fa20c76263043f6.1462543458.git.chunkeey@googlemail.com>
Message-ID: <CACRpkdbqifjgD0hV+mV5bwu-LKmX8huMQhpJQ4wUCXmXZeSfyQ@mail.gmail.com>

On Sun, May 8, 2016 at 3:08 PM, Christian Lamparter
<chunkeey at googlemail.com> wrote:

> This patch adds the device tree bindings for the Western Digital's
> MyBook Live memory-mapped GPIO controllers.
>
> The gpios will be supported by gpio-mmio code of the
> GPIO generic library.
>
> Acked-by: Rob Herring <robh at kernel.org>
> Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>

Looks OK to me and Rob has ACKed so patch applied.

Yours,
Linus Walleij


From patrice.chotard at st.com  Tue May 10 05:00:01 2016
From: patrice.chotard at st.com (Patrice Chotard)
Date: Tue, 10 May 2016 14:00:01 +0200
Subject: [PATCH] pinctrl: stm32: Implement .pin_config_dbg_show()
In-Reply-To: <CACRpkdZ=KsPL1mBS1bLi=jYsv=Vb1QNBi8XPAJW50doPcwBuZg@mail.gmail.com>
References: <1461939943-24752-1-git-send-email-patrice.chotard@st.com>
 <CACRpkdZ=KsPL1mBS1bLi=jYsv=Vb1QNBi8XPAJW50doPcwBuZg@mail.gmail.com>
Message-ID: <5731CD41.60506@st.com>



On 05/10/2016 01:50 PM, Linus Walleij wrote:
> On Fri, Apr 29, 2016 at 4:25 PM,  <patrice.chotard at st.com> wrote:
>
>> From: Patrice Chotard <patrice.chotard at st.com>
>>
>> Signed-off-by: Patrice Chotard <patrice.chotard at st.com>
> Patch applied! Because this gives good debuggability.
>
> But think about refactorings:
>
>> +static bool stm32_pconf_input_get(struct stm32_gpio_bank *bank,
>> +       unsigned int offset)
>> +{
>> +       unsigned long flags;
>> +       u32 val;
>> +
>> +       clk_enable(bank->clk);
>> +       spin_lock_irqsave(&bank->lock, flags);
>> +
>> +       val = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset));
>> +
>> +       spin_unlock_irqrestore(&bank->lock, flags);
>> +       clk_disable(bank->clk);
>> +
>> +       return val;
>> +}
>> +
>> +static bool stm32_pconf_output_get(struct stm32_gpio_bank *bank,
>> +       unsigned int offset)
>> +{
>> +       unsigned long flags;
>> +       u32 val;
>> +
>> +       clk_enable(bank->clk);
>> +       spin_lock_irqsave(&bank->lock, flags);
>> +       val = !!(readl_relaxed(bank->base + STM32_GPIO_ODR) & BIT(offset));
>> +
>> +       spin_unlock_irqrestore(&bank->lock, flags);
>> +       clk_disable(bank->clk);
>> +
>> +       return val;
>> +}
Hi Linus

> Don't you think these two look very similar for example.

You 're right, i will rework this in a separate patch

Thanks

Patrice

>
> But that can be fixed later, debuggability is more important.
>
> Yours,
> Linus Walleij



From arnd at arndb.de  Tue May 10 05:04:27 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:04:27 +0200
Subject: [GIT PULL 3/4] DaVinci defconfig updates for v4.7
In-Reply-To: <1461931627-27761-3-git-send-email-nsekhar@ti.com>
References: <1461931627-27761-1-git-send-email-nsekhar@ti.com>
 <1461931627-27761-3-git-send-email-nsekhar@ti.com>
Message-ID: <15822980.FnPGKL4Ohd@wuerfel>

On Friday 29 April 2016 17:37:06 Sekhar Nori wrote:
> Some defconfig updates to support systemd
> based filesystems, SPI NOR and GPIO sysfs
> entries.
> 

Merged into next/defconfig, thanks!

	Arnd


From peng.fan at nxp.com  Tue May 10 05:04:51 2016
From: peng.fan at nxp.com (Peng Fan)
Date: Tue, 10 May 2016 12:04:51 +0000
Subject: [PATCH V2 3/3] nvmem: imx-ocotp: handling clock
In-Reply-To: <5731B891.4040303@linaro.org>
References: <1461173177-11930-1-git-send-email-van.freenix@gmail.com>
 <1461173177-11930-3-git-send-email-van.freenix@gmail.com>
 <5730825E.5030101@linaro.org> <20160509124140.GA20259@linux-7smt.suse>
 <5731B891.4040303@linaro.org>
Message-ID: <HE1PR0401MB1801F1B547E4C694FDF1E9D388710@HE1PR0401MB1801.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: linux-kernel-owner at vger.kernel.org [mailto:linux-kernel-
> owner at vger.kernel.org] On Behalf Of Srinivas Kandagatla
> Sent: Tuesday, May 10, 2016 6:32 PM
> To: Peng Fan <van.freenix at gmail.com>
> Cc: shawnguo at kernel.org; maxime.ripard at free-electrons.com; linux-arm-
> kernel at lists.infradead.org; devicetree at vger.kernel.org; linux-
> kernel at vger.kernel.org
> Subject: Re: [PATCH V2 3/3] nvmem: imx-ocotp: handling clock
> 
> 
> 
> On 09/05/16 13:41, Peng Fan wrote:
> > Hi Srinivas,
> >
> > On Mon, May 09, 2016 at 01:28:14PM +0100, Srinivas Kandagatla wrote:
> >> Thanks for the Ping, I totally missed this thread.
> >>
> >> On 20/04/16 18:26, Peng Fan wrote:
> >>> Before access ocotp nvmem area, the clock should be enabled.
> >>> Or, `hexdump nvmem` will hang the system. So, use such flow:
> >>> "
> >>>    1. clock_enable_prepare
> >>>    2. read nvmem ocotp area
> >>>    3. clock_disable_unprepare
> >>> "
> >>>
> >>> Signed-off-by: Peng Fan <van.freenix at gmail.com>
> >>> Cc: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
> >>> Cc: Maxime Ripard <maxime.ripard at free-electrons.com>
> >>> Cc: Shawn Guo <shawnguo at kernel.org>
> >>> ---
> >>>
> >>> V2:
> >>>   Follow Fabio's comments, check return value of clk_prepare_enable
> >>>
> >>>   drivers/nvmem/imx-ocotp.c | 16 +++++++++++++++-
> >>>   1 file changed, 15 insertions(+), 1 deletion(-)
> >>
> >> Changes to the driver looks good to me, Only one comment, As the
> >> clock property is now made mandatory, you should update the
> >> dt-bindings with this info too.
> >
> > In Documentation/devicetree/bindings/nvmem/imx-ocotp.txt,
> > the clock property is already marked Required properties:
> 
> Ok, I can take this patch, dt patch should go via the dt maintainers.

Thanks, Srinivas.

Shawn,

Will you review and pick up the other two patches, since changes to i.MX dts files?

https://lkml.org/lkml/2016/4/20/150          arm: dts: imx6qdl: add clocks property for ocotp node  
https://lkml.org/lkml/2016/4/20/153          arm: dts: imx6sl: add clocks property for ocotp node

Thanks,
Peng.
> 
> thanks,
> --srini


From arnd at arndb.de  Tue May 10 05:05:48 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:05:48 +0200
Subject: [GIT PULL] ARM: mvebu: defconfig for v4.7 (#2)
In-Reply-To: <87pot8sct4.fsf@free-electrons.com>
References: <87pot8sct4.fsf@free-electrons.com>
Message-ID: <13443700.NUC16SCx6V@wuerfel>

On Friday 29 April 2016 16:35:19 Gregory CLEMENT wrote:
> mvebu defconfig for 4.7 (part 2)
> 
> - enable AP806 and CP110 syscon driver in arm64 defconfig
> 
> 

Merged into next/defconfig, thanks!

	Arnd


From arnd at arndb.de  Tue May 10 05:06:27 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:06:27 +0200
Subject: [GIT PULL] ARM: tegra: Default configuration updates for v4.7-rc1
In-Reply-To: <1461946869-26124-4-git-send-email-thierry.reding@gmail.com>
References: <1461946869-26124-4-git-send-email-thierry.reding@gmail.com>
Message-ID: <4297244.MnIqCWq68v@wuerfel>

On Friday 29 April 2016 18:21:09 Thierry Reding wrote:
> ARM: tegra: Default configuration updates for v4.7-rc1
> 
> Enable the XUSB pad controller and XUSB controller drivers on the Tegra
> and multi-v7 default configurations.
> 
> 

Pulled into next/defconfig, thanks!

	Arnd


From christoffer.dall at linaro.org  Tue May 10 05:08:06 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 10 May 2016 14:08:06 +0200
Subject: [PATCH v3 15/55] KVM: arm/arm64: vgic-new: Implement virtual IRQ
 injection
In-Reply-To: <1462531568-9799-16-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-16-git-send-email-andre.przywara@arm.com>
Message-ID: <20160510120806.GC27623@cbox>

On Fri, May 06, 2016 at 11:45:28AM +0100, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> Provide a vgic_queue_irq() function which decides whether a given
> IRQ needs to be queued to a VCPU's ap_list.
> This should be called whenever an IRQ becomes pending or enabled,
> either as a result of userspace injection, from in-kernel emulated
> devices like the architected timer or from MMIO accesses to the
> distributor emulation.
> Also provides the necessary functions to allow userland to inject an
> IRQ to a guest.
> Since this is the first code that starts using our locking mechanism, we
> add some (hopefully) clear documentation of our locking strategy and
> requirements along with this patch.
> 
> [Andre: refactor out vgic_queue_irq_unlock()]
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - add spinlock checks protected by CONFIG_DEBUG_SPINLOCK
> - add more comments to vgic_target_oracle
> - remove BUG_ON() if IRQ is neither edge or level
> - rename vgic_queue_irq() to vgic_queue_irq_unlock()
> - simplify initial check in vgic_queue_irq_unlock()
> - extend retry loop to ask the oracle again
> - minor comment fixes
> 
> Changelog v1 .. v2:
> - move most IRQ injection code into vgic_update_irq_pending()
> 
>  include/kvm/vgic/vgic.h  |   3 +
>  virt/kvm/arm/vgic/vgic.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h |   1 +
>  3 files changed, 213 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 39933ee..2bfb42c 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -181,6 +181,9 @@ struct vgic_cpu {
>  	u64 live_lrs;
>  };
>  
> +int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
> +			bool level);
> +
>  #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
>  #define vgic_initialized(k)	(false)
>  #define vgic_ready(k)		((k)->arch.vgic.ready)
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index fb45537..92b78a0 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -19,8 +19,31 @@
>  
>  #include "vgic.h"
>  
> +#define CREATE_TRACE_POINTS
> +#include "../trace.h"
> +
> +#ifdef CONFIG_DEBUG_SPINLOCK
> +#define DEBUG_SPINLOCK_BUG_ON(p) BUG_ON(p)
> +#else
> +#define DEBUG_SPINLOCK_BUG_ON(p)
> +#endif
> +
>  struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
>  
> +/*
> + * Locking order is always:
> + *   vgic_cpu->ap_list_lock
> + *     vgic_irq->irq_lock
> + *
> + * (that is, always take the ap_list_lock before the struct vgic_irq lock).
> + *
> + * When taking more than one ap_list_lock at the same time, always take the
> + * lowest numbered VCPU's ap_list_lock first, so:
> + *   vcpuX->vcpu_id < vcpuY->vcpu_id:
> + *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
> + *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
> + */
> +
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid)
>  {
> @@ -39,3 +62,189 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  	WARN(1, "Looking up struct vgic_irq for reserved INTID");
>  	return NULL;
>  }
> +
> +/**
> + * kvm_vgic_target_oracle - compute the target vcpu for an irq
> + *
> + * @irq:	The irq to route. Must be already locked.
> + *
> + * Based on the current state of the interrupt (enabled, pending,
> + * active, vcpu and target_vcpu), compute the next vcpu this should be
> + * given to. Return NULL if this shouldn't be injected at all.
> + *
> + * Requires the IRQ lock to be held.
> + */
> +static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
> +{
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
> +
> +	/* If the interrupt is active, it must stay on the current vcpu */
> +	if (irq->active)
> +		return irq->vcpu;
> +
> +	/*
> +	 * If the IRQ is not active but enabled and pending, we should direct
> +	 * it to its configured target VCPU.
> +	 */
> +	if (irq->enabled && irq->pending)
> +		return irq->target_vcpu;
> +
> +	/* If neither active nor pending and enabled, then this IRQ should not
> +	 * be queued to any VCPU.
> +	 */
> +	return NULL;
> +}
> +
> +/*
> + * Only valid injection if changing level for level-triggered IRQs or for a
> + * rising edge.
> + */
> +static bool vgic_validate_injection(struct vgic_irq *irq, bool level)
> +{
> +	switch (irq->config) {
> +	case VGIC_CONFIG_LEVEL:
> +		return irq->line_level != level;
> +	case VGIC_CONFIG_EDGE:
> +		return level;
> +	}
> +
> +	return false;
> +}
> +
> +/*
> + * Check whether an IRQ needs to (and can) be queued to a VCPU's ap list.
> + * Do the queuing if necessary, taking the right locks in the right order.
> + * Returns true when the IRQ was queued, false otherwise.
> + *
> + * Needs to be entered with the IRQ lock already held, but will return
> + * with all locks dropped.
> + */
> +bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq)
> +{
> +	struct kvm_vcpu *vcpu;
> +
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
> +
> +retry:
> +	vcpu = vgic_target_oracle(irq);
> +	if (irq->vcpu || !vcpu) {
> +		/*
> +		 * If this IRQ is already on a VCPU's ap_list, then it
> +		 * cannot be moved or modified and there is no more work for
> +		 * us to do.
> +		 *
> +		 * Otherwise, if the irq is not pending and enabled, it does
> +		 * not need to be inserted into an ap_list and there is also
> +		 * no more work for us to do.
> +		 */
> +		spin_unlock(&irq->irq_lock);
> +		return false;
> +	}
> +
> +	/*
> +	 * We must unlock the irq lock to take the ap_list_lock where
> +	 * we are going to insert this new pending interrupt.
> +	 */
> +	spin_unlock(&irq->irq_lock);
> +
> +	/* someone can do stuff here, which we re-check below */
> +
> +	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +	spin_lock(&irq->irq_lock);
> +
> +	/*
> +	 * Did something change behind our backs?
> +	 *
> +	 * There are two cases:
> +	 * 1) The irq became pending or active behind our backs and/or

but you're not checking the active state below?

so did you mean 'became pending and enabled' ?

> +	 *    the irq->vcpu field was set correspondingly when putting
> +	 *    the irq on an ap_list. Then drop the locks and return.
> +	 * 2) Someone changed the affinity on this irq behind our
> +	 *    backs and we are now holding the wrong ap_list_lock.
> +	 *    Then drop the locks and try the new VCPU.
> +	 */

I thought we agreed a long time ago to change this to:

        if (unlinkely(irq->vcpu || vcpu != vgic_target_oracle(irq))) {
		spin_unlock(&irq->irq_lock);
		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
	
		spin_lock(&irq->irq_lock);
		goto retry;
	}

and get rid of two different if statements below ??

At least I don't understand why we are explicitly evaluating
!(irq->pending && irq->enabled) here, but using the oracle above?

In fact, I think if you did what I suggest above, then you can reuse
this for the active state, which frankly looks more complicated than we
had hoped for...

> +	if (irq->vcpu || !(irq->pending && irq->enabled)) {
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +		return false;
> +	}
> +
> +	if (irq->target_vcpu != vcpu) {
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +
> +		spin_lock(&irq->irq_lock);
> +		goto retry;
> +	}
> +
> +	list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
> +	irq->vcpu = vcpu;
> +
> +	spin_unlock(&irq->irq_lock);
> +	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +
> +	kvm_vcpu_kick(vcpu);
> +
> +	return true;
> +}
> +
> +static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
> +				   unsigned int intid, bool level,
> +				   bool mapped_irq)
> +{
> +	struct kvm_vcpu *vcpu;
> +	struct vgic_irq *irq;
> +	int ret;
> +
> +	trace_vgic_update_irq_pending(cpuid, intid, level);
> +
> +	vcpu = kvm_get_vcpu(kvm, cpuid);
> +	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
> +		return -EINVAL;
> +
> +	irq = vgic_get_irq(kvm, vcpu, intid);
> +	if (!irq)
> +		return -EINVAL;
> +
> +	if (irq->hw != mapped_irq)
> +		return -EINVAL;
> +
> +	spin_lock(&irq->irq_lock);
> +
> +	if (!vgic_validate_injection(irq, level)) {
> +		/* Nothing to see here, move along... */
> +		spin_unlock(&irq->irq_lock);
> +		return 0;
> +	}
> +
> +	if (irq->config == VGIC_CONFIG_LEVEL) {
> +		irq->line_level = level;
> +		irq->pending = level || irq->soft_pending;
> +	} else {
> +		irq->pending = true;
> +	}
> +
> +	vgic_queue_irq_unlock(kvm, irq);
> +
> +	return 0;
> +}
> +
> +/**
> + * kvm_vgic_inject_irq - Inject an IRQ from a device to the vgic
> + * @kvm:     The VM structure pointer
> + * @cpuid:   The CPU for PPIs
> + * @intid:   The INTID to inject a new state to.
> + * @level:   Edge-triggered:  true:  to trigger the interrupt
> + *			      false: to ignore the call
> + *	     Level-sensitive  true:  raise the input signal
> + *			      false: lower the input signal
> + *
> + * The VGIC is not concerned with devices being active-LOW or active-HIGH for
> + * level-sensitive interrupts.  You can think of the level parameter as 1
> + * being HIGH and 0 being LOW and all devices being active-HIGH.
> + */
> +int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
> +			bool level)
> +{
> +	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 61b8d22..c625767 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -18,5 +18,6 @@
>  
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid);
> +bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
>  
>  #endif
> -- 
> 2.7.3
> 


From adrian.hunter at intel.com  Tue May 10 05:03:48 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 15:03:48 +0300
Subject: [PATCH 20/23] mmc: sdhci-esdhc-imx: fix strobe DLL lock wrong
 clock issue
In-Reply-To: <1460741387-23815-21-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-21-git-send-email-aisheng.dong@nxp.com>
Message-ID: <5731CE24.2090002@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> When enable DDR, the clock factor definition is changed.
> e.g. original 200Mhz will become 100Mhz one MIX_CTRL_DDREN bit is set
> So we need to update the clock setting then the strobe dll can lock
> the correct clock rate.
> 
> Additionally we also need disable the clock before locking strobe dll.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>

Apart from redundant parentheses (refer below):

Acked-by: Adrian Hunter <adrian.hunter at intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 07b1144..3ff213f 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -852,6 +852,11 @@ static void esdhc_set_strobe_dll(struct sdhci_host *host)
>  	u32 v;
>  
>  	if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
> +		/* disable clock before enabling strobe dll */
> +		writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
> +		       (~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON),

Parentheses look redundant

> +		       host->ioaddr + ESDHC_VENDOR_SPEC);
> +
>  		/* force a reset on strobe dll */
>  		writel(ESDHC_STROBE_DLL_CTRL_RESET,
>  			host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> @@ -913,6 +918,8 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
>  		m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN;
>  		writel(m, host->ioaddr + ESDHC_MIX_CTRL);
>  		imx_data->is_ddr = 1;
> +		/* update clock after enable DDR for strobe DLL lock */
> +		host->ops->set_clock(host, host->clock);
>  		esdhc_set_strobe_dll(host);
>  		break;
>  	}
> 



From arnd at arndb.de  Tue May 10 05:07:57 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:07:57 +0200
Subject: [GIT PULL] Ux500 defconfig updates for v4.7
In-Reply-To: <CACRpkdaf39+gQzBb5U9gM5n17QwsNd7FxTbd3J+hLcuBNczKWA@mail.gmail.com>
References: <CACRpkdaf39+gQzBb5U9gM5n17QwsNd7FxTbd3J+hLcuBNczKWA@mail.gmail.com>
Message-ID: <24266746.WXjeqcnmtv@wuerfel>

On Monday 02 May 2016 10:49:06 Linus Walleij wrote:
> Ux500 defconfig update for v4.7:
> - Remove the unused MACH_UX500_DT option from the multi_v7 defconfig
> - Remove staging driver from u8500_defconfig
> - Update sensor support in u8500_defconfig
> 

I was going to pull this today but noticed that this involves a backmerge
of v4.6-rc6. Can you rebase this on 4.6-rc3 or earlier to avoid the backmerge?

	Arnd


From christoffer.dall at linaro.org  Tue May 10 05:09:00 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 10 May 2016 14:09:00 +0200
Subject: [PATCH v3 26/55] KVM: arm/arm64: vgic-new: Add ACTIVE registers
 handlers
In-Reply-To: <1462531568-9799-27-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-27-git-send-email-andre.przywara@arm.com>
Message-ID: <20160510120900.GD27623@cbox>

On Fri, May 06, 2016 at 11:45:39AM +0100, Andre Przywara wrote:
> The active register handlers are shared between the v2 and v3
> emulation, so their implementation goes into vgic-mmio.c, to be
> easily referenced from the v3 emulation as well later.
> Since activation/deactivation of an interrupt may happen entirely
> in the guest without it ever exiting, we need some extra logic to
> properly track the active state.
> Putting it on an ap_list on activation is similar to the normal case
> handled by vgic_queue_irq_unlock(), but differs in some details that
> make a separate implementation worthwhile.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - handling queueing in write handler
> - remove IRQ lock from read handler
> 
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c |   4 +-
>  virt/kvm/arm/vgic/vgic-mmio.c    | 120 +++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h    |  10 ++++
>  3 files changed, 132 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 4b87e0a..054b52d 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -80,9 +80,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
>  		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index 4df1af7..dbf683e 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -162,6 +162,126 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len)
> +{
> +	u32 intid = (addr & 0x7f) * 8;
> +	u32 value = 0;
> +	int i;
> +
> +	/* Loop over all IRQs affected by this read */
> +	for (i = 0; i < len * 8; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		if (irq->active)
> +			value |= (1U << i);
> +	}
> +
> +	return extract_bytes(value, addr & 3, len);
> +}
> +
> +void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val)
> +{
> +	u32 intid = (addr & 0x7f) * 8;
> +	int i;
> +
> +	for_each_set_bit(i, &val, len * 8) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		irq->active = false;
> +
> +		/*
> +		 * Christoffer wrote:
> +		 * The question is what to do if the vcpu for this irq is
> +		 * running and the LR there has the active bit set, then we'll
> +		 * overwrite this change when we fold the LR state back into
> +		 * the vgic_irq struct.
> +		 *
> +		 * Since I expect this to be extremely rare, one option is to
> +		 * force irq->vcpu to exit (if non-null) and then do you
> +		 * thing here after you've confirm it has exited while holding
> +		 * some lock preventing it from re-entering again.
> +		 * Slightly crazy.
> +		 *
> +		 * The alternative is to put a big fat comment nothing that
> +		 * this is non-supported bad race, and wait until someone
> +		 * submits a bug report relating to this...
> +		 */

I thought I wrote a patch for this?

> +
> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
> +void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val)
> +{
> +	u32 intid = (addr & 0x7f) * 8;
> +	int i;
> +
> +	for_each_set_bit(i, &val, len * 8) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		/* As this is a special case, we can't use the
> +		 * vgic_queue_irq_unlock() function to put this on a VCPU.
> +		 * So deal with this here explicitly unless the IRQs was
> +		 * already active, it was on a VCPU before or there is no
> +		 * target VCPU assigned at the moment.
> +		 */
> +		if (irq->active || irq->vcpu || !irq->target_vcpu) {
> +			irq->active = true;
> +
> +			spin_unlock(&irq->irq_lock);
> +			continue;
> +		}
> +
> +		spin_unlock(&irq->irq_lock);
> +retry:
> +		vcpu = irq->target_vcpu;
> +
> +		spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +		spin_lock(&irq->irq_lock);
> +
> +		/*
> +		 * Recheck after dropping the IRQ lock to see if we should
> +		 * still care about queueing it.
> +		 */
> +		if (irq->active || irq->vcpu) {
> +			irq->active = true;
> +
> +			spin_unlock(&irq->irq_lock);
> +			spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +
> +			continue;
> +		}
> +
> +		/* Did the target VCPU change while we had the lock dropped? */
> +		if (vcpu != irq->target_vcpu) {
> +			spin_unlock(&irq->irq_lock);
> +			spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +
> +			goto retry;
> +		}
> +
> +		/* Now queue the IRQ to the VCPU's ap_list. */
> +		list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
> +		irq->vcpu = vcpu;
> +
> +		irq->active = true;
> +
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +
> +		kvm_vcpu_kick(vcpu);

quite frankly, this looks very complicated and I really think it's worth
reusing the queue function after seeing this (sorry I haven't been able
to before).

-Christoffer

> +	}
> +}
> +
>  static int match_region(const void *key, const void *elt)
>  {
>  	const unsigned int offset = (unsigned long)key;
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index d4fc029..fa875dc 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -96,6 +96,16 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
>  			      gpa_t addr, unsigned int len,
>  			      unsigned long val);
>  
> +unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len);
> +
> +void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val);
> +
> +void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val);
>  
>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>  
> -- 
> 2.7.3
> 


From linus.walleij at linaro.org  Tue May 10 05:08:45 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 10 May 2016 14:08:45 +0200
Subject: [PATCH v8 2/3] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <535f785bf6116c0fb6f46afbb77e6d4bd3ef5f60.1462543458.git.chunkeey@googlemail.com>
References: <cover.1462543457.git.chunkeey@googlemail.com>
 <535f785bf6116c0fb6f46afbb77e6d4bd3ef5f60.1462543458.git.chunkeey@googlemail.com>
Message-ID: <CACRpkdaeZ14hfz-gRetRcdj8NzzyqigV1ZtDSWAwveFxwAgt0w@mail.gmail.com>

On Sun, May 8, 2016 at 3:08 PM, Christian Lamparter
<chunkeey at googlemail.com> wrote:

> From: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
>
> This patch adds support for defining memory-mapped GPIOs which
> are compatible with the existing gpio-mmio interface.

Overall very nice, just waiting for the next version.

> The first user for this binding is "wd,mbl-gpio".

And that binding defines that we have a register named "dat".

> +       if (of_property_read_bool(dev->of_node, "no-output"))

And then this too.

Do we want these generic MMIO bindings (dat, no-output)
in a special document like
Documentation/devicetree/bindings/gpio/gpio-mmio.txt?

Going forward?

This patch set mainly deals with refactorings, but in the
long run we want to slim things down a bit and use standard
bindings I think.

Yours,
Linus Walleij


From arnd at arndb.de  Tue May 10 05:09:04 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:09:04 +0200
Subject: [GIT PULL 5/6] i.MX defconfig updates for 4.7
In-Reply-To: <1462291086-19925-5-git-send-email-shawnguo@kernel.org>
References: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
 <1462291086-19925-5-git-send-email-shawnguo@kernel.org>
Message-ID: <19332422.8mBKvEekr1@wuerfel>

On Tuesday 03 May 2016 23:58:05 Shawn Guo wrote:
> The i.MX defconfig updates for 4.7:
>  - Update multi_v5_defconfig for i.MX21/27 and systemd support
>  - Update imx_v6_v7_defconfig to support devices found on various i.MX6
>    board: FT5x06 and TSC2004 touch, I2C GPIO, MICREL PHY and M41T80 RTC
> 

Merged into next/defconfig, thanks!

	Arnd


From arnd at arndb.de  Tue May 10 05:13:57 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:13:57 +0200
Subject: [GIT PULL] ARM: mvebu: defconfig for v4.7 (#2)
In-Reply-To: <13443700.NUC16SCx6V@wuerfel>
References: <87pot8sct4.fsf@free-electrons.com> <13443700.NUC16SCx6V@wuerfel>
Message-ID: <2554522.hzQidgmgjq@wuerfel>

On Tuesday 10 May 2016 14:05:48 Arnd Bergmann wrote:
> On Friday 29 April 2016 16:35:19 Gregory CLEMENT wrote:
> > mvebu defconfig for 4.7 (part 2)
> > 
> > - enable AP806 and CP110 syscon driver in arm64 defconfig
> > 
> > 
> 
> Merged into next/defconfig, thanks!
> 

I ended up undoing the merge before I pushed it out to the git server
as I noticed you have both arm and arm64 changes in there.

Can you still split up the branch in two?

	Arnd


From linus.walleij at linaro.org  Tue May 10 05:14:45 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 10 May 2016 14:14:45 +0200
Subject: [GIT PULL] Ux500 defconfig updates for v4.7
In-Reply-To: <24266746.WXjeqcnmtv@wuerfel>
References: <CACRpkdaf39+gQzBb5U9gM5n17QwsNd7FxTbd3J+hLcuBNczKWA@mail.gmail.com>
 <24266746.WXjeqcnmtv@wuerfel>
Message-ID: <CACRpkdb6t3QEk6PfTLUXTCCNVWPvq+=BVb1DKJY7q-9HU7+Haw@mail.gmail.com>

On Tue, May 10, 2016 at 2:07 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> On Monday 02 May 2016 10:49:06 Linus Walleij wrote:
>> Ux500 defconfig update for v4.7:
>> - Remove the unused MACH_UX500_DT option from the multi_v7 defconfig
>> - Remove staging driver from u8500_defconfig
>> - Update sensor support in u8500_defconfig
>>
>
> I was going to pull this today but noticed that this involves a backmerge
> of v4.6-rc6. Can you rebase this on 4.6-rc3 or earlier to avoid the backmerge?

Of course. enjoy:

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
tags/ux500-defconfig-armsoc2

for you to fetch changes up to 35bee33355db8347d5f84caef9d2ddde200b8ba6:

  ARM: u8500_defconfig: update sensor config (2016-05-10 14:10:52 +0200)

----------------------------------------------------------------
Ux500 defconfig update for v4.7:
- Remove the unused MACH_UX500_DT option from the multi_v7 defconfig
- Remove staging driver from u8500_defconfig
- Update sensor support in u8500_defconfig

----------------------------------------------------------------
Lee Jones (1):
      ARM: multi_v7_defconfig: Remove unused Kconfig option MACH_UX500_DT

Linus Walleij (2):
      ARM: u8500_defconfig: remove staging from defconfig
      ARM: u8500_defconfig: update sensor config

 arch/arm/configs/multi_v7_defconfig | 1 -
 arch/arm/configs/u8500_defconfig    | 5 ++---
 2 files changed, 2 insertions(+), 4 deletions(-)

Yours,
Linus Walleij


From marc.zyngier at arm.com  Tue May 10 05:14:45 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 13:14:45 +0100
Subject: [PATCH v3 26/55] KVM: arm/arm64: vgic-new: Add ACTIVE registers
 handlers
In-Reply-To: <1462531568-9799-27-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-27-git-send-email-andre.przywara@arm.com>
Message-ID: <5731D0B5.9060605@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> The active register handlers are shared between the v2 and v3
> emulation, so their implementation goes into vgic-mmio.c, to be
> easily referenced from the v3 emulation as well later.
> Since activation/deactivation of an interrupt may happen entirely
> in the guest without it ever exiting, we need some extra logic to
> properly track the active state.
> Putting it on an ap_list on activation is similar to the normal case
> handled by vgic_queue_irq_unlock(), but differs in some details that
> make a separate implementation worthwhile.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - handling queueing in write handler
> - remove IRQ lock from read handler
> 
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c |   4 +-
>  virt/kvm/arm/vgic/vgic-mmio.c    | 120 +++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h    |  10 ++++
>  3 files changed, 132 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 4b87e0a..054b52d 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -80,9 +80,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
>  		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index 4df1af7..dbf683e 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -162,6 +162,126 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len)
> +{
> +	u32 intid = (addr & 0x7f) * 8;
> +	u32 value = 0;
> +	int i;
> +
> +	/* Loop over all IRQs affected by this read */
> +	for (i = 0; i < len * 8; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		if (irq->active)
> +			value |= (1U << i);
> +	}
> +
> +	return extract_bytes(value, addr & 3, len);
> +}
> +
> +void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val)
> +{
> +	u32 intid = (addr & 0x7f) * 8;
> +	int i;
> +
> +	for_each_set_bit(i, &val, len * 8) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		irq->active = false;
> +
> +		/*
> +		 * Christoffer wrote:
> +		 * The question is what to do if the vcpu for this irq is
> +		 * running and the LR there has the active bit set, then we'll
> +		 * overwrite this change when we fold the LR state back into
> +		 * the vgic_irq struct.
> +		 *
> +		 * Since I expect this to be extremely rare, one option is to
> +		 * force irq->vcpu to exit (if non-null) and then do you
> +		 * thing here after you've confirm it has exited while holding
> +		 * some lock preventing it from re-entering again.
> +		 * Slightly crazy.
> +		 *
> +		 * The alternative is to put a big fat comment nothing that
> +		 * this is non-supported bad race, and wait until someone
> +		 * submits a bug report relating to this...
> +		 */

Don't we have a patch by Christoffer that addresses this exact issue?

> +
> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
> +void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val)
> +{
> +	u32 intid = (addr & 0x7f) * 8;
> +	int i;
> +
> +	for_each_set_bit(i, &val, len * 8) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		/* As this is a special case, we can't use the
> +		 * vgic_queue_irq_unlock() function to put this on a VCPU.
> +		 * So deal with this here explicitly unless the IRQs was
> +		 * already active, it was on a VCPU before or there is no
> +		 * target VCPU assigned at the moment.
> +		 */
> +		if (irq->active || irq->vcpu || !irq->target_vcpu) {
> +			irq->active = true;
> +
> +			spin_unlock(&irq->irq_lock);
> +			continue;
> +		}
> +
> +		spin_unlock(&irq->irq_lock);
> +retry:
> +		vcpu = irq->target_vcpu;
> +
> +		spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +		spin_lock(&irq->irq_lock);
> +
> +		/*
> +		 * Recheck after dropping the IRQ lock to see if we should
> +		 * still care about queueing it.
> +		 */
> +		if (irq->active || irq->vcpu) {
> +			irq->active = true;
> +
> +			spin_unlock(&irq->irq_lock);
> +			spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +
> +			continue;
> +		}
> +
> +		/* Did the target VCPU change while we had the lock dropped? */
> +		if (vcpu != irq->target_vcpu) {
> +			spin_unlock(&irq->irq_lock);
> +			spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +
> +			goto retry;
> +		}
> +
> +		/* Now queue the IRQ to the VCPU's ap_list. */
> +		list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
> +		irq->vcpu = vcpu;
> +
> +		irq->active = true;
> +
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +
> +		kvm_vcpu_kick(vcpu);
> +	}

This is annoyingly close to vgic_queue_irq_unlock()... Maybe switching
this to some form of preprocessor template. Or not.

> +}
> +
>  static int match_region(const void *key, const void *elt)
>  {
>  	const unsigned int offset = (unsigned long)key;
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index d4fc029..fa875dc 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -96,6 +96,16 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
>  			      gpa_t addr, unsigned int len,
>  			      unsigned long val);
>  
> +unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len);
> +
> +void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val);
> +
> +void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val);
>  
>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>  
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From adrian.hunter at intel.com  Tue May 10 05:15:59 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 15:15:59 +0300
Subject: [PATCH 21/23] mmc: sdhci-esdhc-imx: factor out hw related
 intialization into function
In-Reply-To: <1460741387-23815-22-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-22-git-send-email-aisheng.dong@nxp.com>
Message-ID: <5731D0FF.60807@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> Factor out hw related intialization into a separate function which
> has two benifits:
> 1) concentrate hw related intialization at one place
> 2) ease the hw state restore after resume by simply
> calling this function

There are really 2 changes here, please make it 2 patches.

> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 76 +++++++++++++++++++++-----------------
>  1 file changed, 42 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 3ff213f..95f3632 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -978,6 +978,44 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
>  	.ops = &sdhci_esdhc_ops,
>  };
>  
> +static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
> +{
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> +
> +	if (esdhc_is_usdhc(imx_data)) {
> +		/*
> +		 * The imx6q ROM code will change the default watermark
> +		 * level setting to something insane.  Change it back here.
> +		 */
> +		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> +
> +		/*
> +		 * ROM code will change the bit burst_length_enable setting
> +		 * to zero if this usdhc is choosed to boot system. Change
> +		 * it back here, otherwise it will impact the performance a
> +		 * lot. This bit is used to enable/disable the burst length
> +		 * for the external AHB2AXI bridge, it's usefully especially
> +		 * for INCR transfer because without burst length indicator,
> +		 * the AHB2AXI bridge does not know the burst length in
> +		 * advance. And without burst length indicator, AHB INCR
> +		 * transfer can only be converted to singles on the AXI side.
> +		 */
> +		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
> +			| ESDHC_BURST_LEN_EN_INCR,
> +			host->ioaddr + SDHCI_HOST_CONTROL);
> +		/*
> +		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
> +		* TO1.1, it's harmless for MX6SL
> +		*/
> +		writel(readl(host->ioaddr + 0x6c) | BIT(7),
> +			host->ioaddr + 0x6c);
> +
> +		/* disable DLL_CTRL delay line settings */
> +		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
> +	}
> +}
> +
>  #ifdef CONFIG_OF
>  static int
>  sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
> @@ -1175,43 +1213,13 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
>  			| SDHCI_QUIRK_BROKEN_ADMA;
>  
> -	/*
> -	 * The imx6q ROM code will change the default watermark level setting
> -	 * to something insane.  Change it back here.
> -	 */
> -	if (esdhc_is_usdhc(imx_data)) {
> -		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> +	sdhci_esdhc_imx_hwinit(host);
>  
> +	if (esdhc_is_usdhc(imx_data)) {
>  		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
>  		host->mmc->caps |= MMC_CAP_1_8V_DDR;
> -
> -		/*
> -		 * ROM code will change the bit burst_length_enable setting
> -		 * to zero if this usdhc is choosed to boot system. Change
> -		 * it back here, otherwise it will impact the performance a
> -		 * lot. This bit is used to enable/disable the burst length
> -		 * for the external AHB2AXI bridge, it's usefully especially
> -		 * for INCR transfer because without burst length indicator,
> -		 * the AHB2AXI bridge does not know the burst length in
> -		 * advance. And without burst length indicator, AHB INCR
> -		 * transfer can only be converted to singles on the AXI side.
> -		 */
> -		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
> -			| ESDHC_BURST_LEN_EN_INCR,
> -			host->ioaddr + SDHCI_HOST_CONTROL);
> -
>  		if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))
>  			host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
> -
> -		/*
> -		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
> -		* TO1.1, it's harmless for MX6SL
> -		*/
> -		writel(readl(host->ioaddr + 0x6c) | BIT(7),
> -			host->ioaddr + 0x6c);
> -
> -		/* disable DLL_CTRL delay line settings */
> -		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
>  	}
>  
>  	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> @@ -1289,8 +1297,8 @@ static int sdhci_esdhc_resume(struct device *dev)
>  {
>  	struct sdhci_host *host = dev_get_drvdata(dev);
>  
> -	/* restore watermark setting in case it's lost in low power mode */
> -	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> +	/* reinitialize hw state in case it's lost in low power mode */
> +	sdhci_esdhc_imx_hwinit(host);
>  
>  	return sdhci_pltfm_resume(dev);
>  }
> 



From nicolas.ferre at atmel.com  Tue May 10 05:20:42 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Tue, 10 May 2016 14:20:42 +0200
Subject: [GIT PULL] at91: defconfig for 4.7 #2
Message-ID: <1462882842-23968-1-git-send-email-nicolas.ferre@atmel.com>

Arnd, Olof, Kevin,

A couple of defconfig updates for AT91. They both touch our own
sama5_defconfig only.

Thanks, best regards,

The following changes since commit ed87957b18f238516e578e5dbd44a5db11300831:

  ARM: multi_v7_defconfig: add the Atmel sama5d2-compatible ADC driver (2016-04-27 14:07:59 +0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91.git tags/at91-defconfig2

for you to fetch changes up to f0d523668cb122905a541cb6b86e3ae49260ae5e:

  ARM: at91/defconfig: sama5: add CONFIG_FHANDLE (2016-05-10 09:57:44 +0200)

----------------------------------------------------------------
Second batch of defconfig:
- sama5_defconfig: update to support easy use of systemd userspace

----------------------------------------------------------------
Marek Vasut (1):
      ARM: at91: sama5: Update defconfig

Nicolas Ferre (1):
      ARM: at91/defconfig: sama5: add CONFIG_FHANDLE

 arch/arm/configs/sama5_defconfig | 2 ++
 1 file changed, 2 insertions(+)

-- 
Nicolas Ferre


From arnd at arndb.de  Tue May 10 05:24:48 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:24:48 +0200
Subject: [GIT PULL] Ux500 defconfig updates for v4.7
In-Reply-To: <CACRpkdb6t3QEk6PfTLUXTCCNVWPvq+=BVb1DKJY7q-9HU7+Haw@mail.gmail.com>
References: <CACRpkdaf39+gQzBb5U9gM5n17QwsNd7FxTbd3J+hLcuBNczKWA@mail.gmail.com>
 <24266746.WXjeqcnmtv@wuerfel>
 <CACRpkdb6t3QEk6PfTLUXTCCNVWPvq+=BVb1DKJY7q-9HU7+Haw@mail.gmail.com>
Message-ID: <13037240.fYhUNtFjsc@wuerfel>

On Tuesday 10 May 2016 14:14:45 Linus Walleij wrote:
> Ux500 defconfig update for v4.7:
> - Remove the unused MACH_UX500_DT option from the multi_v7 defconfig
> - Remove staging driver from u8500_defconfig
> - Update sensor support in u8500_defconfig
> 

Pulled into next/defconfig, thanks for the quick update!

	Arnd


From p.zabel at pengutronix.de  Tue May 10 05:25:38 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Tue, 10 May 2016 14:25:38 +0200
Subject: [RFC PATCH 13/21] reset: uniphier: add reset driver for
 UniPhier PH1-LD4 SoC
In-Reply-To: <1462873862-30940-14-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
 <1462873862-30940-14-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462883138.9155.3.camel@pengutronix.de>

Hi Masahiro,

Am Dienstag, den 10.05.2016, 18:50 +0900 schrieb Masahiro Yamada:
> This series is just for review.
> Please do not apply this patch.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

No need for all these tiny drivers. If you probe from DT as Lee
requests, you can let of_device_id.data point to a compatible specific
uniphier_reset_data.

regards
Philipp



From arnd at arndb.de  Tue May 10 05:28:44 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:28:44 +0200
Subject: [PULL REQUEST] aspeed defconfig changes for 4.7
In-Reply-To: <1462797007-13900-1-git-send-email-joel@jms.id.au>
References: <1462797007-13900-1-git-send-email-joel@jms.id.au>
Message-ID: <2673629.sXUyq8GnCR@wuerfel>

On Monday 09 May 2016 22:00:07 Joel Stanley wrote:
> This adds configurations used for testing Aspeed BMC SoCs, as well as adding
> the v5 part to the multi defconfig.
> 
> 

Merged into next/defconfig, thanks!

	Arnd


From marex at denx.de  Tue May 10 05:31:26 2016
From: marex at denx.de (Marek Vasut)
Date: Tue, 10 May 2016 14:31:26 +0200
Subject: [PATCH] ARM: at91/defconfig: sama5: add CONFIG_FHANDLE
In-Reply-To: <1462867383-31961-1-git-send-email-nicolas.ferre@atmel.com>
References: <572CC603.4000102@denx.de>
 <1462867383-31961-1-git-send-email-nicolas.ferre@atmel.com>
Message-ID: <5731D49E.3080307@denx.de>

On 05/10/2016 10:03 AM, Nicolas Ferre wrote:
> CONFIG_FHANDLE is listed as a mandatory kernel option for systemd. So
> explicitly enable it to allow easy use of systemd userspace.
> 
> Reported-by: Marek Vasut <marex at denx.de>
> Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
> ---
> Hi Marek,

Hi!

> It seems that on my side, CONFIG_FHANDLE is not selected automatically...
> So I add this patch: can you tell me your thoughts?

Uh, weird, I tried this on next just now:

linux-2.6$ git describe HEAD
next-20160510

linux-2.6$ export ARCH=arm ; export CROSS_COMPILE=arm-linux-gnueabi-

linux-2.6$ make sama5_defconfig ; grep FHANDLE .config
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  SHIPPED scripts/kconfig/zconf.tab.c
  SHIPPED scripts/kconfig/zconf.lex.c
  SHIPPED scripts/kconfig/zconf.hash.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
#
# configuration written to .config
#
CONFIG_FHANDLE=y

> Bye,
>    Nico.
> 
>  arch/arm/configs/sama5_defconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
> index 307f92b31e57..9cb1a85bb166 100644
> --- a/arch/arm/configs/sama5_defconfig
> +++ b/arch/arm/configs/sama5_defconfig
> @@ -1,6 +1,7 @@
>  # CONFIG_LOCALVERSION_AUTO is not set
>  # CONFIG_SWAP is not set
>  CONFIG_SYSVIPC=y
> +CONFIG_FHANDLE=y
>  CONFIG_IRQ_DOMAIN_DEBUG=y
>  CONFIG_LOG_BUF_SHIFT=14
>  CONFIG_CGROUPS=y
> 


-- 
Best regards,
Marek Vasut


From harninder.rai at nxp.com  Tue May 10 05:32:15 2016
From: harninder.rai at nxp.com (Harninder Rai)
Date: Tue, 10 May 2016 12:32:15 +0000
Subject: Help needed with kexec on arm64
In-Reply-To: <20160405052341.GA19476@linaro.org>
References: <DB5PR04MB168845795D86B4CE5BA5656FE68B0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <1458230896.3391.18.camel@infradead.org>
 <CAB5YjtBEO=efjhcFdVOaZqG13qK3uzCbS5SFym5hhw-n+_QLhw@mail.gmail.com>
 <DB5PR04MB1688A6D4385B76DAFF71D364E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org>
Message-ID: <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>

> 
> This means that there is no enough space left at this point.
> I guess that you are using too big initramfs against 64MB of total memory.
> Just increase the memory size for crash dump kernel.
> 
> -Takahiro AKASHI

Hello Takahiro Akashi,

I used a smaller initramfs (as you suggested) and my crash kernel has moved further but it again dumped with the following log messages. Any further pointers?
Does this mean that there isn't enough memory to save the core file or something? Because the error mostly are related to OOM killer process

[    8.833434] Freeing unused kernel memory: 748K (ffff800000a3a000 - ffff800000af5000)
[    8.848924] init: Console is alive
[    8.856866] mmc0: new high speed SDHC card at address b368
[    8.868239] mmcblk0: mmc0:b368 SDC   3.75 GiB
[    8.873913]  mmcblk0: p1
[    9.855930] init: - preinit -
Press the [f] key and hit [enter] to enter failsafe mode
Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level
[   12.896779] procd: - early -
[   12.977417] kworker/u16:0 invoked oom-killer: gfp_mask=0x27000c0, order=2, oom_score_adj=0
[   12.994568] CPU: 0 PID: 6 Comm: kworker/u16:0 Not tainted 4.5.0-rc6-00038-gae2804a-dirty #5
[   13.002950] Hardware name: Freescale Layerscape 2085a RDB Board (DT)
[   13.009333] Workqueue: events_unbound call_usermodehelper_exec_work
[   13.015623] Call trace:
[   13.018076] [<ffff800000089760>] dump_backtrace+0x0/0x1ac
[   13.023492] [<ffff800000089920>] show_stack+0x14/0x1c
[   13.028560] [<ffff80000032c1d4>] dump_stack+0x8c/0xb0
[   13.033627] [<ffff8000001aebdc>] dump_header.isra.7+0x4c/0x18c
[   13.039480] [<ffff800000152130>] oom_kill_process+0x26c/0x45c
[   13.045243] [<ffff800000152688>] out_of_memory+0x2e0/0x32c
[   13.050745] [<ffff800000156c68>] __alloc_pages_nodemask+0x83c/0x848
[   13.057031] [<ffff800000156f78>] alloc_kmem_pages_node+0x30/0xa8
[   13.063058] [<ffff8000000b776c>] copy_process.isra.42.part.43+0x128/0x1488
[   13.069955] [<ffff8000000b8c4c>] _do_fork+0xcc/0x338
[   13.074934] [<ffff8000000b8f04>] kernel_thread+0x34/0x3c
[   13.080261] [<ffff8000000cb8e0>] call_usermodehelper_exec_work+0x2c/0xd8
[   13.086984] [<ffff8000000ce4b0>] process_one_work+0x134/0x2f4
[   13.092747] [<ffff8000000ce6c8>] worker_thread+0x58/0x43c
[   13.098162] [<ffff8000000d3f88>] kthread+0xd8/0xec
[   13.102967] [<ffff800000085cd0>] ret_from_fork+0x10/0x40
[   13.261745] Mem-Info:

Thanks and Regards
Harry++


From arnd at arndb.de  Tue May 10 05:30:58 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:30:58 +0200
Subject: [GIT PULL] at91: defconfig for 4.7 #2
In-Reply-To: <1462882842-23968-1-git-send-email-nicolas.ferre@atmel.com>
References: <1462882842-23968-1-git-send-email-nicolas.ferre@atmel.com>
Message-ID: <3612858.WHQLoNoYFx@wuerfel>

On Tuesday 10 May 2016 14:20:42 Nicolas Ferre wrote:
> Arnd, Olof, Kevin,
> 
> A couple of defconfig updates for AT91. They both touch our own
> sama5_defconfig only.
> 

Merged into next/defconfig, thanks!

	Arnd


From arnd at arndb.de  Tue May 10 05:35:22 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:35:22 +0200
Subject: [GIT PULL 6/6] Freescale/NXP arm64 defconfig updates for 4.7
In-Reply-To: <1462291086-19925-6-git-send-email-shawnguo@kernel.org>
References: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
 <1462291086-19925-6-git-send-email-shawnguo@kernel.org>
Message-ID: <5439440.fkC06QzuXX@wuerfel>

On Tuesday 03 May 2016 23:58:06 Shawn Guo wrote:
> Different from above 5 pull requests that start off 4.6-rc1, this one
> is based on 4.6-rc2, because commit 431597bb9556 ("arm64: defconfig:
> updates for 4.6") changes arch/arm64/configs/defconfig dramatically
> and went into 4.6-rc2.  I have to base my branch onto 4.6-rc2 to avoid
> manual merging.
> 

Sure, no problem. As you could tell from our git tree, we are already on
rc3 with the next/arm64 branch, so there is no backmerge.

Pulled into next/arm64 now, thanks!

	Arnd


From bamvor.zhangjian at huawei.com  Tue May 10 05:39:41 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Tue, 10 May 2016 20:39:41 +0800
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <7091358.aJt1stteb5@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <9651510.pg5Vmm8vKS@wuerfel> <5731AE2E.2050403@huawei.com>
 <7091358.aJt1stteb5@wuerfel>
Message-ID: <5731D68D.2090109@huawei.com>

Hi,

On 2016/5/10 19:48, Arnd Bergmann wrote:
> On Tuesday 10 May 2016 17:47:26 Zhangjian wrote:
>> On 2016/5/10 16:36, Arnd Bergmann wrote:
>>> On Tuesday 10 May 2016 15:42:07 Zhangjian wrote:
>>>> On 2016/5/6 20:37, Yury Norov wrote:
>>
>> "include/uapi/asm-generic/posix_types.h" is uapi, we could not check
>> "ARCH_32BIT_OFF_T" here. Besides, the `__kernel_long_t` is long which
>> mean it is 32bit in ILP32. should we define something like x32?
>>       ```
>>       diff --git a/arch/arm64/include/uapi/asm/posix_types.h b/arch/arm64/include/uapi/asm/posix_types.h
>>       index 7985ff6..9baa8d3 100644
>>       --- a/arch/arm64/include/uapi/asm/posix_types.h
>>       +++ b/arch/arm64/include/uapi/asm/posix_types.h
>
> glibc does not use the definition of __kernel_off_t, it has its own
> copy, so changing the kernel headers would do nothing.
Yes, I think so. I am puzzle that how do we ensure that all the new
32bit architecture will define off_t as 64bit after introduce
ARCH_32BIT_OFF_T and do not change any other code?
>
>>       @@ -5,6 +5,9 @@ typedef unsigned short __kernel_old_uid_t;
>>        typedef unsigned short __kernel_old_gid_t;
>>         #define __kernel_old_uid_t __kernel_old_uid_t
>>
>>        +typedef long long __kernel_long_t;
>>        +typedef unsigned long long __kernel_ulong_t;
>>        +
>>         #include <asm-generic/posix_types.h>
>>
>>         #endif /*  __ASM_POSIX_TYPES_H */u
>>       ```
>
> This would break all sorts of things, because __kernel_long_t/__kernel_ulong_t
> are not just used for off_t but also other things.
Yes. But if we do not change __kernel_long_t and __kernel_ulong_t, the
application of ilp32 will think size of long in kernel is 32bit. Is that
correct?
>
>>
>> On the other hand, glibc define it own off_t in "bits/types.h":
>>       __STD_TYPE __OFF_T_TYPE __off_t;        /* Type of file sizes and offsets.  */
>>       __STD_TYPE __OFF64_T_TYPE __off64_t;    /* Type of file sizes and offsets (LFS).  */
>>
>> in "sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h":
>>       #define __OFF_T_TYPE            __SLONGWORD_TYPE
>>       #define __OFF64_T_TYPE          __SQUAD_TYPE
>>
>> If we define off_t as 64bit in glibc:
>>       #define __OFF_T_TYPE           __SQUAD_TYPE
>>
>> Should We need to align all the off_t syscall to 64bit syscall in
>> kernel?
>>
>
> Yes, this is the change that I think we need to make, along with
> the same change for __INO_T_TYPE and
>
> #define __OFF_T_MATCHES_OFF64_T        1
> #define __INO_T_MATCHES_INO64_T        1
>
> If I read the rest of the glibc headers right, that should be all we need
> to ensure that both off_t and off64_t match the __kernel_loff_t based
> syscalls.
Ok, I will test the ltp syscall test.
With this changes, the issue I mentioned should be fixed. But we still
use mmap2 syscall for ILP32 application when we pass the offset instead
of page offset. Is it correct?

Regards

Bamvor

>
> 	Arnd
>



From nicolas.ferre at atmel.com  Tue May 10 05:42:02 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Tue, 10 May 2016 14:42:02 +0200
Subject: [PATCH] ARM: at91/defconfig: sama5: add CONFIG_FHANDLE
In-Reply-To: <5731D49E.3080307@denx.de>
References: <572CC603.4000102@denx.de>
 <1462867383-31961-1-git-send-email-nicolas.ferre@atmel.com>
 <5731D49E.3080307@denx.de>
Message-ID: <5731D71A.5080500@atmel.com>

Le 10/05/2016 14:31, Marek Vasut a ?crit :
> On 05/10/2016 10:03 AM, Nicolas Ferre wrote:
>> CONFIG_FHANDLE is listed as a mandatory kernel option for systemd. So
>> explicitly enable it to allow easy use of systemd userspace.
>>
>> Reported-by: Marek Vasut <marex at denx.de>
>> Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
>> ---
>> Hi Marek,
> 
> Hi!
> 
>> It seems that on my side, CONFIG_FHANDLE is not selected automatically...
>> So I add this patch: can you tell me your thoughts?
> 
> Uh, weird, I tried this on next just now:
> 
> linux-2.6$ git describe HEAD
> next-20160510
> 
> linux-2.6$ export ARCH=arm ; export CROSS_COMPILE=arm-linux-gnueabi-
> 
> linux-2.6$ make sama5_defconfig ; grep FHANDLE .config
>   HOSTCC  scripts/basic/fixdep
>   HOSTCC  scripts/kconfig/conf.o
>   SHIPPED scripts/kconfig/zconf.tab.c
>   SHIPPED scripts/kconfig/zconf.lex.c
>   SHIPPED scripts/kconfig/zconf.hash.c
>   HOSTCC  scripts/kconfig/zconf.tab.o
>   HOSTLD  scripts/kconfig/conf
> #
> # configuration written to .config
> #
> CONFIG_FHANDLE=y

Absolutely. The patch f76be61755c5 ("Make CONFIG_FHANDLE default y") has
been added in v4.6-rc2... while I was doing my tests on at91-next that
is based on v4.6-rc1 :-\

Anyway. It's in now. Thanks,

Bye,
   Nicolas

>>  arch/arm/configs/sama5_defconfig | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
>> index 307f92b31e57..9cb1a85bb166 100644
>> --- a/arch/arm/configs/sama5_defconfig
>> +++ b/arch/arm/configs/sama5_defconfig
>> @@ -1,6 +1,7 @@
>>  # CONFIG_LOCALVERSION_AUTO is not set
>>  # CONFIG_SWAP is not set
>>  CONFIG_SYSVIPC=y
>> +CONFIG_FHANDLE=y
>>  CONFIG_IRQ_DOMAIN_DEBUG=y
>>  CONFIG_LOG_BUF_SHIFT=14
>>  CONFIG_CGROUPS=y
>>
> 
> 


-- 
Nicolas Ferre


From arnd at arndb.de  Tue May 10 05:41:36 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:41:36 +0200
Subject: [PATCH] arm64: defconfig: Add Juno SATA controller
In-Reply-To: <1462441458-24387-1-git-send-email-andre.przywara@arm.com>
References: <1462441458-24387-1-git-send-email-andre.przywara@arm.com>
Message-ID: <3677482.6TVNGmYCjE@wuerfel>

On Thursday 05 May 2016 10:44:18 Andre Przywara wrote:
> The ARM Juno (r1 and r2) boards feature a SATA controller soldered
> on the board and connected to the PCI bus.
> Add the respective driver to defconfig to get hard disks supported out
> of the box on the Junos.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  arch/arm64/configs/defconfig | 1 +
>  1 file changed, 1 insertion(+)
> 

I've applied this directly, although I'd prefer to see patches like this
get routed through the platform (vexpress/juno here) maintainers, or
have an Ack from them.

	Arnd


From boris.brezillon at free-electrons.com  Tue May 10 05:41:43 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 10 May 2016 14:41:43 +0200
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <20160510110742.GI687@leverpostej>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop>
 <20160503185153.5cfddc32@bbrezillon>
 <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
 <20160504113852.10a2dd84@bbrezillon>
 <CAL_Jsq+4aL5znA3zOKdcJb+pEXhVOQthkFF6DN2+P6U37t2o6g@mail.gmail.com>
 <20160504153547.60d736bb@bbrezillon>
 <20160510100448.49834120@bbrezillon>
 <20160510110742.GI687@leverpostej>
Message-ID: <20160510144143.1965ee5e@bbrezillon>

On Tue, 10 May 2016 12:07:42 +0100
Mark Rutland <mark.rutland at arm.com> wrote:

> On Tue, May 10, 2016 at 10:04:48AM +0200, Boris Brezillon wrote:
> > On Wed, 4 May 2016 15:35:47 +0200
> > Boris Brezillon <boris.brezillon at free-electrons.com> wrote:
> >   
> > > On Wed, 4 May 2016 08:06:10 -0500
> > > Rob Herring <robh at kernel.org> wrote:
> > >   
> > > > On Wed, May 4, 2016 at 4:38 AM, Boris Brezillon
> > > > <boris.brezillon at free-electrons.com> wrote:    
> > > > > Hi Rob,
> > > > >
> > > > > On Tue, 3 May 2016 14:11:04 -0500
> > > > > Rob Herring <robh at kernel.org> wrote:
> > > > >      
> > > > >> On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
> > > > >> <boris.brezillon at free-electrons.com> wrote:      
> > > > >> > Hi Rob,
> > > > >> >
> > > > >> > On Tue, 3 May 2016 11:40:19 -0500
> > > > >> > Rob Herring <robh at kernel.org> wrote:
> > > > >> >      
> > > > >> >> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:      
> > > > >> >> > The EBI (External Bus Interface) is used to access external peripherals
> > > > >> >> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
> > > > >> >> > Each device is assigned a CS line and an address range and can have its
> > > > >> >> > own configuration (timings, access mode, bus width, ...).
> > > > >> >> > This driver provides a generic DT binding to configure a device according
> > > > >> >> > to its requirements.
> > > > >> >> > For specific device controllers (like the NAND one) the SMC timings
> > > > >> >> > should be configured by the controller driver through the matrix and smc
> > > > >> >> > syscon regmaps.      
> > > > 
> > > > [...]
> > > >     
> > > > >> >> > +EBI bus configuration associated with specific chip-select will be defined in
> > > > >> >> > +the configs subnode. This configs node will in turn contain several subnodes
> > > > >> >> > +named config-<cs-id>, each of them containing the following properties.      
> > > > >> >>
> > > > >> >> This is a bit unusual. Why not just part of the child device nodes?      
> > > > >> >
> > > > >> > Oh, come on! I reworked the binding because Mark complained about the
> > > > >> > previous binding which was doing exactly what you're suggesting. Can
> > > > >> > you please be consistent in your reviews...      
> > > > >>
> > > > >> No, Mark and I both have our opinions. Which part of this patch
> > > > >> explains the history?      
> > > > >
> > > > > Hm, it's in patch 1/2 (just dropped the cover letter, which might not
> > > > > be such a good idea).
> > > > >      
> > > > >> If the revision history is not in the patch, I'm
> > > > >> not looking at it.
> > > > >>
> > > > >> My issue with it this way is that it has invented yet another way to
> > > > >> describe timings. I would like to be consistent across external bus
> > > > >> descriptions, but we're not very consistent to begin with though. The
> > > > >> most common seems to be the way you first did it. But I agree that it
> > > > >> is kind of screwy to have an intermediate node unless the controller
> > > > >> itself has sub-blocks within it and is not the established way to
> > > > >> describe a bus with chip selects. I would either put the properties
> > > > >> directly in the child nodes (e.g. flash at 0,0) or put your config nodes
> > > > >> in the device node. I'd call it timings instead of config, but that's
> > > > >> just bikeshedding.      
> > > > >
> > > > > Well, it's not only describing timings (see atmel,bus-width,
> > > > > atmel,byte-access-type, ...), but I'm fine with either names :).
> > > > >      
> > > > >>
> > > > >> memory-controller at 1000 {
> > > > >>   ...
> > > > >>   flash at 0,0 {
> > > > >>     timings {
> > > > >>       ...
> > > > >>     };
> > > > >>   };
> > > > >> };      
> > > > >
> > > > > Okay. Mark, what do you think of this approach?
> > > > >
> > > > > Note that one of my previous version was defining timings directly in
> > > > > the EBI device node, and Arnd noted that doing so may cause problems
> > > > > if one of the EBI property (or the config/timing node name) conflict
> > > > > with the sub-device binding, which is why I decided to put the EBI
> > > > > config definitions in a separate subnode.      
> > > > 
> > > > You have vendor prefixes on all the properties so I don't think a
> > > > collision is really a problem. It's also an established pattern in
> > > > i.MX WEIM and OMAP GPMC (which are hiding in bindings/bus/) and I
> > > > prefer consistency.    
> > > 
> > > So let's summarize that.
> > > 
> > > memory-controller at 1000 {
> > > 	...
> > > 	flash at 0,0 {
> > > 		atmel,<ebi-prop-name> = <value>;
> > > 		...
> > > 		<flash-device-prop> = <value>;
> > > 	};
> > > };
> > > 
> > > Would everyone agree on this representation?
> > > 
> > > With this approach, it's a bit more complicated to detect the case
> > > where we want to keep bootloader/firmware config, but it should be
> > > doable (it's much more easier to test for the presence of a
> > > config/timing node than verifying that either all or none of the
> > > mandatory properties are here).
> > > 
> > > Still remains the problem mentioned by Jean-Jacques: what if the
> > > sub-device takes 2 CS lines. Should we apply the same setting to those
> > > slots?
> > >   
> > 
> > Rob, Mark, Arnd, can you take a decision regarding this binding? This
> > driver is floating around for quite some time, and we were asked to
> > rework the binding several times (in time in an opposite direction).
> > 
> > For the record, here is the thread I mentioned earlier [1]. In his
> > answer, Arnd suggests to put timing and bus config description
> > outside of the sub-device node. Mark recently complained about this
> > representation, which led me to the configs/config-X appraoch, and now
> > Rob suggests to go back to the first proposal.
> > 
> > I'm fine doing that, but can you please all confirm that you agree on
> > this binding?  
> 
> Sorry for the delay in getting round to this, and sorry that this
> appears to be going in circles.
> 
> Please go with Rob's suggestion.

Okay. This changes a bit the constraints defined in the binding doc
(no default values for undefined properties: we just keep the
bootloader/firmware config), but otherwise should be easy to implement.

> 
> I'm not sure about the case where a device takes 2 CS lines. I would
> assume that in practice that a sub-device covered my multiple CS lines
> expects the same timings for all its MMIO space, and so having that
> uniform makes sense. Do we have a counter-example?

Nope, I don't. JJH had one (interfacing with an FPGA), maybe he can
detail this use case.


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


From k.kozlowski at samsung.com  Tue May 10 05:43:16 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 14:43:16 +0200
Subject: [PATCH] ARM: dts: exynos: Only Odroid XU3-family boards use DTSI
 with CPU thermal nodes
In-Reply-To: <CANAwSgTy6p9AVmmOWATpSO1JqVbwE0v+y_y-RLd+32RnNJTA+Q@mail.gmail.com>
References: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>
 <CANAwSgT9SY3kj8+beMpc1xGoC=rMBSya+2v2dyZQp6ykH+V0=g@mail.gmail.com>
 <573198BE.6020900@samsung.com>
 <CANAwSgTy6p9AVmmOWATpSO1JqVbwE0v+y_y-RLd+32RnNJTA+Q@mail.gmail.com>
Message-ID: <5731D764.8070007@samsung.com>

On 05/10/2016 11:29 AM, Anand Moon wrote:
>>
>> I am sorry but I do not understand.
>> 1. Are you saying that my patch causes the issue?
>> 2. Are you saying that I should not send some patches because of
>> conflicting work? (that would be peculiar...)
>> 3. Are you saying that I should not apply this patch to me tree because
>> of conflicting work?
>> 4. Other?
>>
>> Best regards.
>> Krzysztof
>>
>>
> 
> Sorry for the confusion it's not about you patch.
> The feature is not working correctly as per my testing with the
> original source code.
> It need to be more tuned or some other approach to the issue need to found.

Known issue. You don't have cpufreq cooling enabled. I sent patches for
that and they are in the mainline. However cpufreq cooling requires
cpufreq which cannot work with BL_SWITCHER and on Exynos542x on
exynos_defconfig BL_SWITCHER is enabled.

Just disable the BL_SWITCHER.

Best regards,
Krzysztof


From marex at denx.de  Tue May 10 05:46:52 2016
From: marex at denx.de (Marek Vasut)
Date: Tue, 10 May 2016 14:46:52 +0200
Subject: [PATCH] ARM: at91/defconfig: sama5: add CONFIG_FHANDLE
In-Reply-To: <5731D71A.5080500@atmel.com>
References: <572CC603.4000102@denx.de>
 <1462867383-31961-1-git-send-email-nicolas.ferre@atmel.com>
 <5731D49E.3080307@denx.de> <5731D71A.5080500@atmel.com>
Message-ID: <5731D83C.3030308@denx.de>

On 05/10/2016 02:42 PM, Nicolas Ferre wrote:
> Le 10/05/2016 14:31, Marek Vasut a ?crit :
>> On 05/10/2016 10:03 AM, Nicolas Ferre wrote:
>>> CONFIG_FHANDLE is listed as a mandatory kernel option for systemd. So
>>> explicitly enable it to allow easy use of systemd userspace.
>>>
>>> Reported-by: Marek Vasut <marex at denx.de>
>>> Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
>>> ---
>>> Hi Marek,
>>
>> Hi!
>>
>>> It seems that on my side, CONFIG_FHANDLE is not selected automatically...
>>> So I add this patch: can you tell me your thoughts?
>>
>> Uh, weird, I tried this on next just now:
>>
>> linux-2.6$ git describe HEAD
>> next-20160510
>>
>> linux-2.6$ export ARCH=arm ; export CROSS_COMPILE=arm-linux-gnueabi-
>>
>> linux-2.6$ make sama5_defconfig ; grep FHANDLE .config
>>   HOSTCC  scripts/basic/fixdep
>>   HOSTCC  scripts/kconfig/conf.o
>>   SHIPPED scripts/kconfig/zconf.tab.c
>>   SHIPPED scripts/kconfig/zconf.lex.c
>>   SHIPPED scripts/kconfig/zconf.hash.c
>>   HOSTCC  scripts/kconfig/zconf.tab.o
>>   HOSTLD  scripts/kconfig/conf
>> #
>> # configuration written to .config
>> #
>> CONFIG_FHANDLE=y
> 
> Absolutely. The patch f76be61755c5 ("Make CONFIG_FHANDLE default y") has
> been added in v4.6-rc2... while I was doing my tests on at91-next that
> is based on v4.6-rc1 :-\
> 
> Anyway. It's in now. Thanks,

Cool, thanks :)

-- 
Best regards,
Marek Vasut


From arnd at arndb.de  Tue May 10 05:50:43 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:50:43 +0200
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <5731D68D.2090109@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <7091358.aJt1stteb5@wuerfel> <5731D68D.2090109@huawei.com>
Message-ID: <4119683.coHZhzaE6c@wuerfel>

On Tuesday 10 May 2016 20:39:41 Zhangjian wrote:
> Hi,
> 
> On 2016/5/10 19:48, Arnd Bergmann wrote:
> > On Tuesday 10 May 2016 17:47:26 Zhangjian wrote:
> >> On 2016/5/10 16:36, Arnd Bergmann wrote:
> >>> On Tuesday 10 May 2016 15:42:07 Zhangjian wrote:
> >>>> On 2016/5/6 20:37, Yury Norov wrote:
> >>
> >> "include/uapi/asm-generic/posix_types.h" is uapi, we could not check
> >> "ARCH_32BIT_OFF_T" here. Besides, the `__kernel_long_t` is long which
> >> mean it is 32bit in ILP32. should we define something like x32?
> >>       ```
> >>       diff --git a/arch/arm64/include/uapi/asm/posix_types.h b/arch/arm64/include/uapi/asm/posix_types.h
> >>       index 7985ff6..9baa8d3 100644
> >>       --- a/arch/arm64/include/uapi/asm/posix_types.h
> >>       +++ b/arch/arm64/include/uapi/asm/posix_types.h
> >
> > glibc does not use the definition of __kernel_off_t, it has its own
> > copy, so changing the kernel headers would do nothing.
> Yes, I think so. I am puzzle that how do we ensure that all the new
> 32bit architecture will define off_t as 64bit after introduce
> ARCH_32BIT_OFF_T and do not change any other code?

This is for historic reasons: we have two sets of system calls passing
file offsets: the original ones passing a 'long' are named e.g. lseek,
pread, pwrite, fadvise, ...

The replacement syscalls that pass a 'long long' __kernel_loff_t are only
available on 32-bit architectures and have different names, e.g. llseek,
pread64, pwrite64, fadvise64, ...

On 64-bit architectures, we only provide the first set, because
__kernel_off_t was already wide enough. On old 32-bit architectures
we have both, and on new 32-bit architectures we only have the second
set, which lets us use the same definitions on all 32-bit architectures.

> >>       @@ -5,6 +5,9 @@ typedef unsigned short __kernel_old_uid_t;
> >>        typedef unsigned short __kernel_old_gid_t;
> >>         #define __kernel_old_uid_t __kernel_old_uid_t
> >>
> >>        +typedef long long __kernel_long_t;
> >>        +typedef unsigned long long __kernel_ulong_t;
> >>        +
> >>         #include <asm-generic/posix_types.h>
> >>
> >>         #endif /*  __ASM_POSIX_TYPES_H */u
> >>       ```
> >
> > This would break all sorts of things, because __kernel_long_t/__kernel_ulong_t
> > are not just used for off_t but also other things.
> Yes. But if we do not change __kernel_long_t and __kernel_ulong_t, the
> application of ilp32 will think size of long in kernel is 32bit. Is that
> correct?

No, __kernel_long_t refers to the definition of 'long' in the kernel/user
ABI, not in the kernel (except on the x86-64 "x32" ABI, which is weird).

A 32-bit user space application must not care about how 'long' is defined
in the kernel, it should run on either 32-bit kernels or 64-bit kernels.
We don't have any plans to do an ilp32-mode kernel, but if we ever want
one, it must use the exact same ABI as the 64-bit kernel when running
ilp32 user space.

> >>
> >> On the other hand, glibc define it own off_t in "bits/types.h":
> >>       __STD_TYPE __OFF_T_TYPE __off_t;        /* Type of file sizes and offsets.  */
> >>       __STD_TYPE __OFF64_T_TYPE __off64_t;    /* Type of file sizes and offsets (LFS).  */
> >>
> >> in "sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h":
> >>       #define __OFF_T_TYPE            __SLONGWORD_TYPE
> >>       #define __OFF64_T_TYPE          __SQUAD_TYPE
> >>
> >> If we define off_t as 64bit in glibc:
> >>       #define __OFF_T_TYPE           __SQUAD_TYPE
> >>
> >> Should We need to align all the off_t syscall to 64bit syscall in
> >> kernel?
> >>
> >
> > Yes, this is the change that I think we need to make, along with
> > the same change for __INO_T_TYPE and
> >
> > #define __OFF_T_MATCHES_OFF64_T        1
> > #define __INO_T_MATCHES_INO64_T        1
> >
> > If I read the rest of the glibc headers right, that should be all we need
> > to ensure that both off_t and off64_t match the __kernel_loff_t based
> > syscalls.
> Ok, I will test the ltp syscall test.
> With this changes, the issue I mentioned should be fixed. But we still
> use mmap2 syscall for ILP32 application when we pass the offset instead
> of page offset. Is it correct?

I don't remember. It's probably not important whether we have the shift
in there, as long as it's independent of the actual kernel page size and
user space and kernel agree on the calling conventions.

	Arnd


From javier at osg.samsung.com  Tue May 10 05:51:30 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 10 May 2016 08:51:30 -0400
Subject: [PATCH v2 20/22] ARM: dts: exynos: Move common
 Exynos5410/542x/5800 nodes to new DTSI
In-Reply-To: <57317292.2080004@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <1462734367-5619-21-git-send-email-krzk@kernel.org>
 <9e642e0d-87e1-4661-0233-acecf0082f24@osg.samsung.com>
 <57317292.2080004@kernel.org>
Message-ID: <68ebff12-702d-106a-7ce7-5063f62f3bc1@osg.samsung.com>

Hello Krzysztof,

On 05/10/2016 01:33 AM, Krzysztof Kozlowski wrote:
> On 05/09/2016 11:53 PM, Javier Martinez Canillas wrote:
>> Hello Krzysztof,
>>
>> On 05/08/2016 03:06 PM, Krzysztof Kozlowski wrote:
>>> The Exynos5410/542x/5800 are very similar designs. Create new new
>>
>> s/new new/a new
>>
>>> DTSI with common nodes to remove DTS duplication. Although currently
>>> only MCT and SysRAM are shared but in future more nodes will be added to
>>> common file.
>>>
>>> The patch should not have functional impact.
>>>
>>
>> A nice way to check this is to diff the disassembled compiled DTBs with
>> and without the patch and making sure that the resulted DTS is the same.
> 
> Yes, that is what I've done. Recently there is a tool making that even
> easier: dtx_diff.
>

I didn't know we had such a tool in mainline now.
Very useful, thanks a lot for the information.
 
> Best regards,
> Krzysztof
> 

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From arnd at arndb.de  Tue May 10 05:53:11 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 14:53:11 +0200
Subject: [GIT PULL] ARM: mvebu: arm64 for v4.7 (#1)
In-Reply-To: <87shy4scun.fsf@free-electrons.com>
References: <87shy4scun.fsf@free-electrons.com>
Message-ID: <3025942.ggz4obVPRx@wuerfel>

On Friday 29 April 2016 16:34:24 Gregory CLEMENT wrote:
> mvebu arm64 for 4.7
> 
> - Mention the arm64 SoCs in the MAINTAINER file
> - Enable syscon drivers for Marvell Armada 7K/8K (replacing the clk
>   one)
> 
> 

Pulled into next/arm64, thanks!

	Arnd


From lee.jones at linaro.org  Tue May 10 06:02:50 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Tue, 10 May 2016 14:02:50 +0100
Subject: [PATCH 3/5] remoteproc: core: Add ability to select a firmware
 from the client
In-Reply-To: <20160506185914.GF1256@tuxbot>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
 <1462454983-13168-4-git-send-email-lee.jones@linaro.org>
 <20160506185914.GF1256@tuxbot>
Message-ID: <20160510130250.GM19473@dell>

On Fri, 06 May 2016, Bjorn Andersson wrote:

> On Thu 05 May 06:29 PDT 2016, Lee Jones wrote:
> 
> > ST Co-Processors can be loaded with different firmwares to execute
> > specific tasks without the need for unloading the rproc module.
> > 
> 
> I'm very much interested in ideas related to this and who "owns" the
> life cycle of remoteprocs, do you have any code I can take a look at
> that's using this interface?

I was part of a conversation on the list which should explain some of
your queries [0].  The conclusion was, that only the client can know
what which firmware it is compatible with.  This information can not
realistically either live in DT (or any other platform data) or within
RemoteProc.  I hope that link answers your questions.

[0] http://www.spinics.net/lists/devicetree-spec/msg00144.html

> > This patch provides a function which can update the firmware name.
> > 
> > NB: This can only happen if the rproc is offline.
> 
> How is this working in the case when the remoteproc provides vdevs that
> is holding references towards the rproc?
> 
> Do you unload rpmsg et al before doing this?

RemoteProc needs to be offline for the firmware name to be set, this
includes links to RPMsg, so yes, they would have to be unloaded.

> > Signed-off-by: Ludovic Barre <ludovic.barre at st.com>
> > Signed-off-by: Lee Jones <lee.jones at linaro.org>
> > ---
> >  drivers/remoteproc/remoteproc_core.c | 63 ++++++++++++++++++++++++++++++++++++
> >  include/linux/remoteproc.h           | 13 ++++++++
> >  2 files changed, 76 insertions(+)

Happy with the remainder of your comments -- will fix.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


From andre.przywara at arm.com  Tue May 10 06:04:32 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue, 10 May 2016 14:04:32 +0100
Subject: [PATCH v3 26/55] KVM: arm/arm64: vgic-new: Add ACTIVE registers
 handlers
In-Reply-To: <5731D0B5.9060605@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-27-git-send-email-andre.przywara@arm.com>
 <5731D0B5.9060605@arm.com>
Message-ID: <5731DC60.40809@arm.com>

Hi Marc,

On 10/05/16 13:14, Marc Zyngier wrote:
> On 06/05/16 11:45, Andre Przywara wrote:
>> The active register handlers are shared between the v2 and v3
>> emulation, so their implementation goes into vgic-mmio.c, to be
>> easily referenced from the v3 emulation as well later.
>> Since activation/deactivation of an interrupt may happen entirely
>> in the guest without it ever exiting, we need some extra logic to
>> properly track the active state.
>> Putting it on an ap_list on activation is similar to the normal case
>> handled by vgic_queue_irq_unlock(), but differs in some details that
>> make a separate implementation worthwhile.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - handling queueing in write handler
>> - remove IRQ lock from read handler
>>
>> Changelog v1 .. v2:
>> - adapt to new MMIO framework
>>
>>  virt/kvm/arm/vgic/vgic-mmio-v2.c |   4 +-
>>  virt/kvm/arm/vgic/vgic-mmio.c    | 120 +++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic-mmio.h    |  10 ++++
>>  3 files changed, 132 insertions(+), 2 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> index 4b87e0a..054b52d 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> @@ -80,9 +80,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
>>  		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
>>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
>> index 4df1af7..dbf683e 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>> @@ -162,6 +162,126 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
>>  	}
>>  }
>>  
>> +unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
>> +				    gpa_t addr, unsigned int len)
>> +{
>> +	u32 intid = (addr & 0x7f) * 8;
>> +	u32 value = 0;
>> +	int i;
>> +
>> +	/* Loop over all IRQs affected by this read */
>> +	for (i = 0; i < len * 8; i++) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
>> +		if (irq->active)
>> +			value |= (1U << i);
>> +	}
>> +
>> +	return extract_bytes(value, addr & 3, len);
>> +}
>> +
>> +void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
>> +			     gpa_t addr, unsigned int len,
>> +			     unsigned long val)
>> +{
>> +	u32 intid = (addr & 0x7f) * 8;
>> +	int i;
>> +
>> +	for_each_set_bit(i, &val, len * 8) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
>> +		spin_lock(&irq->irq_lock);
>> +
>> +		irq->active = false;
>> +
>> +		/*
>> +		 * Christoffer wrote:
>> +		 * The question is what to do if the vcpu for this irq is
>> +		 * running and the LR there has the active bit set, then we'll
>> +		 * overwrite this change when we fold the LR state back into
>> +		 * the vgic_irq struct.
>> +		 *
>> +		 * Since I expect this to be extremely rare, one option is to
>> +		 * force irq->vcpu to exit (if non-null) and then do you
>> +		 * thing here after you've confirm it has exited while holding
>> +		 * some lock preventing it from re-entering again.
>> +		 * Slightly crazy.
>> +		 *
>> +		 * The alternative is to put a big fat comment nothing that
>> +		 * this is non-supported bad race, and wait until someone
>> +		 * submits a bug report relating to this...
>> +		 */
> 
> Don't we have a patch by Christoffer that addresses this exact issue?

Yes, and if I am not mistaken you said last week that we put this patch
and the firmware-independent probing on top of the queue, so I didn't
merge it.

>> +
>> +		spin_unlock(&irq->irq_lock);
>> +	}
>> +}
>> +
>> +void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
>> +			     gpa_t addr, unsigned int len,
>> +			     unsigned long val)
>> +{
>> +	u32 intid = (addr & 0x7f) * 8;
>> +	int i;
>> +
>> +	for_each_set_bit(i, &val, len * 8) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
>> +		spin_lock(&irq->irq_lock);
>> +
>> +		/* As this is a special case, we can't use the
>> +		 * vgic_queue_irq_unlock() function to put this on a VCPU.
>> +		 * So deal with this here explicitly unless the IRQs was
>> +		 * already active, it was on a VCPU before or there is no
>> +		 * target VCPU assigned at the moment.
>> +		 */
>> +		if (irq->active || irq->vcpu || !irq->target_vcpu) {
>> +			irq->active = true;
>> +
>> +			spin_unlock(&irq->irq_lock);
>> +			continue;
>> +		}
>> +
>> +		spin_unlock(&irq->irq_lock);
>> +retry:
>> +		vcpu = irq->target_vcpu;
>> +
>> +		spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
>> +		spin_lock(&irq->irq_lock);
>> +
>> +		/*
>> +		 * Recheck after dropping the IRQ lock to see if we should
>> +		 * still care about queueing it.
>> +		 */
>> +		if (irq->active || irq->vcpu) {
>> +			irq->active = true;
>> +
>> +			spin_unlock(&irq->irq_lock);
>> +			spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
>> +
>> +			continue;
>> +		}
>> +
>> +		/* Did the target VCPU change while we had the lock dropped? */
>> +		if (vcpu != irq->target_vcpu) {
>> +			spin_unlock(&irq->irq_lock);
>> +			spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
>> +
>> +			goto retry;
>> +		}
>> +
>> +		/* Now queue the IRQ to the VCPU's ap_list. */
>> +		list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
>> +		irq->vcpu = vcpu;
>> +
>> +		irq->active = true;
>> +
>> +		spin_unlock(&irq->irq_lock);
>> +		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
>> +
>> +		kvm_vcpu_kick(vcpu);
>> +	}
> 
> This is annoyingly close to vgic_queue_irq_unlock()... Maybe switching
> this to some form of preprocessor template. Or not.

I think we had this discussion with Christoffer before. There are subtle
differences and the impression was that unifying the two would make them
basically unreadable because of all this special handling.
Not sure if the preprocessor would help here.

Cheers,
Andre.

> 
>> +}
>> +
>>  static int match_region(const void *key, const void *elt)
>>  {
>>  	const unsigned int offset = (unsigned long)key;
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
>> index d4fc029..fa875dc 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio.h
>> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
>> @@ -96,6 +96,16 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
>>  			      gpa_t addr, unsigned int len,
>>  			      unsigned long val);
>>  
>> +unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
>> +				    gpa_t addr, unsigned int len);
>> +
>> +void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
>> +			     gpa_t addr, unsigned int len,
>> +			     unsigned long val);
>> +
>> +void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
>> +			     gpa_t addr, unsigned int len,
>> +			     unsigned long val);
>>  
>>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>>  
>>
> 
> Thanks,
> 
> 	M.
> 


From daniel.lezcano at linaro.org  Tue May 10 06:04:14 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 10 May 2016 15:04:14 +0200
Subject: [PATCH 2/4] drivers/clocksource/moxart: Refactor enable/disable
In-Reply-To: <CACPK8XfJ2e1kr-WftidvqsoYew7LqPiNo0sw7opgh8UH=3q_3A@mail.gmail.com>
References: <1462797169-14512-1-git-send-email-joel@jms.id.au>
 <1462797169-14512-3-git-send-email-joel@jms.id.au>
 <CACPK8XfJ2e1kr-WftidvqsoYew7LqPiNo0sw7opgh8UH=3q_3A@mail.gmail.com>
Message-ID: <20160510130414.GE14952@linaro.org>

On Tue, May 10, 2016 at 08:36:50PM +0930, Joel Stanley wrote:
> Hi Daniel,
> 
> Here's a commit message for this patch. If you'd prefer me to resend
> the entire series with this included then I can do that.

No, it is ok (except if there are comments on the patches before I merge 
them).
 
> This patch abstracts the enable and disable register writes into their
> own functions in preparation for future changes to use SoC specific
> values for the writes.

Thanks !

  -- Daniel


From jjhiblot at traphandler.com  Tue May 10 06:08:20 2016
From: jjhiblot at traphandler.com (Jean-Jacques Hiblot)
Date: Tue, 10 May 2016 15:08:20 +0200
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <20160510144143.1965ee5e@bbrezillon>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop> <20160503185153.5cfddc32@bbrezillon>
 <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
 <20160504113852.10a2dd84@bbrezillon>
 <CAL_Jsq+4aL5znA3zOKdcJb+pEXhVOQthkFF6DN2+P6U37t2o6g@mail.gmail.com>
 <20160504153547.60d736bb@bbrezillon> <20160510100448.49834120@bbrezillon>
 <20160510110742.GI687@leverpostej> <20160510144143.1965ee5e@bbrezillon>
Message-ID: <CACh+v5M2yZ403+VwvRMYeGwfhpP+aCGnnNhiQ1wjrxS5fVGVEA@mail.gmail.com>

2016-05-10 14:41 GMT+02:00 Boris Brezillon <boris.brezillon at free-electrons.com>:
> On Tue, 10 May 2016 12:07:42 +0100
> Mark Rutland <mark.rutland at arm.com> wrote:
>
>> On Tue, May 10, 2016 at 10:04:48AM +0200, Boris Brezillon wrote:
>> > On Wed, 4 May 2016 15:35:47 +0200
>> > Boris Brezillon <boris.brezillon at free-electrons.com> wrote:
>> >
>> > > On Wed, 4 May 2016 08:06:10 -0500
>> > > Rob Herring <robh at kernel.org> wrote:
>> > >
>> > > > On Wed, May 4, 2016 at 4:38 AM, Boris Brezillon
>> > > > <boris.brezillon at free-electrons.com> wrote:
>> > > > > Hi Rob,
>> > > > >
>> > > > > On Tue, 3 May 2016 14:11:04 -0500
>> > > > > Rob Herring <robh at kernel.org> wrote:
>> > > > >
>> > > > >> On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
>> > > > >> <boris.brezillon at free-electrons.com> wrote:
>> > > > >> > Hi Rob,
>> > > > >> >
>> > > > >> > On Tue, 3 May 2016 11:40:19 -0500
>> > > > >> > Rob Herring <robh at kernel.org> wrote:
>> > > > >> >
>> > > > >> >> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:
>> > > > >> >> > The EBI (External Bus Interface) is used to access external peripherals
>> > > > >> >> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
>> > > > >> >> > Each device is assigned a CS line and an address range and can have its
>> > > > >> >> > own configuration (timings, access mode, bus width, ...).
>> > > > >> >> > This driver provides a generic DT binding to configure a device according
>> > > > >> >> > to its requirements.
>> > > > >> >> > For specific device controllers (like the NAND one) the SMC timings
>> > > > >> >> > should be configured by the controller driver through the matrix and smc
>> > > > >> >> > syscon regmaps.
>> > > >
>> > > > [...]
>> > > >
>> > > > >> >> > +EBI bus configuration associated with specific chip-select will be defined in
>> > > > >> >> > +the configs subnode. This configs node will in turn contain several subnodes
>> > > > >> >> > +named config-<cs-id>, each of them containing the following properties.
>> > > > >> >>
>> > > > >> >> This is a bit unusual. Why not just part of the child device nodes?
>> > > > >> >
>> > > > >> > Oh, come on! I reworked the binding because Mark complained about the
>> > > > >> > previous binding which was doing exactly what you're suggesting. Can
>> > > > >> > you please be consistent in your reviews...
>> > > > >>
>> > > > >> No, Mark and I both have our opinions. Which part of this patch
>> > > > >> explains the history?
>> > > > >
>> > > > > Hm, it's in patch 1/2 (just dropped the cover letter, which might not
>> > > > > be such a good idea).
>> > > > >
>> > > > >> If the revision history is not in the patch, I'm
>> > > > >> not looking at it.
>> > > > >>
>> > > > >> My issue with it this way is that it has invented yet another way to
>> > > > >> describe timings. I would like to be consistent across external bus
>> > > > >> descriptions, but we're not very consistent to begin with though. The
>> > > > >> most common seems to be the way you first did it. But I agree that it
>> > > > >> is kind of screwy to have an intermediate node unless the controller
>> > > > >> itself has sub-blocks within it and is not the established way to
>> > > > >> describe a bus with chip selects. I would either put the properties
>> > > > >> directly in the child nodes (e.g. flash at 0,0) or put your config nodes
>> > > > >> in the device node. I'd call it timings instead of config, but that's
>> > > > >> just bikeshedding.
>> > > > >
>> > > > > Well, it's not only describing timings (see atmel,bus-width,
>> > > > > atmel,byte-access-type, ...), but I'm fine with either names :).
>> > > > >
>> > > > >>
>> > > > >> memory-controller at 1000 {
>> > > > >>   ...
>> > > > >>   flash at 0,0 {
>> > > > >>     timings {
>> > > > >>       ...
>> > > > >>     };
>> > > > >>   };
>> > > > >> };
>> > > > >
>> > > > > Okay. Mark, what do you think of this approach?
>> > > > >
>> > > > > Note that one of my previous version was defining timings directly in
>> > > > > the EBI device node, and Arnd noted that doing so may cause problems
>> > > > > if one of the EBI property (or the config/timing node name) conflict
>> > > > > with the sub-device binding, which is why I decided to put the EBI
>> > > > > config definitions in a separate subnode.
>> > > >
>> > > > You have vendor prefixes on all the properties so I don't think a
>> > > > collision is really a problem. It's also an established pattern in
>> > > > i.MX WEIM and OMAP GPMC (which are hiding in bindings/bus/) and I
>> > > > prefer consistency.
>> > >
>> > > So let's summarize that.
>> > >
>> > > memory-controller at 1000 {
>> > >   ...
>> > >   flash at 0,0 {
>> > >           atmel,<ebi-prop-name> = <value>;
>> > >           ...
>> > >           <flash-device-prop> = <value>;
>> > >   };
>> > > };
>> > >
>> > > Would everyone agree on this representation?
>> > >
>> > > With this approach, it's a bit more complicated to detect the case
>> > > where we want to keep bootloader/firmware config, but it should be
>> > > doable (it's much more easier to test for the presence of a
>> > > config/timing node than verifying that either all or none of the
>> > > mandatory properties are here).
>> > >
>> > > Still remains the problem mentioned by Jean-Jacques: what if the
>> > > sub-device takes 2 CS lines. Should we apply the same setting to those
>> > > slots?
>> > >
>> >
>> > Rob, Mark, Arnd, can you take a decision regarding this binding? This
>> > driver is floating around for quite some time, and we were asked to
>> > rework the binding several times (in time in an opposite direction).
>> >
>> > For the record, here is the thread I mentioned earlier [1]. In his
>> > answer, Arnd suggests to put timing and bus config description
>> > outside of the sub-device node. Mark recently complained about this
>> > representation, which led me to the configs/config-X appraoch, and now
>> > Rob suggests to go back to the first proposal.
>> >
>> > I'm fine doing that, but can you please all confirm that you agree on
>> > this binding?
>>
>> Sorry for the delay in getting round to this, and sorry that this
>> appears to be going in circles.
>>
>> Please go with Rob's suggestion.
>
> Okay. This changes a bit the constraints defined in the binding doc
> (no default values for undefined properties: we just keep the
> bootloader/firmware config), but otherwise should be easy to implement.
>
>>
>> I'm not sure about the case where a device takes 2 CS lines. I would
>> assume that in practice that a sub-device covered my multiple CS lines
>> expects the same timings for all its MMIO space, and so having that
>> uniform makes sense. Do we have a counter-example?
>
> Nope, I don't. JJH had one (interfacing with an FPGA), maybe he can
> detail this use case.
>
I don't either. It makes sense that a single device with 2 CS uses the
same timings.
My use case was the other way around: 1 CS for several devices.

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


From christoffer.dall at linaro.org  Tue May 10 06:11:16 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 10 May 2016 15:11:16 +0200
Subject: [PATCH v3 17/55] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <1462531568-9799-18-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-18-git-send-email-andre.przywara@arm.com>
Message-ID: <20160510131116.GE27623@cbox>

On Fri, May 06, 2016 at 11:45:30AM +0100, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Implement the framework for syncing IRQs between our emulation and
> the list registers, which represent the guest's view of IRQs.
> This is done in kvm_vgic_flush_hwstate and kvm_vgic_sync_hwstate,
> which gets called on guest entry and exit.
> The code talking to the actual GICv2/v3 hardware is added in the
> following patches.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>

> Changelog RFC..v1:
> - split out vgic_clear_lr() from vgic_populate_lr()
> - rename vgic_populate_lrs() to vgic_flush_lr_state()
> - clean all LRs when the distributor is disabled
> - use list_del() instead of list_del_init()
> - add comments to explain the direction of sync/flush_hwstate
> - remove unneeded BUG_ON(in_interrupt()
> 
> Changelog v2 .. v3:
> - remove bogus v2 specific rebase leftovers
> 
>  include/kvm/vgic/vgic.h  |   4 +
>  virt/kvm/arm/vgic/vgic.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h |   2 +
>  3 files changed, 199 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 2bfb42c..5fae4a9 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -190,6 +190,10 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
>  			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
>  
> +bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
> +void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
> +void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
> +
>  /**
>   * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
>   *
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 4fb20fd..c6f8b9b 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -305,3 +305,196 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  {
>  	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
>  }
> +
> +/**
> + * vgic_prune_ap_list - Remove non-relevant interrupts from the list
> + *
> + * @vcpu: The VCPU pointer
> + *
> + * Go over the list of "interesting" interrupts, and prune those that we
> + * won't have to consider in the near future.
> + */
> +static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq, *tmp;
> +
> +retry:
> +	spin_lock(&vgic_cpu->ap_list_lock);
> +
> +	list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
> +		struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		BUG_ON(vcpu != irq->vcpu);
> +
> +		target_vcpu = vgic_target_oracle(irq);
> +
> +		if (!target_vcpu) {
> +			/*
> +			 * We don't need to process this interrupt any
> +			 * further, move it off the list.
> +			 */
> +			list_del(&irq->ap_list);
> +			irq->vcpu = NULL;
> +			spin_unlock(&irq->irq_lock);
> +			continue;
> +		}
> +
> +		if (target_vcpu == vcpu) {
> +			/* We're on the right CPU */
> +			spin_unlock(&irq->irq_lock);
> +			continue;
> +		}
> +
> +		/* This interrupt looks like it has to be migrated. */
> +
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vgic_cpu->ap_list_lock);
> +
> +		/*
> +		 * Ensure locking order by always locking the smallest
> +		 * ID first.
> +		 */
> +		if (vcpu->vcpu_id < target_vcpu->vcpu_id) {
> +			vcpuA = vcpu;
> +			vcpuB = target_vcpu;
> +		} else {
> +			vcpuA = target_vcpu;
> +			vcpuB = vcpu;
> +		}
> +
> +		spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
> +		spin_lock(&vcpuB->arch.vgic_cpu.ap_list_lock);
> +		spin_lock(&irq->irq_lock);
> +
> +		/*
> +		 * If the affinity has been preserved, move the
> +		 * interrupt around. Otherwise, it means things have
> +		 * changed while the interrupt was unlocked, and we
> +		 * need to replay this.
> +		 *
> +		 * In all cases, we cannot trust the list not to have
> +		 * changed, so we restart from the beginning.
> +		 */
> +		if (target_vcpu == vgic_target_oracle(irq)) {
> +			struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;
> +
> +			list_del(&irq->ap_list);
> +			irq->vcpu = target_vcpu;
> +			list_add_tail(&irq->ap_list, &new_cpu->ap_list_head);
> +		}
> +
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
> +		spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
> +		goto retry;
> +	}
> +
> +	spin_unlock(&vgic_cpu->ap_list_lock);
> +}
> +
> +static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +/* Requires the ap_list_lock and the irq_lock to be held. */
> +static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
> +				    struct vgic_irq *irq, int lr)
> +{
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
> +}
> +
> +static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
> +{
> +}
> +
> +static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq;
> +	int count = 0;
> +
> +	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
> +		spin_lock(&irq->irq_lock);
> +		/* GICv2 SGIs can count for more than one... */
> +		if (vgic_irq_is_sgi(irq->intid) && irq->source)
> +			count += hweight8(irq->source);
> +		else
> +			count++;
> +		spin_unlock(&irq->irq_lock);
> +	}
> +	return count;
> +}
> +
> +/* Requires the VCPU's ap_list_lock to be held. */
> +static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq;
> +	int count = 0;
> +
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
> +
> +	if (unlikely(!vcpu->kvm->arch.vgic.enabled))
> +		goto out_clean;
> +
> +	if (compute_ap_list_depth(vcpu) > kvm_vgic_global_state.nr_lr) {
> +		vgic_set_underflow(vcpu);
> +		vgic_sort_ap_list(vcpu);
> +	}
> +
> +	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
> +		spin_lock(&irq->irq_lock);
> +
> +		if (unlikely(vgic_target_oracle(irq) != vcpu))
> +			goto next;
> +
> +		/*
> +		 * If we get an SGI with multiple sources, try to get
> +		 * them in all at once.
> +		 */
> +		do {
> +			vgic_populate_lr(vcpu, irq, count++);
> +		} while (irq->source && count < kvm_vgic_global_state.nr_lr);
> +
> +next:
> +		spin_unlock(&irq->irq_lock);
> +
> +		if (count == kvm_vgic_global_state.nr_lr)
> +			break;
> +	}
> +
> +out_clean:
> +	vcpu->arch.vgic_cpu.used_lrs = count;
> +
> +	/* Nuke remaining LRs */
> +	for ( ; count < kvm_vgic_global_state.nr_lr; count++)
> +		vgic_clear_lr(vcpu, count);
> +}
> +
> +/* Sync back the hardware VGIC state into our emulation after a guest's run. */
> +void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
> +{
> +	vgic_process_maintenance_interrupt(vcpu);
> +	vgic_fold_lr_state(vcpu);
> +	vgic_prune_ap_list(vcpu);
> +}
> +
> +/* Flush our emulation state into the GIC hardware before entering the guest. */
> +void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
> +{
> +	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +	vgic_flush_lr_state(vcpu);
> +	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index c625767..29b96b9 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -16,6 +16,8 @@
>  #ifndef __KVM_ARM_VGIC_NEW_H__
>  #define __KVM_ARM_VGIC_NEW_H__
>  
> +#define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
> +
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid);
>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
> -- 
> 2.7.3
> 


From adrian.hunter at intel.com  Tue May 10 06:07:53 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 16:07:53 +0300
Subject: [PATCH 22/23] mmc: sdhci-esdhc-imx: move tuning static
 configuration into hwinit function
In-Reply-To: <1460741387-23815-23-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-23-git-send-email-aisheng.dong@nxp.com>
Message-ID: <5731DD29.3020307@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> Move tuning static configuration into hwinit function.
> Tuning configuration may also be lost in low power mode,
> so need restore in hwinit().
> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>

Acked-by: Adrian Hunter <adrian.hunter at intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 36 ++++++++++++++++++------------------
>  1 file changed, 18 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 95f3632..98aa6b5 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -483,7 +483,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
>  			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
>  			u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL);
> -			u32 tuning_ctrl;
>  			if (val & SDHCI_CTRL_TUNED_CLK) {
>  				v |= ESDHC_MIX_CTRL_SMPCLK_SEL;
>  			} else {
> @@ -496,18 +495,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
>  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
>  				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> -				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> -				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
> -				if (imx_data->boarddata.tuning_start_tap) {
> -					tuning_ctrl &= ~ESDHC_TUNING_START_TAP_MASK;
> -					tuning_ctrl |= imx_data->boarddata.tuning_start_tap;
> -				}
> -
> -				if (imx_data->boarddata.tuning_step) {
> -					tuning_ctrl &= ~ESDHC_TUNING_STEP_MASK;
> -					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
> -				}
> -				writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);
>  			} else {
>  				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
>  			}
> @@ -982,6 +969,7 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
>  {
>  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>  	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> +	int tmp;
>  
>  	if (esdhc_is_usdhc(imx_data)) {
>  		/*
> @@ -1013,6 +1001,23 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
>  
>  		/* disable DLL_CTRL delay line settings */
>  		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
> +
> +		if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
> +			tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> +			tmp |= ESDHC_STD_TUNING_EN |
> +				ESDHC_TUNING_START_TAP_DEFAULT;
> +			if (imx_data->boarddata.tuning_start_tap) {
> +				tmp &= ~ESDHC_TUNING_START_TAP_MASK;
> +				tmp |= imx_data->boarddata.tuning_start_tap;
> +			}
> +
> +			if (imx_data->boarddata.tuning_step) {
> +				tmp &= ~ESDHC_TUNING_STEP_MASK;
> +				tmp |= imx_data->boarddata.tuning_step
> +					<< ESDHC_TUNING_STEP_SHIFT;
> +			}
> +			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
> +		}
>  	}
>  }
>  
> @@ -1226,11 +1231,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
>  		sdhci_esdhc_ops.platform_execute_tuning =
>  					esdhc_executing_tuning;
>  
> -	if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING)
> -		writel(readl(host->ioaddr + ESDHC_TUNING_CTRL) |
> -			ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT,
> -			host->ioaddr + ESDHC_TUNING_CTRL);
> -
>  	if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
>  		host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
>  
> 



From christoffer.dall at linaro.org  Tue May 10 06:12:59 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 10 May 2016 15:12:59 +0200
Subject: [PATCH v3 26/55] KVM: arm/arm64: vgic-new: Add ACTIVE registers
 handlers
In-Reply-To: <5731DC60.40809@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-27-git-send-email-andre.przywara@arm.com>
 <5731D0B5.9060605@arm.com> <5731DC60.40809@arm.com>
Message-ID: <20160510131259.GA20499@cbox>

On Tue, May 10, 2016 at 02:04:32PM +0100, Andre Przywara wrote:
> Hi Marc,
> 
> On 10/05/16 13:14, Marc Zyngier wrote:
> > On 06/05/16 11:45, Andre Przywara wrote:
> >> The active register handlers are shared between the v2 and v3
> >> emulation, so their implementation goes into vgic-mmio.c, to be
> >> easily referenced from the v3 emulation as well later.
> >> Since activation/deactivation of an interrupt may happen entirely
> >> in the guest without it ever exiting, we need some extra logic to
> >> properly track the active state.
> >> Putting it on an ap_list on activation is similar to the normal case
> >> handled by vgic_queue_irq_unlock(), but differs in some details that
> >> make a separate implementation worthwhile.
> >>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >> Changelog RFC..v1:
> >> - handling queueing in write handler
> >> - remove IRQ lock from read handler
> >>
> >> Changelog v1 .. v2:
> >> - adapt to new MMIO framework
> >>
> >>  virt/kvm/arm/vgic/vgic-mmio-v2.c |   4 +-
> >>  virt/kvm/arm/vgic/vgic-mmio.c    | 120 +++++++++++++++++++++++++++++++++++++++
> >>  virt/kvm/arm/vgic/vgic-mmio.h    |  10 ++++
> >>  3 files changed, 132 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> index 4b87e0a..054b52d 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> @@ -80,9 +80,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
> >>  		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
> >> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
> >> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
> >>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> >> index 4df1af7..dbf683e 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> >> @@ -162,6 +162,126 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
> >>  	}
> >>  }
> >>  
> >> +unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
> >> +				    gpa_t addr, unsigned int len)
> >> +{
> >> +	u32 intid = (addr & 0x7f) * 8;
> >> +	u32 value = 0;
> >> +	int i;
> >> +
> >> +	/* Loop over all IRQs affected by this read */
> >> +	for (i = 0; i < len * 8; i++) {
> >> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> >> +
> >> +		if (irq->active)
> >> +			value |= (1U << i);
> >> +	}
> >> +
> >> +	return extract_bytes(value, addr & 3, len);
> >> +}
> >> +
> >> +void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
> >> +			     gpa_t addr, unsigned int len,
> >> +			     unsigned long val)
> >> +{
> >> +	u32 intid = (addr & 0x7f) * 8;
> >> +	int i;
> >> +
> >> +	for_each_set_bit(i, &val, len * 8) {
> >> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> >> +
> >> +		spin_lock(&irq->irq_lock);
> >> +
> >> +		irq->active = false;
> >> +
> >> +		/*
> >> +		 * Christoffer wrote:
> >> +		 * The question is what to do if the vcpu for this irq is
> >> +		 * running and the LR there has the active bit set, then we'll
> >> +		 * overwrite this change when we fold the LR state back into
> >> +		 * the vgic_irq struct.
> >> +		 *
> >> +		 * Since I expect this to be extremely rare, one option is to
> >> +		 * force irq->vcpu to exit (if non-null) and then do you
> >> +		 * thing here after you've confirm it has exited while holding
> >> +		 * some lock preventing it from re-entering again.
> >> +		 * Slightly crazy.
> >> +		 *
> >> +		 * The alternative is to put a big fat comment nothing that
> >> +		 * this is non-supported bad race, and wait until someone
> >> +		 * submits a bug report relating to this...
> >> +		 */
> > 
> > Don't we have a patch by Christoffer that addresses this exact issue?
> 
> Yes, and if I am not mistaken you said last week that we put this patch
> and the firmware-independent probing on top of the queue, so I didn't
> merge it.
> 
> >> +
> >> +		spin_unlock(&irq->irq_lock);
> >> +	}
> >> +}
> >> +
> >> +void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
> >> +			     gpa_t addr, unsigned int len,
> >> +			     unsigned long val)
> >> +{
> >> +	u32 intid = (addr & 0x7f) * 8;
> >> +	int i;
> >> +
> >> +	for_each_set_bit(i, &val, len * 8) {
> >> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> >> +
> >> +		spin_lock(&irq->irq_lock);
> >> +
> >> +		/* As this is a special case, we can't use the
> >> +		 * vgic_queue_irq_unlock() function to put this on a VCPU.
> >> +		 * So deal with this here explicitly unless the IRQs was
> >> +		 * already active, it was on a VCPU before or there is no
> >> +		 * target VCPU assigned at the moment.
> >> +		 */
> >> +		if (irq->active || irq->vcpu || !irq->target_vcpu) {
> >> +			irq->active = true;
> >> +
> >> +			spin_unlock(&irq->irq_lock);
> >> +			continue;
> >> +		}
> >> +
> >> +		spin_unlock(&irq->irq_lock);
> >> +retry:
> >> +		vcpu = irq->target_vcpu;
> >> +
> >> +		spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
> >> +		spin_lock(&irq->irq_lock);
> >> +
> >> +		/*
> >> +		 * Recheck after dropping the IRQ lock to see if we should
> >> +		 * still care about queueing it.
> >> +		 */
> >> +		if (irq->active || irq->vcpu) {
> >> +			irq->active = true;
> >> +
> >> +			spin_unlock(&irq->irq_lock);
> >> +			spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> >> +
> >> +			continue;
> >> +		}
> >> +
> >> +		/* Did the target VCPU change while we had the lock dropped? */
> >> +		if (vcpu != irq->target_vcpu) {
> >> +			spin_unlock(&irq->irq_lock);
> >> +			spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> >> +
> >> +			goto retry;
> >> +		}
> >> +
> >> +		/* Now queue the IRQ to the VCPU's ap_list. */
> >> +		list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
> >> +		irq->vcpu = vcpu;
> >> +
> >> +		irq->active = true;
> >> +
> >> +		spin_unlock(&irq->irq_lock);
> >> +		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> >> +
> >> +		kvm_vcpu_kick(vcpu);
> >> +	}
> > 
> > This is annoyingly close to vgic_queue_irq_unlock()... Maybe switching
> > this to some form of preprocessor template. Or not.
> 
> I think we had this discussion with Christoffer before. There are subtle
> differences and the impression was that unifying the two would make them
> basically unreadable because of all this special handling.
> Not sure if the preprocessor would help here.
> 
If we changed the queue function slightly as I suggested, I haven't been
able to come up with a case were we can't do:

spin_lock(&irq->irq_lock);
vgic_queue_irq_unlock(irq);

but I need to look at it more carefully.

-Christoffer


From adrian.hunter at intel.com  Tue May 10 06:10:38 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 10 May 2016 16:10:38 +0300
Subject: [PATCH 23/23] mmc: sdhci-esdhc-imx: clear tuning bits during
 hwinit
In-Reply-To: <1460741387-23815-24-git-send-email-aisheng.dong@nxp.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-24-git-send-email-aisheng.dong@nxp.com>
Message-ID: <5731DDCE.7020102@intel.com>

On 15/04/16 20:29, Dong Aisheng wrote:
> The tuning bits like FBCLK_SEL, SMP_CLK_SEL and DLY_CELL which affects
> timing may have already been set by ROM if booting from SD3.0 mode like
> SDR104. Let's clear it first during hw initialization before do the
> new card enumeration.
> 
> For system resume case, it's safe to clear them too since the following
> card re-initialization in mmc_xx_init_card() will do retuning and set
> correct value again.
> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>

Acked-by: Adrian Hunter <adrian.hunter at intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 98aa6b5..6a699d1 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -1018,6 +1018,11 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
>  			}
>  			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
>  		}
> +
> +		/* clear tuning bits in case ROM has set it already */
> +		writel(0x0, host->ioaddr + ESDHC_MIX_CTRL);
> +		writel(0x0, host->ioaddr + SDHCI_ACMD12_ERR);
> +		writel(0x0, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
>  	}
>  }
>  
> 



From marc.zyngier at arm.com  Tue May 10 06:16:44 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 14:16:44 +0100
Subject: [PATCH] KVM: arm/arm64: vgic-new: fix overlap check for device
 addresses
In-Reply-To: <1462877922-8743-1-git-send-email-andre.przywara@arm.com>
References: <5730C65D.5000609@arm.com>
 <1462877922-8743-1-git-send-email-andre.przywara@arm.com>
Message-ID: <5731DF3C.6020201@arm.com>

On 10/05/16 11:58, Andre Przywara wrote:
> When userland sets the base addresses for the GIC register frames,
> the kernel tries to make sure that the regions for the distributor and
> the one for the CPU interface or the redistributors do not overlap.
> Only that this check currently takes care of a GICv2 model only.
> Rework the overlap check to take a GICv3 in account also.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Hi Marc,
> 
> this one goes on top of the new-vgic-v3 series.
> Does this address your concerns about the overlap check?
> I'd be grateful if you could apply some of your C wizardry on the first
> function ;-)
> 
> Cheers,
> Andre.
> 
>  virt/kvm/arm/vgic/vgic-kvm-device.c | 59 ++++++++++++++++++++++++++-----------
>  1 file changed, 41 insertions(+), 18 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index 2122ff2..fcf38ef 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -21,41 +21,63 @@
>  
>  /* common helpers */
>  
> -static int vgic_ioaddr_overlap(struct kvm *kvm)
> +static phys_addr_t vgic_get_existing_region(struct kvm *kvm, phys_addr_t *addr)
>  {
> -	phys_addr_t dist = kvm->arch.vgic.vgic_dist_base;
> -	phys_addr_t cpu = kvm->arch.vgic.vgic_cpu_base;
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	phys_addr_t cpu_addr;
> +	bool is_vgicv2 = (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2);
>  
> -	if (IS_VGIC_ADDR_UNDEF(dist) || IS_VGIC_ADDR_UNDEF(cpu))
> -		return 0;
> -	if ((dist <= cpu && dist + KVM_VGIC_V2_DIST_SIZE > cpu) ||
> -	    (cpu <= dist && cpu + KVM_VGIC_V2_CPU_SIZE > dist))
> -		return -EBUSY;
> -	return 0;
> +	cpu_addr = is_vgicv2 ? dist->vgic_cpu_base : dist->vgic_redist_base;
> +
> +	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base)) {
> +		if (IS_VGIC_ADDR_UNDEF(cpu_addr))
> +			return 0;
> +
> +		*addr = cpu_addr;
> +		if (is_vgicv2)
> +			return KVM_VGIC_V2_CPU_SIZE;
> +		return atomic_read(&kvm->online_vcpus) * KVM_VGIC_V3_REDIST_SIZE;
> +	}
> +
> +	*addr = dist->vgic_dist_base;
> +	return is_vgicv2 ? KVM_VGIC_V2_DIST_SIZE : KVM_VGIC_V3_DIST_SIZE;
> +}
> +
> +static bool vgic_ioaddr_overlap(struct kvm *kvm, phys_addr_t addr,
> +				phys_addr_t size)
> +{
> +	phys_addr_t used_addr, used_size;
> +
> +	used_size = vgic_get_existing_region(kvm, &used_addr);
> +	if (!used_size)
> +		return false;
> +
> +	if (addr + size <= used_addr)
> +		return false;
> +
> +	if (used_addr + used_size <= addr)
> +		return false;
> +
> +	return true;
>  }
>  
>  static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
>  			      phys_addr_t addr, phys_addr_t size)
>  {
> -	int ret;
> -
>  	if (addr & ~KVM_PHYS_MASK)
>  		return -E2BIG;
>  
> -	if (addr & (SZ_4K - 1))
> -		return -EINVAL;
> -
>  	if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
>  		return -EEXIST;
>  	if (addr + size < addr)
>  		return -EINVAL;
>  
> +	if (vgic_ioaddr_overlap(kvm, addr, size))
> +		return -EBUSY;
> +
>  	*ioaddr = addr;
> -	ret = vgic_ioaddr_overlap(kvm);
> -	if (ret)
> -		*ioaddr = VGIC_ADDR_UNDEF;
>  
> -	return ret;
> +	return 0;
>  }
>  
>  /**
> @@ -104,6 +126,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
>  		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
>  		addr_ptr = &vgic->vgic_redist_base;
>  		block_size = KVM_VGIC_V3_REDIST_SIZE;
> +		block_size *= atomic_read(&kvm->online_vcpus);

What guarantees that the vcpus have been created already? AFAIU, you can
perfectly create the VM, then the GIC, and then the vcpus. So this would
be perfectly be allowed to be zero.

Or did I miss something?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From linux at roeck-us.net  Tue May 10 06:25:09 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 10 May 2016 06:25:09 -0700
Subject: [PATCH 2/2] watchdog: Add Aspeed watchdog driver
In-Reply-To: <CACPK8XfK4Qt2GaSL7eVoNkCawbtXqFX9bGRcgyAyq7R2yuSZkA@mail.gmail.com>
References: <1462797277-14969-1-git-send-email-joel@jms.id.au>
 <1462797277-14969-3-git-send-email-joel@jms.id.au>
 <5730A339.80006@roeck-us.net>
 <CACPK8XfK4Qt2GaSL7eVoNkCawbtXqFX9bGRcgyAyq7R2yuSZkA@mail.gmail.com>
Message-ID: <5731E135.8000100@roeck-us.net>

Hi Joel,

On 05/10/2016 04:10 AM, Joel Stanley wrote:

[ ... ]

>>> +
>>> +       /*
>>> +        * The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only
>>> +        * runs at 1MHz. We chose to always run at 1MHz, as there's no
>>> +        * good reason to have a faster watchdog counter.
>>> +        */
>>> +       wdt->rate = 1000000;
>>
>>
>> Why not just use a define ?
>
> I will add one.
>
> The comment is informative though for people who read the ast2400
> datasheet and wonder why we don't provide the option clocking with
> pclk, I will leave it in.
>

The comment is ok. I just find it unnecessary to have a variable
instead of a constant.

[ ... ]
>
>> ctrl is really static except for the enable flag. Not really sure
>> if having a variable for it has any real benefits - you might as well
>> just read the register and update the enable flag instead as needed when
>> starting or stopping the watchdog. Is there a reason for not doing that ?
>
> Not really. I find it cleaner to keep a copy of the register instead
> of read-modify-write, but if you feel strongly about it I can change.
>

No worries. Not worth arguing about.

Guenter



From christoffer.dall at linaro.org  Tue May 10 06:30:43 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 10 May 2016 15:30:43 +0200
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world
 switch backend
In-Reply-To: <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
Message-ID: <20160510133043.GF27623@cbox>

On Fri, May 06, 2016 at 11:45:31AM +0100, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Processing maintenance interrupts and accessing the list registers
> are dependent on the host's GIC version.
> Introduce vgic-v2.c to contain GICv2 specific functions.
> Implement the GICv2 specific code for syncing the emulation state
> into the VGIC registers.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - remove explicit LR_STATE clearing on maintenance interrupt handling
> - improve documentation for vgic_v2_populate_lr()
> - remove WARN_ON on non-edge IRQs in maintenance interrupts
> - simplify multi-CPU source SGI handling
> 
> Changelog v1 .. v2:
> - inject the IRQ priority into the list register
> 
> Changelog v2 .. v3:
> - cleanup diff containing rebase artifacts
> 
>  include/linux/irqchip/arm-gic.h |   1 +
>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.c        |   6 ++
>  virt/kvm/arm/vgic/vgic.h        |   6 ++
>  4 files changed, 191 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
> 
> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
> index 9c94026..be0d26f 100644
> --- a/include/linux/irqchip/arm-gic.h
> +++ b/include/linux/irqchip/arm-gic.h
> @@ -76,6 +76,7 @@
>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
> +#define GICH_LR_PRIORITY_SHIFT		23
>  #define GICH_LR_STATE			(3 << 28)
>  #define GICH_LR_PENDING_BIT		(1 << 28)
>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> new file mode 100644
> index 0000000..4cee616
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -0,0 +1,178 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * 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/irqchip/arm-gic.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +
> +#include "vgic.h"
> +
> +/*
> + * Call this function to convert a u64 value to an unsigned long * bitmask
> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
> + *
> + * Warning: Calling this function may modify *val.
> + */
> +static unsigned long *u64_to_bitmask(u64 *val)
> +{
> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
> +	*val = (*val >> 32) | (*val << 32);
> +#endif
> +	return (unsigned long *)val;
> +}
> +
> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
> +
> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
> +		u64 eisr = cpuif->vgic_eisr;
> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
> +		int lr;
> +
> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
> +			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
> +
> +			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
> +
> +			kvm_notify_acked_irq(vcpu->kvm, 0,
> +					     intid - VGIC_NR_PRIVATE_IRQS);
> +

why do we need to do this?  I cannot find any consumers of this info
after we've left the hyp code.

Also, I think I offered a comment about why we would potentially need
this in the first place.  This is the famous race where hardware doesn't
guarantee consistency between the MISR and ELRSR right?

> +			cpuif->vgic_elrsr |= 1ULL << lr;
> +		}
> +	}
> +
> +	/* check and disable underflow maintenance IRQ */
> +	cpuif->vgic_hcr &= ~GICH_HCR_UIE;
> +
> +	/*
> +	 * In the next iterations of the vcpu loop, if we sync the
> +	 * vgic state after flushing it, but before entering the guest
> +	 * (this happens for pending signals and vmid rollovers), then
> +	 * make sure we don't pick up any old maintenance interrupts
> +	 * here.
> +	 */
> +	cpuif->vgic_eisr = 0;
> +}
> +
> +void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
> +
> +	cpuif->vgic_hcr |= GICH_HCR_UIE;
> +}
> +
> +/*
> + * transfer the content of the LRs back into the corresponding ap_list:
> + * - active bit is transferred as is
> + * - pending bit is
> + *   - transferred as is in case of edge sensitive IRQs
> + *   - set to the line-level (resample time) for level sensitive IRQs
> + */
> +void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
> +	int lr;
> +
> +	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
> +		u32 val = cpuif->vgic_lr[lr];
> +		u32 intid = val & GICH_LR_VIRTUALID;
> +		struct vgic_irq *irq;
> +
> +		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		/* Always preserve the active bit */
> +		irq->active = !!(val & GICH_LR_ACTIVE_BIT);
> +
> +		/* Edge is the only case where we preserve the pending bit */
> +		if (irq->config == VGIC_CONFIG_EDGE &&
> +		    (val & GICH_LR_PENDING_BIT)) {
> +			irq->pending = true;
> +
> +			if (vgic_irq_is_sgi(intid)) {
> +				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
> +
> +				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
> +				irq->source |= (1 << cpuid);
> +			}
> +		}
> +
> +		/* Clear soft pending state when level IRQs have been acked */
> +		if (irq->config == VGIC_CONFIG_LEVEL &&
> +		    !(val & GICH_LR_PENDING_BIT)) {
> +			irq->soft_pending = false;
> +			irq->pending = irq->line_level;
> +		}
> +
> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
> +/*
> + * Populates the particular LR with the state of a given IRQ:
> + * - for an edge sensitive IRQ the pending state is cleared in struct vgic_irq
> + * - for a level sensitive IRQ the pending state value is unchanged;
> + *   it is dictated directly by the input level
> + *
> + * If @irq describes an SGI with multiple sources, we choose the
> + * lowest-numbered source VCPU and clear that bit in the source bitmap.
> + *
> + * The irq_lock must be held by the caller.
> + */
> +void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
> +{
> +	u32 val = irq->intid;
> +
> +	if (irq->pending) {
> +		val |= GICH_LR_PENDING_BIT;
> +
> +		if (irq->config == VGIC_CONFIG_EDGE)
> +			irq->pending = false;
> +
> +		if (vgic_irq_is_sgi(irq->intid)) {
> +			u32 src = ffs(irq->source);
> +
> +			BUG_ON(!src);
> +			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
> +			irq->source &= ~(1 << (src - 1));
> +			if (irq->source)
> +				irq->pending = true;
> +		}
> +	}
> +
> +	if (irq->active)
> +		val |= GICH_LR_ACTIVE_BIT;
> +
> +	if (irq->hw) {
> +		val |= GICH_LR_HW;
> +		val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
> +	} else {
> +		if (irq->config == VGIC_CONFIG_LEVEL)
> +			val |= GICH_LR_EOI;
> +	}
> +
> +	/* The GICv2 LR only holds five bits of priority. */
> +	val |= (irq->priority >> 3) << GICH_LR_PRIORITY_SHIFT;
> +
> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = val;
> +}
> +
> +void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
> +{
> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index c6f8b9b..68d885c 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -397,10 +397,12 @@ retry:
>  
>  static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
>  {
> +	vgic_v2_process_maintenance(vcpu);
>  }
>  
>  static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
>  {
> +	vgic_v2_fold_lr_state(vcpu);
>  }
>  
>  /* Requires the ap_list_lock and the irq_lock to be held. */
> @@ -409,14 +411,18 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
>  {
>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
> +
> +	vgic_v2_populate_lr(vcpu, irq, lr);
>  }
>  
>  static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
>  {
> +	vgic_v2_clear_lr(vcpu, lr);
>  }
>  
>  static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
>  {
> +	vgic_v2_set_underflow(vcpu);
>  }
>  
>  static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 29b96b9..0db490e 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -22,4 +22,10 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid);
>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
>  
> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
> +void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
> +void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
> +void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
> +void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
> +
>  #endif
> -- 
> 2.7.3
> 


From geert at linux-m68k.org  Tue May 10 06:33:43 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Tue, 10 May 2016 15:33:43 +0200
Subject: [PATCH] arm64: dts: r8a7795: Increase the size of GIC-400 mapped
 registers
In-Reply-To: <1461047395-6532-1-git-send-email-dirk.behme@de.bosch.com>
References: <1461047395-6532-1-git-send-email-dirk.behme@de.bosch.com>
Message-ID: <CAMuHMdV6XOSiSv-mwovnCAMEPsgOc_vEhPPu0aYCgz74EF242g@mail.gmail.com>

CC Marc, lakml

On Tue, Apr 19, 2016 at 8:29 AM, Dirk Behme <dirk.behme at de.bosch.com> wrote:
> From: Pooya Keshavarzi <Pooya.Keshavarzi at de.bosch.com>
>
> There are some requirements about the GIC-400 memory layout and its
> mapping if using 64k aligned base addresses like on r8a7795.
>
> See e.g.
>
> http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=21550029f709072aacf3b9
>
> Map the whole memory range instead of only 0x2000. This will fix
> the issue that some hypervisors, e.g. Xen, fail to handle the
> interrupts correctly.
>
> Signed-off-by: Pooya Keshavarzi <Pooya.Keshavarzi at de.bosch.com>
> Signed-off-by: Dirk Behme <dirk.behme at de.bosch.com>

Based on my understanding below
Acked-by: Geert Uytterhoeven <geert+renesas at glider.be>

> ---
> Note: This patch is against renesas-drivers-2016-04-12-v4.6-rc3
>
>  arch/arm64/boot/dts/renesas/r8a7795.dtsi | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
> index 8be9424..d880fd4 100644
> --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
> +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
> @@ -160,9 +160,9 @@
>                         #address-cells = <0>;
>                         interrupt-controller;
>                         reg = <0x0 0xf1010000 0 0x1000>,
> -                             <0x0 0xf1020000 0 0x2000>,
> +                             <0x0 0xf1020000 0 0x20000>,
>                               <0x0 0xf1040000 0 0x20000>,
> -                             <0x0 0xf1060000 0 0x2000>;
> +                             <0x0 0xf1060000 0 0x20000>;
>                         interrupts = <GIC_PPI 9
>                                         (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
>                 };

Region 0:
    4 KiB-pages 0xf1011000-0xf101ffff are aliased to 0xf1010000-0xf1010fff,
    but we need the first 4 KiB only.

Region 1:
    4 KiB-pages 0xf1021000-0xf102ffff are aliased to 0xf1020000-0xf1020fff,
    4 KiB-pages 0xf1030000-0xf103ffff are all zeroes, probably due to
    non-secure mode?

Region 2:
    4 KiB-pages 0xf1041000-0xf104ffff are aliased to 0xf1040000-0xf1040fff,
    4 KiB-pages 0xf1050000-0xf105ffff are all zeroes, probably due to
    non-secure mode?

Region 3:
    4 KiB-pages 0xf1061000-0xf106ffff are aliased to 0xf1060000-0xf1060fff,
    4 KiB-pages 0xf1070000-0xf107ffff are all zeroes, probably due to
    non-secure mode?

Region 2 already had a 128 KiB size before, which allowed to use 8 KiB at
0xf104f000.

An 8 KiB size for regions 1 and 3 indeed didn't make much sense, as this
covered two identical (aliased) 4 KiB pages, instead of two different pages
at offset 0xf000.

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 arnd at arndb.de  Tue May 10 06:39:03 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 15:39:03 +0200
Subject: [GIT PULL 2/3] Rockchip dts32 updates for v4.7 - part2
In-Reply-To: <76948175.MyD0mx7K4Q@diego>
References: <5544434.9tA8JHBIkp@diego> <76948175.MyD0mx7K4Q@diego>
Message-ID: <2872722.0tBjL4e5JT@wuerfel>

On Friday 29 April 2016 00:24:48 Heiko St?bner wrote:
> This adds the rk3288-miqi as new board, adapts the edp-phy settings
> to the binding-change that made it into 4.6, adds rk3288 i2c controller
> nodes and moves the rk3288 thermal data into the soc dtsi, as there
> really is no need to have that separate file.
> 

Pulled into next/dt, thanks!

	Arnd


From arnd at arndb.de  Tue May 10 06:40:01 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 15:40:01 +0200
Subject: [GIT PULL 2/4] DaVinci DT updates for v4.7 (part 2)
In-Reply-To: <1461931627-27761-2-git-send-email-nsekhar@ti.com>
References: <1461931627-27761-1-git-send-email-nsekhar@ti.com>
 <1461931627-27761-2-git-send-email-nsekhar@ti.com>
Message-ID: <6289720.CuHVqieX7b@wuerfel>

On Friday 29 April 2016 17:37:05 Sekhar Nori wrote:
> Second set of DT updates for DaVinci
> adding support for SPI0 and some low
> priority fixes for ethernet and interrupt
> controller.
> 

Pulled into next/dt, thanks!

	Arnd


From daniel.thompson at linaro.org  Tue May 10 06:41:54 2016
From: daniel.thompson at linaro.org (Daniel Thompson)
Date: Tue, 10 May 2016 14:41:54 +0100
Subject: [PATCH] arm64: kgdb: Match pstate size with gdbserver protocol
In-Reply-To: <20160510104511.GH687@leverpostej>
References: <1462815566-15086-1-git-send-email-daniel.thompson@linaro.org>
 <20160510104511.GH687@leverpostej>
Message-ID: <df946c87-162f-fdda-879b-76b4ad1a1c7a@linaro.org>

On 10/05/16 11:45, Mark Rutland wrote:
>> When commit 44679a4f142b ("arm64: KGDB: Add step debugging support") was
>> introduced it was paired with a gdb patch that made an incompatible
>> change to the gdbserver protocol. This patch was eventually merged into
>> the gdb sources:
>> https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=a4d9ba85ec5597a6a556afe26b712e878374b9dd
>>
>> The change to the protocol was mostly made to simplify big-endian support
>> inside the kernel gdb stub.
>
> While that was how we discovered the inconsistency, a major concern is
> that SPSR_EL* (i.e. PSTATE), as accessed by MRS/MSR is a 64-bit
> quantity, even if the upper 32 bits are RES0 today.
>
> It is conceivable that the upper 32 bits could be used in future (as
> happened with CLIDR_EL1), and for this reason we expose those upper 32
> bits from the kernel, and treat system registers as 64-bit quantities
> generally.

These cases are not exactly the same.

CLIDR_ELx is (or was) architecturally defined as a 64-bit register and 
explicitly marks the upper 32-bits as RES0.

That is not the case for SPSR_ELx; this register is architecturally 
defined to be 32-bit.

I know that doesn't *prevent* SPSR_ELx from being expanded in the future 
it is not unreasonable for gdb to design its wire protocol based on the 
description found in the architecture manual.


> So this was also about ensuring the interface was consistent and to some
> extent future-proof.

gdb remote protocol is already future proof and has never at any point 
contradicted the architecture.

However the changes to the protocol in 7.7.x and 7.8.0 were analogous to 
an unexpected ABI change rather than a carefully controlled introduction 
of a new feature. Like the kernel, once detected, they were reversed ;-) .


Daniel.



From marc.zyngier at arm.com  Tue May 10 06:42:02 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 14:42:02 +0100
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <20160510133043.GF27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
 <20160510133043.GF27623@cbox>
Message-ID: <5731E52A.9000402@arm.com>

On 10/05/16 14:30, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:31AM +0100, Andre Przywara wrote:
>> From: Marc Zyngier <marc.zyngier at arm.com>
>>
>> Processing maintenance interrupts and accessing the list registers
>> are dependent on the host's GIC version.
>> Introduce vgic-v2.c to contain GICv2 specific functions.
>> Implement the GICv2 specific code for syncing the emulation state
>> into the VGIC registers.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - remove explicit LR_STATE clearing on maintenance interrupt handling
>> - improve documentation for vgic_v2_populate_lr()
>> - remove WARN_ON on non-edge IRQs in maintenance interrupts
>> - simplify multi-CPU source SGI handling
>>
>> Changelog v1 .. v2:
>> - inject the IRQ priority into the list register
>>
>> Changelog v2 .. v3:
>> - cleanup diff containing rebase artifacts
>>
>>  include/linux/irqchip/arm-gic.h |   1 +
>>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic.c        |   6 ++
>>  virt/kvm/arm/vgic/vgic.h        |   6 ++
>>  4 files changed, 191 insertions(+)
>>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
>>
>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>> index 9c94026..be0d26f 100644
>> --- a/include/linux/irqchip/arm-gic.h
>> +++ b/include/linux/irqchip/arm-gic.h
>> @@ -76,6 +76,7 @@
>>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
>>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
>>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
>> +#define GICH_LR_PRIORITY_SHIFT		23
>>  #define GICH_LR_STATE			(3 << 28)
>>  #define GICH_LR_PENDING_BIT		(1 << 28)
>>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
>> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
>> new file mode 100644
>> index 0000000..4cee616
>> --- /dev/null
>> +++ b/virt/kvm/arm/vgic/vgic-v2.c
>> @@ -0,0 +1,178 @@
>> +/*
>> + * Copyright (C) 2015, 2016 ARM 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.
>> + *
>> + * 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.
>> + *
>> + * 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/irqchip/arm-gic.h>
>> +#include <linux/kvm.h>
>> +#include <linux/kvm_host.h>
>> +
>> +#include "vgic.h"
>> +
>> +/*
>> + * Call this function to convert a u64 value to an unsigned long * bitmask
>> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
>> + *
>> + * Warning: Calling this function may modify *val.
>> + */
>> +static unsigned long *u64_to_bitmask(u64 *val)
>> +{
>> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
>> +	*val = (*val >> 32) | (*val << 32);
>> +#endif
>> +	return (unsigned long *)val;
>> +}
>> +
>> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
>> +{
>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>> +
>> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
>> +		u64 eisr = cpuif->vgic_eisr;
>> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
>> +		int lr;
>> +
>> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
>> +			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
>> +
>> +			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
>> +
>> +			kvm_notify_acked_irq(vcpu->kvm, 0,
>> +					     intid - VGIC_NR_PRIVATE_IRQS);
>> +
> 
> why do we need to do this?  I cannot find any consumers of this info
> after we've left the hyp code.

I believe that's for vhost and irqfd. Or am I misreading your question?

> Also, I think I offered a comment about why we would potentially need
> this in the first place.  This is the famous race where hardware doesn't
> guarantee consistency between the MISR and ELRSR right?

That's the one (except it is between EISR and ELRSR). I don't have your
initial comment at hand, but would something like the following do?

			/*
			 * The maintenance interrupt may not have had a
			 * chance to update ELRSR, so let's mark the LRs
			 * presents in EISR as empty.
			 */
> 
>> +			cpuif->vgic_elrsr |= 1ULL << lr;
>> +		}
>> +	}

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From arnd at arndb.de  Tue May 10 06:44:00 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 15:44 +0200
Subject: [GIT PULL] Allwinner DT additions for 4.7
In-Reply-To: <20160429163625.GA5732@lukather>
References: <20160429163625.GA5732@lukather>
Message-ID: <3007371.2v3L7cUp1S@wuerfel>

On Friday 29 April 2016 18:36:25 Maxime Ripard wrote:
> Allwinner DT additions for 4.7
> 
> The usual bunch of changes, mostly:
>   * Addition of the SPDIF support
>   * Addition of the pre-requisites for the display support
>   * New boards: Difrence DIT4350, colorfly e708 q1, Dserve DSRV9703C,
>                 Polaroid MID2809PXE4, Orange Pi PC, Orange Pi 2
> 

Merged into next/dt, thanks!

	Arnd


From arnd at arndb.de  Tue May 10 06:45:10 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 15:45:10 +0200
Subject: [GIT PULL] ARM: mediatek: dts updates for v4.7
In-Reply-To: <CABuKBe+jtD4nLXFrxTxKJ_Fq9t9D9a_ibXsSkvvZw5e5p_fZeA@mail.gmail.com>
References: <CABuKBe+jtD4nLXFrxTxKJ_Fq9t9D9a_ibXsSkvvZw5e5p_fZeA@mail.gmail.com>
Message-ID: <6805797.KH0bBfhBJ4@wuerfel>

On Monday 02 May 2016 16:37:23 Matthias Brugger wrote:
> - add pinctrl node for mt2701
> - add mt2701 pmic wrapper binding
> - add auxadc binding document
> 
> 

Merged into next/dt, thanks!

	Arnd


From arnd at arndb.de  Tue May 10 06:46:22 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 15:46:22 +0200
Subject: [GIT PULL 3/6] i.MX device tree updates for 4.7, take 2
In-Reply-To: <1462291086-19925-3-git-send-email-shawnguo@kernel.org>
References: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
 <1462291086-19925-3-git-send-email-shawnguo@kernel.org>
Message-ID: <2951198.nVCPiLiCck@wuerfel>

On Tuesday 03 May 2016 23:58:03 Shawn Guo wrote:
> The i.MX device tree updates for 4.7, take 2:
>  - Update display clock configuration for imx6q-b850v3 board
>  - Use watchdog external reset for imx6q-ba16 board
>  - Update operating points settings for i.MX6UL/SX/DL
>  - New board support: imx6ul-pico-hobbit and imx6q-marsboard
>  - Add SAI audio support for imx6ul-14x14-evk board
>  - Enable USB OTG support for M53EVK board
>  - A couple of fixes on DTC warnings
> 

Merged into next/dt, thanks!

	Arnd


From arnd at arndb.de  Tue May 10 06:47:26 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 15:47:26 +0200
Subject: [GIT PULL] Device Tree updated for Ux500 for v4.7
In-Reply-To: <CACRpkdbjdM=L4DEUZ5fuDPRumXdiztqht1h+zu+UZoJKk1dXoA@mail.gmail.com>
References: <CACRpkdbjdM=L4DEUZ5fuDPRumXdiztqht1h+zu+UZoJKk1dXoA@mail.gmail.com>
Message-ID: <4588497.ydQCIWB9r7@wuerfel>

On Wednesday 04 May 2016 09:38:50 Linus Walleij wrote:
> I guess I should have gotten this out the door earlier, especially
> since the patches were around since forever.
> 
> Anyways this is a few cleanups of DTS files (use proper includes)
> and the assignment of the accelerometers as open drain so they
> actually work.
> 

Merged into next/dt, thanks!

	Arnd


From eric.auger at linaro.org  Tue May 10 06:49:40 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 15:49:40 +0200
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <5731E52A.9000402@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
 <20160510133043.GF27623@cbox> <5731E52A.9000402@arm.com>
Message-ID: <5731E6F4.4010405@linaro.org>

On 05/10/2016 03:42 PM, Marc Zyngier wrote:
> On 10/05/16 14:30, Christoffer Dall wrote:
>> On Fri, May 06, 2016 at 11:45:31AM +0100, Andre Przywara wrote:
>>> From: Marc Zyngier <marc.zyngier at arm.com>
>>>
>>> Processing maintenance interrupts and accessing the list registers
>>> are dependent on the host's GIC version.
>>> Introduce vgic-v2.c to contain GICv2 specific functions.
>>> Implement the GICv2 specific code for syncing the emulation state
>>> into the VGIC registers.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>> Changelog RFC..v1:
>>> - remove explicit LR_STATE clearing on maintenance interrupt handling
>>> - improve documentation for vgic_v2_populate_lr()
>>> - remove WARN_ON on non-edge IRQs in maintenance interrupts
>>> - simplify multi-CPU source SGI handling
>>>
>>> Changelog v1 .. v2:
>>> - inject the IRQ priority into the list register
>>>
>>> Changelog v2 .. v3:
>>> - cleanup diff containing rebase artifacts
>>>
>>>  include/linux/irqchip/arm-gic.h |   1 +
>>>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
>>>  virt/kvm/arm/vgic/vgic.c        |   6 ++
>>>  virt/kvm/arm/vgic/vgic.h        |   6 ++
>>>  4 files changed, 191 insertions(+)
>>>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
>>>
>>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>>> index 9c94026..be0d26f 100644
>>> --- a/include/linux/irqchip/arm-gic.h
>>> +++ b/include/linux/irqchip/arm-gic.h
>>> @@ -76,6 +76,7 @@
>>>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
>>>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
>>>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
>>> +#define GICH_LR_PRIORITY_SHIFT		23
>>>  #define GICH_LR_STATE			(3 << 28)
>>>  #define GICH_LR_PENDING_BIT		(1 << 28)
>>>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
>>> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
>>> new file mode 100644
>>> index 0000000..4cee616
>>> --- /dev/null
>>> +++ b/virt/kvm/arm/vgic/vgic-v2.c
>>> @@ -0,0 +1,178 @@
>>> +/*
>>> + * Copyright (C) 2015, 2016 ARM 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.
>>> + *
>>> + * 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.
>>> + *
>>> + * 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/irqchip/arm-gic.h>
>>> +#include <linux/kvm.h>
>>> +#include <linux/kvm_host.h>
>>> +
>>> +#include "vgic.h"
>>> +
>>> +/*
>>> + * Call this function to convert a u64 value to an unsigned long * bitmask
>>> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
>>> + *
>>> + * Warning: Calling this function may modify *val.
>>> + */
>>> +static unsigned long *u64_to_bitmask(u64 *val)
>>> +{
>>> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
>>> +	*val = (*val >> 32) | (*val << 32);
>>> +#endif
>>> +	return (unsigned long *)val;
>>> +}
>>> +
>>> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
>>> +{
>>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>>> +
>>> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
>>> +		u64 eisr = cpuif->vgic_eisr;
>>> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
>>> +		int lr;
>>> +
>>> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
>>> +			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
>>> +
>>> +			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
>>> +
>>> +			kvm_notify_acked_irq(vcpu->kvm, 0,
>>> +					     intid - VGIC_NR_PRIVATE_IRQS);
>>> +
>>
>> why do we need to do this?  I cannot find any consumers of this info
>> after we've left the hyp code.
> 
> I believe that's for vhost and irqfd. Or am I misreading your question?
Yes that's for irqfd. It triggers the resamplerfd which then "VFIO
unmasks" the IRQ

Eric
> 
>> Also, I think I offered a comment about why we would potentially need
>> this in the first place.  This is the famous race where hardware doesn't
>> guarantee consistency between the MISR and ELRSR right?
> 
> That's the one (except it is between EISR and ELRSR). I don't have your
> initial comment at hand, but would something like the following do?
> 
> 			/*
> 			 * The maintenance interrupt may not have had a
> 			 * chance to update ELRSR, so let's mark the LRs
> 			 * presents in EISR as empty.
> 			 */
>>
>>> +			cpuif->vgic_elrsr |= 1ULL << lr;
>>> +		}
>>> +	}
> 
> Thanks,
> 
> 	M.
> 



From eric.auger at linaro.org  Tue May 10 06:53:39 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 15:53:39 +0200
Subject: [PATCH v3 17/55] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <1462531568-9799-18-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-18-git-send-email-andre.przywara@arm.com>
Message-ID: <5731E7E3.4070908@linaro.org>

On 05/06/2016 12:45 PM, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Implement the framework for syncing IRQs between our emulation and
> the list registers, which represent the guest's view of IRQs.
> This is done in kvm_vgic_flush_hwstate and kvm_vgic_sync_hwstate,
> which gets called on guest entry and exit.
> The code talking to the actual GICv2/v3 hardware is added in the
> following patches.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - split out vgic_clear_lr() from vgic_populate_lr()
> - rename vgic_populate_lrs() to vgic_flush_lr_state()
> - clean all LRs when the distributor is disabled
> - use list_del() instead of list_del_init()
> - add comments to explain the direction of sync/flush_hwstate
> - remove unneeded BUG_ON(in_interrupt()
> 
> Changelog v2 .. v3:
> - remove bogus v2 specific rebase leftovers
> 
>  include/kvm/vgic/vgic.h  |   4 +
>  virt/kvm/arm/vgic/vgic.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h |   2 +
>  3 files changed, 199 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 2bfb42c..5fae4a9 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -190,6 +190,10 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
>  			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
>  
> +bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
> +void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
> +void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
> +
>  /**
>   * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
>   *
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 4fb20fd..c6f8b9b 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -305,3 +305,196 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  {
>  	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
>  }
> +
> +/**
> + * vgic_prune_ap_list - Remove non-relevant interrupts from the list
> + *
> + * @vcpu: The VCPU pointer
> + *
> + * Go over the list of "interesting" interrupts, and prune those that we
> + * won't have to consider in the near future.
> + */
> +static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq, *tmp;
> +
> +retry:
> +	spin_lock(&vgic_cpu->ap_list_lock);
> +
> +	list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
> +		struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		BUG_ON(vcpu != irq->vcpu);
> +
> +		target_vcpu = vgic_target_oracle(irq);
> +
> +		if (!target_vcpu) {
> +			/*
> +			 * We don't need to process this interrupt any
> +			 * further, move it off the list.
> +			 */
> +			list_del(&irq->ap_list);
> +			irq->vcpu = NULL;
> +			spin_unlock(&irq->irq_lock);
> +			continue;
> +		}
> +
> +		if (target_vcpu == vcpu) {
> +			/* We're on the right CPU */
> +			spin_unlock(&irq->irq_lock);
> +			continue;
> +		}
> +
> +		/* This interrupt looks like it has to be migrated. */
> +
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vgic_cpu->ap_list_lock);
> +
> +		/*
> +		 * Ensure locking order by always locking the smallest
> +		 * ID first.
> +		 */
> +		if (vcpu->vcpu_id < target_vcpu->vcpu_id) {
> +			vcpuA = vcpu;
> +			vcpuB = target_vcpu;
> +		} else {
> +			vcpuA = target_vcpu;
> +			vcpuB = vcpu;
> +		}
> +
> +		spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
> +		spin_lock(&vcpuB->arch.vgic_cpu.ap_list_lock);
> +		spin_lock(&irq->irq_lock);
> +
> +		/*
> +		 * If the affinity has been preserved, move the
> +		 * interrupt around. Otherwise, it means things have
> +		 * changed while the interrupt was unlocked, and we
> +		 * need to replay this.
> +		 *
> +		 * In all cases, we cannot trust the list not to have
> +		 * changed, so we restart from the beginning.
> +		 */
> +		if (target_vcpu == vgic_target_oracle(irq)) {
> +			struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;
> +
> +			list_del(&irq->ap_list);
> +			irq->vcpu = target_vcpu;
> +			list_add_tail(&irq->ap_list, &new_cpu->ap_list_head);
> +		}
> +
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
> +		spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
> +		goto retry;
> +	}
> +
> +	spin_unlock(&vgic_cpu->ap_list_lock);
> +}
> +
> +static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +/* Requires the ap_list_lock and the irq_lock to be held. */
> +static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
> +				    struct vgic_irq *irq, int lr)
> +{
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
> +}
> +
> +static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
> +{
> +}
> +
> +static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
> +{
> +}
> +

nit: we may add a comment for compute_ap_list_depth, saying
vgic_cpu->ap_list_lock must be held

Besides Reviewed-by: Eric Auger <eric.auger at linaro.org>

Eric
> +static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq;
> +	int count = 0;
> +
> +	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
> +		spin_lock(&irq->irq_lock);
> +		/* GICv2 SGIs can count for more than one... */
> +		if (vgic_irq_is_sgi(irq->intid) && irq->source)
> +			count += hweight8(irq->source);
> +		else
> +			count++;
> +		spin_unlock(&irq->irq_lock);
> +	}
> +	return count;
> +}
> +
> +/* Requires the VCPU's ap_list_lock to be held. */
> +static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq;
> +	int count = 0;
> +
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
> +
> +	if (unlikely(!vcpu->kvm->arch.vgic.enabled))
> +		goto out_clean;
> +
> +	if (compute_ap_list_depth(vcpu) > kvm_vgic_global_state.nr_lr) {
> +		vgic_set_underflow(vcpu);
> +		vgic_sort_ap_list(vcpu);
> +	}
> +
> +	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
> +		spin_lock(&irq->irq_lock);
> +
> +		if (unlikely(vgic_target_oracle(irq) != vcpu))
> +			goto next;
> +
> +		/*
> +		 * If we get an SGI with multiple sources, try to get
> +		 * them in all at once.
> +		 */
> +		do {
> +			vgic_populate_lr(vcpu, irq, count++);
> +		} while (irq->source && count < kvm_vgic_global_state.nr_lr);
> +
> +next:
> +		spin_unlock(&irq->irq_lock);
> +
> +		if (count == kvm_vgic_global_state.nr_lr)
> +			break;
> +	}
> +
> +out_clean:
> +	vcpu->arch.vgic_cpu.used_lrs = count;
> +
> +	/* Nuke remaining LRs */
> +	for ( ; count < kvm_vgic_global_state.nr_lr; count++)
> +		vgic_clear_lr(vcpu, count);
> +}
> +
> +/* Sync back the hardware VGIC state into our emulation after a guest's run. */
> +void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
> +{
> +	vgic_process_maintenance_interrupt(vcpu);
> +	vgic_fold_lr_state(vcpu);
> +	vgic_prune_ap_list(vcpu);
> +}
> +
> +/* Flush our emulation state into the GIC hardware before entering the guest. */
> +void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
> +{
> +	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +	vgic_flush_lr_state(vcpu);
> +	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index c625767..29b96b9 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -16,6 +16,8 @@
>  #ifndef __KVM_ARM_VGIC_NEW_H__
>  #define __KVM_ARM_VGIC_NEW_H__
>  
> +#define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
> +
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid);
>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
> 



From p.zabel at pengutronix.de  Tue May 10 06:54:57 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Tue, 10 May 2016 15:54:57 +0200
Subject: [RFC PATCH 12/21] reset: uniphier: add core support for
 UniPhier reset driver
In-Reply-To: <1462873862-30940-13-git-send-email-yamada.masahiro@socionext.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
 <1462873862-30940-13-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1462888497.9155.9.camel@pengutronix.de>

Am Dienstag, den 10.05.2016, 18:50 +0900 schrieb Masahiro Yamada:
[...]
> +static int uniphier_reset_update(struct reset_controller_dev *rcdev,
> +				 unsigned long id, bool assert)
> +{
> +	struct uniphier_reset_priv *priv = to_uniphier_reset_priv(rcdev);
> +	const struct uniphier_reset_data *p;
> +	bool handled = false;
> +
> +	for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) {
> +		unsigned int val;
> +		int ret;
> +
> +		if (p->id != id)
> +			continue;
> +
> +		val = p->deassert_val;
> +		if (assert)
> +			val = ~val;
> +
> +		ret = regmap_write_bits(priv->regmap, p->reg, p->mask, val);

What is the difference between mask and deassert_val? Couldn't you just
assign
	val = assert ? 0 : p->mask;
?

> +static const struct reset_control_ops uniphier_reset_ops = {
> +	.assert = uniphier_reset_assert,
> +	.deassert = uniphier_reset_deassert,
> +	.status = uniphier_reset_status,
> +};
> +
> +int uniphier_reset_probe(struct platform_device *pdev,
> +			 const struct uniphier_reset_data *data)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct uniphier_reset_priv *priv;
> +	const struct uniphier_reset_data *p;
> +	struct regmap *regmap;
> +	unsigned int nr_resets = 0;
> +
> +	/* parent should be MFD and syscon node */
> +	regmap = syscon_node_to_regmap(dev->parent->of_node);
> +	if (IS_ERR(regmap)) {
> +		dev_err(dev, "failed to get regmap\n");

syscon_node_to_regmap can return different error codes. It might be
helpful to use
	dev_err(dev, "failed to get regmap: %d\n", PTR_ERR(regmap));
here.

regards
Philipp



From yendapally.reddy at broadcom.com  Tue May 10 06:55:47 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Tue, 10 May 2016 19:25:47 +0530
Subject: [PATCH RESEND 0/3] pwm support for Broadcom iProc SoC's
In-Reply-To: <1459261350-23851-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1459261350-23851-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <CAL2FKYkxugMVsFaFugPNKWwBjpo+2Mkt4x+=c-OgU5PcsOqiuQ@mail.gmail.com>

Hi Thierry,

  Can you please provide review comments for this patch set.

Thanks
Dhananjay

On Tue, Mar 29, 2016 at 7:52 PM, Yendapally Reddy Dhananjaya Reddy
<yendapally.reddy at broadcom.com> wrote:
> This patchset contains the pwm support for the Broadcom's iProc SoC's.
>
> The first patch provides the documentation details and the
> second patch contains the controller support details. The third patch
> contains the enable method for Northstar Plus SoC.
>
> This patch series has been tested on NSP bcm958625HR board with oscilloscope.
> The pwm is not enabled for this board as the pins are open and not used.
>
> This patch series is based on v4.6.0-rc1 and is available from github
> repo: https://github.com/Broadcom/cygnus-linux.git
> branch: iproc-pwm-v1
>
> This patch series was originally sent on 03/01/16.
> See https://lkml.org/lkml/2016/3/1/487
>
> Yendapally Reddy Dhananjaya Reddy (3):
>   Documentation: dt: Add Broadcom iproc pwm controller binding
>   pwm: kona: Add support for Broadcom iproc pwm controller
>   ARM: dts: NSP: Add PWM Support to DT
>
>  .../devicetree/bindings/pwm/brcm,kona-pwm.txt      |   2 +-
>  arch/arm/boot/dts/bcm-nsp.dtsi                     |   8 +
>  drivers/pwm/Kconfig                                |   6 +-
>  drivers/pwm/pwm-bcm-kona.c                         | 183 ++++++++++++++++++---
>  4 files changed, 172 insertions(+), 27 deletions(-)
>
> --
> 2.1.0
>


From k.kozlowski at samsung.com  Tue May 10 06:52:21 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 15:52:21 +0200
Subject: [PATCH 2/2] soc: samsung: pm_domains: Prepare for supporting ARMv8
 Exynos
In-Reply-To: <1462888341-21963-1-git-send-email-k.kozlowski@samsung.com>
References: <1462888341-21963-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462888341-21963-2-git-send-email-k.kozlowski@samsung.com>

The ARMv8 Exynos family (Exynos5433 and Exynos7420) uses different value
(0xf instead of 0x7) for controlling the power domain on/off registers
(both for control and for status).

Choose the value depending on the compatible. This prepares the driver
for supporting ARMv8 SoCs.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/soc/samsung/pm_domains.c | 34 ++++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/soc/samsung/pm_domains.c b/drivers/soc/samsung/pm_domains.c
index 875a2bab64f6..f60515eefb66 100644
--- a/drivers/soc/samsung/pm_domains.c
+++ b/drivers/soc/samsung/pm_domains.c
@@ -23,9 +23,13 @@
 #include <linux/of_platform.h>
 #include <linux/sched.h>
 
-#define INT_LOCAL_PWR_EN	0x7
 #define MAX_CLK_PER_DOMAIN	4
 
+struct exynos_pm_domain_config {
+	/* Value for LOCAL_PWR_CFG and STATUS fields for each domain */
+	u32 local_pwr_cfg;
+};
+
 /*
  * Exynos specific wrapper around the generic power domain
  */
@@ -38,6 +42,7 @@ struct exynos_pm_domain {
 	struct clk *clk[MAX_CLK_PER_DOMAIN];
 	struct clk *pclk[MAX_CLK_PER_DOMAIN];
 	struct clk *asb_clk[MAX_CLK_PER_DOMAIN];
+	u32 local_pwr_cfg;
 };
 
 static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
@@ -69,13 +74,13 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
 		}
 	}
 
-	pwr = power_on ? INT_LOCAL_PWR_EN : 0;
+	pwr = power_on ? pd->local_pwr_cfg : 0;
 	__raw_writel(pwr, base);
 
 	/* Wait max 1ms */
 	timeout = 10;
 
-	while ((__raw_readl(base + 0x4) & INT_LOCAL_PWR_EN) != pwr) {
+	while ((__raw_readl(base + 0x4) & pd->local_pwr_cfg) != pwr) {
 		if (!timeout) {
 			op = (power_on) ? "enable" : "disable";
 			pr_err("Power domain %s %s failed\n", domain->name, op);
@@ -119,14 +124,30 @@ static int exynos_pd_power_off(struct generic_pm_domain *domain)
 	return exynos_pd_power(domain, false);
 }
 
+static const struct exynos_pm_domain_config exynos4210_cfg __initconst = {
+	.local_pwr_cfg		= 0x7,
+};
+
+static const struct of_device_id exynos_pm_domain_of_match[] __initconst = {
+	{
+		.compatible = "samsung,exynos4210-pd",
+		.data = &exynos4210_cfg,
+	},
+	{ },
+};
+
 static __init int exynos4_pm_init_power_domain(void)
 {
 	struct device_node *np;
+	const struct of_device_id *match;
 
-	for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
+	for_each_matching_node_and_match(np, exynos_pm_domain_of_match, &match) {
+		const struct exynos_pm_domain_config *pm_domain_cfg;
 		struct exynos_pm_domain *pd;
 		int on, i;
 
+		pm_domain_cfg = match->data;
+
 		pd = kzalloc(sizeof(*pd), GFP_KERNEL);
 		if (!pd) {
 			pr_err("%s: failed to allocate memory for domain\n",
@@ -153,6 +174,7 @@ static __init int exynos4_pm_init_power_domain(void)
 
 		pd->pd.power_off = exynos_pd_power_off;
 		pd->pd.power_on = exynos_pd_power_on;
+		pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
 
 		for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
 			char clk_name[8];
@@ -185,14 +207,14 @@ static __init int exynos4_pm_init_power_domain(void)
 			clk_put(pd->oscclk);
 
 no_clk:
-		on = __raw_readl(pd->base + 0x4) & INT_LOCAL_PWR_EN;
+		on = __raw_readl(pd->base + 0x4) & pd->local_pwr_cfg;
 
 		pm_genpd_init(&pd->pd, NULL, !on);
 		of_genpd_add_provider_simple(np, &pd->pd);
 	}
 
 	/* Assign the child power domains to their parents */
-	for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") {
+	for_each_matching_node(np, exynos_pm_domain_of_match) {
 		struct generic_pm_domain *child_domain, *parent_domain;
 		struct of_phandle_args args;
 
-- 
1.9.1



From k.kozlowski at samsung.com  Tue May 10 06:52:20 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 15:52:20 +0200
Subject: [PATCH 1/2] ARM: EXYNOS: Move pm_domains driver to drivers/soc/samsung
Message-ID: <1462888341-21963-1-git-send-email-k.kozlowski@samsung.com>

Exynos PM domains driver does not have mach-specific dependencies so it
can be safely moved out of arm/mach-exynos to drivers/soc. This in
future will allow re-using it on ARM64 boards.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm/mach-exynos/Makefile                              | 1 -
 drivers/soc/samsung/Makefile                               | 1 +
 {arch/arm/mach-exynos => drivers/soc/samsung}/pm_domains.c | 0
 3 files changed, 1 insertion(+), 1 deletion(-)
 rename {arch/arm/mach-exynos => drivers/soc/samsung}/pm_domains.c (100%)

diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 34d29df3e006..838249d4ff5c 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_ARCH_EXYNOS)	+= exynos.o exynos-smc.o firmware.o
 
 obj-$(CONFIG_EXYNOS_CPU_SUSPEND) += pm.o sleep.o
 obj-$(CONFIG_PM_SLEEP)		+= suspend.o
-obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
 
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 
diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
index f64ac4d80564..8acba2bbbd78 100644
--- a/drivers/soc/samsung/Makefile
+++ b/drivers/soc/samsung/Makefile
@@ -1,2 +1,3 @@
+obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
 obj-$(CONFIG_EXYNOS_PMU)	+= exynos-pmu.o exynos3250-pmu.o exynos4-pmu.o \
 					exynos5250-pmu.o exynos5420-pmu.o
diff --git a/arch/arm/mach-exynos/pm_domains.c b/drivers/soc/samsung/pm_domains.c
similarity index 100%
rename from arch/arm/mach-exynos/pm_domains.c
rename to drivers/soc/samsung/pm_domains.c
-- 
1.9.1



From richard.genoud at gmail.com  Tue May 10 06:58:42 2016
From: richard.genoud at gmail.com (Richard Genoud)
Date: Tue, 10 May 2016 15:58:42 +0200
Subject: [BISECTED] Regression v4.6-rc1 : nanosleep doesn't return on AT91SAM9
Message-ID: <CACQ1gAg6cKqjaqcV70m2VS5R4_kZEgWTiqzSqDxSjvfrYYxbzg@mail.gmail.com>

Hi,

Starting with 4.6-rc1, a sleep 1 doesn't return :

execve("/bin/sleep", ["sleep", "1"], ["USER=root", "SHLVL=1",
"OLDPWD=/var", "HOME=/", "TERM=vt102",
"PATH=/sbin:/usr/sbin:/bin:/usr/bin", "SHELL=/bin/sh", "PWD=/"]) = 0
uname({sysname="Linux", nodename="LNS",
release="4.5.0-09406-g46e595a17dcf", version="#72 Tue May 10 15:41:34
CEST 2016", machine="armv5tejl", domainname="(none)"}) = 0
brk(0)                                  = 0x153000
brk(0x153d20)                           = 0x153d20
set_tls(0x1534c0, 0x14d1e4, 0, 0x153d20, 0x14e368) = 0
readlink("/proc/self/exe", "/bin/busybox", 4096) = 12
brk(0x174d20)                           = 0x174d20
brk(0x175000)                           = 0x175000
getuid32()                              = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0},

And the heartbeat led doesn't blink anymore (full on), as if the
timers never fire.

The platform is an AT91SAM9G35-CM.

git bisect gives a merge as the 1st bad commit :(
first bad commit: [46e595a17dcf11404f713845ecb5b06b92a94e43] Merge tag
'armsoc-drivers' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc


Here is the git bisect log:
git bisect start
# good: [b562e44f507e863c6792946e4e1b1449fbbac85d] Linux 4.5
git bisect good b562e44f507e863c6792946e4e1b1449fbbac85d
# bad: [f55532a0c0b8bb6148f4e07853b876ef73bc69ca] Linux 4.6-rc1
git bisect bad f55532a0c0b8bb6148f4e07853b876ef73bc69ca
# good: [6b5f04b6cf8ebab9a65d9c0026c650bb2538fd0f] Merge branch
'for-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
git bisect good 6b5f04b6cf8ebab9a65d9c0026c650bb2538fd0f
# bad: [53d2e6976bd4042672ed7b90dfbf4b31635b7dcf] Merge tag
'xfs-for-linus-4.6-rc1' of
git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs
git bisect bad 53d2e6976bd4042672ed7b90dfbf4b31635b7dcf
# good: [8626c56c8279b88b91b8df55345cdf89542d5e90] bridge: fix
potential use-after-free when hook returns QUEUE or STOLEN verdict
git bisect good 8626c56c8279b88b91b8df55345cdf89542d5e90
# good: [8c6d4082fc6ad2214e945b5b7368b828fb16e9a9] Merge tag
'armsoc-arm64' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
git bisect good 8c6d4082fc6ad2214e945b5b7368b828fb16e9a9
# good: [915c56bc01d6eab071e0dd1c6ea3bf73fbe5124f] Merge tag
'armsoc-dt64' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
git bisect good 915c56bc01d6eab071e0dd1c6ea3bf73fbe5124f
# bad: [24b5e20f11a75866bbffc46c30a22fa50612a769] Merge branch
'efi-core-for-linus' of
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
git bisect bad 24b5e20f11a75866bbffc46c30a22fa50612a769
# bad: [46e595a17dcf11404f713845ecb5b06b92a94e43] Merge tag
'armsoc-drivers' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
git bisect bad 46e595a17dcf11404f713845ecb5b06b92a94e43
# good: [4a6f791c359a78535553ccf060615622d27b1ce1] Merge tag
'omap-for-v4.6/defconfig-signed' of
git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into
next/defconfig
git bisect good 4a6f791c359a78535553ccf060615622d27b1ce1
# good: [f628c64fc0ffdcd08f39d74ec23ed7706cb8653b] Merge tag
'at91-ab-4.6-drivers' of
git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux into
next/drivers
git bisect good f628c64fc0ffdcd08f39d74ec23ed7706cb8653b
# good: [387eb3f3d574ebf43b3afe83da59a99481866b78] reset: socfpga:
Make reset_control_ops const
git bisect good 387eb3f3d574ebf43b3afe83da59a99481866b78
# good: [87023bc2ed11ea6b0944b34cc0281454c01832bf] Merge tag
'sunxi-drivers-for-4.6' of
https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into
next/drivers
git bisect good 87023bc2ed11ea6b0944b34cc0281454c01832bf
# good: [33b96d2c9579213cf3f36d7b29841b1e464750c4] bus: imx-weim: Take
the 'status' property value into account
git bisect good 33b96d2c9579213cf3f36d7b29841b1e464750c4
# good: [9fe5bf92c30a89631eb1fafe0d9b18e2ba331ebb] ARM: configs: Add
new config fragment to change RAM start point
git bisect good 9fe5bf92c30a89631eb1fafe0d9b18e2ba331ebb
# good: [e3b1f64e04f57198ca0ab1216d824a5547be8446] Merge tag
'armsoc-defconfig' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
git bisect good e3b1f64e04f57198ca0ab1216d824a5547be8446
# first bad commit: [46e595a17dcf11404f713845ecb5b06b92a94e43] Merge
tag 'armsoc-drivers' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc


And the defconfig :
CONFIG_KERNEL_LZO=y
CONFIG_DEFAULT_HOSTNAME="lns"
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
# CONFIG_CROSS_MEMORY_ATTACH is not set
CONFIG_FHANDLE=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_RELAY=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
CONFIG_SLAB=y
CONFIG_PARTITION_ADVANCED=y
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
# CONFIG_ARCH_MULTI_V7 is not set
CONFIG_ARCH_AT91=y
CONFIG_SOC_AT91SAM9=y
CONFIG_AEABI=y
# CONFIG_COMPACTION is not set
CONFIG_UACCESS_WITH_MEMCPY=y
# CONFIG_ATAGS is not set
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
# CONFIG_COREDUMP is not set
# CONFIG_SUSPEND is not set
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=y
CONFIG_UNIX=y
CONFIG_UNIX_DIAG=y
CONFIG_XFRM_USER=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
CONFIG_INET_UDP_DIAG=y
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_NETFILTER=y
# CONFIG_BRIDGE_NETFILTER is not set
CONFIG_NETFILTER_NETLINK_LOG=y
CONFIG_NF_CONNTRACK=y
# CONFIG_NF_CONNTRACK_PROCFS is not set
CONFIG_NF_CT_NETLINK=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_NF_NAT_IPV4=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_MANGLE=y
CONFIG_NF_CONNTRACK_IPV6=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_MATCH_IPV6HEADER=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_BRIDGE=y
# CONFIG_BRIDGE_IGMP_SNOOPING is not set
CONFIG_DNS_RESOLVER=y
CONFIG_NETLINK_DIAG=y
CONFIG_CFG80211=y
CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=y
CONFIG_MAC80211_LEDS=y
CONFIG_RFKILL=y
CONFIG_RFKILL_INPUT=y
CONFIG_RFKILL_GPIO=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_FIRMWARE_IN_KERNEL is not set
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ATMEL=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_FASTMAP=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=4
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_ATMEL_TCLIB=y
CONFIG_ATMEL_SSC=y
CONFIG_EEPROM_AT24=y
CONFIG_EEPROM_93CX6=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CIRRUS is not set
# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_FARADAY is not set
# CONFIG_NET_VENDOR_HISILICON is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_NETRONOME is not set
# CONFIG_NET_VENDOR_QUALCOMM is not set
# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SMSC is not set
# CONFIG_NET_VENDOR_STMICRO is not set
# CONFIG_NET_VENDOR_SYNOPSYS is not set
# CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WIZNET is not set
CONFIG_PHYLIB=y
CONFIG_DAVICOM_PHY=y
CONFIG_PPP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_ASYNC=y
# CONFIG_USB_NET_DRIVERS is not set
# CONFIG_WLAN is not set
# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
# CONFIG_SERIO is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_ATMEL=y
CONFIG_SERIAL_ATMEL_CONSOLE=y
# CONFIG_SERIAL_ATMEL_PDC is not set
CONFIG_I2C=y
# CONFIG_I2C_COMPAT is not set
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX=y
CONFIG_I2C_AT91=y
CONFIG_I2C_GPIO=y
CONFIG_SPI=y
CONFIG_SPI_ATMEL=y
CONFIG_SPI_SPIDEV=y
CONFIG_GPIO_SYSFS=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_AT91SAM9X_WATCHDOG=y
CONFIG_SSB=y
CONFIG_BCMA=y
CONFIG_SOUND=y
CONFIG_SND=y
# CONFIG_SND_SUPPORT_OLD_API is not set
# CONFIG_SND_VERBOSE_PROCFS is not set
# CONFIG_SND_DRIVERS is not set
# CONFIG_SND_ARM is not set
# CONFIG_SND_SPI is not set
# CONFIG_SND_USB is not set
CONFIG_SND_SOC=y
CONFIG_SND_ATMEL_SOC=y
CONFIG_SND_AT91_SOC_SAM9X5_WM8731=y
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_USB_HIDDEV=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_ACM=y
CONFIG_USB_WDM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_STORAGE_REALTEK=y
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
CONFIG_USB_STORAGE_ISD200=y
CONFIG_USB_STORAGE_USBAT=y
CONFIG_USB_STORAGE_SDDR09=y
CONFIG_USB_STORAGE_SDDR55=y
CONFIG_USB_STORAGE_JUMPSHOT=y
CONFIG_USB_STORAGE_ALAUDA=y
CONFIG_USB_STORAGE_ONETOUCH=y
CONFIG_USB_STORAGE_KARMA=y
CONFIG_USB_STORAGE_CYPRESS_ATACB=y
CONFIG_USB_STORAGE_ENE_UB6250=y
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_IPW=y
CONFIG_USB_SERIAL_PL2303=y
CONFIG_USB_SERIAL_QUALCOMM=y
CONFIG_USB_SERIAL_SIERRAWIRELESS=y
CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_EZUSB_FX2=y
CONFIG_USB_GADGET=y
CONFIG_USB_AT91=y
CONFIG_USB_ATMEL_USBA=y
CONFIG_USB_ETH=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_DMADEVICES=y
CONFIG_AT_HDMAC=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_FANOTIFY=y
CONFIG_VFAT_FS=y
CONFIG_FAT_DEFAULT_CODEPAGE=850
CONFIG_NTFS_FS=y
CONFIG_TMPFS=y
CONFIG_UBIFS_FS=y
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
# CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_CODEPAGE_850=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y
CONFIG_PRINTK_TIME=y
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7
CONFIG_STRIP_ASM_SYMS=y
CONFIG_DEBUG_SECTION_MISMATCH=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_LOCKUP_DETECTOR=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_FUNCTION_TRACER=y
CONFIG_FTRACE_SYSCALLS=y
CONFIG_TRACER_SNAPSHOT=y
CONFIG_KEYS=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_MICHAEL_MIC=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
# CONFIG_CRYPTO_HW is not set
CONFIG_CRC_ITU_T=y
CONFIG_CRC7=y

Regards,
Richard.


From javier at osg.samsung.com  Tue May 10 07:00:05 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 10 May 2016 10:00:05 -0400
Subject: [PATCH v2 00/22] ARM: dts: exynos: Add initial support for Odroid
 XU
In-Reply-To: <57316E10.2030300@kernel.org>
References: <1462734367-5619-1-git-send-email-krzk@kernel.org>
 <0aacc9fe-01c2-a9cd-35c7-db2c17a737c3@osg.samsung.com>
 <57316E10.2030300@kernel.org>
Message-ID: <671c34fa-fbb7-4499-8dbd-87957cd49e15@osg.samsung.com>

Hello Krzysztof,

On 05/10/2016 01:13 AM, Krzysztof Kozlowski wrote:
> On 05/10/2016 12:05 AM, Javier Martinez Canillas wrote:
>> Hello Krzysztof,
>>
>> On 05/08/2016 03:05 PM, Krzysztof Kozlowski wrote:
>>>
>>> Hi,
>>>
>>> Patchset adds necessary clocks, reorganizes existing stuff and finally
>>> adds Odroid XU support.
>>>
>>
>> Do you have a branch available so I can pull these patches and test in
>> the Exynos5 boards I've access to?
> 
> Of course. It sits on my private repo, on Github:
> https://github.com/krzk/linux
> branch: for-next/odroid-xu-v2
>

Thanks for the information, I'll give a try today.
 
> Best regards,
> Krzysztof
> 

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From arnd at arndb.de  Tue May 10 06:59:47 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 15:59:47 +0200
Subject: [PATCH 1/4] ARM: ux500: remove unused regulator data
In-Reply-To: <1462888794-2793296-1-git-send-email-arnd@arndb.de>
References: <1462888794-2793296-1-git-send-email-arnd@arndb.de>
Message-ID: <1462888794-2793296-2-git-send-email-arnd@arndb.de>

Most of the board-mop500-regulators.c file is never referenced and
can simply be removed.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 arch/arm/mach-ux500/board-mop500-regulators.c | 600 --------------------------
 arch/arm/mach-ux500/board-mop500-regulators.h |   8 -
 2 files changed, 608 deletions(-)

diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
index 32d744e91ec2..eff141ddeea5 100644
--- a/arch/arm/mach-ux500/board-mop500-regulators.c
+++ b/arch/arm/mach-ux500/board-mop500-regulators.c
@@ -13,46 +13,6 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/ab8500.h>
 #include "board-mop500-regulators.h"
-#include "id.h"
-
-static struct regulator_consumer_supply gpio_en_3v3_consumers[] = {
-       REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
-};
-
-struct regulator_init_data gpio_en_3v3_regulator = {
-       .constraints = {
-               .name = "EN-3V3",
-               .min_uV = 3300000,
-               .max_uV = 3300000,
-               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies = ARRAY_SIZE(gpio_en_3v3_consumers),
-       .consumer_supplies = gpio_en_3v3_consumers,
-};
-
-/*
- * TPS61052 regulator
- */
-static struct regulator_consumer_supply tps61052_vaudio_consumers[] = {
-	/*
-	 * Boost converter supply to raise voltage on audio speaker, this
-	 * is actually connected to three pins, VInVhfL (left amplifier)
-	 * VInVhfR (right amplifier) and VIntDClassInt - all three must
-	 * be connected to the same voltage.
-	 */
-	REGULATOR_SUPPLY("vintdclassint", "ab8500-codec.0"),
-};
-
-struct regulator_init_data tps61052_regulator = {
-	.constraints = {
-		.name = "vaudio-hf",
-		.min_uV = 4500000,
-		.max_uV = 4500000,
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(tps61052_vaudio_consumers),
-	.consumer_supplies = tps61052_vaudio_consumers,
-};
 
 static struct regulator_consumer_supply ab8500_vaux1_consumers[] = {
 	/* Main display, u8500 R3 uib */
@@ -107,27 +67,6 @@ static struct regulator_consumer_supply ab8500_vaux3_consumers[] = {
 	REGULATOR_SUPPLY("vmmc", "sdi0"),
 };
 
-static struct regulator_consumer_supply ab8505_vaux4_consumers[] = {
-};
-
-static struct regulator_consumer_supply ab8505_vaux5_consumers[] = {
-};
-
-static struct regulator_consumer_supply ab8505_vaux6_consumers[] = {
-};
-
-static struct regulator_consumer_supply ab8505_vaux8_consumers[] = {
-	/* AB8500 audio codec device */
-	REGULATOR_SUPPLY("v-aux8", NULL),
-};
-
-static struct regulator_consumer_supply ab8505_vadc_consumers[] = {
-	/* Internal general-purpose ADC */
-	REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"),
-	/* ADC for charger */
-	REGULATOR_SUPPLY("vddadc", "ab8500-charger.0"),
-};
-
 static struct regulator_consumer_supply ab8500_vtvout_consumers[] = {
 	/* TV-out DENC supply */
 	REGULATOR_SUPPLY("vtvout", "ab8500-denc.0"),
@@ -168,11 +107,6 @@ static struct regulator_consumer_supply ab8500_vintcore_consumers[] = {
 	REGULATOR_SUPPLY("v-intcore", "abx500-clk.0"),
 };
 
-static struct regulator_consumer_supply ab8505_usb_consumers[] = {
-	/* HS USB OTG physical interface */
-	REGULATOR_SUPPLY("v-ape", NULL),
-};
-
 static struct regulator_consumer_supply ab8500_vana_consumers[] = {
 	/* DB8500 DSI */
 	REGULATOR_SUPPLY("vdddsi1v2", "mcde"),
@@ -483,11 +417,6 @@ static struct regulator_consumer_supply ab8500_ext_supply3_consumers[] = {
 	REGULATOR_SUPPLY("vinvsim", "sim-detect.0"),
 };
 
-/* extended configuration for VextSupply2, only used for HREFP_V20 boards */
-static struct ab8500_ext_regulator_cfg ab8500_ext_supply2 = {
-	.hwreq = true,
-};
-
 /*
  * AB8500 external regulators
  */
@@ -526,456 +455,6 @@ static struct regulator_init_data ab8500_ext_regulators[] = {
 	},
 };
 
-/* ab8505 regulator register initialization */
-static struct ab8500_regulator_reg_init ab8505_reg_init[] = {
-	/*
-	 * VarmRequestCtrl
-	 * VsmpsCRequestCtrl
-	 * VsmpsARequestCtrl
-	 * VsmpsBRequestCtrl
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUREQUESTCTRL1,       0x00, 0x00),
-	/*
-	 * VsafeRequestCtrl
-	 * VpllRequestCtrl
-	 * VanaRequestCtrl          = HP/LP depending on VxRequest
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUREQUESTCTRL2,       0x30, 0x00),
-	/*
-	 * Vaux1RequestCtrl         = HP/LP depending on VxRequest
-	 * Vaux2RequestCtrl         = HP/LP depending on VxRequest
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUREQUESTCTRL3,       0xf0, 0x00),
-	/*
-	 * Vaux3RequestCtrl         = HP/LP depending on VxRequest
-	 * SwHPReq                  = Control through SWValid disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUREQUESTCTRL4,       0x07, 0x00),
-	/*
-	 * VsmpsASysClkReq1HPValid
-	 * VsmpsBSysClkReq1HPValid
-	 * VsafeSysClkReq1HPValid
-	 * VanaSysClkReq1HPValid    = disabled
-	 * VpllSysClkReq1HPValid
-	 * Vaux1SysClkReq1HPValid   = disabled
-	 * Vaux2SysClkReq1HPValid   = disabled
-	 * Vaux3SysClkReq1HPValid   = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUSYSCLKREQ1HPVALID1, 0xe8, 0x00),
-	/*
-	 * VsmpsCSysClkReq1HPValid
-	 * VarmSysClkReq1HPValid
-	 * VbbSysClkReq1HPValid
-	 * VsmpsMSysClkReq1HPValid
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUSYSCLKREQ1HPVALID2, 0x00, 0x00),
-	/*
-	 * VsmpsAHwHPReq1Valid
-	 * VsmpsBHwHPReq1Valid
-	 * VsafeHwHPReq1Valid
-	 * VanaHwHPReq1Valid        = disabled
-	 * VpllHwHPReq1Valid
-	 * Vaux1HwHPreq1Valid       = disabled
-	 * Vaux2HwHPReq1Valid       = disabled
-	 * Vaux3HwHPReqValid        = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUHWHPREQ1VALID1,     0xe8, 0x00),
-	/*
-	 * VsmpsMHwHPReq1Valid
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUHWHPREQ1VALID2,     0x00, 0x00),
-	/*
-	 * VsmpsAHwHPReq2Valid
-	 * VsmpsBHwHPReq2Valid
-	 * VsafeHwHPReq2Valid
-	 * VanaHwHPReq2Valid        = disabled
-	 * VpllHwHPReq2Valid
-	 * Vaux1HwHPReq2Valid       = disabled
-	 * Vaux2HwHPReq2Valid       = disabled
-	 * Vaux3HwHPReq2Valid       = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUHWHPREQ2VALID1,     0xe8, 0x00),
-	/*
-	 * VsmpsMHwHPReq2Valid
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUHWHPREQ2VALID2,     0x00, 0x00),
-	/**
-	 * VsmpsCSwHPReqValid
-	 * VarmSwHPReqValid
-	 * VsmpsASwHPReqValid
-	 * VsmpsBSwHPReqValid
-	 * VsafeSwHPReqValid
-	 * VanaSwHPReqValid
-	 * VanaSwHPReqValid         = disabled
-	 * VpllSwHPReqValid
-	 * Vaux1SwHPReqValid        = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUSWHPREQVALID1,      0xa0, 0x00),
-	/*
-	 * Vaux2SwHPReqValid        = disabled
-	 * Vaux3SwHPReqValid        = disabled
-	 * VsmpsMSwHPReqValid
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUSWHPREQVALID2,      0x03, 0x00),
-	/*
-	 * SysClkReq2Valid1         = SysClkReq2 controlled
-	 * SysClkReq3Valid1         = disabled
-	 * SysClkReq4Valid1         = SysClkReq4 controlled
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUSYSCLKREQVALID1,    0x0e, 0x0a),
-	/*
-	 * SysClkReq2Valid2         = disabled
-	 * SysClkReq3Valid2         = disabled
-	 * SysClkReq4Valid2         = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUSYSCLKREQVALID2,    0x0e, 0x00),
-	/*
-	 * Vaux4SwHPReqValid
-	 * Vaux4HwHPReq2Valid
-	 * Vaux4HwHPReq1Valid
-	 * Vaux4SysClkReq1HPValid
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUVAUX4REQVALID,    0x00, 0x00),
-	/*
-	 * VadcEna                  = disabled
-	 * VintCore12Ena            = disabled
-	 * VintCore12Sel            = 1.25 V
-	 * VintCore12LP             = inactive (HP)
-	 * VadcLP                   = inactive (HP)
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUMISC1,              0xfe, 0x10),
-	/*
-	 * VaudioEna                = disabled
-	 * Vaux8Ena                 = disabled
-	 * Vamic1Ena                = disabled
-	 * Vamic2Ena                = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VAUDIOSUPPLY,           0x1e, 0x00),
-	/*
-	 * Vamic1_dzout             = high-Z when Vamic1 is disabled
-	 * Vamic2_dzout             = high-Z when Vamic2 is disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUCTRL1VAMIC,         0x03, 0x00),
-	/*
-	 * VsmpsARegu
-	 * VsmpsASelCtrl
-	 * VsmpsAAutoMode
-	 * VsmpsAPWMMode
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VSMPSAREGU,    0x00, 0x00),
-	/*
-	 * VsmpsBRegu
-	 * VsmpsBSelCtrl
-	 * VsmpsBAutoMode
-	 * VsmpsBPWMMode
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VSMPSBREGU,    0x00, 0x00),
-	/*
-	 * VsafeRegu
-	 * VsafeSelCtrl
-	 * VsafeAutoMode
-	 * VsafePWMMode
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VSAFEREGU,    0x00, 0x00),
-	/*
-	 * VPll                     = Hw controlled (NOTE! PRCMU bits)
-	 * VanaRegu                 = force off
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VPLLVANAREGU,           0x0f, 0x02),
-	/*
-	 * VextSupply1Regu          = force OFF (OTP_ExtSupply12LPnPolarity 1)
-	 * VextSupply2Regu          = force OFF (OTP_ExtSupply12LPnPolarity 1)
-	 * VextSupply3Regu          = force OFF (OTP_ExtSupply3LPnPolarity 0)
-	 * ExtSupply2Bypass         = ExtSupply12LPn ball is 0 when Ena is 0
-	 * ExtSupply3Bypass         = ExtSupply3LPn ball is 0 when Ena is 0
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_EXTSUPPLYREGU,          0xff, 0x30),
-	/*
-	 * Vaux1Regu                = force HP
-	 * Vaux2Regu                = force off
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VAUX12REGU,             0x0f, 0x01),
-	/*
-	 * Vaux3Regu                = force off
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VRF1VAUX3REGU,          0x03, 0x00),
-	/*
-	 * VsmpsASel1
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VSMPSASEL1,    0x00, 0x00),
-	/*
-	 * VsmpsASel2
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VSMPSASEL2,    0x00, 0x00),
-	/*
-	 * VsmpsASel3
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VSMPSASEL3,    0x00, 0x00),
-	/*
-	 * VsmpsBSel1
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VSMPSBSEL1,    0x00, 0x00),
-	/*
-	 * VsmpsBSel2
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VSMPSBSEL2,    0x00, 0x00),
-	/*
-	 * VsmpsBSel3
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VSMPSBSEL3,    0x00, 0x00),
-	/*
-	 * VsafeSel1
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VSAFESEL1,    0x00, 0x00),
-	/*
-	 * VsafeSel2
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VSAFESEL2,    0x00, 0x00),
-	/*
-	 * VsafeSel3
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VSAFESEL3,    0x00, 0x00),
-	/*
-	 * Vaux1Sel                 = 2.8 V
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VAUX1SEL,               0x0f, 0x0C),
-	/*
-	 * Vaux2Sel                 = 2.9 V
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VAUX2SEL,               0x0f, 0x0d),
-	/*
-	 * Vaux3Sel                 = 2.91 V
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VRF1VAUX3SEL,           0x07, 0x07),
-	/*
-	 * Vaux4RequestCtrl
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VAUX4REQCTRL,    0x00, 0x00),
-	/*
-	 * Vaux4Regu
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VAUX4REGU,    0x00, 0x00),
-	/*
-	 * Vaux4Sel
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_VAUX4SEL,    0x00, 0x00),
-	/*
-	 * Vaux1Disch               = short discharge time
-	 * Vaux2Disch               = short discharge time
-	 * Vaux3Disch               = short discharge time
-	 * Vintcore12Disch          = short discharge time
-	 * VTVoutDisch              = short discharge time
-	 * VaudioDisch              = short discharge time
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUCTRLDISCH,          0xfc, 0x00),
-	/*
-	 * VanaDisch                = short discharge time
-	 * Vaux8PullDownEna         = pulldown disabled when Vaux8 is disabled
-	 * Vaux8Disch               = short discharge time
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUCTRLDISCH2,         0x16, 0x00),
-	/*
-	 * Vaux4Disch               = short discharge time
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_REGUCTRLDISCH3,         0x01, 0x00),
-	/*
-	 * Vaux5Sel
-	 * Vaux5LP
-	 * Vaux5Ena
-	 * Vaux5Disch
-	 * Vaux5DisSfst
-	 * Vaux5DisPulld
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_CTRLVAUX5,              0x00, 0x00),
-	/*
-	 * Vaux6Sel
-	 * Vaux6LP
-	 * Vaux6Ena
-	 * Vaux6DisPulld
-	 */
-	INIT_REGULATOR_REGISTER(AB8505_CTRLVAUX6,              0x00, 0x00),
-};
-
-static struct regulator_init_data ab8505_regulators[AB8505_NUM_REGULATORS] = {
-	/* supplies to the display/camera */
-	[AB8505_LDO_AUX1] = {
-		.constraints = {
-			.name = "V-DISPLAY",
-			.min_uV = 2800000,
-			.max_uV = 3300000,
-			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS,
-			.boot_on = 1, /* display is on at boot */
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
-		.consumer_supplies = ab8500_vaux1_consumers,
-	},
-	/* supplies to the on-board eMMC */
-	[AB8505_LDO_AUX2] = {
-		.constraints = {
-			.name = "V-eMMC1",
-			.min_uV = 1100000,
-			.max_uV = 3300000,
-			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS |
-					  REGULATOR_CHANGE_MODE,
-			.valid_modes_mask = REGULATOR_MODE_NORMAL |
-					    REGULATOR_MODE_IDLE,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers),
-		.consumer_supplies = ab8500_vaux2_consumers,
-	},
-	/* supply for VAUX3, supplies to SDcard slots */
-	[AB8505_LDO_AUX3] = {
-		.constraints = {
-			.name = "V-MMC-SD",
-			.min_uV = 1100000,
-			.max_uV = 3300000,
-			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS |
-					  REGULATOR_CHANGE_MODE,
-			.valid_modes_mask = REGULATOR_MODE_NORMAL |
-					    REGULATOR_MODE_IDLE,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers),
-		.consumer_supplies = ab8500_vaux3_consumers,
-	},
-	/* supply for VAUX4, supplies to NFC and standalone secure element */
-	[AB8505_LDO_AUX4] = {
-		.constraints = {
-			.name = "V-NFC-SE",
-			.min_uV = 1100000,
-			.max_uV = 3300000,
-			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS |
-					  REGULATOR_CHANGE_MODE,
-			.valid_modes_mask = REGULATOR_MODE_NORMAL |
-					    REGULATOR_MODE_IDLE,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8505_vaux4_consumers),
-		.consumer_supplies = ab8505_vaux4_consumers,
-	},
-	/* supply for VAUX5, supplies to TBD */
-	[AB8505_LDO_AUX5] = {
-		.constraints = {
-			.name = "V-AUX5",
-			.min_uV = 1050000,
-			.max_uV = 2790000,
-			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS |
-					  REGULATOR_CHANGE_MODE,
-			.valid_modes_mask = REGULATOR_MODE_NORMAL |
-					    REGULATOR_MODE_IDLE,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8505_vaux5_consumers),
-		.consumer_supplies = ab8505_vaux5_consumers,
-	},
-	/* supply for VAUX6, supplies to TBD */
-	[AB8505_LDO_AUX6] = {
-		.constraints = {
-			.name = "V-AUX6",
-			.min_uV = 1050000,
-			.max_uV = 2790000,
-			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS |
-					  REGULATOR_CHANGE_MODE,
-			.valid_modes_mask = REGULATOR_MODE_NORMAL |
-					    REGULATOR_MODE_IDLE,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8505_vaux6_consumers),
-		.consumer_supplies = ab8505_vaux6_consumers,
-	},
-	/* supply for gpadc, ADC LDO */
-	[AB8505_LDO_ADC] = {
-		.constraints = {
-			.name = "V-ADC",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8505_vadc_consumers),
-		.consumer_supplies = ab8505_vadc_consumers,
-	},
-	/* supply for ab8500-vaudio, VAUDIO LDO */
-	[AB8505_LDO_AUDIO] = {
-		.constraints = {
-			.name = "V-AUD",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaud_consumers),
-		.consumer_supplies = ab8500_vaud_consumers,
-	},
-	/* supply for v-anamic1 VAMic1-LDO */
-	[AB8505_LDO_ANAMIC1] = {
-		.constraints = {
-			.name = "V-AMIC1",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS |
-					  REGULATOR_CHANGE_MODE,
-			.valid_modes_mask = REGULATOR_MODE_NORMAL |
-					    REGULATOR_MODE_IDLE,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vamic1_consumers),
-		.consumer_supplies = ab8500_vamic1_consumers,
-	},
-	/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
-	[AB8505_LDO_ANAMIC2] = {
-		.constraints = {
-			.name = "V-AMIC2",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS |
-					  REGULATOR_CHANGE_MODE,
-			.valid_modes_mask = REGULATOR_MODE_NORMAL |
-					    REGULATOR_MODE_IDLE,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vamic2_consumers),
-		.consumer_supplies = ab8500_vamic2_consumers,
-	},
-	/* supply for v-aux8, VAUX8 LDO */
-	[AB8505_LDO_AUX8] = {
-		.constraints = {
-			.name = "V-AUX8",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8505_vaux8_consumers),
-		.consumer_supplies = ab8505_vaux8_consumers,
-	},
-	/* supply for v-intcore12, VINTCORE12 LDO */
-	[AB8505_LDO_INTCORE] = {
-		.constraints = {
-			.name = "V-INTCORE",
-			.min_uV = 1250000,
-			.max_uV = 1350000,
-			.input_uV = 1800000,
-			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS |
-					  REGULATOR_CHANGE_MODE |
-					  REGULATOR_CHANGE_DRMS,
-			.valid_modes_mask = REGULATOR_MODE_NORMAL |
-					    REGULATOR_MODE_IDLE,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers),
-		.consumer_supplies = ab8500_vintcore_consumers,
-	},
-	/* supply for LDO USB */
-	[AB8505_LDO_USB] = {
-		.constraints = {
-			.name = "V-USB",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS |
-					  REGULATOR_CHANGE_MODE,
-			.valid_modes_mask = REGULATOR_MODE_NORMAL |
-					    REGULATOR_MODE_IDLE,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8505_usb_consumers),
-		.consumer_supplies = ab8505_usb_consumers,
-	},
-	/* supply for U8500 CSI-DSI, VANA LDO */
-	[AB8505_LDO_ANA] = {
-		.constraints = {
-			.name = "V-CSI-DSI",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers),
-		.consumer_supplies = ab8500_vana_consumers,
-	},
-};
-
 struct ab8500_regulator_platform_data ab8500_regulator_plat_data = {
 	.reg_init               = ab8500_reg_init,
 	.num_reg_init           = ARRAY_SIZE(ab8500_reg_init),
@@ -984,82 +463,3 @@ struct ab8500_regulator_platform_data ab8500_regulator_plat_data = {
 	.ext_regulator          = ab8500_ext_regulators,
 	.num_ext_regulator      = ARRAY_SIZE(ab8500_ext_regulators),
 };
-
-struct ab8500_regulator_platform_data ab8505_regulator_plat_data = {
-	.reg_init               = ab8505_reg_init,
-	.num_reg_init           = ARRAY_SIZE(ab8505_reg_init),
-	.regulator              = ab8505_regulators,
-	.num_regulator          = ARRAY_SIZE(ab8505_regulators),
-};
-
-static void ab8500_modify_reg_init(int id, u8 mask, u8 value)
-{
-	int i;
-
-	if (cpu_is_u8520()) {
-		for (i = ARRAY_SIZE(ab8505_reg_init) - 1; i >= 0; i--) {
-			if (ab8505_reg_init[i].id == id) {
-				u8 initval = ab8505_reg_init[i].value;
-				initval = (initval & ~mask) | (value & mask);
-				ab8505_reg_init[i].value = initval;
-
-				BUG_ON(mask & ~ab8505_reg_init[i].mask);
-				return;
-			}
-		}
-	} else {
-		for (i = ARRAY_SIZE(ab8500_reg_init) - 1; i >= 0; i--) {
-			if (ab8500_reg_init[i].id == id) {
-				u8 initval = ab8500_reg_init[i].value;
-				initval = (initval & ~mask) | (value & mask);
-				ab8500_reg_init[i].value = initval;
-
-				BUG_ON(mask & ~ab8500_reg_init[i].mask);
-				return;
-			}
-		}
-	}
-
-	BUG_ON(1);
-}
-
-void mop500_regulator_init(void)
-{
-	struct regulator_init_data *regulator;
-
-	/*
-	 * Temporarily turn on Vaux2 on 8520 machine
-	 */
-	if (cpu_is_u8520()) {
-		/* Vaux2 initialized to be on */
-		ab8500_modify_reg_init(AB8505_VAUX12REGU, 0x0f, 0x05);
-	}
-
-	/*
-	 * Handle AB8500_EXT_SUPPLY2 on HREFP_V20_V50 boards (do it for
-	 * all HREFP_V20 boards)
-	 */
-	if (cpu_is_u8500v20()) {
-		/* VextSupply2RequestCtrl =  HP/OFF depending on VxRequest */
-		ab8500_modify_reg_init(AB8500_REGUREQUESTCTRL3, 0x01, 0x01);
-
-		/* VextSupply2SysClkReq1HPValid = SysClkReq1 controlled */
-		ab8500_modify_reg_init(AB8500_REGUSYSCLKREQ1HPVALID2,
-			0x20, 0x20);
-
-		/* VextSupply2 = force HP at initialization */
-		ab8500_modify_reg_init(AB8500_EXTSUPPLYREGU, 0x0c, 0x04);
-
-		/* enable VextSupply2 during platform active */
-		regulator = &ab8500_ext_regulators[AB8500_EXT_SUPPLY2];
-		regulator->constraints.always_on = 1;
-
-		/* disable VextSupply2 in suspend */
-		regulator = &ab8500_ext_regulators[AB8500_EXT_SUPPLY2];
-		regulator->constraints.state_mem.disabled = 1;
-		regulator->constraints.state_standby.disabled = 1;
-
-		/* enable VextSupply2 HW control (used in suspend) */
-		regulator->driver_data = (void *)&ab8500_ext_supply2;
-	}
-}
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.h b/arch/arm/mach-ux500/board-mop500-regulators.h
index 9bece38fe933..3bbb0831b0cf 100644
--- a/arch/arm/mach-ux500/board-mop500-regulators.h
+++ b/arch/arm/mach-ux500/board-mop500-regulators.h
@@ -11,14 +11,6 @@
 #ifndef __BOARD_MOP500_REGULATORS_H
 #define __BOARD_MOP500_REGULATORS_H
 
-#include <linux/regulator/machine.h>
-#include <linux/regulator/ab8500.h>
-
 extern struct ab8500_regulator_platform_data ab8500_regulator_plat_data;
-extern struct ab8500_regulator_platform_data ab8505_regulator_plat_data;
-extern struct regulator_init_data tps61052_regulator;
-extern struct regulator_init_data gpio_en_3v3_regulator;
-
-void mop500_regulator_init(void);
 
 #endif
-- 
2.7.0



From linux.amoon at gmail.com  Tue May 10 07:00:36 2016
From: linux.amoon at gmail.com (Anand Moon)
Date: Tue, 10 May 2016 19:30:36 +0530
Subject: [PATCH] ARM: dts: exynos: Only Odroid XU3-family boards use DTSI
 with CPU thermal nodes
In-Reply-To: <5731D764.8070007@samsung.com>
References: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>
 <CANAwSgT9SY3kj8+beMpc1xGoC=rMBSya+2v2dyZQp6ykH+V0=g@mail.gmail.com>
 <573198BE.6020900@samsung.com>
 <CANAwSgTy6p9AVmmOWATpSO1JqVbwE0v+y_y-RLd+32RnNJTA+Q@mail.gmail.com>
 <5731D764.8070007@samsung.com>
Message-ID: <CANAwSgRsjdQh6ygT__5XcH8-cF9Ch+zbk8oupebwYzY1kCZu6g@mail.gmail.com>

Hi Krzysztof,

On 10 May 2016 at 18:13, Krzysztof Kozlowski <k.kozlowski at samsung.com> wrote:
> On 05/10/2016 11:29 AM, Anand Moon wrote:
>>>
>>> I am sorry but I do not understand.
>>> 1. Are you saying that my patch causes the issue?
>>> 2. Are you saying that I should not send some patches because of
>>> conflicting work? (that would be peculiar...)
>>> 3. Are you saying that I should not apply this patch to me tree because
>>> of conflicting work?
>>> 4. Other?
>>>
>>> Best regards.
>>> Krzysztof
>>>
>>>
>>
>> Sorry for the confusion it's not about you patch.
>> The feature is not working correctly as per my testing with the
>> original source code.
>> It need to be more tuned or some other approach to the issue need to found.
>
> Known issue. You don't have cpufreq cooling enabled. I sent patches for
> that and they are in the mainline. However cpufreq cooling requires
> cpufreq which cannot work with BL_SWITCHER and on Exynos542x on
> exynos_defconfig BL_SWITCHER is enabled.
>
> Just disable the BL_Krzysztof.
>
> Best regards,
> Krzysztof

I have already disabled BL_SWITCHER in my exynos_defconfig. to support
CONFIG_CPUFREQ_DT.

But how about adjust the  the cputemp so that all the core will have
same tip points.

xcpu0-t 0:[ 44][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>     A50
     A60       P70            P85                                C120
]
xcpu1-t 1:[ 46][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                              A85               A103   A110      C120
]
xcpu2-t 2:[ 51][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                         A85               A103   A110      C120 ]
xcpu3-t 3:[ 47][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                             A85               A103   A110      C120 ]
xgpu-th 4:[ 48][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                            A85               A103   A110      C120 ]

Best Regards
-Anand Moon


From arnd at arndb.de  Tue May 10 06:59:48 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 15:59:48 +0200
Subject: [PATCH 2/4] ARM: ux500: move ab8500_regulator_plat_data into driver
In-Reply-To: <1462888794-2793296-1-git-send-email-arnd@arndb.de>
References: <1462888794-2793296-1-git-send-email-arnd@arndb.de>
Message-ID: <1462888794-2793296-3-git-send-email-arnd@arndb.de>

There is only one instance of ab8500_regulator_platform_data, and it's
safe to assume we won't ever merge another one, so it's rather pointless
to pass it through multiple levels of platform data pointers.

This moves the structure and everything referenced by it into the
driver that uses it.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 arch/arm/mach-ux500/Makefile                  |   3 +-
 arch/arm/mach-ux500/board-mop500-regulators.c | 465 --------------------------
 arch/arm/mach-ux500/board-mop500-regulators.h |  16 -
 arch/arm/mach-ux500/cpu-db8500.c              |   2 -
 drivers/regulator/ab8500-ext.c                | 465 +++++++++++++++++++++++++-
 5 files changed, 452 insertions(+), 499 deletions(-)
 delete mode 100644 arch/arm/mach-ux500/board-mop500-regulators.c
 delete mode 100644 arch/arm/mach-ux500/board-mop500-regulators.h

diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index edfff1ae1f8d..ea8893fd128f 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -5,8 +5,7 @@
 obj-y				:= cpu.o id.o pm.o
 obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o
 obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o
-obj-$(CONFIG_MACH_MOP500)	+= board-mop500-regulators.o \
-				board-mop500-audio.o
+obj-$(CONFIG_MACH_MOP500)	+= board-mop500-audio.o
 obj-$(CONFIG_SMP)		+= platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
 obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
deleted file mode 100644
index eff141ddeea5..000000000000
--- a/arch/arm/mach-ux500/board-mop500-regulators.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License v2
- *
- * Authors: Sundar Iyer <sundar.iyer at stericsson.com>
- *          Bengt Jonsson <bengt.g.jonsson at stericsson.com>
- *          Daniel Willerud <daniel.willerud at stericsson.com>
- *
- * MOP500 board specific initialization for regulators
- */
-#include <linux/kernel.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/ab8500.h>
-#include "board-mop500-regulators.h"
-
-static struct regulator_consumer_supply ab8500_vaux1_consumers[] = {
-	/* Main display, u8500 R3 uib */
-	REGULATOR_SUPPLY("vddi", "mcde_disp_sony_acx424akp.0"),
-	/* Main display, u8500 uib and ST uib */
-	REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.0"),
-	/* Secondary display, ST uib */
-	REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.1"),
-	/* SFH7741 proximity sensor */
-	REGULATOR_SUPPLY("vcc", "gpio-keys.0"),
-	/* BH1780GLS ambient light sensor */
-	REGULATOR_SUPPLY("vcc", "2-0029"),
-	/* lsm303dlh accelerometer */
-	REGULATOR_SUPPLY("vdd", "2-0018"),
-	/* lsm303dlhc accelerometer */
-	REGULATOR_SUPPLY("vdd", "2-0019"),
-	/* lsm303dlh magnetometer */
-	REGULATOR_SUPPLY("vdd", "2-001e"),
-	/* Rohm BU21013 Touchscreen devices */
-	REGULATOR_SUPPLY("avdd", "3-005c"),
-	REGULATOR_SUPPLY("avdd", "3-005d"),
-	/* Synaptics RMI4 Touchscreen device */
-	REGULATOR_SUPPLY("vdd", "3-004b"),
-	/* L3G4200D Gyroscope device */
-	REGULATOR_SUPPLY("vdd", "2-0068"),
-	/* Ambient light sensor device */
-	REGULATOR_SUPPLY("vdd", "3-0029"),
-	/* Pressure sensor device */
-	REGULATOR_SUPPLY("vdd", "2-005c"),
-	/* Cypress TrueTouch Touchscreen device */
-	REGULATOR_SUPPLY("vcpin", "spi8.0"),
-	/* Camera device */
-	REGULATOR_SUPPLY("vaux12v5", "mmio_camera"),
-};
-
-static struct regulator_consumer_supply ab8500_vaux2_consumers[] = {
-	/* On-board eMMC power */
-	REGULATOR_SUPPLY("vmmc", "sdi4"),
-	/* AB8500 audio codec */
-	REGULATOR_SUPPLY("vcc-N2158", "ab8500-codec.0"),
-	/* AB8500 accessory detect 1 */
-	REGULATOR_SUPPLY("vcc-N2158", "ab8500-acc-det.0"),
-	/* AB8500 Tv-out device */
-	REGULATOR_SUPPLY("vcc-N2158", "mcde_tv_ab8500.4"),
-	/* AV8100 HDMI device */
-	REGULATOR_SUPPLY("vcc-N2158", "av8100_hdmi.3"),
-};
-
-static struct regulator_consumer_supply ab8500_vaux3_consumers[] = {
-	REGULATOR_SUPPLY("v-SD-STM", "stm"),
-	/* External MMC slot power */
-	REGULATOR_SUPPLY("vmmc", "sdi0"),
-};
-
-static struct regulator_consumer_supply ab8500_vtvout_consumers[] = {
-	/* TV-out DENC supply */
-	REGULATOR_SUPPLY("vtvout", "ab8500-denc.0"),
-	/* Internal general-purpose ADC */
-	REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"),
-	/* ADC for charger */
-	REGULATOR_SUPPLY("vddadc", "ab8500-charger.0"),
-	/* AB8500 Tv-out device */
-	REGULATOR_SUPPLY("vtvout", "mcde_tv_ab8500.4"),
-};
-
-static struct regulator_consumer_supply ab8500_vaud_consumers[] = {
-	/* AB8500 audio-codec main supply */
-	REGULATOR_SUPPLY("vaud", "ab8500-codec.0"),
-};
-
-static struct regulator_consumer_supply ab8500_vamic1_consumers[] = {
-	/* AB8500 audio-codec Mic1 supply */
-	REGULATOR_SUPPLY("vamic1", "ab8500-codec.0"),
-};
-
-static struct regulator_consumer_supply ab8500_vamic2_consumers[] = {
-	/* AB8500 audio-codec Mic2 supply */
-	REGULATOR_SUPPLY("vamic2", "ab8500-codec.0"),
-};
-
-static struct regulator_consumer_supply ab8500_vdmic_consumers[] = {
-	/* AB8500 audio-codec DMic supply */
-	REGULATOR_SUPPLY("vdmic", "ab8500-codec.0"),
-};
-
-static struct regulator_consumer_supply ab8500_vintcore_consumers[] = {
-	/* SoC core supply, no device */
-	REGULATOR_SUPPLY("v-intcore", NULL),
-	/* USB Transceiver */
-	REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"),
-	/* Handled by abx500 clk driver */
-	REGULATOR_SUPPLY("v-intcore", "abx500-clk.0"),
-};
-
-static struct regulator_consumer_supply ab8500_vana_consumers[] = {
-	/* DB8500 DSI */
-	REGULATOR_SUPPLY("vdddsi1v2", "mcde"),
-	REGULATOR_SUPPLY("vdddsi1v2", "b2r2_core"),
-	REGULATOR_SUPPLY("vdddsi1v2", "b2r2_1_core"),
-	REGULATOR_SUPPLY("vdddsi1v2", "dsilink.0"),
-	REGULATOR_SUPPLY("vdddsi1v2", "dsilink.1"),
-	REGULATOR_SUPPLY("vdddsi1v2", "dsilink.2"),
-	/* DB8500 CSI */
-	REGULATOR_SUPPLY("vddcsi1v2", "mmio_camera"),
-};
-
-/* ab8500 regulator register initialization */
-static struct ab8500_regulator_reg_init ab8500_reg_init[] = {
-	/*
-	 * VanaRequestCtrl          = HP/LP depending on VxRequest
-	 * VextSupply1RequestCtrl   = HP/LP depending on VxRequest
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2,       0xf0, 0x00),
-	/*
-	 * VextSupply2RequestCtrl   = HP/LP depending on VxRequest
-	 * VextSupply3RequestCtrl   = HP/LP depending on VxRequest
-	 * Vaux1RequestCtrl         = HP/LP depending on VxRequest
-	 * Vaux2RequestCtrl         = HP/LP depending on VxRequest
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3,       0xff, 0x00),
-	/*
-	 * Vaux3RequestCtrl         = HP/LP depending on VxRequest
-	 * SwHPReq                  = Control through SWValid disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4,       0x07, 0x00),
-	/*
-	 * VanaSysClkReq1HPValid    = disabled
-	 * Vaux1SysClkReq1HPValid   = disabled
-	 * Vaux2SysClkReq1HPValid   = disabled
-	 * Vaux3SysClkReq1HPValid   = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0xe8, 0x00),
-	/*
-	 * VextSupply1SysClkReq1HPValid = disabled
-	 * VextSupply2SysClkReq1HPValid = disabled
-	 * VextSupply3SysClkReq1HPValid = SysClkReq1 controlled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x70, 0x40),
-	/*
-	 * VanaHwHPReq1Valid        = disabled
-	 * Vaux1HwHPreq1Valid       = disabled
-	 * Vaux2HwHPReq1Valid       = disabled
-	 * Vaux3HwHPReqValid        = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1,     0xe8, 0x00),
-	/*
-	 * VextSupply1HwHPReq1Valid = disabled
-	 * VextSupply2HwHPReq1Valid = disabled
-	 * VextSupply3HwHPReq1Valid = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2,     0x07, 0x00),
-	/*
-	 * VanaHwHPReq2Valid        = disabled
-	 * Vaux1HwHPReq2Valid       = disabled
-	 * Vaux2HwHPReq2Valid       = disabled
-	 * Vaux3HwHPReq2Valid       = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1,     0xe8, 0x00),
-	/*
-	 * VextSupply1HwHPReq2Valid = disabled
-	 * VextSupply2HwHPReq2Valid = disabled
-	 * VextSupply3HwHPReq2Valid = HWReq2 controlled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2,     0x07, 0x04),
-	/*
-	 * VanaSwHPReqValid         = disabled
-	 * Vaux1SwHPReqValid        = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1,      0xa0, 0x00),
-	/*
-	 * Vaux2SwHPReqValid        = disabled
-	 * Vaux3SwHPReqValid        = disabled
-	 * VextSupply1SwHPReqValid  = disabled
-	 * VextSupply2SwHPReqValid  = disabled
-	 * VextSupply3SwHPReqValid  = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2,      0x1f, 0x00),
-	/*
-	 * SysClkReq2Valid1         = SysClkReq2 controlled
-	 * SysClkReq3Valid1         = disabled
-	 * SysClkReq4Valid1         = SysClkReq4 controlled
-	 * SysClkReq5Valid1         = disabled
-	 * SysClkReq6Valid1         = SysClkReq6 controlled
-	 * SysClkReq7Valid1         = disabled
-	 * SysClkReq8Valid1         = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1,    0xfe, 0x2a),
-	/*
-	 * SysClkReq2Valid2         = disabled
-	 * SysClkReq3Valid2         = disabled
-	 * SysClkReq4Valid2         = disabled
-	 * SysClkReq5Valid2         = disabled
-	 * SysClkReq6Valid2         = SysClkReq6 controlled
-	 * SysClkReq7Valid2         = disabled
-	 * SysClkReq8Valid2         = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2,    0xfe, 0x20),
-	/*
-	 * VTVoutEna                = disabled
-	 * Vintcore12Ena            = disabled
-	 * Vintcore12Sel            = 1.25 V
-	 * Vintcore12LP             = inactive (HP)
-	 * VTVoutLP                 = inactive (HP)
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUMISC1,              0xfe, 0x10),
-	/*
-	 * VaudioEna                = disabled
-	 * VdmicEna                 = disabled
-	 * Vamic1Ena                = disabled
-	 * Vamic2Ena                = disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY,           0x1e, 0x00),
-	/*
-	 * Vamic1_dzout             = high-Z when Vamic1 is disabled
-	 * Vamic2_dzout             = high-Z when Vamic2 is disabled
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC,         0x03, 0x00),
-	/*
-	 * VPll                     = Hw controlled (NOTE! PRCMU bits)
-	 * VanaRegu                 = force off
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU,           0x0f, 0x02),
-	/*
-	 * VrefDDREna               = disabled
-	 * VrefDDRSleepMode         = inactive (no pulldown)
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_VREFDDR,                0x03, 0x00),
-	/*
-	 * VextSupply1Regu          = force LP
-	 * VextSupply2Regu          = force OFF
-	 * VextSupply3Regu          = force HP (-> STBB2=LP and TPS=LP)
-	 * ExtSupply2Bypass         = ExtSupply12LPn ball is 0 when Ena is 0
-	 * ExtSupply3Bypass         = ExtSupply3LPn ball is 0 when Ena is 0
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU,          0xff, 0x13),
-	/*
-	 * Vaux1Regu                = force HP
-	 * Vaux2Regu                = force off
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU,             0x0f, 0x01),
-	/*
-	 * Vaux3Regu                = force off
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU,          0x03, 0x00),
-	/*
-	 * Vaux1Sel                 = 2.8 V
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL,               0x0f, 0x0C),
-	/*
-	 * Vaux2Sel                 = 2.9 V
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL,               0x0f, 0x0d),
-	/*
-	 * Vaux3Sel                 = 2.91 V
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL,           0x07, 0x07),
-	/*
-	 * VextSupply12LP           = disabled (no LP)
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE,         0x01, 0x00),
-	/*
-	 * Vaux1Disch               = short discharge time
-	 * Vaux2Disch               = short discharge time
-	 * Vaux3Disch               = short discharge time
-	 * Vintcore12Disch          = short discharge time
-	 * VTVoutDisch              = short discharge time
-	 * VaudioDisch              = short discharge time
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH,          0xfc, 0x00),
-	/*
-	 * VanaDisch                = short discharge time
-	 * VdmicPullDownEna         = pulldown disabled when Vdmic is disabled
-	 * VdmicDisch               = short discharge time
-	 */
-	INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2,         0x16, 0x00),
-};
-
-/* AB8500 regulators */
-static struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
-	/* supplies to the display/camera */
-	[AB8500_LDO_AUX1] = {
-		.supply_regulator = "ab8500-ext-supply3",
-		.constraints = {
-			.name = "V-DISPLAY",
-			.min_uV = 2800000,
-			.max_uV = 3300000,
-			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS,
-			.boot_on = 1, /* display is on at boot */
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
-		.consumer_supplies = ab8500_vaux1_consumers,
-	},
-	/* supplies to the on-board eMMC */
-	[AB8500_LDO_AUX2] = {
-		.supply_regulator = "ab8500-ext-supply3",
-		.constraints = {
-			.name = "V-eMMC1",
-			.min_uV = 1100000,
-			.max_uV = 3300000,
-			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS |
-					  REGULATOR_CHANGE_MODE,
-			.valid_modes_mask = REGULATOR_MODE_NORMAL |
-					    REGULATOR_MODE_IDLE,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers),
-		.consumer_supplies = ab8500_vaux2_consumers,
-	},
-	/* supply for VAUX3, supplies to SDcard slots */
-	[AB8500_LDO_AUX3] = {
-		.supply_regulator = "ab8500-ext-supply3",
-		.constraints = {
-			.name = "V-MMC-SD",
-			.min_uV = 1100000,
-			.max_uV = 3300000,
-			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS |
-					  REGULATOR_CHANGE_MODE,
-			.valid_modes_mask = REGULATOR_MODE_NORMAL |
-					    REGULATOR_MODE_IDLE,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers),
-		.consumer_supplies = ab8500_vaux3_consumers,
-	},
-	/* supply for tvout, gpadc, TVOUT LDO */
-	[AB8500_LDO_TVOUT] = {
-		.constraints = {
-			.name = "V-TVOUT",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vtvout_consumers),
-		.consumer_supplies = ab8500_vtvout_consumers,
-	},
-	/* supply for ab8500-vaudio, VAUDIO LDO */
-	[AB8500_LDO_AUDIO] = {
-		.constraints = {
-			.name = "V-AUD",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaud_consumers),
-		.consumer_supplies = ab8500_vaud_consumers,
-	},
-	/* supply for v-anamic1 VAMic1-LDO */
-	[AB8500_LDO_ANAMIC1] = {
-		.constraints = {
-			.name = "V-AMIC1",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vamic1_consumers),
-		.consumer_supplies = ab8500_vamic1_consumers,
-	},
-	/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
-	[AB8500_LDO_ANAMIC2] = {
-		.constraints = {
-			.name = "V-AMIC2",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vamic2_consumers),
-		.consumer_supplies = ab8500_vamic2_consumers,
-	},
-	/* supply for v-dmic, VDMIC LDO */
-	[AB8500_LDO_DMIC] = {
-		.constraints = {
-			.name = "V-DMIC",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vdmic_consumers),
-		.consumer_supplies = ab8500_vdmic_consumers,
-	},
-	/* supply for v-intcore12, VINTCORE12 LDO */
-	[AB8500_LDO_INTCORE] = {
-		.constraints = {
-			.name = "V-INTCORE",
-			.min_uV = 1250000,
-			.max_uV = 1350000,
-			.input_uV = 1800000,
-			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-					  REGULATOR_CHANGE_STATUS |
-					  REGULATOR_CHANGE_MODE |
-					  REGULATOR_CHANGE_DRMS,
-			.valid_modes_mask = REGULATOR_MODE_NORMAL |
-					    REGULATOR_MODE_IDLE,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers),
-		.consumer_supplies = ab8500_vintcore_consumers,
-	},
-	/* supply for U8500 CSI-DSI, VANA LDO */
-	[AB8500_LDO_ANA] = {
-		.constraints = {
-			.name = "V-CSI-DSI",
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		},
-		.num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers),
-		.consumer_supplies = ab8500_vana_consumers,
-	},
-};
-
-/* supply for VextSupply3 */
-static struct regulator_consumer_supply ab8500_ext_supply3_consumers[] = {
-	/* SIM supply for 3 V SIM cards */
-	REGULATOR_SUPPLY("vinvsim", "sim-detect.0"),
-};
-
-/*
- * AB8500 external regulators
- */
-static struct regulator_init_data ab8500_ext_regulators[] = {
-	/* fixed Vbat supplies VSMPS1_EXT_1V8 */
-	[AB8500_EXT_SUPPLY1] = {
-		.constraints = {
-			.name = "ab8500-ext-supply1",
-			.min_uV = 1800000,
-			.max_uV = 1800000,
-			.initial_mode = REGULATOR_MODE_IDLE,
-			.boot_on = 1,
-			.always_on = 1,
-		},
-	},
-	/* fixed Vbat supplies VSMPS2_EXT_1V36 and VSMPS5_EXT_1V15 */
-	[AB8500_EXT_SUPPLY2] = {
-		.constraints = {
-			.name = "ab8500-ext-supply2",
-			.min_uV = 1360000,
-			.max_uV = 1360000,
-		},
-	},
-	/* fixed Vbat supplies VSMPS3_EXT_3V4 and VSMPS4_EXT_3V4 */
-	[AB8500_EXT_SUPPLY3] = {
-		.constraints = {
-			.name = "ab8500-ext-supply3",
-			.min_uV = 3400000,
-			.max_uV = 3400000,
-			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-			.boot_on = 1,
-		},
-		.num_consumer_supplies =
-			ARRAY_SIZE(ab8500_ext_supply3_consumers),
-		.consumer_supplies = ab8500_ext_supply3_consumers,
-	},
-};
-
-struct ab8500_regulator_platform_data ab8500_regulator_plat_data = {
-	.reg_init               = ab8500_reg_init,
-	.num_reg_init           = ARRAY_SIZE(ab8500_reg_init),
-	.regulator              = ab8500_regulators,
-	.num_regulator          = ARRAY_SIZE(ab8500_regulators),
-	.ext_regulator          = ab8500_ext_regulators,
-	.num_ext_regulator      = ARRAY_SIZE(ab8500_ext_regulators),
-};
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.h b/arch/arm/mach-ux500/board-mop500-regulators.h
deleted file mode 100644
index 3bbb0831b0cf..000000000000
--- a/arch/arm/mach-ux500/board-mop500-regulators.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License v2
- *
- * Author: Bengt Jonsson <bengt.g.jonsson at stericsson.com> for ST-Ericsson
- *
- * MOP500 board specific initialization for regulators
- */
-
-#ifndef __BOARD_MOP500_REGULATORS_H
-#define __BOARD_MOP500_REGULATORS_H
-
-extern struct ab8500_regulator_platform_data ab8500_regulator_plat_data;
-
-#endif
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index a557955472ea..c015ef8dd535 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -28,13 +28,11 @@
 
 #include "setup.h"
 
-#include "board-mop500-regulators.h"
 #include "board-mop500.h"
 #include "db8500-regs.h"
 #include "id.h"
 
 static struct ab8500_platform_data ab8500_platdata = {
-	.regulator	= &ab8500_regulator_plat_data,
 };
 
 static struct prcmu_pdata db8500_prcmu_pdata = {
diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c
index 84c1ee39ddae..2ca00045eb99 100644
--- a/drivers/regulator/ab8500-ext.c
+++ b/drivers/regulator/ab8500-ext.c
@@ -25,6 +25,456 @@
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/regulator/ab8500.h>
 
+static struct regulator_consumer_supply ab8500_vaux1_consumers[] = {
+	/* Main display, u8500 R3 uib */
+	REGULATOR_SUPPLY("vddi", "mcde_disp_sony_acx424akp.0"),
+	/* Main display, u8500 uib and ST uib */
+	REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.0"),
+	/* Secondary display, ST uib */
+	REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.1"),
+	/* SFH7741 proximity sensor */
+	REGULATOR_SUPPLY("vcc", "gpio-keys.0"),
+	/* BH1780GLS ambient light sensor */
+	REGULATOR_SUPPLY("vcc", "2-0029"),
+	/* lsm303dlh accelerometer */
+	REGULATOR_SUPPLY("vdd", "2-0018"),
+	/* lsm303dlhc accelerometer */
+	REGULATOR_SUPPLY("vdd", "2-0019"),
+	/* lsm303dlh magnetometer */
+	REGULATOR_SUPPLY("vdd", "2-001e"),
+	/* Rohm BU21013 Touchscreen devices */
+	REGULATOR_SUPPLY("avdd", "3-005c"),
+	REGULATOR_SUPPLY("avdd", "3-005d"),
+	/* Synaptics RMI4 Touchscreen device */
+	REGULATOR_SUPPLY("vdd", "3-004b"),
+	/* L3G4200D Gyroscope device */
+	REGULATOR_SUPPLY("vdd", "2-0068"),
+	/* Ambient light sensor device */
+	REGULATOR_SUPPLY("vdd", "3-0029"),
+	/* Pressure sensor device */
+	REGULATOR_SUPPLY("vdd", "2-005c"),
+	/* Cypress TrueTouch Touchscreen device */
+	REGULATOR_SUPPLY("vcpin", "spi8.0"),
+	/* Camera device */
+	REGULATOR_SUPPLY("vaux12v5", "mmio_camera"),
+};
+
+static struct regulator_consumer_supply ab8500_vaux2_consumers[] = {
+	/* On-board eMMC power */
+	REGULATOR_SUPPLY("vmmc", "sdi4"),
+	/* AB8500 audio codec */
+	REGULATOR_SUPPLY("vcc-N2158", "ab8500-codec.0"),
+	/* AB8500 accessory detect 1 */
+	REGULATOR_SUPPLY("vcc-N2158", "ab8500-acc-det.0"),
+	/* AB8500 Tv-out device */
+	REGULATOR_SUPPLY("vcc-N2158", "mcde_tv_ab8500.4"),
+	/* AV8100 HDMI device */
+	REGULATOR_SUPPLY("vcc-N2158", "av8100_hdmi.3"),
+};
+
+static struct regulator_consumer_supply ab8500_vaux3_consumers[] = {
+	REGULATOR_SUPPLY("v-SD-STM", "stm"),
+	/* External MMC slot power */
+	REGULATOR_SUPPLY("vmmc", "sdi0"),
+};
+
+static struct regulator_consumer_supply ab8500_vtvout_consumers[] = {
+	/* TV-out DENC supply */
+	REGULATOR_SUPPLY("vtvout", "ab8500-denc.0"),
+	/* Internal general-purpose ADC */
+	REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"),
+	/* ADC for charger */
+	REGULATOR_SUPPLY("vddadc", "ab8500-charger.0"),
+	/* AB8500 Tv-out device */
+	REGULATOR_SUPPLY("vtvout", "mcde_tv_ab8500.4"),
+};
+
+static struct regulator_consumer_supply ab8500_vaud_consumers[] = {
+	/* AB8500 audio-codec main supply */
+	REGULATOR_SUPPLY("vaud", "ab8500-codec.0"),
+};
+
+static struct regulator_consumer_supply ab8500_vamic1_consumers[] = {
+	/* AB8500 audio-codec Mic1 supply */
+	REGULATOR_SUPPLY("vamic1", "ab8500-codec.0"),
+};
+
+static struct regulator_consumer_supply ab8500_vamic2_consumers[] = {
+	/* AB8500 audio-codec Mic2 supply */
+	REGULATOR_SUPPLY("vamic2", "ab8500-codec.0"),
+};
+
+static struct regulator_consumer_supply ab8500_vdmic_consumers[] = {
+	/* AB8500 audio-codec DMic supply */
+	REGULATOR_SUPPLY("vdmic", "ab8500-codec.0"),
+};
+
+static struct regulator_consumer_supply ab8500_vintcore_consumers[] = {
+	/* SoC core supply, no device */
+	REGULATOR_SUPPLY("v-intcore", NULL),
+	/* USB Transceiver */
+	REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"),
+	/* Handled by abx500 clk driver */
+	REGULATOR_SUPPLY("v-intcore", "abx500-clk.0"),
+};
+
+static struct regulator_consumer_supply ab8500_vana_consumers[] = {
+	/* DB8500 DSI */
+	REGULATOR_SUPPLY("vdddsi1v2", "mcde"),
+	REGULATOR_SUPPLY("vdddsi1v2", "b2r2_core"),
+	REGULATOR_SUPPLY("vdddsi1v2", "b2r2_1_core"),
+	REGULATOR_SUPPLY("vdddsi1v2", "dsilink.0"),
+	REGULATOR_SUPPLY("vdddsi1v2", "dsilink.1"),
+	REGULATOR_SUPPLY("vdddsi1v2", "dsilink.2"),
+	/* DB8500 CSI */
+	REGULATOR_SUPPLY("vddcsi1v2", "mmio_camera"),
+};
+
+/* ab8500 regulator register initialization */
+static struct ab8500_regulator_reg_init ab8500_reg_init[] = {
+	/*
+	 * VanaRequestCtrl          = HP/LP depending on VxRequest
+	 * VextSupply1RequestCtrl   = HP/LP depending on VxRequest
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2,       0xf0, 0x00),
+	/*
+	 * VextSupply2RequestCtrl   = HP/LP depending on VxRequest
+	 * VextSupply3RequestCtrl   = HP/LP depending on VxRequest
+	 * Vaux1RequestCtrl         = HP/LP depending on VxRequest
+	 * Vaux2RequestCtrl         = HP/LP depending on VxRequest
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3,       0xff, 0x00),
+	/*
+	 * Vaux3RequestCtrl         = HP/LP depending on VxRequest
+	 * SwHPReq                  = Control through SWValid disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4,       0x07, 0x00),
+	/*
+	 * VanaSysClkReq1HPValid    = disabled
+	 * Vaux1SysClkReq1HPValid   = disabled
+	 * Vaux2SysClkReq1HPValid   = disabled
+	 * Vaux3SysClkReq1HPValid   = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0xe8, 0x00),
+	/*
+	 * VextSupply1SysClkReq1HPValid = disabled
+	 * VextSupply2SysClkReq1HPValid = disabled
+	 * VextSupply3SysClkReq1HPValid = SysClkReq1 controlled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x70, 0x40),
+	/*
+	 * VanaHwHPReq1Valid        = disabled
+	 * Vaux1HwHPreq1Valid       = disabled
+	 * Vaux2HwHPReq1Valid       = disabled
+	 * Vaux3HwHPReqValid        = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1,     0xe8, 0x00),
+	/*
+	 * VextSupply1HwHPReq1Valid = disabled
+	 * VextSupply2HwHPReq1Valid = disabled
+	 * VextSupply3HwHPReq1Valid = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2,     0x07, 0x00),
+	/*
+	 * VanaHwHPReq2Valid        = disabled
+	 * Vaux1HwHPReq2Valid       = disabled
+	 * Vaux2HwHPReq2Valid       = disabled
+	 * Vaux3HwHPReq2Valid       = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1,     0xe8, 0x00),
+	/*
+	 * VextSupply1HwHPReq2Valid = disabled
+	 * VextSupply2HwHPReq2Valid = disabled
+	 * VextSupply3HwHPReq2Valid = HWReq2 controlled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2,     0x07, 0x04),
+	/*
+	 * VanaSwHPReqValid         = disabled
+	 * Vaux1SwHPReqValid        = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1,      0xa0, 0x00),
+	/*
+	 * Vaux2SwHPReqValid        = disabled
+	 * Vaux3SwHPReqValid        = disabled
+	 * VextSupply1SwHPReqValid  = disabled
+	 * VextSupply2SwHPReqValid  = disabled
+	 * VextSupply3SwHPReqValid  = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2,      0x1f, 0x00),
+	/*
+	 * SysClkReq2Valid1         = SysClkReq2 controlled
+	 * SysClkReq3Valid1         = disabled
+	 * SysClkReq4Valid1         = SysClkReq4 controlled
+	 * SysClkReq5Valid1         = disabled
+	 * SysClkReq6Valid1         = SysClkReq6 controlled
+	 * SysClkReq7Valid1         = disabled
+	 * SysClkReq8Valid1         = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1,    0xfe, 0x2a),
+	/*
+	 * SysClkReq2Valid2         = disabled
+	 * SysClkReq3Valid2         = disabled
+	 * SysClkReq4Valid2         = disabled
+	 * SysClkReq5Valid2         = disabled
+	 * SysClkReq6Valid2         = SysClkReq6 controlled
+	 * SysClkReq7Valid2         = disabled
+	 * SysClkReq8Valid2         = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2,    0xfe, 0x20),
+	/*
+	 * VTVoutEna                = disabled
+	 * Vintcore12Ena            = disabled
+	 * Vintcore12Sel            = 1.25 V
+	 * Vintcore12LP             = inactive (HP)
+	 * VTVoutLP                 = inactive (HP)
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUMISC1,              0xfe, 0x10),
+	/*
+	 * VaudioEna                = disabled
+	 * VdmicEna                 = disabled
+	 * Vamic1Ena                = disabled
+	 * Vamic2Ena                = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY,           0x1e, 0x00),
+	/*
+	 * Vamic1_dzout             = high-Z when Vamic1 is disabled
+	 * Vamic2_dzout             = high-Z when Vamic2 is disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC,         0x03, 0x00),
+	/*
+	 * VPll                     = Hw controlled (NOTE! PRCMU bits)
+	 * VanaRegu                 = force off
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU,           0x0f, 0x02),
+	/*
+	 * VrefDDREna               = disabled
+	 * VrefDDRSleepMode         = inactive (no pulldown)
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VREFDDR,                0x03, 0x00),
+	/*
+	 * VextSupply1Regu          = force LP
+	 * VextSupply2Regu          = force OFF
+	 * VextSupply3Regu          = force HP (-> STBB2=LP and TPS=LP)
+	 * ExtSupply2Bypass         = ExtSupply12LPn ball is 0 when Ena is 0
+	 * ExtSupply3Bypass         = ExtSupply3LPn ball is 0 when Ena is 0
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU,          0xff, 0x13),
+	/*
+	 * Vaux1Regu                = force HP
+	 * Vaux2Regu                = force off
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU,             0x0f, 0x01),
+	/*
+	 * Vaux3Regu                = force off
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU,          0x03, 0x00),
+	/*
+	 * Vaux1Sel                 = 2.8 V
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL,               0x0f, 0x0C),
+	/*
+	 * Vaux2Sel                 = 2.9 V
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL,               0x0f, 0x0d),
+	/*
+	 * Vaux3Sel                 = 2.91 V
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL,           0x07, 0x07),
+	/*
+	 * VextSupply12LP           = disabled (no LP)
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE,         0x01, 0x00),
+	/*
+	 * Vaux1Disch               = short discharge time
+	 * Vaux2Disch               = short discharge time
+	 * Vaux3Disch               = short discharge time
+	 * Vintcore12Disch          = short discharge time
+	 * VTVoutDisch              = short discharge time
+	 * VaudioDisch              = short discharge time
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH,          0xfc, 0x00),
+	/*
+	 * VanaDisch                = short discharge time
+	 * VdmicPullDownEna         = pulldown disabled when Vdmic is disabled
+	 * VdmicDisch               = short discharge time
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2,         0x16, 0x00),
+};
+
+/* AB8500 regulators */
+static struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
+	/* supplies to the display/camera */
+	[AB8500_LDO_AUX1] = {
+		.supply_regulator = "ab8500-ext-supply3",
+		.constraints = {
+			.name = "V-DISPLAY",
+			.min_uV = 2800000,
+			.max_uV = 3300000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS,
+			.boot_on = 1, /* display is on at boot */
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
+		.consumer_supplies = ab8500_vaux1_consumers,
+	},
+	/* supplies to the on-board eMMC */
+	[AB8500_LDO_AUX2] = {
+		.supply_regulator = "ab8500-ext-supply3",
+		.constraints = {
+			.name = "V-eMMC1",
+			.min_uV = 1100000,
+			.max_uV = 3300000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers),
+		.consumer_supplies = ab8500_vaux2_consumers,
+	},
+	/* supply for VAUX3, supplies to SDcard slots */
+	[AB8500_LDO_AUX3] = {
+		.supply_regulator = "ab8500-ext-supply3",
+		.constraints = {
+			.name = "V-MMC-SD",
+			.min_uV = 1100000,
+			.max_uV = 3300000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers),
+		.consumer_supplies = ab8500_vaux3_consumers,
+	},
+	/* supply for tvout, gpadc, TVOUT LDO */
+	[AB8500_LDO_TVOUT] = {
+		.constraints = {
+			.name = "V-TVOUT",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vtvout_consumers),
+		.consumer_supplies = ab8500_vtvout_consumers,
+	},
+	/* supply for ab8500-vaudio, VAUDIO LDO */
+	[AB8500_LDO_AUDIO] = {
+		.constraints = {
+			.name = "V-AUD",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaud_consumers),
+		.consumer_supplies = ab8500_vaud_consumers,
+	},
+	/* supply for v-anamic1 VAMic1-LDO */
+	[AB8500_LDO_ANAMIC1] = {
+		.constraints = {
+			.name = "V-AMIC1",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vamic1_consumers),
+		.consumer_supplies = ab8500_vamic1_consumers,
+	},
+	/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
+	[AB8500_LDO_ANAMIC2] = {
+		.constraints = {
+			.name = "V-AMIC2",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vamic2_consumers),
+		.consumer_supplies = ab8500_vamic2_consumers,
+	},
+	/* supply for v-dmic, VDMIC LDO */
+	[AB8500_LDO_DMIC] = {
+		.constraints = {
+			.name = "V-DMIC",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vdmic_consumers),
+		.consumer_supplies = ab8500_vdmic_consumers,
+	},
+	/* supply for v-intcore12, VINTCORE12 LDO */
+	[AB8500_LDO_INTCORE] = {
+		.constraints = {
+			.name = "V-INTCORE",
+			.min_uV = 1250000,
+			.max_uV = 1350000,
+			.input_uV = 1800000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_MODE |
+					  REGULATOR_CHANGE_DRMS,
+			.valid_modes_mask = REGULATOR_MODE_NORMAL |
+					    REGULATOR_MODE_IDLE,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers),
+		.consumer_supplies = ab8500_vintcore_consumers,
+	},
+	/* supply for U8500 CSI-DSI, VANA LDO */
+	[AB8500_LDO_ANA] = {
+		.constraints = {
+			.name = "V-CSI-DSI",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers),
+		.consumer_supplies = ab8500_vana_consumers,
+	},
+};
+
+/* supply for VextSupply3 */
+static struct regulator_consumer_supply ab8500_ext_supply3_consumers[] = {
+	/* SIM supply for 3 V SIM cards */
+	REGULATOR_SUPPLY("vinvsim", "sim-detect.0"),
+};
+
+/*
+ * AB8500 external regulators
+ */
+static struct regulator_init_data ab8500_ext_regulators[] = {
+	/* fixed Vbat supplies VSMPS1_EXT_1V8 */
+	[AB8500_EXT_SUPPLY1] = {
+		.constraints = {
+			.name = "ab8500-ext-supply1",
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+			.initial_mode = REGULATOR_MODE_IDLE,
+			.boot_on = 1,
+			.always_on = 1,
+		},
+	},
+	/* fixed Vbat supplies VSMPS2_EXT_1V36 and VSMPS5_EXT_1V15 */
+	[AB8500_EXT_SUPPLY2] = {
+		.constraints = {
+			.name = "ab8500-ext-supply2",
+			.min_uV = 1360000,
+			.max_uV = 1360000,
+		},
+	},
+	/* fixed Vbat supplies VSMPS3_EXT_3V4 and VSMPS4_EXT_3V4 */
+	[AB8500_EXT_SUPPLY3] = {
+		.constraints = {
+			.name = "ab8500-ext-supply3",
+			.min_uV = 3400000,
+			.max_uV = 3400000,
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+			.boot_on = 1,
+		},
+		.num_consumer_supplies =
+			ARRAY_SIZE(ab8500_ext_supply3_consumers),
+		.consumer_supplies = ab8500_ext_supply3_consumers,
+	},
+};
+
+static struct ab8500_regulator_platform_data ab8500_regulator_plat_data = {
+	.reg_init               = ab8500_reg_init,
+	.num_reg_init           = ARRAY_SIZE(ab8500_reg_init),
+	.regulator              = ab8500_regulators,
+	.num_regulator          = ARRAY_SIZE(ab8500_regulators),
+	.ext_regulator          = ab8500_ext_regulators,
+	.num_ext_regulator      = ARRAY_SIZE(ab8500_ext_regulators),
+};
+
 /**
  * struct ab8500_ext_regulator_info - ab8500 regulator information
  * @dev: device pointer
@@ -344,8 +794,7 @@ static struct of_regulator_match ab8500_ext_regulator_match[] = {
 static int ab8500_ext_regulator_probe(struct platform_device *pdev)
 {
 	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
-	struct ab8500_platform_data *ppdata;
-	struct ab8500_regulator_platform_data *pdata;
+	struct ab8500_regulator_platform_data *pdata = &ab8500_regulator_plat_data;
 	struct device_node *np = pdev->dev.of_node;
 	struct regulator_config config = { };
 	int i, err;
@@ -366,18 +815,6 @@ static int ab8500_ext_regulator_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	ppdata = dev_get_platdata(ab8500->dev);
-	if (!ppdata) {
-		dev_err(&pdev->dev, "null parent pdata\n");
-		return -EINVAL;
-	}
-
-	pdata = ppdata->regulator;
-	if (!pdata) {
-		dev_err(&pdev->dev, "null pdata\n");
-		return -EINVAL;
-	}
-
 	/* make sure the platform data has the correct size */
 	if (pdata->num_ext_regulator != ARRAY_SIZE(ab8500_ext_regulator_info)) {
 		dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
-- 
2.7.0



From k.kozlowski at samsung.com  Tue May 10 07:03:07 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 16:03:07 +0200
Subject: [PATCH] ARM: dts: exynos: Only Odroid XU3-family boards use DTSI
 with CPU thermal nodes
In-Reply-To: <CANAwSgRsjdQh6ygT__5XcH8-cF9Ch+zbk8oupebwYzY1kCZu6g@mail.gmail.com>
References: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>
 <CANAwSgT9SY3kj8+beMpc1xGoC=rMBSya+2v2dyZQp6ykH+V0=g@mail.gmail.com>
 <573198BE.6020900@samsung.com>
 <CANAwSgTy6p9AVmmOWATpSO1JqVbwE0v+y_y-RLd+32RnNJTA+Q@mail.gmail.com>
 <5731D764.8070007@samsung.com>
 <CANAwSgRsjdQh6ygT__5XcH8-cF9Ch+zbk8oupebwYzY1kCZu6g@mail.gmail.com>
Message-ID: <5731EA1B.4070201@samsung.com>

On 05/10/2016 04:00 PM, Anand Moon wrote:
> Hi Krzysztof,
> 
> On 10 May 2016 at 18:13, Krzysztof Kozlowski <k.kozlowski at samsung.com> wrote:
>> On 05/10/2016 11:29 AM, Anand Moon wrote:
>>>>
>>>> I am sorry but I do not understand.
>>>> 1. Are you saying that my patch causes the issue?
>>>> 2. Are you saying that I should not send some patches because of
>>>> conflicting work? (that would be peculiar...)
>>>> 3. Are you saying that I should not apply this patch to me tree because
>>>> of conflicting work?
>>>> 4. Other?
>>>>
>>>> Best regards.
>>>> Krzysztof
>>>>
>>>>
>>>
>>> Sorry for the confusion it's not about you patch.
>>> The feature is not working correctly as per my testing with the
>>> original source code.
>>> It need to be more tuned or some other approach to the issue need to found.
>>
>> Known issue. You don't have cpufreq cooling enabled. I sent patches for
>> that and they are in the mainline. However cpufreq cooling requires
>> cpufreq which cannot work with BL_SWITCHER and on Exynos542x on
>> exynos_defconfig BL_SWITCHER is enabled.
>>
>> Just disable the BL_Krzysztof.
>>
>> Best regards,
>> Krzysztof
> 
> I have already disabled BL_SWITCHER in my exynos_defconfig. to support
> CONFIG_CPUFREQ_DT.
> 
> But how about adjust the  the cputemp so that all the core will have
> same tip points.


I don't understand you. All of the cores have same trip points.

Best regards,
Krzysztof

> 
> xcpu0-t 0:[ 44][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>     A50
>      A60       P70            P85                                C120
> ]
> xcpu1-t 1:[ 46][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>                               A85               A103   A110      C120
> ]
> xcpu2-t 2:[ 51][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>                          A85               A103   A110      C120 ]
> xcpu3-t 3:[ 47][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>                              A85               A103   A110      C120 ]
> xgpu-th 4:[ 48][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>                             A85               A103   A110      C120 ]




From arnd at arndb.de  Tue May 10 07:02:05 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 16:02:05 +0200
Subject: [PATCH 3/4] ASoC: ab8500-codec: remove platform data based probe
Message-ID: <1462888941-2810783-1-git-send-email-arnd@arndb.de>

The ux500 platform hasn't used board files for a long time, and
nothing defines a ab8500_codec_platform_data, so we can just
remove the probing based on that and always use device tree
properties directly.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 sound/soc/codecs/ab8500-codec.c | 33 ++++-----------------------------
 1 file changed, 4 insertions(+), 29 deletions(-)

diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index 8b1d0c1a7839..2fc89155f14a 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -2464,45 +2464,20 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec)
 	struct device *dev = codec->dev;
 	struct device_node *np = dev->of_node;
 	struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(dev);
-	struct ab8500_platform_data *pdata;
+	struct ab8500_codec_platform_data codec_pdata;
 	struct filter_control *fc;
 	int status;
 
 	dev_dbg(dev, "%s: Enter.\n", __func__);
 
-	/* Setup AB8500 according to board-settings */
-	pdata = dev_get_platdata(dev->parent);
+	ab8500_codec_of_probe(dev, np, &codec_pdata);
 
-	if (np) {
-		if (!pdata)
-			pdata = devm_kzalloc(dev,
-					sizeof(struct ab8500_platform_data),
-					GFP_KERNEL);
-
-		if (pdata && !pdata->codec)
-			pdata->codec
-				= devm_kzalloc(dev,
-					sizeof(struct ab8500_codec_platform_data),
-					GFP_KERNEL);
-
-		if (!(pdata && pdata->codec))
-			return -ENOMEM;
-
-		ab8500_codec_of_probe(dev, np, pdata->codec);
-
-	} else {
-		if (!(pdata && pdata->codec)) {
-			dev_err(dev, "No codec platform data or DT found\n");
-			return -EINVAL;
-		}
-	}
-
-	status = ab8500_audio_setup_mics(codec, &pdata->codec->amics);
+	status = ab8500_audio_setup_mics(codec, &codec_pdata.amics);
 	if (status < 0) {
 		pr_err("%s: Failed to setup mics (%d)!\n", __func__, status);
 		return status;
 	}
-	status = ab8500_audio_set_ear_cmv(codec, pdata->codec->ear_cmv);
+	status = ab8500_audio_set_ear_cmv(codec, codec_pdata.ear_cmv);
 	if (status < 0) {
 		pr_err("%s: Failed to set earpiece CM-voltage (%d)!\n",
 			__func__, status);
-- 
2.7.0



From arnd at arndb.de  Tue May 10 07:02:45 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 16:02:45 +0200
Subject: [PATCH 4/4] mfd: db8500 stop passing around platform data
Message-ID: <1462889050-2818609-1-git-send-email-arnd@arndb.de>

Except for the constant DB8500_PRCMU_FW_VERSION_OFFSET number, nothing
is ever passed through the platform data and used in a driver, so we
can simply stop passing it around.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 arch/arm/mach-ux500/cpu-db8500.c          | 17 ++--------------
 arch/arm/mach-ux500/setup.h               |  1 -
 drivers/mfd/ab8500-core.c                 |  4 ----
 drivers/mfd/ab8500-sysctrl.c              | 34 -------------------------------
 drivers/mfd/db8500-prcmu.c                | 10 +++------
 include/linux/mfd/abx500/ab8500-sysctrl.h |  6 ------
 include/linux/mfd/dbx500-prcmu.h          | 10 ---------
 7 files changed, 5 insertions(+), 77 deletions(-)

diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index c015ef8dd535..bbd1b4b8d441 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -16,8 +16,6 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/dbx500-prcmu.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/perf/arm_pmu.h>
@@ -32,15 +30,6 @@
 #include "db8500-regs.h"
 #include "id.h"
 
-static struct ab8500_platform_data ab8500_platdata = {
-};
-
-static struct prcmu_pdata db8500_prcmu_pdata = {
-	.ab_platdata	= &ab8500_platdata,
-	.version_offset	= DB8500_PRCMU_FW_VERSION_OFFSET,
-	.legacy_offset	= DB8500_PRCMU_LEGACY_OFFSET,
-};
-
 static void __init u8500_map_io(void)
 {
 	debug_ll_io_init();
@@ -109,8 +98,7 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80125000,
 		       "ux500-msp-i2s.3", &msp3_platform_data),
 	/* Requires non-DT:able platform data. */
-	OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu",
-			&db8500_prcmu_pdata),
+	OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu", NULL),
 	OF_DEV_AUXDATA("stericsson,ux500-cryp", 0xa03cb000, "cryp1", NULL),
 	OF_DEV_AUXDATA("stericsson,ux500-hash", 0xa03c2000, "hash1", NULL),
 	OF_DEV_AUXDATA("stericsson,snd-soc-mop500", 0, "snd-soc-mop500.0",
@@ -119,8 +107,7 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
 };
 
 static struct of_dev_auxdata u8540_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu",
-			&db8500_prcmu_pdata),
+	OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu", NULL),
 	{},
 };
 
diff --git a/arch/arm/mach-ux500/setup.h b/arch/arm/mach-ux500/setup.h
index c704254ab67c..e606847c8b58 100644
--- a/arch/arm/mach-ux500/setup.h
+++ b/arch/arm/mach-ux500/setup.h
@@ -13,7 +13,6 @@
 
 #include <asm/mach/arch.h>
 #include <linux/init.h>
-#include <linux/mfd/abx500/ab8500.h>
 
 void ux500_restart(enum reboot_mode mode, const char *cmd);
 
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index f3d689176fc2..589eebfc13df 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -1087,7 +1087,6 @@ static int ab8500_probe(struct platform_device *pdev)
 		"Vbus Detect (USB)",
 		"USB ID Detect",
 		"UART Factory Mode Detect"};
-	struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
 	const struct platform_device_id *platid = platform_get_device_id(pdev);
 	enum ab8500_version version = AB8500_VERSION_UNDEFINED;
 	struct device_node *np = pdev->dev.of_node;
@@ -1219,9 +1218,6 @@ static int ab8500_probe(struct platform_device *pdev)
 		pr_cont("None\n");
 	}
 
-	if (plat && plat->init)
-		plat->init(ab8500);
-
 	if (is_ab9540(ab8500)) {
 		ret = get_register_interruptible(ab8500, AB8500_CHARGER,
 			AB8500_CH_USBCH_STAT1_REG, &value);
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
index b9f0010309f9..207cc497958a 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -127,45 +127,11 @@ EXPORT_SYMBOL(ab8500_sysctrl_write);
 
 static int ab8500_sysctrl_probe(struct platform_device *pdev)
 {
-	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
-	struct ab8500_platform_data *plat;
-	struct ab8500_sysctrl_platform_data *pdata;
-
-	plat = dev_get_platdata(pdev->dev.parent);
-
-	if (!plat)
-		return -EINVAL;
-
 	sysctrl_dev = &pdev->dev;
 
 	if (!pm_power_off)
 		pm_power_off = ab8500_power_off;
 
-	pdata = plat->sysctrl;
-	if (pdata) {
-		int last, ret, i, j;
-
-		if (is_ab8505(ab8500))
-			last = AB8500_SYSCLKREQ4RFCLKBUF;
-		else
-			last = AB8500_SYSCLKREQ8RFCLKBUF;
-
-		for (i = AB8500_SYSCLKREQ1RFCLKBUF; i <= last; i++) {
-			j = i - AB8500_SYSCLKREQ1RFCLKBUF;
-			ret = ab8500_sysctrl_write(i, 0xff,
-					pdata->initial_req_buf_config[j]);
-			dev_dbg(&pdev->dev,
-					"Setting SysClkReq%dRfClkBuf 0x%X\n",
-					j + 1,
-					pdata->initial_req_buf_config[j]);
-			if (ret < 0) {
-				dev_err(&pdev->dev,
-					"Can't set sysClkReq%dRfClkBuf: %d\n",
-					j + 1, ret);
-			}
-		}
-	}
-
 	return 0;
 }
 
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index c0a86aeb1733..388e268b9bcf 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -3094,8 +3094,7 @@ static void db8500_prcmu_update_cpufreq(void)
 	}
 }
 
-static int db8500_prcmu_register_ab8500(struct device *parent,
-					struct ab8500_platform_data *pdata)
+static int db8500_prcmu_register_ab8500(struct device *parent)
 {
 	struct device_node *np;
 	struct resource ab8500_resource;
@@ -3103,8 +3102,6 @@ static int db8500_prcmu_register_ab8500(struct device *parent,
 		.name = "ab8500-core",
 		.of_compatible = "stericsson,ab8500",
 		.id = AB8500_VERSION_AB8500,
-		.platform_data = pdata,
-		.pdata_size = sizeof(struct ab8500_platform_data),
 		.resources = &ab8500_resource,
 		.num_resources = 1,
 	};
@@ -3133,7 +3130,6 @@ static int db8500_prcmu_register_ab8500(struct device *parent,
 static int db8500_prcmu_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-	struct prcmu_pdata *pdata = dev_get_platdata(&pdev->dev);
 	int irq = 0, err = 0;
 	struct resource *res;
 
@@ -3149,7 +3145,7 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 	init_prcm_registers();
-	dbx500_fw_version_init(pdev, pdata->version_offset);
+	dbx500_fw_version_init(pdev, DB8500_PRCMU_FW_VERSION_OFFSET);
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
 	if (!res) {
 		dev_err(&pdev->dev, "no prcmu tcdm region provided\n");
@@ -3204,7 +3200,7 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
 		}
 	}
 
-	err = db8500_prcmu_register_ab8500(&pdev->dev, pdata->ab_platdata);
+	err = db8500_prcmu_register_ab8500(&pdev->dev);
 	if (err) {
 		mfd_remove_devices(&pdev->dev);
 		pr_err("prcmu: Failed to add ab8500 subdevice\n");
diff --git a/include/linux/mfd/abx500/ab8500-sysctrl.h b/include/linux/mfd/abx500/ab8500-sysctrl.h
index 689312745b2f..01024d1aed0e 100644
--- a/include/linux/mfd/abx500/ab8500-sysctrl.h
+++ b/include/linux/mfd/abx500/ab8500-sysctrl.h
@@ -37,12 +37,6 @@ static inline int ab8500_sysctrl_clear(u16 reg, u8 bits)
 	return ab8500_sysctrl_write(reg, bits, 0);
 }
 
-/* Configuration data for SysClkReq1RfClkBuf - SysClkReq8RfClkBuf */
-struct ab8500_sysctrl_platform_data {
-	u8 initial_req_buf_config[8];
-	u16 (*reboot_reason_code)(const char *cmd);
-};
-
 /* Registers */
 #define AB8500_TURNONSTATUS		0x100
 #define AB8500_RESETSTATUS		0x101
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index bf5109d38a26..5d374601404c 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -178,16 +178,6 @@ enum ddr_pwrst {
 
 #define DB8500_PRCMU_LEGACY_OFFSET		0xDD4
 
-struct prcmu_pdata
-{
-	bool enable_set_ddr_opp;
-	bool enable_ape_opp_100_voltage;
-	struct ab8500_platform_data *ab_platdata;
-	u32 version_offset;
-	u32 legacy_offset;
-	u32 adt_offset;
-};
-
 #define PRCMU_FW_PROJECT_U8500		2
 #define PRCMU_FW_PROJECT_U8400		3
 #define PRCMU_FW_PROJECT_U9500		4 /* Customer specific */
-- 
2.7.0



From christoffer.dall at linaro.org  Tue May 10 07:04:54 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 10 May 2016 16:04:54 +0200
Subject: [PATCH v3 19/55] KVM: arm/arm64: vgic-new: Add GICv3 world
 switch backend
In-Reply-To: <1462531568-9799-20-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-20-git-send-email-andre.przywara@arm.com>
Message-ID: <20160510140454.GG27623@cbox>

On Fri, May 06, 2016 at 11:45:32AM +0100, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> As the GICv3 virtual interface registers differ from their GICv2
> siblings, we need different handlers for processing maintenance
> interrupts and reading/writing to the LRs.
> Implement the respective handler functions and connect them to
> existing code to be called if the host is using a GICv3.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - remove outdated comment about the dist_lock
> - add WARN_ON about LR_STATE not being 0 in maintenance interrupts
> 
> Changelog v1 .. v2:
> - inject the IRQ priority into the list register
> 
> Changelog v2 .. v3:
> - remove no longer needed irqchip/arm-gic.h inclusion
> 
>  include/linux/irqchip/arm-gic-v3.h |   1 +
>  virt/kvm/arm/vgic/vgic-v3.c        | 168 +++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.c           |  25 ++++--
>  virt/kvm/arm/vgic/vgic.h           |  29 +++++++
>  4 files changed, 218 insertions(+), 5 deletions(-)
>  create mode 100644 virt/kvm/arm/vgic/vgic-v3.c
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index ec938d1..35e93cf 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -275,6 +275,7 @@
>  #define ICH_LR_ACTIVE_BIT		(1ULL << 63)
>  #define ICH_LR_PHYS_ID_SHIFT		32
>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
> +#define ICH_LR_PRIORITY_SHIFT		48
>  
>  /* These are for GICv2 emulation only */
>  #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> new file mode 100644
> index 0000000..43d1dd7
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -0,0 +1,168 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * 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/irqchip/arm-gic-v3.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +
> +#include "vgic.h"
> +
> +void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
> +	u32 model = vcpu->kvm->arch.vgic.vgic_model;
> +
> +	if (cpuif->vgic_misr & ICH_MISR_EOI) {
> +		unsigned long eisr_bmap = cpuif->vgic_eisr;
> +		int lr;
> +
> +		for_each_set_bit(lr, &eisr_bmap, kvm_vgic_global_state.nr_lr) {
> +			u32 intid;
> +			u64 val = cpuif->vgic_lr[lr];
> +
> +			if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
> +				intid = val & ICH_LR_VIRTUAL_ID_MASK;
> +			else
> +				intid = val & GICH_LR_VIRTUALID;
> +
> +			WARN_ON(cpuif->vgic_lr[lr] & ICH_LR_STATE);
> +
> +			kvm_notify_acked_irq(vcpu->kvm, 0,
> +					     intid - VGIC_NR_PRIVATE_IRQS);
> +

same question as on the last patch

> +			cpuif->vgic_elrsr |= 1ULL << lr;
> +		}
> +
> +		/*
> +		 * In the next iterations of the vcpu loop, if we sync
> +		 * the vgic state after flushing it, but before
> +		 * entering the guest (this happens for pending
> +		 * signals and vmid rollovers), then make sure we
> +		 * don't pick up any old maintenance interrupts here.
> +		 */
> +		cpuif->vgic_eisr = 0;
> +	}
> +
> +	cpuif->vgic_hcr &= ~ICH_HCR_UIE;
> +}
> +
> +void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
> +
> +	cpuif->vgic_hcr |= ICH_HCR_UIE;
> +}
> +
> +void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
> +	u32 model = vcpu->kvm->arch.vgic.vgic_model;
> +	int lr;
> +
> +	/* Assumes ap_list_lock held */
> +
> +	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
> +		u64 val = cpuif->vgic_lr[lr];
> +		u32 intid;
> +		struct vgic_irq *irq;
> +
> +		if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
> +			intid = val & ICH_LR_VIRTUAL_ID_MASK;
> +		else
> +			intid = val & GICH_LR_VIRTUALID;
> +		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		/* Always preserve the active bit */
> +		irq->active = !!(val & ICH_LR_ACTIVE_BIT);
> +
> +		/* Edge is the only case where we preserve the pending bit */
> +		if (irq->config == VGIC_CONFIG_EDGE &&
> +		    (val & ICH_LR_PENDING_BIT)) {
> +			irq->pending = true;
> +
> +			if (vgic_irq_is_sgi(intid) &&
> +			    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
> +				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
> +
> +				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
> +				irq->source |= (1 << cpuid);
> +			}
> +		}
> +
> +		/* Clear soft pending state when level irqs have been acked */
> +		if (irq->config == VGIC_CONFIG_LEVEL &&
> +		    !(val & ICH_LR_PENDING_BIT)) {
> +			irq->soft_pending = false;
> +			irq->pending = irq->line_level;
> +		}
> +
> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
> +/* Requires the irq to be locked already */
> +void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
> +{
> +	u32 model = vcpu->kvm->arch.vgic.vgic_model;
> +	u64 val = irq->intid;
> +
> +	if (irq->pending) {
> +		val |= ICH_LR_PENDING_BIT;
> +
> +		if (irq->config == VGIC_CONFIG_EDGE)
> +			irq->pending = false;
> +
> +		if (vgic_irq_is_sgi(irq->intid) &&
> +		    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
> +			u32 src = ffs(irq->source);
> +
> +			BUG_ON(!src);
> +			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
> +			irq->source &= ~(1 << (src - 1));
> +			if (irq->source)
> +				irq->pending = true;
> +		}
> +	}
> +
> +	if (irq->active)
> +		val |= ICH_LR_ACTIVE_BIT;
> +
> +	if (irq->hw) {
> +		val |= ICH_LR_HW;
> +		val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
> +	} else {
> +		if (irq->config == VGIC_CONFIG_LEVEL)
> +			val |= ICH_LR_EOI;
> +	}
> +
> +	/*
> +	 * Currently all guest IRQs are Group1, as Group0 would result
> +	 * in a FIQ in the guest, which it wouldn't expect.

I still don't like or understand this comment.  This should simply say
that we're making a gross assumption about all interrupts being group1
here.

> +	 * Eventually we want to make this configurable, so we may
> +	 * revisit this in the future.
> +	 */
> +	if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
> +		val |= ICH_LR_GROUP;
> +
> +	val |= (u64)irq->priority << ICH_LR_PRIORITY_SHIFT;
> +
> +	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = val;
> +}
> +
> +void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
> +{
> +	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 68d885c..64d5b45 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -397,12 +397,18 @@ retry:
>  
>  static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
>  {
> -	vgic_v2_process_maintenance(vcpu);
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_process_maintenance(vcpu);
> +	else
> +		vgic_v3_process_maintenance(vcpu);
>  }
>  
>  static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
>  {
> -	vgic_v2_fold_lr_state(vcpu);
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_fold_lr_state(vcpu);
> +	else
> +		vgic_v3_fold_lr_state(vcpu);
>  }
>  
>  /* Requires the ap_list_lock and the irq_lock to be held. */
> @@ -412,17 +418,26 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
>  
> -	vgic_v2_populate_lr(vcpu, irq, lr);
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_populate_lr(vcpu, irq, lr);
> +	else
> +		vgic_v3_populate_lr(vcpu, irq, lr);
>  }
>  
>  static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
>  {
> -	vgic_v2_clear_lr(vcpu, lr);
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_clear_lr(vcpu, lr);
> +	else
> +		vgic_v3_clear_lr(vcpu, lr);
>  }
>  
>  static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
>  {
> -	vgic_v2_set_underflow(vcpu);
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_set_underflow(vcpu);
> +	else
> +		vgic_v3_set_underflow(vcpu);
>  }
>  
>  static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 0db490e..81b1a20 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -28,4 +28,33 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
>  void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
>  void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
>  
> +#ifdef CONFIG_KVM_ARM_VGIC_V3
> +void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
> +void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
> +void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
> +void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
> +void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
> +#else
> +static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +static inline void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +static inline void vgic_v3_populate_lr(struct kvm_vcpu *vcpu,
> +				       struct vgic_irq *irq, int lr)
> +{
> +}
> +
> +static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
> +{
> +}
> +
> +static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
> +{
> +}
> +#endif
> +
>  #endif
> -- 
> 2.7.3
> 

Otherwise:

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From arnd at arndb.de  Tue May 10 06:59:46 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 15:59:46 +0200
Subject: [RFC PATCH 0/4] ux500 ab8500 cleanup
Message-ID: <1462888794-2793296-1-git-send-email-arnd@arndb.de>

I had promised to send this a while ago, please have a look
at this cleanup I did to move code out of mach-ux500 into the
respective drivers.

Clearly this is not for 4.7 at this time, but if it works, it
would be nice to get it merged into 4.8.

        Arnd



From daniel.thompson at linaro.org  Tue May 10 07:05:15 2016
From: daniel.thompson at linaro.org (Daniel Thompson)
Date: Tue, 10 May 2016 15:05:15 +0100
Subject: [PATCH] arm64: kgdb: Match pstate size with gdbserver protocol
In-Reply-To: <20160510102838.GF22813@arm.com>
References: <1462815566-15086-1-git-send-email-daniel.thompson@linaro.org>
 <20160510102838.GF22813@arm.com>
Message-ID: <d1ef4da0-da9b-37f8-27e8-e28f2b94d611@linaro.org>

On 10/05/16 11:28, Will Deacon wrote:
> Hi Daniel,
>
> So does kgdb do something useful after this patch?

On this occasion I was debugging it on behalf of another developer 
rather than trying to use it myself to debug something so I didn't do 
much additional testing beyond sanity tested the contents of the 
register set.

Naturally it will be *totally* awesome if I get the pseudo-NMI stuff 
working perfectly. ;-)


> On Mon, May 09, 2016 at 06:39:26PM +0100, Daniel Thompson wrote:
>> Current versions of gdb do not interoperate cleanly with kgdb on arm64
>> systems because gdb and kgdb do not use the same register description.
>> This patch modifies kgdb to work with recent releases of gdb (>= 7.8.1).
>>
>> Compatibility with gdb (after the patch is applied) is as follows:
>>
>>   gdb-7.6 and earlier  Ok
>>   gdb-7.7 series       Works if user provides custom target description
>>   gdb-7.8(.0)          Works if user provides custom target description
>>   gdb-7.8.1 and later  Ok
>>
>> When commit 44679a4f142b ("arm64: KGDB: Add step debugging support") was
>> introduced it was paired with a gdb patch that made an incompatible
>> change to the gdbserver protocol. This patch was eventually merged into
>> the gdb sources:
>> https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=a4d9ba85ec5597a6a556afe26b712e878374b9dd
>>
>> The change to the protocol was mostly made to simplify big-endian support
>> inside the kernel gdb stub. Unfortunately the gdb project released
>> gdb-7.7.x and gdb-7.8.0 before the protocol incompatibility was identified
>> and reversed:
>> https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=bdc144174bcb11e808b4e73089b850cf9620a7ee
>>
>> This leaves us in a position where kgdb still uses the no-longer-used
>> protocol; gdb-7.8.1, which restored the original behaviour,If was
>> released on 2014-10-29.
>>
>> I don't believe it is possible to detect/correct the protocol
>> incompatiblity which means the kernel must take a view about which
>> version of the gdb remote protocol is "correct". This patch takes the
>> view that the original/current version of the protocol is correct
>> and that version found in gdb-7.7.x and gdb-7.8.0 is anomalous.
>
> Urgh, this is filthy! Still, without a time machine, I guess there's
> little we can do about it. Can I ask you to respin the patch but with
> the rationale as a comment in the header file, and a pointer to the
> comment from the C code too, please?
>
> The code looks incorrect after this change, so we should justify how
> we've ended up in this state and not everybody looks at the git log
> for that rationale.

Will do.


Daniel.


From arnd at arndb.de  Tue May 10 07:06:59 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 16:06:59 +0200
Subject: [GIT PULL] at91: dt for 4.7 #3
In-Reply-To: <1462546579-3398-1-git-send-email-nicolas.ferre@atmel.com>
References: <1462546579-3398-1-git-send-email-nicolas.ferre@atmel.com>
Message-ID: <5988589.hj0Gr8KPDl@wuerfel>

On Friday 06 May 2016 16:56:19 Nicolas Ferre wrote:
> Some more DT material for 4.7. The fix on the VInCo platform is due to an error
> on the Ethernet driver that was not taking the gpio flag into account. As it is
> about to be fixed now, I have to update the only DT that was making use of it.
> Otherwise, all is about the TRNG nodes addition.
> 
> 

Pulled into next/dt, thanks!

	Arnd


From arnd at arndb.de  Tue May 10 07:10:02 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 16:10:02 +0200
Subject: [PULL REQUEST] aspeed devicetree changes for 4.7
In-Reply-To: <1462796980-13703-1-git-send-email-joel@jms.id.au>
References: <1462796980-13703-1-git-send-email-joel@jms.id.au>
Message-ID: <9966453.FDbS7ntlXe@wuerfel>

On Monday 09 May 2016 21:59:40 Joel Stanley wrote:
> This device trees for a pair of Aspeed BMC SoCs and the boards that they sit
> in.
> 

Pulled into next/dt, thanks!

	Arnd


From christoffer.dall at linaro.org  Tue May 10 07:11:19 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 10 May 2016 16:11:19 +0200
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world
 switch backend
In-Reply-To: <5731E52A.9000402@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
 <20160510133043.GF27623@cbox> <5731E52A.9000402@arm.com>
Message-ID: <20160510141119.GB20499@cbox>

On Tue, May 10, 2016 at 02:42:02PM +0100, Marc Zyngier wrote:
> On 10/05/16 14:30, Christoffer Dall wrote:
> > On Fri, May 06, 2016 at 11:45:31AM +0100, Andre Przywara wrote:
> >> From: Marc Zyngier <marc.zyngier at arm.com>
> >>
> >> Processing maintenance interrupts and accessing the list registers
> >> are dependent on the host's GIC version.
> >> Introduce vgic-v2.c to contain GICv2 specific functions.
> >> Implement the GICv2 specific code for syncing the emulation state
> >> into the VGIC registers.
> >>
> >> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> >> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> >> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >> Changelog RFC..v1:
> >> - remove explicit LR_STATE clearing on maintenance interrupt handling
> >> - improve documentation for vgic_v2_populate_lr()
> >> - remove WARN_ON on non-edge IRQs in maintenance interrupts
> >> - simplify multi-CPU source SGI handling
> >>
> >> Changelog v1 .. v2:
> >> - inject the IRQ priority into the list register
> >>
> >> Changelog v2 .. v3:
> >> - cleanup diff containing rebase artifacts
> >>
> >>  include/linux/irqchip/arm-gic.h |   1 +
> >>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
> >>  virt/kvm/arm/vgic/vgic.c        |   6 ++
> >>  virt/kvm/arm/vgic/vgic.h        |   6 ++
> >>  4 files changed, 191 insertions(+)
> >>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
> >>
> >> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
> >> index 9c94026..be0d26f 100644
> >> --- a/include/linux/irqchip/arm-gic.h
> >> +++ b/include/linux/irqchip/arm-gic.h
> >> @@ -76,6 +76,7 @@
> >>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
> >>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
> >>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
> >> +#define GICH_LR_PRIORITY_SHIFT		23
> >>  #define GICH_LR_STATE			(3 << 28)
> >>  #define GICH_LR_PENDING_BIT		(1 << 28)
> >>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
> >> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> >> new file mode 100644
> >> index 0000000..4cee616
> >> --- /dev/null
> >> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> >> @@ -0,0 +1,178 @@
> >> +/*
> >> + * Copyright (C) 2015, 2016 ARM 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.
> >> + *
> >> + * 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.
> >> + *
> >> + * 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/irqchip/arm-gic.h>
> >> +#include <linux/kvm.h>
> >> +#include <linux/kvm_host.h>
> >> +
> >> +#include "vgic.h"
> >> +
> >> +/*
> >> + * Call this function to convert a u64 value to an unsigned long * bitmask
> >> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
> >> + *
> >> + * Warning: Calling this function may modify *val.
> >> + */
> >> +static unsigned long *u64_to_bitmask(u64 *val)
> >> +{
> >> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
> >> +	*val = (*val >> 32) | (*val << 32);
> >> +#endif
> >> +	return (unsigned long *)val;
> >> +}
> >> +
> >> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
> >> +{
> >> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
> >> +
> >> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
> >> +		u64 eisr = cpuif->vgic_eisr;
> >> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
> >> +		int lr;
> >> +
> >> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
> >> +			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
> >> +
> >> +			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
> >> +
> >> +			kvm_notify_acked_irq(vcpu->kvm, 0,
> >> +					     intid - VGIC_NR_PRIVATE_IRQS);
> >> +
> > 
> > why do we need to do this?  I cannot find any consumers of this info
> > after we've left the hyp code.
> 
> I believe that's for vhost and irqfd. Or am I misreading your question?
> 

I meant the setting of the bits in vgic_elrsr (sorry, badly placed
comment)...

> > Also, I think I offered a comment about why we would potentially need
> > this in the first place.  This is the famous race where hardware doesn't
> > guarantee consistency between the MISR and ELRSR right?
> 
> That's the one (except it is between EISR and ELRSR). I don't have your
> initial comment at hand, but would something like the following do?
> 
> 			/*
> 			 * The maintenance interrupt may not have had a
> 			 * chance to update ELRSR, so let's mark the LRs
> 			 * presents in EISR as empty.
> 			 */
> > 
> >> +			cpuif->vgic_elrsr |= 1ULL << lr;

so, why are we doing this?

> >> +		}
> >> +	}
> 
> Thanks,
> 
> 	M.
> -- 
> Jazz is not dead. It just smells funny...


From arnd at arndb.de  Tue May 10 07:10:59 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 16:10:59 +0200
Subject: [GIT PULL] Allwinner DT for 4.7, round 2
In-Reply-To: <20160509202837.GA19124@lukather>
References: <20160509202837.GA19124@lukather>
Message-ID: <3145233.Qh570kGqYO@wuerfel>

On Monday 09 May 2016 22:28:37 Maxime Ripard wrote:
> Allwinner DT changes for 4.7, round 2
> 
> Mostly DT patches to enable the new DRM driver on the CHIP, preliminary
> support for the A10 and A20, and a support for a new variant of the Olimex
> A20-Olinuxino-Lime2 featuring an eMMC
> 
> 

Merged into next/dt, thanks!

	Arnd


From eric.auger at linaro.org  Tue May 10 07:10:06 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 16:10:06 +0200
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
Message-ID: <5731EBBE.7060203@linaro.org>

On 05/06/2016 12:45 PM, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Processing maintenance interrupts and accessing the list registers
> are dependent on the host's GIC version.
> Introduce vgic-v2.c to contain GICv2 specific functions.
> Implement the GICv2 specific code for syncing the emulation state
> into the VGIC registers.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - remove explicit LR_STATE clearing on maintenance interrupt handling
> - improve documentation for vgic_v2_populate_lr()
> - remove WARN_ON on non-edge IRQs in maintenance interrupts
> - simplify multi-CPU source SGI handling
> 
> Changelog v1 .. v2:
> - inject the IRQ priority into the list register
> 
> Changelog v2 .. v3:
> - cleanup diff containing rebase artifacts
> 
>  include/linux/irqchip/arm-gic.h |   1 +
>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.c        |   6 ++
>  virt/kvm/arm/vgic/vgic.h        |   6 ++
>  4 files changed, 191 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
> 
> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
> index 9c94026..be0d26f 100644
> --- a/include/linux/irqchip/arm-gic.h
> +++ b/include/linux/irqchip/arm-gic.h
> @@ -76,6 +76,7 @@
>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
> +#define GICH_LR_PRIORITY_SHIFT		23
>  #define GICH_LR_STATE			(3 << 28)
>  #define GICH_LR_PENDING_BIT		(1 << 28)
>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> new file mode 100644
> index 0000000..4cee616
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -0,0 +1,178 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * 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/irqchip/arm-gic.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +
> +#include "vgic.h"
> +
> +/*
> + * Call this function to convert a u64 value to an unsigned long * bitmask
> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
> + *
> + * Warning: Calling this function may modify *val.
> + */
> +static unsigned long *u64_to_bitmask(u64 *val)
> +{
> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
> +	*val = (*val >> 32) | (*val << 32);
> +#endif
> +	return (unsigned long *)val;
> +}
> +
> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
> +
> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
> +		u64 eisr = cpuif->vgic_eisr;
> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
> +		int lr;
> +
> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
Didn't we say we could use vcpu->arch.vgic_cpu.used_lrs here?
> +			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
> +
> +			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
> +
> +			kvm_notify_acked_irq(vcpu->kvm, 0,
> +					     intid - VGIC_NR_PRIVATE_IRQS);
> +
> +			cpuif->vgic_elrsr |= 1ULL << lr;
> +		}
> +	}
> +
> +	/* check and disable underflow maintenance IRQ */
check?

Besides
Reviewed-by: Eric Auger <eric.auger at linaro.org>

Eric
> +	cpuif->vgic_hcr &= ~GICH_HCR_UIE;
> +
> +	/*
> +	 * In the next iterations of the vcpu loop, if we sync the
> +	 * vgic state after flushing it, but before entering the guest
> +	 * (this happens for pending signals and vmid rollovers), then
> +	 * make sure we don't pick up any old maintenance interrupts
> +	 * here.
> +	 */
> +	cpuif->vgic_eisr = 0;
> +}
> +
> +void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
> +
> +	cpuif->vgic_hcr |= GICH_HCR_UIE;
> +}
> +
> +/*
> + * transfer the content of the LRs back into the corresponding ap_list:
> + * - active bit is transferred as is
> + * - pending bit is
> + *   - transferred as is in case of edge sensitive IRQs
> + *   - set to the line-level (resample time) for level sensitive IRQs
> + */
> +void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
> +	int lr;
> +
> +	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
> +		u32 val = cpuif->vgic_lr[lr];
> +		u32 intid = val & GICH_LR_VIRTUALID;
> +		struct vgic_irq *irq;
> +
> +		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		/* Always preserve the active bit */
> +		irq->active = !!(val & GICH_LR_ACTIVE_BIT);
> +
> +		/* Edge is the only case where we preserve the pending bit */
> +		if (irq->config == VGIC_CONFIG_EDGE &&
> +		    (val & GICH_LR_PENDING_BIT)) {
> +			irq->pending = true;
> +
> +			if (vgic_irq_is_sgi(intid)) {
> +				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
> +
> +				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
> +				irq->source |= (1 << cpuid);
> +			}
> +		}
> +
> +		/* Clear soft pending state when level IRQs have been acked */
> +		if (irq->config == VGIC_CONFIG_LEVEL &&
> +		    !(val & GICH_LR_PENDING_BIT)) {
> +			irq->soft_pending = false;
> +			irq->pending = irq->line_level;
> +		}
> +
> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
> +/*
> + * Populates the particular LR with the state of a given IRQ:
> + * - for an edge sensitive IRQ the pending state is cleared in struct vgic_irq
> + * - for a level sensitive IRQ the pending state value is unchanged;
> + *   it is dictated directly by the input level
> + *
> + * If @irq describes an SGI with multiple sources, we choose the
> + * lowest-numbered source VCPU and clear that bit in the source bitmap.
> + *
> + * The irq_lock must be held by the caller.
> + */
> +void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
> +{
> +	u32 val = irq->intid;
> +
> +	if (irq->pending) {
> +		val |= GICH_LR_PENDING_BIT;
> +
> +		if (irq->config == VGIC_CONFIG_EDGE)
> +			irq->pending = false;
> +
> +		if (vgic_irq_is_sgi(irq->intid)) {
> +			u32 src = ffs(irq->source);
> +
> +			BUG_ON(!src);
> +			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
> +			irq->source &= ~(1 << (src - 1));
> +			if (irq->source)
> +				irq->pending = true;
> +		}
> +	}
> +
> +	if (irq->active)
> +		val |= GICH_LR_ACTIVE_BIT;
> +
> +	if (irq->hw) {
> +		val |= GICH_LR_HW;
> +		val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
> +	} else {
> +		if (irq->config == VGIC_CONFIG_LEVEL)
> +			val |= GICH_LR_EOI;
> +	}
> +
> +	/* The GICv2 LR only holds five bits of priority. */
> +	val |= (irq->priority >> 3) << GICH_LR_PRIORITY_SHIFT;
> +
> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = val;
> +}
> +
> +void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
> +{
> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index c6f8b9b..68d885c 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -397,10 +397,12 @@ retry:
>  
>  static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
>  {
> +	vgic_v2_process_maintenance(vcpu);
>  }
>  
>  static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
>  {
> +	vgic_v2_fold_lr_state(vcpu);
>  }
>  
>  /* Requires the ap_list_lock and the irq_lock to be held. */
> @@ -409,14 +411,18 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
>  {
>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
> +
> +	vgic_v2_populate_lr(vcpu, irq, lr);
>  }
>  
>  static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
>  {
> +	vgic_v2_clear_lr(vcpu, lr);
>  }
>  
>  static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
>  {
> +	vgic_v2_set_underflow(vcpu);
>  }
>  
>  static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 29b96b9..0db490e 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -22,4 +22,10 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid);
>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
>  
> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
> +void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
> +void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
> +void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
> +void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
> +
>  #endif
> 



From peter.maydell at linaro.org  Tue May 10 07:15:12 2016
From: peter.maydell at linaro.org (Peter Maydell)
Date: Tue, 10 May 2016 15:15:12 +0100
Subject: [PATCH v3 19/55] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <20160510140454.GG27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-20-git-send-email-andre.przywara@arm.com>
 <20160510140454.GG27623@cbox>
Message-ID: <CAFEAcA9U9qqsSJt7RfNJmDutCsYwnaPGfi-sEcnxYYjSm5C8sA@mail.gmail.com>

On 10 May 2016 at 15:04, Christoffer Dall <christoffer.dall at linaro.org> wrote:
> On Fri, May 06, 2016 at 11:45:32AM +0100, Andre Przywara wrote:
>> +     /*
>> +      * Currently all guest IRQs are Group1, as Group0 would result
>> +      * in a FIQ in the guest, which it wouldn't expect.
>
> I still don't like or understand this comment.  This should simply say
> that we're making a gross assumption about all interrupts being group1
> here.

It's not really an assumption so much as it's a missing feature (aka bug):
there's no reason the vGIC shouldn't support group 0 interrupts. We
just get away with only supporting group 1 because Linux guests
happen to only use group 1 interrupts. If/when the vGIC gains support
for group0 interrupts, then it should reset with interrupts configured
in group0 by default.

>> +      * Eventually we want to make this configurable, so we may
>> +      * revisit this in the future.
>> +      */

The only reason to make it configurable is to work around a guest
kernel bug whereby Linux assumes that all interrupts start out
in Group1. Marc sent out a patch earlier today that fixes that bug:
 https://lkml.org/lkml/2016/5/10/297
Depending on how long it takes you to fix this missing vgic feature,
such kernels may all be long-forgotten, in which case you can
get away without the config option :-)

thanks
-- PMM


From arnd at arndb.de  Tue May 10 07:16:22 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 16:16:22 +0200
Subject: [GIT PULL 2/6] i.MX device tree updates for 4.7, with new clocks
In-Reply-To: <1462291086-19925-2-git-send-email-shawnguo@kernel.org>
References: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
 <1462291086-19925-2-git-send-email-shawnguo@kernel.org>
Message-ID: <2576615.2k08M5hHXC@wuerfel>

On Tuesday 03 May 2016 23:58:02 Shawn Guo wrote:
> The i.MX device tree updates with new clocks for 4.7:
>  - Add LCDIF and FlexCAN device support for i.MX7D
>  - New support i.MX7D based Nitrogen7 board from Boundary Devices
>  - Add display support for vf610-colibri board
> 

I've pulled it into the next/late branch, we'll send that on once the
drivers/clk changes are merged.

Thanks,

	Arnd


From lee.jones at linaro.org  Tue May 10 07:16:58 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Tue, 10 May 2016 15:16:58 +0100
Subject: [PATCH 2/5] remoteproc: core: Add rproc OF look-up functions
In-Reply-To: <20160506184842.GE1256@tuxbot>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
 <1462454983-13168-3-git-send-email-lee.jones@linaro.org>
 <20160506184842.GE1256@tuxbot>
Message-ID: <20160510141658.GP19473@dell>

On Fri, 06 May 2016, Bjorn Andersson wrote:

> On Thu 05 May 06:29 PDT 2016, Lee Jones wrote:
> 
> > - of_rproc_byindex(): look-up and obtain a reference to a rproc
> >   		      using the DT phandle "rprocs" and a index.
> > 
> > - of_rproc_byname():  lookup and obtain a reference to a rproc
> >   		      using the DT phandle "rprocs" and "rproc-names".
> > 
> > Signed-off-by: Ludovic Barre <ludovic.barre at st.com>
> > Signed-off-by: Lee Jones <lee.jones at linaro.org>
> > ---
> 
> I like the idea of having these helpers, but we already have
> rproc_get_by_phandle() so these helpers should be built upon that rather
> than adding the additional list.

Since this is a framework consideration, don't you think it would be
better to standardise the phandle name?  This is common practice when
coding at a subsystem level.  Some in use examples include; "clocks",
"power-domains", "mboxes", "dmas", "phys", "resets", "gpios", etc.

Considering the aforementioned examples, I figured "rprocs" would be
suitable.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


From christoffer.dall at linaro.org  Tue May 10 07:18:31 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 10 May 2016 16:18:31 +0200
Subject: [PATCH v3 20/55] KVM: arm/arm64: vgic-new: Implement
 kvm_vgic_vcpu_pending_irq
In-Reply-To: <1462531568-9799-21-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-21-git-send-email-andre.przywara@arm.com>
Message-ID: <20160510141831.GH27623@cbox>

On Fri, May 06, 2016 at 11:45:33AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> Tell KVM whether a particular VCPU has an IRQ that needs handling
> in the guest. This is used to decide whether a VCPU is runnable.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From marc.zyngier at arm.com  Tue May 10 07:17:54 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 15:17:54 +0100
Subject: [PATCH] arm64: dts: r8a7795: Increase the size of GIC-400 mapped
 registers
In-Reply-To: <CAMuHMdV6XOSiSv-mwovnCAMEPsgOc_vEhPPu0aYCgz74EF242g@mail.gmail.com>
References: <1461047395-6532-1-git-send-email-dirk.behme@de.bosch.com>
 <CAMuHMdV6XOSiSv-mwovnCAMEPsgOc_vEhPPu0aYCgz74EF242g@mail.gmail.com>
Message-ID: <5731ED92.6080804@arm.com>

On 10/05/16 14:33, Geert Uytterhoeven wrote:
> CC Marc, lakml
> 
> On Tue, Apr 19, 2016 at 8:29 AM, Dirk Behme <dirk.behme at de.bosch.com> wrote:
>> From: Pooya Keshavarzi <Pooya.Keshavarzi at de.bosch.com>
>>
>> There are some requirements about the GIC-400 memory layout and its
>> mapping if using 64k aligned base addresses like on r8a7795.
>>
>> See e.g.
>>
>> http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=21550029f709072aacf3b9
>>
>> Map the whole memory range instead of only 0x2000. This will fix
>> the issue that some hypervisors, e.g. Xen, fail to handle the
>> interrupts correctly.
>>
>> Signed-off-by: Pooya Keshavarzi <Pooya.Keshavarzi at de.bosch.com>
>> Signed-off-by: Dirk Behme <dirk.behme at de.bosch.com>
> 
> Based on my understanding below
> Acked-by: Geert Uytterhoeven <geert+renesas at glider.be>
> 
>> ---
>> Note: This patch is against renesas-drivers-2016-04-12-v4.6-rc3
>>
>>  arch/arm64/boot/dts/renesas/r8a7795.dtsi | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
>> index 8be9424..d880fd4 100644
>> --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
>> +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
>> @@ -160,9 +160,9 @@
>>                         #address-cells = <0>;
>>                         interrupt-controller;
>>                         reg = <0x0 0xf1010000 0 0x1000>,
>> -                             <0x0 0xf1020000 0 0x2000>,
>> +                             <0x0 0xf1020000 0 0x20000>,
>>                               <0x0 0xf1040000 0 0x20000>,
>> -                             <0x0 0xf1060000 0 0x2000>;
>> +                             <0x0 0xf1060000 0 0x20000>;
>>                         interrupts = <GIC_PPI 9
>>                                         (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
>>                 };
> 
> Region 0:
>     4 KiB-pages 0xf1011000-0xf101ffff are aliased to 0xf1010000-0xf1010fff,
>     but we need the first 4 KiB only.
> 
> Region 1:
>     4 KiB-pages 0xf1021000-0xf102ffff are aliased to 0xf1020000-0xf1020fff,
>     4 KiB-pages 0xf1030000-0xf103ffff are all zeroes, probably due to
>     non-secure mode?

No. This 4kB page only contain a single register (GICC_DIR), which is
WO/RAZ.

> 
> Region 2:
>     4 KiB-pages 0xf1041000-0xf104ffff are aliased to 0xf1040000-0xf1040fff,
>     4 KiB-pages 0xf1050000-0xf105ffff are all zeroes, probably due to
>     non-secure mode?

Neither. The aliases are an unused feature of GIC400 exposing the other
CPUs view of the same registers...

> 
> Region 3:
>     4 KiB-pages 0xf1061000-0xf106ffff are aliased to 0xf1060000-0xf1060fff,
>     4 KiB-pages 0xf1070000-0xf107ffff are all zeroes, probably due to
>     non-secure mode?

Same as region 1.

> 
> Region 2 already had a 128 KiB size before, which allowed to use 8 KiB at
> 0xf104f000.

No. This region (GICH) only needs the first 256 bytes or so. The rest is
either RAZ/WI or useless stuff.

> 
> An 8 KiB size for regions 1 and 3 indeed didn't make much sense, as this
> covered two identical (aliased) 4 KiB pages, instead of two different pages
> at offset 0xf000.

While we're at it, adding a pointer to the documentation (GIC400 and
SBSA) would be tremendously useful, as it'd avoid misinterpreting the
various bits.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From arnd at arndb.de  Tue May 10 07:18:20 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 16:18:20 +0200
Subject: [GIT PULL] ARM: dts: exynos: Devfreq for v4.7
In-Reply-To: <1462367136-28627-1-git-send-email-k.kozlowski@samsung.com>
References: <1462367136-28627-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <4199175.Sym2be3WAj@wuerfel>

On Wednesday 04 May 2016 15:05:36 Krzysztof Kozlowski wrote:
> Topic branch for Device Tree changes adding new generic devfreq driver, for
> v4.7:
> 1. Add bus nodes for Exynos3250, Exynos4x12, Exynos4210 and Exynos542x.
> 2. Split out common PPMU (Performance Monitoring Unit) nodes into separate
>    DTSI. The PPMU provides performance data for devfreq.
> 3. Add NoCP (Network on Chip Probe) node for Exynos542x. On this SoC, like PPMU
>    on older designs, provides performance data for devfreq.
> 4. Enable DFVS (Dynamic Voltage and Frequency Scaling) on boards:
>    - Exynos3250 Rinato,
>    - Exynos4412 Odroid-X/X2/U3 and Trats2,
>    - Exynos5422 Odroid XU3/XU3-Lite/XU4.
> 
> 

Merged into next/late now, so we can track the clk dependency more easily.

Thanks,

	Arnd


From marc.zyngier at arm.com  Tue May 10 07:22:20 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 15:22:20 +0100
Subject: [PATCH v3 19/55] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <CAFEAcA9U9qqsSJt7RfNJmDutCsYwnaPGfi-sEcnxYYjSm5C8sA@mail.gmail.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-20-git-send-email-andre.przywara@arm.com>
 <20160510140454.GG27623@cbox>
 <CAFEAcA9U9qqsSJt7RfNJmDutCsYwnaPGfi-sEcnxYYjSm5C8sA@mail.gmail.com>
Message-ID: <5731EE9C.5000201@arm.com>

On 10/05/16 15:15, Peter Maydell wrote:
> On 10 May 2016 at 15:04, Christoffer Dall <christoffer.dall at linaro.org> wrote:
>> On Fri, May 06, 2016 at 11:45:32AM +0100, Andre Przywara wrote:
>>> +     /*
>>> +      * Currently all guest IRQs are Group1, as Group0 would result
>>> +      * in a FIQ in the guest, which it wouldn't expect.
>>
>> I still don't like or understand this comment.  This should simply say
>> that we're making a gross assumption about all interrupts being group1
>> here.
> 
> It's not really an assumption so much as it's a missing feature (aka bug):
> there's no reason the vGIC shouldn't support group 0 interrupts. We
> just get away with only supporting group 1 because Linux guests
> happen to only use group 1 interrupts. If/when the vGIC gains support
> for group0 interrupts, then it should reset with interrupts configured
> in group0 by default.
> 
>>> +      * Eventually we want to make this configurable, so we may
>>> +      * revisit this in the future.
>>> +      */
> 
> The only reason to make it configurable is to work around a guest
> kernel bug whereby Linux assumes that all interrupts start out
> in Group1. Marc sent out a patch earlier today that fixes that bug:
>  https://lkml.org/lkml/2016/5/10/297
> Depending on how long it takes you to fix this missing vgic feature,
> such kernels may all be long-forgotten, in which case you can
> get away without the config option :-)

I've CC'd stable for this particular patch, so hopefully we won't have
to make it configurable as people will diligently update their
kernels... I also have a patch for handling both groups in KVM, but I'll
hold onto it until we have something we agree on for the bulk of the code.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From dinguyen at kernel.org  Tue May 10 07:25:21 2016
From: dinguyen at kernel.org (Dinh Nguyen)
Date: Tue, 10 May 2016 09:25:21 -0500
Subject: [GIT PULL] SoCFPGA update for v4.7
Message-ID: <1462890321-13569-1-git-send-email-dinguyen@kernel.org>

Hi Arnd, Kevin, Olof:

Please pull in this update for v4.7. I aplogize for the lateness of this PR,
but this patch is dependent on a fix that went in on v4.6-rc7.

That fix is "2882f7637075 ARM: SoCFPGA: simplify secondary trampoline".

Thanks,
Dinh

The following changes since commit 44549e8f5eea4e0a41b487b63e616cb089922b99:

  Linux 4.6-rc7 (2016-05-08 14:38:32 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git socfpga_updates_for_v4.7

for you to fetch changes up to 2882f7637075f876342a6378074d2911cac2fee2:

  ARM: SoCFPGA: simplify secondary trampoline (2016-05-09 13:45:20 -0500)

----------------------------------------------------------------
SoCFPGA updates for v4.7
- Simplify secondary trampoline SMP code

----------------------------------------------------------------
Sascha Hauer (1):
      ARM: SoCFPGA: simplify secondary trampoline

 arch/arm/mach-socfpga/core.h    |  4 ++--
 arch/arm/mach-socfpga/headsmp.S | 27 +++++++---------------
 arch/arm/mach-socfpga/platsmp.c | 51 +++++++++++++++++++----------------------
 arch/arm/mach-socfpga/socfpga.c |  9 --------
 4 files changed, 33 insertions(+), 58 deletions(-)


From richard.genoud at gmail.com  Tue May 10 07:25:25 2016
From: richard.genoud at gmail.com (Richard Genoud)
Date: Tue, 10 May 2016 16:25:25 +0200
Subject: [BISECTED] Regression v4.6-rc1 : nanosleep doesn't return on
 AT91SAM9
In-Reply-To: <CACQ1gAg6cKqjaqcV70m2VS5R4_kZEgWTiqzSqDxSjvfrYYxbzg@mail.gmail.com>
References: <CACQ1gAg6cKqjaqcV70m2VS5R4_kZEgWTiqzSqDxSjvfrYYxbzg@mail.gmail.com>
Message-ID: <CACQ1gAipruXcO=xpooYDOdqZbtESD35wxDf7xNrg4zuuRv1wew@mail.gmail.com>

2016-05-10 15:58 GMT+02:00 Richard Genoud <richard.genoud at gmail.com>:
> Hi,
>
> Starting with 4.6-rc1, a sleep 1 doesn't return :
>
> execve("/bin/sleep", ["sleep", "1"], ["USER=root", "SHLVL=1",
> "OLDPWD=/var", "HOME=/", "TERM=vt102",
> "PATH=/sbin:/usr/sbin:/bin:/usr/bin", "SHELL=/bin/sh", "PWD=/"]) = 0
> uname({sysname="Linux", nodename="LNS",
> release="4.5.0-09406-g46e595a17dcf", version="#72 Tue May 10 15:41:34
> CEST 2016", machine="armv5tejl", domainname="(none)"}) = 0
> brk(0)                                  = 0x153000
> brk(0x153d20)                           = 0x153d20
> set_tls(0x1534c0, 0x14d1e4, 0, 0x153d20, 0x14e368) = 0
> readlink("/proc/self/exe", "/bin/busybox", 4096) = 12
> brk(0x174d20)                           = 0x174d20
> brk(0x175000)                           = 0x175000
> getuid32()                              = 0
> rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
> rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
> rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
> nanosleep({1, 0},
>
> And the heartbeat led doesn't blink anymore (full on), as if the
> timers never fire.
>
> The platform is an AT91SAM9G35-CM.
>
> git bisect gives a merge as the 1st bad commit :(
> first bad commit: [46e595a17dcf11404f713845ecb5b06b92a94e43] Merge tag
> 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc


I went a little further in tracking that down, starting from the merge
(1st bad commit) and reverting some commits.
It seems that the culprit is :
commit 863a81c3be1d931bdae6426e231add9334311f13
Author: Boris Brezillon <boris.brezillon at free-electrons.com>
Date:   Fri Sep 5 09:54:13 2014 +0200
    clk: at91: make use of syscon to share PMC registers in several drivers

Here are the commits I've reverted :

git log --oneline --decorate -20
849cdaa0cf04 (HEAD, tag: good) Revert "clk: at91: make use of syscon
to share PMC registers in several drivers"
4bd6dde95321 (tag: last_bad) Revert "clk: at91: make use of
syscon/regmap internally"
a56dacaa24c4 (tag: always_bad) Revert "clk: at91: remove IRQ handling
and use polling"
33edfe7a2de6 Revert "clk: at91: pmc: merge at91_pmc_init in atmel_pmc_probe"
0b22bb649eae Revert "clk: at91: pmc: move pmc structures to C file"
14994fdff366 Revert "ARM: at91: pm: simply call at91_pm_init"
6f0821175327 (tag: still_bad) Revert "ARM: at91: pm: find and remap the pmc"
b52bbf7fad1b Revert "ARM: at91: pm: move idle functions to pm.c"
dffb1a5f68b9 Revert "ARM: at91: remove useless includes and function prototypes"
db352691dcc1 Revert "usb: gadget: atmel: access the PMC using regmap"
f7b5433dbbc8 Revert "clk: at91: pmc: drop at91_pmc_base"
6e6dfc0d91c0 Revert "clk: at91: pmc: remove useless capacities handling"
ceddd3f88ada Revert "clk: at91: remove useless includes"
46e595a17dcf (tag: bad) Merge tag 'armsoc-drivers' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
e3b1f64e04f5 Merge tag 'armsoc-defconfig' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
915c56bc01d6 Merge tag 'armsoc-dt64' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
5a6b7e53d035 Merge tag 'armsoc-dt' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
8c6d4082fc6a Merge tag 'armsoc-arm64' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
33b3d2e88c9e Merge tag 'armsoc-soc' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
e88fa1b8b00a Merge tag 'armsoc-cleanup' of
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc


From k.kozlowski at samsung.com  Tue May 10 07:30:54 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 16:30:54 +0200
Subject: [PATCH] arm64: exynos: Select SOC specific drivers
Message-ID: <1462890654-8787-1-git-send-email-k.kozlowski@samsung.com>

Recently some Exynos drivers were moved from arm/mach-exynos to
drivers/soc. Building the directory depends on SOC_SAMSUNG Kconfig
option so we want it also on ARMv8 platforms, even though none of the
drivers support ARMv8 SoCs.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm64/Kconfig.platforms | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 54967ffd14c1..735eed65ee0a 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -35,6 +35,7 @@ config ARCH_EXYNOS
 	select HAVE_S3C_RTC if RTC_CLASS
 	select PINCTRL
 	select PINCTRL_EXYNOS
+	select SOC_SAMSUNG
 	help
 	  This enables support for ARMv8 based Samsung Exynos SoC family.
 
-- 
1.9.1



From k.kozlowski at samsung.com  Tue May 10 07:31:26 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 16:31:26 +0200
Subject: [PATCH] soc: samsung: pm_domains: Enable COMPILE_TEST for build
 coverage
Message-ID: <1462890686-8843-1-git-send-email-k.kozlowski@samsung.com>

Introduce a platform selectable symbol EXYNOS_PM_DOMAINS which can be
also toggled on by COMPILE_TEST for some build coverage.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm/mach-exynos/Kconfig | 1 +
 drivers/soc/samsung/Kconfig  | 4 ++++
 drivers/soc/samsung/Makefile | 2 +-
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index e65aa7d11b20..58b334f5f1d6 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -19,6 +19,7 @@ menuconfig ARCH_EXYNOS
 	select EXYNOS_THERMAL
 	select EXYNOS_PMU
 	select EXYNOS_SROM
+	select EXYNOS_PM_DOMAINS if PM_GENERIC_DOMAINS
 	select HAVE_ARM_SCU if SMP
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
index d7fc123006a3..245533907d1b 100644
--- a/drivers/soc/samsung/Kconfig
+++ b/drivers/soc/samsung/Kconfig
@@ -10,4 +10,8 @@ config EXYNOS_PMU
 	bool "Exynos PMU controller driver" if COMPILE_TEST
 	depends on (ARM && ARCH_EXYNOS) || ((ARM || ARM64) && COMPILE_TEST)
 
+config EXYNOS_PM_DOMAINS
+	bool "Exynos PM domains" if COMPILE_TEST
+	depends on PM_GENERIC_DOMAINS || COMPILE_TEST
+
 endif
diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
index 8acba2bbbd78..e60f173c503a 100644
--- a/drivers/soc/samsung/Makefile
+++ b/drivers/soc/samsung/Makefile
@@ -1,3 +1,3 @@
-obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
+obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o
 obj-$(CONFIG_EXYNOS_PMU)	+= exynos-pmu.o exynos3250-pmu.o exynos4-pmu.o \
 					exynos5250-pmu.o exynos5420-pmu.o
-- 
1.9.1



From mark.rutland at arm.com  Tue May 10 07:31:57 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 10 May 2016 15:31:57 +0100
Subject: [PATCH] arm64: kgdb: Match pstate size with gdbserver protocol
In-Reply-To: <df946c87-162f-fdda-879b-76b4ad1a1c7a@linaro.org>
References: <1462815566-15086-1-git-send-email-daniel.thompson@linaro.org>
 <20160510104511.GH687@leverpostej>
 <df946c87-162f-fdda-879b-76b4ad1a1c7a@linaro.org>
Message-ID: <20160510143156.GB10785@leverpostej>

On Tue, May 10, 2016 at 02:41:54PM +0100, Daniel Thompson wrote:
> On 10/05/16 11:45, Mark Rutland wrote:
> >>When commit 44679a4f142b ("arm64: KGDB: Add step debugging support") was
> >>introduced it was paired with a gdb patch that made an incompatible
> >>change to the gdbserver protocol. This patch was eventually merged into
> >>the gdb sources:
> >>https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=a4d9ba85ec5597a6a556afe26b712e878374b9dd
> >>
> >>The change to the protocol was mostly made to simplify big-endian support
> >>inside the kernel gdb stub.
> >
> >While that was how we discovered the inconsistency, a major concern is
> >that SPSR_EL* (i.e. PSTATE), as accessed by MRS/MSR is a 64-bit
> >quantity, even if the upper 32 bits are RES0 today.
> >
> >It is conceivable that the upper 32 bits could be used in future (as
> >happened with CLIDR_EL1), and for this reason we expose those upper 32
> >bits from the kernel, and treat system registers as 64-bit quantities
> >generally.
> 
> These cases are not exactly the same.
> 
> CLIDR_ELx is (or was) architecturally defined as a 64-bit register
> and explicitly marks the upper 32-bits as RES0.
> 
> That is not the case for SPSR_ELx; this register is architecturally
> defined to be 32-bit.

The below doesn't necessarily change your subsequent argument, but that
isn't quite true.

The two cases are in fact identical if you dig into the history a bit
further. Take a look in an earlier revision of the ARM ARM (e.g. ARM DDI
0487A.b), where it was explicitly stated:

	Attributes
		CLIDR_EL1 is a 32-bit register.

This was subsequently upgraded to 64-bit with the addition of ICB.

Based on this, my PoV is that any register that the ARM ARM describes as
"a 32-bit register" is a 64-bit register for which the upper 32 bits are
RES0.

> I know that doesn't *prevent* SPSR_ELx from being expanded in the
> future it is not unreasonable for gdb to design its wire protocol
> based on the description found in the architecture manual.
> 
> >So this was also about ensuring the interface was consistent and to some
> >extent future-proof.
> 
> gdb remote protocol is already future proof and has never at any
> point contradicted the architecture.
> 
> However the changes to the protocol in 7.7.x and 7.8.0 were
> analogous to an unexpected ABI change rather than a carefully
> controlled introduction of a new feature. Like the kernel, once
> detected, they were reversed ;-) .

To be clear, I don't disagree with this. The ARM ARM is at best
amigibious w.r.t. what it means by "a 32-bit register", and that's the
only point of contention.

However, we should make note of the above as a key point of rationale,
as it affects other decisions we make in this area.

Thanks,
Mark.


From andre.przywara at arm.com  Tue May 10 07:35:06 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue, 10 May 2016 15:35:06 +0100
Subject: [PATCH v3a] KVM: arm/arm64: pmu: abstract access to number of SPIs
In-Reply-To: <5731AF57.2040707@linaro.org>
References: <5731AF57.2040707@linaro.org>
Message-ID: <1462890906-6134-1-git-send-email-andre.przywara@arm.com>

Currently the PMU uses a member of the struct vgic_dist directly,
which not only breaks abstraction, but will fail with the new VGIC.
Abstract this access in the VGIC header file.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Hi Eric, Marc,

as this if-statement was quite confusing (it wasn't even the negation
that was wrong), I rewrote it a bit to be more readable.
This one works now with PPIs (after fixing kvmtool).

Does that make sense?

Cheers,
Andre.

 include/kvm/arm_vgic.h |  2 ++
 virt/kvm/arm/pmu.c     | 19 +++++++++++--------
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 6a98e05..d406f8e 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -351,6 +351,8 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
 #define vgic_ready(k)		((k)->arch.vgic.ready)
+#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
+				 ((i) < (k)->arch.vgic.nr_irqs))
 
 int vgic_v2_probe(struct device_node *vgic_node,
 		  const struct vgic_ops **ops,
diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
index 575c7aa..6ab9d6b 100644
--- a/virt/kvm/arm/pmu.c
+++ b/virt/kvm/arm/pmu.c
@@ -436,6 +436,11 @@ static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
+/*
+ * For one VM the interrupt type must be same for each vcpu.
+ * As a PPI, the interrupt number is the same for all vcpus,
+ * while as an SPI it must be a separate number per vcpu.
+ */
 static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
 {
 	int i;
@@ -457,6 +462,7 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
 	return true;
 }
 
+#define irq_is_ppi(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS)
 
 int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 {
@@ -471,14 +477,11 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 		if (get_user(irq, uaddr))
 			return -EFAULT;
 
-		/*
-		 * The PMU overflow interrupt could be a PPI or SPI, but for one
-		 * VM the interrupt type must be same for each vcpu. As a PPI,
-		 * the interrupt number is the same for all vcpus, while as an
-		 * SPI it must be a separate number per vcpu.
-		 */
-		if (irq < VGIC_NR_SGIS || irq >= vcpu->kvm->arch.vgic.nr_irqs ||
-		    !irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
+		/* The PMU overflow interrupt can be a PPI or a valid SPI. */
+		if (!(irq_is_ppi(irq) || vgic_valid_spi(vcpu->kvm, irq)))
+			return -EINVAL;
+
+		if (!irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
 			return -EINVAL;
 
 		if (kvm_arm_pmu_irq_initialized(vcpu))
-- 
2.7.3



From Tirumalesh.Chalamarla at cavium.com  Tue May 10 07:35:02 2016
From: Tirumalesh.Chalamarla at cavium.com (Chalamarla, Tirumalesh)
Date: Tue, 10 May 2016 14:35:02 +0000
Subject: [PATCH v9 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part
 2/3: msi changes
In-Reply-To: <57318F20.4010103@linaro.org>
References: <1462375094-2390-1-git-send-email-eric.auger@linaro.org>
 <9C17BA6B-7304-47CA-A287-77FB41D96AD3@caviumnetworks.com>
 <573040D6.9050803@linaro.org>
 <50F1DA1B-3760-474F-A401-43AA26A5F6B6@caviumnetworks.com>
 <57318F20.4010103@linaro.org>
Message-ID: <FACC8B34-C91A-4F24-88DC-0FE23E368227@caviumnetworks.com>






On 5/10/16, 12:34 AM, "Eric Auger" <eric.auger at linaro.org> wrote:

>Hi Chalamarla,
>> On 5/9/16, 12:48 AM, "Eric Auger" <eric.auger at linaro.org> wrote:
>> 
>>> Hi Chalarmala,
>>> On 05/05/2016 07:44 PM, Chalamarla, Tirumalesh wrote:
>>>> Hi Eric,
>>>>
>>>> Does this series supports gicv3-its emulation?
>>>> Do we have a tree with all the dependent patches
>>> GICv3 ITS emulation support comes with:
>>> [PATCH v4 00/12] KVM: arm64: GICv3 ITS emulation
>>> http://permalink.gmane.org/gmane.comp.emulators.kvm.arm.devel/5738
>>>
>>> My series just allows PCI device MSI transactions to reach the host MSI
>>> frame through the SMMU. Only host GICv2m has been tested at the moment
>>> with a guest exposed with a GICv2m too.
>> 
>> 
>> I wanted to test this series on Cavium Thunder, but the only mode supported is Gicv3 with ITS, is there a chance 
>> That I get a tree with all the dependencies?
>I can prepare a kernel tree with all the dependencies including ITS
>patches supporting get_doorbell_info.
>
>Then on userspace side:
>- do you plan to use QEMU?
>- then can you expose your guest with a GICv3 + v2m? I think this should
>work.
>
>exposing ITS to the guest requires a respin of Pavel's series:
>[Qemu-devel] [RFC PATCH v3 0/5] vITS support
>(https://lists.gnu.org/archive/html/qemu-devel/2015-11/msg05197.html)
>and has more complex kernel dependencies.
>
>I think exposing the guest with GICv3 + v2m should work

Will try both. We have a qemu with that patches will try once the kernel tree is ready.

Thanks,
Tirumalesh.
>
>Best Regards
>
>Eric
>>>> Thanks,
>>>> Tirumalesh. 
>>>> On 5/4/16, 8:18 AM, "linux-arm-kernel on behalf of Eric Auger" <linux-arm-kernel-bounces at lists.infradead.org on behalf of eric.auger at linaro.org> wrote:
>>>>
>>>>> This series implements the MSI address mapping/unmapping in the MSI layer.
>>>>> IOMMU binding happens on pci_enable_msi since this function can sleep and
>>>>> return errors. On msi_domain_set_affinity, msi_domain_(de)activate, which
>>>>> are not allowed to sleep, we simply look for the already existing binding.
>>>>>
>>>>> A new MSI domain info flag value is introduced to report whether the msi
>>>>> domain implements IRQ remapping. GIC v3 ITS is the first MSI controller
>>>>> advertising it. This flag value will be used by VFIO subsystem to
>>>>> determine whether MSI forwarding is safe.
>>>>>
>>>>> More details & context can be found at:
>>>>> http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/
>>>>>
>>>>> Best Regards
>>>>>
>>>>> Eric
>>>>>
>>>>> Applies on top of PART 1/3. Also depends on
>>>>> [PATCH 1/3] iommu: Add MMIO mapping type,
>>>>> http://comments.gmane.org/gmane.linux.kernel.iommu/12869
>>>>>
>>>>> Git: complete series available at
>>>>> https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc6-pcie-passthrough-v9-msi-v9
>>>>>
>>>>> This branch contains all parts in v9.
>>>>>
>>>>> History:
>>>>>
>>>>> v8 -> v9:
>>>>> - use a union in irq_chip_msi_doorbell_info + boolean telling whether the
>>>>>  doorbell is percpu
>>>>> - decouple irq_data parsing from the actual mapping/unmapping in
>>>>>  msi_handle_doorbell_mappings
>>>>> - fix misc style issues
>>>>>
>>>>> v7 -> v8:
>>>>> take into account Marc's comments:
>>>>> - use iommu_msi_msg_pa_to_va with new proto
>>>>> - change in irq_chip_msi_doorbell_info struct definition:
>>>>>  prot and size became shared between all doorbells and phys_addr_t __percpu
>>>>> - cleanups in v2m irqchip
>>>>> - eventually did not touch MSI_FLAG_IRQ_REMAPPING naming
>>>>> - On msi_handle_doorbell_mappings, stop on the first irqchip where doorbells
>>>>>  can be found
>>>>> - fix resource deallocation on mapping failure in msi_domain_alloc_irqs
>>>>>
>>>>> v6 -> v7:
>>>>> - do alloc/map handling on pci_enable_msi and search on msi_(de)domain_activate
>>>>> - add msi_doorbell_info callback in irq-chip to retrieve the characteristics
>>>>>  of doorbells
>>>>>
>>>>> RFC v5 -> patch v6:
>>>>> - split to ease the review process
>>>>> - rebase on default iommu domain code (irq_data_to_msi_mapping_domain
>>>>>  checks IOMMU_DOMAIN_DMA type)
>>>>> - fix unmap sequence on msi_domain_set_affinity (reported by Marc):
>>>>>  unmap the previous doorbell when the new one has been mapped & written to
>>>>>  the device, ie. irq_chip_write_msi_msg.
>>>>> - "msi: msi_compose wrapper removed" following change above
>>>>> - add size parameter to iommu_get_reserved_iova API following Marc's request
>>>>>
>>>>> RFC v4 -> RFC v5:
>>>>> - take into account Thomas' comments on MSI related patches
>>>>>  - split "msi: IOMMU map the doorbell address when needed"
>>>>>  - increase readability and add comments
>>>>>  - fix style issues
>>>>> - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
>>>>> - platform ITS now advertises IOMMU_CAP_INTR_REMAP
>>>>> - fix compilation issue with CONFIG_IOMMU API unset
>>>>> - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING
>>>>>
>>>>> RFC v3 -> v4:
>>>>> - Move doorbell mapping/unmapping in msi.c
>>>>> - fix ref count issue on set_affinity: in case of a change in the address
>>>>>  the previous address is decremented
>>>>> - doorbell map/unmap now is done on msi composition. Should allow the use
>>>>>  case for platform MSI controllers
>>>>> - create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
>>>>>  to reserved IOVA management (looking like dma-iommu glue)
>>>>> - series reordering to ease the review:
>>>>>  - first part is related to IOMMU
>>>>>  - second related to MSI sub-system
>>>>>  - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
>>>>> - expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
>>>>>  [this partially addresses Marc's comments on iommu_get/put_single_reserved
>>>>>   size/alignment problematic - which I did not ignore - but I don't know
>>>>>   how much I can do at the moment]
>>>>>
>>>>> RFC v2 -> RFC v3:
>>>>> - should fix wrong handling of some CONFIG combinations:
>>>>>  CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
>>>>> - fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)
>>>>>
>>>>> PATCH v1 -> RFC v2:
>>>>> - reverted to RFC since it looks more reasonable ;-) the code is split
>>>>>  between VFIO, IOMMU, MSI controller and I am not sure I did the right
>>>>>  choices. Also API need to be further discussed.
>>>>> - iova API usage in arm-smmu.c.
>>>>> - MSI controller natively programs the MSI addr with either the PA or IOVA.
>>>>>  This is not done anymore in vfio-pci driver as suggested by Alex.
>>>>> - check irq remapping capability of the group
>>>>>
>>>>> RFC v1 [2] -> PATCH v1:
>>>>> - use the existing dma map/unmap ioctl interface with a flag to register a
>>>>>  reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
>>>>> - a single reserved IOVA contiguous region now is allowed
>>>>> - use of an RB tree indexed by PA to store allocated reserved slots
>>>>> - use of a vfio_domain iova_domain to manage iova allocation within the
>>>>>  window provided by the userspace
>>>>> - vfio alloc_map/unmap_free take a vfio_group handle
>>>>> - vfio_group handle is cached in vfio_pci_device
>>>>> - add ref counting to bindings
>>>>> - user modality enabled at the end of the series
>>>>>
>>>>>
>>>>> Eric Auger (8):
>>>>>  genirq/msi: Add a new MSI_FLAG_IRQ_REMAPPING flag
>>>>>  irqchip/gic-v3-its: ITS advertises MSI_FLAG_IRQ_REMAPPING
>>>>>  genirq/msi: export msi_get_domain_info
>>>>>  genirq/msi: msi_compose wrapper
>>>>>  genirq/irq: introduce msi_doorbell_info
>>>>>  irqchip/gicv2m: implement msi_doorbell_info callback
>>>>>  genirq/msi: map/unmap the MSI doorbells on msi_domain_alloc/free_irqs
>>>>>  genirq/msi: use the MSI doorbell's IOVA when requested
>>>>>
>>>>> drivers/irqchip/irq-gic-v2m.c                 |  16 +++
>>>>> drivers/irqchip/irq-gic-v3-its-pci-msi.c      |   3 +-
>>>>> drivers/irqchip/irq-gic-v3-its-platform-msi.c |   3 +-
>>>>> include/linux/irq.h                           |  15 ++-
>>>>> include/linux/msi.h                           |   2 +
>>>>> kernel/irq/msi.c                              | 136 +++++++++++++++++++++++---
>>>>> 6 files changed, 161 insertions(+), 14 deletions(-)
>>>>>
>>>>> -- 
>>>>> 1.9.1
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> linux-arm-kernel mailing list
>>>>> linux-arm-kernel at lists.infradead.org
>>>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>
>

From marc.zyngier at arm.com  Tue May 10 07:35:02 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 15:35:02 +0100
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <20160510141119.GB20499@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
 <20160510133043.GF27623@cbox> <5731E52A.9000402@arm.com>
 <20160510141119.GB20499@cbox>
Message-ID: <5731F196.4040906@arm.com>

On 10/05/16 15:11, Christoffer Dall wrote:
> On Tue, May 10, 2016 at 02:42:02PM +0100, Marc Zyngier wrote:
>> On 10/05/16 14:30, Christoffer Dall wrote:
>>> On Fri, May 06, 2016 at 11:45:31AM +0100, Andre Przywara wrote:
>>>> From: Marc Zyngier <marc.zyngier at arm.com>
>>>>
>>>> Processing maintenance interrupts and accessing the list registers
>>>> are dependent on the host's GIC version.
>>>> Introduce vgic-v2.c to contain GICv2 specific functions.
>>>> Implement the GICv2 specific code for syncing the emulation state
>>>> into the VGIC registers.
>>>>
>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>> ---
>>>> Changelog RFC..v1:
>>>> - remove explicit LR_STATE clearing on maintenance interrupt handling
>>>> - improve documentation for vgic_v2_populate_lr()
>>>> - remove WARN_ON on non-edge IRQs in maintenance interrupts
>>>> - simplify multi-CPU source SGI handling
>>>>
>>>> Changelog v1 .. v2:
>>>> - inject the IRQ priority into the list register
>>>>
>>>> Changelog v2 .. v3:
>>>> - cleanup diff containing rebase artifacts
>>>>
>>>>  include/linux/irqchip/arm-gic.h |   1 +
>>>>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
>>>>  virt/kvm/arm/vgic/vgic.c        |   6 ++
>>>>  virt/kvm/arm/vgic/vgic.h        |   6 ++
>>>>  4 files changed, 191 insertions(+)
>>>>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
>>>>
>>>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>>>> index 9c94026..be0d26f 100644
>>>> --- a/include/linux/irqchip/arm-gic.h
>>>> +++ b/include/linux/irqchip/arm-gic.h
>>>> @@ -76,6 +76,7 @@
>>>>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
>>>>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
>>>>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
>>>> +#define GICH_LR_PRIORITY_SHIFT		23
>>>>  #define GICH_LR_STATE			(3 << 28)
>>>>  #define GICH_LR_PENDING_BIT		(1 << 28)
>>>>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
>>>> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
>>>> new file mode 100644
>>>> index 0000000..4cee616
>>>> --- /dev/null
>>>> +++ b/virt/kvm/arm/vgic/vgic-v2.c
>>>> @@ -0,0 +1,178 @@
>>>> +/*
>>>> + * Copyright (C) 2015, 2016 ARM 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.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * 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/irqchip/arm-gic.h>
>>>> +#include <linux/kvm.h>
>>>> +#include <linux/kvm_host.h>
>>>> +
>>>> +#include "vgic.h"
>>>> +
>>>> +/*
>>>> + * Call this function to convert a u64 value to an unsigned long * bitmask
>>>> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
>>>> + *
>>>> + * Warning: Calling this function may modify *val.
>>>> + */
>>>> +static unsigned long *u64_to_bitmask(u64 *val)
>>>> +{
>>>> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
>>>> +	*val = (*val >> 32) | (*val << 32);
>>>> +#endif
>>>> +	return (unsigned long *)val;
>>>> +}
>>>> +
>>>> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
>>>> +{
>>>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>>>> +
>>>> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
>>>> +		u64 eisr = cpuif->vgic_eisr;
>>>> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
>>>> +		int lr;
>>>> +
>>>> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
>>>> +			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
>>>> +
>>>> +			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
>>>> +
>>>> +			kvm_notify_acked_irq(vcpu->kvm, 0,
>>>> +					     intid - VGIC_NR_PRIVATE_IRQS);
>>>> +
>>>
>>> why do we need to do this?  I cannot find any consumers of this info
>>> after we've left the hyp code.
>>
>> I believe that's for vhost and irqfd. Or am I misreading your question?
>>
> 
> I meant the setting of the bits in vgic_elrsr (sorry, badly placed
> comment)...
> 
>>> Also, I think I offered a comment about why we would potentially need
>>> this in the first place.  This is the famous race where hardware doesn't
>>> guarantee consistency between the MISR and ELRSR right?
>>
>> That's the one (except it is between EISR and ELRSR). I don't have your
>> initial comment at hand, but would something like the following do?
>>
>> 			/*
>> 			 * The maintenance interrupt may not have had a
>> 			 * chance to update ELRSR, so let's mark the LRs
>> 			 * presents in EISR as empty.
>> 			 */
>>>
>>>> +			cpuif->vgic_elrsr |= 1ULL << lr;
> 
> so, why are we doing this?

Ah! I finally see what you mean: we don't reuse LRs at all with the new code
base, so knowing which LR is empty is irrelevant. In which case, something
like that should be done:

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index e88b5aa..5a8f4d4 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -52,8 +52,6 @@ void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
 
 			kvm_notify_acked_irq(vcpu->kvm, 0,
 					     intid - VGIC_NR_PRIVATE_IRQS);
-
-			cpuif->vgic_elrsr |= 1ULL << lr;
 		}
 	}
 
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 53f7847..4102f0f 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -43,8 +43,6 @@ void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
 
 			kvm_notify_acked_irq(vcpu->kvm, 0,
 					     intid - VGIC_NR_PRIVATE_IRQS);
-
-			cpuif->vgic_elrsr |= 1ULL << lr;
 		}
 
 		/*

I'll give it a spin, just to be safe.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From thierry.reding at gmail.com  Tue May 10 07:40:24 2016
From: thierry.reding at gmail.com (Thierry Reding)
Date: Tue, 10 May 2016 16:40:24 +0200
Subject: [PATCH RESEND 2/3] pwm: kona: Add support for Broadcom iproc pwm
 controller
In-Reply-To: <1459261350-23851-3-git-send-email-yendapally.reddy@broadcom.com>
References: <1459261350-23851-1-git-send-email-yendapally.reddy@broadcom.com>
 <1459261350-23851-3-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <20160510144024.GA7149@ulmo.ba.sec>

On Tue, Mar 29, 2016 at 10:22:29AM -0400, Yendapally Reddy Dhananjaya Reddy wrote:
> Update the kona driver to support Broadcom iproc pwm controller
> 
> Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
> ---
>  drivers/pwm/Kconfig        |   6 +-
>  drivers/pwm/pwm-bcm-kona.c | 183 +++++++++++++++++++++++++++++++++++++++------
>  2 files changed, 163 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index c182efc..e45ea33 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -76,9 +76,11 @@ config PWM_ATMEL_TCB
>  
>  config PWM_BCM_KONA
>  	tristate "Kona PWM support"
> -	depends on ARCH_BCM_MOBILE
> +	depends on ARCH_BCM_MOBILE || ARCH_BCM_IPROC
> +	default ARCH_BCM_IPROC

Why the default? Typically you'd enable this in one or more of the
default configurations. default ARCH_* is really only useful if the
driver is essential. PWM doesn't usually fall into this category.

> diff --git a/drivers/pwm/pwm-bcm-kona.c b/drivers/pwm/pwm-bcm-kona.c
> index c634183..ef152e3a 100644
> --- a/drivers/pwm/pwm-bcm-kona.c
> +++ b/drivers/pwm/pwm-bcm-kona.c
> @@ -19,6 +19,7 @@
>  #include <linux/math64.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
> +#include <linux/of_device.h>
>  #include <linux/platform_device.h>
>  #include <linux/pwm.h>
>  #include <linux/slab.h>
> @@ -47,30 +48,90 @@
>  
>  #define PWM_CONTROL_OFFSET			(0x00000000)
>  #define PWM_CONTROL_SMOOTH_SHIFT(chan)		(24 + (chan))
> -#define PWM_CONTROL_TYPE_SHIFT(chan)		(16 + (chan))
> +#define PWM_CONTROL_TYPE_SHIFT(shift, chan)	(shift + chan)

You need to put the parameters into parentheses to avoid expansion from
potentially messing up the expression.

>  #define PWM_CONTROL_POLARITY_SHIFT(chan)	(8 + (chan))
>  #define PWM_CONTROL_TRIGGER_SHIFT(chan)		(chan)
>  
>  #define PRESCALE_OFFSET				(0x00000004)
> -#define PRESCALE_SHIFT(chan)			((chan) << 2)
> -#define PRESCALE_MASK(chan)			(0x7 << PRESCALE_SHIFT(chan))
> +#define PRESCALE_SHIFT				(0x00000004)
> +#define PRESCALE_MASK				(0x00000007)

Hmm... this looks odd. Why are you dropping the chan parameter here?

>  #define PRESCALE_MIN				(0x00000000)
>  #define PRESCALE_MAX				(0x00000007)
>  
> -#define PERIOD_COUNT_OFFSET(chan)		(0x00000008 + ((chan) << 3))
> +#define PERIOD_COUNT_OFFSET(offset, chan)	(offset + (chan << 3))

Need parentheses here as well.

>  #define PERIOD_COUNT_MIN			(0x00000002)
>  #define PERIOD_COUNT_MAX			(0x00ffffff)
> +#define KONA_PERIOD_COUNT_OFFSET		(0x00000008)
>  
> -#define DUTY_CYCLE_HIGH_OFFSET(chan)		(0x0000000c + ((chan) << 3))
> +#define DUTY_CYCLE_HIGH_OFFSET(offset, chan)	(offset + (chan << 3))
>  #define DUTY_CYCLE_HIGH_MIN			(0x00000000)
>  #define DUTY_CYCLE_HIGH_MAX			(0x00ffffff)
> +#define KONA_DUTY_CYCLE_HIGH_OFFSET		(0x0000000c)
> +
> +#define PWM_CHANNEL_CNT				(0x00000006)
> +#define SIGNAL_PUSH_PULL			(0x00000001)
> +#define PWMOUT_TYPE_SHIFT			(0x00000010)
> +
> +#define IPROC_PRESCALE_OFFSET			(0x00000024)
> +#define IPROC_PRESCALE_SHIFT			(0x00000006)
> +#define IPROC_PRESCALE_MAX			(0x0000003f)
> +
> +#define IPROC_PERIOD_COUNT_OFFSET		(0x00000004)
> +#define IPROC_PERIOD_COUNT_MIN			(0x00000002)
> +#define IPROC_PERIOD_COUNT_MAX			(0x0000ffff)
> +
> +#define IPROC_DUTY_CYCLE_HIGH_OFFSET		(0x00000008)
> +#define IPROC_DUTY_CYCLE_HIGH_MIN		(0x00000000)
> +#define IPROC_DUTY_CYCLE_HIGH_MAX		(0x0000ffff)
> +
> +#define IPROC_PWM_CHANNEL_CNT			(0x00000004)
> +#define IPROC_SIGNAL_PUSH_PULL			(0x00000000)
> +#define IPROC_PWMOUT_TYPE_SHIFT			(0x0000000f)
> +
> +/*
> + * pwm controller reg structure
> + *
> + * @prescale_offset: prescale register offset
> + * @period_offset: period register offset
> + * @duty_offset: duty register offset
> + * @no_of_channels: number of channels
> + * @out_type_shift: out type shift in the register
> + * @signal_type: push-pull or open drain
> + * @prescale_max: prescale max
> + * @prescale_shift: prescale shift in register
> + * @prescale_ch_ascending: prescale ch order in prescale register
> + * @duty_cycle_max: value of max duty cycle
> + * @duty_cycle_min: value of min duty cycle
> + * @period_count_max: max period count val
> + * @period_count_min: min period count val
> + * @smooth_output_support: pwm smooth output support
> + */
> +struct kona_pwmc_reg {
> +	u32 prescale_offset;
> +	u32 period_offset;
> +	u32 duty_offset;
> +	u32 no_of_channels;
> +	u32 out_type_shift;
> +	u32 signal_type;
> +	u32 prescale_max;
> +	u32 prescale_shift;
> +	bool prescale_ch_ascending;
> +	u32 duty_cycle_max;
> +	u32 duty_cycle_min;
> +	u32 period_count_max;
> +	u32 period_count_min;
> +	bool smooth_output_support;
> +};

This is rather tedious. It looks to me like this isn't very similar to
the existing driver. Register offsets move around, bitfield positions
change, feature set is different. Might be better off turning this into
a separate driver after all.

> +static const struct kona_pwmc_reg kona_pwmc_reg_data = {
> +	.prescale_offset = PRESCALE_OFFSET,
> +	.period_offset = KONA_PERIOD_COUNT_OFFSET,
> +	.duty_offset = KONA_DUTY_CYCLE_HIGH_OFFSET,
> +	.no_of_channels = PWM_CHANNEL_CNT,
> +	.out_type_shift = PWMOUT_TYPE_SHIFT,
> +	.signal_type = SIGNAL_PUSH_PULL,
> +	.prescale_max = PRESCALE_MAX,
> +	.prescale_shift = PRESCALE_SHIFT,
> +	.prescale_ch_ascending = false,
> +	.duty_cycle_max = DUTY_CYCLE_HIGH_MAX,
> +	.duty_cycle_min = DUTY_CYCLE_HIGH_MIN,
> +	.period_count_max = PERIOD_COUNT_MAX,
> +	.period_count_min = PERIOD_COUNT_MIN,
> +	.smooth_output_support = true,
> +};
> +
> +static const struct kona_pwmc_reg iproc_pwmc_reg_data = {
> +	.prescale_offset = IPROC_PRESCALE_OFFSET,
> +	.period_offset = IPROC_PERIOD_COUNT_OFFSET,
> +	.duty_offset = IPROC_DUTY_CYCLE_HIGH_OFFSET,
> +	.no_of_channels = IPROC_PWM_CHANNEL_CNT,
> +	.out_type_shift = IPROC_PWMOUT_TYPE_SHIFT,
> +	.signal_type = IPROC_SIGNAL_PUSH_PULL,
> +	.prescale_max = IPROC_PRESCALE_MAX,
> +	.prescale_shift = IPROC_PRESCALE_SHIFT,
> +	.prescale_ch_ascending = true,
> +	.duty_cycle_max = IPROC_DUTY_CYCLE_HIGH_MAX,
> +	.duty_cycle_min = IPROC_DUTY_CYCLE_HIGH_MIN,
> +	.period_count_max = IPROC_PERIOD_COUNT_MAX,
> +	.period_count_min = IPROC_PERIOD_COUNT_MIN,
> +	.smooth_output_support = false,
> +};

This looks like you could possible support a lot more hardware with this
driver because it's now almost completely parameterized.

I don't see much sense in keeping this in the same driver and I think
it'd be better to write a new one from scratch, even if that means
slight duplication.

Or you'll have to make a very compelling argument as to why this is the
better option.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160510/8ebc180a/attachment.sig>

From julien.grall at arm.com  Tue May 10 07:40:31 2016
From: julien.grall at arm.com (Julien Grall)
Date: Tue, 10 May 2016 15:40:31 +0100
Subject: [PATCH] arm64: cpuinfo: Missing NULL terminator in compat_hwcap_str
Message-ID: <1462891231-17605-1-git-send-email-julien.grall@arm.com>

The loop that browses the array compat_hwcap_str will stop when a NULL
is encountered, however NULL is missing at the end of array. This will
result to overrun until one NULL is found somewhere in the memory.

Fixes: 44b82b7700d0 "arm64: Fix up /proc/cpuinfo"
Signed-off-by: Julien Grall <julien.grall at arm.com>
Cc: stable at vger.kernel.org

---

Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Suzuki K. Poulose <suzuki.poulose at arm.com>
---
 arch/arm64/kernel/cpuinfo.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 84c8684..f0c3fb7 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -87,7 +87,8 @@ static const char *const compat_hwcap_str[] = {
 	"idivt",
 	"vfpd32",
 	"lpae",
-	"evtstrm"
+	"evtstrm",
+	NULL
 };
 
 static const char *const compat_hwcap2_str[] = {
-- 
1.9.1



From gregory.clement at free-electrons.com  Tue May 10 07:42:17 2016
From: gregory.clement at free-electrons.com (Gregory CLEMENT)
Date: Tue, 10 May 2016 16:42:17 +0200
Subject: [GIT PULL] ARM: mvebu: defconfig for v4.7 (#2)
In-Reply-To: <2554522.hzQidgmgjq@wuerfel> (Arnd Bergmann's message of "Tue, 10
 May 2016 14:13:57 +0200")
References: <87pot8sct4.fsf@free-electrons.com> <13443700.NUC16SCx6V@wuerfel>
 <2554522.hzQidgmgjq@wuerfel>
Message-ID: <87vb2mnfee.fsf@free-electrons.com>

Hi Arnd,
 
 On mar., mai 10 2016, Arnd Bergmann <arnd at arndb.de> wrote:

> On Tuesday 10 May 2016 14:05:48 Arnd Bergmann wrote:
>> On Friday 29 April 2016 16:35:19 Gregory CLEMENT wrote:
>> > mvebu defconfig for 4.7 (part 2)
>> > 
>> > - enable AP806 and CP110 syscon driver in arm64 defconfig
>> > 
>> > 
>> 
>> Merged into next/defconfig, thanks!
>> 
>
> I ended up undoing the merge before I pushed it out to the git server
> as I noticed you have both arm and arm64 changes in there.
>
> Can you still split up the branch in two?

As seen on IRC I am about to send a PR with a new mvebu/defconfig64
branch as the only change here was related to arm64.

Gregory

>
> 	Arnd

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com


From dinguyen at kernel.org  Tue May 10 07:43:11 2016
From: dinguyen at kernel.org (Dinh Nguyen)
Date: Tue, 10 May 2016 09:43:11 -0500
Subject: [GIT PULL] SoCFPGA DTS updates for v4.7, part3
Message-ID: <1462891391-13876-1-git-send-email-dinguyen@kernel.org>

Hi Arnd, Kevin, and Olof:

If not too late, please pull in this patch for v4.7.

Thanks,
Dinh

The following changes since commit 02da2d72174c61988eb4456b53f405e3ebdebce4:

  Linux 4.6-rc5 (2016-04-24 16:17:05 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git socfpga_for_next_v4.7_dts_part_3

for you to fetch changes up to fca689561e8170ad954b982b9ce2160a06d9435e:

  ARM: dts: socfpga: add ethernet alias on Arria10 (2016-05-03 09:25:21 -0500)

----------------------------------------------------------------
SoCFPGA DTS update for v4.7, part 3
- Add ethernet alias on Arria10

----------------------------------------------------------------
Dinh Nguyen (1):
      ARM: dts: socfpga: add ethernet alias on Arria10

 arch/arm/boot/dts/socfpga_arria10_socdk.dtsi | 4 ++++
 1 file changed, 4 insertions(+)


From eric.auger at linaro.org  Tue May 10 07:43:17 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 16:43:17 +0200
Subject: [PATCH v9 4/8] iommu/msi-iommu: initialization
In-Reply-To: <20160509145739.41a19743@t450s.home>
References: <1462362007-2753-1-git-send-email-eric.auger@linaro.org>
 <1462362007-2753-5-git-send-email-eric.auger@linaro.org>
 <20160509145739.41a19743@t450s.home>
Message-ID: <5731F385.6070706@linaro.org>

Hi Alex,
On 05/09/2016 10:57 PM, Alex Williamson wrote:
> On Wed,  4 May 2016 11:40:03 +0000
> Eric Auger <eric.auger at linaro.org> wrote:
> 
>> iommu_get/put_msi_cookie allocates/frees the resource used to store
>> and ref count the MSI doorbell mappings. iommu_msi_set_aperture
>> initializes the iova domain used for MSI IOVA allocation and sets the
>> iommu domain's msi geometry.
>>
>> The implementation relies on dma-iommu API and iova API.
>>
>> New msi functions are fully implemented if CONFIG_IOMMU_MSI is set.
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>
>> ---
>> v9:
>> - remove is_aperture_set and use iommu_domain_msi_aperture_valid helper
>>   instead
>> - set iommu domain's msi geometry
>>
>> v8:
>> - new design where msi-iommu relies on dma-iommu
>> - remove the iommu_domain * from the doorbell_mapping struct
>> - added is_aperture_set
>>
>> v7:
>> - fix locking
>> - add iova_cache_get/put
>> - static inline functions when CONFIG_IOMMU_DMA_RESERVED is not set
>> - introduce struct reserved_iova_domain to encapsulate prot info &
>>   add prot parameter in alloc_reserved_iova_domain
>>
>> v5 -> v6:
>> - use spin lock instead of mutex
>>
>> v3 -> v4:
>> - formerly in "iommu/arm-smmu: implement alloc/free_reserved_iova_domain" &
>>   "iommu: add alloc/free_reserved_iova_domain"
>>
>> v2 -> v3:
>> - remove iommu_alloc_reserved_iova_domain & iommu_free_reserved_iova_domain
>>   static implementation in case CONFIG_IOMMU_API is not set
>>
>> v1 -> v2:
>> - moved from vfio API to IOMMU API
>> ---
>>  drivers/iommu/Kconfig     |  7 ++++
>>  drivers/iommu/Makefile    |  1 +
>>  drivers/iommu/msi-iommu.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/msi-iommu.h | 65 +++++++++++++++++++++++++++++++
>>  4 files changed, 170 insertions(+)
>>  create mode 100644 drivers/iommu/msi-iommu.c
>>  create mode 100644 include/linux/msi-iommu.h
>>
>> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
>> index dd1dc39..0078b72 100644
>> --- a/drivers/iommu/Kconfig
>> +++ b/drivers/iommu/Kconfig
>> @@ -74,6 +74,11 @@ config IOMMU_DMA
>>  	select IOMMU_IOVA
>>  	select NEED_SG_DMA_LENGTH
>>  
>> +# IOMMU MSI mapping
>> +config IOMMU_MSI
>> +	bool
>> +	select IOMMU_DMA
>> +
>>  config FSL_PAMU
>>  	bool "Freescale IOMMU support"
>>  	depends on PPC32
>> @@ -307,6 +312,7 @@ config SPAPR_TCE_IOMMU
>>  config ARM_SMMU
>>  	bool "ARM Ltd. System MMU (SMMU) Support"
>>  	depends on (ARM64 || ARM) && MMU
>> +	select IOMMU_MSI
>>  	select IOMMU_API
>>  	select IOMMU_IO_PGTABLE_LPAE
>>  	select ARM_DMA_USE_IOMMU if ARM
>> @@ -320,6 +326,7 @@ config ARM_SMMU
>>  config ARM_SMMU_V3
>>  	bool "ARM Ltd. System MMU Version 3 (SMMUv3) Support"
>>  	depends on ARM64 && PCI
>> +	select IOMMU_MSI
>>  	select IOMMU_API
>>  	select IOMMU_IO_PGTABLE_LPAE
>>  	select GENERIC_MSI_IRQ_DOMAIN
>> diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
>> index c6edb31..a381e66 100644
>> --- a/drivers/iommu/Makefile
>> +++ b/drivers/iommu/Makefile
>> @@ -2,6 +2,7 @@ obj-$(CONFIG_IOMMU_API) += iommu.o
>>  obj-$(CONFIG_IOMMU_API) += iommu-traces.o
>>  obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
>>  obj-$(CONFIG_IOMMU_DMA) += dma-iommu.o
>> +obj-$(CONFIG_IOMMU_MSI) += msi-iommu.o
>>  obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
>>  obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
>>  obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
>> diff --git a/drivers/iommu/msi-iommu.c b/drivers/iommu/msi-iommu.c
>> new file mode 100644
>> index 0000000..4292957
>> --- /dev/null
>> +++ b/drivers/iommu/msi-iommu.c
>> @@ -0,0 +1,97 @@
>> +/*
>> + * Reserved IOVA Management
>> + *
>> + * Copyright (c) 2015 Linaro Ltd.
>> + *              www.linaro.org
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + */
>> +
>> +#include <linux/iommu.h>
>> +#include <linux/dma-iommu.h>
>> +#include <linux/msi-iommu.h>
>> +#include <linux/spinlock.h>
>> +#include <linux/iova.h>
>> +
>> +struct doorbell_mapping {
>> +	struct kref		kref;
>> +	struct list_head	next;
>> +	phys_addr_t		addr;
>> +	dma_addr_t		iova;
>> +	size_t			size;
>> +};
>> +
>> +struct doorbell_mapping_info {
>> +	struct list_head list; /* list of doorbell mapping entries */
>> +	spinlock_t lock;
>> +};
>> +
>> +int iommu_get_msi_cookie(struct iommu_domain *domain)
>> +{
>> +	struct doorbell_mapping_info *dmi;
>> +	int ret;
>> +
>> +	if (domain->msi_cookie || domain->iova_cookie)
>> +		return -EINVAL;
>> +
>> +	ret = iommu_get_dma_cookie(domain);
>> +	if (ret)
>> +		return ret;
>> +
>> +	dmi = kzalloc(sizeof(*dmi), GFP_KERNEL);
>> +
>> +	INIT_LIST_HEAD(&dmi->list);
>> +	spin_lock_init(&dmi->lock);
>> +	iova_cache_get();
>> +
>> +	domain->msi_cookie = dmi;
>> +
>> +	return dmi ? 0 : -ENOMEM;
>> +}
>> +EXPORT_SYMBOL(iommu_get_msi_cookie);
>> +
>> +void iommu_put_msi_cookie(struct iommu_domain *domain)
>> +{
>> +	struct doorbell_mapping_info *dmi = domain->msi_cookie;
>> +
>> +	if (!dmi)
>> +		return;
>> +
>> +	domain->msi_cookie = NULL;
>> +
>> +	WARN_ON(!list_empty(&dmi->list));
>> +
>> +	kfree(dmi);
>> +	iommu_put_dma_cookie(domain);
>> +	iova_cache_put();
>> +}
>> +EXPORT_SYMBOL(iommu_put_msi_cookie);
>> +
>> +int iommu_msi_set_aperture(struct iommu_domain *domain,
>> +			   dma_addr_t start, dma_addr_t end)
>> +{
>> +	struct doorbell_mapping_info *dmi = domain->msi_cookie;
>> +	int ret;
>> +
>> +	if (!dmi || iommu_domain_msi_aperture_valid(domain))
>> +		return -ENODEV;
> 
> 
> nit, the next patch splits to use different errnos for each issue,
> which seems preferable.

sure

Eric
> 
> 
>> +
>> +	ret = iommu_dma_init_domain(domain, start, end - start + 1);
>> +
>> +	if (!ret) {
>> +		domain->msi_geometry.aperture_start = start;
>> +		domain->msi_geometry.aperture_end = end;
>> +	}
>> +
>> +	return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(iommu_msi_set_aperture);
>> +
>> diff --git a/include/linux/msi-iommu.h b/include/linux/msi-iommu.h
>> new file mode 100644
>> index 0000000..392aa6f
>> --- /dev/null
>> +++ b/include/linux/msi-iommu.h
>> @@ -0,0 +1,65 @@
>> +/*
>> + * Copyright (c) 2015 Linaro Ltd.
>> + *              www.linaro.org
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + */
>> +#ifndef __MSI_IOMMU_H
>> +#define __MSI_IOMMU_H
>> +
>> +#include <linux/types.h>
>> +#include <linux/kernel.h>
>> +
>> +struct iommu_domain;
>> +
>> +#ifdef CONFIG_IOMMU_MSI
>> +
>> +/**
>> + * iommu_get_msi_cookie - Acquire MSI mapping resources for a domain
>> + * @domain: IOMMU domain to prepare for MSI mapping
>> + *
>> + * IOMMU drivers which require MSI mapping should normally call this
>> + * from their domain_alloc callback when domain->type ==
>> + * IOMMU_DOMAIN_UNMANAGED.
>> + */
>> +int iommu_get_msi_cookie(struct iommu_domain *domain);
>> +
>> +/**
>> + * iommu_put_msi_cookie - Release a domain's MSI mapping resources
>> + * @domain: IOMMU domain previously prepared by iommu_get_msi_cookie()
>> + *
>> + * IOMMU drivers requesting MSI mapping should normally call this from
>> + * their domain_free callback.
>> + */
>> +void iommu_put_msi_cookie(struct iommu_domain *domain);
>> +
>> +/**
>> + * iommu_msi_set_aperture: allocate the msi iova domain
>> + * according to the specified start/end IOVAs
>> + *
>> + * @domain: iommu domain handle
>> + * @start: MSI iova start address
>> + * @end: MSI iova end address
>> + */
>> +int iommu_msi_set_aperture(struct iommu_domain *domain,
>> +			   dma_addr_t start, dma_addr_t end);
>> +
>> +#else
>> +
>> +static inline int
>> +iommu_msi_set_aperture(struct iommu_domain *domain,
>> +		       dma_addr_t start, dma_addr_t end)
>> +{
>> +	return -ENOENT;
>> +}
>> +
>> +#endif	/* CONFIG_IOMMU_MSI */
>> +#endif	/* __MSI_IOMMU_H */
> 



From gregory.clement at free-electrons.com  Tue May 10 07:44:42 2016
From: gregory.clement at free-electrons.com (Gregory CLEMENT)
Date: Tue, 10 May 2016 16:44:42 +0200
Subject: [GIT PULL] ARM: mvebu: defconfig64 for v4.7 (#1)
Message-ID: <87twi6nfad.fsf@free-electrons.com>

Hi,

Here is the first pull request for defconfig64 for mvebu for v4.7.

Gregory

The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  git://git.infradead.org/linux-mvebu.git tags/mvebu-defconfig64-4.7-1

for you to fetch changes up to e5d8b0ad5ae4c70a7081865a3c6c83ae1afe3087:

  arm64: configs: add options useful for Armada 7K/8K support (2016-05-10 14:42:23 +0200)

----------------------------------------------------------------
mvebu defconfig for arm64 for 4.7

- update arm64 defconfig with options useful for Armada 7K/8K support

----------------------------------------------------------------
Thomas Petazzoni (1):
      arm64: configs: add options useful for Armada 7K/8K support

 arch/arm64/configs/defconfig | 4 ++++
 1 file changed, 4 insertions(+)


From marc.zyngier at arm.com  Tue May 10 07:45:20 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 15:45:20 +0100
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <5731F196.4040906@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
 <20160510133043.GF27623@cbox> <5731E52A.9000402@arm.com>
 <20160510141119.GB20499@cbox> <5731F196.4040906@arm.com>
Message-ID: <5731F400.4080004@arm.com>

On 10/05/16 15:35, Marc Zyngier wrote:
> On 10/05/16 15:11, Christoffer Dall wrote:
>> On Tue, May 10, 2016 at 02:42:02PM +0100, Marc Zyngier wrote:
>>> On 10/05/16 14:30, Christoffer Dall wrote:
>>>> On Fri, May 06, 2016 at 11:45:31AM +0100, Andre Przywara wrote:
>>>>> From: Marc Zyngier <marc.zyngier at arm.com>
>>>>>
>>>>> Processing maintenance interrupts and accessing the list registers
>>>>> are dependent on the host's GIC version.
>>>>> Introduce vgic-v2.c to contain GICv2 specific functions.
>>>>> Implement the GICv2 specific code for syncing the emulation state
>>>>> into the VGIC registers.
>>>>>
>>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>>>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>>>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>>> ---
>>>>> Changelog RFC..v1:
>>>>> - remove explicit LR_STATE clearing on maintenance interrupt handling
>>>>> - improve documentation for vgic_v2_populate_lr()
>>>>> - remove WARN_ON on non-edge IRQs in maintenance interrupts
>>>>> - simplify multi-CPU source SGI handling
>>>>>
>>>>> Changelog v1 .. v2:
>>>>> - inject the IRQ priority into the list register
>>>>>
>>>>> Changelog v2 .. v3:
>>>>> - cleanup diff containing rebase artifacts
>>>>>
>>>>>  include/linux/irqchip/arm-gic.h |   1 +
>>>>>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
>>>>>  virt/kvm/arm/vgic/vgic.c        |   6 ++
>>>>>  virt/kvm/arm/vgic/vgic.h        |   6 ++
>>>>>  4 files changed, 191 insertions(+)
>>>>>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
>>>>>
>>>>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>>>>> index 9c94026..be0d26f 100644
>>>>> --- a/include/linux/irqchip/arm-gic.h
>>>>> +++ b/include/linux/irqchip/arm-gic.h
>>>>> @@ -76,6 +76,7 @@
>>>>>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
>>>>>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
>>>>>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
>>>>> +#define GICH_LR_PRIORITY_SHIFT		23
>>>>>  #define GICH_LR_STATE			(3 << 28)
>>>>>  #define GICH_LR_PENDING_BIT		(1 << 28)
>>>>>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
>>>>> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
>>>>> new file mode 100644
>>>>> index 0000000..4cee616
>>>>> --- /dev/null
>>>>> +++ b/virt/kvm/arm/vgic/vgic-v2.c
>>>>> @@ -0,0 +1,178 @@
>>>>> +/*
>>>>> + * Copyright (C) 2015, 2016 ARM 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.
>>>>> + *
>>>>> + * 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.
>>>>> + *
>>>>> + * 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/irqchip/arm-gic.h>
>>>>> +#include <linux/kvm.h>
>>>>> +#include <linux/kvm_host.h>
>>>>> +
>>>>> +#include "vgic.h"
>>>>> +
>>>>> +/*
>>>>> + * Call this function to convert a u64 value to an unsigned long * bitmask
>>>>> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
>>>>> + *
>>>>> + * Warning: Calling this function may modify *val.
>>>>> + */
>>>>> +static unsigned long *u64_to_bitmask(u64 *val)
>>>>> +{
>>>>> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
>>>>> +	*val = (*val >> 32) | (*val << 32);
>>>>> +#endif
>>>>> +	return (unsigned long *)val;
>>>>> +}
>>>>> +
>>>>> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
>>>>> +{
>>>>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>>>>> +
>>>>> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
>>>>> +		u64 eisr = cpuif->vgic_eisr;
>>>>> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
>>>>> +		int lr;
>>>>> +
>>>>> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
>>>>> +			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
>>>>> +
>>>>> +			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
>>>>> +
>>>>> +			kvm_notify_acked_irq(vcpu->kvm, 0,
>>>>> +					     intid - VGIC_NR_PRIVATE_IRQS);
>>>>> +
>>>>
>>>> why do we need to do this?  I cannot find any consumers of this info
>>>> after we've left the hyp code.
>>>
>>> I believe that's for vhost and irqfd. Or am I misreading your question?
>>>
>>
>> I meant the setting of the bits in vgic_elrsr (sorry, badly placed
>> comment)...
>>
>>>> Also, I think I offered a comment about why we would potentially need
>>>> this in the first place.  This is the famous race where hardware doesn't
>>>> guarantee consistency between the MISR and ELRSR right?
>>>
>>> That's the one (except it is between EISR and ELRSR). I don't have your
>>> initial comment at hand, but would something like the following do?
>>>
>>> 			/*
>>> 			 * The maintenance interrupt may not have had a
>>> 			 * chance to update ELRSR, so let's mark the LRs
>>> 			 * presents in EISR as empty.
>>> 			 */
>>>>
>>>>> +			cpuif->vgic_elrsr |= 1ULL << lr;
>>
>> so, why are we doing this?
> 
> Ah! I finally see what you mean: we don't reuse LRs at all with the new code
> base, so knowing which LR is empty is irrelevant. In which case, something
> like that should be done:
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> index e88b5aa..5a8f4d4 100644
> --- a/virt/kvm/arm/vgic/vgic-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -52,8 +52,6 @@ void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
>  
>  			kvm_notify_acked_irq(vcpu->kvm, 0,
>  					     intid - VGIC_NR_PRIVATE_IRQS);
> -
> -			cpuif->vgic_elrsr |= 1ULL << lr;
>  		}
>  	}
>  
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 53f7847..4102f0f 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -43,8 +43,6 @@ void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
>  
>  			kvm_notify_acked_irq(vcpu->kvm, 0,
>  					     intid - VGIC_NR_PRIVATE_IRQS);
> -
> -			cpuif->vgic_elrsr |= 1ULL << lr;
>  		}
>  
>  		/*
> 
> I'll give it a spin, just to be safe.

Seems OK on GICv2, and this of course leads to some more possible
cleanups or optimizations (I think we can get to a state where we
completely disregards ELRSR). I'll have a look.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From boris.brezillon at free-electrons.com  Tue May 10 07:47:12 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 10 May 2016 16:47:12 +0200
Subject: [BISECTED] Regression v4.6-rc1 : nanosleep doesn't return on
 AT91SAM9
In-Reply-To: <CACQ1gAipruXcO=xpooYDOdqZbtESD35wxDf7xNrg4zuuRv1wew@mail.gmail.com>
References: <CACQ1gAg6cKqjaqcV70m2VS5R4_kZEgWTiqzSqDxSjvfrYYxbzg@mail.gmail.com>
 <CACQ1gAipruXcO=xpooYDOdqZbtESD35wxDf7xNrg4zuuRv1wew@mail.gmail.com>
Message-ID: <20160510164712.56261bb4@bbrezillon>

Hi Richard,

On Tue, 10 May 2016 16:25:25 +0200
Richard Genoud <richard.genoud at gmail.com> wrote:

> 2016-05-10 15:58 GMT+02:00 Richard Genoud <richard.genoud at gmail.com>:
> > Hi,
> >
> > Starting with 4.6-rc1, a sleep 1 doesn't return :
> >
> > execve("/bin/sleep", ["sleep", "1"], ["USER=root", "SHLVL=1",
> > "OLDPWD=/var", "HOME=/", "TERM=vt102",
> > "PATH=/sbin:/usr/sbin:/bin:/usr/bin", "SHELL=/bin/sh", "PWD=/"]) = 0
> > uname({sysname="Linux", nodename="LNS",
> > release="4.5.0-09406-g46e595a17dcf", version="#72 Tue May 10 15:41:34
> > CEST 2016", machine="armv5tejl", domainname="(none)"}) = 0
> > brk(0)                                  = 0x153000
> > brk(0x153d20)                           = 0x153d20
> > set_tls(0x1534c0, 0x14d1e4, 0, 0x153d20, 0x14e368) = 0
> > readlink("/proc/self/exe", "/bin/busybox", 4096) = 12
> > brk(0x174d20)                           = 0x174d20
> > brk(0x175000)                           = 0x175000
> > getuid32()                              = 0
> > rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
> > rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
> > rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
> > nanosleep({1, 0},
> >
> > And the heartbeat led doesn't blink anymore (full on), as if the
> > timers never fire.
> >
> > The platform is an AT91SAM9G35-CM.
> >
> > git bisect gives a merge as the 1st bad commit :(
> > first bad commit: [46e595a17dcf11404f713845ecb5b06b92a94e43] Merge tag
> > 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc  
> 
> 
> I went a little further in tracking that down, starting from the merge
> (1st bad commit) and reverting some commits.
> It seems that the culprit is :
> commit 863a81c3be1d931bdae6426e231add9334311f13
> Author: Boris Brezillon <boris.brezillon at free-electrons.com>
> Date:   Fri Sep 5 09:54:13 2014 +0200
>     clk: at91: make use of syscon to share PMC registers in several drivers
> 
> Here are the commits I've reverted :
> 
> git log --oneline --decorate -20
> 849cdaa0cf04 (HEAD, tag: good) Revert "clk: at91: make use of syscon
> to share PMC registers in several drivers"
> 4bd6dde95321 (tag: last_bad) Revert "clk: at91: make use of
> syscon/regmap internally"
> a56dacaa24c4 (tag: always_bad) Revert "clk: at91: remove IRQ handling
> and use polling"
> 33edfe7a2de6 Revert "clk: at91: pmc: merge at91_pmc_init in atmel_pmc_probe"
> 0b22bb649eae Revert "clk: at91: pmc: move pmc structures to C file"
> 14994fdff366 Revert "ARM: at91: pm: simply call at91_pm_init"
> 6f0821175327 (tag: still_bad) Revert "ARM: at91: pm: find and remap the pmc"
> b52bbf7fad1b Revert "ARM: at91: pm: move idle functions to pm.c"
> dffb1a5f68b9 Revert "ARM: at91: remove useless includes and function prototypes"
> db352691dcc1 Revert "usb: gadget: atmel: access the PMC using regmap"
> f7b5433dbbc8 Revert "clk: at91: pmc: drop at91_pmc_base"
> 6e6dfc0d91c0 Revert "clk: at91: pmc: remove useless capacities handling"
> ceddd3f88ada Revert "clk: at91: remove useless includes"
> 46e595a17dcf (tag: bad) Merge tag 'armsoc-drivers' of
> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
> e3b1f64e04f5 Merge tag 'armsoc-defconfig' of
> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
> 915c56bc01d6 Merge tag 'armsoc-dt64' of
> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
> 5a6b7e53d035 Merge tag 'armsoc-dt' of
> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
> 8c6d4082fc6a Merge tag 'armsoc-arm64' of
> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
> 33b3d2e88c9e Merge tag 'armsoc-soc' of
> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
> e88fa1b8b00a Merge tag 'armsoc-cleanup' of
> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Thanks for the detailed report.

Can you try again after applying this patch [1]?

Regards,

Boris

[1]http://code.bulix.org/dx1c0t-98377

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


From robh at kernel.org  Tue May 10 07:52:41 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 10 May 2016 09:52:41 -0500
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <CACh+v5M2yZ403+VwvRMYeGwfhpP+aCGnnNhiQ1wjrxS5fVGVEA@mail.gmail.com>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop> <20160503185153.5cfddc32@bbrezillon>
 <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
 <20160504113852.10a2dd84@bbrezillon>
 <CAL_Jsq+4aL5znA3zOKdcJb+pEXhVOQthkFF6DN2+P6U37t2o6g@mail.gmail.com>
 <20160504153547.60d736bb@bbrezillon> <20160510100448.49834120@bbrezillon>
 <20160510110742.GI687@leverpostej> <20160510144143.1965ee5e@bbrezillon>
 <CACh+v5M2yZ403+VwvRMYeGwfhpP+aCGnnNhiQ1wjrxS5fVGVEA@mail.gmail.com>
Message-ID: <CAL_JsqL0o7Q4yNF1CCvJDx0nvJLRXZ-ieCDEkOa9ByfvdnuLRw@mail.gmail.com>

On Tue, May 10, 2016 at 8:08 AM, Jean-Jacques Hiblot
<jjhiblot at traphandler.com> wrote:
> 2016-05-10 14:41 GMT+02:00 Boris Brezillon <boris.brezillon at free-electrons.com>:
>> On Tue, 10 May 2016 12:07:42 +0100
>> Mark Rutland <mark.rutland at arm.com> wrote:
>>
>>> On Tue, May 10, 2016 at 10:04:48AM +0200, Boris Brezillon wrote:
>>> > On Wed, 4 May 2016 15:35:47 +0200
>>> > Boris Brezillon <boris.brezillon at free-electrons.com> wrote:
>>> >
>>> > > On Wed, 4 May 2016 08:06:10 -0500
>>> > > Rob Herring <robh at kernel.org> wrote:
>>> > >
>>> > > > On Wed, May 4, 2016 at 4:38 AM, Boris Brezillon
>>> > > > <boris.brezillon at free-electrons.com> wrote:
>>> > > > > Hi Rob,
>>> > > > >
>>> > > > > On Tue, 3 May 2016 14:11:04 -0500
>>> > > > > Rob Herring <robh at kernel.org> wrote:
>>> > > > >
>>> > > > >> On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
>>> > > > >> <boris.brezillon at free-electrons.com> wrote:
>>> > > > >> > Hi Rob,
>>> > > > >> >
>>> > > > >> > On Tue, 3 May 2016 11:40:19 -0500
>>> > > > >> > Rob Herring <robh at kernel.org> wrote:
>>> > > > >> >
>>> > > > >> >> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:
>>> > > > >> >> > The EBI (External Bus Interface) is used to access external peripherals
>>> > > > >> >> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
>>> > > > >> >> > Each device is assigned a CS line and an address range and can have its
>>> > > > >> >> > own configuration (timings, access mode, bus width, ...).
>>> > > > >> >> > This driver provides a generic DT binding to configure a device according
>>> > > > >> >> > to its requirements.
>>> > > > >> >> > For specific device controllers (like the NAND one) the SMC timings
>>> > > > >> >> > should be configured by the controller driver through the matrix and smc
>>> > > > >> >> > syscon regmaps.
>>> > > >
>>> > > > [...]
>>> > > >
>>> > > > >> >> > +EBI bus configuration associated with specific chip-select will be defined in
>>> > > > >> >> > +the configs subnode. This configs node will in turn contain several subnodes
>>> > > > >> >> > +named config-<cs-id>, each of them containing the following properties.
>>> > > > >> >>
>>> > > > >> >> This is a bit unusual. Why not just part of the child device nodes?
>>> > > > >> >
>>> > > > >> > Oh, come on! I reworked the binding because Mark complained about the
>>> > > > >> > previous binding which was doing exactly what you're suggesting. Can
>>> > > > >> > you please be consistent in your reviews...
>>> > > > >>
>>> > > > >> No, Mark and I both have our opinions. Which part of this patch
>>> > > > >> explains the history?
>>> > > > >
>>> > > > > Hm, it's in patch 1/2 (just dropped the cover letter, which might not
>>> > > > > be such a good idea).
>>> > > > >
>>> > > > >> If the revision history is not in the patch, I'm
>>> > > > >> not looking at it.
>>> > > > >>
>>> > > > >> My issue with it this way is that it has invented yet another way to
>>> > > > >> describe timings. I would like to be consistent across external bus
>>> > > > >> descriptions, but we're not very consistent to begin with though. The
>>> > > > >> most common seems to be the way you first did it. But I agree that it
>>> > > > >> is kind of screwy to have an intermediate node unless the controller
>>> > > > >> itself has sub-blocks within it and is not the established way to
>>> > > > >> describe a bus with chip selects. I would either put the properties
>>> > > > >> directly in the child nodes (e.g. flash at 0,0) or put your config nodes
>>> > > > >> in the device node. I'd call it timings instead of config, but that's
>>> > > > >> just bikeshedding.
>>> > > > >
>>> > > > > Well, it's not only describing timings (see atmel,bus-width,
>>> > > > > atmel,byte-access-type, ...), but I'm fine with either names :).
>>> > > > >
>>> > > > >>
>>> > > > >> memory-controller at 1000 {
>>> > > > >>   ...
>>> > > > >>   flash at 0,0 {
>>> > > > >>     timings {
>>> > > > >>       ...
>>> > > > >>     };
>>> > > > >>   };
>>> > > > >> };
>>> > > > >
>>> > > > > Okay. Mark, what do you think of this approach?
>>> > > > >
>>> > > > > Note that one of my previous version was defining timings directly in
>>> > > > > the EBI device node, and Arnd noted that doing so may cause problems
>>> > > > > if one of the EBI property (or the config/timing node name) conflict
>>> > > > > with the sub-device binding, which is why I decided to put the EBI
>>> > > > > config definitions in a separate subnode.
>>> > > >
>>> > > > You have vendor prefixes on all the properties so I don't think a
>>> > > > collision is really a problem. It's also an established pattern in
>>> > > > i.MX WEIM and OMAP GPMC (which are hiding in bindings/bus/) and I
>>> > > > prefer consistency.
>>> > >
>>> > > So let's summarize that.
>>> > >
>>> > > memory-controller at 1000 {
>>> > >   ...
>>> > >   flash at 0,0 {
>>> > >           atmel,<ebi-prop-name> = <value>;
>>> > >           ...
>>> > >           <flash-device-prop> = <value>;
>>> > >   };
>>> > > };
>>> > >
>>> > > Would everyone agree on this representation?
>>> > >
>>> > > With this approach, it's a bit more complicated to detect the case
>>> > > where we want to keep bootloader/firmware config, but it should be
>>> > > doable (it's much more easier to test for the presence of a
>>> > > config/timing node than verifying that either all or none of the
>>> > > mandatory properties are here).
>>> > >
>>> > > Still remains the problem mentioned by Jean-Jacques: what if the
>>> > > sub-device takes 2 CS lines. Should we apply the same setting to those
>>> > > slots?
>>> > >
>>> >
>>> > Rob, Mark, Arnd, can you take a decision regarding this binding? This
>>> > driver is floating around for quite some time, and we were asked to
>>> > rework the binding several times (in time in an opposite direction).
>>> >
>>> > For the record, here is the thread I mentioned earlier [1]. In his
>>> > answer, Arnd suggests to put timing and bus config description
>>> > outside of the sub-device node. Mark recently complained about this
>>> > representation, which led me to the configs/config-X appraoch, and now
>>> > Rob suggests to go back to the first proposal.
>>> >
>>> > I'm fine doing that, but can you please all confirm that you agree on
>>> > this binding?
>>>
>>> Sorry for the delay in getting round to this, and sorry that this
>>> appears to be going in circles.
>>>
>>> Please go with Rob's suggestion.
>>
>> Okay. This changes a bit the constraints defined in the binding doc
>> (no default values for undefined properties: we just keep the
>> bootloader/firmware config), but otherwise should be easy to implement.
>>
>>>
>>> I'm not sure about the case where a device takes 2 CS lines. I would
>>> assume that in practice that a sub-device covered my multiple CS lines
>>> expects the same timings for all its MMIO space, and so having that
>>> uniform makes sense. Do we have a counter-example?
>>
>> Nope, I don't. JJH had one (interfacing with an FPGA), maybe he can
>> detail this use case.
>>
> I don't either. It makes sense that a single device with 2 CS uses the
> same timings.
> My use case was the other way around: 1 CS for several devices.

Ah, I thought it was just wanting to share timings for several CS. In
this case, it would probably make sense to have 3 levels of nodes
(EBI, CS node with timings, device nodes) as you do have some logic in
between to do address decoding. But I think the simple case should
still be 2 levels of nodes and that doesn't really affect the EBI
binding. It just cares that timings are in the immediate child nodes.

Rob


From mark.rutland at arm.com  Tue May 10 07:54:41 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 10 May 2016 15:54:41 +0100
Subject: [PATCH] arm64: cpuinfo: Missing NULL terminator in
 compat_hwcap_str
In-Reply-To: <1462891231-17605-1-git-send-email-julien.grall@arm.com>
References: <1462891231-17605-1-git-send-email-julien.grall@arm.com>
Message-ID: <20160510145441.GC10785@leverpostej>

On Tue, May 10, 2016 at 03:40:31PM +0100, Julien Grall wrote:
> The loop that browses the array compat_hwcap_str will stop when a NULL
> is encountered, however NULL is missing at the end of array. This will
> result to overrun until one NULL is found somewhere in the memory.

Probably worth adding something like:

Note for backporting: commit 12d11817eaafa414 ("arm64: Move
/proc/cpuinfo handling code") moved this code. Prior to that commit, the
same change should be made in arch/arm64/kernel/setup.c.

> Fixes: 44b82b7700d0 "arm64: Fix up /proc/cpuinfo"
> Signed-off-by: Julien Grall <julien.grall at arm.com>
> Cc: stable at vger.kernel.org
> 
> ---
> 
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Suzuki K. Poulose <suzuki.poulose at arm.com>
> ---

Wierd middle '---' between the Cc lines above.

Otherwise:

Reviewed-by: Mark Rutland <mark.rutland at arm.com>

Thanks for fixing this, sorry for introducing it in the first place!

Mark.

>  arch/arm64/kernel/cpuinfo.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> index 84c8684..f0c3fb7 100644
> --- a/arch/arm64/kernel/cpuinfo.c
> +++ b/arch/arm64/kernel/cpuinfo.c
> @@ -87,7 +87,8 @@ static const char *const compat_hwcap_str[] = {
>  	"idivt",
>  	"vfpd32",
>  	"lpae",
> -	"evtstrm"
> +	"evtstrm",
> +	NULL
>  };
>  
>  static const char *const compat_hwcap2_str[] = {
> -- 
> 1.9.1
> 


From eric.auger at linaro.org  Tue May 10 07:54:03 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 16:54:03 +0200
Subject: [PATCH v9 2/7] vfio/type1: vfio_find_dma accepting a type argument
In-Reply-To: <20160509164928.518a05a8@t450s.home>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-3-git-send-email-eric.auger@linaro.org>
 <20160509164928.518a05a8@t450s.home>
Message-ID: <5731F60B.6040105@linaro.org>

Hi Alex,
On 05/10/2016 12:49 AM, Alex Williamson wrote:
> On Wed,  4 May 2016 11:54:13 +0000
> Eric Auger <eric.auger at linaro.org> wrote:
> 
>> In our RB-tree we now have slots of different types (USER and RESERVED).
>> It becomes useful to be able to search for dma slots of a specific type or
>> any type. This patch proposes an implementation for that modality and also
>> changes the existing callers using the USER type.
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>> ---
>>  drivers/vfio/vfio_iommu_type1.c | 63 ++++++++++++++++++++++++++++++++++-------
>>  1 file changed, 53 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
>> index aaf5a6c..2d769d4 100644
>> --- a/drivers/vfio/vfio_iommu_type1.c
>> +++ b/drivers/vfio/vfio_iommu_type1.c
>> @@ -98,23 +98,64 @@ struct vfio_group {
>>   * into DMA'ble space using the IOMMU
>>   */
>>  
>> -static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
>> -				      dma_addr_t start, size_t size)
>> +/**
>> + * vfio_find_dma_from_node: looks for a dma slot intersecting a window
>> + * from a given rb tree node
>> + * @top: top rb tree node where the search starts (including this node)
>> + * @start: window start
>> + * @size: window size
>> + * @type: window type
>> + */
>> +static struct vfio_dma *vfio_find_dma_from_node(struct rb_node *top,
>> +						dma_addr_t start, size_t size,
>> +						enum vfio_iova_type type)
>>  {
>> -	struct rb_node *node = iommu->dma_list.rb_node;
>> +	struct rb_node *node = top;
>> +	struct vfio_dma *dma;
>>  
>>  	while (node) {
>> -		struct vfio_dma *dma = rb_entry(node, struct vfio_dma, node);
>> -
>> +		dma = rb_entry(node, struct vfio_dma, node);
>>  		if (start + size <= dma->iova)
>>  			node = node->rb_left;
>>  		else if (start >= dma->iova + dma->size)
>>  			node = node->rb_right;
>>  		else
>> +			break;
>> +	}
>> +	if (!node)
>> +		return NULL;
>> +
>> +	/* a dma slot intersects our window, check the type also matches */
>> +	if (type == VFIO_IOVA_ANY || dma->type == type)
>> +		return dma;
>> +
>> +	/* restart 2 searches skipping the current node */
>> +	if (start < dma->iova) {
>> +		dma = vfio_find_dma_from_node(node->rb_left, start,
>> +					      size, type);
>> +		if (dma)
>>  			return dma;
>>  	}
>> +	if (start + size > dma->iova + dma->size)
>> +		dma = vfio_find_dma_from_node(node->rb_right, start,
>> +					      size, type);
> 
> It might be nice to split this little bit of trickery out to a separate
> patch so that you can better explain what it does.  It's really not
> needed until we start creating user-type entries, so it shouldn't hurt
> bisection.
OK I will

Regards

Eric
> 
>> +	return dma;
>> +}
>> +
>> +/**
>> + * vfio_find_dma: find a dma slot intersecting a given window
>> + * @iommu: vfio iommu handle
>> + * @start: window base iova
>> + * @size: window size
>> + * @type: window type
>> + */
>> +static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
>> +				      dma_addr_t start, size_t size,
>> +				      enum vfio_iova_type type)
>> +{
>> +	struct rb_node *top_node = iommu->dma_list.rb_node;
>>  
>> -	return NULL;
>> +	return vfio_find_dma_from_node(top_node, start, size, type);
>>  }
>>  
>>  static void vfio_link_dma(struct vfio_iommu *iommu, struct vfio_dma *new)
>> @@ -488,19 +529,21 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
>>  	 * mappings within the range.
>>  	 */
>>  	if (iommu->v2) {
>> -		dma = vfio_find_dma(iommu, unmap->iova, 0);
>> +		dma = vfio_find_dma(iommu, unmap->iova, 0, VFIO_IOVA_USER);
>>  		if (dma && dma->iova != unmap->iova) {
>>  			ret = -EINVAL;
>>  			goto unlock;
>>  		}
>> -		dma = vfio_find_dma(iommu, unmap->iova + unmap->size - 1, 0);
>> +		dma = vfio_find_dma(iommu, unmap->iova + unmap->size - 1, 0,
>> +				    VFIO_IOVA_USER);
>>  		if (dma && dma->iova + dma->size != unmap->iova + unmap->size) {
>>  			ret = -EINVAL;
>>  			goto unlock;
>>  		}
>>  	}
>>  
>> -	while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size))) {
>> +	while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size,
>> +				    VFIO_IOVA_USER))) {
>>  		if (!iommu->v2 && unmap->iova > dma->iova)
>>  			break;
>>  		unmapped += dma->size;
>> @@ -604,7 +647,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
>>  
>>  	mutex_lock(&iommu->lock);
>>  
>> -	if (vfio_find_dma(iommu, iova, size)) {
>> +	if (vfio_find_dma(iommu, iova, size, VFIO_IOVA_ANY)) {
>>  		mutex_unlock(&iommu->lock);
>>  		return -EEXIST;
>>  	}
> 



From drjones at redhat.com  Tue May 10 07:58:32 2016
From: drjones at redhat.com (Andrew Jones)
Date: Tue, 10 May 2016 16:58:32 +0200
Subject: [PATCH v3a] KVM: arm/arm64: pmu: abstract access to number of SPIs
In-Reply-To: <1462890906-6134-1-git-send-email-andre.przywara@arm.com>
References: <5731AF57.2040707@linaro.org>
 <1462890906-6134-1-git-send-email-andre.przywara@arm.com>
Message-ID: <20160510145832.cv3ozila3kisije6@hawk.localdomain>

On Tue, May 10, 2016 at 03:35:06PM +0100, Andre Przywara wrote:
> Currently the PMU uses a member of the struct vgic_dist directly,
> which not only breaks abstraction, but will fail with the new VGIC.
> Abstract this access in the VGIC header file.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Hi Eric, Marc,
> 
> as this if-statement was quite confusing (it wasn't even the negation
> that was wrong), I rewrote it a bit to be more readable.
> This one works now with PPIs (after fixing kvmtool).
> 
> Does that make sense?
> 
> Cheers,
> Andre.
> 
>  include/kvm/arm_vgic.h |  2 ++
>  virt/kvm/arm/pmu.c     | 19 +++++++++++--------
>  2 files changed, 13 insertions(+), 8 deletions(-)
> 
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 6a98e05..d406f8e 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -351,6 +351,8 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
>  #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
>  #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
>  #define vgic_ready(k)		((k)->arch.vgic.ready)
> +#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
> +				 ((i) < (k)->arch.vgic.nr_irqs))
>  
>  int vgic_v2_probe(struct device_node *vgic_node,
>  		  const struct vgic_ops **ops,
> diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
> index 575c7aa..6ab9d6b 100644
> --- a/virt/kvm/arm/pmu.c
> +++ b/virt/kvm/arm/pmu.c
> @@ -436,6 +436,11 @@ static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
>  	return 0;
>  }
>  
> +/*
> + * For one VM the interrupt type must be same for each vcpu.
> + * As a PPI, the interrupt number is the same for all vcpus,
> + * while as an SPI it must be a separate number per vcpu.
> + */
>  static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)

While at it, I'd change this function name to have 'pmu' in it. It's
just a static function, but without pmu in it it looks a bit confusing
now to check the irq is [a valid] spi or ppi number, and then to call
the generically named 'irq_is_valid' on it as well.

Thanks,
drew

>  {
>  	int i;
> @@ -457,6 +462,7 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
>  	return true;
>  }
>  
> +#define irq_is_ppi(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS)
>  
>  int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
>  {
> @@ -471,14 +477,11 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
>  		if (get_user(irq, uaddr))
>  			return -EFAULT;
>  
> -		/*
> -		 * The PMU overflow interrupt could be a PPI or SPI, but for one
> -		 * VM the interrupt type must be same for each vcpu. As a PPI,
> -		 * the interrupt number is the same for all vcpus, while as an
> -		 * SPI it must be a separate number per vcpu.
> -		 */
> -		if (irq < VGIC_NR_SGIS || irq >= vcpu->kvm->arch.vgic.nr_irqs ||
> -		    !irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
> +		/* The PMU overflow interrupt can be a PPI or a valid SPI. */
> +		if (!(irq_is_ppi(irq) || vgic_valid_spi(vcpu->kvm, irq)))
> +			return -EINVAL;
> +
> +		if (!irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
>  			return -EINVAL;
>  
>  		if (kvm_arm_pmu_irq_initialized(vcpu))
> -- 
> 2.7.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From richard.genoud at gmail.com  Tue May 10 07:59:53 2016
From: richard.genoud at gmail.com (Richard Genoud)
Date: Tue, 10 May 2016 16:59:53 +0200
Subject: [BISECTED] Regression v4.6-rc1 : nanosleep doesn't return on
 AT91SAM9
In-Reply-To: <20160510164712.56261bb4@bbrezillon>
References: <CACQ1gAg6cKqjaqcV70m2VS5R4_kZEgWTiqzSqDxSjvfrYYxbzg@mail.gmail.com>
 <CACQ1gAipruXcO=xpooYDOdqZbtESD35wxDf7xNrg4zuuRv1wew@mail.gmail.com>
 <20160510164712.56261bb4@bbrezillon>
Message-ID: <CACQ1gAj4xD1httj=gMKFCfeOnVjSKk+J-y_yZpCkTSiLeTAA4A@mail.gmail.com>

2016-05-10 16:47 GMT+02:00 Boris Brezillon <boris.brezillon at free-electrons.com>:
> Hi Richard,
>
> On Tue, 10 May 2016 16:25:25 +0200
> Richard Genoud <richard.genoud at gmail.com> wrote:
>
>> 2016-05-10 15:58 GMT+02:00 Richard Genoud <richard.genoud at gmail.com>:
>> > Hi,
>> >
>> > Starting with 4.6-rc1, a sleep 1 doesn't return :
>> >
>> > execve("/bin/sleep", ["sleep", "1"], ["USER=root", "SHLVL=1",
>> > "OLDPWD=/var", "HOME=/", "TERM=vt102",
>> > "PATH=/sbin:/usr/sbin:/bin:/usr/bin", "SHELL=/bin/sh", "PWD=/"]) = 0
>> > uname({sysname="Linux", nodename="LNS",
>> > release="4.5.0-09406-g46e595a17dcf", version="#72 Tue May 10 15:41:34
>> > CEST 2016", machine="armv5tejl", domainname="(none)"}) = 0
>> > brk(0)                                  = 0x153000
>> > brk(0x153d20)                           = 0x153d20
>> > set_tls(0x1534c0, 0x14d1e4, 0, 0x153d20, 0x14e368) = 0
>> > readlink("/proc/self/exe", "/bin/busybox", 4096) = 12
>> > brk(0x174d20)                           = 0x174d20
>> > brk(0x175000)                           = 0x175000
>> > getuid32()                              = 0
>> > rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
>> > rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
>> > rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
>> > nanosleep({1, 0},
>> >
>> > And the heartbeat led doesn't blink anymore (full on), as if the
>> > timers never fire.
>> >
>> > The platform is an AT91SAM9G35-CM.
>> >
>> > git bisect gives a merge as the 1st bad commit :(
>> > first bad commit: [46e595a17dcf11404f713845ecb5b06b92a94e43] Merge tag
>> > 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>
>>
>> I went a little further in tracking that down, starting from the merge
>> (1st bad commit) and reverting some commits.
>> It seems that the culprit is :
>> commit 863a81c3be1d931bdae6426e231add9334311f13
>> Author: Boris Brezillon <boris.brezillon at free-electrons.com>
>> Date:   Fri Sep 5 09:54:13 2014 +0200
>>     clk: at91: make use of syscon to share PMC registers in several drivers
>>
>> Here are the commits I've reverted :
>>
>> git log --oneline --decorate -20
>> 849cdaa0cf04 (HEAD, tag: good) Revert "clk: at91: make use of syscon
>> to share PMC registers in several drivers"
>> 4bd6dde95321 (tag: last_bad) Revert "clk: at91: make use of
>> syscon/regmap internally"
>> a56dacaa24c4 (tag: always_bad) Revert "clk: at91: remove IRQ handling
>> and use polling"
>> 33edfe7a2de6 Revert "clk: at91: pmc: merge at91_pmc_init in atmel_pmc_probe"
>> 0b22bb649eae Revert "clk: at91: pmc: move pmc structures to C file"
>> 14994fdff366 Revert "ARM: at91: pm: simply call at91_pm_init"
>> 6f0821175327 (tag: still_bad) Revert "ARM: at91: pm: find and remap the pmc"
>> b52bbf7fad1b Revert "ARM: at91: pm: move idle functions to pm.c"
>> dffb1a5f68b9 Revert "ARM: at91: remove useless includes and function prototypes"
>> db352691dcc1 Revert "usb: gadget: atmel: access the PMC using regmap"
>> f7b5433dbbc8 Revert "clk: at91: pmc: drop at91_pmc_base"
>> 6e6dfc0d91c0 Revert "clk: at91: pmc: remove useless capacities handling"
>> ceddd3f88ada Revert "clk: at91: remove useless includes"
>> 46e595a17dcf (tag: bad) Merge tag 'armsoc-drivers' of
>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>> e3b1f64e04f5 Merge tag 'armsoc-defconfig' of
>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>> 915c56bc01d6 Merge tag 'armsoc-dt64' of
>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>> 5a6b7e53d035 Merge tag 'armsoc-dt' of
>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>> 8c6d4082fc6a Merge tag 'armsoc-arm64' of
>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>> 33b3d2e88c9e Merge tag 'armsoc-soc' of
>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>> e88fa1b8b00a Merge tag 'armsoc-cleanup' of
>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>
> Thanks for the detailed report.
>
> Can you try again after applying this patch [1]?
>
> Regards,
>
> Boris
>
> [1]http://code.bulix.org/dx1c0t-98377

Yes, it works.
Big thumbs up, that was fast !

Less than 1 hour between the report and the patch ! :)

This is clearly 4.6 material (as it's a regression from 4.5), but it's
maybe a little late.
Anrd, Nicolas, what do you think ?


Thanks,
Richard.


From broonie at kernel.org  Tue May 10 08:08:22 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 10 May 2016 16:08:22 +0100
Subject: [PATCH 2/4] ARM: ux500: move ab8500_regulator_plat_data into
 driver
In-Reply-To: <1462888794-2793296-3-git-send-email-arnd@arndb.de>
References: <1462888794-2793296-1-git-send-email-arnd@arndb.de>
 <1462888794-2793296-3-git-send-email-arnd@arndb.de>
Message-ID: <20160510150822.GB6261@sirena.org.uk>

On Tue, May 10, 2016 at 03:59:48PM +0200, Arnd Bergmann wrote:
> There is only one instance of ab8500_regulator_platform_data, and it's
> safe to assume we won't ever merge another one, so it's rather pointless
> to pass it through multiple levels of platform data pointers.

I'm missing patches 1 and 4 in this series.  What's going on, especially
with regard to dependencies?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160510/50ab137a/attachment.sig>

From mmarek at suse.cz  Tue May 10 08:14:37 2016
From: mmarek at suse.cz (Michal Marek)
Date: Tue, 10 May 2016 17:14:37 +0200
Subject: [RESEND PATCH 0/5] gcov fixes and maybe-uninitialized warnings
In-Reply-To: <1461598531-2190169-1-git-send-email-arnd@arndb.de>
References: <1461598531-2190169-1-git-send-email-arnd@arndb.de>
Message-ID: <20160510151437.GA12889@pobox.suse.cz>

On Mon, Apr 25, 2016 at 05:35:26PM +0200, Arnd Bergmann wrote:
> Hi Michal,
> 
> This is a resend of a series I originally sent back in February, but
> unfortunately I never heard back from you. Could you apply these
> patches for v4.7?
> 
> [PATCH 1/5] Kbuild: change CC_OPTIMIZE_FOR_SIZE definition
> [PATCH 2/5] Kbuild: disable 'maybe-uninitialized' warning for
> [PATCH 3/5] gcov: disable for COMPILE_TEST
> [PATCH 4/5] gcov: disable tree-loop-im to reduce stack usage
> [PATCH 5/5] gcov: disable -Wmaybe-uninitialized warning

Applied now, sorry for the delay.

Michal


From nicolas.ferre at atmel.com  Tue May 10 08:18:57 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Tue, 10 May 2016 17:18:57 +0200
Subject: [BISECTED] Regression v4.6-rc1 : nanosleep doesn't return on
 AT91SAM9
In-Reply-To: <CACQ1gAj4xD1httj=gMKFCfeOnVjSKk+J-y_yZpCkTSiLeTAA4A@mail.gmail.com>
References: <CACQ1gAg6cKqjaqcV70m2VS5R4_kZEgWTiqzSqDxSjvfrYYxbzg@mail.gmail.com>
 <CACQ1gAipruXcO=xpooYDOdqZbtESD35wxDf7xNrg4zuuRv1wew@mail.gmail.com>
 <20160510164712.56261bb4@bbrezillon>
 <CACQ1gAj4xD1httj=gMKFCfeOnVjSKk+J-y_yZpCkTSiLeTAA4A@mail.gmail.com>
Message-ID: <5731FBE1.2090202@atmel.com>

Le 10/05/2016 16:59, Richard Genoud a ?crit :
> 2016-05-10 16:47 GMT+02:00 Boris Brezillon <boris.brezillon at free-electrons.com>:
>> Hi Richard,
>>
>> On Tue, 10 May 2016 16:25:25 +0200
>> Richard Genoud <richard.genoud at gmail.com> wrote:
>>
>>> 2016-05-10 15:58 GMT+02:00 Richard Genoud <richard.genoud at gmail.com>:
>>>> Hi,
>>>>
>>>> Starting with 4.6-rc1, a sleep 1 doesn't return :
>>>>
>>>> execve("/bin/sleep", ["sleep", "1"], ["USER=root", "SHLVL=1",
>>>> "OLDPWD=/var", "HOME=/", "TERM=vt102",
>>>> "PATH=/sbin:/usr/sbin:/bin:/usr/bin", "SHELL=/bin/sh", "PWD=/"]) = 0
>>>> uname({sysname="Linux", nodename="LNS",
>>>> release="4.5.0-09406-g46e595a17dcf", version="#72 Tue May 10 15:41:34
>>>> CEST 2016", machine="armv5tejl", domainname="(none)"}) = 0
>>>> brk(0)                                  = 0x153000
>>>> brk(0x153d20)                           = 0x153d20
>>>> set_tls(0x1534c0, 0x14d1e4, 0, 0x153d20, 0x14e368) = 0
>>>> readlink("/proc/self/exe", "/bin/busybox", 4096) = 12
>>>> brk(0x174d20)                           = 0x174d20
>>>> brk(0x175000)                           = 0x175000
>>>> getuid32()                              = 0
>>>> rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
>>>> rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
>>>> rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
>>>> nanosleep({1, 0},
>>>>
>>>> And the heartbeat led doesn't blink anymore (full on), as if the
>>>> timers never fire.
>>>>
>>>> The platform is an AT91SAM9G35-CM.
>>>>
>>>> git bisect gives a merge as the 1st bad commit :(
>>>> first bad commit: [46e595a17dcf11404f713845ecb5b06b92a94e43] Merge tag
>>>> 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>
>>>
>>> I went a little further in tracking that down, starting from the merge
>>> (1st bad commit) and reverting some commits.
>>> It seems that the culprit is :
>>> commit 863a81c3be1d931bdae6426e231add9334311f13
>>> Author: Boris Brezillon <boris.brezillon at free-electrons.com>
>>> Date:   Fri Sep 5 09:54:13 2014 +0200
>>>     clk: at91: make use of syscon to share PMC registers in several drivers
>>>
>>> Here are the commits I've reverted :
>>>
>>> git log --oneline --decorate -20
>>> 849cdaa0cf04 (HEAD, tag: good) Revert "clk: at91: make use of syscon
>>> to share PMC registers in several drivers"
>>> 4bd6dde95321 (tag: last_bad) Revert "clk: at91: make use of
>>> syscon/regmap internally"
>>> a56dacaa24c4 (tag: always_bad) Revert "clk: at91: remove IRQ handling
>>> and use polling"
>>> 33edfe7a2de6 Revert "clk: at91: pmc: merge at91_pmc_init in atmel_pmc_probe"
>>> 0b22bb649eae Revert "clk: at91: pmc: move pmc structures to C file"
>>> 14994fdff366 Revert "ARM: at91: pm: simply call at91_pm_init"
>>> 6f0821175327 (tag: still_bad) Revert "ARM: at91: pm: find and remap the pmc"
>>> b52bbf7fad1b Revert "ARM: at91: pm: move idle functions to pm.c"
>>> dffb1a5f68b9 Revert "ARM: at91: remove useless includes and function prototypes"
>>> db352691dcc1 Revert "usb: gadget: atmel: access the PMC using regmap"
>>> f7b5433dbbc8 Revert "clk: at91: pmc: drop at91_pmc_base"
>>> 6e6dfc0d91c0 Revert "clk: at91: pmc: remove useless capacities handling"
>>> ceddd3f88ada Revert "clk: at91: remove useless includes"
>>> 46e595a17dcf (tag: bad) Merge tag 'armsoc-drivers' of
>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>> e3b1f64e04f5 Merge tag 'armsoc-defconfig' of
>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>> 915c56bc01d6 Merge tag 'armsoc-dt64' of
>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>> 5a6b7e53d035 Merge tag 'armsoc-dt' of
>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>> 8c6d4082fc6a Merge tag 'armsoc-arm64' of
>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>> 33b3d2e88c9e Merge tag 'armsoc-soc' of
>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>> e88fa1b8b00a Merge tag 'armsoc-cleanup' of
>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>
>> Thanks for the detailed report.
>>
>> Can you try again after applying this patch [1]?
>>
>> Regards,
>>
>> Boris
>>
>> [1]http://code.bulix.org/dx1c0t-98377
> 
> Yes, it works.
> Big thumbs up, that was fast !
> 
> Less than 1 hour between the report and the patch ! :)

Yes, absolutely terrific! Thanks Boris.

I'd like you to test with this instead as it's the real range of the IP:
+ reg = <0xfffffc00 0x110>;

Even I'm pretty confident ;-) Can you please do this for us ?

> This is clearly 4.6 material (as it's a regression from 4.5), but it's
> maybe a little late.
> Anrd, Nicolas, what do you think ?

I sent a PR this morning to Arnd with a "fix"... I hope that he won't be
annoyed if I send him another one this evening...  But clearly, it's a
regression and a pretty bad one :-\

Thanks a lot for this report Richard,
-- 
Nicolas Ferre


From tn at semihalf.com  Tue May 10 08:19:51 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 10 May 2016 17:19:51 +0200
Subject: [PATCH V7 01/11] PCI: Provide common functions for ECAM mapping
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <1462893601-8937-2-git-send-email-tn@semihalf.com>

From: Jayachandran C <jchandra at broadcom.com>

Add config option PCI_ECAM and file drivers/pci/ecam.c to provide
generic functions for accessing memory mapped PCI config space.

The API is defined in drivers/pci/ecam.h and is written to replace the
API in drivers/pci/host/pci-host-common.h. The file defines a new
'struct pci_config_window' to hold the information related to a PCI
config area and its mapping. This structure is expected to be used as
sysdata for controllers that have ECAM based mapping.

Helper functions are provided to setup the mapping, free the mapping
and to implement the map_bus method in 'struct pci_ops'

Signed-off-by: Jayachandran C <jchandra at broadcom.com>
---
 drivers/pci/Kconfig  |   3 +
 drivers/pci/Makefile |   2 +
 drivers/pci/ecam.c   | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/pci/ecam.h   |  62 ++++++++++++++++++++
 4 files changed, 228 insertions(+)
 create mode 100644 drivers/pci/ecam.c
 create mode 100644 drivers/pci/ecam.h

diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 209292e..56389be 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -83,6 +83,9 @@ config HT_IRQ
 config PCI_ATS
 	bool
 
+config PCI_ECAM
+	bool
+
 config PCI_IOV
 	bool "PCI IOV support"
 	depends on PCI
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 2154092..1fa6925 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -55,6 +55,8 @@ obj-$(CONFIG_PCI_SYSCALL) += syscall.o
 
 obj-$(CONFIG_PCI_STUB) += pci-stub.o
 
+obj-$(CONFIG_PCI_ECAM) += ecam.o
+
 obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
 
 obj-$(CONFIG_OF) += of.o
diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
new file mode 100644
index 0000000..3d52005
--- /dev/null
+++ b/drivers/pci/ecam.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2016 Broadcom
+ *
+ * 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 (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "ecam.h"
+
+/*
+ * On 64 bit systems, we do a single ioremap for the whole config space
+ * since we have enough virtual address range available. On 32 bit, do an
+ * ioremap per bus.
+ */
+static const bool per_bus_mapping = !config_enabled(CONFIG_64BIT);
+
+/*
+ * Create a PCI config space window
+ *  - reserve mem region
+ *  - alloc struct pci_config_window with space for all mappings
+ *  - ioremap the config space
+ */
+struct pci_config_window *pci_ecam_create(struct device *dev,
+		struct resource *cfgres, struct resource *busr,
+		struct pci_ecam_ops *ops)
+{
+	struct pci_config_window *cfg;
+	unsigned int bus_range, bus_range_max, bsz;
+	int i, err;
+
+	if (busr->start > busr->end)
+		return ERR_PTR(-EINVAL);
+
+	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+	if (!cfg)
+		return ERR_PTR(-ENOMEM);
+
+	cfg->ops = ops;
+	cfg->busr.start = busr->start;
+	cfg->busr.end = busr->end;
+	cfg->busr.flags = IORESOURCE_BUS;
+	bus_range = resource_size(&cfg->busr);
+	bus_range_max = resource_size(cfgres) >> ops->bus_shift;
+	if (bus_range > bus_range_max) {
+		dev_warn(dev, "bus max %#x reduced to %#x",
+					bus_range, bus_range_max);
+		bus_range = bus_range_max;
+		cfg->busr.end = busr->start + bus_range - 1;
+	}
+	bsz = 1 << ops->bus_shift;
+
+	cfg->res.start = cfgres->start;
+	cfg->res.end = cfgres->end;
+	cfg->res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	cfg->res.name = "PCI ECAM";
+
+	err = request_resource(&iomem_resource, &cfg->res);
+	if (err) {
+		dev_err(dev, "request ECAM res %pR failed\n", &cfg->res);
+		goto err_exit;
+	}
+
+	if (per_bus_mapping) {
+		cfg->winp = kcalloc(bus_range, sizeof(*cfg->winp), GFP_KERNEL);
+		if (!cfg->winp)
+			goto err_exit_malloc;
+		for (i = 0; i < bus_range; i++) {
+			cfg->winp[i] = ioremap(cfgres->start + i * bsz, bsz);
+			if (!cfg->winp[i])
+				goto err_exit_iomap;
+		}
+	} else {
+		cfg->win = ioremap(cfgres->start, bus_range * bsz);
+		if (!cfg->win)
+			goto err_exit_iomap;
+	}
+
+	if (ops->init) {
+		err = ops->init(dev, cfg);
+		if (err)
+			goto err_exit;
+	}
+	dev_info(dev, "ECAM at %pR for %pR\n", &cfg->res, &cfg->busr);
+	return cfg;
+
+err_exit_iomap:
+	dev_err(dev, "ECAM ioremap failed\n");
+err_exit_malloc:
+	err = -ENOMEM;
+err_exit:
+	pci_ecam_free(cfg);
+	return ERR_PTR(err);
+}
+
+void pci_ecam_free(struct pci_config_window *cfg)
+{
+	int i;
+
+	if (per_bus_mapping) {
+		if (cfg->winp) {
+			for (i = 0; i < resource_size(&cfg->busr); i++)
+				if (cfg->winp[i])
+					iounmap(cfg->winp[i]);
+			kfree(cfg->winp);
+		}
+	} else {
+		if (cfg->win)
+			iounmap(cfg->win);
+	}
+	if (cfg->res.parent)
+		release_resource(&cfg->res);
+	kfree(cfg);
+}
+
+/*
+ * Function to implement the pci_ops ->map_bus method
+ */
+void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
+			       int where)
+{
+	struct pci_config_window *cfg = bus->sysdata;
+	unsigned int devfn_shift = cfg->ops->bus_shift - 8;
+	unsigned int busn = bus->number;
+	void __iomem *base;
+
+	if (busn < cfg->busr.start || busn > cfg->busr.end)
+		return NULL;
+
+	busn -= cfg->busr.start;
+	if (per_bus_mapping)
+		base = cfg->winp[busn];
+	else
+		base = cfg->win + (busn << cfg->ops->bus_shift);
+	return base + (devfn << devfn_shift) + where;
+}
+
+/* ECAM ops */
+struct pci_ecam_ops pci_generic_ecam_ops = {
+	.bus_shift	= 20,
+	.pci_ops	= {
+		.map_bus	= pci_ecam_map_bus,
+		.read		= pci_generic_config_read,
+		.write		= pci_generic_config_write,
+	}
+};
diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
new file mode 100644
index 0000000..57de00d
--- /dev/null
+++ b/drivers/pci/ecam.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016 Broadcom
+ *
+ * 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 (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+#ifndef DRIVERS_PCI_ECAM_H
+#define DRIVERS_PCI_ECAM_H
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+/*
+ * struct to hold pci ops and bus shift of the config window
+ * for a PCI controller.
+ */
+struct pci_config_window;
+struct pci_ecam_ops {
+	unsigned int			bus_shift;
+	struct pci_ops			pci_ops;
+	int				(*init)(struct device *,
+						struct pci_config_window *);
+};
+
+/*
+ * struct to hold the mappings of a config space window. This
+ * is expected to be used as sysdata for PCI controlllers which
+ * use ECAM.
+ */
+struct pci_config_window {
+	struct resource			res;
+	struct resource			busr;
+	void				*priv;
+	struct pci_ecam_ops		*ops;
+	union {
+		void __iomem		*win;	/* 64-bit single mapping */
+		void __iomem		**winp; /* 32-bit per bus mapping */
+	};
+};
+
+/* create and free for pci_config_window */
+struct pci_config_window *pci_ecam_create(struct device *dev,
+		struct resource *cfgres, struct resource *busr,
+		struct pci_ecam_ops *ops);
+void pci_ecam_free(struct pci_config_window *cfg);
+
+/* map_bus when ->sysdata is an instance of pci_config_window */
+void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
+			       int where);
+/* default ECAM ops, bus shift 20, generic read and write */
+extern struct pci_ecam_ops pci_generic_ecam_ops;
+
+#endif
-- 
1.9.1



From tn at semihalf.com  Tue May 10 08:19:50 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 10 May 2016 17:19:50 +0200
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host controller
Message-ID: <1462893601-8937-1-git-send-email-tn@semihalf.com>

>From the functionality point of view this series may be split into the
following logic parts:
1. New ECAM API and update for users of the pci-host-common API
2. Necessary fixes as the preparation for using driver on ARM64.
3. Use new MCFG interface and implement generic ACPI based PCI host controller driver.
4. Enable above driver on ARM64

Patches has been built on top of 4.6-rc7 and can be found here:
git at github.com:semihalf-nowicki-tomasz/linux.git (pci-acpi-v7)

This has been tested on Cavium ThunderX server. Any help in reviewing and
testing is very appreciated.

v6 -> v7
- drop quirks handling
- changes for ACPI companion and domain number assignment approach
- implement arch pcibios_{add|remove}_bus and call acpi_pci_{add|remove}_bus from there
- cleanups around nomenclature
- use resources oriented API for ECAM
- fix for based address calculation before mapping ECAM region
- remove useless lock for MCFG lookup
- move MCFG stuff to separated file pci_mcfg.c
- drop MCFG entries caching
- rebase against 4.6-rc7

v5 -> v6
- drop idea of x86 MMCONFIG code refactoring
- integrate JC's patches which introduce new ECAM API:
  https://lkml.org/lkml/2016/4/11/907
  git: https://github.com/jchandra-brcm/linux/ (arm64-acpi-pci-v3)
- integrate Sinan's fix for releasing IO resources, see patch [06/13]
- added ACPI support for ThunderX ECAM and PEM drivers
- rebase against 4.6-rc2

v4 -> v5
- drop MCFG refactoring group patches 1-6 from series v4 and integrate Jayachandran's patch
  https://patchwork.ozlabs.org/patch/575525/
- rewrite PCI legacy IRQs allocation
- squash two patches 11 and 12 from series v4, fixed bisection issue
- changelog improvements
- rebase against 4.5-rc3

v3 -> v4
- drop Jiang's fix http://lkml.iu.edu/hypermail/linux/kernel/1601.1/04318.html
- add Lorenzo's fix patch 19/24
- ACPI PCI bus domain number assigning cleanup
- change resource management, we now claim and reassign resources
- improvements for applying quirks
- drop Matthew's http://www.spinics.net/lists/linux-pci/msg45950.html dependency
- rebase against 4.5-rc1

v2 -> v3
- fix legacy IRQ assigning and IO ports registration
- remove reference to arch specific companion device for ia64
- move ACPI PCI host controller driver to pci_root.c
- drop generic domain assignment for x86 and ia64 as I am not
  able to run all necessary test variants
- drop patch which cleaned legacy IRQ assignment since it belongs to
  Mathew's series:
  https://patchwork.ozlabs.org/patch/557504/
- extend MCFG quirk code
- rebase against 4.4

v1 -> v2
- move non-arch specific piece of code to dirver/acpi/ directory
- fix IO resource handling
- introduce PCI config accessors quirks matching
- moved ACPI_COMPANION_SET to generic code

v1 - https://lkml.org/lkml/2015/10/27/504
v2 - https://lkml.org/lkml/2015/12/16/246
v3 - http://lkml.iu.edu/hypermail/linux/kernel/1601.1/04308.html
v4 - https://lkml.org/lkml/2016/2/4/646
v5 - https://lkml.org/lkml/2016/2/16/426
v6 - https://lkml.org/lkml/2016/4/15/594

Jayachandran C (2):
  PCI: Provide common functions for ECAM mapping
  PCI: generic, thunder: update to use generic ECAM API

Tomasz Nowicki (9):
  pci, of: Move the PCI I/O space management to PCI core code.
  pci: Add new function to unmap IO resources.
  acpi, pci: Support IO resources when parsing PCI host bridge
    resources.
  pci, acpi: Provide a way to assign bus domain number.
  pci, acpi: Handle ACPI companion assignment.
  pci, acpi: Support for ACPI based generic PCI host controller
  arm64, pci, acpi: ACPI support for legacy IRQs parsing and
    consolidation with DT code.
  arm64, pci, acpi: Provide ACPI-specific prerequisites for PCI bus
    enumeration.
  arm64, pci, acpi: Start using ACPI based PCI host controller driver
    for ARM64.

 arch/arm64/Kconfig                  |   1 +
 arch/arm64/kernel/pci.c             |  34 +++-----
 drivers/acpi/Kconfig                |   8 ++
 drivers/acpi/Makefile               |   1 +
 drivers/acpi/pci_mcfg.c             |  97 ++++++++++++++++++++++
 drivers/acpi/pci_root.c             |  33 ++++++++
 drivers/acpi/pci_root_generic.c     | 149 +++++++++++++++++++++++++++++++++
 drivers/of/address.c                | 116 +-------------------------
 drivers/pci/Kconfig                 |   3 +
 drivers/pci/Makefile                |   2 +
 drivers/pci/ecam.c                  | 161 ++++++++++++++++++++++++++++++++++++
 drivers/pci/ecam.h                  |  72 ++++++++++++++++
 drivers/pci/host/Kconfig            |   1 +
 drivers/pci/host/pci-host-common.c  | 114 +++++++++++--------------
 drivers/pci/host/pci-host-common.h  |  47 -----------
 drivers/pci/host/pci-host-generic.c |  52 +++---------
 drivers/pci/host/pci-thunder-ecam.c |  39 ++-------
 drivers/pci/host/pci-thunder-pem.c  |  92 ++++++++++-----------
 drivers/pci/pci.c                   | 150 ++++++++++++++++++++++++++++++++-
 drivers/pci/probe.c                 |   2 +
 include/linux/of_address.h          |   9 --
 include/linux/pci-acpi.h            |  14 ++++
 include/linux/pci.h                 |  11 ++-
 23 files changed, 823 insertions(+), 385 deletions(-)
 create mode 100644 drivers/acpi/pci_mcfg.c
 create mode 100644 drivers/acpi/pci_root_generic.c
 create mode 100644 drivers/pci/ecam.c
 create mode 100644 drivers/pci/ecam.h
 delete mode 100644 drivers/pci/host/pci-host-common.h

-- 
1.9.1



From tn at semihalf.com  Tue May 10 08:19:53 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 10 May 2016 17:19:53 +0200
Subject: [PATCH V7 03/11] pci,
 of: Move the PCI I/O space management to PCI core code.
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <1462893601-8937-4-git-send-email-tn@semihalf.com>

No functional changes in this patch.

PCI I/O space mapping code does not depend on OF, therefore it can be
moved to PCI core code. This way we will be able to use it
e.g. in ACPI PCI code.

Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
CC: Arnd Bergmann <arnd at arndb.de>
CC: Liviu Dudau <Liviu.Dudau at arm.com>
---
 drivers/of/address.c       | 116 +--------------------------------------------
 drivers/pci/pci.c          | 115 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of_address.h |   9 ----
 include/linux/pci.h        |   5 ++
 4 files changed, 121 insertions(+), 124 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 91a469d..0a553c0 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -4,6 +4,7 @@
 #include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
+#include <linux/pci.h>
 #include <linux/pci_regs.h>
 #include <linux/sizes.h>
 #include <linux/slab.h>
@@ -673,121 +674,6 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
-#ifdef PCI_IOBASE
-struct io_range {
-	struct list_head list;
-	phys_addr_t start;
-	resource_size_t size;
-};
-
-static LIST_HEAD(io_range_list);
-static DEFINE_SPINLOCK(io_range_lock);
-#endif
-
-/*
- * Record the PCI IO range (expressed as CPU physical address + size).
- * Return a negative value if an error has occured, zero otherwise
- */
-int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
-{
-	int err = 0;
-
-#ifdef PCI_IOBASE
-	struct io_range *range;
-	resource_size_t allocated_size = 0;
-
-	/* check if the range hasn't been previously recorded */
-	spin_lock(&io_range_lock);
-	list_for_each_entry(range, &io_range_list, list) {
-		if (addr >= range->start && addr + size <= range->start + size) {
-			/* range already registered, bail out */
-			goto end_register;
-		}
-		allocated_size += range->size;
-	}
-
-	/* range not registed yet, check for available space */
-	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
-		/* if it's too big check if 64K space can be reserved */
-		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
-			err = -E2BIG;
-			goto end_register;
-		}
-
-		size = SZ_64K;
-		pr_warn("Requested IO range too big, new size set to 64K\n");
-	}
-
-	/* add the range to the list */
-	range = kzalloc(sizeof(*range), GFP_ATOMIC);
-	if (!range) {
-		err = -ENOMEM;
-		goto end_register;
-	}
-
-	range->start = addr;
-	range->size = size;
-
-	list_add_tail(&range->list, &io_range_list);
-
-end_register:
-	spin_unlock(&io_range_lock);
-#endif
-
-	return err;
-}
-
-phys_addr_t pci_pio_to_address(unsigned long pio)
-{
-	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
-
-#ifdef PCI_IOBASE
-	struct io_range *range;
-	resource_size_t allocated_size = 0;
-
-	if (pio > IO_SPACE_LIMIT)
-		return address;
-
-	spin_lock(&io_range_lock);
-	list_for_each_entry(range, &io_range_list, list) {
-		if (pio >= allocated_size && pio < allocated_size + range->size) {
-			address = range->start + pio - allocated_size;
-			break;
-		}
-		allocated_size += range->size;
-	}
-	spin_unlock(&io_range_lock);
-#endif
-
-	return address;
-}
-
-unsigned long __weak pci_address_to_pio(phys_addr_t address)
-{
-#ifdef PCI_IOBASE
-	struct io_range *res;
-	resource_size_t offset = 0;
-	unsigned long addr = -1;
-
-	spin_lock(&io_range_lock);
-	list_for_each_entry(res, &io_range_list, list) {
-		if (address >= res->start && address < res->start + res->size) {
-			addr = address - res->start + offset;
-			break;
-		}
-		offset += res->size;
-	}
-	spin_unlock(&io_range_lock);
-
-	return addr;
-#else
-	if (address > IO_SPACE_LIMIT)
-		return (unsigned long)-1;
-
-	return (unsigned long) address;
-#endif
-}
-
 static int __of_address_to_resource(struct device_node *dev,
 		const __be32 *addrp, u64 size, unsigned int flags,
 		const char *name, struct resource *r)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 25e0327..bc0c914 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3021,6 +3021,121 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
 }
 EXPORT_SYMBOL(pci_request_regions_exclusive);
 
+#ifdef PCI_IOBASE
+struct io_range {
+	struct list_head list;
+	phys_addr_t start;
+	resource_size_t size;
+};
+
+static LIST_HEAD(io_range_list);
+static DEFINE_SPINLOCK(io_range_lock);
+#endif
+
+/*
+ * Record the PCI IO range (expressed as CPU physical address + size).
+ * Return a negative value if an error has occured, zero otherwise
+ */
+int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
+{
+	int err = 0;
+
+#ifdef PCI_IOBASE
+	struct io_range *range;
+	resource_size_t allocated_size = 0;
+
+	/* check if the range hasn't been previously recorded */
+	spin_lock(&io_range_lock);
+	list_for_each_entry(range, &io_range_list, list) {
+		if (addr >= range->start && addr + size <= range->start + size) {
+			/* range already registered, bail out */
+			goto end_register;
+		}
+		allocated_size += range->size;
+	}
+
+	/* range not registed yet, check for available space */
+	if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
+		/* if it's too big check if 64K space can be reserved */
+		if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
+			err = -E2BIG;
+			goto end_register;
+		}
+
+		size = SZ_64K;
+		pr_warn("Requested IO range too big, new size set to 64K\n");
+	}
+
+	/* add the range to the list */
+	range = kzalloc(sizeof(*range), GFP_ATOMIC);
+	if (!range) {
+		err = -ENOMEM;
+		goto end_register;
+	}
+
+	range->start = addr;
+	range->size = size;
+
+	list_add_tail(&range->list, &io_range_list);
+
+end_register:
+	spin_unlock(&io_range_lock);
+#endif
+
+	return err;
+}
+
+phys_addr_t pci_pio_to_address(unsigned long pio)
+{
+	phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
+
+#ifdef PCI_IOBASE
+	struct io_range *range;
+	resource_size_t allocated_size = 0;
+
+	if (pio > IO_SPACE_LIMIT)
+		return address;
+
+	spin_lock(&io_range_lock);
+	list_for_each_entry(range, &io_range_list, list) {
+		if (pio >= allocated_size && pio < allocated_size + range->size) {
+			address = range->start + pio - allocated_size;
+			break;
+		}
+		allocated_size += range->size;
+	}
+	spin_unlock(&io_range_lock);
+#endif
+
+	return address;
+}
+
+unsigned long __weak pci_address_to_pio(phys_addr_t address)
+{
+#ifdef PCI_IOBASE
+	struct io_range *res;
+	resource_size_t offset = 0;
+	unsigned long addr = -1;
+
+	spin_lock(&io_range_lock);
+	list_for_each_entry(res, &io_range_list, list) {
+		if (address >= res->start && address < res->start + res->size) {
+			addr = address - res->start + offset;
+			break;
+		}
+		offset += res->size;
+	}
+	spin_unlock(&io_range_lock);
+
+	return addr;
+#else
+	if (address > IO_SPACE_LIMIT)
+		return (unsigned long)-1;
+
+	return (unsigned long) address;
+#endif
+}
+
 /**
  *	pci_remap_iospace - Remap the memory mapped I/O space
  *	@res: Resource describing the I/O space
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 01c0a55..3786473 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -47,10 +47,6 @@ void __iomem *of_io_request_and_map(struct device_node *device,
 extern const __be32 *of_get_address(struct device_node *dev, int index,
 			   u64 *size, unsigned int *flags);
 
-extern int pci_register_io_range(phys_addr_t addr, resource_size_t size);
-extern unsigned long pci_address_to_pio(phys_addr_t addr);
-extern phys_addr_t pci_pio_to_address(unsigned long pio);
-
 extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
 			struct device_node *node);
 extern struct of_pci_range *of_pci_range_parser_one(
@@ -86,11 +82,6 @@ static inline const __be32 *of_get_address(struct device_node *dev, int index,
 	return NULL;
 }
 
-static inline phys_addr_t pci_pio_to_address(unsigned long pio)
-{
-	return 0;
-}
-
 static inline int of_pci_range_parser_init(struct of_pci_range_parser *parser,
 			struct device_node *node)
 {
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 932ec74..d2a57f3 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1165,6 +1165,9 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
 			void *alignf_data);
 
 
+int pci_register_io_range(phys_addr_t addr, resource_size_t size);
+unsigned long pci_address_to_pio(phys_addr_t addr);
+phys_addr_t pci_pio_to_address(unsigned long pio);
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
 
 static inline pci_bus_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
@@ -1481,6 +1484,8 @@ static inline int pci_request_regions(struct pci_dev *dev, const char *res_name)
 { return -EIO; }
 static inline void pci_release_regions(struct pci_dev *dev) { }
 
+static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
+
 static inline void pci_block_cfg_access(struct pci_dev *dev) { }
 static inline int pci_block_cfg_access_in_atomic(struct pci_dev *dev)
 { return 0; }
-- 
1.9.1



From tn at semihalf.com  Tue May 10 08:19:52 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 10 May 2016 17:19:52 +0200
Subject: [PATCH V7 02/11] PCI: generic, thunder: update to use generic ECAM API
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <1462893601-8937-3-git-send-email-tn@semihalf.com>

From: Jayachandran C <jchandra at broadcom.com>

Use functions provided by drivers/pci/ecam.h for mapping the config
space in drivers/pci/host/pci-host-common.c, and update its users to
use 'struct pci_config_window' and 'struct pci_ecam_ops'

The changes are mostly to use 'struct pci_config_window' in place of
'struct gen_pci'. Some of the fields of gen_pci were only used
temporarily and can be eliminated by using local variables or function
arguments, these are not carried over to struct pci_config_window.

pci-thunder-ecam.c and pci-thunder-pem.c are the only users of the
pci_host_common_probe function and the gen_pci structure, these have
been updated to use the new API as well.

The patch does not introduce any functional changes other than a very
minor one: with the new code, on 64-bit platforms, we do just a single
ioremap for the whole config space.

Signed-off-by: Jayachandran C <jchandra at broadcom.com>
---
 drivers/pci/ecam.h                  |   5 ++
 drivers/pci/host/Kconfig            |   1 +
 drivers/pci/host/pci-host-common.c  | 114 +++++++++++++++---------------------
 drivers/pci/host/pci-host-common.h  |  47 ---------------
 drivers/pci/host/pci-host-generic.c |  52 ++++------------
 drivers/pci/host/pci-thunder-ecam.c |  39 +++---------
 drivers/pci/host/pci-thunder-pem.c  |  92 ++++++++++++++---------------
 7 files changed, 113 insertions(+), 237 deletions(-)
 delete mode 100644 drivers/pci/host/pci-host-common.h

diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
index 57de00d..1ad2176 100644
--- a/drivers/pci/ecam.h
+++ b/drivers/pci/ecam.h
@@ -59,4 +59,9 @@ void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
 /* default ECAM ops, bus shift 20, generic read and write */
 extern struct pci_ecam_ops pci_generic_ecam_ops;
 
+#ifdef CONFIG_PCI_HOST_GENERIC
+/* for DT based pci controllers that support ECAM */
+int pci_host_common_probe(struct platform_device *pdev,
+			  struct pci_ecam_ops *ops);
+#endif
 #endif
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 7a0780d..963300d 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -77,6 +77,7 @@ config PCI_RCAR_GEN2_PCIE
 
 config PCI_HOST_COMMON
 	bool
+	select PCI_ECAM
 
 config PCI_HOST_GENERIC
 	bool "Generic PCI host controller"
diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c
index e9f850f..8cba7ab 100644
--- a/drivers/pci/host/pci-host-common.c
+++ b/drivers/pci/host/pci-host-common.c
@@ -22,27 +22,21 @@
 #include <linux/of_pci.h>
 #include <linux/platform_device.h>
 
-#include "pci-host-common.h"
+#include "../ecam.h"
 
-static void gen_pci_release_of_pci_ranges(struct gen_pci *pci)
-{
-	pci_free_resource_list(&pci->resources);
-}
-
-static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci)
+static int gen_pci_parse_request_of_pci_ranges(struct device *dev,
+		       struct list_head *resources, struct resource **bus_range)
 {
 	int err, res_valid = 0;
-	struct device *dev = pci->host.dev.parent;
 	struct device_node *np = dev->of_node;
 	resource_size_t iobase;
 	struct resource_entry *win;
 
-	err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources,
-					       &iobase);
+	err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase);
 	if (err)
 		return err;
 
-	resource_list_for_each_entry(win, &pci->resources) {
+	resource_list_for_each_entry(win, resources) {
 		struct resource *parent, *res = win->res;
 
 		switch (resource_type(res)) {
@@ -60,7 +54,7 @@ static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci)
 			res_valid |= !(res->flags & IORESOURCE_PREFETCH);
 			break;
 		case IORESOURCE_BUS:
-			pci->cfg.bus_range = res;
+			*bus_range = res;
 		default:
 			continue;
 		}
@@ -79,65 +73,60 @@ static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci)
 	return 0;
 
 out_release_res:
-	gen_pci_release_of_pci_ranges(pci);
 	return err;
 }
 
-static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
+static void gen_pci_unmap_cfg(void *ptr)
+{
+	pci_ecam_free((struct pci_config_window *)ptr);
+}
+
+static struct pci_config_window *gen_pci_init(struct device *dev,
+		struct list_head *resources, struct pci_ecam_ops *ops)
 {
 	int err;
-	u8 bus_max;
-	resource_size_t busn;
-	struct resource *bus_range;
-	struct device *dev = pci->host.dev.parent;
-	struct device_node *np = dev->of_node;
-	u32 sz = 1 << pci->cfg.ops->bus_shift;
+	struct resource cfgres;
+	struct resource *bus_range = NULL;
+	struct pci_config_window *cfg;
 
-	err = of_address_to_resource(np, 0, &pci->cfg.res);
+	/* Parse our PCI ranges and request their resources */
+	err = gen_pci_parse_request_of_pci_ranges(dev, resources, &bus_range);
+	if (err)
+		goto err_out;
+
+	err = of_address_to_resource(dev->of_node, 0, &cfgres);
 	if (err) {
 		dev_err(dev, "missing \"reg\" property\n");
-		return err;
+		goto err_out;
 	}
 
-	/* Limit the bus-range to fit within reg */
-	bus_max = pci->cfg.bus_range->start +
-		  (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1;
-	pci->cfg.bus_range->end = min_t(resource_size_t,
-					pci->cfg.bus_range->end, bus_max);
-
-	pci->cfg.win = devm_kcalloc(dev, resource_size(pci->cfg.bus_range),
-				    sizeof(*pci->cfg.win), GFP_KERNEL);
-	if (!pci->cfg.win)
-		return -ENOMEM;
-
-	/* Map our Configuration Space windows */
-	if (!devm_request_mem_region(dev, pci->cfg.res.start,
-				     resource_size(&pci->cfg.res),
-				     "Configuration Space"))
-		return -ENOMEM;
-
-	bus_range = pci->cfg.bus_range;
-	for (busn = bus_range->start; busn <= bus_range->end; ++busn) {
-		u32 idx = busn - bus_range->start;
-
-		pci->cfg.win[idx] = devm_ioremap(dev,
-						 pci->cfg.res.start + idx * sz,
-						 sz);
-		if (!pci->cfg.win[idx])
-			return -ENOMEM;
+	cfg = pci_ecam_create(dev, &cfgres, bus_range, ops);
+	if (IS_ERR(cfg)) {
+		err = PTR_ERR(cfg);
+		goto err_out;
 	}
 
-	return 0;
+	err = devm_add_action(dev, gen_pci_unmap_cfg, cfg);
+	if (err) {
+		gen_pci_unmap_cfg(cfg);
+		goto err_out;
+	}
+	return cfg;
+
+err_out:
+	pci_free_resource_list(resources);
+	return ERR_PTR(err);
 }
 
 int pci_host_common_probe(struct platform_device *pdev,
-			  struct gen_pci *pci)
+			  struct pci_ecam_ops *ops)
 {
-	int err;
 	const char *type;
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
 	struct pci_bus *bus, *child;
+	struct pci_config_window *cfg;
+	struct list_head resources;
 
 	type = of_get_property(np, "device_type", NULL);
 	if (!type || strcmp(type, "pci")) {
@@ -147,29 +136,18 @@ int pci_host_common_probe(struct platform_device *pdev,
 
 	of_pci_check_probe_only();
 
-	pci->host.dev.parent = dev;
-	INIT_LIST_HEAD(&pci->host.windows);
-	INIT_LIST_HEAD(&pci->resources);
-
-	/* Parse our PCI ranges and request their resources */
-	err = gen_pci_parse_request_of_pci_ranges(pci);
-	if (err)
-		return err;
-
 	/* Parse and map our Configuration Space windows */
-	err = gen_pci_parse_map_cfg_windows(pci);
-	if (err) {
-		gen_pci_release_of_pci_ranges(pci);
-		return err;
-	}
+	INIT_LIST_HEAD(&resources);
+	cfg = gen_pci_init(dev, &resources, ops);
+	if (IS_ERR(cfg))
+		return PTR_ERR(cfg);
 
 	/* Do not reassign resources if probe only */
 	if (!pci_has_flag(PCI_PROBE_ONLY))
 		pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
 
-
-	bus = pci_scan_root_bus(dev, pci->cfg.bus_range->start,
-				&pci->cfg.ops->ops, pci, &pci->resources);
+	bus = pci_scan_root_bus(dev, cfg->busr.start, &ops->pci_ops, cfg,
+				&resources);
 	if (!bus) {
 		dev_err(dev, "Scanning rootbus failed");
 		return -ENODEV;
diff --git a/drivers/pci/host/pci-host-common.h b/drivers/pci/host/pci-host-common.h
deleted file mode 100644
index 09f3fa0..0000000
--- a/drivers/pci/host/pci-host-common.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * Copyright (C) 2014 ARM Limited
- *
- * Author: Will Deacon <will.deacon at arm.com>
- */
-
-#ifndef _PCI_HOST_COMMON_H
-#define _PCI_HOST_COMMON_H
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-struct gen_pci_cfg_bus_ops {
-	u32 bus_shift;
-	struct pci_ops ops;
-};
-
-struct gen_pci_cfg_windows {
-	struct resource				res;
-	struct resource				*bus_range;
-	void __iomem				**win;
-
-	struct gen_pci_cfg_bus_ops		*ops;
-};
-
-struct gen_pci {
-	struct pci_host_bridge			host;
-	struct gen_pci_cfg_windows		cfg;
-	struct list_head			resources;
-};
-
-int pci_host_common_probe(struct platform_device *pdev,
-			  struct gen_pci *pci);
-
-#endif /* _PCI_HOST_COMMON_H */
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
index e8aa78f..6eaceab 100644
--- a/drivers/pci/host/pci-host-generic.c
+++ b/drivers/pci/host/pci-host-generic.c
@@ -25,41 +25,12 @@
 #include <linux/of_pci.h>
 #include <linux/platform_device.h>
 
-#include "pci-host-common.h"
+#include "../ecam.h"
 
-static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus,
-					     unsigned int devfn,
-					     int where)
-{
-	struct gen_pci *pci = bus->sysdata;
-	resource_size_t idx = bus->number - pci->cfg.bus_range->start;
-
-	return pci->cfg.win[idx] + ((devfn << 8) | where);
-}
-
-static struct gen_pci_cfg_bus_ops gen_pci_cfg_cam_bus_ops = {
+static struct pci_ecam_ops gen_pci_cfg_cam_bus_ops = {
 	.bus_shift	= 16,
-	.ops		= {
-		.map_bus	= gen_pci_map_cfg_bus_cam,
-		.read		= pci_generic_config_read,
-		.write		= pci_generic_config_write,
-	}
-};
-
-static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,
-					      unsigned int devfn,
-					      int where)
-{
-	struct gen_pci *pci = bus->sysdata;
-	resource_size_t idx = bus->number - pci->cfg.bus_range->start;
-
-	return pci->cfg.win[idx] + ((devfn << 12) | where);
-}
-
-static struct gen_pci_cfg_bus_ops gen_pci_cfg_ecam_bus_ops = {
-	.bus_shift	= 20,
-	.ops		= {
-		.map_bus	= gen_pci_map_cfg_bus_ecam,
+	.pci_ops	= {
+		.map_bus	= pci_ecam_map_bus,
 		.read		= pci_generic_config_read,
 		.write		= pci_generic_config_write,
 	}
@@ -70,25 +41,22 @@ static const struct of_device_id gen_pci_of_match[] = {
 	  .data = &gen_pci_cfg_cam_bus_ops },
 
 	{ .compatible = "pci-host-ecam-generic",
-	  .data = &gen_pci_cfg_ecam_bus_ops },
+	  .data = &pci_generic_ecam_ops },
 
 	{ },
 };
+
 MODULE_DEVICE_TABLE(of, gen_pci_of_match);
 
 static int gen_pci_probe(struct platform_device *pdev)
 {
-	struct device *dev = &pdev->dev;
 	const struct of_device_id *of_id;
-	struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
-
-	if (!pci)
-		return -ENOMEM;
+	struct pci_ecam_ops *ops;
 
-	of_id = of_match_node(gen_pci_of_match, dev->of_node);
-	pci->cfg.ops = (struct gen_pci_cfg_bus_ops *)of_id->data;
+	of_id = of_match_node(gen_pci_of_match, pdev->dev.of_node);
+	ops = (struct pci_ecam_ops *)of_id->data;
 
-	return pci_host_common_probe(pdev, pci);
+	return pci_host_common_probe(pdev, ops);
 }
 
 static struct platform_driver gen_pci_driver = {
diff --git a/drivers/pci/host/pci-thunder-ecam.c b/drivers/pci/host/pci-thunder-ecam.c
index d71935cb..540d030 100644
--- a/drivers/pci/host/pci-thunder-ecam.c
+++ b/drivers/pci/host/pci-thunder-ecam.c
@@ -13,18 +13,7 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
-#include "pci-host-common.h"
-
-/* Mapping is standard ECAM */
-static void __iomem *thunder_ecam_map_bus(struct pci_bus *bus,
-					  unsigned int devfn,
-					  int where)
-{
-	struct gen_pci *pci = bus->sysdata;
-	resource_size_t idx = bus->number - pci->cfg.bus_range->start;
-
-	return pci->cfg.win[idx] + ((devfn << 12) | where);
-}
+#include "../ecam.h"
 
 static void set_val(u32 v, int where, int size, u32 *val)
 {
@@ -99,7 +88,7 @@ static int handle_ea_bar(u32 e0, int bar, struct pci_bus *bus,
 static int thunder_ecam_p2_config_read(struct pci_bus *bus, unsigned int devfn,
 				       int where, int size, u32 *val)
 {
-	struct gen_pci *pci = bus->sysdata;
+	struct pci_config_window *cfg = bus->sysdata;
 	int where_a = where & ~3;
 	void __iomem *addr;
 	u32 node_bits;
@@ -129,7 +118,7 @@ static int thunder_ecam_p2_config_read(struct pci_bus *bus, unsigned int devfn,
 	 * the config space access window.  Since we are working with
 	 * the high-order 32 bits, shift everything down by 32 bits.
 	 */
-	node_bits = (pci->cfg.res.start >> 32) & (1 << 12);
+	node_bits = (cfg->res.start >> 32) & (1 << 12);
 
 	v |= node_bits;
 	set_val(v, where, size, val);
@@ -358,36 +347,24 @@ static int thunder_ecam_config_write(struct pci_bus *bus, unsigned int devfn,
 	return pci_generic_config_write(bus, devfn, where, size, val);
 }
 
-static struct gen_pci_cfg_bus_ops thunder_ecam_bus_ops = {
+static struct pci_ecam_ops pci_thunder_ecam_ops = {
 	.bus_shift	= 20,
-	.ops		= {
-		.map_bus        = thunder_ecam_map_bus,
+	.pci_ops	= {
+		.map_bus        = pci_ecam_map_bus,
 		.read           = thunder_ecam_config_read,
 		.write          = thunder_ecam_config_write,
 	}
 };
 
 static const struct of_device_id thunder_ecam_of_match[] = {
-	{ .compatible = "cavium,pci-host-thunder-ecam",
-	  .data = &thunder_ecam_bus_ops },
-
+	{ .compatible = "cavium,pci-host-thunder-ecam" },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, thunder_ecam_of_match);
 
 static int thunder_ecam_probe(struct platform_device *pdev)
 {
-	struct device *dev = &pdev->dev;
-	const struct of_device_id *of_id;
-	struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
-
-	if (!pci)
-		return -ENOMEM;
-
-	of_id = of_match_node(thunder_ecam_of_match, dev->of_node);
-	pci->cfg.ops = (struct gen_pci_cfg_bus_ops *)of_id->data;
-
-	return pci_host_common_probe(pdev, pci);
+	return pci_host_common_probe(pdev, &pci_thunder_ecam_ops);
 }
 
 static struct platform_driver thunder_ecam_driver = {
diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
index cabb92a..a7b61ce 100644
--- a/drivers/pci/host/pci-thunder-pem.c
+++ b/drivers/pci/host/pci-thunder-pem.c
@@ -20,34 +20,22 @@
 #include <linux/of_pci.h>
 #include <linux/platform_device.h>
 
-#include "pci-host-common.h"
+#include "../ecam.h"
 
 #define PEM_CFG_WR 0x28
 #define PEM_CFG_RD 0x30
 
 struct thunder_pem_pci {
-	struct gen_pci	gen_pci;
 	u32		ea_entry[3];
 	void __iomem	*pem_reg_base;
 };
 
-static void __iomem *thunder_pem_map_bus(struct pci_bus *bus,
-					 unsigned int devfn, int where)
-{
-	struct gen_pci *pci = bus->sysdata;
-	resource_size_t idx = bus->number - pci->cfg.bus_range->start;
-
-	return pci->cfg.win[idx] + ((devfn << 16) | where);
-}
-
 static int thunder_pem_bridge_read(struct pci_bus *bus, unsigned int devfn,
 				   int where, int size, u32 *val)
 {
 	u64 read_val;
-	struct thunder_pem_pci *pem_pci;
-	struct gen_pci *pci = bus->sysdata;
-
-	pem_pci = container_of(pci, struct thunder_pem_pci, gen_pci);
+	struct pci_config_window *cfg = bus->sysdata;
+	struct thunder_pem_pci *pem_pci = (struct thunder_pem_pci *)cfg->priv;
 
 	if (devfn != 0 || where >= 2048) {
 		*val = ~0;
@@ -132,17 +120,17 @@ static int thunder_pem_bridge_read(struct pci_bus *bus, unsigned int devfn,
 static int thunder_pem_config_read(struct pci_bus *bus, unsigned int devfn,
 				   int where, int size, u32 *val)
 {
-	struct gen_pci *pci = bus->sysdata;
+	struct pci_config_window *cfg = bus->sysdata;
 
-	if (bus->number < pci->cfg.bus_range->start ||
-	    bus->number > pci->cfg.bus_range->end)
+	if (bus->number < cfg->busr.start ||
+	    bus->number > cfg->busr.end)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	/*
 	 * The first device on the bus is the PEM PCIe bridge.
 	 * Special case its config access.
 	 */
-	if (bus->number == pci->cfg.bus_range->start)
+	if (bus->number == cfg->busr.start)
 		return thunder_pem_bridge_read(bus, devfn, where, size, val);
 
 	return pci_generic_config_read(bus, devfn, where, size, val);
@@ -187,12 +175,11 @@ static u32 thunder_pem_bridge_w1c_bits(int where)
 static int thunder_pem_bridge_write(struct pci_bus *bus, unsigned int devfn,
 				    int where, int size, u32 val)
 {
-	struct gen_pci *pci = bus->sysdata;
-	struct thunder_pem_pci *pem_pci;
+	struct pci_config_window *cfg = bus->sysdata;
+	struct thunder_pem_pci *pem_pci = (struct thunder_pem_pci *)cfg->priv;
 	u64 write_val, read_val;
 	u32 mask = 0;
 
-	pem_pci = container_of(pci, struct thunder_pem_pci, gen_pci);
 
 	if (devfn != 0 || where >= 2048)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -256,53 +243,38 @@ static int thunder_pem_bridge_write(struct pci_bus *bus, unsigned int devfn,
 static int thunder_pem_config_write(struct pci_bus *bus, unsigned int devfn,
 				    int where, int size, u32 val)
 {
-	struct gen_pci *pci = bus->sysdata;
+	struct pci_config_window *cfg = bus->sysdata;
 
-	if (bus->number < pci->cfg.bus_range->start ||
-	    bus->number > pci->cfg.bus_range->end)
+	if (bus->number < cfg->busr.start ||
+	    bus->number > cfg->busr.end)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	/*
 	 * The first device on the bus is the PEM PCIe bridge.
 	 * Special case its config access.
 	 */
-	if (bus->number == pci->cfg.bus_range->start)
+	if (bus->number == cfg->busr.start)
 		return thunder_pem_bridge_write(bus, devfn, where, size, val);
 
 
 	return pci_generic_config_write(bus, devfn, where, size, val);
 }
 
-static struct gen_pci_cfg_bus_ops thunder_pem_bus_ops = {
-	.bus_shift	= 24,
-	.ops		= {
-		.map_bus	= thunder_pem_map_bus,
-		.read		= thunder_pem_config_read,
-		.write		= thunder_pem_config_write,
-	}
-};
-
-static const struct of_device_id thunder_pem_of_match[] = {
-	{ .compatible = "cavium,pci-host-thunder-pem",
-	  .data = &thunder_pem_bus_ops },
-
-	{ },
-};
-MODULE_DEVICE_TABLE(of, thunder_pem_of_match);
-
-static int thunder_pem_probe(struct platform_device *pdev)
+static int thunder_pem_init(struct device *dev, struct pci_config_window *cfg)
 {
-	struct device *dev = &pdev->dev;
-	const struct of_device_id *of_id;
 	resource_size_t bar4_start;
 	struct resource *res_pem;
 	struct thunder_pem_pci *pem_pci;
+	struct platform_device *pdev;
+
+	/* Only OF support for now */
+	if (!dev->of_node)
+		return -EINVAL;
 
 	pem_pci = devm_kzalloc(dev, sizeof(*pem_pci), GFP_KERNEL);
 	if (!pem_pci)
 		return -ENOMEM;
 
-	of_id = of_match_node(thunder_pem_of_match, dev->of_node);
-	pem_pci->gen_pci.cfg.ops = (struct gen_pci_cfg_bus_ops *)of_id->data;
+	pdev = to_platform_device(dev);
 
 	/*
 	 * The second register range is the PEM bridge to the PCIe
@@ -330,7 +302,29 @@ static int thunder_pem_probe(struct platform_device *pdev)
 	pem_pci->ea_entry[1] = (u32)(res_pem->end - bar4_start) & ~3u;
 	pem_pci->ea_entry[2] = (u32)(bar4_start >> 32);
 
-	return pci_host_common_probe(pdev, &pem_pci->gen_pci);
+	cfg->priv = pem_pci;
+	return 0;
+}
+
+static struct pci_ecam_ops pci_thunder_pem_ops = {
+	.bus_shift	= 24,
+	.init		= thunder_pem_init,
+	.pci_ops	= {
+		.map_bus	= pci_ecam_map_bus,
+		.read		= thunder_pem_config_read,
+		.write		= thunder_pem_config_write,
+	}
+};
+
+static const struct of_device_id thunder_pem_of_match[] = {
+	{ .compatible = "cavium,pci-host-thunder-pem" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, thunder_pem_of_match);
+
+static int thunder_pem_probe(struct platform_device *pdev)
+{
+	return pci_host_common_probe(pdev, &pci_thunder_pem_ops);
 }
 
 static struct platform_driver thunder_pem_driver = {
-- 
1.9.1



From tn at semihalf.com  Tue May 10 08:19:54 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 10 May 2016 17:19:54 +0200
Subject: [PATCH V7 04/11] pci: Add new function to unmap IO resources.
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <1462893601-8937-5-git-send-email-tn@semihalf.com>

It is very useful to release I/O resources so that the same I/O resources
can be allocated again (pci_remap_iospace), like in PCI hotplug removal
scenario. Therefore this patch implements new pci_unmap_iospace call which
unmaps I/O space as the symmetry to pci_remap_iospace.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 drivers/pci/pci.c   | 24 ++++++++++++++++++++++++
 include/linux/pci.h |  1 +
 2 files changed, 25 insertions(+)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index bc0c914..ff97a0b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -25,6 +25,7 @@
 #include <linux/device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pci_hotplug.h>
+#include <linux/vmalloc.h>
 #include <asm/setup.h>
 #include <linux/aer.h>
 #include "pci.h"
@@ -3167,6 +3168,29 @@ int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
 #endif
 }
 
+/**
+ *	pci_unmap_iospace - Unmap the memory mapped I/O space
+ *	@res: resource to be unmapped
+ *
+ *	Unmap the CPU virtual address @res from virtual address space.
+ *	Only architectures that have memory mapped IO functions defined
+ *	(and the PCI_IOBASE value defined) should call this function.
+ */
+void  pci_unmap_iospace(struct resource *res)
+{
+#if defined(PCI_IOBASE) && defined(CONFIG_MMU)
+	unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start;
+
+	unmap_kernel_range(vaddr, resource_size(res));
+#else
+	/*
+	 * This architecture does not have memory mapped I/O space,
+	 * so this function should never be called.
+	 */
+	WARN_ONCE(1, "This architecture does not support memory mapped I/O\n");
+#endif
+}
+
 static void __pci_set_master(struct pci_dev *dev, bool enable)
 {
 	u16 old_cmd, cmd;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d2a57f3..d6ea6ce 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1169,6 +1169,7 @@ int pci_register_io_range(phys_addr_t addr, resource_size_t size);
 unsigned long pci_address_to_pio(phys_addr_t addr);
 phys_addr_t pci_pio_to_address(unsigned long pio);
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
+void pci_unmap_iospace(struct resource *res);
 
 static inline pci_bus_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
 {
-- 
1.9.1



From tn at semihalf.com  Tue May 10 08:19:57 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 10 May 2016 17:19:57 +0200
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <1462893601-8937-8-git-send-email-tn@semihalf.com>

This patch provides a way to set the ACPI companion in PCI code.
We define acpi_pci_set_companion() to set the ACPI companion pointer and
call it from PCI core code. The function is stub for now.

Signed-off-by: Jayachandran C <jchandra at broadcom.com>
Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 drivers/pci/probe.c      | 2 ++
 include/linux/pci-acpi.h | 4 ++++
 2 files changed, 6 insertions(+)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 8004f67..fb0b752 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/cpumask.h>
+#include <linux/pci-acpi.h>
 #include <linux/pci-aspm.h>
 #include <linux/aer.h>
 #include <linux/acpi.h>
@@ -2141,6 +2142,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	bridge->dev.parent = parent;
 	bridge->dev.release = pci_release_host_bridge_dev;
 	dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
+	acpi_pci_set_companion(bridge);
 	error = pcibios_root_bridge_prepare(bridge);
 	if (error) {
 		kfree(bridge);
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 09f9f02..1baa515 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -111,6 +111,10 @@ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
 static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
 #endif	/* CONFIG_ACPI */
 
+static inline void acpi_pci_set_companion(struct pci_host_bridge *bridge)
+{
+}
+
 static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus)
 {
 	return 0;
-- 
1.9.1



From tn at semihalf.com  Tue May 10 08:19:56 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 10 May 2016 17:19:56 +0200
Subject: [PATCH V7 06/11] pci, acpi: Provide a way to assign bus domain number.
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <1462893601-8937-7-git-send-email-tn@semihalf.com>

This patch provides a way to set the ACPI domain number in PCI code.
pci_create_root_bus is called with NULL as parent in ACPI. This
ends up calling pci_bus_assign_domain_nr with a NULL parent.
So we define acpi_pci_bus_domain_nr() which is meant to retrieve
the PCI domain number based on 'struct pci_bus' in the ACPI way.
pci_bus_assign_domain_nr() is updated to call acpi_pci_bus_domain_nr()
and assign domain number on the root bus, in case of ACPI.

acpi_pci_bus_domain_nr function is stub for now.

While at it, for the sake of code clarity we put ACPI and DT domain
assign methods into the corresponding helpers.

Signed-off-by: Jayachandran C <jchandra at broadcom.com>
Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 drivers/pci/pci.c        | 11 +++++++++--
 include/linux/pci-acpi.h |  5 +++++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index ff97a0b..a1d7bcf 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -19,6 +19,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/log2.h>
+#include <linux/pci-acpi.h>
 #include <linux/pci-aspm.h>
 #include <linux/pm_wakeup.h>
 #include <linux/interrupt.h>
@@ -4918,7 +4919,7 @@ int pci_get_new_domain_nr(void)
 }
 
 #ifdef CONFIG_PCI_DOMAINS_GENERIC
-void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+static int of_pci_bus_domain_nr(struct device *parent)
 {
 	static int use_dt_domains = -1;
 	int domain = -1;
@@ -4962,7 +4963,13 @@ void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
 		domain = -1;
 	}
 
-	bus->domain_nr = domain;
+	return domain;
+}
+
+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+{
+	bus->domain_nr = acpi_disabled ? of_pci_bus_domain_nr(parent) :
+					 acpi_pci_bus_domain_nr(bus);
 }
 #endif
 #endif
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 89ab057..09f9f02 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -111,6 +111,11 @@ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
 static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
 #endif	/* CONFIG_ACPI */
 
+static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus)
+{
+	return 0;
+}
+
 #ifdef CONFIG_ACPI_APEI
 extern bool aer_acpi_firmware_first(void);
 #else
-- 
1.9.1



From tn at semihalf.com  Tue May 10 08:19:55 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 10 May 2016 17:19:55 +0200
Subject: [PATCH V7 05/11] acpi,
 pci: Support IO resources when parsing PCI host bridge resources.
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <1462893601-8937-6-git-send-email-tn@semihalf.com>

Platforms that have memory mapped IO port (such as ARM64) need special
handling for PCI I/O resources. For host bridge's resource probing case
these resources need to be fixed up with pci_register_io_range/pci_remap_iospace etc.

The same I/O resources need to be released after hotplug
removal so that it can be re-added back by the pci_remap_iospace
function during insertion. As a consequence we unmap I/O resources
with pci_unmap_iospace when we release host bridge resources.

Signed-off-by: Jayachandran C <jchandra at broadcom.com>
Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 drivers/acpi/pci_root.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index ae3fe4e..cb3071d 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -719,6 +719,34 @@ next:
 			resource_list_add_tail(entry, resources);
 	}
 }
+static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
+{
+#ifdef PCI_IOBASE
+	struct resource *res = entry->res;
+	resource_size_t cpu_addr = res->start;
+	resource_size_t pci_addr = cpu_addr - entry->offset;
+	resource_size_t length = resource_size(res);
+	unsigned long port;
+
+	if (pci_register_io_range(cpu_addr, length))
+		goto err;
+
+	port = pci_address_to_pio(cpu_addr);
+	if (port == (unsigned long)-1)
+		goto err;
+
+	res->start = port;
+	res->end = port + length - 1;
+	entry->offset = port - pci_addr;
+
+	if (pci_remap_iospace(res, cpu_addr) < 0)
+		goto err;
+	pr_info("Remapped I/O %pa to %pR\n", &cpu_addr, res);
+	return;
+err:
+	res->flags |= IORESOURCE_DISABLED;
+#endif
+}
 
 int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
 {
@@ -740,6 +768,9 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
 			"no IO and memory resources present in _CRS\n");
 	else {
 		resource_list_for_each_entry_safe(entry, tmp, list) {
+			if (entry->res->flags & IORESOURCE_IO)
+				acpi_pci_root_remap_iospace(entry);
+
 			if (entry->res->flags & IORESOURCE_DISABLED)
 				resource_list_destroy_entry(entry);
 			else
@@ -811,6 +842,8 @@ static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
 
 	resource_list_for_each_entry(entry, &bridge->windows) {
 		res = entry->res;
+		if (res->flags & IORESOURCE_IO)
+			pci_unmap_iospace(res);
 		if (res->parent &&
 		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
 			release_resource(res);
-- 
1.9.1



From tn at semihalf.com  Tue May 10 08:19:59 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 10 May 2016 17:19:59 +0200
Subject: [PATCH V7 09/11] arm64, pci,
 acpi: ACPI support for legacy IRQs parsing and consolidation with DT
 code.
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <1462893601-8937-10-git-send-email-tn@semihalf.com>

To enable PCI legacy IRQs on platforms booting with ACPI, arch code
should include ACPI specific callbacks that parse and set-up the
device IRQ number, equivalent to the DT boot path. Owing to the current
ACPI core scan handlers implementation, ACPI PCI legacy IRQs bindings
cannot be parsed at device add time, since that would trigger ACPI scan
handlers ordering issues depending on how the ACPI tables are defined.

To solve this problem and consolidate FW PCI legacy IRQs parsing in
one single pcibios callback (pending final removal), this patch moves
DT PCI IRQ parsing to the pcibios_alloc_irq() callback (called by
PCI core code at device probe time) and adds ACPI PCI legacy IRQs
parsing to the same callback too, so that FW PCI legacy IRQs parsing
is confined in one single arch callback that can be easily removed
when code parsing PCI legacy IRQs is consolidated and moved to core
PCI code.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
---
 arch/arm64/kernel/pci.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
index c72de66..15109c11 100644
--- a/arch/arm64/kernel/pci.c
+++ b/arch/arm64/kernel/pci.c
@@ -50,11 +50,16 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 }
 
 /*
- * Try to assign the IRQ number from DT when adding a new device
+ * Try to assign the IRQ number when probing a new device
  */
-int pcibios_add_device(struct pci_dev *dev)
+int pcibios_alloc_irq(struct pci_dev *dev)
 {
-	dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
+	if (acpi_disabled)
+		dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
+#ifdef CONFIG_ACPI
+	else
+		return acpi_pci_irq_enable(dev);
+#endif
 
 	return 0;
 }
-- 
1.9.1



From tn at semihalf.com  Tue May 10 08:20:01 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 10 May 2016 17:20:01 +0200
Subject: [PATCH V7 11/11] arm64, pci,
 acpi: Start using ACPI based PCI host controller driver for ARM64.
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <1462893601-8937-12-git-send-email-tn@semihalf.com>

It is perfectly fine to use ACPI_PCI_HOST_GENERIC for ARM64,
so lets get rid of PCI init and RAW ACPI accessor empty stubs
and go with full-blown PCI host controller driver.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
To: Catalin Marinas <catalin.marinas at arm.com>
To: Lorenzo Pieralisi <Lorenzo.Pieralisi at arm.com>
To: Will Deacon <will.deacon at arm.com>
To: Arnd Bergmann <arnd at arndb.de>
---
 arch/arm64/Kconfig      |  1 +
 arch/arm64/kernel/pci.c | 24 ------------------------
 2 files changed, 1 insertion(+), 24 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 4f43622..1bded87 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2,6 +2,7 @@ config ARM64
 	def_bool y
 	select ACPI_CCA_REQUIRED if ACPI
 	select ACPI_GENERIC_GSI if ACPI
+	select ACPI_PCI_HOST_GENERIC if ACPI
 	select ACPI_REDUCED_HARDWARE_ONLY if ACPI
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
index eeec5f6..e484c91 100644
--- a/arch/arm64/kernel/pci.c
+++ b/arch/arm64/kernel/pci.c
@@ -74,27 +74,3 @@ void pcibios_remove_bus(struct pci_bus *bus)
 {
 	acpi_pci_remove_bus(bus);
 }
-
-/*
- * raw_pci_read/write - Platform-specific PCI config space access.
- */
-int raw_pci_read(unsigned int domain, unsigned int bus,
-		  unsigned int devfn, int reg, int len, u32 *val)
-{
-	return -ENXIO;
-}
-
-int raw_pci_write(unsigned int domain, unsigned int bus,
-		unsigned int devfn, int reg, int len, u32 val)
-{
-	return -ENXIO;
-}
-
-#ifdef CONFIG_ACPI
-/* Root bridge scanning */
-struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
-{
-	/* TODO: Should be revisited when implementing PCI on ACPI */
-	return NULL;
-}
-#endif
-- 
1.9.1



From tn at semihalf.com  Tue May 10 08:20:00 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 10 May 2016 17:20:00 +0200
Subject: [PATCH V7 10/11] arm64, pci,
 acpi: Provide ACPI-specific prerequisites for PCI bus enumeration.
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <1462893601-8937-11-git-send-email-tn@semihalf.com>

ACPI requires to run acpi_pci_{add|remove}_bus while new PCI bus is created.
This allows to do some ACPI-specific additional configuration, like
PCI hotplug slot enumeration. In order to fulfill these requirements,
we implement arch-specific pcibios_{add|remove}_bus calls
and call acpi_pci_{add|remove}_bus from there.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
To: Catalin Marinas <catalin.marinas at arm.com>
To: Lorenzo Pieralisi <Lorenzo.Pieralisi at arm.com>
To: Will Deacon <will.deacon at arm.com>
To: Arnd Bergmann <arnd at arndb.de>
---
 arch/arm64/kernel/pci.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
index 15109c11..eeec5f6 100644
--- a/arch/arm64/kernel/pci.c
+++ b/arch/arm64/kernel/pci.c
@@ -17,6 +17,7 @@
 #include <linux/mm.h>
 #include <linux/of_pci.h>
 #include <linux/of_platform.h>
+#include <linux/pci-acpi.h>
 #include <linux/slab.h>
 
 /*
@@ -64,6 +65,16 @@ int pcibios_alloc_irq(struct pci_dev *dev)
 	return 0;
 }
 
+void pcibios_add_bus(struct pci_bus *bus)
+{
+	acpi_pci_add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+	acpi_pci_remove_bus(bus);
+}
+
 /*
  * raw_pci_read/write - Platform-specific PCI config space access.
  */
-- 
1.9.1



From tn at semihalf.com  Tue May 10 08:19:58 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 10 May 2016 17:19:58 +0200
Subject: [PATCH V7 08/11] pci,
 acpi: Support for ACPI based generic PCI host controller
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <1462893601-8937-9-git-send-email-tn@semihalf.com>

This patch is going to implement generic PCI host controller for
ACPI world, similar to what pci-host-generic.c driver does for DT world.

All such drivers, which we have seen so far, were implemented within
arch/ directory since they had some arch assumptions (x86 and ia64).
However, they all are doing similar thing, so it makes sense to find
some common code and abstract it into the generic driver.

In order to handle PCI config space regions properly, we define new
MCFG interface which does sanity checks on MCFG table and keeps its
root pointer. User is able to lookup MCFG regions based on that root
pointer and specified domain:bus_start:bus_end touple. We are using
pci_mmcfg_late_init old prototype to avoid another function name.

The implementation of pci_acpi_scan_root() looks up the MCFG entries
and sets up a new mapping (regions are not mapped until host controller ask
for it). Generic PCI functions are used for accessing config space.
Driver selects PCI_ECAM and uses functions from drivers/pci/ecam.h
to create and access ECAM mappings.

As mentioned in Kconfig help section, ACPI_PCI_HOST_GENERIC choice
should be made on a per-architecture basis.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
Signed-off-by: Jayachandran C <jchandra at broadcom.com>
---
 drivers/acpi/Kconfig            |   8 +++
 drivers/acpi/Makefile           |   1 +
 drivers/acpi/pci_mcfg.c         |  97 ++++++++++++++++++++++++++
 drivers/acpi/pci_root_generic.c | 149 ++++++++++++++++++++++++++++++++++++++++
 drivers/pci/ecam.h              |   5 ++
 include/linux/pci-acpi.h        |   5 ++
 include/linux/pci.h             |   5 +-
 7 files changed, 269 insertions(+), 1 deletion(-)
 create mode 100644 drivers/acpi/pci_mcfg.c
 create mode 100644 drivers/acpi/pci_root_generic.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 183ffa3..44afc76 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -346,6 +346,14 @@ config ACPI_PCI_SLOT
 	  i.e., segment/bus/device/function tuples, with physical slots in
 	  the system.  If you are unsure, say N.
 
+config ACPI_PCI_HOST_GENERIC
+	bool
+	select PCI_ECAM
+	help
+	  Select this config option from the architecture Kconfig,
+	  if it is preferred to enable ACPI PCI host controller driver which
+	  has no arch-specific assumptions.
+
 config X86_PM_TIMER
 	bool "Power Management Timer Support" if EXPERT
 	depends on X86
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 81e5cbc..627a2b7 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -40,6 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
 acpi-y				+= ec.o
 acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
 acpi-y				+= pci_root.o pci_link.o pci_irq.o
+obj-$(CONFIG_ACPI_PCI_HOST_GENERIC)	+= pci_root_generic.o pci_mcfg.o
 acpi-y				+= acpi_lpss.o acpi_apd.o
 acpi-y				+= acpi_platform.o
 acpi-y				+= acpi_pnp.o
diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
new file mode 100644
index 0000000..373d079
--- /dev/null
+++ b/drivers/acpi/pci_mcfg.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *	Author: Jayachandran C <jchandra at broadcom.com>
+ * Copyright (C) 2016 Semihalf
+ * 	Author: Tomasz Nowicki <tn at semihalf.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pci-acpi.h>
+
+#define PREFIX	"ACPI: "
+
+/* Root pointer to the mapped MCFG table */
+static struct acpi_table_mcfg *mcfg_table;
+
+#define MCFG_ENTRIES(mcfg_ptr)	(((mcfg_ptr)->header.length -		\
+				sizeof(struct acpi_table_mcfg)) /	\
+				sizeof(struct acpi_mcfg_allocation))
+
+static phys_addr_t pci_mcfg_lookup_static(u16 seg, u8 bus_start, u8 bus_end)
+{
+	struct acpi_mcfg_allocation *mptr;
+	int i;
+
+	if (!mcfg_table) {
+		pr_err(PREFIX "MCFG table not available, lookup failed\n");
+		return -ENXIO;
+	}
+
+	mptr = (struct acpi_mcfg_allocation *) &mcfg_table[1];
+
+	/*
+	 * We expect exact match, unless MCFG entry end bus covers more than
+	 * specified by caller.
+	 */
+	for (i = 0; i < MCFG_ENTRIES(mcfg_table); i++, mptr++) {
+		if (mptr->pci_segment == seg &&
+		    mptr->start_bus_number == bus_start &&
+		    mptr->end_bus_number >= bus_end) {
+			return mptr->address;
+		}
+	}
+
+	return -ENXIO;
+}
+
+phys_addr_t pci_mcfg_lookup(struct acpi_device *device, u16 seg,
+			    struct resource *bus_res)
+{
+	phys_addr_t addr;
+
+	addr = acpi_pci_root_get_mcfg_addr(device->handle);
+	if (addr)
+		return addr;
+
+	return pci_mcfg_lookup_static(seg, bus_res->start, bus_res->end);
+}
+
+static __init int pci_mcfg_parse(struct acpi_table_header *header)
+{
+	struct acpi_table_mcfg *mcfg;
+	int n;
+
+	if (!header)
+		return -EINVAL;
+
+	mcfg = (struct acpi_table_mcfg *)header;
+	n = MCFG_ENTRIES(mcfg);
+	if (n <= 0 || n > 255) {
+		pr_err(PREFIX "MCFG has incorrect entries (%d).\n", n);
+		return -EINVAL;
+	}
+
+	mcfg_table = mcfg;
+	pr_info(PREFIX "MCFG table loaded, %d entries detected\n", n);
+	return 0;
+}
+
+/* Interface called by ACPI - parse and save MCFG table */
+void __init pci_mmcfg_late_init(void)
+{
+	int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse);
+	if (err)
+		pr_err(PREFIX "Failed to parse MCFG (%d)\n", err);
+}
diff --git a/drivers/acpi/pci_root_generic.c b/drivers/acpi/pci_root_generic.c
new file mode 100644
index 0000000..6f4940a
--- /dev/null
+++ b/drivers/acpi/pci_root_generic.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *	Author: Jayachandran C <jchandra at broadcom.com>
+ * Copyright (C) 2016 Semihalf
+ * 	Author: Tomasz Nowicki <tn at semihalf.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pci-acpi.h>
+#include <linux/slab.h>
+
+#include "../pci/ecam.h"
+
+#define PREFIX	"ACPI PCI: "
+
+/* ACPI info for generic ACPI PCI controller */
+struct acpi_pci_generic_root_info {
+	struct acpi_pci_root_info	common;
+	struct pci_config_window	*cfg;	/* config space mapping */
+};
+
+void acpi_pci_set_companion(struct pci_host_bridge *bridge)
+{
+	struct pci_config_window *cfg = bridge->bus->sysdata;
+
+	ACPI_COMPANION_SET(&bridge->dev, cfg->companion);
+}
+
+int acpi_pci_bus_domain_nr(struct pci_bus *bus)
+{
+	struct pci_config_window *cfg = bus->sysdata;
+
+	return cfg->domain;
+}
+
+/*
+ * Lookup the bus range for the domain in MCFG, and set up config space
+ * mapping.
+ */
+static int pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root,
+				       struct acpi_pci_generic_root_info *ri)
+{
+	struct resource *bus_res = &root->secondary;
+	u16 seg = root->segment;
+	struct pci_config_window *cfg;
+	struct resource cfgres;
+	unsigned int bsz;
+	phys_addr_t addr;
+
+	addr = pci_mcfg_lookup(root->device, seg, bus_res);
+	if (IS_ERR_VALUE(addr)) {
+		pr_err(PREFIX"%04x:%pR MCFG region not found\n", seg, bus_res);
+		return addr;
+	}
+
+	bsz = 1 << pci_generic_ecam_ops.bus_shift;
+	cfgres.start = addr + bus_res->start * bsz;
+	cfgres.end = addr + (bus_res->end + 1) * bsz - 1;
+	cfgres.flags = IORESOURCE_MEM;
+	cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
+						  &pci_generic_ecam_ops);
+	if (IS_ERR(cfg)) {
+		pr_err("%04x:%pR error %ld mapping CAM\n", seg, bus_res,
+		       PTR_ERR(cfg));
+		return PTR_ERR(cfg);
+	}
+
+	cfg->domain = seg;
+	cfg->companion = root->device;
+	ri->cfg = cfg;
+	return 0;
+}
+
+/* release_info: free resrouces allocated by init_info */
+static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci)
+{
+	struct acpi_pci_generic_root_info *ri;
+
+	ri = container_of(ci, struct acpi_pci_generic_root_info, common);
+	pci_ecam_free(ri->cfg);
+	kfree(ri);
+}
+
+static struct acpi_pci_root_ops acpi_pci_root_ops = {
+	.release_info = pci_acpi_generic_release_info,
+};
+
+/* Interface called from ACPI code to setup PCI host controller */
+struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
+{
+	int node = acpi_get_node(root->device->handle);
+	struct acpi_pci_generic_root_info *ri;
+	struct pci_bus *bus, *child;
+	int err;
+
+	ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node);
+	if (!ri)
+		return NULL;
+
+	err = pci_acpi_setup_ecam_mapping(root, ri);
+	if (err)
+		return NULL;
+
+	acpi_pci_root_ops.pci_ops = &ri->cfg->ops->pci_ops;
+	bus = acpi_pci_root_create(root, &acpi_pci_root_ops, &ri->common,
+				   ri->cfg);
+	if (!bus)
+		return NULL;
+
+	pci_bus_size_bridges(bus);
+	pci_bus_assign_resources(bus);
+
+	list_for_each_entry(child, &bus->children, node)
+		pcie_bus_configure_settings(child);
+
+	return bus;
+}
+
+int raw_pci_read(unsigned int domain, unsigned int busn, unsigned int devfn,
+		 int reg, int len, u32 *val)
+{
+	struct pci_bus *bus = pci_find_bus(domain, busn);
+
+	if (!bus)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	return bus->ops->read(bus, devfn, reg, len, val);
+}
+
+int raw_pci_write(unsigned int domain, unsigned int busn, unsigned int devfn,
+		  int reg, int len, u32 val)
+{
+	struct pci_bus *bus = pci_find_bus(domain, busn);
+
+	if (!bus)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	return bus->ops->write(bus, devfn, reg, len, val);
+}
diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
index 1ad2176..1cccf57 100644
--- a/drivers/pci/ecam.h
+++ b/drivers/pci/ecam.h
@@ -45,6 +45,11 @@ struct pci_config_window {
 		void __iomem		*win;	/* 64-bit single mapping */
 		void __iomem		**winp; /* 32-bit per bus mapping */
 	};
+#ifdef CONFIG_ACPI_PCI_HOST_GENERIC
+	struct acpi_device		*companion; /* ACPI companion device */
+#endif
+	int				domain;
+
 };
 
 /* create and free for pci_config_window */
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 1baa515..42ff844 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -111,6 +111,10 @@ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
 static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
 #endif	/* CONFIG_ACPI */
 
+#ifdef CONFIG_ACPI_PCI_HOST_GENERIC
+void acpi_pci_set_companion(struct pci_host_bridge *bridge);
+int acpi_pci_bus_domain_nr(struct pci_bus *bus);
+#else
 static inline void acpi_pci_set_companion(struct pci_host_bridge *bridge)
 {
 }
@@ -119,6 +123,7 @@ static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus)
 {
 	return 0;
 }
+#endif
 
 #ifdef CONFIG_ACPI_APEI
 extern bool aer_acpi_firmware_first(void);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d6ea6ce..b2e8886 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1722,7 +1722,10 @@ void pcibios_free_irq(struct pci_dev *dev);
 extern struct dev_pm_ops pcibios_pm_ops;
 #endif
 
-#ifdef CONFIG_PCI_MMCONFIG
+#if defined(CONFIG_PCI_MMCONFIG) || defined(CONFIG_ACPI_PCI_HOST_GENERIC)
+struct acpi_device;
+phys_addr_t pci_mcfg_lookup(struct acpi_device *device, u16 seg,
+			    struct resource *bus_res);
 void __init pci_mmcfg_early_init(void);
 void __init pci_mmcfg_late_init(void);
 #else
-- 
1.9.1



From eric.auger at linaro.org  Tue May 10 08:20:30 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 17:20:30 +0200
Subject: [PATCH v3 17/55] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <1462531568-9799-18-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-18-git-send-email-andre.przywara@arm.com>
Message-ID: <5731FC3E.7020700@linaro.org>

On 05/06/2016 12:45 PM, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Implement the framework for syncing IRQs between our emulation and
> the list registers, which represent the guest's view of IRQs.
> This is done in kvm_vgic_flush_hwstate and kvm_vgic_sync_hwstate,
> which gets called on guest entry and exit.
> The code talking to the actual GICv2/v3 hardware is added in the
> following patches.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - split out vgic_clear_lr() from vgic_populate_lr()
> - rename vgic_populate_lrs() to vgic_flush_lr_state()
> - clean all LRs when the distributor is disabled
> - use list_del() instead of list_del_init()
> - add comments to explain the direction of sync/flush_hwstate
> - remove unneeded BUG_ON(in_interrupt()
> 
> Changelog v2 .. v3:
> - remove bogus v2 specific rebase leftovers
> 
>  include/kvm/vgic/vgic.h  |   4 +
>  virt/kvm/arm/vgic/vgic.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h |   2 +
>  3 files changed, 199 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 2bfb42c..5fae4a9 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -190,6 +190,10 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
>  			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
>  
> +bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
> +void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
> +void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
> +
>  /**
>   * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
>   *
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 4fb20fd..c6f8b9b 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -305,3 +305,196 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  {
>  	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
>  }
> +
> +/**
> + * vgic_prune_ap_list - Remove non-relevant interrupts from the list
> + *
> + * @vcpu: The VCPU pointer
> + *
> + * Go over the list of "interesting" interrupts, and prune those that we
> + * won't have to consider in the near future.
> + */
> +static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq, *tmp;
> +
> +retry:
> +	spin_lock(&vgic_cpu->ap_list_lock);
> +
> +	list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
> +		struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		BUG_ON(vcpu != irq->vcpu);
> +
> +		target_vcpu = vgic_target_oracle(irq);
> +
> +		if (!target_vcpu) {
> +			/*
> +			 * We don't need to process this interrupt any
> +			 * further, move it off the list.
> +			 */
> +			list_del(&irq->ap_list);
> +			irq->vcpu = NULL;
> +			spin_unlock(&irq->irq_lock);
> +			continue;
> +		}
> +
> +		if (target_vcpu == vcpu) {
> +			/* We're on the right CPU */
> +			spin_unlock(&irq->irq_lock);
> +			continue;
> +		}
> +
> +		/* This interrupt looks like it has to be migrated. */
> +
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vgic_cpu->ap_list_lock);
> +
> +		/*
> +		 * Ensure locking order by always locking the smallest
> +		 * ID first.
> +		 */
> +		if (vcpu->vcpu_id < target_vcpu->vcpu_id) {
> +			vcpuA = vcpu;
> +			vcpuB = target_vcpu;
> +		} else {
> +			vcpuA = target_vcpu;
> +			vcpuB = vcpu;
> +		}
> +
> +		spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
> +		spin_lock(&vcpuB->arch.vgic_cpu.ap_list_lock);
> +		spin_lock(&irq->irq_lock);
> +
> +		/*
> +		 * If the affinity has been preserved, move the
> +		 * interrupt around. Otherwise, it means things have
> +		 * changed while the interrupt was unlocked, and we
> +		 * need to replay this.
> +		 *
> +		 * In all cases, we cannot trust the list not to have
> +		 * changed, so we restart from the beginning.
> +		 */
> +		if (target_vcpu == vgic_target_oracle(irq)) {
> +			struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;
> +
> +			list_del(&irq->ap_list);
> +			irq->vcpu = target_vcpu;
> +			list_add_tail(&irq->ap_list, &new_cpu->ap_list_head);
> +		}
> +
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
> +		spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
> +		goto retry;
> +	}
> +
> +	spin_unlock(&vgic_cpu->ap_list_lock);
> +}
> +
> +static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +/* Requires the ap_list_lock and the irq_lock to be held. */
why is it needed to hold the ap_list lock here?
> +static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
> +				    struct vgic_irq *irq, int lr)
> +{
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
?

Eric
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
> +}
> +
> +static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
> +{
> +}
> +
> +static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq;
> +	int count = 0;
> +
> +	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
> +		spin_lock(&irq->irq_lock);
> +		/* GICv2 SGIs can count for more than one... */
> +		if (vgic_irq_is_sgi(irq->intid) && irq->source)
> +			count += hweight8(irq->source);
> +		else
> +			count++;
> +		spin_unlock(&irq->irq_lock);
> +	}
> +	return count;
> +}
> +
> +/* Requires the VCPU's ap_list_lock to be held. */
> +static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq;
> +	int count = 0;
> +
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
> +
> +	if (unlikely(!vcpu->kvm->arch.vgic.enabled))
> +		goto out_clean;
> +
> +	if (compute_ap_list_depth(vcpu) > kvm_vgic_global_state.nr_lr) {
> +		vgic_set_underflow(vcpu);
> +		vgic_sort_ap_list(vcpu);
> +	}
> +
> +	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
> +		spin_lock(&irq->irq_lock);
> +
> +		if (unlikely(vgic_target_oracle(irq) != vcpu))
> +			goto next;
> +
> +		/*
> +		 * If we get an SGI with multiple sources, try to get
> +		 * them in all at once.
> +		 */
> +		do {
> +			vgic_populate_lr(vcpu, irq, count++);
> +		} while (irq->source && count < kvm_vgic_global_state.nr_lr);
> +
> +next:
> +		spin_unlock(&irq->irq_lock);
> +
> +		if (count == kvm_vgic_global_state.nr_lr)
> +			break;
> +	}
> +
> +out_clean:
> +	vcpu->arch.vgic_cpu.used_lrs = count;
> +
> +	/* Nuke remaining LRs */
> +	for ( ; count < kvm_vgic_global_state.nr_lr; count++)
> +		vgic_clear_lr(vcpu, count);
> +}
> +
> +/* Sync back the hardware VGIC state into our emulation after a guest's run. */
> +void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
> +{
> +	vgic_process_maintenance_interrupt(vcpu);
> +	vgic_fold_lr_state(vcpu);
> +	vgic_prune_ap_list(vcpu);
> +}
> +
> +/* Flush our emulation state into the GIC hardware before entering the guest. */
> +void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
> +{
> +	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +	vgic_flush_lr_state(vcpu);
> +	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index c625767..29b96b9 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -16,6 +16,8 @@
>  #ifndef __KVM_ARM_VGIC_NEW_H__
>  #define __KVM_ARM_VGIC_NEW_H__
>  
> +#define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
> +
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid);
>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
> 



From marc.zyngier at arm.com  Tue May 10 08:22:19 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 16:22:19 +0100
Subject: [PATCH v3a] KVM: arm/arm64: pmu: abstract access to number of SPIs
In-Reply-To: <1462890906-6134-1-git-send-email-andre.przywara@arm.com>
References: <5731AF57.2040707@linaro.org>
 <1462890906-6134-1-git-send-email-andre.przywara@arm.com>
Message-ID: <5731FCAB.9050109@arm.com>

On 10/05/16 15:35, Andre Przywara wrote:
> Currently the PMU uses a member of the struct vgic_dist directly,
> which not only breaks abstraction, but will fail with the new VGIC.
> Abstract this access in the VGIC header file.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Hi Eric, Marc,
> 
> as this if-statement was quite confusing (it wasn't even the negation
> that was wrong), I rewrote it a bit to be more readable.
> This one works now with PPIs (after fixing kvmtool).
> 
> Does that make sense?
> 
> Cheers,
> Andre.
> 
>  include/kvm/arm_vgic.h |  2 ++
>  virt/kvm/arm/pmu.c     | 19 +++++++++++--------
>  2 files changed, 13 insertions(+), 8 deletions(-)
> 
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 6a98e05..d406f8e 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -351,6 +351,8 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
>  #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
>  #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
>  #define vgic_ready(k)		((k)->arch.vgic.ready)
> +#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
> +				 ((i) < (k)->arch.vgic.nr_irqs))
>  
>  int vgic_v2_probe(struct device_node *vgic_node,
>  		  const struct vgic_ops **ops,
> diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
> index 575c7aa..6ab9d6b 100644
> --- a/virt/kvm/arm/pmu.c
> +++ b/virt/kvm/arm/pmu.c
> @@ -436,6 +436,11 @@ static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
>  	return 0;
>  }
>  
> +/*
> + * For one VM the interrupt type must be same for each vcpu.
> + * As a PPI, the interrupt number is the same for all vcpus,
> + * while as an SPI it must be a separate number per vcpu.
> + */
>  static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
>  {
>  	int i;
> @@ -457,6 +462,7 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
>  	return true;
>  }
>  
> +#define irq_is_ppi(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS)

You might as well move this to the VGIC code.

>  
>  int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
>  {
> @@ -471,14 +477,11 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
>  		if (get_user(irq, uaddr))
>  			return -EFAULT;
>  
> -		/*
> -		 * The PMU overflow interrupt could be a PPI or SPI, but for one
> -		 * VM the interrupt type must be same for each vcpu. As a PPI,
> -		 * the interrupt number is the same for all vcpus, while as an
> -		 * SPI it must be a separate number per vcpu.
> -		 */
> -		if (irq < VGIC_NR_SGIS || irq >= vcpu->kvm->arch.vgic.nr_irqs ||
> -		    !irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
> +		/* The PMU overflow interrupt can be a PPI or a valid SPI. */
> +		if (!(irq_is_ppi(irq) || vgic_valid_spi(vcpu->kvm, irq)))
> +			return -EINVAL;
> +
> +		if (!irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))

Why do we need to pass this boolean as a parameter? You could rewrite
irq_is_valid() to generate the is_ppi boolean by itself.

>  			return -EINVAL;
>  
>  		if (kvm_arm_pmu_irq_initialized(vcpu))
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From dirk.behme at gmail.com  Tue May 10 08:29:08 2016
From: dirk.behme at gmail.com (Dirk Behme)
Date: Tue, 10 May 2016 17:29:08 +0200
Subject: [PATCH] arm64: dts: r8a7795: Increase the size of GIC-400 mapped
 registers
In-Reply-To: <5731ED92.6080804@arm.com>
References: <1461047395-6532-1-git-send-email-dirk.behme@de.bosch.com>
 <CAMuHMdV6XOSiSv-mwovnCAMEPsgOc_vEhPPu0aYCgz74EF242g@mail.gmail.com>
 <5731ED92.6080804@arm.com>
Message-ID: <5731FE44.8010906@gmail.com>

On 10.05.2016 16:17, Marc Zyngier wrote:
> On 10/05/16 14:33, Geert Uytterhoeven wrote:
>> CC Marc, lakml
>>
>> On Tue, Apr 19, 2016 at 8:29 AM, Dirk Behme <dirk.behme at de.bosch.com> wrote:
>>> From: Pooya Keshavarzi <Pooya.Keshavarzi at de.bosch.com>
>>>
>>> There are some requirements about the GIC-400 memory layout and its
>>> mapping if using 64k aligned base addresses like on r8a7795.
>>>
>>> See e.g.
>>>
>>> http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=21550029f709072aacf3b9
>>>
>>> Map the whole memory range instead of only 0x2000. This will fix
>>> the issue that some hypervisors, e.g. Xen, fail to handle the
>>> interrupts correctly.
>>>
>>> Signed-off-by: Pooya Keshavarzi <Pooya.Keshavarzi at de.bosch.com>
>>> Signed-off-by: Dirk Behme <dirk.behme at de.bosch.com>
>>
>> Based on my understanding below
>> Acked-by: Geert Uytterhoeven <geert+renesas at glider.be>
>>
>>> ---
>>> Note: This patch is against renesas-drivers-2016-04-12-v4.6-rc3
>>>
>>>   arch/arm64/boot/dts/renesas/r8a7795.dtsi | 4 ++--
>>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
>>> index 8be9424..d880fd4 100644
>>> --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
>>> +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
>>> @@ -160,9 +160,9 @@
>>>                          #address-cells = <0>;
>>>                          interrupt-controller;
>>>                          reg = <0x0 0xf1010000 0 0x1000>,
>>> -                             <0x0 0xf1020000 0 0x2000>,
>>> +                             <0x0 0xf1020000 0 0x20000>,
>>>                                <0x0 0xf1040000 0 0x20000>,
>>> -                             <0x0 0xf1060000 0 0x2000>;
>>> +                             <0x0 0xf1060000 0 0x20000>;
>>>                          interrupts = <GIC_PPI 9
>>>                                          (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
>>>                  };
>>
>> Region 0:
>>      4 KiB-pages 0xf1011000-0xf101ffff are aliased to 0xf1010000-0xf1010fff,
>>      but we need the first 4 KiB only.
>>
>> Region 1:
>>      4 KiB-pages 0xf1021000-0xf102ffff are aliased to 0xf1020000-0xf1020fff,
>>      4 KiB-pages 0xf1030000-0xf103ffff are all zeroes, probably due to
>>      non-secure mode?
>
> No. This 4kB page only contain a single register (GICC_DIR), which is
> WO/RAZ.
>
>>
>> Region 2:
>>      4 KiB-pages 0xf1041000-0xf104ffff are aliased to 0xf1040000-0xf1040fff,
>>      4 KiB-pages 0xf1050000-0xf105ffff are all zeroes, probably due to
>>      non-secure mode?
>
> Neither. The aliases are an unused feature of GIC400 exposing the other
> CPUs view of the same registers...
>
>>
>> Region 3:
>>      4 KiB-pages 0xf1061000-0xf106ffff are aliased to 0xf1060000-0xf1060fff,
>>      4 KiB-pages 0xf1070000-0xf107ffff are all zeroes, probably due to
>>      non-secure mode?
>
> Same as region 1.
>
>>
>> Region 2 already had a 128 KiB size before, which allowed to use 8 KiB at
>> 0xf104f000.
>
> No. This region (GICH) only needs the first 256 bytes or so. The rest is
> either RAZ/WI or useless stuff.
>
>>
>> An 8 KiB size for regions 1 and 3 indeed didn't make much sense, as this
>> covered two identical (aliased) 4 KiB pages, instead of two different pages
>> at offset 0xf000.
>
> While we're at it, adding a pointer to the documentation (GIC400 and
> SBSA) would be tremendously useful, as it'd avoid misinterpreting the
> various bits.


If anybody could give a short description I could copy & paste into 
the commit message that would be quite helpful :)


Best regards

Dirk



From eric.auger at linaro.org  Tue May 10 08:28:09 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 17:28:09 +0200
Subject: [PATCH v3 19/55] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <1462531568-9799-20-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-20-git-send-email-andre.przywara@arm.com>
Message-ID: <5731FE09.3000007@linaro.org>

On 05/06/2016 12:45 PM, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> As the GICv3 virtual interface registers differ from their GICv2
> siblings, we need different handlers for processing maintenance
> interrupts and reading/writing to the LRs.
> Implement the respective handler functions and connect them to
> existing code to be called if the host is using a GICv3.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - remove outdated comment about the dist_lock
> - add WARN_ON about LR_STATE not being 0 in maintenance interrupts
> 
> Changelog v1 .. v2:
> - inject the IRQ priority into the list register
> 
> Changelog v2 .. v3:
> - remove no longer needed irqchip/arm-gic.h inclusion
> 
>  include/linux/irqchip/arm-gic-v3.h |   1 +
>  virt/kvm/arm/vgic/vgic-v3.c        | 168 +++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.c           |  25 ++++--
>  virt/kvm/arm/vgic/vgic.h           |  29 +++++++
>  4 files changed, 218 insertions(+), 5 deletions(-)
>  create mode 100644 virt/kvm/arm/vgic/vgic-v3.c
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index ec938d1..35e93cf 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -275,6 +275,7 @@
>  #define ICH_LR_ACTIVE_BIT		(1ULL << 63)
>  #define ICH_LR_PHYS_ID_SHIFT		32
>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
> +#define ICH_LR_PRIORITY_SHIFT		48
>  
>  /* These are for GICv2 emulation only */
>  #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> new file mode 100644
> index 0000000..43d1dd7
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -0,0 +1,168 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * 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/irqchip/arm-gic-v3.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +
> +#include "vgic.h"
> +
> +void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
> +	u32 model = vcpu->kvm->arch.vgic.vgic_model;
> +
> +	if (cpuif->vgic_misr & ICH_MISR_EOI) {
> +		unsigned long eisr_bmap = cpuif->vgic_eisr;
> +		int lr;
> +
> +		for_each_set_bit(lr, &eisr_bmap, kvm_vgic_global_state.nr_lr) {
used_lrs?
> +			u32 intid;
> +			u64 val = cpuif->vgic_lr[lr];
> +
> +			if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
> +				intid = val & ICH_LR_VIRTUAL_ID_MASK;
> +			else
> +				intid = val & GICH_LR_VIRTUALID;
> +
> +			WARN_ON(cpuif->vgic_lr[lr] & ICH_LR_STATE);
> +
> +			kvm_notify_acked_irq(vcpu->kvm, 0,
> +					     intid - VGIC_NR_PRIVATE_IRQS);
> +
> +			cpuif->vgic_elrsr |= 1ULL << lr;
> +		}
> +
> +		/*
> +		 * In the next iterations of the vcpu loop, if we sync
> +		 * the vgic state after flushing it, but before
> +		 * entering the guest (this happens for pending
> +		 * signals and vmid rollovers), then make sure we
> +		 * don't pick up any old maintenance interrupts here.
> +		 */
> +		cpuif->vgic_eisr = 0;
> +	}
> +
> +	cpuif->vgic_hcr &= ~ICH_HCR_UIE;
> +}
> +
> +void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
> +
> +	cpuif->vgic_hcr |= ICH_HCR_UIE;
> +}
> +
> +void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
> +	u32 model = vcpu->kvm->arch.vgic.vgic_model;
> +	int lr;
> +
> +	/* Assumes ap_list_lock held */
I don't think there is such requirement and failed finding the lock held.

Besides Reviewed-by: Eric Auger <eric.auger at linaro.org>

Eric
> +
> +	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
> +		u64 val = cpuif->vgic_lr[lr];
> +		u32 intid;
> +		struct vgic_irq *irq;
> +
> +		if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
> +			intid = val & ICH_LR_VIRTUAL_ID_MASK;
> +		else
> +			intid = val & GICH_LR_VIRTUALID;
> +		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		/* Always preserve the active bit */
> +		irq->active = !!(val & ICH_LR_ACTIVE_BIT);
> +
> +		/* Edge is the only case where we preserve the pending bit */
> +		if (irq->config == VGIC_CONFIG_EDGE &&
> +		    (val & ICH_LR_PENDING_BIT)) {
> +			irq->pending = true;
> +
> +			if (vgic_irq_is_sgi(intid) &&
> +			    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
> +				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
> +
> +				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
> +				irq->source |= (1 << cpuid);
> +			}
> +		}
> +
> +		/* Clear soft pending state when level irqs have been acked */
> +		if (irq->config == VGIC_CONFIG_LEVEL &&
> +		    !(val & ICH_LR_PENDING_BIT)) {
> +			irq->soft_pending = false;
> +			irq->pending = irq->line_level;
> +		}
> +
> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
> +/* Requires the irq to be locked already */
> +void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
> +{
> +	u32 model = vcpu->kvm->arch.vgic.vgic_model;
> +	u64 val = irq->intid;
> +
> +	if (irq->pending) {
> +		val |= ICH_LR_PENDING_BIT;
> +
> +		if (irq->config == VGIC_CONFIG_EDGE)
> +			irq->pending = false;
> +
> +		if (vgic_irq_is_sgi(irq->intid) &&
> +		    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
> +			u32 src = ffs(irq->source);
> +
> +			BUG_ON(!src);
> +			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
> +			irq->source &= ~(1 << (src - 1));
> +			if (irq->source)
> +				irq->pending = true;
> +		}
> +	}
> +
> +	if (irq->active)
> +		val |= ICH_LR_ACTIVE_BIT;
> +
> +	if (irq->hw) {
> +		val |= ICH_LR_HW;
> +		val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
> +	} else {
> +		if (irq->config == VGIC_CONFIG_LEVEL)
> +			val |= ICH_LR_EOI;
> +	}
> +
> +	/*
> +	 * Currently all guest IRQs are Group1, as Group0 would result
> +	 * in a FIQ in the guest, which it wouldn't expect.
> +	 * Eventually we want to make this configurable, so we may
> +	 * revisit this in the future.
> +	 */
> +	if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
> +		val |= ICH_LR_GROUP;
> +
> +	val |= (u64)irq->priority << ICH_LR_PRIORITY_SHIFT;
> +
> +	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = val;
> +}
> +
> +void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
> +{
> +	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 68d885c..64d5b45 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -397,12 +397,18 @@ retry:
>  
>  static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
>  {
> -	vgic_v2_process_maintenance(vcpu);
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_process_maintenance(vcpu);
> +	else
> +		vgic_v3_process_maintenance(vcpu);
>  }
>  
>  static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
>  {
> -	vgic_v2_fold_lr_state(vcpu);
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_fold_lr_state(vcpu);
> +	else
> +		vgic_v3_fold_lr_state(vcpu);
>  }
>  
>  /* Requires the ap_list_lock and the irq_lock to be held. */
> @@ -412,17 +418,26 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
>  
> -	vgic_v2_populate_lr(vcpu, irq, lr);
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_populate_lr(vcpu, irq, lr);
> +	else
> +		vgic_v3_populate_lr(vcpu, irq, lr);
>  }
>  
>  static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
>  {
> -	vgic_v2_clear_lr(vcpu, lr);
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_clear_lr(vcpu, lr);
> +	else
> +		vgic_v3_clear_lr(vcpu, lr);
>  }
>  
>  static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
>  {
> -	vgic_v2_set_underflow(vcpu);
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_set_underflow(vcpu);
> +	else
> +		vgic_v3_set_underflow(vcpu);
>  }
>  
>  static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 0db490e..81b1a20 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -28,4 +28,33 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
>  void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
>  void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
>  
> +#ifdef CONFIG_KVM_ARM_VGIC_V3
> +void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
> +void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
> +void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
> +void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
> +void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
> +#else
> +static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +static inline void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +static inline void vgic_v3_populate_lr(struct kvm_vcpu *vcpu,
> +				       struct vgic_irq *irq, int lr)
> +{
> +}
> +
> +static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
> +{
> +}
> +
> +static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
> +{
> +}
> +#endif
> +
>  #endif
> 



From alex.williamson at redhat.com  Tue May 10 08:29:51 2016
From: alex.williamson at redhat.com (Alex Williamson)
Date: Tue, 10 May 2016 09:29:51 -0600
Subject: [PATCH v9 4/7] vfio: allow reserved msi iova registration
In-Reply-To: <1462362858-2925-5-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-5-git-send-email-eric.auger@linaro.org>
Message-ID: <20160510092951.67c2173e@t450s.home>

On Wed,  4 May 2016 11:54:15 +0000
Eric Auger <eric.auger at linaro.org> wrote:

> The user is allowed to register a reserved MSI IOVA range by using the
> DMA MAP API and setting the new flag: VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA.
> This region is stored in the vfio_dma rb tree. At that point the iova
> range is not mapped to any target address yet. The host kernel will use
> those iova when needed, typically when MSIs are allocated.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Bharat Bhushan <Bharat.Bhushan at freescale.com>
> 
> ---
> v7 -> v8:
> - use iommu_msi_set_aperture function. There is no notion of
>   unregistration anymore since the reserved msi slot remains
>   until the container gets closed.
> 
> v6 -> v7:
> - use iommu_free_reserved_iova_domain
> - convey prot attributes downto dma-reserved-iommu iova domain creation
> - reserved bindings teardown now performed on iommu domain destruction
> - rename VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA into
>          VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA
> - change title
> - pass the protection attribute to dma-reserved-iommu API
> 
> v3 -> v4:
> - use iommu_alloc/free_reserved_iova_domain exported by dma-reserved-iommu
> - protect vfio_register_reserved_iova_range implementation with
>   CONFIG_IOMMU_DMA_RESERVED
> - handle unregistration by user-space and on vfio_iommu_type1 release
> 
> v1 -> v2:
> - set returned value according to alloc_reserved_iova_domain result
> - free the iova domains in case any error occurs
> 
> RFC v1 -> v1:
> - takes into account Alex comments, based on
>   [RFC PATCH 1/6] vfio: Add interface for add/del reserved iova region:
> - use the existing dma map/unmap ioctl interface with a flag to register
>   a reserved IOVA range. A single reserved iova region is allowed.
> ---
>  drivers/vfio/vfio_iommu_type1.c | 78 ++++++++++++++++++++++++++++++++++++++++-
>  include/uapi/linux/vfio.h       | 10 +++++-
>  2 files changed, 86 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 94a9916..4d3a6f1 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -36,6 +36,7 @@
>  #include <linux/uaccess.h>
>  #include <linux/vfio.h>
>  #include <linux/workqueue.h>
> +#include <linux/msi-iommu.h>
>  
>  #define DRIVER_VERSION  "0.2"
>  #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson at redhat.com>"
> @@ -445,6 +446,20 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
>  	vfio_lock_acct(-unlocked);
>  }
>  
> +static int vfio_set_msi_aperture(struct vfio_iommu *iommu,
> +				dma_addr_t iova, size_t size)
> +{
> +	struct vfio_domain *d;
> +	int ret = 0;
> +
> +	list_for_each_entry(d, &iommu->domain_list, next) {
> +		ret = iommu_msi_set_aperture(d->domain, iova, iova + size - 1);
> +		if (ret)
> +			break;
> +	}
> +	return ret;
> +}
> +
>  static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
>  {
>  	vfio_unmap_unpin(iommu, dma);
> @@ -693,6 +708,63 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
>  	return ret;
>  }
>  
> +static int vfio_register_msi_range(struct vfio_iommu *iommu,
> +				   struct vfio_iommu_type1_dma_map *map)
> +{
> +	dma_addr_t iova = map->iova;
> +	size_t size = map->size;
> +	int ret = 0;
> +	struct vfio_dma *dma;
> +	unsigned long order;
> +	uint64_t mask;
> +
> +	/* Verify that none of our __u64 fields overflow */
> +	if (map->size != size || map->iova != iova)
> +		return -EINVAL;
> +
> +	order =  __ffs(vfio_pgsize_bitmap(iommu));
> +	mask = ((uint64_t)1 << order) - 1;
> +
> +	WARN_ON(mask & PAGE_MASK);
> +
> +	if (!size || (size | iova) & mask)
> +		return -EINVAL;
> +
> +	/* Don't allow IOVA address wrap */
> +	if (iova + size - 1 < iova)
> +		return -EINVAL;
> +
> +	mutex_lock(&iommu->lock);
> +
> +	if (vfio_find_dma(iommu, iova, size, VFIO_IOVA_ANY)) {
> +		ret =  -EEXIST;
> +		goto unlock;
> +	}
> +
> +	dma = kzalloc(sizeof(*dma), GFP_KERNEL);
> +	if (!dma) {
> +		ret = -ENOMEM;
> +		goto unlock;
> +	}
> +
> +	dma->iova = iova;
> +	dma->size = size;
> +	dma->type = VFIO_IOVA_RESERVED;

[oops, forgot to send this reply with the others]

I'm tempted to suggest we set type explicitly in the USER case too just
to make that abundantly clear rather than taking advantage of the
kzalloc struct.

> +
> +	ret = vfio_set_msi_aperture(iommu, iova, size);
> +	if (ret)
> +		goto free_unlock;
> +
> +	vfio_link_dma(iommu, dma);
> +	goto unlock;
> +
> +free_unlock:
> +	kfree(dma);
> +unlock:
> +	mutex_unlock(&iommu->lock);
> +	return ret;
> +}
> +
>  static int vfio_bus_type(struct device *dev, void *data)
>  {
>  	struct bus_type **bus = data;
> @@ -1062,7 +1134,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>  	} else if (cmd == VFIO_IOMMU_MAP_DMA) {
>  		struct vfio_iommu_type1_dma_map map;
>  		uint32_t mask = VFIO_DMA_MAP_FLAG_READ |
> -				VFIO_DMA_MAP_FLAG_WRITE;
> +				VFIO_DMA_MAP_FLAG_WRITE |
> +				VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA;
>  
>  		minsz = offsetofend(struct vfio_iommu_type1_dma_map, size);
>  
> @@ -1072,6 +1145,9 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>  		if (map.argsz < minsz || map.flags & ~mask)
>  			return -EINVAL;
>  
> +		if (map.flags & VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA)
> +			return vfio_register_msi_range(iommu, &map);
> +
>  		return vfio_dma_do_map(iommu, &map);
>  
>  	} else if (cmd == VFIO_IOMMU_UNMAP_DMA) {
> diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
> index 255a211..4a9dbc2 100644
> --- a/include/uapi/linux/vfio.h
> +++ b/include/uapi/linux/vfio.h
> @@ -498,12 +498,19 @@ struct vfio_iommu_type1_info {
>   *
>   * Map process virtual addresses to IO virtual addresses using the
>   * provided struct vfio_dma_map. Caller sets argsz. READ &/ WRITE required.
> + *
> + * In case RESERVED_MSI_IOVA flag is set, the API only aims at registering an
> + * IOVA region that will be used on some platforms to map the host MSI frames.
> + * In that specific case, vaddr is ignored. Once registered, an MSI reserved
> + * IOVA region stays until the container is closed.
>   */
>  struct vfio_iommu_type1_dma_map {
>  	__u32	argsz;
>  	__u32	flags;
>  #define VFIO_DMA_MAP_FLAG_READ (1 << 0)		/* readable from device */
>  #define VFIO_DMA_MAP_FLAG_WRITE (1 << 1)	/* writable from device */
> +/* reserved iova for MSI vectors*/
> +#define VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA (1 << 2)
>  	__u64	vaddr;				/* Process virtual address */
>  	__u64	iova;				/* IO virtual address */
>  	__u64	size;				/* Size of mapping (bytes) */
> @@ -519,7 +526,8 @@ struct vfio_iommu_type1_dma_map {
>   * Caller sets argsz.  The actual unmapped size is returned in the size
>   * field.  No guarantee is made to the user that arbitrary unmaps of iova
>   * or size different from those used in the original mapping call will
> - * succeed.
> + * succeed. Once registered, an MSI region cannot be unmapped and stays
> + * until the container is closed.
>   */
>  struct vfio_iommu_type1_dma_unmap {
>  	__u32	argsz;



From eric.auger at linaro.org  Tue May 10 08:34:28 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 17:34:28 +0200
Subject: [PATCH v9 4/7] vfio: allow reserved msi iova registration
In-Reply-To: <20160510092951.67c2173e@t450s.home>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-5-git-send-email-eric.auger@linaro.org>
 <20160510092951.67c2173e@t450s.home>
Message-ID: <5731FF84.6040804@linaro.org>

Hi Alex,
On 05/10/2016 05:29 PM, Alex Williamson wrote:
> On Wed,  4 May 2016 11:54:15 +0000
> Eric Auger <eric.auger at linaro.org> wrote:
> 
>> The user is allowed to register a reserved MSI IOVA range by using the
>> DMA MAP API and setting the new flag: VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA.
>> This region is stored in the vfio_dma rb tree. At that point the iova
>> range is not mapped to any target address yet. The host kernel will use
>> those iova when needed, typically when MSIs are allocated.
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>> Signed-off-by: Bharat Bhushan <Bharat.Bhushan at freescale.com>
>>
>> ---
>> v7 -> v8:
>> - use iommu_msi_set_aperture function. There is no notion of
>>   unregistration anymore since the reserved msi slot remains
>>   until the container gets closed.
>>
>> v6 -> v7:
>> - use iommu_free_reserved_iova_domain
>> - convey prot attributes downto dma-reserved-iommu iova domain creation
>> - reserved bindings teardown now performed on iommu domain destruction
>> - rename VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA into
>>          VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA
>> - change title
>> - pass the protection attribute to dma-reserved-iommu API
>>
>> v3 -> v4:
>> - use iommu_alloc/free_reserved_iova_domain exported by dma-reserved-iommu
>> - protect vfio_register_reserved_iova_range implementation with
>>   CONFIG_IOMMU_DMA_RESERVED
>> - handle unregistration by user-space and on vfio_iommu_type1 release
>>
>> v1 -> v2:
>> - set returned value according to alloc_reserved_iova_domain result
>> - free the iova domains in case any error occurs
>>
>> RFC v1 -> v1:
>> - takes into account Alex comments, based on
>>   [RFC PATCH 1/6] vfio: Add interface for add/del reserved iova region:
>> - use the existing dma map/unmap ioctl interface with a flag to register
>>   a reserved IOVA range. A single reserved iova region is allowed.
>> ---
>>  drivers/vfio/vfio_iommu_type1.c | 78 ++++++++++++++++++++++++++++++++++++++++-
>>  include/uapi/linux/vfio.h       | 10 +++++-
>>  2 files changed, 86 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
>> index 94a9916..4d3a6f1 100644
>> --- a/drivers/vfio/vfio_iommu_type1.c
>> +++ b/drivers/vfio/vfio_iommu_type1.c
>> @@ -36,6 +36,7 @@
>>  #include <linux/uaccess.h>
>>  #include <linux/vfio.h>
>>  #include <linux/workqueue.h>
>> +#include <linux/msi-iommu.h>
>>  
>>  #define DRIVER_VERSION  "0.2"
>>  #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson at redhat.com>"
>> @@ -445,6 +446,20 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
>>  	vfio_lock_acct(-unlocked);
>>  }
>>  
>> +static int vfio_set_msi_aperture(struct vfio_iommu *iommu,
>> +				dma_addr_t iova, size_t size)
>> +{
>> +	struct vfio_domain *d;
>> +	int ret = 0;
>> +
>> +	list_for_each_entry(d, &iommu->domain_list, next) {
>> +		ret = iommu_msi_set_aperture(d->domain, iova, iova + size - 1);
>> +		if (ret)
>> +			break;
>> +	}
>> +	return ret;
>> +}
>> +
>>  static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
>>  {
>>  	vfio_unmap_unpin(iommu, dma);
>> @@ -693,6 +708,63 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
>>  	return ret;
>>  }
>>  
>> +static int vfio_register_msi_range(struct vfio_iommu *iommu,
>> +				   struct vfio_iommu_type1_dma_map *map)
>> +{
>> +	dma_addr_t iova = map->iova;
>> +	size_t size = map->size;
>> +	int ret = 0;
>> +	struct vfio_dma *dma;
>> +	unsigned long order;
>> +	uint64_t mask;
>> +
>> +	/* Verify that none of our __u64 fields overflow */
>> +	if (map->size != size || map->iova != iova)
>> +		return -EINVAL;
>> +
>> +	order =  __ffs(vfio_pgsize_bitmap(iommu));
>> +	mask = ((uint64_t)1 << order) - 1;
>> +
>> +	WARN_ON(mask & PAGE_MASK);
>> +
>> +	if (!size || (size | iova) & mask)
>> +		return -EINVAL;
>> +
>> +	/* Don't allow IOVA address wrap */
>> +	if (iova + size - 1 < iova)
>> +		return -EINVAL;
>> +
>> +	mutex_lock(&iommu->lock);
>> +
>> +	if (vfio_find_dma(iommu, iova, size, VFIO_IOVA_ANY)) {
>> +		ret =  -EEXIST;
>> +		goto unlock;
>> +	}
>> +
>> +	dma = kzalloc(sizeof(*dma), GFP_KERNEL);
>> +	if (!dma) {
>> +		ret = -ENOMEM;
>> +		goto unlock;
>> +	}
>> +
>> +	dma->iova = iova;
>> +	dma->size = size;
>> +	dma->type = VFIO_IOVA_RESERVED;
> 
> [oops, forgot to send this reply with the others]
> 
> I'm tempted to suggest we set type explicitly in the USER case too just
> to make that abundantly clear rather than taking advantage of the
> kzalloc struct.

no worries. OK I will set the dma type explicitly in vfio_dma_do_map too.

Thanks

Eric
> 
>> +
>> +	ret = vfio_set_msi_aperture(iommu, iova, size);
>> +	if (ret)
>> +		goto free_unlock;
>> +
>> +	vfio_link_dma(iommu, dma);
>> +	goto unlock;
>> +
>> +free_unlock:
>> +	kfree(dma);
>> +unlock:
>> +	mutex_unlock(&iommu->lock);
>> +	return ret;
>> +}
>> +
>>  static int vfio_bus_type(struct device *dev, void *data)
>>  {
>>  	struct bus_type **bus = data;
>> @@ -1062,7 +1134,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>>  	} else if (cmd == VFIO_IOMMU_MAP_DMA) {
>>  		struct vfio_iommu_type1_dma_map map;
>>  		uint32_t mask = VFIO_DMA_MAP_FLAG_READ |
>> -				VFIO_DMA_MAP_FLAG_WRITE;
>> +				VFIO_DMA_MAP_FLAG_WRITE |
>> +				VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA;
>>  
>>  		minsz = offsetofend(struct vfio_iommu_type1_dma_map, size);
>>  
>> @@ -1072,6 +1145,9 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>>  		if (map.argsz < minsz || map.flags & ~mask)
>>  			return -EINVAL;
>>  
>> +		if (map.flags & VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA)
>> +			return vfio_register_msi_range(iommu, &map);
>> +
>>  		return vfio_dma_do_map(iommu, &map);
>>  
>>  	} else if (cmd == VFIO_IOMMU_UNMAP_DMA) {
>> diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
>> index 255a211..4a9dbc2 100644
>> --- a/include/uapi/linux/vfio.h
>> +++ b/include/uapi/linux/vfio.h
>> @@ -498,12 +498,19 @@ struct vfio_iommu_type1_info {
>>   *
>>   * Map process virtual addresses to IO virtual addresses using the
>>   * provided struct vfio_dma_map. Caller sets argsz. READ &/ WRITE required.
>> + *
>> + * In case RESERVED_MSI_IOVA flag is set, the API only aims at registering an
>> + * IOVA region that will be used on some platforms to map the host MSI frames.
>> + * In that specific case, vaddr is ignored. Once registered, an MSI reserved
>> + * IOVA region stays until the container is closed.
>>   */
>>  struct vfio_iommu_type1_dma_map {
>>  	__u32	argsz;
>>  	__u32	flags;
>>  #define VFIO_DMA_MAP_FLAG_READ (1 << 0)		/* readable from device */
>>  #define VFIO_DMA_MAP_FLAG_WRITE (1 << 1)	/* writable from device */
>> +/* reserved iova for MSI vectors*/
>> +#define VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA (1 << 2)
>>  	__u64	vaddr;				/* Process virtual address */
>>  	__u64	iova;				/* IO virtual address */
>>  	__u64	size;				/* Size of mapping (bytes) */
>> @@ -519,7 +526,8 @@ struct vfio_iommu_type1_dma_map {
>>   * Caller sets argsz.  The actual unmapped size is returned in the size
>>   * field.  No guarantee is made to the user that arbitrary unmaps of iova
>>   * or size different from those used in the original mapping call will
>> - * succeed.
>> + * succeed. Once registered, an MSI region cannot be unmapped and stays
>> + * until the container is closed.
>>   */
>>  struct vfio_iommu_type1_dma_unmap {
>>  	__u32	argsz;
> 



From mmarek at suse.com  Tue May 10 08:45:17 2016
From: mmarek at suse.com (Michal Marek)
Date: Tue, 10 May 2016 17:45:17 +0200
Subject: [PATCH v1] builddeb: fix missing headers in linux-headers package
In-Reply-To: <572B5BC4.7080402@codeaurora.org>
References: <1459445479-10948-1-git-send-email-asamson@codeaurora.org>
 <572B5BC4.7080402@codeaurora.org>
Message-ID: <20160510154516.GF13314@pobox.suse.cz>

On Thu, May 05, 2016 at 10:42:12AM -0400, Christopher Covington wrote:
> On 03/31/2016 01:31 PM, Azriel Samson wrote:
> > The kernel headers package (linux-headers) doesn't include
> > header files from other architectures required to build
> > out-of-tree modules.
> > 
> > For e.g. on ARM64, opcodes.h includes the same file from ARM
> > which causes the following error:
> > ./arch/arm64/include/asm/opcodes.h:1:43: fatal error:
> > ../../arm/include/asm/opcodes.h: No such file or directory
> > compilation terminated.
> > 
> > Signed-off-by: Azriel Samson <asamson at codeaurora.org>
> > ---
> >  scripts/package/builddeb | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/scripts/package/builddeb b/scripts/package/builddeb
> > index 6c3b038..06ba0d9 100755
> > --- a/scripts/package/builddeb
> > +++ b/scripts/package/builddeb
> > @@ -322,7 +322,7 @@ fi
> >  
> >  # Build kernel header package
> >  (cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles"
> > -(cd $srctree; find arch/$SRCARCH/include include scripts -type f) >> "$objtree/debian/hdrsrcfiles"
> > +(cd $srctree; find arch/*/include include scripts -type f) >> "$objtree/debian/hdrsrcfiles"
> >  (cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles"
> >  (cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles"
> >  (cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f) >> "$objtree/debian/hdrobjfiles"
> 
> Any feedback on this? Michal, do you think this would be appropriate to
> include in 4.7?

Applied to kbuild.git#misc now.

Michal


From arnd at arndb.de  Tue May 10 08:45:31 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 17:45:31 +0200
Subject: [RESEND PATCH 0/5] gcov fixes and maybe-uninitialized warnings
In-Reply-To: <20160510151437.GA12889@pobox.suse.cz>
References: <1461598531-2190169-1-git-send-email-arnd@arndb.de>
 <20160510151437.GA12889@pobox.suse.cz>
Message-ID: <5021654.fHHR0eRNyc@wuerfel>

On Tuesday 10 May 2016 17:14:37 Michal Marek wrote:
> On Mon, Apr 25, 2016 at 05:35:26PM +0200, Arnd Bergmann wrote:
> > Hi Michal,
> > 
> > This is a resend of a series I originally sent back in February, but
> > unfortunately I never heard back from you. Could you apply these
> > patches for v4.7?
> > 
> > [PATCH 1/5] Kbuild: change CC_OPTIMIZE_FOR_SIZE definition
> > [PATCH 2/5] Kbuild: disable 'maybe-uninitialized' warning for
> > [PATCH 3/5] gcov: disable for COMPILE_TEST
> > [PATCH 4/5] gcov: disable tree-loop-im to reduce stack usage
> > [PATCH 5/5] gcov: disable -Wmaybe-uninitialized warning
> 
> Applied now, sorry for the delay.

Great, thanks!

	Arnd


From boris.brezillon at free-electrons.com  Tue May 10 08:47:39 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 10 May 2016 17:47:39 +0200
Subject: [PATCH v7 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <CAL_JsqL0o7Q4yNF1CCvJDx0nvJLRXZ-ieCDEkOa9ByfvdnuLRw@mail.gmail.com>
References: <1461845007-23139-1-git-send-email-boris.brezillon@free-electrons.com>
 <1461845007-23139-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160503164019.GA1604@rob-hp-laptop>
 <20160503185153.5cfddc32@bbrezillon>
 <CAL_Jsq+cTvW=wUUQmD2R-nZ9m3U5E00yEfLy=-Z_X6EQZRO4NQ@mail.gmail.com>
 <20160504113852.10a2dd84@bbrezillon>
 <CAL_Jsq+4aL5znA3zOKdcJb+pEXhVOQthkFF6DN2+P6U37t2o6g@mail.gmail.com>
 <20160504153547.60d736bb@bbrezillon>
 <20160510100448.49834120@bbrezillon>
 <20160510110742.GI687@leverpostej>
 <20160510144143.1965ee5e@bbrezillon>
 <CACh+v5M2yZ403+VwvRMYeGwfhpP+aCGnnNhiQ1wjrxS5fVGVEA@mail.gmail.com>
 <CAL_JsqL0o7Q4yNF1CCvJDx0nvJLRXZ-ieCDEkOa9ByfvdnuLRw@mail.gmail.com>
Message-ID: <20160510174739.624656c6@bbrezillon>

On Tue, 10 May 2016 09:52:41 -0500
Rob Herring <robh at kernel.org> wrote:

> On Tue, May 10, 2016 at 8:08 AM, Jean-Jacques Hiblot
> <jjhiblot at traphandler.com> wrote:
> > 2016-05-10 14:41 GMT+02:00 Boris Brezillon <boris.brezillon at free-electrons.com>:  
> >> On Tue, 10 May 2016 12:07:42 +0100
> >> Mark Rutland <mark.rutland at arm.com> wrote:
> >>  
> >>> On Tue, May 10, 2016 at 10:04:48AM +0200, Boris Brezillon wrote:  
> >>> > On Wed, 4 May 2016 15:35:47 +0200
> >>> > Boris Brezillon <boris.brezillon at free-electrons.com> wrote:
> >>> >  
> >>> > > On Wed, 4 May 2016 08:06:10 -0500
> >>> > > Rob Herring <robh at kernel.org> wrote:
> >>> > >  
> >>> > > > On Wed, May 4, 2016 at 4:38 AM, Boris Brezillon
> >>> > > > <boris.brezillon at free-electrons.com> wrote:  
> >>> > > > > Hi Rob,
> >>> > > > >
> >>> > > > > On Tue, 3 May 2016 14:11:04 -0500
> >>> > > > > Rob Herring <robh at kernel.org> wrote:
> >>> > > > >  
> >>> > > > >> On Tue, May 3, 2016 at 11:51 AM, Boris Brezillon
> >>> > > > >> <boris.brezillon at free-electrons.com> wrote:  
> >>> > > > >> > Hi Rob,
> >>> > > > >> >
> >>> > > > >> > On Tue, 3 May 2016 11:40:19 -0500
> >>> > > > >> > Rob Herring <robh at kernel.org> wrote:
> >>> > > > >> >  
> >>> > > > >> >> On Thu, Apr 28, 2016 at 02:03:27PM +0200, Boris Brezillon wrote:  
> >>> > > > >> >> > The EBI (External Bus Interface) is used to access external peripherals
> >>> > > > >> >> > (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
> >>> > > > >> >> > Each device is assigned a CS line and an address range and can have its
> >>> > > > >> >> > own configuration (timings, access mode, bus width, ...).
> >>> > > > >> >> > This driver provides a generic DT binding to configure a device according
> >>> > > > >> >> > to its requirements.
> >>> > > > >> >> > For specific device controllers (like the NAND one) the SMC timings
> >>> > > > >> >> > should be configured by the controller driver through the matrix and smc
> >>> > > > >> >> > syscon regmaps.  
> >>> > > >
> >>> > > > [...]
> >>> > > >  
> >>> > > > >> >> > +EBI bus configuration associated with specific chip-select will be defined in
> >>> > > > >> >> > +the configs subnode. This configs node will in turn contain several subnodes
> >>> > > > >> >> > +named config-<cs-id>, each of them containing the following properties.  
> >>> > > > >> >>
> >>> > > > >> >> This is a bit unusual. Why not just part of the child device nodes?  
> >>> > > > >> >
> >>> > > > >> > Oh, come on! I reworked the binding because Mark complained about the
> >>> > > > >> > previous binding which was doing exactly what you're suggesting. Can
> >>> > > > >> > you please be consistent in your reviews...  
> >>> > > > >>
> >>> > > > >> No, Mark and I both have our opinions. Which part of this patch
> >>> > > > >> explains the history?  
> >>> > > > >
> >>> > > > > Hm, it's in patch 1/2 (just dropped the cover letter, which might not
> >>> > > > > be such a good idea).
> >>> > > > >  
> >>> > > > >> If the revision history is not in the patch, I'm
> >>> > > > >> not looking at it.
> >>> > > > >>
> >>> > > > >> My issue with it this way is that it has invented yet another way to
> >>> > > > >> describe timings. I would like to be consistent across external bus
> >>> > > > >> descriptions, but we're not very consistent to begin with though. The
> >>> > > > >> most common seems to be the way you first did it. But I agree that it
> >>> > > > >> is kind of screwy to have an intermediate node unless the controller
> >>> > > > >> itself has sub-blocks within it and is not the established way to
> >>> > > > >> describe a bus with chip selects. I would either put the properties
> >>> > > > >> directly in the child nodes (e.g. flash at 0,0) or put your config nodes
> >>> > > > >> in the device node. I'd call it timings instead of config, but that's
> >>> > > > >> just bikeshedding.  
> >>> > > > >
> >>> > > > > Well, it's not only describing timings (see atmel,bus-width,
> >>> > > > > atmel,byte-access-type, ...), but I'm fine with either names :).
> >>> > > > >  
> >>> > > > >>
> >>> > > > >> memory-controller at 1000 {
> >>> > > > >>   ...
> >>> > > > >>   flash at 0,0 {
> >>> > > > >>     timings {
> >>> > > > >>       ...
> >>> > > > >>     };
> >>> > > > >>   };
> >>> > > > >> };  
> >>> > > > >
> >>> > > > > Okay. Mark, what do you think of this approach?
> >>> > > > >
> >>> > > > > Note that one of my previous version was defining timings directly in
> >>> > > > > the EBI device node, and Arnd noted that doing so may cause problems
> >>> > > > > if one of the EBI property (or the config/timing node name) conflict
> >>> > > > > with the sub-device binding, which is why I decided to put the EBI
> >>> > > > > config definitions in a separate subnode.  
> >>> > > >
> >>> > > > You have vendor prefixes on all the properties so I don't think a
> >>> > > > collision is really a problem. It's also an established pattern in
> >>> > > > i.MX WEIM and OMAP GPMC (which are hiding in bindings/bus/) and I
> >>> > > > prefer consistency.  
> >>> > >
> >>> > > So let's summarize that.
> >>> > >
> >>> > > memory-controller at 1000 {
> >>> > >   ...
> >>> > >   flash at 0,0 {
> >>> > >           atmel,<ebi-prop-name> = <value>;
> >>> > >           ...
> >>> > >           <flash-device-prop> = <value>;
> >>> > >   };
> >>> > > };
> >>> > >
> >>> > > Would everyone agree on this representation?
> >>> > >
> >>> > > With this approach, it's a bit more complicated to detect the case
> >>> > > where we want to keep bootloader/firmware config, but it should be
> >>> > > doable (it's much more easier to test for the presence of a
> >>> > > config/timing node than verifying that either all or none of the
> >>> > > mandatory properties are here).
> >>> > >
> >>> > > Still remains the problem mentioned by Jean-Jacques: what if the
> >>> > > sub-device takes 2 CS lines. Should we apply the same setting to those
> >>> > > slots?
> >>> > >  
> >>> >
> >>> > Rob, Mark, Arnd, can you take a decision regarding this binding? This
> >>> > driver is floating around for quite some time, and we were asked to
> >>> > rework the binding several times (in time in an opposite direction).
> >>> >
> >>> > For the record, here is the thread I mentioned earlier [1]. In his
> >>> > answer, Arnd suggests to put timing and bus config description
> >>> > outside of the sub-device node. Mark recently complained about this
> >>> > representation, which led me to the configs/config-X appraoch, and now
> >>> > Rob suggests to go back to the first proposal.
> >>> >
> >>> > I'm fine doing that, but can you please all confirm that you agree on
> >>> > this binding?  
> >>>
> >>> Sorry for the delay in getting round to this, and sorry that this
> >>> appears to be going in circles.
> >>>
> >>> Please go with Rob's suggestion.  
> >>
> >> Okay. This changes a bit the constraints defined in the binding doc
> >> (no default values for undefined properties: we just keep the
> >> bootloader/firmware config), but otherwise should be easy to implement.
> >>  
> >>>
> >>> I'm not sure about the case where a device takes 2 CS lines. I would
> >>> assume that in practice that a sub-device covered my multiple CS lines
> >>> expects the same timings for all its MMIO space, and so having that
> >>> uniform makes sense. Do we have a counter-example?  
> >>
> >> Nope, I don't. JJH had one (interfacing with an FPGA), maybe he can
> >> detail this use case.
> >>  
> > I don't either. It makes sense that a single device with 2 CS uses the
> > same timings.
> > My use case was the other way around: 1 CS for several devices.  
> 
> Ah, I thought it was just wanting to share timings for several CS. In
> this case, it would probably make sense to have 3 levels of nodes
> (EBI, CS node with timings, device nodes) as you do have some logic in
> between to do address decoding. But I think the simple case should
> still be 2 levels of nodes and that doesn't really affect the EBI
> binding. It just cares that timings are in the immediate child nodes.

I'd expect the sub-device driver to change the configuration by itself
in such complex cases (I'm planning to expose APIs to let other drivers
manually configure the EBI bus for their specific use case: it's kind
of required for the NAND controller driver anyway).

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


From john at metanate.com  Tue May 10 08:50:46 2016
From: john at metanate.com (John Keeping)
Date: Tue, 10 May 2016 16:50:46 +0100
Subject: [PATCH] iommu/rockchip: fix zap cache during device attach
Message-ID: <20160510155046.24515-1-john@metanate.com>

rk_iommu_command() takes a struct rk_iommu and iterates over the slave
MMUs, so this is doubly wrong in that we're passing in the wrong pointer
and talking to MMUs that we shouldn't be.

Fixes: cd6438c5f844 ("iommu/rockchip: Reconstruct to support multi slaves")
Signed-off-by: John Keeping <john at metanate.com>
---
 drivers/iommu/rockchip-iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 5710a06c3049..0ea8d9a24de0 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -815,7 +815,7 @@ static int rk_iommu_attach_device(struct iommu_domain *domain,
 	dte_addr = virt_to_phys(rk_domain->dt);
 	for (i = 0; i < iommu->num_mmu; i++) {
 		rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, dte_addr);
-		rk_iommu_command(iommu->bases[i], RK_MMU_CMD_ZAP_CACHE);
+		rk_iommu_base_command(iommu->bases[i], RK_MMU_CMD_ZAP_CACHE);
 		rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, RK_MMU_IRQ_MASK);
 	}
 
-- 
2.8.2.565.gdb84f68.dirty



From catalin.marinas at arm.com  Tue May 10 08:55:58 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 10 May 2016 16:55:58 +0100
Subject: [PATCH] arm64: Make arch_randomize_brk avoid stack area
In-Reply-To: <1462535460.4575.3.camel@linaro.org>
References: <1461848638.2848.19.camel@linaro.org>
 <1462370994.2895.11.camel@linaro.org>
 <20160506111937.GK20671@e104818-lin.cambridge.arm.com>
 <1462535460.4575.3.camel@linaro.org>
Message-ID: <20160510155557.GD3214@e104818-lin.cambridge.arm.com>

On Fri, May 06, 2016 at 12:51:00PM +0100, Jon Medhurst (Tixy) wrote:
> On Fri, 2016-05-06 at 12:19 +0100, Catalin Marinas wrote:
> > On Wed, May 04, 2016 at 03:09:54PM +0100, Jon Medhurst (Tixy) wrote:
> > > Note, in practice, since commit d1fd836dcf00 ("mm: split ET_DYN ASLR
> > > from mmap ASLR") this problem shouldn't occur because the address chosen
> > > for loading binaries is well clear of the stack, however, prior to that
> > > the problem does occur because of the following...
> > 
> > [...]
> > 
> > > These changes have been tested on Linux v4.6-rc4 using 100000
> > > invocations of a program [1] that can display the offset of a process's
> > > brk...
> > 
> > [...]
> > 
> > > Signed-off-by: Jon Medhurst <tixy at linaro.org>
> > > Cc: <stable at vger.kernel.org> # 4.0 and earlier
> > 
> > I don't fully understand what we are supposed to do with this patch.
> > Should it only be applied to stable kernels prior to 4.0? Do we need it
> > in mainline? As you stated above, this problem does not exist in recent
> > kernels.
> 
> Well, if you think it's worthwhile defensive programming against future
> changes to elf loader, then it could go into latest kernels.

I don't think we should bother with latest upstream. AFAICT, with
splitting ET_DYN ASLR from the mmap one, we shouldn't hit this issue.
And I wouldn't expect the two regions to be unified again in the future.

> Otherwise, then yes, it's for Linux 4.0 and earlier. What's the
> process for that, email it to stable at vger.kernel.org direct?

Usually emailing stable at vger.kernel.org with an explanation of why it is
not needed in mainline since it is not a back-port.

> Is that OK without an Ack from an arm64 maintainer?

I guess it's up to the stable maintainers but in any case:

Acked-by: Catalin Marinas <catalin.marinas at arm.com>


From marc.zyngier at arm.com  Tue May 10 09:03:46 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 17:03:46 +0100
Subject: [PATCH] arm64: dts: r8a7795: Increase the size of GIC-400 mapped
 registers
In-Reply-To: <5731FE44.8010906@gmail.com>
References: <1461047395-6532-1-git-send-email-dirk.behme@de.bosch.com>
 <CAMuHMdV6XOSiSv-mwovnCAMEPsgOc_vEhPPu0aYCgz74EF242g@mail.gmail.com>
 <5731ED92.6080804@arm.com> <5731FE44.8010906@gmail.com>
Message-ID: <57320662.9010807@arm.com>

On 10/05/16 16:29, Dirk Behme wrote:
> On 10.05.2016 16:17, Marc Zyngier wrote:
>> On 10/05/16 14:33, Geert Uytterhoeven wrote:
>>> CC Marc, lakml
>>>
>>> On Tue, Apr 19, 2016 at 8:29 AM, Dirk Behme <dirk.behme at de.bosch.com> wrote:
>>>> From: Pooya Keshavarzi <Pooya.Keshavarzi at de.bosch.com>
>>>>
>>>> There are some requirements about the GIC-400 memory layout and its
>>>> mapping if using 64k aligned base addresses like on r8a7795.
>>>>
>>>> See e.g.
>>>>
>>>> http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=21550029f709072aacf3b9
>>>>
>>>> Map the whole memory range instead of only 0x2000. This will fix
>>>> the issue that some hypervisors, e.g. Xen, fail to handle the
>>>> interrupts correctly.
>>>>
>>>> Signed-off-by: Pooya Keshavarzi <Pooya.Keshavarzi at de.bosch.com>
>>>> Signed-off-by: Dirk Behme <dirk.behme at de.bosch.com>
>>>
>>> Based on my understanding below
>>> Acked-by: Geert Uytterhoeven <geert+renesas at glider.be>
>>>
>>>> ---
>>>> Note: This patch is against renesas-drivers-2016-04-12-v4.6-rc3
>>>>
>>>>   arch/arm64/boot/dts/renesas/r8a7795.dtsi | 4 ++--
>>>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
>>>> index 8be9424..d880fd4 100644
>>>> --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
>>>> +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
>>>> @@ -160,9 +160,9 @@
>>>>                          #address-cells = <0>;
>>>>                          interrupt-controller;
>>>>                          reg = <0x0 0xf1010000 0 0x1000>,
>>>> -                             <0x0 0xf1020000 0 0x2000>,
>>>> +                             <0x0 0xf1020000 0 0x20000>,
>>>>                                <0x0 0xf1040000 0 0x20000>,
>>>> -                             <0x0 0xf1060000 0 0x2000>;
>>>> +                             <0x0 0xf1060000 0 0x20000>;
>>>>                          interrupts = <GIC_PPI 9
>>>>                                          (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
>>>>                  };
>>>
>>> Region 0:
>>>      4 KiB-pages 0xf1011000-0xf101ffff are aliased to 0xf1010000-0xf1010fff,
>>>      but we need the first 4 KiB only.
>>>
>>> Region 1:
>>>      4 KiB-pages 0xf1021000-0xf102ffff are aliased to 0xf1020000-0xf1020fff,
>>>      4 KiB-pages 0xf1030000-0xf103ffff are all zeroes, probably due to
>>>      non-secure mode?
>>
>> No. This 4kB page only contain a single register (GICC_DIR), which is
>> WO/RAZ.
>>
>>>
>>> Region 2:
>>>      4 KiB-pages 0xf1041000-0xf104ffff are aliased to 0xf1040000-0xf1040fff,
>>>      4 KiB-pages 0xf1050000-0xf105ffff are all zeroes, probably due to
>>>      non-secure mode?
>>
>> Neither. The aliases are an unused feature of GIC400 exposing the other
>> CPUs view of the same registers...
>>
>>>
>>> Region 3:
>>>      4 KiB-pages 0xf1061000-0xf106ffff are aliased to 0xf1060000-0xf1060fff,
>>>      4 KiB-pages 0xf1070000-0xf107ffff are all zeroes, probably due to
>>>      non-secure mode?
>>
>> Same as region 1.
>>
>>>
>>> Region 2 already had a 128 KiB size before, which allowed to use 8 KiB at
>>> 0xf104f000.
>>
>> No. This region (GICH) only needs the first 256 bytes or so. The rest is
>> either RAZ/WI or useless stuff.
>>
>>>
>>> An 8 KiB size for regions 1 and 3 indeed didn't make much sense, as this
>>> covered two identical (aliased) 4 KiB pages, instead of two different pages
>>> at offset 0xf000.
>>
>> While we're at it, adding a pointer to the documentation (GIC400 and
>> SBSA) would be tremendously useful, as it'd avoid misinterpreting the
>> various bits.
> 
> 
> If anybody could give a short description I could copy & paste into 
> the commit message that would be quite helpful :)

Well, there is my reply to an earlier email in this very thread, as well
as the xen commit which quotes my original commit (which you could also
refer to).

I'll leave it to you to eradicate the swear words (or to leave them in
place as a testimony of what 4 years of GIC hacking can do to an
otherwise sane person).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From john at metanate.com  Tue May 10 09:03:53 2016
From: john at metanate.com (John Keeping)
Date: Tue, 10 May 2016 17:03:53 +0100
Subject: [PATCH 0/3] drm/rockchip: fix some sparse warnings
Message-ID: <20160510160356.1167-1-john@metanate.com>

The first patch wasn't found by sparse, but is something I noticed while
in the area.  The following two fix all of the sparse warnings inside
drm/rockchip.

John Keeping (3):
  drm/rockchip: dw_hdmi: remove unused #include
  drm/rockchip: fb: add missing header
  drm/rockchip: fix "should it be static?" warnings

 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 -
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 4 ++--
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 7 ++++---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++--
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 +-
 5 files changed, 9 insertions(+), 9 deletions(-)

-- 
2.8.2.565.gdb84f68.dirty



From john at metanate.com  Tue May 10 09:03:54 2016
From: john at metanate.com (John Keeping)
Date: Tue, 10 May 2016 17:03:54 +0100
Subject: [PATCH 1/3] drm/rockchip: dw_hdmi: remove unused #include
In-Reply-To: <20160510160356.1167-1-john@metanate.com>
References: <20160510160356.1167-1-john@metanate.com>
Message-ID: <20160510160356.1167-2-john@metanate.com>

drm_encoder_slave is not used in this file.

Signed-off-by: John Keeping <john at metanate.com>
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 801110f65a63..0665fb915579 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -15,7 +15,6 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_edid.h>
-#include <drm/drm_encoder_slave.h>
 #include <drm/bridge/dw_hdmi.h>
 
 #include "rockchip_drm_drv.h"
-- 
2.8.2.565.gdb84f68.dirty



From john at metanate.com  Tue May 10 09:03:55 2016
From: john at metanate.com (John Keeping)
Date: Tue, 10 May 2016 17:03:55 +0100
Subject: [PATCH 2/3] drm/rockchip: fb: add missing header
In-Reply-To: <20160510160356.1167-1-john@metanate.com>
References: <20160510160356.1167-1-john@metanate.com>
Message-ID: <20160510160356.1167-3-john@metanate.com>

This fixes the following sparse warnings:

drivers/gpu/drm/rockchip/rockchip_drm_fb.c:32:23: warning: symbol 'rockchip_fb_get_gem_obj' was not declared. Should it be static?
drivers/gpu/drm/rockchip/rockchip_drm_fb.c:315:24: warning: symbol 'rockchip_drm_framebuffer_init' was not declared. Should it be static?
drivers/gpu/drm/rockchip/rockchip_drm_fb.c:329:6: warning: symbol 'rockchip_drm_mode_config_init' was not declared. Should it be static?

Signed-off-by: John Keeping <john at metanate.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 8c10163a95bc..85aa87ee12f5 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -20,6 +20,7 @@
 #include <drm/drm_crtc_helper.h>
 
 #include "rockchip_drm_drv.h"
+#include "rockchip_drm_fb.h"
 #include "rockchip_drm_gem.h"
 
 #define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)
-- 
2.8.2.565.gdb84f68.dirty



From john at metanate.com  Tue May 10 09:03:56 2016
From: john at metanate.com (John Keeping)
Date: Tue, 10 May 2016 17:03:56 +0100
Subject: [PATCH 3/3] drm/rockchip: fix "should it be static?" warnings
In-Reply-To: <20160510160356.1167-1-john@metanate.com>
References: <20160510160356.1167-1-john@metanate.com>
Message-ID: <20160510160356.1167-4-john@metanate.com>

Combined with the previous commit, this fixes all of the sparse warnings
in drm/rockchip.

Signed-off-by: John Keeping <john at metanate.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 4 ++--
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 6 +++---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++--
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 399adf3c4224..b253f65c3e14 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -287,7 +287,7 @@ static void rockchip_drm_preclose(struct drm_device *dev,
 		rockchip_drm_crtc_cancel_pending_vblank(crtc, file_priv);
 }
 
-void rockchip_drm_lastclose(struct drm_device *dev)
+static void rockchip_drm_lastclose(struct drm_device *dev)
 {
 	struct rockchip_drm_private *priv = dev->dev_private;
 
@@ -307,7 +307,7 @@ static const struct file_operations rockchip_drm_driver_fops = {
 	.release = drm_release,
 };
 
-const struct vm_operations_struct rockchip_drm_vm_ops = {
+static const struct vm_operations_struct rockchip_drm_vm_ops = {
 	.open = drm_gem_vm_open,
 	.close = drm_gem_vm_close,
 };
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 85aa87ee12f5..96d91f16e001 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -275,9 +275,9 @@ void rockchip_drm_atomic_work(struct work_struct *work)
 	rockchip_atomic_commit_complete(commit);
 }
 
-int rockchip_drm_atomic_commit(struct drm_device *dev,
-			       struct drm_atomic_state *state,
-			       bool nonblock)
+static int rockchip_drm_atomic_commit(struct drm_device *dev,
+				      struct drm_atomic_state *state,
+				      bool nonblock)
 {
 	struct rockchip_drm_private *private = dev->dev_private;
 	struct rockchip_atomic_commit *commit = &private->commit;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index bf55cda356ba..949171a80631 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -779,7 +779,7 @@ static const struct drm_plane_helper_funcs plane_helper_funcs = {
 	.atomic_disable = vop_plane_atomic_disable,
 };
 
-void vop_atomic_plane_reset(struct drm_plane *plane)
+static void vop_atomic_plane_reset(struct drm_plane *plane)
 {
 	struct vop_plane_state *vop_plane_state =
 					to_vop_plane_state(plane->state);
@@ -796,7 +796,7 @@ void vop_atomic_plane_reset(struct drm_plane *plane)
 	plane->state->plane = plane;
 }
 
-struct drm_plane_state *
+static struct drm_plane_state *
 vop_atomic_plane_duplicate_state(struct drm_plane *plane)
 {
 	struct vop_plane_state *old_vop_plane_state;
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index 3166b46a5893..52661d116ec2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -299,7 +299,7 @@ static int vop_remove(struct platform_device *pdev)
 	return 0;
 }
 
-struct platform_driver vop_platform_driver = {
+static struct platform_driver vop_platform_driver = {
 	.probe = vop_probe,
 	.remove = vop_remove,
 	.driver = {
-- 
2.8.2.565.gdb84f68.dirty



From absahu at codeaurora.org  Tue May 10 09:09:40 2016
From: absahu at codeaurora.org (Abhishek Sahu)
Date: Tue, 10 May 2016 21:39:40 +0530
Subject: [PATCH] tty: serial: msm: Disable restoring Rx interrupts for DMA Mode
Message-ID: <1462896580-11554-1-git-send-email-absahu@codeaurora.org>

From: Charanya <charanya at codeaurora.org>

The Data loss was happening with current QCOM MSM serial driver during
large file transfer due to simultaneous enabling of both UART and
DMA interrupt. When UART operates in DMA mode, RXLEV (Rx FIFO over
watermark) or RXSTALE (stale interrupts) should not be enabled,
since these conditions will be handled by DMA controller itself.
If these interrupts are enabled then normal UART ISR will read some
bytes of data from Rx Buffer and DMA controller will not receive
these bytes of data, which will cause data loss.

Now this patch removed the code for enabling of RXLEV and RXSTALE
interrupt in DMA Rx completion routine.

Signed-off-by: Charanya <charanya at codeaurora.org>
Signed-off-by: Abhishek Sahu <absahu at codeaurora.org>
---
 drivers/tty/serial/msm_serial.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 96d3ce8..6262b18 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -388,10 +388,6 @@ static void msm_complete_rx_dma(void *args)
 	val &= ~dma->enable_bit;
 	msm_write(port, val, UARTDM_DMEN);
 
-	/* Restore interrupts */
-	msm_port->imr |= UART_IMR_RXLEV | UART_IMR_RXSTALE;
-	msm_write(port, msm_port->imr, UART_IMR);
-
 	if (msm_read(port, UART_SR) & UART_SR_OVERRUN) {
 		port->icount.overrun++;
 		tty_insert_flip_char(tport, 0, TTY_OVERRUN);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



From eric.auger at linaro.org  Tue May 10 09:10:43 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 18:10:43 +0200
Subject: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability at
 msi domain
In-Reply-To: <20160509164942.5af8b30d@t450s.home>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-6-git-send-email-eric.auger@linaro.org>
 <20160509164942.5af8b30d@t450s.home>
Message-ID: <57320803.8070506@linaro.org>

Hi Alex,
On 05/10/2016 12:49 AM, Alex Williamson wrote:
> On Wed,  4 May 2016 11:54:16 +0000
> Eric Auger <eric.auger at linaro.org> wrote:
> 
>> On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is abstracted
>> by the msi controller. vfio_safe_irq_domain allows to check whether
>> interrupts are "safe" for a given device. They are if the device does
>> not use MSI
> 
> Are we sure we're not opening a security hole here?  An MSI is simply a
> DMA write, so really whether or not a device uses MSI is irrelevant.
> If it can generate a DMA to the MSI doorbell then we need to be
> protected and I think we pretty much need to assume that devices are
> DMA capable.  Do the MSI domain checks cover this?
Let me try to rephrase: we check the device is not attached to an MSI
controller (I think this is the semantic of dev_get_msi_domain(dev)).

If it is not, we don't have to care about MSI isolation: there will be
no IOMMU binding between the device and any MSI doorbell. If it is we
check the msi domain is backed by an MSI controller able to perform MSI
isolation.

So effectively "usage of MSIs" is improper - since it is decided after
the group attachment anyway  - and the commit message should rather
state "if the device is linked to an MSI controller" (dt msi-parent
notion I think).

Does it sound better?

Regards

Eric
> 
>> or if the device uses MSI and the msi-parent controller
>> supports IRQ remapping.
>>
>> Then we check at group level if all devices have safe interrupts: if not,
>> we only allow the group to be attached if allow_unsafe_interrupts is set.
>>
>> At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP. This is
>> changed in next patch.
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>
>> ---
>> v3 -> v4:
>> - rename vfio_msi_parent_irq_remapping_capable into vfio_safe_irq_domain
>>   and irq_remapping into safe_irq_domains
>>
>> v2 -> v3:
>> - protect vfio_msi_parent_irq_remapping_capable with
>>   CONFIG_GENERIC_MSI_IRQ_DOMAIN
>> ---
>>  drivers/vfio/vfio_iommu_type1.c | 44 +++++++++++++++++++++++++++++++++++++++--
>>  1 file changed, 42 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
>> index 4d3a6f1..2fc8197 100644
>> --- a/drivers/vfio/vfio_iommu_type1.c
>> +++ b/drivers/vfio/vfio_iommu_type1.c
>> @@ -37,6 +37,8 @@
>>  #include <linux/vfio.h>
>>  #include <linux/workqueue.h>
>>  #include <linux/msi-iommu.h>
>> +#include <linux/irqdomain.h>
>> +#include <linux/msi.h>
>>  
>>  #define DRIVER_VERSION  "0.2"
>>  #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson at redhat.com>"
>> @@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev, void *data)
>>  	return 0;
>>  }
>>  
>> +/**
>> + * vfio_safe_irq_domain: returns whether the irq domain
>> + * the device is attached to is safe with respect to MSI isolation.
>> + * If the irq domain is not an MSI domain, we return it is safe.
>> + *
>> + * @dev: device handle
>> + * @data: unused
>> + * returns 0 if the irq domain is safe, -1 if not.
>> + */
>> +static int vfio_safe_irq_domain(struct device *dev, void *data)
>> +{
>> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
>> +	struct irq_domain *domain;
>> +	struct msi_domain_info *info;
>> +
>> +	domain = dev_get_msi_domain(dev);
>> +	if (!domain)
>> +		return 0;
>> +
>> +	info = msi_get_domain_info(domain);
>> +
>> +	if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
>> +		return -1;
>> +#endif
>> +	return 0;
>> +}
>> +
>>  static int vfio_iommu_replay(struct vfio_iommu *iommu,
>>  			     struct vfio_domain *domain)
>>  {
>> @@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>>  	struct vfio_group *group, *g;
>>  	struct vfio_domain *domain, *d;
>>  	struct bus_type *bus = NULL;
>> -	int ret;
>> +	int ret, safe_irq_domains;
>>  
>>  	mutex_lock(&iommu->lock);
>>  
>> @@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>>  
>>  	group->iommu_group = iommu_group;
>>  
>> +	/*
>> +	 * Determine if all the devices of the group have a safe irq domain
>> +	 * with respect to MSI isolation
>> +	 */
>> +	safe_irq_domains = !iommu_group_for_each_dev(iommu_group, &bus,
>> +				       vfio_safe_irq_domain);
>> +
>>  	/* Determine bus_type in order to allocate a domain */
>>  	ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type);
>>  	if (ret)
>> @@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>>  	INIT_LIST_HEAD(&domain->group_list);
>>  	list_add(&group->next, &domain->group_list);
>>  
>> +	/*
>> +	 * to advertise safe interrupts either the IOMMU or the MSI controllers
>> +	 * must support IRQ remapping/interrupt translation
>> +	 */
>>  	if (!allow_unsafe_interrupts &&
>> -	    !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
>> +	    (!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) && !safe_irq_domains)) {
>>  		pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",
>>  		       __func__);
>>  		ret = -EPERM;
> 



From eric.auger at linaro.org  Tue May 10 09:36:34 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 18:36:34 +0200
Subject: [PATCH v9 7/7] vfio/type1: return MSI geometry through
 VFIO_IOMMU_GET_INFO capability chains
In-Reply-To: <20160509164950.0b1cf9c1@t450s.home>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-8-git-send-email-eric.auger@linaro.org>
 <20160509164950.0b1cf9c1@t450s.home>
Message-ID: <57320E12.9060804@linaro.org>

Hi Alex,
On 05/10/2016 12:49 AM, Alex Williamson wrote:
> On Wed,  4 May 2016 11:54:18 +0000
> Eric Auger <eric.auger at linaro.org> wrote:
> 
>> This patch allows the user-space to retrieve the MSI geometry. The
>> implementation is based on capability chains, now also added to
>> VFIO_IOMMU_GET_INFO.
>>
>> The returned info comprise:
>> - whether the MSI IOVA are constrained to a reserved range (x86 case) and
>>   in the positive, the start/end of the aperture,
>> - or whether the IOVA aperture need to be set by the userspace. In that
>>   case, the size and alignment of the IOVA region to be provided are
>>   returned.
>>
>> In case the userspace must provide the IOVA range, we currently return
>> an arbitrary number of IOVA pages (16), supposed to fulfill the needs of
>> current ARM platforms. This may be deprecated by a more sophisticated
>> computation later on.
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>
>> ---
>> v8 -> v9:
>> - use iommu_msi_supported flag instead of programmable
>> - replace IOMMU_INFO_REQUIRE_MSI_MAP flag by a more sophisticated
>>   capability chain, reporting the MSI geometry
>>
>> v7 -> v8:
>> - use iommu_domain_msi_geometry
>>
>> v6 -> v7:
>> - remove the computation of the number of IOVA pages to be provisionned.
>>   This number depends on the domain/group/device topology which can
>>   dynamically change. Let's rely instead rely on an arbitrary max depending
>>   on the system
>>
>> v4 -> v5:
>> - move msi_info and ret declaration within the conditional code
>>
>> v3 -> v4:
>> - replace former vfio_domains_require_msi_mapping by
>>   more complex computation of MSI mapping requirements, especially the
>>   number of pages to be provided by the user-space.
>> - reword patch title
>>
>> RFC v1 -> v1:
>> - derived from
>>   [RFC PATCH 3/6] vfio: Extend iommu-info to return MSIs automap state
>> - renamed allow_msi_reconfig into require_msi_mapping
>> - fixed VFIO_IOMMU_GET_INFO
>> ---
>>  drivers/vfio/vfio_iommu_type1.c | 69 +++++++++++++++++++++++++++++++++++++++++
>>  include/uapi/linux/vfio.h       | 30 +++++++++++++++++-
>>  2 files changed, 98 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
>> index 2fc8197..841360b 100644
>> --- a/drivers/vfio/vfio_iommu_type1.c
>> +++ b/drivers/vfio/vfio_iommu_type1.c
>> @@ -1134,6 +1134,50 @@ static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu)
>>  	return ret;
>>  }
>>  
>> +static int compute_msi_geometry_caps(struct vfio_iommu *iommu,
>> +				     struct vfio_info_cap *caps)
>> +{
>> +	struct vfio_iommu_type1_info_cap_msi_geometry *vfio_msi_geometry;
>> +	struct iommu_domain_msi_geometry msi_geometry;
>> +	struct vfio_info_cap_header *header;
>> +	struct vfio_domain *d;
>> +	bool mapping_required;
>> +	size_t size;
>> +
>> +	mutex_lock(&iommu->lock);
>> +	/* All domains have same require_msi_map property, pick first */
>> +	d = list_first_entry(&iommu->domain_list, struct vfio_domain, next);
>> +	iommu_domain_get_attr(d->domain, DOMAIN_ATTR_MSI_GEOMETRY,
>> +			      &msi_geometry);
>> +	mapping_required = msi_geometry.iommu_msi_supported;
>> +
>> +	mutex_unlock(&iommu->lock);
>> +
>> +	size = sizeof(*vfio_msi_geometry);
>> +	header = vfio_info_cap_add(caps, size,
>> +				   VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY, 1);
>> +
>> +	if (IS_ERR(header))
>> +		return PTR_ERR(header);
>> +
>> +	vfio_msi_geometry = container_of(header,
>> +				struct vfio_iommu_type1_info_cap_msi_geometry,
>> +				header);
>> +
>> +	vfio_msi_geometry->reserved = !mapping_required;
>> +	if (vfio_msi_geometry->reserved) {
>> +		vfio_msi_geometry->aperture_start = msi_geometry.aperture_start;
>> +		vfio_msi_geometry->aperture_end = msi_geometry.aperture_end;
>> +		return 0;
>> +	}
>> +
>> +	vfio_msi_geometry->alignment = 1 << __ffs(vfio_pgsize_bitmap(iommu));
>> +	/* we currently report the need for an arbitray number of 16 pages */
>> +	vfio_msi_geometry->size = 16 * vfio_msi_geometry->alignment;
> 
> Hmm, that really is arbitrary.  How could we know a real value here?
Yes I fully agree and this is aknowledged in the cover/commit msg. I
dared to do that because this has the benefits to allow introducing the
userspace API while refining this computation later on.

I did not find yet an elegant solution to compute the platform max
number/size of doorbells (besides what I did in the past which was
dependent on the group/device current topology).

Maybe an option would be to have the relevant MSI controllers
registering their doorbells in a global list at probe time and then we
would enumerate all of them. I was reluctant to add this new
functionality in the series at this stage, hence the current simplification.
> 
>> +
>> +	return 0;
>> +}
>> +
>>  static long vfio_iommu_type1_ioctl(void *iommu_data,
>>  				   unsigned int cmd, unsigned long arg)
>>  {
>> @@ -1155,6 +1199,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>>  		}
>>  	} else if (cmd == VFIO_IOMMU_GET_INFO) {
>>  		struct vfio_iommu_type1_info info;
>> +		struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
>> +		int ret;
>>  
>>  		minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes);
>>  
>> @@ -1168,6 +1214,29 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>>  
>>  		info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
>>  
>> +		ret = compute_msi_geometry_caps(iommu, &caps);
>> +		if (ret)
>> +			return ret;
>> +
>> +		if (caps.size) {
>> +			info.flags |= VFIO_IOMMU_INFO_CAPS;
>> +			if (info.argsz < sizeof(info) + caps.size) {
>> +				info.argsz = sizeof(info) + caps.size;
>> +				info.cap_offset = 0;
>> +			} else {
>> +				vfio_info_cap_shift(&caps, sizeof(info));
>> +				if (copy_to_user((void __user *)arg +
>> +						sizeof(info), caps.buf,
>> +						caps.size)) {
>> +					kfree(caps.buf);
>> +					return -EFAULT;
>> +				}
>> +				info.cap_offset = sizeof(info);
>> +			}
>> +
>> +			kfree(caps.buf);
>> +		}
>> +
>>  		return copy_to_user((void __user *)arg, &info, minsz) ?
>>  			-EFAULT : 0;
>>  
>> diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
>> index 4a9dbc2..0ff6a8d 100644
>> --- a/include/uapi/linux/vfio.h
>> +++ b/include/uapi/linux/vfio.h
>> @@ -488,7 +488,33 @@ struct vfio_iommu_type1_info {
>>  	__u32	argsz;
>>  	__u32	flags;
>>  #define VFIO_IOMMU_INFO_PGSIZES (1 << 0)	/* supported page sizes info */
>> -	__u64	iova_pgsizes;		/* Bitmap of supported page sizes */
>> +#define VFIO_IOMMU_INFO_CAPS	(1 << 1)	/* Info supports caps */
>> +	__u32   cap_offset;	/* Offset within info struct of first cap */
>> +	__u64	iova_pgsizes;	/* Bitmap of supported page sizes */
> 
> This would break existing users, we can't arbitrarily change the offset
> of iova_pgsizes.  We can add cap_offset to the end and I think
> everything would work about above if we do that.
Hum yes, sorry for the lack of care.
> 
>> +};
>> +
>> +#define VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY	1
>> +
>> +/*
>> + * The MSI geometry capability allows to report the MSI IOVA geometry:
>> + * - either the MSI IOVAs are constrained within a reserved IOVA aperture
>> + *   whose boundaries are given by [@aperture_start, @aperture_end].
>> + *   this is typically the case on x86 host. The userspace is not allowed
>> + *   to map userspace memory at IOVAs intersecting this range using
>> + *   VFIO_IOMMU_MAP_DMA.
>> + * - or the MSI IOVAs are not requested to belong to any reserved range;
>> + *   in that case the userspace must provide an IOVA window characterized by
>> + *   @size and @alignment using VFIO_IOMMU_MAP_DMA with RESERVED_MSI_IOVA flag.
>> + */
>> +struct vfio_iommu_type1_info_cap_msi_geometry {
>> +	struct vfio_info_cap_header header;
>> +	bool reserved; /* Are MSI IOVAs within a reserved aperture? */
> 
> Do bools have a guaranteed user size?  Let's make this a __u32 and call
> it flags with bit 0 defined as reserved.  I'm tempted to suggest we
> could figure out how to make alignment fit in another __u32 so we have a
> properly packed structure, otherwise we should make a reserved __u32.
OK will rewrite & check that.

Thanks

Eric
> 
>> +	/* reserved */
>> +	__u64 aperture_start;
>> +	__u64 aperture_end;
>> +	/* not reserved */
>> +	__u64 size; /* IOVA aperture size in bytes the userspace must provide */
>> +	__u64 alignment; /* alignment of the window, in bytes */
>>  };
>>  
>>  #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
>> @@ -503,6 +529,8 @@ struct vfio_iommu_type1_info {
>>   * IOVA region that will be used on some platforms to map the host MSI frames.
>>   * In that specific case, vaddr is ignored. Once registered, an MSI reserved
>>   * IOVA region stays until the container is closed.
>> + * The requirement for provisioning such reserved IOVA range can be checked by
>> + * checking the VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY capability.
>>   */
>>  struct vfio_iommu_type1_dma_map {
>>  	__u32	argsz;
> 



From eric.auger at linaro.org  Tue May 10 09:50:25 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Tue, 10 May 2016 18:50:25 +0200
Subject: [PATCH v9 7/7] vfio/type1: return MSI geometry through
 VFIO_IOMMU_GET_INFO capability chains
In-Reply-To: <20160509170312.06e9c4fe@t450s.home>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-8-git-send-email-eric.auger@linaro.org>
 <5729E5BB.1030101@linaro.org> <20160509170312.06e9c4fe@t450s.home>
Message-ID: <57321151.7080609@linaro.org>

On 05/10/2016 01:03 AM, Alex Williamson wrote:
> On Wed, 4 May 2016 14:06:19 +0200
> Eric Auger <eric.auger at linaro.org> wrote:
> 
>> Hi Alex,
>> On 05/04/2016 01:54 PM, Eric Auger wrote:
>>> This patch allows the user-space to retrieve the MSI geometry. The
>>> implementation is based on capability chains, now also added to
>>> VFIO_IOMMU_GET_INFO.  
>>
>> If you prefer we could consider this patch outside of the main series
>> since it brings extra functionalities (MSI geometry reporting). In a
>> first QEMU integration we would live without knowing the MSI geometry I
>> think, all the more so I currently report an arbitrary number of
>> requested IOVA pages. The computation of the exact number of doorbells
>> to map brings extra complexity and I did not address this issue yet.
>>
>> It sketches a possible user API to report the MSI geometry based on the
>> capability chains, as you suggested some time ago. I am currently busy
>> drafting a QEMU integration.
> 
> How would the user know that reserved MSI mappings are requires or
> available without this?  Wouldn't the only option be for userspace to
> try to map something with the reserved MSI flag set and see if the
> kernel accepts it?
Well my first guess was that the (QEMU) virt machine using KVM/PCIe-MSI
passthrough could hardcode an arbitrary "large" iova size (currently 16
64kB pages in my QEMU integration). In case this is not sufficient for
mapping all host doorbells, we would see MSI allocation failing. In case
the need shows up, we could increase the value later on.
  That's not a very desirable programming model.  The
> arbitrary size is pretty ugly, but it at least makes for a consistent
> user interface.  Is it a functional issue if we overestimate the size
> or is it just a matter of wasting IOVA space?  Is there significant
> harm in making it obscenely large, like 1MB?
no just waste of IOVA space. To make it as transparent as possible for
virt machine I wanted to hide in the platform bus reserved IOVA.
  The reference counting and
> re-use of IOVA pages seems like we may often only be using a single
> IOVA page for multiple doorbells.  I guess I'm leaning towards defining
> the API even if the value is somewhat arbitrary because we'd rather have
> control of this rather than having the user guess and try to rope them
> back in later to use a kernel recommended value.  Thanks,

OK

Thanks

Eric
> 
> Alex
> 



From f.fainelli at gmail.com  Tue May 10 10:00:12 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Tue, 10 May 2016 10:00:12 -0700
Subject: [PATCH v2 1/2] Documentation: DT: bindings: Add Broadcom STB PCIe
 bindings
In-Reply-To: <4513390.VWu0VVAxOl@wuerfel>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
 <1462475700-1654-2-git-send-email-f.fainelli@gmail.com>
 <4513390.VWu0VVAxOl@wuerfel>
Message-ID: <5732139C.80101@gmail.com>

On 05/05/2016 02:15 PM, Arnd Bergmann wrote:
>> +Required properties:
>> +- compatible: must be one of: "brcm,bcm7425-pcie"
>> +			      "brcm,bcm7435-pcie"
>> +			      "brcm,bcm7445-pcie"
>> +
>> +- reg: specifies the physical base address of the controller registers and
>> +  its length
>> +
>> +- interrupt-parent: must be a reference (phandle) to the parent interrupt
>> +  controller in the system (7038-l1-intc on MIPS, GIC on ARM/ARM64)
>> +
>> +- interrrupts: first interrupt must be the Level 1 interrupt number corresponding
>> +  to the main PCIe RC interrupt, second interrupt must be the MSI interrupt
>> +  See the interrupt-parent documentation for the number of cells and their meaning:
>> +  MIPS: Documentation/devicetree/bindings/interrupt-controller/brcm,bcm7038-l1-intc.txt
>> +  ARM/ARM64: Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
>> +
>> +- interrupt-names: must be "pcie", and if present "msi"
> 
> When I suggested splitting out the MSI support, I was thinking (but not writing)
> that you'd use an msi-parent property to refer to the node that holds the
> msi-controller as well.

Oh got it now, and it can actually refer to iself.

> 
>> +- ranges: ranges for the PCI outbound windows, no I/O or prefetchable windows
>> +  must be specified here, only non-prefetchable. 32-bits windows or 64-bits
>> +  windows are allowed based on the host processor's capabilities (ARM w/ LPAE,
>> +  ARM64).
> 
> So this supports 64-bit non-prefetchable windows? Usually 64-bit windows
> are prefetchable.

I have yet to verify this, but on ARM64-based STB this should indeed be
the case.

> 
>> +- brcm,log2-scb-sizes: log2 size of the SCB window that is mapped to PCIe space
>> +  there must be exactly one value per memory controller present in the system
>> +  (ranges from 1 to 3)
> 
> I'm still not too happy with this property. I see no reason for the log2
> format (rather than length in bytes, or offset/length tuples, or dma-ranges,
> or phandles pointing to the memory controllers). I think we need to discuss
> this some more.

The two critical pieces of information that the PCIe RC needs are:

- number of memory controllers present in the system to avoid
configuring a window to a non-existing or non-populated memory controller

- size of the memory populated on the memory controller

You would think that we should somehow be able to derive this
information from the "memory" node, but there are a few caveats:

- on MIPS platforms, we have discontiguous physical memory ranges (256MB
@ 0x0, then 768MB or 1792MB @ 0x 0x20000000 and 1GB @ 0x90000000), yet
the PCIe RC does not know about the hole(s)

- on ARM platforms, we have an identiy mapping for the PAs below 4GB,
but when we cross it, we have additional non-linear memory regions

Both of these memory nodes would imply we know how to identify which
physical address belongs to which memory controller, while this is
actually possible and known, it creates a dependency on another piece of
driver to provide that information.

We do have memory controller nodes populated in the Device Tree, however
their binding (out of tree for the moment) does only specify their
programmable register interface, and not how how much physical memory
and where they provide to the system.

It does seem like we should be able to utilize the "dma-ranges" property
to determine both the memory controller number and their respective
populated memory sizes.

In the case where we have an identiy mapping though, this seems a little
redundant, but less of a stretch than our custom properties and nodes.

Does that sound reasonable to you?
-- 
Florian


From andre.przywara at arm.com  Tue May 10 10:18:46 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Tue, 10 May 2016 18:18:46 +0100
Subject: [PATCH v2] KVM: arm/arm64: vgic-new: fix overlap check for device
 addresses
In-Reply-To: <5731DF3C.6020201@arm.com>
References: <5731DF3C.6020201@arm.com>
Message-ID: <1462900726-14666-1-git-send-email-andre.przywara@arm.com>

When userland sets the base addresses for the GIC register frames,
the kernel tries to make sure that the regions for the distributor and
the one for the CPU interface or the redistributors do not overlap.
Currently this check only works properly for GICv2.
For a GICv3 we need the number of VCPUs to compute the size of the
redistributor region, which we only know for sure at init time.
So move the overlap check from kvm_vgic_addr() to the model specific
map_resources() implementation.
This also allows us to simplify the existing checking code a bit.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Hi,

so another rework, now hopefully really covering GICv3 properly.
For consistency I also moved the GICv2 check to init time. This is
a slightly different behaviour, but shouldn't make a difference, as
the init call can fail as well - for instance if no addresses have been
set up at all.

Cheers,
Andre.

 virt/kvm/arm/vgic/vgic-kvm-device.c | 50 ++++++++-----------------------------
 virt/kvm/arm/vgic/vgic-v2.c         | 22 ++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c         | 27 ++++++++++++++++++++
 3 files changed, 60 insertions(+), 39 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 2122ff2..9e736a7 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -19,43 +19,19 @@
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
-/* common helpers */
-
-static int vgic_ioaddr_overlap(struct kvm *kvm)
-{
-	phys_addr_t dist = kvm->arch.vgic.vgic_dist_base;
-	phys_addr_t cpu = kvm->arch.vgic.vgic_cpu_base;
-
-	if (IS_VGIC_ADDR_UNDEF(dist) || IS_VGIC_ADDR_UNDEF(cpu))
-		return 0;
-	if ((dist <= cpu && dist + KVM_VGIC_V2_DIST_SIZE > cpu) ||
-	    (cpu <= dist && cpu + KVM_VGIC_V2_CPU_SIZE > dist))
-		return -EBUSY;
-	return 0;
-}
-
-static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
-			      phys_addr_t addr, phys_addr_t size)
+static int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
+			     phys_addr_t addr, phys_addr_t alignment)
 {
-	int ret;
-
 	if (addr & ~KVM_PHYS_MASK)
 		return -E2BIG;
 
-	if (addr & (SZ_4K - 1))
+	if (!IS_ALIGNED(addr, alignment))
 		return -EINVAL;
 
 	if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
 		return -EEXIST;
-	if (addr + size < addr)
-		return -EINVAL;
-
-	*ioaddr = addr;
-	ret = vgic_ioaddr_overlap(kvm);
-	if (ret)
-		*ioaddr = VGIC_ADDR_UNDEF;
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -70,40 +46,38 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
  * interface in the VM physical address space.  These addresses are properties
  * of the emulated core/SoC and therefore user space initially knows this
  * information.
+ * Check them for sanity (alignment, double assignment). We can't check for
+ * overlapping regions in case of a virtual GICv3 here, since we don't know
+ * the number of VCPUs yet, so we defer this check to map_resources().
  */
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
 {
 	int r = 0;
 	struct vgic_dist *vgic = &kvm->arch.vgic;
 	int type_needed;
-	phys_addr_t *addr_ptr, block_size;
-	phys_addr_t alignment;
+	phys_addr_t *addr_ptr, alignment;
 
 	mutex_lock(&kvm->lock);
 	switch (type) {
 	case KVM_VGIC_V2_ADDR_TYPE_DIST:
 		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
 		addr_ptr = &vgic->vgic_dist_base;
-		block_size = KVM_VGIC_V2_DIST_SIZE;
 		alignment = SZ_4K;
 		break;
 	case KVM_VGIC_V2_ADDR_TYPE_CPU:
 		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
 		addr_ptr = &vgic->vgic_cpu_base;
-		block_size = KVM_VGIC_V2_CPU_SIZE;
 		alignment = SZ_4K;
 		break;
 #ifdef CONFIG_KVM_ARM_VGIC_V3
 	case KVM_VGIC_V3_ADDR_TYPE_DIST:
 		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
 		addr_ptr = &vgic->vgic_dist_base;
-		block_size = KVM_VGIC_V3_DIST_SIZE;
 		alignment = SZ_64K;
 		break;
 	case KVM_VGIC_V3_ADDR_TYPE_REDIST:
 		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
 		addr_ptr = &vgic->vgic_redist_base;
-		block_size = KVM_VGIC_V3_REDIST_SIZE;
 		alignment = SZ_64K;
 		break;
 #endif
@@ -118,11 +92,9 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
 	}
 
 	if (write) {
-		if (!IS_ALIGNED(*addr, alignment))
-			r = -EINVAL;
-		else
-			r = vgic_ioaddr_assign(kvm, addr_ptr,
-					       *addr, block_size);
+		r = vgic_check_ioaddr(kvm, addr_ptr, *addr, alignment);
+		if (!r)
+			*addr_ptr = *addr;
 	} else {
 		*addr = *addr_ptr;
 	}
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 4493593..fe6e3bd 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -225,6 +225,22 @@ void vgic_v2_enable(struct kvm_vcpu *vcpu)
 	vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr = GICH_HCR_EN;
 }
 
+/* check for overlapping regions and for regions crossing the end of memory */
+static bool vgic_check_addresses(gpa_t dist_base, gpa_t cpu_base)
+{
+	if (dist_base + KVM_VGIC_V2_DIST_SIZE < dist_base)
+		return false;
+	if (cpu_base + KVM_VGIC_V2_CPU_SIZE < cpu_base)
+		return false;
+
+	if (dist_base + KVM_VGIC_V2_DIST_SIZE <= cpu_base)
+		return true;
+	if (cpu_base + KVM_VGIC_V2_CPU_SIZE <= dist_base)
+		return true;
+
+	return false;
+}
+
 int vgic_v2_map_resources(struct kvm *kvm)
 {
 	struct vgic_dist *dist = &kvm->arch.vgic;
@@ -240,6 +256,12 @@ int vgic_v2_map_resources(struct kvm *kvm)
 		goto out;
 	}
 
+	if (!vgic_check_addresses(dist->vgic_dist_base, dist->vgic_cpu_base)) {
+		kvm_err("VGIC CPU and dist frames overlap\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
 	/*
 	 * Initialize the vgic if this hasn't already been done on demand by
 	 * accessing the vgic state from userspace.
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 6d7422f..fa444a7 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -221,6 +221,27 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
 	vgic_v3->vgic_hcr = ICH_HCR_EN;
 }
 
+/* check for overlapping regions and for regions crossing the end of memory */
+static bool vgic_check_addresses(struct kvm *kvm)
+{
+	struct vgic_dist *d = &kvm->arch.vgic;
+	gpa_t redist_size = KVM_VGIC_V3_REDIST_SIZE;
+
+	redist_size *= atomic_read(&kvm->online_vcpus);
+
+	if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base)
+		return false;
+	if (d->vgic_redist_base + redist_size < d->vgic_redist_base)
+		return false;
+
+	if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE <= d->vgic_redist_base)
+		return true;
+	if (d->vgic_redist_base + redist_size <= d->vgic_dist_base)
+		return true;
+
+	return false;
+}
+
 int vgic_v3_map_resources(struct kvm *kvm)
 {
 	int ret = 0;
@@ -236,6 +257,12 @@ int vgic_v3_map_resources(struct kvm *kvm)
 		goto out;
 	}
 
+	if (!vgic_check_addresses(kvm)) {
+		kvm_err("VGIC redist and dist frames overlap\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
 	/*
 	 * For a VGICv3 we require the userland to explicitly initialize
 	 * the VGIC before we need to use it.
-- 
2.7.3



From robin.murphy at arm.com  Tue May 10 10:24:34 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 10 May 2016 18:24:34 +0100
Subject: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability at
 msi domain
In-Reply-To: <57320803.8070506@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-6-git-send-email-eric.auger@linaro.org>
 <20160509164942.5af8b30d@t450s.home> <57320803.8070506@linaro.org>
Message-ID: <57321952.2020206@arm.com>

Hi Eric,

On 10/05/16 17:10, Eric Auger wrote:
> Hi Alex,
> On 05/10/2016 12:49 AM, Alex Williamson wrote:
>> On Wed,  4 May 2016 11:54:16 +0000
>> Eric Auger <eric.auger at linaro.org> wrote:
>>
>>> On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is abstracted
>>> by the msi controller. vfio_safe_irq_domain allows to check whether
>>> interrupts are "safe" for a given device. They are if the device does
>>> not use MSI
>>
>> Are we sure we're not opening a security hole here?  An MSI is simply a
>> DMA write, so really whether or not a device uses MSI is irrelevant.
>> If it can generate a DMA to the MSI doorbell then we need to be
>> protected and I think we pretty much need to assume that devices are
>> DMA capable.  Do the MSI domain checks cover this?
> Let me try to rephrase: we check the device is not attached to an MSI
> controller (I think this is the semantic of dev_get_msi_domain(dev)).
>
> If it is not, we don't have to care about MSI isolation: there will be
> no IOMMU binding between the device and any MSI doorbell. If it is we
> check the msi domain is backed by an MSI controller able to perform MSI
> isolation.
 >
> So effectively "usage of MSIs" is improper - since it is decided after
> the group attachment anyway  - and the commit message should rather
> state "if the device is linked to an MSI controller" (dt msi-parent
> notion I think).

Hmm, I think Alex has a point here - on a GICv2m I can happily fire 
arbitrary MSIs from _a shell_ (using /dev/mem), and the CPUs definitely 
aren't in an MSI domain, so I don't think it's valid to assume that a 
device using only wired interrupts, therefore with no connection to any 
MSI controller, isn't still capable of maliciously spewing DMA all over 
any and every doorbell region in the system.

Robin.

> Does it sound better?
>
> Regards
>
> Eric
>>
>>> or if the device uses MSI and the msi-parent controller
>>> supports IRQ remapping.
>>>
>>> Then we check at group level if all devices have safe interrupts: if not,
>>> we only allow the group to be attached if allow_unsafe_interrupts is set.
>>>
>>> At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP. This is
>>> changed in next patch.
>>>
>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>>
>>> ---
>>> v3 -> v4:
>>> - rename vfio_msi_parent_irq_remapping_capable into vfio_safe_irq_domain
>>>    and irq_remapping into safe_irq_domains
>>>
>>> v2 -> v3:
>>> - protect vfio_msi_parent_irq_remapping_capable with
>>>    CONFIG_GENERIC_MSI_IRQ_DOMAIN
>>> ---
>>>   drivers/vfio/vfio_iommu_type1.c | 44 +++++++++++++++++++++++++++++++++++++++--
>>>   1 file changed, 42 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
>>> index 4d3a6f1..2fc8197 100644
>>> --- a/drivers/vfio/vfio_iommu_type1.c
>>> +++ b/drivers/vfio/vfio_iommu_type1.c
>>> @@ -37,6 +37,8 @@
>>>   #include <linux/vfio.h>
>>>   #include <linux/workqueue.h>
>>>   #include <linux/msi-iommu.h>
>>> +#include <linux/irqdomain.h>
>>> +#include <linux/msi.h>
>>>
>>>   #define DRIVER_VERSION  "0.2"
>>>   #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson at redhat.com>"
>>> @@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev, void *data)
>>>   	return 0;
>>>   }
>>>
>>> +/**
>>> + * vfio_safe_irq_domain: returns whether the irq domain
>>> + * the device is attached to is safe with respect to MSI isolation.
>>> + * If the irq domain is not an MSI domain, we return it is safe.
>>> + *
>>> + * @dev: device handle
>>> + * @data: unused
>>> + * returns 0 if the irq domain is safe, -1 if not.
>>> + */
>>> +static int vfio_safe_irq_domain(struct device *dev, void *data)
>>> +{
>>> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
>>> +	struct irq_domain *domain;
>>> +	struct msi_domain_info *info;
>>> +
>>> +	domain = dev_get_msi_domain(dev);
>>> +	if (!domain)
>>> +		return 0;
>>> +
>>> +	info = msi_get_domain_info(domain);
>>> +
>>> +	if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
>>> +		return -1;
>>> +#endif
>>> +	return 0;
>>> +}
>>> +
>>>   static int vfio_iommu_replay(struct vfio_iommu *iommu,
>>>   			     struct vfio_domain *domain)
>>>   {
>>> @@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>>>   	struct vfio_group *group, *g;
>>>   	struct vfio_domain *domain, *d;
>>>   	struct bus_type *bus = NULL;
>>> -	int ret;
>>> +	int ret, safe_irq_domains;
>>>
>>>   	mutex_lock(&iommu->lock);
>>>
>>> @@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>>>
>>>   	group->iommu_group = iommu_group;
>>>
>>> +	/*
>>> +	 * Determine if all the devices of the group have a safe irq domain
>>> +	 * with respect to MSI isolation
>>> +	 */
>>> +	safe_irq_domains = !iommu_group_for_each_dev(iommu_group, &bus,
>>> +				       vfio_safe_irq_domain);
>>> +
>>>   	/* Determine bus_type in order to allocate a domain */
>>>   	ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type);
>>>   	if (ret)
>>> @@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>>>   	INIT_LIST_HEAD(&domain->group_list);
>>>   	list_add(&group->next, &domain->group_list);
>>>
>>> +	/*
>>> +	 * to advertise safe interrupts either the IOMMU or the MSI controllers
>>> +	 * must support IRQ remapping/interrupt translation
>>> +	 */
>>>   	if (!allow_unsafe_interrupts &&
>>> -	    !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
>>> +	    (!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) && !safe_irq_domains)) {
>>>   		pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",
>>>   		       __func__);
>>>   		ret = -EPERM;
>>
>



From marc.zyngier at arm.com  Tue May 10 10:32:22 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 18:32:22 +0100
Subject: [PATCH v3 17/55] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <5731FC3E.7020700@linaro.org>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-18-git-send-email-andre.przywara@arm.com>
 <5731FC3E.7020700@linaro.org>
Message-ID: <57321B26.1030201@arm.com>

On 10/05/16 16:20, Eric Auger wrote:
> On 05/06/2016 12:45 PM, Andre Przywara wrote:
>> From: Marc Zyngier <marc.zyngier at arm.com>
>>
>> Implement the framework for syncing IRQs between our emulation and
>> the list registers, which represent the guest's view of IRQs.
>> This is done in kvm_vgic_flush_hwstate and kvm_vgic_sync_hwstate,
>> which gets called on guest entry and exit.
>> The code talking to the actual GICv2/v3 hardware is added in the
>> following patches.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - split out vgic_clear_lr() from vgic_populate_lr()
>> - rename vgic_populate_lrs() to vgic_flush_lr_state()
>> - clean all LRs when the distributor is disabled
>> - use list_del() instead of list_del_init()
>> - add comments to explain the direction of sync/flush_hwstate
>> - remove unneeded BUG_ON(in_interrupt()
>>
>> Changelog v2 .. v3:
>> - remove bogus v2 specific rebase leftovers
>>
>>  include/kvm/vgic/vgic.h  |   4 +
>>  virt/kvm/arm/vgic/vgic.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic.h |   2 +
>>  3 files changed, 199 insertions(+)
>>
>> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
>> index 2bfb42c..5fae4a9 100644
>> --- a/include/kvm/vgic/vgic.h
>> +++ b/include/kvm/vgic/vgic.h
>> @@ -190,6 +190,10 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>>  #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
>>  			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
>>  
>> +bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
>> +void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
>> +void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
>> +
>>  /**
>>   * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
>>   *
>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>> index 4fb20fd..c6f8b9b 100644
>> --- a/virt/kvm/arm/vgic/vgic.c
>> +++ b/virt/kvm/arm/vgic/vgic.c
>> @@ -305,3 +305,196 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>>  {
>>  	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
>>  }
>> +
>> +/**
>> + * vgic_prune_ap_list - Remove non-relevant interrupts from the list
>> + *
>> + * @vcpu: The VCPU pointer
>> + *
>> + * Go over the list of "interesting" interrupts, and prune those that we
>> + * won't have to consider in the near future.
>> + */
>> +static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
>> +{
>> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
>> +	struct vgic_irq *irq, *tmp;
>> +
>> +retry:
>> +	spin_lock(&vgic_cpu->ap_list_lock);
>> +
>> +	list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
>> +		struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
>> +
>> +		spin_lock(&irq->irq_lock);
>> +
>> +		BUG_ON(vcpu != irq->vcpu);
>> +
>> +		target_vcpu = vgic_target_oracle(irq);
>> +
>> +		if (!target_vcpu) {
>> +			/*
>> +			 * We don't need to process this interrupt any
>> +			 * further, move it off the list.
>> +			 */
>> +			list_del(&irq->ap_list);
>> +			irq->vcpu = NULL;
>> +			spin_unlock(&irq->irq_lock);
>> +			continue;
>> +		}
>> +
>> +		if (target_vcpu == vcpu) {
>> +			/* We're on the right CPU */
>> +			spin_unlock(&irq->irq_lock);
>> +			continue;
>> +		}
>> +
>> +		/* This interrupt looks like it has to be migrated. */
>> +
>> +		spin_unlock(&irq->irq_lock);
>> +		spin_unlock(&vgic_cpu->ap_list_lock);
>> +
>> +		/*
>> +		 * Ensure locking order by always locking the smallest
>> +		 * ID first.
>> +		 */
>> +		if (vcpu->vcpu_id < target_vcpu->vcpu_id) {
>> +			vcpuA = vcpu;
>> +			vcpuB = target_vcpu;
>> +		} else {
>> +			vcpuA = target_vcpu;
>> +			vcpuB = vcpu;
>> +		}
>> +
>> +		spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
>> +		spin_lock(&vcpuB->arch.vgic_cpu.ap_list_lock);
>> +		spin_lock(&irq->irq_lock);
>> +
>> +		/*
>> +		 * If the affinity has been preserved, move the
>> +		 * interrupt around. Otherwise, it means things have
>> +		 * changed while the interrupt was unlocked, and we
>> +		 * need to replay this.
>> +		 *
>> +		 * In all cases, we cannot trust the list not to have
>> +		 * changed, so we restart from the beginning.
>> +		 */
>> +		if (target_vcpu == vgic_target_oracle(irq)) {
>> +			struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;
>> +
>> +			list_del(&irq->ap_list);
>> +			irq->vcpu = target_vcpu;
>> +			list_add_tail(&irq->ap_list, &new_cpu->ap_list_head);
>> +		}
>> +
>> +		spin_unlock(&irq->irq_lock);
>> +		spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
>> +		spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
>> +		goto retry;
>> +	}
>> +
>> +	spin_unlock(&vgic_cpu->ap_list_lock);
>> +}
>> +
>> +static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
>> +{
>> +}
>> +
>> +static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
>> +{
>> +}
>> +
>> +/* Requires the ap_list_lock and the irq_lock to be held. */
> why is it needed to hold the ap_list lock here?
>> +static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
>> +				    struct vgic_irq *irq, int lr)
>> +{
>> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
> ?

Only the irq lock needs to be held for this particular function. It is
vgic_flush_lr_state that requires the ap_list lock to be held, as it is
iterating over all the interrupts for that particular vcpu.

Andre, can you please amend the comment and drop that assertion?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From marc.zyngier at arm.com  Tue May 10 10:35:31 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 10 May 2016 18:35:31 +0100
Subject: [PATCH v3 19/55] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <5731FE09.3000007@linaro.org>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-20-git-send-email-andre.przywara@arm.com>
 <5731FE09.3000007@linaro.org>
Message-ID: <57321BE3.4080204@arm.com>

On 10/05/16 16:28, Eric Auger wrote:
> On 05/06/2016 12:45 PM, Andre Przywara wrote:
>> From: Marc Zyngier <marc.zyngier at arm.com>
>>
>> As the GICv3 virtual interface registers differ from their GICv2
>> siblings, we need different handlers for processing maintenance
>> interrupts and reading/writing to the LRs.
>> Implement the respective handler functions and connect them to
>> existing code to be called if the host is using a GICv3.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - remove outdated comment about the dist_lock
>> - add WARN_ON about LR_STATE not being 0 in maintenance interrupts
>>
>> Changelog v1 .. v2:
>> - inject the IRQ priority into the list register
>>
>> Changelog v2 .. v3:
>> - remove no longer needed irqchip/arm-gic.h inclusion
>>
>>  include/linux/irqchip/arm-gic-v3.h |   1 +
>>  virt/kvm/arm/vgic/vgic-v3.c        | 168 +++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic.c           |  25 ++++--
>>  virt/kvm/arm/vgic/vgic.h           |  29 +++++++
>>  4 files changed, 218 insertions(+), 5 deletions(-)
>>  create mode 100644 virt/kvm/arm/vgic/vgic-v3.c
>>
>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>> index ec938d1..35e93cf 100644
>> --- a/include/linux/irqchip/arm-gic-v3.h
>> +++ b/include/linux/irqchip/arm-gic-v3.h
>> @@ -275,6 +275,7 @@
>>  #define ICH_LR_ACTIVE_BIT		(1ULL << 63)
>>  #define ICH_LR_PHYS_ID_SHIFT		32
>>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
>> +#define ICH_LR_PRIORITY_SHIFT		48
>>  
>>  /* These are for GICv2 emulation only */
>>  #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
>> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
>> new file mode 100644
>> index 0000000..43d1dd7
>> --- /dev/null
>> +++ b/virt/kvm/arm/vgic/vgic-v3.c
>> @@ -0,0 +1,168 @@
>> +/*
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * 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/irqchip/arm-gic-v3.h>
>> +#include <linux/kvm.h>
>> +#include <linux/kvm_host.h>
>> +
>> +#include "vgic.h"
>> +
>> +void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
>> +{
>> +	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
>> +	u32 model = vcpu->kvm->arch.vgic.vgic_model;
>> +
>> +	if (cpuif->vgic_misr & ICH_MISR_EOI) {
>> +		unsigned long eisr_bmap = cpuif->vgic_eisr;
>> +		int lr;
>> +
>> +		for_each_set_bit(lr, &eisr_bmap, kvm_vgic_global_state.nr_lr) {
> used_lrs?

Indeed.

>> +			u32 intid;
>> +			u64 val = cpuif->vgic_lr[lr];
>> +
>> +			if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
>> +				intid = val & ICH_LR_VIRTUAL_ID_MASK;
>> +			else
>> +				intid = val & GICH_LR_VIRTUALID;
>> +
>> +			WARN_ON(cpuif->vgic_lr[lr] & ICH_LR_STATE);
>> +
>> +			kvm_notify_acked_irq(vcpu->kvm, 0,
>> +					     intid - VGIC_NR_PRIVATE_IRQS);
>> +
>> +			cpuif->vgic_elrsr |= 1ULL << lr;
>> +		}
>> +
>> +		/*
>> +		 * In the next iterations of the vcpu loop, if we sync
>> +		 * the vgic state after flushing it, but before
>> +		 * entering the guest (this happens for pending
>> +		 * signals and vmid rollovers), then make sure we
>> +		 * don't pick up any old maintenance interrupts here.
>> +		 */
>> +		cpuif->vgic_eisr = 0;
>> +	}
>> +
>> +	cpuif->vgic_hcr &= ~ICH_HCR_UIE;
>> +}
>> +
>> +void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>> +{
>> +	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
>> +
>> +	cpuif->vgic_hcr |= ICH_HCR_UIE;
>> +}
>> +
>> +void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
>> +{
>> +	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
>> +	u32 model = vcpu->kvm->arch.vgic.vgic_model;
>> +	int lr;
>> +
>> +	/* Assumes ap_list_lock held */
> I don't think there is such requirement and failed finding the lock held.

This looks like a leftover from a previous version. Folding the state is
done on a per-irq basis, and doesn't require to parse the ap_list.

> Besides Reviewed-by: Eric Auger <eric.auger at linaro.org>

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From eric at anholt.net  Tue May 10 10:37:17 2016
From: eric at anholt.net (Eric Anholt)
Date: Tue, 10 May 2016 10:37:17 -0700
Subject: [PATCH 0/3] clk: bcm2835: critical clocks and parent selection
In-Reply-To: <5731B8BA.30402@martin.sperl.org>
References: <1462842090-2017-1-git-send-email-eric@anholt.net>
 <5731B8BA.30402@martin.sperl.org>
Message-ID: <87a8jxyfua.fsf@eliezer.anholt.net>

Martin Sperl <kernel at martin.sperl.org> writes:

> On 10.05.2016 03:01, Eric Anholt wrote:
>> With the new patch 2 inserted between my previous pair, I think this
>> should cover Martin's bugs with clock disabling.
>>
>> I tested patch 2 to be important on the downstream kernel: with the
>> DPI panel support added there, I was losing ethernet (my only I/O)
>> when the HDMI HSM hanging off of PLLD_PER got disabled due to
>> EPROBE_DEFER.
>>
>> Eric Anholt (3):
>>    clk: bcm2835: Mark the VPU clock as critical
>>    clk: bcm2835: Mark GPIO clocks enabled at boot as critical.
>>    clk: bcm2835: Skip PLLC clocks when deciding on a new clock parent
>>
>>   drivers/clk/bcm/clk-bcm2835.c | 32 ++++++++++++++++++++++++++++++--
>>   1 file changed, 30 insertions(+), 2 deletions(-)
>>
> I gave it a try - with all 3 patches applied I get the following enabled 
> clocks:
> root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
> /sys/kernel/debug/clk/aux_uart/clk_enable_count:1
> /sys/kernel/debug/clk/emmc/clk_enable_count:1
> /sys/kernel/debug/clk/gp1/clk_enable_count:1
> /sys/kernel/debug/clk/gp2/clk_enable_count:1
> /sys/kernel/debug/clk/osc/clk_enable_count:1
> /sys/kernel/debug/clk/pllc/clk_enable_count:2
> /sys/kernel/debug/clk/pllc_core0/clk_enable_count:1
> /sys/kernel/debug/clk/pllc_per/clk_enable_count:1
> /sys/kernel/debug/clk/vpu/clk_enable_count:2
>
> At least on my compute module gp1/gp2 is enabled, but there is no rate
> set - so why is it marked as critical for all devices?
> So why apply patch2 for all possible devices?

According to the CLK_IS_CRITICAL patches, the author intended critical
clocks not to use the included function for marking clocks as critical
From the DT.  I'm not sure why, but writing patches using that when they
say not to seemed like a waste.

We could check if gp1/gp2 are already on before marking them critical.

> Loading/unloading the amba_pl011 module does not crash the system,
> but a simple stty -F /dev/ttyAMA0 does crash the system!
>
> Here the sequence:
> root at raspcm:~# dmesg -C
> root at raspcm:~# modprobe amba_pl011
> root at raspcm:~# dmesg -c
> [  141.708453] Serial: AMBA PL011 UART driver
> [  141.709158] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, 
> base_baud = 0) is a PL011 rev2
> root at raspcm:~# rmmod  amba_pl011
> root at raspcm:~# dmesg -c
> [  150.511248] Trying to free nonexistent resource 
> <0000000020201000-0000000020201fff>
> root at raspcm:~# modprobe amba_pl011
> root at raspcm:~# dmesg -c
> [  159.385002] Serial: AMBA PL011 UART driver
> [  159.385714] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, 
> base_baud = 0) is a PL011 rev2
> root at raspcm:~# stty -F /dev/ttyAMA0
> speed 9600 baud; line = 0;
> -brkint -imaxbel
> root at raspcm:~# Timeout, server raspcm not responding.
>
> The reason behind this is that the firmware pre-configured uart clock
> looks like this:
> root at raspcm:~# cat /sys/kernel/debug/clk/uart/regdump
> ctl = 0x00000296
> div = 0x000a6aab
> so it is configured to use plld_per (which itself is running, even if 
> not enabled
> in the kernel)
>
> But as plld_per is not among the enabled clocks then plld_per
> gets disabled as soon as the tty device is closed (by stty) and
> this also disables plld...
>
> Similar effect when using PCM/i2s and use speaker-test:
> root at raspcm:~# dmesg -C
> root at raspcm:~# modprobe snd-soc-bcm2835-i2s; modprobe snd-soc-pcm5102a; 
> modprobe snd-soc-hifiberry-dac
> root at raspcm:~# dmesg
> [   81.968591] snd-hifiberry-dac sound: pcm5102a-hifi <-> 20203000.i2s 
> mapping ok
> root at raspcm:~# speaker-test -c 2 -r 44100 -F S16_LE -f 440 -t sine&
> [1] 579
> root at raspcm:~#
> speaker-test 1.0.28
>
> Playback device is default
> Stream parameters are 44100Hz, S16_LE, 2 channels
> Sine wave rate is 440.0000Hz
> Rate set to 44100Hz (requested 44100Hz)
> Buffer size range from 128 to 131072
> Period size range from 64 to 65536
> Using max buffer size 131072
> Periods = 4
> was set period_size = 32768
> was set buffer_size = 131072
>   0 - Front Left
>   1 - Front Right
>
> root at raspcm:~#
> root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
> /sys/kernel/debug/clk/aux_uart/clk_enable_count:1
> /sys/kernel/debug/clk/emmc/clk_enable_count:1
> /sys/kernel/debug/clk/gp1/clk_enable_count:1
> /sys/kernel/debug/clk/gp2/clk_enable_count:1
> /sys/kernel/debug/clk/osc/clk_enable_count:2
> /sys/kernel/debug/clk/pcm/clk_enable_count:1
> /sys/kernel/debug/clk/pllc/clk_enable_count:2
> /sys/kernel/debug/clk/pllc_core0/clk_enable_count:1
> /sys/kernel/debug/clk/pllc_per/clk_enable_count:1
> /sys/kernel/debug/clk/plld/clk_enable_count:1
> /sys/kernel/debug/clk/plld_per/clk_enable_count:1
> /sys/kernel/debug/clk/vpu/clk_enable_count:2
> root at raspcm:~# kill %1
> root at raspcm:~# Time per period = 106.889502
> Timeout, server raspcm not responding.
>
> You see that plld gets now used and when I kill speaker-test
> the machine crashes again.

Just so I can be clear here: What are you using to talk to the Pi?
Builtin USB ethernet?

> So this patchset does not really solve any of the problems that
> I have reported either.
>
> That is why my patchset has taken the "HAND_OFF" approach
> instead (which still just hides some of the issues), but at least
> it does not crash the system on the use of plld and it allows
> for custom parent and mash selection.

HAND_OFF sure doesn't look like it's landing in the next kernel, so
writing patches using it doesn't make much sense to me.

> In reality it would require consumers of the corresponding
> parent clocks in the kernel (arm, ...) and the knowledge which
> clocks are really needed by the firmware - i.e plld.
>
> Note that the sdram clock is using plld_core parent!
> root at raspcm:~#  cat /sys/kernel/debug/clk/sdram/regdump
> ctl = 0x00004006
> div = 0x00003000
> root at raspcm:~# cat /sys/kernel/debug/clk/sdram/clk_rate
> 166533331

However, it's not enabled, right?  Bit 4 isn't set in the CTL reg.

> and also hsm (probably hardware security module):
> root at raspcm:~# cat /sys/kernel/debug/clk/hsm/regdump
> ctl = 0x000002d6
> div = 0x000030e0
> root at raspcm:~# cat /sys/kernel/debug/clk/hsm/clk_rate
> 163551916

That's the HDMI state machine (there's even a comment saying so),
controlled by the vc4 driver.

> So turning plld off stops sdram and hsm - at least that is my
> interpretation.
>
> This means we need to define a clock property in firmware or
> we need a ram node making use of "mmio-sram" maybe?
>
> Marking sdram as "critical" or "hand_off" could also solve that
> for the moment (but it does not solve all the other hidden
> clock dependencies of the firmware)

If there are other hidden dependencies, then we should figure them out.

> --- a/drivers/clk/bcm/clk-bcm2835.c
> +++ b/drivers/clk/bcm/clk-bcm2835.c
> @@ -1655,7 +1655,8 @@ static const struct bcm2835_clk_desc 
> clk_desc_array[] = {
>                  .ctl_reg = CM_SDCCTL,
>                  .div_reg = CM_SDCDIV,
>                  .int_bits = 6,
> -               .frac_bits = 0),
> +               .frac_bits = 0,
> +               .flags = CLK_IS_CRITICAL),
>          [BCM2835_CLOCK_V3D]     = REGISTER_VPU_CLK(
>                  .name = "v3d",
>                  .ctl_reg = CM_V3DCTL,

The Pi foundation folks believe that the cprman SDRAM clock isn't ever
used (there's a separate PLL in the SDRAM controller, and cprman is only
intended for unused low-power states), and at least in your sample of
the reg, it's not enabled.  Instead of grepping for clk_enable_count, it
would be really useful for debugging to look at your clk_summary
instead.

> Still I would say that this should actually move to the dt to
> correctly describe the HW.

If you created a series that *just* added critical support, using
assigned-clocks, and got the DT folks to agree to it, that would be fine
with me.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160510/e3c8773a/attachment.sig>

From eric at anholt.net  Tue May 10 10:45:43 2016
From: eric at anholt.net (Eric Anholt)
Date: Tue, 10 May 2016 10:45:43 -0700
Subject: [PATCH 0/5] clk: bcm2835: add flags for mash and parent clocks
In-Reply-To: <57319C89.7040705@martin.sperl.org>
References: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
 <87h9e6yb6i.fsf@eliezer.anholt.net> <57319C89.7040705@martin.sperl.org>
Message-ID: <877ff1yfg8.fsf@eliezer.anholt.net>

Martin Sperl <kernel at martin.sperl.org> writes:

> On 10.05.2016 03:05, Eric Anholt wrote:
>> kernel at martin.sperl.org writes:
>>
>>> From: Martin Sperl <kernel at martin.sperl.org>
>>>
>>> Allow flags to be set on a per clock index basis, which control:
>>> * the parent clocks selected when not setting clocks explicitly
>>
>> I don't think we need this other than avoiding PLLC.  What else do you
>> want to filter, and why?
> What about potentially disabling PLLA_per or PLLH_aux?
> Under some circumstances it may make sense to avoid those clocks.
> (or testdebug for that matter).

PLLH and its descendents are only used by vc4, and the parent choice
done by this driver for pllh is correct.

I don't know what you mean by "potentially disabling PLLA_PER".

We don't expose the testdebug parents, because they're of no use to us.

>>> * the clock mode with regards to integer only or higher order mash
>>
>> Please provide justification in the commit message explaining why there
>> is no obvious mash setting to just implement in clk-bcm2835.c, but that
>> that a better policy can be encoded in the DT.
>
> The normal fractional divider will vary the effective period length
> between int(div)/Fparent and (int(div)+1)/Fparent.
>
> So the device (say DAC or other) connected needs to support in
> principle Fparent/int(div) as a clock.
>
> But for higher order mash the HW will spread the period length between:
> (int(div)-3)/Fparent and (int(div)+4)/Fparent.
>
> This value may be outside of the frequencies supported by the attached
> HW. That is why mash is not enabled by default for mash clocks - only
> div.
>
> That is also why we need to have this configurable.
>
> Also obviously higher parent clock frequencies result in higher dividers
> for the same target-frequency. So the above effect is less dramatic
> when using plld_per (or pllc for that matter) compared to the main
> 19.2MHz oscillator, as for 32bit stereo audio at 96kHz (equivalent to
> 6144000Hz) in the first case we have a divider of 81.38 while for the
> second (osc) case we have a divider of 3.125.
>
> The use of mash3 is impossible for osc but the use of mash 2 would
> spread the frequencies between 9.6MHz (div=2) and 3.84MHz (div=5).
>
> For plld_per as parent using mash3 instead we get the range:
> 6410256.4Hz (div=78) and 5882352.9Hz (div=85), which is a much more
> acceptable range and should not impact the device that much.
>
> So enabling mash 3 by default is not in the best interest hence it is
> not done.

It sounds like you're optimizing for reducing frequency spread.  That
sounds fairly easy to do in the parent-choice function.

> As a side note: selection of parent oscillator and corresponding mash
> may have distinct noise behavior on the same device, where for
> 32bit*2 at 48k it is the main oscillator with mash3 while the second best
> match would be pllc with mash2 - not mash3, which has the worsted SN
> from all tested!

But PLLC continues to be unusable, since it's changed at runtime, and
evaluating its noise characteristics based on a snapshot of its
frequency doesn't make any sense.

> This behavior obviously changes with different "target frequencies"
> so it may even be necessary to account for the different target
> frequencies.

This is why encoding mash in the DT doesn't make any sense to me.  You
need a runtime policy for choosing the mash setting based on the
frequency requested, so let's figure out what policy we actually want.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160510/a3970398/attachment.sig>

From rafael at kernel.org  Tue May 10 10:54:17 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Tue, 10 May 2016 19:54:17 +0200
Subject: [PATCH V7 08/11] pci, acpi: Support for ACPI based generic PCI
 host controller
In-Reply-To: <1462893601-8937-9-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-9-git-send-email-tn@semihalf.com>
Message-ID: <CAJZ5v0hp1+D4Hd+6EQeZb_WNn6JK=55h8AAOwAWYX2CwATP0dw@mail.gmail.com>

On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> This patch is going to implement generic PCI host controller for
> ACPI world, similar to what pci-host-generic.c driver does for DT world.
>
> All such drivers, which we have seen so far, were implemented within
> arch/ directory since they had some arch assumptions (x86 and ia64).
> However, they all are doing similar thing, so it makes sense to find
> some common code and abstract it into the generic driver.
>
> In order to handle PCI config space regions properly, we define new
> MCFG interface which does sanity checks on MCFG table and keeps its
> root pointer. User is able to lookup MCFG regions based on that root
> pointer and specified domain:bus_start:bus_end touple. We are using
> pci_mmcfg_late_init old prototype to avoid another function name.
>
> The implementation of pci_acpi_scan_root() looks up the MCFG entries
> and sets up a new mapping (regions are not mapped until host controller ask
> for it). Generic PCI functions are used for accessing config space.
> Driver selects PCI_ECAM and uses functions from drivers/pci/ecam.h
> to create and access ECAM mappings.
>
> As mentioned in Kconfig help section, ACPI_PCI_HOST_GENERIC choice
> should be made on a per-architecture basis.
>
> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
> ---
>  drivers/acpi/Kconfig            |   8 +++
>  drivers/acpi/Makefile           |   1 +
>  drivers/acpi/pci_mcfg.c         |  97 ++++++++++++++++++++++++++
>  drivers/acpi/pci_root_generic.c | 149 ++++++++++++++++++++++++++++++++++++++++

Why do we need a new file?  Would there be any problem with adding
that code to pci_root.c?


From keescook at chromium.org  Tue May 10 10:55:49 2016
From: keescook at chromium.org (Kees Cook)
Date: Tue, 10 May 2016 10:55:49 -0700
Subject: [PATCH] arm64: kernel: Fix incorrect brk randomization
Message-ID: <20160510175549.GA20496@www.outflux.net>

This fixes two issues with the arm64 brk randomziation. First, the
STACK_RND_MASK was being used incorrectly. The original code was:

	unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;

STACK_RND_MASK is 0x7ff (32-bit) or 0x3ffff (64-bit), with 4K pages where
PAGE_SHIFT is 12:

	#define STACK_RND_MASK	(test_thread_flag(TIF_32BIT) ? \
						0x7ff >> (PAGE_SHIFT - 12) : \
						0x3ffff >> (PAGE_SHIFT - 12))

This means the resulting offset from base would be 0x7ff0001 or 0x3ffff0001,
which is wrong since it creates an unaligned end address. It was likely
intended to be:

	unsigned long range_end = base + ((STACK_RND_MASK + 1) << PAGE_SHIFT)

Which would result in offsets of 0x800000 (32-bit) and 0x40000000 (64-bit).

However, even this corrected 32-bit compat offset (0x00800000) is much
smaller than native ARM's brk randomization value (0x02000000):

	unsigned long arch_randomize_brk(struct mm_struct *mm)
	{
	        unsigned long range_end = mm->brk + 0x02000000;
	        return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
	}

So, instead of basing arm64's brk randomization on mistaken STACK_RND_MASK
calculations, just use specific corrected values for compat (0x2000000)
and native arm64 (0x40000000).

Signed-off-by: Kees Cook <keescook at chromium.org>
---
 arch/arm64/kernel/process.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 80624829db61..0d0969bcd76d 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -382,13 +382,14 @@ unsigned long arch_align_stack(unsigned long sp)
 	return sp & ~0xf;
 }
 
-static unsigned long randomize_base(unsigned long base)
-{
-	unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
-	return randomize_range(base, range_end, 0) ? : base;
-}
-
 unsigned long arch_randomize_brk(struct mm_struct *mm)
 {
-	return randomize_base(mm->brk);
+	unsigned long range_end = mm->brk;
+
+	if (test_thread_flag(TIF_32BIT))
+		range_end += 0x02000000;
+	else
+		range_end += 0x40000000;
+
+	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
 }
-- 
2.6.3


-- 
Kees Cook
Chrome OS & Brillo Security


From rafael at kernel.org  Tue May 10 10:59:00 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Tue, 10 May 2016 19:59:00 +0200
Subject: [PATCH V7 03/11] pci, of: Move the PCI I/O space management to
 PCI core code.
In-Reply-To: <1462893601-8937-4-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-4-git-send-email-tn@semihalf.com>
Message-ID: <CAJZ5v0ge+LGwp=AkPF50H1ZXFA6J5ByazuY7Opc-aLJwWrBNxg@mail.gmail.com>

On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> No functional changes in this patch.
>
> PCI I/O space mapping code does not depend on OF, therefore it can be
> moved to PCI core code. This way we will be able to use it
> e.g. in ACPI PCI code.
>
> Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> CC: Arnd Bergmann <arnd at arndb.de>
> CC: Liviu Dudau <Liviu.Dudau at arm.com>
> ---
>  drivers/of/address.c       | 116 +--------------------------------------------
>  drivers/pci/pci.c          | 115 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of_address.h |   9 ----
>  include/linux/pci.h        |   5 ++
>  4 files changed, 121 insertions(+), 124 deletions(-)
>
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 91a469d..0a553c0 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -4,6 +4,7 @@
>  #include <linux/ioport.h>
>  #include <linux/module.h>
>  #include <linux/of_address.h>
> +#include <linux/pci.h>
>  #include <linux/pci_regs.h>
>  #include <linux/sizes.h>
>  #include <linux/slab.h>
> @@ -673,121 +674,6 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
>  }
>  EXPORT_SYMBOL(of_get_address);
>
> -#ifdef PCI_IOBASE
> -struct io_range {
> -       struct list_head list;
> -       phys_addr_t start;
> -       resource_size_t size;
> -};
> -
> -static LIST_HEAD(io_range_list);
> -static DEFINE_SPINLOCK(io_range_lock);
> -#endif
> -
> -/*
> - * Record the PCI IO range (expressed as CPU physical address + size).
> - * Return a negative value if an error has occured, zero otherwise
> - */
> -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> -{
> -       int err = 0;
> -
> -#ifdef PCI_IOBASE
> -       struct io_range *range;
> -       resource_size_t allocated_size = 0;
> -
> -       /* check if the range hasn't been previously recorded */
> -       spin_lock(&io_range_lock);
> -       list_for_each_entry(range, &io_range_list, list) {
> -               if (addr >= range->start && addr + size <= range->start + size) {
> -                       /* range already registered, bail out */
> -                       goto end_register;
> -               }
> -               allocated_size += range->size;
> -       }
> -
> -       /* range not registed yet, check for available space */
> -       if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
> -               /* if it's too big check if 64K space can be reserved */
> -               if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
> -                       err = -E2BIG;
> -                       goto end_register;
> -               }
> -
> -               size = SZ_64K;
> -               pr_warn("Requested IO range too big, new size set to 64K\n");
> -       }
> -
> -       /* add the range to the list */
> -       range = kzalloc(sizeof(*range), GFP_ATOMIC);
> -       if (!range) {
> -               err = -ENOMEM;
> -               goto end_register;
> -       }
> -
> -       range->start = addr;
> -       range->size = size;
> -
> -       list_add_tail(&range->list, &io_range_list);
> -
> -end_register:
> -       spin_unlock(&io_range_lock);
> -#endif
> -
> -       return err;
> -}
> -
> -phys_addr_t pci_pio_to_address(unsigned long pio)
> -{
> -       phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> -
> -#ifdef PCI_IOBASE
> -       struct io_range *range;
> -       resource_size_t allocated_size = 0;
> -
> -       if (pio > IO_SPACE_LIMIT)
> -               return address;
> -
> -       spin_lock(&io_range_lock);
> -       list_for_each_entry(range, &io_range_list, list) {
> -               if (pio >= allocated_size && pio < allocated_size + range->size) {
> -                       address = range->start + pio - allocated_size;
> -                       break;
> -               }
> -               allocated_size += range->size;
> -       }
> -       spin_unlock(&io_range_lock);
> -#endif
> -
> -       return address;
> -}
> -
> -unsigned long __weak pci_address_to_pio(phys_addr_t address)
> -{
> -#ifdef PCI_IOBASE
> -       struct io_range *res;
> -       resource_size_t offset = 0;
> -       unsigned long addr = -1;
> -
> -       spin_lock(&io_range_lock);
> -       list_for_each_entry(res, &io_range_list, list) {
> -               if (address >= res->start && address < res->start + res->size) {
> -                       addr = address - res->start + offset;
> -                       break;
> -               }
> -               offset += res->size;
> -       }
> -       spin_unlock(&io_range_lock);
> -
> -       return addr;
> -#else
> -       if (address > IO_SPACE_LIMIT)
> -               return (unsigned long)-1;
> -
> -       return (unsigned long) address;
> -#endif
> -}
> -
>  static int __of_address_to_resource(struct device_node *dev,
>                 const __be32 *addrp, u64 size, unsigned int flags,
>                 const char *name, struct resource *r)
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 25e0327..bc0c914 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3021,6 +3021,121 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
>  }
>  EXPORT_SYMBOL(pci_request_regions_exclusive);
>
> +#ifdef PCI_IOBASE
> +struct io_range {
> +       struct list_head list;
> +       phys_addr_t start;
> +       resource_size_t size;
> +};
> +
> +static LIST_HEAD(io_range_list);
> +static DEFINE_SPINLOCK(io_range_lock);
> +#endif
> +
> +/*
> + * Record the PCI IO range (expressed as CPU physical address + size).
> + * Return a negative value if an error has occured, zero otherwise
> + */
> +int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
> +{
> +       int err = 0;
> +
> +#ifdef PCI_IOBASE

I understand that this moves code around, but those in-function
#ifdefs aren't nice.  Any chance to get rid of them but putting whole
functions under the #ifdef?


From dianders at chromium.org  Tue May 10 11:16:35 2016
From: dianders at chromium.org (Douglas Anderson)
Date: Tue, 10 May 2016 11:16:35 -0700
Subject: [PATCH] mmc: dw_mmc: rockchip: Set the drive phase to 180 degrees
Message-ID: <1462904195-18229-1-git-send-email-dianders@chromium.org>

Historically for Rockchip devices we've relied on the power-on
default (or perhaps the firmware setting) to get the correct drive
phase for dw_mmc devices.  This worked OK for the most part, but:

* Relying on the setting just "being right" is a bit fragile.

* As soon as there is an instance where the power on default is wrong or
  where the firmware didn't configure this properly then we'll get a
  mysterious failure.

Let's explicitly set this phase in the kernel.

You might notice that this patch is currently very dumb and just always
sets this phase to 180 degrees.  As far as I can tell this is actually a
sane thing to do.  From reading through the Designware Databook it
appears that there are instances where you could still meet hold time
requirements and set this phase to 90 degrees, but nothing I've read
indicates that 180 degrees is not OK also.

As indicated above, adding a delay to the drive is used to achieve
proper hold times.  For a given speed mode hold times are listed in the
spec in terms of nanoseconds.  The hold times are different for
different speed modes.  The actual hold time achieved is actually a
function of Delay_O (an internal delay in dw_mmc, which could vary from
SoC model to SoC model), pad delays, and the drive delay (which we're
setting here).  Note also that by setting the drive delay as a phase we
will get a different number of nanoseconds of delay depending on the
input clock.

Note that, as far as I can tell, this _does_ change the behavior of
rk3288 devices.  On devices I tested, which use coreboot/depthcharge as
BIOS, the SDMMC/SDIO0/SDIO1 drive phase used to be 90 degrees.  Now it
will be 180 degrees.  With my understanding from the Designware Databook
the 180 degrees ought to be more correct and should increase
compatibility.

I have tested this by inserting my collection of uSD cards (mostly UHS,
though a few not) into a veyron_minnie and confirmed that they still
seem to enumerate properly.  For a subset of them I tried putting a
filesystem on them and also tried running mmc_test.

Signed-off-by: Douglas Anderson <dianders at chromium.org>
---
 drivers/mmc/host/dw_mmc-rockchip.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index 8c20b81cafd8..62cbd33a07cd 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -66,6 +66,27 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
 	/* Make sure we use phases which we can enumerate with */
 	if (!IS_ERR(priv->sample_clk))
 		clk_set_phase(priv->sample_clk, priv->default_sample_phase);
+
+	/*
+	 * Set the drive phase to 180 degrees.  This helps us achieve proper
+	 * hold times.
+	 *
+	 * Note that this is _not_ a value that is tuned and is also _not_ a
+	 * value that will vary from board to board.  It is a value that
+	 * _could_ vary between different SoC models (could be different on
+	 * rk3066 vs. rk3288 for instance).  It is also a value that _could_
+	 * need to be adjusted based on our clock frequency and speed mode
+	 * since different speed modes have different hold time requirements
+	 * and hold time requirements are in "ns" (a phase offset adds a
+	 * different "ns" delay for different input clocks).
+	 *
+	 * Despite these theoretical needs, it has been observed that 180
+	 * degrees gives us good signaling across all tested SoCs and all
+	 * tested speed modes.  If when we find someone that needs 90 degrees
+	 * here we can add a table based on speed mode / SoC compatible ID.
+	 */
+	if (!IS_ERR(priv->drv_clk))
+		clk_set_phase(priv->drv_clk, 180);
 }
 
 #define NUM_PHASES			360
-- 
2.8.0.rc3.226.g39d4020



From rafael at kernel.org  Tue May 10 11:18:42 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Tue, 10 May 2016 20:18:42 +0200
Subject: [PATCH V7 08/11] pci, acpi: Support for ACPI based generic PCI
 host controller
In-Reply-To: <1462893601-8937-9-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-9-git-send-email-tn@semihalf.com>
Message-ID: <CAJZ5v0jTLGs1J_YXnAEa901hPHaupQeF1EFH_LGK47qadrYONw@mail.gmail.com>

On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> This patch is going to implement generic PCI host controller for
> ACPI world, similar to what pci-host-generic.c driver does for DT world.
>
> All such drivers, which we have seen so far, were implemented within
> arch/ directory since they had some arch assumptions (x86 and ia64).
> However, they all are doing similar thing, so it makes sense to find
> some common code and abstract it into the generic driver.

Does it mean x86 and ia64 will now be able to use this code too?

> In order to handle PCI config space regions properly, we define new
> MCFG interface which does sanity checks on MCFG table and keeps its
> root pointer. User is able to lookup MCFG regions based on that root
> pointer and specified domain:bus_start:bus_end touple. We are using
> pci_mmcfg_late_init old prototype to avoid another function name.
>
> The implementation of pci_acpi_scan_root() looks up the MCFG entries
> and sets up a new mapping (regions are not mapped until host controller ask
> for it). Generic PCI functions are used for accessing config space.
> Driver selects PCI_ECAM and uses functions from drivers/pci/ecam.h
> to create and access ECAM mappings.
>
> As mentioned in Kconfig help section, ACPI_PCI_HOST_GENERIC choice
> should be made on a per-architecture basis.

If that code really is generic and there will be more than one
architecture using it ever, I think it'll be better for the
architectures that don't use it to set something like
ARCH_ACPI_PCI_HOST and whoever doesn't set that will use the generic
thing.  That'd be more logical at least IMO.

> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
> ---
>  drivers/acpi/Kconfig            |   8 +++
>  drivers/acpi/Makefile           |   1 +
>  drivers/acpi/pci_mcfg.c         |  97 ++++++++++++++++++++++++++
>  drivers/acpi/pci_root_generic.c | 149 ++++++++++++++++++++++++++++++++++++++++
>  drivers/pci/ecam.h              |   5 ++
>  include/linux/pci-acpi.h        |   5 ++
>  include/linux/pci.h             |   5 +-
>  7 files changed, 269 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/acpi/pci_mcfg.c
>  create mode 100644 drivers/acpi/pci_root_generic.c
>
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index 183ffa3..44afc76 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -346,6 +346,14 @@ config ACPI_PCI_SLOT
>           i.e., segment/bus/device/function tuples, with physical slots in
>           the system.  If you are unsure, say N.
>
> +config ACPI_PCI_HOST_GENERIC
> +       bool
> +       select PCI_ECAM
> +       help
> +         Select this config option from the architecture Kconfig,
> +         if it is preferred to enable ACPI PCI host controller driver which
> +         has no arch-specific assumptions.
> +
>  config X86_PM_TIMER
>         bool "Power Management Timer Support" if EXPERT
>         depends on X86
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 81e5cbc..627a2b7 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -40,6 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
>  acpi-y                         += ec.o
>  acpi-$(CONFIG_ACPI_DOCK)       += dock.o
>  acpi-y                         += pci_root.o pci_link.o pci_irq.o
> +obj-$(CONFIG_ACPI_PCI_HOST_GENERIC)    += pci_root_generic.o pci_mcfg.o
>  acpi-y                         += acpi_lpss.o acpi_apd.o
>  acpi-y                         += acpi_platform.o
>  acpi-y                         += acpi_pnp.o
> diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
> new file mode 100644
> index 0000000..373d079
> --- /dev/null
> +++ b/drivers/acpi/pci_mcfg.c
> @@ -0,0 +1,97 @@
> +/*
> + * Copyright (C) 2016 Broadcom
> + *     Author: Jayachandran C <jchandra at broadcom.com>
> + * Copyright (C) 2016 Semihalf
> + *     Author: Tomasz Nowicki <tn at semihalf.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, version 2, as
> + * published by the Free Software Foundation (the "GPL").
> + *
> + * 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 version 2 (GPLv2) for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * version 2 (GPLv2) along with this source code.
> + */
> +#include <linux/kernel.h>
> +#include <linux/pci.h>
> +#include <linux/pci-acpi.h>
> +
> +#define PREFIX "ACPI: "

If that is a new file (and I'm totally unconvinced about the need for
it), can we simply define a pr_fmt() here as all messages in it seem
to be printed by the pr_* functions?


From rafael at kernel.org  Tue May 10 11:20:32 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Tue, 10 May 2016 20:20:32 +0200
Subject: [PATCH V7 05/11] acpi, pci: Support IO resources when parsing PCI
 host bridge resources.
In-Reply-To: <1462893601-8937-6-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-6-git-send-email-tn@semihalf.com>
Message-ID: <CAJZ5v0j-jiGmMWoyd-ab4qiKGAScbxMskqUThBQxkOxPR8unMA@mail.gmail.com>

On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> Platforms that have memory mapped IO port (such as ARM64) need special
> handling for PCI I/O resources. For host bridge's resource probing case
> these resources need to be fixed up with pci_register_io_range/pci_remap_iospace etc.
>
> The same I/O resources need to be released after hotplug
> removal so that it can be re-added back by the pci_remap_iospace
> function during insertion. As a consequence we unmap I/O resources
> with pci_unmap_iospace when we release host bridge resources.
>
> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> ---
>  drivers/acpi/pci_root.c | 33 +++++++++++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
>
> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
> index ae3fe4e..cb3071d 100644
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -719,6 +719,34 @@ next:
>                         resource_list_add_tail(entry, resources);
>         }
>  }
> +static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
> +{
> +#ifdef PCI_IOBASE

Same comment about the #ifdefs as in the other patch.

> +       struct resource *res = entry->res;
> +       resource_size_t cpu_addr = res->start;
> +       resource_size_t pci_addr = cpu_addr - entry->offset;
> +       resource_size_t length = resource_size(res);
> +       unsigned long port;
> +
> +       if (pci_register_io_range(cpu_addr, length))
> +               goto err;
> +
> +       port = pci_address_to_pio(cpu_addr);
> +       if (port == (unsigned long)-1)
> +               goto err;
> +
> +       res->start = port;
> +       res->end = port + length - 1;
> +       entry->offset = port - pci_addr;
> +
> +       if (pci_remap_iospace(res, cpu_addr) < 0)
> +               goto err;

An empty line here?

> +       pr_info("Remapped I/O %pa to %pR\n", &cpu_addr, res);
> +       return;
> +err:
> +       res->flags |= IORESOURCE_DISABLED;
> +#endif
> +}
>
>  int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
>  {
> @@ -740,6 +768,9 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
>                         "no IO and memory resources present in _CRS\n");
>         else {
>                 resource_list_for_each_entry_safe(entry, tmp, list) {
> +                       if (entry->res->flags & IORESOURCE_IO)
> +                               acpi_pci_root_remap_iospace(entry);
> +
>                         if (entry->res->flags & IORESOURCE_DISABLED)
>                                 resource_list_destroy_entry(entry);
>                         else
> @@ -811,6 +842,8 @@ static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
>
>         resource_list_for_each_entry(entry, &bridge->windows) {
>                 res = entry->res;
> +               if (res->flags & IORESOURCE_IO)
> +                       pci_unmap_iospace(res);
>                 if (res->parent &&
>                     (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
>                         release_resource(res);
> --


From luke.starrett at broadcom.com  Tue May 10 11:27:27 2016
From: luke.starrett at broadcom.com (Luke Starrett)
Date: Tue, 10 May 2016 14:27:27 -0400
Subject: [PATCH 1/1] arm64: Add ARM64 optimized IP checksum routine
Message-ID: <1462904847-28369-1-git-send-email-luke.starrett@broadcom.com>

This change implements an optimized checksum for arm64, based loosely on
the original arch/arm implementation.  Load-pair is used for the initial
16B load, reducing the overall number of loads to two for packets without
IP options.  Instruction count is reduced by ~3x compared to generic C
implementation.  Changes were tested against LE and BE operation and for
all possible mis-alignments.

Signed-off-by: Luke Starrett <luke.starrett at broadcom.com>
---
 arch/arm64/include/asm/checksum.h | 57 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 arch/arm64/include/asm/checksum.h

diff --git a/arch/arm64/include/asm/checksum.h b/arch/arm64/include/asm/checksum.h
new file mode 100644
index 0000000..15629d7
--- /dev/null
+++ b/arch/arm64/include/asm/checksum.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016 Broadcom
+ *
+ * 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 (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ *
+ * ip_fast_csum() loosely derived from original arch/arm implementation
+ */
+
+#ifndef __ASM_ARM64_CHECKSUM_H
+#define __ASM_ARM64_CHECKSUM_H
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ */
+static inline __sum16
+ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	u64 tmp, sum;
+
+	__asm__ __volatile__ (
+"	ldp	%0, %3, [%1], #16\n"
+"	sub	%2, %2, #4\n"
+"	adds	%0, %0, %3\n"
+"1:	ldr	%w3, [%1], #4\n"
+"	sub	%2, %2, #1\n"
+"	adcs	%0, %0, %3\n"
+"	tst	%2, #15\n"
+"	bne	1b\n"
+"	adc	%0, %0, xzr\n"
+"	ror	%3, %0, #32\n"
+"	add     %0, %0, %3\n"
+"	lsr	%0, %0, #32\n"
+"	ror	%w3, %w0, #16\n"
+"	add     %w0, %w0, %w3\n"
+"	lsr	%0, %0, #16\n"
+	: "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp)
+	: "1" (iph), "2" (ihl)
+	: "cc", "memory");
+
+	return (__force __sum16)(~sum);
+}
+
+#define ip_fast_csum ip_fast_csum
+#include <asm-generic/checksum.h>
+
+#endif	/* __ASM_ARM64_CHECKSUM_H */
-- 
2.1.0



From krzk at kernel.org  Tue May 10 11:29:30 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 20:29:30 +0200
Subject: [PATCH] ARM: dts: exynos: Replace deprecated hsi2c compatible on
 Exynos5420
Message-ID: <1462904970-31526-1-git-send-email-krzk@kernel.org>

Since commit 218e1496135e ("i2c: exynos5: add support for HSI2C on
Exynos5260 SoC") the "samsung,exynos5-hsi2c" is deprecated in favor of
SoC version specific: "samsung,exynos5250-hsi2c".

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5420.dtsi | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 4c8523471c65..549ebf23fee0 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -645,7 +645,7 @@
 	};
 
 	hsi2c_4: i2c at 12CA0000 {
-		compatible = "samsung,exynos5-hsi2c";
+		compatible = "samsung,exynos5250-hsi2c";
 		reg = <0x12CA0000 0x1000>;
 		interrupts = <0 60 0>;
 		#address-cells = <1>;
@@ -658,7 +658,7 @@
 	};
 
 	hsi2c_5: i2c at 12CB0000 {
-		compatible = "samsung,exynos5-hsi2c";
+		compatible = "samsung,exynos5250-hsi2c";
 		reg = <0x12CB0000 0x1000>;
 		interrupts = <0 61 0>;
 		#address-cells = <1>;
@@ -671,7 +671,7 @@
 	};
 
 	hsi2c_6: i2c at 12CC0000 {
-		compatible = "samsung,exynos5-hsi2c";
+		compatible = "samsung,exynos5250-hsi2c";
 		reg = <0x12CC0000 0x1000>;
 		interrupts = <0 62 0>;
 		#address-cells = <1>;
@@ -684,7 +684,7 @@
 	};
 
 	hsi2c_7: i2c at 12CD0000 {
-		compatible = "samsung,exynos5-hsi2c";
+		compatible = "samsung,exynos5250-hsi2c";
 		reg = <0x12CD0000 0x1000>;
 		interrupts = <0 63 0>;
 		#address-cells = <1>;
@@ -697,7 +697,7 @@
 	};
 
 	hsi2c_8: i2c at 12E00000 {
-		compatible = "samsung,exynos5-hsi2c";
+		compatible = "samsung,exynos5250-hsi2c";
 		reg = <0x12E00000 0x1000>;
 		interrupts = <0 87 0>;
 		#address-cells = <1>;
@@ -710,7 +710,7 @@
 	};
 
 	hsi2c_9: i2c at 12E10000 {
-		compatible = "samsung,exynos5-hsi2c";
+		compatible = "samsung,exynos5250-hsi2c";
 		reg = <0x12E10000 0x1000>;
 		interrupts = <0 88 0>;
 		#address-cells = <1>;
@@ -723,7 +723,7 @@
 	};
 
 	hsi2c_10: i2c at 12E20000 {
-		compatible = "samsung,exynos5-hsi2c";
+		compatible = "samsung,exynos5250-hsi2c";
 		reg = <0x12E20000 0x1000>;
 		interrupts = <0 203 0>;
 		#address-cells = <1>;
-- 
2.5.0



From rafael at kernel.org  Tue May 10 11:37:00 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Tue, 10 May 2016 20:37:00 +0200
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <1462893601-8937-8-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
Message-ID: <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>

On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> This patch provides a way to set the ACPI companion in PCI code.
> We define acpi_pci_set_companion() to set the ACPI companion pointer and
> call it from PCI core code. The function is stub for now.
>
> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> ---
>  drivers/pci/probe.c      | 2 ++
>  include/linux/pci-acpi.h | 4 ++++
>  2 files changed, 6 insertions(+)
>
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 8004f67..fb0b752 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -12,6 +12,7 @@
>  #include <linux/slab.h>
>  #include <linux/module.h>
>  #include <linux/cpumask.h>
> +#include <linux/pci-acpi.h>
>  #include <linux/pci-aspm.h>
>  #include <linux/aer.h>
>  #include <linux/acpi.h>
> @@ -2141,6 +2142,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
>         bridge->dev.parent = parent;
>         bridge->dev.release = pci_release_host_bridge_dev;
>         dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
> +       acpi_pci_set_companion(bridge);

Yes, we'll probably add something similar here.

Do I think now is the right time to do that?  No.

>         error = pcibios_root_bridge_prepare(bridge);
>         if (error) {
>                 kfree(bridge);
> diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
> index 09f9f02..1baa515 100644
> --- a/include/linux/pci-acpi.h
> +++ b/include/linux/pci-acpi.h
> @@ -111,6 +111,10 @@ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
>  static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
>  #endif /* CONFIG_ACPI */
>
> +static inline void acpi_pci_set_companion(struct pci_host_bridge *bridge)
> +{
> +}
> +
>  static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus)
>  {
>         return 0;
> --

Honestly, to me it looks like this series is trying very hard to avoid
doing any PCI host bridge configuration stuff from arch/arm64/
although (a) that might be simpler and (b) it would allow us to
identify the code that's common between *all* architectures using ACPI
support for host bridge configuration and to move *that* to a common
place later.  As done here it seems to be following the "ARM64 is
generic and the rest of the world is special" line which isn't really
helpful.


From bjorn.andersson at linaro.org  Tue May 10 11:39:34 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Tue, 10 May 2016 11:39:34 -0700
Subject: linux-next: build failure after merge of the net-next tree
In-Reply-To: <20160510112905.5bffcad8@canb.auug.org.au>
References: <20160510112905.5bffcad8@canb.auug.org.au>
Message-ID: <20160510183934.GJ1256@tuxbot>

On Mon 09 May 18:29 PDT 2016, Stephen Rothwell wrote:

> Hi all,
> 
> After merging the net-next tree, today's linux-next build (x86_64
> allmodconfig) failed like this:
> 
> net/qrtr/smd.c:106:14: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
>   .callback = qcom_smd_qrtr_callback,
>               ^
> net/qrtr/smd.c:106:14: note: (near initialization for 'qcom_smd_qrtr_driver.callback')
> 
> Caused by commit
> 
>   bdabad3e363d ("net: Add Qualcomm IPC router")
> 
> interacting with commit
> 
>   b853cb9628bf ("soc: qcom: smd: Make callback pass channel reference")
> 
> from the arm-soc tree.
> 
> I added the following merge fix patch (and it turned out I needed the
> new stubs).
> 

Sorry for not spotting this issue earlier, I missed Andy's second pull
request towards arm-soc and thought the SMD changes missed this cycle.


Your patch looks good, but I'm not sure how we should approach the merge
window; Andy can't pick the patch because he doesn't have the qrtr code
and David doesn't have the SMD patches coming through Andy.

FWIW, Reviewed-by: Bjorn Andersson <bjorn.andersson at linaro.org>


I assume we could have the QRTR go through Andy and arm-soc, with
David's approval and this fix squashed in. But we're running rather late
in this cycle, perhaps we should just back the QRTR patches out and I
can respin and resend them after the merge window (for v4.8 instead)?

Suggestions are welcome.

Regards,
Bjorn


From rafael at kernel.org  Tue May 10 11:43:42 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Tue, 10 May 2016 20:43:42 +0200
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
 <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>
Message-ID: <CAJZ5v0jq0NWEYw2Dj6j0pHYrWu-8syYiGP4Nqkm729Uu6hrO7A@mail.gmail.com>

On Tue, May 10, 2016 at 8:37 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:
> On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
>> This patch provides a way to set the ACPI companion in PCI code.
>> We define acpi_pci_set_companion() to set the ACPI companion pointer and
>> call it from PCI core code. The function is stub for now.
>>
>> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
>> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
>> ---
>>  drivers/pci/probe.c      | 2 ++
>>  include/linux/pci-acpi.h | 4 ++++
>>  2 files changed, 6 insertions(+)
>>
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index 8004f67..fb0b752 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -12,6 +12,7 @@
>>  #include <linux/slab.h>
>>  #include <linux/module.h>
>>  #include <linux/cpumask.h>
>> +#include <linux/pci-acpi.h>
>>  #include <linux/pci-aspm.h>
>>  #include <linux/aer.h>
>>  #include <linux/acpi.h>
>> @@ -2141,6 +2142,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
>>         bridge->dev.parent = parent;
>>         bridge->dev.release = pci_release_host_bridge_dev;
>>         dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
>> +       acpi_pci_set_companion(bridge);
>
> Yes, we'll probably add something similar here.
>
> Do I think now is the right time to do that?  No.
>
>>         error = pcibios_root_bridge_prepare(bridge);
>>         if (error) {
>>                 kfree(bridge);
>> diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
>> index 09f9f02..1baa515 100644
>> --- a/include/linux/pci-acpi.h
>> +++ b/include/linux/pci-acpi.h
>> @@ -111,6 +111,10 @@ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
>>  static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
>>  #endif /* CONFIG_ACPI */
>>
>> +static inline void acpi_pci_set_companion(struct pci_host_bridge *bridge)
>> +{
>> +}
>> +
>>  static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus)
>>  {
>>         return 0;
>> --
>
> Honestly, to me it looks like this series is trying very hard to avoid
> doing any PCI host bridge configuration stuff from arch/arm64/
> although (a) that might be simpler and (b) it would allow us to
> identify the code that's common between *all* architectures using ACPI
> support for host bridge configuration and to move *that* to a common
> place later.  As done here it seems to be following the "ARM64 is
> generic and the rest of the world is special" line which isn't really
> helpful.

Speaking of which, at least one of the reasons why the ACPI PCI host
bridge thing on x86 and ia64 went to the arch code was to avoid
explicit references to ACPI-specific data types and related #ifdeffery
in the generic PCI code and data structures.  If you are going to add
those references now anyway, that reason is not relevant any more and
all of that can just be reworked to refer to ACPI explicitly.


From bjorn.andersson at linaro.org  Tue May 10 11:48:06 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Tue, 10 May 2016 11:48:06 -0700
Subject: [PATCH 2/5] remoteproc: core: Add rproc OF look-up functions
In-Reply-To: <20160510141658.GP19473@dell>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
 <1462454983-13168-3-git-send-email-lee.jones@linaro.org>
 <20160506184842.GE1256@tuxbot> <20160510141658.GP19473@dell>
Message-ID: <20160510184806.GK1256@tuxbot>

On Tue 10 May 07:16 PDT 2016, Lee Jones wrote:

> On Fri, 06 May 2016, Bjorn Andersson wrote:
> 
> > On Thu 05 May 06:29 PDT 2016, Lee Jones wrote:
> > 
> > > - of_rproc_byindex(): look-up and obtain a reference to a rproc
> > >   		      using the DT phandle "rprocs" and a index.
> > > 
> > > - of_rproc_byname():  lookup and obtain a reference to a rproc
> > >   		      using the DT phandle "rprocs" and "rproc-names".
> > > 
> > > Signed-off-by: Ludovic Barre <ludovic.barre at st.com>
> > > Signed-off-by: Lee Jones <lee.jones at linaro.org>
> > > ---
> > 
> > I like the idea of having these helpers, but we already have
> > rproc_get_by_phandle() so these helpers should be built upon that rather
> > than adding the additional list.
> 
> Since this is a framework consideration, don't you think it would be
> better to standardise the phandle name?  This is common practice when
> coding at a subsystem level.  Some in use examples include; "clocks",
> "power-domains", "mboxes", "dmas", "phys", "resets", "gpios", etc.
> 
> Considering the aforementioned examples, I figured "rprocs" would be
> suitable.
> 

To summarize our chat for the record and others.


I'm definitely in favour of this and think "rprocs" and "rproc-names"
sounds good.  My comment was only regarding the duplicated
implementation.

Regards,
Bjorn


From geert+renesas at glider.be  Tue May 10 11:56:10 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Tue, 10 May 2016 20:56:10 +0200
Subject: [PATCH] serial: Make SERIAL_MPS2_UART depend on ARCH_MPS2
Message-ID: <1462906570-27684-1-git-send-email-geert+renesas@glider.be>

Enabling support for the UART on the ARM MPS2 platform only make sense
when compiling for the ARM MPS2 platform, unless compile-testing.

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 drivers/tty/serial/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index b84810aa8621d8b1..3def7478ca44f573 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1457,7 +1457,7 @@ config SERIAL_MPS2_UART_CONSOLE
 
 config SERIAL_MPS2_UART
 	bool "MPS2 UART port"
-	depends on ARM || COMPILE_TEST
+	depends on ARCH_MPS2 || COMPILE_TEST
 	select SERIAL_CORE
 	help
 	  This driver support the UART ports on ARM MPS2.
-- 
1.9.1



From geert+renesas at glider.be  Tue May 10 11:59:57 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Tue, 10 May 2016 20:59:57 +0200
Subject: [PATCH -trivial 2/3] ARM: Spelling s/paltform/platform/g
In-Reply-To: <1462906798-27993-1-git-send-email-geert+renesas@glider.be>
References: <1462906798-27993-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1462906798-27993-2-git-send-email-geert+renesas@glider.be>

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2d756aa471f33316..c01039b81d6eeb13 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -897,7 +897,7 @@ config MACH_STM32F429
 	default y
 
 config ARCH_MPS2
-	bool "ARM MPS2 paltform"
+	bool "ARM MPS2 platform"
 	depends on ARM_SINGLE_ARMV7M
 	select ARM_AMBA
 	select CLKSRC_MPS2
-- 
1.9.1



From geert+renesas at glider.be  Tue May 10 11:59:58 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Tue, 10 May 2016 20:59:58 +0200
Subject: [PATCH -trivial 3/3] spi: dw-pci: Spelling s/paltforms/platforms/g
In-Reply-To: <1462906798-27993-1-git-send-email-geert+renesas@glider.be>
References: <1462906798-27993-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1462906798-27993-3-git-send-email-geert+renesas@glider.be>

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 drivers/spi/spi-dw-pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c
index 332ccb0539a77710..ef7db75c92c13b34 100644
--- a/drivers/spi/spi-dw-pci.c
+++ b/drivers/spi/spi-dw-pci.c
@@ -67,7 +67,7 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dws->irq = pdev->irq;
 
 	/*
-	 * Specific handling for paltforms, like dma setup,
+	 * Specific handling for platforms, like dma setup,
 	 * clock rate, FIFO depth.
 	 */
 	if (desc) {
-- 
1.9.1



From geert+renesas at glider.be  Tue May 10 11:59:56 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Tue, 10 May 2016 20:59:56 +0200
Subject: [PATCH -trivial 1/3] Documentation: vm: Spelling s/paltform/platform/g
Message-ID: <1462906798-27993-1-git-send-email-geert+renesas@glider.be>

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 Documentation/vm/hugetlbpage.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index 54dd9b9c6c31aeed..6f3b3fa35613d900 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -275,10 +275,10 @@ This command mounts a (pseudo) filesystem of type hugetlbfs on the directory
 options sets the owner and group of the root of the file system.  By default
 the uid and gid of the current process are taken.  The mode option sets the
 mode of root of file system to value & 01777.  This value is given in octal.
-By default the value 0755 is picked. If the paltform supports multiple huge
+By default the value 0755 is picked. If the platform supports multiple huge
 page sizes, the pagesize option can be used to specify the huge page size and
 associated pool.  pagesize is specified in bytes.  If pagesize is not specified
-the paltform's default huge page size and associated pool will be used. The
+the platform's default huge page size and associated pool will be used. The
 size option sets the maximum value of memory (huge pages) allowed for that
 filesystem (/mnt/huge).  The size option can be specified in bytes, or as a
 percentage of the specified huge page pool (nr_hugepages).  The size is
-- 
1.9.1



From oliver at schinagl.nl  Tue May 10 12:00:20 2016
From: oliver at schinagl.nl (Olliver Schinagl)
Date: Tue, 10 May 2016 21:00:20 +0200
Subject: [PATCH] devicetree: sunxi: Add OLinuXino Lime2 eMMC to the Makefile
Message-ID: <1462906820-5203-1-git-send-email-oliver@schinagl.nl>

ARM: dts: sunxi: Add a olinuxino-lime2-emmc added the new emmc equipped
lime2 but forgot its Makefile. This patch adds an entry to the Makefile.

Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>
---
Maxime, I'm sorry for ommitting the Makefile initially, if it is not merged yet,
maybe just squash it with the previous patch?

 arch/arm/boot/dts/Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 95c1923..07f4cf8 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -695,6 +695,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \
 	sun7i-a20-olimex-som-evb.dtb \
 	sun7i-a20-olinuxino-lime.dtb \
 	sun7i-a20-olinuxino-lime2.dtb \
+	sun7i-a20-olinuxino-lime2-emmc.dtb \
 	sun7i-a20-olinuxino-micro.dtb \
 	sun7i-a20-orangepi.dtb \
 	sun7i-a20-orangepi-mini.dtb \
-- 
2.8.1



From davidm at egauge.net  Tue May 10 12:02:16 2016
From: davidm at egauge.net (David Mosberger-Tang)
Date: Tue, 10 May 2016 13:02:16 -0600
Subject: [PATCH] drivers: nvmem: atmel-secumod: New driver for Atmel Secumod
 nvram.
In-Reply-To: <1453348655-31182-1-git-send-email-davidm@egauge.net>
References: <1453348655-31182-1-git-send-email-davidm@egauge.net>
Message-ID: <1462906936-31353-1-git-send-email-davidm@egauge.net>

Signed-off-by: David Mosberger <davidm at egauge.net>
---
 .../devicetree/bindings/nvmem/atmel-secumod.txt    |  46 ++++++++
 arch/arm/boot/dts/sama5d2.dtsi                     |  20 ++++
 drivers/nvmem/Kconfig                              |   7 ++
 drivers/nvmem/Makefile                             |   2 +
 drivers/nvmem/atmel-secumod.c                      | 122 +++++++++++++++++++++
 5 files changed, 197 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
 create mode 100644 drivers/nvmem/atmel-secumod.c

diff --git a/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
new file mode 100644
index 0000000..0bb7638
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
@@ -0,0 +1,46 @@
+= Atmel Secumod device tree bindings =
+
+This binding is intended to represent Atmel's Secumod which is found
+in SAMA5D2 and perhaps others.
+
+Required properties:
+- compatible: should be "atmel,sama5d2-secumod"
+- reg: Should contain registers location and length of the RAM, followed
+       by register location and length of the Secumod controller.
+
+= Data cells =
+Are child nodes of secumod, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example:
+
+    secumod at fc040000 {
+            compatible = "atmel,sama5d2-secumod";
+            reg = <0xf8044000 0x1420
+                   0xfc040000 0x4000>;
+            status = "okay";
+
+            #address-cells = <1>;
+            #size-cells = <1>;
+
+            secram_auto_erasable at 0000 {
+                    reg = <0x0000 0x1000>;
+            };
+            secram at 1000 {
+                    reg = <0x1000 0x400>;
+            };
+            ram at 1400 {
+                    reg = <0x1400 0x20>;
+            };
+    };
+
+= Data consumers =
+Are device nodes which consume nvmem data cells.
+
+For example:
+
+	ram {
+		...
+		nvmem-cells = <&ram>;
+		nvmem-cell-names = "calibration";
+	};
diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 78996bd..5856d6a 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -1178,6 +1178,26 @@
 				clocks = <&pioA_clk>;
 			};
 
+			secumod at fc040000 {
+				compatible = "atmel,sama5d2-secumod";
+				reg = <0xf8044000 0x1420
+				       0xfc040000 0x4000>;
+				status = "okay";
+
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				secram_auto_erasable at 0000 {
+					reg = <0x0000 0x1000>;
+				};
+				secram at 1000 {
+					reg = <0x1000 0x400>;
+				};
+				ram at 1400 {
+					reg = <0x1400 0x20>;
+				};
+			};
+
 			tdes at fc044000 {
 				compatible = "atmel,at91sam9g46-tdes";
 				reg = <0xfc044000 0x100>;
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index ca52952..3d34fbb 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -102,4 +102,11 @@ config NVMEM_VF610_OCOTP
 	  This driver can also be build as a module. If so, the module will
 	  be called nvmem-vf610-ocotp.
 
+config NVMEM_ATMEL_SECUMOD
+       tristate "Atmel Secure Module driver"
+       depends on ARCH_AT91
+       help
+         Select this to get support for the secure module (SECUMOD) built
+	 into the SAMA5D2 chips.
+
 endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 45ab1ae..9cbd950 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -22,3 +22,5 @@ obj-$(CONFIG_NVMEM_SUNXI_SID)	+= nvmem_sunxi_sid.o
 nvmem_sunxi_sid-y		:= sunxi_sid.o
 obj-$(CONFIG_NVMEM_VF610_OCOTP)	+= nvmem-vf610-ocotp.o
 nvmem-vf610-ocotp-y		:= vf610-ocotp.o
+obj-$(CONFIG_NVMEM_ATMEL_SECUMOD)	+= nvmem-atmel-secumod.o
+nvmem-atmel-secumod-y		:= atmel-secumod.o
diff --git a/drivers/nvmem/atmel-secumod.c b/drivers/nvmem/atmel-secumod.c
new file mode 100644
index 0000000..a6b4574
--- /dev/null
+++ b/drivers/nvmem/atmel-secumod.c
@@ -0,0 +1,122 @@
+/*
+ * Driver for SAMA5D2 secure module (SECUMOD).
+ *
+ * Copyright (C) 2016 eGauge Systems LLC
+ *
+ * David Mosberger <davidm at egauge.net>
+ *
+ * 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/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+static struct regmap_config secumod_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4
+};
+
+static struct nvmem_config econfig = {
+	.name = "secumod",
+	.owner = THIS_MODULE,
+};
+
+/*
+ * Security-module register definitions:
+ */
+#define SECUMOD_RAMRDY	0x0014
+
+/*
+ * Since the secure module may need to automatically erase some of the
+ * RAM, it may take a while for it to be ready.  As far as I know,
+ * it's not documented how long this might take in the worst-case.
+ */
+static void
+secumod_wait_ready (void *regs)
+{
+	unsigned long start, stop;
+
+	start = jiffies;
+	while (!(readl(regs + SECUMOD_RAMRDY) & 1))
+		msleep_interruptible(1);
+	stop = jiffies;
+	if (stop != start)
+		pr_info("nvmem-atmel-secumod: it took %u msec for SECUMOD "
+			"to become ready...\n", jiffies_to_msecs(stop - start));
+	else
+		pr_info("nvmem-atmel-secumod: ready\n");
+}
+
+static int secumod_remove(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+	return nvmem_unregister(nvmem);
+}
+
+static int secumod_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct nvmem_device *nvmem;
+	struct regmap *regmap;
+	void __iomem *base;
+
+	/*
+	 * Map controller address temporarily so we can ensure that
+	 * the hardware is ready:
+	 */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	base = devm_ioremap_resource(dev, res);
+	secumod_wait_ready(base);
+	devm_iounmap(dev, base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	secumod_regmap_config.max_register = resource_size(res) - 1;
+
+	regmap = devm_regmap_init_mmio(dev, base, &secumod_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "%s: regmap init failed\n", __func__);
+		return PTR_ERR(regmap);
+	}
+	econfig.dev = dev;
+	nvmem = nvmem_register(&econfig);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
+
+	platform_set_drvdata(pdev, nvmem);
+
+	return 0;
+}
+
+static const struct of_device_id secumod_of_match[] = {
+	{ .compatible = "atmel,sama5d2-secumod",},
+	{/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, secumod_of_match);
+
+static struct platform_driver secumod_driver = {
+	.probe = secumod_probe,
+	.remove = secumod_remove,
+	.driver = {
+		.name = "atmel,sama5d2-secumod",
+		.of_match_table = secumod_of_match,
+	},
+};
+module_platform_driver(secumod_driver);
+MODULE_AUTHOR("David Mosberger <davidm at egauge.net>");
+MODULE_DESCRIPTION("Atmel Secumod driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1



From maxime.ripard at free-electrons.com  Tue May 10 12:10:45 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Tue, 10 May 2016 21:10:45 +0200
Subject: [PATCH] arm64/sunxi: 4.6-rc1: Add dependency on generic irq chip
In-Reply-To: <1462833455-27720-1-git-send-email-andre.przywara@arm.com>
References: <1462833455-27720-1-git-send-email-andre.przywara@arm.com>
Message-ID: <20160510191045.GM3733@lukather>

On Mon, May 09, 2016 at 11:37:35PM +0100, Andre Przywara wrote:
> From: Suzuki K Poulose <suzuki.poulose at arm.com>
> 
> Commit ce3dd55b99b1 ("arm64: Introduce Allwinner SoC config option"),
> added support for ARCH_SUNXI on arm64, but failed to select
> GENERIC_IRQ_CHIP, which is required for drivers/irqchip/irq-sunxi-nmi.c
> and causes build failures like :
> 
>   UPD     include/generated/compile.h
>   CC      init/version.o
>   LD      init/built-in.o
> drivers/built-in.o: In function `sunxi_sc_nmi_set_type':
> drivers/irqchip/irq-sunxi-nmi.c:114: undefined reference to `irq_setup_alt_chip'
> drivers/built-in.o: In function `irq_domain_add_linear':
> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
> include/linux/irqdomain.h:253: undefined reference to `irq_generic_chip_ops'
> drivers/built-in.o: In function `sunxi_sc_nmi_irq_init':
> drivers/irqchip/irq-sunxi-nmi.c:146: undefined reference to `irq_alloc_domain_generic_chips'
> drivers/irqchip/irq-sunxi-nmi.c:161: undefined reference to `irq_get_domain_generic_chip'
> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
> drivers/irqchip/irq-sunxi-nmi.c:171: undefined reference to `irq_gc_mask_set_bit'
> drivers/irqchip/irq-sunxi-nmi.c:172: undefined reference to `irq_gc_ack_set_bit'
> drivers/irqchip/irq-sunxi-nmi.c:170: undefined reference to `irq_gc_mask_clr_bit'
> 
> Fixes: commit ce3dd55b99b1 ("arm64: Introduce Allwinner SoC config option")
> Cc: Andre Przywara <andre.przywara at arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Acked-by: Maxime Ripard <maxime.ripard at free-electrons.com>

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160510/90df44ad/attachment.sig>

From plaes at plaes.org  Tue May 10 12:10:59 2016
From: plaes at plaes.org (Priit Laes)
Date: Tue, 10 May 2016 22:10:59 +0300
Subject: [linux-sunxi] Re: [PATCH v4 01/11] clk: sunxi: Add display and
 TCON0 clocks driver
In-Reply-To: <20160509223924.GX3492@codeaurora.org>
References: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
 <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
 <20160506223002.GE3492@codeaurora.org> <20160508200308.GF6167@lukather>
 <20160509223238.GW3492@codeaurora.org>
 <20160509223924.GX3492@codeaurora.org>
Message-ID: <1462907459.9981.0.camel@plaes.org>

On Mon, 2016-05-09 at 15:39 -0700, Stephen Boyd wrote:
> On 05/09, Stephen Boyd wrote:
> > 
> > 
> > Ok I applied this one to clk-next.
> > 
> And I squashed this in to silence the following checker warning.
> 
> drivers/clk/sunxi/clk-sun4i-display.c:110:33: warning: Variable
> length array is used.
> 
> ---8<---
> diff --git a/drivers/clk/sunxi/clk-sun4i-display.c
> b/drivers/clk/sunxi/clk-sun4i-display.c
> index f02e250e64ed..f8ff6c4a5633 100644
> --- a/drivers/clk/sunxi/clk-sun4i-display.c
> +++ b/drivers/clk/sunxi/clk-sun4i-display.c
> @@ -107,7 +107,7 @@ static int sun4i_a10_display_reset_xlate(struct
> reset_controller_dev *rcdev,
> ?static void __init sun4i_a10_display_init(struct device_node *node,
> ?					??const struct
> sun4i_a10_display_clk_data *data)
> ?{
> -	const char *parents[data->parents];
> +	const char *parents[4];
> ?	const char *clk_name = node->name;
> ?	struct reset_data *reset_data;
> ?	struct clk_divider *div = NULL;
> @@ -126,8 +126,8 @@ static void __init sun4i_a10_display_init(struct
> device_node *node,
> ?		return;
> ?	}
> ?
> -	ret = of_clk_parent_fill(node, parents, data->parents);
> -	if (ret != data->parents) {
> +	ret = of_clk_parent_fill(node, parents,
> ARRAY_SIZE(parents));
> +	if (ret != ARRAY_SIZE(parents)) {
> ?		pr_err("%s: Could not retrieve the parents\n",
> clk_name);
> ?		goto unmap;
> ?	}

This change breaks at least de_[bf]e clocks which have 3 clock parents.



From bjorn.andersson at linaro.org  Tue May 10 12:21:29 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Tue, 10 May 2016 12:21:29 -0700
Subject: [PATCH 5/5] remoteproc: core: Clip carveout if it's too big
In-Reply-To: <1462454983-13168-6-git-send-email-lee.jones@linaro.org>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
 <1462454983-13168-6-git-send-email-lee.jones@linaro.org>
Message-ID: <20160510192129.GL1256@tuxbot>

On Thu 05 May 06:29 PDT 2016, Lee Jones wrote:

> Carveout size is primarily extracted from the firmware binary.  However,
> DT can over-ride this by providing a different (smaller) size.  We're
> adding protection here to ensure the we only allocate the smaller of the
> two provided sizes in order to decrease the risk of clashes.
> 

Is this really the right thing to do?

The firmware is bundled with a resource table stating a certain size of
this the carveout and this would "silently" give it less space. On some
systems an IOMMU will save us (killing the firmware) but on others I
fear the firmware might just access memory outside its expected buffer.

> Signed-off-by: Lee Jones <lee.jones at linaro.org>
> ---
>  drivers/remoteproc/remoteproc_core.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
[..]
> @@ -600,6 +601,14 @@ static int rproc_handle_carveout(struct rproc *rproc,
>  		return -ENOMEM;
>  
>  	dma_dev = rproc_subdev_lookup(rproc, "carveout");
> +	sub = dev_get_drvdata(dma_dev);
> +
> +	if (rsc->len > resource_size(sub->res)) {
> +		dev_warn(dev, "carveout too big (0x%x): clipping to 0x%x\n",
> +			 rsc->len, resource_size(sub->res));
> +		rsc->len = resource_size(sub->res);
> +	}

I would rather expect this to say:

if (resource_size(sub->res) < rsc->len) {
	dev_err(dev, "defined carveout to small for firmware\n");
	return -EINVAL;
}

Unless we trust the remote firmware to dynamically follow what we put in
the resource table. (And how does it tell us if that limit isn't
enough?)

> +
>  	va = dma_alloc_coherent(dma_dev, rsc->len, &dma, GFP_KERNEL);
>  	if (!va) {
>  		dev_err(dev->parent, "dma_alloc_coherent err: %d\n", rsc->len);


Apart from this concern I'm still need to review the subdev patch; here
related the part that there's only room for one carveout with only one
size.

Regards,
Bjorn


From plaes at plaes.org  Tue May 10 12:24:07 2016
From: plaes at plaes.org (Priit Laes)
Date: Tue, 10 May 2016 22:24:07 +0300
Subject: [PATCH 2/2] ARM: sun7i: A20: Add display and TCON clocks
In-Reply-To: <1462908247-10474-1-git-send-email-plaes@plaes.org>
References: <1462908247-10474-1-git-send-email-plaes@plaes.org>
Message-ID: <1462908247-10474-3-git-send-email-plaes@plaes.org>

Enable the display and TCON clocks that are needed to drive the display
engine, tcon and TV encoders.

Signed-off-by: Priit Laes <plaes at plaes.org>
---
 arch/arm/boot/dts/sun7i-a20.dtsi | 85 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 80 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index febdf4c..82e28c3 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -67,8 +67,8 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0-hdmi";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 43>,
-				 <&ahb_gates 44>, <&dram_gates 26>;
+			clocks = <&ahb_gates 36>, <&ahb_gates 43>, <&ahb_gates 44>,
+				 <&de_be0_clk>, <&tcon0_ch0_clk>, <&dram_gates 26>;
 			status = "disabled";
 		};
 
@@ -76,7 +76,8 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 44>,
+			clocks = <&ahb_gates 36>, <&ahb_gates 44>,
+				 <&de_be0_clk>, <&tcon0_ch0_clk>,
 				 <&dram_gates 26>;
 			status = "disabled";
 		};
@@ -85,8 +86,8 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0-tve0";
-			clocks = <&pll5 1>,
-				 <&ahb_gates 34>, <&ahb_gates 36>, <&ahb_gates 44>,
+			clocks = <&ahb_gates 34>, <&ahb_gates 36>, <&ahb_gates 44>,
+				 <&de_be0_clk>, <&tcon0_ch0_clk>,
 				 <&dram_gates 5>, <&dram_gates 26>;
 			status = "disabled";
 		};
@@ -580,6 +581,80 @@
 					     "dram_de_mp", "dram_ace";
 		};
 
+		de_be0_clk: clk at 01c20104 {
+			#clock-cells = <0>;
+			#reset-cells = <0>;
+			compatible = "allwinner,sun4i-a10-display-clk";
+			reg = <0x01c20104 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll5 1>;
+			clock-output-names = "de-be0";
+		};
+
+		de_be1_clk: clk at 01c20108 {
+			#clock-cells = <0>;
+			#reset-cells = <0>;
+			compatible = "allwinner,sun4i-a10-display-clk";
+			reg = <0x01c20108 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll5 1>;
+			clock-output-names = "de-be1";
+		};
+
+		de_fe0_clk: clk at 01c2010c {
+			#clock-cells = <0>;
+			#reset-cells = <0>;
+			compatible = "allwinner,sun4i-a10-display-clk";
+			reg = <0x01c2010c 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll5 1>;
+			clock-output-names = "de-fe0";
+		};
+
+		de_fe1_clk: clk at 01c20110 {
+			#clock-cells = <0>;
+			#reset-cells = <0>;
+			compatible = "allwinner,sun4i-a10-display-clk";
+			reg = <0x01c20110 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll5 1>;
+			clock-output-names = "de-fe1";
+		};
+
+		tcon0_ch0_clk: clk at 01c20118 {
+			#clock-cells = <0>;
+			#reset-cells = <1>;
+			compatible = "allwinner,sun4i-a10-tcon-ch0-clk";
+			reg = <0x01c20118 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
+			clock-output-names = "tcon0-ch0-sclk";
+
+		};
+
+		tcon1_ch0_clk: clk at 01c2011c {
+			#clock-cells = <0>;
+			#reset-cells = <1>;
+			compatible = "allwinner,sun4i-a10-tcon-ch1-clk";
+			reg = <0x01c2011c 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
+			clock-output-names = "tcon1-ch0-sclk";
+
+		};
+
+		tcon0_ch1_clk: clk at 01c2012c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-tcon-ch0-clk";
+			reg = <0x01c2012c 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
+			clock-output-names = "tcon0-ch1-sclk";
+
+		};
+
+		tcon1_ch1_clk: clk at 01c20130 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-tcon-ch1-clk";
+			reg = <0x01c20130 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
+			clock-output-names = "tcon1-ch1-sclk";
+
+		};
+
 		ve_clk: clk at 01c2013c {
 			#clock-cells = <0>;
 			#reset-cells = <0>;
-- 
2.8.2



From plaes at plaes.org  Tue May 10 12:24:05 2016
From: plaes at plaes.org (Priit Laes)
Date: Tue, 10 May 2016 22:24:05 +0300
Subject: [PATCH 0/2] ARM: dts: sunxi: Add display clocks to sun[47]i.dtsi
Message-ID: <1462908247-10474-1-git-send-email-plaes@plaes.org>

Enable the display and TCON clocks that are needed to drive the display
engine, tcon and TV encoders.

Please note that currently the parent handling for clocks using 
'allwinner,sun4i-a10-display-clk' compatible with number of parents !=4
is broken (like de_[bf]e[01]_clk clocks present in patches).

Priit Laes (2):
  ARM: sun4i: A10: Add display and TCON clocks
  ARM: sun7i: A20: Add display and TCON clocks

 arch/arm/boot/dts/sun4i-a10.dtsi | 91 ++++++++++++++++++++++++++++++++++++----
 arch/arm/boot/dts/sun7i-a20.dtsi | 85 ++++++++++++++++++++++++++++++++++---
 2 files changed, 164 insertions(+), 12 deletions(-)

-- 
2.8.2



From plaes at plaes.org  Tue May 10 12:24:06 2016
From: plaes at plaes.org (Priit Laes)
Date: Tue, 10 May 2016 22:24:06 +0300
Subject: [PATCH 1/2] ARM: sun4i: A10: Add display and TCON clocks
In-Reply-To: <1462908247-10474-1-git-send-email-plaes@plaes.org>
References: <1462908247-10474-1-git-send-email-plaes@plaes.org>
Message-ID: <1462908247-10474-2-git-send-email-plaes@plaes.org>

Enable the display and TCON clocks that are needed to drive the display
engine, tcon and TV encoders.

Signed-off-by: Priit Laes <plaes at plaes.org>
---
 arch/arm/boot/dts/sun4i-a10.dtsi | 91 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 84 insertions(+), 7 deletions(-)

diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index a03e56f..a9c3190 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -65,8 +65,8 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0-hdmi";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 43>,
-				 <&ahb_gates 44>, <&dram_gates 26>;
+			clocks = <&ahb_gates 36>, <&ahb_gates 43>, <&ahb_gates 44>,
+				 <&de_be0_clk>, <&tcon0_ch0_clk>, <&dram_gates 26>;
 			status = "disabled";
 		};
 
@@ -74,8 +74,9 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_fe0-de_be0-lcd0-hdmi";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 43>,
+			clocks = <&ahb_gates 36>, <&ahb_gates 43>,
 				 <&ahb_gates 44>, <&ahb_gates 46>,
+				 <&de_be0_clk>, <&de_fe0_clk>, <&tcon0_ch0_clk>,
 				 <&dram_gates 25>, <&dram_gates 26>;
 			status = "disabled";
 		};
@@ -84,9 +85,9 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_fe0-de_be0-lcd0";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 44>,
-				 <&ahb_gates 46>, <&dram_gates 25>,
-				 <&dram_gates 26>;
+			clocks = <&ahb_gates 36>, <&ahb_gates 44>, <&ahb_gates 46>,
+				 <&de_be0_clk>, <&de_fe0_clk>, <&tcon0_ch0_clk>,
+				 <&dram_gates 25>, <&dram_gates 26>;
 			status = "disabled";
 		};
 
@@ -94,8 +95,9 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_fe0-de_be0-lcd0-tve0";
-			clocks = <&pll5 1>, <&ahb_gates 34>, <&ahb_gates 36>,
+			clocks = <&ahb_gates 34>, <&ahb_gates 36>,
 				 <&ahb_gates 44>, <&ahb_gates 46>,
+				 <&de_be0_clk>, <&de_fe0_clk>, <&tcon0_ch0_clk>,
 				 <&dram_gates 5>, <&dram_gates 25>, <&dram_gates 26>;
 			status = "disabled";
 		};
@@ -574,6 +576,81 @@
 					     "dram_de_mp", "dram_ace";
 		};
 
+		de_be0_clk: clk at 01c20104 {
+			#clock-cells = <0>;
+			#reset-cells = <0>;
+			compatible = "allwinner,sun4i-a10-display-clk";
+			reg = <0x01c20104 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll5 1>;
+			clock-output-names = "de-be0";
+		};
+
+		de_be1_clk: clk at 01c20108 {
+			#clock-cells = <0>;
+			#reset-cells = <0>;
+			compatible = "allwinner,sun4i-a10-display-clk";
+			reg = <0x01c20108 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll5 1>;
+			clock-output-names = "de-be1";
+		};
+
+		de_fe0_clk: clk at 01c2010c {
+			#clock-cells = <0>;
+			#reset-cells = <0>;
+			compatible = "allwinner,sun4i-a10-display-clk";
+			reg = <0x01c2010c 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll5 1>;
+			clock-output-names = "de-fe0";
+		};
+
+		de_fe1_clk: clk at 01c20110 {
+			#clock-cells = <0>;
+			#reset-cells = <0>;
+			compatible = "allwinner,sun4i-a10-display-clk";
+			reg = <0x01c20110 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll5 1>;
+			clock-output-names = "de-fe1";
+		};
+
+
+		tcon0_ch0_clk: clk at 01c20118 {
+			#clock-cells = <0>;
+			#reset-cells = <1>;
+			compatible = "allwinner,sun4i-a10-tcon-ch0-clk";
+			reg = <0x01c20118 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
+			clock-output-names = "tcon0-ch0-sclk";
+
+		};
+
+		tcon1_ch0_clk: clk at 01c2011c {
+			#clock-cells = <0>;
+			#reset-cells = <1>;
+			compatible = "allwinner,sun4i-a10-tcon-ch1-clk";
+			reg = <0x01c2011c 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
+			clock-output-names = "tcon1-ch0-sclk";
+
+		};
+
+		tcon0_ch1_clk: clk at 01c2012c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-tcon-ch0-clk";
+			reg = <0x01c2012c 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
+			clock-output-names = "tcon0-ch1-sclk";
+
+		};
+
+		tcon1_ch1_clk: clk at 01c20130 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-tcon-ch1-clk";
+			reg = <0x01c20130 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
+			clock-output-names = "tcon1-ch1-sclk";
+
+		};
+
 		ve_clk: clk at 01c2013c {
 			#clock-cells = <0>;
 			#reset-cells = <0>;
-- 
2.8.2



From richard.genoud at gmail.com  Tue May 10 12:40:01 2016
From: richard.genoud at gmail.com (Richard Genoud)
Date: Tue, 10 May 2016 21:40:01 +0200
Subject: [BISECTED] Regression v4.6-rc1 : nanosleep doesn't return on
 AT91SAM9
In-Reply-To: <5731FBE1.2090202@atmel.com>
References: <CACQ1gAg6cKqjaqcV70m2VS5R4_kZEgWTiqzSqDxSjvfrYYxbzg@mail.gmail.com>
 <CACQ1gAipruXcO=xpooYDOdqZbtESD35wxDf7xNrg4zuuRv1wew@mail.gmail.com>
 <20160510164712.56261bb4@bbrezillon>
 <CACQ1gAj4xD1httj=gMKFCfeOnVjSKk+J-y_yZpCkTSiLeTAA4A@mail.gmail.com>
 <5731FBE1.2090202@atmel.com>
Message-ID: <CACQ1gAguZSbqnHQyWHSGSO5tc0zgEPq7QRD8ibgaGU60c4CRMw@mail.gmail.com>

2016-05-10 17:18 GMT+02:00 Nicolas Ferre <nicolas.ferre at atmel.com>:
> Le 10/05/2016 16:59, Richard Genoud a ?crit :
>> 2016-05-10 16:47 GMT+02:00 Boris Brezillon <boris.brezillon at free-electrons.com>:
>>> Hi Richard,
>>>
>>> On Tue, 10 May 2016 16:25:25 +0200
>>> Richard Genoud <richard.genoud at gmail.com> wrote:
>>>
>>>> 2016-05-10 15:58 GMT+02:00 Richard Genoud <richard.genoud at gmail.com>:
>>>>> Hi,
>>>>>
>>>>> Starting with 4.6-rc1, a sleep 1 doesn't return :
>>>>>
>>>>> execve("/bin/sleep", ["sleep", "1"], ["USER=root", "SHLVL=1",
>>>>> "OLDPWD=/var", "HOME=/", "TERM=vt102",
>>>>> "PATH=/sbin:/usr/sbin:/bin:/usr/bin", "SHELL=/bin/sh", "PWD=/"]) = 0
>>>>> uname({sysname="Linux", nodename="LNS",
>>>>> release="4.5.0-09406-g46e595a17dcf", version="#72 Tue May 10 15:41:34
>>>>> CEST 2016", machine="armv5tejl", domainname="(none)"}) = 0
>>>>> brk(0)                                  = 0x153000
>>>>> brk(0x153d20)                           = 0x153d20
>>>>> set_tls(0x1534c0, 0x14d1e4, 0, 0x153d20, 0x14e368) = 0
>>>>> readlink("/proc/self/exe", "/bin/busybox", 4096) = 12
>>>>> brk(0x174d20)                           = 0x174d20
>>>>> brk(0x175000)                           = 0x175000
>>>>> getuid32()                              = 0
>>>>> rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
>>>>> rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
>>>>> rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
>>>>> nanosleep({1, 0},
>>>>>
>>>>> And the heartbeat led doesn't blink anymore (full on), as if the
>>>>> timers never fire.
>>>>>
>>>>> The platform is an AT91SAM9G35-CM.
>>>>>
>>>>> git bisect gives a merge as the 1st bad commit :(
>>>>> first bad commit: [46e595a17dcf11404f713845ecb5b06b92a94e43] Merge tag
>>>>> 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>>
>>>>
>>>> I went a little further in tracking that down, starting from the merge
>>>> (1st bad commit) and reverting some commits.
>>>> It seems that the culprit is :
>>>> commit 863a81c3be1d931bdae6426e231add9334311f13
>>>> Author: Boris Brezillon <boris.brezillon at free-electrons.com>
>>>> Date:   Fri Sep 5 09:54:13 2014 +0200
>>>>     clk: at91: make use of syscon to share PMC registers in several drivers
>>>>
>>>> Here are the commits I've reverted :
>>>>
>>>> git log --oneline --decorate -20
>>>> 849cdaa0cf04 (HEAD, tag: good) Revert "clk: at91: make use of syscon
>>>> to share PMC registers in several drivers"
>>>> 4bd6dde95321 (tag: last_bad) Revert "clk: at91: make use of
>>>> syscon/regmap internally"
>>>> a56dacaa24c4 (tag: always_bad) Revert "clk: at91: remove IRQ handling
>>>> and use polling"
>>>> 33edfe7a2de6 Revert "clk: at91: pmc: merge at91_pmc_init in atmel_pmc_probe"
>>>> 0b22bb649eae Revert "clk: at91: pmc: move pmc structures to C file"
>>>> 14994fdff366 Revert "ARM: at91: pm: simply call at91_pm_init"
>>>> 6f0821175327 (tag: still_bad) Revert "ARM: at91: pm: find and remap the pmc"
>>>> b52bbf7fad1b Revert "ARM: at91: pm: move idle functions to pm.c"
>>>> dffb1a5f68b9 Revert "ARM: at91: remove useless includes and function prototypes"
>>>> db352691dcc1 Revert "usb: gadget: atmel: access the PMC using regmap"
>>>> f7b5433dbbc8 Revert "clk: at91: pmc: drop at91_pmc_base"
>>>> 6e6dfc0d91c0 Revert "clk: at91: pmc: remove useless capacities handling"
>>>> ceddd3f88ada Revert "clk: at91: remove useless includes"
>>>> 46e595a17dcf (tag: bad) Merge tag 'armsoc-drivers' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>> e3b1f64e04f5 Merge tag 'armsoc-defconfig' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>> 915c56bc01d6 Merge tag 'armsoc-dt64' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>> 5a6b7e53d035 Merge tag 'armsoc-dt' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>> 8c6d4082fc6a Merge tag 'armsoc-arm64' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>> 33b3d2e88c9e Merge tag 'armsoc-soc' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>> e88fa1b8b00a Merge tag 'armsoc-cleanup' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>
>>> Thanks for the detailed report.
>>>
>>> Can you try again after applying this patch [1]?
>>>
>>> Regards,
>>>
>>> Boris
>>>
>>> [1]http://code.bulix.org/dx1c0t-98377
>>
>> Yes, it works.
>> Big thumbs up, that was fast !
>>
>> Less than 1 hour between the report and the patch ! :)
>
> Yes, absolutely terrific! Thanks Boris.
>
> I'd like you to test with this instead as it's the real range of the IP:
> + reg = <0xfffffc00 0x110>;
>
> Even I'm pretty confident ;-) Can you please do this for us ?
Unfortunately, I can't test it until Thursday morning.

>> This is clearly 4.6 material (as it's a regression from 4.5), but it's
>> maybe a little late.
>> Anrd, Nicolas, what do you think ?
>
> I sent a PR this morning to Arnd with a "fix"... I hope that he won't be
> annoyed if I send him another one this evening...  But clearly, it's a
> regression and a pretty bad one :-\
>
> Thanks a lot for this report Richard,


From arnd at arndb.de  Tue May 10 12:44:50 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 21:44:50 +0200
Subject: [PATCH] arm64/sunxi: 4.6-rc1: Add dependency on generic irq chip
In-Reply-To: <20160510191045.GM3733@lukather>
References: <1462833455-27720-1-git-send-email-andre.przywara@arm.com>
 <20160510191045.GM3733@lukather>
Message-ID: <3061422.ZNsarFN8kL@wuerfel>

On Tuesday 10 May 2016 21:10:45 Maxime Ripard wrote:
> > Fixes: commit ce3dd55b99b1 ("arm64: Introduce Allwinner SoC config option")
> > Cc: Andre Przywara <andre.przywara at arm.com>
> > Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> > Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> 
> Acked-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> 

Applied to fixes, thanks!

	Arnd


From linux.amoon at gmail.com  Tue May 10 12:45:33 2016
From: linux.amoon at gmail.com (Anand Moon)
Date: Wed, 11 May 2016 01:15:33 +0530
Subject: [PATCH] ARM: dts: exynos: Only Odroid XU3-family boards use DTSI
 with CPU thermal nodes
In-Reply-To: <5731EA1B.4070201@samsung.com>
References: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>
 <CANAwSgT9SY3kj8+beMpc1xGoC=rMBSya+2v2dyZQp6ykH+V0=g@mail.gmail.com>
 <573198BE.6020900@samsung.com>
 <CANAwSgTy6p9AVmmOWATpSO1JqVbwE0v+y_y-RLd+32RnNJTA+Q@mail.gmail.com>
 <5731D764.8070007@samsung.com>
 <CANAwSgRsjdQh6ygT__5XcH8-cF9Ch+zbk8oupebwYzY1kCZu6g@mail.gmail.com>
 <5731EA1B.4070201@samsung.com>
Message-ID: <CANAwSgQGhrBca7=Ow8+Hh9t0W9HWp=F43KR0Frfpx9fGngPSaw@mail.gmail.com>

Hi Krzysztof,

On 10 May 2016 at 19:33, Krzysztof Kozlowski <k.kozlowski at samsung.com> wrote:
> On 05/10/2016 04:00 PM, Anand Moon wrote:
>> Hi Krzysztof,
>>
>> On 10 May 2016 at 18:13, Krzysztof Kozlowski <k.kozlowski at samsung.com> wrote:
>>> On 05/10/2016 11:29 AM, Anand Moon wrote:
>>>>>
>>>>> I am sorry but I do not understand.
>>>>> 1. Are you saying that my patch causes the issue?
>>>>> 2. Are you saying that I should not send some patches because of
>>>>> conflicting work? (that would be peculiar...)
>>>>> 3. Are you saying that I should not apply this patch to me tree because
>>>>> of conflicting work?
>>>>> 4. Other?
>>>>>
>>>>> Best regards.
>>>>> Krzysztof
>>>>>
>>>>>
>>>>
>>>> Sorry for the confusion it's not about you patch.
>>>> The feature is not working correctly as per my testing with the
>>>> original source code.
>>>> It need to be more tuned or some other approach to the issue need to found.
>>>
>>> Known issue. You don't have cpufreq cooling enabled. I sent patches for
>>> that and they are in the mainline. However cpufreq cooling requires
>>> cpufreq which cannot work with BL_SWITCHER and on Exynos542x on
>>> exynos_defconfig BL_SWITCHER is enabled.
>>>
>>> Just disable the BL_Krzysztof.
>>>
>>> Best regards,
>>> Krzysztof
>>
>> I have already disabled BL_SWITCHER in my exynos_defconfig. to support
>> CONFIG_CPUFREQ_DT.
>>
>> But how about adjust the  the cputemp so that all the core will have
>> same tip points.
>
>
> I don't understand you. All of the cores have same trip points.
>
> Best regards,
> Krzysztof
>
>>
>> xcpu0-t 0:[ 44][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>     A50
>>      A60       P70            P85                                C120
>> ]
>> xcpu1-t 1:[ 46][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>                               A85               A103   A110      C120
>> ]
>> xcpu2-t 2:[ 51][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>                          A85               A103   A110      C120 ]
>> xcpu3-t 3:[ 47][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>                              A85               A103   A110      C120 ]
>> xgpu-th 4:[ 48][>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>                             A85               A103   A110      C120 ]
>
>

Sorry I am not able to explain my self clearly.
But I have once gain tested these changes.

Only could you append with following changes.
--------------------------------------------------------
+                               cpu_crit0: cpu-crit-0 {
+                                       temperature = <120000>; /*
millicelsius */
+                                       hysteresis = <5000>; /* millicelsius */
+                                       type = "critical";
+                               };
--------------------------------------------------------
hysteresis time help to adjust the present and past temperature inputs
before critical shutdown.

Tested-by: Anand Moon <linux.amoon at gmail.com>

Best Regards
-Anand Moon


From d-gerlach at ti.com  Tue May 10 12:49:41 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Tue, 10 May 2016 14:49:41 -0500
Subject: [PATCH 1/2] ARM: dts: dra7: Add ocmcram nodes
In-Reply-To: <1462909782-14639-1-git-send-email-d-gerlach@ti.com>
References: <1462909782-14639-1-git-send-email-d-gerlach@ti.com>
Message-ID: <1462909782-14639-2-git-send-email-d-gerlach@ti.com>

Add all ocmcram nodes to dra7.dtsi using the generic mmio-sram driver.
DRA7xx and AM57xx families of SoCs can contain three ocmcram regions of
SRAM, one of 512kb and also an optional two additional of 1Mb each. Mark
the two additional 1MB regions of SRAM as disabled as only ocmcmram1 is
on all variants of the SoCs, then depending on which specific variant
is in use the ocmcram2 and ocmcram3 nodes can be enabled in the board
dts file if the data manual for that part number indicates the ocmcram
region is available.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/boot/dts/dra7.dtsi | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 13ac88279427..fd6f74856bd3 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -286,6 +286,38 @@
 			};
 		};
 
+		ocmcram1: ocmcram at 40300000 {
+			compatible = "mmio-sram";
+			reg = <0x40300000 0x80000>;
+			ranges = <0x0 0x40300000 0x80000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
+
+		/*
+		 * NOTE: ocmcram2 and ocmcram3 are not available on all
+		 * DRA7xx and AM57xx variants. Confirm availability in
+		 * the data manual for the exact part number in use
+		 * before enabling these nodes in the board dts file.
+		 */
+		ocmcram2: ocmcram at 40400000 {
+			status = "disabled";
+			compatible = "mmio-sram";
+			reg = <0x40400000 0x100000>;
+			ranges = <0x0 0x40400000 0x100000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
+
+		ocmcram3: ocmcram at 40500000 {
+			status = "disabled";
+			compatible = "mmio-sram";
+			reg = <0x40500000 0x100000>;
+			ranges = <0x0 0x40500000 0x100000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
+
 		bandgap: bandgap at 4a0021e0 {
 			reg = <0x4a0021e0 0xc
 				0x4a00232c 0xc
-- 
2.7.3



From d-gerlach at ti.com  Tue May 10 12:49:40 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Tue, 10 May 2016 14:49:40 -0500
Subject: [PATCH 0/2] ARM: dts: dra7: Add OCMCRAM nodes
Message-ID: <1462909782-14639-1-git-send-email-d-gerlach@ti.com>

Hi,
This series adds ocmcram nodes to use the mmio-sram driver to dra7.dtsi
for use by all dra7xx and am57xx platforms. Not all ocmcram regions are
present on every SoC variant so all possible nodes are added to the parent
dtsi with the optional nodes marked "disabled". Board dts files that are
known to have silicon supporting them can then enable them as needed.

Patch two adds a "dummy" reserved region in the ocmcram1 node that acts
as a placeholder for the region that is needed by secure software running
on secure variants of the SoC. It is left as size zero with the intention
that either:

- The bootloader will step in and adjust the size based on what the
  secure software that is in use requires.
- A board dts with specific requirements will override the node with
  appropriate size.

The SRAM bindings in use are described in this patch [1] that is part of a
series that adds SRAM regions for OMAP3 platforms.

Regards,
Dave

[1] http://marc.info/?l=linux-omap&m=146283061230440&w=2

Dave Gerlach (2):
  ARM: dts: dra7: Add ocmcram nodes
  ARM: dts: dra7: Add ti,secure-ram node to ocmcram1 node

 arch/arm/boot/dts/dra7.dtsi | 47 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

-- 
2.7.3



From d-gerlach at ti.com  Tue May 10 12:49:42 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Tue, 10 May 2016 14:49:42 -0500
Subject: [PATCH 2/2] ARM: dts: dra7: Add ti,secure-ram node to ocmcram1 node
In-Reply-To: <1462909782-14639-1-git-send-email-d-gerlach@ti.com>
References: <1462909782-14639-1-git-send-email-d-gerlach@ti.com>
Message-ID: <1462909782-14639-3-git-send-email-d-gerlach@ti.com>

Secure variants of DRA7xx and AM57xx SoCs may need to reserve a region
of the SRAM for use by secure software. To account for this, add a child
node to the ocmcram1 node that will act as a placeholder at the start
of the SRAM for the reserved region of memory that may be required
by secure services. The node is added with size 0 so that by default
parts will have the full space available but the bootloader or board dts
file is able to resize the node as needed depending on how much reserved
space is needed, if any, so end users of the ocmcram1 region on HS parts
must be aware that a smaller amount of SRAM than expected may be available.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/boot/dts/dra7.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index fd6f74856bd3..f46a265ce315 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -292,6 +292,21 @@
 			ranges = <0x0 0x40300000 0x80000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
+			/*
+			 * This is a placeholder for an optional reserved
+			 * region for use by secure software. The size
+			 * of this region is not known until runtime so it
+			 * is set as zero to either be updated to reserve
+			 * space or left unchanged to leave all SRAM for use.
+			 * On HS parts that that require the reserved region
+			 * either the bootloader can update the size to
+			 * the required amount or the node can be overridden
+			 * from the board dts file for the secure platform.
+			 */
+			sram-hs at 0 {
+				compatible = "ti,secure-ram";
+				reg = <0x0 0x0>;
+			};
 		};
 
 		/*
-- 
2.7.3



From arnd at arndb.de  Tue May 10 12:51:47 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 21:51:47 +0200
Subject: [PATCH v2 1/2] Documentation: DT: bindings: Add Broadcom STB PCIe
 bindings
In-Reply-To: <5732139C.80101@gmail.com>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
 <4513390.VWu0VVAxOl@wuerfel> <5732139C.80101@gmail.com>
Message-ID: <2533093.jsjycoq8tW@wuerfel>

On Tuesday 10 May 2016 10:00:12 Florian Fainelli wrote:
> 
> The two critical pieces of information that the PCIe RC needs are:
> 
> - number of memory controllers present in the system to avoid
> configuring a window to a non-existing or non-populated memory controller
> 
> - size of the memory populated on the memory controller
> 
> You would think that we should somehow be able to derive this
> information from the "memory" node, but there are a few caveats:
> 
> - on MIPS platforms, we have discontiguous physical memory ranges (256MB
> @ 0x0, then 768MB or 1792MB @ 0x 0x20000000 and 1GB @ 0x90000000), yet
> the PCIe RC does not know about the hole(s)

That sounds like you need a dma-ranges property anyway to describe how
the DMA addresses are mapped.

> - on ARM platforms, we have an identiy mapping for the PAs below 4GB,
> but when we cross it, we have additional non-linear memory regions
> 
> Both of these memory nodes would imply we know how to identify which
> physical address belongs to which memory controller, while this is
> actually possible and known, it creates a dependency on another piece of
> driver to provide that information.
> 
> We do have memory controller nodes populated in the Device Tree, however
> their binding (out of tree for the moment) does only specify their
> programmable register interface, and not how how much physical memory
> and where they provide to the system.
> 
> It does seem like we should be able to utilize the "dma-ranges" property
> to determine both the memory controller number and their respective
> populated memory sizes.
> 
> In the case where we have an identiy mapping though, this seems a little
> redundant, but less of a stretch than our custom properties and nodes.
> 
> Does that sound reasonable to you?

I'd have to look at an example first. Ideally, each line in the
dma-ranges property would refer to one memory controller, and
that would be very easy to mandate, but it sounds like in the MIPS
case you end up with an extra entry for the first 256MB that is
on the same memory controller as the second 768MB.

	Arnd


From davem at davemloft.net  Tue May 10 12:53:54 2016
From: davem at davemloft.net (David Miller)
Date: Tue, 10 May 2016 15:53:54 -0400 (EDT)
Subject: [PATCH 5/6] drivers: net: xgene: Using static MSS values
In-Reply-To: <1462838656-22043-6-git-send-email-isubramanian@apm.com>
References: <1462838656-22043-1-git-send-email-isubramanian@apm.com>
 <1462838656-22043-6-git-send-email-isubramanian@apm.com>
Message-ID: <20160510.155354.2183670732162584648.davem@davemloft.net>

From: Iyappan Subramanian <isubramanian at apm.com>
Date: Mon,  9 May 2016 17:04:15 -0700

> Due to the nature of hardware design for TSO, if the MSS values that are
> stored in the register, changes during TSO operation, data corruption may
> occur.
> 
> This patch fixes the issue by using one of the predefined MSS values.
> 
> Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
> Tested-by: Toan Le <toanle at apm.com>

This is a very serious quality of implementation issue.

And it could quietly kill performance for some users, and there is no
way for them to find out that this is happening.

If you use a predefined set of MSS values, if the MSS value we need is
between two of them then there is going to be wasted space on the
wire.  It's can therefore certainly be better to not do TSO in that
case.

I think you absolutely need to disable TSO by default, and require the
user to explicitly turn it on, unless you can fix this problem in
another way.

Thanks.


From chunkeey at googlemail.com  Tue May 10 12:55:15 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Tue, 10 May 2016 21:55:15 +0200
Subject: [PATCH v8 2/3] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <CACRpkdaeZ14hfz-gRetRcdj8NzzyqigV1ZtDSWAwveFxwAgt0w@mail.gmail.com>
References: <cover.1462543457.git.chunkeey@googlemail.com>
 <535f785bf6116c0fb6f46afbb77e6d4bd3ef5f60.1462543458.git.chunkeey@googlemail.com>
 <CACRpkdaeZ14hfz-gRetRcdj8NzzyqigV1ZtDSWAwveFxwAgt0w@mail.gmail.com>
Message-ID: <3359834.V76Y1cJiRU@debian64>

On Tuesday, May 10, 2016 02:08:45 PM Linus Walleij wrote:
> On Sun, May 8, 2016 at 3:08 PM, Christian Lamparter
> <chunkeey at googlemail.com> wrote:
> 
> > From: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
> >
> > This patch adds support for defining memory-mapped GPIOs which
> > are compatible with the existing gpio-mmio interface.
> 
> Overall very nice, just waiting for the next version.

K, will deliver. I noticed that you sent a mail in which you stated
that you applied the dt binding already. Can you update your devel
branch on git.kernel.org's linux-gpio? Then, I'll simply rebase my
series and sent the remaining two patches.
(unless you tell me otherwise).
 
> > The first user for this binding is "wd,mbl-gpio".
> 
> And that binding defines that we have a register named "dat".

Yeah, I had to remove all non wd related bits. But since this 
series was posted (over and over :D) on a public mailing-list
the original  "generic" linux-mmio binding is available for
everybody to perusal[0] and study. I think what we can make
would be something like a devicetree template out of it. This
way people can remove unused flags and regnames for their
compatible device tree binding. (But first: need to finish
that ppc-gpio.txt).

> > +       if (of_property_read_bool(dev->of_node, "no-output"))
> 
> And then this too.
> 
> Do we want these generic MMIO bindings (dat, no-output)
> in a special document like
> Documentation/devicetree/bindings/gpio/gpio-mmio.txt?
> 
> Going forward?
Ah, I was thinking about Documentation/gpio... Since there's no
way it would go in the devicetree/bindings without having a compatible?
(And there's technically none). As far as I know the problem here is not
that it would be impossible to do that (updating a .dts file is "easy"...),
but updating .dtb to a tiny flash-rom on the device might not be. So we
have to make every effort to preserve compatibility for those devices
(and old/incomplete/broken dtbs) as long as the device is supported.

About adding new device:
This will work in the following way: 
 1. new drives will need to supply their hardware-specific devicetree
    binding file to the dt maintainers (This "vendor,device.txt" file
    will be like the wd,mbl-gpio.txt - but modified for the hardware
    (this is where the template would be handy)

 2. Make a one-liner patch which adds a compatible string to
    gpio-mmio.c's bgpio_of_match table:

+	{ .compatible = "vendor,device", .data = bgpio_basic_mmio_parse_dt },

(Of course, not having parses for the "ngpio" property and the flags like
big-endian, reg-output-reg,set, unreadable-reg-dir, ... properties from
the get-go is sad, these can add back once a driver/binding needs it).

I think brcm63xx will be following shortly. So we can test the
procedure.
> This patch set mainly deals with refactorings, but in the
> long run we want to slim things down a bit and use standard
> bindings I think.
Well, to do that, I think we need to collect enough devices to
make it a real "class" of devices first.

Regards,
Christian

[0] <https://lkml.org/lkml/2016/4/28/921>


From kernel at martin.sperl.org  Tue May 10 12:58:08 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Tue, 10 May 2016 21:58:08 +0200
Subject: [PATCH 0/3] clk: bcm2835: critical clocks and parent selection
In-Reply-To: <87a8jxyfua.fsf@eliezer.anholt.net>
References: <1462842090-2017-1-git-send-email-eric@anholt.net>
 <5731B8BA.30402@martin.sperl.org> <87a8jxyfua.fsf@eliezer.anholt.net>
Message-ID: <FD44F435-512C-49A5-B1F5-3C62AAF805AC@martin.sperl.org>



> On 10.05.2016, at 19:37, Eric Anholt <eric at anholt.net> wrote:
> 
> Martin Sperl <kernel at martin.sperl.org> writes:
> 
>>> On 10.05.2016 03:01, Eric Anholt wrote:
>>> With the new patch 2 inserted between my previous pair, I think this
>>> should cover Martin's bugs with clock disabling.
>>> 
>>> I tested patch 2 to be important on the downstream kernel: with the
>>> DPI panel support added there, I was losing ethernet (my only I/O)
>>> when the HDMI HSM hanging off of PLLD_PER got disabled due to
>>> EPROBE_DEFER.
>>> 
>>> Eric Anholt (3):
>>>  clk: bcm2835: Mark the VPU clock as critical
>>>  clk: bcm2835: Mark GPIO clocks enabled at boot as critical.
>>>  clk: bcm2835: Skip PLLC clocks when deciding on a new clock parent
>>> 
>>> drivers/clk/bcm/clk-bcm2835.c | 32 ++++++++++++++++++++++++++++++--
>>> 1 file changed, 30 insertions(+), 2 deletions(-)
>> I gave it a try - with all 3 patches applied I get the following enabled 
>> clocks:
>> root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
>> /sys/kernel/debug/clk/aux_uart/clk_enable_count:1
>> /sys/kernel/debug/clk/emmc/clk_enable_count:1
>> /sys/kernel/debug/clk/gp1/clk_enable_count:1
>> /sys/kernel/debug/clk/gp2/clk_enable_count:1
>> /sys/kernel/debug/clk/osc/clk_enable_count:1
>> /sys/kernel/debug/clk/pllc/clk_enable_count:2
>> /sys/kernel/debug/clk/pllc_core0/clk_enable_count:1
>> /sys/kernel/debug/clk/pllc_per/clk_enable_count:1
>> /sys/kernel/debug/clk/vpu/clk_enable_count:2
>> 
>> At least on my compute module gp1/gp2 is enabled, but there is no rate
>> set - so why is it marked as critical for all devices?
>> So why apply patch2 for all possible devices?
> 
> According to the CLK_IS_CRITICAL patches, the author intended critical
> clocks not to use the included function for marking clocks as critical
> From the DT.  I'm not sure why, but writing patches using that when they
> say not to seemed like a waste.
> 
> We could check if gp1/gp2 are already on before marking them critical.
That may seem reasonable.
> 
>> Loading/unloading the amba_pl011 module does not crash the system,
>> but a simple stty -F /dev/ttyAMA0 does crash the system!
>> 
>> Here the sequence:
>> root at raspcm:~# dmesg -C
>> root at raspcm:~# modprobe amba_pl011
>> root at raspcm:~# dmesg -c
>> [  141.708453] Serial: AMBA PL011 UART driver
>> [  141.709158] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, 
>> base_baud = 0) is a PL011 rev2
>> root at raspcm:~# rmmod  amba_pl011
>> root at raspcm:~# dmesg -c
>> [  150.511248] Trying to free nonexistent resource 
>> <0000000020201000-0000000020201fff>
>> root at raspcm:~# modprobe amba_pl011
>> root at raspcm:~# dmesg -c
>> [  159.385002] Serial: AMBA PL011 UART driver
>> [  159.385714] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, 
>> base_baud = 0) is a PL011 rev2
>> root at raspcm:~# stty -F /dev/ttyAMA0
>> speed 9600 baud; line = 0;
>> -brkint -imaxbel
>> root at raspcm:~# Timeout, server raspcm not responding.
>> 
>> The reason behind this is that the firmware pre-configured uart clock
>> looks like this:
>> root at raspcm:~# cat /sys/kernel/debug/clk/uart/regdump
>> ctl = 0x00000296
>> div = 0x000a6aab
>> so it is configured to use plld_per (which itself is running, even if 
>> not enabled
>> in the kernel)
>> 
>> But as plld_per is not among the enabled clocks then plld_per
>> gets disabled as soon as the tty device is closed (by stty) and
>> this also disables plld...
>> 
>> Similar effect when using PCM/i2s and use speaker-test:
>> root at raspcm:~# dmesg -C
>> root at raspcm:~# modprobe snd-soc-bcm2835-i2s; modprobe snd-soc-pcm5102a; 
>> modprobe snd-soc-hifiberry-dac
>> root at raspcm:~# dmesg
>> [   81.968591] snd-hifiberry-dac sound: pcm5102a-hifi <-> 20203000.i2s 
>> mapping ok
>> root at raspcm:~# speaker-test -c 2 -r 44100 -F S16_LE -f 440 -t sine&
>> [1] 579
>> root at raspcm:~#
>> speaker-test 1.0.28
>> 
>> Playback device is default
>> Stream parameters are 44100Hz, S16_LE, 2 channels
>> Sine wave rate is 440.0000Hz
>> Rate set to 44100Hz (requested 44100Hz)
>> Buffer size range from 128 to 131072
>> Period size range from 64 to 65536
>> Using max buffer size 131072
>> Periods = 4
>> was set period_size = 32768
>> was set buffer_size = 131072
>> 0 - Front Left
>> 1 - Front Right
>> 
>> root at raspcm:~#
>> root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
>> /sys/kernel/debug/clk/aux_uart/clk_enable_count:1
>> /sys/kernel/debug/clk/emmc/clk_enable_count:1
>> /sys/kernel/debug/clk/gp1/clk_enable_count:1
>> /sys/kernel/debug/clk/gp2/clk_enable_count:1
>> /sys/kernel/debug/clk/osc/clk_enable_count:2
>> /sys/kernel/debug/clk/pcm/clk_enable_count:1
>> /sys/kernel/debug/clk/pllc/clk_enable_count:2
>> /sys/kernel/debug/clk/pllc_core0/clk_enable_count:1
>> /sys/kernel/debug/clk/pllc_per/clk_enable_count:1
>> /sys/kernel/debug/clk/plld/clk_enable_count:1
>> /sys/kernel/debug/clk/plld_per/clk_enable_count:1
>> /sys/kernel/debug/clk/vpu/clk_enable_count:2
>> root at raspcm:~# kill %1
>> root at raspcm:~# Time per period = 106.889502
>> Timeout, server raspcm not responding.
>> 
>> You see that plld gets now used and when I kill speaker-test
>> the machine crashes again.
> 
> Just so I can be clear here: What are you using to talk to the Pi?
> Builtin USB ethernet?
Compute module with USB  Ethernet adapter, but I also got an 
enc28j60 connected via spi, but that is not enabled by default

> 
>> So this patchset does not really solve any of the problems that
>> I have reported either.
>> 
>> That is why my patchset has taken the "HAND_OFF" approach
>> instead (which still just hides some of the issues), but at least
>> it does not crash the system on the use of plld and it allows
>> for custom parent and mash selection.
> 
> HAND_OFF sure doesn't look like it's landing in the next kernel, so
> writing patches using it doesn't make much sense to me.

If it is critical or hands-off does not really make a difference...

>> In reality it would require consumers of the corresponding
>> parent clocks in the kernel (arm, ...) and the knowledge which
>> clocks are really needed by the firmware - i.e plld.
>> 
>> Note that the sdram clock is using plld_core parent!
>> root at raspcm:~#  cat /sys/kernel/debug/clk/sdram/regdump
>> ctl = 0x00004006
>> div = 0x00003000
>> root at raspcm:~# cat /sys/kernel/debug/clk/sdram/clk_rate
>> 166533331
> 
> However, it's not enabled, right?  Bit 4 isn't set in the CTL reg.
You are probably right there, but still there must be something
hidden that requires plld or plld_per or plld_core, that requires critical.

There must be some reason why it gets set up during the
boot process by the firmware.

> 
>> and also hsm (probably hardware security module):
>> root at raspcm:~# cat /sys/kernel/debug/clk/hsm/regdump
>> ctl = 0x000002d6
>> div = 0x000030e0
>> root at raspcm:~# cat /sys/kernel/debug/clk/hsm/clk_rate
>> 163551916
> 
> That's the HDMI state machine (there's even a comment saying so),
> controlled by the vc4 driver.
> 
>> So turning plld off stops sdram and hsm - at least that is my
>> interpretation.
>> 
>> This means we need to define a clock property in firmware or
>> we need a ram node making use of "mmio-sram" maybe?
>> 
>> Marking sdram as "critical" or "hand_off" could also solve that
>> for the moment (but it does not solve all the other hidden
>> clock dependencies of the firmware)
> 
> If there are other hidden dependencies, then we should figure them out.

But strangely the sdram (plus the below) is the only one with
plld that is enabled (unless it is one of the clocks we have not
added to the kernel side yet)

Maybe there is something that derives directly from plld_core
or any of the other plld-dividers?

Core would indicate anything central to the videocore...
Anyway both plld_core as well as plld_per ad well as both
Pll_dsi that are running by default (but I doubt that the
Dsi would be relevant)

I guess you are in a better situation to figure out which
hidden HW blocks uses plld...

> 
>> --- a/drivers/clk/bcm/clk-bcm2835.c
>> +++ b/drivers/clk/bcm/clk-bcm2835.c
>> @@ -1655,7 +1655,8 @@ static const struct bcm2835_clk_desc 
>> clk_desc_array[] = {
>>                .ctl_reg = CM_SDCCTL,
>>                .div_reg = CM_SDCDIV,
>>                .int_bits = 6,
>> -               .frac_bits = 0),
>> +               .frac_bits = 0,
>> +               .flags = CLK_IS_CRITICAL),
>>        [BCM2835_CLOCK_V3D]     = REGISTER_VPU_CLK(
>>                .name = "v3d",
>>                .ctl_reg = CM_V3DCTL,
> 
> The Pi foundation folks believe that the cprman SDRAM clock isn't ever
> used (there's a separate PLL in the SDRAM controller, and cprman is only
> intended for unused low-power states), and at least in your sample of
> the reg, it's not enabled.  Instead of grepping for clk_enable_count, it
See my comment above - it must be configured for some reason
during the boot process by the firmware .


> would be really useful for debugging to look at your clk_summary
> instead.

Here you go:
   clock                         enable_cnt  prepare_cnt        rate   accuracy   phase
----------------------------------------------------------------------------------------
 uart1_pclk                               0            0   125000000          0 0
 uart0_pclk                               0            0     3000000          0 0
 apb_pclk                                 0            0   126000000          0 0
 osc                                      2            2    19200000          0 0
    tsens                                 0            0     1920000          0 0
    vec                                   0            0    19200000          0 0
    otp                                   0            0     4800000          0 0
    timer                                 0            0     1000002          0 0
    pllh                                  0            0  1485000000          0 0
       pllh_pix_prediv                    0            0  1485000000          0 0
          pllh_pix                        0            0   148500000          0 0
       pllh_aux_prediv                    0            0     5800782          0 0
          pllh_aux                        0            0      580078          0 0
       pllh_rcal_prediv                   0            0     5800782          0 0
          pllh_rcal                       0            0      580078          0 0
    plld                                  2            2  1998399975          0 0
       plld_dsi1                          0            0     7806250          0 0
       plld_dsi0                          0            0     7806250          0 0
       plld_per                           1            1   499599994          0 0
          pwm                             1            1     9999958          0 0
          hsm                             0            0   163551916          0 0
          uart                            0            0     2997598          0 0
       plld_core                          1            1   499599994          0 0
          sdram                           1            1   166533331          0 0
    pllc                                  2            2  1998399975          0 0
       pllc_per                           1            1   999199988          0 0
          emmc                            1            1   249799997          0 0
       pllc_core2                         0            0     7806250          0 0
       pllc_core1                         0            0     7806250          0 0
       pllc_core0                         1            1   999199988          0 0
          vpu                             1            1   249799997          0 0
             aux_spi2                     0            0   249799997          0 0
             aux_spi1                     0            0   249799997          0 0
             aux_uart                     0            0   249799997          0 0
             peri_image                   0            0   249799997          0 0
    pllb                                  0            0  1399999951          0 0
       pllb_arm                           0            0   699999976          0 0
    plla                                  0            0  1998399975          0 0
       plla_ccp2                          0            0     7806250          0 0
       plla_dsi0                          0            0     7806250          0 0
       plla_per                           0            0     7806250          0 0
       plla_core                          0            0   999199988          0 0
          h264                            0            0   249799997          0 0
          isp                             0            0   249799997          0 0
          v3d                             0            0   249799997          0 0
 dsi1e                                    0            0           0          0 0
 dsi0e                                    0            0           0          0 0
 cam1                                     0            0           0          0 0
 cam0                                     0            0           0          0 0
 dpi                                      0            0           0          0 0
 tec                                      0            0           0          0 0
 smi                                      0            0           0          0 0
 slim                                     0            0           0          0 0
 gp2                                      1            1           0          0 0
 gp1                                      1            1           0          0 0
 gp0                                      0            0           0          0 0
 dft                                      0            0           0          0 0
 aveo                                     0            0           0          0 0
 pcm                                      0            0           0          0 0

(that is with the critical patch for sdram - so ignore the ?enable_count?
for sdram)

> 
>> Still I would say that this should actually move to the dt to
>> correctly describe the HW.
> 
> If you created a series that *just* added critical support, using
> assigned-clocks, and got the DT folks to agree to it, that would be fine
> with me.

In the end I do not care for which patch gets in - I just want a solution
that does not crash and I guess that is also what the foundation
wants (and they want to move to the clock framework and I try to get
it there)

Martin

From serveralex at gmail.com  Tue May 10 13:08:35 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Tue, 10 May 2016 22:08:35 +0200
Subject: [PATCH 1/6] pinctrl: meson: Fix eth_tx_en bit index
In-Reply-To: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
References: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
Message-ID: <1462910920-5462-2-git-send-email-serveralex@gmail.com>

Fix pinctrl eth_tx_en bit index according to Hardkernel ODROID-C1 datasheet.

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 drivers/pinctrl/meson/pinctrl-meson8b.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/meson/pinctrl-meson8b.c b/drivers/pinctrl/meson/pinctrl-meson8b.c
index a100bcf..874f2ed 100644
--- a/drivers/pinctrl/meson/pinctrl-meson8b.c
+++ b/drivers/pinctrl/meson/pinctrl-meson8b.c
@@ -564,7 +564,7 @@ static struct meson_pmx_group meson8b_cbus_groups[] = {
 	GROUP(eth_rx_clk,	6,	3),
 	GROUP(eth_txd0_1,	6,	4),
 	GROUP(eth_txd1_1,	6,	5),
-	GROUP(eth_tx_en,	6,	0),
+	GROUP(eth_tx_en,	6,	6),
 	GROUP(eth_ref_clk,	6,	8),
 	GROUP(eth_mdc,		6,	9),
 	GROUP(eth_mdio_en,	6,	10),
-- 
2.5.0



From serveralex at gmail.com  Tue May 10 13:08:34 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Tue, 10 May 2016 22:08:34 +0200
Subject: [PATCH 0/6] Enable ethernet support on Amlogic meson8b / Hardkernel
 ODROID-C1
Message-ID: <1462910920-5462-1-git-send-email-serveralex@gmail.com>

This patch series fixes a glitch in the pinctrl driver, adds clock gates
support and configures ethernet support via stmmac.

The previously sent patch "pinctrl: meson: Fix eth_tx_en bit index" is
also included in this patch series.

Alexander M?ller (6):
  pinctrl: meson: Fix eth_tx_en bit index
  ARM: DTS: Amlogic: Add ethernet pins
  ARM: clk: Amlogic: Add support for clock gates
  ARM: clk: Amlogic: Add clk81 clock gates
  ARM: DTS: Amlogic: Enable ethernet on meson8b
  ARM: DTS: Amlogic: Enable ethernet on ODROID-C1

 arch/arm/boot/dts/meson8b-odroidc1.dts   |  10 ++
 arch/arm/boot/dts/meson8b.dtsi           |  25 ++++
 drivers/clk/meson/clkc.c                 |  18 +++
 drivers/clk/meson/clkc.h                 |  18 +++
 drivers/clk/meson/meson8b-clkc.c         | 196 +++++++++++++++++++++++++++++++
 drivers/pinctrl/meson/pinctrl-meson8b.c  |   2 +-
 include/dt-bindings/clock/meson8b-clkc.h |  99 +++++++++++++++-
 7 files changed, 365 insertions(+), 3 deletions(-)

-- 
2.5.0



From serveralex at gmail.com  Tue May 10 13:08:36 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Tue, 10 May 2016 22:08:36 +0200
Subject: [PATCH 2/6] ARM: DTS: Amlogic: Add ethernet pins
In-Reply-To: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
References: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
Message-ID: <1462910920-5462-3-git-send-email-serveralex@gmail.com>

Add pins for ethernet interface

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 arch/arm/boot/dts/meson8b.dtsi | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index 2bfe401..8ef2da8 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -171,6 +171,20 @@
 				gpio-controller;
 				#gpio-cells = <2>;
 			};
+
+			ethernet_pins: ethernet {
+				mux {
+					groups = "eth_tx_clk", "eth_tx_en",
+						"eth_txd1_0", "eth_txd1_1",
+						"eth_txd0_0", "eth_txd0_1",
+						"eth_rx_clk", "eth_rx_dv",
+						"eth_rxd1", "eth_rxd0",
+						"eth_mdio_en", "eth_mdc",
+						"eth_ref_clk", "eth_txd2",
+						"eth_txd3";
+					function = "ethernet";
+				};
+			};
 		};
 
 		pinctrl_aobus: pinctrl at c8100084 {
-- 
2.5.0



From serveralex at gmail.com  Tue May 10 13:08:37 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Tue, 10 May 2016 22:08:37 +0200
Subject: [PATCH 3/6] ARM: clk: Amlogic: Add support for clock gates
In-Reply-To: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
References: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
Message-ID: <1462910920-5462-4-git-send-email-serveralex@gmail.com>

Adds support to register clock gates required to enable SoC components that
are disabled by default.

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 drivers/clk/meson/clkc.c | 18 ++++++++++++++++++
 drivers/clk/meson/clkc.h | 18 ++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c
index d920d41..a7a14a2 100644
--- a/drivers/clk/meson/clkc.c
+++ b/drivers/clk/meson/clkc.c
@@ -197,6 +197,20 @@ meson_clk_register_fixed_rate(const struct clk_conf *clk_conf,
 	return clk;
 }
 
+static struct clk * __init
+meson_clk_register_gate(const struct clk_conf *clk_conf,
+			      void __iomem *clk_base, spinlock_t *lock)
+{
+	return clk_register_gate(NULL, clk_conf->clk_name,
+			clk_conf->num_parents
+				? clk_conf->clks_parent[0] : NULL,
+			clk_conf->flags,
+			clk_base + clk_conf->reg_off,
+			clk_conf->conf.gate.bit_idx,
+			0,
+			lock);
+}
+
 void __init meson_clk_register_clks(const struct clk_conf *clk_confs,
 				    unsigned int nr_confs,
 				    void __iomem *clk_base)
@@ -228,6 +242,10 @@ void __init meson_clk_register_clks(const struct clk_conf *clk_confs,
 			clk = meson_clk_register_pll(clk_conf, clk_base,
 						     &clk_lock);
 			break;
+		case CLK_GATE:
+			clk = meson_clk_register_gate(clk_conf, clk_base,
+							 &clk_lock);
+			break;
 		default:
 			clk = NULL;
 		}
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index 609ae92..944a50b 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -85,6 +85,10 @@ struct composite_conf {
 	u8			gate_flags;
 };
 
+struct gate_conf {
+	u8			bit_idx;
+};
+
 #define PNAME(x) static const char *x[]
 
 enum clk_type {
@@ -93,6 +97,7 @@ enum clk_type {
 	CLK_COMPOSITE,
 	CLK_CPU,
 	CLK_PLL,
+	CLK_GATE,
 };
 
 struct clk_conf {
@@ -109,6 +114,7 @@ struct clk_conf {
 		const struct composite_conf		*composite;
 		struct pll_conf			*pll;
 		const struct clk_div_table	*div_table;
+		const struct gate_conf		gate;
 	} conf;
 };
 
@@ -176,6 +182,18 @@ struct clk_conf {
 		.conf.composite			= (_c),			\
 	}								\
 
+#define GATE(_ro, _ci, _cn, _cp, _f, _bi)				\
+	{								\
+		.reg_off			= (_ro),		\
+		.clk_type			= CLK_GATE,		\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.clks_parent			= (_cp),		\
+		.num_parents			= ARRAY_SIZE(_cp),	\
+		.flags				= (_f),			\
+		.conf.gate.bit_idx		= (_bi),		\
+	}								\
+
 struct clk **meson_clk_init(struct device_node *np, unsigned long nr_clks);
 void meson_clk_register_clks(const struct clk_conf *clk_confs,
 			     unsigned int nr_confs, void __iomem *clk_base);
-- 
2.5.0



From serveralex at gmail.com  Tue May 10 13:08:40 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Tue, 10 May 2016 22:08:40 +0200
Subject: [PATCH 6/6] ARM: DTS: Amlogic: Enable ethernet on ODROID-C1
In-Reply-To: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
References: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
Message-ID: <1462910920-5462-7-git-send-email-serveralex@gmail.com>

ODROID-C1 uses Amlogic meson8b integrated ethernet IC (compatible with
stmmac) and a Realtek RTL8211F gigabit ethernet PHY. The reset pin is
connected to GPIOH_4.

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 arch/arm/boot/dts/meson8b-odroidc1.dts | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/meson8b-odroidc1.dts
index e50f1a1..44410d9 100644
--- a/arch/arm/boot/dts/meson8b-odroidc1.dts
+++ b/arch/arm/boot/dts/meson8b-odroidc1.dts
@@ -76,3 +76,13 @@
 	pinctrl-0 = <&uart_ao_a_pins>;
 	pinctrl-names = "default";
 };
+
+&ethmac {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&ethernet_pins>;
+	snps,reset-gpio = <&gpio GPIOH_4 GPIO_ACTIVE_HIGH>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 50000>;
+};
+
-- 
2.5.0



From serveralex at gmail.com  Tue May 10 13:08:39 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Tue, 10 May 2016 22:08:39 +0200
Subject: [PATCH 5/6] ARM: DTS: Amlogic: Enable ethernet on meson8b
In-Reply-To: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
References: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
Message-ID: <1462910920-5462-6-git-send-email-serveralex@gmail.com>

Add ethernet to meson8b devicetree.

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 arch/arm/boot/dts/meson8b.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index 8ef2da8..a62fba9 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -210,5 +210,16 @@
 				};
 			};
 		};
+
+		ethmac: ethernet at c9410000 {
+			compatible = "amlogic,meson6-dwmac", "snps,dwmac";
+			reg = <0xc9410000 0x10000
+				0xc1108108 0x4>;
+			interrupts = <0 8 1>;
+			interrupt-names = "macirq";
+			clocks = <&clkc CLKID_ETHERNET>;
+			clock-names = "stmmaceth";
+			status = "disabled";
+		};
 	};
 }; /* end of / */
-- 
2.5.0



From serveralex at gmail.com  Tue May 10 13:08:38 2016
From: serveralex at gmail.com (=?UTF-8?q?Alexander=20M=C3=BCller?=)
Date: Tue, 10 May 2016 22:08:38 +0200
Subject: [PATCH 4/6] ARM: clk: Amlogic: Add clk81 clock gates
In-Reply-To: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
References: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
Message-ID: <1462910920-5462-5-git-send-email-serveralex@gmail.com>

Add the clk81 clock gates and make them configurable via devicetree.

Signed-off-by: Alexander M?ller <serveralex at gmail.com>
---
 drivers/clk/meson/meson8b-clkc.c         | 196 +++++++++++++++++++++++++++++++
 include/dt-bindings/clock/meson8b-clkc.h |  99 +++++++++++++++-
 2 files changed, 293 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c
index 61f6d55..cb8148c 100644
--- a/drivers/clk/meson/meson8b-clkc.c
+++ b/drivers/clk/meson/meson8b-clkc.c
@@ -26,6 +26,9 @@
 
 #define MESON8B_REG_CTL0_ADDR		0x0000
 #define MESON8B_REG_SYS_CPU_CNTL1	0x015c
+#define MESON8B_REG_HHI_GCLK_MPEG0	0x0140
+#define MESON8B_REG_HHI_GCLK_MPEG1	0x0144
+#define MESON8B_REG_HHI_GCLK_MPEG2	0x0148
 #define MESON8B_REG_HHI_MPEG		0x0174
 #define MESON8B_REG_MALI		0x01b0
 #define MESON8B_REG_PLL_FIXED		0x0280
@@ -108,6 +111,7 @@ PNAME(p_cpu_clk)	= { "sys_pll" };
 PNAME(p_clk81)		= { "fclk_div3", "fclk_div4", "fclk_div5" };
 PNAME(p_mali)		= { "fclk_div3", "fclk_div4", "fclk_div5",
 			    "fclk_div7", "zero" };
+PNAME(p_clk81_gate)	= { "clk81" };
 
 static u32 mux_table_clk81[]	= { 6, 5, 7 };
 static u32 mux_table_mali[]	= { 6, 5, 7, 4, 0 };
@@ -163,6 +167,198 @@ static const struct clk_conf meson8b_clk_confs[] __initconst = {
 		  CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED, &clk81_conf),
 	COMPOSITE(MESON8B_REG_MALI, CLKID_MALI, "mali", p_mali,
 		  CLK_IGNORE_UNUSED, &mali_conf),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_DDR, "ddr", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 0),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_DOS, "dos", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 1),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RESERVED0_0, "reserved0_0",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 2),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RESERVED0_1, "reserved0_1",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 3),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_AHB_BRIDGE, "ahb_bridge",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 4),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_ISA, "isa", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 5),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_PL310_CBUS, "pl310_cbus",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 6),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_PPERIPHS_TOP, "pperiphs_top",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 7),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_SPICC, "spicc", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 8),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_I2C, "i2c", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 9),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_SAR_ADC, "sar_adc", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 10),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_SMART_CARD_MPEG_DOMAIN,
+		"smart_card_mpeg_domain", p_clk81_gate, CLK_IGNORE_UNUSED, 11),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RANDOM_NUM_GEN, "random_num_gen",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 12),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_UART0, "uart0", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 13),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_SDHC, "sdhc", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 14),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_STREAM, "stream", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 15),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_ASYNC_FIFO, "async_fifo",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 16),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_SDIO, "sdio", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 17),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_AUD_BUF, "auf_buf", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 18),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_HIU_PARSER, "hiu_parser",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 19),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RESERVED0_2, "reserved0_2",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 20),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RESERVED0_3, "reserved0_3",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 21),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RESERVED0_4, "reserved0_4",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 22),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_ASSIST_MISC, "assist_misc",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 23),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RESERVED0_5, "reserved0_5",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 24),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RESERVED0_6, "reserved0_6",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 25),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RESERVED0_7, "reserved0_7",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 26),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RESERVED0_8, "reserved0_8",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 27),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RESERVED0_9, "reserved0_9",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 28),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RESERVED0_A, "reserved0_a",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 29),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_SPI, "api", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 30),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG0, CLKID_RESERVED0_B, "reserved0_b",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 31),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_RESERVED1_1, "reserved1_1",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 0),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_RESERVED1_2, "reserved1_2",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 1),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_AUD_IN, "aud_in", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 2),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_ETHERNET, "ethernet",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 3),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_DEMUX, "demux", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 4),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_RESERVED1_3, "reserved1_3",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 5),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_AIU_AI_TOP_GLUE,
+		"aiu_ai_top_glue", p_clk81_gate, CLK_IGNORE_UNUSED, 6),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_AIU_IEC958, "aiu_iec958",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 7),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_AIU_I2S_OUT, "aiu_i2s_out",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 8),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_AIU_AMCLK_MEASURE,
+		"aiu_amclk_measure", p_clk81_gate, CLK_IGNORE_UNUSED, 9),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_AIU_AIFIFO2, "aiu_aififo2",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 10),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_AIU_AUD_MIXER, "aiu_aud_mixer",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 11),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_AIU_MIXER_REG, "aiu_mixer_reg",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 12),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_AIU_ADC, "aiu_adc",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 13),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_BLK_MOV, "blk_mov",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 14),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_AIU_TOP_LEVEL, "aiu_top_level",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 15),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_UART1, "uart1", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 16),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_RESERVED1_4, "reserved1_4",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 17),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_RESERVED1_5, "reserved1_5",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 18),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_RESERVED1_6, "reserved1_6",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 19),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_GE2D, "ge2d", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 20),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_USB0, "usb0", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 21),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_USB1, "usb1", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 22),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_RESET, "reset", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 23),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_NAND, "nand", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 24),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_HIU_PARSER_TOP,
+		"hiu_parser_top", p_clk81_gate, CLK_IGNORE_UNUSED, 25),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_USB_GENERAL, "usb_general",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 26),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_RESERVED1_7, "reserved1_7",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 27),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_VDIN1, "vdin1", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 28),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_AHB_ARB0, "ahb_arb0",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 29),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_EFUSE, "efuse", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 30),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG1, CLKID_ROM_CLK, "rom_clk",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 31),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_0, "reserved2_0",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 0),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_AHB_DATA_BUS, "ahb_data_bus",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 1),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_AHB_CONTROL_BUS,
+		"ahb_control_bus", p_clk81_gate, CLK_IGNORE_UNUSED, 2),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_HDMI_INTR_SYNC,
+		"hdmi_intr_sync", p_clk81_gate, CLK_IGNORE_UNUSED, 3),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_HDMI_PCLK, "hdmi_pclk",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 4),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_1, "reserved2_1",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 5),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_2, "reserved2_2",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 6),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_3, "reserved2_3",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 7),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_MISC_USB1_TO_DDR,
+		"misc_usb1_to_ddr", p_clk81_gate, CLK_IGNORE_UNUSED, 8),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_MISC_USB0_TO_DDR,
+		"misc_usb0_to_ddr", p_clk81_gate, CLK_IGNORE_UNUSED, 9),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_4, "reserved2_4",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 10),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_MMC_PCLK, "mmc_pclk",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 11),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_MISC_DVIN, "misc_dvin",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 12),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_5, "reserved2_5",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 13),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_6, "reserved2_6",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 14),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_UART2, "uart2", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 15),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_7, "reserved2_7",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 16),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_8, "reserved2_8",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 17),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_9, "reserved2_9",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 18),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_A, "reserved2_a",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 19),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_B, "reserved2_b",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 20),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_C, "reserved2_c",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 21),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_SANA, "sana", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 22),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_D, "reserved2_d",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 23),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_E, "reserved2_e",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 24),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_VPU_INTR, "vpu_intr",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 25),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_SECURE_AHP_APB3,
+		"secure_ahp_apb3", p_clk81_gate, CLK_IGNORE_UNUSED, 26),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_F, "reserved2_f",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 27),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_10, "reserved2_10",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 28),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_TO_A9, "to_a9", p_clk81_gate,
+		CLK_IGNORE_UNUSED, 29),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_11, "reserved2_11",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 30),
+	GATE(MESON8B_REG_HHI_GCLK_MPEG2, CLKID_RESERVED2_12, "reserved2_12",
+		p_clk81_gate, CLK_IGNORE_UNUSED, 31),
 };
 
 static void __init meson8b_clkc_init(struct device_node *np)
diff --git a/include/dt-bindings/clock/meson8b-clkc.h b/include/dt-bindings/clock/meson8b-clkc.h
index bd2720d..e7600e3 100644
--- a/include/dt-bindings/clock/meson8b-clkc.h
+++ b/include/dt-bindings/clock/meson8b-clkc.h
@@ -19,7 +19,102 @@
 #define CLKID_MALI		11
 #define CLKID_CPUCLK		12
 #define CLKID_ZERO		13
-
-#define CLK_NR_CLKS		(CLKID_ZERO + 1)
+#define CLKID_DDR		14
+#define CLKID_DOS		15
+#define CLKID_RESERVED0_0	16
+#define CLKID_RESERVED0_1	17
+#define CLKID_AHB_BRIDGE	18
+#define CLKID_ISA		19
+#define CLKID_PL310_CBUS	20
+#define CLKID_PPERIPHS_TOP	21
+#define CLKID_SPICC		22
+#define CLKID_I2C		23
+#define CLKID_SAR_ADC		24
+#define CLKID_SMART_CARD_MPEG_DOMAIN 25
+#define CLKID_RANDOM_NUM_GEN	26
+#define CLKID_UART0		27
+#define CLKID_SDHC		28
+#define CLKID_STREAM		29
+#define CLKID_ASYNC_FIFO	30
+#define CLKID_SDIO		31
+#define CLKID_AUD_BUF		32
+#define CLKID_HIU_PARSER	33
+#define CLKID_RESERVED0_2	34
+#define CLKID_RESERVED0_3	35
+#define CLKID_RESERVED0_4	36
+#define CLKID_ASSIST_MISC	37
+#define CLKID_RESERVED0_5	38
+#define CLKID_RESERVED0_6	39
+#define CLKID_RESERVED0_7	40
+#define CLKID_RESERVED0_8	41
+#define CLKID_RESERVED0_9	42
+#define CLKID_RESERVED0_A	43
+#define CLKID_SPI		44
+#define CLKID_RESERVED0_B	45
+#define CLKID_RESERVED1_1	46
+#define CLKID_RESERVED1_2	47
+#define CLKID_AUD_IN		48
+#define CLKID_ETHERNET		49
+#define CLKID_DEMUX		50
+#define CLKID_RESERVED1_3	51
+#define CLKID_AIU_AI_TOP_GLUE	52
+#define CLKID_AIU_IEC958	53
+#define CLKID_AIU_I2S_OUT	54
+#define CLKID_AIU_AMCLK_MEASURE 55
+#define CLKID_AIU_AIFIFO2	56
+#define CLKID_AIU_AUD_MIXER	57
+#define CLKID_AIU_MIXER_REG	58
+#define CLKID_AIU_ADC		59
+#define CLKID_BLK_MOV		60
+#define CLKID_AIU_TOP_LEVEL	61
+#define CLKID_UART1		62
+#define CLKID_RESERVED1_4	63
+#define CLKID_RESERVED1_5	64
+#define CLKID_RESERVED1_6	65
+#define CLKID_GE2D		66
+#define CLKID_USB0		67
+#define CLKID_USB1		68
+#define CLKID_RESET		69
+#define CLKID_NAND		70
+#define CLKID_HIU_PARSER_TOP	71
+#define CLKID_USB_GENERAL	72
+#define CLKID_RESERVED1_7	73
+#define CLKID_VDIN1		74
+#define CLKID_AHB_ARB0		75
+#define CLKID_EFUSE		76
+#define CLKID_ROM_CLK		77
+#define CLKID_RESERVED2_0	78
+#define CLKID_AHB_DATA_BUS	79
+#define CLKID_AHB_CONTROL_BUS	80
+#define CLKID_HDMI_INTR_SYNC	81
+#define CLKID_HDMI_PCLK		82
+#define CLKID_RESERVED2_1	83
+#define CLKID_RESERVED2_2	84
+#define CLKID_RESERVED2_3	85
+#define CLKID_MISC_USB1_TO_DDR	86
+#define CLKID_MISC_USB0_TO_DDR	87
+#define CLKID_RESERVED2_4	88
+#define CLKID_MMC_PCLK		89
+#define CLKID_MISC_DVIN		90
+#define CLKID_RESERVED2_5	91
+#define CLKID_RESERVED2_6	92
+#define CLKID_UART2		93
+#define CLKID_RESERVED2_7	94
+#define CLKID_RESERVED2_8	95
+#define CLKID_RESERVED2_9	96
+#define CLKID_RESERVED2_A	97
+#define CLKID_RESERVED2_B	98
+#define CLKID_RESERVED2_C	99
+#define CLKID_SANA		100
+#define CLKID_RESERVED2_D	101
+#define CLKID_RESERVED2_E	102
+#define CLKID_VPU_INTR		103
+#define CLKID_SECURE_AHP_APB3	104
+#define CLKID_RESERVED2_F	105
+#define CLKID_RESERVED2_10	106
+#define CLKID_TO_A9		107
+#define CLKID_RESERVED2_11	108
+#define CLKID_RESERVED2_12	109
+#define CLK_NR_CLKS		110
 
 #endif /* __MESON8B_CLKC_H */
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:04 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:04 +0200
Subject: [PATCH v3 01/27] dt-bindings: clock: Add license and reformat
 Exynos5410 clock IDs
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-2-git-send-email-krzk@kernel.org>

Add license and copyrights (file introduced in 2014) to header with
Exynos5410 clock IDs. Additionally reformat it to improve readability.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 include/dt-bindings/clock/exynos5410.h | 54 ++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 9b180f032e2d..213f19e02870 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -1,33 +1,43 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics 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.
+ *
+ * Device Tree binding constants for Exynos5421 clock controller.
+*/
+
 #ifndef _DT_BINDINGS_CLOCK_EXYNOS_5410_H
 #define _DT_BINDINGS_CLOCK_EXYNOS_5410_H
 
 /* core clocks */
-#define CLK_FIN_PLL 1
-#define CLK_FOUT_APLL 2
-#define CLK_FOUT_CPLL 3
-#define CLK_FOUT_MPLL 4
-#define CLK_FOUT_BPLL 5
-#define CLK_FOUT_KPLL 6
+#define CLK_FIN_PLL		1
+#define CLK_FOUT_APLL		2
+#define CLK_FOUT_CPLL		3
+#define CLK_FOUT_MPLL		4
+#define CLK_FOUT_BPLL		5
+#define CLK_FOUT_KPLL		6
 
 /* gate for special clocks (sclk) */
-#define CLK_SCLK_UART0 128
-#define CLK_SCLK_UART1 129
-#define CLK_SCLK_UART2 130
-#define CLK_SCLK_UART3 131
-#define CLK_SCLK_MMC0 132
-#define CLK_SCLK_MMC1 133
-#define CLK_SCLK_MMC2 134
+#define CLK_SCLK_UART0		128
+#define CLK_SCLK_UART1		129
+#define CLK_SCLK_UART2		130
+#define CLK_SCLK_UART3		131
+#define CLK_SCLK_MMC0		132
+#define CLK_SCLK_MMC1		133
+#define CLK_SCLK_MMC2		134
 
 /* gate clocks */
-#define CLK_UART0 257
-#define CLK_UART1 258
-#define CLK_UART2 259
-#define CLK_UART3 260
-#define CLK_MCT 315
-#define CLK_MMC0 351
-#define CLK_MMC1 352
-#define CLK_MMC2 353
+#define CLK_UART0		257
+#define CLK_UART1		258
+#define CLK_UART2		259
+#define CLK_UART3		260
+#define CLK_MCT			315
+#define CLK_MMC0		351
+#define CLK_MMC1		352
+#define CLK_MMC2		353
 
-#define CLK_NR_CLKS 512
+#define CLK_NR_CLKS		512
 
 #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5410_H */
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:05 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:05 +0200
Subject: [PATCH v3 02/27] dt-bindings: clock: Add PWM and USB clock IDs to
 Exynos5410
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-3-git-send-email-krzk@kernel.org>

Add IDs for PWM and USB clocks to Exynos5410. Use the same number as for
Exynos5420 just in case in future these drivers were merged.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 include/dt-bindings/clock/exynos5410.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 213f19e02870..34c8e96987a1 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 Krzysztof Kozlowski
  *
  * 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
@@ -27,16 +28,25 @@
 #define CLK_SCLK_MMC0		132
 #define CLK_SCLK_MMC1		133
 #define CLK_SCLK_MMC2		134
+#define CLK_SCLK_USBD300	150
+#define CLK_SCLK_USBD301	151
+#define CLK_SCLK_USBPHY300	152
+#define CLK_SCLK_USBPHY301	153
+#define CLK_SCLK_PWM		155
 
 /* gate clocks */
 #define CLK_UART0		257
 #define CLK_UART1		258
 #define CLK_UART2		259
 #define CLK_UART3		260
+#define CLK_PWM			279
 #define CLK_MCT			315
 #define CLK_MMC0		351
 #define CLK_MMC1		352
 #define CLK_MMC2		353
+#define CLK_USBH20		365
+#define CLK_USBD300		366
+#define CLK_USBD301		367
 
 #define CLK_NR_CLKS		512
 
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:03 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:03 +0200
Subject: [PATCH v3 00/27] ARM: dts: exynos: Add initial support for Odroid XU
Message-ID: <1462910970-1812-1-git-send-email-krzk@kernel.org>

Hi,

Patchset adds necessary clocks, reorganizes existing stuff and finally
adds Odroid XU support.


Changes since v2
================
1. Got global-ack from Stephen for the clock changes. I think merging
   everything through arm-soc might be the easiest but:
   a. In such case I will prepare a tag with clock changes,
   b. Anyway I will wait for response from Sylwester and Tomasz.
2. Applied comments from Javier and added his Reviewed-by.
3. Patch 22: added ack from Rob.
4. Minor improvements in existing patches.
5. Five new patches at the end: 23-27 (not reviewed yet).
   Some of them could be squashed with existing ones but existing
   changes got reviews. Although the final Odroid XU DTS works fine but
   in general this is still work-in-progress so I suspect it will grow.
   I am releasing it early following Linux concept. :)

Patchset is available at my private repo @github:
https://github.com/krzk/linux.git for-next/odroid-xu-v3

(previous version is in for-next/odroid-xu-v2 branch, if someone would
like to compare them)


Changes since v1
================
1. A lot of new patches.
2. Removed some TODO notes (eMMC 4.5 so no RCLK pin).
3. New clocks, more reorganization.
4. New common DTSI: exynos54xx.dtsi. I know, it is getting more
   and more complicated but this might help removing duplications
   and keeping everything under control.



Merging strategy
================
Complicated! The clock dt-bindings and driver changes can go to clock
tree. However there are three DTS patches in the middle.
a. This has to go in before adding "fin_pll_new" to clock driver:
   - [PATCH v2 03/22] ARM: dts: exynos: Add fin_pll node for clock driver

b. This should go in before renaming "fin_pll_new" back to original name:
   - [PATCH v2 05/22] ARM: dts: exynos: Switch MCT node to a new fin_pll clock
   - [PATCH v2 06/22] ARM: dts: exynos: Remove old fixed-clock provider on SMDK5410

The order of patches in the patchset is really how it should go in
to reduce any bisectability glitches.


Best regards,
Krzysztof


Krzysztof Kozlowski (27):
  dt-bindings: clock: Add license and reformat Exynos5410 clock IDs
  dt-bindings: clock: Add PWM and USB clock IDs to Exynos5410
  ARM: dts: exynos: Add fin_pll node for clock driver
  clk: samsung: exynos5410: Provide fin_pll external fixed clock
  ARM: dts: exynos: Switch MCT node to a new fin_pll clock
  ARM: dts: exynos: Remove old fixed-clock provider on SMDK5410
  clk: samsung: exynos5410: Rename fin_pll from temporary to regular
    name
  clk: samsung: exynos5410: Add serial3, USB and PWM clocks
  ARM: dts: exynos: Re-order alphabetically Exynos5420 SD0/SD1 pinctrl
    nodes
  ARM: dts: exynos: Use lowercase for Exynos5410 CPU node labels
  ARM: dts: exynos: Configure Exynos5410 pinctrl for eMMC and SD card
  ARM: dts: exynos: Split Odroid XU3 LEDs to separate DTSI
  ARM: dts: exynos: Move common nodes to exynos5.dtsi
  ARM: dts: exynos: Prepare for inclusion of exynos5.dtsi in
    exynos5410.dtsi
  ARM: dts: exynos: Use phandle to get parent node in exynos5250-snow
  ARM: dts: exynos: Move Exynos5250 and Exynos5420 nodes under soc
  ARM: dts: exynos: Include common exynos5 in exynos5410.dtsi
  ARM: dts: exynos: Enable UART3 on Exynos5410
  ARM: dts: exynos: MCT is not an interrupt controller and extend length
    of iomap
  ARM: dts: exynos: Move common Exynos5410/542x/5800 nodes to new DTSI
  ARM: dts: exynos: Add USB to Exynos5410
  ARM: dts: exynos: Add initial support for Odroid XU board
  dt-bindings: clock: Add I2C, HSI2C and RTC clock IDs to Exynos5410
  clk: samsung: exynos5410: Add I2C, HSI2C and RTC clocks
  ARM: dts: exynos: Move HSI2C nodes to exynos54xx.dtsi
  ARM: dts: exynos: Add I2C, PWM and UART pinctrl to Exynos5410
  ARM: dts: exynos: Add RTC and I2C to Exynos5410

 .../bindings/arm/samsung/samsung-boards.txt        |    1 +
 arch/arm/boot/dts/Makefile                         |    1 +
 arch/arm/boot/dts/exynos5.dtsi                     |  215 ++-
 arch/arm/boot/dts/exynos5250-snow-common.dtsi      |    2 +-
 arch/arm/boot/dts/exynos5250.dtsi                  | 1701 ++++++++---------
 arch/arm/boot/dts/exynos5410-odroidxu.dts          |  121 ++
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi          |  210 +++
 arch/arm/boot/dts/exynos5410-smdk5410.dts          |   16 +-
 arch/arm/boot/dts/exynos5410.dtsi                  |  270 +--
 arch/arm/boot/dts/exynos5420-pinctrl.dtsi          |   12 +-
 arch/arm/boot/dts/exynos5420.dtsi                  | 1992 +++++++++-----------
 arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts    |   35 +-
 arch/arm/boot/dts/exynos5422-odroidxu3.dts         |   35 +-
 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi    |   50 +
 arch/arm/boot/dts/exynos54xx.dtsi                  |  188 ++
 drivers/clk/samsung/clk-exynos5410.c               |   61 +
 include/dt-bindings/clock/exynos5410.h             |   73 +-
 17 files changed, 2758 insertions(+), 2225 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos5410-odroidxu.dts
 create mode 100644 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
 create mode 100644 arch/arm/boot/dts/exynos54xx.dtsi

-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:06 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:06 +0200
Subject: [PATCH v3 03/27] ARM: dts: exynos: Add fin_pll node for clock driver
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-4-git-send-email-krzk@kernel.org>

For consistency between Exynos5410 and Exynos542x/5800 switch to similar
way of defining fin_pll/oscclk. Add a node early, before implementing
this in driver to preserve bisectability.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410-smdk5410.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts
index 0f6429e1b75c..d7d658deeff4 100644
--- a/arch/arm/boot/dts/exynos5410-smdk5410.dts
+++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts
@@ -31,6 +31,13 @@
 		#clock-cells = <0>;
 	};
 
+	fixed-rate-clocks {
+		oscclk {
+			compatible = "samsung,exynos5420-oscclk";
+			clock-frequency = <24000000>;
+		};
+	};
+
 	firmware at 02037000 {
 		compatible = "samsung,secure-firmware";
 		reg = <0x02037000 0x1000>;
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:07 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:07 +0200
Subject: [PATCH v3 04/27] clk: samsung: exynos5410: Provide fin_pll external
 fixed clock
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-5-git-send-email-krzk@kernel.org>

Just like clock driver for Exynos542x/5800, provide the fixed clock here
so the clock bindings and their consumers would be consistent and
similar.

However a clock named "fin_pll" is already provided by generic
fixed-clock and it is both referenced in the clock driver (by name) and
in DT (by phandle). To make the transition smooth, first introduce the
new external fixed clock here under temporary, different name and switch
internal users to it.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 drivers/clk/samsung/clk-exynos5410.c | 42 +++++++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 13 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index d5d5dcabc4a9..35f2cb36f7ef 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -59,23 +59,29 @@ enum exynos5410_plls {
 };
 
 /* list of all parent clocks */
-PNAME(apll_p)		= { "fin_pll", "fout_apll", };
-PNAME(bpll_p)		= { "fin_pll", "fout_bpll", };
-PNAME(cpll_p)		= { "fin_pll", "fout_cpll" };
-PNAME(mpll_p)		= { "fin_pll", "fout_mpll", };
-PNAME(kpll_p)		= { "fin_pll", "fout_kpll", };
+PNAME(apll_p)		= { "fin_pll_new", "fout_apll", };
+PNAME(bpll_p)		= { "fin_pll_new", "fout_bpll", };
+PNAME(cpll_p)		= { "fin_pll_new", "fout_cpll" };
+PNAME(mpll_p)		= { "fin_pll_new", "fout_mpll", };
+PNAME(kpll_p)		= { "fin_pll_new", "fout_kpll", };
 
 PNAME(mout_cpu_p)	= { "mout_apll", "sclk_mpll", };
 PNAME(mout_kfc_p)	= { "mout_kpll", "sclk_mpll", };
 
-PNAME(mpll_user_p)	= { "fin_pll", "sclk_mpll", };
-PNAME(bpll_user_p)	= { "fin_pll", "sclk_bpll", };
+PNAME(mpll_user_p)	= { "fin_pll_new", "sclk_mpll", };
+PNAME(bpll_user_p)	= { "fin_pll_new", "sclk_bpll", };
 PNAME(mpll_bpll_p)	= { "sclk_mpll_muxed", "sclk_bpll_muxed", };
 
-PNAME(group2_p)		= { "fin_pll", "fin_pll", "none", "none",
+PNAME(group2_p)		= { "fin_pll_new", "fin_pll_new", "none", "none",
 			"none", "none", "sclk_mpll_bpll",
 			 "none", "none", "sclk_cpll" };
 
+/* fixed rate clocks generated outside the soc */
+static struct samsung_fixed_rate_clock
+		exynos5x_fixed_rate_ext_clks[] __initdata = {
+	FRATE(CLK_FIN_PLL, "fin_pll_new", NULL, 0, 0),
+};
+
 static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
 	MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1),
 	MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
@@ -168,18 +174,24 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 };
 
 static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
-	[apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
+	[apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll_new", APLL_LOCK,
 		APLL_CON0, NULL),
-	[cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
+	[cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll_new", CPLL_LOCK,
 		CPLL_CON0, NULL),
-	[mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK,
+	[mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll_new", MPLL_LOCK,
 		MPLL_CON0, NULL),
-	[bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
+	[bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll_new", BPLL_LOCK,
 		BPLL_CON0, NULL),
-	[kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK,
+	[kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll_new", KPLL_LOCK,
 		KPLL_CON0, NULL),
 };
 
+/* Same as in Exynos5420 */
+static const struct of_device_id ext_clk_match[] __initconst = {
+	{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
+	{ },
+};
+
 /* register exynos5410 clocks */
 static void __init exynos5410_clk_init(struct device_node *np)
 {
@@ -192,6 +204,10 @@ static void __init exynos5410_clk_init(struct device_node *np)
 
 	ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
 
+	samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
+			ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
+			ext_clk_match);
+
 	samsung_clk_register_pll(ctx, exynos5410_plls,
 			ARRAY_SIZE(exynos5410_plls), reg_base);
 
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:10 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:10 +0200
Subject: [PATCH v3 07/27] clk: samsung: exynos5410: Rename fin_pll from
 temporary to regular name
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-8-git-send-email-krzk@kernel.org>

For smooth transition of fin_pll to clk-exynos5410.c from fixed-clock
driver, initially it was named "fin_pll_new". Fix this here.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 drivers/clk/samsung/clk-exynos5410.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index 35f2cb36f7ef..a7d714435307 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -59,27 +59,27 @@ enum exynos5410_plls {
 };
 
 /* list of all parent clocks */
-PNAME(apll_p)		= { "fin_pll_new", "fout_apll", };
-PNAME(bpll_p)		= { "fin_pll_new", "fout_bpll", };
-PNAME(cpll_p)		= { "fin_pll_new", "fout_cpll" };
-PNAME(mpll_p)		= { "fin_pll_new", "fout_mpll", };
-PNAME(kpll_p)		= { "fin_pll_new", "fout_kpll", };
+PNAME(apll_p)		= { "fin_pll", "fout_apll", };
+PNAME(bpll_p)		= { "fin_pll", "fout_bpll", };
+PNAME(cpll_p)		= { "fin_pll", "fout_cpll" };
+PNAME(mpll_p)		= { "fin_pll", "fout_mpll", };
+PNAME(kpll_p)		= { "fin_pll", "fout_kpll", };
 
 PNAME(mout_cpu_p)	= { "mout_apll", "sclk_mpll", };
 PNAME(mout_kfc_p)	= { "mout_kpll", "sclk_mpll", };
 
-PNAME(mpll_user_p)	= { "fin_pll_new", "sclk_mpll", };
-PNAME(bpll_user_p)	= { "fin_pll_new", "sclk_bpll", };
+PNAME(mpll_user_p)	= { "fin_pll", "sclk_mpll", };
+PNAME(bpll_user_p)	= { "fin_pll", "sclk_bpll", };
 PNAME(mpll_bpll_p)	= { "sclk_mpll_muxed", "sclk_bpll_muxed", };
 
-PNAME(group2_p)		= { "fin_pll_new", "fin_pll_new", "none", "none",
+PNAME(group2_p)		= { "fin_pll", "fin_pll", "none", "none",
 			"none", "none", "sclk_mpll_bpll",
 			 "none", "none", "sclk_cpll" };
 
 /* fixed rate clocks generated outside the soc */
 static struct samsung_fixed_rate_clock
 		exynos5x_fixed_rate_ext_clks[] __initdata = {
-	FRATE(CLK_FIN_PLL, "fin_pll_new", NULL, 0, 0),
+	FRATE(CLK_FIN_PLL, "fin_pll", NULL, 0, 0),
 };
 
 static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
@@ -174,15 +174,15 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 };
 
 static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
-	[apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll_new", APLL_LOCK,
+	[apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
 		APLL_CON0, NULL),
-	[cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll_new", CPLL_LOCK,
+	[cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
 		CPLL_CON0, NULL),
-	[mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll_new", MPLL_LOCK,
+	[mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK,
 		MPLL_CON0, NULL),
-	[bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll_new", BPLL_LOCK,
+	[bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
 		BPLL_CON0, NULL),
-	[kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll_new", KPLL_LOCK,
+	[kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK,
 		KPLL_CON0, NULL),
 };
 
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:15 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:15 +0200
Subject: [PATCH v3 12/27] ARM: dts: exynos: Split Odroid XU3 LEDs to separate
 DTSI
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-13-git-send-email-krzk@kernel.org>

The LED nodes can be shared between Odroid XU3, XU3-Lite and XU (not yet
added) thus removing duplication.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts | 35 +----------------
 arch/arm/boot/dts/exynos5422-odroidxu3.dts      | 35 +----------------
 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi | 50 +++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 68 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi

diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
index 2ae1cf41dcb6..03fa88c45426 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
@@ -14,44 +14,11 @@
 /dts-v1/;
 #include "exynos5422-odroidxu3-common.dtsi"
 #include "exynos5422-odroidxu3-audio.dtsi"
+#include "exynos54xx-odroidxu-leds.dtsi"
 
 / {
 	model = "Hardkernel Odroid XU3 Lite";
 	compatible = "hardkernel,odroid-xu3-lite", "samsung,exynos5800", "samsung,exynos5";
-
-	pwmleds {
-		compatible = "pwm-leds";
-
-		greenled {
-			label = "green:mmc0";
-			pwms = <&pwm 1 2000000 0>;
-			pwm-names = "pwm1";
-			/*
-			 * Green LED is much brighter than the others
-			 * so limit its max brightness
-			 */
-			max_brightness = <127>;
-			linux,default-trigger = "mmc0";
-		};
-
-		blueled {
-			label = "blue:heartbeat";
-			pwms = <&pwm 2 2000000 0>;
-			pwm-names = "pwm2";
-			max_brightness = <255>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-
-	gpioleds {
-		compatible = "gpio-leds";
-		redled {
-			label = "red:microSD";
-			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
-			default-state = "off";
-			linux,default-trigger = "mmc1";
-		};
-	};
 };
 
 &pwm {
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
index 432406db85de..9ed6564acfb0 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
@@ -13,44 +13,11 @@
 /dts-v1/;
 #include "exynos5422-odroidxu3-common.dtsi"
 #include "exynos5422-odroidxu3-audio.dtsi"
+#include "exynos54xx-odroidxu-leds.dtsi"
 
 / {
 	model = "Hardkernel Odroid XU3";
 	compatible = "hardkernel,odroid-xu3", "samsung,exynos5800", "samsung,exynos5";
-
-	pwmleds {
-		compatible = "pwm-leds";
-
-		greenled {
-			label = "green:mmc0";
-			pwms = <&pwm 1 2000000 0>;
-			pwm-names = "pwm1";
-			/*
-			 * Green LED is much brighter than the others
-			 * so limit its max brightness
-			 */
-			max_brightness = <127>;
-			linux,default-trigger = "mmc0";
-		};
-
-		blueled {
-			label = "blue:heartbeat";
-			pwms = <&pwm 2 2000000 0>;
-			pwm-names = "pwm2";
-			max_brightness = <255>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-
-	gpioleds {
-		compatible = "gpio-leds";
-		redled {
-			label = "red:microSD";
-			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
-			default-state = "off";
-			linux,default-trigger = "mmc1";
-		};
-	};
 };
 
 &i2c_0 {
diff --git a/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi b/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
new file mode 100644
index 000000000000..0ed30206625c
--- /dev/null
+++ b/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
@@ -0,0 +1,50 @@
+/*
+ * Hardkernel Odroid XU/XU3 LED device tree source
+ *
+ * Copyright (c) 2015,2016 Krzysztof Kozlowski
+ * Copyright (c) 2014 Collabora Ltd.
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	pwmleds {
+		compatible = "pwm-leds";
+
+		greenled {
+			label = "green:mmc0";
+			pwms = <&pwm 1 2000000 0>;
+			pwm-names = "pwm1";
+			/*
+			 * Green LED is much brighter than the others
+			 * so limit its max brightness
+			 */
+			max_brightness = <127>;
+			linux,default-trigger = "mmc0";
+		};
+
+		blueled {
+			label = "blue:heartbeat";
+			pwms = <&pwm 2 2000000 0>;
+			pwm-names = "pwm2";
+			max_brightness = <255>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	gpioleds {
+		compatible = "gpio-leds";
+		redled {
+			label = "red:microSD";
+			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "mmc1";
+		};
+	};
+};
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:17 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:17 +0200
Subject: [PATCH v3 14/27] ARM: dts: exynos: Prepare for inclusion of
 exynos5.dtsi in exynos5410.dtsi
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-15-git-send-email-krzk@kernel.org>

Add 'sromc' label to SROM memory controller in common exynos5.dtsi so it
can be referenced by inheriting DTSI.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index c5d198c70b86..30a0b63b06c9 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -35,7 +35,7 @@
 		reg = <0x10000000 0x100>;
 	};
 
-	memory-controller at 12250000 {
+	sromc: memory-controller at 12250000 {
 		compatible = "samsung,exynos4210-srom";
 		reg = <0x12250000 0x14>;
 	};
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:21 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:21 +0200
Subject: [PATCH v3 18/27] ARM: dts: exynos: Enable UART3 on Exynos5410
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-19-git-send-email-krzk@kernel.org>

Just like other Exynos5 family SoCs, this one has four UARTs. Configure
clocks for UART3 and enable it.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index c0540eb76271..62dc3b4aef93 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -215,7 +215,8 @@
 };
 
 &serial_3 {
-	status = "disabled";
+	clocks = <&clock CLK_UART3>, <&clock CLK_SCLK_UART3>;
+	clock-names = "uart", "clk_uart_baud0";
 };
 
 &sromc {
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:16 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:16 +0200
Subject: [PATCH v3 13/27] ARM: dts: exynos: Move common nodes to exynos5.dtsi
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-14-git-send-email-krzk@kernel.org>

Exynos5420 and Exynos5250 share some nodes: the PWM, syscon
(sysreg_system_controller) and first four I2C controllers. Move them to
parent DTSI to avoid duplication.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

Important changes since v2:
1. Move also i2c[0123] to exynos5.dtsi.
---
 arch/arm/boot/dts/exynos5.dtsi    |  56 ++++++++++++++++++++
 arch/arm/boot/dts/exynos5250.dtsi | 108 ++++++++++++--------------------------
 arch/arm/boot/dts/exynos5420.dtsi | 108 ++++++++++++--------------------------
 3 files changed, 124 insertions(+), 148 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index d5c0f18a4223..c5d198c70b86 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -20,6 +20,10 @@
 	interrupt-parent = <&gic>;
 
 	aliases {
+		i2c0 = &i2c_0;
+		i2c1 = &i2c_1;
+		i2c2 = &i2c_2;
+		i2c3 = &i2c_3;
 		serial0 = &serial_0;
 		serial1 = &serial_1;
 		serial2 = &serial_2;
@@ -63,6 +67,11 @@
 		interrupts = <1 9 0xf04>;
 	};
 
+	sysreg_system_controller: syscon at 10050000 {
+		compatible = "samsung,exynos5-sysreg", "syscon";
+		reg = <0x10050000 0x5000>;
+	};
+
 	serial_0: serial at 12C00000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C00000 0x100>;
@@ -87,6 +96,53 @@
 		interrupts = <0 54 0>;
 	};
 
+	i2c_0: i2c at 12C60000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C60000 0x100>;
+		interrupts = <0 56 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,sysreg-phandle = <&sysreg_system_controller>;
+		status = "disabled";
+	};
+
+	i2c_1: i2c at 12C70000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C70000 0x100>;
+		interrupts = <0 57 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,sysreg-phandle = <&sysreg_system_controller>;
+		status = "disabled";
+	};
+
+	i2c_2: i2c at 12C80000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C80000 0x100>;
+		interrupts = <0 58 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,sysreg-phandle = <&sysreg_system_controller>;
+		status = "disabled";
+	};
+
+	i2c_3: i2c at 12C90000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C90000 0x100>;
+		interrupts = <0 59 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,sysreg-phandle = <&sysreg_system_controller>;
+		status = "disabled";
+	};
+
+	pwm: pwm at 12DD0000 {
+		compatible = "samsung,exynos4210-pwm";
+		reg = <0x12DD0000 0x100>;
+		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
+		#pwm-cells = <3>;
+	};
+
 	rtc: rtc at 101E0000 {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x101E0000 0x100>;
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index c7158b2fb213..ae4970d1c74f 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -37,10 +37,6 @@
 		mshc1 = &mmc_1;
 		mshc2 = &mmc_2;
 		mshc3 = &mmc_3;
-		i2c0 = &i2c_0;
-		i2c1 = &i2c_1;
-		i2c2 = &i2c_2;
-		i2c3 = &i2c_3;
 		i2c4 = &i2c_4;
 		i2c5 = &i2c_5;
 		i2c6 = &i2c_6;
@@ -235,11 +231,6 @@
 		interrupt-parent = <&gic>;
 	};
 
-	sysreg_system_controller: syscon at 10050000 {
-		compatible = "samsung,exynos5-sysreg", "syscon";
-		reg = <0x10050000 0x5000>;
-	};
-
 	watchdog at 101D0000 {
 		compatible = "samsung,exynos5250-wdt";
 		reg = <0x101D0000 0x100>;
@@ -328,62 +319,7 @@
 		status = "disabled";
 	};
 
-	i2c_0: i2c at 12C60000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C60000 0x100>;
-		interrupts = <0 56 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C0>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c0_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_1: i2c at 12C70000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C70000 0x100>;
-		interrupts = <0 57 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C1>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c1_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_2: i2c at 12C80000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C80000 0x100>;
-		interrupts = <0 58 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C2>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c2_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_3: i2c at 12C90000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C90000 0x100>;
-		interrupts = <0 59 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C3>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c3_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
+	/* i2c_0-3 are defined in exynos5.dtsi */
 	i2c_4: i2c at 12CA0000 {
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x12CA0000 0x100>;
@@ -662,15 +598,6 @@
 		samsung,pmureg-phandle = <&pmu_system_controller>;
 	};
 
-	pwm: pwm at 12dd0000 {
-		compatible = "samsung,exynos4210-pwm";
-		reg = <0x12dd0000 0x100>;
-		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
-		#pwm-cells = <3>;
-		clocks = <&clock CLK_PWM>;
-		clock-names = "timers";
-	};
-
 	amba {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -1070,6 +997,39 @@
 	iommus = <&sysmmu_fimd1>;
 };
 
+&i2c_0 {
+	clocks = <&clock CLK_I2C0>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_bus>;
+};
+
+&i2c_1 {
+	clocks = <&clock CLK_I2C1>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_bus>;
+};
+
+&i2c_2 {
+	clocks = <&clock CLK_I2C2>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_bus>;
+};
+
+&i2c_3 {
+	clocks = <&clock CLK_I2C3>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_bus>;
+};
+
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
+
 &rtc {
 	clocks = <&clock CLK_RTC>;
 	clock-names = "rtc";
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 549ebf23fee0..f2e8e6482888 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -30,10 +30,6 @@
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
 		pinctrl4 = &pinctrl_4;
-		i2c0 = &i2c_0;
-		i2c1 = &i2c_1;
-		i2c2 = &i2c_2;
-		i2c3 = &i2c_3;
 		i2c4 = &hsi2c_4;
 		i2c5 = &hsi2c_5;
 		i2c6 = &hsi2c_6;
@@ -542,15 +538,6 @@
 		status = "disabled";
 	};
 
-	pwm: pwm at 12dd0000 {
-		compatible = "samsung,exynos4210-pwm";
-		reg = <0x12dd0000 0x100>;
-		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
-		#pwm-cells = <3>;
-		clocks = <&clock CLK_PWM>;
-		clock-names = "timers";
-	};
-
 	dp_phy: dp-video-phy {
 		compatible = "samsung,exynos5420-dp-video-phy";
 		samsung,pmu-syscon = <&pmu_system_controller>;
@@ -588,62 +575,7 @@
 		status = "disabled";
 	};
 
-	i2c_0: i2c at 12C60000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C60000 0x100>;
-		interrupts = <0 56 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C0>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c0_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_1: i2c at 12C70000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C70000 0x100>;
-		interrupts = <0 57 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C1>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c1_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_2: i2c at 12C80000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C80000 0x100>;
-		interrupts = <0 58 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C2>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c2_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_3: i2c at 12C90000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C90000 0x100>;
-		interrupts = <0 59 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C3>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c3_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
+	/* i2c_0-3 are defined in exynos5.dtsi */
 	hsi2c_4: i2c at 12CA0000 {
 		compatible = "samsung,exynos5250-hsi2c";
 		reg = <0x12CA0000 0x1000>;
@@ -823,11 +755,6 @@
 		interrupt-parent = <&gic>;
 	};
 
-	sysreg_system_controller: syscon at 10050000 {
-		compatible = "samsung,exynos5-sysreg", "syscon";
-		reg = <0x10050000 0x5000>;
-	};
-
 	tmu_cpu0: tmu at 10060000 {
 		compatible = "samsung,exynos5420-tmu";
 		reg = <0x10060000 0x100>;
@@ -1207,6 +1134,39 @@
 	iommu-names = "m0", "m1";
 };
 
+&i2c_0 {
+	clocks = <&clock CLK_I2C0>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_bus>;
+};
+
+&i2c_1 {
+	clocks = <&clock CLK_I2C1>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_bus>;
+};
+
+&i2c_2 {
+	clocks = <&clock CLK_I2C2>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_bus>;
+};
+
+&i2c_3 {
+	clocks = <&clock CLK_I2C3>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_bus>;
+};
+
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
+
 &rtc {
 	clocks = <&clock CLK_RTC>;
 	clock-names = "rtc";
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:18 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:18 +0200
Subject: [PATCH v3 15/27] ARM: dts: exynos: Use phandle to get parent node in
 exynos5250-snow
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-16-git-send-email-krzk@kernel.org>

The i2c-arbitrator node in exynos5250-snow-common used absolute path to
reference other node (the i2c parent). Use phandle instead, because the
depth of the other node may be changed (like moving it under 'soc'
node).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5250-snow-common.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5250-snow-common.dtsi b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
index ddfe1f558c10..419d59da1751 100644
--- a/arch/arm/boot/dts/exynos5250-snow-common.dtsi
+++ b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
@@ -61,7 +61,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		i2c-parent = <&{/i2c at 12CA0000}>;
+		i2c-parent = <&i2c_4>;
 
 		our-claim-gpio = <&gpf0 3 GPIO_ACTIVE_LOW>;
 		their-claim-gpios = <&gpe0 4 GPIO_ACTIVE_LOW>;
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:08 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:08 +0200
Subject: [PATCH v3 05/27] ARM: dts: exynos: Switch MCT node to a new fin_pll
 clock
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-6-git-send-email-krzk@kernel.org>

The clk-exynos5410 driver now provides the "fin_pll" external fixed
clock. Switch the Multi-Core Timer to this clock.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 7a56aec2c5ba..233149abfb62 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -125,7 +125,7 @@
 			interrupts = <0>, <1>, <2>, <3>,
 				<4>, <5>, <6>, <7>,
 				<8>, <9>, <10>, <11>;
-			clocks = <&fin_pll>, <&clock CLK_MCT>;
+			clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
 			clock-names = "fin_pll", "mct";
 
 			interrupt_map: interrupt-map {
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:12 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:12 +0200
Subject: [PATCH v3 09/27] ARM: dts: exynos: Re-order alphabetically Exynos5420
 SD0/SD1 pinctrl nodes
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-10-git-send-email-krzk@kernel.org>

The 'sd0_rclk' was put in the middle of SD1 nodes. Remove the confusion.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
index 130563b2ca95..14beb7e07323 100644
--- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
@@ -193,17 +193,17 @@
 		samsung,pin-drv = <3>;
 	};
 
-	sd1_clk: sd1-clk {
-		samsung,pins = "gpc1-0";
+	sd0_rclk: sd0-rclk {
+		samsung,pins = "gpc0-7";
 		samsung,pin-function = <2>;
-		samsung,pin-pud = <0>;
+		samsung,pin-pud = <1>;
 		samsung,pin-drv = <3>;
 	};
 
-	sd0_rclk: sd0-rclk {
-		samsung,pins = "gpc0-7";
+	sd1_clk: sd1-clk {
+		samsung,pins = "gpc1-0";
 		samsung,pin-function = <2>;
-		samsung,pin-pud = <1>;
+		samsung,pin-pud = <0>;
 		samsung,pin-drv = <3>;
 	};
 
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:13 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:13 +0200
Subject: [PATCH v3 10/27] ARM: dts: exynos: Use lowercase for Exynos5410 CPU
 node labels
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-11-git-send-email-krzk@kernel.org>

For consistency lowercase node labels are used.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 233149abfb62..58d3844ef923 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -35,28 +35,28 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		CPU0: cpu at 0 {
+		cpu0: cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU1: cpu at 1 {
+		cpu1: cpu at 1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x1>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU2: cpu at 2 {
+		cpu2: cpu at 2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x2>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU3: cpu at 3 {
+		cpu3: cpu at 3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x3>;
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:11 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:11 +0200
Subject: [PATCH v3 08/27] clk: samsung: exynos5410: Add serial3,
 USB and PWM clocks
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-9-git-send-email-krzk@kernel.org>

Just like other Exynos5 family SoCs, this one has four UARTs. Add
missing UART3 clocks to the Exynos5410 clock driver.

Add clocks for USB and PWM.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 drivers/clk/samsung/clk-exynos5410.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index a7d714435307..40775f678f02 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -33,9 +33,11 @@
 #define SRC_CPERI1		0x4204
 #define DIV_TOP0		0x10510
 #define DIV_TOP1		0x10514
+#define DIV_FSYS0		0x10548
 #define DIV_FSYS1		0x1054c
 #define DIV_FSYS2		0x10550
 #define DIV_PERIC0		0x10558
+#define DIV_PERIC3		0x10564
 #define SRC_TOP0		0x10210
 #define SRC_TOP1		0x10214
 #define SRC_TOP2		0x10218
@@ -44,6 +46,8 @@
 #define SRC_MASK_FSYS		0x10340
 #define SRC_MASK_PERIC0		0x10350
 #define GATE_BUS_FSYS0		0x10740
+#define GATE_TOP_SCLK_FSYS	0x10840
+#define GATE_TOP_SCLK_PERIC	0x10850
 #define GATE_IP_FSYS		0x10944
 #define GATE_IP_PERIC		0x10950
 #define GATE_IP_PERIS		0x10960
@@ -71,6 +75,7 @@ PNAME(mout_kfc_p)	= { "mout_kpll", "sclk_mpll", };
 PNAME(mpll_user_p)	= { "fin_pll", "sclk_mpll", };
 PNAME(bpll_user_p)	= { "fin_pll", "sclk_bpll", };
 PNAME(mpll_bpll_p)	= { "sclk_mpll_muxed", "sclk_bpll_muxed", };
+PNAME(sclk_mpll_bpll_p)	= { "sclk_mpll_bpll", "fin_pll", };
 
 PNAME(group2_p)		= { "fin_pll", "fin_pll", "none", "none",
 			"none", "none", "sclk_mpll_bpll",
@@ -102,10 +107,14 @@ static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
 	MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4),
 	MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4),
 	MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4),
+	MUX(0, "mout_usbd300", sclk_mpll_bpll_p, SRC_FSYS, 28, 1),
+	MUX(0, "mout_usbd301", sclk_mpll_bpll_p, SRC_FSYS, 29, 1),
 
 	MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4),
 	MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4),
 	MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4),
+	MUX(0, "mout_uart3", group2_p, SRC_PERIC0, 12, 4),
+	MUX(0, "mout_pwm", group2_p, SRC_PERIC0, 24, 4),
 
 	MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1),
 	MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1),
@@ -127,6 +136,11 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 	DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3),
 	DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
 
+	DIV(0, "dout_usbphy300", "mout_usbd300", DIV_FSYS0, 16, 4),
+	DIV(0, "dout_usbphy301", "mout_usbd301", DIV_FSYS0, 20, 4),
+	DIV(0, "dout_usbd300", "mout_usbd300", DIV_FSYS0, 24, 4),
+	DIV(0, "dout_usbd301", "mout_usbd301", DIV_FSYS0, 28, 4),
+
 	DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
 	DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
 	DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
@@ -143,6 +157,8 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 	DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
 	DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
 
+	DIV(0, "dout_pwm", "mout_pwm", DIV_PERIC3, 0, 4),
+
 	DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
 	DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3),
 };
@@ -161,9 +177,23 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 	GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0),
 	GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0),
 
+	GATE(CLK_SCLK_USBPHY301, "sclk_usbphy301", "dout_usbphy301",
+	     GATE_TOP_SCLK_FSYS, 7, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_USBPHY300, "sclk_usbphy300", "dout_usbphy300",
+	     GATE_TOP_SCLK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_USBD300, "sclk_usbd300", "dout_usbd300",
+	     GATE_TOP_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_USBD301, "sclk_usbd301", "dout_usbd301",
+	     GATE_TOP_SCLK_FSYS, 10, CLK_SET_RATE_PARENT, 0),
+
+	GATE(CLK_SCLK_PWM, "sclk_pwm", "dout_pwm",
+	     GATE_TOP_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0),
+
 	GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
 	GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
 	GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
+	GATE(CLK_UART3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0),
+	GATE(CLK_PWM, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0),
 
 	GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
 			SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
@@ -171,6 +201,12 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 			SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
 			SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_UART3, "sclk_uart3", "div_uart3",
+			SRC_MASK_PERIC0, 12, CLK_SET_RATE_PARENT, 0),
+
+	GATE(CLK_USBH20, "usbh20", "aclk200_fsys", GATE_IP_FSYS, 18, 0, 0),
+	GATE(CLK_USBD300, "usbd300", "aclk200_fsys", GATE_IP_FSYS, 19, 0, 0),
+	GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_IP_FSYS, 20, 0, 0),
 };
 
 static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:14 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:14 +0200
Subject: [PATCH v3 11/27] ARM: dts: exynos: Configure Exynos5410 pinctrl for
 eMMC and SD card
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-12-git-send-email-krzk@kernel.org>

Configure the pinctrl for MMC0 (eMMC) and MMC2 (microSD card).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

Important changes since v2:
1. Re-order the eMMC pins by pin-name, not by label.
---
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 77 +++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
index f9aa6bb55464..ddacafa1e907 100644
--- a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
@@ -277,6 +277,83 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
+
+	sd0_clk: sd0-clk {
+		samsung,pins = "gpc0-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cmd: sd0-cmd {
+		samsung,pins = "gpc0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cd: sd0-cd {
+		samsung,pins = "gpc0-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus1: sd0-bus-width1 {
+		samsung,pins = "gpc0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus4: sd0-bus-width4 {
+		samsung,pins = "gpc0-4", "gpc0-5", "gpc0-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_clk: sd2-clk {
+		samsung,pins = "gpc2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cmd: sd2-cmd {
+		samsung,pins = "gpc2-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cd: sd2-cd {
+		samsung,pins = "gpc2-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus1: sd2-bus-width1 {
+		samsung,pins = "gpc2-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus4: sd2-bus-width4 {
+		samsung,pins = "gpc2-4", "gpc2-5", "gpc2-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus8: sd0-bus-width8 {
+		samsung,pins = "gpc3-0", "gpc3-1", "gpc3-2", "gpc3-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
 };
 
 &pinctrl_1 {
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:23 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:23 +0200
Subject: [PATCH v3 20/27] ARM: dts: exynos: Move common Exynos5410/542x/5800
 nodes to new DTSI
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-21-git-send-email-krzk@kernel.org>

The Exynos5410/542x/5800 are very similar designs. Create a new
DTSI with common nodes to remove DTS duplication. Although currently
only MCT and SysRAM are shared but in future more nodes will be added to
the common file.

The patch should not have functional impact.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 55 ++++---------------------------
 arch/arm/boot/dts/exynos5420.dtsi | 54 ++++---------------------------
 arch/arm/boot/dts/exynos54xx.dtsi | 68 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+), 97 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos54xx.dtsi

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 62dc3b4aef93..850343d3c2af 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -13,8 +13,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "skeleton.dtsi"
-#include "exynos5.dtsi"
+#include "exynos54xx.dtsi"
 #include "exynos-syscon-restart.dtsi"
 #include <dt-bindings/clock/exynos5410.h>
 
@@ -73,53 +72,6 @@
 			reg = <0x10040000 0x5000>;
 		};
 
-		mct: mct at 101C0000 {
-			compatible = "samsung,exynos4210-mct";
-			reg = <0x101C0000 0xB00>;
-			interrupt-parent = <&interrupt_map>;
-			interrupts = <0>, <1>, <2>, <3>,
-				<4>, <5>, <6>, <7>,
-				<8>, <9>, <10>, <11>;
-			clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
-			clock-names = "fin_pll", "mct";
-
-			interrupt_map: interrupt-map {
-				#interrupt-cells = <1>;
-				#address-cells = <0>;
-				#size-cells = <0>;
-				interrupt-map = <0 &combiner 23 3>,
-						<1 &combiner 23 4>,
-						<2 &combiner 25 2>,
-						<3 &combiner 25 3>,
-						<4 &gic 0 120 0>,
-						<5 &gic 0 121 0>,
-						<6 &gic 0 122 0>,
-						<7 &gic 0 123 0>,
-						<8 &gic 0 128 0>,
-						<9 &gic 0 129 0>,
-						<10 &gic 0 130 0>,
-						<11 &gic 0 131 0>;
-			};
-		};
-
-		sysram at 02020000 {
-			compatible = "mmio-sram";
-			reg = <0x02020000 0x54000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x02020000 0x54000>;
-
-			smp-sysram at 0 {
-				compatible = "samsung,exynos4210-sysram";
-				reg = <0x0 0x1000>;
-			};
-
-			smp-sysram at 53000 {
-				compatible = "samsung,exynos4210-sysram-ns";
-				reg = <0x53000 0x1000>;
-			};
-		};
-
 		clock: clock-controller at 10010000 {
 			compatible = "samsung,exynos5410-clock";
 			reg = <0x10010000 0x30000>;
@@ -194,6 +146,11 @@
 	};
 };
 
+&mct {
+	clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
+	clock-names = "fin_pll", "mct";
+};
+
 &pwm {
 	clocks = <&clock CLK_PWM>;
 	clock-names = "timers";
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 872dadf0f2d4..ebf2ed3c5ff8 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -13,9 +13,8 @@
  * published by the Free Software Foundation.
  */
 
+#include "exynos54xx.dtsi"
 #include <dt-bindings/clock/exynos5420.h>
-#include "exynos5.dtsi"
-
 #include <dt-bindings/clock/exynos-audss-clk.h>
 
 / {
@@ -181,24 +180,6 @@
 			};
 		};
 
-		sysram at 02020000 {
-			compatible = "mmio-sram";
-			reg = <0x02020000 0x54000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x02020000 0x54000>;
-
-			smp-sysram at 0 {
-				compatible = "samsung,exynos4210-sysram";
-				reg = <0x0 0x1000>;
-			};
-
-			smp-sysram at 53000 {
-				compatible = "samsung,exynos4210-sysram-ns";
-				reg = <0x53000 0x1000>;
-			};
-		};
-
 		clock: clock-controller at 10010000 {
 			compatible = "samsung,exynos5420-clock";
 			reg = <0x10010000 0x30000>;
@@ -261,34 +242,6 @@
 			status = "disabled";
 		};
 
-		mct: mct at 101C0000 {
-			compatible = "samsung,exynos4210-mct";
-			reg = <0x101C0000 0xB00>;
-			interrupt-parent = <&mct_map>;
-			interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
-					<8>, <9>, <10>, <11>;
-			clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
-			clock-names = "fin_pll", "mct";
-
-			mct_map: mct-map {
-				#interrupt-cells = <1>;
-				#address-cells = <0>;
-				#size-cells = <0>;
-				interrupt-map = <0 &combiner 23 3>,
-						<1 &combiner 23 4>,
-						<2 &combiner 25 2>,
-						<3 &combiner 25 3>,
-						<4 &gic 0 120 0>,
-						<5 &gic 0 121 0>,
-						<6 &gic 0 122 0>,
-						<7 &gic 0 123 0>,
-						<8 &gic 0 128 0>,
-						<9 &gic 0 129 0>,
-						<10 &gic 0 130 0>,
-						<11 &gic 0 131 0>;
-			};
-		};
-
 		gsc_pd: power-domain at 10044000 {
 			compatible = "samsung,exynos4210-pd";
 			reg = <0x10044000 0x20>;
@@ -1163,6 +1116,11 @@
 	pinctrl-0 = <&i2c3_bus>;
 };
 
+&mct {
+	clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
+	clock-names = "fin_pll", "mct";
+};
+
 &pwm {
 	clocks = <&clock CLK_PWM>;
 	clock-names = "timers";
diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi
new file mode 100644
index 000000000000..9ce625bd79c1
--- /dev/null
+++ b/arch/arm/boot/dts/exynos54xx.dtsi
@@ -0,0 +1,68 @@
+/*
+ * Samsung's Exynos54xx SoC series common device tree source
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2016 Krzysztof Kozlowski
+ *
+ * Device nodes common for Samsung Exynos5410/5420/5422/5800. Specific
+ * Exynos 54xx SoCs should include this file and customize it further
+ * (e.g. with clocks).
+ *
+ * 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 "skeleton.dtsi"
+#include "exynos5.dtsi"
+
+/ {
+	compatible = "samsung,exynos5";
+
+	soc: soc {
+		sysram at 02020000 {
+			compatible = "mmio-sram";
+			reg = <0x02020000 0x54000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x02020000 0x54000>;
+
+			smp-sysram at 0 {
+				compatible = "samsung,exynos4210-sysram";
+				reg = <0x0 0x1000>;
+			};
+
+			smp-sysram at 53000 {
+				compatible = "samsung,exynos4210-sysram-ns";
+				reg = <0x53000 0x1000>;
+			};
+		};
+
+		mct: mct at 101C0000 {
+			compatible = "samsung,exynos4210-mct";
+			reg = <0x101C0000 0xB00>;
+			interrupt-parent = <&mct_map>;
+			interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
+					<8>, <9>, <10>, <11>;
+
+			mct_map: mct-map {
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = <0 &combiner 23 3>,
+						<1 &combiner 23 4>,
+						<2 &combiner 25 2>,
+						<3 &combiner 25 3>,
+						<4 &gic 0 120 0>,
+						<5 &gic 0 121 0>,
+						<6 &gic 0 122 0>,
+						<7 &gic 0 123 0>,
+						<8 &gic 0 128 0>,
+						<9 &gic 0 129 0>,
+						<10 &gic 0 130 0>,
+						<11 &gic 0 131 0>;
+			};
+		};
+	};
+};
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:25 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:25 +0200
Subject: [PATCH v3 22/27] ARM: dts: exynos: Add initial support for Odroid XU
 board
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-23-git-send-email-krzk@kernel.org>

The Hardkernel's Odroid XU board was first design with big.LITTLE SoC
from Samsung: the Exynos5410. Comparing the board to more popular now
Odroid XU3, the differences are:
1. Exynos5410 instead of 5422,
2. MIPI DSI LCD connector,
3. Main PMIC: Maxim 77802 instead of S2MPS11,
4. USB3503+LAN9730 instead of integrated LAN9514,
5. eMMC 4.5 instead of eMMC 5.0,

This patch adds initial support for the XU board with working basic
functions, eMMC/SD and USB (including attached ethernet adapter).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Rob Herring <robh at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 .../bindings/arm/samsung/samsung-boards.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/exynos5410-odroidxu.dts          | 121 +++++++++++++++++++++
 3 files changed, 123 insertions(+)
 create mode 100644 arch/arm/boot/dts/exynos5410-odroidxu.dts

diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
index f5deace2b380..0ea7f14ef294 100644
--- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
+++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
@@ -47,6 +47,7 @@ Required root node properties:
 	- "hardkernel,odroid-u3"  - for Exynos4412-based Hardkernel Odroid U3.
 	- "hardkernel,odroid-x"   - for Exynos4412-based Hardkernel Odroid X.
 	- "hardkernel,odroid-x2"  - for Exynos4412-based Hardkernel Odroid X2.
+	- "hardkernel,odroid-xu"  - for Exynos5410-based Hardkernel Odroid XU.
 	- "hardkernel,odroid-xu3" - for Exynos5422-based Hardkernel Odroid XU3.
 	- "hardkernel,odroid-xu3-lite" - for Exynos5422-based Hardkernel
 					 Odroid XU3 Lite board.
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 5aeb10674370..9ed1c7abedb1 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -134,6 +134,7 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \
 	exynos5250-snow-rev5.dtb \
 	exynos5250-spring.dtb \
 	exynos5260-xyref5260.dtb \
+	exynos5410-odroidxu.dtb \
 	exynos5410-smdk5410.dtb \
 	exynos5420-arndale-octa.dtb \
 	exynos5420-peach-pit.dtb \
diff --git a/arch/arm/boot/dts/exynos5410-odroidxu.dts b/arch/arm/boot/dts/exynos5410-odroidxu.dts
new file mode 100644
index 000000000000..44ba00a6636f
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5410-odroidxu.dts
@@ -0,0 +1,121 @@
+/*
+ * Hardkernel Odroid XU board device tree source
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2016 Krzysztof Kozlowski
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include "exynos5410.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "exynos54xx-odroidxu-leds.dtsi"
+
+/ {
+	model = "Hardkernel Odroid XU";
+	compatible = "hardkernel,odroid-xu", "samsung,exynos5410", "samsung,exynos5";
+
+	memory {
+		reg = <0x40000000 0x7ea00000>;
+	};
+
+	chosen {
+		linux,stdout-path = &serial_2;
+	};
+
+	emmc_pwrseq: pwrseq {
+		pinctrl-0 = <&emmc_nrst_pin>;
+		pinctrl-names = "default";
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpd1 0 GPIO_ACTIVE_LOW>;
+	};
+
+	fan0: pwm-fan {
+		compatible = "pwm-fan";
+		pwms = <&pwm 0 20972 0>;
+		cooling-min-state = <0>;
+		cooling-max-state = <3>;
+		#cooling-cells = <2>;
+		cooling-levels = <0 130 170 230>;
+	};
+
+	fixed-rate-clocks {
+		oscclk {
+			compatible = "samsung,exynos5420-oscclk";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	firmware at 02073000 {
+		compatible = "samsung,secure-firmware";
+		reg = <0x02073000 0x1000>;
+	};
+};
+
+&mmc_0 {
+	status = "okay";
+	mmc-pwrseq = <&emmc_pwrseq>;
+	cd-gpios = <&gpc0 2 GPIO_ACTIVE_LOW>;
+	card-detect-delay = <200>;
+	samsung,dw-mshc-ciu-div = <3>;
+	samsung,dw-mshc-sdr-timing = <0 4>;
+	samsung,dw-mshc-ddr-timing = <0 2>;
+	samsung,dw-mshc-hs400-timing = <0 2>;
+	samsung,read-strobe-delay = <90>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8 &sd0_cd>;
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
+};
+
+&mmc_2 {
+	status = "okay";
+	card-detect-delay = <200>;
+	samsung,dw-mshc-ciu-div = <3>;
+	samsung,dw-mshc-sdr-timing = <0 4>;
+	samsung,dw-mshc-ddr-timing = <0 2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
+	bus-width = <4>;
+	cap-sd-highspeed;
+};
+
+&pinctrl_0 {
+	emmc_nrst_pin: emmc-nrst {
+		samsung,pins = "gpd1-0";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+};
+
+&serial_0 {
+	status = "okay";
+};
+
+&serial_1 {
+	status = "okay";
+};
+
+&serial_2 {
+	status = "okay";
+};
+
+&serial_3 {
+	status = "okay";
+};
+
+&usbdrd_dwc3_0 {
+	dr_mode = "host";
+};
+
+&usbdrd_dwc3_1 {
+	dr_mode = "peripheral";
+};
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:24 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:24 +0200
Subject: [PATCH v3 21/27] ARM: dts: exynos: Add USB to Exynos5410
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-22-git-send-email-krzk@kernel.org>

Move USB 3.0 DWC and 2.0 EHCI/OHCI nodes from exynos5420.dtsi to
exynos54xx.dtsi common for entire family. For Exynos542x/5800 this
should not have functional impact but for Exynos5410 this effectively
adds USB support.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

TODO: lack of regulator causes errors:
	usb usb4-port1: over-current condition
?
---
 arch/arm/boot/dts/exynos5410.dtsi |  39 +++++++++++
 arch/arm/boot/dts/exynos5420.dtsi | 133 +++++++++++---------------------------
 arch/arm/boot/dts/exynos54xx.dtsi |  79 ++++++++++++++++++++++
 3 files changed, 157 insertions(+), 94 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 850343d3c2af..dd4d6d752865 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -185,4 +185,43 @@
 		  3 0 0x07000000 0x20000>;
 };
 
+&usbdrd3_0 {
+	clocks = <&clock CLK_USBD300>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy0 {
+	clocks = <&clock CLK_USBD300>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbdrd3_1 {
+	clocks = <&clock CLK_USBD301>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy1 {
+	clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbhost1 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usbhost2 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usb2_phy {
+	clocks = <&clock CLK_USBH20>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,sysreg-phandle = <&sysreg_system_controller>;
+	samsung,pmureg-phandle = <&pmu_system_controller>;
+};
+
 #include "exynos5410-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index ebf2ed3c5ff8..8fa65eb8027d 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -41,8 +41,6 @@
 		spi0 = &spi_0;
 		spi1 = &spi_1;
 		spi2 = &spi_2;
-		usbdrdphy0 = &usbdrd_phy0;
-		usbdrdphy1 = &usbdrd_phy1;
 	};
 
 	/*
@@ -770,98 +768,6 @@
 			clock-names = "secss";
 		};
 
-		usbdrd3_0: usb3-0 {
-			compatible = "samsung,exynos5250-dwusb3";
-			clocks = <&clock CLK_USBD300>;
-			clock-names = "usbdrd30";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
-
-			usbdrd_dwc3_0: dwc3 at 12000000 {
-				compatible = "snps,dwc3";
-				reg = <0x12000000 0x10000>;
-				interrupts = <0 72 0>;
-				phys = <&usbdrd_phy0 0>, <&usbdrd_phy0 1>;
-				phy-names = "usb2-phy", "usb3-phy";
-			};
-		};
-
-		usbdrd_phy0: phy at 12100000 {
-			compatible = "samsung,exynos5420-usbdrd-phy";
-			reg = <0x12100000 0x100>;
-			clocks = <&clock CLK_USBD300>, <&clock CLK_SCLK_USBPHY300>;
-			clock-names = "phy", "ref";
-			samsung,pmu-syscon = <&pmu_system_controller>;
-			#phy-cells = <1>;
-		};
-
-		usbdrd3_1: usb3-1 {
-			compatible = "samsung,exynos5250-dwusb3";
-			clocks = <&clock CLK_USBD301>;
-			clock-names = "usbdrd30";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
-
-			usbdrd_dwc3_1: dwc3 at 12400000 {
-				compatible = "snps,dwc3";
-				reg = <0x12400000 0x10000>;
-				interrupts = <0 73 0>;
-				phys = <&usbdrd_phy1 0>, <&usbdrd_phy1 1>;
-				phy-names = "usb2-phy", "usb3-phy";
-			};
-		};
-
-		usbdrd_phy1: phy at 12500000 {
-			compatible = "samsung,exynos5420-usbdrd-phy";
-			reg = <0x12500000 0x100>;
-			clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
-			clock-names = "phy", "ref";
-			samsung,pmu-syscon = <&pmu_system_controller>;
-			#phy-cells = <1>;
-		};
-
-		usbhost2: usb at 12110000 {
-			compatible = "samsung,exynos4210-ehci";
-			reg = <0x12110000 0x100>;
-			interrupts = <0 71 0>;
-
-			clocks = <&clock CLK_USBH20>;
-			clock-names = "usbhost";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			port at 0 {
-				reg = <0>;
-				phys = <&usb2_phy 1>;
-			};
-		};
-
-		usbhost1: usb at 12120000 {
-			compatible = "samsung,exynos4210-ohci";
-			reg = <0x12120000 0x100>;
-			interrupts = <0 71 0>;
-
-			clocks = <&clock CLK_USBH20>;
-			clock-names = "usbhost";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			port at 0 {
-				reg = <0>;
-				phys = <&usb2_phy 1>;
-			};
-		};
-
-		usb2_phy: phy at 12130000 {
-			compatible = "samsung,exynos5250-usb2-phy";
-			reg = <0x12130000 0x100>;
-			clocks = <&clock CLK_USBH20>, <&clock CLK_SCLK_USBPHY300>;
-			clock-names = "phy", "ref";
-			#phy-cells = <1>;
-			samsung,sysreg-phandle = <&sysreg_system_controller>;
-			samsung,pmureg-phandle = <&pmu_system_controller>;
-		};
-
 		sysmmu_g2dr: sysmmu at 0x10A60000 {
 			compatible = "samsung,exynos-sysmmu";
 			reg = <0x10A60000 0x1000>;
@@ -1153,4 +1059,43 @@
 	clock-names = "uart", "clk_uart_baud0";
 };
 
+&usbdrd3_0 {
+	clocks = <&clock CLK_USBD300>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy0 {
+	clocks = <&clock CLK_USBD300>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbdrd3_1 {
+	clocks = <&clock CLK_USBD301>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy1 {
+	clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbhost1 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usbhost2 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usb2_phy {
+	clocks = <&clock CLK_USBH20>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,sysreg-phandle = <&sysreg_system_controller>;
+	samsung,pmureg-phandle = <&pmu_system_controller>;
+};
+
 #include "exynos5420-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi
index 9ce625bd79c1..a9a062708237 100644
--- a/arch/arm/boot/dts/exynos54xx.dtsi
+++ b/arch/arm/boot/dts/exynos54xx.dtsi
@@ -20,6 +20,11 @@
 / {
 	compatible = "samsung,exynos5";
 
+	aliases {
+		usbdrdphy0 = &usbdrd_phy0;
+		usbdrdphy1 = &usbdrd_phy1;
+	};
+
 	soc: soc {
 		sysram at 02020000 {
 			compatible = "mmio-sram";
@@ -64,5 +69,79 @@
 						<11 &gic 0 131 0>;
 			};
 		};
+
+		usbdrd3_0: usb3-0 {
+			compatible = "samsung,exynos5250-dwusb3";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			usbdrd_dwc3_0: dwc3 at 12000000 {
+				compatible = "snps,dwc3";
+				reg = <0x12000000 0x10000>;
+				interrupts = <0 72 0>;
+				phys = <&usbdrd_phy0 0>, <&usbdrd_phy0 1>;
+				phy-names = "usb2-phy", "usb3-phy";
+			};
+		};
+
+		usbdrd_phy0: phy at 12100000 {
+			compatible = "samsung,exynos5420-usbdrd-phy";
+			reg = <0x12100000 0x100>;
+			#phy-cells = <1>;
+		};
+
+		usbdrd3_1: usb3-1 {
+			compatible = "samsung,exynos5250-dwusb3";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			usbdrd_dwc3_1: dwc3 at 12400000 {
+				compatible = "snps,dwc3";
+				reg = <0x12400000 0x10000>;
+				interrupts = <0 73 0>;
+				phys = <&usbdrd_phy1 0>, <&usbdrd_phy1 1>;
+				phy-names = "usb2-phy", "usb3-phy";
+			};
+		};
+
+		usbdrd_phy1: phy at 12500000 {
+			compatible = "samsung,exynos5420-usbdrd-phy";
+			reg = <0x12500000 0x100>;
+			#phy-cells = <1>;
+		};
+
+		usbhost2: usb at 12110000 {
+			compatible = "samsung,exynos4210-ehci";
+			reg = <0x12110000 0x100>;
+			interrupts = <0 71 0>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port at 0 {
+				reg = <0>;
+				phys = <&usb2_phy 1>;
+			};
+		};
+
+		usbhost1: usb at 12120000 {
+			compatible = "samsung,exynos4210-ohci";
+			reg = <0x12120000 0x100>;
+			interrupts = <0 71 0>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port at 0 {
+				reg = <0>;
+				phys = <&usb2_phy 1>;
+			};
+		};
+
+		usb2_phy: phy at 12130000 {
+			compatible = "samsung,exynos5250-usb2-phy";
+			reg = <0x12130000 0x100>;
+			#phy-cells = <1>;
+		};
 	};
 };
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:26 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:26 +0200
Subject: [PATCH v3 23/27] dt-bindings: clock: Add I2C,
 HSI2C and RTC clock IDs to Exynos5410
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-24-git-send-email-krzk@kernel.org>

Add IDs for I2C, USI (HSI2C) and RTC clocks to Exynos5410. Use the same
number as for Exynos5420 just in case in future these drivers were
merged.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 include/dt-bindings/clock/exynos5410.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 34c8e96987a1..e94b7bbfd6af 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -38,9 +38,18 @@
 #define CLK_UART0		257
 #define CLK_UART1		258
 #define CLK_UART2		259
+#define CLK_I2C0		261
+#define CLK_I2C1		262
+#define CLK_I2C2		263
+#define CLK_I2C3		264
+#define CLK_USI0		265
+#define CLK_USI1		266
+#define CLK_USI2		267
+#define CLK_USI3		268
 #define CLK_UART3		260
 #define CLK_PWM			279
 #define CLK_MCT			315
+#define CLK_RTC			317
 #define CLK_MMC0		351
 #define CLK_MMC1		352
 #define CLK_MMC2		353
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:27 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:27 +0200
Subject: [PATCH v3 24/27] clk: samsung: exynos5410: Add I2C,
 HSI2C and RTC clocks
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-25-git-send-email-krzk@kernel.org>

Add clocks for I2C, USI (HSI2C) and RTC to the Exynos5410 clock driver.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 drivers/clk/samsung/clk-exynos5410.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index 40775f678f02..8dd0d8f6703e 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -165,6 +165,7 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 
 static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 	GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
+	GATE(CLK_RTC, "rtc", "aclk66", GATE_IP_PERIS, 20, 0, 0),
 
 	GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
 			SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
@@ -193,6 +194,14 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 	GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
 	GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
 	GATE(CLK_UART3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0),
+	GATE(CLK_I2C0, "i2c0", "aclk66", GATE_IP_PERIC, 6, 0, 0),
+	GATE(CLK_I2C1, "i2c1", "aclk66", GATE_IP_PERIC, 7, 0, 0),
+	GATE(CLK_I2C2, "i2c2", "aclk66", GATE_IP_PERIC, 8, 0, 0),
+	GATE(CLK_I2C3, "i2c3", "aclk66", GATE_IP_PERIC, 9, 0, 0),
+	GATE(CLK_USI0, "usi0", "aclk66", GATE_IP_PERIC, 10, 0, 0),
+	GATE(CLK_USI1, "usi1", "aclk66", GATE_IP_PERIC, 11, 0, 0),
+	GATE(CLK_USI2, "usi2", "aclk66", GATE_IP_PERIC, 12, 0, 0),
+	GATE(CLK_USI3, "usi3", "aclk66", GATE_IP_PERIC, 13, 0, 0),
 	GATE(CLK_PWM, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0),
 
 	GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:29 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:29 +0200
Subject: [PATCH v3 26/27] ARM: dts: exynos: Add I2C,
 PWM and UART pinctrl to Exynos5410
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-27-git-send-email-krzk@kernel.org>

Add pincontrol groups for HSI2C (USI), I2C, PWM and UART to Exynos5410.
This allows configuring these pins to specific functions.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 133 ++++++++++++++++++++++++++++++
 1 file changed, 133 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
index ddacafa1e907..b58a0f29f42c 100644
--- a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
@@ -278,6 +278,139 @@
 		#interrupt-cells = <2>;
 	};
 
+	uart0_data: uart0-data {
+		samsung,pins = "gpa0-0", "gpa0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart0_fctl: uart0-fctl {
+		samsung,pins = "gpa0-2", "gpa0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart1_data: uart1-data {
+		samsung,pins = "gpa0-4", "gpa0-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart1_fctl: uart1-fctl {
+		samsung,pins = "gpa0-6", "gpa0-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c2_bus: i2c2-bus {
+		samsung,pins = "gpa0-6", "gpa0-7";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart2_data: uart2-data {
+		samsung,pins = "gpa1-0", "gpa1-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart2_fctl: uart2-fctl {
+		samsung,pins = "gpa1-2", "gpa1-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c3_bus: i2c3-bus {
+		samsung,pins = "gpa1-2", "gpa1-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart3_data: uart3-data {
+		samsung,pins = "gpa1-4", "gpa1-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c4_hs_bus: i2c4-hs-bus {
+		samsung,pins = "gpa2-0", "gpa2-1";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c5_hs_bus: i2c5-hs-bus {
+		samsung,pins = "gpa2-2", "gpa2-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c6_hs_bus: i2c6-hs-bus {
+		samsung,pins = "gpb1-3", "gpb1-4";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm0_out: pwm0-out {
+		samsung,pins = "gpb2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm1_out: pwm1-out {
+		samsung,pins = "gpb2-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm2_out: pwm2-out {
+		samsung,pins = "gpb2-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm3_out: pwm3-out {
+		samsung,pins = "gpb2-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c7_hs_bus: i2c7-hs-bus {
+		samsung,pins = "gpb2-2", "gpb2-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c0_bus: i2c0-bus {
+		samsung,pins = "gpb3-0", "gpb3-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c1_bus: i2c1-bus {
+		samsung,pins = "gpb3-2", "gpb3-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
 	sd0_clk: sd0-clk {
 		samsung,pins = "gpc0-0";
 		samsung,pin-function = <2>;
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:30 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:30 +0200
Subject: [PATCH v3 27/27] ARM: dts: exynos: Add RTC and I2C to Exynos5410
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-28-git-send-email-krzk@kernel.org>

Configure Exynos5410-specific properties of RTC, I2C and HSI2C nodes.
This still does not enable them on the board level though.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410.dtsi | 66 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index dd4d6d752865..ae64cb0a8efd 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -114,6 +114,9 @@
 			status = "disabled";
 		};
 
+		/* i2c_0-3 are defined in exynos5.dtsi */
+		/* hsi2c_4-7 are defined in exynos5xx.dtsi */
+
 		pinctrl_0: pinctrl at 13400000 {
 			compatible = "samsung,exynos5410-pinctrl";
 			reg = <0x13400000 0x1000>;
@@ -146,6 +149,62 @@
 	};
 };
 
+&i2c_0 {
+	clocks = <&clock CLK_I2C0>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_bus>;
+};
+
+&i2c_1 {
+	clocks = <&clock CLK_I2C1>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_bus>;
+};
+
+&i2c_2 {
+	clocks = <&clock CLK_I2C2>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_bus>;
+};
+
+&i2c_3 {
+	clocks = <&clock CLK_I2C3>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_bus>;
+};
+
+&hsi2c_4 {
+	clocks = <&clock CLK_USI0>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_hs_bus>;
+};
+
+&hsi2c_5 {
+	clocks = <&clock CLK_USI1>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c5_hs_bus>;
+};
+
+&hsi2c_6 {
+	clocks = <&clock CLK_USI2>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c6_hs_bus>;
+};
+
+&hsi2c_7 {
+	clocks = <&clock CLK_USI3>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c7_hs_bus>;
+};
+
 &mct {
 	clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
 	clock-names = "fin_pll", "mct";
@@ -156,6 +215,13 @@
 	clock-names = "timers";
 };
 
+&rtc {
+	clocks = <&clock CLK_RTC>;
+	clock-names = "rtc";
+	interrupt-parent = <&pmu_system_controller>;
+	status = "disabled";
+};
+
 &serial_0 {
 	clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
 	clock-names = "uart", "clk_uart_baud0";
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:28 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:28 +0200
Subject: [PATCH v3 25/27] ARM: dts: exynos: Move HSI2C nodes to exynos54xx.dtsi
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-26-git-send-email-krzk@kernel.org>

The USI/HSI2C nodes can be mostly shared between Exynos5420 and
Exynos5410 so move them to common DTSI.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5420.dtsi | 32 ++++++++++++++++++++++++++----
 arch/arm/boot/dts/exynos54xx.dtsi | 41 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 8fa65eb8027d..791243694aa5 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -29,10 +29,6 @@
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
 		pinctrl4 = &pinctrl_4;
-		i2c4 = &hsi2c_4;
-		i2c5 = &hsi2c_5;
-		i2c6 = &hsi2c_6;
-		i2c7 = &hsi2c_7;
 		i2c8 = &hsi2c_8;
 		i2c9 = &hsi2c_9;
 		i2c10 = &hsi2c_10;
@@ -1022,6 +1018,34 @@
 	pinctrl-0 = <&i2c3_bus>;
 };
 
+&hsi2c_4 {
+	clocks = <&clock CLK_USI0>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_hs_bus>;
+};
+
+&hsi2c_5 {
+	clocks = <&clock CLK_USI1>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c5_hs_bus>;
+};
+
+&hsi2c_6 {
+	clocks = <&clock CLK_USI2>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c6_hs_bus>;
+};
+
+&hsi2c_7 {
+	clocks = <&clock CLK_USI3>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c7_hs_bus>;
+};
+
 &mct {
 	clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
 	clock-names = "fin_pll", "mct";
diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi
index a9a062708237..317612089b50 100644
--- a/arch/arm/boot/dts/exynos54xx.dtsi
+++ b/arch/arm/boot/dts/exynos54xx.dtsi
@@ -21,6 +21,10 @@
 	compatible = "samsung,exynos5";
 
 	aliases {
+		i2c4 = &hsi2c_4;
+		i2c5 = &hsi2c_5;
+		i2c6 = &hsi2c_6;
+		i2c7 = &hsi2c_7;
 		usbdrdphy0 = &usbdrd_phy0;
 		usbdrdphy1 = &usbdrd_phy1;
 	};
@@ -70,6 +74,43 @@
 			};
 		};
 
+		/* i2c_0-3 are defined in exynos5.dtsi */
+		hsi2c_4: i2c at 12CA0000 {
+			compatible = "samsung,exynos5250-hsi2c";
+			reg = <0x12CA0000 0x1000>;
+			interrupts = <0 60 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		hsi2c_5: i2c at 12CB0000 {
+			compatible = "samsung,exynos5250-hsi2c";
+			reg = <0x12CB0000 0x1000>;
+			interrupts = <0 61 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		hsi2c_6: i2c at 12CC0000 {
+			compatible = "samsung,exynos5250-hsi2c";
+			reg = <0x12CC0000 0x1000>;
+			interrupts = <0 62 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		hsi2c_7: i2c at 12CD0000 {
+			compatible = "samsung,exynos5250-hsi2c";
+			reg = <0x12CD0000 0x1000>;
+			interrupts = <0 63 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		usbdrd3_0: usb3-0 {
 			compatible = "samsung,exynos5250-dwusb3";
 			#address-cells = <1>;
-- 
2.5.0



From arnd at arndb.de  Tue May 10 13:14:19 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 22:14:19 +0200
Subject: [GIT PULL 3/3] Rockchip dts64 updates for v4.7 - part2
In-Reply-To: <14339181.jSmLu3hG44@diego>
References: <5544434.9tA8JHBIkp@diego> <14339181.jSmLu3hG44@diego>
Message-ID: <4588554.abhnjsmNOD@wuerfel>

On Friday 29 April 2016 00:25:22 Heiko St?bner wrote:
> Adding the new rk3399 core devicetree support as well as a board
> dts for the evaluation board of this chip and similar to the arm32
> side also move the rk3368 thermal data into the core soc dtsi, as
> there really is no need to keep it separate.
> 
> 
Pulled into next/dt64, thanks!

	Arnd


From arnd at arndb.de  Tue May 10 13:20:08 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 22:20:08 +0200
Subject: [GIT PULL 4/6] Freescale/NXP arm64 device tree updates for 4.7
In-Reply-To: <1462291086-19925-4-git-send-email-shawnguo@kernel.org>
References: <1462291086-19925-1-git-send-email-shawnguo@kernel.org>
 <1462291086-19925-4-git-send-email-shawnguo@kernel.org>
Message-ID: <4371195.x8A0fXcrnJ@wuerfel>

On Tuesday 03 May 2016 23:58:04 Shawn Guo wrote:
> The Freescale/NXP arm64 device tree updates for 4.7:
>  - New board support of LS1043a-QDS from Freescale/NXP
>  - Add new compatible for LS1043A and LS2080A GPIO devices
>  - Update device tree bindings and sources for LS2080A fsl-mc device
>  - Update QSPI and DSPI support on LS1043A and LS2080A
> 
> 

Pulled into next/dt64, thanks!

	Arnd


From krzk at kernel.org  Tue May 10 13:09:09 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:09 +0200
Subject: [PATCH v3 06/27] ARM: dts: exynos: Remove old fixed-clock provider on
 SMDK5410
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-7-git-send-email-krzk@kernel.org>

All "fin_pll" clock users were switched to the new one, provided by
Exynos5410 clock driver. Remove old DT node.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410-smdk5410.dts | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts
index d7d658deeff4..377a679b454b 100644
--- a/arch/arm/boot/dts/exynos5410-smdk5410.dts
+++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts
@@ -24,13 +24,6 @@
 		bootargs = "console=ttySAC2,115200";
 	};
 
-	fin_pll: xxti {
-		compatible = "fixed-clock";
-		clock-frequency = <24000000>;
-		clock-output-names = "fin_pll";
-		#clock-cells = <0>;
-	};
-
 	fixed-rate-clocks {
 		oscclk {
 			compatible = "samsung,exynos5420-oscclk";
-- 
2.5.0



From krzk at kernel.org  Tue May 10 13:09:22 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:22 +0200
Subject: [PATCH v3 19/27] ARM: dts: exynos: MCT is not an interrupt controller
 and extend length of iomap
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-20-git-send-email-krzk@kernel.org>

Multi-Core Timer generates interrupts but it is not really an interrupt
controller so remove the "interrupt-controller" and "interrupt-cells"
properties. Additionally extend the length of mapped memory to cover all
registers (last SFR is at 0x0A40).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5420.dtsi | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 4b16a9376a24..872dadf0f2d4 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -263,9 +263,7 @@
 
 		mct: mct at 101C0000 {
 			compatible = "samsung,exynos4210-mct";
-			reg = <0x101C0000 0x800>;
-			interrupt-controller;
-			#interrupt-cells = <1>;
+			reg = <0x101C0000 0xB00>;
 			interrupt-parent = <&mct_map>;
 			interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
 					<8>, <9>, <10>, <11>;
-- 
2.5.0



From arnd at arndb.de  Tue May 10 13:11:06 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 22:11:06 +0200
Subject: [PATCH 2/4] ARM: ux500: move ab8500_regulator_plat_data into
 driver
In-Reply-To: <20160510150822.GB6261@sirena.org.uk>
References: <1462888794-2793296-1-git-send-email-arnd@arndb.de>
 <1462888794-2793296-3-git-send-email-arnd@arndb.de>
 <20160510150822.GB6261@sirena.org.uk>
Message-ID: <3124394.oLWrYAHOyg@wuerfel>

On Tuesday 10 May 2016 16:08:22 Mark Brown wrote:
> On Tue, May 10, 2016 at 03:59:48PM +0200, Arnd Bergmann wrote:
> > There is only one instance of ab8500_regulator_platform_data, and it's
> > safe to assume we won't ever merge another one, so it's rather pointless
> > to pass it through multiple levels of platform data pointers.
> 
> I'm missing patches 1 and 4 in this series.  What's going on, especially
> with regard to dependencies?

The four patches all have to be applied in order, I sent them to Linus (for
ux500) and Lee (for mtd) as a series to first have a look if the series
makes sense as a whole. You got added from get_maintainer.pl for two of
the patches that are in your domain.

I expect to have to either redo the series anyway, or have Linus pick it
up and forward it. If I resend, I'll add you to Cc for the whole series,
or I can bounce them to you if you like.

	Arnd


From arnd at arndb.de  Tue May 10 13:15:56 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 22:15:56 +0200
Subject: [GIT PULL] ARM: mvebu: dt64 for v4.7 (#1)
In-Reply-To: <87r3dosctw.fsf@free-electrons.com>
References: <87r3dosctw.fsf@free-electrons.com>
Message-ID: <6969114.lHuTlEf8YG@wuerfel>

On Friday 29 April 2016 16:34:51 Gregory CLEMENT wrote:
> mvebu dt64 for 4.7
> 
> - switch to label in the mvebu arm64 device tree
> - use new clock binding on Armada 7K/8K
> - improve SPI and I2C description on Armada 7K/8k
> - add CP110 block adding PCIe, SATA and USB3
> - add XOR support on Armada 3700
> - few more little fix
> 

Pulled into next/dt64, thanks!

	Arnd


From arnd at arndb.de  Tue May 10 13:17:05 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 22:17:05 +0200
Subject: [GIT PULL] dt-bindings: gpio: tegra: Add Tegra186 support
In-Reply-To: <1461946869-26124-2-git-send-email-thierry.reding@gmail.com>
References: <1461946869-26124-2-git-send-email-thierry.reding@gmail.com>
Message-ID: <3440686.BWpiYfIJp0@wuerfel>

On Friday 29 April 2016 18:21:07 Thierry Reding wrote:
> dt-bindings: gpio: tegra: Add Tegra186 support
> 
> Adds device tree bindings for the GPIO and AON controllers found on the
> Tegra186 SoC.
> 

Pulled into next/dt64, thanks!

	Arnd


From arnd at arndb.de  Tue May 10 13:18:20 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 22:18:20 +0200
Subject: [GIT PULL] arm64: tegra: Enable GM20B GPU on Tegra210
In-Reply-To: <1461946869-26124-3-git-send-email-thierry.reding@gmail.com>
References: <1461946869-26124-3-git-send-email-thierry.reding@gmail.com>
Message-ID: <2527075.TJdy0Md9Y9@wuerfel>

On Friday 29 April 2016 18:21:08 Thierry Reding wrote:
> arm64: tegra: Enable GM20B GPU on Tegra210
> 
> Complement the GM20B GPU device tree node on Tegra210 with missing
> properties to make it usable.
> 

Pulled into next/dt64, thanks!

	Arnd


From arnd at arndb.de  Tue May 10 13:16:22 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 10 May 2016 22:16:22 +0200
Subject: [GIT PULL] ARM: mvebu: defconfig64 for v4.7 (#1)
In-Reply-To: <87twi6nfad.fsf@free-electrons.com>
References: <87twi6nfad.fsf@free-electrons.com>
Message-ID: <15112851.U73dTNcfKF@wuerfel>

On Tuesday 10 May 2016 16:44:42 Gregory CLEMENT wrote:
> Hi,
> 
> Here is the first pull request for defconfig64 for mvebu for v4.7.
> 
> Gregory
> 
> The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:
> 
>   Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)
> 
> are available in the git repository at:
> 
>   git://git.infradead.org/linux-mvebu.git tags/mvebu-defconfig64-4.7-1
> 
> for you to fetch changes up to e5d8b0ad5ae4c70a7081865a3c6c83ae1afe3087:
> 
>   arm64: configs: add options useful for Armada 7K/8K support (2016-05-10 14:42:23 +0200)
> 
> ----------------------------------------------------------------
> mvebu defconfig for arm64 for 4.7
> 
> - update arm64 defconfig with options useful for Armada 7K/8K support
> 
> ----------------------------------------------------------------

Pulled into next/arm64, thanks for the respin!

	Arnd


From krzk at kernel.org  Tue May 10 13:09:20 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 10 May 2016 22:09:20 +0200
Subject: [PATCH v3 17/27] ARM: dts: exynos: Include common exynos5 in
 exynos5410.dtsi
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <1462910970-1812-18-git-send-email-krzk@kernel.org>

The exynos5.dtsi is used for common nodes shared between Exynos5250 and
Exynos542x. Since Exynos5410 is very similar to Exynos5420 it can
include the common file as well to remove duplication and make
everything more consistent.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410-smdk5410.dts |   6 +-
 arch/arm/boot/dts/exynos5410.dtsi         | 103 ++++++++++--------------------
 2 files changed, 35 insertions(+), 74 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts
index 377a679b454b..501f776f327d 100644
--- a/arch/arm/boot/dts/exynos5410-smdk5410.dts
+++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts
@@ -102,14 +102,14 @@
 	};
 };
 
-&uart0 {
+&serial_0 {
 	status = "okay";
 };
 
-&uart1 {
+&serial_1 {
 	status = "okay";
 };
 
-&uart2 {
+&serial_2 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 58d3844ef923..c0540eb76271 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -14,6 +14,7 @@
  */
 
 #include "skeleton.dtsi"
+#include "exynos5.dtsi"
 #include "exynos-syscon-restart.dtsi"
 #include <dt-bindings/clock/exynos5410.h>
 
@@ -26,9 +27,6 @@
 		pinctrl1 = &pinctrl_1;
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
-		serial0 = &uart0;
-		serial1 = &uart1;
-		serial2 = &uart2;
 	};
 
 	cpus {
@@ -70,49 +68,6 @@
 		#size-cells = <1>;
 		ranges;
 
-		combiner: interrupt-controller at 10440000 {
-			compatible = "samsung,exynos4210-combiner";
-			#interrupt-cells = <2>;
-			interrupt-controller;
-			samsung,combiner-nr = <32>;
-			reg = <0x10440000 0x1000>;
-			interrupts =	<0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
-					<0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
-					<0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
-					<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
-					<0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-					<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
-					<0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-					<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
-		};
-
-		gic: interrupt-controller at 10481000 {
-			compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
-			#interrupt-cells = <3>;
-			interrupt-controller;
-			reg =	<0x10481000 0x1000>,
-				<0x10482000 0x1000>,
-				<0x10484000 0x2000>,
-				<0x10486000 0x2000>;
-			interrupts = <1 9 0xf04>;
-		};
-
-		chipid at 10000000 {
-			compatible = "samsung,exynos4210-chipid";
-			reg = <0x10000000 0x100>;
-		};
-
-		sromc: memory-controller at 12250000 {
-			compatible = "samsung,exynos4210-srom";
-			reg = <0x12250000 0x14>;
-			#address-cells = <2>;
-			#size-cells = <1>;
-			ranges = <0 0 0x04000000 0x20000
-				  1 0 0x05000000 0x20000
-				  2 0 0x06000000 0x20000
-				  3 0 0x07000000 0x20000>;
-		};
-
 		pmu_system_controller: system-controller at 10040000 {
 			compatible = "samsung,exynos5410-pmu", "syscon";
 			reg = <0x10040000 0x5000>;
@@ -236,34 +191,40 @@
 			reg = <0x03860000 0x1000>;
 			interrupts = <0 47 0>;
 		};
+	};
+};
 
-		uart0: serial at 12C00000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C00000 0x100>;
-			interrupts = <0 51 0>;
-			clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
 
-		uart1: serial at 12C10000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C10000 0x100>;
-			interrupts = <0 52 0>;
-			clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
+&serial_0 {
+	clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
+	clock-names = "uart", "clk_uart_baud0";
+};
 
-		uart2: serial at 12C20000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C20000 0x100>;
-			interrupts = <0 53 0>;
-			clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
-	};
+&serial_1 {
+	clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
+	clock-names = "uart", "clk_uart_baud0";
+};
+
+&serial_2 {
+	clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
+	clock-names = "uart", "clk_uart_baud0";
+};
+
+&serial_3 {
+	status = "disabled";
+};
+
+&sromc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	ranges = <0 0 0x04000000 0x20000
+		  1 0 0x05000000 0x20000
+		  2 0 0x06000000 0x20000
+		  3 0 0x07000000 0x20000>;
 };
 
 #include "exynos5410-pinctrl.dtsi"
-- 
2.5.0



From dianders at chromium.org  Tue May 10 14:07:34 2016
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 10 May 2016 14:07:34 -0700
Subject: [PATCH] pinctrl: rockchip: fix pull setting error for rk3399
In-Reply-To: <1462878896-28956-1-git-send-email-wxt@rock-chips.com>
References: <1462878896-28956-1-git-send-email-wxt@rock-chips.com>
Message-ID: <CAD=FV=VrE=9=sgqUXBMwmoQin8S+yPbAgnrO1VUgx5QafYWXhA@mail.gmail.com>

Caesar / David,

On Tue, May 10, 2016 at 4:14 AM, Caesar Wang <wxt at rock-chips.com> wrote:
> From: David Wu <david.wu at rock-chips.com>
>
> This patch fixes the pinctrl pull bias setting, since the pull up/down
> setting is the contrary for gpio0.

Commit message only mentions gpio0, but gpio2 is also fixed in the
commit.  Please mention gpio2 in the commit message.


> From the TRM said, the gpio0 pull polarity setting:
> gpio0a_p (gpio0 )
> GPIO0A PE/PS programmation section, every
> GPIO bit corresponding to 2bits[PS:PE]
> 2'b00: Z(Noraml operaton);
> 2'b11: weak 1(pull-up);
> 2'b01: weak 0(pull-down);
> 2'b10: Z(Noraml operaton);

Despite the fact that the typo (Noralm vs. Normal) is present in the
TRM, maybe we should fix it here?


> Then, the other gpios setting as the following:
> gpio1a_p (gpio1, gpio2, gpio3...)
> GPIO1A PU/PD programmation section, every
> GPIO bit corresponding to 2bits
> 2'b00: Z(Noraml operaton);
> 2'b01: weak 1(pull-up);
> 2'b10: weak 0(pull-down);
> 2'b11: Repeater(Bus keeper)
>
> For example,(rk3399evb board)
> sdmmc_cd --->gpio0_a7
> localhost / # io -r -4 0xff320040
> ff320040: 00004d5f
> In general,the value should be 0x0000cd5f since the pin set in the dts.
>
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> Cc: Linus Walleij <linus.walleij at linaro.org>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Cc: linux-gpio at vger.kernel.org
> ---
>
>  drivers/pinctrl/pinctrl-rockchip.c | 178 ++++++++++++++++++++++++++-----------
>  1 file changed, 126 insertions(+), 52 deletions(-)
>
> diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
> index 596b869..38be9c7 100644
> --- a/drivers/pinctrl/pinctrl-rockchip.c
> +++ b/drivers/pinctrl/pinctrl-rockchip.c
> @@ -99,6 +99,15 @@ enum rockchip_pin_drv_type {
>  };
>
>  /**
> + * enum type index corresponding to rockchip_pull_list arrays index.
> + */
> +enum rockchip_pin_pull_type {
> +       PULL_TYPE_IO_DEFAULT = 0,
> +       PULL_TYPE_IO_1V8_ONLY,
> +       PULL_TYPE_MAX
> +};
> +
> +/**
>   * @drv_type: drive strength variant using rockchip_perpin_drv_type
>   * @offset: if initialized to -1 it will be autocalculated, by specifying
>   *         an initial offset value the relevant source offset can be reset
> @@ -123,6 +132,7 @@ struct rockchip_drv {
>   * @bank_num: number of the bank, to account for holes
>   * @iomux: array describing the 4 iomux sources of the bank
>   * @drv: array describing the 4 drive strength sources of the bank
> + * @pull_type: array describing the 4 pull type sources of the bank
>   * @valid: are all necessary informations present
>   * @of_node: dt node of this bank
>   * @drvdata: common pinctrl basedata
> @@ -143,6 +153,7 @@ struct rockchip_pin_bank {
>         u8                              bank_num;
>         struct rockchip_iomux           iomux[4];
>         struct rockchip_drv             drv[4];
> +       enum rockchip_pin_pull_type     pull_type[4];
>         bool                            valid;
>         struct device_node              *of_node;
>         struct rockchip_pinctrl         *drvdata;
> @@ -198,6 +209,31 @@ struct rockchip_pin_bank {
>                 },                                                      \
>         }
>
> +#define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1,     \
> +                                     drv2, drv3, pull0, pull1,         \
> +                                     pull2, pull3)                     \
> +       {                                                               \
> +               .bank_num       = id,                                   \
> +               .nr_pins        = pins,                                 \
> +               .name           = label,                                \
> +               .iomux          = {                                     \
> +                       { .offset = -1 },                               \
> +                       { .offset = -1 },                               \
> +                       { .offset = -1 },                               \
> +                       { .offset = -1 },                               \
> +               },                                                      \
> +               .drv            = {                                     \
> +                       { .drv_type = drv0, .offset = -1 },             \
> +                       { .drv_type = drv1, .offset = -1 },             \
> +                       { .drv_type = drv2, .offset = -1 },             \
> +                       { .drv_type = drv3, .offset = -1 },             \
> +               },                                                      \
> +               .pull_type[0] = pull0,                                  \
> +               .pull_type[1] = pull1,                                  \
> +               .pull_type[2] = pull2,                                  \
> +               .pull_type[3] = pull3,                                  \
> +       }
> +
>  #define PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(id, pins, label, iom0, iom1,   \
>                                         iom2, iom3, drv0, drv1, drv2,   \
>                                         drv3, offset0, offset1,         \
> @@ -220,6 +256,34 @@ struct rockchip_pin_bank {
>                 },                                                      \
>         }
>
> +#define PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(id, pins,     \
> +                                             label, iom0, iom1, iom2,  \
> +                                             iom3, drv0, drv1, drv2,   \
> +                                             drv3, offset0, offset1,   \
> +                                             offset2, offset3, pull0,  \
> +                                             pull1, pull2, pull3)      \
> +       {                                                               \
> +               .bank_num       = id,                                   \
> +               .nr_pins        = pins,                                 \
> +               .name           = label,                                \
> +               .iomux          = {                                     \
> +                       { .type = iom0, .offset = -1 },                 \
> +                       { .type = iom1, .offset = -1 },                 \
> +                       { .type = iom2, .offset = -1 },                 \
> +                       { .type = iom3, .offset = -1 },                 \
> +               },                                                      \
> +               .drv            = {                                     \
> +                       { .drv_type = drv0, .offset = offset0 },        \
> +                       { .drv_type = drv1, .offset = offset1 },        \
> +                       { .drv_type = drv2, .offset = offset2 },        \
> +                       { .drv_type = drv3, .offset = offset3 },        \
> +               },                                                      \
> +               .pull_type[0] = pull0,                                  \
> +               .pull_type[1] = pull1,                                  \
> +               .pull_type[2] = pull2,                                  \
> +               .pull_type[3] = pull3,                                  \
> +       }
> +
>  /**
>   */
>  struct rockchip_pin_ctrl {
> @@ -1020,12 +1084,27 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
>         return ret;
>  }
>
> +static int rockchip_pull_list[PULL_TYPE_MAX][4] = {
> +       {
> +               PIN_CONFIG_BIAS_DISABLE,
> +               PIN_CONFIG_BIAS_PULL_UP,
> +               PIN_CONFIG_BIAS_PULL_DOWN,
> +               PIN_CONFIG_BIAS_BUS_HOLD
> +       },
> +       {
> +               PIN_CONFIG_BIAS_DISABLE,
> +               PIN_CONFIG_BIAS_PULL_DOWN,
> +               PIN_CONFIG_BIAS_DISABLE,
> +               PIN_CONFIG_BIAS_PULL_UP
> +       },
> +};
> +
>  static int rockchip_get_pull(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;
> +       int reg, ret, pull_type;
>         u8 bit;
>         u32 data;
>
> @@ -1048,22 +1127,11 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
>         case RK3288:
>         case RK3368:
>         case RK3399:
> +               pull_type = bank->pull_type[pin_num / 8];
>                 data >>= bit;
>                 data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
>
> -               switch (data) {
> -               case 0:
> -                       return PIN_CONFIG_BIAS_DISABLE;
> -               case 1:
> -                       return PIN_CONFIG_BIAS_PULL_UP;
> -               case 2:
> -                       return PIN_CONFIG_BIAS_PULL_DOWN;
> -               case 3:
> -                       return PIN_CONFIG_BIAS_BUS_HOLD;
> -               }
> -
> -               dev_err(info->dev, "unknown pull setting\n");
> -               return -EIO;
> +               return rockchip_pull_list[pull_type][data];
>         default:
>                 dev_err(info->dev, "unsupported pinctrl type\n");
>                 return -EINVAL;
> @@ -1076,7 +1144,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
>         struct rockchip_pinctrl *info = bank->drvdata;
>         struct rockchip_pin_ctrl *ctrl = info->ctrl;
>         struct regmap *regmap;
> -       int reg, ret;
> +       int reg, ret, i, pull_type;
>         unsigned long flags;
>         u8 bit;
>         u32 data, rmask;
> @@ -1105,30 +1173,27 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
>         case RK3288:
>         case RK3368:
>         case RK3399:
> +               pull_type = bank->pull_type[pin_num / 8];
> +               ret = -EINVAL;
> +               for (i = 0; i < ARRAY_SIZE(rockchip_pull_list[pull_type]);
> +                       i++) {
> +                       if (rockchip_pull_list[pull_type][i] == pull) {
> +                               ret = i;
> +                               break;
> +                       }
> +               }
> +
> +               if (ret < 0) {
> +                       dev_err(info->dev, "unknown pull setting %d\n", pull);

nit: why change the error message?  Old message was "unsupported"
instead of your new "unknown".  "unsupported" was better IMHO.



> +                       return ret;
> +               }
> +
>                 spin_lock_irqsave(&bank->slock, flags);
>
>                 /* enable the write to the equivalent lower bits */
>                 data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
>                 rmask = data | (data >> 16);
> -
> -               switch (pull) {
> -               case PIN_CONFIG_BIAS_DISABLE:
> -                       break;
> -               case PIN_CONFIG_BIAS_PULL_UP:
> -                       data |= (1 << bit);
> -                       break;
> -               case PIN_CONFIG_BIAS_PULL_DOWN:
> -                       data |= (2 << bit);
> -                       break;
> -               case PIN_CONFIG_BIAS_BUS_HOLD:
> -                       data |= (3 << bit);
> -                       break;
> -               default:
> -                       spin_unlock_irqrestore(&bank->slock, flags);
> -                       dev_err(info->dev, "unsupported pull setting %d\n",
> -                               pull);
> -                       return -EINVAL;
> -               }
> +               data |= (ret << bit);
>
>                 ret = regmap_update_bits(regmap, reg, rmask, data);
>
> @@ -2552,19 +2617,24 @@ static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
>  };
>
>  static struct rockchip_pin_bank rk3399_pin_banks[] = {
> -       PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(0, 32, "gpio0", IOMUX_SOURCE_PMU,
> -                                       IOMUX_SOURCE_PMU,
> -                                       IOMUX_SOURCE_PMU,
> -                                       IOMUX_SOURCE_PMU,
> -                                       DRV_TYPE_IO_1V8_ONLY,
> -                                       DRV_TYPE_IO_1V8_ONLY,
> -                                       DRV_TYPE_IO_DEFAULT,
> -                                       DRV_TYPE_IO_DEFAULT,
> -                                       0x0,
> -                                       0x8,
> -                                       -1,
> -                                       -1
> -                                       ),
> +       PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(0, 32, "gpio0",
> +                                                        IOMUX_SOURCE_PMU,
> +                                                        IOMUX_SOURCE_PMU,
> +                                                        IOMUX_SOURCE_PMU,
> +                                                        IOMUX_SOURCE_PMU,
> +                                                        DRV_TYPE_IO_1V8_ONLY,
> +                                                        DRV_TYPE_IO_1V8_ONLY,
> +                                                        DRV_TYPE_IO_DEFAULT,
> +                                                        DRV_TYPE_IO_DEFAULT,
> +                                                        0x0,
> +                                                        0x8,
> +                                                        -1,
> +                                                        -1,
> +                                                        PULL_TYPE_IO_1V8_ONLY,
> +                                                        PULL_TYPE_IO_1V8_ONLY,
> +                                                        PULL_TYPE_IO_DEFAULT,
> +                                                        PULL_TYPE_IO_DEFAULT
> +                                                       ),
>         PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU,
>                                         IOMUX_SOURCE_PMU,
>                                         IOMUX_SOURCE_PMU,
> @@ -2578,11 +2648,15 @@ static struct rockchip_pin_bank rk3399_pin_banks[] = {
>                                         0x30,
>                                         0x38
>                                         ),
> -       PIN_BANK_DRV_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
> -                          DRV_TYPE_IO_1V8_OR_3V0,
> -                          DRV_TYPE_IO_1V8_ONLY,
> -                          DRV_TYPE_IO_1V8_ONLY
> -                          ),
> +       PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
> +                                     DRV_TYPE_IO_1V8_OR_3V0,
> +                                     DRV_TYPE_IO_1V8_ONLY,
> +                                     DRV_TYPE_IO_1V8_ONLY,
> +                                     PULL_TYPE_IO_DEFAULT,
> +                                     PULL_TYPE_IO_DEFAULT,
> +                                     PULL_TYPE_IO_1V8_ONLY,
> +                                     PULL_TYPE_IO_1V8_ONLY

Are you certain that gpio2 behaves the same way?  The TRM I have says
this for GPIO2C and GPIO2D:

2'b00: pervious-state
2'b01: weak 0(pull-down);
2'b10: pervious-state
2'b11: weak 1(pull-up);

Assuming that "pervious-state" is a simple typo for "previous state"
that would imply that it was behaving as "bus hold" and _not_ "bias
disable".

Note: if it actually is a "bus hold" state then we'll have to figure
out how this would work with existing device trees.  I'd imagine that
they are currently specifying "bias disable" and technically that
might not be possible?



-Doug


From javier at osg.samsung.com  Tue May 10 14:07:27 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 10 May 2016 17:07:27 -0400
Subject: [PATCH 1/2] ARM: exynos_defconfig: Enable MFC driver as module
Message-ID: <1462914448-24480-1-git-send-email-javier@osg.samsung.com>

Exynos SoCs have a Multi Format Video Hardware Codec (MFC) IP block that
can be used to {en,de}code video streams by hardware. Enable support for
its driver as a module so the MFC can be tested.

Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

This patch depends on https://patchwork.kernel.org/patch/8970731/

 arch/arm/configs/exynos_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
index 0600818f0f2a..007c8eca407e 100644
--- a/arch/arm/configs/exynos_defconfig
+++ b/arch/arm/configs/exynos_defconfig
@@ -155,6 +155,7 @@ CONFIG_VIDEO_EXYNOS_FIMC_LITE=m
 CONFIG_VIDEO_EXYNOS4_FIMC_IS=m
 CONFIG_V4L_MEM2MEM_DRIVERS=y
 CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
 CONFIG_DRM=y
 CONFIG_DRM_NXP_PTN3460=y
 CONFIG_DRM_PARADE_PS8622=y
-- 
2.5.5



From javier at osg.samsung.com  Tue May 10 14:07:28 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 10 May 2016 17:07:28 -0400
Subject: [PATCH 2/2] ARM: multi_v7_defconfig: Enable Exynos MFC driver as
 module
In-Reply-To: <1462914448-24480-1-git-send-email-javier@osg.samsung.com>
References: <1462914448-24480-1-git-send-email-javier@osg.samsung.com>
Message-ID: <1462914448-24480-2-git-send-email-javier@osg.samsung.com>

Exynos SoCs have a Multi Format Video Hardware Codec (MFC) IP block that
can be used to {en,de}code video streams by hardware. Enable support for
its driver as a module so the MFC can be tested.

Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

This patch depends on https://patchwork.kernel.org/patch/8970711/

 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 2ba3f0cd2261..8086e9e13ff6 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -534,6 +534,7 @@ CONFIG_VIDEO_EXYNOS_FIMC_LITE=m
 CONFIG_VIDEO_EXYNOS4_FIMC_IS=m
 CONFIG_V4L_MEM2MEM_DRIVERS=y
 CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
 CONFIG_VIDEO_RENESAS_JPU=m
 CONFIG_VIDEO_RENESAS_VSP1=m
 # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
-- 
2.5.5



From sboyd at codeaurora.org  Tue May 10 15:45:59 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Tue, 10 May 2016 15:45:59 -0700
Subject: [PATCH 2/2] ARM: dts: qcom: Enable sdcard and emmc on apq8074
 dragonboard
In-Reply-To: <20160510224559.17568-1-sboyd@codeaurora.org>
References: <20160510224559.17568-1-sboyd@codeaurora.org>
Message-ID: <20160510224559.17568-2-sboyd@codeaurora.org>

Enable the sdcard slot and wire up the regulators for the two
storage controllers found on the apq8074 dragonboard.

Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
---
 arch/arm/boot/dts/qcom-apq8074-dragonboard.dts | 48 ++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts b/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts
index 8d1011d289bc..ad51df27dfb7 100644
--- a/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts
+++ b/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts
@@ -25,11 +25,23 @@
 			bus-width = <8>;
 			non-removable;
 			status = "ok";
+
+			vmmc-supply = <&pm8941_l20>;
+			vqmmc-supply = <&pm8941_s3>;
+
+			pinctrl-names = "default";
+			pinctrl-0 = <&sdhc1_pin_a>;
 		};
 
 		sdhci at f98a4900 {
 			cd-gpios = <&msmgpio 62 0x1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&sdhc2_pin_a>, <&sdhc2_cd_pin_a>;
 			bus-width = <4>;
+			status = "ok";
+
+			vmmc-supply = <&pm8941_l21>;
+			vqmmc-supply = <&pm8941_l13>;
 		};
 
 
@@ -59,6 +71,42 @@
 					function = "blsp_spi8";
 				};
 			};
+
+			sdhc1_pin_a: sdhc1-pin-active {
+				clk {
+					pins = "sdc1_clk";
+					drive-strength = <16>;
+					bias-disable;
+				};
+
+				cmd-data {
+					pins = "sdc1_cmd", "sdc1_data";
+					drive-strength = <10>;
+					bias-pull-up;
+				};
+			};
+
+			sdhc2_cd_pin_a: sdhc2-cd-pin-active {
+				pins = "gpio62";
+				function = "gpio";
+
+				drive-strength = <2>;
+				bias-disable;
+			};
+
+			sdhc2_pin_a: sdhc2-pin-active {
+				clk {
+					pins = "sdc2_clk";
+					drive-strength = <10>;
+					bias-disable;
+				};
+
+				cmd-data {
+					pins = "sdc2_cmd", "sdc2_data";
+					drive-strength = <6>;
+					bias-pull-up;
+				};
+			};
 		};
 
 		i2c at f9967000 {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



From sboyd at codeaurora.org  Tue May 10 15:45:58 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Tue, 10 May 2016 15:45:58 -0700
Subject: [PATCH 1/2] ARM: dts: qcom: Enable RPM regulators on apq8074
 dragonboard
Message-ID: <20160510224559.17568-1-sboyd@codeaurora.org>

Add the appropriate min/max voltages for the regulators on the
apq8074 dragonboard so that they can be used by clients properly.

Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
---
 arch/arm/boot/dts/qcom-apq8074-dragonboard.dts | 199 +++++++++++++++++++++++++
 1 file changed, 199 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts b/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts
index c0e205315042..8d1011d289bc 100644
--- a/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts
+++ b/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts
@@ -75,4 +75,203 @@
 			};
 		};
 	};
+
+	smd {
+		rpm {
+			rpm_requests {
+				pm8841-regulators {
+					s1 {
+						regulator-min-microvolt = <675000>;
+						regulator-max-microvolt = <1050000>;
+					};
+
+					s2 {
+						regulator-min-microvolt = <500000>;
+						regulator-max-microvolt = <1050000>;
+					};
+
+					s3 {
+						regulator-min-microvolt = <500000>;
+						regulator-max-microvolt = <1050000>;
+					};
+
+					s4 {
+						regulator-min-microvolt = <500000>;
+						regulator-max-microvolt = <1050000>;
+					};
+				};
+
+				pm8941-regulators {
+					vdd_l1_l3-supply = <&pm8941_s1>;
+					vdd_l2_lvs1_2_3-supply = <&pm8941_s3>;
+					vdd_l4_l11-supply = <&pm8941_s1>;
+					vdd_l5_l7-supply = <&pm8941_s2>;
+					vdd_l6_l12_l14_l15-supply = <&pm8941_s2>;
+					vin_5vs-supply = <&pm8941_5v>;
+
+					s1 {
+						regulator-min-microvolt = <1300000>;
+						regulator-max-microvolt = <1300000>;
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					s2 {
+						regulator-min-microvolt = <2150000>;
+						regulator-max-microvolt = <2150000>;
+						regulator-boot-on;
+					};
+
+					s3 {
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <1800000>;
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					l1 {
+						regulator-min-microvolt = <1225000>;
+						regulator-max-microvolt = <1225000>;
+
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					l2 {
+						regulator-min-microvolt = <1200000>;
+						regulator-max-microvolt = <1200000>;
+					};
+
+					l3 {
+						regulator-min-microvolt = <1225000>;
+						regulator-max-microvolt = <1225000>;
+					};
+
+					l4 {
+						regulator-min-microvolt = <1225000>;
+						regulator-max-microvolt = <1225000>;
+					};
+
+					l5 {
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <1800000>;
+					};
+
+					l6 {
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <1800000>;
+
+						regulator-boot-on;
+					};
+
+					l7 {
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <1800000>;
+
+						regulator-boot-on;
+					};
+
+					l8 {
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <1800000>;
+					};
+
+					l9 {
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <2950000>;
+					};
+
+					l10 {
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <1800000>;
+						regulator-always-on;
+					};
+
+					l11 {
+						regulator-min-microvolt = <1300000>;
+						regulator-max-microvolt = <1300000>;
+					};
+
+					l12 {
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <1800000>;
+
+						regulator-always-on;
+						regulator-boot-on;
+					};
+
+					l13 {
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <2950000>;
+
+						regulator-boot-on;
+					};
+
+					l14 {
+						regulator-min-microvolt = <1800000>;
+						regulator-max-microvolt = <1800000>;
+					};
+
+					l15 {
+						regulator-min-microvolt = <2050000>;
+						regulator-max-microvolt = <2050000>;
+					};
+
+					l16 {
+						regulator-min-microvolt = <2700000>;
+						regulator-max-microvolt = <2700000>;
+					};
+
+					l17 {
+						regulator-min-microvolt = <2700000>;
+						regulator-max-microvolt = <2700000>;
+					};
+
+					l18 {
+						regulator-min-microvolt = <2850000>;
+						regulator-max-microvolt = <2850000>;
+					};
+
+					l19 {
+						regulator-min-microvolt = <3300000>;
+						regulator-max-microvolt = <3300000>;
+						regulator-always-on;
+					};
+
+					l20 {
+						regulator-min-microvolt = <2950000>;
+						regulator-max-microvolt = <2950000>;
+
+						regulator-allow-set-load;
+						regulator-boot-on;
+						regulator-system-load = <200000>;
+					};
+
+					l21 {
+						regulator-min-microvolt = <2950000>;
+						regulator-max-microvolt = <2950000>;
+
+						regulator-boot-on;
+					};
+
+					l22 {
+						regulator-min-microvolt = <3000000>;
+						regulator-max-microvolt = <3000000>;
+					};
+
+					l23 {
+						regulator-min-microvolt = <3000000>;
+						regulator-max-microvolt = <3000000>;
+					};
+
+					l24 {
+						regulator-min-microvolt = <3075000>;
+						regulator-max-microvolt = <3075000>;
+
+						regulator-boot-on;
+					};
+				};
+			};
+		};
+	};
 };
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



From ttnguyen at apm.com  Tue May 10 16:43:30 2016
From: ttnguyen at apm.com (Tai Tri Nguyen)
Date: Tue, 10 May 2016 16:43:30 -0700
Subject: [PATCH v2 2/4] Documentation: Add documentation for APM X-Gene
 SoC PMU DTS binding
In-Reply-To: <CACgAJHyT31DuVNoyRQZVKjv=zM5Fc-EY0gy=y=pHHrBTT+1Xow@mail.gmail.com>
References: <1460510547-17611-1-git-send-email-ttnguyen@apm.com>
 <1460510547-17611-3-git-send-email-ttnguyen@apm.com>
 <20160418170009.GA15338@rob-hp-laptop>
 <CACgAJHyBbO_LXwtfNVK1f=dY3v1Jfxwxq1dw98EZ0aYdhjPpAg@mail.gmail.com>
 <20160420113121.GE2514@arm.com>
 <20160502205648.GA7374@rob-hp-laptop>
 <CACgAJHyT31DuVNoyRQZVKjv=zM5Fc-EY0gy=y=pHHrBTT+1Xow@mail.gmail.com>
Message-ID: <CACgAJHyHEOe70pOG2yi-XUQS3BYdGmfYD-yTE0wFM9knDtHOiQ@mail.gmail.com>

Hi Rob/Mark,

Do you have any more comments, please?

Thanks,
Tai

On Mon, May 2, 2016 at 2:46 PM, Tai Tri Nguyen <ttnguyen at apm.com> wrote:
> Hi Rob,
>
> On Mon, May 2, 2016 at 1:56 PM, Rob Herring <robh at kernel.org> wrote:
>> On Wed, Apr 20, 2016 at 12:31:22PM +0100, Will Deacon wrote:
>>> On Mon, Apr 18, 2016 at 01:04:53PM -0700, Tai Tri Nguyen wrote:
>>> > >> +Required properties for MCB subnode:
>>> > >> +- compatible         : Shall be "apm,xgene-pmu-mcb".
>>> > >> +- reg                        : First resource shall be the MCB PMU resource.
>>> > >> +- index                      : Instance number of the MCB PMU.
>>> > >> +
>>> > >> +Required properties for MC subnode:
>>> > >> +- compatible         : Shall be "apm,xgene-pmu-mc".
>>> > >> +- reg                        : First resource shall be the MC PMU resource.
>>> > >> +- index                      : Instance number of the MC PMU.
>>> > >
>>> > > Don't use indexes. You probably need phandles to the nodes these are
>>> > > related to.
>>> > >
>>> > > How many variations of child nodes do you expect to have? 2, 10, 50? You
>>> > > might want to just collapse all this down to a single node and put this
>>> > > information in the driver if it is fixed for each SoC and there's only a
>>> > > handful.
>>> > >
>>> >
>>> > For each kind of PMU, for example memory controller PMU, I expect to
>>> > have the number of instances up to 8.
>>> > They are actually all independent PMU nodes and have their own CSR memory bases.
>>> > The indexes are used for exposing the devices to perf user only. It
>>> > doesn't have an impact on the programming model.
>>> > Mark also had the same concern.
>>>
>>> Regardless, I'll need an ack from Rob or Mark before I can merge this.
>>
>> I still have a concern with this. Needing an index to expose to the user
>> is generally not a valid reason. That's OS specific and therefore
>> doesn't belong in DT.
>>
>> Rob
>
> I can use device name here. However, the perf event names will be
> different between DT and ACPI which I want to avoid.
> And the names don't look good at all.
> Also, specifically for MC and MCB PMUs, the indexes are compared
> against the active MC/MCB mask to find out whether they are populated
> or not.
> Without using the index property, I will also need a mapping function
> of physical device addresses and their physical ids.
>
> Thanks,
> --
> Tai



-- 
Tai


From rjw at rjwysocki.net  Tue May 10 17:03:28 2016
From: rjw at rjwysocki.net (Rafael J. Wysocki)
Date: Wed, 11 May 2016 02:03:28 +0200
Subject: [PATCH v4 2/5] ACPI / processor_idle: Add support for Low Power
 Idle(LPI) states
In-Reply-To: <1461069013-13292-3-git-send-email-sudeep.holla@arm.com>
References: <1461069013-13292-1-git-send-email-sudeep.holla@arm.com>
 <1461069013-13292-3-git-send-email-sudeep.holla@arm.com>
Message-ID: <1857618.TLitUhExSh@vostro.rjw.lan>

On Tuesday, April 19, 2016 01:30:10 PM Sudeep Holla wrote:
> ACPI 6.0 introduced an optional object _LPI that provides an alternate
> method to describe Low Power Idle states. It defines the local power
> states for each node in a hierarchical processor topology. The OSPM can
> use _LPI object to select a local power state for each level of processor
> hierarchy in the system. They used to produce a composite power state
> request that is presented to the platform by the OSPM.
> 
> Since multiple processors affect the idle state for any non-leaf hierarchy
> node, coordination of idle state requests between the processors is
> required. ACPI supports two different coordination schemes: Platform
> coordinated and  OS initiated.
> 
> This patch adds initial support for Platform coordination scheme of LPI.
> 
> Cc: "Rafael J. Wysocki" <rjw at rjwysocki.net>
> Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
> ---
>  drivers/acpi/bus.c              |  11 +-
>  drivers/acpi/processor_driver.c |   2 +-
>  drivers/acpi/processor_idle.c   | 441 +++++++++++++++++++++++++++++++++++-----
>  include/acpi/processor.h        |  25 ++-
>  include/linux/acpi.h            |   4 +
>  5 files changed, 422 insertions(+), 61 deletions(-)
> 
> Hi Rafael,
> 
> Yet to be discussed(retained as in from previous version):
> - Kconfig entry removal: Need feedback on how to deal with that
>   without having to introduce dummy _CST related ARM64 callbacks
> - Didn't defer processing of LPI buffers to flattening as it
>   results in the same buffer decoded multiple times
> - ACPI_CSTATE_INTEGER : IMO it's reasonable to keep it aroundsince the
>   it's part of LPI specification(not just ARM FFH)

I'm basically fine with the current set, up to some minor points.

I've sent my comments on patch [1/5] already.

My main concern about the flattening of _LPI is that at one point we'll
probably decide to unflatten it and that will change the behavior for
current users.  There needs to be a plan for that IMO.

> diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
> index c068c829b453..94fe6e0ccfd3 100644
> --- a/drivers/acpi/bus.c
> +++ b/drivers/acpi/bus.c
> @@ -302,6 +302,11 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
>  EXPORT_SYMBOL(acpi_run_osc);
>  
>  bool osc_sb_apei_support_acked;
> +/*
> + * ACPI 6.0 Section 8.4.4.2 Idle State Coordination
> + * OSPM supports platform coordinated low power idle(LPI) states
> + */
> +bool osc_pc_lpi_support_confirmed;
>  static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
>  static void acpi_bus_osc_support(void)
>  {
> @@ -322,6 +327,7 @@ static void acpi_bus_osc_support(void)
>  		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
>  
>  	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
> +	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT;
>  
>  	if (!ghes_disable)
>  		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
> @@ -329,9 +335,12 @@ static void acpi_bus_osc_support(void)
>  		return;
>  	if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
>  		u32 *capbuf_ret = context.ret.pointer;
> -		if (context.ret.length > OSC_SUPPORT_DWORD)
> +		if (context.ret.length > OSC_SUPPORT_DWORD) {
>  			osc_sb_apei_support_acked =
>  				capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
> +			osc_pc_lpi_support_confirmed =
> +				capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT;
> +		}
>  		kfree(context.ret.pointer);
>  	}
>  	/* do we need to check other returned cap? Sounds no */
> diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
> index d2fa8cb82d2b..0ca14ac7bb28 100644
> --- a/drivers/acpi/processor_driver.c
> +++ b/drivers/acpi/processor_driver.c
> @@ -90,7 +90,7 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
>  						  pr->performance_platform_limit);
>  		break;
>  	case ACPI_PROCESSOR_NOTIFY_POWER:
> -		acpi_processor_cst_has_changed(pr);
> +		acpi_processor_power_state_has_changed(pr);
>  		acpi_bus_generate_netlink_event(device->pnp.device_class,
>  						  dev_name(&device->dev), event, 0);
>  		break;
> diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
> index 1f3fe54194b5..5c78d68c7311 100644
> --- a/drivers/acpi/processor_idle.c
> +++ b/drivers/acpi/processor_idle.c
> @@ -303,7 +303,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
>  	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>  	union acpi_object *cst;
>  
> -
>  	if (nocst)
>  		return -ENODEV;
>  
> @@ -576,7 +575,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
>  	return (working);
>  }
>  
> -static int acpi_processor_get_power_info(struct acpi_processor *pr)
> +static int acpi_processor_get_cstate_info(struct acpi_processor *pr)
>  {
>  	unsigned int i;
>  	int result;
> @@ -810,31 +809,12 @@ static void acpi_idle_enter_freeze(struct cpuidle_device *dev,
>  	acpi_idle_do_entry(cx);
>  }
>  
> -/**
> - * acpi_processor_setup_cpuidle_cx - prepares and configures CPUIDLE
> - * device i.e. per-cpu data
> - *
> - * @pr: the ACPI processor
> - * @dev : the cpuidle device
> - */
>  static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
>  					   struct cpuidle_device *dev)
>  {
>  	int i, count = CPUIDLE_DRIVER_STATE_START;
>  	struct acpi_processor_cx *cx;
>  
> -	if (!pr->flags.power_setup_done)
> -		return -EINVAL;
> -
> -	if (pr->flags.power == 0) {
> -		return -EINVAL;
> -	}
> -
> -	if (!dev)
> -		return -EINVAL;
> -
> -	dev->cpu = pr->id;
> -
>  	if (max_cstate == 0)
>  		max_cstate = 1;
>  
> @@ -857,31 +837,13 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
>  	return 0;
>  }
>  
> -/**
> - * acpi_processor_setup_cpuidle states- prepares and configures cpuidle
> - * global state data i.e. idle routines
> - *
> - * @pr: the ACPI processor
> - */
> -static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
> +static int acpi_processor_setup_cstates(struct acpi_processor *pr)
>  {
>  	int i, count = CPUIDLE_DRIVER_STATE_START;
>  	struct acpi_processor_cx *cx;
>  	struct cpuidle_state *state;
>  	struct cpuidle_driver *drv = &acpi_idle_driver;
>  
> -	if (!pr->flags.power_setup_done)
> -		return -EINVAL;
> -
> -	if (pr->flags.power == 0)
> -		return -EINVAL;
> -
> -	drv->safe_state_index = -1;
> -	for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) {
> -		drv->states[i].name[0] = '\0';
> -		drv->states[i].desc[0] = '\0';
> -	}
> -
>  	if (max_cstate == 0)
>  		max_cstate = 1;
>  
> @@ -893,7 +855,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
>  
>  		state = &drv->states[count];
>  		snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i);
> -		strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
> +		strlcpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
>  		state->exit_latency = cx->latency;
>  		state->target_residency = cx->latency * latency_factor;
>  		state->enter = acpi_idle_enter;
> @@ -929,6 +891,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
>  static inline void acpi_processor_cstate_first_run_checks(void)
>  {
>  	static int first_run;
> +	acpi_status status;
>  
>  	if (first_run)
>  		return;
> @@ -951,7 +914,7 @@ static inline void acpi_processor_cstate_first_run_checks(void)
>  
>  static inline int disabled_by_idle_boot_param(void) { return 0; }
>  static inline void acpi_processor_cstate_first_run_checks(void) { }
> -static int acpi_processor_get_power_info(struct acpi_processor *pr)
> +static int acpi_processor_get_cstate_info(struct acpi_processor *pr)
>  {
>  	return -ENODEV;
>  }
> @@ -962,13 +925,386 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
>  	return -EINVAL;
>  }
>  
> -static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
> +static int acpi_processor_setup_cstates(struct acpi_processor *pr)
>  {
>  	return -EINVAL;
>  }
>  
>  #endif
>  
> +struct acpi_processor_lpi_info {
> +	int state_count;
> +	struct acpi_processor_lpi *lpix;
> +};

This is a bit cryptic, especially the name of the lpix field.

I'd do something like

struct acpi_lpi_states_array {
	unsigned int size;
	struct acpi_lpi_state *entries;
};

and that is sort of self-documenting.

> +
> +static int obj_get_integer(union acpi_object *obj, u32 *value)
> +{
> +	if (obj->type != ACPI_TYPE_INTEGER)
> +		return -EINVAL;

I'd add an empty line here and everywhere where there's only one
statement after if () or for () etc.

You've done that in some places IIRC, but please stick to one convention
everywhere.

> +	*value = obj->integer.value;
> +	return 0;
> +}
> +
> +static int acpi_processor_evaluate_lpi(acpi_handle handle,
> +				       struct acpi_processor_lpi_info *info)
> +{
> +	acpi_status status = 0;
> +	int ret = 0;
> +	int pkg_count, state_idx = 1, loop;
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +	union acpi_object *lpi;

I'd call this lpi_data.

> +	struct acpi_processor_lpi *lpix;

What about:

struct acpi_lpi_state *lpi_state;

> +
> +	status = acpi_evaluate_object(handle, "_LPI", NULL, &buffer);
> +	if (ACPI_FAILURE(status)) {
> +		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No _LPI, giving up\n"));
> +		return -ENODEV;
> +	}
> +
> +	lpi = buffer.pointer;
> +
> +	/* There must be at least 4 elements = 3 elements + 1 package */
> +	if (!lpi || lpi->type != ACPI_TYPE_PACKAGE || lpi->package.count < 4) {
> +		pr_debug("not enough elements in _LPI\n");
> +		ret = -ENXIO;

-ENODATA ?

> +		goto end;
> +	}
> +
> +	pkg_count = lpi->package.elements[2].integer.value;
> +
> +	/* Validate number of power states. */
> +	if (pkg_count < 1 || pkg_count != lpi->package.count - 3) {
> +		pr_debug("count given by _LPI is not valid\n");
> +		ret = -ENXIO;

And here.

> +		goto end;
> +	}
> +
> +	lpix = kcalloc(pkg_count, sizeof(*lpix), GFP_KERNEL);
> +	if (!lpix) {
> +		ret = -ENOMEM;
> +		goto end;
> +	}
> +
> +	info->state_count = pkg_count;
> +	info->lpix = lpix;
> +	/* LPI States start at index 3 */
> +	for (loop = 3; state_idx <= pkg_count; loop++, state_idx++, lpix++) {
> +		union acpi_object *element, *pkg_elem, *obj;
> +
> +		element = &lpi->package.elements[loop];
> +		if (element->type != ACPI_TYPE_PACKAGE)
> +			continue;
> +
> +		if (element->package.count < 7)
> +			continue;
> +
> +		pkg_elem = element->package.elements;
> +
> +		obj = pkg_elem + 6;
> +		if (obj->type == ACPI_TYPE_BUFFER) {
> +			struct acpi_power_register *reg;
> +
> +			reg = (struct acpi_power_register *)obj->buffer.pointer;
> +			if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO &&
> +			    (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
> +				continue;
> +			lpix->address = reg->address;
> +			if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE)
> +				lpix->entry_method = ACPI_CSTATE_FFH;
> +			else
> +				lpix->entry_method = ACPI_CSTATE_SYSTEMIO;
> +		} else if (obj->type == ACPI_TYPE_INTEGER) {
> +			lpix->entry_method = ACPI_CSTATE_INTEGER;
> +			lpix->address = obj->integer.value;
> +		} else {
> +			continue;
> +		}
> +
> +		/* elements[7,8] skipped for now i.e. Residency/Usage counter*/
> +
> +		obj = pkg_elem + 9;
> +		if (obj->type == ACPI_TYPE_STRING)
> +			strlcpy(lpix->desc, obj->string.pointer,
> +				ACPI_CX_DESC_LEN);
> +
> +		lpix->index = state_idx;
> +		if (obj_get_integer(pkg_elem + 0, &lpix->min_residency)) {
> +			pr_debug("No min. residency found, assuming 10 us\n");
> +			lpix->min_residency = 10;
> +		}
> +
> +		if (obj_get_integer(pkg_elem + 1, &lpix->wake_latency)) {
> +			pr_debug("No wakeup residency found, assuming 10 us\n");
> +			lpix->wake_latency = 10;
> +		}
> +
> +		if (obj_get_integer(pkg_elem + 2, &lpix->flags))
> +			lpix->flags = 0;
> +
> +		if (obj_get_integer(pkg_elem + 3, &lpix->arch_flags))
> +			lpix->arch_flags = 0;
> +
> +		if (obj_get_integer(pkg_elem + 4, &lpix->res_cnt_freq))
> +			lpix->res_cnt_freq = 1;
> +
> +		if (obj_get_integer(pkg_elem + 5, &lpix->enable_parent_state))
> +			lpix->enable_parent_state = 0;
> +	}
> +	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n",
> +			  state_idx));
> +end:
> +	kfree(buffer.pointer);
> +	return ret;
> +}
> +
> +static int max_leaf_depth, fl_scnt;

Add a comment describing these things?

> +/**
> + * combine_lpi_states - combine local and parent LPI states to form a
> + *			composite LPI state

One line, please.

> + * @l_lpi: local LPI state
> + * @p_lpi: parent LPI state
> + * @c_lpi: composite LPI state

I'd call these local, parent and result, respectively.

> + */
> +static void combine_lpi_states(struct acpi_processor_lpi *l_lpi,
> +			       struct acpi_processor_lpi *p_lpi,
> +			       struct acpi_processor_lpi *c_lpi)
> +{
> +	c_lpi->min_residency = max(l_lpi->min_residency, p_lpi->min_residency);
> +	c_lpi->wake_latency = l_lpi->wake_latency + p_lpi->wake_latency;
> +	c_lpi->enable_parent_state = p_lpi->enable_parent_state;
> +	c_lpi->entry_method = l_lpi->entry_method;
> +
> +	if (p_lpi->entry_method == ACPI_CSTATE_INTEGER)
> +		c_lpi->address = l_lpi->address + p_lpi->address;
> +	else
> +		c_lpi->address = p_lpi->address;
> +
> +	c_lpi->index = p_lpi->index;
> +	c_lpi->flags = p_lpi->flags;
> +	c_lpi->arch_flags = p_lpi->arch_flags;
> +
> +	strlcpy(c_lpi->desc, l_lpi->desc, ACPI_CX_DESC_LEN);
> +	strlcat(c_lpi->desc, "+", ACPI_CX_DESC_LEN);
> +	strlcat(c_lpi->desc, p_lpi->desc, ACPI_CX_DESC_LEN);
> +}
> +
> +#define ACPI_LPI_STATE_FLAGS_ENABLED			BIT(0)
> +
> +static int flatten_lpi_states(struct acpi_processor *pr,
> +			      struct acpi_processor_lpi_info *info,
> +			      struct acpi_processor_lpi *lpi,
> +			      uint32_t depth)
> +{
> +	int j, scount = info[depth].state_count;

state_count ?

> +	struct acpi_processor_lpi *t = info[depth].lpix;

struct acpi_lpi_state *lpi_state = states[depth].entries;

> +
> +	for (j = 0; j < scount; j++, t++) {
> +		struct acpi_processor_lpi *flpi;
> +		bool valid = false;
> +
> +		if (!(t->flags & ACPI_LPI_STATE_FLAGS_ENABLED))
> +			continue;
> +
> +		flpi = &pr->power.lpi_states[fl_scnt];
> +		if (depth == max_leaf_depth) { /* leaf/processor node */
> +			memcpy(flpi, t, sizeof(*t));
> +			fl_scnt++;
> +			valid = true;
> +		} else if (lpi && t->index <= lpi->enable_parent_state) {
> +			combine_lpi_states(lpi, t, flpi);
> +			fl_scnt++;
> +			valid = true;
> +		}
> +
> +		/*
> +		 * flatten recursively from leaf until the highest level
> +		 * (e.g. system) is reached
> +		 */
> +		if (valid && depth)
> +			flatten_lpi_states(pr, info, flpi, depth - 1);
> +	}
> +	return 0;
> +}
> +
> +static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
> +{
> +	int ret, i;
> +	struct acpi_processor_lpi_info *info;
> +	struct acpi_device *d = NULL;
> +	acpi_handle handle = pr->handle, pr_ahandle;
> +	acpi_status status;
> +
> +	if (!osc_pc_lpi_support_confirmed)
> +		return -EOPNOTSUPP;
> +
> +	max_leaf_depth = 0;
> +	if (!acpi_has_method(handle, "_LPI"))
> +		return -EINVAL;
> +	fl_scnt = 0;
> +
> +	while (ACPI_SUCCESS(status = acpi_get_parent(handle, &pr_ahandle))) {
> +		if (!acpi_has_method(handle, "_LPI"))
> +			continue;
> +		acpi_bus_get_device(handle, &d);
> +		if (!strcmp(acpi_device_hid(d), ACPI_PROCESSOR_CONTAINER_HID))
> +			break;
> +		max_leaf_depth++;
> +		handle = pr_ahandle;
> +	}
> +
> +	info = kcalloc(max_leaf_depth + 1, sizeof(*info), GFP_KERNEL);
> +	if (!info)
> +		return -ENOMEM;
> +
> +	pr_ahandle = pr->handle;
> +	for (i = max_leaf_depth; i >= 0 && ACPI_SUCCESS(status); i--) {
> +		handle = pr_ahandle;
> +		ret = acpi_processor_evaluate_lpi(handle, info + i);
> +		if (ret)
> +			break;
> +		status = acpi_get_parent(handle, &pr_ahandle);
> +	}
> +
> +	/* flatten all the LPI states in the entire hierarchy */
> +	flatten_lpi_states(pr, info, NULL, max_leaf_depth);
> +
> +	pr->power.count = fl_scnt;
> +	for (i = 0; i <= max_leaf_depth; i++)
> +		kfree(info[i].lpix);
> +	kfree(info);
> +
> +	/* Tell driver that _LPI is supported. */
> +	pr->flags.has_lpi = 1;
> +	pr->flags.power = 1;
> +
> +	return 0;
> +}
> +
> +int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu)
> +{
> +	return -ENODEV;
> +}
> +
> +int __weak acpi_processor_ffh_lpi_enter(struct acpi_processor_lpi *lpi, int idx)
> +{
> +	return -ENODEV;
> +}
> +
> +/**
> + * acpi_idle_lpi_enter - enters an ACPI any LPI state
> + * @dev: the target CPU
> + * @drv: cpuidle driver containing cpuidle state info
> + * @index: index of target state
> + *
> + * Return: 0 for success or negative value for error
> + */
> +static int acpi_idle_lpi_enter(struct cpuidle_device *dev,
> +			       struct cpuidle_driver *drv, int index)
> +{
> +	struct acpi_processor *pr;
> +	struct acpi_processor_lpi *lpi;
> +
> +	pr = __this_cpu_read(processors);
> +
> +	if (unlikely(!pr))
> +		return -EINVAL;
> +
> +	lpi = &pr->power.lpi_states[index];
> +	if (lpi->entry_method == ACPI_CSTATE_FFH)
> +		/* Call into architectural FFH based C-state */

The comment is not necessary here.

> +		return acpi_processor_ffh_lpi_enter(lpi, index);
> +	return -EINVAL;
> +}
> +
> +static int acpi_processor_setup_lpi_states(struct acpi_processor *pr)
> +{
> +	int i;
> +	struct acpi_processor_lpi *lpi;
> +	struct cpuidle_state *state;
> +	struct cpuidle_driver *drv = &acpi_idle_driver;
> +
> +	if (!pr->flags.has_lpi)
> +		return -EOPNOTSUPP;
> +
> +	for (i = 0; i < fl_scnt && i < CPUIDLE_STATE_MAX; i++) {
> +		lpi = &pr->power.lpi_states[i];
> +
> +		state = &drv->states[i];
> +		snprintf(state->name, CPUIDLE_NAME_LEN, "LPI-%d", i);
> +		strlcpy(state->desc, lpi->desc, CPUIDLE_DESC_LEN);
> +		state->exit_latency = lpi->wake_latency;
> +		state->target_residency = lpi->min_residency;
> +		if (lpi->arch_flags)
> +			state->flags |= CPUIDLE_FLAG_TIMER_STOP;
> +		state->enter = acpi_idle_lpi_enter;

No ->enter_freeze ?

> +		drv->safe_state_index = i;
> +	}
> +
> +	drv->state_count = i;
> +
> +	return 0;
> +}
> +
> +/**
> + * acpi_processor_setup_cpuidle_states- prepares and configures cpuidle
> + * global state data i.e. idle routines
> + *
> + * @pr: the ACPI processor
> + */
> +static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
> +{
> +	int i;
> +	struct cpuidle_driver *drv = &acpi_idle_driver;
> +
> +	if (!pr->flags.power_setup_done)
> +		return -EINVAL;
> +
> +	if (pr->flags.power == 0)
> +		return -EINVAL;
> +
> +	drv->safe_state_index = -1;
> +	for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) {
> +		drv->states[i].name[0] = '\0';
> +		drv->states[i].desc[0] = '\0';
> +	}
> +
> +	if (pr->flags.has_lpi)
> +		return acpi_processor_setup_lpi_states(pr);
> +	return acpi_processor_setup_cstates(pr);
> +}
> +
> +/**
> + * acpi_processor_setup_cpuidle_dev - prepares and configures CPUIDLE
> + * device i.e. per-cpu data
> + *
> + * @pr: the ACPI processor
> + * @dev : the cpuidle device
> + */
> +static int acpi_processor_setup_cpuidle_dev(struct acpi_processor *pr,
> +					    struct cpuidle_device *dev)
> +{
> +	if (!pr->flags.power_setup_done)
> +		return -EINVAL;
> +
> +	if (pr->flags.power == 0)
> +		return -EINVAL;
> +
> +	if (!dev)
> +		return -EINVAL;
> +
> +	dev->cpu = pr->id;
> +	if (pr->flags.has_lpi)
> +		return acpi_processor_ffh_lpi_probe(pr->id);
> +	return acpi_processor_setup_cpuidle_cx(pr, dev);
> +}
> +
> +static int acpi_processor_get_power_info(struct acpi_processor *pr)
> +{
> +	if (acpi_processor_get_lpi_info(pr))
> +		return acpi_processor_get_cstate_info(pr);
> +	return 0;

ret = acpi_processor_get_lpi_info(pr);
if (ret)
	ret = acpi_processor_get_cstate_info(pr);

return ret;

> +}
> +
>  int acpi_processor_hotplug(struct acpi_processor *pr)
>  {
>  	int ret = 0;
> @@ -977,18 +1313,15 @@ int acpi_processor_hotplug(struct acpi_processor *pr)
>  	if (disabled_by_idle_boot_param())
>  		return 0;
>  
> -	if (nocst)
> -		return -ENODEV;
> -
>  	if (!pr->flags.power_setup_done)
>  		return -ENODEV;
>  
>  	dev = per_cpu(acpi_cpuidle_device, pr->id);
>  	cpuidle_pause_and_lock();
>  	cpuidle_disable_device(dev);
> -	acpi_processor_get_power_info(pr);
> -	if (pr->flags.power) {
> -		acpi_processor_setup_cpuidle_cx(pr, dev);
> +	ret = acpi_processor_get_power_info(pr);
> +	if (!ret && pr->flags.power) {
> +		acpi_processor_setup_cpuidle_dev(pr, dev);
>  		ret = cpuidle_enable_device(dev);
>  	}
>  	cpuidle_resume_and_unlock();
> @@ -996,7 +1329,7 @@ int acpi_processor_hotplug(struct acpi_processor *pr)
>  	return ret;
>  }
>  
> -int acpi_processor_cst_has_changed(struct acpi_processor *pr)
> +int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
>  {
>  	int cpu;
>  	struct acpi_processor *_pr;
> @@ -1005,9 +1338,6 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
>  	if (disabled_by_idle_boot_param())
>  		return 0;
>  
> -	if (nocst)
> -		return -ENODEV;
> -
>  	if (!pr->flags.power_setup_done)
>  		return -ENODEV;
>  
> @@ -1044,7 +1374,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
>  			acpi_processor_get_power_info(_pr);
>  			if (_pr->flags.power) {
>  				dev = per_cpu(acpi_cpuidle_device, cpu);
> -				acpi_processor_setup_cpuidle_cx(_pr, dev);
> +				acpi_processor_setup_cpuidle_dev(_pr, dev);
>  				cpuidle_enable_device(dev);
>  			}
>  		}
> @@ -1059,7 +1389,6 @@ static int acpi_processor_registered;
>  
>  int acpi_processor_power_init(struct acpi_processor *pr)
>  {
> -	acpi_status status;
>  	int retval;
>  	struct cpuidle_device *dev;
>  
> @@ -1092,7 +1421,7 @@ int acpi_processor_power_init(struct acpi_processor *pr)
>  			return -ENOMEM;
>  		per_cpu(acpi_cpuidle_device, pr->id) = dev;
>  
> -		acpi_processor_setup_cpuidle_cx(pr, dev);
> +		acpi_processor_setup_cpuidle_dev(pr, dev);
>  
>  		/* Register per-cpu cpuidle_device. Cpuidle driver
>  		 * must already be registered before registering device
> diff --git a/include/acpi/processor.h b/include/acpi/processor.h
> index 50f2423d31fa..7dd1e63199ed 100644
> --- a/include/acpi/processor.h
> +++ b/include/acpi/processor.h
> @@ -39,6 +39,7 @@
>  #define ACPI_CSTATE_SYSTEMIO	0
>  #define ACPI_CSTATE_FFH		1
>  #define ACPI_CSTATE_HALT	2
> +#define ACPI_CSTATE_INTEGER	3
>  
>  #define ACPI_CX_DESC_LEN	32
>  
> @@ -67,9 +68,25 @@ struct acpi_processor_cx {
>  	char desc[ACPI_CX_DESC_LEN];
>  };
>  
> +struct acpi_processor_lpi {

As I said above, I'd call this

struct acpi_lpi_state {

because (a) it represents a state and (b) that doesn't have to be a state
of a processor.

> +	u32 min_residency;
> +	u32 wake_latency; /* worst case */
> +	u32 flags;
> +	u32 arch_flags;
> +	u32 res_cnt_freq;
> +	u32 enable_parent_state;
> +	u64 address;
> +	u8 index;
> +	u8 entry_method;
> +	char desc[ACPI_CX_DESC_LEN];
> +};
> +
>  struct acpi_processor_power {
>  	int count;
> -	struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
> +	union {
> +		struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
> +		struct acpi_processor_lpi lpi_states[ACPI_PROCESSOR_MAX_POWER];
> +	};
>  	int timer_broadcast_on_state;
>  };
>  
> @@ -189,6 +206,7 @@ struct acpi_processor_flags {
>  	u8 bm_control:1;
>  	u8 bm_check:1;
>  	u8 has_cst:1;
> +	u8 has_lpi:1;
>  	u8 power_setup_done:1;
>  	u8 bm_rld_set:1;
>  	u8 need_hotplug_init:1;
> @@ -372,7 +390,7 @@ extern struct cpuidle_driver acpi_idle_driver;
>  #ifdef CONFIG_ACPI_PROCESSOR_IDLE
>  int acpi_processor_power_init(struct acpi_processor *pr);
>  int acpi_processor_power_exit(struct acpi_processor *pr);
> -int acpi_processor_cst_has_changed(struct acpi_processor *pr);
> +int acpi_processor_power_state_has_changed(struct acpi_processor *pr);
>  int acpi_processor_hotplug(struct acpi_processor *pr);
>  #else
>  static inline int acpi_processor_power_init(struct acpi_processor *pr)
> @@ -385,7 +403,8 @@ static inline int acpi_processor_power_exit(struct acpi_processor *pr)
>  	return -ENODEV;
>  }
>  
> -static inline int acpi_processor_cst_has_changed(struct acpi_processor *pr)
> +static inline int
> +acpi_processor_power_state_has_changed(struct acpi_processor *pr)

Please don't break lines like this.  It doesn't hurt if it is longer that 80 chars.

>  {
>  	return -ENODEV;
>  }
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 06ed7e54033e..127fdc04e2b5 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -452,8 +452,12 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
>  #define OSC_SB_HOTPLUG_OST_SUPPORT		0x00000008
>  #define OSC_SB_APEI_SUPPORT			0x00000010
>  #define OSC_SB_CPC_SUPPORT			0x00000020
> +#define OSC_SB_CPCV2_SUPPORT			0x00000040
> +#define OSC_SB_PCLPI_SUPPORT			0x00000080
> +#define OSC_SB_OSLPI_SUPPORT			0x00000100
>  
>  extern bool osc_sb_apei_support_acked;
> +extern bool osc_pc_lpi_support_confirmed;
>  
>  /* PCI Host Bridge _OSC: Capabilities DWORD 2: Support Field */
>  #define OSC_PCI_EXT_CONFIG_SUPPORT		0x00000001
> 

Thanks,
Rafael



From briannorris at chromium.org  Tue May 10 17:02:54 2016
From: briannorris at chromium.org (Brian Norris)
Date: Tue, 10 May 2016 17:02:54 -0700
Subject: [PATCH 1/2] ARM64: dts: rockchip: add sdhci/emmc for rk3399
Message-ID: <1462924975-69072-1-git-send-email-briannorris@chromium.org>

The bindings for rk3399's SDHCI + eMMC PHY have been accepted, so let's
support eMMC now.

Note that 'rockchip,rk3399-sdhci-5.1' is not documented, but per Heiko's
previous suggestion, we don't want to clutter the arasan doc, and it's
just a precautionary measure to have it.

Signed-off-by: Brian Norris <briannorris at chromium.org>
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 46f325a143b0..947d1221592d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -215,6 +215,17 @@
 		status = "disabled";
 	};
 
+	sdhci: sdhci at fe330000 {
+		compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
+		reg = <0x0 0xfe330000 0x0 0x10000>;
+		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;
+		clock-names = "clk_xin", "clk_ahb";
+		phys = <&emmc_phy>;
+		phy-names = "phy_arasan";
+		status = "disabled";
+	};
+
 	usb_host0_ehci: usb at fe380000 {
 		compatible = "generic-ehci";
 		reg = <0x0 0xfe380000 0x0 0x20000>;
@@ -481,8 +492,18 @@
 	};
 
 	grf: syscon at ff770000 {
-		compatible = "rockchip,rk3399-grf", "syscon";
+		compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
 		reg = <0x0 0xff770000 0x0 0x10000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		emmc_phy: phy at f780 {
+			compatible = "rockchip,rk3399-emmc-phy";
+			reg = <0xf780 0x20>;
+			#phy-cells = <0>;
+			status = "disabled";
+		};
 	};
 
 	watchdog at ff840000 {
-- 
2.8.0.rc3.226.g39d4020



From briannorris at chromium.org  Tue May 10 17:02:55 2016
From: briannorris at chromium.org (Brian Norris)
Date: Tue, 10 May 2016 17:02:55 -0700
Subject: [PATCH 2/2] ARM64: dts: rockchip: enable eMMC for rk3399 EVB
In-Reply-To: <1462924975-69072-1-git-send-email-briannorris@chromium.org>
References: <1462924975-69072-1-git-send-email-briannorris@chromium.org>
Message-ID: <1462924975-69072-2-git-send-email-briannorris@chromium.org>

The 'mmc-hs400-enhanced-strobe' property has been acked by Rob Herring,
though it's still not merged.

Signed-off-by: Brian Norris <briannorris at chromium.org>
---
 arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
index 1a3eb1482050..ccfd2bcf02e1 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
@@ -89,6 +89,18 @@
 	status = "okay";
 };
 
+&emmc_phy {
+	status = "okay";
+};
+
+&sdhci {
+	bus-width = <8>;
+	mmc-hs400-1_8v;
+	non-removable;
+	mmc-hs400-enhanced-strobe;
+	status = "okay";
+};
+
 &uart2 {
 	status = "okay";
 };
-- 
2.8.0.rc3.226.g39d4020



From rjw at rjwysocki.net  Tue May 10 17:07:38 2016
From: rjw at rjwysocki.net (Rafael J. Wysocki)
Date: Wed, 11 May 2016 02:07:38 +0200
Subject: [PATCH v4 4/5] arm64: add support for ACPI Low Power Idle(LPI)
In-Reply-To: <1461069013-13292-5-git-send-email-sudeep.holla@arm.com>
References: <1461069013-13292-1-git-send-email-sudeep.holla@arm.com>
 <1461069013-13292-5-git-send-email-sudeep.holla@arm.com>
Message-ID: <3620725.8soc3SaFWB@vostro.rjw.lan>

On Tuesday, April 19, 2016 01:30:12 PM Sudeep Holla wrote:
> This patch adds appropriate callbacks to support ACPI Low Power Idle
> (LPI) on ARM64.
> 
> It also selects ARCH_SUPPORTS_ACPI_PROCESSOR_LPI if ACPI is enabled
> on ARM64.

Can you remind me why we need the ARCH_SUPPORTS_ACPI_PROCESSOR_LPI thing in
addition to the previously defined ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE?

I thought supporting LPI would not require an arch Kconfig option.

Thanks,
Rafael



From rafael at kernel.org  Tue May 10 17:43:11 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Wed, 11 May 2016 02:43:11 +0200
Subject: [PATCH v6 00/14] ACPI NUMA support for ARM64
In-Reply-To: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <CAJZ5v0iMDQ4pWip4vyCos0o+1DFDvXQf4XZQqC4SGjJsDO4Lnw@mail.gmail.com>

On Wed, Apr 27, 2016 at 8:07 PM, David Daney <ddaney.cavm at gmail.com> wrote:
> From: David Daney <david.daney at cavium.com>
>
> Based on git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
> for-next/core branch at commit 643d703d2d2d ("arm64: compat: Check for
> AArch32 state")
>
> ACPI 5.1 already introduced NUMA support for ARM64, which can get the
> NUMA domain information from SRAT and SLIT table, so parse those two
> tables to get mappings from cpu/mem to numa node configuration and
> system locality.
>
> v6 updates:
>
>  - Changed message printed in 13/14 to omit meaningless "cpu"
>    number. (noted by Dennis Chen and Hanjun Guo)
>
>  - New patch 7/14 to print different messages for NUMA disabled case.
>    (noted by Dennis Chen)
>
>  - Squashed two patches into 14/14.
>
>  - Added Reviewed-by to 4/14
>
> v5 updates:
>
>  - Fixed ia64 build failure by gating some unused functions with #if
>    CONFIG_{X86,ARM64}.
>
>  - Fixed section mismatch errors for X86 case.
>
>  - Removed unneeded #include from some files.
>
>  - Tested to build cleanly on ARM64, X86_64, IA64
>
> v4 updates:
>
>  - Updated from Hanjun Guo's v3 patches.
>
>  - Rebased on top of v16 of device-tree NUMA patches.
>
>  - Reordered some of the changes so that we don't introduce code and
>    then change it several times in the patch set.  New code is
>    introduced in its final form.  Code reused from x86 is first moved
>    with no change, and then a separate patch to make any needed
>    changes.
>
>  - code that is used only by ia64, moved to architecture specific
>    files.
>
> v3 updates:
>  - Deep investigation about the ACPI_DEBUG_PRINT() and remvoe
>    that for acpi/numa.c (patch 2/12)
>
>  - Remove the duplicate NULL check for table print (patch 3/12)
>
>  - Introduce CONFIG_ACPI_HAS_NUMA_ARCH_FIXUP to remove duplicate
>    dummy function for acpi_numa_arch_fixup()
>
>  - Solve the problem that the mapping from logical cpu to numa node
>    is wrong which spotted out by Lorenzo
>
>  - cleanups for x86 and move acpi_numa_slit_init() and some other
>    functions to common place, then reduce the duplicate of x86
>    and arm64 (patch 7-12/12).
>
>  - rebased on top of 4.4 and Ganapat's v9 patch set.
>
>
> David Daney (2):
>   arm64, numa: Cleanup NUMA disabled messages.
>   acpi, numa, srat: Improve SRAT error detection and add messages.
>
> Hanjun Guo (11):
>   acpi, numa: Use pr_fmt() instead of printk
>   acpi, numa: Replace ACPI_DEBUG_PRINT() with pr_debug()
>   acpi, numa: remove duplicate NULL check
>   acpi, numa: move acpi_numa_slit_init() to drivers/acpi/numa.c
>   arm64, numa: rework numa_add_memblk()
>   x86, acpi, numa: cleanup acpi_numa_processor_affinity_init()
>   acpi, numa: move bad_srat() and srat_disabled() to
>     drivers/acpi/numa.c
>   acpi, numa: remove unneeded acpi_numa=1
>   acpi, numa: Move acpi_numa_memory_affinity_init() to
>     drivers/acpi/numa.c
>   arm64, acpi, numa: NUMA support based on SRAT and SLIT
>   acpi, numa: Enable ACPI based NUMA on ARM64
>
> Robert Richter (1):
>   acpi, numa: Move acpi_numa_arch_fixup() to ia64 only

I need ACKs from the ARM64 maintainers on patches [6-7/13] and [13-14/14].

The rest looks good to me, so I can apply the series once the above
have been ACKed.

Thanks,
Rafael


From takahiro.akashi at linaro.org  Tue May 10 17:53:35 2016
From: takahiro.akashi at linaro.org (AKASHI Takahiro)
Date: Wed, 11 May 2016 09:53:35 +0900
Subject: Help needed with kexec on arm64
In-Reply-To: <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>
References: <DB5PR04MB168845795D86B4CE5BA5656FE68B0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <1458230896.3391.18.camel@infradead.org>
 <CAB5YjtBEO=efjhcFdVOaZqG13qK3uzCbS5SFym5hhw-n+_QLhw@mail.gmail.com>
 <DB5PR04MB1688A6D4385B76DAFF71D364E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org>
 <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>
Message-ID: <20160511005334.GA8417@linaro.org>

Hi,

On Tue, May 10, 2016 at 12:32:15PM +0000, Harninder Rai wrote:
> > 
> > This means that there is no enough space left at this point.
> > I guess that you are using too big initramfs against 64MB of total memory.
> > Just increase the memory size for crash dump kernel.
> > 
> > -Takahiro AKASHI
> 
> Hello Takahiro Akashi,
> 
> I used a smaller initramfs (as you suggested) and my crash kernel has moved further but it again dumped with the following log messages. Any further pointers?

It seems that you have already reached the point of kicking up "init"
process, and this means that crash dump kernel itself successfully
booted.

> Does this mean that there isn't enough memory to save the core file or something? Because the error mostly are related to OOM killer process

Apparently lack of memory is a cause of OOM killer, but the core file
has nothing to do with this issue.
I think that you don't have enough memory for the system yet.

-Takahiro AKASHI

> 
> [    8.833434] Freeing unused kernel memory: 748K (ffff800000a3a000 - ffff800000af5000)
> [    8.848924] init: Console is alive
> [    8.856866] mmc0: new high speed SDHC card at address b368
> [    8.868239] mmcblk0: mmc0:b368 SDC   3.75 GiB
> [    8.873913]  mmcblk0: p1
> [    9.855930] init: - preinit -
> Press the [f] key and hit [enter] to enter failsafe mode
> Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level
> [   12.896779] procd: - early -
> [   12.977417] kworker/u16:0 invoked oom-killer: gfp_mask=0x27000c0, order=2, oom_score_adj=0
> [   12.994568] CPU: 0 PID: 6 Comm: kworker/u16:0 Not tainted 4.5.0-rc6-00038-gae2804a-dirty #5
> [   13.002950] Hardware name: Freescale Layerscape 2085a RDB Board (DT)
> [   13.009333] Workqueue: events_unbound call_usermodehelper_exec_work
> [   13.015623] Call trace:
> [   13.018076] [<ffff800000089760>] dump_backtrace+0x0/0x1ac
> [   13.023492] [<ffff800000089920>] show_stack+0x14/0x1c
> [   13.028560] [<ffff80000032c1d4>] dump_stack+0x8c/0xb0
> [   13.033627] [<ffff8000001aebdc>] dump_header.isra.7+0x4c/0x18c
> [   13.039480] [<ffff800000152130>] oom_kill_process+0x26c/0x45c
> [   13.045243] [<ffff800000152688>] out_of_memory+0x2e0/0x32c
> [   13.050745] [<ffff800000156c68>] __alloc_pages_nodemask+0x83c/0x848
> [   13.057031] [<ffff800000156f78>] alloc_kmem_pages_node+0x30/0xa8
> [   13.063058] [<ffff8000000b776c>] copy_process.isra.42.part.43+0x128/0x1488
> [   13.069955] [<ffff8000000b8c4c>] _do_fork+0xcc/0x338
> [   13.074934] [<ffff8000000b8f04>] kernel_thread+0x34/0x3c
> [   13.080261] [<ffff8000000cb8e0>] call_usermodehelper_exec_work+0x2c/0xd8
> [   13.086984] [<ffff8000000ce4b0>] process_one_work+0x134/0x2f4
> [   13.092747] [<ffff8000000ce6c8>] worker_thread+0x58/0x43c
> [   13.098162] [<ffff8000000d3f88>] kthread+0xd8/0xec
> [   13.102967] [<ffff800000085cd0>] ret_from_fork+0x10/0x40
> [   13.261745] Mem-Info:
> 
> Thanks and Regards
> Harry++

-- 
Thanks,
-Takahiro AKASHI


From shawn.lin at rock-chips.com  Tue May 10 17:59:24 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Wed, 11 May 2016 08:59:24 +0800
Subject: [PATCH 2/2] ARM64: dts: rockchip: enable eMMC for rk3399 EVB
In-Reply-To: <1462924975-69072-2-git-send-email-briannorris@chromium.org>
References: <1462924975-69072-1-git-send-email-briannorris@chromium.org>
 <1462924975-69072-2-git-send-email-briannorris@chromium.org>
Message-ID: <d8dc5609-3cf6-80ce-462b-d46f0ea6dcff@rock-chips.com>

On 2016/5/11 8:02, Brian Norris wrote:
> The 'mmc-hs400-enhanced-strobe' property has been acked by Rob Herring,
> though it's still not merged.
>

Hi Brain,

I'm not sure whether it's acceptable to upstream new property which
isn't merged yet. My major concern is that as the patchset supporting
h400es will go through mmc tree, so if Ulf should want to shorten the
name (e.g mmc-hs400-es), you would respin this patch.


Thanks.

> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
>  arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> index 1a3eb1482050..ccfd2bcf02e1 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> @@ -89,6 +89,18 @@
>  	status = "okay";
>  };
>
> +&emmc_phy {
> +	status = "okay";
> +};
> +
> +&sdhci {
> +	bus-width = <8>;
> +	mmc-hs400-1_8v;
> +	non-removable;
> +	mmc-hs400-enhanced-strobe;
> +	status = "okay";
> +};
> +
>  &uart2 {
>  	status = "okay";
>  };
>


-- 
Best Regards
Shawn Lin



From shawn.lin at rock-chips.com  Tue May 10 18:17:38 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Wed, 11 May 2016 09:17:38 +0800
Subject: [PATCH 1/2] ARM64: dts: rockchip: add sdhci/emmc for rk3399
In-Reply-To: <1462924975-69072-1-git-send-email-briannorris@chromium.org>
References: <1462924975-69072-1-git-send-email-briannorris@chromium.org>
Message-ID: <3e257ce2-056a-592a-9481-970da1fe0627@rock-chips.com>

+ Huang Lin

On 2016/5/11 8:02, Brian Norris wrote:
> The bindings for rk3399's SDHCI + eMMC PHY have been accepted, so let's
> support eMMC now.
>
> Note that 'rockchip,rk3399-sdhci-5.1' is not documented, but per Heiko's
> previous suggestion, we don't want to clutter the arasan doc, and it's
> just a precautionary measure to have it.
>
> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
>  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> index 46f325a143b0..947d1221592d 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -215,6 +215,17 @@
>  		status = "disabled";
>  	};
>
> +	sdhci: sdhci at fe330000 {
> +		compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
> +		reg = <0x0 0xfe330000 0x0 0x10000>;
> +		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;

sdhci doesn't call clk_set_rate to explicitly assign clk_xin to 200MHz
as it always assumes sdhci controller should meet the highest speed of
each timing mode. And the internal divider will be used. So IMHO,
clk-rockchip for 3399 *haven't* made clk_xin to be 200MHz. Let's assign
the clk stuff to make sure it's 200MHz.

Another problem is that emmc_phy contains a configuration which should
be consistent with clk_out(namely clk_xin/internal dividor). Now I don't
submit unpstream patchset to expose these configurarion, but in
prevention of some misleading, I think it's better to to it.

How about adding these?

assigned-clocks = <&cru SCLK_EMMC>;
assigned-clock-parents = <&cru PLL_CPLL>; //may not need
assigned-clock-rates = <200000000>;

Still you limit your clk_out by adding max-frequency in dts for
specific requirment.

We here manually assigne the clk_xin to be 200MHz, so defaultly
when it's runing in HS200/HS400(ES) mode, internal divider won't
be used(by-pass mode). So the clk jitter is better when by-passing the
clock.

Thanks.

> +		clock-names = "clk_xin", "clk_ahb";
> +		phys = <&emmc_phy>;
> +		phy-names = "phy_arasan";
> +		status = "disabled";
> +	};
> +
>  	usb_host0_ehci: usb at fe380000 {
>  		compatible = "generic-ehci";
>  		reg = <0x0 0xfe380000 0x0 0x20000>;
> @@ -481,8 +492,18 @@
>  	};
>
>  	grf: syscon at ff770000 {
> -		compatible = "rockchip,rk3399-grf", "syscon";
> +		compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
>  		reg = <0x0 0xff770000 0x0 0x10000>;
> +
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +
> +		emmc_phy: phy at f780 {
> +			compatible = "rockchip,rk3399-emmc-phy";
> +			reg = <0xf780 0x20>;
> +			#phy-cells = <0>;
> +			status = "disabled";
> +		};
>  	};
>
>  	watchdog at ff840000 {
>


-- 
Best Regards
Shawn Lin



From briannorris at chromium.org  Tue May 10 18:19:19 2016
From: briannorris at chromium.org (Brian Norris)
Date: Tue, 10 May 2016 18:19:19 -0700
Subject: [PATCH 2/2] ARM64: dts: rockchip: enable eMMC for rk3399 EVB
In-Reply-To: <d8dc5609-3cf6-80ce-462b-d46f0ea6dcff@rock-chips.com>
References: <1462924975-69072-1-git-send-email-briannorris@chromium.org>
 <1462924975-69072-2-git-send-email-briannorris@chromium.org>
 <d8dc5609-3cf6-80ce-462b-d46f0ea6dcff@rock-chips.com>
Message-ID: <20160511011919.GB77327@google.com>

Hi,

On Wed, May 11, 2016 at 08:59:24AM +0800, Shawn Lin wrote:
> On 2016/5/11 8:02, Brian Norris wrote:
> >The 'mmc-hs400-enhanced-strobe' property has been acked by Rob Herring,
> >though it's still not merged.
> >
> 
> Hi Brain,
> 
> I'm not sure whether it's acceptable to upstream new property which
> isn't merged yet. My major concern is that as the patchset supporting
> h400es will go through mmc tree, so if Ulf should want to shorten the
> name (e.g mmc-hs400-es), you would respin this patch.


Well, Heiko can determine when to accept this. I wanted to post it to
get things moving, but I can drop that property for now if it's going to
cause difficulty.

> Thanks.
> 
> >Signed-off-by: Brian Norris <briannorris at chromium.org>
> >---

BTW, I meant to note here that I haven't personally tested this EVB. I
have tested other boards. This patch mostly serves the purpose of an
example user, for my purposes.

Brian

> > arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 12 ++++++++++++
> > 1 file changed, 12 insertions(+)
> >
> >diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> >index 1a3eb1482050..ccfd2bcf02e1 100644
> >--- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> >+++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> >@@ -89,6 +89,18 @@
> > 	status = "okay";
> > };
> >
> >+&emmc_phy {
> >+	status = "okay";
> >+};
> >+
> >+&sdhci {
> >+	bus-width = <8>;
> >+	mmc-hs400-1_8v;
> >+	non-removable;
> >+	mmc-hs400-enhanced-strobe;
> >+	status = "okay";
> >+};
> >+
> > &uart2 {
> > 	status = "okay";
> > };
> >
> 
> 
> -- 
> Best Regards
> Shawn Lin
> 


From yamada.masahiro at socionext.com  Tue May 10 18:51:51 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Wed, 11 May 2016 10:51:51 +0900
Subject: [RFC PATCH 01/21] mfd: uniphier: add UniPhier MFD driver
In-Reply-To: <20160510112622.GL19473@dell>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
 <1462873862-30940-2-git-send-email-yamada.masahiro@socionext.com>
 <20160510112622.GL19473@dell>
Message-ID: <CAK7LNATmuN647=avdqAMahLU+9Bq4m4TkXe5f7q=pi8m=UrXBg@mail.gmail.com>

Hi Lee,

2016-05-10 20:26 GMT+09:00 Lee Jones <lee.jones at linaro.org>:
>> +};
>> +MODULE_DEVICE_TABLE(of, uniphier_mfd_match);
>
> NACK.  Please do not mix MFD and DT registration.

OK, thanks for review.


My basic thought was:

  - Add an MFD node to my DTS only once.
    If I need to expand it in the future, I will just
    need to modify drivers/mtd/uniphier-mfd.c.
    It is just kernel-internal modification, so it does not
    bother DT binding at all.

  - Simplify the node topology of DTS.

-- 
Best Regards
Masahiro Yamada


From bamvor.zhangjian at huawei.com  Tue May 10 19:04:16 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Wed, 11 May 2016 10:04:16 +0800
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <4119683.coHZhzaE6c@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <7091358.aJt1stteb5@wuerfel> <5731D68D.2090109@huawei.com>
 <4119683.coHZhzaE6c@wuerfel>
Message-ID: <57329320.1000500@huawei.com>

Hi,

On 2016/5/10 20:50, Arnd Bergmann wrote:
> On Tuesday 10 May 2016 20:39:41 Zhangjian wrote:
>> Hi,
>>
>> On 2016/5/10 19:48, Arnd Bergmann wrote:
>>> On Tuesday 10 May 2016 17:47:26 Zhangjian wrote:
>>>> On 2016/5/10 16:36, Arnd Bergmann wrote:
>>>>> On Tuesday 10 May 2016 15:42:07 Zhangjian wrote:
>>>>>> On 2016/5/6 20:37, Yury Norov wrote:
>>>>
>>>> "include/uapi/asm-generic/posix_types.h" is uapi, we could not check
>>>> "ARCH_32BIT_OFF_T" here. Besides, the `__kernel_long_t` is long which
>>>> mean it is 32bit in ILP32. should we define something like x32?
>>>>        ```
>>>>        diff --git a/arch/arm64/include/uapi/asm/posix_types.h b/arch/arm64/include/uapi/asm/posix_types.h
>>>>        index 7985ff6..9baa8d3 100644
>>>>        --- a/arch/arm64/include/uapi/asm/posix_types.h
>>>>        +++ b/arch/arm64/include/uapi/asm/posix_types.h
>>>
>>> glibc does not use the definition of __kernel_off_t, it has its own
>>> copy, so changing the kernel headers would do nothing.
>> Yes, I think so. I am puzzle that how do we ensure that all the new
>> 32bit architecture will define off_t as 64bit after introduce
>> ARCH_32BIT_OFF_T and do not change any other code?
>
> This is for historic reasons: we have two sets of system calls passing
> file offsets: the original ones passing a 'long' are named e.g. lseek,
> pread, pwrite, fadvise, ...
>
> The replacement syscalls that pass a 'long long' __kernel_loff_t are only
> available on 32-bit architectures and have different names, e.g. llseek,
> pread64, pwrite64, fadvise64, ...
>
> On 64-bit architectures, we only provide the first set, because
> __kernel_off_t was already wide enough. On old 32-bit architectures
> we have both, and on new 32-bit architectures we only have the second
> set, which lets us use the same definitions on all 32-bit architectures.
>
>>>>        @@ -5,6 +5,9 @@ typedef unsigned short __kernel_old_uid_t;
>>>>         typedef unsigned short __kernel_old_gid_t;
>>>>          #define __kernel_old_uid_t __kernel_old_uid_t
>>>>
>>>>         +typedef long long __kernel_long_t;
>>>>         +typedef unsigned long long __kernel_ulong_t;
>>>>         +
>>>>          #include <asm-generic/posix_types.h>
>>>>
>>>>          #endif /*  __ASM_POSIX_TYPES_H */u
>>>>        ```
>>>
>>> This would break all sorts of things, because __kernel_long_t/__kernel_ulong_t
>>> are not just used for off_t but also other things.
>> Yes. But if we do not change __kernel_long_t and __kernel_ulong_t, the
>> application of ilp32 will think size of long in kernel is 32bit. Is that
>> correct?
>
> No, __kernel_long_t refers to the definition of 'long' in the kernel/user
> ABI, not in the kernel (except on the x86-64 "x32" ABI, which is weird).
Thanks, that is answer my question. I ask this because I saw the posix_types.h
for x32.
> A 32-bit user space application must not care about how 'long' is defined
> in the kernel, it should run on either 32-bit kernels or 64-bit kernels.
> We don't have any plans to do an ilp32-mode kernel, but if we ever want
> one, it must use the exact same ABI as the 64-bit kernel when running
> ilp32 user space.
>
>>>>
>>>> On the other hand, glibc define it own off_t in "bits/types.h":
>>>>        __STD_TYPE __OFF_T_TYPE __off_t;        /* Type of file sizes and offsets.  */
>>>>        __STD_TYPE __OFF64_T_TYPE __off64_t;    /* Type of file sizes and offsets (LFS).  */
>>>>
>>>> in "sysdeps/unix/sysv/linux/aarch64/bits/typesizes.h":
>>>>        #define __OFF_T_TYPE            __SLONGWORD_TYPE
>>>>        #define __OFF64_T_TYPE          __SQUAD_TYPE
>>>>
>>>> If we define off_t as 64bit in glibc:
>>>>        #define __OFF_T_TYPE           __SQUAD_TYPE
>>>>
>>>> Should We need to align all the off_t syscall to 64bit syscall in
>>>> kernel?
>>>>
>>>
>>> Yes, this is the change that I think we need to make, along with
>>> the same change for __INO_T_TYPE and
>>>
>>> #define __OFF_T_MATCHES_OFF64_T        1
>>> #define __INO_T_MATCHES_INO64_T        1
>>>
>>> If I read the rest of the glibc headers right, that should be all we need
>>> to ensure that both off_t and off64_t match the __kernel_loff_t based
>>> syscalls.
>> Ok, I will test the ltp syscall test.
>> With this changes, the issue I mentioned should be fixed. But we still
>> use mmap2 syscall for ILP32 application when we pass the offset instead
>> of page offset. Is it correct?
>
> I don't remember. It's probably not important whether we have the shift
> in there, as long as it's independent of the actual kernel page size and
> user space and kernel agree on the calling conventions.
Well. I am ok with where to shift the pages size because we get the same
result. I was just thinking if we should get rid of the name of mmap2 in our
ILP32 porting. Actually, it is mmap but we name it as mmap2. User may confused
if they do not know the implementations.

Regards

Bamvor

>
> 	Arnd
>



From yamada.masahiro at socionext.com  Tue May 10 19:46:10 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Wed, 11 May 2016 11:46:10 +0900
Subject: [RFC PATCH 12/21] reset: uniphier: add core support for UniPhier
 reset driver
In-Reply-To: <1462888497.9155.9.camel@pengutronix.de>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
 <1462873862-30940-13-git-send-email-yamada.masahiro@socionext.com>
 <1462888497.9155.9.camel@pengutronix.de>
Message-ID: <CAK7LNASpxbW81A7YGQuAqmBdBty4BC6Z8sko8YepXOPnVqSjAQ@mail.gmail.com>

Hi Philipp,


2016-05-10 22:54 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> Am Dienstag, den 10.05.2016, 18:50 +0900 schrieb Masahiro Yamada:
> [...]
>> +static int uniphier_reset_update(struct reset_controller_dev *rcdev,
>> +                              unsigned long id, bool assert)
>> +{
>> +     struct uniphier_reset_priv *priv = to_uniphier_reset_priv(rcdev);
>> +     const struct uniphier_reset_data *p;
>> +     bool handled = false;
>> +
>> +     for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) {
>> +             unsigned int val;
>> +             int ret;
>> +
>> +             if (p->id != id)
>> +                     continue;
>> +
>> +             val = p->deassert_val;
>> +             if (assert)
>> +                     val = ~val;
>> +
>> +             ret = regmap_write_bits(priv->regmap, p->reg, p->mask, val);
>
> What is the difference between mask and deassert_val? Couldn't you just
> assign
>         val = assert ? 0 : p->mask;
> ?


I need to handle both active-high resets and active-low resets.

I thought two ways to do that.


[1] Have mask and a flag indicating active-low/active-high,
    like follows:

     if (flag & UNIPHIER_RST_ACTIVE_LOW)
          assert = !assert;
     val = assert ? 0 : p->mask;

[2] Have mask and deassert_val as in this patch




[1] cannot manage a case where one register contains
active-low bits and active-high bits mixed in it.



For example, let's say reset bits are BIT(1) and BIT(0).

[2] can solve this case as follows:

(a) If both bit1 and bit0 are active-high.
     .mask = BIT(1) | BIT(0);
     .deassert_val = 0;

(b) If bit1 is active-high and bit0 is active-low
     .mask = BIT(1) | BIT(0);
     .deassert_val =  BIT(0);

(c) If bit1 is active-low and bit0 is active-high
     .mask = BIT(1) | BIT(0);
     .deassert_val =  BIT(1);

(d) If both bit1 and bit0 are active-low
     .mask = BIT(1) | BIT(0);
     .deassert_val = BIT(1) | BIT(0);


I have not been hit by such a complicated case though.




>> +static const struct reset_control_ops uniphier_reset_ops = {
>> +     .assert = uniphier_reset_assert,
>> +     .deassert = uniphier_reset_deassert,
>> +     .status = uniphier_reset_status,
>> +};
>> +
>> +int uniphier_reset_probe(struct platform_device *pdev,
>> +                      const struct uniphier_reset_data *data)
>> +{
>> +     struct device *dev = &pdev->dev;
>> +     struct uniphier_reset_priv *priv;
>> +     const struct uniphier_reset_data *p;
>> +     struct regmap *regmap;
>> +     unsigned int nr_resets = 0;
>> +
>> +     /* parent should be MFD and syscon node */
>> +     regmap = syscon_node_to_regmap(dev->parent->of_node);
>> +     if (IS_ERR(regmap)) {
>> +             dev_err(dev, "failed to get regmap\n");
>
> syscon_node_to_regmap can return different error codes. It might be
> helpful to use
>         dev_err(dev, "failed to get regmap: %d\n", PTR_ERR(regmap));
> here.


OK. Will do.


-- 
Best Regards
Masahiro Yamada


From jamesjj.liao at mediatek.com  Tue May 10 19:51:29 2016
From: jamesjj.liao at mediatek.com (James Liao)
Date: Wed, 11 May 2016 10:51:29 +0800
Subject: [PATCH v7 7/9] clk: mediatek: Enable critical clocks for MT2701
In-Reply-To: <20160509221321.GT3492@codeaurora.org>
References: <1460621514-65191-1-git-send-email-jamesjj.liao@mediatek.com>
 <1460621514-65191-8-git-send-email-jamesjj.liao@mediatek.com>
 <20160506231229.GJ3492@codeaurora.org> <1462772426.5344.7.camel@mtksdaap41>
 <20160509221321.GT3492@codeaurora.org>
Message-ID: <1462935089.28773.11.camel@mtksdaap41>

Hi Stephen, Mike, Lee,

On Mon, 2016-05-09 at 15:13 -0700, Stephen Boyd wrote:
> On 05/09, James Liao wrote:
> > Hi Stephen,
> > 
> > On Fri, 2016-05-06 at 16:12 -0700, Stephen Boyd wrote:
> > > On 04/14, James Liao wrote:
> > > > Some system clocks should be turned on by default on MT2701.
> > > > This patch enable these clocks when related clocks have
> > > > been registered.
> > > > 
> > > > Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
> > > > ---
> > > 
> > > critical clks got merged now (sorry I'm slowly getting back to
> > > looking at patches). Please use that flag.
> > 
> > I don't see critical clock support in v4.6-rc7. Is there a repo/branch
> > that has critical clocks merged?
> > 
> 
> Right, it's in clk-next in the clk tree.

I got the latest code from clk-next and tried to use CLK_IS_CRITICAL fro
critical clocks. But There is something wrong with CLK_IS_CRITICAL. For
example, if we set vdec_sel as a critical clock, we'll get the following
result:

    vdecpll                               0            0
       vdecpll_ck                         1            1
          vdec_sel                        1            1

vdec_sel and vdecpll_ck are TOPCKGEN clocks. vdecpll is a APMIXEDSYS
PLL, which will be registered after TOPCKGEN clocks. The prepare and
enable count are incorrect in this case.

We may need to prepare/enable a parent clock if an enabled orphan clock
re-parent to it. I tried the following modification and it can resolve
this issue. But I'm not sure it's a correct place to enable parent
clcoks. May I have your comment on this?

------------------------------------------------------------
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index ce39add..db1bc3a 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2388,8 +2388,15 @@ static int __clk_core_init(struct clk_core *core)
        hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list,
child_node) {
                struct clk_core *parent = __clk_init_parent(orphan);

-               if (parent)
+               if (parent) {
                        clk_core_reparent(orphan, parent);
+
+                       if (orphan->prepare_count)
+                               clk_core_prepare(parent);
+
+                       if (orphan->enable_count )
+                               clk_core_enable(parent);
+               }
        }

        /*
------------------------------------------------------------


Best regards,

James



From yamada.masahiro at socionext.com  Tue May 10 19:52:32 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Wed, 11 May 2016 11:52:32 +0900
Subject: [RFC PATCH 13/21] reset: uniphier: add reset driver for UniPhier
 PH1-LD4 SoC
In-Reply-To: <1462883138.9155.3.camel@pengutronix.de>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
 <1462873862-30940-14-git-send-email-yamada.masahiro@socionext.com>
 <1462883138.9155.3.camel@pengutronix.de>
Message-ID: <CAK7LNASY=Kg-KOMue09_YRoxrBAnXP00oqG4AC2iQM1HJgLc7A@mail.gmail.com>

Hi Philipp,


2016-05-10 21:25 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> Hi Masahiro,
>
> Am Dienstag, den 10.05.2016, 18:50 +0900 schrieb Masahiro Yamada:
>> This series is just for review.
>> Please do not apply this patch.
>>
>> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
>
> No need for all these tiny drivers. If you probe from DT as Lee
> requests, you can let of_device_id.data point to a compatible specific
> uniphier_reset_data.
>

I will need to fill the table a bit more to complete this work,
but I do not think this reset driver will become as big as the clk driver.
(I guess it will be less than 1000 lines.)

If you prefer a single file for the whole of this SoC family,
I can squash all the files into one.
(I can split it if I need to do so in the future.)



-- 
Best Regards
Masahiro Yamada


From robh at kernel.org  Tue May 10 20:24:06 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 10 May 2016 22:24:06 -0500
Subject: [PATCH v2 5/5] vf610-soc: Add Vybrid SoC device tree binding
 documentation
In-Reply-To: <cab9edb2184ec13341a1dae1de9c7ebc@agner.ch>
References: <cover.1462171989.git.maitysanchayan@gmail.com>
 <65f3a7bd7a9faf1b390644d7c599c69683c753c4.1462171990.git.maitysanchayan@gmail.com>
 <20160504023026.GB5382@rob-hp-laptop>
 <20160505082758.GB18151@Sanchayan-Arch.localdomain>
 <CAL_JsqL1qQu_u=6xosP8UmR3oXLawbVz=Hap0wDm7aN4mjK2GA@mail.gmail.com>
 <4ca82be6c1d434c612868b441e9f6e1f@agner.ch>
 <CAL_JsqL7sjdONYad6sXM1KXFCjooANuN7WYg-paV9LnKnuMTnA@mail.gmail.com>
 <cab9edb2184ec13341a1dae1de9c7ebc@agner.ch>
Message-ID: <CAL_JsqLpdu1jpSkU5G0An4_7N3f-DOAF34zSmx2DmB_X7KTMUg@mail.gmail.com>

On Mon, May 9, 2016 at 8:13 PM, Stefan Agner <stefan at agner.ch> wrote:
> On 2016-05-09 15:58, Rob Herring wrote:
>> On Mon, May 9, 2016 at 1:25 PM, Stefan Agner <stefan at agner.ch> wrote:
>>> On 2016-05-09 10:14, Rob Herring wrote:
>>>> On Thu, May 5, 2016 at 3:27 AM,  <maitysanchayan at gmail.com> wrote:
>>>>> Hello Rob,
>>>>>
>>>>> On 16-05-03 21:30:26, Rob Herring wrote:
>>>>>> On Mon, May 02, 2016 at 12:35:04PM +0530, Sanchayan Maity wrote:
>>>>>> > Add device tree binding documentation for Vybrid SoC.

[...]

>>>>> Basically being a standalone platform driver, there was need of a compatible
>>>>> property to bind on. Introducing a separate device tree node for it's sake
>>>>> didn't seem appropriate so the alteration to SoC node's compatible.
>>>>
>>>> Ah, so you are designing a node around the needs of a Linux specific
>>>> driver. Don't do that. DT describes the h/w and this node is not a h/w
>>>> block.
>>>>
>>>> Create a platform device based on a matching SOC compatible string
>>>> instead and make your driver find the information it needs directly
>>>> from the relevant nodes like the ROM node.
>>>
>>> That reads like my words a year ago:
>>> https://lkml.org/lkml/2015/5/22/408
>>>
>>> Initially pretty much everything was hard-coded in the driver.
>>>
>>> Arnd then pushed to use more descriptive in the device tree.
>>>
>>> Of course, we should not end up making up relations which are not there
>>> in hardware. We need to find the right balance.
>>>
>>> Here is my suggestion:
>>> 1. Add "fsl,vf610-soc-bus" as compatible string to the soc node, use it
>>> to bind the "soc bus driver" as a platform driver located in driver/soc/
>>
>> I'm not convinced this is a h/w block. This keeps coming up and I
>> think this is a kernel problem, not a DT problem. Let's face it that
>> there are drivers at the SOC level which don't fit into a DT node.
>> They may be the exception, but they are a common exception. My
>> proposal for how to deal with these cases is here[1].
>
> Probably "fsl,vf610-soc" would be better than "fsl,vf610-soc-bus".

But the node in question is just the bus part of the SoC. Things like
cpus are not included.

> But the SoC is definitely a h/w block! Despite all the individual
> silicon in there, I can even touch the SoC ;-)

Can't argue with that...

> But yeah, I understand what you are saying... We model it as a
> container, and do not attribute any specific thing directly to it. But
> aren't there other containers where we bind to? Is it wrong to bind a
> driver to a container, if that driver implements issues concerning that
> level..?

It is supposed to be a bus, not just a container. However, we probably
don't generally fully and accurately model the buses in SoCs so DT
ends up being just a container frequently. If the bus is more than
simple-bus, then it should have some resource that needs to be
controlled to enable the bus.

>
> The two drivers under drivers/soc/ which implement the SoC bus API and
> both use a compatible string on a container level (e.g.
> arm,realview-pb11mp-soc in arch/arm/boot/dts/arm-realview-pb11mp.dts).

I'm not sure Realview and Integrator are models to follow. They are a
bit unique in their h/w design.

>
>>
>> I also think drivers/soc is a mess because it is randomly used or not.
>> IMO, using it should not be at the whim of whomever does SOC support.
>
> Are you talking about random drivers under drivers/soc/ or the ones
> which implement the SoC bus API? I think that is not the same...

The SoC bus API.

> If SoC bus, agreed, it is a mess. Not only its adoption is sparse, the
> specification is also interpreted differently across different SoC's,
> which I brought up in the past:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2015-March/333765.html
>
> But it exports really useful information to user space, and that has
> real value in practice.

Yes, but the information exported has nothing really to do with a bus.
The "bus" part of it is more sub-classing platform_bus_type for all
platform devices on an SOC. That container may or may not directly
correspond to the bus structure of the SOC as defined in DT. I guess
it is the mixing of really 2 independent things that I don't like and
has made its use sparse. We should perhaps mandate using the bus (for
what I described) and make the information part separate and be able
to populate it from any driver (e.g. an SoC syscon driver which reads
the SOC revision).

Rob


From oss at buserror.net  Tue May 10 20:26:26 2016
From: oss at buserror.net (Scott Wood)
Date: Tue, 10 May 2016 22:26:26 -0500
Subject: [v10, 7/7] mmc: sdhci-of-esdhc: fix host version for
 T4240-R1.0-R2.0
In-Reply-To: <5159406.HOFrj7pRfW@wuerfel>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <4448030.Zs8fVnr3nm@wuerfel>
 <HE1PR04MB0889B52134A43C0E7A452B7BF87C0@HE1PR04MB0889.eurprd04.prod.outlook.com>
 <5159406.HOFrj7pRfW@wuerfel>
Message-ID: <1462937186.16584.77.camel@buserror.net>

On Thu, 2016-05-05 at 13:10 +0200, Arnd Bergmann wrote:
> On Thursday 05 May 2016 09:41:32 Yangbo Lu wrote:
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > Sent: Thursday, May 05, 2016 4:32 PM
> > > To: linuxppc-dev at lists.ozlabs.org
> > > Cc: Yangbo Lu; linux-mmc at vger.kernel.org; devicetree at vger.kernel.org;
> > > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> > > linux-clk at vger.kernel.org; linux-i2c at vger.kernel.org; iommu at lists.linux-
> > > foundation.org; netdev at vger.kernel.org; Mark Rutland;
> > > ulf.hansson at linaro.org; Russell King; Bhupesh Sharma; Joerg Roedel;
> > > Santosh Shilimkar; Yang-Leo Li; Scott Wood; Rob Herring; Claudiu Manoil;
> > > Kumar Gala; Xiaobo Xie; Qiang Zhao
> > > Subject: Re: [v10, 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-
> > > R1.0-R2.0
> > > 
> > > On Thursday 05 May 2016 11:12:30 Yangbo Lu wrote:
> > > > IIRC, it is the same IP block as i.MX and Arnd's point is this won't
> > > > even compile on !PPC. It is things like this that prevent sharing the
> > > > driver.
> > 
> > The whole point of using the MMIO SVR instead of the PPC SPR is so that
> > it will work on ARM...  The guts driver should build on any platform as
> > long as OF is enabled, and if it doesn't find a node to bind to it will
> > return 0 for SVR, and the eSDHC driver will continue (after printing an
> > error that should be removed) without the ability to test for errata
> > based on SVR.
> 
> It feels like a bad design to have to come up with a different
> method for each SoC type here when they all do the same thing
> and want to identify some variant of the chip to do device
> specific quirks.
> 
> As far as I'm concerned, every driver in drivers/soc that needs to
> export a symbol to be used by a device driver is an indication that
> we don't have the right set of abstractions yet. There are cases
> that are not worth abstracting because the functionality is rather
> obscure and only a couple of drivers for one particular chip
> ever need it.
> 
> Finding out the version of the SoC does not look like this case.

I'm open to new ways of abstracting this, but can that please be discussed
after these patches are merged?  This patchset is fixing a problem, the
existing abstraction is unappealing and not widely adopted, a new abstraction
is not ready, and we're only touching code for our hardware.

Oh, and the existing abstraction isn't even "existing".  I don't see any
examples where soc_device is being used like this -- or even any way for a
driver (the one consuming the information, not the soc "driver") to get a
reference to the soc_device that's been registered short of searching for the
device object by name -- and you're asking for new functionality in
drivers/base/soc.c.

> > > I think the first four patches take care of building for ARM,
> > > but the problem remains if you want to enable COMPILE_TEST as
> > > we need for certain automated checking.
> > 
> > What specific problem is there with COMPILE_TEST?
> 
> COMPILE_TEST is solvable here and the way it is implemented in this
> case (selecting FSL_GUTS from the driver) indeed looks like it works
> correctly, but it's still awkward that this means building the
> SoC specific ID stuff into the vmlinux binary for any driver that
> uses something like that for a particular SoC.

Please keep in mind that this is a Freescale-specific driver... it's not as if
we're attaching this dependency to common SDHCI code.

> 
> > > > Dealing with Si revs is a common problem. We should have a
> > > > common solution. There is soc_device for this purpose.
> > > 
> > > Exactly. The last time this came up, I think we agreed to implement a
> > > helper using glob_match() on the soc_device strings. Unfortunately
> > > this hasn't happened then, but I'd still prefer that over yet another
> > > vendor-specific way of dealing with the generic issue.
> > 
> > soc_device would require encoding the SVR as a string and then decoding
> > the string, which is more complicated and error prone than having
> > platform-specific code test a platform-specific number. 
> 
> You already need to encode it as a string to register the soc_device,

No we don't, because we don't already register a soc_device on arm64 or ppc
(and it looks like whatever does get registered on at least some relevant
arm32 chips is not particularly useful).

> and the driver just needs to pass a glob string, so the only part that
> is missing is the generic function that takes the string from the
> driver and passes that to glob_match for the soc_device.

"just"

And what would the glob look like?

I'd rather not write kernel code as if it were a shell/Perl script.

> > And when would it get registered on arm64, which doesn't have
> > platform code?
> 
> Whenever the soc driver is loaded, as is the case now. The match
> function can return -EPROBE_DEFER if no SoC device is registered
> yet.

That's too late for some places where we need access to SVR, e.g. clock
drivers (which use CLK_OF_DECLARE and are initialized very early, not as part
of the driver model and thus can't defer).  Currently we have an #ifdef
CONFIG_PPC for this in drivers/clk/clk-qoriq.c... Maybe we should have done
that here as well, and saved some grief. :-)  At least until an erratum pops
up on an ARM-based chip.

And what happens if we're running on arm32, and thus the arch code already
registered an soc_device with a different (and less useful) encoding?

-Scott



From wxt at rock-chips.com  Tue May 10 20:31:25 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 11 May 2016 11:31:25 +0800
Subject: [PATCH] pinctrl: rockchip: fix pull setting error for rk3399
In-Reply-To: <CAD=FV=VrE=9=sgqUXBMwmoQin8S+yPbAgnrO1VUgx5QafYWXhA@mail.gmail.com>
References: <1462878896-28956-1-git-send-email-wxt@rock-chips.com>
 <CAD=FV=VrE=9=sgqUXBMwmoQin8S+yPbAgnrO1VUgx5QafYWXhA@mail.gmail.com>
Message-ID: <5732A78D.7040308@rock-chips.com>

Doug,

? 2016?05?11? 05:07, Doug Anderson ??:
> Caesar / David,
>
> On Tue, May 10, 2016 at 4:14 AM, Caesar Wang <wxt at rock-chips.com> wrote:
>> From: David Wu <david.wu at rock-chips.com>
>>
>> This patch fixes the pinctrl pull bias setting, since the pull up/down
>> setting is the contrary for gpio0.
> Commit message only mentions gpio0, but gpio2 is also fixed in the
> commit.  Please mention gpio2 in the commit message.

Fix it in next version.

>
>>  From the TRM said, the gpio0 pull polarity setting:
>> gpio0a_p (gpio0 )
>> GPIO0A PE/PS programmation section, every
>> GPIO bit corresponding to 2bits[PS:PE]
>> 2'b00: Z(Noraml operaton);
>> 2'b11: weak 1(pull-up);
>> 2'b01: weak 0(pull-down);
>> 2'b10: Z(Noraml operaton);
> Despite the fact that the typo (Noralm vs. Normal) is present in the
> TRM, maybe we should fix it here?

Yep, ditto.

> <cut>
>
> +
> +               if (ret < 0) {
> +                       dev_err(info->dev, "unknown pull setting %d\n", pull);
> nit: why change the error message?  Old message was "unsupported"
> instead of your new "unknown".  "unsupported" was better IMHO.

Okay, sound resonable.

>
>
>> -       PIN_BANK_DRV_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
>> -                          DRV_TYPE_IO_1V8_OR_3V0,
>> -                          DRV_TYPE_IO_1V8_ONLY,
>> -                          DRV_TYPE_IO_1V8_ONLY
>> -                          ),
>> +       PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
>> +                                     DRV_TYPE_IO_1V8_OR_3V0,
>> +                                     DRV_TYPE_IO_1V8_ONLY,
>> +                                     DRV_TYPE_IO_1V8_ONLY,
>> +                                     PULL_TYPE_IO_DEFAULT,
>> +                                     PULL_TYPE_IO_DEFAULT,
>>
> Are you certain that gpio2 behaves the same way?  The TRM I have says
> this for GPIO2C and GPIO2D:

+                                     PULL_TYPE_IO_1V8_ONLY,
+                                     PULL_TYPE_IO_1V8_ONLY

Yep, so this just set the gpio2c&gpio2d in this function.

>
> 2'b00: pervious-state
> 2'b01: weak 0(pull-down);
> 2'b10: pervious-state
> 2'b11: weak 1(pull-up);
>
> Assuming that "pervious-state" is a simple typo for "previous state"
> that would imply that it was behaving as "bus hold" and _not_ "bias
> disable".

I will say that TRM made the mistake since this is *not* exist.
Okay, fixes by the newer TRM.

>
> Note: if it actually is a "bus hold" state then we'll have to figure
> out how this would work with existing device trees.  I'd imagine that
> they are currently specifying "bias disable" and technically that
> might not be possible?
>
>
>
> -Doug
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip
>


From wxt at rock-chips.com  Tue May 10 20:39:28 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 11 May 2016 11:39:28 +0800
Subject: [PATCH v2] pinctrl: rockchip: fix pull setting error for rk3399
Message-ID: <1462937968-4952-1-git-send-email-wxt@rock-chips.com>

From: David Wu <david.wu at rock-chips.com>

This patch fixes the pinctrl pull bias setting, since the pull up/down
setting is the contrary for gpio0(just the gpio0a and gpio0b) and
gpio2(just the gpio2c and gpio2d).

>From the TRM said, the gpio0a pull polarity setting:
gpio0a_p
GPIO0A PE/PS programmation section, every
GPIO bit corresponding to 2bits[PS:PE]
2'b00: Z(Normal operation);
2'b11: weak 1(pull-up);
2'b01: weak 0(pull-down);
2'b10: Z(Normal operation);

Then, the other gpios setting as the following:
gpio1a_p (e.g.: gpio1, gpio2a, gpio2b, gpio3...)
GPIO1A PU/PD programmation section, every
GPIO bit corresponding to 2bits
2'b00: Z(Normal operation);
2'b01: weak 1(pull-up);
2'b10: weak 0(pull-down);
2'b11: Z(Normal operation);

For example,(rk3399evb board)
sdmmc_cd --->gpio0_a7
localhost / # io -r -4 0xff320040
ff320040: 00004d5f
In general,the value should be 0x0000cd5f since the pin has been set
in the dts.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Linus Walleij <linus.walleij at linaro.org>
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: linux-gpio at vger.kernel.org
---

Changes in v2:
- As Doug commnets on https://patchwork.kernel.org/patch/9056961/
- update the commit for gpio2.
- change the print error messgae.

 drivers/pinctrl/pinctrl-rockchip.c | 179 ++++++++++++++++++++++++++-----------
 1 file changed, 127 insertions(+), 52 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 596b869..a91026e 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -99,6 +99,15 @@ enum rockchip_pin_drv_type {
 };
 
 /**
+ * enum type index corresponding to rockchip_pull_list arrays index.
+ */
+enum rockchip_pin_pull_type {
+	PULL_TYPE_IO_DEFAULT = 0,
+	PULL_TYPE_IO_1V8_ONLY,
+	PULL_TYPE_MAX
+};
+
+/**
  * @drv_type: drive strength variant using rockchip_perpin_drv_type
  * @offset: if initialized to -1 it will be autocalculated, by specifying
  *	    an initial offset value the relevant source offset can be reset
@@ -123,6 +132,7 @@ struct rockchip_drv {
  * @bank_num: number of the bank, to account for holes
  * @iomux: array describing the 4 iomux sources of the bank
  * @drv: array describing the 4 drive strength sources of the bank
+ * @pull_type: array describing the 4 pull type sources of the bank
  * @valid: are all necessary informations present
  * @of_node: dt node of this bank
  * @drvdata: common pinctrl basedata
@@ -143,6 +153,7 @@ struct rockchip_pin_bank {
 	u8				bank_num;
 	struct rockchip_iomux		iomux[4];
 	struct rockchip_drv		drv[4];
+	enum rockchip_pin_pull_type	pull_type[4];
 	bool				valid;
 	struct device_node		*of_node;
 	struct rockchip_pinctrl		*drvdata;
@@ -198,6 +209,31 @@ struct rockchip_pin_bank {
 		},							\
 	}
 
+#define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1,	\
+				      drv2, drv3, pull0, pull1,		\
+				      pull2, pull3)			\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+			{ .offset = -1 },				\
+		},							\
+		.drv		= {					\
+			{ .drv_type = drv0, .offset = -1 },		\
+			{ .drv_type = drv1, .offset = -1 },		\
+			{ .drv_type = drv2, .offset = -1 },		\
+			{ .drv_type = drv3, .offset = -1 },		\
+		},							\
+		.pull_type[0] = pull0,					\
+		.pull_type[1] = pull1,					\
+		.pull_type[2] = pull2,					\
+		.pull_type[3] = pull3,					\
+	}
+
 #define PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(id, pins, label, iom0, iom1,	\
 					iom2, iom3, drv0, drv1, drv2,	\
 					drv3, offset0, offset1,		\
@@ -220,6 +256,34 @@ struct rockchip_pin_bank {
 		},							\
 	}
 
+#define PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(id, pins,	\
+					      label, iom0, iom1, iom2,  \
+					      iom3, drv0, drv1, drv2,   \
+					      drv3, offset0, offset1,   \
+					      offset2, offset3, pull0,  \
+					      pull1, pull2, pull3)	\
+	{								\
+		.bank_num	= id,					\
+		.nr_pins	= pins,					\
+		.name		= label,				\
+		.iomux		= {					\
+			{ .type = iom0, .offset = -1 },			\
+			{ .type = iom1, .offset = -1 },			\
+			{ .type = iom2, .offset = -1 },			\
+			{ .type = iom3, .offset = -1 },			\
+		},							\
+		.drv		= {					\
+			{ .drv_type = drv0, .offset = offset0 },	\
+			{ .drv_type = drv1, .offset = offset1 },	\
+			{ .drv_type = drv2, .offset = offset2 },	\
+			{ .drv_type = drv3, .offset = offset3 },	\
+		},							\
+		.pull_type[0] = pull0,					\
+		.pull_type[1] = pull1,					\
+		.pull_type[2] = pull2,					\
+		.pull_type[3] = pull3,					\
+	}
+
 /**
  */
 struct rockchip_pin_ctrl {
@@ -1020,12 +1084,27 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
 	return ret;
 }
 
+static int rockchip_pull_list[PULL_TYPE_MAX][4] = {
+	{
+		PIN_CONFIG_BIAS_DISABLE,
+		PIN_CONFIG_BIAS_PULL_UP,
+		PIN_CONFIG_BIAS_PULL_DOWN,
+		PIN_CONFIG_BIAS_BUS_HOLD
+	},
+	{
+		PIN_CONFIG_BIAS_DISABLE,
+		PIN_CONFIG_BIAS_PULL_DOWN,
+		PIN_CONFIG_BIAS_DISABLE,
+		PIN_CONFIG_BIAS_PULL_UP
+	},
+};
+
 static int rockchip_get_pull(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;
+	int reg, ret, pull_type;
 	u8 bit;
 	u32 data;
 
@@ -1048,22 +1127,11 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
 	case RK3288:
 	case RK3368:
 	case RK3399:
+		pull_type = bank->pull_type[pin_num / 8];
 		data >>= bit;
 		data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
 
-		switch (data) {
-		case 0:
-			return PIN_CONFIG_BIAS_DISABLE;
-		case 1:
-			return PIN_CONFIG_BIAS_PULL_UP;
-		case 2:
-			return PIN_CONFIG_BIAS_PULL_DOWN;
-		case 3:
-			return PIN_CONFIG_BIAS_BUS_HOLD;
-		}
-
-		dev_err(info->dev, "unknown pull setting\n");
-		return -EIO;
+		return rockchip_pull_list[pull_type][data];
 	default:
 		dev_err(info->dev, "unsupported pinctrl type\n");
 		return -EINVAL;
@@ -1076,7 +1144,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
 	struct rockchip_pinctrl *info = bank->drvdata;
 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
 	struct regmap *regmap;
-	int reg, ret;
+	int reg, ret, i, pull_type;
 	unsigned long flags;
 	u8 bit;
 	u32 data, rmask;
@@ -1105,30 +1173,28 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
 	case RK3288:
 	case RK3368:
 	case RK3399:
+		pull_type = bank->pull_type[pin_num / 8];
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(rockchip_pull_list[pull_type]);
+			i++) {
+			if (rockchip_pull_list[pull_type][i] == pull) {
+				ret = i;
+				break;
+			}
+		}
+
+		if (ret < 0) {
+			dev_err(info->dev, "unsupported pull setting %d\n",
+				pull);
+			return ret;
+		}
+
 		spin_lock_irqsave(&bank->slock, flags);
 
 		/* enable the write to the equivalent lower bits */
 		data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
 		rmask = data | (data >> 16);
-
-		switch (pull) {
-		case PIN_CONFIG_BIAS_DISABLE:
-			break;
-		case PIN_CONFIG_BIAS_PULL_UP:
-			data |= (1 << bit);
-			break;
-		case PIN_CONFIG_BIAS_PULL_DOWN:
-			data |= (2 << bit);
-			break;
-		case PIN_CONFIG_BIAS_BUS_HOLD:
-			data |= (3 << bit);
-			break;
-		default:
-			spin_unlock_irqrestore(&bank->slock, flags);
-			dev_err(info->dev, "unsupported pull setting %d\n",
-				pull);
-			return -EINVAL;
-		}
+		data |= (ret << bit);
 
 		ret = regmap_update_bits(regmap, reg, rmask, data);
 
@@ -2552,19 +2618,24 @@ static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
 };
 
 static struct rockchip_pin_bank rk3399_pin_banks[] = {
-	PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(0, 32, "gpio0", IOMUX_SOURCE_PMU,
-					IOMUX_SOURCE_PMU,
-					IOMUX_SOURCE_PMU,
-					IOMUX_SOURCE_PMU,
-					DRV_TYPE_IO_1V8_ONLY,
-					DRV_TYPE_IO_1V8_ONLY,
-					DRV_TYPE_IO_DEFAULT,
-					DRV_TYPE_IO_DEFAULT,
-					0x0,
-					0x8,
-					-1,
-					-1
-					),
+	PIN_BANK_IOMUX_FLAGS_DRV_FLAGS_OFFSET_PULL_FLAGS(0, 32, "gpio0",
+							 IOMUX_SOURCE_PMU,
+							 IOMUX_SOURCE_PMU,
+							 IOMUX_SOURCE_PMU,
+							 IOMUX_SOURCE_PMU,
+							 DRV_TYPE_IO_1V8_ONLY,
+							 DRV_TYPE_IO_1V8_ONLY,
+							 DRV_TYPE_IO_DEFAULT,
+							 DRV_TYPE_IO_DEFAULT,
+							 0x0,
+							 0x8,
+							 -1,
+							 -1,
+							 PULL_TYPE_IO_1V8_ONLY,
+							 PULL_TYPE_IO_1V8_ONLY,
+							 PULL_TYPE_IO_DEFAULT,
+							 PULL_TYPE_IO_DEFAULT
+							),
 	PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU,
 					IOMUX_SOURCE_PMU,
 					IOMUX_SOURCE_PMU,
@@ -2578,11 +2649,15 @@ static struct rockchip_pin_bank rk3399_pin_banks[] = {
 					0x30,
 					0x38
 					),
-	PIN_BANK_DRV_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
-			   DRV_TYPE_IO_1V8_OR_3V0,
-			   DRV_TYPE_IO_1V8_ONLY,
-			   DRV_TYPE_IO_1V8_ONLY
-			   ),
+	PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
+				      DRV_TYPE_IO_1V8_OR_3V0,
+				      DRV_TYPE_IO_1V8_ONLY,
+				      DRV_TYPE_IO_1V8_ONLY,
+				      PULL_TYPE_IO_DEFAULT,
+				      PULL_TYPE_IO_DEFAULT,
+				      PULL_TYPE_IO_1V8_ONLY,
+				      PULL_TYPE_IO_1V8_ONLY
+				      ),
 	PIN_BANK_DRV_FLAGS(3, 32, "gpio3", DRV_TYPE_IO_3V3_ONLY,
 			   DRV_TYPE_IO_3V3_ONLY,
 			   DRV_TYPE_IO_3V3_ONLY,
-- 
1.9.1



From dianders at chromium.org  Tue May 10 21:00:57 2016
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 10 May 2016 21:00:57 -0700
Subject: [PATCH v2] pinctrl: rockchip: fix pull setting error for rk3399
In-Reply-To: <1462937968-4952-1-git-send-email-wxt@rock-chips.com>
References: <1462937968-4952-1-git-send-email-wxt@rock-chips.com>
Message-ID: <CAD=FV=UXFj9Pq64Ksf8fWtCTffujuZjh8JR4OEmR7=vMTycP1Q@mail.gmail.com>

Caesar,

On Tue, May 10, 2016 at 8:39 PM, Caesar Wang <wxt at rock-chips.com> wrote:
> From: David Wu <david.wu at rock-chips.com>
>
> This patch fixes the pinctrl pull bias setting, since the pull up/down
> setting is the contrary for gpio0(just the gpio0a and gpio0b) and
> gpio2(just the gpio2c and gpio2d).
>
> From the TRM said, the gpio0a pull polarity setting:
> gpio0a_p
> GPIO0A PE/PS programmation section, every
> GPIO bit corresponding to 2bits[PS:PE]
> 2'b00: Z(Normal operation);
> 2'b11: weak 1(pull-up);
> 2'b01: weak 0(pull-down);
> 2'b10: Z(Normal operation);
>
> Then, the other gpios setting as the following:
> gpio1a_p (e.g.: gpio1, gpio2a, gpio2b, gpio3...)
> GPIO1A PU/PD programmation section, every
> GPIO bit corresponding to 2bits
> 2'b00: Z(Normal operation);
> 2'b01: weak 1(pull-up);
> 2'b10: weak 0(pull-down);
> 2'b11: Z(Normal operation);
>
> For example,(rk3399evb board)
> sdmmc_cd --->gpio0_a7
> localhost / # io -r -4 0xff320040
> ff320040: 00004d5f
> In general,the value should be 0x0000cd5f since the pin has been set
> in the dts.
>
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> Cc: Linus Walleij <linus.walleij at linaro.org>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Cc: linux-gpio at vger.kernel.org
> ---
>
> Changes in v2:
> - As Doug commnets on https://patchwork.kernel.org/patch/9056961/
> - update the commit for gpio2.
> - change the print error messgae.
>
>  drivers/pinctrl/pinctrl-rockchip.c | 179 ++++++++++++++++++++++++++-----------
>  1 file changed, 127 insertions(+), 52 deletions(-)

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


From david.wu at rock-chips.com  Tue May 10 12:24:05 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed, 11 May 2016 03:24:05 +0800
Subject: [PATCH v8 1/8] i2c: rk3x: add documentation to fields in "struct
 rk3x_i2c"
In-Reply-To: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462908252-27016-2-git-send-email-david.wu@rock-chips.com>

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
---
Change in v8:
- none

 drivers/i2c/busses/i2c-rk3x.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 80bed02..7e45d51 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -90,6 +90,26 @@ struct rk3x_i2c_soc_data {
 	int grf_offset;
 };
 
+/**
+ * struct rk3x_i2c - private data of the controller
+ * @adap: corresponding I2C adapter
+ * @dev: device for this controller
+ * @soc_data: related soc data struct
+ * @regs: virtual memory area
+ * @clk: clock of i2c bus
+ * @clk_rate_nb: i2c clk rate change notify
+ * @t: I2C known timing information
+ * @lock: spinlock for the i2c bus
+ * @wait: the waitqueue to wait for i2c transfer
+ * @busy: the condition for the event to wait for
+ * @msg: current i2c message
+ * @addr: addr of i2c slave device
+ * @mode: mode of i2c transfer
+ * @is_last_msg: flag determines whether it is the last msg in this transfer
+ * @state: state of i2c transfer
+ * @processed: byte length which has been send or received
+ * @error: error code for i2c transfer
+ */
 struct rk3x_i2c {
 	struct i2c_adapter adap;
 	struct device *dev;
@@ -116,7 +136,7 @@ struct rk3x_i2c {
 
 	/* I2C state machine */
 	enum rk3x_i2c_state state;
-	unsigned int processed; /* sent/received bytes */
+	unsigned int processed;
 	int error;
 };
 
-- 
1.9.1




From david.wu at rock-chips.com  Tue May 10 12:24:06 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed, 11 May 2016 03:24:06 +0800
Subject: [PATCH v8 2/8] i2c: rk3x: use struct "rk3x_i2c_calced_timings"
In-Reply-To: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462908252-27016-3-git-send-email-david.wu@rock-chips.com>

The "div_high" and "div_low" values are always used together.  Group them
into a structure to make it easier to pass them both around.  This
structure also provides a place for future calculated timings.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
---
Change in v8:
- add commit description.

 drivers/i2c/busses/i2c-rk3x.c | 55 +++++++++++++++++++++++++------------------
 1 file changed, 32 insertions(+), 23 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 7e45d51..1e2677a 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -75,6 +75,16 @@ enum {
 #define WAIT_TIMEOUT      1000 /* ms */
 #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */
 
+/**
+ * struct rk3x_i2c_calced_timings:
+ * @div_low: Divider output for low
+ * @div_high: Divider output for high
+ */
+struct rk3x_i2c_calced_timings {
+	unsigned long div_low;
+	unsigned long div_high;
+};
+
 enum rk3x_i2c_state {
 	STATE_IDLE,
 	STATE_START,
@@ -454,9 +464,8 @@ out:
  * Calculate divider values for desired SCL frequency
  *
  * @clk_rate: I2C input clock rate
- * @t: Known I2C timing information.
- * @div_low: Divider output for low
- * @div_high: Divider output for high
+ * @t: Known I2C timing information
+ * @t_calc: Caculated rk3x private timings that would be written into regs
  *
  * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
  * a best-effort divider value is returned in divs. If the target rate is
@@ -464,8 +473,7 @@ out:
  */
 static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 			      struct i2c_timings *t,
-			      unsigned long *div_low,
-			      unsigned long *div_high)
+			      struct rk3x_i2c_calced_timings *t_calc)
 {
 	unsigned long spec_min_low_ns, spec_min_high_ns;
 	unsigned long spec_setup_start, spec_max_data_hold_ns;
@@ -572,8 +580,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 		 * Time needed to meet hold requirements is important.
 		 * Just use that.
 		 */
-		*div_low = min_low_div;
-		*div_high = min_high_div;
+		t_calc->div_low = min_low_div;
+		t_calc->div_high = min_high_div;
 	} else {
 		/*
 		 * We've got to distribute some time among the low and high
@@ -602,25 +610,25 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 
 		/* Give low the "ideal" and give high whatever extra is left */
 		extra_low_div = ideal_low_div - min_low_div;
-		*div_low = ideal_low_div;
-		*div_high = min_high_div + (extra_div - extra_low_div);
+		t_calc->div_low = ideal_low_div;
+		t_calc->div_high = min_high_div + (extra_div - extra_low_div);
 	}
 
 	/*
 	 * Adjust to the fact that the hardware has an implicit "+1".
 	 * NOTE: Above calculations always produce div_low > 0 and div_high > 0.
 	 */
-	*div_low = *div_low - 1;
-	*div_high = *div_high - 1;
+	t_calc->div_low--;
+	t_calc->div_high--;
 
 	/* Maximum divider supported by hw is 0xffff */
-	if (*div_low > 0xffff) {
-		*div_low = 0xffff;
+	if (t_calc->div_low > 0xffff) {
+		t_calc->div_low = 0xffff;
 		ret = -EINVAL;
 	}
 
-	if (*div_high > 0xffff) {
-		*div_high = 0xffff;
+	if (t_calc->div_high > 0xffff) {
+		t_calc->div_high = 0xffff;
 		ret = -EINVAL;
 	}
 
@@ -630,19 +638,21 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
 {
 	struct i2c_timings *t = &i2c->t;
-	unsigned long div_low, div_high;
+	struct rk3x_i2c_calced_timings calc;
 	u64 t_low_ns, t_high_ns;
 	int ret;
 
-	ret = rk3x_i2c_calc_divs(clk_rate, t, &div_low, &div_high);
+	ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
 	WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
 
 	clk_enable(i2c->clk);
-	i2c_writel(i2c, (div_high << 16) | (div_low & 0xffff), REG_CLKDIV);
+	i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
+		   REG_CLKDIV);
 	clk_disable(i2c->clk);
 
-	t_low_ns = div_u64(((u64)div_low + 1) * 8 * 1000000000, clk_rate);
-	t_high_ns = div_u64(((u64)div_high + 1) * 8 * 1000000000, clk_rate);
+	t_low_ns = div_u64(((u64)calc.div_low + 1) * 8 * 1000000000, clk_rate);
+	t_high_ns = div_u64(((u64)calc.div_high + 1) * 8 * 1000000000,
+			    clk_rate);
 	dev_dbg(i2c->dev,
 		"CLK %lukhz, Req %uns, Act low %lluns high %lluns\n",
 		clk_rate / 1000,
@@ -672,12 +682,11 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
 {
 	struct clk_notifier_data *ndata = data;
 	struct rk3x_i2c *i2c = container_of(nb, struct rk3x_i2c, clk_rate_nb);
-	unsigned long div_low, div_high;
+	struct rk3x_i2c_calced_timings calc;
 
 	switch (event) {
 	case PRE_RATE_CHANGE:
-		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t,
-				       &div_low, &div_high) != 0)
+		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &calc) != 0)
 			return NOTIFY_STOP;
 
 		/* scale up */
-- 
1.9.1




From david.wu at rock-chips.com  Tue May 10 12:24:07 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed, 11 May 2016 03:24:07 +0800
Subject: [PATCH v8 3/8] i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd()
In-Reply-To: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462908252-27016-4-git-send-email-david.wu@rock-chips.com>

Call rk3x_i2c_setup() before rk3x_i2c_start()
and the last thing in setup was to clean the IPD,
so no reason to do it at the beginning of start.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
---
Change in v8:
- none

 drivers/i2c/busses/i2c-rk3x.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 1e2677a..9eeb4e5 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -174,7 +174,6 @@ static void rk3x_i2c_start(struct rk3x_i2c *i2c)
 {
 	u32 val;
 
-	rk3x_i2c_clean_ipd(i2c);
 	i2c_writel(i2c, REG_INT_START, REG_IEN);
 
 	/* enable adapter with correct mode, send START condition */
-- 
1.9.1




From david.wu at rock-chips.com  Tue May 10 12:24:08 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed, 11 May 2016 03:24:08 +0800
Subject: [PATCH v8 4/8] i2c: rk3x: Change SoC data to not use array
In-Reply-To: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462908252-27016-5-git-send-email-david.wu@rock-chips.com>

Specifying the i2c SoC data in an array provides very little benefit and
gets unwieldly / confusing as the array grows since the next bit of code
needs to refer to elements in the array by their raw integral index.

Let's just create a single 'static const' structure for each SoC so that
we can refer to these structures by ID.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Heiko Stuebner <heiko at sntech.de>
Suggested-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
---
Change in v8:
- add commit description.

 drivers/i2c/busses/i2c-rk3x.c | 38 ++++++++++++++++++++++++++++++--------
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 9eeb4e5..d7a871f 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -864,17 +864,39 @@ static const struct i2c_algorithm rk3x_i2c_algorithm = {
 	.functionality		= rk3x_i2c_func,
 };
 
-static struct rk3x_i2c_soc_data soc_data[3] = {
-	{ .grf_offset = 0x154 }, /* rk3066 */
-	{ .grf_offset = 0x0a4 }, /* rk3188 */
-	{ .grf_offset = -1 },    /* no I2C switching needed */
+static const struct rk3x_i2c_soc_data rk3066_soc_data = {
+	.grf_offset = 0x154,
+};
+
+static const struct rk3x_i2c_soc_data rk3188_soc_data = {
+	.grf_offset = 0x0a4,
+};
+
+static const struct rk3x_i2c_soc_data rk3228_soc_data = {
+	.grf_offset = -1,
+};
+
+static const struct rk3x_i2c_soc_data rk3288_soc_data = {
+	.grf_offset = -1,
 };
 
 static const struct of_device_id rk3x_i2c_match[] = {
-	{ .compatible = "rockchip,rk3066-i2c", .data = (void *)&soc_data[0] },
-	{ .compatible = "rockchip,rk3188-i2c", .data = (void *)&soc_data[1] },
-	{ .compatible = "rockchip,rk3228-i2c", .data = (void *)&soc_data[2] },
-	{ .compatible = "rockchip,rk3288-i2c", .data = (void *)&soc_data[2] },
+	{
+		.compatible = "rockchip,rk3066-i2c",
+		.data = (void *)&rk3066_soc_data
+	},
+	{
+		.compatible = "rockchip,rk3188-i2c",
+		.data = (void *)&rk3188_soc_data
+	},
+	{
+		.compatible = "rockchip,rk3228-i2c",
+		.data = (void *)&rk3228_soc_data
+	},
+	{
+		.compatible = "rockchip,rk3288-i2c",
+		.data = (void *)&rk3288_soc_data
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, rk3x_i2c_match);
-- 
1.9.1




From david.wu at rock-chips.com  Tue May 10 12:30:47 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed, 11 May 2016 03:30:47 +0800
Subject: [PATCH v8 6/8] dt-bindings: i2c: rk3x: add support for rk3399
In-Reply-To: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462908647-27236-1-git-send-email-david.wu@rock-chips.com>

The bus clock and function clock are separated at rk3399,
and others use one clock as the bus clock and function clock.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
---
Change in v8:
- remove error description.

 Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
index 0b4a85f..5429301 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
@@ -6,10 +6,20 @@ RK3xxx SoCs.
 Required properties :
 
  - reg : Offset and length of the register set for the device
- - compatible : should be "rockchip,rk3066-i2c", "rockchip,rk3188-i2c",
-		"rockchip,rk3228-i2c" or "rockchip,rk3288-i2c".
+ - compatible: should be one of the following:
+   - "rockchip,rk3066-i2c": for rk3066
+   - "rockchip,rk3188-i2c": for rk3188
+   - "rockchip,rk3228-i2c": for rk3228
+   - "rockchip,rk3288-i2c": for rk3288
+   - "rockchip,rk3399-i2c": for rk3399
  - interrupts : interrupt number
- - clocks : parent clock
+ - clocks: See ../clock/clock-bindings.txt
+   - For older hardware (rk3066, rk3188, rk3228, rk3288):
+     - There is one clock that's used both to derive the functional clock
+       for the device and as the bus clock.
+   - For newer hardware (rk3399): specified by name
+     - "i2c": REQUIRED. This is used to derive the functional clock.
+     - "pclk": REQUIRED. This is the bus clock.
 
 Required on RK3066, RK3188 :
 
-- 
1.9.1




From david.wu at rock-chips.com  Tue May 10 12:31:38 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed, 11 May 2016 03:31:38 +0800
Subject: [PATCH v8 7/8] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462908698-27284-1-git-send-email-david.wu@rock-chips.com>

- new method to caculate i2c timings for rk3399:
  There was an timing issue about "repeated start" time at the I2C
  controller of version0, controller appears to drop SDA at .875x (7/8)
  programmed clk high. On version 1 of the controller, the rule(.875x)
  isn't enough to meet tSU;STA
  requirements on 100k's Standard-mode. To resolve this issue,
  sda_update_config, start_setup_config and stop_setup_config for I2C
  timing information are added, new rules are designed to calculate
  the timing information at new v1.
- pclk and function clk are separated at rk3399

Signed-off-by: David Wu <david.wu at rock-chips.com>
---
Changes in v8:
- update tuning in RKI2C_CON register by doing a read-modify-write (Doug)
- new method to use pclk and clk (Doug)

Changes in v7:
- transform into a 9 series patches (Doug)
- drop highspeed with mastercode, and support fast-mode plus (Doug)

 drivers/i2c/busses/i2c-rk3x.c | 289 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 270 insertions(+), 19 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 9791797..25ed1ad 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -58,6 +58,12 @@ enum {
 #define REG_CON_LASTACK   BIT(5) /* 1: send NACK after last received byte */
 #define REG_CON_ACTACK    BIT(6) /* 1: stop if NACK is received */
 
+#define REG_CON_TUNING_MASK GENMASK(15, 8)
+
+#define REG_CON_SDA_CFG(cfg) ((cfg) << 8)
+#define REG_CON_STA_CFG(cfg) ((cfg) << 12)
+#define REG_CON_STO_CFG(cfg) ((cfg) << 14)
+
 /* REG_MRXADDR bits */
 #define REG_MRXADDR_VALID(x) BIT(24 + (x)) /* [x*8+7:x*8] of MRX[R]ADDR valid */
 
@@ -77,40 +83,62 @@ enum {
 
 /**
  * struct i2c_spec_values:
+ * @min_hold_start_ns: min hold time (repeated) START condition
  * @min_low_ns: min LOW period of the SCL clock
  * @min_high_ns: min HIGH period of the SCL cloc
  * @min_setup_start_ns: min set-up time for a repeated START conditio
  * @max_data_hold_ns: max data hold time
+ * @min_data_setup_ns: min data set-up time
+ * @min_setup_stop_ns: min set-up time for STOP condition
+ * @min_hold_buffer_ns: min bus free time between a STOP and
+ * START condition
  */
 struct i2c_spec_values {
+	unsigned long min_hold_start_ns;
 	unsigned long min_low_ns;
 	unsigned long min_high_ns;
 	unsigned long min_setup_start_ns;
 	unsigned long max_data_hold_ns;
+	unsigned long min_data_setup_ns;
+	unsigned long min_setup_stop_ns;
+	unsigned long min_hold_buffer_ns;
 };
 
 static const struct i2c_spec_values standard_mode_spec = {
+	.min_hold_start_ns = 4000,
 	.min_low_ns = 4700,
 	.min_high_ns = 4000,
 	.min_setup_start_ns = 4700,
 	.max_data_hold_ns = 3450,
+	.min_data_setup_ns = 250,
+	.min_setup_stop_ns = 4000,
+	.min_hold_buffer_ns = 4700,
 };
 
 static const struct i2c_spec_values fast_mode_spec = {
+	.min_hold_start_ns = 600,
 	.min_low_ns = 1300,
 	.min_high_ns = 600,
 	.min_setup_start_ns = 600,
 	.max_data_hold_ns = 900,
+	.min_data_setup_ns = 100,
+	.min_setup_stop_ns = 600,
+	.min_hold_buffer_ns = 1300,
 };
 
 /**
  * struct rk3x_i2c_calced_timings:
  * @div_low: Divider output for low
  * @div_high: Divider output for high
+ * @tuning: Used to adjust setup/hold data time,
+ * setup/hold start time and setup stop time for
+ * v1's calc_timings, the tuning should all be 0
+ * for old hardware anyone using v0's calc_timings.
  */
 struct rk3x_i2c_calced_timings {
 	unsigned long div_low;
 	unsigned long div_high;
+	unsigned int tuning;
 };
 
 enum rk3x_i2c_state {
@@ -123,9 +151,12 @@ enum rk3x_i2c_state {
 
 /**
  * @grf_offset: offset inside the grf regmap for setting the i2c type
+ * @calc_timings: Callback function for i2c timing information calculated
  */
 struct rk3x_i2c_soc_data {
 	int grf_offset;
+	int (*calc_timings)(unsigned long, struct i2c_timings *,
+			    struct rk3x_i2c_calced_timings *);
 };
 
 /**
@@ -134,7 +165,8 @@ struct rk3x_i2c_soc_data {
  * @dev: device for this controller
  * @soc_data: related soc data struct
  * @regs: virtual memory area
- * @clk: clock of i2c bus
+ * @clk: function clk for rk3399 or function & Bus clks for others
+ * @pclk: Bus clk for rk3399
  * @clk_rate_nb: i2c clk rate change notify
  * @t: I2C known timing information
  * @lock: spinlock for the i2c bus
@@ -156,6 +188,7 @@ struct rk3x_i2c {
 	/* Hardware resources */
 	void __iomem *regs;
 	struct clk *clk;
+	struct clk *pclk;
 	struct notifier_block clk_rate_nb;
 
 	/* Settings */
@@ -200,12 +233,12 @@ static inline void rk3x_i2c_clean_ipd(struct rk3x_i2c *i2c)
  */
 static void rk3x_i2c_start(struct rk3x_i2c *i2c)
 {
-	u32 val;
+	u32 val = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK;
 
 	i2c_writel(i2c, REG_INT_START, REG_IEN);
 
 	/* enable adapter with correct mode, send START condition */
-	val = REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START;
+	val |= REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START;
 
 	/* if we want to react to NACK, set ACTACK bit */
 	if (!(i2c->msg->flags & I2C_M_IGNORE_NAK))
@@ -513,9 +546,9 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
  * a best-effort divider value is returned in divs. If the target rate is
  * too high, we silently use the highest possible rate.
  */
-static int rk3x_i2c_calc_divs(unsigned long clk_rate,
-			      struct i2c_timings *t,
-			      struct rk3x_i2c_calced_timings *t_calc)
+static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate,
+				    struct i2c_timings *t,
+				    struct rk3x_i2c_calced_timings *t_calc)
 {
 	unsigned long min_low_ns, min_high_ns;
 	unsigned long max_low_ns, min_total_ns;
@@ -661,20 +694,189 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	return ret;
 }
 
+/**
+ * Calculate timing values for desired SCL frequency
+ *
+ * @clk_rate: I2C input clock rate
+ * @t: Known I2C timing information
+ * @t_calc: Caculated rk3x private timings that would be written into regs
+
+ * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
+ * a best-effort divider value is returned in divs. If the target rate is
+ * too high, we silently use the highest possible rate.
+ * The following formulas are v1's method to calculate timings.
+ *
+ * l = divl + 1;
+ * h = divh + 1;
+ * s = sda_update_config + 1;
+ * u = start_setup_config + 1;
+ * p = stop_setup_config + 1;
+ * T = Tclk_i2c;
+
+ * tHigh = 8 * h * T;
+ * tLow = 8 * l * T;
+
+ * tHD;sda = (l * s + 1) * T;
+ * tSU;sda = [(8 - s) * l + 1] * T;
+ * tI2C = 8 * (l + h) * T;
+
+ * tSU;sta = (8h * u + 1) * T;
+ * tHD;sta = [8h * (u + 1) - 1] * T;
+ * tSU;sto = (8h * p + 1) * T;
+ */
+static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
+				    struct i2c_timings *t,
+				    struct rk3x_i2c_calced_timings *t_calc)
+{
+	unsigned long min_low_ns, min_high_ns, min_total_ns;
+	unsigned long min_setup_start_ns, min_setup_data_ns;
+	unsigned long min_setup_stop_ns, max_hold_data_ns;
+
+	unsigned long clk_rate_khz, scl_rate_khz;
+
+	unsigned long min_low_div, min_high_div;
+
+	unsigned long min_div_for_hold, min_total_div;
+	unsigned long extra_div, extra_low_div;
+	unsigned long sda_update_cfg, stp_sta_cfg, stp_sto_cfg;
+
+	const struct i2c_spec_values *spec;
+	int ret = 0;
+
+	/* Support standard-mode and fast-mode */
+	if (WARN_ON(t->bus_freq_hz > 400000))
+		t->bus_freq_hz = 400000;
+
+	/* prevent scl_rate_khz from becoming 0 */
+	if (WARN_ON(t->bus_freq_hz < 1000))
+		t->bus_freq_hz = 1000;
+
+	/*
+	 * min_low_ns: The minimum number of ns we need to hold low to
+	 *	       meet I2C specification, should include fall time.
+	 * min_high_ns: The minimum number of ns we need to hold high to
+	 *	        meet I2C specification, should include rise time.
+	 */
+	spec = rk3x_i2c_get_spec(t->bus_freq_hz);
+
+	/* calculate min-divh and min-divl */
+	clk_rate_khz = DIV_ROUND_UP(clk_rate, 1000);
+	scl_rate_khz = t->bus_freq_hz / 1000;
+	min_total_div = DIV_ROUND_UP(clk_rate_khz, scl_rate_khz * 8);
+
+	min_high_ns = t->scl_rise_ns + spec->min_high_ns;
+	min_high_div = DIV_ROUND_UP(clk_rate_khz * min_high_ns, 8 * 1000000);
+
+	min_low_ns = t->scl_fall_ns + spec->min_low_ns;
+	min_low_div = DIV_ROUND_UP(clk_rate_khz * min_low_ns, 8 * 1000000);
+
+	/*
+	 * Final divh and divl must be greater than 0, otherwise the
+	 * hardware would not output the i2c clk.
+	 */
+	min_high_div = (min_high_div < 1) ? 2 : min_high_div;
+	min_low_div = (min_low_div < 1) ? 2 : min_low_div;
+
+	/* These are the min dividers needed for min hold times. */
+	min_div_for_hold = (min_low_div + min_high_div);
+	min_total_ns = min_low_ns + min_high_ns;
+
+	/*
+	 * This is the maximum divider so we don't go over the maximum.
+	 * We don't round up here (we round down) since this is a maximum.
+	 */
+	 if (min_div_for_hold >= min_total_div) {
+		/*
+		 * Time needed to meet hold requirements is important.
+		 * Just use that.
+		 */
+		t_calc->div_low = min_low_div;
+		t_calc->div_high = min_high_div;
+	} else {
+		/*
+		 * We've got to distribute some time among the low and high
+		 * so we don't run too fast.
+		 * We'll try to split things up by the scale of min_low_div and
+		 * min_high_div, biasing slightly towards having a higher div
+		 * for low (spend more time low).
+		 */
+		extra_div = min_total_div - min_div_for_hold;
+		extra_low_div = DIV_ROUND_UP(min_low_div * extra_div,
+					     min_div_for_hold);
+
+		t_calc->div_low = min_low_div + extra_low_div;
+		t_calc->div_high = min_high_div + (extra_div - extra_low_div);
+	}
+
+	/*
+	 * calculate sda data hold count by the rules, data_upd_st:3
+	 * is a appropriate value to reduce calculated times.
+	 */
+	for (sda_update_cfg = 3; sda_update_cfg > 0; sda_update_cfg--) {
+		max_hold_data_ns =  DIV_ROUND_UP((sda_update_cfg
+						 * (t_calc->div_low) + 1)
+						 * 1000000, clk_rate_khz);
+		min_setup_data_ns =  DIV_ROUND_UP(((8 - sda_update_cfg)
+						 * (t_calc->div_low) + 1)
+						 * 1000000, clk_rate_khz);
+		if ((max_hold_data_ns < spec->max_data_hold_ns) &&
+		    (min_setup_data_ns > spec->min_data_setup_ns))
+			break;
+	}
+
+	/* calculate setup start config */
+	min_setup_start_ns = t->scl_rise_ns + spec->min_setup_start_ns;
+	stp_sta_cfg = DIV_ROUND_UP(clk_rate_khz * min_setup_start_ns
+			   - 1000000, 8 * 1000000 * (t_calc->div_high));
+
+	/* calculate setup stop config */
+	min_setup_stop_ns = t->scl_rise_ns + spec->min_setup_stop_ns;
+	stp_sto_cfg = DIV_ROUND_UP(clk_rate_khz * min_setup_stop_ns
+			   - 1000000, 8 * 1000000 * (t_calc->div_high));
+
+	t_calc->tuning = REG_CON_SDA_CFG(--sda_update_cfg) |
+			 REG_CON_STA_CFG(--stp_sta_cfg) |
+			 REG_CON_STO_CFG(--stp_sto_cfg);
+
+	t_calc->div_low--;
+	t_calc->div_high--;
+
+	/* Maximum divider supported by hw is 0xffff */
+	if (t_calc->div_low > 0xffff) {
+		t_calc->div_low = 0xffff;
+		ret = -EINVAL;
+	}
+
+	if (t_calc->div_high > 0xffff) {
+		t_calc->div_high = 0xffff;
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
 static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
 {
 	struct i2c_timings *t = &i2c->t;
 	struct rk3x_i2c_calced_timings calc;
 	u64 t_low_ns, t_high_ns;
+	u32 val;
 	int ret;
 
-	ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
+	ret = i2c->soc_data->calc_timings(clk_rate, t, &calc);
 	WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
 
-	clk_enable(i2c->clk);
+	clk_enable(i2c->pclk);
+
 	i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
 		   REG_CLKDIV);
-	clk_disable(i2c->clk);
+
+	val = i2c_readl(i2c, REG_CON);
+	val &= ~REG_CON_TUNING_MASK;
+	val |= calc.tuning;
+	i2c_writel(i2c, val, REG_CON);
+
+	clk_disable(i2c->pclk);
 
 	t_low_ns = div_u64(((u64)calc.div_low + 1) * 8 * 1000000000, clk_rate);
 	t_high_ns = div_u64(((u64)calc.div_high + 1) * 8 * 1000000000,
@@ -712,7 +914,13 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
 
 	switch (event) {
 	case PRE_RATE_CHANGE:
-		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &calc) != 0)
+		/*
+		 * Try the calculation (but don't store the result) ahead of
+		 * time to see if we need to block the clock change.  Timings
+		 * shouldn't actually take effect until rk3x_i2c_adapt_div().
+		 */
+		if (i2c->soc_data->calc_timings(ndata->new_rate, &i2c->t,
+						&calc) != 0)
 			return NOTIFY_STOP;
 
 		/* scale up */
@@ -822,12 +1030,14 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
 {
 	struct rk3x_i2c *i2c = (struct rk3x_i2c *)adap->algo_data;
 	unsigned long timeout, flags;
+	u32 val;
 	int ret = 0;
 	int i;
 
 	spin_lock_irqsave(&i2c->lock, flags);
 
 	clk_enable(i2c->clk);
+	clk_enable(i2c->pclk);
 
 	i2c->is_last_msg = false;
 
@@ -861,7 +1071,9 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
 
 			/* Force a STOP condition without interrupt */
 			i2c_writel(i2c, 0, REG_IEN);
-			i2c_writel(i2c, REG_CON_EN | REG_CON_STOP, REG_CON);
+			val = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK;
+			val |= REG_CON_EN | REG_CON_STOP;
+			i2c_writel(i2c, val, REG_CON);
 
 			i2c->state = STATE_IDLE;
 
@@ -875,7 +1087,9 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
 		}
 	}
 
+	clk_disable(i2c->pclk);
 	clk_disable(i2c->clk);
+
 	spin_unlock_irqrestore(&i2c->lock, flags);
 
 	return ret < 0 ? ret : num;
@@ -893,18 +1107,27 @@ static const struct i2c_algorithm rk3x_i2c_algorithm = {
 
 static const struct rk3x_i2c_soc_data rk3066_soc_data = {
 	.grf_offset = 0x154,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
 };
 
 static const struct rk3x_i2c_soc_data rk3188_soc_data = {
 	.grf_offset = 0x0a4,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
 };
 
 static const struct rk3x_i2c_soc_data rk3228_soc_data = {
 	.grf_offset = -1,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
 };
 
 static const struct rk3x_i2c_soc_data rk3288_soc_data = {
 	.grf_offset = -1,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
+};
+
+static const struct rk3x_i2c_soc_data rk3399_soc_data = {
+	.grf_offset = -1,
+	.calc_timings = rk3x_i2c_v1_calc_timings,
 };
 
 static const struct of_device_id rk3x_i2c_match[] = {
@@ -924,6 +1147,10 @@ static const struct of_device_id rk3x_i2c_match[] = {
 		.compatible = "rockchip,rk3288-i2c",
 		.data = (void *)&rk3288_soc_data
 	},
+	{
+		.compatible = "rockchip,rk3399-i2c",
+		.data = (void *)&rk3399_soc_data
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, rk3x_i2c_match);
@@ -963,12 +1190,6 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 	spin_lock_init(&i2c->lock);
 	init_waitqueue_head(&i2c->wait);
 
-	i2c->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(i2c->clk)) {
-		dev_err(&pdev->dev, "cannot get clock\n");
-		return PTR_ERR(i2c->clk);
-	}
-
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	i2c->regs = devm_ioremap_resource(&pdev->dev, mem);
 	if (IS_ERR(i2c->regs))
@@ -1022,17 +1243,44 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, i2c);
 
+	if (i2c->soc_data->calc_timings == rk3x_i2c_v0_calc_timings) {
+		/* Only one clock to use for bus clock and peripheral clock */
+		i2c->clk = devm_clk_get(&pdev->dev, NULL);
+		i2c->pclk = i2c->clk;
+	} else {
+		i2c->clk = devm_clk_get(&pdev->dev, "i2c");
+		i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
+	}
+
+	if (IS_ERR(i2c->clk)) {
+		ret = PTR_ERR(i2c->clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Can't get bus clk: %d\n", ret);
+		return ret;
+	}
+	if (IS_ERR(i2c->pclk)) {
+		ret = PTR_ERR(i2c->pclk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Can't get periph clk: %d\n", ret);
+		return ret;
+	}
+
 	ret = clk_prepare(i2c->clk);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "Could not prepare clock\n");
+		dev_err(&pdev->dev, "Can't prepare bus clk: %d\n", ret);
 		return ret;
 	}
+	ret = clk_prepare(i2c->pclk);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Can't prepare periph clock: %d\n", ret);
+		goto err_clk;
+	}
 
 	i2c->clk_rate_nb.notifier_call = rk3x_i2c_clk_notifier_cb;
 	ret = clk_notifier_register(i2c->clk, &i2c->clk_rate_nb);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Unable to register clock notifier\n");
-		goto err_clk;
+		goto err_pclk;
 	}
 
 	clk_rate = clk_get_rate(i2c->clk);
@@ -1050,6 +1298,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 
 err_clk_notifier:
 	clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb);
+err_pclk:
+	clk_unprepare(i2c->pclk);
 err_clk:
 	clk_unprepare(i2c->clk);
 	return ret;
@@ -1062,6 +1312,7 @@ static int rk3x_i2c_remove(struct platform_device *pdev)
 	i2c_del_adapter(&i2c->adap);
 
 	clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb);
+	clk_unprepare(i2c->pclk);
 	clk_unprepare(i2c->clk);
 
 	return 0;
-- 
1.9.1




From david.wu at rock-chips.com  Tue May 10 12:24:04 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed, 11 May 2016 03:24:04 +0800
Subject: [PATCH v8 0/8] add i2c driver supported for rk3399
Message-ID: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>

There are three points differert from others:
 - new method to caculate i2c timings for rk3399
 - pclk and function clk are separated at rk3399
 - add fast-plus mode supported for rk3399

David Wu (8):
  i2c: rk3x: add documentation to fields in "struct rk3x_i2c"
  i2c: rk3x: use struct "rk3x_i2c_calced_timings"
  i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd()
  i2c: rk3x: Change SoC data to not use array
  i2c: rk3x: Move spec timing data to "static const" structs
  dt-bindings: i2c: rk3x: add support for rk3399
  i2c: rk3x: add i2c support for rk3399 soc
  i2c: rk3x: support fast-mode plus for rk3399

 Documentation/devicetree/bindings/i2c/i2c-rk3x.txt |  16 +-
 drivers/i2c/busses/i2c-rk3x.c                      | 493 +++++++++++++++++----
 2 files changed, 430 insertions(+), 79 deletions(-)

-- 
1.9.1




From david.wu at rock-chips.com  Tue May 10 12:29:58 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed, 11 May 2016 03:29:58 +0800
Subject: [PATCH v8 5/8] i2c: rk3x: Move spec timing data to "static const"
 structs
In-Reply-To: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462908598-27186-1-git-send-email-david.wu@rock-chips.com>

The i2c timing specs are really just constant data.  There's no reason
to write code to init them, so move them out to structures.  This not
only is a cleaner solution but it will reduce code duplication when we
introduce a new variant of rk3x_i2c_calc_divs() in a future patch.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Suggested-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
---
Changes in v8:
- add commit description.
- remove the spec values that were not needed, then
  introduce the additional values in the rk3399 patch. 

 drivers/i2c/busses/i2c-rk3x.c | 83 ++++++++++++++++++++++++++++---------------
 1 file changed, 55 insertions(+), 28 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index d7a871f..9791797 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -76,6 +76,34 @@ enum {
 #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */
 
 /**
+ * struct i2c_spec_values:
+ * @min_low_ns: min LOW period of the SCL clock
+ * @min_high_ns: min HIGH period of the SCL cloc
+ * @min_setup_start_ns: min set-up time for a repeated START conditio
+ * @max_data_hold_ns: max data hold time
+ */
+struct i2c_spec_values {
+	unsigned long min_low_ns;
+	unsigned long min_high_ns;
+	unsigned long min_setup_start_ns;
+	unsigned long max_data_hold_ns;
+};
+
+static const struct i2c_spec_values standard_mode_spec = {
+	.min_low_ns = 4700,
+	.min_high_ns = 4000,
+	.min_setup_start_ns = 4700,
+	.max_data_hold_ns = 3450,
+};
+
+static const struct i2c_spec_values fast_mode_spec = {
+	.min_low_ns = 1300,
+	.min_high_ns = 600,
+	.min_setup_start_ns = 600,
+	.max_data_hold_ns = 900,
+};
+
+/**
  * struct rk3x_i2c_calced_timings:
  * @div_low: Divider output for low
  * @div_high: Divider output for high
@@ -460,6 +488,21 @@ out:
 }
 
 /**
+ * Get timing values of I2C specification
+ *
+ * @speed: Desired SCL frequency
+ *
+ * Returns: Matched i2c spec values.
+ */
+static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
+{
+	if (speed <= 100000)
+		return &standard_mode_spec;
+	else
+		return &fast_mode_spec;
+}
+
+/**
  * Calculate divider values for desired SCL frequency
  *
  * @clk_rate: I2C input clock rate
@@ -474,10 +517,6 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 			      struct i2c_timings *t,
 			      struct rk3x_i2c_calced_timings *t_calc)
 {
-	unsigned long spec_min_low_ns, spec_min_high_ns;
-	unsigned long spec_setup_start, spec_max_data_hold_ns;
-	unsigned long data_hold_buffer_ns;
-
 	unsigned long min_low_ns, min_high_ns;
 	unsigned long max_low_ns, min_total_ns;
 
@@ -489,6 +528,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	unsigned long min_div_for_hold, min_total_div;
 	unsigned long extra_div, extra_low_div, ideal_low_div;
 
+	unsigned long data_hold_buffer_ns = 50;
+	const struct i2c_spec_values *spec;
 	int ret = 0;
 
 	/* Only support standard-mode and fast-mode */
@@ -511,22 +552,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	 *	 This is because the i2c host on Rockchip holds the data line
 	 *	 for half the low time.
 	 */
-	if (t->bus_freq_hz <= 100000) {
-		/* Standard-mode */
-		spec_min_low_ns = 4700;
-		spec_setup_start = 4700;
-		spec_min_high_ns = 4000;
-		spec_max_data_hold_ns = 3450;
-		data_hold_buffer_ns = 50;
-	} else {
-		/* Fast-mode */
-		spec_min_low_ns = 1300;
-		spec_setup_start = 600;
-		spec_min_high_ns = 600;
-		spec_max_data_hold_ns = 900;
-		data_hold_buffer_ns = 50;
-	}
-	min_high_ns = t->scl_rise_ns + spec_min_high_ns;
+	spec = rk3x_i2c_get_spec(t->bus_freq_hz);
+	min_high_ns = t->scl_rise_ns + spec->min_high_ns;
 
 	/*
 	 * Timings for repeated start:
@@ -536,14 +563,14 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	 * We need to account for those rules in picking our "high" time so
 	 * we meet tSU;STA and tHD;STA times.
 	 */
-	min_high_ns = max(min_high_ns,
-		DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start) * 1000, 875));
-	min_high_ns = max(min_high_ns,
-		DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start +
-			      t->sda_fall_ns + spec_min_high_ns), 2));
-
-	min_low_ns = t->scl_fall_ns + spec_min_low_ns;
-	max_low_ns = spec_max_data_hold_ns * 2 - data_hold_buffer_ns;
+	min_high_ns = max(min_high_ns, DIV_ROUND_UP(
+		(t->scl_rise_ns + spec->min_setup_start_ns) * 1000, 875));
+	min_high_ns = max(min_high_ns, DIV_ROUND_UP(
+		(t->scl_rise_ns + spec->min_setup_start_ns + t->sda_fall_ns +
+		spec->min_high_ns), 2));
+
+	min_low_ns = t->scl_fall_ns + spec->min_low_ns;
+	max_low_ns =  spec->max_data_hold_ns * 2 - data_hold_buffer_ns;
 	min_total_ns = min_low_ns + min_high_ns;
 
 	/* Adjust to avoid overflow */
-- 
1.9.1




From david.wu at rock-chips.com  Tue May 10 12:33:14 2016
From: david.wu at rock-chips.com (David Wu)
Date: Wed, 11 May 2016 03:33:14 +0800
Subject: [PATCH v8 8/8] i2c: rk3x: support fast-mode plus for rk3399
In-Reply-To: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1462908794-27333-1-git-send-email-david.wu@rock-chips.com>

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
---
Change in v8:
- None

 drivers/i2c/busses/i2c-rk3x.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 25ed1ad..0ba25ee 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -126,6 +126,17 @@ static const struct i2c_spec_values fast_mode_spec = {
 	.min_hold_buffer_ns = 1300,
 };
 
+static const struct i2c_spec_values fast_mode_plus_spec = {
+	.min_hold_start_ns = 260,
+	.min_low_ns = 500,
+	.min_high_ns = 260,
+	.min_setup_start_ns = 260,
+	.max_data_hold_ns = 400,
+	.min_data_setup_ns = 50,
+	.min_setup_stop_ns = 260,
+	.min_hold_buffer_ns = 500,
+};
+
 /**
  * struct rk3x_i2c_calced_timings:
  * @div_low: Divider output for low
@@ -531,8 +542,10 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
 {
 	if (speed <= 100000)
 		return &standard_mode_spec;
-	else
+	else if (speed <= 400000)
 		return &fast_mode_spec;
+	else
+		return &fast_mode_plus_spec;
 }
 
 /**
@@ -743,9 +756,9 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
 	const struct i2c_spec_values *spec;
 	int ret = 0;
 
-	/* Support standard-mode and fast-mode */
-	if (WARN_ON(t->bus_freq_hz > 400000))
-		t->bus_freq_hz = 400000;
+	/* Support standard-mode, fast-mode and fast-mode plus */
+	if (WARN_ON(t->bus_freq_hz > 1000000))
+		t->bus_freq_hz = 1000000;
 
 	/* prevent scl_rate_khz from becoming 0 */
 	if (WARN_ON(t->bus_freq_hz < 1000))
-- 
1.9.1




From wens at csie.org  Tue May 10 22:23:12 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed, 11 May 2016 13:23:12 +0800
Subject: [PATCH 0/2] ARM: dts: sun6i: Drop constraints on dc1sw regulator
Message-ID: <1462944194-6920-1-git-send-email-wens@csie.org>

Hi Arnd, Olof,

Here are 2 last minute fixes for 4.6. The 2 patches drop constaints on
the dc1sw regulator for 2 A31s tablets. I checked with Maxime and he said
to send them directly to you.

The issue was first brought up and fixed for A23/A33 Q8 tablets in commit
dcf5341f0150 ("ARM: dts: sun8i-q8-common: Do not set constraints on dc1sw
regulator"). It was brought up again yesterday on IRC, and I realized that
2 sun6i A31s tablet DTS files also had this setting. The setting causes
PMIC regulator registration to fail, and since among other things, mmc
depends on the regulators, the system will likely hang.

There seems to be a fix for this queued up for 4.7: commit 45389c47526d
("regulator: core: Add early supply resolution for regulators") in the
regulator "supply" topic branch. So we should be able to revert these
fixes in 4.7.


Regards
ChenYu


Chen-Yu Tsai (2):
  ARM: dts: sun6i: primo81: Drop constraints on dc1sw regulator
  ARM: dts: sun6i: yones-toptech-bs1078-v2: Drop constraints on dc1sw
    regulator

 arch/arm/boot/dts/sun6i-a31s-primo81.dts                 | 2 --
 arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts | 2 --
 2 files changed, 4 deletions(-)

-- 
2.8.1



From wens at csie.org  Tue May 10 22:23:13 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed, 11 May 2016 13:23:13 +0800
Subject: [PATCH 1/2] ARM: dts: sun6i: primo81: Drop constraints on dc1sw
 regulator
In-Reply-To: <1462944194-6920-1-git-send-email-wens@csie.org>
References: <1462944194-6920-1-git-send-email-wens@csie.org>
Message-ID: <1462944194-6920-2-git-send-email-wens@csie.org>

This is the same issue fixed in commit dcf5341f0150 ("ARM: dts:
sun8i-q8-common: Do not set constraints on dc1sw regulator").
Commit message copied:

dc1sw is an on/off only regulator and as such it cannot have constraints.

This is a limitation of the kernel regulator implementation which resolves
supplies on the first regulator_get(), which is done after applying
constraints, and applying the constrains will fail because it calls
_regulator_get_voltage() and _regulator_do_set_voltage() both of which
will fail on a switch regulator when there is no supply (yet).

This causes registering of all axp22x regulators to fail with the
following errors:

[    1.395249] vcc-lcd: failed to get the current voltage(-22)
[    1.405131] axp20x-regulator axp20x-regulator: Failed to register dc1sw
[    1.412436] axp20x-regulator: probe of axp20x-regulator failed with error -22

This commit removes the constrains on dc1sw / vcc-lcd fixing this problem.
Note that dcdc1 itself is contrained to the exact same values, so this
does not change anything.

Cc: Hans de Goede <hdegoede at redhat.com>
Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 arch/arm/boot/dts/sun6i-a31s-primo81.dts | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm/boot/dts/sun6i-a31s-primo81.dts b/arch/arm/boot/dts/sun6i-a31s-primo81.dts
index 68b479b8772c..73c133f5e79c 100644
--- a/arch/arm/boot/dts/sun6i-a31s-primo81.dts
+++ b/arch/arm/boot/dts/sun6i-a31s-primo81.dts
@@ -176,8 +176,6 @@
 };
 
 &reg_dc1sw {
-	regulator-min-microvolt = <3000000>;
-	regulator-max-microvolt = <3000000>;
 	regulator-name = "vcc-lcd";
 };
 
-- 
2.8.1



From wens at csie.org  Tue May 10 22:23:14 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed, 11 May 2016 13:23:14 +0800
Subject: [PATCH 2/2] ARM: dts: sun6i: yones-toptech-bs1078-v2: Drop
 constraints on dc1sw regulator
In-Reply-To: <1462944194-6920-1-git-send-email-wens@csie.org>
References: <1462944194-6920-1-git-send-email-wens@csie.org>
Message-ID: <1462944194-6920-3-git-send-email-wens@csie.org>

This is the same issue fixed in commit dcf5341f0150 ("ARM: dts:
sun8i-q8-common: Do not set constraints on dc1sw regulator").
Commit message copied:

dc1sw is an on/off only regulator and as such it cannot have constraints.

This is a limitation of the kernel regulator implementation which resolves
supplies on the first regulator_get(), which is done after applying
constraints, and applying the constrains will fail because it calls
_regulator_get_voltage() and _regulator_do_set_voltage() both of which
will fail on a switch regulator when there is no supply (yet).

This causes registering of all axp22x regulators to fail with the
following errors:

[    1.395249] vcc-lcd: failed to get the current voltage(-22)
[    1.405131] axp20x-regulator axp20x-regulator: Failed to register dc1sw
[    1.412436] axp20x-regulator: probe of axp20x-regulator failed with error -22

This commit removes the constrains on dc1sw / vcc-lcd fixing this problem.
Note that dcdc1 itself is contrained to the exact same values, so this
does not change anything.

Cc: Hans de Goede <hdegoede at redhat.com>
Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts b/arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts
index 360adfb1e9ca..d6ad6196a768 100644
--- a/arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts
+++ b/arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts
@@ -135,8 +135,6 @@
 
 &reg_dc1sw {
 	regulator-name = "vcc-lcd-usb2";
-	regulator-min-microvolt = <3000000>;
-	regulator-max-microvolt = <3000000>;
 };
 
 &reg_dc5ldo {
-- 
2.8.1



From k.kozlowski at samsung.com  Tue May 10 22:49:19 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 07:49:19 +0200
Subject: [PATCH] ARM: dts: exynos: Only Odroid XU3-family boards use DTSI
 with CPU thermal nodes
In-Reply-To: <CANAwSgQGhrBca7=Ow8+Hh9t0W9HWp=F43KR0Frfpx9fGngPSaw@mail.gmail.com>
References: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>
 <CANAwSgT9SY3kj8+beMpc1xGoC=rMBSya+2v2dyZQp6ykH+V0=g@mail.gmail.com>
 <573198BE.6020900@samsung.com>
 <CANAwSgTy6p9AVmmOWATpSO1JqVbwE0v+y_y-RLd+32RnNJTA+Q@mail.gmail.com>
 <5731D764.8070007@samsung.com>
 <CANAwSgRsjdQh6ygT__5XcH8-cF9Ch+zbk8oupebwYzY1kCZu6g@mail.gmail.com>
 <5731EA1B.4070201@samsung.com>
 <CANAwSgQGhrBca7=Ow8+Hh9t0W9HWp=F43KR0Frfpx9fGngPSaw@mail.gmail.com>
Message-ID: <5732C7DF.2080800@samsung.com>

On 05/10/2016 09:45 PM, Anand Moon wrote:
> Hi Krzysztof,
> 
> Sorry I am not able to explain my self clearly.
> But I have once gain tested these changes.
> 
> Only could you append with following changes.
> --------------------------------------------------------
> +                               cpu_crit0: cpu-crit-0 {
> +                                       temperature = <120000>; /*
> millicelsius */
> +                                       hysteresis = <5000>; /* millicelsius */
> +                                       type = "critical";
> +                               };
> --------------------------------------------------------
> hysteresis time help to adjust the present and past temperature inputs
> before critical shutdown.

I need more details why you want this patch. What is the point of
hysteresis on critical trip point? When reaching this trip point the
system shutdowns... there is nothing more to do, I think.

Best regards,
Krzysztof



From j-keerthy at ti.com  Tue May 10 22:48:03 2016
From: j-keerthy at ti.com (Keerthy)
Date: Wed, 11 May 2016 11:18:03 +0530
Subject: [PATCH 0/8] regulator: tps65218: Clean ups
Message-ID: <1462945691-904-1-git-send-email-j-keerthy@ti.com>

The series cleans up mainly the regulator driver and implements
the device tree parsing using the regulator framework. Removes
all the redundant compatibles for the individual regulators.

One of the patch removes redundant read wrapper and makes
use of regmap_read wherever necessary.

The series is checked for all the regulator registrations on
am437x-gp-evm and am437x-sk-evm.

Keerthy (8):
  mfd: tps65218: Remove redundant read wrapper
  Documentation: regulator: tps65218: Updates according to changes with
    parsing
  mfd: tps65218: Use mfd_add_devices instead of of_platform_populate
  regulator: tps65218: Remove all the compatibles
  ARM: dts: AM437X-GP-EVM: Remove redundant regulator compatibles
  ARM: dts: AM437X-SK-EVM: Remove redundant regulator compatibles
  ARM: dts: AM437X-CM-T43: Remove redundant regulator compatibles
  ARM: dts: AM43X-EPOS-EVM: Remove redundant regulator compatibles

 .../devicetree/bindings/regulator/tps65218.txt     |  88 +++++++++++---
 arch/arm/boot/dts/am437x-cm-t43.dts                |   6 -
 arch/arm/boot/dts/am437x-gp-evm.dts                |   6 -
 arch/arm/boot/dts/am437x-sk-evm.dts                |   5 -
 arch/arm/boot/dts/am43x-epos-evm.dts               |   7 --
 drivers/mfd/tps65218.c                             |  24 ++--
 drivers/regulator/tps65218-regulator.c             | 134 ++++++++-------------
 include/linux/mfd/tps65218.h                       |   2 -
 8 files changed, 127 insertions(+), 145 deletions(-)

-- 
1.9.1



From j-keerthy at ti.com  Tue May 10 22:48:05 2016
From: j-keerthy at ti.com (Keerthy)
Date: Wed, 11 May 2016 11:18:05 +0530
Subject: [PATCH 2/8] Documentation: regulator: tps65218: Update examples
In-Reply-To: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
References: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
Message-ID: <1462945691-904-3-git-send-email-j-keerthy@ti.com>

This updates the device tree according to the preferred way of parsing
the nodes using the regulator framework.

Signed-off-by: Keerthy <j-keerthy at ti.com>
---
 .../devicetree/bindings/regulator/tps65218.txt     | 87 ++++++++++++++++++----
 1 file changed, 71 insertions(+), 16 deletions(-)

diff --git a/Documentation/devicetree/bindings/regulator/tps65218.txt b/Documentation/devicetree/bindings/regulator/tps65218.txt
index fccc1d2..8d3d919 100644
--- a/Documentation/devicetree/bindings/regulator/tps65218.txt
+++ b/Documentation/devicetree/bindings/regulator/tps65218.txt
@@ -1,23 +1,78 @@
 TPS65218 family of regulators
 
 Required properties:
-For tps65218 regulators/LDOs
-- compatible:
-  - "ti,tps65218-dcdc1" for DCDC1
-  - "ti,tps65218-dcdc2" for DCDC2
-  - "ti,tps65218-dcdc3" for DCDC3
-  - "ti,tps65218-dcdc4" for DCDC4
-  - "ti,tps65218-dcdc5" for DCDC5
-  - "ti,tps65218-dcdc6" for DCDC6
-  - "ti,tps65218-ldo1" for LDO1
-
-Optional properties:
-- Any optional property defined in bindings/regulator/regulator.txt
+- compatible: "ti,tps65218"
+- reg: I2C slave address
+- list of regulators provided by this controller, must be named
+  after their hardware counterparts: dcdc[1-6] and ldo1
+- This is the list of child nodes that specify the regulator
+  initialization data for defined regulators. Not all regulators for the given
+  device need to be present. The definition for each of these nodes is defined
+  using the standard binding for regulators found at
+  Documentation/devicetree/bindings/regulator/regulator.txt.
+
+  The valid names for regulators are:
+  tps65217: regulator-dcdc1, regulator-dcdc2, regulator-dcdc3, regulator-dcdc4,
+  regulator-dcdc5, regulator-dcdc6, regulator-ldo1, regulator-ls3
+  Each regulator is defined using the standard binding for regulators.
 
 Example:
+tps65218: tps65218 at 24 {
+	reg = <0x24>;
+	compatible = "ti,tps65218";
+	interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
+	interrupt-controller;
+	#interrupt-cells = <2>;
+
+	dcdc1: regulator-dcdc1 {
+		regulator-name = "vdd_core";
+		regulator-min-microvolt = <912000>;
+		regulator-max-microvolt = <1144000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	dcdc2: regulator-dcdc2 {
+		regulator-name = "vdd_mpu";
+		regulator-min-microvolt = <912000>;
+		regulator-max-microvolt = <1378000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	dcdc3: regulator-dcdc3 {
+		regulator-name = "vdcdc3";
+		regulator-min-microvolt = <1500000>;
+		regulator-max-microvolt = <1500000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	dcdc5: regulator-dcdc5 {
+		regulator-name = "v1_0bat";
+		regulator-min-microvolt = <1000000>;
+		regulator-max-microvolt = <1000000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	dcdc6: regulator-dcdc6 {
+		regulator-name = "v1_8bat";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	ldo1: regulator-ldo1 {
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
 
-	xyz: regulator at 0 {
-		compatible = "ti,tps65218-dcdc1";
-		regulator-min-microvolt  = <1000000>;
-		regulator-max-microvolt  = <3000000>;
+	ls3: regulator-ls3 {
+		regulator-min-microvolt = <100000>;
+		regulator-max-microvolt = <1000000>;
 	};
+};
-- 
1.9.1



From j-keerthy at ti.com  Tue May 10 22:48:04 2016
From: j-keerthy at ti.com (Keerthy)
Date: Wed, 11 May 2016 11:18:04 +0530
Subject: [PATCH 1/8] mfd: tps65218: Remove redundant read wrapper
In-Reply-To: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
References: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
Message-ID: <1462945691-904-2-git-send-email-j-keerthy@ti.com>

Currently read directly calls the repmap read function. Hence
remove the redundant wrapper and use regmap read wherever
needed.

Signed-off-by: Keerthy <j-keerthy at ti.com>
---
 drivers/mfd/tps65218.c                 | 16 +---------------
 drivers/regulator/tps65218-regulator.c |  3 ++-
 include/linux/mfd/tps65218.h           |  2 --
 3 files changed, 3 insertions(+), 18 deletions(-)

diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c
index 80b9dc3..f20a531 100644
--- a/drivers/mfd/tps65218.c
+++ b/drivers/mfd/tps65218.c
@@ -34,20 +34,6 @@
 #define TPS65218_PASSWORD_REGS_UNLOCK   0x7D
 
 /**
- * tps65218_reg_read: Read a single tps65218 register.
- *
- * @tps: Device to read from.
- * @reg: Register to read.
- * @val: Contians the value
- */
-int tps65218_reg_read(struct tps65218 *tps, unsigned int reg,
-			unsigned int *val)
-{
-	return regmap_read(tps->regmap, reg, val);
-}
-EXPORT_SYMBOL_GPL(tps65218_reg_read);
-
-/**
  * tps65218_reg_write: Write a single tps65218 register.
  *
  * @tps65218: Device to write to.
@@ -93,7 +79,7 @@ static int tps65218_update_bits(struct tps65218 *tps, unsigned int reg,
 	int ret;
 	unsigned int data;
 
-	ret = tps65218_reg_read(tps, reg, &data);
+	ret = regmap_read(tps->regmap, reg, &data);
 	if (ret) {
 		dev_err(tps->dev, "Read from reg 0x%x failed\n", reg);
 		return ret;
diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c
index a5e5634..679ab2f 100644
--- a/drivers/regulator/tps65218-regulator.c
+++ b/drivers/regulator/tps65218-regulator.c
@@ -22,6 +22,7 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/of_device.h>
+#include <linux/regmap.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
@@ -224,7 +225,7 @@ static int tps65218_pmic_get_current_limit(struct regulator_dev *dev)
 	unsigned int index;
 	struct tps65218 *tps = rdev_get_drvdata(dev);
 
-	retval = tps65218_reg_read(tps, dev->desc->csel_reg, &index);
+	retval = regmap_read(tps->regmap, dev->desc->csel_reg, &index);
 	if (retval < 0)
 		return retval;
 
diff --git a/include/linux/mfd/tps65218.h b/include/linux/mfd/tps65218.h
index d58f3b5..7c9241f 100644
--- a/include/linux/mfd/tps65218.h
+++ b/include/linux/mfd/tps65218.h
@@ -276,8 +276,6 @@ struct tps65218 {
 	struct regmap *regmap;
 };
 
-int tps65218_reg_read(struct tps65218 *tps, unsigned int reg,
-					unsigned int *val);
 int tps65218_reg_write(struct tps65218 *tps, unsigned int reg,
 			unsigned int val, unsigned int level);
 int tps65218_set_bits(struct tps65218 *tps, unsigned int reg,
-- 
1.9.1



From j-keerthy at ti.com  Tue May 10 22:48:06 2016
From: j-keerthy at ti.com (Keerthy)
Date: Wed, 11 May 2016 11:18:06 +0530
Subject: [PATCH 3/8] mfd: tps65218: Use mfd_add_devices instead of
 of_platform_populate
In-Reply-To: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
References: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
Message-ID: <1462945691-904-4-git-send-email-j-keerthy@ti.com>

mfd_add_devices enables parsing device tree nodes without compatibles
for child nodes. Replace of_platform_populate with mfd_add_devices.

Signed-off-by: Keerthy <j-keerthy at ti.com>
---
 drivers/mfd/tps65218.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c
index f20a531..b8b3a58 100644
--- a/drivers/mfd/tps65218.c
+++ b/drivers/mfd/tps65218.c
@@ -33,6 +33,10 @@
 
 #define TPS65218_PASSWORD_REGS_UNLOCK   0x7D
 
+static const struct mfd_cell tps65218_cells[] = {
+	{ .name = "tps65218-regulator", },
+};
+
 /**
  * tps65218_reg_write: Write a single tps65218 register.
  *
@@ -236,8 +240,10 @@ static int tps65218_probe(struct i2c_client *client,
 	if (ret < 0)
 		return ret;
 
-	ret = of_platform_populate(client->dev.of_node, NULL, NULL,
-				   &client->dev);
+	ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65218_cells,
+			      ARRAY_SIZE(tps65218_cells), NULL, 0,
+			      regmap_irq_get_domain(tps->irq_data));
+
 	if (ret < 0)
 		goto err_irq;
 
-- 
1.9.1



From j-keerthy at ti.com  Tue May 10 22:48:07 2016
From: j-keerthy at ti.com (Keerthy)
Date: Wed, 11 May 2016 11:18:07 +0530
Subject: [PATCH 4/8] regulator: tps65218: Remove all the compatibles
In-Reply-To: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
References: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
Message-ID: <1462945691-904-5-git-send-email-j-keerthy@ti.com>

Remove all the individual compatibles for all the regulators
and introduce id_table and update the driver accordingly
to parse device tree nodes using the regulator framework.

Signed-off-by: Keerthy <j-keerthy at ti.com>
---
 drivers/regulator/tps65218-regulator.c | 131 +++++++++++----------------------
 1 file changed, 45 insertions(+), 86 deletions(-)

diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c
index 679ab2f..8106cc4 100644
--- a/drivers/regulator/tps65218-regulator.c
+++ b/drivers/regulator/tps65218-regulator.c
@@ -31,10 +31,11 @@
 enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4,
 			   DCDC5, DCDC6, LDO1, LS3 };
 
-#define TPS65218_REGULATOR(_name, _id, _type, _ops, _n, _vr, _vm, _er, _em, \
-			    _cr, _cm, _lr, _nlr, _delay, _fuv)		\
+#define TPS65218_REGULATOR(_name, _of,  _id, _type, _ops, _n, _vr, _vm, _er,\
+			   _em,  _cr, _cm, _lr, _nlr, _delay, _fuv)	\
 	{							\
 		.name			= _name,		\
+		.of_match		= _of,			\
 		.id			= _id,			\
 		.ops			= &_ops,		\
 		.n_voltages		= _n,			\
@@ -53,14 +54,6 @@ enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4,
 		.fixed_uV		= _fuv			\
 	}							\
 
-#define TPS65218_INFO(_id, _nm, _min, _max)	\
-	[_id] = {					\
-		.id		= _id,			\
-		.name		= _nm,			\
-		.min_uV		= _min,			\
-		.max_uV		= _max,			\
-	}
-
 static const struct regulator_linear_range dcdc1_dcdc2_ranges[] = {
 	REGULATOR_LINEAR_RANGE(850000, 0x0, 0x32, 10000),
 	REGULATOR_LINEAR_RANGE(1375000, 0x33, 0x3f, 25000),
@@ -76,36 +69,6 @@ static const struct regulator_linear_range dcdc4_ranges[] = {
 	REGULATOR_LINEAR_RANGE(1600000, 0x10, 0x34, 50000),
 };
 
-static struct tps_info tps65218_pmic_regs[] = {
-	TPS65218_INFO(DCDC1, "DCDC1", 850000, 1675000),
-	TPS65218_INFO(DCDC2, "DCDC2", 850000, 1675000),
-	TPS65218_INFO(DCDC3, "DCDC3", 900000, 3400000),
-	TPS65218_INFO(DCDC4, "DCDC4", 1175000, 3400000),
-	TPS65218_INFO(DCDC5, "DCDC5", 1000000, 1000000),
-	TPS65218_INFO(DCDC6, "DCDC6", 1800000, 1800000),
-	TPS65218_INFO(LDO1, "LDO1", 900000, 3400000),
-	TPS65218_INFO(LS3, "LS3", -1, -1),
-};
-
-#define TPS65218_OF_MATCH(comp, label) \
-	{ \
-		.compatible = comp, \
-		.data = &label, \
-	}
-
-static const struct of_device_id tps65218_of_match[] = {
-	TPS65218_OF_MATCH("ti,tps65218-dcdc1", tps65218_pmic_regs[DCDC1]),
-	TPS65218_OF_MATCH("ti,tps65218-dcdc2", tps65218_pmic_regs[DCDC2]),
-	TPS65218_OF_MATCH("ti,tps65218-dcdc3", tps65218_pmic_regs[DCDC3]),
-	TPS65218_OF_MATCH("ti,tps65218-dcdc4", tps65218_pmic_regs[DCDC4]),
-	TPS65218_OF_MATCH("ti,tps65218-dcdc5", tps65218_pmic_regs[DCDC5]),
-	TPS65218_OF_MATCH("ti,tps65218-dcdc6", tps65218_pmic_regs[DCDC6]),
-	TPS65218_OF_MATCH("ti,tps65218-ldo1", tps65218_pmic_regs[LDO1]),
-	TPS65218_OF_MATCH("ti,tps65218-ls3", tps65218_pmic_regs[LS3]),
-	{ }
-};
-MODULE_DEVICE_TABLE(of, tps65218_of_match);
-
 static int tps65218_pmic_set_voltage_sel(struct regulator_dev *dev,
 					 unsigned selector)
 {
@@ -251,92 +214,88 @@ static struct regulator_ops tps65218_dcdc56_pmic_ops = {
 };
 
 static const struct regulator_desc regulators[] = {
-	TPS65218_REGULATOR("DCDC1", TPS65218_DCDC_1, REGULATOR_VOLTAGE,
-			   tps65218_dcdc12_ops, 64, TPS65218_REG_CONTROL_DCDC1,
+	TPS65218_REGULATOR("DCDC1", "regulator-dcdc1", TPS65218_DCDC_1,
+			   REGULATOR_VOLTAGE, tps65218_dcdc12_ops, 64,
+			   TPS65218_REG_CONTROL_DCDC1,
 			   TPS65218_CONTROL_DCDC1_MASK, TPS65218_REG_ENABLE1,
 			   TPS65218_ENABLE1_DC1_EN, 0, 0, dcdc1_dcdc2_ranges,
 			   2, 4000, 0),
-	TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, REGULATOR_VOLTAGE,
-			   tps65218_dcdc12_ops, 64, TPS65218_REG_CONTROL_DCDC2,
+	TPS65218_REGULATOR("DCDC2", "regulator-dcdc2", TPS65218_DCDC_2,
+			   REGULATOR_VOLTAGE, tps65218_dcdc12_ops, 64,
+			   TPS65218_REG_CONTROL_DCDC2,
 			   TPS65218_CONTROL_DCDC2_MASK, TPS65218_REG_ENABLE1,
 			   TPS65218_ENABLE1_DC2_EN, 0, 0, dcdc1_dcdc2_ranges,
 			   2, 4000, 0),
-	TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, REGULATOR_VOLTAGE,
-			   tps65218_ldo1_dcdc34_ops, 64,
+	TPS65218_REGULATOR("DCDC3", "regulator-dcdc3", TPS65218_DCDC_3,
+			   REGULATOR_VOLTAGE, tps65218_ldo1_dcdc34_ops, 64,
 			   TPS65218_REG_CONTROL_DCDC3,
 			   TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1,
 			   TPS65218_ENABLE1_DC3_EN, 0, 0, ldo1_dcdc3_ranges, 2,
 			   0, 0),
-	TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, REGULATOR_VOLTAGE,
-			   tps65218_ldo1_dcdc34_ops, 53,
+	TPS65218_REGULATOR("DCDC4", "regulator-dcdc4", TPS65218_DCDC_4,
+			   REGULATOR_VOLTAGE, tps65218_ldo1_dcdc34_ops, 53,
 			   TPS65218_REG_CONTROL_DCDC4,
 			   TPS65218_CONTROL_DCDC4_MASK, TPS65218_REG_ENABLE1,
 			   TPS65218_ENABLE1_DC4_EN, 0, 0, dcdc4_ranges, 2,
 			   0, 0),
-	TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, REGULATOR_VOLTAGE,
-			   tps65218_dcdc56_pmic_ops, 1, -1, -1,
-			   TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC5_EN, 0, 0,
-			   NULL, 0, 0, 1000000),
-	TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, REGULATOR_VOLTAGE,
-			   tps65218_dcdc56_pmic_ops, 1, -1, -1,
-			   TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC6_EN, 0, 0,
-			   NULL, 0, 0, 1800000),
-	TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, REGULATOR_VOLTAGE,
-			   tps65218_ldo1_dcdc34_ops, 64,
+	TPS65218_REGULATOR("DCDC5", "regulator-dcdc5", TPS65218_DCDC_5,
+			   REGULATOR_VOLTAGE, tps65218_dcdc56_pmic_ops, 1, -1,
+			   -1, TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC5_EN, 0,
+			   0, NULL, 0, 0, 1000000),
+	TPS65218_REGULATOR("DCDC6", "regulator-dcdc6", TPS65218_DCDC_6,
+			   REGULATOR_VOLTAGE, tps65218_dcdc56_pmic_ops, 1, -1,
+			   -1, TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC6_EN, 0,
+			   0, NULL, 0, 0, 1800000),
+	TPS65218_REGULATOR("LDO1", "regulator-ldo1", TPS65218_LDO_1,
+			   REGULATOR_VOLTAGE, tps65218_ldo1_dcdc34_ops, 64,
 			   TPS65218_REG_CONTROL_LDO1,
 			   TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2,
 			   TPS65218_ENABLE2_LDO1_EN, 0, 0, ldo1_dcdc3_ranges,
 			   2, 0, 0),
-	TPS65218_REGULATOR("LS3", TPS65218_LS_3, REGULATOR_CURRENT,
-			   tps65218_ls3_ops, 0, 0, 0, TPS65218_REG_ENABLE2,
-			   TPS65218_ENABLE2_LS3_EN, TPS65218_REG_CONFIG2,
-			   TPS65218_CONFIG2_LS3ILIM_MASK, NULL, 0, 0, 0),
+	TPS65218_REGULATOR("LS3", "regulator-ls3", TPS65218_LS_3,
+			   REGULATOR_CURRENT, tps65218_ls3_ops, 0, 0, 0,
+			   TPS65218_REG_ENABLE2, TPS65218_ENABLE2_LS3_EN,
+			   TPS65218_REG_CONFIG2, TPS65218_CONFIG2_LS3ILIM_MASK,
+			   NULL, 0, 0, 0),
 };
 
 static int tps65218_regulator_probe(struct platform_device *pdev)
 {
 	struct tps65218 *tps = dev_get_drvdata(pdev->dev.parent);
-	struct regulator_init_data *init_data;
-	const struct tps_info	*template;
 	struct regulator_dev *rdev;
-	const struct of_device_id	*match;
 	struct regulator_config config = { };
-	int id;
-
-	match = of_match_device(tps65218_of_match, &pdev->dev);
-	if (!match)
-		return -ENODEV;
-
-	template = match->data;
-	id = template->id;
-	init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
-					       &regulators[id]);
+	int i;
 
-	platform_set_drvdata(pdev, tps);
-
-	tps->info[id] = &tps65218_pmic_regs[id];
 	config.dev = &pdev->dev;
-	config.init_data = init_data;
+	config.dev->of_node = tps->dev->of_node;
 	config.driver_data = tps;
 	config.regmap = tps->regmap;
-	config.of_node = pdev->dev.of_node;
 
-	rdev = devm_regulator_register(&pdev->dev, &regulators[id], &config);
-	if (IS_ERR(rdev)) {
-		dev_err(tps->dev, "failed to register %s regulator\n",
-			pdev->name);
-		return PTR_ERR(rdev);
+	for (i = 0; i < ARRAY_SIZE(regulators); i++) {
+		rdev = devm_regulator_register(&pdev->dev, &regulators[i],
+					       &config);
+		if (IS_ERR(rdev)) {
+			dev_err(tps->dev, "failed to register %s regulator\n",
+				pdev->name);
+			return PTR_ERR(rdev);
+		}
 	}
 
 	return 0;
 }
 
+static const struct platform_device_id tps65218_regulator_id_table[] = {
+	{ "tps65218-regulator", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, tps65218_regulator_id_table);
+
 static struct platform_driver tps65218_regulator_driver = {
 	.driver = {
 		.name = "tps65218-pmic",
-		.of_match_table = tps65218_of_match,
 	},
 	.probe = tps65218_regulator_probe,
+	.id_table = tps65218_regulator_id_table,
 };
 
 module_platform_driver(tps65218_regulator_driver);
-- 
1.9.1



From j-keerthy at ti.com  Tue May 10 22:48:08 2016
From: j-keerthy at ti.com (Keerthy)
Date: Wed, 11 May 2016 11:18:08 +0530
Subject: [PATCH 5/8] ARM: dts: AM437X-GP-EVM: Remove redundant regulator
 compatibles
In-Reply-To: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
References: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
Message-ID: <1462945691-904-6-git-send-email-j-keerthy@ti.com>

With the device tree parsing using the regulator framework
there is a no longer a need for separate compatibles for
individual regulator nodes. Hence removing them all.

Signed-off-by: Keerthy <j-keerthy at ti.com>
---
 arch/arm/boot/dts/am437x-gp-evm.dts | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts
index 8889be1..67329e0 100644
--- a/arch/arm/boot/dts/am437x-gp-evm.dts
+++ b/arch/arm/boot/dts/am437x-gp-evm.dts
@@ -513,7 +513,6 @@
 		#interrupt-cells = <2>;
 
 		dcdc1: regulator-dcdc1 {
-			compatible = "ti,tps65218-dcdc1";
 			regulator-name = "vdd_core";
 			regulator-min-microvolt = <912000>;
 			regulator-max-microvolt = <1144000>;
@@ -522,7 +521,6 @@
 		};
 
 		dcdc2: regulator-dcdc2 {
-			compatible = "ti,tps65218-dcdc2";
 			regulator-name = "vdd_mpu";
 			regulator-min-microvolt = <912000>;
 			regulator-max-microvolt = <1378000>;
@@ -531,7 +529,6 @@
 		};
 
 		dcdc3: regulator-dcdc3 {
-			compatible = "ti,tps65218-dcdc3";
 			regulator-name = "vdcdc3";
 			regulator-min-microvolt = <1500000>;
 			regulator-max-microvolt = <1500000>;
@@ -539,7 +536,6 @@
 			regulator-always-on;
 		};
 		dcdc5: regulator-dcdc5 {
-			compatible = "ti,tps65218-dcdc5";
 			regulator-name = "v1_0bat";
 			regulator-min-microvolt = <1000000>;
 			regulator-max-microvolt = <1000000>;
@@ -548,7 +544,6 @@
 		};
 
 		dcdc6: regulator-dcdc6 {
-			compatible = "ti,tps65218-dcdc6";
 			regulator-name = "v1_8bat";
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
@@ -557,7 +552,6 @@
 		};
 
 		ldo1: regulator-ldo1 {
-			compatible = "ti,tps65218-ldo1";
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
 			regulator-boot-on;
-- 
1.9.1



From j-keerthy at ti.com  Tue May 10 22:48:09 2016
From: j-keerthy at ti.com (Keerthy)
Date: Wed, 11 May 2016 11:18:09 +0530
Subject: [PATCH 6/8] ARM: dts: AM437X-SK-EVM: Remove redundant regulator
 compatibles
In-Reply-To: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
References: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
Message-ID: <1462945691-904-7-git-send-email-j-keerthy@ti.com>

With the device tree parsing using the regulator framework
there is a no longer a need for separate compatibles for
individual regulator nodes. Hence removing them all.

Signed-off-by: Keerthy <j-keerthy at ti.com>
---
 arch/arm/boot/dts/am437x-sk-evm.dts | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts
index d82dd6e..1b404fd 100644
--- a/arch/arm/boot/dts/am437x-sk-evm.dts
+++ b/arch/arm/boot/dts/am437x-sk-evm.dts
@@ -428,7 +428,6 @@
 		#interrupt-cells = <2>;
 
 		dcdc1: regulator-dcdc1 {
-			compatible = "ti,tps65218-dcdc1";
 			/* VDD_CORE limits min of OPP50 and max of OPP100 */
 			regulator-name = "vdd_core";
 			regulator-min-microvolt = <912000>;
@@ -438,7 +437,6 @@
 		};
 
 		dcdc2: regulator-dcdc2 {
-			compatible = "ti,tps65218-dcdc2";
 			/* VDD_MPU limits min of OPP50 and max of OPP_NITRO */
 			regulator-name = "vdd_mpu";
 			regulator-min-microvolt = <912000>;
@@ -448,7 +446,6 @@
 		};
 
 		dcdc3: regulator-dcdc3 {
-			compatible = "ti,tps65218-dcdc3";
 			regulator-name = "vdds_ddr";
 			regulator-min-microvolt = <1500000>;
 			regulator-max-microvolt = <1500000>;
@@ -457,7 +454,6 @@
 		};
 
 		dcdc4: regulator-dcdc4 {
-			compatible = "ti,tps65218-dcdc4";
 			regulator-name = "v3_3d";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
@@ -466,7 +462,6 @@
 		};
 
 		ldo1: regulator-ldo1 {
-			compatible = "ti,tps65218-ldo1";
 			regulator-name = "v1_8d";
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
-- 
1.9.1



From j-keerthy at ti.com  Tue May 10 22:48:11 2016
From: j-keerthy at ti.com (Keerthy)
Date: Wed, 11 May 2016 11:18:11 +0530
Subject: [PATCH 8/8] ARM: dts: AM43X-EPOS-EVM: Remove redundant regulator
 compatibles
In-Reply-To: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
References: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
Message-ID: <1462945691-904-9-git-send-email-j-keerthy@ti.com>

With the device tree parsing using the regulator framework
there is a no longer a need for separate compatibles for
individual regulator nodes. Hence removing them all.

Signed-off-by: Keerthy <j-keerthy at ti.com>
---
 arch/arm/boot/dts/am43x-epos-evm.dts | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts
index d5dd720..4599d23 100644
--- a/arch/arm/boot/dts/am43x-epos-evm.dts
+++ b/arch/arm/boot/dts/am43x-epos-evm.dts
@@ -421,7 +421,6 @@
 		#interrupt-cells = <2>;
 
 		dcdc1: regulator-dcdc1 {
-			compatible = "ti,tps65218-dcdc1";
 			regulator-name = "vdd_core";
 			regulator-min-microvolt = <912000>;
 			regulator-max-microvolt = <1144000>;
@@ -430,7 +429,6 @@
 		};
 
 		dcdc2: regulator-dcdc2 {
-			compatible = "ti,tps65218-dcdc2";
 			regulator-name = "vdd_mpu";
 			regulator-min-microvolt = <912000>;
 			regulator-max-microvolt = <1378000>;
@@ -439,7 +437,6 @@
 		};
 
 		dcdc3: regulator-dcdc3 {
-			compatible = "ti,tps65218-dcdc3";
 			regulator-name = "vdcdc3";
 			regulator-min-microvolt = <1500000>;
 			regulator-max-microvolt = <1500000>;
@@ -448,7 +445,6 @@
 		};
 
 		dcdc4: regulator-dcdc4 {
-			compatible = "ti,tps65218-dcdc4";
 			regulator-name = "vdcdc4";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
@@ -457,21 +453,18 @@
 		};
 
 		dcdc5: regulator-dcdc5 {
-			compatible = "ti,tps65218-dcdc5";
 			regulator-name = "v1_0bat";
 			regulator-min-microvolt = <1000000>;
 			regulator-max-microvolt = <1000000>;
 		};
 
 		dcdc6: regulator-dcdc6 {
-			compatible = "ti,tps65218-dcdc6";
 			regulator-name = "v1_8bat";
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
 		};
 
 		ldo1: regulator-ldo1 {
-			compatible = "ti,tps65218-ldo1";
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
 			regulator-boot-on;
-- 
1.9.1



From j-keerthy at ti.com  Tue May 10 22:48:10 2016
From: j-keerthy at ti.com (Keerthy)
Date: Wed, 11 May 2016 11:18:10 +0530
Subject: [PATCH 7/8] ARM: dts: AM437X-CM-T43: Remove redundant regulator
 compatibles
In-Reply-To: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
References: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
Message-ID: <1462945691-904-8-git-send-email-j-keerthy@ti.com>

With the device tree parsing using the regulator framework
there is a no longer a need for separate compatibles for
individual regulator nodes. Hence removing them all.

Signed-off-by: Keerthy <j-keerthy at ti.com>
---
 arch/arm/boot/dts/am437x-cm-t43.dts | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/arch/arm/boot/dts/am437x-cm-t43.dts b/arch/arm/boot/dts/am437x-cm-t43.dts
index 9551c47..9e92d48 100644
--- a/arch/arm/boot/dts/am437x-cm-t43.dts
+++ b/arch/arm/boot/dts/am437x-cm-t43.dts
@@ -209,7 +209,6 @@
 		#interrupt-cells = <2>;
 
 		dcdc1: regulator-dcdc1 {
-			compatible = "ti,tps65218-dcdc1";
 			regulator-name = "vdd_core";
 			regulator-min-microvolt = <912000>;
 			regulator-max-microvolt = <1144000>;
@@ -218,7 +217,6 @@
 		};
 
 		dcdc2: regulator-dcdc2 {
-			compatible = "ti,tps65218-dcdc2";
 			regulator-name = "vdd_mpu";
 			regulator-min-microvolt = <912000>;
 			regulator-max-microvolt = <1378000>;
@@ -227,7 +225,6 @@
 		};
 
 		dcdc3: regulator-dcdc3 {
-			compatible = "ti,tps65218-dcdc3";
 			regulator-name = "vdcdc3";
 			regulator-suspend-enable;
 			regulator-min-microvolt = <1500000>;
@@ -237,7 +234,6 @@
 		};
 
 		dcdc5: regulator-dcdc5 {
-			compatible = "ti,tps65218-dcdc5";
 			regulator-name = "v1_0bat";
 			regulator-min-microvolt = <1000000>;
 			regulator-max-microvolt = <1000000>;
@@ -246,7 +242,6 @@
 		};
 
 		dcdc6: regulator-dcdc6 {
-			compatible = "ti,tps65218-dcdc6";
 			regulator-name = "v1_8bat";
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
@@ -255,7 +250,6 @@
 		};
 
 		ldo1: regulator-ldo1 {
-			compatible = "ti,tps65218-ldo1";
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
 			regulator-boot-on;
-- 
1.9.1



From k.kozlowski at samsung.com  Tue May 10 23:27:11 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 08:27:11 +0200
Subject: [PATCH 2/2] ARM: multi_v7_defconfig: Enable Exynos MFC driver as
 module
In-Reply-To: <1462914448-24480-2-git-send-email-javier@osg.samsung.com>
References: <1462914448-24480-1-git-send-email-javier@osg.samsung.com>
 <1462914448-24480-2-git-send-email-javier@osg.samsung.com>
Message-ID: <5732D0BF.3020207@samsung.com>

On 05/10/2016 11:07 PM, Javier Martinez Canillas wrote:
> Exynos SoCs have a Multi Format Video Hardware Codec (MFC) IP block that
> can be used to {en,de}code video streams by hardware. Enable support for
> its driver as a module so the MFC can be tested.
> 
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
> 
> ---
> 
> This patch depends on https://patchwork.kernel.org/patch/8970711/
> 
>  arch/arm/configs/multi_v7_defconfig | 1 +
>  1 file changed, 1 insertion(+)


Both patches look good but only exynos_defconfig ended in Patchwork.
This one did not... because you forgot to Cc the samsung-soc list.

Best regards,
Krzysztod


From moinejf at free.fr  Tue May 10 23:46:33 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Wed, 11 May 2016 08:46:33 +0200
Subject: [PATCH 08/16] clk: sunxi-ng: Add M-factor clock support
In-Reply-To: <1462737711-10017-9-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-9-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <20160511084633.29b56effa514996ffafd56ef@free.fr>

On Sun,  8 May 2016 22:01:43 +0200
Maxime Ripard <maxime.ripard at free-electrons.com> wrote:

> Introduce support for clocks that divide by a linear factor.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile |   1 +
>  drivers/clk/sunxi-ng/ccu_m.c  | 135 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_m.h  | 101 +++++++++++++++++++++++++++++++
>  3 files changed, 237 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_m.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_m.h
> 
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index a47a3bbdf285..f41de901c607 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -4,5 +4,6 @@ obj-y += ccu_reset.o
>  obj-y += ccu_div_table.o
>  obj-y += ccu_fixed_factor.o
>  obj-y += ccu_gate.o
> +obj-y += ccu_m.o
>  obj-y += ccu_mux.o
>  obj-y += ccu_phase.o
> diff --git a/drivers/clk/sunxi-ng/ccu_m.c b/drivers/clk/sunxi-ng/ccu_m.c
> new file mode 100644
> index 000000000000..424eb6da0d5b
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_m.c
> @@ -0,0 +1,135 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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.
> + */
	[snip]
> +static int ccu_m_set_rate(struct clk_hw *hw, unsigned long rate,
> +			  unsigned long parent_rate)
> +{
> +	struct ccu_m *cm = hw_to_ccu_m(hw);
> +	unsigned long flags;
> +	unsigned int m;
> +	u32 reg;
> +
> +	ccu_m_find_best(parent_rate, rate, 1 << cm->m.width, &m);
> +
> +	spin_lock_irqsave(cm->common.lock, flags);
> +
> +	reg = readl(cm->common.base + cm->common.reg);
> +	reg &= ((1 << cm->m.width) - 1) << cm->m.shift;

Bug:
	reg &= ~GENMASK(cm->m.width + cm->m.shift, cm->m.shift);

> +
> +	writel(reg | ((m - 1) << cm->m.shift),
> +	       cm->common.base + cm->common.reg);
> +
> +	spin_unlock_irqrestore(cm->common.lock, flags);
> +
> +	return 0;
> +}
	[snip]

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From k.kozlowski at samsung.com  Wed May 11 00:06:52 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 09:06:52 +0200
Subject: [PATCH] ARM: dts: exynos: Enable AX88760 USB hub on Origen board
Message-ID: <1462950412-16681-1-git-send-email-k.kozlowski@samsung.com>

From: Matthew Leach <matthew at mattleach.net>

Enable the Origen's usb phy and ohci devices in the device tree.  Also
add the "samsung,vbus-gpio" property to enable the GPX3(5) gpio pin so
the AX88760 hub is powered.

Signed-off-by: Matthew Leach <matthew at mattleach.net>
[k.kozlowski: Extend nodes by label notation instead of path]
Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm/boot/dts/exynos4412-origen.dts | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts
index 8bca699b7f20..4c59bdb0e6f3 100644
--- a/arch/arm/boot/dts/exynos4412-origen.dts
+++ b/arch/arm/boot/dts/exynos4412-origen.dts
@@ -77,12 +77,29 @@
 			clock-frequency = <24000000>;
 		};
 	};
+
 };
 
 &cpu0 {
 	cpu0-supply = <&buck2_reg>;
 };
 
+&exynos_usbphy {
+	status = "okay";
+};
+
+&ehci {
+	samsung,vbus-gpio = <&gpx3 5 1>;
+	status = "okay";
+
+	port at 1{
+		status = "okay";
+	};
+	port at 2 {
+		status = "okay";
+	};
+};
+
 &fimd {
 	pinctrl-0 = <&lcd_clk &lcd_data24 &pwm1_out>;
 	pinctrl-names = "default";
-- 
1.9.1



From maxime.ripard at free-electrons.com  Wed May 11 00:12:06 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 11 May 2016 09:12:06 +0200
Subject: [PATCH] devicetree: sunxi: Add OLinuXino Lime2 eMMC to the
 Makefile
In-Reply-To: <1462906820-5203-1-git-send-email-oliver@schinagl.nl>
References: <1462906820-5203-1-git-send-email-oliver@schinagl.nl>
Message-ID: <20160511071206.GN3733@lukather>

Hi Oliver,

On Tue, May 10, 2016 at 09:00:20PM +0200, Olliver Schinagl wrote:
> ARM: dts: sunxi: Add a olinuxino-lime2-emmc added the new emmc equipped
> lime2 but forgot its Makefile. This patch adds an entry to the Makefile.
> 
> Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>
> ---
> Maxime, I'm sorry for ommitting the Makefile initially, if it is not merged yet,
> maybe just squash it with the previous patch?

It's merged, and have been sent to armsoc.

Please resend with arm at kernel.org, asking them to apply it directly
(and keep chen-yu and I in cc).

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160511/ecdea871/attachment.sig>

From heiko at sntech.de  Wed May 11 00:11:00 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 11 May 2016 09:11 +0200
Subject: [PATCH v2] pinctrl: rockchip: fix pull setting error for rk3399
In-Reply-To: <1462937968-4952-1-git-send-email-wxt@rock-chips.com>
References: <1462937968-4952-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1493162.roERW60dFE@phil>

Am Mittwoch, 11. Mai 2016, 11:39:28 schrieb Caesar Wang:
> From: David Wu <david.wu at rock-chips.com>
> 
> This patch fixes the pinctrl pull bias setting, since the pull up/down
> setting is the contrary for gpio0(just the gpio0a and gpio0b) and
> gpio2(just the gpio2c and gpio2d).
> 
> From the TRM said, the gpio0a pull polarity setting:
> gpio0a_p
> GPIO0A PE/PS programmation section, every
> GPIO bit corresponding to 2bits[PS:PE]
> 2'b00: Z(Normal operation);
> 2'b11: weak 1(pull-up);
> 2'b01: weak 0(pull-down);
> 2'b10: Z(Normal operation);

This could mention gpio2c and gpio2d as well, as the code now does.

Otherwise the patch looks good and I also compared with the TRM, so

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



From linux.amoon at gmail.com  Wed May 11 00:28:30 2016
From: linux.amoon at gmail.com (Anand Moon)
Date: Wed, 11 May 2016 12:58:30 +0530
Subject: [PATCH] ARM: dts: exynos: Only Odroid XU3-family boards use DTSI
 with CPU thermal nodes
In-Reply-To: <5732C7DF.2080800@samsung.com>
References: <1462774789-15360-1-git-send-email-k.kozlowski@samsung.com>
 <CANAwSgT9SY3kj8+beMpc1xGoC=rMBSya+2v2dyZQp6ykH+V0=g@mail.gmail.com>
 <573198BE.6020900@samsung.com>
 <CANAwSgTy6p9AVmmOWATpSO1JqVbwE0v+y_y-RLd+32RnNJTA+Q@mail.gmail.com>
 <5731D764.8070007@samsung.com>
 <CANAwSgRsjdQh6ygT__5XcH8-cF9Ch+zbk8oupebwYzY1kCZu6g@mail.gmail.com>
 <5731EA1B.4070201@samsung.com>
 <CANAwSgQGhrBca7=Ow8+Hh9t0W9HWp=F43KR0Frfpx9fGngPSaw@mail.gmail.com>
 <5732C7DF.2080800@samsung.com>
Message-ID: <CANAwSgQHHE=USgjea4DpySC7T2+t7Ta8LuyL36cz3DpiyDgaWg@mail.gmail.com>

Hi Krzysztof,

On 11 May 2016 at 11:19, Krzysztof Kozlowski <k.kozlowski at samsung.com> wrote:
> On 05/10/2016 09:45 PM, Anand Moon wrote:
>> Hi Krzysztof,
>>
>> Sorry I am not able to explain my self clearly.
>> But I have once gain tested these changes.
>>
>> Only could you append with following changes.
>> --------------------------------------------------------
>> +                               cpu_crit0: cpu-crit-0 {
>> +                                       temperature = <120000>; /*
>> millicelsius */
>> +                                       hysteresis = <5000>; /* millicelsius */
>> +                                       type = "critical";
>> +                               };
>> --------------------------------------------------------
>> hysteresis time help to adjust the present and past temperature inputs
>> before critical shutdown.
>
> I need more details why you want this patch. What is the point of
> hysteresis on critical trip point? When reaching this trip point the
> system shutdowns... there is nothing more to do, I think.

Ok you are correct and I am completely wrong, It dose not critical
temperate so easily.

>
> Best regards,
> Krzysztof
>

I have enable CONFIG_DYNAMIC_DEBUG and tested with following.

# echo 'module thermal_sys +fp' > /sys/kernel/debug/dynamic_debug/control

Below is the  output of console for stress testing.
[ 1728.744182] update_temperature: thermal thermal_zone3:
last_temperature=92000, current_temperature=92000
[ 1728.744211] thermal_zone_trip_update: thermal thermal_zone3:
Trip0[type=0,temp=85000]:trend=0,throttle=1
[ 1728.744231] thermal_zone_trip_update: thermal thermal_zone3:
Trip1[type=0,temp=103000]:trend=0,throttle=0
[ 1728.744248] thermal_zone_trip_update: thermal thermal_zone3:
Trip2[type=0,temp=110000]:trend=0,throttle=0
[ 1728.755227] update_temperature: thermal thermal_zone2:
last_temperature=86000, current_temperature=86000
[ 1728.755269] thermal_zone_trip_update: thermal thermal_zone2:
Trip0[type=0,temp=85000]:trend=0,throttle=1
[ 1728.755306] thermal_zone_trip_update: thermal thermal_zone2:
Trip1[type=0,temp=103000]:trend=0,throttle=0
[ 1728.755340] thermal_zone_trip_update: thermal thermal_zone2:
Trip2[type=0,temp=110000]:trend=0,throttle=0
[ 1728.964753] update_temperature: thermal thermal_zone0:
last_temperature=78000, current_temperature=83000
[ 1728.964782] thermal_zone_trip_update: thermal thermal_zone0:
Trip0[type=0,temp=50000]:trend=1,throttle=1
[ 1728.964797] get_target_state: thermal cooling_device0: cur_state=2
[ 1728.964810] thermal_zone_trip_update: thermal cooling_device0:
old_target=1, target=1
[ 1728.964837] thermal_zone_trip_update: thermal thermal_zone0:
Trip1[type=0,temp=60000]:trend=1,throttle=1
[ 1728.964850] get_target_state: thermal cooling_device0: cur_state=2
[ 1728.964861] thermal_zone_trip_update: thermal cooling_device0:
old_target=1, target=2
[ 1728.964875] thermal_cdev_update: thermal cooling_device0: zone0->target=1
[ 1728.964886] thermal_cdev_update: thermal cooling_device0: zone0->target=2
[ 1728.964897] thermal_cdev_update: thermal cooling_device0: zone0->target=2
[ 1728.964909] thermal_cdev_update: thermal cooling_device0: set to state 2
[ 1728.964925] thermal_zone_trip_update: thermal thermal_zone0:
Trip2[type=0,temp=70000]:trend=1,throttle=1
[ 1728.964937] get_target_state: thermal cooling_device0: cur_state=2
[ 1728.964948] thermal_zone_trip_update: thermal cooling_device0:
old_target=2, target=3
[ 1728.964962] thermal_cdev_update: thermal cooling_device0: zone0->target=1
[ 1728.964973] thermal_cdev_update: thermal cooling_device0: zone0->target=2
[ 1728.964983] thermal_cdev_update: thermal cooling_device0: zone0->target=3
[ 1728.965000] thermal_cdev_update: thermal cooling_device0: set to state 3
[ 1728.965019] thermal_zone_trip_update: thermal thermal_zone0:
Trip4[type=1,temp=70000]:trend=1,throttle=1

Ok I admit that thermal throttle is working correctly on my Odroid XU4.
Opps .... Sorry for the trouble.

Best Regards
-Anand Moon


From narmstrong at baylibre.com  Wed May 11 00:31:56 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Wed, 11 May 2016 09:31:56 +0200
Subject: [PATCH 1/2] clocksource: sp804: Add support for OX810SE 24bit
 timer width
In-Reply-To: <20160426163055.GB13887@linaro.org>
References: <1459520559-13110-1-git-send-email-narmstrong@baylibre.com>
 <1459520559-13110-2-git-send-email-narmstrong@baylibre.com>
 <20160422074645.GA3974@linaro.org> <alpine.DEB.2.11.1604220953000.3941@nanos>
 <571E2E38.3060401@baylibre.com> <20160426163055.GB13887@linaro.org>
Message-ID: <5732DFEC.6070605@baylibre.com>

On 04/26/2016 06:30 PM, Daniel Lezcano wrote:
> On Mon, Apr 25, 2016 at 04:48:24PM +0200, Neil Armstrong wrote:
>> On 04/22/2016 09:53 AM, Thomas Gleixner wrote:
>>> On Fri, 22 Apr 2016, Daniel Lezcano wrote:
>>>
>>>> On Fri, Apr 01, 2016 at 04:22:38PM +0200, Neil Armstrong wrote:
>>>>> In order to support the Dual-Timer on the Oxford Semiconductor OX810SE SoC,
>>>>> implement variable counter width, keeping 32bit as default width.
>>>>> Add new compatible string oxsemi,ox810se-rps-timer in order to select
>>>>> the 24bit counter width.
>>>>>
>>>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>>>> ---
>>>>>  drivers/clocksource/timer-sp804.c | 107 ++++++++++++++++++++++++--------------
>>>>>  include/clocksource/timer-sp804.h |  42 ++++++++++++---
>>>>>  2 files changed, 102 insertions(+), 47 deletions(-)
>>>>
>>>> I will take those patches but this driver really deserves a cleanup.
>>>
>>> If it deserves a cleanup, then this should happen _BEFORE_ we add new
>>> functionality to it.
>>>
>>> Thanks,
>>>
>>> 	tglx
>>>
>>
>> Hi Thomas, Daniel,
>>
>> Sure this driver should have a cleanup, but it still depends on old legacy vexpress calls.
>>
>> The reason I submitted a change and a small cleanup over this driver is because the high
>> similarities of the HW and avoiding adding a brand new driver cloning much of its
>> functionalities.
> 
> Hi Neil,
> 
> it is a good idea to avoid having new drivers when it is possible to group 
> them into a single one.
>  
>> I propose to study an eventual cleanup, but could this change be submitted for 4.7 since
>> it's part of a base platform support serie ?
> 
> I am not against if the next patches you send are cleanups.
> 
> Thomas ?
> 

Hi Thomas,

Is the proposition acceptable ? When this patchset will hit 4.7, I will work on a rework for 4.8.

Thanks,
Neil




From narmstrong at baylibre.com  Wed May 11 00:34:22 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Wed, 11 May 2016 09:34:22 +0200
Subject: [PATCH v2 2/2] dt-bindings: Add Oxford Semiconductor OXNAS pinctrl
 and gpio bindings
In-Reply-To: <1462952062-5316-1-git-send-email-narmstrong@baylibre.com>
References: <1462952062-5316-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1462952062-5316-3-git-send-email-narmstrong@baylibre.com>

Add pinctrl and gpio DT bindings for Oxford Semiconductor OXNAS SoC Family.
This version supports the ARM926EJ-S based OX810SE SoC with 34 IO pins.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 .../devicetree/bindings/gpio/gpio_oxnas.txt        | 47 ++++++++++++++++++
 .../devicetree/bindings/pinctrl/oxnas,pinctrl.txt  | 57 ++++++++++++++++++++++
 2 files changed, 104 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt

diff --git a/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
new file mode 100644
index 0000000..928ed4f
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
@@ -0,0 +1,47 @@
+* Oxford Semiconductor OXNAS SoC GPIO Controller
+
+Please refer to gpio.txt for generic information regarding GPIO bindings.
+
+Required properties:
+ - compatible: "oxsemi,ox810se-gpio"
+ - reg: Base address and length for the device.
+ - interrupts: The port interrupt shared by all pins.
+ - gpio-controller: Marks the port as GPIO controller.
+ - #gpio-cells: Two. The first cell is the pin number and
+   the second cell is used to specify the gpio polarity as defined in
+   defined in <dt-bindings/gpio/gpio.h>:
+      0 = GPIO_ACTIVE_HIGH
+      1 = GPIO_ACTIVE_LOW
+ - interrupt-controller: Marks the device node as an interrupt controller.
+ - #interrupt-cells: Two. The first cell is the GPIO number and second cell
+   is used to specify the trigger type as defined in
+   <dt-bindings/interrupt-controller/irq.h>:
+      IRQ_TYPE_EDGE_RISING
+      IRQ_TYPE_EDGE_FALLING
+      IRQ_TYPE_EDGE_BOTH
+ - gpio-ranges: Interaction with the PINCTRL subsystem, it also specifies the
+   gpio base and count, should be in the format of numeric-gpio-range as
+   specified in the gpio.txt file.
+
+Example:
+
+gpio0: gpio at 0 {
+	compatible = "oxsemi,ox810se-gpio";
+	reg = <0x000000 0x100000>;
+	interrupts = <21>;
+	#gpio-cells = <2>;
+	gpio-controller;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+	gpio-ranges = <&pinctrl 0 0 32>;
+};
+
+keys {
+	...
+
+	button-esc {
+		label = "ESC";
+		linux,code = <1>;
+		gpios = <&gpio0 12 0>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt
new file mode 100644
index 0000000..d607432
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt
@@ -0,0 +1,57 @@
+* Oxford Semiconductor OXNAS SoC Family Pin Controller
+
+Please refer to pinctrl-bindings.txt, ../gpio/gpio.txt, and
+../interrupt-controller/interrupts.txt for generic information regarding
+pin controller, GPIO, and interrupt bindings.
+
+OXNAS 'pin configuration node' is a node of a group of pins which can be
+used for a specific device or function. This node represents configurations of
+pins, optional function, and optional mux related configuration.
+
+Required properties for pin controller node:
+ - compatible: "oxsemi,ox810se-pinctrl"
+ - oxsemi,sys-ctrl: a phandle to the system controller syscon node
+
+Required properties for pin configuration sub-nodes:
+ - pins: List of pins to which the configuration applies.
+
+Optional properties for pin configuration sub-nodes:
+----------------------------------------------------
+ - function: Mux function for the specified pins.
+ - bias-pull-up: Enable weak pull-up.
+
+Example:
+
+pinctrl: pinctrl {
+	compatible = "oxsemi,ox810se-pinctrl";
+
+	/* Regmap for sys registers */
+	oxsemi,sys-ctrl = <&sys>;
+
+	pinctrl_uart2: pinctrl_uart2 {
+		uart2a {
+			pins = "gpio31";
+			function = "fct3";
+		};
+		uart2b {
+			pins = "gpio32";
+			function = "fct3";
+		};
+	};
+};
+
+uart2: serial at 900000 {
+	compatible = "ns16550a";
+	reg = <0x900000 0x100000>;
+	clocks = <&sysclk>;
+	interrupts = <29>;
+	reg-shift = <0>;
+	fifo-size = <16>;
+	reg-io-width = <1>;
+	current-speed = <115200>;
+	no-loopback-test;
+	status = "disabled";
+	resets = <&reset 22>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+};
-- 
1.9.1



From narmstrong at baylibre.com  Wed May 11 00:34:20 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Wed, 11 May 2016 09:34:20 +0200
Subject: [PATCH v2 0/2] pinctrl: Oxford Semiconductor OXNAS pinctrl and gpio
 support
Message-ID: <1462952062-5316-1-git-send-email-narmstrong@baylibre.com>

This patchset includes support for the pinctrl and gpio controller of the
Oxford Semiconductor OXNAS SoC Family.

Changes since v1 : http://lkml.kernel.org/r/1459689969-5326-1-git-send-email-narmstrong at baylibre.com
- Fix gpio bindings
- remove irqd_to_bank abstraction

It was originally posted part of a platform patchset available here :
http://lkml.kernel.org/r/1458838215-23314-1-git-send-email-narmstrong at baylibre.com

Changes since v3 global patchset :
- Get rid of PLX Technology, replace by Oxford Semiconductor
- Get rid of gpio-bank and ngpios properties, now using gpio-ranges

Neil Armstrong (2):
  pinctrl: Add Oxford Semiconductor OXNAS pinctrl and gpio driver
  dt-bindings: Add Oxford Semiconductor OXNAS pinctrl and gpio bindings

 .../devicetree/bindings/gpio/gpio_oxnas.txt        |  47 ++
 .../devicetree/bindings/pinctrl/oxnas,pinctrl.txt  |  57 ++
 drivers/pinctrl/Kconfig                            |  11 +
 drivers/pinctrl/Makefile                           |   1 +
 drivers/pinctrl/pinctrl-oxnas.c                    | 835 +++++++++++++++++++++
 5 files changed, 951 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt
 create mode 100644 drivers/pinctrl/pinctrl-oxnas.c

-- 
1.9.1



From narmstrong at baylibre.com  Wed May 11 00:34:21 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Wed, 11 May 2016 09:34:21 +0200
Subject: [PATCH v2 1/2] pinctrl: Add Oxford Semiconductor OXNAS pinctrl and
 gpio driver
In-Reply-To: <1462952062-5316-1-git-send-email-narmstrong@baylibre.com>
References: <1462952062-5316-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1462952062-5316-2-git-send-email-narmstrong@baylibre.com>

Add pinctrl and gpio control support to Oxford Semiconductor OXNAS SoC Family.
This version supports the ARM926EJ-S based OX810SE SoC with 34 IO pins.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/pinctrl/Kconfig         |  11 +
 drivers/pinctrl/Makefile        |   1 +
 drivers/pinctrl/pinctrl-oxnas.c | 835 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 847 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-oxnas.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index fb8200b..f06589c 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -129,6 +129,17 @@ config PINCTRL_MESON
 	select OF_GPIO
 	select REGMAP_MMIO
 
+config PINCTRL_OXNAS
+	bool
+	depends on OF
+	select PINMUX
+	select PINCONF
+	select GENERIC_PINCONF
+	select GPIOLIB
+	select OF_GPIO
+	select GPIOLIB_IRQCHIP
+	select MFD_SYSCON
+
 config PINCTRL_ROCKCHIP
 	bool
 	select PINMUX
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index e4bc115..f678343 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_AMD)	+= pinctrl-amd.o
 obj-$(CONFIG_PINCTRL_DIGICOLOR)	+= pinctrl-digicolor.o
 obj-$(CONFIG_PINCTRL_FALCON)	+= pinctrl-falcon.o
 obj-$(CONFIG_PINCTRL_MESON)	+= meson/
+obj-$(CONFIG_PINCTRL_OXNAS)	+= pinctrl-oxnas.o
 obj-$(CONFIG_PINCTRL_PALMAS)	+= pinctrl-palmas.o
 obj-$(CONFIG_PINCTRL_PIC32)	+= pinctrl-pic32.o
 obj-$(CONFIG_PINCTRL_PISTACHIO)	+= pinctrl-pistachio.o
diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c
new file mode 100644
index 0000000..5fd113c
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-oxnas.c
@@ -0,0 +1,835 @@
+/*
+ * Oxford Semiconductor OXNAS SoC Family pinctrl driver
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Based on pinctrl-pic32.c
+ * Joshua Henderson, <joshua.henderson at microchip.com>
+ * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "pinctrl-utils.h"
+
+#define PINS_PER_BANK		32
+
+#define GPIO_BANK_START(bank)		((bank) * PINS_PER_BANK)
+
+/* Regmap Offsets */
+#define PINMUX_PRIMARY_SEL0	0x0c
+#define PINMUX_SECONDARY_SEL0	0x14
+#define PINMUX_TERTIARY_SEL0	0x8c
+#define PINMUX_PRIMARY_SEL1	0x10
+#define PINMUX_SECONDARY_SEL1	0x18
+#define PINMUX_TERTIARY_SEL1	0x90
+#define PINMUX_PULLUP_CTRL0	0xac
+#define PINMUX_PULLUP_CTRL1	0xb0
+
+/* GPIO Registers */
+#define INPUT_VALUE	0x00
+#define IRQ_PENDING	0x0c
+#define OUTPUT_SET	0x14
+#define OUTPUT_CLEAR	0x18
+#define OUTPUT_EN_SET	0x1c
+#define OUTPUT_EN_CLEAR	0x20
+#define RE_IRQ_ENABLE	0x28
+#define FE_IRQ_ENABLE	0x2c
+
+struct oxnas_function {
+	const char *name;
+	const char * const *groups;
+	unsigned int ngroups;
+};
+
+struct oxnas_pin_group {
+	const char *name;
+	unsigned int pin;
+	unsigned int bank;
+	struct oxnas_desc_function *functions;
+};
+
+struct oxnas_desc_function {
+	const char *name;
+	unsigned int fct;
+};
+
+struct oxnas_gpio_bank {
+	void __iomem *reg_base;
+	struct gpio_chip gpio_chip;
+	struct irq_chip irq_chip;
+	unsigned int id;
+};
+
+struct oxnas_pinctrl {
+	struct regmap *regmap;
+	struct device *dev;
+	struct pinctrl_dev *pctldev;
+	const struct pinctrl_pin_desc *pins;
+	unsigned int npins;
+	const struct oxnas_function *functions;
+	unsigned int nfunctions;
+	const struct oxnas_pin_group *groups;
+	unsigned int ngroups;
+	struct oxnas_gpio_bank *gpio_banks;
+	unsigned int nbanks;
+};
+
+static const struct pinctrl_pin_desc oxnas_pins[] = {
+	PINCTRL_PIN(0, "gpio0"),
+	PINCTRL_PIN(1, "gpio1"),
+	PINCTRL_PIN(2, "gpio2"),
+	PINCTRL_PIN(3, "gpio3"),
+	PINCTRL_PIN(4, "gpio4"),
+	PINCTRL_PIN(5, "gpio5"),
+	PINCTRL_PIN(6, "gpio6"),
+	PINCTRL_PIN(7, "gpio7"),
+	PINCTRL_PIN(8, "gpio8"),
+	PINCTRL_PIN(9, "gpio9"),
+	PINCTRL_PIN(10, "gpio10"),
+	PINCTRL_PIN(11, "gpio11"),
+	PINCTRL_PIN(12, "gpio12"),
+	PINCTRL_PIN(13, "gpio13"),
+	PINCTRL_PIN(14, "gpio14"),
+	PINCTRL_PIN(15, "gpio15"),
+	PINCTRL_PIN(16, "gpio16"),
+	PINCTRL_PIN(17, "gpio17"),
+	PINCTRL_PIN(18, "gpio18"),
+	PINCTRL_PIN(19, "gpio19"),
+	PINCTRL_PIN(20, "gpio20"),
+	PINCTRL_PIN(21, "gpio21"),
+	PINCTRL_PIN(22, "gpio22"),
+	PINCTRL_PIN(23, "gpio23"),
+	PINCTRL_PIN(24, "gpio24"),
+	PINCTRL_PIN(25, "gpio25"),
+	PINCTRL_PIN(26, "gpio26"),
+	PINCTRL_PIN(27, "gpio27"),
+	PINCTRL_PIN(28, "gpio28"),
+	PINCTRL_PIN(29, "gpio29"),
+	PINCTRL_PIN(30, "gpio30"),
+	PINCTRL_PIN(31, "gpio31"),
+	PINCTRL_PIN(32, "gpio32"),
+	PINCTRL_PIN(33, "gpio33"),
+	PINCTRL_PIN(34, "gpio34"),
+};
+
+static const char * const oxnas_fct0_group[] = {
+	"gpio0",  "gpio1",  "gpio2",  "gpio3",
+	"gpio4",  "gpio5",  "gpio6",  "gpio7",
+	"gpio8",  "gpio9",  "gpio10", "gpio11",
+	"gpio12", "gpio13", "gpio14", "gpio15",
+	"gpio16", "gpio17", "gpio18", "gpio19",
+	"gpio20", "gpio21", "gpio22", "gpio23",
+	"gpio24", "gpio25", "gpio26", "gpio27",
+	"gpio28", "gpio29", "gpio30", "gpio31",
+	"gpio32", "gpio33", "gpio34"
+};
+
+static const char * const oxnas_fct3_group[] = {
+	"gpio0",  "gpio1",  "gpio2",  "gpio3",
+	"gpio4",  "gpio5",  "gpio6",  "gpio7",
+	"gpio8",  "gpio9",
+	"gpio20",
+	"gpio22", "gpio23", "gpio24", "gpio25",
+	"gpio26", "gpio27", "gpio28", "gpio29",
+	"gpio30", "gpio31", "gpio32", "gpio33",
+	"gpio34"
+};
+
+#define FUNCTION(_name, _gr)					\
+	{							\
+		.name = #_name,					\
+		.groups = oxnas_##_gr##_group,			\
+		.ngroups = ARRAY_SIZE(oxnas_##_gr##_group),	\
+	}
+
+static const struct oxnas_function oxnas_functions[] = {
+	FUNCTION(gpio, fct0),
+	FUNCTION(fct3, fct3),
+};
+
+#define OXNAS_PINCTRL_GROUP(_pin, _name, ...)				\
+	{								\
+		.name = #_name,						\
+		.pin = _pin,						\
+		.bank = _pin / PINS_PER_BANK,				\
+		.functions = (struct oxnas_desc_function[]){		\
+			__VA_ARGS__, { } },				\
+	}
+
+#define OXNAS_PINCTRL_FUNCTION(_name, _fct)		\
+	{						\
+		.name = #_name,				\
+		.fct = _fct,				\
+	}
+
+static const struct oxnas_pin_group oxnas_groups[] = {
+	OXNAS_PINCTRL_GROUP(0, gpio0,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(1, gpio1,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(2, gpio2,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(3, gpio3,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(4, gpio4,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(5, gpio5,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(6, gpio6,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(7, gpio7,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(8, gpio8,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(9, gpio9,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(10, gpio10,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+	OXNAS_PINCTRL_GROUP(11, gpio11,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+	OXNAS_PINCTRL_GROUP(12, gpio12,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+	OXNAS_PINCTRL_GROUP(13, gpio13,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+	OXNAS_PINCTRL_GROUP(14, gpio14,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+	OXNAS_PINCTRL_GROUP(15, gpio15,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+	OXNAS_PINCTRL_GROUP(16, gpio16,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+	OXNAS_PINCTRL_GROUP(17, gpio17,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+	OXNAS_PINCTRL_GROUP(18, gpio18,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+	OXNAS_PINCTRL_GROUP(19, gpio19,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+	OXNAS_PINCTRL_GROUP(20, gpio20,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(21, gpio21,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+	OXNAS_PINCTRL_GROUP(22, gpio22,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(23, gpio23,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(24, gpio24,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(25, gpio25,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(26, gpio26,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(27, gpio27,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(28, gpio28,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(29, gpio29,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(30, gpio30,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(31, gpio31,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(32, gpio32,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(33, gpio33,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+	OXNAS_PINCTRL_GROUP(34, gpio34,
+			OXNAS_PINCTRL_FUNCTION(gpio, 0),
+			OXNAS_PINCTRL_FUNCTION(fct3, 3)),
+};
+
+static inline struct oxnas_gpio_bank *pctl_to_bank(struct oxnas_pinctrl *pctl,
+						   unsigned int pin)
+{
+	return &pctl->gpio_banks[pin / PINS_PER_BANK];
+}
+
+static int oxnas_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctl->ngroups;
+}
+
+static const char *oxnas_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+						unsigned int group)
+{
+	struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctl->groups[group].name;
+}
+
+static int oxnas_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+					unsigned int group,
+					const unsigned int **pins,
+					unsigned int *num_pins)
+{
+	struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = &pctl->groups[group].pin;
+	*num_pins = 1;
+
+	return 0;
+}
+
+static const struct pinctrl_ops oxnas_pinctrl_ops = {
+	.get_groups_count = oxnas_pinctrl_get_groups_count,
+	.get_group_name = oxnas_pinctrl_get_group_name,
+	.get_group_pins = oxnas_pinctrl_get_group_pins,
+	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+	.dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int oxnas_pinmux_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctl->nfunctions;
+}
+
+static const char *
+oxnas_pinmux_get_function_name(struct pinctrl_dev *pctldev, unsigned int func)
+{
+	struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctl->functions[func].name;
+}
+
+static int oxnas_pinmux_get_function_groups(struct pinctrl_dev *pctldev,
+					    unsigned int func,
+					    const char * const **groups,
+					    unsigned int * const num_groups)
+{
+	struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = pctl->functions[func].groups;
+	*num_groups = pctl->functions[func].ngroups;
+
+	return 0;
+}
+
+static int oxnas_pinmux_enable(struct pinctrl_dev *pctldev,
+			       unsigned int func, unsigned int group)
+{
+	struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct oxnas_pin_group *pg = &pctl->groups[group];
+	const struct oxnas_function *pf = &pctl->functions[func];
+	const char *fname = pf->name;
+	struct oxnas_desc_function *functions = pg->functions;
+	u32 mask = BIT(pg->pin);
+
+	while (functions->name) {
+		if (!strcmp(functions->name, fname)) {
+			dev_dbg(pctl->dev,
+				"setting function %s bank %d pin %d fct %d mask %x\n",
+				fname, pg->bank, pg->pin,
+				functions->fct, mask);
+
+			regmap_write_bits(pctl->regmap,
+					  (pg->bank ?
+						PINMUX_PRIMARY_SEL1 :
+						PINMUX_PRIMARY_SEL0),
+					  mask,
+					  (functions->fct == 1 ?
+						mask : 0));
+			regmap_write_bits(pctl->regmap,
+					  (pg->bank ?
+						PINMUX_SECONDARY_SEL1 :
+						PINMUX_SECONDARY_SEL0),
+					  mask,
+					  (functions->fct == 2 ?
+						mask : 0));
+			regmap_write_bits(pctl->regmap,
+					  (pg->bank ?
+						PINMUX_TERTIARY_SEL1 :
+						PINMUX_TERTIARY_SEL0),
+					  mask,
+					  (functions->fct == 3 ?
+						mask : 0));
+
+			return 0;
+		}
+
+		functions++;
+	}
+
+	dev_err(pctl->dev, "cannot mux pin %u to function %u\n", group, func);
+
+	return -EINVAL;
+}
+
+static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev,
+				     struct pinctrl_gpio_range *range,
+				     unsigned int offset)
+{
+	struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	struct oxnas_gpio_bank *bank = gpiochip_get_data(range->gc);
+	u32 mask = BIT(offset - bank->gpio_chip.base);
+
+	dev_dbg(pctl->dev, "requesting gpio %d in bank %d (id %d) with mask 0x%x\n",
+		offset, bank->gpio_chip.base, bank->id, mask);
+
+	regmap_write_bits(pctl->regmap,
+			  (bank->id ?
+				PINMUX_PRIMARY_SEL1 :
+				PINMUX_PRIMARY_SEL0),
+			  mask, 0);
+	regmap_write_bits(pctl->regmap,
+			  (bank->id ?
+				PINMUX_SECONDARY_SEL1 :
+				PINMUX_SECONDARY_SEL0),
+			  mask, 0);
+	regmap_write_bits(pctl->regmap,
+			  (bank->id ?
+				PINMUX_TERTIARY_SEL1 :
+				PINMUX_TERTIARY_SEL0),
+			  mask, 0);
+
+	return 0;
+}
+
+static int oxnas_gpio_direction_input(struct gpio_chip *chip,
+				      unsigned int offset)
+{
+	struct oxnas_gpio_bank *bank = gpiochip_get_data(chip);
+	u32 mask = BIT(offset);
+
+	writel_relaxed(mask, bank->reg_base + OUTPUT_EN_CLEAR);
+
+	return 0;
+}
+
+static int oxnas_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	struct oxnas_gpio_bank *bank = gpiochip_get_data(chip);
+	u32 mask = BIT(offset);
+
+	return (readl_relaxed(bank->reg_base + INPUT_VALUE) & mask) != 0;
+}
+
+static void oxnas_gpio_set(struct gpio_chip *chip, unsigned int offset,
+			       int value)
+{
+	struct oxnas_gpio_bank *bank = gpiochip_get_data(chip);
+	u32 mask = BIT(offset);
+
+	if (value)
+		writel_relaxed(mask, bank->reg_base + OUTPUT_SET);
+	else
+		writel_relaxed(mask, bank->reg_base + OUTPUT_CLEAR);
+}
+
+static int oxnas_gpio_direction_output(struct gpio_chip *chip,
+				       unsigned int offset, int value)
+{
+	struct oxnas_gpio_bank *bank = gpiochip_get_data(chip);
+	u32 mask = BIT(offset);
+
+	oxnas_gpio_set(chip, offset, value);
+	writel_relaxed(mask, bank->reg_base + OUTPUT_EN_SET);
+
+	return 0;
+}
+
+static int oxnas_gpio_set_direction(struct pinctrl_dev *pctldev,
+				    struct pinctrl_gpio_range *range,
+				    unsigned int offset, bool input)
+{
+	struct gpio_chip *chip = range->gc;
+
+	if (input)
+		oxnas_gpio_direction_input(chip, offset);
+	else
+		oxnas_gpio_direction_output(chip, offset, 0);
+
+	return 0;
+}
+
+static const struct pinmux_ops oxnas_pinmux_ops = {
+	.get_functions_count = oxnas_pinmux_get_functions_count,
+	.get_function_name = oxnas_pinmux_get_function_name,
+	.get_function_groups = oxnas_pinmux_get_function_groups,
+	.set_mux = oxnas_pinmux_enable,
+	.gpio_request_enable = oxnas_gpio_request_enable,
+	.gpio_set_direction = oxnas_gpio_set_direction,
+};
+
+static int oxnas_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
+			     unsigned long *config)
+{
+	struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin);
+	unsigned int param = pinconf_to_config_param(*config);
+	u32 mask = BIT(pin - bank->gpio_chip.base);
+	int ret;
+	u32 arg;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_PULL_UP:
+		ret = regmap_read(pctl->regmap,
+				  (bank->id ?
+					PINMUX_PULLUP_CTRL1 :
+					PINMUX_PULLUP_CTRL0),
+				  &arg);
+		if (ret)
+			return ret;
+
+		arg = !!(arg & mask);
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+
+	return 0;
+}
+
+static int oxnas_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+			     unsigned long *configs, unsigned int num_configs)
+{
+	struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin);
+	unsigned int param;
+	u32 arg;
+	unsigned int i;
+	u32 offset = pin - bank->gpio_chip.base;
+	u32 mask = BIT(offset);
+
+	dev_dbg(pctl->dev, "setting pin %d bank %d mask 0x%x\n",
+		pin, bank->gpio_chip.base, mask);
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_PULL_UP:
+			dev_dbg(pctl->dev, "   pullup\n");
+			regmap_write_bits(pctl->regmap,
+					  (bank->id ?
+						PINMUX_PULLUP_CTRL1 :
+						PINMUX_PULLUP_CTRL0),
+					  mask, mask);
+			break;
+		default:
+			dev_err(pctl->dev, "Property %u not supported\n",
+				param);
+			return -ENOTSUPP;
+		}
+	}
+
+	return 0;
+}
+
+static const struct pinconf_ops oxnas_pinconf_ops = {
+	.pin_config_get = oxnas_pinconf_get,
+	.pin_config_set = oxnas_pinconf_set,
+	.is_generic = true,
+};
+
+static struct pinctrl_desc oxnas_pinctrl_desc = {
+	.name = "oxnas-pinctrl",
+	.pctlops = &oxnas_pinctrl_ops,
+	.pmxops = &oxnas_pinmux_ops,
+	.confops = &oxnas_pinconf_ops,
+	.owner = THIS_MODULE,
+};
+
+static void oxnas_gpio_irq_ack(struct irq_data *data)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct oxnas_gpio_bank *bank = gpiochip_get_data(chip);
+	u32 mask = BIT(data->hwirq);
+
+	writel(mask, bank->reg_base + IRQ_PENDING);
+}
+
+static void oxnas_gpio_irq_mask(struct irq_data *data)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct oxnas_gpio_bank *bank = gpiochip_get_data(chip);
+	unsigned int type = irqd_get_trigger_type(data);
+	u32 mask = BIT(data->hwirq);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		writel(readl(bank->reg_base + RE_IRQ_ENABLE) & ~mask,
+		       bank->reg_base + RE_IRQ_ENABLE);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		writel(readl(bank->reg_base + FE_IRQ_ENABLE) & ~mask,
+		       bank->reg_base + FE_IRQ_ENABLE);
+}
+
+static void oxnas_gpio_irq_unmask(struct irq_data *data)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct oxnas_gpio_bank *bank = gpiochip_get_data(chip);
+	unsigned int type = irqd_get_trigger_type(data);
+	u32 mask = BIT(data->hwirq);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		writel(readl(bank->reg_base + RE_IRQ_ENABLE) | mask,
+		       bank->reg_base + RE_IRQ_ENABLE);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		writel(readl(bank->reg_base + FE_IRQ_ENABLE) | mask,
+		       bank->reg_base + FE_IRQ_ENABLE);
+}
+
+static unsigned int oxnas_gpio_irq_startup(struct irq_data *data)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+
+	oxnas_gpio_direction_input(chip, data->hwirq);
+	oxnas_gpio_irq_unmask(data);
+
+	return 0;
+}
+
+static int oxnas_gpio_irq_set_type(struct irq_data *data, unsigned int type)
+{
+	if ((type & (IRQ_TYPE_EDGE_RISING|IRQ_TYPE_EDGE_FALLING)) == 0)
+		return -EINVAL;
+
+	irq_set_handler_locked(data, handle_edge_irq);
+
+	return 0;
+}
+
+static void oxnas_gpio_irq_handler(struct irq_desc *desc)
+{
+	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+	struct oxnas_gpio_bank *bank = gpiochip_get_data(gc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	unsigned long stat;
+	unsigned int pin;
+
+	chained_irq_enter(chip, desc);
+
+	stat = readl(bank->reg_base + IRQ_PENDING);
+
+	for_each_set_bit(pin, &stat, BITS_PER_LONG)
+		generic_handle_irq(irq_linear_revmap(gc->irqdomain, pin));
+
+	chained_irq_exit(chip, desc);
+}
+
+#define GPIO_BANK(_bank)						\
+	{								\
+		.gpio_chip = {						\
+			.label = "GPIO" #_bank,				\
+			.request = gpiochip_generic_request,		\
+			.free = gpiochip_generic_free,			\
+			.direction_input = oxnas_gpio_direction_input,	\
+			.direction_output = oxnas_gpio_direction_output, \
+			.get = oxnas_gpio_get,				\
+			.set = oxnas_gpio_set,				\
+			.ngpio = PINS_PER_BANK,				\
+			.base = GPIO_BANK_START(_bank),			\
+			.owner = THIS_MODULE,				\
+			.can_sleep = 0,					\
+		},							\
+		.irq_chip = {						\
+			.name = "GPIO" #_bank,				\
+			.irq_startup = oxnas_gpio_irq_startup,	\
+			.irq_ack = oxnas_gpio_irq_ack,		\
+			.irq_mask = oxnas_gpio_irq_mask,		\
+			.irq_unmask = oxnas_gpio_irq_unmask,		\
+			.irq_set_type = oxnas_gpio_irq_set_type,	\
+		},							\
+	}
+
+static struct oxnas_gpio_bank oxnas_gpio_banks[] = {
+	GPIO_BANK(0),
+	GPIO_BANK(1),
+};
+
+static int oxnas_pinctrl_probe(struct platform_device *pdev)
+{
+	struct oxnas_pinctrl *pctl;
+
+	pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+	if (!pctl)
+		return -ENOMEM;
+	pctl->dev = &pdev->dev;
+	dev_set_drvdata(&pdev->dev, pctl);
+
+	pctl->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+						       "oxsemi,sys-ctrl");
+	if (IS_ERR(pctl->regmap)) {
+		dev_err(&pdev->dev, "failed to get sys ctrl regmap\n");
+		return -ENODEV;
+	}
+
+	pctl->pins = oxnas_pins;
+	pctl->npins = ARRAY_SIZE(oxnas_pins);
+	pctl->functions = oxnas_functions;
+	pctl->nfunctions = ARRAY_SIZE(oxnas_functions);
+	pctl->groups = oxnas_groups;
+	pctl->ngroups = ARRAY_SIZE(oxnas_groups);
+	pctl->gpio_banks = oxnas_gpio_banks;
+	pctl->nbanks = ARRAY_SIZE(oxnas_gpio_banks);
+
+	oxnas_pinctrl_desc.pins = pctl->pins;
+	oxnas_pinctrl_desc.npins = pctl->npins;
+
+	pctl->pctldev = pinctrl_register(&oxnas_pinctrl_desc,
+					 &pdev->dev, pctl);
+	if (IS_ERR(pctl->pctldev)) {
+		dev_err(&pdev->dev, "Failed to register pinctrl device\n");
+		return PTR_ERR(pctl->pctldev);
+	}
+
+	return 0;
+}
+
+static int oxnas_gpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct of_phandle_args pinspec;
+	struct oxnas_gpio_bank *bank;
+	unsigned int id, ngpios;
+	int irq, ret;
+	struct resource *res;
+
+	if (of_parse_phandle_with_fixed_args(np, "gpio-ranges",
+					     3, 0, &pinspec)) {
+		dev_err(&pdev->dev, "gpio-ranges property not found\n");
+		return -EINVAL;
+	}
+
+	id = pinspec.args[1] / PINS_PER_BANK;
+	ngpios = pinspec.args[2];
+
+	if (id >= ARRAY_SIZE(oxnas_gpio_banks)) {
+		dev_err(&pdev->dev, "invalid gpio-ranges base arg\n");
+		return -EINVAL;
+	}
+
+	if (ngpios > PINS_PER_BANK) {
+		dev_err(&pdev->dev, "invalid gpio-ranges count arg\n");
+		return -EINVAL;
+	}
+
+	bank = &oxnas_gpio_banks[id];
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	bank->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(bank->reg_base))
+		return PTR_ERR(bank->reg_base);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "irq get failed\n");
+		return irq;
+	}
+
+	bank->id = id;
+	bank->gpio_chip.parent = &pdev->dev;
+	bank->gpio_chip.of_node = np;
+	bank->gpio_chip.ngpio = ngpios;
+	ret = gpiochip_add_data(&bank->gpio_chip, bank);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to add GPIO chip %u: %d\n",
+			id, ret);
+		return ret;
+	}
+
+	ret = gpiochip_irqchip_add(&bank->gpio_chip, &bank->irq_chip,
+				0, handle_level_irq, IRQ_TYPE_NONE);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to add IRQ chip %u: %d\n",
+			id, ret);
+		gpiochip_remove(&bank->gpio_chip);
+		return ret;
+	}
+
+	gpiochip_set_chained_irqchip(&bank->gpio_chip, &bank->irq_chip,
+				     irq, oxnas_gpio_irq_handler);
+
+	return 0;
+}
+
+static const struct of_device_id oxnas_pinctrl_of_match[] = {
+	{ .compatible = "oxsemi,ox810se-pinctrl", },
+	{ },
+};
+
+static struct platform_driver oxnas_pinctrl_driver = {
+	.driver = {
+		.name = "oxnas-pinctrl",
+		.of_match_table = oxnas_pinctrl_of_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = oxnas_pinctrl_probe,
+};
+
+static const struct of_device_id oxnas_gpio_of_match[] = {
+	{ .compatible = "oxsemi,ox810se-gpio", },
+	{ },
+};
+
+static struct platform_driver oxnas_gpio_driver = {
+	.driver = {
+		.name = "oxnas-gpio",
+		.of_match_table = oxnas_gpio_of_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = oxnas_gpio_probe,
+};
+
+static int __init oxnas_gpio_register(void)
+{
+	return platform_driver_register(&oxnas_gpio_driver);
+}
+arch_initcall(oxnas_gpio_register);
+
+static int __init oxnas_pinctrl_register(void)
+{
+	return platform_driver_register(&oxnas_pinctrl_driver);
+}
+arch_initcall(oxnas_pinctrl_register);
-- 
1.9.1



From tn at semihalf.com  Wed May 11 00:36:58 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Wed, 11 May 2016 09:36:58 +0200
Subject: [PATCH V7 03/11] pci, of: Move the PCI I/O space management to
 PCI core code.
In-Reply-To: <CAJZ5v0ge+LGwp=AkPF50H1ZXFA6J5ByazuY7Opc-aLJwWrBNxg@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-4-git-send-email-tn@semihalf.com>
 <CAJZ5v0ge+LGwp=AkPF50H1ZXFA6J5ByazuY7Opc-aLJwWrBNxg@mail.gmail.com>
Message-ID: <5732E11A.9090002@semihalf.com>

On 10.05.2016 19:59, Rafael J. Wysocki wrote:
> On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
>> No functional changes in this patch.
>>
>> PCI I/O space mapping code does not depend on OF, therefore it can be
>> moved to PCI core code. This way we will be able to use it
>> e.g. in ACPI PCI code.
>>
>> Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
>> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
>> CC: Arnd Bergmann <arnd at arndb.de>
>> CC: Liviu Dudau <Liviu.Dudau at arm.com>
>> ---
>>   drivers/of/address.c       | 116 +--------------------------------------------
>>   drivers/pci/pci.c          | 115 ++++++++++++++++++++++++++++++++++++++++++++
>>   include/linux/of_address.h |   9 ----
>>   include/linux/pci.h        |   5 ++
>>   4 files changed, 121 insertions(+), 124 deletions(-)
>>
>> diff --git a/drivers/of/address.c b/drivers/of/address.c
>> index 91a469d..0a553c0 100644
>> --- a/drivers/of/address.c
>> +++ b/drivers/of/address.c
>> @@ -4,6 +4,7 @@
>>   #include <linux/ioport.h>
>>   #include <linux/module.h>
>>   #include <linux/of_address.h>
>> +#include <linux/pci.h>
>>   #include <linux/pci_regs.h>
>>   #include <linux/sizes.h>
>>   #include <linux/slab.h>
>> @@ -673,121 +674,6 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
>>   }
>>   EXPORT_SYMBOL(of_get_address);
>>
>> -#ifdef PCI_IOBASE
>> -struct io_range {
>> -       struct list_head list;
>> -       phys_addr_t start;
>> -       resource_size_t size;
>> -};
>> -
>> -static LIST_HEAD(io_range_list);
>> -static DEFINE_SPINLOCK(io_range_lock);
>> -#endif
>> -
>> -/*
>> - * Record the PCI IO range (expressed as CPU physical address + size).
>> - * Return a negative value if an error has occured, zero otherwise
>> - */
>> -int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>> -{
>> -       int err = 0;
>> -
>> -#ifdef PCI_IOBASE
>> -       struct io_range *range;
>> -       resource_size_t allocated_size = 0;
>> -
>> -       /* check if the range hasn't been previously recorded */
>> -       spin_lock(&io_range_lock);
>> -       list_for_each_entry(range, &io_range_list, list) {
>> -               if (addr >= range->start && addr + size <= range->start + size) {
>> -                       /* range already registered, bail out */
>> -                       goto end_register;
>> -               }
>> -               allocated_size += range->size;
>> -       }
>> -
>> -       /* range not registed yet, check for available space */
>> -       if (allocated_size + size - 1 > IO_SPACE_LIMIT) {
>> -               /* if it's too big check if 64K space can be reserved */
>> -               if (allocated_size + SZ_64K - 1 > IO_SPACE_LIMIT) {
>> -                       err = -E2BIG;
>> -                       goto end_register;
>> -               }
>> -
>> -               size = SZ_64K;
>> -               pr_warn("Requested IO range too big, new size set to 64K\n");
>> -       }
>> -
>> -       /* add the range to the list */
>> -       range = kzalloc(sizeof(*range), GFP_ATOMIC);
>> -       if (!range) {
>> -               err = -ENOMEM;
>> -               goto end_register;
>> -       }
>> -
>> -       range->start = addr;
>> -       range->size = size;
>> -
>> -       list_add_tail(&range->list, &io_range_list);
>> -
>> -end_register:
>> -       spin_unlock(&io_range_lock);
>> -#endif
>> -
>> -       return err;
>> -}
>> -
>> -phys_addr_t pci_pio_to_address(unsigned long pio)
>> -{
>> -       phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
>> -
>> -#ifdef PCI_IOBASE
>> -       struct io_range *range;
>> -       resource_size_t allocated_size = 0;
>> -
>> -       if (pio > IO_SPACE_LIMIT)
>> -               return address;
>> -
>> -       spin_lock(&io_range_lock);
>> -       list_for_each_entry(range, &io_range_list, list) {
>> -               if (pio >= allocated_size && pio < allocated_size + range->size) {
>> -                       address = range->start + pio - allocated_size;
>> -                       break;
>> -               }
>> -               allocated_size += range->size;
>> -       }
>> -       spin_unlock(&io_range_lock);
>> -#endif
>> -
>> -       return address;
>> -}
>> -
>> -unsigned long __weak pci_address_to_pio(phys_addr_t address)
>> -{
>> -#ifdef PCI_IOBASE
>> -       struct io_range *res;
>> -       resource_size_t offset = 0;
>> -       unsigned long addr = -1;
>> -
>> -       spin_lock(&io_range_lock);
>> -       list_for_each_entry(res, &io_range_list, list) {
>> -               if (address >= res->start && address < res->start + res->size) {
>> -                       addr = address - res->start + offset;
>> -                       break;
>> -               }
>> -               offset += res->size;
>> -       }
>> -       spin_unlock(&io_range_lock);
>> -
>> -       return addr;
>> -#else
>> -       if (address > IO_SPACE_LIMIT)
>> -               return (unsigned long)-1;
>> -
>> -       return (unsigned long) address;
>> -#endif
>> -}
>> -
>>   static int __of_address_to_resource(struct device_node *dev,
>>                  const __be32 *addrp, u64 size, unsigned int flags,
>>                  const char *name, struct resource *r)
>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>> index 25e0327..bc0c914 100644
>> --- a/drivers/pci/pci.c
>> +++ b/drivers/pci/pci.c
>> @@ -3021,6 +3021,121 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
>>   }
>>   EXPORT_SYMBOL(pci_request_regions_exclusive);
>>
>> +#ifdef PCI_IOBASE
>> +struct io_range {
>> +       struct list_head list;
>> +       phys_addr_t start;
>> +       resource_size_t size;
>> +};
>> +
>> +static LIST_HEAD(io_range_list);
>> +static DEFINE_SPINLOCK(io_range_lock);
>> +#endif
>> +
>> +/*
>> + * Record the PCI IO range (expressed as CPU physical address + size).
>> + * Return a negative value if an error has occured, zero otherwise
>> + */
>> +int __weak pci_register_io_range(phys_addr_t addr, resource_size_t size)
>> +{
>> +       int err = 0;
>> +
>> +#ifdef PCI_IOBASE
>
> I understand that this moves code around, but those in-function
> #ifdefs aren't nice.  Any chance to get rid of them but putting whole
> functions under the #ifdef?
>

This is a __weak implementation, so assuming I would move #ifdef out of 
function I need to provide another empty __weak stub. I do not know 
which solution is more ugly. In any case we can do that cleanup separately.

Tomasz


From lee.jones at linaro.org  Wed May 11 00:38:55 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Wed, 11 May 2016 08:38:55 +0100
Subject: [RFC PATCH 01/21] mfd: uniphier: add UniPhier MFD driver
In-Reply-To: <CAK7LNATmuN647=avdqAMahLU+9Bq4m4TkXe5f7q=pi8m=UrXBg@mail.gmail.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
 <1462873862-30940-2-git-send-email-yamada.masahiro@socionext.com>
 <20160510112622.GL19473@dell>
 <CAK7LNATmuN647=avdqAMahLU+9Bq4m4TkXe5f7q=pi8m=UrXBg@mail.gmail.com>
Message-ID: <20160511073855.GQ19473@dell>

On Wed, 11 May 2016, Masahiro Yamada wrote:

> Hi Lee,
> 
> 2016-05-10 20:26 GMT+09:00 Lee Jones <lee.jones at linaro.org>:
> >> +};
> >> +MODULE_DEVICE_TABLE(of, uniphier_mfd_match);
> >
> > NACK.  Please do not mix MFD and DT registration.
> 
> OK, thanks for review.
> 
> 
> My basic thought was:
> 
>   - Add an MFD node to my DTS only once.
>     If I need to expand it in the future, I will just
>     need to modify drivers/mtd/uniphier-mfd.c.
>     It is just kernel-internal modification, so it does not
>     bother DT binding at all.
> 
>   - Simplify the node topology of DTS.

Just describe the hardware in DT.  If you do so accurately, there
should be no requirement to change it (in theory).

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


From tn at semihalf.com  Wed May 11 00:39:34 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Wed, 11 May 2016 09:39:34 +0200
Subject: [PATCH V7 05/11] acpi, pci: Support IO resources when parsing PCI
 host bridge resources.
In-Reply-To: <CAJZ5v0j-jiGmMWoyd-ab4qiKGAScbxMskqUThBQxkOxPR8unMA@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-6-git-send-email-tn@semihalf.com>
 <CAJZ5v0j-jiGmMWoyd-ab4qiKGAScbxMskqUThBQxkOxPR8unMA@mail.gmail.com>
Message-ID: <5732E1B6.1000709@semihalf.com>

On 10.05.2016 20:20, Rafael J. Wysocki wrote:
> On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
>> Platforms that have memory mapped IO port (such as ARM64) need special
>> handling for PCI I/O resources. For host bridge's resource probing case
>> these resources need to be fixed up with pci_register_io_range/pci_remap_iospace etc.
>>
>> The same I/O resources need to be released after hotplug
>> removal so that it can be re-added back by the pci_remap_iospace
>> function during insertion. As a consequence we unmap I/O resources
>> with pci_unmap_iospace when we release host bridge resources.
>>
>> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
>> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
>> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
>> ---
>>   drivers/acpi/pci_root.c | 33 +++++++++++++++++++++++++++++++++
>>   1 file changed, 33 insertions(+)
>>
>> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
>> index ae3fe4e..cb3071d 100644
>> --- a/drivers/acpi/pci_root.c
>> +++ b/drivers/acpi/pci_root.c
>> @@ -719,6 +719,34 @@ next:
>>                          resource_list_add_tail(entry, resources);
>>          }
>>   }
>> +static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
>> +{
>> +#ifdef PCI_IOBASE
>
> Same comment about the #ifdefs as in the other patch.

OK

>
>> +       struct resource *res = entry->res;
>> +       resource_size_t cpu_addr = res->start;
>> +       resource_size_t pci_addr = cpu_addr - entry->offset;
>> +       resource_size_t length = resource_size(res);
>> +       unsigned long port;
>> +
>> +       if (pci_register_io_range(cpu_addr, length))
>> +               goto err;
>> +
>> +       port = pci_address_to_pio(cpu_addr);
>> +       if (port == (unsigned long)-1)
>> +               goto err;
>> +
>> +       res->start = port;
>> +       res->end = port + length - 1;
>> +       entry->offset = port - pci_addr;
>> +
>> +       if (pci_remap_iospace(res, cpu_addr) < 0)
>> +               goto err;
>
> An empty line here?

yes, empty line would be nice here.

Tomasz


From robin at protonic.nl  Wed May 11 00:46:35 2016
From: robin at protonic.nl (Robin van der Gracht)
Date: Wed, 11 May 2016 09:46:35 +0200
Subject: [GIT PULL] move ARM LCD display driver to auxdisplay
In-Reply-To: <20160510071004.GA7318@kroah.com>
References: <CACRpkdbyO0axd5ergYZcXO302f2fFAPKrSNevkvreP1kRjm-vw@mail.gmail.com>
 <20160425115758.GA4874@lukather>
 <CACRpkdb=s5onVa7qND9nFUtYPw5H-Hdr7Ja5o3=-9+wxghHekQ@mail.gmail.com>
 <20160428092608.GE17159@lukather> <5723755D.9060108@ti.com>
 <20160509090615.6272f8ca@erd979>
 <CACRpkdbZmL9Cqp-ubzyxd7fWUFOVsS1DCxsfG02kSpbWu_rbZQ@mail.gmail.com>
 <20160509161728.3aee1134@erd979>
 <CACRpkdZwPVMx-dXVkfVwFN0juzVuyvShV7yDWbUFSXOPE=uUrw@mail.gmail.com>
 <20160510071004.GA7318@kroah.com>
Message-ID: <20160511094635.299db364@erd979>

On Tue, 10 May 2016 09:10:04 +0200
Greg KH <gregkh at linuxfoundation.org> wrote:

> On Mon, May 09, 2016 at 04:27:00PM +0200, Linus Walleij wrote:
> > On Mon, May 9, 2016 at 4:17 PM, Robin van der Gracht
> > <robin at protonic.nl> wrote:  
> > > On Mon, 9 May 2016 15:19:26 +0200
> > > Linus Walleij <linus.walleij at linaro.org> wrote:
> > >  
> > >> On Mon, May 9, 2016 at 9:06 AM, Robin van der Gracht
> > >> <robin at protonic.nl> wrote:
> > >>  
> > >> > If you guys feel like auxdisplay is not the right subsystem
> > >> > for the driver, and would like me to move it, please share.  
> > >>
> > >> The best would be if you volunteer to maintain it and bring
> > >> it forward.  
> > >
> > > Thats fine. Would it suffice if I submit another patch adding
> > > myself to the maintainers file?  
> > 
> > That's half of it, if Miguel does not come back then his name
> > should be removed as the second step.
> > 
> > You also need to have an idea on a path to funnel accumulated
> > patches upstream to Torvalds. The recent patches to this
> > subsystem were funneled by Greg, so we should ask him how
> > he prefer to proceed.
> > 
> > Greg, what do you prefer?  
> 
> I don't care :)
> 
> I can keep doing this, sending stuff to Linus through my char/misc
> tree, or it can go through someone else's tree, it doesn't bother
> me...

Soo.. You're allowing me to send patches to you so you can funnel
them through your channel (for now)?

Kind regards,
Robin 


From adrian.hunter at intel.com  Wed May 11 00:50:22 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Wed, 11 May 2016 10:50:22 +0300
Subject: [PATCH] mmc: mmc: do not use CMD13 to get status after speed mode
 switch
In-Reply-To: <1462344872-6448-1-git-send-email-chaotian.jing@mediatek.com>
References: <1462344872-6448-1-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <5732E43E.8070800@intel.com>

On 04/05/16 09:54, Chaotian Jing wrote:
> Per JEDEC spec, it is not recommended to use CMD13 to get card status
> after speed mode switch. below are two reason about this:
> 1. CMD13 cannot be guaranteed due to the asynchronous operation.
> Therefore it is not recommended to use CMD13 to check busy completion
> of the timing change indication.
> 2. After switch to HS200, CMD13 will get response of 0x800, and even the
> busy signal gets de-asserted, the response of CMD13 is aslo 0x800.
> 
> this patch drops CMD13 when doing speed mode switch, if host do not
> support MMC_CAP_WAIT_WHILE_BUSY and there is no ops->card_busy(),
> then the only way is to wait a fixed timeout.

This looks like it should be 3 patches:
	1. Change __mmc_switch
	2. Change HS200 and HS400 selection
	3. Change HS selection

However there is another problem: card_busy is not the same as busy signal -
see below.  So that needs to be sorted out first.

> 
> Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
> ---
>  drivers/mmc/core/mmc.c     |   82 ++++++++++++++++----------------------------
>  drivers/mmc/core/mmc_ops.c |   25 +++++++++-----
>  2 files changed, 45 insertions(+), 62 deletions(-)
> 
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 4dbe3df..03ee7a4 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -962,7 +962,7 @@ static int mmc_select_hs(struct mmc_card *card)
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>  			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
>  			   card->ext_csd.generic_cmd6_time,
> -			   true, true, true);
> +			   true, false, true);

If you are going to do that, then you still need to do mmc_switch_status(card).

But we have done CMD13 polling for HS for a long time, so this should be a
separate patch and separately justified.  Maybe we should still poll if
!(host->caps & MMC_CAP_WAIT_WHILE_BUSY) && !host->ops->card_busy.

>  	if (!err)
>  		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
>  
> @@ -1056,7 +1056,6 @@ static int mmc_switch_status(struct mmc_card *card)
>  static int mmc_select_hs400(struct mmc_card *card)
>  {
>  	struct mmc_host *host = card->host;
> -	bool send_status = true;
>  	unsigned int max_dtr;
>  	int err = 0;
>  	u8 val;
> @@ -1068,9 +1067,6 @@ static int mmc_select_hs400(struct mmc_card *card)
>  	      host->ios.bus_width == MMC_BUS_WIDTH_8))
>  		return 0;
>  
> -	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
> -		send_status = false;
> -
>  	/* Reduce frequency to HS frequency */
>  	max_dtr = card->ext_csd.hs_max_dtr;
>  	mmc_set_clock(host, max_dtr);
> @@ -1080,7 +1076,7 @@ static int mmc_select_hs400(struct mmc_card *card)
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>  			   EXT_CSD_HS_TIMING, val,
>  			   card->ext_csd.generic_cmd6_time,
> -			   true, send_status, true);
> +			   true, false, true);
>  	if (err) {
>  		pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
>  			mmc_hostname(host), err);
> @@ -1090,11 +1086,9 @@ static int mmc_select_hs400(struct mmc_card *card)
>  	/* Set host controller to HS timing */
>  	mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
>  
> -	if (!send_status) {
> -		err = mmc_switch_status(card);
> -		if (err)
> -			goto out_err;
> -	}
> +	err = mmc_switch_status(card);
> +	if (err)
> +		goto out_err;
>  
>  	/* Switch card to DDR */
>  	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> @@ -1113,7 +1107,7 @@ static int mmc_select_hs400(struct mmc_card *card)
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>  			   EXT_CSD_HS_TIMING, val,
>  			   card->ext_csd.generic_cmd6_time,
> -			   true, send_status, true);
> +			   true, false, true);
>  	if (err) {
>  		pr_err("%s: switch to hs400 failed, err:%d\n",
>  			 mmc_hostname(host), err);
> @@ -1124,11 +1118,9 @@ static int mmc_select_hs400(struct mmc_card *card)
>  	mmc_set_timing(host, MMC_TIMING_MMC_HS400);
>  	mmc_set_bus_speed(card);
>  
> -	if (!send_status) {
> -		err = mmc_switch_status(card);
> -		if (err)
> -			goto out_err;
> -	}
> +	err = mmc_switch_status(card);
> +	if (err)
> +		goto out_err;
>  
>  	return 0;
>  
> @@ -1146,14 +1138,10 @@ int mmc_hs200_to_hs400(struct mmc_card *card)
>  int mmc_hs400_to_hs200(struct mmc_card *card)
>  {
>  	struct mmc_host *host = card->host;
> -	bool send_status = true;
>  	unsigned int max_dtr;
>  	int err;
>  	u8 val;
>  
> -	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
> -		send_status = false;
> -
>  	/* Reduce frequency to HS */
>  	max_dtr = card->ext_csd.hs_max_dtr;
>  	mmc_set_clock(host, max_dtr);
> @@ -1162,49 +1150,43 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
>  	val = EXT_CSD_TIMING_HS;
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
>  			   val, card->ext_csd.generic_cmd6_time,
> -			   true, send_status, true);
> +			   true, false, true);
>  	if (err)
>  		goto out_err;
>  
>  	mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
>  
> -	if (!send_status) {
> -		err = mmc_switch_status(card);
> -		if (err)
> -			goto out_err;
> -	}
> +	err = mmc_switch_status(card);
> +	if (err)
> +		goto out_err;
>  
>  	/* Switch HS DDR to HS */
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
>  			   EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time,
> -			   true, send_status, true);
> +			   true, false, true);
>  	if (err)
>  		goto out_err;
>  
>  	mmc_set_timing(host, MMC_TIMING_MMC_HS);
>  
> -	if (!send_status) {
> -		err = mmc_switch_status(card);
> -		if (err)
> -			goto out_err;
> -	}
> +	err = mmc_switch_status(card);
> +	if (err)
> +		goto out_err;
>  
>  	/* Switch HS to HS200 */
>  	val = EXT_CSD_TIMING_HS200 |
>  	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
>  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
>  			   val, card->ext_csd.generic_cmd6_time, true,
> -			   send_status, true);
> +			   false, true);
>  	if (err)
>  		goto out_err;
>  
>  	mmc_set_timing(host, MMC_TIMING_MMC_HS200);
>  
> -	if (!send_status) {
> -		err = mmc_switch_status(card);
> -		if (err)
> -			goto out_err;
> -	}
> +	err = mmc_switch_status(card);
> +	if (err)
> +		goto out_err;
>  
>  	mmc_set_bus_speed(card);
>  
> @@ -1243,7 +1225,6 @@ static void mmc_select_driver_type(struct mmc_card *card)
>  static int mmc_select_hs200(struct mmc_card *card)
>  {
>  	struct mmc_host *host = card->host;
> -	bool send_status = true;
>  	unsigned int old_timing;
>  	int err = -EINVAL;
>  	u8 val;
> @@ -1260,9 +1241,6 @@ static int mmc_select_hs200(struct mmc_card *card)
>  
>  	mmc_select_driver_type(card);
>  
> -	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
> -		send_status = false;
> -
>  	/*
>  	 * Set the bus width(4 or 8) with host's support and
>  	 * switch to HS200 mode if bus width is set successfully.
> @@ -1274,20 +1252,18 @@ static int mmc_select_hs200(struct mmc_card *card)
>  		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>  				   EXT_CSD_HS_TIMING, val,
>  				   card->ext_csd.generic_cmd6_time,
> -				   true, send_status, true);
> +				   true, false, true);
>  		if (err)
>  			goto err;
>  		old_timing = host->ios.timing;
>  		mmc_set_timing(host, MMC_TIMING_MMC_HS200);
> -		if (!send_status) {
> -			err = mmc_switch_status(card);
> -			/*
> -			 * mmc_select_timing() assumes timing has not changed if
> -			 * it is a switch error.
> -			 */
> -			if (err == -EBADMSG)
> -				mmc_set_timing(host, old_timing);
> -		}
> +		err = mmc_switch_status(card);
> +		/*
> +		 * mmc_select_timing() assumes timing has not changed if
> +		 * it is a switch error.
> +		 */
> +		if (err == -EBADMSG)
> +			mmc_set_timing(host, old_timing);
>  	}
>  err:
>  	if (err)
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index 62355bd..32de144 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -480,6 +480,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
>  	u32 status = 0;
>  	bool use_r1b_resp = use_busy_signal;
>  	bool expired = false;
> +	bool busy = false;
>  
>  	mmc_retune_hold(host);
>  
> @@ -535,19 +536,24 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
>  	/* Must check status to be sure of no errors. */
>  	timeout = jiffies + msecs_to_jiffies(timeout_ms);
>  	do {
> +		/*
> +		 * Due to the possibility of being preempted after
> +		 * sending the status command, check the expiration
> +		 * time first.
> +		 */
> +		expired = time_after(jiffies, timeout);
>  		if (send_status) {
> -			/*
> -			 * Due to the possibility of being preempted after
> -			 * sending the status command, check the expiration
> -			 * time first.
> -			 */
> -			expired = time_after(jiffies, timeout);
>  			err = __mmc_send_status(card, &status, ignore_crc);
>  			if (err)
>  				goto out;
>  		}
>  		if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
>  			break;
> +		if (host->ops->card_busy) {

card_busy is a problem because it is designed for SD voltage switch which
checks DAT[3:0] whereas the busy signal is only DAT0.

> +			if (!host->ops->card_busy(host))
> +				break;
> +			busy = true;
> +		}
>  		if (mmc_host_is_spi(host))
>  			break;

I would tend to put all the changes together here after the
mmc_host_is_spi() check i.e.

		if (host->ops->card_busy) {
			expired = time_after(jiffies, timeout);
			if (!host->ops->card_busy(host))
				break;
			if (!expired) {
				cond_resched();
				continue;
			}
			pr_err("%s: Card stuck in busy state! %s\n",
			       mmc_hostname(host), __func__);
			err = -ETIMEDOUT;
			goto out;
		}

Also I think the changes to __mmc_switch() should be a separate patch.
However you can't go forward with this until you sort out what card_busy means.

>  
> @@ -556,19 +562,20 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
>  		 * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
>  		 * rely on waiting for the stated timeout to be sufficient.
>  		 */
> -		if (!send_status) {
> +		if (!send_status && !host->ops->card_busy) {
>  			mmc_delay(timeout_ms);
>  			goto out;
>  		}
>  
>  		/* Timeout if the device never leaves the program state. */
> -		if (expired && R1_CURRENT_STATE(status) == R1_STATE_PRG) {
> +		if (expired &&
> +		    (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy)) {
>  			pr_err("%s: Card stuck in programming state! %s\n",
>  				mmc_hostname(host), __func__);
>  			err = -ETIMEDOUT;
>  			goto out;
>  		}
> -	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
> +	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy);
>  
>  	err = mmc_switch_status_error(host, status);
>  out:
> 



From peter.griffin at linaro.org  Wed May 11 00:57:40 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 11 May 2016 08:57:40 +0100
Subject: [PATCH 04/18] dmaengine: st_fdma: Add xp70 firmware loading
 mechanism.
In-Reply-To: <20160426170048.GS2274@localhost>
References: <1461236675-10176-1-git-send-email-peter.griffin@linaro.org>
 <1461236675-10176-5-git-send-email-peter.griffin@linaro.org>
 <20160426170048.GS2274@localhost>
Message-ID: <20160511075740.GB25540@griffinp-ThinkPad-X1-Carbon-2nd>

Hi Vinod,

On Tue, 26 Apr 2016, Vinod Koul wrote:

> On Thu, Apr 21, 2016 at 12:04:21PM +0100, Peter Griffin wrote:
> > +static int
> > +st_fdma_elf_sanity_check(struct st_fdma_dev *fdev, const struct firmware *fw)
> > +{
> > +	const char *fw_name = fdev->fw_name;
> > +	struct elf32_hdr *ehdr;
> > +	char class;
> > +
> > +	if (!fw) {
> > +		dev_err(fdev->dev, "failed to load %s\n", fw_name);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (fw->size < sizeof(*ehdr)) {
> > +		dev_err(fdev->dev, "Image is too small\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	ehdr = (struct elf32_hdr *)fw->data;
> > +
> > +	/* We only support ELF32 at this point */
> > +	class = ehdr->e_ident[EI_CLASS];
> > +	if (class != ELFCLASS32) {
> > +		dev_err(fdev->dev, "Unsupported class: %d\n", class);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
> > +		dev_err(fdev->dev, "Unsupported firmware endianness"
> > +			"(%d) expected (%d)\n", ehdr->e_ident[EI_DATA],
> > +			ELFDATA2LSB);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) {
> > +		dev_err(fdev->dev, "Image is too small (%u)\n", fw->size);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
> > +		dev_err(fdev->dev, "Image is corrupted (bad magic)\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (ehdr->e_phnum != fdev->drvdata->num_mem) {
> > +		dev_err(fdev->dev, "spurious nb of segments (%d) expected (%d)"
> > +			"\n", ehdr->e_phnum, fdev->drvdata->num_mem);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (ehdr->e_type != ET_EXEC) {
> > +		dev_err(fdev->dev, "Unsupported ELF header type (%d) expected"
> > +			" (%d)\n", ehdr->e_type, ET_EXEC);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (ehdr->e_machine != EM_SLIM) {
> > +		dev_err(fdev->dev, "Unsupported ELF header machine (%d) "
> > +			"expected (%d)\n", ehdr->e_machine, EM_SLIM);
> > +		return -EINVAL;
> > +	}
> > +	if (ehdr->e_phoff > fw->size) {
> > +		dev_err(fdev->dev, "Firmware size is too small\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +st_fdma_elf_load_segments(struct st_fdma_dev *fdev, const struct firmware *fw)
> > +{
> > +	struct device *dev = fdev->dev;
> > +	struct elf32_hdr *ehdr;
> > +	struct elf32_phdr *phdr;
> > +	int i, mem_loaded = 0;
> > +	const u8 *elf_data = fw->data;
> > +
> > +	ehdr = (struct elf32_hdr *)elf_data;
> > +	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
> > +
> > +	/*
> > +	 * go through the available ELF segments
> > +	 * the program header's paddr member to contain device addresses.
> > +	 * We then go through the physically contiguous memory regions which we
> > +	 * allocated (and mapped) earlier on the probe,
> > +	 * and "translate" device address to kernel addresses,
> > +	 * so we can copy the segments where they are expected.
> > +	 */
> > +	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
> > +		u32 da = phdr->p_paddr;
> > +		u32 memsz = phdr->p_memsz;
> > +		u32 filesz = phdr->p_filesz;
> > +		u32 offset = phdr->p_offset;
> > +		void *dst;
> > +
> > +		if (phdr->p_type != PT_LOAD)
> > +			continue;
> > +
> > +		dev_dbg(dev, "phdr: type %d da %#x ofst:%#x memsz %#x filesz %#x\n",
> > +			phdr->p_type, da, offset, memsz, filesz);
> > +
> > +		if (filesz > memsz) {
> > +			dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
> > +				filesz, memsz);
> > +			break;
> > +		}
> > +
> > +		if (offset + filesz > fw->size) {
> > +			dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
> > +				offset + filesz, fw->size);
> > +			break;
> > +		}
> > +
> > +		dst = st_fdma_seg_to_mem(fdev, da, memsz);
> > +		if (!dst) {
> > +			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
> > +			break;
> > +		}
> > +
> > +		if (phdr->p_filesz)
> > +			memcpy(dst, elf_data + phdr->p_offset, filesz);
> > +
> > +		if (memsz > filesz)
> > +			memset(dst + filesz, 0, memsz - filesz);
> > +
> > +		mem_loaded++;
> > +	}
> > +
> > +	return (mem_loaded != fdev->drvdata->num_mem) ? -EIO : 0;
> > +}
> 
> Above two seem to be generic code and should be moved to core, this way
> other drivers using ELF firmware binaries can reuse...

Do you mean add to dmaengine.c?

Certainly st_fdma_elf_sanity_check is fairly generic. st_fdma_elf_load_segments
is less so, especially st_fdma_seg_to_mem().

> 
> > @@ -738,6 +925,15 @@ static int st_fdma_slave_config(struct dma_chan *chan,
> >  				struct dma_slave_config *slave_cfg)
> >  {
> >  	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
> > +	int ret;
> > +
> > +	if (!atomic_read(&fchan->fdev->fw_loaded)) {
> > +		ret = st_fdma_get_fw(fchan->fdev);
> 
> this seems quite an odd place to load firmware, can you explain why
> 

Good question :) I've been round the houses a bit on the firmware loading.

I will try and document here what I've tried and the different advantages /
disadvantages I've encountered.

In V3 patches, I used the device_config() hook. This can sleep (I think..it isn't
documented here [1]). This hook happens very close to the dma starting and the
rootfs / firmware is likely to be present. However I've sinced learnt that it
doesn't get  called in the memcpy case so is not a sufficient solution.

In part putting it here was to try and get firmware loading out of probe() based
on your feedback to v1 [2].

In V1 patches: - I was using request_firmware_nowait() in probe() in conjunction with
the CONFIG_FW_LOADER_USER_HELPER kernel option. I've since also learnt that this
kernel option is deprecated and shouldn't be used.

Your feedback in v1 was to move firmware loading to device open [2]. However
what classes is  device open in the dmaengine context is not obvious.

===

device_alloc_chan_resources() hook

This is probably the hook closest to a device open in dmaengine context.
This hook can sleep so request_firmware can be called. However if all drivers
are built-in firmware loading still fails as ALSA drivers calls
devm_snd_dmaengine_pcm_register() which requests dma channels during *its* probe().
This happens way before the rootfs is present and thus firmware loading still
fails, and is still being done indirectly from a probe() anyway.

I had some discussion with Mark and Arnd on IRC, about the possibility of ALSA
not rquesting DMA channels during their probe(). Marks opinion I believe was
this wasn't a good solution as ALSA would be presenting devices to userspace 
that potentially don't exist & can't work.
 
===

*_prep_*() hooks

+ Always get called before a DMA is started

- *prep* hooks can be called from atomic context so can't sleep [1] and can't use
  request_firmware().
- I tried using request_firmwqare_nowait() with GFP_ATOMIC flag firmware. This
  half works but firmware loading doesn't complete before the DMA is started which
  means it often fails on the first DMA attempt.

 ===

Suggested solution for v4 patches: -

Both Arnd, Mark and Lee initial suggestion on irc was that if the device is useless
without firmware, and the firmware isn't available then the driver should call
request_firmware() in probe() and -EPROBE_DEFER if not available.

This solution works well, in both the built-in and modules case. As the deffered
fdma driver re-probes after the rootfs has been mounted when the firmware is
available. The other ALSA depedencies then also re-probe and everything works
nicely (and you can be assured that the devices will actually work at this point).

This fdma driver and the ALSA ones will be enabled in multi_v7_defconfig as modules,
so it is only likely to be used as a module. However using -EPROBE_DEFER
mechanism, has the nice quality that if it is compiled as built-in you still end
up with a working system (albeit with a longer boot time).

Failing that the only other solution I can see is extending the dmaengine API to
provide another hook which can sleep, and must be called before a DMA
transation is started. Note that firmware isn't actually *required* until we
start the dma transaction, but the device is useless without this firmware. In fact
its "registers" are really just offsets into its DMEM so in theory even the
registers are totally firmware dependent.

Also I notice the only other dmaengine driver imx-sdma.c using firmware calls
request_firmware_nowait from its probe().

Are you happy with my proposed solutiion for v4? If not how would you like me to
implement this?

regards,

Peter.

[1] https://www.kernel.org/doc/Documentation/dmaengine/provider.txt

[2] https://lkml.org/lkml/2015/10/13/278


From ynorov at caviumnetworks.com  Wed May 11 01:04:38 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Wed, 11 May 2016 11:04:38 +0300
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <57329320.1000500@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <7091358.aJt1stteb5@wuerfel> <5731D68D.2090109@huawei.com>
 <4119683.coHZhzaE6c@wuerfel> <57329320.1000500@huawei.com>
Message-ID: <20160511075438.GA15628@yury-N73SV>

On Wed, May 11, 2016 at 10:04:16AM +0800, Zhangjian (Bamvor) wrote:
[...]

> >>Ok, I will test the ltp syscall test.
> >>With this changes, the issue I mentioned should be fixed. But we still
> >>use mmap2 syscall for ILP32 application when we pass the offset instead
> >>of page offset. Is it correct?
> >
> >I don't remember. It's probably not important whether we have the shift
> >in there, as long as it's independent of the actual kernel page size and
> >user space and kernel agree on the calling conventions.
> Well. I am ok with where to shift the pages size because we get the same
> result. I was just thinking if we should get rid of the name of mmap2 in our
> ILP32 porting. Actually, it is mmap but we name it as mmap2. User may confused
> if they do not know the implementations.
> 

This is what generic unistd.h does. If you want to change it, you'd
change each arch that uses generic unistd.h.

> Regards
> 
> Bamvor
> 
> >
> >	Arnd
> >
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From arnd at arndb.de  Wed May 11 01:09:52 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 10:09:52 +0200
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <57329320.1000500@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <4119683.coHZhzaE6c@wuerfel> <57329320.1000500@huawei.com>
Message-ID: <4876119.A8fbdncu9Z@wuerfel>

On Wednesday 11 May 2016 10:04:16 Zhangjian wrote:
> > I don't remember. It's probably not important whether we have the shift
> > in there, as long as it's independent of the actual kernel page size and
> > user space and kernel agree on the calling conventions.
> Well. I am ok with where to shift the pages size because we get the same
> result. I was just thinking if we should get rid of the name of mmap2 in our
> ILP32 porting. Actually, it is mmap but we name it as mmap2. User may confused
> if they do not know the implementations.

That is a good point: If the implementation matches the mmap() behavior rather than
mmap2(), we should rename the macro by doing

#undef __NR_mmap2
#define __NR_mmap 222

in the uapi/asm/unistd.h file for ilp32 mode. Alternatively we can keep the
__NR_mmap2 definition but then we need to pass the pgoff (value shifted by
12 bits) argument rather than the size in bytes.

	Arnd


From kernel at martin.sperl.org  Wed May 11 01:21:27 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Wed, 11 May 2016 10:21:27 +0200
Subject: [PATCH 0/3] clk: bcm2835: critical clocks and parent selection
In-Reply-To: <FD44F435-512C-49A5-B1F5-3C62AAF805AC@martin.sperl.org>
References: <1462842090-2017-1-git-send-email-eric@anholt.net>
 <5731B8BA.30402@martin.sperl.org> <87a8jxyfua.fsf@eliezer.anholt.net>
 <FD44F435-512C-49A5-B1F5-3C62AAF805AC@martin.sperl.org>
Message-ID: <5E7C0C2A-8FA0-4EFF-9627-DFC34662590B@martin.sperl.org>

On 10.05.2016, at 21:58, Martin Sperl <kernel at martin.sperl.org> wrote:
> 
> 
> 
>> On 10.05.2016, at 19:37, Eric Anholt <eric at anholt.net> wrote:
>> 
>> Martin Sperl <kernel at martin.sperl.org> writes:
>> 
>>>> On 10.05.2016 03:01, Eric Anholt wrote:
>>>> With the new patch 2 inserted between my previous pair, I think this
>>>> should cover Martin's bugs with clock disabling.
>>>> 
>>>> I tested patch 2 to be important on the downstream kernel: with the
>>>> DPI panel support added there, I was losing ethernet (my only I/O)
>>>> when the HDMI HSM hanging off of PLLD_PER got disabled due to
>>>> EPROBE_DEFER.
>>>> 
>>>> Eric Anholt (3):
>>>> clk: bcm2835: Mark the VPU clock as critical
>>>> clk: bcm2835: Mark GPIO clocks enabled at boot as critical.
>>>> clk: bcm2835: Skip PLLC clocks when deciding on a new clock parent
>>>> 
>>>> drivers/clk/bcm/clk-bcm2835.c | 32 ++++++++++++++++++++++++++++++--
>>>> 1 file changed, 30 insertions(+), 2 deletions(-)
>>> I gave it a try - with all 3 patches applied I get the following enabled 
>>> clocks:
>>> root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
>>> /sys/kernel/debug/clk/aux_uart/clk_enable_count:1
>>> /sys/kernel/debug/clk/emmc/clk_enable_count:1
>>> /sys/kernel/debug/clk/gp1/clk_enable_count:1
>>> /sys/kernel/debug/clk/gp2/clk_enable_count:1
>>> /sys/kernel/debug/clk/osc/clk_enable_count:1
>>> /sys/kernel/debug/clk/pllc/clk_enable_count:2
>>> /sys/kernel/debug/clk/pllc_core0/clk_enable_count:1
>>> /sys/kernel/debug/clk/pllc_per/clk_enable_count:1
>>> /sys/kernel/debug/clk/vpu/clk_enable_count:2
>>> 
>>> At least on my compute module gp1/gp2 is enabled, but there is no rate
>>> set - so why is it marked as critical for all devices?
>>> So why apply patch2 for all possible devices?
>> 
>> According to the CLK_IS_CRITICAL patches, the author intended critical
>> clocks not to use the included function for marking clocks as critical
>> From the DT.  I'm not sure why, but writing patches using that when they
>> say not to seemed like a waste.
>> 
>> We could check if gp1/gp2 are already on before marking them critical.
> That may seem reasonable.
>> 
>>> Loading/unloading the amba_pl011 module does not crash the system,
>>> but a simple stty -F /dev/ttyAMA0 does crash the system!
>>> 
>>> Here the sequence:
>>> root at raspcm:~# dmesg -C
>>> root at raspcm:~# modprobe amba_pl011
>>> root at raspcm:~# dmesg -c
>>> [  141.708453] Serial: AMBA PL011 UART driver
>>> [  141.709158] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, 
>>> base_baud = 0) is a PL011 rev2
>>> root at raspcm:~# rmmod  amba_pl011
>>> root at raspcm:~# dmesg -c
>>> [  150.511248] Trying to free nonexistent resource 
>>> <0000000020201000-0000000020201fff>
>>> root at raspcm:~# modprobe amba_pl011
>>> root at raspcm:~# dmesg -c
>>> [  159.385002] Serial: AMBA PL011 UART driver
>>> [  159.385714] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, 
>>> base_baud = 0) is a PL011 rev2
>>> root at raspcm:~# stty -F /dev/ttyAMA0
>>> speed 9600 baud; line = 0;
>>> -brkint -imaxbel
>>> root at raspcm:~# Timeout, server raspcm not responding.
>>> 
>>> The reason behind this is that the firmware pre-configured uart clock
>>> looks like this:
>>> root at raspcm:~# cat /sys/kernel/debug/clk/uart/regdump
>>> ctl = 0x00000296
>>> div = 0x000a6aab
>>> so it is configured to use plld_per (which itself is running, even if 
>>> not enabled
>>> in the kernel)
>>> 
>>> But as plld_per is not among the enabled clocks then plld_per
>>> gets disabled as soon as the tty device is closed (by stty) and
>>> this also disables plld...
>>> 
>>> Similar effect when using PCM/i2s and use speaker-test:
>>> root at raspcm:~# dmesg -C
>>> root at raspcm:~# modprobe snd-soc-bcm2835-i2s; modprobe snd-soc-pcm5102a; 
>>> modprobe snd-soc-hifiberry-dac
>>> root at raspcm:~# dmesg
>>> [   81.968591] snd-hifiberry-dac sound: pcm5102a-hifi <-> 20203000.i2s 
>>> mapping ok
>>> root at raspcm:~# speaker-test -c 2 -r 44100 -F S16_LE -f 440 -t sine&
>>> [1] 579
>>> root at raspcm:~#
>>> speaker-test 1.0.28
>>> 
>>> Playback device is default
>>> Stream parameters are 44100Hz, S16_LE, 2 channels
>>> Sine wave rate is 440.0000Hz
>>> Rate set to 44100Hz (requested 44100Hz)
>>> Buffer size range from 128 to 131072
>>> Period size range from 64 to 65536
>>> Using max buffer size 131072
>>> Periods = 4
>>> was set period_size = 32768
>>> was set buffer_size = 131072
>>> 0 - Front Left
>>> 1 - Front Right
>>> 
>>> root at raspcm:~#
>>> root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
>>> /sys/kernel/debug/clk/aux_uart/clk_enable_count:1
>>> /sys/kernel/debug/clk/emmc/clk_enable_count:1
>>> /sys/kernel/debug/clk/gp1/clk_enable_count:1
>>> /sys/kernel/debug/clk/gp2/clk_enable_count:1
>>> /sys/kernel/debug/clk/osc/clk_enable_count:2
>>> /sys/kernel/debug/clk/pcm/clk_enable_count:1
>>> /sys/kernel/debug/clk/pllc/clk_enable_count:2
>>> /sys/kernel/debug/clk/pllc_core0/clk_enable_count:1
>>> /sys/kernel/debug/clk/pllc_per/clk_enable_count:1
>>> /sys/kernel/debug/clk/plld/clk_enable_count:1
>>> /sys/kernel/debug/clk/plld_per/clk_enable_count:1
>>> /sys/kernel/debug/clk/vpu/clk_enable_count:2
>>> root at raspcm:~# kill %1
>>> root at raspcm:~# Time per period = 106.889502
>>> Timeout, server raspcm not responding.
>>> 
>>> You see that plld gets now used and when I kill speaker-test
>>> the machine crashes again.
>> 
>> Just so I can be clear here: What are you using to talk to the Pi?
>> Builtin USB ethernet?
> Compute module with USB  Ethernet adapter, but I also got an 
> enc28j60 connected via spi, but that is not enabled by default
> 
>> 
>>> So this patchset does not really solve any of the problems that
>>> I have reported either.
>>> 
>>> That is why my patchset has taken the "HAND_OFF" approach
>>> instead (which still just hides some of the issues), but at least
>>> it does not crash the system on the use of plld and it allows
>>> for custom parent and mash selection.
>> 
>> HAND_OFF sure doesn't look like it's landing in the next kernel, so
>> writing patches using it doesn't make much sense to me.
> 
> If it is critical or hands-off does not really make a difference...
> 
>>> In reality it would require consumers of the corresponding
>>> parent clocks in the kernel (arm, ...) and the knowledge which
>>> clocks are really needed by the firmware - i.e plld.
>>> 
>>> Note that the sdram clock is using plld_core parent!
>>> root at raspcm:~#  cat /sys/kernel/debug/clk/sdram/regdump
>>> ctl = 0x00004006
>>> div = 0x00003000
>>> root at raspcm:~# cat /sys/kernel/debug/clk/sdram/clk_rate
>>> 166533331
>> 
>> However, it's not enabled, right?  Bit 4 isn't set in the CTL reg.
> You are probably right there, but still there must be something
> hidden that requires plld or plld_per or plld_core, that requires critical.
> 
> There must be some reason why it gets set up during the
> boot process by the firmware.
> 

Correction:

Actually the SDC control register contains some more bits compared
to most other clock control registers:
CM_SDCCTL_CTRL (12-15), CM_SDCCTL_ACCPT(16) and CM_SDCCTL_UPDATE(17)

See also:
https://github.com/msperl/rpi-registers/blob/master/md/Region_CM.md#cm_sdcctl

If I poke that register (0x201011a8) from userspace with 0x5a000000
then the machine crashes as well - so I assume these bits control
the custom SD-Ram PLL - unfortunately it still does not say which
PLL is used.

Eric, you may have access to more data regarding this register -
maybe we need to hand this register as a special clock?
and/or expose it as an additional pll?

Note that I also tried disabling PLLD_CORE and the system crashed as well
(root at raspcm:~#  peekpoke $[0x20101000 + 0x10c] w
/dev/mem opened.
Memory mapped at address 0xb6fdd000.
Value at address 0x2010110C (0xb6fdd10c): 0x20A
root at raspcm:~# peekpoke $[0x20101000 + 0x10c] w $[0x5a000000 + 0x20a + 32]
/dev/mem opened.
Memory mapped at address 0xb6fe7000.
Value at address 0x2010110C (0xb6fe710c): 0x20A
Written 0x5A00022A; readback 0x22A
root at raspcm:~# Write failed: Broken pipe

(requires /dev/mem without restrictions)

So this means that it is plld_core related - at least as of now
and the sdram pll currently derives from PLLD_core.

@Eric: so please look at the hld (which you have hinted you have
access to) and come up with something better for sdram

As far as I can tell at the very least the sdram clock is critical
and should be marked as such?

Martin

From andre.przywara at arm.com  Wed May 11 01:24:45 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 09:24:45 +0100
Subject: [PATCH v3 47/55] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <5730C86C.1080004@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-48-git-send-email-andre.przywara@arm.com>
 <5730C86C.1080004@arm.com>
Message-ID: <5732EC4D.30909@arm.com>

Hi,

On 09/05/16 18:27, Marc Zyngier wrote:
> On 06/05/16 11:46, Andre Przywara wrote:
>> Using the VMCR accessors we provide access to GIC CPU interface state
>> to userland by wiring it up to the existing userland interface.
>> [Marc: move and make VMCR accessors static, streamline MMIO handlers]
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> ---
>> Changelog v2 .. v3:
>> - total rework, moving into vgic-mmio-v2.c
>> - move vmcr accessor wrapper functions into this file
>> - use the register description table for CPU i/f registers as well
>> - add RAZ/WI handling for the active priority registers
>> - streamline MMIO handler functions
>>
>>  virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
>>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 104 ++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic.h            |   2 +
>>  3 files changed, 107 insertions(+), 1 deletion(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> index bb33af8..2122ff2 100644
>> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
>> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> @@ -300,7 +300,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
>>  
>>  	switch (attr->group) {
>>  	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>> -		ret = -EINVAL;
>> +		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
>>  		break;
>>  	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>>  		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> index c453e6f..0060539 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> @@ -206,6 +206,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
>>  	}
>>  }
>>  
>> +static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
>> +{
>> +	if (kvm_vgic_global_state.type == VGIC_V2)
>> +		vgic_v2_set_vmcr(vcpu, vmcr);
>> +	else
>> +		vgic_v3_set_vmcr(vcpu, vmcr);
>> +}
>> +
>> +static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
>> +{
>> +	if (kvm_vgic_global_state.type == VGIC_V2)
>> +		vgic_v2_get_vmcr(vcpu, vmcr);
>> +	else
>> +		vgic_v3_get_vmcr(vcpu, vmcr);
>> +}
>> +
>> +#define GICC_ARCH_VERSION_V2	0x2
>> +
>> +/* These are for userland accesses only, there is no guest-facing emulation. */
>> +static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
>> +					   gpa_t addr, unsigned int len)
>> +{
>> +	struct vgic_vmcr vmcr;
>> +	u32 val;
>> +
>> +	vgic_get_vmcr(vcpu, &vmcr);
>> +
>> +	switch (addr & 0xff) {
>> +	case GIC_CPU_CTRL:
>> +		val = vmcr.ctlr;
>> +		break;
>> +	case GIC_CPU_PRIMASK:
>> +		val = vmcr.pmr;
>> +		break;
>> +	case GIC_CPU_BINPOINT:
>> +		val = vmcr.bpr;
>> +		break;
>> +	case GIC_CPU_ALIAS_BINPOINT:
>> +		val = vmcr.abpr;
>> +		break;
>> +	case GIC_CPU_IDENT:
>> +		val = ((PRODUCT_ID_KVM << 20) |
>> +		       (GICC_ARCH_VERSION_V2 << 16) |
>> +		       IMPLEMENTER_ARM);
>> +		break;
>> +	default:
>> +		return 0;
>> +	}
>> +
>> +	return extract_bytes(val, addr & 3, len);
>> +}
>> +
>> +static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
>> +				   gpa_t addr, unsigned int len,
>> +				   unsigned long val)
>> +{
>> +	struct vgic_vmcr vmcr;
>> +
>> +	vgic_get_vmcr(vcpu, &vmcr);
>> +
>> +	switch (addr & 0xff) {
>> +	case GIC_CPU_CTRL:
>> +		vmcr.ctlr = val;
>> +		break;
>> +	case GIC_CPU_PRIMASK:
>> +		vmcr.pmr = val;
>> +		break;
>> +	case GIC_CPU_BINPOINT:
>> +		vmcr.bpr = val;
>> +		break;
>> +	case GIC_CPU_ALIAS_BINPOINT:
>> +		vmcr.abpr = val;
>> +		break;
>> +	}
>> +
>> +	vgic_set_vmcr(vcpu, &vmcr);
>> +}
>> +
>>  static const struct vgic_register_region vgic_v2_dist_registers[] = {
>>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
>>  		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
>> @@ -237,6 +315,21 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>>  		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16),
>>  };
>>  
>> +static const struct vgic_register_region vgic_v2_cpu_registers[] = {
>> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_CTRL,
>> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_PRIMASK,
>> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_BINPOINT,
>> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ALIAS_BINPOINT,
>> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ACTIVEPRIO,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
>> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_IDENT,
>> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
>> +};
>> +
>>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
>>  {
>>  	dev->regions = vgic_v2_dist_registers;
>> @@ -306,6 +399,17 @@ static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
>>  	return ret;
>>  }
>>  
>> +int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>> +			  int offset, u32 *val)
>> +{
>> +	struct vgic_io_device dev = {
>> +		.regions = vgic_v2_cpu_registers,
>> +		.nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers),
>> +	};
>> +
>> +	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
>> +}
>> +
>>  int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>>  			 int offset, u32 *val)
>>  {
> 
> And what about this:
> 
> +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
> +{
> +       int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
> +       const struct vgic_register_region *regions;
> +       gpa_t addr;
> +       int nr_regions, i, len;
> +
> +       addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
> +
> +       switch (attr->group) {
> +       case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> +               regions = vgic_v2_dist_registers;
> +               nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
> +               break;
> +       case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> +               return -ENXIO;          /* TODO: describe CPU i/f regs also */
> +       default:
> +               return -ENXIO;
> +       }
> 
> This TODO was already in the previous version. Can you please wire it
> and give save/restore a chance to work?

Oh dear, thanks for spotting this. It _was_ in my fix patch, but got
lost during the rebase. Will fix it.

Cheers,
Andre.


From oliver at schinagl.nl  Wed May 11 01:27:07 2016
From: oliver at schinagl.nl (Olliver Schinagl)
Date: Wed, 11 May 2016 10:27:07 +0200
Subject: [PATCH 1/1] devicetree: sunxi: Add OLinuXino Lime2 eMMC to the
 Makefile
Message-ID: <1462955227-4454-1-git-send-email-oliver@schinagl.nl>

ARM: dts: sunxi: Add a olinuxino-lime2-emmc added the new emmc equipped
lime2 but forgot its Makefile. This patch adds an entry to the Makefile.

Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>
---
Hi list,

would it be possible to squash or atleast add this patch with/to my previous
patch, ARM: dts: sunxi: Add a olinuxino-lime2-emmc? I mistakenly forgot to
add the changes to the Makefile in the patch.

Sorry, and thank you!

Olliver

 arch/arm/boot/dts/Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 95c1923..07f4cf8 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -695,6 +695,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \
 	sun7i-a20-olimex-som-evb.dtb \
 	sun7i-a20-olinuxino-lime.dtb \
 	sun7i-a20-olinuxino-lime2.dtb \
+	sun7i-a20-olinuxino-lime2-emmc.dtb \
 	sun7i-a20-olinuxino-micro.dtb \
 	sun7i-a20-orangepi.dtb \
 	sun7i-a20-orangepi-mini.dtb \
-- 
2.8.1



From dyoung at redhat.com  Wed May 11 01:29:23 2016
From: dyoung at redhat.com (Dave Young)
Date: Wed, 11 May 2016 16:29:23 +0800
Subject: [PATCH 00/12] Fixing TI Keystone2 kexec
In-Reply-To: <20160428092644.GX19428@n2100.arm.linux.org.uk>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
Message-ID: <20160511082923.GC8995@dhcp-128-65.nay.redhat.com>

Hi, Russell

On 04/28/16 at 10:26am, Russell King - ARM Linux wrote:
> These changes are required for TI Keystone2 kexec to be functional.  TI
> Keystone2 has the run-time view of physical memory above 4GiB, but with
> a boot time alias below 4GiB which can only be used during the early
> boot.
> 
> This means we need to translate run-time physical addresses (which the
> kernel uses) to boot-time physical addresses, which, having discussed
> with Eric, is what the kexec tools and kexec kernel API requires.
> 
> We publish a special set of boot time resources in /proc/iomem, which
> the (modified) kexec tools look for in preference to the normal resources.
> Hence, if these are found, the kexec tools make use of these resources,
> and thus kexec tools use the boot-time view of physical memory.

I think getting memory ranges from device tree will be better than
adding more stuff to /proc/iomem. Geoff's arm64 kexec patches is using dtb
you can refer to the patchset.

Thanks
Dave


From gregkh at linuxfoundation.org  Wed May 11 01:34:18 2016
From: gregkh at linuxfoundation.org (Greg KH)
Date: Wed, 11 May 2016 10:34:18 +0200
Subject: [GIT PULL] move ARM LCD display driver to auxdisplay
In-Reply-To: <20160511094635.299db364@erd979>
References: <20160425115758.GA4874@lukather>
 <CACRpkdb=s5onVa7qND9nFUtYPw5H-Hdr7Ja5o3=-9+wxghHekQ@mail.gmail.com>
 <20160428092608.GE17159@lukather> <5723755D.9060108@ti.com>
 <20160509090615.6272f8ca@erd979>
 <CACRpkdbZmL9Cqp-ubzyxd7fWUFOVsS1DCxsfG02kSpbWu_rbZQ@mail.gmail.com>
 <20160509161728.3aee1134@erd979>
 <CACRpkdZwPVMx-dXVkfVwFN0juzVuyvShV7yDWbUFSXOPE=uUrw@mail.gmail.com>
 <20160510071004.GA7318@kroah.com> <20160511094635.299db364@erd979>
Message-ID: <20160511083418.GB29268@kroah.com>

On Wed, May 11, 2016 at 09:46:35AM +0200, Robin van der Gracht wrote:
> On Tue, 10 May 2016 09:10:04 +0200
> Greg KH <gregkh at linuxfoundation.org> wrote:
> 
> > On Mon, May 09, 2016 at 04:27:00PM +0200, Linus Walleij wrote:
> > > On Mon, May 9, 2016 at 4:17 PM, Robin van der Gracht
> > > <robin at protonic.nl> wrote:  
> > > > On Mon, 9 May 2016 15:19:26 +0200
> > > > Linus Walleij <linus.walleij at linaro.org> wrote:
> > > >  
> > > >> On Mon, May 9, 2016 at 9:06 AM, Robin van der Gracht
> > > >> <robin at protonic.nl> wrote:
> > > >>  
> > > >> > If you guys feel like auxdisplay is not the right subsystem
> > > >> > for the driver, and would like me to move it, please share.  
> > > >>
> > > >> The best would be if you volunteer to maintain it and bring
> > > >> it forward.  
> > > >
> > > > Thats fine. Would it suffice if I submit another patch adding
> > > > myself to the maintainers file?  
> > > 
> > > That's half of it, if Miguel does not come back then his name
> > > should be removed as the second step.
> > > 
> > > You also need to have an idea on a path to funnel accumulated
> > > patches upstream to Torvalds. The recent patches to this
> > > subsystem were funneled by Greg, so we should ask him how
> > > he prefer to proceed.
> > > 
> > > Greg, what do you prefer?  
> > 
> > I don't care :)
> > 
> > I can keep doing this, sending stuff to Linus through my char/misc
> > tree, or it can go through someone else's tree, it doesn't bother
> > me...
> 
> Soo.. You're allowing me to send patches to you so you can funnel
> them through your channel (for now)?

Sure, I'd be glad to do so if that makes your life easier.  Either way
it's no real extra or less overall workload for me :)

thanks,

greg k-h


From linus.walleij at linaro.org  Wed May 11 01:34:48 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 11 May 2016 10:34:48 +0200
Subject: [PATCH v5 08/17] gpio: port LoCoMo gpio support from old driver
In-Reply-To: <20150614152710.GG7557@n2100.arm.linux.org.uk>
References: <1433797008-6246-1-git-send-email-dbaryshkov@gmail.com>
 <1433797008-6246-9-git-send-email-dbaryshkov@gmail.com>
 <20150614152710.GG7557@n2100.arm.linux.org.uk>
Message-ID: <CACRpkdYsf+wEy0juA1ZnpmY8O+aDTt7YketSD-AesBjZmVmzeA@mail.gmail.com>

On Sun, Jun 14, 2015 at 5:27 PM, Russell King - ARM Linux
<linux at arm.linux.org.uk> wrote:
> [Dmitry]

>> +     regmap_write(lg->regmap, LOCOMO_GPO, 0x00);
>> +     regmap_write(lg->regmap, LOCOMO_GPE, 0x00);
>> +     regmap_write(lg->regmap, LOCOMO_GPD, 0x00);
>> +     regmap_write(lg->regmap, LOCOMO_GIE, 0x00);
>
> Do we really want to initialise all outputs like this?  It suffers from
> the problem I mention above - it sets all outputs to zero, then sets
> them as inputs, which can lead to glitching.  What if (eg) the LCD was
> left enabled?  This would mean you're not going through the proper
> power-down sequence for the LCD (for example).

This looks dangerous indeed, why did I miss that before.

Is it possible to just leave these registers as-is, or, in case
you want to know at all times their actual states, implement
the .get_direction() callback? They the kernel can explore
the direction and value of the lines.

> TBH, I think GPIO needs to have a way to claim output GPIOs _without_
> programming their current state for situations like this.  That seems
> to have been an oversight in the model for a while now - it's impossible
> to claim GPIO outputs without setting their initial value,

It is possible in the new descriptor API, you can claim a GPIO
for a device with (see <linux/gpio/consumer.h>

enum gpiod_flags {
        GPIOD_ASIS      = 0,
(...)

I understand it may be a bit thick to ask to migrate the whole
SA1100 codebase to GPIO descriptors though, I don't know how
many machines and drivers that would affect.

I'd consider a patch retrofitting this into the old
API if it would see some real use case.

Yours,
Linus Walleij


From eric.auger at linaro.org  Wed May 11 01:38:46 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed, 11 May 2016 10:38:46 +0200
Subject: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability at
 msi domain
In-Reply-To: <57321952.2020206@arm.com>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-6-git-send-email-eric.auger@linaro.org>
 <20160509164942.5af8b30d@t450s.home> <57320803.8070506@linaro.org>
 <57321952.2020206@arm.com>
Message-ID: <5732EF96.4070001@linaro.org>

Hi Robin, Alex,
On 05/10/2016 07:24 PM, Robin Murphy wrote:
> Hi Eric,
> 
> On 10/05/16 17:10, Eric Auger wrote:
>> Hi Alex,
>> On 05/10/2016 12:49 AM, Alex Williamson wrote:
>>> On Wed,  4 May 2016 11:54:16 +0000
>>> Eric Auger <eric.auger at linaro.org> wrote:
>>>
>>>> On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is
>>>> abstracted
>>>> by the msi controller. vfio_safe_irq_domain allows to check whether
>>>> interrupts are "safe" for a given device. They are if the device does
>>>> not use MSI
>>>
>>> Are we sure we're not opening a security hole here?  An MSI is simply a
>>> DMA write, so really whether or not a device uses MSI is irrelevant.
>>> If it can generate a DMA to the MSI doorbell then we need to be
>>> protected and I think we pretty much need to assume that devices are
>>> DMA capable.  Do the MSI domain checks cover this?
>> Let me try to rephrase: we check the device is not attached to an MSI
>> controller (I think this is the semantic of dev_get_msi_domain(dev)).
>>
>> If it is not, we don't have to care about MSI isolation: there will be
>> no IOMMU binding between the device and any MSI doorbell. If it is we
>> check the msi domain is backed by an MSI controller able to perform MSI
>> isolation.
>>
>> So effectively "usage of MSIs" is improper - since it is decided after
>> the group attachment anyway  - and the commit message should rather
>> state "if the device is linked to an MSI controller" (dt msi-parent
>> notion I think).
> 
> Hmm, I think Alex has a point here - on a GICv2m I can happily fire
> arbitrary MSIs from _a shell_ (using /dev/mem), and the CPUs definitely
> aren't in an MSI domain, so I don't think it's valid to assume that a
> device using only wired interrupts, therefore with no connection to any
> MSI controller, isn't still capable of maliciously spewing DMA all over
> any and every doorbell region in the system.

Sorry but I still don't get the point. For the device to reach the
doorbell there must be an IOMMU mapping.

- if the device is not attached to an MSI domain, there won't be any
doorbell iommu mapping built by this series, so no risk, right?

The device will be allowed to reach only memory iommu mapped by
userspace with VFIO DMA MAP standard API. Of course if the userspace can
mmap all the host PA that's a more general issue, right?

- If the device is attached to an MSI domain (msi-parent link), 2 cases:
1) the MSI controller advertises MSI isolation (ITS cases), no risk
2) the MSI controller does not advertise MSI isolation (GICv2m), there
is a security hole.
   a) by default we reject the device attachment
   b) if the userspace overrides the safe interrupt option he accepts
the security hole

What am I missing?

Best Regards

Eric
> 
> Robin.
> 
>> Does it sound better?
>>
>> Regards
>>
>> Eric
>>>
>>>> or if the device uses MSI and the msi-parent controller
>>>> supports IRQ remapping.
>>>>
>>>> Then we check at group level if all devices have safe interrupts: if
>>>> not,
>>>> we only allow the group to be attached if allow_unsafe_interrupts is
>>>> set.
>>>>
>>>> At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP. This is
>>>> changed in next patch.
>>>>
>>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>>>
>>>> ---
>>>> v3 -> v4:
>>>> - rename vfio_msi_parent_irq_remapping_capable into
>>>> vfio_safe_irq_domain
>>>>    and irq_remapping into safe_irq_domains
>>>>
>>>> v2 -> v3:
>>>> - protect vfio_msi_parent_irq_remapping_capable with
>>>>    CONFIG_GENERIC_MSI_IRQ_DOMAIN
>>>> ---
>>>>   drivers/vfio/vfio_iommu_type1.c | 44
>>>> +++++++++++++++++++++++++++++++++++++++--
>>>>   1 file changed, 42 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/vfio/vfio_iommu_type1.c
>>>> b/drivers/vfio/vfio_iommu_type1.c
>>>> index 4d3a6f1..2fc8197 100644
>>>> --- a/drivers/vfio/vfio_iommu_type1.c
>>>> +++ b/drivers/vfio/vfio_iommu_type1.c
>>>> @@ -37,6 +37,8 @@
>>>>   #include <linux/vfio.h>
>>>>   #include <linux/workqueue.h>
>>>>   #include <linux/msi-iommu.h>
>>>> +#include <linux/irqdomain.h>
>>>> +#include <linux/msi.h>
>>>>
>>>>   #define DRIVER_VERSION  "0.2"
>>>>   #define DRIVER_AUTHOR   "Alex Williamson
>>>> <alex.williamson at redhat.com>"
>>>> @@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev,
>>>> void *data)
>>>>       return 0;
>>>>   }
>>>>
>>>> +/**
>>>> + * vfio_safe_irq_domain: returns whether the irq domain
>>>> + * the device is attached to is safe with respect to MSI isolation.
>>>> + * If the irq domain is not an MSI domain, we return it is safe.
>>>> + *
>>>> + * @dev: device handle
>>>> + * @data: unused
>>>> + * returns 0 if the irq domain is safe, -1 if not.
>>>> + */
>>>> +static int vfio_safe_irq_domain(struct device *dev, void *data)
>>>> +{
>>>> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
>>>> +    struct irq_domain *domain;
>>>> +    struct msi_domain_info *info;
>>>> +
>>>> +    domain = dev_get_msi_domain(dev);
>>>> +    if (!domain)
>>>> +        return 0;
>>>> +
>>>> +    info = msi_get_domain_info(domain);
>>>> +
>>>> +    if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
>>>> +        return -1;
>>>> +#endif
>>>> +    return 0;
>>>> +}
>>>> +
>>>>   static int vfio_iommu_replay(struct vfio_iommu *iommu,
>>>>                    struct vfio_domain *domain)
>>>>   {
>>>> @@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void
>>>> *iommu_data,
>>>>       struct vfio_group *group, *g;
>>>>       struct vfio_domain *domain, *d;
>>>>       struct bus_type *bus = NULL;
>>>> -    int ret;
>>>> +    int ret, safe_irq_domains;
>>>>
>>>>       mutex_lock(&iommu->lock);
>>>>
>>>> @@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void
>>>> *iommu_data,
>>>>
>>>>       group->iommu_group = iommu_group;
>>>>
>>>> +    /*
>>>> +     * Determine if all the devices of the group have a safe irq
>>>> domain
>>>> +     * with respect to MSI isolation
>>>> +     */
>>>> +    safe_irq_domains = !iommu_group_for_each_dev(iommu_group, &bus,
>>>> +                       vfio_safe_irq_domain);
>>>> +
>>>>       /* Determine bus_type in order to allocate a domain */
>>>>       ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type);
>>>>       if (ret)
>>>> @@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void
>>>> *iommu_data,
>>>>       INIT_LIST_HEAD(&domain->group_list);
>>>>       list_add(&group->next, &domain->group_list);
>>>>
>>>> +    /*
>>>> +     * to advertise safe interrupts either the IOMMU or the MSI
>>>> controllers
>>>> +     * must support IRQ remapping/interrupt translation
>>>> +     */
>>>>       if (!allow_unsafe_interrupts &&
>>>> -        !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
>>>> +        (!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) &&
>>>> !safe_irq_domains)) {
>>>>           pr_warn("%s: No interrupt remapping support.  Use the
>>>> module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU
>>>> support on this platform\n",
>>>>                  __func__);
>>>>           ret = -EPERM;
>>>
>>
> 



From linus.walleij at linaro.org  Wed May 11 01:44:36 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 11 May 2016 10:44:36 +0200
Subject: [PATCH v2] pinctrl: rockchip: fix pull setting error for rk3399
In-Reply-To: <1462937968-4952-1-git-send-email-wxt@rock-chips.com>
References: <1462937968-4952-1-git-send-email-wxt@rock-chips.com>
Message-ID: <CACRpkdasLu0ZtOBuyfE=BG6TwY=-NY7Xksywv3jimNGXyx08AQ@mail.gmail.com>

On Wed, May 11, 2016 at 5:39 AM, Caesar Wang <wxt at rock-chips.com> wrote:

> From: David Wu <david.wu at rock-chips.com>
>
> This patch fixes the pinctrl pull bias setting, since the pull up/down
> setting is the contrary for gpio0(just the gpio0a and gpio0b) and
> gpio2(just the gpio2c and gpio2d).
>
> From the TRM said, the gpio0a pull polarity setting:
> gpio0a_p
> GPIO0A PE/PS programmation section, every
> GPIO bit corresponding to 2bits[PS:PE]
> 2'b00: Z(Normal operation);
> 2'b11: weak 1(pull-up);
> 2'b01: weak 0(pull-down);
> 2'b10: Z(Normal operation);
>
> Then, the other gpios setting as the following:
> gpio1a_p (e.g.: gpio1, gpio2a, gpio2b, gpio3...)
> GPIO1A PU/PD programmation section, every
> GPIO bit corresponding to 2bits
> 2'b00: Z(Normal operation);
> 2'b01: weak 1(pull-up);
> 2'b10: weak 0(pull-down);
> 2'b11: Z(Normal operation);
>
> For example,(rk3399evb board)
> sdmmc_cd --->gpio0_a7
> localhost / # io -r -4 0xff320040
> ff320040: 00004d5f
> In general,the value should be 0x0000cd5f since the pin has been set
> in the dts.
>
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> Cc: Linus Walleij <linus.walleij at linaro.org>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Cc: linux-gpio at vger.kernel.org
> ---
>
> Changes in v2:
> - As Doug commnets on https://patchwork.kernel.org/patch/9056961/
> - update the commit for gpio2.
> - change the print error messgae.

Patch applied with the Review tags.

Yours,
Linus Walleij


From peter.ujfalusi at ti.com  Wed May 11 01:44:33 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 11 May 2016 11:44:33 +0300
Subject: [PATCH v3 0/7] ARM/ASoC: OMAP3: Fix McBSP2/3 sidetone support
In-Reply-To: <1461927202-17677-1-git-send-email-peter.ujfalusi@ti.com>
References: <1461927202-17677-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <69ff65ee-e5d1-09fb-fd91-8d7b4d8fdda4@ti.com>

Tony, Paul,

On 04/29/16 13:53, Peter Ujfalusi wrote:
> Hi,
> 
> Based on the ongoing discussion on v2 (ARM: OMAP3: Fix McBSP2/3 hwmod setup for
> sidetone) I have dropped the removal of the sidetone hwmod and only corrected
> it. The series now includes all related changes needed to have correct sidetone
> support whenever we boot in legacy or in DT mode.
> 
> This time the ASoC part have dependency on earlier patches so they can not be
> applied separately.

How should we proceed from here? I don't want to start designing the ST
separation infrastructure which would be based on this series, but if there
are outstanding issues found on this, I would need to go back to the drawing
board.
The separation will be mostly new code and code shuffle in ASoC, but for
legacy I will need to build up something in arch as well, so I would need at
least one release cycle to start with things.

-- 
P?ter

> Regards,
> Peter
> ---
> Peter Ujfalusi (7):
>   ARM: OMAP3: hwmod data: Fix McBSP2/3 sidetone data
>   ARM: dts: omap3: Add clocks to McBSP nodes
>   ARM: OMAP3: McBSP: New callback for McBSP2/3 ICLK idle configuration
>   ARM: OMAP3: pdata-quirks: Add support for McBSP2/3 sidetone handling
>   ASoc: omap-mcbsp: Rename omap_mcbsp_sysfs_remove() to
>     omap_mcbsp_cleanup()
>   ASoC: omap-mcbsp: sidetone: Use the new callback for iclk handling
>   ARM: OMAP2+: McBSP: Remove the old iclk allow/deny idle code
> 
>  arch/arm/boot/dts/omap3.dtsi                | 10 ++++++++++
>  arch/arm/mach-omap2/mcbsp.c                 | 31 ++++++++++++++++-------------
>  arch/arm/mach-omap2/omap_hwmod_3xxx_data.c  | 24 ++++------------------
>  arch/arm/mach-omap2/pdata-quirks.c          | 18 +++++++++++++++++
>  include/linux/platform_data/asoc-ti-mcbsp.h |  4 +++-
>  sound/soc/omap/mcbsp.c                      | 21 +++++++++++++------
>  sound/soc/omap/mcbsp.h                      |  3 ++-
>  sound/soc/omap/omap-mcbsp.c                 |  5 ++++-
>  8 files changed, 73 insertions(+), 43 deletions(-)
> 



From moinejf at free.fr  Wed May 11 01:45:56 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Wed, 11 May 2016 10:45:56 +0200
Subject: [PATCH 13/16] clk: sunxi-ng: Add N-K-M Factor clock
In-Reply-To: <1462737711-10017-14-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-14-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <20160511104556.037a2c17e3a6a0503a26fbf0@free.fr>

On Sun,  8 May 2016 22:01:48 +0200
Maxime Ripard <maxime.ripard at free-electrons.com> wrote:

> Introduce support for clocks that multiply and divide using two linear
> multipliers and one linear divider.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile  |   1 +
>  drivers/clk/sunxi-ng/ccu_nkm.c | 144 +++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_nkm.h |  42 ++++++++++++
>  3 files changed, 187 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_nkm.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_nkm.h
> 
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index fba64c7f4fcd..2bb8bc22e907 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -8,6 +8,7 @@ obj-y += ccu_m.o
>  obj-y += ccu_mp.o
>  obj-y += ccu_mux.o
>  obj-y += ccu_nk.o
> +obj-y += ccu_nkm.o
>  obj-y += ccu_nm.o
>  obj-y += ccu_p.o
>  obj-y += ccu_phase.o
> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
> new file mode 100644
> index 000000000000..9019c7f6988c
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_nkm.c
	[snip]
> @@ -0,0 +1,144 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/rational.h>
> +
> +#include "ccu_gate.h"
> +#include "ccu_nkm.h"
> +
> +void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
> +		       unsigned long max_n, unsigned long max_k, unsigned long max_m,
> +		       unsigned long *n, unsigned long *k, unsigned long *m)

Should be static

	[snip]

> +static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
> +			   unsigned long parent_rate)
> +{
> +	struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
> +	unsigned long n, k, m;
> +	unsigned long flags;
> +	u32 reg;
> +
> +	ccu_nkm_find_best(parent_rate, rate, 1 << nkm->n.width,
> +			  1 << nkm->k.width, 1 << nkm->m.width,
> +			  &n, &k, &m);
> +
> +	spin_lock_irqsave(nkm->common.lock, flags);
> +
> +	reg = readl(nkm->common.base + nkm->common.reg);
> +	reg &= ~GENMASK(nkm->n.width + nkm->n.shift, nkm->n.shift);
> +	reg &= ~GENMASK(nkm->k.width + nkm->k.shift, nkm->k.shift);
> +	reg &= ~GENMASK(nkm->m.width + nkm->m.shift, nkm->m.shift);
> +
> +	reg |= (n - 1) << nkm->m.shift;
> +	reg |= (k - 1) << nkm->m.shift;
> +	reg |= (m - 1) << nkm->m.shift;

	reg |= (n - 1) << nkm->n.shift;
	reg |= (k - 1) << nkm->k.shift;

> +
> +	writel(reg, nkm->common.base + nkm->common.reg);
> +
> +	spin_unlock_irqrestore(nkm->common.lock, flags);
> +
> +	ccu_helper_wait_for_lock(&nkm->common, nkm->lock);
> +
> +	return 0;
> +}
	[snip]

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From moinejf at free.fr  Wed May 11 01:49:06 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Wed, 11 May 2016 10:49:06 +0200
Subject: [PATCH 14/16] clk: sunxi-ng: Add N-K-M-P factor clock
In-Reply-To: <1462737711-10017-15-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-15-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <20160511104906.988800e89f99d24a81f3cb43@free.fr>

On Sun,  8 May 2016 22:01:49 +0200
Maxime Ripard <maxime.ripard at free-electrons.com> wrote:

> Introduce support for clocks that use a combination of two linear
> multipliers (N and K factors), one linear divider (M) and one power of two
> divider (P).
> 
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile   |   1 +
>  drivers/clk/sunxi-ng/ccu_nkmp.c | 157 ++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_nkmp.h |  43 +++++++++++
>  3 files changed, 201 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_nkmp.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_nkmp.h
> 
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 2bb8bc22e907..c794f57b6fb1 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -9,6 +9,7 @@ obj-y += ccu_mp.o
>  obj-y += ccu_mux.o
>  obj-y += ccu_nk.o
>  obj-y += ccu_nkm.o
> +obj-y += ccu_nkmp.o
>  obj-y += ccu_nm.o
>  obj-y += ccu_p.o
>  obj-y += ccu_phase.o
> diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c
> new file mode 100644
> index 000000000000..b7da00773cd6
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c
	[snip]
> @@ -0,0 +1,157 @@
	[snip]
> +static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
> +			   unsigned long parent_rate)
> +{
> +	struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
> +	unsigned long n, k, m, p;
> +	unsigned long flags;
> +	u32 reg;
> +
> +	ccu_nkmp_find_best(parent_rate, rate,
> +			   1 << nkmp->n.width, 1 << nkmp->k.width,
> +			   1 << nkmp->m.width, (1 << nkmp->p.width) - 1,
> +			   &n, &k, &m, &p);
> +
> +	spin_lock_irqsave(nkmp->common.lock, flags);
> +
> +	reg = readl(nkmp->common.base + nkmp->common.reg);
> +	reg &= ~GENMASK(nkmp->n.width + nkmp->n.shift, nkmp->n.shift);
> +	reg &= ~GENMASK(nkmp->k.width + nkmp->k.shift, nkmp->k.shift);
> +	reg &= ~GENMASK(nkmp->m.width + nkmp->m.shift, nkmp->m.shift);
> +	reg &= ~GENMASK(nkmp->p.width + nkmp->p.shift, nkmp->p.shift);
> +
> +	reg |= (n - 1) << nkmp->m.shift;
> +	reg |= (k - 1) << nkmp->m.shift;

	reg |= (n - 1) << nkmp->n.shift;
	reg |= (k - 1) << nkmp->k.shift;

> +	reg |= (m - 1) << nkmp->m.shift;
> +	reg |= p << nkmp->p.shift;
> +
> +	writel(reg, nkmp->common.base + nkmp->common.reg);
> +
> +	spin_unlock_irqrestore(nkmp->common.lock, flags);
> +
> +	ccu_helper_wait_for_lock(&nkmp->common, nkmp->lock);
> +
> +	return 0;
> +}
	[snip]

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From linus.walleij at linaro.org  Wed May 11 01:49:57 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 11 May 2016 10:49:57 +0200
Subject: [PATCH v2 1/4] pinctrl: amlogic: Add support for Amlogic Meson
 GXBB SoC
In-Reply-To: <1462176138-29433-2-git-send-email-carlo@caione.org>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
 <1462176138-29433-2-git-send-email-carlo@caione.org>
Message-ID: <CACRpkdaK6_P0DpAVOEQM-A0rpTJzgo2C4Kr+Mg8ygDe=gEoHxA@mail.gmail.com>

On Mon, May 2, 2016 at 10:02 AM, Carlo Caione <carlo at caione.org> wrote:

> From: Carlo Caione <carlo at endlessm.com>
>
> This patch adds the basic platform file to support the pin controller
> found on the Amlogic Meson GXBB SoCs.
>
> Signed-off-by: Carlo Caione <carlo at endlessm.com>

Patch applied with Kevin's ACK/review tag.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Wed May 11 01:52:46 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 11 May 2016 10:52:46 +0200
Subject: [PATCH v2 2/4] documentation: Add compatibles for Amlogic Meson
 GXBB pin controllers
In-Reply-To: <1462176138-29433-3-git-send-email-carlo@caione.org>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
 <1462176138-29433-3-git-send-email-carlo@caione.org>
Message-ID: <CACRpkdZQHX2YFh7CFpaagrY+BBtyAejdUs4F7ow+3+9+F6mU-A@mail.gmail.com>

On Mon, May 2, 2016 at 10:02 AM, Carlo Caione <carlo at caione.org> wrote:

> From: Carlo Caione <carlo at endlessm.com>
>
> Add the two new compatibles for the Amlogic Meson GXBB pin controllers.
>
> Signed-off-by: Carlo Caione <carlo at endlessm.com>
> ---
>  Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
> index 32f4a2d..fe7fe0b 100644
> --- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
> +++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
> @@ -5,6 +5,8 @@ Required properties for the root node:
>                       "amlogic,meson8b-cbus-pinctrl"
>                       "amlogic,meson8-aobus-pinctrl"
>                       "amlogic,meson8b-aobus-pinctrl"
> +                     "amlogic,meson-gxbb-periphs-pinctrl"
> +                     "amlogic,meson-gxbb-aobus-pinctrl"
>   - reg: address and size of registers controlling irq functionality

This does NOT apply to the pin control tree because upstream does
NOT look like this. It looks like that in linux-next however.

So I guess this must be patched somewhere else
than the pin control tree, so apply it there:

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

Yours,
Linus Walleij


From linux at armlinux.org.uk  Wed May 11 01:52:03 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Wed, 11 May 2016 09:52:03 +0100
Subject: [PATCH 00/12] Fixing TI Keystone2 kexec
In-Reply-To: <20160511082923.GC8995@dhcp-128-65.nay.redhat.com>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <20160511082923.GC8995@dhcp-128-65.nay.redhat.com>
Message-ID: <20160511085203.GN19428@n2100.arm.linux.org.uk>

On Wed, May 11, 2016 at 04:29:23PM +0800, Dave Young wrote:
> Hi, Russell
> 
> On 04/28/16 at 10:26am, Russell King - ARM Linux wrote:
> > These changes are required for TI Keystone2 kexec to be functional.  TI
> > Keystone2 has the run-time view of physical memory above 4GiB, but with
> > a boot time alias below 4GiB which can only be used during the early
> > boot.
> > 
> > This means we need to translate run-time physical addresses (which the
> > kernel uses) to boot-time physical addresses, which, having discussed
> > with Eric, is what the kexec tools and kexec kernel API requires.
> > 
> > We publish a special set of boot time resources in /proc/iomem, which
> > the (modified) kexec tools look for in preference to the normal resources.
> > Hence, if these are found, the kexec tools make use of these resources,
> > and thus kexec tools use the boot-time view of physical memory.
> 
> I think getting memory ranges from device tree will be better than
> adding more stuff to /proc/iomem. Geoff's arm64 kexec patches is using dtb
> you can refer to the patchset.

I think you're confusing things.  DT doesn't contain the boot alias
memory ranges - it's not a separate chunk of memory.  It's an alias
of the same physical address space found higher in the physical
address range.

If we put it in DT, then we need a way to also describe that it is an
alias of some other bit of physical memory.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From linus.walleij at linaro.org  Wed May 11 01:53:35 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 11 May 2016 10:53:35 +0200
Subject: [PATCH v2 3/4] ARM64: Kconfig: Select the Amlogic Meson pin
 controller driver
In-Reply-To: <1462176138-29433-4-git-send-email-carlo@caione.org>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
 <1462176138-29433-4-git-send-email-carlo@caione.org>
Message-ID: <CACRpkdbTr7YUrzSQQci929ugBhTkJKWvpjdf5Wo3HkfVKFhGLw@mail.gmail.com>

On Mon, May 2, 2016 at 10:02 AM, Carlo Caione <carlo at caione.org> wrote:

> From: Carlo Caione <carlo at endlessm.com>
>
> Select the Meson pin controller driver also for the AArch64 Meson
> platform.
>
> Signed-off-by: Carlo Caione <carlo at endlessm.com>

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

I guess this should get merged through the ARM SoC tree.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Wed May 11 01:54:35 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 11 May 2016 10:54:35 +0200
Subject: [PATCH v2 0/4] Amlogic: GXBB: Add pin controller
In-Reply-To: <m2bn4jbbzn.fsf@baylibre.com>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
 <m2bn4jbbzn.fsf@baylibre.com>
Message-ID: <CACRpkdbFm0g-7vayj9KVVEGHWvPbSehD=Yd8Xn-hZc-aKTpEpg@mail.gmail.com>

On Fri, May 6, 2016 at 2:35 PM, Kevin Hilman <khilman at baylibre.com> wrote:

> Linus, with your ack, we could keep this series together, or if you
> prefer, you can take patch 1, and Carlo can take the others through his
> tree.

I've applied 1/4.

The rest can go in wherever, they seem pretty orthogonal.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Wed May 11 01:57:21 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 11 May 2016 10:57:21 +0200
Subject: [PATCH 0/7] pinctrl: meson: Add a bunch more pins
In-Reply-To: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
Message-ID: <CACRpkdY99HWOQ4fhuYuPZ4JpwK6s75TXYpaBaBxhLLJFRLCd6w@mail.gmail.com>

On Fri, May 6, 2016 at 4:21 PM, Kevin Hilman <khilman at baylibre.com> wrote:

> Add support for several more devices, both in the EE domain and in the
> AO domain.  Also, add the pins to the corresponding DTS files.
>
> Tested on odroid-c2 and Amlogic P200 boards, and verified with working
> ethernet.
>
> Depends on the initial GXBB pinctrl support from Carlo[1].  Also
> available in my git tree[2] with all the dependencies included.

Carlo can you review Kevin's patches? I'd like to apply them if
nothing's controversial about them.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Wed May 11 01:58:42 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 11 May 2016 10:58:42 +0200
Subject: [PATCH] pinctrl: meson: Fix eth_tx_en bit index
In-Reply-To: <1462730389-10961-2-git-send-email-serveralex@gmail.com>
References: <1462730389-10961-1-git-send-email-serveralex@gmail.com>
 <1462730389-10961-2-git-send-email-serveralex@gmail.com>
Message-ID: <CACRpkdZz631dio28wqa71uZe3=NSZO55RCxZaQSixfH-o1f4Cw@mail.gmail.com>

On Sun, May 8, 2016 at 7:59 PM, Alexander M?ller <serveralex at gmail.com> wrote:

> Fix pinctrl eth_tx_en bit index according to Hardkernel ODROID-C1 datasheet.
>
> Signed-off-by: Alexander M?ller <serveralex at gmail.com>

Carlo can you review this change?

Yours,
Linus Walleij


From boris.brezillon at free-electrons.com  Wed May 11 02:00:02 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Wed, 11 May 2016 11:00:02 +0200
Subject: [PATCH] ARM: dts: at91: sam9x5: Fix the memory range assigned to the
 PMC
Message-ID: <1462957202-22671-1-git-send-email-boris.brezillon@free-electrons.com>

The memory range assigned to the PMC (Power Management Controller) was
not including the PMC_PCR register which are used to control peripheral
clocks.

This was working fine thanks to the page granularity of ioremap(), but
started to fail when we switched to syscon/regmap, because regmap is
making sure that all accesses are falling into the reserved range.

Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
Reported-by: Richard Genoud <richard.genoud at gmail.com>
Tested-by: Richard Genoud <richard.genoud at gmail.com>
Fixes: 863a81c3be1d ("clk: at91: make use of syscon to share PMC registers in several drivers")
Cc: <stable at vger.kernel.org>
---
Hi Arnd,

This patch is fixing a regression reported by Richard. Since this
regression was introduced in 4.6-rc1 it would be great if you could
take it before 4.6 is released.

Thanks,

Boris
---
 arch/arm/boot/dts/at91sam9x5.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 0827d59..cd0cd5f 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -106,7 +106,7 @@
 
 			pmc: pmc at fffffc00 {
 				compatible = "atmel,at91sam9x5-pmc", "syscon";
-				reg = <0xfffffc00 0x100>;
+				reg = <0xfffffc00 0x200>;
 				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
 				interrupt-controller;
 				#address-cells = <1>;
-- 
2.7.4



From catalin.marinas at arm.com  Wed May 11 02:12:08 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 11 May 2016 10:12:08 +0100
Subject: [PATCH v6 06/14] arm64, numa: rework numa_add_memblk()
In-Reply-To: <1461780436-27182-7-git-send-email-ddaney.cavm@gmail.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <1461780436-27182-7-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <20160511091207.GA3051@e104818-lin.cambridge.arm.com>

On Wed, Apr 27, 2016 at 11:07:08AM -0700, David Daney wrote:
> From: Hanjun Guo <hanjun.guo at linaro.org>
> 
> Rework numa_add_memblk() to update the parameter "u64 size" to "u64
> end", this will make it consistent with x86 and simplifies the arm64
> ACPI NUMA code to be added later.
> 
> Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
> Signed-off-by: Robert Richter <rrichter at cavium.com>
> Signed-off-by: David Daney <david.daney at cavium.com>

Acked-by: Catalin Marinas <catalin.marinas at arm.com>


From catalin.marinas at arm.com  Wed May 11 02:12:29 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 11 May 2016 10:12:29 +0100
Subject: [PATCH v6 07/14] arm64, numa: Cleanup NUMA disabled messages.
In-Reply-To: <1461780436-27182-8-git-send-email-ddaney.cavm@gmail.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <1461780436-27182-8-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <20160511091229.GB3051@e104818-lin.cambridge.arm.com>

On Wed, Apr 27, 2016 at 11:07:09AM -0700, David Daney wrote:
> From: David Daney <david.daney at cavium.com>
> 
> As noted by Dennis Chen, we don't want to print "No NUMA configuration
> found" if NUMA was forced off from the command line.
> 
> Change the type of numa_off to bool, and clean up printing code.
> Print "NUMA disabled" if forced off on command line and "No NUMA
> configuration found" if there was no firmware NUMA information.
> 
> Signed-off-by: David Daney <david.daney at cavium.com>

Acked-by: Catalin Marinas <catalin.marinas at arm.com>


From zengzhaoxiu at 163.com  Wed May 11 02:06:17 2016
From: zengzhaoxiu at 163.com (zengzhaoxiu at 163.com)
Date: Wed, 11 May 2016 17:06:17 +0800
Subject: [patch V4 02/31] bitops: Include generic parity.h in some
 architectures' bitops.h
In-Reply-To: <1462955158-28394-1-git-send-email-zengzhaoxiu@163.com>
References: <1462955158-28394-1-git-send-email-zengzhaoxiu@163.com>
Message-ID: <1462957641-24241-1-git-send-email-zengzhaoxiu@163.com>

From: Zhaoxiu Zeng <zhaoxiu.zeng at gmail.com>

Simply use the generic version.

Signed-off-by: Zhaoxiu Zeng <zhaoxiu.zeng at gmail.com>
Acked-by: Hans-Christian Noren Egtvedt <egtvedt at samfundet.no> [for avr32]
---
 arch/arc/include/asm/bitops.h      | 1 +
 arch/arm/include/asm/bitops.h      | 1 +
 arch/arm64/include/asm/bitops.h    | 1 +
 arch/avr32/include/asm/bitops.h    | 1 +
 arch/c6x/include/asm/bitops.h      | 1 +
 arch/cris/include/asm/bitops.h     | 1 +
 arch/frv/include/asm/bitops.h      | 1 +
 arch/h8300/include/asm/bitops.h    | 1 +
 arch/hexagon/include/asm/bitops.h  | 1 +
 arch/m32r/include/asm/bitops.h     | 1 +
 arch/m68k/include/asm/bitops.h     | 1 +
 arch/metag/include/asm/bitops.h    | 1 +
 arch/mn10300/include/asm/bitops.h  | 1 +
 arch/openrisc/include/asm/bitops.h | 1 +
 arch/parisc/include/asm/bitops.h   | 1 +
 arch/s390/include/asm/bitops.h     | 1 +
 arch/sh/include/asm/bitops.h       | 1 +
 arch/xtensa/include/asm/bitops.h   | 1 +
 18 files changed, 18 insertions(+)

diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h
index 0352fb8..7967e47 100644
--- a/arch/arc/include/asm/bitops.h
+++ b/arch/arc/include/asm/bitops.h
@@ -370,6 +370,7 @@ static inline __attribute__ ((const)) int __ffs(unsigned long x)
 #define ffz(x)	__ffs(~(x))
 
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/lock.h>
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index e943e6c..99f28a6 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -313,6 +313,7 @@ static inline unsigned long __ffs(unsigned long x)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #ifdef __ARMEB__
diff --git a/arch/arm64/include/asm/bitops.h b/arch/arm64/include/asm/bitops.h
index 9c19594..eac4965 100644
--- a/arch/arm64/include/asm/bitops.h
+++ b/arch/arm64/include/asm/bitops.h
@@ -44,6 +44,7 @@ extern int test_and_change_bit(int nr, volatile unsigned long *p);
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/non-atomic.h>
diff --git a/arch/avr32/include/asm/bitops.h b/arch/avr32/include/asm/bitops.h
index 910d537..9f4a2ce 100644
--- a/arch/avr32/include/asm/bitops.h
+++ b/arch/avr32/include/asm/bitops.h
@@ -298,6 +298,7 @@ static inline int ffs(unsigned long word)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 extern unsigned long find_next_zero_bit_le(const void *addr,
diff --git a/arch/c6x/include/asm/bitops.h b/arch/c6x/include/asm/bitops.h
index f0ab012..94eb0d1 100644
--- a/arch/c6x/include/asm/bitops.h
+++ b/arch/c6x/include/asm/bitops.h
@@ -87,6 +87,7 @@ static inline int ffs(int x)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/atomic.h>
diff --git a/arch/cris/include/asm/bitops.h b/arch/cris/include/asm/bitops.h
index 8062cb5..06bc246 100644
--- a/arch/cris/include/asm/bitops.h
+++ b/arch/cris/include/asm/bitops.h
@@ -36,6 +36,7 @@
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/lock.h>
 
diff --git a/arch/frv/include/asm/bitops.h b/arch/frv/include/asm/bitops.h
index 0df8e95..f2a7ee8 100644
--- a/arch/frv/include/asm/bitops.h
+++ b/arch/frv/include/asm/bitops.h
@@ -314,6 +314,7 @@ int __ilog2_u64(u64 n)
 
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/le.h>
diff --git a/arch/h8300/include/asm/bitops.h b/arch/h8300/include/asm/bitops.h
index 05999ab..e392db2 100644
--- a/arch/h8300/include/asm/bitops.h
+++ b/arch/h8300/include/asm/bitops.h
@@ -172,6 +172,7 @@ static inline unsigned long __ffs(unsigned long word)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
diff --git a/arch/hexagon/include/asm/bitops.h b/arch/hexagon/include/asm/bitops.h
index 5e4a59b..2df614e 100644
--- a/arch/hexagon/include/asm/bitops.h
+++ b/arch/hexagon/include/asm/bitops.h
@@ -290,6 +290,7 @@ static inline unsigned long __fls(unsigned long word)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
diff --git a/arch/m32r/include/asm/bitops.h b/arch/m32r/include/asm/bitops.h
index 86ba2b4..e3cf46b 100644
--- a/arch/m32r/include/asm/bitops.h
+++ b/arch/m32r/include/asm/bitops.h
@@ -259,6 +259,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #endif /* __KERNEL__ */
diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h
index b4a9b0d..fd673ea 100644
--- a/arch/m68k/include/asm/bitops.h
+++ b/arch/m68k/include/asm/bitops.h
@@ -519,6 +519,7 @@ static inline int __fls(int x)
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #endif /* __KERNEL__ */
 
diff --git a/arch/metag/include/asm/bitops.h b/arch/metag/include/asm/bitops.h
index 2671134..ad13087 100644
--- a/arch/metag/include/asm/bitops.h
+++ b/arch/metag/include/asm/bitops.h
@@ -118,6 +118,7 @@ static inline int test_and_change_bit(unsigned int bit,
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
diff --git a/arch/mn10300/include/asm/bitops.h b/arch/mn10300/include/asm/bitops.h
index fe6f8e2..60761b7 100644
--- a/arch/mn10300/include/asm/bitops.h
+++ b/arch/mn10300/include/asm/bitops.h
@@ -225,6 +225,7 @@ int ffs(int x)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
 #include <asm-generic/bitops/le.h>
 
diff --git a/arch/openrisc/include/asm/bitops.h b/arch/openrisc/include/asm/bitops.h
index 3003cda..8c97642 100644
--- a/arch/openrisc/include/asm/bitops.h
+++ b/arch/openrisc/include/asm/bitops.h
@@ -43,6 +43,7 @@
 #include <asm-generic/bitops/sched.h>
 #include <asm/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 
 #include <asm-generic/bitops/atomic.h>
diff --git a/arch/parisc/include/asm/bitops.h b/arch/parisc/include/asm/bitops.h
index 3f9406d..867ba10 100644
--- a/arch/parisc/include/asm/bitops.h
+++ b/arch/parisc/include/asm/bitops.h
@@ -211,6 +211,7 @@ static __inline__ int fls(int x)
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 8043f10..198eead 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -460,6 +460,7 @@ static inline int fls(int word)
 #include <asm-generic/bitops/ffz.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
diff --git a/arch/sh/include/asm/bitops.h b/arch/sh/include/asm/bitops.h
index fc8e652..4bf0c35 100644
--- a/arch/sh/include/asm/bitops.h
+++ b/arch/sh/include/asm/bitops.h
@@ -86,6 +86,7 @@ static inline unsigned long ffz(unsigned long word)
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
diff --git a/arch/xtensa/include/asm/bitops.h b/arch/xtensa/include/asm/bitops.h
index 3f44fa2..981fa83 100644
--- a/arch/xtensa/include/asm/bitops.h
+++ b/arch/xtensa/include/asm/bitops.h
@@ -229,6 +229,7 @@ test_and_change_bit(unsigned int bit, volatile unsigned long *p)
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
 
-- 
2.7.4




From carlo at caione.org  Wed May 11 02:13:23 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 11 May 2016 11:13:23 +0200
Subject: [PATCH] pinctrl: meson: Fix eth_tx_en bit index
In-Reply-To: <CACRpkdZz631dio28wqa71uZe3=NSZO55RCxZaQSixfH-o1f4Cw@mail.gmail.com>
References: <1462730389-10961-1-git-send-email-serveralex@gmail.com>
 <1462730389-10961-2-git-send-email-serveralex@gmail.com>
 <CACRpkdZz631dio28wqa71uZe3=NSZO55RCxZaQSixfH-o1f4Cw@mail.gmail.com>
Message-ID: <CAOQ7t2bK-9Ogw4aRhLYPFFJrwEevq_SuOJ6LjxwhJrJgcW+e-A@mail.gmail.com>

On Wed, May 11, 2016 at 10:58 AM, Linus Walleij
<linus.walleij at linaro.org> wrote:
> On Sun, May 8, 2016 at 7:59 PM, Alexander M?ller <serveralex at gmail.com> wrote:
>
>> Fix pinctrl eth_tx_en bit index according to Hardkernel ODROID-C1 datasheet.
>>
>> Signed-off-by: Alexander M?ller <serveralex at gmail.com>
>
> Carlo can you review this change?

Acked-by: Carlo Caione <carlo at endlessm.com>

just to let you know this patch has been posted also as part of a
bigger patchset here
http://permalink.gmane.org/gmane.linux.ports.arm.kernel/498960

-- 
Carlo Caione


From dyoung at redhat.com  Wed May 11 02:13:38 2016
From: dyoung at redhat.com (Dave Young)
Date: Wed, 11 May 2016 17:13:38 +0800
Subject: [PATCH 00/12] Fixing TI Keystone2 kexec
In-Reply-To: <20160511085203.GN19428@n2100.arm.linux.org.uk>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <20160511082923.GC8995@dhcp-128-65.nay.redhat.com>
 <20160511085203.GN19428@n2100.arm.linux.org.uk>
Message-ID: <20160511091338.GC10825@dhcp-128-65.nay.redhat.com>

On 05/11/16 at 09:52am, Russell King - ARM Linux wrote:
> On Wed, May 11, 2016 at 04:29:23PM +0800, Dave Young wrote:
> > Hi, Russell
> > 
> > On 04/28/16 at 10:26am, Russell King - ARM Linux wrote:
> > > These changes are required for TI Keystone2 kexec to be functional.  TI
> > > Keystone2 has the run-time view of physical memory above 4GiB, but with
> > > a boot time alias below 4GiB which can only be used during the early
> > > boot.
> > > 
> > > This means we need to translate run-time physical addresses (which the
> > > kernel uses) to boot-time physical addresses, which, having discussed
> > > with Eric, is what the kexec tools and kexec kernel API requires.
> > > 
> > > We publish a special set of boot time resources in /proc/iomem, which
> > > the (modified) kexec tools look for in preference to the normal resources.
> > > Hence, if these are found, the kexec tools make use of these resources,
> > > and thus kexec tools use the boot-time view of physical memory.
> > 
> > I think getting memory ranges from device tree will be better than
> > adding more stuff to /proc/iomem. Geoff's arm64 kexec patches is using dtb
> > you can refer to the patchset.
> 
> I think you're confusing things.  DT doesn't contain the boot alias
> memory ranges - it's not a separate chunk of memory.  It's an alias
> of the same physical address space found higher in the physical
> address range.

Hmm, if we forget about kexec how does the 1st kernel get boot memory?
not from DT?

> 
> If we put it in DT, then we need a way to also describe that it is an
> alias of some other bit of physical memory.

I may missed the background, I just want kexec to get infomation just like
the normal kernel.

> 
> -- 
> RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.

Thanks
Dave


From carlo at caione.org  Wed May 11 02:18:11 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 11 May 2016 11:18:11 +0200
Subject: [PATCH 0/7] pinctrl: meson: Add a bunch more pins
In-Reply-To: <CACRpkdY99HWOQ4fhuYuPZ4JpwK6s75TXYpaBaBxhLLJFRLCd6w@mail.gmail.com>
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
 <CACRpkdY99HWOQ4fhuYuPZ4JpwK6s75TXYpaBaBxhLLJFRLCd6w@mail.gmail.com>
Message-ID: <CAOQ7t2Ys-zow-wn4p5chYxrYrjun-9_5p4_Xij6bXLApyt5itw@mail.gmail.com>

On Wed, May 11, 2016 at 10:57 AM, Linus Walleij
<linus.walleij at linaro.org> wrote:
> On Fri, May 6, 2016 at 4:21 PM, Kevin Hilman <khilman at baylibre.com> wrote:
>
>> Add support for several more devices, both in the EE domain and in the
>> AO domain.  Also, add the pins to the corresponding DTS files.
>>
>> Tested on odroid-c2 and Amlogic P200 boards, and verified with working
>> ethernet.
>>
>> Depends on the initial GXBB pinctrl support from Carlo[1].  Also
>> available in my git tree[2] with all the dependencies included.
>
> Carlo can you review Kevin's patches? I'd like to apply them if
> nothing's controversial about them.

Go ahead and apply them:

Acked-by: Carlo Caione <carlo at endlessm.com>

The ack is on the formal correctness since I still do not have access
to the datasheet.

Thanks,

-- 
Carlo Caione


From henryc.chen at mediatek.com  Wed May 11 02:12:07 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Wed, 11 May 2016 17:12:07 +0800
Subject: Add support for regulator operation mode of mt6397 
Message-ID: <1462957929-20105-1-git-send-email-henryc.chen@mediatek.com>

Some regulators support different operating modes, but there is no suitable
property that can pass the opeation mode constraints on runtime at present.

This series making the change to specify supported modes as a devicetree list.
Consumers can change or get the regulator operation mode by regulator_set_mode
/regulator_get_mode and define the support operating mode on devicetree.

There is a requirement from SVS driver. SVS calibartion requires that the
regulator be in its low-noise (pwm mode) state at boot, but at all other times
it can be normal mode for power saving.
http://www.spinics.net/lists/devicetree/msg111204.html



From henryc.chen at mediatek.com  Wed May 11 02:12:08 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Wed, 11 May 2016 17:12:08 +0800
Subject: [PATCH 1/2] regulator: Add support for parsing operation mode
In-Reply-To: <1462957929-20105-1-git-send-email-henryc.chen@mediatek.com>
References: <1462957929-20105-1-git-send-email-henryc.chen@mediatek.com>
Message-ID: <1462957929-20105-2-git-send-email-henryc.chen@mediatek.com>

Some regulators support their operating mode to be changed by
consumers for module specific purpose.

This patch adds support to parse those properties and fill the
regulator constraints so the regulator core can call the
regualtor_set_mode to change the modes.

Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
---
 Documentation/devicetree/bindings/regulator/regulator.txt | 10 ++++++++++
 drivers/regulator/of_regulator.c                          | 14 ++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt
index ecfc593..88f98f0 100644
--- a/Documentation/devicetree/bindings/regulator/regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/regulator.txt
@@ -49,6 +49,16 @@ Optional properties:
 	0: Disable active discharge.
 	1: Enable active discharge.
 	Absence of this property will leave configuration to default.
+- regulator-allow-change-mode: allow the regulator mode to be configured
+- regulator-supported-modes: Regulators can run in a variety of different operating
+  modes depending on output load. This allows further system power savings by
+  selecting the best (and most efficient) regulator mode for a desired load.
+  The definition for each of these operation is defined at
+  include/linux/regulator/consumer.h
+	0: FAST.
+	1: NORMAL.
+	2: IDLE.
+	3: STANDBY.
 
 Deprecated properties:
 - regulator-compatible: If a regulator chip contains multiple
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 6b0aa80..12fe8c8 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -167,6 +167,20 @@ static void of_get_regulation_constraints(struct device_node *np,
 		suspend_state = NULL;
 		suspend_np = NULL;
 	}
+
+	if (of_property_read_bool(np, "regulator-allow-change-mode"))
+		constraints->valid_ops_mask |= REGULATOR_CHANGE_MODE;
+
+	ret = of_property_count_elems_of_size(np,
+					      "regulator-supported-modes",
+					      sizeof(u32));
+	for (i = 0; i < ret; i++) {
+		u32 mode;
+
+		of_property_read_u32_index(np, "regulator-supported-modes",
+					   i, &mode);
+		constraints->valid_modes_mask |= (1 << mode);
+	}
 }
 
 /**
-- 
1.8.1.1.dirty



From henryc.chen at mediatek.com  Wed May 11 02:12:09 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Wed, 11 May 2016 17:12:09 +0800
Subject: [PATCH 2/2] regulator: mt6397: Add buck change mode regulator
 interface for mt6397
In-Reply-To: <1462957929-20105-1-git-send-email-henryc.chen@mediatek.com>
References: <1462957929-20105-1-git-send-email-henryc.chen@mediatek.com>
Message-ID: <1462957929-20105-3-git-send-email-henryc.chen@mediatek.com>

BUCKs of mt6397 have auto mode and pwm mode.
User can use regulator interfaces to control modes.

Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
---
 .../bindings/regulator/mt6397-regulator.txt        | 22 +++++
 drivers/regulator/mt6397-regulator.c               | 95 +++++++++++++++++++---
 2 files changed, 105 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/regulator/mt6397-regulator.txt b/Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
index a42b1d6..d3167f2 100644
--- a/Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
@@ -7,6 +7,26 @@ Required properties:
   The definition for each of these nodes is defined using the standard binding
   for regulators at Documentation/devicetree/bindings/regulator/regulator.txt.
 
+The mt6397 buck supports two different operating modes: Fast and Normal
+Mode. Some regulators support the modes to be changed by the consumers during
+normal operation.
+
+The regulators that support the standard "regulator-allow-change-mode" property,
+changing their mode during normal operation are:
+  buck_vpca15, buck_vpca7, buck_vsramca15, buck_vsramca7, buck_vcore, buck_vgpu,
+  buck_vdrm, buck_vio18
+
+The possible values for "regulator-supported-modes" are:
+	0: PWM mode, mapping to regulator fast mode, allow the
+	converter to remain in the PWM mode regardless of the load current, so
+	that the noise spectrum of the converter can be minimized for certain
+	highly-noise-sensitive handset applications.
+	1: Auto mode, mapping to regulator normal mode, mode switch by current
+	loading. At light load currents, the converter automatically enters
+	PFM mode to save power and improve light load efficiency. At heavy
+	load currents, the converter automatically enters PWM mode to minimiz
+	the noise spectrum of the converter.
+
 The valid names for regulators are::
 BUCK:
   buck_vpca15, buck_vpca7, buck_vsramca15, buck_vsramca7, buck_vcore, buck_vgpu,
@@ -30,6 +50,8 @@ Example:
 				regulator-max-microvolt = <1350000>;
 				regulator-ramp-delay = <12500>;
 				regulator-enable-ramp-delay = <200>;
+				regulator-allow-change-mode;
+				regulator-supported-modes = <0 1>;
 			};
 
 			mt6397_vpca7_reg: buck_vpca7 {
diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c
index 17a5b6c..c6c6aa85 100644
--- a/drivers/regulator/mt6397-regulator.c
+++ b/drivers/regulator/mt6397-regulator.c
@@ -23,6 +23,9 @@
 #include <linux/regulator/mt6397-regulator.h>
 #include <linux/regulator/of_regulator.h>
 
+#define MT6397_BUCK_MODE_AUTO	0
+#define MT6397_BUCK_MODE_FORCE_PWM	1
+
 /*
  * MT6397 regulators' information
  *
@@ -38,10 +41,14 @@ struct mt6397_regulator_info {
 	u32 vselon_reg;
 	u32 vselctrl_reg;
 	u32 vselctrl_mask;
+	u32 modeset_reg;
+	u32 modeset_mask;
+	u32 modeset_shift;
 };
 
 #define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg,	\
-		vosel, vosel_mask, voselon, vosel_ctrl)			\
+		vosel, vosel_mask, voselon, vosel_ctrl, _modeset_reg,	\
+		_modeset_shift)					\
 [MT6397_ID_##vreg] = {							\
 	.desc = {							\
 		.name = #vreg,						\
@@ -62,6 +69,9 @@ struct mt6397_regulator_info {
 	.vselon_reg = voselon,						\
 	.vselctrl_reg = vosel_ctrl,					\
 	.vselctrl_mask = BIT(1),					\
+	.modeset_reg = _modeset_reg,					\
+	.modeset_mask = BIT(_modeset_shift),				\
+	.modeset_shift = _modeset_shift					\
 }
 
 #define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel,	\
@@ -145,6 +155,63 @@ static const u32 ldo_volt_table7[] = {
 	1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,
 };
 
+static int mt6397_regulator_set_mode(struct regulator_dev *rdev,
+				     unsigned int mode)
+{
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret, val;
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		val = MT6397_BUCK_MODE_FORCE_PWM;
+		break;
+	case REGULATOR_MODE_NORMAL:
+		val = MT6397_BUCK_MODE_AUTO;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err_mode;
+	}
+
+	dev_dbg(&rdev->dev, "mt6397 buck set_mode %#x, %#x, %#x, %#x\n",
+		info->modeset_reg, info->modeset_mask,
+		info->modeset_shift, val);
+
+	val <<= info->modeset_shift;
+	ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
+				 info->modeset_mask, val);
+err_mode:
+	if (ret != 0) {
+		dev_err(&rdev->dev,
+			"Failed to set mt6397 buck mode: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static unsigned int mt6397_regulator_get_mode(struct regulator_dev *rdev)
+{
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret, regval;
+
+	ret = regmap_read(rdev->regmap, info->modeset_reg, &regval);
+	if (ret != 0) {
+		dev_err(&rdev->dev,
+			"Failed to get mt6397 buck mode: %d\n", ret);
+		return ret;
+	}
+
+	switch ((regval & info->modeset_mask) >> info->modeset_shift) {
+	case MT6397_BUCK_MODE_AUTO:
+		return REGULATOR_MODE_NORMAL;
+	case MT6397_BUCK_MODE_FORCE_PWM:
+		return REGULATOR_MODE_FAST;
+	default:
+		return -EINVAL;
+	}
+}
+
 static int mt6397_get_status(struct regulator_dev *rdev)
 {
 	int ret;
@@ -160,7 +227,7 @@ static int mt6397_get_status(struct regulator_dev *rdev)
 	return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
 }
 
-static struct regulator_ops mt6397_volt_range_ops = {
+static const struct regulator_ops mt6397_volt_range_ops = {
 	.list_voltage = regulator_list_voltage_linear_range,
 	.map_voltage = regulator_map_voltage_linear_range,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -170,9 +237,11 @@ static struct regulator_ops mt6397_volt_range_ops = {
 	.disable = regulator_disable_regmap,
 	.is_enabled = regulator_is_enabled_regmap,
 	.get_status = mt6397_get_status,
+	.set_mode = mt6397_regulator_set_mode,
+	.get_mode = mt6397_regulator_get_mode,
 };
 
-static struct regulator_ops mt6397_volt_table_ops = {
+static const struct regulator_ops mt6397_volt_table_ops = {
 	.list_voltage = regulator_list_voltage_table,
 	.map_voltage = regulator_map_voltage_iterate,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -184,7 +253,7 @@ static struct regulator_ops mt6397_volt_table_ops = {
 	.get_status = mt6397_get_status,
 };
 
-static struct regulator_ops mt6397_volt_fixed_ops = {
+static const struct regulator_ops mt6397_volt_fixed_ops = {
 	.list_voltage = regulator_list_voltage_linear,
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
@@ -196,28 +265,30 @@ static struct regulator_ops mt6397_volt_fixed_ops = {
 static struct mt6397_regulator_info mt6397_regulators[] = {
 	MT6397_BUCK("buck_vpca15", VPCA15, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VCA15_CON7, MT6397_VCA15_CON9, 0x7f,
-		MT6397_VCA15_CON10, MT6397_VCA15_CON5),
+		MT6397_VCA15_CON10, MT6397_VCA15_CON5, MT6397_VCA15_CON2, 11),
 	MT6397_BUCK("buck_vpca7", VPCA7, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VPCA7_CON7, MT6397_VPCA7_CON9, 0x7f,
-		MT6397_VPCA7_CON10, MT6397_VPCA7_CON5),
+		MT6397_VPCA7_CON10, MT6397_VPCA7_CON5, MT6397_VPCA7_CON2, 8),
 	MT6397_BUCK("buck_vsramca15", VSRAMCA15, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VSRMCA15_CON7, MT6397_VSRMCA15_CON9,
-		0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5),
+		0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5,
+		MT6397_VSRMCA15_CON2, 8),
 	MT6397_BUCK("buck_vsramca7", VSRAMCA7, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VSRMCA7_CON7, MT6397_VSRMCA7_CON9,
-		0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5),
+		0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5,
+		MT6397_VSRMCA7_CON2, 8),
 	MT6397_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VCORE_CON7, MT6397_VCORE_CON9, 0x7f,
-		MT6397_VCORE_CON10, MT6397_VCORE_CON5),
+		MT6397_VCORE_CON10, MT6397_VCORE_CON5, MT6397_VCORE_CON2, 8),
 	MT6397_BUCK("buck_vgpu", VGPU, 700000, 1493750, 6250, buck_volt_range1,
 		MT6397_VGPU_CON7, MT6397_VGPU_CON9, 0x7f,
-		MT6397_VGPU_CON10, MT6397_VGPU_CON5),
+		MT6397_VGPU_CON10, MT6397_VGPU_CON5, MT6397_VGPU_CON2, 8),
 	MT6397_BUCK("buck_vdrm", VDRM, 800000, 1593750, 6250, buck_volt_range2,
 		MT6397_VDRM_CON7, MT6397_VDRM_CON9, 0x7f,
-		MT6397_VDRM_CON10, MT6397_VDRM_CON5),
+		MT6397_VDRM_CON10, MT6397_VDRM_CON5, MT6397_VDRM_CON2, 8),
 	MT6397_BUCK("buck_vio18", VIO18, 1500000, 2120000, 20000,
 		buck_volt_range3, MT6397_VIO18_CON7, MT6397_VIO18_CON9, 0x1f,
-		MT6397_VIO18_CON10, MT6397_VIO18_CON5),
+		MT6397_VIO18_CON10, MT6397_VIO18_CON5, MT6397_VIO18_CON2, 8),
 	MT6397_REG_FIXED("ldo_vtcxo", VTCXO, MT6397_ANALDO_CON0, 10, 2800000),
 	MT6397_REG_FIXED("ldo_va28", VA28, MT6397_ANALDO_CON1, 14, 2800000),
 	MT6397_LDO("ldo_vcama", VCAMA, ldo_volt_table1,
-- 
1.8.1.1.dirty



From andre.przywara at arm.com  Wed May 11 02:20:05 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 10:20:05 +0100
Subject: [PATCH v3 14/55] KVM: arm/arm64: vgic-new: Add acccessor to new
 struct vgic_irq instance
In-Reply-To: <5731A864.5000109@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-15-git-send-email-andre.przywara@arm.com>
 <5731A864.5000109@arm.com>
Message-ID: <5732F945.1080203@arm.com>

Hi,

On 10/05/16 10:22, Marc Zyngier wrote:
> On 06/05/16 11:45, Andre Przywara wrote:
>> From: Christoffer Dall <christoffer.dall at linaro.org>
>>
>> The new VGIC implementation centers around a struct vgic_irq instance
>> per virtual IRQ.
>> Provide a function to retrieve the right instance for a given IRQ
>> number and (in case of private interrupts) the right VCPU.
>>
>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>>  virt/kvm/arm/vgic/vgic.c | 41 +++++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic.h | 22 ++++++++++++++++++++++
>>  2 files changed, 63 insertions(+)
>>  create mode 100644 virt/kvm/arm/vgic/vgic.c
>>  create mode 100644 virt/kvm/arm/vgic/vgic.h
>>
>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>> new file mode 100644
>> index 0000000..fb45537
>> --- /dev/null
>> +++ b/virt/kvm/arm/vgic/vgic.c
>> @@ -0,0 +1,41 @@
>> +/*
>> + * Copyright (C) 2015, 2016 ARM 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.
>> + *
>> + * 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.
>> + *
>> + * 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/kvm.h>
>> +#include <linux/kvm_host.h>
>> +
>> +#include "vgic.h"
>> +
>> +struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
> 
> nit: this structure isn't referenced anywhere yet.

I see it actually been used in the previous patch, but we only introduce
the header file here. This is one example of why we decided to not
enable compilation early. If you don't mind, I keep it in here.

Thanks for the ACK.

Cheers,
Andre.

>> +
>> +struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>> +			      u32 intid)
>> +{
>> +	/* SGIs and PPIs */
>> +	if (intid <= VGIC_MAX_PRIVATE)
>> +		return &vcpu->arch.vgic_cpu.private_irqs[intid];
>> +
>> +	/* SPIs */
>> +	if (intid <= VGIC_MAX_SPI)
>> +		return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS];
>> +
>> +	/* LPIs are not yet covered */
>> +	if (intid >= VGIC_MIN_LPI)
>> +		return NULL;
>> +
>> +	WARN(1, "Looking up struct vgic_irq for reserved INTID");
>> +	return NULL;
>> +}
>> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>> new file mode 100644
>> index 0000000..61b8d22
>> --- /dev/null
>> +++ b/virt/kvm/arm/vgic/vgic.h
>> @@ -0,0 +1,22 @@
>> +/*
>> + * Copyright (C) 2015, 2016 ARM 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.
>> + *
>> + * 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.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +#ifndef __KVM_ARM_VGIC_NEW_H__
>> +#define __KVM_ARM_VGIC_NEW_H__
>> +
>> +struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>> +			      u32 intid);
>> +
>> +#endif
>>
> 
> Otherwise:
> 
> Acked-by: Marc Zyngier <marc.zyngier at arm.com>
> 
> 	M.
> 


From robin.murphy at arm.com  Wed May 11 02:31:28 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed, 11 May 2016 10:31:28 +0100
Subject: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability at
 msi domain
In-Reply-To: <5732EF96.4070001@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-6-git-send-email-eric.auger@linaro.org>
 <20160509164942.5af8b30d@t450s.home> <57320803.8070506@linaro.org>
 <57321952.2020206@arm.com> <5732EF96.4070001@linaro.org>
Message-ID: <5732FBF0.4040105@arm.com>

On 11/05/16 09:38, Eric Auger wrote:
> Hi Robin, Alex,
> On 05/10/2016 07:24 PM, Robin Murphy wrote:
>> Hi Eric,
>>
>> On 10/05/16 17:10, Eric Auger wrote:
>>> Hi Alex,
>>> On 05/10/2016 12:49 AM, Alex Williamson wrote:
>>>> On Wed,  4 May 2016 11:54:16 +0000
>>>> Eric Auger <eric.auger at linaro.org> wrote:
>>>>
>>>>> On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is
>>>>> abstracted
>>>>> by the msi controller. vfio_safe_irq_domain allows to check whether
>>>>> interrupts are "safe" for a given device. They are if the device does
>>>>> not use MSI
>>>>
>>>> Are we sure we're not opening a security hole here?  An MSI is simply a
>>>> DMA write, so really whether or not a device uses MSI is irrelevant.
>>>> If it can generate a DMA to the MSI doorbell then we need to be
>>>> protected and I think we pretty much need to assume that devices are
>>>> DMA capable.  Do the MSI domain checks cover this?
>>> Let me try to rephrase: we check the device is not attached to an MSI
>>> controller (I think this is the semantic of dev_get_msi_domain(dev)).
>>>
>>> If it is not, we don't have to care about MSI isolation: there will be
>>> no IOMMU binding between the device and any MSI doorbell. If it is we
>>> check the msi domain is backed by an MSI controller able to perform MSI
>>> isolation.
>>>
>>> So effectively "usage of MSIs" is improper - since it is decided after
>>> the group attachment anyway  - and the commit message should rather
>>> state "if the device is linked to an MSI controller" (dt msi-parent
>>> notion I think).
>>
>> Hmm, I think Alex has a point here - on a GICv2m I can happily fire
>> arbitrary MSIs from _a shell_ (using /dev/mem), and the CPUs definitely
>> aren't in an MSI domain, so I don't think it's valid to assume that a
>> device using only wired interrupts, therefore with no connection to any
>> MSI controller, isn't still capable of maliciously spewing DMA all over
>> any and every doorbell region in the system.
>
> Sorry but I still don't get the point. For the device to reach the
> doorbell there must be an IOMMU mapping.

Only when the doorbell is _downstream_ of IOMMU translation.

> - if the device is not attached to an MSI domain, there won't be any
> doorbell iommu mapping built by this series, so no risk, right?
>
> The device will be allowed to reach only memory iommu mapped by
> userspace with VFIO DMA MAP standard API. Of course if the userspace can
> mmap all the host PA that's a more general issue, right?
>
> - If the device is attached to an MSI domain (msi-parent link), 2 cases:
> 1) the MSI controller advertises MSI isolation (ITS cases), no risk
> 2) the MSI controller does not advertise MSI isolation (GICv2m), there
> is a security hole.
>     a) by default we reject the device attachment
>     b) if the userspace overrides the safe interrupt option he accepts
> the security hole
>
> What am I missing?

The x86-with-interrupt-remapping-disabled case. Currently, without 
unsafe_interrupts, everything is rejected - with this patch, we'll still 
reject anything with an MSI domain, but e.g. legacy PCI devices using 
INTx would be free to scribble all over the un-translated interrupt 
region willy-nilly. That's the subtle, but significant, change in behaviour.

Robin.

> Best Regards
>
> Eric
>>
>> Robin.
>>
>>> Does it sound better?
>>>
>>> Regards
>>>
>>> Eric
>>>>
>>>>> or if the device uses MSI and the msi-parent controller
>>>>> supports IRQ remapping.
>>>>>
>>>>> Then we check at group level if all devices have safe interrupts: if
>>>>> not,
>>>>> we only allow the group to be attached if allow_unsafe_interrupts is
>>>>> set.
>>>>>
>>>>> At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP. This is
>>>>> changed in next patch.
>>>>>
>>>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>>>>
>>>>> ---
>>>>> v3 -> v4:
>>>>> - rename vfio_msi_parent_irq_remapping_capable into
>>>>> vfio_safe_irq_domain
>>>>>     and irq_remapping into safe_irq_domains
>>>>>
>>>>> v2 -> v3:
>>>>> - protect vfio_msi_parent_irq_remapping_capable with
>>>>>     CONFIG_GENERIC_MSI_IRQ_DOMAIN
>>>>> ---
>>>>>    drivers/vfio/vfio_iommu_type1.c | 44
>>>>> +++++++++++++++++++++++++++++++++++++++--
>>>>>    1 file changed, 42 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/drivers/vfio/vfio_iommu_type1.c
>>>>> b/drivers/vfio/vfio_iommu_type1.c
>>>>> index 4d3a6f1..2fc8197 100644
>>>>> --- a/drivers/vfio/vfio_iommu_type1.c
>>>>> +++ b/drivers/vfio/vfio_iommu_type1.c
>>>>> @@ -37,6 +37,8 @@
>>>>>    #include <linux/vfio.h>
>>>>>    #include <linux/workqueue.h>
>>>>>    #include <linux/msi-iommu.h>
>>>>> +#include <linux/irqdomain.h>
>>>>> +#include <linux/msi.h>
>>>>>
>>>>>    #define DRIVER_VERSION  "0.2"
>>>>>    #define DRIVER_AUTHOR   "Alex Williamson
>>>>> <alex.williamson at redhat.com>"
>>>>> @@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev,
>>>>> void *data)
>>>>>        return 0;
>>>>>    }
>>>>>
>>>>> +/**
>>>>> + * vfio_safe_irq_domain: returns whether the irq domain
>>>>> + * the device is attached to is safe with respect to MSI isolation.
>>>>> + * If the irq domain is not an MSI domain, we return it is safe.
>>>>> + *
>>>>> + * @dev: device handle
>>>>> + * @data: unused
>>>>> + * returns 0 if the irq domain is safe, -1 if not.
>>>>> + */
>>>>> +static int vfio_safe_irq_domain(struct device *dev, void *data)
>>>>> +{
>>>>> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
>>>>> +    struct irq_domain *domain;
>>>>> +    struct msi_domain_info *info;
>>>>> +
>>>>> +    domain = dev_get_msi_domain(dev);
>>>>> +    if (!domain)
>>>>> +        return 0;
>>>>> +
>>>>> +    info = msi_get_domain_info(domain);
>>>>> +
>>>>> +    if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
>>>>> +        return -1;
>>>>> +#endif
>>>>> +    return 0;
>>>>> +}
>>>>> +
>>>>>    static int vfio_iommu_replay(struct vfio_iommu *iommu,
>>>>>                     struct vfio_domain *domain)
>>>>>    {
>>>>> @@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void
>>>>> *iommu_data,
>>>>>        struct vfio_group *group, *g;
>>>>>        struct vfio_domain *domain, *d;
>>>>>        struct bus_type *bus = NULL;
>>>>> -    int ret;
>>>>> +    int ret, safe_irq_domains;
>>>>>
>>>>>        mutex_lock(&iommu->lock);
>>>>>
>>>>> @@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void
>>>>> *iommu_data,
>>>>>
>>>>>        group->iommu_group = iommu_group;
>>>>>
>>>>> +    /*
>>>>> +     * Determine if all the devices of the group have a safe irq
>>>>> domain
>>>>> +     * with respect to MSI isolation
>>>>> +     */
>>>>> +    safe_irq_domains = !iommu_group_for_each_dev(iommu_group, &bus,
>>>>> +                       vfio_safe_irq_domain);
>>>>> +
>>>>>        /* Determine bus_type in order to allocate a domain */
>>>>>        ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type);
>>>>>        if (ret)
>>>>> @@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void
>>>>> *iommu_data,
>>>>>        INIT_LIST_HEAD(&domain->group_list);
>>>>>        list_add(&group->next, &domain->group_list);
>>>>>
>>>>> +    /*
>>>>> +     * to advertise safe interrupts either the IOMMU or the MSI
>>>>> controllers
>>>>> +     * must support IRQ remapping/interrupt translation
>>>>> +     */
>>>>>        if (!allow_unsafe_interrupts &&
>>>>> -        !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
>>>>> +        (!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) &&
>>>>> !safe_irq_domains)) {
>>>>>            pr_warn("%s: No interrupt remapping support.  Use the
>>>>> module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU
>>>>> support on this platform\n",
>>>>>                   __func__);
>>>>>            ret = -EPERM;
>>>>
>>>
>>
>



From henryc.chen at mediatek.com  Wed May 11 02:31:28 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Wed, 11 May 2016 17:31:28 +0800
Subject: Add support for regulator operation mode of mt6397 
Message-ID: <1462959090-2877-1-git-send-email-henryc.chen@mediatek.com>

Some regulators support different operating modes, but there is no suitable
property that can pass the opeation mode constraints on runtime at present.

This series making the change to specify supported modes as a devicetree list.
Consumers can change or get the regulator operation mode by regulator_set_mode
/regulator_get_mode and define the support operating mode on devicetree.

There is a requirement from SVS driver. SVS calibartion requires that the
regulator be in its low-noise (pwm mode) state at boot, but at all other times
it can be normal mode for power saving
http://www.spinics.net/lists/devicetree/msg111204.html

Henry Chen (2):
  regulator: Add support for parsing operation mode
  regulator: mt6397: Add buck change mode regulator interface for mt6397

 .../bindings/regulator/mt6397-regulator.txt        | 22 +++++
 .../devicetree/bindings/regulator/regulator.txt    | 10 +++
 drivers/regulator/mt6397-regulator.c               | 95 +++++++++++++++++++---
 drivers/regulator/of_regulator.c                   | 14 ++++
 4 files changed, 129 insertions(+), 12 deletions(-)

-- 
1.8.1.1.dirty



From henryc.chen at mediatek.com  Wed May 11 02:31:29 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Wed, 11 May 2016 17:31:29 +0800
Subject: [PATCH RESEND 1/2] regulator: Add support for parsing operation mode
In-Reply-To: <1462959090-2877-1-git-send-email-henryc.chen@mediatek.com>
References: <1462959090-2877-1-git-send-email-henryc.chen@mediatek.com>
Message-ID: <1462959090-2877-2-git-send-email-henryc.chen@mediatek.com>

Some regulators support their operating mode to be changed by
consumers for module specific purpose.

This patch adds support to parse those properties and fill the
regulator constraints so the regulator core can call the
regualtor_set_mode to change the modes.

Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
---
 Documentation/devicetree/bindings/regulator/regulator.txt | 10 ++++++++++
 drivers/regulator/of_regulator.c                          | 14 ++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt
index ecfc593..88f98f0 100644
--- a/Documentation/devicetree/bindings/regulator/regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/regulator.txt
@@ -49,6 +49,16 @@ Optional properties:
 	0: Disable active discharge.
 	1: Enable active discharge.
 	Absence of this property will leave configuration to default.
+- regulator-allow-change-mode: allow the regulator mode to be configured
+- regulator-supported-modes: Regulators can run in a variety of different operating
+  modes depending on output load. This allows further system power savings by
+  selecting the best (and most efficient) regulator mode for a desired load.
+  The definition for each of these operation is defined at
+  include/linux/regulator/consumer.h
+	0: FAST.
+	1: NORMAL.
+	2: IDLE.
+	3: STANDBY.
 
 Deprecated properties:
 - regulator-compatible: If a regulator chip contains multiple
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 6b0aa80..12fe8c8 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -167,6 +167,20 @@ static void of_get_regulation_constraints(struct device_node *np,
 		suspend_state = NULL;
 		suspend_np = NULL;
 	}
+
+	if (of_property_read_bool(np, "regulator-allow-change-mode"))
+		constraints->valid_ops_mask |= REGULATOR_CHANGE_MODE;
+
+	ret = of_property_count_elems_of_size(np,
+					      "regulator-supported-modes",
+					      sizeof(u32));
+	for (i = 0; i < ret; i++) {
+		u32 mode;
+
+		of_property_read_u32_index(np, "regulator-supported-modes",
+					   i, &mode);
+		constraints->valid_modes_mask |= (1 << mode);
+	}
 }
 
 /**
-- 
1.8.1.1.dirty



From henryc.chen at mediatek.com  Wed May 11 02:31:30 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Wed, 11 May 2016 17:31:30 +0800
Subject: [PATCH RESEND 2/2] regulator: mt6397: Add buck change mode regulator
 interface for mt6397
In-Reply-To: <1462959090-2877-1-git-send-email-henryc.chen@mediatek.com>
References: <1462959090-2877-1-git-send-email-henryc.chen@mediatek.com>
Message-ID: <1462959090-2877-3-git-send-email-henryc.chen@mediatek.com>

BUCKs of mt6397 have auto mode and pwm mode.
User can use regulator interfaces to control modes.

Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
---
 .../bindings/regulator/mt6397-regulator.txt        | 22 +++++
 drivers/regulator/mt6397-regulator.c               | 95 +++++++++++++++++++---
 2 files changed, 105 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/regulator/mt6397-regulator.txt b/Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
index a42b1d6..d3167f2 100644
--- a/Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
@@ -7,6 +7,26 @@ Required properties:
   The definition for each of these nodes is defined using the standard binding
   for regulators at Documentation/devicetree/bindings/regulator/regulator.txt.
 
+The mt6397 buck supports two different operating modes: Fast and Normal
+Mode. Some regulators support the modes to be changed by the consumers during
+normal operation.
+
+The regulators that support the standard "regulator-allow-change-mode" property,
+changing their mode during normal operation are:
+  buck_vpca15, buck_vpca7, buck_vsramca15, buck_vsramca7, buck_vcore, buck_vgpu,
+  buck_vdrm, buck_vio18
+
+The possible values for "regulator-supported-modes" are:
+	0: PWM mode, mapping to regulator fast mode, allow the
+	converter to remain in the PWM mode regardless of the load current, so
+	that the noise spectrum of the converter can be minimized for certain
+	highly-noise-sensitive handset applications.
+	1: Auto mode, mapping to regulator normal mode, mode switch by current
+	loading. At light load currents, the converter automatically enters
+	PFM mode to save power and improve light load efficiency. At heavy
+	load currents, the converter automatically enters PWM mode to minimiz
+	the noise spectrum of the converter.
+
 The valid names for regulators are::
 BUCK:
   buck_vpca15, buck_vpca7, buck_vsramca15, buck_vsramca7, buck_vcore, buck_vgpu,
@@ -30,6 +50,8 @@ Example:
 				regulator-max-microvolt = <1350000>;
 				regulator-ramp-delay = <12500>;
 				regulator-enable-ramp-delay = <200>;
+				regulator-allow-change-mode;
+				regulator-supported-modes = <0 1>;
 			};
 
 			mt6397_vpca7_reg: buck_vpca7 {
diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c
index 17a5b6c..c6c6aa85 100644
--- a/drivers/regulator/mt6397-regulator.c
+++ b/drivers/regulator/mt6397-regulator.c
@@ -23,6 +23,9 @@
 #include <linux/regulator/mt6397-regulator.h>
 #include <linux/regulator/of_regulator.h>
 
+#define MT6397_BUCK_MODE_AUTO	0
+#define MT6397_BUCK_MODE_FORCE_PWM	1
+
 /*
  * MT6397 regulators' information
  *
@@ -38,10 +41,14 @@ struct mt6397_regulator_info {
 	u32 vselon_reg;
 	u32 vselctrl_reg;
 	u32 vselctrl_mask;
+	u32 modeset_reg;
+	u32 modeset_mask;
+	u32 modeset_shift;
 };
 
 #define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg,	\
-		vosel, vosel_mask, voselon, vosel_ctrl)			\
+		vosel, vosel_mask, voselon, vosel_ctrl, _modeset_reg,	\
+		_modeset_shift)					\
 [MT6397_ID_##vreg] = {							\
 	.desc = {							\
 		.name = #vreg,						\
@@ -62,6 +69,9 @@ struct mt6397_regulator_info {
 	.vselon_reg = voselon,						\
 	.vselctrl_reg = vosel_ctrl,					\
 	.vselctrl_mask = BIT(1),					\
+	.modeset_reg = _modeset_reg,					\
+	.modeset_mask = BIT(_modeset_shift),				\
+	.modeset_shift = _modeset_shift					\
 }
 
 #define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel,	\
@@ -145,6 +155,63 @@ static const u32 ldo_volt_table7[] = {
 	1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,
 };
 
+static int mt6397_regulator_set_mode(struct regulator_dev *rdev,
+				     unsigned int mode)
+{
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret, val;
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		val = MT6397_BUCK_MODE_FORCE_PWM;
+		break;
+	case REGULATOR_MODE_NORMAL:
+		val = MT6397_BUCK_MODE_AUTO;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err_mode;
+	}
+
+	dev_dbg(&rdev->dev, "mt6397 buck set_mode %#x, %#x, %#x, %#x\n",
+		info->modeset_reg, info->modeset_mask,
+		info->modeset_shift, val);
+
+	val <<= info->modeset_shift;
+	ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
+				 info->modeset_mask, val);
+err_mode:
+	if (ret != 0) {
+		dev_err(&rdev->dev,
+			"Failed to set mt6397 buck mode: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static unsigned int mt6397_regulator_get_mode(struct regulator_dev *rdev)
+{
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret, regval;
+
+	ret = regmap_read(rdev->regmap, info->modeset_reg, &regval);
+	if (ret != 0) {
+		dev_err(&rdev->dev,
+			"Failed to get mt6397 buck mode: %d\n", ret);
+		return ret;
+	}
+
+	switch ((regval & info->modeset_mask) >> info->modeset_shift) {
+	case MT6397_BUCK_MODE_AUTO:
+		return REGULATOR_MODE_NORMAL;
+	case MT6397_BUCK_MODE_FORCE_PWM:
+		return REGULATOR_MODE_FAST;
+	default:
+		return -EINVAL;
+	}
+}
+
 static int mt6397_get_status(struct regulator_dev *rdev)
 {
 	int ret;
@@ -160,7 +227,7 @@ static int mt6397_get_status(struct regulator_dev *rdev)
 	return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
 }
 
-static struct regulator_ops mt6397_volt_range_ops = {
+static const struct regulator_ops mt6397_volt_range_ops = {
 	.list_voltage = regulator_list_voltage_linear_range,
 	.map_voltage = regulator_map_voltage_linear_range,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -170,9 +237,11 @@ static struct regulator_ops mt6397_volt_range_ops = {
 	.disable = regulator_disable_regmap,
 	.is_enabled = regulator_is_enabled_regmap,
 	.get_status = mt6397_get_status,
+	.set_mode = mt6397_regulator_set_mode,
+	.get_mode = mt6397_regulator_get_mode,
 };
 
-static struct regulator_ops mt6397_volt_table_ops = {
+static const struct regulator_ops mt6397_volt_table_ops = {
 	.list_voltage = regulator_list_voltage_table,
 	.map_voltage = regulator_map_voltage_iterate,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -184,7 +253,7 @@ static struct regulator_ops mt6397_volt_table_ops = {
 	.get_status = mt6397_get_status,
 };
 
-static struct regulator_ops mt6397_volt_fixed_ops = {
+static const struct regulator_ops mt6397_volt_fixed_ops = {
 	.list_voltage = regulator_list_voltage_linear,
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
@@ -196,28 +265,30 @@ static struct regulator_ops mt6397_volt_fixed_ops = {
 static struct mt6397_regulator_info mt6397_regulators[] = {
 	MT6397_BUCK("buck_vpca15", VPCA15, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VCA15_CON7, MT6397_VCA15_CON9, 0x7f,
-		MT6397_VCA15_CON10, MT6397_VCA15_CON5),
+		MT6397_VCA15_CON10, MT6397_VCA15_CON5, MT6397_VCA15_CON2, 11),
 	MT6397_BUCK("buck_vpca7", VPCA7, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VPCA7_CON7, MT6397_VPCA7_CON9, 0x7f,
-		MT6397_VPCA7_CON10, MT6397_VPCA7_CON5),
+		MT6397_VPCA7_CON10, MT6397_VPCA7_CON5, MT6397_VPCA7_CON2, 8),
 	MT6397_BUCK("buck_vsramca15", VSRAMCA15, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VSRMCA15_CON7, MT6397_VSRMCA15_CON9,
-		0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5),
+		0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5,
+		MT6397_VSRMCA15_CON2, 8),
 	MT6397_BUCK("buck_vsramca7", VSRAMCA7, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VSRMCA7_CON7, MT6397_VSRMCA7_CON9,
-		0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5),
+		0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5,
+		MT6397_VSRMCA7_CON2, 8),
 	MT6397_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VCORE_CON7, MT6397_VCORE_CON9, 0x7f,
-		MT6397_VCORE_CON10, MT6397_VCORE_CON5),
+		MT6397_VCORE_CON10, MT6397_VCORE_CON5, MT6397_VCORE_CON2, 8),
 	MT6397_BUCK("buck_vgpu", VGPU, 700000, 1493750, 6250, buck_volt_range1,
 		MT6397_VGPU_CON7, MT6397_VGPU_CON9, 0x7f,
-		MT6397_VGPU_CON10, MT6397_VGPU_CON5),
+		MT6397_VGPU_CON10, MT6397_VGPU_CON5, MT6397_VGPU_CON2, 8),
 	MT6397_BUCK("buck_vdrm", VDRM, 800000, 1593750, 6250, buck_volt_range2,
 		MT6397_VDRM_CON7, MT6397_VDRM_CON9, 0x7f,
-		MT6397_VDRM_CON10, MT6397_VDRM_CON5),
+		MT6397_VDRM_CON10, MT6397_VDRM_CON5, MT6397_VDRM_CON2, 8),
 	MT6397_BUCK("buck_vio18", VIO18, 1500000, 2120000, 20000,
 		buck_volt_range3, MT6397_VIO18_CON7, MT6397_VIO18_CON9, 0x1f,
-		MT6397_VIO18_CON10, MT6397_VIO18_CON5),
+		MT6397_VIO18_CON10, MT6397_VIO18_CON5, MT6397_VIO18_CON2, 8),
 	MT6397_REG_FIXED("ldo_vtcxo", VTCXO, MT6397_ANALDO_CON0, 10, 2800000),
 	MT6397_REG_FIXED("ldo_va28", VA28, MT6397_ANALDO_CON1, 14, 2800000),
 	MT6397_LDO("ldo_vcama", VCAMA, ldo_volt_table1,
-- 
1.8.1.1.dirty



From linux at armlinux.org.uk  Wed May 11 02:32:55 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Wed, 11 May 2016 10:32:55 +0100
Subject: [PATCH 00/12] Fixing TI Keystone2 kexec
In-Reply-To: <20160511091338.GC10825@dhcp-128-65.nay.redhat.com>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <20160511082923.GC8995@dhcp-128-65.nay.redhat.com>
 <20160511085203.GN19428@n2100.arm.linux.org.uk>
 <20160511091338.GC10825@dhcp-128-65.nay.redhat.com>
Message-ID: <20160511093255.GO19428@n2100.arm.linux.org.uk>

On Wed, May 11, 2016 at 05:13:38PM +0800, Dave Young wrote:
> On 05/11/16 at 09:52am, Russell King - ARM Linux wrote:
> > I think you're confusing things.  DT doesn't contain the boot alias
> > memory ranges - it's not a separate chunk of memory.  It's an alias
> > of the same physical address space found higher in the physical
> > address range.
> 
> Hmm, if we forget about kexec how does the 1st kernel get boot memory?
> not from DT?

Just like any other ARM system, it pulls itself up by its shoe laces.

The kernel assumes that it has been placed into RAM with at least 32KiB
of writable memory below it, which it uses for the initial page tables.
It "guesses" that the executing address, rounded down to I-forget-what-
boundary gives the base address of physical memory.

It sets the page table up using that assumption.  The kernel gets going
with C code, and only _then_ parses the DTB.

If we then find that we're running on TI Keystone 2, part of the early
platform initialisation specifies to the ARM core code that the kernel
is to switch a high physical address space > 4GiB, and this provokes
a "dance" where we tear the MMU back down, run some more assembly code
to fix up the page tables, and re-initialise the MMU before returning
to the kernel C code, this time running in the high physical address
space.  This break-modify-make is an architecture requirement.  We
also record the physical address delta between the original physical
address space and the high physical address space so that we can reverse
the translation for code which needs identity mapping (eg, SMP bringup.)

The DTB only contains the high physical address space memory information,
and the kernel now parses the DTB, and sets the page tables up properly
for the running system.

> > If we put it in DT, then we need a way to also describe that it is an
> > alias of some other bit of physical memory.
> 
> I may missed the background, I just want kexec to get infomation just like
> the normal kernel.

See above.  What you're asking for isn't really possible.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From chunkeey at googlemail.com  Wed May 11 02:34:33 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Wed, 11 May 2016 11:34:33 +0200
Subject: [PATCH v9 0/2] gpio: add DT support for memory-mapped GPIOs
Message-ID: <cover.1462911225.git.chunkeey@googlemail.com>

This patch series adds device tree support for generic memory-mapped GPIOs.
The GPIO library already allows drivers and architecture support code to
reuse generic code for managing a GPIO chip. Currently, a developer has
to create a platform device "basic-mmio-gpio" and attach a bgpio_pdata
platform data structure to make use of it. However, for architectures
which rely on the device tree to enumerate devices, creating custom
platform devices is another extra step that can be avoided by having
direct support via a device tree binding.

I initially came across this patch [0] from ?lvaro Fern?ndez Rojas,
while looking for an easy way to add support for the GPIO of my
WD MyBook Live [1] (APM82181). His generic approach patch allowed
me to easily get the GPIO (and the connected LEDs, buttons, gpiohogs)
up and running. Even thought, Mr. Fernandez initially developed it
for his work on the brcm63xx [2].

The third patch (which can be applied at a later time) moves gpio-clps711x,
gpio-ge, gpio-moxart and gpio-ts4800 into gpio-mmio.c. The old driver files
and makefile entries have been removed. The Kconfig entries for these
drivers are kept for compatibility reasons.

And finally, the most important stat about the series:
	>>> 328 insertions(+), 380 deletions(-) <<<
	It still removes more lines than it adds!
	(This also includes the dt binding)

Thanks!

[0] <https://patchwork.ozlabs.org/patch/422121/>
[1] <https://github.com/chunkeey/MBL-openwrt>
[2] <https://wiki.openwrt.org/doc/hardware/soc/soc.broadcom.bcm63xx>

changelog:

v8 -> v9:
	- made dt match table grep-able
	- reorganized bgpio_dt_parse
	- dropped already applied patch (dt binding) from the series

v7 -> v8:
	- removed ngpio property parser and most flags parsers
	- converted clps711x to switch case for GPIO
	- retained original Kconfig syms which now select GPIO_GENERIC_PLATFORM

v6 -> v7:
	- finally made a PATCH series (based on linux-gpio devel branch)
	- added Rob Herring's ACK to the dt bindings
	- cc'd clps711x, gpio-ge, moxart and ts4800 authors for driver
	  changes.

v5 -> v6:
	- rewrote bindings and driver patch to fit the wd,mbl-gpio
	- unified parser code for gpio-ge, gpio-moxart and gpio-ts4800
	- fixed gpio chip's base being overwritten with bogus "0"
	- fixed compat driver crash when reload gpio-generic.ko module
	- dropped already applied patches from the series
	- rebased code on linus' devel tree
	- moved dt bindings patch to the top of the series

v4 -> v5:
	- reverted rename of gpio-mmio.c back to gpio-generic.c
	- fixed Andy Shevchenko's comments
	- consolidated changes from clps711x, gpio-ge, gpio-moxart and
	  gpio-ts4800 into one patch.

v3 -> v4:
	- renamed gpio-generic.c to gpio-mmio.c
	- changed compat. string to "linux,gpio-mmio"
	- integrated Cirrus clps711x driver
	- integrated GE FGPA gpio-ge driver
	- integrated MOXA ART GPIO driver
	- integrated TS4800 gpio driver
	- reshuffled patches, reworded commits, fixed spelling errors, etc.

Christian Lamparter (1):
  gpio: move clps711x, moxart, ts4800 and gpio-ge into gpio-mmio

?lvaro Fern?ndez Rojas (1):
  gpio: mmio: add DT support for memory-mapped GPIOs

 drivers/gpio/Kconfig         |  16 ++-
 drivers/gpio/Makefile        |   4 -
 drivers/gpio/gpio-clps711x.c |  91 --------------
 drivers/gpio/gpio-ge.c       | 114 ------------------
 drivers/gpio/gpio-mmio.c     | 280 ++++++++++++++++++++++++++++++++++++++++++-
 drivers/gpio/gpio-moxart.c   |  84 -------------
 drivers/gpio/gpio-ts4800.c   |  81 -------------
 7 files changed, 290 insertions(+), 380 deletions(-)
 delete mode 100644 drivers/gpio/gpio-clps711x.c
 delete mode 100644 drivers/gpio/gpio-ge.c
 delete mode 100644 drivers/gpio/gpio-moxart.c
 delete mode 100644 drivers/gpio/gpio-ts4800.c

-- 
2.8.1



From chunkeey at googlemail.com  Wed May 11 02:34:34 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Wed, 11 May 2016 11:34:34 +0200
Subject: [PATCH v9 1/2] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <cover.1462911225.git.chunkeey@googlemail.com>
References: <cover.1462911225.git.chunkeey@googlemail.com>
Message-ID: <2c0675cd6f67bd487105c46c38c72d49d84d4df8.1462911225.git.chunkeey@googlemail.com>

From: ?lvaro Fern?ndez Rojas <noltari at gmail.com>

This patch adds support for defining memory-mapped GPIOs which
are compatible with the existing gpio-mmio interface. The generic
library provides support for many memory-mapped GPIO controllers
that are found in various on-board FPGA and ASIC solutions that
are used to control board's switches, LEDs, chip-selects,
Ethernet/USB PHY power, etc.

For setting GPIO's there are three configurations:
	1. single input/output register resource (named "dat"),
	2. set/clear pair (named "set" and "clr"),
	3. single output register resource and single input resource
	   ("set" and dat").

The configuration is detected by which resources are present.
For the single output register, this drives a 1 by setting a bit
and a zero by clearing a bit.  For the set clr pair, this drives
a 1 by setting a bit in the set register and clears it by setting
a bit in the clear register. The configuration is detected by
which resources are present.

For setting the GPIO direction, there are three configurations:
	a. simple bidirectional GPIOs that requires no configuration.
	b. an output direction register (named "dirout")
	   where a 1 bit indicates the GPIO is an output.
	c. an input direction register (named "dirin")
	   where a 1 bit indicates the GPIO is an input.

The first user for this binding is "wd,mbl-gpio".

Reviewed-by: Andy Shevchenko <andy.shevchenko at gmail.com>
Signed-off-by: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
---
 drivers/gpio/gpio-mmio.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 66 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 6c1cb3b..f72e40e 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -61,6 +61,8 @@ o        `                     ~~~~\___/~~~~    ` controller in FPGA is ,.`
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
 #include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 static void bgpio_write8(void __iomem *reg, unsigned long data)
 {
@@ -569,6 +571,58 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
 	return devm_ioremap_resource(&pdev->dev, r);
 }
 
+#ifdef CONFIG_OF
+static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
+				     struct bgpio_pdata *pdata,
+				     unsigned long *flags)
+{
+	struct device *dev = &pdev->dev;
+
+	pdata->base = -1;
+
+	if (of_property_read_bool(dev->of_node, "no-output"))
+		*flags |= BGPIOF_NO_OUTPUT;
+
+	return 0;
+}
+
+static const struct of_device_id bgpio_of_match[] = {
+	{ .compatible = "wd,mbl-gpio", .data = bgpio_basic_mmio_parse_dt },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, bgpio_of_match);
+
+static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
+					  unsigned long *flags)
+{
+	const int (*parse_dt)(struct platform_device *,
+			      struct bgpio_pdata *, unsigned long *);
+	struct bgpio_pdata *pdata;
+	int err;
+
+	parse_dt = of_device_get_match_data(&pdev->dev);
+	if (!parse_dt)
+		return NULL;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata),
+			     GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	err = parse_dt(pdev, pdata, flags);
+	if (err)
+		return ERR_PTR(err);
+
+	return pdata;
+}
+#else
+static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
+					  unsigned long *flags)
+{
+	return NULL;
+}
+#endif /* CONFIG_OF */
+
 static int bgpio_pdev_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -579,10 +633,19 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
 	void __iomem *dirout;
 	void __iomem *dirin;
 	unsigned long sz;
-	unsigned long flags = pdev->id_entry->driver_data;
+	unsigned long flags = 0;
 	int err;
 	struct gpio_chip *gc;
-	struct bgpio_pdata *pdata = dev_get_platdata(dev);
+	struct bgpio_pdata *pdata;
+
+	pdata = bgpio_parse_dt(pdev, &flags);
+	if (IS_ERR(pdata))
+		return PTR_ERR(pdata);
+
+	if (!pdata) {
+		pdata = dev_get_platdata(dev);
+		flags = pdev->id_entry->driver_data;
+	}
 
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
 	if (!r)
@@ -646,6 +709,7 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table);
 static struct platform_driver bgpio_driver = {
 	.driver = {
 		.name = "basic-mmio-gpio",
+		.of_match_table = of_match_ptr(bgpio_of_match),
 	},
 	.id_table = bgpio_id_table,
 	.probe = bgpio_pdev_probe,
-- 
2.8.1



From chunkeey at googlemail.com  Wed May 11 02:34:35 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Wed, 11 May 2016 11:34:35 +0200
Subject: [PATCH v9 2/2] gpio: move clps711x, moxart,
 ts4800 and gpio-ge into gpio-mmio
In-Reply-To: <cover.1462911225.git.chunkeey@googlemail.com>
References: <cover.1462911225.git.chunkeey@googlemail.com>
Message-ID: <85c74586dbd0023306f012764b85d6aa168b4ae7.1462911225.git.chunkeey@googlemail.com>

This patch integrates the GPIO drivers for the following
boards, SoCs, etc. into gpio-mmio:
 - CLPS711X SoCs
 - MOXA ART SoC
 - TS-4800 FPGA DIO blocks and compatibles
 - GPIO controllers found on some GE Single Board Computers

Cc: Alexander Shiyan <shc_work at mail.ru>
Cc: Julien Grossholtz <julien.grossholtz at savoirfairelinux.com>
Cc: Martyn Welch <martyn.welch at ge.com>
Cc: Jonas Jensen <jonas.jensen at gmail.com>
Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
---
 drivers/gpio/Kconfig         |  16 +++-
 drivers/gpio/Makefile        |   4 -
 drivers/gpio/gpio-clps711x.c |  91 -------------------
 drivers/gpio/gpio-ge.c       | 114 -----------------------
 drivers/gpio/gpio-mmio.c     | 212 +++++++++++++++++++++++++++++++++++++++++++
 drivers/gpio/gpio-moxart.c   |  84 -----------------
 drivers/gpio/gpio-ts4800.c   |  81 -----------------
 7 files changed, 224 insertions(+), 378 deletions(-)
 delete mode 100644 drivers/gpio/gpio-clps711x.c
 delete mode 100644 drivers/gpio/gpio-ge.c
 delete mode 100644 drivers/gpio/gpio-moxart.c
 delete mode 100644 drivers/gpio/gpio-ts4800.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a68d838..e4d1065 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -154,7 +154,7 @@ config GPIO_BRCMSTB
 config GPIO_CLPS711X
 	tristate "CLPS711X GPIO support"
 	depends on ARCH_CLPS711X || COMPILE_TEST
-	select GPIO_GENERIC
+	select GPIO_GENERIC_PLATFORM
 	help
 	  Say yes here to support GPIO on CLPS711X SoCs.
 
@@ -196,7 +196,7 @@ config GPIO_ETRAXFS
 config GPIO_GE_FPGA
 	bool "GE FPGA based GPIO"
 	depends on GE_FPGA
-	select GPIO_GENERIC
+	select GPIO_GENERIC_PLATFORM
 	help
 	  Support for common GPIO functionality provided on some GE Single Board
 	  Computers.
@@ -209,6 +209,14 @@ config GPIO_GENERIC_PLATFORM
 	tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
 	select GPIO_GENERIC
 	help
+	  Select this to support many generic memory-mapped GPIO controllers.
+
+	  This driver also includes support for the following GPIOs:
+	    CLPS711X SoCs
+	    MOXA ART SoC
+	    TS-4800 FPGA DIO blocks and compatibles.
+	    GPIOs found on some GE Single Board Computers.
+
 	  Say yes here to support basic platform_device memory-mapped GPIO controllers.
 
 config GPIO_GRGPIO
@@ -288,7 +296,7 @@ config GPIO_MM_LANTIQ
 config GPIO_MOXART
 	bool "MOXART GPIO support"
 	depends on ARCH_MOXART || COMPILE_TEST
-	select GPIO_GENERIC
+	select GPIO_GENERIC_PLATFORM
 	help
 	  Select this option to enable GPIO driver for
 	  MOXA ART SoC devices.
@@ -408,7 +416,7 @@ config GPIO_TS4800
 	tristate "TS-4800 DIO blocks and compatibles"
 	depends on OF_GPIO
 	depends on SOC_IMX51 || COMPILE_TEST
-	select GPIO_GENERIC
+	select GPIO_GENERIC_PLATFORM
 	help
 	  This driver support TS-4800 FPGA GPIO controllers.
 
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 991598e..d8d63ae 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -31,7 +31,6 @@ obj-$(CONFIG_GPIO_ATH79)	+= gpio-ath79.o
 obj-$(CONFIG_GPIO_BCM_KONA)	+= gpio-bcm-kona.o
 obj-$(CONFIG_GPIO_BRCMSTB)	+= gpio-brcmstb.o
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
-obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o
 obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o
 obj-$(CONFIG_GPIO_CRYSTAL_COVE)	+= gpio-crystalcove.o
 obj-$(CONFIG_GPIO_DA9052)	+= gpio-da9052.o
@@ -43,7 +42,6 @@ obj-$(CONFIG_GPIO_EM)		+= gpio-em.o
 obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o
 obj-$(CONFIG_GPIO_ETRAXFS)	+= gpio-etraxfs.o
 obj-$(CONFIG_GPIO_F7188X)	+= gpio-f7188x.o
-obj-$(CONFIG_GPIO_GE_FPGA)	+= gpio-ge.o
 obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o
 obj-$(CONFIG_GPIO_ICH)		+= gpio-ich.o
 obj-$(CONFIG_GPIO_IOP)		+= gpio-iop.o
@@ -68,7 +66,6 @@ obj-$(CONFIG_GPIO_MC9S08DZ60)	+= gpio-mc9s08dz60.o
 obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)	+= gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MM_LANTIQ)	+= gpio-mm-lantiq.o
-obj-$(CONFIG_GPIO_MOXART)	+= gpio-moxart.o
 obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSIC)		+= gpio-msic.o
@@ -107,7 +104,6 @@ obj-$(CONFIG_GPIO_TPS65218)	+= gpio-tps65218.o
 obj-$(CONFIG_GPIO_TPS6586X)	+= gpio-tps6586x.o
 obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
 obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
-obj-$(CONFIG_GPIO_TS4800)	+= gpio-ts4800.o
 obj-$(CONFIG_GPIO_TS5500)	+= gpio-ts5500.o
 obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
 obj-$(CONFIG_GPIO_TWL6040)	+= gpio-twl6040.o
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
deleted file mode 100644
index 5a69025..0000000
--- a/drivers/gpio/gpio-clps711x.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  CLPS711X GPIO driver
- *
- *  Copyright (C) 2012,2013 Alexander Shiyan <shc_work at mail.ru>
- *
- * 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.
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/gpio/driver.h>
-#include <linux/platform_device.h>
-
-static int clps711x_gpio_probe(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	void __iomem *dat, *dir;
-	struct gpio_chip *gc;
-	struct resource *res;
-	int err, id = np ? of_alias_get_id(np, "gpio") : pdev->id;
-
-	if ((id < 0) || (id > 4))
-		return -ENODEV;
-
-	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	dat = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dat))
-		return PTR_ERR(dat);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	dir = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dir))
-		return PTR_ERR(dir);
-
-	switch (id) {
-	case 3:
-		/* PORTD is inverted logic for direction register */
-		err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
-				 NULL, dir, 0);
-		break;
-	default:
-		err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
-				 dir, NULL, 0);
-		break;
-	}
-
-	if (err)
-		return err;
-
-	switch (id) {
-	case 4:
-		/* PORTE is 3 lines only */
-		gc->ngpio = 3;
-		break;
-	default:
-		break;
-	}
-
-	gc->base = id * 8;
-	gc->owner = THIS_MODULE;
-	platform_set_drvdata(pdev, gc);
-
-	return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
-}
-
-static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = {
-	{ .compatible = "cirrus,clps711x-gpio" },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, clps711x_gpio_ids);
-
-static struct platform_driver clps711x_gpio_driver = {
-	.driver	= {
-		.name		= "clps711x-gpio",
-		.of_match_table	= of_match_ptr(clps711x_gpio_ids),
-	},
-	.probe	= clps711x_gpio_probe,
-};
-module_platform_driver(clps711x_gpio_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Alexander Shiyan <shc_work at mail.ru>");
-MODULE_DESCRIPTION("CLPS711X GPIO driver");
-MODULE_ALIAS("platform:clps711x-gpio");
diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c
deleted file mode 100644
index 8650b29..0000000
--- a/drivers/gpio/gpio-ge.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Driver for GE FPGA based GPIO
- *
- * Author: Martyn Welch <martyn.welch at ge.com>
- *
- * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-/* TODO
- *
- * Configuration of output modes (totem-pole/open-drain)
- * Interrupt configuration - interrupts are always generated the FPGA relies on
- * the I/O interrupt controllers mask to stop them propergating
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/of_address.h>
-#include <linux/module.h>
-#include <linux/gpio/driver.h>
-
-#define GEF_GPIO_DIRECT		0x00
-#define GEF_GPIO_IN		0x04
-#define GEF_GPIO_OUT		0x08
-#define GEF_GPIO_TRIG		0x0C
-#define GEF_GPIO_POLAR_A	0x10
-#define GEF_GPIO_POLAR_B	0x14
-#define GEF_GPIO_INT_STAT	0x18
-#define GEF_GPIO_OVERRUN	0x1C
-#define GEF_GPIO_MODE		0x20
-
-static const struct of_device_id gef_gpio_ids[] = {
-	{
-		.compatible	= "gef,sbc610-gpio",
-		.data		= (void *)19,
-	}, {
-		.compatible	= "gef,sbc310-gpio",
-		.data		= (void *)6,
-	}, {
-		.compatible	= "ge,imp3a-gpio",
-		.data		= (void *)16,
-	},
-	{ }
-};
-MODULE_DEVICE_TABLE(of, gef_gpio_ids);
-
-static int __init gef_gpio_probe(struct platform_device *pdev)
-{
-	const struct of_device_id *of_id =
-		of_match_device(gef_gpio_ids, &pdev->dev);
-	struct gpio_chip *gc;
-	void __iomem *regs;
-	int ret;
-
-	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	regs = of_iomap(pdev->dev.of_node, 0);
-	if (!regs)
-		return -ENOMEM;
-
-	ret = bgpio_init(gc, &pdev->dev, 4, regs + GEF_GPIO_IN,
-			 regs + GEF_GPIO_OUT, NULL, NULL,
-			 regs + GEF_GPIO_DIRECT, BGPIOF_BIG_ENDIAN_BYTE_ORDER);
-	if (ret) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		goto err0;
-	}
-
-	/* Setup pointers to chip functions */
-	gc->label = devm_kstrdup(&pdev->dev, pdev->dev.of_node->full_name,
-				     GFP_KERNEL);
-	if (!gc->label) {
-		ret = -ENOMEM;
-		goto err0;
-	}
-
-	gc->base = -1;
-	gc->ngpio = (u16)(uintptr_t)of_id->data;
-	gc->of_gpio_n_cells = 2;
-	gc->of_node = pdev->dev.of_node;
-
-	/* This function adds a memory mapped GPIO chip */
-	ret = devm_gpiochip_add_data(&pdev->dev, gc, NULL);
-	if (ret)
-		goto err0;
-
-	return 0;
-err0:
-	iounmap(regs);
-	pr_err("%s: GPIO chip registration failed\n",
-			pdev->dev.of_node->full_name);
-	return ret;
-};
-
-static struct platform_driver gef_gpio_driver = {
-	.driver = {
-		.name		= "gef-gpio",
-		.of_match_table	= gef_gpio_ids,
-	},
-};
-module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);
-
-MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
-MODULE_AUTHOR("Martyn Welch <martyn.welch at ge.com");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index f72e40e..1de9172 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -586,8 +586,220 @@ static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
 	return 0;
 }
 
+static int clps711x_parse_dt(struct platform_device *pdev,
+			     struct bgpio_pdata *pdata,
+			     unsigned long *flags)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	const char *dir_reg_name;
+	int id = np ? of_alias_get_id(np, "gpio") : pdev->id;
+
+	switch (id) {
+	case 0:
+	case 1:
+	case 2:
+		pdata->ngpio = 0; /* determined by register width */
+		dir_reg_name = "dirout";
+		break;
+	case 3:
+		pdata->ngpio = 0; /* determined by register width */
+		/* PORTD is inverted logic for direction register */
+		dir_reg_name = "dirin";
+		break;
+	case 4:
+		pdata->ngpio = 3; /* PORTE is 3 lines only */
+		dir_reg_name = "dirout";
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	pdata->base = id * 8;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+	if (!res->name || strcmp("dat", res->name))
+		res->name = devm_kstrdup(&pdev->dev, "dat", GFP_KERNEL);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -EINVAL;
+	if (!res->name || strcmp(dir_reg_name, res->name))
+		res->name = devm_kstrdup(&pdev->dev, dir_reg_name, GFP_KERNEL);
+
+	return 0;
+}
+
+static int ge_dt_cb(struct platform_device *pdev,
+		    struct bgpio_pdata *pdata,
+		    unsigned long *flags)
+{
+	struct device_node *np = pdev->dev.of_node;
+
+	pdata->label = devm_kstrdup(&pdev->dev, np->full_name, GFP_KERNEL);
+	if (!pdata->label)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int moxart_dt_cb(struct platform_device *pdev,
+			struct bgpio_pdata *pdata,
+			unsigned long *flags)
+{
+	pdata->base = 0;
+	pdata->label = "moxart-gpio";
+	return 0;
+}
+
+
+static int ts4800_dt_cb(struct platform_device *pdev,
+			struct bgpio_pdata *pdata,
+			unsigned long *flags)
+{
+	int err;
+
+	err = of_property_read_u32(pdev->dev.of_node, "ngpios", &pdata->ngpio);
+	if (err == -EINVAL) {
+		pdata->ngpio = 16;
+		return 0;
+	}
+
+	return err;
+}
+
+/*
+ * bgpio_init() needs up to five named mmio register resources.
+ * These currently are dat, set, clr, [dirout | dirin]. There
+ * is no particular order or predefined place for the entries.
+ * However, dirout and dirin are mutually exclusive.
+ */
+#define __NUM_COMPAT_OVERRIDE_MMIO_RESOURCES 4
+
+struct compat_gpio_device_data {
+	unsigned int expected_resource_size;
+	unsigned int ngpio;
+	resource_size_t register_width;
+	unsigned long flags;
+	int (*call_back)(struct platform_device *pdev,
+			 struct bgpio_pdata *pdata,
+			 unsigned long *flags);
+	struct resource_replacement {
+		resource_size_t start_offset;
+		const char *name;
+	} resources[__NUM_COMPAT_OVERRIDE_MMIO_RESOURCES];
+};
+#undef __NUM_COMPAT_OVERRIDE_MMIO_RESOURCES
+
+#define ADD_COMPAT_REGISTER(_name, _offset)	\
+	{ .name = (_name), .start_offset = (_offset) }
+
+#define ADD_COMPAT_GPIO(_comp, _sz, _ngpio, _width, _cb, _f, _res...)	\
+	{								\
+	  .compatible = (_comp),					\
+	  .data = &(struct compat_gpio_device_data) {			\
+		.expected_resource_size = (_sz),			\
+		.ngpio = (_ngpio),					\
+		.register_width = (_width),				\
+		.flags = (_f),						\
+		.call_back = (_cb),					\
+		.resources = { _res },					\
+	}								\
+}
+
+#define ADD_COMPAT_GE_GPIO(_name, _ngpio)				\
+	ADD_COMPAT_GPIO(_name, 0x24, _ngpio, 0x4, ge_dt_cb,		\
+		 BGPIOF_BIG_ENDIAN_BYTE_ORDER,				\
+		 ADD_COMPAT_REGISTER("dat", 0x04),			\
+		 ADD_COMPAT_REGISTER("set", 0x08),			\
+		 ADD_COMPAT_REGISTER("dirin", 0x00))			\
+
+static const struct of_device_id compat_gpio_devices[] = {
+	ADD_COMPAT_GE_GPIO("ge,imp3a-gpio", 16),
+	ADD_COMPAT_GE_GPIO("gef,sbc310-gpio", 6),
+	ADD_COMPAT_GE_GPIO("gef,sbc610-gpio", 19),
+	ADD_COMPAT_GPIO("moxa,moxart-gpio", 0xc, 0, 0x4, moxart_dt_cb,
+		 BGPIOF_READ_OUTPUT_REG_SET,
+		 ADD_COMPAT_REGISTER("dat", 0x04),
+		 ADD_COMPAT_REGISTER("set", 0x00),
+		 ADD_COMPAT_REGISTER("dirout", 0x08)),
+	ADD_COMPAT_GPIO("technologic,ts4800-gpio", 0x6, 16, 0x2, ts4800_dt_cb,
+		 0, ADD_COMPAT_REGISTER("dat", 0x00),
+		 ADD_COMPAT_REGISTER("set", 0x02),
+		 ADD_COMPAT_REGISTER("dirout", 0x04)),
+};
+
+#undef ADD_COMPAT_GE_GPIO
+#undef ADD_COMPAT_GPIO
+#undef ADD_COMPAT_REGISTER
+
+static int compat_parse_dt(struct platform_device *pdev,
+			   struct bgpio_pdata *pdata,
+			   unsigned long *flags)
+{
+	const struct device_node *node = pdev->dev.of_node;
+	const struct compat_gpio_device_data *entry;
+	const struct of_device_id *of_id;
+	struct resource *res;
+	int err;
+
+	of_id = of_match_node(compat_gpio_devices, node);
+	if (!of_id)
+		return -ENODEV;
+
+	entry = of_id->data;
+	if (!entry || !entry->resources[0].name)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	if (!res->name || strcmp(entry->resources[0].name, res->name)) {
+		struct resource nres[ARRAY_SIZE(entry->resources)];
+		size_t i;
+
+		if (resource_size(res) != entry->expected_resource_size)
+			return -EINVAL;
+
+		for (i = 0; i < ARRAY_SIZE(entry->resources); i++) {
+			if (!entry->resources[i].name)
+				continue;
+
+			nres[i].name = devm_kstrdup(&pdev->dev,
+				entry->resources[i].name, GFP_KERNEL);
+			nres[i].start = res->start +
+				entry->resources[i].start_offset;
+			nres[i].end = nres[i].start +
+				entry->register_width - 1;
+			nres[i].flags = IORESOURCE_MEM;
+		}
+
+		err = platform_device_add_resources(pdev, nres, i);
+		if (err)
+			return err;
+	}
+
+	pdata->base = -1;
+	pdata->ngpio = entry->ngpio;
+	*flags = entry->flags;
+
+	if (entry->call_back)
+		err = entry->call_back(pdev, pdata, flags);
+
+	return err;
+}
+
 static const struct of_device_id bgpio_of_match[] = {
 	{ .compatible = "wd,mbl-gpio", .data = bgpio_basic_mmio_parse_dt },
+	{ .compatible = "cirrus,clps711x-gpio", .data = clps711x_parse_dt },
+	{ .compatible = "ge,imp3a-gpio", .data = compat_parse_dt },
+	{ .compatible = "gef,sbc310-gpio", .data = compat_parse_dt },
+	{ .compatible = "gef,sbc610-gpio", .data = compat_parse_dt },
+	{ .compatible = "moxa,moxart-gpio", .data = compat_parse_dt },
+	{ .compatible = "technologic,ts4800-gpio", .data = compat_parse_dt },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, bgpio_of_match);
diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c
deleted file mode 100644
index d58d389..0000000
--- a/drivers/gpio/gpio-moxart.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * MOXA ART SoCs GPIO driver.
- *
- * Copyright (C) 2013 Jonas Jensen
- *
- * Jonas Jensen <jonas.jensen at gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/of_address.h>
-#include <linux/of_gpio.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/bitops.h>
-#include <linux/gpio/driver.h>
-
-#define GPIO_DATA_OUT		0x00
-#define GPIO_DATA_IN		0x04
-#define GPIO_PIN_DIRECTION	0x08
-
-static int moxart_gpio_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct resource *res;
-	struct gpio_chip *gc;
-	void __iomem *base;
-	int ret;
-
-	gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	ret = bgpio_init(gc, dev, 4, base + GPIO_DATA_IN,
-			 base + GPIO_DATA_OUT, NULL,
-			 base + GPIO_PIN_DIRECTION, NULL,
-			 BGPIOF_READ_OUTPUT_REG_SET);
-	if (ret) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		return ret;
-	}
-
-	gc->label = "moxart-gpio";
-	gc->request = gpiochip_generic_request;
-	gc->free = gpiochip_generic_free;
-	gc->base = 0;
-	gc->owner = THIS_MODULE;
-
-	ret = devm_gpiochip_add_data(dev, gc, NULL);
-	if (ret) {
-		dev_err(dev, "%s: gpiochip_add failed\n",
-			dev->of_node->full_name);
-		return ret;
-	}
-
-	return ret;
-}
-
-static const struct of_device_id moxart_gpio_match[] = {
-	{ .compatible = "moxa,moxart-gpio" },
-	{ }
-};
-
-static struct platform_driver moxart_gpio_driver = {
-	.driver	= {
-		.name		= "moxart-gpio",
-		.of_match_table	= moxart_gpio_match,
-	},
-	.probe	= moxart_gpio_probe,
-};
-builtin_platform_driver(moxart_gpio_driver);
diff --git a/drivers/gpio/gpio-ts4800.c b/drivers/gpio/gpio-ts4800.c
deleted file mode 100644
index 0c144a7..0000000
--- a/drivers/gpio/gpio-ts4800.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * GPIO driver for the TS-4800 board
- *
- * Copyright (c) 2016 - Savoir-faire Linux
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/gpio/driver.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-
-#define DEFAULT_PIN_NUMBER      16
-#define INPUT_REG_OFFSET        0x00
-#define OUTPUT_REG_OFFSET       0x02
-#define DIRECTION_REG_OFFSET    0x04
-
-static int ts4800_gpio_probe(struct platform_device *pdev)
-{
-	struct device_node *node;
-	struct gpio_chip *chip;
-	struct resource *res;
-	void __iomem *base_addr;
-	int retval;
-	u32 ngpios;
-
-	chip = devm_kzalloc(&pdev->dev, sizeof(struct gpio_chip), GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base_addr = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(base_addr))
-		return PTR_ERR(base_addr);
-
-	node = pdev->dev.of_node;
-	if (!node)
-		return -EINVAL;
-
-	retval = of_property_read_u32(node, "ngpios", &ngpios);
-	if (retval == -EINVAL)
-		ngpios = DEFAULT_PIN_NUMBER;
-	else if (retval)
-		return retval;
-
-	retval = bgpio_init(chip, &pdev->dev, 2, base_addr + INPUT_REG_OFFSET,
-			    base_addr + OUTPUT_REG_OFFSET, NULL,
-			    base_addr + DIRECTION_REG_OFFSET, NULL, 0);
-	if (retval) {
-		dev_err(&pdev->dev, "bgpio_init failed\n");
-		return retval;
-	}
-
-	chip->ngpio = ngpios;
-
-	platform_set_drvdata(pdev, chip);
-
-	return devm_gpiochip_add_data(&pdev->dev, chip, NULL);
-}
-
-static const struct of_device_id ts4800_gpio_of_match[] = {
-	{ .compatible = "technologic,ts4800-gpio", },
-	{},
-};
-
-static struct platform_driver ts4800_gpio_driver = {
-	.driver = {
-		   .name = "ts4800-gpio",
-		   .of_match_table = ts4800_gpio_of_match,
-		   },
-	.probe = ts4800_gpio_probe,
-};
-
-module_platform_driver_probe(ts4800_gpio_driver, ts4800_gpio_probe);
-
-MODULE_AUTHOR("Julien Grossholtz <julien.grossholtz at savoirfairelinux.com>");
-MODULE_DESCRIPTION("TS4800 FPGA GPIO driver");
-MODULE_LICENSE("GPL v2");
-- 
2.8.1



From christoffer.dall at linaro.org  Wed May 11 02:38:21 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 11:38:21 +0200
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world
 switch backend
In-Reply-To: <5731F400.4080004@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
 <20160510133043.GF27623@cbox> <5731E52A.9000402@arm.com>
 <20160510141119.GB20499@cbox> <5731F196.4040906@arm.com>
 <5731F400.4080004@arm.com>
Message-ID: <20160511093821.GI27623@cbox>

On Tue, May 10, 2016 at 03:45:20PM +0100, Marc Zyngier wrote:
> On 10/05/16 15:35, Marc Zyngier wrote:
> > On 10/05/16 15:11, Christoffer Dall wrote:
> >> On Tue, May 10, 2016 at 02:42:02PM +0100, Marc Zyngier wrote:
> >>> On 10/05/16 14:30, Christoffer Dall wrote:
> >>>> On Fri, May 06, 2016 at 11:45:31AM +0100, Andre Przywara wrote:
> >>>>> From: Marc Zyngier <marc.zyngier at arm.com>
> >>>>>
> >>>>> Processing maintenance interrupts and accessing the list registers
> >>>>> are dependent on the host's GIC version.
> >>>>> Introduce vgic-v2.c to contain GICv2 specific functions.
> >>>>> Implement the GICv2 specific code for syncing the emulation state
> >>>>> into the VGIC registers.
> >>>>>
> >>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> >>>>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> >>>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> >>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >>>>> ---
> >>>>> Changelog RFC..v1:
> >>>>> - remove explicit LR_STATE clearing on maintenance interrupt handling
> >>>>> - improve documentation for vgic_v2_populate_lr()
> >>>>> - remove WARN_ON on non-edge IRQs in maintenance interrupts
> >>>>> - simplify multi-CPU source SGI handling
> >>>>>
> >>>>> Changelog v1 .. v2:
> >>>>> - inject the IRQ priority into the list register
> >>>>>
> >>>>> Changelog v2 .. v3:
> >>>>> - cleanup diff containing rebase artifacts
> >>>>>
> >>>>>  include/linux/irqchip/arm-gic.h |   1 +
> >>>>>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
> >>>>>  virt/kvm/arm/vgic/vgic.c        |   6 ++
> >>>>>  virt/kvm/arm/vgic/vgic.h        |   6 ++
> >>>>>  4 files changed, 191 insertions(+)
> >>>>>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
> >>>>>
> >>>>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
> >>>>> index 9c94026..be0d26f 100644
> >>>>> --- a/include/linux/irqchip/arm-gic.h
> >>>>> +++ b/include/linux/irqchip/arm-gic.h
> >>>>> @@ -76,6 +76,7 @@
> >>>>>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
> >>>>>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
> >>>>>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
> >>>>> +#define GICH_LR_PRIORITY_SHIFT		23
> >>>>>  #define GICH_LR_STATE			(3 << 28)
> >>>>>  #define GICH_LR_PENDING_BIT		(1 << 28)
> >>>>>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
> >>>>> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> >>>>> new file mode 100644
> >>>>> index 0000000..4cee616
> >>>>> --- /dev/null
> >>>>> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> >>>>> @@ -0,0 +1,178 @@
> >>>>> +/*
> >>>>> + * Copyright (C) 2015, 2016 ARM 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.
> >>>>> + *
> >>>>> + * 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.
> >>>>> + *
> >>>>> + * 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/irqchip/arm-gic.h>
> >>>>> +#include <linux/kvm.h>
> >>>>> +#include <linux/kvm_host.h>
> >>>>> +
> >>>>> +#include "vgic.h"
> >>>>> +
> >>>>> +/*
> >>>>> + * Call this function to convert a u64 value to an unsigned long * bitmask
> >>>>> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
> >>>>> + *
> >>>>> + * Warning: Calling this function may modify *val.
> >>>>> + */
> >>>>> +static unsigned long *u64_to_bitmask(u64 *val)
> >>>>> +{
> >>>>> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
> >>>>> +	*val = (*val >> 32) | (*val << 32);
> >>>>> +#endif
> >>>>> +	return (unsigned long *)val;
> >>>>> +}
> >>>>> +
> >>>>> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
> >>>>> +{
> >>>>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
> >>>>> +
> >>>>> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
> >>>>> +		u64 eisr = cpuif->vgic_eisr;
> >>>>> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
> >>>>> +		int lr;
> >>>>> +
> >>>>> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
> >>>>> +			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
> >>>>> +
> >>>>> +			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
> >>>>> +
> >>>>> +			kvm_notify_acked_irq(vcpu->kvm, 0,
> >>>>> +					     intid - VGIC_NR_PRIVATE_IRQS);
> >>>>> +
> >>>>
> >>>> why do we need to do this?  I cannot find any consumers of this info
> >>>> after we've left the hyp code.
> >>>
> >>> I believe that's for vhost and irqfd. Or am I misreading your question?
> >>>
> >>
> >> I meant the setting of the bits in vgic_elrsr (sorry, badly placed
> >> comment)...
> >>
> >>>> Also, I think I offered a comment about why we would potentially need
> >>>> this in the first place.  This is the famous race where hardware doesn't
> >>>> guarantee consistency between the MISR and ELRSR right?
> >>>
> >>> That's the one (except it is between EISR and ELRSR). I don't have your
> >>> initial comment at hand, but would something like the following do?
> >>>
> >>> 			/*
> >>> 			 * The maintenance interrupt may not have had a
> >>> 			 * chance to update ELRSR, so let's mark the LRs
> >>> 			 * presents in EISR as empty.
> >>> 			 */
> >>>>
> >>>>> +			cpuif->vgic_elrsr |= 1ULL << lr;
> >>
> >> so, why are we doing this?
> > 
> > Ah! I finally see what you mean: we don't reuse LRs at all with the new code
> > base, so knowing which LR is empty is irrelevant. In which case, something
> > like that should be done:
> > 
> > diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> > index e88b5aa..5a8f4d4 100644
> > --- a/virt/kvm/arm/vgic/vgic-v2.c
> > +++ b/virt/kvm/arm/vgic/vgic-v2.c
> > @@ -52,8 +52,6 @@ void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
> >  
> >  			kvm_notify_acked_irq(vcpu->kvm, 0,
> >  					     intid - VGIC_NR_PRIVATE_IRQS);
> > -
> > -			cpuif->vgic_elrsr |= 1ULL << lr;
> >  		}
> >  	}
> >  
> > diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> > index 53f7847..4102f0f 100644
> > --- a/virt/kvm/arm/vgic/vgic-v3.c
> > +++ b/virt/kvm/arm/vgic/vgic-v3.c
> > @@ -43,8 +43,6 @@ void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> >  
> >  			kvm_notify_acked_irq(vcpu->kvm, 0,
> >  					     intid - VGIC_NR_PRIVATE_IRQS);
> > -
> > -			cpuif->vgic_elrsr |= 1ULL << lr;
> >  		}
> >  
> >  		/*
> > 
> > I'll give it a spin, just to be safe.
> 
> Seems OK on GICv2, and this of course leads to some more possible
> cleanups or optimizations (I think we can get to a state where we
> completely disregards ELRSR). I'll have a look.
> 
should be possible.  Eventually I was thinking if we really need EISR as
well?  Could we not deduct that if we have an incative LR from a struct
vgic_irq that is CONFIG_LEVEL where we wrote the LR to either
pending/active on entry, then an EOI has happened and we should signal
the kvm_notify_acked_irq()...

-Christoffer


From julien.grall at arm.com  Wed May 11 02:38:36 2016
From: julien.grall at arm.com (Julien Grall)
Date: Wed, 11 May 2016 10:38:36 +0100
Subject: [PATCH] arm64: cpuinfo: Missing NULL terminator in
 compat_hwcap_str
In-Reply-To: <20160510145441.GC10785@leverpostej>
References: <1462891231-17605-1-git-send-email-julien.grall@arm.com>
 <20160510145441.GC10785@leverpostej>
Message-ID: <5732FD9C.8000503@arm.com>

Hi Mark,

On 10/05/2016 15:54, Mark Rutland wrote:
> On Tue, May 10, 2016 at 03:40:31PM +0100, Julien Grall wrote:
>> The loop that browses the array compat_hwcap_str will stop when a NULL
>> is encountered, however NULL is missing at the end of array. This will
>> result to overrun until one NULL is found somewhere in the memory.
>
> Probably worth adding something like:
>
> Note for backporting: commit 12d11817eaafa414 ("arm64: Move
> /proc/cpuinfo handling code") moved this code. Prior to that commit, the
> same change should be made in arch/arm64/kernel/setup.c.

I can resend the patch with this changes.

>
>> Fixes: 44b82b7700d0 "arm64: Fix up /proc/cpuinfo"
>> Signed-off-by: Julien Grall <julien.grall at arm.com>
>> Cc: stable at vger.kernel.org
>>
>> ---
>>
>> Cc: Mark Rutland <mark.rutland at arm.com>
>> Cc: Suzuki K. Poulose <suzuki.poulose at arm.com>
>> ---
>
> Wierd middle '---' between the Cc lines above.

It is an habit I have with Xen-devel as the Cc are not necessary after 
it has been committed.

>
> Otherwise:
>
> Reviewed-by: Mark Rutland <mark.rutland at arm.com>

Thank you!

Regards,

-- 
Julien Grall


From christoffer.dall at linaro.org  Wed May 11 02:39:19 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 11:39:19 +0200
Subject: [PATCH v3 19/55] KVM: arm/arm64: vgic-new: Add GICv3 world
 switch backend
In-Reply-To: <CAFEAcA9U9qqsSJt7RfNJmDutCsYwnaPGfi-sEcnxYYjSm5C8sA@mail.gmail.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-20-git-send-email-andre.przywara@arm.com>
 <20160510140454.GG27623@cbox>
 <CAFEAcA9U9qqsSJt7RfNJmDutCsYwnaPGfi-sEcnxYYjSm5C8sA@mail.gmail.com>
Message-ID: <20160511093919.GJ27623@cbox>

On Tue, May 10, 2016 at 03:15:12PM +0100, Peter Maydell wrote:
> On 10 May 2016 at 15:04, Christoffer Dall <christoffer.dall at linaro.org> wrote:
> > On Fri, May 06, 2016 at 11:45:32AM +0100, Andre Przywara wrote:
> >> +     /*
> >> +      * Currently all guest IRQs are Group1, as Group0 would result
> >> +      * in a FIQ in the guest, which it wouldn't expect.
> >
> > I still don't like or understand this comment.  This should simply say
> > that we're making a gross assumption about all interrupts being group1
> > here.
> 
> It's not really an assumption so much as it's a missing feature (aka bug):
> there's no reason the vGIC shouldn't support group 0 interrupts. We
> just get away with only supporting group 1 because Linux guests
> happen to only use group 1 interrupts. If/when the vGIC gains support
> for group0 interrupts, then it should reset with interrupts configured
> in group0 by default.
> 
> >> +      * Eventually we want to make this configurable, so we may
> >> +      * revisit this in the future.
> >> +      */
> 
> The only reason to make it configurable is to work around a guest
> kernel bug whereby Linux assumes that all interrupts start out
> in Group1. Marc sent out a patch earlier today that fixes that bug:
>  https://lkml.org/lkml/2016/5/10/297
> Depending on how long it takes you to fix this missing vgic feature,
> such kernels may all be long-forgotten, in which case you can
> get away without the config option :-)
> 
Agreed with all of the above.  My nit here is simply that if we don't
implement grouping support now, then it's just a gross hack, and we
should just state that until we fix it properly.

-Christoffer


From will.deacon at arm.com  Wed May 11 02:40:57 2016
From: will.deacon at arm.com (Will Deacon)
Date: Wed, 11 May 2016 10:40:57 +0100
Subject: [PATCH] arm64: cpuinfo: Missing NULL terminator in
 compat_hwcap_str
In-Reply-To: <5732FD9C.8000503@arm.com>
References: <1462891231-17605-1-git-send-email-julien.grall@arm.com>
 <20160510145441.GC10785@leverpostej> <5732FD9C.8000503@arm.com>
Message-ID: <20160511094057.GE26564@arm.com>

On Wed, May 11, 2016 at 10:38:36AM +0100, Julien Grall wrote:
> Hi Mark,
> 
> On 10/05/2016 15:54, Mark Rutland wrote:
> >On Tue, May 10, 2016 at 03:40:31PM +0100, Julien Grall wrote:
> >>The loop that browses the array compat_hwcap_str will stop when a NULL
> >>is encountered, however NULL is missing at the end of array. This will
> >>result to overrun until one NULL is found somewhere in the memory.
> >
> >Probably worth adding something like:
> >
> >Note for backporting: commit 12d11817eaafa414 ("arm64: Move
> >/proc/cpuinfo handling code") moved this code. Prior to that commit, the
> >same change should be made in arch/arm64/kernel/setup.c.
> 
> I can resend the patch with this changes.

No need, I've already applied it locally with Mark's suggestions.

Will


From tixy at linaro.org  Wed May 11 02:44:28 2016
From: tixy at linaro.org (Jon Medhurst (Tixy))
Date: Wed, 11 May 2016 10:44:28 +0100
Subject: [PATCH] arm64: kernel: Fix incorrect brk randomization
In-Reply-To: <20160510175549.GA20496@www.outflux.net>
References: <20160510175549.GA20496@www.outflux.net>
Message-ID: <1462959868.2834.17.camel@linaro.org>

On Tue, 2016-05-10 at 10:55 -0700, Kees Cook wrote:
> This fixes two issues with the arm64 brk randomziation. First, the
> STACK_RND_MASK was being used incorrectly. The original code was:
> 
> 	unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
> 
> STACK_RND_MASK is 0x7ff (32-bit) or 0x3ffff (64-bit), with 4K pages where
> PAGE_SHIFT is 12:
> 
> 	#define STACK_RND_MASK	(test_thread_flag(TIF_32BIT) ? \
> 						0x7ff >> (PAGE_SHIFT - 12) : \
> 						0x3ffff >> (PAGE_SHIFT - 12))
> 
> This means the resulting offset from base would be 0x7ff0001 or 0x3ffff0001,
> which is wrong since it creates an unaligned end address. It was likely
> intended to be:
> 
> 	unsigned long range_end = base + ((STACK_RND_MASK + 1) << PAGE_SHIFT)
> 
> Which would result in offsets of 0x800000 (32-bit) and 0x40000000 (64-bit).
> 
> However, even this corrected 32-bit compat offset (0x00800000) is much
> smaller than native ARM's brk randomization value (0x02000000):
> 
> 	unsigned long arch_randomize_brk(struct mm_struct *mm)
> 	{
> 	        unsigned long range_end = mm->brk + 0x02000000;
> 	        return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
> 	}
> 
> So, instead of basing arm64's brk randomization on mistaken STACK_RND_MASK
> calculations, just use specific corrected values for compat (0x2000000)
> and native arm64 (0x40000000).
> 
> Signed-off-by: Kees Cook <keescook at chromium.org>

There seems to be a helper 'is_compat_task()' that does
'test_thread_flag(TIF_32BIT)' so could perhaps be used instead, but
that's too nit-picky. This change makes things more consistent with
arch/arm and other arches, and stops use of STACK_RND_MASK for things
that aren't stack related so seems good all round to me.

Reviewed-by: Jon Medhurst <tixy at linaro.org>

> ---
>  arch/arm64/kernel/process.c | 15 ++++++++-------
>  1 file changed, 8 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> index 80624829db61..0d0969bcd76d 100644
> --- a/arch/arm64/kernel/process.c
> +++ b/arch/arm64/kernel/process.c
> @@ -382,13 +382,14 @@ unsigned long arch_align_stack(unsigned long sp)
>  	return sp & ~0xf;
>  }
>  
> -static unsigned long randomize_base(unsigned long base)
> -{
> -	unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
> -	return randomize_range(base, range_end, 0) ? : base;
> -}
> -
>  unsigned long arch_randomize_brk(struct mm_struct *mm)
>  {
> -	return randomize_base(mm->brk);
> +	unsigned long range_end = mm->brk;
> +
> +	if (test_thread_flag(TIF_32BIT))
> +		range_end += 0x02000000;
> +	else
> +		range_end += 0x40000000;
> +
> +	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
>  }
> -- 
> 2.6.3
> 
> 




From eric.auger at linaro.org  Wed May 11 02:44:36 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed, 11 May 2016 11:44:36 +0200
Subject: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability at
 msi domain
In-Reply-To: <5732FBF0.4040105@arm.com>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-6-git-send-email-eric.auger@linaro.org>
 <20160509164942.5af8b30d@t450s.home> <57320803.8070506@linaro.org>
 <57321952.2020206@arm.com> <5732EF96.4070001@linaro.org>
 <5732FBF0.4040105@arm.com>
Message-ID: <5732FF04.6060202@linaro.org>

Hi Robin,
On 05/11/2016 11:31 AM, Robin Murphy wrote:
> On 11/05/16 09:38, Eric Auger wrote:
>> Hi Robin, Alex,
>> On 05/10/2016 07:24 PM, Robin Murphy wrote:
>>> Hi Eric,
>>>
>>> On 10/05/16 17:10, Eric Auger wrote:
>>>> Hi Alex,
>>>> On 05/10/2016 12:49 AM, Alex Williamson wrote:
>>>>> On Wed,  4 May 2016 11:54:16 +0000
>>>>> Eric Auger <eric.auger at linaro.org> wrote:
>>>>>
>>>>>> On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is
>>>>>> abstracted
>>>>>> by the msi controller. vfio_safe_irq_domain allows to check whether
>>>>>> interrupts are "safe" for a given device. They are if the device does
>>>>>> not use MSI
>>>>>
>>>>> Are we sure we're not opening a security hole here?  An MSI is
>>>>> simply a
>>>>> DMA write, so really whether or not a device uses MSI is irrelevant.
>>>>> If it can generate a DMA to the MSI doorbell then we need to be
>>>>> protected and I think we pretty much need to assume that devices are
>>>>> DMA capable.  Do the MSI domain checks cover this?
>>>> Let me try to rephrase: we check the device is not attached to an MSI
>>>> controller (I think this is the semantic of dev_get_msi_domain(dev)).
>>>>
>>>> If it is not, we don't have to care about MSI isolation: there will be
>>>> no IOMMU binding between the device and any MSI doorbell. If it is we
>>>> check the msi domain is backed by an MSI controller able to perform MSI
>>>> isolation.
>>>>
>>>> So effectively "usage of MSIs" is improper - since it is decided after
>>>> the group attachment anyway  - and the commit message should rather
>>>> state "if the device is linked to an MSI controller" (dt msi-parent
>>>> notion I think).
>>>
>>> Hmm, I think Alex has a point here - on a GICv2m I can happily fire
>>> arbitrary MSIs from _a shell_ (using /dev/mem), and the CPUs definitely
>>> aren't in an MSI domain, so I don't think it's valid to assume that a
>>> device using only wired interrupts, therefore with no connection to any
>>> MSI controller, isn't still capable of maliciously spewing DMA all over
>>> any and every doorbell region in the system.
>>
>> Sorry but I still don't get the point. For the device to reach the
>> doorbell there must be an IOMMU mapping.
> 
> Only when the doorbell is _downstream_ of IOMMU translation.
Yes but that's the root hypothesis with VFIO assignment, right?

Except if the no-iommu option is explicitly set by the userspace, there
must be an IOMMU downstream to the device that protects all the DMA
transactions.
> 
>> - if the device is not attached to an MSI domain, there won't be any
>> doorbell iommu mapping built by this series, so no risk, right?
>>
>> The device will be allowed to reach only memory iommu mapped by
>> userspace with VFIO DMA MAP standard API. Of course if the userspace can
>> mmap all the host PA that's a more general issue, right?
>>
>> - If the device is attached to an MSI domain (msi-parent link), 2 cases:
>> 1) the MSI controller advertises MSI isolation (ITS cases), no risk
>> 2) the MSI controller does not advertise MSI isolation (GICv2m), there
>> is a security hole.
>>     a) by default we reject the device attachment
>>     b) if the userspace overrides the safe interrupt option he accepts
>> the security hole
>>
>> What am I missing?
> 
> The x86-with-interrupt-remapping-disabled case. Currently, without
> unsafe_interrupts, everything is rejected - with this patch, we'll still
> reject anything with an MSI domain, but e.g. legacy PCI devices using
> INTx would be free to scribble all over the un-translated interrupt
> region willy-nilly.
Assuming we have an IOMMU, either we have translated transactions or
faults? So if legacy PCI devices try to write into a doorbell, there
must be faults because there is no IOMMU mapping for doorbells?

Best Regards

Eric
 That's the subtle, but significant, change in
> behaviour.
> 
> Robin.
> 
>> Best Regards
>>
>> Eric
>>>
>>> Robin.
>>>
>>>> Does it sound better?
>>>>
>>>> Regards
>>>>
>>>> Eric
>>>>>
>>>>>> or if the device uses MSI and the msi-parent controller
>>>>>> supports IRQ remapping.
>>>>>>
>>>>>> Then we check at group level if all devices have safe interrupts: if
>>>>>> not,
>>>>>> we only allow the group to be attached if allow_unsafe_interrupts is
>>>>>> set.
>>>>>>
>>>>>> At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP. This is
>>>>>> changed in next patch.
>>>>>>
>>>>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>>>>>
>>>>>> ---
>>>>>> v3 -> v4:
>>>>>> - rename vfio_msi_parent_irq_remapping_capable into
>>>>>> vfio_safe_irq_domain
>>>>>>     and irq_remapping into safe_irq_domains
>>>>>>
>>>>>> v2 -> v3:
>>>>>> - protect vfio_msi_parent_irq_remapping_capable with
>>>>>>     CONFIG_GENERIC_MSI_IRQ_DOMAIN
>>>>>> ---
>>>>>>    drivers/vfio/vfio_iommu_type1.c | 44
>>>>>> +++++++++++++++++++++++++++++++++++++++--
>>>>>>    1 file changed, 42 insertions(+), 2 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/vfio/vfio_iommu_type1.c
>>>>>> b/drivers/vfio/vfio_iommu_type1.c
>>>>>> index 4d3a6f1..2fc8197 100644
>>>>>> --- a/drivers/vfio/vfio_iommu_type1.c
>>>>>> +++ b/drivers/vfio/vfio_iommu_type1.c
>>>>>> @@ -37,6 +37,8 @@
>>>>>>    #include <linux/vfio.h>
>>>>>>    #include <linux/workqueue.h>
>>>>>>    #include <linux/msi-iommu.h>
>>>>>> +#include <linux/irqdomain.h>
>>>>>> +#include <linux/msi.h>
>>>>>>
>>>>>>    #define DRIVER_VERSION  "0.2"
>>>>>>    #define DRIVER_AUTHOR   "Alex Williamson
>>>>>> <alex.williamson at redhat.com>"
>>>>>> @@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev,
>>>>>> void *data)
>>>>>>        return 0;
>>>>>>    }
>>>>>>
>>>>>> +/**
>>>>>> + * vfio_safe_irq_domain: returns whether the irq domain
>>>>>> + * the device is attached to is safe with respect to MSI isolation.
>>>>>> + * If the irq domain is not an MSI domain, we return it is safe.
>>>>>> + *
>>>>>> + * @dev: device handle
>>>>>> + * @data: unused
>>>>>> + * returns 0 if the irq domain is safe, -1 if not.
>>>>>> + */
>>>>>> +static int vfio_safe_irq_domain(struct device *dev, void *data)
>>>>>> +{
>>>>>> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
>>>>>> +    struct irq_domain *domain;
>>>>>> +    struct msi_domain_info *info;
>>>>>> +
>>>>>> +    domain = dev_get_msi_domain(dev);
>>>>>> +    if (!domain)
>>>>>> +        return 0;
>>>>>> +
>>>>>> +    info = msi_get_domain_info(domain);
>>>>>> +
>>>>>> +    if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
>>>>>> +        return -1;
>>>>>> +#endif
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>>    static int vfio_iommu_replay(struct vfio_iommu *iommu,
>>>>>>                     struct vfio_domain *domain)
>>>>>>    {
>>>>>> @@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void
>>>>>> *iommu_data,
>>>>>>        struct vfio_group *group, *g;
>>>>>>        struct vfio_domain *domain, *d;
>>>>>>        struct bus_type *bus = NULL;
>>>>>> -    int ret;
>>>>>> +    int ret, safe_irq_domains;
>>>>>>
>>>>>>        mutex_lock(&iommu->lock);
>>>>>>
>>>>>> @@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void
>>>>>> *iommu_data,
>>>>>>
>>>>>>        group->iommu_group = iommu_group;
>>>>>>
>>>>>> +    /*
>>>>>> +     * Determine if all the devices of the group have a safe irq
>>>>>> domain
>>>>>> +     * with respect to MSI isolation
>>>>>> +     */
>>>>>> +    safe_irq_domains = !iommu_group_for_each_dev(iommu_group, &bus,
>>>>>> +                       vfio_safe_irq_domain);
>>>>>> +
>>>>>>        /* Determine bus_type in order to allocate a domain */
>>>>>>        ret = iommu_group_for_each_dev(iommu_group, &bus,
>>>>>> vfio_bus_type);
>>>>>>        if (ret)
>>>>>> @@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void
>>>>>> *iommu_data,
>>>>>>        INIT_LIST_HEAD(&domain->group_list);
>>>>>>        list_add(&group->next, &domain->group_list);
>>>>>>
>>>>>> +    /*
>>>>>> +     * to advertise safe interrupts either the IOMMU or the MSI
>>>>>> controllers
>>>>>> +     * must support IRQ remapping/interrupt translation
>>>>>> +     */
>>>>>>        if (!allow_unsafe_interrupts &&
>>>>>> -        !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
>>>>>> +        (!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) &&
>>>>>> !safe_irq_domains)) {
>>>>>>            pr_warn("%s: No interrupt remapping support.  Use the
>>>>>> module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU
>>>>>> support on this platform\n",
>>>>>>                   __func__);
>>>>>>            ret = -EPERM;
>>>>>
>>>>
>>>
>>
> 



From christoffer.dall at linaro.org  Wed May 11 02:46:49 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 11:46:49 +0200
Subject: [PATCH v3 21/55] KVM: arm/arm64: vgic-new: Add MMIO handling
 framework
In-Reply-To: <1462531568-9799-22-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-22-git-send-email-andre.przywara@arm.com>
Message-ID: <20160511094649.GK27623@cbox>

On Fri, May 06, 2016 at 11:45:34AM +0100, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Add an MMIO handling framework to the VGIC emulation:
> Each register is described by its offset, size (or number of bits per
> IRQ, if applicable) and the read/write handler functions. We provide
> initialization macros to describe each GIC register later easily.
> 
> Separate dispatch functions for read and write accesses are connected
> to the kvm_io_bus framework and binary-search for the responsible
> register handler based on the offset address within the region.
> We convert the incoming data (referenced by a pointer) to the host's
> endianess and use pass-by-value to hand the data over to the actual
> handler functions.
> 
> The register handler prototype and the endianess conversion are
> courtesy of Christoffer Dall.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - rework MMIO dispatching to use only one kvm_io_bus device
> - document purpose of register region macros
> - rename "this" parameter to "dev"
> - change IGROUPR to be RAO (returning 1 => Group1 IRQs)
> 
> Changelog v1 .. v2:
> * MASSIVE rework:
> - store register_region pointer in kvm_io_bus linked struct
> - replace write_mask_xxx functions with extract_bytes() implementation
> - change handler functions' prototypes to take and return unsigned long
> - use binary search to find matching register handler
> - convert endianess of input data in dispatch_mmio_xxx functions
> - improve readability of register initializer macros
> - remove any GICv2/GICv3 specific functions from vgic-mmio.c
> - rename file from vgic_mmio.c to vgic-mmio.c
> 
> Changelog v2 .. v3:
> - replace inclusion of vgic/vgic.h with arm_vgic.h
> 
>  include/kvm/vgic/vgic.h       |  13 ++++
>  virt/kvm/arm/vgic/vgic-mmio.c | 171 ++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h |  77 +++++++++++++++++++
>  3 files changed, 261 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 2615205..4ec1270 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -106,6 +106,16 @@ struct vgic_irq {
>  	enum vgic_irq_config config;	/* Level or edge */
>  };
>  
> +struct vgic_register_region;
> +
> +struct vgic_io_device {
> +	gpa_t base_addr;
> +	struct kvm_vcpu *redist_vcpu;
> +	const struct vgic_register_region *regions;
> +	int nr_regions;
> +	struct kvm_io_device dev;
> +};
> +
>  struct vgic_dist {
>  	bool			in_kernel;
>  	bool			ready;
> @@ -132,6 +142,9 @@ struct vgic_dist {
>  	bool			enabled;
>  
>  	struct vgic_irq		*spis;
> +
> +	struct vgic_io_device	dist_iodev;
> +	struct vgic_io_device	*redist_iodevs;
>  };
>  
>  struct vgic_v2_cpu_if {
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> new file mode 100644
> index 0000000..f5628cb
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -0,0 +1,171 @@
> +/*
> + * VGIC MMIO handling functions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/bsearch.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/iodev.h>
> +#include <kvm/arm_vgic.h>
> +
> +#include "vgic.h"
> +#include "vgic-mmio.h"
> +
> +/* extract @num bytes at @offset bytes offset in data */
> +unsigned long extract_bytes(unsigned long data,
> +			    unsigned int offset, unsigned int num)
> +{
> +	return (data >> (offset * 8)) & GENMASK_ULL(num * 8 - 1, 0);
> +}
> +
> +unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
> +				 gpa_t addr, unsigned int len)
> +{
> +	return 0;
> +}
> +
> +unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
> +				 gpa_t addr, unsigned int len)
> +{
> +	return -1UL;
> +}
> +
> +void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> +			unsigned int len, unsigned long val)
> +{
> +	/* Ignore */
> +}
> +
> +static int match_region(const void *key, const void *elt)
> +{
> +	const unsigned int offset = (unsigned long)key;
> +	const struct vgic_register_region *region = elt;
> +
> +	if (offset < region->reg_offset)
> +		return -1;
> +
> +	if (offset >= region->reg_offset + region->len)
> +		return 1;
> +
> +	return 0;
> +}
> +
> +/* Find the proper register handler entry given a certain address offset. */
> +static const struct vgic_register_region *
> +vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
> +		      unsigned int offset)
> +{
> +	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
> +		       sizeof(region[0]), match_region);
> +}
> +
> +/*
> + * kvm_mmio_read_buf() returns a value in a format where it can be converted
> + * to a byte array and be directly observed as the guest wanted it to appear
> + * in memory if it had done the store itself, which is LE for the GIC, as the
> + * guest knows the GIC is always LE.
> + *
> + * We convert this value to the CPUs native format to deal with it as a data
> + * value.
> + */
> +unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len)
> +{
> +	unsigned long data = kvm_mmio_read_buf(val, len);
> +
> +	switch (len) {
> +	case 1:
> +		return data;
> +	case 2:
> +		return le16_to_cpu(data);
> +	case 4:
> +		return le32_to_cpu(data);
> +	default:
> +		return le64_to_cpu(data);
> +	}
> +}
> +
> +/*
> + * kvm_mmio_write_buf() expects a value in a format such that if converted to
> + * a byte array it is observed as the guest would see it if it could perform
> + * the load directly.  Since the GIC is LE, and the guest knows this, the
> + * guest expects a value in little endian format.
> + *
> + * We convert the data value from the CPUs native format to LE so that the
> + * value is returned in the proper format.
> + */
> +void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
> +				unsigned long data)
> +{
> +	switch (len) {
> +	case 1:
> +		break;
> +	case 2:
> +		data = cpu_to_le16(data);
> +		break;
> +	case 4:
> +		data = cpu_to_le32(data);
> +		break;
> +	default:
> +		data = cpu_to_le64(data);
> +	}
> +
> +	kvm_mmio_write_buf(buf, len, data);
> +}
> +
> +static
> +struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
> +{
> +	return container_of(dev, struct vgic_io_device, dev);
> +}
> +
> +static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
> +			      gpa_t addr, int len, void *val)
> +{
> +	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
> +	const struct vgic_register_region *region;
> +	struct kvm_vcpu *r_vcpu;
> +	unsigned long data;
> +
> +	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
> +				       addr - iodev->base_addr);
> +	if (!region)
> +		return -EOPNOTSUPP;
> +
> +	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
> +	data = region->read(r_vcpu, addr, len);
> +	vgic_data_host_to_mmio_bus(val, len, data);
> +	return 0;
> +}
> +
> +static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
> +			       gpa_t addr, int len, const void *val)
> +{
> +	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
> +	const struct vgic_register_region *region;
> +	struct kvm_vcpu *r_vcpu;
> +	unsigned long data = vgic_data_mmio_bus_to_host(val, len);
> +
> +	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
> +				       addr - iodev->base_addr);
> +	if (!region)
> +		return -EOPNOTSUPP;
> +
> +	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
> +	region->write(r_vcpu, addr, len, data);
> +	return 0;
> +}
> +
> +struct kvm_io_device_ops kvm_io_gic_ops = {
> +	.read = dispatch_mmio_read,
> +	.write = dispatch_mmio_write,
> +};
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> new file mode 100644
> index 0000000..18d3869
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -0,0 +1,77 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef __KVM_ARM_VGIC_MMIO_H__
> +#define __KVM_ARM_VGIC_MMIO_H__
> +
> +struct vgic_register_region {
> +	unsigned int reg_offset;
> +	unsigned int len;
> +	unsigned int bits_per_irq;
> +	unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr,
> +			      unsigned int len);
> +	void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
> +		      unsigned long val);
> +};
> +
> +extern struct kvm_io_device_ops kvm_io_gic_ops;
> +
> +/*
> + * Some VGIC registers store per-IRQ information, with a different number
> + * of bits per IRQ. For those registers this macro is used.
> + * The _WITH_LENGTH version instantiates registers with a fixed length
> + * and is mutually exclusive with the _PER_IRQ version.
> + */
> +#define REGISTER_DESC_WITH_BITS_PER_IRQ(off, read_ops, write_ops, bpi)	\
> +	{								\
> +		.reg_offset = off,					\
> +		.bits_per_irq = bpi,					\
> +		.len = bpi * 1024 / 8,					\
> +		.read = read_ops,					\
> +		.write = write_ops,					\
> +	}
> +
> +#define REGISTER_DESC_WITH_LENGTH(off, read_ops, write_ops, length)	\
> +	{								\
> +		.reg_offset = off,					\
> +		.bits_per_irq = 0,					\
> +		.len = length,						\
> +		.read = read_ops,					\
> +		.write = write_ops,					\
> +	}
> +
> +int kvm_vgic_register_mmio_region(struct kvm *kvm, struct kvm_vcpu *vcpu,
> +				  struct vgic_register_region *reg_desc,
> +				  struct vgic_io_device *region,
> +				  int nr_irqs, bool offset_private);
> +
> +unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len);
> +
> +void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
> +				unsigned long data);
> +
> +unsigned long extract_bytes(unsigned long data,
> +			    unsigned int offset, unsigned int num);
> +
> +unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
> +				 gpa_t addr, unsigned int len);
> +
> +unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
> +				 gpa_t addr, unsigned int len);
> +
> +void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> +			unsigned int len, unsigned long val);
> +
> +#endif
> -- 
> 2.7.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From khilman at baylibre.com  Wed May 11 02:48:39 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 11 May 2016 11:48:39 +0200
Subject: [PATCH 1/6] pinctrl: meson: Fix eth_tx_en bit index
In-Reply-To: <1462910920-5462-2-git-send-email-serveralex@gmail.com>
 ("Alexander =?utf-8?Q?M=C3=BCller=22's?= message of "Tue, 10 May 2016
 22:08:35 +0200")
References: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
 <1462910920-5462-2-git-send-email-serveralex@gmail.com>
Message-ID: <m2r3d97wnc.fsf@baylibre.com>

Alexander M?ller <serveralex at gmail.com> writes:

> Fix pinctrl eth_tx_en bit index according to Hardkernel ODROID-C1 datasheet.
>
> Signed-off-by: Alexander M?ller <serveralex at gmail.com>

Tested-by: Kevin Hilman <khilman at baylibre.com>

Linus, with your ack, we can take this through the amlogic tree, or feel
free to merge as a fix as it can go independetly of the rest of the
series if needed.

Kevin


From christoffer.dall at linaro.org  Wed May 11 02:50:21 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 11:50:21 +0200
Subject: [PATCH v3 22/55] KVM: arm/arm64: vgic-new: Add GICv2 MMIO
 handling framework
In-Reply-To: <1462531568-9799-23-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-23-git-send-email-andre.przywara@arm.com>
Message-ID: <20160511095021.GL27623@cbox>

On Fri, May 06, 2016 at 11:45:35AM +0100, Andre Przywara wrote:
> Create vgic-mmio-v2.c to describe GICv2 emulation specific handlers
> using the initializer macros provided by the VGIC MMIO framework.
> Provide a function to register the GICv2 distributor registers to
> the kvm_io_bus framework.
> The actual handler functions are still stubs in this patch.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
> Changelog v1 .. v2:
> - new patch, split out from the generic MMIO framework patch
> - use a separate file to hold GICv2 emulation specific handlers
> - replace _nyi stub functions with raz/wi versions
> 
> Changelog v2 .. v3:
> - replace kvm/vgic/vgic.h with kvm/arm_vgic.h
> - add vgic_register_dist_iodev() prototype
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.c    | 26 +++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h    |  2 ++
>  virt/kvm/arm/vgic/vgic.h         |  2 ++
>  4 files changed, 92 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v2.c
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> new file mode 100644
> index 0000000..2729a22
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -0,0 +1,62 @@
> +/*
> + * VGICv2 MMIO handling functions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/irqchip/arm-gic.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/iodev.h>
> +#include <kvm/arm_vgic.h>
> +
> +#include "vgic.h"
> +#include "vgic-mmio.h"
> +
> +static const struct vgic_register_region vgic_v2_dist_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 12),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 2),
> +	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
> +	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
> +};
> +
> +unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
> +{
> +	dev->regions = vgic_v2_dist_registers;
> +	dev->nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
> +
> +	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
> +
> +	return SZ_4K;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index f5628cb..41cf4f4 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -169,3 +169,29 @@ struct kvm_io_device_ops kvm_io_gic_ops = {
>  	.read = dispatch_mmio_read,
>  	.write = dispatch_mmio_write,
>  };
> +
> +int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
> +			     enum vgic_type type)
> +{
> +	struct vgic_io_device *io_device = &kvm->arch.vgic.dist_iodev;
> +	int ret = 0;
> +	unsigned int len;
> +
> +	switch (type) {
> +	case VGIC_V2:
> +		len = vgic_v2_init_dist_iodev(io_device);
> +		break;
> +	default:
> +		BUG_ON(1);
> +	}
> +
> +	io_device->base_addr = dist_base_address;
> +	io_device->redist_vcpu = NULL;
> +
> +	mutex_lock(&kvm->slots_lock);
> +	ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address,
> +				      len, &io_device->dev);
> +	mutex_unlock(&kvm->slots_lock);
> +
> +	return ret;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index 18d3869..4f4dd2b 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -74,4 +74,6 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
>  void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
>  			unsigned int len, unsigned long val);
>  
> +unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
> +
>  #endif
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 81b1a20..fd9acaa 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -27,6 +27,8 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
>  void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
>  void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
>  void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
> +int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
> +			     enum vgic_type);
>  
>  #ifdef CONFIG_KVM_ARM_VGIC_V3
>  void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
> -- 
> 2.7.3
> 

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From khilman at baylibre.com  Wed May 11 02:52:00 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 11 May 2016 11:52:00 +0200
Subject: [PATCH 0/6] Enable ethernet support on Amlogic meson8b /
 Hardkernel ODROID-C1
In-Reply-To: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
 ("Alexander =?utf-8?Q?M=C3=BCller=22's?= message of "Tue, 10 May 2016
 22:08:34 +0200")
References: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
Message-ID: <m2eg989b27.fsf@baylibre.com>

Alexander M?ller <serveralex at gmail.com> writes:

> This patch series fixes a glitch in the pinctrl driver, adds clock gates
> support and configures ethernet support via stmmac.
>
> The previously sent patch "pinctrl: meson: Fix eth_tx_en bit index" is
> also included in this patch series.

Tested-by: Kevin Hilman <khilman at baylibre.com>

I tested ethernet support on my odroidc1 with an NFS root and things are
working well.

Alexander, could you separate out the clock patches and (re)send them
making sure to copy the linux-clk list so the clock maintainers are sure
to see them?  Thanks.

Kevin

>
> Alexander M?ller (6):
>   pinctrl: meson: Fix eth_tx_en bit index
>   ARM: DTS: Amlogic: Add ethernet pins
>   ARM: clk: Amlogic: Add support for clock gates
>   ARM: clk: Amlogic: Add clk81 clock gates
>   ARM: DTS: Amlogic: Enable ethernet on meson8b
>   ARM: DTS: Amlogic: Enable ethernet on ODROID-C1
>
>  arch/arm/boot/dts/meson8b-odroidc1.dts   |  10 ++
>  arch/arm/boot/dts/meson8b.dtsi           |  25 ++++
>  drivers/clk/meson/clkc.c                 |  18 +++
>  drivers/clk/meson/clkc.h                 |  18 +++
>  drivers/clk/meson/meson8b-clkc.c         | 196 +++++++++++++++++++++++++++++++
>  drivers/pinctrl/meson/pinctrl-meson8b.c  |   2 +-
>  include/dt-bindings/clock/meson8b-clkc.h |  99 +++++++++++++++-
>  7 files changed, 365 insertions(+), 3 deletions(-)


From marc.zyngier at arm.com  Wed May 11 03:01:09 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 11 May 2016 11:01:09 +0100
Subject: [GIT PULL] irqchip updates for 4.7
Message-ID: <1462960869-27845-1-git-send-email-marc.zyngier@arm.com>

Hi Thomas,

This is the pull request for the irqchip updates targeting 4.7: A
couple of new drivers, quite a few cleanups two bug fixes and a
workaround for a Broadcom erratum. Jon's PM support has uncovered
another bug nest, so I'm holding it until this is properly solved.

A word of warning: there is some other GIC stuff queued through the
KVM/ARM tree (ACPI support) and the arm64 tree (feature detection
code), which are already in -next. I'm including the resolution at the
end of this email.

Thanks,

	M.

The following changes since commit 287e9357abcc0ef079bf4e439e098a3bd6246a05:

  DT/arm,gic-v3: Documment PPI partition support (2016-05-02 13:42:51 +0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git tags/irqchip-for-4.7

for you to fetch changes up to a1dcbd11d09be1cb357b2f217c0eaa1461128da0:

  irqchip/bcm2836: Use a more generic memory barrier call (2016-05-11 10:13:00 +0100)

----------------------------------------------------------------
irqchip updates for Linux 4.7

- Layerscape SCFG MSI controller support
- LPC32xx interrupt controller support
- RPi irqchip support on arm64
- GICv2 cleanup
- GICv2 and GICv3 bug fixes

----------------------------------------------------------------
Christoph Hellwig (1):
      irqchip/irq-alpine-msi: Don't use <asm-generic/msi.h>

Dan Carpenter (1):
      irqchip/mbigen: Checking for IS_ERR() instead of NULL

Eric Anholt (3):
      irqchip/bcm2836: Drop smp_set_ops on arm64 builds
      irqchip/bcm2836: Fix compiler warning on 64-bit build
      irqchip/bcm2836: Use a more generic memory barrier call

Jon Hunter (10):
      genirq: Ensure IRQ descriptor is valid when setting-up the IRQ
      irqchip: Mask the non-type/sense bits when translating an IRQ
      irqchip/gic: Don't unnecessarily write the IRQ configuration
      irqchip/gic: WARN if setting the interrupt type for a PPI fails
      irqchip/gic: Don't initialise chip if mapping IO space fails
      irqchip/gic: Remove static irq_chip definition for eoimode1
      irqchip/gic: Return an error if GIC initialisation fails
      irqchip/gic: Pass GIC pointer to save/restore functions
      irqchip/gic: Store GIC configuration parameters
      irqchip/gic: Add helper functions for GIC setup and teardown

Marc Zyngier (2):
      irqchip/gic-v3: Remove inexistant register definition
      irqchip/gic-v3: Configure all interrupts as non-secure Group-1

Minghuan Lian (2):
      dt/bindings: Add bindings for Layerscape SCFG MSI
      irqchip: Add Layerscape SCFG MSI controller support

Ray Jui (1):
      irqchip/gic-v2m: Add workaround for Broadcom NS2 GICv2m erratum

Shanker Donthineni (1):
      irqchip/gicv3-its: Don't allow devices whose ID is outside range

Vladimir Zapolskiy (1):
      irqchip: Add LPC32xx interrupt controller driver

Will Deacon (1):
      irqchip/gic: Ensure ordering between read of INTACK and shared data

 .../interrupt-controller/fsl,ls-scfg-msi.txt       |  30 ++
 arch/arm/Kconfig                                   |   2 +
 arch/arm/mach-lpc32xx/phy3250.c                    |   1 -
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   2 +
 drivers/irqchip/irq-alpine-msi.c                   |   2 +-
 drivers/irqchip/irq-bcm2836.c                      |  10 +-
 drivers/irqchip/irq-crossbar.c                     |   2 +-
 drivers/irqchip/irq-gic-common.c                   |  20 +-
 drivers/irqchip/irq-gic-v2m.c                      |  19 +-
 drivers/irqchip/irq-gic-v3-its.c                   |  42 ++-
 drivers/irqchip/irq-gic-v3.c                       |  19 ++
 drivers/irqchip/irq-gic.c                          | 322 +++++++++++++--------
 drivers/irqchip/irq-lpc32xx.c                      | 238 +++++++++++++++
 drivers/irqchip/irq-ls-scfg-msi.c                  | 240 +++++++++++++++
 drivers/irqchip/irq-mbigen.c                       |   4 +-
 drivers/irqchip/irq-tegra.c                        |   2 +-
 include/linux/irqchip/arm-gic-v3.h                 |   2 -
 kernel/irq/manage.c                                |   2 +-
 19 files changed, 827 insertions(+), 137 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
 create mode 100644 drivers/irqchip/irq-lpc32xx.c
 create mode 100644 drivers/irqchip/irq-ls-scfg-msi.c

diff --cc drivers/irqchip/Kconfig
index 81f88ad,2f115be..0000000
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@@ -246,10 -246,11 +246,16 @@@ config MVEBU_ODM
  	bool
  	select GENERIC_MSI_IRQ_DOMAIN
  
 +config LS_SCFG_MSI
 +	def_bool y if SOC_LS1021A || ARCH_LAYERSCAPE
 +	depends on PCI && PCI_MSI
 +	select PCI_MSI_IRQ_DOMAIN
 +
+ config EZNPS_GIC
+ 	bool "NPS400 Global Interrupt Manager (GIM)"
+ 	select IRQ_DOMAIN
+ 	help
+ 	  Support the EZchip NPS400 global interrupt controller
+ 
  config PARTITION_PERCPU
  	bool
diff --cc drivers/irqchip/Makefile
index f828244,f475986..0000000
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@@ -67,4 -66,4 +67,5 @@@ obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingen
  obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
  obj-$(CONFIG_PIC32_EVIC)		+= irq-pic32-evic.o
  obj-$(CONFIG_MVEBU_ODMI)		+= irq-mvebu-odmi.o
 +obj-$(CONFIG_LS_SCFG_MSI)		+= irq-ls-scfg-msi.o
+ obj-$(CONFIG_EZNPS_GIC)			+= irq-eznps.o
diff --cc drivers/irqchip/irq-gic.c
index 113e2d0,30d05a4..0000000
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@@ -486,9 -491,8 +488,10 @@@ static int gic_cpu_init(struct gic_chip
  		/*
  		 * Get what the GIC says our CPU mask is.
  		 */
 -		BUG_ON(cpu >= NR_GIC_CPU_IF);
 +		if (WARN_ON(cpu >= NR_GIC_CPU_IF))
 +			return -EINVAL;
 +
+ 		gic_check_cpu_features();
  		cpu_mask = gic_get_cpumask(gic);
  		gic_cpu_map[cpu] = cpu_mask;
  
@@@ -1029,28 -1014,24 +1032,26 @@@ static const struct irq_domain_ops gic_
  	.unmap = gic_irq_domain_unmap,
  };
  
 -static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
 -			   void __iomem *dist_base, void __iomem *cpu_base,
 -			   u32 percpu_offset, struct fwnode_handle *handle)
 +static int __init __gic_init_bases(struct gic_chip_data *gic, int irq_start,
 +				   struct fwnode_handle *handle)
  {
  	irq_hw_number_t hwirq_base;
 -	struct gic_chip_data *gic;
 -	int gic_irqs, irq_base, i;
 -
 -	BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
 +	int gic_irqs, irq_base, i, ret;
  
 -	gic = &gic_data[gic_nr];
 +	if (WARN_ON(!gic || gic->domain))
 +		return -EINVAL;
  
- 	gic_check_cpu_features();
- 
  	/* Initialize irq_chip */
 -	if (static_key_true(&supports_deactivate) && gic_nr == 0) {
 -		gic->chip = gic_eoimode1_chip;
 +	gic->chip = gic_chip;
 +
 +	if (static_key_true(&supports_deactivate) && gic == &gic_data[0]) {
 +		gic->chip.irq_mask = gic_eoimode1_mask_irq;
 +		gic->chip.irq_eoi = gic_eoimode1_eoi_irq;
 +		gic->chip.irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity;
 +		gic->chip.name = kasprintf(GFP_KERNEL, "GICv2");
  	} else {
 -		gic->chip = gic_chip;
 -		gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d", gic_nr);
 +		gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d",
 +					   (int)(gic - &gic_data[0]));
  	}
  
  #ifdef CONFIG_SMP
@@@ -1249,30 -1190,29 +1250,53 @@@ static bool gic_check_eoimode(struct de
  	return true;
  }
  
 +static int gic_of_setup(struct gic_chip_data *gic, struct device_node *node)
 +{
 +	if (!gic || !node)
 +		return -EINVAL;
 +
 +	gic->raw_dist_base = of_iomap(node, 0);
 +	if (WARN(!gic->raw_dist_base, "unable to map gic dist registers\n"))
 +		goto error;
 +
 +	gic->raw_cpu_base = of_iomap(node, 1);
 +	if (WARN(!gic->raw_cpu_base, "unable to map gic cpu registers\n"))
 +		goto error;
 +
 +	if (of_property_read_u32(node, "cpu-offset", &gic->percpu_offset))
 +		gic->percpu_offset = 0;
 +
 +	return 0;
 +
 +error:
 +	gic_teardown(gic);
 +
 +	return -ENOMEM;
 +}
 +
+ static void __init gic_of_setup_kvm_info(struct device_node *node)
+ {
+ 	int ret;
+ 	struct resource *vctrl_res = &gic_v2_kvm_info.vctrl;
+ 	struct resource *vcpu_res = &gic_v2_kvm_info.vcpu;
+ 
+ 	gic_v2_kvm_info.type = GIC_V2;
+ 
+ 	gic_v2_kvm_info.maint_irq = irq_of_parse_and_map(node, 0);
+ 	if (!gic_v2_kvm_info.maint_irq)
+ 		return;
+ 
+ 	ret = of_address_to_resource(node, 2, vctrl_res);
+ 	if (ret)
+ 		return;
+ 
+ 	ret = of_address_to_resource(node, 3, vcpu_res);
+ 	if (ret)
+ 		return;
+ 
+ 	gic_set_kvm_info(&gic_v2_kvm_info);
+ }
+ 
  int __init
  gic_of_init(struct device_node *node, struct device_node *parent)
  {
@@@ -1295,17 -1234,18 +1319,19 @@@
  	 * Disable split EOI/Deactivate if either HYP is not available
  	 * or the CPU interface is too small.
  	 */
 -	if (gic_cnt == 0 && !gic_check_eoimode(node, &cpu_base))
 +	if (gic_cnt == 0 && !gic_check_eoimode(node, &gic->raw_cpu_base))
  		static_key_slow_dec(&supports_deactivate);
  
 -	if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
 -		percpu_offset = 0;
 +	ret = __gic_init_bases(gic, -1, &node->fwnode);
 +	if (ret) {
 +		gic_teardown(gic);
 +		return ret;
 +	}
  
- 	if (!gic_cnt)
 -	__gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset,
 -			 &node->fwnode);
+ 	if (!gic_cnt) {
  		gic_init_physaddr(node);
+ 		gic_of_setup_kvm_info(node);
+ 	}
  
  	if (parent) {
  		irq = irq_of_parse_and_map(node, 0);
@@@ -1402,8 -1390,8 +1476,8 @@@ static int __init gic_v2_acpi_init(stru
  		return -EINVAL;
  	}
  
- 	gic->raw_cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
 -	cpu_base = ioremap(acpi_data.cpu_phys_base, ACPI_GIC_CPU_IF_MEM_SIZE);
 -	if (!cpu_base) {
++	gic->raw_cpu_base = ioremap(acpi_data.cpu_phys_base, ACPI_GIC_CPU_IF_MEM_SIZE);
 +	if (!gic->raw_cpu_base) {
  		pr_err("Unable to map GICC registers\n");
  		return -ENOMEM;
  	}


From jesper.nilsson at axis.com  Wed May 11 03:06:01 2016
From: jesper.nilsson at axis.com (Jesper Nilsson)
Date: Wed, 11 May 2016 12:06:01 +0200
Subject: [patch V4 02/31] bitops: Include generic parity.h in some
 architectures' bitops.h
In-Reply-To: <1462957641-24241-1-git-send-email-zengzhaoxiu@163.com>
References: <1462955158-28394-1-git-send-email-zengzhaoxiu@163.com>
 <1462957641-24241-1-git-send-email-zengzhaoxiu@163.com>
Message-ID: <20160511100601.GY24250@axis.com>

On Wed, May 11, 2016 at 05:06:17PM +0800, zengzhaoxiu at 163.com wrote:
> From: Zhaoxiu Zeng <zhaoxiu.zeng at gmail.com>
> 
> Simply use the generic version.
> 
> Signed-off-by: Zhaoxiu Zeng <zhaoxiu.zeng at gmail.com>
> Acked-by: Hans-Christian Noren Egtvedt <egtvedt at samfundet.no> [for avr32]

For the CRIS part:

Acked-by: Jesper Nilsson <jesper.nilsson at axis.com>

/^JN - Jesper Nilsson
-- 
               Jesper Nilsson -- jesper.nilsson at axis.com


From lorenzo.pieralisi at arm.com  Wed May 11 03:11:01 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Wed, 11 May 2016 11:11:01 +0100
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
 <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>
Message-ID: <20160511101101.GA16101@red-moon>

On Tue, May 10, 2016 at 08:37:00PM +0200, Rafael J. Wysocki wrote:
> On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> > This patch provides a way to set the ACPI companion in PCI code.
> > We define acpi_pci_set_companion() to set the ACPI companion pointer and
> > call it from PCI core code. The function is stub for now.
> >
> > Signed-off-by: Jayachandran C <jchandra at broadcom.com>
> > Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> > ---
> >  drivers/pci/probe.c      | 2 ++
> >  include/linux/pci-acpi.h | 4 ++++
> >  2 files changed, 6 insertions(+)
> >
> > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> > index 8004f67..fb0b752 100644
> > --- a/drivers/pci/probe.c
> > +++ b/drivers/pci/probe.c
> > @@ -12,6 +12,7 @@
> >  #include <linux/slab.h>
> >  #include <linux/module.h>
> >  #include <linux/cpumask.h>
> > +#include <linux/pci-acpi.h>
> >  #include <linux/pci-aspm.h>
> >  #include <linux/aer.h>
> >  #include <linux/acpi.h>
> > @@ -2141,6 +2142,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
> >         bridge->dev.parent = parent;
> >         bridge->dev.release = pci_release_host_bridge_dev;
> >         dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
> > +       acpi_pci_set_companion(bridge);
> 
> Yes, we'll probably add something similar here.
> 
> Do I think now is the right time to do that?  No.
> 
> >         error = pcibios_root_bridge_prepare(bridge);
> >         if (error) {
> >                 kfree(bridge);
> > diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
> > index 09f9f02..1baa515 100644
> > --- a/include/linux/pci-acpi.h
> > +++ b/include/linux/pci-acpi.h
> > @@ -111,6 +111,10 @@ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
> >  static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
> >  #endif /* CONFIG_ACPI */
> >
> > +static inline void acpi_pci_set_companion(struct pci_host_bridge *bridge)
> > +{
> > +}
> > +
> >  static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus)
> >  {
> >         return 0;
> > --
> 
> Honestly, to me it looks like this series is trying very hard to avoid
> doing any PCI host bridge configuration stuff from arch/arm64/
> although (a) that might be simpler and (b) it would allow us to
> identify the code that's common between *all* architectures using ACPI
> support for host bridge configuration and to move *that* to a common
> place later.  As done here it seems to be following the "ARM64 is
> generic and the rest of the world is special" line which isn't really
> helpful.

I think patch [1-2] should be merged regardless (they may require minor
tweaks if we decide to move pci_acpi_scan_root() to arch/arm64 though,
for include files location). I guess you are referring to patch 8 in
your comments above, which boils down to deciding whether:

- pci_acpi_scan_root() (and unfortunately all the MCFG/ECAM handling that
  goes with it) should live in arch/arm64 or drivers/acpi

acpi_pci_bus_domain_nr() is a bit more problematic since it is meant
to be called from PCI core code (ARM64 selects PCI_DOMAINS_GENERIC for
DT and same kernel has to work with OF and ACPI selected) and it is
arch specific (because what we have in bus->sysdata is arch specific,
waiting for the domain number to be embedded in struct pci_host_bridge).

Your point is fair, I am not sure that moving the pci_acpi_scan_root()
to arch/arm64 would make things much simpler though, it is just a matter
of deciding where that code has to live.

How do you want us to proceed ?

Thanks,
Lorenzo


From nicolas.ferre at atmel.com  Wed May 11 03:11:56 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Wed, 11 May 2016 12:11:56 +0200
Subject: [PATCH] ARM: dts: at91: sam9x5: Fix the memory range assigned to
 the PMC
In-Reply-To: <1462957202-22671-1-git-send-email-boris.brezillon@free-electrons.com>
References: <1462957202-22671-1-git-send-email-boris.brezillon@free-electrons.com>
Message-ID: <5733056C.9000100@atmel.com>

Le 11/05/2016 11:00, Boris Brezillon a ?crit :
> The memory range assigned to the PMC (Power Management Controller) was
> not including the PMC_PCR register which are used to control peripheral
> clocks.
> 
> This was working fine thanks to the page granularity of ioremap(), but
> started to fail when we switched to syscon/regmap, because regmap is
> making sure that all accesses are falling into the reserved range.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> Reported-by: Richard Genoud <richard.genoud at gmail.com>
> Tested-by: Richard Genoud <richard.genoud at gmail.com>
> Fixes: 863a81c3be1d ("clk: at91: make use of syscon to share PMC registers in several drivers")
> Cc: <stable at vger.kernel.org>

Acked-by: Nicolas Ferre <nicolas.ferre at atmel.com>

Thanks Boris!


> ---
> Hi Arnd,
> 
> This patch is fixing a regression reported by Richard. Since this
> regression was introduced in 4.6-rc1 it would be great if you could
> take it before 4.6 is released.

Arnd, arm-soc guys,

I can build a Pull-Request instantly today, if you wish: just tell me if
you prefer.

Bye,

> ---
>  arch/arm/boot/dts/at91sam9x5.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
> index 0827d59..cd0cd5f 100644
> --- a/arch/arm/boot/dts/at91sam9x5.dtsi
> +++ b/arch/arm/boot/dts/at91sam9x5.dtsi
> @@ -106,7 +106,7 @@
>  
>  			pmc: pmc at fffffc00 {
>  				compatible = "atmel,at91sam9x5-pmc", "syscon";
> -				reg = <0xfffffc00 0x100>;
> +				reg = <0xfffffc00 0x200>;
>  				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
>  				interrupt-controller;
>  				#address-cells = <1>;
> 


-- 
Nicolas Ferre


From boris.brezillon at free-electrons.com  Wed May 11 03:13:06 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Wed, 11 May 2016 12:13:06 +0200
Subject: [PATCH v8 0/2] memory: add Atmel EBI (External Bus Interface) driver
Message-ID: <1462961588-23004-1-git-send-email-boris.brezillon@free-electrons.com>

The EBI (External Bus Interface) is used to access external peripherals
(NOR, SRAM, NAND, and other specific devices like ethernet controllers).
Each device is assigned a CS line and an address range and can have its
own configuration (timings, access mode, bus width, ...).
This driver provides a generic DT binding to configure a device according
to its requirements.
For specific device controllers (like the NAND one) the SMC timings
should be configured by the controller driver through the matrix and
smc syscon regmaps.

Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>

Changes since v7:
- move EBI bus config properties directly in the sub-device node
- prefix all EBI/SMC properties with atmel,smc-
- rework the driver to take the new binding into account
- disable the subdevice when EBI implementation fails to configure
  the bus as requested

Changes since v6:
- rework the binding to put per-device config information into a
  separate subnode and have devices connected to the EBI bus
  defined as direct children of the EBI node
- make all EBI timings mandatory
- keep adding sub-devices when a failure occurs on one of them

Changes since v5:
- remove the "atmel,specialized-logic" property: now all devices are
  are attached to the SMC logic by default, and specialized drivers
  (like the NAND controller one), should change this configuration
  manually.
- provide hardware readout to allow partial config description.
  This is mainly here to keep existing platforms (where everything
  is configured by the bootloader/bootstrap) in working state.
- rename "atmel,tdf-optimized" into "atmel,tdf-mode" and switch from
  a boolean to string property to properly support partial config

Changes since v4:
- fix inconsistencies in SMC and MATRIX registers definition
- add missing compatible strings for at91sam9rl SoC
- fix DT bindings documentation
- replace "atmel,generic-dev" property by "atmel,specialized-logic"

Changes since v3:
- added AT91_MATRIX_USBPUCR_PUON definition
- removed useless macros (those directly returning SoC specific register
  offsets)
- use syscon_regmap_lookup_by_phandle instead of of_parse_phandle +
  syscon_node_to_regmap
- drop AT91_EBICSA_REGFIELD and AT91_MULTI_EBICSA_REGFIELD macros

Changes since v2:
- minor fixes int DT bindings doc
- fix SMC macros
- make use of SMC macros defined in include/linux/mfd/syscon/atmel-smc.h

Changes since v1:
- almost everything :-)

Boris Brezillon (2):
  memory: add Atmel EBI (External Bus Interface) driver
  memory: atmel-ebi: add DT bindings documentation

 .../bindings/memory-controllers/atmel,ebi.txt      | 136 ++++
 drivers/memory/Kconfig                             |  11 +
 drivers/memory/Makefile                            |   1 +
 drivers/memory/atmel-ebi.c                         | 771 +++++++++++++++++++++
 4 files changed, 919 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
 create mode 100644 drivers/memory/atmel-ebi.c

-- 
2.7.4



From boris.brezillon at free-electrons.com  Wed May 11 03:13:08 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Wed, 11 May 2016 12:13:08 +0200
Subject: [PATCH v8 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <1462961588-23004-1-git-send-email-boris.brezillon@free-electrons.com>
References: <1462961588-23004-1-git-send-email-boris.brezillon@free-electrons.com>
Message-ID: <1462961588-23004-3-git-send-email-boris.brezillon@free-electrons.com>

The EBI (External Bus Interface) is used to access external peripherals
(NOR, SRAM, NAND, and other specific devices like ethernet controllers).
Each device is assigned a CS line and an address range and can have its
own configuration (timings, access mode, bus width, ...).
This driver provides a generic DT binding to configure a device according
to its requirements.
For specific device controllers (like the NAND one) the SMC timings
should be configured by the controller driver through the matrix and smc
syscon regmaps.

Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
---
 .../bindings/memory-controllers/atmel,ebi.txt      | 136 +++++++++++++++++++++
 1 file changed, 136 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt

diff --git a/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
new file mode 100644
index 0000000..2fe9b5b
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
@@ -0,0 +1,136 @@
+* Device tree bindings for Atmel EBI
+
+The External Bus Interface (EBI) controller is a bus where you can connect
+asynchronous (NAND, NOR, SRAM, ....) and synchronous memories (SDR/DDR SDRAMs).
+The EBI provides a glue-less interface to asynchronous memories through the SMC
+(Static Memory Controller).
+
+Required properties:
+
+- compatible:		"atmel,at91sam9260-ebi"
+			"atmel,at91sam9261-ebi"
+			"atmel,at91sam9263-ebi0"
+			"atmel,at91sam9263-ebi1"
+			"atmel,at91sam9rl-ebi"
+			"atmel,at91sam9g45-ebi"
+			"atmel,at91sam9x5-ebi"
+			"atmel,sama5d3-ebi"
+
+- reg:			Contains offset/length value for EBI memory mapping.
+			This property might contain several entries if the EBI
+			memory range is not contiguous
+
+- #address-cells:	Must be 2.
+			The first cell encodes the CS.
+			The second cell encode the offset into the CS memory
+			range.
+
+- #size-cells:		Must be set to 1.
+
+- ranges:		Encodes CS to memory region association.
+
+- clocks:		Clock feeding the EBI controller.
+			See clock-bindings.txt
+
+Children device nodes are representing device connected to the EBI bus.
+
+Required device node properties:
+
+- #reg:			Contains the chip-select id, the offset and the length
+			of the memory region requested by the device.
+
+EBI bus configuration will be defined directly in the device subnode.
+
+Optional EBI/SMC properties:
+
+- atmel,smc-bus-width:		width of the asynchronous device's data bus
+				8, 16 or 32.
+				Default to 8 when undefined.
+
+- atmel,smc-byte-access-type	"write" or "select" (see Atmel datasheet).
+				Default to "select" when undefined.
+
+- atmel,smc-read-mode		"nrd" or "ncs".
+				Default to "ncs" when undefined.
+
+- atmel,smc-write-mode		"nwe" or "ncs".
+				Default to "ncs" when undefined.
+
+- atmel,smc-exnw-mode		"disabled", "frozen" or "ready".
+				Default to "disabled" when undefined.
+
+- atmel,smc-page-mode		enable page mode if present. The provided value
+				defines the page size (supported values: 4, 8,
+				16 and 32).
+
+- atmel,smc-tdf-mode:		"normal" or "optimized". When set to
+				"optimized" the data float time is optimized
+				depending on the next device being accessed
+				(next device setup time is subtracted to the
+				current device data float time).
+				Default to "normal" when undefined.
+
+If at least one atmel,smc- property is defined the following SMC timing
+properties become mandatory. In the other hand, if none of the atmel,smc-
+properties are specified, we assume that the EBI bus configuration will be
+handled by the sub-device driver, and none of those properties should be
+defined.
+
+All the timings are expressed in nanoseconds (see Atmel datasheet for a full
+description).
+
+- atmel,smc-ncs-rd-setup-ns
+- atmel,smc-nrd-setup-ns
+- atmel,smc-ncs-wr-setup-ns
+- atmel,smc-nwe-setup-ns
+- atmel,smc-ncs-rd-pulse-ns
+- atmel,smc-nrd-pulse-ns
+- atmel,smc-ncs-wr-pulse-ns
+- atmel,smc-nwe-pulse-ns
+- atmel,smc-nwe-cycle-ns
+- atmel,smc-nrd-cycle-ns
+- atmel,smc-tdf-ns
+
+Example:
+
+	ebi: ebi at 10000000 {
+		compatible = "atmel,sama5d3-ebi";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		atmel,smc = <&hsmc>;
+		atmel,matrix = <&matrix>;
+		reg = <0x10000000 0x10000000
+		       0x40000000 0x30000000>;
+		ranges = <0x0 0x0 0x10000000 0x10000000
+			  0x1 0x0 0x40000000 0x10000000
+			  0x2 0x0 0x50000000 0x10000000
+			  0x3 0x0 0x60000000 0x10000000>;
+		clocks = <&mck>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_ebi_addr>;
+
+		nor: flash at 0,0 {
+			compatible = "cfi-flash";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0x0 0x1000000>;
+			bank-width = <2>;
+
+			atmel,smc-read-mode = "nrd";
+			atmel,smc-write-mode = "nwe";
+			atmel,smc-bus-width = <16>;
+			atmel,smc-ncs-rd-setup-ns = <0>;
+			atmel,smc-ncs-wr-setup-ns = <0>;
+			atmel,smc-nwe-setup-ns = <8>;
+			atmel,smc-nrd-setup-ns = <16>;
+			atmel,smc-ncs-rd-pulse-ns = <84>;
+			atmel,smc-ncs-wr-pulse-ns = <84>;
+			atmel,smc-nrd-pulse-ns = <76>;
+			atmel,smc-nwe-pulse-ns = <76>;
+			atmel,smc-nrd-cycle-ns = <107>;
+			atmel,smc-nwe-cycle-ns = <84>;
+			atmel,smc-tdf-ns = <16>;
+		};
+	};
+
-- 
2.7.4



From boris.brezillon at free-electrons.com  Wed May 11 03:13:07 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Wed, 11 May 2016 12:13:07 +0200
Subject: [PATCH v8 1/2] memory: add Atmel EBI (External Bus Interface) driver
In-Reply-To: <1462961588-23004-1-git-send-email-boris.brezillon@free-electrons.com>
References: <1462961588-23004-1-git-send-email-boris.brezillon@free-electrons.com>
Message-ID: <1462961588-23004-2-git-send-email-boris.brezillon@free-electrons.com>

The EBI (External Bus Interface) is used to access external peripherals
(NOR, SRAM, NAND, and other specific devices like ethernet controllers).
Each device is assigned a CS line and an address range and can have its
own configuration (timings, access mode, bus width, ...).
This driver provides a generic DT binding to configure a device according
to its requirements.
For specific device controllers (like the NAND one) the SMC timings
should be configured by the controller driver through the matrix and
smc syscon regmaps.

Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
---
 drivers/memory/Kconfig     |  11 +
 drivers/memory/Makefile    |   1 +
 drivers/memory/atmel-ebi.c | 771 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 783 insertions(+)
 create mode 100644 drivers/memory/atmel-ebi.c

diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 51d5cd2..4780136 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -25,6 +25,17 @@ config ATMEL_SDRAMC
 	  Starting with the at91sam9g45, this controller supports SDR, DDR and
 	  LP-DDR memories.
 
+config ATMEL_EBI
+	bool "Atmel EBI driver"
+	default y
+	depends on ARCH_AT91 && OF
+	select MFD_SYSCON
+	help
+	  Driver for Atmel EBI controller.
+	  Used to configure the EBI (external bus interface) when the device-
+	  tree is used. This bus supports NANDs, external ethernet controller,
+	  SRAMs, ATA devices, etc.
+
 config TI_AEMIF
 	tristate "Texas Instruments AEMIF driver"
 	depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 890bdf4..965da6b 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_OF)		+= of_memory.o
 endif
 obj-$(CONFIG_ARM_PL172_MPMC)	+= pl172.o
 obj-$(CONFIG_ATMEL_SDRAMC)	+= atmel-sdramc.o
+obj-$(CONFIG_ATMEL_EBI)		+= atmel-ebi.o
 obj-$(CONFIG_TI_AEMIF)		+= ti-aemif.o
 obj-$(CONFIG_TI_EMIF)		+= emif.o
 obj-$(CONFIG_OMAP_GPMC)		+= omap-gpmc.o
diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c
new file mode 100644
index 0000000..712c767
--- /dev/null
+++ b/drivers/memory/atmel-ebi.c
@@ -0,0 +1,771 @@
+/*
+ * EBI driver for Atmel chips
+ * inspired by the fsl weim bus driver
+ *
+ * Copyright (C) 2013 JJ Hiblot.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/atmel-matrix.h>
+#include <linux/mfd/syscon/atmel-smc.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+struct at91sam9_smc_timings {
+	u32 ncs_rd_setup_ns;
+	u32 nrd_setup_ns;
+	u32 ncs_wr_setup_ns;
+	u32 nwe_setup_ns;
+	u32 ncs_rd_pulse_ns;
+	u32 nrd_pulse_ns;
+	u32 ncs_wr_pulse_ns;
+	u32 nwe_pulse_ns;
+	u32 nrd_cycle_ns;
+	u32 nwe_cycle_ns;
+	u32 tdf_ns;
+};
+
+struct at91sam9_smc_generic_fields {
+	struct regmap_field *setup;
+	struct regmap_field *pulse;
+	struct regmap_field *cycle;
+	struct regmap_field *mode;
+};
+
+struct at91sam9_ebi_dev_config {
+	struct at91sam9_smc_timings timings;
+	u32 mode;
+};
+
+struct at91_ebi_dev_config {
+	int cs;
+	union {
+		struct at91sam9_ebi_dev_config sam9;
+	};
+};
+
+struct at91_ebi;
+
+struct at91_ebi_dev {
+	struct list_head node;
+	struct at91_ebi *ebi;
+	u32 mode;
+	int numcs;
+	struct at91_ebi_dev_config configs[];
+};
+
+struct at91_ebi_caps {
+	unsigned int available_cs;
+	const struct reg_field *ebi_csa;
+	void (*get_config)(struct at91_ebi_dev *ebid,
+			   struct at91_ebi_dev_config *conf);
+	int (*xlate_config)(struct at91_ebi_dev *ebid,
+			    struct device_node *configs_np,
+			    struct at91_ebi_dev_config *conf);
+	int (*apply_config)(struct at91_ebi_dev *ebid,
+			    struct at91_ebi_dev_config *conf);
+	int (*init)(struct at91_ebi *ebi);
+};
+
+struct at91_ebi {
+	struct clk *clk;
+	struct regmap *smc;
+	struct regmap *matrix;
+
+	struct regmap_field *ebi_csa;
+
+	struct device *dev;
+	const struct at91_ebi_caps *caps;
+	struct list_head devs;
+	union {
+		struct at91sam9_smc_generic_fields sam9;
+	};
+};
+
+static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid,
+				    struct at91_ebi_dev_config *conf)
+{
+	struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9;
+	unsigned int clk_rate = clk_get_rate(ebid->ebi->clk);
+	struct at91sam9_ebi_dev_config *config = &conf->sam9;
+	struct at91sam9_smc_timings *timings = &config->timings;
+	unsigned int val;
+
+	regmap_fields_read(fields->mode, conf->cs, &val);
+	config->mode = val & ~AT91_SMC_TDF;
+
+	val = (val & AT91_SMC_TDF) >> 16;
+	timings->tdf_ns = clk_rate * val;
+
+	regmap_fields_read(fields->setup, conf->cs, &val);
+	timings->ncs_rd_setup_ns = (val >> 24) & 0x1f;
+	timings->ncs_rd_setup_ns += ((val >> 29) & 0x1) * 128;
+	timings->ncs_rd_setup_ns *= clk_rate;
+	timings->nrd_setup_ns = (val >> 16) & 0x1f;
+	timings->nrd_setup_ns += ((val >> 21) & 0x1) * 128;
+	timings->nrd_setup_ns *= clk_rate;
+	timings->ncs_wr_setup_ns = (val >> 8) & 0x1f;
+	timings->ncs_wr_setup_ns += ((val >> 13) & 0x1) * 128;
+	timings->ncs_wr_setup_ns *= clk_rate;
+	timings->nwe_setup_ns = val & 0x1f;
+	timings->nwe_setup_ns += ((val >> 5) & 0x1) * 128;
+	timings->nwe_setup_ns *= clk_rate;
+
+	regmap_fields_read(fields->pulse, conf->cs, &val);
+	timings->ncs_rd_pulse_ns = (val >> 24) & 0x3f;
+	timings->ncs_rd_pulse_ns += ((val >> 30) & 0x1) * 256;
+	timings->ncs_rd_pulse_ns *= clk_rate;
+	timings->nrd_pulse_ns = (val >> 16) & 0x3f;
+	timings->nrd_pulse_ns += ((val >> 22) & 0x1) * 256;
+	timings->nrd_pulse_ns *= clk_rate;
+	timings->ncs_wr_pulse_ns = (val >> 8) & 0x3f;
+	timings->ncs_wr_pulse_ns += ((val >> 14) & 0x1) * 256;
+	timings->ncs_wr_pulse_ns *= clk_rate;
+	timings->nwe_pulse_ns = val & 0x3f;
+	timings->nwe_pulse_ns += ((val >> 6) & 0x1) * 256;
+	timings->nwe_pulse_ns *= clk_rate;
+
+	regmap_fields_read(fields->cycle, conf->cs, &val);
+	timings->nrd_cycle_ns = (val >> 16) & 0x7f;
+	timings->nrd_cycle_ns += ((val >> 23) & 0x3) * 256;
+	timings->nrd_cycle_ns *= clk_rate;
+	timings->nwe_cycle_ns = val & 0x7f;
+	timings->nwe_cycle_ns += ((val >> 7) & 0x3) * 256;
+	timings->nwe_cycle_ns *= clk_rate;
+}
+
+static int at91_xlate_timing(struct device_node *np, const char *prop,
+			     u32 *val, bool *required)
+{
+	if (!of_property_read_u32(np, prop, val)) {
+		*required = true;
+		return 0;
+	}
+
+	if (*required)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int at91sam9_smc_xslate_timings(struct at91_ebi_dev *ebid,
+				       struct device_node *np,
+				       struct at91sam9_smc_timings *timings,
+				       bool *required)
+{
+	int ret;
+
+	ret = at91_xlate_timing(np, "atmel,smc-ncs-rd-setup-ns",
+				&timings->ncs_rd_setup_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-nrd-setup-ns",
+				&timings->nrd_setup_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-ncs-wr-setup-ns",
+				&timings->ncs_wr_setup_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-nwe-setup-ns",
+				&timings->nwe_setup_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-ncs-rd-pulse-ns",
+				&timings->ncs_rd_pulse_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-nrd-pulse-ns",
+				&timings->nrd_pulse_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-ncs-wr-pulse-ns",
+				&timings->ncs_wr_pulse_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-nwe-pulse-ns",
+				&timings->nwe_pulse_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-nwe-cycle-ns",
+				&timings->nwe_cycle_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-nrd-cycle-ns",
+				&timings->nrd_cycle_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-tdf-ns",
+				&timings->tdf_ns, required);
+
+out:
+	if (ret)
+		dev_err(ebid->ebi->dev,
+			"missing or invalid timings definition in %s",
+			np->full_name);
+
+	return ret;
+}
+
+static int at91sam9_ebi_xslate_config(struct at91_ebi_dev *ebid,
+				      struct device_node *np,
+				      struct at91_ebi_dev_config *conf)
+{
+	struct at91sam9_ebi_dev_config *config = &conf->sam9;
+	bool required = false;
+	const char *tmp_str;
+	u32 tmp;
+	int ret;
+
+	ret = of_property_read_u32(np, "atmel,smc-bus-width", &tmp);
+	if (!ret) {
+		switch (tmp) {
+		case 8:
+			config->mode |= AT91_SMC_DBW_8;
+			break;
+
+		case 16:
+			config->mode |= AT91_SMC_DBW_16;
+			break;
+
+		case 32:
+			config->mode |= AT91_SMC_DBW_32;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		required = true;
+	}
+
+	if (of_property_read_bool(np, "atmel,smc-tdf-optimized")) {
+		config->mode |= AT91_SMC_TDFMODE_OPTIMIZED;
+		required = true;
+	}
+
+	tmp_str = NULL;
+	of_property_read_string(np, "atmel,smc-byte-access-type", &tmp_str);
+	if (tmp_str && !strcmp(tmp_str, "write")) {
+		config->mode |= AT91_SMC_BAT_WRITE;
+		required = true;
+	}
+
+	tmp_str = NULL;
+	of_property_read_string(np, "atmel,smc-read-mode", &tmp_str);
+	if (tmp_str && !strcmp(tmp_str, "nrd")) {
+		config->mode |= AT91_SMC_READMODE_NRD;
+		required = true;
+	}
+
+	tmp_str = NULL;
+	of_property_read_string(np, "atmel,smc-write-mode", &tmp_str);
+	if (tmp_str && !strcmp(tmp_str, "nwe")) {
+		config->mode |= AT91_SMC_WRITEMODE_NWE;
+		required = true;
+	}
+
+	tmp_str = NULL;
+	of_property_read_string(np, "atmel,smc-exnw-mode", &tmp_str);
+	if (tmp_str) {
+		if (!strcmp(tmp_str, "frozen"))
+			config->mode |= AT91_SMC_EXNWMODE_FROZEN;
+		else if (!strcmp(tmp_str, "ready"))
+			config->mode |= AT91_SMC_EXNWMODE_READY;
+		else if (strcmp(tmp_str, "disabled"))
+			return -EINVAL;
+
+		required = true;
+	}
+
+	ret = of_property_read_u32(np, "atmel,smc-page-mode", &tmp);
+	if (!ret) {
+		switch (tmp) {
+		case 4:
+			config->mode |= AT91_SMC_PS_4;
+			break;
+
+		case 8:
+			config->mode |= AT91_SMC_PS_8;
+			break;
+
+		case 16:
+			config->mode |= AT91_SMC_PS_16;
+			break;
+
+		case 32:
+			config->mode |= AT91_SMC_PS_32;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		config->mode |= AT91_SMC_PMEN;
+		required = true;
+	}
+
+	ret = at91sam9_smc_xslate_timings(ebid, np, &config->timings,
+					  &required);
+	if (ret)
+		return ret;
+
+	return required;
+}
+
+static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid,
+				     struct at91_ebi_dev_config *conf)
+{
+	unsigned int clk_rate = clk_get_rate(ebid->ebi->clk);
+	struct at91sam9_ebi_dev_config *config = &conf->sam9;
+	struct at91sam9_smc_timings *timings = &config->timings;
+	struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9;
+	u32 coded_val;
+	u32 val;
+
+	coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
+						    timings->ncs_rd_setup_ns);
+	val = AT91SAM9_SMC_NCS_NRDSETUP(coded_val);
+	coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
+						    timings->nrd_setup_ns);
+	val |= AT91SAM9_SMC_NRDSETUP(coded_val);
+	coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
+						    timings->ncs_wr_setup_ns);
+	val |= AT91SAM9_SMC_NCS_WRSETUP(coded_val);
+	coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
+						    timings->nwe_setup_ns);
+	val |= AT91SAM9_SMC_NWESETUP(coded_val);
+	regmap_fields_write(fields->setup, conf->cs, val);
+
+	coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
+						    timings->ncs_rd_pulse_ns);
+	val = AT91SAM9_SMC_NCS_NRDPULSE(coded_val);
+	coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
+						    timings->nrd_pulse_ns);
+	val |= AT91SAM9_SMC_NRDPULSE(coded_val);
+	coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
+						    timings->ncs_wr_pulse_ns);
+	val |= AT91SAM9_SMC_NCS_WRPULSE(coded_val);
+	coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
+						    timings->nwe_pulse_ns);
+	val |= AT91SAM9_SMC_NWEPULSE(coded_val);
+	regmap_fields_write(fields->pulse, conf->cs, val);
+
+	coded_val = at91sam9_smc_cycle_ns_to_cycles(clk_rate,
+						    timings->nrd_cycle_ns);
+	val = AT91SAM9_SMC_NRDCYCLE(coded_val);
+	coded_val = at91sam9_smc_cycle_ns_to_cycles(clk_rate,
+						    timings->nwe_cycle_ns);
+	val |= AT91SAM9_SMC_NWECYCLE(coded_val);
+	regmap_fields_write(fields->cycle, conf->cs, val);
+
+	val = DIV_ROUND_UP(timings->tdf_ns, clk_rate);
+	if (val > AT91_SMC_TDF_MAX)
+		val = AT91_SMC_TDF_MAX;
+	regmap_fields_write(fields->mode, conf->cs,
+			    config->mode | AT91_SMC_TDF_(val));
+
+	return 0;
+}
+
+static int at91sam9_ebi_init(struct at91_ebi *ebi)
+{
+	struct at91sam9_smc_generic_fields *fields = &ebi->sam9;
+	struct reg_field field = REG_FIELD(0, 0, 31);
+
+	field.id_size = fls(ebi->caps->available_cs);
+	field.id_offset = AT91SAM9_SMC_GENERIC_BLK_SZ;
+
+	field.reg = AT91SAM9_SMC_SETUP(AT91SAM9_SMC_GENERIC);
+	fields->setup = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->setup))
+		return PTR_ERR(fields->setup);
+
+	field.reg = AT91SAM9_SMC_PULSE(AT91SAM9_SMC_GENERIC);
+	fields->pulse = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->pulse))
+		return PTR_ERR(fields->pulse);
+
+	field.reg = AT91SAM9_SMC_CYCLE(AT91SAM9_SMC_GENERIC);
+	fields->cycle = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->cycle))
+		return PTR_ERR(fields->cycle);
+
+	field.reg = AT91SAM9_SMC_MODE(AT91SAM9_SMC_GENERIC);
+	fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->mode))
+		return PTR_ERR(fields->mode);
+
+	return 0;
+}
+
+static int sama5d3_ebi_init(struct at91_ebi *ebi)
+{
+	struct at91sam9_smc_generic_fields *fields = &ebi->sam9;
+	struct reg_field field = REG_FIELD(0, 0, 31);
+
+	field.id_size = fls(ebi->caps->available_cs);
+	field.id_offset = SAMA5_SMC_GENERIC_BLK_SZ;
+
+	field.reg = AT91SAM9_SMC_SETUP(SAMA5_SMC_GENERIC);
+	fields->setup = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->setup))
+		return PTR_ERR(fields->setup);
+
+	field.reg = AT91SAM9_SMC_PULSE(SAMA5_SMC_GENERIC);
+	fields->pulse = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->pulse))
+		return PTR_ERR(fields->pulse);
+
+	field.reg = AT91SAM9_SMC_CYCLE(SAMA5_SMC_GENERIC);
+	fields->cycle = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->cycle))
+		return PTR_ERR(fields->cycle);
+
+	field.reg = SAMA5_SMC_MODE(SAMA5_SMC_GENERIC);
+	fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->mode))
+		return PTR_ERR(fields->mode);
+
+	return 0;
+}
+
+static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np,
+			      int reg_cells)
+{
+	const struct at91_ebi_caps *caps = ebi->caps;
+	struct at91_ebi_dev_config conf = { };
+	struct device *dev = ebi->dev;
+	struct at91_ebi_dev *ebid;
+	int ret, numcs = 0, i;
+	bool apply = false;
+
+	numcs = of_property_count_elems_of_size(np, "reg",
+						reg_cells * sizeof(u32));
+	if (numcs <= 0) {
+		dev_err(dev, "invalid reg property in %s\n", np->full_name);
+		return -EINVAL;
+	}
+
+	ebid = devm_kzalloc(ebi->dev,
+			    sizeof(*ebid) + (numcs * sizeof(*ebid->configs)),
+			    GFP_KERNEL);
+	if (!ebid)
+		return -ENOMEM;
+
+	ebid->ebi = ebi;
+
+	ret = caps->xlate_config(ebid, np, &conf);
+	if (ret < 0)
+		return ret;
+	else if (ret)
+		apply = true;
+
+	for (i = 0; i < numcs; i++) {
+		u32 cs;
+
+		ret = of_property_read_u32_index(np, "reg", i * reg_cells,
+						 &cs);
+		if (ret)
+			return ret;
+
+		if (cs > AT91_MATRIX_EBI_NUM_CS ||
+		    !(ebi->caps->available_cs & BIT(cs))) {
+			dev_err(dev, "invalid reg property in %s\n",
+				np->full_name);
+			return -EINVAL;
+		}
+
+		ebid->configs[i].cs = cs;
+
+		if (apply) {
+			conf.cs = cs;
+			ret = caps->apply_config(ebid, &conf);
+			if (ret)
+				return ret;
+		}
+
+		caps->get_config(ebid, &ebid->configs[i]);
+
+		/*
+		 * Attach the EBI device to the generic SMC logic if at least
+		 * one "atmel,smc-" property is present.
+		 */
+		if (ebi->ebi_csa && ret)
+			regmap_field_update_bits(ebi->ebi_csa,
+						 BIT(cs), 0);
+	}
+
+	list_add_tail(&ebid->node, &ebi->devs);
+
+	return 0;
+}
+
+static const struct reg_field at91sam9260_ebi_csa =
+				REG_FIELD(AT91SAM9260_MATRIX_EBICSA, 0,
+					  AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9260_ebi_caps = {
+	.available_cs = 0xff,
+	.ebi_csa = &at91sam9260_ebi_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9261_ebi_csa =
+				REG_FIELD(AT91SAM9261_MATRIX_EBICSA, 0,
+					  AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9261_ebi_caps = {
+	.available_cs = 0xff,
+	.ebi_csa = &at91sam9261_ebi_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9263_ebi0_csa =
+				REG_FIELD(AT91SAM9263_MATRIX_EBI0CSA, 0,
+					  AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9263_ebi0_caps = {
+	.available_cs = 0x3f,
+	.ebi_csa = &at91sam9263_ebi0_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9263_ebi1_csa =
+				REG_FIELD(AT91SAM9263_MATRIX_EBI1CSA, 0,
+					  AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9263_ebi1_caps = {
+	.available_cs = 0x7,
+	.ebi_csa = &at91sam9263_ebi1_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9rl_ebi_csa =
+				REG_FIELD(AT91SAM9RL_MATRIX_EBICSA, 0,
+					  AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9rl_ebi_caps = {
+	.available_cs = 0x3f,
+	.ebi_csa = &at91sam9rl_ebi_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9g45_ebi_csa =
+				REG_FIELD(AT91SAM9G45_MATRIX_EBICSA, 0,
+					  AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9g45_ebi_caps = {
+	.available_cs = 0x3f,
+	.ebi_csa = &at91sam9g45_ebi_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct at91_ebi_caps at91sam9x5_ebi_caps = {
+	.available_cs = 0x3f,
+	.ebi_csa = &at91sam9263_ebi0_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct at91_ebi_caps sama5d3_ebi_caps = {
+	.available_cs = 0xf,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = sama5d3_ebi_init,
+};
+
+static const struct of_device_id at91_ebi_id_table[] = {
+	{
+		.compatible = "atmel,at91sam9260-ebi",
+		.data = &at91sam9260_ebi_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9261-ebi",
+		.data = &at91sam9261_ebi_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9263-ebi0",
+		.data = &at91sam9263_ebi0_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9263-ebi1",
+		.data = &at91sam9263_ebi1_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9rl-ebi",
+		.data = &at91sam9rl_ebi_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9g45-ebi",
+		.data = &at91sam9g45_ebi_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9x5-ebi",
+		.data = &at91sam9x5_ebi_caps,
+	},
+	{
+		.compatible = "atmel,sama5d3-ebi",
+		.data = &sama5d3_ebi_caps,
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, at91_ebi_id_table);
+
+static int at91_ebi_dev_disable(struct at91_ebi *ebi, struct device_node *np)
+{
+	struct device *dev = ebi->dev;
+	struct property *newprop;
+
+	newprop = devm_kzalloc(dev, sizeof(*newprop), GFP_KERNEL);
+	if (!newprop)
+		return -ENOMEM;
+
+	newprop->name = devm_kstrdup(dev, "status", GFP_KERNEL);
+	if (!newprop->name)
+		return -ENOMEM;
+
+	newprop->value = devm_kstrdup(dev, "disabled", GFP_KERNEL);
+	if (!newprop->name)
+		return -ENOMEM;
+
+	newprop->length = sizeof("disabled");
+
+	return of_update_property(np, newprop);
+}
+
+static int at91_ebi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *child, *np = dev->of_node;
+	const struct of_device_id *match;
+	struct at91_ebi *ebi;
+	int ret, reg_cells;
+	struct clk *clk;
+	u32 val;
+
+	match = of_match_device(at91_ebi_id_table, dev);
+	if (!match || !match->data)
+		return -EINVAL;
+
+	ebi = devm_kzalloc(dev, sizeof(*ebi), GFP_KERNEL);
+	if (!ebi)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&ebi->devs);
+	ebi->caps = match->data;
+	ebi->dev = dev;
+
+	clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	ebi->clk = clk;
+
+	ebi->smc = syscon_regmap_lookup_by_phandle(np, "atmel,smc");
+	if (IS_ERR(ebi->smc))
+		return PTR_ERR(ebi->smc);
+
+	/*
+	 * The sama5d3 does not provide an EBICSA register and thus does need
+	 * to access the matrix registers.
+	 */
+	if (ebi->caps->ebi_csa) {
+		ebi->matrix =
+			syscon_regmap_lookup_by_phandle(np, "atmel,matrix");
+		if (IS_ERR(ebi->matrix))
+			return PTR_ERR(ebi->matrix);
+
+		ebi->ebi_csa = regmap_field_alloc(ebi->matrix,
+						  *ebi->caps->ebi_csa);
+		if (IS_ERR(ebi->ebi_csa))
+			return PTR_ERR(ebi->ebi_csa);
+	}
+
+	ret = ebi->caps->init(ebi);
+	if (ret)
+		return ret;
+
+	ret = of_property_read_u32(np, "#address-cells", &val);
+	if (ret) {
+		dev_err(dev, "missing #address-cells property\n");
+		return ret;
+	}
+
+	reg_cells = val;
+
+	ret = of_property_read_u32(np, "#size-cells", &val);
+	if (ret) {
+		dev_err(dev, "missing #address-cells property\n");
+		return ret;
+	}
+
+	reg_cells += val;
+
+	for_each_available_child_of_node(np, child) {
+		if (!of_find_property(child, "reg", NULL))
+			continue;
+
+		ret = at91_ebi_dev_setup(ebi, child, reg_cells);
+		if (ret) {
+			dev_err(dev, "failed to configure EBI bus for %s, disabling the device",
+				child->full_name);
+
+			ret = at91_ebi_dev_disable(ebi, child);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return of_platform_populate(np, NULL, NULL, dev);
+}
+
+static struct platform_driver at91_ebi_driver = {
+	.driver = {
+		.name = "atmel-ebi",
+		.of_match_table	= at91_ebi_id_table,
+	},
+};
+module_platform_driver_probe(at91_ebi_driver, at91_ebi_probe);
+
+MODULE_AUTHOR("JJ Hiblot");
+MODULE_DESCRIPTION("Atmel EBI driver");
+MODULE_LICENSE("GPL");
-- 
2.7.4



From bamvor.zhangjian at huawei.com  Wed May 11 03:12:56 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Wed, 11 May 2016 18:12:56 +0800
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <4876119.A8fbdncu9Z@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <4119683.coHZhzaE6c@wuerfel> <57329320.1000500@huawei.com>
 <4876119.A8fbdncu9Z@wuerfel>
Message-ID: <573305A8.50406@huawei.com>

Hi, Arnd

On 2016/5/11 16:09, Arnd Bergmann wrote:
 > On Wednesday 11 May 2016 10:04:16 Zhangjian wrote:
 >>> I don't remember. It's probably not important whether we have the shift
 >>> in there, as long as it's independent of the actual kernel page size and
 >>> user space and kernel agree on the calling conventions.
 >> Well. I am ok with where to shift the pages size because we get the same
 >> result. I was just thinking if we should get rid of the name of mmap2 in our
 >> ILP32 porting. Actually, it is mmap but we name it as mmap2. User may confused
 >> if they do not know the implementations.
 >
 > That is a good point: If the implementation matches the mmap() behavior rather than
 > mmap2(), we should rename the macro by doing
 >
 > #undef __NR_mmap2
 > #define __NR_mmap 222
 >
 > in the uapi/asm/unistd.h file for ilp32 mode.
Do you mean define the following things in kernel:
```
diff --git a/arch/arm64/include/uapi/asm/unistd.h b/arch/arm64/include/uapi/asm/unistd.h
index 1caadc2..3f79640 100644
--- a/arch/arm64/include/uapi/asm/unistd.h
+++ b/arch/arm64/include/uapi/asm/unistd.h
@@ -14,3 +14,9 @@
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  #include <asm-generic/unistd.h>
+
+#ifdef __ILP32__
+#undef __NR_mmap2
+#define __NR_mmap 222
+#endif /* #ifdef __ILP32__ */
+
```
Then glibc could call mmap instead of mmap2.
I could not try it now. Because after change off_t to 64bit in glibc, stat
is fail. I may need to revert the stat relative patch.

 > Alternatively we can keep the
 > __NR_mmap2 definition but then we need to pass the pgoff (value shifted by
 > 12 bits) argument rather than the size in bytes.
It means that we could reuse the existing code of mmap2 in kernel and glibc.
But we need to shift twice when kernel is 64k page.
It seems that the first method is more clear. Suggestion?

Regards

Bamvor
 >
 >   Arnd
 >



From dyoung at redhat.com  Wed May 11 03:31:19 2016
From: dyoung at redhat.com (Dave Young)
Date: Wed, 11 May 2016 18:31:19 +0800
Subject: [PATCH 00/12] Fixing TI Keystone2 kexec
In-Reply-To: <20160511093255.GO19428@n2100.arm.linux.org.uk>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <20160511082923.GC8995@dhcp-128-65.nay.redhat.com>
 <20160511085203.GN19428@n2100.arm.linux.org.uk>
 <20160511091338.GC10825@dhcp-128-65.nay.redhat.com>
 <20160511093255.GO19428@n2100.arm.linux.org.uk>
Message-ID: <20160511103119.GD10825@dhcp-128-65.nay.redhat.com>

On 05/11/16 at 10:32am, Russell King - ARM Linux wrote:
> On Wed, May 11, 2016 at 05:13:38PM +0800, Dave Young wrote:
> > On 05/11/16 at 09:52am, Russell King - ARM Linux wrote:
> > > I think you're confusing things.  DT doesn't contain the boot alias
> > > memory ranges - it's not a separate chunk of memory.  It's an alias
> > > of the same physical address space found higher in the physical
> > > address range.
> > 
> > Hmm, if we forget about kexec how does the 1st kernel get boot memory?
> > not from DT?
> 
> Just like any other ARM system, it pulls itself up by its shoe laces.
> 
> The kernel assumes that it has been placed into RAM with at least 32KiB
> of writable memory below it, which it uses for the initial page tables.
> It "guesses" that the executing address, rounded down to I-forget-what-
> boundary gives the base address of physical memory.
> 
> It sets the page table up using that assumption.  The kernel gets going
> with C code, and only _then_ parses the DTB.
> 
> If we then find that we're running on TI Keystone 2, part of the early
> platform initialisation specifies to the ARM core code that the kernel
> is to switch a high physical address space > 4GiB, and this provokes
> a "dance" where we tear the MMU back down, run some more assembly code
> to fix up the page tables, and re-initialise the MMU before returning
> to the kernel C code, this time running in the high physical address
> space.  This break-modify-make is an architecture requirement.  We
> also record the physical address delta between the original physical
> address space and the high physical address space so that we can reverse
> the translation for code which needs identity mapping (eg, SMP bringup.)
> 
> The DTB only contains the high physical address space memory information,
> and the kernel now parses the DTB, and sets the page tables up properly
> for the running system.

Thanks for the explanation, so the DTB does not contain the delta info
Please ignore the noise then.

> 
> > > If we put it in DT, then we need a way to also describe that it is an
> > > alias of some other bit of physical memory.
> > 
> > I may missed the background, I just want kexec to get infomation just like
> > the normal kernel.
> 
> See above.  What you're asking for isn't really possible.




From p.zabel at pengutronix.de  Wed May 11 03:34:13 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Wed, 11 May 2016 12:34:13 +0200
Subject: [RFC PATCH 13/21] reset: uniphier: add reset driver for
 UniPhier PH1-LD4 SoC
In-Reply-To: <CAK7LNASY=Kg-KOMue09_YRoxrBAnXP00oqG4AC2iQM1HJgLc7A@mail.gmail.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
 <1462873862-30940-14-git-send-email-yamada.masahiro@socionext.com>
 <1462883138.9155.3.camel@pengutronix.de>
 <CAK7LNASY=Kg-KOMue09_YRoxrBAnXP00oqG4AC2iQM1HJgLc7A@mail.gmail.com>
Message-ID: <1462962853.2924.19.camel@pengutronix.de>

Hi Masahiro,

Am Mittwoch, den 11.05.2016, 11:52 +0900 schrieb Masahiro Yamada:
> Hi Philipp,
> 
> 
> 2016-05-10 21:25 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> > Hi Masahiro,
> >
> > Am Dienstag, den 10.05.2016, 18:50 +0900 schrieb Masahiro Yamada:
> >> This series is just for review.
> >> Please do not apply this patch.
> >>
> >> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> >
> > No need for all these tiny drivers. If you probe from DT as Lee
> > requests, you can let of_device_id.data point to a compatible specific
> > uniphier_reset_data.
> >
> 
> I will need to fill the table a bit more to complete this work,
> but I do not think this reset driver will become as big as the clk driver.
> (I guess it will be less than 1000 lines.)
> 
> If you prefer a single file for the whole of this SoC family,
> I can squash all the files into one.
> (I can split it if I need to do so in the future.)

I'm fine with split files if you think the complete lists are too long,
but in that case export the uniphier_reset_data
I don't care about the lists being in a single file so much as I'd
prefer to avoid the duplicated boilerplate of one module_platform_driver
per SoC family member.

> 
> 
> 




From p.zabel at pengutronix.de  Wed May 11 03:34:34 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Wed, 11 May 2016 12:34:34 +0200
Subject: [RFC PATCH 12/21] reset: uniphier: add core support for
 UniPhier reset driver
In-Reply-To: <CAK7LNASpxbW81A7YGQuAqmBdBty4BC6Z8sko8YepXOPnVqSjAQ@mail.gmail.com>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
 <1462873862-30940-13-git-send-email-yamada.masahiro@socionext.com>
 <1462888497.9155.9.camel@pengutronix.de>
 <CAK7LNASpxbW81A7YGQuAqmBdBty4BC6Z8sko8YepXOPnVqSjAQ@mail.gmail.com>
Message-ID: <1462962874.2924.20.camel@pengutronix.de>

Am Mittwoch, den 11.05.2016, 11:46 +0900 schrieb Masahiro Yamada:
> Hi Philipp,
> 
> 
> 2016-05-10 22:54 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> > Am Dienstag, den 10.05.2016, 18:50 +0900 schrieb Masahiro Yamada:
> > [...]
> >> +static int uniphier_reset_update(struct reset_controller_dev *rcdev,
> >> +                              unsigned long id, bool assert)
> >> +{
> >> +     struct uniphier_reset_priv *priv = to_uniphier_reset_priv(rcdev);
> >> +     const struct uniphier_reset_data *p;
> >> +     bool handled = false;
> >> +
> >> +     for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) {
> >> +             unsigned int val;
> >> +             int ret;
> >> +
> >> +             if (p->id != id)
> >> +                     continue;
> >> +
> >> +             val = p->deassert_val;
> >> +             if (assert)
> >> +                     val = ~val;
> >> +
> >> +             ret = regmap_write_bits(priv->regmap, p->reg, p->mask, val);
> >
> > What is the difference between mask and deassert_val? Couldn't you just
> > assign
> >         val = assert ? 0 : p->mask;
> > ?
> 
> 
> I need to handle both active-high resets and active-low resets.

I see. I hadn't seen any active-high resets in your lists yet. If you
need them, you obviously can't simplify this much.

> I thought two ways to do that.
> 
> 
> [1] Have mask and a flag indicating active-low/active-high,
>     like follows:
> 
>      if (flag & UNIPHIER_RST_ACTIVE_LOW)
>           assert = !assert;
>      val = assert ? 0 : p->mask;
> 
> [2] Have mask and deassert_val as in this patch
>
> [1] cannot manage a case where one register contains
> active-low bits and active-high bits mixed in it.
> 
> 
> 
> For example, let's say reset bits are BIT(1) and BIT(0).
> 
> [2] can solve this case as follows:
> 
> (a) If both bit1 and bit0 are active-high.
>      .mask = BIT(1) | BIT(0);
>      .deassert_val = 0;
> 
> (b) If bit1 is active-high and bit0 is active-low
>      .mask = BIT(1) | BIT(0);
>      .deassert_val =  BIT(0);
> 
> (c) If bit1 is active-low and bit0 is active-high
>      .mask = BIT(1) | BIT(0);
>      .deassert_val =  BIT(1);
> 
> (d) If both bit1 and bit0 are active-low
>      .mask = BIT(1) | BIT(0);
>      .deassert_val = BIT(1) | BIT(0);
> 
> 
> I have not been hit by such a complicated case though.

In general it is a good idea not to add complexity for theoretical
cases, on the other hand [1] isn't really much less complex. Can I ask
you to invert the logic, though, and use assert_val instead?

regards
Philipp



From p.zabel at pengutronix.de  Wed May 11 03:37:58 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Wed, 11 May 2016 12:37:58 +0200
Subject: [RFC PATCH 13/21] reset: uniphier: add reset driver for
 UniPhier PH1-LD4 SoC
In-Reply-To: <1462962853.2924.19.camel@pengutronix.de>
References: <1462873862-30940-1-git-send-email-yamada.masahiro@socionext.com>
 <1462873862-30940-14-git-send-email-yamada.masahiro@socionext.com>
 <1462883138.9155.3.camel@pengutronix.de>
 <CAK7LNASY=Kg-KOMue09_YRoxrBAnXP00oqG4AC2iQM1HJgLc7A@mail.gmail.com>
 <1462962853.2924.19.camel@pengutronix.de>
Message-ID: <1462963078.2924.23.camel@pengutronix.de>

Am Mittwoch, den 11.05.2016, 12:34 +0200 schrieb Philipp Zabel:
> Hi Masahiro,
> 
> Am Mittwoch, den 11.05.2016, 11:52 +0900 schrieb Masahiro Yamada:
> > Hi Philipp,
> > 
> > 
> > 2016-05-10 21:25 GMT+09:00 Philipp Zabel <p.zabel at pengutronix.de>:
> > > Hi Masahiro,
> > >
> > > Am Dienstag, den 10.05.2016, 18:50 +0900 schrieb Masahiro Yamada:
> > >> This series is just for review.
> > >> Please do not apply this patch.
> > >>
> > >> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> > >
> > > No need for all these tiny drivers. If you probe from DT as Lee
> > > requests, you can let of_device_id.data point to a compatible specific
> > > uniphier_reset_data.
> > >
> > 
> > I will need to fill the table a bit more to complete this work,
> > but I do not think this reset driver will become as big as the clk driver.
> > (I guess it will be less than 1000 lines.)
> > 
> > If you prefer a single file for the whole of this SoC family,
> > I can squash all the files into one.
> > (I can split it if I need to do so in the future.)
> 
> I'm fine with split files if you think the complete lists are too long,
> but in that case export the uniphier_reset_data

"... and use them from a single platform driver." I wanted to add here
before I tripped over the send button.

> I don't care about the lists being in a single file so much as I'd
> prefer to avoid the duplicated boilerplate of one module_platform_driver
> per SoC family member.

best regards
Philipp


From catalin.marinas at arm.com  Wed May 11 03:39:29 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 11 May 2016 11:39:29 +0100
Subject: [PATCH v6 13/14] arm64, acpi, numa: NUMA support based on SRAT
 and SLIT
In-Reply-To: <1461780436-27182-14-git-send-email-ddaney.cavm@gmail.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <1461780436-27182-14-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <20160511103929.GC3051@e104818-lin.cambridge.arm.com>

On Wed, Apr 27, 2016 at 11:07:15AM -0700, David Daney wrote:
> +static int __init get_mpidr_in_madt(int acpi_id, u64 *mpidr)
> +{
> +	unsigned long madt_end, entry;
> +	struct acpi_table_madt *madt;
> +	acpi_size tbl_size;
> +
> +	if (ACPI_FAILURE(acpi_get_table_with_size(ACPI_SIG_MADT, 0,
> +			(struct acpi_table_header **)&madt, &tbl_size)))
> +		return -ENODEV;
> +
> +	entry = (unsigned long)madt;
> +	madt_end = entry + madt->header.length;
> +
> +	/* Parse all entries looking for a match. */
> +	entry += sizeof(struct acpi_table_madt);
> +	while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
> +		struct acpi_subtable_header *header =
> +			(struct acpi_subtable_header *)entry;
> +
> +		if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
> +			struct acpi_madt_generic_interrupt *gicc =
> +				container_of(header,
> +				struct acpi_madt_generic_interrupt, header);
> +
> +			if ((gicc->flags & ACPI_MADT_ENABLED) &&
> +			    (gicc->uid == acpi_id)) {
> +				*mpidr = gicc->arm_mpidr;
> +				early_acpi_os_unmap_memory(madt, tbl_size);
> +				return 0;
> +			}
> +		}
> +		entry += header->length;
> +	}
> +
> +	early_acpi_os_unmap_memory(madt, tbl_size);
> +	return -ENODEV;
> +}
> +
> +/* Callback for Proximity Domain -> ACPI processor UID mapping */
> +void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa)
> +{
> +	int pxm, node;
> +	u64 mpidr;
> +
> +	if (srat_disabled())
> +		return;
> +
> +	if (pa->header.length < sizeof(struct acpi_srat_gicc_affinity)) {
> +		pr_err("SRAT: Invalid SRAT header length: %d\n",
> +			pa->header.length);
> +		bad_srat();
> +		return;
> +	}
> +
> +	if (!(pa->flags & ACPI_SRAT_GICC_ENABLED))
> +		return;
> +
> +	if (cpus_in_srat >= NR_CPUS) {
> +		pr_warn_once("SRAT: cpu_to_node_map[%d] is too small, may not be able to use all cpus\n",
> +			     NR_CPUS);
> +		return;
> +	}
> +
> +	pxm = pa->proximity_domain;
> +	node = acpi_map_pxm_to_node(pxm);
> +
> +	if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
> +		pr_err("SRAT: Too many proximity domains %d\n", pxm);
> +		bad_srat();
> +		return;
> +	}
> +
> +	if (get_mpidr_in_madt(pa->acpi_processor_uid, &mpidr)) {
> +		pr_err("SRAT: PXM %d with ACPI ID %d has no valid MPIDR in MADT\n",
> +			pxm, pa->acpi_processor_uid);
> +		bad_srat();
> +		return;
> +	}

I wonder whether you could replace the get_mpidr_in_madt() function with
something like acpi_get_phys_id(). It looks like get_mpidr_in_madt()
duplicates functionality already available elsewhere.

-- 
Catalin


From catalin.marinas at arm.com  Wed May 11 03:40:14 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 11 May 2016 11:40:14 +0100
Subject: [PATCH v6 14/14] acpi, numa: Enable ACPI based NUMA on ARM64
In-Reply-To: <1461780436-27182-15-git-send-email-ddaney.cavm@gmail.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <1461780436-27182-15-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <20160511104014.GD3051@e104818-lin.cambridge.arm.com>

On Wed, Apr 27, 2016 at 11:07:16AM -0700, David Daney wrote:
> From: Hanjun Guo <hanjun.guo at linaro.org>
> 
> Add function needed for cpu to node mapping, and enable ACPI based
> NUMA for ARM64 in Kconfig
> 
> Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
> Signed-off-by: Robert Richter <rrichter at cavium.com>
> [david.daney at cavium.com added ACPI_NUMA default to y for ARM64]
> Signed-off-by: David Daney <david.daney at cavium.com>

Acked-by: Catalin Marinas <catalin.marinas at arm.com>


From will.deacon at arm.com  Wed May 11 03:40:32 2016
From: will.deacon at arm.com (Will Deacon)
Date: Wed, 11 May 2016 11:40:32 +0100
Subject: [PATCH v6 00/14] ACPI NUMA support for ARM64
In-Reply-To: <CAJZ5v0iMDQ4pWip4vyCos0o+1DFDvXQf4XZQqC4SGjJsDO4Lnw@mail.gmail.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <CAJZ5v0iMDQ4pWip4vyCos0o+1DFDvXQf4XZQqC4SGjJsDO4Lnw@mail.gmail.com>
Message-ID: <20160511104032.GA31374@arm.com>

On Wed, May 11, 2016 at 02:43:11AM +0200, Rafael J. Wysocki wrote:
> On Wed, Apr 27, 2016 at 8:07 PM, David Daney <ddaney.cavm at gmail.com> wrote:
> > From: David Daney <david.daney at cavium.com>
> >
> > Based on git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
> > for-next/core branch at commit 643d703d2d2d ("arm64: compat: Check for
> > AArch32 state")

[...]

> > David Daney (2):
> >   arm64, numa: Cleanup NUMA disabled messages.
> >   acpi, numa, srat: Improve SRAT error detection and add messages.
> >
> > Hanjun Guo (11):
> >   acpi, numa: Use pr_fmt() instead of printk
> >   acpi, numa: Replace ACPI_DEBUG_PRINT() with pr_debug()
> >   acpi, numa: remove duplicate NULL check
> >   acpi, numa: move acpi_numa_slit_init() to drivers/acpi/numa.c
> >   arm64, numa: rework numa_add_memblk()
> >   x86, acpi, numa: cleanup acpi_numa_processor_affinity_init()
> >   acpi, numa: move bad_srat() and srat_disabled() to
> >     drivers/acpi/numa.c
> >   acpi, numa: remove unneeded acpi_numa=1
> >   acpi, numa: Move acpi_numa_memory_affinity_init() to
> >     drivers/acpi/numa.c
> >   arm64, acpi, numa: NUMA support based on SRAT and SLIT
> >   acpi, numa: Enable ACPI based NUMA on ARM64
> >
> > Robert Richter (1):
> >   acpi, numa: Move acpi_numa_arch_fixup() to ia64 only
> 
> I need ACKs from the ARM64 maintainers on patches [6-7/13] and [13-14/14].

There's also a dependency on the arm64 for-next/core branch, so I've been
largely ignoring this as far as 4.6 is concerned and was planning to take
a proper look for 4.7 once the upcoming merge window is out of the way.

Will


From catalin.marinas at arm.com  Wed May 11 03:42:05 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 11 May 2016 11:42:05 +0100
Subject: [patch V4 02/31] bitops: Include generic parity.h in some
 architectures' bitops.h
In-Reply-To: <1462957641-24241-1-git-send-email-zengzhaoxiu@163.com>
References: <1462955158-28394-1-git-send-email-zengzhaoxiu@163.com>
 <1462957641-24241-1-git-send-email-zengzhaoxiu@163.com>
Message-ID: <20160511104205.GE3051@e104818-lin.cambridge.arm.com>

On Wed, May 11, 2016 at 05:06:17PM +0800, zengzhaoxiu at 163.com wrote:
> From: Zhaoxiu Zeng <zhaoxiu.zeng at gmail.com>
> 
> Simply use the generic version.
> 
> Signed-off-by: Zhaoxiu Zeng <zhaoxiu.zeng at gmail.com>
> Acked-by: Hans-Christian Noren Egtvedt <egtvedt at samfundet.no> [for avr32]
> ---
>  arch/arc/include/asm/bitops.h      | 1 +
>  arch/arm/include/asm/bitops.h      | 1 +
>  arch/arm64/include/asm/bitops.h    | 1 +
>  arch/avr32/include/asm/bitops.h    | 1 +
>  arch/c6x/include/asm/bitops.h      | 1 +
>  arch/cris/include/asm/bitops.h     | 1 +
>  arch/frv/include/asm/bitops.h      | 1 +
>  arch/h8300/include/asm/bitops.h    | 1 +
>  arch/hexagon/include/asm/bitops.h  | 1 +
>  arch/m32r/include/asm/bitops.h     | 1 +
>  arch/m68k/include/asm/bitops.h     | 1 +
>  arch/metag/include/asm/bitops.h    | 1 +
>  arch/mn10300/include/asm/bitops.h  | 1 +
>  arch/openrisc/include/asm/bitops.h | 1 +
>  arch/parisc/include/asm/bitops.h   | 1 +
>  arch/s390/include/asm/bitops.h     | 1 +
>  arch/sh/include/asm/bitops.h       | 1 +
>  arch/xtensa/include/asm/bitops.h   | 1 +

For arm64:

Acked-by: Catalin Marinas <catalin.marinas at arm.com>


From gabriele.paoloni at huawei.com  Wed May 11 03:41:15 2016
From: gabriele.paoloni at huawei.com (Gabriele Paoloni)
Date: Wed, 11 May 2016 10:41:15 +0000
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>

Hi Tomasz

> -----Original Message-----
> From: linux-kernel-owner at vger.kernel.org [mailto:linux-kernel-
> owner at vger.kernel.org] On Behalf Of Tomasz Nowicki
> Sent: 10 May 2016 16:20
> To: helgaas at kernel.org; arnd at arndb.de; will.deacon at arm.com;
> catalin.marinas at arm.com; rafael at kernel.org; hanjun.guo at linaro.org;
> Lorenzo.Pieralisi at arm.com; okaya at codeaurora.org; jchandra at broadcom.com
> Cc: robert.richter at caviumnetworks.com; mw at semihalf.com;
> Liviu.Dudau at arm.com; ddaney at caviumnetworks.com; Wangyijing;
> Suravee.Suthikulpanit at amd.com; msalter at redhat.com; linux-
> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-
> acpi at vger.kernel.org; linux-kernel at vger.kernel.org; linaro-
> acpi at lists.linaro.org; jcm at redhat.com; andrea.gallo at linaro.org;
> dhdang at apm.com; jeremy.linton at arm.com; liudongdong (C);
> cov at codeaurora.org; Tomasz Nowicki
> Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
> controller
> 
> From the functionality point of view this series may be split into the
> following logic parts:
> 1. New ECAM API and update for users of the pci-host-common API
> 2. Necessary fixes as the preparation for using driver on ARM64.
> 3. Use new MCFG interface and implement generic ACPI based PCI host
> controller driver.
> 4. Enable above driver on ARM64
> 
> Patches has been built on top of 4.6-rc7 and can be found here:
> git at github.com:semihalf-nowicki-tomasz/linux.git (pci-acpi-v7)
> 
> This has been tested on Cavium ThunderX server. Any help in reviewing
> and
> testing is very appreciated.
> 
> v6 -> v7
> - drop quirks handling

Maybe I missed something in the v6 discussion thread; when was it
decided to drop quirk handling?

I think it is important to have this in place to accommodate different
vendors. If the intention is to keep this patchset "clean" maybe
we can add it as a separate patch on top later on...

What?s your view?

Thanks

Gab


> - changes for ACPI companion and domain number assignment approach
> - implement arch pcibios_{add|remove}_bus and call
> acpi_pci_{add|remove}_bus from there
> - cleanups around nomenclature
> - use resources oriented API for ECAM
> - fix for based address calculation before mapping ECAM region
> - remove useless lock for MCFG lookup
> - move MCFG stuff to separated file pci_mcfg.c
> - drop MCFG entries caching
> - rebase against 4.6-rc7
> 
> v5 -> v6
> - drop idea of x86 MMCONFIG code refactoring
> - integrate JC's patches which introduce new ECAM API:
>   https://lkml.org/lkml/2016/4/11/907
>   git: https://github.com/jchandra-brcm/linux/ (arm64-acpi-pci-v3)
> - integrate Sinan's fix for releasing IO resources, see patch [06/13]
> - added ACPI support for ThunderX ECAM and PEM drivers
> - rebase against 4.6-rc2
> 
> v4 -> v5
> - drop MCFG refactoring group patches 1-6 from series v4 and integrate
> Jayachandran's patch
>   https://patchwork.ozlabs.org/patch/575525/
> - rewrite PCI legacy IRQs allocation
> - squash two patches 11 and 12 from series v4, fixed bisection issue
> - changelog improvements
> - rebase against 4.5-rc3
> 
> v3 -> v4
> - drop Jiang's fix
> http://lkml.iu.edu/hypermail/linux/kernel/1601.1/04318.html
> - add Lorenzo's fix patch 19/24
> - ACPI PCI bus domain number assigning cleanup
> - change resource management, we now claim and reassign resources
> - improvements for applying quirks
> - drop Matthew's http://www.spinics.net/lists/linux-pci/msg45950.html
> dependency
> - rebase against 4.5-rc1
> 
> v2 -> v3
> - fix legacy IRQ assigning and IO ports registration
> - remove reference to arch specific companion device for ia64
> - move ACPI PCI host controller driver to pci_root.c
> - drop generic domain assignment for x86 and ia64 as I am not
>   able to run all necessary test variants
> - drop patch which cleaned legacy IRQ assignment since it belongs to
>   Mathew's series:
>   https://patchwork.ozlabs.org/patch/557504/
> - extend MCFG quirk code
> - rebase against 4.4
> 
> v1 -> v2
> - move non-arch specific piece of code to dirver/acpi/ directory
> - fix IO resource handling
> - introduce PCI config accessors quirks matching
> - moved ACPI_COMPANION_SET to generic code
> 
> v1 - https://lkml.org/lkml/2015/10/27/504
> v2 - https://lkml.org/lkml/2015/12/16/246
> v3 - http://lkml.iu.edu/hypermail/linux/kernel/1601.1/04308.html
> v4 - https://lkml.org/lkml/2016/2/4/646
> v5 - https://lkml.org/lkml/2016/2/16/426
> v6 - https://lkml.org/lkml/2016/4/15/594
> 
> Jayachandran C (2):
>   PCI: Provide common functions for ECAM mapping
>   PCI: generic, thunder: update to use generic ECAM API
> 
> Tomasz Nowicki (9):
>   pci, of: Move the PCI I/O space management to PCI core code.
>   pci: Add new function to unmap IO resources.
>   acpi, pci: Support IO resources when parsing PCI host bridge
>     resources.
>   pci, acpi: Provide a way to assign bus domain number.
>   pci, acpi: Handle ACPI companion assignment.
>   pci, acpi: Support for ACPI based generic PCI host controller
>   arm64, pci, acpi: ACPI support for legacy IRQs parsing and
>     consolidation with DT code.
>   arm64, pci, acpi: Provide ACPI-specific prerequisites for PCI bus
>     enumeration.
>   arm64, pci, acpi: Start using ACPI based PCI host controller driver
>     for ARM64.
> 
>  arch/arm64/Kconfig                  |   1 +
>  arch/arm64/kernel/pci.c             |  34 +++-----
>  drivers/acpi/Kconfig                |   8 ++
>  drivers/acpi/Makefile               |   1 +
>  drivers/acpi/pci_mcfg.c             |  97 ++++++++++++++++++++++
>  drivers/acpi/pci_root.c             |  33 ++++++++
>  drivers/acpi/pci_root_generic.c     | 149
> +++++++++++++++++++++++++++++++++
>  drivers/of/address.c                | 116 +-------------------------
>  drivers/pci/Kconfig                 |   3 +
>  drivers/pci/Makefile                |   2 +
>  drivers/pci/ecam.c                  | 161
> ++++++++++++++++++++++++++++++++++++
>  drivers/pci/ecam.h                  |  72 ++++++++++++++++
>  drivers/pci/host/Kconfig            |   1 +
>  drivers/pci/host/pci-host-common.c  | 114 +++++++++++--------------
>  drivers/pci/host/pci-host-common.h  |  47 -----------
>  drivers/pci/host/pci-host-generic.c |  52 +++---------
>  drivers/pci/host/pci-thunder-ecam.c |  39 ++-------
>  drivers/pci/host/pci-thunder-pem.c  |  92 ++++++++++-----------
>  drivers/pci/pci.c                   | 150
> ++++++++++++++++++++++++++++++++-
>  drivers/pci/probe.c                 |   2 +
>  include/linux/of_address.h          |   9 --
>  include/linux/pci-acpi.h            |  14 ++++
>  include/linux/pci.h                 |  11 ++-
>  23 files changed, 823 insertions(+), 385 deletions(-)
>  create mode 100644 drivers/acpi/pci_mcfg.c
>  create mode 100644 drivers/acpi/pci_root_generic.c
>  create mode 100644 drivers/pci/ecam.c
>  create mode 100644 drivers/pci/ecam.h
>  delete mode 100644 drivers/pci/host/pci-host-common.h
> 
> --
> 1.9.1


From djkurtz at chromium.org  Wed May 11 03:53:10 2016
From: djkurtz at chromium.org (Daniel Kurtz)
Date: Wed, 11 May 2016 18:53:10 +0800
Subject: [PATCH 1/2] regulator: Add support for parsing operation mode
In-Reply-To: <1462957929-20105-2-git-send-email-henryc.chen@mediatek.com>
References: <1462957929-20105-1-git-send-email-henryc.chen@mediatek.com>
 <1462957929-20105-2-git-send-email-henryc.chen@mediatek.com>
Message-ID: <CAGS+omBy4neiPwQ60x6m4SRHFUkp_v80t+swQUL8JF45Uph+yw@mail.gmail.com>

Hi Henry,

On Wed, May 11, 2016 at 5:12 PM, Henry Chen <henryc.chen at mediatek.com> wrote:
>
> Some regulators support their operating mode to be changed by
> consumers for module specific purpose.
>
> This patch adds support to parse those properties and fill the
> regulator constraints so the regulator core can call the
> regualtor_set_mode to change the modes.
>
> Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
> ---
>  Documentation/devicetree/bindings/regulator/regulator.txt | 10 ++++++++++
>  drivers/regulator/of_regulator.c                          | 14 ++++++++++++++
>  2 files changed, 24 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt
> index ecfc593..88f98f0 100644
> --- a/Documentation/devicetree/bindings/regulator/regulator.txt
> +++ b/Documentation/devicetree/bindings/regulator/regulator.txt
> @@ -49,6 +49,16 @@ Optional properties:
>         0: Disable active discharge.
>         1: Enable active discharge.
>         Absence of this property will leave configuration to default.
> +- regulator-allow-change-mode: allow the regulator mode to be configured

As mentioned by broonie earlier, the explicit 'allow' property is
redundant, if regulator-supported-modes is present, then set
REGULATOR_CHANGE_MODE invalid_ops_mask , else leave it clear.

> +- regulator-supported-modes: Regulators can run in a variety of different operating
> +  modes depending on output load. This allows further system power savings by
> +  selecting the best (and most efficient) regulator mode for a desired load.
> +  The definition for each of these operation is defined at
> +  include/linux/regulator/consumer.h
> +       0: FAST.
> +       1: NORMAL.
> +       2: IDLE.
> +       3: STANDBY.
>
>  Deprecated properties:
>  - regulator-compatible: If a regulator chip contains multiple
> diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
> index 6b0aa80..12fe8c8 100644
> --- a/drivers/regulator/of_regulator.c
> +++ b/drivers/regulator/of_regulator.c

Also, I thought binding document changes are generally in a separate
patch from their implementation.

-Dan

> @@ -167,6 +167,20 @@ static void of_get_regulation_constraints(struct device_node *np,
>                 suspend_state = NULL;
>                 suspend_np = NULL;
>         }
> +
> +       if (of_property_read_bool(np, "regulator-allow-change-mode"))
> +               constraints->valid_ops_mask |= REGULATOR_CHANGE_MODE;
> +
> +       ret = of_property_count_elems_of_size(np,
> +                                             "regulator-supported-modes",
> +                                             sizeof(u32));
> +       for (i = 0; i < ret; i++) {
> +               u32 mode;
> +
> +               of_property_read_u32_index(np, "regulator-supported-modes",
> +                                          i, &mode);
> +               constraints->valid_modes_mask |= (1 << mode);
> +       }
>  }
>
>  /**
> --
> 1.8.1.1.dirty
>


From arnd at arndb.de  Wed May 11 03:55:01 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 12:55:01 +0200
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <20160511075438.GA15628@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <57329320.1000500@huawei.com> <20160511075438.GA15628@yury-N73SV>
Message-ID: <5842999.Zgpfq4gkVz@wuerfel>

On Wednesday 11 May 2016 11:04:38 Yury Norov wrote:
> On Wed, May 11, 2016 at 10:04:16AM +0800, Zhangjian (Bamvor) wrote:
> [...]
> 
> > >>Ok, I will test the ltp syscall test.
> > >>With this changes, the issue I mentioned should be fixed. But we still
> > >>use mmap2 syscall for ILP32 application when we pass the offset instead
> > >>of page offset. Is it correct?
> > >
> > >I don't remember. It's probably not important whether we have the shift
> > >in there, as long as it's independent of the actual kernel page size and
> > >user space and kernel agree on the calling conventions.
> > Well. I am ok with where to shift the pages size because we get the same
> > result. I was just thinking if we should get rid of the name of mmap2 in our
> > ILP32 porting. Actually, it is mmap but we name it as mmap2. User may confused
> > if they do not know the implementations.
> > 
> 
> This is what generic unistd.h does. If you want to change it, you'd
> change each arch that uses generic unistd.h.
> 

Generic unistd.h has this:

#ifdef __SYSCALL_COMPAT
#define __SC_COMP_3264(_nr, _32, _64, _comp) __SYSCALL(_nr, _comp)
#else
#define __SC_COMP_3264(_nr, _32, _64, _comp) __SC_3264(_nr, _32, _64)
#endif

#define __NR3264_mmap 222
__SC_3264(__NR3264_mmap, sys_mmap2, sys_mmap)


#if __BITS_PER_LONG == 64 && !defined(__SYSCALL_COMPAT)
#define __NR_mmap __NR3264_mmap
#else
#define __NR_mmap2 __NR3264_mmap
#endif

So by default we get __NR_mmap2 and sys_mmap2 on 32-bit ABIs, but
__NR_mmap and sys_mmap on 64-bit ABIs, as it should be.

The problem is that arch/arm64/kernel/sys_ilp32.c now overrides
this to use __NR_mmap2 with sys_mmap, so we have a mismatch. I think
we should either override both the implementation and the number,
or neither of them.

I think what happened is that you chose to override sys_mmap because
sys_mmap2 sometimes takes an off_t argument, however the kernel
just treats it as 'unsigned long', with a range of 44 bits for the
offset. Using sys_mmap with a __kernel_loff_t argument gives
us 64-bit range, but if we do that, I think it should be __NR_mmap.

	Arnd


From arnd at arndb.de  Wed May 11 03:56:03 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 12:56:03 +0200
Subject: [PATCH v2 3/4] ARM64: Kconfig: Select the Amlogic Meson pin
 controller driver
In-Reply-To: <CACRpkdbTr7YUrzSQQci929ugBhTkJKWvpjdf5Wo3HkfVKFhGLw@mail.gmail.com>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
 <1462176138-29433-4-git-send-email-carlo@caione.org>
 <CACRpkdbTr7YUrzSQQci929ugBhTkJKWvpjdf5Wo3HkfVKFhGLw@mail.gmail.com>
Message-ID: <3200982.vJgYKNLqaA@wuerfel>

On Wednesday 11 May 2016 10:53:35 Linus Walleij wrote:
> On Mon, May 2, 2016 at 10:02 AM, Carlo Caione <carlo at caione.org> wrote:
> 
> > From: Carlo Caione <carlo at endlessm.com>
> >
> > Select the Meson pin controller driver also for the AArch64 Meson
> > platform.
> >
> > Signed-off-by: Carlo Caione <carlo at endlessm.com>
> 
> Acked-by: Linus Walleij <linus.walleij at linaro.org>
> 
> I guess this should get merged through the ARM SoC tree.
> 

I'd keep it together with the other changes for clarity and
merge it through your tree.

Acked-by: Arnd Bergmann <arnd at arndb.de>


From arnd at arndb.de  Wed May 11 04:01:18 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 13:01:18 +0200
Subject: [PATCH V7 03/11] pci,
 of: Move the PCI I/O space management to PCI core code.
In-Reply-To: <5732E11A.9090002@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <CAJZ5v0ge+LGwp=AkPF50H1ZXFA6J5ByazuY7Opc-aLJwWrBNxg@mail.gmail.com>
 <5732E11A.9090002@semihalf.com>
Message-ID: <4722186.M8gaIx9LyT@wuerfel>

On Wednesday 11 May 2016 09:36:58 Tomasz Nowicki wrote:
> >
> > I understand that this moves code around, but those in-function
> > #ifdefs aren't nice.  Any chance to get rid of them but putting whole
> > functions under the #ifdef?
> >
> 
> This is a __weak implementation, so assuming I would move #ifdef out of 
> function I need to provide another empty __weak stub. I do not know 
> which solution is more ugly. In any case we can do that cleanup separately.
> 

I'd vote for just dropping the __weak here, given that there is no
non-weak implementation. If we end up needing to override this for
some architecture or host bridge in the future, we can think about how
to best do that then.

I agree that should be a separate patch, this one should only move
code from one file to another.

	Arnd


From harninder.rai at nxp.com  Wed May 11 04:06:45 2016
From: harninder.rai at nxp.com (Harninder Rai)
Date: Wed, 11 May 2016 11:06:45 +0000
Subject: Help needed with kexec on arm64
In-Reply-To: <20160511005334.GA8417@linaro.org>
References: <DB5PR04MB168845795D86B4CE5BA5656FE68B0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <1458230896.3391.18.camel@infradead.org>
 <CAB5YjtBEO=efjhcFdVOaZqG13qK3uzCbS5SFym5hhw-n+_QLhw@mail.gmail.com>
 <DB5PR04MB1688A6D4385B76DAFF71D364E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org>
 <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160511005334.GA8417@linaro.org>
Message-ID: <DB5PR04MB1688F1ECCB23EC3A2D76D5B7E6720@DB5PR04MB1688.eurprd04.prod.outlook.com>

Hello Takahiro Akashi,

> >
> > I used a smaller initramfs (as you suggested) and my crash kernel has
> moved further but it again dumped with the following log messages. Any
> further pointers?
> 
> It seems that you have already reached the point of kicking up "init"
> process, and this means that crash dump kernel itself successfully booted.
Yes, I too thought the same
> 
> > Does this mean that there isn't enough memory to save the core file or
> > something? Because the error mostly are related to OOM killer process
> 
> Apparently lack of memory is a cause of OOM killer, but the core file has
> nothing to do with this issue.
> I think that you don't have enough memory for the system yet.
Looks like there's only few MBs space left on my rootfs. Let me try shifting to secondary storage for storing the rootfs or maybe use chroot

Once again, thanks for the help

Regards
Harry++


From tn at semihalf.com  Wed May 11 04:08:00 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Wed, 11 May 2016 13:08:00 +0200
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
Message-ID: <57331290.7070104@semihalf.com>

Hi Gabriele,

On 11.05.2016 12:41, Gabriele Paoloni wrote:
> Hi Tomasz
>
>> -----Original Message-----
>> From: linux-kernel-owner at vger.kernel.org [mailto:linux-kernel-
>> owner at vger.kernel.org] On Behalf Of Tomasz Nowicki
>> Sent: 10 May 2016 16:20
>> To: helgaas at kernel.org; arnd at arndb.de; will.deacon at arm.com;
>> catalin.marinas at arm.com; rafael at kernel.org; hanjun.guo at linaro.org;
>> Lorenzo.Pieralisi at arm.com; okaya at codeaurora.org; jchandra at broadcom.com
>> Cc: robert.richter at caviumnetworks.com; mw at semihalf.com;
>> Liviu.Dudau at arm.com; ddaney at caviumnetworks.com; Wangyijing;
>> Suravee.Suthikulpanit at amd.com; msalter at redhat.com; linux-
>> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-
>> acpi at vger.kernel.org; linux-kernel at vger.kernel.org; linaro-
>> acpi at lists.linaro.org; jcm at redhat.com; andrea.gallo at linaro.org;
>> dhdang at apm.com; jeremy.linton at arm.com; liudongdong (C);
>> cov at codeaurora.org; Tomasz Nowicki
>> Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
>> controller
>>
>>  From the functionality point of view this series may be split into the
>> following logic parts:
>> 1. New ECAM API and update for users of the pci-host-common API
>> 2. Necessary fixes as the preparation for using driver on ARM64.
>> 3. Use new MCFG interface and implement generic ACPI based PCI host
>> controller driver.
>> 4. Enable above driver on ARM64
>>
>> Patches has been built on top of 4.6-rc7 and can be found here:
>> git at github.com:semihalf-nowicki-tomasz/linux.git (pci-acpi-v7)
>>
>> This has been tested on Cavium ThunderX server. Any help in reviewing
>> and
>> testing is very appreciated.
>>
>> v6 -> v7
>> - drop quirks handling
>
> Maybe I missed something in the v6 discussion thread; when was it
> decided to drop quirk handling?

I had such requests in previous series.

>
> I think it is important to have this in place to accommodate different
> vendors. If the intention is to keep this patchset "clean" maybe
> we can add it as a separate patch on top later on...
>
> What?s your view?

Yes, keeping these things separated should help in review. Obviously I 
agree that we need quirk handling but currently there is no 
implementation which we all agree upon. For the test, you can use quirk 
handling approach from the previous series until we sort out final solution.

Thanks,
Tomasz


From bamvor.zhangjian at huawei.com  Wed May 11 04:16:44 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Wed, 11 May 2016 19:16:44 +0800
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <573305A8.50406@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <4119683.coHZhzaE6c@wuerfel> <57329320.1000500@huawei.com>
 <4876119.A8fbdncu9Z@wuerfel> <573305A8.50406@huawei.com>
Message-ID: <5733149C.4030903@huawei.com>

Hi,

On 2016/5/11 18:12, Zhangjian (Bamvor) wrote:
> Hi, Arnd
>
> On 2016/5/11 16:09, Arnd Bergmann wrote:
>  > On Wednesday 11 May 2016 10:04:16 Zhangjian wrote:
>  >>> I don't remember. It's probably not important whether we have the shift
>  >>> in there, as long as it's independent of the actual kernel page size and
>  >>> user space and kernel agree on the calling conventions.
>  >> Well. I am ok with where to shift the pages size because we get the same
>  >> result. I was just thinking if we should get rid of the name of mmap2 in our
>  >> ILP32 porting. Actually, it is mmap but we name it as mmap2. User may confused
>  >> if they do not know the implementations.
>  >
>  > That is a good point: If the implementation matches the mmap() behavior rather than
>  > mmap2(), we should rename the macro by doing
>  >
>  > #undef __NR_mmap2
>  > #define __NR_mmap 222
>  >
>  > in the uapi/asm/unistd.h file for ilp32 mode.
> Do you mean define the following things in kernel:
> ```
> diff --git a/arch/arm64/include/uapi/asm/unistd.h b/arch/arm64/include/uapi/asm/unistd.h
> index 1caadc2..3f79640 100644
> --- a/arch/arm64/include/uapi/asm/unistd.h
> +++ b/arch/arm64/include/uapi/asm/unistd.h
> @@ -14,3 +14,9 @@
>    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>    */
>   #include <asm-generic/unistd.h>
> +
> +#ifdef __ILP32__
> +#undef __NR_mmap2
> +#define __NR_mmap 222
> +#endif /* #ifdef __ILP32__ */
> +
> ```
> Then glibc could call mmap instead of mmap2.
> I could not try it now. Because after change off_t to 64bit in glibc, stat
> is fail. I may need to revert the stat relative patch.
After revert stat relative patch in glibc, mmap01-mmap14 success. But mmap16
success with segfault. I will investigate it later.

There is pointer and size_t in mmap, so, IIUC, we need to clear the top halves
of register by using COMPAT_SYSCALL_WRAP6. And after check the function in
arch/s390/kernel/compat_linux.c, I feel that we need to do the same thing for
pread64 and pwrite64.

But I got following error when I try to add
COMPAT_SYSCALL_WRAP4(pread64, unsigned int, fd, char __user *, buf,
size_t, count, loff_t, pos);
COMPAT_SYSCALL_WRAP4(pwrite64, unsigned int, fd, const char __user *, buf,
size_t, count, loff_t, pos);

The error message:
kernel/compat_wrapper.c: In function 'compat_SyS_pread64':
include/linux/compiler.h:429:38: error: call to '__compiletime_assert_308' declared with attribute error: BUILD_BUG_ON failed: (sizeof(loff_t) > 4) && !__TYPE_IS_L(loff_t) && !__TYPE_IS_UL(loff_t) && !__TYPE_IS_PTR(loff_t)
_compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
^
include/linux/compiler.h:412:4: note: in definition of macro '__compiletime_assert'
prefix ## suffix(); \
^
include/linux/compiler.h:429:2: note: in expansion of macro '_compiletime_assert'
_compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
^
include/linux/bug.h:50:37: note: in expansion of macro 'compiletime_assert'
#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
^
include/linux/bug.h:74:2: note: in expansion of macro 'BUILD_BUG_ON_MSG'
BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
^
include/linux/compat.h:749:2: note: in expansion of macro 'BUILD_BUG_ON'
BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) && \
^
include/linux/syscalls.h:38:23: note: in expansion of macro '__SC_COMPAT_CAST'
#define __MAP1(m,t,a) m(t,a)
^
include/linux/syscalls.h:39:35: note: in expansion of macro '__MAP1'
#define __MAP2(m,t,a,...) m(t,a), __MAP1(m,__VA_ARGS__)
^
include/linux/syscalls.h:40:35: note: in expansion of macro '__MAP2'
#define __MAP3(m,t,a,...) m(t,a), __MAP2(m,__VA_ARGS__)
^
include/linux/syscalls.h:41:35: note: in expansion of macro '__MAP3'
#define __MAP4(m,t,a,...) m(t,a), __MAP3(m,__VA_ARGS__)
^
include/linux/syscalls.h:44:22: note: in expansion of macro '__MAP4'
#define __MAP(n,...) __MAP##n(__VA_ARGS__)
^
include/linux/compat.h:777:19: note: in expansion of macro '__MAP'
return sys##name(__MAP(x, __SC_COMPAT_CAST, __VA_ARGS__)); \
^
include/linux/compat.h:735:41: note: in expansion of macro 'COMPAT_SYSCALL_WRAPx'
#define COMPAT_SYSCALL_WRAP4(name, ...) COMPAT_SYSCALL_WRAPx(4, _##name,\
^
kernel/compat_wrapper.c:307:1: note: in expansion of macro 'COMPAT_SYSCALL_WRAP4'
COMPAT_SYSCALL_WRAP4(pread64, unsigned int, fd, char __user *, buf,
^

Because the loff_t is not the long, unsigned long or pointer.

Regards

Bamvor
>  > Alternatively we can keep the
>  > __NR_mmap2 definition but then we need to pass the pgoff (value shifted by
>  > 12 bits) argument rather than the size in bytes.
> It means that we could reuse the existing code of mmap2 in kernel and glibc.
> But we need to shift twice when kernel is 64k page.
> It seems that the first method is more clear. Suggestion?
>
> Regards
>
> Bamvor
>  >
>  >   Arnd
>  >
>



From carlo at caione.org  Wed May 11 04:25:16 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 11 May 2016 13:25:16 +0200
Subject: [PATCH v2 2/4] documentation: Add compatibles for Amlogic Meson
 GXBB pin controllers
In-Reply-To: <CACRpkdZQHX2YFh7CFpaagrY+BBtyAejdUs4F7ow+3+9+F6mU-A@mail.gmail.com>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
 <1462176138-29433-3-git-send-email-carlo@caione.org>
 <CACRpkdZQHX2YFh7CFpaagrY+BBtyAejdUs4F7ow+3+9+F6mU-A@mail.gmail.com>
Message-ID: <CAOQ7t2ZesQPPXTXEPRhF8TqzK-0c7VjH-_2ZKuxAOcd3-Z0uQQ@mail.gmail.com>

On Wed, May 11, 2016 at 10:52 AM, Linus Walleij
<linus.walleij at linaro.org> wrote:
> On Mon, May 2, 2016 at 10:02 AM, Carlo Caione <carlo at caione.org> wrote:
>
>> From: Carlo Caione <carlo at endlessm.com>
>>
>> Add the two new compatibles for the Amlogic Meson GXBB pin controllers.
>>
>> Signed-off-by: Carlo Caione <carlo at endlessm.com>
>> ---
>>  Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
>> index 32f4a2d..fe7fe0b 100644
>> --- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
>> +++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
>> @@ -5,6 +5,8 @@ Required properties for the root node:
>>                       "amlogic,meson8b-cbus-pinctrl"
>>                       "amlogic,meson8-aobus-pinctrl"
>>                       "amlogic,meson8b-aobus-pinctrl"
>> +                     "amlogic,meson-gxbb-periphs-pinctrl"
>> +                     "amlogic,meson-gxbb-aobus-pinctrl"
>>   - reg: address and size of registers controlling irq functionality
>
> This does NOT apply to the pin control tree because upstream does
> NOT look like this. It looks like that in linux-next however.

Linus master looks like that
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
If you want I can merge it through my tree with the DTS changes.

-- 
Carlo Caione


From andre.przywara at arm.com  Wed May 11 04:30:36 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 12:30:36 +0100
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <5731EBBE.7060203@linaro.org>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
 <5731EBBE.7060203@linaro.org>
Message-ID: <573317DC.4060200@arm.com>

Hi,

On 10/05/16 15:10, Eric Auger wrote:
> On 05/06/2016 12:45 PM, Andre Przywara wrote:
>> From: Marc Zyngier <marc.zyngier at arm.com>
>>
>> Processing maintenance interrupts and accessing the list registers
>> are dependent on the host's GIC version.
>> Introduce vgic-v2.c to contain GICv2 specific functions.
>> Implement the GICv2 specific code for syncing the emulation state
>> into the VGIC registers.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - remove explicit LR_STATE clearing on maintenance interrupt handling
>> - improve documentation for vgic_v2_populate_lr()
>> - remove WARN_ON on non-edge IRQs in maintenance interrupts
>> - simplify multi-CPU source SGI handling
>>
>> Changelog v1 .. v2:
>> - inject the IRQ priority into the list register
>>
>> Changelog v2 .. v3:
>> - cleanup diff containing rebase artifacts
>>
>>  include/linux/irqchip/arm-gic.h |   1 +
>>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic.c        |   6 ++
>>  virt/kvm/arm/vgic/vgic.h        |   6 ++
>>  4 files changed, 191 insertions(+)
>>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
>>
>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>> index 9c94026..be0d26f 100644
>> --- a/include/linux/irqchip/arm-gic.h
>> +++ b/include/linux/irqchip/arm-gic.h
>> @@ -76,6 +76,7 @@
>>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
>>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
>>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
>> +#define GICH_LR_PRIORITY_SHIFT		23
>>  #define GICH_LR_STATE			(3 << 28)
>>  #define GICH_LR_PENDING_BIT		(1 << 28)
>>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
>> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
>> new file mode 100644
>> index 0000000..4cee616
>> --- /dev/null
>> +++ b/virt/kvm/arm/vgic/vgic-v2.c
>> @@ -0,0 +1,178 @@
>> +/*
>> + * Copyright (C) 2015, 2016 ARM 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.
>> + *
>> + * 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.
>> + *
>> + * 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/irqchip/arm-gic.h>
>> +#include <linux/kvm.h>
>> +#include <linux/kvm_host.h>
>> +
>> +#include "vgic.h"
>> +
>> +/*
>> + * Call this function to convert a u64 value to an unsigned long * bitmask
>> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
>> + *
>> + * Warning: Calling this function may modify *val.
>> + */
>> +static unsigned long *u64_to_bitmask(u64 *val)
>> +{
>> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
>> +	*val = (*val >> 32) | (*val << 32);
>> +#endif
>> +	return (unsigned long *)val;
>> +}
>> +
>> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
>> +{
>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>> +
>> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
>> +		u64 eisr = cpuif->vgic_eisr;
>> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
>> +		int lr;
>> +
>> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
> Didn't we say we could use vcpu->arch.vgic_cpu.used_lrs here?

Why would that be useful? Don't we just want to see those LRs that had a
maintenance interrupt received? I don't see the point if iterating over
the used LRs, where we need to check for this condition somehow manually?
Or what am I missing here?

>> +			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
>> +
>> +			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
>> +
>> +			kvm_notify_acked_irq(vcpu->kvm, 0,
>> +					     intid - VGIC_NR_PRIVATE_IRQS);
>> +
>> +			cpuif->vgic_elrsr |= 1ULL << lr;

So are we good with removing this line (and the respective one in v3)?

Cheers,
Andre.

>> +		}
>> +	}
>> +
>> +	/* check and disable underflow maintenance IRQ */
> check?
> 
> Besides
> Reviewed-by: Eric Auger <eric.auger at linaro.org>
> 
> Eric
>> +	cpuif->vgic_hcr &= ~GICH_HCR_UIE;
>> +
>> +	/*
>> +	 * In the next iterations of the vcpu loop, if we sync the
>> +	 * vgic state after flushing it, but before entering the guest
>> +	 * (this happens for pending signals and vmid rollovers), then
>> +	 * make sure we don't pick up any old maintenance interrupts
>> +	 * here.
>> +	 */
>> +	cpuif->vgic_eisr = 0;
>> +}
>> +
>> +void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
>> +{
>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>> +
>> +	cpuif->vgic_hcr |= GICH_HCR_UIE;
>> +}
>> +
>> +/*
>> + * transfer the content of the LRs back into the corresponding ap_list:
>> + * - active bit is transferred as is
>> + * - pending bit is
>> + *   - transferred as is in case of edge sensitive IRQs
>> + *   - set to the line-level (resample time) for level sensitive IRQs
>> + */
>> +void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
>> +{
>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>> +	int lr;
>> +
>> +	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
>> +		u32 val = cpuif->vgic_lr[lr];
>> +		u32 intid = val & GICH_LR_VIRTUALID;
>> +		struct vgic_irq *irq;
>> +
>> +		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
>> +
>> +		spin_lock(&irq->irq_lock);
>> +
>> +		/* Always preserve the active bit */
>> +		irq->active = !!(val & GICH_LR_ACTIVE_BIT);
>> +
>> +		/* Edge is the only case where we preserve the pending bit */
>> +		if (irq->config == VGIC_CONFIG_EDGE &&
>> +		    (val & GICH_LR_PENDING_BIT)) {
>> +			irq->pending = true;
>> +
>> +			if (vgic_irq_is_sgi(intid)) {
>> +				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
>> +
>> +				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
>> +				irq->source |= (1 << cpuid);
>> +			}
>> +		}
>> +
>> +		/* Clear soft pending state when level IRQs have been acked */
>> +		if (irq->config == VGIC_CONFIG_LEVEL &&
>> +		    !(val & GICH_LR_PENDING_BIT)) {
>> +			irq->soft_pending = false;
>> +			irq->pending = irq->line_level;
>> +		}
>> +
>> +		spin_unlock(&irq->irq_lock);
>> +	}
>> +}
>> +
>> +/*
>> + * Populates the particular LR with the state of a given IRQ:
>> + * - for an edge sensitive IRQ the pending state is cleared in struct vgic_irq
>> + * - for a level sensitive IRQ the pending state value is unchanged;
>> + *   it is dictated directly by the input level
>> + *
>> + * If @irq describes an SGI with multiple sources, we choose the
>> + * lowest-numbered source VCPU and clear that bit in the source bitmap.
>> + *
>> + * The irq_lock must be held by the caller.
>> + */
>> +void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
>> +{
>> +	u32 val = irq->intid;
>> +
>> +	if (irq->pending) {
>> +		val |= GICH_LR_PENDING_BIT;
>> +
>> +		if (irq->config == VGIC_CONFIG_EDGE)
>> +			irq->pending = false;
>> +
>> +		if (vgic_irq_is_sgi(irq->intid)) {
>> +			u32 src = ffs(irq->source);
>> +
>> +			BUG_ON(!src);
>> +			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
>> +			irq->source &= ~(1 << (src - 1));
>> +			if (irq->source)
>> +				irq->pending = true;
>> +		}
>> +	}
>> +
>> +	if (irq->active)
>> +		val |= GICH_LR_ACTIVE_BIT;
>> +
>> +	if (irq->hw) {
>> +		val |= GICH_LR_HW;
>> +		val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
>> +	} else {
>> +		if (irq->config == VGIC_CONFIG_LEVEL)
>> +			val |= GICH_LR_EOI;
>> +	}
>> +
>> +	/* The GICv2 LR only holds five bits of priority. */
>> +	val |= (irq->priority >> 3) << GICH_LR_PRIORITY_SHIFT;
>> +
>> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = val;
>> +}
>> +
>> +void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
>> +{
>> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
>> +}
>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>> index c6f8b9b..68d885c 100644
>> --- a/virt/kvm/arm/vgic/vgic.c
>> +++ b/virt/kvm/arm/vgic/vgic.c
>> @@ -397,10 +397,12 @@ retry:
>>  
>>  static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
>>  {
>> +	vgic_v2_process_maintenance(vcpu);
>>  }
>>  
>>  static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
>>  {
>> +	vgic_v2_fold_lr_state(vcpu);
>>  }
>>  
>>  /* Requires the ap_list_lock and the irq_lock to be held. */
>> @@ -409,14 +411,18 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
>>  {
>>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
>>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
>> +
>> +	vgic_v2_populate_lr(vcpu, irq, lr);
>>  }
>>  
>>  static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
>>  {
>> +	vgic_v2_clear_lr(vcpu, lr);
>>  }
>>  
>>  static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
>>  {
>> +	vgic_v2_set_underflow(vcpu);
>>  }
>>  
>>  static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
>> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>> index 29b96b9..0db490e 100644
>> --- a/virt/kvm/arm/vgic/vgic.h
>> +++ b/virt/kvm/arm/vgic/vgic.h
>> @@ -22,4 +22,10 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>>  			      u32 intid);
>>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
>>  
>> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
>> +void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
>> +void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
>> +void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
>> +void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
>> +
>>  #endif
>>
> 


From eric.auger at linaro.org  Wed May 11 04:38:12 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed, 11 May 2016 13:38:12 +0200
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <573317DC.4060200@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
 <5731EBBE.7060203@linaro.org> <573317DC.4060200@arm.com>
Message-ID: <573319A4.30905@linaro.org>

On 05/11/2016 01:30 PM, Andre Przywara wrote:
> Hi,
> 
> On 10/05/16 15:10, Eric Auger wrote:
>> On 05/06/2016 12:45 PM, Andre Przywara wrote:
>>> From: Marc Zyngier <marc.zyngier at arm.com>
>>>
>>> Processing maintenance interrupts and accessing the list registers
>>> are dependent on the host's GIC version.
>>> Introduce vgic-v2.c to contain GICv2 specific functions.
>>> Implement the GICv2 specific code for syncing the emulation state
>>> into the VGIC registers.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>> Changelog RFC..v1:
>>> - remove explicit LR_STATE clearing on maintenance interrupt handling
>>> - improve documentation for vgic_v2_populate_lr()
>>> - remove WARN_ON on non-edge IRQs in maintenance interrupts
>>> - simplify multi-CPU source SGI handling
>>>
>>> Changelog v1 .. v2:
>>> - inject the IRQ priority into the list register
>>>
>>> Changelog v2 .. v3:
>>> - cleanup diff containing rebase artifacts
>>>
>>>  include/linux/irqchip/arm-gic.h |   1 +
>>>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
>>>  virt/kvm/arm/vgic/vgic.c        |   6 ++
>>>  virt/kvm/arm/vgic/vgic.h        |   6 ++
>>>  4 files changed, 191 insertions(+)
>>>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
>>>
>>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>>> index 9c94026..be0d26f 100644
>>> --- a/include/linux/irqchip/arm-gic.h
>>> +++ b/include/linux/irqchip/arm-gic.h
>>> @@ -76,6 +76,7 @@
>>>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
>>>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
>>>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
>>> +#define GICH_LR_PRIORITY_SHIFT		23
>>>  #define GICH_LR_STATE			(3 << 28)
>>>  #define GICH_LR_PENDING_BIT		(1 << 28)
>>>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
>>> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
>>> new file mode 100644
>>> index 0000000..4cee616
>>> --- /dev/null
>>> +++ b/virt/kvm/arm/vgic/vgic-v2.c
>>> @@ -0,0 +1,178 @@
>>> +/*
>>> + * Copyright (C) 2015, 2016 ARM 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.
>>> + *
>>> + * 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.
>>> + *
>>> + * 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/irqchip/arm-gic.h>
>>> +#include <linux/kvm.h>
>>> +#include <linux/kvm_host.h>
>>> +
>>> +#include "vgic.h"
>>> +
>>> +/*
>>> + * Call this function to convert a u64 value to an unsigned long * bitmask
>>> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
>>> + *
>>> + * Warning: Calling this function may modify *val.
>>> + */
>>> +static unsigned long *u64_to_bitmask(u64 *val)
>>> +{
>>> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
>>> +	*val = (*val >> 32) | (*val << 32);
>>> +#endif
>>> +	return (unsigned long *)val;
>>> +}
>>> +
>>> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
>>> +{
>>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>>> +
>>> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
>>> +		u64 eisr = cpuif->vgic_eisr;
>>> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
>>> +		int lr;
>>> +
>>> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
>> Didn't we say we could use vcpu->arch.vgic_cpu.used_lrs here?
> 
> Why would that be useful? Don't we just want to see those LRs that had a
> maintenance interrupt received? I don't see the point if iterating over
> the used LRs, where we need to check for this condition somehow manually?
> Or what am I missing here?

Well I thought that there is no use inspecting bits corresponding to
unused LRs, no?

Cheers

Eric
> 
>>> +			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
>>> +
>>> +			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
>>> +
>>> +			kvm_notify_acked_irq(vcpu->kvm, 0,
>>> +					     intid - VGIC_NR_PRIVATE_IRQS);
>>> +
>>> +			cpuif->vgic_elrsr |= 1ULL << lr;
> 
> So are we good with removing this line (and the respective one in v3)?
> 
> Cheers,
> Andre.
> 
>>> +		}
>>> +	}
>>> +
>>> +	/* check and disable underflow maintenance IRQ */
>> check?
>>
>> Besides
>> Reviewed-by: Eric Auger <eric.auger at linaro.org>
>>
>> Eric
>>> +	cpuif->vgic_hcr &= ~GICH_HCR_UIE;
>>> +
>>> +	/*
>>> +	 * In the next iterations of the vcpu loop, if we sync the
>>> +	 * vgic state after flushing it, but before entering the guest
>>> +	 * (this happens for pending signals and vmid rollovers), then
>>> +	 * make sure we don't pick up any old maintenance interrupts
>>> +	 * here.
>>> +	 */
>>> +	cpuif->vgic_eisr = 0;
>>> +}
>>> +
>>> +void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
>>> +{
>>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>>> +
>>> +	cpuif->vgic_hcr |= GICH_HCR_UIE;
>>> +}
>>> +
>>> +/*
>>> + * transfer the content of the LRs back into the corresponding ap_list:
>>> + * - active bit is transferred as is
>>> + * - pending bit is
>>> + *   - transferred as is in case of edge sensitive IRQs
>>> + *   - set to the line-level (resample time) for level sensitive IRQs
>>> + */
>>> +void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
>>> +{
>>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>>> +	int lr;
>>> +
>>> +	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
>>> +		u32 val = cpuif->vgic_lr[lr];
>>> +		u32 intid = val & GICH_LR_VIRTUALID;
>>> +		struct vgic_irq *irq;
>>> +
>>> +		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
>>> +
>>> +		spin_lock(&irq->irq_lock);
>>> +
>>> +		/* Always preserve the active bit */
>>> +		irq->active = !!(val & GICH_LR_ACTIVE_BIT);
>>> +
>>> +		/* Edge is the only case where we preserve the pending bit */
>>> +		if (irq->config == VGIC_CONFIG_EDGE &&
>>> +		    (val & GICH_LR_PENDING_BIT)) {
>>> +			irq->pending = true;
>>> +
>>> +			if (vgic_irq_is_sgi(intid)) {
>>> +				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
>>> +
>>> +				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
>>> +				irq->source |= (1 << cpuid);
>>> +			}
>>> +		}
>>> +
>>> +		/* Clear soft pending state when level IRQs have been acked */
>>> +		if (irq->config == VGIC_CONFIG_LEVEL &&
>>> +		    !(val & GICH_LR_PENDING_BIT)) {
>>> +			irq->soft_pending = false;
>>> +			irq->pending = irq->line_level;
>>> +		}
>>> +
>>> +		spin_unlock(&irq->irq_lock);
>>> +	}
>>> +}
>>> +
>>> +/*
>>> + * Populates the particular LR with the state of a given IRQ:
>>> + * - for an edge sensitive IRQ the pending state is cleared in struct vgic_irq
>>> + * - for a level sensitive IRQ the pending state value is unchanged;
>>> + *   it is dictated directly by the input level
>>> + *
>>> + * If @irq describes an SGI with multiple sources, we choose the
>>> + * lowest-numbered source VCPU and clear that bit in the source bitmap.
>>> + *
>>> + * The irq_lock must be held by the caller.
>>> + */
>>> +void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
>>> +{
>>> +	u32 val = irq->intid;
>>> +
>>> +	if (irq->pending) {
>>> +		val |= GICH_LR_PENDING_BIT;
>>> +
>>> +		if (irq->config == VGIC_CONFIG_EDGE)
>>> +			irq->pending = false;
>>> +
>>> +		if (vgic_irq_is_sgi(irq->intid)) {
>>> +			u32 src = ffs(irq->source);
>>> +
>>> +			BUG_ON(!src);
>>> +			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
>>> +			irq->source &= ~(1 << (src - 1));
>>> +			if (irq->source)
>>> +				irq->pending = true;
>>> +		}
>>> +	}
>>> +
>>> +	if (irq->active)
>>> +		val |= GICH_LR_ACTIVE_BIT;
>>> +
>>> +	if (irq->hw) {
>>> +		val |= GICH_LR_HW;
>>> +		val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
>>> +	} else {
>>> +		if (irq->config == VGIC_CONFIG_LEVEL)
>>> +			val |= GICH_LR_EOI;
>>> +	}
>>> +
>>> +	/* The GICv2 LR only holds five bits of priority. */
>>> +	val |= (irq->priority >> 3) << GICH_LR_PRIORITY_SHIFT;
>>> +
>>> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = val;
>>> +}
>>> +
>>> +void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
>>> +{
>>> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
>>> +}
>>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>>> index c6f8b9b..68d885c 100644
>>> --- a/virt/kvm/arm/vgic/vgic.c
>>> +++ b/virt/kvm/arm/vgic/vgic.c
>>> @@ -397,10 +397,12 @@ retry:
>>>  
>>>  static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
>>>  {
>>> +	vgic_v2_process_maintenance(vcpu);
>>>  }
>>>  
>>>  static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
>>>  {
>>> +	vgic_v2_fold_lr_state(vcpu);
>>>  }
>>>  
>>>  /* Requires the ap_list_lock and the irq_lock to be held. */
>>> @@ -409,14 +411,18 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
>>>  {
>>>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
>>>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
>>> +
>>> +	vgic_v2_populate_lr(vcpu, irq, lr);
>>>  }
>>>  
>>>  static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
>>>  {
>>> +	vgic_v2_clear_lr(vcpu, lr);
>>>  }
>>>  
>>>  static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
>>>  {
>>> +	vgic_v2_set_underflow(vcpu);
>>>  }
>>>  
>>>  static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
>>> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>>> index 29b96b9..0db490e 100644
>>> --- a/virt/kvm/arm/vgic/vgic.h
>>> +++ b/virt/kvm/arm/vgic/vgic.h
>>> @@ -22,4 +22,10 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>>>  			      u32 intid);
>>>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
>>>  
>>> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
>>> +void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
>>> +void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
>>> +void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
>>> +void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
>>> +
>>>  #endif
>>>
>>



From caesar.upstream at gmail.com  Wed May 11 04:43:06 2016
From: caesar.upstream at gmail.com (Caesar Wang)
Date: Wed, 11 May 2016 19:43:06 +0800
Subject: [PATCH v8 7/8] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <1462908698-27284-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908698-27284-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <57331ACA.5020605@gmail.com>



? 2016?05?11? 03:31, David Wu ??:
> - new method to caculate i2c timings for rk3399:
>    There was an timing issue about "repeated start" time at the I2C
>    controller of version0, controller appears to drop SDA at .875x (7/8)
>    programmed clk high. On version 1 of the controller, the rule(.875x)
>    isn't enough to meet tSU;STA
>    requirements on 100k's Standard-mode. To resolve this issue,
>    sda_update_config, start_setup_config and stop_setup_config for I2C
>    timing information are added, new rules are designed to calculate
>    the timing information at new v1.
> - pclk and function clk are separated at rk3399
>
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> ---
> Changes in v8:
> - update tuning in RKI2C_CON register by doing a read-modify-write (Doug)
> - new method to use pclk and clk (Doug)
>
> Changes in v7:
> - transform into a 9 series patches (Doug)
> - drop highspeed with mastercode, and support fast-mode plus (Doug)

Tested-by: Caesar Wang <wxt at rock-chips.com>
Few comments below:


I picked David's patches up for my rk3399 evb board.
Add the needed i2c devices for dts.

localhost / #modprobe i2c-dev
localhost / # i2cdump -f -y 0 0x1b
No size specified (using byte-data access)
      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f 0123456789abcdef
00: 18 01 09 21 01 13 01 00 00 00 00 01 01 00 00 00 ???!???....??...
10: 80 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ??..............
20: 00 5f 00 6f ff 00 00 00 10 00 ff 0f ff 02 01 0f ._.o....?..?.???
30: 00 00 01 0f 00 00 02 03 00 00 09 00 00 0c 00 0a ..??..??..?..?.?
40: 00 0c 00 0c 00 07 00 0a 00 0c 00 00 00 5f 00 03 .?.?.?.?.?..._.?
50: 06 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ??..............
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
70: 00 cf 03 00 28 00 0c 1c 80 19 00 34 12 00 71 00 .??.(.????.4?.q.
80: 10 50 1f ac 00 40 00 49 00 00 c0 44 41 01 00 00 ?P??. at .I..?DA?..
90: 55 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 U...............
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
localhost / # i2cset -f -y 0 0x1b 0x90 0xff
localhost / # i2cdump -f -y 0 0x1b |grep 90
  No size specified (using byte-data access)
90: ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

The i2c devices are working for my board.

run:
modprobe i2c-dev; for i in $(seq 0 8); do echo ==BUS $i; i2cdetect -y -q 
$i; done
See the output message,and mesure the i2c frequency.





>
>   drivers/i2c/busses/i2c-rk3x.c | 289 +++++++++++++++++++++++++++++++++++++++---
>   1 file changed, 270 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> index 9791797..25ed1ad 100644
> --- a/drivers/i2c/busses/i2c-rk3x.c
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -58,6 +58,12 @@ enum {
>   #define REG_CON_LASTACK   BIT(5) /* 1: send NACK after last received byte */
>   #define REG_CON_ACTACK    BIT(6) /* 1: stop if NACK is received */
>   
> +#define REG_CON_TUNING_MASK GENMASK(15, 8)
> +
> +#define REG_CON_SDA_CFG(cfg) ((cfg) << 8)
> +#define REG_CON_STA_CFG(cfg) ((cfg) << 12)
> +#define REG_CON_STO_CFG(cfg) ((cfg) << 14)
> +
>   /* REG_MRXADDR bits */
>   #define REG_MRXADDR_VALID(x) BIT(24 + (x)) /* [x*8+7:x*8] of MRX[R]ADDR valid */
>   
> @@ -77,40 +83,62 @@ enum {
>   
>   /**
>    * struct i2c_spec_values:
> + * @min_hold_start_ns: min hold time (repeated) START condition
>    * @min_low_ns: min LOW period of the SCL clock
>    * @min_high_ns: min HIGH period of the SCL cloc
>    * @min_setup_start_ns: min set-up time for a repeated START conditio
>    * @max_data_hold_ns: max data hold time
> + * @min_data_setup_ns: min data set-up time
> + * @min_setup_stop_ns: min set-up time for STOP condition
> + * @min_hold_buffer_ns: min bus free time between a STOP and
> + * START condition
>    */
>   struct i2c_spec_values {
> +	unsigned long min_hold_start_ns;
>   	unsigned long min_low_ns;
>   	unsigned long min_high_ns;
>   	unsigned long min_setup_start_ns;
>   	unsigned long max_data_hold_ns;
> +	unsigned long min_data_setup_ns;
> +	unsigned long min_setup_stop_ns;
> +	unsigned long min_hold_buffer_ns;
>   };
>   
>   static const struct i2c_spec_values standard_mode_spec = {
> +	.min_hold_start_ns = 4000,
>   	.min_low_ns = 4700,
>   	.min_high_ns = 4000,
>   	.min_setup_start_ns = 4700,
>   	.max_data_hold_ns = 3450,
> +	.min_data_setup_ns = 250,
> +	.min_setup_stop_ns = 4000,
> +	.min_hold_buffer_ns = 4700,
>   };
>   
>   static const struct i2c_spec_values fast_mode_spec = {
> +	.min_hold_start_ns = 600,
>   	.min_low_ns = 1300,
>   	.min_high_ns = 600,
>   	.min_setup_start_ns = 600,
>   	.max_data_hold_ns = 900,
> +	.min_data_setup_ns = 100,
> +	.min_setup_stop_ns = 600,
> +	.min_hold_buffer_ns = 1300,
>   };
>   
>   /**
>    * struct rk3x_i2c_calced_timings:
>    * @div_low: Divider output for low
>    * @div_high: Divider output for high
> + * @tuning: Used to adjust setup/hold data time,
> + * setup/hold start time and setup stop time for
> + * v1's calc_timings, the tuning should all be 0
> + * for old hardware anyone using v0's calc_timings.
>    */
>   struct rk3x_i2c_calced_timings {
>   	unsigned long div_low;
>   	unsigned long div_high;
> +	unsigned int tuning;
>   };
>   
>   enum rk3x_i2c_state {
> @@ -123,9 +151,12 @@ enum rk3x_i2c_state {
>   
>   /**
>    * @grf_offset: offset inside the grf regmap for setting the i2c type
> + * @calc_timings: Callback function for i2c timing information calculated
>    */
>   struct rk3x_i2c_soc_data {
>   	int grf_offset;
> +	int (*calc_timings)(unsigned long, struct i2c_timings *,
> +			    struct rk3x_i2c_calced_timings *);
>   };
>   
>   /**
> @@ -134,7 +165,8 @@ struct rk3x_i2c_soc_data {
>    * @dev: device for this controller
>    * @soc_data: related soc data struct
>    * @regs: virtual memory area
> - * @clk: clock of i2c bus
> + * @clk: function clk for rk3399 or function & Bus clks for others
> + * @pclk: Bus clk for rk3399
>    * @clk_rate_nb: i2c clk rate change notify
>    * @t: I2C known timing information
>    * @lock: spinlock for the i2c bus
> @@ -156,6 +188,7 @@ struct rk3x_i2c {
>   	/* Hardware resources */
>   	void __iomem *regs;
>   	struct clk *clk;
> +	struct clk *pclk;
>   	struct notifier_block clk_rate_nb;
>   
>   	/* Settings */
> @@ -200,12 +233,12 @@ static inline void rk3x_i2c_clean_ipd(struct rk3x_i2c *i2c)
>    */
>   static void rk3x_i2c_start(struct rk3x_i2c *i2c)
>   {
> -	u32 val;
> +	u32 val = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK;
>   
>   	i2c_writel(i2c, REG_INT_START, REG_IEN);
>   
>   	/* enable adapter with correct mode, send START condition */
> -	val = REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START;
> +	val |= REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START;
>   
>   	/* if we want to react to NACK, set ACTACK bit */
>   	if (!(i2c->msg->flags & I2C_M_IGNORE_NAK))
> @@ -513,9 +546,9 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
>    * a best-effort divider value is returned in divs. If the target rate is
>    * too high, we silently use the highest possible rate.
>    */
> -static int rk3x_i2c_calc_divs(unsigned long clk_rate,
> -			      struct i2c_timings *t,
> -			      struct rk3x_i2c_calced_timings *t_calc)
> +static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate,
> +				    struct i2c_timings *t,
> +				    struct rk3x_i2c_calced_timings *t_calc)
>   {
>   	unsigned long min_low_ns, min_high_ns;
>   	unsigned long max_low_ns, min_total_ns;
> @@ -661,20 +694,189 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
>   	return ret;
>   }
>   
> +/**
> + * Calculate timing values for desired SCL frequency
> + *
> + * @clk_rate: I2C input clock rate
> + * @t: Known I2C timing information
> + * @t_calc: Caculated rk3x private timings that would be written into regs
> +

miss the '* ' , i guess
> + * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
> + * a best-effort divider value is returned in divs. If the target rate is
> + * too high, we silently use the highest possible rate.
> + * The following formulas are v1's method to calculate timings.
> + *
> + * l = divl + 1;
> + * h = divh + 1;
> + * s = sda_update_config + 1;
> + * u = start_setup_config + 1;
> + * p = stop_setup_config + 1;
> + * T = Tclk_i2c;
> +

Ditto
> + * tHigh = 8 * h * T;
> + * tLow = 8 * l * T;
> +

Ditto
> + * tHD;sda = (l * s + 1) * T;
> + * tSU;sda = [(8 - s) * l + 1] * T;
> + * tI2C = 8 * (l + h) * T;
> +

Ditto
> + * tSU;sta = (8h * u + 1) * T;
> + * tHD;sta = [8h * (u + 1) - 1] * T;
> + * tSU;sto = (8h * p + 1) * T;
> + */
> +static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
> +				    struct i2c_timings *t,
> +				    struct rk3x_i2c_calced_timings *t_calc)
> +{
> +	unsigned long min_low_ns, min_high_ns, min_total_ns;
> +	unsigned long min_setup_start_ns, min_setup_data_ns;
> +	unsigned long min_setup_stop_ns, max_hold_data_ns;
> +
> +	unsigned long clk_rate_khz, scl_rate_khz;
> +
> +	unsigned long min_low_div, min_high_div;
> +
> +	unsigned long min_div_for_hold, min_total_div;
> +	unsigned long extra_div, extra_low_div;
> +	unsigned long sda_update_cfg, stp_sta_cfg, stp_sto_cfg;
> +
> +	const struct i2c_spec_values *spec;
> +	int ret = 0;
> +
> +	/* Support standard-mode and fast-mode */
> +	if (WARN_ON(t->bus_freq_hz > 400000))
> +		t->bus_freq_hz = 400000;
> +
> +	/* prevent scl_rate_khz from becoming 0 */
> +	if (WARN_ON(t->bus_freq_hz < 1000))
> +		t->bus_freq_hz = 1000;
> +
> +	/*
> +	 * min_low_ns: The minimum number of ns we need to hold low to
> +	 *	       meet I2C specification, should include fall time.
> +	 * min_high_ns: The minimum number of ns we need to hold high to
> +	 *	        meet I2C specification, should include rise time.
> +	 */
> +	spec = rk3x_i2c_get_spec(t->bus_freq_hz);
> +
> +	/* calculate min-divh and min-divl */
> +	clk_rate_khz = DIV_ROUND_UP(clk_rate, 1000);
> +	scl_rate_khz = t->bus_freq_hz / 1000;
> +	min_total_div = DIV_ROUND_UP(clk_rate_khz, scl_rate_khz * 8);
> +
> +	min_high_ns = t->scl_rise_ns + spec->min_high_ns;
> +	min_high_div = DIV_ROUND_UP(clk_rate_khz * min_high_ns, 8 * 1000000);
> +
> +	min_low_ns = t->scl_fall_ns + spec->min_low_ns;
> +	min_low_div = DIV_ROUND_UP(clk_rate_khz * min_low_ns, 8 * 1000000);
> +
> +	/*
> +	 * Final divh and divl must be greater than 0, otherwise the
> +	 * hardware would not output the i2c clk.
> +	 */
> +	min_high_div = (min_high_div < 1) ? 2 : min_high_div;
> +	min_low_div = (min_low_div < 1) ? 2 : min_low_div;
> +
> +	/* These are the min dividers needed for min hold times. */
> +	min_div_for_hold = (min_low_div + min_high_div);
> +	min_total_ns = min_low_ns + min_high_ns;
> +
> +	/*
> +	 * This is the maximum divider so we don't go over the maximum.
> +	 * We don't round up here (we round down) since this is a maximum.
> +	 */
> +	 if (min_div_for_hold >= min_total_div) {
> +		/*
> +		 * Time needed to meet hold requirements is important.
> +		 * Just use that.
> +		 */
> +		t_calc->div_low = min_low_div;
> +		t_calc->div_high = min_high_div;
> +	} else {
> +		/*
> +		 * We've got to distribute some time among the low and high
> +		 * so we don't run too fast.
> +		 * We'll try to split things up by the scale of min_low_div and
> +		 * min_high_div, biasing slightly towards having a higher div
> +		 * for low (spend more time low).
> +		 */
> +		extra_div = min_total_div - min_div_for_hold;
> +		extra_low_div = DIV_ROUND_UP(min_low_div * extra_div,
> +					     min_div_for_hold);
> +
> +		t_calc->div_low = min_low_div + extra_low_div;
> +		t_calc->div_high = min_high_div + (extra_div - extra_low_div);
> +	}
> +
> +	/*
> +	 * calculate sda data hold count by the rules, data_upd_st:3
> +	 * is a appropriate value to reduce calculated times.
> +	 */
> +	for (sda_update_cfg = 3; sda_update_cfg > 0; sda_update_cfg--) {
> +		max_hold_data_ns =  DIV_ROUND_UP((sda_update_cfg
> +						 * (t_calc->div_low) + 1)
> +						 * 1000000, clk_rate_khz);
> +		min_setup_data_ns =  DIV_ROUND_UP(((8 - sda_update_cfg)
> +						 * (t_calc->div_low) + 1)
> +						 * 1000000, clk_rate_khz);
> +		if ((max_hold_data_ns < spec->max_data_hold_ns) &&
> +		    (min_setup_data_ns > spec->min_data_setup_ns))
> +			break;
> +	}
> +
> +	/* calculate setup start config */
> +	min_setup_start_ns = t->scl_rise_ns + spec->min_setup_start_ns;
> +	stp_sta_cfg = DIV_ROUND_UP(clk_rate_khz * min_setup_start_ns
> +			   - 1000000, 8 * 1000000 * (t_calc->div_high));
> +
> +	/* calculate setup stop config */
> +	min_setup_stop_ns = t->scl_rise_ns + spec->min_setup_stop_ns;
> +	stp_sto_cfg = DIV_ROUND_UP(clk_rate_khz * min_setup_stop_ns
> +			   - 1000000, 8 * 1000000 * (t_calc->div_high));
> +
> +	t_calc->tuning = REG_CON_SDA_CFG(--sda_update_cfg) |
> +			 REG_CON_STA_CFG(--stp_sta_cfg) |
> +			 REG_CON_STO_CFG(--stp_sto_cfg);
> +
> +	t_calc->div_low--;
> +	t_calc->div_high--;
> +
> +	/* Maximum divider supported by hw is 0xffff */
> +	if (t_calc->div_low > 0xffff) {
> +		t_calc->div_low = 0xffff;
> +		ret = -EINVAL;
> +	}
> +
> +	if (t_calc->div_high > 0xffff) {
> +		t_calc->div_high = 0xffff;
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
>   static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
>   {
>   	struct i2c_timings *t = &i2c->t;
>   	struct rk3x_i2c_calced_timings calc;
>   	u64 t_low_ns, t_high_ns;
> +	u32 val;
>   	int ret;
>   
> -	ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
> +	ret = i2c->soc_data->calc_timings(clk_rate, t, &calc);
>   	WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
>   
> -	clk_enable(i2c->clk);
> +	clk_enable(i2c->pclk);
> +
>   	i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
>   		   REG_CLKDIV);
> -	clk_disable(i2c->clk);
> +
> +	val = i2c_readl(i2c, REG_CON);
> +	val &= ~REG_CON_TUNING_MASK;
> +	val |= calc.tuning;
> +	i2c_writel(i2c, val, REG_CON);
> +
> +	clk_disable(i2c->pclk);
>   
>   	t_low_ns = div_u64(((u64)calc.div_low + 1) * 8 * 1000000000, clk_rate);
>   	t_high_ns = div_u64(((u64)calc.div_high + 1) * 8 * 1000000000,
> @@ -712,7 +914,13 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
>   
>   	switch (event) {
>   	case PRE_RATE_CHANGE:
> -		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &calc) != 0)
> +		/*
> +		 * Try the calculation (but don't store the result) ahead of
> +		 * time to see if we need to block the clock change.  Timings
> +		 * shouldn't actually take effect until rk3x_i2c_adapt_div().
> +		 */
> +		if (i2c->soc_data->calc_timings(ndata->new_rate, &i2c->t,
> +						&calc) != 0)
>   			return NOTIFY_STOP;
>   
>   		/* scale up */
> @@ -822,12 +1030,14 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
>   {
>   	struct rk3x_i2c *i2c = (struct rk3x_i2c *)adap->algo_data;
>   	unsigned long timeout, flags;
> +	u32 val;
>   	int ret = 0;
>   	int i;
>   
>   	spin_lock_irqsave(&i2c->lock, flags);
>   
>   	clk_enable(i2c->clk);
> +	clk_enable(i2c->pclk);
>   
>   	i2c->is_last_msg = false;
>   
> @@ -861,7 +1071,9 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
>   
>   			/* Force a STOP condition without interrupt */
>   			i2c_writel(i2c, 0, REG_IEN);
> -			i2c_writel(i2c, REG_CON_EN | REG_CON_STOP, REG_CON);
> +			val = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK;
> +			val |= REG_CON_EN | REG_CON_STOP;
> +			i2c_writel(i2c, val, REG_CON);
>   
>   			i2c->state = STATE_IDLE;
>   
> @@ -875,7 +1087,9 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
>   		}
>   	}
>   
> +	clk_disable(i2c->pclk);
>   	clk_disable(i2c->clk);
> +
>   	spin_unlock_irqrestore(&i2c->lock, flags);
>   
>   	return ret < 0 ? ret : num;
> @@ -893,18 +1107,27 @@ static const struct i2c_algorithm rk3x_i2c_algorithm = {
>   
>   static const struct rk3x_i2c_soc_data rk3066_soc_data = {
>   	.grf_offset = 0x154,
> +	.calc_timings = rk3x_i2c_v0_calc_timings,
>   };
>   
>   static const struct rk3x_i2c_soc_data rk3188_soc_data = {
>   	.grf_offset = 0x0a4,
> +	.calc_timings = rk3x_i2c_v0_calc_timings,
>   };
>   
>   static const struct rk3x_i2c_soc_data rk3228_soc_data = {
>   	.grf_offset = -1,
> +	.calc_timings = rk3x_i2c_v0_calc_timings,
>   };
>   
>   static const struct rk3x_i2c_soc_data rk3288_soc_data = {
>   	.grf_offset = -1,
> +	.calc_timings = rk3x_i2c_v0_calc_timings,
> +};
> +
> +static const struct rk3x_i2c_soc_data rk3399_soc_data = {
> +	.grf_offset = -1,
> +	.calc_timings = rk3x_i2c_v1_calc_timings,
>   };
>   
>   static const struct of_device_id rk3x_i2c_match[] = {
> @@ -924,6 +1147,10 @@ static const struct of_device_id rk3x_i2c_match[] = {
>   		.compatible = "rockchip,rk3288-i2c",
>   		.data = (void *)&rk3288_soc_data
>   	},
> +	{
> +		.compatible = "rockchip,rk3399-i2c",
> +		.data = (void *)&rk3399_soc_data
> +	},
>   	{},
>   };
>   MODULE_DEVICE_TABLE(of, rk3x_i2c_match);
> @@ -963,12 +1190,6 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
>   	spin_lock_init(&i2c->lock);
>   	init_waitqueue_head(&i2c->wait);
>   
> -	i2c->clk = devm_clk_get(&pdev->dev, NULL);
> -	if (IS_ERR(i2c->clk)) {
> -		dev_err(&pdev->dev, "cannot get clock\n");
> -		return PTR_ERR(i2c->clk);
> -	}
> -
>   	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>   	i2c->regs = devm_ioremap_resource(&pdev->dev, mem);
>   	if (IS_ERR(i2c->regs))
> @@ -1022,17 +1243,44 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
>   
>   	platform_set_drvdata(pdev, i2c);
>   
> +	if (i2c->soc_data->calc_timings == rk3x_i2c_v0_calc_timings) {
> +		/* Only one clock to use for bus clock and peripheral clock */
> +		i2c->clk = devm_clk_get(&pdev->dev, NULL);
> +		i2c->pclk = i2c->clk;
> +	} else {
> +		i2c->clk = devm_clk_get(&pdev->dev, "i2c");
> +		i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
> +	}
> +
> +	if (IS_ERR(i2c->clk)) {
> +		ret = PTR_ERR(i2c->clk);
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(&pdev->dev, "Can't get bus clk: %d\n", ret);
> +		return ret;
> +	}
> +	if (IS_ERR(i2c->pclk)) {
> +		ret = PTR_ERR(i2c->pclk);
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(&pdev->dev, "Can't get periph clk: %d\n", ret);
> +		return ret;
> +	}
> +
>   	ret = clk_prepare(i2c->clk);
>   	if (ret < 0) {
> -		dev_err(&pdev->dev, "Could not prepare clock\n");
> +		dev_err(&pdev->dev, "Can't prepare bus clk: %d\n", ret);
>   		return ret;
>   	}
> +	ret = clk_prepare(i2c->pclk);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "Can't prepare periph clock: %d\n", ret);
> +		goto err_clk;
> +	}
>   
>   	i2c->clk_rate_nb.notifier_call = rk3x_i2c_clk_notifier_cb;
>   	ret = clk_notifier_register(i2c->clk, &i2c->clk_rate_nb);
>   	if (ret != 0) {
>   		dev_err(&pdev->dev, "Unable to register clock notifier\n");
> -		goto err_clk;
> +		goto err_pclk;
>   	}
>   
>   	clk_rate = clk_get_rate(i2c->clk);
> @@ -1050,6 +1298,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
>   
>   err_clk_notifier:
>   	clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb);
> +err_pclk:
> +	clk_unprepare(i2c->pclk);
>   err_clk:
>   	clk_unprepare(i2c->clk);
>   	return ret;
> @@ -1062,6 +1312,7 @@ static int rk3x_i2c_remove(struct platform_device *pdev)
>   	i2c_del_adapter(&i2c->adap);
>   
>   	clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb);
> +	clk_unprepare(i2c->pclk);
>   	clk_unprepare(i2c->clk);
>   
>   	return 0;


-- 
Thanks,
Caesar



From caesar.upstream at gmail.com  Wed May 11 04:44:58 2016
From: caesar.upstream at gmail.com (Caesar Wang)
Date: Wed, 11 May 2016 19:44:58 +0800
Subject: [PATCH v8 8/8] i2c: rk3x: support fast-mode plus for rk3399
In-Reply-To: <1462908794-27333-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908794-27333-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <57331B3A.7050801@gmail.com>



? 2016?05?11? 03:33, David Wu ??:
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> Reviewed-by: Douglas Anderson <dianders at chromium.org>

Tested-by: Caesar Wang <wxt at rock-chips.com>
> ---
> Change in v8:
> - None
>
>   drivers/i2c/busses/i2c-rk3x.c | 21 +++++++++++++++++----
>   1 file changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> index 25ed1ad..0ba25ee 100644
> --- a/drivers/i2c/busses/i2c-rk3x.c
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -126,6 +126,17 @@ static const struct i2c_spec_values fast_mode_spec = {
>   	.min_hold_buffer_ns = 1300,
>   };
>   
> +static const struct i2c_spec_values fast_mode_plus_spec = {
> +	.min_hold_start_ns = 260,
> +	.min_low_ns = 500,
> +	.min_high_ns = 260,
> +	.min_setup_start_ns = 260,
> +	.max_data_hold_ns = 400,
> +	.min_data_setup_ns = 50,
> +	.min_setup_stop_ns = 260,
> +	.min_hold_buffer_ns = 500,
> +};
> +
>   /**
>    * struct rk3x_i2c_calced_timings:
>    * @div_low: Divider output for low
> @@ -531,8 +542,10 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
>   {
>   	if (speed <= 100000)
>   		return &standard_mode_spec;
> -	else
> +	else if (speed <= 400000)
>   		return &fast_mode_spec;
> +	else
> +		return &fast_mode_plus_spec;
>   }
>   
>   /**
> @@ -743,9 +756,9 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
>   	const struct i2c_spec_values *spec;
>   	int ret = 0;
>   
> -	/* Support standard-mode and fast-mode */
> -	if (WARN_ON(t->bus_freq_hz > 400000))
> -		t->bus_freq_hz = 400000;
> +	/* Support standard-mode, fast-mode and fast-mode plus */
> +	if (WARN_ON(t->bus_freq_hz > 1000000))
> +		t->bus_freq_hz = 1000000;
>   
>   	/* prevent scl_rate_khz from becoming 0 */
>   	if (WARN_ON(t->bus_freq_hz < 1000))


-- 
Thanks,
Caesar



From linus.walleij at linaro.org  Wed May 11 04:56:11 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 11 May 2016 13:56:11 +0200
Subject: [PATCH 6/6] pinctrl: mt8173: set GPIO16 to usb iddig mode
In-Reply-To: <1462868614-20602-7-git-send-email-chunfeng.yun@mediatek.com>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462868614-20602-7-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <CACRpkdaeD5mk7LXEWnE0=Xute8-JA-fa4tVt4fYhujEXeq2+9w@mail.gmail.com>

On Tue, May 10, 2016 at 10:23 AM, Chunfeng Yun
<chunfeng.yun at mediatek.com> wrote:

> the default mode of GPIO16 pin is gpio, when set EINT16 to
> IRQ_TYPE_LEVEL_HIGH, no interrupt is triggered, it can be
> fixed when set its default mode as usb iddig.
>
> Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>

This looks like it can be merged orthogonally to all the
other patches, but I don't understand the patch or if it
is correct.

Hongzhou/Yingjoe, can either of you review this patch?

Yours,
Linus Walleij


From k.kozlowski at samsung.com  Wed May 11 05:01:57 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:01:57 +0200
Subject: [PATCH 01/18] clk: samsung: Constify clock init data with clock arrays
Message-ID: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>

samsung_cmu_register_one() can accept pointer to const initialization
data: struct samsung_cmu_info. The members of the latter can also be
pointers to const data.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk.c |  2 +-
 drivers/clk/samsung/clk.h | 16 ++++++++--------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index f38a6c49f744..e4d14589cc4a 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -381,7 +381,7 @@ static void samsung_clk_sleep_init(void __iomem *reg_base,
  */
 struct samsung_clk_provider * __init samsung_cmu_register_one(
 			struct device_node *np,
-			struct samsung_cmu_info *cmu)
+			const struct samsung_cmu_info *cmu)
 {
 	void __iomem *reg_base;
 	struct samsung_clk_provider *ctx;
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index aa872d2c5105..61db98dd01a2 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -330,28 +330,28 @@ struct samsung_clock_reg_cache {
 
 struct samsung_cmu_info {
 	/* list of pll clocks and respective count */
-	struct samsung_pll_clock *pll_clks;
+	const struct samsung_pll_clock *pll_clks;
 	unsigned int nr_pll_clks;
 	/* list of mux clocks and respective count */
-	struct samsung_mux_clock *mux_clks;
+	const struct samsung_mux_clock *mux_clks;
 	unsigned int nr_mux_clks;
 	/* list of div clocks and respective count */
-	struct samsung_div_clock *div_clks;
+	const struct samsung_div_clock *div_clks;
 	unsigned int nr_div_clks;
 	/* list of gate clocks and respective count */
-	struct samsung_gate_clock *gate_clks;
+	const struct samsung_gate_clock *gate_clks;
 	unsigned int nr_gate_clks;
 	/* list of fixed clocks and respective count */
-	struct samsung_fixed_rate_clock *fixed_clks;
+	const struct samsung_fixed_rate_clock *fixed_clks;
 	unsigned int nr_fixed_clks;
 	/* list of fixed factor clocks and respective count */
-	struct samsung_fixed_factor_clock *fixed_factor_clks;
+	const struct samsung_fixed_factor_clock *fixed_factor_clks;
 	unsigned int nr_fixed_factor_clks;
 	/* total number of clocks with IDs assigned*/
 	unsigned int nr_clk_ids;
 
 	/* list and number of clocks registers */
-	unsigned long *clk_regs;
+	const unsigned long *clk_regs;
 	unsigned int nr_clk_regs;
 };
 
@@ -395,7 +395,7 @@ extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
 
 extern struct samsung_clk_provider __init *samsung_cmu_register_one(
 			struct device_node *,
-			struct samsung_cmu_info *);
+			const struct samsung_cmu_info *);
 
 extern unsigned long _get_rate(const char *clk_name);
 
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:01:59 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:01:59 +0200
Subject: [PATCH 03/18] clk: samsung: exynos3250: Constify all clock
 initializers
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-3-git-send-email-k.kozlowski@samsung.com>

All of initialization data can be made const.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos3250.c | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index e26b04fea33b..057c3f0d0e35 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -103,7 +103,7 @@
 #define PWR_CTRL1_USE_CORE1_WFI			(1 << 1)
 #define PWR_CTRL1_USE_CORE0_WFI			(1 << 0)
 
-static unsigned long exynos3250_cmu_clk_regs[] __initdata = {
+static const unsigned long exynos3250_cmu_clk_regs[] __initconst = {
 	SRC_LEFTBUS,
 	DIV_LEFTBUS,
 	GATE_IP_LEFTBUS,
@@ -226,7 +226,7 @@ PNAME(group_sclk_fimd0_p)	= { "xxti", "xusbxti",
 PNAME(mout_mfc_p)		= { "mout_mfc_0", "mout_mfc_1" };
 PNAME(mout_g3d_p)		= { "mout_g3d_0", "mout_g3d_1" };
 
-static struct samsung_fixed_factor_clock fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock fixed_factor_clks[] __initconst = {
 	FFACTOR(0, "sclk_mpll_1600", "mout_mpll", 1, 1, 0),
 	FFACTOR(0, "sclk_mpll_mif", "mout_mpll", 1, 2, 0),
 	FFACTOR(0, "sclk_bpll", "fout_bpll", 1, 2, 0),
@@ -237,7 +237,7 @@ static struct samsung_fixed_factor_clock fixed_factor_clks[] __initdata = {
 	FFACTOR(CLK_FIN_PLL, "fin_pll", "xusbxti", 1, 1, 0),
 };
 
-static struct samsung_mux_clock mux_clks[] __initdata = {
+static const struct samsung_mux_clock mux_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by register address in ascending
 	 * order and then bitfield shift in descending order, as it is done
@@ -326,7 +326,7 @@ static struct samsung_mux_clock mux_clks[] __initdata = {
 			CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_div_clock div_clks[] __initdata = {
+static const struct samsung_div_clock div_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by register address in ascending
 	 * order and then bitfield shift in descending order, as it is done
@@ -429,7 +429,7 @@ static struct samsung_div_clock div_clks[] __initdata = {
 	DIV(CLK_DIV_COPY, "div_copy", "mout_hpm", DIV_CPU1, 0, 3),
 };
 
-static struct samsung_gate_clock gate_clks[] __initdata = {
+static const struct samsung_gate_clock gate_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by register address in ascending
 	 * order and then bitfield shift in descending order, as it is done
@@ -669,7 +669,7 @@ static struct samsung_gate_clock gate_clks[] __initdata = {
 };
 
 /* APLL & MPLL & BPLL & UPLL */
-static struct samsung_pll_rate_table exynos3250_pll_rates[] = {
+static const struct samsung_pll_rate_table exynos3250_pll_rates[] = {
 	PLL_35XX_RATE(1200000000, 400, 4, 1),
 	PLL_35XX_RATE(1100000000, 275, 3, 1),
 	PLL_35XX_RATE(1066000000, 533, 6, 1),
@@ -691,7 +691,7 @@ static struct samsung_pll_rate_table exynos3250_pll_rates[] = {
 };
 
 /* EPLL */
-static struct samsung_pll_rate_table exynos3250_epll_rates[] = {
+static const struct samsung_pll_rate_table exynos3250_epll_rates[] = {
 	PLL_36XX_RATE(800000000, 200, 3, 1,     0),
 	PLL_36XX_RATE(288000000,  96, 2, 2,     0),
 	PLL_36XX_RATE(192000000, 128, 2, 3,     0),
@@ -710,7 +710,7 @@ static struct samsung_pll_rate_table exynos3250_epll_rates[] = {
 };
 
 /* VPLL */
-static struct samsung_pll_rate_table exynos3250_vpll_rates[] = {
+static const struct samsung_pll_rate_table exynos3250_vpll_rates[] __initconst = {
 	PLL_36XX_RATE(600000000, 100, 2, 1,     0),
 	PLL_36XX_RATE(533000000, 266, 3, 2, 32768),
 	PLL_36XX_RATE(519230987, 173, 2, 2,  5046),
@@ -740,7 +740,7 @@ static struct samsung_pll_rate_table exynos3250_vpll_rates[] = {
 	{ /* sentinel */ }
 };
 
-static struct samsung_pll_clock exynos3250_plls[] __initdata = {
+static const struct samsung_pll_clock exynos3250_plls[] __initconst = {
 	PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll",
 		APLL_LOCK, APLL_CON0, exynos3250_pll_rates),
 	PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll",
@@ -772,7 +772,7 @@ static void __init exynos3_core_down_clock(void __iomem *reg_base)
 	__raw_writel(0x0, reg_base + PWR_CTRL2);
 }
 
-static struct samsung_cmu_info cmu_info __initdata = {
+static const struct samsung_cmu_info cmu_info __initconst = {
 	.pll_clks		= exynos3250_plls,
 	.nr_pll_clks		= ARRAY_SIZE(exynos3250_plls),
 	.mux_clks		= mux_clks,
@@ -848,7 +848,7 @@ CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
 #define EPLL_CON2		0x111c
 #define SRC_EPLL		0x1120
 
-static unsigned long exynos3250_cmu_dmc_clk_regs[] __initdata = {
+static const unsigned long exynos3250_cmu_dmc_clk_regs[] __initconst = {
 	BPLL_LOCK,
 	BPLL_CON0,
 	BPLL_CON1,
@@ -874,7 +874,7 @@ PNAME(mout_bpll_p)	= { "fin_pll", "fout_bpll", };
 PNAME(mout_mpll_mif_p)	= { "fin_pll", "sclk_mpll_mif", };
 PNAME(mout_dphy_p)	= { "mout_mpll_mif", "mout_bpll", };
 
-static struct samsung_mux_clock dmc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock dmc_mux_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by register address in ascending
 	 * order and then bitfield shift in descending order, as it is done
@@ -893,7 +893,7 @@ static struct samsung_mux_clock dmc_mux_clks[] __initdata = {
 	MUX(CLK_MOUT_EPLL, "mout_epll", mout_epll_p, SRC_EPLL, 4, 1),
 };
 
-static struct samsung_div_clock dmc_div_clks[] __initdata = {
+static const struct samsung_div_clock dmc_div_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by register address in ascending
 	 * order and then bitfield shift in descending order, as it is done
@@ -910,14 +910,14 @@ static struct samsung_div_clock dmc_div_clks[] __initdata = {
 	DIV(CLK_DIV_DMCD, "div_dmcd", "div_dmc", DIV_DMC1, 11, 3),
 };
 
-static struct samsung_pll_clock exynos3250_dmc_plls[] __initdata = {
+static const struct samsung_pll_clock exynos3250_dmc_plls[] __initconst = {
 	PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll",
 		BPLL_LOCK, BPLL_CON0, exynos3250_pll_rates),
 	PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
 		EPLL_LOCK, EPLL_CON0, exynos3250_epll_rates),
 };
 
-static struct samsung_cmu_info dmc_cmu_info __initdata = {
+static const struct samsung_cmu_info dmc_cmu_info __initconst = {
 	.pll_clks		= exynos3250_dmc_plls,
 	.nr_pll_clks		= ARRAY_SIZE(exynos3250_dmc_plls),
 	.mux_clks		= dmc_mux_clks,
@@ -947,7 +947,7 @@ CLK_OF_DECLARE(exynos3250_cmu_dmc, "samsung,exynos3250-cmu-dmc",
 #define GATE_IP_ISP1		0x804
 #define GATE_SCLK_ISP		0x900
 
-static struct samsung_div_clock isp_div_clks[] __initdata = {
+static const struct samsung_div_clock isp_div_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by register address in ascending
 	 * order and then bitfield shift in descending order, as it is done
@@ -967,7 +967,7 @@ static struct samsung_div_clock isp_div_clks[] __initdata = {
 	DIV(CLK_DIV_MPWM, "div_mpwm", "div_isp1", DIV_ISP1, 0, 3),
 };
 
-static struct samsung_gate_clock isp_gate_clks[] __initdata = {
+static const struct samsung_gate_clock isp_gate_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by register address in ascending
 	 * order and then bitfield shift in descending order, as it is done
@@ -1063,7 +1063,7 @@ static struct samsung_gate_clock isp_gate_clks[] __initdata = {
 		GATE_SCLK_ISP, 0, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info isp_cmu_info __initdata = {
+static const struct samsung_cmu_info isp_cmu_info __initconst = {
 	.div_clks	= isp_div_clks,
 	.nr_div_clks	= ARRAY_SIZE(isp_div_clks),
 	.gate_clks	= isp_gate_clks,
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:00 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:00 +0200
Subject: [PATCH 04/18] clk: samsung: exynos4: Move local function to init
 section
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-4-git-send-email-k.kozlowski@samsung.com>

The local exynos4_get_xom() function is referenced only from other
init-level functions.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos4.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 7b3d0f975987..b599ca30d6d0 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -1211,7 +1211,7 @@ static struct samsung_clock_alias exynos4x12_aliases[] __initdata = {
  * controller is first remapped and the value of XOM[0] bit is read to
  * determine the parent clock.
  */
-static unsigned long exynos4_get_xom(void)
+static unsigned long __init exynos4_get_xom(void)
 {
 	unsigned long xom = 0;
 	void __iomem *chipid_base;
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:01:58 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:01:58 +0200
Subject: [PATCH 02/18] clk: samsung: exynos3250: Move platform driver and
 of_device_id to init section
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-2-git-send-email-k.kozlowski@samsung.com>

The platform_driver and of_device_id structs can be moved to init
section because they are referenced only from subsys_initcall-level
function.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos3250.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index 16575ee874cb..e26b04fea33b 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -1079,12 +1079,12 @@ static int __init exynos3250_cmu_isp_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id exynos3250_cmu_isp_of_match[] = {
+static const struct of_device_id exynos3250_cmu_isp_of_match[] __initconst = {
 	{ .compatible = "samsung,exynos3250-cmu-isp", },
 	{ /* sentinel */ }
 };
 
-static struct platform_driver exynos3250_cmu_isp_driver = {
+static struct platform_driver exynos3250_cmu_isp_driver __initdata = {
 	.driver = {
 		.name = "exynos3250-cmu-isp",
 		.of_match_table = exynos3250_cmu_isp_of_match,
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:03 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:03 +0200
Subject: [PATCH 07/18] clk: samsung: exynos4415: Move PLL rates data to init
 section
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-7-git-send-email-k.kozlowski@samsung.com>

The arrays with initialization data of PLLs can be moved to initconst
section because they are referenced only from other initconst-level
symbols.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos4415.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4415.c b/drivers/clk/samsung/clk-exynos4415.c
index 1a9e9d039a3f..6c9063159717 100644
--- a/drivers/clk/samsung/clk-exynos4415.c
+++ b/drivers/clk/samsung/clk-exynos4415.c
@@ -859,7 +859,7 @@ static const struct samsung_gate_clock exynos4415_gate_clks[] __initconst = {
 /*
  * APLL & MPLL & BPLL & ISP_PLL & DISP_PLL & G3D_PLL
  */
-static const struct samsung_pll_rate_table exynos4415_pll_rates[] = {
+static const struct samsung_pll_rate_table exynos4415_pll_rates[] __initconst = {
 	PLL_35XX_RATE(1600000000, 400, 3,  1),
 	PLL_35XX_RATE(1500000000, 250, 2,  1),
 	PLL_35XX_RATE(1400000000, 175, 3,  0),
@@ -891,7 +891,7 @@ static const struct samsung_pll_rate_table exynos4415_pll_rates[] = {
 };
 
 /* EPLL */
-static const struct samsung_pll_rate_table exynos4415_epll_rates[] = {
+static const struct samsung_pll_rate_table exynos4415_epll_rates[] __initconst = {
 	PLL_36XX_RATE(800000000, 200, 3, 1,     0),
 	PLL_36XX_RATE(288000000,  96, 2, 2,     0),
 	PLL_36XX_RATE(192000000, 128, 2, 3,     0),
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:04 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:04 +0200
Subject: [PATCH 08/18] clk: samsung: exynos5250: Constify all clock
 initializers
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-8-git-send-email-k.kozlowski@samsung.com>

All of initialization data can be made const.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos5250.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 837197db4ffb..f24001dcfb8a 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -117,7 +117,7 @@ static struct samsung_clk_reg_dump *exynos5250_save;
  * list of controller registers to be saved and restored during a
  * suspend/resume cycle.
  */
-static unsigned long exynos5250_clk_regs[] __initdata = {
+static const unsigned long exynos5250_clk_regs[] __initconst = {
 	SRC_CPU,
 	DIV_CPU0,
 	PWR_CTRL1,
@@ -266,23 +266,23 @@ static struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initda
 };
 
 /* fixed rate clocks generated inside the soc */
-static struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initconst = {
 	FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, 0, 24000000),
 	FRATE(0, "sclk_hdmi27m", NULL, 0, 27000000),
 	FRATE(0, "sclk_dptxphy", NULL, 0, 24000000),
 	FRATE(0, "sclk_uhostphy", NULL, 0, 48000000),
 };
 
-static struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initconst = {
 	FFACTOR(0, "fout_mplldiv2", "fout_mpll", 1, 2, 0),
 	FFACTOR(0, "fout_bplldiv2", "fout_bpll", 1, 2, 0),
 };
 
-static struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initconst = {
 	MUX(0, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
 };
 
-static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5250_mux_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by (clock domain, register address,
 	 * bitfield shift) triplet in ascending order. When adding new entries,
@@ -378,7 +378,7 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
 	MUX(0, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
 };
 
-static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos5250_div_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by (clock domain, register address,
 	 * bitfield shift) triplet in ascending order. When adding new entries,
@@ -470,7 +470,7 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
 	DIV(CLK_DIV_I2S2, "div_i2s2", "sclk_audio2", DIV_PERIC5, 8, 6),
 };
 
-static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos5250_gate_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by (clock domain, register address,
 	 * bitfield shift) triplet in ascending order. When adding new entries,
@@ -698,7 +698,7 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
 			GATE_IP_ISP1, 7, 0, 0),
 };
 
-static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
+static const struct samsung_pll_rate_table vpll_24mhz_tbl[] __initconst = {
 	/* sorted in descending order */
 	/* PLL_36XX_RATE(rate, m, p, s, k) */
 	PLL_36XX_RATE(266000000, 266, 3, 3, 0),
@@ -707,7 +707,7 @@ static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
 	{ },
 };
 
-static struct samsung_pll_rate_table epll_24mhz_tbl[] __initdata = {
+static const struct samsung_pll_rate_table epll_24mhz_tbl[] __initconst = {
 	/* sorted in descending order */
 	/* PLL_36XX_RATE(rate, m, p, s, k) */
 	PLL_36XX_RATE(192000000, 64, 2, 2, 0),
@@ -721,7 +721,7 @@ static struct samsung_pll_rate_table epll_24mhz_tbl[] __initdata = {
 	{ },
 };
 
-static struct samsung_pll_rate_table apll_24mhz_tbl[] __initdata = {
+static const struct samsung_pll_rate_table apll_24mhz_tbl[] __initconst = {
 	/* sorted in descending order */
 	/* PLL_35XX_RATE(rate, m, p, s) */
 	PLL_35XX_RATE(1700000000, 425, 6, 0),
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:01 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:01 +0200
Subject: [PATCH 05/18] clk: samsung: exynos4: Constify all clock initializers
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-5-git-send-email-k.kozlowski@samsung.com>

All of initialization data can be made const.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos4.c | 56 +++++++++++++++++++--------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index b599ca30d6d0..a6116f572278 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -169,7 +169,7 @@ static struct samsung_clk_reg_dump *exynos4_save_pll;
  * list of controller registers to be saved and restored during a
  * suspend/resume cycle.
  */
-static unsigned long exynos4210_clk_save[] __initdata = {
+static const unsigned long exynos4210_clk_save[] __initconst = {
 	E4210_SRC_IMAGE,
 	E4210_SRC_LCD1,
 	E4210_SRC_MASK_LCD1,
@@ -181,7 +181,7 @@ static unsigned long exynos4210_clk_save[] __initdata = {
 	PWR_CTRL1,
 };
 
-static unsigned long exynos4x12_clk_save[] __initdata = {
+static const unsigned long exynos4x12_clk_save[] __initconst = {
 	E4X12_GATE_IP_IMAGE,
 	E4X12_GATE_IP_PERIR,
 	E4X12_SRC_CAM1,
@@ -192,7 +192,7 @@ static unsigned long exynos4x12_clk_save[] __initdata = {
 	E4X12_PWR_CTRL2,
 };
 
-static unsigned long exynos4_clk_pll_regs[] __initdata = {
+static const unsigned long exynos4_clk_pll_regs[] __initconst = {
 	EPLL_LOCK,
 	VPLL_LOCK,
 	EPLL_CON0,
@@ -203,7 +203,7 @@ static unsigned long exynos4_clk_pll_regs[] __initdata = {
 	VPLL_CON2,
 };
 
-static unsigned long exynos4_clk_regs[] __initdata = {
+static const unsigned long exynos4_clk_regs[] __initconst = {
 	SRC_LEFTBUS,
 	DIV_LEFTBUS,
 	GATE_IP_LEFTBUS,
@@ -505,28 +505,28 @@ static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata
 };
 
 /* fixed rate clocks generated inside the soc */
-static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initconst = {
 	FRATE(0, "sclk_hdmi24m", NULL, 0, 24000000),
 	FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", "hdmi", 0, 27000000),
 	FRATE(0, "sclk_usbphy0", NULL, 0, 48000000),
 };
 
-static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initconst = {
 	FRATE(0, "sclk_usbphy1", NULL, 0, 48000000),
 };
 
-static struct samsung_fixed_factor_clock exynos4_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock exynos4_fixed_factor_clks[] __initconst = {
 	FFACTOR(0, "sclk_apll_div_2", "sclk_apll", 1, 2, 0),
 	FFACTOR(0, "fout_mpll_div_2", "fout_mpll", 1, 2, 0),
 	FFACTOR(0, "fout_apll_div_2", "fout_apll", 1, 2, 0),
 	FFACTOR(0, "arm_clk_div_2", "div_core2", 1, 2, 0),
 };
 
-static struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initconst = {
 	FFACTOR(0, "sclk_mpll_div_2", "sclk_mpll", 1, 2, 0),
 };
 
-static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initconst = {
 	FFACTOR(0, "sclk_mpll_user_l_div_2", "mout_mpll_user_l", 1, 2, 0),
 	FFACTOR(0, "sclk_mpll_user_r_div_2", "mout_mpll_user_r", 1, 2, 0),
 	FFACTOR(0, "sclk_mpll_user_t_div_2", "mout_mpll_user_t", 1, 2, 0),
@@ -534,7 +534,7 @@ static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initda
 };
 
 /* list of mux clocks supported in all exynos4 soc's */
-static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos4_mux_clks[] __initconst = {
 	MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
 			CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0,
 			"mout_apll"),
@@ -555,11 +555,11 @@ static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
 };
 
 /* list of mux clocks supported in exynos4210 soc */
-static struct samsung_mux_clock exynos4210_mux_early[] __initdata = {
+static const struct samsung_mux_clock exynos4210_mux_early[] __initconst = {
 	MUX(0, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1),
 };
 
-static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos4210_mux_clks[] __initconst = {
 	MUX(0, "mout_gdl", sclk_ampll_p4210, SRC_LEFTBUS, 0, 1),
 	MUX(0, "mout_clkout_leftbus", clkout_left_p4210,
 			CLKOUT_CMU_LEFTBUS, 0, 5),
@@ -622,7 +622,7 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
 };
 
 /* list of mux clocks supported in exynos4x12 soc */
-static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos4x12_mux_clks[] __initconst = {
 	MUX(0, "mout_mpll_user_l", mout_mpll_p, SRC_LEFTBUS, 4, 1),
 	MUX(0, "mout_gdl", mout_gdl_p4x12, SRC_LEFTBUS, 0, 1),
 	MUX(0, "mout_clkout_leftbus", clkout_left_p4x12,
@@ -705,7 +705,7 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
 };
 
 /* list of divider clocks supported in all exynos4 soc's */
-static struct samsung_div_clock exynos4_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos4_div_clks[] __initconst = {
 	DIV(CLK_DIV_GDL, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 3),
 	DIV(0, "div_gpl", "div_gdl", DIV_LEFTBUS, 4, 3),
 	DIV(0, "div_clkout_leftbus", "mout_clkout_leftbus",
@@ -795,7 +795,7 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = {
 };
 
 /* list of divider clocks supported in exynos4210 soc */
-static struct samsung_div_clock exynos4210_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos4210_div_clks[] __initconst = {
 	DIV(CLK_ACLK200, "aclk200", "mout_aclk200", DIV_TOP, 0, 3),
 	DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_IMAGE, 0, 4),
 	DIV(0, "div_fimd1", "mout_fimd1", E4210_DIV_LCD1, 0, 4),
@@ -806,7 +806,7 @@ static struct samsung_div_clock exynos4210_div_clks[] __initdata = {
 };
 
 /* list of divider clocks supported in exynos4x12 soc */
-static struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos4x12_div_clks[] __initconst = {
 	DIV(0, "div_mdnie0", "mout_mdnie0", DIV_LCD0, 4, 4),
 	DIV(0, "div_mdnie_pwm0", "mout_mdnie_pwm0", DIV_LCD0, 8, 4),
 	DIV(0, "div_mdnie_pwm_pre0", "div_mdnie_pwm0", DIV_LCD0, 12, 4),
@@ -837,7 +837,7 @@ static struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
 };
 
 /* list of gate clocks supported in all exynos4 soc's */
-static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos4_gate_clks[] __initconst = {
 	/*
 	 * After all Exynos4 based platforms are migrated to use device tree,
 	 * the device name and clock alias names specified below for some
@@ -1043,7 +1043,7 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
 };
 
 /* list of gate clocks supported in exynos4210 soc */
-static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos4210_gate_clks[] __initconst = {
 	GATE(CLK_TVENC, "tvenc", "aclk160", GATE_IP_TV, 2, 0, 0),
 	GATE(CLK_G2D, "g2d", "aclk200", E4210_GATE_IP_IMAGE, 0, 0, 0),
 	GATE(CLK_ROTATOR, "rotator", "aclk200", E4210_GATE_IP_IMAGE, 1, 0, 0),
@@ -1090,7 +1090,7 @@ static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
 };
 
 /* list of gate clocks supported in exynos4x12 soc */
-static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = {
 	GATE(CLK_AUDSS, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0),
 	GATE(CLK_MDNIE0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0),
 	GATE(CLK_ROTATOR, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0),
@@ -1190,17 +1190,17 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
 		0),
 };
 
-static struct samsung_clock_alias exynos4_aliases[] __initdata = {
+static const struct samsung_clock_alias exynos4_aliases[] __initconst = {
 	ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
 	ALIAS(CLK_ARM_CLK, NULL, "armclk"),
 	ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"),
 };
 
-static struct samsung_clock_alias exynos4210_aliases[] __initdata = {
+static const struct samsung_clock_alias exynos4210_aliases[] __initconst = {
 	ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"),
 };
 
-static struct samsung_clock_alias exynos4x12_aliases[] __initdata = {
+static const struct samsung_clock_alias exynos4x12_aliases[] __initconst = {
 	ALIAS(CLK_MOUT_MPLL_USER_C, NULL, "mout_mpll"),
 };
 
@@ -1264,7 +1264,7 @@ static const struct of_device_id ext_clk_match[] __initconst = {
 };
 
 /* PLLs PMS values */
-static struct samsung_pll_rate_table exynos4210_apll_rates[] __initdata = {
+static const struct samsung_pll_rate_table exynos4210_apll_rates[] __initconst = {
 	PLL_45XX_RATE(1200000000, 150,  3, 1, 28),
 	PLL_45XX_RATE(1000000000, 250,  6, 1, 28),
 	PLL_45XX_RATE( 800000000, 200,  6, 1, 28),
@@ -1277,7 +1277,7 @@ static struct samsung_pll_rate_table exynos4210_apll_rates[] __initdata = {
 	{ /* sentinel */ }
 };
 
-static struct samsung_pll_rate_table exynos4210_epll_rates[] __initdata = {
+static const struct samsung_pll_rate_table exynos4210_epll_rates[] __initconst = {
 	PLL_4600_RATE(192000000, 48, 3, 1,     0, 0),
 	PLL_4600_RATE(180633605, 45, 3, 1, 10381, 0),
 	PLL_4600_RATE(180000000, 45, 3, 1,     0, 0),
@@ -1288,7 +1288,7 @@ static struct samsung_pll_rate_table exynos4210_epll_rates[] __initdata = {
 	{ /* sentinel */ }
 };
 
-static struct samsung_pll_rate_table exynos4210_vpll_rates[] __initdata = {
+static const struct samsung_pll_rate_table exynos4210_vpll_rates[] __initconst = {
 	PLL_4650_RATE(360000000, 44, 3, 0, 1024, 0, 14, 0),
 	PLL_4650_RATE(324000000, 53, 2, 1, 1024, 1,  1, 1),
 	PLL_4650_RATE(259617187, 63, 3, 1, 1950, 0, 20, 1),
@@ -1297,7 +1297,7 @@ static struct samsung_pll_rate_table exynos4210_vpll_rates[] __initdata = {
 	{ /* sentinel */ }
 };
 
-static struct samsung_pll_rate_table exynos4x12_apll_rates[] __initdata = {
+static const struct samsung_pll_rate_table exynos4x12_apll_rates[] __initconst = {
 	PLL_35XX_RATE(1500000000, 250, 4, 0),
 	PLL_35XX_RATE(1400000000, 175, 3, 0),
 	PLL_35XX_RATE(1300000000, 325, 6, 0),
@@ -1315,7 +1315,7 @@ static struct samsung_pll_rate_table exynos4x12_apll_rates[] __initdata = {
 	{ /* sentinel */ }
 };
 
-static struct samsung_pll_rate_table exynos4x12_epll_rates[] __initdata = {
+static const struct samsung_pll_rate_table exynos4x12_epll_rates[] __initconst = {
 	PLL_36XX_RATE(192000000, 48, 3, 1,     0),
 	PLL_36XX_RATE(180633605, 45, 3, 1, 10381),
 	PLL_36XX_RATE(180000000, 45, 3, 1,     0),
@@ -1326,7 +1326,7 @@ static struct samsung_pll_rate_table exynos4x12_epll_rates[] __initdata = {
 	{ /* sentinel */ }
 };
 
-static struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initdata = {
+static const struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initconst = {
 	PLL_36XX_RATE(533000000, 133, 3, 1, 16384),
 	PLL_36XX_RATE(440000000, 110, 3, 1,     0),
 	PLL_36XX_RATE(350000000, 175, 3, 2,     0),
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:07 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:07 +0200
Subject: [PATCH 11/18] clk: samsung: exynos5420: Constify all clock
 initializers
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-11-git-send-email-k.kozlowski@samsung.com>

All of initialization data can be made const.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos5420.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 92382cef9f90..adb0ae4efb7a 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -160,7 +160,7 @@ static struct samsung_clk_reg_dump *exynos5800_save;
  * list of controller registers to be saved and restored during a
  * suspend/resume cycle.
  */
-static unsigned long exynos5x_clk_regs[] __initdata = {
+static const unsigned long exynos5x_clk_regs[] __initconst = {
 	SRC_CPU,
 	DIV_CPU0,
 	DIV_CPU1,
@@ -248,7 +248,7 @@ static unsigned long exynos5x_clk_regs[] __initdata = {
 	DIV_KFC0,
 };
 
-static unsigned long exynos5800_clk_regs[] __initdata = {
+static const unsigned long exynos5800_clk_regs[] __initconst = {
 	SRC_TOP8,
 	SRC_TOP9,
 	SRC_CAM,
@@ -484,7 +484,7 @@ static struct samsung_fixed_rate_clock
 };
 
 /* fixed rate clocks generated inside the soc */
-static struct samsung_fixed_rate_clock exynos5x_fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock exynos5x_fixed_rate_clks[] __initconst = {
 	FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, 0, 24000000),
 	FRATE(0, "sclk_pwi", NULL, 0, 24000000),
 	FRATE(0, "sclk_usbh20", NULL, 0, 48000000),
@@ -492,19 +492,19 @@ static struct samsung_fixed_rate_clock exynos5x_fixed_rate_clks[] __initdata = {
 	FRATE(0, "sclk_usbh20_scan_clk", NULL, 0, 480000000),
 };
 
-static struct samsung_fixed_factor_clock
-		exynos5x_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock
+		exynos5x_fixed_factor_clks[] __initconst = {
 	FFACTOR(0, "ff_hsic_12m", "fin_pll", 1, 2, 0),
 	FFACTOR(0, "ff_sw_aclk66", "mout_sw_aclk66", 1, 2, 0),
 };
 
-static struct samsung_fixed_factor_clock
-		exynos5800_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock
+		exynos5800_fixed_factor_clks[] __initconst = {
 	FFACTOR(0, "ff_dout_epll2", "mout_sclk_epll", 1, 2, 0),
 	FFACTOR(0, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0),
 };
 
-static struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = {
 	MUX(0, "mout_aclk400_isp", mout_group3_5800_p, SRC_TOP0, 0, 3),
 	MUX(0, "mout_aclk400_mscl", mout_group3_5800_p, SRC_TOP0, 4, 3),
 	MUX(0, "mout_aclk400_wcore", mout_group2_5800_p, SRC_TOP0, 16, 3),
@@ -553,7 +553,7 @@ static struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
 	MUX(0, "mout_fimd1", mout_group2_p, SRC_DISP10, 4, 3),
 };
 
-static struct samsung_div_clock exynos5800_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos5800_div_clks[] __initconst = {
 	DIV(CLK_DOUT_ACLK400_WCORE, "dout_aclk400_wcore",
 			"mout_aclk400_wcore", DIV_TOP0, 16, 3),
 	DIV(0, "dout_aclk550_cam", "mout_aclk550_cam",
@@ -569,14 +569,14 @@ static struct samsung_div_clock exynos5800_div_clks[] __initdata = {
 	DIV(0, "dout_sclk_sw", "sclk_spll", DIV_TOP9, 24, 6),
 };
 
-static struct samsung_gate_clock exynos5800_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos5800_gate_clks[] __initconst = {
 	GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam",
 				GATE_BUS_TOP, 24, 0, 0),
 	GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
 				GATE_BUS_TOP, 27, 0, 0),
 };
 
-static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
 	MUX(0, "sclk_bpll", mout_bpll_p, TOP_SPARE2, 0, 1),
 	MUX(0, "mout_aclk400_wcore_bpll", mout_aclk400_wcore_bpll_p,
 				TOP_SPARE2, 4, 1),
@@ -606,12 +606,12 @@ static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
 	MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1),
 };
 
-static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos5420_div_clks[] __initconst = {
 	DIV(CLK_DOUT_ACLK400_WCORE, "dout_aclk400_wcore",
 			"mout_aclk400_wcore_bpll", DIV_TOP0, 16, 3),
 };
 
-static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = {
 	MUX(0, "mout_user_pclk66_gpio", mout_user_pclk66_gpio_p,
 			SRC_TOP7, 4, 1),
 	MUX(0, "mout_mspll_kfc", mout_mspll_cpu_p, SRC_TOP7, 8, 2),
@@ -778,7 +778,7 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
 	MUX(0, "mout_isp_sensor", mout_group2_p, SRC_ISP, 28, 3),
 };
 
-static struct samsung_div_clock exynos5x_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos5x_div_clks[] __initconst = {
 	DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
 	DIV(0, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
 	DIV(0, "armclk2", "div_arm", DIV_CPU0, 28, 3),
@@ -911,7 +911,7 @@ static struct samsung_div_clock exynos5x_div_clks[] __initdata = {
 			CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
 	/* G2D */
 	GATE(CLK_MDMA0, "mdma0", "aclk266_g2d", GATE_IP_G2D, 1, 0, 0),
 	GATE(CLK_SSS, "sss", "aclk266_g2d", GATE_IP_G2D, 2, 0, 0),
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:08 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:08 +0200
Subject: [PATCH 12/18] clk: samsung: exynos5440: Constify all clock
 initializers
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-12-git-send-email-k.kozlowski@samsung.com>

All of initialization data can be made const.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos5440.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
index c57cff1e1798..f4fbe00b2a5b 100644
--- a/drivers/clk/samsung/clk-exynos5440.c
+++ b/drivers/clk/samsung/clk-exynos5440.c
@@ -35,7 +35,7 @@ static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initda
 };
 
 /* fixed rate clocks */
-static struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initconst = {
 	FRATE(0, "ppll", NULL, 0, 1000000000),
 	FRATE(0, "usb_phy0", NULL, 0, 60000000),
 	FRATE(0, "usb_phy1", NULL, 0, 60000000),
@@ -44,26 +44,26 @@ static struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata =
 };
 
 /* fixed factor clocks */
-static struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initconst = {
 	FFACTOR(0, "div250", "ppll", 1, 4, 0),
 	FFACTOR(0, "div200", "ppll", 1, 5, 0),
 	FFACTOR(0, "div125", "div250", 1, 2, 0),
 };
 
 /* mux clocks */
-static struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5440_mux_clks[] __initconst = {
 	MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
 	MUX_A(CLK_ARM_CLK, "arm_clk", mout_armclk_p,
 			CPU_CLK_STATUS, 0, 1, "armclk"),
 };
 
 /* divider clocks */
-static struct samsung_div_clock exynos5440_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos5440_div_clks[] __initconst = {
 	DIV(CLK_SPI_BAUD, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
 };
 
 /* gate clocks */
-static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos5440_gate_clks[] __initconst = {
 	GATE(CLK_PB0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
 	GATE(CLK_PR0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
 	GATE(CLK_PR1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:02 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:02 +0200
Subject: [PATCH 06/18] clk: samsung: exynos4415: Constify all clock
 initializers
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-6-git-send-email-k.kozlowski@samsung.com>

All of initialization data can be made const.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos4415.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4415.c b/drivers/clk/samsung/clk-exynos4415.c
index 86ee06b226bd..1a9e9d039a3f 100644
--- a/drivers/clk/samsung/clk-exynos4415.c
+++ b/drivers/clk/samsung/clk-exynos4415.c
@@ -111,7 +111,7 @@
 #define DIV_CPU0		0x14500
 #define DIV_CPU1		0x14504
 
-static unsigned long exynos4415_cmu_clk_regs[] __initdata = {
+static const unsigned long exynos4415_cmu_clk_regs[] __initconst = {
 	SRC_LEFTBUS,
 	DIV_LEFTBUS,
 	GATE_IP_LEFTBUS,
@@ -268,16 +268,16 @@ PNAME(group_aclk_isp0_300_user_p) = { "fin_pll", "mout_aclk_isp0_300" };
 PNAME(group_aclk_isp1_300_user_p) = { "fin_pll", "mout_aclk_isp1_300" };
 PNAME(group_mout_mpll_user_t_p)	= { "mout_mpll_user_t" };
 
-static struct samsung_fixed_factor_clock exynos4415_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock exynos4415_fixed_factor_clks[] __initconst = {
 	/* HACK: fin_pll hardcoded to xusbxti until detection is implemented. */
 	FFACTOR(CLK_FIN_PLL, "fin_pll", "xusbxti", 1, 1, 0),
 };
 
-static struct samsung_fixed_rate_clock exynos4415_fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock exynos4415_fixed_rate_clks[] __initconst = {
 	FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, 0, 27000000),
 };
 
-static struct samsung_mux_clock exynos4415_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos4415_mux_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by register address in ascending
 	 * order and then bitfield shift in descending order, as it is done
@@ -427,7 +427,7 @@ static struct samsung_mux_clock exynos4415_mux_clks[] __initdata = {
 		group_aclk_isp1_300_user_p, SRC_TOP_ISP1, 0, 1),
 };
 
-static struct samsung_div_clock exynos4415_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos4415_div_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by register address in ascending
 	 * order and then bitfield shift in descending order, as it is done
@@ -566,7 +566,7 @@ static struct samsung_div_clock exynos4415_div_clks[] __initdata = {
 	DIV(CLK_DIV_COPY, "div_copy", "mout_hpm", DIV_CPU1, 0, 3),
 };
 
-static struct samsung_gate_clock exynos4415_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos4415_gate_clks[] __initconst = {
 	/*
 	 * NOTE: Following table is sorted by register address in ascending
 	 * order and then bitfield shift in descending order, as it is done
@@ -859,7 +859,7 @@ static struct samsung_gate_clock exynos4415_gate_clks[] __initdata = {
 /*
  * APLL & MPLL & BPLL & ISP_PLL & DISP_PLL & G3D_PLL
  */
-static struct samsung_pll_rate_table exynos4415_pll_rates[] = {
+static const struct samsung_pll_rate_table exynos4415_pll_rates[] = {
 	PLL_35XX_RATE(1600000000, 400, 3,  1),
 	PLL_35XX_RATE(1500000000, 250, 2,  1),
 	PLL_35XX_RATE(1400000000, 175, 3,  0),
@@ -891,7 +891,7 @@ static struct samsung_pll_rate_table exynos4415_pll_rates[] = {
 };
 
 /* EPLL */
-static struct samsung_pll_rate_table exynos4415_epll_rates[] = {
+static const struct samsung_pll_rate_table exynos4415_epll_rates[] = {
 	PLL_36XX_RATE(800000000, 200, 3, 1,     0),
 	PLL_36XX_RATE(288000000,  96, 2, 2,     0),
 	PLL_36XX_RATE(192000000, 128, 2, 3,     0),
@@ -909,7 +909,7 @@ static struct samsung_pll_rate_table exynos4415_epll_rates[] = {
 	{ /* sentinel */ }
 };
 
-static struct samsung_pll_clock exynos4415_plls[] __initdata = {
+static const struct samsung_pll_clock exynos4415_plls[] __initconst = {
 	PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll",
 		APLL_LOCK, APLL_CON0, exynos4415_pll_rates),
 	PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
@@ -922,7 +922,7 @@ static struct samsung_pll_clock exynos4415_plls[] __initdata = {
 		"fin_pll", DISP_PLL_LOCK, DISP_PLL_CON0, exynos4415_pll_rates),
 };
 
-static struct samsung_cmu_info cmu_info __initdata = {
+static const struct samsung_cmu_info cmu_info __initconst = {
 	.pll_clks		= exynos4415_plls,
 	.nr_pll_clks		= ARRAY_SIZE(exynos4415_plls),
 	.mux_clks		= exynos4415_mux_clks,
@@ -961,7 +961,7 @@ CLK_OF_DECLARE(exynos4415_cmu, "samsung,exynos4415-cmu", exynos4415_cmu_init);
 #define SRC_DMC			0x300
 #define DIV_DMC1		0x504
 
-static unsigned long exynos4415_cmu_dmc_clk_regs[] __initdata = {
+static const unsigned long exynos4415_cmu_dmc_clk_regs[] __initconst = {
 	MPLL_LOCK,
 	MPLL_CON0,
 	MPLL_CON1,
@@ -978,14 +978,14 @@ PNAME(mout_mpll_p)		= { "fin_pll", "fout_mpll", };
 PNAME(mout_bpll_p)		= { "fin_pll", "fout_bpll", };
 PNAME(mbpll_p)			= { "mout_mpll", "mout_bpll", };
 
-static struct samsung_mux_clock exynos4415_dmc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos4415_dmc_mux_clks[] __initconst = {
 	MUX(CLK_DMC_MOUT_MPLL, "mout_mpll", mout_mpll_p, SRC_DMC, 12, 1),
 	MUX(CLK_DMC_MOUT_BPLL, "mout_bpll", mout_bpll_p, SRC_DMC, 10, 1),
 	MUX(CLK_DMC_MOUT_DPHY, "mout_dphy", mbpll_p, SRC_DMC, 8, 1),
 	MUX(CLK_DMC_MOUT_DMC_BUS, "mout_dmc_bus", mbpll_p, SRC_DMC, 4, 1),
 };
 
-static struct samsung_div_clock exynos4415_dmc_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos4415_dmc_div_clks[] __initconst = {
 	DIV(CLK_DMC_DIV_DMC, "div_dmc", "div_dmc_pre", DIV_DMC1, 27, 3),
 	DIV(CLK_DMC_DIV_DPHY, "div_dphy", "mout_dphy", DIV_DMC1, 23, 3),
 	DIV(CLK_DMC_DIV_DMC_PRE, "div_dmc_pre", "mout_dmc_bus",
@@ -995,14 +995,14 @@ static struct samsung_div_clock exynos4415_dmc_div_clks[] __initdata = {
 	DIV(CLK_DMC_DIV_MPLL_PRE, "div_mpll_pre", "mout_mpll", DIV_DMC1, 8, 2),
 };
 
-static struct samsung_pll_clock exynos4415_dmc_plls[] __initdata = {
+static const struct samsung_pll_clock exynos4415_dmc_plls[] __initconst = {
 	PLL(pll_35xx, CLK_DMC_FOUT_MPLL, "fout_mpll", "fin_pll",
 		MPLL_LOCK, MPLL_CON0, exynos4415_pll_rates),
 	PLL(pll_35xx, CLK_DMC_FOUT_BPLL, "fout_bpll", "fin_pll",
 		BPLL_LOCK, BPLL_CON0, exynos4415_pll_rates),
 };
 
-static struct samsung_cmu_info cmu_dmc_info __initdata = {
+static const struct samsung_cmu_info cmu_dmc_info __initconst = {
 	.pll_clks		= exynos4415_dmc_plls,
 	.nr_pll_clks		= ARRAY_SIZE(exynos4415_dmc_plls),
 	.mux_clks		= exynos4415_dmc_mux_clks,
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:11 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:11 +0200
Subject: [PATCH 15/18] clk: samsung: exynos5433: Move PLL rates data to init
 section
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-15-git-send-email-k.kozlowski@samsung.com>

The arrays with initialization data of PLLs can be moved to initconst
section because they are referenced only from other initconst-level
symbols.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos5433.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index f202a51ff99b..5993bd5ac6ba 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -693,7 +693,7 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
  * ATLAS_PLL & APOLLO_PLL & MEM0_PLL & MEM1_PLL & BUS_PLL & MFC_PLL
  * & MPHY_PLL & G3D_PLL & DISP_PLL & ISP_PLL
  */
-static const struct samsung_pll_rate_table exynos5443_pll_rates[] = {
+static const struct samsung_pll_rate_table exynos5443_pll_rates[] __initconst = {
 	PLL_35XX_RATE(2500000000U, 625, 6,  0),
 	PLL_35XX_RATE(2400000000U, 500, 5,  0),
 	PLL_35XX_RATE(2300000000U, 575, 6,  0),
@@ -744,7 +744,7 @@ static const struct samsung_pll_rate_table exynos5443_pll_rates[] = {
 };
 
 /* AUD_PLL */
-static const struct samsung_pll_rate_table exynos5443_aud_pll_rates[] = {
+static const struct samsung_pll_rate_table exynos5443_aud_pll_rates[] __initconst = {
 	PLL_36XX_RATE(400000000U, 200, 3, 2,      0),
 	PLL_36XX_RATE(393216000U, 197, 3, 2, -25690),
 	PLL_36XX_RATE(384000000U, 128, 2, 2,      0),
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:13 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:13 +0200
Subject: [PATCH 17/18] clk: samsung: exynos5250: Move sleep init function to
 init section
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-17-git-send-email-k.kozlowski@samsung.com>

The exynos5250_clk_sleep_init() function can be moved to init section
because it is referenced only from other init-level calls.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos5250.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index f24001dcfb8a..bf5ce1baf636 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -190,7 +190,7 @@ static struct syscore_ops exynos5250_clk_syscore_ops = {
 	.resume = exynos5250_clk_resume,
 };
 
-static void exynos5250_clk_sleep_init(void)
+static void __init exynos5250_clk_sleep_init(void)
 {
 	exynos5250_save = samsung_clk_alloc_reg_dump(exynos5250_clk_regs,
 					ARRAY_SIZE(exynos5250_clk_regs));
@@ -203,7 +203,7 @@ static void exynos5250_clk_sleep_init(void)
 	register_syscore_ops(&exynos5250_clk_syscore_ops);
 }
 #else
-static void exynos5250_clk_sleep_init(void) {}
+static void __init exynos5250_clk_sleep_init(void) {}
 #endif
 
 /* list of all parent clock list */
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:10 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:10 +0200
Subject: [PATCH 14/18] clk: samsung: exynos5433: Constify all clock
 initializers
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-14-git-send-email-k.kozlowski@samsung.com>

All of initialization data can be made const.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos5433.c | 240 +++++++++++++++++------------------
 1 file changed, 120 insertions(+), 120 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 128527b8fbeb..f202a51ff99b 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -108,7 +108,7 @@
 #define ENABLE_CMU_TOP			0x0c00
 #define ENABLE_CMU_TOP_DIV_STAT		0x0c04
 
-static unsigned long top_clk_regs[] __initdata = {
+static const unsigned long top_clk_regs[] __initconst = {
 	ISP_PLL_LOCK,
 	AUD_PLL_LOCK,
 	ISP_PLL_CON0,
@@ -218,11 +218,11 @@ PNAME(mout_sclk_audio0_p)	= { "ioclk_audiocdclk0", "oscclk",
 
 PNAME(mout_sclk_hdmi_spdif_p)	= { "sclk_audio1", "ioclk_spdif_extclk", };
 
-static struct samsung_fixed_factor_clock top_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock top_fixed_factor_clks[] __initconst = {
 	FFACTOR(0, "oscclk_efuse_common", "oscclk", 1, 1, 0),
 };
 
-static struct samsung_fixed_rate_clock top_fixed_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock top_fixed_clks[] __initconst = {
 	/* Xi2s{0|1}CDCLK input clock for I2S/PCM */
 	FRATE(0, "ioclk_audiocdclk1", NULL, 0, 100000000),
 	FRATE(0, "ioclk_audiocdclk0", NULL, 0, 100000000),
@@ -238,7 +238,7 @@ static struct samsung_fixed_rate_clock top_fixed_clks[] __initdata = {
 	FRATE(0, "ioclk_i2s1_bclk_in", NULL, 0, 12288000),
 };
 
-static struct samsung_mux_clock top_mux_clks[] __initdata = {
+static const struct samsung_mux_clock top_mux_clks[] __initconst = {
 	/* MUX_SEL_TOP0 */
 	MUX(CLK_MOUT_AUD_PLL, "mout_aud_pll", mout_aud_pll_p, MUX_SEL_TOP0,
 			4, 1),
@@ -374,7 +374,7 @@ static struct samsung_mux_clock top_mux_clks[] __initdata = {
 			mout_sclk_hdmi_spdif_p, MUX_SEL_TOP_DISP, 0, 1),
 };
 
-static struct samsung_div_clock top_div_clks[] __initdata = {
+static const struct samsung_div_clock top_div_clks[] __initconst = {
 	/* DIV_TOP0 */
 	DIV(CLK_DIV_ACLK_CAM1_333, "div_aclk_cam1_333", "mout_aclk_cam1_333",
 			DIV_TOP0, 28, 3),
@@ -538,7 +538,7 @@ static struct samsung_div_clock top_div_clks[] __initdata = {
 			DIV_TOP_PERIC4, 0, 4),
 };
 
-static struct samsung_gate_clock top_gate_clks[] __initdata = {
+static const struct samsung_gate_clock top_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_TOP */
 	GATE(CLK_ACLK_G3D_400, "aclk_g3d_400", "div_aclk_g3d_400",
 			ENABLE_ACLK_TOP, 30, 0, 0),
@@ -693,7 +693,7 @@ static struct samsung_gate_clock top_gate_clks[] __initdata = {
  * ATLAS_PLL & APOLLO_PLL & MEM0_PLL & MEM1_PLL & BUS_PLL & MFC_PLL
  * & MPHY_PLL & G3D_PLL & DISP_PLL & ISP_PLL
  */
-static struct samsung_pll_rate_table exynos5443_pll_rates[] = {
+static const struct samsung_pll_rate_table exynos5443_pll_rates[] = {
 	PLL_35XX_RATE(2500000000U, 625, 6,  0),
 	PLL_35XX_RATE(2400000000U, 500, 5,  0),
 	PLL_35XX_RATE(2300000000U, 575, 6,  0),
@@ -744,7 +744,7 @@ static struct samsung_pll_rate_table exynos5443_pll_rates[] = {
 };
 
 /* AUD_PLL */
-static struct samsung_pll_rate_table exynos5443_aud_pll_rates[] = {
+static const struct samsung_pll_rate_table exynos5443_aud_pll_rates[] = {
 	PLL_36XX_RATE(400000000U, 200, 3, 2,      0),
 	PLL_36XX_RATE(393216000U, 197, 3, 2, -25690),
 	PLL_36XX_RATE(384000000U, 128, 2, 2,      0),
@@ -757,14 +757,14 @@ static struct samsung_pll_rate_table exynos5443_aud_pll_rates[] = {
 	{ /* sentinel */ }
 };
 
-static struct samsung_pll_clock top_pll_clks[] __initdata = {
+static const struct samsung_pll_clock top_pll_clks[] __initconst = {
 	PLL(pll_35xx, CLK_FOUT_ISP_PLL, "fout_isp_pll", "oscclk",
 		ISP_PLL_LOCK, ISP_PLL_CON0, exynos5443_pll_rates),
 	PLL(pll_36xx, CLK_FOUT_AUD_PLL, "fout_aud_pll", "oscclk",
 		AUD_PLL_LOCK, AUD_PLL_CON0, exynos5443_aud_pll_rates),
 };
 
-static struct samsung_cmu_info top_cmu_info __initdata = {
+static const struct samsung_cmu_info top_cmu_info __initconst = {
 	.pll_clks		= top_pll_clks,
 	.nr_pll_clks		= ARRAY_SIZE(top_pll_clks),
 	.mux_clks		= top_mux_clks,
@@ -800,7 +800,7 @@ CLK_OF_DECLARE(exynos5433_cmu_top, "samsung,exynos5433-cmu-top",
 #define DIV_CPIF		0x0600
 #define ENABLE_SCLK_CPIF	0x0a00
 
-static unsigned long cpif_clk_regs[] __initdata = {
+static const unsigned long cpif_clk_regs[] __initconst = {
 	MPHY_PLL_LOCK,
 	MPHY_PLL_CON0,
 	MPHY_PLL_CON1,
@@ -813,24 +813,24 @@ static unsigned long cpif_clk_regs[] __initdata = {
 /* list of all parent clock list */
 PNAME(mout_mphy_pll_p)		= { "oscclk", "fout_mphy_pll", };
 
-static struct samsung_pll_clock cpif_pll_clks[] __initdata = {
+static const struct samsung_pll_clock cpif_pll_clks[] __initconst = {
 	PLL(pll_35xx, CLK_FOUT_MPHY_PLL, "fout_mphy_pll", "oscclk",
 		MPHY_PLL_LOCK, MPHY_PLL_CON0, exynos5443_pll_rates),
 };
 
-static struct samsung_mux_clock cpif_mux_clks[] __initdata = {
+static const struct samsung_mux_clock cpif_mux_clks[] __initconst = {
 	/* MUX_SEL_CPIF0 */
 	MUX(CLK_MOUT_MPHY_PLL, "mout_mphy_pll", mout_mphy_pll_p, MUX_SEL_CPIF0,
 			0, 1),
 };
 
-static struct samsung_div_clock cpif_div_clks[] __initdata = {
+static const struct samsung_div_clock cpif_div_clks[] __initconst = {
 	/* DIV_CPIF */
 	DIV(CLK_DIV_SCLK_MPHY, "div_sclk_mphy", "mout_mphy_pll", DIV_CPIF,
 			0, 6),
 };
 
-static struct samsung_gate_clock cpif_gate_clks[] __initdata = {
+static const struct samsung_gate_clock cpif_gate_clks[] __initconst = {
 	/* ENABLE_SCLK_CPIF */
 	GATE(CLK_SCLK_MPHY_PLL, "sclk_mphy_pll", "mout_mphy_pll",
 			ENABLE_SCLK_CPIF, 9, 0, 0),
@@ -838,7 +838,7 @@ static struct samsung_gate_clock cpif_gate_clks[] __initdata = {
 			ENABLE_SCLK_CPIF, 4, 0, 0),
 };
 
-static struct samsung_cmu_info cpif_cmu_info __initdata = {
+static const struct samsung_cmu_info cpif_cmu_info __initconst = {
 	.pll_clks		= cpif_pll_clks,
 	.nr_pll_clks		= ARRAY_SIZE(cpif_pll_clks),
 	.mux_clks		= cpif_mux_clks,
@@ -939,7 +939,7 @@ CLK_OF_DECLARE(exynos5433_cmu_cpif, "samsung,exynos5433-cmu-cpif",
 #define PAUSE				0x1008
 #define DDRPHY_LOCK_CTRL		0x100c
 
-static unsigned long mif_clk_regs[] __initdata = {
+static const unsigned long mif_clk_regs[] __initconst = {
 	MEM0_PLL_LOCK,
 	MEM1_PLL_LOCK,
 	BUS_PLL_LOCK,
@@ -1004,7 +1004,7 @@ static unsigned long mif_clk_regs[] __initdata = {
 	DDRPHY_LOCK_CTRL,
 };
 
-static struct samsung_pll_clock mif_pll_clks[] __initdata = {
+static const struct samsung_pll_clock mif_pll_clks[] __initconst = {
 	PLL(pll_35xx, CLK_FOUT_MEM0_PLL, "fout_mem0_pll", "oscclk",
 		MEM0_PLL_LOCK, MEM0_PLL_CON0, exynos5443_pll_rates),
 	PLL(pll_35xx, CLK_FOUT_MEM1_PLL, "fout_mem1_pll", "oscclk",
@@ -1065,7 +1065,7 @@ PNAME(mout_sclk_decon_tv_vclk_b_p) = { "mout_sclk_decon_tv_vclk_a",
 PNAME(mout_sclk_dsim1_c_p)	= { "mout_sclk_dsim1_b", "sclk_mphy_pll", };
 PNAME(mout_sclk_dsim1_b_p)	= { "mout_sclk_dsim1_a", "mout_mfc_pll_div2",};
 
-static struct samsung_fixed_factor_clock mif_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock mif_fixed_factor_clks[] __initconst = {
 	/* dout_{mfc|bus|mem1|mem0}_pll is half fixed rate from parent mux */
 	FFACTOR(CLK_DOUT_MFC_PLL, "dout_mfc_pll", "mout_mfc_pll", 1, 1, 0),
 	FFACTOR(CLK_DOUT_BUS_PLL, "dout_bus_pll", "mout_bus_pll", 1, 1, 0),
@@ -1073,7 +1073,7 @@ static struct samsung_fixed_factor_clock mif_fixed_factor_clks[] __initdata = {
 	FFACTOR(CLK_DOUT_MEM0_PLL, "dout_mem0_pll", "mout_mem0_pll", 1, 1, 0),
 };
 
-static struct samsung_mux_clock mif_mux_clks[] __initdata = {
+static const struct samsung_mux_clock mif_mux_clks[] __initconst = {
 	/* MUX_SEL_MIF0 */
 	MUX(CLK_MOUT_MFC_PLL_DIV2, "mout_mfc_pll_div2", mout_mfc_pll_div2_p,
 			MUX_SEL_MIF0, 28, 1),
@@ -1169,7 +1169,7 @@ static struct samsung_mux_clock mif_mux_clks[] __initdata = {
 			MUX_SEL_MIF7, 0, 1),
 };
 
-static struct samsung_div_clock mif_div_clks[] __initdata = {
+static const struct samsung_div_clock mif_div_clks[] __initconst = {
 	/* DIV_MIF1 */
 	DIV(CLK_DIV_SCLK_HPM_MIF, "div_sclk_hpm_mif", "div_clk2x_phy",
 			DIV_MIF1, 16, 2),
@@ -1223,7 +1223,7 @@ static struct samsung_div_clock mif_div_clks[] __initdata = {
 			0, 3),
 };
 
-static struct samsung_gate_clock mif_gate_clks[] __initdata = {
+static const struct samsung_gate_clock mif_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_MIF0 */
 	GATE(CLK_CLK2X_PHY1, "clk2k_phy1", "div_clk2x_phy", ENABLE_ACLK_MIF0,
 			19, CLK_IGNORE_UNUSED, 0),
@@ -1486,7 +1486,7 @@ static struct samsung_gate_clock mif_gate_clks[] __initdata = {
 			ENABLE_SCLK_MIF, 0, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info mif_cmu_info __initdata = {
+static const struct samsung_cmu_info mif_cmu_info __initconst = {
 	.pll_clks		= mif_pll_clks,
 	.nr_pll_clks		= ARRAY_SIZE(mif_pll_clks),
 	.mux_clks		= mif_mux_clks,
@@ -1522,7 +1522,7 @@ CLK_OF_DECLARE(exynos5433_cmu_mif, "samsung,exynos5433-cmu-mif",
 #define ENABLE_IP_PERIC1		0x0B04
 #define ENABLE_IP_PERIC2		0x0B08
 
-static unsigned long peric_clk_regs[] __initdata = {
+static const unsigned long peric_clk_regs[] __initconst = {
 	DIV_PERIC,
 	ENABLE_ACLK_PERIC,
 	ENABLE_PCLK_PERIC0,
@@ -1533,13 +1533,13 @@ static unsigned long peric_clk_regs[] __initdata = {
 	ENABLE_IP_PERIC2,
 };
 
-static struct samsung_div_clock peric_div_clks[] __initdata = {
+static const struct samsung_div_clock peric_div_clks[] __initconst = {
 	/* DIV_PERIC */
 	DIV(CLK_DIV_SCLK_SCI, "div_sclk_sci", "oscclk", DIV_PERIC, 4, 4),
 	DIV(CLK_DIV_SCLK_SC_IN, "div_sclk_sc_in", "oscclk", DIV_PERIC, 0, 4),
 };
 
-static struct samsung_gate_clock peric_gate_clks[] __initdata = {
+static const struct samsung_gate_clock peric_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_PERIC */
 	GATE(CLK_ACLK_AHB2APB_PERIC2P, "aclk_ahb2apb_peric2p", "aclk_peric_66",
 			ENABLE_ACLK_PERIC, 3, CLK_IGNORE_UNUSED, 0),
@@ -1681,7 +1681,7 @@ static struct samsung_gate_clock peric_gate_clks[] __initdata = {
 			ENABLE_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_cmu_info peric_cmu_info __initdata = {
+static const struct samsung_cmu_info peric_cmu_info __initconst = {
 	.div_clks		= peric_div_clks,
 	.nr_div_clks		= ARRAY_SIZE(peric_div_clks),
 	.gate_clks		= peric_gate_clks,
@@ -1728,7 +1728,7 @@ CLK_OF_DECLARE(exynos5433_cmu_peric, "samsung,exynos5433-cmu-peric",
 #define ENABLE_IP_PERIS_SECURE_ANTIBRK_CNT		0x0b1c
 #define ENABLE_IP_PERIS_SECURE_OTP_CON			0x0b20
 
-static unsigned long peris_clk_regs[] __initdata = {
+static const unsigned long peris_clk_regs[] __initconst = {
 	ENABLE_ACLK_PERIS,
 	ENABLE_PCLK_PERIS,
 	ENABLE_PCLK_PERIS_SECURE_TZPC,
@@ -1756,7 +1756,7 @@ static unsigned long peris_clk_regs[] __initdata = {
 	ENABLE_IP_PERIS_SECURE_OTP_CON,
 };
 
-static struct samsung_gate_clock peris_gate_clks[] __initdata = {
+static const struct samsung_gate_clock peris_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_PERIS */
 	GATE(CLK_ACLK_AHB2APB_PERIS1P, "aclk_ahb2apb_peris1p", "aclk_peris_66",
 			ENABLE_ACLK_PERIS, 2, CLK_IGNORE_UNUSED, 0),
@@ -1875,7 +1875,7 @@ static struct samsung_gate_clock peris_gate_clks[] __initdata = {
 			ENABLE_SCLK_PERIS_SECURE_OTP_CON, 0, 0, 0),
 };
 
-static struct samsung_cmu_info peris_cmu_info __initdata = {
+static const struct samsung_cmu_info peris_cmu_info __initconst = {
 	.gate_clks		= peris_gate_clks,
 	.nr_gate_clks		= ARRAY_SIZE(peris_gate_clks),
 	.nr_clk_ids		= PERIS_NR_CLK,
@@ -1959,7 +1959,7 @@ PNAME(mout_sclk_mphy_p)
 		= { "mout_sclk_ufs_mphy_user",
 			    "mout_phyclk_lli_mphy_to_ufs_user", };
 
-static unsigned long fsys_clk_regs[] __initdata = {
+static const unsigned long fsys_clk_regs[] __initconst = {
 	MUX_SEL_FSYS0,
 	MUX_SEL_FSYS1,
 	MUX_SEL_FSYS2,
@@ -1980,7 +1980,7 @@ static unsigned long fsys_clk_regs[] __initdata = {
 	ENABLE_IP_FSYS1,
 };
 
-static struct samsung_fixed_rate_clock fsys_fixed_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock fsys_fixed_clks[] __initconst = {
 	/* PHY clocks from USBDRD30_PHY */
 	FRATE(CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_PHY,
 			"phyclk_usbdrd30_udrd30_phyclock_phy", NULL,
@@ -2020,7 +2020,7 @@ static struct samsung_fixed_rate_clock fsys_fixed_clks[] __initdata = {
 			NULL, 0, 26000000),
 };
 
-static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
+static const struct samsung_mux_clock fsys_mux_clks[] __initconst = {
 	/* MUX_SEL_FSYS0 */
 	MUX(CLK_MOUT_SCLK_UFS_MPHY_USER, "mout_sclk_ufs_mphy_user",
 			mout_sclk_ufs_mphy_user_p, MUX_SEL_FSYS0, 4, 1),
@@ -2104,7 +2104,7 @@ static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
 			MUX_SEL_FSYS4, 0, 1),
 };
 
-static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
+static const struct samsung_gate_clock fsys_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_FSYS0 */
 	GATE(CLK_ACLK_PCIE, "aclk_pcie", "mout_aclk_fsys_200_user",
 			ENABLE_ACLK_FSYS0, 13, CLK_IGNORE_UNUSED, 0),
@@ -2274,7 +2274,7 @@ static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
 	GATE(CLK_PDMA0, "pdma0", "aclk_pdma0", ENABLE_IP_FSYS0, 0, 0, 0),
 };
 
-static struct samsung_cmu_info fsys_cmu_info __initdata = {
+static const struct samsung_cmu_info fsys_cmu_info __initconst = {
 	.mux_clks		= fsys_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(fsys_mux_clks),
 	.gate_clks		= fsys_gate_clks,
@@ -2310,7 +2310,7 @@ CLK_OF_DECLARE(exynos5433_cmu_fsys, "samsung,exynos5433-cmu-fsys",
 #define DIV_ENABLE_IP_G2D1			0x0b04
 #define DIV_ENABLE_IP_G2D_SECURE_SMMU_G2D	0x0b08
 
-static unsigned long g2d_clk_regs[] __initdata = {
+static const unsigned long g2d_clk_regs[] __initconst = {
 	MUX_SEL_G2D0,
 	MUX_SEL_ENABLE_G2D0,
 	DIV_G2D,
@@ -2327,7 +2327,7 @@ static unsigned long g2d_clk_regs[] __initdata = {
 PNAME(mout_aclk_g2d_266_user_p)		= { "oscclk", "aclk_g2d_266", };
 PNAME(mout_aclk_g2d_400_user_p)		= { "oscclk", "aclk_g2d_400", };
 
-static struct samsung_mux_clock g2d_mux_clks[] __initdata = {
+static const struct samsung_mux_clock g2d_mux_clks[] __initconst = {
 	/* MUX_SEL_G2D0 */
 	MUX(CLK_MUX_ACLK_G2D_266_USER, "mout_aclk_g2d_266_user",
 			mout_aclk_g2d_266_user_p, MUX_SEL_G2D0, 4, 1),
@@ -2335,13 +2335,13 @@ static struct samsung_mux_clock g2d_mux_clks[] __initdata = {
 			mout_aclk_g2d_400_user_p, MUX_SEL_G2D0, 0, 1),
 };
 
-static struct samsung_div_clock g2d_div_clks[] __initdata = {
+static const struct samsung_div_clock g2d_div_clks[] __initconst = {
 	/* DIV_G2D */
 	DIV(CLK_DIV_PCLK_G2D, "div_pclk_g2d", "mout_aclk_g2d_266_user",
 			DIV_G2D, 0, 2),
 };
 
-static struct samsung_gate_clock g2d_gate_clks[] __initdata = {
+static const struct samsung_gate_clock g2d_gate_clks[] __initconst = {
 	/* DIV_ENABLE_ACLK_G2D */
 	GATE(CLK_ACLK_SMMU_MDMA1, "aclk_smmu_mdma1", "mout_aclk_g2d_266_user",
 			DIV_ENABLE_ACLK_G2D, 12, 0, 0),
@@ -2398,7 +2398,7 @@ static struct samsung_gate_clock g2d_gate_clks[] __initdata = {
 		DIV_ENABLE_PCLK_G2D_SECURE_SMMU_G2D, 0, 0, 0),
 };
 
-static struct samsung_cmu_info g2d_cmu_info __initdata = {
+static const struct samsung_cmu_info g2d_cmu_info __initconst = {
 	.mux_clks		= g2d_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(g2d_mux_clks),
 	.div_clks		= g2d_div_clks,
@@ -2454,7 +2454,7 @@ CLK_OF_DECLARE(exynos5433_cmu_g2d, "samsung,exynos5433-cmu-g2d",
 #define CLKOUT_CMU_DISP			0x0c00
 #define CLKOUT_CMU_DISP_DIV_STAT	0x0c04
 
-static unsigned long disp_clk_regs[] __initdata = {
+static const unsigned long disp_clk_regs[] __initconst = {
 	DISP_PLL_LOCK,
 	DISP_PLL_CON0,
 	DISP_PLL_CON1,
@@ -2527,12 +2527,12 @@ PNAME(mout_sclk_decon_tv_vclk_c_disp_p)	= {
 PNAME(mout_sclk_decon_tv_vclk_b_disp_p)	= { "mout_sclk_decon_tv_vclk_a_disp",
 					    "mout_sclk_decon_tv_vclk_user", };
 
-static struct samsung_pll_clock disp_pll_clks[] __initdata = {
+static const struct samsung_pll_clock disp_pll_clks[] __initconst = {
 	PLL(pll_35xx, CLK_FOUT_DISP_PLL, "fout_disp_pll", "oscclk",
 		DISP_PLL_LOCK, DISP_PLL_CON0, exynos5443_pll_rates),
 };
 
-static struct samsung_fixed_factor_clock disp_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock disp_fixed_factor_clks[] __initconst = {
 	/*
 	 * sclk_rgb_{vclk|tv_vclk} is half clock of sclk_decon_{vclk|tv_vclk}.
 	 * The divider has fixed value (2) between sclk_rgb_{vclk|tv_vclk}
@@ -2544,7 +2544,7 @@ static struct samsung_fixed_factor_clock disp_fixed_factor_clks[] __initdata = {
 			1, 2, 0),
 };
 
-static struct samsung_fixed_rate_clock disp_fixed_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock disp_fixed_clks[] __initconst = {
 	/* PHY clocks from MIPI_DPHY1 */
 	FRATE(0, "phyclk_mipidphy1_bitclkdiv8_phy", NULL, 0, 188000000),
 	FRATE(0, "phyclk_mipidphy1_rxclkesc0_phy", NULL, 0, 100000000),
@@ -2558,7 +2558,7 @@ static struct samsung_fixed_rate_clock disp_fixed_clks[] __initdata = {
 			NULL, 0, 166000000),
 };
 
-static struct samsung_mux_clock disp_mux_clks[] __initdata = {
+static const struct samsung_mux_clock disp_mux_clks[] __initconst = {
 	/* MUX_SEL_DISP0 */
 	MUX(CLK_MOUT_DISP_PLL, "mout_disp_pll", mout_disp_pll_p, MUX_SEL_DISP0,
 			0, 1),
@@ -2633,7 +2633,7 @@ static struct samsung_mux_clock disp_mux_clks[] __initdata = {
 			mout_sclk_decon_vclk_p, MUX_SEL_DISP4, 0, 1),
 };
 
-static struct samsung_div_clock disp_div_clks[] __initdata = {
+static const struct samsung_div_clock disp_div_clks[] __initconst = {
 	/* DIV_DISP */
 	DIV(CLK_DIV_SCLK_DSIM1_DISP, "div_sclk_dsim1_disp",
 			"mout_sclk_dsim1_b_disp", DIV_DISP, 24, 3),
@@ -2651,7 +2651,7 @@ static struct samsung_div_clock disp_div_clks[] __initdata = {
 			DIV_DISP, 0, 2),
 };
 
-static struct samsung_gate_clock disp_gate_clks[] __initdata = {
+static const struct samsung_gate_clock disp_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_DISP0 */
 	GATE(CLK_ACLK_DECON_TV, "aclk_decon_tv", "mout_aclk_disp_333_user",
 			ENABLE_ACLK_DISP0, 2, 0, 0),
@@ -2811,7 +2811,7 @@ static struct samsung_gate_clock disp_gate_clks[] __initdata = {
 			"div_sclk_decon_eclk_disp", ENABLE_SCLK_DISP, 2, 0, 0),
 };
 
-static struct samsung_cmu_info disp_cmu_info __initdata = {
+static const struct samsung_cmu_info disp_cmu_info __initconst = {
 	.pll_clks		= disp_pll_clks,
 	.nr_pll_clks		= ARRAY_SIZE(disp_pll_clks),
 	.mux_clks		= disp_mux_clks,
@@ -2856,7 +2856,7 @@ CLK_OF_DECLARE(exynos5433_cmu_disp, "samsung,exynos5433-cmu-disp",
 #define ENABLE_IP_AUD0			0x0b00
 #define ENABLE_IP_AUD1			0x0b04
 
-static unsigned long aud_clk_regs[] __initdata = {
+static const unsigned long aud_clk_regs[] __initconst = {
 	MUX_SEL_AUD0,
 	MUX_SEL_AUD1,
 	MUX_ENABLE_AUD0,
@@ -2875,13 +2875,13 @@ static unsigned long aud_clk_regs[] __initdata = {
 PNAME(mout_aud_pll_user_aud_p)	= { "oscclk", "fout_aud_pll", };
 PNAME(mout_sclk_aud_pcm_p)	= { "mout_aud_pll_user", "ioclk_audiocdclk0",};
 
-static struct samsung_fixed_rate_clock aud_fixed_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock aud_fixed_clks[] __initconst = {
 	FRATE(0, "ioclk_jtag_tclk", NULL, 0, 33000000),
 	FRATE(0, "ioclk_slimbus_clk", NULL, 0, 25000000),
 	FRATE(0, "ioclk_i2s_bclk", NULL, 0, 50000000),
 };
 
-static struct samsung_mux_clock aud_mux_clks[] __initdata = {
+static const struct samsung_mux_clock aud_mux_clks[] __initconst = {
 	/* MUX_SEL_AUD0 */
 	MUX(CLK_MOUT_AUD_PLL_USER, "mout_aud_pll_user",
 			mout_aud_pll_user_aud_p, MUX_SEL_AUD0, 0, 1),
@@ -2893,7 +2893,7 @@ static struct samsung_mux_clock aud_mux_clks[] __initdata = {
 			MUX_SEL_AUD1, 0, 1),
 };
 
-static struct samsung_div_clock aud_div_clks[] __initdata = {
+static const struct samsung_div_clock aud_div_clks[] __initconst = {
 	/* DIV_AUD0 */
 	DIV(CLK_DIV_ATCLK_AUD, "div_atclk_aud", "div_aud_ca5", DIV_AUD0,
 			12, 4),
@@ -2915,7 +2915,7 @@ static struct samsung_div_clock aud_div_clks[] __initdata = {
 			DIV_AUD1, 0, 4),
 };
 
-static struct samsung_gate_clock aud_gate_clks[] __initdata = {
+static const struct samsung_gate_clock aud_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_AUD */
 	GATE(CLK_ACLK_INTR_CTRL, "aclk_intr_ctrl", "div_aclk_aud",
 			ENABLE_ACLK_AUD, 12, 0, 0),
@@ -2985,7 +2985,7 @@ static struct samsung_gate_clock aud_gate_clks[] __initdata = {
 			ENABLE_SCLK_AUD1, 0, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info aud_cmu_info __initdata = {
+static const struct samsung_cmu_info aud_cmu_info __initconst = {
 	.mux_clks		= aud_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(aud_mux_clks),
 	.div_clks		= aud_div_clks,
@@ -3031,24 +3031,24 @@ PNAME(mout_aclk_bus2_400_p)	= { "oscclk", "aclk_bus2_400", };
 	ENABLE_IP_BUS0,		\
 	ENABLE_IP_BUS1
 
-static unsigned long bus01_clk_regs[] __initdata = {
+static const unsigned long bus01_clk_regs[] __initconst = {
 	CMU_BUS_COMMON_CLK_REGS,
 };
 
-static unsigned long bus2_clk_regs[] __initdata = {
+static const unsigned long bus2_clk_regs[] __initconst = {
 	MUX_SEL_BUS2,
 	MUX_ENABLE_BUS2,
 	CMU_BUS_COMMON_CLK_REGS,
 };
 
-static struct samsung_div_clock bus0_div_clks[] __initdata = {
+static const struct samsung_div_clock bus0_div_clks[] __initconst = {
 	/* DIV_BUS0 */
 	DIV(CLK_DIV_PCLK_BUS_133, "div_pclk_bus0_133", "aclk_bus0_400",
 			DIV_BUS, 0, 3),
 };
 
 /* CMU_BUS0 clocks */
-static struct samsung_gate_clock bus0_gate_clks[] __initdata = {
+static const struct samsung_gate_clock bus0_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_BUS0 */
 	GATE(CLK_ACLK_AHB2APB_BUSP, "aclk_ahb2apb_bus0p", "div_pclk_bus0_133",
 			ENABLE_ACLK_BUS, 4, CLK_IGNORE_UNUSED, 0),
@@ -3067,13 +3067,13 @@ static struct samsung_gate_clock bus0_gate_clks[] __initdata = {
 };
 
 /* CMU_BUS1 clocks */
-static struct samsung_div_clock bus1_div_clks[] __initdata = {
+static const struct samsung_div_clock bus1_div_clks[] __initconst = {
 	/* DIV_BUS1 */
 	DIV(CLK_DIV_PCLK_BUS_133, "div_pclk_bus1_133", "aclk_bus1_400",
 			DIV_BUS, 0, 3),
 };
 
-static struct samsung_gate_clock bus1_gate_clks[] __initdata = {
+static const struct samsung_gate_clock bus1_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_BUS1 */
 	GATE(CLK_ACLK_AHB2APB_BUSP, "aclk_ahb2apb_bus1p", "div_pclk_bus1_133",
 			ENABLE_ACLK_BUS, 4, CLK_IGNORE_UNUSED, 0),
@@ -3092,19 +3092,19 @@ static struct samsung_gate_clock bus1_gate_clks[] __initdata = {
 };
 
 /* CMU_BUS2 clocks */
-static struct samsung_mux_clock bus2_mux_clks[] __initdata = {
+static const struct samsung_mux_clock bus2_mux_clks[] __initconst = {
 	/* MUX_SEL_BUS2 */
 	MUX(CLK_MOUT_ACLK_BUS2_400_USER, "mout_aclk_bus2_400_user",
 			mout_aclk_bus2_400_p, MUX_SEL_BUS2, 0, 1),
 };
 
-static struct samsung_div_clock bus2_div_clks[] __initdata = {
+static const struct samsung_div_clock bus2_div_clks[] __initconst = {
 	/* DIV_BUS2 */
 	DIV(CLK_DIV_PCLK_BUS_133, "div_pclk_bus2_133",
 			"mout_aclk_bus2_400_user", DIV_BUS, 0, 3),
 };
 
-static struct samsung_gate_clock bus2_gate_clks[] __initdata = {
+static const struct samsung_gate_clock bus2_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_BUS2 */
 	GATE(CLK_ACLK_AHB2APB_BUSP, "aclk_ahb2apb_bus2p", "div_pclk_bus2_133",
 			ENABLE_ACLK_BUS, 3, CLK_IGNORE_UNUSED, 0),
@@ -3133,19 +3133,19 @@ static struct samsung_gate_clock bus2_gate_clks[] __initdata = {
 	.nr_gate_clks		= ARRAY_SIZE(bus##id##_gate_clks),	\
 	.nr_clk_ids		= BUSx_NR_CLK
 
-static struct samsung_cmu_info bus0_cmu_info __initdata = {
+static const struct samsung_cmu_info bus0_cmu_info __initconst = {
 	CMU_BUS_INFO_CLKS(0),
 	.clk_regs		= bus01_clk_regs,
 	.nr_clk_regs		= ARRAY_SIZE(bus01_clk_regs),
 };
 
-static struct samsung_cmu_info bus1_cmu_info __initdata = {
+static const struct samsung_cmu_info bus1_cmu_info __initconst = {
 	CMU_BUS_INFO_CLKS(1),
 	.clk_regs		= bus01_clk_regs,
 	.nr_clk_regs		= ARRAY_SIZE(bus01_clk_regs),
 };
 
-static struct samsung_cmu_info bus2_cmu_info __initdata = {
+static const struct samsung_cmu_info bus2_cmu_info __initconst = {
 	CMU_BUS_INFO_CLKS(2),
 	.mux_clks		= bus2_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(bus2_mux_clks),
@@ -3189,7 +3189,7 @@ exynos5433_cmu_bus_init(2);
 #define CLKOUT_CMU_G3D_DIV_STAT		0x0c04
 #define CLK_STOPCTRL			0x1000
 
-static unsigned long g3d_clk_regs[] __initdata = {
+static const unsigned long g3d_clk_regs[] __initconst = {
 	G3D_PLL_LOCK,
 	G3D_PLL_CON0,
 	G3D_PLL_CON1,
@@ -3212,12 +3212,12 @@ static unsigned long g3d_clk_regs[] __initdata = {
 PNAME(mout_aclk_g3d_400_p)	= { "mout_g3d_pll", "aclk_g3d_400", };
 PNAME(mout_g3d_pll_p)		= { "oscclk", "fout_g3d_pll", };
 
-static struct samsung_pll_clock g3d_pll_clks[] __initdata = {
+static const struct samsung_pll_clock g3d_pll_clks[] __initconst = {
 	PLL(pll_35xx, CLK_FOUT_G3D_PLL, "fout_g3d_pll", "oscclk",
 		G3D_PLL_LOCK, G3D_PLL_CON0, exynos5443_pll_rates),
 };
 
-static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
+static const struct samsung_mux_clock g3d_mux_clks[] __initconst = {
 	/* MUX_SEL_G3D */
 	MUX_F(CLK_MOUT_ACLK_G3D_400, "mout_aclk_g3d_400", mout_aclk_g3d_400_p,
 			MUX_SEL_G3D, 8, 1, CLK_SET_RATE_PARENT, 0),
@@ -3225,7 +3225,7 @@ static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
 			MUX_SEL_G3D, 0, 1, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_div_clock g3d_div_clks[] __initdata = {
+static const struct samsung_div_clock g3d_div_clks[] __initconst = {
 	/* DIV_G3D */
 	DIV(CLK_DIV_SCLK_HPM_G3D, "div_sclk_hpm_g3d", "mout_g3d_pll", DIV_G3D,
 			8, 2),
@@ -3235,7 +3235,7 @@ static struct samsung_div_clock g3d_div_clks[] __initdata = {
 			0, 3, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
+static const struct samsung_gate_clock g3d_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_G3D */
 	GATE(CLK_ACLK_BTS_G3D1, "aclk_bts_g3d1", "div_aclk_g3d",
 			ENABLE_ACLK_G3D, 7, 0, 0),
@@ -3269,7 +3269,7 @@ static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
 			ENABLE_SCLK_G3D, 0, 0, 0),
 };
 
-static struct samsung_cmu_info g3d_cmu_info __initdata = {
+static const struct samsung_cmu_info g3d_cmu_info __initconst = {
 	.pll_clks		= g3d_pll_clks,
 	.nr_pll_clks		= ARRAY_SIZE(g3d_pll_clks),
 	.mux_clks		= g3d_mux_clks,
@@ -3310,7 +3310,7 @@ CLK_OF_DECLARE(exynos5433_cmu_g3d, "samsung,exynos5433-cmu-g3d",
 #define ENABLE_IP_GSCL_SECURE_SMMU_GSCL1	0x0b0c
 #define ENABLE_IP_GSCL_SECURE_SMMU_GSCL2	0x0b10
 
-static unsigned long gscl_clk_regs[] __initdata = {
+static const unsigned long gscl_clk_regs[] __initconst = {
 	MUX_SEL_GSCL,
 	MUX_ENABLE_GSCL,
 	ENABLE_ACLK_GSCL,
@@ -3332,7 +3332,7 @@ static unsigned long gscl_clk_regs[] __initdata = {
 PNAME(aclk_gscl_111_user_p)	= { "oscclk", "aclk_gscl_111", };
 PNAME(aclk_gscl_333_user_p)	= { "oscclk", "aclk_gscl_333", };
 
-static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
+static const struct samsung_mux_clock gscl_mux_clks[] __initconst = {
 	/* MUX_SEL_GSCL */
 	MUX(CLK_MOUT_ACLK_GSCL_111_USER, "mout_aclk_gscl_111_user",
 			aclk_gscl_111_user_p, MUX_SEL_GSCL, 4, 1),
@@ -3340,7 +3340,7 @@ static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
 			aclk_gscl_333_user_p, MUX_SEL_GSCL, 0, 1),
 };
 
-static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
+static const struct samsung_gate_clock gscl_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_GSCL */
 	GATE(CLK_ACLK_BTS_GSCL2, "aclk_bts_gscl2", "mout_aclk_gscl_333_user",
 			ENABLE_ACLK_GSCL, 11, 0, 0),
@@ -3412,7 +3412,7 @@ static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
 		ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL2, 0, 0, 0),
 };
 
-static struct samsung_cmu_info gscl_cmu_info __initdata = {
+static const struct samsung_cmu_info gscl_cmu_info __initconst = {
 	.mux_clks		= gscl_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(gscl_mux_clks),
 	.gate_clks		= gscl_gate_clks,
@@ -3465,7 +3465,7 @@ CLK_OF_DECLARE(exynos5433_cmu_gscl, "samsung,exynos5433-cmu-gscl",
 #define APOLLO_INTR_SPREAD_USE_STANDBYWFI	0x1084
 #define APOLLO_INTR_SPREAD_BLOCKING_DURATION	0x1088
 
-static unsigned long apollo_clk_regs[] __initdata = {
+static const unsigned long apollo_clk_regs[] __initconst = {
 	APOLLO_PLL_LOCK,
 	APOLLO_PLL_CON0,
 	APOLLO_PLL_CON1,
@@ -3500,12 +3500,12 @@ PNAME(mout_bus_pll_apollo_user_p)	= { "oscclk", "sclk_bus_pll_apollo", };
 PNAME(mout_apollo_p)			= { "mout_apollo_pll",
 					    "mout_bus_pll_apollo_user", };
 
-static struct samsung_pll_clock apollo_pll_clks[] __initdata = {
+static const struct samsung_pll_clock apollo_pll_clks[] __initconst = {
 	PLL(pll_35xx, CLK_FOUT_APOLLO_PLL, "fout_apollo_pll", "oscclk",
 		APOLLO_PLL_LOCK, APOLLO_PLL_CON0, exynos5443_pll_rates),
 };
 
-static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
+static const struct samsung_mux_clock apollo_mux_clks[] __initconst = {
 	/* MUX_SEL_APOLLO0 */
 	MUX_F(CLK_MOUT_APOLLO_PLL, "mout_apollo_pll", mout_apollo_pll_p,
 			MUX_SEL_APOLLO0, 0, 1, CLK_SET_RATE_PARENT, 0),
@@ -3519,7 +3519,7 @@ static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
 			0, 1, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_div_clock apollo_div_clks[] __initdata = {
+static const struct samsung_div_clock apollo_div_clks[] __initconst = {
 	/* DIV_APOLLO0 */
 	DIV_F(CLK_DIV_CNTCLK_APOLLO, "div_cntclk_apollo", "div_apollo2",
 			DIV_APOLLO0, 24, 3, CLK_GET_RATE_NOCACHE,
@@ -3550,7 +3550,7 @@ static struct samsung_div_clock apollo_div_clks[] __initdata = {
 			CLK_DIVIDER_READ_ONLY),
 };
 
-static struct samsung_gate_clock apollo_gate_clks[] __initdata = {
+static const struct samsung_gate_clock apollo_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_APOLLO */
 	GATE(CLK_ACLK_ASATBSLV_APOLLO_3_CSSYS, "aclk_asatbslv_apollo_3_cssys",
 			"div_atclk_apollo", ENABLE_ACLK_APOLLO,
@@ -3594,7 +3594,7 @@ static struct samsung_gate_clock apollo_gate_clks[] __initdata = {
 			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_cmu_info apollo_cmu_info __initdata = {
+static const struct samsung_cmu_info apollo_cmu_info __initconst = {
 	.pll_clks		= apollo_pll_clks,
 	.nr_pll_clks		= ARRAY_SIZE(apollo_pll_clks),
 	.mux_clks		= apollo_mux_clks,
@@ -3651,7 +3651,7 @@ CLK_OF_DECLARE(exynos5433_cmu_apollo, "samsung,exynos5433-cmu-apollo",
 #define ATLAS_INTR_SPREAD_USE_STANDBYWFI	0x1084
 #define ATLAS_INTR_SPREAD_BLOCKING_DURATION	0x1088
 
-static unsigned long atlas_clk_regs[] __initdata = {
+static const unsigned long atlas_clk_regs[] __initconst = {
 	ATLAS_PLL_LOCK,
 	ATLAS_PLL_CON0,
 	ATLAS_PLL_CON1,
@@ -3686,12 +3686,12 @@ PNAME(mout_bus_pll_atlas_user_p)	= { "oscclk", "sclk_bus_pll_atlas", };
 PNAME(mout_atlas_p)			= { "mout_atlas_pll",
 					    "mout_bus_pll_atlas_user", };
 
-static struct samsung_pll_clock atlas_pll_clks[] __initdata = {
+static const struct samsung_pll_clock atlas_pll_clks[] __initconst = {
 	PLL(pll_35xx, CLK_FOUT_ATLAS_PLL, "fout_atlas_pll", "oscclk",
 		ATLAS_PLL_LOCK, ATLAS_PLL_CON0, exynos5443_pll_rates),
 };
 
-static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
+static const struct samsung_mux_clock atlas_mux_clks[] __initconst = {
 	/* MUX_SEL_ATLAS0 */
 	MUX_F(CLK_MOUT_ATLAS_PLL, "mout_atlas_pll", mout_atlas_pll_p,
 			MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT, 0),
@@ -3705,7 +3705,7 @@ static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
 			0, 1, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_div_clock atlas_div_clks[] __initdata = {
+static const struct samsung_div_clock atlas_div_clks[] __initconst = {
 	/* DIV_ATLAS0 */
 	DIV_F(CLK_DIV_CNTCLK_ATLAS, "div_cntclk_atlas", "div_atlas2",
 			DIV_ATLAS0, 24, 3, CLK_GET_RATE_NOCACHE,
@@ -3736,7 +3736,7 @@ static struct samsung_div_clock atlas_div_clks[] __initdata = {
 			CLK_DIVIDER_READ_ONLY),
 };
 
-static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
+static const struct samsung_gate_clock atlas_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_ATLAS */
 	GATE(CLK_ACLK_ATB_AUD_CSSYS, "aclk_atb_aud_cssys",
 			"div_atclk_atlas", ENABLE_ACLK_ATLAS,
@@ -3806,7 +3806,7 @@ static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
 			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_cmu_info atlas_cmu_info __initdata = {
+static const struct samsung_cmu_info atlas_cmu_info __initconst = {
 	.pll_clks		= atlas_pll_clks,
 	.nr_pll_clks		= ARRAY_SIZE(atlas_pll_clks),
 	.mux_clks		= atlas_mux_clks,
@@ -3853,7 +3853,7 @@ CLK_OF_DECLARE(exynos5433_cmu_atlas, "samsung,exynos5433-cmu-atlas",
 #define ENABLE_IP_MSCL_SECURE_SMMU_M2MSCALER1		0x0b0c
 #define ENABLE_IP_MSCL_SECURE_SMMU_JPEG			0x0b10
 
-static unsigned long mscl_clk_regs[] __initdata = {
+static const unsigned long mscl_clk_regs[] __initconst = {
 	MUX_SEL_MSCL0,
 	MUX_SEL_MSCL1,
 	MUX_ENABLE_MSCL0,
@@ -3881,7 +3881,7 @@ PNAME(mout_aclk_mscl_400_user_p)	= { "oscclk", "aclk_mscl_400", };
 PNAME(mout_sclk_jpeg_p)			= { "mout_sclk_jpeg_user",
 					"mout_aclk_mscl_400_user", };
 
-static struct samsung_mux_clock mscl_mux_clks[] __initdata = {
+static const struct samsung_mux_clock mscl_mux_clks[] __initconst = {
 	/* MUX_SEL_MSCL0 */
 	MUX(CLK_MOUT_SCLK_JPEG_USER, "mout_sclk_jpeg_user",
 			mout_sclk_jpeg_user_p, MUX_SEL_MSCL0, 4, 1),
@@ -3893,13 +3893,13 @@ static struct samsung_mux_clock mscl_mux_clks[] __initdata = {
 			MUX_SEL_MSCL1, 0, 1),
 };
 
-static struct samsung_div_clock mscl_div_clks[] __initdata = {
+static const struct samsung_div_clock mscl_div_clks[] __initconst = {
 	/* DIV_MSCL */
 	DIV(CLK_DIV_PCLK_MSCL, "div_pclk_mscl", "mout_aclk_mscl_400_user",
 			DIV_MSCL, 0, 3),
 };
 
-static struct samsung_gate_clock mscl_gate_clks[] __initdata = {
+static const struct samsung_gate_clock mscl_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_MSCL */
 	GATE(CLK_ACLK_BTS_JPEG, "aclk_bts_jpeg", "mout_aclk_mscl_400_user",
 			ENABLE_ACLK_MSCL, 9, 0, 0),
@@ -3977,7 +3977,7 @@ static struct samsung_gate_clock mscl_gate_clks[] __initdata = {
 			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_cmu_info mscl_cmu_info __initdata = {
+static const struct samsung_cmu_info mscl_cmu_info __initconst = {
 	.mux_clks		= mscl_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(mscl_mux_clks),
 	.div_clks		= mscl_div_clks,
@@ -4012,7 +4012,7 @@ CLK_OF_DECLARE(exynos5433_cmu_mscl, "samsung,exynos5433-cmu-mscl",
 #define ENABLE_IP_MFC1				0x0b04
 #define ENABLE_IP_MFC_SECURE_SMMU_MFC		0x0b08
 
-static unsigned long mfc_clk_regs[] __initdata = {
+static const unsigned long mfc_clk_regs[] __initconst = {
 	MUX_SEL_MFC,
 	MUX_ENABLE_MFC,
 	DIV_MFC,
@@ -4027,19 +4027,19 @@ static unsigned long mfc_clk_regs[] __initdata = {
 
 PNAME(mout_aclk_mfc_400_user_p)		= { "oscclk", "aclk_mfc_400", };
 
-static struct samsung_mux_clock mfc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock mfc_mux_clks[] __initconst = {
 	/* MUX_SEL_MFC */
 	MUX(CLK_MOUT_ACLK_MFC_400_USER, "mout_aclk_mfc_400_user",
 			mout_aclk_mfc_400_user_p, MUX_SEL_MFC, 0, 0),
 };
 
-static struct samsung_div_clock mfc_div_clks[] __initdata = {
+static const struct samsung_div_clock mfc_div_clks[] __initconst = {
 	/* DIV_MFC */
 	DIV(CLK_DIV_PCLK_MFC, "div_pclk_mfc", "mout_aclk_mfc_400_user",
 			DIV_MFC, 0, 2),
 };
 
-static struct samsung_gate_clock mfc_gate_clks[] __initdata = {
+static const struct samsung_gate_clock mfc_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_MFC */
 	GATE(CLK_ACLK_BTS_MFC_1, "aclk_bts_mfc_1", "mout_aclk_mfc_400_user",
 			ENABLE_ACLK_MFC, 6, 0, 0),
@@ -4085,7 +4085,7 @@ static struct samsung_gate_clock mfc_gate_clks[] __initdata = {
 			0, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info mfc_cmu_info __initdata = {
+static const struct samsung_cmu_info mfc_cmu_info __initconst = {
 	.mux_clks		= mfc_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(mfc_mux_clks),
 	.div_clks		= mfc_div_clks,
@@ -4120,7 +4120,7 @@ CLK_OF_DECLARE(exynos5433_cmu_mfc, "samsung,exynos5433-cmu-mfc",
 #define ENABLE_IP_HEVC1				0x0b04
 #define ENABLE_IP_HEVC_SECURE_SMMU_HEVC		0x0b08
 
-static unsigned long hevc_clk_regs[] __initdata = {
+static const unsigned long hevc_clk_regs[] __initconst = {
 	MUX_SEL_HEVC,
 	MUX_ENABLE_HEVC,
 	DIV_HEVC,
@@ -4135,19 +4135,19 @@ static unsigned long hevc_clk_regs[] __initdata = {
 
 PNAME(mout_aclk_hevc_400_user_p)	= { "oscclk", "aclk_hevc_400", };
 
-static struct samsung_mux_clock hevc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock hevc_mux_clks[] __initconst = {
 	/* MUX_SEL_HEVC */
 	MUX(CLK_MOUT_ACLK_HEVC_400_USER, "mout_aclk_hevc_400_user",
 			mout_aclk_hevc_400_user_p, MUX_SEL_HEVC, 0, 0),
 };
 
-static struct samsung_div_clock hevc_div_clks[] __initdata = {
+static const struct samsung_div_clock hevc_div_clks[] __initconst = {
 	/* DIV_HEVC */
 	DIV(CLK_DIV_PCLK_HEVC, "div_pclk_hevc", "mout_aclk_hevc_400_user",
 			DIV_HEVC, 0, 2),
 };
 
-static struct samsung_gate_clock hevc_gate_clks[] __initdata = {
+static const struct samsung_gate_clock hevc_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_HEVC */
 	GATE(CLK_ACLK_BTS_HEVC_1, "aclk_bts_hevc_1", "mout_aclk_hevc_400_user",
 			ENABLE_ACLK_HEVC, 6, 0, 0),
@@ -4195,7 +4195,7 @@ static struct samsung_gate_clock hevc_gate_clks[] __initdata = {
 			0, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info hevc_cmu_info __initdata = {
+static const struct samsung_cmu_info hevc_cmu_info __initconst = {
 	.mux_clks		= hevc_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(hevc_mux_clks),
 	.div_clks		= hevc_div_clks,
@@ -4232,7 +4232,7 @@ CLK_OF_DECLARE(exynos5433_cmu_hevc, "samsung,exynos5433-cmu-hevc",
 #define ENABLE_IP_ISP2			0x0b08
 #define ENABLE_IP_ISP3			0x0b0c
 
-static unsigned long isp_clk_regs[] __initdata = {
+static const unsigned long isp_clk_regs[] __initconst = {
 	MUX_SEL_ISP,
 	MUX_ENABLE_ISP,
 	DIV_ISP,
@@ -4250,7 +4250,7 @@ static unsigned long isp_clk_regs[] __initdata = {
 PNAME(mout_aclk_isp_dis_400_user_p)	= { "oscclk", "aclk_isp_dis_400", };
 PNAME(mout_aclk_isp_400_user_p)		= { "oscclk", "aclk_isp_400", };
 
-static struct samsung_mux_clock isp_mux_clks[] __initdata = {
+static const struct samsung_mux_clock isp_mux_clks[] __initconst = {
 	/* MUX_SEL_ISP */
 	MUX(CLK_MOUT_ACLK_ISP_DIS_400_USER, "mout_aclk_isp_dis_400_user",
 			mout_aclk_isp_dis_400_user_p, MUX_SEL_ISP, 4, 0),
@@ -4258,7 +4258,7 @@ static struct samsung_mux_clock isp_mux_clks[] __initdata = {
 			mout_aclk_isp_400_user_p, MUX_SEL_ISP, 0, 0),
 };
 
-static struct samsung_div_clock isp_div_clks[] __initdata = {
+static const struct samsung_div_clock isp_div_clks[] __initconst = {
 	/* DIV_ISP */
 	DIV(CLK_DIV_PCLK_ISP_DIS, "div_pclk_isp_dis",
 			"mout_aclk_isp_dis_400_user", DIV_ISP, 12, 3),
@@ -4270,7 +4270,7 @@ static struct samsung_div_clock isp_div_clks[] __initdata = {
 			"mout_aclk_isp_400_user", DIV_ISP, 0, 3),
 };
 
-static struct samsung_gate_clock isp_gate_clks[] __initdata = {
+static const struct samsung_gate_clock isp_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_ISP0 */
 	GATE(CLK_ACLK_ISP_D_GLUE, "aclk_isp_d_glue", "mout_aclk_isp_400_user",
 			ENABLE_ACLK_ISP0, 6, CLK_IGNORE_UNUSED, 0),
@@ -4448,7 +4448,7 @@ static struct samsung_gate_clock isp_gate_clks[] __initdata = {
 			0, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info isp_cmu_info __initdata = {
+static const struct samsung_cmu_info isp_cmu_info __initconst = {
 	.mux_clks		= isp_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(isp_mux_clks),
 	.div_clks		= isp_div_clks,
@@ -4504,7 +4504,7 @@ CLK_OF_DECLARE(exynos5433_cmu_isp, "samsung,exynos5433-cmu-isp",
 #define ENABLE_IP_CAM02			0X0b08
 #define ENABLE_IP_CAM03			0X0b0C
 
-static unsigned long cam0_clk_regs[] __initdata = {
+static const unsigned long cam0_clk_regs[] __initconst = {
 	MUX_SEL_CAM00,
 	MUX_SEL_CAM01,
 	MUX_SEL_CAM02,
@@ -4588,14 +4588,14 @@ PNAME(mout_sclk_pixelasync_lite_c_init_a_p) = {
 					"mout_aclk_cam0_552_user",
 					"mout_aclk_cam0_400_user", };
 
-static struct samsung_fixed_rate_clock cam0_fixed_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock cam0_fixed_clks[] __initconst = {
 	FRATE(CLK_PHYCLK_RXBYTEECLKHS0_S4_PHY, "phyclk_rxbyteclkhs0_s4_phy",
 			NULL, 0, 100000000),
 	FRATE(CLK_PHYCLK_RXBYTEECLKHS0_S2A_PHY, "phyclk_rxbyteclkhs0_s2a_phy",
 			NULL, 0, 100000000),
 };
 
-static struct samsung_mux_clock cam0_mux_clks[] __initdata = {
+static const struct samsung_mux_clock cam0_mux_clks[] __initconst = {
 	/* MUX_SEL_CAM00 */
 	MUX(CLK_MOUT_ACLK_CAM0_333_USER, "mout_aclk_cam0_333_user",
 			mout_aclk_cam0_333_user_p, MUX_SEL_CAM00, 8, 1),
@@ -4669,7 +4669,7 @@ static struct samsung_mux_clock cam0_mux_clks[] __initdata = {
 			MUX_SEL_CAM04, 0, 1),
 };
 
-static struct samsung_div_clock cam0_div_clks[] __initdata = {
+static const struct samsung_div_clock cam0_div_clks[] __initconst = {
 	/* DIV_CAM00 */
 	DIV(CLK_DIV_PCLK_CAM0_50, "div_pclk_cam0_50", "div_aclk_cam0_200",
 			DIV_CAM00, 8, 2),
@@ -4716,7 +4716,7 @@ static struct samsung_div_clock cam0_div_clks[] __initdata = {
 			"mout_sclk_pixelasync_lite_c_init_b", DIV_CAM03, 0, 3),
 };
 
-static struct samsung_gate_clock cam0_gate_clks[] __initdata = {
+static const struct samsung_gate_clock cam0_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_CAM00 */
 	GATE(CLK_ACLK_CSIS1, "aclk_csis1", "div_aclk_csis1", ENABLE_ACLK_CAM00,
 			6, 0, 0),
@@ -4923,7 +4923,7 @@ static struct samsung_gate_clock cam0_gate_clks[] __initdata = {
 			ENABLE_SCLK_CAM0, 0, 0, 0),
 };
 
-static struct samsung_cmu_info cam0_cmu_info __initdata = {
+static const struct samsung_cmu_info cam0_cmu_info __initconst = {
 	.mux_clks		= cam0_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(cam0_mux_clks),
 	.div_clks		= cam0_div_clks,
@@ -4970,7 +4970,7 @@ CLK_OF_DECLARE(exynos5433_cmu_cam0, "samsung,exynos5433-cmu-cam0",
 #define ENABLE_IP_CAM11			0X0b04
 #define ENABLE_IP_CAM12			0X0b08
 
-static unsigned long cam1_clk_regs[] __initdata = {
+static const unsigned long cam1_clk_regs[] __initconst = {
 	MUX_SEL_CAM10,
 	MUX_SEL_CAM11,
 	MUX_SEL_CAM12,
@@ -5016,12 +5016,12 @@ PNAME(mout_aclk_lite_c_b_p)		= { "mout_aclk_lite_c_a",
 PNAME(mout_aclk_lite_c_a_p)		= { "mout_aclk_cam1_552_user",
 					    "mout_aclk_cam1_400_user", };
 
-static struct samsung_fixed_rate_clock cam1_fixed_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock cam1_fixed_clks[] __initconst = {
 	FRATE(CLK_PHYCLK_RXBYTEECLKHS0_S2B, "phyclk_rxbyteclkhs0_s2b_phy", NULL,
 			0, 100000000),
 };
 
-static struct samsung_mux_clock cam1_mux_clks[] __initdata = {
+static const struct samsung_mux_clock cam1_mux_clks[] __initconst = {
 	/* MUX_SEL_CAM10 */
 	MUX(CLK_MOUT_SCLK_ISP_UART_USER, "mout_sclk_isp_uart_user",
 			mout_sclk_isp_uart_user_p, MUX_SEL_CAM10, 20, 1),
@@ -5057,7 +5057,7 @@ static struct samsung_mux_clock cam1_mux_clks[] __initdata = {
 			MUX_SEL_CAM12, 0, 1),
 };
 
-static struct samsung_div_clock cam1_div_clks[] __initdata = {
+static const struct samsung_div_clock cam1_div_clks[] __initconst = {
 	/* DIV_CAM10 */
 	DIV(CLK_DIV_SCLK_ISP_MPWM, "div_sclk_isp_mpwm",
 			"div_pclk_cam1_83", DIV_CAM10, 16, 2),
@@ -5081,7 +5081,7 @@ static struct samsung_div_clock cam1_div_clks[] __initdata = {
 			DIV_CAM11, 0, 3),
 };
 
-static struct samsung_gate_clock cam1_gate_clks[] __initdata = {
+static const struct samsung_gate_clock cam1_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_CAM10 */
 	GATE(CLK_ACLK_ISP_GIC, "aclk_isp_gic", "mout_aclk_cam1_333_user",
 			ENABLE_ACLK_CAM10, 4, 0, 0),
@@ -5296,7 +5296,7 @@ static struct samsung_gate_clock cam1_gate_clks[] __initdata = {
 			ENABLE_SCLK_CAM1, 0, 0, 0),
 };
 
-static struct samsung_cmu_info cam1_cmu_info __initdata = {
+static const struct samsung_cmu_info cam1_cmu_info __initconst = {
 	.mux_clks		= cam1_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(cam1_mux_clks),
 	.div_clks		= cam1_div_clks,
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:12 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:12 +0200
Subject: [PATCH 16/18] clk: samsung: exynos5420: Move sleep init function and
 PLL rates data to init section
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-16-git-send-email-k.kozlowski@samsung.com>

The exynos5420_clk_sleep_init() function and arrays with initialization
data of PLLs can be moved to init section because they are referenced
only from other init-level symbols.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos5420.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index adb0ae4efb7a..79fb8557bcf3 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -306,7 +306,7 @@ static struct syscore_ops exynos5420_clk_syscore_ops = {
 	.resume = exynos5420_clk_resume,
 };
 
-static void exynos5420_clk_sleep_init(void)
+static void __init exynos5420_clk_sleep_init(void)
 {
 	exynos5x_save = samsung_clk_alloc_reg_dump(exynos5x_clk_regs,
 					ARRAY_SIZE(exynos5x_clk_regs));
@@ -333,7 +333,7 @@ err_soc:
 	return;
 }
 #else
-static void exynos5420_clk_sleep_init(void) {}
+static void __init exynos5420_clk_sleep_init(void) {}
 #endif
 
 /* list of all parent clocks */
@@ -1219,7 +1219,7 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
 	GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
 };
 
-static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] = {
+static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __initconst = {
 	PLL_35XX_RATE(2000000000, 250, 3, 0),
 	PLL_35XX_RATE(1900000000, 475, 6, 0),
 	PLL_35XX_RATE(1800000000, 225, 3, 0),
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:05 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:05 +0200
Subject: [PATCH 09/18] clk: samsung: exynos5260: Constify all clock
 initializers
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-9-git-send-email-k.kozlowski@samsung.com>

All of initialization data can be made const.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos5260.c | 114 +++++++++++++++++------------------
 1 file changed, 57 insertions(+), 57 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index 7a7ed075a573..a43642c36039 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -22,7 +22,7 @@
  * Applicable for all 2550 Type PLLS for Exynos5260, listed below
  * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL.
  */
-static struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initdata = {
+static const struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initconst = {
 	PLL_35XX_RATE(1700000000, 425, 6, 0),
 	PLL_35XX_RATE(1600000000, 200, 3, 0),
 	PLL_35XX_RATE(1500000000, 250, 4, 0),
@@ -55,7 +55,7 @@ static struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initdata = {
 /*
  * Applicable for 2650 Type PLL for AUD_PLL.
  */
-static struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initdata = {
+static const struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initconst = {
 	PLL_36XX_RATE(1600000000, 200, 3, 0, 0),
 	PLL_36XX_RATE(1200000000, 100, 2, 0, 0),
 	PLL_36XX_RATE(1000000000, 250, 3, 1, 0),
@@ -78,7 +78,7 @@ static struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initdata = {
 
 /* CMU_AUD */
 
-static unsigned long aud_clk_regs[] __initdata = {
+static const unsigned long aud_clk_regs[] __initconst = {
 	MUX_SEL_AUD,
 	DIV_AUD0,
 	DIV_AUD1,
@@ -92,7 +92,7 @@ PNAME(mout_aud_pll_user_p) = {"fin_pll", "fout_aud_pll"};
 PNAME(mout_sclk_aud_i2s_p) = {"mout_aud_pll_user", "ioclk_i2s_cdclk"};
 PNAME(mout_sclk_aud_pcm_p) = {"mout_aud_pll_user", "ioclk_pcm_extclk"};
 
-static struct samsung_mux_clock aud_mux_clks[] __initdata = {
+static const struct samsung_mux_clock aud_mux_clks[] __initconst = {
 	MUX(AUD_MOUT_AUD_PLL_USER, "mout_aud_pll_user", mout_aud_pll_user_p,
 			MUX_SEL_AUD, 0, 1),
 	MUX(AUD_MOUT_SCLK_AUD_I2S, "mout_sclk_aud_i2s", mout_sclk_aud_i2s_p,
@@ -101,7 +101,7 @@ static struct samsung_mux_clock aud_mux_clks[] __initdata = {
 			MUX_SEL_AUD, 8, 1),
 };
 
-static struct samsung_div_clock aud_div_clks[] __initdata = {
+static const struct samsung_div_clock aud_div_clks[] __initconst = {
 	DIV(AUD_DOUT_ACLK_AUD_131, "dout_aclk_aud_131", "mout_aud_pll_user",
 			DIV_AUD0, 0, 4),
 
@@ -113,7 +113,7 @@ static struct samsung_div_clock aud_div_clks[] __initdata = {
 			DIV_AUD1, 12, 4),
 };
 
-static struct samsung_gate_clock aud_gate_clks[] __initdata = {
+static const struct samsung_gate_clock aud_gate_clks[] __initconst = {
 	GATE(AUD_SCLK_I2S, "sclk_aud_i2s", "dout_sclk_aud_i2s",
 			EN_SCLK_AUD, 0, CLK_SET_RATE_PARENT, 0),
 	GATE(AUD_SCLK_PCM, "sclk_aud_pcm", "dout_sclk_aud_pcm",
@@ -154,7 +154,7 @@ CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud",
 
 /* CMU_DISP */
 
-static unsigned long disp_clk_regs[] __initdata = {
+static const unsigned long disp_clk_regs[] __initconst = {
 	MUX_SEL_DISP0,
 	MUX_SEL_DISP1,
 	MUX_SEL_DISP2,
@@ -201,7 +201,7 @@ PNAME(mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p) = {"fin_pll",
 PNAME(mout_sclk_hdmi_spdif_p) = {"fin_pll", "ioclk_spdif_extclk",
 			"dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
 
-static struct samsung_mux_clock disp_mux_clks[] __initdata = {
+static const struct samsung_mux_clock disp_mux_clks[] __initconst = {
 	MUX(DISP_MOUT_ACLK_DISP_333_USER, "mout_aclk_disp_333_user",
 			mout_aclk_disp_333_user_p,
 			MUX_SEL_DISP0, 0, 1),
@@ -270,7 +270,7 @@ static struct samsung_mux_clock disp_mux_clks[] __initdata = {
 			MUX_SEL_DISP4, 4, 2),
 };
 
-static struct samsung_div_clock disp_div_clks[] __initdata = {
+static const struct samsung_div_clock disp_div_clks[] __initconst = {
 	DIV(DISP_DOUT_PCLK_DISP_111, "dout_pclk_disp_111",
 			"mout_aclk_disp_222_user",
 			DIV_DISP, 8, 4),
@@ -283,7 +283,7 @@ static struct samsung_div_clock disp_div_clks[] __initdata = {
 			DIV_DISP, 16, 4),
 };
 
-static struct samsung_gate_clock disp_gate_clks[] __initdata = {
+static const struct samsung_gate_clock disp_gate_clks[] __initconst = {
 	GATE(DISP_MOUT_HDMI_PHY_PIXEL_USER, "sclk_hdmi_link_i_pixel",
 			"mout_phyclk_hdmi_phy_pixel_clko_user",
 			EN_SCLK_DISP0, 26, CLK_SET_RATE_PARENT, 0),
@@ -344,7 +344,7 @@ CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp",
 
 /* CMU_EGL */
 
-static unsigned long egl_clk_regs[] __initdata = {
+static const unsigned long egl_clk_regs[] __initconst = {
 	EGL_PLL_LOCK,
 	EGL_PLL_CON0,
 	EGL_PLL_CON1,
@@ -361,13 +361,13 @@ static unsigned long egl_clk_regs[] __initdata = {
 PNAME(mout_egl_b_p) = {"mout_egl_pll", "dout_bus_pll"};
 PNAME(mout_egl_pll_p) = {"fin_pll", "fout_egl_pll"};
 
-static struct samsung_mux_clock egl_mux_clks[] __initdata = {
+static const struct samsung_mux_clock egl_mux_clks[] __initconst = {
 	MUX(EGL_MOUT_EGL_PLL, "mout_egl_pll", mout_egl_pll_p,
 			MUX_SEL_EGL, 4, 1),
 	MUX(EGL_MOUT_EGL_B, "mout_egl_b", mout_egl_b_p, MUX_SEL_EGL, 16, 1),
 };
 
-static struct samsung_div_clock egl_div_clks[] __initdata = {
+static const struct samsung_div_clock egl_div_clks[] __initconst = {
 	DIV(EGL_DOUT_EGL1, "dout_egl1", "mout_egl_b", DIV_EGL, 0, 3),
 	DIV(EGL_DOUT_EGL2, "dout_egl2", "dout_egl1", DIV_EGL, 4, 3),
 	DIV(EGL_DOUT_ACLK_EGL, "dout_aclk_egl", "dout_egl2", DIV_EGL, 8, 3),
@@ -379,7 +379,7 @@ static struct samsung_div_clock egl_div_clks[] __initdata = {
 	DIV(EGL_DOUT_EGL_PLL, "dout_egl_pll", "mout_egl_b", DIV_EGL, 24, 3),
 };
 
-static struct samsung_pll_clock egl_pll_clks[] __initdata = {
+static const struct samsung_pll_clock egl_pll_clks[] __initconst = {
 	PLL(pll_2550xx, EGL_FOUT_EGL_PLL, "fout_egl_pll", "fin_pll",
 		EGL_PLL_LOCK, EGL_PLL_CON0,
 		pll2550_24mhz_tbl),
@@ -408,7 +408,7 @@ CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl",
 
 /* CMU_FSYS */
 
-static unsigned long fsys_clk_regs[] __initdata = {
+static const unsigned long fsys_clk_regs[] __initconst = {
 	MUX_SEL_FSYS0,
 	MUX_SEL_FSYS1,
 	EN_ACLK_FSYS,
@@ -431,7 +431,7 @@ PNAME(mout_phyclk_usbdrd30_pipe_pclk_user_p) = {"fin_pll",
 PNAME(mout_phyclk_usbdrd30_phyclock_user_p) = {"fin_pll",
 			"phyclk_usbdrd30_udrd30_phyclock"};
 
-static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
+static const struct samsung_mux_clock fsys_mux_clks[] __initconst = {
 	MUX(FSYS_MOUT_PHYCLK_USBDRD30_PHYCLOCK_USER,
 			"mout_phyclk_usbdrd30_phyclock_user",
 			mout_phyclk_usbdrd30_phyclock_user_p,
@@ -454,7 +454,7 @@ static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
 			MUX_SEL_FSYS1, 16, 1),
 };
 
-static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
+static const struct samsung_gate_clock fsys_gate_clks[] __initconst = {
 	GATE(FSYS_PHYCLK_USBHOST20, "phyclk_usbhost20_phyclock",
 			"mout_phyclk_usbdrd30_phyclock_user",
 			EN_SCLK_FSYS, 1, 0, 0),
@@ -508,7 +508,7 @@ CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys",
 
 /* CMU_G2D */
 
-static unsigned long g2d_clk_regs[] __initdata = {
+static const unsigned long g2d_clk_regs[] __initconst = {
 	MUX_SEL_G2D,
 	MUX_STAT_G2D,
 	DIV_G2D,
@@ -535,18 +535,18 @@ static unsigned long g2d_clk_regs[] __initdata = {
 
 PNAME(mout_aclk_g2d_333_user_p) = {"fin_pll", "dout_aclk_g2d_333"};
 
-static struct samsung_mux_clock g2d_mux_clks[] __initdata = {
+static const struct samsung_mux_clock g2d_mux_clks[] __initconst = {
 	MUX(G2D_MOUT_ACLK_G2D_333_USER, "mout_aclk_g2d_333_user",
 			mout_aclk_g2d_333_user_p,
 			MUX_SEL_G2D, 0, 1),
 };
 
-static struct samsung_div_clock g2d_div_clks[] __initdata = {
+static const struct samsung_div_clock g2d_div_clks[] __initconst = {
 	DIV(G2D_DOUT_PCLK_G2D_83, "dout_pclk_g2d_83", "mout_aclk_g2d_333_user",
 			DIV_G2D, 0, 3),
 };
 
-static struct samsung_gate_clock g2d_gate_clks[] __initdata = {
+static const struct samsung_gate_clock g2d_gate_clks[] __initconst = {
 	GATE(G2D_CLK_G2D, "clk_g2d", "mout_aclk_g2d_333_user",
 			EN_IP_G2D, 4, 0, 0),
 	GATE(G2D_CLK_JPEG, "clk_jpeg", "mout_aclk_g2d_333_user",
@@ -599,7 +599,7 @@ CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d",
 
 /* CMU_G3D */
 
-static unsigned long g3d_clk_regs[] __initdata = {
+static const unsigned long g3d_clk_regs[] __initconst = {
 	G3D_PLL_LOCK,
 	G3D_PLL_CON0,
 	G3D_PLL_CON1,
@@ -615,23 +615,23 @@ static unsigned long g3d_clk_regs[] __initdata = {
 
 PNAME(mout_g3d_pll_p) = {"fin_pll", "fout_g3d_pll"};
 
-static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
+static const struct samsung_mux_clock g3d_mux_clks[] __initconst = {
 	MUX(G3D_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
 			MUX_SEL_G3D, 0, 1),
 };
 
-static struct samsung_div_clock g3d_div_clks[] __initdata = {
+static const struct samsung_div_clock g3d_div_clks[] __initconst = {
 	DIV(G3D_DOUT_PCLK_G3D, "dout_pclk_g3d", "dout_aclk_g3d", DIV_G3D, 0, 3),
 	DIV(G3D_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_g3d_pll", DIV_G3D, 4, 3),
 };
 
-static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
+static const struct samsung_gate_clock g3d_gate_clks[] __initconst = {
 	GATE(G3D_CLK_G3D, "clk_g3d", "dout_aclk_g3d", EN_IP_G3D, 2, 0, 0),
 	GATE(G3D_CLK_G3D_HPM, "clk_g3d_hpm", "dout_aclk_g3d",
 			EN_IP_G3D, 3, 0, 0),
 };
 
-static struct samsung_pll_clock g3d_pll_clks[] __initdata = {
+static const struct samsung_pll_clock g3d_pll_clks[] __initconst = {
 	PLL(pll_2550, G3D_FOUT_G3D_PLL, "fout_g3d_pll", "fin_pll",
 		G3D_PLL_LOCK, G3D_PLL_CON0,
 		pll2550_24mhz_tbl),
@@ -662,7 +662,7 @@ CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d",
 
 /* CMU_GSCL */
 
-static unsigned long gscl_clk_regs[] __initdata = {
+static const unsigned long gscl_clk_regs[] __initconst = {
 	MUX_SEL_GSCL,
 	DIV_GSCL,
 	EN_ACLK_GSCL,
@@ -692,7 +692,7 @@ PNAME(mout_aclk_m2m_400_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
 PNAME(mout_aclk_gscl_fimc_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
 PNAME(mout_aclk_csis_p) = {"dout_aclk_csis_200", "mout_aclk_gscl_fimc_user"};
 
-static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
+static const struct samsung_mux_clock gscl_mux_clks[] __initconst = {
 	MUX(GSCL_MOUT_ACLK_GSCL_333_USER, "mout_aclk_gscl_333_user",
 			mout_aclk_gscl_333_user_p,
 			MUX_SEL_GSCL, 0, 1),
@@ -706,7 +706,7 @@ static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
 			MUX_SEL_GSCL, 24, 1),
 };
 
-static struct samsung_div_clock gscl_div_clks[] __initdata = {
+static const struct samsung_div_clock gscl_div_clks[] __initconst = {
 	DIV(GSCL_DOUT_PCLK_M2M_100, "dout_pclk_m2m_100",
 			"mout_aclk_m2m_400_user",
 			DIV_GSCL, 0, 3),
@@ -715,7 +715,7 @@ static struct samsung_div_clock gscl_div_clks[] __initdata = {
 			DIV_GSCL, 4, 3),
 };
 
-static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
+static const struct samsung_gate_clock gscl_gate_clks[] __initconst = {
 	GATE(GSCL_SCLK_CSIS0_WRAP, "sclk_csis0_wrap", "dout_aclk_csis_200",
 			EN_SCLK_GSCL_FIMC, 0, CLK_SET_RATE_PARENT, 0),
 	GATE(GSCL_SCLK_CSIS1_WRAP, "sclk_csis1_wrap", "dout_aclk_csis_200",
@@ -795,7 +795,7 @@ CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl",
 
 /* CMU_ISP */
 
-static unsigned long isp_clk_regs[] __initdata = {
+static const unsigned long isp_clk_regs[] __initconst = {
 	MUX_SEL_ISP0,
 	MUX_SEL_ISP1,
 	DIV_ISP,
@@ -811,14 +811,14 @@ static unsigned long isp_clk_regs[] __initdata = {
 PNAME(mout_isp_400_user_p) = {"fin_pll", "dout_aclk_isp1_400"};
 PNAME(mout_isp_266_user_p)	 = {"fin_pll", "dout_aclk_isp1_266"};
 
-static struct samsung_mux_clock isp_mux_clks[] __initdata = {
+static const struct samsung_mux_clock isp_mux_clks[] __initconst = {
 	MUX(ISP_MOUT_ISP_266_USER, "mout_isp_266_user", mout_isp_266_user_p,
 			MUX_SEL_ISP0, 0, 1),
 	MUX(ISP_MOUT_ISP_400_USER, "mout_isp_400_user", mout_isp_400_user_p,
 			MUX_SEL_ISP0, 4, 1),
 };
 
-static struct samsung_div_clock isp_div_clks[] __initdata = {
+static const struct samsung_div_clock isp_div_clks[] __initconst = {
 	DIV(ISP_DOUT_PCLK_ISP_66, "dout_pclk_isp_66", "mout_kfc",
 			DIV_ISP, 0, 3),
 	DIV(ISP_DOUT_PCLK_ISP_133, "dout_pclk_isp_133", "mout_kfc",
@@ -830,7 +830,7 @@ static struct samsung_div_clock isp_div_clks[] __initdata = {
 	DIV(ISP_DOUT_SCLK_MPWM, "dout_sclk_mpwm", "mout_kfc", DIV_ISP, 20, 2),
 };
 
-static struct samsung_gate_clock isp_gate_clks[] __initdata = {
+static const struct samsung_gate_clock isp_gate_clks[] __initconst = {
 	GATE(ISP_CLK_GIC, "clk_isp_gic", "mout_aclk_isp1_266",
 			EN_IP_ISP0, 15, 0, 0),
 
@@ -914,7 +914,7 @@ CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp",
 
 /* CMU_KFC */
 
-static unsigned long kfc_clk_regs[] __initdata = {
+static const unsigned long kfc_clk_regs[] __initconst = {
 	KFC_PLL_LOCK,
 	KFC_PLL_CON0,
 	KFC_PLL_CON1,
@@ -932,13 +932,13 @@ static unsigned long kfc_clk_regs[] __initdata = {
 PNAME(mout_kfc_pll_p) = {"fin_pll", "fout_kfc_pll"};
 PNAME(mout_kfc_p)	 = {"mout_kfc_pll", "dout_media_pll"};
 
-static struct samsung_mux_clock kfc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock kfc_mux_clks[] __initconst = {
 	MUX(KFC_MOUT_KFC_PLL, "mout_kfc_pll", mout_kfc_pll_p,
 			MUX_SEL_KFC0, 0, 1),
 	MUX(KFC_MOUT_KFC, "mout_kfc", mout_kfc_p, MUX_SEL_KFC2, 0, 1),
 };
 
-static struct samsung_div_clock kfc_div_clks[] __initdata = {
+static const struct samsung_div_clock kfc_div_clks[] __initconst = {
 	DIV(KFC_DOUT_KFC1, "dout_kfc1", "mout_kfc", DIV_KFC, 0, 3),
 	DIV(KFC_DOUT_KFC2, "dout_kfc2", "dout_kfc1", DIV_KFC, 4, 3),
 	DIV(KFC_DOUT_KFC_ATCLK, "dout_kfc_atclk", "dout_kfc2", DIV_KFC, 8, 3),
@@ -949,7 +949,7 @@ static struct samsung_div_clock kfc_div_clks[] __initdata = {
 	DIV(KFC_DOUT_KFC_PLL, "dout_kfc_pll", "mout_kfc", DIV_KFC, 24, 3),
 };
 
-static struct samsung_pll_clock kfc_pll_clks[] __initdata = {
+static const struct samsung_pll_clock kfc_pll_clks[] __initconst = {
 	PLL(pll_2550xx, KFC_FOUT_KFC_PLL, "fout_kfc_pll", "fin_pll",
 		KFC_PLL_LOCK, KFC_PLL_CON0,
 		pll2550_24mhz_tbl),
@@ -978,7 +978,7 @@ CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc",
 
 /* CMU_MFC */
 
-static unsigned long mfc_clk_regs[] __initdata = {
+static const unsigned long mfc_clk_regs[] __initconst = {
 	MUX_SEL_MFC,
 	DIV_MFC,
 	EN_ACLK_MFC,
@@ -991,18 +991,18 @@ static unsigned long mfc_clk_regs[] __initdata = {
 
 PNAME(mout_aclk_mfc_333_user_p) = {"fin_pll", "dout_aclk_mfc_333"};
 
-static struct samsung_mux_clock mfc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock mfc_mux_clks[] __initconst = {
 	MUX(MFC_MOUT_ACLK_MFC_333_USER, "mout_aclk_mfc_333_user",
 			mout_aclk_mfc_333_user_p,
 			MUX_SEL_MFC, 0, 1),
 };
 
-static struct samsung_div_clock mfc_div_clks[] __initdata = {
+static const struct samsung_div_clock mfc_div_clks[] __initconst = {
 	DIV(MFC_DOUT_PCLK_MFC_83, "dout_pclk_mfc_83", "mout_aclk_mfc_333_user",
 			DIV_MFC, 0, 3),
 };
 
-static struct samsung_gate_clock mfc_gate_clks[] __initdata = {
+static const struct samsung_gate_clock mfc_gate_clks[] __initconst = {
 	GATE(MFC_CLK_MFC, "clk_mfc", "mout_aclk_mfc_333_user",
 			EN_IP_MFC, 1, 0, 0),
 	GATE(MFC_CLK_SMMU2_MFCM0, "clk_smmu2_mfcm0", "mout_aclk_mfc_333_user",
@@ -1034,7 +1034,7 @@ CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc",
 
 /* CMU_MIF */
 
-static unsigned long mif_clk_regs[] __initdata = {
+static const unsigned long mif_clk_regs[] __initconst = {
 	MEM_PLL_LOCK,
 	BUS_PLL_LOCK,
 	MEDIA_PLL_LOCK,
@@ -1076,7 +1076,7 @@ PNAME(mout_mif_drex2x_p) = {"dout_mem_pll", "dout_bus_pll"};
 PNAME(mout_clkm_phy_p) = {"mout_mif_drex", "dout_media_pll"};
 PNAME(mout_clk2x_phy_p) = {"mout_mif_drex2x", "dout_media_pll"};
 
-static struct samsung_mux_clock mif_mux_clks[] __initdata = {
+static const struct samsung_mux_clock mif_mux_clks[] __initconst = {
 	MUX(MIF_MOUT_MEM_PLL, "mout_mem_pll", mout_mem_pll_p,
 			MUX_SEL_MIF, 0, 1),
 	MUX(MIF_MOUT_BUS_PLL, "mout_bus_pll", mout_bus_pll_p,
@@ -1093,7 +1093,7 @@ static struct samsung_mux_clock mif_mux_clks[] __initdata = {
 			MUX_SEL_MIF, 24, 1),
 };
 
-static struct samsung_div_clock mif_div_clks[] __initdata = {
+static const struct samsung_div_clock mif_div_clks[] __initconst = {
 	DIV(MIF_DOUT_MEDIA_PLL, "dout_media_pll", "mout_media_pll",
 			DIV_MIF, 0, 3),
 	DIV(MIF_DOUT_MEM_PLL, "dout_mem_pll", "mout_mem_pll",
@@ -1112,7 +1112,7 @@ static struct samsung_div_clock mif_div_clks[] __initdata = {
 			DIV_MIF, 28, 4),
 };
 
-static struct samsung_gate_clock mif_gate_clks[] __initdata = {
+static const struct samsung_gate_clock mif_gate_clks[] __initconst = {
 	GATE(MIF_CLK_LPDDR3PHY_WRAP0, "clk_lpddr3phy_wrap0", "dout_clk2x_phy",
 			EN_IP_MIF, 12, CLK_IGNORE_UNUSED, 0),
 	GATE(MIF_CLK_LPDDR3PHY_WRAP1, "clk_lpddr3phy_wrap1", "dout_clk2x_phy",
@@ -1146,7 +1146,7 @@ static struct samsung_gate_clock mif_gate_clks[] __initdata = {
 			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_pll_clock mif_pll_clks[] __initdata = {
+static const struct samsung_pll_clock mif_pll_clks[] __initconst = {
 	PLL(pll_2550xx, MIF_FOUT_MEM_PLL, "fout_mem_pll", "fin_pll",
 		MEM_PLL_LOCK, MEM_PLL_CON0,
 		pll2550_24mhz_tbl),
@@ -1183,7 +1183,7 @@ CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif",
 
 /* CMU_PERI */
 
-static unsigned long peri_clk_regs[] __initdata = {
+static const unsigned long peri_clk_regs[] __initconst = {
 	MUX_SEL_PERI,
 	MUX_SEL_PERI1,
 	DIV_PERI,
@@ -1219,7 +1219,7 @@ PNAME(mout_sclk_i2scod_p) = {"ioclk_i2s_cdclk", "fin_pll", "dout_aclk_peri_aud",
 PNAME(mout_sclk_spdif_p) = {"ioclk_spdif_extclk", "fin_pll",
 			"dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
 
-static struct samsung_mux_clock peri_mux_clks[] __initdata = {
+static const struct samsung_mux_clock peri_mux_clks[] __initconst = {
 	MUX(PERI_MOUT_SCLK_PCM, "mout_sclk_pcm", mout_sclk_pcm_p,
 			MUX_SEL_PERI1, 4, 2),
 	MUX(PERI_MOUT_SCLK_I2SCOD, "mout_sclk_i2scod", mout_sclk_i2scod_p,
@@ -1228,12 +1228,12 @@ static struct samsung_mux_clock peri_mux_clks[] __initdata = {
 			MUX_SEL_PERI1, 20, 2),
 };
 
-static struct samsung_div_clock peri_div_clks[] __initdata = {
+static const struct samsung_div_clock peri_div_clks[] __initconst = {
 	DIV(PERI_DOUT_PCM, "dout_pcm", "mout_sclk_pcm", DIV_PERI, 0, 8),
 	DIV(PERI_DOUT_I2S, "dout_i2s", "mout_sclk_i2scod", DIV_PERI, 8, 6),
 };
 
-static struct samsung_gate_clock peri_gate_clks[] __initdata = {
+static const struct samsung_gate_clock peri_gate_clks[] __initconst = {
 	GATE(PERI_SCLK_PCM1, "sclk_pcm1", "dout_pcm", EN_SCLK_PERI, 0,
 			CLK_SET_RATE_PARENT, 0),
 	GATE(PERI_SCLK_I2S, "sclk_i2s", "dout_i2s", EN_SCLK_PERI, 1,
@@ -1389,7 +1389,7 @@ CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri",
 
 /* CMU_TOP */
 
-static unsigned long top_clk_regs[] __initdata = {
+static const unsigned long top_clk_regs[] __initconst = {
 	DISP_PLL_LOCK,
 	AUD_PLL_LOCK,
 	DISP_PLL_CON0,
@@ -1430,7 +1430,7 @@ static unsigned long top_clk_regs[] __initdata = {
 };
 
 /* fixed rate clocks generated inside the soc */
-static struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock fixed_rate_clks[] __initconst = {
 	FRATE(PHYCLK_DPTX_PHY_CH3_TXD_CLK, "phyclk_dptx_phy_ch3_txd_clk", NULL,
 			0, 270000000),
 	FRATE(PHYCLK_DPTX_PHY_CH2_TXD_CLK, "phyclk_dptx_phy_ch2_txd_clk", NULL,
@@ -1513,7 +1513,7 @@ PNAME(mout_sclk_fsys_mmc1_sdclkin_b_p) = {"mout_sclk_fsys_mmc1_sdclkin_a",
 PNAME(mout_sclk_fsys_mmc2_sdclkin_b_p) = {"mout_sclk_fsys_mmc2_sdclkin_a",
 			"mout_mediatop_pll_user"};
 
-static struct samsung_mux_clock top_mux_clks[] __initdata = {
+static const struct samsung_mux_clock top_mux_clks[] __initconst = {
 	MUX(TOP_MOUT_MEDIATOP_PLL_USER, "mout_mediatop_pll_user",
 			mout_mediatop_pll_user_p,
 			MUX_SEL_TOP_PLL0, 0, 1),
@@ -1673,7 +1673,7 @@ static struct samsung_mux_clock top_mux_clks[] __initdata = {
 			MUX_SEL_TOP_GSCL, 20, 1),
 };
 
-static struct samsung_div_clock top_div_clks[] __initdata = {
+static const struct samsung_div_clock top_div_clks[] __initconst = {
 	DIV(TOP_DOUT_ACLK_G2D_333, "dout_aclk_g2d_333", "mout_aclk_g2d_333",
 			DIV_TOP_G2D_MFC, 0, 3),
 	DIV(TOP_DOUT_ACLK_MFC_333, "dout_aclk_mfc_333", "mout_aclk_mfc_333",
@@ -1794,7 +1794,7 @@ static struct samsung_div_clock top_div_clks[] __initdata = {
 
 };
 
-static struct samsung_gate_clock top_gate_clks[] __initdata = {
+static const struct samsung_gate_clock top_gate_clks[] __initconst = {
 	GATE(TOP_SCLK_MMC0, "sclk_fsys_mmc0_sdclkin",
 			"dout_sclk_fsys_mmc0_sdclkin_b",
 			EN_SCLK_TOP, 7, CLK_SET_RATE_PARENT, 0),
@@ -1809,7 +1809,7 @@ static struct samsung_gate_clock top_gate_clks[] __initdata = {
 			CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_pll_clock top_pll_clks[] __initdata = {
+static const struct samsung_pll_clock top_pll_clks[] __initconst = {
 	PLL(pll_2550xx, TOP_FOUT_DISP_PLL, "fout_disp_pll", "fin_pll",
 		DISP_PLL_LOCK, DISP_PLL_CON0,
 		pll2550_24mhz_tbl),
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:06 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:06 +0200
Subject: [PATCH 10/18] clk: samsung: exynos5410: Constify all clock
 initializers
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-10-git-send-email-k.kozlowski@samsung.com>

All of initialization data can be made const.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos5410.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index d5d5dcabc4a9..8e8c7cca8c62 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -76,7 +76,7 @@ PNAME(group2_p)		= { "fin_pll", "fin_pll", "none", "none",
 			"none", "none", "sclk_mpll_bpll",
 			 "none", "none", "sclk_cpll" };
 
-static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
+static const struct samsung_mux_clock exynos5410_mux_clks[] __initconst = {
 	MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1),
 	MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
 
@@ -105,7 +105,7 @@ static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
 	MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1),
 };
 
-static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
+static const struct samsung_div_clock exynos5410_div_clks[] __initconst = {
 	DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
 	DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3),
 
@@ -141,7 +141,7 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 	DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3),
 };
 
-static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
+static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = {
 	GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
 
 	GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
@@ -167,7 +167,7 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 			SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
+static const struct samsung_pll_clock exynos5410_plls[nr_plls] __initconst = {
 	[apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
 		APLL_CON0, NULL),
 	[cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:09 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:09 +0200
Subject: [PATCH 13/18] clk: samsung: exynos7: Constify all clock initializers
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-13-git-send-email-k.kozlowski@samsung.com>

All of initialization data can be made const.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos7.c | 114 +++++++++++++++++++-------------------
 1 file changed, 57 insertions(+), 57 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
index ad68d463b12c..45b348c0cfc6 100644
--- a/drivers/clk/samsung/clk-exynos7.c
+++ b/drivers/clk/samsung/clk-exynos7.c
@@ -36,7 +36,7 @@
 #define ENABLE_ACLK_TOPC1	0x0804
 #define ENABLE_SCLK_TOPC1	0x0A04
 
-static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initconst = {
 	FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_topc_bus0_pll", 1, 2, 0),
 	FFACTOR(0, "ffac_topc_bus0_pll_div4",
 		"ffac_topc_bus0_pll_div2", 1, 2, 0),
@@ -69,7 +69,7 @@ PNAME(mout_topc_mfc_pll_half_p) = { "mout_topc_mfc_pll",
 PNAME(mout_topc_bus0_pll_out_p) = {"mout_topc_bus0_pll",
 	"ffac_topc_bus0_pll_div2"};
 
-static unsigned long topc_clk_regs[] __initdata = {
+static const unsigned long topc_clk_regs[] __initconst = {
 	CC_PLL_LOCK,
 	BUS0_PLL_LOCK,
 	BUS1_DPLL_LOCK,
@@ -89,7 +89,7 @@ static unsigned long topc_clk_regs[] __initdata = {
 	DIV_TOPC3,
 };
 
-static struct samsung_mux_clock topc_mux_clks[] __initdata = {
+static const struct samsung_mux_clock topc_mux_clks[] __initconst = {
 	MUX(0, "mout_topc_bus0_pll", mout_topc_bus0_pll_ctrl_p,
 		MUX_SEL_TOPC0, 0, 1),
 	MUX(0, "mout_topc_bus1_pll", mout_topc_bus1_pll_ctrl_p,
@@ -118,7 +118,7 @@ static struct samsung_mux_clock topc_mux_clks[] __initdata = {
 	MUX(0, "mout_aclk_peris_66", mout_topc_group2, MUX_SEL_TOPC3, 24, 2),
 };
 
-static struct samsung_div_clock topc_div_clks[] __initdata = {
+static const struct samsung_div_clock topc_div_clks[] __initconst = {
 	DIV(DOUT_ACLK_CCORE_133, "dout_aclk_ccore_133", "mout_aclk_ccore_133",
 		DIV_TOPC0, 4, 4),
 
@@ -139,12 +139,12 @@ static struct samsung_div_clock topc_div_clks[] __initdata = {
 		DIV_TOPC3, 28, 4),
 };
 
-static struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initdata = {
+static const struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initconst = {
 	PLL_36XX_RATE(491520000, 20, 1, 0, 31457),
 	{},
 };
 
-static struct samsung_gate_clock topc_gate_clks[] __initdata = {
+static const struct samsung_gate_clock topc_gate_clks[] __initconst = {
 	GATE(ACLK_CCORE_133, "aclk_ccore_133", "dout_aclk_ccore_133",
 		ENABLE_ACLK_TOPC0, 4, 0, 0),
 
@@ -174,7 +174,7 @@ static struct samsung_gate_clock topc_gate_clks[] __initdata = {
 		ENABLE_SCLK_TOPC1, 0, 0, 0),
 };
 
-static struct samsung_pll_clock topc_pll_clks[] __initdata = {
+static const struct samsung_pll_clock topc_pll_clks[] __initconst = {
 	PLL(pll_1451x, 0, "fout_bus0_pll", "fin_pll", BUS0_PLL_LOCK,
 		BUS0_PLL_CON0, NULL),
 	PLL(pll_1452x, 0, "fout_cc_pll", "fin_pll", CC_PLL_LOCK,
@@ -187,7 +187,7 @@ static struct samsung_pll_clock topc_pll_clks[] __initdata = {
 		AUD_PLL_CON0, pll1460x_24mhz_tbl),
 };
 
-static struct samsung_cmu_info topc_cmu_info __initdata = {
+static const struct samsung_cmu_info topc_cmu_info __initconst = {
 	.pll_clks		= topc_pll_clks,
 	.nr_pll_clks		= ARRAY_SIZE(topc_pll_clks),
 	.mux_clks		= topc_mux_clks,
@@ -256,7 +256,7 @@ PNAME(mout_top0_group3) = {"ioclk_audiocdclk0",
 PNAME(mout_top0_group4) = {"ioclk_audiocdclk1", "mout_top0_aud_pll_user",
 	"mout_top0_bus0_pll_half", "mout_top0_bus1_pll_half"};
 
-static unsigned long top0_clk_regs[] __initdata = {
+static const unsigned long top0_clk_regs[] __initconst = {
 	MUX_SEL_TOP00,
 	MUX_SEL_TOP01,
 	MUX_SEL_TOP03,
@@ -275,7 +275,7 @@ static unsigned long top0_clk_regs[] __initdata = {
 	ENABLE_SCLK_TOP0_PERIC3,
 };
 
-static struct samsung_mux_clock top0_mux_clks[] __initdata = {
+static const struct samsung_mux_clock top0_mux_clks[] __initconst = {
 	MUX(0, "mout_top0_aud_pll_user", mout_top0_aud_pll_user_p,
 		MUX_SEL_TOP00, 0, 1),
 	MUX(0, "mout_top0_mfc_pll_user", mout_top0_mfc_pll_user_p,
@@ -315,7 +315,7 @@ static struct samsung_mux_clock top0_mux_clks[] __initdata = {
 	MUX(0, "mout_sclk_spi4", mout_top0_group1, MUX_SEL_TOP0_PERIC3, 20, 2),
 };
 
-static struct samsung_div_clock top0_div_clks[] __initdata = {
+static const struct samsung_div_clock top0_div_clks[] __initconst = {
 	DIV(DOUT_ACLK_PERIC1, "dout_aclk_peric1_66", "mout_aclk_peric1_66",
 		DIV_TOP03, 12, 6),
 	DIV(DOUT_ACLK_PERIC0, "dout_aclk_peric0_66", "mout_aclk_peric0_66",
@@ -338,7 +338,7 @@ static struct samsung_div_clock top0_div_clks[] __initdata = {
 	DIV(0, "dout_sclk_spi4", "mout_sclk_spi4", DIV_TOP0_PERIC3, 20, 12),
 };
 
-static struct samsung_gate_clock top0_gate_clks[] __initdata = {
+static const struct samsung_gate_clock top0_gate_clks[] __initconst = {
 	GATE(CLK_ACLK_PERIC0_66, "aclk_peric0_66", "dout_aclk_peric0_66",
 		ENABLE_ACLK_TOP03, 20, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_ACLK_PERIC1_66, "aclk_peric1_66", "dout_aclk_peric1_66",
@@ -372,7 +372,7 @@ static struct samsung_gate_clock top0_gate_clks[] __initdata = {
 		ENABLE_SCLK_TOP0_PERIC3, 20, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initconst = {
 	FFACTOR(0, "ffac_top0_bus0_pll_div2", "mout_top0_bus0_pll_user",
 		1, 2, 0),
 	FFACTOR(0, "ffac_top0_bus1_pll_div2", "mout_top0_bus1_pll_user",
@@ -381,7 +381,7 @@ static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = {
 	FFACTOR(0, "ffac_top0_mfc_pll_div2", "mout_top0_mfc_pll_user", 1, 2, 0),
 };
 
-static struct samsung_cmu_info top0_cmu_info __initdata = {
+static const struct samsung_cmu_info top0_cmu_info __initconst = {
 	.mux_clks		= top0_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(top0_mux_clks),
 	.div_clks		= top0_div_clks,
@@ -438,7 +438,7 @@ PNAME(mout_top1_group1) = {"mout_top1_bus0_pll_half",
 	"mout_top1_bus1_pll_half", "mout_top1_cc_pll_half",
 	"mout_top1_mfc_pll_half"};
 
-static unsigned long top1_clk_regs[] __initdata = {
+static const unsigned long top1_clk_regs[] __initconst = {
 	MUX_SEL_TOP10,
 	MUX_SEL_TOP11,
 	MUX_SEL_TOP13,
@@ -455,7 +455,7 @@ static unsigned long top1_clk_regs[] __initdata = {
 	ENABLE_SCLK_TOP1_FSYS11,
 };
 
-static struct samsung_mux_clock top1_mux_clks[] __initdata = {
+static const struct samsung_mux_clock top1_mux_clks[] __initconst = {
 	MUX(0, "mout_top1_mfc_pll_user", mout_top1_mfc_pll_user_p,
 		MUX_SEL_TOP10, 4, 1),
 	MUX(0, "mout_top1_cc_pll_user", mout_top1_cc_pll_user_p,
@@ -494,7 +494,7 @@ static struct samsung_mux_clock top1_mux_clks[] __initdata = {
 		MUX_SEL_TOP1_FSYS11, 24, 2),
 };
 
-static struct samsung_div_clock top1_div_clks[] __initdata = {
+static const struct samsung_div_clock top1_div_clks[] __initconst = {
 	DIV(DOUT_ACLK_FSYS1_200, "dout_aclk_fsys1_200", "mout_aclk_fsys1_200",
 		DIV_TOP13, 24, 4),
 	DIV(DOUT_ACLK_FSYS0_200, "dout_aclk_fsys0_200", "mout_aclk_fsys0_200",
@@ -521,7 +521,7 @@ static struct samsung_div_clock top1_div_clks[] __initdata = {
 		"mout_sclk_phy_fsys1_26m", DIV_TOP1_FSYS11, 24, 6),
 };
 
-static struct samsung_gate_clock top1_gate_clks[] __initdata = {
+static const struct samsung_gate_clock top1_gate_clks[] __initconst = {
 	GATE(CLK_SCLK_MMC2, "sclk_mmc2", "dout_sclk_mmc2",
 		ENABLE_SCLK_TOP1_FSYS0, 16, CLK_SET_RATE_PARENT, 0),
 	GATE(0, "sclk_usbdrd300", "dout_sclk_usbdrd300",
@@ -548,7 +548,7 @@ static struct samsung_gate_clock top1_gate_clks[] __initdata = {
 		24, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initconst = {
 	FFACTOR(0, "ffac_top1_bus0_pll_div2", "mout_top1_bus0_pll_user",
 		1, 2, 0),
 	FFACTOR(0, "ffac_top1_bus1_pll_div2", "mout_top1_bus1_pll_user",
@@ -557,7 +557,7 @@ static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = {
 	FFACTOR(0, "ffac_top1_mfc_pll_div2", "mout_top1_mfc_pll_user", 1, 2, 0),
 };
 
-static struct samsung_cmu_info top1_cmu_info __initdata = {
+static const struct samsung_cmu_info top1_cmu_info __initconst = {
 	.mux_clks		= top1_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(top1_mux_clks),
 	.div_clks		= top1_div_clks,
@@ -591,22 +591,22 @@ CLK_OF_DECLARE(exynos7_clk_top1, "samsung,exynos7-clock-top1",
  */
 PNAME(mout_aclk_ccore_133_user_p)	= { "fin_pll", "aclk_ccore_133" };
 
-static unsigned long ccore_clk_regs[] __initdata = {
+static const unsigned long ccore_clk_regs[] __initconst = {
 	MUX_SEL_CCORE,
 	ENABLE_PCLK_CCORE,
 };
 
-static struct samsung_mux_clock ccore_mux_clks[] __initdata = {
+static const struct samsung_mux_clock ccore_mux_clks[] __initconst = {
 	MUX(0, "mout_aclk_ccore_133_user", mout_aclk_ccore_133_user_p,
 		MUX_SEL_CCORE, 1, 1),
 };
 
-static struct samsung_gate_clock ccore_gate_clks[] __initdata = {
+static const struct samsung_gate_clock ccore_gate_clks[] __initconst = {
 	GATE(PCLK_RTC, "pclk_rtc", "mout_aclk_ccore_133_user",
 		ENABLE_PCLK_CCORE, 8, 0, 0),
 };
 
-static struct samsung_cmu_info ccore_cmu_info __initdata = {
+static const struct samsung_cmu_info ccore_cmu_info __initconst = {
 	.mux_clks		= ccore_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(ccore_mux_clks),
 	.gate_clks		= ccore_gate_clks,
@@ -633,20 +633,20 @@ CLK_OF_DECLARE(exynos7_clk_ccore, "samsung,exynos7-clock-ccore",
 PNAME(mout_aclk_peric0_66_user_p)	= { "fin_pll", "aclk_peric0_66" };
 PNAME(mout_sclk_uart0_user_p)	= { "fin_pll", "sclk_uart0" };
 
-static unsigned long peric0_clk_regs[] __initdata = {
+static const unsigned long peric0_clk_regs[] __initconst = {
 	MUX_SEL_PERIC0,
 	ENABLE_PCLK_PERIC0,
 	ENABLE_SCLK_PERIC0,
 };
 
-static struct samsung_mux_clock peric0_mux_clks[] __initdata = {
+static const struct samsung_mux_clock peric0_mux_clks[] __initconst = {
 	MUX(0, "mout_aclk_peric0_66_user", mout_aclk_peric0_66_user_p,
 		MUX_SEL_PERIC0, 0, 1),
 	MUX(0, "mout_sclk_uart0_user", mout_sclk_uart0_user_p,
 		MUX_SEL_PERIC0, 16, 1),
 };
 
-static struct samsung_gate_clock peric0_gate_clks[] __initdata = {
+static const struct samsung_gate_clock peric0_gate_clks[] __initconst = {
 	GATE(PCLK_HSI2C0, "pclk_hsi2c0", "mout_aclk_peric0_66_user",
 		ENABLE_PCLK_PERIC0, 8, 0, 0),
 	GATE(PCLK_HSI2C1, "pclk_hsi2c1", "mout_aclk_peric0_66_user",
@@ -673,7 +673,7 @@ static struct samsung_gate_clock peric0_gate_clks[] __initdata = {
 	GATE(SCLK_PWM, "sclk_pwm", "fin_pll", ENABLE_SCLK_PERIC0, 21, 0, 0),
 };
 
-static struct samsung_cmu_info peric0_cmu_info __initdata = {
+static const struct samsung_cmu_info peric0_cmu_info __initconst = {
 	.mux_clks		= peric0_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(peric0_mux_clks),
 	.gate_clks		= peric0_gate_clks,
@@ -709,7 +709,7 @@ PNAME(mout_sclk_spi2_user_p)		= { "fin_pll", "sclk_spi2" };
 PNAME(mout_sclk_spi3_user_p)		= { "fin_pll", "sclk_spi3" };
 PNAME(mout_sclk_spi4_user_p)		= { "fin_pll", "sclk_spi4" };
 
-static unsigned long peric1_clk_regs[] __initdata = {
+static const unsigned long peric1_clk_regs[] __initconst = {
 	MUX_SEL_PERIC10,
 	MUX_SEL_PERIC11,
 	MUX_SEL_PERIC12,
@@ -717,7 +717,7 @@ static unsigned long peric1_clk_regs[] __initdata = {
 	ENABLE_SCLK_PERIC10,
 };
 
-static struct samsung_mux_clock peric1_mux_clks[] __initdata = {
+static const struct samsung_mux_clock peric1_mux_clks[] __initconst = {
 	MUX(0, "mout_aclk_peric1_66_user", mout_aclk_peric1_66_user_p,
 		MUX_SEL_PERIC10, 0, 1),
 
@@ -739,7 +739,7 @@ static struct samsung_mux_clock peric1_mux_clks[] __initdata = {
 		MUX_SEL_PERIC11, 28, 1),
 };
 
-static struct samsung_gate_clock peric1_gate_clks[] __initdata = {
+static const struct samsung_gate_clock peric1_gate_clks[] __initconst = {
 	GATE(PCLK_HSI2C2, "pclk_hsi2c2", "mout_aclk_peric1_66_user",
 		ENABLE_PCLK_PERIC1, 4, 0, 0),
 	GATE(PCLK_HSI2C3, "pclk_hsi2c3", "mout_aclk_peric1_66_user",
@@ -797,7 +797,7 @@ static struct samsung_gate_clock peric1_gate_clks[] __initdata = {
 		ENABLE_SCLK_PERIC10, 19, CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_cmu_info peric1_cmu_info __initdata = {
+static const struct samsung_cmu_info peric1_cmu_info __initconst = {
 	.mux_clks		= peric1_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(peric1_mux_clks),
 	.gate_clks		= peric1_gate_clks,
@@ -825,7 +825,7 @@ CLK_OF_DECLARE(exynos7_clk_peric1, "samsung,exynos7-clock-peric1",
 /* List of parent clocks for Muxes in CMU_PERIS */
 PNAME(mout_aclk_peris_66_user_p) = { "fin_pll", "aclk_peris_66" };
 
-static unsigned long peris_clk_regs[] __initdata = {
+static const unsigned long peris_clk_regs[] __initconst = {
 	MUX_SEL_PERIS,
 	ENABLE_PCLK_PERIS,
 	ENABLE_PCLK_PERIS_SECURE_CHIPID,
@@ -833,12 +833,12 @@ static unsigned long peris_clk_regs[] __initdata = {
 	ENABLE_SCLK_PERIS_SECURE_CHIPID,
 };
 
-static struct samsung_mux_clock peris_mux_clks[] __initdata = {
+static const struct samsung_mux_clock peris_mux_clks[] __initconst = {
 	MUX(0, "mout_aclk_peris_66_user",
 		mout_aclk_peris_66_user_p, MUX_SEL_PERIS, 0, 1),
 };
 
-static struct samsung_gate_clock peris_gate_clks[] __initdata = {
+static const struct samsung_gate_clock peris_gate_clks[] __initconst = {
 	GATE(PCLK_WDT, "pclk_wdt", "mout_aclk_peris_66_user",
 		ENABLE_PCLK_PERIS, 6, 0, 0),
 	GATE(PCLK_TMU, "pclk_tmu_apbif", "mout_aclk_peris_66_user",
@@ -852,7 +852,7 @@ static struct samsung_gate_clock peris_gate_clks[] __initdata = {
 	GATE(SCLK_TMU, "sclk_tmu", "fin_pll", ENABLE_SCLK_PERIS, 10, 0, 0),
 };
 
-static struct samsung_cmu_info peris_cmu_info __initdata = {
+static const struct samsung_cmu_info peris_cmu_info __initconst = {
 	.mux_clks		= peris_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(peris_mux_clks),
 	.gate_clks		= peris_gate_clks,
@@ -893,12 +893,12 @@ PNAME(mout_phyclk_usbdrd300_udrd30_pipe_pclk_user_p)	= { "fin_pll",
 				"phyclk_usbdrd300_udrd30_pipe_pclk" };
 
 /* fixed rate clocks used in the FSYS0 block */
-static struct samsung_fixed_rate_clock fixed_rate_clks_fsys0[] __initdata = {
+static const struct samsung_fixed_rate_clock fixed_rate_clks_fsys0[] __initconst = {
 	FRATE(0, "phyclk_usbdrd300_udrd30_phyclock", NULL, 0, 60000000),
 	FRATE(0, "phyclk_usbdrd300_udrd30_pipe_pclk", NULL, 0, 125000000),
 };
 
-static unsigned long fsys0_clk_regs[] __initdata = {
+static const unsigned long fsys0_clk_regs[] __initconst = {
 	MUX_SEL_FSYS00,
 	MUX_SEL_FSYS01,
 	MUX_SEL_FSYS02,
@@ -909,7 +909,7 @@ static unsigned long fsys0_clk_regs[] __initdata = {
 	ENABLE_SCLK_FSYS04,
 };
 
-static struct samsung_mux_clock fsys0_mux_clks[] __initdata = {
+static const struct samsung_mux_clock fsys0_mux_clks[] __initconst = {
 	MUX(0, "mout_aclk_fsys0_200_user", mout_aclk_fsys0_200_user_p,
 		MUX_SEL_FSYS00, 24, 1),
 
@@ -926,7 +926,7 @@ static struct samsung_mux_clock fsys0_mux_clks[] __initdata = {
 		MUX_SEL_FSYS02, 28, 1),
 };
 
-static struct samsung_gate_clock fsys0_gate_clks[] __initdata = {
+static const struct samsung_gate_clock fsys0_gate_clks[] __initconst = {
 	GATE(ACLK_PDMA1, "aclk_pdma1", "mout_aclk_fsys0_200_user",
 			ENABLE_ACLK_FSYS00, 3, 0, 0),
 	GATE(ACLK_PDMA0, "aclk_pdma0", "mout_aclk_fsys0_200_user",
@@ -960,7 +960,7 @@ static struct samsung_gate_clock fsys0_gate_clks[] __initdata = {
 		ENABLE_SCLK_FSYS04, 28, 0, 0),
 };
 
-static struct samsung_cmu_info fsys0_cmu_info __initdata = {
+static const struct samsung_cmu_info fsys0_cmu_info __initconst = {
 	.fixed_clks		= fixed_rate_clks_fsys0,
 	.nr_fixed_clks		= ARRAY_SIZE(fixed_rate_clks_fsys0),
 	.mux_clks		= fsys0_mux_clks,
@@ -1005,7 +1005,7 @@ PNAME(mout_phyclk_ufs20_rx0_user_p) = { "fin_pll", "phyclk_ufs20_rx0_symbol" };
 PNAME(mout_phyclk_ufs20_rx1_user_p) = { "fin_pll", "phyclk_ufs20_rx1_symbol" };
 
 /* fixed rate clocks used in the FSYS1 block */
-static struct samsung_fixed_rate_clock fixed_rate_clks_fsys1[] __initdata = {
+static const struct samsung_fixed_rate_clock fixed_rate_clks_fsys1[] __initconst = {
 	FRATE(PHYCLK_UFS20_TX0_SYMBOL, "phyclk_ufs20_tx0_symbol", NULL,
 			0, 300000000),
 	FRATE(PHYCLK_UFS20_RX0_SYMBOL, "phyclk_ufs20_rx0_symbol", NULL,
@@ -1014,7 +1014,7 @@ static struct samsung_fixed_rate_clock fixed_rate_clks_fsys1[] __initdata = {
 			0, 300000000),
 };
 
-static unsigned long fsys1_clk_regs[] __initdata = {
+static const unsigned long fsys1_clk_regs[] __initconst = {
 	MUX_SEL_FSYS10,
 	MUX_SEL_FSYS11,
 	MUX_SEL_FSYS12,
@@ -1026,7 +1026,7 @@ static unsigned long fsys1_clk_regs[] __initdata = {
 	ENABLE_SCLK_FSYS13,
 };
 
-static struct samsung_mux_clock fsys1_mux_clks[] __initdata = {
+static const struct samsung_mux_clock fsys1_mux_clks[] __initconst = {
 	MUX(MOUT_FSYS1_PHYCLK_SEL1, "mout_fsys1_phyclk_sel1",
 		mout_fsys1_group_p, MUX_SEL_FSYS10, 16, 2),
 	MUX(0, "mout_fsys1_phyclk_sel0", mout_fsys1_group_p,
@@ -1049,12 +1049,12 @@ static struct samsung_mux_clock fsys1_mux_clks[] __initdata = {
 		mout_phyclk_ufs20_tx0_user_p, MUX_SEL_FSYS12, 28, 1),
 };
 
-static struct samsung_div_clock fsys1_div_clks[] __initdata = {
+static const struct samsung_div_clock fsys1_div_clks[] __initconst = {
 	DIV(DOUT_PCLK_FSYS1, "dout_pclk_fsys1", "mout_aclk_fsys1_200_user",
 		DIV_FSYS1, 0, 2),
 };
 
-static struct samsung_gate_clock fsys1_gate_clks[] __initdata = {
+static const struct samsung_gate_clock fsys1_gate_clks[] __initconst = {
 	GATE(SCLK_UFSUNIPRO20_USER, "sclk_ufsunipro20_user",
 		"mout_sclk_ufsunipro20_user",
 		ENABLE_SCLK_FSYS11, 20, 0, 0),
@@ -1089,7 +1089,7 @@ static struct samsung_gate_clock fsys1_gate_clks[] __initdata = {
 		ENABLE_SCLK_FSYS13, 24, CLK_IGNORE_UNUSED, 0),
 };
 
-static struct samsung_cmu_info fsys1_cmu_info __initdata = {
+static const struct samsung_cmu_info fsys1_cmu_info __initconst = {
 	.fixed_clks		= fixed_rate_clks_fsys1,
 	.nr_fixed_clks		= ARRAY_SIZE(fixed_rate_clks_fsys1),
 	.mux_clks		= fsys1_mux_clks,
@@ -1119,22 +1119,22 @@ CLK_OF_DECLARE(exynos7_clk_fsys1, "samsung,exynos7-clock-fsys1",
 /* List of parent clocks for Muxes in CMU_MSCL */
 PNAME(mout_aclk_mscl_532_user_p)	= { "fin_pll", "aclk_mscl_532" };
 
-static unsigned long mscl_clk_regs[] __initdata = {
+static const unsigned long mscl_clk_regs[] __initconst = {
 	MUX_SEL_MSCL,
 	DIV_MSCL,
 	ENABLE_ACLK_MSCL,
 	ENABLE_PCLK_MSCL,
 };
 
-static struct samsung_mux_clock mscl_mux_clks[] __initdata = {
+static const struct samsung_mux_clock mscl_mux_clks[] __initconst = {
 	MUX(USERMUX_ACLK_MSCL_532, "usermux_aclk_mscl_532",
 		mout_aclk_mscl_532_user_p, MUX_SEL_MSCL, 0, 1),
 };
-static struct samsung_div_clock mscl_div_clks[] __initdata = {
+static const struct samsung_div_clock mscl_div_clks[] __initconst = {
 	DIV(DOUT_PCLK_MSCL, "dout_pclk_mscl", "usermux_aclk_mscl_532",
 			DIV_MSCL, 0, 3),
 };
-static struct samsung_gate_clock mscl_gate_clks[] __initdata = {
+static const struct samsung_gate_clock mscl_gate_clks[] __initconst = {
 
 	GATE(ACLK_MSCL_0, "aclk_mscl_0", "usermux_aclk_mscl_532",
 			ENABLE_ACLK_MSCL, 31, 0, 0),
@@ -1204,7 +1204,7 @@ static struct samsung_gate_clock mscl_gate_clks[] __initdata = {
 			ENABLE_PCLK_MSCL, 20, 0, 0),
 };
 
-static struct samsung_cmu_info mscl_cmu_info __initdata = {
+static const struct samsung_cmu_info mscl_cmu_info __initconst = {
 	.mux_clks		= mscl_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(mscl_mux_clks),
 	.div_clks		= mscl_div_clks,
@@ -1238,7 +1238,7 @@ CLK_OF_DECLARE(exynos7_clk_mscl, "samsung,exynos7-clock-mscl",
 PNAME(mout_aud_pll_user_p) = { "fin_pll", "fout_aud_pll" };
 PNAME(mout_aud_group_p) = { "dout_aud_cdclk", "ioclk_audiocdclk0" };
 
-static unsigned long aud_clk_regs[] __initdata = {
+static const unsigned long aud_clk_regs[] __initconst = {
 	MUX_SEL_AUD,
 	DIV_AUD0,
 	DIV_AUD1,
@@ -1247,13 +1247,13 @@ static unsigned long aud_clk_regs[] __initdata = {
 	ENABLE_SCLK_AUD,
 };
 
-static struct samsung_mux_clock aud_mux_clks[] __initdata = {
+static const struct samsung_mux_clock aud_mux_clks[] __initconst = {
 	MUX(0, "mout_sclk_i2s", mout_aud_group_p, MUX_SEL_AUD, 12, 1),
 	MUX(0, "mout_sclk_pcm", mout_aud_group_p, MUX_SEL_AUD, 16, 1),
 	MUX(0, "mout_aud_pll_user", mout_aud_pll_user_p, MUX_SEL_AUD, 20, 1),
 };
 
-static struct samsung_div_clock aud_div_clks[] __initdata = {
+static const struct samsung_div_clock aud_div_clks[] __initconst = {
 	DIV(0, "dout_aud_ca5", "mout_aud_pll_user", DIV_AUD0, 0, 4),
 	DIV(0, "dout_aclk_aud", "dout_aud_ca5", DIV_AUD0, 4, 4),
 	DIV(0, "dout_aud_pclk_dbg", "dout_aud_ca5", DIV_AUD0, 8, 4),
@@ -1265,7 +1265,7 @@ static struct samsung_div_clock aud_div_clks[] __initdata = {
 	DIV(0, "dout_aud_cdclk", "mout_aud_pll_user", DIV_AUD1, 24, 4),
 };
 
-static struct samsung_gate_clock aud_gate_clks[] __initdata = {
+static const struct samsung_gate_clock aud_gate_clks[] __initconst = {
 	GATE(SCLK_PCM, "sclk_pcm", "dout_sclk_pcm",
 			ENABLE_SCLK_AUD, 27, CLK_SET_RATE_PARENT, 0),
 	GATE(SCLK_I2S, "sclk_i2s", "dout_sclk_i2s",
@@ -1293,7 +1293,7 @@ static struct samsung_gate_clock aud_gate_clks[] __initdata = {
 	GATE(ACLK_ADMA, "aclk_dmac", "dout_aclk_aud", ENABLE_ACLK_AUD, 31, 0, 0),
 };
 
-static struct samsung_cmu_info aud_cmu_info __initdata = {
+static const struct samsung_cmu_info aud_cmu_info __initconst = {
 	.mux_clks		= aud_mux_clks,
 	.nr_mux_clks		= ARRAY_SIZE(aud_mux_clks),
 	.div_clks		= aud_div_clks,
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 11 05:02:14 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:02:14 +0200
Subject: [PATCH 18/18] clk: samsung: Fully constify mux parent names
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968134-6085-18-git-send-email-k.kozlowski@samsung.com>

The PNAME macro defines array of strings for names of mux parents.
Although the strings itself were const but pointers to them were not thus
this data resided in initdata. Make this an array of const pointers to
const strings and move to initconst section.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 61db98dd01a2..77d4657a95c5 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -261,7 +261,7 @@ struct samsung_gate_clock {
 #define GATE_DA(_id, dname, cname, pname, o, b, f, gf, a)	\
 	__GATE(_id, dname, cname, pname, o, b, f, gf, a)
 
-#define PNAME(x) static const char *x[] __initdata
+#define PNAME(x) static const char * const x[] __initconst
 
 /**
  * struct samsung_clk_reg_dump: register dump of clock controller registers.
-- 
1.9.1



From christoffer.dall at linaro.org  Wed May 11 05:05:33 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 14:05:33 +0200
Subject: [PATCH v3 23/55] KVM: arm/arm64: vgic-new: Add CTLR, TYPER and
 IIDR handlers
In-Reply-To: <1462531568-9799-24-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-24-git-send-email-andre.przywara@arm.com>
Message-ID: <20160511120533.GM27623@cbox>

On Fri, May 06, 2016 at 11:45:36AM +0100, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Those three registers are v2 emulation specific, so their implementation
> lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
> as their implementation is pretty simple.
> When the guest enables the distributor, we kick all VCPUs to get
> potentially pending interrupts serviced.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - kick VCPUs is the distributor gets enabled
> - improve comment
> 
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> - use switch() statements to improve readability
> 
> Changelog v2 .. v3:
> - add vgic_kick_vcpus() implementation
> 
>  include/linux/irqchip/arm-gic.h  |  1 +
>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 48 +++++++++++++++++++++++++++++++++++++++-
>  virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
>  virt/kvm/arm/vgic/vgic.h         |  4 ++++
>  4 files changed, 67 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
> index be0d26f..fd05185 100644
> --- a/include/linux/irqchip/arm-gic.h
> +++ b/include/linux/irqchip/arm-gic.h
> @@ -33,6 +33,7 @@
>  
>  #define GIC_DIST_CTRL			0x000
>  #define GIC_DIST_CTR			0x004
> +#define GIC_DIST_IIDR			0x008
>  #define GIC_DIST_IGROUP			0x080
>  #define GIC_DIST_ENABLE_SET		0x100
>  #define GIC_DIST_ENABLE_CLEAR		0x180
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 2729a22..69e96f7 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -20,9 +20,55 @@
>  #include "vgic.h"
>  #include "vgic-mmio.h"
>  
> +static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
> +					    gpa_t addr, unsigned int len)
> +{
> +	u32 value;
> +
> +	switch (addr & 0x0c) {
> +	case GIC_DIST_CTRL:
> +		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
> +		break;
> +	case GIC_DIST_CTR:
> +		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
> +		value = (value >> 5) - 1;
> +		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
> +		break;
> +	case GIC_DIST_IIDR:
> +		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
> +		break;
> +	default:
> +		return 0;
> +	}
> +
> +	return extract_bytes(value, addr & 3, len);
> +}
> +
> +static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len,
> +				    unsigned long val)
> +{
> +	switch (addr & 0x0c) {
> +	case GIC_DIST_CTRL:
> +		if (!(addr & 1)) {

what is this !(addr & 1) check?

> +			struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
> +			bool was_enabled = dist->enabled;
> +
> +			dist->enabled = val & GICD_ENABLE;
> +			if (!was_enabled && dist->enabled)
> +				vgic_kick_vcpus(vcpu->kvm);
> +		}
> +		break;
> +	case GIC_DIST_CTR:
> +	case GIC_DIST_IIDR:
> +		/* Nothing to do */
> +		return;
> +	}
> +}
> +
>  static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 12),
> +		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index c3dbcf3..5355de6 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -544,3 +544,18 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
>  
>  	return pending;
>  }
> +
> +void vgic_kick_vcpus(struct kvm *kvm)
> +{
> +	struct kvm_vcpu *vcpu;
> +	int c;
> +
> +	/*
> +	 * We've injected an interrupt, time to find out who deserves
> +	 * a good kick...
> +	 */
> +	kvm_for_each_vcpu(c, vcpu, kvm) {
> +		if (kvm_vgic_vcpu_pending_irq(vcpu))
> +			kvm_vcpu_kick(vcpu);
> +	}
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index fd9acaa..cf62015 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -16,11 +16,15 @@
>  #ifndef __KVM_ARM_VGIC_NEW_H__
>  #define __KVM_ARM_VGIC_NEW_H__
>  
> +#define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
> +#define IMPLEMENTER_ARM		0x43b
> +
>  #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
>  
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid);
>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
> +void vgic_kick_vcpus(struct kvm *kvm);
>  
>  void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
>  void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
> -- 
> 2.7.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From k.kozlowski at samsung.com  Wed May 11 05:12:16 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:12:16 +0200
Subject: [PATCH] clk: samsung: exynos3250: Move PLL rates data to init section
In-Reply-To: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
References: <1462968134-6085-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1462968736-7568-1-git-send-email-k.kozlowski@samsung.com>

The arrays with initialization data of PLLs can be moved to initconst
section because they are referenced only from other initconst-level
symbols.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos3250.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index 057c3f0d0e35..b2513959252d 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -669,7 +669,7 @@ static const struct samsung_gate_clock gate_clks[] __initconst = {
 };
 
 /* APLL & MPLL & BPLL & UPLL */
-static const struct samsung_pll_rate_table exynos3250_pll_rates[] = {
+static const struct samsung_pll_rate_table exynos3250_pll_rates[] __initconst = {
 	PLL_35XX_RATE(1200000000, 400, 4, 1),
 	PLL_35XX_RATE(1100000000, 275, 3, 1),
 	PLL_35XX_RATE(1066000000, 533, 6, 1),
@@ -691,7 +691,7 @@ static const struct samsung_pll_rate_table exynos3250_pll_rates[] = {
 };
 
 /* EPLL */
-static const struct samsung_pll_rate_table exynos3250_epll_rates[] = {
+static const struct samsung_pll_rate_table exynos3250_epll_rates[] __initconst = {
 	PLL_36XX_RATE(800000000, 200, 3, 1,     0),
 	PLL_36XX_RATE(288000000,  96, 2, 2,     0),
 	PLL_36XX_RATE(192000000, 128, 2, 3,     0),
-- 
1.9.1



From javier at osg.samsung.com  Wed May 11 05:14:51 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 11 May 2016 08:14:51 -0400
Subject: [PATCH 2/2] ARM: multi_v7_defconfig: Enable Exynos MFC driver as
 module
In-Reply-To: <5732D0BF.3020207@samsung.com>
References: <1462914448-24480-1-git-send-email-javier@osg.samsung.com>
 <1462914448-24480-2-git-send-email-javier@osg.samsung.com>
 <5732D0BF.3020207@samsung.com>
Message-ID: <d36b1ca3-413a-8a19-ad96-0775593e4337@osg.samsung.com>

Hello Krzysztof,

On 05/11/2016 02:27 AM, Krzysztof Kozlowski wrote:
> On 05/10/2016 11:07 PM, Javier Martinez Canillas wrote:
>> Exynos SoCs have a Multi Format Video Hardware Codec (MFC) IP block that
>> can be used to {en,de}code video streams by hardware. Enable support for
>> its driver as a module so the MFC can be tested.
>>
>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>
>> ---
>>
>> This patch depends on https://patchwork.kernel.org/patch/8970711/
>>
>>  arch/arm/configs/multi_v7_defconfig | 1 +
>>  1 file changed, 1 insertion(+)
> 
> 
> Both patches look good but only exynos_defconfig ended in Patchwork.
> This one did not... because you forgot to Cc the samsung-soc list.
>

Sigh, this time I used the cc list suggested by get_maintainers.pl and
forgot to double check if was complete. I'll resend and cc samsung-soc.
 
> Best regards,
> Krzysztod
> 

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From shawnguo at kernel.org  Wed May 11 05:15:12 2016
From: shawnguo at kernel.org (Shawn Guo)
Date: Wed, 11 May 2016 20:15:12 +0800
Subject: [GIT PULL] i.MX clock fixes for 4.6, take 2
In-Reply-To: <20160506180217.GW3492@codeaurora.org>
References: <20160503133605.GN5874@tiger>
 <20160506180217.GW3492@codeaurora.org>
Message-ID: <20160511121512.GP5874@tiger>

On Fri, May 06, 2016 at 11:02:17AM -0700, Stephen Boyd wrote:
> On 05/03, Shawn Guo wrote:
> > The following changes since commit 7196c52c9377df0175b510ff5896bda524f7345e:
> > 
> >   clk: imx6q: fix typo in CAN clock definition (2016-04-13 15:27:15 +0800)
> > 
> > are available in the git repository at:
> > 
> >   git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-clk-fixes-4.6-2
> > 
> > for you to fetch changes up to 3397c2c45b1b6f54834dfeae30a73046f33ca943:
> > 
> >   ARM: dts: imx35: restore existing used clock enumeration (2016-04-18 12:37:21 +0800)
> > 
> > ----------------------------------------------------------------
> > The i.MX clock fixes for 4.6, take 2:
> >  - Fix the commit 3713e3f5e927 ("clk: imx35: define two clocks for rtc")
> >    which messed up the clock enumeration when adding new clock.
> 
> This commit wasn't introduced in this merge window, so I'm going
> to pull this into clk-next unless you have some justification.

That's fine.  Thanks, Stephen.

Shawn


From k.kozlowski at samsung.com  Wed May 11 05:17:11 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:17:11 +0200
Subject: [PATCH 2/2] ARM: multi_v7_defconfig: Enable Exynos MFC driver as
 module
In-Reply-To: <d36b1ca3-413a-8a19-ad96-0775593e4337@osg.samsung.com>
References: <1462914448-24480-1-git-send-email-javier@osg.samsung.com>
 <1462914448-24480-2-git-send-email-javier@osg.samsung.com>
 <5732D0BF.3020207@samsung.com>
 <d36b1ca3-413a-8a19-ad96-0775593e4337@osg.samsung.com>
Message-ID: <573322C7.40203@samsung.com>

On 05/11/2016 02:14 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/11/2016 02:27 AM, Krzysztof Kozlowski wrote:
>> On 05/10/2016 11:07 PM, Javier Martinez Canillas wrote:
>>> Exynos SoCs have a Multi Format Video Hardware Codec (MFC) IP block that
>>> can be used to {en,de}code video streams by hardware. Enable support for
>>> its driver as a module so the MFC can be tested.
>>>
>>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>>
>>> ---
>>>
>>> This patch depends on https://patchwork.kernel.org/patch/8970711/
>>>
>>>  arch/arm/configs/multi_v7_defconfig | 1 +
>>>  1 file changed, 1 insertion(+)
>>
>>
>> Both patches look good but only exynos_defconfig ended in Patchwork.
>> This one did not... because you forgot to Cc the samsung-soc list.
>>
> 
> Sigh, this time I used the cc list suggested by get_maintainers.pl and
> forgot to double check if was complete. I'll resend and cc samsung-soc.

No need. I found it on arm-kernel patchwork and I will apply it from there.

Best regards,
Krzysztof



From linus.walleij at linaro.org  Wed May 11 05:17:11 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 11 May 2016 14:17:11 +0200
Subject: [PATCH v2 2/4] documentation: Add compatibles for Amlogic Meson
 GXBB pin controllers
In-Reply-To: <CAOQ7t2ZesQPPXTXEPRhF8TqzK-0c7VjH-_2ZKuxAOcd3-Z0uQQ@mail.gmail.com>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
 <1462176138-29433-3-git-send-email-carlo@caione.org>
 <CACRpkdZQHX2YFh7CFpaagrY+BBtyAejdUs4F7ow+3+9+F6mU-A@mail.gmail.com>
 <CAOQ7t2ZesQPPXTXEPRhF8TqzK-0c7VjH-_2ZKuxAOcd3-Z0uQQ@mail.gmail.com>
Message-ID: <CACRpkdZyLZREU28bXtHwLkbXJ2Y8QVTe-5P-RT24o3Bp-c-71w@mail.gmail.com>

On Wed, May 11, 2016 at 1:25 PM, Carlo Caione <carlo at caione.org> wrote:
> On Wed, May 11, 2016 at 10:52 AM, Linus Walleij
> <linus.walleij at linaro.org> wrote:
>> On Mon, May 2, 2016 at 10:02 AM, Carlo Caione <carlo at caione.org> wrote:
>>
>>> From: Carlo Caione <carlo at endlessm.com>
>>>
>>> Add the two new compatibles for the Amlogic Meson GXBB pin controllers.
>>>
>>> Signed-off-by: Carlo Caione <carlo at endlessm.com>
>>> ---
>>>  Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt | 2 ++
>>>  1 file changed, 2 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
>>> index 32f4a2d..fe7fe0b 100644
>>> --- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
>>> +++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
>>> @@ -5,6 +5,8 @@ Required properties for the root node:
>>>                       "amlogic,meson8b-cbus-pinctrl"
>>>                       "amlogic,meson8-aobus-pinctrl"
>>>                       "amlogic,meson8b-aobus-pinctrl"
>>> +                     "amlogic,meson-gxbb-periphs-pinctrl"
>>> +                     "amlogic,meson-gxbb-aobus-pinctrl"
>>>   - reg: address and size of registers controlling irq functionality
>>
>> This does NOT apply to the pin control tree because upstream does
>> NOT look like this. It looks like that in linux-next however.
>
> Linus master looks like that
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt

Aha so it was merged by some other tree during the release cycle.
OK sorry, I was confused.

> If you want I can merge it through my tree with the DTS changes.

Sure that makes things easier for me, else I need to backmerge the
-rc6 or something.

Yours,
Linus Walleij


From javier at osg.samsung.com  Wed May 11 05:18:28 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 11 May 2016 08:18:28 -0400
Subject: [PATCH 2/2] ARM: multi_v7_defconfig: Enable Exynos MFC driver as
 module
In-Reply-To: <573322C7.40203@samsung.com>
References: <1462914448-24480-1-git-send-email-javier@osg.samsung.com>
 <1462914448-24480-2-git-send-email-javier@osg.samsung.com>
 <5732D0BF.3020207@samsung.com>
 <d36b1ca3-413a-8a19-ad96-0775593e4337@osg.samsung.com>
 <573322C7.40203@samsung.com>
Message-ID: <0623124f-a588-e8ca-2048-c3f7e1ff6506@osg.samsung.com>

Hello Krzysztof,

On 05/11/2016 08:17 AM, Krzysztof Kozlowski wrote:
> On 05/11/2016 02:14 PM, Javier Martinez Canillas wrote:
>> Hello Krzysztof,
>>
>> On 05/11/2016 02:27 AM, Krzysztof Kozlowski wrote:
>>> On 05/10/2016 11:07 PM, Javier Martinez Canillas wrote:
>>>> Exynos SoCs have a Multi Format Video Hardware Codec (MFC) IP block that
>>>> can be used to {en,de}code video streams by hardware. Enable support for
>>>> its driver as a module so the MFC can be tested.
>>>>
>>>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>>>
>>>> ---
>>>>
>>>> This patch depends on https://patchwork.kernel.org/patch/8970711/
>>>>
>>>>  arch/arm/configs/multi_v7_defconfig | 1 +
>>>>  1 file changed, 1 insertion(+)
>>>
>>>
>>> Both patches look good but only exynos_defconfig ended in Patchwork.
>>> This one did not... because you forgot to Cc the samsung-soc list.
>>>
>>
>> Sigh, this time I used the cc list suggested by get_maintainers.pl and
>> forgot to double check if was complete. I'll resend and cc samsung-soc.
> 
> No need. I found it on arm-kernel patchwork and I will apply it from there.
>

Great, thanks a lot for your help.
 
> Best regards,
> Krzysztof
> 

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From arnd at arndb.de  Wed May 11 05:18:24 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 14:18:24 +0200
Subject: [PATCH] ARM: aspeed: adapt defconfigs for new CONFIG_PRINTK_TIME
Message-ID: <1462969128-4070058-1-git-send-email-arnd@arndb.de>

Commit 94ea9c7a579f ("lib, switch CONFIG_PRINTK_TIME to int") changes
the type of CONFIG_PRINTK_TIME and adapts all existing defconfig files,
while we add two new defconfig files with d0bc3483da87 ("arm/configs:
Add Aspeed defconfig"), with the old type.

This changes the two new defconfig files to match the other ones.
As a result, we get harmless warnings for the arm-soc defconfig
branch by itself, but everything will work when 4.7-rc1 is out.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
I've applied this one to avoid introducing warnings in linux-next.
I could have sorted out the ordering as well to avoid warnings
in arm-soc/for-next, but it doesn't seem worth it as we are not
regressing here.

 arch/arm/configs/aspeed_g4_defconfig | 2 +-
 arch/arm/configs/aspeed_g5_defconfig | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig
index ca39c04fec6b..b6e54ee9bdbd 100644
--- a/arch/arm/configs/aspeed_g4_defconfig
+++ b/arch/arm/configs/aspeed_g4_defconfig
@@ -58,7 +58,7 @@ CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_FIRMWARE_MEMMAP=y
 CONFIG_FANOTIFY=y
-CONFIG_PRINTK_TIME=y
+CONFIG_PRINTK_TIME=1
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_STRIP_ASM_SYMS=y
 CONFIG_PAGE_POISONING=y
diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig
index 4f366b0370e9..892605167357 100644
--- a/arch/arm/configs/aspeed_g5_defconfig
+++ b/arch/arm/configs/aspeed_g5_defconfig
@@ -59,7 +59,7 @@ CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_FIRMWARE_MEMMAP=y
 CONFIG_FANOTIFY=y
-CONFIG_PRINTK_TIME=y
+CONFIG_PRINTK_TIME=1
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_STRIP_ASM_SYMS=y
 CONFIG_PAGE_POISONING=y
-- 
2.7.0



From linus.walleij at linaro.org  Wed May 11 05:19:27 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 11 May 2016 14:19:27 +0200
Subject: [PATCH] pinctrl: meson: Fix eth_tx_en bit index
In-Reply-To: <CAOQ7t2bK-9Ogw4aRhLYPFFJrwEevq_SuOJ6LjxwhJrJgcW+e-A@mail.gmail.com>
References: <1462730389-10961-1-git-send-email-serveralex@gmail.com>
 <1462730389-10961-2-git-send-email-serveralex@gmail.com>
 <CACRpkdZz631dio28wqa71uZe3=NSZO55RCxZaQSixfH-o1f4Cw@mail.gmail.com>
 <CAOQ7t2bK-9Ogw4aRhLYPFFJrwEevq_SuOJ6LjxwhJrJgcW+e-A@mail.gmail.com>
Message-ID: <CACRpkdY7SfFN3LqAowNSyit0sV6W0J4fENEtBhLfmfnPg+xSPA@mail.gmail.com>

On Wed, May 11, 2016 at 11:13 AM, Carlo Caione <carlo at caione.org> wrote:
> On Wed, May 11, 2016 at 10:58 AM, Linus Walleij
> <linus.walleij at linaro.org> wrote:
>> On Sun, May 8, 2016 at 7:59 PM, Alexander M?ller <serveralex at gmail.com> wrote:
>>
>>> Fix pinctrl eth_tx_en bit index according to Hardkernel ODROID-C1 datasheet.
>>>
>>> Signed-off-by: Alexander M?ller <serveralex at gmail.com>
>>
>> Carlo can you review this change?
>
> Acked-by: Carlo Caione <carlo at endlessm.com>

Thanks, patch applied with your ACK.

> just to let you know this patch has been posted also as part of a
> bigger patchset here
> http://permalink.gmane.org/gmane.linux.ports.arm.kernel/498960

Yeah I saw. But it seemed like an orthogonal fix so I better just
merge it now into the pin control tree.

Yours,
Linus Walleij


From andy.shevchenko at gmail.com  Wed May 11 05:19:58 2016
From: andy.shevchenko at gmail.com (Andy Shevchenko)
Date: Wed, 11 May 2016 15:19:58 +0300
Subject: [PATCH v9 2/2] gpio: move clps711x, moxart, ts4800 and gpio-ge
 into gpio-mmio
In-Reply-To: <85c74586dbd0023306f012764b85d6aa168b4ae7.1462911225.git.chunkeey@googlemail.com>
References: <cover.1462911225.git.chunkeey@googlemail.com>
 <85c74586dbd0023306f012764b85d6aa168b4ae7.1462911225.git.chunkeey@googlemail.com>
Message-ID: <CAHp75Vfuu1rsmzoden-kSa_+sQRvoLyAGr=xiqyrnzk9ee4YzA@mail.gmail.com>

On Wed, May 11, 2016 at 12:34 PM, Christian Lamparter
<chunkeey at googlemail.com> wrote:
> This patch integrates the GPIO drivers for the following
> boards, SoCs, etc. into gpio-mmio:
>  - CLPS711X SoCs
>  - MOXA ART SoC
>  - TS-4800 FPGA DIO blocks and compatibles
>  - GPIO controllers found on some GE Single Board Computers
>
> Cc: Alexander Shiyan <shc_work at mail.ru>
> Cc: Julien Grossholtz <julien.grossholtz at savoirfairelinux.com>
> Cc: Martyn Welch <martyn.welch at ge.com>
> Cc: Jonas Jensen <jonas.jensen at gmail.com>
> Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>

FWIW:
Reviewed-by: Andy Shevchenko <andy.shevchenko at gmail.com>


> ---
>  drivers/gpio/Kconfig         |  16 +++-
>  drivers/gpio/Makefile        |   4 -
>  drivers/gpio/gpio-clps711x.c |  91 -------------------
>  drivers/gpio/gpio-ge.c       | 114 -----------------------
>  drivers/gpio/gpio-mmio.c     | 212 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/gpio/gpio-moxart.c   |  84 -----------------
>  drivers/gpio/gpio-ts4800.c   |  81 -----------------
>  7 files changed, 224 insertions(+), 378 deletions(-)
>  delete mode 100644 drivers/gpio/gpio-clps711x.c
>  delete mode 100644 drivers/gpio/gpio-ge.c
>  delete mode 100644 drivers/gpio/gpio-moxart.c
>  delete mode 100644 drivers/gpio/gpio-ts4800.c
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index a68d838..e4d1065 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -154,7 +154,7 @@ config GPIO_BRCMSTB
>  config GPIO_CLPS711X
>         tristate "CLPS711X GPIO support"
>         depends on ARCH_CLPS711X || COMPILE_TEST
> -       select GPIO_GENERIC
> +       select GPIO_GENERIC_PLATFORM
>         help
>           Say yes here to support GPIO on CLPS711X SoCs.
>
> @@ -196,7 +196,7 @@ config GPIO_ETRAXFS
>  config GPIO_GE_FPGA
>         bool "GE FPGA based GPIO"
>         depends on GE_FPGA
> -       select GPIO_GENERIC
> +       select GPIO_GENERIC_PLATFORM
>         help
>           Support for common GPIO functionality provided on some GE Single Board
>           Computers.
> @@ -209,6 +209,14 @@ config GPIO_GENERIC_PLATFORM
>         tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
>         select GPIO_GENERIC
>         help
> +         Select this to support many generic memory-mapped GPIO controllers.
> +
> +         This driver also includes support for the following GPIOs:
> +           CLPS711X SoCs
> +           MOXA ART SoC
> +           TS-4800 FPGA DIO blocks and compatibles.
> +           GPIOs found on some GE Single Board Computers.
> +
>           Say yes here to support basic platform_device memory-mapped GPIO controllers.
>
>  config GPIO_GRGPIO
> @@ -288,7 +296,7 @@ config GPIO_MM_LANTIQ
>  config GPIO_MOXART
>         bool "MOXART GPIO support"
>         depends on ARCH_MOXART || COMPILE_TEST
> -       select GPIO_GENERIC
> +       select GPIO_GENERIC_PLATFORM
>         help
>           Select this option to enable GPIO driver for
>           MOXA ART SoC devices.
> @@ -408,7 +416,7 @@ config GPIO_TS4800
>         tristate "TS-4800 DIO blocks and compatibles"
>         depends on OF_GPIO
>         depends on SOC_IMX51 || COMPILE_TEST
> -       select GPIO_GENERIC
> +       select GPIO_GENERIC_PLATFORM
>         help
>           This driver support TS-4800 FPGA GPIO controllers.
>
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index 991598e..d8d63ae 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -31,7 +31,6 @@ obj-$(CONFIG_GPIO_ATH79)      += gpio-ath79.o
>  obj-$(CONFIG_GPIO_BCM_KONA)    += gpio-bcm-kona.o
>  obj-$(CONFIG_GPIO_BRCMSTB)     += gpio-brcmstb.o
>  obj-$(CONFIG_GPIO_BT8XX)       += gpio-bt8xx.o
> -obj-$(CONFIG_GPIO_CLPS711X)    += gpio-clps711x.o
>  obj-$(CONFIG_GPIO_CS5535)      += gpio-cs5535.o
>  obj-$(CONFIG_GPIO_CRYSTAL_COVE)        += gpio-crystalcove.o
>  obj-$(CONFIG_GPIO_DA9052)      += gpio-da9052.o
> @@ -43,7 +42,6 @@ obj-$(CONFIG_GPIO_EM)         += gpio-em.o
>  obj-$(CONFIG_GPIO_EP93XX)      += gpio-ep93xx.o
>  obj-$(CONFIG_GPIO_ETRAXFS)     += gpio-etraxfs.o
>  obj-$(CONFIG_GPIO_F7188X)      += gpio-f7188x.o
> -obj-$(CONFIG_GPIO_GE_FPGA)     += gpio-ge.o
>  obj-$(CONFIG_GPIO_GRGPIO)      += gpio-grgpio.o
>  obj-$(CONFIG_GPIO_ICH)         += gpio-ich.o
>  obj-$(CONFIG_GPIO_IOP)         += gpio-iop.o
> @@ -68,7 +66,6 @@ obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
>  obj-$(CONFIG_GPIO_MCP23S08)    += gpio-mcp23s08.o
>  obj-$(CONFIG_GPIO_ML_IOH)      += gpio-ml-ioh.o
>  obj-$(CONFIG_GPIO_MM_LANTIQ)   += gpio-mm-lantiq.o
> -obj-$(CONFIG_GPIO_MOXART)      += gpio-moxart.o
>  obj-$(CONFIG_GPIO_MPC5200)     += gpio-mpc5200.o
>  obj-$(CONFIG_GPIO_MPC8XXX)     += gpio-mpc8xxx.o
>  obj-$(CONFIG_GPIO_MSIC)                += gpio-msic.o
> @@ -107,7 +104,6 @@ obj-$(CONFIG_GPIO_TPS65218) += gpio-tps65218.o
>  obj-$(CONFIG_GPIO_TPS6586X)    += gpio-tps6586x.o
>  obj-$(CONFIG_GPIO_TPS65910)    += gpio-tps65910.o
>  obj-$(CONFIG_GPIO_TPS65912)    += gpio-tps65912.o
> -obj-$(CONFIG_GPIO_TS4800)      += gpio-ts4800.o
>  obj-$(CONFIG_GPIO_TS5500)      += gpio-ts5500.o
>  obj-$(CONFIG_GPIO_TWL4030)     += gpio-twl4030.o
>  obj-$(CONFIG_GPIO_TWL6040)     += gpio-twl6040.o
> diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
> deleted file mode 100644
> index 5a69025..0000000
> --- a/drivers/gpio/gpio-clps711x.c
> +++ /dev/null
> @@ -1,91 +0,0 @@
> -/*
> - *  CLPS711X GPIO driver
> - *
> - *  Copyright (C) 2012,2013 Alexander Shiyan <shc_work at mail.ru>
> - *
> - * 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.
> - */
> -
> -#include <linux/err.h>
> -#include <linux/module.h>
> -#include <linux/gpio/driver.h>
> -#include <linux/platform_device.h>
> -
> -static int clps711x_gpio_probe(struct platform_device *pdev)
> -{
> -       struct device_node *np = pdev->dev.of_node;
> -       void __iomem *dat, *dir;
> -       struct gpio_chip *gc;
> -       struct resource *res;
> -       int err, id = np ? of_alias_get_id(np, "gpio") : pdev->id;
> -
> -       if ((id < 0) || (id > 4))
> -               return -ENODEV;
> -
> -       gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
> -       if (!gc)
> -               return -ENOMEM;
> -
> -       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -       dat = devm_ioremap_resource(&pdev->dev, res);
> -       if (IS_ERR(dat))
> -               return PTR_ERR(dat);
> -
> -       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> -       dir = devm_ioremap_resource(&pdev->dev, res);
> -       if (IS_ERR(dir))
> -               return PTR_ERR(dir);
> -
> -       switch (id) {
> -       case 3:
> -               /* PORTD is inverted logic for direction register */
> -               err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
> -                                NULL, dir, 0);
> -               break;
> -       default:
> -               err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
> -                                dir, NULL, 0);
> -               break;
> -       }
> -
> -       if (err)
> -               return err;
> -
> -       switch (id) {
> -       case 4:
> -               /* PORTE is 3 lines only */
> -               gc->ngpio = 3;
> -               break;
> -       default:
> -               break;
> -       }
> -
> -       gc->base = id * 8;
> -       gc->owner = THIS_MODULE;
> -       platform_set_drvdata(pdev, gc);
> -
> -       return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
> -}
> -
> -static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = {
> -       { .compatible = "cirrus,clps711x-gpio" },
> -       { }
> -};
> -MODULE_DEVICE_TABLE(of, clps711x_gpio_ids);
> -
> -static struct platform_driver clps711x_gpio_driver = {
> -       .driver = {
> -               .name           = "clps711x-gpio",
> -               .of_match_table = of_match_ptr(clps711x_gpio_ids),
> -       },
> -       .probe  = clps711x_gpio_probe,
> -};
> -module_platform_driver(clps711x_gpio_driver);
> -
> -MODULE_LICENSE("GPL");
> -MODULE_AUTHOR("Alexander Shiyan <shc_work at mail.ru>");
> -MODULE_DESCRIPTION("CLPS711X GPIO driver");
> -MODULE_ALIAS("platform:clps711x-gpio");
> diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c
> deleted file mode 100644
> index 8650b29..0000000
> --- a/drivers/gpio/gpio-ge.c
> +++ /dev/null
> @@ -1,114 +0,0 @@
> -/*
> - * Driver for GE FPGA based GPIO
> - *
> - * Author: Martyn Welch <martyn.welch at ge.com>
> - *
> - * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
> - *
> - * This file is licensed under the terms of the GNU General Public License
> - * version 2.  This program is licensed "as is" without any warranty of any
> - * kind, whether express or implied.
> - */
> -
> -/* TODO
> - *
> - * Configuration of output modes (totem-pole/open-drain)
> - * Interrupt configuration - interrupts are always generated the FPGA relies on
> - * the I/O interrupt controllers mask to stop them propergating
> - */
> -
> -#include <linux/kernel.h>
> -#include <linux/io.h>
> -#include <linux/slab.h>
> -#include <linux/of_device.h>
> -#include <linux/of_gpio.h>
> -#include <linux/of_address.h>
> -#include <linux/module.h>
> -#include <linux/gpio/driver.h>
> -
> -#define GEF_GPIO_DIRECT                0x00
> -#define GEF_GPIO_IN            0x04
> -#define GEF_GPIO_OUT           0x08
> -#define GEF_GPIO_TRIG          0x0C
> -#define GEF_GPIO_POLAR_A       0x10
> -#define GEF_GPIO_POLAR_B       0x14
> -#define GEF_GPIO_INT_STAT      0x18
> -#define GEF_GPIO_OVERRUN       0x1C
> -#define GEF_GPIO_MODE          0x20
> -
> -static const struct of_device_id gef_gpio_ids[] = {
> -       {
> -               .compatible     = "gef,sbc610-gpio",
> -               .data           = (void *)19,
> -       }, {
> -               .compatible     = "gef,sbc310-gpio",
> -               .data           = (void *)6,
> -       }, {
> -               .compatible     = "ge,imp3a-gpio",
> -               .data           = (void *)16,
> -       },
> -       { }
> -};
> -MODULE_DEVICE_TABLE(of, gef_gpio_ids);
> -
> -static int __init gef_gpio_probe(struct platform_device *pdev)
> -{
> -       const struct of_device_id *of_id =
> -               of_match_device(gef_gpio_ids, &pdev->dev);
> -       struct gpio_chip *gc;
> -       void __iomem *regs;
> -       int ret;
> -
> -       gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
> -       if (!gc)
> -               return -ENOMEM;
> -
> -       regs = of_iomap(pdev->dev.of_node, 0);
> -       if (!regs)
> -               return -ENOMEM;
> -
> -       ret = bgpio_init(gc, &pdev->dev, 4, regs + GEF_GPIO_IN,
> -                        regs + GEF_GPIO_OUT, NULL, NULL,
> -                        regs + GEF_GPIO_DIRECT, BGPIOF_BIG_ENDIAN_BYTE_ORDER);
> -       if (ret) {
> -               dev_err(&pdev->dev, "bgpio_init failed\n");
> -               goto err0;
> -       }
> -
> -       /* Setup pointers to chip functions */
> -       gc->label = devm_kstrdup(&pdev->dev, pdev->dev.of_node->full_name,
> -                                    GFP_KERNEL);
> -       if (!gc->label) {
> -               ret = -ENOMEM;
> -               goto err0;
> -       }
> -
> -       gc->base = -1;
> -       gc->ngpio = (u16)(uintptr_t)of_id->data;
> -       gc->of_gpio_n_cells = 2;
> -       gc->of_node = pdev->dev.of_node;
> -
> -       /* This function adds a memory mapped GPIO chip */
> -       ret = devm_gpiochip_add_data(&pdev->dev, gc, NULL);
> -       if (ret)
> -               goto err0;
> -
> -       return 0;
> -err0:
> -       iounmap(regs);
> -       pr_err("%s: GPIO chip registration failed\n",
> -                       pdev->dev.of_node->full_name);
> -       return ret;
> -};
> -
> -static struct platform_driver gef_gpio_driver = {
> -       .driver = {
> -               .name           = "gef-gpio",
> -               .of_match_table = gef_gpio_ids,
> -       },
> -};
> -module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);
> -
> -MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
> -MODULE_AUTHOR("Martyn Welch <martyn.welch at ge.com");
> -MODULE_LICENSE("GPL");
> diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
> index f72e40e..1de9172 100644
> --- a/drivers/gpio/gpio-mmio.c
> +++ b/drivers/gpio/gpio-mmio.c
> @@ -586,8 +586,220 @@ static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
>         return 0;
>  }
>
> +static int clps711x_parse_dt(struct platform_device *pdev,
> +                            struct bgpio_pdata *pdata,
> +                            unsigned long *flags)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +       struct resource *res;
> +       const char *dir_reg_name;
> +       int id = np ? of_alias_get_id(np, "gpio") : pdev->id;
> +
> +       switch (id) {
> +       case 0:
> +       case 1:
> +       case 2:
> +               pdata->ngpio = 0; /* determined by register width */
> +               dir_reg_name = "dirout";
> +               break;
> +       case 3:
> +               pdata->ngpio = 0; /* determined by register width */
> +               /* PORTD is inverted logic for direction register */
> +               dir_reg_name = "dirin";
> +               break;
> +       case 4:
> +               pdata->ngpio = 3; /* PORTE is 3 lines only */
> +               dir_reg_name = "dirout";
> +               break;
> +       default:
> +               return -ENODEV;
> +       }
> +
> +       pdata->base = id * 8;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!res)
> +               return -EINVAL;
> +       if (!res->name || strcmp("dat", res->name))
> +               res->name = devm_kstrdup(&pdev->dev, "dat", GFP_KERNEL);
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +       if (!res)
> +               return -EINVAL;
> +       if (!res->name || strcmp(dir_reg_name, res->name))
> +               res->name = devm_kstrdup(&pdev->dev, dir_reg_name, GFP_KERNEL);
> +
> +       return 0;
> +}
> +
> +static int ge_dt_cb(struct platform_device *pdev,
> +                   struct bgpio_pdata *pdata,
> +                   unsigned long *flags)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +
> +       pdata->label = devm_kstrdup(&pdev->dev, np->full_name, GFP_KERNEL);
> +       if (!pdata->label)
> +               return -ENOMEM;
> +
> +       return 0;
> +}
> +
> +static int moxart_dt_cb(struct platform_device *pdev,
> +                       struct bgpio_pdata *pdata,
> +                       unsigned long *flags)
> +{
> +       pdata->base = 0;
> +       pdata->label = "moxart-gpio";
> +       return 0;
> +}
> +
> +
> +static int ts4800_dt_cb(struct platform_device *pdev,
> +                       struct bgpio_pdata *pdata,
> +                       unsigned long *flags)
> +{
> +       int err;
> +
> +       err = of_property_read_u32(pdev->dev.of_node, "ngpios", &pdata->ngpio);
> +       if (err == -EINVAL) {
> +               pdata->ngpio = 16;
> +               return 0;
> +       }
> +
> +       return err;
> +}
> +
> +/*
> + * bgpio_init() needs up to five named mmio register resources.
> + * These currently are dat, set, clr, [dirout | dirin]. There
> + * is no particular order or predefined place for the entries.
> + * However, dirout and dirin are mutually exclusive.
> + */
> +#define __NUM_COMPAT_OVERRIDE_MMIO_RESOURCES 4
> +
> +struct compat_gpio_device_data {
> +       unsigned int expected_resource_size;
> +       unsigned int ngpio;
> +       resource_size_t register_width;
> +       unsigned long flags;
> +       int (*call_back)(struct platform_device *pdev,
> +                        struct bgpio_pdata *pdata,
> +                        unsigned long *flags);
> +       struct resource_replacement {
> +               resource_size_t start_offset;
> +               const char *name;
> +       } resources[__NUM_COMPAT_OVERRIDE_MMIO_RESOURCES];
> +};
> +#undef __NUM_COMPAT_OVERRIDE_MMIO_RESOURCES
> +
> +#define ADD_COMPAT_REGISTER(_name, _offset)    \
> +       { .name = (_name), .start_offset = (_offset) }
> +
> +#define ADD_COMPAT_GPIO(_comp, _sz, _ngpio, _width, _cb, _f, _res...)  \
> +       {                                                               \
> +         .compatible = (_comp),                                        \
> +         .data = &(struct compat_gpio_device_data) {                   \
> +               .expected_resource_size = (_sz),                        \
> +               .ngpio = (_ngpio),                                      \
> +               .register_width = (_width),                             \
> +               .flags = (_f),                                          \
> +               .call_back = (_cb),                                     \
> +               .resources = { _res },                                  \
> +       }                                                               \
> +}
> +
> +#define ADD_COMPAT_GE_GPIO(_name, _ngpio)                              \
> +       ADD_COMPAT_GPIO(_name, 0x24, _ngpio, 0x4, ge_dt_cb,             \
> +                BGPIOF_BIG_ENDIAN_BYTE_ORDER,                          \
> +                ADD_COMPAT_REGISTER("dat", 0x04),                      \
> +                ADD_COMPAT_REGISTER("set", 0x08),                      \
> +                ADD_COMPAT_REGISTER("dirin", 0x00))                    \
> +
> +static const struct of_device_id compat_gpio_devices[] = {
> +       ADD_COMPAT_GE_GPIO("ge,imp3a-gpio", 16),
> +       ADD_COMPAT_GE_GPIO("gef,sbc310-gpio", 6),
> +       ADD_COMPAT_GE_GPIO("gef,sbc610-gpio", 19),
> +       ADD_COMPAT_GPIO("moxa,moxart-gpio", 0xc, 0, 0x4, moxart_dt_cb,
> +                BGPIOF_READ_OUTPUT_REG_SET,
> +                ADD_COMPAT_REGISTER("dat", 0x04),
> +                ADD_COMPAT_REGISTER("set", 0x00),
> +                ADD_COMPAT_REGISTER("dirout", 0x08)),
> +       ADD_COMPAT_GPIO("technologic,ts4800-gpio", 0x6, 16, 0x2, ts4800_dt_cb,
> +                0, ADD_COMPAT_REGISTER("dat", 0x00),
> +                ADD_COMPAT_REGISTER("set", 0x02),
> +                ADD_COMPAT_REGISTER("dirout", 0x04)),
> +};
> +
> +#undef ADD_COMPAT_GE_GPIO
> +#undef ADD_COMPAT_GPIO
> +#undef ADD_COMPAT_REGISTER
> +
> +static int compat_parse_dt(struct platform_device *pdev,
> +                          struct bgpio_pdata *pdata,
> +                          unsigned long *flags)
> +{
> +       const struct device_node *node = pdev->dev.of_node;
> +       const struct compat_gpio_device_data *entry;
> +       const struct of_device_id *of_id;
> +       struct resource *res;
> +       int err;
> +
> +       of_id = of_match_node(compat_gpio_devices, node);
> +       if (!of_id)
> +               return -ENODEV;
> +
> +       entry = of_id->data;
> +       if (!entry || !entry->resources[0].name)
> +               return -EINVAL;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!res)
> +               return -EINVAL;
> +
> +       if (!res->name || strcmp(entry->resources[0].name, res->name)) {
> +               struct resource nres[ARRAY_SIZE(entry->resources)];
> +               size_t i;
> +
> +               if (resource_size(res) != entry->expected_resource_size)
> +                       return -EINVAL;
> +
> +               for (i = 0; i < ARRAY_SIZE(entry->resources); i++) {
> +                       if (!entry->resources[i].name)
> +                               continue;
> +
> +                       nres[i].name = devm_kstrdup(&pdev->dev,
> +                               entry->resources[i].name, GFP_KERNEL);
> +                       nres[i].start = res->start +
> +                               entry->resources[i].start_offset;
> +                       nres[i].end = nres[i].start +
> +                               entry->register_width - 1;
> +                       nres[i].flags = IORESOURCE_MEM;
> +               }
> +
> +               err = platform_device_add_resources(pdev, nres, i);
> +               if (err)
> +                       return err;
> +       }
> +
> +       pdata->base = -1;
> +       pdata->ngpio = entry->ngpio;
> +       *flags = entry->flags;
> +
> +       if (entry->call_back)
> +               err = entry->call_back(pdev, pdata, flags);
> +
> +       return err;
> +}
> +
>  static const struct of_device_id bgpio_of_match[] = {
>         { .compatible = "wd,mbl-gpio", .data = bgpio_basic_mmio_parse_dt },
> +       { .compatible = "cirrus,clps711x-gpio", .data = clps711x_parse_dt },
> +       { .compatible = "ge,imp3a-gpio", .data = compat_parse_dt },
> +       { .compatible = "gef,sbc310-gpio", .data = compat_parse_dt },
> +       { .compatible = "gef,sbc610-gpio", .data = compat_parse_dt },
> +       { .compatible = "moxa,moxart-gpio", .data = compat_parse_dt },
> +       { .compatible = "technologic,ts4800-gpio", .data = compat_parse_dt },
>         { }
>  };
>  MODULE_DEVICE_TABLE(of, bgpio_of_match);
> diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c
> deleted file mode 100644
> index d58d389..0000000
> --- a/drivers/gpio/gpio-moxart.c
> +++ /dev/null
> @@ -1,84 +0,0 @@
> -/*
> - * MOXA ART SoCs GPIO driver.
> - *
> - * Copyright (C) 2013 Jonas Jensen
> - *
> - * Jonas Jensen <jonas.jensen at gmail.com>
> - *
> - * This file is licensed under the terms of the GNU General Public
> - * License version 2.  This program is licensed "as is" without any
> - * warranty of any kind, whether express or implied.
> - */
> -
> -#include <linux/err.h>
> -#include <linux/init.h>
> -#include <linux/irq.h>
> -#include <linux/io.h>
> -#include <linux/platform_device.h>
> -#include <linux/of_address.h>
> -#include <linux/of_gpio.h>
> -#include <linux/pinctrl/consumer.h>
> -#include <linux/delay.h>
> -#include <linux/timer.h>
> -#include <linux/bitops.h>
> -#include <linux/gpio/driver.h>
> -
> -#define GPIO_DATA_OUT          0x00
> -#define GPIO_DATA_IN           0x04
> -#define GPIO_PIN_DIRECTION     0x08
> -
> -static int moxart_gpio_probe(struct platform_device *pdev)
> -{
> -       struct device *dev = &pdev->dev;
> -       struct resource *res;
> -       struct gpio_chip *gc;
> -       void __iomem *base;
> -       int ret;
> -
> -       gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
> -       if (!gc)
> -               return -ENOMEM;
> -
> -       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -       base = devm_ioremap_resource(dev, res);
> -       if (IS_ERR(base))
> -               return PTR_ERR(base);
> -
> -       ret = bgpio_init(gc, dev, 4, base + GPIO_DATA_IN,
> -                        base + GPIO_DATA_OUT, NULL,
> -                        base + GPIO_PIN_DIRECTION, NULL,
> -                        BGPIOF_READ_OUTPUT_REG_SET);
> -       if (ret) {
> -               dev_err(&pdev->dev, "bgpio_init failed\n");
> -               return ret;
> -       }
> -
> -       gc->label = "moxart-gpio";
> -       gc->request = gpiochip_generic_request;
> -       gc->free = gpiochip_generic_free;
> -       gc->base = 0;
> -       gc->owner = THIS_MODULE;
> -
> -       ret = devm_gpiochip_add_data(dev, gc, NULL);
> -       if (ret) {
> -               dev_err(dev, "%s: gpiochip_add failed\n",
> -                       dev->of_node->full_name);
> -               return ret;
> -       }
> -
> -       return ret;
> -}
> -
> -static const struct of_device_id moxart_gpio_match[] = {
> -       { .compatible = "moxa,moxart-gpio" },
> -       { }
> -};
> -
> -static struct platform_driver moxart_gpio_driver = {
> -       .driver = {
> -               .name           = "moxart-gpio",
> -               .of_match_table = moxart_gpio_match,
> -       },
> -       .probe  = moxart_gpio_probe,
> -};
> -builtin_platform_driver(moxart_gpio_driver);
> diff --git a/drivers/gpio/gpio-ts4800.c b/drivers/gpio/gpio-ts4800.c
> deleted file mode 100644
> index 0c144a7..0000000
> --- a/drivers/gpio/gpio-ts4800.c
> +++ /dev/null
> @@ -1,81 +0,0 @@
> -/*
> - * GPIO driver for the TS-4800 board
> - *
> - * Copyright (c) 2016 - Savoir-faire Linux
> - *
> - * This file is licensed under the terms of the GNU General Public
> - * License version 2. This program is licensed "as is" without any
> - * warranty of any kind, whether express or implied.
> - */
> -
> -#include <linux/gpio/driver.h>
> -#include <linux/of_address.h>
> -#include <linux/of_device.h>
> -#include <linux/platform_device.h>
> -
> -#define DEFAULT_PIN_NUMBER      16
> -#define INPUT_REG_OFFSET        0x00
> -#define OUTPUT_REG_OFFSET       0x02
> -#define DIRECTION_REG_OFFSET    0x04
> -
> -static int ts4800_gpio_probe(struct platform_device *pdev)
> -{
> -       struct device_node *node;
> -       struct gpio_chip *chip;
> -       struct resource *res;
> -       void __iomem *base_addr;
> -       int retval;
> -       u32 ngpios;
> -
> -       chip = devm_kzalloc(&pdev->dev, sizeof(struct gpio_chip), GFP_KERNEL);
> -       if (!chip)
> -               return -ENOMEM;
> -
> -       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -       base_addr = devm_ioremap_resource(&pdev->dev, res);
> -       if (IS_ERR(base_addr))
> -               return PTR_ERR(base_addr);
> -
> -       node = pdev->dev.of_node;
> -       if (!node)
> -               return -EINVAL;
> -
> -       retval = of_property_read_u32(node, "ngpios", &ngpios);
> -       if (retval == -EINVAL)
> -               ngpios = DEFAULT_PIN_NUMBER;
> -       else if (retval)
> -               return retval;
> -
> -       retval = bgpio_init(chip, &pdev->dev, 2, base_addr + INPUT_REG_OFFSET,
> -                           base_addr + OUTPUT_REG_OFFSET, NULL,
> -                           base_addr + DIRECTION_REG_OFFSET, NULL, 0);
> -       if (retval) {
> -               dev_err(&pdev->dev, "bgpio_init failed\n");
> -               return retval;
> -       }
> -
> -       chip->ngpio = ngpios;
> -
> -       platform_set_drvdata(pdev, chip);
> -
> -       return devm_gpiochip_add_data(&pdev->dev, chip, NULL);
> -}
> -
> -static const struct of_device_id ts4800_gpio_of_match[] = {
> -       { .compatible = "technologic,ts4800-gpio", },
> -       {},
> -};
> -
> -static struct platform_driver ts4800_gpio_driver = {
> -       .driver = {
> -                  .name = "ts4800-gpio",
> -                  .of_match_table = ts4800_gpio_of_match,
> -                  },
> -       .probe = ts4800_gpio_probe,
> -};
> -
> -module_platform_driver_probe(ts4800_gpio_driver, ts4800_gpio_probe);
> -
> -MODULE_AUTHOR("Julien Grossholtz <julien.grossholtz at savoirfairelinux.com>");
> -MODULE_DESCRIPTION("TS4800 FPGA GPIO driver");
> -MODULE_LICENSE("GPL v2");
> --
> 2.8.1
>



-- 
With Best Regards,
Andy Shevchenko


From christoffer.dall at linaro.org  Wed May 11 05:26:48 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 14:26:48 +0200
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world
 switch backend
In-Reply-To: <573317DC.4060200@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
 <5731EBBE.7060203@linaro.org> <573317DC.4060200@arm.com>
Message-ID: <20160511122648.GN27623@cbox>

On Wed, May 11, 2016 at 12:30:36PM +0100, Andre Przywara wrote:
> Hi,
> 
> On 10/05/16 15:10, Eric Auger wrote:
> > On 05/06/2016 12:45 PM, Andre Przywara wrote:
> >> From: Marc Zyngier <marc.zyngier at arm.com>
> >>
> >> Processing maintenance interrupts and accessing the list registers
> >> are dependent on the host's GIC version.
> >> Introduce vgic-v2.c to contain GICv2 specific functions.
> >> Implement the GICv2 specific code for syncing the emulation state
> >> into the VGIC registers.
> >>
> >> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> >> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> >> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >> Changelog RFC..v1:
> >> - remove explicit LR_STATE clearing on maintenance interrupt handling
> >> - improve documentation for vgic_v2_populate_lr()
> >> - remove WARN_ON on non-edge IRQs in maintenance interrupts
> >> - simplify multi-CPU source SGI handling
> >>
> >> Changelog v1 .. v2:
> >> - inject the IRQ priority into the list register
> >>
> >> Changelog v2 .. v3:
> >> - cleanup diff containing rebase artifacts
> >>
> >>  include/linux/irqchip/arm-gic.h |   1 +
> >>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
> >>  virt/kvm/arm/vgic/vgic.c        |   6 ++
> >>  virt/kvm/arm/vgic/vgic.h        |   6 ++
> >>  4 files changed, 191 insertions(+)
> >>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
> >>
> >> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
> >> index 9c94026..be0d26f 100644
> >> --- a/include/linux/irqchip/arm-gic.h
> >> +++ b/include/linux/irqchip/arm-gic.h
> >> @@ -76,6 +76,7 @@
> >>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
> >>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
> >>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
> >> +#define GICH_LR_PRIORITY_SHIFT		23
> >>  #define GICH_LR_STATE			(3 << 28)
> >>  #define GICH_LR_PENDING_BIT		(1 << 28)
> >>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
> >> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> >> new file mode 100644
> >> index 0000000..4cee616
> >> --- /dev/null
> >> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> >> @@ -0,0 +1,178 @@
> >> +/*
> >> + * Copyright (C) 2015, 2016 ARM 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.
> >> + *
> >> + * 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.
> >> + *
> >> + * 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/irqchip/arm-gic.h>
> >> +#include <linux/kvm.h>
> >> +#include <linux/kvm_host.h>
> >> +
> >> +#include "vgic.h"
> >> +
> >> +/*
> >> + * Call this function to convert a u64 value to an unsigned long * bitmask
> >> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
> >> + *
> >> + * Warning: Calling this function may modify *val.
> >> + */
> >> +static unsigned long *u64_to_bitmask(u64 *val)
> >> +{
> >> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
> >> +	*val = (*val >> 32) | (*val << 32);
> >> +#endif
> >> +	return (unsigned long *)val;
> >> +}
> >> +
> >> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
> >> +{
> >> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
> >> +
> >> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
> >> +		u64 eisr = cpuif->vgic_eisr;
> >> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
> >> +		int lr;
> >> +
> >> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
> > Didn't we say we could use vcpu->arch.vgic_cpu.used_lrs here?
> 
> Why would that be useful? Don't we just want to see those LRs that had a
> maintenance interrupt received? I don't see the point if iterating over
> the used LRs, where we need to check for this condition somehow manually?
> Or what am I missing here?

if we get rid of eisr eventually we can optimize the reading of that
away, but I honestly don't think we should be pursuing this straight
away.

> 
> >> +			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
> >> +
> >> +			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
> >> +
> >> +			kvm_notify_acked_irq(vcpu->kvm, 0,
> >> +					     intid - VGIC_NR_PRIVATE_IRQS);
> >> +
> >> +			cpuif->vgic_elrsr |= 1ULL << lr;
> 
> So are we good with removing this line (and the respective one in v3)?
> 
Yes.

-Christoffer


From matt at codeblueprint.co.uk  Wed May 11 05:27:30 2016
From: matt at codeblueprint.co.uk (Matt Fleming)
Date: Wed, 11 May 2016 13:27:30 +0100
Subject: [PATCH] Xen: EFI: Parse DT parameters for Xen specific UEFI
In-Reply-To: <1462523526-3172-1-git-send-email-zhaoshenglong@huawei.com>
References: <1462523526-3172-1-git-send-email-zhaoshenglong@huawei.com>
Message-ID: <20160511122730.GU2839@codeblueprint.co.uk>

On Fri, 06 May, at 04:32:06PM, Shannon Zhao wrote:
> From: Shannon Zhao <shannon.zhao at linaro.org>
> 
> Add a new function to parse DT parameters for Xen specific UEFI just
> like the way for normal UEFI. Then it could reuse the existing codes.
> 
> If Xen supports EFI, initialize runtime services.
 
This commit log would benefit from a little expansion. I'd like to see
information that answers the following questions,

 - How do the Xen DT paramters differ from bare metal?
 - What existing code is reused with your patch?
 - How are Xen runtime services different from bare metal?
 - Why is it OK to force enable EFI runtime services for Xen?

I think it would also be good to explicitly state that we do not
expect to find both Xen EFI DT parameters and bare metal EFI DT
parameters when performing the search; the two should be mutually
exclusive.

> CC: Matt Fleming <matt at codeblueprint.co.uk>
> Signed-off-by: Shannon Zhao <shannon.zhao at linaro.org>
> ---
> Drop using of EFI_PARAVIRT. Discussion can be found from [1].
> [1] https://lkml.org/lkml/2016/4/29/8
> ---
>  arch/arm/include/asm/efi.h         |  2 +
>  arch/arm/xen/enlighten.c           | 16 ++++++++
>  arch/arm64/include/asm/efi.h       |  2 +
>  drivers/firmware/efi/arm-runtime.c | 70 +++++++++++++++++++++++---------
>  drivers/firmware/efi/efi.c         | 81 ++++++++++++++++++++++++++++++--------
>  5 files changed, 137 insertions(+), 34 deletions(-)
> 
> diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
> index e0eea72..5ba4343 100644
> --- a/arch/arm/include/asm/efi.h
> +++ b/arch/arm/include/asm/efi.h
> @@ -52,9 +52,11 @@ static inline void efi_set_pgd(struct mm_struct *mm)
>  
>  void efi_virtmap_load(void);
>  void efi_virtmap_unload(void);
> +int xen_arm_enable_runtime_services(void);
>  
>  #else
>  #define efi_init()
> +#define xen_arm_enable_runtime_services() (0)
>  #endif /* CONFIG_EFI */
>  
>  /* arch specific definitions used by the stub code */
> diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
> index 13e3e9f..3362870 100644
> --- a/arch/arm/xen/enlighten.c
> +++ b/arch/arm/xen/enlighten.c
> @@ -16,6 +16,7 @@
>  #include <asm/xen/hypervisor.h>
>  #include <asm/xen/hypercall.h>
>  #include <asm/system_misc.h>
> +#include <asm/efi.h>
>  #include <linux/interrupt.h>
>  #include <linux/irqreturn.h>
>  #include <linux/module.h>
> @@ -261,6 +262,13 @@ static int __init fdt_find_hyper_node(unsigned long node, const char *uname,
>  	    !strncmp(hyper_node.prefix, s, strlen(hyper_node.prefix)))
>  		hyper_node.version = s + strlen(hyper_node.prefix);
>  
> +	if (IS_ENABLED(CONFIG_XEN_EFI)) {
> +		/* Check if Xen supports EFI */
> +		if ((of_get_flat_dt_subnode_by_name(node, "uefi") > 0) &&
> +		    !efi_runtime_disabled())
> +			set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
> +	}
> +
>  	return 0;
>  }
>  

The above comment could do with including similar information to the
commit log as to why we want to force enable runtime services. For x86
we have this,

	 *
	 * When EFI_PARAVIRT is in force then we could not map runtime
	 * service memory region because we do not have direct access to it.
	 * However, runtime services are available through proxy functions
	 * (e.g. in case of Xen dom0 EFI implementation they call special
	 * hypercall which executes relevant EFI functions) and that is why
	 * they are always enabled.
	 */

We need something similar here.

> @@ -338,6 +346,7 @@ static int __init xen_guest_init(void)
>  {
>  	struct xen_add_to_physmap xatp;
>  	struct shared_info *shared_info_page = NULL;
> +	int ret;
>  
>  	if (!xen_domain())
>  		return 0;
> @@ -352,6 +361,13 @@ static int __init xen_guest_init(void)
>  		return -ENODEV;
>  	}
>  
> +	if (IS_ENABLED(CONFIG_XEN_EFI) && efi_enabled(EFI_BOOT) &&
> +	    efi_enabled(EFI_RUNTIME_SERVICES)) {
> +		ret = xen_arm_enable_runtime_services();
> +		if (ret)
> +			return ret;
> +	}
> +

Is it ever possible to have EFI_RUNTIME_SERVICES set but
efi_enabled(EFI_BOOT) and IS_ENABLED(CONFIG_XEN_EFI) be false inside
this function? If the answer is "no", I'd suggest just reducing this
down to,

	/*
	 * The fdt parsing code will have set EFI_RUNTIME_SERVICES if
	 * it found Xen EFI parameters. Force enable runtime services.
	 */ 
	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
		ret = xen_arm_enable_runtime_services();
		if (ret)
			return ret;
	}

But first, see my comments below.

> @@ -39,6 +40,33 @@ static struct mm_struct efi_mm = {
>  	.mmlist			= LIST_HEAD_INIT(efi_mm.mmlist),
>  };
>  
> +static int __init efi_remap_init(void)
> +{
> +	u64 mapsize;
> +
> +	pr_info("Remapping and enabling EFI services.\n");
> +
> +	mapsize = memmap.map_end - memmap.map;
> +	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
> +						   mapsize);
> +	if (!memmap.map) {
> +		pr_err("Failed to remap EFI memory map\n");
> +		return -ENOMEM;
> +	}
> +	memmap.map_end = memmap.map + mapsize;
> +	efi.memmap = &memmap;
> +
> +	efi.systab = (__force void *)ioremap_cache(efi_system_table,
> +						   sizeof(efi_system_table_t));
> +	if (!efi.systab) {
> +		pr_err("Failed to remap EFI System Table\n");
> +		return -ENOMEM;
> +	}
> +	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
> +
> +	return 0;
> +}
> +
>  static bool __init efi_virtmap_init(void)
>  {
>  	efi_memory_desc_t *md;
> @@ -75,7 +103,7 @@ static bool __init efi_virtmap_init(void)
>   */
>  static int __init arm_enable_runtime_services(void)
>  {
> -	u64 mapsize;
> +	int ret;
>  
>  	if (!efi_enabled(EFI_BOOT)) {
>  		pr_info("EFI services will not be available.\n");
> @@ -87,25 +115,14 @@ static int __init arm_enable_runtime_services(void)
>  		return 0;
>  	}
>  
> -	pr_info("Remapping and enabling EFI services.\n");
> -
> -	mapsize = memmap.map_end - memmap.map;
> -	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
> -						   mapsize);
> -	if (!memmap.map) {
> -		pr_err("Failed to remap EFI memory map\n");
> -		return -ENOMEM;
> +	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
> +		pr_info("EFI runtime services access via paravirt.\n");
> +		return 0;
>  	}
> -	memmap.map_end = memmap.map + mapsize;
> -	efi.memmap = &memmap;
>  
> -	efi.systab = (__force void *)ioremap_cache(efi_system_table,
> -						   sizeof(efi_system_table_t));
> -	if (!efi.systab) {
> -		pr_err("Failed to remap EFI System Table\n");
> -		return -ENOMEM;
> -	}
> -	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
> +	ret = efi_remap_init();
> +	if (ret)
> +		return ret;
>  
>  	if (!efi_virtmap_init()) {
>  		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
> @@ -122,6 +139,23 @@ static int __init arm_enable_runtime_services(void)
>  }
>  early_initcall(arm_enable_runtime_services);
>  
> +int __init xen_arm_enable_runtime_services(void)
> +{
> +	int ret;
> +
> +	ret = efi_remap_init();
> +	if (ret)
> +		return ret;
> +
> +	if (IS_ENABLED(CONFIG_XEN_EFI)) {
> +		/* Set up runtime services function pointers for Xen Dom0 */
> +		xen_efi_runtime_setup();
> +		efi.runtime_version = efi.systab->hdr.revision;
> +	}
> +
> +	return 0;
> +}

Since you call efi_remap_init() in both of these functions, couldn't
you leave the existing code alone and bail after setting up the memory
map and systab in arm_enable_runtime_services()?

Also, why do you need to setup efi.runtime_version here? Isn't that
done inside uefi_init()?

Here is how I would have expected this patch to look:

  - Add FDT code to find hypervisor EFI params

  - Force enable EFI_RUNTIME_SERVICES for Xen and call
    xen_efi_runtime_setup() inside xen_guest_init()

  - Change arm_enable_runtime_services() to handle the case where
    EFI_RUNTIME_SERVICES is already set

Am I misunderstanding some ordering issues?


From matt at codeblueprint.co.uk  Wed May 11 05:29:48 2016
From: matt at codeblueprint.co.uk (Matt Fleming)
Date: Wed, 11 May 2016 13:29:48 +0100
Subject: [PATCH] Xen: EFI: Parse DT parameters for Xen specific UEFI
In-Reply-To: <CANLsYkxUyiUfdjm39SvhKSvmddPLFP3JFAeHpYuxgPyZfexw6w@mail.gmail.com>
References: <1462523526-3172-1-git-send-email-zhaoshenglong@huawei.com>
 <CANLsYkxUyiUfdjm39SvhKSvmddPLFP3JFAeHpYuxgPyZfexw6w@mail.gmail.com>
Message-ID: <20160511122948.GV2839@codeblueprint.co.uk>

On Fri, 06 May, at 09:52:42AM, Mathieu Poirier wrote:
> > +static int __init efi_remap_init(void)
> > +{
> > +       u64 mapsize;
> > +
> > +       pr_info("Remapping and enabling EFI services.\n");
> > +
> > +       mapsize = memmap.map_end - memmap.map;
> > +       memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
> > +                                                  mapsize);
> > +       if (!memmap.map) {
> > +               pr_err("Failed to remap EFI memory map\n");
> > +               return -ENOMEM;
> > +       }
> > +       memmap.map_end = memmap.map + mapsize;
> > +       efi.memmap = &memmap;
> > +
> > +       efi.systab = (__force void *)ioremap_cache(efi_system_table,
> > +                                                  sizeof(efi_system_table_t));
> > +       if (!efi.systab) {
> 
> Is there a reason why memmap.map isn't iounmap() in the error path?
> The original code didn't have it either, hence the question.

I suspect that is a bug.

In reality, if you can't access the EFI System Table because you fail
to map it I would guess you are going to crash very, very quickly
anyhow.


From javier at osg.samsung.com  Wed May 11 05:31:00 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 11 May 2016 08:31:00 -0400
Subject: [PATCH v3 23/27] dt-bindings: clock: Add I2C, HSI2C and RTC clock
 IDs to Exynos5410
In-Reply-To: <1462910970-1812-24-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
 <1462910970-1812-24-git-send-email-krzk@kernel.org>
Message-ID: <ee0b3b8f-d499-c735-1b46-1710e2e91b59@osg.samsung.com>

Hello Krzysztof,

On 05/10/2016 04:09 PM, Krzysztof Kozlowski wrote:
> Add IDs for I2C, USI (HSI2C) and RTC clocks to Exynos5410. Use the same
> number as for Exynos5420 just in case in future these drivers were
> merged.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Wed May 11 05:32:04 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 11 May 2016 08:32:04 -0400
Subject: [PATCH v3 24/27] clk: samsung: exynos5410: Add I2C, HSI2C and RTC
 clocks
In-Reply-To: <1462910970-1812-25-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
 <1462910970-1812-25-git-send-email-krzk@kernel.org>
Message-ID: <bbe92228-c544-a105-b1b2-82e2563018de@osg.samsung.com>

Hello Krzysztof,

On 05/10/2016 04:09 PM, Krzysztof Kozlowski wrote:
> Add clocks for I2C, USI (HSI2C) and RTC to the Exynos5410 clock driver.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From christoffer.dall at linaro.org  Wed May 11 05:34:23 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 14:34:23 +0200
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
Message-ID: <20160511123423.GO27623@cbox>

On Fri, May 06, 2016 at 11:45:37AM +0100, Andre Przywara wrote:
> As the enable register handlers are shared between the v2 and v3
> emulation, their implementation goes into vgic-mmio.c, to be easily
> referenced from the v3 emulation as well later.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - use lower bits of address to determine IRQ number
> - remove TODO, confirmed to be fine
> 
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
>  virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
>  3 files changed, 69 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 69e96f7..448d1da 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -72,9 +72,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index 41cf4f4..077ae86 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -46,6 +46,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
>  	/* Ignore */
>  }
>  
> +/*
> + * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
> + * of the enabled bit, so there is only one function for both here.
> + */
> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len)
> +{
> +	u32 intid = (addr & 0x7f) * 8;

is there anything we can do about this to make it more intuitive?  A
macro to generate the mask/offset based on bits per interrupt or
something?

> +	u32 value = 0;
> +	int i;
> +
> +	/* Loop over all IRQs affected by this read */
> +	for (i = 0; i < len * 8; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		if (irq->enabled)
> +			value |= (1U << i);

I couldn't find the code anywhere that enforces word-aligned accesses to
these registers.  Do we have that?

If that's not the case, doesn't this break of you do a non-word aligned
access?

> +	}
> +
> +	return extract_bytes(value, addr & 3, len);
> +}
> +
> +void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val)
> +{
> +	u32 intid = (addr & 0x7f) * 8;
> +	int i;
> +
> +	for_each_set_bit(i, &val, len * 8) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +		irq->enabled = true;
> +		vgic_queue_irq_unlock(vcpu->kvm, irq);
> +	}
> +}
> +
> +void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val)
> +{
> +	u32 intid = (addr & 0x7f) * 8;
> +	int i;
> +
> +	for_each_set_bit(i, &val, len * 8) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		irq->enabled = false;
> +
> +		spin_unlock(&irq->irq_lock);

nit: whitespace consistency with senable

> +	}
> +}
> +
>  static int match_region(const void *key, const void *elt)
>  {
>  	const unsigned int offset = (unsigned long)key;
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index 4f4dd2b..188909a 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -74,6 +74,17 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
>  void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
>  			unsigned int len, unsigned long val);
>  
> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len);
> +
> +void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val);
> +
> +void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val);
> +
>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>  
>  #endif
> -- 
> 2.7.3
> 


From javier at osg.samsung.com  Wed May 11 05:33:46 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 11 May 2016 08:33:46 -0400
Subject: [PATCH v3 25/27] ARM: dts: exynos: Move HSI2C nodes to
 exynos54xx.dtsi
In-Reply-To: <1462910970-1812-26-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
 <1462910970-1812-26-git-send-email-krzk@kernel.org>
Message-ID: <10927e67-86cb-8d4d-ed2c-1ac480b4e50f@osg.samsung.com>

Hello Krzysztof,

On 05/10/2016 04:09 PM, Krzysztof Kozlowski wrote:
> The USI/HSI2C nodes can be mostly shared between Exynos5420 and
> Exynos5410 so move them to common DTSI.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From arnd at arndb.de  Wed May 11 05:34:22 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 14:34:22 +0200
Subject: [PATCH] drm: mediatek: add COMMON_CLK dependency
Message-ID: <1462970100-240687-1-git-send-email-arnd@arndb.de>

On kernel builds without COMMON_CLK, the newly added mediatek drm
driver fails to build:

drivers/gpu/drm/mediatek/mtk_mipi_tx.c:130:16: error: field 'pll_hw' has incomplete type
  struct clk_hw pll_hw;
                ^~~~~~
In file included from ../include/linux/clk.h:16:0,
                 from ../drivers/gpu/drm/mediatek/mtk_mipi_tx.c:14:
drivers/gpu/drm/mediatek/mtk_mipi_tx.c: In function 'mtk_mipi_tx_from_clk_hw':
include/linux/kernel.h:831:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
  const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                ^
/drivers/gpu/drm/mediatek/mtk_mipi_tx.c:136:9: note: in expansion of macro 'container_of'
  return container_of(hw, struct mtk_mipi_tx, pll_hw);
         ^~~~~~~~~~~~
drivers/gpu/drm/mediatek/mtk_mipi_tx.c: At top level:
drivers/gpu/drm/mediatek/mtk_mipi_tx.c:302:21: error: variable 'mtk_mipi_tx_pll_ops' has initializer but incomplete type
 static const struct clk_ops mtk_mipi_tx_pll_ops = {

This adds the required Kconfig dependency.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/gpu/drm/mediatek/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
index eeefc971801a..0c06a69d7f04 100644
--- a/drivers/gpu/drm/mediatek/Kconfig
+++ b/drivers/gpu/drm/mediatek/Kconfig
@@ -2,6 +2,7 @@ config DRM_MEDIATEK
 	tristate "DRM Support for Mediatek SoCs"
 	depends on DRM
 	depends on ARCH_MEDIATEK || (ARM && COMPILE_TEST)
+	depends on COMMON_CLK
 	select DRM_GEM_CMA_HELPER
 	select DRM_KMS_HELPER
 	select DRM_MIPI_DSI
-- 
2.7.0



From javier at osg.samsung.com  Wed May 11 05:36:34 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 11 May 2016 08:36:34 -0400
Subject: [PATCH v3 26/27] ARM: dts: exynos: Add I2C, PWM and UART pinctrl
 to Exynos5410
In-Reply-To: <1462910970-1812-27-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
 <1462910970-1812-27-git-send-email-krzk@kernel.org>
Message-ID: <1d8b5479-3e29-9523-1862-4dc5fe5da384@osg.samsung.com>

Hello Krzysztof,

On 05/10/2016 04:09 PM, Krzysztof Kozlowski wrote:
> Add pincontrol groups for HSI2C (USI), I2C, PWM and UART to Exynos5410.
> This allows configuring these pins to specific functions.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From heiko at sntech.de  Wed May 11 05:42:23 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 11 May 2016 14:42:23 +0200
Subject: [PATCH] mmc: dw_mmc: rockchip: Set the drive phase to 180 degrees
In-Reply-To: <1462904195-18229-1-git-send-email-dianders@chromium.org>
References: <1462904195-18229-1-git-send-email-dianders@chromium.org>
Message-ID: <6174748.3ugS9uJXKS@phil>

Am Dienstag, 10. Mai 2016, 11:16:35 schrieb Douglas Anderson:
> Historically for Rockchip devices we've relied on the power-on
> default (or perhaps the firmware setting) to get the correct drive
> phase for dw_mmc devices.  This worked OK for the most part, but:
> 
> * Relying on the setting just "being right" is a bit fragile.
> 
> * As soon as there is an instance where the power on default is wrong or
>   where the firmware didn't configure this properly then we'll get a
>   mysterious failure.
> 
> Let's explicitly set this phase in the kernel.
> 
> You might notice that this patch is currently very dumb and just always
> sets this phase to 180 degrees.  As far as I can tell this is actually a
> sane thing to do.  From reading through the Designware Databook it
> appears that there are instances where you could still meet hold time
> requirements and set this phase to 90 degrees, but nothing I've read
> indicates that 180 degrees is not OK also.
> 
> As indicated above, adding a delay to the drive is used to achieve
> proper hold times.  For a given speed mode hold times are listed in the
> spec in terms of nanoseconds.  The hold times are different for
> different speed modes.  The actual hold time achieved is actually a
> function of Delay_O (an internal delay in dw_mmc, which could vary from
> SoC model to SoC model), pad delays, and the drive delay (which we're
> setting here).  Note also that by setting the drive delay as a phase we
> will get a different number of nanoseconds of delay depending on the
> input clock.
> 
> Note that, as far as I can tell, this _does_ change the behavior of
> rk3288 devices.  On devices I tested, which use coreboot/depthcharge as
> BIOS, the SDMMC/SDIO0/SDIO1 drive phase used to be 90 degrees.  Now it
> will be 180 degrees.  With my understanding from the Designware Databook
> the 180 degrees ought to be more correct and should increase
> compatibility.
> 
> I have tested this by inserting my collection of uSD cards (mostly UHS,
> though a few not) into a veyron_minnie and confirmed that they still
> seem to enumerate properly.  For a subset of them I tried putting a
> filesystem on them and also tried running mmc_test.
> 
> Signed-off-by: Douglas Anderson <dianders at chromium.org>
> ---
>  drivers/mmc/host/dw_mmc-rockchip.c | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/drivers/mmc/host/dw_mmc-rockchip.c
> b/drivers/mmc/host/dw_mmc-rockchip.c index 8c20b81cafd8..62cbd33a07cd
> 100644
> --- a/drivers/mmc/host/dw_mmc-rockchip.c
> +++ b/drivers/mmc/host/dw_mmc-rockchip.c
> @@ -66,6 +66,27 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host,
> struct mmc_ios *ios) /* Make sure we use phases which we can enumerate
> with */
>  	if (!IS_ERR(priv->sample_clk))
>  		clk_set_phase(priv->sample_clk, priv->default_sample_phase);
> +
> +	/*
> +	 * Set the drive phase to 180 degrees.  This helps us achieve proper
> +	 * hold times.
> +	 *
> +	 * Note that this is _not_ a value that is tuned and is also _not_ a
> +	 * value that will vary from board to board.  It is a value that
> +	 * _could_ vary between different SoC models (could be different on
> +	 * rk3066 vs. rk3288 for instance).  It is also a value that _could_

I saw you talking with Shawn in the other thread on doing this in a 
different way, but that statement itself is incorrect and should not land in 
the kernel.

At least rk3066/rk3188 (and most likely earlier) do not support the tuning 
at all and the drive-clock is going through a static non-controllable 
inverter (according to the CRU docs), so should always be at 180 degrees.


> +	 * need to be adjusted based on our clock frequency and speed mode
> +	 * since different speed modes have different hold time requirements
> +	 * and hold time requirements are in "ns" (a phase offset adds a
> +	 * different "ns" delay for different input clocks).
> +	 *
> +	 * Despite these theoretical needs, it has been observed that 180
> +	 * degrees gives us good signaling across all tested SoCs and all
> +	 * tested speed modes.  If when we find someone that needs 90 degrees
> +	 * here we can add a table based on speed mode / SoC compatible ID.
> +	 */
> +	if (!IS_ERR(priv->drv_clk))
> +		clk_set_phase(priv->drv_clk, 180);
>  }
> 
>  #define NUM_PHASES			360



From maxime.ripard at free-electrons.com  Wed May 11 05:43:44 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 11 May 2016 14:43:44 +0200
Subject: [PATCH 0/2] ARM: dts: sun6i: Drop constraints on dc1sw regulator
In-Reply-To: <1462944194-6920-1-git-send-email-wens@csie.org>
References: <1462944194-6920-1-git-send-email-wens@csie.org>
Message-ID: <20160511124344.GO3733@lukather>

On Wed, May 11, 2016 at 01:23:12PM +0800, Chen-Yu Tsai wrote:
> Hi Arnd, Olof,
> 
> Here are 2 last minute fixes for 4.6. The 2 patches drop constaints on
> the dc1sw regulator for 2 A31s tablets. I checked with Maxime and he said
> to send them directly to you.
> 
> The issue was first brought up and fixed for A23/A33 Q8 tablets in commit
> dcf5341f0150 ("ARM: dts: sun8i-q8-common: Do not set constraints on dc1sw
> regulator"). It was brought up again yesterday on IRC, and I realized that
> 2 sun6i A31s tablet DTS files also had this setting. The setting causes
> PMIC regulator registration to fail, and since among other things, mmc
> depends on the regulators, the system will likely hang.
> 
> There seems to be a fix for this queued up for 4.7: commit 45389c47526d
> ("regulator: core: Add early supply resolution for regulators") in the
> regulator "supply" topic branch. So we should be able to revert these
> fixes in 4.7.

Acked-by: Maxime Ripard <maxime.ripard at free-electrons.com>

For the two patches.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160511/abb6a4b8/attachment.sig>

From javier at osg.samsung.com  Wed May 11 05:44:16 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 11 May 2016 08:44:16 -0400
Subject: [PATCH v3 27/27] ARM: dts: exynos: Add RTC and I2C to Exynos5410
In-Reply-To: <1462910970-1812-28-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
 <1462910970-1812-28-git-send-email-krzk@kernel.org>
Message-ID: <b1f47282-f70e-4354-9146-9b4b27ba1726@osg.samsung.com>

Hello Krzysztof,

On 05/10/2016 04:09 PM, Krzysztof Kozlowski wrote:
> Configure Exynos5410-specific properties of RTC, I2C and HSI2C nodes.
> This still does not enable them on the board level though.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---
>  arch/arm/boot/dts/exynos5410.dtsi | 66 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 66 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
> index dd4d6d752865..ae64cb0a8efd 100644
> --- a/arch/arm/boot/dts/exynos5410.dtsi
> +++ b/arch/arm/boot/dts/exynos5410.dtsi
> @@ -114,6 +114,9 @@
>  			status = "disabled";
>  		};
>  
> +		/* i2c_0-3 are defined in exynos5.dtsi */
> +		/* hsi2c_4-7 are defined in exynos5xx.dtsi */
> +

I don't think these comments are needed. For each DTS, there are usually a lot of
nodes defined in higher levels of the DT hierarchy but isn't common to mention it.

Specially since the mentioned nodes are referenced here by their labels so it is
implicit that are defined in one of the included DTSI (or dtc will fail to build).

The actual change looks good to me though:

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From andre.przywara at arm.com  Wed May 11 05:47:16 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 13:47:16 +0100
Subject: [PATCH v3 23/55] KVM: arm/arm64: vgic-new: Add CTLR, TYPER and
 IIDR handlers
In-Reply-To: <20160511120533.GM27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-24-git-send-email-andre.przywara@arm.com>
 <20160511120533.GM27623@cbox>
Message-ID: <573329D4.5030508@arm.com>

Hej,

On 11/05/16 13:05, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:36AM +0100, Andre Przywara wrote:
>> From: Marc Zyngier <marc.zyngier at arm.com>
>>
>> Those three registers are v2 emulation specific, so their implementation
>> lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
>> as their implementation is pretty simple.
>> When the guest enables the distributor, we kick all VCPUs to get
>> potentially pending interrupts serviced.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - kick VCPUs is the distributor gets enabled
>> - improve comment
>>
>> Changelog v1 .. v2:
>> - adapt to new MMIO framework
>> - use switch() statements to improve readability
>>
>> Changelog v2 .. v3:
>> - add vgic_kick_vcpus() implementation
>>
>>  include/linux/irqchip/arm-gic.h  |  1 +
>>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 48 +++++++++++++++++++++++++++++++++++++++-
>>  virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
>>  virt/kvm/arm/vgic/vgic.h         |  4 ++++
>>  4 files changed, 67 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>> index be0d26f..fd05185 100644
>> --- a/include/linux/irqchip/arm-gic.h
>> +++ b/include/linux/irqchip/arm-gic.h
>> @@ -33,6 +33,7 @@
>>  
>>  #define GIC_DIST_CTRL			0x000
>>  #define GIC_DIST_CTR			0x004
>> +#define GIC_DIST_IIDR			0x008
>>  #define GIC_DIST_IGROUP			0x080
>>  #define GIC_DIST_ENABLE_SET		0x100
>>  #define GIC_DIST_ENABLE_CLEAR		0x180
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> index 2729a22..69e96f7 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> @@ -20,9 +20,55 @@
>>  #include "vgic.h"
>>  #include "vgic-mmio.h"
>>  
>> +static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
>> +					    gpa_t addr, unsigned int len)
>> +{
>> +	u32 value;
>> +
>> +	switch (addr & 0x0c) {
>> +	case GIC_DIST_CTRL:
>> +		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
>> +		break;
>> +	case GIC_DIST_CTR:
>> +		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
>> +		value = (value >> 5) - 1;
>> +		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
>> +		break;
>> +	case GIC_DIST_IIDR:
>> +		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
>> +		break;
>> +	default:
>> +		return 0;
>> +	}
>> +
>> +	return extract_bytes(value, addr & 3, len);
>> +}
>> +
>> +static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
>> +				    gpa_t addr, unsigned int len,
>> +				    unsigned long val)
>> +{
>> +	switch (addr & 0x0c) {
>> +	case GIC_DIST_CTRL:
>> +		if (!(addr & 1)) {
> 
> what is this !(addr & 1) check?

Mmmh, interesting. The original idea was that we care only about the
lowest significant byte. I guess this was somehow lost in translation
when Marc reworked the function. I think it should at least read:
"if (!(addr & 3))" to match the switch mask, otherwise for instance a
byte write to address 2 triggers the if branch as well.

I will fix the mask to 3 and add a comment.

Thanks,
Andre.


> 
>> +			struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>> +			bool was_enabled = dist->enabled;
>> +
>> +			dist->enabled = val & GICD_ENABLE;
>> +			if (!was_enabled && dist->enabled)
>> +				vgic_kick_vcpus(vcpu->kvm);
>> +		}
>> +		break;
>> +	case GIC_DIST_CTR:
>> +	case GIC_DIST_IIDR:
>> +		/* Nothing to do */
>> +		return;
>> +	}
>> +}
>> +
>>  static const struct vgic_register_region vgic_v2_dist_registers[] = {
>>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 12),
>> +		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
>>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>> index c3dbcf3..5355de6 100644
>> --- a/virt/kvm/arm/vgic/vgic.c
>> +++ b/virt/kvm/arm/vgic/vgic.c
>> @@ -544,3 +544,18 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
>>  
>>  	return pending;
>>  }
>> +
>> +void vgic_kick_vcpus(struct kvm *kvm)
>> +{
>> +	struct kvm_vcpu *vcpu;
>> +	int c;
>> +
>> +	/*
>> +	 * We've injected an interrupt, time to find out who deserves
>> +	 * a good kick...
>> +	 */
>> +	kvm_for_each_vcpu(c, vcpu, kvm) {
>> +		if (kvm_vgic_vcpu_pending_irq(vcpu))
>> +			kvm_vcpu_kick(vcpu);
>> +	}
>> +}
>> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>> index fd9acaa..cf62015 100644
>> --- a/virt/kvm/arm/vgic/vgic.h
>> +++ b/virt/kvm/arm/vgic/vgic.h
>> @@ -16,11 +16,15 @@
>>  #ifndef __KVM_ARM_VGIC_NEW_H__
>>  #define __KVM_ARM_VGIC_NEW_H__
>>  
>> +#define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
>> +#define IMPLEMENTER_ARM		0x43b
>> +
>>  #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
>>  
>>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>>  			      u32 intid);
>>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
>> +void vgic_kick_vcpus(struct kvm *kvm);
>>  
>>  void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
>>  void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
>> -- 
>> 2.7.3
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe kvm" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


From arnd at arndb.de  Wed May 11 05:49:53 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 14:49:53 +0200
Subject: [PATCH] phy: exynos-mipi-video: avoid uninitialized variable use
Message-ID: <1462971012-562097-1-git-send-email-arnd@arndb.de>

A rework of the exynos-mipi-video driver caused a warning
about the new __set_phy_state function potentially accessing
a variable before its initialization:

drivers/phy/phy-exynos-mipi-video.c: In function '__set_phy_state':
drivers/phy/phy-exynos-mipi-video.c:238:13: error: 'val' may be used uninitialized in this function [-Werror=maybe-uninitialized]
  return val & data->resetn_val;
         ~~~~^~~~~~~~~~~~~~~~~~
drivers/phy/phy-exynos-mipi-video.c:235:6: note: 'val' was declared here
  u32 val;

The failure scenario here is the offset passed into a the
stub regmap_read() function that does not modify its output,
however regmap_read() can also fail for other reasons, so
adding error handling (in this case, returning zero from
is_running) seems the best solution.

Note that this warning showed up with the ARM s5pv210_defconfig,
indicating that we most likely want to either enable CONFIG_REGMAP
in that defconfig as well, or disable the phy-exynos-mipi-video
driver.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 97a3042f7616 ("phy: exynos-mipi-video: Rewrite handling of phy registers")
---
 drivers/phy/phy-exynos-mipi-video.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
index cc093ebfda94..8b851f718123 100644
--- a/drivers/phy/phy-exynos-mipi-video.c
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -233,8 +233,12 @@ static inline int __is_running(const struct exynos_mipi_phy_desc *data,
 			struct exynos_mipi_video_phy *state)
 {
 	u32 val;
+	int ret;
+
+	ret = regmap_read(state->regmaps[data->resetn_map], data->resetn_reg, &val);
+	if (ret)
+		return 0;
 
-	regmap_read(state->regmaps[data->resetn_map], data->resetn_reg, &val);
 	return val & data->resetn_val;
 }
 
-- 
2.7.0



From marc.zyngier at arm.com  Wed May 11 05:51:36 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 11 May 2016 13:51:36 +0100
Subject: [PATCH v3 23/55] KVM: arm/arm64: vgic-new: Add CTLR, TYPER and
 IIDR handlers
In-Reply-To: <20160511120533.GM27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-24-git-send-email-andre.przywara@arm.com>
 <20160511120533.GM27623@cbox>
Message-ID: <57332AD8.6050306@arm.com>

On 11/05/16 13:05, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:36AM +0100, Andre Przywara wrote:
>> From: Marc Zyngier <marc.zyngier at arm.com>
>>
>> Those three registers are v2 emulation specific, so their implementation
>> lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
>> as their implementation is pretty simple.
>> When the guest enables the distributor, we kick all VCPUs to get
>> potentially pending interrupts serviced.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - kick VCPUs is the distributor gets enabled
>> - improve comment
>>
>> Changelog v1 .. v2:
>> - adapt to new MMIO framework
>> - use switch() statements to improve readability
>>
>> Changelog v2 .. v3:
>> - add vgic_kick_vcpus() implementation
>>
>>  include/linux/irqchip/arm-gic.h  |  1 +
>>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 48 +++++++++++++++++++++++++++++++++++++++-
>>  virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
>>  virt/kvm/arm/vgic/vgic.h         |  4 ++++
>>  4 files changed, 67 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>> index be0d26f..fd05185 100644
>> --- a/include/linux/irqchip/arm-gic.h
>> +++ b/include/linux/irqchip/arm-gic.h
>> @@ -33,6 +33,7 @@
>>  
>>  #define GIC_DIST_CTRL			0x000
>>  #define GIC_DIST_CTR			0x004
>> +#define GIC_DIST_IIDR			0x008
>>  #define GIC_DIST_IGROUP			0x080
>>  #define GIC_DIST_ENABLE_SET		0x100
>>  #define GIC_DIST_ENABLE_CLEAR		0x180
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> index 2729a22..69e96f7 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> @@ -20,9 +20,55 @@
>>  #include "vgic.h"
>>  #include "vgic-mmio.h"
>>  
>> +static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
>> +					    gpa_t addr, unsigned int len)
>> +{
>> +	u32 value;
>> +
>> +	switch (addr & 0x0c) {
>> +	case GIC_DIST_CTRL:
>> +		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
>> +		break;
>> +	case GIC_DIST_CTR:
>> +		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
>> +		value = (value >> 5) - 1;
>> +		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
>> +		break;
>> +	case GIC_DIST_IIDR:
>> +		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
>> +		break;
>> +	default:
>> +		return 0;
>> +	}
>> +
>> +	return extract_bytes(value, addr & 3, len);
>> +}
>> +
>> +static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
>> +				    gpa_t addr, unsigned int len,
>> +				    unsigned long val)
>> +{
>> +	switch (addr & 0x0c) {
>> +	case GIC_DIST_CTRL:
>> +		if (!(addr & 1)) {
> 
> what is this !(addr & 1) check?

We check that the write includes the lowest byte of the register. But as
we only have aligned accesses, it probably doesn't matter... I'll hack
that away.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From krzk at kernel.org  Wed May 11 05:54:18 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 14:54:18 +0200
Subject: [PATCH v3 27/27] ARM: dts: exynos: Add RTC and I2C to Exynos5410
In-Reply-To: <b1f47282-f70e-4354-9146-9b4b27ba1726@osg.samsung.com>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
 <1462910970-1812-28-git-send-email-krzk@kernel.org>
 <b1f47282-f70e-4354-9146-9b4b27ba1726@osg.samsung.com>
Message-ID: <57332B7A.5070909@kernel.org>

On 05/11/2016 02:44 PM, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/10/2016 04:09 PM, Krzysztof Kozlowski wrote:
>> Configure Exynos5410-specific properties of RTC, I2C and HSI2C nodes.
>> This still does not enable them on the board level though.
>>
>> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
>> ---
>>  arch/arm/boot/dts/exynos5410.dtsi | 66 +++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 66 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
>> index dd4d6d752865..ae64cb0a8efd 100644
>> --- a/arch/arm/boot/dts/exynos5410.dtsi
>> +++ b/arch/arm/boot/dts/exynos5410.dtsi
>> @@ -114,6 +114,9 @@
>>  			status = "disabled";
>>  		};
>>  
>> +		/* i2c_0-3 are defined in exynos5.dtsi */
>> +		/* hsi2c_4-7 are defined in exynos5xx.dtsi */
>> +
> 
> I don't think these comments are needed. For each DTS, there are usually a lot of
> nodes defined in higher levels of the DT hierarchy but isn't common to mention it.
> 
> Specially since the mentioned nodes are referenced here by their labels so it is
> implicit that are defined in one of the included DTSI (or dtc will fail to build).

Okay, if it does not make sense to you then I'll remove them.

Thanks for review!
Krzysztof




From gabriele.paoloni at huawei.com  Wed May 11 05:53:25 2016
From: gabriele.paoloni at huawei.com (Gabriele Paoloni)
Date: Wed, 11 May 2016 12:53:25 +0000
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <57331290.7070104@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
Message-ID: <EE11001F9E5DDD47B7634E2F8A612F2E1ED8E264@lhreml503-mbs>

Hi Tomasz

> -----Original Message-----
> From: Tomasz Nowicki [mailto:tn at semihalf.com]
> Sent: 11 May 2016 12:08
> To: Gabriele Paoloni; helgaas at kernel.org; arnd at arndb.de;
> will.deacon at arm.com; catalin.marinas at arm.com; rafael at kernel.org;
> hanjun.guo at linaro.org; Lorenzo.Pieralisi at arm.com; okaya at codeaurora.org;
> jchandra at broadcom.com
> Cc: robert.richter at caviumnetworks.com; mw at semihalf.com;
> Liviu.Dudau at arm.com; ddaney at caviumnetworks.com; Wangyijing;
> Suravee.Suthikulpanit at amd.com; msalter at redhat.com; linux-
> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-
> acpi at vger.kernel.org; linux-kernel at vger.kernel.org; linaro-
> acpi at lists.linaro.org; jcm at redhat.com; andrea.gallo at linaro.org;
> dhdang at apm.com; jeremy.linton at arm.com; liudongdong (C);
> cov at codeaurora.org
> Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI host
> controller
> 
> Hi Gabriele,
> 
> On 11.05.2016 12:41, Gabriele Paoloni wrote:
> > Hi Tomasz
> >
> >> -----Original Message-----
> >> From: linux-kernel-owner at vger.kernel.org [mailto:linux-kernel-
> >> owner at vger.kernel.org] On Behalf Of Tomasz Nowicki
> >> Sent: 10 May 2016 16:20
> >> To: helgaas at kernel.org; arnd at arndb.de; will.deacon at arm.com;
> >> catalin.marinas at arm.com; rafael at kernel.org; hanjun.guo at linaro.org;
> >> Lorenzo.Pieralisi at arm.com; okaya at codeaurora.org;
> jchandra at broadcom.com
> >> Cc: robert.richter at caviumnetworks.com; mw at semihalf.com;
> >> Liviu.Dudau at arm.com; ddaney at caviumnetworks.com; Wangyijing;
> >> Suravee.Suthikulpanit at amd.com; msalter at redhat.com; linux-
> >> pci at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-
> >> acpi at vger.kernel.org; linux-kernel at vger.kernel.org; linaro-
> >> acpi at lists.linaro.org; jcm at redhat.com; andrea.gallo at linaro.org;
> >> dhdang at apm.com; jeremy.linton at arm.com; liudongdong (C);
> >> cov at codeaurora.org; Tomasz Nowicki
> >> Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
> >> controller
> >>
> >>  From the functionality point of view this series may be split into
> the
> >> following logic parts:
> >> 1. New ECAM API and update for users of the pci-host-common API
> >> 2. Necessary fixes as the preparation for using driver on ARM64.
> >> 3. Use new MCFG interface and implement generic ACPI based PCI host
> >> controller driver.
> >> 4. Enable above driver on ARM64
> >>
> >> Patches has been built on top of 4.6-rc7 and can be found here:
> >> git at github.com:semihalf-nowicki-tomasz/linux.git (pci-acpi-v7)
> >>
> >> This has been tested on Cavium ThunderX server. Any help in
> reviewing
> >> and
> >> testing is very appreciated.
> >>
> >> v6 -> v7
> >> - drop quirks handling
> >
> > Maybe I missed something in the v6 discussion thread; when was it
> > decided to drop quirk handling?
> 
> I had such requests in previous series.
> 
> >
> > I think it is important to have this in place to accommodate
> different
> > vendors. If the intention is to keep this patchset "clean" maybe
> > we can add it as a separate patch on top later on...
> >
> > What's your view?
> 
> Yes, keeping these things separated should help in review. Obviously I
> agree that we need quirk handling but currently there is no
> implementation which we all agree upon. For the test, you can use quirk
> handling approach from the previous series until we sort out final
> solution.

Great

This explains perfectly

We will apply previous series quirks and try to test the patchset
from Huawei side

Many Thanks

Gab

> 
> Thanks,
> Tomasz


From robin.murphy at arm.com  Wed May 11 05:55:20 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed, 11 May 2016 13:55:20 +0100
Subject: [PATCH 1/1] arm64: Add ARM64 optimized IP checksum routine
In-Reply-To: <1462904847-28369-1-git-send-email-luke.starrett@broadcom.com>
References: <1462904847-28369-1-git-send-email-luke.starrett@broadcom.com>
Message-ID: <57332BB8.9060004@arm.com>

Hi Luke,

On 10/05/16 19:27, Luke Starrett wrote:
> This change implements an optimized checksum for arm64, based loosely on
> the original arch/arm implementation.  Load-pair is used for the initial
> 16B load, reducing the overall number of loads to two for packets without
> IP options.  Instruction count is reduced by ~3x compared to generic C
> implementation.  Changes were tested against LE and BE operation and for
> all possible mis-alignments.
>
> Signed-off-by: Luke Starrett <luke.starrett at broadcom.com>
> ---
>   arch/arm64/include/asm/checksum.h | 57 +++++++++++++++++++++++++++++++++++++++
>   1 file changed, 57 insertions(+)
>   create mode 100644 arch/arm64/include/asm/checksum.h
>
> diff --git a/arch/arm64/include/asm/checksum.h b/arch/arm64/include/asm/checksum.h
> new file mode 100644
> index 0000000..15629d7
> --- /dev/null
> +++ b/arch/arm64/include/asm/checksum.h
> @@ -0,0 +1,57 @@
> +/*
> + * Copyright 2016 Broadcom
> + *
> + * 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 (the "GPL").
> + *
> + * 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 version 2 (GPLv2) for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * version 2 (GPLv2) along with this source code.
> + *
> + * ip_fast_csum() loosely derived from original arch/arm implementation
> + */
> +
> +#ifndef __ASM_ARM64_CHECKSUM_H
> +#define __ASM_ARM64_CHECKSUM_H
> +
> +/*
> + * This is a version of ip_compute_csum() optimized for IP headers,
> + * which always checksum on 4 octet boundaries.
> + */
> +static inline __sum16
> +ip_fast_csum(const void *iph, unsigned int ihl)
> +{
> +	u64 tmp, sum;
> +
> +	__asm__ __volatile__ (
> +"	ldp	%0, %3, [%1], #16\n"
> +"	sub	%2, %2, #4\n"
> +"	adds	%0, %0, %3\n"
> +"1:	ldr	%w3, [%1], #4\n"
> +"	sub	%2, %2, #1\n"
> +"	adcs	%0, %0, %3\n"

This looks suspicious - the following tst is going to zero the carry 
flag, so either setting the flags is unnecessary, or things are working 
by chance.

> +"	tst	%2, #15\n"
> +"	bne	1b\n"
> +"	adc	%0, %0, xzr\n"

Similarly, you should never get here with the carry flag set, so this is 
just a pointless nop.

> +"	ror	%3, %0, #32\n"
> +"	add     %0, %0, %3\n"
> +"	lsr	%0, %0, #32\n"
> +"	ror	%w3, %w0, #16\n"
> +"	add     %w0, %w0, %w3\n"
> +"	lsr	%0, %0, #16\n"
> +	: "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp)
> +	: "1" (iph), "2" (ihl)
> +	: "cc", "memory");
> +
> +	return (__force __sum16)(~sum);
> +}

Given that dodginess, and that there doesn't seem to be anything here 
which absolutely _demands_ assembly voodoo, can we not just have an 
optimised C implementation working on larger chunks, along the lines of 
Alpha?

Robin.

> +
> +#define ip_fast_csum ip_fast_csum
> +#include <asm-generic/checksum.h>
> +
> +#endif	/* __ASM_ARM64_CHECKSUM_H */
>



From eric.auger at linaro.org  Wed May 11 05:58:14 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed, 11 May 2016 14:58:14 +0200
Subject: [PATCH v9 3/7] vfio/type1: bypass unmap/unpin and replay for
 VFIO_IOVA_RESERVED slots
In-Reply-To: <20160509164936.1a5ae402@t450s.home>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-4-git-send-email-eric.auger@linaro.org>
 <20160509164936.1a5ae402@t450s.home>
Message-ID: <57332C66.30105@linaro.org>

Hi Alex,
On 05/10/2016 12:49 AM, Alex Williamson wrote:
> On Wed,  4 May 2016 11:54:14 +0000
> Eric Auger <eric.auger at linaro.org> wrote:
> 
>> Before allowing the end-user to create VFIO_IOVA_RESERVED dma slots,
>> let's implement the expected behavior for removal and replay. As opposed
>> to user dma slots, IOVAs are not systematically bound to PAs and PAs are
>> not pinned. VFIO just initializes the IOVA "aperture". IOVAs are allocated
>> outside of the VFIO framework, typically the MSI layer which is
>> responsible to free and unmap them. The MSI mapping resources are freeed
>> by the IOMMU driver on domain destruction.
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>
>> ---
>>
>> v7 -> v8:
>> - do no destroy anything anymore, just bypass unmap/unpin and iommu_map
>>   on replay
>> ---
>>  drivers/vfio/vfio_iommu_type1.c | 5 ++++-
>>  1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
>> index 2d769d4..94a9916 100644
>> --- a/drivers/vfio/vfio_iommu_type1.c
>> +++ b/drivers/vfio/vfio_iommu_type1.c
>> @@ -391,7 +391,7 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
>>  	struct vfio_domain *domain, *d;
>>  	long unlocked = 0;
>>  
>> -	if (!dma->size)
>> +	if (!dma->size || dma->type != VFIO_IOVA_USER)
>>  		return;
>>  	/*
>>  	 * We use the IOMMU to track the physical addresses, otherwise we'd
>> @@ -727,6 +727,9 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
>>  		dma = rb_entry(n, struct vfio_dma, node);
>>  		iova = dma->iova;
>>  
>> +		if (dma->type == VFIO_IOVA_RESERVED)
>> +			continue;
>> +
> 
> But you do still need some sort of replay mechanism, right?  Not to
> replay the IOVA to PA mapping, but to call iommu_msi_set_aperture() for
> the new domain.  How will you know that this entry is an MSI reserved
> range or something else?  Perhaps we can't have a generic "reserved"
> type here.
Thanks for spotting this bug. I was not testing this case yet and
effectively I need to replay the set_aperture.

Thanks for the review

Best Regards

Eric

> 
>>  		while (iova < dma->iova + dma->size) {
>>  			phys_addr_t phys = iommu_iova_to_phys(d->domain, iova);
>>  			size_t size;
> 



From andre.przywara at arm.com  Wed May 11 06:04:13 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 14:04:13 +0100
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <20160511123423.GO27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
 <20160511123423.GO27623@cbox>
Message-ID: <57332DCD.1020701@arm.com>

Hi,

On 11/05/16 13:34, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:37AM +0100, Andre Przywara wrote:
>> As the enable register handlers are shared between the v2 and v3
>> emulation, their implementation goes into vgic-mmio.c, to be easily
>> referenced from the v3 emulation as well later.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - use lower bits of address to determine IRQ number
>> - remove TODO, confirmed to be fine
>>
>> Changelog v1 .. v2:
>> - adapt to new MMIO framework
>>
>>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
>>  virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
>>  3 files changed, 69 insertions(+), 2 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> index 69e96f7..448d1da 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> @@ -72,9 +72,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
>>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
>>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
>> index 41cf4f4..077ae86 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>> @@ -46,6 +46,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
>>  	/* Ignore */
>>  }
>>  
>> +/*
>> + * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
>> + * of the enabled bit, so there is only one function for both here.
>> + */
>> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
>> +				    gpa_t addr, unsigned int len)
>> +{
>> +	u32 intid = (addr & 0x7f) * 8;
> 
> is there anything we can do about this to make it more intuitive?  A
> macro to generate the mask/offset based on bits per interrupt or
> something?

Yes, something where you give it the address and the bits-per-IRQ and it
tells you the IRQ number.
Not sure it is advisable to squash this into v4 still?

> 
>> +	u32 value = 0;
>> +	int i;
>> +
>> +	/* Loop over all IRQs affected by this read */
>> +	for (i = 0; i < len * 8; i++) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
>> +		if (irq->enabled)
>> +			value |= (1U << i);
> 
> I couldn't find the code anywhere that enforces word-aligned accesses to
> these registers.  Do we have that?

Not that I am aware of. I was suggesting this since we have one in the
IROUTER function. Architecturally we don't need to support halfword
accesses, it's: byte + word, word only or double-word + word, depending
on the actual register, IIRC.
As a fix we can at least deny (read: ignore) halfword accesses in
general in the dispatcher. Shall I do this (two two-liners)?
I think byte and word accesses are safe with the existing handlers last
time I checked.

> If that's not the case, doesn't this break of you do a non-word aligned
> access?

Why would it? vgic_data_host_to_mmio_bus and extract_bytes should cover
this, shouldn't they?

Cheers,
Andre.

> 
>> +	}
>> +
>> +	return extract_bytes(value, addr & 3, len);
>> +}
>> +
>> +void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
>> +			     gpa_t addr, unsigned int len,
>> +			     unsigned long val)
>> +{
>> +	u32 intid = (addr & 0x7f) * 8;
>> +	int i;
>> +
>> +	for_each_set_bit(i, &val, len * 8) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
>> +		spin_lock(&irq->irq_lock);
>> +		irq->enabled = true;
>> +		vgic_queue_irq_unlock(vcpu->kvm, irq);
>> +	}
>> +}
>> +
>> +void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
>> +			     gpa_t addr, unsigned int len,
>> +			     unsigned long val)
>> +{
>> +	u32 intid = (addr & 0x7f) * 8;
>> +	int i;
>> +
>> +	for_each_set_bit(i, &val, len * 8) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
>> +		spin_lock(&irq->irq_lock);
>> +
>> +		irq->enabled = false;
>> +
>> +		spin_unlock(&irq->irq_lock);
> 
> nit: whitespace consistency with senable
> 
>> +	}
>> +}
>> +
>>  static int match_region(const void *key, const void *elt)
>>  {
>>  	const unsigned int offset = (unsigned long)key;
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
>> index 4f4dd2b..188909a 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio.h
>> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
>> @@ -74,6 +74,17 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
>>  void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
>>  			unsigned int len, unsigned long val);
>>  
>> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
>> +				    gpa_t addr, unsigned int len);
>> +
>> +void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
>> +			     gpa_t addr, unsigned int len,
>> +			     unsigned long val);
>> +
>> +void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
>> +			     gpa_t addr, unsigned int len,
>> +			     unsigned long val);
>> +
>>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>>  
>>  #endif
>> -- 
>> 2.7.3
>>
> 


From dannenberg at ti.com  Wed May 11 06:07:41 2016
From: dannenberg at ti.com (Andreas Dannenberg)
Date: Wed, 11 May 2016 08:07:41 -0500
Subject: [PATCH 1/2] ARM: dts: dra7: Add ocmcram nodes
In-Reply-To: <1462909782-14639-2-git-send-email-d-gerlach@ti.com>
References: <1462909782-14639-1-git-send-email-d-gerlach@ti.com>
 <1462909782-14639-2-git-send-email-d-gerlach@ti.com>
Message-ID: <20160511130741.GR20461@borg.dal.design.ti.com>

On Tue, May 10, 2016 at 02:49:41PM -0500, Dave Gerlach wrote:
> Add all ocmcram nodes to dra7.dtsi using the generic mmio-sram driver.
> DRA7xx and AM57xx families of SoCs can contain three ocmcram regions of
> SRAM, one of 512kb and also an optional two additional of 1Mb each. Mark
> the two additional 1MB regions of SRAM as disabled as only ocmcmram1 is
> on all variants of the SoCs, then depending on which specific variant
> is in use the ocmcram2 and ocmcram3 nodes can be enabled in the board
> dts file if the data manual for that part number indicates the ocmcram
> region is available.
> 
> Signed-off-by: Dave Gerlach <d-gerlach at ti.com>

Reviewed-by: Andreas Dannenberg <dannenberg at ti.com>


Regards,

--
Andreas Dannenberg
Texas Instruments Inc



From andre.przywara at arm.com  Wed May 11 06:09:26 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 14:09:26 +0100
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <573319A4.30905@linaro.org>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
 <5731EBBE.7060203@linaro.org> <573317DC.4060200@arm.com>
 <573319A4.30905@linaro.org>
Message-ID: <57332F06.90202@arm.com>

Hi,

On 11/05/16 12:38, Eric Auger wrote:
> On 05/11/2016 01:30 PM, Andre Przywara wrote:
>> Hi,
>>
>> On 10/05/16 15:10, Eric Auger wrote:
>>> On 05/06/2016 12:45 PM, Andre Przywara wrote:
>>>> From: Marc Zyngier <marc.zyngier at arm.com>
>>>>
>>>> Processing maintenance interrupts and accessing the list registers
>>>> are dependent on the host's GIC version.
>>>> Introduce vgic-v2.c to contain GICv2 specific functions.
>>>> Implement the GICv2 specific code for syncing the emulation state
>>>> into the VGIC registers.
>>>>
>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>> ---
>>>> Changelog RFC..v1:
>>>> - remove explicit LR_STATE clearing on maintenance interrupt handling
>>>> - improve documentation for vgic_v2_populate_lr()
>>>> - remove WARN_ON on non-edge IRQs in maintenance interrupts
>>>> - simplify multi-CPU source SGI handling
>>>>
>>>> Changelog v1 .. v2:
>>>> - inject the IRQ priority into the list register
>>>>
>>>> Changelog v2 .. v3:
>>>> - cleanup diff containing rebase artifacts
>>>>
>>>>  include/linux/irqchip/arm-gic.h |   1 +
>>>>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
>>>>  virt/kvm/arm/vgic/vgic.c        |   6 ++
>>>>  virt/kvm/arm/vgic/vgic.h        |   6 ++
>>>>  4 files changed, 191 insertions(+)
>>>>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
>>>>
>>>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>>>> index 9c94026..be0d26f 100644
>>>> --- a/include/linux/irqchip/arm-gic.h
>>>> +++ b/include/linux/irqchip/arm-gic.h
>>>> @@ -76,6 +76,7 @@
>>>>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
>>>>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
>>>>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
>>>> +#define GICH_LR_PRIORITY_SHIFT		23
>>>>  #define GICH_LR_STATE			(3 << 28)
>>>>  #define GICH_LR_PENDING_BIT		(1 << 28)
>>>>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
>>>> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
>>>> new file mode 100644
>>>> index 0000000..4cee616
>>>> --- /dev/null
>>>> +++ b/virt/kvm/arm/vgic/vgic-v2.c
>>>> @@ -0,0 +1,178 @@
>>>> +/*
>>>> + * Copyright (C) 2015, 2016 ARM 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.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * 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/irqchip/arm-gic.h>
>>>> +#include <linux/kvm.h>
>>>> +#include <linux/kvm_host.h>
>>>> +
>>>> +#include "vgic.h"
>>>> +
>>>> +/*
>>>> + * Call this function to convert a u64 value to an unsigned long * bitmask
>>>> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
>>>> + *
>>>> + * Warning: Calling this function may modify *val.
>>>> + */
>>>> +static unsigned long *u64_to_bitmask(u64 *val)
>>>> +{
>>>> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
>>>> +	*val = (*val >> 32) | (*val << 32);
>>>> +#endif
>>>> +	return (unsigned long *)val;
>>>> +}
>>>> +
>>>> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
>>>> +{
>>>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>>>> +
>>>> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
>>>> +		u64 eisr = cpuif->vgic_eisr;
>>>> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
>>>> +		int lr;
>>>> +
>>>> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
>>> Didn't we say we could use vcpu->arch.vgic_cpu.used_lrs here?
>>
>> Why would that be useful? Don't we just want to see those LRs that had a
>> maintenance interrupt received? I don't see the point if iterating over
>> the used LRs, where we need to check for this condition somehow manually?
>> Or what am I missing here?
> 
> Well I thought that there is no use inspecting bits corresponding to
> unused LRs, no?

Mmh, maybe I got something wrong here, but this bitmap is supposedly
having only one bit set most of the time, also it points us to every LR
that we need to take care of. So it will never set bits for unused LRs.
By iterating over every used LR on the other hand we would touch LRs
that don't need servicing in this function, also the WARN_ON had to go
then (as we may touch EOIed IRQs).

Do you agree?

Cheers,
Andre.

> 
> Cheers
> 
> Eric
>>
>>>> +			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
>>>> +
>>>> +			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
>>>> +
>>>> +			kvm_notify_acked_irq(vcpu->kvm, 0,
>>>> +					     intid - VGIC_NR_PRIVATE_IRQS);
>>>> +
>>>> +			cpuif->vgic_elrsr |= 1ULL << lr;
>>
>> So are we good with removing this line (and the respective one in v3)?
>>
>> Cheers,
>> Andre.
>>
>>>> +		}
>>>> +	}
>>>> +
>>>> +	/* check and disable underflow maintenance IRQ */
>>> check?
>>>
>>> Besides
>>> Reviewed-by: Eric Auger <eric.auger at linaro.org>
>>>
>>> Eric
>>>> +	cpuif->vgic_hcr &= ~GICH_HCR_UIE;
>>>> +
>>>> +	/*
>>>> +	 * In the next iterations of the vcpu loop, if we sync the
>>>> +	 * vgic state after flushing it, but before entering the guest
>>>> +	 * (this happens for pending signals and vmid rollovers), then
>>>> +	 * make sure we don't pick up any old maintenance interrupts
>>>> +	 * here.
>>>> +	 */
>>>> +	cpuif->vgic_eisr = 0;
>>>> +}
>>>> +
>>>> +void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
>>>> +{
>>>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>>>> +
>>>> +	cpuif->vgic_hcr |= GICH_HCR_UIE;
>>>> +}
>>>> +
>>>> +/*
>>>> + * transfer the content of the LRs back into the corresponding ap_list:
>>>> + * - active bit is transferred as is
>>>> + * - pending bit is
>>>> + *   - transferred as is in case of edge sensitive IRQs
>>>> + *   - set to the line-level (resample time) for level sensitive IRQs
>>>> + */
>>>> +void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
>>>> +{
>>>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>>>> +	int lr;
>>>> +
>>>> +	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
>>>> +		u32 val = cpuif->vgic_lr[lr];
>>>> +		u32 intid = val & GICH_LR_VIRTUALID;
>>>> +		struct vgic_irq *irq;
>>>> +
>>>> +		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
>>>> +
>>>> +		spin_lock(&irq->irq_lock);
>>>> +
>>>> +		/* Always preserve the active bit */
>>>> +		irq->active = !!(val & GICH_LR_ACTIVE_BIT);
>>>> +
>>>> +		/* Edge is the only case where we preserve the pending bit */
>>>> +		if (irq->config == VGIC_CONFIG_EDGE &&
>>>> +		    (val & GICH_LR_PENDING_BIT)) {
>>>> +			irq->pending = true;
>>>> +
>>>> +			if (vgic_irq_is_sgi(intid)) {
>>>> +				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
>>>> +
>>>> +				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
>>>> +				irq->source |= (1 << cpuid);
>>>> +			}
>>>> +		}
>>>> +
>>>> +		/* Clear soft pending state when level IRQs have been acked */
>>>> +		if (irq->config == VGIC_CONFIG_LEVEL &&
>>>> +		    !(val & GICH_LR_PENDING_BIT)) {
>>>> +			irq->soft_pending = false;
>>>> +			irq->pending = irq->line_level;
>>>> +		}
>>>> +
>>>> +		spin_unlock(&irq->irq_lock);
>>>> +	}
>>>> +}
>>>> +
>>>> +/*
>>>> + * Populates the particular LR with the state of a given IRQ:
>>>> + * - for an edge sensitive IRQ the pending state is cleared in struct vgic_irq
>>>> + * - for a level sensitive IRQ the pending state value is unchanged;
>>>> + *   it is dictated directly by the input level
>>>> + *
>>>> + * If @irq describes an SGI with multiple sources, we choose the
>>>> + * lowest-numbered source VCPU and clear that bit in the source bitmap.
>>>> + *
>>>> + * The irq_lock must be held by the caller.
>>>> + */
>>>> +void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
>>>> +{
>>>> +	u32 val = irq->intid;
>>>> +
>>>> +	if (irq->pending) {
>>>> +		val |= GICH_LR_PENDING_BIT;
>>>> +
>>>> +		if (irq->config == VGIC_CONFIG_EDGE)
>>>> +			irq->pending = false;
>>>> +
>>>> +		if (vgic_irq_is_sgi(irq->intid)) {
>>>> +			u32 src = ffs(irq->source);
>>>> +
>>>> +			BUG_ON(!src);
>>>> +			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
>>>> +			irq->source &= ~(1 << (src - 1));
>>>> +			if (irq->source)
>>>> +				irq->pending = true;
>>>> +		}
>>>> +	}
>>>> +
>>>> +	if (irq->active)
>>>> +		val |= GICH_LR_ACTIVE_BIT;
>>>> +
>>>> +	if (irq->hw) {
>>>> +		val |= GICH_LR_HW;
>>>> +		val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
>>>> +	} else {
>>>> +		if (irq->config == VGIC_CONFIG_LEVEL)
>>>> +			val |= GICH_LR_EOI;
>>>> +	}
>>>> +
>>>> +	/* The GICv2 LR only holds five bits of priority. */
>>>> +	val |= (irq->priority >> 3) << GICH_LR_PRIORITY_SHIFT;
>>>> +
>>>> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = val;
>>>> +}
>>>> +
>>>> +void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
>>>> +{
>>>> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
>>>> +}
>>>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>>>> index c6f8b9b..68d885c 100644
>>>> --- a/virt/kvm/arm/vgic/vgic.c
>>>> +++ b/virt/kvm/arm/vgic/vgic.c
>>>> @@ -397,10 +397,12 @@ retry:
>>>>  
>>>>  static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
>>>>  {
>>>> +	vgic_v2_process_maintenance(vcpu);
>>>>  }
>>>>  
>>>>  static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
>>>>  {
>>>> +	vgic_v2_fold_lr_state(vcpu);
>>>>  }
>>>>  
>>>>  /* Requires the ap_list_lock and the irq_lock to be held. */
>>>> @@ -409,14 +411,18 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
>>>>  {
>>>>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vcpu->arch.vgic_cpu.ap_list_lock));
>>>>  	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
>>>> +
>>>> +	vgic_v2_populate_lr(vcpu, irq, lr);
>>>>  }
>>>>  
>>>>  static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
>>>>  {
>>>> +	vgic_v2_clear_lr(vcpu, lr);
>>>>  }
>>>>  
>>>>  static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
>>>>  {
>>>> +	vgic_v2_set_underflow(vcpu);
>>>>  }
>>>>  
>>>>  static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
>>>> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>>>> index 29b96b9..0db490e 100644
>>>> --- a/virt/kvm/arm/vgic/vgic.h
>>>> +++ b/virt/kvm/arm/vgic/vgic.h
>>>> @@ -22,4 +22,10 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>>>>  			      u32 intid);
>>>>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
>>>>  
>>>> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
>>>> +void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
>>>> +void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
>>>> +void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
>>>> +void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
>>>> +
>>>>  #endif
>>>>
>>>
> 


From dannenberg at ti.com  Wed May 11 06:09:13 2016
From: dannenberg at ti.com (Andreas Dannenberg)
Date: Wed, 11 May 2016 08:09:13 -0500
Subject: [PATCH 2/2] ARM: dts: dra7: Add ti,secure-ram node to ocmcram1
 node
In-Reply-To: <1462909782-14639-3-git-send-email-d-gerlach@ti.com>
References: <1462909782-14639-1-git-send-email-d-gerlach@ti.com>
 <1462909782-14639-3-git-send-email-d-gerlach@ti.com>
Message-ID: <20160511130913.GS20461@borg.dal.design.ti.com>

On Tue, May 10, 2016 at 02:49:42PM -0500, Dave Gerlach wrote:
> Secure variants of DRA7xx and AM57xx SoCs may need to reserve a region
> of the SRAM for use by secure software. To account for this, add a child
> node to the ocmcram1 node that will act as a placeholder at the start
> of the SRAM for the reserved region of memory that may be required
> by secure services. The node is added with size 0 so that by default
> parts will have the full space available but the bootloader or board dts
> file is able to resize the node as needed depending on how much reserved
> space is needed, if any, so end users of the ocmcram1 region on HS parts
> must be aware that a smaller amount of SRAM than expected may be available.
> 
> Signed-off-by: Dave Gerlach <d-gerlach at ti.com>

Reviewed-by: Andreas Dannenberg <dannenberg at ti.com>

--
Andreas Dannenberg
Texas Instruments Inc


From christoffer.dall at linaro.org  Wed May 11 06:11:06 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:11:06 +0200
Subject: [PATCH v3 25/55] KVM: arm/arm64: vgic-new: Add PENDING registers
 handlers
In-Reply-To: <1462531568-9799-26-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-26-git-send-email-andre.przywara@arm.com>
Message-ID: <20160511131106.GP27623@cbox>

On Fri, May 06, 2016 at 11:45:38AM +0100, Andre Przywara wrote:
> The pending register handlers are shared between the v2 and v3
> emulation, so their implementation goes into vgic-mmio.c, to be easily
> referenced from the v3 emulation as well later.
> For level triggered interrupts the real line level is unaffected by
> this write, so we keep this state separate and combine it with the
> device's level to get the actual pending state.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - remove IRQ lock from read handler
> - remove TODO from clear pending handler
> 
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
>  virt/kvm/arm/vgic/vgic-mmio.c    | 60 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h    | 12 ++++++++
>  3 files changed, 74 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 448d1da..4b87e0a 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -76,9 +76,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
>  		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index 077ae86..4df1af7 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -102,6 +102,66 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
> +				     gpa_t addr, unsigned int len)
> +{
> +	u32 intid = (addr & 0x7f) * 8;
> +	u32 value = 0;
> +	int i;
> +
> +	/* Loop over all IRQs affected by this read */
> +	for (i = 0; i < len * 8; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		if (irq->pending)
> +			value |= (1U << i);

same question as on the previous patch

> +	}
> +
> +	return extract_bytes(value, addr & 3, len);
> +}
> +
> +void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
> +			      gpa_t addr, unsigned int len,
> +			      unsigned long val)
> +{
> +	u32 intid = (addr & 0x7f) * 8;
> +	int i;
> +
> +	for_each_set_bit(i, &val, len * 8) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +		irq->pending = true;
> +		if (irq->config == VGIC_CONFIG_LEVEL)
> +			irq->soft_pending = true;
> +
> +		vgic_queue_irq_unlock(vcpu->kvm, irq);
> +	}
> +}
> +
> +void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
> +			      gpa_t addr, unsigned int len,
> +			      unsigned long val)
> +{
> +	u32 intid = (addr & 0x7f) * 8;
> +	int i;
> +
> +	for_each_set_bit(i, &val, len * 8) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		if (irq->config == VGIC_CONFIG_LEVEL) {
> +			irq->soft_pending = false;
> +			irq->pending = irq->line_level;
> +		} else {
> +			irq->pending = false;
> +		}
> +
> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
>  static int match_region(const void *key, const void *elt)
>  {
>  	const unsigned int offset = (unsigned long)key;
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index 188909a..d4fc029 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -85,6 +85,18 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
>  			     gpa_t addr, unsigned int len,
>  			     unsigned long val);
>  
> +unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
> +				     gpa_t addr, unsigned int len);
> +
> +void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
> +			      gpa_t addr, unsigned int len,
> +			      unsigned long val);
> +
> +void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
> +			      gpa_t addr, unsigned int len,
> +			      unsigned long val);
> +
> +
>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>  
>  #endif
> -- 
> 2.7.3
> 

Otherwise this looks good.

Thanks,
-Christoffer


From christoffer.dall at linaro.org  Wed May 11 06:14:02 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:14:02 +0200
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <57332DCD.1020701@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
 <20160511123423.GO27623@cbox> <57332DCD.1020701@arm.com>
Message-ID: <20160511131402.GQ27623@cbox>

On Wed, May 11, 2016 at 02:04:13PM +0100, Andre Przywara wrote:
> Hi,
> 
> On 11/05/16 13:34, Christoffer Dall wrote:
> > On Fri, May 06, 2016 at 11:45:37AM +0100, Andre Przywara wrote:
> >> As the enable register handlers are shared between the v2 and v3
> >> emulation, their implementation goes into vgic-mmio.c, to be easily
> >> referenced from the v3 emulation as well later.
> >>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >> Changelog RFC..v1:
> >> - use lower bits of address to determine IRQ number
> >> - remove TODO, confirmed to be fine
> >>
> >> Changelog v1 .. v2:
> >> - adapt to new MMIO framework
> >>
> >>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
> >>  virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
> >>  virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
> >>  3 files changed, 69 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> index 69e96f7..448d1da 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> @@ -72,9 +72,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
> >>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
> >> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
> >> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
> >>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> >> index 41cf4f4..077ae86 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> >> @@ -46,6 +46,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> >>  	/* Ignore */
> >>  }
> >>  
> >> +/*
> >> + * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
> >> + * of the enabled bit, so there is only one function for both here.
> >> + */
> >> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
> >> +				    gpa_t addr, unsigned int len)
> >> +{
> >> +	u32 intid = (addr & 0x7f) * 8;
> > 
> > is there anything we can do about this to make it more intuitive?  A
> > macro to generate the mask/offset based on bits per interrupt or
> > something?
> 
> Yes, something where you give it the address and the bits-per-IRQ and it
> tells you the IRQ number.
> Not sure it is advisable to squash this into v4 still?
> 
> > 
> >> +	u32 value = 0;
> >> +	int i;
> >> +
> >> +	/* Loop over all IRQs affected by this read */
> >> +	for (i = 0; i < len * 8; i++) {
> >> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> >> +
> >> +		if (irq->enabled)
> >> +			value |= (1U << i);
> > 
> > I couldn't find the code anywhere that enforces word-aligned accesses to
> > these registers.  Do we have that?
> 
> Not that I am aware of. I was suggesting this since we have one in the
> IROUTER function. Architecturally we don't need to support halfword
> accesses, it's: byte + word, word only or double-word + word, depending
> on the actual register, IIRC.
> As a fix we can at least deny (read: ignore) halfword accesses in
> general in the dispatcher. Shall I do this (two two-liners)?
> I think byte and word accesses are safe with the existing handlers last
> time I checked.
> 
> > If that's not the case, doesn't this break of you do a non-word aligned
> > access?
> 
> Why would it? vgic_data_host_to_mmio_bus and extract_bytes should cover
> this, shouldn't they?
> 

I think this breaks on a simple byte access.  Let's say you are
accessing byte 1 (addr & 0x7ff == 1), then because you start your loop
at 0, you're going to set bits [7:0] in the value variable, and then
extract bits [15:8] in extract_bytes(), right?

-Christoffer


From andre.przywara at arm.com  Wed May 11 06:13:55 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 14:13:55 +0100
Subject: [PATCH v3 18/55] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <20160511122648.GN27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-19-git-send-email-andre.przywara@arm.com>
 <5731EBBE.7060203@linaro.org> <573317DC.4060200@arm.com>
 <20160511122648.GN27623@cbox>
Message-ID: <57333013.6090301@arm.com>

Hej,

On 11/05/16 13:26, Christoffer Dall wrote:
> On Wed, May 11, 2016 at 12:30:36PM +0100, Andre Przywara wrote:
>> Hi,
>>
>> On 10/05/16 15:10, Eric Auger wrote:
>>> On 05/06/2016 12:45 PM, Andre Przywara wrote:
>>>> From: Marc Zyngier <marc.zyngier at arm.com>
>>>>
>>>> Processing maintenance interrupts and accessing the list registers
>>>> are dependent on the host's GIC version.
>>>> Introduce vgic-v2.c to contain GICv2 specific functions.
>>>> Implement the GICv2 specific code for syncing the emulation state
>>>> into the VGIC registers.
>>>>
>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>> ---
>>>> Changelog RFC..v1:
>>>> - remove explicit LR_STATE clearing on maintenance interrupt handling
>>>> - improve documentation for vgic_v2_populate_lr()
>>>> - remove WARN_ON on non-edge IRQs in maintenance interrupts
>>>> - simplify multi-CPU source SGI handling
>>>>
>>>> Changelog v1 .. v2:
>>>> - inject the IRQ priority into the list register
>>>>
>>>> Changelog v2 .. v3:
>>>> - cleanup diff containing rebase artifacts
>>>>
>>>>  include/linux/irqchip/arm-gic.h |   1 +
>>>>  virt/kvm/arm/vgic/vgic-v2.c     | 178 ++++++++++++++++++++++++++++++++++++++++
>>>>  virt/kvm/arm/vgic/vgic.c        |   6 ++
>>>>  virt/kvm/arm/vgic/vgic.h        |   6 ++
>>>>  4 files changed, 191 insertions(+)
>>>>  create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
>>>>
>>>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>>>> index 9c94026..be0d26f 100644
>>>> --- a/include/linux/irqchip/arm-gic.h
>>>> +++ b/include/linux/irqchip/arm-gic.h
>>>> @@ -76,6 +76,7 @@
>>>>  #define GICH_LR_VIRTUALID		(0x3ff << 0)
>>>>  #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
>>>>  #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
>>>> +#define GICH_LR_PRIORITY_SHIFT		23
>>>>  #define GICH_LR_STATE			(3 << 28)
>>>>  #define GICH_LR_PENDING_BIT		(1 << 28)
>>>>  #define GICH_LR_ACTIVE_BIT		(1 << 29)
>>>> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
>>>> new file mode 100644
>>>> index 0000000..4cee616
>>>> --- /dev/null
>>>> +++ b/virt/kvm/arm/vgic/vgic-v2.c
>>>> @@ -0,0 +1,178 @@
>>>> +/*
>>>> + * Copyright (C) 2015, 2016 ARM 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.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * 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/irqchip/arm-gic.h>
>>>> +#include <linux/kvm.h>
>>>> +#include <linux/kvm_host.h>
>>>> +
>>>> +#include "vgic.h"
>>>> +
>>>> +/*
>>>> + * Call this function to convert a u64 value to an unsigned long * bitmask
>>>> + * in a way that works on both 32-bit and 64-bit LE and BE platforms.
>>>> + *
>>>> + * Warning: Calling this function may modify *val.
>>>> + */
>>>> +static unsigned long *u64_to_bitmask(u64 *val)
>>>> +{
>>>> +#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
>>>> +	*val = (*val >> 32) | (*val << 32);
>>>> +#endif
>>>> +	return (unsigned long *)val;
>>>> +}
>>>> +
>>>> +void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
>>>> +{
>>>> +	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
>>>> +
>>>> +	if (cpuif->vgic_misr & GICH_MISR_EOI) {
>>>> +		u64 eisr = cpuif->vgic_eisr;
>>>> +		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
>>>> +		int lr;
>>>> +
>>>> +		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
>>> Didn't we say we could use vcpu->arch.vgic_cpu.used_lrs here?
>>
>> Why would that be useful? Don't we just want to see those LRs that had a
>> maintenance interrupt received? I don't see the point if iterating over
>> the used LRs, where we need to check for this condition somehow manually?
>> Or what am I missing here?
> 
> if we get rid of eisr eventually we can optimize the reading of that
> away, but I honestly don't think we should be pursuing this straight
> away.

Yes, I realized that too when I tried to change the code. But then we
would need to somehow check for that condition anyway? Whereas right now
the hardware points us exactly to the LRs that need servicing?

Or am I confused about the meaning of the EISR bitmap?

And I agree that this possible optimization is something we should keep
for later. I guess we get plenty of opportunity once we remove the old VGIC.

Cheers,
Andre.


From marc.zyngier at arm.com  Wed May 11 06:13:48 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 11 May 2016 14:13:48 +0100
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <20160511123423.GO27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
 <20160511123423.GO27623@cbox>
Message-ID: <5733300C.9070304@arm.com>

On 11/05/16 13:34, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:37AM +0100, Andre Przywara wrote:
>> As the enable register handlers are shared between the v2 and v3
>> emulation, their implementation goes into vgic-mmio.c, to be easily
>> referenced from the v3 emulation as well later.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - use lower bits of address to determine IRQ number
>> - remove TODO, confirmed to be fine
>>
>> Changelog v1 .. v2:
>> - adapt to new MMIO framework
>>
>>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
>>  virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
>>  3 files changed, 69 insertions(+), 2 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> index 69e96f7..448d1da 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> @@ -72,9 +72,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
>>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
>>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
>> index 41cf4f4..077ae86 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>> @@ -46,6 +46,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
>>  	/* Ignore */
>>  }
>>  
>> +/*
>> + * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
>> + * of the enabled bit, so there is only one function for both here.
>> + */
>> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
>> +				    gpa_t addr, unsigned int len)
>> +{
>> +	u32 intid = (addr & 0x7f) * 8;
> 
> is there anything we can do about this to make it more intuitive?  A
> macro to generate the mask/offset based on bits per interrupt or
> something?

Untested (and thus probably wrong):

#define VGIC_ADDR_IRQ_MASK(bits) ((1024 - 1) >> (4 - (bits))
#define VGIC_ADDR_IRQ_MULT(bits) (8 / (bits))
#define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
					 VGIC_ADDR_IRQ_MULT(bits))

	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From maxime.ripard at free-electrons.com  Wed May 11 06:14:57 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 11 May 2016 15:14:57 +0200
Subject: [PATCH 1/1] devicetree: sunxi: Add OLinuXino Lime2 eMMC to the
 Makefile
In-Reply-To: <1462955227-4454-1-git-send-email-oliver@schinagl.nl>
References: <1462955227-4454-1-git-send-email-oliver@schinagl.nl>
Message-ID: <20160511131457.GS3733@lukather>

Hi Olliver

On Wed, May 11, 2016 at 10:27:07AM +0200, Olliver Schinagl wrote:
> ARM: dts: sunxi: Add a olinuxino-lime2-emmc

This is not the proper commit reference format.

> added the new emmc equipped lime2 but forgot its Makefile. This
> patch adds an entry to the Makefile.
> 
> Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>

Once fixed,
Acked-by: Maxime Ripard <maxime.ripard at free-electrons.com>

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160511/a8a691e5/attachment.sig>

From niklas.soderlund+renesas at ragnatech.se  Wed May 11 06:13:54 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Wed, 11 May 2016 15:13:54 +0200
Subject: [PATCHv3 0/4] ARM: dts: r8a779[0-4]: Reference both DMA controllers
Message-ID: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>

Hi,

R-Car Gen2 have two DMA controllers, which are equivalent. However DMA
slaves were tied only to a single DMA controller in .dtsi. This series
add references to to both DMA controllers for all nodes that previously
only referenced one of them. It also adds dma references to the SDHI
nodes for r8a7794 which according to the datasheet should work but I
have not access to HW to verify.

Tested on Koelsch (r8a7791) by altering the compatible value of either
dmac0 or dmac1 and verifying that the DMA slaves pick the DMA controller
that is available.

* Changes since v2
- Squash a rather large series to one patch per SoC
- Rebase on top of renesas-devel-20160509-v4.6-rc7
- Always reference dmac0 before dmac1

* Changes since v1
- Rebase on top of renesas-devel-20160315-v4.5 and add dmas references
  new nodes (r8a7790: scif2 r8a7793: i2c6,i2c7,i2c8).
- Correct error in commit message 31/31 (s/QSPI/MMCIF).
- Collect Ack and Reviewed tags from Geert.


Niklas S?derlund (4):
  ARM: dts: r8a7790: Reference both DMA controllers
  ARM: dts: r8a7791: Reference both DMA controllers
  ARM: dts: r8a7793: Reference both DMA controllers
  ARM: dts: r8a7794: Reference both DMA controllers

 arch/arm/boot/dts/r8a7790.dtsi | 131 ++++++++++++++++++++++---------------
 arch/arm/boot/dts/r8a7791.dtsi | 145 ++++++++++++++++++++++++-----------------
 arch/arm/boot/dts/r8a7793.dtsi | 130 +++++++++++++++++++++---------------
 arch/arm/boot/dts/r8a7794.dtsi | 119 ++++++++++++++++++++-------------
 4 files changed, 318 insertions(+), 207 deletions(-)

--
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Wed May 11 06:13:57 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Wed, 11 May 2016 15:13:57 +0200
Subject: [PATCHv3 3/4] ARM: dts: r8a7793: Reference both DMA controllers
In-Reply-To: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462972438-20797-4-git-send-email-niklas.soderlund+renesas@ragnatech.se>

R-Car Gen2 have two DMA controllers, which are equivalent. Add
references to both dmac0 and dmac1 so the driver can choose which one to
use.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
---
 arch/arm/boot/dts/r8a7793.dtsi | 130 ++++++++++++++++++++++++-----------------
 1 file changed, 78 insertions(+), 52 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi
index 76c8435..5f50e9b 100644
--- a/arch/arm/boot/dts/r8a7793.dtsi
+++ b/arch/arm/boot/dts/r8a7793.dtsi
@@ -473,8 +473,9 @@
 		reg = <0 0xe60b0000 0 0x425>;
 		interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7793_CLK_IICDVFS>;
-		dmas = <&dmac0 0x77>, <&dmac0 0x78>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x77>, <&dmac0 0x78>,
+		       <&dmac1 0x77>, <&dmac1 0x78>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -486,8 +487,9 @@
 		reg = <0 0xe6500000 0 0x425>;
 		interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_IIC0>;
-		dmas = <&dmac0 0x61>, <&dmac0 0x62>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x61>, <&dmac0 0x62>,
+		       <&dmac1 0x61>, <&dmac1 0x62>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -499,8 +501,9 @@
 		reg = <0 0xe6510000 0 0x425>;
 		interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_IIC1>;
-		dmas = <&dmac0 0x65>, <&dmac0 0x66>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x65>, <&dmac0 0x66>,
+		       <&dmac1 0x65>, <&dmac1 0x66>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -515,8 +518,9 @@
 		reg = <0 0xee100000 0 0x328>;
 		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_SDHI0>;
-		dmas = <&dmac0 0xcd>, <&dmac0 0xce>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xcd>, <&dmac0 0xce>,
+		       <&dmac1 0xcd>, <&dmac1 0xce>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -526,8 +530,9 @@
 		reg = <0 0xee140000 0 0x100>;
 		interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_SDHI1>;
-		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>,
+		       <&dmac1 0xc1>, <&dmac1 0xc2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -537,8 +542,9 @@
 		reg = <0 0xee160000 0 0x100>;
 		interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_SDHI2>;
-		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>,
+		       <&dmac1 0xd3>, <&dmac1 0xd4>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -548,8 +554,9 @@
 		reg = <0 0xee200000 0 0x80>;
 		interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_MMCIF0>;
-		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>,
+		       <&dmac1 0xd1>, <&dmac1 0xd2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
@@ -563,8 +570,9 @@
 		interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFA0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x21>, <&dmac0 0x22>,
+		       <&dmac1 0x21>, <&dmac1 0x22>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -576,8 +584,9 @@
 		interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFA1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x25>, <&dmac0 0x26>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x25>, <&dmac0 0x26>,
+		       <&dmac1 0x25>, <&dmac1 0x26>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -589,8 +598,9 @@
 		interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFA2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x27>, <&dmac0 0x28>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x27>, <&dmac0 0x28>,
+		       <&dmac1 0x27>, <&dmac1 0x28>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -602,8 +612,9 @@
 		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7793_CLK_SCIFA3>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>,
+		       <&dmac1 0x1b>, <&dmac1 0x1c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -615,8 +626,9 @@
 		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7793_CLK_SCIFA4>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1f>, <&dmac0 0x20>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1f>, <&dmac0 0x20>,
+		       <&dmac1 0x1f>, <&dmac1 0x20>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -628,8 +640,9 @@
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7793_CLK_SCIFA5>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x23>, <&dmac0 0x24>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x23>, <&dmac0 0x24>,
+		       <&dmac1 0x23>, <&dmac1 0x24>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -641,8 +654,9 @@
 		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFB0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
+		       <&dmac1 0x3d>, <&dmac1 0x3e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -654,8 +668,9 @@
 		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFB1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x19>, <&dmac0 0x1a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x19>, <&dmac0 0x1a>,
+		       <&dmac1 0x19>, <&dmac1 0x1a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -667,8 +682,9 @@
 		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFB2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>,
+		       <&dmac1 0x1d>, <&dmac1 0x1e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -681,8 +697,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_SCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x29>, <&dmac0 0x2a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+		       <&dmac1 0x29>, <&dmac1 0x2a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -695,8 +712,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_SCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+		       <&dmac1 0x2d>, <&dmac1 0x2e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -709,8 +727,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_SCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+		       <&dmac1 0x2b>, <&dmac1 0x2c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -723,8 +742,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_SCIF3>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2f>, <&dmac0 0x30>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
+		       <&dmac1 0x2f>, <&dmac1 0x30>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -737,8 +757,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_SCIF4>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>,
+		       <&dmac1 0xfb>, <&dmac1 0xfc>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -751,8 +772,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_SCIF5>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>,
+		       <&dmac1 0xfd>, <&dmac1 0xfe>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -765,8 +787,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_HSCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x39>, <&dmac0 0x3a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+		       <&dmac1 0x39>, <&dmac1 0x3a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -779,8 +802,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_HSCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+		       <&dmac1 0x4d>, <&dmac1 0x4e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -793,8 +817,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_HSCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>,
+		       <&dmac1 0x3b>, <&dmac1 0x3c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -816,8 +841,9 @@
 		reg = <0 0xe6b10000 0 0x2c>;
 		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7793_CLK_QSPI_MOD>;
-		dmas = <&dmac0 0x17>, <&dmac0 0x18>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x17>, <&dmac0 0x18>,
+		       <&dmac1 0x17>, <&dmac1 0x18>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		num-cs = <1>;
 		#address-cells = <1>;
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Wed May 11 06:13:58 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Wed, 11 May 2016 15:13:58 +0200
Subject: [PATCHv3 4/4] ARM: dts: r8a7794: Reference both DMA controllers
In-Reply-To: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462972438-20797-5-git-send-email-niklas.soderlund+renesas@ragnatech.se>

R-Car Gen2 have two DMA controllers, which are equivalent. Add
references to both dmac0 and dmac1 so the driver can choose which one to
use.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
---
 arch/arm/boot/dts/r8a7794.dtsi | 119 ++++++++++++++++++++++++++---------------
 1 file changed, 75 insertions(+), 44 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi
index f334a3a..ad1df83 100644
--- a/arch/arm/boot/dts/r8a7794.dtsi
+++ b/arch/arm/boot/dts/r8a7794.dtsi
@@ -302,8 +302,9 @@
 		interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFA0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x21>, <&dmac0 0x22>,
+		       <&dmac1 0x21>, <&dmac1 0x22>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -315,8 +316,9 @@
 		interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFA1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x25>, <&dmac0 0x26>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x25>, <&dmac0 0x26>,
+		       <&dmac1 0x25>, <&dmac1 0x26>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -328,8 +330,9 @@
 		interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFA2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x27>, <&dmac0 0x28>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x27>, <&dmac0 0x28>,
+		       <&dmac1 0x27>, <&dmac1 0x28>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -341,8 +344,9 @@
 		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7794_CLK_SCIFA3>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>,
+		       <&dmac1 0x1b>, <&dmac1 0x1c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -354,8 +358,9 @@
 		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7794_CLK_SCIFA4>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1f>, <&dmac0 0x20>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1f>, <&dmac0 0x20>,
+		       <&dmac1 0x1f>, <&dmac1 0x20>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -367,8 +372,9 @@
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7794_CLK_SCIFA5>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x23>, <&dmac0 0x24>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x23>, <&dmac0 0x24>,
+		       <&dmac1 0x23>, <&dmac1 0x24>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -380,8 +386,9 @@
 		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFB0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
+		       <&dmac1 0x3d>, <&dmac1 0x3e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -393,8 +400,9 @@
 		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFB1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x19>, <&dmac0 0x1a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x19>, <&dmac0 0x1a>,
+		       <&dmac1 0x19>, <&dmac1 0x1a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -406,8 +414,9 @@
 		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFB2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>,
+		       <&dmac1 0x1d>, <&dmac1 0x1e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -420,8 +429,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_SCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x29>, <&dmac0 0x2a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+		       <&dmac1 0x29>, <&dmac1 0x2a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -434,8 +444,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_SCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+		       <&dmac1 0x2d>, <&dmac1 0x2e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -448,8 +459,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_SCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+		       <&dmac1 0x2b>, <&dmac1 0x2c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -462,8 +474,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_SCIF3>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2f>, <&dmac0 0x30>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
+		       <&dmac1 0x2f>, <&dmac1 0x30>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -476,8 +489,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_SCIF4>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>,
+		       <&dmac1 0xfb>, <&dmac1 0xfc>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -490,8 +504,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_SCIF5>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>,
+		       <&dmac1 0xfd>, <&dmac1 0xfe>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -504,8 +519,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_HSCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x39>, <&dmac0 0x3a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+		       <&dmac1 0x39>, <&dmac1 0x3a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -518,8 +534,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_HSCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+		       <&dmac1 0x4d>, <&dmac1 0x4e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -532,8 +549,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_HSCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>,
+		       <&dmac1 0x3b>, <&dmac1 0x3c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -640,8 +658,9 @@
 		reg = <0 0xe6500000 0 0x425>;
 		interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_IIC0>;
-		dmas = <&dmac0 0x61>, <&dmac0 0x62>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x61>, <&dmac0 0x62>,
+		       <&dmac1 0x61>, <&dmac1 0x62>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -653,8 +672,9 @@
 		reg = <0 0xe6510000 0 0x425>;
 		interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_IIC1>;
-		dmas = <&dmac0 0x65>, <&dmac0 0x66>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x65>, <&dmac0 0x66>,
+		       <&dmac1 0x65>, <&dmac1 0x66>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -666,8 +686,9 @@
 		reg = <0 0xee200000 0 0x80>;
 		interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_MMCIF0>;
-		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>,
+		       <&dmac1 0xd1>, <&dmac1 0xd2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
@@ -678,6 +699,9 @@
 		reg = <0 0xee100000 0 0x200>;
 		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_SDHI0>;
+		dmas = <&dmac0 0xcd>, <&dmac0 0xce>,
+		       <&dmac1 0xcd>, <&dmac1 0xce>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -687,6 +711,9 @@
 		reg = <0 0xee140000 0 0x100>;
 		interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_SDHI1>;
+		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>,
+		       <&dmac1 0xc1>, <&dmac1 0xc2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -696,6 +723,9 @@
 		reg = <0 0xee160000 0 0x100>;
 		interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_SDHI2>;
+		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>,
+		       <&dmac1 0xd3>, <&dmac1 0xd4>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -705,8 +735,9 @@
 		reg = <0 0xe6b10000 0 0x2c>;
 		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7794_CLK_QSPI_MOD>;
-		dmas = <&dmac0 0x17>, <&dmac0 0x18>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x17>, <&dmac0 0x18>,
+		       <&dmac1 0x17>, <&dmac1 0x18>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		num-cs = <1>;
 		#address-cells = <1>;
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Wed May 11 06:13:55 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Wed, 11 May 2016 15:13:55 +0200
Subject: [PATCHv3 1/4] ARM: dts: r8a7790: Reference both DMA controllers
In-Reply-To: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462972438-20797-2-git-send-email-niklas.soderlund+renesas@ragnatech.se>

R-Car Gen2 have two DMA controllers, which are equivalent. Add
references to both dmac0 and dmac1 so the driver can choose which one to
use.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
---
 arch/arm/boot/dts/r8a7790.dtsi | 131 ++++++++++++++++++++++++-----------------
 1 file changed, 78 insertions(+), 53 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 83cf23c..14fcd19 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -517,8 +517,9 @@
 		reg = <0 0xe6500000 0 0x425>;
 		interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_IIC0>;
-		dmas = <&dmac0 0x61>, <&dmac0 0x62>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x61>, <&dmac0 0x62>,
+		       <&dmac1 0x61>, <&dmac1 0x62>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -530,8 +531,9 @@
 		reg = <0 0xe6510000 0 0x425>;
 		interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_IIC1>;
-		dmas = <&dmac0 0x65>, <&dmac0 0x66>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x65>, <&dmac0 0x66>,
+		       <&dmac1 0x65>, <&dmac1 0x66>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -543,8 +545,9 @@
 		reg = <0 0xe6520000 0 0x425>;
 		interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_IIC2>;
-		dmas = <&dmac0 0x69>, <&dmac0 0x6a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x69>, <&dmac0 0x6a>,
+		       <&dmac1 0x69>, <&dmac1 0x6a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -556,8 +559,9 @@
 		reg = <0 0xe60b0000 0 0x425>;
 		interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_IICDVFS>;
-		dmas = <&dmac0 0x77>, <&dmac0 0x78>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x77>, <&dmac0 0x78>,
+		       <&dmac1 0x77>, <&dmac1 0x78>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -567,8 +571,9 @@
 		reg = <0 0xee200000 0 0x80>;
 		interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>;
-		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>,
+		       <&dmac1 0xd1>, <&dmac1 0xd2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
@@ -580,8 +585,9 @@
 		reg = <0 0xee220000 0 0x80>;
 		interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_MMCIF1>;
-		dmas = <&dmac0 0xe1>, <&dmac0 0xe2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xe1>, <&dmac0 0xe2>,
+		       <&dmac1 0xe1>, <&dmac1 0xe2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
@@ -598,8 +604,9 @@
 		reg = <0 0xee100000 0 0x328>;
 		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI0>;
-		dmas = <&dmac1 0xcd>, <&dmac1 0xce>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xcd>, <&dmac0 0xce>,
+		       <&dmac1 0xcd>, <&dmac1 0xce>;
+		dma-names = "tx", "rx", "tx", "rx";
 		max-frequency = <195000000>;
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
@@ -610,8 +617,9 @@
 		reg = <0 0xee120000 0 0x328>;
 		interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI1>;
-		dmas = <&dmac1 0xc9>, <&dmac1 0xca>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xc9>, <&dmac0 0xca>,
+		       <&dmac1 0xc9>, <&dmac1 0xca>;
+		dma-names = "tx", "rx", "tx", "rx";
 		max-frequency = <195000000>;
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
@@ -622,8 +630,9 @@
 		reg = <0 0xee140000 0 0x100>;
 		interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI2>;
-		dmas = <&dmac1 0xc1>, <&dmac1 0xc2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>,
+		       <&dmac1 0xc1>, <&dmac1 0xc2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		max-frequency = <97500000>;
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
@@ -634,8 +643,9 @@
 		reg = <0 0xee160000 0 0x100>;
 		interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI3>;
-		dmas = <&dmac1 0xd3>, <&dmac1 0xd4>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>,
+		       <&dmac1 0xd3>, <&dmac1 0xd4>;
+		dma-names = "tx", "rx", "tx", "rx";
 		max-frequency = <97500000>;
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
@@ -648,8 +658,9 @@
 		interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFA0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x21>, <&dmac0 0x22>,
+		       <&dmac1 0x21>, <&dmac1 0x22>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -661,8 +672,9 @@
 		interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFA1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x25>, <&dmac0 0x26>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x25>, <&dmac0 0x26>,
+		       <&dmac1 0x25>, <&dmac1 0x26>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -674,8 +686,9 @@
 		interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFA2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x27>, <&dmac0 0x28>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x27>, <&dmac0 0x28>,
+		       <&dmac1 0x27>, <&dmac1 0x28>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -687,8 +700,9 @@
 		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFB0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
+		       <&dmac1 0x3d>, <&dmac1 0x3e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -700,8 +714,9 @@
 		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFB1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x19>, <&dmac0 0x1a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x19>, <&dmac0 0x1a>,
+		       <&dmac1 0x19>, <&dmac1 0x1a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -713,8 +728,9 @@
 		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFB2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>,
+		       <&dmac1 0x1d>, <&dmac1 0x1e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -727,8 +743,9 @@
 		clocks = <&mstp7_clks R8A7790_CLK_SCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x29>, <&dmac0 0x2a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+		       <&dmac1 0x29>, <&dmac1 0x2a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -741,8 +758,9 @@
 		clocks = <&mstp7_clks R8A7790_CLK_SCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+		       <&dmac1 0x2d>, <&dmac1 0x2e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -755,9 +773,9 @@
 		clocks = <&mstp3_clks R8A7790_CLK_SCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
-		dma-names = "tx", "rx";
-		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
+		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+		       <&dmac1 0x2b>, <&dmac1 0x2c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		status = "disabled";
 	};
 
@@ -769,8 +787,9 @@
 		clocks = <&mstp7_clks R8A7790_CLK_HSCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x39>, <&dmac0 0x3a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+		       <&dmac1 0x39>, <&dmac1 0x3a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -783,8 +802,9 @@
 		clocks = <&mstp7_clks R8A7790_CLK_HSCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+		       <&dmac1 0x4d>, <&dmac1 0x4e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -1469,8 +1489,9 @@
 		reg = <0 0xe6b10000 0 0x2c>;
 		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_QSPI_MOD>;
-		dmas = <&dmac0 0x17>, <&dmac0 0x18>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x17>, <&dmac0 0x18>,
+		       <&dmac1 0x17>, <&dmac1 0x18>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		num-cs = <1>;
 		#address-cells = <1>;
@@ -1483,8 +1504,9 @@
 		reg = <0 0xe6e20000 0 0x0064>;
 		interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp0_clks R8A7790_CLK_MSIOF0>;
-		dmas = <&dmac0 0x51>, <&dmac0 0x52>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x51>, <&dmac0 0x52>,
+		       <&dmac1 0x51>, <&dmac1 0x52>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -1496,8 +1518,9 @@
 		reg = <0 0xe6e10000 0 0x0064>;
 		interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_MSIOF1>;
-		dmas = <&dmac0 0x55>, <&dmac0 0x56>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x55>, <&dmac0 0x56>,
+		       <&dmac1 0x55>, <&dmac1 0x56>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -1509,8 +1532,9 @@
 		reg = <0 0xe6e00000 0 0x0064>;
 		interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_MSIOF2>;
-		dmas = <&dmac0 0x41>, <&dmac0 0x42>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x41>, <&dmac0 0x42>,
+		       <&dmac1 0x41>, <&dmac1 0x42>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -1522,8 +1546,9 @@
 		reg = <0 0xe6c90000 0 0x0064>;
 		interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_MSIOF3>;
-		dmas = <&dmac0 0x45>, <&dmac0 0x46>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x45>, <&dmac0 0x46>,
+		       <&dmac1 0x45>, <&dmac1 0x46>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Wed May 11 06:13:56 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Wed, 11 May 2016 15:13:56 +0200
Subject: [PATCHv3 2/4] ARM: dts: r8a7791: Reference both DMA controllers
In-Reply-To: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1462972438-20797-3-git-send-email-niklas.soderlund+renesas@ragnatech.se>

R-Car Gen2 have two DMA controllers, which are equivalent. Add
references to both dmac0 and dmac1 so the driver can choose which one to
use.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
---
 arch/arm/boot/dts/r8a7791.dtsi | 145 ++++++++++++++++++++++++-----------------
 1 file changed, 87 insertions(+), 58 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index db67e34..2f92414 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -514,8 +514,9 @@
 		reg = <0 0xe60b0000 0 0x425>;
 		interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7791_CLK_IICDVFS>;
-		dmas = <&dmac0 0x77>, <&dmac0 0x78>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x77>, <&dmac0 0x78>,
+		       <&dmac1 0x77>, <&dmac1 0x78>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -527,8 +528,9 @@
 		reg = <0 0xe6500000 0 0x425>;
 		interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_IIC0>;
-		dmas = <&dmac0 0x61>, <&dmac0 0x62>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x61>, <&dmac0 0x62>,
+		       <&dmac1 0x61>, <&dmac1 0x62>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -540,8 +542,9 @@
 		reg = <0 0xe6510000 0 0x425>;
 		interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_IIC1>;
-		dmas = <&dmac0 0x65>, <&dmac0 0x66>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x65>, <&dmac0 0x66>,
+		       <&dmac1 0x65>, <&dmac1 0x66>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -556,8 +559,9 @@
 		reg = <0 0xee200000 0 0x80>;
 		interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_MMCIF0>;
-		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>,
+		       <&dmac1 0xd1>, <&dmac1 0xd2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
@@ -569,8 +573,9 @@
 		reg = <0 0xee100000 0 0x328>;
 		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_SDHI0>;
-		dmas = <&dmac1 0xcd>, <&dmac1 0xce>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xcd>, <&dmac0 0xce>,
+		       <&dmac1 0xcd>, <&dmac1 0xce>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -580,8 +585,9 @@
 		reg = <0 0xee140000 0 0x100>;
 		interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_SDHI1>;
-		dmas = <&dmac1 0xc1>, <&dmac1 0xc2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>,
+		       <&dmac1 0xc1>, <&dmac1 0xc2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -591,8 +597,9 @@
 		reg = <0 0xee160000 0 0x100>;
 		interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_SDHI2>;
-		dmas = <&dmac1 0xd3>, <&dmac1 0xd4>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>,
+		       <&dmac1 0xd3>, <&dmac1 0xd4>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -604,8 +611,9 @@
 		interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFA0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x21>, <&dmac0 0x22>,
+		       <&dmac1 0x21>, <&dmac1 0x22>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -617,8 +625,9 @@
 		interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFA1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x25>, <&dmac0 0x26>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x25>, <&dmac0 0x26>,
+		       <&dmac1 0x25>, <&dmac1 0x26>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -630,8 +639,9 @@
 		interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFA2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x27>, <&dmac0 0x28>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x27>, <&dmac0 0x28>,
+		       <&dmac1 0x27>, <&dmac1 0x28>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -643,8 +653,9 @@
 		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7791_CLK_SCIFA3>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>,
+		       <&dmac1 0x1b>, <&dmac1 0x1c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -656,8 +667,9 @@
 		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7791_CLK_SCIFA4>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1f>, <&dmac0 0x20>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1f>, <&dmac0 0x20>,
+		       <&dmac1 0x1f>, <&dmac1 0x20>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -669,8 +681,9 @@
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7791_CLK_SCIFA5>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x23>, <&dmac0 0x24>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x23>, <&dmac0 0x24>,
+		       <&dmac1 0x23>, <&dmac1 0x24>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -682,8 +695,9 @@
 		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFB0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
+		       <&dmac1 0x3d>, <&dmac1 0x3e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -695,8 +709,9 @@
 		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFB1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x19>, <&dmac0 0x1a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x19>, <&dmac0 0x1a>,
+		       <&dmac1 0x19>, <&dmac1 0x1a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -708,8 +723,9 @@
 		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFB2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>,
+		       <&dmac1 0x1d>, <&dmac1 0x1e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -722,8 +738,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_SCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x29>, <&dmac0 0x2a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+		       <&dmac1 0x29>, <&dmac1 0x2a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -736,8 +753,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_SCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+		       <&dmac1 0x2d>, <&dmac1 0x2e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -750,8 +768,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_SCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+		       <&dmac1 0x2b>, <&dmac1 0x2c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -764,8 +783,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_SCIF3>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2f>, <&dmac0 0x30>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
+		       <&dmac1 0x2f>, <&dmac1 0x30>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -778,8 +798,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_SCIF4>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>,
+		       <&dmac1 0xfb>, <&dmac1 0xfc>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -792,8 +813,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_SCIF5>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>,
+		       <&dmac1 0xfd>, <&dmac1 0xfe>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -806,8 +828,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_HSCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x39>, <&dmac0 0x3a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+		       <&dmac1 0x39>, <&dmac1 0x3a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -820,8 +843,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_HSCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+		       <&dmac1 0x4d>, <&dmac1 0x4e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -834,8 +858,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_HSCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>,
+		       <&dmac1 0x3b>, <&dmac1 0x3c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -1478,8 +1503,9 @@
 		reg = <0 0xe6b10000 0 0x2c>;
 		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7791_CLK_QSPI_MOD>;
-		dmas = <&dmac0 0x17>, <&dmac0 0x18>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x17>, <&dmac0 0x18>,
+		       <&dmac1 0x17>, <&dmac1 0x18>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		num-cs = <1>;
 		#address-cells = <1>;
@@ -1492,8 +1518,9 @@
 		reg = <0 0xe6e20000 0 0x0064>;
 		interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>;
-		dmas = <&dmac0 0x51>, <&dmac0 0x52>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x51>, <&dmac0 0x52>,
+		       <&dmac1 0x51>, <&dmac1 0x52>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -1505,8 +1532,9 @@
 		reg = <0 0xe6e10000 0 0x0064>;
 		interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_MSIOF1>;
-		dmas = <&dmac0 0x55>, <&dmac0 0x56>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x55>, <&dmac0 0x56>,
+		       <&dmac1 0x55>, <&dmac1 0x56>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -1518,8 +1546,9 @@
 		reg = <0 0xe6e00000 0 0x0064>;
 		interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_MSIOF2>;
-		dmas = <&dmac0 0x41>, <&dmac0 0x42>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x41>, <&dmac0 0x42>,
+		       <&dmac1 0x41>, <&dmac1 0x42>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-- 
2.8.2



From christoffer.dall at linaro.org  Wed May 11 06:15:56 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:15:56 +0200
Subject: [PATCH v3 23/55] KVM: arm/arm64: vgic-new: Add CTLR, TYPER and
 IIDR handlers
In-Reply-To: <57332AD8.6050306@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-24-git-send-email-andre.przywara@arm.com>
 <20160511120533.GM27623@cbox> <57332AD8.6050306@arm.com>
Message-ID: <20160511131556.GR27623@cbox>

On Wed, May 11, 2016 at 01:51:36PM +0100, Marc Zyngier wrote:
> On 11/05/16 13:05, Christoffer Dall wrote:
> > On Fri, May 06, 2016 at 11:45:36AM +0100, Andre Przywara wrote:
> >> From: Marc Zyngier <marc.zyngier at arm.com>
> >>
> >> Those three registers are v2 emulation specific, so their implementation
> >> lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
> >> as their implementation is pretty simple.
> >> When the guest enables the distributor, we kick all VCPUs to get
> >> potentially pending interrupts serviced.
> >>
> >> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >> Changelog RFC..v1:
> >> - kick VCPUs is the distributor gets enabled
> >> - improve comment
> >>
> >> Changelog v1 .. v2:
> >> - adapt to new MMIO framework
> >> - use switch() statements to improve readability
> >>
> >> Changelog v2 .. v3:
> >> - add vgic_kick_vcpus() implementation
> >>
> >>  include/linux/irqchip/arm-gic.h  |  1 +
> >>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 48 +++++++++++++++++++++++++++++++++++++++-
> >>  virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
> >>  virt/kvm/arm/vgic/vgic.h         |  4 ++++
> >>  4 files changed, 67 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
> >> index be0d26f..fd05185 100644
> >> --- a/include/linux/irqchip/arm-gic.h
> >> +++ b/include/linux/irqchip/arm-gic.h
> >> @@ -33,6 +33,7 @@
> >>  
> >>  #define GIC_DIST_CTRL			0x000
> >>  #define GIC_DIST_CTR			0x004
> >> +#define GIC_DIST_IIDR			0x008
> >>  #define GIC_DIST_IGROUP			0x080
> >>  #define GIC_DIST_ENABLE_SET		0x100
> >>  #define GIC_DIST_ENABLE_CLEAR		0x180
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> index 2729a22..69e96f7 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> @@ -20,9 +20,55 @@
> >>  #include "vgic.h"
> >>  #include "vgic-mmio.h"
> >>  
> >> +static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
> >> +					    gpa_t addr, unsigned int len)
> >> +{
> >> +	u32 value;
> >> +
> >> +	switch (addr & 0x0c) {
> >> +	case GIC_DIST_CTRL:
> >> +		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
> >> +		break;
> >> +	case GIC_DIST_CTR:
> >> +		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
> >> +		value = (value >> 5) - 1;
> >> +		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
> >> +		break;
> >> +	case GIC_DIST_IIDR:
> >> +		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
> >> +		break;
> >> +	default:
> >> +		return 0;
> >> +	}
> >> +
> >> +	return extract_bytes(value, addr & 3, len);
> >> +}
> >> +
> >> +static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
> >> +				    gpa_t addr, unsigned int len,
> >> +				    unsigned long val)
> >> +{
> >> +	switch (addr & 0x0c) {
> >> +	case GIC_DIST_CTRL:
> >> +		if (!(addr & 1)) {
> > 
> > what is this !(addr & 1) check?
> 
> We check that the write includes the lowest byte of the register. But as
> we only have aligned accesses, it probably doesn't matter... I'll hack
> that away.
> 
where do we check to only have aligned accesses?

-Christoffer


From christoffer.dall at linaro.org  Wed May 11 06:16:30 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:16:30 +0200
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <57332DCD.1020701@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
 <20160511123423.GO27623@cbox> <57332DCD.1020701@arm.com>
Message-ID: <20160511131630.GS27623@cbox>

On Wed, May 11, 2016 at 02:04:13PM +0100, Andre Przywara wrote:
> Hi,
> 
> On 11/05/16 13:34, Christoffer Dall wrote:
> > On Fri, May 06, 2016 at 11:45:37AM +0100, Andre Przywara wrote:
> >> As the enable register handlers are shared between the v2 and v3
> >> emulation, their implementation goes into vgic-mmio.c, to be easily
> >> referenced from the v3 emulation as well later.
> >>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >> Changelog RFC..v1:
> >> - use lower bits of address to determine IRQ number
> >> - remove TODO, confirmed to be fine
> >>
> >> Changelog v1 .. v2:
> >> - adapt to new MMIO framework
> >>
> >>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
> >>  virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
> >>  virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
> >>  3 files changed, 69 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> index 69e96f7..448d1da 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> @@ -72,9 +72,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
> >>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
> >> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
> >> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
> >>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> >> index 41cf4f4..077ae86 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> >> @@ -46,6 +46,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> >>  	/* Ignore */
> >>  }
> >>  
> >> +/*
> >> + * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
> >> + * of the enabled bit, so there is only one function for both here.
> >> + */
> >> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
> >> +				    gpa_t addr, unsigned int len)
> >> +{
> >> +	u32 intid = (addr & 0x7f) * 8;
> > 
> > is there anything we can do about this to make it more intuitive?  A
> > macro to generate the mask/offset based on bits per interrupt or
> > something?
> 
> Yes, something where you give it the address and the bits-per-IRQ and it
> tells you the IRQ number.
> Not sure it is advisable to squash this into v4 still?
> 
I think it should be fairly mechanical and easy to squash, so would
prefer it, but if it gives you hours of headache, maybe not.

-Christoffer


From andre.przywara at arm.com  Wed May 11 06:24:22 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 14:24:22 +0100
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <20160511131402.GQ27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
 <20160511123423.GO27623@cbox> <57332DCD.1020701@arm.com>
 <20160511131402.GQ27623@cbox>
Message-ID: <57333286.2050708@arm.com>



On 11/05/16 14:14, Christoffer Dall wrote:
> On Wed, May 11, 2016 at 02:04:13PM +0100, Andre Przywara wrote:
>> Hi,
>>
>> On 11/05/16 13:34, Christoffer Dall wrote:
>>> On Fri, May 06, 2016 at 11:45:37AM +0100, Andre Przywara wrote:
>>>> As the enable register handlers are shared between the v2 and v3
>>>> emulation, their implementation goes into vgic-mmio.c, to be easily
>>>> referenced from the v3 emulation as well later.
>>>>
>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>> ---
>>>> Changelog RFC..v1:
>>>> - use lower bits of address to determine IRQ number
>>>> - remove TODO, confirmed to be fine
>>>>
>>>> Changelog v1 .. v2:
>>>> - adapt to new MMIO framework
>>>>
>>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
>>>>  virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
>>>>  virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
>>>>  3 files changed, 69 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> index 69e96f7..448d1da 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> @@ -72,9 +72,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
>>>>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
>>>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
>>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
>>>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
>>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
>>>>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
>>>> index 41cf4f4..077ae86 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-mmio.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>>>> @@ -46,6 +46,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
>>>>  	/* Ignore */
>>>>  }
>>>>  
>>>> +/*
>>>> + * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
>>>> + * of the enabled bit, so there is only one function for both here.
>>>> + */
>>>> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
>>>> +				    gpa_t addr, unsigned int len)
>>>> +{
>>>> +	u32 intid = (addr & 0x7f) * 8;
>>>
>>> is there anything we can do about this to make it more intuitive?  A
>>> macro to generate the mask/offset based on bits per interrupt or
>>> something?
>>
>> Yes, something where you give it the address and the bits-per-IRQ and it
>> tells you the IRQ number.
>> Not sure it is advisable to squash this into v4 still?
>>
>>>
>>>> +	u32 value = 0;
>>>> +	int i;
>>>> +
>>>> +	/* Loop over all IRQs affected by this read */
>>>> +	for (i = 0; i < len * 8; i++) {
>>>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>>>> +
>>>> +		if (irq->enabled)
>>>> +			value |= (1U << i);
>>>
>>> I couldn't find the code anywhere that enforces word-aligned accesses to
>>> these registers.  Do we have that?
>>
>> Not that I am aware of. I was suggesting this since we have one in the
>> IROUTER function. Architecturally we don't need to support halfword
>> accesses, it's: byte + word, word only or double-word + word, depending
>> on the actual register, IIRC.
>> As a fix we can at least deny (read: ignore) halfword accesses in
>> general in the dispatcher. Shall I do this (two two-liners)?
>> I think byte and word accesses are safe with the existing handlers last
>> time I checked.
>>
>>> If that's not the case, doesn't this break of you do a non-word aligned
>>> access?
>>
>> Why would it? vgic_data_host_to_mmio_bus and extract_bytes should cover
>> this, shouldn't they?
>>
> 
> I think this breaks on a simple byte access.  Let's say you are
> accessing byte 1 (addr & 0x7ff == 1), then because you start your loop
> at 0, you're going to set bits [7:0] in the value variable, and then
> extract bits [15:8] in extract_bytes(), right?

Looks like, yes. I thought that it would take care of that, because a
handler function shouldn't be bothered with this: it just acts on the
lower bytes (till the length) and extract_bytes() does the rest. I think
this is what the old magic vgic_reg_access does due to "regval >>
word_offset".

Do you care to fix this in extract_bytes?

Cheers,
Andre.


From marc.zyngier at arm.com  Wed May 11 06:27:53 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 11 May 2016 14:27:53 +0100
Subject: [PATCH v3 23/55] KVM: arm/arm64: vgic-new: Add CTLR, TYPER and
 IIDR handlers
In-Reply-To: <20160511131556.GR27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-24-git-send-email-andre.przywara@arm.com>
 <20160511120533.GM27623@cbox> <57332AD8.6050306@arm.com>
 <20160511131556.GR27623@cbox>
Message-ID: <57333359.3000505@arm.com>

On 11/05/16 14:15, Christoffer Dall wrote:
> On Wed, May 11, 2016 at 01:51:36PM +0100, Marc Zyngier wrote:
>> On 11/05/16 13:05, Christoffer Dall wrote:
>>> On Fri, May 06, 2016 at 11:45:36AM +0100, Andre Przywara wrote:
>>>> From: Marc Zyngier <marc.zyngier at arm.com>
>>>>
>>>> Those three registers are v2 emulation specific, so their implementation
>>>> lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
>>>> as their implementation is pretty simple.
>>>> When the guest enables the distributor, we kick all VCPUs to get
>>>> potentially pending interrupts serviced.
>>>>
>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>> ---
>>>> Changelog RFC..v1:
>>>> - kick VCPUs is the distributor gets enabled
>>>> - improve comment
>>>>
>>>> Changelog v1 .. v2:
>>>> - adapt to new MMIO framework
>>>> - use switch() statements to improve readability
>>>>
>>>> Changelog v2 .. v3:
>>>> - add vgic_kick_vcpus() implementation
>>>>
>>>>  include/linux/irqchip/arm-gic.h  |  1 +
>>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 48 +++++++++++++++++++++++++++++++++++++++-
>>>>  virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
>>>>  virt/kvm/arm/vgic/vgic.h         |  4 ++++
>>>>  4 files changed, 67 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>>>> index be0d26f..fd05185 100644
>>>> --- a/include/linux/irqchip/arm-gic.h
>>>> +++ b/include/linux/irqchip/arm-gic.h
>>>> @@ -33,6 +33,7 @@
>>>>  
>>>>  #define GIC_DIST_CTRL			0x000
>>>>  #define GIC_DIST_CTR			0x004
>>>> +#define GIC_DIST_IIDR			0x008
>>>>  #define GIC_DIST_IGROUP			0x080
>>>>  #define GIC_DIST_ENABLE_SET		0x100
>>>>  #define GIC_DIST_ENABLE_CLEAR		0x180
>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> index 2729a22..69e96f7 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> @@ -20,9 +20,55 @@
>>>>  #include "vgic.h"
>>>>  #include "vgic-mmio.h"
>>>>  
>>>> +static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
>>>> +					    gpa_t addr, unsigned int len)
>>>> +{
>>>> +	u32 value;
>>>> +
>>>> +	switch (addr & 0x0c) {
>>>> +	case GIC_DIST_CTRL:
>>>> +		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
>>>> +		break;
>>>> +	case GIC_DIST_CTR:
>>>> +		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
>>>> +		value = (value >> 5) - 1;
>>>> +		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
>>>> +		break;
>>>> +	case GIC_DIST_IIDR:
>>>> +		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
>>>> +		break;
>>>> +	default:
>>>> +		return 0;
>>>> +	}
>>>> +
>>>> +	return extract_bytes(value, addr & 3, len);
>>>> +}
>>>> +
>>>> +static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
>>>> +				    gpa_t addr, unsigned int len,
>>>> +				    unsigned long val)
>>>> +{
>>>> +	switch (addr & 0x0c) {
>>>> +	case GIC_DIST_CTRL:
>>>> +		if (!(addr & 1)) {
>>>
>>> what is this !(addr & 1) check?
>>
>> We check that the write includes the lowest byte of the register. But as
>> we only have aligned accesses, it probably doesn't matter... I'll hack
>> that away.
>>
> where do we check to only have aligned accesses?

Looks like a missing feature. The v2 spec says:

4.1.4 GIC register access
All registers support 32-bit word accesses with the access type defined
in Table 4-1 on page 4-73 and Table 4-2 on page 4-74.
In addition, the GICD_IPRIORITYRn, GICD_ITARGETSRn, GICD_CPENDSGIRn, and
GICD_SPENDSGIRn registers support byte accesses.

Similar thing for v3 (8.1.3).

By the look of it, we should add checks in all accessors. I'll get onto it.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From christoffer.dall at linaro.org  Wed May 11 06:29:53 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:29:53 +0200
Subject: [PULL 00/29] KVM/ARM Changes for v4.7
Message-ID: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>

Hi Paolo and Radim,

Here is the initial set of changes for KVM/ARM for v4.7.

Sorry I'm a bit late with these, but we were trying to get the new vgic
implementation in as part of this, but I have decided to send this pull
request now, and we can follow up with another for the new VGIC,
assuming we feel like we have that in place in a few days.

There are a few changes in this pull request touching things outside
KVM, but they should all carry the necessary acks and it made the
merge process much easier to do it this way.

Hope this works for you guys.

For a description of the content, see below; otherwise:

The following changes since commit 06a71a24bae57a07afee9cda6b00495347d8a448:

  arm64: KVM: unregister notifiers in hyp mode teardown path (2016-04-06 13:47:52 +0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git tags/kvm-arm-for-4.7

for you to fetch changes up to 06485053244480f5f403d8f89b8617bd7d549113:

  kvm: arm64: Enable hardware updates of the Access Flag for Stage 2 page tables (2016-05-09 22:23:08 +0200)


Thanks,
-Christoffer

----------------------------------------------------------------
KVM/ARM Changes for Linux v4.7

Reworks our stage 2 page table handling to have page table manipulation
macros separate from those of the host systems as the underlying
hardware page tables can be configured to be noticably different in
layout from the stage 1 page tables used by the host.

Adds 16K page size support based on the above.

Adds a generic firmware probing layer for the timer and GIC so that KVM
initializes using the same logic based on both ACPI and FDT.

Finally adds support for hardware updating of the access flag.

----------------------------------------------------------------
Catalin Marinas (1):
      kvm: arm64: Enable hardware updates of the Access Flag for Stage 2 page tables

Julien Grall (10):
      clocksource: arm_arch_timer: Gather KVM specific information in a structure
      clocksource: arm_arch_timer: Extend arch_timer_kvm_info to get the virtual IRQ
      irqchip/gic-v2: Gather ACPI specific data in a single structure
      irqchip/gic-v2: Parse and export virtual GIC information
      irqchip/gic-v3: Prefix all pr_* messages by "GICv3: "
      irqchip/gic-v3: Gather all ACPI specific data in a single structure
      irqchip/gic-v3: Parse and export virtual GIC information
      KVM: arm/arm64: arch_timer: Rely on the arch timer to parse the firmware tables
      KVM: arm/arm64: vgic: Rely on the GIC driver to parse the firmware tables
      clocksource: arm_arch_timer: Remove arch_timer_get_timecounter

Marc Zyngier (1):
      arm/arm64: KVM: Enforce Break-Before-Make on Stage-2 page tables

Suzuki K Poulose (17):
      arm64: Reuse TCR field definitions for EL1 and EL2
      arm64: Cleanup VTCR_EL2 and VTTBR field values
      kvm arm: Move fake PGD handling to arch specific files
      arm64: Introduce pmd_thp_or_huge
      kvm-arm: Replace kvm_pmd_huge with pmd_thp_or_huge
      kvm-arm: Remove kvm_pud_huge()
      kvm-arm: arm32: Introduce stage2 page table helpers
      kvm-arm: arm: Introduce hyp page table empty checks
      kvm-arm: arm64: Introduce stage2 page table helpers
      kvm-arm: arm64: Introduce hyp page table empty checks
      kvm-arm: Use explicit stage2 helper routines
      kvm-arm: Add explicit hyp page table modifiers
      kvm-arm: Add stage2 page table modifiers
      kvm-arm: Cleanup kvm_* wrappers
      kvm: arm64: Get rid of fake page table levels
      kvm-arm: Cleanup stage2 pgd handling
      arm64: kvm: Add support for 16K pages

 arch/arm/include/asm/kvm_mmu.h                |  43 +--
 arch/arm/include/asm/stage2_pgtable.h         |  61 ++++
 arch/arm/kvm/arm.c                            |   2 +-
 arch/arm/kvm/mmu.c                            | 408 ++++++++++++++------------
 arch/arm64/include/asm/kvm_arm.h              |  85 +++---
 arch/arm64/include/asm/kvm_mmu.h              | 111 ++-----
 arch/arm64/include/asm/pgtable-hwdef.h        |  80 +++--
 arch/arm64/include/asm/pgtable.h              |  15 +-
 arch/arm64/include/asm/stage2_pgtable-nopmd.h |  42 +++
 arch/arm64/include/asm/stage2_pgtable-nopud.h |  39 +++
 arch/arm64/include/asm/stage2_pgtable.h       | 142 +++++++++
 arch/arm64/kvm/Kconfig                        |   1 -
 arch/arm64/kvm/hyp/s2-setup.c                 |   8 +
 drivers/clocksource/arm_arch_timer.c          |  11 +-
 drivers/irqchip/irq-gic-common.c              |  13 +
 drivers/irqchip/irq-gic-common.h              |   3 +
 drivers/irqchip/irq-gic-v3.c                  | 176 +++++++++--
 drivers/irqchip/irq-gic.c                     |  87 +++++-
 include/clocksource/arm_arch_timer.h          |  12 +-
 include/kvm/arm_vgic.h                        |   7 +-
 include/linux/irqchip/arm-gic-common.h        |  34 +++
 virt/kvm/arm/arch_timer.c                     |  40 +--
 virt/kvm/arm/vgic-v2.c                        |  61 ++--
 virt/kvm/arm/vgic-v3.c                        |  47 +--
 virt/kvm/arm/vgic.c                           |  50 ++--
 25 files changed, 1053 insertions(+), 525 deletions(-)
 create mode 100644 arch/arm/include/asm/stage2_pgtable.h
 create mode 100644 arch/arm64/include/asm/stage2_pgtable-nopmd.h
 create mode 100644 arch/arm64/include/asm/stage2_pgtable-nopud.h
 create mode 100644 arch/arm64/include/asm/stage2_pgtable.h
 create mode 100644 include/linux/irqchip/arm-gic-common.h


From christoffer.dall at linaro.org  Wed May 11 06:29:58 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:29:58 +0200
Subject: [PULL 05/29] kvm-arm: Replace kvm_pmd_huge with pmd_thp_or_huge
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-6-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Both arm and arm64 now provides a helper, pmd_thp_or_huge()
to check if the given pmd represents a huge page. Use that
instead of our own custom check.

Suggested-by: Mark Rutland <mark.rutland at arm.com>
Cc: Marc Zyngier <marc.zyngier at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm/kvm/mmu.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 774d00b..7837f0a 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -45,7 +45,6 @@ static phys_addr_t hyp_idmap_vector;
 
 #define hyp_pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t))
 
-#define kvm_pmd_huge(_x)	(pmd_huge(_x) || pmd_trans_huge(_x))
 #define kvm_pud_huge(_x)	pud_huge(_x)
 
 #define KVM_S2PTE_FLAG_IS_IOMAP		(1UL << 0)
@@ -115,7 +114,7 @@ static bool kvm_is_device_pfn(unsigned long pfn)
  */
 static void stage2_dissolve_pmd(struct kvm *kvm, phys_addr_t addr, pmd_t *pmd)
 {
-	if (!kvm_pmd_huge(*pmd))
+	if (!pmd_thp_or_huge(*pmd))
 		return;
 
 	pmd_clear(pmd);
@@ -177,7 +176,7 @@ static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
 static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
 {
 	pte_t *pte_table = pte_offset_kernel(pmd, 0);
-	VM_BUG_ON(kvm_pmd_huge(*pmd));
+	VM_BUG_ON(pmd_thp_or_huge(*pmd));
 	pmd_clear(pmd);
 	kvm_tlb_flush_vmid_ipa(kvm, addr);
 	pte_free_kernel(NULL, pte_table);
@@ -240,7 +239,7 @@ static void unmap_pmds(struct kvm *kvm, pud_t *pud,
 	do {
 		next = kvm_pmd_addr_end(addr, end);
 		if (!pmd_none(*pmd)) {
-			if (kvm_pmd_huge(*pmd)) {
+			if (pmd_thp_or_huge(*pmd)) {
 				pmd_t old_pmd = *pmd;
 
 				pmd_clear(pmd);
@@ -326,7 +325,7 @@ static void stage2_flush_pmds(struct kvm *kvm, pud_t *pud,
 	do {
 		next = kvm_pmd_addr_end(addr, end);
 		if (!pmd_none(*pmd)) {
-			if (kvm_pmd_huge(*pmd))
+			if (pmd_thp_or_huge(*pmd))
 				kvm_flush_dcache_pmd(*pmd);
 			else
 				stage2_flush_ptes(kvm, pmd, addr, next);
@@ -1050,7 +1049,7 @@ static void stage2_wp_pmds(pud_t *pud, phys_addr_t addr, phys_addr_t end)
 	do {
 		next = kvm_pmd_addr_end(addr, end);
 		if (!pmd_none(*pmd)) {
-			if (kvm_pmd_huge(*pmd)) {
+			if (pmd_thp_or_huge(*pmd)) {
 				if (!kvm_s2pmd_readonly(pmd))
 					kvm_set_s2pmd_readonly(pmd);
 			} else {
@@ -1331,7 +1330,7 @@ static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
 	if (!pmd || pmd_none(*pmd))	/* Nothing there */
 		goto out;
 
-	if (kvm_pmd_huge(*pmd)) {	/* THP, HugeTLB */
+	if (pmd_thp_or_huge(*pmd)) {	/* THP, HugeTLB */
 		*pmd = pmd_mkyoung(*pmd);
 		pfn = pmd_pfn(*pmd);
 		pfn_valid = true;
@@ -1555,7 +1554,7 @@ static int kvm_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
 	if (!pmd || pmd_none(*pmd))	/* Nothing there */
 		return 0;
 
-	if (kvm_pmd_huge(*pmd)) {	/* THP, HugeTLB */
+	if (pmd_thp_or_huge(*pmd)) {	/* THP, HugeTLB */
 		if (pmd_young(*pmd)) {
 			*pmd = pmd_mkold(*pmd);
 			return 1;
@@ -1585,7 +1584,7 @@ static int kvm_test_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
 	if (!pmd || pmd_none(*pmd))	/* Nothing there */
 		return 0;
 
-	if (kvm_pmd_huge(*pmd))		/* THP, HugeTLB */
+	if (pmd_thp_or_huge(*pmd))		/* THP, HugeTLB */
 		return pmd_young(*pmd);
 
 	pte = pte_offset_kernel(pmd, gpa);
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:29:57 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:29:57 +0200
Subject: [PULL 04/29] arm64: Introduce pmd_thp_or_huge
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-5-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Add a helper to determine if a given pmd represents a huge page
either by hugetlb or thp, as we have for arm. This will be used
by KVM MMU code.

Suggested-by: Mark Rutland <mark.rutland at arm.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Steve Capper <steve.capper at linaro.org>
Cc: Will Deacon <will.deacon at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Acked-by: Will Deacon <will.deacon at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm64/include/asm/pgtable.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 989fef1..dda4aa9 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -290,6 +290,8 @@ static inline pgprot_t mk_sect_prot(pgprot_t prot)
 #define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
 #define pmd_mknotpresent(pmd)	(__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK))
 
+#define pmd_thp_or_huge(pmd)	(pmd_huge(pmd) || pmd_trans_huge(pmd))
+
 #define __HAVE_ARCH_PMD_WRITE
 #define pmd_write(pmd)		pte_write(pmd_pte(pmd))
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:29:55 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:29:55 +0200
Subject: [PULL 02/29] arm64: Cleanup VTCR_EL2 and VTTBR field values
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-3-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

We share most of the bits for VTCR_EL2 for different page sizes,
except for the TG0 value and the entry level value. This patch
makes the definitions a bit more cleaner to reflect this fact.

Also cleans up the VTTBR_X calculation. No functional changes.

Cc: Marc Zyngier <marc.zyngier at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm64/include/asm/kvm_arm.h | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index a46b39f..1281d98 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -144,30 +144,32 @@
  * The magic numbers used for VTTBR_X in this patch can be found in Tables
  * D4-23 and D4-25 in ARM DDI 0487A.b.
  */
+
+#define VTCR_EL2_T0SZ_IPA	VTCR_EL2_T0SZ_40B
+#define VTCR_EL2_COMMON_BITS	(VTCR_EL2_SH0_INNER | VTCR_EL2_ORGN0_WBWA | \
+				 VTCR_EL2_IRGN0_WBWA | VTCR_EL2_RES1)
+
 #ifdef CONFIG_ARM64_64K_PAGES
 /*
  * Stage2 translation configuration:
- * 40bits input  (T0SZ = 24)
  * 64kB pages (TG0 = 1)
  * 2 level page tables (SL = 1)
  */
-#define VTCR_EL2_FLAGS		(VTCR_EL2_TG0_64K | VTCR_EL2_SH0_INNER | \
-				 VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \
-				 VTCR_EL2_SL0_LVL1 | VTCR_EL2_RES1)
-#define VTTBR_X		(38 - VTCR_EL2_T0SZ_40B)
+#define VTCR_EL2_TGRAN_FLAGS		(VTCR_EL2_TG0_64K | VTCR_EL2_SL0_LVL1)
+#define VTTBR_X_TGRAN_MAGIC		38
 #else
 /*
  * Stage2 translation configuration:
- * 40bits input  (T0SZ = 24)
  * 4kB pages (TG0 = 0)
  * 3 level page tables (SL = 1)
  */
-#define VTCR_EL2_FLAGS		(VTCR_EL2_TG0_4K | VTCR_EL2_SH0_INNER | \
-				 VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \
-				 VTCR_EL2_SL0_LVL1 | VTCR_EL2_RES1)
-#define VTTBR_X		(37 - VTCR_EL2_T0SZ_40B)
+#define VTCR_EL2_TGRAN_FLAGS		(VTCR_EL2_TG0_4K | VTCR_EL2_SL0_LVL1)
+#define VTTBR_X_TGRAN_MAGIC		37
 #endif
 
+#define VTCR_EL2_FLAGS			(VTCR_EL2_COMMON_BITS | VTCR_EL2_TGRAN_FLAGS)
+#define VTTBR_X				(VTTBR_X_TGRAN_MAGIC - VTCR_EL2_T0SZ_IPA)
+
 #define VTTBR_BADDR_SHIFT (VTTBR_X - 1)
 #define VTTBR_BADDR_MASK  (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
 #define VTTBR_VMID_SHIFT  (UL(48))
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:29:54 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:29:54 +0200
Subject: [PULL 01/29] arm64: Reuse TCR field definitions for EL1 and EL2
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-2-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

TCR_EL1, TCR_EL2 and VTCR_EL2, all share some field positions
(TG0, ORGN0, IRGN0 and SH0) and their corresponding value definitions.

This patch makes the TCR_EL1 definitions reusable and uses them for TCR_EL2
and VTCR_EL2 fields.

This also fixes a bug where we assume TG0 in {V}TCR_EL2 is 1bit field.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Acked-by: Will Deacon <will.deacon at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm64/include/asm/kvm_arm.h       | 48 ++++++++++----------
 arch/arm64/include/asm/pgtable-hwdef.h | 80 ++++++++++++++++++++++++++--------
 2 files changed, 88 insertions(+), 40 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 3f29887..a46b39f 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -96,32 +96,34 @@
 			 SCTLR_EL2_SA | SCTLR_EL2_I)
 
 /* TCR_EL2 Registers bits */
-#define TCR_EL2_RES1	((1 << 31) | (1 << 23))
-#define TCR_EL2_TBI	(1 << 20)
-#define TCR_EL2_PS	(7 << 16)
-#define TCR_EL2_PS_40B	(2 << 16)
-#define TCR_EL2_TG0	(1 << 14)
-#define TCR_EL2_SH0	(3 << 12)
-#define TCR_EL2_ORGN0	(3 << 10)
-#define TCR_EL2_IRGN0	(3 << 8)
-#define TCR_EL2_T0SZ	0x3f
-#define TCR_EL2_MASK	(TCR_EL2_TG0 | TCR_EL2_SH0 | \
-			 TCR_EL2_ORGN0 | TCR_EL2_IRGN0 | TCR_EL2_T0SZ)
+#define TCR_EL2_RES1		((1 << 31) | (1 << 23))
+#define TCR_EL2_TBI		(1 << 20)
+#define TCR_EL2_PS_SHIFT	16
+#define TCR_EL2_PS_MASK		(7 << TCR_EL2_PS_SHIFT)
+#define TCR_EL2_PS_40B		(2 << TCR_EL2_PS_SHIFT)
+#define TCR_EL2_TG0_MASK	TCR_TG0_MASK
+#define TCR_EL2_SH0_MASK	TCR_SH0_MASK
+#define TCR_EL2_ORGN0_MASK	TCR_ORGN0_MASK
+#define TCR_EL2_IRGN0_MASK	TCR_IRGN0_MASK
+#define TCR_EL2_T0SZ_MASK	0x3f
+#define TCR_EL2_MASK	(TCR_EL2_TG0_MASK | TCR_EL2_SH0_MASK | \
+			 TCR_EL2_ORGN0_MASK | TCR_EL2_IRGN0_MASK | TCR_EL2_T0SZ_MASK)
 
 /* VTCR_EL2 Registers bits */
 #define VTCR_EL2_RES1		(1 << 31)
-#define VTCR_EL2_PS_MASK	(7 << 16)
-#define VTCR_EL2_TG0_MASK	(1 << 14)
-#define VTCR_EL2_TG0_4K		(0 << 14)
-#define VTCR_EL2_TG0_64K	(1 << 14)
-#define VTCR_EL2_SH0_MASK	(3 << 12)
-#define VTCR_EL2_SH0_INNER	(3 << 12)
-#define VTCR_EL2_ORGN0_MASK	(3 << 10)
-#define VTCR_EL2_ORGN0_WBWA	(1 << 10)
-#define VTCR_EL2_IRGN0_MASK	(3 << 8)
-#define VTCR_EL2_IRGN0_WBWA	(1 << 8)
-#define VTCR_EL2_SL0_MASK	(3 << 6)
-#define VTCR_EL2_SL0_LVL1	(1 << 6)
+#define VTCR_EL2_PS_MASK	TCR_EL2_PS_MASK
+#define VTCR_EL2_TG0_MASK	TCR_TG0_MASK
+#define VTCR_EL2_TG0_4K		TCR_TG0_4K
+#define VTCR_EL2_TG0_64K	TCR_TG0_64K
+#define VTCR_EL2_SH0_MASK	TCR_SH0_MASK
+#define VTCR_EL2_SH0_INNER	TCR_SH0_INNER
+#define VTCR_EL2_ORGN0_MASK	TCR_ORGN0_MASK
+#define VTCR_EL2_ORGN0_WBWA	TCR_ORGN0_WBWA
+#define VTCR_EL2_IRGN0_MASK	TCR_IRGN0_MASK
+#define VTCR_EL2_IRGN0_WBWA	TCR_IRGN0_WBWA
+#define VTCR_EL2_SL0_SHIFT	6
+#define VTCR_EL2_SL0_MASK	(3 << VTCR_EL2_SL0_SHIFT)
+#define VTCR_EL2_SL0_LVL1	(1 << VTCR_EL2_SL0_SHIFT)
 #define VTCR_EL2_T0SZ_MASK	0x3f
 #define VTCR_EL2_T0SZ_40B	24
 #define VTCR_EL2_VS_SHIFT	19
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 5c25b83..936f173 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -208,23 +208,69 @@
 #define TCR_T1SZ(x)		((UL(64) - (x)) << TCR_T1SZ_OFFSET)
 #define TCR_TxSZ(x)		(TCR_T0SZ(x) | TCR_T1SZ(x))
 #define TCR_TxSZ_WIDTH		6
-#define TCR_IRGN_NC		((UL(0) << 8) | (UL(0) << 24))
-#define TCR_IRGN_WBWA		((UL(1) << 8) | (UL(1) << 24))
-#define TCR_IRGN_WT		((UL(2) << 8) | (UL(2) << 24))
-#define TCR_IRGN_WBnWA		((UL(3) << 8) | (UL(3) << 24))
-#define TCR_IRGN_MASK		((UL(3) << 8) | (UL(3) << 24))
-#define TCR_ORGN_NC		((UL(0) << 10) | (UL(0) << 26))
-#define TCR_ORGN_WBWA		((UL(1) << 10) | (UL(1) << 26))
-#define TCR_ORGN_WT		((UL(2) << 10) | (UL(2) << 26))
-#define TCR_ORGN_WBnWA		((UL(3) << 10) | (UL(3) << 26))
-#define TCR_ORGN_MASK		((UL(3) << 10) | (UL(3) << 26))
-#define TCR_SHARED		((UL(3) << 12) | (UL(3) << 28))
-#define TCR_TG0_4K		(UL(0) << 14)
-#define TCR_TG0_64K		(UL(1) << 14)
-#define TCR_TG0_16K		(UL(2) << 14)
-#define TCR_TG1_16K		(UL(1) << 30)
-#define TCR_TG1_4K		(UL(2) << 30)
-#define TCR_TG1_64K		(UL(3) << 30)
+
+#define TCR_IRGN0_SHIFT		8
+#define TCR_IRGN0_MASK		(UL(3) << TCR_IRGN0_SHIFT)
+#define TCR_IRGN0_NC		(UL(0) << TCR_IRGN0_SHIFT)
+#define TCR_IRGN0_WBWA		(UL(1) << TCR_IRGN0_SHIFT)
+#define TCR_IRGN0_WT		(UL(2) << TCR_IRGN0_SHIFT)
+#define TCR_IRGN0_WBnWA		(UL(3) << TCR_IRGN0_SHIFT)
+
+#define TCR_IRGN1_SHIFT		24
+#define TCR_IRGN1_MASK		(UL(3) << TCR_IRGN1_SHIFT)
+#define TCR_IRGN1_NC		(UL(0) << TCR_IRGN1_SHIFT)
+#define TCR_IRGN1_WBWA		(UL(1) << TCR_IRGN1_SHIFT)
+#define TCR_IRGN1_WT		(UL(2) << TCR_IRGN1_SHIFT)
+#define TCR_IRGN1_WBnWA		(UL(3) << TCR_IRGN1_SHIFT)
+
+#define TCR_IRGN_NC		(TCR_IRGN0_NC | TCR_IRGN1_NC)
+#define TCR_IRGN_WBWA		(TCR_IRGN0_WBWA | TCR_IRGN1_WBWA)
+#define TCR_IRGN_WT		(TCR_IRGN0_WT | TCR_IRGN1_WT)
+#define TCR_IRGN_WBnWA		(TCR_IRGN0_WBnWA | TCR_IRGN1_WBnWA)
+#define TCR_IRGN_MASK		(TCR_IRGN0_MASK | TCR_IRGN1_MASK)
+
+
+#define TCR_ORGN0_SHIFT		10
+#define TCR_ORGN0_MASK		(UL(3) << TCR_ORGN0_SHIFT)
+#define TCR_ORGN0_NC		(UL(0) << TCR_ORGN0_SHIFT)
+#define TCR_ORGN0_WBWA		(UL(1) << TCR_ORGN0_SHIFT)
+#define TCR_ORGN0_WT		(UL(2) << TCR_ORGN0_SHIFT)
+#define TCR_ORGN0_WBnWA		(UL(3) << TCR_ORGN0_SHIFT)
+
+#define TCR_ORGN1_SHIFT		26
+#define TCR_ORGN1_MASK		(UL(3) << TCR_ORGN1_SHIFT)
+#define TCR_ORGN1_NC		(UL(0) << TCR_ORGN1_SHIFT)
+#define TCR_ORGN1_WBWA		(UL(1) << TCR_ORGN1_SHIFT)
+#define TCR_ORGN1_WT		(UL(2) << TCR_ORGN1_SHIFT)
+#define TCR_ORGN1_WBnWA		(UL(3) << TCR_ORGN1_SHIFT)
+
+#define TCR_ORGN_NC		(TCR_ORGN0_NC | TCR_ORGN1_NC)
+#define TCR_ORGN_WBWA		(TCR_ORGN0_WBWA | TCR_ORGN1_WBWA)
+#define TCR_ORGN_WT		(TCR_ORGN0_WT | TCR_ORGN1_WT)
+#define TCR_ORGN_WBnWA		(TCR_ORGN0_WBnWA | TCR_ORGN1_WBnWA)
+#define TCR_ORGN_MASK		(TCR_ORGN0_MASK | TCR_ORGN1_MASK)
+
+#define TCR_SH0_SHIFT		12
+#define TCR_SH0_MASK		(UL(3) << TCR_SH0_SHIFT)
+#define TCR_SH0_INNER		(UL(3) << TCR_SH0_SHIFT)
+
+#define TCR_SH1_SHIFT		28
+#define TCR_SH1_MASK		(UL(3) << TCR_SH1_SHIFT)
+#define TCR_SH1_INNER		(UL(3) << TCR_SH1_SHIFT)
+#define TCR_SHARED		(TCR_SH0_INNER | TCR_SH1_INNER)
+
+#define TCR_TG0_SHIFT		14
+#define TCR_TG0_MASK		(UL(3) << TCR_TG0_SHIFT)
+#define TCR_TG0_4K		(UL(0) << TCR_TG0_SHIFT)
+#define TCR_TG0_64K		(UL(1) << TCR_TG0_SHIFT)
+#define TCR_TG0_16K		(UL(2) << TCR_TG0_SHIFT)
+
+#define TCR_TG1_SHIFT		30
+#define TCR_TG1_MASK		(UL(3) << TCR_TG1_SHIFT)
+#define TCR_TG1_16K		(UL(1) << TCR_TG1_SHIFT)
+#define TCR_TG1_4K		(UL(2) << TCR_TG1_SHIFT)
+#define TCR_TG1_64K		(UL(3) << TCR_TG1_SHIFT)
+
 #define TCR_ASID16		(UL(1) << 36)
 #define TCR_TBI0		(UL(1) << 37)
 #define TCR_HA			(UL(1) << 39)
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:29:56 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:29:56 +0200
Subject: [PULL 03/29] kvm arm: Move fake PGD handling to arch specific files
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-4-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Rearrange the code for fake pgd handling, which is applicable
only for arm64. This will later be removed once we introduce
the stage2 page table walker macros.

Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm/include/asm/kvm_mmu.h   | 11 ++++++++--
 arch/arm/kvm/mmu.c               | 47 ++++++----------------------------------
 arch/arm64/include/asm/kvm_mmu.h | 43 ++++++++++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+), 42 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index da44be9..c2b2b27 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -161,8 +161,6 @@ static inline bool kvm_page_empty(void *ptr)
 #define kvm_pmd_table_empty(kvm, pmdp) kvm_page_empty(pmdp)
 #define kvm_pud_table_empty(kvm, pudp) (0)
 
-#define KVM_PREALLOC_LEVEL	0
-
 static inline void *kvm_get_hwpgd(struct kvm *kvm)
 {
 	return kvm->arch.pgd;
@@ -173,6 +171,15 @@ static inline unsigned int kvm_get_hwpgd_size(void)
 	return PTRS_PER_S2_PGD * sizeof(pgd_t);
 }
 
+static inline pgd_t *kvm_setup_fake_pgd(pgd_t *hwpgd)
+{
+	return hwpgd;
+}
+
+static inline void kvm_free_fake_pgd(pgd_t *pgd)
+{
+}
+
 struct kvm;
 
 #define kvm_flush_dcache_to_poc(a,l)	__cpuc_flush_dcache_area((a), (l))
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 58dbd5c..774d00b 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -684,47 +684,16 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm)
 	if (!hwpgd)
 		return -ENOMEM;
 
-	/* When the kernel uses more levels of page tables than the
+	/*
+	 * When the kernel uses more levels of page tables than the
 	 * guest, we allocate a fake PGD and pre-populate it to point
 	 * to the next-level page table, which will be the real
 	 * initial page table pointed to by the VTTBR.
-	 *
-	 * When KVM_PREALLOC_LEVEL==2, we allocate a single page for
-	 * the PMD and the kernel will use folded pud.
-	 * When KVM_PREALLOC_LEVEL==1, we allocate 2 consecutive PUD
-	 * pages.
 	 */
-	if (KVM_PREALLOC_LEVEL > 0) {
-		int i;
-
-		/*
-		 * Allocate fake pgd for the page table manipulation macros to
-		 * work.  This is not used by the hardware and we have no
-		 * alignment requirement for this allocation.
-		 */
-		pgd = kmalloc(PTRS_PER_S2_PGD * sizeof(pgd_t),
-				GFP_KERNEL | __GFP_ZERO);
-
-		if (!pgd) {
-			kvm_free_hwpgd(hwpgd);
-			return -ENOMEM;
-		}
-
-		/* Plug the HW PGD into the fake one. */
-		for (i = 0; i < PTRS_PER_S2_PGD; i++) {
-			if (KVM_PREALLOC_LEVEL == 1)
-				pgd_populate(NULL, pgd + i,
-					     (pud_t *)hwpgd + i * PTRS_PER_PUD);
-			else if (KVM_PREALLOC_LEVEL == 2)
-				pud_populate(NULL, pud_offset(pgd, 0) + i,
-					     (pmd_t *)hwpgd + i * PTRS_PER_PMD);
-		}
-	} else {
-		/*
-		 * Allocate actual first-level Stage-2 page table used by the
-		 * hardware for Stage-2 page table walks.
-		 */
-		pgd = (pgd_t *)hwpgd;
+	pgd = kvm_setup_fake_pgd(hwpgd);
+	if (IS_ERR(pgd)) {
+		kvm_free_hwpgd(hwpgd);
+		return PTR_ERR(pgd);
 	}
 
 	kvm_clean_pgd(pgd);
@@ -831,9 +800,7 @@ void kvm_free_stage2_pgd(struct kvm *kvm)
 
 	unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
 	kvm_free_hwpgd(kvm_get_hwpgd(kvm));
-	if (KVM_PREALLOC_LEVEL > 0)
-		kfree(kvm->arch.pgd);
-
+	kvm_free_fake_pgd(kvm->arch.pgd);
 	kvm->arch.pgd = NULL;
 }
 
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 22732a5..9a3409f 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -208,6 +208,49 @@ static inline unsigned int kvm_get_hwpgd_size(void)
 	return PTRS_PER_S2_PGD * sizeof(pgd_t);
 }
 
+/*
+ * Allocate fake pgd for the host kernel page table macros to work.
+ * This is not used by the hardware and we have no alignment
+ * requirement for this allocation.
+ */
+static inline pgd_t *kvm_setup_fake_pgd(pgd_t *hwpgd)
+{
+	int i;
+	pgd_t *pgd;
+
+	if (!KVM_PREALLOC_LEVEL)
+		return hwpgd;
+
+	/*
+	 * When KVM_PREALLOC_LEVEL==2, we allocate a single page for
+	 * the PMD and the kernel will use folded pud.
+	 * When KVM_PREALLOC_LEVEL==1, we allocate 2 consecutive PUD
+	 * pages.
+	 */
+
+	pgd = kmalloc(PTRS_PER_S2_PGD * sizeof(pgd_t),
+			GFP_KERNEL | __GFP_ZERO);
+	if (!pgd)
+		return ERR_PTR(-ENOMEM);
+
+	/* Plug the HW PGD into the fake one. */
+	for (i = 0; i < PTRS_PER_S2_PGD; i++) {
+		if (KVM_PREALLOC_LEVEL == 1)
+			pgd_populate(NULL, pgd + i,
+				     (pud_t *)hwpgd + i * PTRS_PER_PUD);
+		else if (KVM_PREALLOC_LEVEL == 2)
+			pud_populate(NULL, pud_offset(pgd, 0) + i,
+				     (pmd_t *)hwpgd + i * PTRS_PER_PMD);
+	}
+
+	return pgd;
+}
+
+static inline void kvm_free_fake_pgd(pgd_t *pgd)
+{
+	if (KVM_PREALLOC_LEVEL > 0)
+		kfree(pgd);
+}
 static inline bool kvm_page_empty(void *ptr)
 {
 	struct page *ptr_page = virt_to_page(ptr);
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:04 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:04 +0200
Subject: [PULL 11/29] kvm-arm: Use explicit stage2 helper routines
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-12-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

We have stage2 page table helpers for both arm and arm64. Switch to
the stage2 helpers for routines that only deal with stage2 page table.

Cc: Marc Zyngier <marc.zyngier at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm/kvm/mmu.c | 48 ++++++++++++++++++++++++------------------------
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index d0c0ee9..f93f717 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -319,9 +319,9 @@ static void stage2_flush_pmds(struct kvm *kvm, pud_t *pud,
 	pmd_t *pmd;
 	phys_addr_t next;
 
-	pmd = pmd_offset(pud, addr);
+	pmd = stage2_pmd_offset(pud, addr);
 	do {
-		next = kvm_pmd_addr_end(addr, end);
+		next = stage2_pmd_addr_end(addr, end);
 		if (!pmd_none(*pmd)) {
 			if (pmd_thp_or_huge(*pmd))
 				kvm_flush_dcache_pmd(*pmd);
@@ -337,11 +337,11 @@ static void stage2_flush_puds(struct kvm *kvm, pgd_t *pgd,
 	pud_t *pud;
 	phys_addr_t next;
 
-	pud = pud_offset(pgd, addr);
+	pud = stage2_pud_offset(pgd, addr);
 	do {
-		next = kvm_pud_addr_end(addr, end);
-		if (!pud_none(*pud)) {
-			if (pud_huge(*pud))
+		next = stage2_pud_addr_end(addr, end);
+		if (!stage2_pud_none(*pud)) {
+			if (stage2_pud_huge(*pud))
 				kvm_flush_dcache_pud(*pud);
 			else
 				stage2_flush_pmds(kvm, pud, addr, next);
@@ -357,9 +357,9 @@ static void stage2_flush_memslot(struct kvm *kvm,
 	phys_addr_t next;
 	pgd_t *pgd;
 
-	pgd = kvm->arch.pgd + kvm_pgd_index(addr);
+	pgd = kvm->arch.pgd + stage2_pgd_index(addr);
 	do {
-		next = kvm_pgd_addr_end(addr, end);
+		next = stage2_pgd_addr_end(addr, end);
 		stage2_flush_puds(kvm, pgd, addr, next);
 	} while (pgd++, addr = next, addr != end);
 }
@@ -807,16 +807,16 @@ static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache
 	pgd_t *pgd;
 	pud_t *pud;
 
-	pgd = kvm->arch.pgd + kvm_pgd_index(addr);
-	if (WARN_ON(pgd_none(*pgd))) {
+	pgd = kvm->arch.pgd + stage2_pgd_index(addr);
+	if (WARN_ON(stage2_pgd_none(*pgd))) {
 		if (!cache)
 			return NULL;
 		pud = mmu_memory_cache_alloc(cache);
-		pgd_populate(NULL, pgd, pud);
+		stage2_pgd_populate(pgd, pud);
 		get_page(virt_to_page(pgd));
 	}
 
-	return pud_offset(pgd, addr);
+	return stage2_pud_offset(pgd, addr);
 }
 
 static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
@@ -826,15 +826,15 @@ static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache
 	pmd_t *pmd;
 
 	pud = stage2_get_pud(kvm, cache, addr);
-	if (pud_none(*pud)) {
+	if (stage2_pud_none(*pud)) {
 		if (!cache)
 			return NULL;
 		pmd = mmu_memory_cache_alloc(cache);
-		pud_populate(NULL, pud, pmd);
+		stage2_pud_populate(pud, pmd);
 		get_page(virt_to_page(pud));
 	}
 
-	return pmd_offset(pud, addr);
+	return stage2_pmd_offset(pud, addr);
 }
 
 static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache
@@ -1042,10 +1042,10 @@ static void stage2_wp_pmds(pud_t *pud, phys_addr_t addr, phys_addr_t end)
 	pmd_t *pmd;
 	phys_addr_t next;
 
-	pmd = pmd_offset(pud, addr);
+	pmd = stage2_pmd_offset(pud, addr);
 
 	do {
-		next = kvm_pmd_addr_end(addr, end);
+		next = stage2_pmd_addr_end(addr, end);
 		if (!pmd_none(*pmd)) {
 			if (pmd_thp_or_huge(*pmd)) {
 				if (!kvm_s2pmd_readonly(pmd))
@@ -1070,12 +1070,12 @@ static void  stage2_wp_puds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end)
 	pud_t *pud;
 	phys_addr_t next;
 
-	pud = pud_offset(pgd, addr);
+	pud = stage2_pud_offset(pgd, addr);
 	do {
-		next = kvm_pud_addr_end(addr, end);
-		if (!pud_none(*pud)) {
+		next = stage2_pud_addr_end(addr, end);
+		if (!stage2_pud_none(*pud)) {
 			/* TODO:PUD not supported, revisit later if supported */
-			BUG_ON(pud_huge(*pud));
+			BUG_ON(stage2_pud_huge(*pud));
 			stage2_wp_pmds(pud, addr, next);
 		}
 	} while (pud++, addr = next, addr != end);
@@ -1092,7 +1092,7 @@ static void stage2_wp_range(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
 	pgd_t *pgd;
 	phys_addr_t next;
 
-	pgd = kvm->arch.pgd + kvm_pgd_index(addr);
+	pgd = kvm->arch.pgd + stage2_pgd_index(addr);
 	do {
 		/*
 		 * Release kvm_mmu_lock periodically if the memory region is
@@ -1104,8 +1104,8 @@ static void stage2_wp_range(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
 		if (need_resched() || spin_needbreak(&kvm->mmu_lock))
 			cond_resched_lock(&kvm->mmu_lock);
 
-		next = kvm_pgd_addr_end(addr, end);
-		if (pgd_present(*pgd))
+		next = stage2_pgd_addr_end(addr, end);
+		if (stage2_pgd_present(*pgd))
 			stage2_wp_puds(pgd, addr, next);
 	} while (pgd++, addr = next, addr != end);
 }
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:29:59 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:29:59 +0200
Subject: [PULL 06/29] kvm-arm: Remove kvm_pud_huge()
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-7-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Get rid of kvm_pud_huge() which falls back to pud_huge. Use
pud_huge instead.

Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm/kvm/mmu.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 7837f0a..d0c0ee9 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -45,8 +45,6 @@ static phys_addr_t hyp_idmap_vector;
 
 #define hyp_pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t))
 
-#define kvm_pud_huge(_x)	pud_huge(_x)
-
 #define KVM_S2PTE_FLAG_IS_IOMAP		(1UL << 0)
 #define KVM_S2_FLAG_LOGGING_ACTIVE	(1UL << 1)
 
@@ -1077,7 +1075,7 @@ static void  stage2_wp_puds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end)
 		next = kvm_pud_addr_end(addr, end);
 		if (!pud_none(*pud)) {
 			/* TODO:PUD not supported, revisit later if supported */
-			BUG_ON(kvm_pud_huge(*pud));
+			BUG_ON(pud_huge(*pud));
 			stage2_wp_pmds(pud, addr, next);
 		}
 	} while (pud++, addr = next, addr != end);
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:00 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:00 +0200
Subject: [PULL 07/29] kvm-arm: arm32: Introduce stage2 page table helpers
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-8-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Define the page table helpers for walking the stage2 pagetable
for arm. Since both hyp and stage2 have the same number of levels,
as that of the host we reuse the host helpers.

The exceptions are the p.d_addr_end routines which have to deal
with IPA > 32bit, hence we use the open coded version of their host helpers
which supports 64bit.

Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 arch/arm/include/asm/kvm_mmu.h        |  1 +
 arch/arm/include/asm/stage2_pgtable.h | 61 +++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)
 create mode 100644 arch/arm/include/asm/stage2_pgtable.h

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index c2b2b27..7d207b4 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -47,6 +47,7 @@
 #include <linux/highmem.h>
 #include <asm/cacheflush.h>
 #include <asm/pgalloc.h>
+#include <asm/stage2_pgtable.h>
 
 int create_hyp_mappings(void *from, void *to);
 int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
diff --git a/arch/arm/include/asm/stage2_pgtable.h b/arch/arm/include/asm/stage2_pgtable.h
new file mode 100644
index 0000000..460d616
--- /dev/null
+++ b/arch/arm/include/asm/stage2_pgtable.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 - ARM Ltd
+ *
+ * stage2 page table helpers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM_S2_PGTABLE_H_
+#define __ARM_S2_PGTABLE_H_
+
+#define stage2_pgd_none(pgd)			pgd_none(pgd)
+#define stage2_pgd_clear(pgd)			pgd_clear(pgd)
+#define stage2_pgd_present(pgd)			pgd_present(pgd)
+#define stage2_pgd_populate(pgd, pud)		pgd_populate(NULL, pgd, pud)
+#define stage2_pud_offset(pgd, address)		pud_offset(pgd, address)
+#define stage2_pud_free(pud)			pud_free(NULL, pud)
+
+#define stage2_pud_none(pud)			pud_none(pud)
+#define stage2_pud_clear(pud)			pud_clear(pud)
+#define stage2_pud_present(pud)			pud_present(pud)
+#define stage2_pud_populate(pud, pmd)		pud_populate(NULL, pud, pmd)
+#define stage2_pmd_offset(pud, address)		pmd_offset(pud, address)
+#define stage2_pmd_free(pmd)			pmd_free(NULL, pmd)
+
+#define stage2_pud_huge(pud)			pud_huge(pud)
+
+/* Open coded p*d_addr_end that can deal with 64bit addresses */
+static inline phys_addr_t stage2_pgd_addr_end(phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t boundary = (addr + PGDIR_SIZE) & PGDIR_MASK;
+
+	return (boundary - 1 < end - 1) ? boundary : end;
+}
+
+#define stage2_pud_addr_end(addr, end)		(end)
+
+static inline phys_addr_t stage2_pmd_addr_end(phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t boundary = (addr + PMD_SIZE) & PMD_MASK;
+
+	return (boundary - 1 < end - 1) ? boundary : end;
+}
+
+#define stage2_pgd_index(addr)				pgd_index(addr)
+
+#define stage2_pte_table_empty(ptep)			kvm_page_empty(ptep)
+#define stage2_pmd_table_empty(pmdp)			kvm_page_empty(pmdp)
+#define stage2_pud_table_empty(pudp)			false
+
+#endif	/* __ARM_S2_PGTABLE_H_ */
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:03 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:03 +0200
Subject: [PULL 10/29] kvm-arm: arm64: Introduce hyp page table empty checks
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-11-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Introduce hyp_pxx_table_empty helpers for checking whether
a given table entry is empty. This will be used explicitly
once we switch to explicit routines for hyp page table walk.

Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm64/include/asm/kvm_mmu.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index e3f53e3..edf3c62 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -249,6 +249,20 @@ static inline bool kvm_page_empty(void *ptr)
 #endif
 
 
+#define hyp_pte_table_empty(ptep) kvm_page_empty(ptep)
+
+#ifdef __PAGETABLE_PMD_FOLDED
+#define hyp_pmd_table_empty(pmdp) (0)
+#else
+#define hyp_pmd_table_empty(pmdp) kvm_page_empty(pmdp)
+#endif
+
+#ifdef __PAGETABLE_PUD_FOLDED
+#define hyp_pud_table_empty(pudp) (0)
+#else
+#define hyp_pud_table_empty(pudp) kvm_page_empty(pudp)
+#endif
+
 struct kvm;
 
 #define kvm_flush_dcache_to_poc(a,l)	__flush_dcache_area((a), (l))
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:01 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:01 +0200
Subject: [PULL 08/29] kvm-arm: arm: Introduce hyp page table empty checks
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-9-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Introduce hyp_pxx_table_empty helpers for checking whether
a given table entry is empty. This will be used explicitly
once we switch to explicit routines for hyp page table walk.

Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 arch/arm/include/asm/kvm_mmu.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 7d207b4..5522cdd 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -160,7 +160,11 @@ static inline bool kvm_page_empty(void *ptr)
 
 #define kvm_pte_table_empty(kvm, ptep) kvm_page_empty(ptep)
 #define kvm_pmd_table_empty(kvm, pmdp) kvm_page_empty(pmdp)
-#define kvm_pud_table_empty(kvm, pudp) (0)
+#define kvm_pud_table_empty(kvm, pudp) false
+
+#define hyp_pte_table_empty(ptep) kvm_page_empty(ptep)
+#define hyp_pmd_table_empty(pmdp) kvm_page_empty(pmdp)
+#define hyp_pud_table_empty(pudp) false
 
 static inline void *kvm_get_hwpgd(struct kvm *kvm)
 {
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:19 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:19 +0200
Subject: [PULL 26/29] KVM: arm/arm64: arch_timer: Rely on the arch timer to
 parse the firmware tables
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-27-git-send-email-christoffer.dall@linaro.org>

From: Julien Grall <julien.grall at arm.com>

The firmware table is currently parsed by the virtual timer code in
order to retrieve the virtual timer interrupt. However, this is already
done by the arch timer driver.

To avoid code duplication, use the newly function arch_timer_get_kvm_info()
which return all the information required by the virtual timer code.

Signed-off-by: Julien Grall <julien.grall at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/arch_timer.c | 40 +++++++++++-----------------------------
 1 file changed, 11 insertions(+), 29 deletions(-)

diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 9aaa35d..409db33 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -17,7 +17,6 @@
  */
 
 #include <linux/cpu.h>
-#include <linux/of_irq.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
@@ -438,45 +437,29 @@ static struct notifier_block kvm_timer_cpu_nb = {
 	.notifier_call = kvm_timer_cpu_notify,
 };
 
-static const struct of_device_id arch_timer_of_match[] = {
-	{ .compatible	= "arm,armv7-timer",	},
-	{ .compatible	= "arm,armv8-timer",	},
-	{},
-};
-
 int kvm_timer_hyp_init(void)
 {
-	struct device_node *np;
-	unsigned int ppi;
+	struct arch_timer_kvm_info *info;
 	int err;
 
-	timecounter = arch_timer_get_timecounter();
-	if (!timecounter)
-		return -ENODEV;
+	info = arch_timer_get_kvm_info();
+	timecounter = &info->timecounter;
 
-	np = of_find_matching_node(NULL, arch_timer_of_match);
-	if (!np) {
-		kvm_err("kvm_arch_timer: can't find DT node\n");
+	if (info->virtual_irq <= 0) {
+		kvm_err("kvm_arch_timer: invalid virtual timer IRQ: %d\n",
+			info->virtual_irq);
 		return -ENODEV;
 	}
+	host_vtimer_irq = info->virtual_irq;
 
-	ppi = irq_of_parse_and_map(np, 2);
-	if (!ppi) {
-		kvm_err("kvm_arch_timer: no virtual timer interrupt\n");
-		err = -EINVAL;
-		goto out;
-	}
-
-	err = request_percpu_irq(ppi, kvm_arch_timer_handler,
+	err = request_percpu_irq(host_vtimer_irq, kvm_arch_timer_handler,
 				 "kvm guest timer", kvm_get_running_vcpus());
 	if (err) {
 		kvm_err("kvm_arch_timer: can't request interrupt %d (%d)\n",
-			ppi, err);
+			host_vtimer_irq, err);
 		goto out;
 	}
 
-	host_vtimer_irq = ppi;
-
 	err = __register_cpu_notifier(&kvm_timer_cpu_nb);
 	if (err) {
 		kvm_err("Cannot register timer CPU notifier\n");
@@ -489,14 +472,13 @@ int kvm_timer_hyp_init(void)
 		goto out_free;
 	}
 
-	kvm_info("%s IRQ%d\n", np->name, ppi);
+	kvm_info("virtual timer IRQ%d\n", host_vtimer_irq);
 	on_each_cpu(kvm_timer_init_interrupt, NULL, 1);
 
 	goto out;
 out_free:
-	free_percpu_irq(ppi, kvm_get_running_vcpus());
+	free_percpu_irq(host_vtimer_irq, kvm_get_running_vcpus());
 out:
-	of_node_put(np);
 	return err;
 }
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:02 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:02 +0200
Subject: [PULL 09/29] kvm-arm: arm64: Introduce stage2 page table helpers
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-10-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Introduce stage2 page table helpers for arm64. With the fake
page table level still in place, the stage2 table has the same
number of levels as that of the host (and hyp), so they all
fallback to the host version.

Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm64/include/asm/kvm_mmu.h        | 29 +----------
 arch/arm64/include/asm/stage2_pgtable.h | 86 +++++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+), 27 deletions(-)
 create mode 100644 arch/arm64/include/asm/stage2_pgtable.h

diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 9a3409f..e3f53e3 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -91,6 +91,8 @@ alternative_endif
 #define KVM_PHYS_SIZE	(1UL << KVM_PHYS_SHIFT)
 #define KVM_PHYS_MASK	(KVM_PHYS_SIZE - 1UL)
 
+#include <asm/stage2_pgtable.h>
+
 int create_hyp_mappings(void *from, void *to);
 int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
 void free_boot_hyp_pgd(void);
@@ -156,35 +158,8 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
 #define kvm_pud_addr_end(addr, end)	pud_addr_end(addr, end)
 #define kvm_pmd_addr_end(addr, end)	pmd_addr_end(addr, end)
 
-/*
- * In the case where PGDIR_SHIFT is larger than KVM_PHYS_SHIFT, we can address
- * the entire IPA input range with a single pgd entry, and we would only need
- * one pgd entry.  Note that in this case, the pgd is actually not used by
- * the MMU for Stage-2 translations, but is merely a fake pgd used as a data
- * structure for the kernel pgtable macros to work.
- */
-#if PGDIR_SHIFT > KVM_PHYS_SHIFT
-#define PTRS_PER_S2_PGD_SHIFT	0
-#else
-#define PTRS_PER_S2_PGD_SHIFT	(KVM_PHYS_SHIFT - PGDIR_SHIFT)
-#endif
-#define PTRS_PER_S2_PGD		(1 << PTRS_PER_S2_PGD_SHIFT)
-
 #define kvm_pgd_index(addr)	(((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1))
 
-/*
- * If we are concatenating first level stage-2 page tables, we would have less
- * than or equal to 16 pointers in the fake PGD, because that's what the
- * architecture allows.  In this case, (4 - CONFIG_PGTABLE_LEVELS)
- * represents the first level for the host, and we add 1 to go to the next
- * level (which uses contatenation) for the stage-2 tables.
- */
-#if PTRS_PER_S2_PGD <= 16
-#define KVM_PREALLOC_LEVEL	(4 - CONFIG_PGTABLE_LEVELS + 1)
-#else
-#define KVM_PREALLOC_LEVEL	(0)
-#endif
-
 static inline void *kvm_get_hwpgd(struct kvm *kvm)
 {
 	pgd_t *pgd = kvm->arch.pgd;
diff --git a/arch/arm64/include/asm/stage2_pgtable.h b/arch/arm64/include/asm/stage2_pgtable.h
new file mode 100644
index 0000000..0ec218f
--- /dev/null
+++ b/arch/arm64/include/asm/stage2_pgtable.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 - ARM Ltd
+ *
+ * stage2 page table helpers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM64_S2_PGTABLE_H_
+#define __ARM64_S2_PGTABLE_H_
+
+#include <asm/pgtable.h>
+
+/*
+ * In the case where PGDIR_SHIFT is larger than KVM_PHYS_SHIFT, we can address
+ * the entire IPA input range with a single pgd entry, and we would only need
+ * one pgd entry.  Note that in this case, the pgd is actually not used by
+ * the MMU for Stage-2 translations, but is merely a fake pgd used as a data
+ * structure for the kernel pgtable macros to work.
+ */
+#if PGDIR_SHIFT > KVM_PHYS_SHIFT
+#define PTRS_PER_S2_PGD_SHIFT	0
+#else
+#define PTRS_PER_S2_PGD_SHIFT	(KVM_PHYS_SHIFT - PGDIR_SHIFT)
+#endif
+#define PTRS_PER_S2_PGD		(1 << PTRS_PER_S2_PGD_SHIFT)
+
+/*
+ * If we are concatenating first level stage-2 page tables, we would have less
+ * than or equal to 16 pointers in the fake PGD, because that's what the
+ * architecture allows.  In this case, (4 - CONFIG_PGTABLE_LEVELS)
+ * represents the first level for the host, and we add 1 to go to the next
+ * level (which uses contatenation) for the stage-2 tables.
+ */
+#if PTRS_PER_S2_PGD <= 16
+#define KVM_PREALLOC_LEVEL	(4 - CONFIG_PGTABLE_LEVELS + 1)
+#else
+#define KVM_PREALLOC_LEVEL	(0)
+#endif
+
+#define stage2_pgd_none(pgd)				pgd_none(pgd)
+#define stage2_pgd_clear(pgd)				pgd_clear(pgd)
+#define stage2_pgd_present(pgd)				pgd_present(pgd)
+#define stage2_pgd_populate(pgd, pud)			pgd_populate(NULL, pgd, pud)
+#define stage2_pud_offset(pgd, address)			pud_offset(pgd, address)
+#define stage2_pud_free(pud)				pud_free(NULL, pud)
+
+#define stage2_pud_none(pud)				pud_none(pud)
+#define stage2_pud_clear(pud)				pud_clear(pud)
+#define stage2_pud_present(pud)				pud_present(pud)
+#define stage2_pud_populate(pud, pmd)			pud_populate(NULL, pud, pmd)
+#define stage2_pmd_offset(pud, address)			pmd_offset(pud, address)
+#define stage2_pmd_free(pmd)				pmd_free(NULL, pmd)
+
+#define stage2_pud_huge(pud)				pud_huge(pud)
+
+#define stage2_pgd_addr_end(address, end)		pgd_addr_end(address, end)
+#define stage2_pud_addr_end(address, end)		pud_addr_end(address, end)
+#define stage2_pmd_addr_end(address, end)		pmd_addr_end(address, end)
+
+#define stage2_pte_table_empty(ptep)			kvm_page_empty(ptep)
+#ifdef __PGTABLE_PMD_FOLDED
+#define stage2_pmd_table_empty(pmdp)			(0)
+#else
+#define stage2_pmd_table_empty(pmdp)			((KVM_PREALLOC_LEVEL < 2) && kvm_page_empty(pmdp))
+#endif
+
+#ifdef __PGTABLE_PUD_FOLDED
+#define stage2_pud_table_empty(pudp)			(0)
+#else
+#define stage2_pud_table_empty(pudp)			((KVM_PREALLOC_LEVEL < 1) && kvm_page_empty(pudp))
+#endif
+
+#define stage2_pgd_index(addr)				(((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1))
+
+#endif	/* __ARM64_S2_PGTABLE_H_ */
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:07 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:07 +0200
Subject: [PULL 14/29] kvm-arm: Cleanup kvm_* wrappers
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-15-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Now that we have switched to explicit page table routines,
get rid of the obsolete kvm_* wrappers.

Also, kvm_tlb_flush_vmid_by_ipa is now called only on stage2
page tables, hence get rid of the redundant check.

Cc: Marc Zyngier <marc.zyngier at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm/include/asm/kvm_mmu.h   | 16 ----------------
 arch/arm/kvm/mmu.c               |  9 +--------
 arch/arm64/include/asm/kvm_mmu.h | 24 ------------------------
 3 files changed, 1 insertion(+), 48 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 5522cdd..a7736d5 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -136,22 +136,6 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
 	return (pmd_val(*pmd) & L_PMD_S2_RDWR) == L_PMD_S2_RDONLY;
 }
 
-
-/* Open coded p*d_addr_end that can deal with 64bit addresses */
-#define kvm_pgd_addr_end(addr, end)					\
-({	u64 __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK;		\
-	(__boundary - 1 < (end) - 1)? __boundary: (end);		\
-})
-
-#define kvm_pud_addr_end(addr,end)		(end)
-
-#define kvm_pmd_addr_end(addr, end)					\
-({	u64 __boundary = ((addr) + PMD_SIZE) & PMD_MASK;		\
-	(__boundary - 1 < (end) - 1)? __boundary: (end);		\
-})
-
-#define kvm_pgd_index(addr)			pgd_index(addr)
-
 static inline bool kvm_page_empty(void *ptr)
 {
 	struct page *ptr_page = virt_to_page(ptr);
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index f2a6d9b..d3fa96e 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -66,14 +66,7 @@ void kvm_flush_remote_tlbs(struct kvm *kvm)
 
 static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
 {
-	/*
-	 * This function also gets called when dealing with HYP page
-	 * tables. As HYP doesn't have an associated struct kvm (and
-	 * the HYP page tables are fairly static), we don't do
-	 * anything there.
-	 */
-	if (kvm)
-		kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa);
+	kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa);
 }
 
 /*
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index edf3c62..a3c0d05 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -153,13 +153,6 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
 	return (pmd_val(*pmd) & PMD_S2_RDWR) == PMD_S2_RDONLY;
 }
 
-
-#define kvm_pgd_addr_end(addr, end)	pgd_addr_end(addr, end)
-#define kvm_pud_addr_end(addr, end)	pud_addr_end(addr, end)
-#define kvm_pmd_addr_end(addr, end)	pmd_addr_end(addr, end)
-
-#define kvm_pgd_index(addr)	(((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1))
-
 static inline void *kvm_get_hwpgd(struct kvm *kvm)
 {
 	pgd_t *pgd = kvm->arch.pgd;
@@ -232,23 +225,6 @@ static inline bool kvm_page_empty(void *ptr)
 	return page_count(ptr_page) == 1;
 }
 
-#define kvm_pte_table_empty(kvm, ptep) kvm_page_empty(ptep)
-
-#ifdef __PAGETABLE_PMD_FOLDED
-#define kvm_pmd_table_empty(kvm, pmdp) (0)
-#else
-#define kvm_pmd_table_empty(kvm, pmdp) \
-	(kvm_page_empty(pmdp) && (!(kvm) || KVM_PREALLOC_LEVEL < 2))
-#endif
-
-#ifdef __PAGETABLE_PUD_FOLDED
-#define kvm_pud_table_empty(kvm, pudp) (0)
-#else
-#define kvm_pud_table_empty(kvm, pudp) \
-	(kvm_page_empty(pudp) && (!(kvm) || KVM_PREALLOC_LEVEL < 1))
-#endif
-
-
 #define hyp_pte_table_empty(ptep) kvm_page_empty(ptep)
 
 #ifdef __PAGETABLE_PMD_FOLDED
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:21 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:21 +0200
Subject: [PULL 28/29] clocksource: arm_arch_timer: Remove
 arch_timer_get_timecounter
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-29-git-send-email-christoffer.dall@linaro.org>

From: Julien Grall <julien.grall at arm.com>

The only call of arch_timer_get_timecounter (in KVM) has been removed.

Signed-off-by: Julien Grall <julien.grall at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 5 -----
 include/clocksource/arm_arch_timer.h | 6 ------
 2 files changed, 11 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index bb58224..4814446 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -475,11 +475,6 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
 	return &arch_timer_kvm_info;
 }
 
-struct timecounter *arch_timer_get_timecounter(void)
-{
-	return &arch_timer_kvm_info.timecounter;
-}
-
 static void __init arch_counter_register(unsigned type)
 {
 	u64 start_count;
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 9dd996a..caedb74 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -58,7 +58,6 @@ struct arch_timer_kvm_info {
 
 extern u32 arch_timer_get_rate(void);
 extern u64 (*arch_timer_read_counter)(void);
-extern struct timecounter *arch_timer_get_timecounter(void);
 extern struct arch_timer_kvm_info *arch_timer_get_kvm_info(void);
 
 #else
@@ -73,11 +72,6 @@ static inline u64 arch_timer_read_counter(void)
 	return 0;
 }
 
-static inline struct timecounter *arch_timer_get_timecounter(void)
-{
-	return NULL;
-}
-
 #endif
 
 #endif
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:20 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:20 +0200
Subject: [PULL 27/29] KVM: arm/arm64: vgic: Rely on the GIC driver to parse
 the firmware tables
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-28-git-send-email-christoffer.dall@linaro.org>

From: Julien Grall <julien.grall at arm.com>

Currently, the firmware tables are parsed 2 times: once in the GIC
drivers, the other time when initializing the vGIC. It means code
duplication and make more tedious to add the support for another
firmware table (like ACPI).

Use the recently introduced helper gic_get_kvm_info() to get
information about the virtual GIC.

With this change, the virtual GIC becomes agnostic to the firmware
table and KVM will be able to initialize the vGIC on ACPI.

Signed-off-by: Julien Grall <julien.grall at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/arm_vgic.h |  7 +++---
 virt/kvm/arm/vgic-v2.c | 61 +++++++++++++++++++++-----------------------------
 virt/kvm/arm/vgic-v3.c | 47 +++++++++++++-------------------------
 virt/kvm/arm/vgic.c    | 50 ++++++++++++++++++++++-------------------
 4 files changed, 73 insertions(+), 92 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 281caf8..be6037a 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -25,6 +25,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <kvm/iodev.h>
+#include <linux/irqchip/arm-gic-common.h>
 
 #define VGIC_NR_IRQS_LEGACY	256
 #define VGIC_NR_SGIS		16
@@ -353,15 +354,15 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
 #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
 #define vgic_ready(k)		((k)->arch.vgic.ready)
 
-int vgic_v2_probe(struct device_node *vgic_node,
+int vgic_v2_probe(const struct gic_kvm_info *gic_kvm_info,
 		  const struct vgic_ops **ops,
 		  const struct vgic_params **params);
 #ifdef CONFIG_KVM_ARM_VGIC_V3
-int vgic_v3_probe(struct device_node *vgic_node,
+int vgic_v3_probe(const struct gic_kvm_info *gic_kvm_info,
 		  const struct vgic_ops **ops,
 		  const struct vgic_params **params);
 #else
-static inline int vgic_v3_probe(struct device_node *vgic_node,
+static inline int vgic_v3_probe(const struct gic_kvm_info *gic_kvm_info,
 				const struct vgic_ops **ops,
 				const struct vgic_params **params)
 {
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
index 67ec334..7e826c9 100644
--- a/virt/kvm/arm/vgic-v2.c
+++ b/virt/kvm/arm/vgic-v2.c
@@ -20,9 +20,6 @@
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
 
 #include <linux/irqchip/arm-gic.h>
 
@@ -186,38 +183,39 @@ static void vgic_cpu_init_lrs(void *params)
 }
 
 /**
- * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
- * @node:	pointer to the DT node
- * @ops: 	address of a pointer to the GICv2 operations
- * @params:	address of a pointer to HW-specific parameters
+ * vgic_v2_probe - probe for a GICv2 compatible interrupt controller
+ * @gic_kvm_info:	pointer to the GIC description
+ * @ops:		address of a pointer to the GICv2 operations
+ * @params:		address of a pointer to HW-specific parameters
  *
  * Returns 0 if a GICv2 has been found, with the low level operations
  * in *ops and the HW parameters in *params. Returns an error code
  * otherwise.
  */
-int vgic_v2_probe(struct device_node *vgic_node,
-		  const struct vgic_ops **ops,
-		  const struct vgic_params **params)
+int vgic_v2_probe(const struct gic_kvm_info *gic_kvm_info,
+		   const struct vgic_ops **ops,
+		   const struct vgic_params **params)
 {
 	int ret;
-	struct resource vctrl_res;
-	struct resource vcpu_res;
 	struct vgic_params *vgic = &vgic_v2_params;
+	const struct resource *vctrl_res = &gic_kvm_info->vctrl;
+	const struct resource *vcpu_res = &gic_kvm_info->vcpu;
 
-	vgic->maint_irq = irq_of_parse_and_map(vgic_node, 0);
-	if (!vgic->maint_irq) {
-		kvm_err("error getting vgic maintenance irq from DT\n");
+	if (!gic_kvm_info->maint_irq) {
+		kvm_err("error getting vgic maintenance irq\n");
 		ret = -ENXIO;
 		goto out;
 	}
+	vgic->maint_irq = gic_kvm_info->maint_irq;
 
-	ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
-	if (ret) {
-		kvm_err("Cannot obtain GICH resource\n");
+	if (!gic_kvm_info->vctrl.start) {
+		kvm_err("GICH not present in the firmware table\n");
+		ret = -ENXIO;
 		goto out;
 	}
 
-	vgic->vctrl_base = of_iomap(vgic_node, 2);
+	vgic->vctrl_base = ioremap(gic_kvm_info->vctrl.start,
+				   resource_size(&gic_kvm_info->vctrl));
 	if (!vgic->vctrl_base) {
 		kvm_err("Cannot ioremap GICH\n");
 		ret = -ENOMEM;
@@ -228,29 +226,23 @@ int vgic_v2_probe(struct device_node *vgic_node,
 	vgic->nr_lr = (vgic->nr_lr & 0x3f) + 1;
 
 	ret = create_hyp_io_mappings(vgic->vctrl_base,
-				     vgic->vctrl_base + resource_size(&vctrl_res),
-				     vctrl_res.start);
+				     vgic->vctrl_base + resource_size(vctrl_res),
+				     vctrl_res->start);
 	if (ret) {
 		kvm_err("Cannot map VCTRL into hyp\n");
 		goto out_unmap;
 	}
 
-	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
-		kvm_err("Cannot obtain GICV resource\n");
-		ret = -ENXIO;
-		goto out_unmap;
-	}
-
-	if (!PAGE_ALIGNED(vcpu_res.start)) {
+	if (!PAGE_ALIGNED(vcpu_res->start)) {
 		kvm_err("GICV physical address 0x%llx not page aligned\n",
-			(unsigned long long)vcpu_res.start);
+			(unsigned long long)vcpu_res->start);
 		ret = -ENXIO;
 		goto out_unmap;
 	}
 
-	if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
+	if (!PAGE_ALIGNED(resource_size(vcpu_res))) {
 		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
-			(unsigned long long)resource_size(&vcpu_res),
+			(unsigned long long)resource_size(vcpu_res),
 			PAGE_SIZE);
 		ret = -ENXIO;
 		goto out_unmap;
@@ -259,10 +251,10 @@ int vgic_v2_probe(struct device_node *vgic_node,
 	vgic->can_emulate_gicv2 = true;
 	kvm_register_device_ops(&kvm_arm_vgic_v2_ops, KVM_DEV_TYPE_ARM_VGIC_V2);
 
-	vgic->vcpu_base = vcpu_res.start;
+	vgic->vcpu_base = vcpu_res->start;
 
-	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
-		 vctrl_res.start, vgic->maint_irq);
+	kvm_info("GICH base=0x%llx, GICV base=0x%llx, IRQ=%d\n",
+		 gic_kvm_info->vctrl.start, vgic->vcpu_base, vgic->maint_irq);
 
 	vgic->type = VGIC_V2;
 	vgic->max_gic_vcpus = VGIC_V2_MAX_CPUS;
@@ -276,6 +268,5 @@ int vgic_v2_probe(struct device_node *vgic_node,
 out_unmap:
 	iounmap(vgic->vctrl_base);
 out:
-	of_node_put(vgic_node);
 	return ret;
 }
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index 999bdc6..c02a1b1 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -20,11 +20,9 @@
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
 
 #include <linux/irqchip/arm-gic-v3.h>
+#include <linux/irqchip/arm-gic-common.h>
 
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_arm.h>
@@ -222,30 +220,24 @@ static void vgic_cpu_init_lrs(void *params)
 }
 
 /**
- * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
- * @node:	pointer to the DT node
- * @ops: 	address of a pointer to the GICv3 operations
- * @params:	address of a pointer to HW-specific parameters
+ * vgic_v3_probe - probe for a GICv3 compatible interrupt controller
+ * @gic_kvm_info:	pointer to the GIC description
+ * @ops:		address of a pointer to the GICv3 operations
+ * @params:		address of a pointer to HW-specific parameters
  *
  * Returns 0 if a GICv3 has been found, with the low level operations
  * in *ops and the HW parameters in *params. Returns an error code
  * otherwise.
  */
-int vgic_v3_probe(struct device_node *vgic_node,
+int vgic_v3_probe(const struct gic_kvm_info *gic_kvm_info,
 		  const struct vgic_ops **ops,
 		  const struct vgic_params **params)
 {
 	int ret = 0;
-	u32 gicv_idx;
-	struct resource vcpu_res;
 	struct vgic_params *vgic = &vgic_v3_params;
+	const struct resource *vcpu_res = &gic_kvm_info->vcpu;
 
-	vgic->maint_irq = irq_of_parse_and_map(vgic_node, 0);
-	if (!vgic->maint_irq) {
-		kvm_err("error getting vgic maintenance irq from DT\n");
-		ret = -ENXIO;
-		goto out;
-	}
+	vgic->maint_irq = gic_kvm_info->maint_irq;
 
 	ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
 
@@ -256,24 +248,19 @@ int vgic_v3_probe(struct device_node *vgic_node,
 	vgic->nr_lr = (ich_vtr_el2 & 0xf) + 1;
 	vgic->can_emulate_gicv2 = false;
 
-	if (of_property_read_u32(vgic_node, "#redistributor-regions", &gicv_idx))
-		gicv_idx = 1;
-
-	gicv_idx += 3; /* Also skip GICD, GICC, GICH */
-	if (of_address_to_resource(vgic_node, gicv_idx, &vcpu_res)) {
+	if (!vcpu_res->start) {
 		kvm_info("GICv3: no GICV resource entry\n");
 		vgic->vcpu_base = 0;
-	} else if (!PAGE_ALIGNED(vcpu_res.start)) {
+	} else if (!PAGE_ALIGNED(vcpu_res->start)) {
 		pr_warn("GICV physical address 0x%llx not page aligned\n",
-			(unsigned long long)vcpu_res.start);
+			(unsigned long long)vcpu_res->start);
 		vgic->vcpu_base = 0;
-	} else if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
+	} else if (!PAGE_ALIGNED(resource_size(vcpu_res))) {
 		pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
-			(unsigned long long)resource_size(&vcpu_res),
+			(unsigned long long)resource_size(vcpu_res),
 			PAGE_SIZE);
-		vgic->vcpu_base = 0;
 	} else {
-		vgic->vcpu_base = vcpu_res.start;
+		vgic->vcpu_base = vcpu_res->start;
 		vgic->can_emulate_gicv2 = true;
 		kvm_register_device_ops(&kvm_arm_vgic_v2_ops,
 					KVM_DEV_TYPE_ARM_VGIC_V2);
@@ -286,15 +273,13 @@ int vgic_v3_probe(struct device_node *vgic_node,
 	vgic->type = VGIC_V3;
 	vgic->max_gic_vcpus = VGIC_V3_MAX_CPUS;
 
-	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
-		 vcpu_res.start, vgic->maint_irq);
+	kvm_info("GICV base=0x%llx, IRQ=%d\n",
+		 vgic->vcpu_base, vgic->maint_irq);
 
 	on_each_cpu(vgic_cpu_init_lrs, vgic, 1);
 
 	*ops = &vgic_v3_ops;
 	*params = vgic;
 
-out:
-	of_node_put(vgic_node);
 	return ret;
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 00429b3..60668a7 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -21,9 +21,7 @@
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
+#include <linux/irq.h>
 #include <linux/rculist.h>
 #include <linux/uaccess.h>
 
@@ -33,6 +31,7 @@
 #include <trace/events/kvm.h>
 #include <asm/kvm.h>
 #include <kvm/iodev.h>
+#include <linux/irqchip/arm-gic-common.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -2389,33 +2388,38 @@ static struct notifier_block vgic_cpu_nb = {
 	.notifier_call = vgic_cpu_notify,
 };
 
-static const struct of_device_id vgic_ids[] = {
-	{ .compatible = "arm,cortex-a15-gic",	.data = vgic_v2_probe, },
-	{ .compatible = "arm,cortex-a7-gic",	.data = vgic_v2_probe, },
-	{ .compatible = "arm,gic-400",		.data = vgic_v2_probe, },
-	{ .compatible = "arm,gic-v3",		.data = vgic_v3_probe, },
-	{},
-};
-
-int kvm_vgic_hyp_init(void)
+static int kvm_vgic_probe(void)
 {
-	const struct of_device_id *matched_id;
-	const int (*vgic_probe)(struct device_node *,const struct vgic_ops **,
-				const struct vgic_params **);
-	struct device_node *vgic_node;
+	const struct gic_kvm_info *gic_kvm_info;
 	int ret;
 
-	vgic_node = of_find_matching_node_and_match(NULL,
-						    vgic_ids, &matched_id);
-	if (!vgic_node) {
-		kvm_err("error: no compatible GIC node found\n");
+	gic_kvm_info = gic_get_kvm_info();
+	if (!gic_kvm_info)
 		return -ENODEV;
+
+	switch (gic_kvm_info->type) {
+	case GIC_V2:
+		ret = vgic_v2_probe(gic_kvm_info, &vgic_ops, &vgic);
+		break;
+	case GIC_V3:
+		ret = vgic_v3_probe(gic_kvm_info, &vgic_ops, &vgic);
+		break;
+	default:
+		ret = -ENODEV;
 	}
 
-	vgic_probe = matched_id->data;
-	ret = vgic_probe(vgic_node, &vgic_ops, &vgic);
-	if (ret)
+	return ret;
+}
+
+int kvm_vgic_hyp_init(void)
+{
+	int ret;
+
+	ret = kvm_vgic_probe();
+	if (ret) {
+		kvm_err("error: KVM vGIC probing failed\n");
 		return ret;
+	}
 
 	ret = request_percpu_irq(vgic->maint_irq, vgic_maintenance_handler,
 				 "vgic", kvm_get_running_vcpus());
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:22 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:22 +0200
Subject: [PULL 29/29] kvm: arm64: Enable hardware updates of the Access Flag
 for Stage 2 page tables
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-30-git-send-email-christoffer.dall@linaro.org>

From: Catalin Marinas <catalin.marinas at arm.com>

The ARMv8.1 architecture extensions introduce support for hardware
updates of the access and dirty information in page table entries. With
VTCR_EL2.HA enabled (bit 21), when the CPU accesses an IPA with the
PTE_AF bit cleared in the stage 2 page table, instead of raising an
Access Flag fault to EL2 the CPU sets the actual page table entry bit
(10). To ensure that kernel modifications to the page table do not
inadvertently revert a bit set by hardware updates, certain Stage 2
software pte/pmd operations must be performed atomically.

The main user of the AF bit is the kvm_age_hva() mechanism. The
kvm_age_hva_handler() function performs a "test and clear young" action
on the pte/pmd. This needs to be atomic in respect of automatic hardware
updates of the AF bit. Since the AF bit is in the same position for both
Stage 1 and Stage 2, the patch reuses the existing
ptep_test_and_clear_young() functionality if
__HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG is defined. Otherwise, the
existing pte_young/pte_mkold mechanism is preserved.

The kvm_set_s2pte_readonly() (and the corresponding pmd equivalent) have
to perform atomic modifications in order to avoid a race with updates of
the AF bit. The arm64 implementation has been re-written using
exclusives.

Currently, kvm_set_s2pte_writable() (and pmd equivalent) take a pointer
argument and modify the pte/pmd in place. However, these functions are
only used on local variables rather than actual page table entries, so
it makes more sense to follow the pte_mkwrite() approach for stage 1
attributes. The change to kvm_s2pte_mkwrite() makes it clear that these
functions do not modify the actual page table entries.

The (pte|pmd)_mkyoung() uses on Stage 2 entries (setting the AF bit
explicitly) do not need to be modified since hardware updates of the
dirty status are not supported by KVM, so there is no possibility of
losing such information.

Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
Cc: Paolo Bonzini <pbonzini at redhat.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 arch/arm/include/asm/kvm_mmu.h   | 10 +++++----
 arch/arm/kvm/mmu.c               | 46 +++++++++++++++++++++++++---------------
 arch/arm64/include/asm/kvm_arm.h |  2 ++
 arch/arm64/include/asm/kvm_mmu.h | 27 +++++++++++++++++------
 arch/arm64/include/asm/pgtable.h | 13 ++++++++----
 arch/arm64/kvm/hyp/s2-setup.c    |  8 +++++++
 6 files changed, 74 insertions(+), 32 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 6344ea0..ef0b276 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -106,14 +106,16 @@ static inline void kvm_clean_pte(pte_t *pte)
 	clean_pte_table(pte);
 }
 
-static inline void kvm_set_s2pte_writable(pte_t *pte)
+static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
 {
-	pte_val(*pte) |= L_PTE_S2_RDWR;
+	pte_val(pte) |= L_PTE_S2_RDWR;
+	return pte;
 }
 
-static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
+static inline pmd_t kvm_s2pmd_mkwrite(pmd_t pmd)
 {
-	pmd_val(*pmd) |= L_PMD_S2_RDWR;
+	pmd_val(pmd) |= L_PMD_S2_RDWR;
+	return pmd;
 }
 
 static inline void kvm_set_s2pte_readonly(pte_t *pte)
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 74b5d19..783e5ff 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -977,6 +977,27 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
 	return 0;
 }
 
+#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+static int stage2_ptep_test_and_clear_young(pte_t *pte)
+{
+	if (pte_young(*pte)) {
+		*pte = pte_mkold(*pte);
+		return 1;
+	}
+	return 0;
+}
+#else
+static int stage2_ptep_test_and_clear_young(pte_t *pte)
+{
+	return __ptep_test_and_clear_young(pte);
+}
+#endif
+
+static int stage2_pmdp_test_and_clear_young(pmd_t *pmd)
+{
+	return stage2_ptep_test_and_clear_young((pte_t *)pmd);
+}
+
 /**
  * kvm_phys_addr_ioremap - map a device range to guest IPA
  *
@@ -1000,7 +1021,7 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
 		pte_t pte = pfn_pte(pfn, PAGE_S2_DEVICE);
 
 		if (writable)
-			kvm_set_s2pte_writable(&pte);
+			pte = kvm_s2pte_mkwrite(pte);
 
 		ret = mmu_topup_memory_cache(&cache, KVM_MMU_CACHE_MIN_PAGES,
 						KVM_NR_MEM_OBJS);
@@ -1342,7 +1363,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 		pmd_t new_pmd = pfn_pmd(pfn, mem_type);
 		new_pmd = pmd_mkhuge(new_pmd);
 		if (writable) {
-			kvm_set_s2pmd_writable(&new_pmd);
+			new_pmd = kvm_s2pmd_mkwrite(new_pmd);
 			kvm_set_pfn_dirty(pfn);
 		}
 		coherent_cache_guest_page(vcpu, pfn, PMD_SIZE, fault_ipa_uncached);
@@ -1351,7 +1372,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 		pte_t new_pte = pfn_pte(pfn, mem_type);
 
 		if (writable) {
-			kvm_set_s2pte_writable(&new_pte);
+			new_pte = kvm_s2pte_mkwrite(new_pte);
 			kvm_set_pfn_dirty(pfn);
 			mark_page_dirty(kvm, gfn);
 		}
@@ -1370,6 +1391,8 @@ out_unlock:
  * Resolve the access fault by making the page young again.
  * Note that because the faulting entry is guaranteed not to be
  * cached in the TLB, we don't need to invalidate anything.
+ * Only the HW Access Flag updates are supported for Stage 2 (no DBM),
+ * so there is no need for atomic (pte|pmd)_mkyoung operations.
  */
 static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
 {
@@ -1610,25 +1633,14 @@ static int kvm_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
 	if (!pmd || pmd_none(*pmd))	/* Nothing there */
 		return 0;
 
-	if (pmd_thp_or_huge(*pmd)) {	/* THP, HugeTLB */
-		if (pmd_young(*pmd)) {
-			*pmd = pmd_mkold(*pmd);
-			return 1;
-		}
-
-		return 0;
-	}
+	if (pmd_thp_or_huge(*pmd))	/* THP, HugeTLB */
+		return stage2_pmdp_test_and_clear_young(pmd);
 
 	pte = pte_offset_kernel(pmd, gpa);
 	if (pte_none(*pte))
 		return 0;
 
-	if (pte_young(*pte)) {
-		*pte = pte_mkold(*pte);	/* Just a page... */
-		return 1;
-	}
-
-	return 0;
+	return stage2_ptep_test_and_clear_young(pte);
 }
 
 static int kvm_test_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index c6cbb36..ffde15f 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -111,6 +111,8 @@
 
 /* VTCR_EL2 Registers bits */
 #define VTCR_EL2_RES1		(1 << 31)
+#define VTCR_EL2_HD		(1 << 22)
+#define VTCR_EL2_HA		(1 << 21)
 #define VTCR_EL2_PS_MASK	TCR_EL2_PS_MASK
 #define VTCR_EL2_TG0_MASK	TCR_TG0_MASK
 #define VTCR_EL2_TG0_4K		TCR_TG0_4K
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 249c4fc..844fe5d 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -111,19 +111,32 @@ static inline void kvm_clean_pmd_entry(pmd_t *pmd) {}
 static inline void kvm_clean_pte(pte_t *pte) {}
 static inline void kvm_clean_pte_entry(pte_t *pte) {}
 
-static inline void kvm_set_s2pte_writable(pte_t *pte)
+static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
 {
-	pte_val(*pte) |= PTE_S2_RDWR;
+	pte_val(pte) |= PTE_S2_RDWR;
+	return pte;
 }
 
-static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
+static inline pmd_t kvm_s2pmd_mkwrite(pmd_t pmd)
 {
-	pmd_val(*pmd) |= PMD_S2_RDWR;
+	pmd_val(pmd) |= PMD_S2_RDWR;
+	return pmd;
 }
 
 static inline void kvm_set_s2pte_readonly(pte_t *pte)
 {
-	pte_val(*pte) = (pte_val(*pte) & ~PTE_S2_RDWR) | PTE_S2_RDONLY;
+	pteval_t pteval;
+	unsigned long tmp;
+
+	asm volatile("//	kvm_set_s2pte_readonly\n"
+	"	prfm	pstl1strm, %2\n"
+	"1:	ldxr	%0, %2\n"
+	"	and	%0, %0, %3		// clear PTE_S2_RDWR\n"
+	"	orr	%0, %0, %4		// set PTE_S2_RDONLY\n"
+	"	stxr	%w1, %0, %2\n"
+	"	cbnz	%w1, 1b\n"
+	: "=&r" (pteval), "=&r" (tmp), "+Q" (pte_val(*pte))
+	: "L" (~PTE_S2_RDWR), "L" (PTE_S2_RDONLY));
 }
 
 static inline bool kvm_s2pte_readonly(pte_t *pte)
@@ -133,12 +146,12 @@ static inline bool kvm_s2pte_readonly(pte_t *pte)
 
 static inline void kvm_set_s2pmd_readonly(pmd_t *pmd)
 {
-	pmd_val(*pmd) = (pmd_val(*pmd) & ~PMD_S2_RDWR) | PMD_S2_RDONLY;
+	kvm_set_s2pte_readonly((pte_t *)pmd);
 }
 
 static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
 {
-	return (pmd_val(*pmd) & PMD_S2_RDWR) == PMD_S2_RDONLY;
+	return kvm_s2pte_readonly((pte_t *)pmd);
 }
 
 static inline bool kvm_page_empty(void *ptr)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index dda4aa9..f1d5afd 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -532,14 +532,12 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
  * Atomic pte/pmd modifications.
  */
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
-					    unsigned long address,
-					    pte_t *ptep)
+static inline int __ptep_test_and_clear_young(pte_t *ptep)
 {
 	pteval_t pteval;
 	unsigned int tmp, res;
 
-	asm volatile("//	ptep_test_and_clear_young\n"
+	asm volatile("//	__ptep_test_and_clear_young\n"
 	"	prfm	pstl1strm, %2\n"
 	"1:	ldxr	%0, %2\n"
 	"	ubfx	%w3, %w0, %5, #1	// extract PTE_AF (young)\n"
@@ -552,6 +550,13 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
 	return res;
 }
 
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
+					    unsigned long address,
+					    pte_t *ptep)
+{
+	return __ptep_test_and_clear_young(ptep);
+}
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 #define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
 static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
diff --git a/arch/arm64/kvm/hyp/s2-setup.c b/arch/arm64/kvm/hyp/s2-setup.c
index bcbe761..b81f409 100644
--- a/arch/arm64/kvm/hyp/s2-setup.c
+++ b/arch/arm64/kvm/hyp/s2-setup.c
@@ -66,6 +66,14 @@ u32 __hyp_text __init_stage2_translation(void)
 	val |= 64 - (parange > 40 ? 40 : parange);
 
 	/*
+	 * Check the availability of Hardware Access Flag / Dirty Bit
+	 * Management in ID_AA64MMFR1_EL1 and enable the feature in VTCR_EL2.
+	 */
+	tmp = (read_sysreg(id_aa64mmfr1_el1) >> ID_AA64MMFR1_HADBS_SHIFT) & 0xf;
+	if (IS_ENABLED(CONFIG_ARM64_HW_AFDBM) && tmp)
+		val |= VTCR_EL2_HA;
+
+	/*
 	 * Read the VMIDBits bits from ID_AA64MMFR1_EL1 and set the VS
 	 * bit in VTCR_EL2.
 	 */
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:06 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:06 +0200
Subject: [PULL 13/29] kvm-arm: Add stage2 page table modifiers
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-14-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Now that the hyp page table is handled by different set of
routines, rename the original shared routines to stage2 handlers.
Also make explicit use of the stage2 page table helpers.

unmap_range has been merged to existing unmap_stage2_range.

Cc: Marc Zyngier <marc.zyngier at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm/kvm/mmu.c | 97 +++++++++++++++++++++++++-----------------------------
 1 file changed, 44 insertions(+), 53 deletions(-)

diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index af526f6..f2a6d9b 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -152,26 +152,26 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc)
 	return p;
 }
 
-static void clear_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr)
+static void clear_stage2_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr)
 {
-	pud_t *pud_table __maybe_unused = pud_offset(pgd, 0);
-	pgd_clear(pgd);
+	pud_t *pud_table __maybe_unused = stage2_pud_offset(pgd, 0UL);
+	stage2_pgd_clear(pgd);
 	kvm_tlb_flush_vmid_ipa(kvm, addr);
-	pud_free(NULL, pud_table);
+	stage2_pud_free(pud_table);
 	put_page(virt_to_page(pgd));
 }
 
-static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
+static void clear_stage2_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
 {
-	pmd_t *pmd_table = pmd_offset(pud, 0);
-	VM_BUG_ON(pud_huge(*pud));
-	pud_clear(pud);
+	pmd_t *pmd_table __maybe_unused = stage2_pmd_offset(pud, 0);
+	VM_BUG_ON(stage2_pud_huge(*pud));
+	stage2_pud_clear(pud);
 	kvm_tlb_flush_vmid_ipa(kvm, addr);
-	pmd_free(NULL, pmd_table);
+	stage2_pmd_free(pmd_table);
 	put_page(virt_to_page(pud));
 }
 
-static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
+static void clear_stage2_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
 {
 	pte_t *pte_table = pte_offset_kernel(pmd, 0);
 	VM_BUG_ON(pmd_thp_or_huge(*pmd));
@@ -201,7 +201,7 @@ static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
  * the corresponding TLBs, we call kvm_flush_dcache_p*() to make sure
  * the IO subsystem will never hit in the cache.
  */
-static void unmap_ptes(struct kvm *kvm, pmd_t *pmd,
+static void unmap_stage2_ptes(struct kvm *kvm, pmd_t *pmd,
 		       phys_addr_t addr, phys_addr_t end)
 {
 	phys_addr_t start_addr = addr;
@@ -223,19 +223,19 @@ static void unmap_ptes(struct kvm *kvm, pmd_t *pmd,
 		}
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 
-	if (kvm_pte_table_empty(kvm, start_pte))
-		clear_pmd_entry(kvm, pmd, start_addr);
+	if (stage2_pte_table_empty(start_pte))
+		clear_stage2_pmd_entry(kvm, pmd, start_addr);
 }
 
-static void unmap_pmds(struct kvm *kvm, pud_t *pud,
+static void unmap_stage2_pmds(struct kvm *kvm, pud_t *pud,
 		       phys_addr_t addr, phys_addr_t end)
 {
 	phys_addr_t next, start_addr = addr;
 	pmd_t *pmd, *start_pmd;
 
-	start_pmd = pmd = pmd_offset(pud, addr);
+	start_pmd = pmd = stage2_pmd_offset(pud, addr);
 	do {
-		next = kvm_pmd_addr_end(addr, end);
+		next = stage2_pmd_addr_end(addr, end);
 		if (!pmd_none(*pmd)) {
 			if (pmd_thp_or_huge(*pmd)) {
 				pmd_t old_pmd = *pmd;
@@ -247,57 +247,64 @@ static void unmap_pmds(struct kvm *kvm, pud_t *pud,
 
 				put_page(virt_to_page(pmd));
 			} else {
-				unmap_ptes(kvm, pmd, addr, next);
+				unmap_stage2_ptes(kvm, pmd, addr, next);
 			}
 		}
 	} while (pmd++, addr = next, addr != end);
 
-	if (kvm_pmd_table_empty(kvm, start_pmd))
-		clear_pud_entry(kvm, pud, start_addr);
+	if (stage2_pmd_table_empty(start_pmd))
+		clear_stage2_pud_entry(kvm, pud, start_addr);
 }
 
-static void unmap_puds(struct kvm *kvm, pgd_t *pgd,
+static void unmap_stage2_puds(struct kvm *kvm, pgd_t *pgd,
 		       phys_addr_t addr, phys_addr_t end)
 {
 	phys_addr_t next, start_addr = addr;
 	pud_t *pud, *start_pud;
 
-	start_pud = pud = pud_offset(pgd, addr);
+	start_pud = pud = stage2_pud_offset(pgd, addr);
 	do {
-		next = kvm_pud_addr_end(addr, end);
-		if (!pud_none(*pud)) {
-			if (pud_huge(*pud)) {
+		next = stage2_pud_addr_end(addr, end);
+		if (!stage2_pud_none(*pud)) {
+			if (stage2_pud_huge(*pud)) {
 				pud_t old_pud = *pud;
 
-				pud_clear(pud);
+				stage2_pud_clear(pud);
 				kvm_tlb_flush_vmid_ipa(kvm, addr);
-
 				kvm_flush_dcache_pud(old_pud);
-
 				put_page(virt_to_page(pud));
 			} else {
-				unmap_pmds(kvm, pud, addr, next);
+				unmap_stage2_pmds(kvm, pud, addr, next);
 			}
 		}
 	} while (pud++, addr = next, addr != end);
 
-	if (kvm_pud_table_empty(kvm, start_pud))
-		clear_pgd_entry(kvm, pgd, start_addr);
+	if (stage2_pud_table_empty(start_pud))
+		clear_stage2_pgd_entry(kvm, pgd, start_addr);
 }
 
-
-static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
-			phys_addr_t start, u64 size)
+/**
+ * unmap_stage2_range -- Clear stage2 page table entries to unmap a range
+ * @kvm:   The VM pointer
+ * @start: The intermediate physical base address of the range to unmap
+ * @size:  The size of the area to unmap
+ *
+ * Clear a range of stage-2 mappings, lowering the various ref-counts.  Must
+ * be called while holding mmu_lock (unless for freeing the stage2 pgd before
+ * destroying the VM), otherwise another faulting VCPU may come in and mess
+ * with things behind our backs.
+ */
+static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
 {
 	pgd_t *pgd;
 	phys_addr_t addr = start, end = start + size;
 	phys_addr_t next;
 
-	pgd = pgdp + kvm_pgd_index(addr);
+	pgd = kvm->arch.pgd + stage2_pgd_index(addr);
 	do {
-		next = kvm_pgd_addr_end(addr, end);
-		if (!pgd_none(*pgd))
-			unmap_puds(kvm, pgd, addr, next);
+		next = stage2_pgd_addr_end(addr, end);
+		if (!stage2_pgd_none(*pgd))
+			unmap_stage2_puds(kvm, pgd, addr, next);
 	} while (pgd++, addr = next, addr != end);
 }
 
@@ -792,22 +799,6 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm)
 	return 0;
 }
 
-/**
- * unmap_stage2_range -- Clear stage2 page table entries to unmap a range
- * @kvm:   The VM pointer
- * @start: The intermediate physical base address of the range to unmap
- * @size:  The size of the area to unmap
- *
- * Clear a range of stage-2 mappings, lowering the various ref-counts.  Must
- * be called while holding mmu_lock (unless for freeing the stage2 pgd before
- * destroying the VM), otherwise another faulting VCPU may come in and mess
- * with things behind our backs.
- */
-static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
-{
-	unmap_range(kvm, kvm->arch.pgd, start, size);
-}
-
 static void stage2_unmap_memslot(struct kvm *kvm,
 				 struct kvm_memory_slot *memslot)
 {
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:08 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:08 +0200
Subject: [PULL 15/29] kvm: arm64: Get rid of fake page table levels
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-16-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

On arm64, the hardware supports concatenation of upto 16 tables,
at entry level for stage2 translations and we make use that whenever
possible. This could lead to reduced number of translation levels than
the normal (stage1 table) table. Also, since the IPA(40bit) is smaller
than the some of the supported VA_BITS (e.g, 48bit), there could be
different number of levels in stage-1 vs stage-2 tables. To reuse the
kernel host page table walker for stage2 we have been using a fake
software page table level, not known to the hardware. But with 16K
translations, there could be upto 2 fake software levels (with 48bit VA
and 40bit IPA), which complicates the code. Hence, we want to get rid of
the hack.

Now that we have explicit accessors for hyp vs stage2 page tables,
define the stage2 walker helpers accordingly based on the actual
table used by the hardware.

Once we know the number of translation levels used by the hardware,
it is merely a job of defining the helpers based on whether a
particular level is folded or not, looking at the number of levels.

Some facts before we calculate the translation levels:

1) Smallest page size supported by arm64 is 4K.
2) The minimum number of bits resolved at any page table level
   is (PAGE_SHIFT - 3) at intermediate levels.
Both of them implies, minimum number of bits required for a level
change is 9.

Since we can concatenate upto 16 tables at stage2 entry, the total
number of page table levels used by the hardware for resolving N bits
is same as that for (N - 4) bits (with concatenation), as there cannot
be a level in between (N, N-4) as per the above rules.

Hence, we have

 STAGE2_PGTABLE_LEVELS = PGTABLE_LEVELS(KVM_PHYS_SHIFT - 4)

With the current IPA limit (40bit), for all supported translations
and VA_BITS, we have the following condition (even for 36bit VA with
16K page size):

 CONFIG_PGTABLE_LEVELS >= STAGE2_PGTABLE_LEVELS.

So, for e.g,  if PUD is present in stage2, it is present in the hyp(host).
Hence, we fall back to the host definition if we find that a level is not
folded. Otherwise we redefine it accordingly. A build time check is added
to make sure the above condition holds. If this condition breaks in future,
we can rearrange the host level helpers and fix our code easily.

Cc: Marc Zyngier <marc.zyngier at arm.com>
Cc: Christoffer Dall <christoffer.dall at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm64/include/asm/kvm_mmu.h              |  64 +-------------
 arch/arm64/include/asm/stage2_pgtable-nopmd.h |  42 +++++++++
 arch/arm64/include/asm/stage2_pgtable-nopud.h |  39 ++++++++
 arch/arm64/include/asm/stage2_pgtable.h       | 122 +++++++++++++++++++-------
 4 files changed, 172 insertions(+), 95 deletions(-)
 create mode 100644 arch/arm64/include/asm/stage2_pgtable-nopmd.h
 create mode 100644 arch/arm64/include/asm/stage2_pgtable-nopud.h

diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index a3c0d05..e3fee0a 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -45,18 +45,6 @@
  */
 #define TRAMPOLINE_VA		(HYP_PAGE_OFFSET_MASK & PAGE_MASK)
 
-/*
- * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation
- * levels in addition to the PGD and potentially the PUD which are
- * pre-allocated (we pre-allocate the fake PGD and the PUD when the Stage-2
- * tables use one level of tables less than the kernel.
- */
-#ifdef CONFIG_ARM64_64K_PAGES
-#define KVM_MMU_CACHE_MIN_PAGES	1
-#else
-#define KVM_MMU_CACHE_MIN_PAGES	2
-#endif
-
 #ifdef __ASSEMBLY__
 
 #include <asm/alternative.h>
@@ -155,69 +143,21 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
 
 static inline void *kvm_get_hwpgd(struct kvm *kvm)
 {
-	pgd_t *pgd = kvm->arch.pgd;
-	pud_t *pud;
-
-	if (KVM_PREALLOC_LEVEL == 0)
-		return pgd;
-
-	pud = pud_offset(pgd, 0);
-	if (KVM_PREALLOC_LEVEL == 1)
-		return pud;
-
-	BUG_ON(KVM_PREALLOC_LEVEL != 2);
-	return pmd_offset(pud, 0);
+	return kvm->arch.pgd;
 }
 
 static inline unsigned int kvm_get_hwpgd_size(void)
 {
-	if (KVM_PREALLOC_LEVEL > 0)
-		return PTRS_PER_S2_PGD * PAGE_SIZE;
 	return PTRS_PER_S2_PGD * sizeof(pgd_t);
 }
 
-/*
- * Allocate fake pgd for the host kernel page table macros to work.
- * This is not used by the hardware and we have no alignment
- * requirement for this allocation.
- */
 static inline pgd_t *kvm_setup_fake_pgd(pgd_t *hwpgd)
 {
-	int i;
-	pgd_t *pgd;
-
-	if (!KVM_PREALLOC_LEVEL)
-		return hwpgd;
-
-	/*
-	 * When KVM_PREALLOC_LEVEL==2, we allocate a single page for
-	 * the PMD and the kernel will use folded pud.
-	 * When KVM_PREALLOC_LEVEL==1, we allocate 2 consecutive PUD
-	 * pages.
-	 */
-
-	pgd = kmalloc(PTRS_PER_S2_PGD * sizeof(pgd_t),
-			GFP_KERNEL | __GFP_ZERO);
-	if (!pgd)
-		return ERR_PTR(-ENOMEM);
-
-	/* Plug the HW PGD into the fake one. */
-	for (i = 0; i < PTRS_PER_S2_PGD; i++) {
-		if (KVM_PREALLOC_LEVEL == 1)
-			pgd_populate(NULL, pgd + i,
-				     (pud_t *)hwpgd + i * PTRS_PER_PUD);
-		else if (KVM_PREALLOC_LEVEL == 2)
-			pud_populate(NULL, pud_offset(pgd, 0) + i,
-				     (pmd_t *)hwpgd + i * PTRS_PER_PMD);
-	}
-
-	return pgd;
+	return hwpgd;
 }
 
 static inline void kvm_free_fake_pgd(pgd_t *pgd)
 {
-	if (KVM_PREALLOC_LEVEL > 0)
-		kfree(pgd);
 }
 static inline bool kvm_page_empty(void *ptr)
 {
diff --git a/arch/arm64/include/asm/stage2_pgtable-nopmd.h b/arch/arm64/include/asm/stage2_pgtable-nopmd.h
new file mode 100644
index 0000000..2656a0f
--- /dev/null
+++ b/arch/arm64/include/asm/stage2_pgtable-nopmd.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 - ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM64_S2_PGTABLE_NOPMD_H_
+#define __ARM64_S2_PGTABLE_NOPMD_H_
+
+#include <asm/stage2_pgtable-nopud.h>
+
+#define __S2_PGTABLE_PMD_FOLDED
+
+#define S2_PMD_SHIFT		S2_PUD_SHIFT
+#define S2_PTRS_PER_PMD		1
+#define S2_PMD_SIZE		(1UL << S2_PMD_SHIFT)
+#define S2_PMD_MASK		(~(S2_PMD_SIZE-1))
+
+#define stage2_pud_none(pud)			(0)
+#define stage2_pud_present(pud)			(1)
+#define stage2_pud_clear(pud)			do { } while (0)
+#define stage2_pud_populate(pud, pmd)		do { } while (0)
+#define stage2_pmd_offset(pud, address)		((pmd_t *)(pud))
+
+#define stage2_pmd_free(pmd)			do { } while (0)
+
+#define stage2_pmd_addr_end(addr, end)		(end)
+
+#define stage2_pud_huge(pud)			(0)
+#define stage2_pmd_table_empty(pmdp)		(0)
+
+#endif
diff --git a/arch/arm64/include/asm/stage2_pgtable-nopud.h b/arch/arm64/include/asm/stage2_pgtable-nopud.h
new file mode 100644
index 0000000..5ee87b5
--- /dev/null
+++ b/arch/arm64/include/asm/stage2_pgtable-nopud.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 - ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM64_S2_PGTABLE_NOPUD_H_
+#define __ARM64_S2_PGTABLE_NOPUD_H_
+
+#define __S2_PGTABLE_PUD_FOLDED
+
+#define S2_PUD_SHIFT		S2_PGDIR_SHIFT
+#define S2_PTRS_PER_PUD		1
+#define S2_PUD_SIZE		(_AC(1, UL) << S2_PUD_SHIFT)
+#define S2_PUD_MASK		(~(S2_PUD_SIZE-1))
+
+#define stage2_pgd_none(pgd)			(0)
+#define stage2_pgd_present(pgd)			(1)
+#define stage2_pgd_clear(pgd)			do { } while (0)
+#define stage2_pgd_populate(pgd, pud)	do { } while (0)
+
+#define stage2_pud_offset(pgd, address)		((pud_t *)(pgd))
+
+#define stage2_pud_free(x)			do { } while (0)
+
+#define stage2_pud_addr_end(addr, end)		(end)
+#define stage2_pud_table_empty(pmdp)		(0)
+
+#endif
diff --git a/arch/arm64/include/asm/stage2_pgtable.h b/arch/arm64/include/asm/stage2_pgtable.h
index 0ec218f..8b68099 100644
--- a/arch/arm64/include/asm/stage2_pgtable.h
+++ b/arch/arm64/include/asm/stage2_pgtable.h
@@ -22,32 +22,61 @@
 #include <asm/pgtable.h>
 
 /*
- * In the case where PGDIR_SHIFT is larger than KVM_PHYS_SHIFT, we can address
- * the entire IPA input range with a single pgd entry, and we would only need
- * one pgd entry.  Note that in this case, the pgd is actually not used by
- * the MMU for Stage-2 translations, but is merely a fake pgd used as a data
- * structure for the kernel pgtable macros to work.
+ * The hardware supports concatenation of up to 16 tables at stage2 entry level
+ * and we use the feature whenever possible.
+ *
+ * Now, the minimum number of bits resolved at any level is (PAGE_SHIFT - 3).
+ * On arm64, the smallest PAGE_SIZE supported is 4k, which means
+ *             (PAGE_SHIFT - 3) > 4 holds for all page sizes.
+ * This implies, the total number of page table levels at stage2 expected
+ * by the hardware is actually the number of levels required for (KVM_PHYS_SHIFT - 4)
+ * in normal translations(e.g, stage1), since we cannot have another level in
+ * the range (KVM_PHYS_SHIFT, KVM_PHYS_SHIFT - 4).
  */
-#if PGDIR_SHIFT > KVM_PHYS_SHIFT
-#define PTRS_PER_S2_PGD_SHIFT	0
-#else
-#define PTRS_PER_S2_PGD_SHIFT	(KVM_PHYS_SHIFT - PGDIR_SHIFT)
-#endif
-#define PTRS_PER_S2_PGD		(1 << PTRS_PER_S2_PGD_SHIFT)
+#define STAGE2_PGTABLE_LEVELS		ARM64_HW_PGTABLE_LEVELS(KVM_PHYS_SHIFT - 4)
 
 /*
- * If we are concatenating first level stage-2 page tables, we would have less
- * than or equal to 16 pointers in the fake PGD, because that's what the
- * architecture allows.  In this case, (4 - CONFIG_PGTABLE_LEVELS)
- * represents the first level for the host, and we add 1 to go to the next
- * level (which uses contatenation) for the stage-2 tables.
+ * With all the supported VA_BITs and 40bit guest IPA, the following condition
+ * is always true:
+ *
+ *       STAGE2_PGTABLE_LEVELS <= CONFIG_PGTABLE_LEVELS
+ *
+ * We base our stage-2 page table walker helpers on this assumption and
+ * fall back to using the host version of the helper wherever possible.
+ * i.e, if a particular level is not folded (e.g, PUD) at stage2, we fall back
+ * to using the host version, since it is guaranteed it is not folded at host.
+ *
+ * If the condition breaks in the future, we can rearrange the host level
+ * definitions and reuse them for stage2. Till then...
  */
-#if PTRS_PER_S2_PGD <= 16
-#define KVM_PREALLOC_LEVEL	(4 - CONFIG_PGTABLE_LEVELS + 1)
-#else
-#define KVM_PREALLOC_LEVEL	(0)
+#if STAGE2_PGTABLE_LEVELS > CONFIG_PGTABLE_LEVELS
+#error "Unsupported combination of guest IPA and host VA_BITS."
 #endif
 
+/* S2_PGDIR_SHIFT is the size mapped by top-level stage2 entry */
+#define S2_PGDIR_SHIFT			ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - STAGE2_PGTABLE_LEVELS)
+#define S2_PGDIR_SIZE			(_AC(1, UL) << S2_PGDIR_SHIFT)
+#define S2_PGDIR_MASK			(~(S2_PGDIR_SIZE - 1))
+
+/*
+ * The number of PTRS across all concatenated stage2 tables given by the
+ * number of bits resolved at the initial level.
+ */
+#define PTRS_PER_S2_PGD			(1 << (KVM_PHYS_SHIFT - S2_PGDIR_SHIFT))
+
+/*
+ * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation
+ * levels in addition to the PGD.
+ */
+#define KVM_MMU_CACHE_MIN_PAGES		(STAGE2_PGTABLE_LEVELS - 1)
+
+
+#if STAGE2_PGTABLE_LEVELS > 3
+
+#define S2_PUD_SHIFT			ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
+#define S2_PUD_SIZE			(_AC(1, UL) << S2_PUD_SHIFT)
+#define S2_PUD_MASK			(~(S2_PUD_SIZE - 1))
+
 #define stage2_pgd_none(pgd)				pgd_none(pgd)
 #define stage2_pgd_clear(pgd)				pgd_clear(pgd)
 #define stage2_pgd_present(pgd)				pgd_present(pgd)
@@ -55,6 +84,24 @@
 #define stage2_pud_offset(pgd, address)			pud_offset(pgd, address)
 #define stage2_pud_free(pud)				pud_free(NULL, pud)
 
+#define stage2_pud_table_empty(pudp)			kvm_page_empty(pudp)
+
+static inline phys_addr_t stage2_pud_addr_end(phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t boundary = (addr + S2_PUD_SIZE) & S2_PUD_MASK;
+
+	return (boundary - 1 < end - 1) ? boundary : end;
+}
+
+#endif		/* STAGE2_PGTABLE_LEVELS > 3 */
+
+
+#if STAGE2_PGTABLE_LEVELS > 2
+
+#define S2_PMD_SHIFT			ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
+#define S2_PMD_SIZE			(_AC(1, UL) << S2_PMD_SHIFT)
+#define S2_PMD_MASK			(~(S2_PMD_SIZE - 1))
+
 #define stage2_pud_none(pud)				pud_none(pud)
 #define stage2_pud_clear(pud)				pud_clear(pud)
 #define stage2_pud_present(pud)				pud_present(pud)
@@ -63,24 +110,33 @@
 #define stage2_pmd_free(pmd)				pmd_free(NULL, pmd)
 
 #define stage2_pud_huge(pud)				pud_huge(pud)
+#define stage2_pmd_table_empty(pmdp)			kvm_page_empty(pmdp)
+
+static inline phys_addr_t stage2_pmd_addr_end(phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t boundary = (addr + S2_PMD_SIZE) & S2_PMD_MASK;
 
-#define stage2_pgd_addr_end(address, end)		pgd_addr_end(address, end)
-#define stage2_pud_addr_end(address, end)		pud_addr_end(address, end)
-#define stage2_pmd_addr_end(address, end)		pmd_addr_end(address, end)
+	return (boundary - 1 < end - 1) ? boundary : end;
+}
+
+#endif		/* STAGE2_PGTABLE_LEVELS > 2 */
 
 #define stage2_pte_table_empty(ptep)			kvm_page_empty(ptep)
-#ifdef __PGTABLE_PMD_FOLDED
-#define stage2_pmd_table_empty(pmdp)			(0)
-#else
-#define stage2_pmd_table_empty(pmdp)			((KVM_PREALLOC_LEVEL < 2) && kvm_page_empty(pmdp))
-#endif
 
-#ifdef __PGTABLE_PUD_FOLDED
-#define stage2_pud_table_empty(pudp)			(0)
-#else
-#define stage2_pud_table_empty(pudp)			((KVM_PREALLOC_LEVEL < 1) && kvm_page_empty(pudp))
+#if STAGE2_PGTABLE_LEVELS == 2
+#include <asm/stage2_pgtable-nopmd.h>
+#elif STAGE2_PGTABLE_LEVELS == 3
+#include <asm/stage2_pgtable-nopud.h>
 #endif
 
-#define stage2_pgd_index(addr)				(((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1))
+
+#define stage2_pgd_index(addr)				(((addr) >> S2_PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1))
+
+static inline phys_addr_t stage2_pgd_addr_end(phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t boundary = (addr + S2_PGDIR_SIZE) & S2_PGDIR_MASK;
+
+	return (boundary - 1 < end - 1) ? boundary : end;
+}
 
 #endif	/* __ARM64_S2_PGTABLE_H_ */
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:12 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:12 +0200
Subject: [PULL 19/29] clocksource: arm_arch_timer: Gather KVM specific
 information in a structure
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-20-git-send-email-christoffer.dall@linaro.org>

From: Julien Grall <julien.grall at arm.com>

Introduce a structure which are filled up by the arch timer driver and
used by the virtual timer in KVM.

The first member of this structure will be the timecounter. More members
will be added later.

A stub for the new helper isn't introduced because KVM requires the arch
timer for both ARM64 and ARM32.

The function arch_timer_get_timecounter is kept for the time being and
will be dropped in a subsequent patch.

Signed-off-by: Julien Grall <julien.grall at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 12 +++++++++---
 include/clocksource/arm_arch_timer.h |  5 +++++
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 5152b38..62bdfe7 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -468,11 +468,16 @@ static struct cyclecounter cyclecounter = {
 	.mask	= CLOCKSOURCE_MASK(56),
 };
 
-static struct timecounter timecounter;
+static struct arch_timer_kvm_info arch_timer_kvm_info;
+
+struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
+{
+	return &arch_timer_kvm_info;
+}
 
 struct timecounter *arch_timer_get_timecounter(void)
 {
-	return &timecounter;
+	return &arch_timer_kvm_info.timecounter;
 }
 
 static void __init arch_counter_register(unsigned type)
@@ -500,7 +505,8 @@ static void __init arch_counter_register(unsigned type)
 	clocksource_register_hz(&clocksource_counter, arch_timer_rate);
 	cyclecounter.mult = clocksource_counter.mult;
 	cyclecounter.shift = clocksource_counter.shift;
-	timecounter_init(&timecounter, &cyclecounter, start_count);
+	timecounter_init(&arch_timer_kvm_info.timecounter,
+			 &cyclecounter, start_count);
 
 	/* 56 bits minimum, so we assume worst case rollover */
 	sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate);
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 25d0914..9101ed6b 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -49,11 +49,16 @@ enum arch_timer_reg {
 
 #define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
 
+struct arch_timer_kvm_info {
+	struct timecounter timecounter;
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
 extern u64 (*arch_timer_read_counter)(void);
 extern struct timecounter *arch_timer_get_timecounter(void);
+extern struct arch_timer_kvm_info *arch_timer_get_kvm_info(void);
 
 #else
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:05 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:05 +0200
Subject: [PULL 12/29] kvm-arm: Add explicit hyp page table modifiers
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-13-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

We have common routines to modify hyp and stage2 page tables
based on the 'kvm' parameter. For a smoother transition to
using separate routines for each, duplicate the routines
and modify the copy to work on hyp.

Marks the forked routines with _hyp_ and gets rid of the
kvm parameter which is no longer needed and is NULL for hyp.
Also, gets rid of calls to kvm_tlb_flush_by_vmid_ipa() calls
from the hyp versions. Uses explicit host page table accessors
instead of the kvm_* page table helpers.

Suggested-by: Christoffer Dall <christoffer.dall at linaro.org>
Cc: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm/kvm/mmu.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 99 insertions(+), 5 deletions(-)

diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index f93f717..af526f6 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -388,6 +388,100 @@ static void stage2_flush_vm(struct kvm *kvm)
 	srcu_read_unlock(&kvm->srcu, idx);
 }
 
+static void clear_hyp_pgd_entry(pgd_t *pgd)
+{
+	pud_t *pud_table __maybe_unused = pud_offset(pgd, 0UL);
+	pgd_clear(pgd);
+	pud_free(NULL, pud_table);
+	put_page(virt_to_page(pgd));
+}
+
+static void clear_hyp_pud_entry(pud_t *pud)
+{
+	pmd_t *pmd_table __maybe_unused = pmd_offset(pud, 0);
+	VM_BUG_ON(pud_huge(*pud));
+	pud_clear(pud);
+	pmd_free(NULL, pmd_table);
+	put_page(virt_to_page(pud));
+}
+
+static void clear_hyp_pmd_entry(pmd_t *pmd)
+{
+	pte_t *pte_table = pte_offset_kernel(pmd, 0);
+	VM_BUG_ON(pmd_thp_or_huge(*pmd));
+	pmd_clear(pmd);
+	pte_free_kernel(NULL, pte_table);
+	put_page(virt_to_page(pmd));
+}
+
+static void unmap_hyp_ptes(pmd_t *pmd, phys_addr_t addr, phys_addr_t end)
+{
+	pte_t *pte, *start_pte;
+
+	start_pte = pte = pte_offset_kernel(pmd, addr);
+	do {
+		if (!pte_none(*pte)) {
+			kvm_set_pte(pte, __pte(0));
+			put_page(virt_to_page(pte));
+		}
+	} while (pte++, addr += PAGE_SIZE, addr != end);
+
+	if (hyp_pte_table_empty(start_pte))
+		clear_hyp_pmd_entry(pmd);
+}
+
+static void unmap_hyp_pmds(pud_t *pud, phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t next;
+	pmd_t *pmd, *start_pmd;
+
+	start_pmd = pmd = pmd_offset(pud, addr);
+	do {
+		next = pmd_addr_end(addr, end);
+		/* Hyp doesn't use huge pmds */
+		if (!pmd_none(*pmd))
+			unmap_hyp_ptes(pmd, addr, next);
+	} while (pmd++, addr = next, addr != end);
+
+	if (hyp_pmd_table_empty(start_pmd))
+		clear_hyp_pud_entry(pud);
+}
+
+static void unmap_hyp_puds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t next;
+	pud_t *pud, *start_pud;
+
+	start_pud = pud = pud_offset(pgd, addr);
+	do {
+		next = pud_addr_end(addr, end);
+		/* Hyp doesn't use huge puds */
+		if (!pud_none(*pud))
+			unmap_hyp_pmds(pud, addr, next);
+	} while (pud++, addr = next, addr != end);
+
+	if (hyp_pud_table_empty(start_pud))
+		clear_hyp_pgd_entry(pgd);
+}
+
+static void unmap_hyp_range(pgd_t *pgdp, phys_addr_t start, u64 size)
+{
+	pgd_t *pgd;
+	phys_addr_t addr = start, end = start + size;
+	phys_addr_t next;
+
+	/*
+	 * We don't unmap anything from HYP, except at the hyp tear down.
+	 * Hence, we don't have to invalidate the TLBs here.
+	 */
+	pgd = pgdp + pgd_index(addr);
+	do {
+		next = pgd_addr_end(addr, end);
+		if (!pgd_none(*pgd))
+			unmap_hyp_puds(pgd, addr, next);
+	} while (pgd++, addr = next, addr != end);
+}
+
 /**
  * free_boot_hyp_pgd - free HYP boot page tables
  *
@@ -398,14 +492,14 @@ void free_boot_hyp_pgd(void)
 	mutex_lock(&kvm_hyp_pgd_mutex);
 
 	if (boot_hyp_pgd) {
-		unmap_range(NULL, boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
-		unmap_range(NULL, boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
+		unmap_hyp_range(boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
+		unmap_hyp_range(boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
 		free_pages((unsigned long)boot_hyp_pgd, hyp_pgd_order);
 		boot_hyp_pgd = NULL;
 	}
 
 	if (hyp_pgd)
-		unmap_range(NULL, hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
+		unmap_hyp_range(hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
 
 	mutex_unlock(&kvm_hyp_pgd_mutex);
 }
@@ -430,9 +524,9 @@ void free_hyp_pgds(void)
 
 	if (hyp_pgd) {
 		for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE)
-			unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
+			unmap_hyp_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
 		for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
-			unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
+			unmap_hyp_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
 
 		free_pages((unsigned long)hyp_pgd, hyp_pgd_order);
 		hyp_pgd = NULL;
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:09 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:09 +0200
Subject: [PULL 16/29] kvm-arm: Cleanup stage2 pgd handling
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-17-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Now that we don't have any fake page table levels for arm64,
cleanup the common code to get rid of the dead code.

Cc: Marc Zyngier <marc.zyngier at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm/include/asm/kvm_mmu.h   | 19 -------------------
 arch/arm/kvm/arm.c               |  2 +-
 arch/arm/kvm/mmu.c               | 37 ++++++-------------------------------
 arch/arm64/include/asm/kvm_mmu.h | 18 ------------------
 4 files changed, 7 insertions(+), 69 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index a7736d5..6344ea0 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -150,25 +150,6 @@ static inline bool kvm_page_empty(void *ptr)
 #define hyp_pmd_table_empty(pmdp) kvm_page_empty(pmdp)
 #define hyp_pud_table_empty(pudp) false
 
-static inline void *kvm_get_hwpgd(struct kvm *kvm)
-{
-	return kvm->arch.pgd;
-}
-
-static inline unsigned int kvm_get_hwpgd_size(void)
-{
-	return PTRS_PER_S2_PGD * sizeof(pgd_t);
-}
-
-static inline pgd_t *kvm_setup_fake_pgd(pgd_t *hwpgd)
-{
-	return hwpgd;
-}
-
-static inline void kvm_free_fake_pgd(pgd_t *pgd)
-{
-}
-
 struct kvm;
 
 #define kvm_flush_dcache_to_poc(a,l)	__cpuc_flush_dcache_area((a), (l))
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index dded1b7..be4b639 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -448,7 +448,7 @@ static void update_vttbr(struct kvm *kvm)
 	kvm_next_vmid &= (1 << kvm_vmid_bits) - 1;
 
 	/* update vttbr to be used with the new vmid */
-	pgd_phys = virt_to_phys(kvm_get_hwpgd(kvm));
+	pgd_phys = virt_to_phys(kvm->arch.pgd);
 	BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK);
 	vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK(kvm_vmid_bits);
 	kvm->arch.vttbr = pgd_phys | vmid;
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index d3fa96e..42eefab 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -43,6 +43,7 @@ static unsigned long hyp_idmap_start;
 static unsigned long hyp_idmap_end;
 static phys_addr_t hyp_idmap_vector;
 
+#define S2_PGD_SIZE	(PTRS_PER_S2_PGD * sizeof(pgd_t))
 #define hyp_pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t))
 
 #define KVM_S2PTE_FLAG_IS_IOMAP		(1UL << 0)
@@ -736,20 +737,6 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr)
 				     __phys_to_pfn(phys_addr), PAGE_HYP_DEVICE);
 }
 
-/* Free the HW pgd, one page at a time */
-static void kvm_free_hwpgd(void *hwpgd)
-{
-	free_pages_exact(hwpgd, kvm_get_hwpgd_size());
-}
-
-/* Allocate the HW PGD, making sure that each page gets its own refcount */
-static void *kvm_alloc_hwpgd(void)
-{
-	unsigned int size = kvm_get_hwpgd_size();
-
-	return alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
-}
-
 /**
  * kvm_alloc_stage2_pgd - allocate level-1 table for stage-2 translation.
  * @kvm:	The KVM struct pointer for the VM.
@@ -764,29 +751,17 @@ static void *kvm_alloc_hwpgd(void)
 int kvm_alloc_stage2_pgd(struct kvm *kvm)
 {
 	pgd_t *pgd;
-	void *hwpgd;
 
 	if (kvm->arch.pgd != NULL) {
 		kvm_err("kvm_arch already initialized?\n");
 		return -EINVAL;
 	}
 
-	hwpgd = kvm_alloc_hwpgd();
-	if (!hwpgd)
+	/* Allocate the HW PGD, making sure that each page gets its own refcount */
+	pgd = alloc_pages_exact(S2_PGD_SIZE, GFP_KERNEL | __GFP_ZERO);
+	if (!pgd)
 		return -ENOMEM;
 
-	/*
-	 * When the kernel uses more levels of page tables than the
-	 * guest, we allocate a fake PGD and pre-populate it to point
-	 * to the next-level page table, which will be the real
-	 * initial page table pointed to by the VTTBR.
-	 */
-	pgd = kvm_setup_fake_pgd(hwpgd);
-	if (IS_ERR(pgd)) {
-		kvm_free_hwpgd(hwpgd);
-		return PTR_ERR(pgd);
-	}
-
 	kvm_clean_pgd(pgd);
 	kvm->arch.pgd = pgd;
 	return 0;
@@ -874,8 +849,8 @@ void kvm_free_stage2_pgd(struct kvm *kvm)
 		return;
 
 	unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
-	kvm_free_hwpgd(kvm_get_hwpgd(kvm));
-	kvm_free_fake_pgd(kvm->arch.pgd);
+	/* Free the HW pgd, one page at a time */
+	free_pages_exact(kvm->arch.pgd, S2_PGD_SIZE);
 	kvm->arch.pgd = NULL;
 }
 
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index e3fee0a..249c4fc 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -141,24 +141,6 @@ static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
 	return (pmd_val(*pmd) & PMD_S2_RDWR) == PMD_S2_RDONLY;
 }
 
-static inline void *kvm_get_hwpgd(struct kvm *kvm)
-{
-	return kvm->arch.pgd;
-}
-
-static inline unsigned int kvm_get_hwpgd_size(void)
-{
-	return PTRS_PER_S2_PGD * sizeof(pgd_t);
-}
-
-static inline pgd_t *kvm_setup_fake_pgd(pgd_t *hwpgd)
-{
-	return hwpgd;
-}
-
-static inline void kvm_free_fake_pgd(pgd_t *pgd)
-{
-}
 static inline bool kvm_page_empty(void *ptr)
 {
 	struct page *ptr_page = virt_to_page(ptr);
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:11 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:11 +0200
Subject: [PULL 18/29] arm/arm64: KVM: Enforce Break-Before-Make on Stage-2
 page tables
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-19-git-send-email-christoffer.dall@linaro.org>

From: Marc Zyngier <marc.zyngier at arm.com>

The ARM architecture mandates that when changing a page table entry
from a valid entry to another valid entry, an invalid entry is first
written, TLB invalidated, and only then the new entry being written.

The current code doesn't respect this, directly writing the new
entry and only then invalidating TLBs. Let's fix it up.

Cc: <stable at vger.kernel.org>
Reported-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 arch/arm/kvm/mmu.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 42eefab..74b5d19 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -910,11 +910,14 @@ static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache
 	VM_BUG_ON(pmd_present(*pmd) && pmd_pfn(*pmd) != pmd_pfn(*new_pmd));
 
 	old_pmd = *pmd;
-	kvm_set_pmd(pmd, *new_pmd);
-	if (pmd_present(old_pmd))
+	if (pmd_present(old_pmd)) {
+		pmd_clear(pmd);
 		kvm_tlb_flush_vmid_ipa(kvm, addr);
-	else
+	} else {
 		get_page(virt_to_page(pmd));
+	}
+
+	kvm_set_pmd(pmd, *new_pmd);
 	return 0;
 }
 
@@ -963,12 +966,14 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
 
 	/* Create 2nd stage page table mapping - Level 3 */
 	old_pte = *pte;
-	kvm_set_pte(pte, *new_pte);
-	if (pte_present(old_pte))
+	if (pte_present(old_pte)) {
+		kvm_set_pte(pte, __pte(0));
 		kvm_tlb_flush_vmid_ipa(kvm, addr);
-	else
+	} else {
 		get_page(virt_to_page(pte));
+	}
 
+	kvm_set_pte(pte, *new_pte);
 	return 0;
 }
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:17 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:17 +0200
Subject: [PULL 24/29] irqchip/gic-v3: Gather all ACPI specific data in a
 single structure
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-25-git-send-email-christoffer.dall@linaro.org>

From: Julien Grall <julien.grall at arm.com>

The ACPI code requires to use global variables in order to collect
information from the tables.

To make clear those variables are ACPI specific, gather all of them in a
single structure.

Furthermore, even if some of the variables are not marked with
__initdata, they are all only used during the initialization. Therefore,
the new variable, which hold the structure, can be marked with
__initdata.

Signed-off-by: Julien Grall <julien.grall at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Reviewed-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 drivers/irqchip/irq-gic-v3.c | 60 ++++++++++++++++++++++++--------------------
 1 file changed, 33 insertions(+), 27 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 6dc6f03..6a9f5ff 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -970,19 +970,22 @@ out_unmap_dist:
 IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 
 #ifdef CONFIG_ACPI
-static void __iomem *dist_base;
-static struct redist_region *redist_regs __initdata;
-static u32 nr_redist_regions __initdata;
-static bool single_redist;
+static struct
+{
+	void __iomem *dist_base;
+	struct redist_region *redist_regs;
+	u32 nr_redist_regions;
+	bool single_redist;
+} acpi_data __initdata;
 
 static void __init
 gic_acpi_register_redist(phys_addr_t phys_base, void __iomem *redist_base)
 {
 	static int count = 0;
 
-	redist_regs[count].phys_base = phys_base;
-	redist_regs[count].redist_base = redist_base;
-	redist_regs[count].single_redist = single_redist;
+	acpi_data.redist_regs[count].phys_base = phys_base;
+	acpi_data.redist_regs[count].redist_base = redist_base;
+	acpi_data.redist_regs[count].single_redist = acpi_data.single_redist;
 	count++;
 }
 
@@ -1010,7 +1013,7 @@ gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
 {
 	struct acpi_madt_generic_interrupt *gicc =
 				(struct acpi_madt_generic_interrupt *)header;
-	u32 reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
+	u32 reg = readl_relaxed(acpi_data.dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
 	u32 size = reg == GIC_PIDR2_ARCH_GICv4 ? SZ_64K * 4 : SZ_64K * 2;
 	void __iomem *redist_base;
 
@@ -1027,7 +1030,7 @@ static int __init gic_acpi_collect_gicr_base(void)
 	acpi_tbl_entry_handler redist_parser;
 	enum acpi_madt_type type;
 
-	if (single_redist) {
+	if (acpi_data.single_redist) {
 		type = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
 		redist_parser = gic_acpi_parse_madt_gicc;
 	} else {
@@ -1078,14 +1081,14 @@ static int __init gic_acpi_count_gicr_regions(void)
 	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
 				      gic_acpi_match_gicr, 0);
 	if (count > 0) {
-		single_redist = false;
+		acpi_data.single_redist = false;
 		return count;
 	}
 
 	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
 				      gic_acpi_match_gicc, 0);
 	if (count > 0)
-		single_redist = true;
+		acpi_data.single_redist = true;
 
 	return count;
 }
@@ -1105,7 +1108,7 @@ static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
 	if (count <= 0)
 		return false;
 
-	nr_redist_regions = count;
+	acpi_data.nr_redist_regions = count;
 	return true;
 }
 
@@ -1116,25 +1119,28 @@ gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
 {
 	struct acpi_madt_generic_distributor *dist;
 	struct fwnode_handle *domain_handle;
+	size_t size;
 	int i, err;
 
 	/* Get distributor base address */
 	dist = (struct acpi_madt_generic_distributor *)header;
-	dist_base = ioremap(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE);
-	if (!dist_base) {
+	acpi_data.dist_base = ioremap(dist->base_address,
+				      ACPI_GICV3_DIST_MEM_SIZE);
+	if (!acpi_data.dist_base) {
 		pr_err("Unable to map GICD registers\n");
 		return -ENOMEM;
 	}
 
-	err = gic_validate_dist_version(dist_base);
+	err = gic_validate_dist_version(acpi_data.dist_base);
 	if (err) {
-		pr_err("No distributor detected at @%p, giving up", dist_base);
+		pr_err("No distributor detected at @%p, giving up",
+		       acpi_data.dist_base);
 		goto out_dist_unmap;
 	}
 
-	redist_regs = kzalloc(sizeof(*redist_regs) * nr_redist_regions,
-			      GFP_KERNEL);
-	if (!redist_regs) {
+	size = sizeof(*acpi_data.redist_regs) * acpi_data.nr_redist_regions;
+	acpi_data.redist_regs = kzalloc(size, GFP_KERNEL);
+	if (!acpi_data.redist_regs) {
 		err = -ENOMEM;
 		goto out_dist_unmap;
 	}
@@ -1143,14 +1149,14 @@ gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
 	if (err)
 		goto out_redist_unmap;
 
-	domain_handle = irq_domain_alloc_fwnode(dist_base);
+	domain_handle = irq_domain_alloc_fwnode(acpi_data.dist_base);
 	if (!domain_handle) {
 		err = -ENOMEM;
 		goto out_redist_unmap;
 	}
 
-	err = gic_init_bases(dist_base, redist_regs, nr_redist_regions, 0,
-			     domain_handle);
+	err = gic_init_bases(acpi_data.dist_base, acpi_data.redist_regs,
+			     acpi_data.nr_redist_regions, 0, domain_handle);
 	if (err)
 		goto out_fwhandle_free;
 
@@ -1160,12 +1166,12 @@ gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
 out_fwhandle_free:
 	irq_domain_free_fwnode(domain_handle);
 out_redist_unmap:
-	for (i = 0; i < nr_redist_regions; i++)
-		if (redist_regs[i].redist_base)
-			iounmap(redist_regs[i].redist_base);
-	kfree(redist_regs);
+	for (i = 0; i < acpi_data.nr_redist_regions; i++)
+		if (acpi_data.redist_regs[i].redist_base)
+			iounmap(acpi_data.redist_regs[i].redist_base);
+	kfree(acpi_data.redist_regs);
 out_dist_unmap:
-	iounmap(dist_base);
+	iounmap(acpi_data.dist_base);
 	return err;
 }
 IRQCHIP_ACPI_DECLARE(gic_v3, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:18 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:18 +0200
Subject: [PULL 25/29] irqchip/gic-v3: Parse and export virtual GIC information
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-26-git-send-email-christoffer.dall@linaro.org>

From: Julien Grall <julien.grall at arm.com>

Fill up the recently introduced gic_kvm_info with the hardware
information used for virtualization.

Signed-off-by: Julien Grall <julien.grall at arm.com>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Jason Cooper <jason at lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 drivers/irqchip/irq-gic-v3.c           | 114 ++++++++++++++++++++++++++++++++-
 include/linux/irqchip/arm-gic-common.h |   1 +
 2 files changed, 114 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 6a9f5ff..05a8560 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 
 #include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic-common.h>
 #include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/cputype.h>
@@ -58,6 +59,8 @@ struct gic_chip_data {
 static struct gic_chip_data gic_data __read_mostly;
 static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE;
 
+static struct gic_kvm_info gic_v3_kvm_info;
+
 #define gic_data_rdist()		(this_cpu_ptr(gic_data.rdists.rdist))
 #define gic_data_rdist_rd_base()	(gic_data_rdist()->rd_base)
 #define gic_data_rdist_sgi_base()	(gic_data_rdist_rd_base() + SZ_64K)
@@ -903,6 +906,30 @@ static int __init gic_validate_dist_version(void __iomem *dist_base)
 	return 0;
 }
 
+static void __init gic_of_setup_kvm_info(struct device_node *node)
+{
+	int ret;
+	struct resource r;
+	u32 gicv_idx;
+
+	gic_v3_kvm_info.type = GIC_V3;
+
+	gic_v3_kvm_info.maint_irq = irq_of_parse_and_map(node, 0);
+	if (!gic_v3_kvm_info.maint_irq)
+		return;
+
+	if (of_property_read_u32(node, "#redistributor-regions",
+				 &gicv_idx))
+		gicv_idx = 1;
+
+	gicv_idx += 3;	/* Also skip GICD, GICC, GICH */
+	ret = of_address_to_resource(node, gicv_idx, &r);
+	if (!ret)
+		gic_v3_kvm_info.vcpu = r;
+
+	gic_set_kvm_info(&gic_v3_kvm_info);
+}
+
 static int __init gic_of_init(struct device_node *node, struct device_node *parent)
 {
 	void __iomem *dist_base;
@@ -954,8 +981,10 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
 
 	err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions,
 			     redist_stride, &node->fwnode);
-	if (!err)
+	if (!err) {
+		gic_of_setup_kvm_info(node);
 		return 0;
+	}
 
 out_unmap_rdist:
 	for (i = 0; i < nr_redist_regions; i++)
@@ -976,6 +1005,9 @@ static struct
 	struct redist_region *redist_regs;
 	u32 nr_redist_regions;
 	bool single_redist;
+	u32 maint_irq;
+	int maint_irq_mode;
+	phys_addr_t vcpu_base;
 } acpi_data __initdata;
 
 static void __init
@@ -1112,7 +1144,85 @@ static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
 	return true;
 }
 
+static int __init gic_acpi_parse_virt_madt_gicc(struct acpi_subtable_header *header,
+						const unsigned long end)
+{
+	struct acpi_madt_generic_interrupt *gicc =
+		(struct acpi_madt_generic_interrupt *)header;
+	int maint_irq_mode;
+	static int first_madt = true;
+
+	/* Skip unusable CPUs */
+	if (!(gicc->flags & ACPI_MADT_ENABLED))
+		return 0;
+
+	maint_irq_mode = (gicc->flags & ACPI_MADT_VGIC_IRQ_MODE) ?
+		ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
+
+	if (first_madt) {
+		first_madt = false;
+
+		acpi_data.maint_irq = gicc->vgic_interrupt;
+		acpi_data.maint_irq_mode = maint_irq_mode;
+		acpi_data.vcpu_base = gicc->gicv_base_address;
+
+		return 0;
+	}
+
+	/*
+	 * The maintenance interrupt and GICV should be the same for every CPU
+	 */
+	if ((acpi_data.maint_irq != gicc->vgic_interrupt) ||
+	    (acpi_data.maint_irq_mode != maint_irq_mode) ||
+	    (acpi_data.vcpu_base != gicc->gicv_base_address))
+		return -EINVAL;
+
+	return 0;
+}
+
+static bool __init gic_acpi_collect_virt_info(void)
+{
+	int count;
+
+	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
+				      gic_acpi_parse_virt_madt_gicc, 0);
+
+	return (count > 0);
+}
+
 #define ACPI_GICV3_DIST_MEM_SIZE (SZ_64K)
+#define ACPI_GICV2_VCTRL_MEM_SIZE	(SZ_4K)
+#define ACPI_GICV2_VCPU_MEM_SIZE	(SZ_8K)
+
+static void __init gic_acpi_setup_kvm_info(void)
+{
+	int irq;
+
+	if (!gic_acpi_collect_virt_info()) {
+		pr_warn("Unable to get hardware information used for virtualization\n");
+		return;
+	}
+
+	gic_v3_kvm_info.type = GIC_V3;
+
+	irq = acpi_register_gsi(NULL, acpi_data.maint_irq,
+				acpi_data.maint_irq_mode,
+				ACPI_ACTIVE_HIGH);
+	if (irq <= 0)
+		return;
+
+	gic_v3_kvm_info.maint_irq = irq;
+
+	if (acpi_data.vcpu_base) {
+		struct resource *vcpu = &gic_v3_kvm_info.vcpu;
+
+		vcpu->flags = IORESOURCE_MEM;
+		vcpu->start = acpi_data.vcpu_base;
+		vcpu->end = vcpu->start + ACPI_GICV2_VCPU_MEM_SIZE - 1;
+	}
+
+	gic_set_kvm_info(&gic_v3_kvm_info);
+}
 
 static int __init
 gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
@@ -1161,6 +1271,8 @@ gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
 		goto out_fwhandle_free;
 
 	acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
+	gic_acpi_setup_kvm_info();
+
 	return 0;
 
 out_fwhandle_free:
diff --git a/include/linux/irqchip/arm-gic-common.h b/include/linux/irqchip/arm-gic-common.h
index ef34f6f..c647b05 100644
--- a/include/linux/irqchip/arm-gic-common.h
+++ b/include/linux/irqchip/arm-gic-common.h
@@ -15,6 +15,7 @@
 
 enum gic_type {
 	GIC_V2,
+	GIC_V3,
 };
 
 struct gic_kvm_info {
-- 
2.1.2.330.g565301e.dirty



From andre.przywara at arm.com  Wed May 11 06:36:20 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 14:36:20 +0100
Subject: [PATCH v3 23/55] KVM: arm/arm64: vgic-new: Add CTLR, TYPER and
 IIDR handlers
In-Reply-To: <57333359.3000505@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-24-git-send-email-andre.przywara@arm.com>
 <20160511120533.GM27623@cbox> <57332AD8.6050306@arm.com>
 <20160511131556.GR27623@cbox> <57333359.3000505@arm.com>
Message-ID: <57333554.9070908@arm.com>

Hi,

On 11/05/16 14:27, Marc Zyngier wrote:
> On 11/05/16 14:15, Christoffer Dall wrote:
>> On Wed, May 11, 2016 at 01:51:36PM +0100, Marc Zyngier wrote:
>>> On 11/05/16 13:05, Christoffer Dall wrote:
>>>> On Fri, May 06, 2016 at 11:45:36AM +0100, Andre Przywara wrote:
>>>>> From: Marc Zyngier <marc.zyngier at arm.com>
>>>>>
>>>>> Those three registers are v2 emulation specific, so their implementation
>>>>> lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
>>>>> as their implementation is pretty simple.
>>>>> When the guest enables the distributor, we kick all VCPUs to get
>>>>> potentially pending interrupts serviced.
>>>>>
>>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>>> ---
>>>>> Changelog RFC..v1:
>>>>> - kick VCPUs is the distributor gets enabled
>>>>> - improve comment
>>>>>
>>>>> Changelog v1 .. v2:
>>>>> - adapt to new MMIO framework
>>>>> - use switch() statements to improve readability
>>>>>
>>>>> Changelog v2 .. v3:
>>>>> - add vgic_kick_vcpus() implementation
>>>>>
>>>>>  include/linux/irqchip/arm-gic.h  |  1 +
>>>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 48 +++++++++++++++++++++++++++++++++++++++-
>>>>>  virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
>>>>>  virt/kvm/arm/vgic/vgic.h         |  4 ++++
>>>>>  4 files changed, 67 insertions(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>>>>> index be0d26f..fd05185 100644
>>>>> --- a/include/linux/irqchip/arm-gic.h
>>>>> +++ b/include/linux/irqchip/arm-gic.h
>>>>> @@ -33,6 +33,7 @@
>>>>>  
>>>>>  #define GIC_DIST_CTRL			0x000
>>>>>  #define GIC_DIST_CTR			0x004
>>>>> +#define GIC_DIST_IIDR			0x008
>>>>>  #define GIC_DIST_IGROUP			0x080
>>>>>  #define GIC_DIST_ENABLE_SET		0x100
>>>>>  #define GIC_DIST_ENABLE_CLEAR		0x180
>>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>>> index 2729a22..69e96f7 100644
>>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>>> @@ -20,9 +20,55 @@
>>>>>  #include "vgic.h"
>>>>>  #include "vgic-mmio.h"
>>>>>  
>>>>> +static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
>>>>> +					    gpa_t addr, unsigned int len)
>>>>> +{
>>>>> +	u32 value;
>>>>> +
>>>>> +	switch (addr & 0x0c) {
>>>>> +	case GIC_DIST_CTRL:
>>>>> +		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
>>>>> +		break;
>>>>> +	case GIC_DIST_CTR:
>>>>> +		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
>>>>> +		value = (value >> 5) - 1;
>>>>> +		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
>>>>> +		break;
>>>>> +	case GIC_DIST_IIDR:
>>>>> +		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
>>>>> +		break;
>>>>> +	default:
>>>>> +		return 0;
>>>>> +	}
>>>>> +
>>>>> +	return extract_bytes(value, addr & 3, len);
>>>>> +}
>>>>> +
>>>>> +static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
>>>>> +				    gpa_t addr, unsigned int len,
>>>>> +				    unsigned long val)
>>>>> +{
>>>>> +	switch (addr & 0x0c) {
>>>>> +	case GIC_DIST_CTRL:
>>>>> +		if (!(addr & 1)) {
>>>>
>>>> what is this !(addr & 1) check?
>>>
>>> We check that the write includes the lowest byte of the register. But as
>>> we only have aligned accesses, it probably doesn't matter... I'll hack
>>> that away.
>>>
>> where do we check to only have aligned accesses?
> 
> Looks like a missing feature. The v2 spec says:
> 
> 4.1.4 GIC register access
> All registers support 32-bit word accesses with the access type defined
> in Table 4-1 on page 4-73 and Table 4-2 on page 4-74.
> In addition, the GICD_IPRIORITYRn, GICD_ITARGETSRn, GICD_CPENDSGIRn, and
> GICD_SPENDSGIRn registers support byte accesses.
> 
> Similar thing for v3 (8.1.3).
> 
> By the look of it, we should add checks in all accessors. I'll get onto it.

What about to tag every register in our vgic_register_region with a
possible access width and do a generic check in
dispatch_mmio_{read,write}? Then we wouldn't need to touch every handler.

Cheers,
Andre.


From christoffer.dall at linaro.org  Wed May 11 06:37:48 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:37:48 +0200
Subject: [PATCH v3 27/55] KVM: arm/arm64: vgic-new: Add PRIORITY
 registers handlers
In-Reply-To: <1462531568-9799-28-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-28-git-send-email-andre.przywara@arm.com>
Message-ID: <20160511133748.GT27623@cbox>

On Fri, May 06, 2016 at 11:45:40AM +0100, Andre Przywara wrote:
> The priority register handlers are shared between the v2 and v3
> emulation, so their implementation goes into vgic-mmio.c, to be
> easily referenced from the v3 emulation as well later.
> There is a corner case when we change the priority of a pending
> interrupt which we don't handle at the moment.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
>  virt/kvm/arm/vgic/vgic-mmio.c    | 39 +++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h    |  7 +++++++
>  3 files changed, 47 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 054b52d..2e17250 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -84,7 +84,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
>  		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index dbf683e..d7fe9e6 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -282,6 +282,45 @@ retry:
>  	}
>  }
>  
> +unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
> +				      gpa_t addr, unsigned int len)
> +{
> +	u32 intid = addr & 0x3ff;
> +	int i;
> +	u64 val = 0;
> +
> +	for (i = 0; i < len; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		val |= (u64)irq->priority << (i * 8);
> +	}
> +
> +	return val;

IPRIORITYRn is specifically one of the registers requiring byte access
to be implemented; why are we not doing the extract_bytes thing here?

> +}
> +
> +/*
> + * We currently don't handle changing the priority of an interrupt that
> + * is already pending on a VCPU. If there is a need for this, we would
> + * need to make this VCPU exit and re-evaluate the priorities, potentially
> + * leading to this interrupt getting presented now to the guest (if it has
> + * been masked by the priority mask before).

I thought we were just going to do a vcpu_kick here?

> + */
> +void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
> +			      gpa_t addr, unsigned int len,
> +			      unsigned long val)
> +{
> +	u32 intid = addr & 0x3ff;
> +	int i;
> +
> +	for (i = 0; i < len; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +		irq->priority = (val >> (i * 8)) & 0xff;

If I wasn't mistaken on my comment in the previous patch, then you have
a problem here too...

> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
>  static int match_region(const void *key, const void *elt)
>  {
>  	const unsigned int offset = (unsigned long)key;
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index fa875dc..cd04ac5 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -107,6 +107,13 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
>  			     gpa_t addr, unsigned int len,
>  			     unsigned long val);
>  
> +unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
> +				      gpa_t addr, unsigned int len);
> +
> +void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
> +			      gpa_t addr, unsigned int len,
> +			      unsigned long val);
> +
>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>  
>  #endif
> -- 
> 2.7.3
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From christoffer.dall at linaro.org  Wed May 11 06:38:51 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:38:51 +0200
Subject: [PATCH v3 23/55] KVM: arm/arm64: vgic-new: Add CTLR, TYPER and
 IIDR handlers
In-Reply-To: <57333359.3000505@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-24-git-send-email-andre.przywara@arm.com>
 <20160511120533.GM27623@cbox> <57332AD8.6050306@arm.com>
 <20160511131556.GR27623@cbox> <57333359.3000505@arm.com>
Message-ID: <20160511133851.GU27623@cbox>

On Wed, May 11, 2016 at 02:27:53PM +0100, Marc Zyngier wrote:
> On 11/05/16 14:15, Christoffer Dall wrote:
> > On Wed, May 11, 2016 at 01:51:36PM +0100, Marc Zyngier wrote:
> >> On 11/05/16 13:05, Christoffer Dall wrote:
> >>> On Fri, May 06, 2016 at 11:45:36AM +0100, Andre Przywara wrote:
> >>>> From: Marc Zyngier <marc.zyngier at arm.com>
> >>>>
> >>>> Those three registers are v2 emulation specific, so their implementation
> >>>> lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
> >>>> as their implementation is pretty simple.
> >>>> When the guest enables the distributor, we kick all VCPUs to get
> >>>> potentially pending interrupts serviced.
> >>>>
> >>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> >>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >>>> ---
> >>>> Changelog RFC..v1:
> >>>> - kick VCPUs is the distributor gets enabled
> >>>> - improve comment
> >>>>
> >>>> Changelog v1 .. v2:
> >>>> - adapt to new MMIO framework
> >>>> - use switch() statements to improve readability
> >>>>
> >>>> Changelog v2 .. v3:
> >>>> - add vgic_kick_vcpus() implementation
> >>>>
> >>>>  include/linux/irqchip/arm-gic.h  |  1 +
> >>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 48 +++++++++++++++++++++++++++++++++++++++-
> >>>>  virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
> >>>>  virt/kvm/arm/vgic/vgic.h         |  4 ++++
> >>>>  4 files changed, 67 insertions(+), 1 deletion(-)
> >>>>
> >>>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
> >>>> index be0d26f..fd05185 100644
> >>>> --- a/include/linux/irqchip/arm-gic.h
> >>>> +++ b/include/linux/irqchip/arm-gic.h
> >>>> @@ -33,6 +33,7 @@
> >>>>  
> >>>>  #define GIC_DIST_CTRL			0x000
> >>>>  #define GIC_DIST_CTR			0x004
> >>>> +#define GIC_DIST_IIDR			0x008
> >>>>  #define GIC_DIST_IGROUP			0x080
> >>>>  #define GIC_DIST_ENABLE_SET		0x100
> >>>>  #define GIC_DIST_ENABLE_CLEAR		0x180
> >>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >>>> index 2729a22..69e96f7 100644
> >>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >>>> @@ -20,9 +20,55 @@
> >>>>  #include "vgic.h"
> >>>>  #include "vgic-mmio.h"
> >>>>  
> >>>> +static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
> >>>> +					    gpa_t addr, unsigned int len)
> >>>> +{
> >>>> +	u32 value;
> >>>> +
> >>>> +	switch (addr & 0x0c) {
> >>>> +	case GIC_DIST_CTRL:
> >>>> +		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
> >>>> +		break;
> >>>> +	case GIC_DIST_CTR:
> >>>> +		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
> >>>> +		value = (value >> 5) - 1;
> >>>> +		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
> >>>> +		break;
> >>>> +	case GIC_DIST_IIDR:
> >>>> +		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
> >>>> +		break;
> >>>> +	default:
> >>>> +		return 0;
> >>>> +	}
> >>>> +
> >>>> +	return extract_bytes(value, addr & 3, len);
> >>>> +}
> >>>> +
> >>>> +static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
> >>>> +				    gpa_t addr, unsigned int len,
> >>>> +				    unsigned long val)
> >>>> +{
> >>>> +	switch (addr & 0x0c) {
> >>>> +	case GIC_DIST_CTRL:
> >>>> +		if (!(addr & 1)) {
> >>>
> >>> what is this !(addr & 1) check?
> >>
> >> We check that the write includes the lowest byte of the register. But as
> >> we only have aligned accesses, it probably doesn't matter... I'll hack
> >> that away.
> >>
> > where do we check to only have aligned accesses?
> 
> Looks like a missing feature. The v2 spec says:
> 
> 4.1.4 GIC register access
> All registers support 32-bit word accesses with the access type defined
> in Table 4-1 on page 4-73 and Table 4-2 on page 4-74.
> In addition, the GICD_IPRIORITYRn, GICD_ITARGETSRn, GICD_CPENDSGIRn, and
> GICD_SPENDSGIRn registers support byte accesses.
> 
> Similar thing for v3 (8.1.3).
> 
> By the look of it, we should add checks in all accessors. I'll get onto it.
> 
Yeah, that's probably the easiest.

-Christoffer


From christoffer.dall at linaro.org  Wed May 11 06:41:23 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:41:23 +0200
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <57333286.2050708@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
 <20160511123423.GO27623@cbox> <57332DCD.1020701@arm.com>
 <20160511131402.GQ27623@cbox> <57333286.2050708@arm.com>
Message-ID: <20160511134123.GV27623@cbox>

On Wed, May 11, 2016 at 02:24:22PM +0100, Andre Przywara wrote:
> 
> 
> On 11/05/16 14:14, Christoffer Dall wrote:
> > On Wed, May 11, 2016 at 02:04:13PM +0100, Andre Przywara wrote:
> >> Hi,
> >>
> >> On 11/05/16 13:34, Christoffer Dall wrote:
> >>> On Fri, May 06, 2016 at 11:45:37AM +0100, Andre Przywara wrote:
> >>>> As the enable register handlers are shared between the v2 and v3
> >>>> emulation, their implementation goes into vgic-mmio.c, to be easily
> >>>> referenced from the v3 emulation as well later.
> >>>>
> >>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >>>> ---
> >>>> Changelog RFC..v1:
> >>>> - use lower bits of address to determine IRQ number
> >>>> - remove TODO, confirmed to be fine
> >>>>
> >>>> Changelog v1 .. v2:
> >>>> - adapt to new MMIO framework
> >>>>
> >>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
> >>>>  virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
> >>>>  virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
> >>>>  3 files changed, 69 insertions(+), 2 deletions(-)
> >>>>
> >>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >>>> index 69e96f7..448d1da 100644
> >>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >>>> @@ -72,9 +72,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
> >>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
> >>>>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
> >>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
> >>>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >>>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
> >>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
> >>>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >>>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
> >>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
> >>>>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
> >>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> >>>> index 41cf4f4..077ae86 100644
> >>>> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> >>>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> >>>> @@ -46,6 +46,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> >>>>  	/* Ignore */
> >>>>  }
> >>>>  
> >>>> +/*
> >>>> + * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
> >>>> + * of the enabled bit, so there is only one function for both here.
> >>>> + */
> >>>> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
> >>>> +				    gpa_t addr, unsigned int len)
> >>>> +{
> >>>> +	u32 intid = (addr & 0x7f) * 8;
> >>>
> >>> is there anything we can do about this to make it more intuitive?  A
> >>> macro to generate the mask/offset based on bits per interrupt or
> >>> something?
> >>
> >> Yes, something where you give it the address and the bits-per-IRQ and it
> >> tells you the IRQ number.
> >> Not sure it is advisable to squash this into v4 still?
> >>
> >>>
> >>>> +	u32 value = 0;
> >>>> +	int i;
> >>>> +
> >>>> +	/* Loop over all IRQs affected by this read */
> >>>> +	for (i = 0; i < len * 8; i++) {
> >>>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> >>>> +
> >>>> +		if (irq->enabled)
> >>>> +			value |= (1U << i);
> >>>
> >>> I couldn't find the code anywhere that enforces word-aligned accesses to
> >>> these registers.  Do we have that?
> >>
> >> Not that I am aware of. I was suggesting this since we have one in the
> >> IROUTER function. Architecturally we don't need to support halfword
> >> accesses, it's: byte + word, word only or double-word + word, depending
> >> on the actual register, IIRC.
> >> As a fix we can at least deny (read: ignore) halfword accesses in
> >> general in the dispatcher. Shall I do this (two two-liners)?
> >> I think byte and word accesses are safe with the existing handlers last
> >> time I checked.
> >>
> >>> If that's not the case, doesn't this break of you do a non-word aligned
> >>> access?
> >>
> >> Why would it? vgic_data_host_to_mmio_bus and extract_bytes should cover
> >> this, shouldn't they?
> >>
> > 
> > I think this breaks on a simple byte access.  Let's say you are
> > accessing byte 1 (addr & 0x7ff == 1), then because you start your loop
> > at 0, you're going to set bits [7:0] in the value variable, and then
> > extract bits [15:8] in extract_bytes(), right?
> 
> Looks like, yes. I thought that it would take care of that, because a
> handler function shouldn't be bothered with this: it just acts on the
> lower bytes (till the length) and extract_bytes() does the rest. I think
> this is what the old magic vgic_reg_access does due to "regval >>
> word_offset".
> 
> Do you care to fix this in extract_bytes?
> 
I don't think this is a fix to extract_bytes.  I think the issue is with
how we build the values.  I though the semanticsehre were that the u32
value in this case would the entire 32-bit register, so can't we simply
mask off the lower bits in the addr on entry to these functions and add
additional checks if there are registers where specifically do not wish
to support byte accessed?

-Christoffer


From geert at linux-m68k.org  Wed May 11 06:46:07 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Wed, 11 May 2016 15:46:07 +0200
Subject: [PATCHv3 0/4] ARM: dts: r8a779[0-4]: Reference both DMA
 controllers
In-Reply-To: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <CAMuHMdWdfJMn+GzEQxpaMW3xYKZQYGK4v_tS_4ZiYjeRNQqGXA@mail.gmail.com>

Hi Niklas,

On Wed, May 11, 2016 at 3:13 PM, Niklas S?derlund
<niklas.soderlund+renesas at ragnatech.se> wrote:
> R-Car Gen2 have two DMA controllers, which are equivalent. However DMA
> slaves were tied only to a single DMA controller in .dtsi. This series
> add references to to both DMA controllers for all nodes that previously
> only referenced one of them. It also adds dma references to the SDHI
> nodes for r8a7794 which according to the datasheet should work but I
> have not access to HW to verify.

Thanks for your series!

> Niklas S?derlund (4):
>   ARM: dts: r8a7790: Reference both DMA controllers
>   ARM: dts: r8a7791: Reference both DMA controllers
>   ARM: dts: r8a7793: Reference both DMA controllers
>   ARM: dts: r8a7794: Reference both DMA controllers

For patches 2-4:
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

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 christoffer.dall at linaro.org  Wed May 11 06:47:25 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:47:25 +0200
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <5733300C.9070304@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
 <20160511123423.GO27623@cbox> <5733300C.9070304@arm.com>
Message-ID: <20160511134725.GW27623@cbox>

On Wed, May 11, 2016 at 02:13:48PM +0100, Marc Zyngier wrote:
> On 11/05/16 13:34, Christoffer Dall wrote:
> > On Fri, May 06, 2016 at 11:45:37AM +0100, Andre Przywara wrote:
> >> As the enable register handlers are shared between the v2 and v3
> >> emulation, their implementation goes into vgic-mmio.c, to be easily
> >> referenced from the v3 emulation as well later.
> >>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >> Changelog RFC..v1:
> >> - use lower bits of address to determine IRQ number
> >> - remove TODO, confirmed to be fine
> >>
> >> Changelog v1 .. v2:
> >> - adapt to new MMIO framework
> >>
> >>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
> >>  virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
> >>  virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
> >>  3 files changed, 69 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> index 69e96f7..448d1da 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> @@ -72,9 +72,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
> >>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
> >> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
> >> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
> >>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> >>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> >> index 41cf4f4..077ae86 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> >> @@ -46,6 +46,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> >>  	/* Ignore */
> >>  }
> >>  
> >> +/*
> >> + * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
> >> + * of the enabled bit, so there is only one function for both here.
> >> + */
> >> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
> >> +				    gpa_t addr, unsigned int len)
> >> +{
> >> +	u32 intid = (addr & 0x7f) * 8;
> > 
> > is there anything we can do about this to make it more intuitive?  A
> > macro to generate the mask/offset based on bits per interrupt or
> > something?
> 
> Untested (and thus probably wrong):
> 
> #define VGIC_ADDR_IRQ_MASK(bits) ((1024 - 1) >> (4 - (bits))

you're going to have to explain this to me, where is the (4 - bits)
coming from?

> #define VGIC_ADDR_IRQ_MULT(bits) (8 / (bits))
> #define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
> 					 VGIC_ADDR_IRQ_MULT(bits))


> 
> 	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
> 
> Thanks,
> 
> 	M.
> -- 
> Jazz is not dead. It just smells funny...


From geert at linux-m68k.org  Wed May 11 06:45:17 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Wed, 11 May 2016 15:45:17 +0200
Subject: [PATCHv3 1/4] ARM: dts: r8a7790: Reference both DMA controllers
In-Reply-To: <1462972438-20797-2-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <1462972438-20797-2-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <CAMuHMdWoPThi0w6siA5LJ60oEH6JMv4x80b_Spg5aF-uHq3WqQ@mail.gmail.com>

Hi Niklas,

On Wed, May 11, 2016 at 3:13 PM, Niklas S?derlund
<niklas.soderlund+renesas at ragnatech.se> wrote:
> R-Car Gen2 have two DMA controllers, which are equivalent. Add
> references to both dmac0 and dmac1 so the driver can choose which one to
> use.
>
> Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
> ---
>  arch/arm/boot/dts/r8a7790.dtsi | 131 ++++++++++++++++++++++++-----------------
>  1 file changed, 78 insertions(+), 53 deletions(-)
>
> diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
> index 83cf23c..14fcd19 100644
> --- a/arch/arm/boot/dts/r8a7790.dtsi
> +++ b/arch/arm/boot/dts/r8a7790.dtsi

> @@ -755,9 +773,9 @@
>                 clocks = <&mstp3_clks R8A7790_CLK_SCIF2>, <&zs_clk>,
>                          <&scif_clk>;
>                 clock-names = "fck", "brg_int", "scif_clk";
> -               dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
> -               dma-names = "tx", "rx";
> -               power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;

Please keep the above line.

> +               dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
> +                      <&dmac1 0x2b>, <&dmac1 0x2c>;
> +               dma-names = "tx", "rx", "tx", "rx";
>                 status = "disabled";
>         };

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 christoffer.dall at linaro.org  Wed May 11 06:30:16 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:16 +0200
Subject: [PULL 23/29] irqchip/gic-v3: Prefix all pr_* messages by "GICv3: "
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-24-git-send-email-christoffer.dall@linaro.org>

From: Julien Grall <julien.grall at arm.com>

Currently, most of the pr_* messages in the GICv3 driver don't have a
prefix.  Add one to make clear where the messages come from.

Signed-off-by: Julien Grall <julien.grall at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 drivers/irqchip/irq-gic-v3.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 5b7d3c2..6dc6f03 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -15,6 +15,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#define pr_fmt(fmt)	"GICv3: " fmt
+
 #include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/cpu_pm.h>
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:15 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:15 +0200
Subject: [PULL 22/29] irqchip/gic-v2: Parse and export virtual GIC information
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-23-git-send-email-christoffer.dall@linaro.org>

From: Julien Grall <julien.grall at arm.com>

For now, the firmware tables are parsed 2 times: once in the GIC
drivers, the other timer when initializing the vGIC. It means code
duplication and make more tedious to add the support for another
firmware table (like ACPI).

Introduce a new structure and set of helpers to get/set the virtual GIC
information. Also fill up the structure for GICv2.

Signed-off-by: Julien Grall <julien.grall at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 drivers/irqchip/irq-gic-common.c       | 13 ++++++
 drivers/irqchip/irq-gic-common.h       |  3 ++
 drivers/irqchip/irq-gic.c              | 76 +++++++++++++++++++++++++++++++++-
 include/linux/irqchip/arm-gic-common.h | 33 +++++++++++++++
 4 files changed, 124 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/irqchip/arm-gic-common.h

diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index f174ce0..2e9443b 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -21,6 +21,19 @@
 
 #include "irq-gic-common.h"
 
+static const struct gic_kvm_info *gic_kvm_info;
+
+const struct gic_kvm_info *gic_get_kvm_info(void)
+{
+	return gic_kvm_info;
+}
+
+void gic_set_kvm_info(const struct gic_kvm_info *info)
+{
+	BUG_ON(gic_kvm_info != NULL);
+	gic_kvm_info = info;
+}
+
 void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
 		void *data)
 {
diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h
index fff697d..205e5fd 100644
--- a/drivers/irqchip/irq-gic-common.h
+++ b/drivers/irqchip/irq-gic-common.h
@@ -19,6 +19,7 @@
 
 #include <linux/of.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip/arm-gic-common.h>
 
 struct gic_quirk {
 	const char *desc;
@@ -35,4 +36,6 @@ void gic_cpu_config(void __iomem *base, void (*sync_access)(void));
 void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
 		void *data);
 
+void gic_set_kvm_info(const struct gic_kvm_info *info);
+
 #endif /* _IRQ_GIC_COMMON_H */
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 7a73786..3f1d9fd 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -102,6 +102,8 @@ static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE;
 
 static struct gic_chip_data gic_data[CONFIG_ARM_GIC_MAX_NR] __read_mostly;
 
+static struct gic_kvm_info gic_v2_kvm_info;
+
 #ifdef CONFIG_GIC_NON_BANKED
 static void __iomem *gic_get_percpu_base(union gic_base *base)
 {
@@ -1189,6 +1191,29 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
 	return true;
 }
 
+static void __init gic_of_setup_kvm_info(struct device_node *node)
+{
+	int ret;
+	struct resource *vctrl_res = &gic_v2_kvm_info.vctrl;
+	struct resource *vcpu_res = &gic_v2_kvm_info.vcpu;
+
+	gic_v2_kvm_info.type = GIC_V2;
+
+	gic_v2_kvm_info.maint_irq = irq_of_parse_and_map(node, 0);
+	if (!gic_v2_kvm_info.maint_irq)
+		return;
+
+	ret = of_address_to_resource(node, 2, vctrl_res);
+	if (ret)
+		return;
+
+	ret = of_address_to_resource(node, 3, vcpu_res);
+	if (ret)
+		return;
+
+	gic_set_kvm_info(&gic_v2_kvm_info);
+}
+
 int __init
 gic_of_init(struct device_node *node, struct device_node *parent)
 {
@@ -1218,8 +1243,10 @@ gic_of_init(struct device_node *node, struct device_node *parent)
 
 	__gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset,
 			 &node->fwnode);
-	if (!gic_cnt)
+	if (!gic_cnt) {
 		gic_init_physaddr(node);
+		gic_of_setup_kvm_info(node);
+	}
 
 	if (parent) {
 		irq = irq_of_parse_and_map(node, 0);
@@ -1248,6 +1275,10 @@ IRQCHIP_DECLARE(pl390, "arm,pl390", gic_of_init);
 static struct
 {
 	phys_addr_t cpu_phys_base;
+	u32 maint_irq;
+	int maint_irq_mode;
+	phys_addr_t vctrl_base;
+	phys_addr_t vcpu_base;
 } acpi_data __initdata;
 
 static int __init
@@ -1272,6 +1303,12 @@ gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
 		return -EINVAL;
 
 	acpi_data.cpu_phys_base = gic_cpu_base;
+	acpi_data.maint_irq = processor->vgic_interrupt;
+	acpi_data.maint_irq_mode = (processor->flags & ACPI_MADT_VGIC_IRQ_MODE) ?
+				    ACPI_EDGE_SENSITIVE : ACPI_LEVEL_SENSITIVE;
+	acpi_data.vctrl_base = processor->gich_base_address;
+	acpi_data.vcpu_base = processor->gicv_base_address;
+
 	cpu_base_assigned = 1;
 	return 0;
 }
@@ -1302,6 +1339,41 @@ static bool __init gic_validate_dist(struct acpi_subtable_header *header,
 
 #define ACPI_GICV2_DIST_MEM_SIZE	(SZ_4K)
 #define ACPI_GIC_CPU_IF_MEM_SIZE	(SZ_8K)
+#define ACPI_GICV2_VCTRL_MEM_SIZE	(SZ_4K)
+#define ACPI_GICV2_VCPU_MEM_SIZE	(SZ_8K)
+
+static void __init gic_acpi_setup_kvm_info(void)
+{
+	int irq;
+	struct resource *vctrl_res = &gic_v2_kvm_info.vctrl;
+	struct resource *vcpu_res = &gic_v2_kvm_info.vcpu;
+
+	gic_v2_kvm_info.type = GIC_V2;
+
+	if (!acpi_data.vctrl_base)
+		return;
+
+	vctrl_res->flags = IORESOURCE_MEM;
+	vctrl_res->start = acpi_data.vctrl_base;
+	vctrl_res->end = vctrl_res->start + ACPI_GICV2_VCTRL_MEM_SIZE - 1;
+
+	if (!acpi_data.vcpu_base)
+		return;
+
+	vcpu_res->flags = IORESOURCE_MEM;
+	vcpu_res->start = acpi_data.vcpu_base;
+	vcpu_res->end = vcpu_res->start + ACPI_GICV2_VCPU_MEM_SIZE - 1;
+
+	irq = acpi_register_gsi(NULL, acpi_data.maint_irq,
+				acpi_data.maint_irq_mode,
+				ACPI_ACTIVE_HIGH);
+	if (irq <= 0)
+		return;
+
+	gic_v2_kvm_info.maint_irq = irq;
+
+	gic_set_kvm_info(&gic_v2_kvm_info);
+}
 
 static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
 				   const unsigned long end)
@@ -1359,6 +1431,8 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
 	if (IS_ENABLED(CONFIG_ARM_GIC_V2M))
 		gicv2m_init(NULL, gic_data[0].domain);
 
+	gic_acpi_setup_kvm_info();
+
 	return 0;
 }
 IRQCHIP_ACPI_DECLARE(gic_v2, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
diff --git a/include/linux/irqchip/arm-gic-common.h b/include/linux/irqchip/arm-gic-common.h
new file mode 100644
index 0000000..ef34f6f
--- /dev/null
+++ b/include/linux/irqchip/arm-gic-common.h
@@ -0,0 +1,33 @@
+/*
+ * include/linux/irqchip/arm-gic-common.h
+ *
+ * Copyright (C) 2016 ARM Limited, All Rights Reserved.
+ *
+ * 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.
+ */
+#ifndef __LINUX_IRQCHIP_ARM_GIC_COMMON_H
+#define __LINUX_IRQCHIP_ARM_GIC_COMMON_H
+
+#include <linux/types.h>
+#include <linux/ioport.h>
+
+enum gic_type {
+	GIC_V2,
+};
+
+struct gic_kvm_info {
+	/* GIC type */
+	enum gic_type	type;
+	/* Virtual CPU interface */
+	struct resource vcpu;
+	/* Interrupt number */
+	unsigned int	maint_irq;
+	/* Virtual control interface */
+	struct resource vctrl;
+};
+
+const struct gic_kvm_info *gic_get_kvm_info(void);
+
+#endif /* __LINUX_IRQCHIP_ARM_GIC_COMMON_H */
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:14 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:14 +0200
Subject: [PULL 21/29] irqchip/gic-v2: Gather ACPI specific data in a single
 structure
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-22-git-send-email-christoffer.dall@linaro.org>

From: Julien Grall <julien.grall at arm.com>

The ACPI code requires to use global variables in order to collect
information from the tables.

For now, a single global variable is used, but more will be added in a
subsequent patch. To make clear they are ACPI specific, gather all the
information in a single structure.

Signed-off-by: Julien Grall <julien.grall at arm.com>
Acked-by: Christofer Dall <christoffer.dall at linaro.org>
Acked-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 drivers/irqchip/irq-gic.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 282344b..7a73786 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -1245,7 +1245,10 @@ IRQCHIP_DECLARE(pl390, "arm,pl390", gic_of_init);
 #endif
 
 #ifdef CONFIG_ACPI
-static phys_addr_t cpu_phy_base __initdata;
+static struct
+{
+	phys_addr_t cpu_phys_base;
+} acpi_data __initdata;
 
 static int __init
 gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
@@ -1265,10 +1268,10 @@ gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
 	 * All CPU interface addresses have to be the same.
 	 */
 	gic_cpu_base = processor->base_address;
-	if (cpu_base_assigned && gic_cpu_base != cpu_phy_base)
+	if (cpu_base_assigned && gic_cpu_base != acpi_data.cpu_phys_base)
 		return -EINVAL;
 
-	cpu_phy_base = gic_cpu_base;
+	acpi_data.cpu_phys_base = gic_cpu_base;
 	cpu_base_assigned = 1;
 	return 0;
 }
@@ -1316,7 +1319,7 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
 		return -EINVAL;
 	}
 
-	cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
+	cpu_base = ioremap(acpi_data.cpu_phys_base, ACPI_GIC_CPU_IF_MEM_SIZE);
 	if (!cpu_base) {
 		pr_err("Unable to map GICC registers\n");
 		return -ENOMEM;
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:10 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:10 +0200
Subject: [PULL 17/29] arm64: kvm: Add support for 16K pages
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-18-git-send-email-christoffer.dall@linaro.org>

From: Suzuki K Poulose <suzuki.poulose at arm.com>

Now that we can handle stage-2 page tables independent
of the host page table levels, wire up the 16K page
support.

Cc: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 arch/arm64/include/asm/kvm_arm.h | 13 +++++++++++--
 arch/arm64/kvm/Kconfig           |  1 -
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 1281d98..c6cbb36 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -114,6 +114,7 @@
 #define VTCR_EL2_PS_MASK	TCR_EL2_PS_MASK
 #define VTCR_EL2_TG0_MASK	TCR_TG0_MASK
 #define VTCR_EL2_TG0_4K		TCR_TG0_4K
+#define VTCR_EL2_TG0_16K	TCR_TG0_16K
 #define VTCR_EL2_TG0_64K	TCR_TG0_64K
 #define VTCR_EL2_SH0_MASK	TCR_SH0_MASK
 #define VTCR_EL2_SH0_INNER	TCR_SH0_INNER
@@ -139,7 +140,7 @@
  * (see hyp-init.S).
  *
  * Note that when using 4K pages, we concatenate two first level page tables
- * together.
+ * together. With 16K pages, we concatenate 16 first level page tables.
  *
  * The magic numbers used for VTTBR_X in this patch can be found in Tables
  * D4-23 and D4-25 in ARM DDI 0487A.b.
@@ -157,7 +158,15 @@
  */
 #define VTCR_EL2_TGRAN_FLAGS		(VTCR_EL2_TG0_64K | VTCR_EL2_SL0_LVL1)
 #define VTTBR_X_TGRAN_MAGIC		38
-#else
+#elif defined(CONFIG_ARM64_16K_PAGES)
+/*
+ * Stage2 translation configuration:
+ * 16kB pages (TG0 = 2)
+ * 2 level page tables (SL = 1)
+ */
+#define VTCR_EL2_TGRAN_FLAGS		(VTCR_EL2_TG0_16K | VTCR_EL2_SL0_LVL1)
+#define VTTBR_X_TGRAN_MAGIC		42
+#else	/* 4K */
 /*
  * Stage2 translation configuration:
  * 4kB pages (TG0 = 0)
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index de7450d..aa2e34e 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -22,7 +22,6 @@ config KVM_ARM_VGIC_V3
 config KVM
 	bool "Kernel-based Virtual Machine (KVM) support"
 	depends on OF
-	depends on !ARM64_16K_PAGES
 	select MMU_NOTIFIER
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Wed May 11 06:30:13 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 15:30:13 +0200
Subject: [PULL 20/29] clocksource: arm_arch_timer: Extend arch_timer_kvm_info
 to get the virtual IRQ
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1462973422-10021-21-git-send-email-christoffer.dall@linaro.org>

From: Julien Grall <julien.grall at arm.com>

Currently, the firmware table is parsed by the virtual timer code in
order to retrieve the virtual timer interrupt. However, this is already
done by the arch timer driver.

To avoid code duplication, extend arch_timer_kvm_info to get the virtual
IRQ.

Note that the KVM code will be modified in a subsequent patch.

Signed-off-by: Julien Grall <julien.grall at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 2 ++
 include/clocksource/arm_arch_timer.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 62bdfe7..bb58224 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -750,6 +750,8 @@ static void __init arch_timer_init(void)
 
 	arch_timer_register();
 	arch_timer_common_init();
+
+	arch_timer_kvm_info.virtual_irq = arch_timer_ppi[VIRT_PPI];
 }
 
 static void __init arch_timer_of_init(struct device_node *np)
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 9101ed6b..9dd996a 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -51,6 +51,7 @@ enum arch_timer_reg {
 
 struct arch_timer_kvm_info {
 	struct timecounter timecounter;
+	int virtual_irq;
 };
 
 #ifdef CONFIG_ARM_ARCH_TIMER
-- 
2.1.2.330.g565301e.dirty



From robin.murphy at arm.com  Wed May 11 06:48:47 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Wed, 11 May 2016 14:48:47 +0100
Subject: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability at
 msi domain
In-Reply-To: <5732FF04.6060202@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-6-git-send-email-eric.auger@linaro.org>
 <20160509164942.5af8b30d@t450s.home> <57320803.8070506@linaro.org>
 <57321952.2020206@arm.com> <5732EF96.4070001@linaro.org>
 <5732FBF0.4040105@arm.com> <5732FF04.6060202@linaro.org>
Message-ID: <5733383F.9060202@arm.com>

On 11/05/16 10:44, Eric Auger wrote:
> Hi Robin,
> On 05/11/2016 11:31 AM, Robin Murphy wrote:
>> On 11/05/16 09:38, Eric Auger wrote:
>>> Hi Robin, Alex,
>>> On 05/10/2016 07:24 PM, Robin Murphy wrote:
>>>> Hi Eric,
>>>>
>>>> On 10/05/16 17:10, Eric Auger wrote:
>>>>> Hi Alex,
>>>>> On 05/10/2016 12:49 AM, Alex Williamson wrote:
>>>>>> On Wed,  4 May 2016 11:54:16 +0000
>>>>>> Eric Auger <eric.auger at linaro.org> wrote:
>>>>>>
>>>>>>> On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is
>>>>>>> abstracted
>>>>>>> by the msi controller. vfio_safe_irq_domain allows to check whether
>>>>>>> interrupts are "safe" for a given device. They are if the device does
>>>>>>> not use MSI
>>>>>>
>>>>>> Are we sure we're not opening a security hole here?  An MSI is
>>>>>> simply a
>>>>>> DMA write, so really whether or not a device uses MSI is irrelevant.
>>>>>> If it can generate a DMA to the MSI doorbell then we need to be
>>>>>> protected and I think we pretty much need to assume that devices are
>>>>>> DMA capable.  Do the MSI domain checks cover this?
>>>>> Let me try to rephrase: we check the device is not attached to an MSI
>>>>> controller (I think this is the semantic of dev_get_msi_domain(dev)).
>>>>>
>>>>> If it is not, we don't have to care about MSI isolation: there will be
>>>>> no IOMMU binding between the device and any MSI doorbell. If it is we
>>>>> check the msi domain is backed by an MSI controller able to perform MSI
>>>>> isolation.
>>>>>
>>>>> So effectively "usage of MSIs" is improper - since it is decided after
>>>>> the group attachment anyway  - and the commit message should rather
>>>>> state "if the device is linked to an MSI controller" (dt msi-parent
>>>>> notion I think).
>>>>
>>>> Hmm, I think Alex has a point here - on a GICv2m I can happily fire
>>>> arbitrary MSIs from _a shell_ (using /dev/mem), and the CPUs definitely
>>>> aren't in an MSI domain, so I don't think it's valid to assume that a
>>>> device using only wired interrupts, therefore with no connection to any
>>>> MSI controller, isn't still capable of maliciously spewing DMA all over
>>>> any and every doorbell region in the system.
>>>
>>> Sorry but I still don't get the point. For the device to reach the
>>> doorbell there must be an IOMMU mapping.
>>
>> Only when the doorbell is _downstream_ of IOMMU translation.
> Yes but that's the root hypothesis with VFIO assignment, right?
>
> Except if the no-iommu option is explicitly set by the userspace, there
> must be an IOMMU downstream to the device that protects all the DMA
> transactions.

The IOMMU is downstream of the device, clearly, but the MSI machinery 
itself could be _in between_ the two - say, integrated into a PCIe root 
complex served by an external SMMU. The doorbell is carved out of the 
upstream address space so that a write targeting the appropriate address 
hits it directly and never even goes out to the SMMU - e.g. 
http://thread.gmane.org/gmane.linux.kernel.pci/47174/focus=47268

>>> - if the device is not attached to an MSI domain, there won't be any
>>> doorbell iommu mapping built by this series, so no risk, right?
>>>
>>> The device will be allowed to reach only memory iommu mapped by
>>> userspace with VFIO DMA MAP standard API. Of course if the userspace can
>>> mmap all the host PA that's a more general issue, right?
>>>
>>> - If the device is attached to an MSI domain (msi-parent link), 2 cases:
>>> 1) the MSI controller advertises MSI isolation (ITS cases), no risk
>>> 2) the MSI controller does not advertise MSI isolation (GICv2m), there
>>> is a security hole.
>>>      a) by default we reject the device attachment
>>>      b) if the userspace overrides the safe interrupt option he accepts
>>> the security hole
>>>
>>> What am I missing?
>>
>> The x86-with-interrupt-remapping-disabled case. Currently, without
>> unsafe_interrupts, everything is rejected - with this patch, we'll still
>> reject anything with an MSI domain, but e.g. legacy PCI devices using
>> INTx would be free to scribble all over the un-translated interrupt
>> region willy-nilly.
> Assuming we have an IOMMU, either we have translated transactions or
> faults? So if legacy PCI devices try to write into a doorbell, there
> must be faults because there is no IOMMU mapping for doorbells?

To the best of my understanding, having been wading through the VT-d 
spec, the case on x86 is as above (OK, so strictly it's more "in 
parallel with" than "in front of") - writes outside the 0xFEExxxxx 
interrupt region go to the DMA remapping units, whereas writes within 
that region go to the interrupt remapping unit, and if that's disabled 
or not implemented, simply sail straight through to the APIC beyond.

Robin.

> Best Regards
>
> Eric
>   That's the subtle, but significant, change in
>> behaviour.
>>
>> Robin.
>>
>>> Best Regards
>>>
>>> Eric
>>>>
>>>> Robin.
>>>>
>>>>> Does it sound better?
>>>>>
>>>>> Regards
>>>>>
>>>>> Eric
>>>>>>
>>>>>>> or if the device uses MSI and the msi-parent controller
>>>>>>> supports IRQ remapping.
>>>>>>>
>>>>>>> Then we check at group level if all devices have safe interrupts: if
>>>>>>> not,
>>>>>>> we only allow the group to be attached if allow_unsafe_interrupts is
>>>>>>> set.
>>>>>>>
>>>>>>> At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP. This is
>>>>>>> changed in next patch.
>>>>>>>
>>>>>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>>>>>>
>>>>>>> ---
>>>>>>> v3 -> v4:
>>>>>>> - rename vfio_msi_parent_irq_remapping_capable into
>>>>>>> vfio_safe_irq_domain
>>>>>>>      and irq_remapping into safe_irq_domains
>>>>>>>
>>>>>>> v2 -> v3:
>>>>>>> - protect vfio_msi_parent_irq_remapping_capable with
>>>>>>>      CONFIG_GENERIC_MSI_IRQ_DOMAIN
>>>>>>> ---
>>>>>>>     drivers/vfio/vfio_iommu_type1.c | 44
>>>>>>> +++++++++++++++++++++++++++++++++++++++--
>>>>>>>     1 file changed, 42 insertions(+), 2 deletions(-)
>>>>>>>
>>>>>>> diff --git a/drivers/vfio/vfio_iommu_type1.c
>>>>>>> b/drivers/vfio/vfio_iommu_type1.c
>>>>>>> index 4d3a6f1..2fc8197 100644
>>>>>>> --- a/drivers/vfio/vfio_iommu_type1.c
>>>>>>> +++ b/drivers/vfio/vfio_iommu_type1.c
>>>>>>> @@ -37,6 +37,8 @@
>>>>>>>     #include <linux/vfio.h>
>>>>>>>     #include <linux/workqueue.h>
>>>>>>>     #include <linux/msi-iommu.h>
>>>>>>> +#include <linux/irqdomain.h>
>>>>>>> +#include <linux/msi.h>
>>>>>>>
>>>>>>>     #define DRIVER_VERSION  "0.2"
>>>>>>>     #define DRIVER_AUTHOR   "Alex Williamson
>>>>>>> <alex.williamson at redhat.com>"
>>>>>>> @@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev,
>>>>>>> void *data)
>>>>>>>         return 0;
>>>>>>>     }
>>>>>>>
>>>>>>> +/**
>>>>>>> + * vfio_safe_irq_domain: returns whether the irq domain
>>>>>>> + * the device is attached to is safe with respect to MSI isolation.
>>>>>>> + * If the irq domain is not an MSI domain, we return it is safe.
>>>>>>> + *
>>>>>>> + * @dev: device handle
>>>>>>> + * @data: unused
>>>>>>> + * returns 0 if the irq domain is safe, -1 if not.
>>>>>>> + */
>>>>>>> +static int vfio_safe_irq_domain(struct device *dev, void *data)
>>>>>>> +{
>>>>>>> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
>>>>>>> +    struct irq_domain *domain;
>>>>>>> +    struct msi_domain_info *info;
>>>>>>> +
>>>>>>> +    domain = dev_get_msi_domain(dev);
>>>>>>> +    if (!domain)
>>>>>>> +        return 0;
>>>>>>> +
>>>>>>> +    info = msi_get_domain_info(domain);
>>>>>>> +
>>>>>>> +    if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
>>>>>>> +        return -1;
>>>>>>> +#endif
>>>>>>> +    return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>>     static int vfio_iommu_replay(struct vfio_iommu *iommu,
>>>>>>>                      struct vfio_domain *domain)
>>>>>>>     {
>>>>>>> @@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void
>>>>>>> *iommu_data,
>>>>>>>         struct vfio_group *group, *g;
>>>>>>>         struct vfio_domain *domain, *d;
>>>>>>>         struct bus_type *bus = NULL;
>>>>>>> -    int ret;
>>>>>>> +    int ret, safe_irq_domains;
>>>>>>>
>>>>>>>         mutex_lock(&iommu->lock);
>>>>>>>
>>>>>>> @@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void
>>>>>>> *iommu_data,
>>>>>>>
>>>>>>>         group->iommu_group = iommu_group;
>>>>>>>
>>>>>>> +    /*
>>>>>>> +     * Determine if all the devices of the group have a safe irq
>>>>>>> domain
>>>>>>> +     * with respect to MSI isolation
>>>>>>> +     */
>>>>>>> +    safe_irq_domains = !iommu_group_for_each_dev(iommu_group, &bus,
>>>>>>> +                       vfio_safe_irq_domain);
>>>>>>> +
>>>>>>>         /* Determine bus_type in order to allocate a domain */
>>>>>>>         ret = iommu_group_for_each_dev(iommu_group, &bus,
>>>>>>> vfio_bus_type);
>>>>>>>         if (ret)
>>>>>>> @@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void
>>>>>>> *iommu_data,
>>>>>>>         INIT_LIST_HEAD(&domain->group_list);
>>>>>>>         list_add(&group->next, &domain->group_list);
>>>>>>>
>>>>>>> +    /*
>>>>>>> +     * to advertise safe interrupts either the IOMMU or the MSI
>>>>>>> controllers
>>>>>>> +     * must support IRQ remapping/interrupt translation
>>>>>>> +     */
>>>>>>>         if (!allow_unsafe_interrupts &&
>>>>>>> -        !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
>>>>>>> +        (!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) &&
>>>>>>> !safe_irq_domains)) {
>>>>>>>             pr_warn("%s: No interrupt remapping support.  Use the
>>>>>>> module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU
>>>>>>> support on this platform\n",
>>>>>>>                    __func__);
>>>>>>>             ret = -EPERM;
>>>>>>
>>>>>
>>>>
>>>
>>
>



From andre.przywara at arm.com  Wed May 11 06:52:49 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 14:52:49 +0100
Subject: [PATCH v3a] KVM: arm/arm64: pmu: abstract access to number of SPIs
In-Reply-To: <20160510145832.cv3ozila3kisije6@hawk.localdomain>
References: <5731AF57.2040707@linaro.org>
 <1462890906-6134-1-git-send-email-andre.przywara@arm.com>
 <20160510145832.cv3ozila3kisije6@hawk.localdomain>
Message-ID: <57333931.6050206@arm.com>

Hi Drew,

On 10/05/16 15:58, Andrew Jones wrote:
> On Tue, May 10, 2016 at 03:35:06PM +0100, Andre Przywara wrote:
>> Currently the PMU uses a member of the struct vgic_dist directly,
>> which not only breaks abstraction, but will fail with the new VGIC.
>> Abstract this access in the VGIC header file.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Hi Eric, Marc,
>>
>> as this if-statement was quite confusing (it wasn't even the negation
>> that was wrong), I rewrote it a bit to be more readable.
>> This one works now with PPIs (after fixing kvmtool).
>>
>> Does that make sense?
>>
>> Cheers,
>> Andre.
>>
>>  include/kvm/arm_vgic.h |  2 ++
>>  virt/kvm/arm/pmu.c     | 19 +++++++++++--------
>>  2 files changed, 13 insertions(+), 8 deletions(-)
>>
>> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
>> index 6a98e05..d406f8e 100644
>> --- a/include/kvm/arm_vgic.h
>> +++ b/include/kvm/arm_vgic.h
>> @@ -351,6 +351,8 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
>>  #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
>>  #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
>>  #define vgic_ready(k)		((k)->arch.vgic.ready)
>> +#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
>> +				 ((i) < (k)->arch.vgic.nr_irqs))
>>  
>>  int vgic_v2_probe(struct device_node *vgic_node,
>>  		  const struct vgic_ops **ops,
>> diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
>> index 575c7aa..6ab9d6b 100644
>> --- a/virt/kvm/arm/pmu.c
>> +++ b/virt/kvm/arm/pmu.c
>> @@ -436,6 +436,11 @@ static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
>>  	return 0;
>>  }
>>  
>> +/*
>> + * For one VM the interrupt type must be same for each vcpu.
>> + * As a PPI, the interrupt number is the same for all vcpus,
>> + * while as an SPI it must be a separate number per vcpu.
>> + */
>>  static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
> 
> While at it, I'd change this function name to have 'pmu' in it. It's
> just a static function, but without pmu in it it looks a bit confusing
> now to check the irq is [a valid] spi or ppi number, and then to call
> the generically named 'irq_is_valid' on it as well.

Yes, indeed. Did that in the new series.

Thanks!
Andre.


From andre.przywara at arm.com  Wed May 11 06:39:08 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 14:39:08 +0100
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <5733300C.9070304@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
 <20160511123423.GO27623@cbox> <5733300C.9070304@arm.com>
Message-ID: <573335FC.8000103@arm.com>

Hi,

On 11/05/16 14:13, Marc Zyngier wrote:
> On 11/05/16 13:34, Christoffer Dall wrote:
>> On Fri, May 06, 2016 at 11:45:37AM +0100, Andre Przywara wrote:
>>> As the enable register handlers are shared between the v2 and v3
>>> emulation, their implementation goes into vgic-mmio.c, to be easily
>>> referenced from the v3 emulation as well later.
>>>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>> Changelog RFC..v1:
>>> - use lower bits of address to determine IRQ number
>>> - remove TODO, confirmed to be fine
>>>
>>> Changelog v1 .. v2:
>>> - adapt to new MMIO framework
>>>
>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
>>>  virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
>>>  virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
>>>  3 files changed, 69 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> index 69e96f7..448d1da 100644
>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> @@ -72,9 +72,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
>>>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
>>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
>>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
>>>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
>>> index 41cf4f4..077ae86 100644
>>> --- a/virt/kvm/arm/vgic/vgic-mmio.c
>>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>>> @@ -46,6 +46,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
>>>  	/* Ignore */
>>>  }
>>>  
>>> +/*
>>> + * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
>>> + * of the enabled bit, so there is only one function for both here.
>>> + */
>>> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
>>> +				    gpa_t addr, unsigned int len)
>>> +{
>>> +	u32 intid = (addr & 0x7f) * 8;
>>
>> is there anything we can do about this to make it more intuitive?  A
>> macro to generate the mask/offset based on bits per interrupt or
>> something?
> 
> Untested (and thus probably wrong):
> 
> #define VGIC_ADDR_IRQ_MASK(bits) ((1024 - 1) >> (4 - (bits))

What about if bits is 8?
Wouldn't GENMASK(bits + 10 - 2, 0) do the trick?

> #define VGIC_ADDR_IRQ_MULT(bits) (8 / (bits))

IROUTER has a bits_per_irq value of 64. We just don't need to call it
from there, but it would be nice if it could cover this.
But I don't know a neat solution for this either.

Cheers,
Andre.

> #define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
> 					 VGIC_ADDR_IRQ_MULT(bits))
> 
> 	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
> 
> Thanks,
> 
> 	M.
> 


From shannon.zhao at linaro.org  Wed May 11 06:35:47 2016
From: shannon.zhao at linaro.org (Shannon Zhao)
Date: Wed, 11 May 2016 21:35:47 +0800
Subject: [PATCH] Xen: EFI: Parse DT parameters for Xen specific UEFI
In-Reply-To: <20160511122730.GU2839@codeblueprint.co.uk>
References: <1462523526-3172-1-git-send-email-zhaoshenglong@huawei.com>
 <20160511122730.GU2839@codeblueprint.co.uk>
Message-ID: <57333533.2030206@linaro.org>

On 2016?05?11? 20:27, Matt Fleming wrote:
> On Fri, 06 May, at 04:32:06PM, Shannon Zhao wrote:
>> > From: Shannon Zhao <shannon.zhao at linaro.org>
>> > 
>> > Add a new function to parse DT parameters for Xen specific UEFI just
>> > like the way for normal UEFI. Then it could reuse the existing codes.
>> > 
>> > If Xen supports EFI, initialize runtime services.
>  
> This commit log would benefit from a little expansion. I'd like to see
> information that answers the following questions,
> 
>  - How do the Xen DT paramters differ from bare metal?
>  - What existing code is reused with your patch?
>  - How are Xen runtime services different from bare metal?
>  - Why is it OK to force enable EFI runtime services for Xen?
> 
> I think it would also be good to explicitly state that we do not
> expect to find both Xen EFI DT parameters and bare metal EFI DT
> parameters when performing the search; the two should be mutually
> exclusive.
> 
>> > CC: Matt Fleming <matt at codeblueprint.co.uk>
>> > Signed-off-by: Shannon Zhao <shannon.zhao at linaro.org>
>> > ---
>> > Drop using of EFI_PARAVIRT. Discussion can be found from [1].
>> > [1] https://lkml.org/lkml/2016/4/29/8
>> > ---
>> >  arch/arm/include/asm/efi.h         |  2 +
>> >  arch/arm/xen/enlighten.c           | 16 ++++++++
>> >  arch/arm64/include/asm/efi.h       |  2 +
>> >  drivers/firmware/efi/arm-runtime.c | 70 +++++++++++++++++++++++---------
>> >  drivers/firmware/efi/efi.c         | 81 ++++++++++++++++++++++++++++++--------
>> >  5 files changed, 137 insertions(+), 34 deletions(-)
>> > 
>> > diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
>> > index e0eea72..5ba4343 100644
>> > --- a/arch/arm/include/asm/efi.h
>> > +++ b/arch/arm/include/asm/efi.h
>> > @@ -52,9 +52,11 @@ static inline void efi_set_pgd(struct mm_struct *mm)
>> >  
>> >  void efi_virtmap_load(void);
>> >  void efi_virtmap_unload(void);
>> > +int xen_arm_enable_runtime_services(void);
>> >  
>> >  #else
>> >  #define efi_init()
>> > +#define xen_arm_enable_runtime_services() (0)
>> >  #endif /* CONFIG_EFI */
>> >  
>> >  /* arch specific definitions used by the stub code */
>> > diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
>> > index 13e3e9f..3362870 100644
>> > --- a/arch/arm/xen/enlighten.c
>> > +++ b/arch/arm/xen/enlighten.c
>> > @@ -16,6 +16,7 @@
>> >  #include <asm/xen/hypervisor.h>
>> >  #include <asm/xen/hypercall.h>
>> >  #include <asm/system_misc.h>
>> > +#include <asm/efi.h>
>> >  #include <linux/interrupt.h>
>> >  #include <linux/irqreturn.h>
>> >  #include <linux/module.h>
>> > @@ -261,6 +262,13 @@ static int __init fdt_find_hyper_node(unsigned long node, const char *uname,
>> >  	    !strncmp(hyper_node.prefix, s, strlen(hyper_node.prefix)))
>> >  		hyper_node.version = s + strlen(hyper_node.prefix);
>> >  
>> > +	if (IS_ENABLED(CONFIG_XEN_EFI)) {
>> > +		/* Check if Xen supports EFI */
>> > +		if ((of_get_flat_dt_subnode_by_name(node, "uefi") > 0) &&
>> > +		    !efi_runtime_disabled())
>> > +			set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
>> > +	}
>> > +
>> >  	return 0;
>> >  }
>> >  
> The above comment could do with including similar information to the
> commit log as to why we want to force enable runtime services. For x86
> we have this,
> 
> 	 *
> 	 * When EFI_PARAVIRT is in force then we could not map runtime
> 	 * service memory region because we do not have direct access to it.
> 	 * However, runtime services are available through proxy functions
> 	 * (e.g. in case of Xen dom0 EFI implementation they call special
> 	 * hypercall which executes relevant EFI functions) and that is why
> 	 * they are always enabled.
> 	 */
> 
> We need something similar here.
> 
>> > @@ -338,6 +346,7 @@ static int __init xen_guest_init(void)
>> >  {
>> >  	struct xen_add_to_physmap xatp;
>> >  	struct shared_info *shared_info_page = NULL;
>> > +	int ret;
>> >  
>> >  	if (!xen_domain())
>> >  		return 0;
>> > @@ -352,6 +361,13 @@ static int __init xen_guest_init(void)
>> >  		return -ENODEV;
>> >  	}
>> >  
>> > +	if (IS_ENABLED(CONFIG_XEN_EFI) && efi_enabled(EFI_BOOT) &&
>> > +	    efi_enabled(EFI_RUNTIME_SERVICES)) {
>> > +		ret = xen_arm_enable_runtime_services();
>> > +		if (ret)
>> > +			return ret;
>> > +	}
>> > +
> Is it ever possible to have EFI_RUNTIME_SERVICES set but
> efi_enabled(EFI_BOOT) and IS_ENABLED(CONFIG_XEN_EFI) be false inside
> this function? If the answer is "no", I'd suggest just reducing this
> down to,
> 
> 	/*
> 	 * The fdt parsing code will have set EFI_RUNTIME_SERVICES if
> 	 * it found Xen EFI parameters. Force enable runtime services.
> 	 */ 
> 	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
> 		ret = xen_arm_enable_runtime_services();
> 		if (ret)
> 			return ret;
> 	}
> 
> But first, see my comments below.
> 
>> > @@ -39,6 +40,33 @@ static struct mm_struct efi_mm = {
>> >  	.mmlist			= LIST_HEAD_INIT(efi_mm.mmlist),
>> >  };
>> >  
>> > +static int __init efi_remap_init(void)
>> > +{
>> > +	u64 mapsize;
>> > +
>> > +	pr_info("Remapping and enabling EFI services.\n");
>> > +
>> > +	mapsize = memmap.map_end - memmap.map;
>> > +	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
>> > +						   mapsize);
>> > +	if (!memmap.map) {
>> > +		pr_err("Failed to remap EFI memory map\n");
>> > +		return -ENOMEM;
>> > +	}
>> > +	memmap.map_end = memmap.map + mapsize;
>> > +	efi.memmap = &memmap;
>> > +
>> > +	efi.systab = (__force void *)ioremap_cache(efi_system_table,
>> > +						   sizeof(efi_system_table_t));
>> > +	if (!efi.systab) {
>> > +		pr_err("Failed to remap EFI System Table\n");
>> > +		return -ENOMEM;
>> > +	}
>> > +	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
>> > +
>> > +	return 0;
>> > +}
>> > +
>> >  static bool __init efi_virtmap_init(void)
>> >  {
>> >  	efi_memory_desc_t *md;
>> > @@ -75,7 +103,7 @@ static bool __init efi_virtmap_init(void)
>> >   */
>> >  static int __init arm_enable_runtime_services(void)
>> >  {
>> > -	u64 mapsize;
>> > +	int ret;
>> >  
>> >  	if (!efi_enabled(EFI_BOOT)) {
>> >  		pr_info("EFI services will not be available.\n");
>> > @@ -87,25 +115,14 @@ static int __init arm_enable_runtime_services(void)
>> >  		return 0;
>> >  	}
>> >  
>> > -	pr_info("Remapping and enabling EFI services.\n");
>> > -
>> > -	mapsize = memmap.map_end - memmap.map;
>> > -	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
>> > -						   mapsize);
>> > -	if (!memmap.map) {
>> > -		pr_err("Failed to remap EFI memory map\n");
>> > -		return -ENOMEM;
>> > +	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
>> > +		pr_info("EFI runtime services access via paravirt.\n");
>> > +		return 0;
>> >  	}
>> > -	memmap.map_end = memmap.map + mapsize;
>> > -	efi.memmap = &memmap;
>> >  
>> > -	efi.systab = (__force void *)ioremap_cache(efi_system_table,
>> > -						   sizeof(efi_system_table_t));
>> > -	if (!efi.systab) {
>> > -		pr_err("Failed to remap EFI System Table\n");
>> > -		return -ENOMEM;
>> > -	}
>> > -	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
>> > +	ret = efi_remap_init();
>> > +	if (ret)
>> > +		return ret;
>> >  
>> >  	if (!efi_virtmap_init()) {
>> >  		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
>> > @@ -122,6 +139,23 @@ static int __init arm_enable_runtime_services(void)
>> >  }
>> >  early_initcall(arm_enable_runtime_services);
>> >  
>> > +int __init xen_arm_enable_runtime_services(void)
>> > +{
>> > +	int ret;
>> > +
>> > +	ret = efi_remap_init();
>> > +	if (ret)
>> > +		return ret;
>> > +
>> > +	if (IS_ENABLED(CONFIG_XEN_EFI)) {
>> > +		/* Set up runtime services function pointers for Xen Dom0 */
>> > +		xen_efi_runtime_setup();
>> > +		efi.runtime_version = efi.systab->hdr.revision;
>> > +	}
>> > +
>> > +	return 0;
>> > +}
> Since you call efi_remap_init() in both of these functions, couldn't
> you leave the existing code alone and bail after setting up the memory
> map and systab in arm_enable_runtime_services()?
> 
> Also, why do you need to setup efi.runtime_version here? Isn't that
> done inside uefi_init()?
> 
I don't see any codes which setup efi.runtime_version in uefi_init().

> Here is how I would have expected this patch to look:
> 
>   - Add FDT code to find hypervisor EFI params
> 
>   - Force enable EFI_RUNTIME_SERVICES for Xen and call
>     xen_efi_runtime_setup() inside xen_guest_init()
> 
>   - Change arm_enable_runtime_services() to handle the case where
>     EFI_RUNTIME_SERVICES is already set
> 
> Am I misunderstanding some ordering issues?

Since xen_guest_init() and arm_enable_runtime_services() are both
early_initcall and the calling order is random I think. And when we call
xen_efi_runtime_setup() and setup efi.runtime_version in
xen_guest_init(), the efi.systab might be NULL. So it needs to map the
systanle explicitly before we use efi.systab.

Thanks,
-- 
Shannon


From niklas.soderlund at ragnatech.se  Wed May 11 07:03:08 2016
From: niklas.soderlund at ragnatech.se (Niklas =?iso-8859-1?Q?S=F6derlund?=)
Date: Wed, 11 May 2016 16:03:08 +0200
Subject: [PATCHv3 1/4] ARM: dts: r8a7790: Reference both DMA controllers
In-Reply-To: <CAMuHMdWoPThi0w6siA5LJ60oEH6JMv4x80b_Spg5aF-uHq3WqQ@mail.gmail.com>
References: <1462972438-20797-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <1462972438-20797-2-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <CAMuHMdWoPThi0w6siA5LJ60oEH6JMv4x80b_Spg5aF-uHq3WqQ@mail.gmail.com>
Message-ID: <20160511140308.GD3256@bigcity.dyn.berto.se>

On 2016-05-11 15:45:17 +0200, Geert Uytterhoeven wrote:
> Hi Niklas,
> 
> On Wed, May 11, 2016 at 3:13 PM, Niklas S?derlund
> <niklas.soderlund+renesas at ragnatech.se> wrote:
> > R-Car Gen2 have two DMA controllers, which are equivalent. Add
> > references to both dmac0 and dmac1 so the driver can choose which one to
> > use.
> >
> > Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
> > ---
> >  arch/arm/boot/dts/r8a7790.dtsi | 131 ++++++++++++++++++++++++-----------------
> >  1 file changed, 78 insertions(+), 53 deletions(-)
> >
> > diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
> > index 83cf23c..14fcd19 100644
> > --- a/arch/arm/boot/dts/r8a7790.dtsi
> > +++ b/arch/arm/boot/dts/r8a7790.dtsi
> 
> > @@ -755,9 +773,9 @@
> >                 clocks = <&mstp3_clks R8A7790_CLK_SCIF2>, <&zs_clk>,
> >                          <&scif_clk>;
> >                 clock-names = "fck", "brg_int", "scif_clk";
> > -               dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
> > -               dma-names = "tx", "rx";
> > -               power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
> 
> Please keep the above line.

My mistake, the above line was not meant to be removed.. thanks for 
pointing it out.

> 
> > +               dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
> > +                      <&dmac1 0x2b>, <&dmac1 0x2c>;
> > +               dma-names = "tx", "rx", "tx", "rx";
> >                 status = "disabled";
> >         };
> 
> 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

-- 
Regards,
Niklas S?derlund


From javier at osg.samsung.com  Wed May 11 07:11:50 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 11 May 2016 10:11:50 -0400
Subject: [PATCH 1/2] ARM: EXYNOS: Move pm_domains driver to
 drivers/soc/samsung
In-Reply-To: <1462888341-21963-1-git-send-email-k.kozlowski@samsung.com>
References: <1462888341-21963-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <61ec0a28-1b40-d66e-d349-f40463bd1637@osg.samsung.com>

Hello Krzysztof,

On 05/10/2016 09:52 AM, Krzysztof Kozlowski wrote:
> Exynos PM domains driver does not have mach-specific dependencies so it
> can be safely moved out of arm/mach-exynos to drivers/soc. This in
> future will allow re-using it on ARM64 boards.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Wed May 11 07:13:09 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 11 May 2016 10:13:09 -0400
Subject: [PATCH 2/2] soc: samsung: pm_domains: Prepare for supporting
 ARMv8 Exynos
In-Reply-To: <1462888341-21963-2-git-send-email-k.kozlowski@samsung.com>
References: <1462888341-21963-1-git-send-email-k.kozlowski@samsung.com>
 <1462888341-21963-2-git-send-email-k.kozlowski@samsung.com>
Message-ID: <7a62ff75-187e-06ef-8331-c056a7eee4e7@osg.samsung.com>

Hello Krzysztof,

On 05/10/2016 09:52 AM, Krzysztof Kozlowski wrote:
> The ARMv8 Exynos family (Exynos5433 and Exynos7420) uses different value
> (0xf instead of 0x7) for controlling the power domain on/off registers
> (both for control and for status).
> 
> Choose the value depending on the compatible. This prepares the driver
> for supporting ARMv8 SoCs.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From robh at kernel.org  Wed May 11 07:14:29 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 11 May 2016 09:14:29 -0500
Subject: [PATCH 4/7] [media] ir-rx51: add DT support to driver
In-Reply-To: <20160510021826.GE1129@earth>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <1462634508-24961-5-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <20160509200657.GA3379@rob-hp-laptop> <5730F8BA.5000402@gmail.com>
 <CAL_JsqJPZS1ne_xAuBFtCc5L1HKFJf0LDUJ7CRSFXhc3adkTfA@mail.gmail.com>
 <20160510021826.GE1129@earth>
Message-ID: <20160511141429.GA5894@rob-hp-laptop>

On Tue, May 10, 2016 at 04:18:27AM +0200, Sebastian Reichel wrote:
> Hi,
> 
> On Mon, May 09, 2016 at 04:07:35PM -0500, Rob Herring wrote:
> > There's already a pwm-led binding that can be used. Though there
> > may be missing consumer IR to LED subsystem support in the kernel.
> > You could list both compatibles, use the rx51 IR driver now, and
> > then move to pwm-led driver in the future.
> 
> Well from a purely HW point of view it's a PWM connected led. The
> usage is completely different though. Usually PWM is used to control
> the LED's brightness via the duty cycle (basic concept: enabling led
> only 50% of time reduces brightness to 50%).
> 
> In the IR led's case the aim is generating a specific serial pattern
> instead. For this task it uses a dmtimer in PWM mode and a second
> one to reconfigure the pwm timer.

In that case, it will probably never be a generic driver.

> I don't know about a good name, but rx51 should be replaced with
> n900 in the compatible string. So maybe "nokia,n900-infrared-diode".

That's fine, but the shorter '-ir' was too.

Rob


From andre.przywara at arm.com  Wed May 11 07:18:00 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 15:18:00 +0100
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <5733300C.9070304@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
 <20160511123423.GO27623@cbox> <5733300C.9070304@arm.com>
Message-ID: <57333F18.5030605@arm.com>

Hi,

On 11/05/16 14:13, Marc Zyngier wrote:
> On 11/05/16 13:34, Christoffer Dall wrote:
>> On Fri, May 06, 2016 at 11:45:37AM +0100, Andre Przywara wrote:
>>> As the enable register handlers are shared between the v2 and v3
>>> emulation, their implementation goes into vgic-mmio.c, to be easily
>>> referenced from the v3 emulation as well later.
>>>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>> Changelog RFC..v1:
>>> - use lower bits of address to determine IRQ number
>>> - remove TODO, confirmed to be fine
>>>
>>> Changelog v1 .. v2:
>>> - adapt to new MMIO framework
>>>
>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
>>>  virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
>>>  virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
>>>  3 files changed, 69 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> index 69e96f7..448d1da 100644
>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> @@ -72,9 +72,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
>>>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
>>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
>>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
>>>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
>>> index 41cf4f4..077ae86 100644
>>> --- a/virt/kvm/arm/vgic/vgic-mmio.c
>>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>>> @@ -46,6 +46,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
>>>  	/* Ignore */
>>>  }
>>>  
>>> +/*
>>> + * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
>>> + * of the enabled bit, so there is only one function for both here.
>>> + */
>>> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
>>> +				    gpa_t addr, unsigned int len)
>>> +{
>>> +	u32 intid = (addr & 0x7f) * 8;
>>
>> is there anything we can do about this to make it more intuitive?  A
>> macro to generate the mask/offset based on bits per interrupt or
>> something?
> 
> Untested (and thus probably wrong):
> 
> #define VGIC_ADDR_IRQ_MASK(bits) ((1024 - 1) >> (4 - (bits))
> #define VGIC_ADDR_IRQ_MULT(bits) (8 / (bits))
> #define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
> 					 VGIC_ADDR_IRQ_MULT(bits))
> 

Would:

#define VGIC_ADDR_IRQ_MASK(bits) GENMASK_ULL((bits) + 10 - 1 - 1, 0)
#define VGIC_ADDR_TO_INTID(addr, bits) (((addr) &		\
			VGIC_ADDR_IRQ_MASK(bits)) * 64 / (bits) / 8)

work for all bitnesses?

Cheers,
Andre.


From andy.gross at linaro.org  Wed May 11 07:15:50 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed, 11 May 2016 09:15:50 -0500
Subject: [Patch v4 0/8] Qualcomm SCM Rework
Message-ID: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>

The following set of patches does a bit of rework on the existing
Qualcomm SCM firmware.  The first couple of patches deals with turning
the current SCM into a platform driver.  The next couple are cleanups
that make adding the 64 support a little easier.  I added in a patch to
convert the scm-32 to use DMA streaming APIs.

I took Kumar's 64 bit support patch and modified it to use the arm_smccc
calls.  This simplified things quite a bit.

Lastly, there are a few DT patches to add the firmware node for a couple of the
supported platforms.

Changes from v3:
  * Added compatibles for the specific platforms requiring one clock.
  * All other platforms will use the generic binding that requires 3 clocks.

Changes from v2:
  * Added use of streaming DMA APIs for scm-32.
  * Changed DT binding to simplify compats.
  * Removed Kconfig.platform change that selected QCOM_SCM for ARM64
  * Fixed misc comments
  * Changed init function to populate the device differently.
  * Fixed missing of_node_put

Changes from v1:
  * Changed binding to reflect proper firmware node usage
  * Added arch_initcall to populate the firmware device, if present
  * Fixed various review comments
  * Removed extraneous includes from SCM 64 file.

Andy Gross (7):
  dt/bindings: firmware: Add Qualcomm SCM binding
  firmware: qcom: scm: Convert SCM to platform driver
  firmware: qcom: scm: Use atomic SCM for cold boot
  firmware: qcom: scm: Generalize shared error map
  firmware: qcom: scm: Convert to streaming DMA APIS
  dts: qcom: apq8084: Add SCM firmware node
  arm64: dts: msm8916: Add SCM firmware node

Kumar Gala (1):
  firmware: qcom: scm: Add support for ARM64 SoCs

 .../devicetree/bindings/firmware/qcom,scm.txt      |  28 +++
 arch/arm/boot/dts/qcom-apq8084.dtsi                |   8 +
 arch/arm64/boot/dts/qcom/msm8916.dtsi              |   8 +
 drivers/firmware/qcom_scm-32.c                     | 234 +++++++++------------
 drivers/firmware/qcom_scm-64.c                     | 208 +++++++++++++++++-
 drivers/firmware/qcom_scm.c                        | 171 ++++++++++++++-
 drivers/firmware/qcom_scm.h                        |  31 ++-
 7 files changed, 526 insertions(+), 162 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/firmware/qcom,scm.txt

-- 
1.9.1



From andy.gross at linaro.org  Wed May 11 07:15:51 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed, 11 May 2016 09:15:51 -0500
Subject: [Patch v4 1/8] dt/bindings: firmware: Add Qualcomm SCM binding
In-Reply-To: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462976158-26016-2-git-send-email-andy.gross@linaro.org>

This patch adds the device tree support for the Qualcomm SCM firmware.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 .../devicetree/bindings/firmware/qcom,scm.txt      | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/qcom,scm.txt

diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
new file mode 100644
index 0000000..0c5f1ff
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
@@ -0,0 +1,28 @@
+QCOM Secure Channel Manager (SCM)
+
+Qualcomm processors include an interface to communicate to the secure firmware.
+This interface allows for clients to request different types of actions.  These
+can include CPU power up/down, HDCP requests, loading of firmware, and other
+assorted actions.
+
+Required properties:
+- compatible: must contain one of the following:
+ * "qcom,scm-apq8064" for APQ8064 platforms
+ * "qcom,scm-msm8660" for MSM8660 platforms
+ * "qcom,scm-msm8690" for MSM8690 platforms
+ * "qcom,scm" for later processors (MSM8916, APQ8084, MSM8974, etc)
+- clocks: One to three clocks may be required based on compatible.
+ * Only core clock required for "qcom,scm-apq8084", "qcom,scm-msm8660", and "qcom,scm-msm8960"
+ * Core, iface, and bus clocks required for "qcom,scm"
+- clock-names: Must contain "core" for the core clock, "iface" for the interface
+  clock and "bus" for the bus clock per the requirements of the compatible.
+
+Example for MSM8916:
+
+	firmware {
+		scm {
+			compatible = "qcom,scm";
+			clocks = <&gcc GCC_CRYPTO_CLK> , <&gcc GCC_CRYPTO_AXI_CLK>, <&gcc GCC_CRYPTO_AHB_CLK>;
+			clock-names = "core", "bus", "iface";
+		};
+	};
-- 
1.9.1



From andy.gross at linaro.org  Wed May 11 07:15:53 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed, 11 May 2016 09:15:53 -0500
Subject: [Patch v4 3/8] firmware: qcom: scm: Use atomic SCM for cold boot
In-Reply-To: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462976158-26016-4-git-send-email-andy.gross@linaro.org>

This patch changes the cold_set_boot_addr function to use atomic SCM
calls.  cold_set_boot_addr required adding qcom_scm_call_atomic2 to
support the two arguments going to the smc call.  Using atomic removes
the need for memory allocation and instead places all arguments in
registers.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm-32.c | 63 ++++++++++++++++++++++++++++++------------
 1 file changed, 45 insertions(+), 18 deletions(-)

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 0883292..5be6a12 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -342,6 +342,41 @@ static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
 	return r0;
 }
 
+/**
+ * qcom_scm_call_atomic2() - Send an atomic SCM command with two arguments
+ * @svc_id:	service identifier
+ * @cmd_id:	command identifier
+ * @arg1:	first argument
+ * @arg2:	second argument
+ *
+ * This shall only be used with commands that are guaranteed to be
+ * uninterruptable, atomic and SMP safe.
+ */
+static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2)
+{
+	int context_id;
+
+	register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 2);
+	register u32 r1 asm("r1") = (u32)&context_id;
+	register u32 r2 asm("r2") = arg1;
+	register u32 r3 asm("r3") = arg2;
+
+	asm volatile(
+			__asmeq("%0", "r0")
+			__asmeq("%1", "r0")
+			__asmeq("%2", "r1")
+			__asmeq("%3", "r2")
+			__asmeq("%4", "r3")
+#ifdef REQUIRES_SEC
+			".arch_extension sec\n"
+#endif
+			"smc    #0      @ switch to secure world\n"
+			: "=r" (r0)
+			: "r" (r0), "r" (r1), "r" (r2), "r" (r3)
+			);
+	return r0;
+}
+
 u32 qcom_scm_get_version(void)
 {
 	int context_id;
@@ -378,22 +413,6 @@ u32 qcom_scm_get_version(void)
 }
 EXPORT_SYMBOL(qcom_scm_get_version);
 
-/*
- * Set the cold/warm boot address for one of the CPU cores.
- */
-static int qcom_scm_set_boot_addr(u32 addr, int flags)
-{
-	struct {
-		__le32 flags;
-		__le32 addr;
-	} cmd;
-
-	cmd.addr = cpu_to_le32(addr);
-	cmd.flags = cpu_to_le32(flags);
-	return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
-			&cmd, sizeof(cmd), NULL, 0);
-}
-
 /**
  * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
  * @entry: Entry point function for the cpus
@@ -423,7 +442,8 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
 			set_cpu_present(cpu, false);
 	}
 
-	return qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
+	return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
+				    flags, virt_to_phys(entry));
 }
 
 /**
@@ -439,6 +459,10 @@ int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
 	int ret;
 	int flags = 0;
 	int cpu;
+	struct {
+		__le32 flags;
+		__le32 addr;
+	} cmd;
 
 	/*
 	 * Reassign only if we are switching from hotplug entry point
@@ -454,7 +478,10 @@ int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
 	if (!flags)
 		return 0;
 
-	ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
+	cmd.addr = cpu_to_le32(virt_to_phys(entry));
+	cmd.flags = cpu_to_le32(flags);
+	ret = qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
+			    &cmd, sizeof(cmd), NULL, 0);
 	if (!ret) {
 		for_each_cpu(cpu, cpus)
 			qcom_scm_wb[cpu].entry = entry;
-- 
1.9.1



From andy.gross at linaro.org  Wed May 11 07:15:54 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed, 11 May 2016 09:15:54 -0500
Subject: [Patch v4 4/8] firmware: qcom: scm: Generalize shared error map
In-Reply-To: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462976158-26016-5-git-send-email-andy.gross@linaro.org>

This patch moves the qcom_scm_remap_error function to the include file
where can be used by both the 32 and 64 bit versions of the code.

Reviewed-by: Stephen Boyd <sboyd at codeaurora.org>
Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>
Signed-off-by: Andy Gross <agross at codeaurora.org>
Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm-32.c | 17 -----------------
 drivers/firmware/qcom_scm.h    | 16 ++++++++++++++++
 2 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 5be6a12..4388d13 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -168,23 +168,6 @@ static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response
 	return (void *)rsp + le32_to_cpu(rsp->buf_offset);
 }
 
-static int qcom_scm_remap_error(int err)
-{
-	pr_err("qcom_scm_call failed with error code %d\n", err);
-	switch (err) {
-	case QCOM_SCM_ERROR:
-		return -EIO;
-	case QCOM_SCM_EINVAL_ADDR:
-	case QCOM_SCM_EINVAL_ARG:
-		return -EINVAL;
-	case QCOM_SCM_EOPNOTSUPP:
-		return -EOPNOTSUPP;
-	case QCOM_SCM_ENOMEM:
-		return -ENOMEM;
-	}
-	return -EINVAL;
-}
-
 static u32 smc(u32 cmd_addr)
 {
 	int context_id;
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index 2cce75c..7dcc733 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -44,4 +44,20 @@ extern int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
 #define QCOM_SCM_ERROR		-1
 #define QCOM_SCM_INTERRUPTED	1
 
+static inline int qcom_scm_remap_error(int err)
+{
+	switch (err) {
+	case QCOM_SCM_ERROR:
+		return -EIO;
+	case QCOM_SCM_EINVAL_ADDR:
+	case QCOM_SCM_EINVAL_ARG:
+		return -EINVAL;
+	case QCOM_SCM_EOPNOTSUPP:
+		return -EOPNOTSUPP;
+	case QCOM_SCM_ENOMEM:
+		return -ENOMEM;
+	}
+	return -EINVAL;
+}
+
 #endif
-- 
1.9.1



From andy.gross at linaro.org  Wed May 11 07:15:57 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed, 11 May 2016 09:15:57 -0500
Subject: [Patch v4 7/8] dts: qcom: apq8084: Add SCM firmware node
In-Reply-To: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462976158-26016-8-git-send-email-andy.gross@linaro.org>

This patch adds the firmware node for the SCM

Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>
Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 arch/arm/boot/dts/qcom-apq8084.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-apq8084.dtsi b/arch/arm/boot/dts/qcom-apq8084.dtsi
index a33a09f..7c2df06 100644
--- a/arch/arm/boot/dts/qcom-apq8084.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8084.dtsi
@@ -86,6 +86,14 @@
 		};
 	};
 
+	firmware {
+		scm {
+			compatible = "qcom,scm";
+			clocks = <&gcc GCC_CE1_CLK> , <&gcc GCC_CE1_AXI_CLK>, <&gcc GCC_CE1_AHB_CLK>;
+			clock-names = "core", "bus", "iface";
+		};
+	};
+
 	cpu-pmu {
 		compatible = "qcom,krait-pmu";
 		interrupts = <1 7 0xf04>;
-- 
1.9.1



From andy.gross at linaro.org  Wed May 11 07:15:55 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed, 11 May 2016 09:15:55 -0500
Subject: [Patch v4 5/8] firmware: qcom: scm: Convert to streaming DMA APIS
In-Reply-To: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462976158-26016-6-git-send-email-andy.gross@linaro.org>

This patch converts the Qualcomm SCM driver to use the streaming DMA APIs
for communication buffers.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm-32.c | 152 +++++++++++++----------------------------
 drivers/firmware/qcom_scm.c    |   6 +-
 drivers/firmware/qcom_scm.h    |  10 +--
 3 files changed, 58 insertions(+), 110 deletions(-)

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 4388d13..3e71aec 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -23,8 +23,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/qcom_scm.h>
-
-#include <asm/cacheflush.h>
+#include <linux/dma-mapping.h>
 
 #include "qcom_scm.h"
 
@@ -97,44 +96,6 @@ struct qcom_scm_response {
 };
 
 /**
- * alloc_qcom_scm_command() - Allocate an SCM command
- * @cmd_size: size of the command buffer
- * @resp_size: size of the response buffer
- *
- * Allocate an SCM command, including enough room for the command
- * and response headers as well as the command and response buffers.
- *
- * Returns a valid &qcom_scm_command on success or %NULL if the allocation fails.
- */
-static struct qcom_scm_command *alloc_qcom_scm_command(size_t cmd_size, size_t resp_size)
-{
-	struct qcom_scm_command *cmd;
-	size_t len = sizeof(*cmd) + sizeof(struct qcom_scm_response) + cmd_size +
-		resp_size;
-	u32 offset;
-
-	cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
-	if (cmd) {
-		cmd->len = cpu_to_le32(len);
-		offset = offsetof(struct qcom_scm_command, buf);
-		cmd->buf_offset = cpu_to_le32(offset);
-		cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
-	}
-	return cmd;
-}
-
-/**
- * free_qcom_scm_command() - Free an SCM command
- * @cmd: command to free
- *
- * Free an SCM command.
- */
-static inline void free_qcom_scm_command(struct qcom_scm_command *cmd)
-{
-	kfree(cmd);
-}
-
-/**
  * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response
  * @cmd: command
  *
@@ -168,7 +129,7 @@ static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response
 	return (void *)rsp + le32_to_cpu(rsp->buf_offset);
 }
 
-static u32 smc(u32 cmd_addr)
+static u32 smc(dma_addr_t cmd_addr)
 {
 	int context_id;
 	register u32 r0 asm("r0") = 1;
@@ -192,51 +153,15 @@ static u32 smc(u32 cmd_addr)
 	return r0;
 }
 
-static int __qcom_scm_call(const struct qcom_scm_command *cmd)
-{
-	int ret;
-	u32 cmd_addr = virt_to_phys(cmd);
-
-	/*
-	 * Flush the command buffer so that the secure world sees
-	 * the correct data.
-	 */
-	secure_flush_area(cmd, cmd->len);
-
-	ret = smc(cmd_addr);
-	if (ret < 0)
-		ret = qcom_scm_remap_error(ret);
-
-	return ret;
-}
-
-static void qcom_scm_inv_range(unsigned long start, unsigned long end)
-{
-	u32 cacheline_size, ctr;
-
-	asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
-	cacheline_size = 4 << ((ctr >> 16) & 0xf);
-
-	start = round_down(start, cacheline_size);
-	end = round_up(end, cacheline_size);
-	outer_inv_range(start, end);
-	while (start < end) {
-		asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
-		     : "memory");
-		start += cacheline_size;
-	}
-	dsb();
-	isb();
-}
-
 /**
  * qcom_scm_call() - Send an SCM command
- * @svc_id: service identifier
- * @cmd_id: command identifier
- * @cmd_buf: command buffer
- * @cmd_len: length of the command buffer
- * @resp_buf: response buffer
- * @resp_len: length of the response buffer
+ * @dev:	struct device
+ * @svc_id:	service identifier
+ * @cmd_id:	command identifier
+ * @cmd_buf:	command buffer
+ * @cmd_len:	length of the command buffer
+ * @resp_buf:	response buffer
+ * @resp_len:	length of the response buffer
  *
  * Sends a command to the SCM and waits for the command to finish processing.
  *
@@ -247,42 +172,60 @@ static void qcom_scm_inv_range(unsigned long start, unsigned long end)
  * and response buffers is taken care of by qcom_scm_call; however, callers are
  * responsible for any other cached buffers passed over to the secure world.
  */
-static int qcom_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf,
-			size_t cmd_len, void *resp_buf, size_t resp_len)
+static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
+			 const void *cmd_buf, size_t cmd_len, void *resp_buf,
+			 size_t resp_len)
 {
 	int ret;
 	struct qcom_scm_command *cmd;
 	struct qcom_scm_response *rsp;
-	unsigned long start, end;
+	size_t alloc_len = sizeof(*cmd) + sizeof(struct qcom_scm_response) +
+			   cmd_len + resp_len;
+	dma_addr_t cmd_phys;
+	u32 offset;
 
-	cmd = alloc_qcom_scm_command(cmd_len, resp_len);
+	cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
 	if (!cmd)
 		return -ENOMEM;
 
+	cmd->len = cpu_to_le32(alloc_len);
+	offset = offsetof(struct qcom_scm_command, buf);
+	cmd->buf_offset = cpu_to_le32(offset);
+	cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_len);
+
 	cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
 	if (cmd_buf)
 		memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len);
 
+	cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, cmd_phys)) {
+		kfree(cmd);
+		return -ENOMEM;
+	}
+
 	mutex_lock(&qcom_scm_lock);
-	ret = __qcom_scm_call(cmd);
+	ret = smc(cmd_phys);
+	if (ret < 0)
+		ret = qcom_scm_remap_error(ret);
 	mutex_unlock(&qcom_scm_lock);
 	if (ret)
 		goto out;
 
 	rsp = qcom_scm_command_to_response(cmd);
-	start = (unsigned long)rsp;
 
 	do {
-		qcom_scm_inv_range(start, start + sizeof(*rsp));
+		dma_sync_single_for_cpu(dev, cmd_phys + cmd_len + offset,
+					sizeof(*rsp), DMA_FROM_DEVICE);
 	} while (!rsp->is_complete);
 
-	end = (unsigned long)qcom_scm_get_response_buffer(rsp) + resp_len;
-	qcom_scm_inv_range(start, end);
-
-	if (resp_buf)
+	if (resp_buf) {
+		dma_sync_single_for_cpu(dev, cmd_phys + alloc_len - resp_len,
+					resp_len, DMA_FROM_DEVICE);
 		memcpy(resp_buf, qcom_scm_get_response_buffer(rsp), resp_len);
+	}
 out:
-	free_qcom_scm_command(cmd);
+	dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE);
+	kfree(cmd);
 	return ret;
 }
 
@@ -437,7 +380,8 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
  * Set the Linux entry point for the SCM to transfer control to when coming
  * out of a power down. CPU power down may be executed on cpuidle or hotplug.
  */
-int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
+int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
+				  const cpumask_t *cpus)
 {
 	int ret;
 	int flags = 0;
@@ -463,7 +407,7 @@ int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
 
 	cmd.addr = cpu_to_le32(virt_to_phys(entry));
 	cmd.flags = cpu_to_le32(flags);
-	ret = qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
+	ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
 			    &cmd, sizeof(cmd), NULL, 0);
 	if (!ret) {
 		for_each_cpu(cpu, cpus)
@@ -487,25 +431,27 @@ void __qcom_scm_cpu_power_down(u32 flags)
 			flags & QCOM_SCM_FLUSH_FLAG_MASK);
 }
 
-int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
+int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
 {
 	int ret;
 	__le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id);
 	__le32 ret_val = 0;
 
-	ret = qcom_scm_call(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, &svc_cmd,
-			sizeof(svc_cmd), &ret_val, sizeof(ret_val));
+	ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD,
+			    &svc_cmd, sizeof(svc_cmd), &ret_val,
+			    sizeof(ret_val));
 	if (ret)
 		return ret;
 
 	return le32_to_cpu(ret_val);
 }
 
-int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
+int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
+			u32 req_cnt, u32 *resp)
 {
 	if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
 		return -ERANGE;
 
-	return qcom_scm_call(QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
+	return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
 		req, req_cnt * sizeof(*req), resp, sizeof(*resp));
 }
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 4d6ae32..23ccec6 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -89,7 +89,7 @@ EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
  */
 int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
 {
-	return __qcom_scm_set_warm_boot_addr(entry, cpus);
+	return __qcom_scm_set_warm_boot_addr(__scm->dev, entry, cpus);
 }
 EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
 
@@ -119,7 +119,7 @@ bool qcom_scm_hdcp_available(void)
 	if (ret)
 		return ret;
 
-	ret = __qcom_scm_is_call_available(QCOM_SCM_SVC_HDCP,
+	ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP,
 						QCOM_SCM_CMD_HDCP);
 
 	qcom_scm_clk_disable();
@@ -143,7 +143,7 @@ int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
 	if (ret)
 		return ret;
 
-	ret = __qcom_scm_hdcp_req(req, req_cnt, resp);
+	ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp);
 	qcom_scm_clk_disable();
 	return ret;
 }
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index 7dcc733..afe6676 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -19,7 +19,8 @@
 #define QCOM_SCM_FLAG_HLOS		0x01
 #define QCOM_SCM_FLAG_COLDBOOT_MC	0x02
 #define QCOM_SCM_FLAG_WARMBOOT_MC	0x04
-extern int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus);
+extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
+		const cpumask_t *cpus);
 extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);
 
 #define QCOM_SCM_CMD_TERMINATE_PC	0x2
@@ -29,12 +30,13 @@ extern void __qcom_scm_cpu_power_down(u32 flags);
 
 #define QCOM_SCM_SVC_INFO		0x6
 #define QCOM_IS_CALL_AVAIL_CMD		0x1
-extern int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id);
+extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
+		u32 cmd_id);
 
 #define QCOM_SCM_SVC_HDCP		0x11
 #define QCOM_SCM_CMD_HDCP		0x01
-extern int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
-		u32 *resp);
+extern int __qcom_scm_hdcp_req(struct device *dev,
+		struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);
 
 /* common error codes */
 #define QCOM_SCM_ENOMEM		-5
-- 
1.9.1



From andy.gross at linaro.org  Wed May 11 07:15:52 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed, 11 May 2016 09:15:52 -0500
Subject: [Patch v4 2/8] firmware: qcom: scm: Convert SCM to platform driver
In-Reply-To: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462976158-26016-3-git-send-email-andy.gross@linaro.org>

This patch converts the Qualcomm SCM firmware driver into a platform
driver.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm.c | 165 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 156 insertions(+), 9 deletions(-)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 45c008d..4d6ae32 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -10,19 +10,61 @@
  * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
  */
-
+#include <linux/platform_device.h>
+#include <linux/module.h>
 #include <linux/cpumask.h>
 #include <linux/export.h>
 #include <linux/types.h>
 #include <linux/qcom_scm.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
 
 #include "qcom_scm.h"
 
+struct qcom_scm {
+	struct device *dev;
+	struct clk *core_clk;
+	struct clk *iface_clk;
+	struct clk *bus_clk;
+};
+
+static struct qcom_scm *__scm;
+
+static int qcom_scm_clk_enable(void)
+{
+	int ret;
+
+	ret = clk_prepare_enable(__scm->core_clk);
+	if (ret)
+		goto bail;
+
+	ret = clk_prepare_enable(__scm->iface_clk);
+	if (ret)
+		goto disable_core;
+
+	ret = clk_prepare_enable(__scm->bus_clk);
+	if (ret)
+		goto disable_iface;
+
+	return 0;
+
+disable_iface:
+	clk_disable_unprepare(__scm->iface_clk);
+disable_core:
+	clk_disable_unprepare(__scm->core_clk);
+bail:
+	return ret;
+}
+
+static void qcom_scm_clk_disable(void)
+{
+	clk_disable_unprepare(__scm->core_clk);
+	clk_disable_unprepare(__scm->iface_clk);
+	clk_disable_unprepare(__scm->bus_clk);
+}
+
 /**
  * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
  * @entry: Entry point function for the cpus
@@ -72,12 +114,17 @@ EXPORT_SYMBOL(qcom_scm_cpu_power_down);
  */
 bool qcom_scm_hdcp_available(void)
 {
-	int ret;
+	int ret = qcom_scm_clk_enable();
+
+	if (ret)
+		return ret;
 
 	ret = __qcom_scm_is_call_available(QCOM_SCM_SVC_HDCP,
-		QCOM_SCM_CMD_HDCP);
+						QCOM_SCM_CMD_HDCP);
+
+	qcom_scm_clk_disable();
 
-	return (ret > 0) ? true : false;
+	return ret > 0 ? true : false;
 }
 EXPORT_SYMBOL(qcom_scm_hdcp_available);
 
@@ -91,6 +138,106 @@ EXPORT_SYMBOL(qcom_scm_hdcp_available);
  */
 int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
 {
-	return __qcom_scm_hdcp_req(req, req_cnt, resp);
+	int ret = qcom_scm_clk_enable();
+
+	if (ret)
+		return ret;
+
+	ret = __qcom_scm_hdcp_req(req, req_cnt, resp);
+	qcom_scm_clk_disable();
+	return ret;
 }
 EXPORT_SYMBOL(qcom_scm_hdcp_req);
+
+static int qcom_scm_probe(struct platform_device *pdev)
+{
+	struct qcom_scm *scm;
+	int ret;
+
+	scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL);
+	if (!scm)
+		return -ENOMEM;
+
+	scm->core_clk = devm_clk_get(&pdev->dev, "core");
+	if (IS_ERR(scm->core_clk)) {
+		if (PTR_ERR(scm->core_clk) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "failed to acquire core clk\n");
+		return PTR_ERR(scm->core_clk);
+	}
+
+	if (of_device_is_compatible(pdev->dev.of_node, "qcom,scm")) {
+		scm->iface_clk = devm_clk_get(&pdev->dev, "iface");
+		if (IS_ERR(scm->iface_clk)) {
+			if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER)
+				dev_err(&pdev->dev, "failed to acquire iface clk\n");
+			return PTR_ERR(scm->iface_clk);
+		}
+
+		scm->bus_clk = devm_clk_get(&pdev->dev, "bus");
+		if (IS_ERR(scm->bus_clk)) {
+			if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER)
+				dev_err(&pdev->dev, "failed to acquire bus clk\n");
+			return PTR_ERR(scm->bus_clk);
+		}
+	}
+
+	/* vote for max clk rate for highest performance */
+	ret = clk_set_rate(scm->core_clk, INT_MAX);
+	if (ret)
+		return ret;
+
+	__scm = scm;
+	__scm->dev = &pdev->dev;
+
+	return 0;
+}
+
+static const struct of_device_id qcom_scm_dt_match[] = {
+	{ .compatible = "qcom,scm-apq8064",},
+	{ .compatible = "qcom,scm-msm8660",},
+	{ .compatible = "qcom,scm-msm8960",},
+	{ .compatible = "qcom,scm",},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, qcom_scm_dt_match);
+
+static struct platform_driver qcom_scm_driver = {
+	.driver = {
+		.name	= "qcom_scm",
+		.of_match_table = qcom_scm_dt_match,
+	},
+	.probe = qcom_scm_probe,
+};
+
+static int __init qcom_scm_init(void)
+{
+	struct device_node *np, *parent;
+	int ret;
+
+	np = of_find_matching_node_and_match(NULL, qcom_scm_dt_match, NULL);
+
+	if (!np)
+		return -ENODEV;
+
+	parent = of_get_next_parent(np);
+	ret = of_platform_populate(parent, qcom_scm_dt_match, NULL, NULL);
+
+	of_node_put(parent);
+
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&qcom_scm_driver);
+}
+
+arch_initcall(qcom_scm_init);
+
+static void __exit qcom_scm_exit(void)
+{
+	platform_driver_unregister(&qcom_scm_driver);
+}
+module_exit(qcom_scm_exit);
+
+MODULE_DESCRIPTION("Qualcomm SCM driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1



From andy.gross at linaro.org  Wed May 11 07:15:58 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed, 11 May 2016 09:15:58 -0500
Subject: [Patch v4 8/8] arm64: dts: msm8916: Add SCM firmware node
In-Reply-To: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462976158-26016-9-git-send-email-andy.gross@linaro.org>

This adds the devicetree node for the SCM firmware.

Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>
Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 arch/arm64/boot/dts/qcom/msm8916.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 9681200..01c7b0c 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -122,6 +122,14 @@
 		hwlocks = <&tcsr_mutex 3>;
 	};
 
+	firmware {
+		scm {
+			compatible = "qcom,scm";
+			clocks = <&gcc GCC_CRYPTO_CLK>, <&gcc GCC_CRYPTO_AXI_CLK>, <&gcc GCC_CRYPTO_AHB_CLK>;
+			clock-names = "core", "bus", "iface";
+		};
+	};
+
 	soc: soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
-- 
1.9.1



From andy.gross at linaro.org  Wed May 11 07:15:56 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed, 11 May 2016 09:15:56 -0500
Subject: [Patch v4 6/8] firmware: qcom: scm: Add support for ARM64 SoCs
In-Reply-To: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1462976158-26016-7-git-send-email-andy.gross@linaro.org>

From: Kumar Gala <galak at codeaurora.org>

Add an implementation of the SCM interface that works on ARM64 SoCs.  This
is used by things like determine if we have HDCP support or not on the
system.

Signed-off-by: Kumar Gala <galak at codeaurora.org>
Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm-32.c |   4 +
 drivers/firmware/qcom_scm-64.c | 208 +++++++++++++++++++++++++++++++++++++++--
 drivers/firmware/qcom_scm.c    |   2 +
 drivers/firmware/qcom_scm.h    |   5 +
 4 files changed, 209 insertions(+), 10 deletions(-)

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 3e71aec..5c290e7 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -455,3 +455,7 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
 	return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
 		req, req_cnt * sizeof(*req), resp, sizeof(*resp));
 }
+
+void __qcom_scm_init(void)
+{
+}
diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c
index bb6555f..b57468e 100644
--- a/drivers/firmware/qcom_scm-64.c
+++ b/drivers/firmware/qcom_scm-64.c
@@ -12,12 +12,148 @@
 
 #include <linux/io.h>
 #include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
 #include <linux/qcom_scm.h>
+#include <linux/arm-smccc.h>
+#include <linux/dma-mapping.h>
+
+#include "qcom_scm.h"
+
+#define QCOM_SCM_FNID(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF))
+
+#define MAX_QCOM_SCM_ARGS 10
+#define MAX_QCOM_SCM_RETS 3
+
+#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\
+			   (((a) & 0xff) << 4) | \
+			   (((b) & 0xff) << 6) | \
+			   (((c) & 0xff) << 8) | \
+			   (((d) & 0xff) << 10) | \
+			   (((e) & 0xff) << 12) | \
+			   (((f) & 0xff) << 14) | \
+			   (((g) & 0xff) << 16) | \
+			   (((h) & 0xff) << 18) | \
+			   (((i) & 0xff) << 20) | \
+			   (((j) & 0xff) << 22) | \
+			   (num & 0xffff))
+
+#define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+
+/**
+ * struct qcom_scm_desc
+ * @arginfo:	Metadata describing the arguments in args[]
+ * @args:	The array of arguments for the secure syscall
+ * @res:	The values returned by the secure syscall
+ */
+struct qcom_scm_desc {
+	u32 arginfo;
+	u64 args[MAX_QCOM_SCM_ARGS];
+	struct arm_smccc_res res;
+};
+
+static u64 qcom_smccc_convention = -1;
+static DEFINE_MUTEX(qcom_scm_lock);
+
+#define QCOM_SCM_EBUSY_WAIT_MS 30
+#define QCOM_SCM_EBUSY_MAX_RETRY 20
+
+#define N_EXT_QCOM_SCM_ARGS 7
+#define FIRST_EXT_ARG_IDX 3
+#define N_REGISTER_ARGS (MAX_QCOM_SCM_ARGS - N_EXT_QCOM_SCM_ARGS + 1)
+
+/**
+ * qcom_scm_call() - Invoke a syscall in the secure world
+ * @dev:	device
+ * @svc_id:	service identifier
+ * @cmd_id:	command identifier
+ * @fn_id:	The function ID for this syscall
+ * @desc:	Descriptor structure containing arguments and return values
+ *
+ * Sends a command to the SCM and waits for the command to finish processing.
+ * This should *only* be called in pre-emptible context.
+*/
+static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
+			 struct qcom_scm_desc *desc)
+{
+	int arglen = desc->arginfo & 0xf;
+	int ret, retry_count = 0, i;
+	u32 fn_id = QCOM_SCM_FNID(svc_id, cmd_id);
+	u64 cmd, x5 = desc->args[FIRST_EXT_ARG_IDX];
+	dma_addr_t args_phys = 0;
+	void *args_virt = NULL;
+	size_t alloc_len;
+
+	if (unlikely(arglen > N_REGISTER_ARGS)) {
+		alloc_len = N_EXT_QCOM_SCM_ARGS * sizeof(u64);
+		args_virt = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
+
+		if (!args_virt)
+			return qcom_scm_remap_error(-ENOMEM);
+
+		if (qcom_smccc_convention == ARM_SMCCC_SMC_32) {
+			__le32 *args = args_virt;
+
+			for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
+				args[i] = cpu_to_le32(desc->args[i +
+						      FIRST_EXT_ARG_IDX]);
+		} else {
+			__le64 *args = args_virt;
+
+			for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
+				args[i] = cpu_to_le64(desc->args[i +
+						      FIRST_EXT_ARG_IDX]);
+		}
+
+		args_phys = dma_map_single(dev, args_virt, alloc_len,
+					   DMA_TO_DEVICE);
+
+		if (dma_mapping_error(dev, args_phys)) {
+			kfree(args_virt);
+			return qcom_scm_remap_error(-ENOMEM);
+		}
+
+		x5 = args_phys;
+	}
+
+	do {
+		mutex_lock(&qcom_scm_lock);
+
+		cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL,
+					 qcom_smccc_convention,
+					 ARM_SMCCC_OWNER_SIP, fn_id);
+
+		do {
+			arm_smccc_smc(cmd, arglen, desc->args[0], desc->args[1],
+				      desc->args[2], x5, 0, 0, &desc->res);
+		} while (desc->res.a0 == QCOM_SCM_INTERRUPTED);
+
+		mutex_unlock(&qcom_scm_lock);
+
+		if (desc->res.a0 == QCOM_SCM_V2_EBUSY) {
+			if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY)
+				break;
+			msleep(QCOM_SCM_EBUSY_WAIT_MS);
+		}
+	}  while (desc->res.a0 == QCOM_SCM_V2_EBUSY);
+
+	if (args_virt) {
+		dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE);
+		kfree(args_virt);
+	}
+
+	if (desc->res.a0 < 0)
+		return qcom_scm_remap_error(ret);
+
+	return 0;
+}
 
 /**
  * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
- * @entry: Entry point function for the cpus
- * @cpus: The cpumask of cpus that will use the entry point
+ * @entry:	Entry point function for the cpus
+ * @cpus:	The cpumask of cpus that will use the entry point
  *
  * Set the cold boot address of the cpus. Any cpu outside the supported
  * range would be removed from the cpu present mask.
@@ -29,20 +165,21 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
 
 /**
  * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
- * @entry: Entry point function for the cpus
- * @cpus: The cpumask of cpus that will use the entry point
+ * @entry:	Entry point function for the cpus
+ * @cpus:	The cpumask of cpus that will use the entry point
  *
  * Set the Linux entry point for the SCM to transfer control to when coming
  * out of a power down. CPU power down may be executed on cpuidle or hotplug.
  */
-int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
+int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
+				  const cpumask_t *cpus)
 {
 	return -ENOTSUPP;
 }
 
 /**
  * qcom_scm_cpu_power_down() - Power down the cpu
- * @flags - Flags to flush cache
+ * @flags:	Flags to flush cache
  *
  * This is an end point to power down cpu. If there was a pending interrupt,
  * the control would return from this function, otherwise, the cpu jumps to the
@@ -52,12 +189,63 @@ void __qcom_scm_cpu_power_down(u32 flags)
 {
 }
 
-int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
+int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
 {
-	return -ENOTSUPP;
+	int ret;
+	struct qcom_scm_desc desc = {0};
+
+	desc.arginfo = QCOM_SCM_ARGS(1);
+	desc.args[0] = QCOM_SCM_FNID(svc_id, cmd_id) |
+			(ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT);
+
+	ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD,
+			    &desc);
+
+	return ret ? : desc.res.a1;
 }
 
-int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
+int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
+			u32 req_cnt, u32 *resp)
 {
-	return -ENOTSUPP;
+	int ret;
+	struct qcom_scm_desc desc = {0};
+
+	if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
+		return -ERANGE;
+
+	desc.args[0] = req[0].addr;
+	desc.args[1] = req[0].val;
+	desc.args[2] = req[1].addr;
+	desc.args[3] = req[1].val;
+	desc.args[4] = req[2].addr;
+	desc.args[5] = req[2].val;
+	desc.args[6] = req[3].addr;
+	desc.args[7] = req[3].val;
+	desc.args[8] = req[4].addr;
+	desc.args[9] = req[4].val;
+	desc.arginfo = QCOM_SCM_ARGS(10);
+
+	ret = qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP, &desc);
+	*resp = desc.res.a1;
+
+	return ret;
+}
+
+void __qcom_scm_init(void)
+{
+	u64 cmd;
+	struct arm_smccc_res res;
+	u32 function = QCOM_SCM_FNID(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD);
+
+	/* First try a SMC64 call */
+	cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64,
+				 ARM_SMCCC_OWNER_SIP, function);
+
+	arm_smccc_smc(cmd, QCOM_SCM_ARGS(1), cmd & (~BIT(ARM_SMCCC_TYPE_SHIFT)),
+		      0, 0, 0, 0, 0, &res);
+
+	if (!res.a0 && res.a1)
+		qcom_smccc_convention = ARM_SMCCC_SMC_64;
+	else
+		qcom_smccc_convention = ARM_SMCCC_SMC_32;
 }
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 23ccec6..475410b3e 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -189,6 +189,8 @@ static int qcom_scm_probe(struct platform_device *pdev)
 	__scm = scm;
 	__scm->dev = &pdev->dev;
 
+	__qcom_scm_init();
+
 	return 0;
 }
 
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index afe6676..0ea55d7 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -38,7 +38,10 @@ extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
 extern int __qcom_scm_hdcp_req(struct device *dev,
 		struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);
 
+extern void __qcom_scm_init(void);
+
 /* common error codes */
+#define QCOM_SCM_V2_EBUSY	-12
 #define QCOM_SCM_ENOMEM		-5
 #define QCOM_SCM_EOPNOTSUPP	-4
 #define QCOM_SCM_EINVAL_ADDR	-3
@@ -58,6 +61,8 @@ static inline int qcom_scm_remap_error(int err)
 		return -EOPNOTSUPP;
 	case QCOM_SCM_ENOMEM:
 		return -ENOMEM;
+	case QCOM_SCM_V2_EBUSY:
+		return -EBUSY;
 	}
 	return -EINVAL;
 }
-- 
1.9.1



From marc.zyngier at arm.com  Wed May 11 07:26:30 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 11 May 2016 15:26:30 +0100
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <573335FC.8000103@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
 <20160511123423.GO27623@cbox> <5733300C.9070304@arm.com>
 <573335FC.8000103@arm.com>
Message-ID: <57334116.7060607@arm.com>

On 11/05/16 14:39, Andre Przywara wrote:
> Hi,
> 
> On 11/05/16 14:13, Marc Zyngier wrote:
>> On 11/05/16 13:34, Christoffer Dall wrote:
>>> On Fri, May 06, 2016 at 11:45:37AM +0100, Andre Przywara wrote:
>>>> As the enable register handlers are shared between the v2 and v3
>>>> emulation, their implementation goes into vgic-mmio.c, to be easily
>>>> referenced from the v3 emulation as well later.
>>>>
>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>> ---
>>>> Changelog RFC..v1:
>>>> - use lower bits of address to determine IRQ number
>>>> - remove TODO, confirmed to be fine
>>>>
>>>> Changelog v1 .. v2:
>>>> - adapt to new MMIO framework
>>>>
>>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
>>>>  virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
>>>>  virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
>>>>  3 files changed, 69 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> index 69e96f7..448d1da 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> @@ -72,9 +72,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
>>>>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
>>>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
>>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
>>>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
>>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
>>>>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>>>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
>>>> index 41cf4f4..077ae86 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-mmio.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>>>> @@ -46,6 +46,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
>>>>  	/* Ignore */
>>>>  }
>>>>  
>>>> +/*
>>>> + * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
>>>> + * of the enabled bit, so there is only one function for both here.
>>>> + */
>>>> +unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
>>>> +				    gpa_t addr, unsigned int len)
>>>> +{
>>>> +	u32 intid = (addr & 0x7f) * 8;
>>>
>>> is there anything we can do about this to make it more intuitive?  A
>>> macro to generate the mask/offset based on bits per interrupt or
>>> something?
>>
>> Untested (and thus probably wrong):
>>
>> #define VGIC_ADDR_IRQ_MASK(bits) ((1024 - 1) >> (4 - (bits))
> 
> What about if bits is 8?

Gnii. This should be ((1024 - 1) >> (4 - ffs(bits))

> Wouldn't GENMASK(bits + 10 - 2, 0) do the trick?

I really can't see how that works... It could be
GENMASK(10 - 1 - ffs(bits), 0) though.

>> #define VGIC_ADDR_IRQ_MULT(bits) (8 / (bits))
> 
> IROUTER has a bits_per_irq value of 64. We just don't need to call it
> from there, but it would be nice if it could cover this.
> But I don't know a neat solution for this either.

Me neither, but I don't see that as a major issue so far.

	M.
-- 
Jazz is not dead. It just smells funny...


From andre.przywara at arm.com  Wed May 11 07:28:42 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 11 May 2016 15:28:42 +0100
Subject: [PATCH v3 24/55] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <57333F18.5030605@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-25-git-send-email-andre.przywara@arm.com>
 <20160511123423.GO27623@cbox> <5733300C.9070304@arm.com>
 <57333F18.5030605@arm.com>
Message-ID: <5733419A.9060001@arm.com>

On 11/05/16 15:18, Andre Przywara wrote:
> Would:
> 
> #define VGIC_ADDR_IRQ_MASK(bits) GENMASK_ULL((bits) + 10 - 1 - 1, 0)

Nonsense. Must be ... ilog2(bits) ..., of course.

Andre.

> #define VGIC_ADDR_TO_INTID(addr, bits) (((addr) &		\
> 			VGIC_ADDR_IRQ_MASK(bits)) * 64 / (bits) / 8)
> 
> work for all bitnesses?


From robh at kernel.org  Wed May 11 07:33:13 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 11 May 2016 09:33:13 -0500
Subject: [PATCH v2 1/2] doc/devicetree: Add Aspeed VIC bindings
In-Reply-To: <1462802317-27086-2-git-send-email-joel@jms.id.au>
References: <462797239-14765-1-git-send-email-joel@jms.id.au>
 <1462802317-27086-1-git-send-email-joel@jms.id.au>
 <1462802317-27086-2-git-send-email-joel@jms.id.au>
Message-ID: <20160511143313.GA7426@rob-hp-laptop>

On Mon, May 09, 2016 at 11:28:36PM +0930, Joel Stanley wrote:
> Signed-off-by: Joel Stanley <joel at jms.id.au>
> ---
> v2:
>   Fix device tree binding example, thanks Baruch and Arnd for pointing this out
> 
>  .../interrupt-controller/aspeed,ast2400-vic.txt    | 24 ++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
> new file mode 100644
> index 000000000000..86dede1755a2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
> @@ -0,0 +1,24 @@
> +Aspeed Vectored Interrupt Controller
> +
> +These bindings are for the Aspeed AST2400 interrupt controller register layout.
> +The SoC has an legacy register layout, but this driver does not support that
> +mode of operation.
> +
> +Required properties:
> +
> +- compatible : should be "aspeed,ast2400-vic".
> +
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source. The value shall be 1.

No need for level vs. edge flags?

> +- valid-sources : bitmask of valid irq sources

Drop this. Either all interrupt controllers need this or none of 
them do. The valid sources are the ones described in the DT.

> +
> +Example:
> +
> + vic: interrupt-controller {

Needs a unit address.

> +      compatible = "aspeed,ast2400-vic";
> +      interrupt-controller;
> +      #interrupt-cells = <1>;
> +      valid-sources = < 0xffffffff 0x0007ffff>;
> +      reg = <0x1e6c0080 0x80>;
> + };
> -- 
> 2.8.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From robh at kernel.org  Wed May 11 07:34:22 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 11 May 2016 09:34:22 -0500
Subject: [PATCH v5 1/4] ASoC: davinci-mcbsp: add binding for McBSP
In-Reply-To: <1462804522-29544-2-git-send-email-petr@barix.com>
References: <1462804522-29544-1-git-send-email-petr@barix.com>
 <1462804522-29544-2-git-send-email-petr@barix.com>
Message-ID: <20160511143422.GA21634@rob-hp-laptop>

On Mon, May 09, 2016 at 04:35:19PM +0200, Petr Kulhavy wrote:
> Add devicetree binding for the TI DA850/OMAP-L138/AM18xx
> MultiChannel Buffered Serial Port (McBSP)
> 
> The optional register range "dat" is not implemented at the moment.
> The current driver supports only DMA into RX/TX registers but no FIFO.
> Once the FIFO is implemented in the driver the "dat" range will be used.
> 
> Signed-off-by: Petr Kulhavy <petr at barix.com>
> ---
> v1: initial
> v2: add missing TC channel in dmas properties (for compatibility with the new EDMA3 binding)
>     remove "-audio" postfix from the compatible string
>     remove "channel-combine" property
> v3: remove the index note from the "mpu" property.
>     specify exactly the supported platforms in compatible string
> v4: minor correction in the example ("interrupt names"), re-added index note to the "mpu" property.
> v5: example updated to match da850.dtsi: using "sound@" and removed leading zeros from the reg property
> 
>  .../devicetree/bindings/sound/davinci-mcbsp.txt    | 52 ++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/davinci-mcbsp.txt

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


From eric.auger at linaro.org  Wed May 11 07:37:33 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Wed, 11 May 2016 16:37:33 +0200
Subject: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability at
 msi domain
In-Reply-To: <5733383F.9060202@arm.com>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
 <1462362858-2925-6-git-send-email-eric.auger@linaro.org>
 <20160509164942.5af8b30d@t450s.home> <57320803.8070506@linaro.org>
 <57321952.2020206@arm.com> <5732EF96.4070001@linaro.org>
 <5732FBF0.4040105@arm.com> <5732FF04.6060202@linaro.org>
 <5733383F.9060202@arm.com>
Message-ID: <573343AD.6040307@linaro.org>

Hi Robin,
On 05/11/2016 03:48 PM, Robin Murphy wrote:
> On 11/05/16 10:44, Eric Auger wrote:
>> Hi Robin,
>> On 05/11/2016 11:31 AM, Robin Murphy wrote:
>>> On 11/05/16 09:38, Eric Auger wrote:
>>>> Hi Robin, Alex,
>>>> On 05/10/2016 07:24 PM, Robin Murphy wrote:
>>>>> Hi Eric,
>>>>>
>>>>> On 10/05/16 17:10, Eric Auger wrote:
>>>>>> Hi Alex,
>>>>>> On 05/10/2016 12:49 AM, Alex Williamson wrote:
>>>>>>> On Wed,  4 May 2016 11:54:16 +0000
>>>>>>> Eric Auger <eric.auger at linaro.org> wrote:
>>>>>>>
>>>>>>>> On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is
>>>>>>>> abstracted
>>>>>>>> by the msi controller. vfio_safe_irq_domain allows to check whether
>>>>>>>> interrupts are "safe" for a given device. They are if the device
>>>>>>>> does
>>>>>>>> not use MSI
>>>>>>>
>>>>>>> Are we sure we're not opening a security hole here?  An MSI is
>>>>>>> simply a
>>>>>>> DMA write, so really whether or not a device uses MSI is irrelevant.
>>>>>>> If it can generate a DMA to the MSI doorbell then we need to be
>>>>>>> protected and I think we pretty much need to assume that devices are
>>>>>>> DMA capable.  Do the MSI domain checks cover this?
>>>>>> Let me try to rephrase: we check the device is not attached to an MSI
>>>>>> controller (I think this is the semantic of dev_get_msi_domain(dev)).
>>>>>>
>>>>>> If it is not, we don't have to care about MSI isolation: there
>>>>>> will be
>>>>>> no IOMMU binding between the device and any MSI doorbell. If it is we
>>>>>> check the msi domain is backed by an MSI controller able to
>>>>>> perform MSI
>>>>>> isolation.
>>>>>>
>>>>>> So effectively "usage of MSIs" is improper - since it is decided
>>>>>> after
>>>>>> the group attachment anyway  - and the commit message should rather
>>>>>> state "if the device is linked to an MSI controller" (dt msi-parent
>>>>>> notion I think).
>>>>>
>>>>> Hmm, I think Alex has a point here - on a GICv2m I can happily fire
>>>>> arbitrary MSIs from _a shell_ (using /dev/mem), and the CPUs
>>>>> definitely
>>>>> aren't in an MSI domain, so I don't think it's valid to assume that a
>>>>> device using only wired interrupts, therefore with no connection to
>>>>> any
>>>>> MSI controller, isn't still capable of maliciously spewing DMA all
>>>>> over
>>>>> any and every doorbell region in the system.
>>>>
>>>> Sorry but I still don't get the point. For the device to reach the
>>>> doorbell there must be an IOMMU mapping.
>>>
>>> Only when the doorbell is _downstream_ of IOMMU translation.
>> Yes but that's the root hypothesis with VFIO assignment, right?
>>
>> Except if the no-iommu option is explicitly set by the userspace, there
>> must be an IOMMU downstream to the device that protects all the DMA
>> transactions.
> 
> The IOMMU is downstream of the device, clearly, but the MSI machinery
> itself could be _in between_ the two - say, integrated into a PCIe root
> complex served by an external SMMU. The doorbell is carved out of the
> upstream address space so that a write targeting the appropriate address
> hits it directly and never even goes out to the SMMU - e.g.
> http://thread.gmane.org/gmane.linux.kernel.pci/47174/focus=47268

Ah OK, I now better understand the point. So in that case not all the
DMA accesses of the devices are properly protected by the sMMU. Doesn't
it look as a kind of PCIe Access Control Service issue here where
transactions are able to bypass the translation service (downstream to
the root complex)?

I clearly did not address that kind of topology in this series. In such
a case the MSIs may even not be mapped at all which was the primary
purpose of the series.

Do you have any clue about how to detect that situation? If we cannot
rely on any iommu service I don't find any other solution but to
recognize this situation and reject the assignment.

> 
>>>> - if the device is not attached to an MSI domain, there won't be any
>>>> doorbell iommu mapping built by this series, so no risk, right?
>>>>
>>>> The device will be allowed to reach only memory iommu mapped by
>>>> userspace with VFIO DMA MAP standard API. Of course if the userspace
>>>> can
>>>> mmap all the host PA that's a more general issue, right?
>>>>
>>>> - If the device is attached to an MSI domain (msi-parent link), 2
>>>> cases:
>>>> 1) the MSI controller advertises MSI isolation (ITS cases), no risk
>>>> 2) the MSI controller does not advertise MSI isolation (GICv2m), there
>>>> is a security hole.
>>>>      a) by default we reject the device attachment
>>>>      b) if the userspace overrides the safe interrupt option he accepts
>>>> the security hole
>>>>
>>>> What am I missing?
>>>
>>> The x86-with-interrupt-remapping-disabled case. Currently, without
>>> unsafe_interrupts, everything is rejected - with this patch, we'll still
>>> reject anything with an MSI domain, but e.g. legacy PCI devices using
>>> INTx would be free to scribble all over the un-translated interrupt
>>> region willy-nilly.
>> Assuming we have an IOMMU, either we have translated transactions or
>> faults? So if legacy PCI devices try to write into a doorbell, there
>> must be faults because there is no IOMMU mapping for doorbells?
> 
> To the best of my understanding, having been wading through the VT-d
> spec, the case on x86 is as above (OK, so strictly it's more "in
> parallel with" than "in front of") - writes outside the 0xFEExxxxx
> interrupt region go to the DMA remapping units, whereas writes within
> that region go to the interrupt remapping unit, and if that's disabled
> or not implemented, simply sail straight through to the APIC beyond.
that's my understanding too

Best Regards

Eric
> 
> Robin.
> 
>> Best Regards
>>
>> Eric
>>   That's the subtle, but significant, change in
>>> behaviour.
>>>
>>> Robin.
>>>
>>>> Best Regards
>>>>
>>>> Eric
>>>>>
>>>>> Robin.
>>>>>
>>>>>> Does it sound better?
>>>>>>
>>>>>> Regards
>>>>>>
>>>>>> Eric
>>>>>>>
>>>>>>>> or if the device uses MSI and the msi-parent controller
>>>>>>>> supports IRQ remapping.
>>>>>>>>
>>>>>>>> Then we check at group level if all devices have safe
>>>>>>>> interrupts: if
>>>>>>>> not,
>>>>>>>> we only allow the group to be attached if
>>>>>>>> allow_unsafe_interrupts is
>>>>>>>> set.
>>>>>>>>
>>>>>>>> At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP.
>>>>>>>> This is
>>>>>>>> changed in next patch.
>>>>>>>>
>>>>>>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>>>>>>>
>>>>>>>> ---
>>>>>>>> v3 -> v4:
>>>>>>>> - rename vfio_msi_parent_irq_remapping_capable into
>>>>>>>> vfio_safe_irq_domain
>>>>>>>>      and irq_remapping into safe_irq_domains
>>>>>>>>
>>>>>>>> v2 -> v3:
>>>>>>>> - protect vfio_msi_parent_irq_remapping_capable with
>>>>>>>>      CONFIG_GENERIC_MSI_IRQ_DOMAIN
>>>>>>>> ---
>>>>>>>>     drivers/vfio/vfio_iommu_type1.c | 44
>>>>>>>> +++++++++++++++++++++++++++++++++++++++--
>>>>>>>>     1 file changed, 42 insertions(+), 2 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/vfio/vfio_iommu_type1.c
>>>>>>>> b/drivers/vfio/vfio_iommu_type1.c
>>>>>>>> index 4d3a6f1..2fc8197 100644
>>>>>>>> --- a/drivers/vfio/vfio_iommu_type1.c
>>>>>>>> +++ b/drivers/vfio/vfio_iommu_type1.c
>>>>>>>> @@ -37,6 +37,8 @@
>>>>>>>>     #include <linux/vfio.h>
>>>>>>>>     #include <linux/workqueue.h>
>>>>>>>>     #include <linux/msi-iommu.h>
>>>>>>>> +#include <linux/irqdomain.h>
>>>>>>>> +#include <linux/msi.h>
>>>>>>>>
>>>>>>>>     #define DRIVER_VERSION  "0.2"
>>>>>>>>     #define DRIVER_AUTHOR   "Alex Williamson
>>>>>>>> <alex.williamson at redhat.com>"
>>>>>>>> @@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev,
>>>>>>>> void *data)
>>>>>>>>         return 0;
>>>>>>>>     }
>>>>>>>>
>>>>>>>> +/**
>>>>>>>> + * vfio_safe_irq_domain: returns whether the irq domain
>>>>>>>> + * the device is attached to is safe with respect to MSI
>>>>>>>> isolation.
>>>>>>>> + * If the irq domain is not an MSI domain, we return it is safe.
>>>>>>>> + *
>>>>>>>> + * @dev: device handle
>>>>>>>> + * @data: unused
>>>>>>>> + * returns 0 if the irq domain is safe, -1 if not.
>>>>>>>> + */
>>>>>>>> +static int vfio_safe_irq_domain(struct device *dev, void *data)
>>>>>>>> +{
>>>>>>>> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
>>>>>>>> +    struct irq_domain *domain;
>>>>>>>> +    struct msi_domain_info *info;
>>>>>>>> +
>>>>>>>> +    domain = dev_get_msi_domain(dev);
>>>>>>>> +    if (!domain)
>>>>>>>> +        return 0;
>>>>>>>> +
>>>>>>>> +    info = msi_get_domain_info(domain);
>>>>>>>> +
>>>>>>>> +    if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
>>>>>>>> +        return -1;
>>>>>>>> +#endif
>>>>>>>> +    return 0;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>     static int vfio_iommu_replay(struct vfio_iommu *iommu,
>>>>>>>>                      struct vfio_domain *domain)
>>>>>>>>     {
>>>>>>>> @@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void
>>>>>>>> *iommu_data,
>>>>>>>>         struct vfio_group *group, *g;
>>>>>>>>         struct vfio_domain *domain, *d;
>>>>>>>>         struct bus_type *bus = NULL;
>>>>>>>> -    int ret;
>>>>>>>> +    int ret, safe_irq_domains;
>>>>>>>>
>>>>>>>>         mutex_lock(&iommu->lock);
>>>>>>>>
>>>>>>>> @@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void
>>>>>>>> *iommu_data,
>>>>>>>>
>>>>>>>>         group->iommu_group = iommu_group;
>>>>>>>>
>>>>>>>> +    /*
>>>>>>>> +     * Determine if all the devices of the group have a safe irq
>>>>>>>> domain
>>>>>>>> +     * with respect to MSI isolation
>>>>>>>> +     */
>>>>>>>> +    safe_irq_domains = !iommu_group_for_each_dev(iommu_group,
>>>>>>>> &bus,
>>>>>>>> +                       vfio_safe_irq_domain);
>>>>>>>> +
>>>>>>>>         /* Determine bus_type in order to allocate a domain */
>>>>>>>>         ret = iommu_group_for_each_dev(iommu_group, &bus,
>>>>>>>> vfio_bus_type);
>>>>>>>>         if (ret)
>>>>>>>> @@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void
>>>>>>>> *iommu_data,
>>>>>>>>         INIT_LIST_HEAD(&domain->group_list);
>>>>>>>>         list_add(&group->next, &domain->group_list);
>>>>>>>>
>>>>>>>> +    /*
>>>>>>>> +     * to advertise safe interrupts either the IOMMU or the MSI
>>>>>>>> controllers
>>>>>>>> +     * must support IRQ remapping/interrupt translation
>>>>>>>> +     */
>>>>>>>>         if (!allow_unsafe_interrupts &&
>>>>>>>> -        !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
>>>>>>>> +        (!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) &&
>>>>>>>> !safe_irq_domains)) {
>>>>>>>>             pr_warn("%s: No interrupt remapping support.  Use the
>>>>>>>> module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU
>>>>>>>> support on this platform\n",
>>>>>>>>                    __func__);
>>>>>>>>             ret = -EPERM;
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
> 



From marc.zyngier at arm.com  Wed May 11 07:40:03 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 11 May 2016 15:40:03 +0100
Subject: [PATCH v3 23/55] KVM: arm/arm64: vgic-new: Add CTLR, TYPER and
 IIDR handlers
In-Reply-To: <57333554.9070908@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-24-git-send-email-andre.przywara@arm.com>
 <20160511120533.GM27623@cbox> <57332AD8.6050306@arm.com>
 <20160511131556.GR27623@cbox> <57333359.3000505@arm.com>
 <57333554.9070908@arm.com>
Message-ID: <57334443.2060501@arm.com>

On 11/05/16 14:36, Andre Przywara wrote:
> Hi,
> 
> On 11/05/16 14:27, Marc Zyngier wrote:
>> On 11/05/16 14:15, Christoffer Dall wrote:
>>> On Wed, May 11, 2016 at 01:51:36PM +0100, Marc Zyngier wrote:
>>>> On 11/05/16 13:05, Christoffer Dall wrote:
>>>>> On Fri, May 06, 2016 at 11:45:36AM +0100, Andre Przywara wrote:
>>>>>> From: Marc Zyngier <marc.zyngier at arm.com>
>>>>>>
>>>>>> Those three registers are v2 emulation specific, so their implementation
>>>>>> lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
>>>>>> as their implementation is pretty simple.
>>>>>> When the guest enables the distributor, we kick all VCPUs to get
>>>>>> potentially pending interrupts serviced.
>>>>>>
>>>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>>>> ---
>>>>>> Changelog RFC..v1:
>>>>>> - kick VCPUs is the distributor gets enabled
>>>>>> - improve comment
>>>>>>
>>>>>> Changelog v1 .. v2:
>>>>>> - adapt to new MMIO framework
>>>>>> - use switch() statements to improve readability
>>>>>>
>>>>>> Changelog v2 .. v3:
>>>>>> - add vgic_kick_vcpus() implementation
>>>>>>
>>>>>>  include/linux/irqchip/arm-gic.h  |  1 +
>>>>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 48 +++++++++++++++++++++++++++++++++++++++-
>>>>>>  virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
>>>>>>  virt/kvm/arm/vgic/vgic.h         |  4 ++++
>>>>>>  4 files changed, 67 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
>>>>>> index be0d26f..fd05185 100644
>>>>>> --- a/include/linux/irqchip/arm-gic.h
>>>>>> +++ b/include/linux/irqchip/arm-gic.h
>>>>>> @@ -33,6 +33,7 @@
>>>>>>  
>>>>>>  #define GIC_DIST_CTRL			0x000
>>>>>>  #define GIC_DIST_CTR			0x004
>>>>>> +#define GIC_DIST_IIDR			0x008
>>>>>>  #define GIC_DIST_IGROUP			0x080
>>>>>>  #define GIC_DIST_ENABLE_SET		0x100
>>>>>>  #define GIC_DIST_ENABLE_CLEAR		0x180
>>>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>>>> index 2729a22..69e96f7 100644
>>>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>>>> @@ -20,9 +20,55 @@
>>>>>>  #include "vgic.h"
>>>>>>  #include "vgic-mmio.h"
>>>>>>  
>>>>>> +static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
>>>>>> +					    gpa_t addr, unsigned int len)
>>>>>> +{
>>>>>> +	u32 value;
>>>>>> +
>>>>>> +	switch (addr & 0x0c) {
>>>>>> +	case GIC_DIST_CTRL:
>>>>>> +		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
>>>>>> +		break;
>>>>>> +	case GIC_DIST_CTR:
>>>>>> +		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
>>>>>> +		value = (value >> 5) - 1;
>>>>>> +		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
>>>>>> +		break;
>>>>>> +	case GIC_DIST_IIDR:
>>>>>> +		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
>>>>>> +		break;
>>>>>> +	default:
>>>>>> +		return 0;
>>>>>> +	}
>>>>>> +
>>>>>> +	return extract_bytes(value, addr & 3, len);
>>>>>> +}
>>>>>> +
>>>>>> +static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
>>>>>> +				    gpa_t addr, unsigned int len,
>>>>>> +				    unsigned long val)
>>>>>> +{
>>>>>> +	switch (addr & 0x0c) {
>>>>>> +	case GIC_DIST_CTRL:
>>>>>> +		if (!(addr & 1)) {
>>>>>
>>>>> what is this !(addr & 1) check?
>>>>
>>>> We check that the write includes the lowest byte of the register. But as
>>>> we only have aligned accesses, it probably doesn't matter... I'll hack
>>>> that away.
>>>>
>>> where do we check to only have aligned accesses?
>>
>> Looks like a missing feature. The v2 spec says:
>>
>> 4.1.4 GIC register access
>> All registers support 32-bit word accesses with the access type defined
>> in Table 4-1 on page 4-73 and Table 4-2 on page 4-74.
>> In addition, the GICD_IPRIORITYRn, GICD_ITARGETSRn, GICD_CPENDSGIRn, and
>> GICD_SPENDSGIRn registers support byte accesses.
>>
>> Similar thing for v3 (8.1.3).
>>
>> By the look of it, we should add checks in all accessors. I'll get onto it.
> 
> What about to tag every register in our vgic_register_region with a
> possible access width and do a generic check in
> dispatch_mmio_{read,write}? Then we wouldn't need to touch every handler.

That's my plan.

	M.
-- 
Jazz is not dead. It just smells funny...


From bharat.kumar.gogada at xilinx.com  Wed May 11 07:45:51 2016
From: bharat.kumar.gogada at xilinx.com (Bharat Kumar Gogada)
Date: Wed, 11 May 2016 14:45:51 +0000
Subject: [PATCH v2 1/2] Documentation: DT: bindings: Add Broadcom STB
 PCIe bindings
In-Reply-To: <1462475700-1654-2-git-send-email-f.fainelli@gmail.com>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
 <1462475700-1654-2-git-send-email-f.fainelli@gmail.com>
Message-ID: <8520D5D51A55D047800579B094147198258955CE@XAP-PVEXMBX01.xlnx.xilinx.com>

> 
>  .../devicetree/bindings/pci/brcm,brcmstb-pcie.txt  | 98
> ++++++++++++++++++++++
>  1 file changed, 98 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
> 
> diff --git a/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
> b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
> new file mode 100644
> index 000000000000..3682b0f0bc26
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pci/brcm,brcmstb-pcie.txt
> @@ -0,0 +1,98 @@
> +Broadcom STB PCIe Host Controller Device Tree Bindings
> +
> +This document describes the binding of the PCIe Root Complex hardware
> +found in Broadcom Set Top Box System-on-Chips such as BCM7425 (MIPS),
> +BCM7435 (MIPS) and
> +BCM7445 (ARMv7).
> +
> +Required properties:
> +- compatible: must be one of: "brcm,bcm7425-pcie"
> +			      "brcm,bcm7435-pcie"
> +			      "brcm,bcm7445-pcie"
> +
> +- reg: specifies the physical base address of the controller registers
> +and
> +  its length
> +
> +- interrupt-parent: must be a reference (phandle) to the parent
> +interrupt
> +  controller in the system (7038-l1-intc on MIPS, GIC on ARM/ARM64)
> +
> +- interrrupts: first interrupt must be the Level 1 interrupt number
> +corresponding
> +  to the main PCIe RC interrupt, second interrupt must be the MSI
> +interrupt
> +  See the interrupt-parent documentation for the number of cells and their
> meaning:
> +  MIPS:
> +Documentation/devicetree/bindings/interrupt-controller/brcm,bcm7038-
> l1-
> +intc.txt
> +  ARM/ARM64:
> +Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
> +
> +- interrupt-names: must be "pcie", and if present "msi"
> +
> +- interrupt-map: see pci.txt
> +
> +- interrupt-map-mask: see pci.txt
> +
> +- #address-cells: must be set to <3>, see pci.txt
> +
> +- #size-cells: must be set to <2>, see pci.txt
> +
> +- ranges: ranges for the PCI outbound windows, no I/O or prefetchable
> +windows
> +  must be specified here, only non-prefetchable. 32-bits windows or
> +64-bits
> +  windows are allowed based on the host processor's capabilities (ARM
> +w/ LPAE,
> +  ARM64).
> +
> +- #interrupt-cells: set to <1>, see pci.txt
> +
> +- brcm,log2-scb-sizes: log2 size of the SCB window that is mapped to
> +PCIe space
> +  there must be exactly one value per memory controller present in the
> +system
> +  (ranges from 1 to 3)

Can you please give more insight on what does this property do ?

Bharat
> +
> +Optional properties:
> +
> +- msi-controller: indicates that this is a MSI controller node (when
> +supported)
> +
> +- clocks: phandle to the functional clock that feeds into the PCIe RC
> +block
> +
> +- clock-names: the name(s) of the clocks specified in 'clocks'.  Note
> +  that if the 'clocks' property is given, 'clock-names' is mandatory,
> +  and the name of the clock is expected to be "pcie".
> +
> +- brcm,ssc: boolean that indicates usage of spread-spectrum clocking
> +
> +- brcm,gen: integer that indicates desired forced generation of link: 1
> +=> 2.5
> +  Gbps, 2 => 5.0 Gbps, 3 => 8.0 Gbps. Will override the auto-negotation
> +if
> +  specified.
> +
> +- <*>-supply: see
> +Documentation/devicetree/bindings/regulator/regulator.txt
> +
> +- <*>-supply-names: see
> +Documentation/devicetree/bindings/regulator/regulator.txt
> +
> +Example Node:
> +
> +This example assumes that the top-level #address-cells = <2> and
> +#size-cells = <2>, e.g: ARM LPAE configuration.
> +
> +	pcie0: pcie-controller at f0460000 {
> +		reg = <0x0 0xf0460000 0x0 0x9310>;
> +		interrupts = <0x0 0x33 0x4>, <0x0 0x34, 0x4>;
> +		interrupt-names = "pcie", "msi";
> +		compatible = "brcm,bcm7445-pcie";
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +
> +		/* Two non-prefetchable 32-bits memory space, each of
> 128MB
> + 		 * with the following mapping:
> +		 * PCIe address		=> CPU physical address space
> +		 * 0x00_0000_0000	=> 0x00_C000_0000
> +		 * 0x00_0800_0000	=> 0x00_C800_0000
> +		 */
> +		ranges = <0x02000000 0x00000000 0x00000000 0x00000000
> 0xc0000000 0x00000000 0x08000000>,
> +			 <0x02000000 0x00000000 0x08000000 0x00000000
> 0xc8000000 0x00000000 0x08000000>;
> +		#interrupt-cells = <1>;
> +		interrupt-map-mask = <0xf800 0 0 7>;
> +		interrupt-map = <0 0 0 1 &intc 47 3
> +				 0 0 0 2 &intc 48 3
> +				 0 0 0 3 &intc 49 3
> +				 0 0 0 4 &intc 50 3>;
> +		clocks = <&pcie0>;
> +		clock-names = "pcie";
> +		brcm,ssc;
> +		brcm,log2-scb-sizes = <0x1e 0x1e 0x1e>;
> +		vreg-wifi-pwr-supply-names = "vreg-wifi-pwr";
> +		vreg-wifi-pwr-supply = <&vreg-wifi-pwr>;
> +	};
> --
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in the
> body of a message to majordomo at vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html


From bharat.kumar.gogada at xilinx.com  Wed May 11 07:47:45 2016
From: bharat.kumar.gogada at xilinx.com (Bharat Kumar Gogada)
Date: Wed, 11 May 2016 14:47:45 +0000
Subject: [PATCH v2 2/2] pci: host: Add Broadcom STB PCIE RC controller
In-Reply-To: <1462475700-1654-3-git-send-email-f.fainelli@gmail.com>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
 <1462475700-1654-3-git-send-email-f.fainelli@gmail.com>
Message-ID: <8520D5D51A55D047800579B094147198258955D9@XAP-PVEXMBX01.xlnx.xilinx.com>

> +
> +static struct pci_ops brcm_pcie_ops = {
> +	.read = brcm_pcie_read_config,
> +	.write = brcm_pcie_write_config,
> +};
> +
> +static int brcm_pcie_probe(struct platform_device *pdev) {
> +	struct device_node *dn = pdev->dev.of_node;
> +	const u32 *log2_scb_sizes, *dma_ranges;
> +	const struct brcm_pcie_cfg_data *data;
> +	const struct of_device_id *of_id;
> +	struct brcm_pcie *pcie;
> +	void __iomem *base;
> +	struct resource *r;
> +	int i, rlen, ret;
> +	u32 tmp;
> +
> +	pcie = devm_kzalloc(&pdev->dev, sizeof(struct brcm_pcie),
> GFP_KERNEL);
> +	if (!pcie)
> +		return -ENOMEM;
> +
> +	of_id = of_match_node(brcm_pcie_match, dn);
> +	if (!of_id)
> +		return -EINVAL;
> +
> +	data = of_id->data;
> +	pcie->type = data->type;
> +	pcie->ops = &data->ops;
> +
> +	platform_set_drvdata(pdev, pcie);
> +
> +	INIT_LIST_HEAD(&pcie->resource);
> +
> +	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(&pdev->dev, r);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	ret = of_alias_get_id(dn, "pcie");
> +	if (ret >= 0)
> +		pcie->num = ret;
> +
> +	pcie->clk = devm_clk_get(&pdev->dev, "pcie");
> +	if (IS_ERR(pcie->clk)) {
> +		dev_err(&pdev->dev, "could not get clock\n");
> +		pcie->clk = NULL;
> +	}
> +
> +	ret = clk_prepare_enable(pcie->clk);
> +	if (ret) {
> +		dev_err(&pdev->dev, "could not enable clock\n");
> +		return ret;
> +	}
> +
> +	pcie->dn = dn;
> +	pcie->base = base;
> +	pcie->dev = &pdev->dev;
> +	pcie->dev->of_node = dn;
> +	pcie->gen = 0;
> +
> +	ret = of_property_read_u32(dn, "brcm,gen", &tmp);
> +	if (ret == 0) {
> +		if (tmp > 0 && tmp < 3)
> +			pcie->gen = (int)tmp;
> +		else
> +			dev_warn(pcie->dev, "bad DT value for prop
> 'brcm,gen");
> +	} else if (ret != -EINVAL) {
> +		dev_warn(pcie->dev, "error reading DT prop 'brcm,gen");
> +	}
> +
> +	pcie->ssc = of_property_read_bool(dn, "brcm,ssc");
> +
> +	/* Get the value for the log2 of the scb sizes. Subtract 15 from
> +	 * each because the target register field has 0==disabled and 1==6KB.
> +	 */
> +	log2_scb_sizes = of_get_property(dn, "brcm,log2-scb-sizes", &rlen);
> +	if (log2_scb_sizes) {
> +		for (i = 0; i < rlen / sizeof(u32); i++) {
> +			pcie->scb_size_vals[i]
> +				= (int)of_read_number(log2_scb_sizes + i, 1)
> +					- 15;
> +			pcie->num_memc++;
> +		}
> +	}
In your device tree documentation this is required property, what if this property 
is missing ?
> +
> +	/* Look for the dma-ranges property.  If it exists, issue a warning
> +	 * as PCIe drivers may not work.  This is because the identity
> +	 * mapping between system memory and PCIe space is not
> preserved,
> +	 * and we need Linux to massage the dma_addr_t values it gets
> +	 * from dma memory allocation.  This functionality will be added
> +	 * in the near future.
> +	 */
> +	dma_ranges = of_get_property(dn, "dma-ranges", &rlen);
> +	if (dma_ranges != NULL)
> +		dev_warn(pcie->dev, "no identity map; PCI drivers may fail");
> +
> +	if (IS_ENABLED(CONFIG_PCI_MSI)) {
> +		ret = irq_of_parse_and_map(pdev->dev.of_node, 1);
> +		if (ret == 0)
> +			dev_warn(pcie->dev, "cannot get msi intr; MSI
> disabled\n");
> +		else
> +			pcie->msi_irq = ret;
> +	}
> +
> +	ret = of_pci_get_host_bridge_resources(dn, 0, 0xff,
> +					       &pcie->resource, NULL);
> +	if (ret) {
> +		dev_err(pcie->dev, "ranges parsing failed\n");
> +		return ret;
> +	}
> +
> +	ret = brcm_pcie_setup_early(pcie);
> +	if (ret)
> +		goto out_err_clk;
> +
> +	/* If setup bridge fails, it cleans up behind itself */
> +	ret = brcm_setup_pcie_bridge(pcie);
> +	if (ret)
> +		goto out_err;
> +
> +	pcie->bus = pci_scan_root_bus(pcie->dev, pcie->num,
> &brcm_pcie_ops,
> +				      pcie, &pcie->resource);
> +	if (!pcie->bus) {
> +		ret = -ENOMEM;
> +		goto out_err_bus;
> +	}
> +
> +	if (IS_ENABLED(CONFIG_PCI_MSI))
> +		brcm_pcie_msi_chip_set(pcie);
> +
> +	pci_bus_size_bridges(pcie->bus);
> +	pci_bus_assign_resources(pcie->bus);
> +
> +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> +	pci_bus_add_devices(pcie->bus);
> +
> +	return 0;
> +
> +out_err_bus:
> +	brcm_pcie_enter_l23(pcie);
> +	brcm_pcie_turn_off(pcie);
> +out_err_clk:
> +	clk_disable_unprepare(pcie->clk);
> +out_err:
> +	return ret;
> +}
> +
> +static int brcm_pcie_remove(struct platform_device *pdev) {
> +	return brcm_pcie_suspend(&pdev->dev);
> +}
> +
> +static struct platform_driver brcm_pcie_driver = {
> +	.probe = brcm_pcie_probe,
> +	.remove = brcm_pcie_remove,
> +	.driver = {
> +		.name = "brcm-pcie",
> +		.owner = THIS_MODULE,
> +		.of_match_table = brcm_pcie_match,
> +		.pm = &brcm_pcie_pm_ops,
> +	},
> +};
> +module_platform_driver(brcm_pcie_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("Broadcom STB PCIE RC driver");
> +MODULE_AUTHOR("Broadcom");
> diff --git a/drivers/pci/host/pcie-brcmstb.h b/drivers/pci/host/pcie-
> brcmstb.h new file mode 100644 index 000000000000..b4a507423bb0
> --- /dev/null
> +++ b/drivers/pci/host/pcie-brcmstb.h
> @@ -0,0 +1,160 @@
> +#ifndef __PCIE_BRCMSTB_H
> +#define __PCIE_BRCMSTB_H
> +
> +#include <linux/io.h>
> +
> +/* Broadcom PCIE Offsets */
> +#define PCIE_RC_CFG_PCIE_LINK_CAPABILITY		0x00b8
> +#define PCIE_RC_CFG_PCIE_LINK_STATUS_CONTROL
> 	0x00bc
> +#define PCIE_RC_CFG_PCIE_ROOT_CAP_CONTROL		0x00c8
> +#define PCIE_RC_CFG_PCIE_LINK_STATUS_CONTROL_2
> 	0x00dc
> +#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1
> 	0x0188
> +#define PCIE_RC_CFG_PRIV1_ID_VAL3			0x043c
> +#define PCIE_RC_DL_MDIO_ADDR				0x1100
> +#define PCIE_RC_DL_MDIO_WR_DATA
> 	0x1104
> +#define PCIE_RC_DL_MDIO_RD_DATA
> 	0x1108
> +#define PCIE_MISC_MISC_CTRL				0x4008
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO		0x400c
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI		0x4010
> +#define PCIE_MISC_RC_BAR1_CONFIG_LO			0x402c
> +#define PCIE_MISC_RC_BAR1_CONFIG_HI			0x4030
> +#define PCIE_MISC_RC_BAR2_CONFIG_LO			0x4034
> +#define PCIE_MISC_RC_BAR2_CONFIG_HI			0x4038
> +#define PCIE_MISC_RC_BAR3_CONFIG_LO			0x403c
> +#define PCIE_MISC_RC_BAR3_CONFIG_HI			0x4040
> +#define PCIE_MISC_MSI_BAR_CONFIG_LO			0x4044
> +#define PCIE_MISC_MSI_BAR_CONFIG_HI			0x4048
> +#define PCIE_MISC_MSI_DATA_CONFIG			0x404c
> +#define PCIE_MISC_PCIE_CTRL				0x4064
> +#define PCIE_MISC_PCIE_STATUS				0x4068
> +#define PCIE_MISC_REVISION				0x406c
> +#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT	0x4070
> +#define PCIE_MISC_HARD_PCIE_HARD_DEBUG
> 	0x4204
> +#define PCIE_INTR2_CPU_BASE				0x4300
> +#define PCIE_MSI_INTR2_BASE				0x4500
> +
> +#define PCIE_RGR1_SW_INIT_1				0x9210
> +#define PCIE_EXT_CFG_INDEX				0x9000
> +#define PCIE_EXT_CFG_DATA				0x9004
> +
> +/* BCM7425 specific register offsets */
> +#define BCM7425_PCIE_RGR1_SW_INIT_1			0x8010
> +#define BCM7425_PCIE_EXT_CFG_INDEX			0x8300
> +#define BCM7425_PCIE_EXT_CFG_DATA			0x8304
> +
> +#define PCI_BUSNUM_SHIFT		20
> +#define PCI_SLOT_SHIFT			15
> +#define PCI_FUNC_SHIFT			12
> +
> +#define BRCM_NUM_PCI_OUT_WINS		4
> +#define BRCM_MAX_SCB			4
> +
> +/* Offsets from PCIE_INTR2_CPU_BASE and PCIE_MSI_INTR2_BASE */
> +#define STATUS				0x0
> +#define SET				0x4
> +#define CLR				0x8
> +#define MASK_STATUS			0xc
> +#define MASK_SET			0x10
> +#define MASK_CLR			0x14
> +
> +enum brcm_pcie_type {
> +	BCM7425,
> +	BCM7435,
> +	GENERIC,
> +};
> +
> +struct brcm_pcie;
> +
> +/* Chip-specific PCIe operations (read/write config and reset) */
> +struct brcm_pcie_ll_ops {
> +	u32 (*read_config)(struct brcm_pcie *pcie, int cfg_idx);
> +	void (*write_config)(struct brcm_pcie *pcie, int cfg_idx, u32 val);
> +	void (*rgr1_sw_init)(struct brcm_pcie *pcie, u32 mask,
> +			     int shift, u32 val);
> +};
> +
> +struct brcm_pcie_cfg_data {
> +	const enum brcm_pcie_type type;
> +	const struct brcm_pcie_ll_ops ops;
> +};
> +
> +struct brcm_msi;
> +
> +/* Internal Bus Controller Information.*/ struct brcm_pcie {
> +	void __iomem		*base;
> +	bool			suspended;
> +	struct clk		*clk;
> +	struct device_node	*dn;
> +	bool			ssc;
> +	int			gen;
> +	int			scb_size_vals[BRCM_MAX_SCB];
> +	struct pci_bus		*bus;
> +	struct device		*dev;
> +	struct list_head	resource;
> +	int			msi_irq;
> +	struct brcm_msi		*msi;
> +	unsigned int		rev;
> +	unsigned int		num;
> +	bool			bridge_setup_done;
> +	enum brcm_pcie_type	type;
> +	const struct brcm_pcie_ll_ops *ops;
> +	unsigned int		num_memc;
> +};
> +
> +/* Helper functions to access read/write config space and software init
> +which
> + * are chip-specific
> + */
> +static inline u32 brcm_pcie_ll_read_config(struct brcm_pcie *pcie, int
> +cfg_idx) {
> +	return pcie->ops->read_config(pcie, cfg_idx); }
> +
> +static inline void brcm_pcie_ll_write_config(struct brcm_pcie *pcie,
> +					     int cfg_idx, u32 val)
> +{
> +	pcie->ops->write_config(pcie, cfg_idx, val); }
> +
> +static inline void brcm_pcie_rgr1_sw_init(struct brcm_pcie *pcie, u32 mask,
> +					  int shift, u32 val)
> +{
> +	pcie->ops->rgr1_sw_init(pcie, mask, shift, val); }
> +
> +/*
> + * MIPS endianness is configured by boot strap, which also reverses all
> + * bus endianness (i.e., big-endian CPU + big endian bus ==> native
> + * endian I/O).
> + *
> + * Other architectures (e.g., ARM) either do not support big endian, or
> + * else leave I/O in little endian mode.
> + */
> +static inline u32 bpcie_readl(void __iomem *base) {
> +	if (IS_ENABLED(CONFIG_MIPS))
> +		return __raw_readl(base);
> +	else
> +		return readl(base);
> +}
> +
> +static inline void bpcie_writel(u32 val, void __iomem *base) {
> +	if (IS_ENABLED(CONFIG_MIPS))
> +		__raw_writel(val, base);
> +	else
> +		writel(val, base);
> +}
> +
> +#ifdef CONFIG_PCIE_BRCMSTB_MSI
> +int brcm_pcie_enable_msi(struct brcm_pcie *pcie, int nr); void
> +brcm_pcie_msi_chip_set(struct brcm_pcie *pcie); #else static inline int
> +brcm_pcie_enable_msi(struct brcm_pcie *pcie, int nr) {
> +	return 0;
> +}
> +static inline void brcm_pcie_msi_chip_set(struct brcm_pcie *pcie) { }
> +#endif
> +
> +#endif /* __PCIE_BRCMSTB_H */
> --
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in the
> body of a message to majordomo at vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html


From arnd at arndb.de  Wed May 11 07:50:01 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 16:50:01 +0200
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <5733149C.4030903@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <573305A8.50406@huawei.com> <5733149C.4030903@huawei.com>
Message-ID: <5250356.myv9GIZ34h@wuerfel>

On Wednesday 11 May 2016 19:16:44 Zhangjian wrote:
> Hi,
> 
> On 2016/5/11 18:12, Zhangjian (Bamvor) wrote:
> > Hi, Arnd
> >
> > On 2016/5/11 16:09, Arnd Bergmann wrote:
> >  > On Wednesday 11 May 2016 10:04:16 Zhangjian wrote:
> >  >>> I don't remember. It's probably not important whether we have the shift
> >  >>> in there, as long as it's independent of the actual kernel page size and
> >  >>> user space and kernel agree on the calling conventions.
> >  >> Well. I am ok with where to shift the pages size because we get the same
> >  >> result. I was just thinking if we should get rid of the name of mmap2 in our
> >  >> ILP32 porting. Actually, it is mmap but we name it as mmap2. User may confused
> >  >> if they do not know the implementations.
> >  >
> >  > That is a good point: If the implementation matches the mmap() behavior rather than
> >  > mmap2(), we should rename the macro by doing
> >  >
> >  > #undef __NR_mmap2
> >  > #define __NR_mmap 222
> >  >
> >  > in the uapi/asm/unistd.h file for ilp32 mode.
> > Do you mean define the following things in kernel:
> > ```
> > diff --git a/arch/arm64/include/uapi/asm/unistd.h b/arch/arm64/include/uapi/asm/unistd.h
> > index 1caadc2..3f79640 100644
> > --- a/arch/arm64/include/uapi/asm/unistd.h
> > +++ b/arch/arm64/include/uapi/asm/unistd.h
> > @@ -14,3 +14,9 @@
> >    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> >    */
> >   #include <asm-generic/unistd.h>
> > +
> > +#ifdef __ILP32__
> > +#undef __NR_mmap2
> > +#define __NR_mmap 222
> > +#endif /* #ifdef __ILP32__ */
> > +
> > ```
> > Then glibc could call mmap instead of mmap2.
> > I could not try it now. Because after change off_t to 64bit in glibc, stat
> > is fail. I may need to revert the stat relative patch.
> After revert stat relative patch in glibc, mmap01-mmap14 success. But mmap16
> success with segfault. I will investigate it later.
> 
> There is pointer and size_t in mmap, so, IIUC, we need to clear the top halves
> of register by using COMPAT_SYSCALL_WRAP6.

Correct, good catch!

> And after check the function in
> arch/s390/kernel/compat_linux.c, I feel that we need to do the same thing for
> pread64 and pwrite64.
> 

> But I got following error when I try to add
> COMPAT_SYSCALL_WRAP4(pread64, unsigned int, fd, char __user *, buf,
> size_t, count, loff_t, pos);
> COMPAT_SYSCALL_WRAP4(pwrite64, unsigned int, fd, const char __user *, buf,
> size_t, count, loff_t, pos);
> 

Hmm, that is indeed tricky. I think COMPAT_SYSCALL_WRAP4 rightfully
refuses the loff_t argument here, as the common case is that this is
not possible.

Can you open-code this using a COMPAT_SYSCALL4 definition similar to what
arch/tile has, but without the merging of the two halves of the argument?

	Arnd


From heiko at sntech.de  Wed May 11 07:51:58 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 11 May 2016 16:51:58 +0200
Subject: [PATCH 2/2] ARM64: dts: rockchip: enable eMMC for rk3399 EVB
In-Reply-To: <1462924975-69072-2-git-send-email-briannorris@chromium.org>
References: <1462924975-69072-1-git-send-email-briannorris@chromium.org>
 <1462924975-69072-2-git-send-email-briannorris@chromium.org>
Message-ID: <4355979.JCGxOmTVBW@phil>

Hi Brian,

Am Dienstag, 10. Mai 2016, 17:02:55 schrieb Brian Norris:
> The 'mmc-hs400-enhanced-strobe' property has been acked by Rob Herring,
> though it's still not merged.

The commit message should describe the actual change not the volatile 
environment surrounding it :-) .

When I apply this patch the property-binding will have made it into a 
maintainer-tree so is not valid anymore then. That is more material for the 
"comment-section" below the "---"

> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
>  arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts index
> 1a3eb1482050..ccfd2bcf02e1 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> @@ -89,6 +89,18 @@
>  	status = "okay";
>  };
> 
> +&emmc_phy {
> +	status = "okay";
> +};
> +
> +&sdhci {
> +	bus-width = <8>;
> +	mmc-hs400-1_8v;
> +	non-removable;
> +	mmc-hs400-enhanced-strobe;

alphabetic ordering of properties please

> +	status = "okay";
> +};
> +
>  &uart2 {
>  	status = "okay";
>  };



From robh at kernel.org  Wed May 11 07:54:09 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 11 May 2016 09:54:09 -0500
Subject: [PATCH 3/6] dt-bindings: mtu3: add devicetree bindings
In-Reply-To: <1462868614-20602-4-git-send-email-chunfeng.yun@mediatek.com>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462868614-20602-4-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <20160511145409.GA23042@rob-hp-laptop>

On Tue, May 10, 2016 at 04:23:31PM +0800, Chunfeng Yun wrote:
> add a DT binding doc for MediaTek USB3 DRD driver
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
> ---
>  Documentation/devicetree/bindings/usb/mtu3.txt |   86 ++++++++++++++++++++++++
>  1 file changed, 86 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/usb/mtu3.txt
> 
> diff --git a/Documentation/devicetree/bindings/usb/mtu3.txt b/Documentation/devicetree/bindings/usb/mtu3.txt
> new file mode 100644
> index 0000000..ff142a5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/mtu3.txt
> @@ -0,0 +1,86 @@
> +The device node for Mediatek USB3.0 DRD controller
> +
> +Required properties:
> + - compatible : should be "mediatek,mt8173-mtu3"
> + - reg : specifies physical base address and size of the registers
> + - reg-names: should be "mac" for device IP and "ippc" for IP port control
> + - interrupts : interrupt used by the device IP
> + - power-domains : a phandle to USB power domain node to control USB's
> +	mtcmos
> + - vusb33-supply : regulator of USB avdd3.3v
> + - clocks : a list of phandle + clock-specifier pairs, one for each
> +	entry in clock-names
> + - clock-names : must contain "sys_ck" for clock of controller;
> +	"wakeup_deb_p0" and "wakeup_deb_p1" are optional, they are
> +	depends on "mediatek,enable-wakeup"
> + - phys : a list of phandle + phy specifier pairs

How many?

> + - dr_mode : should be one of "host", "peripheral" or "otg",
> +	refer to usb/generic.txt
> +
> +Optional properties:
> + - #address-cells, #size-cells : should be '2' if the device has sub-nodes
> +	with 'reg' property
> + - ranges : allows valid 1:1 translation between child's address space and
> +	parent's address space
> + - extcon : external connector for vbus and idpin changes detection, needed
> +	when supports dual-role mode.
> + - vbus-supply : reference to the VBUS regulator, needed when supports
> +	dual-role mode.
> + - pinctl-names : a pinctrl state named "default" must be defined,
> +	"id_float" and "id_ground" are optinal which depends on
> +	"mediatek,enable-manual-drd"
> + - pinctrl-0 : pin control group
> +	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
> +
> + - maximum-speed : valid arguments are "super-speed", "high-speed" and
> +	"full-speed"; refer to usb/generic.txt
> + - mediatek,enable-wakeup : supports ip sleep wakeup used by host mode
> + - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup
> +	control register, it depends on "mediatek,enable-wakeup".

There is a standard wake-up source binding. That assumes asserting the 
device's irq (or one of the irqs) will cause wake-up.

The syscon-wakeup should probably get implemented as a stacked 
irqdomain.

> + - mediatek,enable-manual-drd : supports manual dual-role switch by sysfs
> +	interface; only used when receptacle is TYPE-A and also wants to support
> +	dual-role mode.

sysfs is a Linux detail that doesn't apply to the binding. Does the 
property mean "the IP block supports or doesn't support switching"  or 
"I want to enable switching feature". Only the former belongs in DT.

As far as the sysfs interface, it should be generic, not Mediatek 
specific.

> +
> +Sub-nodes:
> +The xhci should be added as subnode to mtu3 as shown in the following example
> +if host mode is enabled. The DT binding details of xhci can be found in:
> +Documentation/devicetree/bindings/usb/mt8173-xhci.txt

Is XHCI really a sub-block? It seems mostly independent.

> +
> +Example:
> +ssusb: usb at 11271000 {
> +	compatible = "mediatek,mt8173-mtu3";
> +	reg = <0 0x11271000 0 0x3000>,
> +	      <0 0x11280700 0 0x0100>;
> +	reg-names = "mac", "ippc";
> +	interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>;
> +	phys = <&phy_port0 PHY_TYPE_USB3>,
> +	       <&phy_port1 PHY_TYPE_USB2>;
> +	power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
> +	clocks = <&topckgen CLK_TOP_USB30_SEL>,
> +		 <&pericfg CLK_PERI_USB0>,
> +		 <&pericfg CLK_PERI_USB1>;
> +	clock-names = "sys_ck",
> +		      "wakeup_deb_p0",
> +		      "wakeup_deb_p1";
> +	vusb33-supply = <&mt6397_vusb_reg>;
> +	vbus-supply = <&usb_p0_vbus>;
> +	extcon = <&extcon_usb>;
> +	dr_mode = "otg";
> +	mediatek,enable-wakeup;
> +	mediatek,syscon-wakeup = <&pericfg>;
> +	#address-cells = <2>;
> +	#size-cells = <2>;
> +	ranges;
> +	status = "disabled";
> +
> +	usb_host: xhci at 11270000 {
> +		compatible = "mediatek,mt8173-xhci";
> +		reg = <0 0x11270000 0 0x1000>;
> +		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
> +		power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
> +		clocks = <&topckgen CLK_TOP_USB30_SEL>;
> +		clock-names = "sys_ck";
> +		vusb33-supply = <&mt6397_vusb_reg>;
> +		status = "disabled";
> +	};
> +};
> -- 
> 1.7.9.5
> 


From wsa at the-dreams.de  Wed May 11 08:01:22 2016
From: wsa at the-dreams.de (Wolfram Sang)
Date: Wed, 11 May 2016 17:01:22 +0200
Subject: [PATCH] i2c: st: Implement i2c_bus_recovery_info callbacks
In-Reply-To: <20160429140351.GA1459@griffinp-mac>
References: <1460467759-11737-1-git-send-email-peter.griffin@linaro.org>
 <20160424211044.GD4317@katana> <5722107C.3000600@st.com>
 <20160428145720.GA1541@katana> <572344D8.6060401@st.com>
 <20160429140351.GA1459@griffinp-mac>
Message-ID: <20160511150122.GF1716@katana>

> Yes I'll send a v2 with your comment added.

Any news?

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160511/35636bd2/attachment.sig>

From heiko at sntech.de  Wed May 11 08:04:49 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 11 May 2016 17:04:49 +0200
Subject: [PATCH v8 1/8] i2c: rk3x: add documentation to fields in "struct
 rk3x_i2c"
In-Reply-To: <1462908252-27016-2-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908252-27016-2-git-send-email-david.wu@rock-chips.com>
Message-ID: <4217955.sKb92Wcadr@phil>

Am Mittwoch, 11. Mai 2016, 03:24:05 schrieb David Wu:

In general, all patches should have a commit message (even if it's obvious) 
and some maintainers even enforce this in a hard way.

How about something like:

----
Add kernel-doc documentation for the elements of the previously
undocumented struct rk3x_i2c.
----

Some minor nitpicks below, otherwise
Reviewed-by: Heiko Stuebner <heiko at sntech.de>

> Signed-off-by: David Wu <david.wu at rock-chips.com>
> Reviewed-by: Douglas Anderson <dianders at chromium.org>
> ---
> Change in v8:
> - none
> 
>  drivers/i2c/busses/i2c-rk3x.c | 22 +++++++++++++++++++++-
>  1 file changed, 21 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> index 80bed02..7e45d51 100644
> --- a/drivers/i2c/busses/i2c-rk3x.c
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -90,6 +90,26 @@ struct rk3x_i2c_soc_data {
>  	int grf_offset;
>  };
> 
> +/**
> + * struct rk3x_i2c - private data of the controller
> + * @adap: corresponding I2C adapter
> + * @dev: device for this controller
> + * @soc_data: related soc data struct
> + * @regs: virtual memory area
> + * @clk: clock of i2c bus
> + * @clk_rate_nb: i2c clk rate change notify
		^ i2c clk rate change notifier block

> + * @t: I2C known timing information
> + * @lock: spinlock for the i2c bus
> + * @wait: the waitqueue to wait for i2c transfer
> + * @busy: the condition for the event to wait for
> + * @msg: current i2c message
> + * @addr: addr of i2c slave device
> + * @mode: mode of i2c transfer
> + * @is_last_msg: flag determines whether it is the last msg in this
> transfer + * @state: state of i2c transfer
> + * @processed: byte length which has been send or received
										^ sent (with a "t")

> + * @error: error code for i2c transfer
> + */
>  struct rk3x_i2c {
>  	struct i2c_adapter adap;
>  	struct device *dev;
> @@ -116,7 +136,7 @@ struct rk3x_i2c {
> 
>  	/* I2C state machine */
>  	enum rk3x_i2c_state state;
> -	unsigned int processed; /* sent/received bytes */
> +	unsigned int processed;
>  	int error;
>  };



From sudeep.holla at arm.com  Wed May 11 08:06:14 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 11 May 2016 16:06:14 +0100
Subject: [PATCH v4 2/5] ACPI / processor_idle: Add support for Low Power
 Idle(LPI) states
In-Reply-To: <1857618.TLitUhExSh@vostro.rjw.lan>
References: <1461069013-13292-1-git-send-email-sudeep.holla@arm.com>
 <1461069013-13292-3-git-send-email-sudeep.holla@arm.com>
 <1857618.TLitUhExSh@vostro.rjw.lan>
Message-ID: <57334A66.6070004@arm.com>



On 11/05/16 01:03, Rafael J. Wysocki wrote:
> On Tuesday, April 19, 2016 01:30:10 PM Sudeep Holla wrote:
>> ACPI 6.0 introduced an optional object _LPI that provides an alternate
>> method to describe Low Power Idle states. It defines the local power
>> states for each node in a hierarchical processor topology. The OSPM can
>> use _LPI object to select a local power state for each level of processor
>> hierarchy in the system. They used to produce a composite power state
>> request that is presented to the platform by the OSPM.
>>
>> Since multiple processors affect the idle state for any non-leaf hierarchy
>> node, coordination of idle state requests between the processors is
>> required. ACPI supports two different coordination schemes: Platform
>> coordinated and  OS initiated.
>>
>> This patch adds initial support for Platform coordination scheme of LPI.
>>
>> Cc: "Rafael J. Wysocki" <rjw at rjwysocki.net>
>> Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
>> ---
>>   drivers/acpi/bus.c              |  11 +-
>>   drivers/acpi/processor_driver.c |   2 +-
>>   drivers/acpi/processor_idle.c   | 441 +++++++++++++++++++++++++++++++++++-----
>>   include/acpi/processor.h        |  25 ++-
>>   include/linux/acpi.h            |   4 +
>>   5 files changed, 422 insertions(+), 61 deletions(-)
>>
>> Hi Rafael,
>>
>> Yet to be discussed(retained as in from previous version):
>> - Kconfig entry removal: Need feedback on how to deal with that
>>    without having to introduce dummy _CST related ARM64 callbacks
>> - Didn't defer processing of LPI buffers to flattening as it
>>    results in the same buffer decoded multiple times
>> - ACPI_CSTATE_INTEGER : IMO it's reasonable to keep it aroundsince the
>>    it's part of LPI specification(not just ARM FFH)
>
> I'm basically fine with the current set, up to some minor points.
>
> I've sent my comments on patch [1/5] already.
>
> My main concern about the flattening of _LPI is that at one point we'll
> probably decide to unflatten it and that will change the behavior for
> current users.  There needs to be a plan for that IMO.
>

Are you referring the OS co-ordinated mode ? If yes, I agree. If not,
can you explain why would we not flatten the LPI states ?

[...]

>>
>> +struct acpi_processor_lpi_info {
>> +	int state_count;
>> +	struct acpi_processor_lpi *lpix;
>> +};
>
> This is a bit cryptic, especially the name of the lpix field.
>
> I'd do something like
>
> struct acpi_lpi_states_array {
> 	unsigned int size;
> 	struct acpi_lpi_state *entries;
> };
>
> and that is sort of self-documenting.
>

Agreed and that's looks much better.

>> +
>> +static int obj_get_integer(union acpi_object *obj, u32 *value)
>> +{
>> +	if (obj->type != ACPI_TYPE_INTEGER)
>> +		return -EINVAL;
>
> I'd add an empty line here and everywhere where there's only one
> statement after if () or for () etc.
>
> You've done that in some places IIRC, but please stick to one convention
> everywhere.
>

I have taken all the review comments and fixed them as suggested.

[...]

>> +
>> +	for (i = 0; i < fl_scnt && i < CPUIDLE_STATE_MAX; i++) {
>> +		lpi = &pr->power.lpi_states[i];
>> +
>> +		state = &drv->states[i];
>> +		snprintf(state->name, CPUIDLE_NAME_LEN, "LPI-%d", i);
>> +		strlcpy(state->desc, lpi->desc, CPUIDLE_DESC_LEN);
>> +		state->exit_latency = lpi->wake_latency;
>> +		state->target_residency = lpi->min_residency;
>> +		if (lpi->arch_flags)
>> +			state->flags |= CPUIDLE_FLAG_TIMER_STOP;
>> +		state->enter = acpi_idle_lpi_enter;
>
> No ->enter_freeze ?
>

I don't have a system to test this. Also IIUC the cpuidle does support
suspend-to-idle even when ->enter_freeze is not implemented right.
Can we add it later once I find a way to test. Correctly no wakeup on my
test platform :(

>>
>> +struct acpi_processor_lpi {
>
> As I said above, I'd call this
>
> struct acpi_lpi_state {
>
> because (a) it represents a state and (b) that doesn't have to be a state
> of a processor.
>

Agreed, that's mainly copy paste from _CST which calls it
acpi_processor_cx :)

-- 
-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Wed May 11 08:06:29 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 11 May 2016 16:06:29 +0100
Subject: [PATCH v4 4/5] arm64: add support for ACPI Low Power Idle(LPI)
In-Reply-To: <3620725.8soc3SaFWB@vostro.rjw.lan>
References: <1461069013-13292-1-git-send-email-sudeep.holla@arm.com>
 <1461069013-13292-5-git-send-email-sudeep.holla@arm.com>
 <3620725.8soc3SaFWB@vostro.rjw.lan>
Message-ID: <57334A75.10207@arm.com>



On 11/05/16 01:07, Rafael J. Wysocki wrote:
> On Tuesday, April 19, 2016 01:30:12 PM Sudeep Holla wrote:
>> This patch adds appropriate callbacks to support ACPI Low Power Idle
>> (LPI) on ARM64.
>>
>> It also selects ARCH_SUPPORTS_ACPI_PROCESSOR_LPI if ACPI is enabled
>> on ARM64.
>
> Can you remind me why we need the ARCH_SUPPORTS_ACPI_PROCESSOR_LPI thing in
> addition to the previously defined ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE?
>

That's stupid of me, I removed it from the driver in v4 but the few
remnants of it stayed by mistake(mainly in this patch alone)

> I thought supporting LPI would not require an arch Kconfig option.
>

That's correct.

-- 
Regards,
Sudeep


From sudeep.holla at arm.com  Wed May 11 08:07:56 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 11 May 2016 16:07:56 +0100
Subject: [PATCH v4 1/5] ACPI / processor_idle: introduce
 ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE
In-Reply-To: <5796685.UTMTWTestt@vostro.rjw.lan>
References: <1461069013-13292-1-git-send-email-sudeep.holla@arm.com>
 <1461069013-13292-2-git-send-email-sudeep.holla@arm.com>
 <5796685.UTMTWTestt@vostro.rjw.lan>
Message-ID: <57334ACC.2000403@arm.com>



On 10/05/16 01:02, Rafael J. Wysocki wrote:
> On Tuesday, April 19, 2016 01:30:09 PM Sudeep Holla wrote:
>> ACPI 6.0 adds a new method to specify the CPU idle states(C-states)
>> called Low Power Idle(LPI) states. Since new architectures like ARM64
>> use only LPIs, introduce ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE to
>> encapsulate all the code supporting the old style C-states(_CST)
>>
>> This patch will help to extend the processor_idle module to support
>> LPI.
>>
>> Cc: x86 at kernel.org
>> Cc: linux-ia64 at vger.kernel.org
>> Cc: "Rafael J. Wysocki" <rjw at rjwysocki.net>
>> Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
>> ---
>>   arch/ia64/Kconfig             |  1 +
>>   arch/x86/Kconfig              |  1 +
>>   drivers/acpi/Kconfig          |  3 ++
>>   drivers/acpi/processor_idle.c | 74 +++++++++++++++++++++++++++++--------------
>>   include/acpi/processor.h      |  3 +-
>>   5 files changed, 57 insertions(+), 25 deletions(-)
>>
>> diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
>> index b534ebab36ea..717de2a146e2 100644
>> --- a/arch/ia64/Kconfig
>> +++ b/arch/ia64/Kconfig
>> @@ -16,6 +16,7 @@ config IA64
>>   	select PCI if (!IA64_HP_SIM)
>>   	select ACPI if (!IA64_HP_SIM)
>>   	select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
>> +	select ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE if ACPI
>>   	select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
>>   	select HAVE_UNSTABLE_SCHED_CLOCK
>>   	select HAVE_IDE
>> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
>> index 2dc18605831f..eb03fd0d63b9 100644
>> --- a/arch/x86/Kconfig
>> +++ b/arch/x86/Kconfig
>> @@ -37,6 +37,7 @@ config X86
>>   	select ARCH_MIGHT_HAVE_ACPI_PDC		if ACPI
>>   	select ARCH_MIGHT_HAVE_PC_PARPORT
>>   	select ARCH_MIGHT_HAVE_PC_SERIO
>> +	select ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE if ACPI
>>   	select ARCH_SUPPORTS_ATOMIC_RMW
>>   	select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT
>>   	select ARCH_SUPPORTS_INT128		if X86_64
>> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
>> index 82b96ee8624c..ec289078667c 100644
>> --- a/drivers/acpi/Kconfig
>> +++ b/drivers/acpi/Kconfig
>> @@ -48,6 +48,9 @@ config ACPI_LEGACY_TABLES_LOOKUP
>>   config ARCH_MIGHT_HAVE_ACPI_PDC
>>   	bool
>>
>> +config ARCH_SUPPORTS_ACPI_PROCESSOR_CSTATE
>> +	bool
>
> It might be better to do
>
> config ACPI_PROCESSOR_CST
> 	bool
> 	depends on ia64 || x86
>

Done

> Should it depend on ARCH_HAS_POWER_INIT too?
>

IIUC it's not defined for ia64, so better not to add that dependency
here IMO. include/acpi/processor.h encapsulates it. Let me know if I
have misunderstood it.

-- 
Regards,
Sudeep


From petr at barix.com  Wed May 11 08:10:40 2016
From: petr at barix.com (Petr Kulhavy)
Date: Wed, 11 May 2016 17:10:40 +0200
Subject: [PATCH v5 2/4] ASoC: Davinci: McBSP: add device tree support for
 McBSP
In-Reply-To: <20160511145717.GJ6261@sirena.org.uk>
References: <1462804522-29544-1-git-send-email-petr@barix.com>
 <1462804522-29544-3-git-send-email-petr@barix.com>
 <20160511145717.GJ6261@sirena.org.uk>
Message-ID: <57334B70.8000008@barix.com>

On 11.05.2016 16:57, Mark Brown wrote:
> On Mon, May 09, 2016 at 04:35:20PM +0200, Petr Kulhavy wrote:
>> This adds DT support for the TI DA8xx/OMAP-L1x/AM17xx/AM18xx McBSP driver.
>>
>> Signed-off-by: Petr Kulhavy <petr at barix.com>
>> Reviewed-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
> How did this manage to get review but not the accompanying binding?
The whole set got reviewed by Peter in version 4 and the binding in v4 
got acked by Rob.
For the patches 2 and 3 which were taken over into version 5 without any 
modification I left the Reviewed-by tag there.
But since I made a (minor) modification in the binding example I removed 
Rob's ack.

Petr


From nicolas.ferre at atmel.com  Wed May 11 08:12:14 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Wed, 11 May 2016 17:12:14 +0200
Subject: [GIT PULL] at91: fixes for 4.6 #2
Message-ID: <1462979534-29347-1-git-send-email-nicolas.ferre@atmel.com>

Arnd, Olof, Kevin,

Another regression reported by Richard yesterday and quickly fixed by Boris.
Since this regression was introduced in 4.6-rc1 it would be great if you could
take it before 4.6 is released.

Thanks, best regards,

The following changes since commit b8453d4ee9e24c6590dd0eecbab1c3cc2028317f:

  ARM: dts: at91: sama5d2: use "atmel,sama5d3-nfc" compatible for nfc (2016-05-10 09:09:47 +0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91.git tags/at91-fixes2

for you to fetch changes up to aab0a4c83ceb344d2327194bf354820e50607af6:

  ARM: dts: at91: sam9x5: Fix the memory range assigned to the PMC (2016-05-11 16:31:40 +0200)

----------------------------------------------------------------
Second AT91 fix PR for 4.6:
- fix a regression on the clock subsystem while switching to syscon/regmap
  due to a stricter check of the register map.

----------------------------------------------------------------
Boris Brezillon (1):
      ARM: dts: at91: sam9x5: Fix the memory range assigned to the PMC

 arch/arm/boot/dts/at91sam9x5.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

-- 
Nicolas Ferre


From nicolas.ferre at atmel.com  Wed May 11 08:14:07 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Wed, 11 May 2016 17:14:07 +0200
Subject: [PATCH] ARM: dts: at91: sam9x5: Fix the memory range assigned to
 the PMC
In-Reply-To: <5733056C.9000100@atmel.com>
References: <1462957202-22671-1-git-send-email-boris.brezillon@free-electrons.com>
 <5733056C.9000100@atmel.com>
Message-ID: <57334C3F.5010605@atmel.com>

Le 11/05/2016 12:11, Nicolas Ferre a ?crit :
> Le 11/05/2016 11:00, Boris Brezillon a ?crit :
>> The memory range assigned to the PMC (Power Management Controller) was
>> not including the PMC_PCR register which are used to control peripheral
>> clocks.
>>
>> This was working fine thanks to the page granularity of ioremap(), but
>> started to fail when we switched to syscon/regmap, because regmap is
>> making sure that all accesses are falling into the reserved range.
>>
>> Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
>> Reported-by: Richard Genoud <richard.genoud at gmail.com>
>> Tested-by: Richard Genoud <richard.genoud at gmail.com>
>> Fixes: 863a81c3be1d ("clk: at91: make use of syscon to share PMC registers in several drivers")
>> Cc: <stable at vger.kernel.org>
> 
> Acked-by: Nicolas Ferre <nicolas.ferre at atmel.com>
> 
> Thanks Boris!
> 
> 
>> ---
>> Hi Arnd,
>>
>> This patch is fixing a regression reported by Richard. Since this
>> regression was introduced in 4.6-rc1 it would be great if you could
>> take it before 4.6 is released.
> 
> Arnd, arm-soc guys,
> 
> I can build a Pull-Request instantly today, if you wish: just tell me if
> you prefer.

Actually, I've just sent one so that we don't loose time:

"[GIT PULL] at91: fixes for 4.6 #2"

Bye,

>> ---
>>  arch/arm/boot/dts/at91sam9x5.dtsi | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
>> index 0827d59..cd0cd5f 100644
>> --- a/arch/arm/boot/dts/at91sam9x5.dtsi
>> +++ b/arch/arm/boot/dts/at91sam9x5.dtsi
>> @@ -106,7 +106,7 @@
>>  
>>  			pmc: pmc at fffffc00 {
>>  				compatible = "atmel,at91sam9x5-pmc", "syscon";
>> -				reg = <0xfffffc00 0x100>;
>> +				reg = <0xfffffc00 0x200>;
>>  				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
>>  				interrupt-controller;
>>  				#address-cells = <1>;
>>
> 
> 


-- 
Nicolas Ferre


From pbonzini at redhat.com  Wed May 11 08:23:30 2016
From: pbonzini at redhat.com (Paolo Bonzini)
Date: Wed, 11 May 2016 17:23:30 +0200
Subject: [PULL 00/29] KVM/ARM Changes for v4.7
In-Reply-To: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <57334E72.9010109@redhat.com>



On 11/05/2016 15:29, Christoffer Dall wrote:
> Hi Paolo and Radim,
> 
> Here is the initial set of changes for KVM/ARM for v4.7.
> 
> Sorry I'm a bit late with these, but we were trying to get the new vgic
> implementation in as part of this, but I have decided to send this pull
> request now, and we can follow up with another for the new VGIC,
> assuming we feel like we have that in place in a few days.

Don't worry, you're not late at all.  I've pulled this to kvm/queue.

> There are a few changes in this pull request touching things outside
> KVM, but they should all carry the necessary acks and it made the
> merge process much easier to do it this way.

The following are properly acked:

    arm64: Reuse TCR field definitions for EL1 and EL2
    arm64: Introduce pmd_thp_or_huge

I wouldn't have minded more explicit Acked-bys for the following:

    irqchip/gic-v2: Gather ACPI specific data in a single structure
    irqchip/gic-v2: Parse and export virtual GIC information
    irqchip/gic-v3: Prefix all pr_* messages by "GICv3: "
    irqchip/gic-v3: Gather all ACPI specific data in a single structure
    irqchip/gic-v3: Parse and export virtual GIC information

I guess it's fine since Marc Zyngier is maintainer for both KVM and
irqchip, still it's never wrong to get more acks. :)

Thanks,

Paolo

> Hope this works for you guys.
> 
> For a description of the content, see below; otherwise:
> 
> The following changes since commit 06a71a24bae57a07afee9cda6b00495347d8a448:
> 
>   arm64: KVM: unregister notifiers in hyp mode teardown path (2016-04-06 13:47:52 +0200)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git tags/kvm-arm-for-4.7
> 
> for you to fetch changes up to 06485053244480f5f403d8f89b8617bd7d549113:
> 
>   kvm: arm64: Enable hardware updates of the Access Flag for Stage 2 page tables (2016-05-09 22:23:08 +0200)


From msalter at redhat.com  Wed May 11 08:24:12 2016
From: msalter at redhat.com (Mark Salter)
Date: Wed, 11 May 2016 11:24:12 -0400
Subject: [patch V4 02/31] bitops: Include generic parity.h in some
 architectures' bitops.h
In-Reply-To: <1462957641-24241-1-git-send-email-zengzhaoxiu@163.com>
References: <1462955158-28394-1-git-send-email-zengzhaoxiu@163.com>
 <1462957641-24241-1-git-send-email-zengzhaoxiu@163.com>
Message-ID: <1462980252.9978.33.camel@redhat.com>

On Wed, 2016-05-11 at 17:06 +0800, zengzhaoxiu at 163.com wrote:
> From: Zhaoxiu Zeng <zhaoxiu.zeng at gmail.com>
> 
> Simply use the generic version.
> 
> Signed-off-by: Zhaoxiu Zeng <zhaoxiu.zeng at gmail.com>
> Acked-by: Hans-Christian Noren Egtvedt <egtvedt at samfundet.no> [for avr32]
> ---

For c6x:

Acked-by: Mark Salter <msalter at redhat.com>



From peter.griffin at linaro.org  Wed May 11 08:26:20 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 11 May 2016 16:26:20 +0100
Subject: [PATCH] i2c: st: Implement i2c_bus_recovery_info callbacks
In-Reply-To: <20160511150122.GF1716@katana>
References: <1460467759-11737-1-git-send-email-peter.griffin@linaro.org>
 <20160424211044.GD4317@katana> <5722107C.3000600@st.com>
 <20160428145720.GA1541@katana> <572344D8.6060401@st.com>
 <20160429140351.GA1459@griffinp-mac> <20160511150122.GF1716@katana>
Message-ID: <20160511152620.GA22265@griffinp-ThinkPad-X1-Carbon-2nd>

Hi Wolfram,

On Wed, 11 May 2016, Wolfram Sang wrote:

> > Yes I'll send a v2 with your comment added.
> 
> Any news?
>
Sorry, I will re-send it in a few minutes.

Peter. 




From keescook at chromium.org  Wed May 11 08:27:14 2016
From: keescook at chromium.org (Kees Cook)
Date: Wed, 11 May 2016 08:27:14 -0700
Subject: [PATCH] arm64: kernel: Fix incorrect brk randomization
In-Reply-To: <1462959868.2834.17.camel@linaro.org>
References: <20160510175549.GA20496@www.outflux.net>
 <1462959868.2834.17.camel@linaro.org>
Message-ID: <CAGXu5jLy4e1d8oQMAm8JTgCjyCPb_i3QvMw+gT3_H6WeAatO1Q@mail.gmail.com>

On Wed, May 11, 2016 at 2:44 AM, Jon Medhurst (Tixy) <tixy at linaro.org> wrote:
> On Tue, 2016-05-10 at 10:55 -0700, Kees Cook wrote:
>> This fixes two issues with the arm64 brk randomziation. First, the
>> STACK_RND_MASK was being used incorrectly. The original code was:
>>
>>       unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
>>
>> STACK_RND_MASK is 0x7ff (32-bit) or 0x3ffff (64-bit), with 4K pages where
>> PAGE_SHIFT is 12:
>>
>>       #define STACK_RND_MASK  (test_thread_flag(TIF_32BIT) ? \
>>                                               0x7ff >> (PAGE_SHIFT - 12) : \
>>                                               0x3ffff >> (PAGE_SHIFT - 12))
>>
>> This means the resulting offset from base would be 0x7ff0001 or 0x3ffff0001,
>> which is wrong since it creates an unaligned end address. It was likely
>> intended to be:
>>
>>       unsigned long range_end = base + ((STACK_RND_MASK + 1) << PAGE_SHIFT)
>>
>> Which would result in offsets of 0x800000 (32-bit) and 0x40000000 (64-bit).
>>
>> However, even this corrected 32-bit compat offset (0x00800000) is much
>> smaller than native ARM's brk randomization value (0x02000000):
>>
>>       unsigned long arch_randomize_brk(struct mm_struct *mm)
>>       {
>>               unsigned long range_end = mm->brk + 0x02000000;
>>               return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
>>       }
>>
>> So, instead of basing arm64's brk randomization on mistaken STACK_RND_MASK
>> calculations, just use specific corrected values for compat (0x2000000)
>> and native arm64 (0x40000000).
>>
>> Signed-off-by: Kees Cook <keescook at chromium.org>
>
> There seems to be a helper 'is_compat_task()' that does
> 'test_thread_flag(TIF_32BIT)' so could perhaps be used instead, but
> that's too nit-picky. This change makes things more consistent with

Oh, good call. Yeah, none of the other .c code does direct tests for
the TIF_32BIT flag, so I'll use the helper and send a v2. Thanks!

-Kees

> arch/arm and other arches, and stops use of STACK_RND_MASK for things
> that aren't stack related so seems good all round to me.
>
> Reviewed-by: Jon Medhurst <tixy at linaro.org>
>
>> ---
>>  arch/arm64/kernel/process.c | 15 ++++++++-------
>>  1 file changed, 8 insertions(+), 7 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
>> index 80624829db61..0d0969bcd76d 100644
>> --- a/arch/arm64/kernel/process.c
>> +++ b/arch/arm64/kernel/process.c
>> @@ -382,13 +382,14 @@ unsigned long arch_align_stack(unsigned long sp)
>>       return sp & ~0xf;
>>  }
>>
>> -static unsigned long randomize_base(unsigned long base)
>> -{
>> -     unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
>> -     return randomize_range(base, range_end, 0) ? : base;
>> -}
>> -
>>  unsigned long arch_randomize_brk(struct mm_struct *mm)
>>  {
>> -     return randomize_base(mm->brk);
>> +     unsigned long range_end = mm->brk;
>> +
>> +     if (test_thread_flag(TIF_32BIT))
>> +             range_end += 0x02000000;
>> +     else
>> +             range_end += 0x40000000;
>> +
>> +     return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
>>  }
>> --
>> 2.6.3
>>
>>
>
>



-- 
Kees Cook
Chrome OS & Brillo Security


From will.deacon at arm.com  Wed May 11 08:29:38 2016
From: will.deacon at arm.com (Will Deacon)
Date: Wed, 11 May 2016 16:29:38 +0100
Subject: [PATCH] arm64: kernel: Fix incorrect brk randomization
In-Reply-To: <CAGXu5jLy4e1d8oQMAm8JTgCjyCPb_i3QvMw+gT3_H6WeAatO1Q@mail.gmail.com>
References: <20160510175549.GA20496@www.outflux.net>
 <1462959868.2834.17.camel@linaro.org>
 <CAGXu5jLy4e1d8oQMAm8JTgCjyCPb_i3QvMw+gT3_H6WeAatO1Q@mail.gmail.com>
Message-ID: <20160511152938.GA24039@arm.com>

On Wed, May 11, 2016 at 08:27:14AM -0700, Kees Cook wrote:
> On Wed, May 11, 2016 at 2:44 AM, Jon Medhurst (Tixy) <tixy at linaro.org> wrote:
> > On Tue, 2016-05-10 at 10:55 -0700, Kees Cook wrote:
> >> This fixes two issues with the arm64 brk randomziation. First, the
> >> STACK_RND_MASK was being used incorrectly. The original code was:
> >>
> >>       unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
> >>
> >> STACK_RND_MASK is 0x7ff (32-bit) or 0x3ffff (64-bit), with 4K pages where
> >> PAGE_SHIFT is 12:
> >>
> >>       #define STACK_RND_MASK  (test_thread_flag(TIF_32BIT) ? \
> >>                                               0x7ff >> (PAGE_SHIFT - 12) : \
> >>                                               0x3ffff >> (PAGE_SHIFT - 12))
> >>
> >> This means the resulting offset from base would be 0x7ff0001 or 0x3ffff0001,
> >> which is wrong since it creates an unaligned end address. It was likely
> >> intended to be:
> >>
> >>       unsigned long range_end = base + ((STACK_RND_MASK + 1) << PAGE_SHIFT)
> >>
> >> Which would result in offsets of 0x800000 (32-bit) and 0x40000000 (64-bit).
> >>
> >> However, even this corrected 32-bit compat offset (0x00800000) is much
> >> smaller than native ARM's brk randomization value (0x02000000):
> >>
> >>       unsigned long arch_randomize_brk(struct mm_struct *mm)
> >>       {
> >>               unsigned long range_end = mm->brk + 0x02000000;
> >>               return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
> >>       }
> >>
> >> So, instead of basing arm64's brk randomization on mistaken STACK_RND_MASK
> >> calculations, just use specific corrected values for compat (0x2000000)
> >> and native arm64 (0x40000000).
> >>
> >> Signed-off-by: Kees Cook <keescook at chromium.org>
> >
> > There seems to be a helper 'is_compat_task()' that does
> > 'test_thread_flag(TIF_32BIT)' so could perhaps be used instead, but
> > that's too nit-picky. This change makes things more consistent with
> 
> Oh, good call. Yeah, none of the other .c code does direct tests for
> the TIF_32BIT flag, so I'll use the helper and send a v2. Thanks!

I already applied it with that change and Tixy's reviewed-by. Thanks!

Will


From keescook at chromium.org  Wed May 11 08:30:23 2016
From: keescook at chromium.org (Kees Cook)
Date: Wed, 11 May 2016 08:30:23 -0700
Subject: [PATCH] arm64: kernel: Fix incorrect brk randomization
In-Reply-To: <20160511152938.GA24039@arm.com>
References: <20160510175549.GA20496@www.outflux.net>
 <1462959868.2834.17.camel@linaro.org>
 <CAGXu5jLy4e1d8oQMAm8JTgCjyCPb_i3QvMw+gT3_H6WeAatO1Q@mail.gmail.com>
 <20160511152938.GA24039@arm.com>
Message-ID: <CAGXu5jJ1__kKUt0Q9SrAFJaE66a0dGQV5w5Y=-8+aYNW_FEZXQ@mail.gmail.com>

On Wed, May 11, 2016 at 8:29 AM, Will Deacon <will.deacon at arm.com> wrote:
> On Wed, May 11, 2016 at 08:27:14AM -0700, Kees Cook wrote:
>> On Wed, May 11, 2016 at 2:44 AM, Jon Medhurst (Tixy) <tixy at linaro.org> wrote:
>> > On Tue, 2016-05-10 at 10:55 -0700, Kees Cook wrote:
>> >> This fixes two issues with the arm64 brk randomziation. First, the
>> >> STACK_RND_MASK was being used incorrectly. The original code was:
>> >>
>> >>       unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
>> >>
>> >> STACK_RND_MASK is 0x7ff (32-bit) or 0x3ffff (64-bit), with 4K pages where
>> >> PAGE_SHIFT is 12:
>> >>
>> >>       #define STACK_RND_MASK  (test_thread_flag(TIF_32BIT) ? \
>> >>                                               0x7ff >> (PAGE_SHIFT - 12) : \
>> >>                                               0x3ffff >> (PAGE_SHIFT - 12))
>> >>
>> >> This means the resulting offset from base would be 0x7ff0001 or 0x3ffff0001,
>> >> which is wrong since it creates an unaligned end address. It was likely
>> >> intended to be:
>> >>
>> >>       unsigned long range_end = base + ((STACK_RND_MASK + 1) << PAGE_SHIFT)
>> >>
>> >> Which would result in offsets of 0x800000 (32-bit) and 0x40000000 (64-bit).
>> >>
>> >> However, even this corrected 32-bit compat offset (0x00800000) is much
>> >> smaller than native ARM's brk randomization value (0x02000000):
>> >>
>> >>       unsigned long arch_randomize_brk(struct mm_struct *mm)
>> >>       {
>> >>               unsigned long range_end = mm->brk + 0x02000000;
>> >>               return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
>> >>       }
>> >>
>> >> So, instead of basing arm64's brk randomization on mistaken STACK_RND_MASK
>> >> calculations, just use specific corrected values for compat (0x2000000)
>> >> and native arm64 (0x40000000).
>> >>
>> >> Signed-off-by: Kees Cook <keescook at chromium.org>
>> >
>> > There seems to be a helper 'is_compat_task()' that does
>> > 'test_thread_flag(TIF_32BIT)' so could perhaps be used instead, but
>> > that's too nit-picky. This change makes things more consistent with
>>
>> Oh, good call. Yeah, none of the other .c code does direct tests for
>> the TIF_32BIT flag, so I'll use the helper and send a v2. Thanks!
>
> I already applied it with that change and Tixy's reviewed-by. Thanks!

Oh! Perfect, thanks! :)

-Kees

-- 
Kees Cook
Chrome OS & Brillo Security


From james.morse at arm.com  Wed May 11 08:33:06 2016
From: james.morse at arm.com (James Morse)
Date: Wed, 11 May 2016 16:33:06 +0100
Subject: [PATCH v12 00/10] arm64: Add kernel probes (kprobes) support
In-Reply-To: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
Message-ID: <573350B2.4010701@arm.com>

Hi David,

On 27/04/16 19:52, David Long wrote:
> From: "David A. Long" <dave.long at linaro.org>
> 
> This patchset is heavily based on Sandeepa Prabhu's ARM v8 kprobes patches,
> first seen in October 2013. This version attempts to address concerns raised by
> reviewers and also fixes problems discovered during testing.
> 
> This patchset adds support for kernel probes(kprobes), jump probes(jprobes)
> and return probes(kretprobes) support for ARM64.
> 
> The kprobes mechanism makes use of software breakpoint and single stepping
> support available in the ARM v8 kernel.

I applied this series on v4.6-rc7, and built the sample kprobes. They work fine,
unless I throw ftrace into the mix too.

I enabled the function_graph tracer, then tried to load the jprobe example module:
-------------------------%<-------------------------
root at ubuntu:/sys/kernel/debug/tracing# insmod /root/jprobe_example.ko
Planted jprobe at ffffff80080c8f20, handler addr ffffff8000bb3000
root at ubuntu:/sys/kernel/debug/tracing# jprobe: clone_flags = 0x1200011, stack_st
art = 0x0 stack_size = 0x0
Bad mode in Synchronous Abort handler detected, code 0x86000005 -- IABT (current
 EL)
CPU: 5 PID: 1047 Comm: systemd-udevd Not tainted 4.6.0-rc7+ #4064
Hardware name: ARM Juno development board (r1) (DT)
task: ffffffc975948300 ti: ffffffc974e4c000 task.ti: ffffffc974e4c000
PC is at 0x0
LR is at 0x0

pc : [<0000000000000000>] lr : [<0000000000000000>] pstate: 60000145
sp : ffffffc974e4ff00
x29: 0000000001200011 x28: ffffffc974e4c000
x27: ffffff80088d0000 x26: 00000000000000dc
x25: 0000000000000120 x24: 0000000000000015
x23: 0000000060000000 x22: 0000007fa1b40e60
x21: 0000007fa1ce70d0 x20: 0000000000000000
x19: 0000000000000000 x18: 0000000000000a03
x17: 0000007fa1b40d90 x16: ffffff80080c9708
x15: 003b9aca00000000 x14: 0000007fddb7e5c0
x13: 0000007fa1b40e2c x12: 0000000000d00ff0
x11: ffffff8009c4d000 x10: ffffff800920c000
x9 : ffffff8008f5c000 x8 : ffffffc976c06800
x7 : 000000000006daf2 x6 : 0000000000000015
x5 : 0000000000000004 x4 : ffffffc96e8690a0
x3 : 0000001ed7cbab74 x2 : ffffffc96e869000
x1 : 0000000000000000 x0 : 0000000000000000

Internal error: Oops - bad mode: 0 [#1] PREEMPT SMP
Modules linked in: jprobe_example
CPU: 5 PID: 1047 Comm: systemd-udevd Not tainted 4.6.0-rc7+ #4064
Hardware name: ARM Juno development board (r1) (DT)
task: ffffffc975948300 ti: ffffffc974e4c000 task.ti: ffffffc974e4c000
PC is at 0x0
LR is at 0x0

pc : [<0000000000000000>] lr : [<0000000000000000>] pstate: 60000145
sp : ffffffc974e4ff00
x29: 0000000001200011 x28: ffffffc974e4c000
x27: ffffff80088d0000 x26: 00000000000000dc
x25: 0000000000000120 x24: 0000000000000015
x23: 0000000060000000 x22: 0000007fa1b40e60
x21: 0000007fa1ce70d0 x20: 0000000000000000
x19: 0000000000000000 x18: 0000000000000a03
x17: 0000007fa1b40d90 x16: ffffff80080c9708
x15: 003b9aca00000000 x14: 0000007fddb7e5c0
x13: 0000007fa1b40e2c x12: 0000000000d00ff0
x11: ffffff8009c4d000 x10: ffffff800920c000
x9 : ffffff8008f5c000 x8 : ffffffc976c06800
x7 : 000000000006daf2 x6 : 0000000000000015
x5 : 0000000000000004 x4 : ffffffc96e8690a0
x3 : 0000001ed7cbab74 x2 : ffffffc96e869000
x1 : 0000000000000000 x0 : 0000000000000000

Process systemd-udevd (pid: 1047, stack limit = 0xffffffc974e4c020)
Stack: (0xffffffc974e4ff00 to 0xffffffc974e50000)
ff00: 0000000000000417 0000007fa1ce76f0 00000000000000dc 0000000000000417
ff20: 00000000ffffffff 0000007fddb7ecf8 0000000000000005 ffffffffffffffff
ff40: 00000000ff000001 003b9aca00000000 000000555b3868b0 0000007fa1b40d90
ff60: 0000000000000a03 0000007fddb7e5c0 0000000000000000 0000007fddb7e5e0
ff80: 000000555b358000 000000558f56f0e0 0000000000000000 000000558f574f00
ffa0: 000000558f574f00 00000000000004fa 000000558f56f010 0000007fddb7e600
ffc0: 0000007fa1b40e2c 0000007fddb7e5c0 0000007fa1b40e60 0000000060000000
ffe0: 0000000001200011 00000000000000dc 0004000084000200 0800000002000000
Call trace:
[<          (null)>]           (null)
Code: bad PC value
---[ end trace 35d24aad799c2941 ]---
-------------------------%<-------------------------


Thanks,


James





From cedric.madianga at gmail.com  Wed May 11 08:36:09 2016
From: cedric.madianga at gmail.com (M'boumba Cedric Madianga)
Date: Wed, 11 May 2016 17:36:09 +0200
Subject: [PATCH 0/5] Add support for the STM32F4 I2C
Message-ID: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>

This patchset adds support for the I2C controller embedded in STM32F4xx SoC.
It enables I2C transfer in interrupt mode with Standard-mode and Fast-mode bus
speed.

M'boumba Cedric Madianga (5):
  dt-bindings: Document the STM32 I2C bindings
  i2c: Add STM32F4 I2C driver
  ARM: dts: Add I2C1 support for STM32F429 SoC
  ARM: dts: Add I2C1 support for STM32429 eval board
  ARM: configs: Add I2C support for STM32 defconfig

 .../devicetree/bindings/i2c/i2c-stm32.txt          |  33 +
 arch/arm/boot/dts/stm32429i-eval.dts               |   6 +
 arch/arm/boot/dts/stm32f429.dtsi                   |  24 +
 arch/arm/configs/stm32_defconfig                   |   3 +
 drivers/i2c/busses/Kconfig                         |  10 +
 drivers/i2c/busses/Makefile                        |   1 +
 drivers/i2c/busses/i2c-stm32f4.c                   | 872 +++++++++++++++++++++
 7 files changed, 949 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-stm32.txt
 create mode 100644 drivers/i2c/busses/i2c-stm32f4.c

-- 
1.9.1



From cedric.madianga at gmail.com  Wed May 11 08:36:10 2016
From: cedric.madianga at gmail.com (M'boumba Cedric Madianga)
Date: Wed, 11 May 2016 17:36:10 +0200
Subject: [PATCH 1/5] dt-bindings: Document the STM32 I2C bindings
In-Reply-To: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
References: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
Message-ID: <1462980974-22091-2-git-send-email-cedric.madianga@gmail.com>

This patch adds documentation of device tree bindings for the STM32 I2C
controller.

Signed-off-by: M'boumba Cedric Madianga <cedric.madianga at gmail.com>
---
 .../devicetree/bindings/i2c/i2c-stm32.txt          | 33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-stm32.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-stm32.txt b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt
new file mode 100644
index 0000000..73215c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt
@@ -0,0 +1,33 @@
+* I2C controller embedded in STMicroelectronics STM32 I2C platform
+
+Required properties :
+- compatible : Must be "st,i2c-stm32f4"
+- reg : Offset and length of the register set for the device
+- interrupts : Must contain the interrupt id for I2C event and then the
+  interrupt id for I2C error.
+- resets: Must contain the phandle to the reset controller.
+- clocks: Must contain the input clock of the I2C instance.
+- A pinctrl state named "default" must be defined to set pins in mode of
+  operation for I2C transfer
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties :
+- clock-frequency : Desired I2C bus clock frequency in Hz. If not specified,
+  the default 100 kHz frequency will be used. As only Normal and Fast modes
+  are supported, possible values are 100000 and 400000.
+
+Example :
+
+	i2c at 40005400 {
+		compatible = "st,i2c-stm32f4";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x40005400 0x400>;
+		interrupts = <31>,
+			     <32>;
+		resets = <&rcc 277>;
+		clocks = <&rcc 0 149>;
+		pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>;
+		pinctrl-names = "default";
+	};
-- 
1.9.1



From cedric.madianga at gmail.com  Wed May 11 08:36:12 2016
From: cedric.madianga at gmail.com (M'boumba Cedric Madianga)
Date: Wed, 11 May 2016 17:36:12 +0200
Subject: [PATCH 3/5] ARM: dts: Add I2C1 support for STM32F429 SoC
In-Reply-To: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
References: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
Message-ID: <1462980974-22091-4-git-send-email-cedric.madianga@gmail.com>

Signed-off-by: Patrice Chotard <patrice.chotard at st.com>
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga at gmail.com>
---
 arch/arm/boot/dts/stm32f429.dtsi | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index 434d4b9..cbfeb4e 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -323,6 +323,18 @@
 					slew-rate = <2>;
 				};
 			};
+
+			i2c1_sda_pin: i2c1_sda at 0 {
+				pins {
+					pinmux = <STM32F429_PB9_FUNC_I2C1_SDA>;
+					drive-open-drain;
+				};
+			};
+			i2c1_scl_pin: i2c1_scl at 0 {
+				pins {
+					pinmux = <STM32F429_PB6_FUNC_I2C1_SCL>;
+				};
+			};
 		};
 
 		rcc: rcc at 40023800 {
@@ -395,6 +407,18 @@
 			interrupts = <80>;
 			clocks = <&rcc 0 38>;
 		};
+
+		i2c1: i2c at 40005400 {
+			compatible = "st,i2c-stm32f4";
+			reg = <0x40005400 0x400>;
+			interrupts = <31>,
+				     <32>;
+			resets = <&rcc 277>;
+			clocks = <&rcc 0 149>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
 	};
 };
 
-- 
1.9.1



From cedric.madianga at gmail.com  Wed May 11 08:36:13 2016
From: cedric.madianga at gmail.com (M'boumba Cedric Madianga)
Date: Wed, 11 May 2016 17:36:13 +0200
Subject: [PATCH 4/5] ARM: dts: Add I2C1 support for STM32429 eval board
In-Reply-To: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
References: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
Message-ID: <1462980974-22091-5-git-send-email-cedric.madianga@gmail.com>

Signed-off-by: M'boumba Cedric Madianga <cedric.madianga at gmail.com>
---
 arch/arm/boot/dts/stm32429i-eval.dts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts
index 6bfc595..0bf427a 100644
--- a/arch/arm/boot/dts/stm32429i-eval.dts
+++ b/arch/arm/boot/dts/stm32429i-eval.dts
@@ -123,3 +123,9 @@
 	pinctrl-names = "default";
 	status = "okay";
 };
+
+&i2c1 {
+	pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>;
+	pinctrl-names = "default";
+	status = "okay";
+};
-- 
1.9.1



From cedric.madianga at gmail.com  Wed May 11 08:36:11 2016
From: cedric.madianga at gmail.com (M'boumba Cedric Madianga)
Date: Wed, 11 May 2016 17:36:11 +0200
Subject: [PATCH 2/5] i2c: Add STM32F4 I2C driver
In-Reply-To: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
References: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
Message-ID: <1462980974-22091-3-git-send-email-cedric.madianga@gmail.com>

This patch adds support for the STM32F4 I2C controller.

Signed-off-by: M'boumba Cedric Madianga <cedric.madianga at gmail.com>
---
 drivers/i2c/busses/Kconfig       |  10 +
 drivers/i2c/busses/Makefile      |   1 +
 drivers/i2c/busses/i2c-stm32f4.c | 872 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 883 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-stm32f4.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 2dd40dd..947894a 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -873,6 +873,16 @@ config I2C_ST
 	  This driver can also be built as module. If so, the module
 	  will be called i2c-st.
 
+config I2C_STM32F4
+	tristate "STMicroelectronics STM32F4 I2C support"
+	depends on ARCH_STM32
+	help
+	  Enable this option to add support for STM32 I2C controller embedded
+	  in STM32F4 SoCs.
+
+	  This driver can also be built as module. If so, the module
+	  will be called i2c-stm32f4.
+
 config I2C_STU300
 	tristate "ST Microelectronics DDC I2C interface"
 	depends on MACH_U300
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 37f2819..2ac0eb2 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -84,6 +84,7 @@ obj-$(CONFIG_I2C_SH_MOBILE)	+= i2c-sh_mobile.o
 obj-$(CONFIG_I2C_SIMTEC)	+= i2c-simtec.o
 obj-$(CONFIG_I2C_SIRF)		+= i2c-sirf.o
 obj-$(CONFIG_I2C_ST)		+= i2c-st.o
+obj-$(CONFIG_I2C_STM32F4)	+= i2c-stm32f4.o
 obj-$(CONFIG_I2C_STU300)	+= i2c-stu300.o
 obj-$(CONFIG_I2C_SUN6I_P2WI)	+= i2c-sun6i-p2wi.o
 obj-$(CONFIG_I2C_TEGRA)		+= i2c-tegra.o
diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c
new file mode 100644
index 0000000..4692213
--- /dev/null
+++ b/drivers/i2c/busses/i2c-stm32f4.c
@@ -0,0 +1,872 @@
+/*
+ * Driver for STMicroelectronics STM32 I2C controller
+ *
+ * Copyright (C) M'boumba Cedric Madianga 2015
+ * Author: M'boumba Cedric Madianga <cedric.madianga at gmail.com>
+ *
+ * This driver is based on st-i2c.c
+ *
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+/* STM32F4 I2C offset registers */
+#define STM32F4_I2C_CR1			0x00
+#define STM32F4_I2C_CR2			0x04
+#define STM32F4_I2C_DR			0x10
+#define STM32F4_I2C_SR1			0x14
+#define STM32F4_I2C_SR2			0x18
+#define STM32F4_I2C_CCR			0x1C
+#define STM32F4_I2C_TRISE		0x20
+#define STM32F4_I2C_FLTR		0x24
+
+/* STM32F4 I2C control 1*/
+#define STM32F4_I2C_CR1_SWRST		BIT(15)
+#define STM32F4_I2C_CR1_POS		BIT(11)
+#define STM32F4_I2C_CR1_ACK		BIT(10)
+#define STM32F4_I2C_CR1_STOP		BIT(9)
+#define STM32F4_I2C_CR1_START		BIT(8)
+#define STM32F4_I2C_CR1_PE		BIT(0)
+
+/* STM32F4 I2C control 2 */
+#define STM32F4_I2C_CR2_FREQ_MASK	GENMASK(5, 0)
+#define STM32F4_I2C_CR2_FREQ(n)		((n & STM32F4_I2C_CR2_FREQ_MASK))
+#define STM32F4_I2C_CR2_ITBUFEN		BIT(10)
+#define STM32F4_I2C_CR2_ITEVTEN		BIT(9)
+#define STM32F4_I2C_CR2_ITERREN		BIT(8)
+#define STM32F4_I2C_CR2_IRQ_MASK	(STM32F4_I2C_CR2_ITBUFEN \
+					| STM32F4_I2C_CR2_ITEVTEN \
+					| STM32F4_I2C_CR2_ITERREN)
+
+/* STM32F4 I2C Status 1 */
+#define STM32F4_I2C_SR1_AF		BIT(10)
+#define STM32F4_I2C_SR1_ARLO		BIT(9)
+#define STM32F4_I2C_SR1_BERR		BIT(8)
+#define STM32F4_I2C_SR1_TXE		BIT(7)
+#define STM32F4_I2C_SR1_RXNE		BIT(6)
+#define STM32F4_I2C_SR1_BTF		BIT(2)
+#define STM32F4_I2C_SR1_ADDR		BIT(1)
+#define STM32F4_I2C_SR1_SB		BIT(0)
+#define STM32F4_I2C_SR1_ITEVTEN_MASK	(STM32F4_I2C_SR1_BTF \
+					| STM32F4_I2C_SR1_ADDR \
+					| STM32F4_I2C_SR1_SB)
+#define STM32F4_I2C_SR1_ITBUFEN_MASK	(STM32F4_I2C_SR1_TXE \
+					| STM32F4_I2C_SR1_RXNE)
+#define STM32F4_I2C_SR1_ITERREN_MASK	(STM32F4_I2C_SR1_AF \
+					| STM32F4_I2C_SR1_ARLO \
+					| STM32F4_I2C_SR1_BERR)
+
+/* STM32F4 I2C Status 2 */
+#define STM32F4_I2C_SR2_BUSY		BIT(1)
+
+/* STM32F4 I2C Control Clock */
+#define STM32F4_I2C_CCR_CCR_MASK	GENMASK(11, 0)
+#define STM32F4_I2C_CCR_CCR(n)		((n & STM32F4_I2C_CCR_CCR_MASK))
+#define STM32F4_I2C_CCR_FS		BIT(15)
+#define STM32F4_I2C_CCR_DUTY		BIT(14)
+
+/* STM32F4 I2C Trise */
+#define STM32F4_I2C_TRISE_TRISE_MASK	GENMASK(5, 0)
+#define STM32F4_I2C_TRISE_TRISE(n)	((n & STM32F4_I2C_TRISE_TRISE_MASK))
+
+/* STM32F4 I2C Filter */
+#define STM32F4_I2C_FLTR_DNF_MASK	GENMASK(3, 0)
+#define STM32F4_I2C_FLTR_DNF(n)		((n & STM32F4_I2C_FLTR_DNF_MASK))
+#define STM32F4_I2C_FLTR_ANOFF		BIT(4)
+
+#define STM32F4_I2C_MAX_FREQ		0x2a
+#define STM32F4_I2C_MIN_CCR		0x4
+
+enum stm32f4_i2c_speed {
+	STM32F4_I2C_SPEED_STANDARD, /* 100 kHz */
+	STM32F4_I2C_SPEED_FAST, /* 400 kHz */
+	STM32F4_I2C_SPEED_END,
+};
+
+/**
+ * struct stm32f4_i2c_timings - per-Mode tuning parameters
+ * @rate: I2C bus rate
+ * @duty: Fast mode duty cycle
+ */
+struct stm32f4_i2c_timings {
+	u32 rate;
+	u32 duty;
+};
+
+/**
+ * struct stm32f4_i2c_client - client specific data
+ * @addr: 8-bit slave addr, including r/w bit
+ * @count: number of bytes to be transferred
+ * @buf: data buffer
+ * @result: result of the transfer
+ * @stop: last I2C msg to be sent, i.e. STOP to be generated
+ */
+struct stm32f4_i2c_client {
+	u8	addr;
+	u32	count;
+	u8	*buf;
+	int	result;
+	bool	stop;
+};
+
+/**
+ * struct stm32f4_i2c_dev - private data of the controller
+ * @adap: I2C adapter for this controller
+ * @dev: device for this controller
+ * @base: virtual memory area
+ * @complete: completion of I2C message
+ * @irq_event: interrupt event line for the controller
+ * @irq_error: interrupt error line for the controller
+ * @clk: hw i2c clock
+ * speed: I2C clock frequency of the controller. Standard or Fast only supported
+ * @client: I2C transfer information
+ * @busy: I2C transfer on-going
+ * @rst: I2C reset line
+ */
+struct stm32f4_i2c_dev {
+	struct i2c_adapter		adap;
+	struct device			*dev;
+	void __iomem			*base;
+	struct completion		complete;
+	int				irq_event;
+	int				irq_error;
+	struct clk			*clk;
+	int				speed;
+	struct stm32f4_i2c_client	client;
+	bool				busy;
+	struct reset_control		*rst;
+};
+
+static struct stm32f4_i2c_timings i2c_timings[] = {
+	[STM32F4_I2C_SPEED_STANDARD] = {
+		.rate			= 100000,
+		.duty			= 0,
+	},
+	[STM32F4_I2C_SPEED_FAST] = {
+		.rate			= 400000,
+		.duty			= 0,
+	},
+};
+
+static inline void stm32f4_i2c_set_bits(void __iomem *reg, u32 mask)
+{
+	writel_relaxed(readl_relaxed(reg) | mask, reg);
+}
+
+static inline void stm32f4_i2c_clr_bits(void __iomem *reg, u32 mask)
+{
+	writel_relaxed(readl_relaxed(reg) & ~mask, reg);
+}
+
+static void stm32f4_i2c_soft_reset(struct stm32f4_i2c_dev *i2c_dev)
+{
+	void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
+
+	stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_SWRST);
+	stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_SWRST);
+}
+
+static void stm32f4_i2c_set_periph_clk_freq(struct stm32f4_i2c_dev *i2c_dev)
+{
+	u32 clk_rate, cr2, freq;
+
+	cr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+	cr2 &= ~STM32F4_I2C_CR2_FREQ_MASK;
+
+	clk_rate = clk_get_rate(i2c_dev->clk);
+
+	freq = clk_rate / 1000000;
+	if (freq > STM32F4_I2C_MAX_FREQ)
+		freq = STM32F4_I2C_MAX_FREQ;
+
+	cr2 |= STM32F4_I2C_CR2_FREQ(freq);
+	writel_relaxed(cr2, i2c_dev->base + STM32F4_I2C_CR2);
+}
+
+static void stm32f4_i2c_set_rise_time(struct stm32f4_i2c_dev *i2c_dev)
+{
+	u32 trise, freq, cr2;
+
+	cr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+	freq = cr2 & STM32F4_I2C_CR2_FREQ_MASK;
+
+	trise = readl_relaxed(i2c_dev->base + STM32F4_I2C_TRISE);
+	trise &= ~STM32F4_I2C_TRISE_TRISE_MASK;
+
+	if (i2c_dev->speed == STM32F4_I2C_SPEED_STANDARD)
+		trise |= STM32F4_I2C_TRISE_TRISE((freq + 1));
+	else
+		trise |= STM32F4_I2C_TRISE_TRISE((((freq * 300) / 1000) + 1));
+
+	writel_relaxed(trise, i2c_dev->base + STM32F4_I2C_TRISE);
+}
+
+static void stm32f4_i2c_set_speed_mode(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_timings *t = &i2c_timings[i2c_dev->speed];
+	u32 ccr, val, clk_rate;
+
+	ccr = readl_relaxed(i2c_dev->base + STM32F4_I2C_CCR);
+	ccr &= ~(STM32F4_I2C_CCR_FS | STM32F4_I2C_CCR_DUTY |
+		 STM32F4_I2C_CCR_CCR_MASK);
+
+	clk_rate = clk_get_rate(i2c_dev->clk);
+
+	switch (i2c_dev->speed) {
+	case STM32F4_I2C_SPEED_STANDARD:
+		val = clk_rate / t->rate * 2;
+		if (val < STM32F4_I2C_MIN_CCR)
+			ccr |= STM32F4_I2C_CCR_CCR(STM32F4_I2C_MIN_CCR);
+		else
+			ccr |= STM32F4_I2C_CCR_CCR(val);
+		break;
+	case STM32F4_I2C_SPEED_FAST:
+		ccr |= STM32F4_I2C_CCR_FS;
+		if (t->duty) {
+			ccr |= STM32F4_I2C_CCR_DUTY;
+			ccr |= STM32F4_I2C_CCR_CCR(clk_rate / t->rate * 25);
+		} else {
+			ccr |= STM32F4_I2C_CCR_CCR(clk_rate / t->rate * 3);
+		}
+		break;
+	default:
+		dev_err(i2c_dev->dev, "I2C speed mode not supported\n");
+	}
+
+	writel_relaxed(ccr, i2c_dev->base + STM32F4_I2C_CCR);
+}
+
+static void stm32f4_i2c_set_filter(struct stm32f4_i2c_dev *i2c_dev)
+{
+	u32 filter;
+
+	/* Enable analog noise filter and disable digital noise filter */
+	filter = readl_relaxed(i2c_dev->base + STM32F4_I2C_FLTR);
+	filter &= ~(STM32F4_I2C_FLTR_ANOFF | STM32F4_I2C_FLTR_DNF_MASK);
+	writel_relaxed(filter, i2c_dev->base + STM32F4_I2C_FLTR);
+}
+
+/**
+ * stm32f4_i2c_hw_config() - Prepare I2C block
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_hw_config(struct stm32f4_i2c_dev *i2c_dev)
+{
+	void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
+
+	/* Disable I2C */
+	stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_PE);
+
+	stm32f4_i2c_set_periph_clk_freq(i2c_dev);
+
+	stm32f4_i2c_set_rise_time(i2c_dev);
+
+	stm32f4_i2c_set_speed_mode(i2c_dev);
+
+	stm32f4_i2c_set_filter(i2c_dev);
+
+	/* Enable I2C */
+	stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_PE);
+}
+
+static int stm32f4_i2c_wait_free_bus(struct stm32f4_i2c_dev *i2c_dev)
+{
+	u32 status;
+	int ret;
+
+	ret = readl_relaxed_poll_timeout(i2c_dev->base + STM32F4_I2C_SR2,
+					 status,
+					 !(status & STM32F4_I2C_SR2_BUSY),
+					 10, 1000);
+	if (ret) {
+		dev_err(i2c_dev->dev, "bus not free\n");
+		ret = -EBUSY;
+	}
+
+	return ret;
+}
+
+/**
+ * stm32f4_i2c_write_ byte() - Write a byte in the data register
+ * @i2c_dev: Controller's private data
+ * @byte: Data to write in the register
+ */
+static void stm32f4_i2c_write_byte(struct stm32f4_i2c_dev *i2c_dev, u8 byte)
+{
+	writel_relaxed(byte, i2c_dev->base + STM32F4_I2C_DR);
+}
+
+/**
+ * stm32f4_i2c_write_msg() - Fill the data register in write mode
+ * @i2c_dev: Controller's private data
+ *
+ * This function fills the data register with I2C transfer buffer
+ */
+static void stm32f4_i2c_write_msg(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_client *c = &i2c_dev->client;
+
+	stm32f4_i2c_write_byte(i2c_dev, *c->buf++);
+	c->count--;
+}
+
+static void stm32f4_i2c_read_msg(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_client *c = &i2c_dev->client;
+	u32 rbuf;
+
+	rbuf = readl_relaxed(i2c_dev->base + STM32F4_I2C_DR);
+	*c->buf++ = (u8)rbuf & 0xff;
+	c->count--;
+}
+
+static void stm32f4_i2c_terminate_xfer(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_client *c = &i2c_dev->client;
+	void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+	/* Disable all interrupts */
+	stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_IRQ_MASK);
+
+	/* Set STOP or REPSTART */
+	reg = i2c_dev->base + STM32F4_I2C_CR1;
+	if (c->stop)
+		stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+	else
+		stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+
+	complete(&i2c_dev->complete);
+}
+
+/**
+ * stm32f4_i2c_handle_write() - Handle FIFO empty interrupt in case of write
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_write(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_client *c = &i2c_dev->client;
+	void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+	if (c->count) {
+		stm32f4_i2c_write_msg(i2c_dev);
+		if (!c->count) {
+			/* Disable BUF interrupt */
+			stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
+		}
+	} else {
+		stm32f4_i2c_terminate_xfer(i2c_dev);
+	}
+}
+
+/**
+ * stm32f4_i2c_handle_tx_btf() - Handle byte transfer finished interrupt
+ * in case of write
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_tx_btf(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_client *c = &i2c_dev->client;
+
+	if (c->count)
+		stm32f4_i2c_write_msg(i2c_dev);
+	else
+		stm32f4_i2c_terminate_xfer(i2c_dev);
+}
+
+/**
+ * stm32f4_i2c_handle_read() - Handle FIFO enmpty interrupt in case of read
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_read(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_client *c = &i2c_dev->client;
+	void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+	switch (c->count) {
+	case 1:
+		stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_IRQ_MASK);
+		stm32f4_i2c_read_msg(i2c_dev);
+		complete(&i2c_dev->complete);
+		break;
+	case 2:
+	case 3:
+		stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
+		break;
+	default:
+		stm32f4_i2c_read_msg(i2c_dev);
+	}
+}
+
+/**
+ * stm32f4_i2c_handle_rx_btf() - Handle byte transfer finished interrupt
+ * in case of read
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_rx_btf(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_client *c = &i2c_dev->client;
+	void __iomem *reg;
+	u32 mask;
+	int i;
+
+	switch (c->count) {
+	case 2:
+		reg = i2c_dev->base + STM32F4_I2C_CR1;
+		/* Generate STOP or REPSTART */
+		if (c->stop)
+			stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+		else
+			stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+
+		/* Read two last data bytes */
+		for (i = 2; i > 0; i--)
+			stm32f4_i2c_read_msg(i2c_dev);
+
+		/* Disable EVT and ERR interrupt */
+		reg = i2c_dev->base + STM32F4_I2C_CR2;
+		mask = STM32F4_I2C_CR2_ITEVTEN | STM32F4_I2C_CR2_ITERREN;
+		stm32f4_i2c_clr_bits(reg, mask);
+
+		complete(&i2c_dev->complete);
+		break;
+	case 3:
+		/* Enable ACK and read data */
+		reg = i2c_dev->base + STM32F4_I2C_CR1;
+		stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
+		stm32f4_i2c_read_msg(i2c_dev);
+		break;
+	default:
+		stm32f4_i2c_read_msg(i2c_dev);
+	}
+}
+
+/**
+ * stm32f4_i2c_handle_rx_addr() - Handle address matched interrupt in case of
+ * master receiver
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_rx_addr(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_client *c = &i2c_dev->client;
+	void __iomem *reg;
+	u32 sr2;
+
+	switch (c->count) {
+	case 0:
+		stm32f4_i2c_terminate_xfer(i2c_dev);
+		/* Clear ADDR flag */
+		sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+		break;
+	case 1:
+		/*
+		 * Single byte reception:
+		 * Enable NACK, clear ADDR flag and generate STOP or RepSTART
+		 */
+		reg = i2c_dev->base + STM32F4_I2C_CR1;
+		stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
+		sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+		if (c->stop)
+			stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+		else
+			stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+		break;
+	case 2:
+		/*
+		 * 2-byte reception:
+		 * Enable NACK and PEC Position Ack and clear ADDR flag
+		 */
+		reg = i2c_dev->base + STM32F4_I2C_CR1;
+		stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
+		stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_POS);
+		sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+		break;
+
+	default:
+		/* N-byte reception: Enable ACK and clear ADDR flag */
+		reg = i2c_dev->base + STM32F4_I2C_CR1;
+		stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_ACK);
+		sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+		break;
+	}
+}
+
+/**
+ * stm32f4_i2c_isr_event() - Interrupt routine for I2C bus event
+ * @irq: interrupt number
+ * @data: Controller's private data
+ */
+static irqreturn_t stm32f4_i2c_isr_event(int irq, void *data)
+{
+	struct stm32f4_i2c_dev *i2c_dev = data;
+	struct stm32f4_i2c_client *c = &i2c_dev->client;
+	void __iomem *reg;
+	u32 real_status, possible_status, ien, sr2;
+	int flag;
+
+	ien = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+	ien &= STM32F4_I2C_CR2_IRQ_MASK;
+
+	/* Check possible status combinations */
+	if (ien & STM32F4_I2C_CR2_ITEVTEN) {
+		possible_status = STM32F4_I2C_SR1_ITEVTEN_MASK;
+		if (ien & STM32F4_I2C_CR2_ITBUFEN)
+			possible_status |= STM32F4_I2C_SR1_ITBUFEN_MASK;
+	}
+
+	real_status = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR1);
+
+	if (!(real_status & possible_status)) {
+		dev_dbg(i2c_dev->dev,
+			"spurious evt it (status=0x%08x, ien=0x%08x)\n",
+			real_status, ien);
+		return IRQ_NONE;
+	}
+
+	/* Use __fls() to check error bits first */
+	flag = __fls(real_status & possible_status);
+
+	switch (1 << flag) {
+	case STM32F4_I2C_SR1_SB:
+		stm32f4_i2c_write_byte(i2c_dev, c->addr);
+		break;
+
+	case STM32F4_I2C_SR1_ADDR:
+		if (c->addr & I2C_M_RD)
+			stm32f4_i2c_handle_rx_addr(i2c_dev);
+		else
+			sr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+
+		/* Enable ITBUF interrupts */
+		reg = i2c_dev->base + STM32F4_I2C_CR2;
+		stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
+		break;
+
+	case STM32F4_I2C_SR1_BTF:
+		if (c->addr & I2C_M_RD)
+			stm32f4_i2c_handle_rx_btf(i2c_dev);
+		else
+			stm32f4_i2c_handle_tx_btf(i2c_dev);
+		break;
+
+	case STM32F4_I2C_SR1_TXE:
+		stm32f4_i2c_handle_write(i2c_dev);
+		break;
+
+	case STM32F4_I2C_SR1_RXNE:
+		stm32f4_i2c_handle_read(i2c_dev);
+		break;
+
+	default:
+		dev_err(i2c_dev->dev,
+			"evt it unhandled: status=0x%08x)\n", real_status);
+		return IRQ_NONE;
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * stm32f4_i2c_isr_error() - Interrupt routine for I2C bus error
+ * @irq: interrupt number
+ * @data: Controller's private data
+ */
+static irqreturn_t stm32f4_i2c_isr_error(int irq, void *data)
+{
+	struct stm32f4_i2c_dev *i2c_dev = data;
+	struct stm32f4_i2c_client *c = &i2c_dev->client;
+	void __iomem *reg;
+	u32 real_status, possible_status, ien;
+	int flag;
+
+	ien = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+	ien &= STM32F4_I2C_CR2_IRQ_MASK;
+
+	/* Check possible status combinations */
+	if (ien & STM32F4_I2C_CR2_ITERREN)
+		possible_status = STM32F4_I2C_SR1_ITERREN_MASK;
+
+	real_status = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR1);
+
+	if (!(real_status & possible_status)) {
+		dev_dbg(i2c_dev->dev,
+			"spurious err it (status=0x%08x, ien=0x%08x)\n",
+			real_status, ien);
+		return IRQ_NONE;
+	}
+
+	/* Use __fls() to check error bits first */
+	flag = __fls(real_status & possible_status);
+
+	switch (1 << flag) {
+	case STM32F4_I2C_SR1_BERR:
+		reg = i2c_dev->base + STM32F4_I2C_SR1;
+		stm32f4_i2c_clr_bits(reg, STM32F4_I2C_SR1_BERR);
+		c->result = -EIO;
+		break;
+
+	case STM32F4_I2C_SR1_ARLO:
+		reg = i2c_dev->base + STM32F4_I2C_SR1;
+		stm32f4_i2c_clr_bits(reg, STM32F4_I2C_SR1_ARLO);
+		c->result = -EAGAIN;
+		break;
+
+	case STM32F4_I2C_SR1_AF:
+		reg = i2c_dev->base + STM32F4_I2C_CR1;
+		stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+		c->result = -EIO;
+		break;
+
+	default:
+		dev_err(i2c_dev->dev,
+			"err it unhandled: status=0x%08x)\n", real_status);
+		return IRQ_NONE;
+	}
+
+	/* Reset I2C */
+	stm32f4_i2c_soft_reset(i2c_dev);
+
+	/* Disable interrupts */
+	reg = i2c_dev->base + STM32F4_I2C_CR2;
+	stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_IRQ_MASK);
+
+	complete(&i2c_dev->complete);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * stm32f4_i2c_xfer_msg() - Transfer a single I2C message
+ * @i2c_dev: Controller's private data
+ * @msg: I2C message to transfer
+ * @is_first: first message of the sequence
+ * @is_last: last message of the sequence
+ */
+static int stm32f4_i2c_xfer_msg(struct stm32f4_i2c_dev *i2c_dev,
+				struct i2c_msg *msg, bool is_first,
+				bool is_last)
+{
+	struct stm32f4_i2c_client *c = &i2c_dev->client;
+	void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
+	unsigned long timeout;
+	u32 mask;
+	int ret;
+
+	c->addr = (u8)(msg->addr << 1);
+	c->addr	|= (msg->flags & I2C_M_RD);
+	c->buf = msg->buf;
+	c->count = msg->len;
+	c->result = 0;
+	c->stop	= is_last;
+
+	reinit_completion(&i2c_dev->complete);
+
+	/* Enable ITEVT and ITERR interrupts */
+	mask = STM32F4_I2C_CR2_ITEVTEN | STM32F4_I2C_CR2_ITERREN;
+	stm32f4_i2c_set_bits(i2c_dev->base + STM32F4_I2C_CR2, mask);
+
+	if (is_first) {
+		ret = stm32f4_i2c_wait_free_bus(i2c_dev);
+		if (ret)
+			return ret;
+
+		/* START generation */
+		stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+	}
+
+	timeout = wait_for_completion_timeout(&i2c_dev->complete,
+					      i2c_dev->adap.timeout);
+	ret = c->result;
+
+	/* Disable PEC position Ack */
+	stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_POS);
+
+	if (!timeout) {
+		dev_err(i2c_dev->dev, "Access to slave 0x%x timed out\n",
+			c->addr >> 1);
+		ret = -ETIMEDOUT;
+	}
+
+	return ret;
+}
+
+/**
+ * stm32f4_i2c_xfer() - Transfer combined I2C message
+ * @i2c_adap: Adapter pointer to the controller
+ * @msgs: Pointer to data to be written.
+ * @num: Number of messages to be executed
+ */
+static int stm32f4_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
+			    int num)
+{
+	struct stm32f4_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
+	int ret, i;
+
+	i2c_dev->busy = true;
+
+	ret = clk_prepare_enable(i2c_dev->clk);
+	if (ret) {
+		dev_err(i2c_dev->dev, "Failed to prepare_enable clock\n");
+		return ret;
+	}
+
+	stm32f4_i2c_hw_config(i2c_dev);
+
+	for (i = 0; i < num && !ret; i++)
+		ret = stm32f4_i2c_xfer_msg(i2c_dev, &msgs[i], i == 0,
+					   i == num - 1);
+
+	clk_disable_unprepare(i2c_dev->clk);
+
+	i2c_dev->busy = false;
+
+	return (ret < 0) ? ret : i;
+}
+
+static u32 stm32f4_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm stm32f4_i2c_algo = {
+	.master_xfer = stm32f4_i2c_xfer,
+	.functionality = stm32f4_i2c_func,
+};
+
+static int stm32f4_i2c_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct stm32f4_i2c_dev *i2c_dev;
+	struct resource *res;
+	u32 clk_rate;
+	struct i2c_adapter *adap;
+	int ret;
+
+	i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
+	if (!i2c_dev)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(i2c_dev->base))
+		return PTR_ERR(i2c_dev->base);
+
+	i2c_dev->irq_event = irq_of_parse_and_map(np, 0);
+	if (!i2c_dev->irq_event) {
+		dev_err(&pdev->dev, "IRQ missing or invalid\n");
+		return -EINVAL;
+	}
+
+	i2c_dev->irq_error = irq_of_parse_and_map(np, 1);
+	if (!i2c_dev->irq_error) {
+		dev_err(&pdev->dev, "IRQ missing or invalid\n");
+		return -EINVAL;
+	}
+
+	i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(i2c_dev->clk)) {
+		dev_err(&pdev->dev, "Error: Missing controller clock\n");
+		return PTR_ERR(i2c_dev->clk);
+	}
+
+	i2c_dev->rst = devm_reset_control_get(&pdev->dev, NULL);
+	if (IS_ERR(i2c_dev->rst)) {
+		dev_err(&pdev->dev, "Error: Missing controller reset\n");
+		return PTR_ERR(i2c_dev->rst);
+	}
+
+	reset_control_assert(i2c_dev->rst);
+	udelay(2);
+	reset_control_deassert(i2c_dev->rst);
+
+	i2c_dev->speed = STM32F4_I2C_SPEED_STANDARD;
+	ret = of_property_read_u32(np, "clock-frequency", &clk_rate);
+	if ((!ret) && (clk_rate == 400000))
+		i2c_dev->speed = STM32F4_I2C_SPEED_FAST;
+
+	i2c_dev->dev = &pdev->dev;
+
+	ret = devm_request_threaded_irq(&pdev->dev, i2c_dev->irq_event,
+					NULL, stm32f4_i2c_isr_event,
+					IRQF_ONESHOT, pdev->name, i2c_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq %i\n",
+			i2c_dev->irq_error);
+		return ret;
+	}
+
+	ret = devm_request_threaded_irq(&pdev->dev, i2c_dev->irq_error,
+					NULL, stm32f4_i2c_isr_error,
+					IRQF_ONESHOT, pdev->name, i2c_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq %i\n",
+			i2c_dev->irq_error);
+		return ret;
+	}
+
+	adap = &i2c_dev->adap;
+	i2c_set_adapdata(adap, i2c_dev);
+	snprintf(adap->name, sizeof(adap->name), "STM32 I2C(%pa)", &res->start);
+	adap->owner = THIS_MODULE;
+	adap->timeout = 2 * HZ;
+	adap->retries = 0;
+	adap->algo = &stm32f4_i2c_algo;
+	adap->dev.parent = &pdev->dev;
+	adap->dev.of_node = pdev->dev.of_node;
+
+	init_completion(&i2c_dev->complete);
+
+	ret = i2c_add_adapter(adap);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add adapter\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, i2c_dev);
+
+	dev_info(i2c_dev->dev, "STM32F4 I2C driver initialized\n");
+
+	return 0;
+}
+
+static int stm32f4_i2c_remove(struct platform_device *pdev)
+{
+	struct stm32f4_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(&i2c_dev->adap);
+
+	return 0;
+}
+
+static const struct of_device_id stm32f4_i2c_match[] = {
+	{ .compatible = "st,i2c-stm32f4", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, stm32f4_i2c_match);
+
+static struct platform_driver stm32f4_i2c_driver = {
+	.driver = {
+		.name = "i2c-stm32f4",
+		.of_match_table = stm32f4_i2c_match,
+	},
+	.probe = stm32f4_i2c_probe,
+	.remove = stm32f4_i2c_remove,
+};
+
+module_platform_driver(stm32f4_i2c_driver);
+
+MODULE_AUTHOR("M'boumba Cedric Madianga <cedric.madianga at gmail.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32F4 I2C driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1



From cedric.madianga at gmail.com  Wed May 11 08:36:14 2016
From: cedric.madianga at gmail.com (M'boumba Cedric Madianga)
Date: Wed, 11 May 2016 17:36:14 +0200
Subject: [PATCH 5/5] ARM: configs: Add I2C support for STM32 defconfig
In-Reply-To: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
References: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
Message-ID: <1462980974-22091-6-git-send-email-cedric.madianga@gmail.com>

Signed-off-by: M'boumba Cedric Madianga <cedric.madianga at gmail.com>
---
 arch/arm/configs/stm32_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/stm32_defconfig b/arch/arm/configs/stm32_defconfig
index 709e606..411eb0a 100644
--- a/arch/arm/configs/stm32_defconfig
+++ b/arch/arm/configs/stm32_defconfig
@@ -49,6 +49,9 @@ CONFIG_SERIAL_NONSTANDARD=y
 CONFIG_SERIAL_STM32=y
 CONFIG_SERIAL_STM32_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_STM32F4=y
 # CONFIG_HWMON is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_NEW_LEDS=y
-- 
1.9.1



From marc.zyngier at arm.com  Wed May 11 08:37:53 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 11 May 2016 16:37:53 +0100
Subject: [PULL 00/29] KVM/ARM Changes for v4.7
In-Reply-To: <57334E72.9010109@redhat.com>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
 <57334E72.9010109@redhat.com>
Message-ID: <573351D1.4060303@arm.com>

On 11/05/16 16:23, Paolo Bonzini wrote:
> 
> 
> On 11/05/2016 15:29, Christoffer Dall wrote:
>> Hi Paolo and Radim,
>>
>> Here is the initial set of changes for KVM/ARM for v4.7.
>>
>> Sorry I'm a bit late with these, but we were trying to get the new vgic
>> implementation in as part of this, but I have decided to send this pull
>> request now, and we can follow up with another for the new VGIC,
>> assuming we feel like we have that in place in a few days.
> 
> Don't worry, you're not late at all.  I've pulled this to kvm/queue.
> 
>> There are a few changes in this pull request touching things outside
>> KVM, but they should all carry the necessary acks and it made the
>> merge process much easier to do it this way.
> 
> The following are properly acked:
> 
>     arm64: Reuse TCR field definitions for EL1 and EL2
>     arm64: Introduce pmd_thp_or_huge
> 
> I wouldn't have minded more explicit Acked-bys for the following:
> 
>     irqchip/gic-v2: Gather ACPI specific data in a single structure
>     irqchip/gic-v2: Parse and export virtual GIC information
>     irqchip/gic-v3: Prefix all pr_* messages by "GICv3: "
>     irqchip/gic-v3: Gather all ACPI specific data in a single structure
>     irqchip/gic-v3: Parse and export virtual GIC information
> 
> I guess it's fine since Marc Zyngier is maintainer for both KVM and
> irqchip, still it's never wrong to get more acks. :)

Ah, I really thought I acked them. The email must have been stuck in my
head...

So more formally and for documentation purposes:

Acked-by: Marc Zyngier <marc.zyngier at arm.com>

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From sudeep.holla at arm.com  Wed May 11 08:37:42 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 11 May 2016 16:37:42 +0100
Subject: [PATCH v5 5/5] ACPI : enable ACPI_PROCESSOR_IDLE on ARM64
In-Reply-To: <1462981062-24909-1-git-send-email-sudeep.holla@arm.com>
References: <1462981062-24909-1-git-send-email-sudeep.holla@arm.com>
Message-ID: <1462981062-24909-6-git-send-email-sudeep.holla@arm.com>

Now that ACPI processor idle driver supports LPI(Low Power Idle), lets
enable ACPI_PROCESSOR_IDLE for ARM64 too.

This patch just removes the IA64 and X86 dependency on ACPI_PROCESSOR_IDLE

Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 drivers/acpi/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 093bfcc4f9c3..de5c7c09de69 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -238,7 +238,7 @@ config ACPI_CPPC_LIB
 config ACPI_PROCESSOR
 	tristate "Processor"
 	depends on X86 || IA64 || ARM64
-	select ACPI_PROCESSOR_IDLE if X86 || IA64
+	select ACPI_PROCESSOR_IDLE
 	select ACPI_CPU_FREQ_PSS if X86 || IA64
 	default y
 	help
-- 
1.9.1



From sudeep.holla at arm.com  Wed May 11 08:37:40 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 11 May 2016 16:37:40 +0100
Subject: [PATCH v5 3/5] arm64: cpuidle: drop __init section marker to
 arm_cpuidle_init
In-Reply-To: <1462981062-24909-1-git-send-email-sudeep.holla@arm.com>
References: <1462981062-24909-1-git-send-email-sudeep.holla@arm.com>
Message-ID: <1462981062-24909-4-git-send-email-sudeep.holla@arm.com>

Commit ea389daa7fd9 ("arm64: cpuidle: add __init section marker to
arm_cpuidle_init") added the __init annotation to arm_cpuidle_init
as it was not needed after booting which was correct at that time.

However with the introduction of ACPI LPI support, this will be used
from cpuhotplug path in ACPI processor driver.

This patch drops the __init annotation from arm_cpuidle_init to avoid
the following warning:

WARNING: vmlinux.o(.text+0x113c8): Section mismatch in reference from the
	function acpi_processor_ffh_lpi_probe() to the function
	.init.text:arm_cpuidle_init()
The function acpi_processor_ffh_lpi_probe() references
the function __init arm_cpuidle_init().
This is often because acpi_processor_ffh_lpi_probe lacks a __init
annotation or the annotation of arm_cpuidle_init is wrong.

Cc: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 arch/arm64/kernel/cpuidle.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/cpuidle.c b/arch/arm64/kernel/cpuidle.c
index 9047cab68fd3..7ce589ca54a4 100644
--- a/arch/arm64/kernel/cpuidle.c
+++ b/arch/arm64/kernel/cpuidle.c
@@ -15,7 +15,7 @@
 #include <asm/cpuidle.h>
 #include <asm/cpu_ops.h>
 
-int __init arm_cpuidle_init(unsigned int cpu)
+int arm_cpuidle_init(unsigned int cpu)
 {
 	int ret = -EOPNOTSUPP;
 
-- 
1.9.1



From sudeep.holla at arm.com  Wed May 11 08:37:41 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Wed, 11 May 2016 16:37:41 +0100
Subject: [PATCH v5 4/5] arm64: add support for ACPI Low Power Idle(LPI)
In-Reply-To: <1462981062-24909-1-git-send-email-sudeep.holla@arm.com>
References: <1462981062-24909-1-git-send-email-sudeep.holla@arm.com>
Message-ID: <1462981062-24909-5-git-send-email-sudeep.holla@arm.com>

This patch adds appropriate callbacks to support ACPI Low Power Idle
(LPI) on ARM64.

Cc: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: linux-arm-kernel at lists.infradead.org
Signed-off-by: Sudeep Holla <sudeep.holla at arm.com>
---
 arch/arm64/kernel/acpi.c | 48 +++++++++++++++++++++++++++++++++++++++++
 drivers/firmware/psci.c  | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 104 insertions(+)

diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index d1ce8e2f98b9..bf82ce5c8fce 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -18,6 +18,7 @@
 #include <linux/acpi.h>
 #include <linux/bootmem.h>
 #include <linux/cpumask.h>
+#include <linux/cpu_pm.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
@@ -25,6 +26,9 @@
 #include <linux/of_fdt.h>
 #include <linux/smp.h>
 
+#include <acpi/processor.h>
+
+#include <asm/cpuidle.h>
 #include <asm/cputype.h>
 #include <asm/cpu_ops.h>
 #include <asm/smp_plat.h>
@@ -211,6 +215,50 @@ void __init acpi_boot_table_init(void)
 	}
 }
 
+int acpi_processor_ffh_lpi_probe(unsigned int cpu)
+{
+	return arm_cpuidle_init(cpu);
+}
+
+#define ACPI_FFH_LPI_ARM_FLAGS_CORE_CONTEXT	BIT(0)
+#define ACPI_FFH_LPI_ARM_FLAGS_TRACE_CONTEXT	BIT(1)
+#define ACPI_FFH_LPI_ARM_FLAGS_GICR_CONTEXT	BIT(2)
+#define ACPI_FFH_LPI_ARM_FLAGS_GICD_CONTEXT	BIT(3)
+#define ACPI_FFH_LPI_ARM_FLAGS_ALL_CONTEXT	\
+	(ACPI_FFH_LPI_ARM_FLAGS_CORE_CONTEXT |	\
+	 ACPI_FFH_LPI_ARM_FLAGS_TRACE_CONTEXT |	\
+	 ACPI_FFH_LPI_ARM_FLAGS_GICR_CONTEXT |	\
+	 ACPI_FFH_LPI_ARM_FLAGS_GICD_CONTEXT)
+
+struct acpi_lpi_state *lpi;
+int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi, int idx)
+{
+	int ret = 0;
+	bool save_ctx = lpi->arch_flags & ACPI_FFH_LPI_ARM_FLAGS_ALL_CONTEXT;
+
+	if (!idx) {
+		cpu_do_idle();
+		return idx;
+	}
+
+	/* TODO cpu_pm_{enter,exit} can be done in generic code ? */
+	if (save_ctx)
+		ret = cpu_pm_enter();
+	if (!ret) {
+		/*
+		 * Pass idle state index to cpu_suspend which in turn will
+		 * call the CPU ops suspend protocol with idle index as a
+		 * parameter.
+		 */
+		ret = arm_cpuidle_suspend(idx);
+
+		if (save_ctx)
+			cpu_pm_exit();
+	}
+
+	return ret ? -1 : idx;
+}
+
 #ifdef CONFIG_ACPI_APEI
 pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
 {
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index fa4ea22ca12e..e06bfee68e1d 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -13,6 +13,7 @@
 
 #define pr_fmt(fmt) "psci: " fmt
 
+#include <linux/acpi.h>
 #include <linux/arm-smccc.h>
 #include <linux/cpuidle.h>
 #include <linux/errno.h>
@@ -310,11 +311,66 @@ static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
 	return ret;
 }
 
+#ifdef CONFIG_ACPI
+#include <acpi/processor.h>
+
+static int __maybe_unused psci_acpi_cpu_init_idle(unsigned int cpu)
+{
+	int i, count;
+	u32 *psci_states;
+	struct acpi_processor *pr;
+	struct acpi_lpi_state *lpi;
+
+	pr = per_cpu(processors, cpu);
+	if (unlikely(!pr || !pr->flags.has_lpi))
+		return -EINVAL;
+
+	/*
+	 * If the PSCI cpu_suspend function hook has not been initialized
+	 * idle states must not be enabled, so bail out
+	 */
+	if (!psci_ops.cpu_suspend)
+		return -EOPNOTSUPP;
+
+	count = pr->power.count - 1;
+	if (!count)
+		return -ENODEV;
+
+	psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL);
+	if (!psci_states)
+		return -ENOMEM;
+
+	for (i = 0; i < count; i++) {
+		u32 state;
+
+		lpi = &pr->power.lpi_states[i + 1];
+		state = lpi->address & 0xFFFFFFFF;
+		if (!psci_power_state_is_valid(state)) {
+			pr_warn("Invalid PSCI power state %#x\n", state);
+			kfree(psci_states);
+			return -EINVAL;
+		}
+		psci_states[i] = state;
+	}
+	/* Idle states parsed correctly, initialize per-cpu pointer */
+	per_cpu(psci_power_state, cpu) = psci_states;
+	return 0;
+}
+#else
+static int __maybe_unused psci_acpi_cpu_init_idle(unsigned int cpu)
+{
+	return -EINVAL;
+}
+#endif
+
 int psci_cpu_init_idle(unsigned int cpu)
 {
 	struct device_node *cpu_node;
 	int ret;
 
+	if (!acpi_disabled)
+		return psci_acpi_cpu_init_idle(cpu);
+
 	cpu_node = of_get_cpu_node(cpu, NULL);
 	if (!cpu_node)
 		return -ENODEV;
-- 
1.9.1



From pbonzini at redhat.com  Wed May 11 08:41:19 2016
From: pbonzini at redhat.com (Paolo Bonzini)
Date: Wed, 11 May 2016 17:41:19 +0200
Subject: [PULL 00/29] KVM/ARM Changes for v4.7
In-Reply-To: <573351D1.4060303@arm.com>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
 <57334E72.9010109@redhat.com> <573351D1.4060303@arm.com>
Message-ID: <5733529F.3010006@redhat.com>



On 11/05/2016 17:37, Marc Zyngier wrote:
> Ah, I really thought I acked them. The email must have been stuck in my
> head...
> 
> So more formally and for documentation purposes:
> 
> Acked-by: Marc Zyngier <marc.zyngier at arm.com>

Good, I'll add a note in the tag message when sending my own pull
request to Linus.

Thanks,

Paolo


From javier at osg.samsung.com  Wed May 11 08:41:34 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 11 May 2016 11:41:34 -0400
Subject: [PATCH v3 00/27] ARM: dts: exynos: Add initial support for Odroid
 XU
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <09dcc771-40e2-8be0-de73-bc1db37d6804@osg.samsung.com>

Hello Krzysztof,

On 05/10/2016 04:09 PM, Krzysztof Kozlowski wrote:
> Hi,
> 
> Patchset adds necessary clocks, reorganizes existing stuff and finally
> adds Odroid XU support.
> 
> 
> Changes since v2
> ================
> 1. Got global-ack from Stephen for the clock changes. I think merging
>    everything through arm-soc might be the easiest but:
>    a. In such case I will prepare a tag with clock changes,
>    b. Anyway I will wait for response from Sylwester and Tomasz.
> 2. Applied comments from Javier and added his Reviewed-by.
> 3. Patch 22: added ack from Rob.
> 4. Minor improvements in existing patches.
> 5. Five new patches at the end: 23-27 (not reviewed yet).
>    Some of them could be squashed with existing ones but existing
>    changes got reviews. Although the final Odroid XU DTS works fine but
>    in general this is still work-in-progress so I suspect it will grow.
>    I am releasing it early following Linux concept. :)
> 
> Patchset is available at my private repo @github:
> https://github.com/krzk/linux.git for-next/odroid-xu-v3
> 

I have tested this branch on both an Exynos5422 Odroid XU4 board and an
Exynos5800 Peach Pi Chromebook. All the peripherals are working correctly.

So for all patches affecting Exynos54xx/5800 (9,12,13,14,16,19,20,21,25):

Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From christoffer.dall at linaro.org  Wed May 11 08:42:52 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 11 May 2016 17:42:52 +0200
Subject: [PULL 00/29] KVM/ARM Changes for v4.7
In-Reply-To: <57334E72.9010109@redhat.com>
References: <1462973422-10021-1-git-send-email-christoffer.dall@linaro.org>
 <57334E72.9010109@redhat.com>
Message-ID: <20160511154252.GX27623@cbox>

On Wed, May 11, 2016 at 05:23:30PM +0200, Paolo Bonzini wrote:
> 
> 
> On 11/05/2016 15:29, Christoffer Dall wrote:
> > Hi Paolo and Radim,
> > 
> > Here is the initial set of changes for KVM/ARM for v4.7.
> > 
> > Sorry I'm a bit late with these, but we were trying to get the new vgic
> > implementation in as part of this, but I have decided to send this pull
> > request now, and we can follow up with another for the new VGIC,
> > assuming we feel like we have that in place in a few days.
> 
> Don't worry, you're not late at all.  I've pulled this to kvm/queue.
> 
> > There are a few changes in this pull request touching things outside
> > KVM, but they should all carry the necessary acks and it made the
> > merge process much easier to do it this way.
> 
> The following are properly acked:
> 
>     arm64: Reuse TCR field definitions for EL1 and EL2
>     arm64: Introduce pmd_thp_or_huge
> 
> I wouldn't have minded more explicit Acked-bys for the following:
> 
>     irqchip/gic-v2: Gather ACPI specific data in a single structure
>     irqchip/gic-v2: Parse and export virtual GIC information
>     irqchip/gic-v3: Prefix all pr_* messages by "GICv3: "
>     irqchip/gic-v3: Gather all ACPI specific data in a single structure
>     irqchip/gic-v3: Parse and export virtual GIC information
> 
> I guess it's fine since Marc Zyngier is maintainer for both KVM and
> irqchip, still it's never wrong to get more acks. :)
> 
Jason Cooper also acked them all; I swear I intended to add his acks to
all of these specifically, but I must've forgotten.

I have forwarded you his ack for reference.  Let me know if you need me
to do anything else.

Thanks,
-Christoffer


From sricharan at codeaurora.org  Wed May 11 08:57:40 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Wed, 11 May 2016 21:27:40 +0530
Subject: [PATCH 1/2] i2c: qup: Cleared the error bits in ISR
In-Reply-To: <1462797871-8595-2-git-send-email-absahu@codeaurora.org>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
 <1462797871-8595-2-git-send-email-absahu@codeaurora.org>
Message-ID: <000701d1ab9d$df9b3100$9ed19300$@codeaurora.org>

Hi,

> 1. Current QCOM I2C driver hangs when sending data to address 0x03-0x07
> in some scenarios. The QUP controller generates invalid write in this
case,
> since these addresses are reserved for different bus formats.
> 
> 2. Also, the error handling is done by I2C QUP ISR in the case of DMA
mode.
> The state need to be RESET in case of any error for clearing the available
> data in FIFO, which otherwise leaves the BAM DMA controller in hang state.
> 
> This patch fixes the above two issues by clearing the error bits from I2C
and
> QUP status in ISR in case of I2C error, QUP error and resets the QUP state
to
> clear the FIFO data.
> 
> Signed-off-by: Abhishek Sahu <absahu at codeaurora.org>
> ---
>  drivers/i2c/busses/i2c-qup.c | 14 ++++++++------
>  1 file changed, 8 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index
> 23eaabb..8c2f1bc 100644
> --- a/drivers/i2c/busses/i2c-qup.c
> +++ b/drivers/i2c/busses/i2c-qup.c
> @@ -213,14 +213,16 @@ static irqreturn_t qup_i2c_interrupt(int irq, void
> *dev)
>  	bus_err &= I2C_STATUS_ERROR_MASK;
>  	qup_err &= QUP_STATUS_ERROR_FLAGS;
> 
> -	if (qup_err) {
> -		/* Clear Error interrupt */
> +	/* Clear the error bits in QUP_ERROR_FLAGS */
> +	if (qup_err)
>  		writel(qup_err, qup->base + QUP_ERROR_FLAGS);
> -		goto done;
> -	}
> 
> -	if (bus_err) {
> -		/* Clear Error interrupt */
> +	/* Clear the error bits in QUP_I2C_STATUS */
> +	if (bus_err)
> +		writel(bus_err, qup->base + QUP_I2C_STATUS);
> +
> +	/* Reset the QUP State in case of error */
> +	if (qup_err || bus_err) {
>  		writel(QUP_RESET_STATE, qup->base + QUP_STATE);
>  		goto done;
>  	}
       In qup_i2c_xfer and qup_i2c_xfer_v2 state is set to RESET at the end,
when
       there is no error. So would it be fine if we do it there
unconditionally ?

Regards,
 Sricharan





From arnd at arndb.de  Wed May 11 09:01:44 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 18:01:44 +0200
Subject: More build fixes for omapdrm in current -next
Message-ID: <1462982509-342936-1-git-send-email-arnd@arndb.de>

A couple more errors showed up in linux-next in the last few
days, all because of missing header files. I have not seen these
before, and most configurations appear to be fine. There
must have been an implicit inclusion somewhere before that
just got removed, but I couldn't find it and doing the
explicit #include should always be better here.

Please apply for 4.7 to avoid regressing on randconfig builds.

	Arnd



From arnd at arndb.de  Wed May 11 09:01:45 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 18:01:45 +0200
Subject: [PATCH 1/3] drm/omap: include linux/seq_file.h where needed
In-Reply-To: <1462982509-342936-1-git-send-email-arnd@arndb.de>
References: <1462982509-342936-1-git-send-email-arnd@arndb.de>
Message-ID: <1462982509-342936-2-git-send-email-arnd@arndb.de>

The omapdrm driver relies on this header to be included
implicitly, but this does not always work, and I get
this error in randconfig builds:

gpu/drm/omapdrm/dss/hdmi_phy.c: In function 'hdmi_phy_dump':
gpu/drm/omapdrm/dss/hdmi_phy.c:34:2: error: implicit declaration of function 'seq_printf' [-Werror=implicit-function-declaration]
gpu/drm/omapdrm/dss/hdmi_wp.c: In function 'hdmi_wp_dump':
gpu/drm/omapdrm/dss/hdmi_wp.c:26:2: error: implicit declaration of function 'seq_printf' [-Werror=implicit-function-declaration]
gpu/drm/omapdrm/dss/hdmi_pll.c: In function 'hdmi_pll_dump':
gpu/drm/omapdrm/dss/hdmi_pll.c:30:2: error: implicit declaration of function 'seq_printf' [-Werror=implicit-function-declaration]

This adds the #include statements in all files that have
a seq_printf statement.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/gpu/drm/omapdrm/dss/hdmi_phy.c   | 1 +
 drivers/gpu/drm/omapdrm/dss/hdmi_pll.c   | 1 +
 drivers/gpu/drm/omapdrm/dss/hdmi_wp.c    | 1 +
 drivers/gpu/drm/omapdrm/omap_debugfs.c   | 2 ++
 drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | 1 +
 drivers/gpu/drm/omapdrm/omap_fb.c        | 2 ++
 drivers/gpu/drm/omapdrm/omap_gem.c       | 1 +
 7 files changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c b/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c
index 1f5d19c119ce..f98b750fc499 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/seq_file.h>
 #include <video/omapdss.h>
 
 #include "dss.h"
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c b/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c
index 06e23a7c432c..f1015e8b8267 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/seq_file.h>
 
 #include <video/omapdss.h>
 
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
index 13442b9052d1..055f62fca5dc 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
@@ -14,6 +14,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/seq_file.h>
 #include <video/omapdss.h>
 
 #include "dss.h"
diff --git a/drivers/gpu/drm/omapdrm/omap_debugfs.c b/drivers/gpu/drm/omapdrm/omap_debugfs.c
index 6f5fc14fc015..479bf24050f8 100644
--- a/drivers/gpu/drm/omapdrm/omap_debugfs.c
+++ b/drivers/gpu/drm/omapdrm/omap_debugfs.c
@@ -17,6 +17,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/seq_file.h>
+
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_helper.h>
 
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
index de275a5be1db..4ceed7a9762f 100644
--- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
+++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h> /* platform_device() */
 #include <linux/sched.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/vmalloc.h>
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 610962396eb0..dce41e176a64 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -17,6 +17,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/seq_file.h>
+
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index 907154f5b67c..d2d879da6287 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -17,6 +17,7 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/seq_file.h>
 #include <linux/shmem_fs.h>
 #include <linux/spinlock.h>
 #include <linux/pfn_t.h>
-- 
2.7.0



From arnd at arndb.de  Wed May 11 09:01:46 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 18:01:46 +0200
Subject: [PATCH 2/3] drm/omap: include linux/of.h where needed
In-Reply-To: <1462982509-342936-1-git-send-email-arnd@arndb.de>
References: <1462982509-342936-1-git-send-email-arnd@arndb.de>
Message-ID: <1462982509-342936-3-git-send-email-arnd@arndb.de>

Some parts of the OMAP drm driver rely on implicit inclusion of
linux/of.h but fail in some configurations:

drivers/gpu/drm/omapdrm/dss/hdmi4.c: In function 'hdmi_probe_of':
drivers/gpu/drm/omapdrm/dss/hdmi4.c:564:2: error: implicit declaration of function 'of_node_put' [-Werror=implicit-function-declaration]
drivers/gpu/drm/omapdrm/dss/hdmi5.c: In function 'hdmi_probe_of':
drivers/gpu/drm/omapdrm/dss/hdmi5.c:590:2: error: implicit declaration of function 'of_node_put' [-Werror=implicit-function-declaration]

This adds an explicit #include statement to those files.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/gpu/drm/omapdrm/dss/hdmi4.c | 1 +
 drivers/gpu/drm/omapdrm/dss/hdmi5.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index f892ae157ff3..079bcfcbc8ef 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -25,6 +25,7 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/platform_device.h>
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index a43f7b10e113..68ac2491d4b1 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -31,6 +31,7 @@
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 #include <linux/delay.h>
+#include <linux/of.h>
 #include <linux/string.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
-- 
2.7.0



From p.zabel at pengutronix.de  Wed May 11 09:05:33 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Wed, 11 May 2016 18:05:33 +0200
Subject: [PATCH] drm: mediatek: add COMMON_CLK dependency
In-Reply-To: <1462970100-240687-1-git-send-email-arnd@arndb.de>
References: <1462970100-240687-1-git-send-email-arnd@arndb.de>
Message-ID: <1462982733.2924.36.camel@pengutronix.de>

Am Mittwoch, den 11.05.2016, 14:34 +0200 schrieb Arnd Bergmann:
> On kernel builds without COMMON_CLK, the newly added mediatek drm
> driver fails to build:
> 
> drivers/gpu/drm/mediatek/mtk_mipi_tx.c:130:16: error: field 'pll_hw' has incomplete type
>   struct clk_hw pll_hw;
>                 ^~~~~~
> In file included from ../include/linux/clk.h:16:0,
>                  from ../drivers/gpu/drm/mediatek/mtk_mipi_tx.c:14:
> drivers/gpu/drm/mediatek/mtk_mipi_tx.c: In function 'mtk_mipi_tx_from_clk_hw':
> include/linux/kernel.h:831:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
>   const typeof( ((type *)0)->member ) *__mptr = (ptr); \
>                                                 ^
> /drivers/gpu/drm/mediatek/mtk_mipi_tx.c:136:9: note: in expansion of macro 'container_of'
>   return container_of(hw, struct mtk_mipi_tx, pll_hw);
>          ^~~~~~~~~~~~
> drivers/gpu/drm/mediatek/mtk_mipi_tx.c: At top level:
> drivers/gpu/drm/mediatek/mtk_mipi_tx.c:302:21: error: variable 'mtk_mipi_tx_pll_ops' has initializer but incomplete type
>  static const struct clk_ops mtk_mipi_tx_pll_ops = {
> 
> This adds the required Kconfig dependency.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>

Acked-by: Philipp Zabel <p.zabel at pengutronix.de>

regards
Philipp



From arnd at arndb.de  Wed May 11 09:05:39 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 18:05:39 +0200
Subject: [PATCH 3/3] drm/omap: include gpio/consumer.h where needed
In-Reply-To: <1462982509-342936-1-git-send-email-arnd@arndb.de>
References: <1462982509-342936-1-git-send-email-arnd@arndb.de>
Message-ID: <1462982845-461029-1-git-send-email-arnd@arndb.de>

A lot of the display drivers for OMAP use the gpio descriptor functions
that are only available in linux/gpio.h if GPIOLIB is enabled and
otherwise produce a build error:

drivers/gpu/drm/omapdrm/displays/encoder-opa362.c: In function 'opa362_enable':
drivers/gpu/drm/omapdrm/displays/encoder-opa362.c:101:3: error: implicit declaration of function 'gpiod_set_value_cansleep' [-Werror=implicit-function-declaration]
drivers/gpu/drm/omapdrm/displays/panel-dpi.c: In function 'panel_dpi_probe_pdata':
drivers/gpu/drm/omapdrm/displays/panel-dpi.c:189:23: error: implicit declaration of function 'gpio_to_desc' [-Werror=implicit-function-declaration]
drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c: In function 'sharp_ls_enable':
drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c:120:3: error: implicit declaration of function 'gpiod_set_value_cansleep' [-Werror=implicit-function-declaration]

This replaces the existing linux/gpio.h with linux/gpio/consumer.h
where needed. In case of panel-lgphilips-lb035q02.c however, we
also have to include linux/gpio.h to get the definition of gpio_is_valid
and gpio_set_value_cansleep that are used for the non-DT case.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/gpu/drm/omapdrm/displays/connector-hdmi.c           | 1 +
 drivers/gpu/drm/omapdrm/displays/encoder-opa362.c           | 2 +-
 drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c           | 2 +-
 drivers/gpu/drm/omapdrm/displays/panel-dpi.c                | 2 +-
 drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c             | 2 +-
 drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c | 1 +
 drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c     | 2 +-
 drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c  | 2 +-
 drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c     | 2 +-
 drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c     | 2 +-
 10 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
index 225fd8d6ab31..667ca4a24ece 100644
--- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
+++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  */
 
+#include <linux/gpio/consumer.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
index 8c246c213e06..9594ff7a2b0c 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
@@ -14,7 +14,7 @@
  * the Free Software Foundation.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c
index 2fd5602880a7..671806ca7d6a 100644
--- a/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c
+++ b/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c
@@ -9,7 +9,7 @@
  * the Free Software Foundation.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
index e780fd4f8b46..7c2331be8d15 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
@@ -9,7 +9,7 @@
  * the Free Software Foundation.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
index 36485c2137ce..2b118071b5a1 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
@@ -14,7 +14,7 @@
 #include <linux/backlight.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/module.h>
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
index 458f77bc473d..ac680e1de603 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
@@ -15,6 +15,7 @@
 #include <linux/spi/spi.h>
 #include <linux/mutex.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 
 #include <video/omapdss.h>
 #include <video/omap-panel-data.h>
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
index 780cb263a318..38d2920a95e6 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
@@ -15,7 +15,7 @@
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
 #include <linux/fb.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of_gpio.h>
 
 #include <video/omapdss.h>
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
index 529a017602e4..4363fffc87e3 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
@@ -10,7 +10,7 @@
  */
 
 #include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
index 31efcca801bd..deb416736aad 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
@@ -29,7 +29,7 @@
 #include <linux/sched.h>
 #include <linux/backlight.h>
 #include <linux/fb.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
index 03e2beb7b4f0..d93175b03a12 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
@@ -14,7 +14,7 @@
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
 #include <linux/regulator/consumer.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/of_gpio.h>
-- 
2.7.0



From kernel at martin.sperl.org  Wed May 11 09:09:37 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Wed, 11 May 2016 18:09:37 +0200
Subject: [PATCH 0/3] clk: bcm2835: critical clocks and parent selection
In-Reply-To: <5E7C0C2A-8FA0-4EFF-9627-DFC34662590B@martin.sperl.org>
References: <1462842090-2017-1-git-send-email-eric@anholt.net>
 <5731B8BA.30402@martin.sperl.org> <87a8jxyfua.fsf@eliezer.anholt.net>
 <FD44F435-512C-49A5-B1F5-3C62AAF805AC@martin.sperl.org>
 <5E7C0C2A-8FA0-4EFF-9627-DFC34662590B@martin.sperl.org>
Message-ID: <F589714D-F70A-4BF6-B658-A22267853779@martin.sperl.org>


> On 11.05.2016, at 10:21, Martin Sperl <kernel at martin.sperl.org> wrote:
> 
> On 10.05.2016, at 21:58, Martin Sperl <kernel at martin.sperl.org> wrote:
>> 
>> 
>> 
>>> On 10.05.2016, at 19:37, Eric Anholt <eric at anholt.net> wrote:
>>> 
>>> Martin Sperl <kernel at martin.sperl.org> writes:
>>> 
>>>>> On 10.05.2016 03:01, Eric Anholt wrote:
>>>>> With the new patch 2 inserted between my previous pair, I think this
>>>>> should cover Martin's bugs with clock disabling.
>>>>> 
>>>>> I tested patch 2 to be important on the downstream kernel: with the
>>>>> DPI panel support added there, I was losing ethernet (my only I/O)
>>>>> when the HDMI HSM hanging off of PLLD_PER got disabled due to
>>>>> EPROBE_DEFER.
>>>>> 
>>>>> Eric Anholt (3):
>>>>> clk: bcm2835: Mark the VPU clock as critical
>>>>> clk: bcm2835: Mark GPIO clocks enabled at boot as critical.
>>>>> clk: bcm2835: Skip PLLC clocks when deciding on a new clock parent
>>>>> 
>>>>> drivers/clk/bcm/clk-bcm2835.c | 32 ++++++++++++++++++++++++++++++--
>>>>> 1 file changed, 30 insertions(+), 2 deletions(-)
>>>> I gave it a try - with all 3 patches applied I get the following enabled 
>>>> clocks:
>>>> root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
>>>> /sys/kernel/debug/clk/aux_uart/clk_enable_count:1
>>>> /sys/kernel/debug/clk/emmc/clk_enable_count:1
>>>> /sys/kernel/debug/clk/gp1/clk_enable_count:1
>>>> /sys/kernel/debug/clk/gp2/clk_enable_count:1
>>>> /sys/kernel/debug/clk/osc/clk_enable_count:1
>>>> /sys/kernel/debug/clk/pllc/clk_enable_count:2
>>>> /sys/kernel/debug/clk/pllc_core0/clk_enable_count:1
>>>> /sys/kernel/debug/clk/pllc_per/clk_enable_count:1
>>>> /sys/kernel/debug/clk/vpu/clk_enable_count:2
>>>> 
>>>> At least on my compute module gp1/gp2 is enabled, but there is no rate
>>>> set - so why is it marked as critical for all devices?
>>>> So why apply patch2 for all possible devices?
>>> 
>>> According to the CLK_IS_CRITICAL patches, the author intended critical
>>> clocks not to use the included function for marking clocks as critical
>>> From the DT.  I'm not sure why, but writing patches using that when they
>>> say not to seemed like a waste.
>>> 
>>> We could check if gp1/gp2 are already on before marking them critical.
>> That may seem reasonable.
>>> 
>>>> Loading/unloading the amba_pl011 module does not crash the system,
>>>> but a simple stty -F /dev/ttyAMA0 does crash the system!
>>>> 
>>>> Here the sequence:
>>>> root at raspcm:~# dmesg -C
>>>> root at raspcm:~# modprobe amba_pl011
>>>> root at raspcm:~# dmesg -c
>>>> [  141.708453] Serial: AMBA PL011 UART driver
>>>> [  141.709158] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, 
>>>> base_baud = 0) is a PL011 rev2
>>>> root at raspcm:~# rmmod  amba_pl011
>>>> root at raspcm:~# dmesg -c
>>>> [  150.511248] Trying to free nonexistent resource 
>>>> <0000000020201000-0000000020201fff>
>>>> root at raspcm:~# modprobe amba_pl011
>>>> root at raspcm:~# dmesg -c
>>>> [  159.385002] Serial: AMBA PL011 UART driver
>>>> [  159.385714] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, 
>>>> base_baud = 0) is a PL011 rev2
>>>> root at raspcm:~# stty -F /dev/ttyAMA0
>>>> speed 9600 baud; line = 0;
>>>> -brkint -imaxbel
>>>> root at raspcm:~# Timeout, server raspcm not responding.
>>>> 
>>>> The reason behind this is that the firmware pre-configured uart clock
>>>> looks like this:
>>>> root at raspcm:~# cat /sys/kernel/debug/clk/uart/regdump
>>>> ctl = 0x00000296
>>>> div = 0x000a6aab
>>>> so it is configured to use plld_per (which itself is running, even if 
>>>> not enabled
>>>> in the kernel)
>>>> 
>>>> But as plld_per is not among the enabled clocks then plld_per
>>>> gets disabled as soon as the tty device is closed (by stty) and
>>>> this also disables plld...
>>>> 
>>>> Similar effect when using PCM/i2s and use speaker-test:
>>>> root at raspcm:~# dmesg -C
>>>> root at raspcm:~# modprobe snd-soc-bcm2835-i2s; modprobe snd-soc-pcm5102a; 
>>>> modprobe snd-soc-hifiberry-dac
>>>> root at raspcm:~# dmesg
>>>> [   81.968591] snd-hifiberry-dac sound: pcm5102a-hifi <-> 20203000.i2s 
>>>> mapping ok
>>>> root at raspcm:~# speaker-test -c 2 -r 44100 -F S16_LE -f 440 -t sine&
>>>> [1] 579
>>>> root at raspcm:~#
>>>> speaker-test 1.0.28
>>>> 
>>>> Playback device is default
>>>> Stream parameters are 44100Hz, S16_LE, 2 channels
>>>> Sine wave rate is 440.0000Hz
>>>> Rate set to 44100Hz (requested 44100Hz)
>>>> Buffer size range from 128 to 131072
>>>> Period size range from 64 to 65536
>>>> Using max buffer size 131072
>>>> Periods = 4
>>>> was set period_size = 32768
>>>> was set buffer_size = 131072
>>>> 0 - Front Left
>>>> 1 - Front Right
>>>> 
>>>> root at raspcm:~#
>>>> root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
>>>> /sys/kernel/debug/clk/aux_uart/clk_enable_count:1
>>>> /sys/kernel/debug/clk/emmc/clk_enable_count:1
>>>> /sys/kernel/debug/clk/gp1/clk_enable_count:1
>>>> /sys/kernel/debug/clk/gp2/clk_enable_count:1
>>>> /sys/kernel/debug/clk/osc/clk_enable_count:2
>>>> /sys/kernel/debug/clk/pcm/clk_enable_count:1
>>>> /sys/kernel/debug/clk/pllc/clk_enable_count:2
>>>> /sys/kernel/debug/clk/pllc_core0/clk_enable_count:1
>>>> /sys/kernel/debug/clk/pllc_per/clk_enable_count:1
>>>> /sys/kernel/debug/clk/plld/clk_enable_count:1
>>>> /sys/kernel/debug/clk/plld_per/clk_enable_count:1
>>>> /sys/kernel/debug/clk/vpu/clk_enable_count:2
>>>> root at raspcm:~# kill %1
>>>> root at raspcm:~# Time per period = 106.889502
>>>> Timeout, server raspcm not responding.
>>>> 
>>>> You see that plld gets now used and when I kill speaker-test
>>>> the machine crashes again.
>>> 
>>> Just so I can be clear here: What are you using to talk to the Pi?
>>> Builtin USB ethernet?
>> Compute module with USB  Ethernet adapter, but I also got an 
>> enc28j60 connected via spi, but that is not enabled by default
>> 
>>> 
>>>> So this patchset does not really solve any of the problems that
>>>> I have reported either.
>>>> 
>>>> That is why my patchset has taken the "HAND_OFF" approach
>>>> instead (which still just hides some of the issues), but at least
>>>> it does not crash the system on the use of plld and it allows
>>>> for custom parent and mash selection.
>>> 
>>> HAND_OFF sure doesn't look like it's landing in the next kernel, so
>>> writing patches using it doesn't make much sense to me.
>> 
>> If it is critical or hands-off does not really make a difference...
>> 
>>>> In reality it would require consumers of the corresponding
>>>> parent clocks in the kernel (arm, ...) and the knowledge which
>>>> clocks are really needed by the firmware - i.e plld.
>>>> 
>>>> Note that the sdram clock is using plld_core parent!
>>>> root at raspcm:~#  cat /sys/kernel/debug/clk/sdram/regdump
>>>> ctl = 0x00004006
>>>> div = 0x00003000
>>>> root at raspcm:~# cat /sys/kernel/debug/clk/sdram/clk_rate
>>>> 166533331
>>> 
>>> However, it's not enabled, right?  Bit 4 isn't set in the CTL reg.
>> You are probably right there, but still there must be something
>> hidden that requires plld or plld_per or plld_core, that requires critical.
>> 
>> There must be some reason why it gets set up during the
>> boot process by the firmware.
>> 
> 
> Correction:
> 
> Actually the SDC control register contains some more bits compared
> to most other clock control registers:
> CM_SDCCTL_CTRL (12-15), CM_SDCCTL_ACCPT(16) and CM_SDCCTL_UPDATE(17)
> 
> See also:
> https://github.com/msperl/rpi-registers/blob/master/md/Region_CM.md#cm_sdcctl
> 
> If I poke that register (0x201011a8) from userspace with 0x5a000000
> then the machine crashes as well - so I assume these bits control
> the custom SD-Ram PLL - unfortunately it still does not say which
> PLL is used.
> 
> Eric, you may have access to more data regarding this register -
> maybe we need to hand this register as a special clock?
> and/or expose it as an additional pll?
> 
> Note that I also tried disabling PLLD_CORE and the system crashed as well
> (root at raspcm:~#  peekpoke $[0x20101000 + 0x10c] w
> /dev/mem opened.
> Memory mapped at address 0xb6fdd000.
> Value at address 0x2010110C (0xb6fdd10c): 0x20A
> root at raspcm:~# peekpoke $[0x20101000 + 0x10c] w $[0x5a000000 + 0x20a + 32]
> /dev/mem opened.
> Memory mapped at address 0xb6fe7000.
> Value at address 0x2010110C (0xb6fe710c): 0x20A
> Written 0x5A00022A; readback 0x22A
> root at raspcm:~# Write failed: Broken pipe
> 
> (requires /dev/mem without restrictions)
> 
> So this means that it is plld_core related - at least as of now
> and the sdram pll currently derives from PLLD_core.
> 
> @Eric: so please look at the hld (which you have hinted you have
> access to) and come up with something better for sdram
> 
> As far as I can tell at the very least the sdram clock is critical
> and should be marked as such?

So I now got a relatively simple driver that requests:
* the sdram clock
* the ic0 and ic1 register ranges (which afaik are sdram related)
 * exposes those registers read-only via debugfs.

this way the plld_core clock gets enabled and we should be fine.

Device-tree wise it looks like this:
diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index 2b5cbc6..525f1f2 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
+++ b/arch/arm/boot/dts/bcm283x.dtsi
@@ -22,6 +22,12 @@
                #address-cells = <1>;
                #size-cells = <1>;

+               memory-controller at 7e002000 {
+                       compatible = "brcm,bcm2835-sdram";
+                       reg = <0x7e002000 0x58>, <0x7e002800 0x58>;
+                       clocks = <&clocks BCM2835_CLOCK_SDRAM>;
+               };
+
                timer at 7e003000 {
                        compatible = "brcm,bcm2835-system-timer";
                        reg = <0x7e003000 0x1000>;

Note that it looks as if only one bank is ever used on the RPI,
but as I do not know all the details which ones are really used 
I have added both for now.

I guess the other potential missing things are the plla_* related
clocks, which - afaik - shold belong to the arm in some context,
but which are - so far - not claimed, which could result in hickups
unless the videodriver is enabled (and this uses the h264, isp and v3d
clocks)

On a similar front I also have a thermal driver that reads the ts
registers with similar functionality (clock and register wise) - 
it exposes: /sys/class/thermal/thermal_zone0/temp

Martin

From sricharan at codeaurora.org  Wed May 11 09:18:20 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Wed, 11 May 2016 21:48:20 +0530
Subject: [PATCH 2/2] i2c: qup: Fixed the DMA segments length
In-Reply-To: <1462797871-8595-3-git-send-email-absahu@codeaurora.org>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
 <1462797871-8595-3-git-send-email-absahu@codeaurora.org>
Message-ID: <000b01d1aba0$c2fea380$48fbea80$@codeaurora.org>

Hi,

> 1. The current QCOM I2C driver code is failing for transfer length greater
> than 255. This is happening due to improper segments length as the I2C DMA
> segments can be maximum of 256 bytes.
> 
> 2. The transfer length tlen was being initialized with 0 for 256 bytes,
which is
> being passed for DMA mappings resulting in improper DMA mapping length.
> 
> This patch fixes the above said problems by initializing the block count
with
> the values calculated in qup_i2c_set_blk_data and calculating the
remaining
> length for last DMA segment. Also, the block data length need to be
> decremented after each transfer. Additionally, this patch corrects the
tlen
> assignment for DMA mapping.
> 
> Signed-off-by: Abhishek Sahu <absahu at codeaurora.org>
> ---
>  drivers/i2c/busses/i2c-qup.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index
> 8c2f1bc..6d6b7dc 100644
> --- a/drivers/i2c/busses/i2c-qup.c
> +++ b/drivers/i2c/busses/i2c-qup.c
> @@ -651,23 +651,24 @@ static int qup_i2c_bam_do_xfer(struct
> qup_i2c_dev *qup, struct i2c_msg *msg,
>  	u8 *tags;
> 
>  	while (idx < num) {
> -		blocks = (msg->len + limit) / limit;
> -		rem = msg->len % limit;
>  		tx_len = 0, len = 0, i = 0;
> 
>  		qup->is_last = (idx == (num - 1));
> 
>  		qup_i2c_set_blk_data(qup, msg);
> 
> +		blocks = qup->blk.count;
> +		rem = msg->len - (blocks - 1) * limit;
> +
      Same if we had blocks = (msg->len + limit - 1) / limit instead of the
above ?
     Otherwise, 
     Reviewed-by: Sricharan at codeaurora.org

Regards,
 Sricharan



From peter.griffin at linaro.org  Wed May 11 09:21:59 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 11 May 2016 17:21:59 +0100
Subject: [PATCH] i2c: st: Implement bus clear
Message-ID: <1462983719-342-1-git-send-email-peter.griffin@linaro.org>

>From I2C specifications:
      http://www.nxp.com/documents/user_manual/UM10204.pdf

Chapter 3.1.16, when the i2c device held the SDA line low, the master
should send 9 clocks pulses to try to recover.

Signed-off-by: Frederic Pillon <frederic.pillon at st.com>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---

changes since V1:
 - Demote debug to dev_dbg
 - Add comment on how we achieve 9 clock pulses
 - Remove empty st_i2c_get_scl & st_i2c_set_scl (relies on core patch from Wolfram)
 - rebase on v4.6-rc6
---
 drivers/i2c/busses/i2c-st.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c
index 6ee7715..1ad210b 100644
--- a/drivers/i2c/busses/i2c-st.c
+++ b/drivers/i2c/busses/i2c-st.c
@@ -337,10 +337,42 @@ static void st_i2c_hw_config(struct st_i2c_dev *i2c_dev)
 	writel_relaxed(val, i2c_dev->base + SSC_NOISE_SUPP_WIDTH_DATAOUT);
 }
 
+static int st_i2c_recover_bus(struct i2c_adapter *i2c_adap)
+{
+	struct st_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
+	u32 ctl;
+
+	dev_dbg(i2c_dev->dev, "Trying to recover bus\n");
+
+	/*
+	 * SSP IP is dual role SPI/I2C to generate 9 clock pulses
+	 * we switch to SPI node, 9 bit words and write a 0. This
+	 * has been validate with a oscilloscope and is easier
+	 * than switching to GPIO mode.
+	 */
+
+	/* Disable interrupts */
+	writel_relaxed(0, i2c_dev->base + SSC_IEN);
+
+	st_i2c_hw_config(i2c_dev);
+
+	ctl = SSC_CTL_EN | SSC_CTL_MS |	SSC_CTL_EN_RX_FIFO | SSC_CTL_EN_TX_FIFO;
+	st_i2c_set_bits(i2c_dev->base + SSC_CTL, ctl);
+
+	st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_I2CM);
+	usleep_range(8000, 10000);
+
+	writel_relaxed(0, i2c_dev->base + SSC_TBUF);
+	usleep_range(2000, 4000);
+	st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_I2CM);
+
+	return 0;
+}
+
 static int st_i2c_wait_free_bus(struct st_i2c_dev *i2c_dev)
 {
 	u32 sta;
-	int i;
+	int i, ret;
 
 	for (i = 0; i < 10; i++) {
 		sta = readl_relaxed(i2c_dev->base + SSC_STA);
@@ -352,6 +384,12 @@ static int st_i2c_wait_free_bus(struct st_i2c_dev *i2c_dev)
 
 	dev_err(i2c_dev->dev, "bus not free (status = 0x%08x)\n", sta);
 
+	ret = i2c_recover_bus(&i2c_dev->adap);
+	if (ret) {
+		dev_err(i2c_dev->dev, "Failed to recover the bus (%d)\n", ret);
+		return ret;
+	}
+
 	return -EBUSY;
 }
 
@@ -744,6 +782,10 @@ static struct i2c_algorithm st_i2c_algo = {
 	.functionality = st_i2c_func,
 };
 
+static struct i2c_bus_recovery_info st_i2c_recovery_info = {
+	.recover_bus = st_i2c_recover_bus,
+};
+
 static int st_i2c_of_get_deglitch(struct device_node *np,
 		struct st_i2c_dev *i2c_dev)
 {
@@ -826,6 +868,7 @@ static int st_i2c_probe(struct platform_device *pdev)
 	adap->timeout = 2 * HZ;
 	adap->retries = 0;
 	adap->algo = &st_i2c_algo;
+	adap->bus_recovery_info = &st_i2c_recovery_info;
 	adap->dev.parent = &pdev->dev;
 	adap->dev.of_node = pdev->dev.of_node;
 
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 11 09:22:58 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 11 May 2016 17:22:58 +0100
Subject: [PATCH] i2c: st: Implement i2c_bus_recovery_info callbacks
In-Reply-To: <20160424211044.GD4317@katana>
References: <1460467759-11737-1-git-send-email-peter.griffin@linaro.org>
 <20160424211044.GD4317@katana>
Message-ID: <20160511162258.GA381@griffinp-ThinkPad-X1-Carbon-2nd>

Hi Wolfram,

On Sun, 24 Apr 2016, Wolfram Sang wrote:

> > +/*
> > + * i2c bus recovery routines
> > + * get_scl and set_scl must be defined to avoid the recover_bus field of
> > + * i2c_bus_recovery_info to be overriden with NULL during the
> > + * i2c_add_adapter call
> > + */
> 
> Oh, that shouldn't be like this. Can you try this patch and remove the
> empty functions please?

That works, so will need to be applied along with my v2 which I just sent.

regards,

Peter.



From peter.griffin at linaro.org  Wed May 11 09:33:11 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 11 May 2016 17:33:11 +0100
Subject: [PATCH] usb: dwc3: st: Fix USB_DR_MODE_PERIPHERAL configuration.
Message-ID: <1462984391-605-1-git-send-email-peter.griffin@linaro.org>

Set USB3_FORCE_VBUSVALID when configured for USB_DR_MODE_PERIPHERAL
mode, as it is required to have a working setup.

This worked on the internal driver by relying on the reset
value of the syscfg register as the bits aren't explicity cleared
and set like the upstream driver.

Also add a comment about what setting this bit means.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 drivers/usb/dwc3/dwc3-st.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c
index 5c0adb9..50d6ae6 100644
--- a/drivers/usb/dwc3/dwc3-st.c
+++ b/drivers/usb/dwc3/dwc3-st.c
@@ -129,12 +129,18 @@ static int st_dwc3_drd_init(struct st_dwc3 *dwc3_data)
 	switch (dwc3_data->dr_mode) {
 	case USB_DR_MODE_PERIPHERAL:
 
-		val &= ~(USB3_FORCE_VBUSVALID | USB3_DELAY_VBUSVALID
+		val &= ~(USB3_DELAY_VBUSVALID
 			| USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3)
 			| USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2
 			| USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
 
-		val |= USB3_DEVICE_NOT_HOST;
+		/*
+		 * USB3_PORT2_FORCE_VBUSVALID When '1' and when
+		 * USB3_PORT2_DEVICE_NOT_HOST = 1, forces VBUSVLDEXT2 input
+		 * of the pico PHY to 1.
+		 */
+
+		val |= USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID;
 		break;
 
 	case USB_DR_MODE_HOST:
-- 
1.9.1



From dianders at chromium.org  Wed May 11 09:35:29 2016
From: dianders at chromium.org (Doug Anderson)
Date: Wed, 11 May 2016 09:35:29 -0700
Subject: [PATCH v8 6/8] dt-bindings: i2c: rk3x: add support for rk3399
In-Reply-To: <1462908647-27236-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908647-27236-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=VzL8AfzUnPYgsf_NqPgbp2_o_qJC7-DWHmekWVQ-Es=A@mail.gmail.com>

Hi,

On Tue, May 10, 2016 at 12:30 PM, David Wu <david.wu at rock-chips.com> wrote:
> The bus clock and function clock are separated at rk3399,
> and others use one clock as the bus clock and function clock.
>
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> Reviewed-by: Douglas Anderson <dianders at chromium.org>
> ---
> Change in v8:
> - remove error description.
>
>  Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 16 +++++++++++++---
>  1 file changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> index 0b4a85f..5429301 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> +++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> @@ -6,10 +6,20 @@ RK3xxx SoCs.
>  Required properties :
>
>   - reg : Offset and length of the register set for the device
> - - compatible : should be "rockchip,rk3066-i2c", "rockchip,rk3188-i2c",
> -               "rockchip,rk3228-i2c" or "rockchip,rk3288-i2c".
> + - compatible: should be one of the following:
> +   - "rockchip,rk3066-i2c": for rk3066
> +   - "rockchip,rk3188-i2c": for rk3188
> +   - "rockchip,rk3228-i2c": for rk3228
> +   - "rockchip,rk3288-i2c": for rk3288
> +   - "rockchip,rk3399-i2c": for rk3399
>   - interrupts : interrupt number
> - - clocks : parent clock
> + - clocks: See ../clock/clock-bindings.txt
> +   - For older hardware (rk3066, rk3188, rk3228, rk3288):
> +     - There is one clock that's used both to derive the functional clock
> +       for the device and as the bus clock.
> +   - For newer hardware (rk3399): specified by name
> +     - "i2c": REQUIRED. This is used to derive the functional clock.
> +     - "pclk": REQUIRED. This is the bus clock.

Depending on what Rob thinks, it might make sense to remove the above
two "REQUIRED" bits.  That would match his earlier feedback since
we're still in the "Required" section and thus it is redundant.

-Doug


From peter.griffin at linaro.org  Wed May 11 09:40:16 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 11 May 2016 17:40:16 +0100
Subject: [PATCH] ARM: STi: Update machine _namestr to be more generic.
Message-ID: <1462984816-705-1-git-send-email-peter.griffin@linaro.org>

This string is used by dump_stack and as we now support
more SoC's than just STiH415/6 it is misleading to have
the current string in the stack trace.

This patch updates it to be more generic for the STi
family of SoCs.

So instead of looking like this

[  271.672555] Hardware name: STiH415/416 SoC with Flattened Device Tree
[  271.678998] [<c0310490>] (unwind_backtrace) from [<c030bb54>] (show_stack+0x10/0x14)
[  271.686746] [<c030bb54>] (show_stack) from [<c058bc4c>] (dump_stack+0x98/0xac)
[snip]

it now looks like this:

[    2.669879] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.6.0-rc3-00026-g38a1ce6-dirty #76
[    2.677973] Hardware name: STi SoC with Flattened Device Tree
[    2.683723] [<c0310490>] (unwind_backtrace) from [<c030bb54>] (show_stack+0x10/0x14)
[    2.691472] [<c030bb54>] (show_stack) from [<c058bc0c>] (dump_stack+0x98/0xac)
[snip]

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 arch/arm/mach-sti/board-dt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-sti/board-dt.c b/arch/arm/mach-sti/board-dt.c
index ae10fb2..cfee0ef 100644
--- a/arch/arm/mach-sti/board-dt.c
+++ b/arch/arm/mach-sti/board-dt.c
@@ -23,7 +23,7 @@ static const char *const stih41x_dt_match[] __initconst = {
 	NULL
 };
 
-DT_MACHINE_START(STM, "STiH415/416 SoC with Flattened Device Tree")
+DT_MACHINE_START(STM, "STi SoC with Flattened Device Tree")
 	.dt_compat	= stih41x_dt_match,
 	.l2c_aux_val	= L2C_AUX_CTRL_SHARED_OVERRIDE |
 			  L310_AUX_CTRL_DATA_PREFETCH |
-- 
1.9.1



From colin.king at canonical.com  Wed May 11 09:56:54 2016
From: colin.king at canonical.com (Colin King)
Date: Wed, 11 May 2016 17:56:54 +0100
Subject: [PATCH] arm64: do not enforce strict 16 byte alignment to stack
 pointer
Message-ID: <1462985814-16146-1-git-send-email-colin.king@canonical.com>

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

copy_thread should not be enforcing 16 byte aligment and returning
-EINVAL. Other architectures trap misaligned stack access with SIGBUS
so arm64 should follow this convention, so remove the strict enforcement
check.

For example, currently clone(2) fails with -EINVAL when passing
a misaligned stack and this gives little clue to what is wrong. Instead,
it is arguable that a SIGBUS on the fist access to a misaligned stack
allows one to figure out that it is a misaligned stack issue rather
than trying to figure out why an unconventional (and undocumented)
-EINVAL is being returned.

Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
 arch/arm64/kernel/process.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 5655f756..8414971 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -258,9 +258,6 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
 		if (stack_start) {
 			if (is_compat_thread(task_thread_info(p)))
 				childregs->compat_sp = stack_start;
-			/* 16-byte aligned stack mandatory on AArch64 */
-			else if (stack_start & 15)
-				return -EINVAL;
 			else
 				childregs->sp = stack_start;
 		}
-- 
2.8.1



From catalin.marinas at arm.com  Wed May 11 09:59:01 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 11 May 2016 17:59:01 +0100
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <5842999.Zgpfq4gkVz@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <57329320.1000500@huawei.com> <20160511075438.GA15628@yury-N73SV>
 <5842999.Zgpfq4gkVz@wuerfel>
Message-ID: <20160511165900.GM3051@e104818-lin.cambridge.arm.com>

On Wed, May 11, 2016 at 12:55:01PM +0200, Arnd Bergmann wrote:
> On Wednesday 11 May 2016 11:04:38 Yury Norov wrote:
> > On Wed, May 11, 2016 at 10:04:16AM +0800, Zhangjian (Bamvor) wrote:
> > [...]
> > 
> > > >>Ok, I will test the ltp syscall test.
> > > >>With this changes, the issue I mentioned should be fixed. But we still
> > > >>use mmap2 syscall for ILP32 application when we pass the offset instead
> > > >>of page offset. Is it correct?
> > > >
> > > >I don't remember. It's probably not important whether we have the shift
> > > >in there, as long as it's independent of the actual kernel page size and
> > > >user space and kernel agree on the calling conventions.
> > > Well. I am ok with where to shift the pages size because we get the same
> > > result. I was just thinking if we should get rid of the name of mmap2 in our
> > > ILP32 porting. Actually, it is mmap but we name it as mmap2. User may confused
> > > if they do not know the implementations.
> > > 
> > 
> > This is what generic unistd.h does. If you want to change it, you'd
> > change each arch that uses generic unistd.h.
> 
> Generic unistd.h has this:
> 
> #ifdef __SYSCALL_COMPAT
> #define __SC_COMP_3264(_nr, _32, _64, _comp) __SYSCALL(_nr, _comp)
> #else
> #define __SC_COMP_3264(_nr, _32, _64, _comp) __SC_3264(_nr, _32, _64)
> #endif
> 
> #define __NR3264_mmap 222
> __SC_3264(__NR3264_mmap, sys_mmap2, sys_mmap)
> 
> 
> #if __BITS_PER_LONG == 64 && !defined(__SYSCALL_COMPAT)
> #define __NR_mmap __NR3264_mmap
> #else
> #define __NR_mmap2 __NR3264_mmap
> #endif
> 
> So by default we get __NR_mmap2 and sys_mmap2 on 32-bit ABIs, but
> __NR_mmap and sys_mmap on 64-bit ABIs, as it should be.
> 
> The problem is that arch/arm64/kernel/sys_ilp32.c now overrides
> this to use __NR_mmap2 with sys_mmap, so we have a mismatch. I think
> we should either override both the implementation and the number,
> or neither of them.

I would vote for "neither of them" (so we use __NR_mmap2 and sys_mmap2)
to keep it close to new 32-bit architectures, even though we would have
some shifts by 12 in both glibc and kernel.

-- 
Catalin


From broonie at kernel.org  Wed May 11 10:27:33 2016
From: broonie at kernel.org (Mark Brown)
Date: Wed, 11 May 2016 18:27:33 +0100
Subject: Applied "spi: dw-pci: Spelling s/paltforms/platforms/g" to the spi
 tree
In-Reply-To: <1462906798-27993-3-git-send-email-geert+renesas@glider.be>
Message-ID: <E1b0Xv3-0000TA-HX@debutante>

The patch

   spi: dw-pci: Spelling s/paltforms/platforms/g

has been applied to the spi tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 3208a1ccb23018c650ff9e08c4bd1c8b01f6d8f1 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas at glider.be>
Date: Tue, 10 May 2016 20:59:58 +0200
Subject: [PATCH] spi: dw-pci: Spelling s/paltforms/platforms/g

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 drivers/spi/spi-dw-pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c
index 332ccb0539a7..ef7db75c92c1 100644
--- a/drivers/spi/spi-dw-pci.c
+++ b/drivers/spi/spi-dw-pci.c
@@ -67,7 +67,7 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dws->irq = pdev->irq;
 
 	/*
-	 * Specific handling for paltforms, like dma setup,
+	 * Specific handling for platforms, like dma setup,
 	 * clock rate, FIFO depth.
 	 */
 	if (desc) {
-- 
2.8.1



From absahu at codeaurora.org  Wed May 11 10:34:17 2016
From: absahu at codeaurora.org (Abhishek Sahu)
Date: Wed, 11 May 2016 23:04:17 +0530
Subject: [PATCH 1/2] i2c: qup: Cleared the error bits in ISR
In-Reply-To: <000701d1ab9d$df9b3100$9ed19300$@codeaurora.org>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
 <1462797871-8595-2-git-send-email-absahu@codeaurora.org>
 <000701d1ab9d$df9b3100$9ed19300$@codeaurora.org>
Message-ID: <934365f2bd30f242d8548e2a27483679@codeaurora.org>

On 2016-05-11 21:27, Sricharan wrote:
> Hi,
> 
>> 1. Current QCOM I2C driver hangs when sending data to address 
>> 0x03-0x07
>> in some scenarios. The QUP controller generates invalid write in this
>> case,
>> since these addresses are reserved for different bus formats.
>> 
>> 2. Also, the error handling is done by I2C QUP ISR in the case of DMA
>> mode.
>> The state need to be RESET in case of any error for clearing the 
>> available
>> data in FIFO, which otherwise leaves the BAM DMA controller in hang 
>> state.
>> 
>> This patch fixes the above two issues by clearing the error bits from 
>> I2C
>> and
>> QUP status in ISR in case of I2C error, QUP error and resets the QUP 
>> state
>> to
>> clear the FIFO data.
>> 
>> Signed-off-by: Abhishek Sahu <absahu at codeaurora.org>
>> ---
>>  drivers/i2c/busses/i2c-qup.c | 14 ++++++++------
>>  1 file changed, 8 insertions(+), 6 deletions(-)
>> 
>> diff --git a/drivers/i2c/busses/i2c-qup.c 
>> b/drivers/i2c/busses/i2c-qup.c
>> index
>> 23eaabb..8c2f1bc 100644
>> --- a/drivers/i2c/busses/i2c-qup.c
>> +++ b/drivers/i2c/busses/i2c-qup.c
>> @@ -213,14 +213,16 @@ static irqreturn_t qup_i2c_interrupt(int irq, 
>> void
>> *dev)
>>  	bus_err &= I2C_STATUS_ERROR_MASK;
>>  	qup_err &= QUP_STATUS_ERROR_FLAGS;
>> 
>> -	if (qup_err) {
>> -		/* Clear Error interrupt */
>> +	/* Clear the error bits in QUP_ERROR_FLAGS */
>> +	if (qup_err)
>>  		writel(qup_err, qup->base + QUP_ERROR_FLAGS);
>> -		goto done;
>> -	}
>> 
>> -	if (bus_err) {
>> -		/* Clear Error interrupt */
>> +	/* Clear the error bits in QUP_I2C_STATUS */
>> +	if (bus_err)
>> +		writel(bus_err, qup->base + QUP_I2C_STATUS);
>> +
>> +	/* Reset the QUP State in case of error */
>> +	if (qup_err || bus_err) {
>>  		writel(QUP_RESET_STATE, qup->base + QUP_STATE);
>>  		goto done;
>>  	}
>        In qup_i2c_xfer and qup_i2c_xfer_v2 state is set to RESET at the 
> end, when
>        there is no error. So would it be fine if we do it there 
> unconditionally ?
> 
> Regards,
>  Sricharan

RESET the QUP state wouldn't create any issue in the case of multiple 
calls.
The existing code also RESET the QUP state for bus_err but it is not 
clearing
status bits.

-- 
Abhishek Sahu


From dianders at chromium.org  Wed May 11 10:37:57 2016
From: dianders at chromium.org (Doug Anderson)
Date: Wed, 11 May 2016 10:37:57 -0700
Subject: [PATCH v8 7/8] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <1462908698-27284-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908698-27284-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=Uf-U3RBpgFbR3LkPAJTWqz3d02+H7iyA-SS-y=r3cXjA@mail.gmail.com>

Hi,

On Tue, May 10, 2016 at 12:31 PM, David Wu <david.wu at rock-chips.com> wrote:
>  static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
>  {
>         struct i2c_timings *t = &i2c->t;
>         struct rk3x_i2c_calced_timings calc;
>         u64 t_low_ns, t_high_ns;
> +       u32 val;
>         int ret;
>
> -       ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
> +       ret = i2c->soc_data->calc_timings(clk_rate, t, &calc);
>         WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
>
> -       clk_enable(i2c->clk);
> +       clk_enable(i2c->pclk);
> +
>         i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
>                    REG_CLKDIV);
> -       clk_disable(i2c->clk);
> +
> +       val = i2c_readl(i2c, REG_CON);
> +       val &= ~REG_CON_TUNING_MASK;
> +       val |= calc.tuning;
> +       i2c_writel(i2c, val, REG_CON);

Another subtle bug here.  You need to be holding the spinlock here
since you're doing a read-modify-write of a register that is also
touched by the interrupt handler.  We never needed it before because
the previous register update wasn't touched by anyone else and it was
a single atomic write.

Also: technically if we are midway through a transfer when all this
happens then there will be a very short period of time when the two
timing-related registers won't match with each other.  I have no idea
how much that would matter, but in the very least it seems wise to
minimize the time where they mismatch.  So I'd probably write:

       spin_lock_irqsave(&i2c->lock, flags);
       val = i2c_readl(i2c, REG_CON);
       val &= ~REG_CON_TUNING_MASK;
       val |= calc.tuning;
       i2c_writel(i2c, val, REG_CON);
       i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
                  REG_CLKDIV);
       spin_unlock_irqrestore(&i2c->lock, flags);

...if we really end up with on a system with a dynamically changing
clock that uses the new-style timing and we see real problems, we can
always try to come up with a way to avoid any problems.  Sound OK?


Otherwise, I think things look good to me.  Caesar's comments would
also be good to fix.


-Doug


From slemieux.tyco at gmail.com  Wed May 11 10:40:00 2016
From: slemieux.tyco at gmail.com (Sylvain Lemieux)
Date: Wed, 11 May 2016 13:40:00 -0400
Subject: [PATCH] gpio: lpc32xx: disable broken to_irq support
Message-ID: <1462988400-21738-1-git-send-email-slemieux.tyco@gmail.com>

From: Sylvain Lemieux <slemieux at tycoint.com>

The "to_irq" functionality is broken inside this driver since commit
76ba59f8366f ("genirq: Add irq_domain-aware core IRQ handler").

The addition of the new lpc32xx irqchip driver in 4.7, fixed the
lpc32xx platform interrupt issue.

When switching to the new lpc32xx irqchip driver, a warning appear
in the lpc32xx gpio driver: warning: "NR_IRQS" redefined.

To remove this warning (temporary solution), this patch
disables the broken "to_irq" mapping functionality support.

Signed-off-by: Sylvain Lemieux <slemieux at tycoint.com>
---
Note:
* For details on the lpc32xx irqchip patch, refer to:
  http://thread.gmane.org/gmane.linux.drivers.devicetree/165620

* The final solution is to replace the existing lpc32xx gpio driver.
  This work is currently in progress; refer to the following URL:
  http://thread.gmane.org/gmane.linux.drivers.devicetree/144696

 drivers/gpio/gpio-lpc32xx.c | 48 +--------------------------------------------
 1 file changed, 1 insertion(+), 47 deletions(-)

diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index d39014d..fc5f197 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -29,7 +29,6 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <mach/irqs.h>
 
 #define LPC32XX_GPIO_P3_INP_STATE		_GPREG(0x000)
 #define LPC32XX_GPIO_P3_OUTP_SET		_GPREG(0x004)
@@ -371,61 +370,16 @@ static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
 
 static int lpc32xx_gpio_to_irq_p01(struct gpio_chip *chip, unsigned offset)
 {
-	return IRQ_LPC32XX_P0_P1_IRQ;
+	return -ENXIO;
 }
 
-static const char lpc32xx_gpio_to_irq_gpio_p3_table[] = {
-	IRQ_LPC32XX_GPIO_00,
-	IRQ_LPC32XX_GPIO_01,
-	IRQ_LPC32XX_GPIO_02,
-	IRQ_LPC32XX_GPIO_03,
-	IRQ_LPC32XX_GPIO_04,
-	IRQ_LPC32XX_GPIO_05,
-};
-
 static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset)
 {
-	if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpio_p3_table))
-		return lpc32xx_gpio_to_irq_gpio_p3_table[offset];
 	return -ENXIO;
 }
 
-static const char lpc32xx_gpio_to_irq_gpi_p3_table[] = {
-	IRQ_LPC32XX_GPI_00,
-	IRQ_LPC32XX_GPI_01,
-	IRQ_LPC32XX_GPI_02,
-	IRQ_LPC32XX_GPI_03,
-	IRQ_LPC32XX_GPI_04,
-	IRQ_LPC32XX_GPI_05,
-	IRQ_LPC32XX_GPI_06,
-	IRQ_LPC32XX_GPI_07,
-	IRQ_LPC32XX_GPI_08,
-	IRQ_LPC32XX_GPI_09,
-	-ENXIO, /* 10 */
-	-ENXIO, /* 11 */
-	-ENXIO, /* 12 */
-	-ENXIO, /* 13 */
-	-ENXIO, /* 14 */
-	-ENXIO, /* 15 */
-	-ENXIO, /* 16 */
-	-ENXIO, /* 17 */
-	-ENXIO, /* 18 */
-	IRQ_LPC32XX_GPI_19,
-	-ENXIO, /* 20 */
-	-ENXIO, /* 21 */
-	-ENXIO, /* 22 */
-	-ENXIO, /* 23 */
-	-ENXIO, /* 24 */
-	-ENXIO, /* 25 */
-	-ENXIO, /* 26 */
-	-ENXIO, /* 27 */
-	IRQ_LPC32XX_GPI_28,
-};
-
 static int lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip *chip, unsigned offset)
 {
-	if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpi_p3_table))
-		return lpc32xx_gpio_to_irq_gpi_p3_table[offset];
 	return -ENXIO;
 }
 
-- 
1.8.3.1



From absahu at codeaurora.org  Wed May 11 10:43:58 2016
From: absahu at codeaurora.org (Abhishek Sahu)
Date: Wed, 11 May 2016 23:13:58 +0530
Subject: [PATCH 2/2] i2c: qup: Fixed the DMA segments length
In-Reply-To: <000b01d1aba0$c2fea380$48fbea80$@codeaurora.org>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
 <1462797871-8595-3-git-send-email-absahu@codeaurora.org>
 <000b01d1aba0$c2fea380$48fbea80$@codeaurora.org>
Message-ID: <699f798ccc0a7d36640cef42ac26a697@codeaurora.org>

On 2016-05-11 21:48, Sricharan wrote:
> Hi,
> 
>> 1. The current QCOM I2C driver code is failing for transfer length 
>> greater
>> than 255. This is happening due to improper segments length as the I2C 
>> DMA
>> segments can be maximum of 256 bytes.
>> 
>> 2. The transfer length tlen was being initialized with 0 for 256 
>> bytes,
>> which is
>> being passed for DMA mappings resulting in improper DMA mapping 
>> length.
>> 
>> This patch fixes the above said problems by initializing the block 
>> count
>> with
>> the values calculated in qup_i2c_set_blk_data and calculating the
> remaining
>> length for last DMA segment. Also, the block data length need to be
>> decremented after each transfer. Additionally, this patch corrects the
>> tlen
>> assignment for DMA mapping.
>> 
>> Signed-off-by: Abhishek Sahu <absahu at codeaurora.org>
>> ---
>>  drivers/i2c/busses/i2c-qup.c | 12 +++++++-----
>>  1 file changed, 7 insertions(+), 5 deletions(-)
>> 
>> diff --git a/drivers/i2c/busses/i2c-qup.c 
>> b/drivers/i2c/busses/i2c-qup.c
>> index
>> 8c2f1bc..6d6b7dc 100644
>> --- a/drivers/i2c/busses/i2c-qup.c
>> +++ b/drivers/i2c/busses/i2c-qup.c
>> @@ -651,23 +651,24 @@ static int qup_i2c_bam_do_xfer(struct
>> qup_i2c_dev *qup, struct i2c_msg *msg,
>>  	u8 *tags;
>> 
>>  	while (idx < num) {
>> -		blocks = (msg->len + limit) / limit;
>> -		rem = msg->len % limit;
>>  		tx_len = 0, len = 0, i = 0;
>> 
>>  		qup->is_last = (idx == (num - 1));
>> 
>>  		qup_i2c_set_blk_data(qup, msg);
>> 
>> +		blocks = qup->blk.count;
>> +		rem = msg->len - (blocks - 1) * limit;
>> +
>       Same if we had blocks = (msg->len + limit - 1) / limit instead of 
> the
> above ?
Yes. We calculating this inside qup_i2c_set_blk_data and assigning the 
same value to
qup->blk.count so I am using this to avoid redundant arithmetic 
operations.
>      Otherwise,
>      Reviewed-by: Sricharan at codeaurora.org
> 
> Regards,
>  Sricharan

-- 
Abhishek Sahu


From khilman at baylibre.com  Wed May 11 10:57:28 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 11 May 2016 19:57:28 +0200
Subject: [PATCH v5 3/4] ARM: dts: meson8b: Add MMC nodes
In-Reply-To: <1456596108-1406-4-git-send-email-carlo@caione.org> (Carlo
 Caione's message of "Sat, 27 Feb 2016 19:01:47 +0100")
References: <1456596108-1406-1-git-send-email-carlo@caione.org>
 <1456596108-1406-4-git-send-email-carlo@caione.org>
Message-ID: <m24ma47a0n.fsf@baylibre.com>

Hi Carlo,

Carlo Caione <carlo at caione.org> writes:

> From: Carlo Caione <carlo at endlessm.com>
>
> Enable the MMC for the Meson8b platforms.
>
> Signed-off-by: Carlo Caione <carlo at endlessm.com>

[...]

> diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
> index 8bad557..25d795c 100644
> --- a/arch/arm/boot/dts/meson8b.dtsi
> +++ b/arch/arm/boot/dts/meson8b.dtsi
> @@ -187,6 +187,22 @@
>  					function = "uart_ao";
>  				};
>  			};
> +
> +			mmc0_sd_b_pins: mmc0_sd_b {
> +				mux {
> +					groups = "sd_d1_b", "sd_d0_b", "sd_clk_b", "sd_cmd_b",
> +						 "sd_d3_b", "sd_d2_b";
> +					function = "sd_b";
> +				};
> +			};

These pins are added under pinctrl_aobus, but in the pinctrl driver,
they're under cbus.  If I move this into the pinctrl_cbus node, I get it
to work on my odroid-c1, and am able to mount/use an MMC rootfs.

Kevin


From carlo at caione.org  Wed May 11 11:05:02 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 11 May 2016 20:05:02 +0200
Subject: [PATCH v5 3/4] ARM: dts: meson8b: Add MMC nodes
In-Reply-To: <m24ma47a0n.fsf@baylibre.com>
References: <1456596108-1406-1-git-send-email-carlo@caione.org>
 <1456596108-1406-4-git-send-email-carlo@caione.org>
 <m24ma47a0n.fsf@baylibre.com>
Message-ID: <CAOQ7t2ZjezqApQMSmbGQuoo8Lw8Fvrj8E1pfR+Dew=mVqr=eCw@mail.gmail.com>

On Wed, May 11, 2016 at 7:57 PM, Kevin Hilman <khilman at baylibre.com> wrote:
> Hi Carlo,
>
> Carlo Caione <carlo at caione.org> writes:
>
>> From: Carlo Caione <carlo at endlessm.com>
>>
>> Enable the MMC for the Meson8b platforms.
>>
>> Signed-off-by: Carlo Caione <carlo at endlessm.com>
>
> [...]
>
>> diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
>> index 8bad557..25d795c 100644
>> --- a/arch/arm/boot/dts/meson8b.dtsi
>> +++ b/arch/arm/boot/dts/meson8b.dtsi
>> @@ -187,6 +187,22 @@
>>                                       function = "uart_ao";
>>                               };
>>                       };
>> +
>> +                     mmc0_sd_b_pins: mmc0_sd_b {
>> +                             mux {
>> +                                     groups = "sd_d1_b", "sd_d0_b", "sd_clk_b", "sd_cmd_b",
>> +                                              "sd_d3_b", "sd_d2_b";
>> +                                     function = "sd_b";
>> +                             };
>> +                     };
>
> These pins are added under pinctrl_aobus, but in the pinctrl driver,
> they're under cbus.  If I move this into the pinctrl_cbus node, I get it
> to work on my odroid-c1, and am able to mount/use an MMC rootfs.

Ouch, thank you for pointing this out, I'll fix it in v6.

thanks,

-- 
Carlo Caione


From k.kozlowski.k at gmail.com  Wed May 11 11:14:00 2016
From: k.kozlowski.k at gmail.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 20:14:00 +0200
Subject: [PATCH v3 00/27] ARM: dts: exynos: Add initial support for
 Odroid XU
In-Reply-To: <09dcc771-40e2-8be0-de73-bc1db37d6804@osg.samsung.com>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
 <09dcc771-40e2-8be0-de73-bc1db37d6804@osg.samsung.com>
Message-ID: <20160511181400.GA8265@kozik-lap>

On Wed, May 11, 2016 at 11:41:34AM -0400, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 05/10/2016 04:09 PM, Krzysztof Kozlowski wrote:
> > Hi,
> > 
> > Patchset adds necessary clocks, reorganizes existing stuff and finally
> > adds Odroid XU support.
> > 
> > 
> > Changes since v2
> > ================
> > 1. Got global-ack from Stephen for the clock changes. I think merging
> >    everything through arm-soc might be the easiest but:
> >    a. In such case I will prepare a tag with clock changes,
> >    b. Anyway I will wait for response from Sylwester and Tomasz.
> > 2. Applied comments from Javier and added his Reviewed-by.
> > 3. Patch 22: added ack from Rob.
> > 4. Minor improvements in existing patches.
> > 5. Five new patches at the end: 23-27 (not reviewed yet).
> >    Some of them could be squashed with existing ones but existing
> >    changes got reviews. Although the final Odroid XU DTS works fine but
> >    in general this is still work-in-progress so I suspect it will grow.
> >    I am releasing it early following Linux concept. :)
> > 
> > Patchset is available at my private repo @github:
> > https://github.com/krzk/linux.git for-next/odroid-xu-v3
> > 
> 
> I have tested this branch on both an Exynos5422 Odroid XU4 board and an
> Exynos5800 Peach Pi Chromebook. All the peripherals are working correctly.
> 
> So for all patches affecting Exynos54xx/5800 (9,12,13,14,16,19,20,21,25):
> 
> Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>

Thanks!

Best regards,
Krzysztof


From matthew at mattleach.net  Wed May 11 11:18:31 2016
From: matthew at mattleach.net (Matthew Leach)
Date: Wed, 11 May 2016 19:18:31 +0100
Subject: [PATCH] ARM: dts: exynos: Enable AX88760 USB hub on Origen board
In-Reply-To: <1462950412-16681-1-git-send-email-k.kozlowski@samsung.com>
 (Krzysztof Kozlowski's message of "Wed, 11 May 2016 09:06:52 +0200")
References: <1462950412-16681-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <87y47gwj9k.fsf@mattleach.net>

Hi Krzysztof,

Sorry for not acting on the feedback sooner - I lost the email in my
Inbox!

I've tested the patch on my Origen board and it works fine.  One small
comment in-line.

Krzysztof Kozlowski <k.kozlowski at samsung.com> writes:

> From: Matthew Leach <matthew at mattleach.net>
>
> Enable the Origen's usb phy and ohci devices in the device tree.  Also
> add the "samsung,vbus-gpio" property to enable the GPX3(5) gpio pin so
> the AX88760 hub is powered.
>
> Signed-off-by: Matthew Leach <matthew at mattleach.net>
> [k.kozlowski: Extend nodes by label notation instead of path]
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---
>  arch/arm/boot/dts/exynos4412-origen.dts | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>
> diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts
> index 8bca699b7f20..4c59bdb0e6f3 100644
> --- a/arch/arm/boot/dts/exynos4412-origen.dts
> +++ b/arch/arm/boot/dts/exynos4412-origen.dts
> @@ -77,12 +77,29 @@
>  			clock-frequency = <24000000>;
>  		};
>  	};
> +

I think we could loose this line break?

Thanks,
-- 
Matt


From heiko at sntech.de  Wed May 11 11:20:56 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 11 May 2016 20:20:56 +0200
Subject: [PATCH v8 6/8] dt-bindings: i2c: rk3x: add support for rk3399
In-Reply-To: <1462908647-27236-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908647-27236-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1949934.3LNZYXcpHY@phil>

Am Mittwoch, 11. Mai 2016, 03:30:47 schrieb David Wu:
> The bus clock and function clock are separated at rk3399,
> and others use one clock as the bus clock and function clock.
> 
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> Reviewed-by: Douglas Anderson <dianders at chromium.org>

I'd second what Doug said wrt. the removal of the unnecessary "REQUIRED" 
statements of the clock names, especially as the surrounding text makes that 
requirement pretty clear.

Otherwiese looks nice, so

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

> ---
> Change in v8:
> - remove error description.
> 
>  Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 16 +++++++++++++---
>  1 file changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt index
> 0b4a85f..5429301 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> +++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
> @@ -6,10 +6,20 @@ RK3xxx SoCs.
>  Required properties :
> 
>   - reg : Offset and length of the register set for the device
> - - compatible : should be "rockchip,rk3066-i2c", "rockchip,rk3188-i2c",
> -		"rockchip,rk3228-i2c" or "rockchip,rk3288-i2c".
> + - compatible: should be one of the following:
> +   - "rockchip,rk3066-i2c": for rk3066
> +   - "rockchip,rk3188-i2c": for rk3188
> +   - "rockchip,rk3228-i2c": for rk3228
> +   - "rockchip,rk3288-i2c": for rk3288
> +   - "rockchip,rk3399-i2c": for rk3399
>   - interrupts : interrupt number
> - - clocks : parent clock
> + - clocks: See ../clock/clock-bindings.txt
> +   - For older hardware (rk3066, rk3188, rk3228, rk3288):
> +     - There is one clock that's used both to derive the functional clock
> +       for the device and as the bus clock.
> +   - For newer hardware (rk3399): specified by name
> +     - "i2c": REQUIRED. This is used to derive the functional clock.
> +     - "pclk": REQUIRED. This is the bus clock.
> 
>  Required on RK3066, RK3188 :



From serveralex at gmail.com  Wed May 11 11:27:02 2016
From: serveralex at gmail.com (=?utf-8?Q?Alexander_M=C3=BCller?=)
Date: Wed, 11 May 2016 20:27:02 +0200
Subject: [PATCH 0/6] Enable ethernet support on Amlogic meson8b /
 Hardkernel ODROID-C1
In-Reply-To: <m2eg989b27.fsf@baylibre.com>
References: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
 <m2eg989b27.fsf@baylibre.com>
Message-ID: <7BE15397-BC3A-49D2-9FB3-6086BDB8E31E@gmail.com>

Sure. I separated the clock patches and sent them to the linux-clk mailing list:

http://permalink.gmane.org/gmane.linux.kernel.clk/6398

Alex

> On 11 May 2016, at 11:52, Kevin Hilman <khilman at baylibre.com> wrote:
> 
> Alexander M?ller <serveralex at gmail.com> writes:
> 
>> This patch series fixes a glitch in the pinctrl driver, adds clock gates
>> support and configures ethernet support via stmmac.
>> 
>> The previously sent patch "pinctrl: meson: Fix eth_tx_en bit index" is
>> also included in this patch series.
> 
> Tested-by: Kevin Hilman <khilman at baylibre.com>
> 
> I tested ethernet support on my odroidc1 with an NFS root and things are
> working well.
> 
> Alexander, could you separate out the clock patches and (re)send them
> making sure to copy the linux-clk list so the clock maintainers are sure
> to see them?  Thanks.
> 
> Kevin
> 
>> 
>> Alexander M?ller (6):
>>  pinctrl: meson: Fix eth_tx_en bit index
>>  ARM: DTS: Amlogic: Add ethernet pins
>>  ARM: clk: Amlogic: Add support for clock gates
>>  ARM: clk: Amlogic: Add clk81 clock gates
>>  ARM: DTS: Amlogic: Enable ethernet on meson8b
>>  ARM: DTS: Amlogic: Enable ethernet on ODROID-C1
>> 
>> arch/arm/boot/dts/meson8b-odroidc1.dts   |  10 ++
>> arch/arm/boot/dts/meson8b.dtsi           |  25 ++++
>> drivers/clk/meson/clkc.c                 |  18 +++
>> drivers/clk/meson/clkc.h                 |  18 +++
>> drivers/clk/meson/meson8b-clkc.c         | 196 +++++++++++++++++++++++++++++++
>> drivers/pinctrl/meson/pinctrl-meson8b.c  |   2 +-
>> include/dt-bindings/clock/meson8b-clkc.h |  99 +++++++++++++++-
>> 7 files changed, 365 insertions(+), 3 deletions(-)



From heiko at sntech.de  Wed May 11 11:26:52 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 11 May 2016 20:26:52 +0200
Subject: [PATCH v8 3/8] i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd()
In-Reply-To: <1462908252-27016-4-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908252-27016-4-git-send-email-david.wu@rock-chips.com>
Message-ID: <2477327.hJjg0APDhg@phil>

Am Mittwoch, 11. Mai 2016, 03:24:07 schrieb David Wu:
> Call rk3x_i2c_setup() before rk3x_i2c_start()

That beginning of the sentence could use a tiny improvement, like

----
rk3x_i2c_setup() gets called directly before rk3x_i2c_start()
----

to make it obvious what happens in the code.

But a nice small improvement
Reviewed-by: Heiko Stuebner <heiko at sntech.de>

> and the last thing in setup was to clean the IPD,
> so no reason to do it at the beginning of start.
> 
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> Reviewed-by: Douglas Anderson <dianders at chromium.org>
> ---
> Change in v8:
> - none
> 
>  drivers/i2c/busses/i2c-rk3x.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> index 1e2677a..9eeb4e5 100644
> --- a/drivers/i2c/busses/i2c-rk3x.c
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -174,7 +174,6 @@ static void rk3x_i2c_start(struct rk3x_i2c *i2c)
>  {
>  	u32 val;
> 
> -	rk3x_i2c_clean_ipd(i2c);
>  	i2c_writel(i2c, REG_INT_START, REG_IEN);
> 
>  	/* enable adapter with correct mode, send START condition */



From hongzhou.yang at mediatek.com  Wed May 11 11:32:26 2016
From: hongzhou.yang at mediatek.com (Hongzhou Yang)
Date: Wed, 11 May 2016 11:32:26 -0700
Subject: [PATCH 6/6] pinctrl: mt8173: set GPIO16 to usb iddig mode
In-Reply-To: <CACRpkdaeD5mk7LXEWnE0=Xute8-JA-fa4tVt4fYhujEXeq2+9w@mail.gmail.com>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462868614-20602-7-git-send-email-chunfeng.yun@mediatek.com>
 <CACRpkdaeD5mk7LXEWnE0=Xute8-JA-fa4tVt4fYhujEXeq2+9w@mail.gmail.com>
Message-ID: <1462991546.11623.3.camel@mussux00>

On Wed, 2016-05-11 at 13:56 +0200, Linus Walleij wrote:
> On Tue, May 10, 2016 at 10:23 AM, Chunfeng Yun
> <chunfeng.yun at mediatek.com> wrote:
> 
> > the default mode of GPIO16 pin is gpio, when set EINT16 to
> > IRQ_TYPE_LEVEL_HIGH, no interrupt is triggered, it can be
> > fixed when set its default mode as usb iddig.
> >
> > Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
> 

Chunfeng, GPIO16 can be used as EINT16 mode, but the pinmux should be 0.
If you want to set its default mode to iddig, you should set it in dts.

Yours,
Hongzhou



From luke.starrett at broadcom.com  Wed May 11 11:36:46 2016
From: luke.starrett at broadcom.com (Luke Starrett)
Date: Wed, 11 May 2016 14:36:46 -0400
Subject: [PATCH 1/1] arm64: Add ARM64 optimized IP checksum routine
In-Reply-To: <57332BB8.9060004@arm.com>
References: <1462904847-28369-1-git-send-email-luke.starrett@broadcom.com>
 <57332BB8.9060004@arm.com>
Message-ID: <25c62b93-672f-296f-ad8f-e8dd144a3a20@broadcom.com>

On 5/11/2016 8:55 AM, Robin Murphy wrote:
> Hi Luke,
>
> On 10/05/16 19:27, Luke Starrett wrote:
>> This change implements an optimized checksum for arm64, based loosely on
>> the original arch/arm implementation.  Load-pair is used for the initial
>> 16B load, reducing the overall number of loads to two for packets 
>> without
>> IP options.  Instruction count is reduced by ~3x compared to generic C
>> implementation.  Changes were tested against LE and BE operation and for
>> all possible mis-alignments.
>>
>> Signed-off-by: Luke Starrett <luke.starrett at broadcom.com>
>> ---
>>   arch/arm64/include/asm/checksum.h | 57 
>> +++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 57 insertions(+)
>>   create mode 100644 arch/arm64/include/asm/checksum.h
>>
>> diff --git a/arch/arm64/include/asm/checksum.h 
>> b/arch/arm64/include/asm/checksum.h
>> new file mode 100644
>> index 0000000..15629d7
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/checksum.h
>> @@ -0,0 +1,57 @@
>> +/*
>> + * Copyright 2016 Broadcom
>> + *
>> + * 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 (the "GPL").
>> + *
>> + * 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 version 2 (GPLv2) for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * version 2 (GPLv2) along with this source code.
>> + *
>> + * ip_fast_csum() loosely derived from original arch/arm implementation
>> + */
>> +
>> +#ifndef __ASM_ARM64_CHECKSUM_H
>> +#define __ASM_ARM64_CHECKSUM_H
>> +
>> +/*
>> + * This is a version of ip_compute_csum() optimized for IP headers,
>> + * which always checksum on 4 octet boundaries.
>> + */
>> +static inline __sum16
>> +ip_fast_csum(const void *iph, unsigned int ihl)
>> +{
>> +    u64 tmp, sum;
>> +
>> +    __asm__ __volatile__ (
>> +"    ldp    %0, %3, [%1], #16\n"
>> +"    sub    %2, %2, #4\n"
>> +"    adds    %0, %0, %3\n"
>> +"1:    ldr    %w3, [%1], #4\n"
>> +"    sub    %2, %2, #1\n"
>> +"    adcs    %0, %0, %3\n"
>
> This looks suspicious - the following tst is going to zero the carry 
> flag, so either setting the flags is unnecessary, or things are 
> working by chance.
>
Yes, you are correct.  Thinking about this a bit, it is working by 
chance as you expected, given the second adcs is adding a 32b quantity 
to the prior 64b result and unlikely (though not impossible) to produce 
a carry.  I'll reorder this.

>> +"    tst    %2, #15\n"
>> +"    bne    1b\n"
>> +"    adc    %0, %0, xzr\n"
>
> Similarly, you should never get here with the carry flag set, so this 
> is just a pointless nop.
>
>> +"    ror    %3, %0, #32\n"
>> +"    add     %0, %0, %3\n"
>> +"    lsr    %0, %0, #32\n"
>> +"    ror    %w3, %w0, #16\n"
>> +"    add     %w0, %w0, %w3\n"
>> +"    lsr    %0, %0, #16\n"
>> +    : "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp)
>> +    : "1" (iph), "2" (ihl)
>> +    : "cc", "memory");
>> +
>> +    return (__force __sum16)(~sum);
>> +}
>
> Given that dodginess, and that there doesn't seem to be anything here 
> which absolutely _demands_ assembly voodoo, can we not just have an 
> optimised C implementation working on larger chunks, along the lines 
> of Alpha?
>
I would agree, though I couldn't see any obvious way to reduce from 
individual loads to 'ldp' without requiring some level of inlining, and 
at that point just decided to do the whole thing inline.  It was clear 
though that reducing to a single ldp + ldr in the mainstream case was 
beneficial.

Luke


> Robin.
>
>> +
>> +#define ip_fast_csum ip_fast_csum
>> +#include <asm-generic/checksum.h>
>> +
>> +#endif    /* __ASM_ARM64_CHECKSUM_H */
>>
>



From sboyd at codeaurora.org  Wed May 11 11:40:23 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Wed, 11 May 2016 11:40:23 -0700
Subject: [GIT PULL] i.MX clock fixes for 4.6, take 2
In-Reply-To: <20160511121512.GP5874@tiger>
References: <20160503133605.GN5874@tiger>
 <20160506180217.GW3492@codeaurora.org>
 <20160511121512.GP5874@tiger>
Message-ID: <20160511184023.GE3492@codeaurora.org>

On 05/11, Shawn Guo wrote:
> On Fri, May 06, 2016 at 11:02:17AM -0700, Stephen Boyd wrote:
> > On 05/03, Shawn Guo wrote:
> > > The following changes since commit 7196c52c9377df0175b510ff5896bda524f7345e:
> > > 
> > >   clk: imx6q: fix typo in CAN clock definition (2016-04-13 15:27:15 +0800)
> > > 
> > > are available in the git repository at:
> > > 
> > >   git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-clk-fixes-4.6-2
> > > 
> > > for you to fetch changes up to 3397c2c45b1b6f54834dfeae30a73046f33ca943:
> > > 
> > >   ARM: dts: imx35: restore existing used clock enumeration (2016-04-18 12:37:21 +0800)
> > > 
> > > ----------------------------------------------------------------
> > > The i.MX clock fixes for 4.6, take 2:
> > >  - Fix the commit 3713e3f5e927 ("clk: imx35: define two clocks for rtc")
> > >    which messed up the clock enumeration when adding new clock.
> > 
> > This commit wasn't introduced in this merge window, so I'm going
> > to pull this into clk-next unless you have some justification.
> 
> That's fine.  Thanks, Stephen.

Thanks. Pulled into clk-next.

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


From carlo at caione.org  Wed May 11 11:41:04 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 11 May 2016 20:41:04 +0200
Subject: [PATCH v2 3/4] ARM64: Kconfig: Select the Amlogic Meson pin
 controller driver
In-Reply-To: <3200982.vJgYKNLqaA@wuerfel>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
 <1462176138-29433-4-git-send-email-carlo@caione.org>
 <CACRpkdbTr7YUrzSQQci929ugBhTkJKWvpjdf5Wo3HkfVKFhGLw@mail.gmail.com>
 <3200982.vJgYKNLqaA@wuerfel>
Message-ID: <CAOQ7t2aLORBKiuZEp1BZ1+O-Yr5xvM9bjkFnfA9Yn9oZZefSnw@mail.gmail.com>

On Wed, May 11, 2016 at 12:56 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> On Wednesday 11 May 2016 10:53:35 Linus Walleij wrote:
>> On Mon, May 2, 2016 at 10:02 AM, Carlo Caione <carlo at caione.org> wrote:
>>
>> > From: Carlo Caione <carlo at endlessm.com>
>> >
>> > Select the Meson pin controller driver also for the AArch64 Meson
>> > platform.
>> >
>> > Signed-off-by: Carlo Caione <carlo at endlessm.com>
>>
>> Acked-by: Linus Walleij <linus.walleij at linaro.org>
>>
>> I guess this should get merged through the ARM SoC tree.
>>
>
> I'd keep it together with the other changes for clarity and
> merge it through your tree.

Linus,
did you take it? otherwise I can merge it through my repo.

Cheers,

-- 
Carlo Caione


From k.kozlowski.k at gmail.com  Wed May 11 11:51:55 2016
From: k.kozlowski.k at gmail.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 20:51:55 +0200
Subject: [PATCH] phy: exynos-mipi-video: avoid uninitialized variable use
In-Reply-To: <1462971012-562097-1-git-send-email-arnd@arndb.de>
References: <1462971012-562097-1-git-send-email-arnd@arndb.de>
Message-ID: <20160511185155.GB8265@kozik-lap>

On Wed, May 11, 2016 at 02:49:53PM +0200, Arnd Bergmann wrote:
> A rework of the exynos-mipi-video driver caused a warning
> about the new __set_phy_state function potentially accessing
> a variable before its initialization:
> 
> drivers/phy/phy-exynos-mipi-video.c: In function '__set_phy_state':
> drivers/phy/phy-exynos-mipi-video.c:238:13: error: 'val' may be used uninitialized in this function [-Werror=maybe-uninitialized]
>   return val & data->resetn_val;
>          ~~~~^~~~~~~~~~~~~~~~~~
> drivers/phy/phy-exynos-mipi-video.c:235:6: note: 'val' was declared here
>   u32 val;
> 
> The failure scenario here is the offset passed into a the
> stub regmap_read() function that does not modify its output,
> however regmap_read() can also fail for other reasons, so
> adding error handling (in this case, returning zero from
> is_running) seems the best solution.
> 
> Note that this warning showed up with the ARM s5pv210_defconfig,
> indicating that we most likely want to either enable CONFIG_REGMAP
> in that defconfig as well, or disable the phy-exynos-mipi-video
> driver.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Fixes: 97a3042f7616 ("phy: exynos-mipi-video: Rewrite handling of phy registers")
> ---
>  drivers/phy/phy-exynos-mipi-video.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
> index cc093ebfda94..8b851f718123 100644
> --- a/drivers/phy/phy-exynos-mipi-video.c
> +++ b/drivers/phy/phy-exynos-mipi-video.c
> @@ -233,8 +233,12 @@ static inline int __is_running(const struct exynos_mipi_phy_desc *data,
>  			struct exynos_mipi_video_phy *state)
>  {
>  	u32 val;

Other way would be to initialize val=0 since there is no real error code
returned. Anyway:

Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

Best regards,
Krzysztof

> +	int ret;
> +
> +	ret = regmap_read(state->regmaps[data->resetn_map], data->resetn_reg, &val);
> +	if (ret)
> +		return 0;
>  
> -	regmap_read(state->regmaps[data->resetn_map], data->resetn_reg, &val);
>  	return val & data->resetn_val;
>  }
>  
> -- 
> 2.7.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From k.kozlowski at samsung.com  Wed May 11 11:53:38 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 11 May 2016 20:53:38 +0200
Subject: [PATCH] ARM: dts: exynos: Enable AX88760 USB hub on Origen board
In-Reply-To: <87y47gwj9k.fsf@mattleach.net>
References: <1462950412-16681-1-git-send-email-k.kozlowski@samsung.com>
 <87y47gwj9k.fsf@mattleach.net>
Message-ID: <20160511185338.GA10164@kozik-lap>

On Wed, May 11, 2016 at 07:18:31PM +0100, Matthew Leach wrote:
> Hi Krzysztof,
> 
> Sorry for not acting on the feedback sooner - I lost the email in my
> Inbox!
> 
> I've tested the patch on my Origen board and it works fine.  One small
> comment in-line.
> 
> Krzysztof Kozlowski <k.kozlowski at samsung.com> writes:
> 
> > From: Matthew Leach <matthew at mattleach.net>
> >
> > Enable the Origen's usb phy and ohci devices in the device tree.  Also
> > add the "samsung,vbus-gpio" property to enable the GPX3(5) gpio pin so
> > the AX88760 hub is powered.
> >
> > Signed-off-by: Matthew Leach <matthew at mattleach.net>
> > [k.kozlowski: Extend nodes by label notation instead of path]
> > Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> > ---
> >  arch/arm/boot/dts/exynos4412-origen.dts | 17 +++++++++++++++++
> >  1 file changed, 17 insertions(+)
> >
> > diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts
> > index 8bca699b7f20..4c59bdb0e6f3 100644
> > --- a/arch/arm/boot/dts/exynos4412-origen.dts
> > +++ b/arch/arm/boot/dts/exynos4412-origen.dts
> > @@ -77,12 +77,29 @@
> >  			clock-frequency = <24000000>;
> >  		};
> >  	};
> > +
> 
> I think we could loose this line break?

Yeah, that slipped through my fingers.

Thanks for testing,
Krzysztof


From linux at armlinux.org.uk  Wed May 11 11:56:17 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Wed, 11 May 2016 19:56:17 +0100
Subject: [PATCH 11/12] kexec: allow architectures to override boot mapping
In-Reply-To: <E1aviFU-0000jk-9q@rmk-PC.arm.linux.org.uk>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <E1aviFU-0000jk-9q@rmk-PC.arm.linux.org.uk>
Message-ID: <20160511185616.GP19428@n2100.arm.linux.org.uk>

I was going to send the patches to Andrew, but then I noticed this
one has received no acks.  What's the situation for this patch?

On Thu, Apr 28, 2016 at 10:28:40AM +0100, Russell King wrote:
> kexec physical addresses are the boot-time view of the system.  For
> certain ARM systems (such as Keystone 2), the boot view of the system
> does not match the kernel's view of the system: the boot view uses a
> special alias in the lower 4GB of the physical address space.
> 
> To cater for these kinds of setups, we need to translate between the
> boot view physical addresses and the normal kernel view physical
> addresses.  This patch extracts the current transation points into
> linux/kexec.h, and allows an architecture to override the functions.
> 
> Due to the translations required, we unfortunately end up with six
> translation functions, which are reduced down to four that the
> architecture can override.
> 
> Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
> ---
>  include/linux/kexec.h | 38 ++++++++++++++++++++++++++++++++++++++
>  kernel/kexec.c        |  3 ++-
>  kernel/kexec_core.c   | 26 +++++++++++++-------------
>  3 files changed, 53 insertions(+), 14 deletions(-)
> 
> diff --git a/include/linux/kexec.h b/include/linux/kexec.h
> index 52a3a221bcb2..99cb9dac7909 100644
> --- a/include/linux/kexec.h
> +++ b/include/linux/kexec.h
> @@ -318,6 +318,44 @@ int __weak arch_kexec_apply_relocations_add(const Elf_Ehdr *ehdr,
>  int __weak arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
>  					unsigned int relsec);
>  
> +#ifndef page_to_boot_pfn
> +static inline unsigned long page_to_boot_pfn(struct page *page)
> +{
> +	return page_to_pfn(page);
> +}
> +#endif
> +
> +#ifndef boot_pfn_to_page
> +static inline struct page *boot_pfn_to_page(unsigned long boot_pfn)
> +{
> +	return pfn_to_page(boot_pfn);
> +}
> +#endif
> +
> +#ifndef phys_to_boot_phys
> +static inline unsigned long phys_to_boot_phys(phys_addr_t phys)
> +{
> +	return phys;
> +}
> +#endif
> +
> +#ifndef boot_phys_to_phys
> +static inline phys_addr_t boot_phys_to_phys(unsigned long boot_phys)
> +{
> +	return boot_phys;
> +}
> +#endif
> +
> +static inline unsigned long virt_to_boot_phys(void *addr)
> +{
> +	return phys_to_boot_phys(__pa((unsigned long)addr));
> +}
> +
> +static inline void *boot_phys_to_virt(unsigned long entry)
> +{
> +	return phys_to_virt(boot_phys_to_phys(entry));
> +}
> +
>  #else /* !CONFIG_KEXEC_CORE */
>  struct pt_regs;
>  struct task_struct;
> diff --git a/kernel/kexec.c b/kernel/kexec.c
> index ee70aef5cd81..dd49d572a5e2 100644
> --- a/kernel/kexec.c
> +++ b/kernel/kexec.c
> @@ -48,7 +48,8 @@ static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
>  
>  	if (kexec_on_panic) {
>  		/* Verify we have a valid entry point */
> -		if ((entry < crashk_res.start) || (entry > crashk_res.end))
> +		if ((entry < phys_to_boot_phys(crashk_res.start)) ||
> +		    (entry > phys_to_boot_phys(crashk_res.end)))
>  			return -EADDRNOTAVAIL;
>  	}
>  
> diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
> index f9847e5822e6..d04940ccc58d 100644
> --- a/kernel/kexec_core.c
> +++ b/kernel/kexec_core.c
> @@ -229,8 +229,8 @@ int sanity_check_segment_list(struct kimage *image)
>  			mstart = image->segment[i].mem;
>  			mend = mstart + image->segment[i].memsz - 1;
>  			/* Ensure we are within the crash kernel limits */
> -			if ((mstart < crashk_res.start) ||
> -			    (mend > crashk_res.end))
> +			if ((mstart < phys_to_boot_phys(crashk_res.start)) ||
> +			    (mend > phys_to_boot_phys(crashk_res.end)))
>  				return result;
>  		}
>  	}
> @@ -354,7 +354,7 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image,
>  		pages = kimage_alloc_pages(KEXEC_CONTROL_MEMORY_GFP, order);
>  		if (!pages)
>  			break;
> -		pfn   = page_to_pfn(pages);
> +		pfn   = page_to_boot_pfn(pages);
>  		epfn  = pfn + count;
>  		addr  = pfn << PAGE_SHIFT;
>  		eaddr = epfn << PAGE_SHIFT;
> @@ -480,7 +480,7 @@ static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
>  			return -ENOMEM;
>  
>  		ind_page = page_address(page);
> -		*image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
> +		*image->entry = virt_to_boot_phys(ind_page) | IND_INDIRECTION;
>  		image->entry = ind_page;
>  		image->last_entry = ind_page +
>  				      ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
> @@ -535,13 +535,13 @@ void kimage_terminate(struct kimage *image)
>  #define for_each_kimage_entry(image, ptr, entry) \
>  	for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
>  		ptr = (entry & IND_INDIRECTION) ? \
> -			phys_to_virt((entry & PAGE_MASK)) : ptr + 1)
> +			boot_phys_to_virt((entry & PAGE_MASK)) : ptr + 1)
>  
>  static void kimage_free_entry(kimage_entry_t entry)
>  {
>  	struct page *page;
>  
> -	page = pfn_to_page(entry >> PAGE_SHIFT);
> +	page = boot_pfn_to_page(entry >> PAGE_SHIFT);
>  	kimage_free_pages(page);
>  }
>  
> @@ -635,7 +635,7 @@ static struct page *kimage_alloc_page(struct kimage *image,
>  	 * have a match.
>  	 */
>  	list_for_each_entry(page, &image->dest_pages, lru) {
> -		addr = page_to_pfn(page) << PAGE_SHIFT;
> +		addr = page_to_boot_pfn(page) << PAGE_SHIFT;
>  		if (addr == destination) {
>  			list_del(&page->lru);
>  			return page;
> @@ -650,12 +650,12 @@ static struct page *kimage_alloc_page(struct kimage *image,
>  		if (!page)
>  			return NULL;
>  		/* If the page cannot be used file it away */
> -		if (page_to_pfn(page) >
> +		if (page_to_boot_pfn(page) >
>  				(KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
>  			list_add(&page->lru, &image->unusable_pages);
>  			continue;
>  		}
> -		addr = page_to_pfn(page) << PAGE_SHIFT;
> +		addr = page_to_boot_pfn(page) << PAGE_SHIFT;
>  
>  		/* If it is the destination page we want use it */
>  		if (addr == destination)
> @@ -678,7 +678,7 @@ static struct page *kimage_alloc_page(struct kimage *image,
>  			struct page *old_page;
>  
>  			old_addr = *old & PAGE_MASK;
> -			old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
> +			old_page = boot_pfn_to_page(old_addr >> PAGE_SHIFT);
>  			copy_highpage(page, old_page);
>  			*old = addr | (*old & ~PAGE_MASK);
>  
> @@ -734,7 +734,7 @@ static int kimage_load_normal_segment(struct kimage *image,
>  			result  = -ENOMEM;
>  			goto out;
>  		}
> -		result = kimage_add_page(image, page_to_pfn(page)
> +		result = kimage_add_page(image, page_to_boot_pfn(page)
>  								<< PAGE_SHIFT);
>  		if (result < 0)
>  			goto out;
> @@ -795,7 +795,7 @@ static int kimage_load_crash_segment(struct kimage *image,
>  		char *ptr;
>  		size_t uchunk, mchunk;
>  
> -		page = pfn_to_page(maddr >> PAGE_SHIFT);
> +		page = boot_pfn_to_page(maddr >> PAGE_SHIFT);
>  		if (!page) {
>  			result  = -ENOMEM;
>  			goto out;
> @@ -922,7 +922,7 @@ void __weak crash_free_reserved_phys_range(unsigned long begin,
>  	unsigned long addr;
>  
>  	for (addr = begin; addr < end; addr += PAGE_SIZE)
> -		free_reserved_page(pfn_to_page(addr >> PAGE_SHIFT));
> +		free_reserved_page(boot_pfn_to_page(addr >> PAGE_SHIFT));
>  }
>  
>  int crash_shrink_memory(unsigned long new_size)
> -- 
> 2.1.0
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From maxime.ripard at free-electrons.com  Wed May 11 12:12:13 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 11 May 2016 21:12:13 +0200
Subject: [PATCH 0/2] ARM: dts: sunxi: Add display clocks to sun[47]i.dtsi
In-Reply-To: <1462908247-10474-1-git-send-email-plaes@plaes.org>
References: <1462908247-10474-1-git-send-email-plaes@plaes.org>
Message-ID: <20160511191213.GV3733@lukather>

On Tue, May 10, 2016 at 10:24:05PM +0300, Priit Laes wrote:
> Enable the display and TCON clocks that are needed to drive the display
> engine, tcon and TV encoders.
> 
> Please note that currently the parent handling for clocks using 
> 'allwinner,sun4i-a10-display-clk' compatible with number of parents !=4
> is broken (like de_[bf]e[01]_clk clocks present in patches).
> 
> Priit Laes (2):
>   ARM: sun4i: A10: Add display and TCON clocks
>   ARM: sun7i: A20: Add display and TCON clocks

Applied both for 4.8, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160511/291b88ba/attachment.sig>

From arnd at arndb.de  Wed May 11 12:30:07 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 21:30:07 +0200
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <20160511165900.GM3051@e104818-lin.cambridge.arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <5842999.Zgpfq4gkVz@wuerfel>
 <20160511165900.GM3051@e104818-lin.cambridge.arm.com>
Message-ID: <4989778.Fs81NJurjH@wuerfel>

On Wednesday 11 May 2016 17:59:01 Catalin Marinas wrote:
> On Wed, May 11, 2016 at 12:55:01PM +0200, Arnd Bergmann wrote:
> > On Wednesday 11 May 2016 11:04:38 Yury Norov wrote:
> > > On Wed, May 11, 2016 at 10:04:16AM +0800, Zhangjian (Bamvor) wrote:
> > > [...]
> > > 
> > > > >>Ok, I will test the ltp syscall test.
> > > > >>With this changes, the issue I mentioned should be fixed. But we still
> > > > >>use mmap2 syscall for ILP32 application when we pass the offset instead
> > > > >>of page offset. Is it correct?
> > > > >
> > > > >I don't remember. It's probably not important whether we have the shift
> > > > >in there, as long as it's independent of the actual kernel page size and
> > > > >user space and kernel agree on the calling conventions.
> > > > Well. I am ok with where to shift the pages size because we get the same
> > > > result. I was just thinking if we should get rid of the name of mmap2 in our
> > > > ILP32 porting. Actually, it is mmap but we name it as mmap2. User may confused
> > > > if they do not know the implementations.
> > > > 
> > > 
> > > This is what generic unistd.h does. If you want to change it, you'd
> > > change each arch that uses generic unistd.h.
> > 
> > Generic unistd.h has this:
> > 
> > #ifdef __SYSCALL_COMPAT
> > #define __SC_COMP_3264(_nr, _32, _64, _comp) __SYSCALL(_nr, _comp)
> > #else
> > #define __SC_COMP_3264(_nr, _32, _64, _comp) __SC_3264(_nr, _32, _64)
> > #endif
> > 
> > #define __NR3264_mmap 222
> > __SC_3264(__NR3264_mmap, sys_mmap2, sys_mmap)
> > 
> > 
> > #if __BITS_PER_LONG == 64 && !defined(__SYSCALL_COMPAT)
> > #define __NR_mmap __NR3264_mmap
> > #else
> > #define __NR_mmap2 __NR3264_mmap
> > #endif
> > 
> > So by default we get __NR_mmap2 and sys_mmap2 on 32-bit ABIs, but
> > __NR_mmap and sys_mmap on 64-bit ABIs, as it should be.
> > 
> > The problem is that arch/arm64/kernel/sys_ilp32.c now overrides
> > this to use __NR_mmap2 with sys_mmap, so we have a mismatch. I think
> > we should either override both the implementation and the number,
> > or neither of them.
> 
> I would vote for "neither of them" (so we use __NR_mmap2 and sys_mmap2)
> to keep it close to new 32-bit architectures, even though we would have
> some shifts by 12 in both glibc and kernel.

I don't think the shifts are a problem, the main downside would be
the limit to 44 bits of file offsets (16TB files), but it's also
unclear if that is a practical problem at all. If it is, we run
into the same problem on all other 32-bit architectures too.

	Arnd


From festevam at gmail.com  Wed May 11 12:39:30 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Wed, 11 May 2016 16:39:30 -0300
Subject: [PATCH] ARM: imx6ul: Fix Micrel PHY mask
Message-ID: <1462995570-31055-1-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam at nxp.com>

The value used for Micrel PHY mask is not correct. Use the 
MICREL_PHY_ID_MASK definition instead.

Thanks to Jiri Luznicky for proposing the fix at
https://community.freescale.com/thread/387739

Cc: <stable at vger.kernel.org>
Fixes: 709bc0657fe6f9f55 ("ARM: imx6ul: add fec MAC refrence clock and phy fixup init")
Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
---
 arch/arm/mach-imx/mach-imx6ul.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c
index a38b16b..b56de4b 100644
--- a/arch/arm/mach-imx/mach-imx6ul.c
+++ b/arch/arm/mach-imx/mach-imx6ul.c
@@ -46,7 +46,7 @@ static int ksz8081_phy_fixup(struct phy_device *dev)
 static void __init imx6ul_enet_phy_init(void)
 {
 	if (IS_BUILTIN(CONFIG_PHYLIB))
-		phy_register_fixup_for_uid(PHY_ID_KSZ8081, 0xffffffff,
+		phy_register_fixup_for_uid(PHY_ID_KSZ8081, MICREL_PHY_ID_MASK,
 					   ksz8081_phy_fixup);
 }
 
-- 
1.9.1



From bjorn.andersson at linaro.org  Wed May 11 12:49:05 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Wed, 11 May 2016 12:49:05 -0700
Subject: [Patch v4 1/8] dt/bindings: firmware: Add Qualcomm SCM binding
In-Reply-To: <1462976158-26016-2-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
 <1462976158-26016-2-git-send-email-andy.gross@linaro.org>
Message-ID: <20160511194905.GU1256@tuxbot>

On Wed 11 May 07:15 PDT 2016, Andy Gross wrote:

> This patch adds the device tree support for the Qualcomm SCM firmware.
> 
> Signed-off-by: Andy Gross <andy.gross at linaro.org>
> ---
>  .../devicetree/bindings/firmware/qcom,scm.txt      | 28 ++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/firmware/qcom,scm.txt
> 
> diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
> new file mode 100644
> index 0000000..0c5f1ff
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
> @@ -0,0 +1,28 @@
> +QCOM Secure Channel Manager (SCM)
> +
> +Qualcomm processors include an interface to communicate to the secure firmware.
> +This interface allows for clients to request different types of actions.  These
> +can include CPU power up/down, HDCP requests, loading of firmware, and other
> +assorted actions.
> +
> +Required properties:
> +- compatible: must contain one of the following:
> + * "qcom,scm-apq8064" for APQ8064 platforms
> + * "qcom,scm-msm8660" for MSM8660 platforms
> + * "qcom,scm-msm8690" for MSM8690 platforms
> + * "qcom,scm" for later processors (MSM8916, APQ8084, MSM8974, etc)
> +- clocks: One to three clocks may be required based on compatible.
> + * Only core clock required for "qcom,scm-apq8084", "qcom,scm-msm8660", and "qcom,scm-msm8960"
> + * Core, iface, and bus clocks required for "qcom,scm"
> +- clock-names: Must contain "core" for the core clock, "iface" for the interface
> +  clock and "bus" for the bus clock per the requirements of the compatible.

I like this split of generic binding and the special cases, gives the
wanted clarity for the outliers without the added churn in the common
case.

Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>

Regards,
Bjorn


From andrew at lunn.ch  Wed May 11 12:50:14 2016
From: andrew at lunn.ch (Andrew Lunn)
Date: Wed, 11 May 2016 21:50:14 +0200
Subject: [PATCH] ARM: imx6ul: Fix Micrel PHY mask
In-Reply-To: <1462995570-31055-1-git-send-email-festevam@gmail.com>
References: <1462995570-31055-1-git-send-email-festevam@gmail.com>
Message-ID: <20160511195014.GA17613@lunn.ch>

On Wed, May 11, 2016 at 04:39:30PM -0300, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam at nxp.com>
> 
> The value used for Micrel PHY mask is not correct. Use the 
> MICREL_PHY_ID_MASK definition instead.
> 
> Thanks to Jiri Luznicky for proposing the fix at
> https://community.freescale.com/thread/387739
> 
> Cc: <stable at vger.kernel.org>
> Fixes: 709bc0657fe6f9f55 ("ARM: imx6ul: add fec MAC refrence clock and phy fixup init")
> Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>

Reviewed-by: Andrew Lunn <andrew at lunn.ch>

It would be nice if drivers/net/phy/micrel.c was to use
MICREL_PHY_ID_MASK. But that is a different patch.

Thanks
	Andrew		    


From bjorn.andersson at linaro.org  Wed May 11 12:53:20 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Wed, 11 May 2016 12:53:20 -0700
Subject: [Patch v4 2/8] firmware: qcom: scm: Convert SCM to platform driver
In-Reply-To: <1462976158-26016-3-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
 <1462976158-26016-3-git-send-email-andy.gross@linaro.org>
Message-ID: <20160511195320.GV1256@tuxbot>

On Wed 11 May 07:15 PDT 2016, Andy Gross wrote:

> This patch converts the Qualcomm SCM firmware driver into a platform
> driver.
> 
> Signed-off-by: Andy Gross <andy.gross at linaro.org>

Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>

Regards,
Bjorn


From festevam at gmail.com  Wed May 11 12:53:50 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Wed, 11 May 2016 16:53:50 -0300
Subject: [PATCH] ARM: imx6ul: Fix Micrel PHY mask
In-Reply-To: <20160511195014.GA17613@lunn.ch>
References: <1462995570-31055-1-git-send-email-festevam@gmail.com>
 <20160511195014.GA17613@lunn.ch>
Message-ID: <CAOMZO5AaspTp+K6+N=fHvYDSEuUE9Ab4TQFeNtRmDtcn78sW+g@mail.gmail.com>

On Wed, May 11, 2016 at 4:50 PM, Andrew Lunn <andrew at lunn.ch> wrote:

> Reviewed-by: Andrew Lunn <andrew at lunn.ch>
>
> It would be nice if drivers/net/phy/micrel.c was to use
> MICREL_PHY_ID_MASK. But that is a different patch.

Good suggestion. I will submit a patch doing this. Thanks


From bjorn.andersson at linaro.org  Wed May 11 12:56:03 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Wed, 11 May 2016 12:56:03 -0700
Subject: [Patch v4 3/8] firmware: qcom: scm: Use atomic SCM for cold boot
In-Reply-To: <1462976158-26016-4-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
 <1462976158-26016-4-git-send-email-andy.gross@linaro.org>
Message-ID: <20160511195603.GW1256@tuxbot>

On Wed 11 May 07:15 PDT 2016, Andy Gross wrote:

> This patch changes the cold_set_boot_addr function to use atomic SCM
> calls.  cold_set_boot_addr required adding qcom_scm_call_atomic2 to
> support the two arguments going to the smc call.  Using atomic removes
> the need for memory allocation and instead places all arguments in
> registers.
> 
> Signed-off-by: Andy Gross <andy.gross at linaro.org>

Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>

Regards,
Bjorn


From vz at mleia.com  Wed May 11 12:58:14 2016
From: vz at mleia.com (Vladimir Zapolskiy)
Date: Wed, 11 May 2016 22:58:14 +0300
Subject: [PATCH] gpio: lpc32xx: disable broken to_irq support
In-Reply-To: <1462988400-21738-1-git-send-email-slemieux.tyco@gmail.com>
References: <1462988400-21738-1-git-send-email-slemieux.tyco@gmail.com>
Message-ID: <57338ED6.3090001@mleia.com>

Hi Sylvain,

On 11.05.2016 20:40, Sylvain Lemieux wrote:
> From: Sylvain Lemieux <slemieux at tycoint.com>
> 
> The "to_irq" functionality is broken inside this driver since commit
> 76ba59f8366f ("genirq: Add irq_domain-aware core IRQ handler").
> 
> The addition of the new lpc32xx irqchip driver in 4.7, fixed the
> lpc32xx platform interrupt issue.
> 
> When switching to the new lpc32xx irqchip driver, a warning appear
> in the lpc32xx gpio driver: warning: "NR_IRQS" redefined.
> 
> To remove this warning (temporary solution), this patch
> disables the broken "to_irq" mapping functionality support.
> 
> Signed-off-by: Sylvain Lemieux <slemieux at tycoint.com>
> ---
> Note:
> * For details on the lpc32xx irqchip patch, refer to:
>   http://thread.gmane.org/gmane.linux.drivers.devicetree/165620
> 
> * The final solution is to replace the existing lpc32xx gpio driver.
>   This work is currently in progress; refer to the following URL:
>   http://thread.gmane.org/gmane.linux.drivers.devicetree/144696
> 
>  drivers/gpio/gpio-lpc32xx.c | 48 +--------------------------------------------
>  1 file changed, 1 insertion(+), 47 deletions(-)
> 

the change looks good to me.

Probably all lpc32xx_gpio_to_irq* functions can be removed along with .to_irq
callback assignments, but it is up to you.


Acked-by: Vladimir Zapolskiy <vz at mleia.com>


--
With best wishes,
Vladimir


From arnd at arndb.de  Wed May 11 13:11:07 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 22:11:07 +0200
Subject: [PATCH] drm: mediatek: remove IOMMU_DMA select
In-Reply-To: <1462982509-342936-1-git-send-email-arnd@arndb.de>
References: <1462982509-342936-1-git-send-email-arnd@arndb.de>
Message-ID: <1462997501-982363-1-git-send-email-arnd@arndb.de>

We get a harmless build warning when trying to use the mediatek
DRM driver with IOMMU support disabled:

warning: (DRM_MEDIATEK) selects IOMMU_DMA which has unmet direct dependencies (IOMMU_SUPPORT)

However, the IOMMU_DMA symbol is not meant to be used by drivers
at all, and this driver doesn't seem to have a strict dependency
on it other than using the mediatek IOMMU driver that does.

Since we also want to be able to do compile tests with the
driver on other platforms, the IOMMU_DMA symbol should not
be selected here.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
If someone has a better explanation about why the 'select' is here,
let me know, it certainly seems out of place.

 drivers/gpu/drm/mediatek/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
index 0c06a69d7f04..545973f6b743 100644
--- a/drivers/gpu/drm/mediatek/Kconfig
+++ b/drivers/gpu/drm/mediatek/Kconfig
@@ -7,7 +7,6 @@ config DRM_MEDIATEK
 	select DRM_KMS_HELPER
 	select DRM_MIPI_DSI
 	select DRM_PANEL
-	select IOMMU_DMA
 	select MEMORY
 	select MTK_SMI
 	help
-- 
2.7.0



From arnd at arndb.de  Wed May 11 13:15:20 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 11 May 2016 22:15:20 +0200
Subject: [PATCH] drm: mediatek: remove IOMMU_DMA select
In-Reply-To: <1462997501-982363-1-git-send-email-arnd@arndb.de>
References: <1462982509-342936-1-git-send-email-arnd@arndb.de>
 <1462997501-982363-1-git-send-email-arnd@arndb.de>
Message-ID: <3436915.Zo8cThvXaA@wuerfel>

On Wednesday 11 May 2016 22:11:07 Arnd Bergmann wrote:
> We get a harmless build warning when trying to use the mediatek
> DRM driver with IOMMU support disabled:
> 
> warning: (DRM_MEDIATEK) selects IOMMU_DMA which has unmet direct dependencies (IOMMU_SUPPORT)
> 
> However, the IOMMU_DMA symbol is not meant to be used by drivers
> at all, and this driver doesn't seem to have a strict dependency
> on it other than using the mediatek IOMMU driver that does.
> 
> Since we also want to be able to do compile tests with the
> driver on other platforms, the IOMMU_DMA symbol should not
> be selected here.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> ---
> If someone has a better explanation about why the 'select' is here,
> let me know, it certainly seems out of place.

Sorry, I didn't mean to send this as a reply to "More build fixes for
omapdrm in current -next", I copied the wrong command line.

I'll resend it if necessary.

	Arnd



From rafael at kernel.org  Wed May 11 13:30:51 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Wed, 11 May 2016 22:30:51 +0200
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <20160511101101.GA16101@red-moon>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
 <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>
 <20160511101101.GA16101@red-moon>
Message-ID: <CAJZ5v0hgw929W5PjF0PqT+ssiOHd8TeJoSQcz4NUiAovZY2pfQ@mail.gmail.com>

On Wed, May 11, 2016 at 12:11 PM, Lorenzo Pieralisi
<lorenzo.pieralisi at arm.com> wrote:
> On Tue, May 10, 2016 at 08:37:00PM +0200, Rafael J. Wysocki wrote:
>> On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
>> > This patch provides a way to set the ACPI companion in PCI code.
>> > We define acpi_pci_set_companion() to set the ACPI companion pointer and
>> > call it from PCI core code. The function is stub for now.
>> >
>> > Signed-off-by: Jayachandran C <jchandra at broadcom.com>
>> > Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
>> > ---
>> >  drivers/pci/probe.c      | 2 ++
>> >  include/linux/pci-acpi.h | 4 ++++
>> >  2 files changed, 6 insertions(+)
>> >
>> > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> > index 8004f67..fb0b752 100644
>> > --- a/drivers/pci/probe.c
>> > +++ b/drivers/pci/probe.c
>> > @@ -12,6 +12,7 @@
>> >  #include <linux/slab.h>
>> >  #include <linux/module.h>
>> >  #include <linux/cpumask.h>
>> > +#include <linux/pci-acpi.h>
>> >  #include <linux/pci-aspm.h>
>> >  #include <linux/aer.h>
>> >  #include <linux/acpi.h>
>> > @@ -2141,6 +2142,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
>> >         bridge->dev.parent = parent;
>> >         bridge->dev.release = pci_release_host_bridge_dev;
>> >         dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
>> > +       acpi_pci_set_companion(bridge);
>>
>> Yes, we'll probably add something similar here.
>>
>> Do I think now is the right time to do that?  No.
>>
>> >         error = pcibios_root_bridge_prepare(bridge);
>> >         if (error) {
>> >                 kfree(bridge);
>> > diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
>> > index 09f9f02..1baa515 100644
>> > --- a/include/linux/pci-acpi.h
>> > +++ b/include/linux/pci-acpi.h
>> > @@ -111,6 +111,10 @@ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
>> >  static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
>> >  #endif /* CONFIG_ACPI */
>> >
>> > +static inline void acpi_pci_set_companion(struct pci_host_bridge *bridge)
>> > +{
>> > +}
>> > +
>> >  static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus)
>> >  {
>> >         return 0;
>> > --
>>
>> Honestly, to me it looks like this series is trying very hard to avoid
>> doing any PCI host bridge configuration stuff from arch/arm64/
>> although (a) that might be simpler and (b) it would allow us to
>> identify the code that's common between *all* architectures using ACPI
>> support for host bridge configuration and to move *that* to a common
>> place later.  As done here it seems to be following the "ARM64 is
>> generic and the rest of the world is special" line which isn't really
>> helpful.
>
> I think patch [1-2] should be merged regardless (they may require minor
> tweaks if we decide to move pci_acpi_scan_root() to arch/arm64 though,
> for include files location). I guess you are referring to patch 8 in
> your comments above, which boils down to deciding whether:
>
> - pci_acpi_scan_root() (and unfortunately all the MCFG/ECAM handling that
>   goes with it) should live in arch/arm64 or drivers/acpi

To be precise, everything under #ifdef CONFIG_ACPI_PCI_HOST_GENERIC or
equivalent is de facto ARM64-specific, because (as it stands in the
patch series) ARM64 is the only architecture that will select that
option.  Unless you are aware of any more architectures planning to
use ACPI (and I'm not aware of any), it will stay the only
architecture selecting it in the foreseeable future.

Therefore you could replace CONFIG_ACPI_PCI_HOST_GENERIC with
CONFIG_ARM64 everywhere in that code which is why in my opinion the
code should live somewhere under arch/arm64/.

Going forward, it should be possible to identify common parts of the
PCI host bridge configuration code in arch/ and move it to
drivers/acpi/ or drivers/pci/, but I bet that won't be the entire code
this series puts under CONFIG_ACPI_PCI_HOST_GENERIC.

The above leads to a quite straightforward conclusion about the order
in which to do things: I'd add ACPI support for PCI host bridge on
ARM64 following what's been done on ia64 (as x86 is more quirky and
kludgy overall) as far as reasonably possible first and then think
about moving common stuff to a common place.

> acpi_pci_bus_domain_nr() is a bit more problematic since it is meant
> to be called from PCI core code (ARM64 selects PCI_DOMAINS_GENERIC for
> DT and same kernel has to work with OF and ACPI selected) and it is
> arch specific (because what we have in bus->sysdata is arch specific,
> waiting for the domain number to be embedded in struct pci_host_bridge).
>
> Your point is fair, I am not sure that moving the pci_acpi_scan_root()
> to arch/arm64 would make things much simpler though, it is just a matter
> of deciding where that code has to live.
>
> How do you want us to proceed ?

Pretty much as stated above. :-)

Thanks,
Rafael


From matija.glavinic-pecotic.ext at nokia.com  Wed May 11 13:33:51 2016
From: matija.glavinic-pecotic.ext at nokia.com (Matija Glavinic Pecotic)
Date: Wed, 11 May 2016 22:33:51 +0200
Subject: [PATCH] [ARM] Fix A15 798181 errata initialization
Message-ID: <5733972F.9040502@nokia.com>

Current errata initialization doesn't take properly revision and REVIDR
into account. Depending on the core revision, revidr bits should not be
taken into account. Errata misleadingly declares r3p3 to be error-free,
but this is not the case. Include rp3p3 in errata initialization.

Here are possible fixes defined in revidr register for r2 and r3 [1,2]:

r0p0-r2p1: No fixes applied

r2p2,r2p3:

REVIDR[4]: 798181 Moving a virtual page that is being accessed by
	   an active process can lead to unexpected behavior
REVIDR[9]: Not defined

r2p4,r3p0,r3p1,r3p2:

REVIDR[4]: 798181 Moving a virtual page that is being accessed by
	   an active process can lead to unexpected behavior
REVIDR[9]: 798181 Moving a virtual page that is being accessed by
	   an active process can lead to unexpected behavior
	   - This is an update to a previously released ECO.

r3p3:

REVIDR[4]: Reserved
REVIDR[9]: 798181 Moving a virtual page that is being accessed by
	   an active process can lead to unexpected behavior
	   - This is an update to a previously released ECO.

And here is proposed handling from the same documents [1,2]:

* In r3p2 and earlier versions with REVIDR[4]= 0,the full workaround is
  required.
* In r3p2 and earlier versions with REVIDR[4]=1, REVIDR[9]=0, only the
  portion of the workaround up to the end of step 6 is required.
* In r3p2 and earlier versions with REVIDR[4]=1, REVIDR[9]=1, no
  workaround is required.
* In r3p3, if REVIDR[9]=0, only the portion of the workaround up
  to the end of step 6 is required.
* In r3p3, if REVIDR[9]=1, no workaround is required.

These imply following:

REVIDR[9] set -> No WA
REVIDR[4] set, REVIDR[9] cleared -> Partial WA
Both cleared -> Full WA

Where certain bits should and should not be taken into account
depending on whether they are defined for the revision.

Although not explicitly mentioned in the errata note, REVIDR[9] set,
with REVIDR[4] cleared is valid combination which requires no WA. This
is confirmed by ARM support and errata will be updated.

[1] ARM CortexTM-A15 MPCore - NEON
    Product revision r3
    Software Developers Errata Notice
    ARM-EPM-028093 v20.0 Released

[2] ARM CortexTM-A15 MPCore - NEON
    Product Revision r2
    Software Developers Errata Notice
    ARM-EPM-028090 v19.3 Released

Signed-off-by: Matija Glavinic Pecotic <matija.glavinic-pecotic.ext at nokia.com>
Reviewed-by: Alexander Sverdlin <alexander.sverdlin at nokia.com>
---
 arch/arm/kernel/smp_tlb.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
index 2e72be4..b624758 100644
--- a/arch/arm/kernel/smp_tlb.c
+++ b/arch/arm/kernel/smp_tlb.c
@@ -93,17 +93,30 @@ void erratum_a15_798181_init(void)
 	unsigned int revidr = read_cpuid(CPUID_REVIDR);
 
 	/* Brahma-B15 r0p0..r0p2 affected
-	 * Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
-	if ((midr & 0xff0ffff0) == 0x420f00f0 && midr <= 0x420f00f2)
+	 * Cortex-A15 r0p0..r3p3 w/o ECO fix affected
+	 */
+	if ((midr & 0xff0ffff0) == 0x420f00f0 && midr <= 0x420f00f2) {
 		erratum_a15_798181_handler = erratum_a15_798181_broadcast;
-	else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr <= 0x413fc0f2 &&
-		 (revidr & 0x210) != 0x210) {
+	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x412fc0f2) {
+		erratum_a15_798181_handler = erratum_a15_798181_broadcast;
+	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x412fc0f4) {
 		if (revidr & 0x10)
 			erratum_a15_798181_handler =
 				erratum_a15_798181_partial;
 		else
 			erratum_a15_798181_handler =
 				erratum_a15_798181_broadcast;
+	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x413fc0f3) {
+		if ((revidr & 0x210) == 0)
+			erratum_a15_798181_handler =
+				erratum_a15_798181_broadcast;
+		else if (revidr & 0x10)
+			erratum_a15_798181_handler =
+				erratum_a15_798181_partial;
+	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x414fc0f0) {
+		if ((revidr & 0x200) == 0)
+			erratum_a15_798181_handler =
+				erratum_a15_798181_partial;
 	}
 }
 #endif
-- 
2.1.4


From bjorn.andersson at linaro.org  Wed May 11 13:34:44 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Wed, 11 May 2016 13:34:44 -0700
Subject: [Patch v4 5/8] firmware: qcom: scm: Convert to streaming DMA APIS
In-Reply-To: <1462976158-26016-6-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
 <1462976158-26016-6-git-send-email-andy.gross@linaro.org>
Message-ID: <20160511203444.GX1256@tuxbot>

On Wed 11 May 07:15 PDT 2016, Andy Gross wrote:

> This patch converts the Qualcomm SCM driver to use the streaming DMA APIs
> for communication buffers.
> 

Some style issues in qcom_scm_call(), but functionality wise I think
this looks good (with the open question on packing of rsp and rps->buf).

> Signed-off-by: Andy Gross <andy.gross at linaro.org>
> ---
>  drivers/firmware/qcom_scm-32.c | 152 +++++++++++++----------------------------
>  drivers/firmware/qcom_scm.c    |   6 +-
>  drivers/firmware/qcom_scm.h    |  10 +--
>  3 files changed, 58 insertions(+), 110 deletions(-)
> 
> diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
[..]
>  /**
>   * qcom_scm_call() - Send an SCM command
> - * @svc_id: service identifier
> - * @cmd_id: command identifier
> - * @cmd_buf: command buffer
> - * @cmd_len: length of the command buffer
> - * @resp_buf: response buffer
> - * @resp_len: length of the response buffer
> + * @dev:	struct device
> + * @svc_id:	service identifier
> + * @cmd_id:	command identifier
> + * @cmd_buf:	command buffer
> + * @cmd_len:	length of the command buffer
> + * @resp_buf:	response buffer
> + * @resp_len:	length of the response buffer

Leaving the indentation alone clarifies that your changes is just the
addition of "dev".

>   *
>   * Sends a command to the SCM and waits for the command to finish processing.
>   *
> @@ -247,42 +172,60 @@ static void qcom_scm_inv_range(unsigned long start, unsigned long end)
>   * and response buffers is taken care of by qcom_scm_call; however, callers are
>   * responsible for any other cached buffers passed over to the secure world.
>   */
> -static int qcom_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf,
> -			size_t cmd_len, void *resp_buf, size_t resp_len)
> +static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
> +			 const void *cmd_buf, size_t cmd_len, void *resp_buf,
> +			 size_t resp_len)
>  {
>  	int ret;
>  	struct qcom_scm_command *cmd;
>  	struct qcom_scm_response *rsp;
> -	unsigned long start, end;
> +	size_t alloc_len = sizeof(*cmd) + sizeof(struct qcom_scm_response) +
> +			   cmd_len + resp_len;

This would be cleaner if written:

size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len;

> +	dma_addr_t cmd_phys;
> +	u32 offset;
>  
> -	cmd = alloc_qcom_scm_command(cmd_len, resp_len);
> +	cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
>  	if (!cmd)
>  		return -ENOMEM;
>  
> +	cmd->len = cpu_to_le32(alloc_len);
> +	offset = offsetof(struct qcom_scm_command, buf);
> +	cmd->buf_offset = cpu_to_le32(offset);

Sure this is the offset of the buf in *cmd, but based on the rest of my
comments below I would have dropped the offset variable and just used
sizeof(*cmd).

> +	cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_len);

But this would be more intuitive as sizeof(*cmd) + cmd_len;

> +
>  	cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
>  	if (cmd_buf)
>  		memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len);

Somewhat unrelated, but we should probably just inline this helper in
favour of writing "cmd->buf".

>  
> +	cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE);

Unless there's a guarantee that the resp buffer is packed onto the
response we should probably map the entire page(s).

> +	if (dma_mapping_error(dev, cmd_phys)) {
> +		kfree(cmd);
> +		return -ENOMEM;
> +	}
> +
>  	mutex_lock(&qcom_scm_lock);
> -	ret = __qcom_scm_call(cmd);
> +	ret = smc(cmd_phys);
> +	if (ret < 0)
> +		ret = qcom_scm_remap_error(ret);
>  	mutex_unlock(&qcom_scm_lock);
>  	if (ret)
>  		goto out;
>  
>  	rsp = qcom_scm_command_to_response(cmd);
> -	start = (unsigned long)rsp;
>  
>  	do {
> -		qcom_scm_inv_range(start, start + sizeof(*rsp));
> +		dma_sync_single_for_cpu(dev, cmd_phys + cmd_len + offset,

Same here, would be easier to read if it was
  cmd_phys + sizeof(*cmd) + cmd_len;

Or even:
  cmd_phys + le32_to_cpu(cmd->resp_hdr_offset);

> +					sizeof(*rsp), DMA_FROM_DEVICE);
>  	} while (!rsp->is_complete);
>  
> -	end = (unsigned long)qcom_scm_get_response_buffer(rsp) + resp_len;
> -	qcom_scm_inv_range(start, end);
> -
> -	if (resp_buf)
> +	if (resp_buf) {
> +		dma_sync_single_for_cpu(dev, cmd_phys + alloc_len - resp_len,

Do we know that the firmware always set
  rsp->buf_offset = sizeof(*rsp)

Would be clearer (and safe from this assumption) if you have it as:
  cmd_phys + le32_to_cpu(cmd->resp_hdr_offset) + le32_to_cpu(rsp->buf_offset);

> +					resp_len, DMA_FROM_DEVICE);
>  		memcpy(resp_buf, qcom_scm_get_response_buffer(rsp), resp_len);

And as we just calculated that offset, we can drop the
qcom_scm_get_response_buffer() single use helper.

> +	}
>  out:
> -	free_qcom_scm_command(cmd);
> +	dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE);
> +	kfree(cmd);
>  	return ret;
>  }
>  

The rest looks good.

Regards,
Bjorn


From rafael at kernel.org  Wed May 11 13:35:02 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Wed, 11 May 2016 22:35:02 +0200
Subject: [PATCH v6 00/14] ACPI NUMA support for ARM64
In-Reply-To: <20160511104032.GA31374@arm.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <CAJZ5v0iMDQ4pWip4vyCos0o+1DFDvXQf4XZQqC4SGjJsDO4Lnw@mail.gmail.com>
 <20160511104032.GA31374@arm.com>
Message-ID: <CAJZ5v0gQMR7OUyZo5Sa3bgMYZBzdnwFaktz9JCv1ocWXw7yHTg@mail.gmail.com>

On Wed, May 11, 2016 at 12:40 PM, Will Deacon <will.deacon at arm.com> wrote:
> On Wed, May 11, 2016 at 02:43:11AM +0200, Rafael J. Wysocki wrote:
>> On Wed, Apr 27, 2016 at 8:07 PM, David Daney <ddaney.cavm at gmail.com> wrote:
>> > From: David Daney <david.daney at cavium.com>
>> >
>> > Based on git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
>> > for-next/core branch at commit 643d703d2d2d ("arm64: compat: Check for
>> > AArch32 state")
>
> [...]
>
>> > David Daney (2):
>> >   arm64, numa: Cleanup NUMA disabled messages.
>> >   acpi, numa, srat: Improve SRAT error detection and add messages.
>> >
>> > Hanjun Guo (11):
>> >   acpi, numa: Use pr_fmt() instead of printk
>> >   acpi, numa: Replace ACPI_DEBUG_PRINT() with pr_debug()
>> >   acpi, numa: remove duplicate NULL check
>> >   acpi, numa: move acpi_numa_slit_init() to drivers/acpi/numa.c
>> >   arm64, numa: rework numa_add_memblk()
>> >   x86, acpi, numa: cleanup acpi_numa_processor_affinity_init()
>> >   acpi, numa: move bad_srat() and srat_disabled() to
>> >     drivers/acpi/numa.c
>> >   acpi, numa: remove unneeded acpi_numa=1
>> >   acpi, numa: Move acpi_numa_memory_affinity_init() to
>> >     drivers/acpi/numa.c
>> >   arm64, acpi, numa: NUMA support based on SRAT and SLIT
>> >   acpi, numa: Enable ACPI based NUMA on ARM64
>> >
>> > Robert Richter (1):
>> >   acpi, numa: Move acpi_numa_arch_fixup() to ia64 only
>>
>> I need ACKs from the ARM64 maintainers on patches [6-7/13] and [13-14/14].
>
> There's also a dependency on the arm64 for-next/core branch, so I've been
> largely ignoring this as far as 4.6 is concerned and was planning to take
> a proper look for 4.7 once the upcoming merge window is out of the way.

That would be 4.7 and 4.8 respectively I suppose?

Anyway, Catalin has ACKed all of them except for the [13/14], so
technically I can apply [1-12/14] now and then [13-14/14] can be
applied when they are ready.

Do you think there will be any problems with merging [6-7/14] into 4.7
via the ACPI tree?


From rafael at kernel.org  Wed May 11 13:45:56 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Wed, 11 May 2016 22:45:56 +0200
Subject: [PATCH v4 2/5] ACPI / processor_idle: Add support for Low Power
 Idle(LPI) states
In-Reply-To: <57334A66.6070004@arm.com>
References: <1461069013-13292-1-git-send-email-sudeep.holla@arm.com>
 <1461069013-13292-3-git-send-email-sudeep.holla@arm.com>
 <1857618.TLitUhExSh@vostro.rjw.lan> <57334A66.6070004@arm.com>
Message-ID: <CAJZ5v0gbkQmgGuVBxficJjVrOudRTgKKFFp6tFRCG-Byud8Ozg@mail.gmail.com>

On Wed, May 11, 2016 at 5:06 PM, Sudeep Holla <sudeep.holla at arm.com> wrote:
>
>
> On 11/05/16 01:03, Rafael J. Wysocki wrote:
>>
>> On Tuesday, April 19, 2016 01:30:10 PM Sudeep Holla wrote:
>>>

[cut]

>>
>> My main concern about the flattening of _LPI is that at one point we'll
>> probably decide to unflatten it and that will change the behavior for
>> current users.  There needs to be a plan for that IMO.
>>
>
> Are you referring the OS co-ordinated mode ? If yes, I agree. If not,
> can you explain why would we not flatten the LPI states ?

If the platform doesn't autopromote core-level states into
package-level states, then having access to unflattened hierarchy may
be useful.  In some cases the exit latency of core states may be
acceptable, while the exit latency of package states may not be, for
example.

Also the scheduler may want to know which cores are in one package
(from the idle states perspective) at one point.

[cut]

>>> +
>>> +       for (i = 0; i < fl_scnt && i < CPUIDLE_STATE_MAX; i++) {
>>> +               lpi = &pr->power.lpi_states[i];
>>> +
>>> +               state = &drv->states[i];
>>> +               snprintf(state->name, CPUIDLE_NAME_LEN, "LPI-%d", i);
>>> +               strlcpy(state->desc, lpi->desc, CPUIDLE_DESC_LEN);
>>> +               state->exit_latency = lpi->wake_latency;
>>> +               state->target_residency = lpi->min_residency;
>>> +               if (lpi->arch_flags)
>>> +                       state->flags |= CPUIDLE_FLAG_TIMER_STOP;
>>> +               state->enter = acpi_idle_lpi_enter;
>>
>>
>> No ->enter_freeze ?
>>
>
> I don't have a system to test this. Also IIUC the cpuidle does support
> suspend-to-idle even when ->enter_freeze is not implemented right.
> Can we add it later once I find a way to test. Correctly no wakeup on my
> test platform :(

Fair enough.


From ddaney at caviumnetworks.com  Wed May 11 14:08:09 2016
From: ddaney at caviumnetworks.com (David Daney)
Date: Wed, 11 May 2016 14:08:09 -0700
Subject: [PATCH v6 00/14] ACPI NUMA support for ARM64
In-Reply-To: <CAJZ5v0gQMR7OUyZo5Sa3bgMYZBzdnwFaktz9JCv1ocWXw7yHTg@mail.gmail.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <CAJZ5v0iMDQ4pWip4vyCos0o+1DFDvXQf4XZQqC4SGjJsDO4Lnw@mail.gmail.com>
 <20160511104032.GA31374@arm.com>
 <CAJZ5v0gQMR7OUyZo5Sa3bgMYZBzdnwFaktz9JCv1ocWXw7yHTg@mail.gmail.com>
Message-ID: <57339F39.3040603@caviumnetworks.com>

On 05/11/2016 01:35 PM, Rafael J. Wysocki wrote:
> On Wed, May 11, 2016 at 12:40 PM, Will Deacon <will.deacon at arm.com> wrote:
>> On Wed, May 11, 2016 at 02:43:11AM +0200, Rafael J. Wysocki wrote:
>>> On Wed, Apr 27, 2016 at 8:07 PM, David Daney <ddaney.cavm at gmail.com> wrote:
>>>> From: David Daney <david.daney at cavium.com>
>>>>
>>>> Based on git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
>>>> for-next/core branch at commit 643d703d2d2d ("arm64: compat: Check for
>>>> AArch32 state")
>>
>> [...]
>>
>>>> David Daney (2):
>>>>    arm64, numa: Cleanup NUMA disabled messages.
>>>>    acpi, numa, srat: Improve SRAT error detection and add messages.
>>>>
>>>> Hanjun Guo (11):
>>>>    acpi, numa: Use pr_fmt() instead of printk
>>>>    acpi, numa: Replace ACPI_DEBUG_PRINT() with pr_debug()
>>>>    acpi, numa: remove duplicate NULL check
>>>>    acpi, numa: move acpi_numa_slit_init() to drivers/acpi/numa.c
>>>>    arm64, numa: rework numa_add_memblk()
>>>>    x86, acpi, numa: cleanup acpi_numa_processor_affinity_init()
>>>>    acpi, numa: move bad_srat() and srat_disabled() to
>>>>      drivers/acpi/numa.c
>>>>    acpi, numa: remove unneeded acpi_numa=1
>>>>    acpi, numa: Move acpi_numa_memory_affinity_init() to
>>>>      drivers/acpi/numa.c
>>>>    arm64, acpi, numa: NUMA support based on SRAT and SLIT
>>>>    acpi, numa: Enable ACPI based NUMA on ARM64
>>>>
>>>> Robert Richter (1):
>>>>    acpi, numa: Move acpi_numa_arch_fixup() to ia64 only
>>>
>>> I need ACKs from the ARM64 maintainers on patches [6-7/13] and [13-14/14].
>>
>> There's also a dependency on the arm64 for-next/core branch, so I've been
>> largely ignoring this as far as 4.6 is concerned and was planning to take
>> a proper look for 4.7 once the upcoming merge window is out of the way.
>
> That would be 4.7 and 4.8 respectively I suppose?
>
> Anyway, Catalin has ACKed all of them except for the [13/14], so
> technically I can apply [1-12/14] now and then [13-14/14] can be
> applied when they are ready.
>
> Do you think there will be any problems with merging [6-7/14] into 4.7
> via the ACPI tree?
>

I would defer to the arm64 maintainers for decisions about the arm64 
specific parts of the patch set.  That said, many of the arm64 specific 
patches depend on the arm64 for-next/core branch, so you would have to 
be careful about merge ordering if you pull these in before the 
for-next/core branch is merged.

Also FWIW, I plan on addressing Catalin's comments about 13/14 and 
posting a new version of the patch set in the next day or two.

Thanks for looking at these,
David Daney





From heiko at sntech.de  Wed May 11 14:09:43 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 11 May 2016 23:09:43 +0200
Subject: [PATCH v8 8/8] i2c: rk3x: support fast-mode plus for rk3399
In-Reply-To: <1462908794-27333-1-git-send-email-david.wu@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908794-27333-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <5153288.jNhUuzGC3g@phil>

Am Mittwoch, 11. Mai 2016, 03:33:14 schrieb David Wu:

please always try to also provide some sort of commit message.

---
Implement fast mode plus that allows bus speeds of up to 1MHz.
.....

---

Additionally, the i2c-noob in me would wish for a short sentence on where 
the timing values come from (measured, somewhere in the TRM I didn't find or 
something completely different).


Patch content itself looks good, so with a suitable commit message,
Reviewed-by: Heiko Stuebner <heiko at sntech.de>


> Signed-off-by: David Wu <david.wu at rock-chips.com>
> Reviewed-by: Douglas Anderson <dianders at chromium.org>
> ---
> Change in v8:
> - None
> 
>  drivers/i2c/busses/i2c-rk3x.c | 21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> index 25ed1ad..0ba25ee 100644
> --- a/drivers/i2c/busses/i2c-rk3x.c
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -126,6 +126,17 @@ static const struct i2c_spec_values fast_mode_spec =
> { .min_hold_buffer_ns = 1300,
>  };
> 
> +static const struct i2c_spec_values fast_mode_plus_spec = {
> +	.min_hold_start_ns = 260,
> +	.min_low_ns = 500,
> +	.min_high_ns = 260,
> +	.min_setup_start_ns = 260,
> +	.max_data_hold_ns = 400,
> +	.min_data_setup_ns = 50,
> +	.min_setup_stop_ns = 260,
> +	.min_hold_buffer_ns = 500,
> +};
> +
>  /**
>   * struct rk3x_i2c_calced_timings:
>   * @div_low: Divider output for low
> @@ -531,8 +542,10 @@ static const struct i2c_spec_values
> *rk3x_i2c_get_spec(unsigned int speed) {
>  	if (speed <= 100000)
>  		return &standard_mode_spec;
> -	else
> +	else if (speed <= 400000)
>  		return &fast_mode_spec;
> +	else
> +		return &fast_mode_plus_spec;
>  }
> 
>  /**
> @@ -743,9 +756,9 @@ static int rk3x_i2c_v1_calc_timings(unsigned long
> clk_rate, const struct i2c_spec_values *spec;
>  	int ret = 0;
> 
> -	/* Support standard-mode and fast-mode */
> -	if (WARN_ON(t->bus_freq_hz > 400000))
> -		t->bus_freq_hz = 400000;
> +	/* Support standard-mode, fast-mode and fast-mode plus */
> +	if (WARN_ON(t->bus_freq_hz > 1000000))
> +		t->bus_freq_hz = 1000000;
> 
>  	/* prevent scl_rate_khz from becoming 0 */
>  	if (WARN_ON(t->bus_freq_hz < 1000))



From festevam at gmail.com  Wed May 11 14:12:05 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Wed, 11 May 2016 18:12:05 -0300
Subject: mx6ul cannot reboot
Message-ID: <CAOMZO5DLz7vBARB+uweDG+tw0UM3EMDb9+_XcLaaBv0GN+im7g@mail.gmail.com>

Hi,

After issuing a 'reboot' command on mx6ul-evk running 4.6-rc I get the
following problem:

Requesting system reboot
[ 3831.291553] ci_hdrc ci_hdrc.1: remove, state 4
[ 3831.297531] usb usb1: USB disconnect, device number 1
[ 3831.333168] ci_hdrc ci_hdrc.1: USB bus 1 deregistered

(stays 26 seconds here and then continues)

[ 3857.373588] INFO: rcu_sched detected stalls on CPUs/tasks:
[ 3857.379155]  (detected by 0, t=2602 jiffies, g=1880, c=1879, q=29)
[ 3857.385406] All QSes seen, last rcu_sched kthread activity 2602
(355736-353134), jiffies_till_next_fqs=1, root ->qsmask 0x0
[ 3857.396562] init            R running      0   864      1 0x00000002
[ 3857.402999] Backtrace:
[ 3857.405532] [<c010b6e8>] (dump_backtrace) from [<c010b884>]
(show_stack+0x18/0x1c)
[ 3857.413125]  r6:c0d6c6d6 r5:00000001 r4:ddd9c800 r3:00000000
[ 3857.418941] [<c010b86c>] (show_stack) from [<c014fc3c>]
(sched_show_task+0x124/0x234)
[ 3857.426820] [<c014fb18>] (sched_show_task) from [<c0185e24>]
(rcu_check_callbacks+0x844/0x894)
[ 3857.435452]  r6:c0c76b40 r5:c0d14b80 r4:debd0b40
[ 3857.440189] [<c01855e0>] (rcu_check_callbacks) from [<c018884c>]
(update_process_times+0x38/0x64)
[ 3857.449081]  r10:c0d21e1c r9:debcdd10 r8:c019a230 r7:dde7bd50
r6:debce048 r5:00000000
[ 3857.457067]  r4:ddd9c800
[ 3857.459665] [<c0188814>] (update_process_times) from [<c019a174>]
(tick_sched_handle+0x50/0x54)
[ 3857.468386]  r5:00000382 r4:1c92d15d
[ 3857.472048] [<c019a124>] (tick_sched_handle) from [<c019a290>]
(tick_sched_timer+0x60/0xa8)
[ 3857.480443] [<c019a230>] (tick_sched_timer) from [<c018915c>]
(__hrtimer_run_queues+0xc0/0x1c8)
[ 3857.489162]  r7:debcdd80 r6:debcdd00 r5:debcdd8c r4:debce048
[ 3857.494969] [<c018909c>] (__hrtimer_run_queues) from [<c018998c>]
(hrtimer_interrupt+0xc8/0x22c)
[ 3857.503774]  r10:debcddd8 r9:debcddb8 r8:debcddf8 r7:debcdd00
r6:debcdd40 r5:00000003
[ 3857.511758]  r4:ffffffff
[ 3857.514354] [<c01898c4>] (hrtimer_interrupt) from [<c067d994>]
(mxc_timer_interrupt+0x3c/0x44)
[ 3857.522985]  r10:c0d6c710 r9:e0805000 r8:de41d000 r7:00000010
r6:00000000 r5:00000000
[ 3857.530969]  r4:de402440
[ 3857.533568] [<c067d958>] (mxc_timer_interrupt) from [<c0177acc>]
(handle_irq_event_percpu+0x64/0x168)
[ 3857.542809]  r4:de402500 r3:c067d958
[ 3857.546482] [<c0177a68>] (handle_irq_event_percpu) from
[<c0177c10>] (handle_irq_event+0x40/0x64)
[ 3857.555374]  r10:de406000 r9:e0805000 r8:00000001 r7:00000000
r6:c0d10330 r5:de41d060
[ 3857.563358]  r4:de41d000
[ 3857.565956] [<c0177bd0>] (handle_irq_event) from [<c017b120>]
(handle_fasteoi_irq+0xd4/0x1ac)
[ 3857.574502]  r6:c0d10330 r5:de41d060 r4:de41d000 r3:00000000
[ 3857.580305] [<c017b04c>] (handle_fasteoi_irq) from [<c017726c>]
(generic_handle_irq+0x20/0x30)
[ 3857.588937]  r7:00000000 r6:c0c746ec r5:c0d02b10 r4:00000010
[ 3857.594743] [<c017724c>] (generic_handle_irq) from [<c01773b0>]
(__handle_domain_irq+0x6c/0xe4)
[ 3857.603485] [<c0177344>] (__handle_domain_irq) from [<c01015d8>]
(gic_handle_irq+0x4c/0x9c)
[ 3857.611857]  r10:000003eb r8:c0d22000 r7:c0d02c58 r6:dde7bd50
r5:e080400c r4:e0804000
[ 3857.619858] [<c010158c>] (gic_handle_irq) from [<c010c4b8>]
(__irq_svc+0x58/0x78)
[ 3857.627367] Exception stack(0xdde7bd50 to 0xdde7bd98)
[ 3857.632450] bd40:                                     ddce911c
00000001 00000000 00000003
[ 3857.640664] bd60: ddce911c c0d02a48 ddcea000 ddce90c0 c0108044
dde7a000 00000000 dde7bdb4
[ 3857.648875] bd80: dde7bdb8 dde7bda0 c064ad44 c01b247c 20000013 ffffffff
[ 3857.655509]  r10:00000000 r9:dde7a000 r8:c0108044 r7:dde7bd84
r6:ffffffff r5:20000013
[ 3857.663494]  r4:c01b247c r3:ddd9c800
[ 3857.667167] [<c01b2448>] (irq_work_sync) from [<c064ad44>]
(cpufreq_governor_dbs+0x170/0x580)
[ 3857.675713]  r4:00000004 r3:00000001
[ 3857.679384] [<c064abd4>] (cpufreq_governor_dbs) from [<c06480e4>]
(cpufreq_governor+0x64/0x120)
[ 3857.688103]  r10:00000000 r9:dde7a000 r8:c0108044 r7:c1556f80
r6:00000002 r5:ddcea000
[ 3857.696088]  r4:c0d4c5dc
[ 3857.698684] [<c0648080>] (cpufreq_governor) from [<c06493c4>]
(cpufreq_suspend+0x70/0x128)
[ 3857.706967]  r6:c0d4c328 r5:ddcea0dc r4:ddcea000 r3:ddd9c800
[ 3857.712777] [<c0649354>] (cpufreq_suspend) from [<c04da71c>]
(syscore_shutdown+0x4c/0x80)
[ 3857.720976]  r8:c0108044 r7:00000000 r6:c0d6e020 r5:c0d315a8
r4:c0d4c2fc r3:00000000
[ 3857.728895] [<c04da6d0>] (syscore_shutdown) from [<c0147aa8>]
(kernel_restart+0x1c/0x58)
[ 3857.737007]  r6:c0d13074 r5:4321fedc r4:00000000 r3:de434900
[ 3857.742805] [<c0147a8c>] (kernel_restart) from [<c0147cc4>]
(SyS_reboot+0x18c/0x1e4)
[ 3857.750569]  r4:01234567 r3:01234567
[ 3857.754234] [<c0147b38>] (SyS_reboot) from [<c0107ea0>]
(ret_fast_syscall+0x0/0x1c)
[ 3857.761910]  r7:00000058 r6:00000000 r5:00000000 r4:00000000
[ 3857.767707] rcu_sched kthread starved for 2602 jiffies! g1880 c1879
f0x2 RCU_GP_WAIT_FQS(3) ->state=0x0
[ 3857.777123] rcu_sched       R running      0     7      2 0x00000000
[ 3857.783558] Backtrace:
[ 3857.786076] [<c08f488c>] (__schedule) from [<c08f50d8>] (schedule+0x3c/0xa0)
[ 3857.793148]  r10:00000001 r9:00000003 r8:c0d02100 r7:0005636f
r6:debcd4c0 r5:debcd4c0
[ 3857.801133]  r4:de487e9c
[ 3857.803728] [<c08f509c>] (schedule) from [<c08f941c>]
(schedule_timeout+0x138/0x1cc)
[ 3857.811509] [<c08f92e4>] (schedule_timeout) from [<c0184bf0>]
(rcu_gp_kthread+0x3b0/0x894)
[ 3857.819794]  r8:00000000 r7:000002b8 r6:00000001 r5:c0d14e10 r4:c0d14b80
[ 3857.826667] [<c0184840>] (rcu_gp_kthread) from [<c0144e7c>]
(kthread+0xd8/0xf4)
[ 3857.833997]  r7:c0184840
[ 3857.836593] [<c0144da4>] (kthread) from [<c0107f30>]
(ret_from_fork+0x14/0x24)
[ 3857.843836]  r7:00000000 r6:00000000 r5:c0144da4 r4:de435040

I have only seen this on mx6ul.

Any ideas before I start debugging this?

Thanks


From bjorn.andersson at linaro.org  Wed May 11 14:21:23 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Wed, 11 May 2016 14:21:23 -0700
Subject: [Patch v4 6/8] firmware: qcom: scm: Add support for ARM64 SoCs
In-Reply-To: <1462976158-26016-7-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
 <1462976158-26016-7-git-send-email-andy.gross@linaro.org>
Message-ID: <20160511212123.GY1256@tuxbot>

On Wed 11 May 07:15 PDT 2016, Andy Gross wrote:

[..]
> diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c
[..]
> +
> +#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\
> +			   (((a) & 0xff) << 4) | \
> +			   (((b) & 0xff) << 6) | \
> +			   (((c) & 0xff) << 8) | \
> +			   (((d) & 0xff) << 10) | \
> +			   (((e) & 0xff) << 12) | \
> +			   (((f) & 0xff) << 14) | \
> +			   (((g) & 0xff) << 16) | \
> +			   (((h) & 0xff) << 18) | \
> +			   (((i) & 0xff) << 20) | \
> +			   (((j) & 0xff) << 22) | \
> +			   (num & 0xffff))

Sorry, haven't payed attention to the body of this macro before; but
it's "wrong".

num is 4 bits all other entries are 2 bits each. So it should be:

#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\
			   (((a) & 0x3) << 4) | \
			   (((b) & 0x3) << 6) | \
			   (((c) & 0x3) << 8) | \
			   (((d) & 0x3) << 10) | \
			   (((e) & 0x3) << 12) | \
			   (((f) & 0x3) << 14) | \
			   (((g) & 0x3) << 16) | \
			   (((h) & 0x3) << 18) | \
			   (((i) & 0x3) << 20) | \
			   (((j) & 0x3) << 22) | \
			   (num & 0xf))

> +
> +#define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
> +
> +/**
> + * struct qcom_scm_desc
> + * @arginfo:	Metadata describing the arguments in args[]
> + * @args:	The array of arguments for the secure syscall
> + * @res:	The values returned by the secure syscall
> + */
> +struct qcom_scm_desc {
> +	u32 arginfo;
> +	u64 args[MAX_QCOM_SCM_ARGS];
> +	struct arm_smccc_res res;
> +};
> +
> +static u64 qcom_smccc_convention = -1;
> +static DEFINE_MUTEX(qcom_scm_lock);
> +
> +#define QCOM_SCM_EBUSY_WAIT_MS 30
> +#define QCOM_SCM_EBUSY_MAX_RETRY 20
> +
> +#define N_EXT_QCOM_SCM_ARGS 7
> +#define FIRST_EXT_ARG_IDX 3
> +#define N_REGISTER_ARGS (MAX_QCOM_SCM_ARGS - N_EXT_QCOM_SCM_ARGS + 1)
> +
> +/**
> + * qcom_scm_call() - Invoke a syscall in the secure world
> + * @dev:	device
> + * @svc_id:	service identifier
> + * @cmd_id:	command identifier
> + * @fn_id:	The function ID for this syscall

You don't have a fn_id parameter anymore.

> + * @desc:	Descriptor structure containing arguments and return values
> + *
> + * Sends a command to the SCM and waits for the command to finish processing.
> + * This should *only* be called in pre-emptible context.
> +*/
> +static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
> +			 struct qcom_scm_desc *desc)
> +{
> +	int arglen = desc->arginfo & 0xf;
> +	int ret, retry_count = 0, i;
> +	u32 fn_id = QCOM_SCM_FNID(svc_id, cmd_id);
> +	u64 cmd, x5 = desc->args[FIRST_EXT_ARG_IDX];
> +	dma_addr_t args_phys = 0;
> +	void *args_virt = NULL;
> +	size_t alloc_len;
> +
> +	if (unlikely(arglen > N_REGISTER_ARGS)) {
> +		alloc_len = N_EXT_QCOM_SCM_ARGS * sizeof(u64);
> +		args_virt = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
> +
> +		if (!args_virt)
> +			return qcom_scm_remap_error(-ENOMEM);
> +
> +		if (qcom_smccc_convention == ARM_SMCCC_SMC_32) {
> +			__le32 *args = args_virt;
> +
> +			for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
> +				args[i] = cpu_to_le32(desc->args[i +
> +						      FIRST_EXT_ARG_IDX]);
> +		} else {
> +			__le64 *args = args_virt;
> +
> +			for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
> +				args[i] = cpu_to_le64(desc->args[i +
> +						      FIRST_EXT_ARG_IDX]);
> +		}
> +
> +		args_phys = dma_map_single(dev, args_virt, alloc_len,
> +					   DMA_TO_DEVICE);
> +
> +		if (dma_mapping_error(dev, args_phys)) {
> +			kfree(args_virt);
> +			return qcom_scm_remap_error(-ENOMEM);
> +		}
> +
> +		x5 = args_phys;
> +	}
> +
> +	do {
> +		mutex_lock(&qcom_scm_lock);
> +
> +		cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL,
> +					 qcom_smccc_convention,
> +					 ARM_SMCCC_OWNER_SIP, fn_id);
> +
> +		do {
> +			arm_smccc_smc(cmd, arglen, desc->args[0], desc->args[1],
> +				      desc->args[2], x5, 0, 0, &desc->res);

Looking at downstream you should pass the entirety of arginfo as the
second parameter. Currently you only set the num bits, but there are a
few cases when these bits should be set.

> +		} while (desc->res.a0 == QCOM_SCM_INTERRUPTED);
> +
> +		mutex_unlock(&qcom_scm_lock);
> +
> +		if (desc->res.a0 == QCOM_SCM_V2_EBUSY) {
> +			if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY)
> +				break;
> +			msleep(QCOM_SCM_EBUSY_WAIT_MS);
> +		}
> +	}  while (desc->res.a0 == QCOM_SCM_V2_EBUSY);
> +
> +	if (args_virt) {
> +		dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE);
> +		kfree(args_virt);
> +	}
> +
> +	if (desc->res.a0 < 0)
> +		return qcom_scm_remap_error(ret);

Probably not ret, as this is unused.

> +
> +	return 0;
> +}
>  
>  /**
>   * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
> - * @entry: Entry point function for the cpus
> - * @cpus: The cpumask of cpus that will use the entry point
> + * @entry:	Entry point function for the cpus
> + * @cpus:	The cpumask of cpus that will use the entry point

Unnecessary indentation change.

>   *
>   * Set the cold boot address of the cpus. Any cpu outside the supported
>   * range would be removed from the cpu present mask.
> @@ -29,20 +165,21 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
>  
>  /**
>   * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
> - * @entry: Entry point function for the cpus
> - * @cpus: The cpumask of cpus that will use the entry point
> + * @entry:	Entry point function for the cpus
> + * @cpus:	The cpumask of cpus that will use the entry point

Unnecessary indentation change, and you missed adding "dev".

>   *
>   * Set the Linux entry point for the SCM to transfer control to when coming
>   * out of a power down. CPU power down may be executed on cpuidle or hotplug.
>   */
> -int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
> +int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
> +				  const cpumask_t *cpus)
>  {
>  	return -ENOTSUPP;
>  }
>  
>  /**
>   * qcom_scm_cpu_power_down() - Power down the cpu
> - * @flags - Flags to flush cache
> + * @flags:	Flags to flush cache

I presume this one is ok...

>   *
>   * This is an end point to power down cpu. If there was a pending interrupt,
>   * the control would return from this function, otherwise, the cpu jumps to the
> @@ -52,12 +189,63 @@ void __qcom_scm_cpu_power_down(u32 flags)
>  {
>  }
>  

Regards,
Bjorn


From rafael at kernel.org  Wed May 11 14:22:48 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Wed, 11 May 2016 23:22:48 +0200
Subject: [PATCH v6 00/14] ACPI NUMA support for ARM64
In-Reply-To: <57339F39.3040603@caviumnetworks.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <CAJZ5v0iMDQ4pWip4vyCos0o+1DFDvXQf4XZQqC4SGjJsDO4Lnw@mail.gmail.com>
 <20160511104032.GA31374@arm.com>
 <CAJZ5v0gQMR7OUyZo5Sa3bgMYZBzdnwFaktz9JCv1ocWXw7yHTg@mail.gmail.com>
 <57339F39.3040603@caviumnetworks.com>
Message-ID: <CAJZ5v0h8zBEZ2nLLdk62r7uqHizUfVWamUVEriBGe1XBE6462Q@mail.gmail.com>

On Wed, May 11, 2016 at 11:08 PM, David Daney <ddaney at caviumnetworks.com> wrote:
> On 05/11/2016 01:35 PM, Rafael J. Wysocki wrote:
>>
>> On Wed, May 11, 2016 at 12:40 PM, Will Deacon <will.deacon at arm.com> wrote:
>>>
>>> On Wed, May 11, 2016 at 02:43:11AM +0200, Rafael J. Wysocki wrote:
>>>>
>>>> On Wed, Apr 27, 2016 at 8:07 PM, David Daney <ddaney.cavm at gmail.com>
>>>> wrote:
>>>>>
>>>>> From: David Daney <david.daney at cavium.com>
>>>>>
>>>>> Based on git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
>>>>> for-next/core branch at commit 643d703d2d2d ("arm64: compat: Check for
>>>>> AArch32 state")
>>>
>>>
>>> [...]
>>>
>>>>> David Daney (2):
>>>>>    arm64, numa: Cleanup NUMA disabled messages.
>>>>>    acpi, numa, srat: Improve SRAT error detection and add messages.
>>>>>
>>>>> Hanjun Guo (11):
>>>>>    acpi, numa: Use pr_fmt() instead of printk
>>>>>    acpi, numa: Replace ACPI_DEBUG_PRINT() with pr_debug()
>>>>>    acpi, numa: remove duplicate NULL check
>>>>>    acpi, numa: move acpi_numa_slit_init() to drivers/acpi/numa.c
>>>>>    arm64, numa: rework numa_add_memblk()
>>>>>    x86, acpi, numa: cleanup acpi_numa_processor_affinity_init()
>>>>>    acpi, numa: move bad_srat() and srat_disabled() to
>>>>>      drivers/acpi/numa.c
>>>>>    acpi, numa: remove unneeded acpi_numa=1
>>>>>    acpi, numa: Move acpi_numa_memory_affinity_init() to
>>>>>      drivers/acpi/numa.c
>>>>>    arm64, acpi, numa: NUMA support based on SRAT and SLIT
>>>>>    acpi, numa: Enable ACPI based NUMA on ARM64
>>>>>
>>>>> Robert Richter (1):
>>>>>    acpi, numa: Move acpi_numa_arch_fixup() to ia64 only
>>>>
>>>>
>>>> I need ACKs from the ARM64 maintainers on patches [6-7/13] and
>>>> [13-14/14].
>>>
>>>
>>> There's also a dependency on the arm64 for-next/core branch, so I've been
>>> largely ignoring this as far as 4.6 is concerned and was planning to take
>>> a proper look for 4.7 once the upcoming merge window is out of the way.
>>
>>
>> That would be 4.7 and 4.8 respectively I suppose?
>>
>> Anyway, Catalin has ACKed all of them except for the [13/14], so
>> technically I can apply [1-12/14] now and then [13-14/14] can be
>> applied when they are ready.
>>
>> Do you think there will be any problems with merging [6-7/14] into 4.7
>> via the ACPI tree?
>>
>
> I would defer to the arm64 maintainers for decisions about the arm64
> specific parts of the patch set.  That said, many of the arm64 specific
> patches depend on the arm64 for-next/core branch, so you would have to be
> careful about merge ordering if you pull these in before the for-next/core
> branch is merged.

Fair enough.  I will wait for an update then.

> Also FWIW, I plan on addressing Catalin's comments about 13/14 and posting a
> new version of the patch set in the next day or two.

OK, but in that case it won't be considered for 4.7 (at least not by
me), so I'd suggest sending it in the second half of the 4.7 merge
window (or about that time).

Thanks,
Rafael


From ddaney at caviumnetworks.com  Wed May 11 14:30:35 2016
From: ddaney at caviumnetworks.com (David Daney)
Date: Wed, 11 May 2016 14:30:35 -0700
Subject: [PATCH v6 00/14] ACPI NUMA support for ARM64
In-Reply-To: <CAJZ5v0h8zBEZ2nLLdk62r7uqHizUfVWamUVEriBGe1XBE6462Q@mail.gmail.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <CAJZ5v0iMDQ4pWip4vyCos0o+1DFDvXQf4XZQqC4SGjJsDO4Lnw@mail.gmail.com>
 <20160511104032.GA31374@arm.com>
 <CAJZ5v0gQMR7OUyZo5Sa3bgMYZBzdnwFaktz9JCv1ocWXw7yHTg@mail.gmail.com>
 <57339F39.3040603@caviumnetworks.com>
 <CAJZ5v0h8zBEZ2nLLdk62r7uqHizUfVWamUVEriBGe1XBE6462Q@mail.gmail.com>
Message-ID: <5733A47B.8030908@caviumnetworks.com>

On 05/11/2016 02:22 PM, Rafael J. Wysocki wrote:
> On Wed, May 11, 2016 at 11:08 PM, David Daney <ddaney at caviumnetworks.com> wrote:
>> On 05/11/2016 01:35 PM, Rafael J. Wysocki wrote:
>>>
>>> On Wed, May 11, 2016 at 12:40 PM, Will Deacon <will.deacon at arm.com> wrote:
>>>>
>>>> On Wed, May 11, 2016 at 02:43:11AM +0200, Rafael J. Wysocki wrote:
>>>>>
>>>>> On Wed, Apr 27, 2016 at 8:07 PM, David Daney <ddaney.cavm at gmail.com>
>>>>> wrote:
>>>>>>
>>>>>> From: David Daney <david.daney at cavium.com>
>>>>>>
>>>>>> Based on git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
>>>>>> for-next/core branch at commit 643d703d2d2d ("arm64: compat: Check for
>>>>>> AArch32 state")
>>>>
>>>>
>>>> [...]
>>>>
>>>>>> David Daney (2):
>>>>>>     arm64, numa: Cleanup NUMA disabled messages.
>>>>>>     acpi, numa, srat: Improve SRAT error detection and add messages.
>>>>>>
>>>>>> Hanjun Guo (11):
>>>>>>     acpi, numa: Use pr_fmt() instead of printk
>>>>>>     acpi, numa: Replace ACPI_DEBUG_PRINT() with pr_debug()
>>>>>>     acpi, numa: remove duplicate NULL check
>>>>>>     acpi, numa: move acpi_numa_slit_init() to drivers/acpi/numa.c
>>>>>>     arm64, numa: rework numa_add_memblk()
>>>>>>     x86, acpi, numa: cleanup acpi_numa_processor_affinity_init()
>>>>>>     acpi, numa: move bad_srat() and srat_disabled() to
>>>>>>       drivers/acpi/numa.c
>>>>>>     acpi, numa: remove unneeded acpi_numa=1
>>>>>>     acpi, numa: Move acpi_numa_memory_affinity_init() to
>>>>>>       drivers/acpi/numa.c
>>>>>>     arm64, acpi, numa: NUMA support based on SRAT and SLIT
>>>>>>     acpi, numa: Enable ACPI based NUMA on ARM64
>>>>>>
>>>>>> Robert Richter (1):
>>>>>>     acpi, numa: Move acpi_numa_arch_fixup() to ia64 only
>>>>>
>>>>>
>>>>> I need ACKs from the ARM64 maintainers on patches [6-7/13] and
>>>>> [13-14/14].
>>>>
>>>>
>>>> There's also a dependency on the arm64 for-next/core branch, so I've been
>>>> largely ignoring this as far as 4.6 is concerned and was planning to take
>>>> a proper look for 4.7 once the upcoming merge window is out of the way.
>>>
>>>
>>> That would be 4.7 and 4.8 respectively I suppose?
>>>
>>> Anyway, Catalin has ACKed all of them except for the [13/14], so
>>> technically I can apply [1-12/14] now and then [13-14/14] can be
>>> applied when they are ready.
>>>
>>> Do you think there will be any problems with merging [6-7/14] into 4.7
>>> via the ACPI tree?
>>>
>>
>> I would defer to the arm64 maintainers for decisions about the arm64
>> specific parts of the patch set.  That said, many of the arm64 specific
>> patches depend on the arm64 for-next/core branch, so you would have to be
>> careful about merge ordering if you pull these in before the for-next/core
>> branch is merged.
>
> Fair enough.  I will wait for an update then.
>
>> Also FWIW, I plan on addressing Catalin's comments about 13/14 and posting a
>> new version of the patch set in the next day or two.
>
> OK, but in that case it won't be considered for 4.7 (at least not by
> me), so I'd suggest sending it in the second half of the 4.7 merge
> window (or about that time).

To be candid, I would very much like for you to pull in as many of the 
patches as you are comfortable with as soon as possible.

I don't know where Will and Catalin stand on this, and their opinion is 
obviously important, but getting 1-12/14 merged to v4.7 and deferring 
the last two for v4.8 would simplify the whole process for me.  The 
drawback is carrying dead code around until the final parts are merged.

David Daney


From chris.brand at broadcom.com  Wed May 11 14:36:16 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Wed, 11 May 2016 14:36:16 -0700
Subject: [PATCH v2 0/6] Support BCM23550 SoC
Message-ID: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>

This patchset introduces support for the BCM23550 SoC and the Broadcom
Sparrow development board.

It modifies the BCM21664 support slightly to share code between the two.

With this patchset, a multi-v7 kernel brings up all 4 CPUs on a Sparrow
board, and gets to a shell prompt. Many of the IP blocks that are shared
with BCM28155 and BCM21664 are also functional, although not all have
been thoroughly tested.

Changes since v1
- Moved chosen node from dtsi to dts file
- Added stdout-path property to chosen node in dts
- Removed "-cpu-method" from CPU enable method name

Chris Brand (6):
  power: Introduce Broadcom kona reset driver
  arm: bcm21664: Remove reset code
  docs: Document BCM23550 bindings
  arm: Add support for Broadcom BCM23550 SoC
  arm: BCM23550 SMP support
  arm: dt: bcm23550: Add device tree files

 .../bindings/arm/bcm/brcm,bcm23550-cpu-method.txt  |  36 ++
 .../devicetree/bindings/arm/bcm/brcm,bcm23550.txt  |  15 +
 Documentation/devicetree/bindings/arm/cpus.txt     |   1 +
 arch/arm/boot/dts/Makefile                         |   3 +-
 arch/arm/boot/dts/bcm23550-sparrow.dts             |  80 ++++
 arch/arm/boot/dts/bcm23550.dtsi                    | 415 +++++++++++++++++++++
 arch/arm/mach-bcm/Kconfig                          |  12 +-
 arch/arm/mach-bcm/Makefile                         |   5 +-
 arch/arm/mach-bcm/board_bcm21664.c                 |  42 ---
 arch/arm/mach-bcm/board_bcm23550.c                 |  25 ++
 arch/arm/mach-bcm/platsmp.c                        |  58 +++
 drivers/power/reset/Kconfig                        |  10 +
 drivers/power/reset/Makefile                       |   1 +
 drivers/power/reset/brcm-kona-reset.c              |  75 ++++
 14 files changed, 732 insertions(+), 46 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt
 create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt
 create mode 100644 arch/arm/boot/dts/bcm23550-sparrow.dts
 create mode 100644 arch/arm/boot/dts/bcm23550.dtsi
 create mode 100644 arch/arm/mach-bcm/board_bcm23550.c
 create mode 100644 drivers/power/reset/brcm-kona-reset.c

-- 
1.9.1



From chris.brand at broadcom.com  Wed May 11 14:36:17 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Wed, 11 May 2016 14:36:17 -0700
Subject: [PATCH v2 1/6] power: Introduce Broadcom kona reset driver
In-Reply-To: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
References: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <1463002582-6875-2-git-send-email-chris.brand@broadcom.com>

This driver supports reset on both BCM21664 and BCM23550.
Code is being moved from arch/arm/mach-bcm/board_bcm21664.c

Signed-off-by: Chris Brand <chris.brand at broadcom.com>
---
 drivers/power/reset/Kconfig           | 10 +++++
 drivers/power/reset/Makefile          |  1 +
 drivers/power/reset/brcm-kona-reset.c | 75 +++++++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)
 create mode 100644 drivers/power/reset/brcm-kona-reset.c

diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 0a6408a39c66..1a7c49f3650a 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -38,6 +38,16 @@ config POWER_RESET_AXXIA
 
 	  Say Y if you have an Axxia family SoC.
 
+config POWER_RESET_BRCMKONA
+	bool "Broadcom Kona reset driver"
+	depends on ARM || COMPILE_TEST
+	default ARCH_BCM_MOBILE
+	help
+	  This driver provides restart support for Broadcom Kona chips.
+
+	  Say Y here if you have a Broadcom Kona-based board and you wish
+	  to have restart support.
+
 config POWER_RESET_BRCMSTB
 	bool "Broadcom STB reset driver"
 	depends on ARM || MIPS || COMPILE_TEST
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 096fa67047f6..ddb9a5b35480 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
 obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o
 obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
 obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
+obj-$(CONFIG_POWER_RESET_BRCMKONA) += brcm-kona-reset.o
 obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
 obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
diff --git a/drivers/power/reset/brcm-kona-reset.c b/drivers/power/reset/brcm-kona-reset.c
new file mode 100644
index 000000000000..d6f2070be89c
--- /dev/null
+++ b/drivers/power/reset/brcm-kona-reset.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; 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/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/reboot.h>
+
+#include <asm/mach/arch.h>
+
+#define RSTMGR_REG_WR_ACCESS_OFFSET	0
+#define RSTMGR_REG_CHIP_SOFT_RST_OFFSET	4
+
+#define RSTMGR_WR_PASSWORD		0xa5a5
+#define RSTMGR_WR_PASSWORD_SHIFT	8
+#define RSTMGR_WR_ACCESS_ENABLE		1
+
+static void __iomem *kona_reset_base;
+
+static int kona_reset_handler(struct notifier_block *this,
+				unsigned long mode, void *cmd)
+{
+	/*
+	 * A soft reset is triggered by writing a 0 to bit 0 of the soft reset
+	 * register. To write to that register we must first write the password
+	 * and the enable bit in the write access enable register.
+	 */
+	writel((RSTMGR_WR_PASSWORD << RSTMGR_WR_PASSWORD_SHIFT) |
+		RSTMGR_WR_ACCESS_ENABLE,
+		kona_reset_base + RSTMGR_REG_WR_ACCESS_OFFSET);
+	writel(0, kona_reset_base + RSTMGR_REG_CHIP_SOFT_RST_OFFSET);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block kona_reset_nb = {
+	.notifier_call = kona_reset_handler,
+	.priority = 128,
+};
+
+static int kona_reset_probe(struct platform_device *pdev)
+{
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	kona_reset_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(kona_reset_base))
+		return PTR_ERR(kona_reset_base);
+
+	return register_restart_handler(&kona_reset_nb);
+}
+
+static const struct of_device_id of_match[] = {
+	{ .compatible = "brcm,bcm21664-resetmgr" },
+	{},
+};
+
+static struct platform_driver bcm_kona_reset_driver = {
+	.probe = kona_reset_probe,
+	.driver = {
+		.name = "brcm-kona-reset",
+		.of_match_table = of_match,
+	},
+};
+
+builtin_platform_driver(bcm_kona_reset_driver);
-- 
1.9.1



From chris.brand at broadcom.com  Wed May 11 14:36:18 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Wed, 11 May 2016 14:36:18 -0700
Subject: [PATCH v2 2/6] arm: bcm21664: Remove reset code
In-Reply-To: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
References: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <1463002582-6875-3-git-send-email-chris.brand@broadcom.com>

The kona reset driver now provides this functionality.

Signed-off-by: Chris Brand <chris.brand at broadcom.com>
---
 arch/arm/mach-bcm/board_bcm21664.c | 42 --------------------------------------
 1 file changed, 42 deletions(-)

diff --git a/arch/arm/mach-bcm/board_bcm21664.c b/arch/arm/mach-bcm/board_bcm21664.c
index 82ad5687771f..65b3db06e57a 100644
--- a/arch/arm/mach-bcm/board_bcm21664.c
+++ b/arch/arm/mach-bcm/board_bcm21664.c
@@ -11,53 +11,12 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/of_address.h>
 #include <linux/of_platform.h>
-#include <linux/io.h>
 
 #include <asm/mach/arch.h>
 
 #include "kona_l2_cache.h"
 
-#define RSTMGR_DT_STRING		"brcm,bcm21664-resetmgr"
-
-#define RSTMGR_REG_WR_ACCESS_OFFSET	0
-#define RSTMGR_REG_CHIP_SOFT_RST_OFFSET	4
-
-#define RSTMGR_WR_PASSWORD		0xa5a5
-#define RSTMGR_WR_PASSWORD_SHIFT	8
-#define RSTMGR_WR_ACCESS_ENABLE		1
-
-static void bcm21664_restart(enum reboot_mode mode, const char *cmd)
-{
-	void __iomem *base;
-	struct device_node *resetmgr;
-
-	resetmgr = of_find_compatible_node(NULL, NULL, RSTMGR_DT_STRING);
-	if (!resetmgr) {
-		pr_emerg("Couldn't find " RSTMGR_DT_STRING "\n");
-		return;
-	}
-	base = of_iomap(resetmgr, 0);
-	if (!base) {
-		pr_emerg("Couldn't map " RSTMGR_DT_STRING "\n");
-		return;
-	}
-
-	/*
-	 * A soft reset is triggered by writing a 0 to bit 0 of the soft reset
-	 * register. To write to that register we must first write the password
-	 * and the enable bit in the write access enable register.
-	 */
-	writel((RSTMGR_WR_PASSWORD << RSTMGR_WR_PASSWORD_SHIFT) |
-		RSTMGR_WR_ACCESS_ENABLE,
-		base + RSTMGR_REG_WR_ACCESS_OFFSET);
-	writel(0, base + RSTMGR_REG_CHIP_SOFT_RST_OFFSET);
-
-	/* Wait for reset */
-	while (1);
-}
-
 static void __init bcm21664_init(void)
 {
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
@@ -71,6 +30,5 @@ static const char * const bcm21664_dt_compat[] = {
 
 DT_MACHINE_START(BCM21664_DT, "BCM21664 Broadcom Application Processor")
 	.init_machine = bcm21664_init,
-	.restart = bcm21664_restart,
 	.dt_compat = bcm21664_dt_compat,
 MACHINE_END
-- 
1.9.1



From chris.brand at broadcom.com  Wed May 11 14:36:19 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Wed, 11 May 2016 14:36:19 -0700
Subject: [PATCH v2 3/6] docs: Document BCM23550 bindings
In-Reply-To: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
References: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <1463002582-6875-4-git-send-email-chris.brand@broadcom.com>

Add binding document for Broadcom BCM23550 SoC.

BCM23550 has a Cluster Dormant Control IP block that holds cores
in an idle state. Introduce a new CPU enable method in which the CDC is
accessed to bring the core online.

Signed-off-by: Chris Brand <chris.brand at broadcom.com>
---
 .../bindings/arm/bcm/brcm,bcm23550-cpu-method.txt  | 36 ++++++++++++++++++++++
 .../devicetree/bindings/arm/bcm/brcm,bcm23550.txt  | 15 +++++++++
 Documentation/devicetree/bindings/arm/cpus.txt     |  1 +
 3 files changed, 52 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt
 create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt

diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt
new file mode 100644
index 000000000000..a3af54c0e404
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt
@@ -0,0 +1,36 @@
+Broadcom Kona Family CPU Enable Method
+--------------------------------------
+This binding defines the enable method used for starting secondary
+CPUs in the following Broadcom SoCs:
+  BCM23550
+
+The enable method is specified by defining the following required
+properties in the "cpu" device tree node:
+  - enable-method = "brcm,bcm23550";
+  - secondary-boot-reg = <...>;
+
+The secondary-boot-reg property is a u32 value that specifies the
+physical address of the register used to request the ROM holding pen
+code release a secondary CPU.  The value written to the register is
+formed by encoding the target CPU id into the low bits of the
+physical start address it should jump to.
+
+Example:
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+			enable-method = "brcm,bcm23550";
+			secondary-boot-reg = <0x3500417c>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt
new file mode 100644
index 000000000000..080baad923d6
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt
@@ -0,0 +1,15 @@
+Broadcom BCM23550 device tree bindings
+--------------------------------------
+
+This document describes the device tree bindings for boards with the BCM23550
+SoC.
+
+Required root node property:
+  - compatible: brcm,bcm23550
+
+Example:
+	/ {
+		model = "BCM23550 SoC";
+		compatible = "brcm,bcm23550";
+		[...]
+	}
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index ccc62f145306..37765e76db71 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -194,6 +194,7 @@ nodes to be present and contain the properties described below.
 			    "allwinner,sun8i-a23"
 			    "arm,psci"
 			    "arm,realview-smp"
+			    "brcm,bcm23550"
 			    "brcm,bcm-nsp-smp"
 			    "brcm,brahma-b15"
 			    "marvell,armada-375-smp"
-- 
1.9.1



From chris.brand at broadcom.com  Wed May 11 14:36:20 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Wed, 11 May 2016 14:36:20 -0700
Subject: [PATCH v2 4/6] arm: Add support for Broadcom BCM23550 SoC
In-Reply-To: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
References: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <1463002582-6875-5-git-send-email-chris.brand@broadcom.com>

BCM23550 is a quad-A7 SoC used on the Broadcom "Sparrow" board.
It shares many IP blocks with other Broadcom Kona chips.

Signed-off-by: Chris Brand <chris.brand at broadcom.com>
---
 arch/arm/mach-bcm/Kconfig          | 12 ++++++++++--
 arch/arm/mach-bcm/Makefile         |  5 ++++-
 arch/arm/mach-bcm/board_bcm23550.c | 25 +++++++++++++++++++++++++
 3 files changed, 39 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-bcm/board_bcm23550.c

diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 7ef121472cdd..cb1281f115a9 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -111,9 +111,17 @@ config ARCH_BCM_21664
 	  Enable support for the BCM21664 family, which includes
 	  BCM21663 and BCM21664 variants.
 
+config ARCH_BCM_23550
+	bool "Broadcom BCM23550 SoC"
+	depends on ARCH_MULTI_V7
+	select ARCH_BCM_MOBILE
+	select HAVE_SMP
+	help
+	  Enable support for the BCM23550.
+
 config ARCH_BCM_MOBILE_L2_CACHE
 	bool "Broadcom mobile SoC level 2 cache support"
-	depends on ARCH_BCM_MOBILE
+	depends on ARCH_BCM_281XX || ARCH_BCM_21664
 	default y
 	select CACHE_L2X0
 	select ARCH_BCM_MOBILE_SMC
@@ -128,7 +136,7 @@ config ARCH_BCM_MOBILE_SMP
 	select HAVE_ARM_SCU
 	select ARM_ERRATA_764369
 	help
-	  SMP support for the BCM281XX and BCM21664 SoC families.
+	  SMP support for the BCM281XX, BCM21664 and BCM23550 SoC families.
 	  Provided as an option so SMP support for SoCs of this type
 	  can be disabled for an SMP-enabled kernel.
 
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile
index 7d665151c772..980f5850097c 100644
--- a/arch/arm/mach-bcm/Makefile
+++ b/arch/arm/mach-bcm/Makefile
@@ -26,7 +26,10 @@ obj-$(CONFIG_ARCH_BCM_281XX)	+= board_bcm281xx.o
 # BCM21664
 obj-$(CONFIG_ARCH_BCM_21664)	+= board_bcm21664.o
 
-# BCM281XX and BCM21664 SMP support
+# BCM23550
+obj-$(CONFIG_ARCH_BCM_23550)	+= board_bcm23550.o
+
+# BCM281XX, BCM21664 and BCM23550 SMP support
 obj-$(CONFIG_ARCH_BCM_MOBILE_SMP) += platsmp.o
 
 # BCM281XX and BCM21664 L2 cache control
diff --git a/arch/arm/mach-bcm/board_bcm23550.c b/arch/arm/mach-bcm/board_bcm23550.c
new file mode 100644
index 000000000000..0ac01debd077
--- /dev/null
+++ b/arch/arm/mach-bcm/board_bcm23550.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+
+static const char * const bcm23550_dt_compat[] = {
+	"brcm,bcm23550",
+	NULL,
+};
+
+DT_MACHINE_START(BCM23550_DT, "BCM23550 Broadcom Application Processor")
+	.dt_compat = bcm23550_dt_compat,
+MACHINE_END
-- 
1.9.1



From chris.brand at broadcom.com  Wed May 11 14:36:21 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Wed, 11 May 2016 14:36:21 -0700
Subject: [PATCH v2 5/6] arm: BCM23550 SMP support
In-Reply-To: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
References: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <1463002582-6875-6-git-send-email-chris.brand@broadcom.com>

BCM23550 has a Cluster Dormant Control IP block that holds cores
in an idle state. Support a new CPU enable method in which the CDC is
accessed to bring the core online.

Signed-off-by: Raymond Ngun <raymond.ngun at broadcom.com>
Signed-off-by: Chris Brand <chris.brand at broadcom.com>
---
 arch/arm/mach-bcm/platsmp.c | 58 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/arch/arm/mach-bcm/platsmp.c b/arch/arm/mach-bcm/platsmp.c
index cfae9c71fb74..33c4d8349f95 100644
--- a/arch/arm/mach-bcm/platsmp.c
+++ b/arch/arm/mach-bcm/platsmp.c
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 #include <linux/jiffies.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 
@@ -255,6 +256,57 @@ static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
 	return -ENXIO;
 }
 
+/* Cluster Dormant Control command to bring CPU into a running state */
+#define CDC_CMD			6
+#define CDC_CMD_OFFSET		0
+#define CDC_CMD_REG(cpu)	(CDC_CMD_OFFSET + 4*(cpu))
+
+/*
+ * BCM23550 has a Cluster Dormant Control block that keeps the core in
+ * idle state. A command needs to be sent to the block to bring the CPU
+ * into running state.
+ */
+static int bcm23550_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	void __iomem *cdc_base;
+	struct device_node *dn;
+	char *name;
+	int ret;
+
+	/* Make sure a CDC node exists before booting the
+	 * secondary core.
+	 */
+	name = "brcm,bcm23550-cdc";
+	dn = of_find_compatible_node(NULL, NULL, name);
+	if (!dn) {
+		pr_err("unable to find cdc node\n");
+		return -ENODEV;
+	}
+
+	cdc_base = of_iomap(dn, 0);
+	of_node_put(dn);
+
+	if (!cdc_base) {
+		pr_err("unable to remap cdc base register\n");
+		return -ENOMEM;
+	}
+
+	/* Boot the secondary core */
+	ret = kona_boot_secondary(cpu, idle);
+	if (ret)
+		goto out;
+
+	/* Bring this CPU to RUN state so that nIRQ nFIQ
+	 * signals are unblocked.
+	 */
+	writel_relaxed(CDC_CMD, cdc_base + CDC_CMD_REG(cpu));
+
+out:
+	iounmap(cdc_base);
+
+	return ret;
+}
+
 static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	int ret;
@@ -283,6 +335,12 @@ static const struct smp_operations bcm_smp_ops __initconst = {
 CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
 			&bcm_smp_ops);
 
+static const struct smp_operations bcm23550_smp_ops __initconst = {
+	.smp_boot_secondary	= bcm23550_boot_secondary,
+};
+CPU_METHOD_OF_DECLARE(bcm_smp_bcm23550, "brcm,bcm23550",
+			&bcm23550_smp_ops);
+
 static const struct smp_operations nsp_smp_ops __initconst = {
 	.smp_prepare_cpus	= bcm_smp_prepare_cpus,
 	.smp_boot_secondary	= nsp_boot_secondary,
-- 
1.9.1



From chris.brand at broadcom.com  Wed May 11 14:36:22 2016
From: chris.brand at broadcom.com (Chris Brand)
Date: Wed, 11 May 2016 14:36:22 -0700
Subject: [PATCH v2 6/6] arm: dt: bcm23550: Add device tree files
In-Reply-To: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
References: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
Message-ID: <1463002582-6875-7-git-send-email-chris.brand@broadcom.com>

Add device tree files for the Broadcom BCM23550 SoC and the
Broadcom Sparrow board.

Signed-off-by: Chris Brand <chris.brand at broadcom.com>
---
 arch/arm/boot/dts/Makefile             |   3 +-
 arch/arm/boot/dts/bcm23550-sparrow.dts |  80 +++++++
 arch/arm/boot/dts/bcm23550.dtsi        | 415 +++++++++++++++++++++++++++++++++
 3 files changed, 497 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boot/dts/bcm23550-sparrow.dts
 create mode 100644 arch/arm/boot/dts/bcm23550.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 95c1923ce6fa..72ab80fa9079 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -95,7 +95,8 @@ dtb-$(CONFIG_ARCH_BCM_CYGNUS) += \
 	bcm958305k.dtb
 dtb-$(CONFIG_ARCH_BCM_MOBILE) += \
 	bcm28155-ap.dtb \
-	bcm21664-garnet.dtb
+	bcm21664-garnet.dtb \
+	bcm23550-sparrow.dtb
 dtb-$(CONFIG_ARCH_BCM_NSP) += \
 	bcm958625k.dtb
 dtb-$(CONFIG_ARCH_BERLIN) += \
diff --git a/arch/arm/boot/dts/bcm23550-sparrow.dts b/arch/arm/boot/dts/bcm23550-sparrow.dts
new file mode 100644
index 000000000000..4d525ccb48c8
--- /dev/null
+++ b/arch/arm/boot/dts/bcm23550-sparrow.dts
@@ -0,0 +1,80 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright(c) 2016 Broadcom.  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in
+ *      the documentation and/or other materials provided with the
+ *      distribution.
+ *    * Neither the name of Broadcom Corporation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "bcm23550.dtsi"
+
+/ {
+	model = "BCM23550 Sparrow board";
+	compatible = "brcm,bcm23550-sparrow", "brcm,bcm23550";
+
+	chosen {
+		stdout-path = "/slaves at 3e000000/serial at 0:115200n8";
+		bootargs = "console=ttyS0,115200n8";
+	};
+
+	memory {
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+};
+
+&uartb {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&sdio1 {
+	max-frequency = <48000000>;
+	status = "okay";
+};
+
+&sdio2 {
+	non-removable;
+	max-frequency = <48000000>;
+	status = "okay";
+};
+
+&sdio4 {
+	max-frequency = <48000000>;
+	cd-gpios = <&gpio 91 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/bcm23550.dtsi b/arch/arm/boot/dts/bcm23550.dtsi
new file mode 100644
index 000000000000..a7a643f38385
--- /dev/null
+++ b/arch/arm/boot/dts/bcm23550.dtsi
@@ -0,0 +1,415 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright(c) 2016 Broadcom.  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in
+ *      the documentation and/or other materials provided with the
+ *      distribution.
+ *    * Neither the name of Broadcom Corporation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/* BCM23550 and BCM21664 have almost identical clocks */
+#include "dt-bindings/clock/bcm21664.h"
+
+#include "skeleton.dtsi"
+
+/ {
+	model = "BCM23550 SoC";
+	compatible = "brcm,bcm23550";
+	interrupt-parent = <&gic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0>;
+			clock-frequency = <1000000000>;
+		};
+
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			enable-method = "brcm,bcm23550";
+			secondary-boot-reg = <0x35004178>;
+			reg = <1>;
+			clock-frequency = <1000000000>;
+		};
+
+		cpu2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			enable-method = "brcm,bcm23550";
+			secondary-boot-reg = <0x35004178>;
+			reg = <2>;
+			clock-frequency = <1000000000>;
+		};
+
+		cpu3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			enable-method = "brcm,bcm23550";
+			secondary-boot-reg = <0x35004178>;
+			reg = <3>;
+			clock-frequency = <1000000000>;
+		};
+	};
+
+	/* Hub bus */
+	hub at 34000000 {
+		compatible = "simple-bus";
+		ranges = <0 0x34000000 0x102f83ac>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		smc at 4e000 {
+			compatible = "brcm,bcm23550-smc", "brcm,kona-smc";
+			reg = <0x0004e000 0x400>; /* 1 KiB in SRAM */
+		};
+
+		resetmgr: reset-controller at 1001f00 {
+			compatible = "brcm,bcm21664-resetmgr";
+			reg = <0x01001f00 0x24>;
+		};
+
+		gpio: gpio at 1003000 {
+			compatible = "brcm,bcm23550-gpio", "brcm,kona-gpio";
+			reg = <0x01003000 0x524>;
+			interrupts =
+			       <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH
+				GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH
+				GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH
+				GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+			#gpio-cells = <2>;
+			#interrupt-cells = <2>;
+			gpio-controller;
+			interrupt-controller;
+		};
+
+		timer at 1006000 {
+			compatible = "brcm,kona-timer";
+			reg = <0x01006000 0x1c>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&aon_ccu BCM21664_AON_CCU_HUB_TIMER>;
+		};
+	};
+
+	/* Slaves bus */
+	slaves at 3e000000 {
+		compatible = "simple-bus";
+		ranges = <0 0x3e000000 0x0001c070>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		uartb: serial at 0 {
+			compatible = "snps,dw-apb-uart";
+			status = "disabled";
+			reg = <0x00000000 0x118>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB>;
+			interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+		};
+
+		uartb2: serial at 1000 {
+			compatible = "snps,dw-apb-uart";
+			status = "disabled";
+			reg = <0x00001000 0x118>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB2>;
+			interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+		};
+
+		uartb3: serial at 2000 {
+			compatible = "snps,dw-apb-uart";
+			status = "disabled";
+			reg = <0x00002000 0x118>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_UARTB3>;
+			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+		};
+
+		bsc1: i2c at 16000 {
+			compatible = "brcm,kona-i2c";
+			reg = <0x00016000 0x70>;
+			interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC1>;
+			status = "disabled";
+		};
+
+		bsc2: i2c at 17000 {
+			compatible = "brcm,kona-i2c";
+			reg = <0x00017000 0x70>;
+			interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC2>;
+			status = "disabled";
+		};
+
+		bsc3: i2c at 18000 {
+			compatible = "brcm,kona-i2c";
+			reg = <0x00018000 0x70>;
+			interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC3>;
+			status = "disabled";
+		};
+
+		bsc4: i2c at 1c000 {
+			compatible = "brcm,kona-i2c";
+			reg = <0x0001c000 0x70>;
+			interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&slave_ccu BCM21664_SLAVE_CCU_BSC4>;
+			status = "disabled";
+		};
+	};
+
+	/* Apps bus */
+	apps at 3e300000 {
+		compatible = "simple-bus";
+		ranges = <0 0x3e300000 0x01b77000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		usbotg: usb at e20000 {
+			compatible = "snps,dwc2";
+			reg = <0x00e20000 0x10000>;
+			interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&usb_otg_ahb_clk>;
+			clock-names = "otg";
+			phys = <&usbphy>;
+			phy-names = "usb2-phy";
+			status = "disabled";
+		};
+
+		usbphy: usb-phy at e30000 {
+			compatible = "brcm,kona-usb2-phy";
+			reg = <0x00e30000 0x28>;
+			#phy-cells = <0>;
+			status = "disabled";
+		};
+
+		sdio1: sdio at e80000 {
+			compatible = "brcm,kona-sdhci";
+			reg = <0x00e80000 0x801c>;
+			interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO1>;
+			status = "disabled";
+		};
+
+		sdio2: sdio at e90000 {
+			compatible = "brcm,kona-sdhci";
+			reg = <0x00e90000 0x801c>;
+			interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO2>;
+			status = "disabled";
+		};
+
+		sdio3: sdio at ea0000 {
+			compatible = "brcm,kona-sdhci";
+			reg = <0x00ea0000 0x801c>;
+			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO3>;
+			status = "disabled";
+		};
+
+		sdio4: sdio at eb0000 {
+			compatible = "brcm,kona-sdhci";
+			reg = <0x00eb0000 0x801c>;
+			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&master_ccu BCM21664_MASTER_CCU_SDIO4>;
+			status = "disabled";
+		};
+
+		cdc: cdc at 1b0e000 {
+			compatible = "brcm,bcm23550-cdc";
+			reg = <0x01b0e000 0x78>;
+		};
+
+		gic: interrupt-controller at 1b21000 {
+			compatible = "arm,cortex-a9-gic";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0x01b21000 0x1000>,
+			      <0x01b22000 0x1000>;
+		};
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/*
+		 * Fixed clocks are defined before CCUs whose
+		 * clocks may depend on them.
+		 */
+
+		ref_32k_clk: ref_32k {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		bbl_32k_clk: bbl_32k {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		ref_13m_clk: ref_13m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <13000000>;
+		};
+
+		var_13m_clk: var_13m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <13000000>;
+		};
+
+		dft_19_5m_clk: dft_19_5m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <19500000>;
+		};
+
+		ref_crystal_clk: ref_crystal {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <26000000>;
+		};
+
+		ref_52m_clk: ref_52m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <52000000>;
+		};
+
+		var_52m_clk: var_52m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <52000000>;
+		};
+
+		usb_otg_ahb_clk: usb_otg_ahb {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <52000000>;
+		};
+
+		ref_96m_clk: ref_96m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <96000000>;
+		};
+
+		var_96m_clk: var_96m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <96000000>;
+		};
+
+		ref_104m_clk: ref_104m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <104000000>;
+		};
+
+		var_104m_clk: var_104m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <104000000>;
+		};
+
+		ref_156m_clk: ref_156m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <156000000>;
+		};
+
+		var_156m_clk: var_156m {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <156000000>;
+		};
+
+		root_ccu: root_ccu {
+			compatible = BCM21664_DT_ROOT_CCU_COMPAT;
+			reg = <0x35001000 0x0f00>;
+			#clock-cells = <1>;
+			clock-output-names = "frac_1m";
+		};
+
+		aon_ccu: aon_ccu {
+			compatible = BCM21664_DT_AON_CCU_COMPAT;
+			reg = <0x35002000 0x0f00>;
+			#clock-cells = <1>;
+			clock-output-names = "hub_timer";
+		};
+
+		slave_ccu: slave_ccu {
+			compatible = BCM21664_DT_SLAVE_CCU_COMPAT;
+			reg = <0x3e011000 0x0f00>;
+			#clock-cells = <1>;
+			clock-output-names = "uartb",
+					     "uartb2",
+					     "uartb3",
+					     "bsc1",
+					     "bsc2",
+					     "bsc3",
+					     "bsc4";
+		};
+
+		master_ccu: master_ccu {
+			compatible = BCM21664_DT_MASTER_CCU_COMPAT;
+			reg = <0x3f001000 0x0f00>;
+			#clock-cells = <1>;
+			clock-output-names = "sdio1",
+					     "sdio2",
+					     "sdio3",
+					     "sdio4",
+					     "sdio1_sleep",
+					     "sdio2_sleep",
+					     "sdio3_sleep",
+					     "sdio4_sleep";
+		};
+	};
+};
-- 
1.9.1



From dianders at chromium.org  Wed May 11 14:40:48 2016
From: dianders at chromium.org (Douglas Anderson)
Date: Wed, 11 May 2016 14:40:48 -0700
Subject: [PATCH v2] mmc: dw_mmc: rockchip: Set the drive phase properly
Message-ID: <1463002848-580-1-git-send-email-dianders@chromium.org>

Historically for Rockchip devices we've relied on the power-on
default (or perhaps the firmware setting) to get the correct drive
phase for dw_mmc devices.  This worked OK for the most part, but:

* Relying on the setting just "being right" is a bit fragile.

* As soon as there is an instance where the power on default is wrong or
  where the firmware didn't configure this properly then we'll get a
  mysterious failure.

Let's explicitly set this phase in the kernel.

The comments inside this patch try to explain the situation quite
throughly, but the high level overview of this is:

Before this patch on rk3288 devices tested:
* eMMC: 180 degrees
* SDMMC/SDIO0/SDIO1: 90 degrees

After this patch:
* Use 90 degree phase offset usually.
* Use 180 degree phase offset for MMC_DDR52, SDR104, HS200.

That means we are _changing_ behavior for those devices in this way:

* If we have HS200 eMMC or DDR52 eMMC, we'll run ID mode at 90
  degrees (vs 180) but otherwise have no change.

* For any non-HS200 / non-DDR52 eMMC devices we'll now _always_ run at
  90 degrees (vs 180).  It seems fairly unlikely that building modern
  hardware is using an eMMC that isn't using DDR52 or HS200, of course.

* For SDR104 cards we'll now run with 180 degree phase offset (vs 90).
  It's expected that 90 degree phase offset would have worked OK, but
  this gives us extra margin.

I have tested this by inserting my collection of uSD cards (mostly UHS,
though a few not) into a veyron_minnie and confirmed that they still
seem to enumerate properly.  For a subset of them I tried putting a
filesystem on them and also tried running mmc_test.

Signed-off-by: Douglas Anderson <dianders at chromium.org>
---
Changes in v2:
- Now use 90 degrees for some modes; updated comments to say why.

 drivers/mmc/host/dw_mmc-rockchip.c | 64 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index 8c20b81cafd8..8068fa887db8 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -66,6 +66,70 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
 	/* Make sure we use phases which we can enumerate with */
 	if (!IS_ERR(priv->sample_clk))
 		clk_set_phase(priv->sample_clk, priv->default_sample_phase);
+
+	/*
+	 * Set the drive phase offset based on speed mode to achieve hold times.
+	 *
+	 * That this is _not_ a value that is dynamically tuned and is also
+	 * _not_ a value that will vary from board to board.  It is a value
+	 * that could vary between different SoC models if they had massively
+	 * different output clock delays inside their dw_mmc IP block (delay_o),
+	 * but since it's OK to overshoot a little we don't need to do complex
+	 * calculations and can pick values that will just work for everyone.
+	 *
+	 * When picking values we'll stick with picking 0/90/180/270 since
+	 * those can be made very accurately on all known Rockchip SoCs.
+	 *
+	 * Note that these values match values from the DesignWare Databook
+	 * tables for the most part except for SDR12 and "ID mode".  For those
+	 * two modes the databook calculations assume a clock in of 50MHz.  As
+	 * seen above, we always use a clock in rate that is exactly the
+	 * card's input clock (times RK3288_CLKGEN_DIV, but that gets divided
+	 * back out before the controller sees it).
+	 *
+	 * From measurement of a single device, it appears that delay_o is
+	 * about .5 ns.  Since we try to leave a bit of margin, it's expected
+	 * that numbers here will be fine even with much larger delay_o
+	 * (the 1.4 ns assumed by the DesignWare Databook would result in the
+	 * same results, for instance).
+	 */
+	if (!IS_ERR(priv->drv_clk)) {
+		int phase;
+
+		/*
+		 * In almost all cases a 90 degree phase offset will provide
+		 * sufficient hold times across all valid input clock rates
+		 * assuming delay_o is not absurd for a given SoC.  We'll use
+		 * that as a default.
+		 */
+		phase = 90;
+
+		switch (ios->timing) {
+		case MMC_TIMING_MMC_DDR52:
+			/*
+			 * Since clock in rate with MMC_DDR52 is doubled when
+			 * bus width is 8 we need to double the phase offset
+			 * to get the same timings.
+			 */
+			if (ios->bus_width == MMC_BUS_WIDTH_8)
+				phase = 180;
+			break;
+		case MMC_TIMING_UHS_SDR104:
+		case MMC_TIMING_MMC_HS200:
+			/*
+			 * In the case of 150 MHz clock (typical max for
+			 * Rockchip SoCs), 90 degree offset will add a delay
+			 * of 1.67 ns.  That will meet min hold time of .8 ns
+			 * as long as clock output delay is < .87 ns.  On
+			 * SoCs measured this seems to be OK, but it doesn't
+			 * hurt to give margin here, so we use 180.
+			 */
+			phase = 180;
+			break;
+		}
+
+		clk_set_phase(priv->drv_clk, phase);
+	}
 }
 
 #define NUM_PHASES			360
-- 
2.8.0.rc3.226.g39d4020



From uurprV at mail.com  Wed May 11 15:05:59 2016
From: uurprV at mail.com (=?utf-8?B?0JDQu9C10LrRgdC10Lkg0J/QvtC/0L7QsiAo0JfQsNC10Lwp?=)
Date: Wed, 11 May 2016 22:05:59 +0000
Subject: =?utf-8?B?0J/RgNC10LTQu9Cw0LPQsNC10Lwg0LfQsNC50LzRiyDQv9C+0LQg0LfQsNC70L7QsyDQvtCx0YrQtdC60YLQvtCyINC90LXQtNCy0LjQttC40LzQvtGB0YLQuC4=?=
Message-ID: <mailman.22.1463004567.1636.linux-arm-kernel@lists.infradead.org>

????? ??? ????? ???????? ???????????? ???????????? 
? ?????????? ? ????????????? ??????? 
??? ?????????? ??? ? ???????????

??????? ??????? ??? ??????? ???????????? ( ????????? ??? ?????, ??????, ???????????????? ?????????, ??????? ?????????, ???????? ?????????).

??????? ?????? ????? ?????? ???????? ? ????????? ?? ????? ????, ???????? ??????? ??? ???????????? ????????????.
????????? ????? ????????? ?????????? ???? ? ??????????? ? ???????????? ? ?????????? ?????????.
????????? ???????? ????? ???? ?????? ??? ???????????, ??? ? ? ????? ????????? ?????.

?????? ?? ?????? ?? I8% ? ??? (??? ??????? ???????? ? ?????????????? ????????).
???? ???????? ?????????? ???????? ?? 5 ???.

???????? ????? ????????? ?????????? ?? ??????? ?? ????? ?????:
http://?????-???-????????????.??

From nkaje at codeaurora.org  Wed May 11 15:09:59 2016
From: nkaje at codeaurora.org (Naveen Kaje)
Date: Wed, 11 May 2016 16:09:59 -0600
Subject: [PATCH 1/2] i2c: qup: add ACPI support
In-Reply-To: <000201d1aa82$07b3f680$171be380$@codeaurora.org>
References: <1462317959-11632-1-git-send-email-nkaje@codeaurora.org>
 <000201d1aa82$07b3f680$171be380$@codeaurora.org>
Message-ID: <e31e85f4-93f7-f9ad-295f-76b5dc28b9e2@codeaurora.org>



On 5/10/2016 12:05 AM, Sricharan wrote:
> +additional lists
>
>> Add support to get the device parameters from ACPI. Assume that the clocks
>> are managed by firmware.
>>
>> Signed-off-by: Naveen Kaje <nkaje at codeaurora.org>
>> ---
> <snip>
>> +	bool input_clk_ctrl = true;
>>
>>   	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
>>   	if (!qup)
>> @@ -1372,7 +1378,14 @@ static int qup_i2c_probe(struct platform_device
>> *pdev)
>>   	init_completion(&qup->xfer);
>>   	platform_set_drvdata(pdev, qup);
>>
>> -	of_property_read_u32(node, "clock-frequency", &clk_freq);
>> +	ret = device_property_read_u32(qup->dev, "clock-frequency",
>> &clk_freq);
>> +	if (ret) {
>> +		dev_warn(qup->dev, "using default clock-frequency values");
>> +		clk_freq = DEFAULT_CLK_FREQ;
>> +	}
>> +
>> +	if (ACPI_HANDLE(qup->dev) && !node)
>> +		input_clk_ctrl = false;
>>
>>   	if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-
>> v1.1.1")) {
>>   		qup->adap.algo = &qup_i2c_algo;
>> @@ -1454,20 +1467,29 @@ nodma:
>>   		return qup->irq;
>>   	}
>>
>> -	qup->clk = devm_clk_get(qup->dev, "core");
>> -	if (IS_ERR(qup->clk)) {
>> -		dev_err(qup->dev, "Could not get core clock\n");
>> -		return PTR_ERR(qup->clk);
>> -	}
>> +	if (input_clk_ctrl) {
>       The above ACPI_HANDLE check can be directly used here and avoid the
> variable.
Thanks for reviewing. Will do in V2.
>
>> +		qup->clk = devm_clk_get(qup->dev, "core");
>> +		if (IS_ERR(qup->clk)) {
>> +			dev_err(qup->dev, "Could not get core clock\n");
>> +			return PTR_ERR(qup->clk);
>> +		}
>>
>> -	qup->pclk = devm_clk_get(qup->dev, "iface");
>> -	if (IS_ERR(qup->pclk)) {
>> -		dev_err(qup->dev, "Could not get iface clock\n");
>> -		return PTR_ERR(qup->pclk);
>> +		qup->pclk = devm_clk_get(qup->dev, "iface");
>> +		if (IS_ERR(qup->pclk)) {
>> +			dev_err(qup->dev, "Could not get iface clock\n");
>> +			return PTR_ERR(qup->pclk);
>> +		}
>> +		qup_i2c_enable_clocks(qup);
>> +		src_clk_freq = clk_get_rate(qup->clk);
>> +	} else {
>> +		ret = device_property_read_u32(qup->dev,
>> +				"src-clock-hz", &src_clk_freq);
>> +		if (ret) {
>> +			dev_warn(qup->dev, "using default src-clock-hz");
>> +			src_clk_freq = DEFAULT_SRC_CLK;
>> +		}
>>   	}
>>
>> -	qup_i2c_enable_clocks(qup);
>> -
>>   	/*
>>   	 * Bootloaders might leave a pending interrupt on certain QUP's,
>>   	 * so we reset the core before registering for interrupts.
>> @@ -1514,7 +1536,6 @@ nodma:
>>   	size = QUP_INPUT_FIFO_SIZE(io_mode);
>>   	qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
>>
>> -	src_clk_freq = clk_get_rate(qup->clk);
>>   	fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
>>   	hs_div = 3;
>>   	qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff); @@ -1534,6 +1555,8
>> @@ nodma:
>>   	qup->adap.dev.parent = qup->dev;
>>   	qup->adap.dev.of_node = pdev->dev.of_node;
>>   	qup->is_last = true;
>> +	if (ACPI_HANDLE(qup->dev))
>> +		ACPI_COMPANION_SET(&qup->adap.dev,
>> ACPI_COMPANION(qup->dev));
>      Can we move this inside the above check.
Will do in V2.
>>   	strlcpy(qup->adap.name, "QUP I2C adapter", sizeof(qup-
>>> adap.name));
>> @@ -1639,6 +1662,13 @@ static const struct of_device_id
>> qup_i2c_dt_match[] = {  };  MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
>>
>> +#if IS_ENABLED(CONFIG_ACPI)
>> +static const struct acpi_device_id qup_i2c_acpi_match[] = {
>> +	{ "QCOM8010"},
>> +	{ },
>> +};
>> +MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_ids); #endif
>>   static struct platform_driver qup_i2c_driver = {
>>   	.probe  = qup_i2c_probe,
>>   	.remove = qup_i2c_remove,
>> @@ -1646,6 +1676,7 @@ static struct platform_driver qup_i2c_driver = {
>>   		.name = "i2c_qup",
>>   		.pm = &qup_i2c_qup_pm_ops,
>>   		.of_match_table = qup_i2c_dt_match,
>> +		.acpi_match_table = ACPI_PTR(qup_i2c_acpi_match),
>   Should this also be in #if IS_ENABLED(CONFIG_ACPI) check ?
No, ACPI_PTR (defined in include/linux/acpi.h) takes care of setting the 
pointer value based on the availability of CONFIG_ACPI.
>
> Regards,
>   Sricharan
>



From nkaje at codeaurora.org  Wed May 11 15:11:09 2016
From: nkaje at codeaurora.org (Naveen Kaje)
Date: Wed, 11 May 2016 16:11:09 -0600
Subject: [PATCH 2/2] i2c: qup: support SMBus block read
In-Reply-To: <000b01d1aa8b$7317a300$5946e900$@codeaurora.org>
References: <1462317959-11632-1-git-send-email-nkaje@codeaurora.org>
 <1462317959-11632-2-git-send-email-nkaje@codeaurora.org>
 <000b01d1aa8b$7317a300$5946e900$@codeaurora.org>
Message-ID: <5298a5a9-77cf-ca51-8146-044c75498128@codeaurora.org>



On 5/10/2016 1:13 AM, Sricharan wrote:
> +additional lists
>
>> I2C QUP driver relies on SMBus emulation support from the framework.
>> To handle SMBus block reads, the driver should check I2C_M_RECV_LEN flag
>> and should read the first byte received as the message length.
>>
>> The driver configures the QUP hardware to read one byte. Once the message
>> length is known from this byte, the QUP hardware is configured to read the
>> rest.
>>
>> Signed-off-by: Naveen Kaje <nkaje at codeaurora.org>
>> ---
>>   drivers/i2c/busses/i2c-qup.c | 95 ++++++++++++++++++++++++++++++-------
>> -------
>>   1 file changed, 66 insertions(+), 29 deletions(-)
>>
>> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
> index
>> ef31b26..2658b67 100644
>> --- a/drivers/i2c/busses/i2c-qup.c
>> +++ b/drivers/i2c/busses/i2c-qup.c
>> @@ -526,38 +526,49 @@ static int qup_i2c_set_tags(u8 *tags, struct
>> qup_i2c_dev *qup,
>>
>>   	int last = (qup->blk.pos == (qup->blk.count - 1)) && (qup->is_last);
>>
>> -	if (qup->blk.pos == 0) {
>> -		tags[len++] = QUP_TAG_V2_START;
>> -		tags[len++] = addr & 0xff;
>> +	/* Handle SMBus block data read */
>> +	if ((msg->flags & I2C_M_RD) && (msg->flags & I2C_M_RECV_LEN)
>> &&
>> +	    (msg->len > 1)) {
>> +		tags[len++] = QUP_TAG_V2_DATARD_STOP;
>> +		data_len = qup_i2c_get_data_len(qup);
>> +		tags[len++] = data_len - 1;
>> +	} else {
>> +		if (qup->blk.pos == 0) {
>> +			tags[len++] = QUP_TAG_V2_START;
>> +			tags[len++] = addr & 0xff;
>>
>> -		if (msg->flags & I2C_M_TEN)
>> -			tags[len++] = addr >> 8;
>> -	}
>> +			if (msg->flags & I2C_M_TEN)
>> +				tags[len++] = addr >> 8;
>> +		}
>>
>> -	/* Send _STOP commands for the last block */
>> -	if (last) {
>> -		if (msg->flags & I2C_M_RD)
>> -			tags[len++] = QUP_TAG_V2_DATARD_STOP;
>> -		else
>> -			tags[len++] = QUP_TAG_V2_DATAWR_STOP;
>> -	} else {
>> -		if (msg->flags & I2C_M_RD)
>> +		/* Send _STOP commands for the last block */
>> +		if ((msg->flags & I2C_M_RD)
>> +			&& (msg->flags & I2C_M_RECV_LEN)) {
>>   			tags[len++] = QUP_TAG_V2_DATARD;
>> -		else
>> -			tags[len++] = QUP_TAG_V2_DATAWR;
>> -	}
>> +		} else if (last) {
>> +			if (msg->flags & I2C_M_RD)
>> +				tags[len++] = QUP_TAG_V2_DATARD_STOP;
>> +			else
>> +				tags[len++] = QUP_TAG_V2_DATAWR_STOP;
>> +		} else {
>> +			if (msg->flags & I2C_M_RD)
>> +				tags[len++] = QUP_TAG_V2_DATARD;
>> +			else
>> +				tags[len++] = QUP_TAG_V2_DATAWR;
>> +		}
>>
>> -	data_len = qup_i2c_get_data_len(qup);
>> +		data_len = qup_i2c_get_data_len(qup);
>>
>> -	/* 0 implies 256 bytes */
>> -	if (data_len == QUP_READ_LIMIT)
>> -		tags[len++] = 0;
>> -	else
>> -		tags[len++] = data_len;
>> +		/* 0 implies 256 bytes */
>> +		if (data_len == QUP_READ_LIMIT)
>> +			tags[len++] = 0;
>> +		else
>> +			tags[len++] = data_len;
>>
>> -	if ((msg->flags & I2C_M_RD) && last && is_dma) {
>> -		tags[len++] = QUP_BAM_INPUT_EOT;
>> -		tags[len++] = QUP_BAM_FLUSH_STOP;
>> +		if ((msg->flags & I2C_M_RD) && last && is_dma) {
>> +			tags[len++] = QUP_BAM_INPUT_EOT;
>> +			tags[len++] = QUP_BAM_FLUSH_STOP;
>> +		}
>>   	}
>>
>     Will it look simpler if we add a qup_i2c_set_tags_smb instead and add an
>     Comment ? Here it is not clear how this is different from a normal read.
Will rework this and send V2.
> <snip..>
>
>> +
>> +		/* Handle SMBus block read length */
>> +		if ((msg->flags & I2C_M_RECV_LEN) && (msg->len == 1)) {
>> +			if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
>> +				ret = -EPROTO;
>> +				goto err;
>> +			}
>> +			msg->len += msg->buf[0];
>> +			qup->pos = 0;
>> +			qup_i2c_set_read_mode_v2(qup, msg->len);
>> +			qup_i2c_issue_xfer_v2(qup, msg);
>> +			ret = qup_i2c_wait_for_complete(qup, msg);
>> +			if (ret)
>> +				goto err;
>> +			qup_i2c_set_blk_data(qup, msg);
>> +		}
>>   	} while (qup->blk.pos < qup->blk.count);
>         
>           When v2 mode is not supported this should return an error,
>           in qup_i2c_xfer for msg->flags & I2C_M_RECV_LEN
Will add a check in qup_i2c_xfer in the next version of the patch.
>
> Regards,
>   Sricharan
>



From sboyd at codeaurora.org  Wed May 11 15:13:45 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Wed, 11 May 2016 15:13:45 -0700
Subject: [PATCH v4 01/11] clk: sunxi: Add display and TCON0 clocks driver
In-Reply-To: <20160510063618.GI3733@lukather>
References: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
 <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
 <20160506223002.GE3492@codeaurora.org>
 <20160508200308.GF6167@lukather>
 <20160509223238.GW3492@codeaurora.org>
 <20160509223924.GX3492@codeaurora.org>
 <20160510063618.GI3733@lukather>
Message-ID: <20160511221345.GF3492@codeaurora.org>

On 05/10, Maxime Ripard wrote:
> Hi Stephen,
> 
> On Mon, May 09, 2016 at 03:39:24PM -0700, Stephen Boyd wrote:
> > On 05/09, Stephen Boyd wrote:
> > > 
> > > Ok I applied this one to clk-next.
> > > 
> > 
> > And I squashed this in to silence the following checker warning.
> > 
> > drivers/clk/sunxi/clk-sun4i-display.c:110:33: warning: Variable
> > length array is used.
> 
> Thanks, just out of curiosity, which checker are you talking about?
> sparse?
> 

I use sparse and smatch. I can't recall which one is complaining
here and technically smatch uses sparse underneath.

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


From sboyd at codeaurora.org  Wed May 11 15:15:41 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Wed, 11 May 2016 15:15:41 -0700
Subject: [linux-sunxi] Re: [PATCH v4 01/11] clk: sunxi: Add display and
 TCON0 clocks driver
In-Reply-To: <1462907459.9981.0.camel@plaes.org>
References: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
 <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
 <20160506223002.GE3492@codeaurora.org>
 <20160508200308.GF6167@lukather>
 <20160509223238.GW3492@codeaurora.org>
 <20160509223924.GX3492@codeaurora.org>
 <1462907459.9981.0.camel@plaes.org>
Message-ID: <20160511221541.GG3492@codeaurora.org>

On 05/10, Priit Laes wrote:
> On Mon, 2016-05-09 at 15:39 -0700, Stephen Boyd wrote:
> > On 05/09, Stephen Boyd wrote:
> > > 
> > > 
> > > Ok I applied this one to clk-next.
> > > 
> > And I squashed this in to silence the following checker warning.
> > 
> > drivers/clk/sunxi/clk-sun4i-display.c:110:33: warning: Variable
> > length array is used.
> > 
> > ---8<---
> > diff --git a/drivers/clk/sunxi/clk-sun4i-display.c
> > b/drivers/clk/sunxi/clk-sun4i-display.c
> > index f02e250e64ed..f8ff6c4a5633 100644
> > --- a/drivers/clk/sunxi/clk-sun4i-display.c
> > +++ b/drivers/clk/sunxi/clk-sun4i-display.c
> > @@ -107,7 +107,7 @@ static int sun4i_a10_display_reset_xlate(struct
> > reset_controller_dev *rcdev,
> > ?static void __init sun4i_a10_display_init(struct device_node *node,
> > ?					??const struct
> > sun4i_a10_display_clk_data *data)
> > ?{
> > -	const char *parents[data->parents];
> > +	const char *parents[4];
> 
> This change breaks at least de_[bf]e clocks which have 3 clock parents.
> 

I just used the largest data->parents number, which was 4. How
does that break anything?

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


From rafael at kernel.org  Wed May 11 15:29:02 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Thu, 12 May 2016 00:29:02 +0200
Subject: [PATCH v6 00/14] ACPI NUMA support for ARM64
In-Reply-To: <5733A47B.8030908@caviumnetworks.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <CAJZ5v0iMDQ4pWip4vyCos0o+1DFDvXQf4XZQqC4SGjJsDO4Lnw@mail.gmail.com>
 <20160511104032.GA31374@arm.com>
 <CAJZ5v0gQMR7OUyZo5Sa3bgMYZBzdnwFaktz9JCv1ocWXw7yHTg@mail.gmail.com>
 <57339F39.3040603@caviumnetworks.com>
 <CAJZ5v0h8zBEZ2nLLdk62r7uqHizUfVWamUVEriBGe1XBE6462Q@mail.gmail.com>
 <5733A47B.8030908@caviumnetworks.com>
Message-ID: <CAJZ5v0gBTANFntBSkyaRtt-BKOMC+pz_R9CwM6wKnp=Ni1dPFA@mail.gmail.com>

On Wed, May 11, 2016 at 11:30 PM, David Daney <ddaney at caviumnetworks.com> wrote:
> On 05/11/2016 02:22 PM, Rafael J. Wysocki wrote:
>>
>> On Wed, May 11, 2016 at 11:08 PM, David Daney <ddaney at caviumnetworks.com>
>> wrote:
>>>
>>> On 05/11/2016 01:35 PM, Rafael J. Wysocki wrote:
>>>>
>>>>
>>>> On Wed, May 11, 2016 at 12:40 PM, Will Deacon <will.deacon at arm.com>
>>>> wrote:
>>>>>
>>>>>
>>>>> On Wed, May 11, 2016 at 02:43:11AM +0200, Rafael J. Wysocki wrote:
>>>>>>
>>>>>>
>>>>>> On Wed, Apr 27, 2016 at 8:07 PM, David Daney <ddaney.cavm at gmail.com>
>>>>>> wrote:
>>>>>>>
>>>>>>>
>>>>>>> From: David Daney <david.daney at cavium.com>
>>>>>>>
>>>>>>> Based on
>>>>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
>>>>>>> for-next/core branch at commit 643d703d2d2d ("arm64: compat: Check
>>>>>>> for
>>>>>>> AArch32 state")
>>>>>
>>>>>
>>>>>
>>>>> [...]
>>>>>
>>>>>>> David Daney (2):
>>>>>>>     arm64, numa: Cleanup NUMA disabled messages.
>>>>>>>     acpi, numa, srat: Improve SRAT error detection and add messages.
>>>>>>>
>>>>>>> Hanjun Guo (11):
>>>>>>>     acpi, numa: Use pr_fmt() instead of printk
>>>>>>>     acpi, numa: Replace ACPI_DEBUG_PRINT() with pr_debug()
>>>>>>>     acpi, numa: remove duplicate NULL check
>>>>>>>     acpi, numa: move acpi_numa_slit_init() to drivers/acpi/numa.c
>>>>>>>     arm64, numa: rework numa_add_memblk()
>>>>>>>     x86, acpi, numa: cleanup acpi_numa_processor_affinity_init()
>>>>>>>     acpi, numa: move bad_srat() and srat_disabled() to
>>>>>>>       drivers/acpi/numa.c
>>>>>>>     acpi, numa: remove unneeded acpi_numa=1
>>>>>>>     acpi, numa: Move acpi_numa_memory_affinity_init() to
>>>>>>>       drivers/acpi/numa.c
>>>>>>>     arm64, acpi, numa: NUMA support based on SRAT and SLIT
>>>>>>>     acpi, numa: Enable ACPI based NUMA on ARM64
>>>>>>>
>>>>>>> Robert Richter (1):
>>>>>>>     acpi, numa: Move acpi_numa_arch_fixup() to ia64 only
>>>>>>
>>>>>>
>>>>>>
>>>>>> I need ACKs from the ARM64 maintainers on patches [6-7/13] and
>>>>>> [13-14/14].
>>>>>
>>>>>
>>>>>
>>>>> There's also a dependency on the arm64 for-next/core branch, so I've
>>>>> been
>>>>> largely ignoring this as far as 4.6 is concerned and was planning to
>>>>> take
>>>>> a proper look for 4.7 once the upcoming merge window is out of the way.
>>>>
>>>>
>>>>
>>>> That would be 4.7 and 4.8 respectively I suppose?
>>>>
>>>> Anyway, Catalin has ACKed all of them except for the [13/14], so
>>>> technically I can apply [1-12/14] now and then [13-14/14] can be
>>>> applied when they are ready.
>>>>
>>>> Do you think there will be any problems with merging [6-7/14] into 4.7
>>>> via the ACPI tree?
>>>>
>>>
>>> I would defer to the arm64 maintainers for decisions about the arm64
>>> specific parts of the patch set.  That said, many of the arm64 specific
>>> patches depend on the arm64 for-next/core branch, so you would have to be
>>> careful about merge ordering if you pull these in before the
>>> for-next/core
>>> branch is merged.
>>
>>
>> Fair enough.  I will wait for an update then.
>>
>>> Also FWIW, I plan on addressing Catalin's comments about 13/14 and
>>> posting a
>>> new version of the patch set in the next day or two.
>>
>>
>> OK, but in that case it won't be considered for 4.7 (at least not by
>> me), so I'd suggest sending it in the second half of the 4.7 merge
>> window (or about that time).
>
>
> To be candid, I would very much like for you to pull in as many of the
> patches as you are comfortable with as soon as possible.
>
> I don't know where Will and Catalin stand on this, and their opinion is
> obviously important, but getting 1-12/14 merged to v4.7 and deferring the
> last two for v4.8 would simplify the whole process for me.  The drawback is
> carrying dead code around until the final parts are merged.

That is not unheard of, however.

OK, I'll try to put the [1-12/14] into my linux-next branch early next
week and we'll see if that triggers any conflicts.


From bjorn.andersson at linaro.org  Wed May 11 15:30:30 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Wed, 11 May 2016 15:30:30 -0700
Subject: [PATCH 4/5] remoteproc: core: Supply framework to request,
 declare and fetch shared memory
In-Reply-To: <1462454983-13168-5-git-send-email-lee.jones@linaro.org>
References: <1462454983-13168-1-git-send-email-lee.jones@linaro.org>
 <1462454983-13168-5-git-send-email-lee.jones@linaro.org>
Message-ID: <20160511223030.GZ1256@tuxbot>

On Thu 05 May 06:29 PDT 2016, Lee Jones wrote:

> Normally used for management of; carveout, devmem and trace memory.
> 

I like the gist of this, but I have two issues from the Qualcomm land
that I think would tie into a slightly more generic version of this.

1) Registering carveouts from memory-regions, without having a resource
   table.
2) Tying the Qualcomm shared memory implementation to the appropriate
   remoteproc instance (e.g. for crash handling).

I also think we should match the subdev with entries from the resource
table based on some key, so that we don't add a limitation of only
having a single carveout per rproc.


I will do some prototyping based on your patch and will get back to you.

Regards,
Bjorn


From briannorris at chromium.org  Wed May 11 15:31:14 2016
From: briannorris at chromium.org (Brian Norris)
Date: Wed, 11 May 2016 15:31:14 -0700
Subject: [PATCH 1/2] ARM64: dts: rockchip: add sdhci/emmc for rk3399
In-Reply-To: <3e257ce2-056a-592a-9481-970da1fe0627@rock-chips.com>
References: <1462924975-69072-1-git-send-email-briannorris@chromium.org>
 <3e257ce2-056a-592a-9481-970da1fe0627@rock-chips.com>
Message-ID: <20160511223114.GA65449@google.com>

On Wed, May 11, 2016 at 09:17:38AM +0800, Shawn Lin wrote:
> + Huang Lin
> 
> On 2016/5/11 8:02, Brian Norris wrote:
> >The bindings for rk3399's SDHCI + eMMC PHY have been accepted, so let's
> >support eMMC now.
> >
> >Note that 'rockchip,rk3399-sdhci-5.1' is not documented, but per Heiko's
> >previous suggestion, we don't want to clutter the arasan doc, and it's
> >just a precautionary measure to have it.
> >
> >Signed-off-by: Brian Norris <briannorris at chromium.org>
> >---
> > arch/arm64/boot/dts/rockchip/rk3399.dtsi | 23 ++++++++++++++++++++++-
> > 1 file changed, 22 insertions(+), 1 deletion(-)
> >
> >diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> >index 46f325a143b0..947d1221592d 100644
> >--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> >+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> >@@ -215,6 +215,17 @@
> > 		status = "disabled";
> > 	};
> >
> >+	sdhci: sdhci at fe330000 {
> >+		compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
> >+		reg = <0x0 0xfe330000 0x0 0x10000>;
> >+		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
> >+		clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;
> 
> sdhci doesn't call clk_set_rate to explicitly assign clk_xin to 200MHz
> as it always assumes sdhci controller should meet the highest speed of
> each timing mode. And the internal divider will be used. So IMHO,
> clk-rockchip for 3399 *haven't* made clk_xin to be 200MHz. Let's assign
> the clk stuff to make sure it's 200MHz.
> 
> Another problem is that emmc_phy contains a configuration which should
> be consistent with clk_out(namely clk_xin/internal dividor). Now I don't
> submit unpstream patchset to expose these configurarion, but in
> prevention of some misleading, I think it's better to to it.
> 
> How about adding these?
> 
> assigned-clocks = <&cru SCLK_EMMC>;
> assigned-clock-parents = <&cru PLL_CPLL>; //may not need
> assigned-clock-rates = <200000000>;

Makes sense. Will add these.

> Still you limit your clk_out by adding max-frequency in dts for
> specific requirment.
> 
> We here manually assigne the clk_xin to be 200MHz, so defaultly
> when it's runing in HS200/HS400(ES) mode, internal divider won't
> be used(by-pass mode). So the clk jitter is better when by-passing the
> clock.
> 
> Thanks.

Brian


From briannorris at chromium.org  Wed May 11 15:32:33 2016
From: briannorris at chromium.org (Brian Norris)
Date: Wed, 11 May 2016 15:32:33 -0700
Subject: [PATCH 2/2] ARM64: dts: rockchip: enable eMMC for rk3399 EVB
In-Reply-To: <4355979.JCGxOmTVBW@phil>
References: <1462924975-69072-1-git-send-email-briannorris@chromium.org>
 <1462924975-69072-2-git-send-email-briannorris@chromium.org>
 <4355979.JCGxOmTVBW@phil>
Message-ID: <20160511223233.GB65449@google.com>

On Wed, May 11, 2016 at 04:51:58PM +0200, Heiko Stuebner wrote:
> Hi Brian,
> 
> Am Dienstag, 10. Mai 2016, 17:02:55 schrieb Brian Norris:
> > The 'mmc-hs400-enhanced-strobe' property has been acked by Rob Herring,
> > though it's still not merged.
> 
> The commit message should describe the actual change not the volatile 
> environment surrounding it :-) .
> 
> When I apply this patch the property-binding will have made it into a 
> maintainer-tree so is not valid anymore then. That is more material for the 
> "comment-section" below the "---"

Of course. I think I just felt guilty without a commit message :)

> > Signed-off-by: Brian Norris <briannorris at chromium.org>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 12 ++++++++++++
> >  1 file changed, 12 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> > b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts index
> > 1a3eb1482050..ccfd2bcf02e1 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> > +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> > @@ -89,6 +89,18 @@
> >  	status = "okay";
> >  };
> > 
> > +&emmc_phy {
> > +	status = "okay";
> > +};
> > +
> > +&sdhci {
> > +	bus-width = <8>;
> > +	mmc-hs400-1_8v;
> > +	non-removable;
> > +	mmc-hs400-enhanced-strobe;
> 
> alphabetic ordering of properties please

Will fix.

Thanks,
Brian

> > +	status = "okay";
> > +};
> > +
> >  &uart2 {
> >  	status = "okay";
> >  };
> 


From heiko at sntech.de  Wed May 11 15:36:20 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 12 May 2016 00:36:20 +0200
Subject: [PATCH 2/2] ARM64: dts: rockchip: enable eMMC for rk3399 EVB
In-Reply-To: <20160511223233.GB65449@google.com>
References: <1462924975-69072-1-git-send-email-briannorris@chromium.org>
 <4355979.JCGxOmTVBW@phil> <20160511223233.GB65449@google.com>
Message-ID: <8868581.lJFUogXGzy@phil>

Am Mittwoch, 11. Mai 2016, 15:32:33 schrieb Brian Norris:
> On Wed, May 11, 2016 at 04:51:58PM +0200, Heiko Stuebner wrote:
> > Hi Brian,
> > 
> > Am Dienstag, 10. Mai 2016, 17:02:55 schrieb Brian Norris:
> > > The 'mmc-hs400-enhanced-strobe' property has been acked by Rob
> > > Herring,
> > > though it's still not merged.
> > 
> > The commit message should describe the actual change not the volatile
> > environment surrounding it :-) .
> > 
> > When I apply this patch the property-binding will have made it into a
> > maintainer-tree so is not valid anymore then. That is more material for
> > the "comment-section" below the "---"
> 
> Of course. I think I just felt guilty without a commit message :)

I really prefer a (even simple) message being there - although I'm not as 
strict as Greg and Felipe ;-) , and in cases like this I think something 
like "enable the newly added emmc node on the rk3399 evaluation board" 
should be sufficient.


Heiko



From helgaas at kernel.org  Wed May 11 15:43:14 2016
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Wed, 11 May 2016 17:43:14 -0500
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <CAJZ5v0hgw929W5PjF0PqT+ssiOHd8TeJoSQcz4NUiAovZY2pfQ@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
 <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>
 <20160511101101.GA16101@red-moon>
 <CAJZ5v0hgw929W5PjF0PqT+ssiOHd8TeJoSQcz4NUiAovZY2pfQ@mail.gmail.com>
Message-ID: <20160511224314.GD28812@localhost>

On Wed, May 11, 2016 at 10:30:51PM +0200, Rafael J. Wysocki wrote:
> On Wed, May 11, 2016 at 12:11 PM, Lorenzo Pieralisi
> <lorenzo.pieralisi at arm.com> wrote:
> > On Tue, May 10, 2016 at 08:37:00PM +0200, Rafael J. Wysocki wrote:
> >> On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> >> > This patch provides a way to set the ACPI companion in PCI code.
> >> > We define acpi_pci_set_companion() to set the ACPI companion pointer and
> >> > call it from PCI core code. The function is stub for now.
> >> >
> >> > Signed-off-by: Jayachandran C <jchandra at broadcom.com>
> >> > Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> >> > ---
> >> >  drivers/pci/probe.c      | 2 ++
> >> >  include/linux/pci-acpi.h | 4 ++++
> >> >  2 files changed, 6 insertions(+)
> >> >
> >> > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> >> > index 8004f67..fb0b752 100644
> >> > --- a/drivers/pci/probe.c
> >> > +++ b/drivers/pci/probe.c
> >> > @@ -12,6 +12,7 @@
> >> >  #include <linux/slab.h>
> >> >  #include <linux/module.h>
> >> >  #include <linux/cpumask.h>
> >> > +#include <linux/pci-acpi.h>
> >> >  #include <linux/pci-aspm.h>
> >> >  #include <linux/aer.h>
> >> >  #include <linux/acpi.h>
> >> > @@ -2141,6 +2142,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
> >> >         bridge->dev.parent = parent;
> >> >         bridge->dev.release = pci_release_host_bridge_dev;
> >> >         dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
> >> > +       acpi_pci_set_companion(bridge);
> >>
> >> Yes, we'll probably add something similar here.
> >>
> >> Do I think now is the right time to do that?  No.
> >>
> >> >         error = pcibios_root_bridge_prepare(bridge);
> >> >         if (error) {
> >> >                 kfree(bridge);
> >> > diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
> >> > index 09f9f02..1baa515 100644
> >> > --- a/include/linux/pci-acpi.h
> >> > +++ b/include/linux/pci-acpi.h
> >> > @@ -111,6 +111,10 @@ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
> >> >  static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
> >> >  #endif /* CONFIG_ACPI */
> >> >
> >> > +static inline void acpi_pci_set_companion(struct pci_host_bridge *bridge)
> >> > +{
> >> > +}
> >> > +
> >> >  static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus)
> >> >  {
> >> >         return 0;
> >> > --
> >>
> >> Honestly, to me it looks like this series is trying very hard to avoid
> >> doing any PCI host bridge configuration stuff from arch/arm64/
> >> although (a) that might be simpler and (b) it would allow us to
> >> identify the code that's common between *all* architectures using ACPI
> >> support for host bridge configuration and to move *that* to a common
> >> place later.  As done here it seems to be following the "ARM64 is
> >> generic and the rest of the world is special" line which isn't really
> >> helpful.
> >
> > I think patch [1-2] should be merged regardless (they may require minor
> > tweaks if we decide to move pci_acpi_scan_root() to arch/arm64 though,
> > for include files location). I guess you are referring to patch 8 in
> > your comments above, which boils down to deciding whether:
> >
> > - pci_acpi_scan_root() (and unfortunately all the MCFG/ECAM handling that
> >   goes with it) should live in arch/arm64 or drivers/acpi
> 
> To be precise, everything under #ifdef CONFIG_ACPI_PCI_HOST_GENERIC or
> equivalent is de facto ARM64-specific, because (as it stands in the
> patch series) ARM64 is the only architecture that will select that
> option.  Unless you are aware of any more architectures planning to
> use ACPI (and I'm not aware of any), it will stay the only
> architecture selecting it in the foreseeable future.
> 
> Therefore you could replace CONFIG_ACPI_PCI_HOST_GENERIC with
> CONFIG_ARM64 everywhere in that code which is why in my opinion the
> code should live somewhere under arch/arm64/.
> 
> Going forward, it should be possible to identify common parts of the
> PCI host bridge configuration code in arch/ and move it to
> drivers/acpi/ or drivers/pci/, but I bet that won't be the entire code
> this series puts under CONFIG_ACPI_PCI_HOST_GENERIC.
> 
> The above leads to a quite straightforward conclusion about the order
> in which to do things: I'd add ACPI support for PCI host bridge on
> ARM64 following what's been done on ia64 (as x86 is more quirky and
> kludgy overall) as far as reasonably possible first and then think
> about moving common stuff to a common place.

That does seem like a reasonable approach.  I had hoped to get more of
this in for v4.7, but we don't have much time left.  Maybe some of
Rafael's comments can be addressed by moving and slight restructuring
and we can still squeeze it in.

The first three patches:

  PCI: Provide common functions for ECAM mapping
  PCI: generic, thunder: Use generic ECAM API
  PCI, of: Move PCI I/O space management to PCI core code

seem relatively straightforward, and I applied them to pci/arm64 with
the intent of merging them unless there are objections.  I made the
following tweaks, mainly to try to improve some error messages:

diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
index 3d52005..e1add01 100644
--- a/drivers/pci/ecam.c
+++ b/drivers/pci/ecam.c
@@ -24,9 +24,9 @@
 #include "ecam.h"
 
 /*
- * On 64 bit systems, we do a single ioremap for the whole config space
- * since we have enough virtual address range available. On 32 bit, do an
- * ioremap per bus.
+ * On 64-bit systems, we do a single ioremap for the whole config space
+ * since we have enough virtual address range available.  On 32-bit, we
+ * ioremap the config space for each bus individually.
  */
 static const bool per_bus_mapping = !config_enabled(CONFIG_64BIT);
 
@@ -42,6 +42,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
 {
 	struct pci_config_window *cfg;
 	unsigned int bus_range, bus_range_max, bsz;
+	struct resource *conflict;
 	int i, err;
 
 	if (busr->start > busr->end)
@@ -58,10 +59,10 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
 	bus_range = resource_size(&cfg->busr);
 	bus_range_max = resource_size(cfgres) >> ops->bus_shift;
 	if (bus_range > bus_range_max) {
-		dev_warn(dev, "bus max %#x reduced to %#x",
-					bus_range, bus_range_max);
 		bus_range = bus_range_max;
 		cfg->busr.end = busr->start + bus_range - 1;
+		dev_warn(dev, "ECAM area %pR can only accommodate %pR (reduced from %pR desired)\n",
+			 cfgres, &cfg->busr, busr);
 	}
 	bsz = 1 << ops->bus_shift;
 
@@ -70,9 +71,11 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
 	cfg->res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 	cfg->res.name = "PCI ECAM";
 
-	err = request_resource(&iomem_resource, &cfg->res);
-	if (err) {
-		dev_err(dev, "request ECAM res %pR failed\n", &cfg->res);
+	conflict = request_resource(&iomem_resource, &cfg->res);
+	if (conflict) {
+		err = -EBUSY;
+		dev_err(dev, "can't claim ECAM area %pR: address conflict with %s %pR\n",
+			&cfg->res, conflict->name, conflict);
 		goto err_exit;
 	}
 
diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
index 1ad2176..9878beb 100644
--- a/drivers/pci/ecam.h
+++ b/drivers/pci/ecam.h
@@ -33,7 +33,7 @@ struct pci_ecam_ops {
 
 /*
  * struct to hold the mappings of a config space window. This
- * is expected to be used as sysdata for PCI controlllers which
+ * is expected to be used as sysdata for PCI controllers that
  * use ECAM.
  */
 struct pci_config_window {
@@ -43,11 +43,11 @@ struct pci_config_window {
 	struct pci_ecam_ops		*ops;
 	union {
 		void __iomem		*win;	/* 64-bit single mapping */
-		void __iomem		**winp; /* 32-bit per bus mapping */
+		void __iomem		**winp; /* 32-bit per-bus mapping */
 	};
 };
 
-/* create and free for pci_config_window */
+/* create and free pci_config_window */
 struct pci_config_window *pci_ecam_create(struct device *dev,
 		struct resource *cfgres, struct resource *busr,
 		struct pci_ecam_ops *ops);
@@ -56,11 +56,11 @@ void pci_ecam_free(struct pci_config_window *cfg);
 /* map_bus when ->sysdata is an instance of pci_config_window */
 void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
 			       int where);
-/* default ECAM ops, bus shift 20, generic read and write */
+/* default ECAM ops */
 extern struct pci_ecam_ops pci_generic_ecam_ops;
 
 #ifdef CONFIG_PCI_HOST_GENERIC
-/* for DT based pci controllers that support ECAM */
+/* for DT-based PCI controllers that support ECAM */
 int pci_host_common_probe(struct platform_device *pdev,
 			  struct pci_ecam_ops *ops);
 #endif


From jon.mason at broadcom.com  Wed May 11 15:56:08 2016
From: jon.mason at broadcom.com (Jon Mason)
Date: Wed, 11 May 2016 18:56:08 -0400
Subject: [PATCH 1/2] arm64: dts: NS2: Add all of the UARTs
Message-ID: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>

Add all of the UARTs present on NS2 and enable them in the SVK device
tree file.  Also, do some magic to make sure that uart3 is discovered as
ttyS0 (as that is the console UART).

Signed-off-by: Jon Mason <jonmason at broadcom.com>
---
 arch/arm64/boot/dts/broadcom/ns2-svk.dts | 16 ++++++++++++++++
 arch/arm64/boot/dts/broadcom/ns2.dtsi    | 30 ++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
index 7cd3640..b062a44 100644
--- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts
+++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
@@ -40,10 +40,14 @@
 
 	aliases {
 		serial0 = &uart3;
+		serial1 = &uart0;
+		serial2 = &uart1;
+		serial3 = &uart2;
 	};
 
 	chosen {
 		stdout-path = "serial0:115200n8";
+		bootargs = "earlycon=uart8250,mmio32,0x66130000";
 	};
 
 	memory {
@@ -68,6 +72,18 @@
 	status = "ok";
 };
 
+&uart0 {
+	status = "ok";
+};
+
+&uart1 {
+	status = "ok";
+};
+
+&uart2 {
+	status = "ok";
+};
+
 &uart3 {
 	status = "ok";
 };
diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi
index 788ed8f..c77a9e8 100644
--- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
+++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
@@ -357,6 +357,36 @@
 			status = "disabled";
 		};
 
+		uart0: serial at 66100000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x66100000 0x100>;
+			interrupts = <GIC_SPI 390 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&iprocslow>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			status = "disabled";
+		};
+
+		uart1: serial at 66110000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x66110000 0x100>;
+			interrupts = <GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&iprocslow>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			status = "disabled";
+		};
+
+		uart2: serial at 66120000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x66120000 0x100>;
+			interrupts = <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&iprocslow>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			status = "disabled";
+		};
+
 		uart3: serial at 66130000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x66130000 0x100>;
-- 
1.9.1



From jon.mason at broadcom.com  Wed May 11 15:56:09 2016
From: jon.mason at broadcom.com (Jon Mason)
Date: Wed, 11 May 2016 18:56:09 -0400
Subject: [PATCH 2/2] arm64: dts: NS2: Add CCI-400 PMU support
In-Reply-To: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
References: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
Message-ID: <1463007369-13071-2-git-send-email-jonmason@broadcom.com>

Add support to the Northstar 2 Device tree file for the ARM CCI-400 PMU.

Signed-off-by: Jon Mason <jonmason at broadcom.com>
---
 arch/arm64/boot/dts/broadcom/ns2.dtsi | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi
index c77a9e8..d1dc812 100644
--- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
+++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
@@ -279,6 +279,26 @@
 				      IRQ_TYPE_LEVEL_HIGH)>;
 		};
 
+		cci at 65590000 {
+			compatible = "arm,cci-400";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x65590000 0x1000>;
+			ranges = <0 0x65590000 0x10000>;
+
+			pmu at 9000 {
+				compatible = "arm,cci-400-pmu,r1",
+					     "arm,cci-400-pmu";
+				reg = <0x9000 0x4000>;
+				interrupts = <GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH>;
+			};
+		};
+
 		timer0: timer at 66030000 {
 			compatible = "arm,sp804", "arm,primecell";
 			reg = <0x66030000 0x1000>;
-- 
1.9.1



From sboyd at codeaurora.org  Wed May 11 15:58:54 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Wed, 11 May 2016 15:58:54 -0700
Subject: [PATCH 3/3] clk: bcm2835: Skip PLLC clocks when deciding on a
 new clock parent
In-Reply-To: <1462842090-2017-4-git-send-email-eric@anholt.net>
References: <1462842090-2017-1-git-send-email-eric@anholt.net>
 <1462842090-2017-4-git-send-email-eric@anholt.net>
Message-ID: <20160511225854.GI3492@codeaurora.org>

On 05/09, Eric Anholt wrote:
> If the firmware had set up a clock to source from PLLC, go along with
> it.  But if we're looking for a new parent, we don't want to switch it
> to PLLC because the firmware will force PLLC (and thus the AXI bus
> clock) to different frequencies during over-temp/under-voltage,
> without notification to Linux.
> 
> On my system, this moves the Linux-enabled HDMI state machine and DSI1
> escape clock over to plld_per from pllc_per.  EMMC still ends up on
> pllc_per, because the firmware had set it up to use that.

Is it ok for EMMC rate to change with over-temp/under-voltage?
The description makes it sound like PLLC is for clks that want to
run at some system bus rate and they don't care about exact
frequencies.

> 
> Signed-off-by: Eric Anholt <eric at anholt.net>
> Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks")
> diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
> index 1091012ecec6..1d8f29ea9f69 100644
> --- a/drivers/clk/bcm/clk-bcm2835.c
> +++ b/drivers/clk/bcm/clk-bcm2835.c
> @@ -1008,16 +1008,28 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw,
>  	return 0;
>  }
>  
> +static bool
> +bcm2835_clk_is_pllc(struct clk_hw *hw)
> +{
> +	if (!hw)
> +		return false;
> +
> +	return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0;

This strcmp is not great. Any chance we could look for the parent
by reading the hardware and knowing what bit corresponds to pllc
as a parent? That would be much nicer so that we don't rely on
string comparisons for something the hardware can tell us.

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


From jon.mason at broadcom.com  Wed May 11 16:19:07 2016
From: jon.mason at broadcom.com (Jon Mason)
Date: Wed, 11 May 2016 19:19:07 -0400
Subject: [PATCH v2 0/3] ARM: dts: bcm5301x: Add TWD, I2C, and syscon
Message-ID: <1463008750-13902-1-git-send-email-jonmason@broadcom.com>

Reviving, correcting, and resending this patch series from December
http://lists.infradead.org/pipermail/linux-arm-kernel/2015-December/395155.html

In v2:
* Corrected TWD DT names, per Sergei Shtylyov
* Modified syscon size, per Arnd Bergmann (or atleast my rough
  understanding of what he was trying to say)

Jon Mason (3):
  ARM: dts: bcm5301x: Add TWD WD Support to DT
  ARM: dts: bcm5301x: Add I2C support to the DT
  arm: dts: bcm5301x: Add syscon based reboot in DT

 arch/arm/boot/dts/bcm5301x.dtsi | 36 +++++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)

-- 
1.9.1



From jon.mason at broadcom.com  Wed May 11 16:19:08 2016
From: jon.mason at broadcom.com (Jon Mason)
Date: Wed, 11 May 2016 19:19:08 -0400
Subject: [PATCH v2 1/3] ARM: dts: bcm5301x: Add TWD WD Support to DT
In-Reply-To: <1463008750-13902-1-git-send-email-jonmason@broadcom.com>
References: <1463008750-13902-1-git-send-email-jonmason@broadcom.com>
Message-ID: <1463008750-13902-2-git-send-email-jonmason@broadcom.com>

Add support for the ARM TWD Watchdog to the bcm5301x device tree.  The
ARM TWD timer allocated the register space for the WDT, so this patch
necessitated shrinking that.  Also, the GIC masks were added for these.

Signed-off-by: Jon Mason <jonmason at broadcom.com>
---
 arch/arm/boot/dts/bcm5301x.dtsi | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi
index 65a1309..4b9887f 100644
--- a/arch/arm/boot/dts/bcm5301x.dtsi
+++ b/arch/arm/boot/dts/bcm5301x.dtsi
@@ -66,10 +66,19 @@
 			clocks = <&periph_clk>;
 		};
 
-		local-timer at 20600 {
+		timer at 20600 {
 			compatible = "arm,cortex-a9-twd-timer";
-			reg = <0x20600 0x100>;
-			interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>;
+			reg = <0x20600 0x20>;
+			interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
+						  IRQ_TYPE_LEVEL_HIGH)>;
+			clocks = <&periph_clk>;
+		};
+
+		watchdog at 20620 {
+			compatible = "arm,cortex-a9-twd-wdt";
+			reg = <0x20620 0x20>;
+			interrupts = <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) |
+						  IRQ_TYPE_LEVEL_HIGH)>;
 			clocks = <&periph_clk>;
 		};
 
-- 
1.9.1



From jon.mason at broadcom.com  Wed May 11 16:19:09 2016
From: jon.mason at broadcom.com (Jon Mason)
Date: Wed, 11 May 2016 19:19:09 -0400
Subject: [PATCH v2 2/3] ARM: dts: bcm5301x: Add I2C support to the DT
In-Reply-To: <1463008750-13902-1-git-send-email-jonmason@broadcom.com>
References: <1463008750-13902-1-git-send-email-jonmason@broadcom.com>
Message-ID: <1463008750-13902-3-git-send-email-jonmason@broadcom.com>

Add I2C support to the bcm5301x Device Tree.  Since no driver changes
are needed to enable this hardware, only the device tree changes are
required to make this functional.

Signed-off-by: Jon Mason <jonmason at broadcom.com>
---
 arch/arm/boot/dts/bcm5301x.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi
index 4b9887f..ffc4a9b 100644
--- a/arch/arm/boot/dts/bcm5301x.dtsi
+++ b/arch/arm/boot/dts/bcm5301x.dtsi
@@ -218,6 +218,15 @@
 		};
 	};
 
+	i2c0: i2c at 18009000 {
+		compatible = "brcm,iproc-i2c";
+		reg = <0x18009000 0x50>;
+		interrupts = <GIC_SPI 121 IRQ_TYPE_NONE>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-frequency = <100000>;
+	};
+
 	lcpll0: lcpll0 at 1800c100 {
 		#clock-cells = <1>;
 		compatible = "brcm,nsp-lcpll0";
-- 
1.9.1



From jon.mason at broadcom.com  Wed May 11 16:19:10 2016
From: jon.mason at broadcom.com (Jon Mason)
Date: Wed, 11 May 2016 19:19:10 -0400
Subject: [PATCH v2 3/3] arm: dts: bcm5301x: Add syscon based reboot in DT
In-Reply-To: <1463008750-13902-1-git-send-email-jonmason@broadcom.com>
References: <1463008750-13902-1-git-send-email-jonmason@broadcom.com>
Message-ID: <1463008750-13902-4-git-send-email-jonmason@broadcom.com>

Add the ability to reboot via a reset of the processor.  This is
achieved via a write of 0x39 to the CRU Reset Register.  Unfortunately,
this only resets the core and not the other IP blocks.  So if possible,
other methods should be used on the individual boards.

Signed-off-by: Jon Mason <jonmason at broadcom.com>
---
 arch/arm/boot/dts/bcm5301x.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi
index ffc4a9b..d4e1672 100644
--- a/arch/arm/boot/dts/bcm5301x.dtsi
+++ b/arch/arm/boot/dts/bcm5301x.dtsi
@@ -246,6 +246,18 @@
 				     "sata2";
 	};
 
+	cru: cru at 1800c184 {
+		compatible = "syscon";
+		reg = <0x1800c184 0x4>;
+	};
+
+	reboot at 1800c184 {
+		compatible ="syscon-reboot";
+		regmap = <&cru>;
+		offset = <0>;
+		mask = <0x39>;
+	};
+
 	nand: nand at 18028000 {
 		compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1", "brcm,brcmnand";
 		reg = <0x18028000 0x600>, <0x1811a408 0x600>, <0x18028f00 0x20>;
-- 
1.9.1



From matt at codeblueprint.co.uk  Wed May 11 16:24:44 2016
From: matt at codeblueprint.co.uk (Matt Fleming)
Date: Thu, 12 May 2016 00:24:44 +0100
Subject: [PATCH] Xen: EFI: Parse DT parameters for Xen specific UEFI
In-Reply-To: <57333533.2030206@linaro.org>
References: <1462523526-3172-1-git-send-email-zhaoshenglong@huawei.com>
 <20160511122730.GU2839@codeblueprint.co.uk>
 <57333533.2030206@linaro.org>
Message-ID: <20160511232444.GY2839@codeblueprint.co.uk>

On Wed, 11 May, at 09:35:47PM, Shannon Zhao wrote:
> > 
> > Also, why do you need to setup efi.runtime_version here? Isn't that
> > done inside uefi_init()?
> > 
> I don't see any codes which setup efi.runtime_version in uefi_init().
 
Look in the EFI tree,

  https://git.kernel.org/cgit/linux/kernel/git/mfleming/efi.git/tree/drivers/firmware/efi/arm-init.c?h=next#n120

> > Here is how I would have expected this patch to look:
> > 
> >   - Add FDT code to find hypervisor EFI params
> > 
> >   - Force enable EFI_RUNTIME_SERVICES for Xen and call
> >     xen_efi_runtime_setup() inside xen_guest_init()
> > 
> >   - Change arm_enable_runtime_services() to handle the case where
> >     EFI_RUNTIME_SERVICES is already set
> > 
> > Am I misunderstanding some ordering issues?
> 
> Since xen_guest_init() and arm_enable_runtime_services() are both
> early_initcall and the calling order is random I think.

Urgh, right, I missed that.

> And when we call xen_efi_runtime_setup() and setup
> efi.runtime_version in xen_guest_init(), the efi.systab might be
> NULL. So it needs to map the systanle explicitly before we use
> efi.systab.

Could you explain why you need to copy efi.runtime_version instead of
letting the existing code in uefi_init() set it up?

Also, efi.systab isn't used by xen_efi_runtime_setup() as far I can
see, not sure why you need that either?


From dianders at chromium.org  Wed May 11 16:41:54 2016
From: dianders at chromium.org (Doug Anderson)
Date: Wed, 11 May 2016 16:41:54 -0700
Subject: [PATCH v8 8/8] i2c: rk3x: support fast-mode plus for rk3399
In-Reply-To: <5153288.jNhUuzGC3g@phil>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908794-27333-1-git-send-email-david.wu@rock-chips.com>
 <5153288.jNhUuzGC3g@phil>
Message-ID: <CAD=FV=VzQ8PRokgAaTV00L31mcXFEzBG8c1NB4+Rqyx75hwwDg@mail.gmail.com>

Heiko,

On Wed, May 11, 2016 at 2:09 PM, Heiko Stuebner <heiko at sntech.de> wrote:
> Additionally, the i2c-noob in me would wish for a short sentence on where
> the timing values come from (measured, somewhere in the TRM I didn't find or
> something completely different).

If you search for "UM10204" you'll find the first link is
<http://www.nxp.com/documents/user_manual/UM10204.pdf>.  That appears
to be the official standard.  At least that's what
<http://www.i2c-bus.org/fast-mode-plus/> says (though they have an old
link).

Agree that it wouldn't hurt to mention that in the commit message.

-Doug


From ddaney at caviumnetworks.com  Wed May 11 17:06:13 2016
From: ddaney at caviumnetworks.com (David Daney)
Date: Wed, 11 May 2016 17:06:13 -0700
Subject: [PATCH v6 13/14] arm64, acpi, numa: NUMA support based on SRAT
 and SLIT
In-Reply-To: <20160511103929.GC3051@e104818-lin.cambridge.arm.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <1461780436-27182-14-git-send-email-ddaney.cavm@gmail.com>
 <20160511103929.GC3051@e104818-lin.cambridge.arm.com>
Message-ID: <5733C8F5.6090206@caviumnetworks.com>

On 05/11/2016 03:39 AM, Catalin Marinas wrote:
> On Wed, Apr 27, 2016 at 11:07:15AM -0700, David Daney wrote:
>> +static int __init get_mpidr_in_madt(int acpi_id, u64 *mpidr)
>> +{
>> +	unsigned long madt_end, entry;
>> +	struct acpi_table_madt *madt;
>> +	acpi_size tbl_size;
>> +
>> +	if (ACPI_FAILURE(acpi_get_table_with_size(ACPI_SIG_MADT, 0,
>> +			(struct acpi_table_header **)&madt, &tbl_size)))
>> +		return -ENODEV;
>> +
>> +	entry = (unsigned long)madt;
>> +	madt_end = entry + madt->header.length;
>> +
>> +	/* Parse all entries looking for a match. */
>> +	entry += sizeof(struct acpi_table_madt);
>> +	while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
>> +		struct acpi_subtable_header *header =
>> +			(struct acpi_subtable_header *)entry;
>> +
>> +		if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
>> +			struct acpi_madt_generic_interrupt *gicc =
>> +				container_of(header,
>> +				struct acpi_madt_generic_interrupt, header);
>> +
>> +			if ((gicc->flags & ACPI_MADT_ENABLED) &&
>> +			    (gicc->uid == acpi_id)) {
>> +				*mpidr = gicc->arm_mpidr;
>> +				early_acpi_os_unmap_memory(madt, tbl_size);
>> +				return 0;
>> +			}
>> +		}
>> +		entry += header->length;
>> +	}
>> +
>> +	early_acpi_os_unmap_memory(madt, tbl_size);
>> +	return -ENODEV;
>> +}
>> +
>> +/* Callback for Proximity Domain -> ACPI processor UID mapping */
>> +void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa)
>> +{
>> +	int pxm, node;
>> +	u64 mpidr;
>> +
>> +	if (srat_disabled())
>> +		return;
>> +
>> +	if (pa->header.length < sizeof(struct acpi_srat_gicc_affinity)) {
>> +		pr_err("SRAT: Invalid SRAT header length: %d\n",
>> +			pa->header.length);
>> +		bad_srat();
>> +		return;
>> +	}
>> +
>> +	if (!(pa->flags & ACPI_SRAT_GICC_ENABLED))
>> +		return;
>> +
>> +	if (cpus_in_srat >= NR_CPUS) {
>> +		pr_warn_once("SRAT: cpu_to_node_map[%d] is too small, may not be able to use all cpus\n",
>> +			     NR_CPUS);
>> +		return;
>> +	}
>> +
>> +	pxm = pa->proximity_domain;
>> +	node = acpi_map_pxm_to_node(pxm);
>> +
>> +	if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
>> +		pr_err("SRAT: Too many proximity domains %d\n", pxm);
>> +		bad_srat();
>> +		return;
>> +	}
>> +
>> +	if (get_mpidr_in_madt(pa->acpi_processor_uid, &mpidr)) {
>> +		pr_err("SRAT: PXM %d with ACPI ID %d has no valid MPIDR in MADT\n",
>> +			pxm, pa->acpi_processor_uid);
>> +		bad_srat();
>> +		return;
>> +	}
>
> I wonder whether you could replace the get_mpidr_in_madt() function with
> something like acpi_get_phys_id(). It looks like get_mpidr_in_madt()
> duplicates functionality already available elsewhere.
>

I just tried that, and it doesn't work.

The problem is that this code is being run very early in the boot, and 
kmalloc cannot be used.  acpi_get_phys_id() and its ilk can only be used 
once we have working kmalloc.  We need to extract the NUMA information 
early like this precisely because it is needed to initializing the slab 
system

Notice that we are using early_acpi_os_unmap_memory() et al. in 
get_mpidr_in_madt() explicitly for this reason.

In summary: I don't think we need another revision of this patch, it is 
like this for a good reason.

David Daney



From ynorov at caviumnetworks.com  Wed May 11 17:20:00 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 12 May 2016 03:20:00 +0300
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <20160512002000.GA30997@yury-N73SV>

Hi,

I debugged preadv02 and pwritev02 failures and found very weird bug.
Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
of vector, and kernel reports successful read/write.

There are 2 problems:
1. How kernel allows such address to be passed to fs subsystem;
2. How fs successes to read/write at non-mapped, and in fact non-user
address.

I don't know the answer on 2'nd question, and it might be something
generic. But I investigated first problem.

The problem is that compat_rw_copy_check_uvector() uses access_ok() to
validate user address, and on arm64 it ends up with checking buffer
end against current_thread_info()->addr_limit.

current_thread_info()->addr_limit for ilp32, and most probably for
aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
It happens because on thread creation we call flush_old_exec() to set 
addr_limit, and completely ignore compat mode there.

This patch fixes it. It also fixes USER_DS macro to return different
values depending on compat.

This patch is enough to handle preadv02 and pwritev02, but problem #2
is still there.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/include/asm/elf.h     | 1 +
 arch/arm64/include/asm/uaccess.h | 2 +-
 arch/arm64/kernel/binfmt_elf32.c | 1 +
 arch/arm64/kernel/binfmt_ilp32.c | 1 +
 4 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 7a39683..6ba4952 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -146,6 +146,7 @@ typedef struct user_fpsimd_state elf_fpregset_t;
 do {						\
 	clear_thread_flag(TIF_32BIT_AARCH64);	\
 	clear_thread_flag(TIF_32BIT);		\
+	set_fs(TASK_SIZE_64);			\
 } while (0)
 
 #define ARCH_DLINFO							\
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 19cfdc5..3b0dd8d 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -51,7 +51,7 @@
 #define KERNEL_DS	(-1UL)
 #define get_ds()	(KERNEL_DS)
 
-#define USER_DS		TASK_SIZE_64
+#define USER_DS		TASK_SIZE
 #define get_fs()	(current_thread_info()->addr_limit)
 
 static inline void set_fs(mm_segment_t fs)
diff --git a/arch/arm64/kernel/binfmt_elf32.c b/arch/arm64/kernel/binfmt_elf32.c
index 5487872..2e8d9f3 100644
--- a/arch/arm64/kernel/binfmt_elf32.c
+++ b/arch/arm64/kernel/binfmt_elf32.c
@@ -12,6 +12,7 @@
 do {						\
 	clear_thread_flag(TIF_32BIT_AARCH64);	\
 	set_thread_flag(TIF_32BIT);		\
+	set_fs(TASK_SIZE_32);			\
 } while (0)
 
 #define COMPAT_ARCH_DLINFO
diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
index a934fd4..a8599c6 100644
--- a/arch/arm64/kernel/binfmt_ilp32.c
+++ b/arch/arm64/kernel/binfmt_ilp32.c
@@ -59,6 +59,7 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
 do {									\
 	set_thread_flag(TIF_32BIT_AARCH64);				\
 	clear_thread_flag(TIF_32BIT);					\
+	set_fs(TASK_SIZE_32);						\
 } while (0)
 
 #undef ARCH_DLINFO
-- 
2.5.0



From benh at kernel.crashing.org  Wed May 11 18:01:22 2016
From: benh at kernel.crashing.org (Benjamin Herrenschmidt)
Date: Thu, 12 May 2016 11:01:22 +1000
Subject: [PATCH v2 1/2] doc/devicetree: Add Aspeed VIC bindings
In-Reply-To: <20160511143313.GA7426@rob-hp-laptop>
References: <462797239-14765-1-git-send-email-joel@jms.id.au>
 <1462802317-27086-1-git-send-email-joel@jms.id.au>
 <1462802317-27086-2-git-send-email-joel@jms.id.au>
 <20160511143313.GA7426@rob-hp-laptop>
Message-ID: <1463014882.20290.203.camel@kernel.crashing.org>

On Wed, 2016-05-11 at 09:33 -0500, Rob Herring wrote:
> > +- interrupt-controller : Identifies the node as an interrupt controller
> > +- #interrupt-cells : Specifies the number of cells needed to encode an
> > +? interrupt source. The value shall be 1.
> 
> No need for level vs. edge flags?

That's an open question. Most interrupts are fixed. A handful of GPIOs
can be configured either way. For now I am relying on uboot setting up
the right config for them and I read it back at boot time, but we could
make it part of the binding I suppose.

> > +- valid-sources : bitmask of valid irq sources
> 
> Drop this. Either all interrupt controllers need this or none of?
> them do. The valid sources are the ones described in the DT.

Looking at the code (I wrote that ages ago), this is only used for:

? - Failing map on an unsupported source, so we could drop it

? - Counting the number of sources in order to optimize the
? ? revmap size allocation. We could unconditionally allocate
? ? 64, I don't see a big deal here.

So yes Joel, feel free to just ditch this.

> > +
> > +Example:
> > +
> > + vic: interrupt-controller {
> 
> Needs a unit address.
> 
> > +????? compatible = "aspeed,ast2400-vic";
> > +????? interrupt-controller;
> > +????? #interrupt-cells = <1>;
> > +????? valid-sources = < 0xffffffff 0x0007ffff>;
> > +????? reg = <0x1e6c0080 0x80>;
> > + };
> > --?
> > 2.8.1
> >?
> > --
> > To unsubscribe from this list: send the line "unsubscribe devicetree" in
> > the body of a message to majordomo at vger.kernel.org
> > More majordomo info at? http://vger.kernel.org/majordomo-info.html


From sboyd at codeaurora.org  Wed May 11 18:02:25 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Wed, 11 May 2016 18:02:25 -0700
Subject: [PATCH 0/3] msm_serial cleanups
Message-ID: <20160512010228.21548-1-sboyd@codeaurora.org>

This is a small set of three patches that mostly gets rid
of the header file and protects us from a bad uartclk setting
if the stars align improperly (so far they haven't). I also
cleaned up the includes to protect us from any include
update fallout.

Stephen Boyd (3):
  tty: serial: msm: Move header file into driver
  tty: serial: msm: Only configure MND registers on hw that has it
  tty: serial: msm: Cleanup include usage

 drivers/tty/serial/msm_serial.c | 189 +++++++++++++++++++++++++++++++++++++---
 drivers/tty/serial/msm_serial.h | 184 --------------------------------------
 2 files changed, 179 insertions(+), 194 deletions(-)
 delete mode 100644 drivers/tty/serial/msm_serial.h

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



From sboyd at codeaurora.org  Wed May 11 18:02:28 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Wed, 11 May 2016 18:02:28 -0700
Subject: [PATCH 3/3] tty: serial: msm: Cleanup include usage
In-Reply-To: <20160512010228.21548-1-sboyd@codeaurora.org>
References: <20160512010228.21548-1-sboyd@codeaurora.org>
Message-ID: <20160512010228.21548-4-sboyd@codeaurora.org>

The hrtimer include isn't used and neither is serial. Drop those
ones. The irq.h header really should be interrupt.h because this
is an interrupt user and not an interrupt chip. Finally add
wait.h for the wake_up*() usage in this driver and kernel.h for
container_of().

Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
---
 drivers/tty/serial/msm_serial.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index a051dc5def24..88af5a3d21dd 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -19,26 +19,26 @@
 # define SUPPORT_SYSRQ
 #endif
 
+#include <linux/kernel.h>
 #include <linux/atomic.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
-#include <linux/hrtimer.h>
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial_core.h>
-#include <linux/serial.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/wait.h>
 
 #define UART_MR1			0x0000
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



From sboyd at codeaurora.org  Wed May 11 18:02:27 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Wed, 11 May 2016 18:02:27 -0700
Subject: [PATCH 2/3] tty: serial: msm: Only configure MND registers on hw that
 has it
In-Reply-To: <20160512010228.21548-1-sboyd@codeaurora.org>
References: <20160512010228.21548-1-sboyd@codeaurora.org>
Message-ID: <20160512010228.21548-3-sboyd@codeaurora.org>

The registers that msm_serial_set_mnd_regs() writes only exist on
the non-uartdm hardware, so let's return early here if this
function is called on uartdm hardware. This also prevents us from
messing up the uartclk variable if the uartclk rate happens to be
19.2 or 4.8 MHz.

Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
---
 drivers/tty/serial/msm_serial.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 28b8ac423de1..a051dc5def24 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -232,6 +232,15 @@ static void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
 
 static void msm_serial_set_mnd_regs(struct uart_port *port)
 {
+	struct msm_port *msm_port = UART_TO_MSM(port);
+
+	/*
+	 * These registers don't exist so we change the clk input rate
+	 * on uartdm hardware instead
+	 */
+	if (msm_port->is_uartdm)
+		return;
+
 	if (port->uartclk == 19200000)
 		msm_serial_set_mnd_regs_tcxo(port);
 	else if (port->uartclk == 4800000)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



From sboyd at codeaurora.org  Wed May 11 18:02:26 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Wed, 11 May 2016 18:02:26 -0700
Subject: [PATCH 1/3] tty: serial: msm: Move header file into driver
In-Reply-To: <20160512010228.21548-1-sboyd@codeaurora.org>
References: <20160512010228.21548-1-sboyd@codeaurora.org>
Message-ID: <20160512010228.21548-2-sboyd@codeaurora.org>

This header file is only used by the driver, so let's merge the
two together to reduce files and make it easier to see the whole
driver without flipping through two files. This also makes it
easier to use the structures defined in msm_serial.c in the
functions that are defined in msm_serial.h by placing them in the
proper locations.

Signed-off-by: Stephen Boyd <sboyd at codeaurora.org>
---
 drivers/tty/serial/msm_serial.c | 172 +++++++++++++++++++++++++++++++++++--
 drivers/tty/serial/msm_serial.h | 184 ----------------------------------------
 2 files changed, 166 insertions(+), 190 deletions(-)
 delete mode 100644 drivers/tty/serial/msm_serial.h

diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index b7d80bd57db9..28b8ac423de1 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -40,12 +40,126 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 
-#include "msm_serial.h"
-
-#define UARTDM_BURST_SIZE	16   /* in bytes */
-#define UARTDM_TX_AIGN(x)	((x) & ~0x3) /* valid for > 1p3 */
-#define UARTDM_TX_MAX		256   /* in bytes, valid for <= 1p3 */
-#define UARTDM_RX_SIZE		(UART_XMIT_SIZE / 4)
+#define UART_MR1			0x0000
+
+#define UART_MR1_AUTO_RFR_LEVEL0	0x3F
+#define UART_MR1_AUTO_RFR_LEVEL1	0x3FF00
+#define UART_DM_MR1_AUTO_RFR_LEVEL1	0xFFFFFF00
+#define UART_MR1_RX_RDY_CTL		BIT(7)
+#define UART_MR1_CTS_CTL		BIT(6)
+
+#define UART_MR2			0x0004
+#define UART_MR2_ERROR_MODE		BIT(6)
+#define UART_MR2_BITS_PER_CHAR		0x30
+#define UART_MR2_BITS_PER_CHAR_5	(0x0 << 4)
+#define UART_MR2_BITS_PER_CHAR_6	(0x1 << 4)
+#define UART_MR2_BITS_PER_CHAR_7	(0x2 << 4)
+#define UART_MR2_BITS_PER_CHAR_8	(0x3 << 4)
+#define UART_MR2_STOP_BIT_LEN_ONE	(0x1 << 2)
+#define UART_MR2_STOP_BIT_LEN_TWO	(0x3 << 2)
+#define UART_MR2_PARITY_MODE_NONE	0x0
+#define UART_MR2_PARITY_MODE_ODD	0x1
+#define UART_MR2_PARITY_MODE_EVEN	0x2
+#define UART_MR2_PARITY_MODE_SPACE	0x3
+#define UART_MR2_PARITY_MODE		0x3
+
+#define UART_CSR			0x0008
+
+#define UART_TF				0x000C
+#define UARTDM_TF			0x0070
+
+#define UART_CR				0x0010
+#define UART_CR_CMD_NULL		(0 << 4)
+#define UART_CR_CMD_RESET_RX		(1 << 4)
+#define UART_CR_CMD_RESET_TX		(2 << 4)
+#define UART_CR_CMD_RESET_ERR		(3 << 4)
+#define UART_CR_CMD_RESET_BREAK_INT	(4 << 4)
+#define UART_CR_CMD_START_BREAK		(5 << 4)
+#define UART_CR_CMD_STOP_BREAK		(6 << 4)
+#define UART_CR_CMD_RESET_CTS		(7 << 4)
+#define UART_CR_CMD_RESET_STALE_INT	(8 << 4)
+#define UART_CR_CMD_PACKET_MODE		(9 << 4)
+#define UART_CR_CMD_MODE_RESET		(12 << 4)
+#define UART_CR_CMD_SET_RFR		(13 << 4)
+#define UART_CR_CMD_RESET_RFR		(14 << 4)
+#define UART_CR_CMD_PROTECTION_EN	(16 << 4)
+#define UART_CR_CMD_STALE_EVENT_DISABLE	(6 << 8)
+#define UART_CR_CMD_STALE_EVENT_ENABLE	(80 << 4)
+#define UART_CR_CMD_FORCE_STALE		(4 << 8)
+#define UART_CR_CMD_RESET_TX_READY	(3 << 8)
+#define UART_CR_TX_DISABLE		BIT(3)
+#define UART_CR_TX_ENABLE		BIT(2)
+#define UART_CR_RX_DISABLE		BIT(1)
+#define UART_CR_RX_ENABLE		BIT(0)
+#define UART_CR_CMD_RESET_RXBREAK_START	((1 << 11) | (2 << 4))
+
+#define UART_IMR			0x0014
+#define UART_IMR_TXLEV			BIT(0)
+#define UART_IMR_RXSTALE		BIT(3)
+#define UART_IMR_RXLEV			BIT(4)
+#define UART_IMR_DELTA_CTS		BIT(5)
+#define UART_IMR_CURRENT_CTS		BIT(6)
+#define UART_IMR_RXBREAK_START		BIT(10)
+
+#define UART_IPR_RXSTALE_LAST		0x20
+#define UART_IPR_STALE_LSB		0x1F
+#define UART_IPR_STALE_TIMEOUT_MSB	0x3FF80
+#define UART_DM_IPR_STALE_TIMEOUT_MSB	0xFFFFFF80
+
+#define UART_IPR			0x0018
+#define UART_TFWR			0x001C
+#define UART_RFWR			0x0020
+#define UART_HCR			0x0024
+
+#define UART_MREG			0x0028
+#define UART_NREG			0x002C
+#define UART_DREG			0x0030
+#define UART_MNDREG			0x0034
+#define UART_IRDA			0x0038
+#define UART_MISR_MODE			0x0040
+#define UART_MISR_RESET			0x0044
+#define UART_MISR_EXPORT		0x0048
+#define UART_MISR_VAL			0x004C
+#define UART_TEST_CTRL			0x0050
+
+#define UART_SR				0x0008
+#define UART_SR_HUNT_CHAR		BIT(7)
+#define UART_SR_RX_BREAK		BIT(6)
+#define UART_SR_PAR_FRAME_ERR		BIT(5)
+#define UART_SR_OVERRUN			BIT(4)
+#define UART_SR_TX_EMPTY		BIT(3)
+#define UART_SR_TX_READY		BIT(2)
+#define UART_SR_RX_FULL			BIT(1)
+#define UART_SR_RX_READY		BIT(0)
+
+#define UART_RF				0x000C
+#define UARTDM_RF			0x0070
+#define UART_MISR			0x0010
+#define UART_ISR			0x0014
+#define UART_ISR_TX_READY		BIT(7)
+
+#define UARTDM_RXFS			0x50
+#define UARTDM_RXFS_BUF_SHIFT		0x7
+#define UARTDM_RXFS_BUF_MASK		0x7
+
+#define UARTDM_DMEN			0x3C
+#define UARTDM_DMEN_RX_SC_ENABLE	BIT(5)
+#define UARTDM_DMEN_TX_SC_ENABLE	BIT(4)
+
+#define UARTDM_DMEN_TX_BAM_ENABLE	BIT(2)	/* UARTDM_1P4 */
+#define UARTDM_DMEN_TX_DM_ENABLE	BIT(0)	/* < UARTDM_1P4 */
+
+#define UARTDM_DMEN_RX_BAM_ENABLE	BIT(3)	/* UARTDM_1P4 */
+#define UARTDM_DMEN_RX_DM_ENABLE	BIT(1)	/* < UARTDM_1P4 */
+
+#define UARTDM_DMRX			0x34
+#define UARTDM_NCF_TX			0x40
+#define UARTDM_RX_TOTAL_SNAP		0x38
+
+#define UARTDM_BURST_SIZE		16   /* in bytes */
+#define UARTDM_TX_AIGN(x)		((x) & ~0x3) /* valid for > 1p3 */
+#define UARTDM_TX_MAX			256   /* in bytes, valid for <= 1p3 */
+#define UARTDM_RX_SIZE			(UART_XMIT_SIZE / 4)
 
 enum {
 	UARTDM_1P1 = 1,
@@ -78,6 +192,52 @@ struct msm_port {
 	struct msm_dma		rx_dma;
 };
 
+#define UART_TO_MSM(uart_port)	container_of(uart_port, struct msm_port, uart)
+
+static
+void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
+{
+	writel_relaxed(val, port->membase + off);
+}
+
+static
+unsigned int msm_read(struct uart_port *port, unsigned int off)
+{
+	return readl_relaxed(port->membase + off);
+}
+
+/*
+ * Setup the MND registers to use the TCXO clock.
+ */
+static void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
+{
+	msm_write(port, 0x06, UART_MREG);
+	msm_write(port, 0xF1, UART_NREG);
+	msm_write(port, 0x0F, UART_DREG);
+	msm_write(port, 0x1A, UART_MNDREG);
+	port->uartclk = 1843200;
+}
+
+/*
+ * Setup the MND registers to use the TCXO clock divided by 4.
+ */
+static void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
+{
+	msm_write(port, 0x18, UART_MREG);
+	msm_write(port, 0xF6, UART_NREG);
+	msm_write(port, 0x0F, UART_DREG);
+	msm_write(port, 0x0A, UART_MNDREG);
+	port->uartclk = 1843200;
+}
+
+static void msm_serial_set_mnd_regs(struct uart_port *port)
+{
+	if (port->uartclk == 19200000)
+		msm_serial_set_mnd_regs_tcxo(port);
+	else if (port->uartclk == 4800000)
+		msm_serial_set_mnd_regs_tcxoby4(port);
+}
+
 static void msm_handle_tx(struct uart_port *port);
 static void msm_start_rx_dma(struct msm_port *msm_port);
 
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
deleted file mode 100644
index 178645826f16..000000000000
--- a/drivers/tty/serial/msm_serial.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Author: Robert Love <rlove at google.com>
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __DRIVERS_SERIAL_MSM_SERIAL_H
-#define __DRIVERS_SERIAL_MSM_SERIAL_H
-
-#define UART_MR1			0x0000
-
-#define UART_MR1_AUTO_RFR_LEVEL0	0x3F
-#define UART_MR1_AUTO_RFR_LEVEL1	0x3FF00
-#define UART_DM_MR1_AUTO_RFR_LEVEL1	0xFFFFFF00
-#define UART_MR1_RX_RDY_CTL		BIT(7)
-#define UART_MR1_CTS_CTL		BIT(6)
-
-#define UART_MR2			0x0004
-#define UART_MR2_ERROR_MODE		BIT(6)
-#define UART_MR2_BITS_PER_CHAR		0x30
-#define UART_MR2_BITS_PER_CHAR_5	(0x0 << 4)
-#define UART_MR2_BITS_PER_CHAR_6	(0x1 << 4)
-#define UART_MR2_BITS_PER_CHAR_7	(0x2 << 4)
-#define UART_MR2_BITS_PER_CHAR_8	(0x3 << 4)
-#define UART_MR2_STOP_BIT_LEN_ONE	(0x1 << 2)
-#define UART_MR2_STOP_BIT_LEN_TWO	(0x3 << 2)
-#define UART_MR2_PARITY_MODE_NONE	0x0
-#define UART_MR2_PARITY_MODE_ODD	0x1
-#define UART_MR2_PARITY_MODE_EVEN	0x2
-#define UART_MR2_PARITY_MODE_SPACE	0x3
-#define UART_MR2_PARITY_MODE		0x3
-
-#define UART_CSR			0x0008
-
-#define UART_TF		0x000C
-#define UARTDM_TF	0x0070
-
-#define UART_CR				0x0010
-#define UART_CR_CMD_NULL		(0 << 4)
-#define UART_CR_CMD_RESET_RX		(1 << 4)
-#define UART_CR_CMD_RESET_TX		(2 << 4)
-#define UART_CR_CMD_RESET_ERR		(3 << 4)
-#define UART_CR_CMD_RESET_BREAK_INT	(4 << 4)
-#define UART_CR_CMD_START_BREAK		(5 << 4)
-#define UART_CR_CMD_STOP_BREAK		(6 << 4)
-#define UART_CR_CMD_RESET_CTS		(7 << 4)
-#define UART_CR_CMD_RESET_STALE_INT	(8 << 4)
-#define UART_CR_CMD_PACKET_MODE		(9 << 4)
-#define UART_CR_CMD_MODE_RESET		(12 << 4)
-#define UART_CR_CMD_SET_RFR		(13 << 4)
-#define UART_CR_CMD_RESET_RFR		(14 << 4)
-#define UART_CR_CMD_PROTECTION_EN	(16 << 4)
-#define UART_CR_CMD_STALE_EVENT_DISABLE	(6 << 8)
-#define UART_CR_CMD_STALE_EVENT_ENABLE	(80 << 4)
-#define UART_CR_CMD_FORCE_STALE		(4 << 8)
-#define UART_CR_CMD_RESET_TX_READY	(3 << 8)
-#define UART_CR_TX_DISABLE		BIT(3)
-#define UART_CR_TX_ENABLE		BIT(2)
-#define UART_CR_RX_DISABLE		BIT(1)
-#define UART_CR_RX_ENABLE		BIT(0)
-#define UART_CR_CMD_RESET_RXBREAK_START	((1 << 11) | (2 << 4))
-
-#define UART_IMR		0x0014
-#define UART_IMR_TXLEV			BIT(0)
-#define UART_IMR_RXSTALE		BIT(3)
-#define UART_IMR_RXLEV			BIT(4)
-#define UART_IMR_DELTA_CTS		BIT(5)
-#define UART_IMR_CURRENT_CTS		BIT(6)
-#define UART_IMR_RXBREAK_START		BIT(10)
-
-#define UART_IPR_RXSTALE_LAST		0x20
-#define UART_IPR_STALE_LSB		0x1F
-#define UART_IPR_STALE_TIMEOUT_MSB	0x3FF80
-#define UART_DM_IPR_STALE_TIMEOUT_MSB	0xFFFFFF80
-
-#define UART_IPR	0x0018
-#define UART_TFWR	0x001C
-#define UART_RFWR	0x0020
-#define UART_HCR	0x0024
-
-#define UART_MREG		0x0028
-#define UART_NREG		0x002C
-#define UART_DREG		0x0030
-#define UART_MNDREG		0x0034
-#define UART_IRDA		0x0038
-#define UART_MISR_MODE		0x0040
-#define UART_MISR_RESET		0x0044
-#define UART_MISR_EXPORT	0x0048
-#define UART_MISR_VAL		0x004C
-#define UART_TEST_CTRL		0x0050
-
-#define UART_SR			0x0008
-#define UART_SR_HUNT_CHAR	BIT(7)
-#define UART_SR_RX_BREAK	BIT(6)
-#define UART_SR_PAR_FRAME_ERR	BIT(5)
-#define UART_SR_OVERRUN		BIT(4)
-#define UART_SR_TX_EMPTY	BIT(3)
-#define UART_SR_TX_READY	BIT(2)
-#define UART_SR_RX_FULL		BIT(1)
-#define UART_SR_RX_READY	BIT(0)
-
-#define UART_RF			0x000C
-#define UARTDM_RF		0x0070
-#define UART_MISR		0x0010
-#define UART_ISR		0x0014
-#define UART_ISR_TX_READY	BIT(7)
-
-#define UARTDM_RXFS		0x50
-#define UARTDM_RXFS_BUF_SHIFT	0x7
-#define UARTDM_RXFS_BUF_MASK	0x7
-
-#define UARTDM_DMEN		0x3C
-#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
-#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
-
-#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2)	/* UARTDM_1P4 */
-#define UARTDM_DMEN_TX_DM_ENABLE  BIT(0)	/* < UARTDM_1P4 */
-
-#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3)	/* UARTDM_1P4 */
-#define UARTDM_DMEN_RX_DM_ENABLE  BIT(1)	/* < UARTDM_1P4 */
-
-#define UARTDM_DMRX		0x34
-#define UARTDM_NCF_TX		0x40
-#define UARTDM_RX_TOTAL_SNAP	0x38
-
-#define UART_TO_MSM(uart_port)	((struct msm_port *) uart_port)
-
-static inline
-void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
-{
-	writel_relaxed(val, port->membase + off);
-}
-
-static inline
-unsigned int msm_read(struct uart_port *port, unsigned int off)
-{
-	return readl_relaxed(port->membase + off);
-}
-
-/*
- * Setup the MND registers to use the TCXO clock.
- */
-static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
-{
-	msm_write(port, 0x06, UART_MREG);
-	msm_write(port, 0xF1, UART_NREG);
-	msm_write(port, 0x0F, UART_DREG);
-	msm_write(port, 0x1A, UART_MNDREG);
-	port->uartclk = 1843200;
-}
-
-/*
- * Setup the MND registers to use the TCXO clock divided by 4.
- */
-static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
-{
-	msm_write(port, 0x18, UART_MREG);
-	msm_write(port, 0xF6, UART_NREG);
-	msm_write(port, 0x0F, UART_DREG);
-	msm_write(port, 0x0A, UART_MNDREG);
-	port->uartclk = 1843200;
-}
-
-static inline
-void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
-{
-	if (port->uartclk == 19200000)
-		msm_serial_set_mnd_regs_tcxo(port);
-	else if (port->uartclk == 4800000)
-		msm_serial_set_mnd_regs_tcxoby4(port);
-}
-
-#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_from_uartclk
-
-#endif	/* __DRIVERS_SERIAL_MSM_SERIAL_H */
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



From hanjun.guo at linaro.org  Wed May 11 18:03:28 2016
From: hanjun.guo at linaro.org (Hanjun Guo)
Date: Thu, 12 May 2016 09:03:28 +0800
Subject: [PATCH v6 13/14] arm64, acpi, numa: NUMA support based on SRAT
 and SLIT
In-Reply-To: <5733C8F5.6090206@caviumnetworks.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <1461780436-27182-14-git-send-email-ddaney.cavm@gmail.com>
 <20160511103929.GC3051@e104818-lin.cambridge.arm.com>
 <5733C8F5.6090206@caviumnetworks.com>
Message-ID: <5733D660.7030604@linaro.org>

On 2016/5/12 8:06, David Daney wrote:
> On 05/11/2016 03:39 AM, Catalin Marinas wrote:
>> On Wed, Apr 27, 2016 at 11:07:15AM -0700, David Daney wrote:
>>> +static int __init get_mpidr_in_madt(int acpi_id, u64 *mpidr)
>>> +{
>>> +    unsigned long madt_end, entry;
>>> +    struct acpi_table_madt *madt;
>>> +    acpi_size tbl_size;
>>> +
>>> +    if (ACPI_FAILURE(acpi_get_table_with_size(ACPI_SIG_MADT, 0,
>>> +            (struct acpi_table_header **)&madt, &tbl_size)))
>>> +        return -ENODEV;
>>> +
>>> +    entry = (unsigned long)madt;
>>> +    madt_end = entry + madt->header.length;
>>> +
>>> +    /* Parse all entries looking for a match. */
>>> +    entry += sizeof(struct acpi_table_madt);
>>> +    while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
>>> +        struct acpi_subtable_header *header =
>>> +            (struct acpi_subtable_header *)entry;
>>> +
>>> +        if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
>>> +            struct acpi_madt_generic_interrupt *gicc =
>>> +                container_of(header,
>>> +                struct acpi_madt_generic_interrupt, header);
>>> +
>>> +            if ((gicc->flags & ACPI_MADT_ENABLED) &&
>>> +                (gicc->uid == acpi_id)) {
>>> +                *mpidr = gicc->arm_mpidr;
>>> +                early_acpi_os_unmap_memory(madt, tbl_size);
>>> +                return 0;
>>> +            }
>>> +        }
>>> +        entry += header->length;
>>> +    }
>>> +
>>> +    early_acpi_os_unmap_memory(madt, tbl_size);
>>> +    return -ENODEV;
>>> +}
>>> +
>>> +/* Callback for Proximity Domain -> ACPI processor UID mapping */
>>> +void __init acpi_numa_gicc_affinity_init(struct
>>> acpi_srat_gicc_affinity *pa)
>>> +{
>>> +    int pxm, node;
>>> +    u64 mpidr;
>>> +
>>> +    if (srat_disabled())
>>> +        return;
>>> +
>>> +    if (pa->header.length < sizeof(struct acpi_srat_gicc_affinity)) {
>>> +        pr_err("SRAT: Invalid SRAT header length: %d\n",
>>> +            pa->header.length);
>>> +        bad_srat();
>>> +        return;
>>> +    }
>>> +
>>> +    if (!(pa->flags & ACPI_SRAT_GICC_ENABLED))
>>> +        return;
>>> +
>>> +    if (cpus_in_srat >= NR_CPUS) {
>>> +        pr_warn_once("SRAT: cpu_to_node_map[%d] is too small, may
>>> not be able to use all cpus\n",
>>> +                 NR_CPUS);
>>> +        return;
>>> +    }
>>> +
>>> +    pxm = pa->proximity_domain;
>>> +    node = acpi_map_pxm_to_node(pxm);
>>> +
>>> +    if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
>>> +        pr_err("SRAT: Too many proximity domains %d\n", pxm);
>>> +        bad_srat();
>>> +        return;
>>> +    }
>>> +
>>> +    if (get_mpidr_in_madt(pa->acpi_processor_uid, &mpidr)) {
>>> +        pr_err("SRAT: PXM %d with ACPI ID %d has no valid MPIDR in
>>> MADT\n",
>>> +            pxm, pa->acpi_processor_uid);
>>> +        bad_srat();
>>> +        return;
>>> +    }
>>
>> I wonder whether you could replace the get_mpidr_in_madt() function with
>> something like acpi_get_phys_id(). It looks like get_mpidr_in_madt()
>> duplicates functionality already available elsewhere.
>>
>
> I just tried that, and it doesn't work.
>
> The problem is that this code is being run very early in the boot, and
> kmalloc cannot be used.  acpi_get_phys_id() and its ilk can only be used
> once we have working kmalloc.  We need to extract the NUMA information
> early like this precisely because it is needed to initializing the slab
> system
>
> Notice that we are using early_acpi_os_unmap_memory() et al. in
> get_mpidr_in_madt() explicitly for this reason.

I got the same conclusion when I was preparing this patch set.

Thanks
Hanjun


From david.wu at rock-chips.com  Wed May 11 18:08:58 2016
From: david.wu at rock-chips.com (David.Wu)
Date: Thu, 12 May 2016 09:08:58 +0800
Subject: [PATCH v8 7/8] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <CAD=FV=Uf-U3RBpgFbR3LkPAJTWqz3d02+H7iyA-SS-y=r3cXjA@mail.gmail.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908698-27284-1-git-send-email-david.wu@rock-chips.com>
 <CAD=FV=Uf-U3RBpgFbR3LkPAJTWqz3d02+H7iyA-SS-y=r3cXjA@mail.gmail.com>
Message-ID: <5733D7AA.1060500@rock-chips.com>

Hi Doug,

? 2016/5/12 1:37, Doug Anderson ??:
> Hi,
>
> On Tue, May 10, 2016 at 12:31 PM, David Wu <david.wu at rock-chips.com> wrote:
>>   static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
>>   {
>>          struct i2c_timings *t = &i2c->t;
>>          struct rk3x_i2c_calced_timings calc;
>>          u64 t_low_ns, t_high_ns;
>> +       u32 val;
>>          int ret;
>>
>> -       ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
>> +       ret = i2c->soc_data->calc_timings(clk_rate, t, &calc);
>>          WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
>>
>> -       clk_enable(i2c->clk);
>> +       clk_enable(i2c->pclk);
>> +
>>          i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
>>                     REG_CLKDIV);
>> -       clk_disable(i2c->clk);
>> +
>> +       val = i2c_readl(i2c, REG_CON);
>> +       val &= ~REG_CON_TUNING_MASK;
>> +       val |= calc.tuning;
>> +       i2c_writel(i2c, val, REG_CON);
>
> Another subtle bug here.  You need to be holding the spinlock here
> since you're doing a read-modify-write of a register that is also
> touched by the interrupt handler.  We never needed it before because
> the previous register update wasn't touched by anyone else and it was
> a single atomic write.
>
> Also: technically if we are midway through a transfer when all this
> happens then there will be a very short period of time when the two
> timing-related registers won't match with each other.  I have no idea
> how much that would matter, but in the very least it seems wise to
> minimize the time where they mismatch.  So I'd probably write:
>
>         spin_lock_irqsave(&i2c->lock, flags);
>         val = i2c_readl(i2c, REG_CON);
>         val &= ~REG_CON_TUNING_MASK;
>         val |= calc.tuning;
>         i2c_writel(i2c, val, REG_CON);
>         i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
>                    REG_CLKDIV);
>         spin_unlock_irqrestore(&i2c->lock, flags);
>
> ...if we really end up with on a system with a dynamically changing
> clock that uses the new-style timing and we see real problems, we can
> always try to come up with a way to avoid any problems.  Sound OK?
>
>

Good, add spin_lock is very necessary for atomic write here, thanks for 
your advice.

> Otherwise, I think things look good to me.  Caesar's comments would
> also be good to fix.
>
>
> -Doug
>
>
>



From david.wu at rock-chips.com  Wed May 11 18:11:29 2016
From: david.wu at rock-chips.com (David.Wu)
Date: Thu, 12 May 2016 09:11:29 +0800
Subject: [PATCH v8 3/8] i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd()
In-Reply-To: <2477327.hJjg0APDhg@phil>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908252-27016-4-git-send-email-david.wu@rock-chips.com>
 <2477327.hJjg0APDhg@phil>
Message-ID: <5733D841.1020905@rock-chips.com>

Hi Heiko

? 2016/5/12 2:26, Heiko Stuebner ??:
> Am Mittwoch, 11. Mai 2016, 03:24:07 schrieb David Wu:
>> Call rk3x_i2c_setup() before rk3x_i2c_start()
>
> That beginning of the sentence could use a tiny improvement, like
>
> ----
> rk3x_i2c_setup() gets called directly before rk3x_i2c_start()
> ----
>

Okay, i will add it in next version, Thanks.

> to make it obvious what happens in the code.
>
> But a nice small improvement
> Reviewed-by: Heiko Stuebner <heiko at sntech.de>
>
>> and the last thing in setup was to clean the IPD,
>> so no reason to do it at the beginning of start.
>>
>> Signed-off-by: David Wu <david.wu at rock-chips.com>
>> Reviewed-by: Douglas Anderson <dianders at chromium.org>
>> ---
>> Change in v8:
>> - none
>>
>>   drivers/i2c/busses/i2c-rk3x.c | 1 -
>>   1 file changed, 1 deletion(-)
>>
>> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
>> index 1e2677a..9eeb4e5 100644
>> --- a/drivers/i2c/busses/i2c-rk3x.c
>> +++ b/drivers/i2c/busses/i2c-rk3x.c
>> @@ -174,7 +174,6 @@ static void rk3x_i2c_start(struct rk3x_i2c *i2c)
>>   {
>>   	u32 val;
>>
>> -	rk3x_i2c_clean_ipd(i2c);
>>   	i2c_writel(i2c, REG_INT_START, REG_IEN);
>>
>>   	/* enable adapter with correct mode, send START condition */
>
>
>
>



From wenyou.yang at atmel.com  Wed May 11 18:05:34 2016
From: wenyou.yang at atmel.com (Wenyou Yang)
Date: Thu, 12 May 2016 09:05:34 +0800
Subject: [PATCH] usb: ohci-at91: Suspend the ports while USB suspending
Message-ID: <1463015134-32364-1-git-send-email-wenyou.yang@atmel.com>

In order to get lower consumption, as a workaround, suspend
the USB PORTA/B/C via set the SUSPEND_A/B/C bits of OHCI Interrupt
Configuration Register while OHCI USB suspending.

This suspend operation must be done before stopping the USB clock,
resume after the USB clock enabled.

Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
---

 drivers/usb/host/ohci-at91.c | 63 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index d177372..ce898e0 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -21,6 +21,8 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 
@@ -51,6 +53,7 @@ struct ohci_at91_priv {
 	struct clk *hclk;
 	bool clocked;
 	bool wakeup;		/* Saved wake-up state for resume */
+	struct regmap *sfr_regmap;
 };
 /* interface and function clocks; sometimes also an AHB clock */
 
@@ -132,6 +135,17 @@ static void at91_stop_hc(struct platform_device *pdev)
 
 /*-------------------------------------------------------------------------*/
 
+struct regmap *at91_dt_syscon_sfr(void)
+{
+	struct regmap *regmap;
+
+	regmap = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
+	if (IS_ERR(regmap))
+		return NULL;
+
+	return regmap;
+}
+
 static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
 
 /* configure so an HC device and id are always provided */
@@ -197,6 +211,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
 		goto err;
 	}
 
+	ohci_at91->sfr_regmap = at91_dt_syscon_sfr();
+
 	board = hcd->self.controller->platform_data;
 	ohci = hcd_to_ohci(hcd);
 	ohci->num_ports = board->ports;
@@ -581,6 +597,49 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#define SFR_OHCIICR		0x10
+#define SFR_OHCIICR_SUSPEND_A	BIT(8)
+#define SFR_OHCIICR_SUSPEND_B	BIT(9)
+#define SFR_OHCIICR_SUSPEND_C	BIT(10)
+
+#define SFR_OHCIICR_USB_SUSPEND	(SFR_OHCIICR_SUSPEND_A | \
+				 SFR_OHCIICR_SUSPEND_B | \
+				 SFR_OHCIICR_SUSPEND_C)
+
+static int ohci_at91_port_ctrl(struct regmap *regmap, bool enable)
+{
+	u32 regval;
+	int ret;
+
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	ret = regmap_read(regmap, SFR_OHCIICR, &regval);
+	if (ret)
+		return ret;
+
+	if (enable)
+		regval &= ~SFR_OHCIICR_USB_SUSPEND;
+	else
+		regval |= SFR_OHCIICR_USB_SUSPEND;
+
+	regmap_write(regmap, SFR_OHCIICR, regval);
+
+	regmap_read(regmap, SFR_OHCIICR, &regval);
+
+	return 0;
+}
+
+static int ohci_at91_port_suspend(struct regmap *regmap)
+{
+	return ohci_at91_port_ctrl(regmap, false);
+}
+
+static int ohci_at91_port_resume(struct regmap *regmap)
+{
+	return ohci_at91_port_ctrl(regmap, true);
+}
+
 static int __maybe_unused
 ohci_hcd_at91_drv_suspend(struct device *dev)
 {
@@ -618,6 +677,8 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
 		ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
 		ohci->rh_state = OHCI_RH_HALTED;
 
+		ohci_at91_port_suspend(ohci_at91->sfr_regmap);
+
 		/* flush the writes */
 		(void) ohci_readl (ohci, &ohci->regs->control);
 		at91_stop_clock(ohci_at91);
@@ -637,6 +698,8 @@ ohci_hcd_at91_drv_resume(struct device *dev)
 
 	at91_start_clock(ohci_at91);
 
+	ohci_at91_port_resume(ohci_at91->sfr_regmap);
+
 	ohci_resume(hcd, false);
 	return 0;
 }
-- 
2.7.4



From david.wu at rock-chips.com  Wed May 11 18:14:04 2016
From: david.wu at rock-chips.com (David.Wu)
Date: Thu, 12 May 2016 09:14:04 +0800
Subject: [PATCH v8 6/8] dt-bindings: i2c: rk3x: add support for rk3399
In-Reply-To: <CAD=FV=VzL8AfzUnPYgsf_NqPgbp2_o_qJC7-DWHmekWVQ-Es=A@mail.gmail.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908647-27236-1-git-send-email-david.wu@rock-chips.com>
 <CAD=FV=VzL8AfzUnPYgsf_NqPgbp2_o_qJC7-DWHmekWVQ-Es=A@mail.gmail.com>
Message-ID: <5733D8DC.1010603@rock-chips.com>

Hi Doug,

? 2016/5/12 0:35, Doug Anderson ??:
> Hi,
>
> On Tue, May 10, 2016 at 12:30 PM, David Wu <david.wu at rock-chips.com> wrote:
>> The bus clock and function clock are separated at rk3399,
>> and others use one clock as the bus clock and function clock.
>>
>> Signed-off-by: David Wu <david.wu at rock-chips.com>
>> Reviewed-by: Douglas Anderson <dianders at chromium.org>
>> ---
>> Change in v8:
>> - remove error description.
>>
>>   Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 16 +++++++++++++---
>>   1 file changed, 13 insertions(+), 3 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
>> index 0b4a85f..5429301 100644
>> --- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
>> +++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
>> @@ -6,10 +6,20 @@ RK3xxx SoCs.
>>   Required properties :
>>
>>    - reg : Offset and length of the register set for the device
>> - - compatible : should be "rockchip,rk3066-i2c", "rockchip,rk3188-i2c",
>> -               "rockchip,rk3228-i2c" or "rockchip,rk3288-i2c".
>> + - compatible: should be one of the following:
>> +   - "rockchip,rk3066-i2c": for rk3066
>> +   - "rockchip,rk3188-i2c": for rk3188
>> +   - "rockchip,rk3228-i2c": for rk3228
>> +   - "rockchip,rk3288-i2c": for rk3288
>> +   - "rockchip,rk3399-i2c": for rk3399
>>    - interrupts : interrupt number
>> - - clocks : parent clock
>> + - clocks: See ../clock/clock-bindings.txt
>> +   - For older hardware (rk3066, rk3188, rk3228, rk3288):
>> +     - There is one clock that's used both to derive the functional clock
>> +       for the device and as the bus clock.
>> +   - For newer hardware (rk3399): specified by name
>> +     - "i2c": REQUIRED. This is used to derive the functional clock.
>> +     - "pclk": REQUIRED. This is the bus clock.
>
> Depending on what Rob thinks, it might make sense to remove the above
> two "REQUIRED" bits.  That would match his earlier feedback since
> we're still in the "Required" section and thus it is redundant.
>

Okay, i make a little misunderstand for that, so i will fix it in next 
version.

> -Doug
>
>
>



From sboyd at codeaurora.org  Wed May 11 18:41:26 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Wed, 11 May 2016 18:41:26 -0700
Subject: [PATCH] tty: serial: msm: Disable restoring Rx interrupts for
 DMA Mode
In-Reply-To: <1462896580-11554-1-git-send-email-absahu@codeaurora.org>
References: <1462896580-11554-1-git-send-email-absahu@codeaurora.org>
Message-ID: <20160512014126.GK3492@codeaurora.org>

On 05/10, Abhishek Sahu wrote:
> From: Charanya <charanya at codeaurora.org>

Was it intentional to only have one name here?

> 
> The Data loss was happening with current QCOM MSM serial driver during
> large file transfer due to simultaneous enabling of both UART and
> DMA interrupt. When UART operates in DMA mode, RXLEV (Rx FIFO over
> watermark) or RXSTALE (stale interrupts) should not be enabled,
> since these conditions will be handled by DMA controller itself.
> If these interrupts are enabled then normal UART ISR will read some
> bytes of data from Rx Buffer and DMA controller will not receive
> these bytes of data, which will cause data loss.
> 
> Now this patch removed the code for enabling of RXLEV and RXSTALE
> interrupt in DMA Rx completion routine.

I'm lost, we keep both these irqs masked (well only if uartdm
version is 1.4 or greater) pretty much the entire time we're
using DMA for RX. msm_start_rx_dma() will mask them and then when
the callback completes we'll unmask them (the part that's deleted
in this patch), but then we'll go back and remask them almost
immediately because we call msm_start_rx_dma() from the dma
completion handler.

Can you clearly describe how this is actually fixing any
problems? What's the sequence of events that happens to cause
corruption?

This does raise the question though why we ever mask/unmask these
interrupts if we're always going to keep them masked while doing
DMA RX. Presumably if we can use DMA to RX, we can always use it
and set things up properly at startup time instead of later on.

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


From eric at anholt.net  Wed May 11 18:45:48 2016
From: eric at anholt.net (Eric Anholt)
Date: Wed, 11 May 2016 18:45:48 -0700
Subject: [PATCH 3/3] clk: bcm2835: Skip PLLC clocks when deciding on a new
 clock parent
In-Reply-To: <20160511225854.GI3492@codeaurora.org>
References: <1462842090-2017-1-git-send-email-eric@anholt.net>
 <1462842090-2017-4-git-send-email-eric@anholt.net>
 <20160511225854.GI3492@codeaurora.org>
Message-ID: <87mvnw82wj.fsf@eliezer.anholt.net>

Stephen Boyd <sboyd at codeaurora.org> writes:

> On 05/09, Eric Anholt wrote:
>> If the firmware had set up a clock to source from PLLC, go along with
>> it.  But if we're looking for a new parent, we don't want to switch it
>> to PLLC because the firmware will force PLLC (and thus the AXI bus
>> clock) to different frequencies during over-temp/under-voltage,
>> without notification to Linux.
>> 
>> On my system, this moves the Linux-enabled HDMI state machine and DSI1
>> escape clock over to plld_per from pllc_per.  EMMC still ends up on
>> pllc_per, because the firmware had set it up to use that.
>
> Is it ok for EMMC rate to change with over-temp/under-voltage?
> The description makes it sound like PLLC is for clks that want to
> run at some system bus rate and they don't care about exact
> frequencies.

I'm surprised it's OK for it to change, but the firmware is very
intentionally putting it on PLLC (there's this #define for where most
peripherals go, and EMMC doesn't use it and goes for PLLC instead).  If
we do decide we want to override the firmware, I suspect we'll use
assigned-clock-parents for that.

>> Signed-off-by: Eric Anholt <eric at anholt.net>
>> Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks")
>> diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
>> index 1091012ecec6..1d8f29ea9f69 100644
>> --- a/drivers/clk/bcm/clk-bcm2835.c
>> +++ b/drivers/clk/bcm/clk-bcm2835.c
>> @@ -1008,16 +1008,28 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw,
>>  	return 0;
>>  }
>>  
>> +static bool
>> +bcm2835_clk_is_pllc(struct clk_hw *hw)
>> +{
>> +	if (!hw)
>> +		return false;
>> +
>> +	return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0;
>
> This strcmp is not great. Any chance we could look for the parent
> by reading the hardware and knowing what bit corresponds to pllc
> as a parent? That would be much nicer so that we don't rely on
> string comparisons for something the hardware can tell us.

We just have the parent index, but which indices are pllc dividers is
different between bcm2835_clock_per_parents and
bcm2835_clock_vpu_parents.  So, I guess it's possible, but seems more
error-prone than the strncmp.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160511/cd7e6df2/attachment-0001.sig>

From chunfeng.yun at mediatek.com  Wed May 11 18:41:22 2016
From: chunfeng.yun at mediatek.com (chunfeng yun)
Date: Thu, 12 May 2016 09:41:22 +0800
Subject: [PATCH 6/6] pinctrl: mt8173: set GPIO16 to usb iddig mode
In-Reply-To: <1462991546.11623.3.camel@mussux00>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462868614-20602-7-git-send-email-chunfeng.yun@mediatek.com>
 <CACRpkdaeD5mk7LXEWnE0=Xute8-JA-fa4tVt4fYhujEXeq2+9w@mail.gmail.com>
 <1462991546.11623.3.camel@mussux00>
Message-ID: <1463017282.11651.82.camel@mhfsdcap03>

Hi,

On Wed, 2016-05-11 at 11:32 -0700, Hongzhou Yang wrote:
> On Wed, 2016-05-11 at 13:56 +0200, Linus Walleij wrote:
> > On Tue, May 10, 2016 at 10:23 AM, Chunfeng Yun
> > <chunfeng.yun at mediatek.com> wrote:
> > 
> > > the default mode of GPIO16 pin is gpio, when set EINT16 to
> > > IRQ_TYPE_LEVEL_HIGH, no interrupt is triggered, it can be
> > > fixed when set its default mode as usb iddig.
> > >
> > > Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
> > 
> 
> Chunfeng, GPIO16 can be used as EINT16 mode, but the pinmux should be 0.
> If you want to set its default mode to iddig, you should set it in dts.
> 
I set it in DTS, but it didn't work, because when usb driver requested
IRQ, pinmux was switched back to default mode set by
MTK_EINT_FUNCTION().


> Yours,
> Hongzhou
> 




From hongzhou.yang at mediatek.com  Wed May 11 19:09:02 2016
From: hongzhou.yang at mediatek.com (Hongzhou Yang)
Date: Wed, 11 May 2016 19:09:02 -0700
Subject: [PATCH 6/6] pinctrl: mt8173: set GPIO16 to usb iddig mode
In-Reply-To: <1463017282.11651.82.camel@mhfsdcap03>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462868614-20602-7-git-send-email-chunfeng.yun@mediatek.com>
 <CACRpkdaeD5mk7LXEWnE0=Xute8-JA-fa4tVt4fYhujEXeq2+9w@mail.gmail.com>
 <1462991546.11623.3.camel@mussux00> <1463017282.11651.82.camel@mhfsdcap03>
Message-ID: <1463018942.1608.5.camel@mussux00>

On Thu, 2016-05-12 at 09:41 +0800, chunfeng yun wrote:
> Hi,
> 
> On Wed, 2016-05-11 at 11:32 -0700, Hongzhou Yang wrote:
> > On Wed, 2016-05-11 at 13:56 +0200, Linus Walleij wrote:
> > > On Tue, May 10, 2016 at 10:23 AM, Chunfeng Yun
> > > <chunfeng.yun at mediatek.com> wrote:
> > > 
> > > > the default mode of GPIO16 pin is gpio, when set EINT16 to
> > > > IRQ_TYPE_LEVEL_HIGH, no interrupt is triggered, it can be
> > > > fixed when set its default mode as usb iddig.
> > > >
> > > > Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
> > > 
> > 
> > Chunfeng, GPIO16 can be used as EINT16 mode, but the pinmux should be 0.
> > If you want to set its default mode to iddig, you should set it in dts.
> > 
> I set it in DTS, but it didn't work, because when usb driver requested
> IRQ, pinmux was switched back to default mode set by
> MTK_EINT_FUNCTION().
> 

After confirmed, there are something wrong with data sheet and pinmux
table, and GPIO16 can only receive interrupt by mode 1. So

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

Yours,
Hongzhou




From zhaoshenglong at huawei.com  Wed May 11 19:22:07 2016
From: zhaoshenglong at huawei.com (Shannon Zhao)
Date: Thu, 12 May 2016 10:22:07 +0800
Subject: [PATCH] Xen: EFI: Parse DT parameters for Xen specific UEFI
In-Reply-To: <20160511232444.GY2839@codeblueprint.co.uk>
References: <1462523526-3172-1-git-send-email-zhaoshenglong@huawei.com>
 <20160511122730.GU2839@codeblueprint.co.uk> <57333533.2030206@linaro.org>
 <20160511232444.GY2839@codeblueprint.co.uk>
Message-ID: <5733E8CF.3070004@huawei.com>



On 2016/5/12 7:24, Matt Fleming wrote:
> On Wed, 11 May, at 09:35:47PM, Shannon Zhao wrote:
>>> > > 
>>> > > Also, why do you need to setup efi.runtime_version here? Isn't that
>>> > > done inside uefi_init()?
>>> > > 
>> > I don't see any codes which setup efi.runtime_version in uefi_init().
>  
> Look in the EFI tree,
> 
>   https://git.kernel.org/cgit/linux/kernel/git/mfleming/efi.git/tree/drivers/firmware/efi/arm-init.c?h=next#n120
> 
Ah, there are some patches in EFI tree introducing this change, but they
are not in kernel matser but I didn't notice this, sorry.

>>> > > Here is how I would have expected this patch to look:
>>> > > 
>>> > >   - Add FDT code to find hypervisor EFI params
>>> > > 
>>> > >   - Force enable EFI_RUNTIME_SERVICES for Xen and call
>>> > >     xen_efi_runtime_setup() inside xen_guest_init()
>>> > > 
>>> > >   - Change arm_enable_runtime_services() to handle the case where
>>> > >     EFI_RUNTIME_SERVICES is already set
>>> > > 
>>> > > Am I misunderstanding some ordering issues?
>> > 
>> > Since xen_guest_init() and arm_enable_runtime_services() are both
>> > early_initcall and the calling order is random I think.
> Urgh, right, I missed that.
> 
>> > And when we call xen_efi_runtime_setup() and setup
>> > efi.runtime_version in xen_guest_init(), the efi.systab might be
>> > NULL. So it needs to map the systanle explicitly before we use
>> > efi.systab.
> Could you explain why you need to copy efi.runtime_version instead of
> letting the existing code in uefi_init() set it up?
> 
> Also, efi.systab isn't used by xen_efi_runtime_setup() as far I can
> see, not sure why you need that either?
As said above, I will rebase this patch on top of the EFI next branch.

Thanks,
-- 
Shannon



From huawei.libin at huawei.com  Wed May 11 19:26:40 2016
From: huawei.libin at huawei.com (Li Bin)
Date: Thu, 12 May 2016 10:26:40 +0800
Subject: [PATCH v12 00/10] arm64: Add kernel probes (kprobes) support
In-Reply-To: <573350B2.4010701@arm.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <573350B2.4010701@arm.com>
Message-ID: <5733E9E0.1060504@huawei.com>



on 2016/5/11 23:33, James Morse wrote:
> Hi David,
> 
> On 27/04/16 19:52, David Long wrote:
>> From: "David A. Long" <dave.long at linaro.org>
>>
>> This patchset is heavily based on Sandeepa Prabhu's ARM v8 kprobes patches,
>> first seen in October 2013. This version attempts to address concerns raised by
>> reviewers and also fixes problems discovered during testing.
>>
>> This patchset adds support for kernel probes(kprobes), jump probes(jprobes)
>> and return probes(kretprobes) support for ARM64.
>>
>> The kprobes mechanism makes use of software breakpoint and single stepping
>> support available in the ARM v8 kernel.
> 
> I applied this series on v4.6-rc7, and built the sample kprobes. They work fine,
> unless I throw ftrace into the mix too.
> 
> I enabled the function_graph tracer, then tried to load the jprobe example module:
> -------------------------%<-------------------------
> root at ubuntu:/sys/kernel/debug/tracing# insmod /root/jprobe_example.ko
> Planted jprobe at ffffff80080c8f20, handler addr ffffff8000bb3000
> root at ubuntu:/sys/kernel/debug/tracing# jprobe: clone_flags = 0x1200011, stack_st
> art = 0x0 stack_size = 0x0
> Bad mode in Synchronous Abort handler detected, code 0x86000005 -- IABT (current
>  EL)
> CPU: 5 PID: 1047 Comm: systemd-udevd Not tainted 4.6.0-rc7+ #4064
> Hardware name: ARM Juno development board (r1) (DT)
> task: ffffffc975948300 ti: ffffffc974e4c000 task.ti: ffffffc974e4c000
> PC is at 0x0
> LR is at 0x0
> 
> pc : [<0000000000000000>] lr : [<0000000000000000>] pstate: 60000145
> sp : ffffffc974e4ff00
> x29: 0000000001200011 x28: ffffffc974e4c000
> x27: ffffff80088d0000 x26: 00000000000000dc
> x25: 0000000000000120 x24: 0000000000000015
> x23: 0000000060000000 x22: 0000007fa1b40e60
> x21: 0000007fa1ce70d0 x20: 0000000000000000
> x19: 0000000000000000 x18: 0000000000000a03
> x17: 0000007fa1b40d90 x16: ffffff80080c9708
> x15: 003b9aca00000000 x14: 0000007fddb7e5c0
> x13: 0000007fa1b40e2c x12: 0000000000d00ff0
> x11: ffffff8009c4d000 x10: ffffff800920c000
> x9 : ffffff8008f5c000 x8 : ffffffc976c06800
> x7 : 000000000006daf2 x6 : 0000000000000015
> x5 : 0000000000000004 x4 : ffffffc96e8690a0
> x3 : 0000001ed7cbab74 x2 : ffffffc96e869000
> x1 : 0000000000000000 x0 : 0000000000000000
> 
> Internal error: Oops - bad mode: 0 [#1] PREEMPT SMP
> Modules linked in: jprobe_example
> CPU: 5 PID: 1047 Comm: systemd-udevd Not tainted 4.6.0-rc7+ #4064
> Hardware name: ARM Juno development board (r1) (DT)
> task: ffffffc975948300 ti: ffffffc974e4c000 task.ti: ffffffc974e4c000
> PC is at 0x0
> LR is at 0x0
> 
> pc : [<0000000000000000>] lr : [<0000000000000000>] pstate: 60000145
> sp : ffffffc974e4ff00
> x29: 0000000001200011 x28: ffffffc974e4c000
> x27: ffffff80088d0000 x26: 00000000000000dc
> x25: 0000000000000120 x24: 0000000000000015
> x23: 0000000060000000 x22: 0000007fa1b40e60
> x21: 0000007fa1ce70d0 x20: 0000000000000000
> x19: 0000000000000000 x18: 0000000000000a03
> x17: 0000007fa1b40d90 x16: ffffff80080c9708
> x15: 003b9aca00000000 x14: 0000007fddb7e5c0
> x13: 0000007fa1b40e2c x12: 0000000000d00ff0
> x11: ffffff8009c4d000 x10: ffffff800920c000
> x9 : ffffff8008f5c000 x8 : ffffffc976c06800
> x7 : 000000000006daf2 x6 : 0000000000000015
> x5 : 0000000000000004 x4 : ffffffc96e8690a0
> x3 : 0000001ed7cbab74 x2 : ffffffc96e869000
> x1 : 0000000000000000 x0 : 0000000000000000
> 
> Process systemd-udevd (pid: 1047, stack limit = 0xffffffc974e4c020)
> Stack: (0xffffffc974e4ff00 to 0xffffffc974e50000)
> ff00: 0000000000000417 0000007fa1ce76f0 00000000000000dc 0000000000000417
> ff20: 00000000ffffffff 0000007fddb7ecf8 0000000000000005 ffffffffffffffff
> ff40: 00000000ff000001 003b9aca00000000 000000555b3868b0 0000007fa1b40d90
> ff60: 0000000000000a03 0000007fddb7e5c0 0000000000000000 0000007fddb7e5e0
> ff80: 000000555b358000 000000558f56f0e0 0000000000000000 000000558f574f00
> ffa0: 000000558f574f00 00000000000004fa 000000558f56f010 0000007fddb7e600
> ffc0: 0000007fa1b40e2c 0000007fddb7e5c0 0000007fa1b40e60 0000000060000000
> ffe0: 0000000001200011 00000000000000dc 0004000084000200 0800000002000000
> Call trace:
> [<          (null)>]           (null)
> Code: bad PC value
> ---[ end trace 35d24aad799c2941 ]---
> -------------------------%<-------------------------
> 

To solve this, it should pause function tracing before the jprobe handler is called
and unpause it before it returns back to the function it probed.

diff --git a/arch/arm64/kernel/kprobes.c b/arch/arm64/kernel/kprobes.c
index db2d95c..b21ed00 100644
--- a/arch/arm64/kernel/kprobes.c
+++ b/arch/arm64/kernel/kprobes.c
@@ -714,6 +714,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)

        instruction_pointer_set(regs, (long)jp->entry);
        preempt_disable();
+       pause_graph_tracing();
        return 1;
 }

@@ -757,6 +758,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
                        show_regs(regs);
                        BUG();
                }
+               unpause_graph_tracing();
                *regs = kcb->jprobe_saved_regs;
                memcpy((void *)stack_addr, kcb->jprobes_stack,
                       MIN_STACK_SIZE(stack_addr));


Li Bin

> 
> Thanks,
> 
> 
> James
> 
> 
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 
> .
> 



From sricharan at codeaurora.org  Wed May 11 19:28:59 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Thu, 12 May 2016 07:58:59 +0530
Subject: [PATCH 1/2] i2c: qup: Cleared the error bits in ISR
In-Reply-To: <934365f2bd30f242d8548e2a27483679@codeaurora.org>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
 <1462797871-8595-2-git-send-email-absahu@codeaurora.org>
 <000701d1ab9d$df9b3100$9ed19300$@codeaurora.org>
 <934365f2bd30f242d8548e2a27483679@codeaurora.org>
Message-ID: <000901d1abf6$0f3ebf50$2dbc3df0$@codeaurora.org>

Hi,

> -----Original Message-----
> From: linux-arm-kernel [mailto:linux-arm-kernel-
> bounces at lists.infradead.org] On Behalf Of Abhishek Sahu
> Sent: Wednesday, May 11, 2016 11:04 PM
> To: Sricharan <sricharan at codeaurora.org>
> Cc: architt at codeaurora.org; wsa at the-dreams.de; linux-arm-
> msm at vger.kernel.org; ntelkar at codeaurora.org; linux-
> kernel at vger.kernel.org; dmaengine at vger.kernel.org; linux-
> i2c at vger.kernel.org; agross at codeaurora.org; andy.gross at linaro.org; linux-
> arm-kernel at lists.infradead.org
> Subject: RE: [PATCH 1/2] i2c: qup: Cleared the error bits in ISR
> 
> On 2016-05-11 21:27, Sricharan wrote:
> > Hi,
> >
> >> 1. Current QCOM I2C driver hangs when sending data to address
> >> 0x03-0x07
> >> in some scenarios. The QUP controller generates invalid write in this
> >> case, since these addresses are reserved for different bus formats.
> >>
> >> 2. Also, the error handling is done by I2C QUP ISR in the case of DMA
> >> mode.
> >> The state need to be RESET in case of any error for clearing the
> >> available data in FIFO, which otherwise leaves the BAM DMA controller
> >> in hang state.
> >>
> >> This patch fixes the above two issues by clearing the error bits from
> >> I2C and QUP status in ISR in case of I2C error, QUP error and resets
> >> the QUP state to clear the FIFO data.
> >>
> >> Signed-off-by: Abhishek Sahu <absahu at codeaurora.org>
> >> ---
> >>  drivers/i2c/busses/i2c-qup.c | 14 ++++++++------
> >>  1 file changed, 8 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/i2c/busses/i2c-qup.c
> >> b/drivers/i2c/busses/i2c-qup.c index 23eaabb..8c2f1bc 100644
> >> --- a/drivers/i2c/busses/i2c-qup.c
> >> +++ b/drivers/i2c/busses/i2c-qup.c
> >> @@ -213,14 +213,16 @@ static irqreturn_t qup_i2c_interrupt(int irq,
> >> void
> >> *dev)
> >>  	bus_err &= I2C_STATUS_ERROR_MASK;
> >>  	qup_err &= QUP_STATUS_ERROR_FLAGS;
> >>
> >> -	if (qup_err) {
> >> -		/* Clear Error interrupt */
> >> +	/* Clear the error bits in QUP_ERROR_FLAGS */
> >> +	if (qup_err)
> >>  		writel(qup_err, qup->base + QUP_ERROR_FLAGS);
> >> -		goto done;
> >> -	}
> >>
> >> -	if (bus_err) {
> >> -		/* Clear Error interrupt */
> >> +	/* Clear the error bits in QUP_I2C_STATUS */
> >> +	if (bus_err)
> >> +		writel(bus_err, qup->base + QUP_I2C_STATUS);
> >> +
> >> +	/* Reset the QUP State in case of error */
> >> +	if (qup_err || bus_err) {
> >>  		writel(QUP_RESET_STATE, qup->base + QUP_STATE);
> >>  		goto done;
> >>  	}
> >        In qup_i2c_xfer and qup_i2c_xfer_v2 state is set to RESET at
> > the end, when
> >        there is no error. So would it be fine if we do it there
> > unconditionally ?
> >
> > Regards,
> >  Sricharan
> 
> RESET the QUP state wouldn't create any issue in the case of multiple
calls.
> The existing code also RESET the QUP state for bus_err but it is not
clearing
> status bits.
    So is there a difference that you see by setting it in isr for qup
errors ?
    Otherwise, its better to set it in one place unconditionally instead of
doing
    it in two places ?

Regards,
 Sricharan



From hongzhou.yang at mediatek.com  Wed May 11 19:55:01 2016
From: hongzhou.yang at mediatek.com (Hongzhou Yang)
Date: Wed, 11 May 2016 19:55:01 -0700
Subject: [PATCH 6/6] pinctrl: mt8173: set GPIO16 to usb iddig mode
In-Reply-To: <1463018942.1608.5.camel@mussux00>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462868614-20602-7-git-send-email-chunfeng.yun@mediatek.com>
 <CACRpkdaeD5mk7LXEWnE0=Xute8-JA-fa4tVt4fYhujEXeq2+9w@mail.gmail.com>
 <1462991546.11623.3.camel@mussux00> <1463017282.11651.82.camel@mhfsdcap03>
 <1463018942.1608.5.camel@mussux00>
Message-ID: <1463021701.25171.5.camel@mussux00>

On Wed, 2016-05-11 at 19:09 -0700, Hongzhou Yang wrote:
> On Thu, 2016-05-12 at 09:41 +0800, chunfeng yun wrote:
> > Hi,
> > 
> > On Wed, 2016-05-11 at 11:32 -0700, Hongzhou Yang wrote:
> > > On Wed, 2016-05-11 at 13:56 +0200, Linus Walleij wrote:
> > > > On Tue, May 10, 2016 at 10:23 AM, Chunfeng Yun
> > > > <chunfeng.yun at mediatek.com> wrote:
> > > > 
> > > > > the default mode of GPIO16 pin is gpio, when set EINT16 to
> > > > > IRQ_TYPE_LEVEL_HIGH, no interrupt is triggered, it can be
> > > > > fixed when set its default mode as usb iddig.
> > > > >
> > > > > Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
> > > > 
> > > 
> > > Chunfeng, GPIO16 can be used as EINT16 mode, but the pinmux should be 0.
> > > If you want to set its default mode to iddig, you should set it in dts.
> > > 
> > I set it in DTS, but it didn't work, because when usb driver requested
> > IRQ, pinmux was switched back to default mode set by
> > MTK_EINT_FUNCTION().
> > 
> 
> After confirmed, there are something wrong with data sheet and pinmux
> table, and GPIO16 can only receive interrupt by mode 1. So
> 
> Acked-by: Hongzhou Yang <hongzhou.yang at mediatek.com>
> 

Linus,

We find there are some other pins still have the same problem, so please
hold on it. Sorry for so much noise.

Thanks,
Hongzhou



From shawn.lin at rock-chips.com  Wed May 11 20:13:54 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Thu, 12 May 2016 11:13:54 +0800
Subject: [PATCH v2] mmc: dw_mmc: rockchip: Set the drive phase properly
In-Reply-To: <1463002848-580-1-git-send-email-dianders@chromium.org>
References: <1463002848-580-1-git-send-email-dianders@chromium.org>
Message-ID: <4ea71cf9-873f-960a-67cb-54da603fd628@rock-chips.com>

On 2016/5/12 5:40, Douglas Anderson wrote:
> Historically for Rockchip devices we've relied on the power-on
> default (or perhaps the firmware setting) to get the correct drive
> phase for dw_mmc devices.  This worked OK for the most part, but:
>
> * Relying on the setting just "being right" is a bit fragile.
>
> * As soon as there is an instance where the power on default is wrong or
>   where the firmware didn't configure this properly then we'll get a
>   mysterious failure.
>
> Let's explicitly set this phase in the kernel.
>
> The comments inside this patch try to explain the situation quite
> throughly, but the high level overview of this is:
>
> Before this patch on rk3288 devices tested:
> * eMMC: 180 degrees
> * SDMMC/SDIO0/SDIO1: 90 degrees
>
> After this patch:
> * Use 90 degree phase offset usually.
> * Use 180 degree phase offset for MMC_DDR52, SDR104, HS200.

Thanks for doing this.

Reviewed-by: Shawn Lin<shawn.lin at rock-chips.com>

>
> That means we are _changing_ behavior for those devices in this way:
>
> * If we have HS200 eMMC or DDR52 eMMC, we'll run ID mode at 90
>   degrees (vs 180) but otherwise have no change.
>
> * For any non-HS200 / non-DDR52 eMMC devices we'll now _always_ run at
>   90 degrees (vs 180).  It seems fairly unlikely that building modern
>   hardware is using an eMMC that isn't using DDR52 or HS200, of course.
>
> * For SDR104 cards we'll now run with 180 degree phase offset (vs 90).
>   It's expected that 90 degree phase offset would have worked OK, but
>   this gives us extra margin.
>
> I have tested this by inserting my collection of uSD cards (mostly UHS,
> though a few not) into a veyron_minnie and confirmed that they still
> seem to enumerate properly.  For a subset of them I tried putting a
> filesystem on them and also tried running mmc_test.
>
> Signed-off-by: Douglas Anderson <dianders at chromium.org>
> ---
> Changes in v2:
> - Now use 90 degrees for some modes; updated comments to say why.
>
>  drivers/mmc/host/dw_mmc-rockchip.c | 64 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 64 insertions(+)
>
> diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
> index 8c20b81cafd8..8068fa887db8 100644
> --- a/drivers/mmc/host/dw_mmc-rockchip.c
> +++ b/drivers/mmc/host/dw_mmc-rockchip.c
> @@ -66,6 +66,70 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>  	/* Make sure we use phases which we can enumerate with */
>  	if (!IS_ERR(priv->sample_clk))
>  		clk_set_phase(priv->sample_clk, priv->default_sample_phase);
> +
> +	/*
> +	 * Set the drive phase offset based on speed mode to achieve hold times.
> +	 *
> +	 * That this is _not_ a value that is dynamically tuned and is also
> +	 * _not_ a value that will vary from board to board.  It is a value
> +	 * that could vary between different SoC models if they had massively
> +	 * different output clock delays inside their dw_mmc IP block (delay_o),
> +	 * but since it's OK to overshoot a little we don't need to do complex
> +	 * calculations and can pick values that will just work for everyone.
> +	 *
> +	 * When picking values we'll stick with picking 0/90/180/270 since
> +	 * those can be made very accurately on all known Rockchip SoCs.
> +	 *
> +	 * Note that these values match values from the DesignWare Databook
> +	 * tables for the most part except for SDR12 and "ID mode".  For those
> +	 * two modes the databook calculations assume a clock in of 50MHz.  As
> +	 * seen above, we always use a clock in rate that is exactly the
> +	 * card's input clock (times RK3288_CLKGEN_DIV, but that gets divided
> +	 * back out before the controller sees it).
> +	 *
> +	 * From measurement of a single device, it appears that delay_o is
> +	 * about .5 ns.  Since we try to leave a bit of margin, it's expected
> +	 * that numbers here will be fine even with much larger delay_o
> +	 * (the 1.4 ns assumed by the DesignWare Databook would result in the
> +	 * same results, for instance).
> +	 */
> +	if (!IS_ERR(priv->drv_clk)) {
> +		int phase;
> +
> +		/*
> +		 * In almost all cases a 90 degree phase offset will provide
> +		 * sufficient hold times across all valid input clock rates
> +		 * assuming delay_o is not absurd for a given SoC.  We'll use
> +		 * that as a default.
> +		 */
> +		phase = 90;
> +
> +		switch (ios->timing) {
> +		case MMC_TIMING_MMC_DDR52:
> +			/*
> +			 * Since clock in rate with MMC_DDR52 is doubled when
> +			 * bus width is 8 we need to double the phase offset
> +			 * to get the same timings.
> +			 */
> +			if (ios->bus_width == MMC_BUS_WIDTH_8)
> +				phase = 180;
> +			break;
> +		case MMC_TIMING_UHS_SDR104:
> +		case MMC_TIMING_MMC_HS200:
> +			/*
> +			 * In the case of 150 MHz clock (typical max for
> +			 * Rockchip SoCs), 90 degree offset will add a delay
> +			 * of 1.67 ns.  That will meet min hold time of .8 ns
> +			 * as long as clock output delay is < .87 ns.  On
> +			 * SoCs measured this seems to be OK, but it doesn't
> +			 * hurt to give margin here, so we use 180.
> +			 */
> +			phase = 180;
> +			break;
> +		}
> +
> +		clk_set_phase(priv->drv_clk, phase);
> +	}
>  }
>
>  #define NUM_PHASES			360
>


-- 
Best Regards
Shawn Lin



From plaes at plaes.org  Wed May 11 20:39:20 2016
From: plaes at plaes.org (Priit Laes)
Date: Thu, 12 May 2016 06:39:20 +0300
Subject: [linux-sunxi] Re: [PATCH v4 01/11] clk: sunxi: Add display and
 TCON0 clocks driver
In-Reply-To: <20160511221541.GG3492@codeaurora.org>
References: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
 <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
 <20160506223002.GE3492@codeaurora.org> <20160508200308.GF6167@lukather>
 <20160509223238.GW3492@codeaurora.org>
 <20160509223924.GX3492@codeaurora.org> <1462907459.9981.0.camel@plaes.org>
 <20160511221541.GG3492@codeaurora.org>
Message-ID: <1463024360.16747.4.camel@plaes.org>

On Wed, 2016-05-11 at 15:15 -0700, Stephen Boyd wrote:
> On 05/10, Priit Laes wrote:
> > 
> > On Mon, 2016-05-09 at 15:39 -0700, Stephen Boyd wrote:
> > > 
> > > On 05/09, Stephen Boyd wrote:
> > > > 
> > > > 
> > > > 
> > > > Ok I applied this one to clk-next.
> > > > 
> > > And I squashed this in to silence the following checker warning.
> > > 
> > > drivers/clk/sunxi/clk-sun4i-display.c:110:33: warning: Variable
> > > length array is used.
> > > 
> > > ---8<---
> > > diff --git a/drivers/clk/sunxi/clk-sun4i-display.c
> > > b/drivers/clk/sunxi/clk-sun4i-display.c
> > > index f02e250e64ed..f8ff6c4a5633 100644
> > > --- a/drivers/clk/sunxi/clk-sun4i-display.c
> > > +++ b/drivers/clk/sunxi/clk-sun4i-display.c
> > > @@ -107,7 +107,7 @@ static int
> > > sun4i_a10_display_reset_xlate(struct
> > > reset_controller_dev *rcdev,
> > > ?static void __init sun4i_a10_display_init(struct device_node
> > > *node,
> > > ?					??const struct
> > > sun4i_a10_display_clk_data *data)
> > > ?{
> > > -	const char *parents[data->parents];
> > > +	const char *parents[4];
> > This change breaks at least de_[bf]e clocks which have 3 clock
> > parents.

> I just used the largest data->parents number, which was 4. How
> does that break anything?

If you look at the?sun4i_a10_display_init, it contains this block:

? ? ret = of_clk_parent_fill(node, parents, ARRAY_SIZE(parents));
????if (ret != ARRAY_SIZE(parents)) {
????????pr_err("%s: Could not retrieve the parents\n", clk_name);
????????goto unmap;
????}

of_clk_parent_fill returns 3 for de_be/de_fe nodes, and
ARRAY_SIZE(parents) is 4.

P?ikest,
Priit :)


From bamvor.zhangjian at huawei.com  Wed May 11 20:45:53 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Thu, 12 May 2016 11:45:53 +0800
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <5250356.myv9GIZ34h@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <573305A8.50406@huawei.com> <5733149C.4030903@huawei.com>
 <5250356.myv9GIZ34h@wuerfel>
Message-ID: <5733FC71.8070101@huawei.com>

Hi, Arnd

On 2016/5/11 22:50, Arnd Bergmann wrote:
> On Wednesday 11 May 2016 19:16:44 Zhangjian wrote:
>> Hi,
>>
>> On 2016/5/11 18:12, Zhangjian (Bamvor) wrote:
>>> Hi, Arnd
>>>
>>> On 2016/5/11 16:09, Arnd Bergmann wrote:
>>>   > On Wednesday 11 May 2016 10:04:16 Zhangjian wrote:
>>>   >>> I don't remember. It's probably not important whether we have the shift
>>>   >>> in there, as long as it's independent of the actual kernel page size and
>>>   >>> user space and kernel agree on the calling conventions.
>>>   >> Well. I am ok with where to shift the pages size because we get the same
>>>   >> result. I was just thinking if we should get rid of the name of mmap2 in our
>>>   >> ILP32 porting. Actually, it is mmap but we name it as mmap2. User may confused
>>>   >> if they do not know the implementations.
>>>   >
>>>   > That is a good point: If the implementation matches the mmap() behavior rather than
>>>   > mmap2(), we should rename the macro by doing
>>>   >
>>>   > #undef __NR_mmap2
>>>   > #define __NR_mmap 222
>>>   >
>>>   > in the uapi/asm/unistd.h file for ilp32 mode.
>>> Do you mean define the following things in kernel:
>>> ```
>>> diff --git a/arch/arm64/include/uapi/asm/unistd.h b/arch/arm64/include/uapi/asm/unistd.h
>>> index 1caadc2..3f79640 100644
>>> --- a/arch/arm64/include/uapi/asm/unistd.h
>>> +++ b/arch/arm64/include/uapi/asm/unistd.h
>>> @@ -14,3 +14,9 @@
>>>     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>>     */
>>>    #include <asm-generic/unistd.h>
>>> +
>>> +#ifdef __ILP32__
>>> +#undef __NR_mmap2
>>> +#define __NR_mmap 222
>>> +#endif /* #ifdef __ILP32__ */
>>> +
>>> ```
>>> Then glibc could call mmap instead of mmap2.
>>> I could not try it now. Because after change off_t to 64bit in glibc, stat
>>> is fail. I may need to revert the stat relative patch.
>> After revert stat relative patch in glibc, mmap01-mmap14 success. But mmap16
>> success with segfault. I will investigate it later.
>>
>> There is pointer and size_t in mmap, so, IIUC, we need to clear the top halves
>> of register by using COMPAT_SYSCALL_WRAP6.
>
> Correct, good catch!
>
>> And after check the function in
>> arch/s390/kernel/compat_linux.c, I feel that we need to do the same thing for
>> pread64 and pwrite64.
>>
>
>> But I got following error when I try to add
>> COMPAT_SYSCALL_WRAP4(pread64, unsigned int, fd, char __user *, buf,
>> size_t, count, loff_t, pos);
>> COMPAT_SYSCALL_WRAP4(pwrite64, unsigned int, fd, const char __user *, buf,
>> size_t, count, loff_t, pos);
>>
>
> Hmm, that is indeed tricky. I think COMPAT_SYSCALL_WRAP4 rightfully
> refuses the loff_t argument here, as the common case is that this is
> not possible.
It works if I apply the following patch, I defined the wrong `__TYPE_IS_xxx`
yesterday. Should we merge this into ILP32 series or send the compat.h
and syscalls.h individually? The current series of ILP32 is a little bit
long and hard to review.
diff --git a/include/linux/compat.h b/include/linux/compat.h
index ba6ebe0..22a9565 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -747,7 +747,8 @@ asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32,
  #ifndef __SC_COMPAT_CAST
  #define __SC_COMPAT_CAST(t, a) ({                                      \
         BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) &&              \
-                    !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t));            \
+                    !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t) &&           \
+                    !__TYPE_IS_LOFFT(t));                              \
         ((t) ((t)(-1) < 0 ? (s64)(s32)(a) : (u64)(u32)(a)));            \
  })
  #endif
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 6e57d9c..66eb85d 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -47,6 +47,7 @@
  #define __TYPE_IS_L(t) (__same_type((t)0, 0L))
  #define __TYPE_IS_UL(t)        (__same_type((t)0, 0UL))
  #define __TYPE_IS_LL(t) (__same_type((t)0, 0LL) || __same_type((t)0, 0ULL))
+#define __TYPE_IS_LOFFT(t)     (__same_type((t)0, (loff_t)0))
  #define __SC_LONG(t, a) __typeof(__builtin_choose_expr(__TYPE_IS_LL(t), 0LL, 0L)) a
  #define __SC_CAST(t, a)        (t) a
  #define __SC_ARGS(t, a)        a
diff --git a/kernel/compat_wrapper.c b/kernel/compat_wrapper.c
index 98b68b8..28f02d0 100644
--- a/kernel/compat_wrapper.c
+++ b/kernel/compat_wrapper.c
@@ -304,3 +304,7 @@ COMPAT_SYSCALL_WRAP3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
  COMPAT_SYSCALL_WRAP6(sendto, int, fd, void __user *, buff, size_t, len,
                      unsigned int, flags, struct sockaddr __user *, addr,
                      int, addr_len);
+COMPAT_SYSCALL_WRAP4(pread64, unsigned int, fd, char __user *, buf,
+                       size_t, count, loff_t, pos);
+COMPAT_SYSCALL_WRAP4(pwrite64, unsigned int, fd, const char __user *, buf,
+                        size_t, count, loff_t, pos);
 >
 > Can you open-code this using a COMPAT_SYSCALL4 definition similar to what
 > arch/tile has, but without the merging of the two halves of the argument?
I am lost here. Tile do not use the wrapper, and it do not use the loff_t
either:
COMPAT_SYSCALL_DEFINE6(pread64, unsigned int, fd, char __user *, ubuf,
                        size_t, count, u32, dummy, u32, low, u32, high)

Regards

Bamvor
> 	Arnd
>



From alexandre.belloni at free-electrons.com  Wed May 11 20:53:15 2016
From: alexandre.belloni at free-electrons.com (Alexandre Belloni)
Date: Thu, 12 May 2016 05:53:15 +0200
Subject: [PATCH] usb: ohci-at91: Suspend the ports while USB suspending
In-Reply-To: <1463015134-32364-1-git-send-email-wenyou.yang@atmel.com>
References: <1463015134-32364-1-git-send-email-wenyou.yang@atmel.com>
Message-ID: <20160512035315.GA19408@piout.net>

Hi,

On 12/05/2016 at 09:05:34 +0800, Wenyou Yang wrote :
> In order to get lower consumption, as a workaround, suspend
> the USB PORTA/B/C via set the SUSPEND_A/B/C bits of OHCI Interrupt
> Configuration Register while OHCI USB suspending.
> 

Why is that a workaround?

> This suspend operation must be done before stopping the USB clock,
> resume after the USB clock enabled.
> 
> Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> ---
> 
>  drivers/usb/host/ohci-at91.c | 63 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 63 insertions(+)
> 
> diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
> index d177372..ce898e0 100644
> --- a/drivers/usb/host/ohci-at91.c
> +++ b/drivers/usb/host/ohci-at91.c
> @@ -21,6 +21,8 @@
>  #include <linux/io.h>
>  #include <linux/kernel.h>
>  #include <linux/module.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
>  #include <linux/usb.h>
>  #include <linux/usb/hcd.h>
>  
> @@ -51,6 +53,7 @@ struct ohci_at91_priv {
>  	struct clk *hclk;
>  	bool clocked;
>  	bool wakeup;		/* Saved wake-up state for resume */
> +	struct regmap *sfr_regmap;
>  };
>  /* interface and function clocks; sometimes also an AHB clock */
>  
> @@ -132,6 +135,17 @@ static void at91_stop_hc(struct platform_device *pdev)
>  
>  /*-------------------------------------------------------------------------*/
>  
> +struct regmap *at91_dt_syscon_sfr(void)
> +{
> +	struct regmap *regmap;
> +
> +	regmap = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
> +	if (IS_ERR(regmap))
> +		return NULL;
> +
> +	return regmap;
> +}
> +
>  static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
>  
>  /* configure so an HC device and id are always provided */
> @@ -197,6 +211,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
>  		goto err;
>  	}
>  
> +	ohci_at91->sfr_regmap = at91_dt_syscon_sfr();
> +
>  	board = hcd->self.controller->platform_data;
>  	ohci = hcd_to_ohci(hcd);
>  	ohci->num_ports = board->ports;
> @@ -581,6 +597,49 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +#define SFR_OHCIICR		0x10
> +#define SFR_OHCIICR_SUSPEND_A	BIT(8)
> +#define SFR_OHCIICR_SUSPEND_B	BIT(9)
> +#define SFR_OHCIICR_SUSPEND_C	BIT(10)
> +
> +#define SFR_OHCIICR_USB_SUSPEND	(SFR_OHCIICR_SUSPEND_A | \
> +				 SFR_OHCIICR_SUSPEND_B | \
> +				 SFR_OHCIICR_SUSPEND_C)
> +

Those defines should go in a header file either in include/soc/at91 or
in include/linux/mfd

> +static int ohci_at91_port_ctrl(struct regmap *regmap, bool enable)
> +{
> +	u32 regval;
> +	int ret;
> +
> +	if (IS_ERR(regmap))
> +		return PTR_ERR(regmap);
> +
> +	ret = regmap_read(regmap, SFR_OHCIICR, &regval);
> +	if (ret)
> +		return ret;
> +
> +	if (enable)
> +		regval &= ~SFR_OHCIICR_USB_SUSPEND;
> +	else
> +		regval |= SFR_OHCIICR_USB_SUSPEND;
> +
> +	regmap_write(regmap, SFR_OHCIICR, regval);
> +
> +	regmap_read(regmap, SFR_OHCIICR, &regval);
> +
> +	return 0;
> +}
> +
> +static int ohci_at91_port_suspend(struct regmap *regmap)
> +{
> +	return ohci_at91_port_ctrl(regmap, false);
> +}
> +
> +static int ohci_at91_port_resume(struct regmap *regmap)
> +{
> +	return ohci_at91_port_ctrl(regmap, true);
> +}
> +
>  static int __maybe_unused
>  ohci_hcd_at91_drv_suspend(struct device *dev)
>  {
> @@ -618,6 +677,8 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
>  		ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
>  		ohci->rh_state = OHCI_RH_HALTED;
>  
> +		ohci_at91_port_suspend(ohci_at91->sfr_regmap);
> +

The main issue I see here is that you will call that function for all
SoCs and it will always fail unless it is running on a sama5d2. Maybe we
could be smarter about that.


-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com


From andy.gross at linaro.org  Wed May 11 22:02:45 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 00:02:45 -0500
Subject: [PATCH] tty: serial: msm: Disable restoring Rx interrupts for
 DMA Mode
In-Reply-To: <20160512014126.GK3492@codeaurora.org>
References: <1462896580-11554-1-git-send-email-absahu@codeaurora.org>
 <20160512014126.GK3492@codeaurora.org>
Message-ID: <20160512050245.GD8453@hector.attlocal.net>

On Wed, May 11, 2016 at 06:41:26PM -0700, Stephen Boyd wrote:
> On 05/10, Abhishek Sahu wrote:
> > From: Charanya <charanya at codeaurora.org>
> 
> Was it intentional to only have one name here?
> 
> > 
> > The Data loss was happening with current QCOM MSM serial driver during
> > large file transfer due to simultaneous enabling of both UART and
> > DMA interrupt. When UART operates in DMA mode, RXLEV (Rx FIFO over
> > watermark) or RXSTALE (stale interrupts) should not be enabled,
> > since these conditions will be handled by DMA controller itself.
> > If these interrupts are enabled then normal UART ISR will read some
> > bytes of data from Rx Buffer and DMA controller will not receive
> > these bytes of data, which will cause data loss.
> > 
> > Now this patch removed the code for enabling of RXLEV and RXSTALE
> > interrupt in DMA Rx completion routine.
> 
> I'm lost, we keep both these irqs masked (well only if uartdm
> version is 1.4 or greater) pretty much the entire time we're
> using DMA for RX. msm_start_rx_dma() will mask them and then when
> the callback completes we'll unmask them (the part that's deleted
> in this patch), but then we'll go back and remask them almost
> immediately because we call msm_start_rx_dma() from the dma
> completion handler.
> 
> Can you clearly describe how this is actually fixing any
> problems? What's the sequence of events that happens to cause
> corruption?
> 
> This does raise the question though why we ever mask/unmask these
> interrupts if we're always going to keep them masked while doing
> DMA RX. Presumably if we can use DMA to RX, we can always use it
> and set things up properly at startup time instead of later on.

Thats probably the right thing to do.  We shouldn't be masking/unmasking
the unused IRQs to begin with.


From fthain at telegraphics.com.au  Wed May 11 22:06:00 2016
From: fthain at telegraphics.com.au (Finn Thain)
Date: Thu, 12 May 2016 15:06:00 +1000 (AEST)
Subject: [PATCH] drivers: nvmem: atmel-secumod: New driver for Atmel
 Secumod nvram.
In-Reply-To: <1462906936-31353-1-git-send-email-davidm@egauge.net>
References: <1453348655-31182-1-git-send-email-davidm@egauge.net>
 <1462906936-31353-1-git-send-email-davidm@egauge.net>
Message-ID: <alpine.LNX.2.00.1605121505320.21379@nippy.intranet>


On Tue, 10 May 2016, David Mosberger-Tang wrote:

> Signed-off-by: David Mosberger <davidm at egauge.net>
> ---
>  .../devicetree/bindings/nvmem/atmel-secumod.txt    |  46 ++++++++
>  arch/arm/boot/dts/sama5d2.dtsi                     |  20 ++++
>  drivers/nvmem/Kconfig                              |   7 ++
>  drivers/nvmem/Makefile                             |   2 +
>  drivers/nvmem/atmel-secumod.c                      | 122 +++++++++++++++++++++
>  5 files changed, 197 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
>  create mode 100644 drivers/nvmem/atmel-secumod.c
> 
> diff --git a/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
> new file mode 100644
> index 0000000..0bb7638
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
> @@ -0,0 +1,46 @@
> += Atmel Secumod device tree bindings =
> +
> +This binding is intended to represent Atmel's Secumod which is found
> +in SAMA5D2 and perhaps others.
> +
> +Required properties:
> +- compatible: should be "atmel,sama5d2-secumod"
> +- reg: Should contain registers location and length of the RAM, followed
> +       by register location and length of the Secumod controller.
> +
> += Data cells =
> +Are child nodes of secumod, bindings of which as described in
> +bindings/nvmem/nvmem.txt
> +
> +Example:
> +
> +    secumod at fc040000 {
> +            compatible = "atmel,sama5d2-secumod";
> +            reg = <0xf8044000 0x1420
> +                   0xfc040000 0x4000>;
> +            status = "okay";
> +
> +            #address-cells = <1>;
> +            #size-cells = <1>;
> +
> +            secram_auto_erasable at 0000 {
> +                    reg = <0x0000 0x1000>;
> +            };
> +            secram at 1000 {
> +                    reg = <0x1000 0x400>;
> +            };
> +            ram at 1400 {
> +                    reg = <0x1400 0x20>;
> +            };
> +    };
> +
> += Data consumers =
> +Are device nodes which consume nvmem data cells.
> +
> +For example:
> +
> +	ram {
> +		...
> +		nvmem-cells = <&ram>;
> +		nvmem-cell-names = "calibration";
> +	};
> diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
> index 78996bd..5856d6a 100644
> --- a/arch/arm/boot/dts/sama5d2.dtsi
> +++ b/arch/arm/boot/dts/sama5d2.dtsi
> @@ -1178,6 +1178,26 @@
>  				clocks = <&pioA_clk>;
>  			};
>  
> +			secumod at fc040000 {
> +				compatible = "atmel,sama5d2-secumod";
> +				reg = <0xf8044000 0x1420
> +				       0xfc040000 0x4000>;
> +				status = "okay";
> +
> +				#address-cells = <1>;
> +				#size-cells = <1>;
> +
> +				secram_auto_erasable at 0000 {
> +					reg = <0x0000 0x1000>;
> +				};
> +				secram at 1000 {
> +					reg = <0x1000 0x400>;
> +				};
> +				ram at 1400 {
> +					reg = <0x1400 0x20>;
> +				};
> +			};
> +
>  			tdes at fc044000 {
>  				compatible = "atmel,at91sam9g46-tdes";
>  				reg = <0xfc044000 0x100>;
> diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
> index ca52952..3d34fbb 100644
> --- a/drivers/nvmem/Kconfig
> +++ b/drivers/nvmem/Kconfig
> @@ -102,4 +102,11 @@ config NVMEM_VF610_OCOTP
>  	  This driver can also be build as a module. If so, the module will
>  	  be called nvmem-vf610-ocotp.
>  
> +config NVMEM_ATMEL_SECUMOD
> +       tristate "Atmel Secure Module driver"
> +       depends on ARCH_AT91
> +       help
> +         Select this to get support for the secure module (SECUMOD) built
> +	 into the SAMA5D2 chips.
> +
>  endif
> diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
> index 45ab1ae..9cbd950 100644
> --- a/drivers/nvmem/Makefile
> +++ b/drivers/nvmem/Makefile
> @@ -22,3 +22,5 @@ obj-$(CONFIG_NVMEM_SUNXI_SID)	+= nvmem_sunxi_sid.o
>  nvmem_sunxi_sid-y		:= sunxi_sid.o
>  obj-$(CONFIG_NVMEM_VF610_OCOTP)	+= nvmem-vf610-ocotp.o
>  nvmem-vf610-ocotp-y		:= vf610-ocotp.o
> +obj-$(CONFIG_NVMEM_ATMEL_SECUMOD)	+= nvmem-atmel-secumod.o
> +nvmem-atmel-secumod-y		:= atmel-secumod.o
> diff --git a/drivers/nvmem/atmel-secumod.c b/drivers/nvmem/atmel-secumod.c
> new file mode 100644
> index 0000000..a6b4574
> --- /dev/null
> +++ b/drivers/nvmem/atmel-secumod.c
> @@ -0,0 +1,122 @@
> +/*
> + * Driver for SAMA5D2 secure module (SECUMOD).
> + *
> + * Copyright (C) 2016 eGauge Systems LLC
> + *
> + * David Mosberger <davidm at egauge.net>
> + *
> + * 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/delay.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/nvmem-provider.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +static struct regmap_config secumod_regmap_config = {
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4
> +};
> +
> +static struct nvmem_config econfig = {
> +	.name = "secumod",
> +	.owner = THIS_MODULE,
> +};
> +
> +/*
> + * Security-module register definitions:
> + */
> +#define SECUMOD_RAMRDY	0x0014
> +
> +/*
> + * Since the secure module may need to automatically erase some of the
> + * RAM, it may take a while for it to be ready.  As far as I know,
> + * it's not documented how long this might take in the worst-case.
> + */
> +static void
> +secumod_wait_ready (void *regs)
> +{
> +	unsigned long start, stop;
> +
> +	start = jiffies;
> +	while (!(readl(regs + SECUMOD_RAMRDY) & 1))
> +		msleep_interruptible(1);
> +	stop = jiffies;
> +	if (stop != start)
> +		pr_info("nvmem-atmel-secumod: it took %u msec for SECUMOD "
> +			"to become ready...\n", jiffies_to_msecs(stop - start));
> +	else
> +		pr_info("nvmem-atmel-secumod: ready\n");
> +}
> +
> +static int secumod_remove(struct platform_device *pdev)
> +{
> +	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
> +
> +	return nvmem_unregister(nvmem);
> +}
> +
> +static int secumod_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct resource *res;
> +	struct nvmem_device *nvmem;
> +	struct regmap *regmap;
> +	void __iomem *base;
> +
> +	/*
> +	 * Map controller address temporarily so we can ensure that
> +	 * the hardware is ready:
> +	 */
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	base = devm_ioremap_resource(dev, res);

I would check IS_ERR(base) here...

> +	secumod_wait_ready(base);
> +	devm_iounmap(dev, base);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(dev, res);
> +
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);

...just like you did here.

When you send v2, you should address it to all of the relevant maintainers 
and mailing lists in order to get the necessary Acked-by tags. My tags 
aren't useful here. Please see,

$ scripts/get_maintainer.pl this.patch

-- 

> +
> +	secumod_regmap_config.max_register = resource_size(res) - 1;
> +
> +	regmap = devm_regmap_init_mmio(dev, base, &secumod_regmap_config);
> +	if (IS_ERR(regmap)) {
> +		dev_err(dev, "%s: regmap init failed\n", __func__);
> +		return PTR_ERR(regmap);
> +	}
> +	econfig.dev = dev;
> +	nvmem = nvmem_register(&econfig);
> +	if (IS_ERR(nvmem))
> +		return PTR_ERR(nvmem);
> +
> +	platform_set_drvdata(pdev, nvmem);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id secumod_of_match[] = {
> +	{ .compatible = "atmel,sama5d2-secumod",},
> +	{/* sentinel */},
> +};
> +MODULE_DEVICE_TABLE(of, secumod_of_match);
> +
> +static struct platform_driver secumod_driver = {
> +	.probe = secumod_probe,
> +	.remove = secumod_remove,
> +	.driver = {
> +		.name = "atmel,sama5d2-secumod",
> +		.of_match_table = secumod_of_match,
> +	},
> +};
> +module_platform_driver(secumod_driver);
> +MODULE_AUTHOR("David Mosberger <davidm at egauge.net>");
> +MODULE_DESCRIPTION("Atmel Secumod driver");
> +MODULE_LICENSE("GPL v2");
> 


From andy.gross at linaro.org  Wed May 11 22:13:47 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 00:13:47 -0500
Subject: [PATCH 1/2] i2c: qup: Cleared the error bits in ISR
In-Reply-To: <934365f2bd30f242d8548e2a27483679@codeaurora.org>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
 <1462797871-8595-2-git-send-email-absahu@codeaurora.org>
 <000701d1ab9d$df9b3100$9ed19300$@codeaurora.org>
 <934365f2bd30f242d8548e2a27483679@codeaurora.org>
Message-ID: <20160512051347.GE8453@hector.attlocal.net>

On Wed, May 11, 2016 at 11:04:17PM +0530, Abhishek Sahu wrote:

<snip>

> >       In qup_i2c_xfer and qup_i2c_xfer_v2 state is set to RESET at the
> >end, when
> >       there is no error. So would it be fine if we do it there
> >unconditionally ?
> >
> >Regards,
> > Sricharan
> 
> RESET the QUP state wouldn't create any issue in the case of multiple calls.
> The existing code also RESET the QUP state for bus_err but it is not
> clearing
> status bits.

It'd be better to not reset the QUP inside the ISR at all.  I think the better
solution is making the reset occur in the xfer function.  So just clear the bits
like you should in the isr, and defer reset till later.


From vinod.koul at intel.com  Wed May 11 22:40:20 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Thu, 12 May 2016 11:10:20 +0530
Subject: [PATCH 04/18] dmaengine: st_fdma: Add xp70 firmware loading
 mechanism.
In-Reply-To: <20160511075740.GB25540@griffinp-ThinkPad-X1-Carbon-2nd>
References: <1461236675-10176-1-git-send-email-peter.griffin@linaro.org>
 <1461236675-10176-5-git-send-email-peter.griffin@linaro.org>
 <20160426170048.GS2274@localhost>
 <20160511075740.GB25540@griffinp-ThinkPad-X1-Carbon-2nd>
Message-ID: <20160512054020.GW2274@localhost>

On Wed, May 11, 2016 at 08:57:40AM +0100, Peter Griffin wrote:
> > Above two seem to be generic code and should be moved to core, this way
> > other drivers using ELF firmware binaries can reuse...
> 
> Do you mean add to dmaengine.c?

Nope this is not specfic to dmaengine. Perhaps drivers/base/..

> Certainly st_fdma_elf_sanity_check is fairly generic. st_fdma_elf_load_segments
> is less so, especially st_fdma_seg_to_mem().
> 
> > 
> > > @@ -738,6 +925,15 @@ static int st_fdma_slave_config(struct dma_chan *chan,
> > >  				struct dma_slave_config *slave_cfg)
> > >  {
> > >  	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
> > > +	int ret;
> > > +
> > > +	if (!atomic_read(&fchan->fdev->fw_loaded)) {
> > > +		ret = st_fdma_get_fw(fchan->fdev);
> > 
> > this seems quite an odd place to load firmware, can you explain why
> > 
> 
> Good question :) I've been round the houses a bit on the firmware loading.
> 
> I will try and document here what I've tried and the different advantages /
> disadvantages I've encountered.

Per Linus, driver should load firmware on first open. So either you should
do it while channel allocation or first descriptor allocation.

> 
> In V3 patches, I used the device_config() hook. This can sleep (I think..it isn't
> documented here [1]). This hook happens very close to the dma starting and the
> rootfs / firmware is likely to be present. However I've sinced learnt that it
> doesn't get  called in the memcpy case so is not a sufficient solution.
> 
> In part putting it here was to try and get firmware loading out of probe() based
> on your feedback to v1 [2].
> 
> In V1 patches: - I was using request_firmware_nowait() in probe() in conjunction with
> the CONFIG_FW_LOADER_USER_HELPER kernel option. I've since also learnt that this
> kernel option is deprecated and shouldn't be used.

I think nowait version is better. Why do you need
CONFIG_FW_LOADER_USER_HELPER?

> Your feedback in v1 was to move firmware loading to device open [2]. However
> what classes is  device open in the dmaengine context is not obvious.

channel allocation or descriptor allocation

> 
> ===
> 
> device_alloc_chan_resources() hook
> 
> This is probably the hook closest to a device open in dmaengine context.
> This hook can sleep so request_firmware can be called. However if all drivers
> are built-in firmware loading still fails as ALSA drivers calls
> devm_snd_dmaengine_pcm_register() which requests dma channels during *its* probe().
> This happens way before the rootfs is present and thus firmware loading still
> fails, and is still being done indirectly from a probe() anyway.
> 
> I had some discussion with Mark and Arnd on IRC, about the possibility of ALSA
> not rquesting DMA channels during their probe(). Marks opinion I believe was
> this wasn't a good solution as ALSA would be presenting devices to userspace 
> that potentially don't exist & can't work.

Hmmm, there are two parts, one is requesting the firmware and second is the
loading part.

Since descriptor allocation is atomic in nature, I think we should load the
firmware using nowait version and if you can atomically copy then do so at
first descriptor allocation. If not then you should copy in nowait handler

> ===
> 
> *_prep_*() hooks
> 
> + Always get called before a DMA is started
> 
> - *prep* hooks can be called from atomic context so can't sleep [1] and can't use
>   request_firmware().
> - I tried using request_firmwqare_nowait() with GFP_ATOMIC flag firmware. This
>   half works but firmware loading doesn't complete before the DMA is started which
>   means it often fails on the first DMA attempt.
> 
>  ===
> 
> Suggested solution for v4 patches: -
> 
> Both Arnd, Mark and Lee initial suggestion on irc was that if the device is useless
> without firmware, and the firmware isn't available then the driver should call
> request_firmware() in probe() and -EPROBE_DEFER if not available.
> 
> This solution works well, in both the built-in and modules case. As the deffered
> fdma driver re-probes after the rootfs has been mounted when the firmware is
> available. The other ALSA depedencies then also re-probe and everything works
> nicely (and you can be assured that the devices will actually work at this point).
> 
> This fdma driver and the ALSA ones will be enabled in multi_v7_defconfig as modules,
> so it is only likely to be used as a module. However using -EPROBE_DEFER
> mechanism, has the nice quality that if it is compiled as built-in you still end
> up with a working system (albeit with a longer boot time).

I think that makes sense, relying on deferred probing seems a better way to
manage

> 
> Failing that the only other solution I can see is extending the dmaengine API to
> provide another hook which can sleep, and must be called before a DMA
> transation is started. Note that firmware isn't actually *required* until we
> start the dma transaction, but the device is useless without this firmware. In fact
> its "registers" are really just offsets into its DMEM so in theory even the
> registers are totally firmware dependent.
> 
> Also I notice the only other dmaengine driver imx-sdma.c using firmware calls
> request_firmware_nowait from its probe().
> 
> Are you happy with my proposed solutiion for v4? If not how would you like me to
> implement this?
> 
> regards,
> 
> Peter.
> 
> [1] https://www.kernel.org/doc/Documentation/dmaengine/provider.txt
> 
> [2] https://lkml.org/lkml/2015/10/13/278
> --
> To unsubscribe from this list: send the line "unsubscribe dmaengine" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
~Vinod


From Wenyou.Yang at atmel.com  Wed May 11 22:50:18 2016
From: Wenyou.Yang at atmel.com (Yang, Wenyou)
Date: Thu, 12 May 2016 05:50:18 +0000
Subject: [PATCH] usb: ohci-at91: Suspend the ports while USB suspending
In-Reply-To: <20160512035315.GA19408@piout.net>
References: <1463015134-32364-1-git-send-email-wenyou.yang@atmel.com>
 <20160512035315.GA19408@piout.net>
Message-ID: <B256D81BAE5131468A838E5D7A2436410164FB80B8@penmbx01>



> -----Original Message-----
> From: Alexandre Belloni [mailto:alexandre.belloni at free-electrons.com]
> Sent: 2016?5?12? 11:53
> To: Yang, Wenyou <Wenyou.Yang at atmel.com>
> Cc: Alan Stern <stern at rowland.harvard.edu>; Greg Kroah-Hartman
> <gregkh at linuxfoundation.org>; Ferre, Nicolas <Nicolas.FERRE at atmel.com>;
> linux-usb at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org
> Subject: Re: [PATCH] usb: ohci-at91: Suspend the ports while USB suspending
> 
> Hi,
> 
> On 12/05/2016 at 09:05:34 +0800, Wenyou Yang wrote :
> > In order to get lower consumption, as a workaround, suspend the USB
> > PORTA/B/C via set the SUSPEND_A/B/C bits of OHCI Interrupt
> > Configuration Register while OHCI USB suspending.
> >
> 
> Why is that a workaround?

Because if these bits is not set as this patch, there is 5mA current left
at VDDOSC rail during suspend. If apply this patch, this current will disappear.

So, I think it is a workaround.

> 
> > This suspend operation must be done before stopping the USB clock,
> > resume after the USB clock enabled.
> >
> > Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> > ---
> >
> >  drivers/usb/host/ohci-at91.c | 63
> > ++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 63 insertions(+)
> >
> > diff --git a/drivers/usb/host/ohci-at91.c
> > b/drivers/usb/host/ohci-at91.c index d177372..ce898e0 100644
> > --- a/drivers/usb/host/ohci-at91.c
> > +++ b/drivers/usb/host/ohci-at91.c
> > @@ -21,6 +21,8 @@
> >  #include <linux/io.h>
> >  #include <linux/kernel.h>
> >  #include <linux/module.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/regmap.h>
> >  #include <linux/usb.h>
> >  #include <linux/usb/hcd.h>
> >
> > @@ -51,6 +53,7 @@ struct ohci_at91_priv {
> >  	struct clk *hclk;
> >  	bool clocked;
> >  	bool wakeup;		/* Saved wake-up state for resume */
> > +	struct regmap *sfr_regmap;
> >  };
> >  /* interface and function clocks; sometimes also an AHB clock */
> >
> > @@ -132,6 +135,17 @@ static void at91_stop_hc(struct platform_device
> > *pdev)
> >
> >
> > /*--------------------------------------------------------------------
> > -----*/
> >
> > +struct regmap *at91_dt_syscon_sfr(void) {
> > +	struct regmap *regmap;
> > +
> > +	regmap = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
> > +	if (IS_ERR(regmap))
> > +		return NULL;
> > +
> > +	return regmap;
> > +}
> > +
> >  static void usb_hcd_at91_remove (struct usb_hcd *, struct
> > platform_device *);
> >
> >  /* configure so an HC device and id are always provided */ @@ -197,6
> > +211,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
> >  		goto err;
> >  	}
> >
> > +	ohci_at91->sfr_regmap = at91_dt_syscon_sfr();
> > +
> >  	board = hcd->self.controller->platform_data;
> >  	ohci = hcd_to_ohci(hcd);
> >  	ohci->num_ports = board->ports;
> > @@ -581,6 +597,49 @@ static int ohci_hcd_at91_drv_remove(struct
> platform_device *pdev)
> >  	return 0;
> >  }
> >
> > +#define SFR_OHCIICR		0x10
> > +#define SFR_OHCIICR_SUSPEND_A	BIT(8)
> > +#define SFR_OHCIICR_SUSPEND_B	BIT(9)
> > +#define SFR_OHCIICR_SUSPEND_C	BIT(10)
> > +
> > +#define SFR_OHCIICR_USB_SUSPEND	(SFR_OHCIICR_SUSPEND_A | \
> > +				 SFR_OHCIICR_SUSPEND_B | \
> > +				 SFR_OHCIICR_SUSPEND_C)
> > +
> 
> Those defines should go in a header file either in include/soc/at91 or in
> include/linux/mfd
> 
> > +static int ohci_at91_port_ctrl(struct regmap *regmap, bool enable) {
> > +	u32 regval;
> > +	int ret;
> > +
> > +	if (IS_ERR(regmap))
> > +		return PTR_ERR(regmap);
> > +
> > +	ret = regmap_read(regmap, SFR_OHCIICR, &regval);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (enable)
> > +		regval &= ~SFR_OHCIICR_USB_SUSPEND;
> > +	else
> > +		regval |= SFR_OHCIICR_USB_SUSPEND;
> > +
> > +	regmap_write(regmap, SFR_OHCIICR, regval);
> > +
> > +	regmap_read(regmap, SFR_OHCIICR, &regval);
> > +
> > +	return 0;
> > +}
> > +
> > +static int ohci_at91_port_suspend(struct regmap *regmap) {
> > +	return ohci_at91_port_ctrl(regmap, false); }
> > +
> > +static int ohci_at91_port_resume(struct regmap *regmap) {
> > +	return ohci_at91_port_ctrl(regmap, true); }
> > +
> >  static int __maybe_unused
> >  ohci_hcd_at91_drv_suspend(struct device *dev)  { @@ -618,6 +677,8 @@
> > ohci_hcd_at91_drv_suspend(struct device *dev)
> >  		ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
> >  		ohci->rh_state = OHCI_RH_HALTED;
> >
> > +		ohci_at91_port_suspend(ohci_at91->sfr_regmap);
> > +
> 
> The main issue I see here is that you will call that function for all SoCs and it will
> always fail unless it is running on a sama5d2. Maybe we could be smarter about
> that.

Can we use another compatible, such as "atmel,sama5d2-ohci" to differentiate it? 


Best Regards,
Wenyou Yang

From wangkefeng.wang at huawei.com  Wed May 11 23:16:46 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 14:16:46 +0800
Subject: [PATCH 1/2] arm64: dts: NS2: Add all of the UARTs
In-Reply-To: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
References: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
Message-ID: <57341FCE.6050403@huawei.com>



On 2016/5/12 6:56, Jon Mason wrote:
> Add all of the UARTs present on NS2 and enable them in the SVK device
> tree file.  Also, do some magic to make sure that uart3 is discovered as
> ttyS0 (as that is the console UART).
> 
> Signed-off-by: Jon Mason <jonmason at broadcom.com>
> ---
>  arch/arm64/boot/dts/broadcom/ns2-svk.dts | 16 ++++++++++++++++
>  arch/arm64/boot/dts/broadcom/ns2.dtsi    | 30 ++++++++++++++++++++++++++++++
>  2 files changed, 46 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
> index 7cd3640..b062a44 100644
> --- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts
> +++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
> @@ -40,10 +40,14 @@
>  
>  	aliases {
>  		serial0 = &uart3;
> +		serial1 = &uart0;
> +		serial2 = &uart1;
> +		serial3 = &uart2;
>  	};
>  
>  	chosen {
>  		stdout-path = "serial0:115200n8";
> +		bootargs = "earlycon=uart8250,mmio32,0x66130000";

Hi Jon,

I submit a patch[1], with it, we can use earlycon without option to enable early console
for "snps,dw-apb-uart", could you help me to test it, thanks.

BRs,
Kefeng


[1] https://lkml.org/lkml/2016/5/11/34

>  	};
>  
>  	memory {
> @@ -68,6 +72,18 @@
>  	status = "ok";
>  };
>  
> +&uart0 {
> +	status = "ok";
> +};
> +
> +&uart1 {
> +	status = "ok";
> +};
> +
> +&uart2 {
> +	status = "ok";
> +};
> +
>  &uart3 {
>  	status = "ok";
>  };
> diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi
> index 788ed8f..c77a9e8 100644
> --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
> +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
> @@ -357,6 +357,36 @@
>  			status = "disabled";
>  		};
>  
> +		uart0: serial at 66100000 {
> +			compatible = "snps,dw-apb-uart";
> +			reg = <0x66100000 0x100>;
> +			interrupts = <GIC_SPI 390 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&iprocslow>;
> +			reg-shift = <2>;
> +			reg-io-width = <4>;
> +			status = "disabled";
> +		};
> +
> +		uart1: serial at 66110000 {
> +			compatible = "snps,dw-apb-uart";
> +			reg = <0x66110000 0x100>;
> +			interrupts = <GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&iprocslow>;
> +			reg-shift = <2>;
> +			reg-io-width = <4>;
> +			status = "disabled";
> +		};
> +
> +		uart2: serial at 66120000 {
> +			compatible = "snps,dw-apb-uart";
> +			reg = <0x66120000 0x100>;
> +			interrupts = <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&iprocslow>;
> +			reg-shift = <2>;
> +			reg-io-width = <4>;
> +			status = "disabled";
> +		};
> +
>  		uart3: serial at 66130000 {
>  			compatible = "snps,dw-apb-uart";
>  			reg = <0x66130000 0x100>;
> 



From absahu at codeaurora.org  Wed May 11 23:18:43 2016
From: absahu at codeaurora.org (Abhishek Sahu)
Date: Thu, 12 May 2016 11:48:43 +0530
Subject: [PATCH 1/2] i2c: qup: Cleared the error bits in ISR
In-Reply-To: <20160512051347.GE8453@hector.attlocal.net>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
 <1462797871-8595-2-git-send-email-absahu@codeaurora.org>
 <000701d1ab9d$df9b3100$9ed19300$@codeaurora.org>
 <934365f2bd30f242d8548e2a27483679@codeaurora.org>
 <20160512051347.GE8453@hector.attlocal.net>
Message-ID: <20160512061843.GA6187@chewinlnx07.qualcomm.com>

On Thu, May 12, 2016 at 12:13:47AM -0500, Andy Gross wrote:
> On Wed, May 11, 2016 at 11:04:17PM +0530, Abhishek Sahu wrote:
> 
> <snip>
> 
> > >       In qup_i2c_xfer and qup_i2c_xfer_v2 state is set to RESET at the
> > >end, when
> > >       there is no error. So would it be fine if we do it there
> > >unconditionally ?
> > >
> > >Regards,
> > > Sricharan
> > 
> > RESET the QUP state wouldn't create any issue in the case of multiple calls.
> > The existing code also RESET the QUP state for bus_err but it is not
> > clearing
> > status bits.
> 
> It'd be better to not reset the QUP inside the ISR at all.  I think the better
> solution is making the reset occur in the xfer function.  So just clear the bits
> like you should in the isr, and defer reset till later.

This is a HW workaround for QUP where we need to RESET the core in
ISR. When interrupt is level triggerd, more than one interrupt may
fire in error cases and QUP will generate these interrupts after
completion of current interrupt. Thus we reset the core immediately
in the ISR to ward off the next interrupt.

-- 
Abhishek Sahu


From vinod.koul at intel.com  Wed May 11 23:29:58 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Thu, 12 May 2016 11:59:58 +0530
Subject: [PATCH v4 0/5] dmaengine: vdma: AXI DMA's enhancments
In-Reply-To: <1460006985-14805-1-git-send-email-appanad@xilinx.com>
References: <1460006985-14805-1-git-send-email-appanad@xilinx.com>
Message-ID: <20160512062957.GA2274@localhost>

On Thu, Apr 07, 2016 at 10:59:40AM +0530, Kedareswara rao Appana wrote:
> This patch series does some enhancments to the VDMA driver
> which includes
> --> Adding support for AXI DMA IP.
> --> Adding support for AXI CDMA IP.

Applied all, thanks

> 
> Kedareswara rao Appana (5):
>   dmaengine: vdma: Rename xilinx_vdma_ prefix to xilinx_dma
>   Documentation: DT: vdma: update binding doc for AXI DMA
>   dmaengine: vdma: Add Support for Xilinx AXI Direct Memory Access
>     Engine
>   Documentation: DT: vdma: update binding doc for AXI CDMA
>   dmaengine: vdma: Add Support for Xilinx AXI Central Direct Memory
>     Access Engine
> 
>  .../devicetree/bindings/dma/xilinx/xilinx_vdma.txt |   17 +-
>  drivers/dma/xilinx/xilinx_vdma.c                   | 1326 ++++++++++++++------
>  include/linux/dma/xilinx_dma.h                     |   14 +
>  3 files changed, 1003 insertions(+), 354 deletions(-)
> 
> -- 
> 2.1.2
> 

-- 
~Vinod


From bhe at redhat.com  Wed May 11 23:26:27 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 12 May 2016 14:26:27 +0800
Subject: [PATCH 11/12] kexec: allow architectures to override boot mapping
In-Reply-To: <E1aviFU-0000jk-9q@rmk-PC.arm.linux.org.uk>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <E1aviFU-0000jk-9q@rmk-PC.arm.linux.org.uk>
Message-ID: <20160512062627.GB2711@x1.redhat.com>

On 04/28/16 at 10:28am, Russell King wrote:
> diff --git a/include/linux/kexec.h b/include/linux/kexec.h
> index 52a3a221bcb2..99cb9dac7909 100644
> --- a/include/linux/kexec.h
> +++ b/include/linux/kexec.h
> @@ -318,6 +318,44 @@ int __weak arch_kexec_apply_relocations_add(const Elf_Ehdr *ehdr,
>  int __weak arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
>  					unsigned int relsec);
>  
> +#ifndef page_to_boot_pfn
> +static inline unsigned long page_to_boot_pfn(struct page *page)
> +{
> +	return page_to_pfn(page);
> +}
> +#endif

I am thinking if it's appropriate to introduce a new concept which only
exists in a certain system of a certain ARCH. Is it unavoidable? If have
to can we name it as kexec_page_to_pfn/kexec_pfn_to_page, etc? People
might not need to know about boot view physical address and kernel view
physical address things when they just want to understand kexec
implementation related to one ARCH except of ARM, even related to ARM
but not Keystone 2.

> +
> +#ifndef boot_pfn_to_page
> +static inline struct page *boot_pfn_to_page(unsigned long boot_pfn)
> +{
> +	return pfn_to_page(boot_pfn);
> +}
> +#endif
> +
> +#ifndef phys_to_boot_phys
> +static inline unsigned long phys_to_boot_phys(phys_addr_t phys)
> +{
> +	return phys;
> +}
> +#endif
> +
> +#ifndef boot_phys_to_phys
> +static inline phys_addr_t boot_phys_to_phys(unsigned long boot_phys)
> +{
> +	return boot_phys;
> +}
> +#endif
> +
> +static inline unsigned long virt_to_boot_phys(void *addr)
> +{
> +	return phys_to_boot_phys(__pa((unsigned long)addr));
> +}
> +
> +static inline void *boot_phys_to_virt(unsigned long entry)
> +{
> +	return phys_to_virt(boot_phys_to_phys(entry));
> +}
> +
>  #else /* !CONFIG_KEXEC_CORE */
>  struct pt_regs;
>  struct task_struct;
> diff --git a/kernel/kexec.c b/kernel/kexec.c
> index ee70aef5cd81..dd49d572a5e2 100644
> --- a/kernel/kexec.c
> +++ b/kernel/kexec.c
> @@ -48,7 +48,8 @@ static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
>  
>  	if (kexec_on_panic) {
>  		/* Verify we have a valid entry point */
> -		if ((entry < crashk_res.start) || (entry > crashk_res.end))
> +		if ((entry < phys_to_boot_phys(crashk_res.start)) ||
> +		    (entry > phys_to_boot_phys(crashk_res.end)))
>  			return -EADDRNOTAVAIL;
>  	}
>  
> diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
> index f9847e5822e6..d04940ccc58d 100644
> --- a/kernel/kexec_core.c
> +++ b/kernel/kexec_core.c
> @@ -229,8 +229,8 @@ int sanity_check_segment_list(struct kimage *image)
>  			mstart = image->segment[i].mem;
>  			mend = mstart + image->segment[i].memsz - 1;
>  			/* Ensure we are within the crash kernel limits */
> -			if ((mstart < crashk_res.start) ||
> -			    (mend > crashk_res.end))
> +			if ((mstart < phys_to_boot_phys(crashk_res.start)) ||
> +			    (mend > phys_to_boot_phys(crashk_res.end)))
>  				return result;
>  		}
>  	}
> @@ -354,7 +354,7 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image,
>  		pages = kimage_alloc_pages(KEXEC_CONTROL_MEMORY_GFP, order);
>  		if (!pages)
>  			break;
> -		pfn   = page_to_pfn(pages);
> +		pfn   = page_to_boot_pfn(pages);
>  		epfn  = pfn + count;
>  		addr  = pfn << PAGE_SHIFT;
>  		eaddr = epfn << PAGE_SHIFT;
> @@ -480,7 +480,7 @@ static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
>  			return -ENOMEM;
>  
>  		ind_page = page_address(page);
> -		*image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
> +		*image->entry = virt_to_boot_phys(ind_page) | IND_INDIRECTION;
>  		image->entry = ind_page;
>  		image->last_entry = ind_page +
>  				      ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
> @@ -535,13 +535,13 @@ void kimage_terminate(struct kimage *image)
>  #define for_each_kimage_entry(image, ptr, entry) \
>  	for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
>  		ptr = (entry & IND_INDIRECTION) ? \
> -			phys_to_virt((entry & PAGE_MASK)) : ptr + 1)
> +			boot_phys_to_virt((entry & PAGE_MASK)) : ptr + 1)
>  
>  static void kimage_free_entry(kimage_entry_t entry)
>  {
>  	struct page *page;
>  
> -	page = pfn_to_page(entry >> PAGE_SHIFT);
> +	page = boot_pfn_to_page(entry >> PAGE_SHIFT);
>  	kimage_free_pages(page);
>  }
>  
> @@ -635,7 +635,7 @@ static struct page *kimage_alloc_page(struct kimage *image,
>  	 * have a match.
>  	 */
>  	list_for_each_entry(page, &image->dest_pages, lru) {
> -		addr = page_to_pfn(page) << PAGE_SHIFT;
> +		addr = page_to_boot_pfn(page) << PAGE_SHIFT;
>  		if (addr == destination) {
>  			list_del(&page->lru);
>  			return page;
> @@ -650,12 +650,12 @@ static struct page *kimage_alloc_page(struct kimage *image,
>  		if (!page)
>  			return NULL;
>  		/* If the page cannot be used file it away */
> -		if (page_to_pfn(page) >
> +		if (page_to_boot_pfn(page) >
>  				(KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
>  			list_add(&page->lru, &image->unusable_pages);
>  			continue;
>  		}
> -		addr = page_to_pfn(page) << PAGE_SHIFT;
> +		addr = page_to_boot_pfn(page) << PAGE_SHIFT;
>  
>  		/* If it is the destination page we want use it */
>  		if (addr == destination)
> @@ -678,7 +678,7 @@ static struct page *kimage_alloc_page(struct kimage *image,
>  			struct page *old_page;
>  
>  			old_addr = *old & PAGE_MASK;
> -			old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
> +			old_page = boot_pfn_to_page(old_addr >> PAGE_SHIFT);
>  			copy_highpage(page, old_page);
>  			*old = addr | (*old & ~PAGE_MASK);
>  
> @@ -734,7 +734,7 @@ static int kimage_load_normal_segment(struct kimage *image,
>  			result  = -ENOMEM;
>  			goto out;
>  		}
> -		result = kimage_add_page(image, page_to_pfn(page)
> +		result = kimage_add_page(image, page_to_boot_pfn(page)
>  								<< PAGE_SHIFT);
>  		if (result < 0)
>  			goto out;
> @@ -795,7 +795,7 @@ static int kimage_load_crash_segment(struct kimage *image,
>  		char *ptr;
>  		size_t uchunk, mchunk;
>  
> -		page = pfn_to_page(maddr >> PAGE_SHIFT);
> +		page = boot_pfn_to_page(maddr >> PAGE_SHIFT);
>  		if (!page) {
>  			result  = -ENOMEM;
>  			goto out;
> @@ -922,7 +922,7 @@ void __weak crash_free_reserved_phys_range(unsigned long begin,
>  	unsigned long addr;
>  
>  	for (addr = begin; addr < end; addr += PAGE_SIZE)
> -		free_reserved_page(pfn_to_page(addr >> PAGE_SHIFT));
> +		free_reserved_page(boot_pfn_to_page(addr >> PAGE_SHIFT));
>  }
>  
>  int crash_shrink_memory(unsigned long new_size)
> -- 
> 2.1.0
> 
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


From joel at jms.id.au  Wed May 11 23:34:24 2016
From: joel at jms.id.au (Joel Stanley)
Date: Thu, 12 May 2016 16:04:24 +0930
Subject: [PATCH] ARM: aspeed: adapt defconfigs for new CONFIG_PRINTK_TIME
In-Reply-To: <1462969128-4070058-1-git-send-email-arnd@arndb.de>
References: <1462969128-4070058-1-git-send-email-arnd@arndb.de>
Message-ID: <CACPK8XeUTSF=c2jdmkQiQn2kfnVxvD00Cq_rj=COP7yL1-P-+A@mail.gmail.com>

On Wed, May 11, 2016 at 9:48 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> Commit 94ea9c7a579f ("lib, switch CONFIG_PRINTK_TIME to int") changes
> the type of CONFIG_PRINTK_TIME and adapts all existing defconfig files,
> while we add two new defconfig files with d0bc3483da87 ("arm/configs:
> Add Aspeed defconfig"), with the old type.
>
> This changes the two new defconfig files to match the other ones.
> As a result, we get harmless warnings for the arm-soc defconfig
> branch by itself, but everything will work when 4.7-rc1 is out.
>
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> ---
> I've applied this one to avoid introducing warnings in linux-next.
> I could have sorted out the ordering as well to avoid warnings
> in arm-soc/for-next, but it doesn't seem worth it as we are not
> regressing here.

Thanks Arnd.

Acked-by: Joel Stanley <joel at jms.id.au>

>
>  arch/arm/configs/aspeed_g4_defconfig | 2 +-
>  arch/arm/configs/aspeed_g5_defconfig | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig
> index ca39c04fec6b..b6e54ee9bdbd 100644
> --- a/arch/arm/configs/aspeed_g4_defconfig
> +++ b/arch/arm/configs/aspeed_g4_defconfig
> @@ -58,7 +58,7 @@ CONFIG_SERIAL_OF_PLATFORM=y
>  # CONFIG_IOMMU_SUPPORT is not set
>  CONFIG_FIRMWARE_MEMMAP=y
>  CONFIG_FANOTIFY=y
> -CONFIG_PRINTK_TIME=y
> +CONFIG_PRINTK_TIME=1
>  CONFIG_DYNAMIC_DEBUG=y
>  CONFIG_STRIP_ASM_SYMS=y
>  CONFIG_PAGE_POISONING=y
> diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig
> index 4f366b0370e9..892605167357 100644
> --- a/arch/arm/configs/aspeed_g5_defconfig
> +++ b/arch/arm/configs/aspeed_g5_defconfig
> @@ -59,7 +59,7 @@ CONFIG_SERIAL_OF_PLATFORM=y
>  # CONFIG_IOMMU_SUPPORT is not set
>  CONFIG_FIRMWARE_MEMMAP=y
>  CONFIG_FANOTIFY=y
> -CONFIG_PRINTK_TIME=y
> +CONFIG_PRINTK_TIME=1
>  CONFIG_DYNAMIC_DEBUG=y
>  CONFIG_STRIP_ASM_SYMS=y
>  CONFIG_PAGE_POISONING=y
> --
> 2.7.0
>


From richard.genoud at gmail.com  Wed May 11 23:41:55 2016
From: richard.genoud at gmail.com (Richard Genoud)
Date: Thu, 12 May 2016 08:41:55 +0200
Subject: [BISECTED] Regression v4.6-rc1 : nanosleep doesn't return on
 AT91SAM9
In-Reply-To: <5731FBE1.2090202@atmel.com>
References: <CACQ1gAg6cKqjaqcV70m2VS5R4_kZEgWTiqzSqDxSjvfrYYxbzg@mail.gmail.com>
 <CACQ1gAipruXcO=xpooYDOdqZbtESD35wxDf7xNrg4zuuRv1wew@mail.gmail.com>
 <20160510164712.56261bb4@bbrezillon>
 <CACQ1gAj4xD1httj=gMKFCfeOnVjSKk+J-y_yZpCkTSiLeTAA4A@mail.gmail.com>
 <5731FBE1.2090202@atmel.com>
Message-ID: <CACQ1gAgZyFF08uFEEzBT3_W156foNXXDh3RudO+7tuKbzPD-XA@mail.gmail.com>

2016-05-10 17:18 GMT+02:00 Nicolas Ferre <nicolas.ferre at atmel.com>:
> Le 10/05/2016 16:59, Richard Genoud a ?crit :
>> 2016-05-10 16:47 GMT+02:00 Boris Brezillon <boris.brezillon at free-electrons.com>:
>>> Hi Richard,
>>>
>>> On Tue, 10 May 2016 16:25:25 +0200
>>> Richard Genoud <richard.genoud at gmail.com> wrote:
>>>
>>>> 2016-05-10 15:58 GMT+02:00 Richard Genoud <richard.genoud at gmail.com>:
>>>>> Hi,
>>>>>
>>>>> Starting with 4.6-rc1, a sleep 1 doesn't return :
>>>>>
>>>>> execve("/bin/sleep", ["sleep", "1"], ["USER=root", "SHLVL=1",
>>>>> "OLDPWD=/var", "HOME=/", "TERM=vt102",
>>>>> "PATH=/sbin:/usr/sbin:/bin:/usr/bin", "SHELL=/bin/sh", "PWD=/"]) = 0
>>>>> uname({sysname="Linux", nodename="LNS",
>>>>> release="4.5.0-09406-g46e595a17dcf", version="#72 Tue May 10 15:41:34
>>>>> CEST 2016", machine="armv5tejl", domainname="(none)"}) = 0
>>>>> brk(0)                                  = 0x153000
>>>>> brk(0x153d20)                           = 0x153d20
>>>>> set_tls(0x1534c0, 0x14d1e4, 0, 0x153d20, 0x14e368) = 0
>>>>> readlink("/proc/self/exe", "/bin/busybox", 4096) = 12
>>>>> brk(0x174d20)                           = 0x174d20
>>>>> brk(0x175000)                           = 0x175000
>>>>> getuid32()                              = 0
>>>>> rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
>>>>> rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
>>>>> rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
>>>>> nanosleep({1, 0},
>>>>>
>>>>> And the heartbeat led doesn't blink anymore (full on), as if the
>>>>> timers never fire.
>>>>>
>>>>> The platform is an AT91SAM9G35-CM.
>>>>>
>>>>> git bisect gives a merge as the 1st bad commit :(
>>>>> first bad commit: [46e595a17dcf11404f713845ecb5b06b92a94e43] Merge tag
>>>>> 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>>
>>>>
>>>> I went a little further in tracking that down, starting from the merge
>>>> (1st bad commit) and reverting some commits.
>>>> It seems that the culprit is :
>>>> commit 863a81c3be1d931bdae6426e231add9334311f13
>>>> Author: Boris Brezillon <boris.brezillon at free-electrons.com>
>>>> Date:   Fri Sep 5 09:54:13 2014 +0200
>>>>     clk: at91: make use of syscon to share PMC registers in several drivers
>>>>
>>>> Here are the commits I've reverted :
>>>>
>>>> git log --oneline --decorate -20
>>>> 849cdaa0cf04 (HEAD, tag: good) Revert "clk: at91: make use of syscon
>>>> to share PMC registers in several drivers"
>>>> 4bd6dde95321 (tag: last_bad) Revert "clk: at91: make use of
>>>> syscon/regmap internally"
>>>> a56dacaa24c4 (tag: always_bad) Revert "clk: at91: remove IRQ handling
>>>> and use polling"
>>>> 33edfe7a2de6 Revert "clk: at91: pmc: merge at91_pmc_init in atmel_pmc_probe"
>>>> 0b22bb649eae Revert "clk: at91: pmc: move pmc structures to C file"
>>>> 14994fdff366 Revert "ARM: at91: pm: simply call at91_pm_init"
>>>> 6f0821175327 (tag: still_bad) Revert "ARM: at91: pm: find and remap the pmc"
>>>> b52bbf7fad1b Revert "ARM: at91: pm: move idle functions to pm.c"
>>>> dffb1a5f68b9 Revert "ARM: at91: remove useless includes and function prototypes"
>>>> db352691dcc1 Revert "usb: gadget: atmel: access the PMC using regmap"
>>>> f7b5433dbbc8 Revert "clk: at91: pmc: drop at91_pmc_base"
>>>> 6e6dfc0d91c0 Revert "clk: at91: pmc: remove useless capacities handling"
>>>> ceddd3f88ada Revert "clk: at91: remove useless includes"
>>>> 46e595a17dcf (tag: bad) Merge tag 'armsoc-drivers' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>> e3b1f64e04f5 Merge tag 'armsoc-defconfig' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>> 915c56bc01d6 Merge tag 'armsoc-dt64' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>> 5a6b7e53d035 Merge tag 'armsoc-dt' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>> 8c6d4082fc6a Merge tag 'armsoc-arm64' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>> 33b3d2e88c9e Merge tag 'armsoc-soc' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>> e88fa1b8b00a Merge tag 'armsoc-cleanup' of
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
>>>
>>> Thanks for the detailed report.
>>>
>>> Can you try again after applying this patch [1]?
>>>
>>> Regards,
>>>
>>> Boris
>>>
>>> [1]http://code.bulix.org/dx1c0t-98377
>>
>> Yes, it works.
>> Big thumbs up, that was fast !
>>
>> Less than 1 hour between the report and the patch ! :)
>
> Yes, absolutely terrific! Thanks Boris.
>
> I'd like you to test with this instead as it's the real range of the IP:
> + reg = <0xfffffc00 0x110>;
>
> Even I'm pretty confident ;-) Can you please do this for us ?
It works. Leds are blinking and nanosleep() doesn't block forever.

>> This is clearly 4.6 material (as it's a regression from 4.5), but it's
>> maybe a little late.
>> Anrd, Nicolas, what do you think ?
>
> I sent a PR this morning to Arnd with a "fix"... I hope that he won't be
> annoyed if I send him another one this evening...  But clearly, it's a
> regression and a pretty bad one :-\
>
> Thanks a lot for this report Richard,
you're welcome !


Richard.


From maxime.ripard at free-electrons.com  Wed May 11 23:59:43 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Thu, 12 May 2016 08:59:43 +0200
Subject: [linux-sunxi] Re: [PATCH v4 01/11] clk: sunxi: Add display and
 TCON0 clocks driver
In-Reply-To: <1463024360.16747.4.camel@plaes.org>
References: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
 <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
 <20160506223002.GE3492@codeaurora.org>
 <20160508200308.GF6167@lukather>
 <20160509223238.GW3492@codeaurora.org>
 <20160509223924.GX3492@codeaurora.org>
 <1462907459.9981.0.camel@plaes.org>
 <20160511221541.GG3492@codeaurora.org>
 <1463024360.16747.4.camel@plaes.org>
Message-ID: <20160512065943.GX3733@lukather>

On Thu, May 12, 2016 at 06:39:20AM +0300, Priit Laes wrote:
> On Wed, 2016-05-11 at 15:15 -0700, Stephen Boyd wrote:
> > On 05/10, Priit Laes wrote:
> > > 
> > > On Mon, 2016-05-09 at 15:39 -0700, Stephen Boyd wrote:
> > > > 
> > > > On 05/09, Stephen Boyd wrote:
> > > > > 
> > > > > 
> > > > > 
> > > > > Ok I applied this one to clk-next.
> > > > > 
> > > > And I squashed this in to silence the following checker warning.
> > > > 
> > > > drivers/clk/sunxi/clk-sun4i-display.c:110:33: warning: Variable
> > > > length array is used.
> > > > 
> > > > ---8<---
> > > > diff --git a/drivers/clk/sunxi/clk-sun4i-display.c
> > > > b/drivers/clk/sunxi/clk-sun4i-display.c
> > > > index f02e250e64ed..f8ff6c4a5633 100644
> > > > --- a/drivers/clk/sunxi/clk-sun4i-display.c
> > > > +++ b/drivers/clk/sunxi/clk-sun4i-display.c
> > > > @@ -107,7 +107,7 @@ static int
> > > > sun4i_a10_display_reset_xlate(struct
> > > > reset_controller_dev *rcdev,
> > > > ?static void __init sun4i_a10_display_init(struct device_node
> > > > *node,
> > > > ?					??const struct
> > > > sun4i_a10_display_clk_data *data)
> > > > ?{
> > > > -	const char *parents[data->parents];
> > > > +	const char *parents[4];
> > > This change breaks at least de_[bf]e clocks which have 3 clock
> > > parents.
> 
> > I just used the largest data->parents number, which was 4. How
> > does that break anything?
> 
> If you look at the?sun4i_a10_display_init, it contains this block:
> 
> ? ? ret = of_clk_parent_fill(node, parents, ARRAY_SIZE(parents));
> ????if (ret != ARRAY_SIZE(parents)) {
> ????????pr_err("%s: Could not retrieve the parents\n", clk_name);
> ????????goto unmap;
> ????}
> 
> of_clk_parent_fill returns 3 for de_be/de_fe nodes, and
> ARRAY_SIZE(parents) is 4.

Replacing both ARRAY_SIZE(parents) by data->parents would work though.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160512/443d58bd/attachment.sig>

From stanimir.varbanov at linaro.org  Thu May 12 00:00:35 2016
From: stanimir.varbanov at linaro.org (Stanimir Varbanov)
Date: Thu, 12 May 2016 10:00:35 +0300
Subject: [Patch v4 1/8] dt/bindings: firmware: Add Qualcomm SCM binding
In-Reply-To: <1462976158-26016-2-git-send-email-andy.gross@linaro.org>
References: <1462976158-26016-1-git-send-email-andy.gross@linaro.org>
 <1462976158-26016-2-git-send-email-andy.gross@linaro.org>
Message-ID: <57342A13.3090006@linaro.org>

On 05/11/2016 05:15 PM, Andy Gross wrote:
> This patch adds the device tree support for the Qualcomm SCM firmware.
> 
> Signed-off-by: Andy Gross <andy.gross at linaro.org>
> ---
>  .../devicetree/bindings/firmware/qcom,scm.txt      | 28 ++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/firmware/qcom,scm.txt
> 
> diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
> new file mode 100644
> index 0000000..0c5f1ff
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
> @@ -0,0 +1,28 @@
> +QCOM Secure Channel Manager (SCM)
> +
> +Qualcomm processors include an interface to communicate to the secure firmware.
> +This interface allows for clients to request different types of actions.  These
> +can include CPU power up/down, HDCP requests, loading of firmware, and other
> +assorted actions.
> +
> +Required properties:
> +- compatible: must contain one of the following:
> + * "qcom,scm-apq8064" for APQ8064 platforms
> + * "qcom,scm-msm8660" for MSM8660 platforms
> + * "qcom,scm-msm8690" for MSM8690 platforms
> + * "qcom,scm" for later processors (MSM8916, APQ8084, MSM8974, etc)
> +- clocks: One to three clocks may be required based on compatible.
> + * Only core clock required for "qcom,scm-apq8084", "qcom,scm-msm8660", and "qcom,scm-msm8960"
                                                ^^^^
probably this should be apq8064?

-- 
regards,
Stan


From chaotian.jing at mediatek.com  Thu May 12 00:00:31 2016
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Thu, 12 May 2016 15:00:31 +0800
Subject: [PATCH] mmc: mmc: do not use CMD13 to get status after speed
 mode switch
In-Reply-To: <5732E43E.8070800@intel.com>
References: <1462344872-6448-1-git-send-email-chaotian.jing@mediatek.com>
 <5732E43E.8070800@intel.com>
Message-ID: <1463036431.11653.3.camel@mhfsdcap03>

On Wed, 2016-05-11 at 10:50 +0300, Adrian Hunter wrote:
> On 04/05/16 09:54, Chaotian Jing wrote:
> > Per JEDEC spec, it is not recommended to use CMD13 to get card status
> > after speed mode switch. below are two reason about this:
> > 1. CMD13 cannot be guaranteed due to the asynchronous operation.
> > Therefore it is not recommended to use CMD13 to check busy completion
> > of the timing change indication.
> > 2. After switch to HS200, CMD13 will get response of 0x800, and even the
> > busy signal gets de-asserted, the response of CMD13 is aslo 0x800.
> > 
> > this patch drops CMD13 when doing speed mode switch, if host do not
> > support MMC_CAP_WAIT_WHILE_BUSY and there is no ops->card_busy(),
> > then the only way is to wait a fixed timeout.
> 
> This looks like it should be 3 patches:
> 	1. Change __mmc_switch
> 	2. Change HS200 and HS400 selection
> 	3. Change HS selection
> 
> However there is another problem: card_busy is not the same as busy signal -
> see below.  So that needs to be sorted out first.
> 
We should make that card_busy() is the same with busy signal asserted.
as you know, if card was not in busy state, all data pins should be high
level as it is pull-up by default. so that's no conflict to check card
busy signal by DAT0 or DAT0 ~ DAT3.
And, if someone thinks that its card_busy() is only used for SD card,
then its MMC host driver should not provide ops->card_busy().
> > 
> > Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
> > ---
> >  drivers/mmc/core/mmc.c     |   82 ++++++++++++++++----------------------------
> >  drivers/mmc/core/mmc_ops.c |   25 +++++++++-----
> >  2 files changed, 45 insertions(+), 62 deletions(-)
> > 
> > diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> > index 4dbe3df..03ee7a4 100644
> > --- a/drivers/mmc/core/mmc.c
> > +++ b/drivers/mmc/core/mmc.c
> > @@ -962,7 +962,7 @@ static int mmc_select_hs(struct mmc_card *card)
> >  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> >  			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
> >  			   card->ext_csd.generic_cmd6_time,
> > -			   true, true, true);
> > +			   true, false, true);
> 
> If you are going to do that, then you still need to do mmc_switch_status(card).
> 
> But we have done CMD13 polling for HS for a long time, so this should be a
> separate patch and separately justified.  Maybe we should still poll if
> !(host->caps & MMC_CAP_WAIT_WHILE_BUSY) && !host->ops->card_busy.
> 
> >  	if (!err)
> >  		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
> >  
> > @@ -1056,7 +1056,6 @@ static int mmc_switch_status(struct mmc_card *card)
> >  static int mmc_select_hs400(struct mmc_card *card)
> >  {
> >  	struct mmc_host *host = card->host;
> > -	bool send_status = true;
> >  	unsigned int max_dtr;
> >  	int err = 0;
> >  	u8 val;
> > @@ -1068,9 +1067,6 @@ static int mmc_select_hs400(struct mmc_card *card)
> >  	      host->ios.bus_width == MMC_BUS_WIDTH_8))
> >  		return 0;
> >  
> > -	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
> > -		send_status = false;
> > -
> >  	/* Reduce frequency to HS frequency */
> >  	max_dtr = card->ext_csd.hs_max_dtr;
> >  	mmc_set_clock(host, max_dtr);
> > @@ -1080,7 +1076,7 @@ static int mmc_select_hs400(struct mmc_card *card)
> >  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> >  			   EXT_CSD_HS_TIMING, val,
> >  			   card->ext_csd.generic_cmd6_time,
> > -			   true, send_status, true);
> > +			   true, false, true);
> >  	if (err) {
> >  		pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
> >  			mmc_hostname(host), err);
> > @@ -1090,11 +1086,9 @@ static int mmc_select_hs400(struct mmc_card *card)
> >  	/* Set host controller to HS timing */
> >  	mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
> >  
> > -	if (!send_status) {
> > -		err = mmc_switch_status(card);
> > -		if (err)
> > -			goto out_err;
> > -	}
> > +	err = mmc_switch_status(card);
> > +	if (err)
> > +		goto out_err;
> >  
> >  	/* Switch card to DDR */
> >  	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> > @@ -1113,7 +1107,7 @@ static int mmc_select_hs400(struct mmc_card *card)
> >  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> >  			   EXT_CSD_HS_TIMING, val,
> >  			   card->ext_csd.generic_cmd6_time,
> > -			   true, send_status, true);
> > +			   true, false, true);
> >  	if (err) {
> >  		pr_err("%s: switch to hs400 failed, err:%d\n",
> >  			 mmc_hostname(host), err);
> > @@ -1124,11 +1118,9 @@ static int mmc_select_hs400(struct mmc_card *card)
> >  	mmc_set_timing(host, MMC_TIMING_MMC_HS400);
> >  	mmc_set_bus_speed(card);
> >  
> > -	if (!send_status) {
> > -		err = mmc_switch_status(card);
> > -		if (err)
> > -			goto out_err;
> > -	}
> > +	err = mmc_switch_status(card);
> > +	if (err)
> > +		goto out_err;
> >  
> >  	return 0;
> >  
> > @@ -1146,14 +1138,10 @@ int mmc_hs200_to_hs400(struct mmc_card *card)
> >  int mmc_hs400_to_hs200(struct mmc_card *card)
> >  {
> >  	struct mmc_host *host = card->host;
> > -	bool send_status = true;
> >  	unsigned int max_dtr;
> >  	int err;
> >  	u8 val;
> >  
> > -	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
> > -		send_status = false;
> > -
> >  	/* Reduce frequency to HS */
> >  	max_dtr = card->ext_csd.hs_max_dtr;
> >  	mmc_set_clock(host, max_dtr);
> > @@ -1162,49 +1150,43 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
> >  	val = EXT_CSD_TIMING_HS;
> >  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
> >  			   val, card->ext_csd.generic_cmd6_time,
> > -			   true, send_status, true);
> > +			   true, false, true);
> >  	if (err)
> >  		goto out_err;
> >  
> >  	mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
> >  
> > -	if (!send_status) {
> > -		err = mmc_switch_status(card);
> > -		if (err)
> > -			goto out_err;
> > -	}
> > +	err = mmc_switch_status(card);
> > +	if (err)
> > +		goto out_err;
> >  
> >  	/* Switch HS DDR to HS */
> >  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
> >  			   EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time,
> > -			   true, send_status, true);
> > +			   true, false, true);
> >  	if (err)
> >  		goto out_err;
> >  
> >  	mmc_set_timing(host, MMC_TIMING_MMC_HS);
> >  
> > -	if (!send_status) {
> > -		err = mmc_switch_status(card);
> > -		if (err)
> > -			goto out_err;
> > -	}
> > +	err = mmc_switch_status(card);
> > +	if (err)
> > +		goto out_err;
> >  
> >  	/* Switch HS to HS200 */
> >  	val = EXT_CSD_TIMING_HS200 |
> >  	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
> >  	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
> >  			   val, card->ext_csd.generic_cmd6_time, true,
> > -			   send_status, true);
> > +			   false, true);
> >  	if (err)
> >  		goto out_err;
> >  
> >  	mmc_set_timing(host, MMC_TIMING_MMC_HS200);
> >  
> > -	if (!send_status) {
> > -		err = mmc_switch_status(card);
> > -		if (err)
> > -			goto out_err;
> > -	}
> > +	err = mmc_switch_status(card);
> > +	if (err)
> > +		goto out_err;
> >  
> >  	mmc_set_bus_speed(card);
> >  
> > @@ -1243,7 +1225,6 @@ static void mmc_select_driver_type(struct mmc_card *card)
> >  static int mmc_select_hs200(struct mmc_card *card)
> >  {
> >  	struct mmc_host *host = card->host;
> > -	bool send_status = true;
> >  	unsigned int old_timing;
> >  	int err = -EINVAL;
> >  	u8 val;
> > @@ -1260,9 +1241,6 @@ static int mmc_select_hs200(struct mmc_card *card)
> >  
> >  	mmc_select_driver_type(card);
> >  
> > -	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
> > -		send_status = false;
> > -
> >  	/*
> >  	 * Set the bus width(4 or 8) with host's support and
> >  	 * switch to HS200 mode if bus width is set successfully.
> > @@ -1274,20 +1252,18 @@ static int mmc_select_hs200(struct mmc_card *card)
> >  		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> >  				   EXT_CSD_HS_TIMING, val,
> >  				   card->ext_csd.generic_cmd6_time,
> > -				   true, send_status, true);
> > +				   true, false, true);
> >  		if (err)
> >  			goto err;
> >  		old_timing = host->ios.timing;
> >  		mmc_set_timing(host, MMC_TIMING_MMC_HS200);
> > -		if (!send_status) {
> > -			err = mmc_switch_status(card);
> > -			/*
> > -			 * mmc_select_timing() assumes timing has not changed if
> > -			 * it is a switch error.
> > -			 */
> > -			if (err == -EBADMSG)
> > -				mmc_set_timing(host, old_timing);
> > -		}
> > +		err = mmc_switch_status(card);
> > +		/*
> > +		 * mmc_select_timing() assumes timing has not changed if
> > +		 * it is a switch error.
> > +		 */
> > +		if (err == -EBADMSG)
> > +			mmc_set_timing(host, old_timing);
> >  	}
> >  err:
> >  	if (err)
> > diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> > index 62355bd..32de144 100644
> > --- a/drivers/mmc/core/mmc_ops.c
> > +++ b/drivers/mmc/core/mmc_ops.c
> > @@ -480,6 +480,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
> >  	u32 status = 0;
> >  	bool use_r1b_resp = use_busy_signal;
> >  	bool expired = false;
> > +	bool busy = false;
> >  
> >  	mmc_retune_hold(host);
> >  
> > @@ -535,19 +536,24 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
> >  	/* Must check status to be sure of no errors. */
> >  	timeout = jiffies + msecs_to_jiffies(timeout_ms);
> >  	do {
> > +		/*
> > +		 * Due to the possibility of being preempted after
> > +		 * sending the status command, check the expiration
> > +		 * time first.
> > +		 */
> > +		expired = time_after(jiffies, timeout);
> >  		if (send_status) {
> > -			/*
> > -			 * Due to the possibility of being preempted after
> > -			 * sending the status command, check the expiration
> > -			 * time first.
> > -			 */
> > -			expired = time_after(jiffies, timeout);
> >  			err = __mmc_send_status(card, &status, ignore_crc);
> >  			if (err)
> >  				goto out;
> >  		}
> >  		if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
> >  			break;
> > +		if (host->ops->card_busy) {
> 
> card_busy is a problem because it is designed for SD voltage switch which
> checks DAT[3:0] whereas the busy signal is only DAT0.
> 
> > +			if (!host->ops->card_busy(host))
> > +				break;
> > +			busy = true;
> > +		}
> >  		if (mmc_host_is_spi(host))
> >  			break;
> 
> I would tend to put all the changes together here after the
> mmc_host_is_spi() check i.e.
> 
> 		if (host->ops->card_busy) {
> 			expired = time_after(jiffies, timeout);
> 			if (!host->ops->card_busy(host))
> 				break;
> 			if (!expired) {
> 				cond_resched();
> 				continue;
> 			}
> 			pr_err("%s: Card stuck in busy state! %s\n",
> 			       mmc_hostname(host), __func__);
> 			err = -ETIMEDOUT;
> 			goto out;
> 		}
> 
> Also I think the changes to __mmc_switch() should be a separate patch.
> However you can't go forward with this until you sort out what card_busy means.
> 
> >  
> > @@ -556,19 +562,20 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
> >  		 * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
> >  		 * rely on waiting for the stated timeout to be sufficient.
> >  		 */
> > -		if (!send_status) {
> > +		if (!send_status && !host->ops->card_busy) {
> >  			mmc_delay(timeout_ms);
> >  			goto out;
> >  		}
> >  
> >  		/* Timeout if the device never leaves the program state. */
> > -		if (expired && R1_CURRENT_STATE(status) == R1_STATE_PRG) {
> > +		if (expired &&
> > +		    (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy)) {
> >  			pr_err("%s: Card stuck in programming state! %s\n",
> >  				mmc_hostname(host), __func__);
> >  			err = -ETIMEDOUT;
> >  			goto out;
> >  		}
> > -	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
> > +	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy);
> >  
> >  	err = mmc_switch_status_error(host, status);
> >  out:
> > 
> 




From hs.liao at mediatek.com  Thu May 12 00:13:27 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Thu, 12 May 2016 15:13:27 +0800
Subject: [PATCH v6 1/4] dt-bindings: soc: Add documentation for the MediaTek
 GCE unit
In-Reply-To: <1463037210-863-1-git-send-email-hs.liao@mediatek.com>
References: <1463037210-863-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1463037210-863-2-git-send-email-hs.liao@mediatek.com>

This adds documentation for the MediaTek Global Command Engine (GCE) unit
found in MT8173 SoCs.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/soc/mediatek/gce.txt       | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/gce.txt

diff --git a/Documentation/devicetree/bindings/soc/mediatek/gce.txt b/Documentation/devicetree/bindings/soc/mediatek/gce.txt
new file mode 100644
index 0000000..eff07e2
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/gce.txt
@@ -0,0 +1,34 @@
+MediaTek GCE
+===============
+
+The Global Command Engine (GCE) is used to help read/write registers with
+critical time limitation, such as updating display configuration during the
+vblank. The GCE can be used to implement the Command Queue (CMDQ) driver.
+
+Required properties:
+- compatible: Must be "mediatek,mt8173-gce"
+- reg: Address range of the GCE unit
+- interrupts: The interrupt signal from the GCE block
+- clock: Clocks according to the common clock binding
+- clock-names: Must be "gce" to stand for GCE clock
+
+Required properties for a client device:
+- mediatek,gce: Should point to the respective GCE block
+
+Example:
+
+	gce: gce at 10212000 {
+		compatible = "mediatek,mt8173-gce";
+		reg = <0 0x10212000 0 0x1000>;
+		interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&infracfg CLK_INFRA_GCE>;
+		clock-names = "gce";
+	};
+
+Example for a client device:
+
+	mmsys: clock-controller at 14000000 {
+		compatible = "mediatek,mt8173-mmsys";
+		mediatek,gce = <&gce>;
+		...
+	};
-- 
1.9.1



From hs.liao at mediatek.com  Thu May 12 00:13:28 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Thu, 12 May 2016 15:13:28 +0800
Subject: [PATCH v6 2/4] CMDQ: Mediatek CMDQ driver
In-Reply-To: <1463037210-863-1-git-send-email-hs.liao@mediatek.com>
References: <1463037210-863-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1463037210-863-3-git-send-email-hs.liao@mediatek.com>

This patch is first version of Mediatek Command Queue(CMDQ) driver. The
CMDQ is used to help read/write registers with critical time limitation,
such as updating display configuration during the vblank. It controls
Global Command Engine (GCE) hardware to achieve this requirement.
Currently, CMDQ only supports display related hardwares, but we expect
it can be extended to other hardwares for future requirements.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
Signed-off-by: CK Hu <ck.hu at mediatek.com>
---
 drivers/soc/mediatek/Kconfig    |   10 +
 drivers/soc/mediatek/Makefile   |    1 +
 drivers/soc/mediatek/mtk-cmdq.c | 1204 +++++++++++++++++++++++++++++++++++++++
 include/soc/mediatek/cmdq.h     |  197 +++++++
 4 files changed, 1412 insertions(+)
 create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
 create mode 100644 include/soc/mediatek/cmdq.h

diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 0a4ea80..c4ad75c 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -1,6 +1,16 @@
 #
 # MediaTek SoC drivers
 #
+config MTK_CMDQ
+	bool "MediaTek CMDQ Support"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	select MTK_INFRACFG
+	help
+	  Say yes here to add support for the MediaTek Command Queue (CMDQ)
+	  driver. The CMDQ is used to help read/write registers with critical
+	  time limitation, such as updating display configuration during the
+	  vblank.
+
 config MTK_INFRACFG
 	bool "MediaTek INFRACFG Support"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index 12998b0..f7397ef 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq.o
 obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
 obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
 obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
new file mode 100644
index 0000000..72afc3f
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-cmdq.c
@@ -0,0 +1,1204 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/suspend.h>
+#include <linux/workqueue.h>
+#include <soc/mediatek/cmdq.h>
+
+#define CMDQ_INITIAL_CMD_BLOCK_SIZE	PAGE_SIZE
+#define CMDQ_INST_SIZE			8 /* instruction is 64-bit */
+
+#define CMDQ_DEFAULT_TIMEOUT_MS		1000
+#define CMDQ_ACQUIRE_THREAD_TIMEOUT_MS	5000
+
+#define CMDQ_DRIVER_DEVICE_NAME		"mtk_cmdq"
+#define CMDQ_CLK_NAME			"gce"
+
+#define CMDQ_CURR_IRQ_STATUS_OFFSET	0x010
+#define CMDQ_THR_SLOT_CYCLES_OFFSET	0x030
+
+#define CMDQ_THR_BASE			0x100
+#define CMDQ_THR_SHIFT			0x080
+#define CMDQ_THR_WARM_RESET_OFFSET	0x00
+#define CMDQ_THR_ENABLE_TASK_OFFSET	0x04
+#define CMDQ_THR_SUSPEND_TASK_OFFSET	0x08
+#define CMDQ_THR_CURR_STATUS_OFFSET	0x0c
+#define CMDQ_THR_IRQ_STATUS_OFFSET	0x10
+#define CMDQ_THR_IRQ_ENABLE_OFFSET	0x14
+#define CMDQ_THR_CURR_ADDR_OFFSET	0x20
+#define CMDQ_THR_END_ADDR_OFFSET	0x24
+#define CMDQ_THR_CFG_OFFSET		0x40
+
+#define CMDQ_IRQ_MASK			0xffff
+
+#define CMDQ_THR_ENABLED		0x1
+#define CMDQ_THR_DISABLED		0x0
+#define CMDQ_THR_SUSPEND		0x1
+#define CMDQ_THR_RESUME			0x0
+#define CMDQ_THR_STATUS_SUSPENDED	BIT(1)
+#define CMDQ_THR_WARM_RESET		BIT(0)
+#define CMDQ_THR_SLOT_CYCLES		0x3200
+#define CMDQ_THR_PRIORITY		3
+#define CMDQ_THR_IRQ_DONE		0x1
+#define CMDQ_THR_IRQ_ERROR		0x12
+#define CMDQ_THR_IRQ_EN			0x13 /* done + error */
+#define CMDQ_THR_IRQ_MASK		0x13
+#define CMDQ_THR_EXECUTING		BIT(31)
+
+#define CMDQ_ARG_A_WRITE_MASK		0xffff
+#define CMDQ_SUBSYS_MASK		0x1f
+
+#define CMDQ_OP_CODE_SHIFT		24
+#define CMDQ_SUBSYS_SHIFT		16
+
+#define CMDQ_JUMP_BY_OFFSET		0x10000000
+#define CMDQ_JUMP_BY_PA			0x10000001
+#define CMDQ_JUMP_PASS			CMDQ_INST_SIZE
+
+#define CMDQ_WFE_UPDATE			BIT(31)
+#define CMDQ_WFE_WAIT			BIT(15)
+#define CMDQ_WFE_WAIT_VALUE		0x1
+
+#define CMDQ_EOC_IRQ_EN			BIT(0)
+
+#define CMDQ_ENABLE_MASK		BIT(0)
+
+#define CMDQ_OP_CODE_MASK		0xff000000
+
+enum cmdq_thread_index {
+	CMDQ_THR_DISP_MAIN_IDX,	/* main */
+	CMDQ_THR_DISP_SUB_IDX,	/* sub */
+	CMDQ_THR_DISP_MISC_IDX,	/* misc */
+	CMDQ_THR_MAX_COUNT,	/* max */
+};
+
+struct cmdq_command {
+	struct cmdq	*cmdq;
+	u64		engine_flag;
+	void		*base; /* command buffer pointer */
+	size_t		size; /* command buffer size (bytes) */
+};
+
+/*
+ * CMDQ_CODE_MOVE:
+ *   move value into internal register as mask
+ *   format: op mask
+ * CMDQ_CODE_WRITE:
+ *   write value into target register
+ *   format: op subsys address value
+ * CMDQ_CODE_JUMP:
+ *   jump by offset
+ *   format: op offset
+ * CMDQ_CODE_WFE:
+ *   wait for event and clear
+ *   it is just clear if no wait
+ *   format: [wait]  op event update:1 to_wait:1 wait:1
+ *           [clear] op event update:1 to_wait:0 wait:0
+ * CMDQ_CODE_EOC:
+ *   end of command
+ *   format: op irq_flag
+ */
+enum cmdq_code {
+	CMDQ_CODE_MOVE = 0x02,
+	CMDQ_CODE_WRITE = 0x04,
+	CMDQ_CODE_JUMP = 0x10,
+	CMDQ_CODE_WFE = 0x20,
+	CMDQ_CODE_EOC = 0x40,
+};
+
+enum cmdq_task_state {
+	TASK_STATE_WAITING,	/* allocated but waiting for available thread */
+	TASK_STATE_BUSY,	/* task running on a thread */
+	TASK_STATE_ERROR,	/* task execution error */
+	TASK_STATE_DONE,	/* task finished */
+};
+
+struct cmdq_task_cb {
+	cmdq_async_flush_cb	cb;
+	void			*data;
+};
+
+struct cmdq_thread;
+
+struct cmdq_task {
+	struct cmdq		*cmdq;
+	struct list_head	list_entry;
+	enum cmdq_task_state	task_state;
+	void			*va_base; /* va */
+	dma_addr_t		mva_base; /* pa */
+	u64			engine_flag;
+	size_t			command_size;
+	u32			num_cmd; /* 2 * number of commands */
+	struct cmdq_thread	*thread;
+	struct cmdq_task_cb	cb; /* callback */
+	/* work item when auto release is used */
+	struct work_struct	auto_release_work;
+};
+
+struct cmdq_thread {
+	void __iomem		*base;
+	u32			task_count;
+	struct list_head	task_busy_list;
+	wait_queue_head_t	wait_queue; /* wait task done */
+};
+
+struct cmdq {
+	struct device		*dev;
+	void __iomem		*base;
+	u32			irq;
+
+	/*
+	 * task_cache: struct cmdq_task object cache
+	 * task_consume_wait_queue_item: task consuming work
+	 * task_consume_wq: task consuming workqueue
+	 * task_auto_release_wq: auto-release workqueue
+	 */
+	struct kmem_cache	*task_cache;
+	struct list_head	task_wait_list;
+	struct work_struct	task_consume_wait_queue_item;
+	struct workqueue_struct	*task_consume_wq;
+	struct workqueue_struct	*task_auto_release_wq;
+
+	struct cmdq_thread	thread[CMDQ_THR_MAX_COUNT];
+	struct mutex		task_mutex;	/* for task list */
+	spinlock_t		exec_lock;	/* for exec task */
+	wait_queue_head_t	thread_dispatch_queue;
+	struct clk		*clock;
+};
+
+struct cmdq_subsys {
+	u32	base_addr;
+	int	id;
+};
+
+static const struct cmdq_subsys g_subsys[] = {
+	{0x1400, 1},
+	{0x1401, 2},
+	{0x1402, 3},
+};
+
+static int cmdq_clk_enable(struct cmdq *cmdq)
+{
+	struct device *dev = cmdq->dev;
+	int err;
+
+	err = clk_prepare_enable(cmdq->clock);
+	if (err < 0) {
+		dev_err(dev, "prepare and enable clk:%s fail\n",
+			CMDQ_CLK_NAME);
+		return err;
+	}
+	return 0;
+}
+
+static void cmdq_clk_disable(struct cmdq *cmdq)
+{
+	clk_disable_unprepare(cmdq->clock);
+}
+
+static int cmdq_subsys_base_addr_to_id(u32 base_addr)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(g_subsys); i++)
+		if (g_subsys[i].base_addr == base_addr)
+			return g_subsys[i].id;
+	return -EFAULT;
+}
+
+static int cmdq_eng_get_thread(u64 flag)
+{
+	if (flag & BIT_ULL(CMDQ_ENG_DISP_DSI0))
+		return CMDQ_THR_DISP_MAIN_IDX;
+	else if (flag & BIT_ULL(CMDQ_ENG_DISP_DPI0))
+		return CMDQ_THR_DISP_SUB_IDX;
+	else
+		return CMDQ_THR_DISP_MISC_IDX;
+}
+
+static void cmdq_task_release_internal(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+
+	mutex_lock(&cmdq->task_mutex);
+	dma_free_coherent(cmdq->dev, task->command_size, task->va_base,
+			  task->mva_base);
+	kmem_cache_free(cmdq->task_cache, task);
+	mutex_unlock(&cmdq->task_mutex);
+}
+
+static struct cmdq_task *cmdq_task_acquire(struct cmdq_command *command,
+					   struct cmdq_task_cb *cb)
+{
+	struct cmdq *cmdq = command->cmdq;
+	struct device *dev = cmdq->dev;
+	struct cmdq_task *task;
+
+	mutex_lock(&cmdq->task_mutex);
+	task = kmem_cache_zalloc(cmdq->task_cache, GFP_KERNEL);
+	INIT_LIST_HEAD(&task->list_entry);
+	task->va_base = dma_alloc_coherent(dev, command->size, &task->mva_base,
+					   GFP_KERNEL);
+	if (!task->va_base) {
+		dev_err(dev, "allocate command buffer failed\n");
+		kmem_cache_free(cmdq->task_cache, task);
+		mutex_unlock(&cmdq->task_mutex);
+		return NULL;
+	}
+
+	task->cmdq = cmdq;
+	task->command_size = command->size;
+	task->engine_flag = command->engine_flag;
+	task->task_state = TASK_STATE_WAITING;
+	if (cb)
+		task->cb = *cb;
+	memcpy(task->va_base, command->base, command->size);
+	task->num_cmd = task->command_size / sizeof(u32);
+	list_add_tail(&task->list_entry, &cmdq->task_wait_list);
+	mutex_unlock(&cmdq->task_mutex);
+	return task;
+}
+
+static void cmdq_thread_writel(struct cmdq_thread *thread, u32 value,
+			       u32 offset)
+{
+	writel(value, thread->base + offset);
+}
+
+static u32 cmdq_thread_readl(struct cmdq_thread *thread, u32 offset)
+{
+	return readl(thread->base + offset);
+}
+
+static struct cmdq_thread *cmdq_thread_get(struct cmdq *cmdq, int tid)
+{
+	struct cmdq_thread *thread = &cmdq->thread[tid];
+
+	cmdq_clk_enable(cmdq);
+	return thread;
+}
+
+static void cmdq_thread_put(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	if (WARN_ON(thread == NULL))
+		return;
+	cmdq_clk_disable(cmdq);
+}
+
+static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	u32 enabled;
+	u32 status;
+
+	/* write suspend bit */
+	cmdq_thread_writel(thread, CMDQ_THR_SUSPEND,
+			   CMDQ_THR_SUSPEND_TASK_OFFSET);
+
+	/* If already disabled, treat as suspended successful. */
+	enabled = cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK_OFFSET);
+	if (!(enabled & CMDQ_THR_ENABLED))
+		return 0;
+
+	/* poll suspended status */
+	if (readl_poll_timeout_atomic(thread->base +
+				      CMDQ_THR_CURR_STATUS_OFFSET,
+				      status,
+				      status & CMDQ_THR_STATUS_SUSPENDED,
+				      0, 10)) {
+		dev_err(cmdq->dev, "Suspend HW thread 0x%x failed\n",
+			(u32)(thread->base - cmdq->base));
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static void cmdq_thread_resume(struct cmdq_thread *thread)
+{
+	cmdq_thread_writel(thread, CMDQ_THR_RESUME,
+			   CMDQ_THR_SUSPEND_TASK_OFFSET);
+}
+
+static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	void __iomem *gce_base = cmdq->base;
+	u32 warm_reset;
+
+	cmdq_thread_writel(thread, CMDQ_THR_WARM_RESET,
+			   CMDQ_THR_WARM_RESET_OFFSET);
+	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET_OFFSET,
+				      warm_reset,
+				      !(warm_reset & CMDQ_THR_WARM_RESET),
+				      0, 10)) {
+		dev_err(cmdq->dev, "Reset HW thread 0x%x failed\n",
+			(u32)(thread->base - cmdq->base));
+		return -EFAULT;
+	}
+	writel(CMDQ_THR_SLOT_CYCLES, gce_base + CMDQ_THR_SLOT_CYCLES_OFFSET);
+	return 0;
+}
+
+static void cmdq_thread_disable(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	cmdq_thread_reset(cmdq, thread);
+	cmdq_thread_writel(thread, CMDQ_THR_DISABLED,
+			   CMDQ_THR_ENABLE_TASK_OFFSET);
+}
+
+/* notify GCE to re-fetch commands by setting HW thread PC */
+static void cmdq_thread_invalidate_fetched_data(struct cmdq_thread *thread)
+{
+	cmdq_thread_writel(thread,
+			   cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR_OFFSET),
+			   CMDQ_THR_CURR_ADDR_OFFSET);
+}
+
+static void cmdq_task_insert_into_thread(struct cmdq_task *task)
+{
+	struct cmdq_thread *thread = task->thread;
+	struct cmdq_task *prev_task = list_last_entry(
+			&thread->task_busy_list, typeof(*task), list_entry);
+	u32 *prev_task_base;
+
+	/* insert task, and let previous task jump to this task */
+	list_move_tail(&task->list_entry, &thread->task_busy_list);
+	prev_task_base = prev_task->va_base;
+	prev_task_base[prev_task->num_cmd - 1] = CMDQ_JUMP_BY_PA;
+	prev_task_base[prev_task->num_cmd - 2] = task->mva_base;
+
+	/* re-fetch command buffer */
+	cmdq_thread_invalidate_fetched_data(thread);
+}
+
+/* we assume tasks in the same display thread are waiting the same event. */
+static void cmdq_task_remove_wfe(struct cmdq_task *task)
+{
+	u32 wfe_option = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
+	u32 wfe_op = CMDQ_CODE_WFE << CMDQ_OP_CODE_SHIFT;
+	u32 *base = task->va_base;
+	int i;
+
+	for (i = 0; i < task->num_cmd; i += 2) {
+		if (base[i] == wfe_option &&
+		    (base[i + 1] & CMDQ_OP_CODE_MASK) == wfe_op) {
+			base[i] = CMDQ_JUMP_PASS;
+			base[i + 1] = CMDQ_JUMP_BY_OFFSET;
+		}
+	}
+}
+
+static int cmdq_task_exec_async(struct cmdq_task *task,
+				struct cmdq_thread *thread)
+{
+	struct cmdq *cmdq = task->cmdq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+	task->thread = thread;
+	task->task_state = TASK_STATE_BUSY;
+	if (thread->task_count <= 0) {
+		if (WARN_ON(cmdq_thread_reset(cmdq, thread) < 0)) {
+			spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+			return -EFAULT;
+		}
+
+		cmdq_thread_writel(thread, task->mva_base,
+				   CMDQ_THR_CURR_ADDR_OFFSET);
+		cmdq_thread_writel(thread, task->mva_base + task->command_size,
+				   CMDQ_THR_END_ADDR_OFFSET);
+		cmdq_thread_writel(thread, CMDQ_THR_PRIORITY,
+				   CMDQ_THR_CFG_OFFSET);
+		cmdq_thread_writel(thread, CMDQ_THR_IRQ_EN,
+				   CMDQ_THR_IRQ_ENABLE_OFFSET);
+
+		list_move_tail(&task->list_entry,
+			       &thread->task_busy_list);
+		thread->task_count = 1;
+
+		/* enable HW thread */
+		cmdq_thread_writel(thread, CMDQ_THR_ENABLED,
+				   CMDQ_THR_ENABLE_TASK_OFFSET);
+	} else {
+		unsigned long curr_pa, end_pa;
+		int err;
+
+		err = cmdq_thread_suspend(cmdq, thread);
+		if (WARN_ON(err < 0)) {
+			spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+			return err;
+		}
+
+		/*
+		 * check boundary condition
+		 * PC = END - 8, EOC is executed
+		 * PC = END - 0, all CMDs are executed
+		 */
+		curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR_OFFSET);
+		end_pa = cmdq_thread_readl(thread, CMDQ_THR_END_ADDR_OFFSET);
+		if ((curr_pa == end_pa - 8) || (curr_pa == end_pa - 0)) {
+			/* set to task directly */
+			cmdq_thread_writel(thread, task->mva_base,
+					   CMDQ_THR_CURR_ADDR_OFFSET);
+			cmdq_thread_writel(thread,
+					   task->mva_base + task->command_size,
+					   CMDQ_THR_END_ADDR_OFFSET);
+			list_move_tail(&task->list_entry,
+				       &thread->task_busy_list);
+			thread->task_count++;
+		} else {
+			cmdq_task_insert_into_thread(task);
+
+			if (thread == &cmdq->thread[CMDQ_THR_DISP_MAIN_IDX] ||
+			    thread == &cmdq->thread[CMDQ_THR_DISP_SUB_IDX])
+				cmdq_task_remove_wfe(task);
+
+			smp_mb(); /* modify jump before enable thread */
+			cmdq_thread_writel(thread,
+					   task->mva_base + task->command_size,
+					   CMDQ_THR_END_ADDR_OFFSET);
+			thread->task_count++;
+		}
+
+		cmdq_thread_resume(thread);
+	}
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+	return 0;
+}
+
+static void cmdq_handle_error_done(struct cmdq *cmdq,
+				   struct cmdq_thread *thread, bool err)
+{
+	struct cmdq_task *task, *tmp, *curr_task = NULL;
+	u32 curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR_OFFSET);
+	struct cmdq_cb_data cmdq_cb_data;
+
+	list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
+				 list_entry) {
+		if (curr_pa >= task->mva_base &&
+		    curr_pa < (task->mva_base + task->command_size)) {
+			curr_task = task;
+			break;
+		}
+
+		if (task->cb.cb) {
+			cmdq_cb_data.err = false;
+			cmdq_cb_data.data = task->cb.data;
+			task->cb.cb(cmdq_cb_data);
+		}
+		task->task_state = TASK_STATE_DONE;
+		list_del(&task->list_entry);
+		thread->task_count--;
+	}
+
+	if (curr_task) {
+		if (curr_task->cb.cb) {
+			cmdq_cb_data.err = err;
+			cmdq_cb_data.data = curr_task->cb.data;
+			curr_task->cb.cb(cmdq_cb_data);
+		}
+		if (err)
+			task->task_state = TASK_STATE_ERROR;
+		else
+			task->task_state = TASK_STATE_DONE;
+		list_del(&curr_task->list_entry);
+		thread->task_count--;
+	}
+
+	wake_up(&thread->wait_queue);
+}
+
+static void cmdq_handle_irq(struct cmdq *cmdq, int tid)
+{
+	struct device *dev = cmdq->dev;
+	struct cmdq_thread *thread = &cmdq->thread[tid];
+	unsigned long flags = 0L;
+	int value;
+	int enabled;
+
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+
+	/*
+	 * it is possible for another CPU core
+	 * to run "release task" right before we acquire the spin lock
+	 * and thus reset / disable this HW thread
+	 * so we check both the IRQ flag and the enable bit of this thread
+	 */
+	value = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS_OFFSET);
+	if (!(value & CMDQ_THR_IRQ_MASK)) {
+		dev_err(dev,
+			"IRQ: thread 0x%x got interrupt but IRQ flag=0x%x\n",
+			(u32)(thread->base - cmdq->base), value);
+		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+		return;
+	}
+
+	enabled = cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK_OFFSET);
+	if (!(enabled & CMDQ_THR_ENABLED)) {
+		dev_err(dev,
+			"IRQ: thread 0x%x got interrupt but enabled=0x%x\n",
+			(u32)(thread->base - cmdq->base), enabled);
+		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+		return;
+	}
+
+	/*
+	 * Move the reset IRQ before read HW cookie
+	 * to prevent race condition and save the cost of suspend
+	 */
+	cmdq_thread_writel(thread, ~value, CMDQ_THR_IRQ_STATUS_OFFSET);
+
+	if (value & CMDQ_THR_IRQ_ERROR)
+		cmdq_handle_error_done(cmdq, thread, true);
+	else if (value & CMDQ_THR_IRQ_DONE)
+		cmdq_handle_error_done(cmdq, thread, false);
+
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+}
+
+static void cmdq_consume_waiting_list(struct work_struct *work)
+{
+	struct cmdq *cmdq = container_of(work, struct cmdq,
+					 task_consume_wait_queue_item);
+	struct device *dev = cmdq->dev;
+	struct cmdq_task *task, *tmp;
+	u32 err_bits = 0;
+	const u32 disp_mask = BIT(CMDQ_THR_DISP_MAIN_IDX) |
+			      BIT(CMDQ_THR_DISP_SUB_IDX) |
+			      BIT(CMDQ_THR_DISP_MISC_IDX);
+
+	mutex_lock(&cmdq->task_mutex);
+
+	if (list_empty(&cmdq->task_wait_list)) {
+		mutex_unlock(&cmdq->task_mutex);
+		return;
+	}
+
+	list_for_each_entry_safe(task, tmp, &cmdq->task_wait_list, list_entry) {
+		struct cmdq_thread *thread = NULL;
+		int candidate_tid = cmdq_eng_get_thread(task->engine_flag);
+		int err;
+
+		/*
+		 * Once waiting occur,
+		 * skip following tasks to keep order of display tasks.
+		 */
+		if (err_bits & disp_mask & candidate_tid)
+			continue;
+
+		thread = cmdq_thread_get(cmdq, candidate_tid);
+		err = cmdq_task_exec_async(task, thread);
+		if (err < 0) {
+			dev_warn(dev, "start task fail. wait\n");
+			err_bits |= BIT(candidate_tid);
+			continue;
+		}
+	}
+
+	/*
+	 * Wake up waiting task(s) whether success or not
+	 * because wake up condition will check task's thread.
+	 * (cmdq_task_wait_and_release)
+	 */
+	wake_up_all(&cmdq->thread_dispatch_queue);
+
+	mutex_unlock(&cmdq->task_mutex);
+}
+
+static int cmdq_task_submit_async(struct cmdq_command *command,
+				  struct cmdq_task **task_out,
+				  struct cmdq_task_cb *cb)
+{
+	struct cmdq *cmdq = command->cmdq;
+
+	/* creates a new task and put into tail of waiting list */
+	*task_out = cmdq_task_acquire(command, cb);
+	if (!(*task_out))
+		return -EFAULT;
+	/* Do consumption here to gain some time if HW thread is available. */
+	cmdq_consume_waiting_list(&cmdq->task_consume_wait_queue_item);
+	return 0;
+}
+
+static int cmdq_task_handle_error_result(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+	struct device *dev = cmdq->dev;
+	struct cmdq_thread *thread = task->thread;
+	int err;
+	struct cmdq_task *next_task, *prev_task;
+	u32 *prev_va, *curr_va;
+	u32 irq_flag;
+
+	dev_err(dev,
+		"task(0x%p) state is not TASK_STATE_DONE, but %d.\n",
+		task, task->task_state);
+
+	/* suspend HW thread to ensure consistency */
+	err = cmdq_thread_suspend(cmdq, thread);
+	if (WARN_ON(err < 0))
+		return err;
+
+	/*
+	 * Save next_task and prev_task in advance
+	 * since cmdq_handle_error_done will remove list_entry.
+	 */
+	next_task = prev_task = NULL;
+	if (task->list_entry.next != &thread->task_busy_list)
+		next_task = list_next_entry(task, list_entry);
+	if (task->list_entry.prev != &thread->task_busy_list)
+		prev_task = list_prev_entry(task, list_entry);
+
+	/*
+	 * Although IRQ is disabled, GCE continues to execute.
+	 * It may have pending IRQ before HW thread is suspended,
+	 * so check this condition again.
+	 */
+	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS_OFFSET);
+	if (irq_flag & CMDQ_THR_IRQ_ERROR)
+		cmdq_handle_error_done(cmdq, thread, true);
+	else if (irq_flag & CMDQ_THR_IRQ_DONE)
+		cmdq_handle_error_done(cmdq, thread, false);
+	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS_OFFSET);
+
+	/* success after handling pending irq */
+	if (task->task_state == TASK_STATE_DONE) {
+		cmdq_thread_resume(thread);
+		return 0;
+	}
+
+	/* error in this task */
+	if (task->task_state == TASK_STATE_ERROR) {
+		if (next_task) /* move to next task */
+			cmdq_thread_writel(thread, next_task->mva_base,
+					   CMDQ_THR_CURR_ADDR_OFFSET);
+		cmdq_thread_resume(thread);
+		return -ECANCELED;
+	}
+
+	/* If task is running, force to remove it. */
+	dev_err(dev, "task 0x%p timeout or killed\n", task);
+
+	if (task->task_state == TASK_STATE_BUSY)
+		task->task_state = TASK_STATE_ERROR;
+
+	if (prev_task) {
+		u32 prev_num, curr_num;
+
+		prev_va = prev_task->va_base;
+		prev_num = prev_task->num_cmd;
+
+		curr_va = task->va_base;
+		curr_num = task->num_cmd;
+
+		/* copy JUMP instruction */
+		prev_va[prev_num - 2] = curr_va[curr_num - 2];
+		prev_va[prev_num - 1] = curr_va[curr_num - 1];
+
+		/* re-fetch command */
+		cmdq_thread_invalidate_fetched_data(thread);
+	} else if (next_task) { /* move to next task */
+		cmdq_thread_writel(thread, next_task->mva_base,
+				   CMDQ_THR_CURR_ADDR_OFFSET);
+	}
+
+	list_del(&task->list_entry);
+	thread->task_count--;
+	cmdq_thread_resume(thread);
+	return -ECANCELED;
+}
+
+static int cmdq_task_wait_result(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+	struct cmdq_thread *thread = task->thread;
+	int err = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+	if (task->task_state != TASK_STATE_DONE)
+		err = cmdq_task_handle_error_result(task);
+	if (thread->task_count <= 0)
+		cmdq_thread_disable(cmdq, thread);
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+	return err;
+}
+
+static int cmdq_task_wait_done(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+	struct device *dev = cmdq->dev;
+	int wait_q;
+	unsigned long timeout = msecs_to_jiffies(
+			CMDQ_ACQUIRE_THREAD_TIMEOUT_MS);
+
+	/* wait for acquiring thread (cmdq_consume_waiting_list) */
+	wait_q = wait_event_timeout(
+			cmdq->thread_dispatch_queue,
+			task->thread, timeout);
+	if (!wait_q) {
+		mutex_lock(&cmdq->task_mutex);
+		/* Check if task was just consumed. */
+		if (!task->thread) {
+			dev_err(dev,
+				"task(0x%p) timeout with invalid thread\n",
+				task);
+			/*
+			 * Remove from waiting list,
+			 * so it won't be consumed in the future.
+			 */
+			list_del_init(&task->list_entry);
+			mutex_unlock(&cmdq->task_mutex);
+			return -EINVAL;
+		}
+		/* valid thread, so we keep going */
+		mutex_unlock(&cmdq->task_mutex);
+	}
+
+	/* wait for execution */
+	wait_q = wait_event_timeout(task->thread->wait_queue,
+				    (task->task_state != TASK_STATE_BUSY &&
+				     task->task_state != TASK_STATE_WAITING),
+				    msecs_to_jiffies(CMDQ_DEFAULT_TIMEOUT_MS));
+	if (!wait_q)
+		dev_dbg(dev, "timeout!\n");
+
+	/* wake up and continue */
+	return cmdq_task_wait_result(task);
+}
+
+static int cmdq_task_wait_and_release(struct cmdq_task *task)
+{
+	int err = cmdq_task_wait_done(task);
+
+	/* release regardless of success or not */
+	cmdq_thread_put(task->cmdq, task->thread);
+	cmdq_task_release_internal(task);
+	return err;
+}
+
+static void cmdq_auto_release(struct work_struct *work_item)
+{
+	struct cmdq_task *task = container_of(work_item, struct cmdq_task,
+					      auto_release_work);
+	struct cmdq *cmdq = task->cmdq;
+	struct cmdq_task_cb cb = task->cb;
+	int err = cmdq_task_wait_and_release(task);
+	struct cmdq_cb_data cmdq_cb_data;
+
+	/* isr fail, so call cb here to prevent lock */
+	if (err < 0 && cb.cb) {
+		cmdq_cb_data.err = true;
+		cmdq_cb_data.data = cb.data;
+		cb.cb(cmdq_cb_data);
+	}
+
+	/* prevent no more flush or interrupt to consume waiting tasks */
+	if (err < 0)
+		queue_work(cmdq->task_consume_wq,
+			   &cmdq->task_consume_wait_queue_item);
+}
+
+static void cmdq_task_auto_release(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+
+	/*
+	 * the work item is embeded in task already
+	 * but we need to initialized it
+	 */
+	INIT_WORK(&task->auto_release_work, cmdq_auto_release);
+	queue_work(cmdq->task_auto_release_wq, &task->auto_release_work);
+}
+
+static int cmdq_task_submit(struct cmdq_command *command)
+{
+	struct device *dev = command->cmdq->dev;
+	int err;
+	struct cmdq_task *task;
+
+	err = cmdq_task_submit_async(command, &task, NULL);
+	if (err < 0) {
+		dev_err(dev, "cmdq_task_submit_async failed=%d\n", err);
+		return err;
+	}
+	err = cmdq_task_wait_and_release(task);
+	if (err < 0)
+		dev_err(dev, "task(0x%p) wait fail\n", task);
+	return err;
+}
+
+static int cmdq_remove(struct platform_device *pdev)
+{
+	struct cmdq *cmdq = platform_get_drvdata(pdev);
+	struct cmdq_task *task, *tmp;
+
+	destroy_workqueue(cmdq->task_consume_wq);
+	cmdq->task_consume_wq = NULL;
+	destroy_workqueue(cmdq->task_auto_release_wq);
+	cmdq->task_auto_release_wq = NULL;
+
+	/* release task_wait_list */
+	list_for_each_entry_safe(task, tmp, &cmdq->task_wait_list, list_entry) {
+		dma_free_coherent(cmdq->dev, task->command_size, task->va_base,
+				  task->mva_base);
+		list_del(&task->list_entry);
+		kmem_cache_free(cmdq->task_cache, task);
+	}
+
+	kmem_cache_destroy(cmdq->task_cache);
+	cmdq->task_cache = NULL;
+	return 0;
+}
+
+static irqreturn_t cmdq_irq_handler(int irq, void *dev)
+{
+	struct cmdq *cmdq = dev;
+	u32 irq_status;
+	int i;
+
+	irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS_OFFSET);
+	irq_status &= CMDQ_IRQ_MASK;
+	irq_status ^= CMDQ_IRQ_MASK;
+
+	if (!irq_status)
+		return IRQ_NONE;
+
+	while (irq_status) {
+		i = ffs(irq_status) - 1;
+		irq_status &= ~BIT(i);
+		cmdq_handle_irq(cmdq, i);
+	}
+
+	queue_work(cmdq->task_consume_wq, &cmdq->task_consume_wait_queue_item);
+	return IRQ_HANDLED;
+}
+
+static int cmdq_initialize(struct cmdq *cmdq)
+{
+	int i;
+
+	mutex_init(&cmdq->task_mutex);
+	spin_lock_init(&cmdq->exec_lock);
+	init_waitqueue_head(&cmdq->thread_dispatch_queue);
+	cmdq->task_cache = kmem_cache_create(
+			CMDQ_DRIVER_DEVICE_NAME "_task",
+			sizeof(struct cmdq_task), __alignof__(struct cmdq_task),
+			SLAB_POISON | SLAB_HWCACHE_ALIGN | SLAB_RED_ZONE, NULL);
+	INIT_LIST_HEAD(&cmdq->task_wait_list);
+	INIT_WORK(&cmdq->task_consume_wait_queue_item,
+		  cmdq_consume_waiting_list);
+	cmdq->task_auto_release_wq = alloc_ordered_workqueue(
+			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI, "cmdq_auto_release");
+	cmdq->task_consume_wq = alloc_ordered_workqueue(
+			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI, "cmdq_task");
+
+	/* initialize cmdq thread */
+	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
+		cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
+				CMDQ_THR_SHIFT * i;
+		init_waitqueue_head(&cmdq->thread[i].wait_queue);
+		INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list);
+	}
+
+	return 0;
+}
+
+static int cmdq_rec_realloc_cmd_buffer(struct cmdq_rec *rec, size_t size)
+{
+	void *new_buf = krealloc(rec->buf, size, GFP_KERNEL | __GFP_ZERO);
+
+	if (!new_buf)
+		return -ENOMEM;
+	rec->buf = new_buf;
+	rec->buf_size = size;
+	return 0;
+}
+
+struct cmdq_base *cmdq_register_device(struct device *dev)
+{
+	struct cmdq_base *cmdq_base;
+	struct resource res;
+	int subsys;
+	u32 base;
+
+	if (of_address_to_resource(dev->of_node, 0, &res))
+		return NULL;
+	base = (u32)res.start;
+
+	subsys = cmdq_subsys_base_addr_to_id(base >> 16);
+	if (subsys < 0)
+		return NULL;
+
+	cmdq_base = devm_kmalloc(dev, sizeof(*cmdq_base), GFP_KERNEL);
+	if (!cmdq_base)
+		return NULL;
+	cmdq_base->subsys = subsys;
+	cmdq_base->base = base;
+
+	return cmdq_base;
+}
+EXPORT_SYMBOL(cmdq_register_device);
+
+int cmdq_rec_create(struct device *dev, u64 engine_flag,
+		    struct cmdq_rec **rec_ptr)
+{
+	struct cmdq_rec *rec;
+	int err;
+
+	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
+	if (!rec)
+		return -ENOMEM;
+	rec->cmdq = dev_get_drvdata(dev);
+	rec->engine_flag = engine_flag;
+	err = cmdq_rec_realloc_cmd_buffer(rec, CMDQ_INITIAL_CMD_BLOCK_SIZE);
+	if (err < 0) {
+		kfree(rec);
+		return err;
+	}
+	*rec_ptr = rec;
+	return 0;
+}
+EXPORT_SYMBOL(cmdq_rec_create);
+
+static int cmdq_rec_append_command(struct cmdq_rec *rec, enum cmdq_code code,
+				   u32 arg_a, u32 arg_b)
+{
+	u32 *cmd_ptr;
+	int err;
+
+	if (WARN_ON(rec->finalized))
+		return -EBUSY;
+	if (code < CMDQ_CODE_MOVE || code > CMDQ_CODE_EOC)
+		return -EINVAL;
+	if (unlikely(rec->command_size + CMDQ_INST_SIZE > rec->buf_size)) {
+		err = cmdq_rec_realloc_cmd_buffer(rec, rec->buf_size * 2);
+		if (err < 0)
+			return err;
+	}
+	cmd_ptr = (u32 *)(rec->buf + rec->command_size);
+	cmd_ptr[0] = arg_b;
+	cmd_ptr[1] = (code << CMDQ_OP_CODE_SHIFT) | arg_a;
+	rec->command_size += CMDQ_INST_SIZE;
+	return 0;
+}
+
+int cmdq_rec_write(struct cmdq_rec *rec, u32 value, struct cmdq_base *base,
+		   u32 offset)
+{
+	u32 arg_a = ((base->base + offset) & CMDQ_ARG_A_WRITE_MASK) |
+		    ((base->subsys & CMDQ_SUBSYS_MASK) << CMDQ_SUBSYS_SHIFT);
+
+	return cmdq_rec_append_command(rec, CMDQ_CODE_WRITE, arg_a, value);
+}
+EXPORT_SYMBOL(cmdq_rec_write);
+
+int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
+			struct cmdq_base *base, u32 offset, u32 mask)
+{
+	u32 offset_mask = offset;
+	int err;
+
+	if (mask != 0xffffffff) {
+		err = cmdq_rec_append_command(rec, CMDQ_CODE_MOVE, 0, ~mask);
+		if (err < 0)
+			return err;
+		offset_mask |= CMDQ_ENABLE_MASK;
+	}
+	return cmdq_rec_write(rec, value, base, offset_mask);
+}
+EXPORT_SYMBOL(cmdq_rec_write_mask);
+
+int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event)
+{
+	u32 arg_b;
+
+	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
+		return -EINVAL;
+
+	/*
+	 * bit 0-11: wait value
+	 * bit 15: 1 - wait, 0 - no wait
+	 * bit 16-27: update value
+	 * bit 31: 1 - update, 0 - no update
+	 */
+	arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
+	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event, arg_b);
+}
+EXPORT_SYMBOL(cmdq_rec_wfe);
+
+int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event)
+{
+	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
+		return -EINVAL;
+
+	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event,
+				       CMDQ_WFE_UPDATE);
+}
+EXPORT_SYMBOL(cmdq_rec_clear_event);
+
+static int cmdq_rec_fill_command(struct cmdq_rec *rec,
+				 struct cmdq_command *command)
+{
+	if (!rec->finalized) {
+		int err;
+
+		/* insert EOC and generate IRQ for each command iteration */
+		err = cmdq_rec_append_command(rec, CMDQ_CODE_EOC, 0,
+					      CMDQ_EOC_IRQ_EN);
+		if (err < 0)
+			return err;
+
+		/* JUMP to end */
+		err = cmdq_rec_append_command(rec, CMDQ_CODE_JUMP, 0,
+					      CMDQ_JUMP_PASS);
+		if (err < 0)
+			return err;
+
+		rec->finalized = true;
+	}
+
+	command->cmdq = rec->cmdq;
+	command->engine_flag = rec->engine_flag;
+	command->base = rec->buf;
+	command->size = rec->command_size;
+	return 0;
+}
+
+int cmdq_rec_flush(struct cmdq_rec *rec)
+{
+	int err;
+	struct cmdq_command command;
+
+	err = cmdq_rec_fill_command(rec, &command);
+	if (err < 0)
+		return err;
+	return cmdq_task_submit(&command);
+}
+EXPORT_SYMBOL(cmdq_rec_flush);
+
+int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
+			 void *data)
+{
+	int err;
+	struct cmdq_command command;
+	struct cmdq_task *task;
+	struct cmdq_task_cb task_cb;
+
+	err = cmdq_rec_fill_command(rec, &command);
+	if (err < 0)
+		return err;
+	task_cb.cb = cb;
+	task_cb.data = data;
+	err = cmdq_task_submit_async(&command, &task, &task_cb);
+	if (err < 0)
+		return err;
+	cmdq_task_auto_release(task);
+	return 0;
+}
+EXPORT_SYMBOL(cmdq_rec_flush_async);
+
+void cmdq_rec_destroy(struct cmdq_rec *rec)
+{
+	kfree(rec->buf);
+	kfree(rec);
+}
+EXPORT_SYMBOL(cmdq_rec_destroy);
+
+static int cmdq_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct resource *res;
+	struct cmdq *cmdq;
+	int err;
+
+	cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
+	if (!cmdq)
+		return -ENOMEM;
+	cmdq->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	cmdq->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(cmdq->base)) {
+		dev_err(dev, "failed to ioremap gce\n");
+		return PTR_ERR(cmdq->base);
+	}
+
+	cmdq->irq = irq_of_parse_and_map(node, 0);
+	if (!cmdq->irq) {
+		dev_err(dev, "failed to get irq\n");
+		return -EINVAL;
+	}
+
+	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
+		dev, cmdq->base, cmdq->irq);
+
+	/* init cmdq and save to device private data */
+	err = cmdq_initialize(cmdq);
+	if (err < 0) {
+		dev_err(dev, "failed to init cmdq\n");
+		return err;
+	}
+	platform_set_drvdata(pdev, cmdq);
+
+	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
+			       CMDQ_DRIVER_DEVICE_NAME, cmdq);
+	if (err < 0) {
+		dev_err(dev, "failed to register ISR (%d)\n", err);
+		goto fail;
+	}
+
+	cmdq->clock = devm_clk_get(dev, CMDQ_CLK_NAME);
+	if (IS_ERR(cmdq->clock)) {
+		dev_err(dev, "failed to get clk:%s\n", CMDQ_CLK_NAME);
+		err = PTR_ERR(cmdq->clock);
+		goto fail;
+	}
+	return 0;
+
+fail:
+	cmdq_remove(pdev);
+	return err;
+}
+
+static const struct of_device_id cmdq_of_ids[] = {
+	{.compatible = "mediatek,mt8173-gce",},
+	{}
+};
+
+static struct platform_driver cmdq_drv = {
+	.probe = cmdq_probe,
+	.remove = cmdq_remove,
+	.driver = {
+		.name = CMDQ_DRIVER_DEVICE_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = cmdq_of_ids,
+	}
+};
+
+builtin_platform_driver(cmdq_drv);
diff --git a/include/soc/mediatek/cmdq.h b/include/soc/mediatek/cmdq.h
new file mode 100644
index 0000000..60eef3d
--- /dev/null
+++ b/include/soc/mediatek/cmdq.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_CMDQ_H__
+#define __MTK_CMDQ_H__
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+enum cmdq_eng {
+	CMDQ_ENG_DISP_AAL,
+	CMDQ_ENG_DISP_COLOR0,
+	CMDQ_ENG_DISP_COLOR1,
+	CMDQ_ENG_DISP_DPI0,
+	CMDQ_ENG_DISP_DSI0,
+	CMDQ_ENG_DISP_DSI1,
+	CMDQ_ENG_DISP_GAMMA,
+	CMDQ_ENG_DISP_OD,
+	CMDQ_ENG_DISP_OVL0,
+	CMDQ_ENG_DISP_OVL1,
+	CMDQ_ENG_DISP_PWM0,
+	CMDQ_ENG_DISP_PWM1,
+	CMDQ_ENG_DISP_RDMA0,
+	CMDQ_ENG_DISP_RDMA1,
+	CMDQ_ENG_DISP_RDMA2,
+	CMDQ_ENG_DISP_UFOE,
+	CMDQ_ENG_DISP_WDMA0,
+	CMDQ_ENG_DISP_WDMA1,
+	CMDQ_ENG_MAX,
+};
+
+/* events for CMDQ and display */
+enum cmdq_event {
+	/* Display start of frame(SOF) events */
+	CMDQ_EVENT_DISP_OVL0_SOF = 11,
+	CMDQ_EVENT_DISP_OVL1_SOF = 12,
+	CMDQ_EVENT_DISP_RDMA0_SOF = 13,
+	CMDQ_EVENT_DISP_RDMA1_SOF = 14,
+	CMDQ_EVENT_DISP_RDMA2_SOF = 15,
+	CMDQ_EVENT_DISP_WDMA0_SOF = 16,
+	CMDQ_EVENT_DISP_WDMA1_SOF = 17,
+	/* Display end of frame(EOF) events */
+	CMDQ_EVENT_DISP_OVL0_EOF = 39,
+	CMDQ_EVENT_DISP_OVL1_EOF = 40,
+	CMDQ_EVENT_DISP_RDMA0_EOF = 41,
+	CMDQ_EVENT_DISP_RDMA1_EOF = 42,
+	CMDQ_EVENT_DISP_RDMA2_EOF = 43,
+	CMDQ_EVENT_DISP_WDMA0_EOF = 44,
+	CMDQ_EVENT_DISP_WDMA1_EOF = 45,
+	/* Mutex end of frame(EOF) events */
+	CMDQ_EVENT_MUTEX0_STREAM_EOF = 53,
+	CMDQ_EVENT_MUTEX1_STREAM_EOF = 54,
+	CMDQ_EVENT_MUTEX2_STREAM_EOF = 55,
+	CMDQ_EVENT_MUTEX3_STREAM_EOF = 56,
+	CMDQ_EVENT_MUTEX4_STREAM_EOF = 57,
+	/* Display underrun events */
+	CMDQ_EVENT_DISP_RDMA0_UNDERRUN = 63,
+	CMDQ_EVENT_DISP_RDMA1_UNDERRUN = 64,
+	CMDQ_EVENT_DISP_RDMA2_UNDERRUN = 65,
+	/* Keep this at the end of HW events */
+	CMDQ_MAX_HW_EVENT_COUNT = 260,
+};
+
+struct cmdq_cb_data {
+	bool	err;
+	void	*data;
+};
+
+typedef int (*cmdq_async_flush_cb)(struct cmdq_cb_data data);
+
+struct cmdq_task;
+struct cmdq;
+
+struct cmdq_rec {
+	struct cmdq		*cmdq;
+	u64			engine_flag;
+	size_t			command_size;
+	void			*buf;
+	size_t			buf_size;
+	bool			finalized;
+};
+
+struct cmdq_base {
+	int	subsys;
+	u32	base;
+};
+
+/**
+ * cmdq_register_device() - register device which needs CMDQ
+ * @dev:		device
+ *
+ * Return: cmdq_base pointer or NULL for failed
+ */
+struct cmdq_base *cmdq_register_device(struct device *dev);
+
+/**
+ * cmdq_rec_create() - create command queue record
+ * @dev:		device
+ * @engine_flag:	command queue engine flag
+ * @rec_ptr:		command queue record pointer to retrieve cmdq_rec
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_create(struct device *dev, u64 engine_flag,
+		    struct cmdq_rec **rec_ptr);
+
+/**
+ * cmdq_rec_write() - append write command to the command queue record
+ * @rec:	the command queue record
+ * @value:	the specified target register value
+ * @base:	the command queue base
+ * @offset:	register offset from module base
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_write(struct cmdq_rec *rec, u32 value,
+		   struct cmdq_base *base, u32 offset);
+
+/**
+ * cmdq_rec_write_mask() - append write command with mask to the command
+ *			   queue record
+ * @rec:	the command queue record
+ * @value:	the specified target register value
+ * @base:	the command queue base
+ * @offset:	register offset from module base
+ * @mask:	the specified target register mask
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
+			struct cmdq_base *base, u32 offset, u32 mask);
+
+/**
+ * cmdq_rec_wfe() - append wait for event command to the command queue record
+ * @rec:	the command queue record
+ * @event:	the desired event type to "wait and CLEAR"
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event);
+
+/**
+ * cmdq_rec_clear_event() - append clear event command to the command queue
+ *			    record
+ * @rec:	the command queue record
+ * @event:	the desired event to be cleared
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event);
+
+/**
+ * cmdq_rec_flush() - trigger CMDQ to execute the recorded commands
+ * @rec:	the command queue record
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ * Trigger CMDQ to execute the recorded commands. Note that this is a
+ * synchronous flush function. When the function returned, the recorded
+ * commands have been done.
+ */
+int cmdq_rec_flush(struct cmdq_rec *rec);
+
+/**
+ * cmdq_rec_flush_async() - trigger CMDQ to asynchronously execute the recorded
+ *			    commands and call back after ISR is finished
+ * @rec:	the command queue record
+ * @cb:		called in the end of CMDQ ISR
+ * @data:	this data will pass back to cb
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ * Trigger CMDQ to asynchronously execute the recorded commands and call back
+ * after ISR is finished. Note that this is an ASYNC function. When the function
+ * returned, it may or may not be finished. The ISR callback function is called
+ * in the end of ISR.
+ */
+int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
+			 void *data);
+
+/**
+ * cmdq_rec_destroy() - destroy command queue record
+ * @rec:	the command queue record
+ */
+void cmdq_rec_destroy(struct cmdq_rec *rec);
+
+#endif	/* __MTK_CMDQ_H__ */
-- 
1.9.1



From u.kleine-koenig at pengutronix.de  Thu May 12 00:15:42 2016
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Thu, 12 May 2016 09:15:42 +0200
Subject: [RFC] Reset pins of phys and their representation in a device tree
Message-ID: <20160512071542.GC30822@pengutronix.de>

Hello,

I have a machine here where the reset pin of the phy is connected to a
GPIO.

There are different possibilities available today to handle this
situation, here are the ones I'm aware of:

 - Use a gpio-hog to set the reset gpio to non-active
   This might result in dependency problems (and that's what I am
   currently faced with) because there is no connection in the device
   tree between the hog and the phy.

 - [Documentation/devicetree/bindings/net/fsl-fec.txt]
   The fec node supports properties

	phy-reset-gpios = <&gpio2 14 0>;
	phy-reset-duration = <200> /* milliseconds */;

   Something similar exists in TI's vendor kernel
   (http://git.ti.com/ti-linux-kernel/ti-linux-kernel/commit/17d192b999ee904ced223c16cef76111a51c461b)
   with different (and IMHO bader) naming.
   This is the wrong place to specify the gpios; they shouldn't be in the
   mac's node, but in a phy node instead.

So what I actually want is to put the gpio specification in the right
place and let it look as follows:

	mymdiobus {
		[...]
		myfirstphy: ethernet-phy at 0 {
			compatible = "ethernet-phy-ieee802.3-c22";
			reg = <0>;

			reset-gpios = <&gpio2 14 0>;
			reset-duration-ms = <200>;
		};

		mysecondphy: ethernet-phy at 2 {
			compatible = "ethernet-phy-ieee802.3-c22";
			reg = <2>;

			reset-gpios = <&gpio3 10 0>;
			reset-duration-ms = <200>;
		};
	};

And with this we could defer probe of &myfirstphy if &gpio2 isn't
available yet.

Does this sound sensible? Does something like that already exist which I
missed? Any further ideas/comments?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From hs.liao at mediatek.com  Thu May 12 00:13:29 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Thu, 12 May 2016 15:13:29 +0800
Subject: [PATCH v6 3/4] arm64: dts: mt8173: Add GCE node
In-Reply-To: <1463037210-863-1-git-send-email-hs.liao@mediatek.com>
References: <1463037210-863-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1463037210-863-4-git-send-email-hs.liao@mediatek.com>

This patch adds the device node of the GCE hardware for CMDQ module.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index eab7efc..63d1718 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -300,6 +300,14 @@
 			#clock-cells = <1>;
 		};
 
+		gce: gce at 10212000 {
+			compatible = "mediatek,mt8173-gce";
+			reg = <0 0x10212000 0 0x1000>;
+			interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>;
+			clocks = <&infracfg CLK_INFRA_GCE>;
+			clock-names = "gce";
+		};
+
 		gic: interrupt-controller at 10220000 {
 			compatible = "arm,gic-400";
 			#interrupt-cells = <3>;
-- 
1.9.1



From hs.liao at mediatek.com  Thu May 12 00:13:30 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Thu, 12 May 2016 15:13:30 +0800
Subject: [PATCH v6 4/4] CMDQ: suspend/resume protection
In-Reply-To: <1463037210-863-1-git-send-email-hs.liao@mediatek.com>
References: <1463037210-863-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1463037210-863-5-git-send-email-hs.liao@mediatek.com>

Add suspend/resume protection mechanism to prevent active task(s) in
suspend.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
---
 drivers/soc/mediatek/mtk-cmdq.c | 266 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 254 insertions(+), 12 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
index 72afc3f..ab67a88 100644
--- a/drivers/soc/mediatek/mtk-cmdq.c
+++ b/drivers/soc/mediatek/mtk-cmdq.c
@@ -40,6 +40,7 @@
 #define CMDQ_CLK_NAME			"gce"
 
 #define CMDQ_CURR_IRQ_STATUS_OFFSET	0x010
+#define CMDQ_CURR_LOADED_THR_OFFSET	0x018
 #define CMDQ_THR_SLOT_CYCLES_OFFSET	0x030
 
 #define CMDQ_THR_BASE			0x100
@@ -134,6 +135,7 @@ enum cmdq_code {
 enum cmdq_task_state {
 	TASK_STATE_WAITING,	/* allocated but waiting for available thread */
 	TASK_STATE_BUSY,	/* task running on a thread */
+	TASK_STATE_KILLED,	/* task process being killed */
 	TASK_STATE_ERROR,	/* task execution error */
 	TASK_STATE_DONE,	/* task finished */
 };
@@ -169,6 +171,8 @@ struct cmdq_thread {
 
 struct cmdq {
 	struct device		*dev;
+	struct notifier_block	pm_notifier;
+
 	void __iomem		*base;
 	u32			irq;
 
@@ -186,9 +190,12 @@ struct cmdq {
 
 	struct cmdq_thread	thread[CMDQ_THR_MAX_COUNT];
 	struct mutex		task_mutex;	/* for task list */
+	atomic_t		thread_usage;
 	spinlock_t		exec_lock;	/* for exec task */
 	wait_queue_head_t	thread_dispatch_queue;
 	struct clk		*clock;
+	atomic_t		suspending;
+	bool			suspended;
 };
 
 struct cmdq_subsys {
@@ -241,14 +248,24 @@ static int cmdq_eng_get_thread(u64 flag)
 		return CMDQ_THR_DISP_MISC_IDX;
 }
 
-static void cmdq_task_release_internal(struct cmdq_task *task)
+static void cmdq_task_release_unlocked(struct cmdq_task *task)
 {
 	struct cmdq *cmdq = task->cmdq;
 
-	mutex_lock(&cmdq->task_mutex);
+	/* This func should be inside cmdq->task_mutex mutex */
+	lockdep_assert_held(&cmdq->task_mutex);
+
 	dma_free_coherent(cmdq->dev, task->command_size, task->va_base,
 			  task->mva_base);
 	kmem_cache_free(cmdq->task_cache, task);
+}
+
+static void cmdq_task_release_internal(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+
+	mutex_lock(&cmdq->task_mutex);
+	cmdq_task_release_unlocked(task);
 	mutex_unlock(&cmdq->task_mutex);
 }
 
@@ -300,6 +317,7 @@ static struct cmdq_thread *cmdq_thread_get(struct cmdq *cmdq, int tid)
 	struct cmdq_thread *thread = &cmdq->thread[tid];
 
 	cmdq_clk_enable(cmdq);
+	atomic_inc(&cmdq->thread_usage);
 	return thread;
 }
 
@@ -308,6 +326,7 @@ static void cmdq_thread_put(struct cmdq *cmdq, struct cmdq_thread *thread)
 	if (WARN_ON(thread == NULL))
 		return;
 	cmdq_clk_disable(cmdq);
+	atomic_dec(&cmdq->thread_usage);
 }
 
 static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
@@ -580,6 +599,18 @@ static void cmdq_handle_irq(struct cmdq *cmdq, int tid)
 	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
 }
 
+static int cmdq_resumed_notifier(struct cmdq *cmdq)
+{
+	/*
+	 * during suspended, there may be queued tasks.
+	 * we should process them if any.
+	 */
+	queue_work(cmdq->task_consume_wq,
+		   &cmdq->task_consume_wait_queue_item);
+
+	return 0;
+}
+
 static void cmdq_consume_waiting_list(struct work_struct *work)
 {
 	struct cmdq *cmdq = container_of(work, struct cmdq,
@@ -591,6 +622,12 @@ static void cmdq_consume_waiting_list(struct work_struct *work)
 			      BIT(CMDQ_THR_DISP_SUB_IDX) |
 			      BIT(CMDQ_THR_DISP_MISC_IDX);
 
+	/* do not execute any task after suspended */
+	if (cmdq->suspended) {
+		dev_warn(dev, "task is consumed after suspended\n");
+		return;
+	}
+
 	mutex_lock(&cmdq->task_mutex);
 
 	if (list_empty(&cmdq->task_wait_list)) {
@@ -740,6 +777,14 @@ static int cmdq_task_wait_result(struct cmdq_task *task)
 	unsigned long flags;
 
 	spin_lock_irqsave(&cmdq->exec_lock, flags);
+
+	/* suspending, so just return */
+	if (atomic_read(&cmdq->suspending) &&
+	    task->task_state == TASK_STATE_KILLED) {
+		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+		return 0;
+	}
+
 	if (task->task_state != TASK_STATE_DONE)
 		err = cmdq_task_handle_error_result(task);
 	if (thread->task_count <= 0)
@@ -748,6 +793,18 @@ static int cmdq_task_wait_result(struct cmdq_task *task)
 	return err;
 }
 
+static void cmdq_lock_task_mutex(struct cmdq *cmdq)
+{
+	if (!atomic_read(&cmdq->suspending))
+		mutex_lock(&cmdq->task_mutex);
+}
+
+static void cmdq_unlock_task_mutex(struct cmdq *cmdq)
+{
+	if (!atomic_read(&cmdq->suspending))
+		mutex_unlock(&cmdq->task_mutex);
+}
+
 static int cmdq_task_wait_done(struct cmdq_task *task)
 {
 	struct cmdq *cmdq = task->cmdq;
@@ -761,7 +818,7 @@ static int cmdq_task_wait_done(struct cmdq_task *task)
 			cmdq->thread_dispatch_queue,
 			task->thread, timeout);
 	if (!wait_q) {
-		mutex_lock(&cmdq->task_mutex);
+		cmdq_lock_task_mutex(cmdq);
 		/* Check if task was just consumed. */
 		if (!task->thread) {
 			dev_err(dev,
@@ -772,11 +829,11 @@ static int cmdq_task_wait_done(struct cmdq_task *task)
 			 * so it won't be consumed in the future.
 			 */
 			list_del_init(&task->list_entry);
-			mutex_unlock(&cmdq->task_mutex);
+			cmdq_unlock_task_mutex(cmdq);
 			return -EINVAL;
 		}
 		/* valid thread, so we keep going */
-		mutex_unlock(&cmdq->task_mutex);
+		cmdq_unlock_task_mutex(cmdq);
 	}
 
 	/* wait for execution */
@@ -797,7 +854,9 @@ static int cmdq_task_wait_and_release(struct cmdq_task *task)
 
 	/* release regardless of success or not */
 	cmdq_thread_put(task->cmdq, task->thread);
-	cmdq_task_release_internal(task);
+	if (!(atomic_read(&task->cmdq->suspending) &&
+	      task->task_state == TASK_STATE_KILLED))
+		cmdq_task_release_internal(task);
 	return err;
 }
 
@@ -823,9 +882,22 @@ static void cmdq_auto_release(struct work_struct *work_item)
 			   &cmdq->task_consume_wait_queue_item);
 }
 
-static void cmdq_task_auto_release(struct cmdq_task *task)
+static void cmdq_task_auto_release(struct cmdq *cmdq, struct cmdq_task *task)
 {
-	struct cmdq *cmdq = task->cmdq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+
+	if (atomic_read(&cmdq->suspending) || cmdq->suspended) {
+		/*
+		 * This means system is suspened between
+		 * cmdq_task_submit_async() and cmdq_task_auto_release(),
+		 * so return immediately.
+		 * This task should be forced to remove by suspend flow.
+		 */
+		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+		return;
+	}
 
 	/*
 	 * the work item is embeded in task already
@@ -833,6 +905,8 @@ static void cmdq_task_auto_release(struct cmdq_task *task)
 	 */
 	INIT_WORK(&task->auto_release_work, cmdq_auto_release);
 	queue_work(cmdq->task_auto_release_wq, &task->auto_release_work);
+
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
 }
 
 static int cmdq_task_submit(struct cmdq_command *command)
@@ -852,7 +926,7 @@ static int cmdq_task_submit(struct cmdq_command *command)
 	return err;
 }
 
-static int cmdq_remove(struct platform_device *pdev)
+static void cmdq_deinitialize(struct platform_device *pdev)
 {
 	struct cmdq *cmdq = platform_get_drvdata(pdev);
 	struct cmdq_task *task, *tmp;
@@ -872,7 +946,6 @@ static int cmdq_remove(struct platform_device *pdev)
 
 	kmem_cache_destroy(cmdq->task_cache);
 	cmdq->task_cache = NULL;
-	return 0;
 }
 
 static irqreturn_t cmdq_irq_handler(int irq, void *dev)
@@ -1094,6 +1167,13 @@ int cmdq_rec_flush(struct cmdq_rec *rec)
 	int err;
 	struct cmdq_command command;
 
+	/* do not allow flush after suspending or suspended */
+	if (atomic_read(&rec->cmdq->suspending) || rec->cmdq->suspended) {
+		dev_err(rec->cmdq->dev,
+			"%s is called after suspending\n", __func__);
+		return -EPERM;
+	}
+
 	err = cmdq_rec_fill_command(rec, &command);
 	if (err < 0)
 		return err;
@@ -1109,6 +1189,13 @@ int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
 	struct cmdq_task *task;
 	struct cmdq_task_cb task_cb;
 
+	/* do not allow flush after suspending or suspended */
+	if (atomic_read(&rec->cmdq->suspending) || rec->cmdq->suspended) {
+		dev_err(rec->cmdq->dev,
+			"%s is called after suspending\n", __func__);
+		return -EPERM;
+	}
+
 	err = cmdq_rec_fill_command(rec, &command);
 	if (err < 0)
 		return err;
@@ -1117,7 +1204,13 @@ int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
 	err = cmdq_task_submit_async(&command, &task, &task_cb);
 	if (err < 0)
 		return err;
-	cmdq_task_auto_release(task);
+
+	/*
+	 * Task could be released in suspend flow,
+	 * so we have to pass cmdq as parameter.
+	 */
+	cmdq_task_auto_release(rec->cmdq, task);
+
 	return 0;
 }
 EXPORT_SYMBOL(cmdq_rec_flush_async);
@@ -1129,6 +1222,126 @@ void cmdq_rec_destroy(struct cmdq_rec *rec)
 }
 EXPORT_SYMBOL(cmdq_rec_destroy);
 
+static int cmdq_pm_notifier_cb(struct notifier_block *nb, unsigned long event,
+			       void *ptr)
+{
+	struct cmdq *cmdq = container_of(nb, struct cmdq, pm_notifier);
+
+	switch (event) {
+	case PM_SUSPEND_PREPARE:
+		/*
+		 * Going to suspend the system
+		 * The next stage is freeze process.
+		 * We will queue all request in suspend callback,
+		 * so don't care this stage
+		 */
+		return NOTIFY_DONE;
+	case PM_POST_SUSPEND:
+		/*
+		 * processes had resumed in previous stage
+		 * (system resume callback)
+		 * resume CMDQ driver to execute.
+		 */
+		cmdq_resumed_notifier(cmdq);
+		return NOTIFY_OK;
+	default:
+		return NOTIFY_DONE;
+	}
+	return NOTIFY_DONE;
+}
+
+static int cmdq_suspend(struct device *dev)
+{
+	struct cmdq *cmdq = dev_get_drvdata(dev);
+	u32 exec_threads = readl(cmdq->base + CMDQ_CURR_LOADED_THR_OFFSET);
+	int ref_count;
+	unsigned long flags;
+	struct cmdq_thread *thread;
+	struct cmdq_task *task, *tmp;
+	int i;
+
+	atomic_set(&cmdq->suspending, 1);
+
+	/*
+	 * lock to prevent cmdq_consume_waiting_list() and
+	 * cmdq_acquire_task(), i.e. no new active tasks
+	 */
+	mutex_lock(&cmdq->task_mutex);
+
+	ref_count = atomic_read(&cmdq->thread_usage);
+	if (ref_count <= 0 && !(exec_threads & CMDQ_THR_EXECUTING))
+		goto exit;
+
+	dev_err(dev, "suspend: kill running, tasks.\n");
+	dev_err(dev, "threads: 0x%08x, ref:%d\n", exec_threads, ref_count);
+
+	/*
+	 * We need to ensure the system is ready to suspend,
+	 * so kill all running CMDQ tasks and release HW engines.
+	 */
+
+	/* remove all active task from thread and disable thread */
+	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
+		thread = &cmdq->thread[i];
+
+		if (thread->task_count <= 0)
+			continue;
+
+		cmdq_clk_enable(cmdq); /* prevent clk disable in release flow */
+		cmdq_thread_suspend(cmdq, thread);
+
+		list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
+					 list_entry) {
+			bool already_done = false;
+
+			spin_lock_irqsave(&cmdq->exec_lock, flags);
+			if (task->task_state == TASK_STATE_BUSY) {
+				/* still wait_event */
+				list_del(&task->list_entry);
+				task->task_state = TASK_STATE_KILLED;
+			} else {
+				/* almost finish its work */
+				already_done = true;
+			}
+			spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+
+			/*
+			 * TASK_STATE_KILLED will unlock
+			 * wait_event_timeout in cmdq_task_wait_done(),
+			 * so flush_work to wait auto release flow.
+			 *
+			 * We don't know processes running order,
+			 * so call cmdq_task_release_unlocked() here to
+			 * prevent releasing task before flush_work, and
+			 * also to prevent deadlock of task_mutex.
+			 */
+			if (!already_done) {
+				flush_work(&task->auto_release_work);
+				cmdq_task_release_unlocked(task);
+			}
+		}
+
+		cmdq_thread_resume(thread);
+		cmdq_thread_disable(cmdq, &cmdq->thread[i]);
+		cmdq_clk_disable(cmdq);
+	}
+
+exit:
+	cmdq->suspended = true;
+	mutex_unlock(&cmdq->task_mutex);
+	atomic_set(&cmdq->suspending, 0);
+	/* ALWAYS allow suspend */
+	return 0;
+}
+
+static int cmdq_resume(struct device *dev)
+{
+	struct cmdq *cmdq = dev_get_drvdata(dev);
+
+	cmdq->suspended = false;
+	return 0;
+}
+
 static int cmdq_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -1179,13 +1392,41 @@ static int cmdq_probe(struct platform_device *pdev)
 		err = PTR_ERR(cmdq->clock);
 		goto fail;
 	}
+
+	/* hibernation and suspend events */
+	cmdq->pm_notifier.notifier_call = cmdq_pm_notifier_cb;
+	cmdq->pm_notifier.priority = 5;
+	err = register_pm_notifier(&cmdq->pm_notifier);
+	if (err < 0) {
+		dev_err(dev, "failed to register cmdq pm notifier\n");
+		goto fail;
+	}
+
 	return 0;
 
 fail:
-	cmdq_remove(pdev);
+	cmdq_deinitialize(pdev);
 	return err;
 }
 
+static int cmdq_remove(struct platform_device *pdev)
+{
+	struct cmdq *cmdq = platform_get_drvdata(pdev);
+	int err;
+
+	err = unregister_pm_notifier(&cmdq->pm_notifier);
+	if (err < 0)
+		dev_err(&pdev->dev, "unregister pm notifier failed\n");
+
+	cmdq_deinitialize(pdev);
+	return 0;
+}
+
+static const struct dev_pm_ops cmdq_pm_ops = {
+	.suspend = cmdq_suspend,
+	.resume = cmdq_resume,
+};
+
 static const struct of_device_id cmdq_of_ids[] = {
 	{.compatible = "mediatek,mt8173-gce",},
 	{}
@@ -1197,6 +1438,7 @@ static struct platform_driver cmdq_drv = {
 	.driver = {
 		.name = CMDQ_DRIVER_DEVICE_NAME,
 		.owner = THIS_MODULE,
+		.pm = &cmdq_pm_ops,
 		.of_match_table = cmdq_of_ids,
 	}
 };
-- 
1.9.1



From hs.liao at mediatek.com  Thu May 12 00:13:26 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Thu, 12 May 2016 15:13:26 +0800
Subject: [PATCH v6 0/4] Mediatek MT8173 CMDQ support
Message-ID: <1463037210-863-1-git-send-email-hs.liao@mediatek.com>


Hi,

This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used
to help read/write registers with critical time limitation, such as
updating display configuration during the vblank. It controls Global
Command Engine (GCE) hardware to achieve this requirement.

These patches have a build dependency on top of v4.6-rc1.

Changes since v5:
 - keep order of display tasks
 - use list instead of arrary for thread's tasks management
 - remove task_active_list
 - prevent deadlock in suspend/resume flow
 - prevent to flush in both suspending and suspended
 - prevent to add auto release work after suspending or suspended
 - merge cmdq_task_create() into cmdq_task_acquire()
 - remove cmdq_task_free_command_buffer() and call dma_free_coherent()
   directly

Best regards,
HS Liao

HS Liao (4):
  dt-bindings: soc: Add documentation for the MediaTek GCE unit
  CMDQ: Mediatek CMDQ driver
  arm64: dts: mt8173: Add GCE node
  CMDQ: suspend/resume protection

 .../devicetree/bindings/soc/mediatek/gce.txt       |   34 +
 arch/arm64/boot/dts/mediatek/mt8173.dtsi           |    8 +
 drivers/soc/mediatek/Kconfig                       |   10 +
 drivers/soc/mediatek/Makefile                      |    1 +
 drivers/soc/mediatek/mtk-cmdq.c                    | 1446 ++++++++++++++++++++
 include/soc/mediatek/cmdq.h                        |  197 +++
 6 files changed, 1696 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/gce.txt
 create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
 create mode 100644 include/soc/mediatek/cmdq.h

-- 
1.9.1




From chunfeng.yun at mediatek.com  Thu May 12 00:24:04 2016
From: chunfeng.yun at mediatek.com (chunfeng yun)
Date: Thu, 12 May 2016 15:24:04 +0800
Subject: [PATCH 3/6] dt-bindings: mtu3: add devicetree bindings
In-Reply-To: <20160511145409.GA23042@rob-hp-laptop>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462868614-20602-4-git-send-email-chunfeng.yun@mediatek.com>
 <20160511145409.GA23042@rob-hp-laptop>
Message-ID: <1463037844.11651.118.camel@mhfsdcap03>

Hi,

On Wed, 2016-05-11 at 09:54 -0500, Rob Herring wrote:
> On Tue, May 10, 2016 at 04:23:31PM +0800, Chunfeng Yun wrote:
> > add a DT binding doc for MediaTek USB3 DRD driver
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
> > ---
> >  Documentation/devicetree/bindings/usb/mtu3.txt |   86 ++++++++++++++++++++++++
> >  1 file changed, 86 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/usb/mtu3.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/usb/mtu3.txt b/Documentation/devicetree/bindings/usb/mtu3.txt
> > new file mode 100644
> > index 0000000..ff142a5
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/usb/mtu3.txt
> > @@ -0,0 +1,86 @@
> > +The device node for Mediatek USB3.0 DRD controller
> > +
> > +Required properties:
> > + - compatible : should be "mediatek,mt8173-mtu3"
> > + - reg : specifies physical base address and size of the registers
> > + - reg-names: should be "mac" for device IP and "ippc" for IP port control
> > + - interrupts : interrupt used by the device IP
> > + - power-domains : a phandle to USB power domain node to control USB's
> > +	mtcmos
> > + - vusb33-supply : regulator of USB avdd3.3v
> > + - clocks : a list of phandle + clock-specifier pairs, one for each
> > +	entry in clock-names
> > + - clock-names : must contain "sys_ck" for clock of controller;
> > +	"wakeup_deb_p0" and "wakeup_deb_p1" are optional, they are
> > +	depends on "mediatek,enable-wakeup"
> > + - phys : a list of phandle + phy specifier pairs
> 
> How many?
It depends on implementation; there are two phys on mt8173 platform

> 
> > + - dr_mode : should be one of "host", "peripheral" or "otg",
> > +	refer to usb/generic.txt
> > +
> > +Optional properties:
> > + - #address-cells, #size-cells : should be '2' if the device has sub-nodes
> > +	with 'reg' property
> > + - ranges : allows valid 1:1 translation between child's address space and
> > +	parent's address space
> > + - extcon : external connector for vbus and idpin changes detection, needed
> > +	when supports dual-role mode.
> > + - vbus-supply : reference to the VBUS regulator, needed when supports
> > +	dual-role mode.
> > + - pinctl-names : a pinctrl state named "default" must be defined,
> > +	"id_float" and "id_ground" are optinal which depends on
> > +	"mediatek,enable-manual-drd"
> > + - pinctrl-0 : pin control group
> > +	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
> > +
> > + - maximum-speed : valid arguments are "super-speed", "high-speed" and
> > +	"full-speed"; refer to usb/generic.txt
> > + - mediatek,enable-wakeup : supports ip sleep wakeup used by host mode
> > + - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup
> > +	control register, it depends on "mediatek,enable-wakeup".
> 
> There is a standard wake-up source binding. That assumes asserting the 
> device's irq (or one of the irqs) will cause wake-up.
> 
> The syscon-wakeup should probably get implemented as a stacked 
> irqdomain.
> 
Syscon-wakeup is used to control which usb wakeup mode we want to use,
such as ip sleep(usb suspend/resume signal), or line state(changes of D
+/-). And it doesn't trigger device's interrupt, so can't implement
device's irq to wake up system.

> > + - mediatek,enable-manual-drd : supports manual dual-role switch by sysfs
> > +	interface; only used when receptacle is TYPE-A and also wants to support
> > +	dual-role mode.
> 
> sysfs is a Linux detail that doesn't apply to the binding. Does the 
> property mean "the IP block supports or doesn't support switching"  or 
> "I want to enable switching feature". Only the former belongs in DT.
> 
It is the former case, and has little relation with sysfs interface.
I will modify it later, sorry for my unclear description. 

> As far as the sysfs interface, it should be generic, not Mediatek 
> specific.
> 
> > +
> > +Sub-nodes:
> > +The xhci should be added as subnode to mtu3 as shown in the following example
> > +if host mode is enabled. The DT binding details of xhci can be found in:
> > +Documentation/devicetree/bindings/usb/mt8173-xhci.txt
> 
> Is XHCI really a sub-block? It seems mostly independent.
Yes, the mtk's usb3 controller contains three parts: mu3d IP, xHCI IP
and IPPC (IP power and control).

> 
> > +
> > +Example:
> > +ssusb: usb at 11271000 {
> > +	compatible = "mediatek,mt8173-mtu3";
> > +	reg = <0 0x11271000 0 0x3000>,
> > +	      <0 0x11280700 0 0x0100>;
> > +	reg-names = "mac", "ippc";
> > +	interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>;
> > +	phys = <&phy_port0 PHY_TYPE_USB3>,
> > +	       <&phy_port1 PHY_TYPE_USB2>;
> > +	power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
> > +	clocks = <&topckgen CLK_TOP_USB30_SEL>,
> > +		 <&pericfg CLK_PERI_USB0>,
> > +		 <&pericfg CLK_PERI_USB1>;
> > +	clock-names = "sys_ck",
> > +		      "wakeup_deb_p0",
> > +		      "wakeup_deb_p1";
> > +	vusb33-supply = <&mt6397_vusb_reg>;
> > +	vbus-supply = <&usb_p0_vbus>;
> > +	extcon = <&extcon_usb>;
> > +	dr_mode = "otg";
> > +	mediatek,enable-wakeup;
> > +	mediatek,syscon-wakeup = <&pericfg>;
> > +	#address-cells = <2>;
> > +	#size-cells = <2>;
> > +	ranges;
> > +	status = "disabled";
> > +
> > +	usb_host: xhci at 11270000 {
> > +		compatible = "mediatek,mt8173-xhci";
> > +		reg = <0 0x11270000 0 0x1000>;
> > +		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
> > +		power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
> > +		clocks = <&topckgen CLK_TOP_USB30_SEL>;
> > +		clock-names = "sys_ck";
> > +		vusb33-supply = <&mt6397_vusb_reg>;
> > +		status = "disabled";
> > +	};
> > +};
> > -- 
> > 1.7.9.5
> > 




From david.wu at rock-chips.com  Thu May 12 00:52:58 2016
From: david.wu at rock-chips.com (David Wu)
Date: Thu, 12 May 2016 15:52:58 +0800
Subject: [PATCH v9 0/8] add i2c driver supported for rk3399
Message-ID: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>

There are three points differert from others:
 - new method to caculate i2c timings for rk3399
 - pclk and function clk are separated at rk3399
 - add fast-plus mode supported for rk3399

David Wu (8):
  i2c: rk3x: add documentation to fields in "struct rk3x_i2c"
  i2c: rk3x: use struct "rk3x_i2c_calced_timings"
  i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd()
  i2c: rk3x: Change SoC data to not use array
  i2c: rk3x: Move spec timing data to "static const" structs
  dt-bindings: i2c: rk3x: add support for rk3399
  i2c: rk3x: add i2c support for rk3399 soc
  i2c: rk3x: support fast-mode plus for rk3399

 Documentation/devicetree/bindings/i2c/i2c-rk3x.txt |  16 +-
 drivers/i2c/busses/i2c-rk3x.c                      | 495 +++++++++++++++++----
 2 files changed, 432 insertions(+), 79 deletions(-)

-- 
1.9.1




From david.wu at rock-chips.com  Thu May 12 00:52:59 2016
From: david.wu at rock-chips.com (David Wu)
Date: Thu, 12 May 2016 15:52:59 +0800
Subject: [PATCH v9 1/8] i2c: rk3x: add documentation to fields in "struct
 rk3x_i2c"
In-Reply-To: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
References: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463039586-8134-2-git-send-email-david.wu@rock-chips.com>

Add kernel-doc documentation for the elements of the previously
undocumented struct rk3x_i2c.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Heiko Stuebner <heiko at sntech.de>
---
Change in v9:
- add commit description.

Change in v8:
- none

 drivers/i2c/busses/i2c-rk3x.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 80bed02..7e45d51 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -90,6 +90,26 @@ struct rk3x_i2c_soc_data {
 	int grf_offset;
 };
 
+/**
+ * struct rk3x_i2c - private data of the controller
+ * @adap: corresponding I2C adapter
+ * @dev: device for this controller
+ * @soc_data: related soc data struct
+ * @regs: virtual memory area
+ * @clk: clock of i2c bus
+ * @clk_rate_nb: i2c clk rate change notify
+ * @t: I2C known timing information
+ * @lock: spinlock for the i2c bus
+ * @wait: the waitqueue to wait for i2c transfer
+ * @busy: the condition for the event to wait for
+ * @msg: current i2c message
+ * @addr: addr of i2c slave device
+ * @mode: mode of i2c transfer
+ * @is_last_msg: flag determines whether it is the last msg in this transfer
+ * @state: state of i2c transfer
+ * @processed: byte length which has been send or received
+ * @error: error code for i2c transfer
+ */
 struct rk3x_i2c {
 	struct i2c_adapter adap;
 	struct device *dev;
@@ -116,7 +136,7 @@ struct rk3x_i2c {
 
 	/* I2C state machine */
 	enum rk3x_i2c_state state;
-	unsigned int processed; /* sent/received bytes */
+	unsigned int processed;
 	int error;
 };
 
-- 
1.9.1




From david.wu at rock-chips.com  Thu May 12 00:53:00 2016
From: david.wu at rock-chips.com (David Wu)
Date: Thu, 12 May 2016 15:53:00 +0800
Subject: [PATCH v9 2/8] i2c: rk3x: use struct "rk3x_i2c_calced_timings"
In-Reply-To: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
References: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463039586-8134-3-git-send-email-david.wu@rock-chips.com>

The "div_high" and "div_low" values are always used together.
Group them into a structure to make it easier to pass them
both around. This structure also provides a place for future
calculated timings.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
---
Change in v9:
- none

Change in v8:
- add commit description.

 drivers/i2c/busses/i2c-rk3x.c | 55 +++++++++++++++++++++++++------------------
 1 file changed, 32 insertions(+), 23 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 7e45d51..1e2677a 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -75,6 +75,16 @@ enum {
 #define WAIT_TIMEOUT      1000 /* ms */
 #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */
 
+/**
+ * struct rk3x_i2c_calced_timings:
+ * @div_low: Divider output for low
+ * @div_high: Divider output for high
+ */
+struct rk3x_i2c_calced_timings {
+	unsigned long div_low;
+	unsigned long div_high;
+};
+
 enum rk3x_i2c_state {
 	STATE_IDLE,
 	STATE_START,
@@ -454,9 +464,8 @@ out:
  * Calculate divider values for desired SCL frequency
  *
  * @clk_rate: I2C input clock rate
- * @t: Known I2C timing information.
- * @div_low: Divider output for low
- * @div_high: Divider output for high
+ * @t: Known I2C timing information
+ * @t_calc: Caculated rk3x private timings that would be written into regs
  *
  * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
  * a best-effort divider value is returned in divs. If the target rate is
@@ -464,8 +473,7 @@ out:
  */
 static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 			      struct i2c_timings *t,
-			      unsigned long *div_low,
-			      unsigned long *div_high)
+			      struct rk3x_i2c_calced_timings *t_calc)
 {
 	unsigned long spec_min_low_ns, spec_min_high_ns;
 	unsigned long spec_setup_start, spec_max_data_hold_ns;
@@ -572,8 +580,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 		 * Time needed to meet hold requirements is important.
 		 * Just use that.
 		 */
-		*div_low = min_low_div;
-		*div_high = min_high_div;
+		t_calc->div_low = min_low_div;
+		t_calc->div_high = min_high_div;
 	} else {
 		/*
 		 * We've got to distribute some time among the low and high
@@ -602,25 +610,25 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 
 		/* Give low the "ideal" and give high whatever extra is left */
 		extra_low_div = ideal_low_div - min_low_div;
-		*div_low = ideal_low_div;
-		*div_high = min_high_div + (extra_div - extra_low_div);
+		t_calc->div_low = ideal_low_div;
+		t_calc->div_high = min_high_div + (extra_div - extra_low_div);
 	}
 
 	/*
 	 * Adjust to the fact that the hardware has an implicit "+1".
 	 * NOTE: Above calculations always produce div_low > 0 and div_high > 0.
 	 */
-	*div_low = *div_low - 1;
-	*div_high = *div_high - 1;
+	t_calc->div_low--;
+	t_calc->div_high--;
 
 	/* Maximum divider supported by hw is 0xffff */
-	if (*div_low > 0xffff) {
-		*div_low = 0xffff;
+	if (t_calc->div_low > 0xffff) {
+		t_calc->div_low = 0xffff;
 		ret = -EINVAL;
 	}
 
-	if (*div_high > 0xffff) {
-		*div_high = 0xffff;
+	if (t_calc->div_high > 0xffff) {
+		t_calc->div_high = 0xffff;
 		ret = -EINVAL;
 	}
 
@@ -630,19 +638,21 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
 {
 	struct i2c_timings *t = &i2c->t;
-	unsigned long div_low, div_high;
+	struct rk3x_i2c_calced_timings calc;
 	u64 t_low_ns, t_high_ns;
 	int ret;
 
-	ret = rk3x_i2c_calc_divs(clk_rate, t, &div_low, &div_high);
+	ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
 	WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
 
 	clk_enable(i2c->clk);
-	i2c_writel(i2c, (div_high << 16) | (div_low & 0xffff), REG_CLKDIV);
+	i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
+		   REG_CLKDIV);
 	clk_disable(i2c->clk);
 
-	t_low_ns = div_u64(((u64)div_low + 1) * 8 * 1000000000, clk_rate);
-	t_high_ns = div_u64(((u64)div_high + 1) * 8 * 1000000000, clk_rate);
+	t_low_ns = div_u64(((u64)calc.div_low + 1) * 8 * 1000000000, clk_rate);
+	t_high_ns = div_u64(((u64)calc.div_high + 1) * 8 * 1000000000,
+			    clk_rate);
 	dev_dbg(i2c->dev,
 		"CLK %lukhz, Req %uns, Act low %lluns high %lluns\n",
 		clk_rate / 1000,
@@ -672,12 +682,11 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
 {
 	struct clk_notifier_data *ndata = data;
 	struct rk3x_i2c *i2c = container_of(nb, struct rk3x_i2c, clk_rate_nb);
-	unsigned long div_low, div_high;
+	struct rk3x_i2c_calced_timings calc;
 
 	switch (event) {
 	case PRE_RATE_CHANGE:
-		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t,
-				       &div_low, &div_high) != 0)
+		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &calc) != 0)
 			return NOTIFY_STOP;
 
 		/* scale up */
-- 
1.9.1




From david.wu at rock-chips.com  Thu May 12 00:53:01 2016
From: david.wu at rock-chips.com (David Wu)
Date: Thu, 12 May 2016 15:53:01 +0800
Subject: [PATCH v9 3/8] i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd()
In-Reply-To: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
References: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463039586-8134-4-git-send-email-david.wu@rock-chips.com>

rk3x_i2c_setup() gets called directly before rk3x_i2c_start(),
and the last thing in setup was to clean the IPD, so no reason
to do it at the beginning of start.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Heiko Stuebner <heiko at sntech.de>
---
Change in v9:
- modify commit message

Change in v8:
- none

 drivers/i2c/busses/i2c-rk3x.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 1e2677a..9eeb4e5 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -174,7 +174,6 @@ static void rk3x_i2c_start(struct rk3x_i2c *i2c)
 {
 	u32 val;
 
-	rk3x_i2c_clean_ipd(i2c);
 	i2c_writel(i2c, REG_INT_START, REG_IEN);
 
 	/* enable adapter with correct mode, send START condition */
-- 
1.9.1




From david.wu at rock-chips.com  Thu May 12 00:53:02 2016
From: david.wu at rock-chips.com (David Wu)
Date: Thu, 12 May 2016 15:53:02 +0800
Subject: [PATCH v9 4/8] i2c: rk3x: Change SoC data to not use array
In-Reply-To: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
References: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463039586-8134-5-git-send-email-david.wu@rock-chips.com>

Specifying the i2c SoC data in an array provides very little benefit and
gets unwieldly / confusing as the array grows since the next bit of code
needs to refer to elements in the array by their raw integral index.

Let's just create a single 'static const' structure for each SoC so that
we can refer to these structures by ID.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Heiko Stuebner <heiko at sntech.de>
Suggested-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
---
Change in v9:
- none

Change in v8:
- add commit description.

 drivers/i2c/busses/i2c-rk3x.c | 38 ++++++++++++++++++++++++++++++--------
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 9eeb4e5..d7a871f 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -864,17 +864,39 @@ static const struct i2c_algorithm rk3x_i2c_algorithm = {
 	.functionality		= rk3x_i2c_func,
 };
 
-static struct rk3x_i2c_soc_data soc_data[3] = {
-	{ .grf_offset = 0x154 }, /* rk3066 */
-	{ .grf_offset = 0x0a4 }, /* rk3188 */
-	{ .grf_offset = -1 },    /* no I2C switching needed */
+static const struct rk3x_i2c_soc_data rk3066_soc_data = {
+	.grf_offset = 0x154,
+};
+
+static const struct rk3x_i2c_soc_data rk3188_soc_data = {
+	.grf_offset = 0x0a4,
+};
+
+static const struct rk3x_i2c_soc_data rk3228_soc_data = {
+	.grf_offset = -1,
+};
+
+static const struct rk3x_i2c_soc_data rk3288_soc_data = {
+	.grf_offset = -1,
 };
 
 static const struct of_device_id rk3x_i2c_match[] = {
-	{ .compatible = "rockchip,rk3066-i2c", .data = (void *)&soc_data[0] },
-	{ .compatible = "rockchip,rk3188-i2c", .data = (void *)&soc_data[1] },
-	{ .compatible = "rockchip,rk3228-i2c", .data = (void *)&soc_data[2] },
-	{ .compatible = "rockchip,rk3288-i2c", .data = (void *)&soc_data[2] },
+	{
+		.compatible = "rockchip,rk3066-i2c",
+		.data = (void *)&rk3066_soc_data
+	},
+	{
+		.compatible = "rockchip,rk3188-i2c",
+		.data = (void *)&rk3188_soc_data
+	},
+	{
+		.compatible = "rockchip,rk3228-i2c",
+		.data = (void *)&rk3228_soc_data
+	},
+	{
+		.compatible = "rockchip,rk3288-i2c",
+		.data = (void *)&rk3288_soc_data
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, rk3x_i2c_match);
-- 
1.9.1




From david.wu at rock-chips.com  Thu May 12 00:57:09 2016
From: david.wu at rock-chips.com (David Wu)
Date: Thu, 12 May 2016 15:57:09 +0800
Subject: [PATCH v9 5/8] i2c: rk3x: Move spec timing data to "static const"
 structs
In-Reply-To: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
References: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463039829-8267-1-git-send-email-david.wu@rock-chips.com>

The i2c timing specs are really just constant data. There's no reason
to write code to init them, so move them out to structures. This not
only is a cleaner solution but it will reduce code duplication when we
introduce a new variant of rk3x_i2c_calc_divs() in a future patch.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Suggested-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
---
Change in v9:
- none

Changes in v8:
- add commit description.
- remove the spec values that were not needed, then
  introduce the additional values in the rk3399 patch. 

 drivers/i2c/busses/i2c-rk3x.c | 83 ++++++++++++++++++++++++++++---------------
 1 file changed, 55 insertions(+), 28 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index d7a871f..9791797 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -76,6 +76,34 @@ enum {
 #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */
 
 /**
+ * struct i2c_spec_values:
+ * @min_low_ns: min LOW period of the SCL clock
+ * @min_high_ns: min HIGH period of the SCL cloc
+ * @min_setup_start_ns: min set-up time for a repeated START conditio
+ * @max_data_hold_ns: max data hold time
+ */
+struct i2c_spec_values {
+	unsigned long min_low_ns;
+	unsigned long min_high_ns;
+	unsigned long min_setup_start_ns;
+	unsigned long max_data_hold_ns;
+};
+
+static const struct i2c_spec_values standard_mode_spec = {
+	.min_low_ns = 4700,
+	.min_high_ns = 4000,
+	.min_setup_start_ns = 4700,
+	.max_data_hold_ns = 3450,
+};
+
+static const struct i2c_spec_values fast_mode_spec = {
+	.min_low_ns = 1300,
+	.min_high_ns = 600,
+	.min_setup_start_ns = 600,
+	.max_data_hold_ns = 900,
+};
+
+/**
  * struct rk3x_i2c_calced_timings:
  * @div_low: Divider output for low
  * @div_high: Divider output for high
@@ -460,6 +488,21 @@ out:
 }
 
 /**
+ * Get timing values of I2C specification
+ *
+ * @speed: Desired SCL frequency
+ *
+ * Returns: Matched i2c spec values.
+ */
+static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
+{
+	if (speed <= 100000)
+		return &standard_mode_spec;
+	else
+		return &fast_mode_spec;
+}
+
+/**
  * Calculate divider values for desired SCL frequency
  *
  * @clk_rate: I2C input clock rate
@@ -474,10 +517,6 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 			      struct i2c_timings *t,
 			      struct rk3x_i2c_calced_timings *t_calc)
 {
-	unsigned long spec_min_low_ns, spec_min_high_ns;
-	unsigned long spec_setup_start, spec_max_data_hold_ns;
-	unsigned long data_hold_buffer_ns;
-
 	unsigned long min_low_ns, min_high_ns;
 	unsigned long max_low_ns, min_total_ns;
 
@@ -489,6 +528,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	unsigned long min_div_for_hold, min_total_div;
 	unsigned long extra_div, extra_low_div, ideal_low_div;
 
+	unsigned long data_hold_buffer_ns = 50;
+	const struct i2c_spec_values *spec;
 	int ret = 0;
 
 	/* Only support standard-mode and fast-mode */
@@ -511,22 +552,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	 *	 This is because the i2c host on Rockchip holds the data line
 	 *	 for half the low time.
 	 */
-	if (t->bus_freq_hz <= 100000) {
-		/* Standard-mode */
-		spec_min_low_ns = 4700;
-		spec_setup_start = 4700;
-		spec_min_high_ns = 4000;
-		spec_max_data_hold_ns = 3450;
-		data_hold_buffer_ns = 50;
-	} else {
-		/* Fast-mode */
-		spec_min_low_ns = 1300;
-		spec_setup_start = 600;
-		spec_min_high_ns = 600;
-		spec_max_data_hold_ns = 900;
-		data_hold_buffer_ns = 50;
-	}
-	min_high_ns = t->scl_rise_ns + spec_min_high_ns;
+	spec = rk3x_i2c_get_spec(t->bus_freq_hz);
+	min_high_ns = t->scl_rise_ns + spec->min_high_ns;
 
 	/*
 	 * Timings for repeated start:
@@ -536,14 +563,14 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	 * We need to account for those rules in picking our "high" time so
 	 * we meet tSU;STA and tHD;STA times.
 	 */
-	min_high_ns = max(min_high_ns,
-		DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start) * 1000, 875));
-	min_high_ns = max(min_high_ns,
-		DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start +
-			      t->sda_fall_ns + spec_min_high_ns), 2));
-
-	min_low_ns = t->scl_fall_ns + spec_min_low_ns;
-	max_low_ns = spec_max_data_hold_ns * 2 - data_hold_buffer_ns;
+	min_high_ns = max(min_high_ns, DIV_ROUND_UP(
+		(t->scl_rise_ns + spec->min_setup_start_ns) * 1000, 875));
+	min_high_ns = max(min_high_ns, DIV_ROUND_UP(
+		(t->scl_rise_ns + spec->min_setup_start_ns + t->sda_fall_ns +
+		spec->min_high_ns), 2));
+
+	min_low_ns = t->scl_fall_ns + spec->min_low_ns;
+	max_low_ns =  spec->max_data_hold_ns * 2 - data_hold_buffer_ns;
 	min_total_ns = min_low_ns + min_high_ns;
 
 	/* Adjust to avoid overflow */
-- 
1.9.1




From david.wu at rock-chips.com  Thu May 12 00:57:59 2016
From: david.wu at rock-chips.com (David Wu)
Date: Thu, 12 May 2016 15:57:59 +0800
Subject: [PATCH v9 6/8] dt-bindings: i2c: rk3x: add support for rk3399
In-Reply-To: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
References: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463039879-8318-1-git-send-email-david.wu@rock-chips.com>

The bus clock and function clock are separated at rk3399,
and others use one clock as the bus clock and function clock.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Heiko Stuebner <heiko at sntech.de>
---
Change in v9:
- remove unnecessary "REQUIRED".

Change in v8:
- remove error description.

 Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
index 0b4a85f..bbc5a1e 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
@@ -6,10 +6,20 @@ RK3xxx SoCs.
 Required properties :
 
  - reg : Offset and length of the register set for the device
- - compatible : should be "rockchip,rk3066-i2c", "rockchip,rk3188-i2c",
-		"rockchip,rk3228-i2c" or "rockchip,rk3288-i2c".
+ - compatible: should be one of the following:
+   - "rockchip,rk3066-i2c": for rk3066
+   - "rockchip,rk3188-i2c": for rk3188
+   - "rockchip,rk3228-i2c": for rk3228
+   - "rockchip,rk3288-i2c": for rk3288
+   - "rockchip,rk3399-i2c": for rk3399
  - interrupts : interrupt number
- - clocks : parent clock
+ - clocks: See ../clock/clock-bindings.txt
+   - For older hardware (rk3066, rk3188, rk3228, rk3288):
+     - There is one clock that's used both to derive the functional clock
+       for the device and as the bus clock.
+   - For newer hardware (rk3399): specified by name
+     - "i2c": This is used to derive the functional clock.
+     - "pclk": This is the bus clock.
 
 Required on RK3066, RK3188 :
 
-- 
1.9.1




From david.wu at rock-chips.com  Thu May 12 00:58:50 2016
From: david.wu at rock-chips.com (David Wu)
Date: Thu, 12 May 2016 15:58:50 +0800
Subject: [PATCH v9 7/8] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
References: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463039930-8367-1-git-send-email-david.wu@rock-chips.com>

- new method to caculate i2c timings for rk3399:
  There was an timing issue about "repeated start" time at the I2C
  controller of version0, controller appears to drop SDA at .875x (7/8)
  programmed clk high. On version 1 of the controller, the rule(.875x)
  isn't enough to meet tSU;STA
  requirements on 100k's Standard-mode. To resolve this issue,
  sda_update_config, start_setup_config and stop_setup_config for I2C
  timing information are added, new rules are designed to calculate
  the timing information at new v1.
- pclk and function clk are separated at rk3399

Signed-off-by: David Wu <david.wu at rock-chips.com>
Tested-by: Caesar Wang <wxt at rock-chips.com>
---
Change in v9:
- add spin lock for tuning updated in rk3x_i2c_adapt_div() (Doug) 

Changes in v8:
- update tuning in RKI2C_CON register by doing a read-modify-write (Doug)
- new method to use pclk and clk (Doug)

Changes in v7:
- transform into a 9 series patches (Doug)
- drop highspeed with mastercode, and support fast-mode plus (Doug)

 drivers/i2c/busses/i2c-rk3x.c | 291 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 272 insertions(+), 19 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 9791797..673656e 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -58,6 +58,12 @@ enum {
 #define REG_CON_LASTACK   BIT(5) /* 1: send NACK after last received byte */
 #define REG_CON_ACTACK    BIT(6) /* 1: stop if NACK is received */
 
+#define REG_CON_TUNING_MASK GENMASK(15, 8)
+
+#define REG_CON_SDA_CFG(cfg) ((cfg) << 8)
+#define REG_CON_STA_CFG(cfg) ((cfg) << 12)
+#define REG_CON_STO_CFG(cfg) ((cfg) << 14)
+
 /* REG_MRXADDR bits */
 #define REG_MRXADDR_VALID(x) BIT(24 + (x)) /* [x*8+7:x*8] of MRX[R]ADDR valid */
 
@@ -77,40 +83,62 @@ enum {
 
 /**
  * struct i2c_spec_values:
+ * @min_hold_start_ns: min hold time (repeated) START condition
  * @min_low_ns: min LOW period of the SCL clock
  * @min_high_ns: min HIGH period of the SCL cloc
  * @min_setup_start_ns: min set-up time for a repeated START conditio
  * @max_data_hold_ns: max data hold time
+ * @min_data_setup_ns: min data set-up time
+ * @min_setup_stop_ns: min set-up time for STOP condition
+ * @min_hold_buffer_ns: min bus free time between a STOP and
+ * START condition
  */
 struct i2c_spec_values {
+	unsigned long min_hold_start_ns;
 	unsigned long min_low_ns;
 	unsigned long min_high_ns;
 	unsigned long min_setup_start_ns;
 	unsigned long max_data_hold_ns;
+	unsigned long min_data_setup_ns;
+	unsigned long min_setup_stop_ns;
+	unsigned long min_hold_buffer_ns;
 };
 
 static const struct i2c_spec_values standard_mode_spec = {
+	.min_hold_start_ns = 4000,
 	.min_low_ns = 4700,
 	.min_high_ns = 4000,
 	.min_setup_start_ns = 4700,
 	.max_data_hold_ns = 3450,
+	.min_data_setup_ns = 250,
+	.min_setup_stop_ns = 4000,
+	.min_hold_buffer_ns = 4700,
 };
 
 static const struct i2c_spec_values fast_mode_spec = {
+	.min_hold_start_ns = 600,
 	.min_low_ns = 1300,
 	.min_high_ns = 600,
 	.min_setup_start_ns = 600,
 	.max_data_hold_ns = 900,
+	.min_data_setup_ns = 100,
+	.min_setup_stop_ns = 600,
+	.min_hold_buffer_ns = 1300,
 };
 
 /**
  * struct rk3x_i2c_calced_timings:
  * @div_low: Divider output for low
  * @div_high: Divider output for high
+ * @tuning: Used to adjust setup/hold data time,
+ * setup/hold start time and setup stop time for
+ * v1's calc_timings, the tuning should all be 0
+ * for old hardware anyone using v0's calc_timings.
  */
 struct rk3x_i2c_calced_timings {
 	unsigned long div_low;
 	unsigned long div_high;
+	unsigned int tuning;
 };
 
 enum rk3x_i2c_state {
@@ -123,9 +151,12 @@ enum rk3x_i2c_state {
 
 /**
  * @grf_offset: offset inside the grf regmap for setting the i2c type
+ * @calc_timings: Callback function for i2c timing information calculated
  */
 struct rk3x_i2c_soc_data {
 	int grf_offset;
+	int (*calc_timings)(unsigned long, struct i2c_timings *,
+			    struct rk3x_i2c_calced_timings *);
 };
 
 /**
@@ -134,7 +165,8 @@ struct rk3x_i2c_soc_data {
  * @dev: device for this controller
  * @soc_data: related soc data struct
  * @regs: virtual memory area
- * @clk: clock of i2c bus
+ * @clk: function clk for rk3399 or function & Bus clks for others
+ * @pclk: Bus clk for rk3399
  * @clk_rate_nb: i2c clk rate change notify
  * @t: I2C known timing information
  * @lock: spinlock for the i2c bus
@@ -156,6 +188,7 @@ struct rk3x_i2c {
 	/* Hardware resources */
 	void __iomem *regs;
 	struct clk *clk;
+	struct clk *pclk;
 	struct notifier_block clk_rate_nb;
 
 	/* Settings */
@@ -200,12 +233,12 @@ static inline void rk3x_i2c_clean_ipd(struct rk3x_i2c *i2c)
  */
 static void rk3x_i2c_start(struct rk3x_i2c *i2c)
 {
-	u32 val;
+	u32 val = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK;
 
 	i2c_writel(i2c, REG_INT_START, REG_IEN);
 
 	/* enable adapter with correct mode, send START condition */
-	val = REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START;
+	val |= REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START;
 
 	/* if we want to react to NACK, set ACTACK bit */
 	if (!(i2c->msg->flags & I2C_M_IGNORE_NAK))
@@ -513,9 +546,9 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
  * a best-effort divider value is returned in divs. If the target rate is
  * too high, we silently use the highest possible rate.
  */
-static int rk3x_i2c_calc_divs(unsigned long clk_rate,
-			      struct i2c_timings *t,
-			      struct rk3x_i2c_calced_timings *t_calc)
+static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate,
+				    struct i2c_timings *t,
+				    struct rk3x_i2c_calced_timings *t_calc)
 {
 	unsigned long min_low_ns, min_high_ns;
 	unsigned long max_low_ns, min_total_ns;
@@ -661,20 +694,191 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	return ret;
 }
 
+/**
+ * Calculate timing values for desired SCL frequency
+ *
+ * @clk_rate: I2C input clock rate
+ * @t: Known I2C timing information
+ * @t_calc: Caculated rk3x private timings that would be written into regs
+ *
+ * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
+ * a best-effort divider value is returned in divs. If the target rate is
+ * too high, we silently use the highest possible rate.
+ * The following formulas are v1's method to calculate timings.
+ *
+ * l = divl + 1;
+ * h = divh + 1;
+ * s = sda_update_config + 1;
+ * u = start_setup_config + 1;
+ * p = stop_setup_config + 1;
+ * T = Tclk_i2c;
+ *
+ * tHigh = 8 * h * T;
+ * tLow = 8 * l * T;
+ *
+ * tHD;sda = (l * s + 1) * T;
+ * tSU;sda = [(8 - s) * l + 1] * T;
+ * tI2C = 8 * (l + h) * T;
+ *
+ * tSU;sta = (8h * u + 1) * T;
+ * tHD;sta = [8h * (u + 1) - 1] * T;
+ * tSU;sto = (8h * p + 1) * T;
+ */
+static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
+				    struct i2c_timings *t,
+				    struct rk3x_i2c_calced_timings *t_calc)
+{
+	unsigned long min_low_ns, min_high_ns, min_total_ns;
+	unsigned long min_setup_start_ns, min_setup_data_ns;
+	unsigned long min_setup_stop_ns, max_hold_data_ns;
+
+	unsigned long clk_rate_khz, scl_rate_khz;
+
+	unsigned long min_low_div, min_high_div;
+
+	unsigned long min_div_for_hold, min_total_div;
+	unsigned long extra_div, extra_low_div;
+	unsigned long sda_update_cfg, stp_sta_cfg, stp_sto_cfg;
+
+	const struct i2c_spec_values *spec;
+	int ret = 0;
+
+	/* Support standard-mode and fast-mode */
+	if (WARN_ON(t->bus_freq_hz > 400000))
+		t->bus_freq_hz = 400000;
+
+	/* prevent scl_rate_khz from becoming 0 */
+	if (WARN_ON(t->bus_freq_hz < 1000))
+		t->bus_freq_hz = 1000;
+
+	/*
+	 * min_low_ns: The minimum number of ns we need to hold low to
+	 *	       meet I2C specification, should include fall time.
+	 * min_high_ns: The minimum number of ns we need to hold high to
+	 *	        meet I2C specification, should include rise time.
+	 */
+	spec = rk3x_i2c_get_spec(t->bus_freq_hz);
+
+	/* calculate min-divh and min-divl */
+	clk_rate_khz = DIV_ROUND_UP(clk_rate, 1000);
+	scl_rate_khz = t->bus_freq_hz / 1000;
+	min_total_div = DIV_ROUND_UP(clk_rate_khz, scl_rate_khz * 8);
+
+	min_high_ns = t->scl_rise_ns + spec->min_high_ns;
+	min_high_div = DIV_ROUND_UP(clk_rate_khz * min_high_ns, 8 * 1000000);
+
+	min_low_ns = t->scl_fall_ns + spec->min_low_ns;
+	min_low_div = DIV_ROUND_UP(clk_rate_khz * min_low_ns, 8 * 1000000);
+
+	/*
+	 * Final divh and divl must be greater than 0, otherwise the
+	 * hardware would not output the i2c clk.
+	 */
+	min_high_div = (min_high_div < 1) ? 2 : min_high_div;
+	min_low_div = (min_low_div < 1) ? 2 : min_low_div;
+
+	/* These are the min dividers needed for min hold times. */
+	min_div_for_hold = (min_low_div + min_high_div);
+	min_total_ns = min_low_ns + min_high_ns;
+
+	/*
+	 * This is the maximum divider so we don't go over the maximum.
+	 * We don't round up here (we round down) since this is a maximum.
+	 */
+	 if (min_div_for_hold >= min_total_div) {
+		/*
+		 * Time needed to meet hold requirements is important.
+		 * Just use that.
+		 */
+		t_calc->div_low = min_low_div;
+		t_calc->div_high = min_high_div;
+	} else {
+		/*
+		 * We've got to distribute some time among the low and high
+		 * so we don't run too fast.
+		 * We'll try to split things up by the scale of min_low_div and
+		 * min_high_div, biasing slightly towards having a higher div
+		 * for low (spend more time low).
+		 */
+		extra_div = min_total_div - min_div_for_hold;
+		extra_low_div = DIV_ROUND_UP(min_low_div * extra_div,
+					     min_div_for_hold);
+
+		t_calc->div_low = min_low_div + extra_low_div;
+		t_calc->div_high = min_high_div + (extra_div - extra_low_div);
+	}
+
+	/*
+	 * calculate sda data hold count by the rules, data_upd_st:3
+	 * is a appropriate value to reduce calculated times.
+	 */
+	for (sda_update_cfg = 3; sda_update_cfg > 0; sda_update_cfg--) {
+		max_hold_data_ns =  DIV_ROUND_UP((sda_update_cfg
+						 * (t_calc->div_low) + 1)
+						 * 1000000, clk_rate_khz);
+		min_setup_data_ns =  DIV_ROUND_UP(((8 - sda_update_cfg)
+						 * (t_calc->div_low) + 1)
+						 * 1000000, clk_rate_khz);
+		if ((max_hold_data_ns < spec->max_data_hold_ns) &&
+		    (min_setup_data_ns > spec->min_data_setup_ns))
+			break;
+	}
+
+	/* calculate setup start config */
+	min_setup_start_ns = t->scl_rise_ns + spec->min_setup_start_ns;
+	stp_sta_cfg = DIV_ROUND_UP(clk_rate_khz * min_setup_start_ns
+			   - 1000000, 8 * 1000000 * (t_calc->div_high));
+
+	/* calculate setup stop config */
+	min_setup_stop_ns = t->scl_rise_ns + spec->min_setup_stop_ns;
+	stp_sto_cfg = DIV_ROUND_UP(clk_rate_khz * min_setup_stop_ns
+			   - 1000000, 8 * 1000000 * (t_calc->div_high));
+
+	t_calc->tuning = REG_CON_SDA_CFG(--sda_update_cfg) |
+			 REG_CON_STA_CFG(--stp_sta_cfg) |
+			 REG_CON_STO_CFG(--stp_sto_cfg);
+
+	t_calc->div_low--;
+	t_calc->div_high--;
+
+	/* Maximum divider supported by hw is 0xffff */
+	if (t_calc->div_low > 0xffff) {
+		t_calc->div_low = 0xffff;
+		ret = -EINVAL;
+	}
+
+	if (t_calc->div_high > 0xffff) {
+		t_calc->div_high = 0xffff;
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
 static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
 {
 	struct i2c_timings *t = &i2c->t;
 	struct rk3x_i2c_calced_timings calc;
 	u64 t_low_ns, t_high_ns;
+	unsigned long flags;
+	u32 val;
 	int ret;
 
-	ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
+	ret = i2c->soc_data->calc_timings(clk_rate, t, &calc);
 	WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
 
-	clk_enable(i2c->clk);
+	clk_enable(i2c->pclk);
+
+	spin_lock_irqsave(&i2c->lock, flags);
+	val = i2c_readl(i2c, REG_CON);
+	val &= ~REG_CON_TUNING_MASK;
+	val |= calc.tuning;
+	i2c_writel(i2c, val, REG_CON);
 	i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
 		   REG_CLKDIV);
-	clk_disable(i2c->clk);
+	spin_unlock_irqrestore(&i2c->lock, flags);
+
+	clk_disable(i2c->pclk);
 
 	t_low_ns = div_u64(((u64)calc.div_low + 1) * 8 * 1000000000, clk_rate);
 	t_high_ns = div_u64(((u64)calc.div_high + 1) * 8 * 1000000000,
@@ -712,7 +916,13 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
 
 	switch (event) {
 	case PRE_RATE_CHANGE:
-		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &calc) != 0)
+		/*
+		 * Try the calculation (but don't store the result) ahead of
+		 * time to see if we need to block the clock change.  Timings
+		 * shouldn't actually take effect until rk3x_i2c_adapt_div().
+		 */
+		if (i2c->soc_data->calc_timings(ndata->new_rate, &i2c->t,
+						&calc) != 0)
 			return NOTIFY_STOP;
 
 		/* scale up */
@@ -822,12 +1032,14 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
 {
 	struct rk3x_i2c *i2c = (struct rk3x_i2c *)adap->algo_data;
 	unsigned long timeout, flags;
+	u32 val;
 	int ret = 0;
 	int i;
 
 	spin_lock_irqsave(&i2c->lock, flags);
 
 	clk_enable(i2c->clk);
+	clk_enable(i2c->pclk);
 
 	i2c->is_last_msg = false;
 
@@ -861,7 +1073,9 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
 
 			/* Force a STOP condition without interrupt */
 			i2c_writel(i2c, 0, REG_IEN);
-			i2c_writel(i2c, REG_CON_EN | REG_CON_STOP, REG_CON);
+			val = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK;
+			val |= REG_CON_EN | REG_CON_STOP;
+			i2c_writel(i2c, val, REG_CON);
 
 			i2c->state = STATE_IDLE;
 
@@ -875,7 +1089,9 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
 		}
 	}
 
+	clk_disable(i2c->pclk);
 	clk_disable(i2c->clk);
+
 	spin_unlock_irqrestore(&i2c->lock, flags);
 
 	return ret < 0 ? ret : num;
@@ -893,18 +1109,27 @@ static const struct i2c_algorithm rk3x_i2c_algorithm = {
 
 static const struct rk3x_i2c_soc_data rk3066_soc_data = {
 	.grf_offset = 0x154,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
 };
 
 static const struct rk3x_i2c_soc_data rk3188_soc_data = {
 	.grf_offset = 0x0a4,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
 };
 
 static const struct rk3x_i2c_soc_data rk3228_soc_data = {
 	.grf_offset = -1,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
 };
 
 static const struct rk3x_i2c_soc_data rk3288_soc_data = {
 	.grf_offset = -1,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
+};
+
+static const struct rk3x_i2c_soc_data rk3399_soc_data = {
+	.grf_offset = -1,
+	.calc_timings = rk3x_i2c_v1_calc_timings,
 };
 
 static const struct of_device_id rk3x_i2c_match[] = {
@@ -924,6 +1149,10 @@ static const struct of_device_id rk3x_i2c_match[] = {
 		.compatible = "rockchip,rk3288-i2c",
 		.data = (void *)&rk3288_soc_data
 	},
+	{
+		.compatible = "rockchip,rk3399-i2c",
+		.data = (void *)&rk3399_soc_data
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, rk3x_i2c_match);
@@ -963,12 +1192,6 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 	spin_lock_init(&i2c->lock);
 	init_waitqueue_head(&i2c->wait);
 
-	i2c->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(i2c->clk)) {
-		dev_err(&pdev->dev, "cannot get clock\n");
-		return PTR_ERR(i2c->clk);
-	}
-
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	i2c->regs = devm_ioremap_resource(&pdev->dev, mem);
 	if (IS_ERR(i2c->regs))
@@ -1022,17 +1245,44 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, i2c);
 
+	if (i2c->soc_data->calc_timings == rk3x_i2c_v0_calc_timings) {
+		/* Only one clock to use for bus clock and peripheral clock */
+		i2c->clk = devm_clk_get(&pdev->dev, NULL);
+		i2c->pclk = i2c->clk;
+	} else {
+		i2c->clk = devm_clk_get(&pdev->dev, "i2c");
+		i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
+	}
+
+	if (IS_ERR(i2c->clk)) {
+		ret = PTR_ERR(i2c->clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Can't get bus clk: %d\n", ret);
+		return ret;
+	}
+	if (IS_ERR(i2c->pclk)) {
+		ret = PTR_ERR(i2c->pclk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Can't get periph clk: %d\n", ret);
+		return ret;
+	}
+
 	ret = clk_prepare(i2c->clk);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "Could not prepare clock\n");
+		dev_err(&pdev->dev, "Can't prepare bus clk: %d\n", ret);
 		return ret;
 	}
+	ret = clk_prepare(i2c->pclk);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Can't prepare periph clock: %d\n", ret);
+		goto err_clk;
+	}
 
 	i2c->clk_rate_nb.notifier_call = rk3x_i2c_clk_notifier_cb;
 	ret = clk_notifier_register(i2c->clk, &i2c->clk_rate_nb);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Unable to register clock notifier\n");
-		goto err_clk;
+		goto err_pclk;
 	}
 
 	clk_rate = clk_get_rate(i2c->clk);
@@ -1050,6 +1300,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 
 err_clk_notifier:
 	clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb);
+err_pclk:
+	clk_unprepare(i2c->pclk);
 err_clk:
 	clk_unprepare(i2c->clk);
 	return ret;
@@ -1062,6 +1314,7 @@ static int rk3x_i2c_remove(struct platform_device *pdev)
 	i2c_del_adapter(&i2c->adap);
 
 	clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb);
+	clk_unprepare(i2c->pclk);
 	clk_unprepare(i2c->clk);
 
 	return 0;
-- 
1.9.1




From david.wu at rock-chips.com  Thu May 12 01:01:15 2016
From: david.wu at rock-chips.com (David Wu)
Date: Thu, 12 May 2016 16:01:15 +0800
Subject: [PATCH v9 8/8] i2c: rk3x: support fast-mode plus for rk3399
In-Reply-To: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
References: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463040075-8438-1-git-send-email-david.wu@rock-chips.com>

Implement fast mode plus that allows bus speeds of up to 1MHz.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Tested-by: Caesar Wang <wxt at rock-chips.com>
Reviewed-by: Heiko Stuebner <heiko at sntech.de>
---
Change in v9:
- add commit message

Change in v8:
- none

 drivers/i2c/busses/i2c-rk3x.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 673656e..ba4ce39 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -126,6 +126,17 @@ static const struct i2c_spec_values fast_mode_spec = {
 	.min_hold_buffer_ns = 1300,
 };
 
+static const struct i2c_spec_values fast_mode_plus_spec = {
+	.min_hold_start_ns = 260,
+	.min_low_ns = 500,
+	.min_high_ns = 260,
+	.min_setup_start_ns = 260,
+	.max_data_hold_ns = 400,
+	.min_data_setup_ns = 50,
+	.min_setup_stop_ns = 260,
+	.min_hold_buffer_ns = 500,
+};
+
 /**
  * struct rk3x_i2c_calced_timings:
  * @div_low: Divider output for low
@@ -531,8 +542,10 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
 {
 	if (speed <= 100000)
 		return &standard_mode_spec;
-	else
+	else if (speed <= 400000)
 		return &fast_mode_spec;
+	else
+		return &fast_mode_plus_spec;
 }
 
 /**
@@ -743,9 +756,9 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
 	const struct i2c_spec_values *spec;
 	int ret = 0;
 
-	/* Support standard-mode and fast-mode */
-	if (WARN_ON(t->bus_freq_hz > 400000))
-		t->bus_freq_hz = 400000;
+	/* Support standard-mode, fast-mode and fast-mode plus */
+	if (WARN_ON(t->bus_freq_hz > 1000000))
+		t->bus_freq_hz = 1000000;
 
 	/* prevent scl_rate_khz from becoming 0 */
 	if (WARN_ON(t->bus_freq_hz < 1000))
-- 
1.9.1




From jcm at jonmasters.org  Thu May 12 01:20:25 2016
From: jcm at jonmasters.org (Jon Masters)
Date: Thu, 12 May 2016 04:20:25 -0400
Subject: [PATCH v7 0/5] ACPI: parse the SPCR table
In-Reply-To: <1459431629-27934-1-git-send-email-aleksey.makarov@linaro.org>
References: <1459431629-27934-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1bff98e3-2d94-ed76-1165-ed7d43bbfcf3@jonmasters.org>

On 03/31/2016 09:40 AM, Aleksey Makarov wrote:

> 'ARM Server Base Boot Requirements' [1] mentions SPCR (Serial Port
> Console Redirection Table) [2] as a mandatory ACPI table that
> specifies the configuration of serial console.

Hi Aleksey,

Can you summarize the status of this patch series?

Jon.



From linux at armlinux.org.uk  Thu May 12 01:22:42 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Thu, 12 May 2016 09:22:42 +0100
Subject: [PATCH 11/12] kexec: allow architectures to override boot mapping
In-Reply-To: <20160512062627.GB2711@x1.redhat.com>
References: <20160428092644.GX19428@n2100.arm.linux.org.uk>
 <E1aviFU-0000jk-9q@rmk-PC.arm.linux.org.uk>
 <20160512062627.GB2711@x1.redhat.com>
Message-ID: <20160512082242.GQ19428@n2100.arm.linux.org.uk>

On Thu, May 12, 2016 at 02:26:27PM +0800, Baoquan He wrote:
> On 04/28/16 at 10:28am, Russell King wrote:
> > diff --git a/include/linux/kexec.h b/include/linux/kexec.h
> > index 52a3a221bcb2..99cb9dac7909 100644
> > --- a/include/linux/kexec.h
> > +++ b/include/linux/kexec.h
> > @@ -318,6 +318,44 @@ int __weak arch_kexec_apply_relocations_add(const Elf_Ehdr *ehdr,
> >  int __weak arch_kexec_apply_relocations(const Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
> >  					unsigned int relsec);
> >  
> > +#ifndef page_to_boot_pfn
> > +static inline unsigned long page_to_boot_pfn(struct page *page)
> > +{
> > +	return page_to_pfn(page);
> > +}
> > +#endif
> 
> I am thinking if it's appropriate to introduce a new concept which only
> exists in a certain system of a certain ARCH. Is it unavoidable? If have
> to can we name it as kexec_page_to_pfn/kexec_pfn_to_page, etc? People
> might not need to know about boot view physical address and kernel view
> physical address things when they just want to understand kexec
> implementation related to one ARCH except of ARM, even related to ARM
> but not Keystone 2.

Well, what do you suggest we do instead?

Eric, please get involved in this discussion, as this was your idea.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From ynorov at caviumnetworks.com  Thu May 12 01:24:27 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 12 May 2016 11:24:27 +0300
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <5733FC71.8070101@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <573305A8.50406@huawei.com> <5733149C.4030903@huawei.com>
 <5250356.myv9GIZ34h@wuerfel> <5733FC71.8070101@huawei.com>
Message-ID: <20160512082427.GA1587@yury-N73SV>

On Thu, May 12, 2016 at 11:45:53AM +0800, Zhangjian (Bamvor) wrote:

[...]

> >Hmm, that is indeed tricky. I think COMPAT_SYSCALL_WRAP4 rightfully
> >refuses the loff_t argument here, as the common case is that this is
> >not possible.
> It works if I apply the following patch, I defined the wrong `__TYPE_IS_xxx`
> yesterday. Should we merge this into ILP32 series or send the compat.h
> and syscalls.h individually? The current series of ILP32 is a little bit
> long and hard to review.
> diff --git a/include/linux/compat.h b/include/linux/compat.h
> index ba6ebe0..22a9565 100644
> --- a/include/linux/compat.h
> +++ b/include/linux/compat.h
> @@ -747,7 +747,8 @@ asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32,
>  #ifndef __SC_COMPAT_CAST
>  #define __SC_COMPAT_CAST(t, a) ({                                      \
>         BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) &&              \
> -                    !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t));            \
> +                    !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t) &&           \
> +                    !__TYPE_IS_LOFFT(t));                              \

I think it's wrong, as loff_t is 64-bit in 32-bit userspace, and this
will clear meaningful data in top halve.

>         ((t) ((t)(-1) < 0 ? (s64)(s32)(a) : (u64)(u32)(a)));            \
>  })
>  #endif
> diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
> index 6e57d9c..66eb85d 100644
> --- a/include/linux/syscalls.h
> +++ b/include/linux/syscalls.h
> @@ -47,6 +47,7 @@
>  #define __TYPE_IS_L(t) (__same_type((t)0, 0L))
>  #define __TYPE_IS_UL(t)        (__same_type((t)0, 0UL))
>  #define __TYPE_IS_LL(t) (__same_type((t)0, 0LL) || __same_type((t)0, 0ULL))
> +#define __TYPE_IS_LOFFT(t)     (__same_type((t)0, (loff_t)0))
>  #define __SC_LONG(t, a) __typeof(__builtin_choose_expr(__TYPE_IS_LL(t), 0LL, 0L)) a
>  #define __SC_CAST(t, a)        (t) a
>  #define __SC_ARGS(t, a)        a
> diff --git a/kernel/compat_wrapper.c b/kernel/compat_wrapper.c
> index 98b68b8..28f02d0 100644
> --- a/kernel/compat_wrapper.c
> +++ b/kernel/compat_wrapper.c
> @@ -304,3 +304,7 @@ COMPAT_SYSCALL_WRAP3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
>  COMPAT_SYSCALL_WRAP6(sendto, int, fd, void __user *, buff, size_t, len,
>                      unsigned int, flags, struct sockaddr __user *, addr,
>                      int, addr_len);
> +COMPAT_SYSCALL_WRAP4(pread64, unsigned int, fd, char __user *, buf,
> +                       size_t, count, loff_t, pos);
> +COMPAT_SYSCALL_WRAP4(pwrite64, unsigned int, fd, const char __user *, buf,
> +                        size_t, count, loff_t, pos);

For cases like this I think we should write wrappers by hands. In
unistd.h we can use __SC_WRAP, so they will work like wrappers
generated by COMPAT_SYSCALL_WRAPx() 


From heiko at sntech.de  Thu May 12 01:30:25 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 12 May 2016 10:30:25 +0200
Subject: [PATCH v8 8/8] i2c: rk3x: support fast-mode plus for rk3399
In-Reply-To: <CAD=FV=VzQ8PRokgAaTV00L31mcXFEzBG8c1NB4+Rqyx75hwwDg@mail.gmail.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <5153288.jNhUuzGC3g@phil>
 <CAD=FV=VzQ8PRokgAaTV00L31mcXFEzBG8c1NB4+Rqyx75hwwDg@mail.gmail.com>
Message-ID: <6806722.VBDbziL6YI@phil>

Am Mittwoch, 11. Mai 2016, 16:41:54 schrieb Doug Anderson:
> Heiko,
> 
> On Wed, May 11, 2016 at 2:09 PM, Heiko Stuebner <heiko at sntech.de> wrote:
> > Additionally, the i2c-noob in me would wish for a short sentence on
> > where
> > the timing values come from (measured, somewhere in the TRM I didn't
> > find or something completely different).
> 
> If you search for "UM10204" you'll find the first link is
> <http://www.nxp.com/documents/user_manual/UM10204.pdf>.  That appears
> to be the official standard.  At least that's what
> <http://www.i2c-bus.org/fast-mode-plus/> says (though they have an old
> link).

I did find that document yesterday, but was to blind and somehow only saw the 
separate table for highspeed-timings. On a closer look, I now also found the 
timing-table for the other modes [due to the bigger font-size used there? 
;-) ]



From maxime.ripard at free-electrons.com  Thu May 12 01:30:47 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Thu, 12 May 2016 10:30:47 +0200
Subject: [linux-sunxi] Re: [PATCH v4 01/11] clk: sunxi: Add display and
 TCON0 clocks driver
In-Reply-To: <20160512065943.GX3733@lukather>
References: <1461590572-4027-1-git-send-email-maxime.ripard@free-electrons.com>
 <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
 <20160506223002.GE3492@codeaurora.org>
 <20160508200308.GF6167@lukather>
 <20160509223238.GW3492@codeaurora.org>
 <20160509223924.GX3492@codeaurora.org>
 <1462907459.9981.0.camel@plaes.org>
 <20160511221541.GG3492@codeaurora.org>
 <1463024360.16747.4.camel@plaes.org>
 <20160512065943.GX3733@lukather>
Message-ID: <20160512083047.GY3733@lukather>

On Thu, May 12, 2016 at 08:59:43AM +0200, Maxime Ripard wrote:
> On Thu, May 12, 2016 at 06:39:20AM +0300, Priit Laes wrote:
> > On Wed, 2016-05-11 at 15:15 -0700, Stephen Boyd wrote:
> > > On 05/10, Priit Laes wrote:
> > > > 
> > > > On Mon, 2016-05-09 at 15:39 -0700, Stephen Boyd wrote:
> > > > > 
> > > > > On 05/09, Stephen Boyd wrote:
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > Ok I applied this one to clk-next.
> > > > > > 
> > > > > And I squashed this in to silence the following checker warning.
> > > > > 
> > > > > drivers/clk/sunxi/clk-sun4i-display.c:110:33: warning: Variable
> > > > > length array is used.
> > > > > 
> > > > > ---8<---
> > > > > diff --git a/drivers/clk/sunxi/clk-sun4i-display.c
> > > > > b/drivers/clk/sunxi/clk-sun4i-display.c
> > > > > index f02e250e64ed..f8ff6c4a5633 100644
> > > > > --- a/drivers/clk/sunxi/clk-sun4i-display.c
> > > > > +++ b/drivers/clk/sunxi/clk-sun4i-display.c
> > > > > @@ -107,7 +107,7 @@ static int
> > > > > sun4i_a10_display_reset_xlate(struct
> > > > > reset_controller_dev *rcdev,
> > > > > ?static void __init sun4i_a10_display_init(struct device_node
> > > > > *node,
> > > > > ?					??const struct
> > > > > sun4i_a10_display_clk_data *data)
> > > > > ?{
> > > > > -	const char *parents[data->parents];
> > > > > +	const char *parents[4];
> > > > This change breaks at least de_[bf]e clocks which have 3 clock
> > > > parents.
> > 
> > > I just used the largest data->parents number, which was 4. How
> > > does that break anything?
> > 
> > If you look at the?sun4i_a10_display_init, it contains this block:
> > 
> > ? ? ret = of_clk_parent_fill(node, parents, ARRAY_SIZE(parents));
> > ????if (ret != ARRAY_SIZE(parents)) {
> > ????????pr_err("%s: Could not retrieve the parents\n", clk_name);
> > ????????goto unmap;
> > ????}
> > 
> > of_clk_parent_fill returns 3 for de_be/de_fe nodes, and
> > ARRAY_SIZE(parents) is 4.
> 
> Replacing both ARRAY_SIZE(parents) by data->parents would work though.

I just tested on top of current next, and indeed the following patch
is needed.

Stephen, could you squash it in the former patch?

diff --git a/drivers/clk/sunxi/clk-sun4i-display.c b/drivers/clk/sunxi/clk-sun4i-display.c
index 70803aa7028c..9780fac6d029 100644
--- a/drivers/clk/sunxi/clk-sun4i-display.c
+++ b/drivers/clk/sunxi/clk-sun4i-display.c
@@ -128,8 +128,8 @@ static void __init sun4i_a10_display_init(struct device_node *node,
 		return;
 	}
 
-	ret = of_clk_parent_fill(node, parents, ARRAY_SIZE(parents));
-	if (ret != ARRAY_SIZE(parents)) {
+	ret = of_clk_parent_fill(node, parents, data->parents);
+	if (ret != data->parents) {
 		pr_err("%s: Could not retrieve the parents\n", clk_name);
 		goto unmap;
 	}

Thanks!
Maxime					  

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160512/bea383f2/attachment.sig>

From christoffer.dall at linaro.org  Thu May 12 01:32:49 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 10:32:49 +0200
Subject: [PATCH v3 28/55] KVM: arm/arm64: vgic-new: Add CONFIG registers
 handlers
In-Reply-To: <1462531568-9799-29-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-29-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512083249.GY27623@cbox>

On Fri, May 06, 2016 at 11:45:41AM +0100, Andre Przywara wrote:
> The config register handlers are shared between the v2 and v3
> emulation, so their implementation goes into vgic-mmio.c, to be
> easily referenced from the v3 emulation as well later.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
>  virt/kvm/arm/vgic/vgic-mmio.c    | 46 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h    |  7 ++++++
>  3 files changed, 54 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 2e17250..2a953ec 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -88,7 +88,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 2),
> +		vgic_mmio_read_config, vgic_mmio_write_config, 2),
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index d7fe9e6..19fed56 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -321,6 +321,52 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len)
> +{
> +	u32 intid = (addr & 0xff) * 4;
> +	u32 value = 0;
> +	int i;
> +
> +	for (i = 0; i < len * 4; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		if (irq->config == VGIC_CONFIG_EDGE)
> +			value |= (2U << (i * 2));
> +	}
> +
> +	return extract_bytes(value, addr & 3, len);
> +}
> +
> +void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
> +			    gpa_t addr, unsigned int len,
> +			    unsigned long val)
> +{
> +	u32 intid = (addr & 0xff) * 4;
> +	int i;
> +
> +	for (i = 0; i < len * 4; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		if (intid + i < 16)

s/16/VGIC_NR_SGIS/

> +			continue;

It's implementation defined if software can program the configuration of
PPIs, and since our timer code relies on its virtual PPI always being
level triggered, I think we should change the above to
VGIC_NR_PRIVATE_IRQS and then if someone ever needs a configurable
virtual PPI, we can add that later.

> +
> +		/*
> +		 * The spec says that interrupts must be disabled before
> +		 * changing the configuration to avoid UNDEFINED behaviour.
> +		 */

not sure what this comment tells us about the implementation?  Should we
check that the IRQ is disabled before proceeding?

> +
> +		spin_lock(&irq->irq_lock);
> +		if (test_bit(i * 2 + 1, &val)) {
> +			irq->config = VGIC_CONFIG_EDGE;
> +		} else {
> +			irq->config = VGIC_CONFIG_LEVEL;
> +			irq->pending = irq->line_level | irq->soft_pending;
> +		}
> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
>  static int match_region(const void *key, const void *elt)
>  {
>  	const unsigned int offset = (unsigned long)key;
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index cd04ac5..884eb71 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -114,6 +114,13 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
>  			      gpa_t addr, unsigned int len,
>  			      unsigned long val);
>  
> +unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len);
> +
> +void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
> +			    gpa_t addr, unsigned int len,
> +			    unsigned long val);
> +
>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>  
>  #endif
> -- 
> 2.7.3
> 


From christoffer.dall at linaro.org  Thu May 12 01:35:49 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 10:35:49 +0200
Subject: [PATCH v3 29/55] KVM: arm/arm64: vgic-new: Add TARGET registers
 handlers
In-Reply-To: <1462531568-9799-30-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-30-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512083549.GZ27623@cbox>

On Fri, May 06, 2016 at 11:45:42AM +0100, Andre Przywara wrote:
> The target register handlers are v2 emulation specific, so their
> implementation lives entirely in vgic-mmio-v2.c.
> We copy the old VGIC behaviour of assigning an IRQ to the first VCPU
> set in the target mask instead of making it possibly pending on
> multiple VCPUs.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - remove runtime VCPU determination from this v2-only register
> - fold in implementation of vgic_v2_irq_change_affinity()
> - replace ffs() with __ffs()
> 
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 42 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 2a953ec..888529e 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -66,6 +66,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
> +					   gpa_t addr, unsigned int len)
> +{
> +	u32 intid = addr & 0x3ff;
> +	int i;
> +	u64 val = 0;
> +
> +	for (i = 0; i < len; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		val |= (u64)irq->targets << (i * 8);
> +	}
> +
> +	return val;

this register should allow byte access, so you're missing a call to
extract_bytes() ?


> +}
> +
> +static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
> +				   gpa_t addr, unsigned int len,
> +				   unsigned long val)
> +{
> +	u32 intid = addr & 0x3ff;
> +	int i;
> +
> +	/* GICD_ITARGETSR[0-7] are read-only */
> +	if (intid < VGIC_NR_PRIVATE_IRQS)
> +		return;
> +
> +	for (i = 0; i < len; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
> +		int target;
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		irq->targets = (val >> (i * 8)) & 0xff;

this doesn't seem right given byte accesses either, and I don't see the
fixups we have in the works fixing it...

> +		target = irq->targets ? __ffs(irq->targets) : 0;
> +		irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target);
> +
> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
>  static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
>  		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
> @@ -86,7 +127,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
>  		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +		vgic_mmio_read_target, vgic_mmio_write_target, 8),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
>  		vgic_mmio_read_config, vgic_mmio_write_config, 2),
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
> -- 
> 2.7.3
> 


From arnd at arndb.de  Thu May 12 01:38:31 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 12 May 2016 10:38:31 +0200
Subject: [PATCH] ARM: samsung: improve static dma_mask definition
Message-ID: <1463042333-281444-1-git-send-email-arnd@arndb.de>

When no DMA master devices are part of the kernel configuration,
we get a warning about the unused dma mask definition:

arch/arm/plat-samsung/devs.c:71:12: error: 'samsung_device_dma_mask' defined but not used [-Werror=unused-variable]
 static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);

We could simply mark this as __maybe_unused to shut up that warning,
but a nicer solution seems to be to have a separate mask for each
device. The advantage is that a driver that happens to call
dma_set_mask() on one device doesn't implicitly change the mask
for the other devices as well. This is more of a theoretical
problem, as obviously nothing does it for the devices in this
file (or they would have always been broken), but it feels
cleaner that way.

The definition works by creating an array in place so we can take
the address of it and let the compiler generate a hidden symbol
for it at compile time.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 arch/arm/plat-samsung/devs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 84baa16f4c0b..e93aa6734147 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -68,7 +68,7 @@
 #include <linux/platform_data/asoc-s3c.h>
 #include <linux/platform_data/spi-s3c64xx.h>
 
-static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
+#define samsung_device_dma_mask (*((u64[]) { DMA_BIT_MASK(32) }))
 
 /* AC97 */
 #ifdef CONFIG_CPU_S3C2440
-- 
2.7.0



From marc.zyngier at arm.com  Thu May 12 01:39:41 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 12 May 2016 09:39:41 +0100
Subject: [PATCH v3 29/55] KVM: arm/arm64: vgic-new: Add TARGET registers
 handlers
In-Reply-To: <20160512083549.GZ27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-30-git-send-email-andre.przywara@arm.com>
 <20160512083549.GZ27623@cbox>
Message-ID: <5734414D.5090304@arm.com>

On 12/05/16 09:35, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:42AM +0100, Andre Przywara wrote:
>> The target register handlers are v2 emulation specific, so their
>> implementation lives entirely in vgic-mmio-v2.c.
>> We copy the old VGIC behaviour of assigning an IRQ to the first VCPU
>> set in the target mask instead of making it possibly pending on
>> multiple VCPUs.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - remove runtime VCPU determination from this v2-only register
>> - fold in implementation of vgic_v2_irq_change_affinity()
>> - replace ffs() with __ffs()
>>
>> Changelog v1 .. v2:
>> - adapt to new MMIO framework
>>
>>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 42 insertions(+), 1 deletion(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> index 2a953ec..888529e 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> @@ -66,6 +66,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
>>  	}
>>  }
>>  
>> +static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
>> +					   gpa_t addr, unsigned int len)
>> +{
>> +	u32 intid = addr & 0x3ff;
>> +	int i;
>> +	u64 val = 0;
>> +
>> +	for (i = 0; i < len; i++) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
>> +		val |= (u64)irq->targets << (i * 8);
>> +	}
>> +
>> +	return val;
> 
> this register should allow byte access, so you're missing a call to
> extract_bytes() ?
> 
> 
>> +}
>> +
>> +static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
>> +				   gpa_t addr, unsigned int len,
>> +				   unsigned long val)
>> +{
>> +	u32 intid = addr & 0x3ff;
>> +	int i;
>> +
>> +	/* GICD_ITARGETSR[0-7] are read-only */
>> +	if (intid < VGIC_NR_PRIVATE_IRQS)
>> +		return;
>> +
>> +	for (i = 0; i < len; i++) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
>> +		int target;
>> +
>> +		spin_lock(&irq->irq_lock);
>> +
>> +		irq->targets = (val >> (i * 8)) & 0xff;
> 
> this doesn't seem right given byte accesses either, and I don't see the
> fixups we have in the works fixing it...

I'll give it a whirl. the priority stuff needs addressing as well.

	M.
-- 
Jazz is not dead. It just smells funny...


From christoffer.dall at linaro.org  Thu May 12 01:40:39 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 10:40:39 +0200
Subject: [PATCH v3 30/55] KVM: arm/arm64: vgic-new: Add SGIR register
 handler
In-Reply-To: <1462531568-9799-31-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-31-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512084039.GA27623@cbox>

On Fri, May 06, 2016 at 11:45:43AM +0100, Andre Przywara wrote:
> Triggering an IPI via this register is v2 specific, so the
> implementation lives entirely in vgic-mmio-v2.c.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - silently return on illegal TargetListFilter value (=3)
> 
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 42 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 888529e..8f8ea57 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -66,6 +66,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
> +				 gpa_t addr, unsigned int len,
> +				 unsigned long val)
> +{
> +	int nr_vcpus = atomic_read(&source_vcpu->kvm->online_vcpus);
> +	int intid = val & 0xf;
> +	int targets = (val >> 16) & 0xff;
> +	int mode = (val >> 24) & 0x03;
> +	int c;
> +	struct kvm_vcpu *vcpu;
> +
> +	switch (mode) {
> +	case 0x0:		/* as specified by targets */
> +		break;
> +	case 0x1:
> +		targets = (1U << nr_vcpus) - 1;			/* all, ... */
> +		targets &= ~(1U << source_vcpu->vcpu_id);	/* but self */
> +		break;
> +	case 0x2:		/* this very vCPU only */
> +		targets = (1U << source_vcpu->vcpu_id);
> +		break;
> +	case 0x3:		/* reserved */
> +		return;
> +	}
> +
> +	kvm_for_each_vcpu(c, vcpu, source_vcpu->kvm) {
> +		struct vgic_irq *irq;
> +
> +		if (!(targets & (1U << c)))
> +			continue;
> +
> +		irq = vgic_get_irq(source_vcpu->kvm, vcpu, intid);
> +
> +		spin_lock(&irq->irq_lock);
> +		irq->pending = true;
> +		irq->source |= 1U << source_vcpu->vcpu_id;
> +
> +		vgic_queue_irq_unlock(source_vcpu->kvm, irq);
> +	}
> +}
> +
>  static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
>  					   gpa_t addr, unsigned int len)
>  {
> @@ -131,7 +172,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
>  		vgic_mmio_read_config, vgic_mmio_write_config, 2),
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4),
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
> -- 
> 2.7.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

(assuming the alignment check is fixed by other patches)

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Thu May 12 01:54:49 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 10:54:49 +0200
Subject: [PATCH v3 29/55] KVM: arm/arm64: vgic-new: Add TARGET registers
 handlers
In-Reply-To: <20160512083549.GZ27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-30-git-send-email-andre.przywara@arm.com>
 <20160512083549.GZ27623@cbox>
Message-ID: <20160512085449.GA2370@cbox>

On Thu, May 12, 2016 at 10:35:49AM +0200, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:42AM +0100, Andre Przywara wrote:
> > The target register handlers are v2 emulation specific, so their
> > implementation lives entirely in vgic-mmio-v2.c.
> > We copy the old VGIC behaviour of assigning an IRQ to the first VCPU
> > set in the target mask instead of making it possibly pending on
> > multiple VCPUs.
> > 
> > Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> > ---
> > Changelog RFC..v1:
> > - remove runtime VCPU determination from this v2-only register
> > - fold in implementation of vgic_v2_irq_change_affinity()
> > - replace ffs() with __ffs()
> > 
> > Changelog v1 .. v2:
> > - adapt to new MMIO framework
> > 
> >  virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 42 insertions(+), 1 deletion(-)
> > 
> > diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> > index 2a953ec..888529e 100644
> > --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> > +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> > @@ -66,6 +66,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
> >  	}
> >  }
> >  
> > +static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
> > +					   gpa_t addr, unsigned int len)
> > +{
> > +	u32 intid = addr & 0x3ff;
> > +	int i;
> > +	u64 val = 0;
> > +
> > +	for (i = 0; i < len; i++) {
> > +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> > +
> > +		val |= (u64)irq->targets << (i * 8);
> > +	}
> > +
> > +	return val;
> 
> this register should allow byte access, so you're missing a call to
> extract_bytes() ?
> 
Strike that, not enough coffee this morning.

I was in the mindset that val was always being constructed as the full
32-bit register value.

> 
> > +}
> > +
> > +static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
> > +				   gpa_t addr, unsigned int len,
> > +				   unsigned long val)
> > +{
> > +	u32 intid = addr & 0x3ff;
> > +	int i;
> > +
> > +	/* GICD_ITARGETSR[0-7] are read-only */
> > +	if (intid < VGIC_NR_PRIVATE_IRQS)
> > +		return;
> > +
> > +	for (i = 0; i < len; i++) {
> > +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
> > +		int target;
> > +
> > +		spin_lock(&irq->irq_lock);
> > +
> > +		irq->targets = (val >> (i * 8)) & 0xff;
> 
> this doesn't seem right given byte accesses either, and I don't see the
> fixups we have in the works fixing it...
> 

Strike that too, sorry.

-Christoffer


From niklas.soderlund+renesas at ragnatech.se  Thu May 12 01:54:41 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Thu, 12 May 2016 10:54:41 +0200
Subject: [PATCHv4 0/4] Reference both DMA controllers
Message-ID: <1463043285-14702-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>

Hi,

R-Car Gen2 have two DMA controllers, which are equivalent. However DMA
slaves were tied only to a single DMA controller in .dtsi. This series
add references to to both DMA controllers for all nodes that previously
only referenced one of them. It also adds dma references to the SDHI
nodes for r8a7794 which according to the datasheet should work but I
have not access to HW to verify.

Tested on Koelsch (r8a7791) by altering the compatible value of either
dmac0 or dmac1 and verifying that the DMA slaves pick the DMA controller
that is available.

* Changes since v3
- Fix accidentally deleted line, thanks Geert for spotting my error. I
  have now learnt the virtue of 'git diff --color-words'.
- Add Reviewed-by from Geert for patch 2-4.

* Changes since v2
- Squash a rather large series to one patch per SoC
- Rebase on top of renesas-devel-20160509-v4.6-rc7
- Always reference dmac0 before dmac1

* Changes since v1
- Rebase on top of renesas-devel-20160315-v4.5 and add dmas references
  new nodes (r8a7790: scif2 r8a7793: i2c6,i2c7,i2c8).
- Correct error in commit message 31/31 (s/QSPI/MMCIF).
- Collect Ack and Reviewed tags from Geert.

Niklas S?derlund (4):
  ARM: dts: r8a7790: Reference both DMA controllers
  ARM: dts: r8a7791: Reference both DMA controllers
  ARM: dts: r8a7793: Reference both DMA controllers
  ARM: dts: r8a7794: Reference both DMA controllers

 arch/arm/boot/dts/r8a7790.dtsi | 130 +++++++++++++++++++++---------------
 arch/arm/boot/dts/r8a7791.dtsi | 145 ++++++++++++++++++++++++-----------------
 arch/arm/boot/dts/r8a7793.dtsi | 130 +++++++++++++++++++++---------------
 arch/arm/boot/dts/r8a7794.dtsi | 119 ++++++++++++++++++++-------------
 4 files changed, 318 insertions(+), 206 deletions(-)

--
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Thu May 12 01:54:43 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Thu, 12 May 2016 10:54:43 +0200
Subject: [PATCHv4 2/4] ARM: dts: r8a7791: Reference both DMA controllers
In-Reply-To: <1463043285-14702-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1463043285-14702-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1463043285-14702-3-git-send-email-niklas.soderlund+renesas@ragnatech.se>

R-Car Gen2 have two DMA controllers, which are equivalent. Add
references to both dmac0 and dmac1 so the driver can choose which one to
use.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7791.dtsi | 145 ++++++++++++++++++++++++-----------------
 1 file changed, 87 insertions(+), 58 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index db67e34..2f92414 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -514,8 +514,9 @@
 		reg = <0 0xe60b0000 0 0x425>;
 		interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7791_CLK_IICDVFS>;
-		dmas = <&dmac0 0x77>, <&dmac0 0x78>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x77>, <&dmac0 0x78>,
+		       <&dmac1 0x77>, <&dmac1 0x78>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -527,8 +528,9 @@
 		reg = <0 0xe6500000 0 0x425>;
 		interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_IIC0>;
-		dmas = <&dmac0 0x61>, <&dmac0 0x62>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x61>, <&dmac0 0x62>,
+		       <&dmac1 0x61>, <&dmac1 0x62>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -540,8 +542,9 @@
 		reg = <0 0xe6510000 0 0x425>;
 		interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_IIC1>;
-		dmas = <&dmac0 0x65>, <&dmac0 0x66>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x65>, <&dmac0 0x66>,
+		       <&dmac1 0x65>, <&dmac1 0x66>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -556,8 +559,9 @@
 		reg = <0 0xee200000 0 0x80>;
 		interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_MMCIF0>;
-		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>,
+		       <&dmac1 0xd1>, <&dmac1 0xd2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
@@ -569,8 +573,9 @@
 		reg = <0 0xee100000 0 0x328>;
 		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_SDHI0>;
-		dmas = <&dmac1 0xcd>, <&dmac1 0xce>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xcd>, <&dmac0 0xce>,
+		       <&dmac1 0xcd>, <&dmac1 0xce>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -580,8 +585,9 @@
 		reg = <0 0xee140000 0 0x100>;
 		interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_SDHI1>;
-		dmas = <&dmac1 0xc1>, <&dmac1 0xc2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>,
+		       <&dmac1 0xc1>, <&dmac1 0xc2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -591,8 +597,9 @@
 		reg = <0 0xee160000 0 0x100>;
 		interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_SDHI2>;
-		dmas = <&dmac1 0xd3>, <&dmac1 0xd4>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>,
+		       <&dmac1 0xd3>, <&dmac1 0xd4>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -604,8 +611,9 @@
 		interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFA0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x21>, <&dmac0 0x22>,
+		       <&dmac1 0x21>, <&dmac1 0x22>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -617,8 +625,9 @@
 		interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFA1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x25>, <&dmac0 0x26>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x25>, <&dmac0 0x26>,
+		       <&dmac1 0x25>, <&dmac1 0x26>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -630,8 +639,9 @@
 		interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFA2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x27>, <&dmac0 0x28>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x27>, <&dmac0 0x28>,
+		       <&dmac1 0x27>, <&dmac1 0x28>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -643,8 +653,9 @@
 		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7791_CLK_SCIFA3>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>,
+		       <&dmac1 0x1b>, <&dmac1 0x1c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -656,8 +667,9 @@
 		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7791_CLK_SCIFA4>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1f>, <&dmac0 0x20>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1f>, <&dmac0 0x20>,
+		       <&dmac1 0x1f>, <&dmac1 0x20>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -669,8 +681,9 @@
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7791_CLK_SCIFA5>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x23>, <&dmac0 0x24>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x23>, <&dmac0 0x24>,
+		       <&dmac1 0x23>, <&dmac1 0x24>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -682,8 +695,9 @@
 		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFB0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
+		       <&dmac1 0x3d>, <&dmac1 0x3e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -695,8 +709,9 @@
 		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFB1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x19>, <&dmac0 0x1a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x19>, <&dmac0 0x1a>,
+		       <&dmac1 0x19>, <&dmac1 0x1a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -708,8 +723,9 @@
 		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFB2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>,
+		       <&dmac1 0x1d>, <&dmac1 0x1e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -722,8 +738,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_SCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x29>, <&dmac0 0x2a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+		       <&dmac1 0x29>, <&dmac1 0x2a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -736,8 +753,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_SCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+		       <&dmac1 0x2d>, <&dmac1 0x2e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -750,8 +768,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_SCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+		       <&dmac1 0x2b>, <&dmac1 0x2c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -764,8 +783,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_SCIF3>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2f>, <&dmac0 0x30>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
+		       <&dmac1 0x2f>, <&dmac1 0x30>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -778,8 +798,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_SCIF4>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>,
+		       <&dmac1 0xfb>, <&dmac1 0xfc>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -792,8 +813,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_SCIF5>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>,
+		       <&dmac1 0xfd>, <&dmac1 0xfe>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -806,8 +828,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_HSCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x39>, <&dmac0 0x3a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+		       <&dmac1 0x39>, <&dmac1 0x3a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -820,8 +843,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_HSCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+		       <&dmac1 0x4d>, <&dmac1 0x4e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -834,8 +858,9 @@
 		clocks = <&mstp7_clks R8A7791_CLK_HSCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>,
+		       <&dmac1 0x3b>, <&dmac1 0x3c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -1478,8 +1503,9 @@
 		reg = <0 0xe6b10000 0 0x2c>;
 		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7791_CLK_QSPI_MOD>;
-		dmas = <&dmac0 0x17>, <&dmac0 0x18>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x17>, <&dmac0 0x18>,
+		       <&dmac1 0x17>, <&dmac1 0x18>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		num-cs = <1>;
 		#address-cells = <1>;
@@ -1492,8 +1518,9 @@
 		reg = <0 0xe6e20000 0 0x0064>;
 		interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>;
-		dmas = <&dmac0 0x51>, <&dmac0 0x52>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x51>, <&dmac0 0x52>,
+		       <&dmac1 0x51>, <&dmac1 0x52>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -1505,8 +1532,9 @@
 		reg = <0 0xe6e10000 0 0x0064>;
 		interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_MSIOF1>;
-		dmas = <&dmac0 0x55>, <&dmac0 0x56>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x55>, <&dmac0 0x56>,
+		       <&dmac1 0x55>, <&dmac1 0x56>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -1518,8 +1546,9 @@
 		reg = <0 0xe6e00000 0 0x0064>;
 		interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_MSIOF2>;
-		dmas = <&dmac0 0x41>, <&dmac0 0x42>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x41>, <&dmac0 0x42>,
+		       <&dmac1 0x41>, <&dmac1 0x42>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Thu May 12 01:54:44 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Thu, 12 May 2016 10:54:44 +0200
Subject: [PATCHv4 3/4] ARM: dts: r8a7793: Reference both DMA controllers
In-Reply-To: <1463043285-14702-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1463043285-14702-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1463043285-14702-4-git-send-email-niklas.soderlund+renesas@ragnatech.se>

R-Car Gen2 have two DMA controllers, which are equivalent. Add
references to both dmac0 and dmac1 so the driver can choose which one to
use.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7793.dtsi | 130 ++++++++++++++++++++++++-----------------
 1 file changed, 78 insertions(+), 52 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi
index 76c8435..5f50e9b 100644
--- a/arch/arm/boot/dts/r8a7793.dtsi
+++ b/arch/arm/boot/dts/r8a7793.dtsi
@@ -473,8 +473,9 @@
 		reg = <0 0xe60b0000 0 0x425>;
 		interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7793_CLK_IICDVFS>;
-		dmas = <&dmac0 0x77>, <&dmac0 0x78>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x77>, <&dmac0 0x78>,
+		       <&dmac1 0x77>, <&dmac1 0x78>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -486,8 +487,9 @@
 		reg = <0 0xe6500000 0 0x425>;
 		interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_IIC0>;
-		dmas = <&dmac0 0x61>, <&dmac0 0x62>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x61>, <&dmac0 0x62>,
+		       <&dmac1 0x61>, <&dmac1 0x62>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -499,8 +501,9 @@
 		reg = <0 0xe6510000 0 0x425>;
 		interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_IIC1>;
-		dmas = <&dmac0 0x65>, <&dmac0 0x66>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x65>, <&dmac0 0x66>,
+		       <&dmac1 0x65>, <&dmac1 0x66>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -515,8 +518,9 @@
 		reg = <0 0xee100000 0 0x328>;
 		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_SDHI0>;
-		dmas = <&dmac0 0xcd>, <&dmac0 0xce>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xcd>, <&dmac0 0xce>,
+		       <&dmac1 0xcd>, <&dmac1 0xce>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -526,8 +530,9 @@
 		reg = <0 0xee140000 0 0x100>;
 		interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_SDHI1>;
-		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>,
+		       <&dmac1 0xc1>, <&dmac1 0xc2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -537,8 +542,9 @@
 		reg = <0 0xee160000 0 0x100>;
 		interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_SDHI2>;
-		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>,
+		       <&dmac1 0xd3>, <&dmac1 0xd4>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -548,8 +554,9 @@
 		reg = <0 0xee200000 0 0x80>;
 		interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_MMCIF0>;
-		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>,
+		       <&dmac1 0xd1>, <&dmac1 0xd2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
@@ -563,8 +570,9 @@
 		interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFA0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x21>, <&dmac0 0x22>,
+		       <&dmac1 0x21>, <&dmac1 0x22>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -576,8 +584,9 @@
 		interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFA1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x25>, <&dmac0 0x26>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x25>, <&dmac0 0x26>,
+		       <&dmac1 0x25>, <&dmac1 0x26>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -589,8 +598,9 @@
 		interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFA2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x27>, <&dmac0 0x28>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x27>, <&dmac0 0x28>,
+		       <&dmac1 0x27>, <&dmac1 0x28>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -602,8 +612,9 @@
 		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7793_CLK_SCIFA3>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>,
+		       <&dmac1 0x1b>, <&dmac1 0x1c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -615,8 +626,9 @@
 		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7793_CLK_SCIFA4>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1f>, <&dmac0 0x20>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1f>, <&dmac0 0x20>,
+		       <&dmac1 0x1f>, <&dmac1 0x20>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -628,8 +640,9 @@
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7793_CLK_SCIFA5>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x23>, <&dmac0 0x24>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x23>, <&dmac0 0x24>,
+		       <&dmac1 0x23>, <&dmac1 0x24>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -641,8 +654,9 @@
 		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFB0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
+		       <&dmac1 0x3d>, <&dmac1 0x3e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -654,8 +668,9 @@
 		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFB1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x19>, <&dmac0 0x1a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x19>, <&dmac0 0x1a>,
+		       <&dmac1 0x19>, <&dmac1 0x1a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -667,8 +682,9 @@
 		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFB2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>,
+		       <&dmac1 0x1d>, <&dmac1 0x1e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -681,8 +697,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_SCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x29>, <&dmac0 0x2a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+		       <&dmac1 0x29>, <&dmac1 0x2a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -695,8 +712,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_SCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+		       <&dmac1 0x2d>, <&dmac1 0x2e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -709,8 +727,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_SCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+		       <&dmac1 0x2b>, <&dmac1 0x2c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -723,8 +742,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_SCIF3>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2f>, <&dmac0 0x30>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
+		       <&dmac1 0x2f>, <&dmac1 0x30>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -737,8 +757,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_SCIF4>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>,
+		       <&dmac1 0xfb>, <&dmac1 0xfc>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -751,8 +772,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_SCIF5>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>,
+		       <&dmac1 0xfd>, <&dmac1 0xfe>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -765,8 +787,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_HSCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x39>, <&dmac0 0x3a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+		       <&dmac1 0x39>, <&dmac1 0x3a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -779,8 +802,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_HSCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+		       <&dmac1 0x4d>, <&dmac1 0x4e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -793,8 +817,9 @@
 		clocks = <&mstp7_clks R8A7793_CLK_HSCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>,
+		       <&dmac1 0x3b>, <&dmac1 0x3c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -816,8 +841,9 @@
 		reg = <0 0xe6b10000 0 0x2c>;
 		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7793_CLK_QSPI_MOD>;
-		dmas = <&dmac0 0x17>, <&dmac0 0x18>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x17>, <&dmac0 0x18>,
+		       <&dmac1 0x17>, <&dmac1 0x18>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		num-cs = <1>;
 		#address-cells = <1>;
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Thu May 12 01:54:45 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Thu, 12 May 2016 10:54:45 +0200
Subject: [PATCHv4 4/4] ARM: dts: r8a7794: Reference both DMA controllers
In-Reply-To: <1463043285-14702-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1463043285-14702-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1463043285-14702-5-git-send-email-niklas.soderlund+renesas@ragnatech.se>

R-Car Gen2 have two DMA controllers, which are equivalent. Add
references to both dmac0 and dmac1 so the driver can choose which one to
use.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7794.dtsi | 119 ++++++++++++++++++++++++++---------------
 1 file changed, 75 insertions(+), 44 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi
index f334a3a..ad1df83 100644
--- a/arch/arm/boot/dts/r8a7794.dtsi
+++ b/arch/arm/boot/dts/r8a7794.dtsi
@@ -302,8 +302,9 @@
 		interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFA0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x21>, <&dmac0 0x22>,
+		       <&dmac1 0x21>, <&dmac1 0x22>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -315,8 +316,9 @@
 		interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFA1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x25>, <&dmac0 0x26>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x25>, <&dmac0 0x26>,
+		       <&dmac1 0x25>, <&dmac1 0x26>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -328,8 +330,9 @@
 		interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFA2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x27>, <&dmac0 0x28>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x27>, <&dmac0 0x28>,
+		       <&dmac1 0x27>, <&dmac1 0x28>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -341,8 +344,9 @@
 		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7794_CLK_SCIFA3>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>,
+		       <&dmac1 0x1b>, <&dmac1 0x1c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -354,8 +358,9 @@
 		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7794_CLK_SCIFA4>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1f>, <&dmac0 0x20>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1f>, <&dmac0 0x20>,
+		       <&dmac1 0x1f>, <&dmac1 0x20>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -367,8 +372,9 @@
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp11_clks R8A7794_CLK_SCIFA5>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x23>, <&dmac0 0x24>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x23>, <&dmac0 0x24>,
+		       <&dmac1 0x23>, <&dmac1 0x24>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -380,8 +386,9 @@
 		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFB0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
+		       <&dmac1 0x3d>, <&dmac1 0x3e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -393,8 +400,9 @@
 		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFB1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x19>, <&dmac0 0x1a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x19>, <&dmac0 0x1a>,
+		       <&dmac1 0x19>, <&dmac1 0x1a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -406,8 +414,9 @@
 		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFB2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>,
+		       <&dmac1 0x1d>, <&dmac1 0x1e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -420,8 +429,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_SCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x29>, <&dmac0 0x2a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+		       <&dmac1 0x29>, <&dmac1 0x2a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -434,8 +444,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_SCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+		       <&dmac1 0x2d>, <&dmac1 0x2e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -448,8 +459,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_SCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+		       <&dmac1 0x2b>, <&dmac1 0x2c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -462,8 +474,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_SCIF3>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2f>, <&dmac0 0x30>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
+		       <&dmac1 0x2f>, <&dmac1 0x30>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -476,8 +489,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_SCIF4>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>,
+		       <&dmac1 0xfb>, <&dmac1 0xfc>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -490,8 +504,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_SCIF5>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>,
+		       <&dmac1 0xfd>, <&dmac1 0xfe>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -504,8 +519,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_HSCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x39>, <&dmac0 0x3a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+		       <&dmac1 0x39>, <&dmac1 0x3a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -518,8 +534,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_HSCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+		       <&dmac1 0x4d>, <&dmac1 0x4e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -532,8 +549,9 @@
 		clocks = <&mstp7_clks R8A7794_CLK_HSCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>,
+		       <&dmac1 0x3b>, <&dmac1 0x3c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -640,8 +658,9 @@
 		reg = <0 0xe6500000 0 0x425>;
 		interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_IIC0>;
-		dmas = <&dmac0 0x61>, <&dmac0 0x62>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x61>, <&dmac0 0x62>,
+		       <&dmac1 0x61>, <&dmac1 0x62>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -653,8 +672,9 @@
 		reg = <0 0xe6510000 0 0x425>;
 		interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_IIC1>;
-		dmas = <&dmac0 0x65>, <&dmac0 0x66>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x65>, <&dmac0 0x66>,
+		       <&dmac1 0x65>, <&dmac1 0x66>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -666,8 +686,9 @@
 		reg = <0 0xee200000 0 0x80>;
 		interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_MMCIF0>;
-		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>,
+		       <&dmac1 0xd1>, <&dmac1 0xd2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
@@ -678,6 +699,9 @@
 		reg = <0 0xee100000 0 0x200>;
 		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_SDHI0>;
+		dmas = <&dmac0 0xcd>, <&dmac0 0xce>,
+		       <&dmac1 0xcd>, <&dmac1 0xce>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -687,6 +711,9 @@
 		reg = <0 0xee140000 0 0x100>;
 		interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_SDHI1>;
+		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>,
+		       <&dmac1 0xc1>, <&dmac1 0xc2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -696,6 +723,9 @@
 		reg = <0 0xee160000 0 0x100>;
 		interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_SDHI2>;
+		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>,
+		       <&dmac1 0xd3>, <&dmac1 0xd4>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -705,8 +735,9 @@
 		reg = <0 0xe6b10000 0 0x2c>;
 		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7794_CLK_QSPI_MOD>;
-		dmas = <&dmac0 0x17>, <&dmac0 0x18>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x17>, <&dmac0 0x18>,
+		       <&dmac1 0x17>, <&dmac1 0x18>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		num-cs = <1>;
 		#address-cells = <1>;
-- 
2.8.2



From niklas.soderlund+renesas at ragnatech.se  Thu May 12 01:54:42 2016
From: niklas.soderlund+renesas at ragnatech.se (=?UTF-8?q?Niklas=20S=C3=B6derlund?=)
Date: Thu, 12 May 2016 10:54:42 +0200
Subject: [PATCHv4 1/4] ARM: dts: r8a7790: Reference both DMA controllers
In-Reply-To: <1463043285-14702-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1463043285-14702-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <1463043285-14702-2-git-send-email-niklas.soderlund+renesas@ragnatech.se>

R-Car Gen2 have two DMA controllers, which are equivalent. Add
references to both dmac0 and dmac1 so the driver can choose which one to
use.

Signed-off-by: Niklas S?derlund <niklas.soderlund+renesas at ragnatech.se>
---
 arch/arm/boot/dts/r8a7790.dtsi | 130 ++++++++++++++++++++++++-----------------
 1 file changed, 78 insertions(+), 52 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 83cf23c..ac80db4 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -517,8 +517,9 @@
 		reg = <0 0xe6500000 0 0x425>;
 		interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_IIC0>;
-		dmas = <&dmac0 0x61>, <&dmac0 0x62>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x61>, <&dmac0 0x62>,
+		       <&dmac1 0x61>, <&dmac1 0x62>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -530,8 +531,9 @@
 		reg = <0 0xe6510000 0 0x425>;
 		interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_IIC1>;
-		dmas = <&dmac0 0x65>, <&dmac0 0x66>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x65>, <&dmac0 0x66>,
+		       <&dmac1 0x65>, <&dmac1 0x66>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -543,8 +545,9 @@
 		reg = <0 0xe6520000 0 0x425>;
 		interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_IIC2>;
-		dmas = <&dmac0 0x69>, <&dmac0 0x6a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x69>, <&dmac0 0x6a>,
+		       <&dmac1 0x69>, <&dmac1 0x6a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -556,8 +559,9 @@
 		reg = <0 0xe60b0000 0 0x425>;
 		interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_IICDVFS>;
-		dmas = <&dmac0 0x77>, <&dmac0 0x78>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x77>, <&dmac0 0x78>,
+		       <&dmac1 0x77>, <&dmac1 0x78>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -567,8 +571,9 @@
 		reg = <0 0xee200000 0 0x80>;
 		interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>;
-		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>,
+		       <&dmac1 0xd1>, <&dmac1 0xd2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
@@ -580,8 +585,9 @@
 		reg = <0 0xee220000 0 0x80>;
 		interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_MMCIF1>;
-		dmas = <&dmac0 0xe1>, <&dmac0 0xe2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xe1>, <&dmac0 0xe2>,
+		       <&dmac1 0xe1>, <&dmac1 0xe2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
@@ -598,8 +604,9 @@
 		reg = <0 0xee100000 0 0x328>;
 		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI0>;
-		dmas = <&dmac1 0xcd>, <&dmac1 0xce>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xcd>, <&dmac0 0xce>,
+		       <&dmac1 0xcd>, <&dmac1 0xce>;
+		dma-names = "tx", "rx", "tx", "rx";
 		max-frequency = <195000000>;
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
@@ -610,8 +617,9 @@
 		reg = <0 0xee120000 0 0x328>;
 		interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI1>;
-		dmas = <&dmac1 0xc9>, <&dmac1 0xca>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xc9>, <&dmac0 0xca>,
+		       <&dmac1 0xc9>, <&dmac1 0xca>;
+		dma-names = "tx", "rx", "tx", "rx";
 		max-frequency = <195000000>;
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
@@ -622,8 +630,9 @@
 		reg = <0 0xee140000 0 0x100>;
 		interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI2>;
-		dmas = <&dmac1 0xc1>, <&dmac1 0xc2>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>,
+		       <&dmac1 0xc1>, <&dmac1 0xc2>;
+		dma-names = "tx", "rx", "tx", "rx";
 		max-frequency = <97500000>;
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
@@ -634,8 +643,9 @@
 		reg = <0 0xee160000 0 0x100>;
 		interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI3>;
-		dmas = <&dmac1 0xd3>, <&dmac1 0xd4>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>,
+		       <&dmac1 0xd3>, <&dmac1 0xd4>;
+		dma-names = "tx", "rx", "tx", "rx";
 		max-frequency = <97500000>;
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
@@ -648,8 +658,9 @@
 		interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFA0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x21>, <&dmac0 0x22>,
+		       <&dmac1 0x21>, <&dmac1 0x22>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -661,8 +672,9 @@
 		interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFA1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x25>, <&dmac0 0x26>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x25>, <&dmac0 0x26>,
+		       <&dmac1 0x25>, <&dmac1 0x26>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -674,8 +686,9 @@
 		interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFA2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x27>, <&dmac0 0x28>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x27>, <&dmac0 0x28>,
+		       <&dmac1 0x27>, <&dmac1 0x28>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -687,8 +700,9 @@
 		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFB0>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
+		       <&dmac1 0x3d>, <&dmac1 0x3e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -700,8 +714,9 @@
 		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFB1>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x19>, <&dmac0 0x1a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x19>, <&dmac0 0x1a>,
+		       <&dmac1 0x19>, <&dmac1 0x1a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -713,8 +728,9 @@
 		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFB2>;
 		clock-names = "fck";
-		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>,
+		       <&dmac1 0x1d>, <&dmac1 0x1e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -727,8 +743,9 @@
 		clocks = <&mstp7_clks R8A7790_CLK_SCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x29>, <&dmac0 0x2a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+		       <&dmac1 0x29>, <&dmac1 0x2a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -741,8 +758,9 @@
 		clocks = <&mstp7_clks R8A7790_CLK_SCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+		       <&dmac1 0x2d>, <&dmac1 0x2e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -755,8 +773,9 @@
 		clocks = <&mstp3_clks R8A7790_CLK_SCIF2>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+		       <&dmac1 0x2b>, <&dmac1 0x2c>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -769,8 +788,9 @@
 		clocks = <&mstp7_clks R8A7790_CLK_HSCIF0>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x39>, <&dmac0 0x3a>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+		       <&dmac1 0x39>, <&dmac1 0x3a>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -783,8 +803,9 @@
 		clocks = <&mstp7_clks R8A7790_CLK_HSCIF1>, <&zs_clk>,
 			 <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+		       <&dmac1 0x4d>, <&dmac1 0x4e>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -1469,8 +1490,9 @@
 		reg = <0 0xe6b10000 0 0x2c>;
 		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_QSPI_MOD>;
-		dmas = <&dmac0 0x17>, <&dmac0 0x18>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x17>, <&dmac0 0x18>,
+		       <&dmac1 0x17>, <&dmac1 0x18>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		num-cs = <1>;
 		#address-cells = <1>;
@@ -1483,8 +1505,9 @@
 		reg = <0 0xe6e20000 0 0x0064>;
 		interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp0_clks R8A7790_CLK_MSIOF0>;
-		dmas = <&dmac0 0x51>, <&dmac0 0x52>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x51>, <&dmac0 0x52>,
+		       <&dmac1 0x51>, <&dmac1 0x52>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -1496,8 +1519,9 @@
 		reg = <0 0xe6e10000 0 0x0064>;
 		interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_MSIOF1>;
-		dmas = <&dmac0 0x55>, <&dmac0 0x56>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x55>, <&dmac0 0x56>,
+		       <&dmac1 0x55>, <&dmac1 0x56>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -1509,8 +1533,9 @@
 		reg = <0 0xe6e00000 0 0x0064>;
 		interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_MSIOF2>;
-		dmas = <&dmac0 0x41>, <&dmac0 0x42>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x41>, <&dmac0 0x42>,
+		       <&dmac1 0x41>, <&dmac1 0x42>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -1522,8 +1547,9 @@
 		reg = <0 0xe6c90000 0 0x0064>;
 		interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_MSIOF3>;
-		dmas = <&dmac0 0x45>, <&dmac0 0x46>;
-		dma-names = "tx", "rx";
+		dmas = <&dmac0 0x45>, <&dmac0 0x46>,
+		       <&dmac1 0x45>, <&dmac1 0x46>;
+		dma-names = "tx", "rx", "tx", "rx";
 		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-- 
2.8.2



From will.deacon at arm.com  Thu May 12 01:56:16 2016
From: will.deacon at arm.com (Will Deacon)
Date: Thu, 12 May 2016 09:56:16 +0100
Subject: [PATCH v6 00/14] ACPI NUMA support for ARM64
In-Reply-To: <CAJZ5v0gBTANFntBSkyaRtt-BKOMC+pz_R9CwM6wKnp=Ni1dPFA@mail.gmail.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <CAJZ5v0iMDQ4pWip4vyCos0o+1DFDvXQf4XZQqC4SGjJsDO4Lnw@mail.gmail.com>
 <20160511104032.GA31374@arm.com>
 <CAJZ5v0gQMR7OUyZo5Sa3bgMYZBzdnwFaktz9JCv1ocWXw7yHTg@mail.gmail.com>
 <57339F39.3040603@caviumnetworks.com>
 <CAJZ5v0h8zBEZ2nLLdk62r7uqHizUfVWamUVEriBGe1XBE6462Q@mail.gmail.com>
 <5733A47B.8030908@caviumnetworks.com>
 <CAJZ5v0gBTANFntBSkyaRtt-BKOMC+pz_R9CwM6wKnp=Ni1dPFA@mail.gmail.com>
Message-ID: <20160512085616.GA25355@arm.com>

On Thu, May 12, 2016 at 12:29:02AM +0200, Rafael J. Wysocki wrote:
> On Wed, May 11, 2016 at 11:30 PM, David Daney <ddaney at caviumnetworks.com> wrote:
> > On 05/11/2016 02:22 PM, Rafael J. Wysocki wrote:
> >> On Wed, May 11, 2016 at 11:08 PM, David Daney <ddaney at caviumnetworks.com>
> >> wrote:
> >>> On 05/11/2016 01:35 PM, Rafael J. Wysocki wrote:
> >>>> On Wed, May 11, 2016 at 12:40 PM, Will Deacon <will.deacon at arm.com>
> >>>> wrote:
> >>>>> On Wed, May 11, 2016 at 02:43:11AM +0200, Rafael J. Wysocki wrote:
> >>>>> There's also a dependency on the arm64 for-next/core branch, so I've
> >>>>> been
> >>>>> largely ignoring this as far as 4.6 is concerned and was planning to
> >>>>> take
> >>>>> a proper look for 4.7 once the upcoming merge window is out of the way.
> >>>>
> >>>>
> >>>>
> >>>> That would be 4.7 and 4.8 respectively I suppose?

Argh, yes, of course! :)

> >>>>
> >>>> Anyway, Catalin has ACKed all of them except for the [13/14], so
> >>>> technically I can apply [1-12/14] now and then [13-14/14] can be
> >>>> applied when they are ready.
> >>>>
> >>>> Do you think there will be any problems with merging [6-7/14] into 4.7
> >>>> via the ACPI tree?
> >>>>
> >>>
> >>> I would defer to the arm64 maintainers for decisions about the arm64
> >>> specific parts of the patch set.  That said, many of the arm64 specific
> >>> patches depend on the arm64 for-next/core branch, so you would have to be
> >>> careful about merge ordering if you pull these in before the
> >>> for-next/core
> >>> branch is merged.
> >>
> >>
> >> Fair enough.  I will wait for an update then.
> >>
> >>> Also FWIW, I plan on addressing Catalin's comments about 13/14 and
> >>> posting a
> >>> new version of the patch set in the next day or two.
> >>
> >>
> >> OK, but in that case it won't be considered for 4.7 (at least not by
> >> me), so I'd suggest sending it in the second half of the 4.7 merge
> >> window (or about that time).
> >
> >
> > To be candid, I would very much like for you to pull in as many of the
> > patches as you are comfortable with as soon as possible.
> >
> > I don't know where Will and Catalin stand on this, and their opinion is
> > obviously important, but getting 1-12/14 merged to v4.7 and deferring the
> > last two for v4.8 would simplify the whole process for me.  The drawback is
> > carrying dead code around until the final parts are merged.
> 
> That is not unheard of, however.
> 
> OK, I'll try to put the [1-12/14] into my linux-next branch early next
> week and we'll see if that triggers any conflicts.

I'd really much rather this waited until after the merge window. My
understanding is that it's bad practice to put stuff into -next during the
merge window, and you'd end up having to send a pull based on a random
commit (the arm64 pull request?) in the second half. On top of that, this
series would get very little exposure in -next during that time.

On the other hand, putting this into linux-next after the merge window
gives us time for testing, allows David to rework patch 13 (which is aiming
for 4.8 anyway iiuc) and avoids merge window churn.

Will


From shijie.huang at arm.com  Thu May 12 02:03:57 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Thu, 12 May 2016 17:03:57 +0800
Subject: [PATCH] deb-pkg: add the shared header file for arm64
Message-ID: <1463043837-4348-1-git-send-email-shijie.huang@arm.com>

The arch/arm/include/asm/opcodes.h is also used by the arm64.
This patch copies it to the arm64 deb package.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 scripts/package/builddeb | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 6c3b038..f4de0d7 100755
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -323,6 +323,12 @@ fi
 # Build kernel header package
 (cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles"
 (cd $srctree; find arch/$SRCARCH/include include scripts -type f) >> "$objtree/debian/hdrsrcfiles"
+
+if [ "$ARCH" = "arm64" ]; then
+	# The arm64 shares the same header file with the arm
+	(cd $srctree; echo arch/arm/include/asm/opcodes.h) >> "$objtree/debian/hdrsrcfiles"
+fi
+
 (cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles"
 (cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles"
 (cd $objtree; find arch/$SRCARCH/include Module.symvers include scripts -type f) >> "$objtree/debian/hdrobjfiles"
-- 
2.1.4



From christoffer.dall at linaro.org  Thu May 12 02:09:09 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 11:09:09 +0200
Subject: [PATCH v3 31/55] KVM: arm/arm64: vgic-new: Add SGIPENDR register
 handlers
In-Reply-To: <1462531568-9799-32-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-32-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512090909.GB27623@cbox>

On Fri, May 06, 2016 at 11:45:44AM +0100, Andre Przywara wrote:
> As this register is v2 specific, its implementation lives entirely
> in vgic-mmio-v2.c.
> This register allows setting the source mask of an IPI.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - remove IRQ lock from read handler
> - update pending bit on setting the first / clearing the last bit
> - queue virtual IRQ if necessary
> 
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 60 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 8f8ea57..8006ac0 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -148,6 +148,64 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
> +					    gpa_t addr, unsigned int len)
> +{
> +	u32 intid = addr & 0x0f;
> +	int i;
> +	u64 val = 0;
> +
> +	for (i = 0; i < len; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		val |= (u64)irq->source << (i * 8);
> +	}
> +	return val;
> +}
> +
> +static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
> +				     gpa_t addr, unsigned int len,
> +				     unsigned long val)
> +{
> +	u32 intid = addr & 0x0f;
> +	int i;
> +
> +	for (i = 0; i < len; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		irq->source &= ~((val >> (i * 8)) & 0xff);
> +		if (!irq->source)
> +			irq->pending = false;
> +
> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
> +static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
> +				     gpa_t addr, unsigned int len,
> +				     unsigned long val)
> +{
> +	u32 intid = addr & 0x0f;
> +	int i;
> +
> +	for (i = 0; i < len; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		irq->source |= (val >> (i * 8)) & 0xff;
> +
> +		if (irq->source) {
> +			irq->pending = true;
> +			vgic_queue_irq_unlock(vcpu->kvm, irq);
> +		} else {
> +			spin_unlock(&irq->irq_lock);
> +		}
> +	}
> +}
> +
>  static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
>  		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
> @@ -174,9 +232,9 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
>  		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4),
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
> +		vgic_mmio_read_sgipend, vgic_mmio_write_sgipendc, 16),
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
> +		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16),
>  };
>  
>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
> -- 
> 2.7.3
> 

Again, assuming alignment checking is fixed:

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From marc.zyngier at arm.com  Thu May 12 02:10:33 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 12 May 2016 10:10:33 +0100
Subject: [PATCH v3 27/55] KVM: arm/arm64: vgic-new: Add PRIORITY registers
 handlers
In-Reply-To: <1462531568-9799-28-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-28-git-send-email-andre.przywara@arm.com>
Message-ID: <57344889.1050802@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> The priority register handlers are shared between the v2 and v3
> emulation, so their implementation goes into vgic-mmio.c, to be
> easily referenced from the v3 emulation as well later.
> There is a corner case when we change the priority of a pending
> interrupt which we don't handle at the moment.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
>  virt/kvm/arm/vgic/vgic-mmio.c    | 39 +++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h    |  7 +++++++
>  3 files changed, 47 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 054b52d..2e17250 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -84,7 +84,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
>  		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index dbf683e..d7fe9e6 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -282,6 +282,45 @@ retry:
>  	}
>  }
>  
> +unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
> +				      gpa_t addr, unsigned int len)
> +{
> +	u32 intid = addr & 0x3ff;
> +	int i;
> +	u64 val = 0;
> +
> +	for (i = 0; i < len; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		val |= (u64)irq->priority << (i * 8);
> +	}
> +
> +	return val;
> +}
> +
> +/*
> + * We currently don't handle changing the priority of an interrupt that
> + * is already pending on a VCPU. If there is a need for this, we would
> + * need to make this VCPU exit and re-evaluate the priorities, potentially
> + * leading to this interrupt getting presented now to the guest (if it has
> + * been masked by the priority mask before).
> + */
> +void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
> +			      gpa_t addr, unsigned int len,
> +			      unsigned long val)
> +{
> +	u32 intid = addr & 0x3ff;
> +	int i;
> +
> +	for (i = 0; i < len; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +		irq->priority = (val >> (i * 8)) & 0xff;

This is wrong. We should only write the number of bits of priority we
actually emulate. And given that we use a common framework for v2 and
v3, this should probably be 5 bits (32 priorities should be enough for
everybody).

I'll try and cook something.

	M.
-- 
Jazz is not dead. It just smells funny...


From catalin.marinas at arm.com  Thu May 12 02:17:58 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 12 May 2016 10:17:58 +0100
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <4989778.Fs81NJurjH@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <5842999.Zgpfq4gkVz@wuerfel>
 <20160511165900.GM3051@e104818-lin.cambridge.arm.com>
 <4989778.Fs81NJurjH@wuerfel>
Message-ID: <20160512091758.GB11226@e104818-lin.cambridge.arm.com>

On Wed, May 11, 2016 at 09:30:07PM +0200, Arnd Bergmann wrote:
> On Wednesday 11 May 2016 17:59:01 Catalin Marinas wrote:
> > On Wed, May 11, 2016 at 12:55:01PM +0200, Arnd Bergmann wrote:
> > > On Wednesday 11 May 2016 11:04:38 Yury Norov wrote:
> > > > On Wed, May 11, 2016 at 10:04:16AM +0800, Zhangjian (Bamvor) wrote:
> > > > [...]
> > > > 
> > > > > >>Ok, I will test the ltp syscall test.
> > > > > >>With this changes, the issue I mentioned should be fixed. But we still
> > > > > >>use mmap2 syscall for ILP32 application when we pass the offset instead
> > > > > >>of page offset. Is it correct?
> > > > > >
> > > > > >I don't remember. It's probably not important whether we have the shift
> > > > > >in there, as long as it's independent of the actual kernel page size and
> > > > > >user space and kernel agree on the calling conventions.
> > > > > Well. I am ok with where to shift the pages size because we get the same
> > > > > result. I was just thinking if we should get rid of the name of mmap2 in our
> > > > > ILP32 porting. Actually, it is mmap but we name it as mmap2. User may confused
> > > > > if they do not know the implementations.
> > > > > 
> > > > 
> > > > This is what generic unistd.h does. If you want to change it, you'd
> > > > change each arch that uses generic unistd.h.
> > > 
> > > Generic unistd.h has this:
> > > 
> > > #ifdef __SYSCALL_COMPAT
> > > #define __SC_COMP_3264(_nr, _32, _64, _comp) __SYSCALL(_nr, _comp)
> > > #else
> > > #define __SC_COMP_3264(_nr, _32, _64, _comp) __SC_3264(_nr, _32, _64)
> > > #endif
> > > 
> > > #define __NR3264_mmap 222
> > > __SC_3264(__NR3264_mmap, sys_mmap2, sys_mmap)
> > > 
> > > 
> > > #if __BITS_PER_LONG == 64 && !defined(__SYSCALL_COMPAT)
> > > #define __NR_mmap __NR3264_mmap
> > > #else
> > > #define __NR_mmap2 __NR3264_mmap
> > > #endif
> > > 
> > > So by default we get __NR_mmap2 and sys_mmap2 on 32-bit ABIs, but
> > > __NR_mmap and sys_mmap on 64-bit ABIs, as it should be.
> > > 
> > > The problem is that arch/arm64/kernel/sys_ilp32.c now overrides
> > > this to use __NR_mmap2 with sys_mmap, so we have a mismatch. I think
> > > we should either override both the implementation and the number,
> > > or neither of them.
> > 
> > I would vote for "neither of them" (so we use __NR_mmap2 and sys_mmap2)
> > to keep it close to new 32-bit architectures, even though we would have
> > some shifts by 12 in both glibc and kernel.
> 
> I don't think the shifts are a problem, the main downside would be
> the limit to 44 bits of file offsets (16TB files), but it's also
> unclear if that is a practical problem at all. If it is, we run
> into the same problem on all other 32-bit architectures too.

I hope people are seriously thinking of moving to an LP64 ABI if they
have such large file offset needs.

-- 
Catalin


From kernel at martin.sperl.org  Thu May 12 02:19:43 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Thu, 12 May 2016 11:19:43 +0200
Subject: [PATCH 0/5] clk: bcm2835: add flags for mash and parent clocks
In-Reply-To: <877ff1yfg8.fsf@eliezer.anholt.net>
References: <1462463608-22940-1-git-send-email-kernel@martin.sperl.org>
 <87h9e6yb6i.fsf@eliezer.anholt.net> <57319C89.7040705@martin.sperl.org>
 <877ff1yfg8.fsf@eliezer.anholt.net>
Message-ID: <57344AAF.8000205@martin.sperl.org>



On 10.05.2016 19:45, Eric Anholt wrote:
> Martin Sperl <kernel at martin.sperl.org> writes:
>
>> On 10.05.2016 03:05, Eric Anholt wrote:
>>> kernel at martin.sperl.org writes:
>>>
>>>> From: Martin Sperl <kernel at martin.sperl.org>
>>>>
>>>> Allow flags to be set on a per clock index basis, which control:
>>>> * the parent clocks selected when not setting clocks explicitly
>>>
>>> I don't think we need this other than avoiding PLLC.  What else do you
>>> want to filter, and why?
>> What about potentially disabling PLLA_per or PLLH_aux?
>> Under some circumstances it may make sense to avoid those clocks.
>> (or testdebug for that matter).
>
> PLLH and its descendents are only used by vc4, and the parent choice
> done by this driver for pllh is correct.
>
> I don't know what you mean by "potentially disabling PLLA_PER".
>
> We don't expose the testdebug parents, because they're of no use to us.
For all practical purposes we still have all the clocks as potential
parents during automatic clock selection - and that includes:
PLLA_PER, PLLH_AUX and TESTDEBUGX.

Not all of them are enabled, but some are - so If I select an i2s 
frequency of "3903125" then plla_per will get used with a divider of 2.

>>>> * the clock mode with regards to integer only or higher order mash
>>>
>>> Please provide justification in the commit message explaining why there
>>> is no obvious mash setting to just implement in clk-bcm2835.c, but that
>>> that a better policy can be encoded in the DT.
>>
>> The normal fractional divider will vary the effective period length
>> between int(div)/Fparent and (int(div)+1)/Fparent.
>>
>> So the device (say DAC or other) connected needs to support in
>> principle Fparent/int(div) as a clock.
>>
>> But for higher order mash the HW will spread the period length between:
>> (int(div)-3)/Fparent and (int(div)+4)/Fparent.
>>
>> This value may be outside of the frequencies supported by the attached
>> HW. That is why mash is not enabled by default for mash clocks - only
>> div.
>>
>> That is also why we need to have this configurable.
>>
>> Also obviously higher parent clock frequencies result in higher dividers
>> for the same target-frequency. So the above effect is less dramatic
>> when using plld_per (or pllc for that matter) compared to the main
>> 19.2MHz oscillator, as for 32bit stereo audio at 96kHz (equivalent to
>> 6144000Hz) in the first case we have a divider of 81.38 while for the
>> second (osc) case we have a divider of 3.125.
>>
>> The use of mash3 is impossible for osc but the use of mash 2 would
>> spread the frequencies between 9.6MHz (div=2) and 3.84MHz (div=5).
>>
>> For plld_per as parent using mash3 instead we get the range:
>> 6410256.4Hz (div=78) and 5882352.9Hz (div=85), which is a much more
>> acceptable range and should not impact the device that much.
>>
>> So enabling mash 3 by default is not in the best interest hence it is
>> not done.
>
> It sounds like you're optimizing for reducing frequency spread.  That
> sounds fairly easy to do in the parent-choice function.

You misunderstand my argument here!

I know that it may be automated, but you may have different devices
connected to: i2s/pcm, pwm, gp and slim.

Some of them need the audio spreading, while others need a stable
waveform - as mentioned mash3 varies the period between:
(divi-2)/fparent and (divi+4)/fparent in discrete steps
For this the worsted case is a requested frequency that results
in a divider between 4 and 5.

Also some DAC require a STABLE clock waveform on i2s with
specific requirements for ton/(ton+toff) between 40% and 60%,
as they have their own internal PLL, while others do not need
this kind of behavior and can handle variable period-length.
But then these DAC still have a minimum period length, which we
may not exceed.

So making an automatic selection is not possible hence
we need a means to configure the supported mash level
to get the best results in all cases.

>
>> As a side note: selection of parent oscillator and corresponding mash
>> may have distinct noise behavior on the same device, where for
>> 32bit*2 at 48k it is the main oscillator with mash3 while the second best
>> match would be pllc with mash2 - not mash3, which has the worsted SN
>> from all tested!
>
> But PLLC continues to be unusable, since it's changed at runtime, and
> evaluating its noise characteristics based on a snapshot of its
> frequency doesn't make any sense.
That was a general side note not necessarily related to PLLC.
But this may be better handled by a generic clock driver
similar to clk-fixed-factor.

>
>> This behavior obviously changes with different "target frequencies"
>> so it may even be necessary to account for the different target
>> frequencies.
>
> This is why encoding mash in the DT doesn't make any sense to me.  You
> need a runtime policy for choosing the mash setting based on the
> frequency requested, so let's figure out what policy we actually want.
See the argument of different devices/DAC with different requirements.
There is no way for any of this to work automatically and make every
client happy.



From arnd at arndb.de  Thu May 12 02:19:21 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 12 May 2016 11:19:21 +0200
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160512002000.GA30997@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
Message-ID: <4326765.8HKKkI07Zs@wuerfel>

On Thursday 12 May 2016 03:20:00 Yury Norov wrote:
> 
> I debugged preadv02 and pwritev02 failures and found very weird bug.
> Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> of vector, and kernel reports successful read/write.
> 
> There are 2 problems:
> 1. How kernel allows such address to be passed to fs subsystem;
> 2. How fs successes to read/write at non-mapped, and in fact non-user
> address.
> 
> I don't know the answer on 2'nd question, and it might be something
> generic. But I investigated first problem.
> 
> The problem is that compat_rw_copy_check_uvector() uses access_ok() to
> validate user address, and on arm64 it ends up with checking buffer
> end against current_thread_info()->addr_limit.
> 
> current_thread_info()->addr_limit for ilp32, and most probably for
> aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
> It happens because on thread creation we call flush_old_exec() to set 
> addr_limit, and completely ignore compat mode there.
> 
> This patch fixes it. It also fixes USER_DS macro to return different
> values depending on compat.
> 
> This patch is enough to handle preadv02 and pwritev02, but problem #2
> is still there.
> 
> Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
> 

Good catch!

Can you do a version of this patch that works on the current
mainline kernel and can be backported to fix aarch32 emulation?

For ilp32 mode, I think we can better fix arch/arm64/kernel/binfmt_ilp32.c
as it is introduced.

	Arnd


From arnd at arndb.de  Thu May 12 02:21:42 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 12 May 2016 11:21:42 +0200
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <20160512091758.GB11226@e104818-lin.cambridge.arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <4989778.Fs81NJurjH@wuerfel>
 <20160512091758.GB11226@e104818-lin.cambridge.arm.com>
Message-ID: <2733875.IzutTZKHMc@wuerfel>

On Thursday 12 May 2016 10:17:58 Catalin Marinas wrote:
> On Wed, May 11, 2016 at 09:30:07PM +0200, Arnd Bergmann wrote:
> > On Wednesday 11 May 2016 17:59:01 Catalin Marinas wrote:
> > 
> > I don't think the shifts are a problem, the main downside would be
> > the limit to 44 bits of file offsets (16TB files), but it's also
> > unclear if that is a practical problem at all. If it is, we run
> > into the same problem on all other 32-bit architectures too.
> 
> I hope people are seriously thinking of moving to an LP64 ABI if they
> have such large file offset needs.

Good point. 44 bits of file size is certainly enough for mmap()
on a 32-bit task: you would only be able to map a very small fraction
of the file anyway, and if you want to map larger files, and should
move to 64-bit tasks long before this becomes a limitation.

	Arnd


From robin.murphy at arm.com  Thu May 12 02:24:02 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 12 May 2016 10:24:02 +0100
Subject: [PATCH] drm: mediatek: remove IOMMU_DMA select
In-Reply-To: <1462997501-982363-1-git-send-email-arnd@arndb.de>
References: <1462982509-342936-1-git-send-email-arnd@arndb.de>
 <1462997501-982363-1-git-send-email-arnd@arndb.de>
Message-ID: <57344BB2.8020608@arm.com>

On 11/05/16 21:11, Arnd Bergmann wrote:
> We get a harmless build warning when trying to use the mediatek
> DRM driver with IOMMU support disabled:
>
> warning: (DRM_MEDIATEK) selects IOMMU_DMA which has unmet direct dependencies (IOMMU_SUPPORT)
>
> However, the IOMMU_DMA symbol is not meant to be used by drivers
> at all, and this driver doesn't seem to have a strict dependency
> on it other than using the mediatek IOMMU driver that does.
>
> Since we also want to be able to do compile tests with the
> driver on other platforms, the IOMMU_DMA symbol should not
> be selected here.
>
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> ---
> If someone has a better explanation about why the 'select' is here,
> let me know, it certainly seems out of place.

Ack - it's neither an IOMMU driver nor a DMA API implementation, so it 
has no business with IOMMU_DMA. If there's an IOMMU dependency in 
general it should be on MTK_IOMMU, not underlying implementation details.

Robin.

>   drivers/gpu/drm/mediatek/Kconfig | 1 -
>   1 file changed, 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
> index 0c06a69d7f04..545973f6b743 100644
> --- a/drivers/gpu/drm/mediatek/Kconfig
> +++ b/drivers/gpu/drm/mediatek/Kconfig
> @@ -7,7 +7,6 @@ config DRM_MEDIATEK
>   	select DRM_KMS_HELPER
>   	select DRM_MIPI_DSI
>   	select DRM_PANEL
> -	select IOMMU_DMA
>   	select MEMORY
>   	select MTK_SMI
>   	help
>



From catalin.marinas at arm.com  Thu May 12 02:25:45 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 12 May 2016 10:25:45 +0100
Subject: [PATCH] arm64: do not enforce strict 16 byte alignment to stack
 pointer
In-Reply-To: <1462985814-16146-1-git-send-email-colin.king@canonical.com>
References: <1462985814-16146-1-git-send-email-colin.king@canonical.com>
Message-ID: <20160512092545.GC11226@e104818-lin.cambridge.arm.com>

On Wed, May 11, 2016 at 05:56:54PM +0100, Colin King wrote:
> From: Colin Ian King <colin.king at canonical.com>
> 
> copy_thread should not be enforcing 16 byte aligment and returning
> -EINVAL. Other architectures trap misaligned stack access with SIGBUS
> so arm64 should follow this convention, so remove the strict enforcement
> check.
> 
> For example, currently clone(2) fails with -EINVAL when passing
> a misaligned stack and this gives little clue to what is wrong. Instead,
> it is arguable that a SIGBUS on the fist access to a misaligned stack
> allows one to figure out that it is a misaligned stack issue rather
> than trying to figure out why an unconventional (and undocumented)
> -EINVAL is being returned.
> 
> Signed-off-by: Colin Ian King <colin.king at canonical.com>
> ---
>  arch/arm64/kernel/process.c | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> index 5655f756..8414971 100644
> --- a/arch/arm64/kernel/process.c
> +++ b/arch/arm64/kernel/process.c
> @@ -258,9 +258,6 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
>  		if (stack_start) {
>  			if (is_compat_thread(task_thread_info(p)))
>  				childregs->compat_sp = stack_start;
> -			/* 16-byte aligned stack mandatory on AArch64 */
> -			else if (stack_start & 15)
> -				return -EINVAL;
>  			else
>  				childregs->sp = stack_start;
>  		}

As we discussed on the linux-man list, I don't expect this change to
break existing working user apps since they pass an aligned stack
already. I really doubt anyone relies on the -EINVAL here.

That said, I don't think we should add a cc stable (which you haven't
anyway), at least we have a point in time where this change was made. As
the patch stands:

Acked-by: Catalin Marinas <catalin.marinas at arm.com>

(but let's wait for Will's opinion as well)


From hongbo.zhang at nxp.com  Thu May 12 02:42:29 2016
From: hongbo.zhang at nxp.com (Hongbo Zhang)
Date: Thu, 12 May 2016 09:42:29 +0000
Subject: [PSCI DISCUSS] How to implement standby and suspend-to-ram by PSCI
References: <DB3PR04MB0812DAA98F71C30E8A8832E3847D0@DB3PR04MB0812.eurprd04.prod.outlook.com>
 <572C9BF2.9010004@arm.com>
Message-ID: <DB3PR04MB08125A628F5034749F8109D884730@DB3PR04MB0812.eurprd04.prod.outlook.com>

Hi Sudeep,

On 2016?05?06? 21:28, Sudeep Holla wrote:
> Hi Hongbo,
>
> On 06/05/16 11:11, Hongbo Zhang wrote:
>> Hi Guys,
>> We know in the legacy kernel suspend codes, a typical suspend_ops->enter
>> callback is like this:
>>
>
> [...]
>
>>
>> That means we implement standby and suspend-to-ram in one callback, and
>> these two state can be identified by an input parameter 'state'.
>>
>> While now PSCI is used for ARM to implement cores operations and power
>> management, for the above suspend_ops->enter we choose SYSTEM_SUSPEND
>> function, and this function is defined for suspend-to-ram, then here
>> comes the problem:
>>
>> How can we implement the standby state following the PSCI framework?
>>
>
> Jisheng Zhang raised similar question few months back and we had a
> discussion. Please have a look at the thread [1]
>
I looked through that discussion, it seems better I continue to reply 
there but I didn't book that mailing list, so I add linux-arm-kernel 
list and Jisheng here.

>> I couldn't find other PSCI function which fits for standby well.
>> In the spec there isn't such a 'state' parameter passed for
>> SYSTEM_SUSPEND (only entry_point_address and context_id), can we change
>> the spec a bit, e.g. using one more register to pass another 'state'
>> parameter? is that acceptable? (similar like CPU_SUSPEND then)
>>
>
> Since the standby state is not well defined on ARM systems, it's hard to
> define the conditions like system suspend and hence difficult to
> generalize in the spec. I think suspend-to-idle should suffice in your
> case. Anyways its better to get more information on the definition of
> standby on your platform.
>

On our platform we have some shallow states which maps to cpuidle well, 
and we have two more deeper states:

Sleep state:
All cores are in WFI state,
Core cluster is in standby state, e.g. L2 cache is flushed then stops 
snooping,
Only those modules which are required to wake up the device still have a 
running clock, other device modules in chip are clock gated.

Deep sleep state:
ARM cores and DDR controller are switched off,
DDR is in self-refresh mode,
VDD power to off domain IPs are removed, Only the blocks needed to 
detect wake up and sequence the chip out of deep sleep are on.

For the two states, except for the wake-up devices, all the other device 
dirver's suspend callback needs to be called because those devices will 
be clock or power gated off. So, the kernel suspend process (freeze 
tasks, suspend devices etc) are needed for our sleep and deep sleep states.
In fact we've already implemented these two stated by legacy way, e.g. 
mapping sleep state to STANDBY and deep sleep to MEM, both states are 
implemented in one traditional .enter callback and can be indexed by a 
'state' parameter.

While transferring to PSCI, we met the problem I mentioned.

As to the freeze(suspend-to-idle), it is described as "a generic, pure 
software, light-weight, system sleep state" in the Document, and the 
fact is only acpi is using it, what's more, I don't think it satisfy us 
well, because the freeze_enter() is executed before 
disable_nonboot_cpus() and syscore_suspend(), while the later two are 
necessary for us.

So it seems another 'state' parameter for SYSTEM_SUSPEND can settle this 
problem, but it is lack in the spec.

There are diverse kinds of ARM SOC, and divers kind of peripheral 
devices in each SOC, so even for the SYSTEM_SUSPEND, there may be 
different states too(deeper or shallower states of each device, more or 
less of devices are put to idle), the more the PSCI spec supports, the 
better.



From appana.durga.rao at xilinx.com  Thu May 12 02:43:47 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Thu, 12 May 2016 15:13:47 +0530
Subject: [RESEND PATCH v4 2/3] Documentation: DT: vdma: Add clock support for
 dmas
In-Reply-To: <1463046228-21651-1-git-send-email-appanad@xilinx.com>
References: <1463046228-21651-1-git-send-email-appanad@xilinx.com>
Message-ID: <1463046228-21651-3-git-send-email-appanad@xilinx.com>

This patch updates the binding doc with clock description
for AXI DMA's.

Acked-by: S?ren Brinkmann <soren.brinkmann at xilinx.com>
Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
 .../devicetree/bindings/dma/xilinx/xilinx_vdma.txt        | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt
index fcc2b65..a1f2683 100644
--- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt
+++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt
@@ -21,6 +21,18 @@ Required properties:
 - dma-channel child node: Should have at least one channel and can have up to
 	two channels per device. This node specifies the properties of each
 	DMA channel (see child node properties below).
+- clocks: Input clock specifier. Refer to common clock bindings.
+- clock-names: List of input clocks
+	For VDMA:
+	Required elements: "s_axi_lite_aclk"
+	Optional elements: "m_axi_mm2s_aclk" "m_axi_s2mm_aclk",
+			   "m_axis_mm2s_aclk", "s_axis_s2mm_aclk"
+	For CDMA:
+	Required elements: "s_axi_lite_aclk", "m_axi_aclk"
+	FOR AXIDMA:
+	Required elements: "s_axi_lite_aclk"
+	Optional elements: "m_axi_mm2s_aclk", "m_axi_s2mm_aclk",
+			   "m_axi_sg_aclk"
 
 Required properties for VDMA:
 - xlnx,num-fstores: Should be the number of framebuffers as configured in h/w.
@@ -60,6 +72,9 @@ axi_vdma_0: axivdma at 40030000 {
 	xlnx,num-fstores = <0x8>;
 	xlnx,flush-fsync = <0x1>;
 	xlnx,addrwidth = <0x20>;
+	clocks = <&clk 0>, <&clk 1>, <&clk 2>, <&clk 3>, <&clk 4>;
+	clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk",
+		      "m_axis_mm2s_aclk", "s_axis_s2mm_aclk";
 	dma-channel at 40030000 {
 		compatible = "xlnx,axi-vdma-mm2s-channel";
 		interrupts = < 0 54 4 >;
-- 
2.1.1



From appana.durga.rao at xilinx.com  Thu May 12 02:43:45 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Thu, 12 May 2016 15:13:45 +0530
Subject: [RESEND PATCH v4 0/3] dmaengine: Add clock support for AXI DMAS
Message-ID: <1463046228-21651-1-git-send-email-appanad@xilinx.com>

This patch series adds basic clock support for AXI DMAS
This patch series is created on top of the dma-next branch.

Kedareswara rao Appana (3):
  dmaengine: vdma: Add config structure to differentiate dmas
  Documentation: DT: vdma: Add clock support for dmas
  dmaengine: vdma: Add clock support

 .../devicetree/bindings/dma/xilinx/xilinx_vdma.txt |  15 +
 drivers/dma/xilinx/xilinx_vdma.c                   | 307 ++++++++++++++++++---
 2 files changed, 289 insertions(+), 33 deletions(-)

-- 
2.1.1



From appana.durga.rao at xilinx.com  Thu May 12 02:43:46 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Thu, 12 May 2016 15:13:46 +0530
Subject: [RESEND PATCH v4 1/3] dmaengine: vdma: Add config structure to
 differentiate dmas
In-Reply-To: <1463046228-21651-1-git-send-email-appanad@xilinx.com>
References: <1463046228-21651-1-git-send-email-appanad@xilinx.com>
Message-ID: <1463046228-21651-2-git-send-email-appanad@xilinx.com>

This patch adds config structure in the driver to differentiate
AXI DMA's and to add more features(clock support etc..) to these DMA's.

Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
 drivers/dma/xilinx/xilinx_vdma.c | 83 ++++++++++++++++++++++++----------------
 1 file changed, 51 insertions(+), 32 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
index 626939b..1d50e05 100644
--- a/drivers/dma/xilinx/xilinx_vdma.c
+++ b/drivers/dma/xilinx/xilinx_vdma.c
@@ -342,6 +342,10 @@ struct xilinx_dma_chan {
 	void (*start_transfer)(struct xilinx_dma_chan *chan);
 };
 
+struct dma_config {
+	enum xdma_ip_type dmatype;
+};
+
 /**
  * struct xilinx_dma_device - DMA device structure
  * @regs: I/O mapped base address
@@ -351,7 +355,7 @@ struct xilinx_dma_chan {
  * @has_sg: Specifies whether Scatter-Gather is present or not
  * @flush_on_fsync: Flush on frame sync
  * @ext_addr: Indicates 64 bit addressing is supported by dma device
- * @dmatype: DMA ip type
+ * @dma_config: DMA config structure
  */
 struct xilinx_dma_device {
 	void __iomem *regs;
@@ -361,7 +365,7 @@ struct xilinx_dma_device {
 	bool has_sg;
 	u32 flush_on_fsync;
 	bool ext_addr;
-	enum xdma_ip_type dmatype;
+	const struct dma_config *dma_config;
 };
 
 /* Macros */
@@ -572,12 +576,12 @@ xilinx_dma_free_tx_descriptor(struct xilinx_dma_chan *chan,
 	if (!desc)
 		return;
 
-	if (chan->xdev->dmatype == XDMA_TYPE_VDMA) {
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 		list_for_each_entry_safe(segment, next, &desc->segments, node) {
 			list_del(&segment->node);
 			xilinx_vdma_free_tx_segment(chan, segment);
 		}
-	} else if (chan->xdev->dmatype == XDMA_TYPE_CDMA) {
+	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
 		list_for_each_entry_safe(cdma_segment, cdma_next,
 					 &desc->segments, node) {
 			list_del(&cdma_segment->node);
@@ -640,7 +644,7 @@ static void xilinx_dma_free_chan_resources(struct dma_chan *dchan)
 	dev_dbg(chan->dev, "Free all channel resources.\n");
 
 	xilinx_dma_free_descriptors(chan);
-	if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA)
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
 		xilinx_dma_free_tx_segment(chan, chan->seg_v);
 	dma_pool_destroy(chan->desc_pool);
 	chan->desc_pool = NULL;
@@ -710,13 +714,13 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 	 * We need the descriptor to be aligned to 64bytes
 	 * for meeting Xilinx VDMA specification requirement.
 	 */
-	if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA) {
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		chan->desc_pool = dma_pool_create("xilinx_dma_desc_pool",
 				   chan->dev,
 				   sizeof(struct xilinx_axidma_tx_segment),
 				   __alignof__(struct xilinx_axidma_tx_segment),
 				   0);
-	} else if (chan->xdev->dmatype == XDMA_TYPE_CDMA) {
+	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
 		chan->desc_pool = dma_pool_create("xilinx_cdma_desc_pool",
 				   chan->dev,
 				   sizeof(struct xilinx_cdma_tx_segment),
@@ -737,7 +741,7 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 		return -ENOMEM;
 	}
 
-	if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA)
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
 		/*
 		 * For AXI DMA case after submitting a pending_list, keep
 		 * an extra segment allocated so that the "next descriptor"
@@ -750,7 +754,7 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 
 	dma_cookie_init(dchan);
 
-	if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA) {
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		/* For AXI DMA resetting once channel will reset the
 		 * other channel as well so enable the interrupts here.
 		 */
@@ -758,7 +762,7 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 			      XILINX_DMA_DMAXR_ALL_IRQ_MASK);
 	}
 
-	if ((chan->xdev->dmatype == XDMA_TYPE_CDMA) && chan->has_sg)
+	if ((chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) && chan->has_sg)
 		dma_ctrl_set(chan, XILINX_DMA_REG_DMACR,
 			     XILINX_CDMA_CR_SGMODE);
 
@@ -789,7 +793,7 @@ static enum dma_status xilinx_dma_tx_status(struct dma_chan *dchan,
 	if (ret == DMA_COMPLETE || !txstate)
 		return ret;
 
-	if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA) {
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		spin_lock_irqsave(&chan->lock, flags);
 
 		desc = list_last_entry(&chan->active_list,
@@ -1331,12 +1335,12 @@ static void append_desc_queue(struct xilinx_dma_chan *chan,
 	 */
 	tail_desc = list_last_entry(&chan->pending_list,
 				    struct xilinx_dma_tx_descriptor, node);
-	if (chan->xdev->dmatype == XDMA_TYPE_VDMA) {
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 		tail_segment = list_last_entry(&tail_desc->segments,
 					       struct xilinx_vdma_tx_segment,
 					       node);
 		tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
-	} else if (chan->xdev->dmatype == XDMA_TYPE_CDMA) {
+	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
 		cdma_tail_segment = list_last_entry(&tail_desc->segments,
 						struct xilinx_cdma_tx_segment,
 						node);
@@ -1356,8 +1360,8 @@ append:
 	list_add_tail(&desc->node, &chan->pending_list);
 	chan->desc_pendingcount++;
 
-	if (chan->has_sg && (chan->xdev->dmatype == XDMA_TYPE_VDMA) &&
-	    unlikely(chan->desc_pendingcount > chan->num_frms)) {
+	if (chan->has_sg && (chan->xdev->dma_config->dmatype == XDMA_TYPE_VDMA)
+	    && unlikely(chan->desc_pendingcount > chan->num_frms)) {
 		dev_dbg(chan->dev, "desc pendingcount is too high\n");
 		chan->desc_pendingcount = chan->num_frms;
 	}
@@ -1810,7 +1814,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
 		chan->id = 0;
 
 		chan->ctrl_offset = XILINX_DMA_MM2S_CTRL_OFFSET;
-		if (xdev->dmatype == XDMA_TYPE_VDMA) {
+		if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 			chan->desc_offset = XILINX_VDMA_MM2S_DESC_OFFSET;
 
 			if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
@@ -1823,7 +1827,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
 		chan->id = 1;
 
 		chan->ctrl_offset = XILINX_DMA_S2MM_CTRL_OFFSET;
-		if (xdev->dmatype == XDMA_TYPE_VDMA) {
+		if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 			chan->desc_offset = XILINX_VDMA_S2MM_DESC_OFFSET;
 
 			if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
@@ -1844,9 +1848,9 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
 		return err;
 	}
 
-	if (xdev->dmatype == XDMA_TYPE_AXIDMA)
+	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
 		chan->start_transfer = xilinx_dma_start_transfer;
-	else if (xdev->dmatype == XDMA_TYPE_CDMA)
+	else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA)
 		chan->start_transfer = xilinx_cdma_start_transfer;
 	else
 		chan->start_transfer = xilinx_vdma_start_transfer;
@@ -1893,13 +1897,22 @@ static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec,
 	return dma_get_slave_channel(&xdev->chan[chan_id]->common);
 }
 
+static const struct dma_config axidma_config = {
+	.dmatype = XDMA_TYPE_AXIDMA,
+};
+
+static const struct dma_config axicdma_config = {
+	.dmatype = XDMA_TYPE_CDMA,
+};
+
+static const struct dma_config axivdma_config = {
+	.dmatype = XDMA_TYPE_VDMA,
+};
+
 static const struct of_device_id xilinx_dma_of_ids[] = {
-	{ .compatible = "xlnx,axi-dma-1.00.a",
-	  .data = (void *)XDMA_TYPE_AXIDMA },
-	{ .compatible = "xlnx,axi-cdma-1.00.a",
-	  .data = (void *)XDMA_TYPE_CDMA },
-	{ .compatible = "xlnx,axi-vdma-1.00.a",
-	  .data = (void *)XDMA_TYPE_VDMA },
+	{ .compatible = "xlnx,axi-dma-1.00.a", .data = &axidma_config },
+	{ .compatible = "xlnx,axi-cdma-1.00.a", .data = &axicdma_config },
+	{ .compatible = "xlnx,axi-vdma-1.00.a", .data = &axivdma_config },
 	{}
 };
 MODULE_DEVICE_TABLE(of, xilinx_dma_of_ids);
@@ -1914,7 +1927,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
 	struct xilinx_dma_device *xdev;
-	struct device_node *child;
+	struct device_node *child, *np = pdev->dev.of_node;
 	struct resource *io;
 	u32 num_frames, addr_width;
 	int i, err;
@@ -1925,7 +1938,13 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	xdev->dev = &pdev->dev;
-	xdev->dmatype = (enum xdma_ip_type)of_device_get_match_data(&pdev->dev);
+	if (np) {
+		const struct of_device_id *match;
+
+		match = of_match_node(xilinx_dma_of_ids, np);
+		if (match && match->data)
+			xdev->dma_config = match->data;
+	}
 
 	/* Request and map I/O memory */
 	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1936,7 +1955,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 	/* Retrieve the DMA engine properties from the device tree */
 	xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg");
 
-	if (xdev->dmatype == XDMA_TYPE_VDMA) {
+	if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 		err = of_property_read_u32(node, "xlnx,num-fstores",
 					   &num_frames);
 		if (err < 0) {
@@ -1968,7 +1987,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 	xdev->common.dev = &pdev->dev;
 
 	INIT_LIST_HEAD(&xdev->common.channels);
-	if (!(xdev->dmatype == XDMA_TYPE_CDMA)) {
+	if (!(xdev->dma_config->dmatype == XDMA_TYPE_CDMA)) {
 		dma_cap_set(DMA_SLAVE, xdev->common.cap_mask);
 		dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask);
 	}
@@ -1980,12 +1999,12 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 	xdev->common.device_terminate_all = xilinx_dma_terminate_all;
 	xdev->common.device_tx_status = xilinx_dma_tx_status;
 	xdev->common.device_issue_pending = xilinx_dma_issue_pending;
-	if (xdev->dmatype == XDMA_TYPE_AXIDMA) {
+	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg;
 		/* Residue calculation is supported by only AXI DMA */
 		xdev->common.residue_granularity =
 					  DMA_RESIDUE_GRANULARITY_SEGMENT;
-	} else if (xdev->dmatype == XDMA_TYPE_CDMA) {
+	} else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
 		dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask);
 		xdev->common.device_prep_dma_memcpy = xilinx_cdma_prep_memcpy;
 	} else {
@@ -2002,7 +2021,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 			goto error;
 	}
 
-	if (xdev->dmatype == XDMA_TYPE_VDMA) {
+	if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 		for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
 			if (xdev->chan[i])
 				xdev->chan[i]->num_frms = num_frames;
-- 
2.1.1



From appana.durga.rao at xilinx.com  Thu May 12 02:43:48 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Thu, 12 May 2016 15:13:48 +0530
Subject: [RESEND PATCH v4 3/3] dmaengine: vdma: Add clock support
In-Reply-To: <1463046228-21651-1-git-send-email-appanad@xilinx.com>
References: <1463046228-21651-1-git-send-email-appanad@xilinx.com>
Message-ID: <1463046228-21651-4-git-send-email-appanad@xilinx.com>

Added basic clock support for axi dma's.
The clocks are requested at probe and released at remove.

Reviewed-by: Shubhrajyoti Datta <shubhraj at xilinx.com>
Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
 drivers/dma/xilinx/xilinx_vdma.c | 226 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 224 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
index 1d50e05..31ae528 100644
--- a/drivers/dma/xilinx/xilinx_vdma.c
+++ b/drivers/dma/xilinx/xilinx_vdma.c
@@ -44,6 +44,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 
 #include "../dmaengine.h"
 
@@ -344,6 +345,9 @@ struct xilinx_dma_chan {
 
 struct dma_config {
 	enum xdma_ip_type dmatype;
+	int (*clk_init)(struct platform_device *pdev, struct clk **axi_clk,
+			struct clk **tx_clk, struct clk **txs_clk,
+			struct clk **rx_clk, struct clk **rxs_clk);
 };
 
 /**
@@ -355,7 +359,13 @@ struct dma_config {
  * @has_sg: Specifies whether Scatter-Gather is present or not
  * @flush_on_fsync: Flush on frame sync
  * @ext_addr: Indicates 64 bit addressing is supported by dma device
+ * @pdev: Platform device structure pointer
  * @dma_config: DMA config structure
+ * @axi_clk: DMA Axi4-lite interace clock
+ * @tx_clk: DMA mm2s clock
+ * @txs_clk: DMA mm2s stream clock
+ * @rx_clk: DMA s2mm clock
+ * @rxs_clk: DMA s2mm stream clock
  */
 struct xilinx_dma_device {
 	void __iomem *regs;
@@ -365,7 +375,13 @@ struct xilinx_dma_device {
 	bool has_sg;
 	u32 flush_on_fsync;
 	bool ext_addr;
+	struct platform_device  *pdev;
 	const struct dma_config *dma_config;
+	struct clk *axi_clk;
+	struct clk *tx_clk;
+	struct clk *txs_clk;
+	struct clk *rx_clk;
+	struct clk *rxs_clk;
 };
 
 /* Macros */
@@ -1756,6 +1772,195 @@ static void xilinx_dma_chan_remove(struct xilinx_dma_chan *chan)
 	list_del(&chan->common.device_node);
 }
 
+static int axidma_clk_init(struct platform_device *pdev, struct clk **axi_clk,
+			    struct clk **tx_clk, struct clk **rx_clk,
+			    struct clk **sg_clk, struct clk **tmp_clk)
+{
+	int err;
+
+	*tmp_clk = NULL;
+
+	*axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
+	if (IS_ERR(*axi_clk)) {
+		err = PTR_ERR(*axi_clk);
+		dev_err(&pdev->dev, "failed to get axi_aclk (%u)\n", err);
+		return err;
+	}
+
+	*tx_clk = devm_clk_get(&pdev->dev, "m_axi_mm2s_aclk");
+	if (IS_ERR(*tx_clk))
+		*tx_clk = NULL;
+
+	*rx_clk = devm_clk_get(&pdev->dev, "m_axi_s2mm_aclk");
+	if (IS_ERR(*rx_clk))
+		*rx_clk = NULL;
+
+	*sg_clk = devm_clk_get(&pdev->dev, "m_axi_sg_aclk");
+	if (IS_ERR(*sg_clk))
+		*sg_clk = NULL;
+
+	err = clk_prepare_enable(*axi_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axi_clk (%u)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*tx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
+		goto err_disable_axiclk;
+	}
+
+	err = clk_prepare_enable(*rx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable rx_clk (%u)\n", err);
+		goto err_disable_txclk;
+	}
+
+	err = clk_prepare_enable(*sg_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable sg_clk (%u)\n", err);
+		goto err_disable_rxclk;
+	}
+
+	return 0;
+
+err_disable_rxclk:
+	clk_disable_unprepare(*rx_clk);
+err_disable_txclk:
+	clk_disable_unprepare(*tx_clk);
+err_disable_axiclk:
+	clk_disable_unprepare(*axi_clk);
+
+	return err;
+}
+
+static int axicdma_clk_init(struct platform_device *pdev, struct clk **axi_clk,
+			    struct clk **dev_clk, struct clk **tmp_clk,
+			    struct clk **tmp1_clk, struct clk **tmp2_clk)
+{
+	int err;
+
+	*tmp_clk = NULL;
+	*tmp1_clk = NULL;
+	*tmp2_clk = NULL;
+
+	*axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
+	if (IS_ERR(*axi_clk)) {
+		err = PTR_ERR(*axi_clk);
+		dev_err(&pdev->dev, "failed to get axi_clk (%u)\n", err);
+		return err;
+	}
+
+	*dev_clk = devm_clk_get(&pdev->dev, "m_axi_aclk");
+	if (IS_ERR(*dev_clk)) {
+		err = PTR_ERR(*dev_clk);
+		dev_err(&pdev->dev, "failed to get dev_clk (%u)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*axi_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axi_clk (%u)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*dev_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable dev_clk (%u)\n", err);
+		goto err_disable_axiclk;
+	}
+
+	return 0;
+
+err_disable_axiclk:
+	clk_disable_unprepare(*axi_clk);
+
+	return err;
+}
+
+static int axivdma_clk_init(struct platform_device *pdev, struct clk **axi_clk,
+			    struct clk **tx_clk, struct clk **txs_clk,
+			    struct clk **rx_clk, struct clk **rxs_clk)
+{
+	int err;
+
+	*axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
+	if (IS_ERR(*axi_clk)) {
+		err = PTR_ERR(*axi_clk);
+		dev_err(&pdev->dev, "failed to get axi_aclk (%u)\n", err);
+		return err;
+	}
+
+	*tx_clk = devm_clk_get(&pdev->dev, "m_axi_mm2s_aclk");
+	if (IS_ERR(*tx_clk))
+		*tx_clk = NULL;
+
+	*txs_clk = devm_clk_get(&pdev->dev, "m_axis_mm2s_aclk");
+	if (IS_ERR(*txs_clk))
+		*txs_clk = NULL;
+
+	*rx_clk = devm_clk_get(&pdev->dev, "m_axi_s2mm_aclk");
+	if (IS_ERR(*rx_clk))
+		*rx_clk = NULL;
+
+	*rxs_clk = devm_clk_get(&pdev->dev, "s_axis_s2mm_aclk");
+	if (IS_ERR(*rxs_clk))
+		*rxs_clk = NULL;
+
+	err = clk_prepare_enable(*axi_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axi_clk (%u)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*tx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
+		goto err_disable_axiclk;
+	}
+
+	err = clk_prepare_enable(*txs_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable txs_clk (%u)\n", err);
+		goto err_disable_txclk;
+	}
+
+	err = clk_prepare_enable(*rx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable rx_clk (%u)\n", err);
+		goto err_disable_txsclk;
+	}
+
+	err = clk_prepare_enable(*rxs_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable rxs_clk (%u)\n", err);
+		goto err_disable_rxclk;
+	}
+
+	return 0;
+
+err_disable_rxclk:
+	clk_disable_unprepare(*rx_clk);
+err_disable_txsclk:
+	clk_disable_unprepare(*txs_clk);
+err_disable_txclk:
+	clk_disable_unprepare(*tx_clk);
+err_disable_axiclk:
+	clk_disable_unprepare(*axi_clk);
+
+	return err;
+}
+
+static void xdma_disable_allclks(struct xilinx_dma_device *xdev)
+{
+	clk_disable_unprepare(xdev->rxs_clk);
+	clk_disable_unprepare(xdev->rx_clk);
+	clk_disable_unprepare(xdev->txs_clk);
+	clk_disable_unprepare(xdev->tx_clk);
+	clk_disable_unprepare(xdev->axi_clk);
+}
+
 /**
  * xilinx_dma_chan_probe - Per Channel Probing
  * It get channel features from the device tree entry and
@@ -1899,14 +2104,17 @@ static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec,
 
 static const struct dma_config axidma_config = {
 	.dmatype = XDMA_TYPE_AXIDMA,
+	.clk_init = axidma_clk_init,
 };
 
 static const struct dma_config axicdma_config = {
 	.dmatype = XDMA_TYPE_CDMA,
+	.clk_init = axicdma_clk_init,
 };
 
 static const struct dma_config axivdma_config = {
 	.dmatype = XDMA_TYPE_VDMA,
+	.clk_init = axivdma_clk_init,
 };
 
 static const struct of_device_id xilinx_dma_of_ids[] = {
@@ -1925,6 +2133,9 @@ MODULE_DEVICE_TABLE(of, xilinx_dma_of_ids);
  */
 static int xilinx_dma_probe(struct platform_device *pdev)
 {
+	int (*clk_init)(struct platform_device *, struct clk **, struct clk **,
+			struct clk **, struct clk **, struct clk **)
+					= axivdma_clk_init;
 	struct device_node *node = pdev->dev.of_node;
 	struct xilinx_dma_device *xdev;
 	struct device_node *child, *np = pdev->dev.of_node;
@@ -1942,10 +2153,17 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 		const struct of_device_id *match;
 
 		match = of_match_node(xilinx_dma_of_ids, np);
-		if (match && match->data)
+		if (match && match->data) {
 			xdev->dma_config = match->data;
+			clk_init = xdev->dma_config->clk_init;
+		}
 	}
 
+	err = clk_init(pdev, &xdev->axi_clk, &xdev->tx_clk, &xdev->txs_clk,
+		       &xdev->rx_clk, &xdev->rxs_clk);
+	if (err)
+		return err;
+
 	/* Request and map I/O memory */
 	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	xdev->regs = devm_ioremap_resource(&pdev->dev, io);
@@ -2018,7 +2236,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 	for_each_child_of_node(node, child) {
 		err = xilinx_dma_chan_probe(xdev, child);
 		if (err < 0)
-			goto error;
+			goto disable_clks;
 	}
 
 	if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
@@ -2042,6 +2260,8 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 
 	return 0;
 
+disable_clks:
+	xdma_disable_allclks(xdev);
 error:
 	for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
 		if (xdev->chan[i])
@@ -2069,6 +2289,8 @@ static int xilinx_dma_remove(struct platform_device *pdev)
 		if (xdev->chan[i])
 			xilinx_dma_chan_remove(xdev->chan[i]);
 
+	xdma_disable_allclks(xdev);
+
 	return 0;
 }
 
-- 
2.1.1



From catalin.marinas at arm.com  Thu May 12 02:49:16 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 12 May 2016 10:49:16 +0100
Subject: [PATCH v6 13/14] arm64, acpi, numa: NUMA support based on SRAT
 and SLIT
In-Reply-To: <5733C8F5.6090206@caviumnetworks.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <1461780436-27182-14-git-send-email-ddaney.cavm@gmail.com>
 <20160511103929.GC3051@e104818-lin.cambridge.arm.com>
 <5733C8F5.6090206@caviumnetworks.com>
Message-ID: <20160512094915.GD11226@e104818-lin.cambridge.arm.com>

On Wed, May 11, 2016 at 05:06:13PM -0700, David Daney wrote:
> On 05/11/2016 03:39 AM, Catalin Marinas wrote:
> >On Wed, Apr 27, 2016 at 11:07:15AM -0700, David Daney wrote:
> >>+static int __init get_mpidr_in_madt(int acpi_id, u64 *mpidr)
> >>+{
> >>+	unsigned long madt_end, entry;
> >>+	struct acpi_table_madt *madt;
> >>+	acpi_size tbl_size;
> >>+
> >>+	if (ACPI_FAILURE(acpi_get_table_with_size(ACPI_SIG_MADT, 0,
> >>+			(struct acpi_table_header **)&madt, &tbl_size)))
> >>+		return -ENODEV;
> >>+
> >>+	entry = (unsigned long)madt;
> >>+	madt_end = entry + madt->header.length;
> >>+
> >>+	/* Parse all entries looking for a match. */
> >>+	entry += sizeof(struct acpi_table_madt);
> >>+	while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
> >>+		struct acpi_subtable_header *header =
> >>+			(struct acpi_subtable_header *)entry;
> >>+
> >>+		if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
> >>+			struct acpi_madt_generic_interrupt *gicc =
> >>+				container_of(header,
> >>+				struct acpi_madt_generic_interrupt, header);
> >>+
> >>+			if ((gicc->flags & ACPI_MADT_ENABLED) &&
> >>+			    (gicc->uid == acpi_id)) {
> >>+				*mpidr = gicc->arm_mpidr;
> >>+				early_acpi_os_unmap_memory(madt, tbl_size);
> >>+				return 0;
> >>+			}
> >>+		}
> >>+		entry += header->length;
> >>+	}
> >>+
> >>+	early_acpi_os_unmap_memory(madt, tbl_size);
> >>+	return -ENODEV;
> >>+}
> >>+
> >>+/* Callback for Proximity Domain -> ACPI processor UID mapping */
> >>+void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa)
> >>+{
> >>+	int pxm, node;
> >>+	u64 mpidr;
> >>+
> >>+	if (srat_disabled())
> >>+		return;
> >>+
> >>+	if (pa->header.length < sizeof(struct acpi_srat_gicc_affinity)) {
> >>+		pr_err("SRAT: Invalid SRAT header length: %d\n",
> >>+			pa->header.length);
> >>+		bad_srat();
> >>+		return;
> >>+	}
> >>+
> >>+	if (!(pa->flags & ACPI_SRAT_GICC_ENABLED))
> >>+		return;
> >>+
> >>+	if (cpus_in_srat >= NR_CPUS) {
> >>+		pr_warn_once("SRAT: cpu_to_node_map[%d] is too small, may not be able to use all cpus\n",
> >>+			     NR_CPUS);
> >>+		return;
> >>+	}
> >>+
> >>+	pxm = pa->proximity_domain;
> >>+	node = acpi_map_pxm_to_node(pxm);
> >>+
> >>+	if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
> >>+		pr_err("SRAT: Too many proximity domains %d\n", pxm);
> >>+		bad_srat();
> >>+		return;
> >>+	}
> >>+
> >>+	if (get_mpidr_in_madt(pa->acpi_processor_uid, &mpidr)) {
> >>+		pr_err("SRAT: PXM %d with ACPI ID %d has no valid MPIDR in MADT\n",
> >>+			pxm, pa->acpi_processor_uid);
> >>+		bad_srat();
> >>+		return;
> >>+	}
> >
> >I wonder whether you could replace the get_mpidr_in_madt() function with
> >something like acpi_get_phys_id(). It looks like get_mpidr_in_madt()
> >duplicates functionality already available elsewhere.
> 
> I just tried that, and it doesn't work.
> 
> The problem is that this code is being run very early in the boot, and
> kmalloc cannot be used.  acpi_get_phys_id() and its ilk can only be used
> once we have working kmalloc.  We need to extract the NUMA information early
> like this precisely because it is needed to initializing the slab system
> 
> Notice that we are using early_acpi_os_unmap_memory() et al. in
> get_mpidr_in_madt() explicitly for this reason.
> 
> In summary: I don't think we need another revision of this patch, it is like
> this for a good reason.

Slightly confusing, in another reply you said you are going to address
my comment. So, is it doable?

-- 
Catalin


From peter.maydell at linaro.org  Thu May 12 02:56:57 2016
From: peter.maydell at linaro.org (Peter Maydell)
Date: Thu, 12 May 2016 10:56:57 +0100
Subject: [PATCH v3 27/55] KVM: arm/arm64: vgic-new: Add PRIORITY registers
 handlers
In-Reply-To: <57344889.1050802@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-28-git-send-email-andre.przywara@arm.com>
 <57344889.1050802@arm.com>
Message-ID: <CAFEAcA95nt_4wueOTzergNfupg4zGMTj_EQgCLrRunpg6GUbPA@mail.gmail.com>

On 12 May 2016 at 10:10, Marc Zyngier <marc.zyngier at arm.com> wrote:
> This is wrong. We should only write the number of bits of priority we
> actually emulate. And given that we use a common framework for v2 and
> v3, this should probably be 5 bits (32 priorities should be enough for
> everybody).

FWIW QEMU's GICv2 and GICv3 emulations both implement the full
8 bits of priority.

thanks
-- PMM


From lorenzo.pieralisi at arm.com  Thu May 12 03:01:03 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Thu, 12 May 2016 11:01:03 +0100
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <20160511224314.GD28812@localhost>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
 <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>
 <20160511101101.GA16101@red-moon>
 <CAJZ5v0hgw929W5PjF0PqT+ssiOHd8TeJoSQcz4NUiAovZY2pfQ@mail.gmail.com>
 <20160511224314.GD28812@localhost>
Message-ID: <20160512100103.GA19460@red-moon>

On Wed, May 11, 2016 at 05:43:14PM -0500, Bjorn Helgaas wrote:
> On Wed, May 11, 2016 at 10:30:51PM +0200, Rafael J. Wysocki wrote:
> > On Wed, May 11, 2016 at 12:11 PM, Lorenzo Pieralisi
> > <lorenzo.pieralisi at arm.com> wrote:
> > > On Tue, May 10, 2016 at 08:37:00PM +0200, Rafael J. Wysocki wrote:
> > >> On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> > >> > This patch provides a way to set the ACPI companion in PCI code.
> > >> > We define acpi_pci_set_companion() to set the ACPI companion pointer and
> > >> > call it from PCI core code. The function is stub for now.
> > >> >
> > >> > Signed-off-by: Jayachandran C <jchandra at broadcom.com>
> > >> > Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> > >> > ---
> > >> >  drivers/pci/probe.c      | 2 ++
> > >> >  include/linux/pci-acpi.h | 4 ++++
> > >> >  2 files changed, 6 insertions(+)
> > >> >
> > >> > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> > >> > index 8004f67..fb0b752 100644
> > >> > --- a/drivers/pci/probe.c
> > >> > +++ b/drivers/pci/probe.c
> > >> > @@ -12,6 +12,7 @@
> > >> >  #include <linux/slab.h>
> > >> >  #include <linux/module.h>
> > >> >  #include <linux/cpumask.h>
> > >> > +#include <linux/pci-acpi.h>
> > >> >  #include <linux/pci-aspm.h>
> > >> >  #include <linux/aer.h>
> > >> >  #include <linux/acpi.h>
> > >> > @@ -2141,6 +2142,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
> > >> >         bridge->dev.parent = parent;
> > >> >         bridge->dev.release = pci_release_host_bridge_dev;
> > >> >         dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
> > >> > +       acpi_pci_set_companion(bridge);
> > >>
> > >> Yes, we'll probably add something similar here.
> > >>
> > >> Do I think now is the right time to do that?  No.
> > >>
> > >> >         error = pcibios_root_bridge_prepare(bridge);
> > >> >         if (error) {
> > >> >                 kfree(bridge);
> > >> > diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
> > >> > index 09f9f02..1baa515 100644
> > >> > --- a/include/linux/pci-acpi.h
> > >> > +++ b/include/linux/pci-acpi.h
> > >> > @@ -111,6 +111,10 @@ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
> > >> >  static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
> > >> >  #endif /* CONFIG_ACPI */
> > >> >
> > >> > +static inline void acpi_pci_set_companion(struct pci_host_bridge *bridge)
> > >> > +{
> > >> > +}
> > >> > +
> > >> >  static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus)
> > >> >  {
> > >> >         return 0;
> > >> > --
> > >>
> > >> Honestly, to me it looks like this series is trying very hard to avoid
> > >> doing any PCI host bridge configuration stuff from arch/arm64/
> > >> although (a) that might be simpler and (b) it would allow us to
> > >> identify the code that's common between *all* architectures using ACPI
> > >> support for host bridge configuration and to move *that* to a common
> > >> place later.  As done here it seems to be following the "ARM64 is
> > >> generic and the rest of the world is special" line which isn't really
> > >> helpful.
> > >
> > > I think patch [1-2] should be merged regardless (they may require minor
> > > tweaks if we decide to move pci_acpi_scan_root() to arch/arm64 though,
> > > for include files location). I guess you are referring to patch 8 in
> > > your comments above, which boils down to deciding whether:
> > >
> > > - pci_acpi_scan_root() (and unfortunately all the MCFG/ECAM handling that
> > >   goes with it) should live in arch/arm64 or drivers/acpi
> > 
> > To be precise, everything under #ifdef CONFIG_ACPI_PCI_HOST_GENERIC or
> > equivalent is de facto ARM64-specific, because (as it stands in the
> > patch series) ARM64 is the only architecture that will select that
> > option.  Unless you are aware of any more architectures planning to
> > use ACPI (and I'm not aware of any), it will stay the only
> > architecture selecting it in the foreseeable future.
> > 
> > Therefore you could replace CONFIG_ACPI_PCI_HOST_GENERIC with
> > CONFIG_ARM64 everywhere in that code which is why in my opinion the
> > code should live somewhere under arch/arm64/.
> > 
> > Going forward, it should be possible to identify common parts of the
> > PCI host bridge configuration code in arch/ and move it to
> > drivers/acpi/ or drivers/pci/, but I bet that won't be the entire code
> > this series puts under CONFIG_ACPI_PCI_HOST_GENERIC.
> > 
> > The above leads to a quite straightforward conclusion about the order
> > in which to do things: I'd add ACPI support for PCI host bridge on
> > ARM64 following what's been done on ia64 (as x86 is more quirky and
> > kludgy overall) as far as reasonably possible first and then think
> > about moving common stuff to a common place.
> 
> That does seem like a reasonable approach.  I had hoped to get more of
> this in for v4.7, but we don't have much time left.  Maybe some of
> Rafael's comments can be addressed by moving and slight restructuring
> and we can still squeeze it in.

Yes, it seems like a reasonable approach, as long as we accept that
part of this series has to live in arch/arm64 otherwise we are going
round in circles (because that's the gist of this discussion, to
decide where this code has to live, I do not think there is any objection
to the code per-se anymore).

I suggest we post a v8 (with code move to arch/arm64) end of merge
window (or you prefer seeing patches now to prevent any additional
changes later ?), my aim is to get this into -next (whether via arm64 or
pci tree it has to be decided) as early as possible for next cycle (-rc1)
so that it can get exposure and testing, I do not think that missing the
merge window is a big issue if we agree that the code is ready to go.

> The first three patches:
> 
>   PCI: Provide common functions for ECAM mapping
>   PCI: generic, thunder: Use generic ECAM API
>   PCI, of: Move PCI I/O space management to PCI core code
> 
> seem relatively straightforward, and I applied them to pci/arm64 with
> the intent of merging them unless there are objections.  I made the
> following tweaks, mainly to try to improve some error messages:

Ok, thanks a lot !

Lorenzo

> diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
> index 3d52005..e1add01 100644
> --- a/drivers/pci/ecam.c
> +++ b/drivers/pci/ecam.c
> @@ -24,9 +24,9 @@
>  #include "ecam.h"
>  
>  /*
> - * On 64 bit systems, we do a single ioremap for the whole config space
> - * since we have enough virtual address range available. On 32 bit, do an
> - * ioremap per bus.
> + * On 64-bit systems, we do a single ioremap for the whole config space
> + * since we have enough virtual address range available.  On 32-bit, we
> + * ioremap the config space for each bus individually.
>   */
>  static const bool per_bus_mapping = !config_enabled(CONFIG_64BIT);
>  
> @@ -42,6 +42,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
>  {
>  	struct pci_config_window *cfg;
>  	unsigned int bus_range, bus_range_max, bsz;
> +	struct resource *conflict;
>  	int i, err;
>  
>  	if (busr->start > busr->end)
> @@ -58,10 +59,10 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
>  	bus_range = resource_size(&cfg->busr);
>  	bus_range_max = resource_size(cfgres) >> ops->bus_shift;
>  	if (bus_range > bus_range_max) {
> -		dev_warn(dev, "bus max %#x reduced to %#x",
> -					bus_range, bus_range_max);
>  		bus_range = bus_range_max;
>  		cfg->busr.end = busr->start + bus_range - 1;
> +		dev_warn(dev, "ECAM area %pR can only accommodate %pR (reduced from %pR desired)\n",
> +			 cfgres, &cfg->busr, busr);
>  	}
>  	bsz = 1 << ops->bus_shift;
>  
> @@ -70,9 +71,11 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
>  	cfg->res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
>  	cfg->res.name = "PCI ECAM";
>  
> -	err = request_resource(&iomem_resource, &cfg->res);
> -	if (err) {
> -		dev_err(dev, "request ECAM res %pR failed\n", &cfg->res);
> +	conflict = request_resource(&iomem_resource, &cfg->res);
> +	if (conflict) {
> +		err = -EBUSY;
> +		dev_err(dev, "can't claim ECAM area %pR: address conflict with %s %pR\n",
> +			&cfg->res, conflict->name, conflict);
>  		goto err_exit;
>  	}
>  
> diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
> index 1ad2176..9878beb 100644
> --- a/drivers/pci/ecam.h
> +++ b/drivers/pci/ecam.h
> @@ -33,7 +33,7 @@ struct pci_ecam_ops {
>  
>  /*
>   * struct to hold the mappings of a config space window. This
> - * is expected to be used as sysdata for PCI controlllers which
> + * is expected to be used as sysdata for PCI controllers that
>   * use ECAM.
>   */
>  struct pci_config_window {
> @@ -43,11 +43,11 @@ struct pci_config_window {
>  	struct pci_ecam_ops		*ops;
>  	union {
>  		void __iomem		*win;	/* 64-bit single mapping */
> -		void __iomem		**winp; /* 32-bit per bus mapping */
> +		void __iomem		**winp; /* 32-bit per-bus mapping */
>  	};
>  };
>  
> -/* create and free for pci_config_window */
> +/* create and free pci_config_window */
>  struct pci_config_window *pci_ecam_create(struct device *dev,
>  		struct resource *cfgres, struct resource *busr,
>  		struct pci_ecam_ops *ops);
> @@ -56,11 +56,11 @@ void pci_ecam_free(struct pci_config_window *cfg);
>  /* map_bus when ->sysdata is an instance of pci_config_window */
>  void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
>  			       int where);
> -/* default ECAM ops, bus shift 20, generic read and write */
> +/* default ECAM ops */
>  extern struct pci_ecam_ops pci_generic_ecam_ops;
>  
>  #ifdef CONFIG_PCI_HOST_GENERIC
> -/* for DT based pci controllers that support ECAM */
> +/* for DT-based PCI controllers that support ECAM */
>  int pci_host_common_probe(struct platform_device *pdev,
>  			  struct pci_ecam_ops *ops);
>  #endif
> 


From matt at codeblueprint.co.uk  Thu May 12 03:04:10 2016
From: matt at codeblueprint.co.uk (Matt Fleming)
Date: Thu, 12 May 2016 11:04:10 +0100
Subject: [PATCH] Xen: EFI: Parse DT parameters for Xen specific UEFI
In-Reply-To: <5733E8CF.3070004@huawei.com>
References: <1462523526-3172-1-git-send-email-zhaoshenglong@huawei.com>
 <20160511122730.GU2839@codeblueprint.co.uk>
 <57333533.2030206@linaro.org>
 <20160511232444.GY2839@codeblueprint.co.uk>
 <5733E8CF.3070004@huawei.com>
Message-ID: <20160512100410.GA2728@codeblueprint.co.uk>

On Thu, 12 May, at 10:22:07AM, Shannon Zhao wrote:
> 
> As said above, I will rebase this patch on top of the EFI next branch.

OK thanks.

Note that it is not possible to escape merge conflicts, since there
are changes in the xen tip tree that are not in the EFI next branch
and vice versa.

For example these commits from xen/linux-next look relevant,

  8e147fcc3ffa ("FDT: Add a helper to get the subnode by given name")
  37060935dc04 ("ARM64: XEN: Add a function to initialize Xen specific UEFI runtime services")
  acb2c923a860 ("XEN: EFI: Move x86 specific codes to architecture directory")
  055be2d42408 ("ARM: Xen: Document UEFI support on Xen ARM virtual platforms")
  3915fea959b6 ("ARM: XEN: Move xen_early_init() before efi_init()")

Linus, Stefano, tip-folks: I'm soliciting opinions on the correct way
to handle this inter-tree dependency where we've got changes to EFI
code in two separate trees and Shannon wants to write patches on top
of both.

I'm guessing the best solution is to merge xen/linux-next and efi/next
into a topic branch either in the EFI tree or Xen tree, but I want to
be cautious of the branch history that will create.

(In hindsight all of these change should have probably gone via the
EFI tree.)


From sudeep.holla at arm.com  Thu May 12 03:08:46 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Thu, 12 May 2016 11:08:46 +0100
Subject: [PSCI DISCUSS] How to implement standby and suspend-to-ram by PSCI
In-Reply-To: <DB3PR04MB08125A628F5034749F8109D884730@DB3PR04MB0812.eurprd04.prod.outlook.com>
References: <DB3PR04MB0812DAA98F71C30E8A8832E3847D0@DB3PR04MB0812.eurprd04.prod.outlook.com>
 <572C9BF2.9010004@arm.com>
 <DB3PR04MB08125A628F5034749F8109D884730@DB3PR04MB0812.eurprd04.prod.outlook.com>
Message-ID: <5734562E.40303@arm.com>



On 12/05/16 10:42, Hongbo Zhang wrote:
> Hi Sudeep,
> 

[...]

> 
> Sleep state:
> All cores are in WFI state,
> Core cluster is in standby state, e.g. L2 cache is flushed then stops
> snooping,
> Only those modules which are required to wake up the device still have a
> running clock, other device modules in chip are clock gated.
> 
> Deep sleep state:
> ARM cores and DDR controller are switched off,
> DDR is in self-refresh mode,
> VDD power to off domain IPs are removed, Only the blocks needed to
> detect wake up and sequence the chip out of deep sleep are on.
> 
> For the two states, except for the wake-up devices, all the other device
> dirver's suspend callback needs to be called because those devices will
> be clock or power gated off. So, the kernel suspend process (freeze
> tasks, suspend devices etc) are needed for our sleep and deep sleep states.
> In fact we've already implemented these two stated by legacy way, e.g.
> mapping sleep state to STANDBY and deep sleep to MEM, both states are
> implemented in one traditional .enter callback and can be indexed by a
> 'state' parameter.
> 

Yes I understand that.

> While transferring to PSCI, we met the problem I mentioned.
> 
> As to the freeze(suspend-to-idle), it is described as "a generic, pure
> software, light-weight, system sleep state" in the Document, and the
> fact is only acpi is using it, 

No, it independent of ACPI. It can be used on any platform with CPUIdle
support.

> what's more, I don't think it satisfy us
> well, because the freeze_enter() is executed before
> disable_nonboot_cpus() and syscore_suspend(), while the later two are
> necessary for us.
> 

Care to explain ? With suspend-to-idle, wakeup latency is much lesser as
the CPUs are not hotplugged out. I don't think it makes huge different
with power on ARM platforms. So its is much better than standby which
does CPU hotplugging IMO.

> So it seems another 'state' parameter for SYSTEM_SUSPEND can settle this
> problem, but it is lack in the spec.
> 

If you still think you can't make use of suspend-to-idle with added
advantage of reduced wakeup latency, please send email with all the
details to errata at arm.com as suggested in the PSCI specification.

> There are diverse kinds of ARM SOC, and divers kind of peripheral
> devices in each SOC, so even for the SYSTEM_SUSPEND, there may be
> different states too(deeper or shallower states of each device, more or
> less of devices are put to idle), the more the PSCI spec supports, the
> better.
> 

With runtime PM, you can work out on the peripheral device PM directly,
so I can't imagine how the diversity there adds to SYSTEM_SUSPEND
complexity.

-- 
Regards,
Sudeep


From marc.zyngier at arm.com  Thu May 12 03:09:19 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 12 May 2016 11:09:19 +0100
Subject: [PATCH v3 27/55] KVM: arm/arm64: vgic-new: Add PRIORITY registers
 handlers
In-Reply-To: <CAFEAcA95nt_4wueOTzergNfupg4zGMTj_EQgCLrRunpg6GUbPA@mail.gmail.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-28-git-send-email-andre.przywara@arm.com>
 <57344889.1050802@arm.com>
 <CAFEAcA95nt_4wueOTzergNfupg4zGMTj_EQgCLrRunpg6GUbPA@mail.gmail.com>
Message-ID: <5734564F.2080001@arm.com>

On 12/05/16 10:56, Peter Maydell wrote:
> On 12 May 2016 at 10:10, Marc Zyngier <marc.zyngier at arm.com> wrote:
>> This is wrong. We should only write the number of bits of priority we
>> actually emulate. And given that we use a common framework for v2 and
>> v3, this should probably be 5 bits (32 priorities should be enough for
>> everybody).
> 
> FWIW QEMU's GICv2 and GICv3 emulations both implement the full
> 8 bits of priority.

On GICv2, GICH_APR is only 32bit, implying that a guest can only ever
use 5 bits of priority. GICH_VTR also says that the only allowed value
for PRIbits is 32 priority levels (iow 5 bits).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From oliver at schinagl.nl  Thu May 12 03:10:51 2016
From: oliver at schinagl.nl (Olliver Schinagl)
Date: Thu, 12 May 2016 12:10:51 +0200
Subject: [PATCHv2] devicetree: sunxi: Add OLinuXino Lime2 eMMC to the Makefile
Message-ID: <1463047851-2039-1-git-send-email-oliver@schinagl.nl>

commit 27dd9af6bc (ARM: dts: sunxi: Add a olinuxino-lime2-emmc added the new
emmc equipped) lime2 but forgot its Makefile.

This patch adds an entry to the Makefile.

Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>
---
Changes since v0:
  Added proper commit reference.

 arch/arm/boot/dts/Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 95c1923..07f4cf8 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -695,6 +695,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \
 	sun7i-a20-olimex-som-evb.dtb \
 	sun7i-a20-olinuxino-lime.dtb \
 	sun7i-a20-olinuxino-lime2.dtb \
+	sun7i-a20-olinuxino-lime2-emmc.dtb \
 	sun7i-a20-olinuxino-micro.dtb \
 	sun7i-a20-orangepi.dtb \
 	sun7i-a20-orangepi-mini.dtb \
-- 
2.8.1



From will.deacon at arm.com  Thu May 12 03:16:46 2016
From: will.deacon at arm.com (Will Deacon)
Date: Thu, 12 May 2016 11:16:46 +0100
Subject: [PATCH] arm64: do not enforce strict 16 byte alignment to stack
 pointer
In-Reply-To: <20160512092545.GC11226@e104818-lin.cambridge.arm.com>
References: <1462985814-16146-1-git-send-email-colin.king@canonical.com>
 <20160512092545.GC11226@e104818-lin.cambridge.arm.com>
Message-ID: <20160512101645.GB25355@arm.com>

[Adding Jacob]

On Thu, May 12, 2016 at 10:25:45AM +0100, Catalin Marinas wrote:
> On Wed, May 11, 2016 at 05:56:54PM +0100, Colin King wrote:
> > From: Colin Ian King <colin.king at canonical.com>
> > 
> > copy_thread should not be enforcing 16 byte aligment and returning
> > -EINVAL. Other architectures trap misaligned stack access with SIGBUS
> > so arm64 should follow this convention, so remove the strict enforcement
> > check.
> > 
> > For example, currently clone(2) fails with -EINVAL when passing
> > a misaligned stack and this gives little clue to what is wrong. Instead,
> > it is arguable that a SIGBUS on the fist access to a misaligned stack
> > allows one to figure out that it is a misaligned stack issue rather
> > than trying to figure out why an unconventional (and undocumented)
> > -EINVAL is being returned.
> > 
> > Signed-off-by: Colin Ian King <colin.king at canonical.com>
> > ---
> >  arch/arm64/kernel/process.c | 3 ---
> >  1 file changed, 3 deletions(-)
> > 
> > diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> > index 5655f756..8414971 100644
> > --- a/arch/arm64/kernel/process.c
> > +++ b/arch/arm64/kernel/process.c
> > @@ -258,9 +258,6 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
> >  		if (stack_start) {
> >  			if (is_compat_thread(task_thread_info(p)))
> >  				childregs->compat_sp = stack_start;
> > -			/* 16-byte aligned stack mandatory on AArch64 */
> > -			else if (stack_start & 15)
> > -				return -EINVAL;
> >  			else
> >  				childregs->sp = stack_start;
> >  		}
> 
> As we discussed on the linux-man list, I don't expect this change to
> break existing working user apps since they pass an aligned stack
> already. I really doubt anyone relies on the -EINVAL here.
> 
> That said, I don't think we should add a cc stable (which you haven't
> anyway), at least we have a point in time where this change was made. As
> the patch stands:
> 
> Acked-by: Catalin Marinas <catalin.marinas at arm.com>

As far as today's mainline is concerned, this looks fine to me. However,
there is one nagging issue in that the JavaScript guys have started asking
us to relax the strict alignment altogether (there is a bit in the SCTLR
register for this). I'm not at all keen on doing this per-process, since
context-switching the SCTLR is likely to be slow, so if we were to allow
this relaxation it would probably be in the form of a global /sysfs knob
or the like. That would then mean that you wouldn't get -EINVAL *or*
SIGBUS for a misaligned stack passed to clone().

I think in that case, the options are either (a) return -EINVAL when
strict alignment checking is disabled or (b) do nothing and let users
debug their broken programs.

None of this is a blocker for the patch (which I plan to apply), but
food for thought.

Will


From robin at protonic.nl  Thu May 12 03:25:00 2016
From: robin at protonic.nl (Robin van der Gracht)
Date: Thu, 12 May 2016 12:25:00 +0200
Subject: [GIT PULL] move ARM LCD display driver to auxdisplay
In-Reply-To: <CACRpkdZwPVMx-dXVkfVwFN0juzVuyvShV7yDWbUFSXOPE=uUrw@mail.gmail.com>
References: <CACRpkdbyO0axd5ergYZcXO302f2fFAPKrSNevkvreP1kRjm-vw@mail.gmail.com>
 <20160425115758.GA4874@lukather>
 <CACRpkdb=s5onVa7qND9nFUtYPw5H-Hdr7Ja5o3=-9+wxghHekQ@mail.gmail.com>
 <20160428092608.GE17159@lukather> <5723755D.9060108@ti.com>
 <20160509090615.6272f8ca@erd979>
 <CACRpkdbZmL9Cqp-ubzyxd7fWUFOVsS1DCxsfG02kSpbWu_rbZQ@mail.gmail.com>
 <20160509161728.3aee1134@erd979>
 <CACRpkdZwPVMx-dXVkfVwFN0juzVuyvShV7yDWbUFSXOPE=uUrw@mail.gmail.com>
Message-ID: <20160512122500.11411882@erd979>

On Mon, 9 May 2016 16:27:00 +0200
Linus Walleij <linus.walleij at linaro.org> wrote:

> On Mon, May 9, 2016 at 4:17 PM, Robin van der Gracht
> <robin at protonic.nl> wrote:
> > On Mon, 9 May 2016 15:19:26 +0200
> > Linus Walleij <linus.walleij at linaro.org> wrote:
> >  
> >> On Mon, May 9, 2016 at 9:06 AM, Robin van der Gracht
> >> <robin at protonic.nl> wrote:
> >>  
> >> > If you guys feel like auxdisplay is not the right subsystem for
> >> > the driver, and would like me to move it, please share.  
> >>
> >> The best would be if you volunteer to maintain it and bring
> >> it forward.  
> >
> > Thats fine. Would it suffice if I submit another patch adding myself
> > to the maintainers file?  
> 
> That's half of it, if Miguel does not come back then his name
> should be removed as the second step.
> 

First half is completed. I've added myself as maintainer for the
driver I've posted recently (HT16K33 LED CONTROLLER DRIVER).

According to MAINTAINERS, Miguel maintains:
 - CFAG12864B LCD DRIVER
 - CFAG12864BFB LCD FRAMEBUFFER DRIVER
 - KS0108 LCD CONTROLLER DRIVER
 - AUXILIARY DISPLAY DRIVERS

AFAIK, I should not be judge in Miguels case.

@linus: I'll send my patches to Greg if you agree on this.

Kind regards,
Robin van der Gracht


From christoffer.dall at linaro.org  Thu May 12 03:26:30 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 12:26:30 +0200
Subject: [PATCH v3 32/55] KVM: arm/arm64: vgic-new: Add GICv3 MMIO
 handling framework
In-Reply-To: <1462531568-9799-33-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-33-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512102630.GC27623@cbox>

On Fri, May 06, 2016 at 11:45:45AM +0100, Andre Przywara wrote:
> Create a new file called vgic-mmio-v3.c and describe the GICv3
> distributor and redistributor registers there.
> This adds a special macro to deal with the split of SGI/PPI in the
> redistributor and SPIs in the distributor, which allows us to reuse
> the existing GICv2 handlers for those registers which are compatible.
> Also we provide a function to deal with the registration of the two
> separate redistributor frames per VCPU.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Reviewed-by: Eric Auger <eric.auger at linaro.org>
> ---
> Changelog RFC..v1:
> - adapt to new MMIO registration approach:
>   register one device for the distributor and two for each VCPU
> - implement special handling for private interrupts
> - remove empty stub functions
> - make IGROUPR return RAO
> 
> Changelog v1 .. v2:
> - adapt to new framework, introduce vgic-mmio-v3.c
> - remove userland register access functions (for now)
> - precompute .len when describing a VGIC register
> - add missed pointer incrementation on registering redist regions
> - replace _nyi stub functions with raz/wi versions
> 
> Changelog v2 .. v3:
> - replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h
> - add prototype and stub code for vgic_register_redist_iodevs
> - rename register struct variables _rdbase_ and _sgibase_
> 
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
>  virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
>  virt/kvm/arm/vgic/vgic.h         |   7 ++
>  4 files changed, 205 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> new file mode 100644
> index 0000000..06c7ec5
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -0,0 +1,191 @@
> +/*
> + * VGICv3 MMIO handling functions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/irqchip/arm-gic-v3.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/iodev.h>
> +#include <kvm/arm_vgic.h>
> +
> +#include <asm/kvm_emulate.h>
> +
> +#include "vgic.h"
> +#include "vgic-mmio.h"
> +
> +/*
> + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
> + * redistributors, while SPIs are covered by registers in the distributor
> + * block. Trying to set private IRQs in this block gets ignored.
> + * We take some special care here to fix the calculation of the register
> + * offset.
> + */
> +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \
> +	{								\
> +		.reg_offset = off,					\
> +		.bits_per_irq = bpi,					\
> +		.len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8,		\
> +		.read = vgic_mmio_read_raz,				\
> +		.write = vgic_mmio_write_wi,				\
> +	}, {								\
> +		.reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8,	\
> +		.bits_per_irq = bpi,					\
> +		.len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
> +		.read = read_ops,					\
> +		.write = write_ops,					\
> +	}
> +
> +static const struct vgic_register_region vgic_v3_dist_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
> +		vgic_mmio_read_config, vgic_mmio_write_config, 2),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 64),
> +	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
> +};
> +
> +static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
> +};
> +
> +static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 32),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
> +		vgic_mmio_read_config, vgic_mmio_write_config, 8),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +};
> +
> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
> +{
> +	dev->regions = vgic_v3_dist_registers;
> +	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
> +
> +	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
> +
> +	return SZ_64K;
> +}
> +
> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
> +{
> +	int nr_vcpus = atomic_read(&kvm->online_vcpus);
> +	struct kvm_vcpu *vcpu;
> +	struct vgic_io_device *devices, *device;
> +	int c, ret = 0;
> +
> +	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
> +			  GFP_KERNEL);
> +	if (!devices)
> +		return -ENOMEM;
> +
> +	device = devices;
> +	kvm_for_each_vcpu(c, vcpu, kvm) {
> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
> +		device->base_addr = redist_base_address;
> +		device->regions = vgic_v3_rdbase_registers;
> +		device->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
> +		device->redist_vcpu = vcpu;
> +
> +		mutex_lock(&kvm->slots_lock);
> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
> +					      redist_base_address,
> +					      SZ_64K, &device->dev);
> +		mutex_unlock(&kvm->slots_lock);
> +
> +		if (ret)
> +			break;
> +
> +		device++;
> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
> +		device->base_addr = redist_base_address + SZ_64K;
> +		device->regions = vgic_v3_sgibase_registers;
> +		device->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
> +		device->redist_vcpu = vcpu;
> +
> +		mutex_lock(&kvm->slots_lock);
> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
> +					      redist_base_address + SZ_64K,
> +					      SZ_64K, &device->dev);
> +		mutex_unlock(&kvm->slots_lock);
> +		if (ret) {
> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
> +						  &devices[c * 2].dev);
> +			break;
> +		}
> +		device++;
> +		redist_base_address += 2 * SZ_64K;

while I think this whole thing is actually correct, I think it could
have been much more clear by, in the beginning of the loop doing:

	gpa_t rd_base = redist_base_address + c * SZ_64K * 2;
	gpa_t sgi_base = rd_base + SZ_64K;
	struct vgic_io_device *rd_dev = &devices[c];
	struct vgic_io_device *sgi_dev = &devices[c + 1];

and then referring directly to these variables.

> +	}
> +
> +	if (ret) {
> +		for (c--; c >= 0; c--) {

holy dark mother of all that's evil; I think this is correct.

> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
> +						  &devices[c * 2].dev);
> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
> +						  &devices[c * 2 + 1].dev);

do we really need this though?  Can't we just rely on KVM to tear down
thew whole bus infrastructure as we're returning an error anyway?

(have you looked at what the unregister_dev function does, it's full of
kmallocs and other fun stuff).


Thanks,
-Christoffer

> +		}
> +		kfree(devices);
> +	} else {
> +		kvm->arch.vgic.redist_iodevs = devices;
> +	}
> +
> +	return ret;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index 19fed56..d1b88d2 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -502,6 +502,11 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>  	case VGIC_V2:
>  		len = vgic_v2_init_dist_iodev(io_device);
>  		break;
> +#ifdef CONFIG_KVM_ARM_VGIC_V3
> +	case VGIC_V3:
> +		len = vgic_v3_init_dist_iodev(io_device);
> +		break;
> +#endif
>  	default:
>  		BUG_ON(1);
>  	}
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index 884eb71..3585ac6 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -123,4 +123,6 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
>  
>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>  
> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
> +
>  #endif
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index cf62015..39a8a65 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -40,6 +40,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
>  void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
>  void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
>  #else
>  static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
>  {
> @@ -61,6 +62,12 @@ static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
>  static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>  {
>  }
> +
> +static inline int vgic_register_redist_iodevs(struct kvm *kvm,
> +					      gpa_t dist_base_address)
> +{
> +	return -ENODEV;
> +}
>  #endif
>  
>  #endif
> -- 
> 2.7.3
> 




From gnurou at gmail.com  Thu May 12 03:26:32 2016
From: gnurou at gmail.com (Alexandre Courbot)
Date: Thu, 12 May 2016 19:26:32 +0900
Subject: [PATCH v9 1/2] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <2c0675cd6f67bd487105c46c38c72d49d84d4df8.1462911225.git.chunkeey@googlemail.com>
References: <cover.1462911225.git.chunkeey@googlemail.com>
 <cover.1462911225.git.chunkeey@googlemail.com>
 <2c0675cd6f67bd487105c46c38c72d49d84d4df8.1462911225.git.chunkeey@googlemail.com>
Message-ID: <0a1ab2b6-b4c5-44d7-abb4-ce1e9da7e477@gmail.com>

On Wednesday, May 11, 2016 6:34:34 PM JST, Christian Lamparter wrote:
> From: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
>
> This patch adds support for defining memory-mapped GPIOs which
> are compatible with the existing gpio-mmio interface. The generic
> library provides support for many memory-mapped GPIO controllers
> that are found in various on-board FPGA and ASIC solutions that
> are used to control board's switches, LEDs, chip-selects,
> Ethernet/USB PHY power, etc.
>
> For setting GPIO's there are three configurations:

s/GPIO's/GPIOs

> 	1. single input/output register resource (named "dat"),
> 	2. set/clear pair (named "set" and "clr"),
> 	3. single output register resource and single input resource
> 	   ("set" and dat").
>
> The configuration is detected by which resources are present.
> For the single output register, this drives a 1 by setting a bit
> and a zero by clearing a bit.  For the set clr pair, this drives
> a 1 by setting a bit in the set register and clears it by setting
> a bit in the clear register. The configuration is detected by
> which resources are present.

The last sentence of this paragraph repeats for first one.

>
> For setting the GPIO direction, there are three configurations:
> 	a. simple bidirectional GPIOs that requires no configuration.
> 	b. an output direction register (named "dirout")
> 	   where a 1 bit indicates the GPIO is an output.
> 	c. an input direction register (named "dirin")
> 	   where a 1 bit indicates the GPIO is an input.
>
> The first user for this binding is "wd,mbl-gpio".
>
> Reviewed-by: Andy Shevchenko <andy.shevchenko at gmail.com>
> Signed-off-by: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
> Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
> ---
>  drivers/gpio/gpio-mmio.c | 68 
> ++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 66 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
> index 6c1cb3b..f72e40e 100644
> --- a/drivers/gpio/gpio-mmio.c
> +++ b/drivers/gpio/gpio-mmio.c
> @@ -61,6 +61,8 @@ o        `                     ~~~~\___/~~~~  
>   ` controller in FPGA is ,.`
>  #include <linux/bitops.h>
>  #include <linux/platform_device.h>
>  #include <linux/mod_devicetable.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
>  
>  static void bgpio_write8(void __iomem *reg, unsigned long data)
>  {
> @@ -569,6 +571,58 @@ static void __iomem *bgpio_map(struct 
> platform_device *pdev,
>  	return devm_ioremap_resource(&pdev->dev, r);
>  }
>  
> +#ifdef CONFIG_OF
> +static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
> +				     struct bgpio_pdata *pdata,
> +				     unsigned long *flags)
> +{
> +	struct device *dev = &pdev->dev;
> +
> +	pdata->base = -1;
> +
> +	if (of_property_read_bool(dev->of_node, "no-output"))
> +		*flags |= BGPIOF_NO_OUTPUT;

I don't think it is a good idea to add "generic" properties. Whether a 
controller is capable of output or not should be determined by its 
compatible string only, and not a vague property.

> +
> +	return 0;
> +}
> +
> +static const struct of_device_id bgpio_of_match[] = {
> +	{ .compatible = "wd,mbl-gpio", .data = bgpio_basic_mmio_parse_dt },

Mmm cannot you determine whether your controller is capable of output or 
not just from the compatible property here? If so, the 
bgpio_basic_mmio_parse_dt seems to be unneeded. If not, then this is 
dependent on the wd,mbl-gpio binding and should be renamed accordingly.

> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, bgpio_of_match);
> +
> +static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
> +					  unsigned long *flags)
> +{
> +	const int (*parse_dt)(struct platform_device *,
> +			      struct bgpio_pdata *, unsigned long *);
> +	struct bgpio_pdata *pdata;
> +	int err;
> +
> +	parse_dt = of_device_get_match_data(&pdev->dev);
> +	if (!parse_dt)
> +		return NULL;
> +
> +	pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata),
> +			     GFP_KERNEL);
> +	if (!pdata)
> +		return ERR_PTR(-ENOMEM);
> +
> +	err = parse_dt(pdev, pdata, flags);
> +	if (err)
> +		return ERR_PTR(err);
> +
> +	return pdata;
> +}
> +#else
> +static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
> +					  unsigned long *flags)
> +{
> +	return NULL;
> +}
> +#endif /* CONFIG_OF */
> +
>  static int bgpio_pdev_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -579,10 +633,19 @@ static int bgpio_pdev_probe(struct 
> platform_device *pdev)
>  	void __iomem *dirout;
>  	void __iomem *dirin;
>  	unsigned long sz;
> -	unsigned long flags = pdev->id_entry->driver_data;
> +	unsigned long flags = 0;
>  	int err;
>  	struct gpio_chip *gc;
> -	struct bgpio_pdata *pdata = dev_get_platdata(dev);
> +	struct bgpio_pdata *pdata;
> +
> +	pdata = bgpio_parse_dt(pdev, &flags);
> +	if (IS_ERR(pdata))
> +		return PTR_ERR(pdata);
> +
> +	if (!pdata) {
> +		pdata = dev_get_platdata(dev);
> +		flags = pdev->id_entry->driver_data;
> +	}
>  
>  	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
>  	if (!r)
> @@ -646,6 +709,7 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table);
>  static struct platform_driver bgpio_driver = {
>  	.driver = {
>  		.name = "basic-mmio-gpio",
> +		.of_match_table = of_match_ptr(bgpio_of_match),
>  	},
>  	.id_table = bgpio_id_table,
>  	.probe = bgpio_pdev_probe,

It seems to me that this patch does two things:

1) Add code to support device tree lookup
2) Add support for "wd,mbl-gpio".

If true, these two things should be in their own patches. You should also 
have another patch that adds the DT bindings for "wd,mbl-gpio", so I would 
do things in that order:

1/3: DT support for basic-mmio-gpio
2/3: DT bindings for "wd,mbl-gpio" (and have them validated by the DT 
people - e.g. do you really need a "reg" property or is it here just to fit 
with what bgpio_pdev_probe expects? More about this on 2/2)
3/3: Support for "wd,mbl-gpio" in basic-mmio-gpio



From gnurou at gmail.com  Thu May 12 03:30:05 2016
From: gnurou at gmail.com (Alexandre Courbot)
Date: Thu, 12 May 2016 19:30:05 +0900
Subject: [PATCH v9 2/2] gpio: move clps711x, moxart,
 ts4800 and gpio-ge =?iso-8859-1?Q?into_gpio-mmio?=
In-Reply-To: <85c74586dbd0023306f012764b85d6aa168b4ae7.1462911225.git.chunkeey@googlemail.com>
References: <cover.1462911225.git.chunkeey@googlemail.com>
 <cover.1462911225.git.chunkeey@googlemail.com>
 <85c74586dbd0023306f012764b85d6aa168b4ae7.1462911225.git.chunkeey@googlemail.com>
Message-ID: <3c67e0ca-43eb-4a77-90ef-f8e2757c8edd@gmail.com>

On Wednesday, May 11, 2016 6:34:35 PM JST, Christian Lamparter wrote:
> This patch integrates the GPIO drivers for the following
> boards, SoCs, etc. into gpio-mmio:
>  - CLPS711X SoCs
>  - MOXA ART SoC
>  - TS-4800 FPGA DIO blocks and compatibles
>  - GPIO controllers found on some GE Single Board Computers
>
> Cc: Alexander Shiyan <shc_work at mail.ru>
> Cc: Julien Grossholtz <julien.grossholtz at savoirfairelinux.com>
> Cc: Martyn Welch <martyn.welch at ge.com>
> Cc: Jonas Jensen <jonas.jensen at gmail.com>
> Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
> ---
>  drivers/gpio/Kconfig         |  16 +++-
>  drivers/gpio/Makefile        |   4 -
>  drivers/gpio/gpio-clps711x.c |  91 -------------------
>  drivers/gpio/gpio-ge.c       | 114 -----------------------
>  drivers/gpio/gpio-mmio.c     | 212 
> +++++++++++++++++++++++++++++++++++++++++++
>  drivers/gpio/gpio-moxart.c   |  84 -----------------
>  drivers/gpio/gpio-ts4800.c   |  81 -----------------
>  7 files changed, 224 insertions(+), 378 deletions(-)
>  delete mode 100644 drivers/gpio/gpio-clps711x.c
>  delete mode 100644 drivers/gpio/gpio-ge.c
>  delete mode 100644 drivers/gpio/gpio-moxart.c
>  delete mode 100644 drivers/gpio/gpio-ts4800.c
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index a68d838..e4d1065 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -154,7 +154,7 @@ config GPIO_BRCMSTB
>  config GPIO_CLPS711X
>  	tristate "CLPS711X GPIO support"
>  	depends on ARCH_CLPS711X || COMPILE_TEST
> -	select GPIO_GENERIC
> +	select GPIO_GENERIC_PLATFORM
>  	help
>  	  Say yes here to support GPIO on CLPS711X SoCs.
>  
> @@ -196,7 +196,7 @@ config GPIO_ETRAXFS
>  config GPIO_GE_FPGA
>  	bool "GE FPGA based GPIO"
>  	depends on GE_FPGA
> -	select GPIO_GENERIC
> +	select GPIO_GENERIC_PLATFORM
>  	help
>  	  Support for common GPIO functionality provided on some GE Single Board
>  	  Computers.
> @@ -209,6 +209,14 @@ config GPIO_GENERIC_PLATFORM
>  	tristate "Generic memory-mapped GPIO controller support (MMIO 
> platform device)"
>  	select GPIO_GENERIC
>  	help
> +	  Select this to support many generic memory-mapped GPIO controllers.
> +
> +	  This driver also includes support for the following GPIOs:
> +	    CLPS711X SoCs
> +	    MOXA ART SoC
> +	    TS-4800 FPGA DIO blocks and compatibles.
> +	    GPIOs found on some GE Single Board Computers.
> +
>  	  Say yes here to support basic platform_device memory-mapped 
> GPIO controllers.
>  
>  config GPIO_GRGPIO
> @@ -288,7 +296,7 @@ config GPIO_MM_LANTIQ
>  config GPIO_MOXART
>  	bool "MOXART GPIO support"
>  	depends on ARCH_MOXART || COMPILE_TEST
> -	select GPIO_GENERIC
> +	select GPIO_GENERIC_PLATFORM
>  	help
>  	  Select this option to enable GPIO driver for
>  	  MOXA ART SoC devices.
> @@ -408,7 +416,7 @@ config GPIO_TS4800
>  	tristate "TS-4800 DIO blocks and compatibles"
>  	depends on OF_GPIO
>  	depends on SOC_IMX51 || COMPILE_TEST
> -	select GPIO_GENERIC
> +	select GPIO_GENERIC_PLATFORM
>  	help
>  	  This driver support TS-4800 FPGA GPIO controllers.
>  
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index 991598e..d8d63ae 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -31,7 +31,6 @@ obj-$(CONFIG_GPIO_ATH79)	+= gpio-ath79.o
>  obj-$(CONFIG_GPIO_BCM_KONA)	+= gpio-bcm-kona.o
>  obj-$(CONFIG_GPIO_BRCMSTB)	+= gpio-brcmstb.o
>  obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
> -obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o
>  obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o
>  obj-$(CONFIG_GPIO_CRYSTAL_COVE)	+= gpio-crystalcove.o
>  obj-$(CONFIG_GPIO_DA9052)	+= gpio-da9052.o
> @@ -43,7 +42,6 @@ obj-$(CONFIG_GPIO_EM)		+= gpio-em.o
>  obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o
>  obj-$(CONFIG_GPIO_ETRAXFS)	+= gpio-etraxfs.o
>  obj-$(CONFIG_GPIO_F7188X)	+= gpio-f7188x.o
> -obj-$(CONFIG_GPIO_GE_FPGA)	+= gpio-ge.o
>  obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o
>  obj-$(CONFIG_GPIO_ICH)		+= gpio-ich.o
>  obj-$(CONFIG_GPIO_IOP)		+= gpio-iop.o
> @@ -68,7 +66,6 @@ obj-$(CONFIG_GPIO_MC9S08DZ60)	+= gpio-mc9s08dz60.o
>  obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o
>  obj-$(CONFIG_GPIO_ML_IOH)	+= gpio-ml-ioh.o
>  obj-$(CONFIG_GPIO_MM_LANTIQ)	+= gpio-mm-lantiq.o
> -obj-$(CONFIG_GPIO_MOXART)	+= gpio-moxart.o
>  obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o
>  obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
>  obj-$(CONFIG_GPIO_MSIC)		+= gpio-msic.o
> @@ -107,7 +104,6 @@ obj-$(CONFIG_GPIO_TPS65218)	+= gpio-tps65218.o
>  obj-$(CONFIG_GPIO_TPS6586X)	+= gpio-tps6586x.o
>  obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
>  obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
> -obj-$(CONFIG_GPIO_TS4800)	+= gpio-ts4800.o
>  obj-$(CONFIG_GPIO_TS5500)	+= gpio-ts5500.o
>  obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
>  obj-$(CONFIG_GPIO_TWL6040)	+= gpio-twl6040.o
> diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
> deleted file mode 100644
> index 5a69025..0000000
> --- a/drivers/gpio/gpio-clps711x.c
> +++ /dev/null
> @@ -1,91 +0,0 @@
> -/*
> - *  CLPS711X GPIO driver
> - *
> - *  Copyright (C) 2012,2013 Alexander Shiyan <shc_work at mail.ru>
> - *
> - * 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.
> - */
> -
> -#include <linux/err.h>
> -#include <linux/module.h>
> -#include <linux/gpio/driver.h>
> -#include <linux/platform_device.h>
> -
> -static int clps711x_gpio_probe(struct platform_device *pdev)
> -{
> -	struct device_node *np = pdev->dev.of_node;
> -	void __iomem *dat, *dir;
> -	struct gpio_chip *gc;
> -	struct resource *res;
> -	int err, id = np ? of_alias_get_id(np, "gpio") : pdev->id;
> -
> -	if ((id < 0) || (id > 4))
> -		return -ENODEV;
> -
> -	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
> -	if (!gc)
> -		return -ENOMEM;
> -
> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	dat = devm_ioremap_resource(&pdev->dev, res);
> -	if (IS_ERR(dat))
> -		return PTR_ERR(dat);
> -
> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> -	dir = devm_ioremap_resource(&pdev->dev, res);
> -	if (IS_ERR(dir))
> -		return PTR_ERR(dir);
> -
> -	switch (id) {
> -	case 3:
> -		/* PORTD is inverted logic for direction register */
> -		err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
> -				 NULL, dir, 0);
> -		break;
> -	default:
> -		err = bgpio_init(gc, &pdev->dev, 1, dat, NULL, NULL,
> -				 dir, NULL, 0);
> -		break;
> -	}
> -
> -	if (err)
> -		return err;
> -
> -	switch (id) {
> -	case 4:
> -		/* PORTE is 3 lines only */
> -		gc->ngpio = 3;
> -		break;
> -	default:
> -		break;
> -	}
> -
> -	gc->base = id * 8;
> -	gc->owner = THIS_MODULE;
> -	platform_set_drvdata(pdev, gc);
> -
> -	return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
> -}
> -
> -static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = {
> -	{ .compatible = "cirrus,clps711x-gpio" },
> -	{ }
> -};
> -MODULE_DEVICE_TABLE(of, clps711x_gpio_ids);
> -
> -static struct platform_driver clps711x_gpio_driver = {
> -	.driver	= {
> -		.name		= "clps711x-gpio",
> -		.of_match_table	= of_match_ptr(clps711x_gpio_ids),
> -	},
> -	.probe	= clps711x_gpio_probe,
> -};
> -module_platform_driver(clps711x_gpio_driver);
> -
> -MODULE_LICENSE("GPL");
> -MODULE_AUTHOR("Alexander Shiyan <shc_work at mail.ru>");
> -MODULE_DESCRIPTION("CLPS711X GPIO driver");
> -MODULE_ALIAS("platform:clps711x-gpio");
> diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c
> deleted file mode 100644
> index 8650b29..0000000
> --- a/drivers/gpio/gpio-ge.c
> +++ /dev/null
> @@ -1,114 +0,0 @@
> -/*
> - * Driver for GE FPGA based GPIO
> - *
> - * Author: Martyn Welch <martyn.welch at ge.com>
> - *
> - * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc.
> - *
> - * This file is licensed under the terms of the GNU General Public License
> - * version 2.  This program is licensed "as is" without any warranty of any
> - * kind, whether express or implied.
> - */
> -
> -/* TODO
> - *
> - * Configuration of output modes (totem-pole/open-drain)
> - * Interrupt configuration - interrupts are always generated 
> the FPGA relies on
> - * the I/O interrupt controllers mask to stop them propergating
> - */
> -
> -#include <linux/kernel.h>
> -#include <linux/io.h>
> -#include <linux/slab.h>
> -#include <linux/of_device.h>
> -#include <linux/of_gpio.h>
> -#include <linux/of_address.h>
> -#include <linux/module.h>
> -#include <linux/gpio/driver.h>
> -
> -#define GEF_GPIO_DIRECT		0x00
> -#define GEF_GPIO_IN		0x04
> -#define GEF_GPIO_OUT		0x08
> -#define GEF_GPIO_TRIG		0x0C
> -#define GEF_GPIO_POLAR_A	0x10
> -#define GEF_GPIO_POLAR_B	0x14
> -#define GEF_GPIO_INT_STAT	0x18
> -#define GEF_GPIO_OVERRUN	0x1C
> -#define GEF_GPIO_MODE		0x20
> -
> -static const struct of_device_id gef_gpio_ids[] = {
> -	{
> -		.compatible	= "gef,sbc610-gpio",
> -		.data		= (void *)19,
> -	}, {
> -		.compatible	= "gef,sbc310-gpio",
> -		.data		= (void *)6,
> -	}, {
> -		.compatible	= "ge,imp3a-gpio",
> -		.data		= (void *)16,
> -	},
> -	{ }
> -};
> -MODULE_DEVICE_TABLE(of, gef_gpio_ids);
> -
> -static int __init gef_gpio_probe(struct platform_device *pdev)
> -{
> -	const struct of_device_id *of_id =
> -		of_match_device(gef_gpio_ids, &pdev->dev);
> -	struct gpio_chip *gc;
> -	void __iomem *regs;
> -	int ret;
> -
> -	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
> -	if (!gc)
> -		return -ENOMEM;
> -
> -	regs = of_iomap(pdev->dev.of_node, 0);
> -	if (!regs)
> -		return -ENOMEM;
> -
> -	ret = bgpio_init(gc, &pdev->dev, 4, regs + GEF_GPIO_IN,
> -			 regs + GEF_GPIO_OUT, NULL, NULL,
> -			 regs + GEF_GPIO_DIRECT, BGPIOF_BIG_ENDIAN_BYTE_ORDER);
> -	if (ret) {
> -		dev_err(&pdev->dev, "bgpio_init failed\n");
> -		goto err0;
> -	}
> -
> -	/* Setup pointers to chip functions */
> -	gc->label = devm_kstrdup(&pdev->dev, pdev->dev.of_node->full_name,
> -				     GFP_KERNEL);
> -	if (!gc->label) {
> -		ret = -ENOMEM;
> -		goto err0;
> -	}
> -
> -	gc->base = -1;
> -	gc->ngpio = (u16)(uintptr_t)of_id->data;
> -	gc->of_gpio_n_cells = 2;
> -	gc->of_node = pdev->dev.of_node;
> -
> -	/* This function adds a memory mapped GPIO chip */
> -	ret = devm_gpiochip_add_data(&pdev->dev, gc, NULL);
> -	if (ret)
> -		goto err0;
> -
> -	return 0;
> -err0:
> -	iounmap(regs);
> -	pr_err("%s: GPIO chip registration failed\n",
> -			pdev->dev.of_node->full_name);
> -	return ret;
> -};
> -
> -static struct platform_driver gef_gpio_driver = {
> -	.driver = {
> -		.name		= "gef-gpio",
> -		.of_match_table	= gef_gpio_ids,
> -	},
> -};
> -module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);
> -
> -MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
> -MODULE_AUTHOR("Martyn Welch <martyn.welch at ge.com");
> -MODULE_LICENSE("GPL");
> diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
> index f72e40e..1de9172 100644
> --- a/drivers/gpio/gpio-mmio.c
> +++ b/drivers/gpio/gpio-mmio.c
> @@ -586,8 +586,220 @@ static int 
> bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
>  	return 0;
>  }
>  
> +static int clps711x_parse_dt(struct platform_device *pdev,
> +			     struct bgpio_pdata *pdata,
> +			     unsigned long *flags)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct resource *res;
> +	const char *dir_reg_name;
> +	int id = np ? of_alias_get_id(np, "gpio") : pdev->id;
> +
> +	switch (id) {
> +	case 0:
> +	case 1:
> +	case 2:
> +		pdata->ngpio = 0; /* determined by register width */
> +		dir_reg_name = "dirout";
> +		break;
> +	case 3:
> +		pdata->ngpio = 0; /* determined by register width */
> +		/* PORTD is inverted logic for direction register */
> +		dir_reg_name = "dirin";
> +		break;
> +	case 4:
> +		pdata->ngpio = 3; /* PORTE is 3 lines only */
> +		dir_reg_name = "dirout";
> +		break;
> +	default:
> +		return -ENODEV;
> +	}
> +
> +	pdata->base = id * 8;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -EINVAL;
> +	if (!res->name || strcmp("dat", res->name))
> +		res->name = devm_kstrdup(&pdev->dev, "dat", GFP_KERNEL);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	if (!res)
> +		return -EINVAL;
> +	if (!res->name || strcmp(dir_reg_name, res->name))
> +		res->name = devm_kstrdup(&pdev->dev, dir_reg_name, GFP_KERNEL);

Ouch, I don't like this. Also the probability that the "if (!res->name || 
...)" condition is not met is so small that I would not bother with it and 
do the kstrdup unconditionally. But maybe we can remove this altogether - 
see below...

> +
> +	return 0;
> +}
> +
> +static int ge_dt_cb(struct platform_device *pdev,
> +		    struct bgpio_pdata *pdata,
> +		    unsigned long *flags)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +
> +	pdata->label = devm_kstrdup(&pdev->dev, np->full_name, GFP_KERNEL);
> +	if (!pdata->label)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
> +static int moxart_dt_cb(struct platform_device *pdev,
> +			struct bgpio_pdata *pdata,
> +			unsigned long *flags)
> +{
> +	pdata->base = 0;
> +	pdata->label = "moxart-gpio";
> +	return 0;
> +}
> +
> +
> +static int ts4800_dt_cb(struct platform_device *pdev,
> +			struct bgpio_pdata *pdata,
> +			unsigned long *flags)
> +{
> +	int err;
> +
> +	err = of_property_read_u32(pdev->dev.of_node, "ngpios", &pdata->ngpio);
> +	if (err == -EINVAL) {
> +		pdata->ngpio = 16;
> +		return 0;
> +	}
> +
> +	return err;
> +}
> +
> +/*
> + * bgpio_init() needs up to five named mmio register resources.
> + * These currently are dat, set, clr, [dirout | dirin]. There
> + * is no particular order or predefined place for the entries.
> + * However, dirout and dirin are mutually exclusive.
> + */
> +#define __NUM_COMPAT_OVERRIDE_MMIO_RESOURCES 4
> +
> +struct compat_gpio_device_data {
> +	unsigned int expected_resource_size;
> +	unsigned int ngpio;
> +	resource_size_t register_width;
> +	unsigned long flags;
> +	int (*call_back)(struct platform_device *pdev,
> +			 struct bgpio_pdata *pdata,
> +			 unsigned long *flags);
> +	struct resource_replacement {
> +		resource_size_t start_offset;
> +		const char *name;
> +	} resources[__NUM_COMPAT_OVERRIDE_MMIO_RESOURCES];
> +};
> +#undef __NUM_COMPAT_OVERRIDE_MMIO_RESOURCES
> +
> +#define ADD_COMPAT_REGISTER(_name, _offset)	\
> +	{ .name = (_name), .start_offset = (_offset) }
> +
> +#define ADD_COMPAT_GPIO(_comp, _sz, _ngpio, _width, _cb, _f, _res...)	\
> +	{								\
> +	  .compatible = (_comp),					\
> +	  .data = &(struct compat_gpio_device_data) {			\
> +		.expected_resource_size = (_sz),			\
> +		.ngpio = (_ngpio),					\
> +		.register_width = (_width),				\
> +		.flags = (_f),						\
> +		.call_back = (_cb),					\
> +		.resources = { _res },					\
> +	}								\
> +}
> +
> +#define ADD_COMPAT_GE_GPIO(_name, _ngpio)				\
> +	ADD_COMPAT_GPIO(_name, 0x24, _ngpio, 0x4, ge_dt_cb,		\
> +		 BGPIOF_BIG_ENDIAN_BYTE_ORDER,				\
> +		 ADD_COMPAT_REGISTER("dat", 0x04),			\
> +		 ADD_COMPAT_REGISTER("set", 0x08),			\
> +		 ADD_COMPAT_REGISTER("dirin", 0x00))			\
> +
> +static const struct of_device_id compat_gpio_devices[] = {
> +	ADD_COMPAT_GE_GPIO("ge,imp3a-gpio", 16),
> +	ADD_COMPAT_GE_GPIO("gef,sbc310-gpio", 6),
> +	ADD_COMPAT_GE_GPIO("gef,sbc610-gpio", 19),
> +	ADD_COMPAT_GPIO("moxa,moxart-gpio", 0xc, 0, 0x4, moxart_dt_cb,
> +		 BGPIOF_READ_OUTPUT_REG_SET,
> +		 ADD_COMPAT_REGISTER("dat", 0x04),
> +		 ADD_COMPAT_REGISTER("set", 0x00),
> +		 ADD_COMPAT_REGISTER("dirout", 0x08)),
> +	ADD_COMPAT_GPIO("technologic,ts4800-gpio", 0x6, 16, 0x2, ts4800_dt_cb,
> +		 0, ADD_COMPAT_REGISTER("dat", 0x00),
> +		 ADD_COMPAT_REGISTER("set", 0x02),
> +		 ADD_COMPAT_REGISTER("dirout", 0x04)),
> +};
> +
> +#undef ADD_COMPAT_GE_GPIO
> +#undef ADD_COMPAT_GPIO
> +#undef ADD_COMPAT_REGISTER
> +
> +static int compat_parse_dt(struct platform_device *pdev,
> +			   struct bgpio_pdata *pdata,
> +			   unsigned long *flags)
> +{
> +	const struct device_node *node = pdev->dev.of_node;
> +	const struct compat_gpio_device_data *entry;
> +	const struct of_device_id *of_id;
> +	struct resource *res;
> +	int err;
> +
> +	of_id = of_match_node(compat_gpio_devices, node);
> +	if (!of_id)
> +		return -ENODEV;
> +
> +	entry = of_id->data;
> +	if (!entry || !entry->resources[0].name)
> +		return -EINVAL;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -EINVAL;
> +
> +	if (!res->name || strcmp(entry->resources[0].name, res->name)) {
> +		struct resource nres[ARRAY_SIZE(entry->resources)];
> +		size_t i;
> +
> +		if (resource_size(res) != entry->expected_resource_size)
> +			return -EINVAL;
> +
> +		for (i = 0; i < ARRAY_SIZE(entry->resources); i++) {
> +			if (!entry->resources[i].name)
> +				continue;
> +
> +			nres[i].name = devm_kstrdup(&pdev->dev,
> +				entry->resources[i].name, GFP_KERNEL);
> +			nres[i].start = res->start +
> +				entry->resources[i].start_offset;
> +			nres[i].end = nres[i].start +
> +				entry->register_width - 1;
> +			nres[i].flags = IORESOURCE_MEM;
> +		}
> +
> +		err = platform_device_add_resources(pdev, nres, i);
> +		if (err)
> +			return err;
> +	}
> +
> +	pdata->base = -1;
> +	pdata->ngpio = entry->ngpio;
> +	*flags = entry->flags;
> +
> +	if (entry->call_back)
> +		err = entry->call_back(pdev, pdata, flags);
> +
> +	return err;
> +}

Ok, so this is getting quite complex, with two of_device_id tables and two 
levels of hooks, mainly because you want to use the bgpio_pdev_probe() 
function which relies on named memory resources.

This function is here for basic platform devices, and you are not obliged 
to rely on it for DT. Feel free to write your own function (or rather split 
bgpio_pdev_probe() in two code paths) if it can reduce the amount of black 
magic you need to do (especially the renaming of resources on-the-fly).

At the end of the day what you want is a function that calls bgpio_init() 
with the right parameters. These parameters should be inferred from the 
compatible property whenever possible (which is most of the time, and why I 
am suspiscious of using "reg" properties for these devices since I don't 
think it can change much?), and passed as-is to bgpio_init(). Your 
compat_gpio_device_data struct basically encodes this, so this will take 
care of all the "compat" devices.

For the other devices, you should be able to fill in such a structure from 
the DT properties. Then you just use it for the parameters of bgpio_init(). 
It will be more elegant that adding resources, and probably shorter as 
well.

> +
>  static const struct of_device_id bgpio_of_match[] = {
>  	{ .compatible = "wd,mbl-gpio", .data = bgpio_basic_mmio_parse_dt },
> +	{ .compatible = "cirrus,clps711x-gpio", .data = clps711x_parse_dt },
> +	{ .compatible = "ge,imp3a-gpio", .data = compat_parse_dt },
> +	{ .compatible = "gef,sbc310-gpio", .data = compat_parse_dt },
> +	{ .compatible = "gef,sbc610-gpio", .data = compat_parse_dt },
> +	{ .compatible = "moxa,moxart-gpio", .data = compat_parse_dt },
> +	{ .compatible = "technologic,ts4800-gpio", .data = compat_parse_dt },

If you implement my idea, the function referred to by .data should return 
that structure I was talking about, and bgpio_init() can be called directly 
on it after that. The current path of bgpio_pdev_probe() should only be 
taken if bgpio_parse_dt() returned NULL.

I believe this will reduce the number of lines in your patch some more, and 
it will also make the code easier to read.

Also this should be split into several patches, like the previous one: the 
first one adds the required infrastructure to gpio-mmio, and the subsequent 
patches each move one device into gpio-mmio.


From ynorov at caviumnetworks.com  Thu May 12 03:30:24 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 12 May 2016 13:30:24 +0300
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <4326765.8HKKkI07Zs@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV> <4326765.8HKKkI07Zs@wuerfel>
Message-ID: <20160512103024.GA7639@yury-N73SV>

On Thu, May 12, 2016 at 11:19:21AM +0200, Arnd Bergmann wrote:
> On Thursday 12 May 2016 03:20:00 Yury Norov wrote:
> > 
> > I debugged preadv02 and pwritev02 failures and found very weird bug.
> > Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> > of vector, and kernel reports successful read/write.
> > 
> > There are 2 problems:
> > 1. How kernel allows such address to be passed to fs subsystem;
> > 2. How fs successes to read/write at non-mapped, and in fact non-user
> > address.
> > 
> > I don't know the answer on 2'nd question, and it might be something
> > generic. But I investigated first problem.
> > 
> > The problem is that compat_rw_copy_check_uvector() uses access_ok() to
> > validate user address, and on arm64 it ends up with checking buffer
> > end against current_thread_info()->addr_limit.
> > 
> > current_thread_info()->addr_limit for ilp32, and most probably for
> > aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
> > It happens because on thread creation we call flush_old_exec() to set 
> > addr_limit, and completely ignore compat mode there.
> > 
> > This patch fixes it. It also fixes USER_DS macro to return different
> > values depending on compat.
> > 
> > This patch is enough to handle preadv02 and pwritev02, but problem #2
> > is still there.
> > 
> > Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
> > 
> 
> Good catch!
> 
> Can you do a version of this patch that works on the current
> mainline kernel and can be backported to fix aarch32 emulation?
> 
> For ilp32 mode, I think we can better fix arch/arm64/kernel/binfmt_ilp32.c
> as it is introduced.
> 
> 	Arnd
> 

OK, will do

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


From adrian.hunter at intel.com  Thu May 12 03:29:40 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Thu, 12 May 2016 13:29:40 +0300
Subject: [PATCH] mmc: mmc: do not use CMD13 to get status after speed mode
 switch
In-Reply-To: <1463036431.11653.3.camel@mhfsdcap03>
References: <1462344872-6448-1-git-send-email-chaotian.jing@mediatek.com>
 <5732E43E.8070800@intel.com> <1463036431.11653.3.camel@mhfsdcap03>
Message-ID: <57345B14.7030308@intel.com>

On 12/05/16 10:00, Chaotian Jing wrote:
> On Wed, 2016-05-11 at 10:50 +0300, Adrian Hunter wrote:
>> On 04/05/16 09:54, Chaotian Jing wrote:
>>> Per JEDEC spec, it is not recommended to use CMD13 to get card status
>>> after speed mode switch. below are two reason about this:
>>> 1. CMD13 cannot be guaranteed due to the asynchronous operation.
>>> Therefore it is not recommended to use CMD13 to check busy completion
>>> of the timing change indication.
>>> 2. After switch to HS200, CMD13 will get response of 0x800, and even the
>>> busy signal gets de-asserted, the response of CMD13 is aslo 0x800.
>>>
>>> this patch drops CMD13 when doing speed mode switch, if host do not
>>> support MMC_CAP_WAIT_WHILE_BUSY and there is no ops->card_busy(),
>>> then the only way is to wait a fixed timeout.
>>
>> This looks like it should be 3 patches:
>> 	1. Change __mmc_switch
>> 	2. Change HS200 and HS400 selection
>> 	3. Change HS selection
>>
>> However there is another problem: card_busy is not the same as busy signal -
>> see below.  So that needs to be sorted out first.
>>
> We should make that card_busy() is the same with busy signal asserted.
> as you know, if card was not in busy state, all data pins should be high
> level as it is pull-up by default. so that's no conflict to check card
> busy signal by DAT0 or DAT0 ~ DAT3.

Potentially SDIO uses DAT1 for card interrupt, so that is a conflict right
there.

Also SDHCI does it backwards (don't ask me why) and considers 0000 to be
busy, so there's another conflict.

Some of the language in the SD and SDHCI specifications seems to indicate
that checking all 4 DAT lines during voltage switch is optional i.e. only 1
of the lines must be checked.  If that is true then we could change all the
drivers over to check just DAT0, and expect that to work for both busy
signalling and SD voltage switch checks.

So it seems to me card_busy still needs to be sorted out first.



From jchandra at broadcom.com  Thu May 12 03:43:43 2016
From: jchandra at broadcom.com (Jayachandran C)
Date: Thu, 12 May 2016 16:13:43 +0530
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <20160511224314.GD28812@localhost>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
 <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>
 <20160511101101.GA16101@red-moon>
 <CAJZ5v0hgw929W5PjF0PqT+ssiOHd8TeJoSQcz4NUiAovZY2pfQ@mail.gmail.com>
 <20160511224314.GD28812@localhost>
Message-ID: <CAKc_7PW8BqQSTn01zDVsec4KXunQUKfcEft8=MH-E0xsmheo3w@mail.gmail.com>

On Thu, May 12, 2016 at 4:13 AM, Bjorn Helgaas <helgaas at kernel.org> wrote:
> On Wed, May 11, 2016 at 10:30:51PM +0200, Rafael J. Wysocki wrote:
>> On Wed, May 11, 2016 at 12:11 PM, Lorenzo Pieralisi
>> <lorenzo.pieralisi at arm.com> wrote:
>> > On Tue, May 10, 2016 at 08:37:00PM +0200, Rafael J. Wysocki wrote:
>> >> On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
>> >> > This patch provides a way to set the ACPI companion in PCI code.
>> >> > We define acpi_pci_set_companion() to set the ACPI companion pointer and
>> >> > call it from PCI core code. The function is stub for now.
>> >> >
>> >> > Signed-off-by: Jayachandran C <jchandra at broadcom.com>
>> >> > Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
>> >> > ---
>> >> >  drivers/pci/probe.c      | 2 ++
>> >> >  include/linux/pci-acpi.h | 4 ++++
>> >> >  2 files changed, 6 insertions(+)
>> >> >
>> >> > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> >> > index 8004f67..fb0b752 100644
>> >> > --- a/drivers/pci/probe.c
>> >> > +++ b/drivers/pci/probe.c
>> >> > @@ -12,6 +12,7 @@
>> >> >  #include <linux/slab.h>
>> >> >  #include <linux/module.h>
>> >> >  #include <linux/cpumask.h>
>> >> > +#include <linux/pci-acpi.h>
>> >> >  #include <linux/pci-aspm.h>
>> >> >  #include <linux/aer.h>
>> >> >  #include <linux/acpi.h>
>> >> > @@ -2141,6 +2142,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
>> >> >         bridge->dev.parent = parent;
>> >> >         bridge->dev.release = pci_release_host_bridge_dev;
>> >> >         dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
>> >> > +       acpi_pci_set_companion(bridge);
>> >>
>> >> Yes, we'll probably add something similar here.
>> >>
>> >> Do I think now is the right time to do that?  No.
>> >>
>> >> >         error = pcibios_root_bridge_prepare(bridge);
>> >> >         if (error) {
>> >> >                 kfree(bridge);
>> >> > diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
>> >> > index 09f9f02..1baa515 100644
>> >> > --- a/include/linux/pci-acpi.h
>> >> > +++ b/include/linux/pci-acpi.h
>> >> > @@ -111,6 +111,10 @@ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
>> >> >  static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
>> >> >  #endif /* CONFIG_ACPI */
>> >> >
>> >> > +static inline void acpi_pci_set_companion(struct pci_host_bridge *bridge)
>> >> > +{
>> >> > +}
>> >> > +
>> >> >  static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus)
>> >> >  {
>> >> >         return 0;
>> >> > --
>> >>
>> >> Honestly, to me it looks like this series is trying very hard to avoid
>> >> doing any PCI host bridge configuration stuff from arch/arm64/
>> >> although (a) that might be simpler and (b) it would allow us to
>> >> identify the code that's common between *all* architectures using ACPI
>> >> support for host bridge configuration and to move *that* to a common
>> >> place later.  As done here it seems to be following the "ARM64 is
>> >> generic and the rest of the world is special" line which isn't really
>> >> helpful.
>> >
>> > I think patch [1-2] should be merged regardless (they may require minor
>> > tweaks if we decide to move pci_acpi_scan_root() to arch/arm64 though,
>> > for include files location). I guess you are referring to patch 8 in
>> > your comments above, which boils down to deciding whether:
>> >
>> > - pci_acpi_scan_root() (and unfortunately all the MCFG/ECAM handling that
>> >   goes with it) should live in arch/arm64 or drivers/acpi
>>
>> To be precise, everything under #ifdef CONFIG_ACPI_PCI_HOST_GENERIC or
>> equivalent is de facto ARM64-specific, because (as it stands in the
>> patch series) ARM64 is the only architecture that will select that
>> option.  Unless you are aware of any more architectures planning to
>> use ACPI (and I'm not aware of any), it will stay the only
>> architecture selecting it in the foreseeable future.
>>
>> Therefore you could replace CONFIG_ACPI_PCI_HOST_GENERIC with
>> CONFIG_ARM64 everywhere in that code which is why in my opinion the
>> code should live somewhere under arch/arm64/.
>>
>> Going forward, it should be possible to identify common parts of the
>> PCI host bridge configuration code in arch/ and move it to
>> drivers/acpi/ or drivers/pci/, but I bet that won't be the entire code
>> this series puts under CONFIG_ACPI_PCI_HOST_GENERIC.
>>
>> The above leads to a quite straightforward conclusion about the order
>> in which to do things: I'd add ACPI support for PCI host bridge on
>> ARM64 following what's been done on ia64 (as x86 is more quirky and
>> kludgy overall) as far as reasonably possible first and then think
>> about moving common stuff to a common place.
>
> That does seem like a reasonable approach.  I had hoped to get more of
> this in for v4.7, but we don't have much time left.  Maybe some of
> Rafael's comments can be addressed by moving and slight restructuring
> and we can still squeeze it in.
>
> The first three patches:
>
>   PCI: Provide common functions for ECAM mapping
>   PCI: generic, thunder: Use generic ECAM API
>   PCI, of: Move PCI I/O space management to PCI core code
>
> seem relatively straightforward, and I applied them to pci/arm64 with
> the intent of merging them unless there are objections.  I made the
> following tweaks, mainly to try to improve some error messages:
>
> diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
> index 3d52005..e1add01 100644
> --- a/drivers/pci/ecam.c
> +++ b/drivers/pci/ecam.c
> @@ -24,9 +24,9 @@
>  #include "ecam.h"
>
>  /*
> - * On 64 bit systems, we do a single ioremap for the whole config space
> - * since we have enough virtual address range available. On 32 bit, do an
> - * ioremap per bus.
> + * On 64-bit systems, we do a single ioremap for the whole config space
> + * since we have enough virtual address range available.  On 32-bit, we
> + * ioremap the config space for each bus individually.
>   */
>  static const bool per_bus_mapping = !config_enabled(CONFIG_64BIT);
>
> @@ -42,6 +42,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
>  {
>         struct pci_config_window *cfg;
>         unsigned int bus_range, bus_range_max, bsz;
> +       struct resource *conflict;
>         int i, err;
>
>         if (busr->start > busr->end)
> @@ -58,10 +59,10 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
>         bus_range = resource_size(&cfg->busr);
>         bus_range_max = resource_size(cfgres) >> ops->bus_shift;
>         if (bus_range > bus_range_max) {
> -               dev_warn(dev, "bus max %#x reduced to %#x",
> -                                       bus_range, bus_range_max);
>                 bus_range = bus_range_max;
>                 cfg->busr.end = busr->start + bus_range - 1;
> +               dev_warn(dev, "ECAM area %pR can only accommodate %pR (reduced from %pR desired)\n",
> +                        cfgres, &cfg->busr, busr);
>         }
>         bsz = 1 << ops->bus_shift;
>
> @@ -70,9 +71,11 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
>         cfg->res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
>         cfg->res.name = "PCI ECAM";
>
> -       err = request_resource(&iomem_resource, &cfg->res);
> -       if (err) {
> -               dev_err(dev, "request ECAM res %pR failed\n", &cfg->res);
> +       conflict = request_resource(&iomem_resource, &cfg->res);
> +       if (conflict) {
> +               err = -EBUSY;
> +               dev_err(dev, "can't claim ECAM area %pR: address conflict with %s %pR\n",
> +                       &cfg->res, conflict->name, conflict);
>                 goto err_exit;
>         }
>
> diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
> index 1ad2176..9878beb 100644
> --- a/drivers/pci/ecam.h
> +++ b/drivers/pci/ecam.h
> @@ -33,7 +33,7 @@ struct pci_ecam_ops {
>
>  /*
>   * struct to hold the mappings of a config space window. This
> - * is expected to be used as sysdata for PCI controlllers which
> + * is expected to be used as sysdata for PCI controllers that
>   * use ECAM.
>   */
>  struct pci_config_window {
> @@ -43,11 +43,11 @@ struct pci_config_window {
>         struct pci_ecam_ops             *ops;
>         union {
>                 void __iomem            *win;   /* 64-bit single mapping */
> -               void __iomem            **winp; /* 32-bit per bus mapping */
> +               void __iomem            **winp; /* 32-bit per-bus mapping */
>         };
>  };
>
> -/* create and free for pci_config_window */
> +/* create and free pci_config_window */
>  struct pci_config_window *pci_ecam_create(struct device *dev,
>                 struct resource *cfgres, struct resource *busr,
>                 struct pci_ecam_ops *ops);
> @@ -56,11 +56,11 @@ void pci_ecam_free(struct pci_config_window *cfg);
>  /* map_bus when ->sysdata is an instance of pci_config_window */
>  void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
>                                int where);
> -/* default ECAM ops, bus shift 20, generic read and write */
> +/* default ECAM ops */
>  extern struct pci_ecam_ops pci_generic_ecam_ops;
>
>  #ifdef CONFIG_PCI_HOST_GENERIC
> -/* for DT based pci controllers that support ECAM */
> +/* for DT-based PCI controllers that support ECAM */
>  int pci_host_common_probe(struct platform_device *pdev,
>                           struct pci_ecam_ops *ops);
>  #endif

If we are moving the ACPI/PCI code from drivers/acpi to
arch/arm64/ , there is an issue in having the header file
ecam.h in drivers/pci

The current include of "../pci/ecam.h" is slightly ugly (Arnd
and David had already noted this), but including the driver
header from arch code would be even worse.

I can either merge ecam.h into include/linux/pci.h
or move it to a new file include/linux/pci-ecam.h, any
suggestion on which is preferable?

JC.


From p.zabel at pengutronix.de  Thu May 12 03:46:15 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Thu, 12 May 2016 12:46:15 +0200
Subject: [PATCH] drm: mediatek: remove IOMMU_DMA select
In-Reply-To: <1462997501-982363-1-git-send-email-arnd@arndb.de>
References: <1462982509-342936-1-git-send-email-arnd@arndb.de>
 <1462997501-982363-1-git-send-email-arnd@arndb.de>
Message-ID: <1463049975.3070.29.camel@pengutronix.de>

Am Mittwoch, den 11.05.2016, 22:11 +0200 schrieb Arnd Bergmann:
> We get a harmless build warning when trying to use the mediatek
> DRM driver with IOMMU support disabled:
> 
> warning: (DRM_MEDIATEK) selects IOMMU_DMA which has unmet direct dependencies (IOMMU_SUPPORT)
> 
> However, the IOMMU_DMA symbol is not meant to be used by drivers
> at all, and this driver doesn't seem to have a strict dependency
> on it other than using the mediatek IOMMU driver that does.
> 
> Since we also want to be able to do compile tests with the
> driver on other platforms, the IOMMU_DMA symbol should not
> be selected here.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> ---
> If someone has a better explanation about why the 'select' is here,
> let me know, it certainly seems out of place.

No, it just has been there since the initial RFC and nobody noticed.

>  drivers/gpu/drm/mediatek/Kconfig | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
> index 0c06a69d7f04..545973f6b743 100644
> --- a/drivers/gpu/drm/mediatek/Kconfig
> +++ b/drivers/gpu/drm/mediatek/Kconfig
> @@ -7,7 +7,6 @@ config DRM_MEDIATEK
>  	select DRM_KMS_HELPER
>  	select DRM_MIPI_DSI
>  	select DRM_PANEL
> -	select IOMMU_DMA
>  	select MEMORY
>  	select MTK_SMI
>  	help

Acked-by: Philipp Zabel <p.zabel at pengutronix.de>

I tried
  make ARCH=arm64 allnoconfig
and then set
  CONFIG_MODULES=y
  CONFIG_ARCH_MEDIATEK=y
  CONFIG_DRM=m
  CONFIG_DRM_MEDIATEK=m

And it builds fine with IOMMU_DMA/MTK_IOMMU disabled.

thanks
Philipp



From tn at semihalf.com  Thu May 12 03:50:07 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Thu, 12 May 2016 12:50:07 +0200
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <20160511224314.GD28812@localhost>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
 <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>
 <20160511101101.GA16101@red-moon>
 <CAJZ5v0hgw929W5PjF0PqT+ssiOHd8TeJoSQcz4NUiAovZY2pfQ@mail.gmail.com>
 <20160511224314.GD28812@localhost>
Message-ID: <57345FDF.4000804@semihalf.com>

On 12.05.2016 00:43, Bjorn Helgaas wrote:
> On Wed, May 11, 2016 at 10:30:51PM +0200, Rafael J. Wysocki wrote:
>> On Wed, May 11, 2016 at 12:11 PM, Lorenzo Pieralisi
>> <lorenzo.pieralisi at arm.com> wrote:
>>> On Tue, May 10, 2016 at 08:37:00PM +0200, Rafael J. Wysocki wrote:
>>>> On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
>>>>> This patch provides a way to set the ACPI companion in PCI code.
>>>>> We define acpi_pci_set_companion() to set the ACPI companion pointer and
>>>>> call it from PCI core code. The function is stub for now.
>>>>>
>>>>> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
>>>>> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
>>>>> ---
>>>>>   drivers/pci/probe.c      | 2 ++
>>>>>   include/linux/pci-acpi.h | 4 ++++
>>>>>   2 files changed, 6 insertions(+)
>>>>>
>>>>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>>>>> index 8004f67..fb0b752 100644
>>>>> --- a/drivers/pci/probe.c
>>>>> +++ b/drivers/pci/probe.c
>>>>> @@ -12,6 +12,7 @@
>>>>>   #include <linux/slab.h>
>>>>>   #include <linux/module.h>
>>>>>   #include <linux/cpumask.h>
>>>>> +#include <linux/pci-acpi.h>
>>>>>   #include <linux/pci-aspm.h>
>>>>>   #include <linux/aer.h>
>>>>>   #include <linux/acpi.h>
>>>>> @@ -2141,6 +2142,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
>>>>>          bridge->dev.parent = parent;
>>>>>          bridge->dev.release = pci_release_host_bridge_dev;
>>>>>          dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
>>>>> +       acpi_pci_set_companion(bridge);
>>>>
>>>> Yes, we'll probably add something similar here.
>>>>
>>>> Do I think now is the right time to do that?  No.
>>>>
>>>>>          error = pcibios_root_bridge_prepare(bridge);
>>>>>          if (error) {
>>>>>                  kfree(bridge);
>>>>> diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
>>>>> index 09f9f02..1baa515 100644
>>>>> --- a/include/linux/pci-acpi.h
>>>>> +++ b/include/linux/pci-acpi.h
>>>>> @@ -111,6 +111,10 @@ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
>>>>>   static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
>>>>>   #endif /* CONFIG_ACPI */
>>>>>
>>>>> +static inline void acpi_pci_set_companion(struct pci_host_bridge *bridge)
>>>>> +{
>>>>> +}
>>>>> +
>>>>>   static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus)
>>>>>   {
>>>>>          return 0;
>>>>> --
>>>>
>>>> Honestly, to me it looks like this series is trying very hard to avoid
>>>> doing any PCI host bridge configuration stuff from arch/arm64/
>>>> although (a) that might be simpler and (b) it would allow us to
>>>> identify the code that's common between *all* architectures using ACPI
>>>> support for host bridge configuration and to move *that* to a common
>>>> place later.  As done here it seems to be following the "ARM64 is
>>>> generic and the rest of the world is special" line which isn't really
>>>> helpful.
>>>
>>> I think patch [1-2] should be merged regardless (they may require minor
>>> tweaks if we decide to move pci_acpi_scan_root() to arch/arm64 though,
>>> for include files location). I guess you are referring to patch 8 in
>>> your comments above, which boils down to deciding whether:
>>>
>>> - pci_acpi_scan_root() (and unfortunately all the MCFG/ECAM handling that
>>>    goes with it) should live in arch/arm64 or drivers/acpi
>>
>> To be precise, everything under #ifdef CONFIG_ACPI_PCI_HOST_GENERIC or
>> equivalent is de facto ARM64-specific, because (as it stands in the
>> patch series) ARM64 is the only architecture that will select that
>> option.  Unless you are aware of any more architectures planning to
>> use ACPI (and I'm not aware of any), it will stay the only
>> architecture selecting it in the foreseeable future.
>>
>> Therefore you could replace CONFIG_ACPI_PCI_HOST_GENERIC with
>> CONFIG_ARM64 everywhere in that code which is why in my opinion the
>> code should live somewhere under arch/arm64/.
>>
>> Going forward, it should be possible to identify common parts of the
>> PCI host bridge configuration code in arch/ and move it to
>> drivers/acpi/ or drivers/pci/, but I bet that won't be the entire code
>> this series puts under CONFIG_ACPI_PCI_HOST_GENERIC.
>>
>> The above leads to a quite straightforward conclusion about the order
>> in which to do things: I'd add ACPI support for PCI host bridge on
>> ARM64 following what's been done on ia64 (as x86 is more quirky and
>> kludgy overall) as far as reasonably possible first and then think
>> about moving common stuff to a common place.
>
> That does seem like a reasonable approach.  I had hoped to get more of
> this in for v4.7, but we don't have much time left.  Maybe some of
> Rafael's comments can be addressed by moving and slight restructuring
> and we can still squeeze it in.
>
> The first three patches:
>
>    PCI: Provide common functions for ECAM mapping
>    PCI: generic, thunder: Use generic ECAM API
>    PCI, of: Move PCI I/O space management to PCI core code
>
> seem relatively straightforward, and I applied them to pci/arm64 with
> the intent of merging them unless there are objections.  I made the
> following tweaks, mainly to try to improve some error messages:
>
> diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
> index 3d52005..e1add01 100644
> --- a/drivers/pci/ecam.c
> +++ b/drivers/pci/ecam.c
> @@ -24,9 +24,9 @@
>   #include "ecam.h"
>
>   /*
> - * On 64 bit systems, we do a single ioremap for the whole config space
> - * since we have enough virtual address range available. On 32 bit, do an
> - * ioremap per bus.
> + * On 64-bit systems, we do a single ioremap for the whole config space
> + * since we have enough virtual address range available.  On 32-bit, we
> + * ioremap the config space for each bus individually.
>    */
>   static const bool per_bus_mapping = !config_enabled(CONFIG_64BIT);
>
> @@ -42,6 +42,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
>   {
>   	struct pci_config_window *cfg;
>   	unsigned int bus_range, bus_range_max, bsz;
> +	struct resource *conflict;
>   	int i, err;
>
>   	if (busr->start > busr->end)
> @@ -58,10 +59,10 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
>   	bus_range = resource_size(&cfg->busr);
>   	bus_range_max = resource_size(cfgres) >> ops->bus_shift;
>   	if (bus_range > bus_range_max) {
> -		dev_warn(dev, "bus max %#x reduced to %#x",
> -					bus_range, bus_range_max);
>   		bus_range = bus_range_max;
>   		cfg->busr.end = busr->start + bus_range - 1;
> +		dev_warn(dev, "ECAM area %pR can only accommodate %pR (reduced from %pR desired)\n",
> +			 cfgres, &cfg->busr, busr);
>   	}
>   	bsz = 1 << ops->bus_shift;
>
> @@ -70,9 +71,11 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
>   	cfg->res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
>   	cfg->res.name = "PCI ECAM";
>
> -	err = request_resource(&iomem_resource, &cfg->res);
> -	if (err) {
> -		dev_err(dev, "request ECAM res %pR failed\n", &cfg->res);
> +	conflict = request_resource(&iomem_resource, &cfg->res);

We need request_resource_conflict here then:
-	conflict = request_resource(&iomem_resource, &cfg->res);
+	conflict = request_resource_conflict(&iomem_resource, &cfg->res);

Thanks,
Tomasz


From andre.przywara at arm.com  Thu May 12 03:52:58 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 12 May 2016 11:52:58 +0100
Subject: [PATCH v3 32/55] KVM: arm/arm64: vgic-new: Add GICv3 MMIO
 handling framework
In-Reply-To: <20160512102630.GC27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-33-git-send-email-andre.przywara@arm.com>
 <20160512102630.GC27623@cbox>
Message-ID: <5734608A.1080902@arm.com>

Hi,

On 12/05/16 11:26, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:45AM +0100, Andre Przywara wrote:
>> Create a new file called vgic-mmio-v3.c and describe the GICv3
>> distributor and redistributor registers there.
>> This adds a special macro to deal with the split of SGI/PPI in the
>> redistributor and SPIs in the distributor, which allows us to reuse
>> the existing GICv2 handlers for those registers which are compatible.
>> Also we provide a function to deal with the registration of the two
>> separate redistributor frames per VCPU.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> Reviewed-by: Eric Auger <eric.auger at linaro.org>
>> ---
>> Changelog RFC..v1:
>> - adapt to new MMIO registration approach:
>>   register one device for the distributor and two for each VCPU
>> - implement special handling for private interrupts
>> - remove empty stub functions
>> - make IGROUPR return RAO
>>
>> Changelog v1 .. v2:
>> - adapt to new framework, introduce vgic-mmio-v3.c
>> - remove userland register access functions (for now)
>> - precompute .len when describing a VGIC register
>> - add missed pointer incrementation on registering redist regions
>> - replace _nyi stub functions with raz/wi versions
>>
>> Changelog v2 .. v3:
>> - replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h
>> - add prototype and stub code for vgic_register_redist_iodevs
>> - rename register struct variables _rdbase_ and _sgibase_
>>
>>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
>>  virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
>>  virt/kvm/arm/vgic/vgic.h         |   7 ++
>>  4 files changed, 205 insertions(+)
>>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> new file mode 100644
>> index 0000000..06c7ec5
>> --- /dev/null
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> @@ -0,0 +1,191 @@
>> +/*
>> + * VGICv3 MMIO handling functions
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <linux/irqchip/arm-gic-v3.h>
>> +#include <linux/kvm.h>
>> +#include <linux/kvm_host.h>
>> +#include <kvm/iodev.h>
>> +#include <kvm/arm_vgic.h>
>> +
>> +#include <asm/kvm_emulate.h>
>> +
>> +#include "vgic.h"
>> +#include "vgic-mmio.h"
>> +
>> +/*
>> + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
>> + * redistributors, while SPIs are covered by registers in the distributor
>> + * block. Trying to set private IRQs in this block gets ignored.
>> + * We take some special care here to fix the calculation of the register
>> + * offset.
>> + */
>> +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \
>> +	{								\
>> +		.reg_offset = off,					\
>> +		.bits_per_irq = bpi,					\
>> +		.len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8,		\
>> +		.read = vgic_mmio_read_raz,				\
>> +		.write = vgic_mmio_write_wi,				\
>> +	}, {								\
>> +		.reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8,	\
>> +		.bits_per_irq = bpi,					\
>> +		.len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
>> +		.read = read_ops,					\
>> +		.write = write_ops,					\
>> +	}
>> +
>> +static const struct vgic_register_region vgic_v3_dist_registers[] = {
>> +	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
>> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
>> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
>> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
>> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
>> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
>> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
>> +		vgic_mmio_read_config, vgic_mmio_write_config, 2),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 64),
>> +	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
>> +};
>> +
>> +static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
>> +	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
>> +};
>> +
>> +static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
>> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
>> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
>> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
>> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
>> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
>> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 32),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
>> +		vgic_mmio_read_config, vgic_mmio_write_config, 8),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>> +	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>> +};
>> +
>> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
>> +{
>> +	dev->regions = vgic_v3_dist_registers;
>> +	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
>> +
>> +	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
>> +
>> +	return SZ_64K;
>> +}
>> +
>> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
>> +{
>> +	int nr_vcpus = atomic_read(&kvm->online_vcpus);
>> +	struct kvm_vcpu *vcpu;
>> +	struct vgic_io_device *devices, *device;
>> +	int c, ret = 0;
>> +
>> +	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
>> +			  GFP_KERNEL);
>> +	if (!devices)
>> +		return -ENOMEM;
>> +
>> +	device = devices;
>> +	kvm_for_each_vcpu(c, vcpu, kvm) {
>> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
>> +		device->base_addr = redist_base_address;
>> +		device->regions = vgic_v3_rdbase_registers;
>> +		device->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
>> +		device->redist_vcpu = vcpu;
>> +
>> +		mutex_lock(&kvm->slots_lock);
>> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
>> +					      redist_base_address,
>> +					      SZ_64K, &device->dev);
>> +		mutex_unlock(&kvm->slots_lock);
>> +
>> +		if (ret)
>> +			break;
>> +
>> +		device++;
>> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
>> +		device->base_addr = redist_base_address + SZ_64K;
>> +		device->regions = vgic_v3_sgibase_registers;
>> +		device->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
>> +		device->redist_vcpu = vcpu;
>> +
>> +		mutex_lock(&kvm->slots_lock);
>> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
>> +					      redist_base_address + SZ_64K,
>> +					      SZ_64K, &device->dev);
>> +		mutex_unlock(&kvm->slots_lock);
>> +		if (ret) {
>> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
>> +						  &devices[c * 2].dev);
>> +			break;
>> +		}
>> +		device++;
>> +		redist_base_address += 2 * SZ_64K;
> 
> while I think this whole thing is actually correct, I think it could
> have been much more clear by, in the beginning of the loop doing:
> 
> 	gpa_t rd_base = redist_base_address + c * SZ_64K * 2;
> 	gpa_t sgi_base = rd_base + SZ_64K;
> 	struct vgic_io_device *rd_dev = &devices[c];
> 	struct vgic_io_device *sgi_dev = &devices[c + 1];
> 
> and then referring directly to these variables.

Yeah, looks useful, not sure we want to change it last minute though.

>> +	}
>> +
>> +	if (ret) {
>> +		for (c--; c >= 0; c--) {
> 
> holy dark mother of all that's evil; I think this is correct.
> 
>> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
>> +						  &devices[c * 2].dev);
>> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
>> +						  &devices[c * 2 + 1].dev);
> 
> do we really need this though?  Can't we just rely on KVM to tear down
> thew whole bus infrastructure as we're returning an error anyway?

I haven't checked if this is really necessary, but this missing teardown
was mentioned multiple times in previous reviews, so I just did it.
We can remove it once we have proven that it's pointless later.

> (have you looked at what the unregister_dev function does, it's full of
> kmallocs and other fun stuff).

TBH, this whole kvm_io_bus framework is really weird (I think
registering a new region copies every thing it had before) and designed
for the x86 use case. But it shouldn't be this series which fixes this.

Cheers,
Andre.

> 
> Thanks,
> -Christoffer
> 
>> +		}
>> +		kfree(devices);
>> +	} else {
>> +		kvm->arch.vgic.redist_iodevs = devices;
>> +	}
>> +
>> +	return ret;
>> +}
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
>> index 19fed56..d1b88d2 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>> @@ -502,6 +502,11 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>>  	case VGIC_V2:
>>  		len = vgic_v2_init_dist_iodev(io_device);
>>  		break;
>> +#ifdef CONFIG_KVM_ARM_VGIC_V3
>> +	case VGIC_V3:
>> +		len = vgic_v3_init_dist_iodev(io_device);
>> +		break;
>> +#endif
>>  	default:
>>  		BUG_ON(1);
>>  	}
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
>> index 884eb71..3585ac6 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio.h
>> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
>> @@ -123,4 +123,6 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
>>  
>>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>>  
>> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
>> +
>>  #endif
>> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>> index cf62015..39a8a65 100644
>> --- a/virt/kvm/arm/vgic/vgic.h
>> +++ b/virt/kvm/arm/vgic/vgic.h
>> @@ -40,6 +40,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
>>  void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
>>  void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
>>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
>> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
>>  #else
>>  static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
>>  {
>> @@ -61,6 +62,12 @@ static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
>>  static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>>  {
>>  }
>> +
>> +static inline int vgic_register_redist_iodevs(struct kvm *kvm,
>> +					      gpa_t dist_base_address)
>> +{
>> +	return -ENODEV;
>> +}
>>  #endif
>>  
>>  #endif
>> -- 
>> 2.7.3
>>
> 
> 


From marc.zyngier at arm.com  Thu May 12 03:58:10 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 12 May 2016 11:58:10 +0100
Subject: [PATCH v3 32/55] KVM: arm/arm64: vgic-new: Add GICv3 MMIO
 handling framework
In-Reply-To: <5734608A.1080902@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-33-git-send-email-andre.przywara@arm.com>
 <20160512102630.GC27623@cbox> <5734608A.1080902@arm.com>
Message-ID: <573461C2.4090400@arm.com>

On 12/05/16 11:52, Andre Przywara wrote:
> Hi,
> 
> On 12/05/16 11:26, Christoffer Dall wrote:
>> On Fri, May 06, 2016 at 11:45:45AM +0100, Andre Przywara wrote:
>>> Create a new file called vgic-mmio-v3.c and describe the GICv3
>>> distributor and redistributor registers there.
>>> This adds a special macro to deal with the split of SGI/PPI in the
>>> redistributor and SPIs in the distributor, which allows us to reuse
>>> the existing GICv2 handlers for those registers which are compatible.
>>> Also we provide a function to deal with the registration of the two
>>> separate redistributor frames per VCPU.
>>>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> Reviewed-by: Eric Auger <eric.auger at linaro.org>
>>> ---
>>> Changelog RFC..v1:
>>> - adapt to new MMIO registration approach:
>>>   register one device for the distributor and two for each VCPU
>>> - implement special handling for private interrupts
>>> - remove empty stub functions
>>> - make IGROUPR return RAO
>>>
>>> Changelog v1 .. v2:
>>> - adapt to new framework, introduce vgic-mmio-v3.c
>>> - remove userland register access functions (for now)
>>> - precompute .len when describing a VGIC register
>>> - add missed pointer incrementation on registering redist regions
>>> - replace _nyi stub functions with raz/wi versions
>>>
>>> Changelog v2 .. v3:
>>> - replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h
>>> - add prototype and stub code for vgic_register_redist_iodevs
>>> - rename register struct variables _rdbase_ and _sgibase_
>>>
>>>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 191 +++++++++++++++++++++++++++++++++++++++
>>>  virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
>>>  virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
>>>  virt/kvm/arm/vgic/vgic.h         |   7 ++
>>>  4 files changed, 205 insertions(+)
>>>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
>>>
>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>>> new file mode 100644
>>> index 0000000..06c7ec5
>>> --- /dev/null
>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>>> @@ -0,0 +1,191 @@
>>> +/*
>>> + * VGICv3 MMIO handling functions
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + */
>>> +
>>> +#include <linux/irqchip/arm-gic-v3.h>
>>> +#include <linux/kvm.h>
>>> +#include <linux/kvm_host.h>
>>> +#include <kvm/iodev.h>
>>> +#include <kvm/arm_vgic.h>
>>> +
>>> +#include <asm/kvm_emulate.h>
>>> +
>>> +#include "vgic.h"
>>> +#include "vgic-mmio.h"
>>> +
>>> +/*
>>> + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
>>> + * redistributors, while SPIs are covered by registers in the distributor
>>> + * block. Trying to set private IRQs in this block gets ignored.
>>> + * We take some special care here to fix the calculation of the register
>>> + * offset.
>>> + */
>>> +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, read_ops, write_ops, bpi) \
>>> +	{								\
>>> +		.reg_offset = off,					\
>>> +		.bits_per_irq = bpi,					\
>>> +		.len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8,		\
>>> +		.read = vgic_mmio_read_raz,				\
>>> +		.write = vgic_mmio_write_wi,				\
>>> +	}, {								\
>>> +		.reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8,	\
>>> +		.bits_per_irq = bpi,					\
>>> +		.len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
>>> +		.read = read_ops,					\
>>> +		.write = write_ops,					\
>>> +	}
>>> +
>>> +static const struct vgic_register_region vgic_v3_dist_registers[] = {
>>> +	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
>>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
>>> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
>>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1),
>>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
>>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1),
>>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
>>> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 1),
>>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
>>> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1),
>>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
>>> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1),
>>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
>>> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1),
>>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
>>> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 8),
>>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
>>> +		vgic_mmio_read_config, vgic_mmio_write_config, 2),
>>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>>> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 64),
>>> +	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
>>> +};
>>> +
>>> +static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
>>> +};
>>> +
>>> +static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
>>> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 4),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
>>> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 4),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
>>> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
>>> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 4),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
>>> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
>>> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 4),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
>>> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 4),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
>>> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 32),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
>>> +		vgic_mmio_read_config, vgic_mmio_write_config, 8),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>>> +	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
>>> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>>> +};
>>> +
>>> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
>>> +{
>>> +	dev->regions = vgic_v3_dist_registers;
>>> +	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
>>> +
>>> +	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
>>> +
>>> +	return SZ_64K;
>>> +}
>>> +
>>> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
>>> +{
>>> +	int nr_vcpus = atomic_read(&kvm->online_vcpus);
>>> +	struct kvm_vcpu *vcpu;
>>> +	struct vgic_io_device *devices, *device;
>>> +	int c, ret = 0;
>>> +
>>> +	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
>>> +			  GFP_KERNEL);
>>> +	if (!devices)
>>> +		return -ENOMEM;
>>> +
>>> +	device = devices;
>>> +	kvm_for_each_vcpu(c, vcpu, kvm) {
>>> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
>>> +		device->base_addr = redist_base_address;
>>> +		device->regions = vgic_v3_rdbase_registers;
>>> +		device->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
>>> +		device->redist_vcpu = vcpu;
>>> +
>>> +		mutex_lock(&kvm->slots_lock);
>>> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
>>> +					      redist_base_address,
>>> +					      SZ_64K, &device->dev);
>>> +		mutex_unlock(&kvm->slots_lock);
>>> +
>>> +		if (ret)
>>> +			break;
>>> +
>>> +		device++;
>>> +		kvm_iodevice_init(&device->dev, &kvm_io_gic_ops);
>>> +		device->base_addr = redist_base_address + SZ_64K;
>>> +		device->regions = vgic_v3_sgibase_registers;
>>> +		device->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
>>> +		device->redist_vcpu = vcpu;
>>> +
>>> +		mutex_lock(&kvm->slots_lock);
>>> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
>>> +					      redist_base_address + SZ_64K,
>>> +					      SZ_64K, &device->dev);
>>> +		mutex_unlock(&kvm->slots_lock);
>>> +		if (ret) {
>>> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
>>> +						  &devices[c * 2].dev);
>>> +			break;
>>> +		}
>>> +		device++;
>>> +		redist_base_address += 2 * SZ_64K;
>>
>> while I think this whole thing is actually correct, I think it could
>> have been much more clear by, in the beginning of the loop doing:
>>
>> 	gpa_t rd_base = redist_base_address + c * SZ_64K * 2;
>> 	gpa_t sgi_base = rd_base + SZ_64K;
>> 	struct vgic_io_device *rd_dev = &devices[c];
>> 	struct vgic_io_device *sgi_dev = &devices[c + 1];
>>
>> and then referring directly to these variables.
> 
> Yeah, looks useful, not sure we want to change it last minute though.

Why not? We're changing much more fundamental things already. I'd rather
have something that I can easily read and convince myself that it does
the right thing rather than merge something that I'm suspicious of.

In other words, we fix it.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From sstabellini at kernel.org  Thu May 12 03:58:04 2016
From: sstabellini at kernel.org (Stefano Stabellini)
Date: Thu, 12 May 2016 11:58:04 +0100 (BST)
Subject: [PATCH] Xen: EFI: Parse DT parameters for Xen specific UEFI
In-Reply-To: <20160512100410.GA2728@codeblueprint.co.uk>
References: <1462523526-3172-1-git-send-email-zhaoshenglong@huawei.com>
 <20160511122730.GU2839@codeblueprint.co.uk> <57333533.2030206@linaro.org>
 <20160511232444.GY2839@codeblueprint.co.uk> <5733E8CF.3070004@huawei.com>
 <20160512100410.GA2728@codeblueprint.co.uk>
Message-ID: <alpine.DEB.2.10.1605121138500.2494@sstabellini-ThinkPad-X260>

On Thu, 12 May 2016, Matt Fleming wrote:
> On Thu, 12 May, at 10:22:07AM, Shannon Zhao wrote:
> > 
> > As said above, I will rebase this patch on top of the EFI next branch.
> 
> OK thanks.
> 
> Note that it is not possible to escape merge conflicts, since there
> are changes in the xen tip tree that are not in the EFI next branch
> and vice versa.
> 
> For example these commits from xen/linux-next look relevant,
> 
>   8e147fcc3ffa ("FDT: Add a helper to get the subnode by given name")
>   37060935dc04 ("ARM64: XEN: Add a function to initialize Xen specific UEFI runtime services")
>   acb2c923a860 ("XEN: EFI: Move x86 specific codes to architecture directory")
>   055be2d42408 ("ARM: Xen: Document UEFI support on Xen ARM virtual platforms")
>   3915fea959b6 ("ARM: XEN: Move xen_early_init() before efi_init()")

>From a diffstat perspective, the changes introduced by these commits
affect drivers/of/fdt.c, arch/arm/xen, arch/x86/xen, drivers/xen and
little else. I don't think they should cause merge troubles.


> Linus, Stefano, tip-folks: I'm soliciting opinions on the correct way
> to handle this inter-tree dependency where we've got changes to EFI
> code in two separate trees and Shannon wants to write patches on top
> of both.
> 
> I'm guessing the best solution is to merge xen/linux-next and efi/next
> into a topic branch either in the EFI tree or Xen tree, but I want to
> be cautious of the branch history that will create.

I am OK with that. You and I will have to be careful with the pull
requests.


> (In hindsight all of these change should have probably gone via the
> EFI tree.)

That is still possible if deemed best. 


From lee.jones at linaro.org  Thu May 12 04:18:16 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Thu, 12 May 2016 12:18:16 +0100
Subject: [PATCH] ARM: STi: Update machine _namestr to be more generic.
In-Reply-To: <1462984816-705-1-git-send-email-peter.griffin@linaro.org>
References: <1462984816-705-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <20160512111816.GA1433@dell.open.watershed.co.uk>

On Wed, 11 May 2016, Peter Griffin wrote:

> This string is used by dump_stack and as we now support
> more SoC's than just STiH415/6 it is misleading to have
> the current string in the stack trace.
> 
> This patch updates it to be more generic for the STi
> family of SoCs.
> 
> So instead of looking like this
> 
> [  271.672555] Hardware name: STiH415/416 SoC with Flattened Device Tree
> [  271.678998] [<c0310490>] (unwind_backtrace) from [<c030bb54>] (show_stack+0x10/0x14)
> [  271.686746] [<c030bb54>] (show_stack) from [<c058bc4c>] (dump_stack+0x98/0xac)
> [snip]
> 
> it now looks like this:
> 
> [    2.669879] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.6.0-rc3-00026-g38a1ce6-dirty #76
> [    2.677973] Hardware name: STi SoC with Flattened Device Tree
> [    2.683723] [<c0310490>] (unwind_backtrace) from [<c030bb54>] (show_stack+0x10/0x14)
> [    2.691472] [<c030bb54>] (show_stack) from [<c058bc0c>] (dump_stack+0x98/0xac)
> [snip]
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
>  arch/arm/mach-sti/board-dt.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

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

> diff --git a/arch/arm/mach-sti/board-dt.c b/arch/arm/mach-sti/board-dt.c
> index ae10fb2..cfee0ef 100644
> --- a/arch/arm/mach-sti/board-dt.c
> +++ b/arch/arm/mach-sti/board-dt.c
> @@ -23,7 +23,7 @@ static const char *const stih41x_dt_match[] __initconst = {
>  	NULL
>  };
>  
> -DT_MACHINE_START(STM, "STiH415/416 SoC with Flattened Device Tree")
> +DT_MACHINE_START(STM, "STi SoC with Flattened Device Tree")
>  	.dt_compat	= stih41x_dt_match,
>  	.l2c_aux_val	= L2C_AUX_CTRL_SHARED_OVERRIDE |
>  			  L310_AUX_CTRL_DATA_PREFETCH |

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


From tiffany.lin at mediatek.com  Thu May 12 04:24:03 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Thu, 12 May 2016 19:24:03 +0800
Subject: [PATCH v2 2/9] [media] : v4l: add Mediatek compressed video block
 format
In-Reply-To: <1463052250-38262-2-git-send-email-tiffany.lin@mediatek.com>
References: <1463052250-38262-1-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-2-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1463052250-38262-3-git-send-email-tiffany.lin@mediatek.com>

Add V4L2_PIX_FMT_MT21 format used on MT8173 driver.
It is compressed format and need MT8173 MDP driver to transfer to other 
standard format.

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 include/uapi/linux/videodev2.h |    1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 8f95191..52feea6 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -625,6 +625,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_Y8I      v4l2_fourcc('Y', '8', 'I', ' ') /* Greyscale 8-bit L/R interleaved */
 #define V4L2_PIX_FMT_Y12I     v4l2_fourcc('Y', '1', '2', 'I') /* Greyscale 12-bit L/R interleaved */
 #define V4L2_PIX_FMT_Z16      v4l2_fourcc('Z', '1', '6', ' ') /* Depth data 16-bit */
+#define V4L2_PIX_FMT_MT21     v4l2_fourcc('M', 'T', '2', '1') /* Mediatek compressed block mode  */
 
 /* SDR formats - used only for Software Defined Radio devices */
 #define V4L2_SDR_FMT_CU8          v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Thu May 12 04:24:10 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Thu, 12 May 2016 19:24:10 +0800
Subject: [PATCH v2 9/9] arm64: dts: mediatek: Add Video Decoder for MT8173
In-Reply-To: <1463052250-38262-9-git-send-email-tiffany.lin@mediatek.com>
References: <1463052250-38262-1-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-2-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-3-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-4-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-5-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-6-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-7-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-8-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-9-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1463052250-38262-10-git-send-email-tiffany.lin@mediatek.com>

Add video decoder node for MT8173

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi |   38 ++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index 348ce0e..8c9e3b6 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -691,6 +691,44 @@
 			#clock-cells = <1>;
 		};
 
+		vcodec_dec: vcodec at 16000000 {
+			compatible = "mediatek,mt8173-vcodec-dec";
+			reg = <0 0x16000000 0 0x100>,	/* VDEC_SYS */
+			      <0 0x16020000 0 0x1000>,	/* VDEC_MISC */
+			      <0 0x16021000 0 0x800>,	/* VDEC_LD */
+			      <0 0x16021800 0 0x800>,	/* VDEC_TOP */
+			      <0 0x16022000 0 0x1000>,	/* VDEC_CM */
+			      <0 0x16023000 0 0x1000>,	/* VDEC_AD */
+			      <0 0x16024000 0 0x1000>,	/* VDEC_AV */
+			      <0 0x16025000 0 0x1000>,	/* VDEC_PP */
+			      <0 0x16026800 0 0x800>,	/* VDEC_HWD */
+			      <0 0x16027000 0 0x800>,	/* VDEC_HWQ */
+			      <0 0x16027800 0 0x800>,	/* VDEC_HWB */
+			      <0 0x16028400 0 0x400>;	/* VDEC_HWG */
+			interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_LOW>;
+			mediatek,larb = <&larb1>;
+			iommus = <&iommu M4U_PORT_HW_VDEC_MC_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_PP_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_AVC_MV_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_PRED_RD_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_PRED_WR_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_UFO_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_VLD_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_VLD2_EXT>;
+			mediatek,vpu = <&vpu>;
+			power-domains = <&scpsys MT8173_POWER_DOMAIN_VDEC>;
+			clocks = <&apmixedsys CLK_APMIXED_VCODECPLL>,
+				 <&topckgen CLK_TOP_UNIVPLL_D2>,
+				 <&topckgen CLK_TOP_CCI400_SEL>,
+				 <&topckgen CLK_TOP_VDEC_SEL>,
+				 <&topckgen CLK_TOP_VCODECPLL>;
+			clock-names = "vcodecpll",
+				      "univpll_d2",
+				      "clk_cci400_sel",
+				      "vdec_sel",
+				      "vdecpll";
+		};
+
 		larb1: larb at 16010000 {
 			compatible = "mediatek,mt8173-smi-larb";
 			reg = <0 0x16010000 0 0x1000>;
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Thu May 12 04:24:04 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Thu, 12 May 2016 19:24:04 +0800
Subject: [PATCH v2 3/9] [media] DocBook/v4l: Add compressed video formats used
 on MT8173 codec driver
In-Reply-To: <1463052250-38262-3-git-send-email-tiffany.lin@mediatek.com>
References: <1463052250-38262-1-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-2-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-3-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1463052250-38262-4-git-send-email-tiffany.lin@mediatek.com>

Add V4L2_PIX_FMT_MT21 documentation

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 Documentation/DocBook/media/v4l/pixfmt.xml |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
index 5a08aee..d40e0ce 100644
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt.xml
@@ -1980,6 +1980,12 @@ array. Anything what's in between the UYVY lines is JPEG data and should be
 concatenated to form the JPEG stream. </para>
 </entry>
 	  </row>
+	  <row id="V4L2_PIX_FMT_MT21">
+	    <entry><constant>V4L2_PIX_FMT_MT21</constant></entry>
+	    <entry>'MT21'</entry>
+	    <entry>Compressed two-planar YVU420 format used by Mediatek MT8173
+	    codec driver.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Thu May 12 04:24:01 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Thu, 12 May 2016 19:24:01 +0800
Subject: [PATCH v2 0/9] Add MT8173 Video Decoder Driver
Message-ID: <1463052250-38262-1-git-send-email-tiffany.lin@mediatek.com>

==============
 Introduction
==============

The purpose of this series is to add the driver for video codec hw embedded in the Mediatek's MT8173 SoCs.
Mediatek Video Codec is able to handle video decoding of in a range of formats.

This patch series add Mediatek block format V4L2_PIX_FMT_MT21, the decoder driver will decoded bitstream to
V4L2_PIX_FMT_MT21 format.

This patch series rely on MTK VPU driver in patch series "Add MT8173 Video Encoder Driver and VPU Driver"[1]
and patch "CHROMIUM: v4l: Add V4L2_PIX_FMT_VP9 definition"[2] for VP9 support.
Mediatek Video Decoder driver rely on VPU driver to load, communicate with VPU.

Internally the driver uses videobuf2 framework and MTK IOMMU and MTK SMI both have been merged in v4.6-rc1.

[1]https://patchwork.linuxtv.org/patch/33734/
[2]https://chromium-review.googlesource.com/#/c/245241/

==================
 Device interface
==================

In principle the driver bases on v4l2 memory-to-memory framework:
it provides a single video node and each opened file handle gets its own private context with separate
buffer queues. Each context consist of 2 buffer queues: OUTPUT (for source buffers, i.e. bitstream)
and CAPTURE (for destination buffers, i.e. decoded video frames).
OUTPUT and CAPTURE buffer could be MMAP or DMABUF memory type.
VIDIOC_G_CTRL and VIDIOC_G_EXT_CTRLS return V4L2_CID_MIN_BUFFERS_FOR_CAPTURE only when dirver in MTK_STATE_HEADER
state, or it will return EAGAIN.
Driver do not support subscribe event for control 'User Controls' for now.
And it default support export DMABUF for other display drivers.

Change in v2:
1. Add documentation for V4L2_PIX_FMT_MT21
2. Remove DRM_FORMAT_MT21
3. Refine code according to review comments

v4l2-compliance test output:
localhost Encode # ./v4l2-compliance -d /dev/video0
Driver Info:
        Driver name   : mtk-vcodec-dec
        Card type     : platform:mt8173
        Bus info      : platform:mt8173
        Driver version: 4.4.0
        Capabilities  : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps   : 0x04204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format

Compliance test for device /dev/video0 (not using libv4l2):

Required ioctls:
        test VIDIOC_QUERYCAP: OK

Allow for multiple opens:
        test second video open: OK
        test VIDIOC_QUERYCAP: OK
        test VIDIOC_G/S_PRIORITY: OK

Debug ioctls:
        test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
        test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
        test VIDIOC_ENUMAUDIO: OK (Not Supported)
        test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDIO: OK (Not Supported)
        Inputs: 0 Audio Inputs: 0 Tuners: 0

Output ioctls:
        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
        Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
        test VIDIOC_G/S_EDID: OK (Not Supported)

        Control ioctls:
                test VIDIOC_QUERYCTRL/MENU: OK
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-controls.cpp(357): g_ctrl returned an error (11)
                test VIDIOC_G/S_CTRL: FAIL
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-controls.cpp(579): g_ext_ctrls returned an error (11)
                test VIDIOC_G/S/TRY_EXT_CTRLS: FAIL
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-controls.cpp(721): subscribe event for control 'User Controls' failed
                test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: FAIL
                test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
                Standard Controls: 2 Private Controls: 0

        Format ioctls:
                test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
                test VIDIOC_G/S_PARM: OK (Not Supported)
                test VIDIOC_G_FBUF: OK (Not Supported)
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-formats.cpp(405): expected EINVAL, but got 11 when getting format for buftype 9
                test VIDIOC_G_FMT: FAIL
                test VIDIOC_TRY_FMT: OK (Not Supported)
                test VIDIOC_S_FMT: OK (Not Supported)
                test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)

        Codec ioctls:
                test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
                test VIDIOC_G_ENC_INDEX: OK (Not Supported)
                test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

        Buffer ioctls:
                test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(500): q.has_expbuf(node)
                test VIDIOC_EXPBUF: FAIL


Total: 38, Succeeded: 33, Failed: 5, Warnings: 0


Andrew-CT Chen (1):
  WIP: media: VPU: Add decoder driver

Tiffany Lin (8):
  [media] : v4l: add Mediatek compressed video block format
  [media] DocBook/v4l: Add compressed video formats used on MT8173
    codec driver
  WIP: media: devicetree: bindings: Document Mediatek Video Decoder
  WIP: media: Add Mediatek V4L2 Video Decoder Driver
  WIP: media: Add Mediatek H264 Video Decode Driver
  WIP: media: Add Mediatek VP8 Video Decoder Driver
  WIP: media: Add Mediatek VP9 Video Decoder Driver
  WIP: arm64: dts: mt8173: Add node for Mediatek Video Decoder

 Documentation/DocBook/media/v4l/pixfmt.xml         |    6 +
 .../devicetree/bindings/media/mediatek-vcodec.txt  |   50 +-
 arch/arm64/boot/dts/mediatek/mt8173.dtsi           |   38 +
 drivers/media/platform/mtk-vcodec/Makefile         |   15 +-
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 1336 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h |   81 ++
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c |  440 +++++++
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c  |  154 +++
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h  |   28 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h |   81 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_intr.h    |    2 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_util.c    |   10 +-
 .../media/platform/mtk-vcodec/vdec/vdec_h264_if.c  |  504 ++++++++
 .../media/platform/mtk-vcodec/vdec/vdec_vp8_if.c   |  632 +++++++++
 .../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c   |  947 ++++++++++++++
 drivers/media/platform/mtk-vcodec/vdec_drv_base.h  |   56 +
 drivers/media/platform/mtk-vcodec/vdec_drv_if.c    |  123 ++
 drivers/media/platform/mtk-vcodec/vdec_drv_if.h    |   93 ++
 drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h   |  103 ++
 drivers/media/platform/mtk-vcodec/vdec_vpu_if.c    |  168 +++
 drivers/media/platform/mtk-vcodec/vdec_vpu_if.h    |   96 ++
 drivers/media/platform/mtk-vpu/mtk_vpu.c           |   12 +
 drivers/media/platform/mtk-vpu/mtk_vpu.h           |   27 +
 include/uapi/linux/videodev2.h                     |    1 +
 24 files changed, 4982 insertions(+), 21 deletions(-)
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_drv_base.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_drv_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_drv_if.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_vpu_if.h

-- 
1.7.9.5



From tiffany.lin at mediatek.com  Thu May 12 04:24:05 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Thu, 12 May 2016 19:24:05 +0800
Subject: [PATCH v2 4/9] dt-bindings: Add a binding for Mediatek Video Decoder
In-Reply-To: <1463052250-38262-4-git-send-email-tiffany.lin@mediatek.com>
References: <1463052250-38262-1-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-2-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-3-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-4-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1463052250-38262-5-git-send-email-tiffany.lin@mediatek.com>

Add a DT binding documentation of Video Decoder for the
MT8173 SoC from Mediatek.

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 .../devicetree/bindings/media/mediatek-vcodec.txt  |   50 ++++++++++++++++++--
 1 file changed, 46 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/mediatek-vcodec.txt b/Documentation/devicetree/bindings/media/mediatek-vcodec.txt
index 59a47a5..9aa8848 100644
--- a/Documentation/devicetree/bindings/media/mediatek-vcodec.txt
+++ b/Documentation/devicetree/bindings/media/mediatek-vcodec.txt
@@ -1,25 +1,67 @@
 Mediatek Video Codec
 
 Mediatek Video Codec is the video codec hw present in Mediatek SoCs which
-supports high resolution encoding functionalities.
+supports high resolution encoding and decoding functionalities.
 
 Required properties:
 - compatible : "mediatek,mt8173-vcodec-enc" for encoder
+  "mediatek,mt8173-vcodec-dec" for decoder.
 - reg : Physical base address of the video codec registers and length of
   memory mapped region.
 - interrupts : interrupt number to the cpu.
 - mediatek,larb : must contain the local arbiters in the current Socs.
 - clocks : list of clock specifiers, corresponding to entries in
   the clock-names property.
-- clock-names: encoder must contain "venc_sel_src", "venc_sel",
-- "venc_lt_sel_src", "venc_lt_sel".
+- clock-names: encoder must contain "venc_sel_src", "venc_sel",,
+  "venc_lt_sel_src", "venc_lt_sel", decoder must contain "vcodecpll",
+  "univpll_d2", "clk_cci400_sel", "vdec_sel", "vdecpll".
 - iommus : should point to the respective IOMMU block with master port as
   argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
   for details.
 - mediatek,vpu : the node of video processor unit
 
+
 Example:
-vcodec_enc: vcodec at 0x18002000 {
+
+vcodec_dec: vcodec at 16000000 {
+    compatible = "mediatek,mt8173-vcodec-dec";
+    reg = <0 0x16000000 0 0x100>,   /*VDEC_SYS*/
+          <0 0x16020000 0 0x1000>,  /*VDEC_MISC*/
+          <0 0x16021000 0 0x800>,   /*VDEC_LD*/
+          <0 0x16021800 0 0x800>,   /*VDEC_TOP*/
+          <0 0x16022000 0 0x1000>,  /*VDEC_CM*/
+          <0 0x16023000 0 0x1000>,  /*VDEC_AD*/
+          <0 0x16024000 0 0x1000>,  /*VDEC_AV*/
+          <0 0x16025000 0 0x1000>,  /*VDEC_PP*/
+          <0 0x16026800 0 0x800>,   /*VP8_VD*/
+          <0 0x16027000 0 0x800>,   /*VP6_VD*/
+          <0 0x16027800 0 0x800>,   /*VP8_VL*/
+          <0 0x16028400 0 0x400>;   /*VP9_VD*/
+    interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_LOW>;
+    mediatek,larb = <&larb1>;
+    iommus = <&iommu M4U_PORT_HW_VDEC_MC_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_PP_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_AVC_MV_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_PRED_RD_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_PRED_WR_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_UFO_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_VLD_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_VLD2_EXT>;
+    mediatek,vpu = <&vpu>;
+    power-domains = <&scpsys MT8173_POWER_DOMAIN_VDEC>;
+    clocks = <&apmixedsys CLK_APMIXED_VCODECPLL>,
+             <&topckgen CLK_TOP_UNIVPLL_D2>,
+             <&topckgen CLK_TOP_CCI400_SEL>,  
+             <&topckgen CLK_TOP_VDEC_SEL>,
+             <&topckgen CLK_TOP_VCODECPLL>;
+    clock-names = "vcodecpll",
+                  "univpll_d2",
+                  "clk_cci400_sel",   
+                  "vdec_sel",  
+                  "vdecpll";
+  };
+
+  vcodec_enc: vcodec at 0x18002000 {
     compatible = "mediatek,mt8173-vcodec-enc";
     reg = <0 0x18002000 0 0x1000>,    /*VENC_SYS*/
           <0 0x19002000 0 0x1000>;    /*VENC_LT_SYS*/
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Thu May 12 04:24:02 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Thu, 12 May 2016 19:24:02 +0800
Subject: [PATCH v2 1/9] [media] VPU: mediatek: Add decode support
In-Reply-To: <1463052250-38262-1-git-send-email-tiffany.lin@mediatek.com>
References: <1463052250-38262-1-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1463052250-38262-2-git-send-email-tiffany.lin@mediatek.com>

From: Andrew-CT Chen <andrew-ct.chen at mediatek.com>

VPU driver add decode support

Signed-off-by: Andrew-CT Chen <andrew-ct.chen at mediatek.com>
Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 drivers/media/platform/mtk-vpu/mtk_vpu.c |   12 ++++++++++++
 drivers/media/platform/mtk-vpu/mtk_vpu.h |   27 +++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c
index b60d02c..ca23b1f 100644
--- a/drivers/media/platform/mtk-vpu/mtk_vpu.c
+++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c
@@ -134,6 +134,8 @@ struct vpu_wdt {
  *
  * @signaled:		the signal of vpu initialization completed
  * @fw_ver:		VPU firmware version
+ * @dec_capability:	decoder capability which is not used for now and
+ *			the value is reserved for future use
  * @enc_capability:	encoder capability which is not used for now and
  *			the value is reserved for future use
  * @wq:			wait queue for VPU initialization status
@@ -141,6 +143,7 @@ struct vpu_wdt {
 struct vpu_run {
 	u32 signaled;
 	char fw_ver[VPU_FW_VER_LEN];
+	unsigned int	dec_capability;
 	unsigned int	enc_capability;
 	wait_queue_head_t wq;
 };
@@ -415,6 +418,14 @@ int vpu_wdt_reg_handler(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(vpu_wdt_reg_handler);
 
+unsigned int vpu_get_vdec_hw_capa(struct platform_device *pdev)
+{
+	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
+
+	return vpu->run.dec_capability;
+}
+EXPORT_SYMBOL_GPL(vpu_get_vdec_hw_capa);
+
 unsigned int vpu_get_venc_hw_capa(struct platform_device *pdev)
 {
 	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
@@ -600,6 +611,7 @@ static void vpu_init_ipi_handler(void *data, unsigned int len, void *priv)
 
 	vpu->run.signaled = run->signaled;
 	strncpy(vpu->run.fw_ver, run->fw_ver, VPU_FW_VER_LEN);
+	vpu->run.dec_capability = run->dec_capability;
 	vpu->run.enc_capability = run->enc_capability;
 	wake_up_interruptible(&vpu->run.wq);
 }
diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.h b/drivers/media/platform/mtk-vpu/mtk_vpu.h
index 5ab37f0..f457479 100644
--- a/drivers/media/platform/mtk-vpu/mtk_vpu.h
+++ b/drivers/media/platform/mtk-vpu/mtk_vpu.h
@@ -37,6 +37,18 @@ typedef void (*ipi_handler_t) (void *data,
 			 command to VPU.
 			 For other IPI below, AP should send the request
 			 to VPU to trigger the interrupt.
+ * @IPI_VDEC_H264:	 The interrupt from vpu is to notify kernel to
+			 handle H264 vidoe decoder job, and vice versa.
+			 Decode output format is always MT21 no matter what
+			 the input format is.
+ * @IPI_VDEC_VP8:	 The interrupt from is to notify kernel to
+			 handle VP8 video decoder job, and vice versa.
+			 Decode output format is always MT21 no matter what
+			 the input format is.
+ * @IPI_VDEC_VP9:	 The interrupt from vpu is to notify kernel to
+			 handle VP9 video decoder job, and vice versa.
+			 Decode output format is always MT21 no matter what
+			 the input format is.
  * @IPI_VENC_H264:	 The interrupt from vpu is to notify kernel to
 			 handle H264 video encoder job, and vice versa.
  * @IPI_VENC_VP8:	 The interrupt fro vpu is to notify kernel to
@@ -46,6 +58,9 @@ typedef void (*ipi_handler_t) (void *data,
 
 enum ipi_id {
 	IPI_VPU_INIT = 0,
+	IPI_VDEC_H264,
+	IPI_VDEC_VP8,
+	IPI_VDEC_VP9,
 	IPI_VENC_H264,
 	IPI_VENC_VP8,
 	IPI_MAX,
@@ -55,10 +70,12 @@ enum ipi_id {
  * enum rst_id - reset id to register reset function for VPU watchdog timeout
  *
  * @VPU_RST_ENC: encoder reset id
+ * @VPU_RST_DEC: decoder reset id
  * @VPU_RST_MAX: maximum reset id
  */
 enum rst_id {
 	VPU_RST_ENC,
+	VPU_RST_DEC,
 	VPU_RST_MAX,
 };
 
@@ -125,6 +142,16 @@ struct platform_device *vpu_get_plat_device(struct platform_device *pdev);
 int vpu_wdt_reg_handler(struct platform_device *pdev,
 			void vpu_wdt_reset_func(void *),
 			void *priv, enum rst_id id);
+
+/**
+ * vpu_get_vdec_hw_capa - get video decoder hardware capability
+ *
+ * @pdev:	VPU platform device
+ *
+ * Return: video decoder hardware capability
+ **/
+unsigned int vpu_get_vdec_hw_capa(struct platform_device *pdev);
+
 /**
  * vpu_get_venc_hw_capa - get video encoder hardware capability
  *
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Thu May 12 04:24:08 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Thu, 12 May 2016 19:24:08 +0800
Subject: [PATCH v2 7/9] [media] vcodec: mediatek: Add Mediatek VP8 Video
 Decoder Driver
In-Reply-To: <1463052250-38262-7-git-send-email-tiffany.lin@mediatek.com>
References: <1463052250-38262-1-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-2-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-3-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-4-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-5-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-6-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-7-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1463052250-38262-8-git-send-email-tiffany.lin@mediatek.com>

Add vp8 decoder driver for MT8173

Signed-off-by: PC Chen <pc.chen at mediatek.com>
Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 drivers/media/platform/mtk-vcodec/Makefile         |    1 +
 .../media/platform/mtk-vcodec/vdec/vdec_vp8_if.c   |  632 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/vdec_drv_if.c    |    3 +
 3 files changed, 636 insertions(+)
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c

diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
index 58243ed..7743c81 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
 				       mtk-vcodec-common.o
 
 mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
+		vdec/vdec_vp8_if.o \
 		mtk_vcodec_dec_drv.o \
 		vdec_drv_if.o \
 		vdec_vpu_if.o \
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
new file mode 100644
index 0000000..cd9b190
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Jungchang Tsao <jungchang.tsao at mediatek.com>
+ *	   PC Chen <pc.chen at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "../mtk_vcodec_intr.h"
+#include "../vdec_vpu_if.h"
+#include "../vdec_drv_base.h"
+
+/* Decoding picture buffer size (3 reference frames plus current frame) */
+#define VP8_DPB_SIZE			4
+
+/* HW working buffer size (bytes) */
+#define VP8_WORKING_BUF_SZ		(45 * 4096)
+
+/* HW control register address */
+#define VP8_SEGID_DRAM_ADDR		0x3c
+#define VP8_HW_VLD_ADDR			0x93C
+#define VP8_HW_VLD_VALUE		0x940
+#define VP8_BSASET			0x100
+#define VP8_BSDSET			0x104
+#define VP8_RW_CKEN_SET			0x0
+#define VP8_RW_DCM_CON			0x18
+#define VP8_WO_VLD_SRST			0x108
+#define VP8_RW_MISC_SYS_SEL		0x84
+#define VP8_RW_MISC_SPEC_CON		0xC8
+#define VP8_WO_VLD_SRST			0x108
+#define VP8_RW_VP8_CTRL			0xA4
+#define VP8_RW_MISC_DCM_CON		0xEC
+#define VP8_RW_MISC_SRST		0xF4
+#define VP8_RW_MISC_FUNC_CON		0xCC
+
+#define VP8_MAX_FRM_BUF_NUM		5
+#define VP8_MAX_FRM_BUF_NODE_NUM	(VP8_MAX_FRM_BUF_NUM * 2)
+
+/* required buffer size (bytes) to store decode information */
+#define VP8_HW_SEGMENT_DATA_SZ		272
+#define VP8_HW_SEGMENT_UINT		4
+
+#define VP8_DEC_TABLE_PROC_LOOP		96
+#define VP8_DEC_TABLE_UNIT		3
+#define VP8_DEC_TABLE_SZ		300
+#define VP8_DEC_TABLE_OFFSET		2
+#define VP8_DEC_TABLE_RW_UNIT		4
+
+/**
+ * struct vdec_vp8_dec_info - decode misc information
+ * @working_buf_dma   : working buffer dma address
+ * @prev_y_dma        : previous decoded frame buffer Y plane address
+ * @cur_y_fb_dma      : current plane Y frame buffer dma address
+ * @cur_c_fb_dma      : current plane C frame buffer dma address
+ * @bs_dma	      : bitstream dma address
+ * @bs_sz	      : bitstream size
+ * @resolution_changed: resolution change flag 1 - changed,  0 - not change
+ * @show_frame	      : display this frame or not
+ * @wait_key_frame    : wait key frame coming
+ */
+struct vdec_vp8_dec_info {
+	uint64_t working_buf_dma;
+	uint64_t prev_y_dma;
+	uint64_t cur_y_fb_dma;
+	uint64_t cur_c_fb_dma;
+	uint64_t bs_dma;
+	uint32_t bs_sz;
+	uint32_t resolution_changed;
+	uint32_t show_frame;
+	uint32_t wait_key_frame;
+};
+
+/**
+ * struct vdec_vp8_vsi - VPU shared information
+ * @dec			: decoding information
+ * @pic			: picture information
+ * @dec_table		: decoder coefficient table
+ * @segment_buf		: segmentation buffer
+ * @load_data		: flag to indicate reload decode data
+ */
+struct vdec_vp8_vsi {
+	struct vdec_vp8_dec_info dec;
+	struct vdec_pic_info pic;
+	uint32_t dec_table[VP8_DEC_TABLE_SZ];
+	uint32_t segment_buf[VP8_HW_SEGMENT_DATA_SZ][VP8_HW_SEGMENT_UINT];
+	uint32_t load_data;
+};
+
+/**
+ * struct vdec_vp8_hw_reg_base - HW register base
+ * @sys		: base address for sys
+ * @misc	: base address for misc
+ * @ld		: base address for ld
+ * @top		: base address for top
+ * @cm		: base address for cm
+ * @hwd		: base address for hwd
+ * @hwb		: base address for hwb
+*/
+struct vdec_vp8_hw_reg_base {
+	void __iomem *sys;
+	void __iomem *misc;
+	void __iomem *ld;
+	void __iomem *top;
+	void __iomem *cm;
+	void __iomem *hwd;
+	void __iomem *hwb;
+};
+
+/**
+ * struct vdec_vp8_vpu_inst - VPU instance for VP8 decode
+ * @wq_hd	: Wait queue to wait VPU message ack
+ * @signaled	: 1 - Host has received ack message from VPU, 0 - not recevie
+ * @failure	: VPU execution result status 0 - success, others - fail
+ * @inst_addr	: VPU decoder instance address
+ */
+struct vdec_vp8_vpu_inst {
+	wait_queue_head_t wq_hd;
+	int signaled;
+	int failure;
+	uint32_t inst_addr;
+};
+
+/* frame buffer (fb) list
+ * [available_fb_node_list]  - decode fb are initialized to 0 and populated in
+ * [fb_use_list]  - fb is set after decode and is moved to this list
+ * [fb_free_list] - fb is not needed for reference will be moved from
+ *		     [fb_use_list] to [fb_free_list] and
+ *		     once user remove fb from [fb_free_list],
+ *		     it is circulated back to [available_fb_node_list]
+ * [fb_disp_list] - fb is set after decode and is moved to this list
+ *                   once user remove fb from [fb_disp_list] it is
+ *                   circulated back to [available_fb_node_list]
+ */
+
+/**
+ * struct vdec_vp8_inst - VP8 decoder instance
+ * @cur_fb		   : current frame buffer
+ * @dec_fb		   : decode frame buffer node
+ * @available_fb_node_list : list to store available frame buffer node
+ * @fb_use_list		   : list to store frame buffer in use
+ * @fb_free_list	   : list to store free frame buffer
+ * @fb_disp_list	   : list to store display ready frame buffer
+ * @working_buf		   : HW decoder working buffer
+ * @reg_base		   : HW register base address
+ * @frm_cnt		   : decode frame count
+ * @ctx			   : V4L2 context
+ * @dev			   : platform device
+ * @vpu			   : VPU instance for decoder
+ * @vsi			   : VPU share information
+ */
+struct vdec_vp8_inst {
+	struct vdec_fb *cur_fb;
+	struct vdec_fb_node dec_fb[VP8_MAX_FRM_BUF_NODE_NUM];
+	struct list_head available_fb_node_list;
+	struct list_head fb_use_list;
+	struct list_head fb_free_list;
+	struct list_head fb_disp_list;
+	struct mtk_vcodec_mem working_buf;
+	struct vdec_vp8_hw_reg_base reg_base;
+	unsigned int frm_cnt;
+	struct mtk_vcodec_ctx *ctx;
+	struct vdec_vpu_inst vpu;
+	struct vdec_vp8_vsi *vsi;
+};
+
+static void get_hw_reg_base(struct vdec_vp8_inst *inst)
+{
+	inst->reg_base.top = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_TOP);
+	inst->reg_base.cm = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_CM);
+	inst->reg_base.hwd = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_HWD);
+	inst->reg_base.sys = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_SYS);
+	inst->reg_base.misc = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_MISC);
+	inst->reg_base.ld = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_LD);
+	inst->reg_base.hwb = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_HWB);
+}
+
+static void write_hw_segmentation_data(struct vdec_vp8_inst *inst)
+{
+	int i, j;
+	u32 seg_id_addr;
+	u32 val;
+	void __iomem *cm = inst->reg_base.cm;
+	struct vdec_vp8_vsi *vsi = inst->vsi;
+
+	seg_id_addr = readl(inst->reg_base.top + VP8_SEGID_DRAM_ADDR) >> 4;
+
+	for (i = 0; i < ARRAY_SIZE(vsi->segment_buf); i++) {
+		for (j = ARRAY_SIZE(vsi->segment_buf[i]) - 1; j >= 0; j--) {
+			val = (1 << 16) + ((seg_id_addr + i) << 2) + j;
+			writel(val, cm + VP8_HW_VLD_ADDR);
+
+			val = vsi->segment_buf[i][j];
+			writel(val, cm + VP8_HW_VLD_VALUE);
+		}
+	}
+}
+
+static void read_hw_segmentation_data(struct vdec_vp8_inst *inst)
+{
+	int i, j;
+	u32 seg_id_addr;
+	u32 val;
+	void __iomem *cm = inst->reg_base.cm;
+	struct vdec_vp8_vsi *vsi = inst->vsi;
+
+	seg_id_addr = readl(inst->reg_base.top + VP8_SEGID_DRAM_ADDR) >> 4;
+
+	for (i = 0; i < ARRAY_SIZE(vsi->segment_buf); i++) {
+		for (j = ARRAY_SIZE(vsi->segment_buf[i]) - 1; j >= 0; j--) {
+			val = ((seg_id_addr + i) << 2) + j;
+			writel(val, cm + VP8_HW_VLD_ADDR);
+
+			val = readl(cm + VP8_HW_VLD_VALUE);
+			vsi->segment_buf[i][j] = val;
+		}
+	}
+}
+
+/* reset HW and enable HW read/write data function */
+static void enable_hw_rw_function(struct vdec_vp8_inst *inst)
+{
+	u32 val = 0;
+	void __iomem *sys = inst->reg_base.sys;
+	void __iomem *misc = inst->reg_base.misc;
+	void __iomem *ld = inst->reg_base.ld;
+	void __iomem *hwb = inst->reg_base.hwb;
+	void __iomem *hwd = inst->reg_base.hwd;
+
+	writel(0x1, sys + VP8_RW_CKEN_SET);
+	writel(0x101, ld + VP8_WO_VLD_SRST);
+	writel(0x101, hwb + VP8_WO_VLD_SRST);
+
+	writel(1, sys);
+	val = readl(misc + VP8_RW_MISC_SRST);
+	writel((val & 0xFFFFFFFE), misc + VP8_RW_MISC_SRST);
+
+	writel(0x1, misc + VP8_RW_MISC_SYS_SEL);
+	writel(0x17F, misc + VP8_RW_MISC_SPEC_CON);
+	writel(0x71201100, misc + VP8_RW_MISC_FUNC_CON);
+	writel(0x0, ld + VP8_WO_VLD_SRST);
+	writel(0x0, hwb + VP8_WO_VLD_SRST);
+	writel(0x1, sys + VP8_RW_DCM_CON);
+	writel(0x1, misc + VP8_RW_MISC_DCM_CON);
+	writel(0x1, hwd + VP8_RW_VP8_CTRL);
+}
+
+static void store_dec_table(struct vdec_vp8_inst *inst)
+{
+	int i, j;
+	u32 addr = 0, val = 0;
+	void __iomem *hwd = inst->reg_base.hwd;
+	u32 *p = &inst->vsi->dec_table[VP8_DEC_TABLE_OFFSET];
+
+	for (i = 0; i < VP8_DEC_TABLE_PROC_LOOP; i++) {
+		writel(addr, hwd + VP8_BSASET);
+		for (j = 0; j < VP8_DEC_TABLE_UNIT ; j++) {
+			val = *p++;
+			writel(val, hwd + VP8_BSDSET);
+		}
+		addr += VP8_DEC_TABLE_RW_UNIT;
+	}
+}
+
+static void load_dec_table(struct vdec_vp8_inst *inst)
+{
+	int i;
+	u32 addr = 0;
+	u32 *p = &inst->vsi->dec_table[VP8_DEC_TABLE_OFFSET];
+	void __iomem *hwd = inst->reg_base.hwd;
+
+	for (i = 0; i < VP8_DEC_TABLE_PROC_LOOP; i++) {
+		writel(addr, hwd + VP8_BSASET);
+		/* read total 11 bytes */
+		*p++ = readl(hwd + VP8_BSDSET);
+		*p++ = readl(hwd + VP8_BSDSET);
+		*p++ = readl(hwd + VP8_BSDSET) & 0xFFFFFF;
+		addr += VP8_DEC_TABLE_RW_UNIT;
+	}
+}
+
+static void get_pic_info(struct vdec_vp8_inst *inst, struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+
+	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
+			 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
+	mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+			 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void vp8_dec_finish(struct vdec_vp8_inst *inst)
+{
+	struct vdec_fb_node *node;
+	uint64_t prev_y_dma = inst->vsi->dec.prev_y_dma;
+
+	mtk_vcodec_debug(inst, "prev fb base dma=%llx", prev_y_dma);
+
+	/* put last decode ok frame to fb_free_list */
+	if (0 != prev_y_dma) {
+		list_for_each_entry(node, &inst->fb_use_list, list) {
+			struct vdec_fb *fb = (struct vdec_fb *)node->fb;
+
+			if (prev_y_dma == (uint64_t)fb->base_y.dma_addr) {
+				list_move_tail(&node->list,
+					       &inst->fb_free_list);
+				break;
+			}
+		}
+	}
+
+	/* available_fb_node_list -> fb_use_list */
+	node = list_first_entry(&inst->available_fb_node_list,
+				struct vdec_fb_node, list);
+	node->fb = inst->cur_fb;
+	list_move_tail(&node->list, &inst->fb_use_list);
+
+	/* available_fb_node_list -> fb_disp_list */
+	if (inst->vsi->dec.show_frame) {
+		node = list_first_entry(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+		node->fb = inst->cur_fb;
+		list_move_tail(&node->list, &inst->fb_disp_list);
+	}
+}
+
+static void move_fb_list_use_to_free(struct vdec_vp8_inst *inst)
+{
+	struct vdec_fb_node *node, *tmp;
+
+	list_for_each_entry_safe(node, tmp, &inst->fb_use_list, list)
+		list_move_tail(&node->list, &inst->fb_free_list);
+}
+
+static void init_list(struct vdec_vp8_inst *inst)
+{
+	int i;
+
+	INIT_LIST_HEAD(&inst->available_fb_node_list);
+	INIT_LIST_HEAD(&inst->fb_use_list);
+	INIT_LIST_HEAD(&inst->fb_free_list);
+	INIT_LIST_HEAD(&inst->fb_disp_list);
+
+	for (i = 0; i < ARRAY_SIZE(inst->dec_fb); i++) {
+		INIT_LIST_HEAD(&inst->dec_fb[i].list);
+		inst->dec_fb[i].fb = NULL;
+		list_add_tail(&inst->dec_fb[i].list,
+			      &inst->available_fb_node_list);
+	}
+}
+
+static void add_fb_to_free_list(struct vdec_vp8_inst *inst, void *fb)
+{
+	struct vdec_fb_node *node;
+
+	if (fb) {
+		node = list_first_entry(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+		node->fb = fb;
+		list_move_tail(&node->list, &inst->fb_free_list);
+	}
+}
+
+static int alloc_working_buf(struct vdec_vp8_inst *inst)
+{
+	int err;
+	struct mtk_vcodec_mem *mem = &inst->working_buf;
+
+	mem->size = VP8_WORKING_BUF_SZ;
+	err = mtk_vcodec_mem_alloc(inst->ctx, mem);
+	if (err) {
+		mtk_vcodec_err(inst, "Cannot allocate working buffer");
+		return err;
+	}
+
+	inst->vsi->dec.working_buf_dma = (uint64_t)mem->dma_addr;
+	return 0;
+}
+
+static void free_working_buf(struct vdec_vp8_inst *inst)
+{
+	struct mtk_vcodec_mem *mem = &inst->working_buf;
+
+	if (mem->va)
+		mtk_vcodec_mem_free(inst->ctx, mem);
+
+	inst->vsi->dec.working_buf_dma = 0;
+}
+
+static int vdec_vp8_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_vp8_inst *inst;
+	int err;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return  -ENOMEM;
+
+	inst->ctx = ctx;
+
+	inst->vpu.id = IPI_VDEC_VP8;
+	inst->vpu.dev = ctx->dev->vpu_plat_dev;
+	inst->vpu.ctx = ctx;
+	inst->vpu.handler = vpu_dec_ipi_handler;
+
+	err = vpu_dec_init(&inst->vpu);
+	if (err) {
+		mtk_vcodec_err(inst, "vdec_vp8 init err=%d", err);
+		goto error_free_inst;
+	}
+
+	inst->vsi = (struct vdec_vp8_vsi *)inst->vpu.vsi;
+	init_list(inst);
+	err = alloc_working_buf(inst);
+	if (err)
+		goto error_deinit;
+
+	get_hw_reg_base(inst);
+	mtk_vcodec_debug(inst, "VP8 Instance >> %p", inst);
+
+	*h_vdec = (unsigned long)inst;
+	return 0;
+
+error_deinit:
+	vpu_dec_deinit(&inst->vpu);
+error_free_inst:
+	kfree(inst);
+	return err;
+}
+
+static int vdec_vp8_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+			   struct vdec_fb *fb, bool *res_chg)
+{
+	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
+	struct vdec_vp8_dec_info *dec = &inst->vsi->dec;
+	struct vdec_vpu_inst *vpu = &inst->vpu;
+	unsigned char *bs_va;
+	unsigned int data;
+	int err = 0;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+
+	/* bs NULL means flush decoder */
+	if (bs == NULL) {
+		move_fb_list_use_to_free(inst);
+		return vpu_dec_reset(vpu);
+	}
+
+	y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
+	c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
+
+	mtk_vcodec_debug(inst, "+ [%d] FB y_dma=%llx c_dma=%llx fb=%p",
+			 inst->frm_cnt, y_fb_dma, c_fb_dma, fb);
+
+	inst->cur_fb = fb;
+	dec->bs_dma = (unsigned long)bs->dma_addr;
+	dec->bs_sz = bs->size;
+	dec->cur_y_fb_dma = y_fb_dma;
+	dec->cur_c_fb_dma = c_fb_dma;
+
+	mtk_vcodec_debug(inst, "\n + FRAME[%d] +\n", inst->frm_cnt);
+
+	write_hw_segmentation_data(inst);
+	enable_hw_rw_function(inst);
+	store_dec_table(inst);
+
+	bs_va = (unsigned char *)bs->va;
+
+	/* retrieve width/hight and scale info from header */
+	data = (*(bs_va + 9) << 24) | (*(bs_va + 8) << 16) |
+	       (*(bs_va + 7) << 8) | *(bs_va + 6);
+	err = vpu_dec_start(vpu, &data, 1);
+	if (err) {
+		add_fb_to_free_list(inst, fb);
+		if (dec->wait_key_frame) {
+			mtk_vcodec_debug(inst, "wait key frame !");
+			return 0;
+		}
+
+		goto error;
+	}
+
+	if (dec->resolution_changed) {
+		mtk_vcodec_debug(inst, "- resolution_changed -");
+		*res_chg = true;
+		add_fb_to_free_list(inst, fb);
+		return 0;
+	}
+
+	/* wait decoder done interrupt */
+	mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
+				     WAIT_INTR_TIMEOUT_MS);
+
+	if (inst->vsi->load_data)
+		load_dec_table(inst);
+
+	vp8_dec_finish(inst);
+	read_hw_segmentation_data(inst);
+
+	err = vpu_dec_end(vpu);
+	if (err)
+		goto error;
+
+	mtk_vcodec_debug(inst, "\n - FRAME[%d] - show=%d\n", inst->frm_cnt,
+			 dec->show_frame);
+	inst->frm_cnt++;
+	*res_chg = false;
+	return 0;
+
+error:
+	mtk_vcodec_err(inst, "\n - FRAME[%d] - err=%d\n", inst->frm_cnt, err);
+	return err;
+}
+
+static void get_disp_fb(struct vdec_vp8_inst *inst, struct vdec_fb **out_fb)
+{
+	struct vdec_fb_node *node;
+	struct vdec_fb *fb;
+
+	node = list_first_entry_or_null(&inst->fb_disp_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		list_move_tail(&node->list, &inst->available_fb_node_list);
+		fb = (struct vdec_fb *)node->fb;
+		fb->status |= FB_ST_DISPLAY;
+		mtk_vcodec_debug(inst, "[FB] get disp fb %p st=%d",
+				 node->fb, fb->status);
+	} else {
+		fb = NULL;
+		mtk_vcodec_debug(inst, "[FB] there is no disp fb");
+	}
+
+	*out_fb = fb;
+}
+
+static void get_free_fb(struct vdec_vp8_inst *inst, struct vdec_fb **out_fb)
+{
+	struct vdec_fb_node *node;
+	struct vdec_fb *fb;
+
+	node = list_first_entry_or_null(&inst->fb_free_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		list_move_tail(&node->list, &inst->available_fb_node_list);
+		fb = (struct vdec_fb *)node->fb;
+		fb->status |= FB_ST_FREE;
+		mtk_vcodec_debug(inst, "[FB] get free fb %p st=%d",
+				 node->fb, fb->status);
+	} else {
+		fb = NULL;
+		mtk_vcodec_debug(inst, "[FB] there is no free fb");
+	}
+
+	*out_fb = fb;
+}
+
+static void get_crop_info(struct vdec_vp8_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = 0;
+	cr->top = 0;
+	cr->width = inst->vsi->pic.pic_w;
+	cr->height = inst->vsi->pic.pic_h;
+	mtk_vcodec_debug(inst, "get crop info l=%d, t=%d, w=%d, h=%d",
+			 cr->left, cr->top, cr->width, cr->height);
+}
+
+static int vdec_vp8_get_param(unsigned long h_vdec,
+			      enum vdec_get_param_type type, void *out)
+{
+	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
+
+	switch (type) {
+	case GET_PARAM_DISP_FRAME_BUFFER:
+		get_disp_fb(inst, out);
+		break;
+
+	case GET_PARAM_FREE_FRAME_BUFFER:
+		get_free_fb(inst, out);
+		break;
+
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		*((unsigned int *)out) = VP8_DPB_SIZE;
+		break;
+
+	default:
+		mtk_vcodec_err(inst, "invalid get parameter type=%d", type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vdec_vp8_deinit(unsigned long h_vdec)
+{
+	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
+
+	mtk_vcodec_debug_enter(inst);
+
+	vpu_dec_deinit(&inst->vpu);
+	free_working_buf(inst);
+	kfree(inst);
+
+	return 0;
+}
+
+static struct vdec_common_if vdec_vp8_if = {
+	vdec_vp8_init,
+	vdec_vp8_decode,
+	vdec_vp8_get_param,
+	vdec_vp8_deinit,
+};
+
+struct vdec_common_if *get_vp8_dec_comm_if(void);
+
+struct vdec_common_if *get_vp8_dec_comm_if(void)
+{
+	return &vdec_vp8_if;
+}
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
index 576920c..6e2f065 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
@@ -25,6 +25,7 @@
 #include "mtk_vpu.h"
 
 struct vdec_common_if *get_h264_dec_comm_if(void);
+struct vdec_common_if *get_vp8_dec_comm_if(void);
 
 int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 {
@@ -35,6 +36,8 @@ int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 		ctx->dec_if = get_h264_dec_comm_if();
 		break;
 	case V4L2_PIX_FMT_VP8:
+		ctx->dec_if = get_vp8_dec_comm_if();
+		break;
 	case V4L2_PIX_FMT_VP9:
 	default:
 		return -EINVAL;
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Thu May 12 04:24:07 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Thu, 12 May 2016 19:24:07 +0800
Subject: [PATCH v2 6/9] [media] vcodec: mediatek: Add Mediatek H264 Video
 Decoder Driver
In-Reply-To: <1463052250-38262-6-git-send-email-tiffany.lin@mediatek.com>
References: <1463052250-38262-1-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-2-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-3-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-4-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-5-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-6-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1463052250-38262-7-git-send-email-tiffany.lin@mediatek.com>

Add h264 decoder driver for MT8173

Signed-off-by: PC Chen <pc.chen at mediatek.com>
Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 drivers/media/platform/mtk-vcodec/Makefile         |    5 +-
 .../media/platform/mtk-vcodec/vdec/vdec_h264_if.c  |  504 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/vdec_drv_if.c    |    4 +
 drivers/media/platform/mtk-vcodec/vdec_vpu_if.c    |  168 +++++++
 drivers/media/platform/mtk-vcodec/vdec_vpu_if.h    |   96 ++++
 5 files changed, 775 insertions(+), 2 deletions(-)
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_vpu_if.h

diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
index 4c8ed2f..58243ed 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -1,11 +1,12 @@
 
-
 obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
 				       mtk-vcodec-enc.o \
 				       mtk-vcodec-common.o
 
-mtk-vcodec-dec-y := mtk_vcodec_dec_drv.o \
+mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
+		mtk_vcodec_dec_drv.o \
 		vdec_drv_if.o \
+		vdec_vpu_if.o \
 		mtk_vcodec_dec.o \
 		mtk_vcodec_dec_pm.o \
 
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
new file mode 100644
index 0000000..fcd92f2
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "../mtk_vcodec_intr.h"
+#include "../vdec_vpu_if.h"
+#include "../vdec_drv_base.h"
+
+#define NAL_NON_IDR_SLICE			0x01
+#define NAL_IDR_SLICE				0x05
+#define NAL_H264_PPS				0x08
+#define NAL_TYPE(value)				((value) & 0x1F)
+
+#define BUF_PREDICTION_SZ			(32 * 1024)
+
+#define MB_UNIT_LEN				16
+
+/* motion vector size (bytes) for every macro block */
+#define HW_MB_STORE_SZ				64
+
+#define H264_MAX_FB_NUM				17
+#define HDR_PARSING_BUF_SZ			1024
+
+/**
+ * struct h264_fb - h264 decode frame buffer information
+ * @vdec_fb_va  : virtual address of struct vdec_fb
+ * @y_fb_dma    : dma address of Y frame buffer (luma)
+ * @c_fb_dma    : dma address of C frame buffer (chroma)
+ * @poc         : picture order count of frame buffer
+ * @reserved    : for 8 bytes alignment
+ */
+struct h264_fb {
+	uint64_t vdec_fb_va;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	int32_t poc;
+	uint32_t reserved;
+};
+
+/**
+ * struct h264_ring_fb_list - ring frame buffer list
+ * @fb_list   : frame buffer arrary
+ * @read_idx  : read index
+ * @write_idx : write index
+ * @count     : buffer count in list
+ */
+struct h264_ring_fb_list {
+	struct h264_fb fb_list[H264_MAX_FB_NUM];
+	unsigned int read_idx;
+	unsigned int write_idx;
+	unsigned int count;
+	unsigned int reserved;
+};
+
+/**
+ * struct vdec_h264_dec_info - decode information
+ * @dpb_sz		: decoding picture buffer size
+ * @resolution_changed  : resoltion change happen
+ * @realloc_mv_buf	: flag to notify driver to re-allocate mv buffer
+ * @reserved		: for 8 bytes alignment
+ * @bs_dma		: Input bit-stream buffer dma address
+ * @y_fb_dma		: Y frame buffer dma address
+ * @c_fb_dma		: C frame buffer dma address
+ * @vdec_fb_va		: VDEC frame buffer struct virtual address
+ */
+struct vdec_h264_dec_info {
+	uint32_t dpb_sz;
+	uint32_t resolution_changed;
+	uint32_t realloc_mv_buf;
+	uint32_t reserved;
+	uint64_t bs_dma;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	uint64_t vdec_fb_va;
+};
+
+/**
+ * struct vdec_h264_vsi - shared memory for decode information exchange
+ *                        between VPU and Host.
+ *                        The memory is allocated by VPU then mapping to Host
+ *                        in vpu_dec_init() and freed in vpu_dec_deinit()
+ *                        by VPU.
+ *                        AP-W/R : AP is writer/reader on this item
+ *                        VPU-W/R: VPU is write/reader on this item
+ * @hdr_buf      : Header parsing buffer (AP-W, VPU-R)
+ * @pred_buf_dma : HW working predication buffer dma address (AP-W, VPU-R)
+ * @mv_buf_dma   : HW working motion vector buffer dma address (AP-W, VPU-R)
+ * @list_free    : free frame buffer ring list (AP-W/R, VPU-W)
+ * @list_disp    : display frame buffer ring list (AP-R, VPU-W)
+ * @dec          : decode information (AP-R, VPU-W)
+ * @pic          : picture information (AP-R, VPU-W)
+ * @crop         : crop information (AP-R, VPU-W)
+ */
+struct vdec_h264_vsi {
+	unsigned char hdr_buf[HDR_PARSING_BUF_SZ];
+	uint64_t pred_buf_dma;
+	uint64_t mv_buf_dma[H264_MAX_FB_NUM];
+	struct h264_ring_fb_list list_free;
+	struct h264_ring_fb_list list_disp;
+	struct vdec_h264_dec_info dec;
+	struct vdec_pic_info pic;
+	struct v4l2_rect crop;
+};
+
+/**
+ * struct vdec_h264_inst - h264 decoder instance
+ * @num_nalu : how many nalus be decoded
+ * @ctx      : point to mtk_vcodec_ctx
+ * @pred_buf : HW working predication buffer
+ * @mv_buf   : HW working motion vector buffer
+ * @vpu      : VPU instance
+ * @vsi      : VPU shared information
+ */
+struct vdec_h264_inst {
+	unsigned int num_nalu;
+	struct mtk_vcodec_ctx *ctx;
+	struct mtk_vcodec_mem pred_buf;
+	struct mtk_vcodec_mem mv_buf[H264_MAX_FB_NUM];
+	struct vdec_vpu_inst vpu;
+	struct vdec_h264_vsi *vsi;
+};
+
+static unsigned int get_mv_buf_size(unsigned int width, unsigned int height)
+{
+	return HW_MB_STORE_SZ * (width/MB_UNIT_LEN) * (height/MB_UNIT_LEN);
+}
+
+static int allocate_predication_buf(struct vdec_h264_inst *inst)
+{
+	int err = 0;
+
+	inst->pred_buf.size = BUF_PREDICTION_SZ;
+	err = mtk_vcodec_mem_alloc(inst->ctx, &inst->pred_buf);
+	if (err) {
+		mtk_vcodec_err(inst, "failed to allocate ppl buf");
+		return err;
+	}
+
+	inst->vsi->pred_buf_dma = inst->pred_buf.dma_addr;
+	return 0;
+}
+
+static void free_predication_buf(struct vdec_h264_inst *inst)
+{
+	struct mtk_vcodec_mem *mem = NULL;
+
+	mtk_vcodec_debug_enter(inst);
+
+	inst->vsi->pred_buf_dma = 0;
+	mem = &inst->pred_buf;
+	if (mem->va)
+		mtk_vcodec_mem_free(inst->ctx, mem);
+}
+
+static int alloc_mv_buf(struct vdec_h264_inst *inst, struct vdec_pic_info *pic)
+{
+	int i;
+	int err;
+	struct mtk_vcodec_mem *mem = NULL;
+	unsigned int buf_sz = get_mv_buf_size(pic->buf_w, pic->buf_h);
+
+	for (i = 0; i < H264_MAX_FB_NUM; i++) {
+		mem = &inst->mv_buf[i];
+		if (mem->va)
+			mtk_vcodec_mem_free(inst->ctx, mem);
+		mem->size = buf_sz;
+		err = mtk_vcodec_mem_alloc(inst->ctx, mem);
+		if (err) {
+			mtk_vcodec_err(inst, "failed to allocate mv buf");
+			return err;
+		}
+		inst->vsi->mv_buf_dma[i] = mem->dma_addr;
+	}
+
+	return 0;
+}
+
+static void free_mv_buf(struct vdec_h264_inst *inst)
+{
+	int i;
+	struct mtk_vcodec_mem *mem = NULL;
+
+	for (i = 0; i < H264_MAX_FB_NUM; i++) {
+		inst->vsi->mv_buf_dma[i] = 0;
+		mem = &inst->mv_buf[i];
+		if (mem->va)
+			mtk_vcodec_mem_free(inst->ctx, mem);
+	}
+}
+
+static int check_list_validity(struct vdec_h264_inst *inst, bool disp_list)
+{
+	struct h264_ring_fb_list *list;
+
+	list = disp_list ? &inst->vsi->list_disp : &inst->vsi->list_free;
+
+	if (list->count > H264_MAX_FB_NUM ||
+	    list->read_idx >= H264_MAX_FB_NUM ||
+	    list->write_idx >= H264_MAX_FB_NUM) {
+		mtk_vcodec_err(inst, "%s list err: cnt=%d r_idx=%d w_idx=%d",
+			       disp_list ? "disp" : "free", list->count,
+			       list->read_idx, list->write_idx);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void put_fb_to_free(struct vdec_h264_inst *inst, struct vdec_fb *fb)
+{
+	struct h264_ring_fb_list *list;
+
+	if (fb) {
+		if (check_list_validity(inst, false))
+			return;
+
+		list = &inst->vsi->list_free;
+		if (list->count == H264_MAX_FB_NUM) {
+			mtk_vcodec_err(inst, "[FB] put fb free_list full");
+			return;
+		}
+
+		mtk_vcodec_debug(inst, "[FB] put fb into free_list @(%p, %llx)",
+				 fb->base_y.va, (u64)fb->base_y.dma_addr);
+
+		list->fb_list[list->write_idx].vdec_fb_va = (u64)fb;
+		list->write_idx = (list->write_idx == H264_MAX_FB_NUM - 1) ?
+				  0 : list->write_idx + 1;
+		list->count++;
+	}
+}
+
+static void get_pic_info(struct vdec_h264_inst *inst,
+			 struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
+			 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
+	mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+			 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = inst->vsi->crop.left;
+	cr->top = inst->vsi->crop.top;
+	cr->width = inst->vsi->crop.width;
+	cr->height = inst->vsi->crop.height;
+
+	mtk_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d",
+			 cr->left, cr->top, cr->width, cr->height);
+}
+
+static void get_dpb_size(struct vdec_h264_inst *inst, unsigned int *dpb_sz)
+{
+	*dpb_sz = inst->vsi->dec.dpb_sz;
+	mtk_vcodec_debug(inst, "sz=%d", *dpb_sz);
+}
+
+static int vdec_h264_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_h264_inst *inst = NULL;
+	int err;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->ctx = ctx;
+
+	inst->vpu.id = IPI_VDEC_H264;
+	inst->vpu.dev = ctx->dev->vpu_plat_dev;
+	inst->vpu.ctx = ctx;
+	inst->vpu.handler = vpu_dec_ipi_handler;
+
+	err = vpu_dec_init(&inst->vpu);
+	if (err) {
+		mtk_vcodec_err(inst, "vdec_h264 init err=%d", err);
+		goto error_free_inst;
+	}
+
+	inst->vsi = (struct vdec_h264_vsi *)inst->vpu.vsi;
+	err = allocate_predication_buf(inst);
+	if (err)
+		goto error_deinit;
+
+	mtk_vcodec_debug(inst, "H264 Instance >> %p", inst);
+
+	*h_vdec = (unsigned long)inst;
+	return 0;
+
+error_deinit:
+	vpu_dec_deinit(&inst->vpu);
+
+error_free_inst:
+	kfree(inst);
+	return err;
+}
+
+static int vdec_h264_deinit(unsigned long h_vdec)
+{
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+
+	mtk_vcodec_debug_enter(inst);
+
+	vpu_dec_deinit(&inst->vpu);
+	free_predication_buf(inst);
+	free_mv_buf(inst);
+
+	kfree(inst);
+	return 0;
+}
+
+static int find_start_code(unsigned char *data, unsigned int data_sz)
+{
+	if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1)
+		return 3;
+
+	if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 &&
+	    data[3] == 1)
+		return 4;
+
+	return -1;
+}
+
+static int vdec_h264_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+			    struct vdec_fb *fb, bool *res_chg)
+{
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+	struct vdec_vpu_inst *vpu = &inst->vpu;
+	int nal_start_idx = 0;
+	int err = 0;
+	unsigned int nal_start;
+	unsigned int nal_type;
+	unsigned char *buf;
+	unsigned int buf_sz;
+	unsigned int data[2];
+	uint64_t vdec_fb_va = (u64)fb;
+	uint64_t y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
+	uint64_t c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
+
+	mtk_vcodec_debug(inst, "+ [%d] FB y_dma=%llx c_dma=%llx va=%p",
+			 ++inst->num_nalu, y_fb_dma, c_fb_dma, fb);
+
+	/* bs NULL means flush decoder */
+	if (bs == NULL)
+		return vpu_dec_reset(vpu);
+
+	buf = (unsigned char *)bs->va;
+	buf_sz = bs->size;
+	nal_start_idx = find_start_code(buf, buf_sz);
+	if (nal_start_idx < 0)
+		goto err_free_fb_out;
+
+	nal_start = buf[nal_start_idx];
+	nal_type = NAL_TYPE(buf[nal_start_idx]);
+	mtk_vcodec_debug(inst, "\n + NALU[%d] type %d +\n", inst->num_nalu,
+			 nal_type);
+
+	if (nal_type == NAL_H264_PPS) {
+		buf_sz -= nal_start_idx;
+		if (buf_sz > HDR_PARSING_BUF_SZ) {
+			err = -EILSEQ;
+			goto err_free_fb_out;
+		}
+		memcpy(inst->vsi->hdr_buf, buf + nal_start_idx, buf_sz);
+	}
+
+	inst->vsi->dec.bs_dma = (uint64_t)bs->dma_addr;
+	inst->vsi->dec.y_fb_dma = y_fb_dma;
+	inst->vsi->dec.c_fb_dma = c_fb_dma;
+	inst->vsi->dec.vdec_fb_va = vdec_fb_va;
+
+	data[0] = buf_sz;
+	data[1] = nal_start;
+	err = vpu_dec_start(vpu, data, 2);
+	if (err)
+		goto err_free_fb_out;
+
+	*res_chg = inst->vsi->dec.resolution_changed;
+	if (*res_chg) {
+		struct vdec_pic_info pic;
+
+		mtk_vcodec_debug(inst, "- resolution changed -");
+		get_pic_info(inst, &pic);
+
+		if (inst->vsi->dec.realloc_mv_buf) {
+			err = alloc_mv_buf(inst, &pic);
+			if (err)
+				goto err_free_fb_out;
+		}
+	}
+
+	if (nal_type == NAL_NON_IDR_SLICE || nal_type == NAL_IDR_SLICE) {
+		/* wait decoder done interrupt */
+		err = mtk_vcodec_wait_for_done_ctx(inst->ctx,
+						   MTK_INST_IRQ_RECEIVED,
+						   WAIT_INTR_TIMEOUT_MS);
+		if (err)
+			goto err_free_fb_out;
+
+		vpu_dec_end(vpu);
+	}
+
+	mtk_vcodec_debug(inst, "\n - NALU[%d] type=%d -\n", inst->num_nalu,
+			 nal_type);
+	return 0;
+
+err_free_fb_out:
+	put_fb_to_free(inst, fb);
+	mtk_vcodec_err(inst, "\n - NALU[%d] err=%d -\n", inst->num_nalu, err);
+	return err;
+}
+
+static void vdec_h264_get_fb(struct vdec_h264_inst *inst,
+			     struct h264_ring_fb_list *list,
+			     bool disp_list, struct vdec_fb **out_fb)
+{
+	struct vdec_fb *fb;
+
+	if (check_list_validity(inst, disp_list))
+		return;
+
+	if (list->count == 0) {
+		mtk_vcodec_debug(inst, "[FB] there is no %s fb",
+				 disp_list ? "disp" : "free");
+		*out_fb = NULL;
+		return;
+	}
+
+	fb = (struct vdec_fb *)list->fb_list[list->read_idx].vdec_fb_va;
+	fb->status |= (disp_list ? FB_ST_DISPLAY : FB_ST_FREE);
+
+	*out_fb = fb;
+	mtk_vcodec_debug(inst, "[FB] get %s fb st=%d poc=%d %llx",
+			 disp_list ? "disp" : "free",
+			 fb->status, list->fb_list[list->read_idx].poc,
+			 list->fb_list[list->read_idx].vdec_fb_va);
+
+	list->read_idx = (list->read_idx == H264_MAX_FB_NUM - 1) ?
+			 0 : list->read_idx + 1;
+	list->count--;
+}
+
+static int vdec_h264_get_param(unsigned long h_vdec,
+			       enum vdec_get_param_type type, void *out)
+{
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+
+	switch (type) {
+	case GET_PARAM_DISP_FRAME_BUFFER:
+		vdec_h264_get_fb(inst, &inst->vsi->list_disp, true, out);
+		break;
+
+	case GET_PARAM_FREE_FRAME_BUFFER:
+		vdec_h264_get_fb(inst, &inst->vsi->list_free, false, out);
+		break;
+
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		get_dpb_size(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+
+	default:
+		mtk_vcodec_err(inst, "invalid get parameter type=%d", type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct vdec_common_if vdec_h264_if = {
+	vdec_h264_init,
+	vdec_h264_decode,
+	vdec_h264_get_param,
+	vdec_h264_deinit,
+};
+
+struct vdec_common_if *get_h264_dec_comm_if(void);
+
+struct vdec_common_if *get_h264_dec_comm_if(void)
+{
+	return &vdec_h264_if;
+}
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
index 1d12719..576920c 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
@@ -24,12 +24,16 @@
 #include "mtk_vcodec_util.h"
 #include "mtk_vpu.h"
 
+struct vdec_common_if *get_h264_dec_comm_if(void);
+
 int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 {
 	int ret = 0;
 
 	switch (fourcc) {
 	case V4L2_PIX_FMT_H264:
+		ctx->dec_if = get_h264_dec_comm_if();
+		break;
 	case V4L2_PIX_FMT_VP8:
 	case V4L2_PIX_FMT_VP9:
 	default:
diff --git a/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
new file mode 100644
index 0000000..0798a6b
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_util.h"
+#include "vdec_ipi_msg.h"
+#include "vdec_vpu_if.h"
+
+static void handle_init_ack_msg(struct vdec_vpu_ipi_init_ack *msg)
+{
+	struct vdec_vpu_inst *vpu = (struct vdec_vpu_inst *)msg->ap_inst_addr;
+
+	mtk_vcodec_debug(vpu, "+ ap_inst_addr = 0x%llx", msg->ap_inst_addr);
+
+	/* mapping VPU address to kernel virtual address */
+	/* the content in vsi is initialized to 0 in VPU */
+	vpu->vsi = vpu_mapping_dm_addr(vpu->dev, msg->vpu_inst_addr);
+	vpu->inst_addr = msg->vpu_inst_addr;
+
+	mtk_vcodec_debug(vpu, "- vpu_inst_addr = 0x%x", vpu->inst_addr);
+}
+
+/*
+ * This function runs in interrupt context and it means there's an IPI MSG
+ * from VPU.
+ */
+void vpu_dec_ipi_handler(void *data, unsigned int len, void *priv)
+{
+	struct vdec_vpu_ipi_ack *msg = data;
+	struct vdec_vpu_inst *vpu = (struct vdec_vpu_inst *)msg->ap_inst_addr;
+
+	mtk_vcodec_debug(vpu, "+ id=%X", msg->msg_id);
+
+	if (msg->status == 0) {
+		switch (msg->msg_id) {
+		case VPU_IPIMSG_DEC_INIT_ACK:
+			handle_init_ack_msg(data);
+			break;
+
+		case VPU_IPIMSG_DEC_START_ACK:
+		case VPU_IPIMSG_DEC_END_ACK:
+		case VPU_IPIMSG_DEC_DEINIT_ACK:
+		case VPU_IPIMSG_DEC_RESET_ACK:
+			break;
+
+		default:
+			mtk_vcodec_err(vpu, "invalid msg=%X", msg->msg_id);
+			break;
+		}
+	}
+
+	mtk_vcodec_debug(vpu, "- id=%X", msg->msg_id);
+	vpu->failure = msg->status;
+	vpu->signaled = 1;
+}
+
+static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, void *msg, int len)
+{
+	int err;
+	uint32_t msg_id = *(uint32_t *)msg;
+
+	mtk_vcodec_debug(vpu, "id=%X", msg_id);
+
+	vpu->failure = 0;
+	vpu->signaled = 0;
+
+	err = vpu_ipi_send(vpu->dev, vpu->id, msg, len);
+	if (err) {
+		mtk_vcodec_err(vpu, "send fail vpu_id=%d msg_id=%X status=%d",
+			       vpu->id, msg_id, err);
+		return err;
+	}
+
+	return vpu->failure;
+}
+
+static int vcodec_send_ap_ipi(struct vdec_vpu_inst *vpu, unsigned int msg_id)
+{
+	struct vdec_ap_ipi_cmd msg;
+	int err = 0;
+
+	mtk_vcodec_debug(vpu, "+ id=%X", msg_id);
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_id = msg_id;
+	msg.vpu_inst_addr = vpu->inst_addr;
+
+	err = vcodec_vpu_send_msg(vpu, &msg, sizeof(msg));
+	mtk_vcodec_debug(vpu, "- id=%X ret=%d", msg_id, err);
+	return err;
+}
+
+int vpu_dec_init(struct vdec_vpu_inst *vpu)
+{
+	struct vdec_ap_ipi_init msg;
+	int err;
+
+	mtk_vcodec_debug_enter(vpu);
+
+	init_waitqueue_head(&vpu->wq);
+
+	err = vpu_ipi_register(vpu->dev, vpu->id, vpu->handler, "vdec", NULL);
+	if (err != 0) {
+		mtk_vcodec_err(vpu, "vpu_ipi_register fail status=%d", err);
+		return err;
+	}
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_id = AP_IPIMSG_DEC_INIT;
+	msg.ap_inst_addr = (unsigned long)vpu;
+
+	mtk_vcodec_debug(vpu, "vdec_inst=%p", vpu);
+
+	err = vcodec_vpu_send_msg(vpu, (void *)&msg, sizeof(msg));
+	mtk_vcodec_debug(vpu, "- ret=%d", err);
+	return err;
+}
+
+int vpu_dec_start(struct vdec_vpu_inst *vpu, uint32_t *data, unsigned int len)
+{
+	struct vdec_ap_ipi_dec_start msg;
+	int i;
+	int err = 0;
+
+	mtk_vcodec_debug_enter(vpu);
+
+	if (len > ARRAY_SIZE(msg.data)) {
+		mtk_vcodec_err(vpu, "invalid len = %d\n", len);
+		return -EINVAL;
+	}
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_id = AP_IPIMSG_DEC_START;
+	msg.vpu_inst_addr = vpu->inst_addr;
+
+	for (i = 0; i < len; i++)
+		msg.data[i] = data[i];
+
+	err = vcodec_vpu_send_msg(vpu, (void *)&msg, sizeof(msg));
+	mtk_vcodec_debug(vpu, "- ret=%d", err);
+	return err;
+}
+
+int vpu_dec_end(struct vdec_vpu_inst *vpu)
+{
+	return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_END);
+}
+
+int vpu_dec_deinit(struct vdec_vpu_inst *vpu)
+{
+	return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_DEINIT);
+}
+
+int vpu_dec_reset(struct vdec_vpu_inst *vpu)
+{
+	return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_RESET);
+}
diff --git a/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h
new file mode 100644
index 0000000..8dcc1cb
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VDEC_VPU_IF_H_
+#define _VDEC_VPU_IF_H_
+
+#include "mtk_vpu.h"
+
+/**
+ * struct vdec_vpu_inst - VPU instance for video codec
+ * @ipi_id      : ipi id for each decoder
+ * @vsi         : driver structure allocated by VPU side and shared to AP side
+ *                for control and info share
+ * @failure     : VPU execution result status, 0: success, others: fail
+ * @inst_addr	: VPU decoder instance address
+ * @signaled    : 1 - Host has received ack message from VPU, 0 - not received
+ * @ctx         : context for v4l2 layer integration
+ * @dev	        : platform device of VPU
+ * @wq          : wait queue to wait VPU message ack
+ * @handler     : ipi handler for each decoder
+ */
+struct vdec_vpu_inst {
+	enum ipi_id id;
+	void *vsi;
+	int32_t failure;
+	uint32_t inst_addr;
+	unsigned int signaled;
+	struct mtk_vcodec_ctx *ctx;
+	struct platform_device *dev;
+	wait_queue_head_t wq;
+	ipi_handler_t handler;
+};
+
+/**
+ * vpu_dec_init - init decoder instance and allocate required resource in VPU.
+ *
+ * @vpu: instance for vdec_vpu_inst
+ */
+int vpu_dec_init(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_start - start decoding, basically the function will be invoked once
+ *                 every frame.
+ *
+ * @vpu : instance for vdec_vpu_inst
+ * @data: meta data to pass bitstream info to VPU decoder
+ * @len : meta data length
+ */
+int vpu_dec_start(struct vdec_vpu_inst *vpu, uint32_t *data, unsigned int len);
+
+/**
+ * vpu_dec_end - end decoding, basically the function will be invoked once
+ *               when HW decoding done interrupt received successfully. The
+ *               decoder in VPU will continute to do referene frame management
+ *               and check if there is a new decoded frame available to display.
+ *
+ * @vpu : instance for vdec_vpu_inst
+ */
+int vpu_dec_end(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_deinit - deinit decoder instance and resource freed in VPU.
+ *
+ * @vpu: instance for vdec_vpu_inst
+ */
+int vpu_dec_deinit(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_reset - reset decoder, use for flush decoder when end of stream or
+ *                 seek. Remainig non displayed frame will be pushed to display.
+ *
+ * @vpu: instance for vdec_vpu_inst
+ */
+int vpu_dec_reset(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_ipi_handler - Handler for VPU ipi message.
+ *
+ * @data: ipi message
+ * @len : length of ipi message
+ * @priv: callback private data whcih is passed by decoder when register.
+ */
+void vpu_dec_ipi_handler(void *data, unsigned int len, void *priv);
+
+#endif
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Thu May 12 04:24:09 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Thu, 12 May 2016 19:24:09 +0800
Subject: [PATCH v2 8/9] [media] vcodec: mediatek: Add Mediatek VP9 Video
 Decoder Driver
In-Reply-To: <1463052250-38262-8-git-send-email-tiffany.lin@mediatek.com>
References: <1463052250-38262-1-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-2-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-3-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-4-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-5-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-6-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-7-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-8-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1463052250-38262-9-git-send-email-tiffany.lin@mediatek.com>

Add vp9 decoder driver for MT8173

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 drivers/media/platform/mtk-vcodec/Makefile         |    1 +
 .../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c   |  947 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/vdec_drv_if.c    |    3 +
 3 files changed, 951 insertions(+)
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c

diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
index 7743c81..852d969 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
 
 mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
 		vdec/vdec_vp8_if.o \
+		vdec/vdec_vp9_if.o \
 		mtk_vcodec_dec_drv.o \
 		vdec_drv_if.o \
 		vdec_vpu_if.o \
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
new file mode 100644
index 0000000..d2b36fd
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
@@ -0,0 +1,947 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Daniel Hsiao <daniel.hsiao at mediatek.com>
+ *		Kai-Sean Yang <kai-sean.yang at mediatek.com>
+ *		Tiffany Lin <tiffany.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+
+#include "../mtk_vcodec_intr.h"
+#include "../vdec_drv_base.h"
+#include "../vdec_vpu_if.h"
+
+#define VP9_SUPER_FRAME_BS_SZ 64
+#define MAX_VP9_DPB_SIZE	9
+
+#define REFS_PER_FRAME 3
+#define MAX_NUM_REF_FRAMES 8
+#define VP9_MAX_FRM_BUF_NUM 9
+#define VP9_MAX_FRM_BUF_NODE_NUM (VP9_MAX_FRM_BUF_NUM * 2)
+#define MAX_CODED_WIDTH		4096U
+#define MAX_CODED_HEIGHT	2304U
+
+
+struct vdec_vp9_frm_hdr {
+	unsigned int width;
+	unsigned int height;
+	unsigned char show_frame;
+};
+
+struct vdec_vp9_work_buf {
+	unsigned int buf_w;
+	unsigned int buf_h;
+	struct mtk_vcodec_mem mv_buf;
+};
+
+struct vp9_input_ctx {
+	unsigned long v_fifo_sa;
+	unsigned long v_fifo_ea;
+	unsigned long p_fifo_sa;
+	unsigned long p_fifo_ea;
+	unsigned long v_frm_sa;
+	unsigned long v_frm_ea;
+	unsigned long p_frm_sa;
+	unsigned long p_frm_end;
+	unsigned int frm_sz;
+	unsigned int uncompress_sz;
+};
+
+struct vp9_dram_buf {
+	unsigned long va;
+	unsigned long pa;
+	unsigned int sz;
+	unsigned int vpua;
+};
+
+struct vp9_fb_info {
+	struct vdec_fb *fb;
+	struct vp9_dram_buf y_buf;
+	struct vp9_dram_buf c_buf;
+	struct vp9_dram_buf ufo_len_y;
+	struct vp9_dram_buf ufo_len_c;
+	unsigned int y_width;
+	unsigned int y_height;
+	unsigned int y_crop_width;
+	unsigned int y_crop_height;
+
+	unsigned int c_width;
+	unsigned int c_height;
+	unsigned int c_crop_width;
+	unsigned int c_crop_height;
+
+	unsigned int frm_num;
+};
+
+struct vp9_ref_cnt_buf {
+	struct vp9_fb_info buf;
+	unsigned int ref_cnt;
+};
+
+struct vp9_scale_factors {
+	int x_scale_fp;
+	int y_scale_fp;
+	int x_step_q4;
+	int y_step_q4;
+	unsigned int ref_scaling_en;
+};
+
+struct vp9_ref_buf {
+	struct vp9_fb_info *buf;
+	struct vp9_scale_factors scale_factors;
+	unsigned int idx;
+};
+
+struct vp9_sf_ref_fb {
+	struct vdec_fb fb;
+	int used;
+	int idx;
+};
+
+/*
+ * struct vdec_vp9_vsi - shared buffer between host and VPU firmware
+ */
+struct vdec_vp9_vsi {
+	unsigned char sf_bs_buf[VP9_SUPER_FRAME_BS_SZ];
+	struct vp9_sf_ref_fb sf_ref_fb[VP9_MAX_FRM_BUF_NUM-1];
+	int sf_next_ref_fb_idx;
+	unsigned int sf_frm_cnt;
+	unsigned int sf_frm_offset[VP9_MAX_FRM_BUF_NUM-1];
+	unsigned int sf_frm_sz[VP9_MAX_FRM_BUF_NUM-1];
+	unsigned int sf_frm_idx;
+	unsigned int sf_init;
+	struct vdec_fb fb;
+	struct mtk_vcodec_mem bs;
+	struct vdec_fb cur_fb;
+	unsigned int pic_w;
+	unsigned int pic_h;
+	unsigned int buf_w;
+	unsigned int buf_h;
+	unsigned int buf_sz_y_bs;
+	unsigned int buf_sz_c_bs;
+	unsigned int buf_len_sz_y;
+	unsigned int buf_len_sz_c;
+	unsigned int profile;
+	unsigned int show_frame;
+	unsigned int show_existing_frame;
+	unsigned int frm_to_show;
+	unsigned int refresh_frm_flags;
+	unsigned int resolution_changed;
+
+	struct vp9_input_ctx input_ctx;
+	struct vp9_ref_cnt_buf frm_bufs[VP9_MAX_FRM_BUF_NUM];
+	int ref_frm_map[MAX_NUM_REF_FRAMES];
+
+	unsigned int new_fb_idx;
+	unsigned int frm_num;
+
+	struct vp9_dram_buf seg_id_buf;
+	struct vp9_dram_buf tile_buf;
+	struct vp9_dram_buf count_tbl_buf;
+	struct vp9_dram_buf prob_tbl_buf;
+	struct vp9_dram_buf mv_buf;
+	struct vp9_ref_buf frm_refs[REFS_PER_FRAME];
+};
+
+struct vdec_vp9_inst {
+	struct vdec_vp9_work_buf work_buf;
+	struct vdec_vp9_frm_hdr frm_hdr;
+	struct vdec_fb_node dec_fb[VP9_MAX_FRM_BUF_NODE_NUM];
+	struct list_head available_fb_node_list;
+	struct list_head fb_use_list;
+	struct list_head fb_free_list;
+	struct list_head fb_disp_list;
+	struct vdec_fb *cur_fb;
+	unsigned int frm_cnt;
+	unsigned int total_frm_cnt;
+	void *ctx;
+	struct vdec_vpu_inst vpu;
+	struct vdec_vp9_vsi *vsi;
+	unsigned int show_reg;
+	struct mtk_vcodec_mem mem;
+};
+
+static bool vp9_is_sf_ref_fb(struct vdec_vp9_inst *inst, struct vdec_fb *fb)
+{
+	int i;
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+
+	for (i = 0; i < ARRAY_SIZE(vsi->sf_ref_fb); i++) {
+		if (fb == &vsi->sf_ref_fb[i].fb)
+			return true;
+	}
+	return false;
+}
+
+static struct vdec_fb *vp9_rm_from_fb_use_list(struct vdec_vp9_inst
+					*inst, void *addr)
+{
+	struct vdec_fb *fb = NULL;
+	struct vdec_fb_node *node;
+
+	list_for_each_entry(node, &inst->fb_use_list, list) {
+		fb = (struct vdec_fb *)node->fb;
+		if (fb->base_y.va == addr) {
+			list_move_tail(&node->list,
+				       &inst->available_fb_node_list);
+			break;
+		}
+	}
+	return fb;
+}
+
+static void vp9_add_to_fb_free_list(struct vdec_vp9_inst *inst,
+			     struct vdec_fb *fb)
+{
+	struct vdec_fb_node *node;
+
+	if (fb) {
+		node = list_first_entry_or_null(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+
+		if (node) {
+			node->fb = fb;
+			list_move_tail(&node->list, &inst->fb_free_list);
+		}
+	} else {
+		mtk_vcodec_debug(inst, "No free fb node");
+	}
+}
+
+static void vp9_free_sf_ref_fb(struct vdec_fb *fb)
+{
+	struct vp9_sf_ref_fb *sf_ref_fb =
+		container_of(fb, struct vp9_sf_ref_fb, fb);
+
+	sf_ref_fb->used = 0;
+}
+
+static void vp9_ref_cnt_fb(struct vdec_vp9_inst *inst, int *idx,
+			   int new_idx)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	int ref_idx = *idx;
+
+	if (ref_idx >= 0 && vsi->frm_bufs[ref_idx].ref_cnt > 0) {
+		vsi->frm_bufs[ref_idx].ref_cnt--;
+
+		if (vsi->frm_bufs[ref_idx].ref_cnt == 0) {
+			if (!vp9_is_sf_ref_fb(inst,
+					      vsi->frm_bufs[ref_idx].buf.fb)) {
+				struct vdec_fb *fb;
+
+				fb = vp9_rm_from_fb_use_list(inst,
+				     vsi->frm_bufs[ref_idx].buf.fb->base_y.va);
+				vp9_add_to_fb_free_list(inst, fb);
+			} else
+				vp9_free_sf_ref_fb(vsi->frm_bufs[ref_idx].buf.fb);
+		}
+	}
+
+	*idx = new_idx;
+	vsi->frm_bufs[new_idx].ref_cnt++;
+}
+
+static void vp9_free_all_sf_ref_fb(struct vdec_vp9_inst *inst)
+{
+	int i;
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+
+	for (i = 0; i < ARRAY_SIZE(vsi->sf_ref_fb); i++) {
+		if (vsi->sf_ref_fb[i].fb.base_y.va) {
+			mtk_vcodec_mem_free(inst->ctx,
+				&vsi->sf_ref_fb[i].fb.base_y);
+			mtk_vcodec_mem_free(inst->ctx,
+				&vsi->sf_ref_fb[i].fb.base_c);
+			vsi->sf_ref_fb[i].used = 0;
+		}
+	}
+}
+
+/* For each sub-frame except the last one, the driver will dynamically
+ * allocate reference buffer by calling vp9_get_sf_ref_fb()
+ * The last sub-frame will use the original fb provided by the
+ * vp9_dec_decode() interface
+ */
+static int vp9_get_sf_ref_fb(struct vdec_vp9_inst *inst)
+{
+	int idx;
+	struct mtk_vcodec_mem *mem_basy_y;
+	struct mtk_vcodec_mem *mem_basy_c;
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+
+	if ((inst->frm_hdr.width > MAX_CODED_WIDTH) ||
+		(inst->frm_hdr.height > MAX_CODED_HEIGHT)) {
+		mtk_vcodec_err(inst, "Invalid w/h %d/%d",
+									inst->frm_hdr.width,
+									inst->frm_hdr.height);
+		return -1;
+	}
+
+	for (idx = 0;
+			idx < ARRAY_SIZE(vsi->sf_ref_fb);
+			idx++) {
+		if (vsi->sf_ref_fb[idx].fb.base_y.va &&
+		    vsi->sf_ref_fb[idx].used == 0) {
+			return idx;
+		}
+	}
+
+	for (idx = 0;
+			idx < ARRAY_SIZE(vsi->sf_ref_fb);
+			idx++) {
+		if (vsi->sf_ref_fb[idx].fb.base_y.va == NULL)
+			break;
+	}
+
+	if (idx == ARRAY_SIZE(vsi->sf_ref_fb)) {
+		mtk_vcodec_err(inst, "List Full");
+		return -1;
+	}
+
+	mem_basy_y = &vsi->sf_ref_fb[idx].fb.base_y;
+	mem_basy_y->size = vsi->buf_sz_y_bs +
+		    vsi->buf_len_sz_y;
+
+	if (mtk_vcodec_mem_alloc(inst->ctx, mem_basy_y)) {
+		mtk_vcodec_err(inst, "Cannot allocate sf_ref_buf y_buf");
+		return -1;
+	}
+
+	mem_basy_c = &vsi->sf_ref_fb[idx].fb.base_c;
+	mem_basy_c->size = vsi->buf_sz_c_bs +
+		    vsi->buf_len_sz_c;
+
+	if (mtk_vcodec_mem_alloc(inst->ctx, mem_basy_c)) {
+		mtk_vcodec_err(inst, "Cannot allocate sf_ref_fb c_buf");
+		return -1;
+	}
+	vsi->sf_ref_fb[idx].used = 0;
+	vsi->sf_ref_fb[idx].idx = idx;
+
+	return idx;
+}
+
+static bool vp9_alloc_work_buf(struct vdec_vp9_inst *inst)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	int result;
+	struct mtk_vcodec_mem *mem;
+
+	if ((vsi->pic_w > MAX_CODED_WIDTH) ||
+			(vsi->pic_h > MAX_CODED_HEIGHT)) {
+		mtk_vcodec_err(inst, "Invalid w/h %d/%d",
+									inst->frm_hdr.width,
+									inst->frm_hdr.height);
+		return false;
+	}
+
+	inst->frm_hdr.width = vsi->pic_w;
+	inst->frm_hdr.height = vsi->pic_h;
+	inst->work_buf.buf_w = vsi->buf_w;
+	inst->work_buf.buf_h = vsi->buf_h;
+
+	mtk_vcodec_debug(inst, "BUF CHG(%d): w/h/sb_w/sb_h=%d/%d/%d/%d",
+		     vsi->resolution_changed,
+		     inst->frm_hdr.width,
+		     inst->frm_hdr.height,
+		     inst->work_buf.buf_w,
+		     inst->work_buf.buf_h);
+
+	mem = &inst->work_buf.mv_buf;
+
+	if (mem->va)
+		mtk_vcodec_mem_free(inst->ctx, mem);
+
+	mem->size = ((inst->work_buf.buf_w / 64) *
+		    (inst->work_buf.buf_h / 64) + 2) * 36 * 16;
+
+	result = mtk_vcodec_mem_alloc(inst->ctx, mem);
+	if (result) {
+		mem->size = 0;
+		mtk_vcodec_err(inst, "Cannot allocate mv_buf");
+		return false;
+	}
+	/* Set the va again */
+	vsi->mv_buf.va = (unsigned long)mem->va;
+	vsi->mv_buf.pa = (unsigned long)mem->dma_addr;
+	vsi->mv_buf.sz = (unsigned int)mem->size;
+
+	vp9_free_all_sf_ref_fb(inst);
+	vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
+
+	return true;
+}
+
+static bool vp9_add_to_fb_disp_list(struct vdec_vp9_inst *inst,
+			     struct vdec_fb *fb)
+{
+	struct vdec_fb_node *node;
+
+	if (!fb) {
+		mtk_vcodec_err(inst, "fb == NULL");
+		return false;
+	}
+
+	node = list_first_entry_or_null(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		node->fb = fb;
+		list_move_tail(&node->list, &inst->fb_disp_list);
+	} else {
+		mtk_vcodec_err(inst, "No available fb node");
+		return false;
+	}
+
+	return true;
+}
+
+/* If any buffer updating is signaled it should be done here. */
+static void vp9_swap_frm_bufs(struct vdec_vp9_inst *inst)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	struct vp9_fb_info *frm_to_show;
+	int ref_index = 0, mask;
+
+	for (mask = vsi->refresh_frm_flags; mask; mask >>= 1) {
+		if (mask & 1)
+			vp9_ref_cnt_fb(inst, &vsi->ref_frm_map[ref_index],
+				       vsi->new_fb_idx);
+		++ref_index;
+	}
+
+	frm_to_show = &vsi->frm_bufs[vsi->new_fb_idx].buf;
+	vsi->frm_bufs[vsi->new_fb_idx].ref_cnt--;
+
+	if (frm_to_show->fb != inst->cur_fb) {
+		/* This frame is show exist frame and no decode output
+		  * copy frame data from frm_to_show to current CAPTURE
+		  * buffer
+		  */
+		if ((frm_to_show->fb != NULL) &&
+				(inst->cur_fb->base_y.size >=
+				frm_to_show->fb->base_y.size)) {
+			memcpy((void *)inst->cur_fb->base_y.va,
+					(void *)frm_to_show->fb->base_y.va,
+					inst->work_buf.buf_w *
+					inst->work_buf.buf_h);
+			memcpy((void *)inst->cur_fb->base_c.va,
+					(void *)frm_to_show->fb->base_c.va,
+					inst->work_buf.buf_w *
+					inst->work_buf.buf_h / 2);
+		} else {
+			/* After resolution change case, current CAPTURE buffer
+			  * may have less buffer size than frm_to_show buffer
+			  * size
+			  */
+			if (frm_to_show->fb != NULL)
+				mtk_vcodec_err(inst,
+					"inst->cur_fb->base_y.size=%lx, frm_to_show->fb.base_y.size=%lx",
+					inst->cur_fb->base_y.size,
+					frm_to_show->fb->base_y.size);
+		}
+		if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) {
+			if (inst->frm_hdr.show_frame)
+				vp9_add_to_fb_disp_list(inst, inst->cur_fb);
+		}
+	} else {
+		if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) {
+			if (inst->frm_hdr.show_frame)
+				vp9_add_to_fb_disp_list(inst, frm_to_show->fb);
+		}
+	}
+
+	/* when ref_cnt ==0, move this fb to fb_free_list. v4l2 driver will
+	 * clean fb_free_list
+	 */
+	if (vsi->frm_bufs[vsi->new_fb_idx].ref_cnt == 0) {
+		if (!vp9_is_sf_ref_fb(
+			inst, vsi->frm_bufs[vsi->new_fb_idx].buf.fb)) {
+			struct vdec_fb *fb;
+
+			fb = vp9_rm_from_fb_use_list(inst,
+			     vsi->frm_bufs[vsi->new_fb_idx].buf.fb->base_y.va);
+
+			vp9_add_to_fb_free_list(inst, fb);
+		} else {
+			vp9_free_sf_ref_fb(vsi->frm_bufs[vsi->new_fb_idx].buf.fb);
+		}
+	}
+
+	/* if this super frame and it is not last sub-frame, get next fb for
+	 * sub-frame decode
+	 */
+	if (vsi->sf_frm_cnt > 0 && vsi->sf_frm_idx != vsi->sf_frm_cnt - 1)
+		vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
+}
+
+static bool vp9_wait_dec_end(struct vdec_vp9_inst *inst)
+{
+	struct mtk_vcodec_ctx *ctx = inst->ctx;
+
+	mtk_vcodec_wait_for_done_ctx(inst->ctx,
+						MTK_INST_IRQ_RECEIVED,
+						WAIT_INTR_TIMEOUT_MS);
+
+	if (ctx->irq_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
+		return true;
+	else
+		return false;
+}
+
+static struct vdec_vp9_inst *vp9_alloc_inst(struct mtk_vcodec_ctx *ctx)
+{
+	int result;
+	struct mtk_vcodec_mem mem;
+	struct vdec_vp9_inst *inst;
+
+	memset(&mem, 0, sizeof(mem));
+	mem.size = sizeof(struct vdec_vp9_inst);
+	result = mtk_vcodec_mem_alloc(ctx, &mem);
+	if (result)
+		return NULL;
+
+	inst = mem.va;
+	inst->mem = mem;
+
+	return inst;
+}
+
+static void vp9_free_inst(struct vdec_vp9_inst *inst)
+{
+	struct mtk_vcodec_mem mem;
+
+	mem = inst->mem;
+	if (mem.va)
+		mtk_vcodec_mem_free(inst->ctx, &mem);
+}
+
+static bool vp9_decode_end_proc(struct vdec_vp9_inst *inst)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	bool ret = false;
+
+	if (!vsi->show_existing_frame) {
+		ret = vp9_wait_dec_end(inst);
+		if (!ret) {
+			mtk_vcodec_err(inst, "Decode failed, Decode Timeout @[%d]",
+					   vsi->frm_num);
+			return false;
+		}
+
+		if (vpu_dec_end(&inst->vpu)) {
+			mtk_vcodec_err(inst, "vp9_dec_vpu_end failed");
+			return false;
+		}
+		mtk_vcodec_debug(inst, "Decode Ok @%d (%d/%d)", vsi->frm_num,
+					inst->frm_hdr.width, inst->frm_hdr.height);
+	} else {
+		mtk_vcodec_debug(inst, "Decode Ok @%d (show_existing_frame)",
+					vsi->frm_num);
+	}
+
+	vp9_swap_frm_bufs(inst);
+	vsi->frm_num++;
+	return true;
+}
+
+static bool vp9_is_last_sub_frm(struct vdec_vp9_inst *inst)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+
+	if (vsi->sf_frm_cnt <= 0 || vsi->sf_frm_idx == vsi->sf_frm_cnt)
+		return true;
+
+	return false;
+}
+
+static struct vdec_fb *vp9_rm_from_fb_disp_list(struct vdec_vp9_inst *inst)
+{
+	struct vdec_fb_node *node;
+	struct vdec_fb *fb = NULL;
+
+	node = list_first_entry_or_null(&inst->fb_disp_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		fb = (struct vdec_fb *)node->fb;
+		fb->status |= FB_ST_DISPLAY;
+		list_move_tail(&node->list, &inst->available_fb_node_list);
+		mtk_vcodec_debug(inst, "[FB] get disp fb %p st=%d",
+				 node->fb, fb->status);
+	} else
+		mtk_vcodec_debug(inst, "[FB] there is no disp fb");
+
+	return fb;
+}
+
+static bool vp9_add_to_fb_use_list(struct vdec_vp9_inst *inst,
+			    struct vdec_fb *fb)
+{
+	struct vdec_fb_node *node;
+
+	if (!fb) {
+		mtk_vcodec_err(inst, "fb == NULL");
+		return false;
+	}
+
+	node = list_first_entry_or_null(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		node->fb = fb;
+		list_move_tail(&node->list, &inst->fb_use_list);
+	} else {
+		mtk_vcodec_err(inst, "No free fb node");
+		return false;
+	}
+	return true;
+}
+
+static void vp9_reset(struct vdec_vp9_inst *inst)
+{
+	struct vdec_fb_node *node, *tmp;
+
+	list_for_each_entry_safe(node, tmp, &inst->fb_use_list, list)
+		list_move_tail(&node->list, &inst->fb_free_list);
+
+	vp9_free_all_sf_ref_fb(inst);
+	inst->vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
+
+	if (vpu_dec_reset(&inst->vpu))
+		mtk_vcodec_err(inst, "vp9_dec_vpu_reset failed");
+
+	/* Set the va again, since vpu_dec_reset will clear mv_buf in vpu */
+	inst->vsi->mv_buf.va = (unsigned long)inst->work_buf.mv_buf.va;
+	inst->vsi->mv_buf.pa = (unsigned long)inst->work_buf.mv_buf.dma_addr;
+	inst->vsi->mv_buf.sz = (unsigned long)inst->work_buf.mv_buf.size;
+}
+
+static void init_all_fb_lists(struct vdec_vp9_inst *inst)
+{
+	int i;
+
+	INIT_LIST_HEAD(&inst->available_fb_node_list);
+	INIT_LIST_HEAD(&inst->fb_use_list);
+	INIT_LIST_HEAD(&inst->fb_free_list);
+	INIT_LIST_HEAD(&inst->fb_disp_list);
+
+	for (i = 0; i < ARRAY_SIZE(inst->dec_fb); i++) {
+		INIT_LIST_HEAD(&inst->dec_fb[i].list);
+		inst->dec_fb[i].fb = NULL;
+		list_add_tail(&inst->dec_fb[i].list,
+			      &inst->available_fb_node_list);
+	}
+}
+
+static void get_pic_info(struct vdec_vp9_inst *inst, struct vdec_pic_info *pic)
+{
+	pic->y_bs_sz = inst->vsi->buf_sz_y_bs;
+	pic->c_bs_sz = inst->vsi->buf_sz_c_bs;
+	pic->y_len_sz = inst->vsi->buf_len_sz_y;
+	pic->c_len_sz = inst->vsi->buf_len_sz_c;
+
+	pic->pic_w = inst->frm_hdr.width;
+	pic->pic_h = inst->frm_hdr.height;
+	pic->buf_w = inst->work_buf.buf_w;
+	pic->buf_h = inst->work_buf.buf_h;
+
+	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
+		 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
+	mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+		 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_disp_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb)
+{
+
+	*out_fb = vp9_rm_from_fb_disp_list(inst);
+	if (*out_fb)
+		(*out_fb)->status |= FB_ST_DISPLAY;
+}
+
+static void get_free_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb)
+{
+	struct vdec_fb_node *node;
+	struct vdec_fb *fb = NULL;
+
+	node = list_first_entry_or_null(&inst->fb_free_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		list_move_tail(&node->list, &inst->available_fb_node_list);
+		fb = (struct vdec_fb *)node->fb;
+		fb->status |= FB_ST_FREE;
+		mtk_vcodec_debug(inst, "[FB] get free fb %p st=%d",
+				 node->fb, fb->status);
+	} else {
+		mtk_vcodec_debug(inst, "[FB] there is no free fb");
+	}
+
+	*out_fb = fb;
+}
+
+static int vdec_vp9_deinit(unsigned long h_vdec)
+{
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+	struct mtk_vcodec_mem *mem;
+	int ret = 0;
+
+	ret = vpu_dec_deinit(&inst->vpu);
+	if (ret)
+		mtk_vcodec_err(inst, "vpu_dec_deinit failed");
+
+	mem = &inst->work_buf.mv_buf;
+	if (mem->va)
+		mtk_vcodec_mem_free(inst->ctx, mem);
+
+	vp9_free_all_sf_ref_fb(inst);
+	vp9_free_inst(inst);
+
+	return ret;
+}
+
+static int vdec_vp9_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_vp9_inst *inst;
+
+	inst = vp9_alloc_inst(ctx);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->frm_cnt = 0;
+	inst->total_frm_cnt = 0;
+	inst->ctx = ctx;
+
+	inst->vpu.id = IPI_VDEC_VP9;
+	inst->vpu.dev = ctx->dev->vpu_plat_dev;
+	inst->vpu.ctx = ctx;
+	inst->vpu.handler = vpu_dec_ipi_handler;
+
+	if (vpu_dec_init(&inst->vpu)) {
+		mtk_vcodec_err(inst, "vp9_dec_vpu_init failed");
+		goto err_deinit_inst;
+	}
+
+	inst->vsi = (struct vdec_vp9_vsi *)inst->vpu.vsi;
+	init_all_fb_lists(inst);
+
+	(*h_vdec) = (unsigned long)inst;
+	return 0;
+
+err_deinit_inst:
+	vp9_free_inst(inst);
+
+	return -EINVAL;
+}
+
+static int vdec_vp9_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+		   struct vdec_fb *fb, bool *res_chg)
+{
+	int ret = 0;
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	u32 data[3];
+	int i;
+
+	*res_chg = false;
+
+	if ((bs == NULL) && (fb == NULL)) {
+		mtk_vcodec_debug(inst, "[EOS]");
+		vp9_reset(inst);
+		return ret;
+	}
+
+	if (bs == NULL) {
+		mtk_vcodec_err(inst, "bs == NULL");
+		return -EINVAL;;
+	}
+
+	mtk_vcodec_debug(inst, "Input BS Size = %ld", bs->size);
+
+	while (1) {
+		struct vdec_fb *cur_fb = NULL;
+
+		data[0] = *((unsigned int *)bs->va);
+		data[1] = *((unsigned int *)(bs->va + 4));
+		data[2] = *((unsigned int *)(bs->va + 8));
+
+		vsi->bs = *bs;
+
+		if (fb)
+			vsi->fb = *fb;
+
+		if (!vsi->sf_init) {
+			unsigned int sf_bs_sz;
+			unsigned int sf_bs_off;
+			unsigned char *sf_bs_src;
+			unsigned char *sf_bs_dst;
+
+			sf_bs_sz = bs->size > VP9_SUPER_FRAME_BS_SZ ?
+								VP9_SUPER_FRAME_BS_SZ : bs->size;
+			sf_bs_off = VP9_SUPER_FRAME_BS_SZ - sf_bs_sz;
+			sf_bs_src = bs->va + bs->size - sf_bs_sz;
+			sf_bs_dst = vsi->sf_bs_buf + sf_bs_off;
+			memcpy(sf_bs_dst, sf_bs_src, sf_bs_sz);
+		} else {
+			if ((vsi->sf_frm_cnt > 0) &&
+				(vsi->sf_frm_idx < vsi->sf_frm_cnt)) {
+				unsigned int idx = vsi->sf_frm_idx;
+
+				memcpy((void *)vsi->input_ctx.v_frm_sa,
+					   (void *)(vsi->input_ctx.v_frm_sa +
+					   vsi->sf_frm_offset[idx]),
+					   vsi->sf_frm_sz[idx]);
+			}
+		}
+		ret = vpu_dec_start(&inst->vpu, data, 3);
+		if (ret) {
+			mtk_vcodec_err(inst, "vpu_dec_start failed");
+			goto DECODE_ERROR;
+		}
+
+		if (vsi->resolution_changed) {
+			if (!vp9_alloc_work_buf(inst)) {
+				ret = -EINVAL;
+				goto DECODE_ERROR;
+			}
+		}
+
+		if (vsi->sf_frm_cnt > 0) {
+			cur_fb = &vsi->sf_ref_fb[vsi->sf_next_ref_fb_idx].fb;
+
+			if (vsi->sf_frm_idx < vsi->sf_frm_cnt)
+				inst->cur_fb = cur_fb;
+			else
+				inst->cur_fb = fb;
+		} else {
+			inst->cur_fb = fb;
+		}
+
+		vsi->frm_bufs[vsi->new_fb_idx].buf.fb = inst->cur_fb;
+		if (!vp9_is_sf_ref_fb(inst, inst->cur_fb))
+			vp9_add_to_fb_use_list(inst, inst->cur_fb);
+
+		mtk_vcodec_debug(inst, "[#pic %d]", vsi->frm_num);
+
+		/* the same as VP9_SKIP_FRAME */
+		inst->frm_hdr.show_frame = vsi->show_frame;
+
+		if (vsi->show_existing_frame)
+			mtk_vcodec_debug(inst,
+				"drv->new_fb_idx=%d, drv->frm_to_show=%d",
+				vsi->new_fb_idx, vsi->frm_to_show);
+
+		if (vsi->show_existing_frame && (vsi->frm_to_show <
+					VP9_MAX_FRM_BUF_NUM)) {
+			mtk_vcodec_err(inst,
+				"Skip Decode drv->new_fb_idx=%d, drv->frm_to_show=%d",
+				vsi->new_fb_idx, vsi->frm_to_show);
+
+			vp9_ref_cnt_fb(inst, &vsi->new_fb_idx,
+							vsi->frm_to_show);
+			ret = -EINVAL;
+			goto DECODE_ERROR;
+		}
+
+		/* VPU assign the buffer pointer in its address space,
+		 * reassign here
+		 */
+		for (i = 0; i < ARRAY_SIZE(vsi->frm_refs); i++) {
+			unsigned int idx = vsi->frm_refs[i].idx;
+
+			vsi->frm_refs[i].buf = &vsi->frm_bufs[idx].buf;
+		}
+
+		if (vsi->resolution_changed) {
+			*res_chg = true;
+			mtk_vcodec_err(inst, ".........VDEC_ST_RESOLUTION_CHANGED");
+
+			ret = 0;
+			goto DECODE_ERROR;
+		}
+
+		if (vp9_decode_end_proc(inst) != true) {
+			mtk_vcodec_err(inst, "vp9_decode_end_proc");
+			ret = -EINVAL;
+			goto DECODE_ERROR;
+		}
+
+		inst->total_frm_cnt++;
+		if (vp9_is_last_sub_frm(inst))
+			break;
+
+	}
+	inst->frm_cnt++;
+
+DECODE_ERROR:
+	if (ret < 0)
+		vp9_add_to_fb_free_list(inst, fb);
+
+	return ret;
+}
+
+static void get_crop_info(struct vdec_vp9_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = 0;
+	cr->top = 0;
+	cr->width = inst->frm_hdr.width;
+	cr->height = inst->frm_hdr.height;
+	mtk_vcodec_debug(inst, "get crop info l=%d, t=%d, w=%d, h=%d\n",
+			 cr->left, cr->top, cr->width, cr->height);
+}
+
+static int vdec_vp9_get_param(unsigned long h_vdec,
+			enum vdec_get_param_type type, void *out)
+{
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+	int ret = 0;
+
+	switch (type) {
+	case GET_PARAM_DISP_FRAME_BUFFER:
+		get_disp_fb(inst, out);
+		break;
+	case GET_PARAM_FREE_FRAME_BUFFER:
+		get_free_fb(inst, out);
+		break;
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+	case GET_PARAM_DPB_SIZE:
+		*((unsigned int *)out) = MAX_VP9_DPB_SIZE;
+		break;
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+	default:
+		mtk_vcodec_err(inst, "not supported param type %d", type);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static struct vdec_common_if vdec_vp9_if = {
+	vdec_vp9_init,
+	vdec_vp9_decode,
+	vdec_vp9_get_param,
+	vdec_vp9_deinit,
+};
+
+struct vdec_common_if *get_vp9_dec_comm_if(void);
+
+struct vdec_common_if *get_vp9_dec_comm_if(void)
+{
+	return &vdec_vp9_if;
+}
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
index 6e2f065..f5781d7 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
@@ -26,6 +26,7 @@
 
 struct vdec_common_if *get_h264_dec_comm_if(void);
 struct vdec_common_if *get_vp8_dec_comm_if(void);
+struct vdec_common_if *get_vp9_dec_comm_if(void);
 
 int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 {
@@ -39,6 +40,8 @@ int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 		ctx->dec_if = get_vp8_dec_comm_if();
 		break;
 	case V4L2_PIX_FMT_VP9:
+		ctx->dec_if = get_vp9_dec_comm_if();
+		break;
 	default:
 		return -EINVAL;
 	}
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Thu May 12 04:24:06 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Thu, 12 May 2016 19:24:06 +0800
Subject: [PATCH v2 5/9] [Media] vcodec: mediatek: Add Mediatek V4L2 Video
 Decoder Driver
In-Reply-To: <1463052250-38262-5-git-send-email-tiffany.lin@mediatek.com>
References: <1463052250-38262-1-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-2-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-3-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-4-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-5-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1463052250-38262-6-git-send-email-tiffany.lin@mediatek.com>

Add v4l2 layer decoder driver for MT8173

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 drivers/media/platform/mtk-vcodec/Makefile         |   10 +-
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 1336 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h |   81 ++
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c |  440 +++++++
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c  |  154 +++
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h  |   28 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h |   81 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_intr.h    |    2 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_util.c    |   10 +-
 drivers/media/platform/mtk-vcodec/vdec_drv_base.h  |   56 +
 drivers/media/platform/mtk-vcodec/vdec_drv_if.c    |  113 ++
 drivers/media/platform/mtk-vcodec/vdec_drv_if.h    |   93 ++
 drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h   |  103 ++
 13 files changed, 2491 insertions(+), 16 deletions(-)
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_drv_base.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_drv_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_drv_if.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h

diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
index dc5cb00..4c8ed2f 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -1,7 +1,13 @@
 
 
-obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-enc.o mtk-vcodec-common.o
-
+obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
+				       mtk-vcodec-enc.o \
+				       mtk-vcodec-common.o
+
+mtk-vcodec-dec-y := mtk_vcodec_dec_drv.o \
+		vdec_drv_if.o \
+		mtk_vcodec_dec.o \
+		mtk_vcodec_dec_pm.o \
 
 
 mtk-vcodec-enc-y := venc/venc_vp8_if.o \
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
new file mode 100644
index 0000000..35c2186
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
@@ -0,0 +1,1336 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen at mediatek.com>
+*         Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_dec.h"
+#include "mtk_vcodec_intr.h"
+#include "mtk_vcodec_util.h"
+#include "vdec_drv_if.h"
+#include "mtk_vcodec_dec_pm.h"
+
+#define OUT_FMT_IDX	0
+#define CAP_FMT_IDX	3
+
+#define VCODEC_CAPABILITY_4K_DISABLED	0x10
+#define VCODEC_DEC_4K_CODED_WIDTH	4096U
+#define VCODEC_DEC_4K_CODED_HEIGHT	2304U
+
+#define MTK_VDEC_MIN_W	64U
+#define MTK_VDEC_MIN_H	64U
+#define MTK_VDEC_MAX_W	2048U
+#define MTK_VDEC_MAX_H	1088U
+#define DFT_CFG_WIDTH	MTK_VDEC_MIN_W
+#define DFT_CFG_HEIGHT	MTK_VDEC_MIN_H
+
+static struct mtk_video_fmt mtk_video_formats[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_H264,
+		.type = MTK_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP8,
+		.type = MTK_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP9,
+		.type = MTK_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_MT21,
+		.type = MTK_FMT_FRAME,
+		.num_planes = 2,
+	},
+};
+
+static const struct mtk_codec_framesizes mtk_vdec_framesizes[] = {
+	{
+		.fourcc	= V4L2_PIX_FMT_H264,
+		.stepwise = {  MTK_VDEC_MIN_W, MTK_VDEC_MAX_W, 16,
+				MTK_VDEC_MIN_H, MTK_VDEC_MAX_H, 16 },
+	},
+	{
+		.fourcc	= V4L2_PIX_FMT_VP8,
+		.stepwise = {  MTK_VDEC_MIN_W, MTK_VDEC_MAX_W, 16,
+				MTK_VDEC_MIN_H, MTK_VDEC_MAX_H, 16 },
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP9,
+		.stepwise = {  MTK_VDEC_MIN_W, MTK_VDEC_MAX_W, 16,
+				MTK_VDEC_MIN_H, MTK_VDEC_MAX_H, 16 },
+	},
+};
+
+#define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(mtk_vdec_framesizes)
+#define NUM_FORMATS ARRAY_SIZE(mtk_video_formats)
+
+static struct mtk_video_fmt *mtk_vdec_find_format(struct v4l2_format *f)
+{
+	struct mtk_video_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < NUM_FORMATS; k++) {
+		fmt = &mtk_video_formats[k];
+		if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static struct mtk_q_data *mtk_vdec_get_q_data(struct mtk_vcodec_ctx *ctx,
+					      enum v4l2_buf_type type)
+{
+	if (V4L2_TYPE_IS_OUTPUT(type))
+		return &ctx->q_data[MTK_Q_DATA_SRC];
+
+	return &ctx->q_data[MTK_Q_DATA_DST];
+}
+
+static struct vb2_buffer *get_display_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct vdec_fb *disp_frame_buffer = NULL;
+	struct mtk_video_dec_buf *dstbuf;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+	if (vdec_if_get_param(ctx,
+			GET_PARAM_DISP_FRAME_BUFFER,
+			&disp_frame_buffer)) {
+		mtk_v4l2_err("[%d]Cannot get param : GET_PARAM_DISP_FRAME_BUFFER",
+			ctx->id);
+		return NULL;
+	}
+
+	if (disp_frame_buffer == NULL) {
+		mtk_v4l2_debug(3, "No display frame buffer");
+		return NULL;
+	}
+
+	dstbuf = container_of(disp_frame_buffer, struct mtk_video_dec_buf, frame_buffer);
+	mutex_lock(&dstbuf->lock);
+	if (dstbuf->used) {
+		vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0,
+					ctx->picinfo.y_bs_sz);
+		vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1,
+					ctx->picinfo.c_bs_sz);
+
+		dstbuf->ready_to_display = true;
+
+		mtk_v4l2_debug(2,
+				"[%d]status=%x queue id=%d to done_list %d",
+				ctx->id, disp_frame_buffer->status,
+				dstbuf->vb.vb2_buf.index,
+				dstbuf->queued_in_vb2);
+
+		v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE);
+		ctx->decoded_frame_cnt++;
+	}
+	mutex_unlock(&dstbuf->lock);
+	return &dstbuf->vb.vb2_buf;
+}
+
+static struct vb2_buffer *get_free_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct mtk_video_dec_buf *dstbuf;
+	struct vdec_fb *free_frame_buffer;
+
+	if (vdec_if_get_param(ctx,
+				GET_PARAM_FREE_FRAME_BUFFER,
+				&free_frame_buffer)) {
+		mtk_v4l2_err("[%d] Error!! Cannot get param", ctx->id);
+		return NULL;
+	}
+	if (free_frame_buffer == NULL) {
+		mtk_v4l2_debug(3, " No free frame buffer");
+		return NULL;
+	}
+
+	mtk_v4l2_debug(3, "[%d] tmp_frame_addr = 0x%p",
+			ctx->id, free_frame_buffer);
+
+	dstbuf = container_of(free_frame_buffer, struct mtk_video_dec_buf, frame_buffer);
+
+	mutex_lock(&dstbuf->lock);
+	if (dstbuf->used) {
+		if ((dstbuf->queued_in_vb2) &&
+		    (dstbuf->queued_in_v4l2) &&
+		    (free_frame_buffer->status == FB_ST_FREE)) {
+			mtk_v4l2_debug(2,
+				"[%d]status=%x queue id=%d to rdy_queue %d",
+				ctx->id, free_frame_buffer->status,
+				dstbuf->vb.vb2_buf.index,
+				dstbuf->queued_in_vb2);
+			v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb);
+		} else if ((dstbuf->queued_in_vb2 == false) &&
+			   (dstbuf->queued_in_v4l2 == true)) {
+			mtk_v4l2_debug(2,
+					"[%d]status=%x queue id=%d to rdy_queue",
+					ctx->id, free_frame_buffer->status,
+					dstbuf->vb.vb2_buf.index);
+			v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb);
+			dstbuf->queued_in_vb2 = true;
+		} else {
+			mtk_v4l2_debug(2,
+					"[%d]status=%x err queue id=%d %d %d",
+					ctx->id, free_frame_buffer->status,
+					dstbuf->vb.vb2_buf.index,
+					dstbuf->queued_in_vb2,
+					dstbuf->queued_in_v4l2);
+		}
+		dstbuf->used = false;
+	}
+	mutex_unlock(&dstbuf->lock);
+	return &dstbuf->vb.vb2_buf;
+}
+
+static void clean_display_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct vb2_buffer *framptr;
+
+	do {
+		framptr = get_display_buffer(ctx);
+	} while (framptr);
+}
+
+static void clean_free_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct vb2_buffer *framptr;
+
+	do {
+		framptr = get_free_buffer(ctx);
+	} while (framptr);
+}
+
+static int mtk_vdec_queue_res_chg_event(struct mtk_vcodec_ctx *ctx)
+{
+	static const struct v4l2_event ev_src_ch = {
+		.type = V4L2_EVENT_SOURCE_CHANGE,
+		.u.src_change.changes =
+		V4L2_EVENT_SRC_CH_RESOLUTION,
+	};
+
+	mtk_v4l2_debug(1, "[%d]", ctx->id);
+	v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
+
+	return 0;
+}
+
+static void mtk_vdec_flush_decoder(struct mtk_vcodec_ctx *ctx)
+{
+	bool res_chg;
+	int ret = 0;
+
+	ret = vdec_if_decode(ctx, NULL, NULL, &res_chg);
+	if (ret)
+		mtk_v4l2_err("DecodeFinal failed");
+
+	clean_display_buffer(ctx);
+	clean_free_buffer(ctx);
+}
+
+static bool mtk_vdec_pic_info_update(struct mtk_vcodec_ctx *ctx)
+{
+	int dpbsize;
+
+	if (vdec_if_get_param(ctx,
+				GET_PARAM_PIC_INFO,
+				&ctx->last_decoded_picinfo)) {
+		mtk_v4l2_err("[%d]Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR",
+				ctx->id);
+		return false;
+	}
+
+	if (ctx->last_decoded_picinfo.pic_w == 0 ||
+		ctx->last_decoded_picinfo.pic_h == 0 ||
+		ctx->last_decoded_picinfo.buf_w == 0 ||
+		ctx->last_decoded_picinfo.buf_h == 0)
+		return false;
+
+	if ((ctx->last_decoded_picinfo.pic_w != ctx->picinfo.pic_w) ||
+	    (ctx->last_decoded_picinfo.pic_h != ctx->picinfo.pic_h)) {
+
+		mtk_v4l2_debug(1,
+				"[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)",
+				ctx->id, ctx->last_decoded_picinfo.pic_w,
+				ctx->last_decoded_picinfo.pic_h,
+				ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+				ctx->last_decoded_picinfo.buf_w,
+				ctx->last_decoded_picinfo.buf_h);
+
+		vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize);
+		if (dpbsize == 0)
+			dpbsize = 1;
+		ctx->dpb_count = dpbsize;
+		return true;
+	}
+
+	return false;
+}
+
+static void mtk_vdec_worker(struct work_struct *work)
+{
+	struct mtk_vcodec_ctx *ctx = container_of(work, struct mtk_vcodec_ctx,
+				decode_work);
+	struct mtk_vcodec_dev *dev = ctx->dev;
+	struct vb2_buffer *src_buf, *dst_buf;
+	struct mtk_vcodec_mem buf;
+	struct vdec_fb *pfb;
+	bool res_chg = false;
+	int ret;
+	struct mtk_video_dec_buf *dst_buf_info, *src_buf_info;
+	struct vb2_v4l2_buffer *dst_vb2_v4l2, *src_vb2_v4l2;
+
+	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+	if (src_buf == NULL) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_v4l2_debug(1, "[%d] src_buf empty!!", ctx->id);
+		return;
+	}
+
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+	if (dst_buf == NULL) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_v4l2_debug(1, "[%d] dst_buf empty!!", ctx->id);
+		return;
+	}
+
+	src_vb2_v4l2 = container_of(src_buf, struct vb2_v4l2_buffer, vb2_buf);
+	src_buf_info = container_of(src_vb2_v4l2, struct mtk_video_dec_buf, vb);
+
+	dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf);
+	dst_buf_info = container_of(dst_vb2_v4l2, struct mtk_video_dec_buf, vb);
+
+	buf.va = vb2_plane_vaddr(src_buf, 0);
+	buf.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+	buf.size = (unsigned int)src_buf->planes[0].bytesused;
+	if (!buf.va) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_v4l2_err("[%d] id=%d src_addr is NULL!!",
+				ctx->id, src_buf->index);
+		return;
+	}
+
+	pfb = &dst_buf_info->frame_buffer;
+	pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0);
+	pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+	pfb->base_y.size = ctx->picinfo.y_bs_sz + ctx->picinfo.y_len_sz;
+
+	pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1);
+	pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1);
+	pfb->base_c.size = ctx->picinfo.c_bs_sz + ctx->picinfo.c_len_sz;
+	pfb->status = 0;
+	mtk_v4l2_debug(3, "===>[%d] vdec_if_decode() ===>", ctx->id);
+	mtk_v4l2_debug(3,
+			"[%d] Bitstream VA=%p DMA=%llx Size=0x%lx vb=%p",
+			ctx->id, buf.va,
+			(u64)buf.dma_addr,
+			buf.size, src_buf);
+
+	mtk_v4l2_debug(3,
+			"id=%d Framebuf  pfb=%p VA=%p Y_DMA=%llx C_DMA=%llx Size=0x%lx",
+			dst_buf->index, pfb,
+			pfb->base_y.va, (u64)pfb->base_y.dma_addr,
+			(u64)pfb->base_c.dma_addr, pfb->base_y.size);
+
+	if (src_buf_info->lastframe == true) {
+		/* update src buf status */
+		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		src_buf_info->lastframe = false;
+		v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE);
+
+		/* update dst buf status */
+		dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+		dst_buf_info->used = false;
+
+		clean_display_buffer(ctx);
+		vb2_set_plane_payload(&dst_buf_info->vb.vb2_buf, 0, 0);
+		vb2_set_plane_payload(&dst_buf_info->vb.vb2_buf, 1, 0);
+		v4l2_m2m_buf_done(&dst_buf_info->vb, VB2_BUF_STATE_DONE);
+		clean_free_buffer(ctx);
+	} else {
+		dst_buf_info->vb.vb2_buf.timestamp
+				= src_buf_info->vb.vb2_buf.timestamp;
+		dst_buf_info->vb.timecode
+				= src_buf_info->vb.timecode;
+		mutex_lock(&dst_buf_info->lock);
+		dst_buf_info->used = true;
+		mutex_unlock(&dst_buf_info->lock);
+		src_buf_info->used = true;
+
+		ret = vdec_if_decode(ctx, &buf, pfb, &res_chg);
+
+		if (ret) {
+			mtk_v4l2_err(
+				" <===[%d], src_buf[%d]%d sz=0x%zx pts=%llu dst_buf[%d] vdec_if_decode() ret=%d res_chg=%d===>",
+				ctx->id,
+				src_buf->index,
+				src_buf_info->lastframe,
+				buf.size,
+				src_buf_info->vb.vb2_buf.timestamp,
+				dst_buf->index,
+				ret, res_chg);
+			src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+			v4l2_m2m_buf_done(&src_buf_info->vb,
+					VB2_BUF_STATE_ERROR);
+		} else if (res_chg == false) {
+			/* we only return src buffer with VB2_BUF_STATE_DONE
+			  * when decode success without resolution change
+			  */
+			src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+			v4l2_m2m_buf_done(&src_buf_info->vb,
+					VB2_BUF_STATE_DONE);
+		}
+
+		dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+		clean_display_buffer(ctx);
+		clean_free_buffer(ctx);
+
+		if ((ret == 0) && (res_chg == true)) {
+			mtk_vdec_pic_info_update(ctx);
+			/*
+			 * On encountering a resolution change in the stream.
+			 * The driver must first process and decode all
+			 * remaining buffers from before the resolution change
+			 * point, so call flush decode here
+			 */
+			mtk_vdec_flush_decoder(ctx);
+			/*
+			 * After all buffers containing decoded frames from
+			 * before the resolution change point ready to be
+			 * dequeued on the CAPTURE queue, the driver sends a
+			 * V4L2_EVENT_SOURCE_CHANGE event for source change
+			 * type V4L2_EVENT_SRC_CH_RESOLUTION
+			 */
+			mtk_vdec_queue_res_chg_event(ctx);
+		}
+	}
+
+	v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+}
+
+int mtk_vdec_unlock(struct mtk_vcodec_ctx *ctx)
+{
+	mutex_unlock(&ctx->dev->dec_mutex);
+	return 0;
+}
+
+int mtk_vdec_lock(struct mtk_vcodec_ctx *ctx)
+{
+	mutex_lock(&ctx->dev->dec_mutex);
+	return 0;
+}
+
+void mtk_vcodec_vdec_release(struct mtk_vcodec_ctx *ctx)
+{
+	vdec_if_deinit(ctx);
+	ctx->state = MTK_STATE_FREE;
+}
+
+void mtk_vcodec_dec_set_default_params(struct mtk_vcodec_ctx *ctx)
+{
+	struct mtk_q_data *q_data;
+
+	ctx->m2m_ctx->q_lock = &ctx->dev->dev_mutex;
+	ctx->fh.m2m_ctx = ctx->m2m_ctx;
+	ctx->fh.ctrl_handler = &ctx->ctrl_hdl;
+	INIT_WORK(&ctx->decode_work, mtk_vdec_worker);
+	ctx->colorspace = V4L2_COLORSPACE_REC709;
+	ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
+	ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+
+	q_data = &ctx->q_data[MTK_Q_DATA_SRC];
+	memset(q_data, 0, sizeof(struct mtk_q_data));
+	q_data->visible_width = DFT_CFG_WIDTH;
+	q_data->visible_height = DFT_CFG_HEIGHT;
+	q_data->fmt = &mtk_video_formats[OUT_FMT_IDX];
+	q_data->field = V4L2_FIELD_NONE;
+
+	ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
+		DFT_CFG_WIDTH * DFT_CFG_HEIGHT;
+	ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] = 0;
+
+	q_data = &ctx->q_data[MTK_Q_DATA_DST];
+	memset(q_data, 0, sizeof(struct mtk_q_data));
+	q_data->visible_width = DFT_CFG_WIDTH;
+	q_data->visible_height = DFT_CFG_HEIGHT;
+	q_data->coded_width = DFT_CFG_WIDTH;
+	q_data->coded_height = DFT_CFG_HEIGHT;
+	q_data->fmt = &mtk_video_formats[CAP_FMT_IDX];
+	q_data->field = V4L2_FIELD_NONE;
+
+	v4l_bound_align_image(&q_data->coded_width,
+				MTK_VDEC_MIN_W,
+				MTK_VDEC_MAX_W, 4,
+				&q_data->coded_height,
+				MTK_VDEC_MIN_H,
+				MTK_VDEC_MAX_H, 5, 6);
+
+	q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height;
+	q_data->bytesperline[0] = q_data->coded_width;
+	q_data->sizeimage[1] = q_data->sizeimage[0] / 2;
+	q_data->bytesperline[1] = q_data->coded_width;
+}
+
+static int vidioc_vdec_qbuf(struct file *file, void *priv,
+			    struct v4l2_buffer *buf)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct vb2_queue *vq;
+	struct vb2_buffer *vb;
+	struct mtk_video_dec_buf *mtkbuf;
+	struct vb2_v4l2_buffer	*vb2_v4l2;
+
+	if (ctx->state == MTK_STATE_ABORT) {
+		mtk_v4l2_err("[%d] Call on QBUF after unrecoverable error",
+				ctx->id);
+		return -EIO;
+	}
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, buf->type);
+	vb = vq->bufs[buf->index];
+	vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
+	mtkbuf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
+
+	if ((buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) &&
+	    (buf->m.planes[0].bytesused == 0)) {
+		mtkbuf->lastframe = true;
+		mtk_v4l2_debug(1, "[%d] (%d) id=%d lastframe=%d (%d,%d, %d) vb=%p",
+			 ctx->id, buf->type, buf->index,
+			 mtkbuf->lastframe, buf->bytesused,
+			 buf->m.planes[0].bytesused, buf->length,
+			 vb);
+	}
+
+	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_vdec_dqbuf(struct file *file, void *priv,
+			     struct v4l2_buffer *buf)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (ctx->state == MTK_STATE_ABORT) {
+		mtk_v4l2_err("[%d] Call on QBUF after unrecoverable error",
+				ctx->id);
+		return -EIO;
+	}
+
+	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_vdec_querycap(struct file *file, void *priv,
+				struct v4l2_capability *cap)
+{
+	strlcpy(cap->driver, MTK_VCODEC_DEC_NAME, sizeof(cap->driver));
+	strlcpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info));
+	strlcpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card));
+	cap->device_caps  = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+	return 0;
+}
+
+static int vidioc_vdec_subscribe_evt(struct v4l2_fh *fh,
+				     const struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_EOS:
+		return v4l2_event_subscribe(fh, sub, 2, NULL);
+	case V4L2_EVENT_SOURCE_CHANGE:
+		return v4l2_src_change_event_subscribe(fh, sub);
+	default:
+		return v4l2_ctrl_subscribe_event(fh, sub);
+	}
+}
+
+static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct mtk_video_fmt *fmt;
+
+	fmt = mtk_vdec_find_format(f);
+	if (!fmt) {
+		f->fmt.pix.pixelformat = mtk_video_formats[CAP_FMT_IDX].fourcc;
+		fmt = mtk_vdec_find_format(f);
+	}
+
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+	struct mtk_video_fmt *fmt;
+
+	fmt = mtk_vdec_find_format(f);
+	if (!fmt) {
+		f->fmt.pix.pixelformat = mtk_video_formats[OUT_FMT_IDX].fourcc;
+		fmt = mtk_vdec_find_format(f);
+	}
+
+	if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) {
+		mtk_v4l2_err("sizeimage of output format must be given");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vidioc_vdec_g_selection(struct file *file, void *priv,
+			 struct v4l2_selection *s)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (V4L2_TYPE_IS_OUTPUT(s->type))
+		return -EINVAL;
+
+	if (s->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	if (ctx->state < MTK_STATE_HEADER)
+		return -EINVAL;
+
+	if ((ctx->q_data[MTK_Q_DATA_SRC].fmt->fourcc == V4L2_PIX_FMT_H264) ||
+	    (ctx->q_data[MTK_Q_DATA_SRC].fmt->fourcc == V4L2_PIX_FMT_VP8) ||
+	    (ctx->q_data[MTK_Q_DATA_SRC].fmt->fourcc == V4L2_PIX_FMT_VP9)) {
+
+		if (vdec_if_get_param(ctx,
+					GET_PARAM_CROP_INFO,
+					&(s->r))) {
+			mtk_v4l2_debug(2,
+					"[%d]Error!! Cannot get param : GET_PARAM_CROP_INFO ERR",
+					ctx->id);
+			s->r.left = 0;
+			s->r.top = 0;
+			s->r.width = ctx->picinfo.buf_w;
+			s->r.height = ctx->picinfo.buf_h;
+		}
+		mtk_v4l2_debug(2, "Cropping info: l=%d t=%d w=%d h=%d",
+				 s->r.left, s->r.top, s->r.width,
+				 s->r.height);
+	} else {
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = ctx->picinfo.pic_w;
+		s->r.height = ctx->picinfo.pic_h;
+		mtk_v4l2_debug(2, "Cropping info: w=%d h=%d fw=%d fh=%d",
+				s->r.width, s->r.height, ctx->picinfo.buf_w,
+				ctx->picinfo.buf_h);
+	}
+	return 0;
+}
+
+static int vidioc_vdec_s_fmt(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct v4l2_pix_format_mplane *pix_mp;
+	struct vb2_queue *vq;
+	struct mtk_q_data *q_data;
+	int ret = 0;
+	struct mtk_video_fmt *fmt;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+
+	fmt = mtk_vdec_find_format(f);
+	if (fmt == NULL) {
+		mtk_v4l2_err("mtk_vdec_find_format fail");
+		return ret;
+	}
+
+	pix_mp = &f->fmt.pix_mp;
+	if ((f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) &&
+	    vb2_is_busy(&ctx->m2m_ctx->out_q_ctx.q)) {
+		mtk_v4l2_err("out_q_ctx buffers already requested");
+		ret = -EBUSY;
+	}
+
+	if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+	    vb2_is_busy(&ctx->m2m_ctx->cap_q_ctx.q)) {
+		mtk_v4l2_err("cap_q_ctx buffers already requested");
+		ret = -EBUSY;
+	}
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+	if (!vq)
+		return -EINVAL;
+
+	q_data = mtk_vdec_get_q_data(ctx, f->type);
+	if (!q_data)
+		return -EINVAL;
+
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		q_data->fmt = fmt;
+		q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
+		pix_mp->plane_fmt[0].bytesperline = 0;
+		pix_mp->width = 0;
+		pix_mp->height = 0;
+
+		if (ctx->state == MTK_STATE_FREE) {
+			ret = vdec_if_init(ctx, q_data->fmt->fourcc);
+			if (ret) {
+				mtk_v4l2_err("[%d]: vdec_if_init() fail ret=%d",
+					ctx->id, ret);
+				return -EINVAL;
+			}
+			ctx->state = MTK_STATE_INIT;
+		}
+	} else {
+		q_data->fmt = fmt;
+	}
+
+	return 0;
+}
+
+static int vidioc_enum_framesizes(struct file *file, void *priv,
+				struct v4l2_frmsizeenum *fsize)
+{
+	int i = 0;
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (fsize->index != 0)
+		return -EINVAL;
+
+	for (i = 0; i < NUM_SUPPORTED_FRAMESIZE; ++i) {
+		if (fsize->pixel_format != mtk_vdec_framesizes[i].fourcc)
+			continue;
+
+		fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+		fsize->stepwise = mtk_vdec_framesizes[i].stepwise;
+		if (!(ctx->dev->dec_capability &
+				VCODEC_CAPABILITY_4K_DISABLED)) {
+			mtk_v4l2_debug(0, "4K is enabled");
+			fsize->stepwise.max_width =
+					VCODEC_DEC_4K_CODED_WIDTH;
+			fsize->stepwise.max_height =
+					VCODEC_DEC_4K_CODED_HEIGHT;
+		}
+		mtk_v4l2_debug(1, "%x, %d %d %d %d %d %d",
+				ctx->dev->dec_capability,
+				fsize->stepwise.min_width,
+				fsize->stepwise.max_width,
+				fsize->stepwise.step_width,
+				fsize->stepwise.min_height,
+				fsize->stepwise.max_height,
+				fsize->stepwise.step_height);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue)
+{
+	struct mtk_video_fmt *fmt;
+	int i, j = 0;
+
+	for (i = 0; i < NUM_FORMATS; i++) {
+		if (output_queue && (mtk_video_formats[i].type != MTK_FMT_DEC))
+			continue;
+		if (!output_queue &&
+			(mtk_video_formats[i].type != MTK_FMT_FRAME))
+			continue;
+
+		if (j == f->index)
+			break;
+		++j;
+	}
+
+	if (i == NUM_FORMATS)
+		return -EINVAL;
+
+	fmt = &mtk_video_formats[i];
+	f->pixelformat = fmt->fourcc;
+
+	return 0;
+}
+
+static int vidioc_vdec_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
+					       struct v4l2_fmtdesc *f)
+{
+	return vidioc_enum_fmt(f, false);
+}
+
+static int vidioc_vdec_enum_fmt_vid_out_mplane(struct file *file, void *priv,
+					       struct v4l2_fmtdesc *f)
+{
+	return vidioc_enum_fmt(f, true);
+}
+
+static int vidioc_vdec_g_fmt(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct vb2_queue *vq;
+	struct mtk_q_data *q_data;
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+	if (!vq) {
+		mtk_v4l2_err("no vb2 queue for type=%d",
+			f->type);
+		return -EINVAL;
+	}
+
+	q_data = mtk_vdec_get_q_data(ctx, f->type);
+
+	if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+	    (ctx->state >= MTK_STATE_HEADER)) {
+		/* previous decode might have resolution change that make
+		 * picinfo changed update context'x picinfo here to make sure
+		 * we know what report to user space
+		 */
+		memcpy(&ctx->picinfo, &ctx->last_decoded_picinfo,
+			sizeof(struct vdec_pic_info));
+		q_data->sizeimage[0] = ctx->picinfo.y_bs_sz +
+					ctx->picinfo.y_len_sz;
+		q_data->sizeimage[1] = ctx->picinfo.c_bs_sz +
+					ctx->picinfo.c_len_sz;
+		q_data->bytesperline[0] = ctx->last_decoded_picinfo.buf_w;
+		q_data->bytesperline[1] = ctx->last_decoded_picinfo.buf_w;
+		q_data->coded_width = ctx->picinfo.buf_w;
+		q_data->coded_height = ctx->picinfo.buf_h;
+
+		/*
+		 * Width and height are set to the dimensions
+		 * of the movie, the buffer is bigger and
+		 * further processing stages should crop to this
+		 * rectangle.
+		 */
+		pix_mp->width = q_data->coded_width;
+		pix_mp->height = q_data->coded_height;
+		pix_mp->field = V4L2_FIELD_NONE;
+
+		/*
+		 * Set pixelformat to the format in which mt vcodec
+		 * outputs the decoded frame
+		 */
+		pix_mp->num_planes = q_data->fmt->num_planes;
+		pix_mp->pixelformat = q_data->fmt->fourcc;
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+		pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1];
+		pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1];
+
+	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		/*
+		 * This is run on OUTPUT
+		 * The buffer contains compressed image
+		 * so width and height have no meaning.
+		 * Assign value here to pass v4l2-compliance test
+		 */
+		pix_mp->width = q_data->visible_width;
+		pix_mp->height = q_data->visible_height;
+		pix_mp->field = V4L2_FIELD_NONE;
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+		pix_mp->pixelformat = q_data->fmt->fourcc;
+		pix_mp->num_planes = q_data->fmt->num_planes;
+	} else {
+		pix_mp->width = q_data->coded_width;
+		pix_mp->height = q_data->coded_height;
+		pix_mp->field = V4L2_FIELD_NONE;
+		pix_mp->num_planes = q_data->fmt->num_planes;
+		pix_mp->pixelformat = q_data->fmt->fourcc;
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+		pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1];
+		pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1];
+
+		mtk_v4l2_debug(1, "[%d] state=%d Format could not be read %d, not ready yet!",
+				ctx->id, ctx->state, f->type);
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static int vb2ops_vdec_queue_setup(struct vb2_queue *vq,
+				unsigned int *nbuffers,
+				unsigned int *nplanes,
+				unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vq);
+	struct mtk_q_data *q_data;
+	unsigned int i;
+
+	q_data = mtk_vdec_get_q_data(ctx, vq->type);
+
+	if (q_data == NULL) {
+		mtk_v4l2_err("vq->type=%d err\n", vq->type);
+		return -EINVAL;
+	}
+
+	if (*nplanes) {
+		for (i = 0; i < *nplanes; i++) {
+			if (sizes[i] < q_data->sizeimage[i])
+				return -EINVAL;
+			alloc_ctxs[i] = ctx->dev->alloc_ctx;
+		}
+	} else {
+
+		if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+			if (ctx->state < MTK_STATE_HEADER) {
+				mtk_v4l2_err("State not ready");
+				return -EINVAL;
+			}
+			/*
+			 * Output plane count is 2 - one for Y and one for CbCr
+			 */
+			*nplanes = 2;
+		} else {
+			*nplanes = 1;
+		}
+
+		for (i = 0; i < *nplanes; i++) {
+			sizes[i] = q_data->sizeimage[i];
+			alloc_ctxs[i] = ctx->dev->alloc_ctx;
+		}
+	}
+
+	mtk_v4l2_debug(1,
+			"[%d]\t type = %d, get %d plane(s), %d buffer(s) of size 0x%x 0x%x ",
+			ctx->id, vq->type, *nplanes, *nbuffers,
+			sizes[0], sizes[1]);
+
+	return 0;
+}
+
+static int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct mtk_q_data *q_data;
+	int i;
+
+	mtk_v4l2_debug(3, "[%d] (%d) id=%d",
+			ctx->id, vb->vb2_queue->type, vb->index);
+
+	q_data = mtk_vdec_get_q_data(ctx, vb->vb2_queue->type);
+
+	for (i = 0; i < q_data->fmt->num_planes; i++) {
+		if (vb2_plane_size(vb, i) > q_data->sizeimage[i]) {
+			mtk_v4l2_err("data will not fit into plane %d (%lu < %d)",
+				i, vb2_plane_size(vb, i),
+				q_data->sizeimage[i]);
+		}
+	}
+
+	return 0;
+}
+
+static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb,
+				struct vb2_v4l2_buffer, vb2_buf);
+	struct mtk_video_dec_buf *buf = container_of(vb2_v4l2,
+				struct mtk_video_dec_buf, vb);
+
+	mtk_v4l2_debug(3, "[%d] (%d) id=%d, vb=%p",
+			ctx->id, vb->vb2_queue->type,
+			vb->index, vb);
+	/*
+	 * check if this buffer is ready to be used after decode
+	 */
+	if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		struct vb2_buffer *src_buf;
+		struct mtk_vcodec_mem buf;
+		bool res_chg = false;
+		int ret = 0;
+		int dpbsize = 1;
+
+		v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2);
+
+		if (ctx->state == MTK_STATE_INIT) {
+			src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+			if (!src_buf) {
+				mtk_v4l2_err("No src buffer");
+				return;
+			}
+
+			buf.va	= vb2_plane_vaddr(src_buf, 0);
+			buf.dma_addr = vb2_dma_contig_plane_dma_addr(
+						src_buf,
+						0);
+			buf.size = (size_t)src_buf->planes[0].bytesused;
+			mtk_v4l2_debug(2,
+					"[%d] buf id=%d va=%p dma=%llx size=%zu",
+					ctx->id,
+					src_buf->index,
+					buf.va, (u64)buf.dma_addr, buf.size);
+
+			ret = vdec_if_decode(ctx, &buf, NULL, &res_chg);
+			if (ret) {
+				src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+				v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+						VB2_BUF_STATE_DONE);
+				mtk_v4l2_err("[%d] vdec_if_decode() src_buf=%d, size=%zu, fail=%d",
+						ctx->id,
+						src_buf->index,
+						buf.size, ret);
+				return;
+			}
+
+			if (vdec_if_get_param(ctx,
+						GET_PARAM_PIC_INFO,
+						&ctx->picinfo)) {
+				mtk_v4l2_err("[%d]Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR",
+						ctx->id);
+				return;
+			}
+
+			memcpy(&ctx->last_decoded_picinfo, &ctx->picinfo,
+				sizeof(struct vdec_pic_info));
+			ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
+						ctx->picinfo.y_bs_sz +
+						ctx->picinfo.y_len_sz;
+			ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] =
+						ctx->picinfo.buf_w;
+			ctx->q_data[MTK_Q_DATA_DST].sizeimage[1] =
+						ctx->picinfo.c_bs_sz +
+						ctx->picinfo.c_len_sz;
+			ctx->q_data[MTK_Q_DATA_DST].bytesperline[1] =
+						ctx->picinfo.buf_w;
+			mtk_v4l2_debug(2, "[%d] vdec_if_init() OK wxh=%dx%d pic wxh=%dx%d sz[0]=0x%x sz[1]=0x%x",
+				ctx->id,
+				ctx->picinfo.buf_w, ctx->picinfo.buf_h,
+				ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+				ctx->q_data[MTK_Q_DATA_DST].sizeimage[0],
+				ctx->q_data[MTK_Q_DATA_DST].sizeimage[1]);
+
+			vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize);
+			if (dpbsize == 0) {
+				mtk_v4l2_debug(2,
+						"[%d] vdec_if_get_param()  GET_PARAM_DPB_SIZE fail=%d",
+						ctx->id, ret);
+				dpbsize = 1;
+			}
+			ctx->dpb_count = dpbsize;
+			ctx->state = MTK_STATE_HEADER;
+			mtk_v4l2_debug(1, "[%d] dpbsize=%d", ctx->id,
+					ctx->dpb_count);
+		} else {
+			mtk_v4l2_debug(3, "[%d] already init driver %d",
+					ctx->id, ctx->state);
+		}
+	} else {
+		mutex_lock(&buf->lock);
+		if (buf->used == false) {
+			v4l2_m2m_buf_queue(ctx->m2m_ctx,
+					to_vb2_v4l2_buffer(vb));
+			buf->queued_in_vb2 = true;
+			buf->queued_in_v4l2 = true;
+			buf->ready_to_display = false;
+		} else {
+			buf->queued_in_vb2 = false;
+			buf->queued_in_v4l2 = true;
+			buf->ready_to_display = false;
+		}
+		mutex_unlock(&buf->lock);
+	}
+}
+
+static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb)
+{
+	if (vb->vb2_queue->type ==
+		V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		struct vb2_v4l2_buffer *vb2_v4l2;
+		struct mtk_video_dec_buf *buf;
+
+		vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
+		buf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
+		mutex_lock(&buf->lock);
+		buf->queued_in_v4l2 = false;
+		buf->queued_in_vb2 = false;
+		mutex_unlock(&buf->lock);
+	}
+}
+
+static int vb2ops_vdec_buf_init(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb,
+					struct vb2_v4l2_buffer, vb2_buf);
+	struct mtk_video_dec_buf *buf = container_of(vb2_v4l2,
+					struct mtk_video_dec_buf, vb);
+
+	if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		buf->used = false;
+		buf->ready_to_display = false;
+		buf->queued_in_v4l2 = false;
+		mutex_init(&buf->lock);
+	} else {
+		buf->lastframe = false;
+	}
+
+	return 0;
+}
+
+static int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q);
+
+	if (ctx->state == MTK_STATE_FLUSH)
+		ctx->state = MTK_STATE_HEADER;
+
+	return 0;
+}
+
+static void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
+{
+	struct vb2_buffer *src_buf = NULL, *dst_buf = NULL;
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q);
+
+	mtk_v4l2_debug(1, "[%d] (%d) state=(%x) ctx->decoded_frame_cnt=%d",
+			ctx->id, q->type, ctx->state, ctx->decoded_frame_cnt);
+
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
+			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+					VB2_BUF_STATE_ERROR);
+
+	} else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		int i;
+		struct vb2_v4l2_buffer *vb2_v4l2;
+		struct mtk_video_dec_buf *buf;
+
+		if (ctx->state >= MTK_STATE_HEADER)
+			mtk_vdec_flush_decoder(ctx);
+
+		ctx->state = MTK_STATE_FLUSH;
+
+		while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) {
+			vb2_set_plane_payload(dst_buf, 0, 0);
+			vb2_set_plane_payload(dst_buf, 1, 0);
+			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
+				VB2_BUF_STATE_ERROR);
+		}
+
+		for (i = 0; i < q->num_buffers; ++i) {
+			if (q->bufs[i]->state == VB2_BUF_STATE_ACTIVE) {
+				vb2_v4l2 = container_of(q->bufs[i],
+					struct vb2_v4l2_buffer, vb2_buf);
+				buf = container_of(vb2_v4l2,
+					struct mtk_video_dec_buf, vb);
+
+				mtk_v4l2_debug(1, "[%d] id=%d, type=%d, [%d %d] %d -> VB2_BUF_STATE_ERROR",
+						ctx->id, i, q->type,
+						buf->queued_in_vb2,
+						buf->queued_in_v4l2,
+						(int)q->bufs[i]->state);
+				v4l2_m2m_buf_done(vb2_v4l2,
+						VB2_BUF_STATE_ERROR);
+			}
+		}
+	}
+}
+
+static void m2mops_vdec_device_run(void *priv)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+	struct mtk_vcodec_dev *dev = ctx->dev;
+
+	queue_work(dev->decode_workqueue, &ctx->decode_work);
+}
+
+static int m2mops_vdec_job_ready(void *m2m_priv)
+{
+	struct mtk_vcodec_ctx *ctx = m2m_priv;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+
+	if (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx))
+		return 0;
+
+	if (!v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx))
+		return 0;
+
+	if (ctx->state == MTK_STATE_ABORT)
+		return 0;
+
+	if ((ctx->last_decoded_picinfo.pic_w != ctx->picinfo.pic_w) ||
+	    (ctx->last_decoded_picinfo.pic_h != ctx->picinfo.pic_h))
+		return 0;
+
+	if (ctx->state != MTK_STATE_HEADER)
+		return 0;
+
+	return 1;
+}
+
+static void m2mops_vdec_job_abort(void *priv)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+
+	ctx->state = MTK_STATE_ABORT;
+}
+
+static int mtk_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mtk_vcodec_ctx *ctx = ctrl_to_ctx(ctrl);
+	int ret = 0;
+	switch (ctrl->id) {
+	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+		if (ctx->state >= MTK_STATE_HEADER) {
+			ctrl->val = ctx->dpb_count;
+		} else {
+			mtk_v4l2_err("Seqinfo not ready");
+			ctrl->val = 1;
+			ret = -EAGAIN;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops mtk_vcodec_dec_ctrl_ops = {
+	.g_volatile_ctrl = mtk_vdec_g_v_ctrl,
+};
+
+int mtk_vcodec_dec_ctrls_setup(struct mtk_vcodec_ctx *ctx)
+{
+	struct v4l2_ctrl *ctrl;
+
+	v4l2_ctrl_handler_init(&ctx->ctrl_hdl, 1);
+
+	ctrl = v4l2_ctrl_new_std(&ctx->ctrl_hdl,
+				&mtk_vcodec_dec_ctrl_ops,
+				V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
+				1, 32, 1, 1);
+	ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+	if (ctx->ctrl_hdl.error) {
+		mtk_v4l2_err("Adding control failed %d",
+				ctx->ctrl_hdl.error);
+		return ctx->ctrl_hdl.error;
+	}
+
+	v4l2_ctrl_handler_setup(&ctx->ctrl_hdl);
+	return 0;
+}
+
+static void m2mops_vdec_lock(void *m2m_priv)
+{
+	struct mtk_vcodec_ctx *ctx = m2m_priv;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+	mutex_lock(&ctx->dev->dev_mutex);
+}
+
+static void m2mops_vdec_unlock(void *m2m_priv)
+{
+	struct mtk_vcodec_ctx *ctx = m2m_priv;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+	mutex_unlock(&ctx->dev->dev_mutex);
+}
+
+const struct v4l2_m2m_ops mtk_vdec_m2m_ops = {
+	.device_run	= m2mops_vdec_device_run,
+	.job_ready	= m2mops_vdec_job_ready,
+	.job_abort	= m2mops_vdec_job_abort,
+	.lock		= m2mops_vdec_lock,
+	.unlock		= m2mops_vdec_unlock,
+};
+
+static const struct vb2_ops mtk_vdec_vb2_ops = {
+	.queue_setup	= vb2ops_vdec_queue_setup,
+	.buf_prepare	= vb2ops_vdec_buf_prepare,
+	.buf_queue	= vb2ops_vdec_buf_queue,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
+	.buf_init	= vb2ops_vdec_buf_init,
+	.buf_finish	= vb2ops_vdec_buf_finish,
+	.start_streaming	= vb2ops_vdec_start_streaming,
+	.stop_streaming	= vb2ops_vdec_stop_streaming,
+};
+
+const struct v4l2_ioctl_ops mtk_vdec_ioctl_ops = {
+	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff	= v4l2_m2m_ioctl_streamoff,
+	.vidioc_reqbufs		= v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
+	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
+
+	.vidioc_qbuf		= vidioc_vdec_qbuf,
+	.vidioc_dqbuf		= vidioc_vdec_dqbuf,
+
+	.vidioc_try_fmt_vid_cap_mplane	= vidioc_try_fmt_vid_cap_mplane,
+	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_out_mplane,
+
+	.vidioc_s_fmt_vid_cap_mplane	= vidioc_vdec_s_fmt,
+	.vidioc_s_fmt_vid_out_mplane	= vidioc_vdec_s_fmt,
+	.vidioc_g_fmt_vid_cap_mplane	= vidioc_vdec_g_fmt,
+	.vidioc_g_fmt_vid_out_mplane	= vidioc_vdec_g_fmt,
+
+	.vidioc_enum_fmt_vid_cap_mplane	= vidioc_vdec_enum_fmt_vid_cap_mplane,
+	.vidioc_enum_fmt_vid_out_mplane	= vidioc_vdec_enum_fmt_vid_out_mplane,
+	.vidioc_enum_framesizes	= vidioc_enum_framesizes,
+
+	.vidioc_querycap		= vidioc_vdec_querycap,
+	.vidioc_subscribe_event		= vidioc_vdec_subscribe_evt,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+	.vidioc_g_selection		= vidioc_vdec_g_selection,
+};
+
+int mtk_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
+			   struct vb2_queue *dst_vq)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+	int ret = 0;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+
+	src_vq->type		= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes	= VB2_DMABUF | VB2_MMAP;
+	src_vq->drv_priv	= ctx;
+	src_vq->buf_struct_size = sizeof(struct mtk_video_dec_buf);
+	src_vq->ops		= &mtk_vdec_vb2_ops;
+	src_vq->mem_ops		= &vb2_dma_contig_memops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock 		= &ctx->dev->dev_mutex;
+
+	ret = vb2_queue_init(src_vq);
+	if (ret) {
+		mtk_v4l2_err("Failed to initialize videobuf2 queue(output)");
+		return ret;
+	}
+	dst_vq->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes	= VB2_DMABUF | VB2_MMAP;
+	dst_vq->drv_priv	= ctx;
+	dst_vq->buf_struct_size = sizeof(struct mtk_video_dec_buf);
+	dst_vq->ops		= &mtk_vdec_vb2_ops;
+	dst_vq->mem_ops		= &vb2_dma_contig_memops;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock 		= &ctx->dev->dev_mutex;
+
+	ret = vb2_queue_init(dst_vq);
+	if (ret) {
+		vb2_queue_release(src_vq);
+		mtk_v4l2_err("Failed to initialize videobuf2 queue(capture)");
+	}
+
+	return ret;
+}
+
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
new file mode 100644
index 0000000..18d4925
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen at mediatek.com>
+*         Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MTK_VCODEC_DEC_H_
+#define _MTK_VCODEC_DEC_H_
+
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
+
+#define MTK_VDEC_IRQ_STATUS_DEC_SUCCESS        0x10000
+
+/**
+ * struct vdec_fb  - decoder frame buffer
+ * @base_y	: Y plane memory info
+ * @base_c	: C plane memory info
+ * @status      : frame buffer status (vdec_fb_status)
+ */
+struct vdec_fb {
+	struct mtk_vcodec_mem	base_y;
+	struct mtk_vcodec_mem	base_c;
+	unsigned int	status;
+};
+
+/**
+ * struct mtk_video_dec_buf - Private data related to each VB2 buffer.
+ * @b:			VB2 buffer
+ * @list:			link list
+ * @used:		Output buffer contain decoded frame data
+ * @ready_to_display:	Output buffer not display yet
+ * @queued_in_vb2:	Output buffer is queue in vb2
+ * @queued_in_v4l2:	Output buffer is in v4l2
+ * @lastframe:		Intput buffer is last buffer - EOS
+ * @frame_buffer:		Decode status of output buffer
+ * @lock:			V4L2 and decode thread should get mutex
+ *			before r/w info in mtk_video_dec_buf
+ */
+struct mtk_video_dec_buf {
+	struct vb2_v4l2_buffer	vb;
+	struct list_head	list;
+
+	bool	used;
+	bool	ready_to_display;
+	bool	queued_in_vb2;
+	bool	queued_in_v4l2;
+	bool	lastframe;
+	struct vdec_fb	frame_buffer;
+	struct mutex	lock;
+};
+
+extern const struct v4l2_ioctl_ops mtk_vdec_ioctl_ops;
+extern const struct v4l2_m2m_ops mtk_vdec_m2m_ops;
+
+
+/*
+ * mtk_vdec_lock/mtk_vdec_unlock are for ctx instance to
+ * get/release lock before/after access decoder hw.
+ * mtk_vdec_lock get decoder hw lock and set curr_ctx
+ * to ctx instance that get lock
+ */
+int mtk_vdec_unlock(struct mtk_vcodec_ctx *ctx);
+int mtk_vdec_lock(struct mtk_vcodec_ctx *ctx);
+int mtk_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
+			   struct vb2_queue *dst_vq);
+void mtk_vcodec_dec_set_default_params(struct mtk_vcodec_ctx *ctx);
+void mtk_vcodec_vdec_release(struct mtk_vcodec_ctx *ctx);
+int mtk_vcodec_dec_ctrls_setup(struct mtk_vcodec_ctx *ctx);
+
+
+#endif /* _MTK_VCODEC_DEC_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
new file mode 100644
index 0000000..80a7aae
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -0,0 +1,440 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen at mediatek.com>
+*         Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_dec.h"
+#include "mtk_vcodec_dec_pm.h"
+#include "mtk_vcodec_intr.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
+
+#define VDEC_HW_ACTIVE	0x10
+#define VDEC_IRQ_CFG	0x11
+#define VDEC_IRQ_CLR	0x10
+#define VDEC_IRQ_CFG_REG	0xa4
+
+module_param(mtk_v4l2_dbg_level, int, S_IRUGO | S_IWUSR);
+module_param(mtk_vcodec_dbg, bool, S_IRUGO | S_IWUSR);
+
+/* Wake up context wait_queue */
+static void wake_up_ctx(struct mtk_vcodec_ctx *ctx, unsigned int reason)
+{
+	ctx->int_cond = 1;
+	ctx->int_type = reason;
+	wake_up_interruptible(&ctx->queue);
+}
+
+static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void *priv)
+{
+	struct mtk_vcodec_dev *dev = priv;
+	unsigned long flags;
+	struct mtk_vcodec_ctx *ctx;
+	unsigned int cg_status = 0;
+	unsigned int dec_done_status = 0;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+	ctx = dev->curr_ctx;
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+
+	cg_status = readl(dev->reg_base[0] + (0));
+	if ((cg_status & VDEC_HW_ACTIVE) != 0) {
+		mtk_v4l2_err("DEC ISR, VDEC active is not 0x0 (0x%08x)",
+			     cg_status);
+		return IRQ_HANDLED;
+	}
+
+	dec_done_status = readl(dev->reg_base[1] + VDEC_IRQ_CFG_REG);
+	ctx->irq_status = dec_done_status;
+	if ((dec_done_status & (0x1 << 16)) != 0x10000)
+		return IRQ_HANDLED;
+
+	/* clear interrupt */
+	writel((readl(dev->reg_base[1] + VDEC_IRQ_CFG_REG) | VDEC_IRQ_CFG),
+		dev->reg_base[1] + VDEC_IRQ_CFG_REG);
+	writel((readl(dev->reg_base[1] + VDEC_IRQ_CFG_REG) & ~VDEC_IRQ_CLR),
+		dev->reg_base[1] + VDEC_IRQ_CFG_REG);
+
+	wake_up_ctx(ctx, MTK_INST_IRQ_RECEIVED);
+
+	mtk_v4l2_debug(3,
+			"mtk_vcodec_dec_irq_handler :wake up ctx %d, dec_done_status=%x",
+			ctx->id, dec_done_status);
+
+	return IRQ_HANDLED;
+}
+
+static void mtk_vcodec_dec_reset_handler(void *priv)
+{
+	struct mtk_vcodec_dev *dev = priv;
+	struct mtk_vcodec_ctx *ctx;
+
+	mtk_v4l2_debug(0, "Watchdog timeout!!");
+
+	mutex_lock(&dev->dev_mutex);
+	list_for_each_entry(ctx, &dev->ctx_list, list) {
+		ctx->state = MTK_STATE_ABORT;
+		mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ERROR",
+				ctx->id);
+	}
+	mutex_unlock(&dev->dev_mutex);
+}
+
+static int fops_vcodec_open(struct file *file)
+{
+	struct mtk_vcodec_dev *dev = video_drvdata(file);
+	struct mtk_vcodec_ctx *ctx = NULL;
+	int ret = 0;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	mutex_lock(&dev->dev_mutex);
+	ctx->id = dev->id_counter++;
+	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	file->private_data = &ctx->fh;
+	v4l2_fh_add(&ctx->fh);
+	INIT_LIST_HEAD(&ctx->list);
+	ctx->dev = dev;
+	init_waitqueue_head(&ctx->queue);
+
+	ctx->type = MTK_INST_DECODER;
+	ret = mtk_vcodec_dec_ctrls_setup(ctx);
+	if (ret) {
+		mtk_v4l2_err("Failed to setup mt vcodec controls");
+		goto err_ctrls_setup;
+	}
+	ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx,
+		&mtk_vcodec_dec_queue_init);
+	if (IS_ERR((__force void *)ctx->m2m_ctx)) {
+		ret = PTR_ERR((__force void *)ctx->m2m_ctx);
+		mtk_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)",
+			ret);
+		goto err_m2m_ctx_init;
+	}
+	mtk_vcodec_dec_set_default_params(ctx);
+
+	if (v4l2_fh_is_singular(&ctx->fh)) {
+		mtk_vcodec_dec_pw_on(&dev->pm);
+		/*
+		 * vpu_load_firmware checks if it was loaded already and
+		 * does nothing in that case
+		 */
+		ret = vpu_load_firmware(dev->vpu_plat_dev);
+		if (ret < 0) {
+			/*
+			 * Return 0 if downloading firmware successfully,
+			 * otherwise it is failed
+			 */
+			mtk_v4l2_err("vpu_load_firmware failed!");
+			goto err_load_fw;
+		}
+
+		dev->dec_capability =
+			vpu_get_vdec_hw_capa(dev->vpu_plat_dev);
+		mtk_v4l2_debug(0, "decoder capability %x",
+			dev->dec_capability);
+	}
+
+	dev->num_instances++;
+	list_add(&ctx->list, &dev->ctx_list);
+
+	mutex_unlock(&dev->dev_mutex);
+	mtk_v4l2_debug(0, "%s decoder [%d]", dev_name(&dev->plat_dev->dev),
+			ctx->id);
+	return ret;
+
+	/* Deinit when failure occurred */
+err_load_fw:
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+err_m2m_ctx_init:
+	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+err_ctrls_setup:
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	kfree(ctx);
+	mutex_unlock(&dev->dev_mutex);
+
+	return ret;
+}
+
+static int fops_vcodec_release(struct file *file)
+{
+	struct mtk_vcodec_dev *dev = video_drvdata(file);
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(file->private_data);
+
+	mtk_v4l2_debug(0, "[%d] decoder", ctx->id);
+	mutex_lock(&dev->dev_mutex);
+
+	mtk_vcodec_vdec_release(ctx);
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+
+	list_del_init(&ctx->list);
+	dev->num_instances--;
+	if (dev->num_instances == 0)
+		mtk_vcodec_dec_pw_off(&dev->pm);
+	kfree(ctx);
+	mutex_unlock(&dev->dev_mutex);
+	return 0;
+}
+
+static const struct v4l2_file_operations mtk_vcodec_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fops_vcodec_open,
+	.release	= fops_vcodec_release,
+	.poll		= v4l2_m2m_fop_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= v4l2_m2m_fop_mmap,
+};
+
+static int mtk_vcodec_probe(struct platform_device *pdev)
+{
+	struct mtk_vcodec_dev *dev;
+	struct video_device *vfd_dec;
+	struct resource *res;
+	int i, ret;
+	DEFINE_DMA_ATTRS(attrs);
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&dev->ctx_list);
+	dev->plat_dev = pdev;
+
+	dev->vpu_plat_dev = vpu_get_plat_device(dev->plat_dev);
+	if (dev->vpu_plat_dev == NULL) {
+		mtk_v4l2_err("[VPU] vpu device in not ready");
+		return -EPROBE_DEFER;
+	}
+
+	vpu_wdt_reg_handler(dev->vpu_plat_dev, mtk_vcodec_dec_reset_handler,
+			dev, VPU_RST_DEC);
+
+	ret = mtk_vcodec_init_dec_pm(dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to get mt vcodec clock source");
+		return ret;
+	}
+
+	for (i = 0; i < NUM_MAX_VDEC_REG_BASE; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (res == NULL) {
+			dev_err(&pdev->dev, "get memory resource failed.");
+			ret = -ENXIO;
+			goto err_res;
+		}
+		dev->reg_base[i] = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR((__force void *)dev->reg_base[i])) {
+			dev_err(&pdev->dev,
+				"devm_ioremap_resource %d failed.", i);
+			ret = PTR_ERR((__force void *)dev->reg_base);
+			goto err_res;
+		}
+		mtk_v4l2_debug(2, "reg[%d] base=%p", i, dev->reg_base[i]);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to get irq resource");
+		ret = -ENOENT;
+		goto err_res;
+	}
+
+	dev->dec_irq = platform_get_irq(pdev, 0);
+	ret = devm_request_irq(&pdev->dev, dev->dec_irq,
+			mtk_vcodec_dec_irq_handler, 0, pdev->name, dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to install dev->dec_irq %d (%d)",
+			dev->dec_irq,
+			ret);
+		goto err_res;
+	}
+
+	disable_irq(dev->dec_irq);
+	mutex_init(&dev->dec_mutex);
+	mutex_init(&dev->dev_mutex);
+	spin_lock_init(&dev->irqlock);
+
+	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
+		"[/MTK_V4L2_VDEC]");
+
+	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+	if (ret) {
+		mtk_v4l2_err("v4l2_device_register err=%d", ret);
+		goto err_res;
+	}
+
+	init_waitqueue_head(&dev->queue);
+
+	vfd_dec = video_device_alloc();
+	if (!vfd_dec) {
+		mtk_v4l2_err("Failed to allocate video device");
+		ret = -ENOMEM;
+		goto err_dec_alloc;
+	}
+	vfd_dec->fops		= &mtk_vcodec_fops;
+	vfd_dec->ioctl_ops	= &mtk_vdec_ioctl_ops;
+	vfd_dec->release	= video_device_release;
+	vfd_dec->lock		= &dev->dev_mutex;
+	vfd_dec->v4l2_dev	= &dev->v4l2_dev;
+	vfd_dec->vfl_dir	= VFL_DIR_M2M;
+	vfd_dec->device_caps	= V4L2_CAP_VIDEO_M2M_MPLANE |
+			V4L2_CAP_STREAMING;
+
+	snprintf(vfd_dec->name, sizeof(vfd_dec->name), "%s",
+		MTK_VCODEC_DEC_NAME);
+	video_set_drvdata(vfd_dec, dev);
+	dev->vfd_dec = vfd_dec;
+	platform_set_drvdata(pdev, dev);
+
+	dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	if (IS_ERR((__force void *)dev->alloc_ctx)) {
+		mtk_v4l2_err("Failed to alloc vb2 dma context 0");
+		ret = PTR_ERR((__force void *)dev->alloc_ctx);
+		goto err_vb2_ctx_init;
+	}
+
+	dev->m2m_dev_dec = v4l2_m2m_init(&mtk_vdec_m2m_ops);
+	if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
+		mtk_v4l2_err("Failed to init mem2mem dec device");
+		ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
+		goto err_dec_mem_init;
+	}
+
+	dev->decode_workqueue =
+		alloc_ordered_workqueue(MTK_VCODEC_DEC_NAME,
+			WQ_MEM_RECLAIM | WQ_FREEZABLE);
+	if (!dev->decode_workqueue) {
+		mtk_v4l2_err("Failed to create decode workqueue");
+		ret = -EINVAL;
+		goto err_event_workq;
+	}
+
+	ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 0);
+	if (ret) {
+		mtk_v4l2_err("Failed to register video device");
+		goto err_dec_reg;
+	}
+
+	/* Avoid the iommu eat big hunks */
+	dma_set_attr(DMA_ATTR_ALLOC_SINGLE_PAGES, &attrs);
+
+	mtk_v4l2_debug(0, "decoder registered as /dev/video%d",
+		vfd_dec->num);
+
+	return 0;
+
+err_dec_reg:
+	destroy_workqueue(dev->decode_workqueue);
+err_event_workq:
+	v4l2_m2m_release(dev->m2m_dev_dec);
+err_dec_mem_init:
+	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+err_vb2_ctx_init:
+	video_unregister_device(vfd_dec);
+err_dec_alloc:
+	v4l2_device_unregister(&dev->v4l2_dev);
+err_res:
+	mtk_vcodec_release_dec_pm(dev);
+	return ret;
+}
+
+static const struct of_device_id mtk_vcodec_match[] = {
+	{.compatible = "mediatek,mt8173-vcodec-dec",},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, mtk_vcodec_match);
+
+static int mtk_vcodec_dec_remove(struct platform_device *pdev)
+{
+	struct mtk_vcodec_dev *dev = platform_get_drvdata(pdev);
+
+	flush_workqueue(dev->decode_workqueue);
+	destroy_workqueue(dev->decode_workqueue);
+	if (dev->m2m_dev_dec)
+		v4l2_m2m_release(dev->m2m_dev_dec);
+	if (dev->alloc_ctx)
+		vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+
+	if (dev->vfd_dec)
+		video_unregister_device(dev->vfd_dec);
+
+	v4l2_device_unregister(&dev->v4l2_dev);
+	mtk_vcodec_release_dec_pm(dev);
+	return 0;
+}
+
+static int mtk_vcodec_vdec_pm_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mtk_vcodec_dev *m_dev = platform_get_drvdata(pdev);
+
+	mtk_v4l2_debug(3, "m_dev->num_instances=%d", m_dev->num_instances);
+
+	if (m_dev->num_instances == 0)
+		return 0;
+
+	return 0;
+}
+
+static int mtk_vcodec_vdec_pm_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct mtk_vcodec_dev *m_dev = platform_get_drvdata(pdev);
+
+	mtk_v4l2_debug(3, "m_dev->num_instances=%d", m_dev->num_instances);
+
+	if (m_dev->num_instances == 0)
+		return 0;
+
+	return 0;
+}
+
+static const struct dev_pm_ops mtk_vcodec_vdec_pm_ops = {
+	SET_RUNTIME_PM_OPS(mtk_vcodec_vdec_pm_runtime_suspend,
+			   mtk_vcodec_vdec_pm_runtime_resume,
+			   NULL)
+};
+
+static struct platform_driver mtk_vcodec_dec_driver = {
+	.probe	= mtk_vcodec_probe,
+	.remove	= mtk_vcodec_dec_remove,
+	.driver	= {
+		.name	= MTK_VCODEC_DEC_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = mtk_vcodec_match,
+		.pm = &mtk_vcodec_vdec_pm_ops,
+	},
+};
+
+module_platform_driver(mtk_vcodec_dec_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Mediatek video codec V4L2 driver");
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
new file mode 100644
index 0000000..3dfebb2
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -0,0 +1,154 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/clk.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <soc/mediatek/smi.h>
+
+#include "mtk_vcodec_dec_pm.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
+
+int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
+{
+	struct device_node *node;
+	struct platform_device *pdev;
+	struct device *dev;
+	struct mtk_vcodec_pm *pm;
+	int ret = 0;
+
+	pdev = mtkdev->plat_dev;
+	pm = &mtkdev->pm;
+	pm->mtkdev = mtkdev;
+	dev = &pdev->dev;
+	node = of_parse_phandle(dev->of_node, "mediatek,larb", 0);
+	if (!node)
+		return -1;
+
+	pdev = of_find_device_by_node(node);
+	if (WARN_ON(!pdev)) {
+		of_node_put(node);
+		return -1;
+	}
+	pm->larbvdec = &pdev->dev;
+
+	pdev = mtkdev->plat_dev;
+	pm_runtime_enable(&pdev->dev);
+	pm->dev = &pdev->dev;
+
+	pm->vcodecpll = devm_clk_get(&pdev->dev, "vcodecpll");
+	if (pm->vcodecpll == NULL) {
+		mtk_v4l2_err("devm_clk_get vcodecpll fail");
+		ret = -1;
+	}
+
+	pm->univpll_d2 = devm_clk_get(&pdev->dev, "univpll_d2");
+	if (pm->univpll_d2 == NULL) {
+		mtk_v4l2_err("devm_clk_get univpll_d2 fail");
+		ret = -1;
+	}
+
+	pm->clk_cci400_sel = devm_clk_get(&pdev->dev, "clk_cci400_sel");
+	if (pm->clk_cci400_sel == NULL) {
+		mtk_v4l2_err("devm_clk_get clk_cci400_sel fail");
+		ret = -1;
+	}
+
+	pm->vdec_sel = devm_clk_get(&pdev->dev, "vdec_sel");
+	if (pm->vdec_sel == NULL) {
+		mtk_v4l2_err("devm_clk_get vdec_sel fail");
+		ret = -1;
+	}
+
+	pm->vdecpll = devm_clk_get(&pdev->dev, "vdecpll");
+	if (pm->vdecpll == NULL) {
+		mtk_v4l2_err("devm_clk_get vdecpll fail");
+		ret = -1;
+	}
+
+	return ret;
+}
+
+void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
+{
+	pm_runtime_disable(dev->pm.dev);
+}
+
+void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
+{
+	int ret;
+
+	ret = pm_runtime_get_sync(pm->dev);
+	if (ret)
+		mtk_v4l2_err("pm_runtime_get_sync fail %d", ret);
+}
+
+void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm)
+{
+	int ret;
+
+	ret = pm_runtime_put_sync(pm->dev);
+	if (ret)
+		mtk_v4l2_err("pm_runtime_put_sync fail %d", ret);
+}
+
+void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)
+{
+	int ret;
+
+	clk_set_rate(pm->vcodecpll, 1482 * 1000000);
+
+	ret = clk_prepare_enable(pm->vcodecpll);
+	if (ret)
+		mtk_v4l2_err("vcodecpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->univpll_d2);
+	if (ret)
+		mtk_v4l2_err("univpll_d2 fail %d", ret);
+
+	ret = clk_prepare_enable(pm->clk_cci400_sel);
+	if (ret)
+		mtk_v4l2_err("clk_cci400_sel fail %d", ret);
+
+	ret = clk_set_parent(pm->clk_cci400_sel, pm->univpll_d2);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vdecpll);
+	if (ret)
+		mtk_v4l2_err("vdecpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vdec_sel);
+	if (ret)
+		mtk_v4l2_err("vdec_sel fail %d", ret);
+
+	ret = clk_set_parent(pm->vdec_sel, pm->vdecpll);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent fail %d", ret);
+
+	ret = mtk_smi_larb_get(pm->larbvdec);
+	if (ret)
+		mtk_v4l2_err("mtk_smi_larb_get larbvdec fail %d", ret);
+
+}
+
+void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm)
+{
+	mtk_smi_larb_put(pm->larbvdec);
+	clk_disable_unprepare(pm->vdec_sel);
+	clk_disable_unprepare(pm->vdecpll);
+}
+
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
new file mode 100644
index 0000000..b8bf56f
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MTK_VCODEC_DEC_PM_H_
+#define _MTK_VCODEC_DEC_PM_H_
+
+#include "mtk_vcodec_drv.h"
+
+int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *dev);
+void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev);
+
+void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm);
+void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm);
+void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm);
+void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm);
+
+#endif /* _MTK_VCODEC_DEC_PM_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index 78eee50..15a5093 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -26,10 +26,10 @@
 #include "mtk_vcodec_util.h"
 
 #define MTK_VCODEC_DRV_NAME	"mtk_vcodec_drv"
+#define MTK_VCODEC_DEC_NAME	"mtk-vcodec-dec" 
 #define MTK_VCODEC_ENC_NAME	"mtk-vcodec-enc"
 #define MTK_PLATFORM_STR	"platform:mt8173"
 
-
 #define MTK_VCODEC_MAX_PLANES	3
 #define MTK_V4L2_BENCHMARK	0
 #define WAIT_INTR_TIMEOUT_MS	1000
@@ -197,6 +197,30 @@ struct mtk_vcodec_pm {
 };
 
 /**
+ * struct vdec_pic_info  - picture size information
+ * @pic_w: picture width
+ * @pic_h: picture height
+ * @buf_w: picture buffer width (16 aligned up from pic_w)
+ * @buf_h: picture buffer heiht (32 aligned up from pic_h)
+ * @y_bs_sz: Y bitstream size
+ * @c_bs_sz: CbCr bitstream size
+ * @y_len_sz: Y length size
+ * @c_len_sz: CbCr length size
+ * E.g. suppose picture size is 176x144,
+ *      buffer size will be aligned to 176x160.
+ */
+struct vdec_pic_info {
+	unsigned int pic_w;
+	unsigned int pic_h;
+	unsigned int buf_w;
+	unsigned int buf_h;
+	unsigned int y_bs_sz;
+	unsigned int c_bs_sz;
+	unsigned int y_len_sz;
+	unsigned int c_len_sz;
+};
+
+/**
  * struct mtk_vcodec_ctx - Context (instance) private data.
  *
  * @type: type of the instance - decoder or encoder
@@ -210,9 +234,12 @@ struct mtk_vcodec_pm {
  * @state: state of the context
  * @param_change: indicate encode parameter type
  * @enc_params: encoding parameters
- * @enc_if: hoooked encoder driver interface
+ * @dec_if: hooked decoder driver interface
+ * @enc_if: hooked encoder driver interface
  * @drv_handle: driver handle for specific decode/encode instance
  *
+ * @picinfo: store picture info after header parsing
+ * @dpb_count: store dpb count after header parsing
  * @int_cond: variable used by the waitqueue
  * @int_type: type of the last interrupt
  * @queue: waitqueue that can be used to wait for this context to
@@ -220,7 +247,9 @@ struct mtk_vcodec_pm {
  * @irq_status: irq status
  *
  * @ctrl_hdl: handler for v4l2 framework
+ * @decode_work: worker for the decoding
  * @encode_work: worker for the encoding
+ * @last_decoded_picinfo: pic information get from latest decode
  *
  * @colorspace: enum v4l2_colorspace; supplemental to pixelformat
  * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
@@ -240,21 +269,29 @@ struct mtk_vcodec_ctx {
 	enum mtk_encode_param param_change;
 	struct mtk_enc_params enc_params;
 
+	struct vdec_common_if *dec_if;
 	struct venc_common_if *enc_if;
 	unsigned long drv_handle;
 
+	struct vdec_pic_info picinfo;
+	int dpb_count;
+
 	int int_cond;
 	int int_type;
 	wait_queue_head_t queue;
 	unsigned int irq_status;
 
 	struct v4l2_ctrl_handler ctrl_hdl;
+	struct work_struct decode_work;
 	struct work_struct encode_work;
+	struct vdec_pic_info last_decoded_picinfo;
 
 	enum v4l2_colorspace colorspace;
 	enum v4l2_ycbcr_encoding ycbcr_enc;
 	enum v4l2_quantization quantization;
 	enum v4l2_xfer_func xfer_func;
+
+	int decoded_frame_cnt;
 };
 
 /**
@@ -268,25 +305,48 @@ struct mtk_vcodec_ctx {
  * @alloc_ctx: VB2 allocator context
  *	       (for allocations without kernel mapping).
  * @ctx_list: list of struct mtk_vcodec_ctx
- * @irqlock: protect data access by irq handler and work thread
- * @curr_ctx: The context that is waiting for codec hardware
+ * @irqlock: protect data access by irq handler and work thread -- curr_ctx
+ * @curr_ctx: The context that is waiting for codec hardware. Protected by
+ *		irqlock and dec_mutex or enc_mutex.
  *
  * @reg_base: Mapped address of MTK Vcodec registers.
  *
- * @id_counter: used to identify current opened instance
+ * @id_counter:  An integer id given to the next opened instance
  * @num_instances: counter of active MTK Vcodec instances
  *
  * @encode_workqueue: encode work queue
  *
+ * @v4l2_dev: V4L2 device to register video devices for.
+ * @vfd_dec: Video device for decoder
+ * @vfd_enc: Video device for encoder
+ *
+ * @m2m_dev_dec: m2m device for decoder
+ * @m2m_dev_enc: m2m device for encoder
+ * @plat_dev: platform device
+ * @vpu_plat_dev: mtk vpu platform device
+ * @alloc_ctx:VB2 allocator context
+ *	      (for allocations without kernel mapping).
+ * @ctx_list: list of struct mtk_vcodec_ctx
+ * @irqlock: protect data access by irq handler and work thread
+ * @curr_ctx: The context that is waiting for codec hardware
+ * @reg_base: Mapped address of MTK Vcodec registers.
+ *
+ * @instance_mask: used to mark which index id are used
+ * @num_instances: counter of active MTK Vcodec instances
+ *
+ * @decode_workqueue: decode work queue
+ * @encode_workqueue: encode work queue
  * @int_cond: used to identify interrupt condition happen
  * @int_type: used to identify what kind of interrupt condition happen
  * @dev_mutex: video_device lock
  * @queue: waitqueue for waiting for completion of device commands
  *
+ * @dec_irq: decoder irq resource
  * @enc_irq: h264 encoder irq resource
- * @enc_lt_irq: vp8 encoder irq resource
+ * @enc_lt_irq: vp8 encoder lt irq resource
  *
- * @enc_mutex: encoder hardware lock.
+ * @dec_mutex: decoder hardware lock
+ * @enc_mutex: encoder hardware lock
  *
  * @pm: power management control
  * @dec_capability: used to identify decode capability, ex: 4k
@@ -294,8 +354,10 @@ struct mtk_vcodec_ctx {
  */
 struct mtk_vcodec_dev {
 	struct v4l2_device v4l2_dev;
+	struct video_device *vfd_dec;
 	struct video_device *vfd_enc;
-
+	
+	struct v4l2_m2m_dev *m2m_dev_dec;
 	struct v4l2_m2m_dev *m2m_dev_enc;
 	struct platform_device *plat_dev;
 	struct platform_device *vpu_plat_dev;
@@ -308,6 +370,7 @@ struct mtk_vcodec_dev {
 	unsigned long id_counter;
 	int num_instances;
 
+	struct workqueue_struct *decode_workqueue;
 	struct workqueue_struct *encode_workqueue;
 
 	int int_cond;
@@ -315,9 +378,11 @@ struct mtk_vcodec_dev {
 	struct mutex dev_mutex;
 	wait_queue_head_t queue;
 
+	int dec_irq;
 	int enc_irq;
 	int enc_lt_irq;
 
+	struct mutex dec_mutex;
 	struct mutex enc_mutex;
 
 	struct mtk_vcodec_pm pm;
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h
index 33e890f..fbb8b1e 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h
@@ -16,7 +16,7 @@
 #define _MTK_VCODEC_INTR_H_
 
 #define MTK_INST_IRQ_RECEIVED		0x1
-#define MTK_INST_WORK_THREAD_ABORT_DONE	0x2
+
 
 struct mtk_vcodec_ctx;
 
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
index 5e36513..70ec3ad 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
@@ -81,14 +81,14 @@ void mtk_vcodec_mem_free(struct mtk_vcodec_ctx *data,
 		return;
 	}
 
-	dma_free_coherent(dev, size, mem->va, mem->dma_addr);
-	mem->va = NULL;
-	mem->dma_addr = 0;
-	mem->size = 0;
-
 	mtk_v4l2_debug(3, "[%d]  - va      = %p", ctx->id, mem->va);
 	mtk_v4l2_debug(3, "[%d]  - dma     = 0x%lx", ctx->id,
 		       (unsigned long)mem->dma_addr);
 	mtk_v4l2_debug(3, "[%d]    size = 0x%lx", ctx->id, size);
+
+	dma_free_coherent(dev, size, mem->va, mem->dma_addr);
+	mem->va = NULL;
+	mem->dma_addr = 0;
+	mem->size = 0;
 }
 EXPORT_SYMBOL(mtk_vcodec_mem_free);
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_base.h b/drivers/media/platform/mtk-vcodec/vdec_drv_base.h
new file mode 100644
index 0000000..73ea1fe
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_base.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VDEC_DRV_BASE_
+#define _VDEC_DRV_BASE_
+
+#include "mtk_vcodec_drv.h"
+
+#include "vdec_drv_if.h"
+
+struct vdec_common_if {
+	/**
+	 * (*init)() - initialize decode driver
+	 * @ctx     : [in] mtk v4l2 context
+	 * @h_vdec  : [out] driver handle
+	 */
+	int (*init)(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec);
+
+	/**
+	 * (*decode)() - trigger decode
+	 * @h_vdec  : [in] driver handle
+	 * @bs      : [in] input bitstream
+	 * @fb      : [in] frame buffer to store decoded frame
+	 * @res_chg : [out] resolution change happen
+	 */
+	int (*decode)(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+		      struct vdec_fb *fb, bool *res_chg);
+
+	/**
+	 * (*get_param)() - get driver's parameter
+	 * @h_vdec : [in] driver handle
+	 * @type   : [in] input parameter type
+	 * @out    : [out] buffer to store query result
+	 */
+	int (*get_param)(unsigned long h_vdec, enum vdec_get_param_type type,
+			 void *out);
+
+	/**
+	 * (*deinit)() - deinitialize driver.
+	 * @h_vdec : [in] driver handle to be deinit
+	 */
+	int (*deinit)(unsigned long h_vdec);
+};
+
+#endif
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
new file mode 100644
index 0000000..1d12719
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *         Tiffany Lin <tiffany.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "vdec_drv_base.h"
+#include "vdec_drv_if.h"
+
+#include "mtk_vcodec_dec_pm.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
+
+int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
+{
+	int ret = 0;
+
+	switch (fourcc) {
+	case V4L2_PIX_FMT_H264:
+	case V4L2_PIX_FMT_VP8:
+	case V4L2_PIX_FMT_VP9:
+	default:
+		return -EINVAL;
+	}
+
+	mtk_vdec_lock(ctx);
+	mtk_vcodec_dec_clock_on(&ctx->dev->pm);
+	ret = ctx->dec_if->init(ctx, &ctx->drv_handle);
+	mtk_vcodec_dec_clock_off(&ctx->dev->pm);
+	mtk_vdec_unlock(ctx);
+
+	return ret;
+}
+
+int vdec_if_decode(struct mtk_vcodec_ctx *ctx, struct mtk_vcodec_mem *bs,
+		   struct vdec_fb *fb, bool *res_chg)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	if (bs) {
+		if ((bs->dma_addr & 63) != 0)
+			return -EINVAL;
+	}
+
+	if (fb) {
+		if (((fb->base_y.dma_addr & 511) != 0) ||
+		    ((fb->base_c.dma_addr & 511) != 0))
+			return -EINVAL;
+	}
+
+	mtk_vdec_lock(ctx);
+
+	spin_lock_irqsave(&ctx->dev->irqlock, flags);
+	ctx->dev->curr_ctx = ctx;
+	spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
+
+	mtk_vcodec_dec_clock_on(&ctx->dev->pm);
+	enable_irq(ctx->dev->dec_irq);
+	ret = ctx->dec_if->decode(ctx->drv_handle, bs, fb, res_chg);
+	disable_irq(ctx->dev->dec_irq);
+	mtk_vcodec_dec_clock_off(&ctx->dev->pm);
+
+	spin_lock_irqsave(&ctx->dev->irqlock, flags);
+	ctx->dev->curr_ctx = NULL;
+	spin_unlock_irqrestore(&ctx->dev->irqlock, flags);
+
+	mtk_vdec_unlock(ctx);
+
+	return ret;
+}
+
+int vdec_if_get_param(struct mtk_vcodec_ctx *ctx, enum vdec_get_param_type type,
+		      void *out)
+{
+	int ret = 0;
+
+	mtk_vdec_lock(ctx);
+	ret = ctx->dec_if->get_param(ctx->drv_handle, type, out);
+	mtk_vdec_unlock(ctx);
+
+	return ret;
+}
+
+int vdec_if_deinit(struct mtk_vcodec_ctx *ctx)
+{
+	int ret = 0;
+
+	if (ctx->drv_handle == 0)
+		return 0;
+
+	mtk_vdec_lock(ctx);
+	mtk_vcodec_dec_clock_on(&ctx->dev->pm);
+	ret = ctx->dec_if->deinit(ctx->drv_handle);
+	mtk_vcodec_dec_clock_off(&ctx->dev->pm);
+	mtk_vdec_unlock(ctx);
+
+	ctx->drv_handle = 0;
+	return ret;
+}
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_if.h b/drivers/media/platform/mtk-vcodec/vdec_drv_if.h
new file mode 100644
index 0000000..9717446
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_if.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *		   Tiffany Lin <tiffany.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VDEC_DRV_IF_H_
+#define _VDEC_DRV_IF_H_
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_dec.h"
+#include "mtk_vcodec_util.h"
+
+/**
+ * struct vdec_fb_status  - decoder frame buffer status
+ * @FB_ST_NORMAL	: initial state
+ * @FB_ST_DISPLAY	: frmae buffer is ready to be displayed
+ * @FB_ST_FREE		: frame buffer is not used by decoder any more
+ */
+enum vdec_fb_status {
+	FB_ST_NORMAL		= 0,
+	FB_ST_DISPLAY		= (1 << 0),
+	FB_ST_FREE		= (1 << 1)
+};
+
+enum vdec_get_param_type {
+	GET_PARAM_DISP_FRAME_BUFFER,
+	GET_PARAM_FREE_FRAME_BUFFER,
+	GET_PARAM_PIC_INFO,
+	GET_PARAM_CROP_INFO,
+	GET_PARAM_DPB_SIZE
+};
+
+/**
+ * struct vdec_fb_node  - decoder frame buffer node
+ * @list	: list to hold this node
+ * @fb		: point to frame buffer (vdec_fb)
+ */
+struct vdec_fb_node {
+	struct list_head list;
+	void *fb;
+};
+
+/**
+ * For the same vdec_handle, these functions below are not thread safe.
+ * For different vdec_handle, these functions can be called at the same time.
+ */
+
+/**
+ * vdec_if_init() - initialize decode driver
+ * @ctx      : [in] v4l2 context
+ * @fourcc   : [in] video format fourcc, V4L2_PIX_FMT_H264/VP8/VP9..
+ */
+int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc);
+
+/**
+ * vdec_if_deinit() - deinitialize decode driver
+ * @ctx : [in] v4l2 context
+ *
+ */
+int vdec_if_deinit(struct mtk_vcodec_ctx *ctx);
+
+/**
+ * vdec_if_decode() - trigger decode
+ * @handle  : [in] video decode handle
+ * @bs      : [in] input bitstream
+ * @fb      : [in] frame buffer to store decoded frame
+ * @res_chg : [out] resolution change happen
+ *
+ * while EOF flush decode, need to set input bitstream as NULL
+ */
+int vdec_if_decode(struct mtk_vcodec_ctx *ctx, struct mtk_vcodec_mem *bs,
+		   struct vdec_fb *fb, bool *res_chg);
+
+/**
+ * vdec_if_get_param() - get driver's parameter
+ * @handle : [in] video decode handle
+ * @type   : [in] input parameter type
+ * @out    : [out] buffer to store query result
+ */
+int vdec_if_get_param(struct mtk_vcodec_ctx *ctx, enum vdec_get_param_type type,
+		      void *out);
+
+#endif
diff --git a/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h b/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
new file mode 100644
index 0000000..66e5b47
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VDEC_IPI_MSG_H_
+#define _VDEC_IPI_MSG_H_
+
+/**
+ * enum vdec_ipi_msgid - message id between AP and VPU
+ * @AP_IPIMSG_XXX:		AP to VPU cmd message id
+ * @VPU_IPIMSG_XXX_DONE:	VPU ack AP cmd message id
+ */
+enum vdec_ipi_msgid {
+	AP_IPIMSG_DEC_INIT = 0xA000,
+	AP_IPIMSG_DEC_START = 0xA001,
+	AP_IPIMSG_DEC_END = 0xA002,
+	AP_IPIMSG_DEC_DEINIT = 0xA003,
+	AP_IPIMSG_DEC_RESET = 0xA004,
+
+	VPU_IPIMSG_DEC_INIT_ACK = 0xB000,
+	VPU_IPIMSG_DEC_START_ACK = 0xB001,
+	VPU_IPIMSG_DEC_END_ACK = 0xB002,
+	VPU_IPIMSG_DEC_DEINIT_ACK = 0xB003,
+	VPU_IPIMSG_DEC_RESET_ACK = 0xB004,
+};
+
+/**
+ * struct vdec_ap_ipi_cmd - generic AP to VPU ipi command format
+ * @msg_id        : vdec_ipi_msgid
+ * @vpu_inst_addr : VPU decoder instance address
+ */
+struct vdec_ap_ipi_cmd {
+	uint32_t msg_id;
+	uint32_t vpu_inst_addr;
+};
+
+/**
+ * struct vdec_vpu_ipi_ack - generic VPU to AP ipi command format
+ * @msg_id       : vdec_ipi_msgid
+ * @status       : VPU exeuction result
+ * @ap_inst_addr : AP video decoder instance address
+ */
+struct vdec_vpu_ipi_ack {
+	uint32_t msg_id;
+	int32_t status;
+	uint64_t ap_inst_addr;
+};
+
+/**
+ * struct vdec_ap_ipi_init - for AP_IPIMSG_DEC_INIT
+ * @msg_id       : AP_IPIMSG_DEC_INIT
+ * @reserved     : Reserved field
+ * @ap_inst_addr : AP video decoder instance address
+ */
+struct vdec_ap_ipi_init {
+	uint32_t msg_id;
+	uint32_t reserved;
+	uint64_t ap_inst_addr;
+};
+
+/**
+ * struct vdec_ap_ipi_dec_start - for AP_IPIMSG_DEC_START
+ * @msg_id        : AP_IPIMSG_DEC_START
+ * @vpu_inst_addr : VPU decoder instance address
+ * @data          : Header info
+ *                  H264 decoder [0]:buf_sz [1]:nal_start
+ *                  VP8 decoder  [0]:width/height
+ *                  VP9 decoder  [0]:profile, [1][2] width/height
+ * @reserved      : Reserved field
+ */
+struct vdec_ap_ipi_dec_start {
+	uint32_t msg_id;
+	uint32_t vpu_inst_addr;
+	uint32_t data[3];
+	uint32_t reserved;
+};
+
+/**
+ * struct vdec_vpu_ipi_init_ack - for VPU_IPIMSG_DEC_INIT_ACK
+ * @msg_id		: VPU_IPIMSG_DEC_INIT_ACK
+ * @status		: VPU exeuction result
+ * @ap_inst_addr	: AP vcodec_vpu_inst instance address
+ * @vpu_inst_addr	: VPU decoder instance address
+ */
+struct vdec_vpu_ipi_init_ack {
+	uint32_t msg_id;
+	int32_t status;
+	uint64_t ap_inst_addr;
+	uint32_t vpu_inst_addr;
+};
+
+#endif
-- 
1.7.9.5



From ynorov at caviumnetworks.com  Thu May 12 04:26:54 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 12 May 2016 14:26:54 +0300
Subject: [PATCH] arm64: fix current_thread_info()->addr_limit setup
Message-ID: <1463052414-29033-1-git-send-email-ynorov@caviumnetworks.com>

At elf loading in flush_old_exec() in fs/exec.c, generic code sets
current_thread_info()->addr_limit to one that corresponds aarch64 value,
and ignores compat mode there as corresponding status setup happens
later on in load_elf_binary() by SET_PERSONALITY() macro. As result,
compat task has wrong addr_limit, and it may cause various bugs.

This patch fixes it. It also fixes USER_DS macro to return different
values depending on compat at runtime.

It was discovered during ilp32 development. See details here:
https://lkml.org/lkml/2016/5/11/975

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/include/asm/elf.h     | 11 +++++++++--
 arch/arm64/include/asm/uaccess.h |  2 +-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 24ed037..fda75ce 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -138,7 +138,10 @@ typedef struct user_fpsimd_state elf_fpregset_t;
  */
 #define ELF_PLAT_INIT(_r, load_addr)	(_r)->regs[0] = 0
 
-#define SET_PERSONALITY(ex)		clear_thread_flag(TIF_32BIT);
+#define SET_PERSONALITY(ex) do {					\
+	clear_thread_flag(TIF_32BIT);					\
+	set_fs(TASK_SIZE_64);						\
+} while (0)
 
 #define ARCH_DLINFO							\
 do {									\
@@ -181,7 +184,11 @@ typedef compat_elf_greg_t		compat_elf_gregset_t[COMPAT_ELF_NGREG];
 					 ((x)->e_flags & EF_ARM_EABI_MASK))
 
 #define compat_start_thread		compat_start_thread
-#define COMPAT_SET_PERSONALITY(ex)	set_thread_flag(TIF_32BIT);
+#define COMPAT_SET_PERSONALITY(ex) do {					\
+	set_thread_flag(TIF_32BIT);					\
+	set_fs(TASK_SIZE_32);						\
+} while (0)
+
 #define COMPAT_ARCH_DLINFO
 extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
 				      int uses_interp);
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 0685d74..5b269e6 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -60,7 +60,7 @@ extern int fixup_exception(struct pt_regs *regs);
 #define KERNEL_DS	(-1UL)
 #define get_ds()	(KERNEL_DS)
 
-#define USER_DS		TASK_SIZE_64
+#define USER_DS		TASK_SIZE
 #define get_fs()	(current_thread_info()->addr_limit)
 
 static inline void set_fs(mm_segment_t fs)
-- 
2.5.0



From rafael at kernel.org  Thu May 12 04:27:23 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Thu, 12 May 2016 13:27:23 +0200
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <CAKc_7PW8BqQSTn01zDVsec4KXunQUKfcEft8=MH-E0xsmheo3w@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
 <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>
 <20160511101101.GA16101@red-moon>
 <CAJZ5v0hgw929W5PjF0PqT+ssiOHd8TeJoSQcz4NUiAovZY2pfQ@mail.gmail.com>
 <20160511224314.GD28812@localhost>
 <CAKc_7PW8BqQSTn01zDVsec4KXunQUKfcEft8=MH-E0xsmheo3w@mail.gmail.com>
Message-ID: <CAJZ5v0jOAOWLNab0vMOVyciwOhtkuPdqZt3wkFbprq+PkEQNVg@mail.gmail.com>

On Thu, May 12, 2016 at 12:43 PM, Jayachandran C <jchandra at broadcom.com> wrote:
> On Thu, May 12, 2016 at 4:13 AM, Bjorn Helgaas <helgaas at kernel.org> wrote:
>> On Wed, May 11, 2016 at 10:30:51PM +0200, Rafael J. Wysocki wrote:
>>> On Wed, May 11, 2016 at 12:11 PM, Lorenzo Pieralisi
>>> <lorenzo.pieralisi at arm.com> wrote:
>>> > On Tue, May 10, 2016 at 08:37:00PM +0200, Rafael J. Wysocki wrote:
>>> >> On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:

[cut]

>
> If we are moving the ACPI/PCI code from drivers/acpi to
> arch/arm64/ , there is an issue in having the header file
> ecam.h in drivers/pci
>
> The current include of "../pci/ecam.h" is slightly ugly (Arnd
> and David had already noted this), but including the driver
> header from arch code would be even worse.
>
> I can either merge ecam.h into include/linux/pci.h
> or move it to a new file include/linux/pci-ecam.h, any
> suggestion on which is preferable?

My preference would be pci-ecam.h as we did a similar thing for
pci-dma.h, for example, but basically this is up to Bjorn.


From agraf at suse.de  Thu May 12 04:44:01 2016
From: agraf at suse.de (Alexander Graf)
Date: Thu, 12 May 2016 13:44:01 +0200
Subject: [PATCH] ZynqMP: Align gic ranges for 64k in device tree
Message-ID: <1463053441-57572-1-git-send-email-agraf@suse.de>

The GIC ranges in the zynqmp device tree are only 4kb aligned. Since
commit 12e14066f we automatically deal with aliases GIC regions though,
so we can map them transparently into guests even on 64kb page size
systems.

This patch makes use of that features and sets GICC and GICV to 64kb
aligned and sized regions.

Signed-off-by: Alexander Graf <agraf at suse.de>
---
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index e595f22..38c4310 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -81,9 +81,9 @@
 			compatible = "arm,gic-400", "arm,cortex-a15-gic";
 			#interrupt-cells = <3>;
 			reg = <0x0 0xf9010000 0x10000>,
-			      <0x0 0xf902f000 0x2000>,
+			      <0x0 0xf9020000 0x20000>,
 			      <0x0 0xf9040000 0x20000>,
-			      <0x0 0xf906f000 0x2000>;
+			      <0x0 0xf9060000 0x20000>;
 			interrupt-controller;
 			interrupt-parent = <&gic>;
 			interrupts = <1 9 0xf04>;
-- 
1.8.5.6



From christoffer.dall at linaro.org  Thu May 12 04:46:51 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 13:46:51 +0200
Subject: [PATCH v3 17/55] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <1462531568-9799-18-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-18-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512114651.GB2370@cbox>

On Fri, May 06, 2016 at 11:45:30AM +0100, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Implement the framework for syncing IRQs between our emulation and
> the list registers, which represent the guest's view of IRQs.
> This is done in kvm_vgic_flush_hwstate and kvm_vgic_sync_hwstate,
> which gets called on guest entry and exit.
> The code talking to the actual GICv2/v3 hardware is added in the
> following patches.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---

[...]

> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 4fb20fd..c6f8b9b 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c

[...]

> +
> +/* Requires the VCPU's ap_list_lock to be held. */
> +static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq;
> +	int count = 0;
> +
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
> +
> +	if (unlikely(!vcpu->kvm->arch.vgic.enabled))
> +		goto out_clean;


I know I said I reviewed this, but thinking about this more carefully,
doesn't the enable bit actually tell us if forwarding of pending
interrupts is enabled, but not whether or not the vgic exists?

So you could imagine a guest that turns off the GIC, but still has
active interrupts that it wants to disable/EOI, in the case of
shutdown/reboot for example, or is this architecturally not allowed?

If it is, then we should, at least theoretically, still forward active
interrupts in LRs despite the enabled bit being clear, but modify the
oracle to take the global enable bit into account.

Thanks,
-Christoffer

> +
> +	if (compute_ap_list_depth(vcpu) > kvm_vgic_global_state.nr_lr) {
> +		vgic_set_underflow(vcpu);
> +		vgic_sort_ap_list(vcpu);
> +	}
> +
> +	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
> +		spin_lock(&irq->irq_lock);
> +
> +		if (unlikely(vgic_target_oracle(irq) != vcpu))
> +			goto next;
> +
> +		/*
> +		 * If we get an SGI with multiple sources, try to get
> +		 * them in all at once.
> +		 */
> +		do {
> +			vgic_populate_lr(vcpu, irq, count++);
> +		} while (irq->source && count < kvm_vgic_global_state.nr_lr);
> +
> +next:
> +		spin_unlock(&irq->irq_lock);
> +
> +		if (count == kvm_vgic_global_state.nr_lr)
> +			break;
> +	}
> +
> +out_clean:
> +	vcpu->arch.vgic_cpu.used_lrs = count;
> +
> +	/* Nuke remaining LRs */
> +	for ( ; count < kvm_vgic_global_state.nr_lr; count++)
> +		vgic_clear_lr(vcpu, count);
> +}
> +


From christoffer.dall at linaro.org  Thu May 12 04:47:03 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 13:47:03 +0200
Subject: [PATCH v3 33/55] KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR, 
 TYPER handlers
In-Reply-To: <1462531568-9799-34-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-34-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512114703.GD27623@cbox>

On Fri, May 06, 2016 at 11:45:46AM +0100, Andre Przywara wrote:
> As in the GICv2 emulation we handle those three registers in one
> function.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - kick VCPUs if distributor gets enabled
> 
> Changelog v1 .. v2:
> - rewrite write handler to use switch statement
> 
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 50 +++++++++++++++++++++++++++++++++++++++-
>  virt/kvm/arm/vgic/vgic.h         |  2 ++
>  2 files changed, 51 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index 06c7ec5..5f4558c 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -22,6 +22,54 @@
>  #include "vgic.h"
>  #include "vgic-mmio.h"
>  
> +static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
> +					    gpa_t addr, unsigned int len)
> +{
> +	u32 value = 0;
> +
> +	switch (addr & 0x0c) {
> +	case GICD_CTLR:
> +		if (vcpu->kvm->arch.vgic.enabled)
> +			value |= GICD_CTLR_ENABLE_SS_G1;
> +		value |= GICD_CTLR_ARE_NS | GICD_CTLR_DS;
> +		break;
> +	case GICD_TYPER:
> +		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
> +		value = (value >> 5) - 1;
> +		value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19;
> +		break;
> +	case GICD_IIDR:
> +		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
> +		break;
> +	default:
> +		return 0;
> +	}
> +
> +	return extract_bytes(value, addr & 3, len);

why do we return extract_bytes here?  This register can only be accessed
in full with a 32-bit aligned access, right?

> +}
> +
> +static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len,
> +				    unsigned long val)
> +{
> +	switch (addr & 0x0c) {
> +	case GICD_CTLR:
> +		if (!(addr & 1)) {

obviously same question as on the v2 counterpart

> +			struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
> +			bool was_enabled = dist->enabled;
> +
> +			dist->enabled = val & GICD_CTLR_ENABLE_SS_G1;
> +
> +			if (!was_enabled && dist->enabled)
> +				vgic_kick_vcpus(vcpu->kvm);
> +		}
> +		break;
> +	case GICD_TYPER:
> +	case GICD_IIDR:
> +		return;
> +	}
> +}
> +
>  /*
>   * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
>   * redistributors, while SPIs are covered by registers in the distributor
> @@ -46,7 +94,7 @@
>  
>  static const struct vgic_register_region vgic_v3_dist_registers[] = {
>  	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
> +		vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc, 16),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 39a8a65..635e2e2 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -19,6 +19,8 @@
>  #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
>  #define IMPLEMENTER_ARM		0x43b
>  
> +#define INTERRUPT_ID_BITS_SPIS	10
> +
>  #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
>  
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
> -- 
> 2.7.3
> 


From yt.shen at mediatek.com  Thu May 12 04:49:53 2016
From: yt.shen at mediatek.com (yt.shen at mediatek.com)
Date: Thu, 12 May 2016 19:49:53 +0800
Subject: [RFC 1/3] dt-bindings: drm/mediatek: Add display binding for Mediatek
 SoC MT2701
In-Reply-To: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
References: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
Message-ID: <1463053795-55455-2-git-send-email-yt.shen@mediatek.com>

From: YT Shen <yt.shen at mediatek.com>

Add device tree binding documentation for the display subsystem in
Mediatek SoC MT2701

Signed-off-by: YT Shen <yt.shen at mediatek.com>
---
 .../bindings/display/mediatek/mediatek,disp.txt    |    1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
index db6e77e..53b3cc3 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
@@ -40,6 +40,7 @@ Required properties (all function blocks):
 	"mediatek,<chip>-dpi"        - DPI controller, see mediatek,dpi.txt
 	"mediatek,<chip>-disp-mutex" - display mutex
 	"mediatek,<chip>-disp-od"    - overdrive
+	"mediatek,<chip>-disp-bls"   - backlight
 - reg: Physical base address and length of the function block register space
 - interrupts: The interrupt signal from the function block (required, except for
   merge and split function blocks).
-- 
1.7.9.5



From yt.shen at mediatek.com  Thu May 12 04:49:55 2016
From: yt.shen at mediatek.com (yt.shen at mediatek.com)
Date: Thu, 12 May 2016 19:49:55 +0800
Subject: [RFC 3/3] arm: dts: mt2701: Add display subsystem related nodes for
 MT2701
In-Reply-To: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
References: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
Message-ID: <1463053795-55455-4-git-send-email-yt.shen@mediatek.com>

From: YT Shen <yt.shen at mediatek.com>

This patch adds the device nodes for the DISP function blocks for MT2701

Signed-off-by: YT Shen <yt.shen at mediatek.com>
---
 arch/arm/boot/dts/mt2701.dtsi |  117 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 117 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 363de0d..0beef2a 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -24,6 +24,13 @@
 	compatible = "mediatek,mt2701";
 	interrupt-parent = <&sysirq>;
 
+	aliases {
+		rdma0 = &rdma0;
+		rdma1 = &rdma1;
+		dpi0 = &dpi0;
+		dpi1 = &dpi1;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -171,6 +178,14 @@
 		power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
 	};
 
+	mipi_tx0: mipi-dphy at 10010000 {
+		compatible = "mediatek,mt2701-mipi-tx";
+		reg = <0 0x10010000 0 0x90>;
+		clocks = <&clk26m>;
+		clock-output-names = "mipi_tx0_pll";
+		status = "disabled";
+	};
+
 	sysirq: interrupt-controller at 10200100 {
 		compatible = "mediatek,mt2701-sysirq",
 			     "mediatek,mt6577-sysirq";
@@ -255,6 +270,79 @@
 		status = "disabled";
 	};
 
+	ovl at 14007000 {
+		compatible = "mediatek,mt2701-disp-ovl";
+		reg = <0 0x14007000 0 0x1000>;
+		interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DISP_OVL>;
+		iommus = <&iommu MT2701_M4U_PORT_DISP_OVL_0>;
+		mediatek,larb = <&larb0>;
+	};
+
+	rdma0: rdma at 14008000 {
+		compatible = "mediatek,mt2701-disp-rdma";
+		reg = <0 0x14008000 0 0x1000>;
+		interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DISP_RDMA>;
+		iommus = <&iommu MT2701_M4U_PORT_DISP_RDMA>;
+		mediatek,larb = <&larb0>;
+	};
+
+	wdma at 14009000 {
+		compatible = "mediatek,mt2701-disp-wdma";
+		reg = <0 0x14009000 0 0x1000>;
+		interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DISP_WDMA>;
+		iommus = <&iommu MT2701_M4U_PORT_DISP_WDMA>;
+		mediatek,larb = <&larb0>;
+	};
+
+	bls at 1400a000 {
+		compatible = "mediatek,mt2701-disp-bls";
+		reg = <0 0x1400a000 0 0x1000>;
+		interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DISP_BLS>;
+	};
+
+	color at 1400b000 {
+		compatible = "mediatek,mt2701-disp-color";
+		reg = <0 0x1400b000 0 0x1000>;
+		interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DISP_COLOR>;
+	};
+
+	dsi0: dsi at 1400c000 {
+		compatible = "mediatek,mt2701-dsi";
+		reg = <0 0x1400c000 0 0x1000>;
+		interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DSI_ENGINE>, <&mmsys CLK_MM_DSI_DIG>,
+			 <&mipi_tx0>;
+		clock-names = "engine", "digital", "hs";
+		phys = <&mipi_tx0>;
+		phy-names = "dphy";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	dpi0: dpi at 1400d000 {
+		compatible = "mediatek,mt2701-dpi";
+		reg = <0 0x1400d000 0 0x1000>;
+		interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DPI_DIGL>,
+			 <&mmsys CLK_MM_DPI_ENGINE>;
+		clock-names = "clk_dpi_digl",
+			      "clk_dpi_engine";
+		status = "disabled";
+	};
+
+	mutex: mutex at 1400e000 {
+		compatible = "mediatek,mt2701-disp-mutex";
+		reg = <0 0x1400e000 0 0x1000>;
+		interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_MUTEX_32K>;
+	};
+
 	larb0: larb at 14010000 {
 		compatible = "mediatek,mt2701-smi-larb";
 		reg = <0 0x14010000 0 0x1000>;
@@ -265,6 +353,35 @@
 		power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
 	};
 
+	rdma1: rdma at 14012000 {
+		compatible = "mediatek,mt2701-disp-rdma";
+		reg = <0 0x14012000 0 0x1000>;
+		interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DISP_RDMA1>;
+		iommus = <&iommu MT2701_M4U_PORT_DISP_RDMA1>;
+		mediatek,larb = <&larb0>;
+	};
+
+	ufoe at 14013000 {
+		compatible = "mediatek,mt2701-disp-ufoe";
+		reg = <0 0x14013000 0 0x1000>;
+		clocks = <&mmsys CLK_MM_DISP_UFOE>;
+	};
+
+	dpi1: dpi at 14014000 {
+		compatible = "mediatek,mt2701-dpi";
+		reg = <0 0x14014000 0 0x1000>;
+		interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DPI1_DIGL>,
+			 <&mmsys CLK_MM_DPI1_ENGINE>,
+			 <&topckgen CLK_TOP_DPI1_SEL>,
+			 <&topckgen CLK_TOP_TVDPLL>,
+			 <&topckgen CLK_TOP_TVDPLL_D2>,
+			 <&topckgen CLK_TOP_TVDPLL_D4>;
+		clock-names = "pixel", "engine", "sel","div1","div2","div4";
+		status = "disabled";
+	};
+
 	imgsys: syscon at 15000000 {
 		compatible = "mediatek,mt2701-imgsys", "syscon";
 		reg = <0 0x15000000 0 0x1000>;
-- 
1.7.9.5



From yt.shen at mediatek.com  Thu May 12 04:49:54 2016
From: yt.shen at mediatek.com (yt.shen at mediatek.com)
Date: Thu, 12 May 2016 19:49:54 +0800
Subject: [RFC 2/3] drm/mediatek: add support for Mediatek SoC MT2701
In-Reply-To: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
References: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
Message-ID: <1463053795-55455-3-git-send-email-yt.shen@mediatek.com>

From: YT Shen <yt.shen at mediatek.com>

This patch add support for the Mediatek MT2701 DISP subsystem.
There is only one OVL engine in MT2701, and we have shadow
register support here.

Signed-off-by: YT Shen <yt.shen at mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c     |   49 ++++++---
 drivers/gpu/drm/mediatek/mtk_disp_rdma.c    |   36 +++++--
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c     |   78 +++++++++-----
 drivers/gpu/drm/mediatek/mtk_drm_ddp.c      |  151 ++++++++++++++++++++-------
 drivers/gpu/drm/mediatek/mtk_drm_ddp.h      |    2 +
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c |   63 +++++++++--
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |   15 +++
 drivers/gpu/drm/mediatek/mtk_drm_drv.c      |   72 +++++++++++--
 drivers/gpu/drm/mediatek/mtk_drm_drv.h      |    9 ++
 drivers/gpu/drm/mediatek/mtk_drm_gem.c      |    4 +
 10 files changed, 373 insertions(+), 106 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 8f62671f..e4a10bd6 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -40,8 +40,6 @@
 #define	OVL_RDMA_MEM_GMC	0x40402020
 
 #define OVL_CON_BYTE_SWAP	BIT(24)
-#define OVL_CON_CLRFMT_RGB565	(0 << 12)
-#define OVL_CON_CLRFMT_RGB888	(1 << 12)
 #define OVL_CON_CLRFMT_RGBA8888	(2 << 12)
 #define OVL_CON_CLRFMT_ARGB8888	(3 << 12)
 #define	OVL_CON_AEN		BIT(8)
@@ -136,18 +134,18 @@ static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx)
 	writel(0x0, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx));
 }
 
-static unsigned int ovl_fmt_convert(unsigned int fmt)
+static unsigned int ovl_fmt_convert(struct mtk_ddp_comp *comp, unsigned int fmt)
 {
 	switch (fmt) {
 	default:
 	case DRM_FORMAT_RGB565:
-		return OVL_CON_CLRFMT_RGB565;
+		return comp->data->ovl.fmt_rgb565;
 	case DRM_FORMAT_BGR565:
-		return OVL_CON_CLRFMT_RGB565 | OVL_CON_BYTE_SWAP;
+		return comp->data->ovl.fmt_rgb565 | OVL_CON_BYTE_SWAP;
 	case DRM_FORMAT_RGB888:
-		return OVL_CON_CLRFMT_RGB888;
+		return comp->data->ovl.fmt_rgb888;
 	case DRM_FORMAT_BGR888:
-		return OVL_CON_CLRFMT_RGB888 | OVL_CON_BYTE_SWAP;
+		return comp->data->ovl.fmt_rgb888 | OVL_CON_BYTE_SWAP;
 	case DRM_FORMAT_RGBX8888:
 	case DRM_FORMAT_RGBA8888:
 		return OVL_CON_CLRFMT_ARGB8888;
@@ -177,7 +175,7 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
 	if (!pending->enable)
 		mtk_ovl_layer_off(comp, idx);
 
-	con = ovl_fmt_convert(fmt);
+	con = ovl_fmt_convert(comp, fmt);
 	if (idx != 0)
 		con |= OVL_CON_AEN | OVL_CON_ALPHA;
 
@@ -185,7 +183,7 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
 	writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx));
 	writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx));
 	writel_relaxed(offset, comp->regs + DISP_REG_OVL_OFFSET(idx));
-	writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(idx));
+	writel_relaxed(addr, comp->regs + (comp->data->ovl.addr_offset + idx * 0x20));
 
 	if (pending->enable)
 		mtk_ovl_layer_on(comp, idx);
@@ -233,6 +231,32 @@ static const struct component_ops mtk_disp_ovl_component_ops = {
 	.unbind = mtk_disp_ovl_unbind,
 };
 
+static struct mtk_ddp_comp_driver_data mt2701_ovl_driver_data = {
+	.ovl = {0x0040, 1 << 12, 0}
+};
+
+static struct mtk_ddp_comp_driver_data mt8173_ovl_driver_data = {
+	.ovl = {0x0f40, 0, 1 << 12}
+};
+
+static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt2701-disp-ovl",
+	  .data = &mt2701_ovl_driver_data},
+	{ .compatible = "mediatek,mt8173-disp-ovl",
+	  .data = &mt8173_ovl_driver_data},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
+
+static inline struct mtk_ddp_comp_driver_data *mtk_ovl_get_driver_data(
+	struct platform_device *pdev)
+{
+	const struct of_device_id *of_id =
+		of_match_device(mtk_disp_ovl_driver_dt_match, &pdev->dev);
+
+	return (struct mtk_ddp_comp_driver_data *)of_id->data;
+}
+
 static int mtk_disp_ovl_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -269,6 +293,8 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	priv->ddp_comp.data = mtk_ovl_get_driver_data(pdev);
+
 	platform_set_drvdata(pdev, priv);
 
 	ret = component_add(dev, &mtk_disp_ovl_component_ops);
@@ -285,11 +311,6 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
-	{ .compatible = "mediatek,mt8173-disp-ovl", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
 
 struct platform_driver mtk_disp_ovl_driver = {
 	.probe		= mtk_disp_ovl_probe,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index 5fb80cb..41a6f36 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -122,7 +122,7 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width,
 	 */
 	threshold = width * height * vrefresh * 4 * 7 / 1000000;
 	reg = RDMA_FIFO_UNDERFLOW_EN |
-	      RDMA_FIFO_PSEUDO_SIZE(SZ_8K) |
+	      RDMA_FIFO_PSEUDO_SIZE(comp->data->rdma_fifo_pseudo_size) |
 	      RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold);
 	writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON);
 }
@@ -167,6 +167,32 @@ static const struct component_ops mtk_disp_rdma_component_ops = {
 	.unbind = mtk_disp_rdma_unbind,
 };
 
+static struct mtk_ddp_comp_driver_data mt2701_rdma_driver_data = {
+	.rdma_fifo_pseudo_size = SZ_4K,
+};
+
+static struct mtk_ddp_comp_driver_data mt8173_rdma_driver_data = {
+	.rdma_fifo_pseudo_size = SZ_8K,
+};
+
+static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt2701-disp-rdma",
+	  .data = &mt2701_rdma_driver_data},
+	{ .compatible = "mediatek,mt8173-disp-rdma",
+	  .data = &mt8173_rdma_driver_data},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
+
+static inline struct mtk_ddp_comp_driver_data *mtk_rdma_get_driver_data(
+	struct platform_device *pdev)
+{
+	const struct of_device_id *of_id =
+		of_match_device(mtk_disp_rdma_driver_dt_match, &pdev->dev);
+
+	return (struct mtk_ddp_comp_driver_data *)of_id->data;
+}
+
 static int mtk_disp_rdma_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -196,6 +222,8 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	priv->ddp_comp.data = mtk_rdma_get_driver_data(pdev);
+
 	/* Disable and clear pending interrupts */
 	writel(0x0, priv->ddp_comp.regs + DISP_REG_RDMA_INT_ENABLE);
 	writel(0x0, priv->ddp_comp.regs + DISP_REG_RDMA_INT_STATUS);
@@ -223,12 +251,6 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
-	{ .compatible = "mediatek,mt8173-disp-rdma", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
-
 struct platform_driver mtk_disp_rdma_driver = {
 	.probe		= mtk_disp_rdma_probe,
 	.remove		= mtk_disp_rdma_remove,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 3095fc1..6ecd35b 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -315,6 +315,42 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
 	pm_runtime_put(drm->dev);
 }
 
+static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
+{
+	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+	struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
+	struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
+	unsigned int i;
+
+	/*
+	 * TODO: instead of updating the registers here, we should prepare
+	 * working registers in atomic_commit and let the hardware command
+	 * queue update module registers on vblank.
+	 */
+	if (state->pending_config) {
+		mtk_ddp_comp_config(ovl, state->pending_width,
+				    state->pending_height,
+				    state->pending_vrefresh);
+
+		state->pending_config = false;
+	}
+
+	if (mtk_crtc->pending_planes) {
+		for (i = 0; i < OVL_LAYER_NR; i++) {
+			struct drm_plane *plane = &mtk_crtc->planes[i].base;
+			struct mtk_plane_state *plane_state;
+
+			plane_state = to_mtk_plane_state(plane->state);
+
+			if (plane_state->pending.config) {
+				mtk_ddp_comp_layer_config(ovl, i, plane_state);
+				plane_state->pending.config = false;
+			}
+		}
+		mtk_crtc->pending_planes = false;
+	}
+}
+
 static void mtk_drm_crtc_enable(struct drm_crtc *crtc)
 {
 	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
@@ -375,6 +411,7 @@ static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc,
 {
 	struct mtk_crtc_state *state = to_mtk_crtc_state(crtc->state);
 	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+	struct mtk_drm_private *priv = crtc->dev->dev_private;
 
 	if (mtk_crtc->event && state->base.event)
 		DRM_ERROR("new event while there is still a pending event\n");
@@ -385,12 +422,16 @@ static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc,
 		mtk_crtc->event = state->base.event;
 		state->base.event = NULL;
 	}
+
+	if (priv->data->shadow_register)
+		mtk_disp_mutex_acquire(mtk_crtc->mutex);
 }
 
 static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
 				      struct drm_crtc_state *old_crtc_state)
 {
 	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+	struct mtk_drm_private *priv = crtc->dev->dev_private;
 	unsigned int pending_planes = 0;
 	int i;
 
@@ -409,6 +450,11 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
 	}
 	if (pending_planes)
 		mtk_crtc->pending_planes = true;
+
+	if (priv->data->shadow_register) {
+		mtk_crtc_ddp_config(crtc);
+		mtk_disp_mutex_release(mtk_crtc->mutex);
+	}
 }
 
 static const struct drm_crtc_funcs mtk_crtc_funcs = {
@@ -453,36 +499,10 @@ err_cleanup_crtc:
 void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl)
 {
 	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
-	struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
-	unsigned int i;
+	struct mtk_drm_private *priv = crtc->dev->dev_private;
 
-	/*
-	 * TODO: instead of updating the registers here, we should prepare
-	 * working registers in atomic_commit and let the hardware command
-	 * queue update module registers on vblank.
-	 */
-	if (state->pending_config) {
-		mtk_ddp_comp_config(ovl, state->pending_width,
-				    state->pending_height,
-				    state->pending_vrefresh);
-
-		state->pending_config = false;
-	}
-
-	if (mtk_crtc->pending_planes) {
-		for (i = 0; i < OVL_LAYER_NR; i++) {
-			struct drm_plane *plane = &mtk_crtc->planes[i].base;
-			struct mtk_plane_state *plane_state;
-
-			plane_state = to_mtk_plane_state(plane->state);
-
-			if (plane_state->pending.config) {
-				mtk_ddp_comp_layer_config(ovl, i, plane_state);
-				plane_state->pending.config = false;
-			}
-		}
-		mtk_crtc->pending_planes = false;
-	}
+	if (!priv->data->shadow_register)
+		mtk_crtc_ddp_config(crtc);
 
 	mtk_drm_finish_page_flip(mtk_crtc);
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index 17ba935..699e039 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
@@ -31,26 +32,38 @@
 #define DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN	0x0c8
 #define DISP_REG_CONFIG_MMSYS_CG_CON0		0x100
 
+#define DISP_REG_CONFIG_DISP_OVL_MOUT_EN	0x030
+#define DISP_REG_CONFIG_OUT_SEL			0x04c
+#define DISP_REG_CONFIG_DSI_SEL			0x050
+
 #define DISP_REG_MUTEX_EN(n)	(0x20 + 0x20 * (n))
+#define DISP_REG_MUTEX(n)	(0x24 + 0x20 * (n))
 #define DISP_REG_MUTEX_RST(n)	(0x28 + 0x20 * (n))
 #define DISP_REG_MUTEX_MOD(n)	(0x2c + 0x20 * (n))
 #define DISP_REG_MUTEX_SOF(n)	(0x30 + 0x20 * (n))
 
-#define MUTEX_MOD_DISP_OVL0		BIT(11)
-#define MUTEX_MOD_DISP_OVL1		BIT(12)
-#define MUTEX_MOD_DISP_RDMA0		BIT(13)
-#define MUTEX_MOD_DISP_RDMA1		BIT(14)
-#define MUTEX_MOD_DISP_RDMA2		BIT(15)
-#define MUTEX_MOD_DISP_WDMA0		BIT(16)
-#define MUTEX_MOD_DISP_WDMA1		BIT(17)
-#define MUTEX_MOD_DISP_COLOR0		BIT(18)
-#define MUTEX_MOD_DISP_COLOR1		BIT(19)
-#define MUTEX_MOD_DISP_AAL		BIT(20)
-#define MUTEX_MOD_DISP_GAMMA		BIT(21)
-#define MUTEX_MOD_DISP_UFOE		BIT(22)
-#define MUTEX_MOD_DISP_PWM0		BIT(23)
-#define MUTEX_MOD_DISP_PWM1		BIT(24)
-#define MUTEX_MOD_DISP_OD		BIT(25)
+#define MUTEX_MOD_MT8173_DISP_OVL0		BIT(11)
+#define MUTEX_MOD_MT8173_DISP_OVL1		BIT(12)
+#define MUTEX_MOD_MT8173_DISP_RDMA0		BIT(13)
+#define MUTEX_MOD_MT8173_DISP_RDMA1		BIT(14)
+#define MUTEX_MOD_MT8173_DISP_RDMA2		BIT(15)
+#define MUTEX_MOD_MT8173_DISP_WDMA0		BIT(16)
+#define MUTEX_MOD_MT8173_DISP_WDMA1		BIT(17)
+#define MUTEX_MOD_MT8173_DISP_COLOR0		BIT(18)
+#define MUTEX_MOD_MT8173_DISP_COLOR1		BIT(19)
+#define MUTEX_MOD_MT8173_DISP_AAL		BIT(20)
+#define MUTEX_MOD_MT8173_DISP_GAMMA		BIT(21)
+#define MUTEX_MOD_MT8173_DISP_UFOE		BIT(22)
+#define MUTEX_MOD_MT8173_DISP_PWM0		BIT(23)
+#define MUTEX_MOD_MT8173_DISP_PWM1		BIT(24)
+#define MUTEX_MOD_MT8173_DISP_OD		BIT(25)
+
+#define MUTEX_MOD_MT2701_DISP_OVL		BIT(3)
+#define MUTEX_MOD_MT2701_DISP_WDMA		BIT(6)
+#define MUTEX_MOD_MT2701_DISP_COLOR		BIT(7)
+#define MUTEX_MOD_MT2701_DISP_BLS		BIT(9)
+#define MUTEX_MOD_MT2701_DISP_RDMA0		BIT(10)
+#define MUTEX_MOD_MT2701_DISP_RDMA1		BIT(12)
 
 #define MUTEX_SOF_SINGLE_MODE		0
 #define MUTEX_SOF_DSI0			1
@@ -67,6 +80,10 @@
 #define DPI0_SEL_IN_RDMA1		0x1
 #define COLOR1_SEL_IN_OVL1		0x1
 
+#define OVL_MOUT_EN_RDMA		0x1
+#define BLS_TO_DSI_RDMA1_TO_DPI1	0x8
+#define DSI_SEL_IN_BLS			0x0
+
 struct mtk_disp_mutex {
 	int id;
 	bool claimed;
@@ -77,24 +94,34 @@ struct mtk_ddp {
 	struct clk			*clk;
 	void __iomem			*regs;
 	struct mtk_disp_mutex		mutex[10];
+	const unsigned int		*mutex_mod;
 };
 
-static const unsigned int mutex_mod[DDP_COMPONENT_ID_MAX] = {
-	[DDP_COMPONENT_AAL] = MUTEX_MOD_DISP_AAL,
-	[DDP_COMPONENT_COLOR0] = MUTEX_MOD_DISP_COLOR0,
-	[DDP_COMPONENT_COLOR1] = MUTEX_MOD_DISP_COLOR1,
-	[DDP_COMPONENT_GAMMA] = MUTEX_MOD_DISP_GAMMA,
-	[DDP_COMPONENT_OD] = MUTEX_MOD_DISP_OD,
-	[DDP_COMPONENT_OVL0] = MUTEX_MOD_DISP_OVL0,
-	[DDP_COMPONENT_OVL1] = MUTEX_MOD_DISP_OVL1,
-	[DDP_COMPONENT_PWM0] = MUTEX_MOD_DISP_PWM0,
-	[DDP_COMPONENT_PWM1] = MUTEX_MOD_DISP_PWM1,
-	[DDP_COMPONENT_RDMA0] = MUTEX_MOD_DISP_RDMA0,
-	[DDP_COMPONENT_RDMA1] = MUTEX_MOD_DISP_RDMA1,
-	[DDP_COMPONENT_RDMA2] = MUTEX_MOD_DISP_RDMA2,
-	[DDP_COMPONENT_UFOE] = MUTEX_MOD_DISP_UFOE,
-	[DDP_COMPONENT_WDMA0] = MUTEX_MOD_DISP_WDMA0,
-	[DDP_COMPONENT_WDMA1] = MUTEX_MOD_DISP_WDMA1,
+static const unsigned int mutex_mod_mt2701[DDP_COMPONENT_ID_MAX] = {
+	[DDP_COMPONENT_BLS] = MUTEX_MOD_MT2701_DISP_BLS,
+	[DDP_COMPONENT_COLOR0] = MUTEX_MOD_MT2701_DISP_COLOR,
+	[DDP_COMPONENT_OVL0] = MUTEX_MOD_MT2701_DISP_OVL,
+	[DDP_COMPONENT_RDMA0] = MUTEX_MOD_MT2701_DISP_RDMA0,
+	[DDP_COMPONENT_RDMA1] = MUTEX_MOD_MT2701_DISP_RDMA1,
+	[DDP_COMPONENT_WDMA0] = MUTEX_MOD_MT2701_DISP_WDMA,
+};
+
+static const unsigned int mutex_mod_mt8173[DDP_COMPONENT_ID_MAX] = {
+	[DDP_COMPONENT_AAL] = MUTEX_MOD_MT8173_DISP_AAL,
+	[DDP_COMPONENT_COLOR0] = MUTEX_MOD_MT8173_DISP_COLOR0,
+	[DDP_COMPONENT_COLOR1] = MUTEX_MOD_MT8173_DISP_COLOR1,
+	[DDP_COMPONENT_GAMMA] = MUTEX_MOD_MT8173_DISP_GAMMA,
+	[DDP_COMPONENT_OD] = MUTEX_MOD_MT8173_DISP_OD,
+	[DDP_COMPONENT_OVL0] = MUTEX_MOD_MT8173_DISP_OVL0,
+	[DDP_COMPONENT_OVL1] = MUTEX_MOD_MT8173_DISP_OVL1,
+	[DDP_COMPONENT_PWM0] = MUTEX_MOD_MT8173_DISP_PWM0,
+	[DDP_COMPONENT_PWM1] = MUTEX_MOD_MT8173_DISP_PWM1,
+	[DDP_COMPONENT_RDMA0] = MUTEX_MOD_MT8173_DISP_RDMA0,
+	[DDP_COMPONENT_RDMA1] = MUTEX_MOD_MT8173_DISP_RDMA1,
+	[DDP_COMPONENT_RDMA2] = MUTEX_MOD_MT8173_DISP_RDMA2,
+	[DDP_COMPONENT_UFOE] = MUTEX_MOD_MT8173_DISP_UFOE,
+	[DDP_COMPONENT_WDMA0] = MUTEX_MOD_MT8173_DISP_WDMA0,
+	[DDP_COMPONENT_WDMA1] = MUTEX_MOD_MT8173_DISP_WDMA1,
 };
 
 static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
@@ -106,6 +133,9 @@ static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
 	if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
 		*addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN;
 		value = OVL0_MOUT_EN_COLOR0;
+	} else if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_RDMA0) {
+		*addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN;
+		value = OVL_MOUT_EN_RDMA;
 	} else if (cur == DDP_COMPONENT_OD && next == DDP_COMPONENT_RDMA0) {
 		*addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
 		value = OD_MOUT_EN_RDMA0;
@@ -143,6 +173,9 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,
 	} else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
 		*addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN;
 		value = COLOR1_SEL_IN_OVL1;
+	} else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
+		*addr = DISP_REG_CONFIG_DSI_SEL;
+		value = DSI_SEL_IN_BLS;
 	} else {
 		value = 0;
 	}
@@ -150,6 +183,15 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,
 	return value;
 }
 
+static void mtk_ddp_mux_sel(void __iomem *config_regs,
+			    enum mtk_ddp_comp_id cur, enum mtk_ddp_comp_id next)
+{
+	if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
+		writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1,
+			       config_regs + DISP_REG_CONFIG_OUT_SEL);
+	}
+}
+
 void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
 			      enum mtk_ddp_comp_id cur,
 			      enum mtk_ddp_comp_id next)
@@ -162,6 +204,8 @@ void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
 		writel_relaxed(reg, config_regs + addr);
 	}
 
+	mtk_ddp_mux_sel(config_regs, cur, next);
+
 	value = mtk_ddp_sel_in(cur, next, &addr);
 	if (value) {
 		reg = readl_relaxed(config_regs + addr) | value;
@@ -247,7 +291,7 @@ void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
 		break;
 	default:
 		reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
-		reg |= mutex_mod[id];
+		reg |= ddp->mutex_mod[id];
 		writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
 		return;
 	}
@@ -273,7 +317,7 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
 		break;
 	default:
 		reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
-		reg &= ~mutex_mod[id];
+		reg &= ~(ddp->mutex_mod[id]);
 		writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
 		break;
 	}
@@ -299,8 +343,40 @@ void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex)
 	writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
 }
 
+void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex)
+{
+	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+					   mutex[mutex->id]);
+
+	unsigned int cnt = 0;
+
+	writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
+	writel(1, ddp->regs + DISP_REG_MUTEX(mutex->id));
+	while (!(readl(ddp->regs + DISP_REG_MUTEX(mutex->id)) & 0x2)) {
+		if (cnt++ > 10000)
+			break;
+		udelay(1);
+	}
+}
+
+void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex)
+{
+	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+					   mutex[mutex->id]);
+
+	writel(0, ddp->regs + DISP_REG_MUTEX(mutex->id));
+}
+
+static const struct of_device_id ddp_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt2701-disp-mutex", .data = mutex_mod_mt2701},
+	{ .compatible = "mediatek,mt8173-disp-mutex", .data = mutex_mod_mt8173},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
+
 static int mtk_ddp_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *of_id;
 	struct device *dev = &pdev->dev;
 	struct mtk_ddp *ddp;
 	struct resource *regs;
@@ -326,6 +402,9 @@ static int mtk_ddp_probe(struct platform_device *pdev)
 		return PTR_ERR(ddp->regs);
 	}
 
+	of_id = of_match_device(ddp_driver_dt_match, &pdev->dev);
+	ddp->mutex_mod = of_id->data;
+
 	platform_set_drvdata(pdev, ddp);
 
 	return 0;
@@ -336,12 +415,6 @@ static int mtk_ddp_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id ddp_driver_dt_match[] = {
-	{ .compatible = "mediatek,mt8173-disp-mutex" },
-	{},
-};
-MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
-
 struct platform_driver mtk_ddp_driver = {
 	.probe		= mtk_ddp_probe,
 	.remove		= mtk_ddp_remove,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp.h
index 92c1175..f9a7991 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.h
@@ -37,5 +37,7 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
 				enum mtk_ddp_comp_id id);
 void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex);
 void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex);
+void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex);
+void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex);
 
 #endif /* MTK_DRM_DDP_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 3970fcf..a1a1297 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -25,6 +25,11 @@
 #include "mtk_drm_plane.h"
 #include "mtk_drm_ddp_comp.h"
 
+#define DISP_REG_BLS_EN				0x0000
+#define DISP_REG_BLS_SRC_SIZE			0x0018
+#define DISP_REG_BLS_PWM_DUTY			0x00a0
+#define DISP_REG_BLS_PWM_CON			0x00a8
+
 #define DISP_OD_EN				0x0000
 #define DISP_OD_INTEN				0x0008
 #define DISP_OD_INTSTA				0x000c
@@ -34,9 +39,8 @@
 #define DISP_REG_UFO_START			0x0000
 
 #define DISP_COLOR_CFG_MAIN			0x0400
-#define DISP_COLOR_START			0x0c00
-#define DISP_COLOR_WIDTH			0x0c50
-#define DISP_COLOR_HEIGHT			0x0c54
+#define DISP_COLOR_WIDTH			0x50
+#define DISP_COLOR_HEIGHT			0x54
 
 #define	OD_RELAY_MODE		BIT(0)
 
@@ -45,18 +49,30 @@
 #define	COLOR_BYPASS_ALL	BIT(7)
 #define	COLOR_SEQ_SEL		BIT(13)
 
+#define BLS_PWM_CLKDIV		BIT(16)
+#define BLS_PWM_EN		BIT(16)
+
+static void mtk_bls_config(struct mtk_ddp_comp *comp, unsigned int w,
+		unsigned int h, unsigned int vrefresh)
+{
+	writel(h << 16 | w, comp->regs + DISP_REG_BLS_SRC_SIZE);
+	writel(0, comp->regs + DISP_REG_BLS_PWM_DUTY);
+	writel(BLS_PWM_CLKDIV, comp->regs + DISP_REG_BLS_PWM_CON);
+	writel(BLS_PWM_EN, comp->regs + DISP_REG_BLS_EN);
+}
+
 static void mtk_color_config(struct mtk_ddp_comp *comp, unsigned int w,
 			     unsigned int h, unsigned int vrefresh)
 {
-	writel(w, comp->regs + DISP_COLOR_WIDTH);
-	writel(h, comp->regs + DISP_COLOR_HEIGHT);
+	writel(w, comp->regs + comp->data->color_offset + DISP_COLOR_WIDTH);
+	writel(h, comp->regs + comp->data->color_offset + DISP_COLOR_HEIGHT);
 }
 
 static void mtk_color_start(struct mtk_ddp_comp *comp)
 {
 	writel(COLOR_BYPASS_ALL | COLOR_SEQ_SEL,
 	       comp->regs + DISP_COLOR_CFG_MAIN);
-	writel(0x1, comp->regs + DISP_COLOR_START);
+	writel(0x1, comp->regs + comp->data->color_offset);
 }
 
 static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w,
@@ -76,6 +92,10 @@ static void mtk_ufoe_start(struct mtk_ddp_comp *comp)
 	writel(UFO_BYPASS, comp->regs + DISP_REG_UFO_START);
 }
 
+static const struct mtk_ddp_comp_funcs ddp_bls = {
+	.config = mtk_bls_config,
+};
+
 static const struct mtk_ddp_comp_funcs ddp_color = {
 	.config = mtk_color_config,
 	.start = mtk_color_start,
@@ -103,6 +123,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
 	[MTK_DISP_PWM] = "pwm",
 	[MTK_DISP_MUTEX] = "mutex",
 	[MTK_DISP_OD] = "od",
+	[MTK_DISP_BLS] = "bls",
 };
 
 struct mtk_ddp_comp_match {
@@ -113,6 +134,7 @@ struct mtk_ddp_comp_match {
 
 static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
 	[DDP_COMPONENT_AAL]	= { MTK_DISP_AAL,	0, NULL },
+	[DDP_COMPONENT_BLS]	= { MTK_DISP_BLS,	0, &ddp_bls },
 	[DDP_COMPONENT_COLOR0]	= { MTK_DISP_COLOR,	0, &ddp_color },
 	[DDP_COMPONENT_COLOR1]	= { MTK_DISP_COLOR,	1, &ddp_color },
 	[DDP_COMPONENT_DPI0]	= { MTK_DPI,		0, NULL },
@@ -131,6 +153,32 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
 	[DDP_COMPONENT_WDMA1]	= { MTK_DISP_WDMA,	1, NULL },
 };
 
+static struct mtk_ddp_comp_driver_data mt2701_color_driver_data = {
+	.color_offset = 0x0f00,
+};
+
+static struct mtk_ddp_comp_driver_data mt8173_color_driver_data = {
+	.color_offset = 0x0c00,
+};
+
+static const struct of_device_id mtk_disp_color_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt2701-disp-color",
+	  .data = &mt2701_color_driver_data},
+	{ .compatible = "mediatek,mt8173-disp-color",
+	  .data = &mt8173_color_driver_data},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_color_driver_dt_match);
+
+static inline struct mtk_ddp_comp_driver_data *mtk_color_get_driver_data(
+	struct device_node *node)
+{
+	const struct of_device_id *of_id =
+		of_match_node(mtk_disp_color_driver_dt_match, node);
+
+	return (struct mtk_ddp_comp_driver_data *)of_id->data;
+}
+
 int mtk_ddp_comp_get_id(struct device_node *node,
 			enum mtk_ddp_comp_type comp_type)
 {
@@ -177,6 +225,9 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
 
 	type = mtk_ddp_matches[comp_id].type;
 
+	if (type == MTK_DISP_COLOR)
+		comp->data = mtk_color_get_driver_data(node);
+
 	/* Only DMA capable components need the LARB property */
 	comp->larb_dev = NULL;
 	if (type != MTK_DISP_OVL &&
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index 6b13ba9..8939206 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -35,6 +35,7 @@ enum mtk_ddp_comp_type {
 	MTK_DISP_PWM,
 	MTK_DISP_MUTEX,
 	MTK_DISP_OD,
+	MTK_DISP_BLS,
 	MTK_DDP_COMP_TYPE_MAX,
 };
 
@@ -57,6 +58,7 @@ enum mtk_ddp_comp_id {
 	DDP_COMPONENT_UFOE,
 	DDP_COMPONENT_WDMA0,
 	DDP_COMPONENT_WDMA1,
+	DDP_COMPONENT_BLS,
 	DDP_COMPONENT_ID_MAX,
 };
 
@@ -75,6 +77,18 @@ struct mtk_ddp_comp_funcs {
 			     struct mtk_plane_state *state);
 };
 
+struct mtk_ddp_comp_driver_data {
+	union {
+		struct ovl {
+			unsigned int addr_offset;
+			unsigned int fmt_rgb565;
+			unsigned int fmt_rgb888;
+		} ovl;
+		unsigned int rdma_fifo_pseudo_size;
+		unsigned int color_offset;
+	};
+};
+
 struct mtk_ddp_comp {
 	struct clk *clk;
 	void __iomem *regs;
@@ -82,6 +96,7 @@ struct mtk_ddp_comp {
 	struct device *larb_dev;
 	enum mtk_ddp_comp_id id;
 	const struct mtk_ddp_comp_funcs *funcs;
+	struct mtk_ddp_comp_driver_data *data;
 };
 
 static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 2774cbd..472ed21 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -109,7 +109,20 @@ static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = {
 	.atomic_commit = mtk_atomic_commit,
 };
 
-static const enum mtk_ddp_comp_id mtk_ddp_main[] = {
+static const enum mtk_ddp_comp_id mtk_ddp_main_2701[] = {
+	DDP_COMPONENT_OVL0,
+	DDP_COMPONENT_RDMA0,
+	DDP_COMPONENT_COLOR0,
+	DDP_COMPONENT_BLS,
+	DDP_COMPONENT_DSI0,
+};
+
+static const enum mtk_ddp_comp_id mtk_ddp_ext_2701[] = {
+	DDP_COMPONENT_OVL0,
+	DDP_COMPONENT_DSI0,
+};
+
+static const enum mtk_ddp_comp_id mtk_ddp_main_8173[] = {
 	DDP_COMPONENT_OVL0,
 	DDP_COMPONENT_COLOR0,
 	DDP_COMPONENT_AAL,
@@ -120,7 +133,7 @@ static const enum mtk_ddp_comp_id mtk_ddp_main[] = {
 	DDP_COMPONENT_PWM0,
 };
 
-static const enum mtk_ddp_comp_id mtk_ddp_ext[] = {
+static const enum mtk_ddp_comp_id mtk_ddp_ext_8173[] = {
 	DDP_COMPONENT_OVL1,
 	DDP_COMPONENT_COLOR1,
 	DDP_COMPONENT_GAMMA,
@@ -128,6 +141,22 @@ static const enum mtk_ddp_comp_id mtk_ddp_ext[] = {
 	DDP_COMPONENT_DPI0,
 };
 
+static struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
+	.main_path = mtk_ddp_main_2701,
+	.main_len = ARRAY_SIZE(mtk_ddp_main_2701),
+	.ext_path = mtk_ddp_ext_2701,
+	.ext_len = ARRAY_SIZE(mtk_ddp_ext_2701),
+	.shadow_register = true,
+};
+
+static struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
+	.main_path = mtk_ddp_main_8173,
+	.main_len = ARRAY_SIZE(mtk_ddp_main_8173),
+	.ext_path = mtk_ddp_ext_8173,
+	.ext_len = ARRAY_SIZE(mtk_ddp_ext_8173),
+	.shadow_register = false,
+};
+
 static int mtk_drm_kms_init(struct drm_device *drm)
 {
 	struct mtk_drm_private *private = drm->dev_private;
@@ -170,17 +199,19 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 	 * and each statically assigned to a crtc:
 	 * OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ...
 	 */
-	ret = mtk_drm_crtc_create(drm, mtk_ddp_main, ARRAY_SIZE(mtk_ddp_main));
+	ret = mtk_drm_crtc_create(drm, private->data->main_path,
+				  private->data->main_len);
 	if (ret < 0)
 		goto err_component_unbind;
 	/* ... and OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0. */
-	ret = mtk_drm_crtc_create(drm, mtk_ddp_ext, ARRAY_SIZE(mtk_ddp_ext));
+	ret = mtk_drm_crtc_create(drm, private->data->ext_path,
+				  private->data->ext_len);
 	if (ret < 0)
 		goto err_component_unbind;
 
 	/* Use OVL device for all DMA memory allocations */
-	np = private->comp_node[mtk_ddp_main[0]] ?:
-	     private->comp_node[mtk_ddp_ext[0]];
+	np = private->comp_node[private->data->main_path[0]] ?:
+	     private->comp_node[private->data->ext_path[0]];
 	pdev = of_find_device_by_node(np);
 	if (!pdev) {
 		ret = -ENODEV;
@@ -316,21 +347,44 @@ static const struct component_master_ops mtk_drm_ops = {
 };
 
 static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
+	{ .compatible = "mediatek,mt2701-disp-ovl",   .data = (void *)MTK_DISP_OVL },
 	{ .compatible = "mediatek,mt8173-disp-ovl",   .data = (void *)MTK_DISP_OVL },
+	{ .compatible = "mediatek,mt2701-disp-rdma",  .data = (void *)MTK_DISP_RDMA },
 	{ .compatible = "mediatek,mt8173-disp-rdma",  .data = (void *)MTK_DISP_RDMA },
+	{ .compatible = "mediatek,mt2701-disp-wdma",  .data = (void *)MTK_DISP_WDMA },
 	{ .compatible = "mediatek,mt8173-disp-wdma",  .data = (void *)MTK_DISP_WDMA },
+	{ .compatible = "mediatek,mt2701-disp-color", .data = (void *)MTK_DISP_COLOR },
 	{ .compatible = "mediatek,mt8173-disp-color", .data = (void *)MTK_DISP_COLOR },
 	{ .compatible = "mediatek,mt8173-disp-aal",   .data = (void *)MTK_DISP_AAL},
 	{ .compatible = "mediatek,mt8173-disp-gamma", .data = (void *)MTK_DISP_GAMMA, },
 	{ .compatible = "mediatek,mt8173-disp-ufoe",  .data = (void *)MTK_DISP_UFOE },
+	{ .compatible = "mediatek,mt2701-dsi",	      .data = (void *)MTK_DSI },
 	{ .compatible = "mediatek,mt8173-dsi",        .data = (void *)MTK_DSI },
+	{ .compatible = "mediatek,mt2701-dpi",	      .data = (void *)MTK_DPI },
 	{ .compatible = "mediatek,mt8173-dpi",        .data = (void *)MTK_DPI },
+	{ .compatible = "mediatek,mt2701-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
 	{ .compatible = "mediatek,mt8173-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
 	{ .compatible = "mediatek,mt8173-disp-pwm",   .data = (void *)MTK_DISP_PWM },
 	{ .compatible = "mediatek,mt8173-disp-od",    .data = (void *)MTK_DISP_OD },
+	{ .compatible = "mediatek,mt2701-disp-bls",   .data = (void *)MTK_DISP_BLS },
 	{ }
 };
 
+static const struct of_device_id mtk_drm_of_ids[] = {
+	{ .compatible = "mediatek,mt2701-mmsys", .data = &mt2701_mmsys_driver_data},
+	{ .compatible = "mediatek,mt8173-mmsys", .data = &mt8173_mmsys_driver_data},
+	{ }
+};
+
+static inline struct mtk_mmsys_driver_data *mtk_drm_get_driver_data(
+	struct platform_device *pdev)
+{
+	const struct of_device_id *of_id =
+		of_match_device(mtk_drm_of_ids, &pdev->dev);
+
+	return (struct mtk_mmsys_driver_data *)of_id->data;
+}
+
 static int mtk_drm_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -347,6 +401,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
 
 	mutex_init(&private->commit.lock);
 	INIT_WORK(&private->commit.work, mtk_atomic_work);
+	private->data = mtk_drm_get_driver_data(pdev);
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	private->config_regs = devm_ioremap_resource(dev, mem);
@@ -497,11 +552,6 @@ static int mtk_drm_sys_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops, mtk_drm_sys_suspend,
 			 mtk_drm_sys_resume);
 
-static const struct of_device_id mtk_drm_of_ids[] = {
-	{ .compatible = "mediatek,mt8173-mmsys", },
-	{ }
-};
-
 static struct platform_driver mtk_drm_platform_driver = {
 	.probe	= mtk_drm_probe,
 	.remove	= mtk_drm_remove,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index aa93894..2aa2ac1 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -28,6 +28,14 @@ struct drm_fb_helper;
 struct drm_property;
 struct regmap;
 
+struct mtk_mmsys_driver_data {
+	const enum mtk_ddp_comp_id *main_path;
+	unsigned int main_len;
+	const enum mtk_ddp_comp_id *ext_path;
+	unsigned int ext_len;
+	bool shadow_register;
+};
+
 struct mtk_drm_private {
 	struct drm_device *drm;
 	struct device *dma_dev;
@@ -40,6 +48,7 @@ struct mtk_drm_private {
 	void __iomem *config_regs;
 	struct device_node *comp_node[DDP_COMPONENT_ID_MAX];
 	struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX];
+	struct mtk_mmsys_driver_data *data;
 
 	struct {
 		struct drm_atomic_state *state;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
index a773bfa..d70776c 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
@@ -108,6 +108,10 @@ int mtk_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
 	int ret;
 
 	args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+	/*
+	* align to 8 bytes since Mali requires it.
+	*/
+	args->pitch = ALIGN(args->pitch, 8);
 	args->size = args->pitch * args->height;
 
 	mtk_gem = mtk_drm_gem_create(dev, args->size, false);
-- 
1.7.9.5



From aleksey.makarov at linaro.org  Thu May 12 04:52:02 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Thu, 12 May 2016 14:52:02 +0300
Subject: [PATCH v7 0/5] ACPI: parse the SPCR table
In-Reply-To: <1bff98e3-2d94-ed76-1165-ed7d43bbfcf3@jonmasters.org>
References: <1459431629-27934-1-git-send-email-aleksey.makarov@linaro.org>
 <1bff98e3-2d94-ed76-1165-ed7d43bbfcf3@jonmasters.org>
Message-ID: <bc91f503-cee5-db03-51bf-a36ef3e95a1f@linaro.org>

Hi Jon,

In v7 I addressed the issues that were brought up by Rafael J . Wysocki
(but I still do not have ACK from ACPI people).

The issue with D02 will be addressed in a separate patch.

There possibly is an issue with 16550 and command line console with I am
investigating and probably will address in a separate patch.

I know no other problems with it and reviewers seem happy.

So I believe this patchset could be pulled.  If needed, I will send v8.

Thank you
Aleksey Makarov

On 05/12/2016 11:20 AM, Jon Masters wrote:
> On 03/31/2016 09:40 AM, Aleksey Makarov wrote:
> 
>> 'ARM Server Base Boot Requirements' [1] mentions SPCR (Serial Port
>> Console Redirection Table) [2] as a mandatory ACPI table that
>> specifies the configuration of serial console.
> 
> Hi Aleksey,
> 
> Can you summarize the status of this patch series?
> 
> Jon.
> 


From yt.shen at mediatek.com  Thu May 12 04:49:52 2016
From: yt.shen at mediatek.com (yt.shen at mediatek.com)
Date: Thu, 12 May 2016 19:49:52 +0800
Subject: [RFC 0/3] MT2701 DRM support
Message-ID: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>

From: YT Shen <yt.shen at mediatek.com>

This is MT2701 DRM support RFC, based on MT8173 DRM patch v16.
Most codes are the same, except some register changed.

For example:
 - DISP_OVL address offset changed, color format definition changed.
 - DISP_RDMA fifo size changed.
 - DISP_COLOR offset changed.

We add a new component DISP_BLS, and the connection settings are updated.
And we have shadow register support in MT2701.

The RFC depends on MT2701 iommu/smi driver.
https://patchwork.kernel.org/patch/9043411/ ("dt-bindings: mediatek: add descriptions for mediatek mt2701 iommu and smi"),
https://patchwork.kernel.org/patch/9043391/ ("iommu/mediatek: move the common struct into header file"),
https://patchwork.kernel.org/patch/9043421/ ("memory/mediatek: add support for mt2701"),
https://patchwork.kernel.org/patch/9043451/ ("iommu/mediatek: add support for mtk iommu generation one HW"),
https://patchwork.kernel.org/patch/9043471/ ("ARM: dts: mt2701: add iommu/smi dtsi node for mt2701"),

Thanks,
yt.shen

YT Shen (3):
  dt-bindings: drm/mediatek: Add display binding for Mediatek SoC MT2701
  drm/mediatek: add support for Mediatek SoC MT2701
  arm: dts: mt2701: Add display subsystem related nodes for MT2701

 .../bindings/display/mediatek/mediatek,disp.txt    |    1 +
 arch/arm/boot/dts/mt2701.dtsi                      |  117 +++++++++++++++
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c            |   49 +++++--
 drivers/gpu/drm/mediatek/mtk_disp_rdma.c           |   36 ++++-
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c            |   78 ++++++----
 drivers/gpu/drm/mediatek/mtk_drm_ddp.c             |  151 +++++++++++++++-----
 drivers/gpu/drm/mediatek/mtk_drm_ddp.h             |    2 +
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c        |   63 +++++++-
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h        |   15 ++
 drivers/gpu/drm/mediatek/mtk_drm_drv.c             |   72 ++++++++--
 drivers/gpu/drm/mediatek/mtk_drm_drv.h             |    9 ++
 drivers/gpu/drm/mediatek/mtk_drm_gem.c             |    4 +
 12 files changed, 491 insertions(+), 106 deletions(-)

-- 
1.7.9.5



From christoffer.dall at linaro.org  Thu May 12 04:59:40 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 13:59:40 +0200
Subject: [PATCH v3 34/55] KVM: arm/arm64: vgic-new: Add GICv3
 redistributor IIDR and TYPER handler
In-Reply-To: <1462531568-9799-35-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-35-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512115940.GE27623@cbox>

On Fri, May 06, 2016 at 11:45:47AM +0100, Andre Przywara wrote:
> The redistributor TYPER tells the OS about the associated MPIDR,
> also the LAST bit is crucial to determine the number of redistributors.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 44 ++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 42 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index 5f4558c..d137242 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -71,6 +71,46 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
>  }
>  
>  /*
> + * We use a compressed version of the MPIDR (all 32 bits in one 32-bit word)
> + * when we store the target MPIDR written by the guest.
> + */
> +static u32 compress_mpidr(unsigned long mpidr)
> +{
> +	u32 ret;
> +
> +	ret = MPIDR_AFFINITY_LEVEL(mpidr, 0);
> +	ret |= MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8;
> +	ret |= MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16;
> +	ret |= MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24;
> +
> +	return ret;
> +}
> +
> +static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
> +					      gpa_t addr, unsigned int len)
> +{
> +	unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
> +	int target_vcpu_id = vcpu->vcpu_id;
> +	u64 value;
> +
> +	value = (u64)compress_mpidr(mpidr) << 32;
> +	value |= ((target_vcpu_id & 0xffff) << 8);
> +	if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
> +		value |= GICR_TYPER_LAST;
> +
> +	return extract_bytes(value, addr & 7, len);
> +}
> +
> +static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
> +					     gpa_t addr, unsigned int len)
> +{
> +	u32 value;
> +
> +	value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
> +	return extract_bytes(value, addr & 3, len);
> +}
> +
> +/*
>   * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
>   * redistributors, while SPIs are covered by registers in the distributor
>   * block. Trying to set private IRQs in this block gets ignored.
> @@ -127,9 +167,9 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
>  	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
>  	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 4),
> +		vgic_mmio_read_v3r_iidr, vgic_mmio_write_wi, 4),
>  	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
> +		vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, 8),
>  	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>  	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
> -- 
> 2.7.3
> 
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From wangkefeng.wang at huawei.com  Thu May 12 05:06:00 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:00 +0800
Subject: [PATCH v4 03/18] arm: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-4-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers about the
of_platform_populate with default match table.

Cc: Nicolas Ferre <nicolas.ferre at atmel.com>
Cc: Ray Jui <rjui at broadcom.com>
Cc: Lee Jones <lee at kernel.org>
Cc: Krzysztof Halasa <khalasa at piap.pl>
Cc: Kukjin Kim <kgene at kernel.org>
Cc: Rob Herring <robh at kernel.org>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Santosh Shilimkar <ssantosh at kernel.org>
Cc: Roland Stigge <stigge at antcom.de>
Cc: Jason Cooper <jason at lakedaemon.net>
Cc: Haojian Zhuang <haojian.zhuang at gmail.com>
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: Viresh Kumar <vireshk at kernel.org>
Cc: Shiraz Hashim <shiraz.linux.kernel at gmail.com>
Cc: Tony Prisk <linux at prisktech.co.nz>
Cc: Arnd Bergmann <arnd at arndb.de>
Cc: Russell King <linux at arm.linux.org.uk>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/arm/kernel/setup.c                 |  6 +-----
 arch/arm/mach-artpec/board-artpec6.c    |  3 ---
 arch/arm/mach-bcm/board_bcm21664.c      |  2 --
 arch/arm/mach-bcm/board_bcm281xx.c      |  2 --
 arch/arm/mach-bcm/board_bcm2835.c       | 10 ----------
 arch/arm/mach-exynos/exynos.c           |  3 ---
 arch/arm/mach-highbank/highbank.c       |  3 ---
 arch/arm/mach-imx/imx27-dt.c            |  2 --
 arch/arm/mach-imx/mach-imx51.c          |  2 --
 arch/arm/mach-imx/mach-imx53.c          |  2 --
 arch/arm/mach-imx/mach-imx6ul.c         |  1 -
 arch/arm/mach-imx/mach-imx7d.c          |  1 -
 arch/arm/mach-keystone/keystone.c       |  1 -
 arch/arm/mach-mvebu/board-v7.c          |  3 ---
 arch/arm/mach-mvebu/dove.c              |  2 --
 arch/arm/mach-picoxcell/common.c        |  2 --
 arch/arm/mach-rockchip/rockchip.c       |  1 -
 arch/arm/mach-s3c24xx/mach-s3c2416-dt.c |  2 --
 arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c |  3 ---
 arch/arm/mach-shmobile/setup-r8a7740.c  |  3 ---
 arch/arm/mach-shmobile/setup-sh73a0.c   |  2 --
 arch/arm/mach-spear/spear1310.c         |  2 --
 arch/arm/mach-spear/spear1340.c         |  1 -
 arch/arm/mach-vt8500/vt8500.c           |  3 ---
 24 files changed, 1 insertion(+), 61 deletions(-)

diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 18a29a0..5397cb3 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -903,11 +903,7 @@ static int __init customize_machine(void)
 	 */
 	if (machine_desc->init_machine)
 		machine_desc->init_machine();
-#ifdef CONFIG_OF
-	else
-		of_platform_populate(NULL, of_default_bus_match_table,
-					NULL, NULL);
-#endif
+
 	return 0;
 }
 arch_initcall(customize_machine);
diff --git a/arch/arm/mach-artpec/board-artpec6.c b/arch/arm/mach-artpec/board-artpec6.c
index 71513df..a0b1979 100644
--- a/arch/arm/mach-artpec/board-artpec6.c
+++ b/arch/arm/mach-artpec/board-artpec6.c
@@ -13,7 +13,6 @@
 #include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic.h>
 #include <linux/mfd/syscon.h>
-#include <linux/of_platform.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk-provider.h>
@@ -44,8 +43,6 @@ static void __init artpec6_init_machine(void)
 		regmap_write(regmap, ARTPEC6_DMACFG_REGNUM,
 			     ARTPEC6_DMACFG_UARTS_BURST);
 	};
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static void artpec6_l2c310_write_sec(unsigned long val, unsigned reg)
diff --git a/arch/arm/mach-bcm/board_bcm21664.c b/arch/arm/mach-bcm/board_bcm21664.c
index 82ad568..0d7034c 100644
--- a/arch/arm/mach-bcm/board_bcm21664.c
+++ b/arch/arm/mach-bcm/board_bcm21664.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/of_address.h>
-#include <linux/of_platform.h>
 #include <linux/io.h>
 
 #include <asm/mach/arch.h>
@@ -60,7 +59,6 @@ static void bcm21664_restart(enum reboot_mode mode, const char *cmd)
 
 static void __init bcm21664_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	kona_l2_cache_init();
 }
 
diff --git a/arch/arm/mach-bcm/board_bcm281xx.c b/arch/arm/mach-bcm/board_bcm281xx.c
index 2e367bd..b81bb38 100644
--- a/arch/arm/mach-bcm/board_bcm281xx.c
+++ b/arch/arm/mach-bcm/board_bcm281xx.c
@@ -13,7 +13,6 @@
 
 #include <linux/clocksource.h>
 #include <linux/of_address.h>
-#include <linux/of_platform.h>
 
 #include <asm/mach/arch.h>
 
@@ -58,7 +57,6 @@ static void bcm281xx_restart(enum reboot_mode mode, const char *cmd)
 
 static void __init bcm281xx_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	kona_l2_cache_init();
 }
 
diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c
index 834d676..0c1edfc 100644
--- a/arch/arm/mach-bcm/board_bcm2835.c
+++ b/arch/arm/mach-bcm/board_bcm2835.c
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 #include <linux/irqchip.h>
 #include <linux/of_address.h>
-#include <linux/of_platform.h>
 #include <linux/clk/bcm2835.h>
 
 #include <asm/mach/arch.h>
@@ -23,16 +22,7 @@
 
 static void __init bcm2835_init(void)
 {
-	int ret;
-
 	bcm2835_init_clocks();
-
-	ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
-				   NULL);
-	if (ret) {
-		pr_err("of_platform_populate failed: %d\n", ret);
-		BUG();
-	}
 }
 
 static const char * const bcm2835_compat[] = {
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index bbf51a4..d4fa77e 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -14,7 +14,6 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/irqchip.h>
 #include <linux/soc/samsung/exynos-regs-pmu.h>
@@ -263,8 +262,6 @@ static void __init exynos_dt_machine_init(void)
 		platform_device_register(&exynos_cpuidle);
 
 	exynos_cpufreq_init();
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static char const *const exynos_dt_compat[] __initconst = {
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index 6050a14..07f6098 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -23,7 +23,6 @@
 #include <linux/pl320-ipc.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
-#include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/reboot.h>
 #include <linux/amba/bus.h>
@@ -163,8 +162,6 @@ static void __init highbank_init(void)
 
 	pl320_ipc_register_notifier(&hb_keys_nb);
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-
 	if (psci_ops.cpu_suspend)
 		platform_device_register(&highbank_cpuidle_device);
 }
diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c
index bd42d1b..ae33ce4 100644
--- a/arch/arm/mach-imx/imx27-dt.c
+++ b/arch/arm/mach-imx/imx27-dt.c
@@ -22,8 +22,6 @@ static void __init imx27_dt_init(void)
 {
 	struct platform_device_info devinfo = { .name = "cpufreq-dt", };
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-
 	platform_device_register_full(&devinfo);
 }
 
diff --git a/arch/arm/mach-imx/mach-imx51.c b/arch/arm/mach-imx/mach-imx51.c
index 6883fba..a4ada63 100644
--- a/arch/arm/mach-imx/mach-imx51.c
+++ b/arch/arm/mach-imx/mach-imx51.c
@@ -54,8 +54,6 @@ static void __init imx51_dt_init(void)
 
 	imx51_ipu_mipi_setup();
 	imx_src_init();
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	platform_device_register_full(&devinfo);
 }
 
diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c
index 86316a9..13a94a4 100644
--- a/arch/arm/mach-imx/mach-imx53.c
+++ b/arch/arm/mach-imx/mach-imx53.c
@@ -32,8 +32,6 @@ static void __init imx53_dt_init(void)
 {
 	imx_src_init();
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-
 	imx_aips_allow_unprivileged_access("fsl,imx53-aipstz");
 }
 
diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c
index a38b16b..4078b1c 100644
--- a/arch/arm/mach-imx/mach-imx6ul.c
+++ b/arch/arm/mach-imx/mach-imx6ul.c
@@ -64,7 +64,6 @@ static void __init imx6ul_init_machine(void)
 	if (parent == NULL)
 		pr_warn("failed to initialize soc device\n");
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	imx6ul_enet_init();
 	imx_anatop_init();
 	imx6ul_pm_init();
diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c
index 5a27f20..a924952 100644
--- a/arch/arm/mach-imx/mach-imx7d.c
+++ b/arch/arm/mach-imx/mach-imx7d.c
@@ -93,7 +93,6 @@ static void __init imx7d_init_machine(void)
 	if (parent == NULL)
 		pr_warn("failed to initialize soc device\n");
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	imx_anatop_init();
 	imx7d_enet_init();
 }
diff --git a/arch/arm/mach-keystone/keystone.c b/arch/arm/mach-keystone/keystone.c
index e6b9cb1..afe35d0 100644
--- a/arch/arm/mach-keystone/keystone.c
+++ b/arch/arm/mach-keystone/keystone.c
@@ -60,7 +60,6 @@ static void __init keystone_init(void)
 		bus_register_notifier(&platform_bus_type, &platform_nb);
 	}
 	keystone_pm_runtime_init();
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static unsigned long keystone_virt_to_idmap(unsigned long x)
diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
index 1648edd..ccca951 100644
--- a/arch/arm/mach-mvebu/board-v7.c
+++ b/arch/arm/mach-mvebu/board-v7.c
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <linux/io.h>
 #include <linux/clocksource.h>
 #include <linux/dma-mapping.h>
@@ -144,8 +143,6 @@ static void __init mvebu_dt_init(void)
 {
 	if (of_machine_is_compatible("marvell,armadaxp"))
 		i2c_quirk();
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char * const armada_370_xp_dt_compat[] __initconst = {
diff --git a/arch/arm/mach-mvebu/dove.c b/arch/arm/mach-mvebu/dove.c
index 1aebb82..d076c57 100644
--- a/arch/arm/mach-mvebu/dove.c
+++ b/arch/arm/mach-mvebu/dove.c
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/mbus.h>
 #include <linux/of.h>
-#include <linux/of_platform.h>
 #include <linux/soc/dove/pmu.h>
 #include <asm/hardware/cache-tauros2.h>
 #include <asm/mach/arch.h>
@@ -26,7 +25,6 @@ static void __init dove_init(void)
 #endif
 	BUG_ON(mvebu_mbus_dt_init(false));
 	dove_init_pmu();
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char * const dove_dt_compat[] __initconst = {
diff --git a/arch/arm/mach-picoxcell/common.c b/arch/arm/mach-picoxcell/common.c
index ec79fea..4e3d6d5 100644
--- a/arch/arm/mach-picoxcell/common.c
+++ b/arch/arm/mach-picoxcell/common.c
@@ -10,7 +10,6 @@
 #include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/of_platform.h>
 #include <linux/reboot.h>
 
 #include <asm/mach/arch.h>
@@ -54,7 +53,6 @@ static void __init picoxcell_map_io(void)
 
 static void __init picoxcell_init_machine(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	picoxcell_setup_restart();
 }
 
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index 3f07cc5..5e00909 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -73,7 +73,6 @@ static void __init rockchip_timer_init(void)
 static void __init rockchip_dt_init(void)
 {
 	rockchip_suspend_init();
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	platform_device_register_simple("cpufreq-dt", 0, NULL, 0);
 }
 
diff --git a/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c b/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c
index 5f028ff..c83c076 100644
--- a/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c
+++ b/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c
@@ -17,7 +17,6 @@
 
 #include <linux/clocksource.h>
 #include <linux/irqchip.h>
-#include <linux/of_platform.h>
 #include <linux/serial_s3c.h>
 
 #include <asm/mach/arch.h>
@@ -35,7 +34,6 @@ static void __init s3c2416_dt_map_io(void)
 
 static void __init s3c2416_dt_machine_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	s3c_pm_init();
 }
 
diff --git a/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c b/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
index bbf74ed..5bf9afa 100644
--- a/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
+++ b/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
@@ -8,8 +8,6 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/of_platform.h>
-
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
@@ -48,7 +46,6 @@ static void __init s3c64xx_dt_map_io(void)
 static void __init s3c64xx_dt_init_machine(void)
 {
 	samsung_wdt_reset_of_init();
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static void s3c64xx_dt_restart(enum reboot_mode mode, const char *cmd)
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index db6dbfb..3849eef 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -18,7 +18,6 @@
 #include <linux/io.h>
 #include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic.h>
-#include <linux/of_platform.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
@@ -77,8 +76,6 @@ static void __init r8a7740_init_irq_of(void)
 static void __init r8a7740_generic_init(void)
 {
 	r8a7740_meram_workaround();
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char *const r8a7740_boards_compat_dt[] __initconst = {
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index 99a2004..a25ff18 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/of_platform.h>
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/io.h>
@@ -55,7 +54,6 @@ static void __init sh73a0_generic_init(void)
 	/* Shared attribute override enable, 64K*8way */
 	l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
 #endif
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char *const sh73a0_boards_compat_dt[] __initconst = {
diff --git a/arch/arm/mach-spear/spear1310.c b/arch/arm/mach-spear/spear1310.c
index cd5d375..a7d4f13 100644
--- a/arch/arm/mach-spear/spear1310.c
+++ b/arch/arm/mach-spear/spear1310.c
@@ -14,7 +14,6 @@
 #define pr_fmt(fmt) "SPEAr1310: " fmt
 
 #include <linux/amba/pl022.h>
-#include <linux/of_platform.h>
 #include <linux/pata_arasan_cf_data.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -27,7 +26,6 @@
 
 static void __init spear1310_dt_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	platform_device_register_simple("spear-cpufreq", -1, NULL, 0);
 }
 
diff --git a/arch/arm/mach-spear/spear1340.c b/arch/arm/mach-spear/spear1340.c
index 94594d5..a212af9 100644
--- a/arch/arm/mach-spear/spear1340.c
+++ b/arch/arm/mach-spear/spear1340.c
@@ -19,7 +19,6 @@
 
 static void __init spear1340_dt_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	platform_device_register_simple("spear-cpufreq", -1, NULL, 0);
 }
 
diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c
index 3bc0dc9..773c04f 100644
--- a/arch/arm/mach-vt8500/vt8500.c
+++ b/arch/arm/mach-vt8500/vt8500.c
@@ -30,7 +30,6 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <linux/of_platform.h>
 
 #define LEGACY_GPIO_BASE	0xD8110000
 #define LEGACY_PMC_BASE		0xD8130000
@@ -158,8 +157,6 @@ static void __init vt8500_init(void)
 		pm_power_off = &vt8500_power_off;
 	else
 		pr_err("%s: PMC Hibernation register could not be remapped, not enabling power off!\n", __func__);
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char * const vt8500_dt_compat[] = {
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:05 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:05 +0800
Subject: [PATCH v4 08/18] mips: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-9-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers about the
of_platform_populate with default match table.

Cc: Ralf Baechle <ralf at linux-mips.org>
Cc: Alban Bedel <albeu at free.fr>
Cc: Paul Burton <paul.burton at imgtec.com>
Cc: James Hogan <james.hogan at imgtec.com>
Cc: Joshua Henderson <joshua.henderson at microchip.com>
Cc: Zubair Lutfullah Kakakhel <Zubair.Kakakhel at imgtec.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/mips/ath79/setup.c           |  2 --
 arch/mips/jz4740/setup.c          |  8 --------
 arch/mips/mti-sead3/sead3-setup.c |  8 --------
 arch/mips/pistachio/init.c        | 13 -------------
 arch/mips/xilfpga/init.c          | 13 -------------
 5 files changed, 44 deletions(-)

diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index be451ee4a..c221506 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -17,7 +17,6 @@
 #include <linux/bootmem.h>
 #include <linux/err.h>
 #include <linux/clk.h>
-#include <linux/of_platform.h>
 #include <linux/of_fdt.h>
 
 #include <asm/bootinfo.h>
@@ -248,7 +247,6 @@ void __init plat_time_init(void)
 
 static int __init ath79_setup(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	if  (mips_machtype == ATH79_MACH_GENERIC_OF)
 		return 0;
 
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index 510fc0d..0914ef7 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/libfdt.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 
 #include <asm/bootinfo.h>
 #include <asm/prom.h>
@@ -74,13 +73,6 @@ void __init device_tree_init(void)
 	unflatten_and_copy_device_tree();
 }
 
-static int __init populate_machine(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	return 0;
-}
-arch_initcall(populate_machine);
-
 const char *get_system_type(void)
 {
 	if (config_enabled(CONFIG_MACH_JZ4780))
diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c
index e43f480..9f85854 100644
--- a/arch/mips/mti-sead3/sead3-setup.c
+++ b/arch/mips/mti-sead3/sead3-setup.c
@@ -8,7 +8,6 @@
  */
 #include <linux/init.h>
 #include <linux/libfdt.h>
-#include <linux/of_platform.h>
 #include <linux/of_fdt.h>
 
 #include <asm/prom.h>
@@ -102,10 +101,3 @@ void __init device_tree_init(void)
 
 	unflatten_and_copy_device_tree();
 }
-
-static int __init customize_machine(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	return 0;
-}
-arch_initcall(customize_machine);
diff --git a/arch/mips/pistachio/init.c b/arch/mips/pistachio/init.c
index 96ba2cc..8b730fe 100644
--- a/arch/mips/pistachio/init.c
+++ b/arch/mips/pistachio/init.c
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 
 #include <asm/cacheflush.h>
 #include <asm/dma-coherence.h>
@@ -122,15 +121,3 @@ void __init device_tree_init(void)
 
 	unflatten_and_copy_device_tree();
 }
-
-static int __init plat_of_setup(void)
-{
-	if (!of_have_populated_dt())
-		panic("Device tree not present");
-
-	if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL))
-		panic("Failed to populate DT");
-
-	return 0;
-}
-arch_initcall(plat_of_setup);
diff --git a/arch/mips/xilfpga/init.c b/arch/mips/xilfpga/init.c
index ce2aee2..602e384 100644
--- a/arch/mips/xilfpga/init.c
+++ b/arch/mips/xilfpga/init.c
@@ -10,7 +10,6 @@
  */
 
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 
 #include <asm/prom.h>
 
@@ -43,15 +42,3 @@ void __init device_tree_init(void)
 
 	unflatten_and_copy_device_tree();
 }
-
-static int __init plat_of_setup(void)
-{
-	if (!of_have_populated_dt())
-		panic("Device tree not present");
-
-	if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL))
-		panic("Failed to populate DT");
-
-	return 0;
-}
-arch_initcall(plat_of_setup);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:05:57 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:05:57 +0800
Subject: [PATCH v4 00/18] Cleanup for populate default bus
Message-ID: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>

This cleanup patchset cantains two parts.

Firstly, introduce a new way to populate the default bus, then, we can
drop unnecessary calls from the arch code, and do the same thing for
of_iommu_init() in [1].

Secondly, use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with default
match table, After that, it is possible for driver code build as a module,
and no need to export of_default_bus_match_table anymore.

This patchset is based on Linux 4.6-rc5, and only test in arm/arm64 qemu
with defconfig.

Changes since v3:
- Get rid of by making of_platform_populate callable multiple times,
  sugguested by Rob Herring

Changes since v2:
- Add more acks
- Update based on v4.6-rc2, of-generic.c in sh and board-artpec6.c in arm
  are considered

Changes since v1:
- Add ack, test and review
- Remove v1 patch 14/15, the similar patch has posted and applied,
  see https://patchwork.kernel.org/patch/8096991/

v1:
- https://lkml.org/lkml/2016/1/26/1123

[1]: https://lkml.org/lkml/2016/4/23/31

Kefeng Wang (18):
  of/platform: Add common method to populate default bus
  arc: Remove unnecessary of_platform_populate with default match table
  arm: Remove unnecessary of_platform_populate with default match table
  arm64: Remove unnecessary of_platform_populate with default match
    table
  c6x: Remove unnecessary of_platform_populate with default match table
  cris: Remove unnecessary of_platform_populate with default match
    table
  metag: Remove unnecessary of_platform_populate with default match
    table
  mips: Remove unnecessary of_platform_populate with default match
    table
  nios2: Remove unnecessary of_platform_populate with default match
    table
  sh: Remove unnecessary of_platform_populate with default match table
  xtensa: Remove unnecessary of_platform_populate with default match
    table
  arm: use of_platform_default_populate() to populate
  mips: use of_platform_default_populate() to populate default bus
  bus: imx-weim: use of_platform_default_populate() to populate default
    bus
  bus: uniphier-system-bus: use of_platform_default_populate() to
    populate default bus
  memory: omap-gpmc: use of_platform_default_populate() to populate
    default bus
  of: unittest: use of_platform_default_populate() to populate default
    bus
  Revert "of/platform: export of_default_bus_match_table"

 arch/arc/kernel/setup.c                  |  6 ------
 arch/arm/kernel/setup.c                  |  6 +-----
 arch/arm/mach-artpec/board-artpec6.c     |  3 ---
 arch/arm/mach-at91/at91rm9200.c          |  2 +-
 arch/arm/mach-at91/at91sam9.c            |  2 +-
 arch/arm/mach-at91/sama5.c               |  2 +-
 arch/arm/mach-bcm/board_bcm21664.c       |  2 --
 arch/arm/mach-bcm/board_bcm281xx.c       |  2 --
 arch/arm/mach-bcm/board_bcm2835.c        | 10 ----------
 arch/arm/mach-cns3xxx/core.c             |  3 +--
 arch/arm/mach-davinci/da8xx-dt.c         |  3 +--
 arch/arm/mach-exynos/exynos.c            |  3 ---
 arch/arm/mach-highbank/highbank.c        |  3 ---
 arch/arm/mach-imx/imx27-dt.c             |  2 --
 arch/arm/mach-imx/mach-imx51.c           |  2 --
 arch/arm/mach-imx/mach-imx53.c           |  2 --
 arch/arm/mach-imx/mach-imx6q.c           |  2 +-
 arch/arm/mach-imx/mach-imx6sl.c          |  2 +-
 arch/arm/mach-imx/mach-imx6sx.c          |  2 +-
 arch/arm/mach-imx/mach-imx6ul.c          |  1 -
 arch/arm/mach-imx/mach-imx7d.c           |  1 -
 arch/arm/mach-integrator/integrator_ap.c |  3 +--
 arch/arm/mach-integrator/integrator_cp.c |  3 +--
 arch/arm/mach-keystone/keystone.c        |  1 -
 arch/arm/mach-lpc32xx/phy3250.c          |  3 +--
 arch/arm/mach-mvebu/board-v7.c           |  3 ---
 arch/arm/mach-mvebu/dove.c               |  2 --
 arch/arm/mach-mvebu/kirkwood.c           |  2 +-
 arch/arm/mach-mxs/mach-mxs.c             |  3 +--
 arch/arm/mach-nspire/nspire.c            |  3 +--
 arch/arm/mach-orion5x/board-dt.c         |  3 +--
 arch/arm/mach-picoxcell/common.c         |  2 --
 arch/arm/mach-rockchip/rockchip.c        |  1 -
 arch/arm/mach-s3c24xx/mach-s3c2416-dt.c  |  2 --
 arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c  |  3 ---
 arch/arm/mach-shmobile/setup-r8a7740.c   |  3 ---
 arch/arm/mach-shmobile/setup-sh73a0.c    |  2 --
 arch/arm/mach-spear/spear1310.c          |  2 --
 arch/arm/mach-spear/spear1340.c          |  1 -
 arch/arm/mach-spear/spear300.c           |  3 +--
 arch/arm/mach-spear/spear310.c           |  3 +--
 arch/arm/mach-spear/spear320.c           |  3 +--
 arch/arm/mach-spear/spear6xx.c           |  3 +--
 arch/arm/mach-tegra/tegra.c              |  2 +-
 arch/arm/mach-u300/core.c                |  3 +--
 arch/arm/mach-versatile/versatile_dt.c   |  3 +--
 arch/arm/mach-vt8500/vt8500.c            |  3 ---
 arch/arm/mach-zynq/common.c              |  2 +-
 arch/arm64/kernel/setup.c                | 13 -------------
 arch/c6x/platforms/Makefile              |  2 +-
 arch/c6x/platforms/platform.c            | 17 -----------------
 arch/cris/kernel/setup.c                 |  8 --------
 arch/metag/kernel/setup.c                |  5 +----
 arch/mips/ath79/setup.c                  |  2 --
 arch/mips/jz4740/setup.c                 |  8 --------
 arch/mips/mti-sead3/sead3-setup.c        |  8 --------
 arch/mips/pic32/pic32mzda/init.c         |  3 +--
 arch/mips/pistachio/init.c               | 13 -------------
 arch/mips/xilfpga/init.c                 | 13 -------------
 arch/nios2/platform/platform.c           |  4 +---
 arch/sh/boards/of-generic.c              | 14 --------------
 arch/xtensa/kernel/setup.c               | 11 -----------
 arch/xtensa/kernel/time.c                |  2 ++
 drivers/bus/imx-weim.c                   |  5 ++---
 drivers/bus/uniphier-system-bus.c        |  3 +--
 drivers/memory/omap-gpmc.c               |  3 +--
 drivers/of/platform.c                    | 24 ++++++++++++++++++++++--
 drivers/of/unittest.c                    |  5 ++---
 68 files changed, 58 insertions(+), 233 deletions(-)
 delete mode 100644 arch/c6x/platforms/platform.c

-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:12 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:12 +0800
Subject: [PATCH v4 15/18] bus: uniphier-system-bus: use
 of_platform_default_populate() to populate default bus
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-16-git-send-email-wangkefeng.wang@huawei.com>

Use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with
the default match table.

Acked-by: Masahiro Yamada <yamada.masahiro at socionext.com>
Cc: Masahiro Yamada <yamada.masahiro at socionext.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/bus/uniphier-system-bus.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/bus/uniphier-system-bus.c b/drivers/bus/uniphier-system-bus.c
index 350b730..1e6e0269 100644
--- a/drivers/bus/uniphier-system-bus.c
+++ b/drivers/bus/uniphier-system-bus.c
@@ -257,8 +257,7 @@ static int uniphier_system_bus_probe(struct platform_device *pdev)
 	uniphier_system_bus_set_reg(priv);
 
 	/* Now, the bus is configured.  Populate platform_devices below it */
-	return of_platform_populate(dev->of_node, of_default_bus_match_table,
-				    NULL, dev);
+	return of_platform_default_populate(dev->of_node, NULL, dev);
 }
 
 static const struct of_device_id uniphier_system_bus_match[] = {
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:05:59 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:05:59 +0800
Subject: [PATCH v4 02/18] arc: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-3-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers about the
of_platform_populate with default match table.

Cc: Vineet Gupta <vgupta at synopsys.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/arc/kernel/setup.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 151acf0..27d25baa 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -15,7 +15,6 @@
 #include <linux/cpu.h>
 #include <linux/clk-provider.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <linux/cache.h>
 #include <asm/sections.h>
 #include <asm/arcregs.h>
@@ -445,11 +444,6 @@ void __init setup_arch(char **cmdline_p)
 static int __init customize_machine(void)
 {
 	of_clk_init(NULL);
-	/*
-	 * Traverses flattened DeviceTree - registering platform devices
-	 * (if any) complete with their resources
-	 */
-	of_platform_default_populate(NULL, NULL, NULL);
 
 	if (machine_desc->init_machine)
 		machine_desc->init_machine();
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:01 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:01 +0800
Subject: [PATCH v4 04/18] arm64: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-5-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers about the
of_platform_populate with default match table.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
Cc: Arnd Bergmann <arnd at arndb.de>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/arm64/kernel/setup.c | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index e20b64f..df6b819 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -40,7 +40,6 @@
 #include <linux/proc_fs.h>
 #include <linux/memblock.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <linux/efi.h>
 #include <linux/psci.h>
 
@@ -361,18 +360,6 @@ void __init setup_arch(char **cmdline_p)
 	}
 }
 
-static int __init arm64_device_init(void)
-{
-	if (of_have_populated_dt()) {
-		of_platform_populate(NULL, of_default_bus_match_table,
-				     NULL, NULL);
-	} else if (acpi_disabled) {
-		pr_crit("Device tree not populated\n");
-	}
-	return 0;
-}
-arch_initcall_sync(arm64_device_init);
-
 static int __init topology_init(void)
 {
 	int i;
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:06 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:06 +0800
Subject: [PATCH v4 09/18] nios2: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-10-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers about the
of_platform_populate with default match table.

Cc: Ley Foon Tan <lftan at altera.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/nios2/platform/platform.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/arch/nios2/platform/platform.c b/arch/nios2/platform/platform.c
index d478773..2a35154 100644
--- a/arch/nios2/platform/platform.c
+++ b/arch/nios2/platform/platform.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
 #include <linux/err.h>
@@ -39,8 +38,7 @@ static int __init nios2_soc_device_init(void)
 		}
 	}
 
-	return of_platform_populate(NULL, of_default_bus_match_table,
-		NULL, NULL);
+	return 0;
 }
 
 device_initcall(nios2_soc_device_init);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:05:58 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:05:58 +0800
Subject: [PATCH v4 01/18] of/platform: Add common method to populate default
 bus
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-2-git-send-email-wangkefeng.wang@huawei.com>

The arch code calls of_platform_populate() with default match table
when it want to populate default bus.

This patch introduce a new of_platform_default_populate_init() and make it
arch_initcall_sync(it should be later than some iommu configration, eg,
of_iommu_init() and swiotlb_late_init in arm64), then we can finish above
job in common method.

In order to avoid the default bus being populated twice, simply checking
the flag of bus node whether has be set OF_POPULATED_BUS or not.

After that, we can safely remove the caller in arch code.

Btw, add debug print in of_platform_populate(), and use __func__ to
print function's name of of_platform_bus_create().

Cc: Rob Herring <robh+dt at kernel.org>
Cc: Frank Rowand <frowand.list at gmail.com>
Cc: Grant Likely <grant.likely at linaro.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/of/platform.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 8d103e4..f601b30 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -11,6 +11,7 @@
  *  2 of the License, or (at your option) any later version.
  *
  */
+#include <linux/acpi.h>
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/amba/bus.h>
@@ -345,6 +346,12 @@ static int of_platform_bus_create(struct device_node *bus,
 		return 0;
 	}
 
+	if (of_node_check_flag(bus, OF_POPULATED_BUS)) {
+		pr_debug("%s() - skipping %s, already populated\n",
+			__func__, bus->full_name);
+		return 0;
+	}
+
 	auxdata = of_dev_lookup(lookup, bus);
 	if (auxdata) {
 		bus_id = auxdata->name;
@@ -396,7 +403,7 @@ int of_platform_bus_probe(struct device_node *root,
 	if (!root)
 		return -EINVAL;
 
-	pr_debug("of_platform_bus_probe()\n");
+	pr_debug("%s()\n", __func__);
 	pr_debug(" starting at: %s\n", root->full_name);
 
 	/* Do a self check of bus type, if there's a match, create children */
@@ -448,6 +455,9 @@ int of_platform_populate(struct device_node *root,
 	if (!root)
 		return -EINVAL;
 
+	pr_debug("%s()\n", __func__);
+	pr_debug(" starting at: %s\n", root->full_name);
+
 	for_each_child_of_node(root, child) {
 		rc = of_platform_bus_create(child, matches, lookup, parent, true);
 		if (rc) {
@@ -471,6 +481,17 @@ int of_platform_default_populate(struct device_node *root,
 }
 EXPORT_SYMBOL_GPL(of_platform_default_populate);
 
+static int __init of_platform_default_populate_init(void)
+{
+	if (of_have_populated_dt())
+		of_platform_default_populate(NULL, NULL, NULL);
+	else if (acpi_disabled)
+		pr_crit("Device tree not populated\n");
+
+	return 0;
+}
+arch_initcall_sync(of_platform_default_populate_init);
+
 static int of_platform_device_destroy(struct device *dev, void *data)
 {
 	/* Do not touch devices not populated from the device tree */
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:13 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:13 +0800
Subject: [PATCH v4 16/18] memory: omap-gpmc: use
 of_platform_default_populate() to populate default bus
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-17-git-send-email-wangkefeng.wang@huawei.com>

Use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with
the default match table.

Acked-by: Roger Quadros <rogerq at ti.com>
Cc: Roger Quadros <rogerq at ti.com>
Cc: Tony Lindgren <tony at atomide.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/memory/omap-gpmc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 21825dd..b9f6cc8 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -2046,8 +2046,7 @@ no_timings:
 	/* is child a common bus? */
 	if (of_match_node(of_default_bus_match_table, child))
 		/* create children and other common bus children */
-		if (of_platform_populate(child, of_default_bus_match_table,
-					 NULL, &pdev->dev))
+		if (of_platform_default_populate(child, NULL, &pdev->dev))
 			goto err_child_fail;
 
 	return 0;
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:10 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:10 +0800
Subject: [PATCH v4 13/18] mips: use of_platform_default_populate() to populate
 default bus
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-14-git-send-email-wangkefeng.wang@huawei.com>

Use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with
the default match table.

Cc: Joshua Henderson <joshua.henderson at microchip.com>
Cc: Ralf Baechle <ralf at linux-mips.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/mips/pic32/pic32mzda/init.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/mips/pic32/pic32mzda/init.c b/arch/mips/pic32/pic32mzda/init.c
index 775ff90..77ecf32 100644
--- a/arch/mips/pic32/pic32mzda/init.c
+++ b/arch/mips/pic32/pic32mzda/init.c
@@ -147,8 +147,7 @@ static int __init plat_of_setup(void)
 		panic("Device tree not present");
 
 	pic32_of_prepare_platform_data(pic32_auxdata_lookup);
-	if (of_platform_populate(NULL, of_default_bus_match_table,
-				 pic32_auxdata_lookup, NULL))
+	if (of_platform_default_populate(NULL, pic32_auxdata_lookup, NULL))
 		panic("Failed to populate DT");
 
 	return 0;
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:08 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:08 +0800
Subject: [PATCH v4 11/18] xtensa: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-12-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers about the
of_platform_populate with default match table.

Move of_clk_init() into time_init(), then drop xtensa_device_probe() fully.

Cc: Chris Zankel <chris at zankel.net>
Cc: Max Filippov <jcmvbkbc at gmail.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/xtensa/kernel/setup.c | 11 -----------
 arch/xtensa/kernel/time.c  |  2 ++
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 9735691..18af563 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -22,10 +22,8 @@
 #include <linux/bootmem.h>
 #include <linux/kernel.h>
 #include <linux/percpu.h>
-#include <linux/clk-provider.h>
 #include <linux/cpu.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
 # include <linux/console.h>
@@ -252,15 +250,6 @@ void __init early_init_devtree(void *params)
 		strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 }
 
-static int __init xtensa_device_probe(void)
-{
-	of_clk_init(NULL);
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	return 0;
-}
-
-device_initcall(xtensa_device_probe);
-
 #endif /* CONFIG_OF */
 
 /*
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index b9ad9fe..6ec73c9 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -15,6 +15,7 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/time.h>
+#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
@@ -148,6 +149,7 @@ void __init time_init(void)
 	local_timer_setup(0);
 	setup_irq(this_cpu_ptr(&ccount_timer)->evt.irq, &timer_irqaction);
 	sched_clock_register(ccount_sched_clock_read, 32, ccount_freq);
+	of_clk_init(NULL);
 	clocksource_probe();
 }
 
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:03 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:03 +0800
Subject: [PATCH v4 06/18] cris: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-7-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers about the
of_platform_populate with default match table.

Cc: Mikael Starvik <starvik at axis.com>
Cc: Jesper Nilsson <jesper.nilsson at axis.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/cris/kernel/setup.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index bb12aa9..4b4853d 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -21,7 +21,6 @@
 #include <linux/cpu.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <asm/setup.h>
 #include <arch/system.h>
 
@@ -212,10 +211,3 @@ static int __init topology_init(void)
 }
 
 subsys_initcall(topology_init);
-
-static int __init cris_of_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	return 0;
-}
-core_initcall(cris_of_init);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:02 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:02 +0800
Subject: [PATCH v4 05/18] c6x: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-6-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers about the
of_platform_populate with default match table.

Cc: Mikael Starvik <starvik at axis.com>
Cc: Jesper Nilsson <jesper.nilsson at axis.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/c6x/platforms/Makefile   |  2 +-
 arch/c6x/platforms/platform.c | 17 -----------------
 2 files changed, 1 insertion(+), 18 deletions(-)
 delete mode 100644 arch/c6x/platforms/platform.c

diff --git a/arch/c6x/platforms/Makefile b/arch/c6x/platforms/Makefile
index 9a95b9b..5f7d934 100644
--- a/arch/c6x/platforms/Makefile
+++ b/arch/c6x/platforms/Makefile
@@ -4,7 +4,7 @@
 # Copyright 2010, 2011 Texas Instruments Incorporated
 #
 
-obj-y = platform.o cache.o megamod-pic.o pll.o plldata.o timer64.o
+obj-y = cache.o megamod-pic.o pll.o plldata.o timer64.o
 obj-y += dscr.o
 
 # SoC objects
diff --git a/arch/c6x/platforms/platform.c b/arch/c6x/platforms/platform.c
deleted file mode 100644
index 26c1a35..0000000
--- a/arch/c6x/platforms/platform.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2011 Texas Instruments Incorporated
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#include <linux/init.h>
-#include <linux/of_platform.h>
-
-static int __init c6x_device_probe(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	return 0;
-}
-core_initcall(c6x_device_probe);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:09 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:09 +0800
Subject: [PATCH v4 12/18] arm: use of_platform_default_populate() to populate
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-13-git-send-email-wangkefeng.wang@huawei.com>

Use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with
the default match table.

Cc: Nicolas Ferre <nicolas.ferre at atmel.com>
Cc: Krzysztof Halasa <khalasa at piap.pl>
Cc: Sekhar Nori <nsekhar at ti.com>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Roland Stigge <stigge at antcom.de>
Cc: Jason Cooper <jason at lakedaemon.net>
Cc: Ray Jui <rjui at broadcom.com>
Cc: Viresh Kumar <vireshk at kernel.org>
Cc: Stephen Warren <swarren at wwwdotorg.org>
Cc: Rob Herring <robh at kernel.org>
Cc: Michal Simek <michal.simek at xilinx.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/arm/mach-at91/at91rm9200.c          | 2 +-
 arch/arm/mach-at91/at91sam9.c            | 2 +-
 arch/arm/mach-at91/sama5.c               | 2 +-
 arch/arm/mach-cns3xxx/core.c             | 3 +--
 arch/arm/mach-davinci/da8xx-dt.c         | 3 +--
 arch/arm/mach-imx/mach-imx6q.c           | 2 +-
 arch/arm/mach-imx/mach-imx6sl.c          | 2 +-
 arch/arm/mach-imx/mach-imx6sx.c          | 2 +-
 arch/arm/mach-integrator/integrator_ap.c | 3 +--
 arch/arm/mach-integrator/integrator_cp.c | 3 +--
 arch/arm/mach-lpc32xx/phy3250.c          | 3 +--
 arch/arm/mach-mvebu/kirkwood.c           | 2 +-
 arch/arm/mach-mxs/mach-mxs.c             | 3 +--
 arch/arm/mach-nspire/nspire.c            | 3 +--
 arch/arm/mach-orion5x/board-dt.c         | 3 +--
 arch/arm/mach-spear/spear300.c           | 3 +--
 arch/arm/mach-spear/spear310.c           | 3 +--
 arch/arm/mach-spear/spear320.c           | 3 +--
 arch/arm/mach-spear/spear6xx.c           | 3 +--
 arch/arm/mach-tegra/tegra.c              | 2 +-
 arch/arm/mach-u300/core.c                | 3 +--
 arch/arm/mach-versatile/versatile_dt.c   | 3 +--
 arch/arm/mach-zynq/common.c              | 2 +-
 23 files changed, 23 insertions(+), 37 deletions(-)

diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index 63b4fa2..d068ec3 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -30,7 +30,7 @@ static void __init at91rm9200_dt_device_init(void)
 	if (soc != NULL)
 		soc_dev = soc_device_to_device(soc);
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev);
+	of_platform_default_populate(NULL, NULL, soc_dev);
 
 	at91rm9200_pm_init();
 }
diff --git a/arch/arm/mach-at91/at91sam9.c b/arch/arm/mach-at91/at91sam9.c
index cada2a6..ba28e9c 100644
--- a/arch/arm/mach-at91/at91sam9.c
+++ b/arch/arm/mach-at91/at91sam9.c
@@ -61,7 +61,7 @@ static void __init at91sam9_common_init(void)
 	if (soc != NULL)
 		soc_dev = soc_device_to_device(soc);
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev);
+	of_platform_default_populate(NULL, NULL, soc_dev);
 }
 
 static void __init at91sam9_dt_device_init(void)
diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c
index df8fdf1..c7d17df 100644
--- a/arch/arm/mach-at91/sama5.c
+++ b/arch/arm/mach-at91/sama5.c
@@ -50,7 +50,7 @@ static void __init sama5_dt_device_init(void)
 	if (soc != NULL)
 		soc_dev = soc_device_to_device(soc);
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev);
+	of_platform_default_populate(NULL, NULL, soc_dev);
 	sama5_pm_init();
 }
 
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index 9b1dc22..03da381 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -395,8 +395,7 @@ static void __init cns3xxx_init(void)
 
 	pm_power_off = cns3xxx_power_off;
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-                        cns3xxx_auxdata, NULL);
+	of_platform_default_populate(NULL, cns3xxx_auxdata, NULL);
 }
 
 static const char *const cns3xxx_dt_compat[] __initconst = {
diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c
index c4b5808..da46dc7 100644
--- a/arch/arm/mach-davinci/da8xx-dt.c
+++ b/arch/arm/mach-davinci/da8xx-dt.c
@@ -54,8 +54,7 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
 
 static void __init da850_init_machine(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     da850_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, da850_auxdata_lookup, NULL);
 
 }
 
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index cb27d56..e394070 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -278,7 +278,7 @@ static void __init imx6q_init_machine(void)
 
 	imx6q_enet_phy_init();
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+	of_platform_default_populate(NULL, NULL, parent);
 
 	imx_anatop_init();
 	cpu_is_imx6q() ?  imx6q_pm_init() : imx6dl_pm_init();
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index 3003263..37ae87d 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -52,7 +52,7 @@ static void __init imx6sl_init_machine(void)
 	if (parent == NULL)
 		pr_warn("failed to initialize soc device\n");
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+	of_platform_default_populate(NULL, NULL, parent);
 
 	imx6sl_fec_init();
 	imx_anatop_init();
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 6a0b061..107cfc1 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -72,7 +72,7 @@ static void __init imx6sx_init_machine(void)
 	if (parent == NULL)
 		pr_warn("failed to initialize soc device\n");
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+	of_platform_default_populate(NULL, NULL, parent);
 
 	imx6sx_enet_init();
 	imx_anatop_init();
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 5b0e363..4c2facd 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -302,8 +302,7 @@ static void __init ap_init_of(void)
 	if (!ebi_base)
 		return;
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			ap_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, ap_auxdata_lookup, NULL);
 
 	sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
 	for (i = 0; i < 4; i++) {
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index b5fb71a..31d893e 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -282,8 +282,7 @@ static void __init intcp_init_of(void)
 	if (!intcp_con_base)
 		return;
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     intcp_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, intcp_auxdata_lookup, NULL);
 }
 
 static const char * intcp_dt_board_compat[] = {
diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c
index b2f9e22..c6ec7ba 100644
--- a/arch/arm/mach-lpc32xx/phy3250.c
+++ b/arch/arm/mach-lpc32xx/phy3250.c
@@ -191,8 +191,7 @@ static void __init lpc3250_machine_init(void)
 		LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN,
 		LPC32XX_CLKPWR_TEST_CLK_SEL);
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     lpc32xx_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, lpc32xx_auxdata_lookup, NULL);
 }
 
 static const char *const lpc32xx_dt_compat[] __initconst = {
diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c
index f9d8e1e..8f459ee 100644
--- a/arch/arm/mach-mvebu/kirkwood.c
+++ b/arch/arm/mach-mvebu/kirkwood.c
@@ -179,7 +179,7 @@ static void __init kirkwood_dt_init(void)
 	kirkwood_pm_init();
 	kirkwood_dt_eth_fixup();
 
-	of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL);
+	of_platform_default_populate(NULL, auxdata, NULL);
 }
 
 static const char * const kirkwood_dt_board_compat[] __initconst = {
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index f1ea470..0b7fe74 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -498,8 +498,7 @@ static void __init mxs_machine_init(void)
 	else if (of_machine_is_compatible("msr,m28cu3"))
 		m28cu3_init();
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     NULL, parent);
+	of_platform_default_populate(NULL, NULL, parent);
 
 	mxs_restart_init();
 
diff --git a/arch/arm/mach-nspire/nspire.c b/arch/arm/mach-nspire/nspire.c
index 34c2a1b3..f0808fc 100644
--- a/arch/arm/mach-nspire/nspire.c
+++ b/arch/arm/mach-nspire/nspire.c
@@ -57,8 +57,7 @@ static struct of_dev_auxdata nspire_auxdata[] __initdata = {
 
 static void __init nspire_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-			nspire_auxdata, NULL);
+	of_platform_default_populate(NULL, nspire_auxdata, NULL);
 }
 
 static void nspire_restart(enum reboot_mode mode, const char *cmd)
diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c
index 6f4c2c4..3d36f1d 100644
--- a/arch/arm/mach-orion5x/board-dt.c
+++ b/arch/arm/mach-orion5x/board-dt.c
@@ -63,8 +63,7 @@ static void __init orion5x_dt_init(void)
 	if (of_machine_is_compatible("maxtor,shared-storage-2"))
 		mss2_init();
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     orion5x_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, orion5x_auxdata_lookup, NULL);
 }
 
 static const char *orion5x_dt_compat[] = {
diff --git a/arch/arm/mach-spear/spear300.c b/arch/arm/mach-spear/spear300.c
index 5b32edd..325b895 100644
--- a/arch/arm/mach-spear/spear300.c
+++ b/arch/arm/mach-spear/spear300.c
@@ -194,8 +194,7 @@ static void __init spear300_dt_init(void)
 	pl080_plat_data.slave_channels = spear300_dma_info;
 	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear300_dma_info);
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear300_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, spear300_auxdata_lookup, NULL);
 }
 
 static const char * const spear300_dt_board_compat[] = {
diff --git a/arch/arm/mach-spear/spear310.c b/arch/arm/mach-spear/spear310.c
index 86a44ac..59e173d 100644
--- a/arch/arm/mach-spear/spear310.c
+++ b/arch/arm/mach-spear/spear310.c
@@ -236,8 +236,7 @@ static void __init spear310_dt_init(void)
 	pl080_plat_data.slave_channels = spear310_dma_info;
 	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear310_dma_info);
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear310_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, spear310_auxdata_lookup, NULL);
 }
 
 static const char * const spear310_dt_board_compat[] = {
diff --git a/arch/arm/mach-spear/spear320.c b/arch/arm/mach-spear/spear320.c
index d45d751..0958f68 100644
--- a/arch/arm/mach-spear/spear320.c
+++ b/arch/arm/mach-spear/spear320.c
@@ -240,8 +240,7 @@ static void __init spear320_dt_init(void)
 	pl080_plat_data.slave_channels = spear320_dma_info;
 	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear320_dma_info);
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear320_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, spear320_auxdata_lookup, NULL);
 }
 
 static const char * const spear320_dt_board_compat[] = {
diff --git a/arch/arm/mach-spear/spear6xx.c b/arch/arm/mach-spear/spear6xx.c
index da26fa5b..ccf3573 100644
--- a/arch/arm/mach-spear/spear6xx.c
+++ b/arch/arm/mach-spear/spear6xx.c
@@ -411,8 +411,7 @@ struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
 
 static void __init spear600_dt_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear6xx_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, spear6xx_auxdata_lookup, NULL);
 }
 
 static const char *spear600_dt_board_compat[] = {
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index 2378fa56..6745a65 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -115,7 +115,7 @@ static void __init tegra_dt_init(void)
 	 * devices
 	 */
 out:
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+	of_platform_default_populate(NULL, NULL, parent);
 }
 
 static void __init paz00_init(void)
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index 546338b..a4910ea 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -391,8 +391,7 @@ static void __init u300_init_machine_dt(void)
 	pinctrl_register_mappings(u300_pinmux_map,
 				  ARRAY_SIZE(u300_pinmux_map));
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			u300_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, u300_auxdata_lookup, NULL);
 
 	/* Enable SEMI self refresh */
 	val = readw(syscon_base + U300_SYSCON_SMCR) |
diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c
index dff1c05..efcf7b9 100644
--- a/arch/arm/mach-versatile/versatile_dt.c
+++ b/arch/arm/mach-versatile/versatile_dt.c
@@ -391,8 +391,7 @@ static void __init versatile_dt_init(void)
 	versatile_dt_pci_init();
 
 	platform_device_register(&versatile_flash_device);
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     versatile_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, versatile_auxdata_lookup, NULL);
 }
 
 static const char *const versatile_dt_match[] __initconst = {
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index 860ffb6..06abe29 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -142,7 +142,7 @@ out:
 	 * Finished with the static registrations now; fill in the missing
 	 * devices
 	 */
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+	of_platform_default_populate(NULL, NULL, parent);
 
 	platform_device_register(&zynq_cpuidle_device);
 	platform_device_register_full(&devinfo);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:04 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:04 +0800
Subject: [PATCH v4 07/18] metag: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-8-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers about the
of_platform_populate with default match table.

Cc: James Hogan <james.hogan at imgtec.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/metag/kernel/setup.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/arch/metag/kernel/setup.c b/arch/metag/kernel/setup.c
index 31cf53d..1166f1f 100644
--- a/arch/metag/kernel/setup.c
+++ b/arch/metag/kernel/setup.c
@@ -20,7 +20,6 @@
 #include <linux/memblock.h>
 #include <linux/mm.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <linux/pfn.h>
 #include <linux/root_dev.h>
 #include <linux/sched.h>
@@ -414,9 +413,7 @@ static int __init customize_machine(void)
 	/* customizes platform devices, or adds new ones */
 	if (machine_desc->init_machine)
 		machine_desc->init_machine();
-	else
-		of_platform_populate(NULL, of_default_bus_match_table, NULL,
-				     NULL);
+
 	return 0;
 }
 arch_initcall(customize_machine);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:07 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:07 +0800
Subject: [PATCH v4 10/18] sh: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-11-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers about the
of_platform_populate with default match table.

Cc: Yoshinori Sato <ysato at users.sourceforge.jp>
Cc: Rich Felker <dalias at libc.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/sh/boards/of-generic.c | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c
index b4d4313..911ffb9 100644
--- a/arch/sh/boards/of-generic.c
+++ b/arch/sh/boards/of-generic.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/of.h>
-#include <linux/of_platform.h>
 #include <linux/of_fdt.h>
 #include <linux/clocksource.h>
 #include <linux/irqchip.h>
@@ -179,16 +178,3 @@ void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
 void __init plat_irq_setup(void)
 {
 }
-
-static int __init sh_of_device_init(void)
-{
-	pr_info("SH generic board support: populating platform devices\n");
-	if (of_have_populated_dt()) {
-		of_platform_populate(NULL, of_default_bus_match_table,
-				     NULL, NULL);
-	} else {
-		pr_crit("Device tree not populated\n");
-	}
-	return 0;
-}
-arch_initcall_sync(sh_of_device_init);
-- 
1.7.12.4



From chunkeey at googlemail.com  Thu May 12 05:07:24 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Thu, 12 May 2016 14:07:24 +0200
Subject: [PATCH v9 1/2] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <0a1ab2b6-b4c5-44d7-abb4-ce1e9da7e477@gmail.com>
References: <cover.1462911225.git.chunkeey@googlemail.com>
 <2c0675cd6f67bd487105c46c38c72d49d84d4df8.1462911225.git.chunkeey@googlemail.com>
 <0a1ab2b6-b4c5-44d7-abb4-ce1e9da7e477@gmail.com>
Message-ID: <4114007.EkZL1biBx8@debian64>

On Thursday, May 12, 2016 07:26:32 PM Alexandre Courbot wrote:
> On Wednesday, May 11, 2016 6:34:34 PM JST, Christian Lamparter wrote:
> > From: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
> >
> > This patch adds support for defining memory-mapped GPIOs which
> > are compatible with the existing gpio-mmio interface. The generic
> > library provides support for many memory-mapped GPIO controllers
> > that are found in various on-board FPGA and ASIC solutions that
> > are used to control board's switches, LEDs, chip-selects,
> > Ethernet/USB PHY power, etc.
> >
> > For setting GPIO's there are three configurations:
> 
> s/GPIO's/GPIOs
OK

> > 	1. single input/output register resource (named "dat"),
> > 	2. set/clear pair (named "set" and "clr"),
> > 	3. single output register resource and single input resource
> > 	   ("set" and dat").
> >
> > The configuration is detected by which resources are present.
> > For the single output register, this drives a 1 by setting a bit
> > and a zero by clearing a bit.  For the set clr pair, this drives
> > a 1 by setting a bit in the set register and clears it by setting
> > a bit in the clear register. The configuration is detected by
> > which resources are present.
> 
> The last sentence of this paragraph repeats for first one.
Ok

> >
> > For setting the GPIO direction, there are three configurations:
> > 	a. simple bidirectional GPIOs that requires no configuration.
> > 	b. an output direction register (named "dirout")
> > 	   where a 1 bit indicates the GPIO is an output.
> > 	c. an input direction register (named "dirin")
> > 	   where a 1 bit indicates the GPIO is an input.
> >
> > The first user for this binding is "wd,mbl-gpio".
> >
> > Reviewed-by: Andy Shevchenko <andy.shevchenko at gmail.com>
> > Signed-off-by: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
> > Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
> > ---
> >  static void bgpio_write8(void __iomem *reg, unsigned long data)
> >  {
> > @@ -569,6 +571,58 @@ static void __iomem *bgpio_map(struct 
> > platform_device *pdev,
> >  	return devm_ioremap_resource(&pdev->dev, r);
> >  }
> >  
> > +#ifdef CONFIG_OF
> > +static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
> > +				     struct bgpio_pdata *pdata,
> > +				     unsigned long *flags)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +
> > +	pdata->base = -1;
> > +
> > +	if (of_property_read_bool(dev->of_node, "no-output"))
> > +		*flags |= BGPIOF_NO_OUTPUT;
> 
> I don't think it is a good idea to add "generic" properties. Whether a 
> controller is capable of output or not should be determined by its 
> compatible string only, and not a vague property.

Well, meet the gpios on the MBL. If you want to figure out how WD wired
up these two GPIOs (one is input, the other output), I can sent you a
built-yourself MBL kit. It just needs a 3,5" drive and a 12V 2A power
plug with a standard 5.5mm plug.

> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id bgpio_of_match[] = {
> > +	{ .compatible = "wd,mbl-gpio", .data = bgpio_basic_mmio_parse_dt },
> 
> Mmm cannot you determine whether your controller is capable of output or 
> not just from the compatible property here? If so, the 
> bgpio_basic_mmio_parse_dt seems to be unneeded. If not, then this is 
> dependent on the wd,mbl-gpio binding and should be renamed accordingly.
Sadly I don't know of any method. The device has two GPIOs one at 0x4e0000000.
The other one is at 0x4e0100000. The address tells me that there are two 
external chips connected to the EBC (memory bank - RAM, ROM and DMA chips
go here according to IBM's documentations). Which is not the place you
would expect peripherals. 

> > @@ -646,6 +709,7 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table);
> >  static struct platform_driver bgpio_driver = {
> >  	.driver = {
> >  		.name = "basic-mmio-gpio",
> > +		.of_match_table = of_match_ptr(bgpio_of_match),
> >  	},
> >  	.id_table = bgpio_id_table,
> >  	.probe = bgpio_pdev_probe,
> 
> It seems to me that this patch does two things:
> 
> 1) Add code to support device tree lookup
> 2) Add support for "wd,mbl-gpio".
> 
> If true, these two things should be in their own patches. You should also 
> have another patch that adds the DT bindings for "wd,mbl-gpio", so I would 
> do things in that order:

The DT bindings have been merged. That's why I dropped it from the rebase.

> 1/3: DT support for basic-mmio-gpio
Sadly, adding the "basic-mmio-gpio" binding is not possible without a ACK from
the device tree maintainers. They have voiced their concerns. I think this was
your post of the discussion on it:
<http://www.spinics.net/lists/devicetree/msg124613.html>

That's why the series was updated around v5 and v6 to use the "wd,mbl-gpio"
binding.

So yes, I wanted to go this route in the beginning as well. But no go.
If we find more devices we could have a "basic-mmio-gpio" class. But
for now, we have to start somewhere.

> 2/3: DT bindings for "wd,mbl-gpio" (and have them validated by the DT 
> people - e.g. do you really need a "reg" property or is it here just to fit 
> with what bgpio_pdev_probe expects? More about this on 2/2)
> 3/3: Support for "wd,mbl-gpio" in basic-mmio-gpio
Yes, that would have been nice. And I agree it was the way to do it. But
without the wd,mbl-gpio mapping I would add the bgpio_parse_dt function
without any caller. (As I can't add the compatible = "basic-mmio-gpio", ...)

Regards,
Christian


From wangkefeng.wang at huawei.com  Thu May 12 05:06:15 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:15 +0800
Subject: [PATCH v4 18/18] Revert "of/platform: export
 of_default_bus_match_table"
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-19-git-send-email-wangkefeng.wang@huawei.com>

This reverts commit b80443c2211c7daaabd20fbbe9e7beb3fa3408e0.

After covering to use helper of_platform_default_populate() to populate
the default bus, no need to export of_default_bus_match_table anymore.

Reviewed-by: Masahiro Yamada <yamada.masahiro at socionext.com>
Cc: Masahiro Yamada <yamada.masahiro at socionext.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Frank Rowand <frowand.list at gmail.com>
Cc: Grant Likely <grant.likely at linaro.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/of/platform.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index f601b30..3ea8610 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -32,7 +32,6 @@ const struct of_device_id of_default_bus_match_table[] = {
 #endif /* CONFIG_ARM_AMBA */
 	{} /* Empty terminated list */
 };
-EXPORT_SYMBOL(of_default_bus_match_table);
 
 static int of_dev_node_match(struct device *dev, void *data)
 {
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:06:14 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:14 +0800
Subject: [PATCH v4 17/18] of: unittest: use of_platform_default_populate() to
 populate default bus
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-18-git-send-email-wangkefeng.wang@huawei.com>

Use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with
the default match table.

Cc: Rob Herring <robh+dt at kernel.org>
Cc: Frank Rowand <frowand.list at gmail.com>
Cc: Grant Likely <grant.likely at linaro.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/of/unittest.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index e986e6e..e72cee3 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -772,7 +772,7 @@ static void __init of_unittest_platform_populate(void)
 	};
 
 	np = of_find_node_by_path("/testcase-data");
-	of_platform_populate(np, of_default_bus_match_table, NULL, NULL);
+	of_platform_default_populate(np, NULL, NULL);
 
 	/* Test that a missing irq domain returns -EPROBE_DEFER */
 	np = of_find_node_by_path("/testcase-data/testcase-device1");
@@ -1885,8 +1885,7 @@ static void __init of_unittest_overlay(void)
 		goto out;
 	}
 
-	ret = of_platform_populate(bus_np, of_default_bus_match_table,
-			NULL, NULL);
+	ret = of_platform_default_populate(bus_np, NULL, NULL);
 	if (ret != 0) {
 		unittest(0, "could not populate bus @ \"%s\"\n", bus_path);
 		goto out;
-- 
1.7.12.4



From helgaas at kernel.org  Thu May 12 05:08:36 2016
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Thu, 12 May 2016 07:08:36 -0500
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <57345FDF.4000804@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
 <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>
 <20160511101101.GA16101@red-moon>
 <CAJZ5v0hgw929W5PjF0PqT+ssiOHd8TeJoSQcz4NUiAovZY2pfQ@mail.gmail.com>
 <20160511224314.GD28812@localhost> <57345FDF.4000804@semihalf.com>
Message-ID: <20160512120836.GF28812@localhost>

On Thu, May 12, 2016 at 12:50:07PM +0200, Tomasz Nowicki wrote:
> On 12.05.2016 00:43, Bjorn Helgaas wrote:

> >@@ -70,9 +71,11 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
> >  	cfg->res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
> >  	cfg->res.name = "PCI ECAM";
> >
> >-	err = request_resource(&iomem_resource, &cfg->res);
> >-	if (err) {
> >-		dev_err(dev, "request ECAM res %pR failed\n", &cfg->res);
> >+	conflict = request_resource(&iomem_resource, &cfg->res);
> 
> We need request_resource_conflict here then:
> -	conflict = request_resource(&iomem_resource, &cfg->res);
> +	conflict = request_resource_conflict(&iomem_resource, &cfg->res);

Whoops, fixed, thanks!


From wangkefeng.wang at huawei.com  Thu May 12 05:06:11 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:06:11 +0800
Subject: [PATCH v4 14/18] bus: imx-weim: use of_platform_default_populate() to
 populate default bus
In-Reply-To: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463054775-18170-15-git-send-email-wangkefeng.wang@huawei.com>

Use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with
the default match table.

Acked-by: Shawn Guo <shawn.guo at linaro.org>
Cc: Signed-off-by: Huang Shijie <b32955 at freescale.com>
Cc: Shawn Guo <shawn.guo at linaro.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/bus/imx-weim.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index 1827fc4..4bd361d 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -163,9 +163,8 @@ static int __init weim_parse_dt(struct platform_device *pdev,
 	}
 
 	if (have_child)
-		ret = of_platform_populate(pdev->dev.of_node,
-				   of_default_bus_match_table,
-				   NULL, &pdev->dev);
+		ret = of_platform_default_populate(pdev->dev.of_node,
+						   NULL, &pdev->dev);
 	if (ret)
 		dev_err(&pdev->dev, "%s fail to create devices.\n",
 			pdev->dev.of_node->full_name);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Thu May 12 05:16:27 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:16:27 +0800
Subject: [PATCH v3 2/2] arm64: mm: Show bss segment in kernel memory layout
In-Reply-To: <1463055387-19289-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1460948988-7477-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463055387-19289-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463055387-19289-3-git-send-email-wangkefeng.wang@huawei.com>

Show the bss segment information as with text and data in Virtual
memory kernel layout.

Acked-by: James Morse <james.morse at arm.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/arm64/mm/init.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index ce2e400..c96fe51 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -379,6 +379,8 @@ void __init mem_init(void)
 		MLK_ROUNDUP(__init_begin, __init_end));
 	pr_cont("      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
 		MLK_ROUNDUP(_sdata, _edata));
+	pr_cont("       .bss : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+		MLK_ROUNDUP(__bss_start, __bss_stop));
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
 	pr_cont("    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n",
 		MLG(VMEMMAP_START, VMEMMAP_START + VMEMMAP_SIZE));
-- 
2.6.0.GIT



From wangkefeng.wang at huawei.com  Thu May 12 05:16:26 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:16:26 +0800
Subject: [PATCH v3 1/2] arm64: mm: make pr_cont() per line in Virtual kernel
 memory layout
In-Reply-To: <1463055387-19289-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1460948988-7477-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463055387-19289-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463055387-19289-2-git-send-email-wangkefeng.wang@huawei.com>

Each line with single pr_cont() in Virtual kernel memory layout,
or the dump of the kernel memory layout in dmesg is not aligned
when PRINTK_TIME enabled, due to the missing time stamps.

Tested-by: James Morse <james.morse at arm.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/arm64/mm/init.c | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index ea989d8..ce2e400 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -371,19 +371,18 @@ void __init mem_init(void)
 		MLM(MODULES_VADDR, MODULES_END));
 	pr_cont("    vmalloc : 0x%16lx - 0x%16lx   (%6ld GB)\n",
 		MLG(VMALLOC_START, VMALLOC_END));
-	pr_cont("      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n"
-		"    .rodata : 0x%p" " - 0x%p" "   (%6ld KB)\n"
-		"      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n"
-		"      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
-		MLK_ROUNDUP(_text, __start_rodata),
-		MLK_ROUNDUP(__start_rodata, _etext),
-		MLK_ROUNDUP(__init_begin, __init_end),
+	pr_cont("      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+		MLK_ROUNDUP(_text, __start_rodata));
+	pr_cont("    .rodata : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+		MLK_ROUNDUP(__start_rodata, _etext));
+	pr_cont("      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+		MLK_ROUNDUP(__init_begin, __init_end));
+	pr_cont("      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
 		MLK_ROUNDUP(_sdata, _edata));
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
-	pr_cont("    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n"
-		"              0x%16lx - 0x%16lx   (%6ld MB actual)\n",
-		MLG(VMEMMAP_START,
-		    VMEMMAP_START + VMEMMAP_SIZE),
+	pr_cont("    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n",
+		MLG(VMEMMAP_START, VMEMMAP_START + VMEMMAP_SIZE));
+	pr_cont("              0x%16lx - 0x%16lx   (%6ld MB actual)\n",
 		MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()),
 		    (unsigned long)virt_to_page(high_memory)));
 #endif
-- 
2.6.0.GIT



From wangkefeng.wang at huawei.com  Thu May 12 05:16:25 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 20:16:25 +0800
Subject: [PATCH v3 0/2] arm64: mm: Enhance Virtual kernel memory layout
In-Reply-To: <1460948988-7477-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1460948988-7477-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1463055387-19289-1-git-send-email-wangkefeng.wang@huawei.com>

This is a micro enhance for Virtual kernel memory layout. Show bss info,
and make each line with single pr_cont().

With this patchset,

[    0.000000] Virtual kernel memory layout:
[    0.000000]     modules : 0xffffff8000000000 - 0xffffff8008000000   (   128 MB)
[    0.000000]     vmalloc : 0xffffff8008000000 - 0xffffffbdbfff0000   (   246 GB)
[    0.000000]       .text : 0xffffff8008080000 - 0xffffff8008755000   (  6996 KB)
[    0.000000]     .rodata : 0xffffff8008755000 - 0xffffff8008a3d000   (  2976 KB)
[    0.000000]       .init : 0xffffff8008a3d000 - 0xffffff8008b09000   (   816 KB)
[    0.000000]       .data : 0xffffff8008b09000 - 0xffffff8008ba6800   (   630 KB)
[    0.000000]        .bss : 0xffffff8008ba6800 - 0xffffff8008be3738   (   244 KB)
[    0.000000]     vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000   (     8 GB maximum)
[    0.000000]               0xffffffbdc0000000 - 0xffffffbdc8000000   (   128 MB actual)
[    0.000000]     fixed   : 0xffffffbffe7fd000 - 0xffffffbffec00000   (  4108 KB)
[    0.000000]     PCI I/O : 0xffffffbffee00000 - 0xffffffbfffe00000   (    16 MB)
[    0.000000]     memory  : 0xffffffc000000000 - 0xffffffc200000000   (  8192 MB)

Before,

[    0.000000] Virtual kernel memory layout:
[    0.000000]     modules : 0xffffff8000000000 - 0xffffff8008000000   (   128 MB)
[    0.000000]     vmalloc : 0xffffff8008000000 - 0xffffffbdbfff0000   (   246 GB)
[    0.000000]       .text : 0xffffff8008080000 - 0xffffff8008753000   (  6988 KB)
    .rodata : 0xffffff8008753000 - 0xffffff8008a3a000   (  2972 KB)
      .init : 0xffffff8008a3a000 - 0xffffff8008b06000   (   816 KB)
      .data : 0xffffff8008b06000 - 0xffffff8008ba2400   (   625 KB)
[    0.000000]     vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000   (     8 GB maximum)
              0xffffffbdc0000000 - 0xffffffbdc8000000   (   128 MB actual)
[    0.000000]     fixed   : 0xffffffbffe7fd000 - 0xffffffbffec00000   (  4108 KB)
[    0.000000]     PCI I/O : 0xffffffbffee00000 - 0xffffffbfffe00000   (    16 MB)
[    0.000000]     memory  : 0xffffffc000000000 - 0xffffffc200000000   (  8192 MB)

Changes since v2:
- Add tested/ack by James Morse.
- Remove restrictive printing, keep the same as mm/dump.c.

Changes since v1:
- Drop vector info and spilt the patch, suggested by James Morse.

Kefeng Wang (2):
  arm64: mm: make pr_cont() per line in Virtual kernel memory layout
  arm64: mm: Show bss segment in kernel memory layout

 arch/arm64/mm/init.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

-- 
2.6.0.GIT



From christoffer.dall at linaro.org  Thu May 12 05:12:26 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 14:12:26 +0200
Subject: [PATCH v3 35/55] KVM: arm/arm64: vgic-new: Add GICv3 IDREGS
 register handler
In-Reply-To: <1462531568-9799-36-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-36-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512121226.GF27623@cbox>

On Fri, May 06, 2016 at 11:45:48AM +0100, Andre Przywara wrote:
> We implement the only one ID register that is required by the
> architecture, also this is the one that Linux actually checks.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 20 ++++++++++++++++++--
>  1 file changed, 18 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index d137242..48fba9c 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -110,6 +110,22 @@ static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
>  	return extract_bytes(value, addr & 3, len);
>  }
>  
> +static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu,
> +					      gpa_t addr, unsigned int len)
> +{
> +	u32 regnr = (addr & 0x3f) - (GICD_IDREGS & 0x3f);

this regnr thing is confusing, because it's not an index, it's an
address offset.

why can't you do:

	switch (addr & 0xffff) {
	case GICD_PIDR2:
	}


> +	u32 reg = 0;
> +
> +	switch (regnr + GICD_IDREGS) {
> +	case GICD_PIDR2:
> +		/* report a GICv3 compliant implementation */
> +		reg = 0x3b;
> +		break;
> +	}
> +
> +	return extract_bytes(reg, addr & 3, len);
> +}
> +
>  /*
>   * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
>   * redistributors, while SPIs are covered by registers in the distributor
> @@ -160,7 +176,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
>  	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 64),
>  	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
> +		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48),
>  };
>  
>  static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
> @@ -175,7 +191,7 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
>  	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 8),
>  	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 48),
> +		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48),
>  };
>  
>  static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
> -- 
> 2.7.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From christoffer.dall at linaro.org  Thu May 12 05:12:58 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 14:12:58 +0200
Subject: [PATCH v3 13/55] KVM: arm/arm64: vgic-new: Add data structure
 definitions
In-Reply-To: <1462531568-9799-14-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-14-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512121258.GG27623@cbox>

On Fri, May 06, 2016 at 11:45:26AM +0100, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> Add a new header file for the new and improved GIC implementation.
> The big change is that we now have a struct vgic_irq per IRQ instead
> of spreading all the information over various bitmaps.
> 
> We include this new header conditionally from within the old header
> file for the time being to avoid touching all the users.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changes RFC .. v1:
> - adapt to 4.6-rc (adding live_lrs member)
> - elaborate on ap_list usage
> 
> Changes v1 .. v2:
> - change data type of dist->enabled to bool
> 
>  include/kvm/arm_vgic.h  |   5 ++
>  include/kvm/vgic/vgic.h | 201 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 206 insertions(+)
>  create mode 100644 include/kvm/vgic/vgic.h
> 
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index c14ff77..d406f8e 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -19,6 +19,10 @@
>  #ifndef __ASM_ARM_KVM_VGIC_H
>  #define __ASM_ARM_KVM_VGIC_H
>  
> +#ifdef CONFIG_KVM_NEW_VGIC
> +#include <kvm/vgic/vgic.h>
> +#else
> +
>  #include <linux/kernel.h>
>  #include <linux/kvm.h>
>  #include <linux/irqreturn.h>
> @@ -366,4 +370,5 @@ static inline int vgic_v3_probe(struct device_node *vgic_node,
>  }
>  #endif
>  
> +#endif	/* old VGIC include */
>  #endif
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> new file mode 100644
> index 0000000..39933ee
> --- /dev/null
> +++ b/include/kvm/vgic/vgic.h
> @@ -0,0 +1,201 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef __ASM_ARM_KVM_VGIC_VGIC_H
> +#define __ASM_ARM_KVM_VGIC_VGIC_H
> +
> +#include <linux/kernel.h>
> +#include <linux/kvm.h>
> +#include <linux/irqreturn.h>
> +#include <linux/spinlock.h>
> +#include <linux/types.h>
> +#include <kvm/iodev.h>
> +
> +#define VGIC_V3_MAX_CPUS	255
> +#define VGIC_V2_MAX_CPUS	8
> +#define VGIC_NR_IRQS_LEGACY     256
> +#define VGIC_NR_SGIS		16
> +#define VGIC_NR_PPIS		16
> +#define VGIC_NR_PRIVATE_IRQS	(VGIC_NR_SGIS + VGIC_NR_PPIS)
> +#define VGIC_MAX_PRIVATE	(VGIC_NR_PRIVATE_IRQS - 1)
> +#define VGIC_MAX_SPI		1019
> +#define VGIC_MAX_RESERVED	1023
> +#define VGIC_MIN_LPI		8192
> +
> +enum vgic_type {
> +	VGIC_V2,		/* Good ol' GICv2 */
> +	VGIC_V3,		/* New fancy GICv3 */
> +};
> +
> +/* same for all guests, as depending only on the _host's_ GIC model */
> +struct vgic_global {
> +	/* type of the host GIC */
> +	enum vgic_type		type;
> +
> +	/* Physical address of vgic virtual cpu interface */
> +	phys_addr_t		vcpu_base;
> +
> +	/* virtual control interface mapping */
> +	void __iomem		*vctrl_base;
> +
> +	/* Number of implemented list registers */
> +	int			nr_lr;
> +
> +	/* Maintenance IRQ number */

nit: this is the physial INTID, right?

> +	unsigned int		maint_irq;
> +
> +	/* maximum number of VCPUs allowed (GICv2 limits us to 8) */
> +	int			max_gic_vcpus;
> +
> +	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
> +	bool			can_emulate_gicv2;
> +};
> +
> +extern struct vgic_global kvm_vgic_global_state;
> +
> +#define VGIC_V2_MAX_LRS		(1 << 6)
> +#define VGIC_V3_MAX_LRS		16
> +#define VGIC_V3_LR_INDEX(lr)	(VGIC_V3_MAX_LRS - 1 - lr)
> +
> +enum vgic_irq_config {
> +	VGIC_CONFIG_EDGE = 0,
> +	VGIC_CONFIG_LEVEL
> +};
> +
> +struct vgic_irq {
> +	spinlock_t irq_lock;		/* Protects the content of the struct */
> +	struct list_head ap_list;
> +
> +	struct kvm_vcpu *vcpu;		/* SGIs and PPIs: The VCPU
> +					 * SPIs and LPIs: The VCPU whose ap_list
> +					 * on which this is queued.

nit: s/on which this is queued/this is queued on/

> +					 */
> +
> +	struct kvm_vcpu *target_vcpu;	/* The VCPU that this interrupt should
> +					 * be send to, as a result of the

nit: s/send/sent/

> +					 * targets reg (v2) or the
> +					 * affinity reg (v3).
> +					 */
> +
> +	u32 intid;			/* Guest visible INTID */
> +	bool pending;
> +	bool line_level;		/* Level only */
> +	bool soft_pending;		/* Level only */
> +	bool active;			/* not used for LPIs */
> +	bool enabled;
> +	bool hw;			/* Tied to HW IRQ */
> +	u32 hwintid;			/* HW INTID number */
> +	union {
> +		u8 targets;			/* GICv2 target VCPUs mask */
> +		u32 mpidr;			/* GICv3 target VCPU */
> +	};
> +	u8 source;			/* GICv2 SGIs only */
> +	u8 priority;
> +	enum vgic_irq_config config;	/* Level or edge */
> +};
> +
> +struct vgic_dist {
> +	bool			in_kernel;
> +	bool			ready;
> +
> +	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
> +	u32			vgic_model;
> +
> +	int			nr_spis;
> +
> +	/* TODO: Consider moving to global state */
> +	/* Virtual control interface mapping */
> +	void __iomem		*vctrl_base;
> +
> +	/* base addresses in guest physical address space: */
> +	gpa_t			vgic_dist_base;		/* distributor */
> +	union {
> +		/* either a GICv2 CPU interface */
> +		gpa_t			vgic_cpu_base;
> +		/* or a number of GICv3 redistributor regions */
> +		gpa_t			vgic_redist_base;
> +	};
> +
> +	/* distributor enabled */
> +	bool			enabled;
> +
> +	struct vgic_irq		*spis;
> +};
> +
> +struct vgic_v2_cpu_if {
> +	u32		vgic_hcr;
> +	u32		vgic_vmcr;
> +	u32		vgic_misr;	/* Saved only */
> +	u64		vgic_eisr;	/* Saved only */
> +	u64		vgic_elrsr;	/* Saved only */
> +	u32		vgic_apr;
> +	u32		vgic_lr[VGIC_V2_MAX_LRS];
> +};
> +
> +struct vgic_v3_cpu_if {
> +#ifdef CONFIG_KVM_ARM_VGIC_V3
> +	u32		vgic_hcr;
> +	u32		vgic_vmcr;
> +	u32		vgic_sre;	/* Restored only, change ignored */
> +	u32		vgic_misr;	/* Saved only */
> +	u32		vgic_eisr;	/* Saved only */
> +	u32		vgic_elrsr;	/* Saved only */
> +	u32		vgic_ap0r[4];
> +	u32		vgic_ap1r[4];
> +	u64		vgic_lr[VGIC_V3_MAX_LRS];
> +#endif
> +};
> +
> +struct vgic_cpu {
> +	/* CPU vif control registers for world switch */
> +	union {
> +		struct vgic_v2_cpu_if	vgic_v2;
> +		struct vgic_v3_cpu_if	vgic_v3;
> +	};
> +
> +	unsigned int used_lrs;
> +	struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
> +
> +	spinlock_t ap_list_lock;	/* Protects the ap_list */
> +
> +	/*
> +	 * List of IRQs that this VCPU should consider because they are either
> +	 * Active or Pending (hence the name; AP list), or because they recently
> +	 * were one of the two and need to be migrated off this list to another
> +	 * VCPU.
> +	 */
> +	struct list_head ap_list_head;
> +
> +	u64 live_lrs;
> +};
> +
> +#define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
> +#define vgic_initialized(k)	(false)
> +#define vgic_ready(k)		((k)->arch.vgic.ready)
> +#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
> +			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))

this should really be a static inline at this point.

> +
> +/**
> + * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
> + *
> + * The host's GIC naturally limits the maximum amount of VCPUs a guest
> + * can use.
> + */
> +static inline int kvm_vgic_get_max_vcpus(void)
> +{
> +	return kvm_vgic_global_state.max_gic_vcpus;
> +}
> +
> +#endif /* __ASM_ARM_KVM_VGIC_VGIC_H */
> -- 
> 2.7.3
> 


From marc.zyngier at arm.com  Thu May 12 05:17:38 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 12 May 2016 13:17:38 +0100
Subject: [PATCH v3 13/55] KVM: arm/arm64: vgic-new: Add data structure
 definitions
In-Reply-To: <20160512121258.GG27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-14-git-send-email-andre.przywara@arm.com>
 <20160512121258.GG27623@cbox>
Message-ID: <57347462.1020504@arm.com>

On 12/05/16 13:12, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:26AM +0100, Andre Przywara wrote:
>> From: Christoffer Dall <christoffer.dall at linaro.org>
>>
>> Add a new header file for the new and improved GIC implementation.
>> The big change is that we now have a struct vgic_irq per IRQ instead
>> of spreading all the information over various bitmaps.
>>
>> We include this new header conditionally from within the old header
>> file for the time being to avoid touching all the users.
>>
>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changes RFC .. v1:
>> - adapt to 4.6-rc (adding live_lrs member)
>> - elaborate on ap_list usage
>>
>> Changes v1 .. v2:
>> - change data type of dist->enabled to bool
>>
>>  include/kvm/arm_vgic.h  |   5 ++
>>  include/kvm/vgic/vgic.h | 201 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 206 insertions(+)
>>  create mode 100644 include/kvm/vgic/vgic.h
>>
>> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
>> index c14ff77..d406f8e 100644
>> --- a/include/kvm/arm_vgic.h
>> +++ b/include/kvm/arm_vgic.h
>> @@ -19,6 +19,10 @@
>>  #ifndef __ASM_ARM_KVM_VGIC_H
>>  #define __ASM_ARM_KVM_VGIC_H
>>  
>> +#ifdef CONFIG_KVM_NEW_VGIC
>> +#include <kvm/vgic/vgic.h>
>> +#else
>> +
>>  #include <linux/kernel.h>
>>  #include <linux/kvm.h>
>>  #include <linux/irqreturn.h>
>> @@ -366,4 +370,5 @@ static inline int vgic_v3_probe(struct device_node *vgic_node,
>>  }
>>  #endif
>>  
>> +#endif	/* old VGIC include */
>>  #endif
>> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
>> new file mode 100644
>> index 0000000..39933ee
>> --- /dev/null
>> +++ b/include/kvm/vgic/vgic.h
>> @@ -0,0 +1,201 @@
>> +/*
>> + * Copyright (C) 2015, 2016 ARM 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.
>> + *
>> + * 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.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +#ifndef __ASM_ARM_KVM_VGIC_VGIC_H
>> +#define __ASM_ARM_KVM_VGIC_VGIC_H
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/kvm.h>
>> +#include <linux/irqreturn.h>
>> +#include <linux/spinlock.h>
>> +#include <linux/types.h>
>> +#include <kvm/iodev.h>
>> +
>> +#define VGIC_V3_MAX_CPUS	255
>> +#define VGIC_V2_MAX_CPUS	8
>> +#define VGIC_NR_IRQS_LEGACY     256
>> +#define VGIC_NR_SGIS		16
>> +#define VGIC_NR_PPIS		16
>> +#define VGIC_NR_PRIVATE_IRQS	(VGIC_NR_SGIS + VGIC_NR_PPIS)
>> +#define VGIC_MAX_PRIVATE	(VGIC_NR_PRIVATE_IRQS - 1)
>> +#define VGIC_MAX_SPI		1019
>> +#define VGIC_MAX_RESERVED	1023
>> +#define VGIC_MIN_LPI		8192
>> +
>> +enum vgic_type {
>> +	VGIC_V2,		/* Good ol' GICv2 */
>> +	VGIC_V3,		/* New fancy GICv3 */
>> +};
>> +
>> +/* same for all guests, as depending only on the _host's_ GIC model */
>> +struct vgic_global {
>> +	/* type of the host GIC */
>> +	enum vgic_type		type;
>> +
>> +	/* Physical address of vgic virtual cpu interface */
>> +	phys_addr_t		vcpu_base;
>> +
>> +	/* virtual control interface mapping */
>> +	void __iomem		*vctrl_base;
>> +
>> +	/* Number of implemented list registers */
>> +	int			nr_lr;
>> +
>> +	/* Maintenance IRQ number */
> 
> nit: this is the physial INTID, right?
> 
>> +	unsigned int		maint_irq;

No, this is the actual Linux IRQ number.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From christoffer.dall at linaro.org  Thu May 12 05:21:19 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 14:21:19 +0200
Subject: [PATCH v3 36/55] KVM: arm/arm64: vgic-new: Add GICv3 IROUTER
 register handlers
In-Reply-To: <1462531568-9799-37-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-37-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512122119.GH27623@cbox>

On Fri, May 06, 2016 at 11:45:49AM +0100, Andre Przywara wrote:
> Since GICv3 supports much more than the 8 CPUs the GICv2 ITARGETSR
> register can handle, the new IROUTER register covers the whole range
> of possible target (V)CPUs by using the same MPIDR that the cores
> report themselves.
> In addition to translating this MPIDR into a vcpu pointer we store
> the originally written value as well. The architecture allows to
> write any values into the register, which must be read back as written.
> 
> Since we don't support affinity level 3, we don't need to take care
> about the upper word of this 64-bit register, which simplifies the
> handling a bit.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - fold in and simplify vgic_v3_irq_change_affinity
> 
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 65 +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 64 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index 48fba9c..3bcc2c4 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -86,6 +86,69 @@ static u32 compress_mpidr(unsigned long mpidr)
>  	return ret;
>  }
>  
> +static unsigned long decompress_mpidr(u32 value)
> +{
> +	unsigned long mpidr;
> +
> +	mpidr  = ((value >>  0) & 0xFF) << MPIDR_LEVEL_SHIFT(0);
> +	mpidr |= ((value >>  8) & 0xFF) << MPIDR_LEVEL_SHIFT(1);
> +	mpidr |= ((value >> 16) & 0xFF) << MPIDR_LEVEL_SHIFT(2);
> +	mpidr |= (u64)((value >> 24) & 0xFF) << MPIDR_LEVEL_SHIFT(3);
> +
> +	return mpidr;
> +}
> +
> +static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
> +					    gpa_t addr, unsigned int len)
> +{
> +	int intid = (addr & 0x1fff) / 8;
> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
> +	unsigned long mpidr;
> +
> +	if (!irq)
> +		return 0;
> +
> +	mpidr = decompress_mpidr(irq->mpidr);

I'm unsure here; do we ned a READ_ONCE() in lieu taking the lock or are
we guaranteed that this is a single memory access even with compiler
inlining etc.?

> +	return extract_bytes(mpidr, addr & 7, len);
> +}
> +
> +static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len,
> +				    unsigned long val)
> +{
> +	int intid = (addr & 0x1fff) / 8;
> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
> +	unsigned long mask = 0xffffffff;	/* upper word is WI */
> +	u64 mpidr;
> +
> +	if (!irq)
> +		return;
> +
> +	/*
> +	 * There are only two supported options:
> +	 * (1) aligned 64-bit access
> +	 * (2) aligned 32-bit access
> +	 *
> +	 * TODO: make this check generic and move it to dispatch_...()
> +	 */
> +	if (len != 4 && len != 8)
> +		return;
> +
> +
> +	/* The upper word is WI for us since we don't implement Aff3. */
> +	if (addr & 4)
> +		return;
> +
> +	spin_lock(&irq->irq_lock);
> +
> +	mpidr = decompress_mpidr(irq->mpidr);
> +	mpidr = (mpidr & ~mask) | (val & mask);
> +	irq->mpidr = compress_mpidr(mpidr);
> +	irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, mpidr);

this is weird because it doesn't preserve read-as-written semantics but
allows a guest to write something into the RES0 field and read that back
in the Aff3 field...

> +
> +	spin_unlock(&irq->irq_lock);
> +}
> +
>  static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
>  					      gpa_t addr, unsigned int len)
>  {
> @@ -174,7 +237,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
>  	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 64),
> +		vgic_mmio_read_irouter, vgic_mmio_write_irouter, 64),
>  	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
>  		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48),
>  };
> -- 
> 2.7.3
> 


From zhaoshenglong at huawei.com  Thu May 12 05:19:54 2016
From: zhaoshenglong at huawei.com (Shannon Zhao)
Date: Thu, 12 May 2016 20:19:54 +0800
Subject: [PATCH v2] Xen: EFI: Parse DT parameters for Xen specific UEFI
Message-ID: <1463055594-14980-1-git-send-email-zhaoshenglong@huawei.com>

From: Shannon Zhao <shannon.zhao at linaro.org>

The EFI DT parameters for bare metal are located under /chosen node,
while for Xen Dom0 they are located under /hyperviosr/uefi node. These
parameters under /chosen and /hyperviosr/uefi are not expected to appear
at the same time.
Parse these EFI parameters and initialize EFI like the way for bare
metal except the runtime services because the runtime services for Xen
Dom0 are available through hypercalls and they are always enabled. So it
sets the EFI_RUNTIME_SERVICES flag if it finds /hyperviosr/uefi node and
bails out in arm_enable_runtime_services() when EFI_RUNTIME_SERVICES
flag is set already.

CC: Matt Fleming <matt at codeblueprint.co.uk>
Signed-off-by: Shannon Zhao <shannon.zhao at linaro.org>
---
v2: rebase it on top of EFI and Xen next branch, add some comments to
explain the codes. 
---
 arch/arm/xen/enlighten.c           | 22 +++++++++++
 drivers/firmware/efi/arm-runtime.c |  5 +++
 drivers/firmware/efi/efi.c         | 81 ++++++++++++++++++++++++++++++--------
 3 files changed, 92 insertions(+), 16 deletions(-)

diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 13e3e9f..d4f36eb 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -15,7 +15,9 @@
 #include <asm/paravirt.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
+#include <asm/xen/xen-ops.h>
 #include <asm/system_misc.h>
+#include <asm/efi.h>
 #include <linux/interrupt.h>
 #include <linux/irqreturn.h>
 #include <linux/module.h>
@@ -261,6 +263,19 @@ static int __init fdt_find_hyper_node(unsigned long node, const char *uname,
 	    !strncmp(hyper_node.prefix, s, strlen(hyper_node.prefix)))
 		hyper_node.version = s + strlen(hyper_node.prefix);
 
+	/*
+	 * Check if Xen supports EFI by checking whether there is the
+	 * "/hypervisor/uefi" node in DT. If so, runtime services are available
+	 * through proxy functions (e.g. in case of Xen dom0 EFI implementation
+	 * they call special hypercall which executes relevant EFI functions)
+	 * and that is why they are always enabled.
+	 */
+	if (IS_ENABLED(CONFIG_XEN_EFI)) {
+		if ((of_get_flat_dt_subnode_by_name(node, "uefi") > 0) &&
+		    !efi_runtime_disabled())
+			set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+	}
+
 	return 0;
 }
 
@@ -352,6 +367,13 @@ static int __init xen_guest_init(void)
 		return -ENODEV;
 	}
 
+	/*
+	 * The fdt parsing codes have set EFI_RUNTIME_SERVICES if Xen EFI
+	 * parameters are found. Force enable runtime services.
+	 */
+	if (efi_enabled(EFI_RUNTIME_SERVICES))
+		xen_efi_runtime_setup();
+
 	shared_info_page = (struct shared_info *)get_zeroed_page(GFP_KERNEL);
 
 	if (!shared_info_page) {
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index 17ccf0a..c394b81 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -107,6 +107,11 @@ static int __init arm_enable_runtime_services(void)
 		return 0;
 	}
 
+	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
+		pr_info("EFI runtime services access via paravirt.\n");
+		return 0;
+	}
+
 	pr_info("Remapping and enabling EFI services.\n");
 
 	mapsize = efi.memmap.map_end - efi.memmap.map;
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 05509f3..1c6f9dd 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -472,12 +472,14 @@ device_initcall(efi_load_efivars);
 		FIELD_SIZEOF(struct efi_fdt_params, field) \
 	}
 
-static __initdata struct {
+struct params {
 	const char name[32];
 	const char propname[32];
 	int offset;
 	int size;
-} dt_params[] = {
+};
+
+static __initdata struct params fdt_params[] = {
 	UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
 	UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
 	UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
@@ -485,44 +487,91 @@ static __initdata struct {
 	UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
 };
 
+static __initdata struct params xen_fdt_params[] = {
+	UEFI_PARAM("System Table", "xen,uefi-system-table", system_table),
+	UEFI_PARAM("MemMap Address", "xen,uefi-mmap-start", mmap),
+	UEFI_PARAM("MemMap Size", "xen,uefi-mmap-size", mmap_size),
+	UEFI_PARAM("MemMap Desc. Size", "xen,uefi-mmap-desc-size", desc_size),
+	UEFI_PARAM("MemMap Desc. Version", "xen,uefi-mmap-desc-ver", desc_ver)
+};
+
+#define EFI_FDT_PARAMS_SIZE	ARRAY_SIZE(fdt_params)
+
+static __initdata struct {
+	const char *uname;
+	const char *subnode;
+	struct params *params;
+} dt_params[] = {
+	{ "hypervisor", "uefi", xen_fdt_params },
+	{ "chosen", NULL, fdt_params },
+};
+
 struct param_info {
 	int found;
 	void *params;
+	const char *missing;
 };
 
-static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
-				       int depth, void *data)
+static int __init __find_uefi_params(unsigned long node,
+				     struct param_info *info,
+				     struct params *params)
 {
-	struct param_info *info = data;
 	const void *prop;
 	void *dest;
 	u64 val;
 	int i, len;
 
-	if (depth != 1 || strcmp(uname, "chosen") != 0)
-		return 0;
-
-	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
-		prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
-		if (!prop)
+	for (i = 0; i < EFI_FDT_PARAMS_SIZE; i++) {
+		prop = of_get_flat_dt_prop(node, params[i].propname, &len);
+		if (!prop) {
+			info->missing = params[i].name;
 			return 0;
-		dest = info->params + dt_params[i].offset;
+		}
+
+		dest = info->params + params[i].offset;
 		info->found++;
 
 		val = of_read_number(prop, len / sizeof(u32));
 
-		if (dt_params[i].size == sizeof(u32))
+		if (params[i].size == sizeof(u32))
 			*(u32 *)dest = val;
 		else
 			*(u64 *)dest = val;
 
 		if (efi_enabled(EFI_DBG))
-			pr_info("  %s: 0x%0*llx\n", dt_params[i].name,
-				dt_params[i].size * 2, val);
+			pr_info("  %s: 0x%0*llx\n", params[i].name,
+				params[i].size * 2, val);
 	}
+
 	return 1;
 }
 
+static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
+				       int depth, void *data)
+{
+	struct param_info *info = data;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
+		const char *subnode = dt_params[i].subnode;
+
+		if (depth != 1 || strcmp(uname, dt_params[i].uname) != 0) {
+			info->missing = dt_params[i].params[0].name;
+			continue;
+		}
+
+		if (subnode) {
+			node = of_get_flat_dt_subnode_by_name(node, subnode);
+			if (node < 0)
+				return 0;
+		}
+
+		return __find_uefi_params(node, info, dt_params[i].params);
+	}
+
+	return 0;
+}
+
 int __init efi_get_fdt_params(struct efi_fdt_params *params)
 {
 	struct param_info info;
@@ -538,7 +587,7 @@ int __init efi_get_fdt_params(struct efi_fdt_params *params)
 		pr_info("UEFI not found.\n");
 	else if (!ret)
 		pr_err("Can't find '%s' in device tree!\n",
-		       dt_params[info.found].name);
+		       info.missing);
 
 	return ret;
 }
-- 
2.0.4




From christoffer.dall at linaro.org  Thu May 12 05:23:17 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 14:23:17 +0200
Subject: [PATCH v3 13/55] KVM: arm/arm64: vgic-new: Add data structure
 definitions
In-Reply-To: <57347462.1020504@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-14-git-send-email-andre.przywara@arm.com>
 <20160512121258.GG27623@cbox> <57347462.1020504@arm.com>
Message-ID: <20160512122317.GC2370@cbox>

On Thu, May 12, 2016 at 01:17:38PM +0100, Marc Zyngier wrote:
> On 12/05/16 13:12, Christoffer Dall wrote:
> > On Fri, May 06, 2016 at 11:45:26AM +0100, Andre Przywara wrote:
> >> From: Christoffer Dall <christoffer.dall at linaro.org>
> >>
> >> Add a new header file for the new and improved GIC implementation.
> >> The big change is that we now have a struct vgic_irq per IRQ instead
> >> of spreading all the information over various bitmaps.
> >>
> >> We include this new header conditionally from within the old header
> >> file for the time being to avoid touching all the users.
> >>
> >> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >> Changes RFC .. v1:
> >> - adapt to 4.6-rc (adding live_lrs member)
> >> - elaborate on ap_list usage
> >>
> >> Changes v1 .. v2:
> >> - change data type of dist->enabled to bool
> >>
> >>  include/kvm/arm_vgic.h  |   5 ++
> >>  include/kvm/vgic/vgic.h | 201 ++++++++++++++++++++++++++++++++++++++++++++++++
> >>  2 files changed, 206 insertions(+)
> >>  create mode 100644 include/kvm/vgic/vgic.h
> >>
> >> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> >> index c14ff77..d406f8e 100644
> >> --- a/include/kvm/arm_vgic.h
> >> +++ b/include/kvm/arm_vgic.h
> >> @@ -19,6 +19,10 @@
> >>  #ifndef __ASM_ARM_KVM_VGIC_H
> >>  #define __ASM_ARM_KVM_VGIC_H
> >>  
> >> +#ifdef CONFIG_KVM_NEW_VGIC
> >> +#include <kvm/vgic/vgic.h>
> >> +#else
> >> +
> >>  #include <linux/kernel.h>
> >>  #include <linux/kvm.h>
> >>  #include <linux/irqreturn.h>
> >> @@ -366,4 +370,5 @@ static inline int vgic_v3_probe(struct device_node *vgic_node,
> >>  }
> >>  #endif
> >>  
> >> +#endif	/* old VGIC include */
> >>  #endif
> >> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> >> new file mode 100644
> >> index 0000000..39933ee
> >> --- /dev/null
> >> +++ b/include/kvm/vgic/vgic.h
> >> @@ -0,0 +1,201 @@
> >> +/*
> >> + * Copyright (C) 2015, 2016 ARM 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.
> >> + *
> >> + * 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.
> >> + *
> >> + * You should have received a copy of the GNU General Public License
> >> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> >> + */
> >> +#ifndef __ASM_ARM_KVM_VGIC_VGIC_H
> >> +#define __ASM_ARM_KVM_VGIC_VGIC_H
> >> +
> >> +#include <linux/kernel.h>
> >> +#include <linux/kvm.h>
> >> +#include <linux/irqreturn.h>
> >> +#include <linux/spinlock.h>
> >> +#include <linux/types.h>
> >> +#include <kvm/iodev.h>
> >> +
> >> +#define VGIC_V3_MAX_CPUS	255
> >> +#define VGIC_V2_MAX_CPUS	8
> >> +#define VGIC_NR_IRQS_LEGACY     256
> >> +#define VGIC_NR_SGIS		16
> >> +#define VGIC_NR_PPIS		16
> >> +#define VGIC_NR_PRIVATE_IRQS	(VGIC_NR_SGIS + VGIC_NR_PPIS)
> >> +#define VGIC_MAX_PRIVATE	(VGIC_NR_PRIVATE_IRQS - 1)
> >> +#define VGIC_MAX_SPI		1019
> >> +#define VGIC_MAX_RESERVED	1023
> >> +#define VGIC_MIN_LPI		8192
> >> +
> >> +enum vgic_type {
> >> +	VGIC_V2,		/* Good ol' GICv2 */
> >> +	VGIC_V3,		/* New fancy GICv3 */
> >> +};
> >> +
> >> +/* same for all guests, as depending only on the _host's_ GIC model */
> >> +struct vgic_global {
> >> +	/* type of the host GIC */
> >> +	enum vgic_type		type;
> >> +
> >> +	/* Physical address of vgic virtual cpu interface */
> >> +	phys_addr_t		vcpu_base;
> >> +
> >> +	/* virtual control interface mapping */
> >> +	void __iomem		*vctrl_base;
> >> +
> >> +	/* Number of implemented list registers */
> >> +	int			nr_lr;
> >> +
> >> +	/* Maintenance IRQ number */
> > 
> > nit: this is the physial INTID, right?
> > 
> >> +	unsigned int		maint_irq;
> 
> No, this is the actual Linux IRQ number.
> 
oh right, it's set by irq_of_parse_and_map.

My bad,
-Christoffer


From sergei.shtylyov at cogentembedded.com  Thu May 12 05:25:02 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 12 May 2016 15:25:02 +0300
Subject: [RFC] Reset pins of phys and their representation in a device tree
In-Reply-To: <20160512071542.GC30822@pengutronix.de>
References: <20160512071542.GC30822@pengutronix.de>
Message-ID: <e75ab3a0-da5e-fef1-d5e1-65c37e7714eb@cogentembedded.com>

Hello.

On 5/12/2016 10:15 AM, Uwe Kleine-K?nig wrote:

> I have a machine here where the reset pin of the phy is connected to a
> GPIO.
>
> There are different possibilities available today to handle this
> situation, here are the ones I'm aware of:
>
>  - Use a gpio-hog to set the reset gpio to non-active
>    This might result in dependency problems (and that's what I am
>    currently faced with) because there is no connection in the device
>    tree between the hog and the phy.
>
>  - [Documentation/devicetree/bindings/net/fsl-fec.txt]
>    The fec node supports properties
>
> 	phy-reset-gpios = <&gpio2 14 0>;
> 	phy-reset-duration = <200> /* milliseconds */;
>
>    Something similar exists in TI's vendor kernel
>    (http://git.ti.com/ti-linux-kernel/ti-linux-kernel/commit/17d192b999ee904ced223c16cef76111a51c461b)
>    with different (and IMHO bader) naming.
>    This is the wrong place to specify the gpios; they shouldn't be in the
>    mac's node, but in a phy node instead.
>
> So what I actually want is to put the gpio specification in the right
> place and let it look as follows:
>
> 	mymdiobus {
> 		[...]
> 		myfirstphy: ethernet-phy at 0 {
> 			compatible = "ethernet-phy-ieee802.3-c22";
> 			reg = <0>;
>
> 			reset-gpios = <&gpio2 14 0>;
> 			reset-duration-ms = <200>;
> 		};
>
> 		mysecondphy: ethernet-phy at 2 {
> 			compatible = "ethernet-phy-ieee802.3-c22";
> 			reg = <2>;
>
> 			reset-gpios = <&gpio3 10 0>;
> 			reset-duration-ms = <200>;
> 		};
> 	};
>
> And with this we could defer probe of &myfirstphy if &gpio2 isn't
> available yet.
>
> Does this sound sensible? Does something like that already exist which I
> missed? Any further ideas/comments?

http://patchwork.ozlabs.org/patch/616495/

    I'll post a new version RSN.

> Best regards
> Uwe

MBR, Sergei



From appana.durga.rao at xilinx.com  Thu May 12 05:29:23 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Thu, 12 May 2016 17:59:23 +0530
Subject: [PATCH v8 1/2] Documentation: DT: dma: Add Xilinx zynqmp dma device
 tree binding documentation
Message-ID: <1463056164-3210-1-git-send-email-appanad@xilinx.com>

Device-tree binding documentation for Xilinx zynqmp dma engine used in
Zynq UltraScale+ MPSoC.

Signed-off-by: Punnaiah Choudary Kalluri <punnaia at xilinx.com>
Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
Changes in v8:
- Removed all the software runtime configuration parameters
  from the binding doc as suggested by the Lars.
Changes in v7:
- None.
Changes in v6:
- Removed desc-axi-cache/dst-axi-cache/src-axi-cache properties
  from the binding doc as it allow broken combinations when dma-coherent
  is set as suggested by Rob.
- Fixed minor comments given by Rob related coding(lower case DT node name).
Changes in v5:
- Use dma-coherent flag for coherent transfers as suggested by rob.
- Removed unnecessary properties from binding doc as suggested by Rob.
Changes in v4:
- None
Changes in v3:
- None
Changes in v2:
- None.

 .../devicetree/bindings/dma/xilinx/zynqmp_dma.txt  | 30 ++++++++++++++++++++++
 1 file changed, 30 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/xilinx/zynqmp_dma.txt

diff --git a/Documentation/devicetree/bindings/dma/xilinx/zynqmp_dma.txt b/Documentation/devicetree/bindings/dma/xilinx/zynqmp_dma.txt
new file mode 100644
index 0000000..eea9924
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/xilinx/zynqmp_dma.txt
@@ -0,0 +1,30 @@
+Xilinx ZynqMP DMA engine, it does support memory to memory transfers,
+memory to device and device to memory transfers. It also has flow
+control and rate control support for slave/peripheral dma access.
+
+Required properties:
+- compatible		: Should be "xlnx,zynqmp-dma-1.0"
+- reg			: Memory map for gdma/adma module access.
+- interrupt-parent	: Interrupt controller the interrupt is routed through
+- interrupts		: Should contain DMA channel interrupt.
+- xlnx,bus-width	: Axi buswidth in bits. Should contain 128 or 64
+- clock-names		: List of input clocks "clk_main", "clk_apb"
+			  (see clock bindings for details)
+
+Optional properties:
+- xlnx,include-sg	: Indicates the controller to operate in simple or
+			  scatter gather dma mode
+- dma-coherent		: Present if dma operations are coherent.
+
+Example:
+++++++++
+fpd_dma_chan1: dma at fd500000 {
+	compatible = "xlnx,zynqmp-dma-1.0";
+	reg = <0x0 0xFD500000 0x1000>;
+	interrupt-parent = <&gic>;
+	interrupts = <0 117 4>;
+	clock-names = "clk_main", "clk_apb";
+	xlnx,bus-width = <128>;
+	xlnx,include-sg;
+	dma-coherent;
+};
-- 
2.1.1



From appana.durga.rao at xilinx.com  Thu May 12 05:29:24 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Thu, 12 May 2016 17:59:24 +0530
Subject: [PATCH v8 2/2] dmaengine: Add Xilinx zynqmp dma engine driver support
In-Reply-To: <1463056164-3210-1-git-send-email-appanad@xilinx.com>
References: <1463056164-3210-1-git-send-email-appanad@xilinx.com>
Message-ID: <1463056164-3210-2-git-send-email-appanad@xilinx.com>

Added the driver for zynqmp dma engine used in Zynq
UltraScale+ MPSoC. This dma controller supports memory to memory
and memory to I/O buffer transfers.

Signed-off-by: Punnaiah Choudary Kalluri <punnaia at xilinx.com>
Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
Changes for v8:
- Derive the software runtime configuration parameters
  through config strucutre and configure them during transfer
  as suggested by the Lars.
Changes for v7:
- Fixed kbuild compilation warnings.
- Fixed {src,dst}_addr_widths are supposed to be a bitmask of
  supported slave device widths as suggested by Rob.
Changes in v6:
- Removed unnecessary axcache properties from the driver
- Fixed compilation issues
Changes in v5:
- Removed in_interrupt check from the tasklet cleanup as
  suggested by the vinod/lars.
Changes in v4:
- Modified the defines to start with ZYNQMP_DMA perfix
- Changed the zynqmp_dma_alloc_chan_resources to return number of
  allocated descriptors
- Changed the zynqmp_dma_device variable name
- Released the locks before calling user callback
- freeup irq in zynqmp_dma_chan_remove function.
Changes in v3:
- Modified the zynqmp_dma_chan_is_idle function return type to bool
Changes in v2:
- Corrected the function header documentation
- Framework expects bus-width value in bytes. so, fixed it
- Removed magic numbers for bus-width

 drivers/dma/Kconfig             |    6 +
 drivers/dma/xilinx/Makefile     |    1 +
 drivers/dma/xilinx/zynqmp_dma.c | 1267 +++++++++++++++++++++++++++++++++++++++
 include/linux/dma/xilinx_dma.h  |   19 +-
 4 files changed, 1292 insertions(+), 1 deletion(-)
 create mode 100644 drivers/dma/xilinx/zynqmp_dma.c

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index f843dd5..6758417 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -527,6 +527,12 @@ config ZX_DMA
 	help
 	  Support the DMA engine for ZTE ZX296702 platform devices.
 
+config XILINX_ZYNQMP_DMA
+	tristate "Xilinx ZynqMP DMA Engine"
+	depends on (ARCH_ZYNQ || MICROBLAZE || ARM64)
+	select DMA_ENGINE
+	help
+	  Enable support for Xilinx ZynqMP DMA controller.
 
 # driver files
 source "drivers/dma/bestcomm/Kconfig"
diff --git a/drivers/dma/xilinx/Makefile b/drivers/dma/xilinx/Makefile
index 3c4e9f2..95469dc 100644
--- a/drivers/dma/xilinx/Makefile
+++ b/drivers/dma/xilinx/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_XILINX_VDMA) += xilinx_vdma.o
+obj-$(CONFIG_XILINX_ZYNQMP_DMA) += zynqmp_dma.o
diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
new file mode 100644
index 0000000..619abce
--- /dev/null
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -0,0 +1,1267 @@
+/*
+ * DMA driver for Xilinx ZynqMP DMA Engine
+ *
+ * Copyright (C) 2016 Xilinx, Inc. All rights reserved.
+ *
+ * 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.
+ */
+
+#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma/xilinx_dma.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_dma.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#include "../dmaengine.h"
+
+/* Register Offsets */
+#define ZYNQMP_DMA_ISR			0x100
+#define ZYNQMP_DMA_IMR			0x104
+#define ZYNQMP_DMA_IER			0x108
+#define ZYNQMP_DMA_IDS			0x10C
+#define ZYNQMP_DMA_CTRL0		0x110
+#define ZYNQMP_DMA_CTRL1		0x114
+#define ZYNQMP_DMA_DATA_ATTR		0x120
+#define ZYNQMP_DMA_DSCR_ATTR		0x124
+#define ZYNQMP_DMA_SRC_DSCR_WRD0	0x128
+#define ZYNQMP_DMA_SRC_DSCR_WRD1	0x12C
+#define ZYNQMP_DMA_SRC_DSCR_WRD2	0x130
+#define ZYNQMP_DMA_SRC_DSCR_WRD3	0x134
+#define ZYNQMP_DMA_DST_DSCR_WRD0	0x138
+#define ZYNQMP_DMA_DST_DSCR_WRD1	0x13C
+#define ZYNQMP_DMA_DST_DSCR_WRD2	0x140
+#define ZYNQMP_DMA_DST_DSCR_WRD3	0x144
+#define ZYNQMP_DMA_SRC_START_LSB	0x158
+#define ZYNQMP_DMA_SRC_START_MSB	0x15C
+#define ZYNQMP_DMA_DST_START_LSB	0x160
+#define ZYNQMP_DMA_DST_START_MSB	0x164
+#define ZYNQMP_DMA_RATE_CTRL		0x18C
+#define ZYNQMP_DMA_IRQ_SRC_ACCT		0x190
+#define ZYNQMP_DMA_IRQ_DST_ACCT		0x194
+#define ZYNQMP_DMA_CTRL2		0x200
+
+/* Interrupt registers bit field definitions */
+#define ZYNQMP_DMA_DONE			BIT(10)
+#define ZYNQMP_DMA_AXI_WR_DATA		BIT(9)
+#define ZYNQMP_DMA_AXI_RD_DATA		BIT(8)
+#define ZYNQMP_DMA_AXI_RD_DST_DSCR	BIT(7)
+#define ZYNQMP_DMA_AXI_RD_SRC_DSCR	BIT(6)
+#define ZYNQMP_DMA_IRQ_DST_ACCT_ERR	BIT(5)
+#define ZYNQMP_DMA_IRQ_SRC_ACCT_ERR	BIT(4)
+#define ZYNQMP_DMA_BYTE_CNT_OVRFL	BIT(3)
+#define ZYNQMP_DMA_DST_DSCR_DONE	BIT(2)
+#define ZYNQMP_DMA_INV_APB		BIT(0)
+
+/* Control 0 register bit field definitions */
+#define ZYNQMP_DMA_OVR_FETCH		BIT(7)
+#define ZYNQMP_DMA_POINT_TYPE_SG	BIT(6)
+#define ZYNQMP_DMA_RATE_CTRL_EN		BIT(3)
+
+/* Control 1 register bit field definitions */
+#define ZYNQMP_DMA_SRC_ISSUE		GENMASK(4, 0)
+
+/* Data Attribute register bit field definitions */
+#define ZYNQMP_DMA_ARBURST		GENMASK(27, 26)
+#define ZYNQMP_DMA_ARCACHE		GENMASK(25, 22)
+#define ZYNQMP_DMA_ARCACHE_OFST		22
+#define ZYNQMP_DMA_ARQOS		GENMASK(21, 18)
+#define ZYNQMP_DMA_ARQOS_OFST		18
+#define ZYNQMP_DMA_ARLEN		GENMASK(17, 14)
+#define ZYNQMP_DMA_ARLEN_OFST		14
+#define ZYNQMP_DMA_AWBURST		GENMASK(13, 12)
+#define ZYNQMP_DMA_AWCACHE		GENMASK(11, 8)
+#define ZYNQMP_DMA_AWCACHE_OFST		8
+#define ZYNQMP_DMA_AWQOS		GENMASK(7, 4)
+#define ZYNQMP_DMA_AWQOS_OFST		4
+#define ZYNQMP_DMA_AWLEN		GENMASK(3, 0)
+#define ZYNQMP_DMA_AWLEN_OFST		0
+
+/* Descriptor Attribute register bit field definitions */
+#define ZYNQMP_DMA_AXCOHRNT		BIT(8)
+#define ZYNQMP_DMA_AXCACHE		GENMASK(7, 4)
+#define ZYNQMP_DMA_AXCACHE_OFST		4
+#define ZYNQMP_DMA_AXQOS		GENMASK(3, 0)
+#define ZYNQMP_DMA_AXQOS_OFST		0
+
+/* Control register 2 bit field definitions */
+#define ZYNQMP_DMA_ENABLE		BIT(0)
+
+/* Buffer Descriptor definitions */
+#define ZYNQMP_DMA_DESC_CTRL_STOP	0x10
+#define ZYNQMP_DMA_DESC_CTRL_COMP_INT	0x4
+#define ZYNQMP_DMA_DESC_CTRL_SIZE_256	0x2
+#define ZYNQMP_DMA_DESC_CTRL_COHRNT	0x1
+
+/* Interrupt Mask specific definitions */
+#define ZYNQMP_DMA_INT_ERR	(ZYNQMP_DMA_AXI_RD_DATA | \
+				ZYNQMP_DMA_AXI_WR_DATA | \
+				ZYNQMP_DMA_AXI_RD_DST_DSCR | \
+				ZYNQMP_DMA_AXI_RD_SRC_DSCR | \
+				ZYNQMP_DMA_INV_APB)
+#define ZYNQMP_DMA_INT_OVRFL	(ZYNQMP_DMA_BYTE_CNT_OVRFL | \
+				ZYNQMP_DMA_IRQ_SRC_ACCT_ERR | \
+				ZYNQMP_DMA_IRQ_DST_ACCT_ERR)
+#define ZYNQMP_DMA_INT_DONE	(ZYNQMP_DMA_DONE | ZYNQMP_DMA_DST_DSCR_DONE)
+#define ZYNQMP_DMA_INT_EN_DEFAULT_MASK	(ZYNQMP_DMA_INT_DONE | \
+					ZYNQMP_DMA_INT_ERR | \
+					ZYNQMP_DMA_INT_OVRFL | \
+					ZYNQMP_DMA_DST_DSCR_DONE)
+
+/* Max number of descriptors per channel */
+#define ZYNQMP_DMA_NUM_DESCS	32
+
+/* Max transfer size per descriptor */
+#define ZYNQMP_DMA_MAX_TRANS_LEN	0x40000000
+
+/* Reset values for data attributes */
+#define ZYNQMP_DMA_AXCACHE_VAL		0xF
+#define ZYNQMP_DMA_ARLEN_RST_VAL	0xF
+#define ZYNQMP_DMA_AWLEN_RST_VAL	0xF
+
+#define ZYNQMP_DMA_SRC_ISSUE_RST_VAL	0x1F
+
+#define ZYNQMP_DMA_IDS_DEFAULT_MASK	0xFFF
+
+/* Bus width in bits */
+#define ZYNQMP_DMA_BUS_WIDTH_64		64
+#define ZYNQMP_DMA_BUS_WIDTH_128	128
+
+#define ZYNQMP_DMA_DESC_SIZE(chan)	(chan->desc_size)
+
+#define to_chan(chan)		container_of(chan, struct zynqmp_dma_chan, \
+					     common)
+#define tx_to_desc(tx)		container_of(tx, struct zynqmp_dma_desc_sw, \
+					     async_tx)
+
+/**
+ * struct zynqmp_dma_desc_ll - Hw linked list descriptor
+ * @addr: Buffer address
+ * @size: Size of the buffer
+ * @ctrl: Control word
+ * @nxtdscraddr: Next descriptor base address
+ * @rsvd: Reserved field and for Hw internal use.
+ */
+struct zynqmp_dma_desc_ll {
+	u64 addr;
+	u32 size;
+	u32 ctrl;
+	u64 nxtdscraddr;
+	u64 rsvd;
+}; __aligned(64)
+
+/**
+ * struct zynqmp_dma_desc_sw - Per Transaction structure
+ * @src: Source address for simple mode dma
+ * @dst: Destination address for simple mode dma
+ * @len: Transfer length for simple mode dma
+ * @node: Node in the channel descriptor list
+ * @tx_list: List head for the current transfer
+ * @async_tx: Async transaction descriptor
+ * @src_v: Virtual address of the src descriptor
+ * @src_p: Physical address of the src descriptor
+ * @dst_v: Virtual address of the dst descriptor
+ * @dst_p: Physical address of the dst descriptor
+ */
+struct zynqmp_dma_desc_sw {
+	u64 src;
+	u64 dst;
+	u32 len;
+	struct list_head node;
+	struct list_head tx_list;
+	struct dma_async_tx_descriptor async_tx;
+	struct zynqmp_dma_desc_ll *src_v;
+	dma_addr_t src_p;
+	struct zynqmp_dma_desc_ll *dst_v;
+	dma_addr_t dst_p;
+};
+
+/**
+ * struct zynqmp_dma_chan - Driver specific DMA channel structure
+ * @zdev: Driver specific device structure
+ * @regs: Control registers offset
+ * @lock: Descriptor operation lock
+ * @pending_list: Descriptors waiting
+ * @free_list: Descriptors free
+ * @active_list: Descriptors active
+ * @sw_desc_pool: SW descriptor pool
+ * @done_list: Complete descriptors
+ * @common: DMA common channel
+ * @desc_pool_v: Statically allocated descriptor base
+ * @desc_pool_p: Physical allocated descriptor base
+ * @desc_free_cnt: Descriptor available count
+ * @dev: The dma device
+ * @irq: Channel IRQ
+ * @has_sg: Support scatter gather transfers
+ * @is_dmacoherent: Tells whether dma operations are coherent or not
+ * @tasklet: Cleanup work after irq
+ * @idle : Channel status;
+ * @desc_size: Size of the low level descriptor
+ * @err: Channel has errors
+ * @bus_width: Bus width
+ * @clk_main: Pointer to main clock
+ * @clk_apb: Pointer to apb clock
+ * @config: Device configuration info
+ */
+struct zynqmp_dma_chan {
+	struct zynqmp_dma_device *zdev;
+	void __iomem *regs;
+	spinlock_t lock;
+	struct list_head pending_list;
+	struct list_head free_list;
+	struct list_head active_list;
+	struct zynqmp_dma_desc_sw *sw_desc_pool;
+	struct list_head done_list;
+	struct dma_chan common;
+	void *desc_pool_v;
+	dma_addr_t desc_pool_p;
+	u32 desc_free_cnt;
+	struct device *dev;
+	int irq;
+	bool has_sg;
+	bool is_dmacoherent;
+	struct tasklet_struct tasklet;
+	bool idle;
+	u32 desc_size;
+	bool err;
+	u32 bus_width;
+	struct clk *clk_main;
+	struct clk *clk_apb;
+	struct zynqmp_dma_config config;
+};
+
+/**
+ * struct zynqmp_dma_device - DMA device structure
+ * @dev: Device Structure
+ * @common: DMA device structure
+ * @chan: Driver specific DMA channel
+ */
+struct zynqmp_dma_device {
+	struct device *dev;
+	struct dma_device common;
+	struct zynqmp_dma_chan *chan;
+};
+
+/**
+ * zynqmp_dma_chan_is_idle - Provides the channel idle status
+ * @chan: ZynqMP DMA DMA channel pointer
+ *
+ * Return: 'true' if the channel is idle otherwise 'false'
+ */
+static inline bool zynqmp_dma_chan_is_idle(struct zynqmp_dma_chan *chan)
+{
+	return chan->idle;
+
+}
+
+/**
+ * zynqmp_dma_update_desc_to_ctrlr - Updates descriptor to the controller
+ * @chan: ZynqMP DMA DMA channel pointer
+ * @desc: Transaction descriptor pointer
+ */
+static void zynqmp_dma_update_desc_to_ctrlr(struct zynqmp_dma_chan *chan,
+				      struct zynqmp_dma_desc_sw *desc)
+{
+	dma_addr_t addr;
+
+	addr = desc->src_p;
+	writel(addr, chan->regs + ZYNQMP_DMA_SRC_START_LSB);
+	writel(upper_32_bits(addr), chan->regs + ZYNQMP_DMA_SRC_START_MSB);
+	addr = desc->dst_p;
+	writel(addr, chan->regs + ZYNQMP_DMA_DST_START_LSB);
+	writel(upper_32_bits(addr), chan->regs + ZYNQMP_DMA_DST_START_MSB);
+}
+
+/**
+ * zynqmp_dma_desc_config_eod - Mark the descriptor as end descriptor
+ * @chan: ZynqMP DMA channel pointer
+ * @desc: Hw descriptor pointer
+ */
+static void zynqmp_dma_desc_config_eod(struct zynqmp_dma_chan *chan, void *desc)
+{
+	struct zynqmp_dma_desc_ll *hw = (struct zynqmp_dma_desc_ll *)desc;
+
+	hw->ctrl |= ZYNQMP_DMA_DESC_CTRL_STOP;
+	hw++;
+	hw->ctrl |= ZYNQMP_DMA_DESC_CTRL_COMP_INT | ZYNQMP_DMA_DESC_CTRL_STOP;
+}
+
+/**
+ * zynqmp_dma_config_simple_desc - Configure the transfer parameters
+ * @chan: ZynqMP DMA channel pointer
+ * @src: Source buffer address
+ * @dst: Destination buffer address
+ * @len: Transfer length
+ */
+static void zynqmp_dma_config_simple_desc(struct zynqmp_dma_chan *chan,
+					  dma_addr_t src, dma_addr_t dst,
+					  size_t len)
+{
+	u32 val;
+
+	writel(src, chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD0);
+	writel(upper_32_bits(src), chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD1);
+	writel(len, chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD2);
+
+	if (chan->is_dmacoherent)
+		writel(ZYNQMP_DMA_DESC_CTRL_COHRNT,
+			chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD3);
+	else
+		writel(0, chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD3);
+
+	writel(dst, chan->regs + ZYNQMP_DMA_DST_DSCR_WRD0);
+	writel(upper_32_bits(dst), chan->regs + ZYNQMP_DMA_DST_DSCR_WRD1);
+	writel(len, chan->regs + ZYNQMP_DMA_DST_DSCR_WRD2);
+
+	if (chan->is_dmacoherent)
+		val = ZYNQMP_DMA_DESC_CTRL_COHRNT |
+				ZYNQMP_DMA_DESC_CTRL_COMP_INT;
+	else
+		val = ZYNQMP_DMA_DESC_CTRL_COMP_INT;
+	writel(val, chan->regs + ZYNQMP_DMA_DST_DSCR_WRD3);
+}
+
+/**
+ * zynqmp_dma_config_sg_ll_desc - Configure the linked list descriptor
+ * @chan: ZynqMP DMA channel pointer
+ * @sdesc: Hw descriptor pointer
+ * @src: Source buffer address
+ * @dst: Destination buffer address
+ * @len: Transfer length
+ * @prev: Previous hw descriptor pointer
+ */
+static void zynqmp_dma_config_sg_ll_desc(struct zynqmp_dma_chan *chan,
+				   struct zynqmp_dma_desc_ll *sdesc,
+				   dma_addr_t src, dma_addr_t dst, size_t len,
+				   struct zynqmp_dma_desc_ll *prev)
+{
+	struct zynqmp_dma_desc_ll *ddesc = sdesc + 1;
+
+	sdesc->size = ddesc->size = len;
+	sdesc->addr = src;
+	ddesc->addr = dst;
+
+	sdesc->ctrl = ddesc->ctrl = ZYNQMP_DMA_DESC_CTRL_SIZE_256;
+	if (chan->is_dmacoherent) {
+		sdesc->ctrl |= ZYNQMP_DMA_DESC_CTRL_COHRNT;
+		ddesc->ctrl |= ZYNQMP_DMA_DESC_CTRL_COHRNT;
+	}
+
+	if (prev) {
+		dma_addr_t addr = chan->desc_pool_p +
+			    ((dma_addr_t)sdesc - (dma_addr_t)chan->desc_pool_v);
+		ddesc = prev + 1;
+		prev->nxtdscraddr = addr;
+		ddesc->nxtdscraddr = addr + ZYNQMP_DMA_DESC_SIZE(chan);
+	}
+}
+
+/**
+ * zynqmp_dma_init - Initialize the channel
+ * @chan: ZynqMP DMA channel pointer
+ */
+static void zynqmp_dma_init(struct zynqmp_dma_chan *chan)
+{
+	u32 val;
+
+	writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS);
+	val = readl(chan->regs + ZYNQMP_DMA_ISR);
+	writel(val, chan->regs + ZYNQMP_DMA_ISR);
+
+	val = 0;
+	if (chan->has_sg)
+		val |= ZYNQMP_DMA_POINT_TYPE_SG;
+	writel(val, chan->regs + ZYNQMP_DMA_CTRL0);
+
+	val = 0;
+	if (chan->is_dmacoherent) {
+		val |= ZYNQMP_DMA_AXCOHRNT;
+		val = (val & ~ZYNQMP_DMA_AXCACHE) |
+			(ZYNQMP_DMA_AXCACHE_VAL << ZYNQMP_DMA_AXCACHE_OFST);
+	}
+	writel(val, chan->regs + ZYNQMP_DMA_DSCR_ATTR);
+
+	val = readl(chan->regs + ZYNQMP_DMA_DATA_ATTR);
+	if (chan->is_dmacoherent) {
+		val = (val & ~ZYNQMP_DMA_ARCACHE) |
+			(ZYNQMP_DMA_AXCACHE_VAL << ZYNQMP_DMA_ARCACHE_OFST);
+		val = (val & ~ZYNQMP_DMA_AWCACHE) |
+			(ZYNQMP_DMA_AXCACHE_VAL << ZYNQMP_DMA_AWCACHE_OFST);
+	}
+	writel(val, chan->regs + ZYNQMP_DMA_DATA_ATTR);
+
+	/* Clearing the interrupt account rgisters */
+	val = readl(chan->regs + ZYNQMP_DMA_IRQ_SRC_ACCT);
+	val = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
+
+	chan->idle = true;
+}
+
+/**
+ * zynqmp_dma_tx_submit - Submit DMA transaction
+ * @tx: Async transaction descriptor pointer
+ *
+ * Return: cookie value
+ */
+static dma_cookie_t zynqmp_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct zynqmp_dma_chan *chan = to_chan(tx->chan);
+	struct zynqmp_dma_desc_sw *desc, *new;
+	dma_cookie_t cookie;
+
+	new = tx_to_desc(tx);
+	spin_lock_bh(&chan->lock);
+	cookie = dma_cookie_assign(tx);
+
+	if (!list_empty(&chan->pending_list) && chan->has_sg) {
+		desc = list_last_entry(&chan->pending_list,
+				     struct zynqmp_dma_desc_sw, node);
+		if (!list_empty(&desc->tx_list))
+			desc = list_last_entry(&desc->tx_list,
+					       struct zynqmp_dma_desc_sw, node);
+		desc->src_v->nxtdscraddr = new->src_p;
+		desc->src_v->ctrl &= ~ZYNQMP_DMA_DESC_CTRL_STOP;
+		desc->dst_v->nxtdscraddr = new->dst_p;
+		desc->dst_v->ctrl &= ~ZYNQMP_DMA_DESC_CTRL_STOP;
+	}
+
+	list_add_tail(&new->node, &chan->pending_list);
+	spin_unlock_bh(&chan->lock);
+
+	return cookie;
+}
+
+/**
+ * zynqmp_dma_get_descriptor - Get the sw descriptor from the pool
+ * @chan: ZynqMP DMA channel pointer
+ *
+ * Return: The sw descriptor
+ */
+static struct zynqmp_dma_desc_sw *
+zynqmp_dma_get_descriptor(struct zynqmp_dma_chan *chan)
+{
+	struct zynqmp_dma_desc_sw *desc;
+
+	spin_lock_bh(&chan->lock);
+	desc = list_first_entry(&chan->free_list, struct zynqmp_dma_desc_sw,
+				 node);
+	list_del(&desc->node);
+	spin_unlock_bh(&chan->lock);
+
+	INIT_LIST_HEAD(&desc->tx_list);
+	/* Clear the src and dst descriptor memory */
+	if (chan->has_sg) {
+		memset((void *)desc->src_v, 0, ZYNQMP_DMA_DESC_SIZE(chan));
+		memset((void *)desc->dst_v, 0, ZYNQMP_DMA_DESC_SIZE(chan));
+	}
+
+	return desc;
+}
+
+/**
+ * zynqmp_dma_free_descriptor - Issue pending transactions
+ * @chan: ZynqMP DMA channel pointer
+ * @sdesc: Transaction descriptor pointer
+ */
+static void zynqmp_dma_free_descriptor(struct zynqmp_dma_chan *chan,
+				 struct zynqmp_dma_desc_sw *sdesc)
+{
+	struct zynqmp_dma_desc_sw *child, *next;
+
+	chan->desc_free_cnt++;
+	list_add_tail(&sdesc->node, &chan->free_list);
+	list_for_each_entry_safe(child, next, &sdesc->tx_list, node) {
+		chan->desc_free_cnt++;
+		INIT_LIST_HEAD(&child->tx_list);
+		list_move_tail(&child->node, &chan->free_list);
+	}
+	INIT_LIST_HEAD(&sdesc->tx_list);
+}
+
+/**
+ * zynqmp_dma_free_desc_list - Free descriptors list
+ * @chan: ZynqMP DMA channel pointer
+ * @list: List to parse and delete the descriptor
+ */
+static void zynqmp_dma_free_desc_list(struct zynqmp_dma_chan *chan,
+				      struct list_head *list)
+{
+	struct zynqmp_dma_desc_sw *desc, *next;
+
+	list_for_each_entry_safe(desc, next, list, node)
+		zynqmp_dma_free_descriptor(chan, desc);
+}
+
+/**
+ * zynqmp_dma_alloc_chan_resources - Allocate channel resources
+ * @dchan: DMA channel
+ *
+ * Return: Number of descriptors on success and failure value on error
+ */
+static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan)
+{
+	struct zynqmp_dma_chan *chan = to_chan(dchan);
+	struct zynqmp_dma_desc_sw *desc;
+	int i;
+
+	chan->sw_desc_pool = kzalloc(sizeof(*desc) * ZYNQMP_DMA_NUM_DESCS,
+				     GFP_KERNEL);
+	if (!chan->sw_desc_pool)
+		return -ENOMEM;
+	chan->idle = true;
+	chan->desc_free_cnt = ZYNQMP_DMA_NUM_DESCS;
+
+	INIT_LIST_HEAD(&chan->free_list);
+
+	for (i = 0; i < ZYNQMP_DMA_NUM_DESCS; i++) {
+		desc = chan->sw_desc_pool + i;
+		dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
+		desc->async_tx.tx_submit = zynqmp_dma_tx_submit;
+		list_add_tail(&desc->node, &chan->free_list);
+	}
+
+	if (!chan->has_sg)
+		return 0;
+
+	chan->desc_pool_v = dma_zalloc_coherent(chan->dev,
+				(2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS),
+				&chan->desc_pool_p, GFP_KERNEL);
+	if (!chan->desc_pool_v)
+		return -ENOMEM;
+
+	for (i = 0; i < ZYNQMP_DMA_NUM_DESCS; i++) {
+		desc = chan->sw_desc_pool + i;
+		desc->src_v = (struct zynqmp_dma_desc_ll *) (chan->desc_pool_v +
+					(i * ZYNQMP_DMA_DESC_SIZE(chan) * 2));
+		desc->dst_v = (struct zynqmp_dma_desc_ll *) (desc->src_v + 1);
+		desc->src_p = chan->desc_pool_p +
+				(i * ZYNQMP_DMA_DESC_SIZE(chan) * 2);
+		desc->dst_p = desc->src_p + ZYNQMP_DMA_DESC_SIZE(chan);
+	}
+
+	return ZYNQMP_DMA_NUM_DESCS;
+}
+
+/**
+ * zynqmp_dma_start - Start DMA channel
+ * @chan: ZynqMP DMA channel pointer
+ */
+static void zynqmp_dma_start(struct zynqmp_dma_chan *chan)
+{
+	writel(ZYNQMP_DMA_INT_EN_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IER);
+	chan->idle = false;
+	writel(ZYNQMP_DMA_ENABLE, chan->regs + ZYNQMP_DMA_CTRL2);
+}
+
+/**
+ * zynqmp_dma_handle_ovfl_int - Process the overflow interrupt
+ * @chan: ZynqMP DMA channel pointer
+ * @status: Interrupt status value
+ */
+static void zynqmp_dma_handle_ovfl_int(struct zynqmp_dma_chan *chan, u32 status)
+{
+	u32 val;
+
+	if (status & ZYNQMP_DMA_IRQ_DST_ACCT_ERR)
+		val = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
+	if (status & ZYNQMP_DMA_IRQ_SRC_ACCT_ERR)
+		val = readl(chan->regs + ZYNQMP_DMA_IRQ_SRC_ACCT);
+}
+
+static void zynqmp_dma_config(struct zynqmp_dma_chan *chan)
+{
+	u32 val;
+
+	val = readl(chan->regs + ZYNQMP_DMA_CTRL0);
+	if (chan->config.ovrfetch)
+		val |= ZYNQMP_DMA_OVR_FETCH;
+	if (chan->config.ratectrl) {
+		val |= ZYNQMP_DMA_RATE_CTRL_EN;
+		writel(chan->config.ratectrl, chan->regs +
+		       ZYNQMP_DMA_RATE_CTRL);
+	}
+	writel(val, chan->regs + ZYNQMP_DMA_CTRL0);
+
+	val = readl(chan->regs + ZYNQMP_DMA_CTRL1);
+	if (chan->config.src_issue)
+		val = (val & ~ZYNQMP_DMA_SRC_ISSUE) | chan->config.src_issue;
+	else
+		val |= ZYNQMP_DMA_SRC_ISSUE_RST_VAL;
+	writel(val, chan->regs + ZYNQMP_DMA_CTRL1);
+
+	val = readl(chan->regs + ZYNQMP_DMA_DATA_ATTR);
+	if (chan->config.src_burst_len)
+		val = (val & ~ZYNQMP_DMA_ARLEN) |
+			(chan->config.src_burst_len << ZYNQMP_DMA_ARLEN_OFST);
+	else
+		val |= ZYNQMP_DMA_ARLEN_RST_VAL;
+
+	if (chan->config.dst_burst_len)
+		val = (val & ~ZYNQMP_DMA_AWLEN) |
+			(chan->config.dst_burst_len << ZYNQMP_DMA_AWLEN_OFST);
+	else
+		val |= ZYNQMP_DMA_AWLEN_RST_VAL;
+	writel(val, chan->regs + ZYNQMP_DMA_DATA_ATTR);
+
+}
+
+/**
+ * zynqmp_dma_start_transfer - Initiate the new transfer
+ * @chan: ZynqMP DMA channel pointer
+ */
+static void zynqmp_dma_start_transfer(struct zynqmp_dma_chan *chan)
+{
+	struct zynqmp_dma_desc_sw *desc;
+
+	if (!zynqmp_dma_chan_is_idle(chan))
+		return;
+
+	zynqmp_dma_config(chan);
+
+	desc = list_first_entry_or_null(&chan->pending_list,
+					struct zynqmp_dma_desc_sw, node);
+	if (!desc)
+		return;
+
+	if (chan->has_sg)
+		list_splice_tail_init(&chan->pending_list, &chan->active_list);
+	else
+		list_move_tail(&desc->node, &chan->active_list);
+
+	if (chan->has_sg)
+		zynqmp_dma_update_desc_to_ctrlr(chan, desc);
+	else
+		zynqmp_dma_config_simple_desc(chan, desc->src, desc->dst,
+					      desc->len);
+
+	zynqmp_dma_start(chan);
+}
+
+
+/**
+ * zynqmp_dma_chan_desc_cleanup - Cleanup the completed descriptors
+ * @chan: ZynqMP DMA channel
+ */
+static void zynqmp_dma_chan_desc_cleanup(struct zynqmp_dma_chan *chan)
+{
+	struct zynqmp_dma_desc_sw *desc, *next;
+
+	list_for_each_entry_safe(desc, next, &chan->done_list, node) {
+		dma_async_tx_callback callback;
+		void *callback_param;
+
+		list_del(&desc->node);
+
+		callback = desc->async_tx.callback;
+		callback_param = desc->async_tx.callback_param;
+		if (callback) {
+			spin_unlock(&chan->lock);
+			callback(callback_param);
+			spin_lock(&chan->lock);
+		}
+
+		/* Run any dependencies, then free the descriptor */
+		zynqmp_dma_free_descriptor(chan, desc);
+	}
+}
+
+/**
+ * zynqmp_dma_complete_descriptor - Mark the active descriptor as complete
+ * @chan: ZynqMP DMA channel pointer
+ */
+static void zynqmp_dma_complete_descriptor(struct zynqmp_dma_chan *chan)
+{
+	struct zynqmp_dma_desc_sw *desc;
+
+	desc = list_first_entry_or_null(&chan->active_list,
+					struct zynqmp_dma_desc_sw, node);
+	if (!desc)
+		return;
+	list_del(&desc->node);
+	dma_cookie_complete(&desc->async_tx);
+	list_add_tail(&desc->node, &chan->done_list);
+}
+
+/**
+ * zynqmp_dma_issue_pending - Issue pending transactions
+ * @dchan: DMA channel pointer
+ */
+static void zynqmp_dma_issue_pending(struct dma_chan *dchan)
+{
+	struct zynqmp_dma_chan *chan = to_chan(dchan);
+
+	spin_lock_bh(&chan->lock);
+	zynqmp_dma_start_transfer(chan);
+	spin_unlock_bh(&chan->lock);
+}
+
+/**
+ * zynqmp_dma_free_descriptors - Free channel descriptors
+ * @dchan: DMA channel pointer
+ */
+static void zynqmp_dma_free_descriptors(struct zynqmp_dma_chan *chan)
+{
+	zynqmp_dma_free_desc_list(chan, &chan->active_list);
+	zynqmp_dma_free_desc_list(chan, &chan->pending_list);
+	zynqmp_dma_free_desc_list(chan, &chan->done_list);
+}
+
+/**
+ * zynqmp_dma_free_chan_resources - Free channel resources
+ * @dchan: DMA channel pointer
+ */
+static void zynqmp_dma_free_chan_resources(struct dma_chan *dchan)
+{
+	struct zynqmp_dma_chan *chan = to_chan(dchan);
+
+	spin_lock_bh(&chan->lock);
+	zynqmp_dma_free_descriptors(chan);
+	spin_unlock_bh(&chan->lock);
+	dma_free_coherent(chan->dev,
+		(2 * ZYNQMP_DMA_DESC_SIZE(chan) * ZYNQMP_DMA_NUM_DESCS),
+		chan->desc_pool_v, chan->desc_pool_p);
+	kfree(chan->sw_desc_pool);
+}
+
+/**
+ * zynqmp_dma_tx_status - Get dma transaction status
+ * @dchan: DMA channel pointer
+ * @cookie: Transaction identifier
+ * @txstate: Transaction state
+ *
+ * Return: DMA transaction status
+ */
+static enum dma_status zynqmp_dma_tx_status(struct dma_chan *dchan,
+				      dma_cookie_t cookie,
+				      struct dma_tx_state *txstate)
+{
+	return dma_cookie_status(dchan, cookie, txstate);
+}
+
+/**
+ * zynqmp_dma_reset - Reset the channel
+ * @chan: ZynqMP DMA channel pointer
+ */
+static void zynqmp_dma_reset(struct zynqmp_dma_chan *chan)
+{
+	writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS);
+
+	zynqmp_dma_complete_descriptor(chan);
+	zynqmp_dma_chan_desc_cleanup(chan);
+	zynqmp_dma_free_descriptors(chan);
+	zynqmp_dma_init(chan);
+}
+
+/**
+ * zynqmp_dma_irq_handler - ZynqMP DMA Interrupt handler
+ * @irq: IRQ number
+ * @data: Pointer to the ZynqMP DMA channel structure
+ *
+ * Return: IRQ_HANDLED/IRQ_NONE
+ */
+static irqreturn_t zynqmp_dma_irq_handler(int irq, void *data)
+{
+	struct zynqmp_dma_chan *chan = (struct zynqmp_dma_chan *)data;
+	u32 isr, imr, status;
+	irqreturn_t ret = IRQ_NONE;
+
+	isr = readl(chan->regs + ZYNQMP_DMA_ISR);
+	imr = readl(chan->regs + ZYNQMP_DMA_IMR);
+	status = isr & ~imr;
+
+	writel(isr, chan->regs + ZYNQMP_DMA_ISR);
+	if (status & ZYNQMP_DMA_INT_DONE) {
+		tasklet_schedule(&chan->tasklet);
+		ret = IRQ_HANDLED;
+	}
+
+	if (status & ZYNQMP_DMA_DONE)
+		chan->idle = true;
+
+	if (status & ZYNQMP_DMA_INT_ERR) {
+		chan->err = true;
+		tasklet_schedule(&chan->tasklet);
+		dev_err(chan->dev, "Channel %p has errors\n", chan);
+		ret = IRQ_HANDLED;
+	}
+
+	if (status & ZYNQMP_DMA_INT_OVRFL) {
+		zynqmp_dma_handle_ovfl_int(chan, status);
+		dev_info(chan->dev, "Channel %p overflow interrupt\n", chan);
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+/**
+ * zynqmp_dma_do_tasklet - Schedule completion tasklet
+ * @data: Pointer to the ZynqMP DMA channel structure
+ */
+static void zynqmp_dma_do_tasklet(unsigned long data)
+{
+	struct zynqmp_dma_chan *chan = (struct zynqmp_dma_chan *)data;
+	u32 count;
+
+	spin_lock(&chan->lock);
+
+	if (chan->err) {
+		zynqmp_dma_reset(chan);
+		chan->err = false;
+		goto unlock;
+	}
+
+	count = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
+
+	while (count) {
+		zynqmp_dma_complete_descriptor(chan);
+		zynqmp_dma_chan_desc_cleanup(chan);
+		count--;
+	}
+
+	if (chan->idle)
+		zynqmp_dma_start_transfer(chan);
+
+unlock:
+	spin_unlock(&chan->lock);
+}
+
+/**
+ * zynqmp_dma_device_terminate_all - Aborts all transfers on a channel
+ * @dchan: DMA channel pointer
+ *
+ * Return: Always '0'
+ */
+static int zynqmp_dma_device_terminate_all(struct dma_chan *dchan)
+{
+	struct zynqmp_dma_chan *chan = to_chan(dchan);
+
+	spin_lock_bh(&chan->lock);
+	writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS);
+	zynqmp_dma_free_descriptors(chan);
+	spin_unlock_bh(&chan->lock);
+
+	return 0;
+}
+
+/**
+ * zynqmp_dma_prep_memcpy - prepare descriptors for memcpy transaction
+ * @dchan: DMA channel
+ * @dma_dst: Destination buffer address
+ * @dma_src: Source buffer address
+ * @len: Transfer length
+ * @flags: transfer ack flags
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
+ */
+static struct dma_async_tx_descriptor *zynqmp_dma_prep_memcpy(
+				struct dma_chan *dchan, dma_addr_t dma_dst,
+				dma_addr_t dma_src, size_t len, ulong flags)
+{
+	struct zynqmp_dma_chan *chan;
+	struct zynqmp_dma_desc_sw *new, *first = NULL;
+	void *desc = NULL, *prev = NULL;
+	size_t copy;
+	u32 desc_cnt;
+
+	chan = to_chan(dchan);
+
+	if ((len > ZYNQMP_DMA_MAX_TRANS_LEN) && !chan->has_sg)
+		return NULL;
+
+	desc_cnt = DIV_ROUND_UP(len, ZYNQMP_DMA_MAX_TRANS_LEN);
+
+	spin_lock_bh(&chan->lock);
+	if ((desc_cnt > chan->desc_free_cnt) && chan->has_sg) {
+		spin_unlock_bh(&chan->lock);
+		dev_dbg(chan->dev, "chan %p descs are not available\n", chan);
+		return NULL;
+	}
+	chan->desc_free_cnt = chan->desc_free_cnt - desc_cnt;
+	spin_unlock_bh(&chan->lock);
+
+	do {
+		/* Allocate and populate the descriptor */
+		new = zynqmp_dma_get_descriptor(chan);
+
+		copy = min_t(size_t, len, ZYNQMP_DMA_MAX_TRANS_LEN);
+		if (chan->has_sg) {
+			desc = (struct zynqmp_dma_desc_ll *)new->src_v;
+			zynqmp_dma_config_sg_ll_desc(chan, desc, dma_src,
+						     dma_dst, copy, prev);
+		} else {
+			new->src = dma_src;
+			new->dst = dma_dst;
+			new->len = len;
+		}
+
+		prev = desc;
+		len -= copy;
+		dma_src += copy;
+		dma_dst += copy;
+		if (!first)
+			first = new;
+		else
+			list_add_tail(&new->node, &first->tx_list);
+	} while (len);
+
+	if (chan->has_sg)
+		zynqmp_dma_desc_config_eod(chan, desc);
+
+	async_tx_ack(&first->async_tx);
+	first->async_tx.flags = flags;
+	return &first->async_tx;
+}
+
+/**
+ * zynqmp_dma_prep_slave_sg - prepare descriptors for a memory sg transaction
+ * @dchan: DMA channel
+ * @dst_sg: Destination scatter list
+ * @dst_sg_len: Number of entries in destination scatter list
+ * @src_sg: Source scatter list
+ * @src_sg_len: Number of entries in source scatter list
+ * @flags: transfer ack flags
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
+ */
+static struct dma_async_tx_descriptor *zynqmp_dma_prep_sg(
+			struct dma_chan *dchan, struct scatterlist *dst_sg,
+			unsigned int dst_sg_len, struct scatterlist *src_sg,
+			unsigned int src_sg_len, unsigned long flags)
+{
+	struct zynqmp_dma_desc_sw *new, *first = NULL;
+	struct zynqmp_dma_chan *chan = to_chan(dchan);
+	void *desc = NULL, *prev = NULL;
+	size_t len, dst_avail, src_avail;
+	dma_addr_t dma_dst, dma_src;
+	u32 desc_cnt = 0, i;
+	struct scatterlist *sg;
+
+	if (!chan->has_sg)
+		return NULL;
+
+	for_each_sg(src_sg, sg, src_sg_len, i)
+		desc_cnt += DIV_ROUND_UP(sg_dma_len(sg),
+					 ZYNQMP_DMA_MAX_TRANS_LEN);
+
+	spin_lock_bh(&chan->lock);
+	if (desc_cnt > chan->desc_free_cnt) {
+		spin_unlock_bh(&chan->lock);
+		dev_dbg(chan->dev, "chan %p descs are not available\n", chan);
+		return NULL;
+	}
+	chan->desc_free_cnt = chan->desc_free_cnt - desc_cnt;
+	spin_unlock_bh(&chan->lock);
+
+	dst_avail = sg_dma_len(dst_sg);
+	src_avail = sg_dma_len(src_sg);
+
+	/* Run until we are out of scatterlist entries */
+	while (true) {
+		/* Allocate and populate the descriptor */
+		new = zynqmp_dma_get_descriptor(chan);
+		desc = (struct zynqmp_dma_desc_ll *)new->src_v;
+		len = min_t(size_t, src_avail, dst_avail);
+		len = min_t(size_t, len, ZYNQMP_DMA_MAX_TRANS_LEN);
+		if (len == 0)
+			goto fetch;
+		dma_dst = sg_dma_address(dst_sg) + sg_dma_len(dst_sg) -
+			dst_avail;
+		dma_src = sg_dma_address(src_sg) + sg_dma_len(src_sg) -
+			src_avail;
+
+		zynqmp_dma_config_sg_ll_desc(chan, desc, dma_src, dma_dst,
+					     len, prev);
+		prev = desc;
+		dst_avail -= len;
+		src_avail -= len;
+
+		if (!first)
+			first = new;
+		else
+			list_add_tail(&new->node, &first->tx_list);
+fetch:
+		/* Fetch the next dst scatterlist entry */
+		if (dst_avail == 0) {
+			if (dst_sg_len == 0)
+				break;
+			dst_sg = sg_next(dst_sg);
+			if (dst_sg == NULL)
+				break;
+			dst_sg_len--;
+			dst_avail = sg_dma_len(dst_sg);
+		}
+		/* Fetch the next src scatterlist entry */
+		if (src_avail == 0) {
+			if (src_sg_len == 0)
+				break;
+			src_sg = sg_next(src_sg);
+			if (src_sg == NULL)
+				break;
+			src_sg_len--;
+			src_avail = sg_dma_len(src_sg);
+		}
+	}
+
+	zynqmp_dma_desc_config_eod(chan, desc);
+	first->async_tx.flags = flags;
+	return &first->async_tx;
+}
+
+/**
+ * zynqmp_dma_channel_set_config - Configure ZYNQMP DMA channel
+ * @dchan: DMA channel
+ * @cfg: ZYNQMP DMA device configuration pointer
+ *
+ * Return: '0' always
+ */
+int zynqmp_dma_channel_set_config(struct dma_chan *dchan,
+				  struct zynqmp_dma_config *cfg)
+{
+	struct zynqmp_dma_chan *chan = to_chan(dchan);
+
+	chan->config.ovrfetch = cfg->ovrfetch;
+	chan->config.ratectrl = cfg->ratectrl;
+	chan->config.src_issue = cfg->src_issue;
+	chan->config.src_burst_len = cfg->src_burst_len;
+	chan->config.dst_burst_len = cfg->dst_burst_len;
+
+	return 0;
+}
+EXPORT_SYMBOL(zynqmp_dma_channel_set_config);
+
+/**
+ * zynqmp_dma_chan_remove - Channel remove function
+ * @chan: ZynqMP DMA channel pointer
+ */
+static void zynqmp_dma_chan_remove(struct zynqmp_dma_chan *chan)
+{
+	if (!chan)
+		return;
+
+	devm_free_irq(chan->zdev->dev, chan->irq, chan);
+	tasklet_kill(&chan->tasklet);
+	list_del(&chan->common.device_node);
+	clk_disable_unprepare(chan->clk_apb);
+	clk_disable_unprepare(chan->clk_main);
+}
+
+/**
+ * zynqmp_dma_chan_probe - Per Channel Probing
+ * @zdev: Driver specific device structure
+ * @pdev: Pointer to the platform_device structure
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev,
+			   struct platform_device *pdev)
+{
+	struct zynqmp_dma_chan *chan;
+	struct resource *res;
+	struct device_node *node = pdev->dev.of_node;
+	int err;
+
+	chan = devm_kzalloc(zdev->dev, sizeof(*chan), GFP_KERNEL);
+	if (!chan)
+		return -ENOMEM;
+	chan->dev = zdev->dev;
+	chan->zdev = zdev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	chan->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(chan->regs))
+		return PTR_ERR(chan->regs);
+
+	chan->bus_width = ZYNQMP_DMA_BUS_WIDTH_64;
+	chan->config.src_issue = ZYNQMP_DMA_SRC_ISSUE_RST_VAL;
+	chan->config.dst_burst_len = ZYNQMP_DMA_AWLEN_RST_VAL;
+	chan->config.src_burst_len = ZYNQMP_DMA_ARLEN_RST_VAL;
+	err = of_property_read_u32(node, "xlnx,bus-width", &chan->bus_width);
+	if ((err < 0) && ((chan->bus_width != ZYNQMP_DMA_BUS_WIDTH_64) ||
+			  (chan->bus_width != ZYNQMP_DMA_BUS_WIDTH_128))) {
+		dev_err(zdev->dev, "invalid bus-width value");
+		return err;
+	}
+
+	chan->bus_width = chan->bus_width / 8;
+	chan->has_sg = of_property_read_bool(node, "xlnx,include-sg");
+	chan->is_dmacoherent =  of_property_read_bool(node, "dma-coherent");
+
+	zdev->chan = chan;
+	tasklet_init(&chan->tasklet, zynqmp_dma_do_tasklet, (ulong)chan);
+	spin_lock_init(&chan->lock);
+	INIT_LIST_HEAD(&chan->active_list);
+	INIT_LIST_HEAD(&chan->pending_list);
+	INIT_LIST_HEAD(&chan->done_list);
+	INIT_LIST_HEAD(&chan->free_list);
+
+	dma_cookie_init(&chan->common);
+	chan->common.device = &zdev->common;
+	list_add_tail(&chan->common.device_node, &zdev->common.channels);
+
+	zynqmp_dma_init(chan);
+	chan->irq = platform_get_irq(pdev, 0);
+	if (chan->irq < 0)
+		return -ENXIO;
+	err = devm_request_irq(&pdev->dev, chan->irq, zynqmp_dma_irq_handler, 0,
+			       "zynqmp-dma", chan);
+	if (err)
+		return err;
+	chan->clk_main = devm_clk_get(&pdev->dev, "clk_main");
+	if (IS_ERR(chan->clk_main)) {
+		dev_err(&pdev->dev, "main clock not found.\n");
+		return PTR_ERR(chan->clk_main);
+	}
+
+	chan->clk_apb = devm_clk_get(&pdev->dev, "clk_apb");
+	if (IS_ERR(chan->clk_apb)) {
+		dev_err(&pdev->dev, "apb clock not found.\n");
+		return PTR_ERR(chan->clk_apb);
+	}
+
+	err = clk_prepare_enable(chan->clk_main);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to enable main clock.\n");
+		return err;
+	}
+
+	err = clk_prepare_enable(chan->clk_apb);
+	if (err) {
+		clk_disable_unprepare(chan->clk_main);
+		dev_err(&pdev->dev, "Unable to enable apb clock.\n");
+		return err;
+	}
+
+	chan->desc_size = sizeof(struct zynqmp_dma_desc_ll);
+	chan->idle = true;
+	return 0;
+}
+
+/**
+ * of_zynqmp_dma_xlate - Translation function
+ * @dma_spec: Pointer to DMA specifier as found in the device tree
+ * @ofdma: Pointer to DMA controller data
+ *
+ * Return: DMA channel pointer on success and NULL on error
+ */
+static struct dma_chan *of_zynqmp_dma_xlate(struct of_phandle_args *dma_spec,
+					    struct of_dma *ofdma)
+{
+	struct zynqmp_dma_device *zdev = ofdma->of_dma_data;
+
+	return dma_get_slave_channel(&zdev->chan->common);
+}
+
+/**
+ * zynqmp_dma_probe - Driver probe function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int zynqmp_dma_probe(struct platform_device *pdev)
+{
+	struct zynqmp_dma_device *zdev;
+	struct dma_device *p;
+	int ret;
+
+	zdev = devm_kzalloc(&pdev->dev, sizeof(*zdev), GFP_KERNEL);
+	if (!zdev)
+		return -ENOMEM;
+
+	zdev->dev = &pdev->dev;
+	INIT_LIST_HEAD(&zdev->common.channels);
+
+	dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
+	dma_cap_set(DMA_SG, zdev->common.cap_mask);
+	dma_cap_set(DMA_MEMCPY, zdev->common.cap_mask);
+
+	p = &zdev->common;
+	p->device_prep_dma_sg = zynqmp_dma_prep_sg;
+	p->device_prep_dma_memcpy = zynqmp_dma_prep_memcpy;
+	p->device_terminate_all = zynqmp_dma_device_terminate_all;
+	p->device_issue_pending = zynqmp_dma_issue_pending;
+	p->device_alloc_chan_resources = zynqmp_dma_alloc_chan_resources;
+	p->device_free_chan_resources = zynqmp_dma_free_chan_resources;
+	p->device_tx_status = zynqmp_dma_tx_status;
+	p->dev = &pdev->dev;
+
+	platform_set_drvdata(pdev, zdev);
+
+	ret = zynqmp_dma_chan_probe(zdev, pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Probing channel failed\n");
+		goto free_chan_resources;
+	}
+
+	p->dst_addr_widths = BIT(zdev->chan->bus_width);
+	p->src_addr_widths = BIT(zdev->chan->bus_width);
+
+	dma_async_device_register(&zdev->common);
+
+	ret = of_dma_controller_register(pdev->dev.of_node,
+					 of_zynqmp_dma_xlate, zdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to register DMA to DT\n");
+		dma_async_device_unregister(&zdev->common);
+		goto free_chan_resources;
+	}
+
+	dev_info(&pdev->dev, "ZynqMP DMA driver Probe success\n");
+
+	return 0;
+
+free_chan_resources:
+	zynqmp_dma_chan_remove(zdev->chan);
+	return ret;
+}
+
+/**
+ * zynqmp_dma_remove - Driver remove function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * Return: Always '0'
+ */
+static int zynqmp_dma_remove(struct platform_device *pdev)
+{
+	struct zynqmp_dma_device *zdev = platform_get_drvdata(pdev);
+
+	of_dma_controller_free(pdev->dev.of_node);
+	dma_async_device_unregister(&zdev->common);
+
+	zynqmp_dma_chan_remove(zdev->chan);
+
+	return 0;
+}
+
+static const struct of_device_id zynqmp_dma_of_match[] = {
+	{ .compatible = "xlnx,zynqmp-dma-1.0", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, zynqmp_dma_of_match);
+
+static struct platform_driver zynqmp_dma_driver = {
+	.driver = {
+		.name = "xilinx-zynqmp-dma",
+		.of_match_table = zynqmp_dma_of_match,
+	},
+	.probe = zynqmp_dma_probe,
+	.remove = zynqmp_dma_remove,
+};
+
+module_platform_driver(zynqmp_dma_driver);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx ZynqMP DMA driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/dma/xilinx_dma.h b/include/linux/dma/xilinx_dma.h
index 3ae3000..f89e63e 100644
--- a/include/linux/dma/xilinx_dma.h
+++ b/include/linux/dma/xilinx_dma.h
@@ -42,6 +42,22 @@ struct xilinx_vdma_config {
 };
 
 /**
+ * struct zynqmp_dma_config - ZYNQMP DMA Configuration structure
+ * @ovrfetch: Overfetch status
+ * @ratectrl: Rate control value
+ * @src_issue: Out standing transactions on source
+ * @src_burst_len: Source burst length
+ * @dst_burst_len: Dest burst length
+ */
+struct zynqmp_dma_config {
+	bool ovrfetch;
+	u32 ratectrl;
+	u32 src_issue;
+	u32 src_burst_len;
+	u32 dst_burst_len;
+};
+
+/**
  * enum xdma_ip_type: DMA IP type.
  *
  * XDMA_TYPE_AXIDMA: Axi dma ip.
@@ -57,5 +73,6 @@ enum xdma_ip_type {
 
 int xilinx_vdma_channel_set_config(struct dma_chan *dchan,
 					struct xilinx_vdma_config *cfg);
-
+int zynqmp_dma_channel_set_config(struct dma_chan *dchan,
+					struct zynqmp_dma_config *cfg);
 #endif
-- 
2.1.1



From andre.przywara at arm.com  Thu May 12 05:33:24 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 12 May 2016 13:33:24 +0100
Subject: [PATCH v3 33/55] KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR, 
 TYPER handlers
In-Reply-To: <20160512114703.GD27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-34-git-send-email-andre.przywara@arm.com>
 <20160512114703.GD27623@cbox>
Message-ID: <57347814.8060206@arm.com>

Hi,

On 12/05/16 12:47, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:46AM +0100, Andre Przywara wrote:
>> As in the GICv2 emulation we handle those three registers in one
>> function.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - kick VCPUs if distributor gets enabled
>>
>> Changelog v1 .. v2:
>> - rewrite write handler to use switch statement
>>
>>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 50 +++++++++++++++++++++++++++++++++++++++-
>>  virt/kvm/arm/vgic/vgic.h         |  2 ++
>>  2 files changed, 51 insertions(+), 1 deletion(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> index 06c7ec5..5f4558c 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> @@ -22,6 +22,54 @@
>>  #include "vgic.h"
>>  #include "vgic-mmio.h"
>>  
>> +static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
>> +					    gpa_t addr, unsigned int len)
>> +{
>> +	u32 value = 0;
>> +
>> +	switch (addr & 0x0c) {
>> +	case GICD_CTLR:
>> +		if (vcpu->kvm->arch.vgic.enabled)
>> +			value |= GICD_CTLR_ENABLE_SS_G1;
>> +		value |= GICD_CTLR_ARE_NS | GICD_CTLR_DS;
>> +		break;
>> +	case GICD_TYPER:
>> +		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
>> +		value = (value >> 5) - 1;
>> +		value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19;
>> +		break;
>> +	case GICD_IIDR:
>> +		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
>> +		break;
>> +	default:
>> +		return 0;
>> +	}
>> +
>> +	return extract_bytes(value, addr & 3, len);
> 
> why do we return extract_bytes here?  This register can only be accessed
> in full with a 32-bit aligned access, right?

... which we only ensure since last night.
So: yes, I think this can go.
Will fix it.

> 
>> +}
>> +
>> +static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
>> +				    gpa_t addr, unsigned int len,
>> +				    unsigned long val)
>> +{
>> +	switch (addr & 0x0c) {
>> +	case GICD_CTLR:
>> +		if (!(addr & 1)) {
> 
> obviously same question as on the v2 counterpart

Noted, will be fixed.

Cheers,
Andre.

> 
>> +			struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>> +			bool was_enabled = dist->enabled;
>> +
>> +			dist->enabled = val & GICD_CTLR_ENABLE_SS_G1;
>> +
>> +			if (!was_enabled && dist->enabled)
>> +				vgic_kick_vcpus(vcpu->kvm);
>> +		}
>> +		break;
>> +	case GICD_TYPER:
>> +	case GICD_IIDR:
>> +		return;
>> +	}
>> +}
>> +
>>  /*
>>   * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
>>   * redistributors, while SPIs are covered by registers in the distributor
>> @@ -46,7 +94,7 @@
>>  
>>  static const struct vgic_register_region vgic_v3_dist_registers[] = {
>>  	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
>> +		vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc, 16),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
>>  		vgic_mmio_read_rao, vgic_mmio_write_wi, 1),
>>  	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
>> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
>> index 39a8a65..635e2e2 100644
>> --- a/virt/kvm/arm/vgic/vgic.h
>> +++ b/virt/kvm/arm/vgic/vgic.h
>> @@ -19,6 +19,8 @@
>>  #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
>>  #define IMPLEMENTER_ARM		0x43b
>>  
>> +#define INTERRUPT_ID_BITS_SPIS	10
>> +
>>  #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
>>  
>>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>> -- 
>> 2.7.3
>>
> 


From andre.przywara at arm.com  Thu May 12 05:37:10 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 12 May 2016 13:37:10 +0100
Subject: [PATCH v3 35/55] KVM: arm/arm64: vgic-new: Add GICv3 IDREGS
 register handler
In-Reply-To: <20160512121226.GF27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-36-git-send-email-andre.przywara@arm.com>
 <20160512121226.GF27623@cbox>
Message-ID: <573478F6.5070103@arm.com>

Hi,

On 12/05/16 13:12, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:48AM +0100, Andre Przywara wrote:
>> We implement the only one ID register that is required by the
>> architecture, also this is the one that Linux actually checks.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog v1 .. v2:
>> - adapt to new MMIO framework
>>
>>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 20 ++++++++++++++++++--
>>  1 file changed, 18 insertions(+), 2 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> index d137242..48fba9c 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> @@ -110,6 +110,22 @@ static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
>>  	return extract_bytes(value, addr & 3, len);
>>  }
>>  
>> +static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu,
>> +					      gpa_t addr, unsigned int len)
>> +{
>> +	u32 regnr = (addr & 0x3f) - (GICD_IDREGS & 0x3f);
> 
> this regnr thing is confusing, because it's not an index, it's an
> address offset.
> 
> why can't you do:
> 
> 	switch (addr & 0xffff) {
> 	case GICD_PIDR2:
> 	}

Makes sense. This was a leftover from the time I had subtraction instead
of masking for the IRQ number determination.
Will fix it.

Thanks,
Andre.


From marc.zyngier at arm.com  Thu May 12 05:37:57 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 12 May 2016 13:37:57 +0100
Subject: [PATCH v3 36/55] KVM: arm/arm64: vgic-new: Add GICv3 IROUTER
 register handlers
In-Reply-To: <20160512122119.GH27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-37-git-send-email-andre.przywara@arm.com>
 <20160512122119.GH27623@cbox>
Message-ID: <57347925.2030902@arm.com>

On 12/05/16 13:21, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:49AM +0100, Andre Przywara wrote:
>> Since GICv3 supports much more than the 8 CPUs the GICv2 ITARGETSR
>> register can handle, the new IROUTER register covers the whole range
>> of possible target (V)CPUs by using the same MPIDR that the cores
>> report themselves.
>> In addition to translating this MPIDR into a vcpu pointer we store
>> the originally written value as well. The architecture allows to
>> write any values into the register, which must be read back as written.
>>
>> Since we don't support affinity level 3, we don't need to take care
>> about the upper word of this 64-bit register, which simplifies the
>> handling a bit.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changelog RFC..v1:
>> - fold in and simplify vgic_v3_irq_change_affinity
>>
>> Changelog v1 .. v2:
>> - adapt to new MMIO framework
>>
>>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 65 +++++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 64 insertions(+), 1 deletion(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> index 48fba9c..3bcc2c4 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>> @@ -86,6 +86,69 @@ static u32 compress_mpidr(unsigned long mpidr)
>>  	return ret;
>>  }
>>  
>> +static unsigned long decompress_mpidr(u32 value)
>> +{
>> +	unsigned long mpidr;
>> +
>> +	mpidr  = ((value >>  0) & 0xFF) << MPIDR_LEVEL_SHIFT(0);
>> +	mpidr |= ((value >>  8) & 0xFF) << MPIDR_LEVEL_SHIFT(1);
>> +	mpidr |= ((value >> 16) & 0xFF) << MPIDR_LEVEL_SHIFT(2);
>> +	mpidr |= (u64)((value >> 24) & 0xFF) << MPIDR_LEVEL_SHIFT(3);
>> +
>> +	return mpidr;
>> +}
>> +
>> +static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
>> +					    gpa_t addr, unsigned int len)
>> +{
>> +	int intid = (addr & 0x1fff) / 8;
>> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
>> +	unsigned long mpidr;
>> +
>> +	if (!irq)
>> +		return 0;
>> +
>> +	mpidr = decompress_mpidr(irq->mpidr);
> 
> I'm unsure here; do we ned a READ_ONCE() in lieu taking the lock or are
> we guaranteed that this is a single memory access even with compiler
> inlining etc.?

I can't imagine the compiler being stupid enough to read this multiple
times, but better safe than sorry. +1 for READ_ONCE().

> 
>> +	return extract_bytes(mpidr, addr & 7, len);
>> +}
>> +
>> +static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
>> +				    gpa_t addr, unsigned int len,
>> +				    unsigned long val)
>> +{
>> +	int intid = (addr & 0x1fff) / 8;
>> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
>> +	unsigned long mask = 0xffffffff;	/* upper word is WI */
>> +	u64 mpidr;
>> +
>> +	if (!irq)
>> +		return;
>> +
>> +	/*
>> +	 * There are only two supported options:
>> +	 * (1) aligned 64-bit access
>> +	 * (2) aligned 32-bit access
>> +	 *
>> +	 * TODO: make this check generic and move it to dispatch_...()
>> +	 */
>> +	if (len != 4 && len != 8)
>> +		return;
>> +
>> +
>> +	/* The upper word is WI for us since we don't implement Aff3. */
>> +	if (addr & 4)
>> +		return;
>> +
>> +	spin_lock(&irq->irq_lock);
>> +
>> +	mpidr = decompress_mpidr(irq->mpidr);
>> +	mpidr = (mpidr & ~mask) | (val & mask);
>> +	irq->mpidr = compress_mpidr(mpidr);
>> +	irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, mpidr);
> 
> this is weird because it doesn't preserve read-as-written semantics but
> allows a guest to write something into the RES0 field and read that back
> in the Aff3 field...

I don't see how we get this RES0/Aff3 mixup, but I can see other issues:

>> +	unsigned long mask = 0xffffffff;	/* upper word is WI */

followed by:

>> +	mpidr = (mpidr & ~mask) | (val & mask);

is not going to preserve the top bits on 32bit (assuming we could
perform a 64bit access on 32bit, but still). Also, the mask preserves
the IRM bit, which is wrong (we don't support 1-of-n distribution).

Why don't we just have

	mpidr = val & GENMASK_ULL(23, 0);

and let's be done with it? I must be missing something about this whole
Aff3 thing...

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From kernel at martin.sperl.org  Thu May 12 05:38:48 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu, 12 May 2016 12:38:48 +0000
Subject: [PATCH 0/4] add minimal bcm2835-sdram driver
Message-ID: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

As the sdram clock is a critical clock to the system
the minimal bcm2835-sdram driver claims (and enables)
this clock and also exposes the corresponding sdram
registers via debugfs.

Martin Sperl (4):
  dt: bindings: add bcm2835-memory-controller documentation
  memory: bcm2835: add bcm2835-memory controller
  ARM: dts: bcm2835: add the bcm2835-sdram-controller to the dt
  ARM: bcm2835_defconfig: add bcm2835-sdram controller

 .../memory-controllers/brcm,bcm2835-sdram.txt      |  16 +++
 arch/arm/boot/dts/bcm283x.dtsi                     |   6 +
 arch/arm/configs/bcm2835_defconfig                 |   1 +
 drivers/memory/Kconfig                             |   7 +
 drivers/memory/Makefile                            |   1 +
 drivers/memory/bcm2835-sdram.c                     | 152 +++++++++++++++++++++
 6 files changed, 183 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/brcm,bcm2835-sdram.txt
 create mode 100644 drivers/memory/bcm2835-sdram.c

--
2.1.4


From kernel at martin.sperl.org  Thu May 12 05:38:49 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu, 12 May 2016 12:38:49 +0000
Subject: [PATCH 1/4] dt: bindings: add bcm2835-memory-controller documentation
In-Reply-To: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463056732-5607-2-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add memory controller dt-binding documentation for the
bcm2835 soc.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 .../bindings/memory-controllers/brcm,bcm2835-sdram.txt   | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/brcm,bcm2835-sdram.txt

diff --git a/Documentation/devicetree/bindings/memory-controllers/brcm,bcm2835-sdram.txt b/Documentation/devicetree/bindings/memory-controllers/brcm,bcm2835-sdram.txt
new file mode 100644
index 0000000..d1cb151
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/brcm,bcm2835-sdram.txt
@@ -0,0 +1,16 @@
+Binding for SDRAM driver for BCM2835 SoCs.
+
+Required parameters:
+-------------------
+
+compatible : 	should be: "brcm,bcm2835-sdram"
+reg :		Address ranges of the ic1/ic2 registers.
+clocks : 	Phandle of the clock used by the sdram.
+
+Example:
+
+memory-conroller at 7e002000 {
+	compatible = "brcm,bcm2835-sdram";
+	reg = <0x7e002000 0x58>, <0x7e002800 0x58>;
+	clocks = <&clocks BCM2835_CLOCK_SDRAM>;
+};
-- 
2.1.4



From kernel at martin.sperl.org  Thu May 12 05:38:50 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu, 12 May 2016 12:38:50 +0000
Subject: [PATCH 2/4] memory: bcm2835: add bcm2835-memory controller
In-Reply-To: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463056732-5607-3-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add a memory-controller driver for the bcm2835 SOC.

This is mostly needed to claim the SDRAM clock
so that this (and the corresponding parent pll)
never gets disabled.

It also exposes the sdram registers via debugfs.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 drivers/memory/Kconfig         |   7 ++
 drivers/memory/Makefile        |   1 +
 drivers/memory/bcm2835-sdram.c | 152 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 160 insertions(+)
 create mode 100644 drivers/memory/bcm2835-sdram.c

diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 51d5cd2..a55cad3 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -25,6 +25,13 @@ config ATMEL_SDRAMC
 	  Starting with the at91sam9g45, this controller supports SDR, DDR and
 	  LP-DDR memories.
 
+config BCM2835_SDRAM
+	bool "Broadcom BCM2835 SDRAM Controller"
+	default y
+	depends on ARCH_BCM2835 || COMPILE_TEST
+	help
+	  This driver is for Broadcom BCM2835 SDRAM Controller.
+
 config TI_AEMIF
 	tristate "Texas Instruments AEMIF driver"
 	depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 890bdf4..1287b90 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_OF)		+= of_memory.o
 endif
 obj-$(CONFIG_ARM_PL172_MPMC)	+= pl172.o
 obj-$(CONFIG_ATMEL_SDRAMC)	+= atmel-sdramc.o
+obj-$(CONFIG_BCM2835_SDRAM)	+= bcm2835-sdram.o
 obj-$(CONFIG_TI_AEMIF)		+= ti-aemif.o
 obj-$(CONFIG_TI_EMIF)		+= emif.o
 obj-$(CONFIG_OMAP_GPMC)		+= omap-gpmc.o
diff --git a/drivers/memory/bcm2835-sdram.c b/drivers/memory/bcm2835-sdram.c
new file mode 100644
index 0000000..7c9c0ca
--- /dev/null
+++ b/drivers/memory/bcm2835-sdram.c
@@ -0,0 +1,152 @@
+/*
+ * Driver for Broadcom BCM2835 soc sdram controller
+ *
+ * Copyright (C) 2016 Martin Sperl
+ *
+ * inspired by: atmel-sdramc
+ *
+ * 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.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+struct bcm2835_sdram_data {
+	void __iomem *regs[2];
+	struct dentry *debugfsdir;
+	struct clk *clk;
+};
+
+#define R(n, o) { .name = n, .offset = o }
+static const struct debugfs_reg32 bcm2835_sdram_regs[] = {
+	R("c",			0x00),
+	R("s",			0x04),
+	R("src0",		0x08),
+	R("src1",		0x0c),
+	R("mask0",		0x10),
+	R("mask1",		0x14),
+	R("mask2",		0x18),
+	R("mask3",		0x1c),
+	R("mask4",		0x20),
+	R("mask5",		0x24),
+	R("mask6",		0x28),
+	R("mask7",		0x2c),
+	R("vaddr",		0x30),
+	R("wakeup",		0x34),
+	R("profile",		0x38),
+	/* 0x3c is not defined */
+	R("force0",		0x40),
+	R("force1",		0x44),
+	/* 0x48 to 0x54 are write only */
+};
+
+static void bcm2835_sdram_debugfs(struct platform_device *pdev)
+{
+	struct bcm2835_sdram_data *data = platform_get_drvdata(pdev);
+	struct debugfs_regset32 *regset;
+	char *name;
+	int i;
+
+	data->debugfsdir = debugfs_create_dir("bcm2835_sdram", NULL);
+	if (!data->debugfsdir)
+		return;
+
+	/* create the regsets */
+	for (i = 0; i < 2; i++) {
+		name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+				      "regset%d", i);
+		if (!name)
+			return;
+
+		regset = devm_kzalloc(&pdev->dev, sizeof(*regset),
+				      GFP_KERNEL);
+		if (!regset)
+			return;
+
+		regset->regs = bcm2835_sdram_regs;
+		regset->nregs = ARRAY_SIZE(bcm2835_sdram_regs);
+		regset->base = data->regs[i];
+
+		debugfs_create_regset32(name, S_IRUGO,
+					data->debugfsdir, regset);
+	}
+}
+
+static int bcm2835_sdram_probe(struct platform_device *pdev)
+{
+	struct bcm2835_sdram_data *data;
+	struct resource *res;
+	int err, i;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, data);
+
+	/* get registers */
+	for (i = 0; i < 2; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		data->regs[i] = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(data->regs[i])) {
+			err = PTR_ERR(data->regs[i]);
+			dev_err(&pdev->dev,
+				"Could not get register set %d: %d\n",
+				i, err);
+			return err;
+		}
+	}
+	/* get clock */
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+	clk_prepare_enable(data->clk);
+
+	bcm2835_sdram_debugfs(pdev);
+
+	return 0;
+}
+
+static int bcm2835_sdram_remove(struct platform_device *pdev)
+{
+	struct bcm2835_sdram_data *data = platform_get_drvdata(pdev);
+
+	debugfs_remove_recursive(data->debugfsdir);
+
+	return 0;
+}
+
+static const struct of_device_id bcm2835_sdram_of_match_table[] = {
+	{ .compatible = "brcm,bcm2835-sdram", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_sdram_of_match_table);
+
+static struct platform_driver bcm2835_sdram_driver = {
+	.probe = bcm2835_sdram_probe,
+	.remove = bcm2835_sdram_remove,
+	.driver = {
+		.name = "bcm2835_sdram",
+		.of_match_table = bcm2835_sdram_of_match_table,
+	},
+};
+module_platform_driver(bcm2835_sdram_driver);
+
+MODULE_AUTHOR("Martin Sperl");
+MODULE_DESCRIPTION("sdram driver for bcm2835 chip");
+MODULE_LICENSE("GPL");
-- 
2.1.4



From kernel at martin.sperl.org  Thu May 12 05:38:51 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu, 12 May 2016 12:38:51 +0000
Subject: [PATCH 3/4] ARM: dts: bcm2835: add the bcm2835-sdram-controller to
 the dt
In-Reply-To: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463056732-5607-4-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add the bcm2835 sdram controller to the device tree.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 arch/arm/boot/dts/bcm283x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index 8aaf193..9db9d97 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
+++ b/arch/arm/boot/dts/bcm283x.dtsi
@@ -22,6 +22,12 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 
+		memory-controller at 7e002000 {
+			compatible = "brcm,bcm2835-sdram";
+			reg = <0x7e002000 0x58>, <0x7e002800 0x58>;
+			clocks = <&clocks BCM2835_CLOCK_SDRAM>;
+		};
+
 		timer at 7e003000 {
 			compatible = "brcm,bcm2835-system-timer";
 			reg = <0x7e003000 0x1000>;
-- 
2.1.4



From kernel at martin.sperl.org  Thu May 12 05:38:52 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu, 12 May 2016 12:38:52 +0000
Subject: [PATCH 4/4] ARM: bcm2835_defconfig: add bcm2835-sdram controller
In-Reply-To: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463056732-5607-5-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add the bcm2835-sdram controller driver to the default config.
(as the driver is enabled by default vi KConfig, we only need
to enable CONFIG_MEMORY)

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 arch/arm/configs/bcm2835_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index 1ef69fc..29a44bd 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -107,6 +107,7 @@ CONFIG_MAILBOX=y
 CONFIG_BCM2835_MBOX=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_RASPBERRYPI_POWER=y
+CONFIG_MEMORY=y
 CONFIG_PWM=y
 CONFIG_PWM_BCM2835=y
 CONFIG_RASPBERRYPI_FIRMWARE=y
--
2.1.4


From christoffer.dall at linaro.org  Thu May 12 05:40:15 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 14:40:15 +0200
Subject: [PATCH v3 37/55] KVM: arm/arm64: vgic-new: Add GICv3 SGI system
 register trap handler
In-Reply-To: <1462531568-9799-38-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-38-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512124015.GI27623@cbox>

On Fri, May 06, 2016 at 11:45:50AM +0100, Andre Przywara wrote:
> In contrast to GICv2 SGIs in a GICv3 implementation are not triggered
> by a MMIO write, but with a system register write. KVM knows about
> that register already, we just need to implement the handler and wire
> it up to the core KVM/ARM code.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - add comment about SGI_AFFINITY_LEVEL macro
> 
>  include/kvm/vgic/vgic.h          |   8 +++
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 106 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 114 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 4ec1270..2c43eb8 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -209,6 +209,14 @@ bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
>  void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
>  void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
>  
> +#ifdef CONFIG_KVM_ARM_VGIC_V3
> +void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
> +#else
> +static inline void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
> +{
> +}
> +#endif
> +
>  /**
>   * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
>   *
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index 3bcc2c4..af12592 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -356,3 +356,109 @@ int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
>  
>  	return ret;
>  }
> +
> +/*
> + * Compare a given affinity (level 1-3 and a level 0 mask, from the SGI
> + * generation register ICC_SGI1R_EL1) with a given VCPU.
> + * If the VCPU's MPIDR matches, return the level0 affinity, otherwise
> + * return -1.
> + */
> +static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct kvm_vcpu *vcpu)
> +{
> +	unsigned long affinity;
> +	int level0;
> +
> +	/*
> +	 * Split the current VCPU's MPIDR into affinity level 0 and the
> +	 * rest as this is what we have to compare against.
> +	 */
> +	affinity = kvm_vcpu_get_mpidr_aff(vcpu);
> +	level0 = MPIDR_AFFINITY_LEVEL(affinity, 0);
> +	affinity &= ~MPIDR_LEVEL_MASK;
> +
> +	/* bail out if the upper three levels don't match */
> +	if (sgi_aff != affinity)
> +		return -1;
> +
> +	/* Is this VCPU's bit set in the mask ? */
> +	if (!(sgi_cpu_mask & BIT(level0)))
> +		return -1;
> +
> +	return level0;
> +}
> +
> +/*
> + * The ICC_SGI* registers encode the affinity differently from the MPIDR,
> + * so provide a wrapper to use the existing defines to isolate a certain
> + * affinity level.
> + */
> +#define SGI_AFFINITY_LEVEL(reg, level) \
> +	((((reg) & ICC_SGI1R_AFFINITY_## level ##_MASK) \
> +	>> ICC_SGI1R_AFFINITY_## level ##_SHIFT) << MPIDR_LEVEL_SHIFT(level))

Do we really prefer this over (untested):

	static inline u64 decode_sgi_affinity(u64 reg)
	{
		u64 aff1, aff2, aff3;

		aff1 = (reg & ICC_SGI1R_AFFINITY_1_MASK) >> ICC_SGI1R_AFFINITY_1_SHIFT;
		aff2 = (reg & ICC_SGI1R_AFFINITY_2_MASK) >> ICC_SGI1R_AFFINITY_2_SHIFT;
		aff3 = (reg & ICC_SGI1R_AFFINITY_3_MASK) >> ICC_SGI1R_AFFINITY_3_SHIFT;

		return (aff1 << MPIDR_LEVEL_SHIFT(1)) |
		       (aff2 << MPIDR_LEVEL_SHIFT(2)) |
		       (aff3 << MPIDR_LEVEL_SHIFT(3));
	}

> +
> +/**
> + * vgic_v3_dispatch_sgi - handle SGI requests from VCPUs
> + * @vcpu: The VCPU requesting a SGI
> + * @reg: The value written into the ICC_SGI1R_EL1 register by that VCPU
> + *
> + * With GICv3 (and ARE=1) CPUs trigger SGIs by writing to a system register.
> + * This will trap in sys_regs.c and call this function.
> + * This ICC_SGI1R_EL1 register contains the upper three affinity levels of the
> + * target processors as well as a bitmask of 16 Aff0 CPUs.
> + * If the interrupt routing mode bit is not set, we iterate over all VCPUs to
> + * check for matching ones. If this bit is set, we signal all, but not the
> + * calling VCPU.
> + */
> +void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
> +{
> +	struct kvm *kvm = vcpu->kvm;
> +	struct kvm_vcpu *c_vcpu;
> +	u16 target_cpus;
> +	u64 mpidr;
> +	int sgi, c;
> +	int vcpu_id = vcpu->vcpu_id;
> +	bool broadcast;
> +
> +	sgi = (reg & ICC_SGI1R_SGI_ID_MASK) >> ICC_SGI1R_SGI_ID_SHIFT;
> +	broadcast = reg & BIT(ICC_SGI1R_IRQ_ROUTING_MODE_BIT);
> +	target_cpus = (reg & ICC_SGI1R_TARGET_LIST_MASK) >> ICC_SGI1R_TARGET_LIST_SHIFT;
> +	mpidr = SGI_AFFINITY_LEVEL(reg, 3);
> +	mpidr |= SGI_AFFINITY_LEVEL(reg, 2);
> +	mpidr |= SGI_AFFINITY_LEVEL(reg, 1);
> +
> +	/*
> +	 * We iterate over all VCPUs to find the MPIDRs matching the request.
> +	 * If we have handled one CPU, we clear its bit to detect early
> +	 * if we are already finished. This avoids iterating through all
> +	 * VCPUs when most of the times we just signal a single VCPU.
> +	 */
> +	kvm_for_each_vcpu(c, c_vcpu, kvm) {
> +		struct vgic_irq *irq;
> +
> +		/* Exit early if we have dealt with all requested CPUs */
> +		if (!broadcast && target_cpus == 0)
> +			break;
> +
> +		/* Don't signal the calling VCPU */
> +		if (broadcast && c == vcpu_id)
> +			continue;
> +
> +		if (!broadcast) {
> +			int level0;
> +
> +			level0 = match_mpidr(mpidr, target_cpus, c_vcpu);
> +			if (level0 == -1)
> +				continue;
> +
> +			/* remove this matching VCPU from the mask */
> +			target_cpus &= ~BIT(level0);
> +		}
> +
> +		irq = vgic_get_irq(vcpu->kvm, c_vcpu, sgi);
> +
> +		spin_lock(&irq->irq_lock);
> +		irq->pending = true;
> +
> +		vgic_queue_irq_unlock(vcpu->kvm, irq);
> +	}
> +}
> -- 
> 2.7.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

otherwise:

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From honghui.zhang at mediatek.com  Thu May 12 05:41:24 2016
From: honghui.zhang at mediatek.com (Honghui Zhang)
Date: Thu, 12 May 2016 20:41:24 +0800
Subject: [PATCH 4/5] iommu/mediatek: add support for mtk iommu
 generation one HW
In-Reply-To: <5731B7D8.8040304@arm.com>
References: <1462780816-5288-1-git-send-email-honghui.zhang@mediatek.com>
 <1462780816-5288-5-git-send-email-honghui.zhang@mediatek.com>
 <5731B7D8.8040304@arm.com>
Message-ID: <1463056884.29375.7.camel@mtksdaap41>

Hi, Robin, Thanks very much for your comment, and sorry for the last
reply format.

On Tue, 2016-05-10 at 11:28 +0100, Robin Murphy wrote:
> On 09/05/16 09:00, honghui.zhang at mediatek.com wrote:
> [...]
> > +static void *mtk_iommu_alloc_pgt(struct device *dev, size_t size, gfp_t gfp)
> > +{
> > +	dma_addr_t dma;
> > +	void *pages = alloc_pages_exact(size, gfp | __GFP_ZERO);
> > +
> > +	if (!pages)
> > +		return NULL;
> > +
> > +	dma = dma_map_single(dev, pages, size, DMA_TO_DEVICE);
> > +	if (dma_mapping_error(dev, dma))
> > +		goto out_free;
> > +	/*
> > +	 * We depend on the IOMMU being able to work with any physical
> > +	 * address directly, so if the DMA layer suggests otherwise by
> > +	 * translating or truncating them, that bodes very badly...
> > +	 */
> > +	if (dma != virt_to_phys(pages))
> > +		goto out_unmap;
> 
> Given that you've only got a single table to allocate, and at 4MB it has 
> a fair chance of failing beyond early boot time, just use 
> dma_alloc_coherent() - you don't need to care about the dma <-> phys 
> relationship because you don't have multi-level tables to walk. That 
> way, you can get rid of all the awkward streaming DMA stuff, and also 
> benefit from CMA to avoid allocation failures.
> 

The dma_alloc_coheret interface is good enough for me, thanks.

> > +	kmemleak_ignore(pages);
> > +	return pages;
> > +
> > +out_unmap:
> > +	dev_err(dev, "Cannot accommodate DMA translation for IOMMU page tables\n");
> > +	dma_unmap_single(dev, dma, size, DMA_TO_DEVICE);
> > +out_free:
> > +	free_pages_exact(pages, size);
> > +	return NULL;
> > +
> > +}
> > +
> > +static void mtk_iommu_free_pgt(struct device *dev, void *pages, size_t size)
> > +{
> > +	dma_unmap_single(dev, (dma_addr_t)virt_to_phys(pages),
> > +			 size, DMA_TO_DEVICE);
> > +	free_pages_exact(pages, size);
> > +}
> > +
> > +static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data)
> > +{
> > +	struct mtk_iommu_domain *dom = data->m4u_dom;
> > +
> > +	spin_lock_init(&dom->pgtlock);
> > +
> > +	dom->pgt_va = mtk_iommu_alloc_pgt(data->dev,
> > +				dom->pgt_size, GFP_KERNEL);
> > +	if (!dom->pgt_va)
> > +		return -ENOMEM;
> > +
> > +	dom->pgt_pa = virt_to_phys(dom->pgt_va);
> > +
> > +	writel(dom->pgt_pa, data->base + REG_MMU_PT_BASE_ADDR);
> > +
> > +	dom->cookie = (void *)data;
> > +
> > +	return 0;
> > +}
> > +
> > +static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type)
> > +{
> > +	struct mtk_iommu_domain *dom;
> > +
> > +	if (type != IOMMU_DOMAIN_UNMANAGED)
> > +		return NULL;
> > +
> > +	dom = kzalloc(sizeof(*dom), GFP_KERNEL);
> > +	if (!dom)
> > +		return NULL;
> > +
> > +	/*
> > +	 * MTK m4u support 4GB iova address space, and oly support 4K page
> > +	 * mapping. So the pagetable size should be exactly as 4M.
> > +	 */
> > +	dom->pgt_size = SZ_4M;
> 
> If the table size is fixed, then why bother having a variable at all?

I will follow your advise for next version.
thanks.
> 
> > +	return &dom->domain;
> > +}
> > +
> > +static void mtk_iommu_domain_free(struct iommu_domain *domain)
> > +{
> > +	kfree(to_mtk_domain(domain));
> > +}
> > +
> 
> [...]
> 
> > +static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
> > +			 phys_addr_t paddr, size_t size, int prot)
> > +{
> > +	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
> > +	struct mtk_iommu_data *data = dom->cookie;
> > +	unsigned int page_num = size >> MTK_IOMMU_PAGE_SHIFT;
> 
> Since you only advertise a single page size, this will always be 1, so 
> you could either get rid of the loop here...

I would prefer your following advise to modify the pgsize_bitmap, thanks
very much.

> 
> > +	unsigned long flags;
> > +	unsigned int i;
> > +	u32 *pgt_base_iova;
> > +	u32 pabase = (u32)paddr;
> > +	int map_size = 0;
> > +
> > +	spin_lock_irqsave(&dom->pgtlock, flags);
> > +	pgt_base_iova = dom->pgt_va + (iova  >> MTK_IOMMU_PAGE_SHIFT);
> > +	for (i = 0; i < page_num; i++) {
> > +		pgt_base_iova[i] = pabase | F_DESC_VALID | F_DESC_NONSEC;
> > +		pabase += MTK_IOMMU_PAGE_SIZE;
> > +		map_size += MTK_IOMMU_PAGE_SIZE;
> > +	}
> > +	dma_sync_single_for_device(data->dev,
> > +			dom->pgt_pa + (iova >> MTK_IOMMU_PAGE_SHIFT),
> > +			(size >> MTK_IOMMU_PAGE_SHIFT) * sizeof(u32),
> > +			DMA_TO_DEVICE);
> > +	spin_unlock_irqrestore(&dom->pgtlock, flags);
> > +
> > +	mtk_iommu_tlb_flush_range(data, iova, size);
> > +
> > +	return map_size;
> > +}
> 
> [...]
> 
> > +static struct iommu_ops mtk_iommu_ops = {
> > +	.domain_alloc	= mtk_iommu_domain_alloc,
> > +	.domain_free	= mtk_iommu_domain_free,
> > +	.attach_dev	= mtk_iommu_attach_device,
> > +	.detach_dev	= mtk_iommu_detach_device,
> > +	.map		= mtk_iommu_map,
> > +	.unmap		= mtk_iommu_unmap,
> > +	.map_sg		= default_iommu_map_sg,
> > +	.iova_to_phys	= mtk_iommu_iova_to_phys,
> > +	.add_device	= mtk_iommu_add_device,
> > +	.remove_device	= mtk_iommu_remove_device,
> > +	.device_group	= mtk_iommu_device_group,
> > +	.pgsize_bitmap	= MTK_IOMMU_PAGE_SIZE,
> > +};
> 
> ...or perhaps advertise .pgsize_bitmap = ~0UL << MTK_IOMMU_PAGE_SHIFT 
> here, so you actually can handle multiple entries at once for larger 
> mappings - given how simple the page table format is that doesn't seem 
> too unreasonable, especially since it should give you a big efficiency 
> win in terms of TLB maintenance.
> 
> Robin.
> 




From lars at metafoo.de  Thu May 12 05:43:08 2016
From: lars at metafoo.de (Lars-Peter Clausen)
Date: Thu, 12 May 2016 14:43:08 +0200
Subject: [PATCH v8 1/2] Documentation: DT: dma: Add Xilinx zynqmp dma
 device tree binding documentation
In-Reply-To: <1463056164-3210-1-git-send-email-appanad@xilinx.com>
References: <1463056164-3210-1-git-send-email-appanad@xilinx.com>
Message-ID: <57347A5C.1080606@metafoo.de>

On 05/12/2016 02:29 PM, Kedareswara rao Appana wrote:
[...]
> +- xlnx,include-sg	: Indicates the controller to operate in simple or
> +			  scatter gather dma mode

This is also a software runtime configuration parameter.



From bamvor.zhangjian at huawei.com  Thu May 12 05:49:24 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Thu, 12 May 2016 20:49:24 +0800
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <2733875.IzutTZKHMc@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <4989778.Fs81NJurjH@wuerfel>
 <20160512091758.GB11226@e104818-lin.cambridge.arm.com>
 <2733875.IzutTZKHMc@wuerfel>
Message-ID: <57347BD4.8010105@huawei.com>

Hi,

On 2016/5/12 17:21, Arnd Bergmann wrote:
> On Thursday 12 May 2016 10:17:58 Catalin Marinas wrote:
>> On Wed, May 11, 2016 at 09:30:07PM +0200, Arnd Bergmann wrote:
>>> On Wednesday 11 May 2016 17:59:01 Catalin Marinas wrote:
>>>
>>> I don't think the shifts are a problem, the main downside would be
>>> the limit to 44 bits of file offsets (16TB files), but it's also
>>> unclear if that is a practical problem at all. If it is, we run
>>> into the same problem on all other 32-bit architectures too.
>>
>> I hope people are seriously thinking of moving to an LP64 ABI if they
>> have such large file offset needs.
>
> Good point. 44 bits of file size is certainly enough for mmap()
> on a 32-bit task: you would only be able to map a very small fraction
> of the file anyway, and if you want to map larger files, and should
> move to 64-bit tasks long before this becomes a limitation.
Hi,

I apply the following patch in order to make use of the REAL mmmap2. LTP
test pass in litle endian. mmap16 successful with segfault in big endian.

BTW, I saw the similar code in tile, mips, microblaze and s390 compat. Should
we merge these code into a common syscall wrapper?

kernel:
diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
index d85fe94..2cd72eb 100644
--- a/arch/arm64/kernel/sys_ilp32.c
+++ b/arch/arm64/kernel/sys_ilp32.c
@@ -41,7 +41,16 @@
  #define compat_sys_sync_file_range     sys_sync_file_range
  #define compat_sys_truncate64          sys_truncate
  #define sys_llseek                     sys_lseek
-#define sys_mmap2                     sys_mmap
+
+SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
+       unsigned long, prot, unsigned long, flags, unsigned long, fd,
+       unsigned long, pgoff)
+{
+       if (pgoff & (~PAGE_MASK >> 12))
+               return -EINVAL;
+
+       return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12));
+}

  asmlinkage long ilp32_sys_rt_sigreturn_wrapper(void);
  #define compat_sys_rt_sigreturn        ilp32_sys_rt_sigreturn_wrapper

glibc:
diff --git a/sysdeps/unix/sysv/linux/aarch64/ilp32/mmap.c b/sysdeps/unix/sysv/linux/aarch64/ilp32/mmap.c
index e69de29..f75e251 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ilp32/mmap.c
+++ b/sysdeps/unix/sysv/linux/aarch64/ilp32/mmap.c
@@ -0,0 +1,2 @@
+#include <sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c>
+
diff --git a/sysdeps/unix/sysv/linux/aarch64/ilp32/mmap64.c b/sysdeps/unix/sysv/linux/aarch64/ilp32/mmap64.c
index c6c7f1d..6f1a141 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ilp32/mmap64.c
+++ b/sysdeps/unix/sysv/linux/aarch64/ilp32/mmap64.c
@@ -1,29 +1 @@
-#include <errno.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <string.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-
-/* mmap is provided by mmap as they are the same. */
-void *__mmap (void *__addr, size_t __len, int __prot,
-                    int __flags, int __fd, __off_t __offset)
-{
-   void *result;
-   result = (void *) INLINE_SYSCALL (mmap2, 6, __addr, __len, __prot, __flags,
-   return result;
-}
-/* mmap64 is provided by mmap as they are the same. */
-void *__mmap64 (void *__addr, size_t __len, int __prot,
-                    int __flags, int __fd, __off64_t __offset)
-{
-   void *result;
-   result = (void *)
-     INLINE_SYSCALL (mmap2, 6, __addr,
-                     __len, __prot, __flags, __fd, __offset);
-   return result;
-}
-weak_alias (__mmap, mmap)
-weak_alias (__mmap64, mmap64)
+#include <sysdeps/unix/sysv/linux/mmap64.c>

Regards

Bamvor
> 	Arnd
>



From m.szyprowski at samsung.com  Thu May 12 05:52:59 2016
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Thu, 12 May 2016 14:52:59 +0200
Subject: [RFC 0/9] IOMMU probe deferral support
In-Reply-To: <1461599894-1969-1-git-send-email-sricharan@codeaurora.org>
References: <1461599894-1969-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <f192d4a0-9e13-4ae2-d3da-058e2e092634@samsung.com>

Hello,


On 2016-04-25 17:58, Sricharan R wrote:
> This is mostly a repost of the probe deferral series from
> Laurent Pinchart [1]. Added a check to fix boot with ACPI.
> Adapted arm-smmu driver to work with deferred probing and added
> a new api for the below reason. This is based on the generic iommu binding
> series from Robin Murphy <robin.murphy at arm.com>.

Thanks for this patchset. I'm working on some serious rework in exynos power
domains and clocks support code and it turned out that I need this feature
to resolve probing order. It works fine on my internal tree, where some
iommu controllers cannot get their clocks early enough.

Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>

> Now associating a group with an master has become mandatory and happens
> when the master is added to the bus using BUS_ADD_DEVICE from iommu core.
> But the iommu has to be ready before this using early iommu registration
> and also master should have been added to the iommu using xlate. So, when
> trying to get rid of the early registration and using late probing for iommu
> devices to sort out the probing order, the newly added api is meant to be
> called during the late probing to add the master to the iommu. add_iommu_group
> could be modified to do the same though.
>
> The one issue here is the DRIVER_BIND notifier from iommu core
> might be called at a wrong point since the addition of a group to the device
> happens after this.
>
> Will be good to know the right direction to proceed on this fully.
>
> [1] http://lists.linuxfoundation.org/pipermail/iommu/2015-May/013016.html
>
> Laurent Pinchart (6):
>    arm: dma-mapping: Don't override dma_ops in arch_setup_dma_ops()
>    of: dma: Move range size workaround to of_dma_get_range()
>    of: dma: Make of_dma_deconfigure() public
>    of: dma: Split of_configure_dma() into mask and ops configuration
>    drivers: platform: Configure dma operations at probe time
>    iommu: of: Handle IOMMU lookup failure with deferred probing or error
>
> Sricharan R (3):
>    drivers: iommu: Add a new add device api
>    drivers: of: call iommu_bus_add_dev after iommu_configure_ops
>    drivers: iommu: arm-smmu: Set iommu_ops in probe
>
>   arch/arm/mm/dma-mapping.c |  9 ++++++
>   drivers/base/platform.c   | 13 ++++++++
>   drivers/iommu/arm-smmu.c  | 34 ++------------------
>   drivers/iommu/iommu.c     | 12 +++++++
>   drivers/iommu/of_iommu.c  | 16 ++++++++--
>   drivers/of/address.c      | 20 ++++++++++--
>   drivers/of/device.c       | 81 +++++++++++++++++++++++++++++++----------------
>   drivers/of/platform.c     | 16 ++++------
>   drivers/pci/probe.c       |  3 +-
>   include/linux/iommu.h     |  1 +
>   include/linux/of_device.h | 14 ++++++--
>   11 files changed, 141 insertions(+), 78 deletions(-)
>

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



From bamvor.zhangjian at huawei.com  Thu May 12 05:52:46 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Thu, 12 May 2016 20:52:46 +0800
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <20160512082427.GA1587@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <573305A8.50406@huawei.com> <5733149C.4030903@huawei.com>
 <5250356.myv9GIZ34h@wuerfel> <5733FC71.8070101@huawei.com>
 <20160512082427.GA1587@yury-N73SV>
Message-ID: <57347C9E.7010708@huawei.com>

Hi,

On 2016/5/12 16:24, Yury Norov wrote:
> On Thu, May 12, 2016 at 11:45:53AM +0800, Zhangjian (Bamvor) wrote:
>
> [...]
>
>>> Hmm, that is indeed tricky. I think COMPAT_SYSCALL_WRAP4 rightfully
>>> refuses the loff_t argument here, as the common case is that this is
>>> not possible.
>> It works if I apply the following patch, I defined the wrong `__TYPE_IS_xxx`
>> yesterday. Should we merge this into ILP32 series or send the compat.h
>> and syscalls.h individually? The current series of ILP32 is a little bit
>> long and hard to review.
>> diff --git a/include/linux/compat.h b/include/linux/compat.h
>> index ba6ebe0..22a9565 100644
>> --- a/include/linux/compat.h
>> +++ b/include/linux/compat.h
>> @@ -747,7 +747,8 @@ asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32,
>>   #ifndef __SC_COMPAT_CAST
>>   #define __SC_COMPAT_CAST(t, a) ({                                      \
>>          BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) &&              \
>> -                    !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t));            \
>> +                    !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t) &&           \
>> +                    !__TYPE_IS_LOFFT(t));                              \
>
> I think it's wrong, as loff_t is 64-bit in 32-bit userspace, and this
> will clear meaningful data in top halve.
Yes. It is my fault. The original thoughts is clear the up 32bit for size_t.
How should we skip the loff_t?

Regards

Bamvor



From rafael at kernel.org  Thu May 12 05:54:35 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Thu, 12 May 2016 14:54:35 +0200
Subject: [PATCH v6 00/14] ACPI NUMA support for ARM64
In-Reply-To: <20160512085616.GA25355@arm.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <CAJZ5v0iMDQ4pWip4vyCos0o+1DFDvXQf4XZQqC4SGjJsDO4Lnw@mail.gmail.com>
 <20160511104032.GA31374@arm.com>
 <CAJZ5v0gQMR7OUyZo5Sa3bgMYZBzdnwFaktz9JCv1ocWXw7yHTg@mail.gmail.com>
 <57339F39.3040603@caviumnetworks.com>
 <CAJZ5v0h8zBEZ2nLLdk62r7uqHizUfVWamUVEriBGe1XBE6462Q@mail.gmail.com>
 <5733A47B.8030908@caviumnetworks.com>
 <CAJZ5v0gBTANFntBSkyaRtt-BKOMC+pz_R9CwM6wKnp=Ni1dPFA@mail.gmail.com>
 <20160512085616.GA25355@arm.com>
Message-ID: <CAJZ5v0iVf-+ngd-qDUk8Acf7mGrq0f8j2d_QtfxQxuBH_93t3w@mail.gmail.com>

On Thu, May 12, 2016 at 10:56 AM, Will Deacon <will.deacon at arm.com> wrote:
> On Thu, May 12, 2016 at 12:29:02AM +0200, Rafael J. Wysocki wrote:
>> On Wed, May 11, 2016 at 11:30 PM, David Daney <ddaney at caviumnetworks.com> wrote:
>> > On 05/11/2016 02:22 PM, Rafael J. Wysocki wrote:
>> >> On Wed, May 11, 2016 at 11:08 PM, David Daney <ddaney at caviumnetworks.com>
>> >> wrote:
>> >>> On 05/11/2016 01:35 PM, Rafael J. Wysocki wrote:
>> >>>> On Wed, May 11, 2016 at 12:40 PM, Will Deacon <will.deacon at arm.com>
>> >>>> wrote:
>> >>>>> On Wed, May 11, 2016 at 02:43:11AM +0200, Rafael J. Wysocki wrote:
>> >>>>> There's also a dependency on the arm64 for-next/core branch, so I've
>> >>>>> been
>> >>>>> largely ignoring this as far as 4.6 is concerned and was planning to
>> >>>>> take
>> >>>>> a proper look for 4.7 once the upcoming merge window is out of the way.
>> >>>>
>> >>>>
>> >>>>
>> >>>> That would be 4.7 and 4.8 respectively I suppose?
>
> Argh, yes, of course! :)
>
>> >>>>
>> >>>> Anyway, Catalin has ACKed all of them except for the [13/14], so
>> >>>> technically I can apply [1-12/14] now and then [13-14/14] can be
>> >>>> applied when they are ready.
>> >>>>
>> >>>> Do you think there will be any problems with merging [6-7/14] into 4.7
>> >>>> via the ACPI tree?
>> >>>>
>> >>>
>> >>> I would defer to the arm64 maintainers for decisions about the arm64
>> >>> specific parts of the patch set.  That said, many of the arm64 specific
>> >>> patches depend on the arm64 for-next/core branch, so you would have to be
>> >>> careful about merge ordering if you pull these in before the
>> >>> for-next/core
>> >>> branch is merged.
>> >>
>> >>
>> >> Fair enough.  I will wait for an update then.
>> >>
>> >>> Also FWIW, I plan on addressing Catalin's comments about 13/14 and
>> >>> posting a
>> >>> new version of the patch set in the next day or two.
>> >>
>> >>
>> >> OK, but in that case it won't be considered for 4.7 (at least not by
>> >> me), so I'd suggest sending it in the second half of the 4.7 merge
>> >> window (or about that time).
>> >
>> >
>> > To be candid, I would very much like for you to pull in as many of the
>> > patches as you are comfortable with as soon as possible.
>> >
>> > I don't know where Will and Catalin stand on this, and their opinion is
>> > obviously important, but getting 1-12/14 merged to v4.7 and deferring the
>> > last two for v4.8 would simplify the whole process for me.  The drawback is
>> > carrying dead code around until the final parts are merged.
>>
>> That is not unheard of, however.
>>
>> OK, I'll try to put the [1-12/14] into my linux-next branch early next
>> week and we'll see if that triggers any conflicts.
>
> I'd really much rather this waited until after the merge window.

That's fine by me, so I guess my previous request for the next version
to be sent by the end of the merge window applies. :-)

> My understanding is that it's bad practice to put stuff into -next during the
> merge window,

Unless you want to push that stuff to Linus during the merge window in
progress, that is.

> and you'd end up having to send a pull based on a random
> commit (the arm64 pull request?) in the second half. On top of that, this
> series would get very little exposure in -next during that time.
>
> On the other hand, putting this into linux-next after the merge window
> gives us time for testing, allows David to rework patch 13 (which is aiming
> for 4.8 anyway iiuc) and avoids merge window churn.

OK


From ynorov at caviumnetworks.com  Thu May 12 05:59:09 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 12 May 2016 15:59:09 +0300
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <57347C9E.7010708@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <573305A8.50406@huawei.com> <5733149C.4030903@huawei.com>
 <5250356.myv9GIZ34h@wuerfel> <5733FC71.8070101@huawei.com>
 <20160512082427.GA1587@yury-N73SV> <57347C9E.7010708@huawei.com>
Message-ID: <20160512125909.GA29077@yury-N73SV>

On Thu, May 12, 2016 at 08:52:46PM +0800, Zhangjian (Bamvor) wrote:
> Hi,
> 
> On 2016/5/12 16:24, Yury Norov wrote:
> >On Thu, May 12, 2016 at 11:45:53AM +0800, Zhangjian (Bamvor) wrote:
> >
> >[...]
> >
> >>>Hmm, that is indeed tricky. I think COMPAT_SYSCALL_WRAP4 rightfully
> >>>refuses the loff_t argument here, as the common case is that this is
> >>>not possible.
> >>It works if I apply the following patch, I defined the wrong `__TYPE_IS_xxx`
> >>yesterday. Should we merge this into ILP32 series or send the compat.h
> >>and syscalls.h individually? The current series of ILP32 is a little bit
> >>long and hard to review.
> >>diff --git a/include/linux/compat.h b/include/linux/compat.h
> >>index ba6ebe0..22a9565 100644
> >>--- a/include/linux/compat.h
> >>+++ b/include/linux/compat.h
> >>@@ -747,7 +747,8 @@ asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32,
> >>  #ifndef __SC_COMPAT_CAST
> >>  #define __SC_COMPAT_CAST(t, a) ({                                      \
> >>         BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) &&              \
> >>-                    !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t));            \
> >>+                    !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t) &&           \
> >>+                    !__TYPE_IS_LOFFT(t));                              \
> >
> >I think it's wrong, as loff_t is 64-bit in 32-bit userspace, and this
> >will clear meaningful data in top halve.
> Yes. It is my fault. The original thoughts is clear the up 32bit for size_t.
> How should we skip the loff_t?
> 
> Regards
> 
> Bamvor

I already suggested:

For cases like this I think we should write wrappers by hands. In
unistd.h we can use __SC_WRAP, so they will work like wrappers
generated by COMPAT_SYSCALL_WRAPx()

Do you see any downsides?


From chunkeey at googlemail.com  Thu May 12 06:07:06 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Thu, 12 May 2016 15:07:06 +0200
Subject: [PATCH v9 2/2] gpio: move clps711x, moxart,
 ts4800 and gpio-ge into gpio-mmio
In-Reply-To: <3c67e0ca-43eb-4a77-90ef-f8e2757c8edd@gmail.com>
References: <cover.1462911225.git.chunkeey@googlemail.com>
 <85c74586dbd0023306f012764b85d6aa168b4ae7.1462911225.git.chunkeey@googlemail.com>
 <3c67e0ca-43eb-4a77-90ef-f8e2757c8edd@gmail.com>
Message-ID: <1626318.aFfl1tphqe@debian64>

On Thursday, May 12, 2016 07:30:05 PM Alexandre Courbot wrote:
> On Wednesday, May 11, 2016 6:34:35 PM JST, Christian Lamparter wrote:
> > This patch integrates the GPIO drivers for the following
> > boards, SoCs, etc. into gpio-mmio:
> >  - CLPS711X SoCs
> >  - MOXA ART SoC
> >  - TS-4800 FPGA DIO blocks and compatibles
> >  - GPIO controllers found on some GE Single Board Computers
> >
> > Cc: Alexander Shiyan <shc_work at mail.ru>
> > Cc: Julien Grossholtz <julien.grossholtz at savoirfairelinux.com>
> > Cc: Martyn Welch <martyn.welch at ge.com>
> > Cc: Jonas Jensen <jonas.jensen at gmail.com>
> > Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
> > ---
[...]
> > diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
> > index f72e40e..1de9172 100644
> > --- a/drivers/gpio/gpio-mmio.c
> > +++ b/drivers/gpio/gpio-mmio.c
> > @@ -586,8 +586,220 @@ static int 
> > bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
> >  	return 0;
> >  }
> >  
> > +static int clps711x_parse_dt(struct platform_device *pdev,
> > +			     struct bgpio_pdata *pdata,
> > +			     unsigned long *flags)
> > +{
> > +	struct device_node *np = pdev->dev.of_node;
> > +	struct resource *res;
> > +	const char *dir_reg_name;
> > +	int id = np ? of_alias_get_id(np, "gpio") : pdev->id;
> > +
> > +	switch (id) {
> > +	case 0:
> > +	case 1:
> > +	case 2:
> > +		pdata->ngpio = 0; /* determined by register width */
> > +		dir_reg_name = "dirout";
> > +		break;
> > +	case 3:
> > +		pdata->ngpio = 0; /* determined by register width */
> > +		/* PORTD is inverted logic for direction register */
> > +		dir_reg_name = "dirin";
> > +		break;
> > +	case 4:
> > +		pdata->ngpio = 3; /* PORTE is 3 lines only */
> > +		dir_reg_name = "dirout";
> > +		break;
> > +	default:
> > +		return -ENODEV;
> > +	}
> > +
> > +	pdata->base = id * 8;
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	if (!res)
> > +		return -EINVAL;
> > +	if (!res->name || strcmp("dat", res->name))
> > +		res->name = devm_kstrdup(&pdev->dev, "dat", GFP_KERNEL);
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> > +	if (!res)
> > +		return -EINVAL;
> > +	if (!res->name || strcmp(dir_reg_name, res->name))
> > +		res->name = devm_kstrdup(&pdev->dev, dir_reg_name, GFP_KERNEL);
> 
> Ouch, I don't like this. Also the probability that the "if (!res->name || 
> ...)" condition is not met is so small that I would not bother with it and 
> do the kstrdup unconditionally. But maybe we can remove this altogether - 
> see below...

The !res->name check is simply there because the kernel's strcmp doesn't
check for NULL... the res->name will be coming from the device tree.
Yes it should always be initialized but again: it's not within the functions 
control so it better be prepared for it. The "dir_reg_name" is part of the
function so we can guarantee that it's not NULL or a invalid string. 

About the leakage: I use devm_kstrdup unlike the dump strdup, it does bind
the dupped string to the device. This way the resource is not leaked even
if the module is loaded and unloaded, it stays with the device. (Until
it is destroyed).
 
Note: The strcmp is there to check if resource name was already updated
so even if the module was loaded multiple times it will dup the string
just once.

Doing a direct assignment like I did in the earlier versions would lead
to issues since the device resources are part of the the device and not
with the driver module.

> > +/*
> > + * bgpio_init() needs up to five named mmio register resources.
> > + * These currently are dat, set, clr, [dirout | dirin]. There
> > + * is no particular order or predefined place for the entries.
> > + * However, dirout and dirin are mutually exclusive.
> > + */
> > +#define __NUM_COMPAT_OVERRIDE_MMIO_RESOURCES 4
> > +
> > +struct compat_gpio_device_data {
> > +	unsigned int expected_resource_size;
> > +	unsigned int ngpio;
> > +	resource_size_t register_width;
> > +	unsigned long flags;
> > +	int (*call_back)(struct platform_device *pdev,
> > +			 struct bgpio_pdata *pdata,
> > +			 unsigned long *flags);
> > +	struct resource_replacement {
> > +		resource_size_t start_offset;
> > +		const char *name;
> > +	} resources[__NUM_COMPAT_OVERRIDE_MMIO_RESOURCES];
> > +};
> > +#undef __NUM_COMPAT_OVERRIDE_MMIO_RESOURCES
> > +
> > +#define ADD_COMPAT_REGISTER(_name, _offset)	\
> > +	{ .name = (_name), .start_offset = (_offset) }
> > +
> > +#define ADD_COMPAT_GPIO(_comp, _sz, _ngpio, _width, _cb, _f, _res...)	\
> > +	{								\
> > +	  .compatible = (_comp),					\
> > +	  .data = &(struct compat_gpio_device_data) {			\
> > +		.expected_resource_size = (_sz),			\
> > +		.ngpio = (_ngpio),					\
> > +		.register_width = (_width),				\
> > +		.flags = (_f),						\
> > +		.call_back = (_cb),					\
> > +		.resources = { _res },					\
> > +	}								\
> > +}
> > +
> > +#define ADD_COMPAT_GE_GPIO(_name, _ngpio)				\
> > +	ADD_COMPAT_GPIO(_name, 0x24, _ngpio, 0x4, ge_dt_cb,		\
> > +		 BGPIOF_BIG_ENDIAN_BYTE_ORDER,				\
> > +		 ADD_COMPAT_REGISTER("dat", 0x04),			\
> > +		 ADD_COMPAT_REGISTER("set", 0x08),			\
> > +		 ADD_COMPAT_REGISTER("dirin", 0x00))			\
> > +
> > +static const struct of_device_id compat_gpio_devices[] = {
> > +	ADD_COMPAT_GE_GPIO("ge,imp3a-gpio", 16),
> > +	ADD_COMPAT_GE_GPIO("gef,sbc310-gpio", 6),
> > +	ADD_COMPAT_GE_GPIO("gef,sbc610-gpio", 19),
> > +	ADD_COMPAT_GPIO("moxa,moxart-gpio", 0xc, 0, 0x4, moxart_dt_cb,
> > +		 BGPIOF_READ_OUTPUT_REG_SET,
> > +		 ADD_COMPAT_REGISTER("dat", 0x04),
> > +		 ADD_COMPAT_REGISTER("set", 0x00),
> > +		 ADD_COMPAT_REGISTER("dirout", 0x08)),
> > +	ADD_COMPAT_GPIO("technologic,ts4800-gpio", 0x6, 16, 0x2, ts4800_dt_cb,
> > +		 0, ADD_COMPAT_REGISTER("dat", 0x00),
> > +		 ADD_COMPAT_REGISTER("set", 0x02),
> > +		 ADD_COMPAT_REGISTER("dirout", 0x04)),
> > +};
> > +
> > +#undef ADD_COMPAT_GE_GPIO
> > +#undef ADD_COMPAT_GPIO
> > +#undef ADD_COMPAT_REGISTER
> > +
> > +static int compat_parse_dt(struct platform_device *pdev,
> > +			   struct bgpio_pdata *pdata,
> > +			   unsigned long *flags)
> > +{
> > +	const struct device_node *node = pdev->dev.of_node;
> > +	const struct compat_gpio_device_data *entry;
> > +	const struct of_device_id *of_id;
> > +	struct resource *res;
> > +	int err;
> > +
> > +	of_id = of_match_node(compat_gpio_devices, node);
> > +	if (!of_id)
> > +		return -ENODEV;
> > +
> > +	entry = of_id->data;
> > +	if (!entry || !entry->resources[0].name)
> > +		return -EINVAL;
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	if (!res)
> > +		return -EINVAL;
> > +
> > +	if (!res->name || strcmp(entry->resources[0].name, res->name)) {
> > +		struct resource nres[ARRAY_SIZE(entry->resources)];
> > +		size_t i;
> > +
> > +		if (resource_size(res) != entry->expected_resource_size)
> > +			return -EINVAL;
> > +
> > +		for (i = 0; i < ARRAY_SIZE(entry->resources); i++) {
> > +			if (!entry->resources[i].name)
> > +				continue;
> > +
> > +			nres[i].name = devm_kstrdup(&pdev->dev,
> > +				entry->resources[i].name, GFP_KERNEL);
> > +			nres[i].start = res->start +
> > +				entry->resources[i].start_offset;
> > +			nres[i].end = nres[i].start +
> > +				entry->register_width - 1;
> > +			nres[i].flags = IORESOURCE_MEM;
> > +		}
> > +
> > +		err = platform_device_add_resources(pdev, nres, i);
> > +		if (err)
> > +			return err;
> > +	}
> > +
> > +	pdata->base = -1;
> > +	pdata->ngpio = entry->ngpio;
> > +	*flags = entry->flags;
> > +
> > +	if (entry->call_back)
> > +		err = entry->call_back(pdev, pdata, flags);
> > +
> > +	return err;
> > +}
> 
> Ok, so this is getting quite complex, with two of_device_id tables and two 
> levels of hooks, mainly because you want to use the bgpio_pdev_probe() 
> function which relies on named memory resources.
I think I need more here. The bgpio_pdev_probe() also sets up the bgpio_maps()
(there are 6 and I'm using 4 at the moment for all compat chips). 
The bgpio_pdev_probe() also deals with devm_gpiochip_add_data() and allocates
the memory for the gpiochip structure... as well as  and the error handling.
etc...

That's why I reused the existing code as much as possible.
(But let's get to the main issue here:)
> This function is here for basic platform devices, and you are not obliged 
> to rely on it for DT. Feel free to write your own function (or rather split 
> bgpio_pdev_probe() in two code paths) if it can reduce the amount of black 
> magic you need to do (especially the renaming of resources on-the-fly).
> 
> At the end of the day what you want is a function that calls bgpio_init() 
> with the right parameters. These parameters should be inferred from the 
> compatible property whenever possible (which is most of the time, and why I 
> am suspiscious of using "reg" properties for these devices since I don't 
> think it can change much?), and passed as-is to bgpio_init(). Your 
> compat_gpio_device_data struct basically encodes this, so this will take 
> care of all the "compat" devices.
> 
> For the other devices, you should be able to fill in such a structure from 
> the DT properties. Then you just use it for the parameters of bgpio_init(). 
> It will be more elegant that adding resources, and probably shorter as 
> well.
> 
> > +
> >  static const struct of_device_id bgpio_of_match[] = {
> >  	{ .compatible = "wd,mbl-gpio", .data = bgpio_basic_mmio_parse_dt },
> > +	{ .compatible = "cirrus,clps711x-gpio", .data = clps711x_parse_dt },
> > +	{ .compatible = "ge,imp3a-gpio", .data = compat_parse_dt },
> > +	{ .compatible = "gef,sbc310-gpio", .data = compat_parse_dt },
> > +	{ .compatible = "gef,sbc610-gpio", .data = compat_parse_dt },
> > +	{ .compatible = "moxa,moxart-gpio", .data = compat_parse_dt },
> > +	{ .compatible = "technologic,ts4800-gpio", .data = compat_parse_dt },
> 
> If you implement my idea, the function referred to by .data should return 
> that structure I was talking about, and bgpio_init() can be called directly 
> on it after that. The current path of bgpio_pdev_probe() should only be 
> taken if bgpio_parse_dt() returned NULL.
> 
> I believe this will reduce the number of lines in your patch some more, and 
> it will also make the code easier to read.
> 
> Also this should be split into several patches, like the previous one: the 
> first one adds the required infrastructure to gpio-mmio, and the subsequent 
> patches each move one device into gpio-mmio.

The main issue why this got so complicated was keeping compatibility with
the existing drivers.

If you look at "clps711x_parse_dt". You will see that it supports 5 GPIOs.
The thing that makes it really ugly is that it uses the dt alias as a way
to identify each port (A-E). The Port is then used to encode the number of
gpios the controller has and whenever it is dirin or dirout... 
I argued that this information should be put in the dts and I made patch
for it. But updating the dts was not the way to go. as Rob explained
in <http://www.spinics.net/lists/devicetree/msg124538.html>.

This means that unless you can make a single structure that would encode
everything these compat drivers do, (look at the call_back functions of
the other drivers, each of the compat drivers also has a little bit of
extra code associated to setup stuff like a label or have an extra ngpios
property parser, etc...). I cannot see how you could make this any better
without breaking compatibility. This was the sole reason why there are
these individual parsers. (In RFC v4? I had that parser in their original
files - I don't know if this would have worked any better, but feedback
indicated that everything should be moved to the gpio-mmio.c). 

So, what's your take on it?

Note: This patch was added to this series as a request of Rob to demonstrate
that having a device tree binding for the gpio-mmio.c driver is something we
want. It isn't necessary to apply it right away as it also hinges on the ACKs
of people who use these devices. And so far, nobody replied. We can add this
individual patch at a later time. 

Regards,
Christian


From arnd at arndb.de  Thu May 12 06:06:39 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 12 May 2016 15:06:39 +0200
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <57347BD4.8010105@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <2733875.IzutTZKHMc@wuerfel> <57347BD4.8010105@huawei.com>
Message-ID: <4521594.dSmlmmAdFg@wuerfel>

On Thursday 12 May 2016 20:49:24 Zhangjian wrote:
> Hi,
> 
> On 2016/5/12 17:21, Arnd Bergmann wrote:
> > On Thursday 12 May 2016 10:17:58 Catalin Marinas wrote:
> >> On Wed, May 11, 2016 at 09:30:07PM +0200, Arnd Bergmann wrote:
> >>> On Wednesday 11 May 2016 17:59:01 Catalin Marinas wrote:
> >>>
> >>> I don't think the shifts are a problem, the main downside would be
> >>> the limit to 44 bits of file offsets (16TB files), but it's also
> >>> unclear if that is a practical problem at all. If it is, we run
> >>> into the same problem on all other 32-bit architectures too.
> >>
> >> I hope people are seriously thinking of moving to an LP64 ABI if they
> >> have such large file offset needs.
> >
> > Good point. 44 bits of file size is certainly enough for mmap()
> > on a 32-bit task: you would only be able to map a very small fraction
> > of the file anyway, and if you want to map larger files, and should
> > move to 64-bit tasks long before this becomes a limitation.
> Hi,
> 
> I apply the following patch in order to make use of the REAL mmmap2. LTP
> test pass in litle endian. mmap16 successful with segfault in big endian.
> 
> BTW, I saw the similar code in tile, mips, microblaze and s390 compat. Should
> we merge these code into a common syscall wrapper?

I think that's a good idea. The function used to be slightly different
for each architecture, but now it seems we have a significant number
of identical implementations that we could just merge them together
into one.

sys_mmap_pgoff was originally introduced as the common implementation
and it reduced the amount of duplication a lot, but as its units
are based on PAGE_SIZE rather than hardwired 4096 bytes, it's
not as useful.

> diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
> index d85fe94..2cd72eb 100644
> --- a/arch/arm64/kernel/sys_ilp32.c
> +++ b/arch/arm64/kernel/sys_ilp32.c
> @@ -41,7 +41,16 @@
>   #define compat_sys_sync_file_range     sys_sync_file_range
>   #define compat_sys_truncate64          sys_truncate
>   #define sys_llseek                     sys_lseek
> -#define sys_mmap2                     sys_mmap
> +
> +SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
> +       unsigned long, prot, unsigned long, flags, unsigned long, fd,
> +       unsigned long, pgoff)
> +{
> +       if (pgoff & (~PAGE_MASK >> 12))
> +               return -EINVAL;
> +
> +       return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12));
> +}
> 

Looks good to me.

	Arnd


From daniel.thompson at linaro.org  Thu May 12 06:08:29 2016
From: daniel.thompson at linaro.org (Daniel Thompson)
Date: Thu, 12 May 2016 14:08:29 +0100
Subject: [PATCH] arm64: kgdb: Match pstate size with gdbserver protocol
In-Reply-To: <20160510143156.GB10785@leverpostej>
References: <1462815566-15086-1-git-send-email-daniel.thompson@linaro.org>
 <20160510104511.GH687@leverpostej>
 <df946c87-162f-fdda-879b-76b4ad1a1c7a@linaro.org>
 <20160510143156.GB10785@leverpostej>
Message-ID: <daaec290-2d7c-551a-1129-4b672b7ef739@linaro.org>

On 10/05/16 15:31, Mark Rutland wrote:
> On Tue, May 10, 2016 at 02:41:54PM +0100, Daniel Thompson wrote:
>> On 10/05/16 11:45, Mark Rutland wrote:
>>>> When commit 44679a4f142b ("arm64: KGDB: Add step debugging support") was
>>>> introduced it was paired with a gdb patch that made an incompatible
>>>> change to the gdbserver protocol. This patch was eventually merged into
>>>> the gdb sources:
>>>> https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=a4d9ba85ec5597a6a556afe26b712e878374b9dd
>>>>
>>>> The change to the protocol was mostly made to simplify big-endian support
>>>> inside the kernel gdb stub.
>>>
>>> While that was how we discovered the inconsistency, a major concern is
>>> that SPSR_EL* (i.e. PSTATE), as accessed by MRS/MSR is a 64-bit
>>> quantity, even if the upper 32 bits are RES0 today.
>>>
>>> It is conceivable that the upper 32 bits could be used in future (as
>>> happened with CLIDR_EL1), and for this reason we expose those upper 32
>>> bits from the kernel, and treat system registers as 64-bit quantities
>>> generally.
>>
>> These cases are not exactly the same.
>>
>> CLIDR_ELx is (or was) architecturally defined as a 64-bit register
>> and explicitly marks the upper 32-bits as RES0.
>>
>> That is not the case for SPSR_ELx; this register is architecturally
>> defined to be 32-bit.
>
> The below doesn't necessarily change your subsequent argument, but that
> isn't quite true.
>
> The two cases are in fact identical if you dig into the history a bit
> further. Take a look in an earlier revision of the ARM ARM (e.g. ARM DDI
> 0487A.b), where it was explicitly stated:
>
> 	Attributes
> 		CLIDR_EL1 is a 32-bit register.

I see. I only when back as far as A.e ...


> Based on this, my PoV is that any register that the ARM ARM describes as
> "a 32-bit register" is a 64-bit register for which the upper 32 bits are
> RES0.

Understood.

>> I know that doesn't *prevent* SPSR_ELx from being expanded in the
>> future it is not unreasonable for gdb to design its wire protocol
>> based on the description found in the architecture manual.
>>
>>> So this was also about ensuring the interface was consistent and to some
>>> extent future-proof.
>>
>> gdb remote protocol is already future proof and has never at any
>> point contradicted the architecture.
>>
>> However the changes to the protocol in 7.7.x and 7.8.0 were
>> analogous to an unexpected ABI change rather than a carefully
>> controlled introduction of a new feature. Like the kernel, once
>> detected, they were reversed ;-) .
>
> To be clear, I don't disagree with this. The ARM ARM is at best
> amigibious w.r.t. what it means by "a 32-bit register", and that's the
> only point of contention.

Agree... such ambiguity strikes me as a particularly serious problem for 
switchable context registers since it takes *very* close attention to 
the ARM ARM for an existing OS to determine that it is required to treat 
the upper 32-bits of context should-be-zero-or-preserved.


> However, we should make note of the above as a key point of rationale,
> as it affects other decisions we make in this area.

Ok. I'll add comments describing how the gdbremote protocol is 
interpreting the spec.


Daniel.


From wangkefeng.wang at huawei.com  Thu May 12 06:08:59 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 12 May 2016 21:08:59 +0800
Subject: [PATCH v7 0/5] ACPI: parse the SPCR table
In-Reply-To: <bc91f503-cee5-db03-51bf-a36ef3e95a1f@linaro.org>
References: <1459431629-27934-1-git-send-email-aleksey.makarov@linaro.org>
 <1bff98e3-2d94-ed76-1165-ed7d43bbfcf3@jonmasters.org>
 <bc91f503-cee5-db03-51bf-a36ef3e95a1f@linaro.org>
Message-ID: <5734806B.50705@huawei.com>



On 2016/5/12 19:52, Aleksey Makarov wrote:
> Hi Jon,
> 
> In v7 I addressed the issues that were brought up by Rafael J . Wysocki
> (but I still do not have ACK from ACPI people).
> 
> The issue with D02 will be addressed in a separate patch.
> 
> There possibly is an issue with 16550 and command line console with I am
> investigating and probably will address in a separate patch.


Sound good, and will retest this in D02 with the coming patch, and

Tested-by: Kefeng Wang <wangkefeng.wang at huawei.com>

BRs,
Kefeng

> 
> I know no other problems with it and reviewers seem happy.
> 
> So I believe this patchset could be pulled.  If needed, I will send v8.
> 
> Thank you
> Aleksey Makarov
> 
> On 05/12/2016 11:20 AM, Jon Masters wrote:
>> On 03/31/2016 09:40 AM, Aleksey Makarov wrote:
>>
>>> 'ARM Server Base Boot Requirements' [1] mentions SPCR (Serial Port
>>> Console Redirection Table) [2] as a mandatory ACPI table that
>>> specifies the configuration of serial console.
>>
>> Hi Aleksey,
>>
>> Can you summarize the status of this patch series?
>>
>> Jon.
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> .
> 



From ynorov at caviumnetworks.com  Thu May 12 06:19:48 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 12 May 2016 16:19:48 +0300
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <4521594.dSmlmmAdFg@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <2733875.IzutTZKHMc@wuerfel> <57347BD4.8010105@huawei.com>
 <4521594.dSmlmmAdFg@wuerfel>
Message-ID: <20160512131948.GA30205@yury-N73SV>

On Thu, May 12, 2016 at 03:06:39PM +0200, Arnd Bergmann wrote:
> On Thursday 12 May 2016 20:49:24 Zhangjian wrote:
> > Hi,
> > 
> > On 2016/5/12 17:21, Arnd Bergmann wrote:
> > > On Thursday 12 May 2016 10:17:58 Catalin Marinas wrote:
> > >> On Wed, May 11, 2016 at 09:30:07PM +0200, Arnd Bergmann wrote:
> > >>> On Wednesday 11 May 2016 17:59:01 Catalin Marinas wrote:
> > >>>
> > >>> I don't think the shifts are a problem, the main downside would be
> > >>> the limit to 44 bits of file offsets (16TB files), but it's also
> > >>> unclear if that is a practical problem at all. If it is, we run
> > >>> into the same problem on all other 32-bit architectures too.
> > >>
> > >> I hope people are seriously thinking of moving to an LP64 ABI if they
> > >> have such large file offset needs.
> > >
> > > Good point. 44 bits of file size is certainly enough for mmap()
> > > on a 32-bit task: you would only be able to map a very small fraction
> > > of the file anyway, and if you want to map larger files, and should
> > > move to 64-bit tasks long before this becomes a limitation.
> > Hi,
> > 
> > I apply the following patch in order to make use of the REAL mmmap2. LTP
> > test pass in litle endian. mmap16 successful with segfault in big endian.
> > 
> > BTW, I saw the similar code in tile, mips, microblaze and s390 compat. Should
> > we merge these code into a common syscall wrapper?
> 
> I think that's a good idea. The function used to be slightly different
> for each architecture, but now it seems we have a significant number
> of identical implementations that we could just merge them together
> into one.
> 
> sys_mmap_pgoff was originally introduced as the common implementation
> and it reduced the amount of duplication a lot, but as its units
> are based on PAGE_SIZE rather than hardwired 4096 bytes, it's
> not as useful.
> 

microblaze and mips (twice) are doing like this. And aarh32 as well,
in arch/arm64/kernel/entry32.S

In previous submissions it was a patch that shares aarch32 code to
ilp32. If we decided turn around again, I think, we'd pick up that patch.

The other option is to make this hack generic, as so many arches use it.


From andre.przywara at arm.com  Thu May 12 06:25:23 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 12 May 2016 14:25:23 +0100
Subject: [PATCH v3 13/55] KVM: arm/arm64: vgic-new: Add data structure
 definitions
In-Reply-To: <20160512121258.GG27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-14-git-send-email-andre.przywara@arm.com>
 <20160512121258.GG27623@cbox>
Message-ID: <57348443.3090906@arm.com>

Hi,

On 12/05/16 13:12, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:26AM +0100, Andre Przywara wrote:
>> From: Christoffer Dall <christoffer.dall at linaro.org>
>>
>> Add a new header file for the new and improved GIC implementation.
>> The big change is that we now have a struct vgic_irq per IRQ instead
>> of spreading all the information over various bitmaps.
>>
>> We include this new header conditionally from within the old header
>> file for the time being to avoid touching all the users.
>>
>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>> Changes RFC .. v1:
>> - adapt to 4.6-rc (adding live_lrs member)
>> - elaborate on ap_list usage
>>
>> Changes v1 .. v2:
>> - change data type of dist->enabled to bool
>>
>>  include/kvm/arm_vgic.h  |   5 ++
>>  include/kvm/vgic/vgic.h | 201 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 206 insertions(+)
>>  create mode 100644 include/kvm/vgic/vgic.h
>>
>> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
>> index c14ff77..d406f8e 100644
>> --- a/include/kvm/arm_vgic.h
>> +++ b/include/kvm/arm_vgic.h
>> @@ -19,6 +19,10 @@
>>  #ifndef __ASM_ARM_KVM_VGIC_H
>>  #define __ASM_ARM_KVM_VGIC_H
>>  
>> +#ifdef CONFIG_KVM_NEW_VGIC
>> +#include <kvm/vgic/vgic.h>
>> +#else
>> +
>>  #include <linux/kernel.h>
>>  #include <linux/kvm.h>
>>  #include <linux/irqreturn.h>
>> @@ -366,4 +370,5 @@ static inline int vgic_v3_probe(struct device_node *vgic_node,
>>  }
>>  #endif
>>  
>> +#endif	/* old VGIC include */
>>  #endif
>> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
>> new file mode 100644
>> index 0000000..39933ee
>> --- /dev/null
>> +++ b/include/kvm/vgic/vgic.h
>> @@ -0,0 +1,201 @@
>> +/*
>> + * Copyright (C) 2015, 2016 ARM 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.
>> + *
>> + * 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.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +#ifndef __ASM_ARM_KVM_VGIC_VGIC_H
>> +#define __ASM_ARM_KVM_VGIC_VGIC_H
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/kvm.h>
>> +#include <linux/irqreturn.h>
>> +#include <linux/spinlock.h>
>> +#include <linux/types.h>
>> +#include <kvm/iodev.h>
>> +
>> +#define VGIC_V3_MAX_CPUS	255
>> +#define VGIC_V2_MAX_CPUS	8
>> +#define VGIC_NR_IRQS_LEGACY     256
>> +#define VGIC_NR_SGIS		16
>> +#define VGIC_NR_PPIS		16
>> +#define VGIC_NR_PRIVATE_IRQS	(VGIC_NR_SGIS + VGIC_NR_PPIS)
>> +#define VGIC_MAX_PRIVATE	(VGIC_NR_PRIVATE_IRQS - 1)
>> +#define VGIC_MAX_SPI		1019
>> +#define VGIC_MAX_RESERVED	1023
>> +#define VGIC_MIN_LPI		8192
>> +
>> +enum vgic_type {
>> +	VGIC_V2,		/* Good ol' GICv2 */
>> +	VGIC_V3,		/* New fancy GICv3 */
>> +};
>> +
>> +/* same for all guests, as depending only on the _host's_ GIC model */
>> +struct vgic_global {
>> +	/* type of the host GIC */
>> +	enum vgic_type		type;
>> +
>> +	/* Physical address of vgic virtual cpu interface */
>> +	phys_addr_t		vcpu_base;
>> +
>> +	/* virtual control interface mapping */
>> +	void __iomem		*vctrl_base;
>> +
>> +	/* Number of implemented list registers */
>> +	int			nr_lr;
>> +
>> +	/* Maintenance IRQ number */
> 
> nit: this is the physial INTID, right?
> 
>> +	unsigned int		maint_irq;
>> +
>> +	/* maximum number of VCPUs allowed (GICv2 limits us to 8) */
>> +	int			max_gic_vcpus;
>> +
>> +	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
>> +	bool			can_emulate_gicv2;
>> +};
>> +
>> +extern struct vgic_global kvm_vgic_global_state;
>> +
>> +#define VGIC_V2_MAX_LRS		(1 << 6)
>> +#define VGIC_V3_MAX_LRS		16
>> +#define VGIC_V3_LR_INDEX(lr)	(VGIC_V3_MAX_LRS - 1 - lr)
>> +
>> +enum vgic_irq_config {
>> +	VGIC_CONFIG_EDGE = 0,
>> +	VGIC_CONFIG_LEVEL
>> +};
>> +
>> +struct vgic_irq {
>> +	spinlock_t irq_lock;		/* Protects the content of the struct */
>> +	struct list_head ap_list;
>> +
>> +	struct kvm_vcpu *vcpu;		/* SGIs and PPIs: The VCPU
>> +					 * SPIs and LPIs: The VCPU whose ap_list
>> +					 * on which this is queued.
> 
> nit: s/on which this is queued/this is queued on/
> 
>> +					 */
>> +
>> +	struct kvm_vcpu *target_vcpu;	/* The VCPU that this interrupt should
>> +					 * be send to, as a result of the
> 
> nit: s/send/sent/

Both fixed.

>> +					 * targets reg (v2) or the
>> +					 * affinity reg (v3).
>> +					 */
>> +
>> +	u32 intid;			/* Guest visible INTID */
>> +	bool pending;
>> +	bool line_level;		/* Level only */
>> +	bool soft_pending;		/* Level only */
>> +	bool active;			/* not used for LPIs */
>> +	bool enabled;
>> +	bool hw;			/* Tied to HW IRQ */
>> +	u32 hwintid;			/* HW INTID number */
>> +	union {
>> +		u8 targets;			/* GICv2 target VCPUs mask */
>> +		u32 mpidr;			/* GICv3 target VCPU */
>> +	};
>> +	u8 source;			/* GICv2 SGIs only */
>> +	u8 priority;
>> +	enum vgic_irq_config config;	/* Level or edge */
>> +};
>> +
>> +struct vgic_dist {
>> +	bool			in_kernel;
>> +	bool			ready;
>> +
>> +	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
>> +	u32			vgic_model;
>> +
>> +	int			nr_spis;
>> +
>> +	/* TODO: Consider moving to global state */
>> +	/* Virtual control interface mapping */
>> +	void __iomem		*vctrl_base;
>> +
>> +	/* base addresses in guest physical address space: */
>> +	gpa_t			vgic_dist_base;		/* distributor */
>> +	union {
>> +		/* either a GICv2 CPU interface */
>> +		gpa_t			vgic_cpu_base;
>> +		/* or a number of GICv3 redistributor regions */
>> +		gpa_t			vgic_redist_base;
>> +	};
>> +
>> +	/* distributor enabled */
>> +	bool			enabled;
>> +
>> +	struct vgic_irq		*spis;
>> +};
>> +
>> +struct vgic_v2_cpu_if {
>> +	u32		vgic_hcr;
>> +	u32		vgic_vmcr;
>> +	u32		vgic_misr;	/* Saved only */
>> +	u64		vgic_eisr;	/* Saved only */
>> +	u64		vgic_elrsr;	/* Saved only */
>> +	u32		vgic_apr;
>> +	u32		vgic_lr[VGIC_V2_MAX_LRS];
>> +};
>> +
>> +struct vgic_v3_cpu_if {
>> +#ifdef CONFIG_KVM_ARM_VGIC_V3
>> +	u32		vgic_hcr;
>> +	u32		vgic_vmcr;
>> +	u32		vgic_sre;	/* Restored only, change ignored */
>> +	u32		vgic_misr;	/* Saved only */
>> +	u32		vgic_eisr;	/* Saved only */
>> +	u32		vgic_elrsr;	/* Saved only */
>> +	u32		vgic_ap0r[4];
>> +	u32		vgic_ap1r[4];
>> +	u64		vgic_lr[VGIC_V3_MAX_LRS];
>> +#endif
>> +};
>> +
>> +struct vgic_cpu {
>> +	/* CPU vif control registers for world switch */
>> +	union {
>> +		struct vgic_v2_cpu_if	vgic_v2;
>> +		struct vgic_v3_cpu_if	vgic_v3;
>> +	};
>> +
>> +	unsigned int used_lrs;
>> +	struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
>> +
>> +	spinlock_t ap_list_lock;	/* Protects the ap_list */
>> +
>> +	/*
>> +	 * List of IRQs that this VCPU should consider because they are either
>> +	 * Active or Pending (hence the name; AP list), or because they recently
>> +	 * were one of the two and need to be migrated off this list to another
>> +	 * VCPU.
>> +	 */
>> +	struct list_head ap_list_head;
>> +
>> +	u64 live_lrs;
>> +};
>> +
>> +#define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
>> +#define vgic_initialized(k)	(false)
>> +#define vgic_ready(k)		((k)->arch.vgic.ready)
>> +#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
>> +			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
> 
> this should really be a static inline at this point.

I think I tried this at the very beginning and it doesn't work. I get:

In file included from include/kvm/arm_vgic.h:23:0,
                 from arch/arm64/include/asm/kvm_host.h:39,
                 from include/linux/kvm_host.h:36,
                 from arch/arm64/kernel/asm-offsets.c:24:
include/kvm/vgic/vgic.h: In function 'vgic_valid_spi':
include/kvm/vgic/vgic.h:232:13: error: dereferencing pointer to
incomplete type 'struct kvm'
   (irq < kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS);
             ^
./Kbuild:80: recipe for target 'arch/arm64/kernel/asm-offsets.s' failed
make[3]: *** [arch/arm64/kernel/asm-offsets.s] Error 1

Is this because asm-offsets.s includes this file and struct kvm is
opaque at this point?
Or is my brain totally GICed by now?

Cheers,
Andre.


From catalin.marinas at arm.com  Thu May 12 06:35:34 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 12 May 2016 14:35:34 +0100
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160512002000.GA30997@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
Message-ID: <20160512133533.GF11226@e104818-lin.cambridge.arm.com>

On Thu, May 12, 2016 at 03:20:00AM +0300, Yury Norov wrote:
> I debugged preadv02 and pwritev02 failures and found very weird bug.
> Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> of vector, and kernel reports successful read/write.
> 
> There are 2 problems:
> 1. How kernel allows such address to be passed to fs subsystem;
> 2. How fs successes to read/write at non-mapped, and in fact non-user
> address.
> 
> I don't know the answer on 2'nd question, and it might be something
> generic. But I investigated first problem.
> 
> The problem is that compat_rw_copy_check_uvector() uses access_ok() to
> validate user address, and on arm64 it ends up with checking buffer
> end against current_thread_info()->addr_limit.
> 
> current_thread_info()->addr_limit for ilp32, and most probably for
> aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
> It happens because on thread creation we call flush_old_exec() to set 
> addr_limit, and completely ignore compat mode there.

I assume accesses beyond this address would fault anyway but I haven't
checked the code paths.

> diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
> index 7a39683..6ba4952 100644
> --- a/arch/arm64/include/asm/elf.h
> +++ b/arch/arm64/include/asm/elf.h
> @@ -146,6 +146,7 @@ typedef struct user_fpsimd_state elf_fpregset_t;
>  do {						\
>  	clear_thread_flag(TIF_32BIT_AARCH64);	\
>  	clear_thread_flag(TIF_32BIT);		\
> +	set_fs(TASK_SIZE_64);			\
>  } while (0)

See below.

> diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
> index 19cfdc5..3b0dd8d 100644
> --- a/arch/arm64/include/asm/uaccess.h
> +++ b/arch/arm64/include/asm/uaccess.h
> @@ -51,7 +51,7 @@
>  #define KERNEL_DS	(-1UL)
>  #define get_ds()	(KERNEL_DS)
>  
> -#define USER_DS		TASK_SIZE_64
> +#define USER_DS		TASK_SIZE

I agree with this.

>  #define get_fs()	(current_thread_info()->addr_limit)
>  
>  static inline void set_fs(mm_segment_t fs)
> diff --git a/arch/arm64/kernel/binfmt_elf32.c b/arch/arm64/kernel/binfmt_elf32.c
> index 5487872..2e8d9f3 100644
> --- a/arch/arm64/kernel/binfmt_elf32.c
> +++ b/arch/arm64/kernel/binfmt_elf32.c
> @@ -12,6 +12,7 @@
>  do {						\
>  	clear_thread_flag(TIF_32BIT_AARCH64);	\
>  	set_thread_flag(TIF_32BIT);		\
> +	set_fs(TASK_SIZE_32);			\
>  } while (0)
>  
>  #define COMPAT_ARCH_DLINFO
> diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
> index a934fd4..a8599c6 100644
> --- a/arch/arm64/kernel/binfmt_ilp32.c
> +++ b/arch/arm64/kernel/binfmt_ilp32.c
> @@ -59,6 +59,7 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
>  do {									\
>  	set_thread_flag(TIF_32BIT_AARCH64);				\
>  	clear_thread_flag(TIF_32BIT);					\
> +	set_fs(TASK_SIZE_32);						\
>  } while (0)

I don't think we need these two. AFAICT, flush_old_exec() takes care of
setting the USER_DS for the new thread.

-- 
Catalin


From will.deacon at arm.com  Thu May 12 06:36:43 2016
From: will.deacon at arm.com (Will Deacon)
Date: Thu, 12 May 2016 14:36:43 +0100
Subject: [PATCH v3 0/2] arm64: mm: Enhance Virtual kernel memory layout
In-Reply-To: <1463055387-19289-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1460948988-7477-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463055387-19289-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <20160512133642.GC25355@arm.com>

On Thu, May 12, 2016 at 08:16:25PM +0800, Kefeng Wang wrote:
> This is a micro enhance for Virtual kernel memory layout. Show bss info,
> and make each line with single pr_cont().

I already queued[1] the previous version of this after James acked it,
so if you want to make further changes, please send incremental patches
for review.

Will

[1]
https://git.kernel.org/cgit/linux/kernel/git/arm64/linux.git/commit/?h=for-next/core&id=9974723e31d1fa99e3c0efb2ae6cbbf089c0080c
https://git.kernel.org/cgit/linux/kernel/git/arm64/linux.git/commit/?h=for-next/core&id=d32351c8242b7067b3f3e3a6caf7a387ff43f978


From javier at dowhile0.org  Thu May 12 06:40:01 2016
From: javier at dowhile0.org (Javier Martinez Canillas)
Date: Thu, 12 May 2016 09:40:01 -0400
Subject: [RFC] Reset pins of phys and their representation in a device tree
In-Reply-To: <e75ab3a0-da5e-fef1-d5e1-65c37e7714eb@cogentembedded.com>
References: <20160512071542.GC30822@pengutronix.de>
 <e75ab3a0-da5e-fef1-d5e1-65c37e7714eb@cogentembedded.com>
Message-ID: <CABxcv==YQshEvUw2a91nqjqrT3JU52Yzy4RbcWiTS-nWMf2m=Q@mail.gmail.com>

[adding Krzysztof as cc]

On Thu, May 12, 2016 at 8:25 AM, Sergei Shtylyov
<sergei.shtylyov at cogentembedded.com> wrote:
> Hello.
>
>
> On 5/12/2016 10:15 AM, Uwe Kleine-K?nig wrote:
>
>> I have a machine here where the reset pin of the phy is connected to a
>> GPIO.
>>
>> There are different possibilities available today to handle this
>> situation, here are the ones I'm aware of:
>>
>>  - Use a gpio-hog to set the reset gpio to non-active
>>    This might result in dependency problems (and that's what I am
>>    currently faced with) because there is no connection in the device
>>    tree between the hog and the phy.
>>
>>  - [Documentation/devicetree/bindings/net/fsl-fec.txt]
>>    The fec node supports properties
>>
>>         phy-reset-gpios = <&gpio2 14 0>;
>>         phy-reset-duration = <200> /* milliseconds */;
>>
>>    Something similar exists in TI's vendor kernel
>>
>> (http://git.ti.com/ti-linux-kernel/ti-linux-kernel/commit/17d192b999ee904ced223c16cef76111a51c461b)
>>    with different (and IMHO bader) naming.
>>    This is the wrong place to specify the gpios; they shouldn't be in the
>>    mac's node, but in a phy node instead.
>>
>> So what I actually want is to put the gpio specification in the right
>> place and let it look as follows:
>>
>>         mymdiobus {
>>                 [...]
>>                 myfirstphy: ethernet-phy at 0 {
>>                         compatible = "ethernet-phy-ieee802.3-c22";
>>                         reg = <0>;
>>
>>                         reset-gpios = <&gpio2 14 0>;
>>                         reset-duration-ms = <200>;
>>                 };
>>
>>                 mysecondphy: ethernet-phy at 2 {
>>                         compatible = "ethernet-phy-ieee802.3-c22";
>>                         reg = <2>;
>>
>>                         reset-gpios = <&gpio3 10 0>;
>>                         reset-duration-ms = <200>;
>>                 };
>>         };
>>
>> And with this we could defer probe of &myfirstphy if &gpio2 isn't
>> available yet.
>>
>> Does this sound sensible? Does something like that already exist which I
>> missed? Any further ideas/comments?
>
>
> http://patchwork.ozlabs.org/patch/616495/
>
>    I'll post a new version RSN.
>

This seems to be similar to what's needed by MMC/SD/SDIO devices (i.e:
a WiFi chip) that needs some power sequence for reset and be
enumerable.

Krzysztof has been working  to make the MMC pwrseq framework more
generic [0] since he wants to use it also for built-in USB devices.

>From a quick look at the patches mentioned in this thread, it seems
that the same framework can be used to reset the PHYs unless I'm
missing something. Have you considered using this? It would be good if
there is a consistent way to define the power sequence for devices
across the different subsystems.

[0]: https://lkml.org/lkml/2016/5/5/230

Best regards,
Javier


From linus.walleij at linaro.org  Thu May 12 06:40:38 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 12 May 2016 15:40:38 +0200
Subject: [PATCH] pinctrl: stm32: Implement .pin_config_dbg_show()
In-Reply-To: <5733364A.3090606@st.com>
References: <1461939943-24752-1-git-send-email-patrice.chotard@st.com>
 <CACRpkdZ=KsPL1mBS1bLi=jYsv=Vb1QNBi8XPAJW50doPcwBuZg@mail.gmail.com>
 <5733364A.3090606@st.com>
Message-ID: <CACRpkdawoqfqN8YeojyrzPru2fwrFMidc1e2v7yxHRpPf+rK6w@mail.gmail.com>

On Wed, May 11, 2016 at 3:40 PM, Patrice Chotard <patrice.chotard at st.com> wrote:
> On 05/10/2016 01:50 PM, Linus Walleij wrote:

> Sorry i didn't pay attention, but there is a compilation warning in this
> patch.
>
> drivers/pinctrl/stm32/pinctrl-stm32.c:823:7: warning: too many arguments for
> format [-Wformat-extra-args]
>        speeds[speed], "speed");
>
>
> What do you prefer ?
>  _ me to submit a v2 fixing this warning and at the same occasion include
> the requested code factorization
>  _ or submit additionnal patchset ?

Just send a patch on top fixing this.

Yours,
Linus Walleij


From christoffer.dall at linaro.org  Thu May 12 06:41:39 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 15:41:39 +0200
Subject: [PATCH v3 36/55] KVM: arm/arm64: vgic-new: Add GICv3 IROUTER
 register handlers
In-Reply-To: <57347925.2030902@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-37-git-send-email-andre.przywara@arm.com>
 <20160512122119.GH27623@cbox> <57347925.2030902@arm.com>
Message-ID: <20160512134139.GA5878@cbox>

On Thu, May 12, 2016 at 01:37:57PM +0100, Marc Zyngier wrote:
> On 12/05/16 13:21, Christoffer Dall wrote:
> > On Fri, May 06, 2016 at 11:45:49AM +0100, Andre Przywara wrote:
> >> Since GICv3 supports much more than the 8 CPUs the GICv2 ITARGETSR
> >> register can handle, the new IROUTER register covers the whole range
> >> of possible target (V)CPUs by using the same MPIDR that the cores
> >> report themselves.
> >> In addition to translating this MPIDR into a vcpu pointer we store
> >> the originally written value as well. The architecture allows to
> >> write any values into the register, which must be read back as written.
> >>
> >> Since we don't support affinity level 3, we don't need to take care
> >> about the upper word of this 64-bit register, which simplifies the
> >> handling a bit.
> >>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >> Changelog RFC..v1:
> >> - fold in and simplify vgic_v3_irq_change_affinity
> >>
> >> Changelog v1 .. v2:
> >> - adapt to new MMIO framework
> >>
> >>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 65 +++++++++++++++++++++++++++++++++++++++-
> >>  1 file changed, 64 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> >> index 48fba9c..3bcc2c4 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> >> @@ -86,6 +86,69 @@ static u32 compress_mpidr(unsigned long mpidr)
> >>  	return ret;
> >>  }
> >>  
> >> +static unsigned long decompress_mpidr(u32 value)
> >> +{
> >> +	unsigned long mpidr;
> >> +
> >> +	mpidr  = ((value >>  0) & 0xFF) << MPIDR_LEVEL_SHIFT(0);
> >> +	mpidr |= ((value >>  8) & 0xFF) << MPIDR_LEVEL_SHIFT(1);
> >> +	mpidr |= ((value >> 16) & 0xFF) << MPIDR_LEVEL_SHIFT(2);
> >> +	mpidr |= (u64)((value >> 24) & 0xFF) << MPIDR_LEVEL_SHIFT(3);
> >> +
> >> +	return mpidr;
> >> +}
> >> +
> >> +static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
> >> +					    gpa_t addr, unsigned int len)
> >> +{
> >> +	int intid = (addr & 0x1fff) / 8;
> >> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
> >> +	unsigned long mpidr;
> >> +
> >> +	if (!irq)
> >> +		return 0;
> >> +
> >> +	mpidr = decompress_mpidr(irq->mpidr);
> > 
> > I'm unsure here; do we ned a READ_ONCE() in lieu taking the lock or are
> > we guaranteed that this is a single memory access even with compiler
> > inlining etc.?
> 
> I can't imagine the compiler being stupid enough to read this multiple
> times, but better safe than sorry. +1 for READ_ONCE().
> 
> > 
> >> +	return extract_bytes(mpidr, addr & 7, len);
> >> +}
> >> +
> >> +static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
> >> +				    gpa_t addr, unsigned int len,
> >> +				    unsigned long val)
> >> +{
> >> +	int intid = (addr & 0x1fff) / 8;
> >> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
> >> +	unsigned long mask = 0xffffffff;	/* upper word is WI */
> >> +	u64 mpidr;
> >> +
> >> +	if (!irq)
> >> +		return;
> >> +
> >> +	/*
> >> +	 * There are only two supported options:
> >> +	 * (1) aligned 64-bit access
> >> +	 * (2) aligned 32-bit access
> >> +	 *
> >> +	 * TODO: make this check generic and move it to dispatch_...()
> >> +	 */
> >> +	if (len != 4 && len != 8)
> >> +		return;
> >> +
> >> +
> >> +	/* The upper word is WI for us since we don't implement Aff3. */
> >> +	if (addr & 4)
> >> +		return;
> >> +
> >> +	spin_lock(&irq->irq_lock);
> >> +
> >> +	mpidr = decompress_mpidr(irq->mpidr);
> >> +	mpidr = (mpidr & ~mask) | (val & mask);
> >> +	irq->mpidr = compress_mpidr(mpidr);
> >> +	irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, mpidr);
> > 
> > this is weird because it doesn't preserve read-as-written semantics but
> > allows a guest to write something into the RES0 field and read that back
> > in the Aff3 field...
> 
> I don't see how we get this RES0/Aff3 mixup, but I can see other issues:
> 
oh, never mind, compress_mpidr expects aff3 in bits[39:32] and throws
the rest away.

/me hides under table.


From linus.walleij at linaro.org  Thu May 12 06:41:12 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 12 May 2016 15:41:12 +0200
Subject: [PATCH 1/6] pinctrl: meson: Fix eth_tx_en bit index
In-Reply-To: <m2r3d97wnc.fsf@baylibre.com>
References: <1462910920-5462-1-git-send-email-serveralex@gmail.com>
 <1462910920-5462-2-git-send-email-serveralex@gmail.com>
 <m2r3d97wnc.fsf@baylibre.com>
Message-ID: <CACRpkda40Gb4ye7_dBwOcsWZTT2V6qByVOyv_Z_Mg4RX+CLNiA@mail.gmail.com>

On Wed, May 11, 2016 at 11:48 AM, Kevin Hilman <khilman at baylibre.com> wrote:
> Alexander M?ller <serveralex at gmail.com> writes:
>
>> Fix pinctrl eth_tx_en bit index according to Hardkernel ODROID-C1 datasheet.
>>
>> Signed-off-by: Alexander M?ller <serveralex at gmail.com>
>
> Tested-by: Kevin Hilman <khilman at baylibre.com>
>
> Linus, with your ack, we can take this through the amlogic tree, or feel
> free to merge as a fix as it can go independetly of the rest of the
> series if needed.

I've merged this patch.

Yours,
Linus Walleij


From ynorov at caviumnetworks.com  Thu May 12 06:44:31 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 12 May 2016 16:44:31 +0300
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
Message-ID: <20160512134431.GB30205@yury-N73SV>

On Thu, May 12, 2016 at 02:35:34PM +0100, Catalin Marinas wrote:
> On Thu, May 12, 2016 at 03:20:00AM +0300, Yury Norov wrote:
> > I debugged preadv02 and pwritev02 failures and found very weird bug.
> > Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> > of vector, and kernel reports successful read/write.
> > 
> > There are 2 problems:
> > 1. How kernel allows such address to be passed to fs subsystem;
> > 2. How fs successes to read/write at non-mapped, and in fact non-user
> > address.
> > 
> > I don't know the answer on 2'nd question, and it might be something
> > generic. But I investigated first problem.
> > 
> > The problem is that compat_rw_copy_check_uvector() uses access_ok() to
> > validate user address, and on arm64 it ends up with checking buffer
> > end against current_thread_info()->addr_limit.
> > 
> > current_thread_info()->addr_limit for ilp32, and most probably for
> > aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
> > It happens because on thread creation we call flush_old_exec() to set 
> > addr_limit, and completely ignore compat mode there.
> 
> I assume accesses beyond this address would fault anyway but I haven't
> checked the code paths.
> 
> > diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
> > index 7a39683..6ba4952 100644
> > --- a/arch/arm64/include/asm/elf.h
> > +++ b/arch/arm64/include/asm/elf.h
> > @@ -146,6 +146,7 @@ typedef struct user_fpsimd_state elf_fpregset_t;
> >  do {						\
> >  	clear_thread_flag(TIF_32BIT_AARCH64);	\
> >  	clear_thread_flag(TIF_32BIT);		\
> > +	set_fs(TASK_SIZE_64);			\
> >  } while (0)
> 
> See below.
> 
> > diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
> > index 19cfdc5..3b0dd8d 100644
> > --- a/arch/arm64/include/asm/uaccess.h
> > +++ b/arch/arm64/include/asm/uaccess.h
> > @@ -51,7 +51,7 @@
> >  #define KERNEL_DS	(-1UL)
> >  #define get_ds()	(KERNEL_DS)
> >  
> > -#define USER_DS		TASK_SIZE_64
> > +#define USER_DS		TASK_SIZE
> 
> I agree with this.
> 
> >  #define get_fs()	(current_thread_info()->addr_limit)
> >  
> >  static inline void set_fs(mm_segment_t fs)
> > diff --git a/arch/arm64/kernel/binfmt_elf32.c b/arch/arm64/kernel/binfmt_elf32.c
> > index 5487872..2e8d9f3 100644
> > --- a/arch/arm64/kernel/binfmt_elf32.c
> > +++ b/arch/arm64/kernel/binfmt_elf32.c
> > @@ -12,6 +12,7 @@
> >  do {						\
> >  	clear_thread_flag(TIF_32BIT_AARCH64);	\
> >  	set_thread_flag(TIF_32BIT);		\
> > +	set_fs(TASK_SIZE_32);			\
> >  } while (0)
> >  
> >  #define COMPAT_ARCH_DLINFO
> > diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
> > index a934fd4..a8599c6 100644
> > --- a/arch/arm64/kernel/binfmt_ilp32.c
> > +++ b/arch/arm64/kernel/binfmt_ilp32.c
> > @@ -59,6 +59,7 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
> >  do {									\
> >  	set_thread_flag(TIF_32BIT_AARCH64);				\
> >  	clear_thread_flag(TIF_32BIT);					\
> > +	set_fs(TASK_SIZE_32);						\
> >  } while (0)
> 
> I don't think we need these two. AFAICT, flush_old_exec() takes care of
> setting the USER_DS for the new thread.

That's true, but USER_DS depends on personality which is not set yet
for new thread, as I wrote above. In fact, I tried correct USER_DS
only, and it doesn't work

> 
> -- 
> Catalin


From christoffer.dall at linaro.org  Thu May 12 06:48:44 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 15:48:44 +0200
Subject: [PATCH v3 13/55] KVM: arm/arm64: vgic-new: Add data structure
 definitions
In-Reply-To: <57348443.3090906@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-14-git-send-email-andre.przywara@arm.com>
 <20160512121258.GG27623@cbox> <57348443.3090906@arm.com>
Message-ID: <20160512134844.GB5878@cbox>

On Thu, May 12, 2016 at 02:25:23PM +0100, Andre Przywara wrote:
> Hi,
> 
> On 12/05/16 13:12, Christoffer Dall wrote:
> > On Fri, May 06, 2016 at 11:45:26AM +0100, Andre Przywara wrote:
> >> From: Christoffer Dall <christoffer.dall at linaro.org>
> >>
> >> Add a new header file for the new and improved GIC implementation.
> >> The big change is that we now have a struct vgic_irq per IRQ instead
> >> of spreading all the information over various bitmaps.
> >>
> >> We include this new header conditionally from within the old header
> >> file for the time being to avoid touching all the users.
> >>
> >> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >> Changes RFC .. v1:
> >> - adapt to 4.6-rc (adding live_lrs member)
> >> - elaborate on ap_list usage
> >>
> >> Changes v1 .. v2:
> >> - change data type of dist->enabled to bool
> >>
> >>  include/kvm/arm_vgic.h  |   5 ++
> >>  include/kvm/vgic/vgic.h | 201 ++++++++++++++++++++++++++++++++++++++++++++++++
> >>  2 files changed, 206 insertions(+)
> >>  create mode 100644 include/kvm/vgic/vgic.h
> >>
> >> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> >> index c14ff77..d406f8e 100644
> >> --- a/include/kvm/arm_vgic.h
> >> +++ b/include/kvm/arm_vgic.h
> >> @@ -19,6 +19,10 @@
> >>  #ifndef __ASM_ARM_KVM_VGIC_H
> >>  #define __ASM_ARM_KVM_VGIC_H
> >>  
> >> +#ifdef CONFIG_KVM_NEW_VGIC
> >> +#include <kvm/vgic/vgic.h>
> >> +#else
> >> +
> >>  #include <linux/kernel.h>
> >>  #include <linux/kvm.h>
> >>  #include <linux/irqreturn.h>
> >> @@ -366,4 +370,5 @@ static inline int vgic_v3_probe(struct device_node *vgic_node,
> >>  }
> >>  #endif
> >>  
> >> +#endif	/* old VGIC include */
> >>  #endif
> >> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> >> new file mode 100644
> >> index 0000000..39933ee
> >> --- /dev/null
> >> +++ b/include/kvm/vgic/vgic.h
> >> @@ -0,0 +1,201 @@
> >> +/*
> >> + * Copyright (C) 2015, 2016 ARM 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.
> >> + *
> >> + * 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.
> >> + *
> >> + * You should have received a copy of the GNU General Public License
> >> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> >> + */
> >> +#ifndef __ASM_ARM_KVM_VGIC_VGIC_H
> >> +#define __ASM_ARM_KVM_VGIC_VGIC_H
> >> +
> >> +#include <linux/kernel.h>
> >> +#include <linux/kvm.h>
> >> +#include <linux/irqreturn.h>
> >> +#include <linux/spinlock.h>
> >> +#include <linux/types.h>
> >> +#include <kvm/iodev.h>
> >> +
> >> +#define VGIC_V3_MAX_CPUS	255
> >> +#define VGIC_V2_MAX_CPUS	8
> >> +#define VGIC_NR_IRQS_LEGACY     256
> >> +#define VGIC_NR_SGIS		16
> >> +#define VGIC_NR_PPIS		16
> >> +#define VGIC_NR_PRIVATE_IRQS	(VGIC_NR_SGIS + VGIC_NR_PPIS)
> >> +#define VGIC_MAX_PRIVATE	(VGIC_NR_PRIVATE_IRQS - 1)
> >> +#define VGIC_MAX_SPI		1019
> >> +#define VGIC_MAX_RESERVED	1023
> >> +#define VGIC_MIN_LPI		8192
> >> +
> >> +enum vgic_type {
> >> +	VGIC_V2,		/* Good ol' GICv2 */
> >> +	VGIC_V3,		/* New fancy GICv3 */
> >> +};
> >> +
> >> +/* same for all guests, as depending only on the _host's_ GIC model */
> >> +struct vgic_global {
> >> +	/* type of the host GIC */
> >> +	enum vgic_type		type;
> >> +
> >> +	/* Physical address of vgic virtual cpu interface */
> >> +	phys_addr_t		vcpu_base;
> >> +
> >> +	/* virtual control interface mapping */
> >> +	void __iomem		*vctrl_base;
> >> +
> >> +	/* Number of implemented list registers */
> >> +	int			nr_lr;
> >> +
> >> +	/* Maintenance IRQ number */
> > 
> > nit: this is the physial INTID, right?
> > 
> >> +	unsigned int		maint_irq;
> >> +
> >> +	/* maximum number of VCPUs allowed (GICv2 limits us to 8) */
> >> +	int			max_gic_vcpus;
> >> +
> >> +	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
> >> +	bool			can_emulate_gicv2;
> >> +};
> >> +
> >> +extern struct vgic_global kvm_vgic_global_state;
> >> +
> >> +#define VGIC_V2_MAX_LRS		(1 << 6)
> >> +#define VGIC_V3_MAX_LRS		16
> >> +#define VGIC_V3_LR_INDEX(lr)	(VGIC_V3_MAX_LRS - 1 - lr)
> >> +
> >> +enum vgic_irq_config {
> >> +	VGIC_CONFIG_EDGE = 0,
> >> +	VGIC_CONFIG_LEVEL
> >> +};
> >> +
> >> +struct vgic_irq {
> >> +	spinlock_t irq_lock;		/* Protects the content of the struct */
> >> +	struct list_head ap_list;
> >> +
> >> +	struct kvm_vcpu *vcpu;		/* SGIs and PPIs: The VCPU
> >> +					 * SPIs and LPIs: The VCPU whose ap_list
> >> +					 * on which this is queued.
> > 
> > nit: s/on which this is queued/this is queued on/
> > 
> >> +					 */
> >> +
> >> +	struct kvm_vcpu *target_vcpu;	/* The VCPU that this interrupt should
> >> +					 * be send to, as a result of the
> > 
> > nit: s/send/sent/
> 
> Both fixed.
> 
> >> +					 * targets reg (v2) or the
> >> +					 * affinity reg (v3).
> >> +					 */
> >> +
> >> +	u32 intid;			/* Guest visible INTID */
> >> +	bool pending;
> >> +	bool line_level;		/* Level only */
> >> +	bool soft_pending;		/* Level only */
> >> +	bool active;			/* not used for LPIs */
> >> +	bool enabled;
> >> +	bool hw;			/* Tied to HW IRQ */
> >> +	u32 hwintid;			/* HW INTID number */
> >> +	union {
> >> +		u8 targets;			/* GICv2 target VCPUs mask */
> >> +		u32 mpidr;			/* GICv3 target VCPU */
> >> +	};
> >> +	u8 source;			/* GICv2 SGIs only */
> >> +	u8 priority;
> >> +	enum vgic_irq_config config;	/* Level or edge */
> >> +};
> >> +
> >> +struct vgic_dist {
> >> +	bool			in_kernel;
> >> +	bool			ready;
> >> +
> >> +	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
> >> +	u32			vgic_model;
> >> +
> >> +	int			nr_spis;
> >> +
> >> +	/* TODO: Consider moving to global state */
> >> +	/* Virtual control interface mapping */
> >> +	void __iomem		*vctrl_base;
> >> +
> >> +	/* base addresses in guest physical address space: */
> >> +	gpa_t			vgic_dist_base;		/* distributor */
> >> +	union {
> >> +		/* either a GICv2 CPU interface */
> >> +		gpa_t			vgic_cpu_base;
> >> +		/* or a number of GICv3 redistributor regions */
> >> +		gpa_t			vgic_redist_base;
> >> +	};
> >> +
> >> +	/* distributor enabled */
> >> +	bool			enabled;
> >> +
> >> +	struct vgic_irq		*spis;
> >> +};
> >> +
> >> +struct vgic_v2_cpu_if {
> >> +	u32		vgic_hcr;
> >> +	u32		vgic_vmcr;
> >> +	u32		vgic_misr;	/* Saved only */
> >> +	u64		vgic_eisr;	/* Saved only */
> >> +	u64		vgic_elrsr;	/* Saved only */
> >> +	u32		vgic_apr;
> >> +	u32		vgic_lr[VGIC_V2_MAX_LRS];
> >> +};
> >> +
> >> +struct vgic_v3_cpu_if {
> >> +#ifdef CONFIG_KVM_ARM_VGIC_V3
> >> +	u32		vgic_hcr;
> >> +	u32		vgic_vmcr;
> >> +	u32		vgic_sre;	/* Restored only, change ignored */
> >> +	u32		vgic_misr;	/* Saved only */
> >> +	u32		vgic_eisr;	/* Saved only */
> >> +	u32		vgic_elrsr;	/* Saved only */
> >> +	u32		vgic_ap0r[4];
> >> +	u32		vgic_ap1r[4];
> >> +	u64		vgic_lr[VGIC_V3_MAX_LRS];
> >> +#endif
> >> +};
> >> +
> >> +struct vgic_cpu {
> >> +	/* CPU vif control registers for world switch */
> >> +	union {
> >> +		struct vgic_v2_cpu_if	vgic_v2;
> >> +		struct vgic_v3_cpu_if	vgic_v3;
> >> +	};
> >> +
> >> +	unsigned int used_lrs;
> >> +	struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
> >> +
> >> +	spinlock_t ap_list_lock;	/* Protects the ap_list */
> >> +
> >> +	/*
> >> +	 * List of IRQs that this VCPU should consider because they are either
> >> +	 * Active or Pending (hence the name; AP list), or because they recently
> >> +	 * were one of the two and need to be migrated off this list to another
> >> +	 * VCPU.
> >> +	 */
> >> +	struct list_head ap_list_head;
> >> +
> >> +	u64 live_lrs;
> >> +};
> >> +
> >> +#define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
> >> +#define vgic_initialized(k)	(false)
> >> +#define vgic_ready(k)		((k)->arch.vgic.ready)
> >> +#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
> >> +			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
> > 
> > this should really be a static inline at this point.
> 
> I think I tried this at the very beginning and it doesn't work. I get:
> 
> In file included from include/kvm/arm_vgic.h:23:0,
>                  from arch/arm64/include/asm/kvm_host.h:39,
>                  from include/linux/kvm_host.h:36,
>                  from arch/arm64/kernel/asm-offsets.c:24:
> include/kvm/vgic/vgic.h: In function 'vgic_valid_spi':
> include/kvm/vgic/vgic.h:232:13: error: dereferencing pointer to
> incomplete type 'struct kvm'
>    (irq < kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS);
>              ^
> ./Kbuild:80: recipe for target 'arch/arm64/kernel/asm-offsets.s' failed
> make[3]: *** [arch/arm64/kernel/asm-offsets.s] Error 1
> 
> Is this because asm-offsets.s includes this file and struct kvm is
> opaque at this point?

Probably, but in this case, never mind, we can rework that another time.

> Or is my brain totally GICed by now?
> 

Haha, I definitely feel GICed!

-Christoffer


From wens at csie.org  Thu May 12 06:49:05 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Thu, 12 May 2016 21:49:05 +0800
Subject: [RFC] Reset pins of phys and their representation in a device tree
In-Reply-To: <CABxcv==YQshEvUw2a91nqjqrT3JU52Yzy4RbcWiTS-nWMf2m=Q@mail.gmail.com>
References: <20160512071542.GC30822@pengutronix.de>
 <e75ab3a0-da5e-fef1-d5e1-65c37e7714eb@cogentembedded.com>
 <CABxcv==YQshEvUw2a91nqjqrT3JU52Yzy4RbcWiTS-nWMf2m=Q@mail.gmail.com>
Message-ID: <CAGb2v64=iEA4VS3r4-ctVR6OKu_rRbiZytDtuQJ_LDr8JPq0Pg@mail.gmail.com>

Hi,

On Thu, May 12, 2016 at 9:40 PM, Javier Martinez Canillas
<javier at dowhile0.org> wrote:
> [adding Krzysztof as cc]
>
> On Thu, May 12, 2016 at 8:25 AM, Sergei Shtylyov
> <sergei.shtylyov at cogentembedded.com> wrote:
>> Hello.
>>
>>
>> On 5/12/2016 10:15 AM, Uwe Kleine-K?nig wrote:
>>
>>> I have a machine here where the reset pin of the phy is connected to a
>>> GPIO.
>>>
>>> There are different possibilities available today to handle this
>>> situation, here are the ones I'm aware of:
>>>
>>>  - Use a gpio-hog to set the reset gpio to non-active
>>>    This might result in dependency problems (and that's what I am
>>>    currently faced with) because there is no connection in the device
>>>    tree between the hog and the phy.
>>>
>>>  - [Documentation/devicetree/bindings/net/fsl-fec.txt]
>>>    The fec node supports properties
>>>
>>>         phy-reset-gpios = <&gpio2 14 0>;
>>>         phy-reset-duration = <200> /* milliseconds */;
>>>
>>>    Something similar exists in TI's vendor kernel
>>>
>>> (http://git.ti.com/ti-linux-kernel/ti-linux-kernel/commit/17d192b999ee904ced223c16cef76111a51c461b)
>>>    with different (and IMHO bader) naming.
>>>    This is the wrong place to specify the gpios; they shouldn't be in the
>>>    mac's node, but in a phy node instead.
>>>
>>> So what I actually want is to put the gpio specification in the right
>>> place and let it look as follows:
>>>
>>>         mymdiobus {
>>>                 [...]
>>>                 myfirstphy: ethernet-phy at 0 {
>>>                         compatible = "ethernet-phy-ieee802.3-c22";
>>>                         reg = <0>;
>>>
>>>                         reset-gpios = <&gpio2 14 0>;
>>>                         reset-duration-ms = <200>;
>>>                 };
>>>
>>>                 mysecondphy: ethernet-phy at 2 {
>>>                         compatible = "ethernet-phy-ieee802.3-c22";
>>>                         reg = <2>;
>>>
>>>                         reset-gpios = <&gpio3 10 0>;
>>>                         reset-duration-ms = <200>;
>>>                 };
>>>         };
>>>
>>> And with this we could defer probe of &myfirstphy if &gpio2 isn't
>>> available yet.
>>>
>>> Does this sound sensible? Does something like that already exist which I
>>> missed? Any further ideas/comments?
>>
>>
>> http://patchwork.ozlabs.org/patch/616495/
>>
>>    I'll post a new version RSN.
>>
>
> This seems to be similar to what's needed by MMC/SD/SDIO devices (i.e:
> a WiFi chip) that needs some power sequence for reset and be
> enumerable.
>
> Krzysztof has been working  to make the MMC pwrseq framework more
> generic [0] since he wants to use it also for built-in USB devices.
>
> From a quick look at the patches mentioned in this thread, it seems
> that the same framework can be used to reset the PHYs unless I'm
> missing something. Have you considered using this? It would be good if
> there is a consistent way to define the power sequence for devices
> across the different subsystems.
>
> [0]: https://lkml.org/lkml/2016/5/5/230

You probably missed the part that Rob nacked the bindings in that
series?

Putting the reset gpios under the PHY nodes and handling it from
phylib is probably the way to go. I'd like to ask for regulator
and clock support as well, if possible.

Regards
ChenYu


From andre.przywara at arm.com  Thu May 12 07:00:47 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 12 May 2016 15:00:47 +0100
Subject: [PATCH v3 36/55] KVM: arm/arm64: vgic-new: Add GICv3 IROUTER
 register handlers
In-Reply-To: <57347925.2030902@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-37-git-send-email-andre.przywara@arm.com>
 <20160512122119.GH27623@cbox> <57347925.2030902@arm.com>
Message-ID: <57348C8F.6080409@arm.com>

Hi,

On 12/05/16 13:37, Marc Zyngier wrote:
> On 12/05/16 13:21, Christoffer Dall wrote:
>> On Fri, May 06, 2016 at 11:45:49AM +0100, Andre Przywara wrote:
>>> Since GICv3 supports much more than the 8 CPUs the GICv2 ITARGETSR
>>> register can handle, the new IROUTER register covers the whole range
>>> of possible target (V)CPUs by using the same MPIDR that the cores
>>> report themselves.
>>> In addition to translating this MPIDR into a vcpu pointer we store
>>> the originally written value as well. The architecture allows to
>>> write any values into the register, which must be read back as written.
>>>
>>> Since we don't support affinity level 3, we don't need to take care
>>> about the upper word of this 64-bit register, which simplifies the
>>> handling a bit.
>>>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>> Changelog RFC..v1:
>>> - fold in and simplify vgic_v3_irq_change_affinity
>>>
>>> Changelog v1 .. v2:
>>> - adapt to new MMIO framework
>>>
>>>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 65 +++++++++++++++++++++++++++++++++++++++-
>>>  1 file changed, 64 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>>> index 48fba9c..3bcc2c4 100644
>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>>> @@ -86,6 +86,69 @@ static u32 compress_mpidr(unsigned long mpidr)
>>>  	return ret;
>>>  }
>>>  
>>> +static unsigned long decompress_mpidr(u32 value)
>>> +{
>>> +	unsigned long mpidr;
>>> +
>>> +	mpidr  = ((value >>  0) & 0xFF) << MPIDR_LEVEL_SHIFT(0);
>>> +	mpidr |= ((value >>  8) & 0xFF) << MPIDR_LEVEL_SHIFT(1);
>>> +	mpidr |= ((value >> 16) & 0xFF) << MPIDR_LEVEL_SHIFT(2);
>>> +	mpidr |= (u64)((value >> 24) & 0xFF) << MPIDR_LEVEL_SHIFT(3);
>>> +
>>> +	return mpidr;
>>> +}
>>> +
>>> +static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
>>> +					    gpa_t addr, unsigned int len)
>>> +{
>>> +	int intid = (addr & 0x1fff) / 8;
>>> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
>>> +	unsigned long mpidr;
>>> +
>>> +	if (!irq)
>>> +		return 0;
>>> +
>>> +	mpidr = decompress_mpidr(irq->mpidr);
>>
>> I'm unsure here; do we ned a READ_ONCE() in lieu taking the lock or are
>> we guaranteed that this is a single memory access even with compiler
>> inlining etc.?
> 
> I can't imagine the compiler being stupid enough to read this multiple
> times, but better safe than sorry. +1 for READ_ONCE().
> 
>>
>>> +	return extract_bytes(mpidr, addr & 7, len);
>>> +}
>>> +
>>> +static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
>>> +				    gpa_t addr, unsigned int len,
>>> +				    unsigned long val)
>>> +{
>>> +	int intid = (addr & 0x1fff) / 8;
>>> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
>>> +	unsigned long mask = 0xffffffff;	/* upper word is WI */
>>> +	u64 mpidr;
>>> +
>>> +	if (!irq)
>>> +		return;
>>> +
>>> +	/*
>>> +	 * There are only two supported options:
>>> +	 * (1) aligned 64-bit access
>>> +	 * (2) aligned 32-bit access
>>> +	 *
>>> +	 * TODO: make this check generic and move it to dispatch_...()
>>> +	 */
>>> +	if (len != 4 && len != 8)
>>> +		return;
>>> +
>>> +
>>> +	/* The upper word is WI for us since we don't implement Aff3. */
>>> +	if (addr & 4)
>>> +		return;
>>> +
>>> +	spin_lock(&irq->irq_lock);
>>> +
>>> +	mpidr = decompress_mpidr(irq->mpidr);
>>> +	mpidr = (mpidr & ~mask) | (val & mask);
>>> +	irq->mpidr = compress_mpidr(mpidr);
>>> +	irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, mpidr);
>>
>> this is weird because it doesn't preserve read-as-written semantics but
>> allows a guest to write something into the RES0 field and read that back
>> in the Aff3 field...

Technically Aff3 is not RES0, even if the A3V bit is cleared.
The A3V bit just disables Aff3 on the CPU interface side, specifically
for ICC_SGI0R_EL1 & friends.
I think we agreed some time ago that we have to support read-as-written
for this register and don't forward this IRQ if the MPIDR is not valid,
as the spec demands.

> I don't see how we get this RES0/Aff3 mixup, but I can see other issues:
> 
>>> +	unsigned long mask = 0xffffffff;	/* upper word is WI */
> 
> followed by:
> 
>>> +	mpidr = (mpidr & ~mask) | (val & mask);
> 
> is not going to preserve the top bits on 32bit (assuming we could
> perform a 64bit access on 32bit, but still).

Which would be fixed by making mask a u64?

> Also, the mask preserves
> the IRM bit, which is wrong (we don't support 1-of-n distribution).

Agreed on this.

> 
> Why don't we just have
> 
> 	mpidr = val & GENMASK_ULL(23, 0);
> 
> and let's be done with it? I must be missing something about this whole
> Aff3 thing...

Well, this would be a simple solution if we don't have to preserve bogus
MPIDRs.
The spec is a bit vague here:
"For each interrupt, a GIC implementation might support fewer than 256
values for an affinity level. In this case, some bits of the
corresponding affinity level field might be RO."

Not sure if this can apply to _all_ bits of an affinity level or not.

I think the key question is: do we need to preserve any MPIDR value
written into this register?

Cheers,
Andre.


From javier at dowhile0.org  Thu May 12 07:06:11 2016
From: javier at dowhile0.org (Javier Martinez Canillas)
Date: Thu, 12 May 2016 10:06:11 -0400
Subject: [RFC] Reset pins of phys and their representation in a device tree
In-Reply-To: <CAGb2v64=iEA4VS3r4-ctVR6OKu_rRbiZytDtuQJ_LDr8JPq0Pg@mail.gmail.com>
References: <20160512071542.GC30822@pengutronix.de>
 <e75ab3a0-da5e-fef1-d5e1-65c37e7714eb@cogentembedded.com>
 <CABxcv==YQshEvUw2a91nqjqrT3JU52Yzy4RbcWiTS-nWMf2m=Q@mail.gmail.com>
 <CAGb2v64=iEA4VS3r4-ctVR6OKu_rRbiZytDtuQJ_LDr8JPq0Pg@mail.gmail.com>
Message-ID: <CABxcv=maDoyayE3HaxXsvBhHS5GEQuMD0F7nRONKoFuEaXOZFQ@mail.gmail.com>

Hello ChenYu

On Thu, May 12, 2016 at 9:49 AM, Chen-Yu Tsai <wens at csie.org> wrote:
> Hi,
>
> On Thu, May 12, 2016 at 9:40 PM, Javier Martinez Canillas
> <javier at dowhile0.org> wrote:
>> [adding Krzysztof as cc]
>>
>> On Thu, May 12, 2016 at 8:25 AM, Sergei Shtylyov
>> <sergei.shtylyov at cogentembedded.com> wrote:
>>> Hello.
>>>
>>>
>>> On 5/12/2016 10:15 AM, Uwe Kleine-K?nig wrote:
>>>
>>>> I have a machine here where the reset pin of the phy is connected to a
>>>> GPIO.
>>>>
>>>> There are different possibilities available today to handle this
>>>> situation, here are the ones I'm aware of:
>>>>
>>>>  - Use a gpio-hog to set the reset gpio to non-active
>>>>    This might result in dependency problems (and that's what I am
>>>>    currently faced with) because there is no connection in the device
>>>>    tree between the hog and the phy.
>>>>
>>>>  - [Documentation/devicetree/bindings/net/fsl-fec.txt]
>>>>    The fec node supports properties
>>>>
>>>>         phy-reset-gpios = <&gpio2 14 0>;
>>>>         phy-reset-duration = <200> /* milliseconds */;
>>>>
>>>>    Something similar exists in TI's vendor kernel
>>>>
>>>> (http://git.ti.com/ti-linux-kernel/ti-linux-kernel/commit/17d192b999ee904ced223c16cef76111a51c461b)
>>>>    with different (and IMHO bader) naming.
>>>>    This is the wrong place to specify the gpios; they shouldn't be in the
>>>>    mac's node, but in a phy node instead.
>>>>
>>>> So what I actually want is to put the gpio specification in the right
>>>> place and let it look as follows:
>>>>
>>>>         mymdiobus {
>>>>                 [...]
>>>>                 myfirstphy: ethernet-phy at 0 {
>>>>                         compatible = "ethernet-phy-ieee802.3-c22";
>>>>                         reg = <0>;
>>>>
>>>>                         reset-gpios = <&gpio2 14 0>;
>>>>                         reset-duration-ms = <200>;
>>>>                 };
>>>>
>>>>                 mysecondphy: ethernet-phy at 2 {
>>>>                         compatible = "ethernet-phy-ieee802.3-c22";
>>>>                         reg = <2>;
>>>>
>>>>                         reset-gpios = <&gpio3 10 0>;
>>>>                         reset-duration-ms = <200>;
>>>>                 };
>>>>         };
>>>>
>>>> And with this we could defer probe of &myfirstphy if &gpio2 isn't
>>>> available yet.
>>>>
>>>> Does this sound sensible? Does something like that already exist which I
>>>> missed? Any further ideas/comments?
>>>
>>>
>>> http://patchwork.ozlabs.org/patch/616495/
>>>
>>>    I'll post a new version RSN.
>>>
>>
>> This seems to be similar to what's needed by MMC/SD/SDIO devices (i.e:
>> a WiFi chip) that needs some power sequence for reset and be
>> enumerable.
>>
>> Krzysztof has been working  to make the MMC pwrseq framework more
>> generic [0] since he wants to use it also for built-in USB devices.
>>
>> From a quick look at the patches mentioned in this thread, it seems
>> that the same framework can be used to reset the PHYs unless I'm
>> missing something. Have you considered using this? It would be good if
>> there is a consistent way to define the power sequence for devices
>> across the different subsystems.
>>
>> [0]: https://lkml.org/lkml/2016/5/5/230
>
> You probably missed the part that Rob nacked the bindings in that
> series?
>

No, I didn't miss that. AFAICT the way forward is still being
discussed as you can see from the last email in that thread from Ulf
[0].

And yes, the DT bindings is likely to change (keeping the backward
compat for MMC) which is good,  but still the power sequence
management code can be reused across subsystems.

> Putting the reset gpios under the PHY nodes and handling it from
> phylib is probably the way to go. I'd like to ask for regulator
> and clock support as well, if possible.
>

A GPIO array, clock and regulator (after Krzysztof patch) is already
supported by the pwrseq_simple provider for example.

> Regards
> ChenYu

[0]: https://lkml.org/lkml/2016/5/10/320


From catalin.marinas at arm.com  Thu May 12 07:07:35 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 12 May 2016 15:07:35 +0100
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160512134431.GB30205@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
 <20160512134431.GB30205@yury-N73SV>
Message-ID: <20160512140734.GG11226@e104818-lin.cambridge.arm.com>

On Thu, May 12, 2016 at 04:44:31PM +0300, Yury Norov wrote:
> On Thu, May 12, 2016 at 02:35:34PM +0100, Catalin Marinas wrote:
> > On Thu, May 12, 2016 at 03:20:00AM +0300, Yury Norov wrote:
> > > I debugged preadv02 and pwritev02 failures and found very weird bug.
> > > Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> > > of vector, and kernel reports successful read/write.
> > > 
> > > There are 2 problems:
> > > 1. How kernel allows such address to be passed to fs subsystem;
> > > 2. How fs successes to read/write at non-mapped, and in fact non-user
> > > address.
> > > 
> > > I don't know the answer on 2'nd question, and it might be something
> > > generic. But I investigated first problem.
> > > 
> > > The problem is that compat_rw_copy_check_uvector() uses access_ok() to
> > > validate user address, and on arm64 it ends up with checking buffer
> > > end against current_thread_info()->addr_limit.
> > > 
> > > current_thread_info()->addr_limit for ilp32, and most probably for
> > > aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
> > > It happens because on thread creation we call flush_old_exec() to set 
> > > addr_limit, and completely ignore compat mode there.

[...]

> > > --- a/arch/arm64/kernel/binfmt_elf32.c
> > > +++ b/arch/arm64/kernel/binfmt_elf32.c
> > > @@ -12,6 +12,7 @@
> > >  do {						\
> > >  	clear_thread_flag(TIF_32BIT_AARCH64);	\
> > >  	set_thread_flag(TIF_32BIT);		\
> > > +	set_fs(TASK_SIZE_32);			\
> > >  } while (0)
> > >  
> > >  #define COMPAT_ARCH_DLINFO
> > > diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
> > > index a934fd4..a8599c6 100644
> > > --- a/arch/arm64/kernel/binfmt_ilp32.c
> > > +++ b/arch/arm64/kernel/binfmt_ilp32.c
> > > @@ -59,6 +59,7 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
> > >  do {									\
> > >  	set_thread_flag(TIF_32BIT_AARCH64);				\
> > >  	clear_thread_flag(TIF_32BIT);					\
> > > +	set_fs(TASK_SIZE_32);						\
> > >  } while (0)
> > 
> > I don't think we need these two. AFAICT, flush_old_exec() takes care of
> > setting the USER_DS for the new thread.
> 
> That's true, but USER_DS depends on personality which is not set yet
> for new thread, as I wrote above. In fact, I tried correct USER_DS
> only, and it doesn't work

Ah, it looks like load_elf_binary() sets the personality after
flush_old_exec(). Looking at powerpc and x86, they set USER_DS to the
maximum 64-bit task value, so they should have a similar issue with
native 32-bit vs compat behaviour.

So what exactly is LTP complaining about? Is different error (like
EFAULT vs EINVAL) or not getting an error at all.

(I need to update my LTP, the preadv tests appeared in December last
year)

-- 
Catalin


From joel at jms.id.au  Thu May 12 07:17:09 2016
From: joel at jms.id.au (Joel Stanley)
Date: Thu, 12 May 2016 23:47:09 +0930
Subject: [PATCH v2 0/2] watchdog: Add Aspeed watchdog driver
In-Reply-To: <1462797277-14969-1-git-send-email-joel@jms.id.au>
References: <1462797277-14969-1-git-send-email-joel@jms.id.au>
Message-ID: <1463062631-16432-1-git-send-email-joel@jms.id.au>

Hello,

These patches add support for the watchdog timer found in Aspeed ast2400 and
ast2500 BMC SoCs.

The u-boot that ships on the edk and with many systems leaves the watchdog
running when jumping to the kernel, making this driver required for operation.

It has been tested on the ast2400 in an OpenPower Palmetto, and the ast2500-edk
dev board.

Changes in v2:

Addressed review from Guenter:
 - dropped the drv_dbgs
 - added defines for all of the constants
 - clarified the type of reset we want
 - leaves the watchdog running

This also updates the device tree compatible string following review from Rob.
As Arnd already took my device tree tree, I will send him a patch to fix that.

Cheers,

Joel

Joel Stanley (2):
  doc/devicetree: Add Aspeed watchdog timer bindings
  watchdog: Add Aspeed watchdog driver

 .../devicetree/bindings/watchdog/aspeed-wdt.txt    |  16 ++
 drivers/watchdog/Kconfig                           |  13 ++
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/aspeed_wdt.c                      | 209 +++++++++++++++++++++
 4 files changed, 239 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
 create mode 100644 drivers/watchdog/aspeed_wdt.c

-- 
2.8.1



From joel at jms.id.au  Thu May 12 07:17:10 2016
From: joel at jms.id.au (Joel Stanley)
Date: Thu, 12 May 2016 23:47:10 +0930
Subject: [PATCH v2 1/2] doc/devicetree: Add Aspeed watchdog timer bindings
In-Reply-To: <1463062631-16432-1-git-send-email-joel@jms.id.au>
References: <1462797277-14969-1-git-send-email-joel@jms.id.au>
 <1463062631-16432-1-git-send-email-joel@jms.id.au>
Message-ID: <1463062631-16432-2-git-send-email-joel@jms.id.au>

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 .../devicetree/bindings/watchdog/aspeed-wdt.txt          | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
new file mode 100644
index 000000000000..78ad314eaab9
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
@@ -0,0 +1,16 @@
+Aspeed Watchdog Timer
+
+Required properties:
+ - compatible: must be one of:
+	- "aspeed,ast2400-wdt"
+	- "aspeed,ast2500-wdt"
+
+ - reg: physical base address of the controller and length of memory mapped
+   region
+
+Example:
+
+	watchdog1: watchdog at 1e785000 {
+		compatible = "aspeed,ast2400-wdt";
+		reg = <0x1e785000 0x1c>;
+	};
-- 
2.8.1



From joel at jms.id.au  Thu May 12 07:17:11 2016
From: joel at jms.id.au (Joel Stanley)
Date: Thu, 12 May 2016 23:47:11 +0930
Subject: [PATCH v2 2/2] watchdog: Add Aspeed watchdog driver
In-Reply-To: <1463062631-16432-1-git-send-email-joel@jms.id.au>
References: <1462797277-14969-1-git-send-email-joel@jms.id.au>
 <1463062631-16432-1-git-send-email-joel@jms.id.au>
Message-ID: <1463062631-16432-3-git-send-email-joel@jms.id.au>

Provides generic watchdog features as well as reboot support for the
Apeed SoC.

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/watchdog/Kconfig      |  13 +++
 drivers/watchdog/Makefile     |   1 +
 drivers/watchdog/aspeed_wdt.c | 209 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 223 insertions(+)
 create mode 100644 drivers/watchdog/aspeed_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fb947655badd..4f0e2ded4785 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -661,6 +661,19 @@ config ATLAS7_WATCHDOG
 	  To compile this driver as a module, choose M here: the
 	  module will be called atlas7_wdt.
 
+config ASPEED_WATCHDOG
+	tristate "Aspeed watchdog support"
+	depends on ARCH_ASPEED || COMPILE_TEST
+	select WATCHDOG_CORE
+	help
+	  Say Y here to include support for the watchdog timer
+	  in Apseed BMC SoCs.
+
+	  This driver is required to reboot the SoC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called aspeed_wdt.
+
 # AVR32 Architecture
 
 config AT32AP700X_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index feb6270fdbde..36855375e0ce 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
 obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
 obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o
+obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
new file mode 100644
index 000000000000..f7ae41ef4121
--- /dev/null
+++ b/drivers/watchdog/aspeed_wdt.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2016 IBM Corporation
+ *
+ * Joel Stanley <joel at jms.id.au>
+ *
+ * Based on the qcom-watchdog driver
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/watchdog.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+struct aspeed_wdt {
+	struct watchdog_device	wdd;
+	unsigned long		rate;
+	void __iomem		*base;
+	u32			ctrl;
+};
+
+static const struct of_device_id aspeed_wdt_of_table[] = {
+	{ .compatible = "aspeed,ast2400-wdt" },
+	{ .compatible = "aspeed,ast2500-wdt" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
+
+#define WDT_STATUS		0x00
+#define WDT_RELOAD_VALUE	0x04
+#define WDT_RESTART		0x08
+#define WDT_CTRL		0x0C
+#define   WDT_CTRL_RESET_MODE_SOC	(0x00 << 5)
+#define   WDT_CTRL_RESET_MODE_FULL_CHIP	(0x01 << 5)
+#define   WDT_CTRL_1MHZ_CLK		BIT(4)
+#define   WDT_CTRL_WDT_EXT		BIT(3)
+#define   WDT_CTRL_WDT_INTR		BIT(2)
+#define   WDT_CTRL_RESET_SYSTEM		BIT(1)
+#define   WDT_CTRL_ENABLE		BIT(0)
+
+#define WDT_RESTART_MAGIC	0x4755
+
+#define WDT_MIN_TIMEOUT		1
+/* 32 bits at 1MHz, in milliseconds */
+#define WDT_MAX_TIMEOUT_MS	4294967
+#define WDT_DEFAULT_TIMEOUT	30
+#define WDT_1MHZ_CLOCK		1000000
+
+static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd)
+{
+	return container_of(wdd, struct aspeed_wdt, wdd);
+}
+
+static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
+{
+	wdt->ctrl |= WDT_CTRL_ENABLE;
+
+	writel(0, wdt->base + WDT_CTRL);
+	writel(count, wdt->base + WDT_RELOAD_VALUE);
+	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
+	writel(wdt->ctrl, wdt->base + WDT_CTRL);
+}
+
+static int aspeed_wdt_start(struct watchdog_device *wdd)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+
+	aspeed_wdt_enable(wdt, wdd->timeout * wdt->rate);
+
+	return 0;
+}
+
+static int aspeed_wdt_stop(struct watchdog_device *wdd)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+
+	wdt->ctrl &= ~WDT_CTRL_ENABLE;
+	writel(wdt->ctrl, wdt->base + WDT_CTRL);
+
+	return 0;
+}
+
+static int aspeed_wdt_ping(struct watchdog_device *wdd)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+
+	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
+
+	return 0;
+}
+
+static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
+				  unsigned int timeout)
+{
+	wdd->timeout = timeout;
+
+	return aspeed_wdt_start(wdd);
+}
+
+static int aspeed_wdt_restart(struct watchdog_device *wdd,
+			      unsigned long action, void *data)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+
+	aspeed_wdt_enable(wdt, 128 * wdt->rate / 1000);
+
+	return 0;
+}
+
+static const struct watchdog_ops aspeed_wdt_ops = {
+	.start		= aspeed_wdt_start,
+	.stop		= aspeed_wdt_stop,
+	.ping		= aspeed_wdt_ping,
+	.set_timeout	= aspeed_wdt_set_timeout,
+	.restart	= aspeed_wdt_restart,
+	.owner		= THIS_MODULE,
+};
+
+static const struct watchdog_info aspeed_wdt_info = {
+	.options	= WDIOF_KEEPALIVEPING
+			| WDIOF_MAGICCLOSE
+			| WDIOF_SETTIMEOUT,
+	.identity	= KBUILD_MODNAME,
+};
+
+static int aspeed_wdt_remove(struct platform_device *pdev)
+{
+	struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
+
+	watchdog_unregister_device(&wdt->wdd);
+
+	return 0;
+}
+
+static int aspeed_wdt_probe(struct platform_device *pdev)
+{
+	struct aspeed_wdt *wdt;
+	struct resource *res;
+	int ret;
+
+	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+	if (!wdt)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	wdt->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(wdt->base))
+		return PTR_ERR(wdt->base);
+
+	/*
+	 * The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only
+	 * runs at 1MHz. We chose to always run at 1MHz, as there's no
+	 * good reason to have a faster watchdog counter.
+	 */
+	wdt->rate = WDT_1MHZ_CLOCK;
+	wdt->wdd.info = &aspeed_wdt_info;
+	wdt->wdd.ops = &aspeed_wdt_ops;
+	wdt->wdd.min_timeout = WDT_MIN_TIMEOUT;
+	wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS;
+	wdt->wdd.parent = &pdev->dev;
+
+	wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT;
+	watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
+
+	/*
+	 * Control reset on a per-device basis to ensure the
+	 * host is not affected by a BMC reboot, so only reset
+	 * the SOC and not the full chip
+	 */
+	wdt->ctrl = WDT_CTRL_RESET_MODE_SOC |
+		WDT_CTRL_1MHZ_CLK |
+		WDT_CTRL_RESET_SYSTEM;
+
+	if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_ENABLE)  {
+		aspeed_wdt_start(&wdt->wdd);
+		set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
+	}
+
+	ret = watchdog_register_device(&wdt->wdd);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register\n");
+		return ret;
+	}
+
+	dev_info(&pdev->dev, "rate %lu, max timeout %u, timeout %d\n",
+		 wdt->rate, wdt->wdd.max_timeout, wdt->wdd.timeout);
+
+	platform_set_drvdata(pdev, wdt);
+
+	return 0;
+}
+
+static struct platform_driver aspeed_watchdog_driver = {
+	.probe = aspeed_wdt_probe,
+	.remove = aspeed_wdt_remove,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.of_match_table = of_match_ptr(aspeed_wdt_of_table),
+	},
+};
+module_platform_driver(aspeed_watchdog_driver);
+
+MODULE_DESCRIPTION("Aspeed Watchdog Driver");
+MODULE_LICENSE("GPL");
-- 
2.8.1



From catalin.marinas at arm.com  Thu May 12 07:20:16 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 12 May 2016 15:20:16 +0100
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
 <20160512134431.GB30205@yury-N73SV>
 <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
Message-ID: <20160512142016.GH11226@e104818-lin.cambridge.arm.com>

On Thu, May 12, 2016 at 03:07:35PM +0100, Catalin Marinas wrote:
> On Thu, May 12, 2016 at 04:44:31PM +0300, Yury Norov wrote:
> > On Thu, May 12, 2016 at 02:35:34PM +0100, Catalin Marinas wrote:
> > > On Thu, May 12, 2016 at 03:20:00AM +0300, Yury Norov wrote:
> > > > I debugged preadv02 and pwritev02 failures and found very weird bug.
> > > > Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> > > > of vector, and kernel reports successful read/write.
> > > > 
> > > > There are 2 problems:
> > > > 1. How kernel allows such address to be passed to fs subsystem;
> > > > 2. How fs successes to read/write at non-mapped, and in fact non-user
> > > > address.
> > > > 
> > > > I don't know the answer on 2'nd question, and it might be something
> > > > generic. But I investigated first problem.
> > > > 
> > > > The problem is that compat_rw_copy_check_uvector() uses access_ok() to
> > > > validate user address, and on arm64 it ends up with checking buffer
> > > > end against current_thread_info()->addr_limit.
> > > > 
> > > > current_thread_info()->addr_limit for ilp32, and most probably for
> > > > aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
> > > > It happens because on thread creation we call flush_old_exec() to set 
> > > > addr_limit, and completely ignore compat mode there.
> 
> [...]
> 
> > > > --- a/arch/arm64/kernel/binfmt_elf32.c
> > > > +++ b/arch/arm64/kernel/binfmt_elf32.c
> > > > @@ -12,6 +12,7 @@
> > > >  do {						\
> > > >  	clear_thread_flag(TIF_32BIT_AARCH64);	\
> > > >  	set_thread_flag(TIF_32BIT);		\
> > > > +	set_fs(TASK_SIZE_32);			\
> > > >  } while (0)
> > > >  
> > > >  #define COMPAT_ARCH_DLINFO
> > > > diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
> > > > index a934fd4..a8599c6 100644
> > > > --- a/arch/arm64/kernel/binfmt_ilp32.c
> > > > +++ b/arch/arm64/kernel/binfmt_ilp32.c
> > > > @@ -59,6 +59,7 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
> > > >  do {									\
> > > >  	set_thread_flag(TIF_32BIT_AARCH64);				\
> > > >  	clear_thread_flag(TIF_32BIT);					\
> > > > +	set_fs(TASK_SIZE_32);						\
> > > >  } while (0)
> > > 
> > > I don't think we need these two. AFAICT, flush_old_exec() takes care of
> > > setting the USER_DS for the new thread.
> > 
> > That's true, but USER_DS depends on personality which is not set yet
> > for new thread, as I wrote above. In fact, I tried correct USER_DS
> > only, and it doesn't work
> 
> Ah, it looks like load_elf_binary() sets the personality after
> flush_old_exec(). Looking at powerpc and x86, they set USER_DS to the
> maximum 64-bit task value, so they should have a similar issue with
> native 32-bit vs compat behaviour.

I think we have another problem. flush_old_exec() calls the arm64
flush_thread() where tls_thread_flush() checks for is_compat_task(). So
starting a 32-bit application from a 64-bit one not go on the correct
path.

-- 
Catalin


From marc.zyngier at arm.com  Thu May 12 07:20:16 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 12 May 2016 15:20:16 +0100
Subject: [PATCH v3 36/55] KVM: arm/arm64: vgic-new: Add GICv3 IROUTER
 register handlers
In-Reply-To: <57348C8F.6080409@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-37-git-send-email-andre.przywara@arm.com>
 <20160512122119.GH27623@cbox> <57347925.2030902@arm.com>
 <57348C8F.6080409@arm.com>
Message-ID: <57349120.1020402@arm.com>

On 12/05/16 15:00, Andre Przywara wrote:
> Hi,
> 
> On 12/05/16 13:37, Marc Zyngier wrote:
>> On 12/05/16 13:21, Christoffer Dall wrote:
>>> On Fri, May 06, 2016 at 11:45:49AM +0100, Andre Przywara wrote:
>>>> Since GICv3 supports much more than the 8 CPUs the GICv2 ITARGETSR
>>>> register can handle, the new IROUTER register covers the whole range
>>>> of possible target (V)CPUs by using the same MPIDR that the cores
>>>> report themselves.
>>>> In addition to translating this MPIDR into a vcpu pointer we store
>>>> the originally written value as well. The architecture allows to
>>>> write any values into the register, which must be read back as written.
>>>>
>>>> Since we don't support affinity level 3, we don't need to take care
>>>> about the upper word of this 64-bit register, which simplifies the
>>>> handling a bit.
>>>>
>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>> ---
>>>> Changelog RFC..v1:
>>>> - fold in and simplify vgic_v3_irq_change_affinity
>>>>
>>>> Changelog v1 .. v2:
>>>> - adapt to new MMIO framework
>>>>
>>>>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 65 +++++++++++++++++++++++++++++++++++++++-
>>>>  1 file changed, 64 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>>>> index 48fba9c..3bcc2c4 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
>>>> @@ -86,6 +86,69 @@ static u32 compress_mpidr(unsigned long mpidr)
>>>>  	return ret;
>>>>  }
>>>>  
>>>> +static unsigned long decompress_mpidr(u32 value)
>>>> +{
>>>> +	unsigned long mpidr;
>>>> +
>>>> +	mpidr  = ((value >>  0) & 0xFF) << MPIDR_LEVEL_SHIFT(0);
>>>> +	mpidr |= ((value >>  8) & 0xFF) << MPIDR_LEVEL_SHIFT(1);
>>>> +	mpidr |= ((value >> 16) & 0xFF) << MPIDR_LEVEL_SHIFT(2);
>>>> +	mpidr |= (u64)((value >> 24) & 0xFF) << MPIDR_LEVEL_SHIFT(3);
>>>> +
>>>> +	return mpidr;
>>>> +}
>>>> +
>>>> +static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
>>>> +					    gpa_t addr, unsigned int len)
>>>> +{
>>>> +	int intid = (addr & 0x1fff) / 8;
>>>> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
>>>> +	unsigned long mpidr;
>>>> +
>>>> +	if (!irq)
>>>> +		return 0;
>>>> +
>>>> +	mpidr = decompress_mpidr(irq->mpidr);
>>>
>>> I'm unsure here; do we ned a READ_ONCE() in lieu taking the lock or are
>>> we guaranteed that this is a single memory access even with compiler
>>> inlining etc.?
>>
>> I can't imagine the compiler being stupid enough to read this multiple
>> times, but better safe than sorry. +1 for READ_ONCE().
>>
>>>
>>>> +	return extract_bytes(mpidr, addr & 7, len);
>>>> +}
>>>> +
>>>> +static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
>>>> +				    gpa_t addr, unsigned int len,
>>>> +				    unsigned long val)
>>>> +{
>>>> +	int intid = (addr & 0x1fff) / 8;
>>>> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
>>>> +	unsigned long mask = 0xffffffff;	/* upper word is WI */
>>>> +	u64 mpidr;
>>>> +
>>>> +	if (!irq)
>>>> +		return;
>>>> +
>>>> +	/*
>>>> +	 * There are only two supported options:
>>>> +	 * (1) aligned 64-bit access
>>>> +	 * (2) aligned 32-bit access
>>>> +	 *
>>>> +	 * TODO: make this check generic and move it to dispatch_...()
>>>> +	 */
>>>> +	if (len != 4 && len != 8)
>>>> +		return;
>>>> +
>>>> +
>>>> +	/* The upper word is WI for us since we don't implement Aff3. */
>>>> +	if (addr & 4)
>>>> +		return;
>>>> +
>>>> +	spin_lock(&irq->irq_lock);
>>>> +
>>>> +	mpidr = decompress_mpidr(irq->mpidr);
>>>> +	mpidr = (mpidr & ~mask) | (val & mask);
>>>> +	irq->mpidr = compress_mpidr(mpidr);
>>>> +	irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, mpidr);
>>>
>>> this is weird because it doesn't preserve read-as-written semantics but
>>> allows a guest to write something into the RES0 field and read that back
>>> in the Aff3 field...
> 
> Technically Aff3 is not RES0, even if the A3V bit is cleared.
> The A3V bit just disables Aff3 on the CPU interface side, specifically
> for ICC_SGI0R_EL1 & friends.
> I think we agreed some time ago that we have to support read-as-written
> for this register and don't forward this IRQ if the MPIDR is not valid,
> as the spec demands.
> 
>> I don't see how we get this RES0/Aff3 mixup, but I can see other issues:
>>
>>>> +	unsigned long mask = 0xffffffff;	/* upper word is WI */
>>
>> followed by:
>>
>>>> +	mpidr = (mpidr & ~mask) | (val & mask);
>>
>> is not going to preserve the top bits on 32bit (assuming we could
>> perform a 64bit access on 32bit, but still).
> 
> Which would be fixed by making mask a u64?
> 
>> Also, the mask preserves
>> the IRM bit, which is wrong (we don't support 1-of-n distribution).
> 
> Agreed on this.
> 
>>
>> Why don't we just have
>>
>> 	mpidr = val & GENMASK_ULL(23, 0);
>>
>> and let's be done with it? I must be missing something about this whole
>> Aff3 thing...
> 
> Well, this would be a simple solution if we don't have to preserve bogus
> MPIDRs.
> The spec is a bit vague here:
> "For each interrupt, a GIC implementation might support fewer than 256
> values for an affinity level. In this case, some bits of the
> corresponding affinity level field might be RO."
> 
> Not sure if this can apply to _all_ bits of an affinity level or not.

I believe it does. Take GIC500 for example: it only implements Aff0
(only 8 cores) and Aff1 (32 clusters). Not even Aff2.

> I think the key question is: do we need to preserve any MPIDR value
> written into this register?

I can't see why. What's the point of storing something you can't even
address? Knowing the HW guys, they'd hate to have precious gates just to
serve as an external brain pack for the SW dudes.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From mmarek at suse.com  Thu May 12 07:22:26 2016
From: mmarek at suse.com (Michal Marek)
Date: Thu, 12 May 2016 16:22:26 +0200
Subject: [PATCH] deb-pkg: add the shared header file for arm64
In-Reply-To: <1463043837-4348-1-git-send-email-shijie.huang@arm.com>
References: <1463043837-4348-1-git-send-email-shijie.huang@arm.com>
Message-ID: <573491A2.7070809@suse.com>

On 2016-05-12 11:03, Huang Shijie wrote:
> The arch/arm/include/asm/opcodes.h is also used by the arm64.
> This patch copies it to the arm64 deb package.
> 
> Signed-off-by: Huang Shijie <shijie.huang at arm.com>
> ---
>  scripts/package/builddeb | 6 ++++++
>  1 file changed, 6 insertions(+)


Hi Huang,

this is fixed (admittedly in a more aggressive way) by 962475ac2f96
("builddeb: fix missing headers in linux-headers package") in linux-next.

Michal


From ynorov at caviumnetworks.com  Thu May 12 07:24:57 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 12 May 2016 17:24:57 +0300
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
 <20160512134431.GB30205@yury-N73SV>
 <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
Message-ID: <20160512142457.GC30205@yury-N73SV>

On Thu, May 12, 2016 at 03:07:35PM +0100, Catalin Marinas wrote:
> On Thu, May 12, 2016 at 04:44:31PM +0300, Yury Norov wrote:
> > On Thu, May 12, 2016 at 02:35:34PM +0100, Catalin Marinas wrote:
> > > On Thu, May 12, 2016 at 03:20:00AM +0300, Yury Norov wrote:
> > > > I debugged preadv02 and pwritev02 failures and found very weird bug.
> > > > Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> > > > of vector, and kernel reports successful read/write.
> > > > 
> > > > There are 2 problems:
> > > > 1. How kernel allows such address to be passed to fs subsystem;
> > > > 2. How fs successes to read/write at non-mapped, and in fact non-user
> > > > address.
> > > > 
> > > > I don't know the answer on 2'nd question, and it might be something
> > > > generic. But I investigated first problem.
> > > > 
> > > > The problem is that compat_rw_copy_check_uvector() uses access_ok() to
> > > > validate user address, and on arm64 it ends up with checking buffer
> > > > end against current_thread_info()->addr_limit.
> > > > 
> > > > current_thread_info()->addr_limit for ilp32, and most probably for
> > > > aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
> > > > It happens because on thread creation we call flush_old_exec() to set 
> > > > addr_limit, and completely ignore compat mode there.
> 
> [...]
> 
> > > > --- a/arch/arm64/kernel/binfmt_elf32.c
> > > > +++ b/arch/arm64/kernel/binfmt_elf32.c
> > > > @@ -12,6 +12,7 @@
> > > >  do {						\
> > > >  	clear_thread_flag(TIF_32BIT_AARCH64);	\
> > > >  	set_thread_flag(TIF_32BIT);		\
> > > > +	set_fs(TASK_SIZE_32);			\
> > > >  } while (0)
> > > >  
> > > >  #define COMPAT_ARCH_DLINFO
> > > > diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
> > > > index a934fd4..a8599c6 100644
> > > > --- a/arch/arm64/kernel/binfmt_ilp32.c
> > > > +++ b/arch/arm64/kernel/binfmt_ilp32.c
> > > > @@ -59,6 +59,7 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
> > > >  do {									\
> > > >  	set_thread_flag(TIF_32BIT_AARCH64);				\
> > > >  	clear_thread_flag(TIF_32BIT);					\
> > > > +	set_fs(TASK_SIZE_32);						\
> > > >  } while (0)
> > > 
> > > I don't think we need these two. AFAICT, flush_old_exec() takes care of
> > > setting the USER_DS for the new thread.
> > 
> > That's true, but USER_DS depends on personality which is not set yet
> > for new thread, as I wrote above. In fact, I tried correct USER_DS
> > only, and it doesn't work
> 
> Ah, it looks like load_elf_binary() sets the personality after
> flush_old_exec(). Looking at powerpc and x86, they set USER_DS to the
> maximum 64-bit task value, so they should have a similar issue with
> native 32-bit vs compat behaviour.

Hmmm. If so, it means we'd introduce generic fix. It would be removing 
set_fs() from flush_old_exec() and appending it to load_elf_binary()
after SET_PERSONALITY(). But I think it should be agreed with other
arches developers. I've sent standalone patch for aarch64 (you in CC)
so let's move discussion there.

> So what exactly is LTP complaining about? Is different error (like
> EFAULT vs EINVAL) or not getting an error at all.
 
It should be EINVAL, but it succeed. The other problem is that
following fs routines does not complain on wrong address.

> (I need to update my LTP, the preadv tests appeared in December last
> year)
> 

preadv02 was extended with this testcase in April.

> -- 
> Catalin


From robin.murphy at arm.com  Thu May 12 07:26:48 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 12 May 2016 15:26:48 +0100
Subject: [PATCH] arm64: Implement optimised IP checksum helpers
Message-ID: <6ca77904d1eced60d86145dc5da361f3aefc6fec.1463062758.git.robin.murphy@arm.com>

AArch64 is capable of 128-bit memory accesses without alignment
restrictions, which makes it both possible and highly practical to slurp
up a typical 20-byte IP header in just 2 loads. Implement our own
version of ip_fast_checksum() to take advantage of that, resulting in
considerably fewer instructions and memory accesses than the generic
version. We can also get more optimal code generation for csum_fold() by
defining it a slightly different way round from the generic version, so
throw that into the mix too.

Suggested-by: Luke Starrett <luke.starrett at broadcom.com>
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---

Having spent an evening poring over disassembler output, it turns out
that there's really no need to drop into asm for this, hurrah! I've
taken it for a spin on both big and little-endian, with no ill effects.

 arch/arm64/include/asm/checksum.h | 49 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)
 create mode 100644 arch/arm64/include/asm/checksum.h

diff --git a/arch/arm64/include/asm/checksum.h b/arch/arm64/include/asm/checksum.h
new file mode 100644
index 000000000000..7e975ffce837
--- /dev/null
+++ b/arch/arm64/include/asm/checksum.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_CHECKSUM_H
+#define __ASM_CHECKSUM_H
+
+static inline __sum16 csum_fold(__wsum csum)
+{
+	u32 sum = (__force u32)csum;
+	sum += (sum >> 16) | (sum << 16);
+	return ~(__force __sum16)(sum >> 16);
+}
+#define csum_fold csum_fold
+
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	__uint128_t tmp;
+	u64 sum;
+
+	tmp = *(const __uint128_t *)iph;
+	iph += 16;
+	ihl -= 4;
+	tmp += ((tmp >> 64) | (tmp << 64));
+	sum = tmp >> 64;
+	do {
+		sum += *(const u32 *)iph;
+		iph += 4;
+	} while (--ihl);
+
+	sum += ((sum >> 32) | (sum << 32));
+	return csum_fold(sum >> 32);
+}
+#define ip_fast_csum ip_fast_csum
+
+#include <asm-generic/checksum.h>
+
+#endif	/* __ASM_CHECKSUM_H */
-- 
2.8.1.dirty



From ynorov at caviumnetworks.com  Thu May 12 07:34:15 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 12 May 2016 17:34:15 +0300
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160512142016.GH11226@e104818-lin.cambridge.arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
 <20160512134431.GB30205@yury-N73SV>
 <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
 <20160512142016.GH11226@e104818-lin.cambridge.arm.com>
Message-ID: <20160512143415.GD30205@yury-N73SV>

On Thu, May 12, 2016 at 03:20:16PM +0100, Catalin Marinas wrote:
> On Thu, May 12, 2016 at 03:07:35PM +0100, Catalin Marinas wrote:
> > On Thu, May 12, 2016 at 04:44:31PM +0300, Yury Norov wrote:
> > > On Thu, May 12, 2016 at 02:35:34PM +0100, Catalin Marinas wrote:
> > > > On Thu, May 12, 2016 at 03:20:00AM +0300, Yury Norov wrote:
> > > > > I debugged preadv02 and pwritev02 failures and found very weird bug.
> > > > > Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> > > > > of vector, and kernel reports successful read/write.
> > > > > 
> > > > > There are 2 problems:
> > > > > 1. How kernel allows such address to be passed to fs subsystem;
> > > > > 2. How fs successes to read/write at non-mapped, and in fact non-user
> > > > > address.
> > > > > 
> > > > > I don't know the answer on 2'nd question, and it might be something
> > > > > generic. But I investigated first problem.
> > > > > 
> > > > > The problem is that compat_rw_copy_check_uvector() uses access_ok() to
> > > > > validate user address, and on arm64 it ends up with checking buffer
> > > > > end against current_thread_info()->addr_limit.
> > > > > 
> > > > > current_thread_info()->addr_limit for ilp32, and most probably for
> > > > > aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
> > > > > It happens because on thread creation we call flush_old_exec() to set 
> > > > > addr_limit, and completely ignore compat mode there.
> > 
> > [...]
> > 
> > > > > --- a/arch/arm64/kernel/binfmt_elf32.c
> > > > > +++ b/arch/arm64/kernel/binfmt_elf32.c
> > > > > @@ -12,6 +12,7 @@
> > > > >  do {						\
> > > > >  	clear_thread_flag(TIF_32BIT_AARCH64);	\
> > > > >  	set_thread_flag(TIF_32BIT);		\
> > > > > +	set_fs(TASK_SIZE_32);			\
> > > > >  } while (0)
> > > > >  
> > > > >  #define COMPAT_ARCH_DLINFO
> > > > > diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
> > > > > index a934fd4..a8599c6 100644
> > > > > --- a/arch/arm64/kernel/binfmt_ilp32.c
> > > > > +++ b/arch/arm64/kernel/binfmt_ilp32.c
> > > > > @@ -59,6 +59,7 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
> > > > >  do {									\
> > > > >  	set_thread_flag(TIF_32BIT_AARCH64);				\
> > > > >  	clear_thread_flag(TIF_32BIT);					\
> > > > > +	set_fs(TASK_SIZE_32);						\
> > > > >  } while (0)
> > > > 
> > > > I don't think we need these two. AFAICT, flush_old_exec() takes care of
> > > > setting the USER_DS for the new thread.
> > > 
> > > That's true, but USER_DS depends on personality which is not set yet
> > > for new thread, as I wrote above. In fact, I tried correct USER_DS
> > > only, and it doesn't work
> > 
> > Ah, it looks like load_elf_binary() sets the personality after
> > flush_old_exec(). Looking at powerpc and x86, they set USER_DS to the
> > maximum 64-bit task value, so they should have a similar issue with
> > native 32-bit vs compat behaviour.
> 
> I think we have another problem. flush_old_exec() calls the arm64
> flush_thread() where tls_thread_flush() checks for is_compat_task(). So
> starting a 32-bit application from a 64-bit one not go on the correct
> path.

As per now, all native, aarch32 and ilp32 tasks can exec() any
binaries they need. Are you think it's wrong? If so, how we coild run
first compat application (maybe shell), it there are only lp64 tasks
on the system?

> 
> -- 
> Catalin


From kernel at martin.sperl.org  Thu May 12 07:35:34 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu, 12 May 2016 14:35:34 +0000
Subject: [PATCH 0/4] bcm2835: add thermal driver
Message-ID: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add thermal driver for the bcm2835 SOC.

Right now this driver does not set up the thermal device
itself, but relies on the fact that the firmware is setting
the device up correctly.

Also it is currently only reading from the register-set.

The driver also exposes the registers via debugfs.

Martin Sperl (4):
  dt: bindings: add thermal device driver for bcm2835
  thermal: bcm2835: add thermal driver for bcm2835 soc
  ARM: bcm2835: add thermal node to device-tree of bcm283x
  ARM: bcm2835: add thermal driver to default_config

 .../bindings/thermal/bcm2835-thermal.txt           |  16 ++
 arch/arm/boot/dts/bcm283x.dtsi                     |   6 +
 arch/arm/configs/bcm2835_defconfig                 |   2 +
 drivers/thermal/Kconfig                            |   5 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/bcm/Kconfig                        |   4 +
 drivers/thermal/bcm/Makefile                       |   1 +
 drivers/thermal/bcm/bcm2835_thermal.c              | 205 +++++++++++++++++++++
 8 files changed, 240 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/bcm2835-thermal.txt
 create mode 100644 drivers/thermal/bcm/Kconfig
 create mode 100644 drivers/thermal/bcm/Makefile
 create mode 100644 drivers/thermal/bcm/bcm2835_thermal.c

--
2.1.4


From kernel at martin.sperl.org  Thu May 12 07:35:35 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu, 12 May 2016 14:35:35 +0000
Subject: [PATCH 1/4] dt: bindings: add thermal device driver for bcm2835
In-Reply-To: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
References: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463063738-11506-2-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add documentation for bcm2835 SOC thermal sensor.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 .../devicetree/bindings/thermal/bcm2835-thermal.txt      | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/bcm2835-thermal.txt

diff --git a/Documentation/devicetree/bindings/thermal/bcm2835-thermal.txt b/Documentation/devicetree/bindings/thermal/bcm2835-thermal.txt
new file mode 100644
index 0000000..607519a
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/bcm2835-thermal.txt
@@ -0,0 +1,16 @@
+Binding for Thermal Sensor driver for BCM2835 SoCs.
+
+Required parameters:
+-------------------
+
+compatible : 	should be: "brcm,bcm2835-thermal"
+reg :		Address range of the thermal registers.
+clocks : 	Phandle of the clock used by the thermal sensor.
+
+Example:
+
+thermal: thermal at 0x7e212000 {
+	compatible = "brcm,bcm2835-thermal";
+	reg = <0x7e212000 0x8>;
+	clocks = <&clocks BCM2835_CLOCK_TSENS>;
+};
-- 
2.1.4



From kernel at martin.sperl.org  Thu May 12 07:35:36 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu, 12 May 2016 14:35:36 +0000
Subject: [PATCH 2/4] thermal: bcm2835: add thermal driver for bcm2835 soc
In-Reply-To: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
References: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463063738-11506-3-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add basic thermal driver for bcm2835 SOC.

This driver currently relies on the firmware setting up the
tsense HW block and does not set it up itself.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 drivers/thermal/Kconfig               |   5 +
 drivers/thermal/Makefile              |   1 +
 drivers/thermal/bcm/Kconfig           |   4 +
 drivers/thermal/bcm/Makefile          |   1 +
 drivers/thermal/bcm/bcm2835_thermal.c | 205 ++++++++++++++++++++++++++++++++++
 5 files changed, 216 insertions(+)
 create mode 100644 drivers/thermal/bcm/Kconfig
 create mode 100644 drivers/thermal/bcm/Makefile
 create mode 100644 drivers/thermal/bcm/bcm2835_thermal.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index c37eedc..10f92c6 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -381,6 +381,11 @@ config MTK_THERMAL
 	  Enable this option if you want to have support for thermal management
 	  controller present in Mediatek SoCs
 
+menu "Broadcom thermal drivers"
+depends on ARCH_BCM || COMPILE_TEST
+source "drivers/thermal/bcm/Kconfig"
+endmenu
+
 menu "Texas Instruments thermal drivers"
 depends on ARCH_HAS_BANDGAP || COMPILE_TEST
 depends on HAS_IOMEM
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 8e9cbc3..6df1aa3 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -49,3 +49,4 @@ obj-$(CONFIG_ST_THERMAL)	+= st/
 obj-$(CONFIG_TEGRA_SOCTHERM)	+= tegra_soctherm.o
 obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
 obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
+obj-y				+= bcm/
diff --git a/drivers/thermal/bcm/Kconfig b/drivers/thermal/bcm/Kconfig
new file mode 100644
index 0000000..62245ae
--- /dev/null
+++ b/drivers/thermal/bcm/Kconfig
@@ -0,0 +1,4 @@
+config BCM2835_THERMAL
+       tristate "Thermal sensors on bcm2835 SoC"
+       help
+         Support for thermal sensors on Broadcom bcm2835 SoCs.
diff --git a/drivers/thermal/bcm/Makefile b/drivers/thermal/bcm/Makefile
new file mode 100644
index 0000000..13456d2
--- /dev/null
+++ b/drivers/thermal/bcm/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_BCM2835_THERMAL)		:= bcm2835_thermal.o
diff --git a/drivers/thermal/bcm/bcm2835_thermal.c b/drivers/thermal/bcm/bcm2835_thermal.c
new file mode 100644
index 0000000..a1fdc84
--- /dev/null
+++ b/drivers/thermal/bcm/bcm2835_thermal.c
@@ -0,0 +1,205 @@
+/*
+ * Driver for Broadcom BCM2835 soc temperature sensor
+ *
+ * Copyright (C) 2015 Martin Sperl
+ *
+ * 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.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+
+#define BCM2835_TS_TSENSCTL			0x00
+#define BCM2835_TS_TSENSSTAT			0x04
+
+#define BCM2835_TS_TSENSCTL_PRWDW		BIT(0)
+#define BCM2835_TS_TSENSCTL_RSTB		BIT(1)
+#define BCM2835_TS_TSENSCTL_CTRL		BIT(0)
+#define BCM2835_TS_TSENSCTL_EN_INT		BIT(0)
+#define BCM2835_TS_TSENSCTL_DIRECT		BIT(0)
+#define BCM2835_TS_TSENSCTL_CLR_INT		BIT(0)
+#define BCM2835_TS_TSENSCTL_THOLD_SHIFT		8
+#define BCM2835_TS_TSENSCTL_THOLD_BITS		10
+#define BCM2835_TS_TSENSCTL_THOLD_MASK		     \
+	GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS +     \
+		BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \
+		BCM2835_TS_TSENSCTL_THOLD_SHIFT)
+#define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT	18
+#define BCM2835_TS_TSENSCTL_RSTDELAY_BITS	8
+#define BCM2835_TS_TSENSCTL_REGULEN		BIT(26)
+
+#define BCM2835_TS_TSENSSTAT_DATA_BITS		10
+#define BCM2835_TS_TSENSSTAT_DATA_SHIFT		0
+#define BCM2835_TS_TSENSSTAT_DATA_MASK		     \
+	GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS +     \
+		BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \
+		BCM2835_TS_TSENSSTAT_DATA_SHIFT)
+#define BCM2835_TS_TSENSSTAT_VALID		BIT(10)
+#define BCM2835_TS_TSENSSTAT_INTERRUPT		BIT(11)
+
+/* empirical linear approximation for conversion to temperature */
+#define BCM2835_TS_VALUE_OFFSET			407000
+#define BCM2835_TS_VALUE_SLOPE			-538
+
+struct bcm2835_thermal_data {
+	void __iomem *regs;
+	struct clk *clk;
+	struct dentry *debugfsdir;
+};
+
+static int bcm2835_thermal_get_temp(struct thermal_zone_device *tz,
+				    int *temp)
+{
+	struct bcm2835_thermal_data *data = tz->devdata;
+	u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT);
+
+	/* mask the relevant bits */
+	val &= BCM2835_TS_TSENSSTAT_DATA_MASK;
+
+	/* linear approximation */
+	*temp = BCM2835_TS_VALUE_OFFSET +
+		(val * BCM2835_TS_VALUE_SLOPE);
+
+	return 0;
+}
+
+static const struct debugfs_reg32 bcm2835_thermal_regs[] = {
+	{
+		.name = "ctl",
+		.offset = 0
+	},
+	{
+		.name = "stat",
+		.offset = 4
+	}
+};
+
+static void bcm2835_thermal_debugfs(struct platform_device *pdev)
+{
+	struct thermal_zone_device *tz = platform_get_drvdata(pdev);
+	struct bcm2835_thermal_data *data = tz->devdata;
+	struct debugfs_regset32 *regset;
+
+	data->debugfsdir = debugfs_create_dir("bcm2835_thermal", NULL);
+	if (!data->debugfsdir)
+		return;
+
+	regset = devm_kzalloc(&pdev->dev, sizeof(*regset), GFP_KERNEL);
+	if (!regset)
+		return;
+
+	regset->regs = bcm2835_thermal_regs;
+	regset->nregs = ARRAY_SIZE(bcm2835_thermal_regs);
+	regset->base = data->regs;
+
+	debugfs_create_regset32("regset", S_IRUGO,
+				data->debugfsdir, regset);
+}
+
+static struct thermal_zone_device_ops bcm2835_thermal_ops  = {
+	.get_temp = bcm2835_thermal_get_temp,
+};
+
+static int bcm2835_thermal_probe(struct platform_device *pdev)
+{
+	struct thermal_zone_device *tz;
+	struct bcm2835_thermal_data *data;
+	struct resource *res;
+	int err;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	/* get registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(data->regs)) {
+		err = PTR_ERR(data->regs);
+		dev_err(&pdev->dev, "Could not get registers: %d\n", err);
+		return err;
+	}
+
+	/* get clock */
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk)) {
+		err = PTR_ERR(data->clk);
+		if (err != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Could not get clk: %d\n", err);
+		return err;
+	}
+
+	/*
+	 * for now we assume the firmware sets up the device,
+	 * so we will not write to ctl, we just prepare the clock
+	 */
+	clk_prepare_enable(data->clk);
+
+	/* register it */
+	tz = thermal_zone_device_register("bcm2835_thermal",
+					  0, 0, data,
+					  &bcm2835_thermal_ops,
+					  NULL, 0, 0);
+	if (IS_ERR(tz)) {
+		clk_disable_unprepare(data->clk);
+		err = PTR_ERR(tz);
+		dev_err(&pdev->dev,
+			"Failed to register the thermal device: %d\n",
+			err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, tz);
+
+	bcm2835_thermal_debugfs(pdev);
+
+	return 0;
+}
+
+static int bcm2835_thermal_remove(struct platform_device *pdev)
+{
+	struct thermal_zone_device *tz = platform_get_drvdata(pdev);
+	struct bcm2835_thermal_data *data = tz->devdata;
+
+	debugfs_remove_recursive(data->debugfsdir);
+	thermal_zone_device_unregister(tz);
+
+	return 0;
+}
+
+static const struct of_device_id bcm2835_thermal_of_match_table[] = {
+	{ .compatible = "brcm,bcm2835-thermal", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);
+
+static struct platform_driver bcm2835_thermal_driver = {
+	.probe = bcm2835_thermal_probe,
+	.remove = bcm2835_thermal_remove,
+	.driver = {
+		.name = "bcm2835_thermal",
+		.of_match_table = bcm2835_thermal_of_match_table,
+	},
+};
+module_platform_driver(bcm2835_thermal_driver);
+
+MODULE_AUTHOR("Martin Sperl");
+MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");
+MODULE_LICENSE("GPL");
-- 
2.1.4



From kernel at martin.sperl.org  Thu May 12 07:35:37 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu, 12 May 2016 14:35:37 +0000
Subject: [PATCH 3/4] ARM: bcm2835: add thermal node to device-tree of bcm283x
In-Reply-To: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
References: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463063738-11506-4-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add the node for the thermal sensor of the bcm2835-soc
to the device tree.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 arch/arm/boot/dts/bcm283x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index 9db9d97..525f1f2 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
+++ b/arch/arm/boot/dts/bcm283x.dtsi
@@ -159,6 +159,12 @@
 			status = "disabled";
 		};
 
+		thermal: thermal at 0x7e212000 {
+			compatible = "brcm,bcm2835-thermal";
+			reg = <0x7e212000 0x8>;
+			clocks = <&clocks BCM2835_CLOCK_TSENS>;
+		};
+
 		aux: aux at 0x7e215000 {
 			compatible = "brcm,bcm2835-aux";
 			#clock-cells = <1>;
-- 
2.1.4



From kernel at martin.sperl.org  Thu May 12 07:35:38 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Thu, 12 May 2016 14:35:38 +0000
Subject: [PATCH 4/4] ARM: bcm2835: add thermal driver to default_config
In-Reply-To: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
References: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463063738-11506-5-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add the thermal driver to list of compiled modules
in the default config for bcm2835.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 arch/arm/configs/bcm2835_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index 29a44bd..634e07e 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -71,6 +71,8 @@ CONFIG_SPI_BCM2835=y
 CONFIG_SPI_BCM2835AUX=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_BCM2835_THERMAL=y
 CONFIG_WATCHDOG=y
 CONFIG_BCM2835_WDT=y
 CONFIG_FB=y
-- 
2.1.4



From joel at jms.id.au  Thu May 12 07:43:11 2016
From: joel at jms.id.au (Joel Stanley)
Date: Fri, 13 May 2016 00:13:11 +0930
Subject: [PATCH v3 0/2] irqchip: Support Aspeed IRQ controller
In-Reply-To: <1462802317-27086-1-git-send-email-joel@jms.id.au>
References: <1462802317-27086-1-git-send-email-joel@jms.id.au>
Message-ID: <1463064193-2178-1-git-send-email-joel@jms.id.au>

Hello All,

This adds support for the IRQ controller found in the Aspeed ast2400 and
ast2500 BMC SoCs.

It's been tested on the ast2400 in an OpenPower Palmetto system, and on the
ast2500-edk developer kit.

V2 has a fix for the compatible string in the device tree bindings.

V3 drops the valid-sources bitmasks and adds a unit address to the example in
the bindings

Cheers,

Joel

Benjamin Herrenschmidt (1):
  irqchip: Add irq controller for Aspeed

Joel Stanley (1):
  doc/devicetree: Add Aspeed VIC bindings

 .../interrupt-controller/aspeed,ast2400-vic.txt    |  22 ++
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-aspeed-vic.c                   | 230 +++++++++++++++++++++
 3 files changed, 253 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
 create mode 100644 drivers/irqchip/irq-aspeed-vic.c

-- 
2.8.1



From joel at jms.id.au  Thu May 12 07:43:12 2016
From: joel at jms.id.au (Joel Stanley)
Date: Fri, 13 May 2016 00:13:12 +0930
Subject: [PATCH v3 1/2] doc/devicetree: Add Aspeed VIC bindings
In-Reply-To: <1463064193-2178-1-git-send-email-joel@jms.id.au>
References: <1462802317-27086-1-git-send-email-joel@jms.id.au>
 <1463064193-2178-1-git-send-email-joel@jms.id.au>
Message-ID: <1463064193-2178-2-git-send-email-joel@jms.id.au>

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 .../interrupt-controller/aspeed,ast2400-vic.txt    | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
new file mode 100644
index 000000000000..6c6e85324b9d
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
@@ -0,0 +1,22 @@
+Aspeed Vectored Interrupt Controller
+
+These bindings are for the Aspeed AST2400 interrupt controller register layout.
+The SoC has an legacy register layout, but this driver does not support that
+mode of operation.
+
+Required properties:
+
+- compatible : should be "aspeed,ast2400-vic".
+
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+
+Example:
+
+ vic: interrupt-controller at 1e6c0080 {
+      compatible = "aspeed,ast2400-vic";
+      interrupt-controller;
+      #interrupt-cells = <1>;
+      reg = <0x1e6c0080 0x80>;
+ };
-- 
2.8.1



From joel at jms.id.au  Thu May 12 07:43:13 2016
From: joel at jms.id.au (Joel Stanley)
Date: Fri, 13 May 2016 00:13:13 +0930
Subject: [PATCH v3 2/2] irqchip: Add irq controller for Aspeed
In-Reply-To: <1463064193-2178-1-git-send-email-joel@jms.id.au>
References: <1462802317-27086-1-git-send-email-joel@jms.id.au>
 <1463064193-2178-1-git-send-email-joel@jms.id.au>
Message-ID: <1463064193-2178-3-git-send-email-joel@jms.id.au>

From: Benjamin Herrenschmidt <benh at kernel.crashing.org>

Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/irqchip/Makefile         |   1 +
 drivers/irqchip/irq-aspeed-vic.c | 230 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 231 insertions(+)
 create mode 100644 drivers/irqchip/irq-aspeed-vic.c

diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index b03cfcbbac6b..ec82e6e15a38 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -65,3 +65,4 @@ obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
 obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
 obj-$(CONFIG_PIC32_EVIC)		+= irq-pic32-evic.o
 obj-$(CONFIG_MVEBU_ODMI)		+= irq-mvebu-odmi.o
+obj-$(CONFIG_ARCH_ASPEED)		+= irq-aspeed-vic.o
diff --git a/drivers/irqchip/irq-aspeed-vic.c b/drivers/irqchip/irq-aspeed-vic.c
new file mode 100644
index 000000000000..d24451d5bf8a
--- /dev/null
+++ b/drivers/irqchip/irq-aspeed-vic.c
@@ -0,0 +1,230 @@
+/*
+ *  Copyright (C) 2015 - Ben Herrenschmidt, IBM Corp.
+ *
+ *  Driver for Aspeed "new" VIC as found in SoC generation 3 and later
+ *
+ *  Based on irq-vic.c:
+ *
+ *  Copyright (C) 1999 - 2003 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * 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/export.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/syscore_ops.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+
+#include <asm/exception.h>
+#include <asm/irq.h>
+
+/* These definitions correspond to the "new mapping" of the
+ * register set that interleaves "high" and "low". The offsets
+ * below are for the "low" register, add 4 to get to the high one
+ */
+#define AVIC_IRQ_STATUS		0x00
+#define AVIC_FIQ_STATUS		0x08
+#define AVIC_RAW_STATUS		0x10
+#define AVIC_INT_SELECT		0x18
+#define AVIC_INT_ENABLE		0x20
+#define AVIC_INT_ENABLE_CLR	0x28
+#define AVIC_INT_TRIGGER	0x30
+#define AVIC_INT_TRIGGER_CLR	0x38
+#define AVIC_INT_SENSE		0x40
+#define AVIC_INT_DUAL_EDGE	0x48
+#define AVIC_INT_EVENT		0x50
+#define AVIC_EDGE_CLR		0x58
+#define AVIC_EDGE_STATUS	0x60
+
+#define NUM_IRQS		64
+
+struct aspeed_vic {
+	void __iomem		*base;
+	u32			edge_sources[2];
+	struct irq_domain	*dom;
+};
+static struct aspeed_vic *system_avic;
+
+static void vic_init_hw(struct aspeed_vic *vic)
+{
+	u32 sense;
+
+	/* Disable all interrupts */
+	writel(0xffffffff, vic->base + AVIC_INT_ENABLE_CLR);
+	writel(0xffffffff, vic->base + AVIC_INT_ENABLE_CLR + 4);
+
+	/* Make sure no soft trigger is on */
+	writel(0xffffffff, vic->base + AVIC_INT_TRIGGER_CLR);
+	writel(0xffffffff, vic->base + AVIC_INT_TRIGGER_CLR + 4);
+
+	/* Set everything to be IRQ */
+	writel(0, vic->base + AVIC_INT_SELECT);
+	writel(0, vic->base + AVIC_INT_SELECT + 4);
+
+	/* Some interrupts have a programable high/low level trigger
+	 * (4 GPIO direct inputs), for now we assume this was configured
+	 * by firmware. We read which ones are edge now.
+	 */
+	sense = readl(vic->base + AVIC_INT_SENSE);
+	vic->edge_sources[0] = ~sense;
+	sense = readl(vic->base + AVIC_INT_SENSE + 4);
+	vic->edge_sources[1] = ~sense;
+
+	/* Clear edge detection latches */
+	writel(0xffffffff, vic->base + AVIC_EDGE_CLR);
+	writel(0xffffffff, vic->base + AVIC_EDGE_CLR + 4);
+}
+
+static void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
+{
+	struct aspeed_vic *vic = system_avic;
+	u32 stat, irq;
+
+	for (;;) {
+		irq = 0;
+		stat = readl_relaxed(vic->base + AVIC_IRQ_STATUS);
+		if (!stat) {
+			stat = readl_relaxed(vic->base + AVIC_IRQ_STATUS + 4);
+			irq = 32;
+		}
+		if (stat == 0)
+			break;
+		irq += ffs(stat) - 1;
+		handle_domain_irq(vic->dom, irq, regs);
+	}
+}
+
+static void avic_ack_irq(struct irq_data *d)
+{
+	struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+	unsigned int sidx = d->hwirq >> 5;
+	unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+	/* Clear edge latch for edge interrupts, nop for level */
+	if (vic->edge_sources[sidx] & sbit)
+		writel(sbit, vic->base + AVIC_EDGE_CLR + sidx * 4);
+}
+
+static void avic_mask_irq(struct irq_data *d)
+{
+	struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+	unsigned int sidx = d->hwirq >> 5;
+	unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+	writel(sbit, vic->base + AVIC_INT_ENABLE_CLR + sidx * 4);
+}
+
+static void avic_unmask_irq(struct irq_data *d)
+{
+	struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+	unsigned int sidx = d->hwirq >> 5;
+	unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+	writel(sbit, vic->base + AVIC_INT_ENABLE + sidx * 4);
+}
+
+/* For level irq, faster than going through a nop "ack" and mask */
+static void avic_mask_ack_irq(struct irq_data *d)
+{
+	struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+	unsigned int sidx = d->hwirq >> 5;
+	unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+	/* First mask */
+	writel(sbit, vic->base + AVIC_INT_ENABLE_CLR + sidx * 4);
+
+	/* Then clear edge latch for edge interrupts */
+	if (vic->edge_sources[sidx] & sbit)
+		writel(sbit, vic->base + AVIC_EDGE_CLR + sidx * 4);
+}
+
+static struct irq_chip avic_chip = {
+	.name		= "AVIC",
+	.irq_ack	= avic_ack_irq,
+	.irq_mask	= avic_mask_irq,
+	.irq_unmask	= avic_unmask_irq,
+	.irq_mask_ack	= avic_mask_ack_irq,
+};
+
+static int avic_map(struct irq_domain *d, unsigned int irq,
+		    irq_hw_number_t hwirq)
+{
+	struct aspeed_vic *vic = d->host_data;
+	unsigned int sidx = hwirq >> 5;
+	unsigned int sbit = 1u << (hwirq & 0x1f);
+
+	/* Check if interrupt exists */
+	if (sidx > 1)
+		return -EPERM;
+
+	if (vic->edge_sources[sidx] & sbit)
+		irq_set_chip_and_handler(irq, &avic_chip, handle_edge_irq);
+	else
+		irq_set_chip_and_handler(irq, &avic_chip, handle_level_irq);
+	irq_set_chip_data(irq, vic);
+	irq_set_probe(irq);
+	return 0;
+}
+
+static struct irq_domain_ops avic_dom_ops = {
+	.map = avic_map,
+	.xlate = irq_domain_xlate_onetwocell,
+};
+
+static int __init avic_of_init(struct device_node *node,
+			       struct device_node *parent)
+{
+	void __iomem *regs;
+	struct aspeed_vic *vic;
+
+	if (WARN(parent, "non-root Aspeed VIC not supported"))
+		return -EINVAL;
+	if (WARN(system_avic, "duplicate Aspeed VIC not supported"))
+		return -EINVAL;
+
+	regs = of_iomap(node, 0);
+	if (WARN_ON(!regs))
+		return -EIO;
+
+	vic = kzalloc(sizeof(struct aspeed_vic), GFP_KERNEL);
+	if (WARN_ON(!vic)) {
+		iounmap(regs);
+		return -ENOMEM;
+	}
+	vic->base = regs;
+
+	/* Initialize soures, all masked */
+	vic_init_hw(vic);
+
+	/* Ready to receive interrupts */
+	system_avic = vic;
+	set_handle_irq(avic_handle_irq);
+
+	/* Register our domain */
+	vic->dom = irq_domain_add_simple(node, NUM_IRQS, 0,
+					 &avic_dom_ops, vic);
+
+	return 0;
+}
+
+IRQCHIP_DECLARE(aspeed_new_vic, "aspeed,ast2400-vic", avic_of_init);
-- 
2.8.1



From patrice.chotard at st.com  Thu May 12 07:46:35 2016
From: patrice.chotard at st.com (patrice.chotard at st.com)
Date: Thu, 12 May 2016 16:46:35 +0200
Subject: [PATCH 2/2] pinctrl: stm32: factorize stm32_pconf_input/output_get()
In-Reply-To: <1463064395-4669-1-git-send-email-patrice.chotard@st.com>
References: <1463064395-4669-1-git-send-email-patrice.chotard@st.com>
Message-ID: <1463064395-4669-3-git-send-email-patrice.chotard@st.com>

From: Patrice Chotard <patrice.chotard at st.com>

As these 2 functions code are 95% similar, factorize them.

Signed-off-by: Patrice Chotard <patrice.chotard at st.com>
---
 drivers/pinctrl/stm32/pinctrl-stm32.c | 31 ++++++++++---------------------
 1 file changed, 10 insertions(+), 21 deletions(-)

diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index 249da52..8b82d3e 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -661,8 +661,8 @@ static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank,
 	return (val >> (offset * 2));
 }
 
-static bool stm32_pconf_input_get(struct stm32_gpio_bank *bank,
-	unsigned int offset)
+static bool stm32_pconf_get(struct stm32_gpio_bank *bank,
+	unsigned int offset, bool dir)
 {
 	unsigned long flags;
 	u32 val;
@@ -670,23 +670,12 @@ static bool stm32_pconf_input_get(struct stm32_gpio_bank *bank,
 	clk_enable(bank->clk);
 	spin_lock_irqsave(&bank->lock, flags);
 
-	val = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset));
-
-	spin_unlock_irqrestore(&bank->lock, flags);
-	clk_disable(bank->clk);
-
-	return val;
-}
-
-static bool stm32_pconf_output_get(struct stm32_gpio_bank *bank,
-	unsigned int offset)
-{
-	unsigned long flags;
-	u32 val;
-
-	clk_enable(bank->clk);
-	spin_lock_irqsave(&bank->lock, flags);
-	val = !!(readl_relaxed(bank->base + STM32_GPIO_ODR) & BIT(offset));
+	if (dir)
+		val = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) &
+			 BIT(offset));
+	else
+		val = !!(readl_relaxed(bank->base + STM32_GPIO_ODR) &
+			 BIT(offset));
 
 	spin_unlock_irqrestore(&bank->lock, flags);
 	clk_disable(bank->clk);
@@ -795,7 +784,7 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
 	switch (mode) {
 	/* input */
 	case 0:
-		val = stm32_pconf_input_get(bank, offset);
+		val = stm32_pconf_get(bank, offset, true);
 		seq_printf(s, "- %s - %s",
 			   val ? "high" : "low",
 			   biasing[bias]);
@@ -805,7 +794,7 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
 	case 1:
 		drive = stm32_pconf_get_driving(bank, offset);
 		speed = stm32_pconf_get_speed(bank, offset);
-		val = stm32_pconf_output_get(bank, offset);
+		val = stm32_pconf_get(bank, offset, false);
 		seq_printf(s, "- %s - %s - %s - %s speed",
 			   val ? "high" : "low",
 			   drive ? "open drain" : "push pull",
-- 
1.9.1



From patrice.chotard at st.com  Thu May 12 07:46:33 2016
From: patrice.chotard at st.com (patrice.chotard at st.com)
Date: Thu, 12 May 2016 16:46:33 +0200
Subject: [PATCH 0/2] pinctrl: stm32: .pin_config_dbg_show fixes
Message-ID: <1463064395-4669-1-git-send-email-patrice.chotard@st.com>

From: Patrice Chotard <patrice.chotard at st.com>

Patrice Chotard (2):
  pinctrl: stm32: fix warning
  pinctrl: stm32: factorize stm32_pconf_input/output_get()

 drivers/pinctrl/stm32/pinctrl-stm32.c | 39 +++++++++++++----------------------
 1 file changed, 14 insertions(+), 25 deletions(-)

-- 
1.9.1



From patrice.chotard at st.com  Thu May 12 07:46:34 2016
From: patrice.chotard at st.com (patrice.chotard at st.com)
Date: Thu, 12 May 2016 16:46:34 +0200
Subject: [PATCH 1/2] pinctrl: stm32: fix warning
In-Reply-To: <1463064395-4669-1-git-send-email-patrice.chotard@st.com>
References: <1463064395-4669-1-git-send-email-patrice.chotard@st.com>
Message-ID: <1463064395-4669-2-git-send-email-patrice.chotard@st.com>

From: Patrice Chotard <patrice.chotard at st.com>

fix compilation warning :
drivers/pinctrl/stm32/pinctrl-stm32.c:823:7: warning: too many arguments for format [-Wformat-extra-args]
           speeds[speed], "speed");

Signed-off-by: Patrice Chotard <patrice.chotard at st.com>
---
 drivers/pinctrl/stm32/pinctrl-stm32.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index 1527740..249da52 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -806,21 +806,21 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
 		drive = stm32_pconf_get_driving(bank, offset);
 		speed = stm32_pconf_get_speed(bank, offset);
 		val = stm32_pconf_output_get(bank, offset);
-		seq_printf(s, "- %s - %s - %s - %s %s",
+		seq_printf(s, "- %s - %s - %s - %s speed",
 			   val ? "high" : "low",
 			   drive ? "open drain" : "push pull",
 			   biasing[bias],
-			   speeds[speed], "speed");
+			   speeds[speed]);
 		break;
 
 	/* alternate */
 	case 2:
 		drive = stm32_pconf_get_driving(bank, offset);
 		speed = stm32_pconf_get_speed(bank, offset);
-		seq_printf(s, "%d - %s -%s", alt,
+		seq_printf(s, "%d - %s -%s - %s speed", alt,
 			   drive ? "open drain" : "push pull",
 			   biasing[bias],
-			   speeds[speed], "speed");
+			   speeds[speed]);
 		break;
 
 	/* analog */
-- 
1.9.1



From patrice.chotard at st.com  Thu May 12 07:47:22 2016
From: patrice.chotard at st.com (Patrice Chotard)
Date: Thu, 12 May 2016 16:47:22 +0200
Subject: [PATCH] pinctrl: stm32: Implement .pin_config_dbg_show()
In-Reply-To: <CACRpkdawoqfqN8YeojyrzPru2fwrFMidc1e2v7yxHRpPf+rK6w@mail.gmail.com>
References: <1461939943-24752-1-git-send-email-patrice.chotard@st.com>
 <CACRpkdZ=KsPL1mBS1bLi=jYsv=Vb1QNBi8XPAJW50doPcwBuZg@mail.gmail.com>
 <5733364A.3090606@st.com>
 <CACRpkdawoqfqN8YeojyrzPru2fwrFMidc1e2v7yxHRpPf+rK6w@mail.gmail.com>
Message-ID: <5734977A.1090409@st.com>



On 05/12/2016 03:40 PM, Linus Walleij wrote:
> On Wed, May 11, 2016 at 3:40 PM, Patrice Chotard <patrice.chotard at st.com> wrote:
>> On 05/10/2016 01:50 PM, Linus Walleij wrote:
>> Sorry i didn't pay attention, but there is a compilation warning in this
>> patch.
>>
>> drivers/pinctrl/stm32/pinctrl-stm32.c:823:7: warning: too many arguments for
>> format [-Wformat-extra-args]
>>         speeds[speed], "speed");
>>
>>
>> What do you prefer ?
>>   _ me to submit a v2 fixing this warning and at the same occasion include
>> the requested code factorization
>>   _ or submit additionnal patchset ?
> Just send a patch on top fixing this.

Series just send

Thanks
Patrice

>
> Yours,
> Linus Walleij



From stefan.wahren at i2se.com  Thu May 12 07:50:54 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Thu, 12 May 2016 16:50:54 +0200 (CEST)
Subject: [PATCH 0/4] add minimal bcm2835-sdram driver
In-Reply-To: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1861597197.20753.36a104a6-5284-487f-b397-da7ff0407f1f.open-xchange@email.1und1.de>

Hi Martin,

> kernel at martin.sperl.org hat am 12. Mai 2016 um 14:38 geschrieben:
> 
> 
> From: Martin Sperl <kernel at martin.sperl.org>
> 
> As the sdram clock is a critical clock to the system
> the minimal bcm2835-sdram driver claims (and enables)
> this clock and also exposes the corresponding sdram
> registers via debugfs.

sounds like this driver should fix an clock handling issue. Unfortunately this
isn't a solution in case the driver is disabled.

Does the GPU firmware handle the SDRAM controller or is it initialized by
bootcode?

Stefan


From james.morse at arm.com  Thu May 12 07:49:30 2016
From: james.morse at arm.com (James Morse)
Date: Thu, 12 May 2016 15:49:30 +0100
Subject: [PATCH v12 06/10] arm64: Treat all entry code as non-kprobe-able
In-Reply-To: <1461783185-9056-7-git-send-email-dave.long@linaro.org>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-7-git-send-email-dave.long@linaro.org>
Message-ID: <573497FA.5030309@arm.com>

Hi David, Pratyush

On 27/04/16 19:53, David Long wrote:
> From: Pratyush Anand <panand at redhat.com>
> 
> Entry symbols are not kprobe safe. So blacklist them for kprobing.
> 
> Signed-off-by: Pratyush Anand <panand at redhat.com>

> diff --git a/arch/arm64/kernel/kprobes.c b/arch/arm64/kernel/kprobes.c
> index dfa1b1f..6a1292b 100644
> --- a/arch/arm64/kernel/kprobes.c
> +++ b/arch/arm64/kernel/kprobes.c
> @@ -29,6 +29,7 @@
>  #include <asm/system_misc.h>
>  #include <asm/insn.h>
>  #include <asm/uaccess.h>
> +#include <asm-generic/sections.h>
>  
>  #include "kprobes-arm64.h"
>  
> @@ -514,6 +515,15 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
>  	return 1;
>  }
>  
> +bool arch_within_kprobe_blacklist(unsigned long addr)
> +{
> +	return  (addr >= (unsigned long)__kprobes_text_start &&
> +		 addr < (unsigned long)__kprobes_text_end) ||
> +		(addr >= (unsigned long)__entry_text_start &&
> +		 addr < (unsigned long)__entry_text_end) ||
> +		 !!search_exception_tables(addr);
> +}
> +

Looking at __kvm_hyp_vector, we don't have support for handling breakpoints at
EL2, so we should forbid kprobing these address ranges too:
__hyp_text_start -> __hyp_text_end
__hyp_idmap_text_start -> __hyp_idmap_text_end

These can probably be guarded with is_kernel_in_hyp_mode(), if this is true then
we are running with VHE where this code runs at the same exception level as the
rest of the kernel, so we can probe them. (In this case you may want to add
'eret' to aarch64_insn_is_branch() in patch 2)


Probing things in the kernel idmap sounds dangerous! Lets blacklist that too:
__idmap_text_start -> __idmap_text_end



Thanks,

James


From ludovic.desroches at atmel.com  Thu May 12 07:54:08 2016
From: ludovic.desroches at atmel.com (Ludovic Desroches)
Date: Thu, 12 May 2016 16:54:08 +0200
Subject: [PATCH 1/3] dmaengine: at_xdmac: align descriptors on 64 bits
Message-ID: <1463064854-6719-1-git-send-email-ludovic.desroches@atmel.com>

Having descriptors aligned on 64 bits allows update CNDA and CUBC in an
atomic way.

Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>
Fixes: e1f7c9eee707 ("dmaengine: at_xdmac: creation of the atmel
eXtended DMA Controller driver")
Cc: stable at vger.kernel.org #v4.1 and later
---
 drivers/dma/at_xdmac.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 8e304b1..ba9b0b7 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -242,7 +242,7 @@ struct at_xdmac_lld {
 	u32		mbr_dus;	/* Destination Microblock Stride Register */
 };
 
-
+/* 64-bit alignment needed to update CNDA and CUBC registers in an atomic way. */
 struct at_xdmac_desc {
 	struct at_xdmac_lld		lld;
 	enum dma_transfer_direction	direction;
@@ -253,7 +253,7 @@ struct at_xdmac_desc {
 	unsigned int			xfer_size;
 	struct list_head		descs_list;
 	struct list_head		xfer_node;
-};
+} __aligned(sizeof(u64));
 
 static inline void __iomem *at_xdmac_chan_reg_base(struct at_xdmac *atxdmac, unsigned int chan_nb)
 {
-- 
2.5.0



From catalin.marinas at arm.com  Thu May 12 07:54:03 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 12 May 2016 15:54:03 +0100
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160512143415.GD30205@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
 <20160512134431.GB30205@yury-N73SV>
 <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
 <20160512142016.GH11226@e104818-lin.cambridge.arm.com>
 <20160512143415.GD30205@yury-N73SV>
Message-ID: <20160512145402.GI11226@e104818-lin.cambridge.arm.com>

On Thu, May 12, 2016 at 05:34:15PM +0300, Yury Norov wrote:
> On Thu, May 12, 2016 at 03:20:16PM +0100, Catalin Marinas wrote:
> > On Thu, May 12, 2016 at 03:07:35PM +0100, Catalin Marinas wrote:
> > > On Thu, May 12, 2016 at 04:44:31PM +0300, Yury Norov wrote:
> > > > On Thu, May 12, 2016 at 02:35:34PM +0100, Catalin Marinas wrote:
> > > > > On Thu, May 12, 2016 at 03:20:00AM +0300, Yury Norov wrote:
> > > > > > I debugged preadv02 and pwritev02 failures and found very weird bug.
> > > > > > Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> > > > > > of vector, and kernel reports successful read/write.
> > > > > > 
> > > > > > There are 2 problems:
> > > > > > 1. How kernel allows such address to be passed to fs subsystem;
> > > > > > 2. How fs successes to read/write at non-mapped, and in fact non-user
> > > > > > address.
> > > > > > 
> > > > > > I don't know the answer on 2'nd question, and it might be something
> > > > > > generic. But I investigated first problem.
> > > > > > 
> > > > > > The problem is that compat_rw_copy_check_uvector() uses access_ok() to
> > > > > > validate user address, and on arm64 it ends up with checking buffer
> > > > > > end against current_thread_info()->addr_limit.
> > > > > > 
> > > > > > current_thread_info()->addr_limit for ilp32, and most probably for
> > > > > > aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
> > > > > > It happens because on thread creation we call flush_old_exec() to set 
> > > > > > addr_limit, and completely ignore compat mode there.
> > > 
> > > [...]
> > > 
> > > > > > --- a/arch/arm64/kernel/binfmt_elf32.c
> > > > > > +++ b/arch/arm64/kernel/binfmt_elf32.c
> > > > > > @@ -12,6 +12,7 @@
> > > > > >  do {						\
> > > > > >  	clear_thread_flag(TIF_32BIT_AARCH64);	\
> > > > > >  	set_thread_flag(TIF_32BIT);		\
> > > > > > +	set_fs(TASK_SIZE_32);			\
> > > > > >  } while (0)
> > > > > >  
> > > > > >  #define COMPAT_ARCH_DLINFO
> > > > > > diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
> > > > > > index a934fd4..a8599c6 100644
> > > > > > --- a/arch/arm64/kernel/binfmt_ilp32.c
> > > > > > +++ b/arch/arm64/kernel/binfmt_ilp32.c
> > > > > > @@ -59,6 +59,7 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
> > > > > >  do {									\
> > > > > >  	set_thread_flag(TIF_32BIT_AARCH64);				\
> > > > > >  	clear_thread_flag(TIF_32BIT);					\
> > > > > > +	set_fs(TASK_SIZE_32);						\
> > > > > >  } while (0)
> > > > > 
> > > > > I don't think we need these two. AFAICT, flush_old_exec() takes care of
> > > > > setting the USER_DS for the new thread.
> > > > 
> > > > That's true, but USER_DS depends on personality which is not set yet
> > > > for new thread, as I wrote above. In fact, I tried correct USER_DS
> > > > only, and it doesn't work
> > > 
> > > Ah, it looks like load_elf_binary() sets the personality after
> > > flush_old_exec(). Looking at powerpc and x86, they set USER_DS to the
> > > maximum 64-bit task value, so they should have a similar issue with
> > > native 32-bit vs compat behaviour.
> > 
> > I think we have another problem. flush_old_exec() calls the arm64
> > flush_thread() where tls_thread_flush() checks for is_compat_task(). So
> > starting a 32-bit application from a 64-bit one not go on the correct
> > path.
> 
> As per now, all native, aarch32 and ilp32 tasks can exec() any
> binaries they need.

And that's correct.

> Are you think it's wrong? If so, how we coild run
> first compat application (maybe shell), it there are only lp64 tasks
> on the system?

What I meant is that we rely on flush_old_exec() to initialise the TLS
register for the compat task but it currently depends on what the parent
is. I think tls_thread_flush() should actually drop the is_compat_task()
thread and always initialise all the TLS registers.

-- 
Catalin


From ludovic.desroches at atmel.com  Thu May 12 07:54:09 2016
From: ludovic.desroches at atmel.com (Ludovic Desroches)
Date: Thu, 12 May 2016 16:54:09 +0200
Subject: [PATCH 2/3] dmaengine: at_xdmac: fix residue corruption
In-Reply-To: <1463064854-6719-1-git-send-email-ludovic.desroches@atmel.com>
References: <1463064854-6719-1-git-send-email-ludovic.desroches@atmel.com>
Message-ID: <1463064854-6719-2-git-send-email-ludovic.desroches@atmel.com>

An unexpected value of CUBC can lead to a corrupted residue. A more
complex sequence is needed to detect an inaccurate value for NCA or CUBC.

Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>
Fixes: e1f7c9eee707 ("dmaengine: at_xdmac: creation of the atmel
eXtended DMA Controller driver")
Cc: stable at vger.kernel.org #v4.1 and later
---
 drivers/dma/at_xdmac.c | 54 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index ba9b0b7..b02494e 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -1400,6 +1400,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
 	u32			cur_nda, check_nda, cur_ubc, mask, value;
 	u8			dwidth = 0;
 	unsigned long		flags;
+	bool			initd;
 
 	ret = dma_cookie_status(chan, cookie, txstate);
 	if (ret == DMA_COMPLETE)
@@ -1435,34 +1436,43 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
 	}
 
 	/*
-	 * When processing the residue, we need to read two registers but we
-	 * can't do it in an atomic way. AT_XDMAC_CNDA is used to find where
-	 * we stand in the descriptor list and AT_XDMAC_CUBC is used
-	 * to know how many data are remaining for the current descriptor.
-	 * Since the dma channel is not paused to not loose data, between the
-	 * AT_XDMAC_CNDA and AT_XDMAC_CUBC read, we may have change of
-	 * descriptor.
-	 * For that reason, after reading AT_XDMAC_CUBC, we check if we are
-	 * still using the same descriptor by reading a second time
-	 * AT_XDMAC_CNDA. If AT_XDMAC_CNDA has changed, it means we have to
-	 * read again AT_XDMAC_CUBC.
+	 * The easiest way to compute the residue should be to pause the DMA
+	 * but doing this can lead to miss some data as some devices don't
+	 * have FIFO.
+	 * We need to read several registers because:
+	 * - DMA is running therefore a descriptor change is possible while
+	 * reading these registers
+	 * - When the block transfer is done, the value of the CUBC register
+	 * is set to its initial value until the fetch of the next descriptor.
+	 * This value will corrupt the residue calculation so we have to skip
+	 * it.
+	 *
+	 * INITD --------                    ------------
+	 *              |____________________|
+	 *       _______________________  _______________
+	 * NDA       @desc2             \/   @desc3
+	 *       _______________________/\_______________
+	 *       __________  ___________  _______________
+	 * CUBC       0    \/ MAX desc1 \/  MAX desc2
+	 *       __________/\___________/\_______________
+	 *
+	 * Since descriptors are aligned on 64 bits, we can assume that
+	 * the update of NDA and CUBC is atomic.
 	 * Memory barriers are used to ensure the read order of the registers.
-	 * A max number of retries is set because unlikely it can never ends if
-	 * we are transferring a lot of data with small buffers.
+	 * A max number of retries is set because unlikely it could never ends.
 	 */
-	cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
-	rmb();
-	cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
 	for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
-		rmb();
 		check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
-
-		if (likely(cur_nda == check_nda))
-			break;
-
-		cur_nda = check_nda;
+		rmb();
+		initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
 		rmb();
 		cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
+		rmb();
+		cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
+		rmb();
+
+		if ((check_nda == cur_nda) && initd)
+			break;
 	}
 
 	if (unlikely(retry >= AT_XDMAC_RESIDUE_MAX_RETRIES)) {
-- 
2.5.0



From ludovic.desroches at atmel.com  Thu May 12 07:54:10 2016
From: ludovic.desroches at atmel.com (Ludovic Desroches)
Date: Thu, 12 May 2016 16:54:10 +0200
Subject: [PATCH 3/3] dmaengine: at_xdmac: double FIFO flush needed to compute
 residue
In-Reply-To: <1463064854-6719-1-git-send-email-ludovic.desroches@atmel.com>
References: <1463064854-6719-1-git-send-email-ludovic.desroches@atmel.com>
Message-ID: <1463064854-6719-3-git-send-email-ludovic.desroches@atmel.com>

Due to the way CUBC register is updated, a double flush is needed to
compute an accurate residue. First flush aim is to get data from the DMA
FIFO and second one ensures that we won't report data which are not in
memory.

Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>
Fixes: e1f7c9eee707 ("dmaengine: at_xdmac: creation of the atmel
eXtended DMA Controller driver")
Cc: stable at vger.kernel.org #v4.1 and later
---
 drivers/dma/at_xdmac.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index b02494e..75bd662 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -1425,7 +1425,16 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
 	residue = desc->xfer_size;
 	/*
 	 * Flush FIFO: only relevant when the transfer is source peripheral
-	 * synchronized.
+	 * synchronized. Flush is needed before reading CUBC because data in
+	 * the FIFO are not reported by CUBC. Reporting a residue of the
+	 * transfer length while we have data in FIFO can cause issue.
+	 * Usecase: atmel USART has a timeout which means I have received
+	 * characters but there is no more character received for a while. On
+	 * timeout, it requests the residue. If the data are in the DMA FIFO,
+	 * we will return a residue of the transfer length. It means no data
+	 * received. If an application is waiting for these data, it will hang
+	 * since we won't have another USART timeout without receiving new
+	 * data.
 	 */
 	mask = AT_XDMAC_CC_TYPE | AT_XDMAC_CC_DSYNC;
 	value = AT_XDMAC_CC_TYPE_PER_TRAN | AT_XDMAC_CC_DSYNC_PER2MEM;
@@ -1481,6 +1490,19 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
 	}
 
 	/*
+	 * Flush FIFO: only relevant when the transfer is source peripheral
+	 * synchronized. Another flush is needed here because CUBC is updated
+	 * when the controller sends the data write command. It can lead to
+	 * report data that are not written in the memory or the device. The
+	 * FIFO flush ensures that data are really written.
+	 */
+	if ((desc->lld.mbr_cfg & mask) == value) {
+		at_xdmac_write(atxdmac, AT_XDMAC_GSWF, atchan->mask);
+		while (!(at_xdmac_chan_read(atchan, AT_XDMAC_CIS) & AT_XDMAC_CIS_FIS))
+			cpu_relax();
+	}
+
+	/*
 	 * Remove size of all microblocks already transferred and the current
 	 * one. Then add the remaining size to transfer of the current
 	 * microblock.
-- 
2.5.0



From stefan.wahren at i2se.com  Thu May 12 07:56:59 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Thu, 12 May 2016 16:56:59 +0200 (CEST)
Subject: [PATCH 3/4] ARM: dts: bcm2835: add the bcm2835-sdram-controller
 to the dt
In-Reply-To: <1463056732-5607-4-git-send-email-kernel@martin.sperl.org>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
 <1463056732-5607-4-git-send-email-kernel@martin.sperl.org>
Message-ID: <73859954.21004.36a104a6-5284-487f-b397-da7ff0407f1f.open-xchange@email.1und1.de>

Hi,

> kernel at martin.sperl.org hat am 12. Mai 2016 um 14:38 geschrieben:
> 
> 
> From: Martin Sperl <kernel at martin.sperl.org>
> 
> Add the bcm2835 sdram controller to the device tree.
> 
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
> ---
>  arch/arm/boot/dts/bcm283x.dtsi | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
> index 8aaf193..9db9d97 100644
> --- a/arch/arm/boot/dts/bcm283x.dtsi
> +++ b/arch/arm/boot/dts/bcm283x.dtsi
> @@ -22,6 +22,12 @@
>  		#address-cells = <1>;
>  		#size-cells = <1>;
>  
> +		memory-controller at 7e002000 {
> +			compatible = "brcm,bcm2835-sdram";
> +			reg = <0x7e002000 0x58>, <0x7e002800 0x58>;

where do you get these addresses?

According to register documentation [1] the adresses belong to the interrupt
controller.

Maybe 0x7ee00000 is the right address.

[1] - https://github.com/hermanhermitage/videocoreiv/wiki/Register-Documentation

> +			clocks = <&clocks BCM2835_CLOCK_SDRAM>;
> +		};
> +
>  		timer at 7e003000 {
>  			compatible = "brcm,bcm2835-system-timer";
>  			reg = <0x7e003000 0x1000>;
> -- 
> 2.1.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From yingjoe.chen at mediatek.com  Thu May 12 07:59:44 2016
From: yingjoe.chen at mediatek.com (Yingjoe Chen)
Date: Thu, 12 May 2016 22:59:44 +0800
Subject: [RFC 1/3] dt-bindings: drm/mediatek: Add display binding for
 Mediatek SoC MT2701
In-Reply-To: <1463053795-55455-2-git-send-email-yt.shen@mediatek.com>
References: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
 <1463053795-55455-2-git-send-email-yt.shen@mediatek.com>
Message-ID: <1463065184.17225.2.camel@mtksdaap41>

On Thu, 2016-05-12 at 19:49 +0800, yt.shen at mediatek.com wrote:
> From: YT Shen <yt.shen at mediatek.com>
> 
> Add device tree binding documentation for the display subsystem in
> Mediatek SoC MT2701
> 
> Signed-off-by: YT Shen <yt.shen at mediatek.com>
> ---
>  .../bindings/display/mediatek/mediatek,disp.txt    |    1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
> index db6e77e..53b3cc3 100644
> --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
> +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
> @@ -40,6 +40,7 @@ Required properties (all function blocks):
>  	"mediatek,<chip>-dpi"        - DPI controller, see mediatek,dpi.txt
>  	"mediatek,<chip>-disp-mutex" - display mutex
>  	"mediatek,<chip>-disp-od"    - overdrive
> +	"mediatek,<chip>-disp-bls"   - backlight
>  - reg: Physical base address and length of the function block register space
>  - interrupts: The interrupt signal from the function block (required, except for
>    merge and split function blocks).


Hi,

This one is in conflict with "Support Mediatek Soc MT2701 disp pwm"
series Weiqing sent last week, which add disp-bls support to display pwm
driver.

Joe.C




From james.morse at arm.com  Thu May 12 08:01:54 2016
From: james.morse at arm.com (James Morse)
Date: Thu, 12 May 2016 16:01:54 +0100
Subject: [PATCH v12 05/10] arm64: Kprobes with single stepping support
In-Reply-To: <1461783185-9056-6-git-send-email-dave.long@linaro.org>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-6-git-send-email-dave.long@linaro.org>
Message-ID: <57349AE2.3060507@arm.com>

Hi David, Sandeepa,

On 27/04/16 19:53, David Long wrote:
> From: Sandeepa Prabhu <sandeepa.s.prabhu at gmail.com>

> diff --git a/arch/arm64/kernel/kprobes.c b/arch/arm64/kernel/kprobes.c
> new file mode 100644
> index 0000000..dfa1b1f
> --- /dev/null
> +++ b/arch/arm64/kernel/kprobes.c
> @@ -0,0 +1,520 @@
> +/*
> + * arch/arm64/kernel/kprobes.c
> + *
> + * Kprobes support for ARM64
> + *
> + * Copyright (C) 2013 Linaro Limited.
> + * Author: Sandeepa Prabhu <sandeepa.prabhu at linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + */
> +#include <linux/kernel.h>
> +#include <linux/kprobes.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/stop_machine.h>
> +#include <linux/stringify.h>
> +#include <asm/traps.h>
> +#include <asm/ptrace.h>
> +#include <asm/cacheflush.h>
> +#include <asm/debug-monitors.h>
> +#include <asm/system_misc.h>
> +#include <asm/insn.h>
> +#include <asm/uaccess.h>
> +
> +#include "kprobes-arm64.h"
> +
> +#define MIN_STACK_SIZE(addr)	min((unsigned long)MAX_STACK_SIZE,	\
> +	(unsigned long)current_thread_info() + THREAD_START_SP - (addr))

What if we probe something called on the irq stack?
This needs the on_irq_stack() checks too, the start/end can be found from the
per-cpu irq_stack value.

[ ... ]

> +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
> +{
> +	struct jprobe *jp = container_of(p, struct jprobe, kp);
> +	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
> +	long stack_ptr = kernel_stack_pointer(regs);
> +
> +	kcb->jprobe_saved_regs = *regs;
> +	memcpy(kcb->jprobes_stack, (void *)stack_ptr,
> +	       MIN_STACK_SIZE(stack_ptr));

I wonder if we need this stack save/restore?

The comment next to the equivalent code for x86 says:
> gcc assumes that the callee owns the argument space and could overwrite it,
> e.g. tailcall optimization. So, to be absolutely safe we also save and
> restore enough stack bytes to cover the argument area.

On arm64 the first eight arguments are passed in registers, so we might not need
this stack copy. (sparc and powerpc work like this too, their versions of this
function don't copy chunks of the stack).

... then I went looking for functions with >8 arguments...

Looking at the arm64 defconfig dwarf debug data, there are 71 of these that
don't get inlined, picking at random:
> rockchip_clk_register_pll() has 13
> fib_dump_info() has 11
> vma_merge() has 10
> vring_create_virtqueue() has 10
etc...

So we do need this stack copying, so that we can probe these function without
risking the arguments being modified.

It may be worth including a comment to the effect that this stack save/restore
is needed for functions that pass >8 arguments where the pre-handler may change
these values on the stack.


> +	preempt_enable_no_resched();
> +	return 1;
> +}
> +


Thanks,

James


From david.wu at rock-chips.com  Thu May 12 08:07:34 2016
From: david.wu at rock-chips.com (David.Wu)
Date: Thu, 12 May 2016 23:07:34 +0800
Subject: [PATCH v8 7/8] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <5733D7AA.1060500@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908698-27284-1-git-send-email-david.wu@rock-chips.com>
 <CAD=FV=Uf-U3RBpgFbR3LkPAJTWqz3d02+H7iyA-SS-y=r3cXjA@mail.gmail.com>
 <5733D7AA.1060500@rock-chips.com>
Message-ID: <57349C36.4030401@rock-chips.com>

Hi Doug?

? 2016/5/12 9:08, David.Wu ??:
> Hi Doug,
>
> ? 2016/5/12 1:37, Doug Anderson ??:
>> Hi,
>>
>> On Tue, May 10, 2016 at 12:31 PM, David Wu <david.wu at rock-chips.com>
>> wrote:
>>>   static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long
>>> clk_rate)
>>>   {
>>>          struct i2c_timings *t = &i2c->t;
>>>          struct rk3x_i2c_calced_timings calc;
>>>          u64 t_low_ns, t_high_ns;
>>> +       u32 val;
>>>          int ret;
>>>
>>> -       ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
>>> +       ret = i2c->soc_data->calc_timings(clk_rate, t, &calc);
>>>          WARN_ONCE(ret != 0, "Could not reach SCL freq %u",
>>> t->bus_freq_hz);
>>>
>>> -       clk_enable(i2c->clk);
>>> +       clk_enable(i2c->pclk);
>>> +
>>>          i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low &
>>> 0xffff),
>>>                     REG_CLKDIV);
>>> -       clk_disable(i2c->clk);
>>> +
>>> +       val = i2c_readl(i2c, REG_CON);
>>> +       val &= ~REG_CON_TUNING_MASK;
>>> +       val |= calc.tuning;
>>> +       i2c_writel(i2c, val, REG_CON);
>>
>> Another subtle bug here.  You need to be holding the spinlock here
>> since you're doing a read-modify-write of a register that is also
>> touched by the interrupt handler.  We never needed it before because
>> the previous register update wasn't touched by anyone else and it was
>> a single atomic write.
>>
>> Also: technically if we are midway through a transfer when all this
>> happens then there will be a very short period of time when the two
>> timing-related registers won't match with each other.  I have no idea
>> how much that would matter, but in the very least it seems wise to
>> minimize the time where they mismatch.  So I'd probably write:
>>
>>         spin_lock_irqsave(&i2c->lock, flags);
>>         val = i2c_readl(i2c, REG_CON);
>>         val &= ~REG_CON_TUNING_MASK;
>>         val |= calc.tuning;
>>         i2c_writel(i2c, val, REG_CON);
>>         i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
>>                    REG_CLKDIV);
>>         spin_unlock_irqrestore(&i2c->lock, flags);
>>
>> ...if we really end up with on a system with a dynamically changing
>> clock that uses the new-style timing and we see real problems, we can
>> always try to come up with a way to avoid any problems.  Sound OK?
>>
>>
>
> Good, add spin_lock is very necessary for atomic write here, thanks for
> your advice.

I also found a subtle bug, it would clean the con register by use 
"i2c_writel(i2c, 0, REG_CON)" in rk3x_i2c_stop(). So i think it would be 
fixed by using read-modify-write way here in next version.

>
>> Otherwise, I think things look good to me.  Caesar's comments would
>> also be good to fix.
>>
>>
>> -Doug
>>
>>
>>



From andre.przywara at arm.com  Thu May 12 08:08:31 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 12 May 2016 16:08:31 +0100
Subject: [PATCH v3 17/55] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <20160512114651.GB2370@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-18-git-send-email-andre.przywara@arm.com>
 <20160512114651.GB2370@cbox>
Message-ID: <57349C6F.8050406@arm.com>

Hi,

On 12/05/16 12:46, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:30AM +0100, Andre Przywara wrote:
>> From: Marc Zyngier <marc.zyngier at arm.com>
>>
>> Implement the framework for syncing IRQs between our emulation and
>> the list registers, which represent the guest's view of IRQs.
>> This is done in kvm_vgic_flush_hwstate and kvm_vgic_sync_hwstate,
>> which gets called on guest entry and exit.
>> The code talking to the actual GICv2/v3 hardware is added in the
>> following patches.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
> 
> [...]
> 
>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>> index 4fb20fd..c6f8b9b 100644
>> --- a/virt/kvm/arm/vgic/vgic.c
>> +++ b/virt/kvm/arm/vgic/vgic.c
> 
> [...]
> 
>> +
>> +/* Requires the VCPU's ap_list_lock to be held. */
>> +static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
>> +{
>> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
>> +	struct vgic_irq *irq;
>> +	int count = 0;
>> +
>> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
>> +
>> +	if (unlikely(!vcpu->kvm->arch.vgic.enabled))
>> +		goto out_clean;
> 
> 
> I know I said I reviewed this, but thinking about this more carefully,
> doesn't the enable bit actually tell us if forwarding of pending
> interrupts is enabled, but not whether or not the vgic exists?
> 
> So you could imagine a guest that turns off the GIC, but still has
> active interrupts that it wants to disable/EOI, in the case of
> shutdown/reboot for example, or is this architecturally not allowed?

I guess you are right, the spec talks only about GICD.CTLR[Enable]
controlling the forwarding of pending interrupts to the CPU interface.
If you don't want interrupts at all, I guess you disable the CPU interface.

So we just don't put pending IRQs in the LR, but only active ones.
I am coding this right now.

Cheers,
Andre

> 
> If it is, then we should, at least theoretically, still forward active
> interrupts in LRs despite the enabled bit being clear, but modify the
> oracle to take the global enable bit into account.
> 
> Thanks,
> -Christoffer


From ddaney at caviumnetworks.com  Thu May 12 08:27:08 2016
From: ddaney at caviumnetworks.com (David Daney)
Date: Thu, 12 May 2016 08:27:08 -0700
Subject: [PATCH v6 13/14] arm64, acpi, numa: NUMA support based on SRAT
 and SLIT
In-Reply-To: <20160512094915.GD11226@e104818-lin.cambridge.arm.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <1461780436-27182-14-git-send-email-ddaney.cavm@gmail.com>
 <20160511103929.GC3051@e104818-lin.cambridge.arm.com>
 <5733C8F5.6090206@caviumnetworks.com>
 <20160512094915.GD11226@e104818-lin.cambridge.arm.com>
Message-ID: <5734A0CC.8010600@caviumnetworks.com>

On 05/12/2016 02:49 AM, Catalin Marinas wrote:
> On Wed, May 11, 2016 at 05:06:13PM -0700, David Daney wrote:
>> On 05/11/2016 03:39 AM, Catalin Marinas wrote:
[...]
>>>
>>> I wonder whether you could replace the get_mpidr_in_madt() function with
>>> something like acpi_get_phys_id(). It looks like get_mpidr_in_madt()
>>> duplicates functionality already available elsewhere.
>>
>> I just tried that, and it doesn't work.
>>
>> The problem is that this code is being run very early in the boot, and
>> kmalloc cannot be used.  acpi_get_phys_id() and its ilk can only be used
>> once we have working kmalloc.  We need to extract the NUMA information early
>> like this precisely because it is needed to initializing the slab system
>>
>> Notice that we are using early_acpi_os_unmap_memory() et al. in
>> get_mpidr_in_madt() explicitly for this reason.
>>
>> In summary: I don't think we need another revision of this patch, it is like
>> this for a good reason.
>
> Slightly confusing, in another reply you said you are going to address
> my comment. So, is it doable?

I don't think so.

My previous reply, to the thread in 0/14, was prematurely made with the 
incorrect assumption that it was a simple change.  Now, after really 
digging in to the code, and attempting to do as you suggested, I have 
changed my mind.

As I indicated above, there are no remaining suggestions or requests for 
changes to this patch set pending action.  Unless people find additional 
problems, I think it is ready for merging.

I know that Will and Rafael were discussing the proper timing for 
merging this in the other thread, so I leave it in their hands at this 
point.

Thanks,
David Daney


>



From catalin.marinas at arm.com  Thu May 12 08:28:06 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 12 May 2016 16:28:06 +0100
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160512142457.GC30205@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
 <20160512134431.GB30205@yury-N73SV>
 <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
 <20160512142457.GC30205@yury-N73SV>
Message-ID: <20160512152805.GJ11226@e104818-lin.cambridge.arm.com>

On Thu, May 12, 2016 at 05:24:57PM +0300, Yury Norov wrote:
> On Thu, May 12, 2016 at 03:07:35PM +0100, Catalin Marinas wrote:
> > On Thu, May 12, 2016 at 04:44:31PM +0300, Yury Norov wrote:
> > > On Thu, May 12, 2016 at 02:35:34PM +0100, Catalin Marinas wrote:
> > > > On Thu, May 12, 2016 at 03:20:00AM +0300, Yury Norov wrote:
> > > > > I debugged preadv02 and pwritev02 failures and found very weird bug.
> > > > > Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> > > > > of vector, and kernel reports successful read/write.
> > > > > 
> > > > > There are 2 problems:
> > > > > 1. How kernel allows such address to be passed to fs subsystem;
> > > > > 2. How fs successes to read/write at non-mapped, and in fact non-user
> > > > > address.
> > > > > 
> > > > > I don't know the answer on 2'nd question, and it might be something
> > > > > generic. But I investigated first problem.
> > > > > 
> > > > > The problem is that compat_rw_copy_check_uvector() uses access_ok() to
> > > > > validate user address, and on arm64 it ends up with checking buffer
> > > > > end against current_thread_info()->addr_limit.
> > > > > 
> > > > > current_thread_info()->addr_limit for ilp32, and most probably for
> > > > > aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
> > > > > It happens because on thread creation we call flush_old_exec() to set 
> > > > > addr_limit, and completely ignore compat mode there.
> > 
> > [...]
> > 
> > > > > --- a/arch/arm64/kernel/binfmt_elf32.c
> > > > > +++ b/arch/arm64/kernel/binfmt_elf32.c
> > > > > @@ -12,6 +12,7 @@
> > > > >  do {						\
> > > > >  	clear_thread_flag(TIF_32BIT_AARCH64);	\
> > > > >  	set_thread_flag(TIF_32BIT);		\
> > > > > +	set_fs(TASK_SIZE_32);			\
> > > > >  } while (0)
> > > > >  
> > > > >  #define COMPAT_ARCH_DLINFO
> > > > > diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
> > > > > index a934fd4..a8599c6 100644
> > > > > --- a/arch/arm64/kernel/binfmt_ilp32.c
> > > > > +++ b/arch/arm64/kernel/binfmt_ilp32.c
> > > > > @@ -59,6 +59,7 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
> > > > >  do {									\
> > > > >  	set_thread_flag(TIF_32BIT_AARCH64);				\
> > > > >  	clear_thread_flag(TIF_32BIT);					\
> > > > > +	set_fs(TASK_SIZE_32);						\
> > > > >  } while (0)
> > > > 
> > > > I don't think we need these two. AFAICT, flush_old_exec() takes care of
> > > > setting the USER_DS for the new thread.
> > > 
> > > That's true, but USER_DS depends on personality which is not set yet
> > > for new thread, as I wrote above. In fact, I tried correct USER_DS
> > > only, and it doesn't work
> > 
> > Ah, it looks like load_elf_binary() sets the personality after
> > flush_old_exec(). Looking at powerpc and x86, they set USER_DS to the
> > maximum 64-bit task value, so they should have a similar issue with
> > native 32-bit vs compat behaviour.
> 
> Hmmm. If so, it means we'd introduce generic fix. It would be removing 
> set_fs() from flush_old_exec() and appending it to load_elf_binary()
> after SET_PERSONALITY(). But I think it should be agreed with other
> arches developers.

The set_fs() in flush_old_exec() is probably fine, it may be meant to
re-set the USER_DS for the old thread.

It appears that at least powerpc and x86 don't have different USER_DS
setting for native and compat, so moving the set_fs() call further down
would not make any difference for them, nor will it fix the preadv02 LTP
test (if it fails for them, I haven't checked).

> I've sent standalone patch for aarch64 (you in CC) so let's move
> discussion there.

I've seen the patch but we would lose some discussion history here. I
think we should continue this thread and just summarise the conclusion
in reply to the other patch. This thread is also available on
linux-arch, in case other architecture maintainers follow it.

> > So what exactly is LTP complaining about? Is different error (like
> > EFAULT vs EINVAL) or not getting an error at all.
>  
> It should be EINVAL, but it succeed. The other problem is that
> following fs routines does not complain on wrong address.

I see. The test asks the kernel to write a single byte (out of maximum
64) to the user address 0xffffffff. In the absence of the access_ok()
check, this operation succeeds. If the preadv syscall gets 2 bytes as
the count, then it would fail with EFAULT.

While it's not really a bug, I agree that for matching the native 32-bit
behavior (basically for other syscalls like those involving vfs_read()),
the simplest fix would be to have a dynamic USER_DS.

-- 
Catalin


From kernel at martin.sperl.org  Thu May 12 08:28:57 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Thu, 12 May 2016 17:28:57 +0200
Subject: [PATCH 0/4] add minimal bcm2835-sdram driver
In-Reply-To: <1861597197.20753.36a104a6-5284-487f-b397-da7ff0407f1f.open-xchange@email.1und1.de>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
 <1861597197.20753.36a104a6-5284-487f-b397-da7ff0407f1f.open-xchange@email.1und1.de>
Message-ID: <B30D094A-1E5A-4777-8F2A-C3D53AF89044@martin.sperl.org>


> On 12.05.2016, at 16:50, Stefan Wahren <stefan.wahren at i2se.com> wrote:
> 
> Hi Martin,
> 
>> kernel at martin.sperl.org hat am 12. Mai 2016 um 14:38 geschrieben:
>> 
>> 
>> From: Martin Sperl <kernel at martin.sperl.org>
>> 
>> As the sdram clock is a critical clock to the system
>> the minimal bcm2835-sdram driver claims (and enables)
>> this clock and also exposes the corresponding sdram
>> registers via debugfs.
> 
> sounds like this driver should fix an clock handling issue. Unfortunately this
> isn't a solution in case the driver is disabled.
Unfortunately there is no way around this - the driver has
to be enabled so that the sdram clock or the parent pll,
which typically is plld_core, never gets disabled.

The only other option would be marking the clock as critical
for those legacy drivers.

See also the discussions around the clock register for the
sdram clock, where we have the ?normal? clock and some
pll as well - even if the ?normal? clock is disabled, 
then clearing the sdram register (or the parent) freezes
the system.

> 
> Does the GPU firmware handle the SDRAM controller or is it initialized by
> bootcode?
> 

AFAIK it is enabled in bootcode.bin and - as of now - the firmware
updates refresh cycles when SOC temperatures change.
FW checks every 30 seconds unless there is a key set in config.txt,
which - supposedly - produces a slight impact every 30 seconds to
the system.

Martin

From ynorov at caviumnetworks.com  Thu May 12 08:27:21 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 12 May 2016 18:27:21 +0300
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160512145402.GI11226@e104818-lin.cambridge.arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
 <20160512134431.GB30205@yury-N73SV>
 <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
 <20160512142016.GH11226@e104818-lin.cambridge.arm.com>
 <20160512143415.GD30205@yury-N73SV>
 <20160512145402.GI11226@e104818-lin.cambridge.arm.com>
Message-ID: <20160512152721.GA31729@yury-N73SV>

On Thu, May 12, 2016 at 03:54:03PM +0100, Catalin Marinas wrote:
> On Thu, May 12, 2016 at 05:34:15PM +0300, Yury Norov wrote:
> > On Thu, May 12, 2016 at 03:20:16PM +0100, Catalin Marinas wrote:
> > > On Thu, May 12, 2016 at 03:07:35PM +0100, Catalin Marinas wrote:
> > > > On Thu, May 12, 2016 at 04:44:31PM +0300, Yury Norov wrote:
> > > > > On Thu, May 12, 2016 at 02:35:34PM +0100, Catalin Marinas wrote:
> > > > > > On Thu, May 12, 2016 at 03:20:00AM +0300, Yury Norov wrote:
> > > > > > > I debugged preadv02 and pwritev02 failures and found very weird bug.
> > > > > > > Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> > > > > > > of vector, and kernel reports successful read/write.
> > > > > > > 
> > > > > > > There are 2 problems:
> > > > > > > 1. How kernel allows such address to be passed to fs subsystem;
> > > > > > > 2. How fs successes to read/write at non-mapped, and in fact non-user
> > > > > > > address.
> > > > > > > 
> > > > > > > I don't know the answer on 2'nd question, and it might be something
> > > > > > > generic. But I investigated first problem.
> > > > > > > 
> > > > > > > The problem is that compat_rw_copy_check_uvector() uses access_ok() to
> > > > > > > validate user address, and on arm64 it ends up with checking buffer
> > > > > > > end against current_thread_info()->addr_limit.
> > > > > > > 
> > > > > > > current_thread_info()->addr_limit for ilp32, and most probably for
> > > > > > > aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
> > > > > > > It happens because on thread creation we call flush_old_exec() to set 
> > > > > > > addr_limit, and completely ignore compat mode there.
> > > > 
> > > > [...]
> > > > 
> > > > > > > --- a/arch/arm64/kernel/binfmt_elf32.c
> > > > > > > +++ b/arch/arm64/kernel/binfmt_elf32.c
> > > > > > > @@ -12,6 +12,7 @@
> > > > > > >  do {						\
> > > > > > >  	clear_thread_flag(TIF_32BIT_AARCH64);	\
> > > > > > >  	set_thread_flag(TIF_32BIT);		\
> > > > > > > +	set_fs(TASK_SIZE_32);			\
> > > > > > >  } while (0)
> > > > > > >  
> > > > > > >  #define COMPAT_ARCH_DLINFO
> > > > > > > diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
> > > > > > > index a934fd4..a8599c6 100644
> > > > > > > --- a/arch/arm64/kernel/binfmt_ilp32.c
> > > > > > > +++ b/arch/arm64/kernel/binfmt_ilp32.c
> > > > > > > @@ -59,6 +59,7 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
> > > > > > >  do {									\
> > > > > > >  	set_thread_flag(TIF_32BIT_AARCH64);				\
> > > > > > >  	clear_thread_flag(TIF_32BIT);					\
> > > > > > > +	set_fs(TASK_SIZE_32);						\
> > > > > > >  } while (0)
> > > > > > 
> > > > > > I don't think we need these two. AFAICT, flush_old_exec() takes care of
> > > > > > setting the USER_DS for the new thread.
> > > > > 
> > > > > That's true, but USER_DS depends on personality which is not set yet
> > > > > for new thread, as I wrote above. In fact, I tried correct USER_DS
> > > > > only, and it doesn't work
> > > > 
> > > > Ah, it looks like load_elf_binary() sets the personality after
> > > > flush_old_exec(). Looking at powerpc and x86, they set USER_DS to the
> > > > maximum 64-bit task value, so they should have a similar issue with
> > > > native 32-bit vs compat behaviour.
> > > 
> > > I think we have another problem. flush_old_exec() calls the arm64
> > > flush_thread() where tls_thread_flush() checks for is_compat_task(). So
> > > starting a 32-bit application from a 64-bit one not go on the correct
> > > path.
> > 
> > As per now, all native, aarch32 and ilp32 tasks can exec() any
> > binaries they need.
> 
> And that's correct.
> 
> > Are you think it's wrong? If so, how we coild run
> > first compat application (maybe shell), it there are only lp64 tasks
> > on the system?
> 
> What I meant is that we rely on flush_old_exec() to initialise the TLS
> register for the compat task but it currently depends on what the parent
> is. I think tls_thread_flush() should actually drop the is_compat_task()
> thread and always initialise all the TLS registers.
> 

OK. I'll do it in v2.

> -- 
> Catalin


From luke.starrett at broadcom.com  Thu May 12 08:34:37 2016
From: luke.starrett at broadcom.com (Luke Starrett)
Date: Thu, 12 May 2016 11:34:37 -0400
Subject: [PATCH] arm64: Implement optimised IP checksum helpers
In-Reply-To: <6ca77904d1eced60d86145dc5da361f3aefc6fec.1463062758.git.robin.murphy@arm.com>
References: <6ca77904d1eced60d86145dc5da361f3aefc6fec.1463062758.git.robin.murphy@arm.com>
Message-ID: <a3d91ddf-565d-5cef-0a56-39154e3a00d2@broadcom.com>

Hi Robin,

I pulled this in to a userspace test app expecting that the __uint128_t 
type might cause GCC to emit 'ldp'.  Seems like that was that your 
intent based on your commit note.  Instead I see two 64b loads (ldr Xn), 
and a single 32b load (ldr Wn) for the trailing 4B.  This was with 
Linaro GCC 4.9-2015.06.

Otherwise, the C cycle count looks good enough compared to the asm version.

Thanks,

Luke


On 5/12/2016 10:26 AM, Robin Murphy wrote:
> AArch64 is capable of 128-bit memory accesses without alignment
> restrictions, which makes it both possible and highly practical to slurp
> up a typical 20-byte IP header in just 2 loads. Implement our own
> version of ip_fast_checksum() to take advantage of that, resulting in
> considerably fewer instructions and memory accesses than the generic
> version. We can also get more optimal code generation for csum_fold() by
> defining it a slightly different way round from the generic version, so
> throw that into the mix too.
>
> Suggested-by: Luke Starrett <luke.starrett at broadcom.com>
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
>
> Having spent an evening poring over disassembler output, it turns out
> that there's really no need to drop into asm for this, hurrah! I've
> taken it for a spin on both big and little-endian, with no ill effects.
>
>   arch/arm64/include/asm/checksum.h | 49 +++++++++++++++++++++++++++++++++++++++
>   1 file changed, 49 insertions(+)
>   create mode 100644 arch/arm64/include/asm/checksum.h
>
> diff --git a/arch/arm64/include/asm/checksum.h b/arch/arm64/include/asm/checksum.h
> new file mode 100644
> index 000000000000..7e975ffce837
> --- /dev/null
> +++ b/arch/arm64/include/asm/checksum.h
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright (C) 2016 ARM 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef __ASM_CHECKSUM_H
> +#define __ASM_CHECKSUM_H
> +
> +static inline __sum16 csum_fold(__wsum csum)
> +{
> +	u32 sum = (__force u32)csum;
> +	sum += (sum >> 16) | (sum << 16);
> +	return ~(__force __sum16)(sum >> 16);
> +}
> +#define csum_fold csum_fold
> +
> +static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
> +{
> +	__uint128_t tmp;
> +	u64 sum;
> +
> +	tmp = *(const __uint128_t *)iph;
> +	iph += 16;
> +	ihl -= 4;
> +	tmp += ((tmp >> 64) | (tmp << 64));
> +	sum = tmp >> 64;
> +	do {
> +		sum += *(const u32 *)iph;
> +		iph += 4;
> +	} while (--ihl);
> +
> +	sum += ((sum >> 32) | (sum << 32));
> +	return csum_fold(sum >> 32);
> +}
> +#define ip_fast_csum ip_fast_csum
> +
> +#include <asm-generic/checksum.h>
> +
> +#endif	/* __ASM_CHECKSUM_H */



From ludovic.desroches at atmel.com  Thu May 12 08:37:34 2016
From: ludovic.desroches at atmel.com (Ludovic Desroches)
Date: Thu, 12 May 2016 17:37:34 +0200
Subject: [PATCH 1/3] tty/serial: atmel: re-integrate status check in irq
 handler
Message-ID: <1463067456-6983-1-git-send-email-ludovic.desroches@atmel.com>

From: Nicolas Ferre <nicolas.ferre at atmel.com>

The IRQ status check and related actions was done in the tasklet without
benefit. So, move it back to the IRQ context to simplify IRQ handling and
having the possibility to split the tasklet in two separated ones for
receive and transmit actions.

Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>
---
 drivers/tty/serial/atmel_serial.c | 43 ++++++++++++++++-----------------------
 1 file changed, 17 insertions(+), 26 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 954941d..8854ac6 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -146,9 +146,7 @@ struct atmel_uart_port {
 	struct scatterlist		sg_tx;
 	struct scatterlist		sg_rx;
 	struct tasklet_struct	tasklet;
-	unsigned int		irq_status;
 	unsigned int		irq_status_prev;
-	unsigned int		status_change;
 	unsigned int		tx_len;
 
 	struct circ_buf		rx_ring;
@@ -1237,14 +1235,27 @@ atmel_handle_status(struct uart_port *port, unsigned int pending,
 		    unsigned int status)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+	unsigned int status_change;
 
 	if (pending & (ATMEL_US_RIIC | ATMEL_US_DSRIC | ATMEL_US_DCDIC
 				| ATMEL_US_CTSIC)) {
-		atmel_port->irq_status = status;
-		atmel_port->status_change = atmel_port->irq_status ^
-					    atmel_port->irq_status_prev;
+		status_change = status ^ atmel_port->irq_status_prev;
 		atmel_port->irq_status_prev = status;
-		tasklet_schedule(&atmel_port->tasklet);
+
+		if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
+					| ATMEL_US_DCD | ATMEL_US_CTS)) {
+			/* TODO: All reads to CSR will clear these interrupts! */
+			if (status_change & ATMEL_US_RI)
+				port->icount.rng++;
+			if (status_change & ATMEL_US_DSR)
+				port->icount.dsr++;
+			if (status_change & ATMEL_US_DCD)
+				uart_handle_dcd_change(port, !(status & ATMEL_US_DCD));
+			if (status_change & ATMEL_US_CTS)
+				uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
+
+			wake_up_interruptible(&port->state->port.delta_msr_wait);
+		}
 	}
 }
 
@@ -1575,31 +1586,12 @@ static void atmel_tasklet_func(unsigned long data)
 {
 	struct uart_port *port = (struct uart_port *)data;
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-	unsigned int status = atmel_port->irq_status;
-	unsigned int status_change = atmel_port->status_change;
 
 	/* The interrupt handler does not take the lock */
 	spin_lock(&port->lock);
 
 	atmel_port->schedule_tx(port);
 
-	if (status_change & (ATMEL_US_RI | ATMEL_US_DSR
-				| ATMEL_US_DCD | ATMEL_US_CTS)) {
-		/* TODO: All reads to CSR will clear these interrupts! */
-		if (status_change & ATMEL_US_RI)
-			port->icount.rng++;
-		if (status_change & ATMEL_US_DSR)
-			port->icount.dsr++;
-		if (status_change & ATMEL_US_DCD)
-			uart_handle_dcd_change(port, !(status & ATMEL_US_DCD));
-		if (status_change & ATMEL_US_CTS)
-			uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
-
-		wake_up_interruptible(&port->state->port.delta_msr_wait);
-
-		atmel_port->status_change = 0;
-	}
-
 	atmel_port->schedule_rx(port);
 
 	spin_unlock(&port->lock);
@@ -1833,7 +1825,6 @@ static int atmel_startup(struct uart_port *port)
 
 	/* Save current CSR for comparison in atmel_tasklet_func() */
 	atmel_port->irq_status_prev = atmel_get_lines_status(port);
-	atmel_port->irq_status = atmel_port->irq_status_prev;
 
 	/*
 	 * Finally, enable the serial port
-- 
2.5.0



From ludovic.desroches at atmel.com  Thu May 12 08:37:35 2016
From: ludovic.desroches at atmel.com (Ludovic Desroches)
Date: Thu, 12 May 2016 17:37:35 +0200
Subject: [PATCH 2/3] tty/serial: atmel: split tx and rx paths
In-Reply-To: <1463067456-6983-1-git-send-email-ludovic.desroches@atmel.com>
References: <1463067456-6983-1-git-send-email-ludovic.desroches@atmel.com>
Message-ID: <1463067456-6983-2-git-send-email-ludovic.desroches@atmel.com>

From: Nicolas Ferre <nicolas.ferre at atmel.com>

Split TX and RX paths to not schedule RX tasklet on TX events and vice versa.

Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>
---
 drivers/tty/serial/atmel_serial.c | 53 +++++++++++++++++++++++++--------------
 1 file changed, 34 insertions(+), 19 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 8854ac6..6c1ec7d 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -145,7 +145,8 @@ struct atmel_uart_port {
 	dma_cookie_t			cookie_rx;
 	struct scatterlist		sg_tx;
 	struct scatterlist		sg_rx;
-	struct tasklet_struct	tasklet;
+	struct tasklet_struct	tasklet_rx;
+	struct tasklet_struct	tasklet_tx;
 	unsigned int		irq_status_prev;
 	unsigned int		tx_len;
 
@@ -708,7 +709,7 @@ static void atmel_rx_chars(struct uart_port *port)
 		status = atmel_uart_readl(port, ATMEL_US_CSR);
 	}
 
-	tasklet_schedule(&atmel_port->tasklet);
+	tasklet_schedule(&atmel_port->tasklet_rx);
 }
 
 /*
@@ -779,7 +780,7 @@ static void atmel_complete_tx_dma(void *arg)
 	 * remaining data from the beginning of xmit->buf to xmit->head.
 	 */
 	if (!uart_circ_empty(xmit))
-		tasklet_schedule(&atmel_port->tasklet);
+		tasklet_schedule(&atmel_port->tasklet_tx);
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -964,7 +965,7 @@ static void atmel_complete_rx_dma(void *arg)
 	struct uart_port *port = arg;
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	tasklet_schedule(&atmel_port->tasklet);
+	tasklet_schedule(&atmel_port->tasklet_rx);
 }
 
 static void atmel_release_rx_dma(struct uart_port *port)
@@ -1004,7 +1005,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
 	if (dmastat == DMA_ERROR) {
 		dev_dbg(port->dev, "Get residue error, restart tasklet\n");
 		atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
-		tasklet_schedule(&atmel_port->tasklet);
+		tasklet_schedule(&atmel_port->tasklet_rx);
 		return;
 	}
 
@@ -1158,7 +1159,7 @@ static void atmel_uart_timer_callback(unsigned long data)
 	struct uart_port *port = (void *)data;
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	tasklet_schedule(&atmel_port->tasklet);
+	tasklet_schedule(&atmel_port->tasklet_rx);
 	mod_timer(&atmel_port->uart_timer, jiffies + uart_poll_timeout(port));
 }
 
@@ -1181,7 +1182,7 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 		if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
 			atmel_uart_writel(port, ATMEL_US_IDR,
 					  (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
-			tasklet_schedule(&atmel_port->tasklet);
+			tasklet_schedule(&atmel_port->tasklet_rx);
 		}
 
 		if (pending & (ATMEL_US_RXBRK | ATMEL_US_OVRE |
@@ -1193,7 +1194,7 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending)
 		if (pending & ATMEL_US_TIMEOUT) {
 			atmel_uart_writel(port, ATMEL_US_IDR,
 					  ATMEL_US_TIMEOUT);
-			tasklet_schedule(&atmel_port->tasklet);
+			tasklet_schedule(&atmel_port->tasklet_rx);
 		}
 	}
 
@@ -1223,7 +1224,7 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
 		/* Either PDC or interrupt transmission */
 		atmel_uart_writel(port, ATMEL_US_IDR,
 				  atmel_port->tx_done_mask);
-		tasklet_schedule(&atmel_port->tasklet);
+		tasklet_schedule(&atmel_port->tasklet_tx);
 	}
 }
 
@@ -1582,18 +1583,25 @@ static int atmel_prepare_rx_pdc(struct uart_port *port)
 /*
  * tasklet handling tty stuff outside the interrupt handler.
  */
-static void atmel_tasklet_func(unsigned long data)
+static void atmel_tasklet_rx_func(unsigned long data)
 {
 	struct uart_port *port = (struct uart_port *)data;
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
 	/* The interrupt handler does not take the lock */
 	spin_lock(&port->lock);
-
-	atmel_port->schedule_tx(port);
-
 	atmel_port->schedule_rx(port);
+	spin_unlock(&port->lock);
+}
 
+static void atmel_tasklet_tx_func(unsigned long data)
+{
+	struct uart_port *port = (struct uart_port *)data;
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+
+	/* The interrupt handler does not take the lock */
+	spin_lock(&port->lock);
+	atmel_port->schedule_tx(port);
 	spin_unlock(&port->lock);
 }
 
@@ -1777,7 +1785,8 @@ static int atmel_startup(struct uart_port *port)
 		return retval;
 	}
 
-	tasklet_enable(&atmel_port->tasklet);
+	tasklet_enable(&atmel_port->tasklet_rx);
+	tasklet_enable(&atmel_port->tasklet_tx);
 
 	/*
 	 * Initialize DMA (if necessary)
@@ -1906,8 +1915,10 @@ static void atmel_shutdown(struct uart_port *port)
 	 * Clear out any scheduled tasklets before
 	 * we destroy the buffers
 	 */
-	tasklet_disable(&atmel_port->tasklet);
-	tasklet_kill(&atmel_port->tasklet);
+	tasklet_disable(&atmel_port->tasklet_rx);
+	tasklet_disable(&atmel_port->tasklet_tx);
+	tasklet_kill(&atmel_port->tasklet_rx);
+	tasklet_kill(&atmel_port->tasklet_tx);
 
 	/*
 	 * Ensure everything is stopped and
@@ -2302,9 +2313,12 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
 	port->irq	= pdev->resource[1].start;
 	port->rs485_config	= atmel_config_rs485;
 
-	tasklet_init(&atmel_port->tasklet, atmel_tasklet_func,
+	tasklet_init(&atmel_port->tasklet_rx, atmel_tasklet_rx_func,
+			(unsigned long)port);
+	tasklet_init(&atmel_port->tasklet_tx, atmel_tasklet_tx_func,
 			(unsigned long)port);
-	tasklet_disable(&atmel_port->tasklet);
+	tasklet_disable(&atmel_port->tasklet_rx);
+	tasklet_disable(&atmel_port->tasklet_tx);
 
 	memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
 
@@ -2786,7 +2800,8 @@ static int atmel_serial_remove(struct platform_device *pdev)
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	int ret = 0;
 
-	tasklet_kill(&atmel_port->tasklet);
+	tasklet_kill(&atmel_port->tasklet_rx);
+	tasklet_kill(&atmel_port->tasklet_tx);
 
 	device_init_wakeup(&pdev->dev, 0);
 
-- 
2.5.0



From ludovic.desroches at atmel.com  Thu May 12 08:37:36 2016
From: ludovic.desroches at atmel.com (Ludovic Desroches)
Date: Thu, 12 May 2016 17:37:36 +0200
Subject: [PATCH 3/3] tty/serial: atmel: add comment for the ring buffer size
 macro
In-Reply-To: <1463067456-6983-1-git-send-email-ludovic.desroches@atmel.com>
References: <1463067456-6983-1-git-send-email-ludovic.desroches@atmel.com>
Message-ID: <1463067456-6983-3-git-send-email-ludovic.desroches@atmel.com>

There is a macro named ATMEL_SERIAL_RINGSIZE which suggesting that it
corresponds to the real size of the ring buffer. Let warn people that
there is a factor of four since allocation size is
sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE.

Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>
---
 drivers/tty/serial/atmel_serial.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 6c1ec7d..8570163 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -108,6 +108,12 @@ struct atmel_uart_char {
 	u16		ch;
 };
 
+/*
+ * Be careful, the real size of the ring buffer is
+ * sizeof(atmel_uart_char) * ATMEL_SERIAL_RINGSIZE. It means that ring buffer
+ * can contain up to 1024 characters in PIO mode and up to 4096 characters in
+ * DMA mode.
+ */
 #define ATMEL_SERIAL_RINGSIZE 1024
 
 /*
-- 
2.5.0



From arnd at arndb.de  Thu May 12 08:46:06 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 12 May 2016 17:46:06 +0200
Subject: [GIT PULL] at91: fixes for 4.6 #2
In-Reply-To: <1462979534-29347-1-git-send-email-nicolas.ferre@atmel.com>
References: <1462979534-29347-1-git-send-email-nicolas.ferre@atmel.com>
Message-ID: <4044486.EpCxRlo97u@wuerfel>

On Wednesday 11 May 2016 17:12:14 Nicolas Ferre wrote:
> Another regression reported by Richard yesterday and quickly fixed by Boris.
> Since this regression was introduced in 4.6-rc1 it would be great if you could
> take it before 4.6 is released.

Applied to fixes, thanks!

	Arnd


From stefan.wahren at i2se.com  Thu May 12 08:55:47 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Thu, 12 May 2016 17:55:47 +0200 (CEST)
Subject: [PATCH 0/4] add minimal bcm2835-sdram driver
In-Reply-To: <B30D094A-1E5A-4777-8F2A-C3D53AF89044@martin.sperl.org>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
 <1861597197.20753.36a104a6-5284-487f-b397-da7ff0407f1f.open-xchange@email.1und1.de>
 <B30D094A-1E5A-4777-8F2A-C3D53AF89044@martin.sperl.org>
Message-ID: <527736177.22944.36a104a6-5284-487f-b397-da7ff0407f1f.open-xchange@email.1und1.de>

Hi,

> Martin Sperl <kernel at martin.sperl.org> hat am 12. Mai 2016 um 17:28
> geschrieben:
> 
> 
> 
> > On 12.05.2016, at 16:50, Stefan Wahren <stefan.wahren at i2se.com> wrote:
> > 
> > Hi Martin,
> > 
> >> kernel at martin.sperl.org hat am 12. Mai 2016 um 14:38 geschrieben:
> >> 
> >> 
> >> From: Martin Sperl <kernel at martin.sperl.org>
> >> 
> >> As the sdram clock is a critical clock to the system
> >> the minimal bcm2835-sdram driver claims (and enables)
> >> this clock and also exposes the corresponding sdram
> >> registers via debugfs.
> > 
> > sounds like this driver should fix an clock handling issue. Unfortunately
> > this
> > isn't a solution in case the driver is disabled.
> Unfortunately there is no way around this - the driver has
> to be enabled so that the sdram clock or the parent pll,
> which typically is plld_core, never gets disabled.
> 
> The only other option would be marking the clock as critical
> for those legacy drivers.

i would prefer this option. Since this would be more a fix we could get this
faster in, it's more clear why we are doing that and less to review.

Did i miss a drawback?

Stefan

> 
> See also the discussions around the clock register for the
> sdram clock, where we have the ?normal? clock and some
> pll as well - even if the ?normal? clock is disabled, 
> then clearing the sdram register (or the parent) freezes
> the system.
> 
> > 
> > Does the GPU firmware handle the SDRAM controller or is it initialized by
> > bootcode?
> > 
> 
> AFAIK it is enabled in bootcode.bin and - as of now - the firmware
> updates refresh cycles when SOC temperatures change.
> FW checks every 30 seconds unless there is a key set in config.txt,
> which - supposedly - produces a slight impact every 30 seconds to
> the system.
> 
> Martin


From nicolas.ferre at atmel.com  Thu May 12 08:57:17 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Thu, 12 May 2016 17:57:17 +0200
Subject: [PATCH 3/3] tty/serial: atmel: add comment for the ring buffer
 size macro
In-Reply-To: <1463067456-6983-3-git-send-email-ludovic.desroches@atmel.com>
References: <1463067456-6983-1-git-send-email-ludovic.desroches@atmel.com>
 <1463067456-6983-3-git-send-email-ludovic.desroches@atmel.com>
Message-ID: <5734A7DD.8030705@atmel.com>

Le 12/05/2016 17:37, Ludovic Desroches a ?crit :
> There is a macro named ATMEL_SERIAL_RINGSIZE which suggesting that it
> corresponds to the real size of the ring buffer. Let warn people that
> there is a factor of four since allocation size is
> sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE.
> 
> Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>

Acked-by: Nicolas Ferre <nicolas.ferre at atmel.com>

Thanks!

> ---
>  drivers/tty/serial/atmel_serial.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index 6c1ec7d..8570163 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -108,6 +108,12 @@ struct atmel_uart_char {
>  	u16		ch;
>  };
>  
> +/*
> + * Be careful, the real size of the ring buffer is
> + * sizeof(atmel_uart_char) * ATMEL_SERIAL_RINGSIZE. It means that ring buffer
> + * can contain up to 1024 characters in PIO mode and up to 4096 characters in
> + * DMA mode.
> + */
>  #define ATMEL_SERIAL_RINGSIZE 1024
>  
>  /*
> 


-- 
Nicolas Ferre


From kernel at martin.sperl.org  Thu May 12 09:00:07 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Thu, 12 May 2016 18:00:07 +0200
Subject: [PATCH 3/4] ARM: dts: bcm2835: add the bcm2835-sdram-controller
 to the dt
In-Reply-To: <73859954.21004.36a104a6-5284-487f-b397-da7ff0407f1f.open-xchange@email.1und1.de>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
 <1463056732-5607-4-git-send-email-kernel@martin.sperl.org>
 <73859954.21004.36a104a6-5284-487f-b397-da7ff0407f1f.open-xchange@email.1und1.de>
Message-ID: <0DF5210B-0269-4E49-A8E4-A4A83FCAABCF@martin.sperl.org>


> On 12.05.2016, at 16:56, Stefan Wahren <stefan.wahren at i2se.com> wrote:
> 
> Hi,
> 
>> kernel at martin.sperl.org hat am 12. Mai 2016 um 14:38 geschrieben:
>> 
>> 
>> From: Martin Sperl <kernel at martin.sperl.org>
>> 
>> Add the bcm2835 sdram controller to the device tree.
>> 
>> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
>> ---
>> arch/arm/boot/dts/bcm283x.dtsi | 6 ++++++
>> 1 file changed, 6 insertions(+)
>> 
>> diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
>> index 8aaf193..9db9d97 100644
>> --- a/arch/arm/boot/dts/bcm283x.dtsi
>> +++ b/arch/arm/boot/dts/bcm283x.dtsi
>> @@ -22,6 +22,12 @@
>> 		#address-cells = <1>;
>> 		#size-cells = <1>;
>> 
>> +		memory-controller at 7e002000 {
>> +			compatible = "brcm,bcm2835-sdram";
>> +			reg = <0x7e002000 0x58>, <0x7e002800 0x58>;
> 
> where do you get these addresses?
I took this info based on the shared headers by broadcom:
https://github.com/msperl/rpi-registers/blob/master/md/README.md

And the bootrom code showed something similar that would point to
these registers.

Ic0 and ic1 register values also show the valid memory regions:
Especially IC[01]_SRC0 contains reference to the SRAM
size on the CM - 0x20000000
here the fump of devmem2: 
Value at address 0x3F00200C (0x76f3300c): 0x20000000.

But as you point out that may also be the interrupt controller for the VC4
cores?

It is probably the location where the VC4 interrupt table is situated.


> According to register documentation [1] the adresses belong to the interrupt
> controller.
> 
> Maybe 0x7ee00000 is the right address.
This would also fall in range with the cache register ranges:
0x7ee00000 SD
0x7ee01000 L2
0x7ee02000 L1 

L1 contains also IC0 and IC1 register names (L1_IC0_CONTROL et.al.)
so I guess this is what has set me in the wrong direction...

Thanks for pointing it out...

I guess I will need to amend the patchset for that?

Martin




From kernel at martin.sperl.org  Thu May 12 09:03:00 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Thu, 12 May 2016 18:03:00 +0200
Subject: [PATCH 0/4] add minimal bcm2835-sdram driver
In-Reply-To: <527736177.22944.36a104a6-5284-487f-b397-da7ff0407f1f.open-xchange@email.1und1.de>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
 <1861597197.20753.36a104a6-5284-487f-b397-da7ff0407f1f.open-xchange@email.1und1.de>
 <B30D094A-1E5A-4777-8F2A-C3D53AF89044@martin.sperl.org>
 <527736177.22944.36a104a6-5284-487f-b397-da7ff0407f1f.open-xchange@email.1und1.de>
Message-ID: <9C676BB7-E96C-4526-B0FD-2D441C1200CC@martin.sperl.org>


> On 12.05.2016, at 17:55, Stefan Wahren <stefan.wahren at i2se.com> wrote:
> 
> Hi,
> 
>> Martin Sperl <kernel at martin.sperl.org> hat am 12. Mai 2016 um 17:28
>> geschrieben:
>> 
>> 
>> 
>>> On 12.05.2016, at 16:50, Stefan Wahren <stefan.wahren at i2se.com> wrote:
>>> 
>>> Hi Martin,
>>> 
>>>> kernel at martin.sperl.org hat am 12. Mai 2016 um 14:38 geschrieben:
>>>> 
>>>> 
>>>> From: Martin Sperl <kernel at martin.sperl.org>
>>>> 
>>>> As the sdram clock is a critical clock to the system
>>>> the minimal bcm2835-sdram driver claims (and enables)
>>>> this clock and also exposes the corresponding sdram
>>>> registers via debugfs.
>>> 
>>> sounds like this driver should fix an clock handling issue. Unfortunately
>>> this
>>> isn't a solution in case the driver is disabled.
>> Unfortunately there is no way around this - the driver has
>> to be enabled so that the sdram clock or the parent pll,
>> which typically is plld_core, never gets disabled.
>> 
>> The only other option would be marking the clock as critical
>> for those legacy drivers.
> 
> i would prefer this option. Since this would be more a fix we could get this
> faster in, it's more clear why we are doing that and less to review.
> 
> Did i miss a drawback?

We had long discussions already on that - and HAND_OFF did not make
it into the kernel either.

I had hoped that this was simple enough.

Martin





From vinod.koul at intel.com  Thu May 12 09:09:50 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Thu, 12 May 2016 21:39:50 +0530
Subject: [RESEND PATCH v4 1/3] dmaengine: vdma: Add config structure to
 differentiate dmas
In-Reply-To: <1463046228-21651-2-git-send-email-appanad@xilinx.com>
References: <1463046228-21651-1-git-send-email-appanad@xilinx.com>
 <1463046228-21651-2-git-send-email-appanad@xilinx.com>
Message-ID: <20160512160950.GF2274@localhost>

On Thu, May 12, 2016 at 03:13:46PM +0530, Kedareswara rao Appana wrote:
> This patch adds config structure in the driver to differentiate
> AXI DMA's and to add more features(clock support etc..) to these DMA's.
> 
> Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
> ---
>  drivers/dma/xilinx/xilinx_vdma.c | 83 ++++++++++++++++++++++++----------------
>  1 file changed, 51 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
> index 626939b..1d50e05 100644
> --- a/drivers/dma/xilinx/xilinx_vdma.c
> +++ b/drivers/dma/xilinx/xilinx_vdma.c
> @@ -342,6 +342,10 @@ struct xilinx_dma_chan {
>  	void (*start_transfer)(struct xilinx_dma_chan *chan);
>  };
>  
> +struct dma_config {

xilinx_dma_config ?

This makes reader believe that thismight be coething related to dmaengine
core

>  static const struct of_device_id xilinx_dma_of_ids[] = {
> -	{ .compatible = "xlnx,axi-dma-1.00.a",
> -	  .data = (void *)XDMA_TYPE_AXIDMA },
> -	{ .compatible = "xlnx,axi-cdma-1.00.a",
> -	  .data = (void *)XDMA_TYPE_CDMA },
> -	{ .compatible = "xlnx,axi-vdma-1.00.a",
> -	  .data = (void *)XDMA_TYPE_VDMA },
> +	{ .compatible = "xlnx,axi-dma-1.00.a", .data = &axidma_config },
> +	{ .compatible = "xlnx,axi-cdma-1.00.a", .data = &axicdma_config },
> +	{ .compatible = "xlnx,axi-vdma-1.00.a", .data = &axivdma_config },

why do we want a struct for this and not pass XDMA_TYPE_xxx as .data

-- 
~Vinod


From ynorov at caviumnetworks.com  Thu May 12 09:06:03 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 12 May 2016 19:06:03 +0300
Subject: [PATCH v2] arm64: fix current_thread_info()->addr_limit setup
Message-ID: <1463069163-374-1-git-send-email-ynorov@caviumnetworks.com>

At elf loading in flush_old_exec() in fs/exec.c, generic code sets
current_thread_info()->addr_limit to one that corresponds aarch64 value,
and ignores compat mode there as corresponding status setup happens
later on in load_elf_binary() by SET_PERSONALITY() macro. As result,
compat task has wrong addr_limit, and it may cause various bugs.

This patch fixes it. It also fixes USER_DS macro to return different
values depending on compat at runtime.

It was discovered during ilp32 development. See details here:
https://lkml.org/lkml/2016/5/11/975

v2:
 flush tpidrro_el0 unconditionally in tls_thread_flush() as if exec() is
 called by aarch64 task, is_compat_task() fails even if new thread is
 aarch32.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/include/asm/elf.h     | 11 +++++++++--
 arch/arm64/include/asm/uaccess.h |  2 +-
 arch/arm64/kernel/process.c      | 18 +++++++-----------
 3 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 24ed037..fda75ce 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -138,7 +138,10 @@ typedef struct user_fpsimd_state elf_fpregset_t;
  */
 #define ELF_PLAT_INIT(_r, load_addr)	(_r)->regs[0] = 0
 
-#define SET_PERSONALITY(ex)		clear_thread_flag(TIF_32BIT);
+#define SET_PERSONALITY(ex) do {					\
+	clear_thread_flag(TIF_32BIT);					\
+	set_fs(TASK_SIZE_64);						\
+} while (0)
 
 #define ARCH_DLINFO							\
 do {									\
@@ -181,7 +184,11 @@ typedef compat_elf_greg_t		compat_elf_gregset_t[COMPAT_ELF_NGREG];
 					 ((x)->e_flags & EF_ARM_EABI_MASK))
 
 #define compat_start_thread		compat_start_thread
-#define COMPAT_SET_PERSONALITY(ex)	set_thread_flag(TIF_32BIT);
+#define COMPAT_SET_PERSONALITY(ex) do {					\
+	set_thread_flag(TIF_32BIT);					\
+	set_fs(TASK_SIZE_32);						\
+} while (0)
+
 #define COMPAT_ARCH_DLINFO
 extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
 				      int uses_interp);
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 0685d74..5b269e6 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -60,7 +60,7 @@ extern int fixup_exception(struct pt_regs *regs);
 #define KERNEL_DS	(-1UL)
 #define get_ds()	(KERNEL_DS)
 
-#define USER_DS		TASK_SIZE_64
+#define USER_DS		TASK_SIZE
 #define get_fs()	(current_thread_info()->addr_limit)
 
 static inline void set_fs(mm_segment_t fs)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 8062482..2b25930 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -211,17 +211,13 @@ static void tls_thread_flush(void)
 {
 	asm ("msr tpidr_el0, xzr");
 
-	if (is_compat_task()) {
-		current->thread.tp_value = 0;
-
-		/*
-		 * We need to ensure ordering between the shadow state and the
-		 * hardware state, so that we don't corrupt the hardware state
-		 * with a stale shadow state during context switch.
-		 */
-		barrier();
-		asm ("msr tpidrro_el0, xzr");
-	}
+	/*
+	 * We need to ensure ordering between the shadow state and the
+	 * hardware state, so that we don't corrupt the hardware state
+	 * with a stale shadow state during context switch.
+	 */
+	barrier();
+	asm ("msr tpidrro_el0, xzr");
 }
 
 void flush_thread(void)
-- 
2.5.0



From appana.durga.rao at xilinx.com  Thu May 12 09:09:32 2016
From: appana.durga.rao at xilinx.com (Appana Durga Kedareswara Rao)
Date: Thu, 12 May 2016 16:09:32 +0000
Subject: [RESEND PATCH v4 1/3] dmaengine: vdma: Add config structure to
 differentiate dmas
In-Reply-To: <20160512160950.GF2274@localhost>
References: <1463046228-21651-1-git-send-email-appanad@xilinx.com>
 <1463046228-21651-2-git-send-email-appanad@xilinx.com>
 <20160512160950.GF2274@localhost>
Message-ID: <C246CAC1457055469EF09E3A7AC4E11A4A5812A5@XAP-PVEXMBX01.xlnx.xilinx.com>

Hi Vinod,

> On Thu, May 12, 2016 at 03:13:46PM +0530, Kedareswara rao Appana wrote:
> > This patch adds config structure in the driver to differentiate AXI
> > DMA's and to add more features(clock support etc..) to these DMA's.
> >
> > Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
> > ---
> >  drivers/dma/xilinx/xilinx_vdma.c | 83
> > ++++++++++++++++++++++++----------------
> >  1 file changed, 51 insertions(+), 32 deletions(-)
> >
> > diff --git a/drivers/dma/xilinx/xilinx_vdma.c
> > b/drivers/dma/xilinx/xilinx_vdma.c
> > index 626939b..1d50e05 100644
> > --- a/drivers/dma/xilinx/xilinx_vdma.c
> > +++ b/drivers/dma/xilinx/xilinx_vdma.c
> > @@ -342,6 +342,10 @@ struct xilinx_dma_chan {
> >  	void (*start_transfer)(struct xilinx_dma_chan *chan);  };
> >
> > +struct dma_config {
> 
> xilinx_dma_config ?

Ok will fix in the next version...

> 
> This makes reader believe that thismight be coething related to dmaengine core
> 
> >  static const struct of_device_id xilinx_dma_of_ids[] = {
> > -	{ .compatible = "xlnx,axi-dma-1.00.a",
> > -	  .data = (void *)XDMA_TYPE_AXIDMA },
> > -	{ .compatible = "xlnx,axi-cdma-1.00.a",
> > -	  .data = (void *)XDMA_TYPE_CDMA },
> > -	{ .compatible = "xlnx,axi-vdma-1.00.a",
> > -	  .data = (void *)XDMA_TYPE_VDMA },
> > +	{ .compatible = "xlnx,axi-dma-1.00.a", .data = &axidma_config },
> > +	{ .compatible = "xlnx,axi-cdma-1.00.a", .data = &axicdma_config },
> > +	{ .compatible = "xlnx,axi-vdma-1.00.a", .data = &axivdma_config },
> 
> why do we want a struct for this and not pass XDMA_TYPE_xxx as .data

In the next patch of this series added clock configuration in the config structure.
As the number clocks for each of the IP varies and the clocks are configurable
That's why added a separate config struct instead of XDMA_TYPE...

Regards,
Kedar.

> 
> --
> ~Vinod


From catalin.marinas at arm.com  Thu May 12 09:24:49 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 12 May 2016 17:24:49 +0100
Subject: [PATCH v6 13/14] arm64, acpi, numa: NUMA support based on SRAT
 and SLIT
In-Reply-To: <5734A0CC.8010600@caviumnetworks.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <1461780436-27182-14-git-send-email-ddaney.cavm@gmail.com>
 <20160511103929.GC3051@e104818-lin.cambridge.arm.com>
 <5733C8F5.6090206@caviumnetworks.com>
 <20160512094915.GD11226@e104818-lin.cambridge.arm.com>
 <5734A0CC.8010600@caviumnetworks.com>
Message-ID: <20160512162449.GK11226@e104818-lin.cambridge.arm.com>

On Thu, May 12, 2016 at 08:27:08AM -0700, David Daney wrote:
> On 05/12/2016 02:49 AM, Catalin Marinas wrote:
> >On Wed, May 11, 2016 at 05:06:13PM -0700, David Daney wrote:
> >>On 05/11/2016 03:39 AM, Catalin Marinas wrote:
> [...]
> >>>
> >>>I wonder whether you could replace the get_mpidr_in_madt() function with
> >>>something like acpi_get_phys_id(). It looks like get_mpidr_in_madt()
> >>>duplicates functionality already available elsewhere.
> >>
> >>I just tried that, and it doesn't work.
> >>
> >>The problem is that this code is being run very early in the boot, and
> >>kmalloc cannot be used.  acpi_get_phys_id() and its ilk can only be used
> >>once we have working kmalloc.  We need to extract the NUMA information early
> >>like this precisely because it is needed to initializing the slab system
> >>
> >>Notice that we are using early_acpi_os_unmap_memory() et al. in
> >>get_mpidr_in_madt() explicitly for this reason.
> >>
> >>In summary: I don't think we need another revision of this patch, it is like
> >>this for a good reason.
> >
> >Slightly confusing, in another reply you said you are going to address
> >my comment. So, is it doable?
> 
> I don't think so.
> 
> My previous reply, to the thread in 0/14, was prematurely made with the
> incorrect assumption that it was a simple change.  Now, after really digging
> in to the code, and attempting to do as you suggested, I have changed my
> mind.

Would the snippet below help with avoiding any kmalloc calls? At a quick
look, it seems that it's only map_mat_entry() that ends up using
kmalloc() calls. Alternatively, exporting map_madt_entry() may work as
well.

diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 33a38d604630..77af0a7df914 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -152,6 +152,9 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
 	struct acpi_subtable_header *header;
 	phys_cpuid_t phys_id = PHYS_CPUID_INVALID;
 
+	if (!acpi_gbl_permanent_mmap)
+		return phys_id;
+
 	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
 		goto exit;
 

-- 
Catalin


From tony at atomide.com  Thu May 12 09:30:34 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 12 May 2016 09:30:34 -0700
Subject: [RFC PATCH 0/3] Add ioremap_exec and extend drivers/misc/sram.c
In-Reply-To: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
References: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
Message-ID: <20160512163033.GP5995@atomide.com>

* Dave Gerlach <d-gerlach at ti.com> [160509 14:44]:
> Hi,
> There are several instances when one would want to execute out of on-chip
> SRAM, such as PM code on ARM platforms, so once again revisiting this
> series to allow that. Seems that having a solution for allowing SRAM to be
> mapped as executable will help clean up PM code on several ARM platforms and
> also open the door for others like TI AM335x and AM437x. This was first sent
> here [1] but this is rebased and updated for v4.6-rc.
> 
> Many platforms have migrated to using the generic SRAM driver at
> drivers/misc/sram.c but it doesn't seem like there is a clean solution
> for the common problem of needing to map executable pages.
> 
> Currently I see several platforms (at-91, imx6, socfpga) taking the
> address allocated by the genpool given by the SRAM driver and then calling
> __arm_ioremap_exec on it again to get a new address that can be executed.
> This doesn't seem like the cleanest solution, but maybe it works for code
> that is under mach-xxx but what about code that migrates outside into the
> drivers layer? Do any other architectures have a requirement for this?
> 
> I've converted omap3 PM code to use the generic SRAM driver which I'll send
> in a series right after this one, and AM335x and AM437x can both make use of
> this series as well and even go as far as to move a chunk of the PM
> code into drivers (needs to be updated but sent long ago here [2]), but
> that will be blocked if we don't have a generic way to ioremap memory as
> exec, or at least a way to do it from drivers/.
> 
> If we don't want to go down this path, is there a better idea for how to
> call ioremap_exec from drivers/ that we can all agree on?

Looks to me that this should allow moving the current SRAM code
into drivers. So feel free to add:

Acked-by: Tony Lindgren <tony at atomide.com>


From kevin.brodsky at arm.com  Thu May 12 09:39:15 2016
From: kevin.brodsky at arm.com (Kevin Brodsky)
Date: Thu, 12 May 2016 17:39:15 +0100
Subject: [PATCH RESEND] arm64: fix vdso-offsets.h dependency
Message-ID: <1463071155-7435-1-git-send-email-kevin.brodsky@arm.com>

arm64/kernel/{vdso,signal}.c include vdso-offsets.h, as well as any
file that includes asm/vdso.h. Therefore, vdso-offsets.h must be
generated before these files are compiled.

The current rules in arm64/kernel/Makefile do not actually enforce
this, because even though $(obj)/vdso is listed as a prerequisite for
vdso-offsets.h, this does not result in the intended effect of
building the vdso subdirectory (before all the other objects). As a
consequence, depending on the order in which the rules are followed,
vdso-offsets.h is updated or not before arm64/kernel/{vdso,signal}.o
are built. The current rules also impose an unnecessary dependency on
vdso-offsets.h for all arm64/kernel/*.o, resulting in unnecessary
rebuilds. This is made obvious when using make -j:

  touch arch/arm64/kernel/vdso/gettimeofday.S && make -j$NCPUS arch/arm64/kernel

will sometimes result in none of arm64/kernel/*.o being
rebuilt, sometimes all of them, or even just some of them.

It is quite difficult to ensure that a header is generated before it
is used with recursive Makefiles by using normal rules.  Instead,
arch-specific generated headers are normally built in the archprepare
recipe in the arch Makefile (see for instance arch/ia64/Makefile).
Unfortunately, asm-offsets.h is included in gettimeofday.S, and must
therefore be generated before vdso-offsets.h, which is not the case if
archprepare is used. For this reason, a rule run after archprepare has
to be used.

This commit adds rules in arm64/Makefile to build vdso-offsets.h
during the prepare step, ensuring that vdso-offsets.h is generated
before building anything. It also removes the now-unnecessary
dependencies on vdso-offsets.h in arm64/kernel/Makefile. Finally, it
removes the duplication of asm-offsets.h between arm64/kernel/vdso/
and include/generated/ and makes include/generated/vdso-offsets.h a
target in arm64/kernel/vdso/Makefile.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
Cc: Michal Marek <mmarek at suse.com>
Signed-off-by: Kevin Brodsky <kevin.brodsky at arm.com>
---

Resending with linux-kbuild in cc, hopefully some people there will have
an opinion on this.

I am not completely satisfied with the fix, since it uses a hack with
the prepare and prepare0 rules that should not be used in arch
Makefiles. However, all of my other attempts (including explicit
dependencies on gettimeofday.S, etc. in arm64/kernel/Makefile) failed
in some way. Hopefully, a Makefile wizard will come up with a better
solution.

 arch/arm64/Makefile             | 10 ++++++++++
 arch/arm64/kernel/Makefile      |  4 ----
 arch/arm64/kernel/vdso/Makefile |  7 +++----
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 354d75402ace..7bb702a0f1e2 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -119,6 +119,16 @@ archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
 	$(Q)$(MAKE) $(clean)=$(boot)/dts
 
+# We need to generate vdso-offsets.h before compiling certain files in kernel/.
+# In order to do that, we should use the archprepare target, but we can't since
+# asm-offsets.h is included in some files used to generate vdso-offsets.h, and
+# asm-offsets.h is built in prepare0, for which archprepare is a dependency.
+# Therefore we need to generate the header after prepare0 has been made, hence
+# this hack.
+prepare: vdso_prepare
+vdso_prepare: prepare0
+	$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso include/generated/vdso-offsets.h
+
 define archhelp
   echo  '* Image.gz      - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)'
   echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 3793003e16a2..bab85990691d 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -50,7 +50,3 @@ obj-y					+= $(arm64-obj-y) vdso/
 obj-m					+= $(arm64-obj-m)
 head-y					:= head.o
 extra-y					+= $(head-y) vmlinux.lds
-
-# vDSO - this must be built first to generate the symbol offsets
-$(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h
-$(obj)/vdso/vdso-offsets.h: $(obj)/vdso
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index b467fd0a384b..62c84f7cb01b 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -23,7 +23,7 @@ GCOV_PROFILE := n
 ccflags-y += -Wl,-shared
 
 obj-y += vdso.o
-extra-y += vdso.lds vdso-offsets.h
+extra-y += vdso.lds
 CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
 
 # Force dependency (incbin is bad)
@@ -42,11 +42,10 @@ $(obj)/%.so: $(obj)/%.so.dbg FORCE
 gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
 quiet_cmd_vdsosym = VDSOSYM $@
 define cmd_vdsosym
-	$(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ && \
-	cp $@ include/generated/
+	$(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
 endef
 
-$(obj)/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
+include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
 	$(call if_changed,vdsosym)
 
 # Assembly rules for the .S files
-- 
2.8.0



From linux at armlinux.org.uk  Thu May 12 09:37:59 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Thu, 12 May 2016 17:37:59 +0100
Subject: [RFC PATCH 1/3] asm-generic: io: Add exec versions of ioremap
In-Reply-To: <1462830111-28172-2-git-send-email-d-gerlach@ti.com>
References: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
 <1462830111-28172-2-git-send-email-d-gerlach@ti.com>
Message-ID: <20160512163759.GW5783@n2100.arm.linux.org.uk>

On Mon, May 09, 2016 at 04:41:49PM -0500, Dave Gerlach wrote:
> diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
> index 66a978d05958..c6eef3c98074 100644
> --- a/arch/arm/mm/ioremap.c
> +++ b/arch/arm/mm/ioremap.c
> @@ -400,6 +400,20 @@ EXPORT_SYMBOL(ioremap_wc);
>   * clocks that would affect normal memory for example. Please see
>   * CONFIG_GENERIC_ALLOCATOR for allocating external memory.
>   */
> +void __iomem *ioremap_exec(resource_size_t res_cookie, size_t size)
> +{
> +	return arch_ioremap_caller(res_cookie, size, MT_MEMORY_RWX,
> +				   __builtin_return_address(0));
> +}
> +EXPORT_SYMBOL(ioremap_exec);
> +
> +void __iomem *ioremap_exec_nocache(resource_size_t res_cookie, size_t size)
> +{
> +	return arch_ioremap_caller(res_cookie, size, MT_MEMORY_RWX_NONCACHED,
> +				   __builtin_return_address(0));
> +}
> +EXPORT_SYMBOL(ioremap_exec_nocache);

I think these should be called memremap_exec() and similar.  Please
see the description of memremap() in kernel/memremap.c.  If you're
going to be executing code, the region must not have I/O side effects
and according to the new definition of memremap() vs ioremap(), the
memremap() interfaces fit better.

Please also get these reviewed by Dan Williams who provided the
memremap() API.

Thanks.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From tony at atomide.com  Thu May 12 09:42:01 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 12 May 2016 09:42:01 -0700
Subject: [PATCH v3 0/7] ARM/ASoC: OMAP3: Fix McBSP2/3 sidetone support
In-Reply-To: <69ff65ee-e5d1-09fb-fd91-8d7b4d8fdda4@ti.com>
References: <1461927202-17677-1-git-send-email-peter.ujfalusi@ti.com>
 <69ff65ee-e5d1-09fb-fd91-8d7b4d8fdda4@ti.com>
Message-ID: <20160512164201.GQ5995@atomide.com>

* Peter Ujfalusi <peter.ujfalusi at ti.com> [160511 01:46]:
> Tony, Paul,
> 
> On 04/29/16 13:53, Peter Ujfalusi wrote:
> > Hi,
> > 
> > Based on the ongoing discussion on v2 (ARM: OMAP3: Fix McBSP2/3 hwmod setup for
> > sidetone) I have dropped the removal of the sidetone hwmod and only corrected
> > it. The series now includes all related changes needed to have correct sidetone
> > support whenever we boot in legacy or in DT mode.
> > 
> > This time the ASoC part have dependency on earlier patches so they can not be
> > applied separately.
> 
> How should we proceed from here? I don't want to start designing the ST
> separation infrastructure which would be based on this series, but if there
> are outstanding issues found on this, I would need to go back to the drawing
> board.
> The separation will be mostly new code and code shuffle in ASoC, but for
> legacy I will need to build up something in arch as well, so I would need at
> least one release cycle to start with things.

Well looks like we have all the acks, so I can apply these. We have
not heard from Paul on this for a while, so let's wait few days for
that.

Meanwhile, Mark wanted to fix the subject for one of the patches, care
to repost that at least? Or the whole series with acks, could be a
pull request too against v4.6-rc1 :)

Regards,

Tony



From ray.jui at broadcom.com  Thu May 12 09:52:31 2016
From: ray.jui at broadcom.com (Ray Jui)
Date: Thu, 12 May 2016 09:52:31 -0700
Subject: [PATCH 1/2] arm64: dts: NS2: Add all of the UARTs
In-Reply-To: <CAC3K-4qbkt3DCgd6qurNo3V+++x70bbFC--aunR0DbCTBvBNZg@mail.gmail.com>
References: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
 <57341FCE.6050403@huawei.com>
 <CAC3K-4qbkt3DCgd6qurNo3V+++x70bbFC--aunR0DbCTBvBNZg@mail.gmail.com>
Message-ID: <befabac6-aae2-fb3b-2faa-5463b7287b2a@broadcom.com>

Hi Kefeng,

On 5/12/2016 7:46 AM, Jon Mason wrote:
>
>
> On Thu, May 12, 2016 at 2:16 AM, Kefeng Wang <wangkefeng.wang at huawei.com
> <mailto:wangkefeng.wang at huawei.com>> wrote:
>
>
>
>     On 2016/5/12 6:56, Jon Mason wrote:
>     > Add all of the UARTs present on NS2 and enable them in the SVK device
>     > tree file.  Also, do some magic to make sure that uart3 is discovered as
>     > ttyS0 (as that is the console UART).
>     >
>     > Signed-off-by: Jon Mason <jonmason at broadcom.com <mailto:jonmason at broadcom.com>>
>     > ---
>     >  arch/arm64/boot/dts/broadcom/ns2-svk.dts | 16 ++++++++++++++++
>     >  arch/arm64/boot/dts/broadcom/ns2.dtsi    | 30 ++++++++++++++++++++++++++++++
>     >  2 files changed, 46 insertions(+)
>     >
>     > diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
>     > index 7cd3640..b062a44 100644
>     > --- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts
>     > +++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
>     > @@ -40,10 +40,14 @@
>     >
>     >       aliases {
>     >               serial0 = &uart3;
>     > +             serial1 = &uart0;
>     > +             serial2 = &uart1;
>     > +             serial3 = &uart2;
>     >       };
>     >
>     >       chosen {
>     >               stdout-path = "serial0:115200n8";
>     > +             bootargs = "earlycon=uart8250,mmio32,0x66130000";
>
>     Hi Jon,
>
>     I submit a patch[1], with it, we can use earlycon without option to
>     enable early console
>     for "snps,dw-apb-uart", could you help me to test it, thanks.
>
>
> Adding your change and removing the line above does not cause earlycon
> to work for me.  Is there any additional changes necessary for this to work?
>
> Thanks,
> Jon
>

"OF_EARLYCON_DECLARE" doesn't seem to have a way to deal with DT 
properties? In the case of UART for NS2, it needs mmio32, configured 
with DT property "reg-io-width" set to 4. I don't think 
"OF_EARLYCON_DECLARE" is parsing that, which is likely the reason why it 
doesn't work for devices that required mmio32.

Thanks,

Ray


From tony at atomide.com  Thu May 12 09:57:56 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 12 May 2016 09:57:56 -0700
Subject: [PATCH] ARM: dts: omap5-igep0050: Correct hdmi regulator
In-Reply-To: <CAPjucKb2PLSZcD3YZ9xQk1F62ugFaGAkBBqMp5GmoWFd0H8Vfg@mail.gmail.com>
References: <1461925297-9734-1-git-send-email-peter.ujfalusi@ti.com>
 <6ee9d67a-e907-715a-f3f5-d90a470314c3@ti.com>
 <20160504172634.GS5995@atomide.com> <572A38FD.9050801@ti.com>
 <20160505184609.GB5995@atomide.com>
 <2822D1C2B9B19F4A8261F756A13373F801BEF7B4@DFLE11.ent.ti.com>
 <CAPjucKb+4vd8Ar3MATCuTx+9R36PeB0hbvwDaAD1KTZFCiVJEA@mail.gmail.com>
 <2822D1C2B9B19F4A8261F756A13373F801BF86D2@DFLE11.ent.ti.com>
 <2822D1C2B9B19F4A8261F756A13373F801BF8703@DFLE11.ent.ti.com>
 <CAPjucKb2PLSZcD3YZ9xQk1F62ugFaGAkBBqMp5GmoWFd0H8Vfg@mail.gmail.com>
Message-ID: <20160512165755.GR5995@atomide.com>

* Eduard Gavin <egavin at iseebcn.com> [160509 07:43]:
> Dear Nishanth,
>   In igepV5 the LDO7 is connected to:
>     VDDA_DSIPORTA - ball AA33
>     VDDA_DSIPORTC - ball AE33
>     VDDA_HDMI - ball AN25
>   LDO4 is connected to:
>     VPP1 - ball AD9

Thanks for the info, here's an updated patch with comments and now
using 1.8V instead of the 2.0V omap5-board-common.dtsi.

Regards,

Tony

8< -----------------
From: Tony Lindgren <tony at atomide.com>
Date: Mon, 9 May 2016 07:51:00 -0700
Subject: [PATCH] ARM: dts: Fix ldo7 source for HDMI on igepv5

Fix ldo7 source for HDMI on igepv5.

Suggested-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
Signed-off-by: Tony Lindgren <tony at atomide.com>

--- a/arch/arm/boot/dts/omap5-igep0050.dts
+++ b/arch/arm/boot/dts/omap5-igep0050.dts
@@ -35,6 +35,16 @@
 	};
 };
 
+/*
+ * LDO7 is used for HDMI: VDDA_DSIPORTA - ball AA33, VDDA_DSIPORTC - ball AE33
+ * VDDA_HDMI - ball AN25. LDO4 is: VPP1 - ball AD9.
+ */
+&ldo7_reg {
+	status = "okay";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+};
+
 &omap5_pmx_core {
 	i2c4_pins: pinmux_i2c4_pins {
 		pinctrl-single,pins = <


From robin.murphy at arm.com  Thu May 12 10:08:41 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 12 May 2016 18:08:41 +0100
Subject: [PATCH] arm64: Implement optimised IP checksum helpers
In-Reply-To: <a3d91ddf-565d-5cef-0a56-39154e3a00d2@broadcom.com>
References: <6ca77904d1eced60d86145dc5da361f3aefc6fec.1463062758.git.robin.murphy@arm.com>
 <a3d91ddf-565d-5cef-0a56-39154e3a00d2@broadcom.com>
Message-ID: <5734B899.3040207@arm.com>

Hi Luke,

On 12/05/16 16:34, Luke Starrett wrote:
> Hi Robin,
>
> I pulled this in to a userspace test app expecting that the __uint128_t
> type might cause GCC to emit 'ldp'.  Seems like that was that your
> intent based on your commit note.  Instead I see two 64b loads (ldr Xn),
> and a single 32b load (ldr Wn) for the trailing 4B.  This was with
> Linaro GCC 4.9-2015.06.

GCC 5 happily emits ldp there, but indeed I couldn't figure out how to 
convince GCC 4 to do so. From a quick ferret around in the GCC Git, it 
looks like the relevant optimisations may have only gone in post-4.9.

> Otherwise, the C cycle count looks good enough compared to the asm version.

Yeah, compiling as standalone functions with GCC 5 I get 19 instructions 
vs. 17 for the asm, but the loop logic gets optimised out completely 
when ihl is a compile-time constant (e.g. inet_gro_receive())

Cheers,
Robin.

>
> Thanks,
>
> Luke
>
>
> On 5/12/2016 10:26 AM, Robin Murphy wrote:
>> AArch64 is capable of 128-bit memory accesses without alignment
>> restrictions, which makes it both possible and highly practical to slurp
>> up a typical 20-byte IP header in just 2 loads. Implement our own
>> version of ip_fast_checksum() to take advantage of that, resulting in
>> considerably fewer instructions and memory accesses than the generic
>> version. We can also get more optimal code generation for csum_fold() by
>> defining it a slightly different way round from the generic version, so
>> throw that into the mix too.
>>
>> Suggested-by: Luke Starrett <luke.starrett at broadcom.com>
>> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
>> ---
>>
>> Having spent an evening poring over disassembler output, it turns out
>> that there's really no need to drop into asm for this, hurrah! I've
>> taken it for a spin on both big and little-endian, with no ill effects.
>>
>>   arch/arm64/include/asm/checksum.h | 49
>> +++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 49 insertions(+)
>>   create mode 100644 arch/arm64/include/asm/checksum.h
>>
>> diff --git a/arch/arm64/include/asm/checksum.h
>> b/arch/arm64/include/asm/checksum.h
>> new file mode 100644
>> index 000000000000..7e975ffce837
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/checksum.h
>> @@ -0,0 +1,49 @@
>> +/*
>> + * Copyright (C) 2016 ARM 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.
>> + *
>> + * 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.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +#ifndef __ASM_CHECKSUM_H
>> +#define __ASM_CHECKSUM_H
>> +
>> +static inline __sum16 csum_fold(__wsum csum)
>> +{
>> +    u32 sum = (__force u32)csum;
>> +    sum += (sum >> 16) | (sum << 16);
>> +    return ~(__force __sum16)(sum >> 16);
>> +}
>> +#define csum_fold csum_fold
>> +
>> +static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
>> +{
>> +    __uint128_t tmp;
>> +    u64 sum;
>> +
>> +    tmp = *(const __uint128_t *)iph;
>> +    iph += 16;
>> +    ihl -= 4;
>> +    tmp += ((tmp >> 64) | (tmp << 64));
>> +    sum = tmp >> 64;
>> +    do {
>> +        sum += *(const u32 *)iph;
>> +        iph += 4;
>> +    } while (--ihl);
>> +
>> +    sum += ((sum >> 32) | (sum << 32));
>> +    return csum_fold(sum >> 32);
>> +}
>> +#define ip_fast_csum ip_fast_csum
>> +
>> +#include <asm-generic/checksum.h>
>> +
>> +#endif    /* __ASM_CHECKSUM_H */
>



From tony at atomide.com  Thu May 12 10:08:57 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 12 May 2016 10:08:57 -0700
Subject: [PATCH 5/8] ARM: dts: AM437X-GP-EVM: Remove redundant regulator
 compatibles
In-Reply-To: <1462945691-904-6-git-send-email-j-keerthy@ti.com>
References: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
 <1462945691-904-6-git-send-email-j-keerthy@ti.com>
Message-ID: <20160512170857.GS5995@atomide.com>

Hi,

* Keerthy <j-keerthy at ti.com> [160510 22:56]:
> With the device tree parsing using the regulator framework
> there is a no longer a need for separate compatibles for
> individual regulator nodes. Hence removing them all.

Please resend the dts related clean-up patches separately
once the rest of the dependencies are merged. I'm unable to
keep track of these dependencies myself :)

Regards,

Tony


From tony at atomide.com  Thu May 12 10:12:44 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 12 May 2016 10:12:44 -0700
Subject: [PATCH] ARM: OMAP5 / DRA7: Introduce workaround for 801819
In-Reply-To: <1438876464-15424-1-git-send-email-nm@ti.com>
References: <1438876464-15424-1-git-send-email-nm@ti.com>
Message-ID: <20160512171244.GT5995@atomide.com>

* Nishanth Menon <nm at ti.com> [150806 08:57]:
> Add workaround for Cortex-A15 ARM erratum 801819 which says in summary
> that "A livelock can occur in the L2 cache arbitration that might
> prevent a snoop from completing. Under certain conditions this can
> cause the system to deadlock. "

Thanks for the late reminder, this has totally fallen through the
cracks. Applying into omap-for-v4.7/fixes. Once merged to mainline,
it can be requested for stable if needed.

Regards,

Tony


From robh at kernel.org  Thu May 12 10:20:27 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 12 May 2016 12:20:27 -0500
Subject: [PATCH v2 1/2] doc/devicetree: Add Aspeed VIC bindings
In-Reply-To: <1463014882.20290.203.camel@kernel.crashing.org>
References: <462797239-14765-1-git-send-email-joel@jms.id.au>
 <1462802317-27086-1-git-send-email-joel@jms.id.au>
 <1462802317-27086-2-git-send-email-joel@jms.id.au>
 <20160511143313.GA7426@rob-hp-laptop>
 <1463014882.20290.203.camel@kernel.crashing.org>
Message-ID: <CAL_JsqJDGmvDxm1kN1w6NQZs0JLeA-V=X_BWi=VOaMTwftLn-w@mail.gmail.com>

On Wed, May 11, 2016 at 8:01 PM, Benjamin Herrenschmidt
<benh at kernel.crashing.org> wrote:
> On Wed, 2016-05-11 at 09:33 -0500, Rob Herring wrote:
>> > +- interrupt-controller : Identifies the node as an interrupt controller
>> > +- #interrupt-cells : Specifies the number of cells needed to encode an
>> > +  interrupt source. The value shall be 1.
>>
>> No need for level vs. edge flags?
>
> That's an open question. Most interrupts are fixed. A handful of GPIOs
> can be configured either way. For now I am relying on uboot setting up
> the right config for them and I read it back at boot time, but we could
> make it part of the binding I suppose.

It is almost standard to just use 2 cells here even if reserved for
future use. Especially since the IP block seems to have registers to
control that.

>
>> > +- valid-sources : bitmask of valid irq sources
>>
>> Drop this. Either all interrupt controllers need this or none of
>> them do. The valid sources are the ones described in the DT.
>
> Looking at the code (I wrote that ages ago), this is only used for:

I'm guessing it came from the VIC binding. I never really liked the
property, but not enough to worry about it.

Rob


From catalin.marinas at arm.com  Thu May 12 10:22:03 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 12 May 2016 18:22:03 +0100
Subject: [PATCH v2] arm64: fix current_thread_info()->addr_limit setup
In-Reply-To: <1463069163-374-1-git-send-email-ynorov@caviumnetworks.com>
References: <1463069163-374-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <20160512172203.GL11226@e104818-lin.cambridge.arm.com>

On Thu, May 12, 2016 at 07:06:03PM +0300, Yury Norov wrote:
> diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
> index 24ed037..fda75ce 100644
> --- a/arch/arm64/include/asm/elf.h
> +++ b/arch/arm64/include/asm/elf.h
> @@ -138,7 +138,10 @@ typedef struct user_fpsimd_state elf_fpregset_t;
>   */
>  #define ELF_PLAT_INIT(_r, load_addr)	(_r)->regs[0] = 0
>  
> -#define SET_PERSONALITY(ex)		clear_thread_flag(TIF_32BIT);
> +#define SET_PERSONALITY(ex) do {					\
> +	clear_thread_flag(TIF_32BIT);					\
> +	set_fs(TASK_SIZE_64);						\
> +} while (0)
>  
>  #define ARCH_DLINFO							\
>  do {									\
> @@ -181,7 +184,11 @@ typedef compat_elf_greg_t		compat_elf_gregset_t[COMPAT_ELF_NGREG];
>  					 ((x)->e_flags & EF_ARM_EABI_MASK))
>  
>  #define compat_start_thread		compat_start_thread
> -#define COMPAT_SET_PERSONALITY(ex)	set_thread_flag(TIF_32BIT);
> +#define COMPAT_SET_PERSONALITY(ex) do {					\
> +	set_thread_flag(TIF_32BIT);					\
> +	set_fs(TASK_SIZE_32);						\
> +} while (0)
> +
>  #define COMPAT_ARCH_DLINFO
>  extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
>  				      int uses_interp);
> diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
> index 0685d74..5b269e6 100644
> --- a/arch/arm64/include/asm/uaccess.h
> +++ b/arch/arm64/include/asm/uaccess.h
> @@ -60,7 +60,7 @@ extern int fixup_exception(struct pt_regs *regs);
>  #define KERNEL_DS	(-1UL)
>  #define get_ds()	(KERNEL_DS)
>  
> -#define USER_DS		TASK_SIZE_64
> +#define USER_DS		TASK_SIZE

We can avoid the USER_DS change as long as SET_PERSONALITY updates the
thread's addr_limit. There are very few explicit set_fs(USER_DS) calls
and they are on the thread exit path (or exec).

That's unless we try to make a generic set_fs(USER_DS) addition to
something like setup_new_exec() and we wouldn't need the SET_PERSONALITY
changes:

diff --git a/fs/exec.c b/fs/exec.c
index c4010b8207a1..54cc537f5986 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1226,6 +1226,9 @@ EXPORT_SYMBOL(would_dump);
 
 void setup_new_exec(struct linux_binprm * bprm)
 {
+	/* set the address limit for the new executable */
+	set_fs(USER_DS);
+
 	arch_pick_mmap_layout(current->mm);
 
 	/* This is the point of no return */

>  #define get_fs()	(current_thread_info()->addr_limit)
>  
>  static inline void set_fs(mm_segment_t fs)
> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> index 8062482..2b25930 100644
> --- a/arch/arm64/kernel/process.c
> +++ b/arch/arm64/kernel/process.c
> @@ -211,17 +211,13 @@ static void tls_thread_flush(void)
>  {
>  	asm ("msr tpidr_el0, xzr");
>  
> -	if (is_compat_task()) {
> -		current->thread.tp_value = 0;
> -
> -		/*
> -		 * We need to ensure ordering between the shadow state and the
> -		 * hardware state, so that we don't corrupt the hardware state
> -		 * with a stale shadow state during context switch.
> -		 */
> -		barrier();
> -		asm ("msr tpidrro_el0, xzr");
> -	}
> +	/*
> +	 * We need to ensure ordering between the shadow state and the
> +	 * hardware state, so that we don't corrupt the hardware state
> +	 * with a stale shadow state during context switch.
> +	 */
> +	barrier();
> +	asm ("msr tpidrro_el0, xzr");
>  }

Why did you dropped tp_value initialisation? Context switching on native
64-bit tasks rely on copying the tpidr_el0 in and out of tp_value.
However, compat tasks use the read-only tpidrro_el0 register set
explicitly via a system call. Until this call happens, the TLS register
would contain some garbage after the thread has been switched back in.

-- 
Catalin


From andy.gross at linaro.org  Thu May 12 10:58:30 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 12:58:30 -0500
Subject: [PATCH 1/2] i2c: qup: Cleared the error bits in ISR
In-Reply-To: <20160512061843.GA6187@chewinlnx07.qualcomm.com>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
 <1462797871-8595-2-git-send-email-absahu@codeaurora.org>
 <000701d1ab9d$df9b3100$9ed19300$@codeaurora.org>
 <934365f2bd30f242d8548e2a27483679@codeaurora.org>
 <20160512051347.GE8453@hector.attlocal.net>
 <20160512061843.GA6187@chewinlnx07.qualcomm.com>
Message-ID: <20160512175830.GA32019@hector>

On Thu, May 12, 2016 at 11:48:43AM +0530, Abhishek Sahu wrote:
> On Thu, May 12, 2016 at 12:13:47AM -0500, Andy Gross wrote:
> > On Wed, May 11, 2016 at 11:04:17PM +0530, Abhishek Sahu wrote:
> > 
> > <snip>
> > 
> > > >       In qup_i2c_xfer and qup_i2c_xfer_v2 state is set to RESET at the
> > > >end, when
> > > >       there is no error. So would it be fine if we do it there
> > > >unconditionally ?
> > > >
> > > >Regards,
> > > > Sricharan
> > > 
> > > RESET the QUP state wouldn't create any issue in the case of multiple calls.
> > > The existing code also RESET the QUP state for bus_err but it is not
> > > clearing
> > > status bits.
> > 
> > It'd be better to not reset the QUP inside the ISR at all.  I think the better
> > solution is making the reset occur in the xfer function.  So just clear the bits
> > like you should in the isr, and defer reset till later.
> 
> This is a HW workaround for QUP where we need to RESET the core in
> ISR. When interrupt is level triggerd, more than one interrupt may
> fire in error cases and QUP will generate these interrupts after
> completion of current interrupt. Thus we reset the core immediately
> in the ISR to ward off the next interrupt.

I wonder if that was just an expedient solution.  And it seems like it could be
a little racy as a poll is not being done to make sure the QUP state machine
transitions to reset.  Is there any documentation/errata on this?  Or is this
just from commit comments?


Regards,
Andy


From dianders at chromium.org  Thu May 12 11:03:17 2016
From: dianders at chromium.org (Douglas Anderson)
Date: Thu, 12 May 2016 11:03:17 -0700
Subject: [PATCH 2/2] clk: rockchip: fix the rk3399 sdmmc sample shift
In-Reply-To: <1463076197-15900-1-git-send-email-dianders@chromium.org>
References: <1463076197-15900-1-git-send-email-dianders@chromium.org>
Message-ID: <1463076197-15900-2-git-send-email-dianders@chromium.org>

Just like every other Rockhip device, the MMC "_sample" clocks should
have a shift of 0, not a shift of 1.  The rk3399 TRM agrees.  Presumably
these values were set to 0 because of a typo.

Things _sorta_ would have worked with the incorrect sample phase shift
because of the register layout but wouldn't have been ideal and we would
have skipped lots of phases.  Also: we would never actually enabled the
fine delay unless we happened to have 128 or more delay elements.

This is expected behavior before this patch:
* Try to set:     0 degrees +   1 delay elements
  Actually get:   0 degrees +   0 delay elements
* Try to set:    90 degrees +   0 delay elements
  Actually get: 180 degrees +   0 delay elements
* Try to set:   180 degrees +   0 delay elements
  Actually get:   0 degrees +   0 delay elements
* Try to set:   270 degrees +   0 delay elements
  Actually get: 180 degrees +   0 delay elements
* Try to set:     0 degrees + 129 delay elements
  Actually get:   0 degrees +   2 delay elements
* Try to set:   180 degrees + 129 delay elements
  Actually get:   0 degrees +   3 delay elements
* Try to set:     0 degrees + 130 delay elements
  Actually get:   0 degrees +   4 delay elements

I verified that old code had a problem by turning on debug printouts and
seeing that the old code would report this for one SD card I had:
  Good phase range 347-101 (115 len)
  Good phase range 202-326 (125 len)

After my fix, it went down to one big good range for the same card.
This is more expected:
  Good phase range 189-1 (173 len)
  Good phase range 82-85 (4 len)
  Good phase range 166-168 (3 len)

Signed-off-by: Douglas Anderson <dianders at chromium.org>
---
 drivers/clk/rockchip/clk-rk3399.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
index 291543f52caa..14ff3e109e1e 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -895,10 +895,10 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
 			RK3399_CLKGATE_CON(6), 1, GFLAGS),
 
 	MMC(SCLK_SDMMC_DRV,     "sdmmc_drv",    "clk_sdmmc", RK3399_SDMMC_CON0, 1),
-	MMC(SCLK_SDMMC_SAMPLE,  "sdmmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 1),
+	MMC(SCLK_SDMMC_SAMPLE,  "sdmmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 0),
 
 	MMC(SCLK_SDIO_DRV,      "sdio_drv",    "clk_sdio",  RK3399_SDIO_CON0,  1),
-	MMC(SCLK_SDIO_SAMPLE,   "sdio_sample", "clk_sdio",  RK3399_SDIO_CON1,  1),
+	MMC(SCLK_SDIO_SAMPLE,   "sdio_sample", "clk_sdio",  RK3399_SDIO_CON1,  0),
 
 	/* pcie */
 	COMPOSITE(SCLK_PCIE_PM, "clk_pcie_pm", mux_pll_src_cpll_gpll_npll_24m_p, 0,
-- 
2.8.0.rc3.226.g39d4020



From dianders at chromium.org  Thu May 12 11:03:16 2016
From: dianders at chromium.org (Douglas Anderson)
Date: Thu, 12 May 2016 11:03:16 -0700
Subject: [PATCH 1/2] Revert "clk: rockchip: reset init state before mmc card
 initialization"
Message-ID: <1463076197-15900-1-git-send-email-dianders@chromium.org>

This reverts commit 7a03fe6f48f3 ("clk: rockchip: reset init state
before mmc card initialization").

Though not totally obvious from the commit message nor from the source
code, that commit appears to be trying to reset the "_drv" MMC clocks to
90 degrees (note that the "_sample" MMC clocks have a shift of 0 so are
not touched).

The major problem here is that it doesn't properly reset things.  The
phase is a two bit field and the commit only touches one of the two
bits.  Thus the commit had the following affect:
- phase   0  => phase  90
- phase  90  => phase  90
- phase 180  => phase 270
- phase 270  => phase 270

Things get even weirder if you happen to have a bootloader that was
actually using delay elements (should be no reason to, but you never
know), since those are additional bits that weren't touched by the
original patch.

This is unlikely to be what we actually want.  Checking on rk3288-veyron
devices, I can see that the bootloader leaves these clocks as:
- emmc:  phase 180
- sdmmc: phase 90
- sdio0: phase 90

Thus on rk3288-veyron devices the commit we're reverting had the effect
of changing the eMMC clock to phase 270.  This probably explains the
scattered reports I've heard of eMMC devices not working on some veyron
devices when using the upstream kernel.

The original commit was presumably made because previously the kernel
didn't touch the "_drv" phase at all and relied on whatever value was
there when the kernel started.  If someone was using a bootloader that
touched the "_drv" phase then, indeed, we should have code in the kernel
to fix that.  ...and also, to get ideal timings, we should also have the
kernel change the phase depending on the speed mode.  In fact, that's
the subject of a recent patch I posted at
<https://patchwork.kernel.org/patch/9075141/>.

Ideally, we should take both the patch posted to dw_mmc and this
revert.  Since those will likely go through different trees, here I
describe behavior with the combos:

1. Just this revert: likely will fix rk3288-veyron eMMC on some devices
   + other cases; might break someone with a strange bootloader that
   sets the phase to 0 or one that uses delay elements (pretty
   unpredicable what would happen in that case).
2. Just dw_mmc patch: fixes everyone.  Effectly the dw_mmc patch will
   totally override the broken patch and fix everything.
3. Both patches: fixes everyone.  Once dw_mmc is initting properly then
   any defaults from the clock code doesn't mattery.

Fixes: 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card initialization")
Signed-off-by: Douglas Anderson <dianders at chromium.org>
---
 drivers/clk/rockchip/clk-mmc-phase.c | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
index bc856f21f6b2..5b18265c2306 100644
--- a/drivers/clk/rockchip/clk-mmc-phase.c
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
@@ -41,8 +41,6 @@ static unsigned long rockchip_mmc_recalc(struct clk_hw *hw,
 #define ROCKCHIP_MMC_DEGREE_MASK 0x3
 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
-#define ROCKCHIP_MMC_INIT_STATE_RESET 0x1
-#define ROCKCHIP_MMC_INIT_STATE_SHIFT 1
 
 #define PSECS_PER_SEC 1000000000000LL
 
@@ -162,15 +160,6 @@ struct clk *rockchip_clk_register_mmc(const char *name,
 	mmc_clock->reg = reg;
 	mmc_clock->shift = shift;
 
-	/*
-	 * Assert init_state to soft reset the CLKGEN
-	 * for mmc tuning phase and degree
-	 */
-	if (mmc_clock->shift == ROCKCHIP_MMC_INIT_STATE_SHIFT)
-		writel(HIWORD_UPDATE(ROCKCHIP_MMC_INIT_STATE_RESET,
-				     ROCKCHIP_MMC_INIT_STATE_RESET,
-				     mmc_clock->shift), mmc_clock->reg);
-
 	clk = clk_register(NULL, &mmc_clock->hw);
 	if (IS_ERR(clk))
 		kfree(mmc_clock);
-- 
2.8.0.rc3.226.g39d4020



From ynorov at caviumnetworks.com  Thu May 12 11:03:42 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 12 May 2016 21:03:42 +0300
Subject: [PATCH v2] arm64: fix current_thread_info()->addr_limit setup
In-Reply-To: <20160512172203.GL11226@e104818-lin.cambridge.arm.com>
References: <1463069163-374-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512172203.GL11226@e104818-lin.cambridge.arm.com>
Message-ID: <20160512175154.GA13383@yury-N73SV>

On Thu, May 12, 2016 at 06:22:03PM +0100, Catalin Marinas wrote:
> On Thu, May 12, 2016 at 07:06:03PM +0300, Yury Norov wrote:
> > diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
> > index 24ed037..fda75ce 100644
> > --- a/arch/arm64/include/asm/elf.h
> > +++ b/arch/arm64/include/asm/elf.h
> > @@ -138,7 +138,10 @@ typedef struct user_fpsimd_state elf_fpregset_t;
> >   */
> >  #define ELF_PLAT_INIT(_r, load_addr)	(_r)->regs[0] = 0
> >  
> > -#define SET_PERSONALITY(ex)		clear_thread_flag(TIF_32BIT);
> > +#define SET_PERSONALITY(ex) do {					\
> > +	clear_thread_flag(TIF_32BIT);					\
> > +	set_fs(TASK_SIZE_64);						\
> > +} while (0)
> >  
> >  #define ARCH_DLINFO							\
> >  do {									\
> > @@ -181,7 +184,11 @@ typedef compat_elf_greg_t		compat_elf_gregset_t[COMPAT_ELF_NGREG];
> >  					 ((x)->e_flags & EF_ARM_EABI_MASK))
> >  
> >  #define compat_start_thread		compat_start_thread
> > -#define COMPAT_SET_PERSONALITY(ex)	set_thread_flag(TIF_32BIT);
> > +#define COMPAT_SET_PERSONALITY(ex) do {					\
> > +	set_thread_flag(TIF_32BIT);					\
> > +	set_fs(TASK_SIZE_32);						\
> > +} while (0)
> > +
> >  #define COMPAT_ARCH_DLINFO
> >  extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
> >  				      int uses_interp);
> > diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
> > index 0685d74..5b269e6 100644
> > --- a/arch/arm64/include/asm/uaccess.h
> > +++ b/arch/arm64/include/asm/uaccess.h
> > @@ -60,7 +60,7 @@ extern int fixup_exception(struct pt_regs *regs);
> >  #define KERNEL_DS	(-1UL)
> >  #define get_ds()	(KERNEL_DS)
> >  
> > -#define USER_DS		TASK_SIZE_64
> > +#define USER_DS		TASK_SIZE
> 
> We can avoid the USER_DS change as long as SET_PERSONALITY updates the
> thread's addr_limit. There are very few explicit set_fs(USER_DS) calls
> and they are on the thread exit path (or exec).
> 
> That's unless we try to make a generic set_fs(USER_DS) addition to
> something like setup_new_exec() and we wouldn't need the SET_PERSONALITY
> changes:
> 

I think we'd better leave it fixed. Just because it's correct. Now it
looks like we have fixed early usages (before SET_PERSONALITY()) of
set_fs() explicitly, and normal usages (and possible in future) by
fixing USER_DS.

> diff --git a/fs/exec.c b/fs/exec.c
> index c4010b8207a1..54cc537f5986 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -1226,6 +1226,9 @@ EXPORT_SYMBOL(would_dump);
>  
>  void setup_new_exec(struct linux_binprm * bprm)
>  {
> +	/* set the address limit for the new executable */
> +	set_fs(USER_DS);
> +
>  	arch_pick_mmap_layout(current->mm);
>  
>  	/* This is the point of no return */
> 
> >  #define get_fs()	(current_thread_info()->addr_limit)
> >  
> >  static inline void set_fs(mm_segment_t fs)
> > diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> > index 8062482..2b25930 100644
> > --- a/arch/arm64/kernel/process.c
> > +++ b/arch/arm64/kernel/process.c
> > @@ -211,17 +211,13 @@ static void tls_thread_flush(void)
> >  {
> >  	asm ("msr tpidr_el0, xzr");
> >  
> > -	if (is_compat_task()) {
> > -		current->thread.tp_value = 0;
> > -
> > -		/*
> > -		 * We need to ensure ordering between the shadow state and the
> > -		 * hardware state, so that we don't corrupt the hardware state
> > -		 * with a stale shadow state during context switch.
> > -		 */
> > -		barrier();
> > -		asm ("msr tpidrro_el0, xzr");
> > -	}
> > +	/*
> > +	 * We need to ensure ordering between the shadow state and the
> > +	 * hardware state, so that we don't corrupt the hardware state
> > +	 * with a stale shadow state during context switch.
> > +	 */
> > +	barrier();
> > +	asm ("msr tpidrro_el0, xzr");
> >  }
> 
> Why did you dropped tp_value initialisation? Context switching on native
> 64-bit tasks rely on copying the tpidr_el0 in and out of tp_value.
> However, compat tasks use the read-only tpidrro_el0 register set
> explicitly via a system call. Until this call happens, the TLS register
> would contain some garbage after the thread has been switched back in.
> 

OOPS, my fault. I just missed a line. Should I send v3, or you or Arnd
can apply it and fix in your branch?

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


From stern at rowland.harvard.edu  Thu May 12 11:11:14 2016
From: stern at rowland.harvard.edu (Alan Stern)
Date: Thu, 12 May 2016 14:11:14 -0400 (EDT)
Subject: [PATCH] usb: ohci-at91: Suspend the ports while USB suspending
In-Reply-To: <1463015134-32364-1-git-send-email-wenyou.yang@atmel.com>
Message-ID: <Pine.LNX.4.44L0.1605121359120.5957-100000@netrider.rowland.org>

On Thu, 12 May 2016, Wenyou Yang wrote:

> In order to get lower consumption, as a workaround, suspend
> the USB PORTA/B/C via set the SUSPEND_A/B/C bits of OHCI Interrupt
> Configuration Register while OHCI USB suspending.

What does this mean?  What does suspending a port do?  Is it the same 
as a normal USB port suspend?

If it is the same, why doesn't the USB_PORT_FEAT_SUSPEND subcase of the 
SetPortFeature case in ohci_hub_control() already take care of this?

> This suspend operation must be done before stopping the USB clock,
> resume after the USB clock enabled.
> 
> Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> ---

> @@ -132,6 +135,17 @@ static void at91_stop_hc(struct platform_device *pdev)
>  
>  /*-------------------------------------------------------------------------*/
>  
> +struct regmap *at91_dt_syscon_sfr(void)
> +{
> +	struct regmap *regmap;
> +
> +	regmap = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
> +	if (IS_ERR(regmap))
> +		return NULL;

If you get an error, the regmap pointer is set to NULL...

> @@ -197,6 +211,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
>  		goto err;
>  	}
>  
> +	ohci_at91->sfr_regmap = at91_dt_syscon_sfr();

With no other error checking...

> +
>  	board = hcd->self.controller->platform_data;
>  	ohci = hcd_to_ohci(hcd);
>  	ohci->num_ports = board->ports;

> +static int ohci_at91_port_ctrl(struct regmap *regmap, bool enable)
> +{
> +	u32 regval;
> +	int ret;
> +
> +	if (IS_ERR(regmap))
> +		return PTR_ERR(regmap);
> +
> +	ret = regmap_read(regmap, SFR_OHCIICR, &regval);

And now what happens if regmap is NULL?  Hint: It won't be pretty...

Alan Stern



From pthomas8589 at gmail.com  Thu May 12 11:10:48 2016
From: pthomas8589 at gmail.com (Paul Thomas)
Date: Thu, 12 May 2016 14:10:48 -0400
Subject: [PATCH v4 3/5] dmaengine: vdma: Add Support for Xilinx AXI Direct
 Memory Access Engine
In-Reply-To: <1460006985-14805-4-git-send-email-appanad@xilinx.com>
References: <1460006985-14805-1-git-send-email-appanad@xilinx.com>
 <1460006985-14805-4-git-send-email-appanad@xilinx.com>
Message-ID: <CAD56B7fQWeDZDtKz2BgzpWSCMVdAGyUTBjUiuVnZ_8j51-SpoA@mail.gmail.com>

Nice Kedar!

Is this getting applied? I would really like to see this get into the mainline.

thanks,
Paul

On Thu, Apr 7, 2016 at 1:29 AM, Kedareswara rao Appana
<appana.durga.rao at xilinx.com> wrote:
> This patch adds support for the AXI Direct Memory Access (AXI DMA)
> core in the existing vdma driver, AXI DMA Core is a
> soft Xilinx IP core that provides high-bandwidth
> direct memory access between memory and AXI4-Stream
> type target peripherals.
>
> Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
> ---
> Changes for v4:
> ---> None.
> Changes for v3:
> ---> None.
> Changes for v2:
> ---> have differenet structures for h/w desc.
> ---> Added comments to the relevant sections as suggested by Laurent Pinchart.
> ---> Fixed trival code clean up/spacing issues as suggested by Laurent Pinchart
>
>  drivers/dma/xilinx/xilinx_vdma.c | 474 +++++++++++++++++++++++++++++++++++----
>  include/linux/dma/xilinx_dma.h   |  12 +
>  2 files changed, 444 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
> index b805a11..6ecf731 100644
> --- a/drivers/dma/xilinx/xilinx_vdma.c
> +++ b/drivers/dma/xilinx/xilinx_vdma.c
> @@ -16,6 +16,11 @@
>   * video device (S2MM). Initialization, status, interrupt and management
>   * registers are accessed through an AXI4-Lite slave interface.
>   *
> + * The AXI Direct Memory Access (AXI DMA) core is a soft Xilinx IP core that
> + * provides high-bandwidth one dimensional direct memory access between memory
> + * and AXI4-Stream target peripherals. It supports one receive and one
> + * transmit channel, both of them optional at synthesis time.
> + *
>   * 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
> @@ -140,6 +145,19 @@
>  /* Delay loop counter to prevent hardware failure */
>  #define XILINX_DMA_LOOP_COUNT          1000000
>
> +/* AXI DMA Specific Registers/Offsets */
> +#define XILINX_DMA_REG_SRCDSTADDR      0x18
> +#define XILINX_DMA_REG_BTT             0x28
> +
> +/* AXI DMA Specific Masks/Bit fields */
> +#define XILINX_DMA_MAX_TRANS_LEN       GENMASK(22, 0)
> +#define XILINX_DMA_CR_COALESCE_MAX     GENMASK(23, 16)
> +#define XILINX_DMA_CR_COALESCE_SHIFT   16
> +#define XILINX_DMA_BD_SOP              BIT(27)
> +#define XILINX_DMA_BD_EOP              BIT(26)
> +#define XILINX_DMA_COALESCE_MAX                255
> +#define XILINX_DMA_NUM_APP_WORDS       5
> +
>  /**
>   * struct xilinx_vdma_desc_hw - Hardware Descriptor
>   * @next_desc: Next Descriptor Pointer @0x00
> @@ -162,6 +180,30 @@ struct xilinx_vdma_desc_hw {
>  } __aligned(64);
>
>  /**
> + * struct xilinx_axidma_desc_hw - Hardware Descriptor for AXI DMA
> + * @next_desc: Next Descriptor Pointer @0x00
> + * @pad1: Reserved @0x04
> + * @buf_addr: Buffer address @0x08
> + * @pad2: Reserved @0x0C
> + * @pad3: Reserved @0x10
> + * @pad4: Reserved @0x14
> + * @control: Control field @0x18
> + * @status: Status field @0x1C
> + * @app: APP Fields @0x20 - 0x30
> + */
> +struct xilinx_axidma_desc_hw {
> +       u32 next_desc;
> +       u32 pad1;
> +       u32 buf_addr;
> +       u32 pad2;
> +       u32 pad3;
> +       u32 pad4;
> +       u32 control;
> +       u32 status;
> +       u32 app[XILINX_DMA_NUM_APP_WORDS];
> +} __aligned(64);
> +
> +/**
>   * struct xilinx_vdma_tx_segment - Descriptor segment
>   * @hw: Hardware descriptor
>   * @node: Node in the descriptor segments list
> @@ -174,6 +216,18 @@ struct xilinx_vdma_tx_segment {
>  } __aligned(64);
>
>  /**
> + * struct xilinx_axidma_tx_segment - Descriptor segment
> + * @hw: Hardware descriptor
> + * @node: Node in the descriptor segments list
> + * @phys: Physical address of segment
> + */
> +struct xilinx_axidma_tx_segment {
> +       struct xilinx_axidma_desc_hw hw;
> +       struct list_head node;
> +       dma_addr_t phys;
> +} __aligned(64);
> +
> +/**
>   * struct xilinx_dma_tx_descriptor - Per Transaction structure
>   * @async_tx: Async transaction descriptor
>   * @segments: TX segments list
> @@ -210,6 +264,9 @@ struct xilinx_dma_tx_descriptor {
>   * @desc_pendingcount: Descriptor pending count
>   * @ext_addr: Indicates 64 bit addressing is supported by dma channel
>   * @desc_submitcount: Descriptor h/w submitted count
> + * @residue: Residue for AXI DMA
> + * @seg_v: Statically allocated segments base
> + * @start_transfer: Differentiate b/w DMA IP's transfer
>   */
>  struct xilinx_dma_chan {
>         struct xilinx_dma_device *xdev;
> @@ -235,6 +292,9 @@ struct xilinx_dma_chan {
>         u32 desc_pendingcount;
>         bool ext_addr;
>         u32 desc_submitcount;
> +       u32 residue;
> +       struct xilinx_axidma_tx_segment *seg_v;
> +       void (*start_transfer)(struct xilinx_dma_chan *chan);
>  };
>
>  /**
> @@ -246,6 +306,7 @@ struct xilinx_dma_chan {
>   * @has_sg: Specifies whether Scatter-Gather is present or not
>   * @flush_on_fsync: Flush on frame sync
>   * @ext_addr: Indicates 64 bit addressing is supported by dma device
> + * @dmatype: DMA ip type
>   */
>  struct xilinx_dma_device {
>         void __iomem *regs;
> @@ -255,6 +316,7 @@ struct xilinx_dma_device {
>         bool has_sg;
>         u32 flush_on_fsync;
>         bool ext_addr;
> +       enum xdma_ip_type dmatype;
>  };
>
>  /* Macros */
> @@ -354,6 +416,39 @@ xilinx_vdma_alloc_tx_segment(struct xilinx_dma_chan *chan)
>  }
>
>  /**
> + * xilinx_axidma_alloc_tx_segment - Allocate transaction segment
> + * @chan: Driver specific DMA channel
> + *
> + * Return: The allocated segment on success and NULL on failure.
> + */
> +static struct xilinx_axidma_tx_segment *
> +xilinx_axidma_alloc_tx_segment(struct xilinx_dma_chan *chan)
> +{
> +       struct xilinx_axidma_tx_segment *segment;
> +       dma_addr_t phys;
> +
> +       segment = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &phys);
> +       if (!segment)
> +               return NULL;
> +
> +       memset(segment, 0, sizeof(*segment));
> +       segment->phys = phys;
> +
> +       return segment;
> +}
> +
> +/**
> + * xilinx_dma_free_tx_segment - Free transaction segment
> + * @chan: Driver specific DMA channel
> + * @segment: DMA transaction segment
> + */
> +static void xilinx_dma_free_tx_segment(struct xilinx_dma_chan *chan,
> +                               struct xilinx_axidma_tx_segment *segment)
> +{
> +       dma_pool_free(chan->desc_pool, segment, segment->phys);
> +}
> +
> +/**
>   * xilinx_vdma_free_tx_segment - Free transaction segment
>   * @chan: Driver specific DMA channel
>   * @segment: DMA transaction segment
> @@ -394,13 +489,22 @@ xilinx_dma_free_tx_descriptor(struct xilinx_dma_chan *chan,
>                                struct xilinx_dma_tx_descriptor *desc)
>  {
>         struct xilinx_vdma_tx_segment *segment, *next;
> +       struct xilinx_axidma_tx_segment *axidma_segment, *axidma_next;
>
>         if (!desc)
>                 return;
>
> -       list_for_each_entry_safe(segment, next, &desc->segments, node) {
> -               list_del(&segment->node);
> -               xilinx_vdma_free_tx_segment(chan, segment);
> +       if (chan->xdev->dmatype == XDMA_TYPE_VDMA) {
> +               list_for_each_entry_safe(segment, next, &desc->segments, node) {
> +                       list_del(&segment->node);
> +                       xilinx_vdma_free_tx_segment(chan, segment);
> +               }
> +       } else {
> +               list_for_each_entry_safe(axidma_segment, axidma_next,
> +                                        &desc->segments, node) {
> +                       list_del(&axidma_segment->node);
> +                       xilinx_dma_free_tx_segment(chan, axidma_segment);
> +               }
>         }
>
>         kfree(desc);
> @@ -452,6 +556,8 @@ static void xilinx_dma_free_chan_resources(struct dma_chan *dchan)
>         dev_dbg(chan->dev, "Free all channel resources.\n");
>
>         xilinx_dma_free_descriptors(chan);
> +       if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA)
> +               xilinx_dma_free_tx_segment(chan, chan->seg_v);
>         dma_pool_destroy(chan->desc_pool);
>         chan->desc_pool = NULL;
>  }
> @@ -520,10 +626,20 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
>          * We need the descriptor to be aligned to 64bytes
>          * for meeting Xilinx VDMA specification requirement.
>          */
> -       chan->desc_pool = dma_pool_create("xilinx_vdma_desc_pool",
> -                               chan->dev,
> -                               sizeof(struct xilinx_vdma_tx_segment),
> -                               __alignof__(struct xilinx_vdma_tx_segment), 0);
> +       if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA) {
> +               chan->desc_pool = dma_pool_create("xilinx_dma_desc_pool",
> +                                  chan->dev,
> +                                  sizeof(struct xilinx_axidma_tx_segment),
> +                                  __alignof__(struct xilinx_axidma_tx_segment),
> +                                  0);
> +       } else {
> +               chan->desc_pool = dma_pool_create("xilinx_vdma_desc_pool",
> +                                    chan->dev,
> +                                    sizeof(struct xilinx_vdma_tx_segment),
> +                                    __alignof__(struct xilinx_vdma_tx_segment),
> +                                    0);
> +       }
> +
>         if (!chan->desc_pool) {
>                 dev_err(chan->dev,
>                         "unable to allocate channel %d descriptor pool\n",
> @@ -531,7 +647,27 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
>                 return -ENOMEM;
>         }
>
> +       if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA)
> +               /*
> +                * For AXI DMA case after submitting a pending_list, keep
> +                * an extra segment allocated so that the "next descriptor"
> +                * pointer on the tail descriptor always points to a
> +                * valid descriptor, even when paused after reaching taildesc.
> +                * This way, it is possible to issue additional
> +                * transfers without halting and restarting the channel.
> +                */
> +               chan->seg_v = xilinx_axidma_alloc_tx_segment(chan);
> +
>         dma_cookie_init(dchan);
> +
> +       if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA) {
> +               /* For AXI DMA resetting once channel will reset the
> +                * other channel as well so enable the interrupts here.
> +                */
> +               dma_ctrl_set(chan, XILINX_DMA_REG_DMACR,
> +                             XILINX_DMA_DMAXR_ALL_IRQ_MASK);
> +       }
> +
>         return 0;
>  }
>
> @@ -547,7 +683,37 @@ static enum dma_status xilinx_dma_tx_status(struct dma_chan *dchan,
>                                         dma_cookie_t cookie,
>                                         struct dma_tx_state *txstate)
>  {
> -       return dma_cookie_status(dchan, cookie, txstate);
> +       struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
> +       struct xilinx_dma_tx_descriptor *desc;
> +       struct xilinx_axidma_tx_segment *segment;
> +       struct xilinx_axidma_desc_hw *hw;
> +       enum dma_status ret;
> +       unsigned long flags;
> +       u32 residue = 0;
> +
> +       ret = dma_cookie_status(dchan, cookie, txstate);
> +       if (ret == DMA_COMPLETE || !txstate)
> +               return ret;
> +
> +       if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA) {
> +               spin_lock_irqsave(&chan->lock, flags);
> +
> +               desc = list_last_entry(&chan->active_list,
> +                                      struct xilinx_dma_tx_descriptor, node);
> +               if (chan->has_sg) {
> +                       list_for_each_entry(segment, &desc->segments, node) {
> +                               hw = &segment->hw;
> +                               residue += (hw->control - hw->status) &
> +                                          XILINX_DMA_MAX_TRANS_LEN;
> +                       }
> +               }
> +               spin_unlock_irqrestore(&chan->lock, flags);
> +
> +               chan->residue = residue;
> +               dma_set_residue(txstate, chan->residue);
> +       }
> +
> +       return ret;
>  }
>
>  /**
> @@ -755,6 +921,91 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan)
>  }
>
>  /**
> + * xilinx_dma_start_transfer - Starts DMA transfer
> + * @chan: Driver specific channel struct pointer
> + */
> +static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
> +{
> +       struct xilinx_dma_tx_descriptor *head_desc, *tail_desc;
> +       struct xilinx_axidma_tx_segment *tail_segment, *old_head, *new_head;
> +       u32 reg;
> +
> +       if (chan->err)
> +               return;
> +
> +       if (list_empty(&chan->pending_list))
> +               return;
> +
> +       /* If it is SG mode and hardware is busy, cannot submit */
> +       if (chan->has_sg && xilinx_dma_is_running(chan) &&
> +           !xilinx_dma_is_idle(chan)) {
> +               dev_dbg(chan->dev, "DMA controller still busy\n");
> +               return;
> +       }
> +
> +       head_desc = list_first_entry(&chan->pending_list,
> +                                    struct xilinx_dma_tx_descriptor, node);
> +       tail_desc = list_last_entry(&chan->pending_list,
> +                                   struct xilinx_dma_tx_descriptor, node);
> +       tail_segment = list_last_entry(&tail_desc->segments,
> +                                      struct xilinx_axidma_tx_segment, node);
> +
> +       old_head = list_first_entry(&head_desc->segments,
> +                               struct xilinx_axidma_tx_segment, node);
> +       new_head = chan->seg_v;
> +       /* Copy Buffer Descriptor fields. */
> +       new_head->hw = old_head->hw;
> +
> +       /* Swap and save new reserve */
> +       list_replace_init(&old_head->node, &new_head->node);
> +       chan->seg_v = old_head;
> +
> +       tail_segment->hw.next_desc = chan->seg_v->phys;
> +       head_desc->async_tx.phys = new_head->phys;
> +
> +       reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
> +
> +       if (chan->desc_pendingcount <= XILINX_DMA_COALESCE_MAX) {
> +               reg &= ~XILINX_DMA_CR_COALESCE_MAX;
> +               reg |= chan->desc_pendingcount <<
> +                                 XILINX_DMA_CR_COALESCE_SHIFT;
> +               dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
> +       }
> +
> +       if (chan->has_sg)
> +               dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
> +                              head_desc->async_tx.phys);
> +
> +       xilinx_dma_start(chan);
> +
> +       if (chan->err)
> +               return;
> +
> +       /* Start the transfer */
> +       if (chan->has_sg) {
> +               dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
> +                              tail_segment->phys);
> +       } else {
> +               struct xilinx_axidma_tx_segment *segment;
> +               struct xilinx_axidma_desc_hw *hw;
> +
> +               segment = list_first_entry(&head_desc->segments,
> +                                          struct xilinx_axidma_tx_segment,
> +                                          node);
> +               hw = &segment->hw;
> +
> +               dma_ctrl_write(chan, XILINX_DMA_REG_SRCDSTADDR, hw->buf_addr);
> +
> +               /* Start the transfer */
> +               dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
> +                              hw->control & XILINX_DMA_MAX_TRANS_LEN);
> +       }
> +
> +       list_splice_tail_init(&chan->pending_list, &chan->active_list);
> +       chan->desc_pendingcount = 0;
> +}
> +
> +/**
>   * xilinx_dma_issue_pending - Issue pending transactions
>   * @dchan: DMA channel
>   */
> @@ -764,7 +1015,7 @@ static void xilinx_dma_issue_pending(struct dma_chan *dchan)
>         unsigned long flags;
>
>         spin_lock_irqsave(&chan->lock, flags);
> -       xilinx_vdma_start_transfer(chan);
> +       chan->start_transfer(chan);
>         spin_unlock_irqrestore(&chan->lock, flags);
>  }
>
> @@ -896,7 +1147,7 @@ static irqreturn_t xilinx_dma_irq_handler(int irq, void *data)
>         if (status & XILINX_DMA_DMASR_FRM_CNT_IRQ) {
>                 spin_lock(&chan->lock);
>                 xilinx_dma_complete_descriptor(chan);
> -               xilinx_vdma_start_transfer(chan);
> +               chan->start_transfer(chan);
>                 spin_unlock(&chan->lock);
>         }
>
> @@ -914,6 +1165,7 @@ static void append_desc_queue(struct xilinx_dma_chan *chan,
>  {
>         struct xilinx_vdma_tx_segment *tail_segment;
>         struct xilinx_dma_tx_descriptor *tail_desc;
> +       struct xilinx_axidma_tx_segment *axidma_tail_segment;
>
>         if (list_empty(&chan->pending_list))
>                 goto append;
> @@ -924,9 +1176,17 @@ static void append_desc_queue(struct xilinx_dma_chan *chan,
>          */
>         tail_desc = list_last_entry(&chan->pending_list,
>                                     struct xilinx_dma_tx_descriptor, node);
> -       tail_segment = list_last_entry(&tail_desc->segments,
> -                                      struct xilinx_vdma_tx_segment, node);
> -       tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
> +       if (chan->xdev->dmatype == XDMA_TYPE_VDMA) {
> +               tail_segment = list_last_entry(&tail_desc->segments,
> +                                              struct xilinx_vdma_tx_segment,
> +                                              node);
> +               tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
> +       } else {
> +               axidma_tail_segment = list_last_entry(&tail_desc->segments,
> +                                              struct xilinx_axidma_tx_segment,
> +                                              node);
> +               axidma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
> +       }
>
>         /*
>          * Add the software descriptor and all children to the list
> @@ -936,7 +1196,7 @@ append:
>         list_add_tail(&desc->node, &chan->pending_list);
>         chan->desc_pendingcount++;
>
> -       if (chan->has_sg &&
> +       if (chan->has_sg && (chan->xdev->dmatype == XDMA_TYPE_VDMA) &&
>             unlikely(chan->desc_pendingcount > chan->num_frms)) {
>                 dev_dbg(chan->dev, "desc pendingcount is too high\n");
>                 chan->desc_pendingcount = chan->num_frms;
> @@ -1064,6 +1324,109 @@ error:
>  }
>
>  /**
> + * xilinx_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction
> + * @dchan: DMA channel
> + * @sgl: scatterlist to transfer to/from
> + * @sg_len: number of entries in @scatterlist
> + * @direction: DMA direction
> + * @flags: transfer ack flags
> + * @context: APP words of the descriptor
> + *
> + * Return: Async transaction descriptor on success and NULL on failure
> + */
> +static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg(
> +       struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len,
> +       enum dma_transfer_direction direction, unsigned long flags,
> +       void *context)
> +{
> +       struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
> +       struct xilinx_dma_tx_descriptor *desc;
> +       struct xilinx_axidma_tx_segment *segment = NULL, *prev = NULL;
> +       u32 *app_w = (u32 *)context;
> +       struct scatterlist *sg;
> +       size_t copy;
> +       size_t sg_used;
> +       unsigned int i;
> +
> +       if (!is_slave_direction(direction))
> +               return NULL;
> +
> +       /* Allocate a transaction descriptor. */
> +       desc = xilinx_dma_alloc_tx_descriptor(chan);
> +       if (!desc)
> +               return NULL;
> +
> +       dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
> +       desc->async_tx.tx_submit = xilinx_dma_tx_submit;
> +
> +       /* Build transactions using information in the scatter gather list */
> +       for_each_sg(sgl, sg, sg_len, i) {
> +               sg_used = 0;
> +
> +               /* Loop until the entire scatterlist entry is used */
> +               while (sg_used < sg_dma_len(sg)) {
> +                       struct xilinx_axidma_desc_hw *hw;
> +
> +                       /* Get a free segment */
> +                       segment = xilinx_axidma_alloc_tx_segment(chan);
> +                       if (!segment)
> +                               goto error;
> +
> +                       /*
> +                        * Calculate the maximum number of bytes to transfer,
> +                        * making sure it is less than the hw limit
> +                        */
> +                       copy = min_t(size_t, sg_dma_len(sg) - sg_used,
> +                                    XILINX_DMA_MAX_TRANS_LEN);
> +                       hw = &segment->hw;
> +
> +                       /* Fill in the descriptor */
> +                       hw->buf_addr = sg_dma_address(sg) + sg_used;
> +
> +                       hw->control = copy;
> +
> +                       if (chan->direction == DMA_MEM_TO_DEV) {
> +                               if (app_w)
> +                                       memcpy(hw->app, app_w, sizeof(u32) *
> +                                              XILINX_DMA_NUM_APP_WORDS);
> +                       }
> +
> +                       if (prev)
> +                               prev->hw.next_desc = segment->phys;
> +
> +                       prev = segment;
> +                       sg_used += copy;
> +
> +                       /*
> +                        * Insert the segment into the descriptor segments
> +                        * list.
> +                        */
> +                       list_add_tail(&segment->node, &desc->segments);
> +               }
> +       }
> +
> +       segment = list_first_entry(&desc->segments,
> +                                  struct xilinx_axidma_tx_segment, node);
> +       desc->async_tx.phys = segment->phys;
> +       prev->hw.next_desc = segment->phys;
> +
> +       /* For the last DMA_MEM_TO_DEV transfer, set EOP */
> +       if (chan->direction == DMA_MEM_TO_DEV) {
> +               segment->hw.control |= XILINX_DMA_BD_SOP;
> +               segment = list_last_entry(&desc->segments,
> +                                         struct xilinx_axidma_tx_segment,
> +                                         node);
> +               segment->hw.control |= XILINX_DMA_BD_EOP;
> +       }
> +
> +       return &desc->async_tx;
> +
> +error:
> +       xilinx_dma_free_tx_descriptor(chan, desc);
> +       return NULL;
> +}
> +
> +/**
>   * xilinx_dma_terminate_all - Halt the channel and free descriptors
>   * @chan: Driver specific DMA Channel pointer
>   */
> @@ -1225,22 +1588,26 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
>                 chan->id = 0;
>
>                 chan->ctrl_offset = XILINX_DMA_MM2S_CTRL_OFFSET;
> -               chan->desc_offset = XILINX_VDMA_MM2S_DESC_OFFSET;
> +               if (xdev->dmatype == XDMA_TYPE_VDMA) {
> +                       chan->desc_offset = XILINX_VDMA_MM2S_DESC_OFFSET;
>
> -               if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
> -                   xdev->flush_on_fsync == XILINX_DMA_FLUSH_MM2S)
> -                       chan->flush_on_fsync = true;
> +                       if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
> +                           xdev->flush_on_fsync == XILINX_DMA_FLUSH_MM2S)
> +                               chan->flush_on_fsync = true;
> +               }
>         } else if (of_device_is_compatible(node,
>                                             "xlnx,axi-vdma-s2mm-channel")) {
>                 chan->direction = DMA_DEV_TO_MEM;
>                 chan->id = 1;
>
>                 chan->ctrl_offset = XILINX_DMA_S2MM_CTRL_OFFSET;
> -               chan->desc_offset = XILINX_VDMA_S2MM_DESC_OFFSET;
> +               if (xdev->dmatype == XDMA_TYPE_VDMA) {
> +                       chan->desc_offset = XILINX_VDMA_S2MM_DESC_OFFSET;
>
> -               if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
> -                   xdev->flush_on_fsync == XILINX_DMA_FLUSH_S2MM)
> -                       chan->flush_on_fsync = true;
> +                       if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
> +                           xdev->flush_on_fsync == XILINX_DMA_FLUSH_S2MM)
> +                               chan->flush_on_fsync = true;
> +               }
>         } else {
>                 dev_err(xdev->dev, "Invalid channel compatible node\n");
>                 return -EINVAL;
> @@ -1255,6 +1622,11 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
>                 return err;
>         }
>
> +       if (xdev->dmatype == XDMA_TYPE_AXIDMA)
> +               chan->start_transfer = xilinx_dma_start_transfer;
> +       else
> +               chan->start_transfer = xilinx_vdma_start_transfer;
> +
>         /* Initialize the tasklet */
>         tasklet_init(&chan->tasklet, xilinx_dma_do_tasklet,
>                         (unsigned long)chan);
> @@ -1297,6 +1669,15 @@ static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec,
>         return dma_get_slave_channel(&xdev->chan[chan_id]->common);
>  }
>
> +static const struct of_device_id xilinx_dma_of_ids[] = {
> +       { .compatible = "xlnx,axi-dma-1.00.a",
> +         .data = (void *)XDMA_TYPE_AXIDMA },
> +       { .compatible = "xlnx,axi-vdma-1.00.a",
> +         .data = (void *)XDMA_TYPE_VDMA },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(of, xilinx_dma_of_ids);
> +
>  /**
>   * xilinx_dma_probe - Driver probe function
>   * @pdev: Pointer to the platform_device structure
> @@ -1318,6 +1699,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
>                 return -ENOMEM;
>
>         xdev->dev = &pdev->dev;
> +       xdev->dmatype = (enum xdma_ip_type)of_device_get_match_data(&pdev->dev);
>
>         /* Request and map I/O memory */
>         io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> @@ -1328,16 +1710,21 @@ static int xilinx_dma_probe(struct platform_device *pdev)
>         /* Retrieve the DMA engine properties from the device tree */
>         xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg");
>
> -       err = of_property_read_u32(node, "xlnx,num-fstores", &num_frames);
> -       if (err < 0) {
> -               dev_err(xdev->dev, "missing xlnx,num-fstores property\n");
> -               return err;
> -       }
> +       if (xdev->dmatype == XDMA_TYPE_VDMA) {
> +               err = of_property_read_u32(node, "xlnx,num-fstores",
> +                                          &num_frames);
> +               if (err < 0) {
> +                       dev_err(xdev->dev,
> +                               "missing xlnx,num-fstores property\n");
> +                       return err;
> +               }
>
> -       err = of_property_read_u32(node, "xlnx,flush-fsync",
> -                                       &xdev->flush_on_fsync);
> -       if (err < 0)
> -               dev_warn(xdev->dev, "missing xlnx,flush-fsync property\n");
> +               err = of_property_read_u32(node, "xlnx,flush-fsync",
> +                                          &xdev->flush_on_fsync);
> +               if (err < 0)
> +                       dev_warn(xdev->dev,
> +                                "missing xlnx,flush-fsync property\n");
> +       }
>
>         err = of_property_read_u32(node, "xlnx,addrwidth", &addr_width);
>         if (err < 0)
> @@ -1362,11 +1749,18 @@ static int xilinx_dma_probe(struct platform_device *pdev)
>                                 xilinx_dma_alloc_chan_resources;
>         xdev->common.device_free_chan_resources =
>                                 xilinx_dma_free_chan_resources;
> -       xdev->common.device_prep_interleaved_dma =
> -                               xilinx_vdma_dma_prep_interleaved;
>         xdev->common.device_terminate_all = xilinx_dma_terminate_all;
>         xdev->common.device_tx_status = xilinx_dma_tx_status;
>         xdev->common.device_issue_pending = xilinx_dma_issue_pending;
> +       if (xdev->dmatype == XDMA_TYPE_AXIDMA) {
> +               xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg;
> +               /* Residue calculation is supported by only AXI DMA */
> +               xdev->common.residue_granularity =
> +                                         DMA_RESIDUE_GRANULARITY_SEGMENT;
> +       } else {
> +               xdev->common.device_prep_interleaved_dma =
> +                               xilinx_vdma_dma_prep_interleaved;
> +       }
>
>         platform_set_drvdata(pdev, xdev);
>
> @@ -1377,9 +1771,11 @@ static int xilinx_dma_probe(struct platform_device *pdev)
>                         goto error;
>         }
>
> -       for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
> -               if (xdev->chan[i])
> -                       xdev->chan[i]->num_frms = num_frames;
> +       if (xdev->dmatype == XDMA_TYPE_VDMA) {
> +               for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
> +                       if (xdev->chan[i])
> +                               xdev->chan[i]->num_frms = num_frames;
> +       }
>
>         /* Register the DMA engine with the core */
>         dma_async_device_register(&xdev->common);
> @@ -1426,12 +1822,6 @@ static int xilinx_dma_remove(struct platform_device *pdev)
>         return 0;
>  }
>
> -static const struct of_device_id xilinx_dma_of_ids[] = {
> -       { .compatible = "xlnx,axi-vdma-1.00.a",},
> -       {}
> -};
> -MODULE_DEVICE_TABLE(of, xilinx_dma_of_ids);
> -
>  static struct platform_driver xilinx_vdma_driver = {
>         .driver = {
>                 .name = "xilinx-vdma",
> diff --git a/include/linux/dma/xilinx_dma.h b/include/linux/dma/xilinx_dma.h
> index 34b98f2..5db17ff 100644
> --- a/include/linux/dma/xilinx_dma.h
> +++ b/include/linux/dma/xilinx_dma.h
> @@ -41,6 +41,18 @@ struct xilinx_vdma_config {
>         int ext_fsync;
>  };
>
> +/**
> + * enum xdma_ip_type: DMA IP type.
> + *
> + * XDMA_TYPE_AXIDMA: Axi dma ip.
> + * XDMA_TYPE_VDMA: Axi vdma ip.
> + *
> + */
> +enum xdma_ip_type {
> +       XDMA_TYPE_AXIDMA = 0,
> +       XDMA_TYPE_VDMA,
> +};
> +
>  int xilinx_vdma_channel_set_config(struct dma_chan *dchan,
>                                         struct xilinx_vdma_config *cfg);
>
> --
> 2.1.2
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From eric at anholt.net  Thu May 12 11:15:27 2016
From: eric at anholt.net (Eric Anholt)
Date: Thu, 12 May 2016 11:15:27 -0700
Subject: [PATCH 0/4] add minimal bcm2835-sdram driver
In-Reply-To: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <87twi39m80.fsf@eliezer.anholt.net>

kernel at martin.sperl.org writes:

> From: Martin Sperl <kernel at martin.sperl.org>
>
> As the sdram clock is a critical clock to the system
> the minimal bcm2835-sdram driver claims (and enables)
> this clock and also exposes the corresponding sdram
> registers via debugfs.

I don't think this is a good solution to the problem you are trying to
work around.  You're relying on the fact that this driver gets
successfully probed before a driver that would -EPROBE_DEFER on a
sibling clock, which is not a guarantee.

Let's please continue the debugging of clock management on linux-clk.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160512/1f9f9b34/attachment.sig>

From dianders at chromium.org  Thu May 12 11:15:52 2016
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 12 May 2016 11:15:52 -0700
Subject: [PATCH v2] mmc: dw_mmc: rockchip: Set the drive phase properly
In-Reply-To: <1463002848-580-1-git-send-email-dianders@chromium.org>
References: <1463002848-580-1-git-send-email-dianders@chromium.org>
Message-ID: <CAD=FV=UiPo5EnsX+erm5PDsuCHczr1qbhwz8s4FcLeNGPdVuGQ@mail.gmail.com>

Hi,

On Wed, May 11, 2016 at 2:40 PM, Douglas Anderson <dianders at chromium.org> wrote:
> Historically for Rockchip devices we've relied on the power-on
> default (or perhaps the firmware setting) to get the correct drive
> phase for dw_mmc devices.  This worked OK for the most part, but:
>
> * Relying on the setting just "being right" is a bit fragile.
>
> * As soon as there is an instance where the power on default is wrong or
>   where the firmware didn't configure this properly then we'll get a
>   mysterious failure.
>
> Let's explicitly set this phase in the kernel.
>
> The comments inside this patch try to explain the situation quite
> throughly, but the high level overview of this is:
>
> Before this patch on rk3288 devices tested:
> * eMMC: 180 degrees
> * SDMMC/SDIO0/SDIO1: 90 degrees
>
> After this patch:
> * Use 90 degree phase offset usually.
> * Use 180 degree phase offset for MMC_DDR52, SDR104, HS200.
>
> That means we are _changing_ behavior for those devices in this way:
>
> * If we have HS200 eMMC or DDR52 eMMC, we'll run ID mode at 90
>   degrees (vs 180) but otherwise have no change.
>
> * For any non-HS200 / non-DDR52 eMMC devices we'll now _always_ run at
>   90 degrees (vs 180).  It seems fairly unlikely that building modern
>   hardware is using an eMMC that isn't using DDR52 or HS200, of course.
>
> * For SDR104 cards we'll now run with 180 degree phase offset (vs 90).
>   It's expected that 90 degree phase offset would have worked OK, but
>   this gives us extra margin.
>
> I have tested this by inserting my collection of uSD cards (mostly UHS,
> though a few not) into a veyron_minnie and confirmed that they still
> seem to enumerate properly.  For a subset of them I tried putting a
> filesystem on them and also tried running mmc_test.
>
> Signed-off-by: Douglas Anderson <dianders at chromium.org>
> ---
> Changes in v2:
> - Now use 90 degrees for some modes; updated comments to say why.
>
>  drivers/mmc/host/dw_mmc-rockchip.c | 64 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 64 insertions(+)

Just a note that I have since found out that recent patches in the
kernel in fact _do_ init the drive phase and apparently do it
improperly.  That means that $SUBJECT patch actually is expected to
fix real problems on real devices.

See <https://patchwork.kernel.org/patch/9085311/> for some details.

-Doug


From d-gerlach at ti.com  Thu May 12 11:20:52 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Thu, 12 May 2016 13:20:52 -0500
Subject: [PATCH] ARM: OMAP2+: AM43XX: Enable fixes for Cortex-A9 errata
Message-ID: <1463077252-13078-1-git-send-email-d-gerlach@ti.com>

This patch explicitly enables the fixes for the below errata applicable
for AM43x Socs as was done for OMAP4.

754322: Faulty MMU translations following ASID switch

775420: A data cache maintenance operation which aborts,
        followed by an ISB, without any DSB in-between,
        might lead to deadlock

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/mach-omap2/Kconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 0517f0c1581a..f9deed2e6ef5 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -67,6 +67,8 @@ config SOC_AM43XX
 	select HAVE_ARM_SCU
 	select GENERIC_CLOCKEVENTS_BROADCAST
 	select HAVE_ARM_TWD
+	select ARM_ERRATA_754322
+	select ARM_ERRATA_775420
 
 config SOC_DRA7XX
 	bool "TI DRA7XX"
-- 
2.7.3



From eric at anholt.net  Thu May 12 11:23:15 2016
From: eric at anholt.net (Eric Anholt)
Date: Thu, 12 May 2016 11:23:15 -0700
Subject: [PATCH 0/3] clk: bcm2835: critical clocks and parent selection
In-Reply-To: <FD44F435-512C-49A5-B1F5-3C62AAF805AC@martin.sperl.org>
References: <1462842090-2017-1-git-send-email-eric@anholt.net>
 <5731B8BA.30402@martin.sperl.org> <87a8jxyfua.fsf@eliezer.anholt.net>
 <FD44F435-512C-49A5-B1F5-3C62AAF805AC@martin.sperl.org>
Message-ID: <87oa8b9lv0.fsf@eliezer.anholt.net>

Martin Sperl <kernel at martin.sperl.org> writes:

>> On 10.05.2016, at 19:37, Eric Anholt <eric at anholt.net> wrote:
>> 
>> Martin Sperl <kernel at martin.sperl.org> writes:
>>> and also hsm (probably hardware security module):
>>> root at raspcm:~# cat /sys/kernel/debug/clk/hsm/regdump
>>> ctl = 0x000002d6
>>> div = 0x000030e0
>>> root at raspcm:~# cat /sys/kernel/debug/clk/hsm/clk_rate
>>> 163551916
>> 
>> That's the HDMI state machine (there's even a comment saying so),
>> controlled by the vc4 driver.
>> 
>>> So turning plld off stops sdram and hsm - at least that is my
>>> interpretation.
>>> 
>>> This means we need to define a clock property in firmware or
>>> we need a ram node making use of "mmio-sram" maybe?
>>> 
>>> Marking sdram as "critical" or "hand_off" could also solve that
>>> for the moment (but it does not solve all the other hidden
>>> clock dependencies of the firmware)
>> 
>> If there are other hidden dependencies, then we should figure them out.
>
> But strangely the sdram (plus the below) is the only one with
> plld that is enabled (unless it is one of the clocks we have not
> added to the kernel side yet)
>
> Maybe there is something that derives directly from plld_core
> or any of the other plld-dividers?

Nothing I can find.

> Core would indicate anything central to the videocore...
> Anyway both plld_core as well as plld_per ad well as both
> Pll_dsi that are running by default (but I doubt that the
> Dsi would be relevant)
>
> I guess you are in a better situation to figure out which
> hidden HW blocks uses plld...
>
>> 
>>> --- a/drivers/clk/bcm/clk-bcm2835.c
>>> +++ b/drivers/clk/bcm/clk-bcm2835.c
>>> @@ -1655,7 +1655,8 @@ static const struct bcm2835_clk_desc 
>>> clk_desc_array[] = {
>>>                .ctl_reg = CM_SDCCTL,
>>>                .div_reg = CM_SDCDIV,
>>>                .int_bits = 6,
>>> -               .frac_bits = 0),
>>> +               .frac_bits = 0,
>>> +               .flags = CLK_IS_CRITICAL),
>>>        [BCM2835_CLOCK_V3D]     = REGISTER_VPU_CLK(
>>>                .name = "v3d",
>>>                .ctl_reg = CM_V3DCTL,
>> 
>> The Pi foundation folks believe that the cprman SDRAM clock isn't ever
>> used (there's a separate PLL in the SDRAM controller, and cprman is only
>> intended for unused low-power states), and at least in your sample of
>> the reg, it's not enabled.  Instead of grepping for clk_enable_count, it
> See my comment above - it must be configured for some reason
> during the boot process by the firmware .

You have to write the register to configure the sdram controller's clock
parent.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160512/b537a4e4/attachment.sig>

From julien.grall at arm.com  Thu May 12 11:24:08 2016
From: julien.grall at arm.com (Julien Grall)
Date: Thu, 12 May 2016 19:24:08 +0100
Subject: [PATCH v16 00/20] arm64 kexec kernel patches v16
In-Reply-To: <cover.1460668521.git.geoff@infradead.org>
References: <cover.1460668521.git.geoff@infradead.org>
Message-ID: <5734CA48.7040706@arm.com>

Hello Geoff,

On 14/04/16 22:21, Geoff Levand wrote:
> This series adds the core support for kexec re-boot and kdump on ARM64.  This
> version of the series combines Takahiro's kdump patches with my kexec patches.
> Please consider all patches for inclusion.
>
> To load a second stage kernel and execute a kexec re-boot or to work with kdump
> on ARM64 systems a series of patches to kexec-tools [2], which have not yet been
> merged upstream, are needed.  Please update to the latest if you have been using
> an older version.
>
> To examine vmcore (/proc/vmcore), you should use
>    - gdb v7.7 or later
>    - crash v7.1.1 or later

I have been trying to use crash dump with your branch without much 
success on juno-r2:

WARNING: could not find MAGIC_START!
crash: cannot determine base kernel version
crash: /root/vmlinux and /root/coredump.kernel do not match!

Looking at the debug log (-p 5), the translation va -> pa computed by 
crash is wrong.

The physical address expected is 0x80a76b28, but crash return 0x88a76b28.

I am using crash built from [1] and the panic has been created using 
/proc/sysrq-trigger.

Also, crash dump seems to always report that Xen is running even when 
KVM was in used (see logs [2]) below.

Lastly, crash fails with an error after a couple of minutes (see logs [2]).

How you seen such errors during your testing?

Regards,

[1] https://github.com/crash-utility/crash
[2] http://pastebin.com/wC8w44SN

-- 
Julien Grall


From eric at anholt.net  Thu May 12 11:24:46 2016
From: eric at anholt.net (Eric Anholt)
Date: Thu, 12 May 2016 11:24:46 -0700
Subject: [PATCH 0/3] clk: bcm2835: critical clocks and parent selection
In-Reply-To: <5E7C0C2A-8FA0-4EFF-9627-DFC34662590B@martin.sperl.org>
References: <1462842090-2017-1-git-send-email-eric@anholt.net>
 <5731B8BA.30402@martin.sperl.org> <87a8jxyfua.fsf@eliezer.anholt.net>
 <FD44F435-512C-49A5-B1F5-3C62AAF805AC@martin.sperl.org>
 <5E7C0C2A-8FA0-4EFF-9627-DFC34662590B@martin.sperl.org>
Message-ID: <87lh3f9lsh.fsf@eliezer.anholt.net>

Martin Sperl <kernel at martin.sperl.org> writes:

> On 10.05.2016, at 21:58, Martin Sperl <kernel at martin.sperl.org> wrote:
>> 
>> 
>> 
>>> On 10.05.2016, at 19:37, Eric Anholt <eric at anholt.net> wrote:
>>> 
>>> Martin Sperl <kernel at martin.sperl.org> writes:
>>> 
>>>>> On 10.05.2016 03:01, Eric Anholt wrote:
>>>>> With the new patch 2 inserted between my previous pair, I think this
>>>>> should cover Martin's bugs with clock disabling.
>>>>> 
>>>>> I tested patch 2 to be important on the downstream kernel: with the
>>>>> DPI panel support added there, I was losing ethernet (my only I/O)
>>>>> when the HDMI HSM hanging off of PLLD_PER got disabled due to
>>>>> EPROBE_DEFER.
>>>>> 
>>>>> Eric Anholt (3):
>>>>> clk: bcm2835: Mark the VPU clock as critical
>>>>> clk: bcm2835: Mark GPIO clocks enabled at boot as critical.
>>>>> clk: bcm2835: Skip PLLC clocks when deciding on a new clock parent
>>>>> 
>>>>> drivers/clk/bcm/clk-bcm2835.c | 32 ++++++++++++++++++++++++++++++--
>>>>> 1 file changed, 30 insertions(+), 2 deletions(-)
>>>> I gave it a try - with all 3 patches applied I get the following enabled 
>>>> clocks:
>>>> root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
>>>> /sys/kernel/debug/clk/aux_uart/clk_enable_count:1
>>>> /sys/kernel/debug/clk/emmc/clk_enable_count:1
>>>> /sys/kernel/debug/clk/gp1/clk_enable_count:1
>>>> /sys/kernel/debug/clk/gp2/clk_enable_count:1
>>>> /sys/kernel/debug/clk/osc/clk_enable_count:1
>>>> /sys/kernel/debug/clk/pllc/clk_enable_count:2
>>>> /sys/kernel/debug/clk/pllc_core0/clk_enable_count:1
>>>> /sys/kernel/debug/clk/pllc_per/clk_enable_count:1
>>>> /sys/kernel/debug/clk/vpu/clk_enable_count:2
>>>> 
>>>> At least on my compute module gp1/gp2 is enabled, but there is no rate
>>>> set - so why is it marked as critical for all devices?
>>>> So why apply patch2 for all possible devices?
>>> 
>>> According to the CLK_IS_CRITICAL patches, the author intended critical
>>> clocks not to use the included function for marking clocks as critical
>>> From the DT.  I'm not sure why, but writing patches using that when they
>>> say not to seemed like a waste.
>>> 
>>> We could check if gp1/gp2 are already on before marking them critical.
>> That may seem reasonable.
>>> 
>>>> Loading/unloading the amba_pl011 module does not crash the system,
>>>> but a simple stty -F /dev/ttyAMA0 does crash the system!
>>>> 
>>>> Here the sequence:
>>>> root at raspcm:~# dmesg -C
>>>> root at raspcm:~# modprobe amba_pl011
>>>> root at raspcm:~# dmesg -c
>>>> [  141.708453] Serial: AMBA PL011 UART driver
>>>> [  141.709158] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, 
>>>> base_baud = 0) is a PL011 rev2
>>>> root at raspcm:~# rmmod  amba_pl011
>>>> root at raspcm:~# dmesg -c
>>>> [  150.511248] Trying to free nonexistent resource 
>>>> <0000000020201000-0000000020201fff>
>>>> root at raspcm:~# modprobe amba_pl011
>>>> root at raspcm:~# dmesg -c
>>>> [  159.385002] Serial: AMBA PL011 UART driver
>>>> [  159.385714] 20201000.uart: ttyAMA0 at MMIO 0x20201000 (irq = 81, 
>>>> base_baud = 0) is a PL011 rev2
>>>> root at raspcm:~# stty -F /dev/ttyAMA0
>>>> speed 9600 baud; line = 0;
>>>> -brkint -imaxbel
>>>> root at raspcm:~# Timeout, server raspcm not responding.
>>>> 
>>>> The reason behind this is that the firmware pre-configured uart clock
>>>> looks like this:
>>>> root at raspcm:~# cat /sys/kernel/debug/clk/uart/regdump
>>>> ctl = 0x00000296
>>>> div = 0x000a6aab
>>>> so it is configured to use plld_per (which itself is running, even if 
>>>> not enabled
>>>> in the kernel)
>>>> 
>>>> But as plld_per is not among the enabled clocks then plld_per
>>>> gets disabled as soon as the tty device is closed (by stty) and
>>>> this also disables plld...
>>>> 
>>>> Similar effect when using PCM/i2s and use speaker-test:
>>>> root at raspcm:~# dmesg -C
>>>> root at raspcm:~# modprobe snd-soc-bcm2835-i2s; modprobe snd-soc-pcm5102a; 
>>>> modprobe snd-soc-hifiberry-dac
>>>> root at raspcm:~# dmesg
>>>> [   81.968591] snd-hifiberry-dac sound: pcm5102a-hifi <-> 20203000.i2s 
>>>> mapping ok
>>>> root at raspcm:~# speaker-test -c 2 -r 44100 -F S16_LE -f 440 -t sine&
>>>> [1] 579
>>>> root at raspcm:~#
>>>> speaker-test 1.0.28
>>>> 
>>>> Playback device is default
>>>> Stream parameters are 44100Hz, S16_LE, 2 channels
>>>> Sine wave rate is 440.0000Hz
>>>> Rate set to 44100Hz (requested 44100Hz)
>>>> Buffer size range from 128 to 131072
>>>> Period size range from 64 to 65536
>>>> Using max buffer size 131072
>>>> Periods = 4
>>>> was set period_size = 32768
>>>> was set buffer_size = 131072
>>>> 0 - Front Left
>>>> 1 - Front Right
>>>> 
>>>> root at raspcm:~#
>>>> root at raspcm:~# grep -vE ^0 /sys/kernel/debug/clk/*/clk_enable_count
>>>> /sys/kernel/debug/clk/aux_uart/clk_enable_count:1
>>>> /sys/kernel/debug/clk/emmc/clk_enable_count:1
>>>> /sys/kernel/debug/clk/gp1/clk_enable_count:1
>>>> /sys/kernel/debug/clk/gp2/clk_enable_count:1
>>>> /sys/kernel/debug/clk/osc/clk_enable_count:2
>>>> /sys/kernel/debug/clk/pcm/clk_enable_count:1
>>>> /sys/kernel/debug/clk/pllc/clk_enable_count:2
>>>> /sys/kernel/debug/clk/pllc_core0/clk_enable_count:1
>>>> /sys/kernel/debug/clk/pllc_per/clk_enable_count:1
>>>> /sys/kernel/debug/clk/plld/clk_enable_count:1
>>>> /sys/kernel/debug/clk/plld_per/clk_enable_count:1
>>>> /sys/kernel/debug/clk/vpu/clk_enable_count:2
>>>> root at raspcm:~# kill %1
>>>> root at raspcm:~# Time per period = 106.889502
>>>> Timeout, server raspcm not responding.
>>>> 
>>>> You see that plld gets now used and when I kill speaker-test
>>>> the machine crashes again.
>>> 
>>> Just so I can be clear here: What are you using to talk to the Pi?
>>> Builtin USB ethernet?
>> Compute module with USB  Ethernet adapter, but I also got an 
>> enc28j60 connected via spi, but that is not enabled by default
>> 
>>> 
>>>> So this patchset does not really solve any of the problems that
>>>> I have reported either.
>>>> 
>>>> That is why my patchset has taken the "HAND_OFF" approach
>>>> instead (which still just hides some of the issues), but at least
>>>> it does not crash the system on the use of plld and it allows
>>>> for custom parent and mash selection.
>>> 
>>> HAND_OFF sure doesn't look like it's landing in the next kernel, so
>>> writing patches using it doesn't make much sense to me.
>> 
>> If it is critical or hands-off does not really make a difference...
>> 
>>>> In reality it would require consumers of the corresponding
>>>> parent clocks in the kernel (arm, ...) and the knowledge which
>>>> clocks are really needed by the firmware - i.e plld.
>>>> 
>>>> Note that the sdram clock is using plld_core parent!
>>>> root at raspcm:~#  cat /sys/kernel/debug/clk/sdram/regdump
>>>> ctl = 0x00004006
>>>> div = 0x00003000
>>>> root at raspcm:~# cat /sys/kernel/debug/clk/sdram/clk_rate
>>>> 166533331
>>> 
>>> However, it's not enabled, right?  Bit 4 isn't set in the CTL reg.
>> You are probably right there, but still there must be something
>> hidden that requires plld or plld_per or plld_core, that requires critical.
>> 
>> There must be some reason why it gets set up during the
>> boot process by the firmware.
>> 
>
> Correction:
>
> Actually the SDC control register contains some more bits compared
> to most other clock control registers:
> CM_SDCCTL_CTRL (12-15), CM_SDCCTL_ACCPT(16) and CM_SDCCTL_UPDATE(17)
>
> See also:
> https://github.com/msperl/rpi-registers/blob/master/md/Region_CM.md#cm_sdcctl
>
> If I poke that register (0x201011a8) from userspace with 0x5a000000
> then the machine crashes as well - so I assume these bits control
> the custom SD-Ram PLL - unfortunately it still does not say which
> PLL is used.

You must not change the CTRL bits while ACCEPT is unset.

> Note that I also tried disabling PLLD_CORE and the system crashed as well
> (root at raspcm:~#  peekpoke $[0x20101000 + 0x10c] w
> /dev/mem opened.
> Memory mapped at address 0xb6fdd000.
> Value at address 0x2010110C (0xb6fdd10c): 0x20A
> root at raspcm:~# peekpoke $[0x20101000 + 0x10c] w $[0x5a000000 + 0x20a + 32]
> /dev/mem opened.
> Memory mapped at address 0xb6fe7000.
> Value at address 0x2010110C (0xb6fe710c): 0x20A
> Written 0x5A00022A; readback 0x22A
> root at raspcm:~# Write failed: Broken pipe

I don't have an answer for this one, and spent a while digging.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160512/7be444d5/attachment-0001.sig>

From christoffer.dall at linaro.org  Thu May 12 11:30:16 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 20:30:16 +0200
Subject: [PATCH v3 43/55] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 access to VGIC registers
In-Reply-To: <1462531568-9799-44-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-44-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512183016.GJ27623@cbox>

On Fri, May 06, 2016 at 11:45:56AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
> and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
> access VGIC registers.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 34 ++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h            |  1 +
>  3 files changed, 86 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index 0189c13..c952f6f 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -252,6 +252,21 @@ void kvm_register_vgic_device(unsigned long type)
>  	}
>  }
>  
> +/** vgic_attr_regs_access: allows user space to read/write VGIC registers
> + *
> + * @dev: kvm device handle
> + * @attr: kvm device attribute
> + * @reg: address the value is read or written
> + * @is_write: write flag
> + *
> + */
> +static int vgic_attr_regs_access(struct kvm_device *dev,
> +				 struct kvm_device_attr *attr,
> +				 u32 *reg, bool is_write)
> +{
> +	return -ENXIO;
> +}
> +
>  /* V2 ops */
>  
>  static int vgic_v2_set_attr(struct kvm_device *dev,
> @@ -260,8 +275,23 @@ static int vgic_v2_set_attr(struct kvm_device *dev,
>  	int ret;
>  
>  	ret = vgic_set_common_attr(dev, attr);
> -	return ret;
> +	if (ret != -ENXIO)
> +		return ret;
> +
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
> +		u32 reg;
> +
> +		if (get_user(reg, uaddr))
> +			return -EFAULT;
>  
> +		return vgic_attr_regs_access(dev, attr, &reg, true);
> +	}
> +	}
> +
> +	return -ENXIO;
>  }
>  
>  static int vgic_v2_get_attr(struct kvm_device *dev,
> @@ -270,7 +300,23 @@ static int vgic_v2_get_attr(struct kvm_device *dev,
>  	int ret;
>  
>  	ret = vgic_get_common_attr(dev, attr);
> -	return ret;
> +	if (ret != -ENXIO)
> +		return ret;
> +
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
> +		u32 reg = 0;
> +
> +		ret = vgic_attr_regs_access(dev, attr, &reg, false);
> +		if (ret)
> +			return ret;
> +		return put_user(reg, uaddr);
> +	}
> +	}
> +
> +	return -ENXIO;
>  }
>  
>  static int vgic_v2_has_attr(struct kvm_device *dev,
> @@ -284,6 +330,9 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
>  			return 0;
>  		}
>  		break;
> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> +		return vgic_v2_has_attr_regs(dev, attr);
>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
>  		return 0;
>  	case KVM_DEV_ARM_VGIC_GRP_CTRL:
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 8006ac0..cf8fee9 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -246,3 +246,37 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
>  
>  	return SZ_4K;
>  }
> +
> +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
> +{
> +	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
> +	const struct vgic_register_region *regions;
> +	gpa_t addr;
> +	int nr_regions, i, len;
> +
> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
> +
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> +		regions = vgic_v2_dist_registers;
> +		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
> +		break;
> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> +		return -ENXIO;		/* TODO: describe CPU i/f regs also */
> +	default:
> +		return -ENXIO;
> +	}
> +
> +	for (i = 0; i < nr_regions; i++) {
> +		if (regions[i].bits_per_irq)
> +			len = (regions[i].bits_per_irq * nr_irqs) / 8;
> +		else
> +			len = regions[i].len;
> +
> +		if (regions[i].reg_offset <= addr &&
> +		    regions[i].reg_offset + len > addr)
> +			return 0;

should we check if addr is word-aligned ?

> +	}
> +
> +	return -ENXIO;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index c44ee01..a4397f9 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -36,6 +36,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
>  void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
>  void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
>  void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
> +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
>  int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>  			     enum vgic_type);
>  
> -- 
> 2.7.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From hdegoede at redhat.com  Thu May 12 11:31:09 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Thu, 12 May 2016 20:31:09 +0200
Subject: [PATCH 2/2] musb: sunxi: Set state to A_WAIT_VRISE when enabling VBus
In-Reply-To: <1463077869-13224-1-git-send-email-hdegoede@redhat.com>
References: <1463077869-13224-1-git-send-email-hdegoede@redhat.com>
Message-ID: <1463077869-13224-2-git-send-email-hdegoede@redhat.com>

When the board is powering attached usb devices via the otg port
sometimes / on some devices it takes slightly too long for the VBus
detection code in phy-sun4i-usb.c to signal that VBus is high after
enabling VBus and the musb hardware signals a MUSB_INTR_VBUSERROR
interrupt.

This commit sets the otg state to A_WAIT_VRISE upon enabling Vbus
making musb_stage0_irq() ignore the first VBUSERR_RETRY_COUNT
VBUSERROR interrupts, fixing connection issues in these cases.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 drivers/usb/musb/sunxi.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index 2c33d9b..2ee48fb 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -112,7 +112,7 @@ static void sunxi_musb_work(struct work_struct *work)
 		if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
 			set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 			musb->xceiv->otg->default_a = 1;
-			musb->xceiv->otg->state = OTG_STATE_A_IDLE;
+			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
 			MUSB_HST_MODE(musb);
 			devctl |= MUSB_DEVCTL_SESSION;
 		} else {
@@ -145,9 +145,10 @@ static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
 {
 	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 
-	if (is_on)
+	if (is_on) {
 		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
-	else
+		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
+	} else
 		clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 
 	schedule_work(&glue->work);
@@ -325,6 +326,7 @@ static int sunxi_set_mode(struct musb *musb, u8 mode)
 		set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
 		/* Stop musb work from turning vbus off again */
 		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
 	}
 
 	return 0;
-- 
2.7.4



From hdegoede at redhat.com  Thu May 12 11:31:08 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Thu, 12 May 2016 20:31:08 +0200
Subject: [PATCH 1/2] musb: sunxi: Add set_mode platform function
Message-ID: <1463077869-13224-1-git-send-email-hdegoede@redhat.com>

Move the mode handling to the platform_set_mode callback.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 drivers/usb/musb/sunxi.c | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index fdab423..2c33d9b 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -264,15 +264,6 @@ static int sunxi_musb_init(struct musb *musb)
 	if (ret)
 		goto error_unregister_notifier;
 
-	if (musb->port_mode == MUSB_PORT_MODE_HOST) {
-		ret = phy_power_on(glue->phy);
-		if (ret)
-			goto error_phy_exit;
-		set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
-		/* Stop musb work from turning vbus off again */
-		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
-	}
-
 	musb->isr = sunxi_musb_interrupt;
 
 	/* Stop the musb-core from doing runtime pm (not supported on sunxi) */
@@ -280,8 +271,6 @@ static int sunxi_musb_init(struct musb *musb)
 
 	return 0;
 
-error_phy_exit:
-	phy_exit(glue->phy);
 error_unregister_notifier:
 	if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
 		extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
@@ -323,6 +312,24 @@ static int sunxi_musb_exit(struct musb *musb)
 	return 0;
 }
 
+static int sunxi_set_mode(struct musb *musb, u8 mode)
+{
+	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+	int ret;
+
+	if (mode == MUSB_HOST) {
+		ret = phy_power_on(glue->phy);
+		if (ret)
+			return ret;
+
+		set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
+		/* Stop musb work from turning vbus off again */
+		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+	}
+
+	return 0;
+}
+
 static void sunxi_musb_enable(struct musb *musb)
 {
 	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
@@ -569,6 +576,7 @@ static const struct musb_platform_ops sunxi_musb_ops = {
 	.exit		= sunxi_musb_exit,
 	.enable		= sunxi_musb_enable,
 	.disable	= sunxi_musb_disable,
+	.set_mode	= sunxi_set_mode,
 	.fifo_offset	= sunxi_musb_fifo_offset,
 	.ep_offset	= sunxi_musb_ep_offset,
 	.busctl_offset	= sunxi_musb_busctl_offset,
-- 
2.7.4



From dianders at chromium.org  Thu May 12 11:31:50 2016
From: dianders at chromium.org (Douglas Anderson)
Date: Thu, 12 May 2016 11:31:50 -0700
Subject: [PATCH v3] mmc: dw_mmc: rockchip: Set the drive phase properly
Message-ID: <1463077910-25914-1-git-send-email-dianders@chromium.org>

Historically for Rockchip devices we've relied on the power-on
default (or perhaps the firmware setting) to get the correct drive
phase for dw_mmc devices.  This worked OK for the most part, but:

* Relying on the setting just "being right" is a bit fragile.

* As soon as there is an instance where the power on default is wrong or
  where the firmware didn't configure this properly then we'll get a
  mysterious failure.

In commit 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card
initialization") we actually started setting this explicitly in the
kernel, but that commit wasn't quite right and also wasn't quite
enough.  See <https://patchwork.kernel.org/patch/9085311/> for some
details.

Let's explicitly set this phase in dw_mmc.

The comments inside this patch try to explain the situation quite
throughly, but the high level overview of this is:

Before this patch on rk3288 devices tested (after revert of the clock
patch described above):
* eMMC: 180 degrees
* SDMMC/SDIO0/SDIO1: 90 degrees

After this patch:
* Use 90 degree phase offset usually.
* Use 180 degree phase offset for MMC_DDR52, SDR104, HS200.

That means we are _changing_ behavior for those devices in this way:

* If we have HS200 eMMC or DDR52 eMMC, we'll run ID mode at 90
  degrees (vs 180) but otherwise have no change.

* For any non-HS200 / non-DDR52 eMMC devices we'll now _always_ run at
  90 degrees (vs 180).  It seems fairly unlikely that building modern
  hardware is using an eMMC that isn't using DDR52 or HS200, of course.

* For SDR104 cards we'll now run with 180 degree phase offset (vs 90).
  It's expected that 90 degree phase offset would have worked OK, but
  this gives us extra margin.

I have tested this by inserting my collection of uSD cards (mostly UHS,
though a few not) into a veyron_minnie and confirmed that they still
seem to enumerate properly.  For a subset of them I tried putting a
filesystem on them and also tried running mmc_test.

Fixes: 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card initialization")
Signed-off-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Shawn Lin <shawn.lin at rock-chips.com>
---
Changes in v3:
- Fixed minor typo; point that this really fixes something in desc.
- Add Shawn's Reviewed-by

Changes in v2:
- Now use 90 degrees for some modes; updated comments to say why.

 drivers/mmc/host/dw_mmc-rockchip.c | 64 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index 8c20b81cafd8..b9e4fe5a2393 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -66,6 +66,70 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
 	/* Make sure we use phases which we can enumerate with */
 	if (!IS_ERR(priv->sample_clk))
 		clk_set_phase(priv->sample_clk, priv->default_sample_phase);
+
+	/*
+	 * Set the drive phase offset based on speed mode to achieve hold times.
+	 *
+	 * NOTE: this is _not_ a value that is dynamically tuned and is also
+	 * _not_ a value that will vary from board to board.  It is a value
+	 * that could vary between different SoC models if they had massively
+	 * different output clock delays inside their dw_mmc IP block (delay_o),
+	 * but since it's OK to overshoot a little we don't need to do complex
+	 * calculations and can pick values that will just work for everyone.
+	 *
+	 * When picking values we'll stick with picking 0/90/180/270 since
+	 * those can be made very accurately on all known Rockchip SoCs.
+	 *
+	 * Note that these values match values from the DesignWare Databook
+	 * tables for the most part except for SDR12 and "ID mode".  For those
+	 * two modes the databook calculations assume a clock in of 50MHz.  As
+	 * seen above, we always use a clock in rate that is exactly the
+	 * card's input clock (times RK3288_CLKGEN_DIV, but that gets divided
+	 * back out before the controller sees it).
+	 *
+	 * From measurement of a single device, it appears that delay_o is
+	 * about .5 ns.  Since we try to leave a bit of margin, it's expected
+	 * that numbers here will be fine even with much larger delay_o
+	 * (the 1.4 ns assumed by the DesignWare Databook would result in the
+	 * same results, for instance).
+	 */
+	if (!IS_ERR(priv->drv_clk)) {
+		int phase;
+
+		/*
+		 * In almost all cases a 90 degree phase offset will provide
+		 * sufficient hold times across all valid input clock rates
+		 * assuming delay_o is not absurd for a given SoC.  We'll use
+		 * that as a default.
+		 */
+		phase = 90;
+
+		switch (ios->timing) {
+		case MMC_TIMING_MMC_DDR52:
+			/*
+			 * Since clock in rate with MMC_DDR52 is doubled when
+			 * bus width is 8 we need to double the phase offset
+			 * to get the same timings.
+			 */
+			if (ios->bus_width == MMC_BUS_WIDTH_8)
+				phase = 180;
+			break;
+		case MMC_TIMING_UHS_SDR104:
+		case MMC_TIMING_MMC_HS200:
+			/*
+			 * In the case of 150 MHz clock (typical max for
+			 * Rockchip SoCs), 90 degree offset will add a delay
+			 * of 1.67 ns.  That will meet min hold time of .8 ns
+			 * as long as clock output delay is < .87 ns.  On
+			 * SoCs measured this seems to be OK, but it doesn't
+			 * hurt to give margin here, so we use 180.
+			 */
+			phase = 180;
+			break;
+		}
+
+		clk_set_phase(priv->drv_clk, phase);
+	}
 }
 
 #define NUM_PHASES			360
-- 
2.8.0.rc3.226.g39d4020



From luke.starrett at broadcom.com  Thu May 12 11:32:25 2016
From: luke.starrett at broadcom.com (Luke Starrett)
Date: Thu, 12 May 2016 14:32:25 -0400
Subject: [PATCH] arm64: Implement optimised IP checksum helpers
In-Reply-To: <5734B899.3040207@arm.com>
References: <6ca77904d1eced60d86145dc5da361f3aefc6fec.1463062758.git.robin.murphy@arm.com>
 <a3d91ddf-565d-5cef-0a56-39154e3a00d2@broadcom.com>
 <5734B899.3040207@arm.com>
Message-ID: <49017ef4-1e96-3684-dec1-5f013724f8f2@broadcom.com>

Hi Robin,

On 5/12/2016 1:08 PM, Robin Murphy wrote:
> Hi Luke,
>
> On 12/05/16 16:34, Luke Starrett wrote:
>> Hi Robin,
>>
>> I pulled this in to a userspace test app expecting that the __uint128_t
>> type might cause GCC to emit 'ldp'.  Seems like that was that your
>> intent based on your commit note.  Instead I see two 64b loads (ldr Xn),
>> and a single 32b load (ldr Wn) for the trailing 4B.  This was with
>> Linaro GCC 4.9-2015.06.
>
> GCC 5 happily emits ldp there, but indeed I couldn't figure out how to 
> convince GCC 4 to do so. From a quick ferret around in the GCC Git, it 
> looks like the relevant optimisations may have only gone in post-4.9.
>
Not a problem.  I was just curious for my own selfish reasons.

>> Otherwise, the C cycle count looks good enough compared to the asm 
>> version.
>
> Yeah, compiling as standalone functions with GCC 5 I get 19 
> instructions vs. 17 for the asm, but the loop logic gets optimised out 
> completely when ihl is a compile-time constant (e.g. inet_gro_receive())
>

I updated to Linaro GCC 5.3-2016.02, and saw what you described.  I ran 
some smoke testing against a random header generator.  LGTM.

Acked-by: Luke Starrett <luke.starrett at broadcom.com>


From christoffer.dall at linaro.org  Thu May 12 11:41:10 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 20:41:10 +0200
Subject: [PATCH v3 45/55] KVM: arm/arm64: vgic-new: Add userland access
 to VGIC dist registers
In-Reply-To: <1462531568-9799-46-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-46-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512184110.GK27623@cbox>

On Fri, May 06, 2016 at 11:45:58AM +0100, Andre Przywara wrote:
> Userland may want to save and restore the state of the in-kernel VGIC,
> so we provide the code which takes a userland request and translate
> that into calls to our MMIO framework.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-kvm-device.c | 50 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 49 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index c952f6f..bb33af8 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -264,7 +264,55 @@ static int vgic_attr_regs_access(struct kvm_device *dev,

come to think of it, this is GICv2 specific right?

why don't we call it vgic_v2_attr_regs_access then?

and should it really live in this file?

>  				 struct kvm_device_attr *attr,
>  				 u32 *reg, bool is_write)
>  {
> -	return -ENXIO;
> +	gpa_t addr;
> +	int cpuid, ret, c;
> +	struct kvm_vcpu *vcpu, *tmp_vcpu;
> +
> +	cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
> +		 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
> +	vcpu = kvm_get_vcpu(dev->kvm, cpuid);
> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
> +
> +	mutex_lock(&dev->kvm->lock);
> +
> +	ret = vgic_init(dev->kvm);
> +	if (ret)
> +		goto out;
> +
> +	if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	/*
> +	 * Ensure that no other VCPU is running by checking the vcpu->cpu
> +	 * field.  If no other VPCUs are running we can safely access the VGIC
> +	 * state, because even if another VPU is run after this point, that
> +	 * VCPU will not touch the vgic state, because it will block on
> +	 * getting the vgic->lock in kvm_vgic_sync_hwstate().
> +	 */

eh, I don't see us grabbing any vgic->lock (does that still exist?)
here?

> +	kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm) {
> +		if (unlikely(tmp_vcpu->cpu != -1)) {
> +			ret = -EBUSY;
> +			goto out;
> +		}
> +	}
> +
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> +		ret = -EINVAL;
> +		break;
> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> +		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +out:
> +	mutex_unlock(&dev->kvm->lock);
> +	return ret;
>  }
>  
>  /* V2 ops */
> -- 
> 2.7.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Thanks,
-Christoffer


From christoffer.dall at linaro.org  Thu May 12 11:43:16 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 20:43:16 +0200
Subject: [PATCH v3 46/55] KVM: arm/arm64: vgic-new: Add GICH_VMCR accessors
In-Reply-To: <1462531568-9799-47-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-47-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512184316.GL27623@cbox>

On Fri, May 06, 2016 at 11:45:59AM +0100, Andre Przywara wrote:
> Since the GIC CPU interface is always virtualized by the hardware,
> we don't have CPU interface state information readily available in our
> emulation if userland wants to save or restore it.
> Fortunately the GIC hypervisor interface provides the VMCR register to
> access the required virtual CPU interface bits.
> Provide wrappers for GICv2 and GICv3 hosts to have access to this
> register.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v2 .. v3:
> - remove exported v2/v3 selector functions (as per Marc's patch)
> 
>  include/kvm/vgic/vgic.h     |  7 +++++++
>  virt/kvm/arm/vgic/vgic-v2.c | 29 +++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c | 22 ++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h    | 14 ++++++++++++++
>  4 files changed, 72 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 73cab36..cfc3640 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -171,6 +171,13 @@ struct vgic_v3_cpu_if {
>  #endif
>  };
>  
> +struct vgic_vmcr {
> +	u32	ctlr;
> +	u32	abpr;
> +	u32	bpr;
> +	u32	pmr;
> +};
> +

is this going to be used outside the vgic code?

otherwise it could go in virt/kvm/arm/vgic/vgic.h instead?

>  struct vgic_cpu {
>  	/* CPU vif control registers for world switch */
>  	union {
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> index 4cee616..70cac63 100644
> --- a/virt/kvm/arm/vgic/vgic-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -176,3 +176,32 @@ void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
>  {
>  	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
>  }
> +
> +void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
> +{
> +	u32 vmcr;
> +
> +	vmcr  = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK;
> +	vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) &
> +		GICH_VMCR_ALIAS_BINPOINT_MASK;
> +	vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) &
> +		GICH_VMCR_BINPOINT_MASK;
> +	vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) &
> +		GICH_VMCR_PRIMASK_MASK;
> +
> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = vmcr;
> +}
> +
> +void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
> +{
> +	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr;
> +
> +	vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >>
> +			GICH_VMCR_CTRL_SHIFT;
> +	vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >>
> +			GICH_VMCR_ALIAS_BINPOINT_SHIFT;
> +	vmcrp->bpr  = (vmcr & GICH_VMCR_BINPOINT_MASK) >>
> +			GICH_VMCR_BINPOINT_SHIFT;
> +	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
> +			GICH_VMCR_PRIMASK_SHIFT;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 43d1dd7..dca52b3 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -166,3 +166,25 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
>  {
>  	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
>  }
> +
> +void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
> +{
> +	u32 vmcr;
> +
> +	vmcr  = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK;
> +	vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
> +	vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
> +	vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
> +
> +	vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
> +}
> +
> +void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
> +{
> +	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
> +
> +	vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT;
> +	vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
> +	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
> +	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index bc5750e..5260d23 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -39,6 +39,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
>  int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
>  int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  			 int offset, u32 *val);
> +void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>  			     enum vgic_type);
>  
> @@ -48,6 +50,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
>  void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
>  void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
> +void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
>  #else
>  static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> @@ -71,6 +75,16 @@ static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>  {
>  }
>  
> +static inline
> +void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> +{
> +}
> +
> +static inline
> +void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> +{
> +}
> +
>  static inline int vgic_register_redist_iodevs(struct kvm *kvm,
>  					      gpa_t dist_base_address)
>  {
> -- 
> 2.7.3
> 


From dalias at libc.org  Thu May 12 11:38:22 2016
From: dalias at libc.org (Rich Felker)
Date: Thu, 12 May 2016 14:38:22 -0400
Subject: [PATCH v4 10/18] sh: Remove unnecessary of_platform_populate
 with default match table
In-Reply-To: <1463054775-18170-11-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463054775-18170-11-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <20160512183822.GL21636@brightrain.aerifal.cx>

On Thu, May 12, 2016 at 08:06:07PM +0800, Kefeng Wang wrote:
> After patch "of/platform: Add common method to populate default bus",
> it is possible for arch code to remove unnecessary callers about the
> of_platform_populate with default match table.

s/about the/of/ ?

> Cc: Yoshinori Sato <ysato at users.sourceforge.jp>
> Cc: Rich Felker <dalias at libc.org>
> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> ---
>  arch/sh/boards/of-generic.c | 14 --------------
>  1 file changed, 14 deletions(-)
> 
> diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c
> index b4d4313..911ffb9 100644
> --- a/arch/sh/boards/of-generic.c
> +++ b/arch/sh/boards/of-generic.c
> @@ -9,7 +9,6 @@
>   */
>  
>  #include <linux/of.h>
> -#include <linux/of_platform.h>
>  #include <linux/of_fdt.h>
>  #include <linux/clocksource.h>
>  #include <linux/irqchip.h>
> @@ -179,16 +178,3 @@ void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
>  void __init plat_irq_setup(void)
>  {
>  }
> -
> -static int __init sh_of_device_init(void)
> -{
> -	pr_info("SH generic board support: populating platform devices\n");
> -	if (of_have_populated_dt()) {
> -		of_platform_populate(NULL, of_default_bus_match_table,
> -				     NULL, NULL);
> -	} else {
> -		pr_crit("Device tree not populated\n");
> -	}
> -	return 0;
> -}
> -arch_initcall_sync(sh_of_device_init);
> -- 
> 1.7.12.4

I have not tested this, but as long as the new arch-generic code takes
place at the same point in the init sequence (arch_initcall_sync), as
it seems to, I don't expect any sh-specific breakage. In general I'm
happy to see this kind of change.

Rich


From christoffer.dall at linaro.org  Thu May 12 11:47:40 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 20:47:40 +0200
Subject: [PATCH v3 47/55] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <1462531568-9799-48-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-48-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512184740.GM27623@cbox>

On Fri, May 06, 2016 at 11:46:00AM +0100, Andre Przywara wrote:
> Using the VMCR accessors we provide access to GIC CPU interface state
> to userland by wiring it up to the existing userland interface.
> [Marc: move and make VMCR accessors static, streamline MMIO handlers]

does this mean Marc did this and serves as credit or is it a lost
reminder?

> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
> Changelog v2 .. v3:
> - total rework, moving into vgic-mmio-v2.c
> - move vmcr accessor wrapper functions into this file
> - use the register description table for CPU i/f registers as well
> - add RAZ/WI handling for the active priority registers
> - streamline MMIO handler functions
> 
>  virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 104 ++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h            |   2 +
>  3 files changed, 107 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index bb33af8..2122ff2 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -300,7 +300,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
>  
>  	switch (attr->group) {
>  	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> -		ret = -EINVAL;
> +		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
>  		break;
>  	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>  		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index c453e6f..0060539 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -206,6 +206,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> +{
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_set_vmcr(vcpu, vmcr);
> +	else
> +		vgic_v3_set_vmcr(vcpu, vmcr);
> +}
> +
> +static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> +{
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_get_vmcr(vcpu, vmcr);
> +	else
> +		vgic_v3_get_vmcr(vcpu, vmcr);
> +}
> +
> +#define GICC_ARCH_VERSION_V2	0x2
> +
> +/* These are for userland accesses only, there is no guest-facing emulation. */
> +static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
> +					   gpa_t addr, unsigned int len)
> +{
> +	struct vgic_vmcr vmcr;
> +	u32 val;
> +
> +	vgic_get_vmcr(vcpu, &vmcr);
> +
> +	switch (addr & 0xff) {
> +	case GIC_CPU_CTRL:
> +		val = vmcr.ctlr;
> +		break;
> +	case GIC_CPU_PRIMASK:
> +		val = vmcr.pmr;
> +		break;
> +	case GIC_CPU_BINPOINT:
> +		val = vmcr.bpr;
> +		break;
> +	case GIC_CPU_ALIAS_BINPOINT:
> +		val = vmcr.abpr;
> +		break;
> +	case GIC_CPU_IDENT:
> +		val = ((PRODUCT_ID_KVM << 20) |
> +		       (GICC_ARCH_VERSION_V2 << 16) |
> +		       IMPLEMENTER_ARM);
> +		break;
> +	default:
> +		return 0;
> +	}
> +
> +	return extract_bytes(val, addr & 3, len);

I don't think we allow anything than a full 32-bit aligned accesses
from userspace - we shouldn't at least.

> +}
> +
> +static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
> +				   gpa_t addr, unsigned int len,
> +				   unsigned long val)
> +{
> +	struct vgic_vmcr vmcr;
> +
> +	vgic_get_vmcr(vcpu, &vmcr);
> +
> +	switch (addr & 0xff) {
> +	case GIC_CPU_CTRL:
> +		vmcr.ctlr = val;
> +		break;
> +	case GIC_CPU_PRIMASK:
> +		vmcr.pmr = val;
> +		break;
> +	case GIC_CPU_BINPOINT:
> +		vmcr.bpr = val;
> +		break;
> +	case GIC_CPU_ALIAS_BINPOINT:
> +		vmcr.abpr = val;
> +		break;
> +	}
> +
> +	vgic_set_vmcr(vcpu, &vmcr);
> +}
> +
>  static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
>  		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12),
> @@ -237,6 +315,21 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16),
>  };
>  
> +static const struct vgic_register_region vgic_v2_cpu_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_CTRL,
> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_PRIMASK,
> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_BINPOINT,
> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ALIAS_BINPOINT,
> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ACTIVEPRIO,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16),
> +	REGISTER_DESC_WITH_LENGTH(GIC_CPU_IDENT,
> +		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4),
> +};
> +
>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
>  {
>  	dev->regions = vgic_v2_dist_registers;
> @@ -306,6 +399,17 @@ static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
>  	return ret;
>  }
>  
> +int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> +			  int offset, u32 *val)
> +{
> +	struct vgic_io_device dev = {
> +		.regions = vgic_v2_cpu_registers,
> +		.nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers),
> +	};
> +
> +	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
> +}
> +
>  int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  			 int offset, u32 *val)
>  {
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 5260d23..7a69955 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -39,6 +39,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
>  int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
>  int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  			 int offset, u32 *val);
> +int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> +			  int offset, u32 *val);
>  void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
> -- 
> 2.7.3
> 

Thanks,
-Christoffer


From andre.przywara at arm.com  Thu May 12 11:52:38 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 12 May 2016 19:52:38 +0100
Subject: [PATCH v3 47/55] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <20160512184740.GM27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-48-git-send-email-andre.przywara@arm.com>
 <20160512184740.GM27623@cbox>
Message-ID: <5734D0F6.9090406@arm.com>

Hi,

On 12/05/16 19:47, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:46:00AM +0100, Andre Przywara wrote:
>> Using the VMCR accessors we provide access to GIC CPU interface state
>> to userland by wiring it up to the existing userland interface.
>> [Marc: move and make VMCR accessors static, streamline MMIO handlers]
> 
> does this mean Marc did this and serves as credit or is it a lost
> reminder?

It was meant as credit. I thought that is the usual annotation for this?

>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> ---
>> Changelog v2 .. v3:
>> - total rework, moving into vgic-mmio-v2.c
>> - move vmcr accessor wrapper functions into this file
>> - use the register description table for CPU i/f registers as well
>> - add RAZ/WI handling for the active priority registers
>> - streamline MMIO handler functions
>>
>>  virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
>>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 104 ++++++++++++++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic.h            |   2 +
>>  3 files changed, 107 insertions(+), 1 deletion(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> index bb33af8..2122ff2 100644
>> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
>> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> @@ -300,7 +300,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
>>  
>>  	switch (attr->group) {
>>  	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>> -		ret = -EINVAL;
>> +		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
>>  		break;
>>  	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>>  		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> index c453e6f..0060539 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> @@ -206,6 +206,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
>>  	}
>>  }
>>  
>> +static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
>> +{
>> +	if (kvm_vgic_global_state.type == VGIC_V2)
>> +		vgic_v2_set_vmcr(vcpu, vmcr);
>> +	else
>> +		vgic_v3_set_vmcr(vcpu, vmcr);
>> +}
>> +
>> +static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
>> +{
>> +	if (kvm_vgic_global_state.type == VGIC_V2)
>> +		vgic_v2_get_vmcr(vcpu, vmcr);
>> +	else
>> +		vgic_v3_get_vmcr(vcpu, vmcr);
>> +}
>> +
>> +#define GICC_ARCH_VERSION_V2	0x2
>> +
>> +/* These are for userland accesses only, there is no guest-facing emulation. */
>> +static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
>> +					   gpa_t addr, unsigned int len)
>> +{
>> +	struct vgic_vmcr vmcr;
>> +	u32 val;
>> +
>> +	vgic_get_vmcr(vcpu, &vmcr);
>> +
>> +	switch (addr & 0xff) {
>> +	case GIC_CPU_CTRL:
>> +		val = vmcr.ctlr;
>> +		break;
>> +	case GIC_CPU_PRIMASK:
>> +		val = vmcr.pmr;
>> +		break;
>> +	case GIC_CPU_BINPOINT:
>> +		val = vmcr.bpr;
>> +		break;
>> +	case GIC_CPU_ALIAS_BINPOINT:
>> +		val = vmcr.abpr;
>> +		break;
>> +	case GIC_CPU_IDENT:
>> +		val = ((PRODUCT_ID_KVM << 20) |
>> +		       (GICC_ARCH_VERSION_V2 << 16) |
>> +		       IMPLEMENTER_ARM);
>> +		break;
>> +	default:
>> +		return 0;
>> +	}
>> +
>> +	return extract_bytes(val, addr & 3, len);
> 
> I don't think we allow anything than a full 32-bit aligned accesses
> from userspace - we shouldn't at least.

Indeed - I think userland was always 32-bit only. And since last night
we even enforce this. So potentially there are more extract_bytes()
calls that can go.

Cheers,
Andre.


From christoffer.dall at linaro.org  Thu May 12 12:00:52 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 21:00:52 +0200
Subject: [PATCH v3 48/55] KVM: arm/arm64: vgic-new: vgic_init: implement
 kvm_vgic_hyp_init
In-Reply-To: <1462531568-9799-49-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-49-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512190052.GN27623@cbox>

On Fri, May 06, 2016 at 11:46:01AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> Implements kvm_vgic_hyp_init and vgic_probe function.
> 
> The vgic_global struct is enriched with new fields populated
> by those functions.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - rename vgic_init.c to vgic-init.c
> 
> Changelog v2 .. v3:
> - include kvm/arm_vgic.h instead of kvm/vgic/vgic.h
> - move ich_vtr_el2 variable into probe function
> 
>  include/kvm/vgic/vgic.h       |   1 +
>  virt/kvm/arm/vgic/vgic-init.c | 122 ++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v2.c   |  90 +++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c   |  73 +++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h      |   7 +++
>  5 files changed, 293 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-init.c
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index cfc3640..d144e3d 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -202,6 +202,7 @@ struct vgic_cpu {
>  };
>  
>  int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
> +int kvm_vgic_hyp_init(void);
>  
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  			bool level);
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> new file mode 100644
> index 0000000..f10997b
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -0,0 +1,122 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * 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/uaccess.h>
> +#include <linux/interrupt.h>
> +#include <linux/cpu.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/arm_vgic.h>
> +#include <asm/kvm_mmu.h>
> +#include "vgic.h"
> +
> +/* GENERIC PROBE */
> +
> +static void vgic_init_maintenance_interrupt(void *info)
> +{
> +	enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0);
> +}
> +
> +static int vgic_cpu_notify(struct notifier_block *self,
> +			   unsigned long action, void *cpu)
> +{
> +	switch (action) {
> +	case CPU_STARTING:
> +	case CPU_STARTING_FROZEN:
> +		vgic_init_maintenance_interrupt(NULL);
> +		break;
> +	case CPU_DYING:
> +	case CPU_DYING_FROZEN:
> +		disable_percpu_irq(kvm_vgic_global_state.maint_irq);
> +		break;
> +	}
> +
> +	return NOTIFY_OK;
> +}
> +
> +static struct notifier_block vgic_cpu_nb = {
> +	.notifier_call = vgic_cpu_notify,
> +};
> +
> +static irqreturn_t vgic_maintenance_handler(int irq, void *data)
> +{
> +	/*
> +	 * We cannot rely on the vgic maintenance interrupt to be
> +	 * delivered synchronously. This means we can only use it to
> +	 * exit the VM, and we perform the handling of EOIed
> +	 * interrupts on the exit path (see vgic_process_maintenance).
> +	 */
> +	return IRQ_HANDLED;
> +}
> +
> +static const struct of_device_id vgic_ids[] = {
> +	{ .compatible = "arm,cortex-a15-gic",	.data = vgic_v2_probe, },
> +	{ .compatible = "arm,cortex-a7-gic",	.data = vgic_v2_probe, },
> +	{ .compatible = "arm,gic-400",		.data = vgic_v2_probe, },
> +	{ .compatible = "arm,gic-v3",		.data = vgic_v3_probe, },
> +	{},
> +};
> +
> +/**
> + * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable
> + * according to the host GIC model. Accordingly calls either
> + * vgic_v2/v3_probe which registers the KVM_DEVICE that can be
> + * instantiated by a guest later on .
> + */
> +int kvm_vgic_hyp_init(void)
> +{
> +	const struct of_device_id *matched_id;
> +	const int (*vgic_probe)(struct device_node *);
> +	struct device_node *vgic_node;
> +	int ret;
> +
> +	vgic_node = of_find_matching_node_and_match(NULL,
> +						    vgic_ids, &matched_id);
> +	if (!vgic_node) {
> +		kvm_err("error: no compatible GIC node found\n");
> +		return -ENODEV;
> +	}
> +
> +	vgic_probe = matched_id->data;
> +	ret = vgic_probe(vgic_node);
> +	if (ret)
> +		return ret;
> +
> +	ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
> +				 vgic_maintenance_handler,
> +				 "vgic", kvm_get_running_vcpus());
> +	if (ret) {
> +		kvm_err("Cannot register interrupt %d\n",
> +			kvm_vgic_global_state.maint_irq);
> +		return ret;
> +	}
> +
> +	ret = __register_cpu_notifier(&vgic_cpu_nb);
> +	if (ret) {
> +		kvm_err("Cannot register vgic CPU notifier\n");
> +		goto out_free_irq;
> +	}
> +
> +	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
> +
> +	return 0;
> +
> +out_free_irq:
> +	free_percpu_irq(kvm_vgic_global_state.maint_irq,
> +			kvm_get_running_vcpus());
> +	return ret;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> index 70cac63..91b69a4 100644
> --- a/virt/kvm/arm/vgic/vgic-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -17,6 +17,11 @@
>  #include <linux/irqchip/arm-gic.h>
>  #include <linux/kvm.h>
>  #include <linux/kvm_host.h>
> +#include <kvm/arm_vgic.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <asm/kvm_mmu.h>
>  
>  #include "vgic.h"
>  
> @@ -205,3 +210,88 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>  	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
>  			GICH_VMCR_PRIMASK_SHIFT;
>  }
> +
> +/**
> + * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
> + * @node:	pointer to the DT node
> + *
> + * Returns 0 if a GICv2 has been found, returns an error code otherwise
> + */
> +int vgic_v2_probe(struct device_node *vgic_node)
> +{
> +	int ret;
> +	struct resource vctrl_res;
> +	struct resource vcpu_res;
> +
> +	kvm_vgic_global_state.maint_irq = irq_of_parse_and_map(vgic_node, 0);
> +	if (!kvm_vgic_global_state.maint_irq) {
> +		kvm_err("error getting vgic maintenance irq from DT\n");
> +		ret = -ENXIO;
> +		goto out;
> +	}
> +
> +	ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
> +	if (ret) {
> +		kvm_err("Cannot obtain GICH resource\n");
> +		goto out;
> +	}
> +
> +	kvm_vgic_global_state.vctrl_base = of_iomap(vgic_node, 2);
> +	if (!kvm_vgic_global_state.vctrl_base) {
> +		kvm_err("Cannot ioremap GICH\n");
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	kvm_vgic_global_state.nr_lr =
> +		readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
> +	kvm_vgic_global_state.nr_lr = (kvm_vgic_global_state.nr_lr & 0x3f) + 1;

could we please do:
	vtr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
	kvm_vgic_global_state.nr_lr = (vtr & 0x3f) + 1;

instead?

> +
> +	ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
> +				     kvm_vgic_global_state.vctrl_base +
> +					 resource_size(&vctrl_res),
> +				     vctrl_res.start);
> +	if (ret) {
> +		kvm_err("Cannot map VCTRL into hyp\n");
> +		goto out_unmap;
> +	}
> +
> +	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
> +		kvm_err("Cannot obtain GICV resource\n");
> +		ret = -ENXIO;
> +		goto out_unmap;
> +	}
> +
> +	if (!PAGE_ALIGNED(vcpu_res.start)) {
> +		kvm_err("GICV physical address 0x%llx not page aligned\n",
> +			(unsigned long long)vcpu_res.start);
> +		ret = -ENXIO;
> +		goto out_unmap;
> +	}
> +
> +	if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
> +		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
> +			(unsigned long long)resource_size(&vcpu_res),
> +			PAGE_SIZE);
> +		ret = -ENXIO;
> +		goto out_unmap;
> +	}
> +
> +	kvm_vgic_global_state.can_emulate_gicv2 = true;
> +	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
> +
> +	kvm_vgic_global_state.vcpu_base = vcpu_res.start;
> +
> +	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
> +		 vctrl_res.start, kvm_vgic_global_state.maint_irq);
> +
> +	kvm_vgic_global_state.type = VGIC_V2;
> +	kvm_vgic_global_state.max_gic_vcpus = VGIC_V2_MAX_CPUS;
> +	goto out;
> +
> +out_unmap:
> +	iounmap(kvm_vgic_global_state.vctrl_base);
> +out:
> +	of_node_put(vgic_node);
> +	return ret;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index dca52b3..48b0bb7 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -15,6 +15,12 @@
>  #include <linux/irqchip/arm-gic-v3.h>
>  #include <linux/kvm.h>
>  #include <linux/kvm_host.h>
> +#include <kvm/arm_vgic.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <asm/kvm_mmu.h>
> +#include <asm/kvm_asm.h>
>  
>  #include "vgic.h"
>  
> @@ -188,3 +194,70 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>  	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
>  	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
>  }
> +
> +/**
> + * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
> + * @node:	pointer to the DT node
> + *
> + * Returns 0 if a GICv3 has been found, returns an error code otherwise
> + */
> +int vgic_v3_probe(struct device_node *vgic_node)
> +{
> +	u32 ich_vtr_el2;
> +	u32 gicv_idx;
> +	int ret = 0;
> +	struct resource vcpu_res;
> +
> +	kvm_vgic_global_state.maint_irq = irq_of_parse_and_map(vgic_node, 0);
> +	if (!kvm_vgic_global_state.maint_irq) {
> +		kvm_err("error getting vgic maintenance irq from DT\n");
> +		ret = -ENXIO;
> +		goto out;
> +	}
> +
> +	ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
> +
> +	/*
> +	 * The ListRegs field is 5 bits, but there is a architectural
> +	 * maximum of 16 list registers. Just ignore bit 4...
> +	 */
> +	kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
> +	kvm_vgic_global_state.can_emulate_gicv2 = false;
> +
> +	if (of_property_read_u32(vgic_node, "#redistributor-regions",
> +				 &gicv_idx))
> +		gicv_idx = 1;
> +
> +	gicv_idx += 3; /* Also skip GICD, GICC, GICH */
> +	if (of_address_to_resource(vgic_node, gicv_idx, &vcpu_res)) {
> +		kvm_info("GICv3: no GICV resource entry\n");
> +		kvm_vgic_global_state.vcpu_base = 0;
> +	} else if (!PAGE_ALIGNED(vcpu_res.start)) {
> +		pr_warn("GICV physical address 0x%llx not page aligned\n",
> +			(unsigned long long)vcpu_res.start);
> +		kvm_vgic_global_state.vcpu_base = 0;
> +	} else if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
> +		pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
> +			(unsigned long long)resource_size(&vcpu_res),
> +			PAGE_SIZE);
> +		kvm_vgic_global_state.vcpu_base = 0;
> +	} else {
> +		kvm_vgic_global_state.vcpu_base = vcpu_res.start;
> +		kvm_vgic_global_state.can_emulate_gicv2 = true;
> +		kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
> +	}
> +	if (kvm_vgic_global_state.vcpu_base == 0)
> +		kvm_info("disabling GICv2 emulation\n");
> +	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V3);
> +
> +	kvm_vgic_global_state.vctrl_base = NULL;
> +	kvm_vgic_global_state.type = VGIC_V3;
> +	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
> +
> +	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
> +		 vcpu_res.start, kvm_vgic_global_state.maint_irq);
> +
> +out:
> +	of_node_put(vgic_node);
> +	return ret;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 7a69955..e49b1df 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -43,6 +43,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  			  int offset, u32 *val);
>  void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +int vgic_v2_probe(struct device_node *vgic_node);
>  int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>  			     enum vgic_type);
>  
> @@ -54,6 +55,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
>  void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +int vgic_v3_probe(struct device_node *vgic_node);
>  int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
>  #else
>  static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> @@ -87,6 +89,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
>  {
>  }
>  
> +static inline int vgic_v3_probe(struct device_node *vgic_node)
> +{
> +	return -ENODEV;
> +}
> +
>  static inline int vgic_register_redist_iodevs(struct kvm *kvm,
>  					      gpa_t dist_base_address)
>  {
> -- 
> 2.7.3
> 
> --

I think we need to change this behavior to use the gic_kvm_info
structure populated by Julien's patches now and in kvmarm/next for the
next version of the series, and then I'll review that part properly.
Thoughts?

Thanks,
-Christoffer


From laurent.pinchart at ideasonboard.com  Thu May 12 12:01:13 2016
From: laurent.pinchart at ideasonboard.com (Laurent Pinchart)
Date: Thu, 12 May 2016 22:01:13 +0300
Subject: [PATCH] PM / Runtime: Defer resuming of the device in
 pm_runtime_force_resume()
In-Reply-To: <CAPDyKFpOxabizwQqhtKb-h0vGpTRtrCa0nPxAKMY22rnjLCouw@mail.gmail.com>
References: <1461234842-22820-1-git-send-email-ulf.hansson@linaro.org>
 <5465506.Z3sjI0lQh6@avalon>
 <CAPDyKFpOxabizwQqhtKb-h0vGpTRtrCa0nPxAKMY22rnjLCouw@mail.gmail.com>
Message-ID: <4661739.p5SU9QcIps@avalon>

Hello,

On Wednesday 27 Apr 2016 16:23:49 Ulf Hansson wrote:
> [...]
> 
> >> Following you reasoning, I agree!
> >> 
> >> Let's put this patch on hold for a little while. I am already working
> >> on changing genpd, so it shouldn't take long before I can post some
> >> additional genpd patches improving the behaviour.
> > 
> > I'd like to see something merged for v4.7 if possible. I agree that my
> > patch isn't a long term solution (we want to avoid adding additional
> > fields to the device power structure), but it has the benefit of being
> > available now and fixing the problem I ran into with drivers that would
> > be broken on v4.7 without a fix. Do you think you could get a better fix
> > ready in time for v4.7 ? If so I'm fine with dropping this patch, but
> > otherwise I'd prefer to get it merged and reverted as part of your better
> > implementation for v4.8.
> 
> My impression was that devices becomes unnecessary resumed when they
> don't need to. They won't stay resumed as the PM core invokes
> pm_runtime_put() in the system PM complete phase.
> 
> So, in the end I think we are trying to optimize a behaviour here, but
> not fix something that is "broken", correct?
> 
> Anyway, I have no objections to your proposed solution, so I leave it
> to Rafael and Kevin to decide what to do.

Kevin, Rafael, any comment ? I need to fix PM support in a driver that is 
currently broken partly due to this issue. Which of "PM / Runtime: Only force-
resume device if it has been force-suspended" and this patch should we merge, 
if any ?

> From my side I will continue with the improvements for the system PM
> support in genpd.

Thanks.

-- 
Regards,

Laurent Pinchart



From christoffer.dall at linaro.org  Thu May 12 12:02:16 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 21:02:16 +0200
Subject: [PATCH v2] KVM: arm/arm64: vgic-new: Switch to
 firmware-independent probing
In-Reply-To: <1462869983-5410-1-git-send-email-marc.zyngier@arm.com>
References: <1462869983-5410-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <20160512190216.GO27623@cbox>

On Tue, May 10, 2016 at 09:46:23AM +0100, Marc Zyngier wrote:
> As we did for the legacy code, switch the new VGIC implementation
> the firmware-independent probing, giving us ACPI support for free.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>

So just remembered you wrote this after sending my comments to patch 48.

Are we planning to squash this into the series so I can review in
completeness/with context, or?

Thanks,
-Christoffer

> ---
> - From v1: Some additional cleanups, rebased on the lastest drop.
> 
>  virt/kvm/arm/vgic/vgic-init.c | 39 ++++++++++----------
>  virt/kvm/arm/vgic/vgic-v2.c   | 82 +++++++++++++++----------------------------
>  virt/kvm/arm/vgic/vgic-v3.c   | 44 ++++++-----------------
>  virt/kvm/arm/vgic/vgic.h      |  8 +++--
>  4 files changed, 63 insertions(+), 110 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> index 7fefb12..0c2c504 100644
> --- a/virt/kvm/arm/vgic/vgic-init.c
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -17,8 +17,6 @@
>  #include <linux/uaccess.h>
>  #include <linux/interrupt.h>
>  #include <linux/cpu.h>
> -#include <linux/of_address.h>
> -#include <linux/of_irq.h>
>  #include <linux/kvm_host.h>
>  #include <kvm/arm_vgic.h>
>  #include <asm/kvm_mmu.h>
> @@ -387,14 +385,6 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data)
>  	return IRQ_HANDLED;
>  }
>  
> -static const struct of_device_id vgic_ids[] = {
> -	{ .compatible = "arm,cortex-a15-gic",	.data = vgic_v2_probe, },
> -	{ .compatible = "arm,cortex-a7-gic",	.data = vgic_v2_probe, },
> -	{ .compatible = "arm,gic-400",		.data = vgic_v2_probe, },
> -	{ .compatible = "arm,gic-v3",		.data = vgic_v3_probe, },
> -	{},
> -};
> -
>  /**
>   * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable
>   * according to the host GIC model. Accordingly calls either
> @@ -403,23 +393,33 @@ static const struct of_device_id vgic_ids[] = {
>   */
>  int kvm_vgic_hyp_init(void)
>  {
> -	const struct of_device_id *matched_id;
> -	const int (*vgic_probe)(struct device_node *);
> -	struct device_node *vgic_node;
> +	const struct gic_kvm_info *gic_kvm_info;
>  	int ret;
>  
> -	vgic_node = of_find_matching_node_and_match(NULL,
> -						    vgic_ids, &matched_id);
> -	if (!vgic_node) {
> -		kvm_err("error: no compatible GIC node found\n");
> +	gic_kvm_info = gic_get_kvm_info();
> +	if (!gic_kvm_info)
>  		return -ENODEV;
> +
> +	if (!gic_kvm_info->maint_irq) {
> +		kvm_err("No vgic maintenance irq\n");
> +		return -ENXIO;
>  	}
>  
> -	vgic_probe = matched_id->data;
> -	ret = vgic_probe(vgic_node);
> +	switch (gic_kvm_info->type) {
> +	case GIC_V2:
> +		ret = vgic_v2_probe(gic_kvm_info);
> +		break;
> +	case GIC_V3:
> +		ret = vgic_v3_probe(gic_kvm_info);
> +		break;
> +	default:
> +		ret = -ENODEV;
> +	};
> +
>  	if (ret)
>  		return ret;
>  
> +	kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
>  	ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
>  				 vgic_maintenance_handler,
>  				 "vgic", kvm_get_running_vcpus());
> @@ -437,6 +437,7 @@ int kvm_vgic_hyp_init(void)
>  
>  	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
>  
> +	kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq);
>  	return 0;
>  
>  out_free_irq:
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> index 4493593..e88b5aa 100644
> --- a/virt/kvm/arm/vgic/vgic-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -18,9 +18,6 @@
>  #include <linux/kvm.h>
>  #include <linux/kvm_host.h>
>  #include <kvm/arm_vgic.h>
> -#include <linux/of.h>
> -#include <linux/of_address.h>
> -#include <linux/of_irq.h>
>  #include <asm/kvm_mmu.h>
>  
>  #include "vgic.h"
> @@ -278,81 +275,58 @@ out:
>   *
>   * Returns 0 if a GICv2 has been found, returns an error code otherwise
>   */
> -int vgic_v2_probe(struct device_node *vgic_node)
> +int vgic_v2_probe(const struct gic_kvm_info *info)
>  {
>  	int ret;
> -	struct resource vctrl_res;
> -	struct resource vcpu_res;
>  
> -	kvm_vgic_global_state.maint_irq = irq_of_parse_and_map(vgic_node, 0);
> -	if (!kvm_vgic_global_state.maint_irq) {
> -		kvm_err("error getting vgic maintenance irq from DT\n");
> -		ret = -ENXIO;
> -		goto out;
> +	if (!info->vctrl.start) {
> +		kvm_err("GICH not present in the firmware table\n");
> +		return -ENXIO;
>  	}
>  
> -	ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
> -	if (ret) {
> -		kvm_err("Cannot obtain GICH resource\n");
> -		goto out;
> +	if (!PAGE_ALIGNED(info->vcpu.start)) {
> +		kvm_err("GICV physical address 0x%llx not page aligned\n",
> +			(unsigned long long)info->vcpu.start);
> +		return -ENXIO;
> +	}
> +
> +	if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
> +		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
> +			(unsigned long long)resource_size(&info->vcpu),
> +			PAGE_SIZE);
> +		return -ENXIO;
>  	}
>  
> -	kvm_vgic_global_state.vctrl_base = of_iomap(vgic_node, 2);
> +	kvm_vgic_global_state.vctrl_base = ioremap(info->vctrl.start,
> +						   resource_size(&info->vctrl));
>  	if (!kvm_vgic_global_state.vctrl_base) {
>  		kvm_err("Cannot ioremap GICH\n");
> -		ret = -ENOMEM;
> -		goto out;
> +		return -ENOMEM;
>  	}
>  
>  	kvm_vgic_global_state.nr_lr =
>  		readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
> -	kvm_vgic_global_state.nr_lr = (kvm_vgic_global_state.nr_lr & 0x3f) + 1;
> +	kvm_vgic_global_state.nr_lr &= 0x3f;
> +	kvm_vgic_global_state.nr_lr += 1;
>  
>  	ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
>  				     kvm_vgic_global_state.vctrl_base +
> -					 resource_size(&vctrl_res),
> -				     vctrl_res.start);
> +					 resource_size(&info->vctrl),
> +				     info->vctrl.start);
>  	if (ret) {
>  		kvm_err("Cannot map VCTRL into hyp\n");
> -		goto out_unmap;
> -	}
> -
> -	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
> -		kvm_err("Cannot obtain GICV resource\n");
> -		ret = -ENXIO;
> -		goto out_unmap;
> -	}
> -
> -	if (!PAGE_ALIGNED(vcpu_res.start)) {
> -		kvm_err("GICV physical address 0x%llx not page aligned\n",
> -			(unsigned long long)vcpu_res.start);
> -		ret = -ENXIO;
> -		goto out_unmap;
> -	}
> -
> -	if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
> -		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
> -			(unsigned long long)resource_size(&vcpu_res),
> -			PAGE_SIZE);
> -		ret = -ENXIO;
> -		goto out_unmap;
> +		iounmap(kvm_vgic_global_state.vctrl_base);
> +		return ret;
>  	}
>  
>  	kvm_vgic_global_state.can_emulate_gicv2 = true;
>  	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
>  
> -	kvm_vgic_global_state.vcpu_base = vcpu_res.start;
> -
> -	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
> -		 vctrl_res.start, kvm_vgic_global_state.maint_irq);
> -
> +	kvm_vgic_global_state.vcpu_base = info->vcpu.start;
>  	kvm_vgic_global_state.type = VGIC_V2;
>  	kvm_vgic_global_state.max_gic_vcpus = VGIC_V2_MAX_CPUS;
> -	goto out;
>  
> -out_unmap:
> -	iounmap(kvm_vgic_global_state.vctrl_base);
> -out:
> -	of_node_put(vgic_node);
> -	return ret;
> +	kvm_info("vgic-v2@%llx\n", info->vctrl.start);
> +
> +	return 0;
>  }
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 6d7422f..6073f5d 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -16,9 +16,6 @@
>  #include <linux/kvm.h>
>  #include <linux/kvm_host.h>
>  #include <kvm/arm_vgic.h>
> -#include <linux/of.h>
> -#include <linux/of_address.h>
> -#include <linux/of_irq.h>
>  #include <asm/kvm_mmu.h>
>  #include <asm/kvm_asm.h>
>  
> @@ -271,21 +268,9 @@ out:
>   *
>   * Returns 0 if a GICv3 has been found, returns an error code otherwise
>   */
> -int vgic_v3_probe(struct device_node *vgic_node)
> +int vgic_v3_probe(const struct gic_kvm_info *info)
>  {
> -	u32 ich_vtr_el2;
> -	u32 gicv_idx;
> -	int ret = 0;
> -	struct resource vcpu_res;
> -
> -	kvm_vgic_global_state.maint_irq = irq_of_parse_and_map(vgic_node, 0);
> -	if (!kvm_vgic_global_state.maint_irq) {
> -		kvm_err("error getting vgic maintenance irq from DT\n");
> -		ret = -ENXIO;
> -		goto out;
> -	}
> -
> -	ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
> +	u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
>  
>  	/*
>  	 * The ListRegs field is 5 bits, but there is a architectural
> @@ -294,27 +279,23 @@ int vgic_v3_probe(struct device_node *vgic_node)
>  	kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>  
> -	if (of_property_read_u32(vgic_node, "#redistributor-regions",
> -				 &gicv_idx))
> -		gicv_idx = 1;
> -
> -	gicv_idx += 3; /* Also skip GICD, GICC, GICH */
> -	if (of_address_to_resource(vgic_node, gicv_idx, &vcpu_res)) {
> +	if (!info->vcpu.start) {
>  		kvm_info("GICv3: no GICV resource entry\n");
>  		kvm_vgic_global_state.vcpu_base = 0;
> -	} else if (!PAGE_ALIGNED(vcpu_res.start)) {
> +	} else if (!PAGE_ALIGNED(info->vcpu.start)) {
>  		pr_warn("GICV physical address 0x%llx not page aligned\n",
> -			(unsigned long long)vcpu_res.start);
> +			(unsigned long long)info->vcpu.start);
>  		kvm_vgic_global_state.vcpu_base = 0;
> -	} else if (!PAGE_ALIGNED(resource_size(&vcpu_res))) {
> +	} else if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
>  		pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
> -			(unsigned long long)resource_size(&vcpu_res),
> +			(unsigned long long)resource_size(&info->vcpu),
>  			PAGE_SIZE);
>  		kvm_vgic_global_state.vcpu_base = 0;
>  	} else {
> -		kvm_vgic_global_state.vcpu_base = vcpu_res.start;
> +		kvm_vgic_global_state.vcpu_base = info->vcpu.start;
>  		kvm_vgic_global_state.can_emulate_gicv2 = true;
>  		kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
> +		kvm_info("vgic-v2@%llx\n", info->vcpu.start);
>  	}
>  	if (kvm_vgic_global_state.vcpu_base == 0)
>  		kvm_info("disabling GICv2 emulation\n");
> @@ -324,10 +305,5 @@ int vgic_v3_probe(struct device_node *vgic_node)
>  	kvm_vgic_global_state.type = VGIC_V3;
>  	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
>  
> -	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
> -		 vcpu_res.start, kvm_vgic_global_state.maint_irq);
> -
> -out:
> -	of_node_put(vgic_node);
> -	return ret;
> +	return 0;
>  }
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 5c7dc99..83d3c48 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -16,6 +16,8 @@
>  #ifndef __KVM_ARM_VGIC_NEW_H__
>  #define __KVM_ARM_VGIC_NEW_H__
>  
> +#include <linux/irqchip/arm-gic-common.h>
> +
>  #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
>  #define IMPLEMENTER_ARM		0x43b
>  
> @@ -44,7 +46,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v2_enable(struct kvm_vcpu *vcpu);
> -int vgic_v2_probe(struct device_node *vgic_node);
> +int vgic_v2_probe(const struct gic_kvm_info *info);
>  int vgic_v2_map_resources(struct kvm *kvm);
>  int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>  			     enum vgic_type);
> @@ -58,7 +60,7 @@ void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
>  void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v3_enable(struct kvm_vcpu *vcpu);
> -int vgic_v3_probe(struct device_node *vgic_node);
> +int vgic_v3_probe(const struct gic_kvm_info *info);
>  int vgic_v3_map_resources(struct kvm *kvm);
>  int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
>  #else
> @@ -97,7 +99,7 @@ static inline void vgic_v3_enable(struct kvm_vcpu *vcpu)
>  {
>  }
>  
> -static inline int vgic_v3_probe(struct device_node *vgic_node)
> +static inline int vgic_v3_probe(const struct gic_kvm_info *info)
>  {
>  	return -ENODEV;
>  }
> -- 
> 2.1.4
> 


From christoffer.dall at linaro.org  Thu May 12 12:08:36 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 21:08:36 +0200
Subject: [PATCH v3 49/55] KVM: arm/arm64: vgic-new: vgic_init: implement
 vgic_create
In-Reply-To: <1462531568-9799-50-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-50-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512190836.GP27623@cbox>

On Fri, May 06, 2016 at 11:46:02AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> This patch implements the vgic_creation function which is
> called on CREATE_IRQCHIP VM IOCTL (v2 only) or KVM_CREATE_DEVICE
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  include/kvm/vgic/vgic.h       |  1 +
>  virt/kvm/arm/vgic/vgic-init.c | 84 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 85 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index d144e3d..899b7b7 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -202,6 +202,7 @@ struct vgic_cpu {
>  };
>  
>  int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
> +int kvm_vgic_create(struct kvm *kvm, u32 type);
>  int kvm_vgic_hyp_init(void);
>  
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> index f10997b..a150363 100644
> --- a/virt/kvm/arm/vgic/vgic-init.c
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -24,6 +24,90 @@
>  #include <asm/kvm_mmu.h>
>  #include "vgic.h"
>  
> +/* CREATION */
> +
> +/**
> + * kvm_vgic_create: triggered by the instantiation of the VGIC device by
> + * user space, either through the legacy ARM specific VM IOCTL (CREATE_IRQCHIP)

nit: is KVM_CREATE_IRQCHIP ARM specific or are we talking about the ARM
implementation of a generic ioctl?

> + * or through the generic VM IOCTL, KVM_CREATE_DEVICE API.
> + * Completion can be tested by irqchip_in_kernel

s/Completion can be tested by irqchip_in_kernel/
  irqchip_in_kernel() tells you if this function succeeded or not/

> + */
> +int kvm_vgic_create(struct kvm *kvm, u32 type)
> +{
> +	int i, vcpu_lock_idx = -1, ret;
> +	struct kvm_vcpu *vcpu;
> +
> +	mutex_lock(&kvm->lock);
> +
> +	if (irqchip_in_kernel(kvm)) {
> +		ret = -EEXIST;
> +		goto out;
> +	}
> +
> +	/*
> +	 * This function is also called by the KVM_CREATE_IRQCHIP handler,
> +	 * which had no chance yet to check the availability of the GICv2
> +	 * emulation. So check this here again. KVM_CREATE_DEVICE does
> +	 * the proper checks already.
> +	 */
> +	if (type == KVM_DEV_TYPE_ARM_VGIC_V2 &&
> +		!kvm_vgic_global_state.can_emulate_gicv2) {
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	/*
> +	 * Any time a vcpu is run, vcpu_load is called which tries to grab the
> +	 * vcpu->mutex.  By grabbing the vcpu->mutex of all VCPUs we ensure
> +	 * that no other VCPUs are run while we create the vgic.
> +	 */
> +	ret = -EBUSY;
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		if (!mutex_trylock(&vcpu->mutex))
> +			goto out_unlock;
> +		vcpu_lock_idx = i;
> +	}
> +
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		if (vcpu->arch.has_run_once)
> +			goto out_unlock;
> +	}
> +	ret = 0;
> +
> +	if (type == KVM_DEV_TYPE_ARM_VGIC_V2)
> +		kvm->arch.max_vcpus = VGIC_V2_MAX_CPUS;
> +	else
> +		kvm->arch.max_vcpus = VGIC_V3_MAX_CPUS;
> +
> +	if (atomic_read(&kvm->online_vcpus) > kvm->arch.max_vcpus) {
> +		ret = -E2BIG;
> +		goto out_unlock;
> +	}
> +
> +	kvm->arch.vgic.in_kernel = true;
> +	kvm->arch.vgic.vgic_model = type;
> +
> +	/*
> +	 * kvm_vgic_global_state.vctrl_base is set on vgic probe (kvm_arch_init)
> +	 * it is stored in distributor struct for asm save/restore purpose

we don't have any assembly code anymore, so could we simply export the
global state to __hyp code?

> +	 */
> +	kvm->arch.vgic.vctrl_base = kvm_vgic_global_state.vctrl_base;
> +
> +	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
> +	kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
> +	kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
> +
> +out_unlock:
> +	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
> +		vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
> +		mutex_unlock(&vcpu->mutex);
> +	}
> +
> +out:
> +	mutex_unlock(&kvm->lock);
> +	return ret;
> +}
> +
>  /* GENERIC PROBE */
>  
>  static void vgic_init_maintenance_interrupt(void *info)
> -- 
> 2.7.3
> 


From andre.przywara at arm.com  Thu May 12 12:10:21 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 12 May 2016 20:10:21 +0100
Subject: [PATCH v3 45/55] KVM: arm/arm64: vgic-new: Add userland access to
 VGIC dist registers
In-Reply-To: <20160512184110.GK27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-46-git-send-email-andre.przywara@arm.com>
 <20160512184110.GK27623@cbox>
Message-ID: <5734D51D.3000105@arm.com>

Hi,

On 12/05/16 19:41, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:58AM +0100, Andre Przywara wrote:
>> Userland may want to save and restore the state of the in-kernel VGIC,
>> so we provide the code which takes a userland request and translate
>> that into calls to our MMIO framework.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>>  virt/kvm/arm/vgic/vgic-kvm-device.c | 50 ++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 49 insertions(+), 1 deletion(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> index c952f6f..bb33af8 100644
>> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
>> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> @@ -264,7 +264,55 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
> 
> come to think of it, this is GICv2 specific right?
> 
> why don't we call it vgic_v2_attr_regs_access then?
> 
> and should it really live in this file?

Mmmh, at the moment every userland access is v2 specific, but
potentially this function should cover GICv3 as well, I think. We might
need some adjustments once this will be implemented, but in general I
don't see anything too v2 specific in here?

>>  				 struct kvm_device_attr *attr,
>>  				 u32 *reg, bool is_write)
>>  {
>> -	return -ENXIO;
>> +	gpa_t addr;
>> +	int cpuid, ret, c;
>> +	struct kvm_vcpu *vcpu, *tmp_vcpu;
>> +
>> +	cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
>> +		 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
>> +	vcpu = kvm_get_vcpu(dev->kvm, cpuid);
>> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
>> +
>> +	mutex_lock(&dev->kvm->lock);
>> +
>> +	ret = vgic_init(dev->kvm);
>> +	if (ret)
>> +		goto out;
>> +
>> +	if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
>> +		ret = -EINVAL;
>> +		goto out;
>> +	}
>> +
>> +	/*
>> +	 * Ensure that no other VCPU is running by checking the vcpu->cpu
>> +	 * field.  If no other VPCUs are running we can safely access the VGIC
>> +	 * state, because even if another VPU is run after this point, that
>> +	 * VCPU will not touch the vgic state, because it will block on
>> +	 * getting the vgic->lock in kvm_vgic_sync_hwstate().
>> +	 */
> 
> eh, I don't see us grabbing any vgic->lock (does that still exist?)
> here?

Yeah, that scared me the other day too.
In fact I think we cannot guarantee this requirement anymore with our
existing locks - but maybe we can pause the guest explicitly as we do
now for the clear-active handler?

Cheers,
Andre.

>> +	kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm) {
>> +		if (unlikely(tmp_vcpu->cpu != -1)) {
>> +			ret = -EBUSY;
>> +			goto out;
>> +		}
>> +	}
>> +
>> +	switch (attr->group) {
>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>> +		ret = -EINVAL;
>> +		break;
>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>> +		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
>> +		break;
>> +	default:
>> +		ret = -EINVAL;
>> +		break;
>> +	}
>> +
>> +out:
>> +	mutex_unlock(&dev->kvm->lock);
>> +	return ret;
>>  }
>>  
>>  /* V2 ops */
>> -- 
>> 2.7.3
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe kvm" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> Thanks,
> -Christoffer
> 


From nm at ti.com  Thu May 12 12:19:15 2016
From: nm at ti.com (Nishanth Menon)
Date: Thu, 12 May 2016 14:19:15 -0500
Subject: [PATCH] ARM: dts: omap5-igep0050: Correct hdmi regulator
In-Reply-To: <20160512165755.GR5995@atomide.com>
References: <1461925297-9734-1-git-send-email-peter.ujfalusi@ti.com>
 <6ee9d67a-e907-715a-f3f5-d90a470314c3@ti.com>
 <20160504172634.GS5995@atomide.com> <572A38FD.9050801@ti.com>
 <20160505184609.GB5995@atomide.com>
 <2822D1C2B9B19F4A8261F756A13373F801BEF7B4@DFLE11.ent.ti.com>
 <CAPjucKb+4vd8Ar3MATCuTx+9R36PeB0hbvwDaAD1KTZFCiVJEA@mail.gmail.com>
 <2822D1C2B9B19F4A8261F756A13373F801BF86D2@DFLE11.ent.ti.com>
 <2822D1C2B9B19F4A8261F756A13373F801BF8703@DFLE11.ent.ti.com>
 <CAPjucKb2PLSZcD3YZ9xQk1F62ugFaGAkBBqMp5GmoWFd0H8Vfg@mail.gmail.com>
 <20160512165755.GR5995@atomide.com>
Message-ID: <5734D733.9060400@ti.com>

On 05/12/2016 11:57 AM, Tony Lindgren wrote:
> * Eduard Gavin <egavin at iseebcn.com> [160509 07:43]:
>> Dear Nishanth,
>>   In igepV5 the LDO7 is connected to:
>>     VDDA_DSIPORTA - ball AA33
>>     VDDA_DSIPORTC - ball AE33
>>     VDDA_HDMI - ball AN25
>>   LDO4 is connected to:
>>     VPP1 - ball AD9
> 
> Thanks for the info, here's an updated patch with comments and now
> using 1.8V instead of the 2.0V omap5-board-common.dtsi.
> 
> Regards,
> 
> Tony
> 
> 8< -----------------
> From: Tony Lindgren <tony at atomide.com>
> Date: Mon, 9 May 2016 07:51:00 -0700
> Subject: [PATCH] ARM: dts: Fix ldo7 source for HDMI on igepv5
> 
> Fix ldo7 source for HDMI on igepv5.
> 
> Suggested-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
> Signed-off-by: Tony Lindgren <tony at atomide.com>
> 
> --- a/arch/arm/boot/dts/omap5-igep0050.dts
> +++ b/arch/arm/boot/dts/omap5-igep0050.dts
> @@ -35,6 +35,16 @@
>  	};
>  };
>  
> +/*
> + * LDO7 is used for HDMI: VDDA_DSIPORTA - ball AA33, VDDA_DSIPORTC - ball AE33
> + * VDDA_HDMI - ball AN25. LDO4 is: VPP1 - ball AD9.

We should set ldo4_reg as 2v as well (default in omap5-board-common is
1.8v). VPP1 should be 2v to prevent efuse from being messed up.

> + */
> +&ldo7_reg {
> +	status = "okay";
> +	regulator-min-microvolt = <1800000>;
> +	regulator-max-microvolt = <1800000>;
> +};
> +
>  &omap5_pmx_core {
>  	i2c4_pins: pinmux_i2c4_pins {
>  		pinctrl-single,pins = <
> 


-- 
Regards,
Nishanth Menon


From nm at ti.com  Thu May 12 12:19:49 2016
From: nm at ti.com (Nishanth Menon)
Date: Thu, 12 May 2016 14:19:49 -0500
Subject: [PATCH] ARM: OMAP5 / DRA7: Introduce workaround for 801819
In-Reply-To: <20160512171244.GT5995@atomide.com>
References: <1438876464-15424-1-git-send-email-nm@ti.com>
 <20160512171244.GT5995@atomide.com>
Message-ID: <5734D755.3040406@ti.com>

On 05/12/2016 12:12 PM, Tony Lindgren wrote:
> * Nishanth Menon <nm at ti.com> [150806 08:57]:
>> Add workaround for Cortex-A15 ARM erratum 801819 which says in summary
>> that "A livelock can occur in the L2 cache arbitration that might
>> prevent a snoop from completing. Under certain conditions this can
>> cause the system to deadlock. "
> 
> Thanks for the late reminder, this has totally fallen through the
> cracks. Applying into omap-for-v4.7/fixes. Once merged to mainline,
> it can be requested for stable if needed.

Thanks for digging this out.


-- 
Regards,
Nishanth Menon


From christoffer.dall at linaro.org  Thu May 12 12:25:50 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 21:25:50 +0200
Subject: [PATCH v3 50/55] KVM: arm/arm64: vgic-new: vgic_init: implement
 vgic_init
In-Reply-To: <1462531568-9799-51-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-51-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512192550.GQ27623@cbox>

On Fri, May 06, 2016 at 11:46:03AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> This patch allocates and initializes the data structures used
> to model the vgic distributor and virtual cpu interfaces. At that
> stage the number of IRQs and number of virtual CPUs is frozen.
> 
> The following early_init functions are kept since they are called from
> arm.c. However they may disappear in subsequent patches since
> they are void.
> 
> vgic_[v2|v3]_enable still is stubbed at this stage.

I suggest deleting the last two paragraphs.

> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - initialize v2/v3 default CPU affinities explicitly
> 
> Changelog v1 .. v2:
> - move lazy_init() into vgic_update_irq_pending()
> 
>  include/kvm/vgic/vgic.h       |   7 +-
>  virt/kvm/arm/vgic/vgic-init.c | 213 ++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v2.c   |   5 +
>  virt/kvm/arm/vgic/vgic-v3.c   |   5 +
>  virt/kvm/arm/vgic/vgic.c      |   4 +
>  virt/kvm/arm/vgic/vgic.h      |   8 ++
>  6 files changed, 241 insertions(+), 1 deletion(-)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 899b7b7..538078a 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -119,6 +119,7 @@ struct vgic_io_device {
>  struct vgic_dist {
>  	bool			in_kernel;
>  	bool			ready;
> +	bool			initialized;
>  
>  	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
>  	u32			vgic_model;
> @@ -202,7 +203,11 @@ struct vgic_cpu {
>  };
>  
>  int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
> +void kvm_vgic_early_init(struct kvm *kvm);
>  int kvm_vgic_create(struct kvm *kvm, u32 type);
> +void kvm_vgic_destroy(struct kvm *kvm);
> +void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
> +void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
>  int kvm_vgic_hyp_init(void);
>  
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
> @@ -211,7 +216,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
>  
>  #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
> -#define vgic_initialized(k)	(false)
> +#define vgic_initialized(k)	((k)->arch.vgic.initialized)
>  #define vgic_ready(k)		((k)->arch.vgic.ready)
>  #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
>  			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> index a150363..3f9c137 100644
> --- a/virt/kvm/arm/vgic/vgic-init.c
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -24,6 +24,42 @@
>  #include <asm/kvm_mmu.h>
>  #include "vgic.h"
>  
> +/*
> + * Initialization rules: there are multiple stages to the vgic
> + * initialization, both for the distributor and the CPU interfaces.
> + *
> + * Distributor:
> + *
> + * - kvm_vgic_early_init(): initialization of static data that doesn't
> + *   depend on any sizing information or emulation type. No allocation
> + *   is allowed there.
> + *
> + * - vgic_init(): allocation and initialization of the generic data
> + *   structures that depend on sizing information (number of CPUs,
> + *   number of interrupts). Also initializes the vcpu specific data
> + *   structures. Can be executed lazily for GICv2.
> + *
> + * CPU Interface:
> + *
> + * - kvm_vgic_cpu_early_init(): initialization of static data that
> + *   doesn't depend on any sizing information or emulation type. No
> + *   allocation is allowed there.
> + */
> +
> +/* EARLY INIT */
> +
> +/*
> + * Those 2 functions should not be needed anymore but they
> + * still are called from arm.c
> + */
> +void kvm_vgic_early_init(struct kvm *kvm)
> +{
> +}
> +
> +void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu)
> +{
> +}
> +
>  /* CREATION */
>  
>  /**
> @@ -108,6 +144,183 @@ out:
>  	return ret;
>  }
>  
> +/* INIT/DESTROY */
> +
> +/**
> + * kvm_vgic_dist_init: initialize the dist data structures
> + * @kvm: kvm struct pointer
> + * @nr_spis: number of spis, frozen by caller
> + */
> +int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)

is this ever called from outside this file?

If not, why is it not static?

> +{
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	struct kvm_vcpu *vcpu0 = kvm_get_vcpu(kvm, 0);
> +	int i;
> +
> +	dist->spis = kcalloc(nr_spis, sizeof(struct vgic_irq), GFP_KERNEL);
> +	if (!dist->spis)
> +		return  -ENOMEM;
> +
> +	/*
> +	 * In following code we do not take the irq struct lock since
> +	 * no other action on irq structs can happen while the VGIC is
> +	 * not initialized yet:
> +	 * injection requires (VGICV3) or does (VGIC2) initialization.
> +	 * MMIO access triggers init.

I don't understand these two last lines of comment?

> +	 */
> +	for (i = 0; i < nr_spis; i++) {
> +		struct vgic_irq *irq = &dist->spis[i];
> +
> +		irq->intid = i + VGIC_NR_PRIVATE_IRQS;
> +		INIT_LIST_HEAD(&irq->ap_list);
> +		spin_lock_init(&irq->irq_lock);
> +		irq->vcpu = NULL;
> +		irq->target_vcpu = vcpu0;
> +		if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
> +			irq->targets = 0;
> +		else
> +			irq->mpidr = 0;
> +	}
> +	return 0;
> +}
> +
> +/**
> + * kvm_vgic_vcpu_init: initialize the vcpu data structures and
> + * enable the VCPU interface
> + * @kvm: kvm struct pointer
> + */
> +void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)

same here

> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	int i;
> +
> +	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
> +	spin_lock_init(&vgic_cpu->ap_list_lock);
> +
> +	/*
> +	 * Enable and configure all SGIs to be edge-triggered and
> +	 * configure all PPIs as level-triggered.
> +	 */
> +	for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
> +		struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
> +
> +		INIT_LIST_HEAD(&irq->ap_list);
> +		spin_lock_init(&irq->irq_lock);
> +		irq->intid = i;
> +		irq->vcpu = NULL;
> +		irq->target_vcpu = vcpu;
> +		irq->targets = 1U << vcpu->vcpu_id;
> +		if (vgic_irq_is_sgi(i)) {
> +			/* SGIs */
> +			irq->enabled = 1;
> +			irq->config = VGIC_CONFIG_EDGE;
> +		} else {
> +			/* PPIs */
> +			irq->config = VGIC_CONFIG_LEVEL;
> +		}
> +	}
> +	if (kvm_vgic_global_state.type == VGIC_V2)
> +		vgic_v2_enable(vcpu);
> +	else
> +		vgic_v3_enable(vcpu);
> +}
> +
> +/*
> + * vgic_init: allocates and initializes dist and vcpu data structures
> + * depending on two dimensioning parameters:
> + * - the number of spis
> + * - the number of vcpus
> + * The function is generally called when nr_spis has been explicitly set
> + * by the guest through the KVM DEVICE API. If not nr_spis is set to 256.
> + * Completion can be tested by vgic_initialized

s/Completion can be tested by vgic_initialized/
  vgic_initialized() returns true when this function has succeeded/

> + * Must be called with kvm->lock held!
> + */
> +int vgic_init(struct kvm *kvm)
> +{
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	struct kvm_vcpu *vcpu;
> +	int ret = 0, i;
> +
> +	if (vgic_initialized(kvm))
> +		return 0;
> +
> +	/* freeze the number of spis */
> +	if (!dist->nr_spis)
> +		dist->nr_spis = VGIC_NR_IRQS_LEGACY - VGIC_NR_PRIVATE_IRQS;
> +
> +	ret = kvm_vgic_dist_init(kvm, dist->nr_spis);
> +	if (ret)
> +		goto out;
> +
> +	kvm_for_each_vcpu(i, vcpu, kvm)
> +		kvm_vgic_vcpu_init(vcpu);
> +
> +	dist->initialized = true;
> +out:
> +	return ret;
> +}
> +
> +static void kvm_vgic_dist_destroy(struct kvm *kvm)
> +{
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +
> +	mutex_lock(&kvm->lock);
> +
> +	dist->ready = false;
> +	dist->initialized = false;
> +
> +	kfree(dist->spis);
> +	kfree(dist->redist_iodevs);
> +	dist->nr_spis = 0;
> +
> +	mutex_unlock(&kvm->lock);
> +}
> +
> +void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +
> +	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);

this is actually not the state prior to initialization, so is this
really required?

> +}
> +
> +void kvm_vgic_destroy(struct kvm *kvm)
> +{
> +	struct kvm_vcpu *vcpu;
> +	int i;
> +
> +	kvm_vgic_dist_destroy(kvm);
> +
> +	kvm_for_each_vcpu(i, vcpu, kvm)
> +		kvm_vgic_vcpu_destroy(vcpu);
> +}
> +
> +/**
> + * Lazy init only is allowed if the GIC exposed to the guest is a GICV2.
> + * GICV3 must be explicitly initialized by the guest using the
> + * KVM_DEV_ARM_VGIC_GRP_CTRL KVM_DEVICE group

nit: period after group.

> + */
> +int vgic_lazy_init(struct kvm *kvm)
> +{
> +	int ret = 0;
> +
> +	if (unlikely(!vgic_initialized(kvm))) {
> +		/*
> +		 * We only provide the automatic initialization of the VGIC
> +		 * for the legacy case of a GICv2. Any other type must
> +		 * be explicitly initialized once setup with the respective
> +		 * KVM device call.
> +		 */
> +		if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2)
> +			return -EBUSY;
> +
> +		mutex_lock(&kvm->lock);
> +		ret = vgic_init(kvm);
> +		mutex_unlock(&kvm->lock);
> +	}
> +
> +	return ret;
> +}
> +
>  /* GENERIC PROBE */
>  
>  static void vgic_init_maintenance_interrupt(void *info)
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> index 91b69a4..48aa877 100644
> --- a/virt/kvm/arm/vgic/vgic-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -211,6 +211,11 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>  			GICH_VMCR_PRIMASK_SHIFT;
>  }
>  
> +/* not yet implemented */
> +void vgic_v2_enable(struct kvm_vcpu *vcpu)
> +{
> +}
> +
>  /**
>   * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
>   * @node:	pointer to the DT node
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 48b0bb7..7cab5b9 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -195,6 +195,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>  	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
>  }
>  
> +/* not yet implemented */
> +void vgic_v3_enable(struct kvm_vcpu *vcpu)
> +{
> +}
> +
>  /**
>   * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
>   * @node:	pointer to the DT node
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 5355de6..068389a 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -255,6 +255,10 @@ static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
>  
>  	trace_vgic_update_irq_pending(cpuid, intid, level);
>  
> +	ret = vgic_lazy_init(kvm);
> +	if (ret)
> +		return ret;
> +
>  	vcpu = kvm_get_vcpu(kvm, cpuid);
>  	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
>  		return -EINVAL;
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index e49b1df..cad04eb 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -43,6 +43,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  			  int offset, u32 *val);
>  void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +void vgic_v2_enable(struct kvm_vcpu *vcpu);
>  int vgic_v2_probe(struct device_node *vgic_node);
>  int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>  			     enum vgic_type);
> @@ -55,6 +56,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
>  void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +void vgic_v3_enable(struct kvm_vcpu *vcpu);
>  int vgic_v3_probe(struct device_node *vgic_node);
>  int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
>  #else
> @@ -89,6 +91,10 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
>  {
>  }
>  
> +static inline void vgic_v3_enable(struct kvm_vcpu *vcpu)
> +{
> +}
> +
>  static inline int vgic_v3_probe(struct device_node *vgic_node)
>  {
>  	return -ENODEV;
> @@ -102,5 +108,7 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
>  #endif
>  
>  void kvm_register_vgic_device(unsigned long type);
> +int vgic_lazy_init(struct kvm *kvm);
> +int vgic_init(struct kvm *kvm);
>  
>  #endif
> -- 
> 2.7.3
> 
> --

The cosmetic comments notwithstanding:

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Thu May 12 12:28:28 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 21:28:28 +0200
Subject: [PATCH v3 51/55] KVM: arm/arm64: vgic-new: vgic_init: implement
 map_resources
In-Reply-To: <1462531568-9799-52-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-52-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512192828.GR27623@cbox>

On Fri, May 06, 2016 at 11:46:04AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> map_resources is the last initialization step. It is executed on
> 1st VCPU run. At that stage the code checks the userspace has provided
> the base addresses for the relevant VGIC regions, which depend on
> the type of VGIC that is exposed to the guest.
> 
> The function also forces the vgic_init if it has not been executed yet
> (only allowed for VGIC v2).
> 
> for GICv2, The VGIC CPU interface is mapped onto the GIC virtual CPU
> interface.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  include/kvm/vgic/vgic.h       |  1 +
>  virt/kvm/arm/vgic/vgic-init.c | 27 +++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v2.c   | 47 +++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c   | 44 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h      |  7 +++++++
>  5 files changed, 126 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 538078a..07c3011 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -208,6 +208,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type);
>  void kvm_vgic_destroy(struct kvm *kvm);
>  void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
>  void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
> +int kvm_vgic_map_resources(struct kvm *kvm);
>  int kvm_vgic_hyp_init(void);
>  
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> index 3f9c137..7fefb12 100644
> --- a/virt/kvm/arm/vgic/vgic-init.c
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -321,6 +321,33 @@ int vgic_lazy_init(struct kvm *kvm)
>  	return ret;
>  }
>  
> +/* RESOURCE MAPPING */
> +
> +/**
> + * Map the MMIO regions depending on the VGIC model exposed to the guest
> + * called on the first VCPU run.
> + * Also map the virtual CPU interface into the VM.
> + * v2/v3 derivatives call vgic_init if not already done.
> + * Completion can be tested by vgic_ready

s/Completion can be tested by vgic_ready/
 vgic_ready() returns true if this function has succeeded/

> + */
> +int kvm_vgic_map_resources(struct kvm *kvm)
> +{
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	int ret = 0;
> +
> +	mutex_lock(&kvm->lock);
> +	if (!irqchip_in_kernel(kvm))
> +		goto out;
> +
> +	if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
> +		ret = vgic_v2_map_resources(kvm);
> +	else
> +		ret = vgic_v3_map_resources(kvm);
> +out:
> +	mutex_unlock(&kvm->lock);
> +	return ret;
> +}
> +
>  /* GENERIC PROBE */
>  
>  static void vgic_init_maintenance_interrupt(void *info)
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> index 48aa877..1e411f5 100644
> --- a/virt/kvm/arm/vgic/vgic-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -216,6 +216,53 @@ void vgic_v2_enable(struct kvm_vcpu *vcpu)
>  {
>  }
>  
> +int vgic_v2_map_resources(struct kvm *kvm)
> +{
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	int ret = 0;
> +
> +	if (vgic_ready(kvm))
> +		goto out;
> +
> +	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
> +	    IS_VGIC_ADDR_UNDEF(dist->vgic_cpu_base)) {
> +		kvm_err("Need to set vgic cpu and dist addresses first\n");
> +		ret = -ENXIO;
> +		goto out;
> +	}
> +
> +	/*
> +	 * Initialize the vgic if this hasn't already been done on demand by
> +	 * accessing the vgic state from userspace.
> +	 */
> +	ret = vgic_init(kvm);
> +	if (ret) {
> +		kvm_err("Unable to initialize VGIC dynamic data structures\n");
> +		goto out;
> +	}
> +
> +	ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V2);
> +	if (ret) {
> +		kvm_err("Unable to register VGIC MMIO regions\n");
> +		goto out;
> +	}
> +
> +	ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base,
> +				    kvm_vgic_global_state.vcpu_base,
> +				    KVM_VGIC_V2_CPU_SIZE, true);
> +	if (ret) {
> +		kvm_err("Unable to remap VGIC CPU to VCPU\n");
> +		goto out;
> +	}
> +
> +	dist->ready = true;
> +
> +out:
> +	if (ret)
> +		kvm_vgic_destroy(kvm);
> +	return ret;
> +}
> +
>  /**
>   * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
>   * @node:	pointer to the DT node
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 7cab5b9..4bfd42a 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -200,6 +200,50 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>  {
>  }
>  
> +int vgic_v3_map_resources(struct kvm *kvm)
> +{
> +	int ret = 0;
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +
> +	if (vgic_ready(kvm))
> +		goto out;
> +
> +	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
> +	    IS_VGIC_ADDR_UNDEF(dist->vgic_redist_base)) {
> +		kvm_err("Need to set vgic distributor addresses first\n");
> +		ret = -ENXIO;
> +		goto out;
> +	}
> +
> +	/*
> +	 * For a VGICv3 we require the userland to explicitly initialize
> +	 * the VGIC before we need to use it.
> +	 */
> +	if (!vgic_initialized(kvm)) {
> +		ret = -EBUSY;
> +		goto out;
> +	}
> +
> +	ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V3);
> +	if (ret) {
> +		kvm_err("Unable to register VGICv3 dist MMIO regions\n");
> +		goto out;
> +	}
> +
> +	ret = vgic_register_redist_iodevs(kvm, dist->vgic_redist_base);
> +	if (ret) {
> +		kvm_err("Unable to register VGICv3 redist MMIO regions\n");
> +		goto out;
> +	}
> +
> +	dist->ready = true;
> +
> +out:
> +	if (ret)
> +		kvm_vgic_destroy(kvm);
> +	return ret;
> +}
> +
>  /**
>   * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
>   * @node:	pointer to the DT node
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index cad04eb..5c7dc99 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -45,6 +45,7 @@ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v2_enable(struct kvm_vcpu *vcpu);
>  int vgic_v2_probe(struct device_node *vgic_node);
> +int vgic_v2_map_resources(struct kvm *kvm);
>  int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>  			     enum vgic_type);
>  
> @@ -58,6 +59,7 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v3_enable(struct kvm_vcpu *vcpu);
>  int vgic_v3_probe(struct device_node *vgic_node);
> +int vgic_v3_map_resources(struct kvm *kvm);
>  int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
>  #else
>  static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> @@ -100,6 +102,11 @@ static inline int vgic_v3_probe(struct device_node *vgic_node)
>  	return -ENODEV;
>  }
>  
> +static inline int vgic_v3_map_resources(struct kvm *kvm)
> +{
> +	return -ENODEV;
> +}
> +
>  static inline int vgic_register_redist_iodevs(struct kvm *kvm,
>  					      gpa_t dist_base_address)
>  {
> -- 
> 2.7.3
> 
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From chunkeey at googlemail.com  Thu May 12 12:28:09 2016
From: chunkeey at googlemail.com (Christian Lamparter)
Date: Thu, 12 May 2016 21:28:09 +0200
Subject: [PATCH v9.1] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <0a1ab2b6-b4c5-44d7-abb4-ce1e9da7e477@gmail.com>
References: <0a1ab2b6-b4c5-44d7-abb4-ce1e9da7e477@gmail.com>
Message-ID: <3e75e8316ceac62f61f3ffc839faaac8789ca936.1463078228.git.chunkeey@googlemail.com>

From: ?lvaro Fern?ndez Rojas <noltari at gmail.com>

This patch adds support for defining memory-mapped GPIOs which
are compatible with the existing gpio-mmio interface. The generic
library provides support for many memory-mapped GPIO controllers
that are found in various on-board FPGA and ASIC solutions that
are used to control board's switches, LEDs, chip-selects,
Ethernet/USB PHY power, etc.

For setting GPIOs there are three configurations:
	1. single input/output register resource (named "dat"),
	2. set/clear pair (named "set" and "clr"),
	3. single output register resource and single input resource
	   ("set" and dat").

The configuration is detected by which resources are present.
For the single output register, this drives a 1 by setting a bit
and a zero by clearing a bit.  For the set clr pair, this drives
a 1 by setting a bit in the set register and clears it by setting
a bit in the clear register.

For setting the GPIO direction, there are three configurations:
	a. simple bidirectional GPIOs that requires no configuration.
	b. an output direction register (named "dirout")
	   where a 1 bit indicates the GPIO is an output.
	c. an input direction register (named "dirin")
	   where a 1 bit indicates the GPIO is an input.

The first user for this binding is "wd,mbl-gpio".

Reviewed-by: Andy Shevchenko <andy.shevchenko at gmail.com>
Signed-off-by: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
---
 drivers/gpio/gpio-mmio.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 66 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 6c1cb3b..f72e40e 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -61,6 +61,8 @@ o        `                     ~~~~\___/~~~~    ` controller in FPGA is ,.`
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
 #include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 static void bgpio_write8(void __iomem *reg, unsigned long data)
 {
@@ -569,6 +571,58 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
 	return devm_ioremap_resource(&pdev->dev, r);
 }
 
+#ifdef CONFIG_OF
+static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
+				     struct bgpio_pdata *pdata,
+				     unsigned long *flags)
+{
+	struct device *dev = &pdev->dev;
+
+	pdata->base = -1;
+
+	if (of_property_read_bool(dev->of_node, "no-output"))
+		*flags |= BGPIOF_NO_OUTPUT;
+
+	return 0;
+}
+
+static const struct of_device_id bgpio_of_match[] = {
+	{ .compatible = "wd,mbl-gpio", .data = bgpio_basic_mmio_parse_dt },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, bgpio_of_match);
+
+static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
+					  unsigned long *flags)
+{
+	const int (*parse_dt)(struct platform_device *,
+			      struct bgpio_pdata *, unsigned long *);
+	struct bgpio_pdata *pdata;
+	int err;
+
+	parse_dt = of_device_get_match_data(&pdev->dev);
+	if (!parse_dt)
+		return NULL;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata),
+			     GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	err = parse_dt(pdev, pdata, flags);
+	if (err)
+		return ERR_PTR(err);
+
+	return pdata;
+}
+#else
+static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
+					  unsigned long *flags)
+{
+	return NULL;
+}
+#endif /* CONFIG_OF */
+
 static int bgpio_pdev_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -579,10 +633,19 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
 	void __iomem *dirout;
 	void __iomem *dirin;
 	unsigned long sz;
-	unsigned long flags = pdev->id_entry->driver_data;
+	unsigned long flags = 0;
 	int err;
 	struct gpio_chip *gc;
-	struct bgpio_pdata *pdata = dev_get_platdata(dev);
+	struct bgpio_pdata *pdata;
+
+	pdata = bgpio_parse_dt(pdev, &flags);
+	if (IS_ERR(pdata))
+		return PTR_ERR(pdata);
+
+	if (!pdata) {
+		pdata = dev_get_platdata(dev);
+		flags = pdev->id_entry->driver_data;
+	}
 
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
 	if (!r)
@@ -646,6 +709,7 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table);
 static struct platform_driver bgpio_driver = {
 	.driver = {
 		.name = "basic-mmio-gpio",
+		.of_match_table = of_match_ptr(bgpio_of_match),
 	},
 	.id_table = bgpio_id_table,
 	.probe = bgpio_pdev_probe,
-- 
2.8.1



From christoffer.dall at linaro.org  Thu May 12 12:30:07 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 21:30:07 +0200
Subject: [PATCH v3 52/55] KVM: arm/arm64: vgic-new: Add vgic_v2/v3_enable
In-Reply-To: <1462531568-9799-53-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-53-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512193007.GS27623@cbox>

On Fri, May 06, 2016 at 11:46:05AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> Enable the VGIC operation by properly initialising the registers
> in the hypervisor GIC interface.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-v2.c | 11 ++++++++++-
>  virt/kvm/arm/vgic/vgic-v3.c | 23 ++++++++++++++++++++++-
>  2 files changed, 32 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> index 1e411f5..4493593 100644
> --- a/virt/kvm/arm/vgic/vgic-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -211,9 +211,18 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>  			GICH_VMCR_PRIMASK_SHIFT;
>  }
>  
> -/* not yet implemented */
>  void vgic_v2_enable(struct kvm_vcpu *vcpu)
>  {
> +	/*
> +	 * By forcing VMCR to zero, the GIC will restore the binary
> +	 * points to their reset values. Anything else resets to zero
> +	 * anyway.
> +	 */
> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = 0;
> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr = ~0;
> +
> +	/* Get the show on the road... */
> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr = GICH_HCR_EN;
>  }
>  
>  int vgic_v2_map_resources(struct kvm *kvm)
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 4bfd42a..6d7422f 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -195,9 +195,30 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>  	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
>  }
>  
> -/* not yet implemented */
>  void vgic_v3_enable(struct kvm_vcpu *vcpu)
>  {
> +	struct vgic_v3_cpu_if *vgic_v3 = &vcpu->arch.vgic_cpu.vgic_v3;
> +
> +	/*
> +	 * By forcing VMCR to zero, the GIC will restore the binary
> +	 * points to their reset values. Anything else resets to zero
> +	 * anyway.
> +	 */
> +	vgic_v3->vgic_vmcr = 0;
> +	vgic_v3->vgic_elrsr = ~0;
> +
> +	/*
> +	 * If we are emulating a GICv3, we do it in an non-GICv2-compatible
> +	 * way, so we force SRE to 1 to demonstrate this to the guest.
> +	 * This goes with the spec allowing the value to be RAO/WI.
> +	 */
> +	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
> +		vgic_v3->vgic_sre = ICC_SRE_EL1_SRE;
> +	else
> +		vgic_v3->vgic_sre = 0;
> +
> +	/* Get the show on the road... */
> +	vgic_v3->vgic_hcr = ICH_HCR_EN;
>  }
>  
>  int vgic_v3_map_resources(struct kvm *kvm)
> -- 
> 2.7.3
> 

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From absahu at codeaurora.org  Thu May 12 12:32:29 2016
From: absahu at codeaurora.org (Abhishek Sahu)
Date: Fri, 13 May 2016 01:02:29 +0530
Subject: [PATCH 1/2] i2c: qup: Cleared the error bits in ISR
In-Reply-To: <20160512175830.GA32019@hector>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
 <1462797871-8595-2-git-send-email-absahu@codeaurora.org>
 <000701d1ab9d$df9b3100$9ed19300$@codeaurora.org>
 <934365f2bd30f242d8548e2a27483679@codeaurora.org>
 <20160512051347.GE8453@hector.attlocal.net>
 <20160512061843.GA6187@chewinlnx07.qualcomm.com>
 <20160512175830.GA32019@hector>
Message-ID: <20160512193229.GA10499@chewinlnx07.qualcomm.com>

On Thu, May 12, 2016 at 12:58:30PM -0500, Andy Gross wrote:
> On Thu, May 12, 2016 at 11:48:43AM +0530, Abhishek Sahu wrote:
> > On Thu, May 12, 2016 at 12:13:47AM -0500, Andy Gross wrote:
> > > On Wed, May 11, 2016 at 11:04:17PM +0530, Abhishek Sahu wrote:
> > > 
> > > <snip>
> > > 
> > > > >       In qup_i2c_xfer and qup_i2c_xfer_v2 state is set to RESET at the
> > > > >end, when
> > > > >       there is no error. So would it be fine if we do it there
> > > > >unconditionally ?
> > > > >
> > > > >Regards,
> > > > > Sricharan
> > > > 
> > > > RESET the QUP state wouldn't create any issue in the case of multiple calls.
> > > > The existing code also RESET the QUP state for bus_err but it is not
> > > > clearing
> > > > status bits.
> > > 
> > > It'd be better to not reset the QUP inside the ISR at all.  I think the better
> > > solution is making the reset occur in the xfer function.  So just clear the bits
> > > like you should in the isr, and defer reset till later.
> > 
> > This is a HW workaround for QUP where we need to RESET the core in
> > ISR. When interrupt is level triggerd, more than one interrupt may
> > fire in error cases and QUP will generate these interrupts after
> > completion of current interrupt. Thus we reset the core immediately
> > in the ISR to ward off the next interrupt.
> 
> I wonder if that was just an expedient solution.  And it seems like it could be
> a little racy as a poll is not being done to make sure the QUP state machine
> transitions to reset.  Is there any documentation/errata on this?  Or is this
> just from commit comments?
> 
> 
> Regards,
> Andy

Hi Andy,

Thanks for your comments. We have only added the patch for clearing
the error bits. This resetting of QUP is present in the base code
itself. Since this QUP is being used by all the QCOM chips that's why
we have not changed the existing QUP reset logic. We will look
into reset polling logic separately and will post the patch for the
same.

We got the input for QUP RESET by referring our working internal
drivers and we also faced the BAM hang issue in base upstream
driver, if we don't do this RESET. If we schedule any transfer
with DMA mode then the DMA Engine (BAM) will never get any interrupt
for these errors, since the QUP interrupt handles the error cases.
The BAM will generate the interrupt only when it will receive the
requested amount of data. This reset will clear the QUP FIFO and
we will get the BAM transfer completion interrupt by the existing
logic present in the base bam transfer function.

-- 
Abhishek Sahu


From dinguyen at opensource.altera.com  Thu May 12 12:25:23 2016
From: dinguyen at opensource.altera.com (dinguyen at opensource.altera.com)
Date: Thu, 12 May 2016 14:25:23 -0500
Subject: [PATCH] ARM: dts: socfpga: fix definitions of serial console for
 Arria10
Message-ID: <1463081123-3181-1-git-send-email-dinguyen@opensource.altera.com>

From: Matthew Gerlach <mgerlach at opensource.altera.com>

The notion of which uart instance is serial0 or serial1
is board specific rather than generic to the chip. This
patch removes the serial aliases from generic chip dtsi
and adds an appropriate alias to the board specific dtsi.
By making the alias for serial0 point to uart1 for the arria10_socdk,
the linux boot command line supports specifying console=ttyS0,115200
for backwards compatibility, and it supports not specifying
the console at all.

Signed-off-by: Matthew Gerlach <mgerlach at opensource.altera.com>
Signed-off-by: Dinh Nguyen <dinguyen at opensource.altera.com>
---
 arch/arm/boot/dts/socfpga_arria10.dtsi       | 5 -----
 arch/arm/boot/dts/socfpga_arria10_socdk.dtsi | 6 +++++-
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi
index 1c5e139..48658f9 100644
--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
+++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
@@ -22,11 +22,6 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
-	aliases {
-		serial0 = &uart0;
-		serial1 = &uart1;
-	};
-
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi b/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
index 567df98..b1a4293 100644
--- a/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
+++ b/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
@@ -20,9 +20,13 @@
 	model = "Altera SOCFPGA Arria 10";
 	compatible = "altr,socfpga-arria10", "altr,socfpga";
 
+	aliases {
+		serial0 = &uart1;
+	};
+
 	chosen {
 		bootargs = "earlyprintk";
-		stdout-path = "serial1:115200n8";
+		stdout-path = "serial0:115200n8";
 	};
 
 	memory {
-- 
2.6.2



From christoffer.dall at linaro.org  Thu May 12 12:33:47 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 21:33:47 +0200
Subject: [PATCH v3 53/55] KVM: arm/arm64: vgic-new: Wire up irqfd injection
In-Reply-To: <1462531568-9799-54-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-54-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512193347.GT27623@cbox>

On Fri, May 06, 2016 at 11:46:06AM +0100, Andre Przywara wrote:
> Connect to the new VGIC to the irqfd framework, so that we can
> inject IRQs.
> GSI routing and MSI routing is not yet implemented.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-irqfd.c | 52 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-irqfd.c
> 
> diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
> new file mode 100644
> index 0000000..c675513
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-irqfd.c
> @@ -0,0 +1,52 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * 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/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <trace/events/kvm.h>
> +
> +int kvm_irq_map_gsi(struct kvm *kvm,
> +		    struct kvm_kernel_irq_routing_entry *entries,
> +		    int gsi)
> +{
> +	return 0;
> +}
> +
> +int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned int irqchip,
> +			 unsigned int pin)
> +{
> +	return pin;
> +}
> +
> +int kvm_set_irq(struct kvm *kvm, int irq_source_id,
> +		u32 irq, int level, bool line_status)
> +{
> +	unsigned int spi = irq + VGIC_NR_PRIVATE_IRQS;
> +
> +	trace_kvm_set_irq(irq, level, irq_source_id);
> +
> +	BUG_ON(!vgic_initialized(kvm));
> +
> +	return kvm_vgic_inject_irq(kvm, 0, spi, level);
> +}
> +
> +/* MSI not implemented yet */
> +int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
> +		struct kvm *kvm, int irq_source_id,
> +		int level, bool line_status)
> +{
> +	return 0;
> +}
> -- 
> 2.7.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Thu May 12 12:36:28 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 21:36:28 +0200
Subject: [PATCH v3 54/55] KVM: arm/arm64: vgic-new: implement mapped IRQ
 handling
In-Reply-To: <1462531568-9799-55-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-55-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512193628.GU27623@cbox>

On Fri, May 06, 2016 at 11:46:07AM +0100, Andre Przywara wrote:
> We now store the mapped hardware IRQ number in our struct, so we
> don't need the irq_phys_map for the new VGIC.
> Implement the hardware IRQ mapping on top of the reworked arch
> timer interface.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - adapt to new arch_timer mapped IRQ interface
> - implement inject_mapped_irq() as a macro (since it is identical to
>   the "un-mapped" IRQ implementation)
> 
> Changelog v1 .. v2:
> - replace inject_mapped_irq() macro with a separate implementation,
>   which only allows mapped IRQs to be injected via this interface
> 
>  include/kvm/vgic/vgic.h  |  5 +++++
>  virt/kvm/arm/vgic/vgic.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 55 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 07c3011..64aca0c 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -213,6 +213,11 @@ int kvm_vgic_hyp_init(void);
>  
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  			bool level);
> +int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
> +			       bool level);
> +int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq);
> +int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
> +bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
>  
>  int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
>  
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 068389a..3f854c5 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -310,6 +310,44 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
>  }
>  
> +int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
> +			       bool level)
> +{
> +	return vgic_update_irq_pending(kvm, cpuid, intid, level, true);
> +}
> +
> +int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq)
> +{
> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
> +
> +	BUG_ON(!irq);
> +
> +	spin_lock(&irq->irq_lock);
> +
> +	irq->hw = true;
> +	irq->hwintid = phys_irq;
> +
> +	spin_unlock(&irq->irq_lock);
> +
> +	return 0;
> +}
> +
> +int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
> +{
> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
> +
> +	BUG_ON(!irq);
> +
> +	spin_lock(&irq->irq_lock);
> +
> +	irq->hw = false;
> +	irq->hwintid = 0;
> +
> +	spin_unlock(&irq->irq_lock);
> +
> +	return 0;
> +}
> +
>  /**
>   * vgic_prune_ap_list - Remove non-relevant interrupts from the list
>   *
> @@ -563,3 +601,15 @@ void vgic_kick_vcpus(struct kvm *kvm)
>  			kvm_vcpu_kick(vcpu);
>  	}
>  }
> +
> +bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
> +{
> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
> +	bool map_is_active;
> +
> +	spin_lock(&irq->irq_lock);
> +	map_is_active = irq->hw && irq->active;
> +	spin_unlock(&irq->irq_lock);
> +
> +	return map_is_active;
> +}
> -- 
> 2.7.3
> 

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Thu May 12 12:43:03 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 12 May 2016 21:43:03 +0200
Subject: [PATCH v2] KVM: arm/arm64: vgic-new: fix overlap check for
 device addresses
In-Reply-To: <1462900726-14666-1-git-send-email-andre.przywara@arm.com>
References: <5731DF3C.6020201@arm.com>
 <1462900726-14666-1-git-send-email-andre.przywara@arm.com>
Message-ID: <20160512194303.GV27623@cbox>

On Tue, May 10, 2016 at 06:18:46PM +0100, Andre Przywara wrote:
> When userland sets the base addresses for the GIC register frames,
> the kernel tries to make sure that the regions for the distributor and
> the one for the CPU interface or the redistributors do not overlap.
> Currently this check only works properly for GICv2.
> For a GICv3 we need the number of VCPUs to compute the size of the
> redistributor region, which we only know for sure at init time.
> So move the overlap check from kvm_vgic_addr() to the model specific
> map_resources() implementation.
> This also allows us to simplify the existing checking code a bit.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Hi,
> 
> so another rework, now hopefully really covering GICv3 properly.
> For consistency I also moved the GICv2 check to init time. This is
> a slightly different behaviour, but shouldn't make a difference, as
> the init call can fail as well - for instance if no addresses have been
> set up at all.
> 
> Cheers,
> Andre.
> 
>  virt/kvm/arm/vgic/vgic-kvm-device.c | 50 ++++++++-----------------------------
>  virt/kvm/arm/vgic/vgic-v2.c         | 22 ++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c         | 27 ++++++++++++++++++++
>  3 files changed, 60 insertions(+), 39 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index 2122ff2..9e736a7 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -19,43 +19,19 @@
>  #include <asm/kvm_mmu.h>
>  #include "vgic.h"
>  
> -/* common helpers */
> -
> -static int vgic_ioaddr_overlap(struct kvm *kvm)
> -{
> -	phys_addr_t dist = kvm->arch.vgic.vgic_dist_base;
> -	phys_addr_t cpu = kvm->arch.vgic.vgic_cpu_base;
> -
> -	if (IS_VGIC_ADDR_UNDEF(dist) || IS_VGIC_ADDR_UNDEF(cpu))
> -		return 0;
> -	if ((dist <= cpu && dist + KVM_VGIC_V2_DIST_SIZE > cpu) ||
> -	    (cpu <= dist && cpu + KVM_VGIC_V2_CPU_SIZE > dist))
> -		return -EBUSY;
> -	return 0;
> -}
> -
> -static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
> -			      phys_addr_t addr, phys_addr_t size)
> +static int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
> +			     phys_addr_t addr, phys_addr_t alignment)
>  {
> -	int ret;
> -
>  	if (addr & ~KVM_PHYS_MASK)
>  		return -E2BIG;
>  
> -	if (addr & (SZ_4K - 1))
> +	if (!IS_ALIGNED(addr, alignment))
>  		return -EINVAL;
>  
>  	if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
>  		return -EEXIST;
> -	if (addr + size < addr)
> -		return -EINVAL;
> -
> -	*ioaddr = addr;
> -	ret = vgic_ioaddr_overlap(kvm);
> -	if (ret)
> -		*ioaddr = VGIC_ADDR_UNDEF;
>  
> -	return ret;
> +	return 0;
>  }
>  
>  /**
> @@ -70,40 +46,38 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
>   * interface in the VM physical address space.  These addresses are properties
>   * of the emulated core/SoC and therefore user space initially knows this
>   * information.
> + * Check them for sanity (alignment, double assignment). We can't check for
> + * overlapping regions in case of a virtual GICv3 here, since we don't know
> + * the number of VCPUs yet, so we defer this check to map_resources().
>   */
>  int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
>  {
>  	int r = 0;
>  	struct vgic_dist *vgic = &kvm->arch.vgic;
>  	int type_needed;
> -	phys_addr_t *addr_ptr, block_size;
> -	phys_addr_t alignment;
> +	phys_addr_t *addr_ptr, alignment;
>  
>  	mutex_lock(&kvm->lock);
>  	switch (type) {
>  	case KVM_VGIC_V2_ADDR_TYPE_DIST:
>  		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
>  		addr_ptr = &vgic->vgic_dist_base;
> -		block_size = KVM_VGIC_V2_DIST_SIZE;
>  		alignment = SZ_4K;
>  		break;
>  	case KVM_VGIC_V2_ADDR_TYPE_CPU:
>  		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
>  		addr_ptr = &vgic->vgic_cpu_base;
> -		block_size = KVM_VGIC_V2_CPU_SIZE;
>  		alignment = SZ_4K;
>  		break;
>  #ifdef CONFIG_KVM_ARM_VGIC_V3
>  	case KVM_VGIC_V3_ADDR_TYPE_DIST:
>  		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
>  		addr_ptr = &vgic->vgic_dist_base;
> -		block_size = KVM_VGIC_V3_DIST_SIZE;
>  		alignment = SZ_64K;
>  		break;
>  	case KVM_VGIC_V3_ADDR_TYPE_REDIST:
>  		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
>  		addr_ptr = &vgic->vgic_redist_base;
> -		block_size = KVM_VGIC_V3_REDIST_SIZE;
>  		alignment = SZ_64K;
>  		break;
>  #endif
> @@ -118,11 +92,9 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
>  	}
>  
>  	if (write) {
> -		if (!IS_ALIGNED(*addr, alignment))
> -			r = -EINVAL;
> -		else
> -			r = vgic_ioaddr_assign(kvm, addr_ptr,
> -					       *addr, block_size);
> +		r = vgic_check_ioaddr(kvm, addr_ptr, *addr, alignment);
> +		if (!r)
> +			*addr_ptr = *addr;
>  	} else {
>  		*addr = *addr_ptr;
>  	}
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> index 4493593..fe6e3bd 100644
> --- a/virt/kvm/arm/vgic/vgic-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -225,6 +225,22 @@ void vgic_v2_enable(struct kvm_vcpu *vcpu)
>  	vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr = GICH_HCR_EN;
>  }
>  
> +/* check for overlapping regions and for regions crossing the end of memory */
> +static bool vgic_check_addresses(gpa_t dist_base, gpa_t cpu_base)
> +{
> +	if (dist_base + KVM_VGIC_V2_DIST_SIZE < dist_base)
> +		return false;
> +	if (cpu_base + KVM_VGIC_V2_CPU_SIZE < cpu_base)
> +		return false;
> +
> +	if (dist_base + KVM_VGIC_V2_DIST_SIZE <= cpu_base)
> +		return true;
> +	if (cpu_base + KVM_VGIC_V2_CPU_SIZE <= dist_base)
> +		return true;
> +
> +	return false;
> +}
> +
>  int vgic_v2_map_resources(struct kvm *kvm)
>  {
>  	struct vgic_dist *dist = &kvm->arch.vgic;
> @@ -240,6 +256,12 @@ int vgic_v2_map_resources(struct kvm *kvm)
>  		goto out;
>  	}
>  
> +	if (!vgic_check_addresses(dist->vgic_dist_base, dist->vgic_cpu_base)) {
> +		kvm_err("VGIC CPU and dist frames overlap\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
>  	/*
>  	 * Initialize the vgic if this hasn't already been done on demand by
>  	 * accessing the vgic state from userspace.
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 6d7422f..fa444a7 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -221,6 +221,27 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>  	vgic_v3->vgic_hcr = ICH_HCR_EN;
>  }
>  
> +/* check for overlapping regions and for regions crossing the end of memory */
> +static bool vgic_check_addresses(struct kvm *kvm)
> +{
> +	struct vgic_dist *d = &kvm->arch.vgic;
> +	gpa_t redist_size = KVM_VGIC_V3_REDIST_SIZE;
> +
> +	redist_size = KVM_VGIC_V3_REDIST_SIZE * atomic_read(&kvm->online_vcpus);

this looks horrible IMHO, you can fit the full calculations on exactly
80 chars, which must be a sign of what was supposed to happen ;)

> +
> +	if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base)
> +		return false;
> +	if (d->vgic_redist_base + redist_size < d->vgic_redist_base)
> +		return false;
> +
> +	if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE <= d->vgic_redist_base)
> +		return true;
> +	if (d->vgic_redist_base + redist_size <= d->vgic_dist_base)
> +		return true;
> +
> +	return false;
> +}
> +
>  int vgic_v3_map_resources(struct kvm *kvm)
>  {
>  	int ret = 0;
> @@ -236,6 +257,12 @@ int vgic_v3_map_resources(struct kvm *kvm)
>  		goto out;
>  	}
>  
> +	if (!vgic_check_addresses(kvm)) {
> +		kvm_err("VGIC redist and dist frames overlap\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
>  	/*
>  	 * For a VGICv3 we require the userland to explicitly initialize
>  	 * the VGIC before we need to use it.
> -- 
> 2.7.3
> 

I would have named the check_addresses functions with the specific vgic
version, but anyhow:

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From kernel at martin.sperl.org  Thu May 12 12:46:17 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Thu, 12 May 2016 21:46:17 +0200
Subject: [PATCH 0/4] add minimal bcm2835-sdram driver
In-Reply-To: <87twi39m80.fsf@eliezer.anholt.net>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
 <87twi39m80.fsf@eliezer.anholt.net>
Message-ID: <BF982CDB-28CF-4AB3-BC4B-E1D88F34E72A@martin.sperl.org>



> On 12.05.2016, at 20:15, Eric Anholt <eric at anholt.net> wrote:
> 
> kernel at martin.sperl.org writes:
> 
>> From: Martin Sperl <kernel at martin.sperl.org>
>> 
>> As the sdram clock is a critical clock to the system
>> the minimal bcm2835-sdram driver claims (and enables)
>> this clock and also exposes the corresponding sdram
>> registers via debugfs.
> 
> I don't think this is a good solution to the problem you are trying to
> work around.  You're relying on the fact that this driver gets
> successfully probed before a driver that would -EPROBE_DEFER on a
> sibling clock, which is not a guarantee.
Ah - that is probably the reason why hand_off has not gone in...

> 
> Let's please continue the debugging of clock management on linux-clk.

I am just trying to find a solution that works...

Still I think that having a driver that claims the clock and register range
is good to have - at least this way we can have a peek at what
the firmware does set up.


From andy.gross at linaro.org  Thu May 12 13:05:39 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 15:05:39 -0500
Subject: [PATCH 1/2] i2c: qup: Cleared the error bits in ISR
In-Reply-To: <20160512193229.GA10499@chewinlnx07.qualcomm.com>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
 <1462797871-8595-2-git-send-email-absahu@codeaurora.org>
 <000701d1ab9d$df9b3100$9ed19300$@codeaurora.org>
 <934365f2bd30f242d8548e2a27483679@codeaurora.org>
 <20160512051347.GE8453@hector.attlocal.net>
 <20160512061843.GA6187@chewinlnx07.qualcomm.com>
 <20160512175830.GA32019@hector>
 <20160512193229.GA10499@chewinlnx07.qualcomm.com>
Message-ID: <CAPBZ5QdD6knEzQVW-BAgRSMcd=Gqv9_1Xt2LNc+qWgtre_2ZXQ@mail.gmail.com>

On 12 May 2016 at 14:32, Abhishek Sahu <absahu at codeaurora.org> wrote:
> On Thu, May 12, 2016 at 12:58:30PM -0500, Andy Gross wrote:
>> On Thu, May 12, 2016 at 11:48:43AM +0530, Abhishek Sahu wrote:
>> > On Thu, May 12, 2016 at 12:13:47AM -0500, Andy Gross wrote:
>> > > On Wed, May 11, 2016 at 11:04:17PM +0530, Abhishek Sahu wrote:
>> > >
>> > > <snip>
>> > >
>> > > > >       In qup_i2c_xfer and qup_i2c_xfer_v2 state is set to RESET at the
>> > > > >end, when
>> > > > >       there is no error. So would it be fine if we do it there
>> > > > >unconditionally ?
>> > > > >
>> > > > >Regards,
>> > > > > Sricharan
>> > > >
>> > > > RESET the QUP state wouldn't create any issue in the case of multiple calls.
>> > > > The existing code also RESET the QUP state for bus_err but it is not
>> > > > clearing
>> > > > status bits.
>> > >
>> > > It'd be better to not reset the QUP inside the ISR at all.  I think the better
>> > > solution is making the reset occur in the xfer function.  So just clear the bits
>> > > like you should in the isr, and defer reset till later.
>> >
>> > This is a HW workaround for QUP where we need to RESET the core in
>> > ISR. When interrupt is level triggerd, more than one interrupt may
>> > fire in error cases and QUP will generate these interrupts after
>> > completion of current interrupt. Thus we reset the core immediately
>> > in the ISR to ward off the next interrupt.
>>
>> I wonder if that was just an expedient solution.  And it seems like it could be
>> a little racy as a poll is not being done to make sure the QUP state machine
>> transitions to reset.  Is there any documentation/errata on this?  Or is this
>> just from commit comments?
>>
>>
>> Regards,
>> Andy
>
> Hi Andy,
>
> Thanks for your comments. We have only added the patch for clearing
> the error bits. This resetting of QUP is present in the base code
> itself. Since this QUP is being used by all the QCOM chips that's why
> we have not changed the existing QUP reset logic. We will look
> into reset polling logic separately and will post the patch for the
> same.

Yeah, it is present in the current code.  I hadn't seen any errata on
this issue, so that is why I was curious.  In many cases, the code in
the mainline driver was carried forward from the downstream CAF
driver.  I know the two don't look that similar in some regards, but
in most cases the actions taken are the same, even if it is not
obvious.

> We got the input for QUP RESET by referring our working internal
> drivers and we also faced the BAM hang issue in base upstream
> driver, if we don't do this RESET. If we schedule any transfer
> with DMA mode then the DMA Engine (BAM) will never get any interrupt
> for these errors, since the QUP interrupt handles the error cases.
> The BAM will generate the interrupt only when it will receive the
> requested amount of data. This reset will clear the QUP FIFO and
> we will get the BAM transfer completion interrupt by the existing
> logic present in the base bam transfer function.

Right.  If the QUP has an issue and isn't processing data, and you
have a BAM transaction pending for this, you have to not only ack the
qup error, but also terminate the BAM transaction.

What test case are you using to test out the error path?  Something
other than NACKs?

Regards,

Andy


From sergei.shtylyov at cogentembedded.com  Thu May 12 13:21:42 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 12 May 2016 23:21:42 +0300
Subject: [PATCH 2/2] musb: sunxi: Set state to A_WAIT_VRISE when enabling
 VBus
In-Reply-To: <1463077869-13224-2-git-send-email-hdegoede@redhat.com>
References: <1463077869-13224-1-git-send-email-hdegoede@redhat.com>
 <1463077869-13224-2-git-send-email-hdegoede@redhat.com>
Message-ID: <b60f2279-77e8-c7c3-c857-a2dfef20d3d6@cogentembedded.com>

Hello.

On 05/12/2016 09:31 PM, Hans de Goede wrote:

> When the board is powering attached usb devices via the otg port
> sometimes / on some devices it takes slightly too long for the VBus

    I think it's either VBUS or Vbus, not this strange spelling.

> detection code in phy-sun4i-usb.c to signal that VBus is high after
> enabling VBus and the musb hardware signals a MUSB_INTR_VBUSERROR
> interrupt.
>
> This commit sets the otg state to A_WAIT_VRISE upon enabling Vbus
> making musb_stage0_irq() ignore the first VBUSERR_RETRY_COUNT
> VBUSERROR interrupts, fixing connection issues in these cases.
>
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> ---
>  drivers/usb/musb/sunxi.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
> index 2c33d9b..2ee48fb 100644
> --- a/drivers/usb/musb/sunxi.c
> +++ b/drivers/usb/musb/sunxi.c
> @@ -112,7 +112,7 @@ static void sunxi_musb_work(struct work_struct *work)
>  		if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
>  			set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
>  			musb->xceiv->otg->default_a = 1;
> -			musb->xceiv->otg->state = OTG_STATE_A_IDLE;
> +			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
>  			MUSB_HST_MODE(musb);
>  			devctl |= MUSB_DEVCTL_SESSION;
>  		} else {
> @@ -145,9 +145,10 @@ static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
>  {
>  	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
>
> -	if (is_on)
> +	if (is_on) {
>  		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
> -	else
> +		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
> +	} else
>  		clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);

   CodingStyle, all *if* branches should use {} if one uses {}.

[...]

MBR, Sergei



From tony at atomide.com  Thu May 12 13:26:57 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 12 May 2016 13:26:57 -0700
Subject: [PATCH] ARM: dts: omap5-igep0050: Correct hdmi regulator
In-Reply-To: <5734D733.9060400@ti.com>
References: <20160504172634.GS5995@atomide.com> <572A38FD.9050801@ti.com>
 <20160505184609.GB5995@atomide.com>
 <2822D1C2B9B19F4A8261F756A13373F801BEF7B4@DFLE11.ent.ti.com>
 <CAPjucKb+4vd8Ar3MATCuTx+9R36PeB0hbvwDaAD1KTZFCiVJEA@mail.gmail.com>
 <2822D1C2B9B19F4A8261F756A13373F801BF86D2@DFLE11.ent.ti.com>
 <2822D1C2B9B19F4A8261F756A13373F801BF8703@DFLE11.ent.ti.com>
 <CAPjucKb2PLSZcD3YZ9xQk1F62ugFaGAkBBqMp5GmoWFd0H8Vfg@mail.gmail.com>
 <20160512165755.GR5995@atomide.com> <5734D733.9060400@ti.com>
Message-ID: <20160512202656.GU5995@atomide.com>

* Nishanth Menon <nm at ti.com> [160512 12:21]:
> On 05/12/2016 11:57 AM, Tony Lindgren wrote:
> > + * LDO7 is used for HDMI: VDDA_DSIPORTA - ball AA33, VDDA_DSIPORTC - ball AE33
> > + * VDDA_HDMI - ball AN25. LDO4 is: VPP1 - ball AD9.
> 
> We should set ldo4_reg as 2v as well (default in omap5-board-common is
> 1.8v). VPP1 should be 2v to prevent efuse from being messed up.

Oh OK, here's the patch updated for ldo4.

Tony

8< --------------------
From: Tony Lindgren <tony at atomide.com>
Date: Thu, 12 May 2016 09:51:51 -0700
Subject: [PATCH] ARM: dts: Fix ldo7 source for HDMI on igepv5

Fix ldo7 source for HDMI on igepv5.

Suggested-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
Signed-off-by: Tony Lindgren <tony at atomide.com>

--- a/arch/arm/boot/dts/omap5-igep0050.dts
+++ b/arch/arm/boot/dts/omap5-igep0050.dts
@@ -35,6 +35,22 @@
 	};
 };
 
+/* LDO4 is VPP1 - ball AD9 */
+&ldo4_reg {
+	regulator-min-microvolt = <2000000>;
+	regulator-max-microvolt = <2000000>;
+};
+
+/*
+ * LDO7 is used for HDMI: VDDA_DSIPORTA - ball AA33, VDDA_DSIPORTC - ball AE33,
+ * VDDA_HDMI - ball AN25
+ */
+&ldo7_reg {
+	status = "okay";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+};
+
 &omap5_pmx_core {
 	i2c4_pins: pinmux_i2c4_pins {
 		pinctrl-single,pins = <


From absahu at codeaurora.org  Thu May 12 13:27:55 2016
From: absahu at codeaurora.org (Abhishek Sahu)
Date: Fri, 13 May 2016 01:57:55 +0530
Subject: [PATCH 1/2] i2c: qup: Cleared the error bits in ISR
In-Reply-To: <CAPBZ5QdD6knEzQVW-BAgRSMcd=Gqv9_1Xt2LNc+qWgtre_2ZXQ@mail.gmail.com>
References: <1462797871-8595-1-git-send-email-absahu@codeaurora.org>
 <1462797871-8595-2-git-send-email-absahu@codeaurora.org>
 <000701d1ab9d$df9b3100$9ed19300$@codeaurora.org>
 <934365f2bd30f242d8548e2a27483679@codeaurora.org>
 <20160512051347.GE8453@hector.attlocal.net>
 <20160512061843.GA6187@chewinlnx07.qualcomm.com>
 <20160512175830.GA32019@hector>
 <20160512193229.GA10499@chewinlnx07.qualcomm.com>
 <CAPBZ5QdD6knEzQVW-BAgRSMcd=Gqv9_1Xt2LNc+qWgtre_2ZXQ@mail.gmail.com>
Message-ID: <20160512202755.GA3680@chewinlnx07.qualcomm.com>

On Thu, May 12, 2016 at 03:05:39PM -0500, Andy Gross wrote:
> On 12 May 2016 at 14:32, Abhishek Sahu <absahu at codeaurora.org> wrote:
> > On Thu, May 12, 2016 at 12:58:30PM -0500, Andy Gross wrote:
> >> On Thu, May 12, 2016 at 11:48:43AM +0530, Abhishek Sahu wrote:
> >> > On Thu, May 12, 2016 at 12:13:47AM -0500, Andy Gross wrote:
> >> > > On Wed, May 11, 2016 at 11:04:17PM +0530, Abhishek Sahu wrote:
> >> > >
> >> > > <snip>
> >> > >
> >> > > > >       In qup_i2c_xfer and qup_i2c_xfer_v2 state is set to RESET at the
> >> > > > >end, when
> >> > > > >       there is no error. So would it be fine if we do it there
> >> > > > >unconditionally ?
> >> > > > >
> >> > > > >Regards,
> >> > > > > Sricharan
> >> > > >
> >> > > > RESET the QUP state wouldn't create any issue in the case of multiple calls.
> >> > > > The existing code also RESET the QUP state for bus_err but it is not
> >> > > > clearing
> >> > > > status bits.
> >> > >
> >> > > It'd be better to not reset the QUP inside the ISR at all.  I think the better
> >> > > solution is making the reset occur in the xfer function.  So just clear the bits
> >> > > like you should in the isr, and defer reset till later.
> >> >
> >> > This is a HW workaround for QUP where we need to RESET the core in
> >> > ISR. When interrupt is level triggerd, more than one interrupt may
> >> > fire in error cases and QUP will generate these interrupts after
> >> > completion of current interrupt. Thus we reset the core immediately
> >> > in the ISR to ward off the next interrupt.
> >>
> >> I wonder if that was just an expedient solution.  And it seems like it could be
> >> a little racy as a poll is not being done to make sure the QUP state machine
> >> transitions to reset.  Is there any documentation/errata on this?  Or is this
> >> just from commit comments?
> >>
> >>
> >> Regards,
> >> Andy
> >
> > Hi Andy,
> >
> > Thanks for your comments. We have only added the patch for clearing
> > the error bits. This resetting of QUP is present in the base code
> > itself. Since this QUP is being used by all the QCOM chips that's why
> > we have not changed the existing QUP reset logic. We will look
> > into reset polling logic separately and will post the patch for the
> > same.
> 
> Yeah, it is present in the current code.  I hadn't seen any errata on
> this issue, so that is why I was curious.  In many cases, the code in
> the mainline driver was carried forward from the downstream CAF
> driver.  I know the two don't look that similar in some regards, but
> in most cases the actions taken are the same, even if it is not
> obvious.
> 
> > We got the input for QUP RESET by referring our working internal
> > drivers and we also faced the BAM hang issue in base upstream
> > driver, if we don't do this RESET. If we schedule any transfer
> > with DMA mode then the DMA Engine (BAM) will never get any interrupt
> > for these errors, since the QUP interrupt handles the error cases.
> > The BAM will generate the interrupt only when it will receive the
> > requested amount of data. This reset will clear the QUP FIFO and
> > we will get the BAM transfer completion interrupt by the existing
> > logic present in the base bam transfer function.
> 
> Right.  If the QUP has an issue and isn't processing data, and you
> have a BAM transaction pending for this, you have to not only ack the
> qup error, but also terminate the BAM transaction.
> 
> What test case are you using to test out the error path?  Something
> other than NACKs?
> 
> Regards,
> 
> Andy

Hi Andy,

We run the command i2cdetect for address 0x3 to 0x77. The QUP generates
write error for address 0x3 to 0x7 apart from other bus errors since
these are reserved addresses. I was getting the crash in non DMA mode
and BAM hang in DMA mode before putting the fix.

Also we have connected the I2C TPM and run the following script
overnight for both DMA and Non DMA mode.  The script checks for
all transfer length and we are generating multiple NACK and
Non NACK error before each valid transfer.

a=1

while [ $a -lt 4096 ]
do
   echo $a
   i2cdetect -y -a -r 0 0x03 0x77
   tpm-manager get_random $a
   i2cdetect -y -a -r 1 0x03 0x77
   a=`expr $a + 1`
done

--
Abhishek Sahu


From rafael at kernel.org  Thu May 12 13:28:22 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Thu, 12 May 2016 22:28:22 +0200
Subject: [PATCH] PM / Runtime: Defer resuming of the device in
 pm_runtime_force_resume()
In-Reply-To: <4661739.p5SU9QcIps@avalon>
References: <1461234842-22820-1-git-send-email-ulf.hansson@linaro.org>
 <5465506.Z3sjI0lQh6@avalon>
 <CAPDyKFpOxabizwQqhtKb-h0vGpTRtrCa0nPxAKMY22rnjLCouw@mail.gmail.com>
 <4661739.p5SU9QcIps@avalon>
Message-ID: <CAJZ5v0jTAM74asCM5gG5wBWn+gvSQ21_W6dY9WQD+cMybUnEEg@mail.gmail.com>

On Thu, May 12, 2016 at 9:01 PM, Laurent Pinchart
<laurent.pinchart at ideasonboard.com> wrote:
> Hello,
>
> On Wednesday 27 Apr 2016 16:23:49 Ulf Hansson wrote:
>> [...]
>>
>> >> Following you reasoning, I agree!
>> >>
>> >> Let's put this patch on hold for a little while. I am already working
>> >> on changing genpd, so it shouldn't take long before I can post some
>> >> additional genpd patches improving the behaviour.
>> >
>> > I'd like to see something merged for v4.7 if possible. I agree that my
>> > patch isn't a long term solution (we want to avoid adding additional
>> > fields to the device power structure), but it has the benefit of being
>> > available now and fixing the problem I ran into with drivers that would
>> > be broken on v4.7 without a fix. Do you think you could get a better fix
>> > ready in time for v4.7 ? If so I'm fine with dropping this patch, but
>> > otherwise I'd prefer to get it merged and reverted as part of your better
>> > implementation for v4.8.
>>
>> My impression was that devices becomes unnecessary resumed when they
>> don't need to. They won't stay resumed as the PM core invokes
>> pm_runtime_put() in the system PM complete phase.
>>
>> So, in the end I think we are trying to optimize a behaviour here, but
>> not fix something that is "broken", correct?
>>
>> Anyway, I have no objections to your proposed solution, so I leave it
>> to Rafael and Kevin to decide what to do.
>
> Kevin, Rafael, any comment ? I need to fix PM support in a driver that is
> currently broken partly due to this issue. Which of "PM / Runtime: Only force-
> resume device if it has been force-suspended" and this patch should we merge,
> if any ?

My and Kevin's assumption was that Ulf would provide a better fix
shortly, but I'm not sure how realistic that is.

Ulf?


From tony at atomide.com  Thu May 12 13:35:06 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 12 May 2016 13:35:06 -0700
Subject: [PATCH RESEND 0/4] arm: dts: am57xx: Correct the thermal
 thresholds
In-Reply-To: <57316262.80003@ti.com>
References: <1461837949-11116-1-git-send-email-j-keerthy@ti.com>
 <57316262.80003@ti.com>
Message-ID: <20160512203505.GV5995@atomide.com>

Hi,

* Keerthy <a0393675 at ti.com> [160509 21:25]:
> Tony,
> 
> On Thursday 28 April 2016 03:35 PM, Keerthy wrote:
> >Noticed that earlier post had a wrong list name hence resending the
> >series.
> >
> >Currently all the am57xx versions are wrongly re-using the dra7  thermal
> >threholds. Introduing the correct thermal thresholds based on industrial
> >or commercial grade silicon present on the individual boards.
> >
> >Tested on AM57XX-BEAGLE-X15 (Commercial) and AM572X-IDK(Industrial)
> >for the trip_point node sysfs temperatures.
> >
> 
> A Gentle ping on this series.

I already have these in Linux next for v4.7 merge window:

5b6042237dc8 ("ARM: dts: am57xx-idk: Include Industrial grade  thermal thresholds")
266e62f97539 ("ARM: dts: am57xx-beagle-x15: Include the commercial grade thresholds")
cf9b7d5e9cfd ("ARM: dts: am57xx: Introduce industrial grade thermal thresholds")
286db0a516e0 ("ARM: dts: am57xx: Introduce commercial grade thermal thresholds")

Care to check if those are OK? If fixes are needed, please post an
incremental patch against current Linux next.

Regards,

Tony


From sergei.shtylyov at cogentembedded.com  Thu May 12 13:38:08 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 12 May 2016 23:38:08 +0300
Subject: [PATCH v3 0/6] Add R8A7794/SILK sound DT support
Message-ID: <2378837.cigT3tNQPe@wasted.cogentembedded.com>

Hello.

   Here's the set of 6 patches against Simon Horman's 'renesas.git' repo,
'renesas-devel-20160509-v4.6-rc7' tag. I'm adding the sound device tree support
for the R8A7794 SoC based SILK board.

[1/6] ARM: dts: r8a7794: add audio clocks
[2/6] ARM: dts: r8a7794: add MSTP5 clocks
[3/6] ARM: dts: r8a7794: add MSTP10 clocks
[4/6] ARM: dts: r8a7794: add Audio-DMAC support
[5/6] ARM: dts: r8a7794: add sound support
[6/6] ARM: dts: silk: add sound support

WBR, Sergei



From sergei.shtylyov at cogentembedded.com  Thu May 12 13:40:24 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 12 May 2016 23:40:24 +0300
Subject: [PATCH v3 1/6] ARM: dts: r8a7794: add audio clocks
In-Reply-To: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
Message-ID: <2753859.2OOnqVymyK@wasted.cogentembedded.com>

Describe  the external audio clocks (signals AUDIO_CLK[ABC]) required by
the sound driver.  Boards that provide audio clocks need to  override the
clock frequencies.

This patch is based on the commit 0d3dbde84a45 ("ARM: shmobile: r8a7791:
add  audio clock on DTSI").

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
Changes in version 3:
- removed now redundant "clock-output-names" properties;
- reformatted the changelog;
- refreshed the patch.

 arch/arm/boot/dts/r8a7794.dtsi |   21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

Index: renesas/arch/arm/boot/dts/r8a7794.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7794.dtsi
+++ renesas/arch/arm/boot/dts/r8a7794.dtsi
@@ -920,6 +920,27 @@
 			clock-frequency = <0>;
 		};
 
+		/*
+		 * The external audio clocks are configured  as 0 Hz fixed
+		 * frequency clocks by default.  Boards that provide audio
+		 * clocks should override them.
+		 */
+		audio_clka: audio_clka {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+		audio_clkb: audio_clkb {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+		audio_clkc: audio_clkc {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+
 		/* Special CPG clocks */
 		cpg_clocks: cpg_clocks at e6150000 {
 			compatible = "renesas,r8a7794-cpg-clocks",



From ddaney at caviumnetworks.com  Thu May 12 13:40:24 2016
From: ddaney at caviumnetworks.com (David Daney)
Date: Thu, 12 May 2016 13:40:24 -0700
Subject: [PATCH v6 13/14] arm64, acpi, numa: NUMA support based on SRAT
 and SLIT
In-Reply-To: <20160512162449.GK11226@e104818-lin.cambridge.arm.com>
References: <1461780436-27182-1-git-send-email-ddaney.cavm@gmail.com>
 <1461780436-27182-14-git-send-email-ddaney.cavm@gmail.com>
 <20160511103929.GC3051@e104818-lin.cambridge.arm.com>
 <5733C8F5.6090206@caviumnetworks.com>
 <20160512094915.GD11226@e104818-lin.cambridge.arm.com>
 <5734A0CC.8010600@caviumnetworks.com>
 <20160512162449.GK11226@e104818-lin.cambridge.arm.com>
Message-ID: <5734EA38.2040206@caviumnetworks.com>

On 05/12/2016 09:24 AM, Catalin Marinas wrote:
> On Thu, May 12, 2016 at 08:27:08AM -0700, David Daney wrote:
>> On 05/12/2016 02:49 AM, Catalin Marinas wrote:
>>> On Wed, May 11, 2016 at 05:06:13PM -0700, David Daney wrote:
>>>> On 05/11/2016 03:39 AM, Catalin Marinas wrote:
>> [...]
>>>>>
>>>>> I wonder whether you could replace the get_mpidr_in_madt() function with
>>>>> something like acpi_get_phys_id(). It looks like get_mpidr_in_madt()
>>>>> duplicates functionality already available elsewhere.
>>>>
>>>> I just tried that, and it doesn't work.
>>>>
>>>> The problem is that this code is being run very early in the boot, and
>>>> kmalloc cannot be used.  acpi_get_phys_id() and its ilk can only be used
>>>> once we have working kmalloc.  We need to extract the NUMA information early
>>>> like this precisely because it is needed to initializing the slab system
>>>>
>>>> Notice that we are using early_acpi_os_unmap_memory() et al. in
>>>> get_mpidr_in_madt() explicitly for this reason.
>>>>
>>>> In summary: I don't think we need another revision of this patch, it is like
>>>> this for a good reason.
>>>
>>> Slightly confusing, in another reply you said you are going to address
>>> my comment. So, is it doable?
>>
>> I don't think so.
>>
>> My previous reply, to the thread in 0/14, was prematurely made with the
>> incorrect assumption that it was a simple change.  Now, after really digging
>> in to the code, and attempting to do as you suggested, I have changed my
>> mind.
>
> Would the snippet below help with avoiding any kmalloc calls? At a quick
> look, it seems that it's only map_mat_entry() that ends up using
> kmalloc() calls. Alternatively, exporting map_madt_entry() may work as
> well.

I think making a non-static version of map_madt_entry() is the cleanest 
solution.  That works, so I will send a new version of the patch set 
that does that instead.

David.


>
> diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
> index 33a38d604630..77af0a7df914 100644
> --- a/drivers/acpi/processor_core.c
> +++ b/drivers/acpi/processor_core.c
> @@ -152,6 +152,9 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
>   	struct acpi_subtable_header *header;
>   	phys_cpuid_t phys_id = PHYS_CPUID_INVALID;
>
> +	if (!acpi_gbl_permanent_mmap)
> +		return phys_id;
> +
>   	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
>   		goto exit;
>
>



From tony at atomide.com  Thu May 12 13:44:58 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 12 May 2016 13:44:58 -0700
Subject: [PATCH] ARM: dts: dra7: Add gpmc dma channel
In-Reply-To: <1462383835-10839-1-git-send-email-fcooper@ti.com>
References: <1462383835-10839-1-git-send-email-fcooper@ti.com>
Message-ID: <20160512204458.GX5995@atomide.com>

* Franklin S Cooper Jr <fcooper at ti.com> [160504 10:45]:
> Add dma channel information to the gpmc.
> 
> Signed-off-by: Franklin S Cooper Jr <fcooper at ti.com>
> Signed-off-by: Sekhar Nori <nsekhar at ti.com>
> ---
> This patch is based on top of linux-next where EDMA support for DRA7 has
> been added.

Thanks applying into omap-for-v4.7/dt as a fix for the merge window.

Regards,

Tony


From sergei.shtylyov at cogentembedded.com  Thu May 12 13:45:08 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 12 May 2016 23:45:08 +0300
Subject: [PATCH v3 2/6] ARM: dts: r8a7794: add MSTP5 clocks
In-Reply-To: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
Message-ID: <1576909.nm8MtQ2Ln5@wasted.cogentembedded.com>

Add some MSTP5 clocks to the R8A7794 device tree.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
Changes in version 3:
- refreshed the patch.

Changes in version 2:
- added "the" article to the change log.

 arch/arm/boot/dts/r8a7794.dtsi            |    9 +++++++++
 include/dt-bindings/clock/r8a7794-clock.h |    1 +
 2 files changed, 10 insertions(+)

Index: renesas/arch/arm/boot/dts/r8a7794.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7794.dtsi
+++ renesas/arch/arm/boot/dts/r8a7794.dtsi
@@ -1172,6 +1172,15 @@
 			clock-indices = <R8A7794_CLK_IRQC>;
 			clock-output-names = "irqc";
 		};
+		mstp5_clks: mstp5_clks at e6150144 {
+			compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>;
+			clocks = <&hp_clk>, <&extal_clk>, <&p_clk>;
+			#clock-cells = <1>;
+			clock-indices = <R8A7794_CLK_AUDIO_DMAC0
+					 R8A7794_CLK_THERMAL R8A7794_CLK_PWM>;
+			clock-output-names = "audmac0", "thermal", "pwm";
+		};
 		mstp7_clks: mstp7_clks at e615014c {
 			compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>;
Index: renesas/include/dt-bindings/clock/r8a7794-clock.h
===================================================================
--- renesas.orig/include/dt-bindings/clock/r8a7794-clock.h
+++ renesas/include/dt-bindings/clock/r8a7794-clock.h
@@ -67,6 +67,7 @@
 #define R8A7794_CLK_IRQC		7
 
 /* MSTP5 */
+#define R8A7794_CLK_AUDIO_DMAC0		2
 #define R8A7794_CLK_THERMAL		22
 #define R8A7794_CLK_PWM			23
 



From tony at atomide.com  Thu May 12 13:46:02 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 12 May 2016 13:46:02 -0700
Subject: [PATCH V2] ARM: dts: am57xx-idk-common: Fix input supply names
In-Reply-To: <1462541877-20032-1-git-send-email-nm@ti.com>
References: <1462541877-20032-1-git-send-email-nm@ti.com>
Message-ID: <20160512204601.GY5995@atomide.com>

* Nishanth Menon <nm at ti.com> [160506 06:39]:
> Palmas Regulator is an exception and does not follow the standard
> "vin-supply" common definitions for all regulators, as a result of this,
> the input supplies are not reported to regulator framework, with the
> obvious result of not being appropriately mapped. Fix the same.
> 
> Signed-off-by: Nishanth Menon <nm at ti.com>
> ---
> Changes since V1:
> 	- fix up fat fingered deletion of regulator name of ldortc
> V1: https://patchwork.kernel.org/patch/9028201/

Applying into omap-for-v4.7/dt as a fix for the merge window.

Tony


From sergei.shtylyov at cogentembedded.com  Thu May 12 13:46:30 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 12 May 2016 23:46:30 +0300
Subject: [PATCH v3 3/6] ARM: dts: r8a7794: add MSTP10 clocks
In-Reply-To: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
Message-ID: <3321354.LNTkVAhXvF@wasted.cogentembedded.com>

Add MSTP10 clocks to the R8A7794 device tree.

This patch is based on the commit ee9141522dcf ("ARM: shmobile: r8a7791:
add MSTP10 support on DTSI").

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
Changes in version 3:
- refreshed the patch.

Changes in version 2:
- fixed the SoC model in the change log;
- added "the" article to the change log.

 arch/arm/boot/dts/r8a7794.dtsi            |   53 ++++++++++++++++++++++++++++++
 include/dt-bindings/clock/r8a7794-clock.h |   28 +++++++++++++++
 2 files changed, 81 insertions(+)

Index: renesas/arch/arm/boot/dts/r8a7794.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7794.dtsi
+++ renesas/arch/arm/boot/dts/r8a7794.dtsi
@@ -1235,6 +1235,59 @@
 				"gpio1", "gpio0", "rcan1", "rcan0", "qspi_mod",
 				"i2c5", "i2c4", "i2c3", "i2c2", "i2c1", "i2c0";
 		};
+		mstp10_clks: mstp10_clks at e6150998 {
+			compatible = "renesas,r8a7794-mstp-clocks",
+				     "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
+			clocks = <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+				 <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+				 <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>,
+				 <&mstp10_clks R8A7794_CLK_SCU_ALL>;
+			#clock-cells = <1>;
+			clock-indices = <R8A7794_CLK_SSI_ALL
+					 R8A7794_CLK_SSI9 R8A7794_CLK_SSI8
+					 R8A7794_CLK_SSI7 R8A7794_CLK_SSI6
+					 R8A7794_CLK_SSI5 R8A7794_CLK_SSI4
+					 R8A7794_CLK_SSI3 R8A7794_CLK_SSI2
+					 R8A7794_CLK_SSI1 R8A7794_CLK_SSI0
+					 R8A7794_CLK_SCU_ALL
+					 R8A7794_CLK_SCU_DVC1
+					 R8A7794_CLK_SCU_DVC0
+					 R8A7794_CLK_SCU_CTU1_MIX1
+					 R8A7794_CLK_SCU_CTU0_MIX0
+					 R8A7794_CLK_SCU_SRC9
+					 R8A7794_CLK_SCU_SRC8
+					 R8A7794_CLK_SCU_SRC7
+					 R8A7794_CLK_SCU_SRC6
+					 R8A7794_CLK_SCU_SRC5
+					 R8A7794_CLK_SCU_SRC4
+					 R8A7794_CLK_SCU_SRC3
+					 R8A7794_CLK_SCU_SRC2
+					 R8A7794_CLK_SCU_SRC1
+					 R8A7794_CLK_SCU_SRC0>;
+			clock-output-names = "ssi-all", "ssi9", "ssi8", "ssi7",
+					     "ssi6", "ssi5", "ssi4", "ssi3",
+					     "ssi2", "ssi1", "ssi0",
+					     "scu-all", "scu-dvc1", "scu-dvc0",
+					     "scu-ctu1-mix1", "scu-ctu0-mix0",
+					     "scu-src9", "scu-src8", "scu-src7",
+					     "scu-src6", "scu-src5", "scu-src4",
+					     "scu-src3", "scu-src2", "scu-src1",
+					     "scu-src0";
+		};
 		mstp11_clks: mstp11_clks at e615099c {
 			compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615099c 0 4>, <0 0xe61509ac 0 4>;
Index: renesas/include/dt-bindings/clock/r8a7794-clock.h
===================================================================
--- renesas.orig/include/dt-bindings/clock/r8a7794-clock.h
+++ renesas/include/dt-bindings/clock/r8a7794-clock.h
@@ -109,6 +109,34 @@
 #define R8A7794_CLK_I2C1		30
 #define R8A7794_CLK_I2C0		31
 
+/* MSTP10 */
+#define R8A7794_CLK_SSI_ALL		5
+#define R8A7794_CLK_SSI9		6
+#define R8A7794_CLK_SSI8		7
+#define R8A7794_CLK_SSI7		8
+#define R8A7794_CLK_SSI6		9
+#define R8A7794_CLK_SSI5		10
+#define R8A7794_CLK_SSI4		11
+#define R8A7794_CLK_SSI3		12
+#define R8A7794_CLK_SSI2		13
+#define R8A7794_CLK_SSI1		14
+#define R8A7794_CLK_SSI0		15
+#define R8A7794_CLK_SCU_ALL		17
+#define R8A7794_CLK_SCU_DVC1		18
+#define R8A7794_CLK_SCU_DVC0		19
+#define R8A7794_CLK_SCU_CTU1_MIX1	20
+#define R8A7794_CLK_SCU_CTU0_MIX0	21
+#define R8A7794_CLK_SCU_SRC9		22
+#define R8A7794_CLK_SCU_SRC8		23
+#define R8A7794_CLK_SCU_SRC7		24
+#define R8A7794_CLK_SCU_SRC6		25
+#define R8A7794_CLK_SCU_SRC5		26
+#define R8A7794_CLK_SCU_SRC4		27
+#define R8A7794_CLK_SCU_SRC3		28
+#define R8A7794_CLK_SCU_SRC2		29
+#define R8A7794_CLK_SCU_SRC1		30
+#define R8A7794_CLK_SCU_SRC0		31
+
 /* MSTP11 */
 #define R8A7794_CLK_SCIFA3		6
 #define R8A7794_CLK_SCIFA4		7



From sergei.shtylyov at cogentembedded.com  Thu May 12 13:47:31 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 12 May 2016 23:47:31 +0300
Subject: [PATCH v3 4/6] ARM: dts: r8a7794: add Audio-DMAC support
In-Reply-To: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
Message-ID: <25671875.9c5xSSzmjj@wasted.cogentembedded.com>

Describe Audio-DMAC in the R8A7794 device tree.

This patch is loosely based on the commit 8994fff67761 ("ARM: shmobile:
r8a7791: Add Audio DMAC devices to DT").

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
Changes in version 3:
- refreshed the patch.

 arch/arm/boot/dts/r8a7794.dtsi |   28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

Index: renesas/arch/arm/boot/dts/r8a7794.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7794.dtsi
+++ renesas/arch/arm/boot/dts/r8a7794.dtsi
@@ -295,6 +295,34 @@
 		dma-channels = <15>;
 	};
 
+	audma0: dma-controller at ec700000 {
+		compatible = "renesas,dmac-r8a7794", "renesas,rcar-dmac";
+		reg = <0 0xec700000 0 0x10000>;
+		interrupts =	<GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH
+				 GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "error",
+				  "ch0", "ch1", "ch2", "ch3", "ch4", "ch5",
+				  "ch6", "ch7", "ch8", "ch9", "ch10", "ch11",
+				  "ch12";
+		clocks = <&mstp5_clks R8A7794_CLK_AUDIO_DMAC0>;
+		clock-names = "fck";
+		power-domains = <&cpg_clocks>;
+		#dma-cells = <1>;
+		dma-channels = <13>;
+	};
+
 	scifa0: serial at e6c40000 {
 		compatible = "renesas,scifa-r8a7794",
 			     "renesas,rcar-gen2-scifa", "renesas,scifa";




From tony at atomide.com  Thu May 12 13:48:10 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 12 May 2016 13:48:10 -0700
Subject: [PATCH] ARM: OMAP2+: AM43XX: Enable fixes for Cortex-A9 errata
In-Reply-To: <1463077252-13078-1-git-send-email-d-gerlach@ti.com>
References: <1463077252-13078-1-git-send-email-d-gerlach@ti.com>
Message-ID: <20160512204809.GZ5995@atomide.com>

* Dave Gerlach <d-gerlach at ti.com> [160512 11:23]:
> This patch explicitly enables the fixes for the below errata applicable
> for AM43x Socs as was done for OMAP4.
> 
> 754322: Faulty MMU translations following ASID switch
> 
> 775420: A data cache maintenance operation which aborts,
>         followed by an ISB, without any DSB in-between,
>         might lead to deadlock

Applying into omap-for-v4.7/fixes thanks.

Tony


From sergei.shtylyov at cogentembedded.com  Thu May 12 13:49:21 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 12 May 2016 23:49:21 +0300
Subject: [PATCH v3 5/6] ARM: dts: r8a7794: add sound support
In-Reply-To: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
Message-ID: <38505966.asxJl6Sq91@wasted.cogentembedded.com>

Define the generic R8A7794 part of  the sound device node.
This sound device  is a complex one and comprises the Audio Clock Generator
(ADG), Sampling Rate Converter Unit (SCU), Serial Sound Interface [Unit]
(SSI[U]), and Audio DMAC-Peripheral-Peripheral.
It is up  to the board file to enable the device.

This patch is based on the R8A7791 sound work by Kuninori Morimoto.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
Changes in version 3:
- added back (now disabled) SRC0 node;
- refreshed the patch.

Changes in version 2:
- added "ctu.[01]", "mix.[01]", "dvc.[01]" to the "clock-names" prop;
- added  CTU/DVC/MIX subnodes;
- removed SRC0/7/8/9 subnodes;
- added missing colon to the subject.

 arch/arm/boot/dts/r8a7794.dtsi |  185 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 185 insertions(+)

Index: renesas/arch/arm/boot/dts/r8a7794.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7794.dtsi
+++ renesas/arch/arm/boot/dts/r8a7794.dtsi
@@ -1385,4 +1385,189 @@
 		#iommu-cells = <1>;
 		status = "disabled";
 	};
+
+	rcar_sound: sound at ec500000 {
+		/*
+		 * #sound-dai-cells is required
+		 *
+		 * Single DAI : #sound-dai-cells = <0>;         <&rcar_sound>;
+		 * Multi  DAI : #sound-dai-cells = <1>;         <&rcar_sound N>;
+		 */
+		compatible = "renesas,rcar_sound-r8a7794",
+			     "renesas,rcar_sound-gen2";
+		reg =	<0 0xec500000 0 0x1000>, /* SCU */
+			<0 0xec5a0000 0 0x100>,  /* ADG */
+			<0 0xec540000 0 0x1000>, /* SSIU */
+			<0 0xec541000 0 0x280>,  /* SSI */
+			<0 0xec740000 0 0x200>;  /* Audio DMAC peri peri */
+		reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
+
+		clocks = <&mstp10_clks R8A7794_CLK_SSI_ALL>,
+			 <&mstp10_clks R8A7794_CLK_SSI9>,
+			 <&mstp10_clks R8A7794_CLK_SSI8>,
+			 <&mstp10_clks R8A7794_CLK_SSI7>,
+			 <&mstp10_clks R8A7794_CLK_SSI6>,
+			 <&mstp10_clks R8A7794_CLK_SSI5>,
+			 <&mstp10_clks R8A7794_CLK_SSI4>,
+			 <&mstp10_clks R8A7794_CLK_SSI3>,
+			 <&mstp10_clks R8A7794_CLK_SSI2>,
+			 <&mstp10_clks R8A7794_CLK_SSI1>,
+			 <&mstp10_clks R8A7794_CLK_SSI0>,
+			 <&mstp10_clks R8A7794_CLK_SCU_SRC9>,
+			 <&mstp10_clks R8A7794_CLK_SCU_SRC8>,
+			 <&mstp10_clks R8A7794_CLK_SCU_SRC7>,
+			 <&mstp10_clks R8A7794_CLK_SCU_SRC6>,
+			 <&mstp10_clks R8A7794_CLK_SCU_SRC5>,
+			 <&mstp10_clks R8A7794_CLK_SCU_SRC4>,
+			 <&mstp10_clks R8A7794_CLK_SCU_SRC3>,
+			 <&mstp10_clks R8A7794_CLK_SCU_SRC2>,
+			 <&mstp10_clks R8A7794_CLK_SCU_SRC1>,
+			 <&mstp10_clks R8A7794_CLK_SCU_SRC0>,
+			 <&mstp10_clks R8A7794_CLK_SCU_CTU0_MIX0>,
+			 <&mstp10_clks R8A7794_CLK_SCU_CTU1_MIX1>,
+			 <&mstp10_clks R8A7794_CLK_SCU_CTU0_MIX0>,
+			 <&mstp10_clks R8A7794_CLK_SCU_CTU1_MIX1>,
+			 <&mstp10_clks R8A7794_CLK_SCU_DVC0>,
+			 <&mstp10_clks R8A7794_CLK_SCU_DVC1>,
+			 <&audio_clka>, <&audio_clkb>, <&audio_clkc>,
+			 <&m2_clk>;
+		clock-names = "ssi-all",
+			      "ssi.9", "ssi.8", "ssi.7", "ssi.6", "ssi.5",
+			      "ssi.4", "ssi.3", "ssi.2", "ssi.1", "ssi.0",
+			      "src.9", "src.8", "src.7", "src.6", "src.5",
+			      "src.4", "src.3", "src.2", "src.1", "src.0",
+			      "ctu.0", "ctu.1",
+			      "mix.0", "mix.1",
+			      "dvc.0", "dvc.1",
+			      "clk_a", "clk_b", "clk_c", "clk_i";
+		power-domains = <&cpg_clocks>;
+
+		status = "disabled";
+
+		rcar_sound,dvc {
+			dvc0: dvc at 0 {
+				dmas = <&audma0 0xbc>;
+				dma-names = "tx";
+			};
+			dvc1: dvc at 1 {
+				dmas = <&audma0 0xbe>;
+				dma-names = "tx";
+			};
+		};
+
+		rcar_sound,mix {
+			mix0: mix at 0 { };
+			mix1: mix at 1 { };
+		};
+
+		rcar_sound,ctu {
+			ctu00: ctu at 0 { };
+			ctu01: ctu at 1 { };
+			ctu02: ctu at 2 { };
+			ctu03: ctu at 3 { };
+			ctu10: ctu at 4 { };
+			ctu11: ctu at 5 { };
+			ctu12: ctu at 6 { };
+			ctu13: ctu at 7 { };
+		};
+
+		rcar_sound,src {
+			src at 0 {
+				status = "disabled";
+			};
+			src1: src at 1 {
+				interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x87>, <&audma0 0x9c>;
+				dma-names = "rx", "tx";
+			};
+			src2: src at 2 {
+				interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x89>, <&audma0 0x9e>;
+				dma-names = "rx", "tx";
+			};
+			src3: src at 3 {
+				interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x8b>, <&audma0 0xa0>;
+				dma-names = "rx", "tx";
+			};
+			src4: src at 4 {
+				interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x8d>, <&audma0 0xb0>;
+				dma-names = "rx", "tx";
+			};
+			src5: src at 5 {
+				interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x8f>, <&audma0 0xb2>;
+				dma-names = "rx", "tx";
+			};
+			src6: src at 6 {
+				interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x91>, <&audma0 0xb4>;
+				dma-names = "rx", "tx";
+			};
+		};
+
+		rcar_sound,ssi {
+			ssi0: ssi at 0 {
+				interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x01>, <&audma0 0x02>,
+				       <&audma0 0x15>, <&audma0 0x16>;
+				dma-names = "rx", "tx", "rxu", "txu";
+			};
+			ssi1: ssi at 1 {
+				interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x03>, <&audma0 0x04>,
+				       <&audma0 0x49>, <&audma0 0x4a>;
+				dma-names = "rx", "tx", "rxu", "txu";
+			};
+			ssi2: ssi at 2 {
+				interrupts = <GIC_SPI 372 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x05>, <&audma0 0x06>,
+				       <&audma0 0x63>, <&audma0 0x64>;
+				dma-names = "rx", "tx", "rxu", "txu";
+			};
+			ssi3: ssi at 3 {
+				interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x07>, <&audma0 0x08>,
+				       <&audma0 0x6f>, <&audma0 0x70>;
+				dma-names = "rx", "tx", "rxu", "txu";
+			};
+			ssi4: ssi at 4 {
+				interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x09>, <&audma0 0x0a>,
+				       <&audma0 0x71>, <&audma0 0x72>;
+				dma-names = "rx", "tx", "rxu", "txu";
+			};
+			ssi5: ssi at 5 {
+				interrupts = <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x0b>, <&audma0 0x0c>,
+				       <&audma0 0x73>, <&audma0 0x74>;
+				dma-names = "rx", "tx", "rxu", "txu";
+			};
+			ssi6: ssi at 6 {
+				interrupts = <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x0d>, <&audma0 0x0e>,
+				       <&audma0 0x75>, <&audma0 0x76>;
+				dma-names = "rx", "tx", "rxu", "txu";
+			};
+			ssi7: ssi at 7 {
+				interrupts = <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x0f>, <&audma0 0x10>,
+				       <&audma0 0x79>, <&audma0 0x7a>;
+				dma-names = "rx", "tx", "rxu", "txu";
+			};
+			ssi8: ssi at 8 {
+				interrupts = <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x11>, <&audma0 0x12>,
+				       <&audma0 0x7b>, <&audma0 0x7c>;
+				dma-names = "rx", "tx", "rxu", "txu";
+			};
+			ssi9: ssi at 9 {
+				interrupts = <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&audma0 0x13>, <&audma0 0x14>,
+				       <&audma0 0x7d>, <&audma0 0x7e>;
+				dma-names = "rx", "tx", "rxu", "txu";
+			};
+		};
+	};
 };



From sergei.shtylyov at cogentembedded.com  Thu May 12 13:51:32 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 12 May 2016 23:51:32 +0300
Subject: [PATCH v3 6/6] ARM: dts: silk: add sound support
In-Reply-To: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
Message-ID: <9205499.bquhjWrlAH@wasted.cogentembedded.com>

Define the SILK board dependent part of the R8A7794 sound  device node.
Add device node for Asahi Kasei AK4643 stereo codec to the I2C1 bus.
Add the "simple-audio-card" device node to interconnect the SoC sound
device  and the codec.

This patch is based on the commit 493b4da7c10c ("ARM: dts: porter: add
sound support").

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
This patch is against  the 'renesas-devel-20160509-v4.6-rc7' tag of Simon
Horman's 'renesas.git' repo. It depends on the 5 R8A7794 sound support patches
posted earlier in order to build...

Changes in version 3:
- new patch in this series;
- renamed the X9 clock node, getting rid of the "clock-output-names" property;
- removed the "renesas," prefix from the pin properties;
- refreshed the patch.

 arch/arm/boot/dts/r8a7794-silk.dts |   70 +++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

Index: renesas/arch/arm/boot/dts/r8a7794-silk.dts
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7794-silk.dts
+++ renesas/arch/arm/boot/dts/r8a7794-silk.dts
@@ -10,6 +10,17 @@
  * kind, whether express or implied.
  */
 
+/*
+ * SSI-AK4643
+ *
+ * SW1: 2-1: AK4643
+ *      2-3: ADV7511
+ *
+ * This command is required before playback/capture:
+ *
+ *	amixer set "LINEOUT Mixer DACL" on
+ */
+
 /dts-v1/;
 #include "r8a7794.dtsi"
 #include <dt-bindings/gpio/gpio.h>
@@ -119,6 +130,29 @@
 		#clock-cells = <0>;
 		clock-frequency = <74250000>;
 	};
+
+	x9_clk: audio_clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <12288000>;
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+
+		simple-audio-card,format = "left_j";
+		simple-audio-card,bitclock-master = <&soundcodec>;
+		simple-audio-card,frame-master = <&soundcodec>;
+
+		simple-audio-card,cpu {
+			sound-dai = <&rcar_sound>;
+		};
+
+		soundcodec: simple-audio-card,codec {
+			sound-dai = <&ak4643>;
+			clocks = <&x9_clk>;
+		};
+	};
 };
 
 &extal_clk {
@@ -193,6 +227,16 @@
 		groups = "du1_rgb666", "du1_sync", "du1_disp", "du1_clk0_out";
 		function = "du1";
 	};
+
+	ssi_pins: sound {
+		groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
+		function = "ssi";
+	};
+
+	audio_clk_pins: audio_clk {
+		groups = "audio_clkc";
+		function = "audio_clk";
+	};
 };
 
 &scif2 {
@@ -230,6 +274,12 @@
 	status = "okay";
 	clock-frequency = <400000>;
 
+	ak4643: codec at 12 {
+		compatible = "asahi-kasei,ak4643";
+		#sound-dai-cells = <0>;
+		reg = <0x12>;
+	};
+
 	composite-in at 20 {
 		compatible = "adi,adv7180";
 		reg = <0x20>;
@@ -392,3 +442,23 @@
 		};
 	};
 };
+
+&rcar_sound {
+	pinctrl-0 = <&ssi_pins &audio_clk_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	/* Single DAI */
+	#sound-dai-cells = <0>;
+
+	rcar_sound,dai {
+		dai0 {
+			playback = <&ssi0>;
+			capture  = <&ssi1>;
+		};
+	};
+};
+
+&ssi1 {
+	shared-pin;
+};



From tony at atomide.com  Thu May 12 13:53:56 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 12 May 2016 13:53:56 -0700
Subject: [PATCH 1/2] ARM: dts: igep00x0: Add SD card-detect.
In-Reply-To: <CABxcv=nqdETAJBpO-akYipuHH6F6vy5wxHX+dOt9=0CKTTkt=Q@mail.gmail.com>
References: <1462568554-7868-1-git-send-email-enric.balletbo@collabora.com>
 <CABxcv=nZ1hjVGnNG65eKDrxAYFBcavML+GjxXtfTcVO5N83xkA@mail.gmail.com>
 <572D0B10.60908@collabora.com>
 <CABxcv=nqdETAJBpO-akYipuHH6F6vy5wxHX+dOt9=0CKTTkt=Q@mail.gmail.com>
Message-ID: <20160512205356.GA5995@atomide.com>

* Javier Martinez Canillas <javier at dowhile0.org> [160506 14:28]:
> Hello Enric,
> 
> On Fri, May 6, 2016 at 5:22 PM, Enric Balletbo i Serra
> <enric.balletbo at collabora.com> wrote:
> > Hi Javier,
> >
> > On 06/05/16 23:07, Javier Martinez Canillas wrote:
> >> Hello Enric,
> >>
> >> On Fri, May 6, 2016 at 5:02 PM, Enric Balletbo i Serra
> >> <enric.balletbo at collabora.com> wrote:
> >>> Fix SD card remove/insert detection by adding the correct card-detect
> >>> pin. All IGEP OMAP3 based boards use the same card-detect pin.
> >>>
> >>> Signed-off-by: Enric Balletbo i Serra <enric.balletbo at collabora.com>
> >>> Signed-off-by: Ladislav Michl <ladis at linux-mips.org>
> >>
> >> Shouldn't his be Suggested-by: Ladislav Michl <ladis at linux-mips.org> instead?
> >>
> >> Or if the patch was originally from Ladis, then he should remain the
> >> author with your S-o-B after his.
> >>
> >
> > Well Ladis sent the same patch as I had in my local repository for long
> > time, so to be strict the correct is have two authors and two S-o-B. My bad
> > is not send the patch before.
> 
> Got it, then I think is correct to have both S-o-B. Thanks for the
> clarification.

OK thanks for checking, applying both into omap-for-v4.7/dt.

Tony


From arnd at arndb.de  Thu May 12 14:01:30 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 12 May 2016 23:01:30 +0200
Subject: [PATCH] soc: mtk-pmic-wrap: avoid integer overflow warning
Message-ID: <1463086904-2493288-1-git-send-email-arnd@arndb.de>

On ARM64, the mtk-pmic-wrap driver causes a harmless warning:

mtk-pmic-wrap.c:1062:16: warning: large integer implicitly truncated to unsigned type [-Woverflow]
mtk-pmic-wrap.c:1074:16: warning: large integer implicitly truncated to unsigned type [-Woverflow]
mtk-pmic-wrap.c:1086:16: warning: large integer implicitly truncated to unsigned type [-Woverflow]
  .int_en_all = ~(BIT(31) | BIT(1)),

The problem is that the result of the BIT() macro is an 'unsigned long',
so taking the bitwise NOT operation of that results in an integer
with the upper 32 bits all set and that cannot be assigned to a
'u32' variable without loss of information.

This is harmless because we were never interested in the upper bits
here anyway, so we can shut up the warning by adding a simple cast
to 'u32'.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/soc/mediatek/mtk-pmic-wrap.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index 3c3e56df526e..a003ba26ca6e 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -1059,7 +1059,7 @@ static const struct pmic_wrapper_type pwrap_mt2701 = {
 	.regs = mt2701_regs,
 	.type = PWRAP_MT2701,
 	.arb_en_all = 0x3f,
-	.int_en_all = ~(BIT(31) | BIT(2)),
+	.int_en_all = ~(u32)(BIT(31) | BIT(2)),
 	.spi_w = PWRAP_MAN_CMD_SPI_WRITE_NEW,
 	.wdt_src = PWRAP_WDT_SRC_MASK_ALL,
 	.has_bridge = 0,
@@ -1071,7 +1071,7 @@ static struct pmic_wrapper_type pwrap_mt8135 = {
 	.regs = mt8135_regs,
 	.type = PWRAP_MT8135,
 	.arb_en_all = 0x1ff,
-	.int_en_all = ~(BIT(31) | BIT(1)),
+	.int_en_all = ~(u32)(BIT(31) | BIT(1)),
 	.spi_w = PWRAP_MAN_CMD_SPI_WRITE,
 	.wdt_src = PWRAP_WDT_SRC_MASK_ALL,
 	.has_bridge = 1,
@@ -1083,7 +1083,7 @@ static struct pmic_wrapper_type pwrap_mt8173 = {
 	.regs = mt8173_regs,
 	.type = PWRAP_MT8173,
 	.arb_en_all = 0x3f,
-	.int_en_all = ~(BIT(31) | BIT(1)),
+	.int_en_all = ~(u32)(BIT(31) | BIT(1)),
 	.spi_w = PWRAP_MAN_CMD_SPI_WRITE,
 	.wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD,
 	.has_bridge = 0,
-- 
2.7.0



From dianders at chromium.org  Thu May 12 14:09:24 2016
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 12 May 2016 14:09:24 -0700
Subject: [PATCH v8 7/8] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <57349C36.4030401@rock-chips.com>
References: <1462908252-27016-1-git-send-email-david.wu@rock-chips.com>
 <1462908698-27284-1-git-send-email-david.wu@rock-chips.com>
 <CAD=FV=Uf-U3RBpgFbR3LkPAJTWqz3d02+H7iyA-SS-y=r3cXjA@mail.gmail.com>
 <5733D7AA.1060500@rock-chips.com> <57349C36.4030401@rock-chips.com>
Message-ID: <CAD=FV=W1-DDtuLUzW1uLiFxuhpnmhnKB1od_yweY=WJ-4u3=kQ@mail.gmail.com>

David,

On Thu, May 12, 2016 at 8:07 AM, David.Wu <david.wu at rock-chips.com> wrote:
> I also found a subtle bug, it would clean the con register by use
> "i2c_writel(i2c, 0, REG_CON)" in rk3x_i2c_stop(). So i think it would be
> fixed by using read-modify-write way here in next version.

Good catch.  I look forward to the next version (maybe the last
version, since this series is looking really good).

-Doug


From sergei.shtylyov at cogentembedded.com  Thu May 12 14:16:17 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Fri, 13 May 2016 00:16:17 +0300
Subject: [PATCH v3 0/6] Add R8A7794/SILK sound DT support
In-Reply-To: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
Message-ID: <7d19e749-8264-9004-64f4-aefabda699c6@cogentembedded.com>

Hello.

On 05/12/2016 11:38 PM, Sergei Shtylyov wrote:

>    Here's the set of 6 patches against Simon Horman's 'renesas.git' repo,
> 'renesas-devel-20160509-v4.6-rc7' tag. I'm adding the sound device tree support
> for the R8A7794 SoC based SILK board.
>
> [1/6] ARM: dts: r8a7794: add audio clocks
> [2/6] ARM: dts: r8a7794: add MSTP5 clocks
> [3/6] ARM: dts: r8a7794: add MSTP10 clocks
> [4/6] ARM: dts: r8a7794: add Audio-DMAC support
> [5/6] ARM: dts: r8a7794: add sound support
> [6/6] ARM: dts: silk: add sound support

    Oops, forgot to mention that patch #5 depends on the R-Car sound patch 
posted yesterday in order to get interpreted as intended (it uses a disabled 
SRC node).

WBR, Sergei



From roy.lists at gmail.com  Thu May 12 14:30:26 2016
From: roy.lists at gmail.com (Roy Franz (HPE))
Date: Thu, 12 May 2016 14:30:26 -0700
Subject: [PATCH v5 0/1] ARM64: ACPI: Update documentation for latest
 specification version
In-Reply-To: <3b6d5be3-40ab-94dc-2590-8b2638cbdc15@redhat.com>
References: <1461619287-27211-1-git-send-email-al.stone@linaro.org>
 <3b6d5be3-40ab-94dc-2590-8b2638cbdc15@redhat.com>
Message-ID: <CAK-u0Q=zrPhOnkut1vJgAS5DKKRSD2oVxCeZen_6LqvYCR5nCw@mail.gmail.com>

On Mon, May 2, 2016 at 1:19 PM, Al Stone <ahs3 at redhat.com> wrote:
> On 04/25/2016 03:21 PM, Al Stone wrote:
>> The ACPI 6.1 specification was recently released at the end of January
>> 2016, but the arm64 kernel documentation for the use of ACPI was written
>> for the 5.1 version of the spec.  There were significant additions to the
>> spec that had not yet been mentioned -- for example, the 6.0 mechanisms
>> added to make it easier to define processors and low power idle states,
>> as well as the 6.1 addition allowing regular interrupts (not just from
>> GPIO) be used to signal ACPI general purpose events.
>>
>> This patch reflects going back through and examining the specs in detail
>> and updating content appropriately.  Whilst there, a few odds and ends of
>> typos were caught as well.  This brings the documentation up to date with
>> ACPI 6.1 for arm64.
>>
>> Changes for v5:
>>    -- Miscellaneous typos and corrections (Lorenzo Pieralisi)
>>    -- Add linux-acpi@ ML to the distribution list (Alexey Klimov)
>>    -- Corrections to CPPC information (Alexey Klimov)
>>    -- ACK from Lorenzo Pieralisi
>>    -- Updated bibliographic info (Al Stone)
>>
>> Changes for v4:
>>    -- Clarify that IORT can sometimes be optional (Jon Masters).
>>    -- Remove "Use as needed" descriptions of ACPI objects; they provide
>>       no substantive information and doing so simplifies maintenance of
>>       this document over time.  These have been replaced with a simpler
>>       notice that states that unless otherwise noted, do what the ACPI
>>       specification says is needed.
>>    -- Corrected the _OSI object usage recommendation; it described kernel
>>       behavior that does not exist (Al Stone).
>>
>> Changes for v3:
>>    -- Clarify use of _LPI/_RDI (Vikas Sajjan)
>>    -- Whitespace cleanup as pointed out by checkpatch
>>
>> Changes for v2:
>>    -- Clean up white space (Harb Abdulhahmid)
>>    -- Clarification on _CCA usage (Harb Abdulhamid)
>>    -- IORT moved to required from recommended (Hanjun Guo)
>>    -- Clarify IORT description (Hanjun Guo)
>>
>>
>> Al Stone (1):
>>   ARM64: ACPI: Update documentation for latest specification version
>>
>>  Documentation/arm64/acpi_object_usage.txt | 343 ++++++++++++++++--------------
>>  Documentation/arm64/arm-acpi.txt          |  40 ++--
>>  2 files changed, 213 insertions(+), 170 deletions(-)
>>
>
> Ping?  If there are no further comments, can this be pulled in through
> either the documentation or arm64 tree?
>
> Thanks.

I've read through this - looks good to me.  I think it provides useful
guidance to
reference as we work on getting good ACPI support provided by various platforms
under development.

Reviewed-by: Roy Franz <roy.franz at hpe.com>

>
> --
> ciao,
> al
> -----------------------------------
> Al Stone
> Software Engineer
> Red Hat, Inc.
> ahs3 at redhat.com
> -----------------------------------
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From sboyd at codeaurora.org  Thu May 12 14:47:02 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Thu, 12 May 2016 14:47:02 -0700
Subject: [linux-sunxi] Re: [PATCH v4 01/11] clk: sunxi: Add display and
 TCON0 clocks driver
In-Reply-To: <20160512083047.GY3733@lukather>
References: <1461590572-4027-2-git-send-email-maxime.ripard@free-electrons.com>
 <20160506223002.GE3492@codeaurora.org>
 <20160508200308.GF6167@lukather>
 <20160509223238.GW3492@codeaurora.org>
 <20160509223924.GX3492@codeaurora.org>
 <1462907459.9981.0.camel@plaes.org>
 <20160511221541.GG3492@codeaurora.org>
 <1463024360.16747.4.camel@plaes.org>
 <20160512065943.GX3733@lukather> <20160512083047.GY3733@lukather>
Message-ID: <20160512214702.GL3492@codeaurora.org>

On 05/12, Maxime Ripard wrote:
> 
> diff --git a/drivers/clk/sunxi/clk-sun4i-display.c b/drivers/clk/sunxi/clk-sun4i-display.c
> index 70803aa7028c..9780fac6d029 100644
> --- a/drivers/clk/sunxi/clk-sun4i-display.c
> +++ b/drivers/clk/sunxi/clk-sun4i-display.c
> @@ -128,8 +128,8 @@ static void __init sun4i_a10_display_init(struct device_node *node,
>  		return;
>  	}
>  
> -	ret = of_clk_parent_fill(node, parents, ARRAY_SIZE(parents));
> -	if (ret != ARRAY_SIZE(parents)) {
> +	ret = of_clk_parent_fill(node, parents, data->parents);
> +	if (ret != data->parents) {
>  		pr_err("%s: Could not retrieve the parents\n", clk_name);
>  		goto unmap;
>  	}

Ah ok. Thanks for catching that thinko and sending a patch.

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


From matija.glavinic-pecotic.ext at nokia.com  Thu May 12 14:49:24 2016
From: matija.glavinic-pecotic.ext at nokia.com (Matija Glavinic Pecotic)
Date: Thu, 12 May 2016 23:49:24 +0200
Subject: [PATCH] ARM: Fix A15 798181 errata initialization
Message-ID: <5734FA64.6040501@nokia.com>

Current errata initialization doesn't take properly revision and REVIDR
into account. Depending on the core revision, revidr bits should not be
taken into account. Errata misleadingly declares r3p3 to be error-free,
but this is not the case. Include rp3p3 in errata initialization.

Here are possible fixes defined in revidr register for r2 and r3 [1,2]:

r0p0-r2p1: No fixes applied

r2p2,r2p3:

REVIDR[4]: 798181 Moving a virtual page that is being accessed by
	   an active process can lead to unexpected behavior
REVIDR[9]: Not defined

r2p4,r3p0,r3p1,r3p2:

REVIDR[4]: 798181 Moving a virtual page that is being accessed by
	   an active process can lead to unexpected behavior
REVIDR[9]: 798181 Moving a virtual page that is being accessed by
	   an active process can lead to unexpected behavior
	   - This is an update to a previously released ECO.

r3p3:

REVIDR[4]: Reserved
REVIDR[9]: 798181 Moving a virtual page that is being accessed by
	   an active process can lead to unexpected behavior
	   - This is an update to a previously released ECO.

And here is proposed handling from the same documents [1,2]:

* In r3p2 and earlier versions with REVIDR[4]= 0,the full workaround is
  required.
* In r3p2 and earlier versions with REVIDR[4]=1, REVIDR[9]=0, only the
  portion of the workaround up to the end of step 6 is required.
* In r3p2 and earlier versions with REVIDR[4]=1, REVIDR[9]=1, no
  workaround is required.
* In r3p3, if REVIDR[9]=0, only the portion of the workaround up
  to the end of step 6 is required.
* In r3p3, if REVIDR[9]=1, no workaround is required.

These imply following:

REVIDR[9] set -> No WA
REVIDR[4] set, REVIDR[9] cleared -> Partial WA
Both cleared -> Full WA

Where certain bits should and should not be taken into account
depending on whether they are defined for the revision.

Although not explicitly mentioned in the errata note, REVIDR[9] set,
with REVIDR[4] cleared is valid combination which requires no WA. This
is confirmed by ARM support and errata will be updated.

[1] ARM CortexTM-A15 MPCore - NEON
    Product revision r3
    Software Developers Errata Notice
    ARM-EPM-028093 v20.0 Released

[2] ARM CortexTM-A15 MPCore - NEON
    Product Revision r2
    Software Developers Errata Notice
    ARM-EPM-028090 v19.3 Released

Signed-off-by: Matija Glavinic Pecotic <matija.glavinic-pecotic.ext at nokia.com>
Reviewed-by: Alexander Sverdlin <alexander.sverdlin at nokia.com>
---
 arch/arm/kernel/smp_tlb.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
index 2e72be4..b624758 100644
--- a/arch/arm/kernel/smp_tlb.c
+++ b/arch/arm/kernel/smp_tlb.c
@@ -93,17 +93,30 @@ void erratum_a15_798181_init(void)
 	unsigned int revidr = read_cpuid(CPUID_REVIDR);
 
 	/* Brahma-B15 r0p0..r0p2 affected
-	 * Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
-	if ((midr & 0xff0ffff0) == 0x420f00f0 && midr <= 0x420f00f2)
+	 * Cortex-A15 r0p0..r3p3 w/o ECO fix affected
+	 */
+	if ((midr & 0xff0ffff0) == 0x420f00f0 && midr <= 0x420f00f2) {
 		erratum_a15_798181_handler = erratum_a15_798181_broadcast;
-	else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr <= 0x413fc0f2 &&
-		 (revidr & 0x210) != 0x210) {
+	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x412fc0f2) {
+		erratum_a15_798181_handler = erratum_a15_798181_broadcast;
+	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x412fc0f4) {
 		if (revidr & 0x10)
 			erratum_a15_798181_handler =
 				erratum_a15_798181_partial;
 		else
 			erratum_a15_798181_handler =
 				erratum_a15_798181_broadcast;
+	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x413fc0f3) {
+		if ((revidr & 0x210) == 0)
+			erratum_a15_798181_handler =
+				erratum_a15_798181_broadcast;
+		else if (revidr & 0x10)
+			erratum_a15_798181_handler =
+				erratum_a15_798181_partial;
+	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x414fc0f0) {
+		if ((revidr & 0x200) == 0)
+			erratum_a15_798181_handler =
+				erratum_a15_798181_partial;
 	}
 }
 #endif
-- 
2.1.4


From dianders at chromium.org  Thu May 12 15:02:10 2016
From: dianders at chromium.org (Douglas Anderson)
Date: Thu, 12 May 2016 15:02:10 -0700
Subject: [PATCH] arm64: dts: Add symlinks for cros-ec-keyboard and cros-ec-sbs
Message-ID: <1463090530-21864-1-git-send-email-dianders@chromium.org>

We'd like to be able to use the cros-ec-keyboard.dtsi and
cros-ec-sbs.dtsi snippets for arm64 devices.  Currently those files live
in the arm/boot/dts directory.

Let's follow the convention set by commit 8ee57b8182c4 ("ARM64: dts:
vexpress: Use a symlink to vexpress-v2m-rs1.dtsi from arch=arm") and use
a symlink.  Note that in this case we put the files in a new
"include/common" directory since these snippets may need to be
referenced by dts files in many different subdirectories.

Signed-off-by: Douglas Anderson <dianders at chromium.org>
---
Note that, as of right now, there are no users of this.  However, given
development happening it is almost 100% certain that users will arrive
soon.  If we need to wait for the first user before landing this we can
leave this on the back burner.  If it's OK to have no users (yet), let's
land.

 arch/arm64/boot/dts/include/common/cros-ec-keyboard.dtsi | 1 +
 arch/arm64/boot/dts/include/common/cros-ec-sbs.dtsi      | 1 +
 2 files changed, 2 insertions(+)
 create mode 120000 arch/arm64/boot/dts/include/common/cros-ec-keyboard.dtsi
 create mode 120000 arch/arm64/boot/dts/include/common/cros-ec-sbs.dtsi

diff --git a/arch/arm64/boot/dts/include/common/cros-ec-keyboard.dtsi b/arch/arm64/boot/dts/include/common/cros-ec-keyboard.dtsi
new file mode 120000
index 000000000000..1c1889f0a791
--- /dev/null
+++ b/arch/arm64/boot/dts/include/common/cros-ec-keyboard.dtsi
@@ -0,0 +1 @@
+../../../../../arm/boot/dts/cros-ec-keyboard.dtsi
\ No newline at end of file
diff --git a/arch/arm64/boot/dts/include/common/cros-ec-sbs.dtsi b/arch/arm64/boot/dts/include/common/cros-ec-sbs.dtsi
new file mode 120000
index 000000000000..3d7ae9c88bcd
--- /dev/null
+++ b/arch/arm64/boot/dts/include/common/cros-ec-sbs.dtsi
@@ -0,0 +1 @@
+../../../../../arm/boot/dts/cros-ec-sbs.dtsi
\ No newline at end of file
-- 
2.8.0.rc3.226.g39d4020



From briannorris at chromium.org  Thu May 12 15:22:23 2016
From: briannorris at chromium.org (Brian Norris)
Date: Thu, 12 May 2016 15:22:23 -0700
Subject: [PATCH 1/2] ARM64: dts: rockchip: add sdhci/emmc for rk3399
In-Reply-To: <3e257ce2-056a-592a-9481-970da1fe0627@rock-chips.com>
References: <1462924975-69072-1-git-send-email-briannorris@chromium.org>
 <3e257ce2-056a-592a-9481-970da1fe0627@rock-chips.com>
Message-ID: <20160512222223.GA57835@google.com>

On Wed, May 11, 2016 at 09:17:38AM +0800, Shawn Lin wrote:
> How about adding these?
> 
> assigned-clocks = <&cru SCLK_EMMC>;
> assigned-clock-parents = <&cru PLL_CPLL>; //may not need

BTW, even if I assign the parent here, it's not actually taking effect
on my system. Presumably the common clock framework is finding a
"better" way to satisfy 200 MHz through GPLL instead. So I'm dropping
the assigned-clock-parents for v2.

> assigned-clock-rates = <200000000>;

Brian


From briannorris at chromium.org  Thu May 12 15:35:51 2016
From: briannorris at chromium.org (Brian Norris)
Date: Thu, 12 May 2016 15:35:51 -0700
Subject: [PATCH v2 1/2] ARM64: dts: rockchip: add sdhci/emmc for rk3399
Message-ID: <1463092552-60696-1-git-send-email-briannorris@chromium.org>

Add description for the SDHCI v5.1 eMMC controller on rk3399. Fix it to
200 MHz, to support all supported timing modes.

Note that 'rockchip,rk3399-sdhci-5.1' is not documented; we presumably
have a compliant Arasan controller, but let's have a rockchip property
as the canonical backup/precautionary measure. Per Heiko's previous
suggestion, let's not clutter the arasan doc with it.

Signed-off-by: Brian Norris <briannorris at chromium.org>
---
v2:

 * improved commit message
 * assign eMMC clock to 200 MHz

 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 46f325a143b0..9980c2eab4e9 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -215,6 +215,19 @@
 		status = "disabled";
 	};
 
+	sdhci: sdhci at fe330000 {
+		compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
+		reg = <0x0 0xfe330000 0x0 0x10000>;
+		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;
+		clock-names = "clk_xin", "clk_ahb";
+		assigned-clocks = <&cru SCLK_EMMC>;
+		assigned-clock-rates = <200000000>;
+		phys = <&emmc_phy>;
+		phy-names = "phy_arasan";
+		status = "disabled";
+	};
+
 	usb_host0_ehci: usb at fe380000 {
 		compatible = "generic-ehci";
 		reg = <0x0 0xfe380000 0x0 0x20000>;
@@ -481,8 +494,18 @@
 	};
 
 	grf: syscon at ff770000 {
-		compatible = "rockchip,rk3399-grf", "syscon";
+		compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
 		reg = <0x0 0xff770000 0x0 0x10000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		emmc_phy: phy at f780 {
+			compatible = "rockchip,rk3399-emmc-phy";
+			reg = <0xf780 0x20>;
+			#phy-cells = <0>;
+			status = "disabled";
+		};
 	};
 
 	watchdog at ff840000 {
-- 
2.8.0.rc3.226.g39d4020



From briannorris at chromium.org  Thu May 12 15:35:52 2016
From: briannorris at chromium.org (Brian Norris)
Date: Thu, 12 May 2016 15:35:52 -0700
Subject: [PATCH v2 2/2] ARM64: dts: rockchip: enable eMMC for rk3399 EVB
In-Reply-To: <1463092552-60696-1-git-send-email-briannorris@chromium.org>
References: <1463092552-60696-1-git-send-email-briannorris@chromium.org>
Message-ID: <1463092552-60696-2-git-send-email-briannorris@chromium.org>

Rockchip's rk3399 evaluation board has eMMC. Let's enable the
newly-added node.

Signed-off-by: Brian Norris <briannorris at chromium.org>
---
v2:

 * better commit description

 arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
index 1a3eb1482050..0b27d91084c4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
@@ -89,6 +89,18 @@
 	status = "okay";
 };
 
+&emmc_phy {
+	status = "okay";
+};
+
+&sdhci {
+	bus-width = <8>;
+	mmc-hs400-1_8v;
+	mmc-hs400-enhanced-strobe;
+	non-removable;
+	status = "okay";
+};
+
 &uart2 {
 	status = "okay";
 };
-- 
2.8.0.rc3.226.g39d4020



From briannorris at chromium.org  Thu May 12 15:43:04 2016
From: briannorris at chromium.org (Brian Norris)
Date: Thu, 12 May 2016 15:43:04 -0700
Subject: [PATCH 2/4] phy: rockchip-emmc: configure frequency range and drive
 impedance
In-Reply-To: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
Message-ID: <1463092986-61777-2-git-send-email-briannorris@chromium.org>

From: Shawn Lin <shawn.lin at rock-chips.com>

Signal integrity analysis has suggested we set these values. Do this in
power_on(), so that they get reconfigured after suspend/resume.

Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
Signed-off-by: Brian Norris <briannorris at chromium.org>
---
 drivers/phy/phy-rockchip-emmc.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/phy-rockchip-emmc.c
index 48cbe691a889..5641dede32f6 100644
--- a/drivers/phy/phy-rockchip-emmc.c
+++ b/drivers/phy/phy-rockchip-emmc.c
@@ -56,6 +56,19 @@
 #define PHYCTRL_DLLRDY_SHIFT	0x5
 #define PHYCTRL_DLLRDY_DONE	0x1
 #define PHYCTRL_DLLRDY_GOING	0x0
+#define PHYCTRL_FREQSEL_200M	0x0
+#define PHYCTRL_FREQSEL_50M	0x1
+#define PHYCTRL_FREQSEL_100M	0x2
+#define PHYCTRL_FREQSEL_150M	0x3
+#define PHYCTRL_FREQSEL_MASK	0x3
+#define PHYCTRL_FREQSEL_SHIFT	0xc
+#define PHYCTRL_DR_MASK		0x7
+#define PHYCTRL_DR_SHIFT	0x4
+#define PHYCTRL_DR_50OHM	0x0
+#define PHYCTRL_DR_33OHM	0x1
+#define PHYCTRL_DR_66OHM	0x2
+#define PHYCTRL_DR_100OHM	0x3
+#define PHYCTRL_DR_40OHM	0x4
 
 struct rockchip_emmc_phy {
 	unsigned int	reg_offset;
@@ -154,6 +167,20 @@ static int rockchip_emmc_phy_power_on(struct phy *phy)
 	struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
 	int ret = 0;
 
+	/* DLL operation: 170 to 200 MHz */
+	regmap_write(rk_phy->reg_base,
+		     rk_phy->reg_offset + GRF_EMMCPHY_CON0,
+		     HIWORD_UPDATE(PHYCTRL_FREQSEL_200M,
+				   PHYCTRL_FREQSEL_MASK,
+				   PHYCTRL_FREQSEL_SHIFT));
+
+	/* Drive impedance: 50 Ohm */
+	regmap_write(rk_phy->reg_base,
+		     rk_phy->reg_offset + GRF_EMMCPHY_CON6,
+		     HIWORD_UPDATE(PHYCTRL_DR_50OHM,
+				   PHYCTRL_DR_MASK,
+				   PHYCTRL_DR_SHIFT));
+
 	/* Power up emmc phy analog blocks */
 	ret = rockchip_emmc_phy_power(rk_phy, PHYCTRL_PDB_PWR_ON);
 	if (ret)
-- 
2.8.0.rc3.226.g39d4020



From briannorris at chromium.org  Thu May 12 15:43:03 2016
From: briannorris at chromium.org (Brian Norris)
Date: Thu, 12 May 2016 15:43:03 -0700
Subject: [PATCH 1/4] phy: rockchip-emmc: give DLL some extra time to be ready
Message-ID: <1463092986-61777-1-git-send-email-briannorris@chromium.org>

From: Shawn Lin <shawn.lin at rock-chips.com>

According to the databook, 10.2us is the max time for dll to be ready to
work. However in testing, some chips need 20us for dll to be ready. This
patch adds some extra margin for dllrdy to be ready, fixing our
-ETIMEDOUT issues.

Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
Signed-off-by: Brian Norris <briannorris at chromium.org>
---
 drivers/phy/phy-rockchip-emmc.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/phy-rockchip-emmc.c
index 6ebcf3e41c46..48cbe691a889 100644
--- a/drivers/phy/phy-rockchip-emmc.c
+++ b/drivers/phy/phy-rockchip-emmc.c
@@ -119,10 +119,11 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,
 				   PHYCTRL_ENDLL_MASK,
 				   PHYCTRL_ENDLL_SHIFT));
 	/*
-	 * After enable analog DLL circuits, we need extra 10.2us
-	 * for dll to be ready for work.
+	 * After enable analog DLL circuits, we need an extra 10.2us
+	 * for dll to be ready for work. But according to testing, we
+	 * find some chips need more than 25us.
 	 */
-	udelay(11);
+	udelay(30);
 	regmap_read(rk_phy->reg_base,
 		    rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
 		    &dllrdy);
-- 
2.8.0.rc3.226.g39d4020



From briannorris at chromium.org  Thu May 12 15:43:05 2016
From: briannorris at chromium.org (Brian Norris)
Date: Thu, 12 May 2016 15:43:05 -0700
Subject: [PATCH 3/4] phy: rockchip-emmc: configure default output tap delay
In-Reply-To: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
Message-ID: <1463092986-61777-3-git-send-email-briannorris@chromium.org>

The output tap delay controls helps maintain the hold requirements for
eMMC. The exact value is dependent on the SoC and other factors, though
it isn't really an exact science. But the default of 0 is not very good,
as it doesn't give the eMMC much hold time, so let's bump up to 4
(approx 90 degree phase?). If we need to configure this any further
(e.g., based on board or speed factors), we may need to consider a
device tree representation.

Suggested-by: Shawn Lin <shawn.lin at rock-chips.com>
Signed-off-by: Brian Norris <briannorris at chromium.org>
---
 drivers/phy/phy-rockchip-emmc.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/phy-rockchip-emmc.c
index 5641dede32f6..f94d3a6587ed 100644
--- a/drivers/phy/phy-rockchip-emmc.c
+++ b/drivers/phy/phy-rockchip-emmc.c
@@ -69,6 +69,11 @@
 #define PHYCTRL_DR_66OHM	0x2
 #define PHYCTRL_DR_100OHM	0x3
 #define PHYCTRL_DR_40OHM	0x4
+#define PHYCTRL_OTAPDLYENA		0x1
+#define PHYCTRL_OTAPDLYENA_MASK		0x1
+#define PHYCTRL_OTAPDLYENA_SHIFT	0xb
+#define PHYCTRL_OTAPDLYSEL_MASK		0xf
+#define PHYCTRL_OTAPDLYSEL_SHIFT	0x7
 
 struct rockchip_emmc_phy {
 	unsigned int	reg_offset;
@@ -181,6 +186,20 @@ static int rockchip_emmc_phy_power_on(struct phy *phy)
 				   PHYCTRL_DR_MASK,
 				   PHYCTRL_DR_SHIFT));
 
+	/* Output tap delay: enable */
+	regmap_write(rk_phy->reg_base,
+		     rk_phy->reg_offset + GRF_EMMCPHY_CON0,
+		     HIWORD_UPDATE(PHYCTRL_OTAPDLYENA,
+				   PHYCTRL_OTAPDLYENA_MASK,
+				   PHYCTRL_OTAPDLYENA_SHIFT));
+
+	/* Output tap delay */
+	regmap_write(rk_phy->reg_base,
+		     rk_phy->reg_offset + GRF_EMMCPHY_CON0,
+		     HIWORD_UPDATE(4,
+				   PHYCTRL_OTAPDLYSEL_MASK,
+				   PHYCTRL_OTAPDLYSEL_SHIFT));
+
 	/* Power up emmc phy analog blocks */
 	ret = rockchip_emmc_phy_power(rk_phy, PHYCTRL_PDB_PWR_ON);
 	if (ret)
-- 
2.8.0.rc3.226.g39d4020



From briannorris at chromium.org  Thu May 12 15:43:06 2016
From: briannorris at chromium.org (Brian Norris)
Date: Thu, 12 May 2016 15:43:06 -0700
Subject: [PATCH 4/4] phy: rockchip-emmc: reindent the register definitions
In-Reply-To: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
Message-ID: <1463092986-61777-4-git-send-email-briannorris@chromium.org>

Some of the spacing was wrong (spaces instead of tabs), and due to
longer entries added later, the columns weren't aligned. Let's get
everything consistent.

Signed-off-by: Brian Norris <briannorris at chromium.org>
---
 drivers/phy/phy-rockchip-emmc.c | 76 ++++++++++++++++++++---------------------
 1 file changed, 38 insertions(+), 38 deletions(-)

diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/phy-rockchip-emmc.c
index f94d3a6587ed..c27ca2b39dfe 100644
--- a/drivers/phy/phy-rockchip-emmc.c
+++ b/drivers/phy/phy-rockchip-emmc.c
@@ -31,44 +31,44 @@
 		((val) << (shift) | (mask) << ((shift) + 16))
 
 /* Register definition */
-#define GRF_EMMCPHY_CON0	0x0
-#define GRF_EMMCPHY_CON1	0x4
-#define GRF_EMMCPHY_CON2	0x8
-#define GRF_EMMCPHY_CON3	0xc
-#define GRF_EMMCPHY_CON4	0x10
-#define GRF_EMMCPHY_CON5	0x14
-#define GRF_EMMCPHY_CON6	0x18
-#define GRF_EMMCPHY_STATUS	0x20
-
-#define PHYCTRL_PDB_MASK	0x1
-#define PHYCTRL_PDB_SHIFT	0x0
-#define PHYCTRL_PDB_PWR_ON	0x1
-#define PHYCTRL_PDB_PWR_OFF	0x0
-#define PHYCTRL_ENDLL_MASK	0x1
-#define PHYCTRL_ENDLL_SHIFT     0x1
-#define PHYCTRL_ENDLL_ENABLE	0x1
-#define PHYCTRL_ENDLL_DISABLE	0x0
-#define PHYCTRL_CALDONE_MASK	0x1
-#define PHYCTRL_CALDONE_SHIFT   0x6
-#define PHYCTRL_CALDONE_DONE	0x1
-#define PHYCTRL_CALDONE_GOING	0x0
-#define PHYCTRL_DLLRDY_MASK	0x1
-#define PHYCTRL_DLLRDY_SHIFT	0x5
-#define PHYCTRL_DLLRDY_DONE	0x1
-#define PHYCTRL_DLLRDY_GOING	0x0
-#define PHYCTRL_FREQSEL_200M	0x0
-#define PHYCTRL_FREQSEL_50M	0x1
-#define PHYCTRL_FREQSEL_100M	0x2
-#define PHYCTRL_FREQSEL_150M	0x3
-#define PHYCTRL_FREQSEL_MASK	0x3
-#define PHYCTRL_FREQSEL_SHIFT	0xc
-#define PHYCTRL_DR_MASK		0x7
-#define PHYCTRL_DR_SHIFT	0x4
-#define PHYCTRL_DR_50OHM	0x0
-#define PHYCTRL_DR_33OHM	0x1
-#define PHYCTRL_DR_66OHM	0x2
-#define PHYCTRL_DR_100OHM	0x3
-#define PHYCTRL_DR_40OHM	0x4
+#define GRF_EMMCPHY_CON0		0x0
+#define GRF_EMMCPHY_CON1		0x4
+#define GRF_EMMCPHY_CON2		0x8
+#define GRF_EMMCPHY_CON3		0xc
+#define GRF_EMMCPHY_CON4		0x10
+#define GRF_EMMCPHY_CON5		0x14
+#define GRF_EMMCPHY_CON6		0x18
+#define GRF_EMMCPHY_STATUS		0x20
+
+#define PHYCTRL_PDB_MASK		0x1
+#define PHYCTRL_PDB_SHIFT		0x0
+#define PHYCTRL_PDB_PWR_ON		0x1
+#define PHYCTRL_PDB_PWR_OFF		0x0
+#define PHYCTRL_ENDLL_MASK		0x1
+#define PHYCTRL_ENDLL_SHIFT		0x1
+#define PHYCTRL_ENDLL_ENABLE		0x1
+#define PHYCTRL_ENDLL_DISABLE		0x0
+#define PHYCTRL_CALDONE_MASK		0x1
+#define PHYCTRL_CALDONE_SHIFT		0x6
+#define PHYCTRL_CALDONE_DONE		0x1
+#define PHYCTRL_CALDONE_GOING		0x0
+#define PHYCTRL_DLLRDY_MASK		0x1
+#define PHYCTRL_DLLRDY_SHIFT		0x5
+#define PHYCTRL_DLLRDY_DONE		0x1
+#define PHYCTRL_DLLRDY_GOING		0x0
+#define PHYCTRL_FREQSEL_200M		0x0
+#define PHYCTRL_FREQSEL_50M		0x1
+#define PHYCTRL_FREQSEL_100M		0x2
+#define PHYCTRL_FREQSEL_150M		0x3
+#define PHYCTRL_FREQSEL_MASK		0x3
+#define PHYCTRL_FREQSEL_SHIFT		0xc
+#define PHYCTRL_DR_MASK			0x7
+#define PHYCTRL_DR_SHIFT		0x4
+#define PHYCTRL_DR_50OHM		0x0
+#define PHYCTRL_DR_33OHM		0x1
+#define PHYCTRL_DR_66OHM		0x2
+#define PHYCTRL_DR_100OHM		0x3
+#define PHYCTRL_DR_40OHM		0x4
 #define PHYCTRL_OTAPDLYENA		0x1
 #define PHYCTRL_OTAPDLYENA_MASK		0x1
 #define PHYCTRL_OTAPDLYENA_SHIFT	0xb
-- 
2.8.0.rc3.226.g39d4020



From heiko at sntech.de  Thu May 12 15:52:51 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Fri, 13 May 2016 00:52:51 +0200
Subject: [PATCH v3] mmc: dw_mmc: rockchip: Set the drive phase properly
In-Reply-To: <1463077910-25914-1-git-send-email-dianders@chromium.org>
References: <1463077910-25914-1-git-send-email-dianders@chromium.org>
Message-ID: <2865073.LogD6IIKLp@phil>

Am Donnerstag, 12. Mai 2016, 11:31:50 schrieb Douglas Anderson:

[...]

> In commit 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card
> initialization") we actually started setting this explicitly in the
> kernel, but that commit wasn't quite right and also wasn't quite
> enough.  See <https://patchwork.kernel.org/patch/9085311/> for some
> details.
> 
> Let's explicitly set this phase in dw_mmc.

[...]

> Fixes: 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card
> initialization") Signed-off-by: Douglas Anderson <dianders at chromium.org>
> Reviewed-by: Shawn Lin <shawn.lin at rock-chips.com>

I've tested this patch together with the two clock patches linked above on a 
rk3288-firefly and a rk3288-veyron-jerry. On the firefly tuning still does not 
work (probably really some regulator issue) and on veyron tuning still works 
as expected, so

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

Doug's explanations both in the commit message and the code look sane to me, 
but I don't feel confident enough in my understanding of the matter to 
transform that into a Reviewed-by tag.


Heiko


From eric at anholt.net  Thu May 12 15:58:55 2016
From: eric at anholt.net (Eric Anholt)
Date: Thu, 12 May 2016 15:58:55 -0700
Subject: [PATCH 0/4] bcm2835: add thermal driver
In-Reply-To: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
References: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <87ziruano0.fsf@eliezer.anholt.net>

kernel at martin.sperl.org writes:

> From: Martin Sperl <kernel at martin.sperl.org>
>
> Add thermal driver for the bcm2835 SOC.
>
> Right now this driver does not set up the thermal device
> itself, but relies on the fact that the firmware is setting
> the device up correctly.
>
> Also it is currently only reading from the register-set.
>
> The driver also exposes the registers via debugfs.

I had looked through before and decided that the FW was turning the
tempsens clock on and off at runtime so we'd have to go through it for
checking temperature.  Looking at it now, though, it keeps the clock
running the entire time and just does a read periodically.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160512/7863f378/attachment.sig>

From alcooperx at gmail.com  Thu May 12 16:02:36 2016
From: alcooperx at gmail.com (Alan Cooper)
Date: Thu, 12 May 2016 19:02:36 -0400
Subject: [PATCH 3/6] dt-bindings: mtu3: add devicetree bindings
In-Reply-To: <1463037844.11651.118.camel@mhfsdcap03>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462868614-20602-4-git-send-email-chunfeng.yun@mediatek.com>
 <20160511145409.GA23042@rob-hp-laptop>
 <1463037844.11651.118.camel@mhfsdcap03>
Message-ID: <CAOGqxeUYEGKq5yhHbgcjPZtY06ZfDp2iCLZDqS3uyfCW523B4w@mail.gmail.com>

On Thu, May 12, 2016 at 3:24 AM, chunfeng yun <chunfeng.yun at mediatek.com> wrote:
>> > + - mediatek,enable-manual-drd : supports manual dual-role switch by sysfs
>> > +   interface; only used when receptacle is TYPE-A and also wants to support
>> > +   dual-role mode.
>>
>> sysfs is a Linux detail that doesn't apply to the binding. Does the
>> property mean "the IP block supports or doesn't support switching"  or
>> "I want to enable switching feature". Only the former belongs in DT.
>>
> It is the former case, and has little relation with sysfs interface.
> I will modify it later, sorry for my unclear description.

Could the property name be just "enable-manual-drd" instead of
"mediatek,enable-manual-drd"? I expect to have to add this
functionality to our USB driver in the near future.


From eric at anholt.net  Thu May 12 16:03:23 2016
From: eric at anholt.net (Eric Anholt)
Date: Thu, 12 May 2016 16:03:23 -0700
Subject: [PATCH 1/4] dt: bindings: add thermal device driver for bcm2835
In-Reply-To: <1463063738-11506-2-git-send-email-kernel@martin.sperl.org>
References: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
 <1463063738-11506-2-git-send-email-kernel@martin.sperl.org>
Message-ID: <87wpmyangk.fsf@eliezer.anholt.net>

kernel at martin.sperl.org writes:

> From: Martin Sperl <kernel at martin.sperl.org>
>
> Add documentation for bcm2835 SOC thermal sensor.
>
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
> ---
>  .../devicetree/bindings/thermal/bcm2835-thermal.txt      | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/thermal/bcm2835-thermal.txt
>
> diff --git a/Documentation/devicetree/bindings/thermal/bcm2835-thermal.txt b/Documentation/devicetree/bindings/thermal/bcm2835-thermal.txt
> new file mode 100644
> index 0000000..607519a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/bcm2835-thermal.txt

There's a naming convention for the BCM DT bindings these days where you
basically name it after the compatible string, so this file should be
moved to "brcm,bcm2835-thermal.txt" (yes, even though it's inconsistent
with the rest of the files in the directory).

> @@ -0,0 +1,16 @@
> +Binding for Thermal Sensor driver for BCM2835 SoCs.
> +
> +Required parameters:
> +-------------------
> +
> +compatible : 	should be: "brcm,bcm2835-thermal"

Optional: change to 'should be: "brcm,bcm2835-thermal" or
"brcm,bcm2837-thermal"' (see next review for explanation).

I would also drop the space before the colons on the parameters, but as
long as the filename is changed this patch is:

Acked-by: Eric Anholt <eric at anholt.net>

> +reg :		Address range of the thermal registers.
> +clocks : 	Phandle of the clock used by the thermal sensor.
> +
> +Example:
> +
> +thermal: thermal at 0x7e212000 {
> +	compatible = "brcm,bcm2835-thermal";
> +	reg = <0x7e212000 0x8>;
> +	clocks = <&clocks BCM2835_CLOCK_TSENS>;
> +};
> -- 
> 2.1.4
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160512/f512b792/attachment.sig>

From briannorris at chromium.org  Thu May 12 16:10:23 2016
From: briannorris at chromium.org (Brian Norris)
Date: Thu, 12 May 2016 16:10:23 -0700
Subject: [PATCH 2/2] clk: rockchip: fix the rk3399 sdmmc sample shift
In-Reply-To: <1463076197-15900-2-git-send-email-dianders@chromium.org>
References: <1463076197-15900-1-git-send-email-dianders@chromium.org>
 <1463076197-15900-2-git-send-email-dianders@chromium.org>
Message-ID: <20160512231023.GA63308@google.com>

On Thu, May 12, 2016 at 11:03:17AM -0700, Doug Anderson wrote:
> Just like every other Rockhip device, the MMC "_sample" clocks should
> have a shift of 0, not a shift of 1.  The rk3399 TRM agrees.  Presumably
> these values were set to 0 because of a typo.

I'll semi-disagree about the TRM: the TRM doesn't seem to agree with
itself, so it sometimes agrees with you and sometimes doesn't :)

On page 79 of the 2nd (?) book, it looks like {SDMMC,SDIO}_CON{0,}[2:1]
are {drv,sample}_degree. But on page 208 of the 1st book, those are put
at bits [1:0].

Perhaps we can get a straight answer from Rockchip though.

Brian

> Things _sorta_ would have worked with the incorrect sample phase shift
> because of the register layout but wouldn't have been ideal and we would
> have skipped lots of phases.  Also: we would never actually enabled the
> fine delay unless we happened to have 128 or more delay elements.
> 
> This is expected behavior before this patch:
> * Try to set:     0 degrees +   1 delay elements
>   Actually get:   0 degrees +   0 delay elements
> * Try to set:    90 degrees +   0 delay elements
>   Actually get: 180 degrees +   0 delay elements
> * Try to set:   180 degrees +   0 delay elements
>   Actually get:   0 degrees +   0 delay elements
> * Try to set:   270 degrees +   0 delay elements
>   Actually get: 180 degrees +   0 delay elements
> * Try to set:     0 degrees + 129 delay elements
>   Actually get:   0 degrees +   2 delay elements
> * Try to set:   180 degrees + 129 delay elements
>   Actually get:   0 degrees +   3 delay elements
> * Try to set:     0 degrees + 130 delay elements
>   Actually get:   0 degrees +   4 delay elements
> 
> I verified that old code had a problem by turning on debug printouts and
> seeing that the old code would report this for one SD card I had:
>   Good phase range 347-101 (115 len)
>   Good phase range 202-326 (125 len)
> 
> After my fix, it went down to one big good range for the same card.
> This is more expected:
>   Good phase range 189-1 (173 len)
>   Good phase range 82-85 (4 len)
>   Good phase range 166-168 (3 len)
> 
> Signed-off-by: Douglas Anderson <dianders at chromium.org>
> ---
>  drivers/clk/rockchip/clk-rk3399.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
> index 291543f52caa..14ff3e109e1e 100644
> --- a/drivers/clk/rockchip/clk-rk3399.c
> +++ b/drivers/clk/rockchip/clk-rk3399.c
> @@ -895,10 +895,10 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
>  			RK3399_CLKGATE_CON(6), 1, GFLAGS),
>  
>  	MMC(SCLK_SDMMC_DRV,     "sdmmc_drv",    "clk_sdmmc", RK3399_SDMMC_CON0, 1),
> -	MMC(SCLK_SDMMC_SAMPLE,  "sdmmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 1),
> +	MMC(SCLK_SDMMC_SAMPLE,  "sdmmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 0),
>  
>  	MMC(SCLK_SDIO_DRV,      "sdio_drv",    "clk_sdio",  RK3399_SDIO_CON0,  1),
> -	MMC(SCLK_SDIO_SAMPLE,   "sdio_sample", "clk_sdio",  RK3399_SDIO_CON1,  1),
> +	MMC(SCLK_SDIO_SAMPLE,   "sdio_sample", "clk_sdio",  RK3399_SDIO_CON1,  0),
>  
>  	/* pcie */
>  	COMPOSITE(SCLK_PCIE_PM, "clk_pcie_pm", mux_pll_src_cpll_gpll_npll_24m_p, 0,


From eric at anholt.net  Thu May 12 16:23:46 2016
From: eric at anholt.net (Eric Anholt)
Date: Thu, 12 May 2016 16:23:46 -0700
Subject: [PATCH 2/4] thermal: bcm2835: add thermal driver for bcm2835 soc
In-Reply-To: <1463063738-11506-3-git-send-email-kernel@martin.sperl.org>
References: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
 <1463063738-11506-3-git-send-email-kernel@martin.sperl.org>
Message-ID: <87shxmamil.fsf@eliezer.anholt.net>

kernel at martin.sperl.org writes:

> From: Martin Sperl <kernel at martin.sperl.org>
>
> Add basic thermal driver for bcm2835 SOC.
>
> This driver currently relies on the firmware setting up the
> tsense HW block and does not set it up itself.
>
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
> ---
>  drivers/thermal/Kconfig               |   5 +
>  drivers/thermal/Makefile              |   1 +
>  drivers/thermal/bcm/Kconfig           |   4 +
>  drivers/thermal/bcm/Makefile          |   1 +
>  drivers/thermal/bcm/bcm2835_thermal.c | 205 ++++++++++++++++++++++++++++++++++
>  5 files changed, 216 insertions(+)
>  create mode 100644 drivers/thermal/bcm/Kconfig
>  create mode 100644 drivers/thermal/bcm/Makefile
>  create mode 100644 drivers/thermal/bcm/bcm2835_thermal.c
>

> diff --git a/drivers/thermal/bcm/bcm2835_thermal.c b/drivers/thermal/bcm/bcm2835_thermal.c
> new file mode 100644
> index 0000000..a1fdc84
> --- /dev/null
> +++ b/drivers/thermal/bcm/bcm2835_thermal.c
> @@ -0,0 +1,205 @@
> +/*
> + * Driver for Broadcom BCM2835 soc temperature sensor
> + *
> + * Copyright (C) 2015 Martin Sperl
> + *
> + * 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.h>
> +#include <linux/debugfs.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/thermal.h>
> +
> +#define BCM2835_TS_TSENSCTL			0x00
> +#define BCM2835_TS_TSENSSTAT			0x04
> +
> +#define BCM2835_TS_TSENSCTL_PRWDW		BIT(0)
> +#define BCM2835_TS_TSENSCTL_RSTB		BIT(1)
> +#define BCM2835_TS_TSENSCTL_CTRL		BIT(0)
> +#define BCM2835_TS_TSENSCTL_EN_INT		BIT(0)
> +#define BCM2835_TS_TSENSCTL_DIRECT		BIT(0)
> +#define BCM2835_TS_TSENSCTL_CLR_INT		BIT(0)

Bad bit definitions here.  CTRL is a field from 2:4, en_int is bit 5,
direct is bit 6, clr is bit 7.

> +#define BCM2835_TS_TSENSCTL_THOLD_SHIFT		8
> +#define BCM2835_TS_TSENSCTL_THOLD_BITS		10
> +#define BCM2835_TS_TSENSCTL_THOLD_MASK		     \
> +	GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS +     \
> +		BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \
> +		BCM2835_TS_TSENSCTL_THOLD_SHIFT)
> +#define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT	18
> +#define BCM2835_TS_TSENSCTL_RSTDELAY_BITS	8
> +#define BCM2835_TS_TSENSCTL_REGULEN		BIT(26)
> +
> +#define BCM2835_TS_TSENSSTAT_DATA_BITS		10
> +#define BCM2835_TS_TSENSSTAT_DATA_SHIFT		0
> +#define BCM2835_TS_TSENSSTAT_DATA_MASK		     \
> +	GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS +     \
> +		BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \
> +		BCM2835_TS_TSENSSTAT_DATA_SHIFT)

Optional: Just use GENMASK with the bit numbers and drop the BITS/SHIFT
definitions, since they aren't used.

> +#define BCM2835_TS_TSENSSTAT_VALID		BIT(10)
> +#define BCM2835_TS_TSENSSTAT_INTERRUPT		BIT(11)
> +
> +/* empirical linear approximation for conversion to temperature */
> +#define BCM2835_TS_VALUE_OFFSET			407000
> +#define BCM2835_TS_VALUE_SLOPE			-538

This matches for pi1/2.  However, apparently on Pi3 the sensor was
reporting low so the firmware adjusts the answer it up by 5C.  Not
required, but it would be nice to have a brcm,bcm2837-thermal compatible
string that increased the offset by 5C, so that we can enable this
driver right away for pi3.

> +struct bcm2835_thermal_data {
> +	void __iomem *regs;
> +	struct clk *clk;
> +	struct dentry *debugfsdir;
> +};
> +
> +static int bcm2835_thermal_get_temp(struct thermal_zone_device *tz,
> +				    int *temp)
> +{
> +	struct bcm2835_thermal_data *data = tz->devdata;
> +	u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT);
> +
> +	/* mask the relevant bits */
> +	val &= BCM2835_TS_TSENSSTAT_DATA_MASK;
> +
> +	/* linear approximation */
> +	*temp = BCM2835_TS_VALUE_OFFSET +
> +		(val * BCM2835_TS_VALUE_SLOPE);
> +
> +	return 0;
> +}

You need to check if the VALID bit is set and do something appropriate
(I suspect just throw an error) if unset.

> +	/*
> +	 * for now we assume the firmware sets up the device,
> +	 * so we will not write to ctl, we just prepare the clock
> +	 */
> +	clk_prepare_enable(data->clk);

Optional setup: given the values you can read out of tsensctl set up by
the firmware currently, if at boot RSTB isn't set, then set the values
except for rstb in one writel, then OR in rstb in in the next writel.
Then the driver should be ready in case we ever get a firmware that does
less work.

Thanks for writing the driver!  With the bit definition fix and the
VALID check, I'll be ready to add a reviewed-by.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160512/8eb260e4/attachment-0001.sig>

From eric at anholt.net  Thu May 12 16:24:34 2016
From: eric at anholt.net (Eric Anholt)
Date: Thu, 12 May 2016 16:24:34 -0700
Subject: [PATCH 3/4] ARM: bcm2835: add thermal node to device-tree of
 bcm283x
In-Reply-To: <1463063738-11506-4-git-send-email-kernel@martin.sperl.org>
References: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
 <1463063738-11506-4-git-send-email-kernel@martin.sperl.org>
Message-ID: <87posqamh9.fsf@eliezer.anholt.net>

kernel at martin.sperl.org writes:

> From: Martin Sperl <kernel at martin.sperl.org>
>
> Add the node for the thermal sensor of the bcm2835-soc
> to the device tree.
>
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
> ---
>  arch/arm/boot/dts/bcm283x.dtsi | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
> index 9db9d97..525f1f2 100644
> --- a/arch/arm/boot/dts/bcm283x.dtsi
> +++ b/arch/arm/boot/dts/bcm283x.dtsi
> @@ -159,6 +159,12 @@
>  			status = "disabled";
>  		};
>  
> +		thermal: thermal at 0x7e212000 {
> +			compatible = "brcm,bcm2835-thermal";
> +			reg = <0x7e212000 0x8>;
> +			clocks = <&clocks BCM2835_CLOCK_TSENS>;
> +		};
> +

You could drop the "thermal: " here since nothing refers to it.  Either
way,

Reviewed-by: Eric Anholt <eric at anholt.net>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160512/05f0c6a6/attachment.sig>

From eric at anholt.net  Thu May 12 16:26:13 2016
From: eric at anholt.net (Eric Anholt)
Date: Thu, 12 May 2016 16:26:13 -0700
Subject: [PATCH 4/4] ARM: bcm2835: add thermal driver to default_config
In-Reply-To: <1463063738-11506-5-git-send-email-kernel@martin.sperl.org>
References: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
 <1463063738-11506-5-git-send-email-kernel@martin.sperl.org>
Message-ID: <87lh3eamei.fsf@eliezer.anholt.net>

kernel at martin.sperl.org writes:

> From: Martin Sperl <kernel at martin.sperl.org>
>
> Add the thermal driver to list of compiled modules
> in the default config for bcm2835.
>
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
> ---
>  arch/arm/configs/bcm2835_defconfig | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
> index 29a44bd..634e07e 100644
> --- a/arch/arm/configs/bcm2835_defconfig
> +++ b/arch/arm/configs/bcm2835_defconfig
> @@ -71,6 +71,8 @@ CONFIG_SPI_BCM2835=y
>  CONFIG_SPI_BCM2835AUX=y
>  CONFIG_GPIO_SYSFS=y
>  # CONFIG_HWMON is not set
> +CONFIG_THERMAL=y
> +CONFIG_BCM2835_THERMAL=y
>  CONFIG_WATCHDOG=y
>  CONFIG_BCM2835_WDT=y
>  CONFIG_FB=y
> -- 
> 2.1.4

It would be nice to see multi_v7_defconfig changed, too, since that's
what we expect people to be actually using

This patch is: Reviewed-by: Eric Anholt <eric at anholt.net>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160512/453aaf3a/attachment.sig>

From sboyd at codeaurora.org  Thu May 12 16:33:38 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Thu, 12 May 2016 16:33:38 -0700
Subject: [PATCH 2/4] drvers/clk: Support fourth generation Aspeed SoCs
In-Reply-To: <CACPK8Xfq=Pfy=7GYuS7LJs-CFJOimBUoHA=Y6NHb4=DRcOnvfQ@mail.gmail.com>
References: <1462797111-14271-1-git-send-email-joel@jms.id.au>
 <1462797111-14271-3-git-send-email-joel@jms.id.au>
 <20160509224953.GZ3492@codeaurora.org>
 <CACPK8Xfq=Pfy=7GYuS7LJs-CFJOimBUoHA=Y6NHb4=DRcOnvfQ@mail.gmail.com>
Message-ID: <20160512233338.GM3492@codeaurora.org>

On 05/10, Joel Stanley wrote:
> On Tue, May 10, 2016 at 8:19 AM, Stephen Boyd <sboyd at codeaurora.org> wrote:
> > Please write a proper clk driver that sets clkin to be the parent
> > of this clk registered here and then calculates the frequency
> > based on the parent clk rate and the strapping registers via the
> > recalc rate callback.
> 
> After a few goes I understood what you meant here.
> 
> Is the pclk part okay? I modified the pclk part use a fixed factor
> clock instead of the fixed clock, so I could drop the pclk_get_rate
> call below.

Sorry what's the pclk part? Using a fixed factor is OK, as long
as we don't have to call clk_get_rate() in this driver it's a
better design.

> 
> > Also please move this to a platform driver
> > instead of using CLK_OF_DECLARE assuming this isn't required for
> > any timers in the system.
> 
> Can you clarify here? We do use the rate of pclk (the apb clock) in
> the clocksource driver to calculate our count_per_tick value.

Ok. I was hoping that this wasn't providing any clks required in
the timer driver. Even if that's true, we could just register the
part of the clk tree that needs to be ready for the timer from
CLK_OF_DECLARE() and then register the other clks from a regular
platform driver. Some people have already started doing this, so
there are some examples around (clk/nxp/clk-lpc18xx-creg.c is one
example).

> > Following on Rob's comment, please combine this into one driver
> > instead of having different DT nodes for different clks that are
> > all really part of one clock controller hw block.
> 
> Ok, I have had a go at this. In our case the clock registers are part
> of the "SCU" IP; a collection of disparate functions that happen to
> include clock control. Is syscon the right thing to use here?
> 
> regmap = syscon_regmap_lookup_by_compatible("aspeed,ast2400-syscon-scu");
> ret = regmap_read(hpll->regmap, 0x70, &reg);
> 

In that case I don't have a problem with a toplevel MFD node in
DT with a child node for the clk part and a child node for other
logical driver parts. Or it could all be one MFD driver and node
that knows to add a clk device as a child of the MFD purely in
software so that we can fork control of the clk part over to the
drivers/clk directory. If you have the clk driver attach to some
child device then you can always get the regmap from the parent
MFD via the dev->parent pointer.

Maybe Rob can chime in here too with the proper design, because
I've seen both styles.

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


From sboyd at codeaurora.org  Thu May 12 16:39:35 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Thu, 12 May 2016 16:39:35 -0700
Subject: [PATCHv2 00/28] ARM: OMAP2+: hwmod module clock type support
In-Reply-To: <1460632097-25727-1-git-send-email-t-kristo@ti.com>
References: <1460632097-25727-1-git-send-email-t-kristo@ti.com>
Message-ID: <20160512233935.GN3492@codeaurora.org>

On 04/14, Tero Kristo wrote:
> Hi,
> 
> v2 contains following changes in comparison to v1:
> 
> - Patch ordering changed a bit, clk/ti, mach-omap2, dts patches are now
>   mostly grouped together, with the exception of the introduction of
>   clock helper API, which is needed by everything else. Please note
>   that the ordering must be preserved between mach-omap2/clk-driver/dts
>   to avoid boot problems.
> - Dropped hwmod data removal patches for now, this allows booting with
>   either new or old DTS data.
> - Fixed a typo in the hwmod clock driver timeout handling, the comparison
>   for timeout against ktime_us_delta was wrong causing too short
>   timeouts, this was apparent with cpuidle enabled on OMAP4
> - Added patch #6 to fetch hwmod main clock based on the hwmod name itself,
>   if found, ignore main_clk / clkctrl setup for the hwmod
> - Added patch #7 to fix issue in omap2 timer caused by patch #6, with
>   dynamic parsing of main clock, the hwmod must be setup before attempting
>   to access main_clk.

What's the general design goal of this series? This cover letter
is more like a change and test log instead of an overall argument
for why the series should be merged so I'm left to piecing
together the commit text from the 28 different patches. I suspect
it's to get rid of DT_CLK macros and do something with hwmod in a
more generic way, but that's all I got.

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


From heiko at sntech.de  Thu May 12 16:41:11 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Fri, 13 May 2016 01:41:11 +0200
Subject: [PATCH 1/2] Revert "clk: rockchip: reset init state before mmc
 card initialization"
In-Reply-To: <1463076197-15900-1-git-send-email-dianders@chromium.org>
References: <1463076197-15900-1-git-send-email-dianders@chromium.org>
Message-ID: <2083095.luTHhmZ9EO@phil>

Am Donnerstag, 12. Mai 2016, 11:03:16 schrieb Douglas Anderson:

Not sure what the policy is for revert-subjects in the clock-tree, but I 
guess

clk: rockchip: Revert "reset init state before mmc card initialization"

might look nicer?

> This reverts commit 7a03fe6f48f3 ("clk: rockchip: reset init state
> before mmc card initialization").

I've tested these two patches together with the dw_mmc one and everything 
that worked before still works (tuning on veyron-jerry) and everything that 
didn't work still doesn't work (tuning on firefly [likely a regulator issue]).

And re-checking the code against the TRM I now also see the mask that is to 
short (1 bit in the code vs. the actual 2 bits described in the manual)

[...]

> 1. Just this revert: likely will fix rk3288-veyron eMMC on some devices
>    + other cases; might break someone with a strange bootloader that
>    sets the phase to 0 or one that uses delay elements (pretty
>    unpredicable what would happen in that case).
> 2. Just dw_mmc patch: fixes everyone.  Effectly the dw_mmc patch will
>    totally override the broken patch and fix everything.
> 3. Both patches: fixes everyone.  Once dw_mmc is initting properly then
>    any defaults from the clock code doesn't mattery.

I'm still trying to make up my mind on how to proceed - aka in which order 
patches should get picked up.

Going with the "if it isn't upstream it doesn't exist" mantra Rob wrote 
somewhere some days ago, taking this revert should not hurt anything, as all 
the non-veyron devices currently don't support any tuning at all.

So I'd think except for the issue Shawn was originally trying to fix (for 
some non-mainline board?) it should be possible to take this patch any time 
independently of the dw_mmc part.

If Stephen or Mike want to do this directly, this is
Reviewed-by: Heiko Stuebner <heiko at sntech.de>

> Fixes: 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card
> initialization")
> Signed-off-by: Douglas Anderson <dianders at chromium.org>




From shawn.lin at rock-chips.com  Thu May 12 16:47:02 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Fri, 13 May 2016 07:47:02 +0800
Subject: [PATCH 2/2] clk: rockchip: fix the rk3399 sdmmc sample shift
In-Reply-To: <20160512231023.GA63308@google.com>
References: <1463076197-15900-1-git-send-email-dianders@chromium.org>
 <1463076197-15900-2-git-send-email-dianders@chromium.org>
 <20160512231023.GA63308@google.com>
Message-ID: <84673e7c-dd64-b2ca-5c7c-5c7f34d239d8@rock-chips.com>

? 2016/5/13 7:10, Brian Norris ??:
> On Thu, May 12, 2016 at 11:03:17AM -0700, Doug Anderson wrote:
>> Just like every other Rockhip device, the MMC "_sample" clocks should
>> have a shift of 0, not a shift of 1.  The rk3399 TRM agrees.  Presumably
>> these values were set to 0 because of a typo.
>
> I'll semi-disagree about the TRM: the TRM doesn't seem to agree with
> itself, so it sometimes agrees with you and sometimes doesn't :)
>
> On page 79 of the 2nd (?) book, it looks like {SDMMC,SDIO}_CON{0,}[2:1]
> are {drv,sample}_degree. But on page 208 of the 1st book, those are put
> at bits [1:0].
>


Please refer to Mobile Strorage Host Controller section for anything
about sdmmc/sdio. So shift should be 1.

Sometime I also get bothered to address it. Anyway, I will always keep
a eye on it from now on.....

> Perhaps we can get a straight answer from Rockchip though.
>
> Brian
>
>> Things _sorta_ would have worked with the incorrect sample phase shift
>> because of the register layout but wouldn't have been ideal and we would
>> have skipped lots of phases.  Also: we would never actually enabled the
>> fine delay unless we happened to have 128 or more delay elements.
>>
>> This is expected behavior before this patch:
>> * Try to set:     0 degrees +   1 delay elements
>>   Actually get:   0 degrees +   0 delay elements
>> * Try to set:    90 degrees +   0 delay elements
>>   Actually get: 180 degrees +   0 delay elements
>> * Try to set:   180 degrees +   0 delay elements
>>   Actually get:   0 degrees +   0 delay elements
>> * Try to set:   270 degrees +   0 delay elements
>>   Actually get: 180 degrees +   0 delay elements
>> * Try to set:     0 degrees + 129 delay elements
>>   Actually get:   0 degrees +   2 delay elements
>> * Try to set:   180 degrees + 129 delay elements
>>   Actually get:   0 degrees +   3 delay elements
>> * Try to set:     0 degrees + 130 delay elements
>>   Actually get:   0 degrees +   4 delay elements
>>
>> I verified that old code had a problem by turning on debug printouts and
>> seeing that the old code would report this for one SD card I had:
>>   Good phase range 347-101 (115 len)
>>   Good phase range 202-326 (125 len)
>>
>> After my fix, it went down to one big good range for the same card.
>> This is more expected:
>>   Good phase range 189-1 (173 len)
>>   Good phase range 82-85 (4 len)
>>   Good phase range 166-168 (3 len)
>>
>> Signed-off-by: Douglas Anderson <dianders at chromium.org>
>> ---
>>  drivers/clk/rockchip/clk-rk3399.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
>> index 291543f52caa..14ff3e109e1e 100644
>> --- a/drivers/clk/rockchip/clk-rk3399.c
>> +++ b/drivers/clk/rockchip/clk-rk3399.c
>> @@ -895,10 +895,10 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
>>  			RK3399_CLKGATE_CON(6), 1, GFLAGS),
>>
>>  	MMC(SCLK_SDMMC_DRV,     "sdmmc_drv",    "clk_sdmmc", RK3399_SDMMC_CON0, 1),
>> -	MMC(SCLK_SDMMC_SAMPLE,  "sdmmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 1),
>> +	MMC(SCLK_SDMMC_SAMPLE,  "sdmmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 0),
>>
>>  	MMC(SCLK_SDIO_DRV,      "sdio_drv",    "clk_sdio",  RK3399_SDIO_CON0,  1),
>> -	MMC(SCLK_SDIO_SAMPLE,   "sdio_sample", "clk_sdio",  RK3399_SDIO_CON1,  1),
>> +	MMC(SCLK_SDIO_SAMPLE,   "sdio_sample", "clk_sdio",  RK3399_SDIO_CON1,  0),
>>
>>  	/* pcie */
>>  	COMPOSITE(SCLK_PCIE_PM, "clk_pcie_pm", mux_pll_src_cpll_gpll_npll_24m_p, 0,
>
>
>


-- 
Best Regards
Shawn Lin



From shawn.lin at rock-chips.com  Thu May 12 17:19:54 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Fri, 13 May 2016 08:19:54 +0800
Subject: [PATCH 1/2] Revert "clk: rockchip: reset init state before mmc
 card initialization"
In-Reply-To: <1463076197-15900-1-git-send-email-dianders@chromium.org>
References: <1463076197-15900-1-git-send-email-dianders@chromium.org>
Message-ID: <78aecdae-7b9b-d687-a8d3-44f476ddd73e@rock-chips.com>

On 2016/5/13 2:03, Douglas Anderson wrote:
> This reverts commit 7a03fe6f48f3 ("clk: rockchip: reset init state
> before mmc card initialization").
>
> Though not totally obvious from the commit message nor from the source
> code, that commit appears to be trying to reset the "_drv" MMC clocks to
> 90 degrees (note that the "_sample" MMC clocks have a shift of 0 so are
> not touched).

Hrrr...my fault, anyway it should be reverted in case of new register
layout in the future.

Have you found the difference of sample shift between rk3399 and former
Socs?  Per Mobile Storage Host Controller section, it migrate from
bit[1:0] to bit[2:1]...

Acutally there are three register layouts about sdmmc/sdio tuning
stuff I found. Although just two types were upstreamed, it still
caused difficulty. With your patch for dw_mmc to explictly assign
dr_phase, we keep the phase policy better to be unstood and traced.

Again sorry for commit 7a03fe6f48!

>
> The major problem here is that it doesn't properly reset things.  The
> phase is a two bit field and the commit only touches one of the two
> bits.  Thus the commit had the following affect:
> - phase   0  => phase  90
> - phase  90  => phase  90
> - phase 180  => phase 270
> - phase 270  => phase 270
>
> Things get even weirder if you happen to have a bootloader that was
> actually using delay elements (should be no reason to, but you never
> know), since those are additional bits that weren't touched by the
> original patch.
>
> This is unlikely to be what we actually want.  Checking on rk3288-veyron
> devices, I can see that the bootloader leaves these clocks as:
> - emmc:  phase 180
> - sdmmc: phase 90
> - sdio0: phase 90
>
> Thus on rk3288-veyron devices the commit we're reverting had the effect
> of changing the eMMC clock to phase 270.  This probably explains the
> scattered reports I've heard of eMMC devices not working on some veyron
> devices when using the upstream kernel.
>
> The original commit was presumably made because previously the kernel
> didn't touch the "_drv" phase at all and relied on whatever value was
> there when the kernel started.  If someone was using a bootloader that
> touched the "_drv" phase then, indeed, we should have code in the kernel
> to fix that.  ...and also, to get ideal timings, we should also have the
> kernel change the phase depending on the speed mode.  In fact, that's
> the subject of a recent patch I posted at
> <https://patchwork.kernel.org/patch/9075141/>.
>
> Ideally, we should take both the patch posted to dw_mmc and this
> revert.  Since those will likely go through different trees, here I
> describe behavior with the combos:
>
> 1. Just this revert: likely will fix rk3288-veyron eMMC on some devices
>    + other cases; might break someone with a strange bootloader that
>    sets the phase to 0 or one that uses delay elements (pretty
>    unpredicable what would happen in that case).
> 2. Just dw_mmc patch: fixes everyone.  Effectly the dw_mmc patch will
>    totally override the broken patch and fix everything.
> 3. Both patches: fixes everyone.  Once dw_mmc is initting properly then
>    any defaults from the clock code doesn't mattery.
>
> Fixes: 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card initialization")
> Signed-off-by: Douglas Anderson <dianders at chromium.org>
> ---
>  drivers/clk/rockchip/clk-mmc-phase.c | 11 -----------
>  1 file changed, 11 deletions(-)
>
> diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
> index bc856f21f6b2..5b18265c2306 100644
> --- a/drivers/clk/rockchip/clk-mmc-phase.c
> +++ b/drivers/clk/rockchip/clk-mmc-phase.c
> @@ -41,8 +41,6 @@ static unsigned long rockchip_mmc_recalc(struct clk_hw *hw,
>  #define ROCKCHIP_MMC_DEGREE_MASK 0x3
>  #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
>  #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
> -#define ROCKCHIP_MMC_INIT_STATE_RESET 0x1
> -#define ROCKCHIP_MMC_INIT_STATE_SHIFT 1
>
>  #define PSECS_PER_SEC 1000000000000LL
>
> @@ -162,15 +160,6 @@ struct clk *rockchip_clk_register_mmc(const char *name,
>  	mmc_clock->reg = reg;
>  	mmc_clock->shift = shift;
>
> -	/*
> -	 * Assert init_state to soft reset the CLKGEN
> -	 * for mmc tuning phase and degree
> -	 */
> -	if (mmc_clock->shift == ROCKCHIP_MMC_INIT_STATE_SHIFT)
> -		writel(HIWORD_UPDATE(ROCKCHIP_MMC_INIT_STATE_RESET,
> -				     ROCKCHIP_MMC_INIT_STATE_RESET,
> -				     mmc_clock->shift), mmc_clock->reg);
> -
>  	clk = clk_register(NULL, &mmc_clock->hw);
>  	if (IS_ERR(clk))
>  		kfree(mmc_clock);
>


-- 
Best Regards
Shawn Lin



From shawn.lin at rock-chips.com  Thu May 12 17:42:29 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Fri, 13 May 2016 08:42:29 +0800
Subject: [PATCH v2 1/2] ARM64: dts: rockchip: add sdhci/emmc for rk3399
In-Reply-To: <1463092552-60696-1-git-send-email-briannorris@chromium.org>
References: <1463092552-60696-1-git-send-email-briannorris@chromium.org>
Message-ID: <d0aaec3a-65a2-5d0f-b37b-e3f174afc0c8@rock-chips.com>

? 2016/5/13 6:35, Brian Norris ??:
> Add description for the SDHCI v5.1 eMMC controller on rk3399. Fix it to
> 200 MHz, to support all supported timing modes.
>
> Note that 'rockchip,rk3399-sdhci-5.1' is not documented; we presumably
> have a compliant Arasan controller, but let's have a rockchip property
> as the canonical backup/precautionary measure. Per Heiko's previous
> suggestion, let's not clutter the arasan doc with it.
>
> Signed-off-by: Brian Norris <briannorris at chromium.org>

Except for adding "rockchip,rk3399-sdhci-5.1", it looks nice and keeps
consistent with our local kernel-4.4 tree.

Reviewed-by: Shawn Lin <shawn.lin at rock-chips.com>

> ---
> v2:
>
>  * improved commit message
>  * assign eMMC clock to 200 MHz
>
>  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 25 ++++++++++++++++++++++++-
>  1 file changed, 24 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> index 46f325a143b0..9980c2eab4e9 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -215,6 +215,19 @@
>  		status = "disabled";
>  	};
>
> +	sdhci: sdhci at fe330000 {
> +		compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
> +		reg = <0x0 0xfe330000 0x0 0x10000>;
> +		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;
> +		clock-names = "clk_xin", "clk_ahb";
> +		assigned-clocks = <&cru SCLK_EMMC>;
> +		assigned-clock-rates = <200000000>;
> +		phys = <&emmc_phy>;
> +		phy-names = "phy_arasan";
> +		status = "disabled";
> +	};
> +
>  	usb_host0_ehci: usb at fe380000 {
>  		compatible = "generic-ehci";
>  		reg = <0x0 0xfe380000 0x0 0x20000>;
> @@ -481,8 +494,18 @@
>  	};
>
>  	grf: syscon at ff770000 {
> -		compatible = "rockchip,rk3399-grf", "syscon";
> +		compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
>  		reg = <0x0 0xff770000 0x0 0x10000>;
> +
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +
> +		emmc_phy: phy at f780 {
> +			compatible = "rockchip,rk3399-emmc-phy";
> +			reg = <0xf780 0x20>;
> +			#phy-cells = <0>;
> +			status = "disabled";
> +		};
>  	};
>
>  	watchdog at ff840000 {
>


-- 
Best Regards
Shawn Lin



From shawn.lin at rock-chips.com  Thu May 12 18:02:41 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Fri, 13 May 2016 09:02:41 +0800
Subject: [PATCH 2/4] phy: rockchip-emmc: configure frequency range and
 drive impedance
In-Reply-To: <1463092986-61777-2-git-send-email-briannorris@chromium.org>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
 <1463092986-61777-2-git-send-email-briannorris@chromium.org>
Message-ID: <3695875b-09c3-cd80-3062-55d985e51f70@rock-chips.com>

Hi Brian,

On 2016/5/13 6:43, Brian Norris wrote:
> From: Shawn Lin <shawn.lin at rock-chips.com>
>
> Signal integrity analysis has suggested we set these values. Do this in
> power_on(), so that they get reconfigured after suspend/resume.
>
> Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
>  drivers/phy/phy-rockchip-emmc.c | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
>
> diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/phy-rockchip-emmc.c
> index 48cbe691a889..5641dede32f6 100644
> --- a/drivers/phy/phy-rockchip-emmc.c
> +++ b/drivers/phy/phy-rockchip-emmc.c
> @@ -56,6 +56,19 @@
>  #define PHYCTRL_DLLRDY_SHIFT	0x5
>  #define PHYCTRL_DLLRDY_DONE	0x1
>  #define PHYCTRL_DLLRDY_GOING	0x0
> +#define PHYCTRL_FREQSEL_200M	0x0
> +#define PHYCTRL_FREQSEL_50M	0x1
> +#define PHYCTRL_FREQSEL_100M	0x2
> +#define PHYCTRL_FREQSEL_150M	0x3
> +#define PHYCTRL_FREQSEL_MASK	0x3
> +#define PHYCTRL_FREQSEL_SHIFT	0xc
> +#define PHYCTRL_DR_MASK		0x7
> +#define PHYCTRL_DR_SHIFT	0x4
> +#define PHYCTRL_DR_50OHM	0x0
> +#define PHYCTRL_DR_33OHM	0x1
> +#define PHYCTRL_DR_66OHM	0x2
> +#define PHYCTRL_DR_100OHM	0x3
> +#define PHYCTRL_DR_40OHM	0x4
>
>  struct rockchip_emmc_phy {
>  	unsigned int	reg_offset;
> @@ -154,6 +167,20 @@ static int rockchip_emmc_phy_power_on(struct phy *phy)
>  	struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
>  	int ret = 0;
>
> +	/* DLL operation: 170 to 200 MHz */

What is 170 here? Should we expose them to dt instead of hardcoding
them?

Per the commit msg, signal may vary from board to board, so I guess
50ohm may not always be the best selection?

Another thing I need to elaborate more here is that emmc phy only
supports 50/100/150/200Mhz. Presumably people love to use the highest
speed mode with its upper limiting frequency, but in case of some
special requirement or bad board design, they want to add max-frequency
in dts for emmc controller. In this case PHYCTRL_FREQSEL_XXXM should
meet the actual max-frequency, take 100M for example, otherwise
emmc_phy's  tuning block will use 200M to do some calculation but it
certainly should be 100M. This leads emmc_phy to choose the wrong
phase. Finally maybe you will see triggering re-tune easily or some
worse case of even tuning failure when probing card.


> +	regmap_write(rk_phy->reg_base,
> +		     rk_phy->reg_offset + GRF_EMMCPHY_CON0,
> +		     HIWORD_UPDATE(PHYCTRL_FREQSEL_200M,
> +				   PHYCTRL_FREQSEL_MASK,
> +				   PHYCTRL_FREQSEL_SHIFT));
> +
> +	/* Drive impedance: 50 Ohm */
> +	regmap_write(rk_phy->reg_base,
> +		     rk_phy->reg_offset + GRF_EMMCPHY_CON6,
> +		     HIWORD_UPDATE(PHYCTRL_DR_50OHM,
> +				   PHYCTRL_DR_MASK,
> +				   PHYCTRL_DR_SHIFT));
> +
>  	/* Power up emmc phy analog blocks */
>  	ret = rockchip_emmc_phy_power(rk_phy, PHYCTRL_PDB_PWR_ON);
>  	if (ret)
>


-- 
Best Regards
Shawn Lin



From wangkefeng.wang at huawei.com  Thu May 12 18:17:02 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Fri, 13 May 2016 09:17:02 +0800
Subject: [PATCH 1/2] arm64: dts: NS2: Add all of the UARTs
In-Reply-To: <befabac6-aae2-fb3b-2faa-5463b7287b2a@broadcom.com>
References: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
 <57341FCE.6050403@huawei.com>
 <CAC3K-4qbkt3DCgd6qurNo3V+++x70bbFC--aunR0DbCTBvBNZg@mail.gmail.com>
 <befabac6-aae2-fb3b-2faa-5463b7287b2a@broadcom.com>
Message-ID: <57352B0E.5070803@huawei.com>



On 2016/5/13 0:52, Ray Jui wrote:
> Hi Kefeng,
> 
> On 5/12/2016 7:46 AM, Jon Mason wrote:
>>
>>
>> On Thu, May 12, 2016 at 2:16 AM, Kefeng Wang <wangkefeng.wang at huawei.com
>> <mailto:wangkefeng.wang at huawei.com>> wrote:
>>
>>
>>
>>     On 2016/5/12 6:56, Jon Mason wrote:
>>     > Add all of the UARTs present on NS2 and enable them in the SVK device
>>     > tree file.  Also, do some magic to make sure that uart3 is discovered as
>>     > ttyS0 (as that is the console UART).
>>     >
>>     > Signed-off-by: Jon Mason <jonmason at broadcom.com <mailto:jonmason at broadcom.com>>
>>     > ---
>>     >  arch/arm64/boot/dts/broadcom/ns2-svk.dts | 16 ++++++++++++++++
>>     >  arch/arm64/boot/dts/broadcom/ns2.dtsi    | 30 ++++++++++++++++++++++++++++++
>>     >  2 files changed, 46 insertions(+)
>>     >
>>     > diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
>>     > index 7cd3640..b062a44 100644
>>     > --- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts
>>     > +++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
>>     > @@ -40,10 +40,14 @@
>>     >
>>     >       aliases {
>>     >               serial0 = &uart3;
>>     > +             serial1 = &uart0;
>>     > +             serial2 = &uart1;
>>     > +             serial3 = &uart2;
>>     >       };
>>     >
>>     >       chosen {
>>     >               stdout-path = "serial0:115200n8";
>>     > +             bootargs = "earlycon=uart8250,mmio32,0x66130000";
>>
>>     Hi Jon,
>>
>>     I submit a patch[1], with it, we can use earlycon without option to
>>     enable early console
>>     for "snps,dw-apb-uart", could you help me to test it, thanks.
>>
>>
>> Adding your change and removing the line above does not cause earlycon
>> to work for me.  Is there any additional changes necessary for this to work?
>>
>> Thanks,
>> Jon
>>
> 
> "OF_EARLYCON_DECLARE" doesn't seem to have a way to deal with DT properties? In the case of UART for NS2, it needs mmio32, configured with DT property "reg-io-width" set to 4. I don't think "OF_EARLYCON_DECLARE" is parsing that, which is likely the reason why it doesn't work for devices that required mmio32.
> 
It should work, I test this in Hisi D02 board, it uses same uart and same configuration.

early_init_dt_scan_chosen_serial()
 for (match = __earlycon_table; match < __earlycon_table_end; match++)
 	......
	of_setup_earlycon()
		val = of_get_flat_dt_prop(node, "reg-io-width", NULL);  // will obtain the reg-io-width and set iotype=mmio32
		err = match->setup(&early_console_dev, options);  // call early_serial8250_setup

Could you check it again, thanks,

Kefeng


> Thanks,
> 
> Ray
> 
> .
> 



From wangkefeng.wang at huawei.com  Thu May 12 18:21:10 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Fri, 13 May 2016 09:21:10 +0800
Subject: [PATCH v3 0/2] arm64: mm: Enhance Virtual kernel memory layout
In-Reply-To: <20160512133642.GC25355@arm.com>
References: <1460948988-7477-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463055387-19289-1-git-send-email-wangkefeng.wang@huawei.com>
 <20160512133642.GC25355@arm.com>
Message-ID: <57352C06.3070807@huawei.com>



On 2016/5/12 21:36, Will Deacon wrote:
> On Thu, May 12, 2016 at 08:16:25PM +0800, Kefeng Wang wrote:
>> This is a micro enhance for Virtual kernel memory layout. Show bss info,
>> and make each line with single pr_cont().
> 
> I already queued[1] the previous version of this after James acked it,
> so if you want to make further changes, please send incremental patches
> for review.
> 

I can't see them before, thanks Will.

BRs,
Kefeng


> Will
> 
> [1]
> https://git.kernel.org/cgit/linux/kernel/git/arm64/linux.git/commit/?h=for-next/core&id=9974723e31d1fa99e3c0efb2ae6cbbf089c0080c
> https://git.kernel.org/cgit/linux/kernel/git/arm64/linux.git/commit/?h=for-next/core&id=d32351c8242b7067b3f3e3a6caf7a387ff43f978
> 
> .
> 



From Wenyou.Yang at atmel.com  Thu May 12 18:36:39 2016
From: Wenyou.Yang at atmel.com (Yang, Wenyou)
Date: Fri, 13 May 2016 01:36:39 +0000
Subject: [PATCH] usb: ohci-at91: Suspend the ports while USB suspending
In-Reply-To: <Pine.LNX.4.44L0.1605121359120.5957-100000@netrider.rowland.org>
References: <1463015134-32364-1-git-send-email-wenyou.yang@atmel.com>
 <Pine.LNX.4.44L0.1605121359120.5957-100000@netrider.rowland.org>
Message-ID: <B256D81BAE5131468A838E5D7A243641016509B9A5@penmbx01>

Hi Alan,

> -----Original Message-----
> From: Alan Stern [mailto:stern at rowland.harvard.edu]
> Sent: 2016?5?13? 2:11
> To: Yang, Wenyou <Wenyou.Yang at atmel.com>
> Cc: Greg Kroah-Hartman <gregkh at linuxfoundation.org>; Ferre, Nicolas
> <Nicolas.FERRE at atmel.com>; linux-usb at vger.kernel.org; linux-
> kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH] usb: ohci-at91: Suspend the ports while USB suspending
> 
> On Thu, 12 May 2016, Wenyou Yang wrote:
> 
> > In order to get lower consumption, as a workaround, suspend the USB
> > PORTA/B/C via set the SUSPEND_A/B/C bits of OHCI Interrupt
> > Configuration Register while OHCI USB suspending.
> 
> What does this mean?  What does suspending a port do?  

It is a IP workaround for SAMA5D2 USB. By setting corresponding bits of a specific register to get lower consumption.  

> Is it the same as a normal USB port suspend?

No, it is not same.

> 
> If it is the same, why doesn't the USB_PORT_FEAT_SUSPEND subcase of the
> SetPortFeature case in ohci_hub_control() already take care of this?
> 
> > This suspend operation must be done before stopping the USB clock,
> > resume after the USB clock enabled.
> >
> > Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> > ---
> 
> > @@ -132,6 +135,17 @@ static void at91_stop_hc(struct platform_device
> > *pdev)
> >
> >
> > /*--------------------------------------------------------------------
> > -----*/
> >
> > +struct regmap *at91_dt_syscon_sfr(void) {
> > +	struct regmap *regmap;
> > +
> > +	regmap = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
> > +	if (IS_ERR(regmap))
> > +		return NULL;
> 
> If you get an error, the regmap pointer is set to NULL...
> 
> > @@ -197,6 +211,8 @@ static int usb_hcd_at91_probe(const struct hc_driver
> *driver,
> >  		goto err;
> >  	}
> >
> > +	ohci_at91->sfr_regmap = at91_dt_syscon_sfr();
> 
> With no other error checking...

Add error checking in next version.

> 
> > +
> >  	board = hcd->self.controller->platform_data;
> >  	ohci = hcd_to_ohci(hcd);
> >  	ohci->num_ports = board->ports;
> 
> > +static int ohci_at91_port_ctrl(struct regmap *regmap, bool enable) {
> > +	u32 regval;
> > +	int ret;
> > +
> > +	if (IS_ERR(regmap))
> > +		return PTR_ERR(regmap);
> > +
> > +	ret = regmap_read(regmap, SFR_OHCIICR, &regval);
> 
> And now what happens if regmap is NULL?  Hint: It won't be pretty...

Yes, it is not pretty. Will rework in next version.

> 
> Alan Stern


Best Regards,
Wenyou Yang


From wangkefeng.wang at huawei.com  Thu May 12 18:44:49 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Fri, 13 May 2016 09:44:49 +0800
Subject: [PATCH v4 10/18] sh: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <20160512183822.GL21636@brightrain.aerifal.cx>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463054775-18170-11-git-send-email-wangkefeng.wang@huawei.com>
 <20160512183822.GL21636@brightrain.aerifal.cx>
Message-ID: <57353191.7020609@huawei.com>



On 2016/5/13 2:38, Rich Felker wrote:
> On Thu, May 12, 2016 at 08:06:07PM +0800, Kefeng Wang wrote:
>> After patch "of/platform: Add common method to populate default bus",
>> it is possible for arch code to remove unnecessary callers about the
>> of_platform_populate with default match table.
> 
> s/about the/of/ ?

Ok, will update.

> 
>> Cc: Yoshinori Sato <ysato at users.sourceforge.jp>
>> Cc: Rich Felker <dalias at libc.org>
>> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
>> ---
>>  arch/sh/boards/of-generic.c | 14 --------------
>>  1 file changed, 14 deletions(-)
>>
>> diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c
>> index b4d4313..911ffb9 100644
>> --- a/arch/sh/boards/of-generic.c
>> +++ b/arch/sh/boards/of-generic.c
>> @@ -9,7 +9,6 @@
>>   */
>>  
>>  #include <linux/of.h>
>> -#include <linux/of_platform.h>
>>  #include <linux/of_fdt.h>
>>  #include <linux/clocksource.h>
>>  #include <linux/irqchip.h>
>> @@ -179,16 +178,3 @@ void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
>>  void __init plat_irq_setup(void)
>>  {
>>  }
>> -
>> -static int __init sh_of_device_init(void)
>> -{
>> -	pr_info("SH generic board support: populating platform devices\n");
>> -	if (of_have_populated_dt()) {
>> -		of_platform_populate(NULL, of_default_bus_match_table,
>> -				     NULL, NULL);
>> -	} else {
>> -		pr_crit("Device tree not populated\n");
>> -	}
>> -	return 0;
>> -}
>> -arch_initcall_sync(sh_of_device_init);
>> -- 
>> 1.7.12.4
> 
> I have not tested this, but as long as the new arch-generic code takes
> place at the same point in the init sequence (arch_initcall_sync), as
> it seems to, I don't expect any sh-specific breakage. In general I'm
> happy to see this kind of change.

Hope no breakage in all archs, but I can only test this in few arm/arm64 boards :(

Thanks,
Kefeng

> 
> Rich
> 
> .
> 



From hanjun.guo at linaro.org  Thu May 12 18:48:50 2016
From: hanjun.guo at linaro.org (Hanjun Guo)
Date: Fri, 13 May 2016 09:48:50 +0800
Subject: [PATCH v5 1/1] ARM64: ACPI: Update documentation for latest
 specification version
In-Reply-To: <1461619287-27211-2-git-send-email-al.stone@linaro.org>
References: <1461619287-27211-1-git-send-email-al.stone@linaro.org>
 <1461619287-27211-2-git-send-email-al.stone@linaro.org>
Message-ID: <57353282.3090107@linaro.org>

On 2016/4/26 5:21, Al Stone wrote:
> The ACPI 6.1 specification was recently released at the end of January
> 2016, but the arm64 kernel documentation for the use of ACPI was written
> for the 5.1 version of the spec.  There were significant additions to the
> spec that had not yet been mentioned -- for example, the 6.0 mechanisms
> added to make it easier to define processors and low power idle states,
> as well as the 6.1 addition allowing regular interrupts (not just from
> GPIO) be used to signal ACPI general purpose events.
>
> This patch reflects going back through and examining the specs in detail
> and updating content appropriately.  Whilst there, a few odds and ends of
> typos were caught as well.  This brings the documentation up to date with
> ACPI 6.1 for arm64.
>
> Signed-off-by: Al Stone <al.stone at linaro.org>
> Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
> ---
>   Documentation/arm64/acpi_object_usage.txt | 343 ++++++++++++++++--------------
>   Documentation/arm64/arm-acpi.txt          |  40 ++--
>   2 files changed, 213 insertions(+), 170 deletions(-)
>
> diff --git a/Documentation/arm64/acpi_object_usage.txt b/Documentation/arm64/acpi_object_usage.txt
> index a6e1a18..c77010c 100644
> --- a/Documentation/arm64/acpi_object_usage.txt
> +++ b/Documentation/arm64/acpi_object_usage.txt
> @@ -13,14 +13,14 @@ For ACPI on arm64, tables also fall into the following categories:
>
>          -- Required: DSDT, FADT, GTDT, MADT, MCFG, RSDP, SPCR, XSDT
>
> -       -- Recommended: BERT, EINJ, ERST, HEST, SSDT
> +       -- Recommended: BERT, EINJ, ERST, HEST, PCCT, SSDT
>
> -       -- Optional: BGRT, CPEP, CSRT, DRTM, ECDT, FACS, FPDT, MCHI, MPST,
> -          MSCT, RASF, SBST, SLIT, SPMI, SRAT, TCPA, TPM2, UEFI
> -
> -       -- Not supported: BOOT, DBG2, DBGP, DMAR, ETDT, HPET, IBFT, IVRS,
> -          LPIT, MSDM, RSDT, SLIC, WAET, WDAT, WDRT, WPBT
> +       -- Optional: BGRT, CPEP, CSRT, DBG2, DRTM, ECDT, FACS, FPDT, IORT,
> +          MCHI, MPST, MSCT, NFIT, PMTT, RASF, SBST, SLIT, SPMI, SRAT, STAO,
> +	  TCPA, TPM2, UEFI, XENV
>
> +       -- Not supported: BOOT, DBGP, DMAR, ETDT, HPET, IBFT, IVRS, LPIT,
> +          MSDM, OEMx, PSDT, RSDT, SLIC, WAET, WDAT, WDRT, WPBT
>
>   Table  Usage for ARMv8 Linux
>   -----  ----------------------------------------------------------------
> @@ -50,7 +50,8 @@ CSRT   Signature Reserved (signature == "CSRT")
>
>   DBG2   Signature Reserved (signature == "DBG2")
>          == DeBuG port table 2 ==
> -       Microsoft only table, will not be supported.
> +       License has changed and should be usable.  Optional if used instead
> +       of earlycon=<device> on the command line.
>
>   DBGP   Signature Reserved (signature == "DBGP")
>          == DeBuG Port table ==
> @@ -133,10 +134,11 @@ GTDT   Section 5.2.24 (signature == "GTDT")
>
>   HEST   Section 18.3.2 (signature == "HEST")
>          == Hardware Error Source Table ==
> -       Until further error source types are defined, use only types 6 (AER
> -       Root Port), 7 (AER Endpoint), 8 (AER Bridge), or 9 (Generic Hardware
> -       Error Source).  Firmware first error handling is possible if and only
> -       if Trusted Firmware is being used on arm64.
> +       ARM-specific error sources have been defined; please use those or the
> +       PCI types such as type 6 (AER Root Port), 7 (AER Endpoint), or 8 (AER
> +       Bridge), or use type 9 (Generic Hardware Error Source).  Firmware first
> +       error handling is possible if and only if Trusted Firmware is being
> +       used on arm64.
>
>          Must be supplied if RAS support is provided by the platform.  It
>          is recommended this table be supplied.
> @@ -149,20 +151,30 @@ IBFT   Signature Reserved (signature == "IBFT")
>          == iSCSI Boot Firmware Table ==
>          Microsoft defined table, support TBD.
>
> +IORT   Signature Reserved (signature == "IORT")
> +       == Input Output Remapping Table ==
> +       arm64 only table, required in order to describe IO topology, SMMUs,
> +       and GIC ITSs, and how those various components are connected together,
> +       such as identifying which components are behind which SMMUs/ITSs.
> +       This table will only be required on certain SBSA platforms (e.g.,
> +       when using GICv3-ITS and an SMMU); on SBSA Level 0 platforms, it
> +       remains optional.

Hmm, yes, for GICv2 based system, we don't need a IORT table,

Reviewed-by: Hanjun Guo <hanjun.guo at linaro.org>

Thanks
Hanjun


From shijie.huang at arm.com  Thu May 12 18:49:06 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Fri, 13 May 2016 09:49:06 +0800
Subject: [PATCH] deb-pkg: add the shared header file for arm64
In-Reply-To: <573491A2.7070809@suse.com>
References: <1463043837-4348-1-git-send-email-shijie.huang@arm.com>
 <573491A2.7070809@suse.com>
Message-ID: <20160513014905.GA15321@sha-win-210.asiapac.arm.com>

On Thu, May 12, 2016 at 04:22:26PM +0200, Michal Marek wrote:
> On 2016-05-12 11:03, Huang Shijie wrote:
> > The arch/arm/include/asm/opcodes.h is also used by the arm64.
> > This patch copies it to the arm64 deb package.
> > 
> > Signed-off-by: Huang Shijie <shijie.huang at arm.com>
> > ---
> >  scripts/package/builddeb | 6 ++++++
> >  1 file changed, 6 insertions(+)
> 
> 
> Hi Huang,
> 
> this is fixed (admittedly in a more aggressive way) by 962475ac2f96
> ("builddeb: fix missing headers in linux-headers package") in linux-next.
okay. got it.

thanks
Huang Shijie



From chunfeng.yun at mediatek.com  Thu May 12 19:00:20 2016
From: chunfeng.yun at mediatek.com (chunfeng yun)
Date: Fri, 13 May 2016 10:00:20 +0800
Subject: [PATCH 3/6] dt-bindings: mtu3: add devicetree bindings
In-Reply-To: <CAOGqxeUYEGKq5yhHbgcjPZtY06ZfDp2iCLZDqS3uyfCW523B4w@mail.gmail.com>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462868614-20602-4-git-send-email-chunfeng.yun@mediatek.com>
 <20160511145409.GA23042@rob-hp-laptop>
 <1463037844.11651.118.camel@mhfsdcap03>
 <CAOGqxeUYEGKq5yhHbgcjPZtY06ZfDp2iCLZDqS3uyfCW523B4w@mail.gmail.com>
Message-ID: <1463104820.11651.125.camel@mhfsdcap03>

Hi,

On Thu, 2016-05-12 at 19:02 -0400, Alan Cooper wrote:
> On Thu, May 12, 2016 at 3:24 AM, chunfeng yun <chunfeng.yun at mediatek.com> wrote:
> >> > + - mediatek,enable-manual-drd : supports manual dual-role switch by sysfs
> >> > +   interface; only used when receptacle is TYPE-A and also wants to support
> >> > +   dual-role mode.
> >>
> >> sysfs is a Linux detail that doesn't apply to the binding. Does the
> >> property mean "the IP block supports or doesn't support switching"  or
> >> "I want to enable switching feature". Only the former belongs in DT.
> >>
> > It is the former case, and has little relation with sysfs interface.
> > I will modify it later, sorry for my unclear description.
> 
> Could the property name be just "enable-manual-drd" instead of
> "mediatek,enable-manual-drd"? I expect to have to add this
> functionality to our USB driver in the near future.

Do you mean provide some APIs to in common USB driver?





From dianders at chromium.org  Thu May 12 19:11:25 2016
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 12 May 2016 19:11:25 -0700
Subject: [PATCH 1/2] Revert "clk: rockchip: reset init state before mmc
 card initialization"
In-Reply-To: <2083095.luTHhmZ9EO@phil>
References: <1463076197-15900-1-git-send-email-dianders@chromium.org>
 <2083095.luTHhmZ9EO@phil>
Message-ID: <CAD=FV=XVMQ025Z-+C4fVQUuof=9wnjvJKr2PtuJhxOVwo7TjSg@mail.gmail.com>

Heiko,

On Thu, May 12, 2016 at 4:41 PM, Heiko Stuebner <heiko at sntech.de> wrote:
> Am Donnerstag, 12. Mai 2016, 11:03:16 schrieb Douglas Anderson:
>
> Not sure what the policy is for revert-subjects in the clock-tree, but I
> guess
>
> clk: rockchip: Revert "reset init state before mmc card initialization"
>
> might look nicer?

Sure.  If you want me to re-post with that, let me know.  Else feel
free to fix when applying.


>> This reverts commit 7a03fe6f48f3 ("clk: rockchip: reset init state
>> before mmc card initialization").
>
> I've tested these two patches together with the dw_mmc one and everything
> that worked before still works (tuning on veyron-jerry) and everything that
> didn't work still doesn't work (tuning on firefly [likely a regulator issue]).
>
> And re-checking the code against the TRM I now also see the mask that is to
> short (1 bit in the code vs. the actual 2 bits described in the manual)
>
> [...]
>
>> 1. Just this revert: likely will fix rk3288-veyron eMMC on some devices
>>    + other cases; might break someone with a strange bootloader that
>>    sets the phase to 0 or one that uses delay elements (pretty
>>    unpredicable what would happen in that case).
>> 2. Just dw_mmc patch: fixes everyone.  Effectly the dw_mmc patch will
>>    totally override the broken patch and fix everything.
>> 3. Both patches: fixes everyone.  Once dw_mmc is initting properly then
>>    any defaults from the clock code doesn't mattery.
>
> I'm still trying to make up my mind on how to proceed - aka in which order
> patches should get picked up.
>
> Going with the "if it isn't upstream it doesn't exist" mantra Rob wrote
> somewhere some days ago, taking this revert should not hurt anything, as all
> the non-veyron devices currently don't support any tuning at all.

Note that this patch can still affect devices that don't use tuning.
MMC Hold times are important not just for high speed modes but even
for low speed modes.


> So I'd think except for the issue Shawn was originally trying to fix (for
> some non-mainline board?) it should be possible to take this patch any time
> independently of the dw_mmc part.

Yeah, just not sure.  Shawn: do you know which specific device you
were trying to fix with the original patch?  Is it OK to revert for
now until the dw_mmc patch lands?


From wangkefeng.wang at huawei.com  Thu May 12 19:09:37 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Fri, 13 May 2016 10:09:37 +0800
Subject: [PATCH 1/2] arm64: dts: NS2: Add all of the UARTs
In-Reply-To: <CAC3K-4qbkt3DCgd6qurNo3V+++x70bbFC--aunR0DbCTBvBNZg@mail.gmail.com>
References: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
 <57341FCE.6050403@huawei.com>
 <CAC3K-4qbkt3DCgd6qurNo3V+++x70bbFC--aunR0DbCTBvBNZg@mail.gmail.com>
Message-ID: <57353761.5020409@huawei.com>



On 2016/5/12 22:46, Jon Mason wrote:
> 
> 
> On Thu, May 12, 2016 at 2:16 AM, Kefeng Wang <wangkefeng.wang at huawei.com <mailto:wangkefeng.wang at huawei.com>> wrote:
> 
> 
> 
>     On 2016/5/12 6:56, Jon Mason wrote:
>     > Add all of the UARTs present on NS2 and enable them in the SVK device
>     > tree file.  Also, do some magic to make sure that uart3 is discovered as
>     > ttyS0 (as that is the console UART).
>     >
>     > Signed-off-by: Jon Mason <jonmason at broadcom.com <mailto:jonmason at broadcom.com>>
>     > ---
>     >  arch/arm64/boot/dts/broadcom/ns2-svk.dts | 16 ++++++++++++++++
>     >  arch/arm64/boot/dts/broadcom/ns2.dtsi    | 30 ++++++++++++++++++++++++++++++
>     >  2 files changed, 46 insertions(+)
>     >
>     > diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
>     > index 7cd3640..b062a44 100644
>     > --- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts
>     > +++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
>     > @@ -40,10 +40,14 @@
>     >
>     >       aliases {
>     >               serial0 = &uart3;
>     > +             serial1 = &uart0;
>     > +             serial2 = &uart1;
>     > +             serial3 = &uart2;
>     >       };
>     >
>     >       chosen {
>     >               stdout-path = "serial0:115200n8";
>     > +             bootargs = "earlycon=uart8250,mmio32,0x66130000";
> 
>     Hi Jon,
> 
>     I submit a patch[1], with it, we can use earlycon without option to enable early console
>     for "snps,dw-apb-uart", could you help me to test it, thanks.
> 
> 
> Adding your change and removing the line above does not cause earlycon to work for me.  Is there any additional changes necessary for this to work?
With my patch, the bootargs still need contain earlycon, but no need uart8250,mmio32,0x66130000;

chosen {
	stdout-path = "serial0:115200n8";
	bootargs = "earlycon";
}

Hope it would work.

BRs,
Kefeng

> 
> Thanks,
> Jon
>  
> 
> 
>     BRs,
>     Kefeng
> 
> 
>     [1] https://lkml.org/lkml/2016/5/11/34
> 
>     >       };
>     >
>     >       memory {
>     > @@ -68,6 +72,18 @@
>     >       status = "ok";
>     >  };
>     >
>     > +&uart0 {
>     > +     status = "ok";
>     > +};
>     > +
>     > +&uart1 {
>     > +     status = "ok";
>     > +};
>     > +
>     > +&uart2 {
>     > +     status = "ok";
>     > +};
>     > +
>     >  &uart3 {
>     >       status = "ok";
>     >  };
>     > diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi
>     > index 788ed8f..c77a9e8 100644
>     > --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
>     > +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
>     > @@ -357,6 +357,36 @@
>     >                       status = "disabled";
>     >               };
>     >
>     > +             uart0: serial at 66100000 {
>     > +                     compatible = "snps,dw-apb-uart";
>     > +                     reg = <0x66100000 0x100>;
>     > +                     interrupts = <GIC_SPI 390 IRQ_TYPE_LEVEL_HIGH>;
>     > +                     clocks = <&iprocslow>;
>     > +                     reg-shift = <2>;
>     > +                     reg-io-width = <4>;
>     > +                     status = "disabled";
>     > +             };
>     > +
>     > +             uart1: serial at 66110000 {
>     > +                     compatible = "snps,dw-apb-uart";
>     > +                     reg = <0x66110000 0x100>;
>     > +                     interrupts = <GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH>;
>     > +                     clocks = <&iprocslow>;
>     > +                     reg-shift = <2>;
>     > +                     reg-io-width = <4>;
>     > +                     status = "disabled";
>     > +             };
>     > +
>     > +             uart2: serial at 66120000 {
>     > +                     compatible = "snps,dw-apb-uart";
>     > +                     reg = <0x66120000 0x100>;
>     > +                     interrupts = <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH>;
>     > +                     clocks = <&iprocslow>;
>     > +                     reg-shift = <2>;
>     > +                     reg-io-width = <4>;
>     > +                     status = "disabled";
>     > +             };
>     > +
>     >               uart3: serial at 66130000 {
>     >                       compatible = "snps,dw-apb-uart";
>     >                       reg = <0x66130000 0x100>;
>     >
> 
> 



From chaotian.jing at mediatek.com  Thu May 12 19:42:23 2016
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Fri, 13 May 2016 10:42:23 +0800
Subject: [PATCH] mmc: mmc: do not use CMD13 to get status after speed
 mode switch
In-Reply-To: <57345B14.7030308@intel.com>
References: <1462344872-6448-1-git-send-email-chaotian.jing@mediatek.com>
 <5732E43E.8070800@intel.com> <1463036431.11653.3.camel@mhfsdcap03>
 <57345B14.7030308@intel.com>
Message-ID: <1463107343.26133.6.camel@mhfsdcap03>

On Thu, 2016-05-12 at 13:29 +0300, Adrian Hunter wrote:
> On 12/05/16 10:00, Chaotian Jing wrote:
> > On Wed, 2016-05-11 at 10:50 +0300, Adrian Hunter wrote:
> >> On 04/05/16 09:54, Chaotian Jing wrote:
> >>> Per JEDEC spec, it is not recommended to use CMD13 to get card status
> >>> after speed mode switch. below are two reason about this:
> >>> 1. CMD13 cannot be guaranteed due to the asynchronous operation.
> >>> Therefore it is not recommended to use CMD13 to check busy completion
> >>> of the timing change indication.
> >>> 2. After switch to HS200, CMD13 will get response of 0x800, and even the
> >>> busy signal gets de-asserted, the response of CMD13 is aslo 0x800.
> >>>
> >>> this patch drops CMD13 when doing speed mode switch, if host do not
> >>> support MMC_CAP_WAIT_WHILE_BUSY and there is no ops->card_busy(),
> >>> then the only way is to wait a fixed timeout.
> >>
> >> This looks like it should be 3 patches:
> >> 	1. Change __mmc_switch
> >> 	2. Change HS200 and HS400 selection
> >> 	3. Change HS selection
> >>
> >> However there is another problem: card_busy is not the same as busy signal -
> >> see below.  So that needs to be sorted out first.
> >>
> > We should make that card_busy() is the same with busy signal asserted.
> > as you know, if card was not in busy state, all data pins should be high
> > level as it is pull-up by default. so that's no conflict to check card
> > busy signal by DAT0 or DAT0 ~ DAT3.
> 
> Potentially SDIO uses DAT1 for card interrupt, so that is a conflict right
> there.
> 
> Also SDHCI does it backwards (don't ask me why) and considers 0000 to be
> busy, so there's another conflict.
> 
> Some of the language in the SD and SDHCI specifications seems to indicate
> that checking all 4 DAT lines during voltage switch is optional i.e. only 1
> of the lines must be checked.  If that is true then we could change all the
> drivers over to check just DAT0, and expect that to work for both busy
> signalling and SD voltage switch checks.
> 
> So it seems to me card_busy still needs to be sorted out first.

One thing must point out is that the __mmc_switch() is only for MMC
card. SD/SDIO will never use this interface.
by the way, Per JEDEC SD3.0 spec, below is the quote from spec:
"Completion of voltage switch sequence is checked by high level of
DAT[3:0]. Any bit of DAT[3:0] can be checked depends on ability of the
host."
So that the implement of ops->card_busy() can be changed from check
DAT[3:0] to only check DAT[0].

In fact, for SD/SDIO voltage switch, if switch success, all DAT pins are
high level and if switch failed, all data pins are low level.
> 




From dhdang at apm.com  Thu May 12 19:55:20 2016
From: dhdang at apm.com (Duc Dang)
Date: Thu, 12 May 2016 19:55:20 -0700
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <CADaLNDnXiL2nYtSmd1h-9MSnUUY4S+dAEcFXRSE_jjWhqRzufQ@mail.gmail.com>

On Tue, May 10, 2016 at 8:19 AM, Tomasz Nowicki <tn at semihalf.com> wrote:
> From the functionality point of view this series may be split into the
> following logic parts:
> 1. New ECAM API and update for users of the pci-host-common API
> 2. Necessary fixes as the preparation for using driver on ARM64.
> 3. Use new MCFG interface and implement generic ACPI based PCI host controller driver.
> 4. Enable above driver on ARM64
>
> Patches has been built on top of 4.6-rc7 and can be found here:
> git at github.com:semihalf-nowicki-tomasz/linux.git (pci-acpi-v7)
>
> This has been tested on Cavium ThunderX server. Any help in reviewing and
> testing is very appreciated.

I tried this series on APM X-Gene platforms (with ECAM fix-up quirk
added) and PCIe works fine.

Regards,
Duc Dang.
>
> v6 -> v7
> - drop quirks handling
> - changes for ACPI companion and domain number assignment approach
> - implement arch pcibios_{add|remove}_bus and call acpi_pci_{add|remove}_bus from there
> - cleanups around nomenclature
> - use resources oriented API for ECAM
> - fix for based address calculation before mapping ECAM region
> - remove useless lock for MCFG lookup
> - move MCFG stuff to separated file pci_mcfg.c
> - drop MCFG entries caching
> - rebase against 4.6-rc7
>
> v5 -> v6
> - drop idea of x86 MMCONFIG code refactoring
> - integrate JC's patches which introduce new ECAM API:
>   https://lkml.org/lkml/2016/4/11/907
>   git: https://github.com/jchandra-brcm/linux/ (arm64-acpi-pci-v3)
> - integrate Sinan's fix for releasing IO resources, see patch [06/13]
> - added ACPI support for ThunderX ECAM and PEM drivers
> - rebase against 4.6-rc2
>
> v4 -> v5
> - drop MCFG refactoring group patches 1-6 from series v4 and integrate Jayachandran's patch
>   https://patchwork.ozlabs.org/patch/575525/
> - rewrite PCI legacy IRQs allocation
> - squash two patches 11 and 12 from series v4, fixed bisection issue
> - changelog improvements
> - rebase against 4.5-rc3
>
> v3 -> v4
> - drop Jiang's fix http://lkml.iu.edu/hypermail/linux/kernel/1601.1/04318.html
> - add Lorenzo's fix patch 19/24
> - ACPI PCI bus domain number assigning cleanup
> - change resource management, we now claim and reassign resources
> - improvements for applying quirks
> - drop Matthew's http://www.spinics.net/lists/linux-pci/msg45950.html dependency
> - rebase against 4.5-rc1
>
> v2 -> v3
> - fix legacy IRQ assigning and IO ports registration
> - remove reference to arch specific companion device for ia64
> - move ACPI PCI host controller driver to pci_root.c
> - drop generic domain assignment for x86 and ia64 as I am not
>   able to run all necessary test variants
> - drop patch which cleaned legacy IRQ assignment since it belongs to
>   Mathew's series:
>   https://patchwork.ozlabs.org/patch/557504/
> - extend MCFG quirk code
> - rebase against 4.4
>
> v1 -> v2
> - move non-arch specific piece of code to dirver/acpi/ directory
> - fix IO resource handling
> - introduce PCI config accessors quirks matching
> - moved ACPI_COMPANION_SET to generic code
>
> v1 - https://lkml.org/lkml/2015/10/27/504
> v2 - https://lkml.org/lkml/2015/12/16/246
> v3 - http://lkml.iu.edu/hypermail/linux/kernel/1601.1/04308.html
> v4 - https://lkml.org/lkml/2016/2/4/646
> v5 - https://lkml.org/lkml/2016/2/16/426
> v6 - https://lkml.org/lkml/2016/4/15/594
>
> Jayachandran C (2):
>   PCI: Provide common functions for ECAM mapping
>   PCI: generic, thunder: update to use generic ECAM API
>
> Tomasz Nowicki (9):
>   pci, of: Move the PCI I/O space management to PCI core code.
>   pci: Add new function to unmap IO resources.
>   acpi, pci: Support IO resources when parsing PCI host bridge
>     resources.
>   pci, acpi: Provide a way to assign bus domain number.
>   pci, acpi: Handle ACPI companion assignment.
>   pci, acpi: Support for ACPI based generic PCI host controller
>   arm64, pci, acpi: ACPI support for legacy IRQs parsing and
>     consolidation with DT code.
>   arm64, pci, acpi: Provide ACPI-specific prerequisites for PCI bus
>     enumeration.
>   arm64, pci, acpi: Start using ACPI based PCI host controller driver
>     for ARM64.
>
>  arch/arm64/Kconfig                  |   1 +
>  arch/arm64/kernel/pci.c             |  34 +++-----
>  drivers/acpi/Kconfig                |   8 ++
>  drivers/acpi/Makefile               |   1 +
>  drivers/acpi/pci_mcfg.c             |  97 ++++++++++++++++++++++
>  drivers/acpi/pci_root.c             |  33 ++++++++
>  drivers/acpi/pci_root_generic.c     | 149 +++++++++++++++++++++++++++++++++
>  drivers/of/address.c                | 116 +-------------------------
>  drivers/pci/Kconfig                 |   3 +
>  drivers/pci/Makefile                |   2 +
>  drivers/pci/ecam.c                  | 161 ++++++++++++++++++++++++++++++++++++
>  drivers/pci/ecam.h                  |  72 ++++++++++++++++
>  drivers/pci/host/Kconfig            |   1 +
>  drivers/pci/host/pci-host-common.c  | 114 +++++++++++--------------
>  drivers/pci/host/pci-host-common.h  |  47 -----------
>  drivers/pci/host/pci-host-generic.c |  52 +++---------
>  drivers/pci/host/pci-thunder-ecam.c |  39 ++-------
>  drivers/pci/host/pci-thunder-pem.c  |  92 ++++++++++-----------
>  drivers/pci/pci.c                   | 150 ++++++++++++++++++++++++++++++++-
>  drivers/pci/probe.c                 |   2 +
>  include/linux/of_address.h          |   9 --
>  include/linux/pci-acpi.h            |  14 ++++
>  include/linux/pci.h                 |  11 ++-
>  23 files changed, 823 insertions(+), 385 deletions(-)
>  create mode 100644 drivers/acpi/pci_mcfg.c
>  create mode 100644 drivers/acpi/pci_root_generic.c
>  create mode 100644 drivers/pci/ecam.c
>  create mode 100644 drivers/pci/ecam.h
>  delete mode 100644 drivers/pci/host/pci-host-common.h
>
> --
> 1.9.1
>


From viresh.kumar at linaro.org  Thu May 12 19:58:48 2016
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Fri, 13 May 2016 08:28:48 +0530
Subject: [PATCH v4 03/18] arm: Remove unnecessary of_platform_populate
 with default match table
In-Reply-To: <1463054775-18170-4-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463054775-18170-4-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <20160513025848.GK9661@vireshk-i7>

On 12-05-16, 20:06, Kefeng Wang wrote:
> After patch "of/platform: Add common method to populate default bus",
> it is possible for arch code to remove unnecessary callers about the
> of_platform_populate with default match table.
> 
> Cc: Nicolas Ferre <nicolas.ferre at atmel.com>
> Cc: Ray Jui <rjui at broadcom.com>
> Cc: Lee Jones <lee at kernel.org>
> Cc: Krzysztof Halasa <khalasa at piap.pl>
> Cc: Kukjin Kim <kgene at kernel.org>
> Cc: Rob Herring <robh at kernel.org>
> Cc: Shawn Guo <shawnguo at kernel.org>
> Cc: Santosh Shilimkar <ssantosh at kernel.org>
> Cc: Roland Stigge <stigge at antcom.de>
> Cc: Jason Cooper <jason at lakedaemon.net>
> Cc: Haojian Zhuang <haojian.zhuang at gmail.com>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Cc: Viresh Kumar <vireshk at kernel.org>
> Cc: Shiraz Hashim <shiraz.linux.kernel at gmail.com>
> Cc: Tony Prisk <linux at prisktech.co.nz>
> Cc: Arnd Bergmann <arnd at arndb.de>
> Cc: Russell King <linux at arm.linux.org.uk>
> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> ---
>  arch/arm/mach-spear/spear1310.c         |  2 --
>  arch/arm/mach-spear/spear1340.c         |  1 -

Acked-by: Viresh Kumar <viresh.kumar at linaro.org>

-- 
viresh


From viresh.kumar at linaro.org  Thu May 12 19:59:18 2016
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Fri, 13 May 2016 08:29:18 +0530
Subject: [PATCH v4 12/18] arm: use of_platform_default_populate() to
 populate
In-Reply-To: <1463054775-18170-13-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463054775-18170-13-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <20160513025918.GL9661@vireshk-i7>

On 12-05-16, 20:06, Kefeng Wang wrote:
> Use helper of_platform_default_populate() in linux/of_platform
> when possible, instead of calling of_platform_populate() with
> the default match table.
> 
> Cc: Nicolas Ferre <nicolas.ferre at atmel.com>
> Cc: Krzysztof Halasa <khalasa at piap.pl>
> Cc: Sekhar Nori <nsekhar at ti.com>
> Cc: Shawn Guo <shawnguo at kernel.org>
> Cc: Russell King <linux at arm.linux.org.uk>
> Cc: Roland Stigge <stigge at antcom.de>
> Cc: Jason Cooper <jason at lakedaemon.net>
> Cc: Ray Jui <rjui at broadcom.com>
> Cc: Viresh Kumar <vireshk at kernel.org>
> Cc: Stephen Warren <swarren at wwwdotorg.org>
> Cc: Rob Herring <robh at kernel.org>
> Cc: Michal Simek <michal.simek at xilinx.com>
> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> ---
>  arch/arm/mach-spear/spear300.c           | 3 +--
>  arch/arm/mach-spear/spear310.c           | 3 +--
>  arch/arm/mach-spear/spear320.c           | 3 +--
>  arch/arm/mach-spear/spear6xx.c           | 3 +--

Acked-by: Viresh Kumar <viresh.kumar at linaro.org>

-- 
viresh


From Vineet.Gupta1 at synopsys.com  Thu May 12 20:03:36 2016
From: Vineet.Gupta1 at synopsys.com (Vineet Gupta)
Date: Fri, 13 May 2016 03:03:36 +0000
Subject: [PATCH v4 02/18] arc: Remove unnecessary of_platform_populate
 with default match table
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463054775-18170-3-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <C2D7FE5348E1B147BCA15975FBA23075F4EA216B@us01wembx1.internal.synopsys.com>

On Thursday 12 May 2016 05:32 PM, Kefeng Wang wrote:
> After patch "of/platform: Add common method to populate default bus",
> it is possible for arch code to remove unnecessary callers about the
> of_platform_populate with default match table.
>
> Cc: Vineet Gupta <vgupta at synopsys.com>
> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>

Acked-by: Vineet Gupta <vgupta at synopsys.com>



From robh at kernel.org  Thu May 12 20:09:08 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 12 May 2016 22:09:08 -0500
Subject: [PATCH 3/6] dt-bindings: mtu3: add devicetree bindings
In-Reply-To: <1463104820.11651.125.camel@mhfsdcap03>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462868614-20602-4-git-send-email-chunfeng.yun@mediatek.com>
 <20160511145409.GA23042@rob-hp-laptop> <1463037844.11651.118.camel@mhfsdcap03>
 <CAOGqxeUYEGKq5yhHbgcjPZtY06ZfDp2iCLZDqS3uyfCW523B4w@mail.gmail.com>
 <1463104820.11651.125.camel@mhfsdcap03>
Message-ID: <CAL_JsqJKW_C-LtCchAMn5c_VHxBz6n3DBBRFn9hCXcaAbpZrUg@mail.gmail.com>

On Thu, May 12, 2016 at 9:00 PM, chunfeng yun <chunfeng.yun at mediatek.com> wrote:
> Hi,
>
> On Thu, 2016-05-12 at 19:02 -0400, Alan Cooper wrote:
>> On Thu, May 12, 2016 at 3:24 AM, chunfeng yun <chunfeng.yun at mediatek.com> wrote:
>> >> > + - mediatek,enable-manual-drd : supports manual dual-role switch by sysfs
>> >> > +   interface; only used when receptacle is TYPE-A and also wants to support
>> >> > +   dual-role mode.
>> >>
>> >> sysfs is a Linux detail that doesn't apply to the binding. Does the
>> >> property mean "the IP block supports or doesn't support switching"  or
>> >> "I want to enable switching feature". Only the former belongs in DT.
>> >>
>> > It is the former case, and has little relation with sysfs interface.
>> > I will modify it later, sorry for my unclear description.
>>
>> Could the property name be just "enable-manual-drd" instead of
>> "mediatek,enable-manual-drd"? I expect to have to add this
>> functionality to our USB driver in the near future.
>
> Do you mean provide some APIs to in common USB driver?

Probably, but first just put the property in a common binding doc.

Rob


From chunfeng.yun at mediatek.com  Thu May 12 20:19:13 2016
From: chunfeng.yun at mediatek.com (chunfeng yun)
Date: Fri, 13 May 2016 11:19:13 +0800
Subject: [PATCH 3/6] dt-bindings: mtu3: add devicetree bindings
In-Reply-To: <CAL_JsqJKW_C-LtCchAMn5c_VHxBz6n3DBBRFn9hCXcaAbpZrUg@mail.gmail.com>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462868614-20602-4-git-send-email-chunfeng.yun@mediatek.com>
 <20160511145409.GA23042@rob-hp-laptop>
 <1463037844.11651.118.camel@mhfsdcap03>
 <CAOGqxeUYEGKq5yhHbgcjPZtY06ZfDp2iCLZDqS3uyfCW523B4w@mail.gmail.com>
 <1463104820.11651.125.camel@mhfsdcap03>
 <CAL_JsqJKW_C-LtCchAMn5c_VHxBz6n3DBBRFn9hCXcaAbpZrUg@mail.gmail.com>
Message-ID: <1463109553.11651.127.camel@mhfsdcap03>

On Thu, 2016-05-12 at 22:09 -0500, Rob Herring wrote:
> On Thu, May 12, 2016 at 9:00 PM, chunfeng yun <chunfeng.yun at mediatek.com> wrote:
> > Hi,
> >
> > On Thu, 2016-05-12 at 19:02 -0400, Alan Cooper wrote:
> >> On Thu, May 12, 2016 at 3:24 AM, chunfeng yun <chunfeng.yun at mediatek.com> wrote:
> >> >> > + - mediatek,enable-manual-drd : supports manual dual-role switch by sysfs
> >> >> > +   interface; only used when receptacle is TYPE-A and also wants to support
> >> >> > +   dual-role mode.
> >> >>
> >> >> sysfs is a Linux detail that doesn't apply to the binding. Does the
> >> >> property mean "the IP block supports or doesn't support switching"  or
> >> >> "I want to enable switching feature". Only the former belongs in DT.
> >> >>
> >> > It is the former case, and has little relation with sysfs interface.
> >> > I will modify it later, sorry for my unclear description.
> >>
> >> Could the property name be just "enable-manual-drd" instead of
> >> "mediatek,enable-manual-drd"? I expect to have to add this
> >> functionality to our USB driver in the near future.
> >
> > Do you mean provide some APIs to in common USB driver?
> 
> Probably, but first just put the property in a common binding doc.
> 
Ok, I modify it later

Thanks.

> Rob




From andy.gross at linaro.org  Thu May 12 20:46:53 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 22:46:53 -0500
Subject: [Patch v5 0/8] Qualcomm SCM Rework
Message-ID: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>

The following set of patches does a bit of rework on the existing
Qualcomm SCM firmware.  The first couple of patches deals with turning
the current SCM into a platform driver.  The next couple are cleanups
that make adding the 64 support a little easier.  I added in a patch to
convert the scm-32 to use DMA streaming APIs.

I took Kumar's 64 bit support patch and modified it to use the arm_smccc
calls.  This simplified things quite a bit.

Lastly, there are a few DT patches to add the firmware node for a couple of the
supported platforms.

Changes from v4:
  * Fix Documentation error
  * Fix misc review comments

Changes from v3:
  * Added compatibles for the specific platforms requiring one clock.
  * All other platforms will use the generic binding that requires 3 clocks.

Changes from v2:
  * Added use of streaming DMA APIs for scm-32.
  * Changed DT binding to simplify compats.
  * Removed Kconfig.platform change that selected QCOM_SCM for ARM64
  * Fixed misc comments
  * Changed init function to populate the device differently.
  * Fixed missing of_node_put

Changes from v1:
  * Changed binding to reflect proper firmware node usage
  * Added arch_initcall to populate the firmware device, if present
  * Fixed various review comments
  * Removed extraneous includes from SCM 64 file.


Andy Gross (7):
  dt/bindings: firmware: Add Qualcomm SCM binding
  firmware: qcom: scm: Convert SCM to platform driver
  firmware: qcom: scm: Use atomic SCM for cold boot
  firmware: qcom: scm: Generalize shared error map
  firmware: qcom: scm: Convert to streaming DMA APIS
  dts: qcom: apq8084: Add SCM firmware node
  arm64: dts: msm8916: Add SCM firmware node

Kumar Gala (1):
  firmware: qcom: scm: Add support for ARM64 SoCs

 .../devicetree/bindings/firmware/qcom,scm.txt      |  28 +++
 arch/arm/boot/dts/qcom-apq8084.dtsi                |   8 +
 arch/arm64/boot/dts/qcom/msm8916.dtsi              |   8 +
 drivers/firmware/qcom_scm-32.c                     | 271 ++++++++-------------
 drivers/firmware/qcom_scm-64.c                     | 199 ++++++++++++++-
 drivers/firmware/qcom_scm.c                        | 171 ++++++++++++-
 drivers/firmware/qcom_scm.h                        |  31 ++-
 7 files changed, 523 insertions(+), 193 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/firmware/qcom,scm.txt

-- 
1.9.1



From andy.gross at linaro.org  Thu May 12 20:46:56 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 22:46:56 -0500
Subject: [Patch v5 3/8] firmware: qcom: scm: Use atomic SCM for cold boot
In-Reply-To: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463111221-6963-4-git-send-email-andy.gross@linaro.org>

This patch changes the cold_set_boot_addr function to use atomic SCM
calls.  cold_set_boot_addr required adding qcom_scm_call_atomic2 to
support the two arguments going to the smc call.  Using atomic removes
the need for memory allocation and instead places all arguments in
registers.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm-32.c | 63 ++++++++++++++++++++++++++++++------------
 1 file changed, 45 insertions(+), 18 deletions(-)

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 0883292..5be6a12 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -342,6 +342,41 @@ static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
 	return r0;
 }
 
+/**
+ * qcom_scm_call_atomic2() - Send an atomic SCM command with two arguments
+ * @svc_id:	service identifier
+ * @cmd_id:	command identifier
+ * @arg1:	first argument
+ * @arg2:	second argument
+ *
+ * This shall only be used with commands that are guaranteed to be
+ * uninterruptable, atomic and SMP safe.
+ */
+static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2)
+{
+	int context_id;
+
+	register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 2);
+	register u32 r1 asm("r1") = (u32)&context_id;
+	register u32 r2 asm("r2") = arg1;
+	register u32 r3 asm("r3") = arg2;
+
+	asm volatile(
+			__asmeq("%0", "r0")
+			__asmeq("%1", "r0")
+			__asmeq("%2", "r1")
+			__asmeq("%3", "r2")
+			__asmeq("%4", "r3")
+#ifdef REQUIRES_SEC
+			".arch_extension sec\n"
+#endif
+			"smc    #0      @ switch to secure world\n"
+			: "=r" (r0)
+			: "r" (r0), "r" (r1), "r" (r2), "r" (r3)
+			);
+	return r0;
+}
+
 u32 qcom_scm_get_version(void)
 {
 	int context_id;
@@ -378,22 +413,6 @@ u32 qcom_scm_get_version(void)
 }
 EXPORT_SYMBOL(qcom_scm_get_version);
 
-/*
- * Set the cold/warm boot address for one of the CPU cores.
- */
-static int qcom_scm_set_boot_addr(u32 addr, int flags)
-{
-	struct {
-		__le32 flags;
-		__le32 addr;
-	} cmd;
-
-	cmd.addr = cpu_to_le32(addr);
-	cmd.flags = cpu_to_le32(flags);
-	return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
-			&cmd, sizeof(cmd), NULL, 0);
-}
-
 /**
  * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
  * @entry: Entry point function for the cpus
@@ -423,7 +442,8 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
 			set_cpu_present(cpu, false);
 	}
 
-	return qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
+	return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
+				    flags, virt_to_phys(entry));
 }
 
 /**
@@ -439,6 +459,10 @@ int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
 	int ret;
 	int flags = 0;
 	int cpu;
+	struct {
+		__le32 flags;
+		__le32 addr;
+	} cmd;
 
 	/*
 	 * Reassign only if we are switching from hotplug entry point
@@ -454,7 +478,10 @@ int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
 	if (!flags)
 		return 0;
 
-	ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
+	cmd.addr = cpu_to_le32(virt_to_phys(entry));
+	cmd.flags = cpu_to_le32(flags);
+	ret = qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
+			    &cmd, sizeof(cmd), NULL, 0);
 	if (!ret) {
 		for_each_cpu(cpu, cpus)
 			qcom_scm_wb[cpu].entry = entry;
-- 
1.9.1



From andy.gross at linaro.org  Thu May 12 20:46:54 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 22:46:54 -0500
Subject: [Patch v5 1/8] dt/bindings: firmware: Add Qualcomm SCM binding
In-Reply-To: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463111221-6963-2-git-send-email-andy.gross@linaro.org>

This patch adds the device tree support for the Qualcomm SCM firmware.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 .../devicetree/bindings/firmware/qcom,scm.txt      | 28 ++++++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/qcom,scm.txt

diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
new file mode 100644
index 0000000..3b4436e
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
@@ -0,0 +1,28 @@
+QCOM Secure Channel Manager (SCM)
+
+Qualcomm processors include an interface to communicate to the secure firmware.
+This interface allows for clients to request different types of actions.  These
+can include CPU power up/down, HDCP requests, loading of firmware, and other
+assorted actions.
+
+Required properties:
+- compatible: must contain one of the following:
+ * "qcom,scm-apq8064" for APQ8064 platforms
+ * "qcom,scm-msm8660" for MSM8660 platforms
+ * "qcom,scm-msm8690" for MSM8690 platforms
+ * "qcom,scm" for later processors (MSM8916, APQ8084, MSM8974, etc)
+- clocks: One to three clocks may be required based on compatible.
+ * Only core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660", and "qcom,scm-msm8960"
+ * Core, iface, and bus clocks required for "qcom,scm"
+- clock-names: Must contain "core" for the core clock, "iface" for the interface
+  clock and "bus" for the bus clock per the requirements of the compatible.
+
+Example for MSM8916:
+
+	firmware {
+		scm {
+			compatible = "qcom,scm";
+			clocks = <&gcc GCC_CRYPTO_CLK> , <&gcc GCC_CRYPTO_AXI_CLK>, <&gcc GCC_CRYPTO_AHB_CLK>;
+			clock-names = "core", "bus", "iface";
+		};
+	};
-- 
1.9.1



From andy.gross at linaro.org  Thu May 12 20:46:55 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 22:46:55 -0500
Subject: [Patch v5 2/8] firmware: qcom: scm: Convert SCM to platform driver
In-Reply-To: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463111221-6963-3-git-send-email-andy.gross@linaro.org>

This patch converts the Qualcomm SCM firmware driver into a platform
driver.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm.c | 165 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 156 insertions(+), 9 deletions(-)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 45c008d..4d6ae32 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -10,19 +10,61 @@
  * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
  */
-
+#include <linux/platform_device.h>
+#include <linux/module.h>
 #include <linux/cpumask.h>
 #include <linux/export.h>
 #include <linux/types.h>
 #include <linux/qcom_scm.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
 
 #include "qcom_scm.h"
 
+struct qcom_scm {
+	struct device *dev;
+	struct clk *core_clk;
+	struct clk *iface_clk;
+	struct clk *bus_clk;
+};
+
+static struct qcom_scm *__scm;
+
+static int qcom_scm_clk_enable(void)
+{
+	int ret;
+
+	ret = clk_prepare_enable(__scm->core_clk);
+	if (ret)
+		goto bail;
+
+	ret = clk_prepare_enable(__scm->iface_clk);
+	if (ret)
+		goto disable_core;
+
+	ret = clk_prepare_enable(__scm->bus_clk);
+	if (ret)
+		goto disable_iface;
+
+	return 0;
+
+disable_iface:
+	clk_disable_unprepare(__scm->iface_clk);
+disable_core:
+	clk_disable_unprepare(__scm->core_clk);
+bail:
+	return ret;
+}
+
+static void qcom_scm_clk_disable(void)
+{
+	clk_disable_unprepare(__scm->core_clk);
+	clk_disable_unprepare(__scm->iface_clk);
+	clk_disable_unprepare(__scm->bus_clk);
+}
+
 /**
  * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
  * @entry: Entry point function for the cpus
@@ -72,12 +114,17 @@ EXPORT_SYMBOL(qcom_scm_cpu_power_down);
  */
 bool qcom_scm_hdcp_available(void)
 {
-	int ret;
+	int ret = qcom_scm_clk_enable();
+
+	if (ret)
+		return ret;
 
 	ret = __qcom_scm_is_call_available(QCOM_SCM_SVC_HDCP,
-		QCOM_SCM_CMD_HDCP);
+						QCOM_SCM_CMD_HDCP);
+
+	qcom_scm_clk_disable();
 
-	return (ret > 0) ? true : false;
+	return ret > 0 ? true : false;
 }
 EXPORT_SYMBOL(qcom_scm_hdcp_available);
 
@@ -91,6 +138,106 @@ EXPORT_SYMBOL(qcom_scm_hdcp_available);
  */
 int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
 {
-	return __qcom_scm_hdcp_req(req, req_cnt, resp);
+	int ret = qcom_scm_clk_enable();
+
+	if (ret)
+		return ret;
+
+	ret = __qcom_scm_hdcp_req(req, req_cnt, resp);
+	qcom_scm_clk_disable();
+	return ret;
 }
 EXPORT_SYMBOL(qcom_scm_hdcp_req);
+
+static int qcom_scm_probe(struct platform_device *pdev)
+{
+	struct qcom_scm *scm;
+	int ret;
+
+	scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL);
+	if (!scm)
+		return -ENOMEM;
+
+	scm->core_clk = devm_clk_get(&pdev->dev, "core");
+	if (IS_ERR(scm->core_clk)) {
+		if (PTR_ERR(scm->core_clk) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "failed to acquire core clk\n");
+		return PTR_ERR(scm->core_clk);
+	}
+
+	if (of_device_is_compatible(pdev->dev.of_node, "qcom,scm")) {
+		scm->iface_clk = devm_clk_get(&pdev->dev, "iface");
+		if (IS_ERR(scm->iface_clk)) {
+			if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER)
+				dev_err(&pdev->dev, "failed to acquire iface clk\n");
+			return PTR_ERR(scm->iface_clk);
+		}
+
+		scm->bus_clk = devm_clk_get(&pdev->dev, "bus");
+		if (IS_ERR(scm->bus_clk)) {
+			if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER)
+				dev_err(&pdev->dev, "failed to acquire bus clk\n");
+			return PTR_ERR(scm->bus_clk);
+		}
+	}
+
+	/* vote for max clk rate for highest performance */
+	ret = clk_set_rate(scm->core_clk, INT_MAX);
+	if (ret)
+		return ret;
+
+	__scm = scm;
+	__scm->dev = &pdev->dev;
+
+	return 0;
+}
+
+static const struct of_device_id qcom_scm_dt_match[] = {
+	{ .compatible = "qcom,scm-apq8064",},
+	{ .compatible = "qcom,scm-msm8660",},
+	{ .compatible = "qcom,scm-msm8960",},
+	{ .compatible = "qcom,scm",},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, qcom_scm_dt_match);
+
+static struct platform_driver qcom_scm_driver = {
+	.driver = {
+		.name	= "qcom_scm",
+		.of_match_table = qcom_scm_dt_match,
+	},
+	.probe = qcom_scm_probe,
+};
+
+static int __init qcom_scm_init(void)
+{
+	struct device_node *np, *parent;
+	int ret;
+
+	np = of_find_matching_node_and_match(NULL, qcom_scm_dt_match, NULL);
+
+	if (!np)
+		return -ENODEV;
+
+	parent = of_get_next_parent(np);
+	ret = of_platform_populate(parent, qcom_scm_dt_match, NULL, NULL);
+
+	of_node_put(parent);
+
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&qcom_scm_driver);
+}
+
+arch_initcall(qcom_scm_init);
+
+static void __exit qcom_scm_exit(void)
+{
+	platform_driver_unregister(&qcom_scm_driver);
+}
+module_exit(qcom_scm_exit);
+
+MODULE_DESCRIPTION("Qualcomm SCM driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1



From andy.gross at linaro.org  Thu May 12 20:46:57 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 22:46:57 -0500
Subject: [Patch v5 4/8] firmware: qcom: scm: Generalize shared error map
In-Reply-To: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463111221-6963-5-git-send-email-andy.gross@linaro.org>

This patch moves the qcom_scm_remap_error function to the include file
where can be used by both the 32 and 64 bit versions of the code.

Reviewed-by: Stephen Boyd <sboyd at codeaurora.org>
Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>
Signed-off-by: Andy Gross <agross at codeaurora.org>
Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm-32.c | 17 -----------------
 drivers/firmware/qcom_scm.h    | 16 ++++++++++++++++
 2 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 5be6a12..4388d13 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -168,23 +168,6 @@ static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response
 	return (void *)rsp + le32_to_cpu(rsp->buf_offset);
 }
 
-static int qcom_scm_remap_error(int err)
-{
-	pr_err("qcom_scm_call failed with error code %d\n", err);
-	switch (err) {
-	case QCOM_SCM_ERROR:
-		return -EIO;
-	case QCOM_SCM_EINVAL_ADDR:
-	case QCOM_SCM_EINVAL_ARG:
-		return -EINVAL;
-	case QCOM_SCM_EOPNOTSUPP:
-		return -EOPNOTSUPP;
-	case QCOM_SCM_ENOMEM:
-		return -ENOMEM;
-	}
-	return -EINVAL;
-}
-
 static u32 smc(u32 cmd_addr)
 {
 	int context_id;
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index 2cce75c..7dcc733 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -44,4 +44,20 @@ extern int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
 #define QCOM_SCM_ERROR		-1
 #define QCOM_SCM_INTERRUPTED	1
 
+static inline int qcom_scm_remap_error(int err)
+{
+	switch (err) {
+	case QCOM_SCM_ERROR:
+		return -EIO;
+	case QCOM_SCM_EINVAL_ADDR:
+	case QCOM_SCM_EINVAL_ARG:
+		return -EINVAL;
+	case QCOM_SCM_EOPNOTSUPP:
+		return -EOPNOTSUPP;
+	case QCOM_SCM_ENOMEM:
+		return -ENOMEM;
+	}
+	return -EINVAL;
+}
+
 #endif
-- 
1.9.1



From andy.gross at linaro.org  Thu May 12 20:46:59 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 22:46:59 -0500
Subject: [Patch v5 6/8] firmware: qcom: scm: Add support for ARM64 SoCs
In-Reply-To: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463111221-6963-7-git-send-email-andy.gross@linaro.org>

From: Kumar Gala <galak at codeaurora.org>

Add an implementation of the SCM interface that works on ARM64 SoCs.  This
is used by things like determine if we have HDCP support or not on the
system.

Signed-off-by: Kumar Gala <galak at codeaurora.org>
Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm-32.c |   4 +
 drivers/firmware/qcom_scm-64.c | 199 +++++++++++++++++++++++++++++++++++++++--
 drivers/firmware/qcom_scm.c    |   2 +
 drivers/firmware/qcom_scm.h    |   5 ++
 4 files changed, 205 insertions(+), 5 deletions(-)

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index e92bf7a..4971b55 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -420,3 +420,7 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
 	return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
 		req, req_cnt * sizeof(*req), resp, sizeof(*resp));
 }
+
+void __qcom_scm_init(void)
+{
+}
diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c
index bb6555f..43ed4de 100644
--- a/drivers/firmware/qcom_scm-64.c
+++ b/drivers/firmware/qcom_scm-64.c
@@ -12,7 +12,143 @@
 
 #include <linux/io.h>
 #include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
 #include <linux/qcom_scm.h>
+#include <linux/arm-smccc.h>
+#include <linux/dma-mapping.h>
+
+#include "qcom_scm.h"
+
+#define QCOM_SCM_FNID(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF))
+
+#define MAX_QCOM_SCM_ARGS 10
+#define MAX_QCOM_SCM_RETS 3
+
+#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\
+			   (((a) & 0x3) << 4) | \
+			   (((b) & 0x3) << 6) | \
+			   (((c) & 0x3) << 8) | \
+			   (((d) & 0x3) << 10) | \
+			   (((e) & 0x3) << 12) | \
+			   (((f) & 0x3) << 14) | \
+			   (((g) & 0x3) << 16) | \
+			   (((h) & 0x3) << 18) | \
+			   (((i) & 0x3) << 20) | \
+			   (((j) & 0x3) << 22) | \
+			   (num & 0xf))
+
+#define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+
+/**
+ * struct qcom_scm_desc
+ * @arginfo:	Metadata describing the arguments in args[]
+ * @args:	The array of arguments for the secure syscall
+ * @res:	The values returned by the secure syscall
+ */
+struct qcom_scm_desc {
+	u32 arginfo;
+	u64 args[MAX_QCOM_SCM_ARGS];
+	struct arm_smccc_res res;
+};
+
+static u64 qcom_smccc_convention = -1;
+static DEFINE_MUTEX(qcom_scm_lock);
+
+#define QCOM_SCM_EBUSY_WAIT_MS 30
+#define QCOM_SCM_EBUSY_MAX_RETRY 20
+
+#define N_EXT_QCOM_SCM_ARGS 7
+#define FIRST_EXT_ARG_IDX 3
+#define N_REGISTER_ARGS (MAX_QCOM_SCM_ARGS - N_EXT_QCOM_SCM_ARGS + 1)
+
+/**
+ * qcom_scm_call() - Invoke a syscall in the secure world
+ * @dev:	device
+ * @svc_id:	service identifier
+ * @cmd_id:	command identifier
+ * @desc:	Descriptor structure containing arguments and return values
+ *
+ * Sends a command to the SCM and waits for the command to finish processing.
+ * This should *only* be called in pre-emptible context.
+*/
+static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
+			 struct qcom_scm_desc *desc)
+{
+	int arglen = desc->arginfo & 0xf;
+	int retry_count = 0, i;
+	u32 fn_id = QCOM_SCM_FNID(svc_id, cmd_id);
+	u64 cmd, x5 = desc->args[FIRST_EXT_ARG_IDX];
+	dma_addr_t args_phys = 0;
+	void *args_virt = NULL;
+	size_t alloc_len;
+
+	if (unlikely(arglen > N_REGISTER_ARGS)) {
+		alloc_len = N_EXT_QCOM_SCM_ARGS * sizeof(u64);
+		args_virt = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
+
+		if (!args_virt)
+			return qcom_scm_remap_error(-ENOMEM);
+
+		if (qcom_smccc_convention == ARM_SMCCC_SMC_32) {
+			__le32 *args = args_virt;
+
+			for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
+				args[i] = cpu_to_le32(desc->args[i +
+						      FIRST_EXT_ARG_IDX]);
+		} else {
+			__le64 *args = args_virt;
+
+			for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
+				args[i] = cpu_to_le64(desc->args[i +
+						      FIRST_EXT_ARG_IDX]);
+		}
+
+		args_phys = dma_map_single(dev, args_virt, alloc_len,
+					   DMA_TO_DEVICE);
+
+		if (dma_mapping_error(dev, args_phys)) {
+			kfree(args_virt);
+			return qcom_scm_remap_error(-ENOMEM);
+		}
+
+		x5 = args_phys;
+	}
+
+	do {
+		mutex_lock(&qcom_scm_lock);
+
+		cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL,
+					 qcom_smccc_convention,
+					 ARM_SMCCC_OWNER_SIP, fn_id);
+
+		do {
+			arm_smccc_smc(cmd, desc->arginfo, desc->args[0],
+				      desc->args[1], desc->args[2], x5, 0, 0,
+				      &desc->res);
+		} while (desc->res.a0 == QCOM_SCM_INTERRUPTED);
+
+		mutex_unlock(&qcom_scm_lock);
+
+		if (desc->res.a0 == QCOM_SCM_V2_EBUSY) {
+			if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY)
+				break;
+			msleep(QCOM_SCM_EBUSY_WAIT_MS);
+		}
+	}  while (desc->res.a0 == QCOM_SCM_V2_EBUSY);
+
+	if (args_virt) {
+		dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE);
+		kfree(args_virt);
+	}
+
+	if (desc->res.a0 < 0)
+		return qcom_scm_remap_error(desc->res.a0);
+
+	return 0;
+}
 
 /**
  * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
@@ -29,13 +165,15 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
 
 /**
  * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
+ * @dev: Device pointer
  * @entry: Entry point function for the cpus
  * @cpus: The cpumask of cpus that will use the entry point
  *
  * Set the Linux entry point for the SCM to transfer control to when coming
  * out of a power down. CPU power down may be executed on cpuidle or hotplug.
  */
-int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
+int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
+				  const cpumask_t *cpus)
 {
 	return -ENOTSUPP;
 }
@@ -52,12 +190,63 @@ void __qcom_scm_cpu_power_down(u32 flags)
 {
 }
 
-int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
+int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
 {
-	return -ENOTSUPP;
+	int ret;
+	struct qcom_scm_desc desc = {0};
+
+	desc.arginfo = QCOM_SCM_ARGS(1);
+	desc.args[0] = QCOM_SCM_FNID(svc_id, cmd_id) |
+			(ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT);
+
+	ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD,
+			    &desc);
+
+	return ret ? : desc.res.a1;
 }
 
-int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
+int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
+			u32 req_cnt, u32 *resp)
 {
-	return -ENOTSUPP;
+	int ret;
+	struct qcom_scm_desc desc = {0};
+
+	if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
+		return -ERANGE;
+
+	desc.args[0] = req[0].addr;
+	desc.args[1] = req[0].val;
+	desc.args[2] = req[1].addr;
+	desc.args[3] = req[1].val;
+	desc.args[4] = req[2].addr;
+	desc.args[5] = req[2].val;
+	desc.args[6] = req[3].addr;
+	desc.args[7] = req[3].val;
+	desc.args[8] = req[4].addr;
+	desc.args[9] = req[4].val;
+	desc.arginfo = QCOM_SCM_ARGS(10);
+
+	ret = qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP, &desc);
+	*resp = desc.res.a1;
+
+	return ret;
+}
+
+void __qcom_scm_init(void)
+{
+	u64 cmd;
+	struct arm_smccc_res res;
+	u32 function = QCOM_SCM_FNID(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD);
+
+	/* First try a SMC64 call */
+	cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64,
+				 ARM_SMCCC_OWNER_SIP, function);
+
+	arm_smccc_smc(cmd, QCOM_SCM_ARGS(1), cmd & (~BIT(ARM_SMCCC_TYPE_SHIFT)),
+		      0, 0, 0, 0, 0, &res);
+
+	if (!res.a0 && res.a1)
+		qcom_smccc_convention = ARM_SMCCC_SMC_64;
+	else
+		qcom_smccc_convention = ARM_SMCCC_SMC_32;
 }
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 23ccec6..475410b3e 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -189,6 +189,8 @@ static int qcom_scm_probe(struct platform_device *pdev)
 	__scm = scm;
 	__scm->dev = &pdev->dev;
 
+	__qcom_scm_init();
+
 	return 0;
 }
 
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index afe6676..0ea55d7 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -38,7 +38,10 @@ extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
 extern int __qcom_scm_hdcp_req(struct device *dev,
 		struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);
 
+extern void __qcom_scm_init(void);
+
 /* common error codes */
+#define QCOM_SCM_V2_EBUSY	-12
 #define QCOM_SCM_ENOMEM		-5
 #define QCOM_SCM_EOPNOTSUPP	-4
 #define QCOM_SCM_EINVAL_ADDR	-3
@@ -58,6 +61,8 @@ static inline int qcom_scm_remap_error(int err)
 		return -EOPNOTSUPP;
 	case QCOM_SCM_ENOMEM:
 		return -ENOMEM;
+	case QCOM_SCM_V2_EBUSY:
+		return -EBUSY;
 	}
 	return -EINVAL;
 }
-- 
1.9.1



From andy.gross at linaro.org  Thu May 12 20:47:01 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 22:47:01 -0500
Subject: [Patch v5 8/8] arm64: dts: msm8916: Add SCM firmware node
In-Reply-To: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463111221-6963-9-git-send-email-andy.gross@linaro.org>

This adds the devicetree node for the SCM firmware.

Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>
Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 arch/arm64/boot/dts/qcom/msm8916.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 9681200..01c7b0c 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -122,6 +122,14 @@
 		hwlocks = <&tcsr_mutex 3>;
 	};
 
+	firmware {
+		scm {
+			compatible = "qcom,scm";
+			clocks = <&gcc GCC_CRYPTO_CLK>, <&gcc GCC_CRYPTO_AXI_CLK>, <&gcc GCC_CRYPTO_AHB_CLK>;
+			clock-names = "core", "bus", "iface";
+		};
+	};
+
 	soc: soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
-- 
1.9.1



From andy.gross at linaro.org  Thu May 12 20:46:58 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 22:46:58 -0500
Subject: [Patch v5 5/8] firmware: qcom: scm: Convert to streaming DMA APIS
In-Reply-To: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463111221-6963-6-git-send-email-andy.gross@linaro.org>

This patch converts the Qualcomm SCM driver to use the streaming DMA APIs
for communication buffers.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/firmware/qcom_scm-32.c | 189 +++++++++++------------------------------
 drivers/firmware/qcom_scm.c    |   6 +-
 drivers/firmware/qcom_scm.h    |  10 ++-
 3 files changed, 59 insertions(+), 146 deletions(-)

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 4388d13..e92bf7a 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -23,8 +23,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/qcom_scm.h>
-
-#include <asm/cacheflush.h>
+#include <linux/dma-mapping.h>
 
 #include "qcom_scm.h"
 
@@ -64,11 +63,11 @@ static DEFINE_MUTEX(qcom_scm_lock);
  *
  *	------------------- <--- struct qcom_scm_command
  *	| command header  |
- *	------------------- <--- qcom_scm_get_command_buffer()
+ *	------------------- <--- buf[0]
  *	| command buffer  |
- *	------------------- <--- struct qcom_scm_response and
- *	| response header |      qcom_scm_command_to_response()
- *	------------------- <--- qcom_scm_get_response_buffer()
+ *	------------------- <--- struct qcom_scm_response
+ *	| response header |
+ *	-------------------
  *	| response buffer |
  *	-------------------
  *
@@ -96,79 +95,7 @@ struct qcom_scm_response {
 	__le32 is_complete;
 };
 
-/**
- * alloc_qcom_scm_command() - Allocate an SCM command
- * @cmd_size: size of the command buffer
- * @resp_size: size of the response buffer
- *
- * Allocate an SCM command, including enough room for the command
- * and response headers as well as the command and response buffers.
- *
- * Returns a valid &qcom_scm_command on success or %NULL if the allocation fails.
- */
-static struct qcom_scm_command *alloc_qcom_scm_command(size_t cmd_size, size_t resp_size)
-{
-	struct qcom_scm_command *cmd;
-	size_t len = sizeof(*cmd) + sizeof(struct qcom_scm_response) + cmd_size +
-		resp_size;
-	u32 offset;
-
-	cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
-	if (cmd) {
-		cmd->len = cpu_to_le32(len);
-		offset = offsetof(struct qcom_scm_command, buf);
-		cmd->buf_offset = cpu_to_le32(offset);
-		cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
-	}
-	return cmd;
-}
-
-/**
- * free_qcom_scm_command() - Free an SCM command
- * @cmd: command to free
- *
- * Free an SCM command.
- */
-static inline void free_qcom_scm_command(struct qcom_scm_command *cmd)
-{
-	kfree(cmd);
-}
-
-/**
- * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response
- * @cmd: command
- *
- * Returns a pointer to a response for a command.
- */
-static inline struct qcom_scm_response *qcom_scm_command_to_response(
-		const struct qcom_scm_command *cmd)
-{
-	return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
-}
-
-/**
- * qcom_scm_get_command_buffer() - Get a pointer to a command buffer
- * @cmd: command
- *
- * Returns a pointer to the command buffer of a command.
- */
-static inline void *qcom_scm_get_command_buffer(const struct qcom_scm_command *cmd)
-{
-	return (void *)cmd->buf;
-}
-
-/**
- * qcom_scm_get_response_buffer() - Get a pointer to a response buffer
- * @rsp: response
- *
- * Returns a pointer to a response buffer of a response.
- */
-static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response *rsp)
-{
-	return (void *)rsp + le32_to_cpu(rsp->buf_offset);
-}
-
-static u32 smc(u32 cmd_addr)
+static u32 smc(dma_addr_t cmd_addr)
 {
 	int context_id;
 	register u32 r0 asm("r0") = 1;
@@ -192,45 +119,9 @@ static u32 smc(u32 cmd_addr)
 	return r0;
 }
 
-static int __qcom_scm_call(const struct qcom_scm_command *cmd)
-{
-	int ret;
-	u32 cmd_addr = virt_to_phys(cmd);
-
-	/*
-	 * Flush the command buffer so that the secure world sees
-	 * the correct data.
-	 */
-	secure_flush_area(cmd, cmd->len);
-
-	ret = smc(cmd_addr);
-	if (ret < 0)
-		ret = qcom_scm_remap_error(ret);
-
-	return ret;
-}
-
-static void qcom_scm_inv_range(unsigned long start, unsigned long end)
-{
-	u32 cacheline_size, ctr;
-
-	asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
-	cacheline_size = 4 << ((ctr >> 16) & 0xf);
-
-	start = round_down(start, cacheline_size);
-	end = round_up(end, cacheline_size);
-	outer_inv_range(start, end);
-	while (start < end) {
-		asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
-		     : "memory");
-		start += cacheline_size;
-	}
-	dsb();
-	isb();
-}
-
 /**
  * qcom_scm_call() - Send an SCM command
+ * @dev: struct device
  * @svc_id: service identifier
  * @cmd_id: command identifier
  * @cmd_buf: command buffer
@@ -247,42 +138,59 @@ static void qcom_scm_inv_range(unsigned long start, unsigned long end)
  * and response buffers is taken care of by qcom_scm_call; however, callers are
  * responsible for any other cached buffers passed over to the secure world.
  */
-static int qcom_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf,
-			size_t cmd_len, void *resp_buf, size_t resp_len)
+static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
+			 const void *cmd_buf, size_t cmd_len, void *resp_buf,
+			 size_t resp_len)
 {
 	int ret;
 	struct qcom_scm_command *cmd;
 	struct qcom_scm_response *rsp;
-	unsigned long start, end;
+	size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len;
+	dma_addr_t cmd_phys;
 
-	cmd = alloc_qcom_scm_command(cmd_len, resp_len);
+	cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
 	if (!cmd)
 		return -ENOMEM;
 
+	cmd->len = cpu_to_le32(alloc_len);
+	cmd->buf_offset = cpu_to_le32(sizeof(*cmd));
+	cmd->resp_hdr_offset = cpu_to_le32(sizeof(*cmd) + cmd_len);
+
 	cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
 	if (cmd_buf)
-		memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len);
+		memcpy(cmd->buf, cmd_buf, cmd_len);
+
+	rsp = (void *)cmd->buf + le32_to_cpu(cmd->resp_hdr_offset);
+
+	cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, cmd_phys)) {
+		kfree(cmd);
+		return -ENOMEM;
+	}
 
 	mutex_lock(&qcom_scm_lock);
-	ret = __qcom_scm_call(cmd);
+	ret = smc(cmd_phys);
+	if (ret < 0)
+		ret = qcom_scm_remap_error(ret);
 	mutex_unlock(&qcom_scm_lock);
 	if (ret)
 		goto out;
 
-	rsp = qcom_scm_command_to_response(cmd);
-	start = (unsigned long)rsp;
-
 	do {
-		qcom_scm_inv_range(start, start + sizeof(*rsp));
+		dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len,
+					sizeof(*rsp), DMA_FROM_DEVICE);
 	} while (!rsp->is_complete);
 
-	end = (unsigned long)qcom_scm_get_response_buffer(rsp) + resp_len;
-	qcom_scm_inv_range(start, end);
-
-	if (resp_buf)
-		memcpy(resp_buf, qcom_scm_get_response_buffer(rsp), resp_len);
+	if (resp_buf) {
+		dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len +
+					le32_to_cpu(rsp->buf_offset),
+					resp_len, DMA_FROM_DEVICE);
+		memcpy(resp_buf, (void *)rsp + le32_to_cpu(rsp->buf_offset),
+		       resp_len);
+	}
 out:
-	free_qcom_scm_command(cmd);
+	dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE);
+	kfree(cmd);
 	return ret;
 }
 
@@ -437,7 +345,8 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
  * Set the Linux entry point for the SCM to transfer control to when coming
  * out of a power down. CPU power down may be executed on cpuidle or hotplug.
  */
-int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
+int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
+				  const cpumask_t *cpus)
 {
 	int ret;
 	int flags = 0;
@@ -463,7 +372,7 @@ int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
 
 	cmd.addr = cpu_to_le32(virt_to_phys(entry));
 	cmd.flags = cpu_to_le32(flags);
-	ret = qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
+	ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
 			    &cmd, sizeof(cmd), NULL, 0);
 	if (!ret) {
 		for_each_cpu(cpu, cpus)
@@ -487,25 +396,27 @@ void __qcom_scm_cpu_power_down(u32 flags)
 			flags & QCOM_SCM_FLUSH_FLAG_MASK);
 }
 
-int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
+int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
 {
 	int ret;
 	__le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id);
 	__le32 ret_val = 0;
 
-	ret = qcom_scm_call(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, &svc_cmd,
-			sizeof(svc_cmd), &ret_val, sizeof(ret_val));
+	ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD,
+			    &svc_cmd, sizeof(svc_cmd), &ret_val,
+			    sizeof(ret_val));
 	if (ret)
 		return ret;
 
 	return le32_to_cpu(ret_val);
 }
 
-int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
+int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
+			u32 req_cnt, u32 *resp)
 {
 	if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
 		return -ERANGE;
 
-	return qcom_scm_call(QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
+	return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
 		req, req_cnt * sizeof(*req), resp, sizeof(*resp));
 }
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 4d6ae32..23ccec6 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -89,7 +89,7 @@ EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
  */
 int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
 {
-	return __qcom_scm_set_warm_boot_addr(entry, cpus);
+	return __qcom_scm_set_warm_boot_addr(__scm->dev, entry, cpus);
 }
 EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
 
@@ -119,7 +119,7 @@ bool qcom_scm_hdcp_available(void)
 	if (ret)
 		return ret;
 
-	ret = __qcom_scm_is_call_available(QCOM_SCM_SVC_HDCP,
+	ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP,
 						QCOM_SCM_CMD_HDCP);
 
 	qcom_scm_clk_disable();
@@ -143,7 +143,7 @@ int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
 	if (ret)
 		return ret;
 
-	ret = __qcom_scm_hdcp_req(req, req_cnt, resp);
+	ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp);
 	qcom_scm_clk_disable();
 	return ret;
 }
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index 7dcc733..afe6676 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -19,7 +19,8 @@
 #define QCOM_SCM_FLAG_HLOS		0x01
 #define QCOM_SCM_FLAG_COLDBOOT_MC	0x02
 #define QCOM_SCM_FLAG_WARMBOOT_MC	0x04
-extern int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus);
+extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
+		const cpumask_t *cpus);
 extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);
 
 #define QCOM_SCM_CMD_TERMINATE_PC	0x2
@@ -29,12 +30,13 @@ extern void __qcom_scm_cpu_power_down(u32 flags);
 
 #define QCOM_SCM_SVC_INFO		0x6
 #define QCOM_IS_CALL_AVAIL_CMD		0x1
-extern int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id);
+extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
+		u32 cmd_id);
 
 #define QCOM_SCM_SVC_HDCP		0x11
 #define QCOM_SCM_CMD_HDCP		0x01
-extern int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
-		u32 *resp);
+extern int __qcom_scm_hdcp_req(struct device *dev,
+		struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);
 
 /* common error codes */
 #define QCOM_SCM_ENOMEM		-5
-- 
1.9.1



From andy.gross at linaro.org  Thu May 12 20:47:00 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 12 May 2016 22:47:00 -0500
Subject: [Patch v5 7/8] dts: qcom: apq8084: Add SCM firmware node
In-Reply-To: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463111221-6963-8-git-send-email-andy.gross@linaro.org>

This patch adds the firmware node for the SCM

Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>
Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 arch/arm/boot/dts/qcom-apq8084.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-apq8084.dtsi b/arch/arm/boot/dts/qcom-apq8084.dtsi
index a33a09f..7c2df06 100644
--- a/arch/arm/boot/dts/qcom-apq8084.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8084.dtsi
@@ -86,6 +86,14 @@
 		};
 	};
 
+	firmware {
+		scm {
+			compatible = "qcom,scm";
+			clocks = <&gcc GCC_CE1_CLK> , <&gcc GCC_CE1_AXI_CLK>, <&gcc GCC_CE1_AHB_CLK>;
+			clock-names = "core", "bus", "iface";
+		};
+	};
+
 	cpu-pmu {
 		compatible = "qcom,krait-pmu";
 		interrupts = <1 7 0xf04>;
-- 
1.9.1



From ck.hu at mediatek.com  Thu May 12 20:59:16 2016
From: ck.hu at mediatek.com (CK Hu)
Date: Fri, 13 May 2016 11:59:16 +0800
Subject: [RFC 2/3] drm/mediatek: add support for Mediatek SoC MT2701
In-Reply-To: <1463053795-55455-3-git-send-email-yt.shen@mediatek.com>
References: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
 <1463053795-55455-3-git-send-email-yt.shen@mediatek.com>
Message-ID: <1463111956.12239.15.camel@mtksdaap41>

Hi, YT:

On Thu, 2016-05-12 at 19:49 +0800, yt.shen at mediatek.com wrote:
> From: YT Shen <yt.shen at mediatek.com>
> 
> This patch add support for the Mediatek MT2701 DISP subsystem.
> There is only one OVL engine in MT2701, and we have shadow
> register support here.
> 
> Signed-off-by: YT Shen <yt.shen at mediatek.com>
> ---

> @@ -385,12 +422,16 @@ static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc,
>  		mtk_crtc->event = state->base.event;
>  		state->base.event = NULL;
>  	}
> +
> +	if (priv->data->shadow_register)
> +		mtk_disp_mutex_acquire(mtk_crtc->mutex);
>  }
>  
> @@ -409,6 +450,11 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
>  	}
>  	if (pending_planes)
>  		mtk_crtc->pending_planes = true;
> +
> +	if (priv->data->shadow_register) {
> +		mtk_crtc_ddp_config(crtc);
> +		mtk_disp_mutex_release(mtk_crtc->mutex);
> +	}
>  }
>  

I think it's better to call mtk_disp_mutex_acquire() and
mtk_disp_mutex_release() as near as possible to prevent mutex locked for
a long time. All HW register access of this atomic setting is in
mtk_crtc_ddp_config(), so it's better to move mtk_disp_mutex_acquire()
just before mtk_crtc_ddp_config().

Regards,
CK



From linux at roeck-us.net  Thu May 12 21:22:55 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Thu, 12 May 2016 21:22:55 -0700
Subject: arm build failures in -next due to 'sched/core: Add
 switch_mm_irqs_off() and use it in the scheduler'
Message-ID: <20160513042255.GA28453@roeck-us.net>

Hi Andy,

I see various arm build failures in -next. One example is spitz_defconfig.
Bisect points to commit 'sched/core: Add switch_mm_irqs_off() and use it
in the scheduler'. Reverting the commit fixes the problem.

In file included from include/linux/mmu_context.h:4:0,
                 from drivers/usb/gadget/legacy/inode.c:27:
./arch/arm/include/asm/mmu_context.h:
	In function 'finish_arch_post_lock_switch':
./arch/arm/include/asm/mmu_context.h:88:3: error:
	implicit declaration of function 'preempt_enable_no_resched'

This has been going on for a while, so maybe it has been reported already.
If so, sorry for the noise.

Bisect log is attached.

Guenter

---
# bad: [dd1071fe27ec200ddc49a494e1275a8269248843] x86/rwsem: Save and restore all callee-clobbered regs in 32-bit ____down_write()
# good: [44549e8f5eea4e0a41b487b63e616cb089922b99] Linux 4.6-rc7
git bisect start 'HEAD' 'v4.6-rc7'
# good: [b6cf27d48f370bf2d42888921632ae05340aaca9] Merge remote-tracking branch 'crypto/master'
git bisect good b6cf27d48f370bf2d42888921632ae05340aaca9
# bad: [607563e7793b7c4f3ab134dc200552a555ca5cb2] Merge remote-tracking branch 'tip/auto-latest'
git bisect bad 607563e7793b7c4f3ab134dc200552a555ca5cb2
# good: [05454bc3dd6d8c4cff684ea881d79db952030075] Merge remote-tracking branch 'block/for-next'
git bisect good 05454bc3dd6d8c4cff684ea881d79db952030075
# good: [3ed15da0d55d9147f6434fe57db60a5b4059cbfd] Merge remote-tracking branch 'spi/for-next'
git bisect good 3ed15da0d55d9147f6434fe57db60a5b4059cbfd
# good: [25ea4e608611c03ad9829a727f6cc198db952d06] Merge branch 'perf/core'
git bisect good 25ea4e608611c03ad9829a727f6cc198db952d06
# bad: [df9f17497431a073c33aea6994f3b5b53fd89806] manual merge of x86/asm
git bisect bad df9f17497431a073c33aea6994f3b5b53fd89806
# bad: [d10c98b20678fb22506d6c712d7a0af6885001a1] Merge branch 'timers/core'
git bisect bad d10c98b20678fb22506d6c712d7a0af6885001a1
# bad: [b52fad2db5d792d89975cebf2fe1646a7af28ed0] sched/fair: Update rq clock before updating nohz CPU load
git bisect bad b52fad2db5d792d89975cebf2fe1646a7af28ed0
# good: [1f41906a6fda1114debd3898668bd7ab6470ee41] sched/fair: Correctly handle nohz ticks CPU load accounting
git bisect good 1f41906a6fda1114debd3898668bd7ab6470ee41
# bad: [64b7aad5798478ffff52e110878ccaae4c3aaa34] Merge branch 'sched/urgent' into sched/core, to pick up fixes before applying new changes
git bisect bad 64b7aad5798478ffff52e110878ccaae4c3aaa34
# good: [8efd755ac2fe262d4c8d5c9bbe054bb67dae93da] mm/mmu_context, sched/core: Fix mmu_context.h assumption
git bisect good 8efd755ac2fe262d4c8d5c9bbe054bb67dae93da
# bad: [e1074888c326038340a1ada9129d679e661f2ea6] x86/mm: Build arch/x86/mm/tlb.c even on !SMP
git bisect bad e1074888c326038340a1ada9129d679e661f2ea6
# bad: [f98db6013c557c216da5038d9c52045be55cd039] sched/core: Add switch_mm_irqs_off() and use it in the scheduler
git bisect bad f98db6013c557c216da5038d9c52045be55cd039
# first bad commit: [f98db6013c557c216da5038d9c52045be55cd039] sched/core: Add switch_mm_irqs_off() and use it in the scheduler


From appana.durga.rao at xilinx.com  Thu May 12 21:36:10 2016
From: appana.durga.rao at xilinx.com (Appana Durga Kedareswara Rao)
Date: Fri, 13 May 2016 04:36:10 +0000
Subject: [PATCH v4 3/5] dmaengine: vdma: Add Support for Xilinx AXI
 Direct Memory Access Engine
In-Reply-To: <CAD56B7fQWeDZDtKz2BgzpWSCMVdAGyUTBjUiuVnZ_8j51-SpoA@mail.gmail.com>
References: <1460006985-14805-1-git-send-email-appanad@xilinx.com>
 <1460006985-14805-4-git-send-email-appanad@xilinx.com>
 <CAD56B7fQWeDZDtKz2BgzpWSCMVdAGyUTBjUiuVnZ_8j51-SpoA@mail.gmail.com>
Message-ID: <C246CAC1457055469EF09E3A7AC4E11A4A5813F2@XAP-PVEXMBX01.xlnx.xilinx.com>

Hi Paul,

> 
> Nice Kedar!
> 
> Is this getting applied? I would really like to see this get into the mainline.

This patch got applied to the dma-next branch...
Here @ http://git.kernel.org/cgit/linux/kernel/git/vkoul/slave-dma.git/log/?h=next 

Thanks,
Kedar.


From dianders at chromium.org  Thu May 12 21:36:41 2016
From: dianders at chromium.org (Doug Anderson)
Date: Thu, 12 May 2016 21:36:41 -0700
Subject: [PATCH 2/2] clk: rockchip: fix the rk3399 sdmmc sample shift
In-Reply-To: <84673e7c-dd64-b2ca-5c7c-5c7f34d239d8@rock-chips.com>
References: <1463076197-15900-1-git-send-email-dianders@chromium.org>
 <1463076197-15900-2-git-send-email-dianders@chromium.org>
 <20160512231023.GA63308@google.com>
 <84673e7c-dd64-b2ca-5c7c-5c7f34d239d8@rock-chips.com>
Message-ID: <CAD=FV=WEAOwhDDBHBtuzSz35i0XRZw4LbFEnFCFYd-4NVH5d-g@mail.gmail.com>

Shawn,

On Thu, May 12, 2016 at 4:47 PM, Shawn Lin <shawn.lin at rock-chips.com> wrote:
> ? 2016/5/13 7:10, Brian Norris ??:
>>
>> On Thu, May 12, 2016 at 11:03:17AM -0700, Doug Anderson wrote:
>>>
>>> Just like every other Rockhip device, the MMC "_sample" clocks should
>>> have a shift of 0, not a shift of 1.  The rk3399 TRM agrees.  Presumably
>>> these values were set to 0 because of a typo.
>>
>>
>> I'll semi-disagree about the TRM: the TRM doesn't seem to agree with
>> itself, so it sometimes agrees with you and sometimes doesn't :)
>>
>> On page 79 of the 2nd (?) book, it looks like {SDMMC,SDIO}_CON{0,}[2:1]
>> are {drv,sample}_degree. But on page 208 of the 1st book, those are put
>> at bits [1:0].
>>
>
>
> Please refer to Mobile Strorage Host Controller section for anything
> about sdmmc/sdio. So shift should be 1.
>
> Sometime I also get bothered to address it. Anyway, I will always keep
> a eye on it from now on.....

I still in general have mistrust for TRM docs for things like this.
Have you verified that this was an intentional change for rk3399, or
could it be a  typo?  Typically SoCs don't change this type of stuff
for no reason.

This should be possible to verify in one of two ways.  If the TRM has
a typo and things truly _do_ start at 0 instead of 1, then:

1. There will be roughly mirrors of valid ranges.
2. Things won't match up if we change tuning to use 180 course offsets
and the rest fine offsets.

It would be ideal if you could confirm with the chip guys, but if you
can't I'll try to do more tests tomorrow.


From oss at buserror.net  Thu May 12 21:37:40 2016
From: oss at buserror.net (Scott Wood)
Date: Thu, 12 May 2016 23:37:40 -0500
Subject: [PATCH v2 2/2] arm64: dts: Add timer erratum property for LS2080A and
 LS1043A
In-Reply-To: <1463114260-8724-1-git-send-email-oss@buserror.net>
References: <1463114260-8724-1-git-send-email-oss@buserror.net>
Message-ID: <1463114260-8724-2-git-send-email-oss@buserror.net>

Signed-off-by: Scott Wood <oss at buserror.net>
---
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 1 +
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 1 +
 2 files changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index be72bf5..596420c 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -115,6 +115,7 @@
 			     <1 14 0x1>, /* Physical Non-Secure PPI */
 			     <1 11 0x1>, /* Virtual PPI */
 			     <1 10 0x1>; /* Hypervisor PPI */
+		fsl,erratum-a008585;
 	};
 
 	pmu {
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index 9d746c6..0270ccf 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -171,6 +171,7 @@
 			     <1 14 0x8>, /* Physical Non-Secure PPI, active-low */
 			     <1 11 0x8>, /* Virtual PPI, active-low */
 			     <1 10 0x8>; /* Hypervisor PPI, active-low */
+		fsl,erratum-a008585;
 	};
 
 	pmu {
-- 
2.5.0



From oss at buserror.net  Thu May 12 21:37:39 2016
From: oss at buserror.net (Scott Wood)
Date: Thu, 12 May 2016 23:37:39 -0500
Subject: [PATCH v2 1/2] ARM64: arch_timer: Work around QorIQ Erratum A-008585
Message-ID: <1463114260-8724-1-git-send-email-oss@buserror.net>

Erratum A-008585 says that the ARM generic timer counter "has the
potential to contain an erroneous value for a small number of core
clock cycles every time the timer value changes".  Accesses to TVAL
(both read and write) are also affected due to the implicit counter
read.  Accesses to CVAL are not affected.

The workaround is to reread TVAL and count registers until successive reads
return the same value, and when writing TVAL to retry until counter
reads before and after the write return the same value.

This erratum can be found on LS1043A and LS2080A.

Signed-off-by: Scott Wood <oss at buserror.net>
---
v2:
Significant rework based on feedback, including using static_key,
disabling VDSO counter access rather than adding the workaround to the
VDSO, and uninlining the loops.

Dropped the separate property for indicating that writes to TVAL are
affected, as I believe that's just a side effect of the implicit
counter read being corrupted, and thus a chip that is affected by one
will always be affected by the other.

Dropped the arm32 portion as it seems there was confusion about whether
LS1021A is affected.  Currently I am being told that it is not
affected.

I considered writing to CVAL rather than looping on TVAL writes, but
that would still have required separate set_next_event() code for the
erratum, and adding CVAL to the enum would have required a bunch of
extra handlers in switch statements (even where unused, due to compiler
warnings about unhandled enum values) including in an arm32 header.  It
seemed better to avoid the arm32 interaction and new untested
accessors.
---
 .../devicetree/bindings/arm/arch_timer.txt         |   6 ++
 arch/arm64/include/asm/arch_timer.h                |  37 +++++--
 drivers/clocksource/arm_arch_timer.c               | 110 +++++++++++++++++++++
 3 files changed, 144 insertions(+), 9 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
index e774128..ef5fbe9 100644
--- a/Documentation/devicetree/bindings/arm/arch_timer.txt
+++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
@@ -25,6 +25,12 @@ to deliver its interrupts via SPIs.
 - always-on : a boolean property. If present, the timer is powered through an
   always-on power domain, therefore it never loses context.
 
+- fsl,erratum-a008585 : A boolean property. Indicates the presence of
+  QorIQ erratum A-008585, which says that reading the counter is
+  unreliable unless the same value is returned by back-to-back reads.
+  This also affects writes to the tval register, due to the implicit
+  counter read.
+
 ** Optional properties:
 
 - arm,cpu-registers-not-fw-configured : Firmware does not initialize
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index fbe0ca3..9715e85 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -23,10 +23,33 @@
 
 #include <linux/bug.h>
 #include <linux/init.h>
+#include <linux/jump_label.h>
 #include <linux/types.h>
 
 #include <clocksource/arm_arch_timer.h>
 
+extern struct static_key_false arch_timer_read_ool_enabled;
+
+#define ARCH_TIMER_REG_READ(reg, func) \
+extern u64 func##_ool(void); \
+static inline u64 __##func(void) \
+{ \
+	u64 val; \
+	asm volatile("mrs %0, " reg : "=r" (val)); \
+	return val; \
+} \
+static inline u64 _##func(void) \
+{ \
+	if (static_branch_unlikely(&arch_timer_read_ool_enabled)) \
+		return func##_ool(); \
+	else \
+		return __##func(); \
+}
+
+ARCH_TIMER_REG_READ("cntp_tval_el0", arch_timer_get_ptval)
+ARCH_TIMER_REG_READ("cntv_tval_el0", arch_timer_get_vtval)
+ARCH_TIMER_REG_READ("cntvct_el0", arch_counter_get_cntvct)
+
 /*
  * These register accessors are marked inline so the compiler can
  * nicely work out which register we want, and chuck away the rest of
@@ -66,19 +89,19 @@ u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
 	if (access == ARCH_TIMER_PHYS_ACCESS) {
 		switch (reg) {
 		case ARCH_TIMER_REG_CTRL:
-			asm volatile("mrs %0,  cntp_ctl_el0" : "=r" (val));
+			asm volatile("mrs %0, cntp_ctl_el0" : "=r" (val));
 			break;
 		case ARCH_TIMER_REG_TVAL:
-			asm volatile("mrs %0, cntp_tval_el0" : "=r" (val));
+			val = _arch_timer_get_ptval();
 			break;
 		}
 	} else if (access == ARCH_TIMER_VIRT_ACCESS) {
 		switch (reg) {
 		case ARCH_TIMER_REG_CTRL:
-			asm volatile("mrs %0,  cntv_ctl_el0" : "=r" (val));
+			asm volatile("mrs %0, cntv_ctl_el0" : "=r" (val));
 			break;
 		case ARCH_TIMER_REG_TVAL:
-			asm volatile("mrs %0, cntv_tval_el0" : "=r" (val));
+			val = _arch_timer_get_vtval();
 			break;
 		}
 	}
@@ -116,12 +139,8 @@ static inline u64 arch_counter_get_cntpct(void)
 
 static inline u64 arch_counter_get_cntvct(void)
 {
-	u64 cval;
-
 	isb();
-	asm volatile("mrs %0, cntvct_el0" : "=r" (cval));
-
-	return cval;
+	return _arch_counter_get_cntvct();
 }
 
 static inline int arch_timer_arch_init(void)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 5152b38..6f78831 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -79,10 +79,52 @@ static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI;
 static bool arch_timer_c3stop;
 static bool arch_timer_mem_use_virtual;
 
+DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled);
+EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled);
+
 /*
  * Architected system timer support.
  */
 
+#ifdef CONFIG_ARM64
+/*
+ * __always_inline is used to ensure that func() is not an actual function
+ * pointer, which would result in the register accesses potentially being too
+ * far apart for the loop to work.
+ */
+static __always_inline u64 arch_timer_reread(u64 (*func)(void))
+{
+	u64 cval_old, cval_new;
+	int timeout = 200;
+
+	do {
+		isb();
+		cval_old = func();
+		cval_new = func();
+		timeout--;
+	} while (cval_old != cval_new && timeout);
+
+	WARN_ON_ONCE(!timeout);
+	return cval_new;
+}
+
+u64 arch_counter_get_cntvct_ool(void)
+{
+	return arch_timer_reread(__arch_counter_get_cntvct);
+}
+
+u64 arch_timer_get_vtval_ool(void)
+{
+	return arch_timer_reread(__arch_timer_get_vtval);
+}
+
+u64 arch_timer_get_ptval_ool(void)
+{
+	return arch_timer_reread(__arch_timer_get_ptval);
+}
+
+#endif /* ARM64 */
+
 static __always_inline
 void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val,
 			  struct clock_event_device *clk)
@@ -232,6 +274,50 @@ static __always_inline void set_next_event(const int access, unsigned long evt,
 	arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
 }
 
+#ifdef CONFIG_ARM64
+static __always_inline void rewrite_tval(const int access,
+		unsigned long evt, struct clock_event_device *clk)
+{
+	u64 cval_old, cval_new;
+	int timeout = 200;
+
+	do {
+		cval_old = __arch_counter_get_cntvct();
+		arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt, clk);
+		cval_new = __arch_counter_get_cntvct();
+		timeout--;
+	} while (cval_old != cval_new && timeout);
+
+	WARN_ON_ONCE(!timeout);
+}
+
+static __always_inline void set_next_event_errata(const int access,
+		unsigned long evt, struct clock_event_device *clk)
+{
+	unsigned long ctrl;
+
+	ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
+	ctrl |= ARCH_TIMER_CTRL_ENABLE;
+	ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
+	rewrite_tval(access, evt, clk);
+	arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
+}
+
+static int arch_timer_set_next_event_virt_errata(unsigned long evt,
+						 struct clock_event_device *clk)
+{
+	set_next_event_errata(ARCH_TIMER_VIRT_ACCESS, evt, clk);
+	return 0;
+}
+
+static int arch_timer_set_next_event_phys_errata(unsigned long evt,
+						 struct clock_event_device *clk)
+{
+	set_next_event_errata(ARCH_TIMER_PHYS_ACCESS, evt, clk);
+	return 0;
+}
+#endif /* ARM64 */
+
 static int arch_timer_set_next_event_virt(unsigned long evt,
 					  struct clock_event_device *clk)
 {
@@ -277,6 +363,13 @@ static void __arch_timer_setup(unsigned type,
 			clk->set_state_shutdown = arch_timer_shutdown_virt;
 			clk->set_state_oneshot_stopped = arch_timer_shutdown_virt;
 			clk->set_next_event = arch_timer_set_next_event_virt;
+
+#ifdef CONFIG_ARM64
+			if (static_branch_unlikely(&arch_timer_read_ool_enabled))
+				clk->set_next_event =
+					arch_timer_set_next_event_virt_errata;
+#endif
+
 			break;
 		case PHYS_SECURE_PPI:
 		case PHYS_NONSECURE_PPI:
@@ -284,6 +377,13 @@ static void __arch_timer_setup(unsigned type,
 			clk->set_state_shutdown = arch_timer_shutdown_phys;
 			clk->set_state_oneshot_stopped = arch_timer_shutdown_phys;
 			clk->set_next_event = arch_timer_set_next_event_phys;
+
+#ifdef CONFIG_ARM64
+			if (static_branch_unlikely(&arch_timer_read_ool_enabled))
+				clk->set_next_event =
+					arch_timer_set_next_event_phys_errata;
+#endif
+
 			break;
 		default:
 			BUG();
@@ -485,6 +585,13 @@ static void __init arch_counter_register(unsigned type)
 			arch_timer_read_counter = arch_counter_get_cntvct;
 		else
 			arch_timer_read_counter = arch_counter_get_cntpct;
+
+		/*
+		 * Don't use the vdso fastpath if errata require using
+		 * the out-of-line counter accessor.
+		 */
+		if (static_branch_unlikely(&arch_timer_read_ool_enabled))
+			clocksource_counter.name = "arch_sys_counter_ool";
 	} else {
 		arch_timer_read_counter = arch_counter_get_cntvct_mem;
 
@@ -763,6 +870,9 @@ static void __init arch_timer_of_init(struct device_node *np)
 
 	arch_timer_c3stop = !of_property_read_bool(np, "always-on");
 
+	if (of_property_read_bool(np, "fsl,erratum-a008585"))
+		static_branch_enable(&arch_timer_read_ool_enabled);
+
 	/*
 	 * If we cannot rely on firmware initializing the timer registers then
 	 * we should use the physical timers instead.
-- 
2.5.0



From appana.durga.rao at xilinx.com  Thu May 12 21:42:23 2016
From: appana.durga.rao at xilinx.com (Appana Durga Kedareswara Rao)
Date: Fri, 13 May 2016 04:42:23 +0000
Subject: [PATCH v8 1/2] Documentation: DT: dma: Add Xilinx zynqmp dma
 device tree binding documentation
In-Reply-To: <57347A5C.1080606@metafoo.de>
References: <1463056164-3210-1-git-send-email-appanad@xilinx.com>
 <57347A5C.1080606@metafoo.de>
Message-ID: <C246CAC1457055469EF09E3A7AC4E11A4A581418@XAP-PVEXMBX01.xlnx.xilinx.com>


Hi Lars,

	Thanks for the review...

> 
> On 05/12/2016 02:29 PM, Kedareswara rao Appana wrote:
> [...]
> > +- xlnx,include-sg	: Indicates the controller to operate in simple or
> > +			  scatter gather dma mode
> 
> This is also a software runtime configuration parameter.

Hmm I missed it will fix in the next version of the patch.

Regards,
Kedar.



From takahiro.akashi at linaro.org  Thu May 12 21:55:15 2016
From: takahiro.akashi at linaro.org (AKASHI Takahiro)
Date: Fri, 13 May 2016 13:55:15 +0900
Subject: [PATCH v16 00/20] arm64 kexec kernel patches v16
In-Reply-To: <5734CA48.7040706@arm.com>
References: <cover.1460668521.git.geoff@infradead.org>
 <5734CA48.7040706@arm.com>
Message-ID: <20160513045501.GC8417@linaro.org>

[+Ard]

Hi Julien,

Thank you for reporting this issue.

On Thu, May 12, 2016 at 07:24:08PM +0100, Julien Grall wrote:
> Hello Geoff,
> 
> On 14/04/16 22:21, Geoff Levand wrote:
> >This series adds the core support for kexec re-boot and kdump on ARM64.  This
> >version of the series combines Takahiro's kdump patches with my kexec patches.
> >Please consider all patches for inclusion.
> >
> >To load a second stage kernel and execute a kexec re-boot or to work with kdump
> >on ARM64 systems a series of patches to kexec-tools [2], which have not yet been
> >merged upstream, are needed.  Please update to the latest if you have been using
> >an older version.
> >
> >To examine vmcore (/proc/vmcore), you should use
> >   - gdb v7.7 or later
> >   - crash v7.1.1 or later
> 
> I have been trying to use crash dump with your branch without much
> success on juno-r2:
> 
> WARNING: could not find MAGIC_START!
> crash: cannot determine base kernel version
> crash: /root/vmlinux and /root/coredump.kernel do not match!
> 
> Looking at the debug log (-p 5), the translation va -> pa computed
> by crash is wrong.
> 
> The physical address expected is 0x80a76b28, but crash return 0x88a76b28.

Yeah, this is due to Ard's KASLR patches (especially, f9040773b7bb: "arm64:
move kernel image to base of vmalloc area").
Now that the kernel image (and so all the kernel symbols) is located
in the vmalloc area, which is below PAGE_OFFSET, we can't use liner mapping
conversion for va -> pa in order to access kernel data in the core image.

I'm sure that the image (/proc/vmcore) is still sane, and we will have
to fix a user-space tool, i.e. crash.
The good news is that I've already confirmed that we could read the core
image successfully by adding a bit nasty hack to the tool.

I'll let you know once a refined patch gets ready.

Thanks for your patience,
-Takahiro AKASHI

> I am using crash built from [1] and the panic has been created using
> /proc/sysrq-trigger.
> 
> Also, crash dump seems to always report that Xen is running even
> when KVM was in used (see logs [2]) below.
> 
> Lastly, crash fails with an error after a couple of minutes (see logs [2]).
>
> How you seen such errors during your testing?
> 
> Regards,
> 
> [1] https://github.com/crash-utility/crash
> [2] http://pastebin.com/wC8w44SN
> 
> -- 
> Julien Grall


From a0393675 at ti.com  Thu May 12 22:19:20 2016
From: a0393675 at ti.com (Keerthy)
Date: Fri, 13 May 2016 10:49:20 +0530
Subject: [PATCH RESEND 0/4] arm: dts: am57xx: Correct the thermal
 thresholds
In-Reply-To: <20160512203505.GV5995@atomide.com>
References: <1461837949-11116-1-git-send-email-j-keerthy@ti.com>
 <57316262.80003@ti.com> <20160512203505.GV5995@atomide.com>
Message-ID: <573563D8.7020503@ti.com>



On Friday 13 May 2016 02:05 AM, Tony Lindgren wrote:
> Hi,
>
> * Keerthy <a0393675 at ti.com> [160509 21:25]:
>> Tony,
>>
>> On Thursday 28 April 2016 03:35 PM, Keerthy wrote:
>>> Noticed that earlier post had a wrong list name hence resending the
>>> series.
>>>
>>> Currently all the am57xx versions are wrongly re-using the dra7  thermal
>>> threholds. Introduing the correct thermal thresholds based on industrial
>>> or commercial grade silicon present on the individual boards.
>>>
>>> Tested on AM57XX-BEAGLE-X15 (Commercial) and AM572X-IDK(Industrial)
>>> for the trip_point node sysfs temperatures.
>>>
>>
>> A Gentle ping on this series.
>
> I already have these in Linux next for v4.7 merge window:
>
> 5b6042237dc8 ("ARM: dts: am57xx-idk: Include Industrial grade  thermal thresholds")
> 266e62f97539 ("ARM: dts: am57xx-beagle-x15: Include the commercial grade thresholds")
> cf9b7d5e9cfd ("ARM: dts: am57xx: Introduce industrial grade thermal thresholds")
> 286db0a516e0 ("ARM: dts: am57xx: Introduce commercial grade thermal thresholds")
>
> Care to check if those are OK? If fixes are needed, please post an
> incremental patch against current Linux next.

Thanks Tony. Those 4 commits are fine.

Regards,
Keerthy
>
> Regards,
>
> Tony
>


From luto at amacapital.net  Thu May 12 22:46:56 2016
From: luto at amacapital.net (Andy Lutomirski)
Date: Thu, 12 May 2016 22:46:56 -0700
Subject: [PATCH] sched/core: don't include asm/mmu_context from drivers
In-Reply-To: <20160429094218.61b26849@gandalf.local.home>
References: <1461919995-21001-1-git-send-email-arnd@arndb.de>
 <20160429094218.61b26849@gandalf.local.home>
Message-ID: <CALCETrV_wgy0vpWiLYRJn1Q41C6adKKgbEOFthoAXiG601JPYQ@mail.gmail.com>

On Fri, Apr 29, 2016 at 6:42 AM, Steven Rostedt <rostedt at goodmis.org> wrote:
> On Fri, 29 Apr 2016 10:52:32 +0200
> Arnd Bergmann <arnd at arndb.de> wrote:
>
>> This reverts the earlier fix attempt and works around the problem
>> by including both linux/mmu_context.h and asm/mmu_context.h from
>> kernel/sched/core.c. This is not a good solution but seems less
>> hacky than the alternatives.
>
> What about simply not compiling finish_arch_post_lock_switch() when
> building modules?
>
> (untested, not compiled or anything)
>
> Signed-off-by: Steven Rostedt <rostedt at goodmis.org>
> ---
> diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h
> index fa5b42d44985..3f22d1b6bac8 100644
> --- a/arch/arm/include/asm/mmu_context.h
> +++ b/arch/arm/include/asm/mmu_context.h
> @@ -66,6 +66,7 @@ static inline void check_and_switch_context(struct mm_struct *mm,
>                 cpu_switch_mm(mm->pgd, mm);
>  }
>
> +#ifndef MODULE
>  #define finish_arch_post_lock_switch \
>         finish_arch_post_lock_switch
>  static inline void finish_arch_post_lock_switch(void)
> @@ -87,6 +88,7 @@ static inline void finish_arch_post_lock_switch(void)
>                 preempt_enable_no_resched();
>         }
>  }
> +#endif /* !MODULE */
>
>  #endif /* CONFIG_MMU */
>


Can someone in arm land ack this so Ingo can apply it?

--Andy

-- 
Andy Lutomirski
AMA Capital Management, LLC


From geert at linux-m68k.org  Thu May 12 23:12:37 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Fri, 13 May 2016 08:12:37 +0200
Subject: [PATCH v3 4/6] ARM: dts: r8a7794: add Audio-DMAC support
In-Reply-To: <25671875.9c5xSSzmjj@wasted.cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
 <25671875.9c5xSSzmjj@wasted.cogentembedded.com>
Message-ID: <CAMuHMdUqys5qFShjfTfBn8sK1xs=+q91QFnvmS59GK_PqTByNA@mail.gmail.com>

Hi Sergei,

On Thu, May 12, 2016 at 10:47 PM, Sergei Shtylyov
<sergei.shtylyov at cogentembedded.com> wrote:
> --- renesas.orig/arch/arm/boot/dts/r8a7794.dtsi
> +++ renesas/arch/arm/boot/dts/r8a7794.dtsi
> @@ -295,6 +295,34 @@
>                 dma-channels = <15>;
>         };
>
> +       audma0: dma-controller at ec700000 {
> +               compatible = "renesas,dmac-r8a7794", "renesas,rcar-dmac";
> +               reg = <0 0xec700000 0 0x10000>;
> +               interrupts =    <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH
> +                                GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>;
> +               interrupt-names = "error",
> +                                 "ch0", "ch1", "ch2", "ch3", "ch4", "ch5",
> +                                 "ch6", "ch7", "ch8", "ch9", "ch10", "ch11",
> +                                 "ch12";
> +               clocks = <&mstp5_clks R8A7794_CLK_AUDIO_DMAC0>;
> +               clock-names = "fck";
> +               power-domains = <&cpg_clocks>;

In renesas-devel-20160509-v4.6-rc7, that should be

        power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;

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 geert at linux-m68k.org  Thu May 12 23:13:28 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Fri, 13 May 2016 08:13:28 +0200
Subject: [PATCH v3 5/6] ARM: dts: r8a7794: add sound support
In-Reply-To: <38505966.asxJl6Sq91@wasted.cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
 <38505966.asxJl6Sq91@wasted.cogentembedded.com>
Message-ID: <CAMuHMdXdN+nf+_scyDA7yW2NgNiFhK8a1Vt1-uA+FEymoFiPNw@mail.gmail.com>

On Thu, May 12, 2016 at 10:49 PM, Sergei Shtylyov
<sergei.shtylyov at cogentembedded.com> wrote:
> --- renesas.orig/arch/arm/boot/dts/r8a7794.dtsi
> +++ renesas/arch/arm/boot/dts/r8a7794.dtsi
> @@ -1385,4 +1385,189 @@
>                 #iommu-cells = <1>;
>                 status = "disabled";
>         };
> +
> +       rcar_sound: sound at ec500000 {
> +               /*
> +                * #sound-dai-cells is required
> +                *
> +                * Single DAI : #sound-dai-cells = <0>;         <&rcar_sound>;
> +                * Multi  DAI : #sound-dai-cells = <1>;         <&rcar_sound N>;
> +                */
> +               compatible = "renesas,rcar_sound-r8a7794",
> +                            "renesas,rcar_sound-gen2";
> +               reg =   <0 0xec500000 0 0x1000>, /* SCU */
> +                       <0 0xec5a0000 0 0x100>,  /* ADG */
> +                       <0 0xec540000 0 0x1000>, /* SSIU */
> +                       <0 0xec541000 0 0x280>,  /* SSI */
> +                       <0 0xec740000 0 0x200>;  /* Audio DMAC peri peri */
> +               reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
> +
> +               clocks = <&mstp10_clks R8A7794_CLK_SSI_ALL>,
> +                        <&mstp10_clks R8A7794_CLK_SSI9>,
> +                        <&mstp10_clks R8A7794_CLK_SSI8>,
> +                        <&mstp10_clks R8A7794_CLK_SSI7>,
> +                        <&mstp10_clks R8A7794_CLK_SSI6>,
> +                        <&mstp10_clks R8A7794_CLK_SSI5>,
> +                        <&mstp10_clks R8A7794_CLK_SSI4>,
> +                        <&mstp10_clks R8A7794_CLK_SSI3>,
> +                        <&mstp10_clks R8A7794_CLK_SSI2>,
> +                        <&mstp10_clks R8A7794_CLK_SSI1>,
> +                        <&mstp10_clks R8A7794_CLK_SSI0>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_SRC9>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_SRC8>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_SRC7>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_SRC6>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_SRC5>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_SRC4>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_SRC3>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_SRC2>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_SRC1>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_SRC0>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_CTU0_MIX0>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_CTU1_MIX1>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_CTU0_MIX0>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_CTU1_MIX1>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_DVC0>,
> +                        <&mstp10_clks R8A7794_CLK_SCU_DVC1>,
> +                        <&audio_clka>, <&audio_clkb>, <&audio_clkc>,
> +                        <&m2_clk>;
> +               clock-names = "ssi-all",
> +                             "ssi.9", "ssi.8", "ssi.7", "ssi.6", "ssi.5",
> +                             "ssi.4", "ssi.3", "ssi.2", "ssi.1", "ssi.0",
> +                             "src.9", "src.8", "src.7", "src.6", "src.5",
> +                             "src.4", "src.3", "src.2", "src.1", "src.0",
> +                             "ctu.0", "ctu.1",
> +                             "mix.0", "mix.1",
> +                             "dvc.0", "dvc.1",
> +                             "clk_a", "clk_b", "clk_c", "clk_i";
> +               power-domains = <&cpg_clocks>;

In renesas-devel-20160509-v4.6-rc7, that should be

        power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;

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 ivo.g.dimitrov.75 at gmail.com  Thu May 12 23:15:38 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Fri, 13 May 2016 09:15:38 +0300
Subject: [PATCH 4/7] [media] ir-rx51: add DT support to driver
In-Reply-To: <20160511141429.GA5894@rob-hp-laptop>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <1462634508-24961-5-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <20160509200657.GA3379@rob-hp-laptop> <5730F8BA.5000402@gmail.com>
 <CAL_JsqJPZS1ne_xAuBFtCc5L1HKFJf0LDUJ7CRSFXhc3adkTfA@mail.gmail.com>
 <20160510021826.GE1129@earth> <20160511141429.GA5894@rob-hp-laptop>
Message-ID: <5735710A.6060404@gmail.com>

Hi,

On 11.05.2016 17:14, Rob Herring wrote:
> On Tue, May 10, 2016 at 04:18:27AM +0200, Sebastian Reichel wrote:
>> Hi,
>>
>> On Mon, May 09, 2016 at 04:07:35PM -0500, Rob Herring wrote:
>>> There's already a pwm-led binding that can be used. Though there
>>> may be missing consumer IR to LED subsystem support in the kernel.
>>> You could list both compatibles, use the rx51 IR driver now, and
>>> then move to pwm-led driver in the future.
>>
>> Well from a purely HW point of view it's a PWM connected led. The
>> usage is completely different though. Usually PWM is used to control
>> the LED's brightness via the duty cycle (basic concept: enabling led
>> only 50% of time reduces brightness to 50%).
>>
>> In the IR led's case the aim is generating a specific serial pattern
>> instead. For this task it uses a dmtimer in PWM mode and a second
>> one to reconfigure the pwm timer.
>
> In that case, it will probably never be a generic driver.
>
>> I don't know about a good name, but rx51 should be replaced with
>> n900 in the compatible string. So maybe "nokia,n900-infrared-diode".
>
> That's fine, but the shorter '-ir' was too.
>

I prefer the shorter "nokia,n900-ir", will resend the series with it 
used, unless someone has concerns about it.

Ivo


From kernel at martin.sperl.org  Thu May 12 23:29:37 2016
From: kernel at martin.sperl.org (Martin Sperl)
Date: Fri, 13 May 2016 08:29:37 +0200
Subject: [PATCH 3/4] ARM: bcm2835: add thermal node to device-tree of
 bcm283x
In-Reply-To: <87posqamh9.fsf@eliezer.anholt.net>
References: <1463063738-11506-1-git-send-email-kernel@martin.sperl.org>
 <1463063738-11506-4-git-send-email-kernel@martin.sperl.org>
 <87posqamh9.fsf@eliezer.anholt.net>
Message-ID: <FA3695BE-D1A7-44E3-9714-08B6A002EB06@martin.sperl.org>


> On 13.05.2016, at 01:24, Eric Anholt <eric at anholt.net> wrote:
> 
> kernel at martin.sperl.org writes:
> 
>> From: Martin Sperl <kernel at martin.sperl.org>
>> 
>> Add the node for the thermal sensor of the bcm2835-soc
>> to the device tree.
>> 
>> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
>> ---
>> arch/arm/boot/dts/bcm283x.dtsi | 6 ++++++
>> 1 file changed, 6 insertions(+)
>> 
>> diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
>> index 9db9d97..525f1f2 100644
>> --- a/arch/arm/boot/dts/bcm283x.dtsi
>> +++ b/arch/arm/boot/dts/bcm283x.dtsi
>> @@ -159,6 +159,12 @@
>> 			status = "disabled";
>> 		};
>> 
>> +		thermal: thermal at 0x7e212000 {
>> +			compatible = "brcm,bcm2835-thermal";
>> +			reg = <0x7e212000 0x8>;
>> +			clocks = <&clocks BCM2835_CLOCK_TSENS>;
>> +		};
>> +
> 
> You could drop the "thermal: " here since nothing refers to it.  Either
> way,
Actually you will refer to it in the device tree for the bcm2837
so that you can set a different compatible string.



From zlim.lnx at gmail.com  Thu May 12 23:37:58 2016
From: zlim.lnx at gmail.com (Zi Shen Lim)
Date: Thu, 12 May 2016 23:37:58 -0700
Subject: [PATCH] arm64: bpf: jit JMP_JSET_{X,K}
Message-ID: <1463121478-18484-1-git-send-email-zlim.lnx@gmail.com>

Original implementation commit e54bcde3d69d ("arm64: eBPF JIT compiler")
had the relevant code paths, but due to an oversight always fail jiting.

As a result, we had been falling back to BPF interpreter whenever a BPF
program has JMP_JSET_{X,K} instructions.

With this fix, we confirm that the corresponding tests in lib/test_bpf
continue to pass, and also jited.

...
[    2.784553] test_bpf: #30 JSET jited:1 188 192 197 PASS
[    2.791373] test_bpf: #31 tcpdump port 22 jited:1 325 677 625 PASS
[    2.808800] test_bpf: #32 tcpdump complex jited:1 323 731 991 PASS
...
[    3.190759] test_bpf: #237 JMP_JSET_K: if (0x3 & 0x2) return 1 jited:1 110 PASS
[    3.192524] test_bpf: #238 JMP_JSET_K: if (0x3 & 0xffffffff) return 1 jited:1 98 PASS
[    3.211014] test_bpf: #249 JMP_JSET_X: if (0x3 & 0x2) return 1 jited:1 120 PASS
[    3.212973] test_bpf: #250 JMP_JSET_X: if (0x3 & 0xffffffff) return 1 jited:1 89 PASS
...

Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler")
Signed-off-by: Zi Shen Lim <zlim.lnx at gmail.com>
---
 arch/arm64/net/bpf_jit_comp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 031ed08..d0d5190 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -478,6 +478,7 @@ emit_cond_jmp:
 		case BPF_JGE:
 			jmp_cond = A64_COND_CS;
 			break;
+		case BPF_JSET:
 		case BPF_JNE:
 			jmp_cond = A64_COND_NE;
 			break;
-- 
1.9.1



From sricharan at codeaurora.org  Thu May 12 23:53:00 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Fri, 13 May 2016 12:23:00 +0530
Subject: [RFC 0/9] IOMMU probe deferral support
In-Reply-To: <f192d4a0-9e13-4ae2-d3da-058e2e092634@samsung.com>
References: <1461599894-1969-1-git-send-email-sricharan@codeaurora.org>
 <f192d4a0-9e13-4ae2-d3da-058e2e092634@samsung.com>
Message-ID: <000001d1ace4$1ac1e250$5045a6f0$@codeaurora.org>

Hi Marek,

> -----Original Message-----
> From: linux-arm-kernel [mailto:linux-arm-kernel-
> bounces at lists.infradead.org] On Behalf Of Marek Szyprowski
> Sent: Thursday, May 12, 2016 6:23 PM
> To: Sricharan R <sricharan at codeaurora.org>; will.deacon at arm.com;
> robin.murphy at arm.com; joro at 8bytes.org; iommu at lists.linux-
> foundation.org; linux-arm-kernel at lists.infradead.org;
> laurent.pinchart at ideasonboard.com
> Subject: Re: [RFC 0/9] IOMMU probe deferral support
> 
> Hello,
> 
> 
> On 2016-04-25 17:58, Sricharan R wrote:
> > This is mostly a repost of the probe deferral series from Laurent
> > Pinchart [1]. Added a check to fix boot with ACPI.
> > Adapted arm-smmu driver to work with deferred probing and added a new
> > api for the below reason. This is based on the generic iommu binding
> > series from Robin Murphy <robin.murphy at arm.com>.
> 
> Thanks for this patchset. I'm working on some serious rework in exynos
> power domains and clocks support code and it turned out that I need this
> feature to resolve probing order. It works fine on my internal tree, where
> some iommu controllers cannot get their clocks early enough.
> 
> Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
> 
   Thanks for testing. So the issue that I was facing also was the same
where the iommu
   controllers cannot get clocks early. So waiting for some suggestions if
this is right/
   or there is another way for doing this probe deferral?

Regards,
 Sricharan



From appana.durga.rao at xilinx.com  Fri May 13 00:03:28 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Fri, 13 May 2016 12:33:28 +0530
Subject: [PATCH v5 0/3] dmaengine: Add clock support for AXI DMAS
Message-ID: <1463123011-4911-1-git-send-email-appanad@xilinx.com>

This patch series adds basic clock support for AXI DMAS
This patch series is created on top of the dma-next branch.

Kedareswara rao Appana (3):
  dmaengine: vdma: Add config structure to differentiate dmas
  Documentation: DT: vdma: Add clock support for dmas
  dmaengine: vdma: Add clock support

 .../devicetree/bindings/dma/xilinx/xilinx_vdma.txt |  15 +
 drivers/dma/xilinx/xilinx_vdma.c                   | 307 ++++++++++++++++++---
 2 files changed, 289 insertions(+), 33 deletions(-)

-- 
2.1.1



From appana.durga.rao at xilinx.com  Fri May 13 00:03:29 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Fri, 13 May 2016 12:33:29 +0530
Subject: [PATCH v5 1/3] dmaengine: vdma: Add config structure to differentiate
 dmas
In-Reply-To: <1463123011-4911-1-git-send-email-appanad@xilinx.com>
References: <1463123011-4911-1-git-send-email-appanad@xilinx.com>
Message-ID: <1463123011-4911-2-git-send-email-appanad@xilinx.com>

This patch adds config structure in the driver to differentiate
AXI DMA's and to add more features(clock support etc..) to these DMA's.

Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
Changes for v5:
---> Rename dma_config struct to xilinx_dma_config
     as suggested by vinod.
Changes for v4:
---> None.
Changes for v3:
---> New patch.

 drivers/dma/xilinx/xilinx_vdma.c | 83 ++++++++++++++++++++++++----------------
 1 file changed, 51 insertions(+), 32 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
index 626939b..905b289 100644
--- a/drivers/dma/xilinx/xilinx_vdma.c
+++ b/drivers/dma/xilinx/xilinx_vdma.c
@@ -342,6 +342,10 @@ struct xilinx_dma_chan {
 	void (*start_transfer)(struct xilinx_dma_chan *chan);
 };
 
+struct xilinx_dma_config {
+	enum xdma_ip_type dmatype;
+};
+
 /**
  * struct xilinx_dma_device - DMA device structure
  * @regs: I/O mapped base address
@@ -351,7 +355,7 @@ struct xilinx_dma_chan {
  * @has_sg: Specifies whether Scatter-Gather is present or not
  * @flush_on_fsync: Flush on frame sync
  * @ext_addr: Indicates 64 bit addressing is supported by dma device
- * @dmatype: DMA ip type
+ * @dma_config: DMA config structure
  */
 struct xilinx_dma_device {
 	void __iomem *regs;
@@ -361,7 +365,7 @@ struct xilinx_dma_device {
 	bool has_sg;
 	u32 flush_on_fsync;
 	bool ext_addr;
-	enum xdma_ip_type dmatype;
+	const struct xilinx_dma_config *dma_config;
 };
 
 /* Macros */
@@ -572,12 +576,12 @@ xilinx_dma_free_tx_descriptor(struct xilinx_dma_chan *chan,
 	if (!desc)
 		return;
 
-	if (chan->xdev->dmatype == XDMA_TYPE_VDMA) {
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 		list_for_each_entry_safe(segment, next, &desc->segments, node) {
 			list_del(&segment->node);
 			xilinx_vdma_free_tx_segment(chan, segment);
 		}
-	} else if (chan->xdev->dmatype == XDMA_TYPE_CDMA) {
+	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
 		list_for_each_entry_safe(cdma_segment, cdma_next,
 					 &desc->segments, node) {
 			list_del(&cdma_segment->node);
@@ -640,7 +644,7 @@ static void xilinx_dma_free_chan_resources(struct dma_chan *dchan)
 	dev_dbg(chan->dev, "Free all channel resources.\n");
 
 	xilinx_dma_free_descriptors(chan);
-	if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA)
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
 		xilinx_dma_free_tx_segment(chan, chan->seg_v);
 	dma_pool_destroy(chan->desc_pool);
 	chan->desc_pool = NULL;
@@ -710,13 +714,13 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 	 * We need the descriptor to be aligned to 64bytes
 	 * for meeting Xilinx VDMA specification requirement.
 	 */
-	if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA) {
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		chan->desc_pool = dma_pool_create("xilinx_dma_desc_pool",
 				   chan->dev,
 				   sizeof(struct xilinx_axidma_tx_segment),
 				   __alignof__(struct xilinx_axidma_tx_segment),
 				   0);
-	} else if (chan->xdev->dmatype == XDMA_TYPE_CDMA) {
+	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
 		chan->desc_pool = dma_pool_create("xilinx_cdma_desc_pool",
 				   chan->dev,
 				   sizeof(struct xilinx_cdma_tx_segment),
@@ -737,7 +741,7 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 		return -ENOMEM;
 	}
 
-	if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA)
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
 		/*
 		 * For AXI DMA case after submitting a pending_list, keep
 		 * an extra segment allocated so that the "next descriptor"
@@ -750,7 +754,7 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 
 	dma_cookie_init(dchan);
 
-	if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA) {
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		/* For AXI DMA resetting once channel will reset the
 		 * other channel as well so enable the interrupts here.
 		 */
@@ -758,7 +762,7 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 			      XILINX_DMA_DMAXR_ALL_IRQ_MASK);
 	}
 
-	if ((chan->xdev->dmatype == XDMA_TYPE_CDMA) && chan->has_sg)
+	if ((chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) && chan->has_sg)
 		dma_ctrl_set(chan, XILINX_DMA_REG_DMACR,
 			     XILINX_CDMA_CR_SGMODE);
 
@@ -789,7 +793,7 @@ static enum dma_status xilinx_dma_tx_status(struct dma_chan *dchan,
 	if (ret == DMA_COMPLETE || !txstate)
 		return ret;
 
-	if (chan->xdev->dmatype == XDMA_TYPE_AXIDMA) {
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		spin_lock_irqsave(&chan->lock, flags);
 
 		desc = list_last_entry(&chan->active_list,
@@ -1331,12 +1335,12 @@ static void append_desc_queue(struct xilinx_dma_chan *chan,
 	 */
 	tail_desc = list_last_entry(&chan->pending_list,
 				    struct xilinx_dma_tx_descriptor, node);
-	if (chan->xdev->dmatype == XDMA_TYPE_VDMA) {
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 		tail_segment = list_last_entry(&tail_desc->segments,
 					       struct xilinx_vdma_tx_segment,
 					       node);
 		tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
-	} else if (chan->xdev->dmatype == XDMA_TYPE_CDMA) {
+	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
 		cdma_tail_segment = list_last_entry(&tail_desc->segments,
 						struct xilinx_cdma_tx_segment,
 						node);
@@ -1356,8 +1360,8 @@ append:
 	list_add_tail(&desc->node, &chan->pending_list);
 	chan->desc_pendingcount++;
 
-	if (chan->has_sg && (chan->xdev->dmatype == XDMA_TYPE_VDMA) &&
-	    unlikely(chan->desc_pendingcount > chan->num_frms)) {
+	if (chan->has_sg && (chan->xdev->dma_config->dmatype == XDMA_TYPE_VDMA)
+	    && unlikely(chan->desc_pendingcount > chan->num_frms)) {
 		dev_dbg(chan->dev, "desc pendingcount is too high\n");
 		chan->desc_pendingcount = chan->num_frms;
 	}
@@ -1810,7 +1814,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
 		chan->id = 0;
 
 		chan->ctrl_offset = XILINX_DMA_MM2S_CTRL_OFFSET;
-		if (xdev->dmatype == XDMA_TYPE_VDMA) {
+		if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 			chan->desc_offset = XILINX_VDMA_MM2S_DESC_OFFSET;
 
 			if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
@@ -1823,7 +1827,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
 		chan->id = 1;
 
 		chan->ctrl_offset = XILINX_DMA_S2MM_CTRL_OFFSET;
-		if (xdev->dmatype == XDMA_TYPE_VDMA) {
+		if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 			chan->desc_offset = XILINX_VDMA_S2MM_DESC_OFFSET;
 
 			if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
@@ -1844,9 +1848,9 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
 		return err;
 	}
 
-	if (xdev->dmatype == XDMA_TYPE_AXIDMA)
+	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
 		chan->start_transfer = xilinx_dma_start_transfer;
-	else if (xdev->dmatype == XDMA_TYPE_CDMA)
+	else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA)
 		chan->start_transfer = xilinx_cdma_start_transfer;
 	else
 		chan->start_transfer = xilinx_vdma_start_transfer;
@@ -1893,13 +1897,22 @@ static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec,
 	return dma_get_slave_channel(&xdev->chan[chan_id]->common);
 }
 
+static const struct xilinx_dma_config axidma_config = {
+	.dmatype = XDMA_TYPE_AXIDMA,
+};
+
+static const struct xilinx_dma_config axicdma_config = {
+	.dmatype = XDMA_TYPE_CDMA,
+};
+
+static const struct xilinx_dma_config axivdma_config = {
+	.dmatype = XDMA_TYPE_VDMA,
+};
+
 static const struct of_device_id xilinx_dma_of_ids[] = {
-	{ .compatible = "xlnx,axi-dma-1.00.a",
-	  .data = (void *)XDMA_TYPE_AXIDMA },
-	{ .compatible = "xlnx,axi-cdma-1.00.a",
-	  .data = (void *)XDMA_TYPE_CDMA },
-	{ .compatible = "xlnx,axi-vdma-1.00.a",
-	  .data = (void *)XDMA_TYPE_VDMA },
+	{ .compatible = "xlnx,axi-dma-1.00.a", .data = &axidma_config },
+	{ .compatible = "xlnx,axi-cdma-1.00.a", .data = &axicdma_config },
+	{ .compatible = "xlnx,axi-vdma-1.00.a", .data = &axivdma_config },
 	{}
 };
 MODULE_DEVICE_TABLE(of, xilinx_dma_of_ids);
@@ -1914,7 +1927,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
 	struct xilinx_dma_device *xdev;
-	struct device_node *child;
+	struct device_node *child, *np = pdev->dev.of_node;
 	struct resource *io;
 	u32 num_frames, addr_width;
 	int i, err;
@@ -1925,7 +1938,13 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	xdev->dev = &pdev->dev;
-	xdev->dmatype = (enum xdma_ip_type)of_device_get_match_data(&pdev->dev);
+	if (np) {
+		const struct of_device_id *match;
+
+		match = of_match_node(xilinx_dma_of_ids, np);
+		if (match && match->data)
+			xdev->dma_config = match->data;
+	}
 
 	/* Request and map I/O memory */
 	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1936,7 +1955,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 	/* Retrieve the DMA engine properties from the device tree */
 	xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg");
 
-	if (xdev->dmatype == XDMA_TYPE_VDMA) {
+	if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 		err = of_property_read_u32(node, "xlnx,num-fstores",
 					   &num_frames);
 		if (err < 0) {
@@ -1968,7 +1987,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 	xdev->common.dev = &pdev->dev;
 
 	INIT_LIST_HEAD(&xdev->common.channels);
-	if (!(xdev->dmatype == XDMA_TYPE_CDMA)) {
+	if (!(xdev->dma_config->dmatype == XDMA_TYPE_CDMA)) {
 		dma_cap_set(DMA_SLAVE, xdev->common.cap_mask);
 		dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask);
 	}
@@ -1980,12 +1999,12 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 	xdev->common.device_terminate_all = xilinx_dma_terminate_all;
 	xdev->common.device_tx_status = xilinx_dma_tx_status;
 	xdev->common.device_issue_pending = xilinx_dma_issue_pending;
-	if (xdev->dmatype == XDMA_TYPE_AXIDMA) {
+	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg;
 		/* Residue calculation is supported by only AXI DMA */
 		xdev->common.residue_granularity =
 					  DMA_RESIDUE_GRANULARITY_SEGMENT;
-	} else if (xdev->dmatype == XDMA_TYPE_CDMA) {
+	} else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
 		dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask);
 		xdev->common.device_prep_dma_memcpy = xilinx_cdma_prep_memcpy;
 	} else {
@@ -2002,7 +2021,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 			goto error;
 	}
 
-	if (xdev->dmatype == XDMA_TYPE_VDMA) {
+	if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 		for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
 			if (xdev->chan[i])
 				xdev->chan[i]->num_frms = num_frames;
-- 
2.1.1



From appana.durga.rao at xilinx.com  Fri May 13 00:03:30 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Fri, 13 May 2016 12:33:30 +0530
Subject: [PATCH v5 2/3] Documentation: DT: vdma: Add clock support for dmas
In-Reply-To: <1463123011-4911-1-git-send-email-appanad@xilinx.com>
References: <1463123011-4911-1-git-send-email-appanad@xilinx.com>
Message-ID: <1463123011-4911-3-git-send-email-appanad@xilinx.com>

This patch updates the binding doc with clock description
for AXI DMA's.

Acked-by: Rob Herring <robh at kernel.org>
Acked-by: S?ren Brinkmann <soren.brinkmann at xilinx.com>
Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
Changes for v5:
---> None.
Changes for v4:
---> None.
Changes for v3:
---> Added clock support for all the AXI DMA's.
Changes for v2:
--> Listed down all the clocks supported by the h/w
    as suggested by the Datta.
--> Used IP clock names instead of shortcut clock name

 .../devicetree/bindings/dma/xilinx/xilinx_vdma.txt        | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt
index fcc2b65..a1f2683 100644
--- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt
+++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt
@@ -21,6 +21,18 @@ Required properties:
 - dma-channel child node: Should have at least one channel and can have up to
 	two channels per device. This node specifies the properties of each
 	DMA channel (see child node properties below).
+- clocks: Input clock specifier. Refer to common clock bindings.
+- clock-names: List of input clocks
+	For VDMA:
+	Required elements: "s_axi_lite_aclk"
+	Optional elements: "m_axi_mm2s_aclk" "m_axi_s2mm_aclk",
+			   "m_axis_mm2s_aclk", "s_axis_s2mm_aclk"
+	For CDMA:
+	Required elements: "s_axi_lite_aclk", "m_axi_aclk"
+	FOR AXIDMA:
+	Required elements: "s_axi_lite_aclk"
+	Optional elements: "m_axi_mm2s_aclk", "m_axi_s2mm_aclk",
+			   "m_axi_sg_aclk"
 
 Required properties for VDMA:
 - xlnx,num-fstores: Should be the number of framebuffers as configured in h/w.
@@ -60,6 +72,9 @@ axi_vdma_0: axivdma at 40030000 {
 	xlnx,num-fstores = <0x8>;
 	xlnx,flush-fsync = <0x1>;
 	xlnx,addrwidth = <0x20>;
+	clocks = <&clk 0>, <&clk 1>, <&clk 2>, <&clk 3>, <&clk 4>;
+	clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk",
+		      "m_axis_mm2s_aclk", "s_axis_s2mm_aclk";
 	dma-channel at 40030000 {
 		compatible = "xlnx,axi-vdma-mm2s-channel";
 		interrupts = < 0 54 4 >;
-- 
2.1.1



From appana.durga.rao at xilinx.com  Fri May 13 00:03:31 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Fri, 13 May 2016 12:33:31 +0530
Subject: [PATCH v5 3/3] dmaengine: vdma: Add clock support
In-Reply-To: <1463123011-4911-1-git-send-email-appanad@xilinx.com>
References: <1463123011-4911-1-git-send-email-appanad@xilinx.com>
Message-ID: <1463123011-4911-4-git-send-email-appanad@xilinx.com>

Added basic clock support for axi dma's.
The clocks are requested at probe and released at remove.

Reviewed-by: Shubhrajyoti Datta <shubhraj at xilinx.com>
Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
Changes for v5:
---> None.
Changes for v4:
---> Documented struct members as suggested by Soren.
---> Fixed required clock according to binding but a failure is ignored
in the cdma case as suggested by Soren.
---> Removed unnecessary IS_ERR checks during disabling the clocks.
Changes for v3:
---> Added clock support for all the AXI DMA's.
---> Fixed clk_unprepare leak during probe fail as suggested by Moritz.
---> Fixed comment driver specifically asks for the clocks it needs and return
an error if a mandatory clock is missing as suggested by soren.
Changes for v2:
---> None.

 drivers/dma/xilinx/xilinx_vdma.c | 226 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 224 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
index 905b289..df91185 100644
--- a/drivers/dma/xilinx/xilinx_vdma.c
+++ b/drivers/dma/xilinx/xilinx_vdma.c
@@ -44,6 +44,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 
 #include "../dmaengine.h"
 
@@ -344,6 +345,9 @@ struct xilinx_dma_chan {
 
 struct xilinx_dma_config {
 	enum xdma_ip_type dmatype;
+	int (*clk_init)(struct platform_device *pdev, struct clk **axi_clk,
+			struct clk **tx_clk, struct clk **txs_clk,
+			struct clk **rx_clk, struct clk **rxs_clk);
 };
 
 /**
@@ -355,7 +359,13 @@ struct xilinx_dma_config {
  * @has_sg: Specifies whether Scatter-Gather is present or not
  * @flush_on_fsync: Flush on frame sync
  * @ext_addr: Indicates 64 bit addressing is supported by dma device
+ * @pdev: Platform device structure pointer
  * @dma_config: DMA config structure
+ * @axi_clk: DMA Axi4-lite interace clock
+ * @tx_clk: DMA mm2s clock
+ * @txs_clk: DMA mm2s stream clock
+ * @rx_clk: DMA s2mm clock
+ * @rxs_clk: DMA s2mm stream clock
  */
 struct xilinx_dma_device {
 	void __iomem *regs;
@@ -365,7 +375,13 @@ struct xilinx_dma_device {
 	bool has_sg;
 	u32 flush_on_fsync;
 	bool ext_addr;
+	struct platform_device  *pdev;
 	const struct xilinx_dma_config *dma_config;
+	struct clk *axi_clk;
+	struct clk *tx_clk;
+	struct clk *txs_clk;
+	struct clk *rx_clk;
+	struct clk *rxs_clk;
 };
 
 /* Macros */
@@ -1756,6 +1772,195 @@ static void xilinx_dma_chan_remove(struct xilinx_dma_chan *chan)
 	list_del(&chan->common.device_node);
 }
 
+static int axidma_clk_init(struct platform_device *pdev, struct clk **axi_clk,
+			    struct clk **tx_clk, struct clk **rx_clk,
+			    struct clk **sg_clk, struct clk **tmp_clk)
+{
+	int err;
+
+	*tmp_clk = NULL;
+
+	*axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
+	if (IS_ERR(*axi_clk)) {
+		err = PTR_ERR(*axi_clk);
+		dev_err(&pdev->dev, "failed to get axi_aclk (%u)\n", err);
+		return err;
+	}
+
+	*tx_clk = devm_clk_get(&pdev->dev, "m_axi_mm2s_aclk");
+	if (IS_ERR(*tx_clk))
+		*tx_clk = NULL;
+
+	*rx_clk = devm_clk_get(&pdev->dev, "m_axi_s2mm_aclk");
+	if (IS_ERR(*rx_clk))
+		*rx_clk = NULL;
+
+	*sg_clk = devm_clk_get(&pdev->dev, "m_axi_sg_aclk");
+	if (IS_ERR(*sg_clk))
+		*sg_clk = NULL;
+
+	err = clk_prepare_enable(*axi_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axi_clk (%u)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*tx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
+		goto err_disable_axiclk;
+	}
+
+	err = clk_prepare_enable(*rx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable rx_clk (%u)\n", err);
+		goto err_disable_txclk;
+	}
+
+	err = clk_prepare_enable(*sg_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable sg_clk (%u)\n", err);
+		goto err_disable_rxclk;
+	}
+
+	return 0;
+
+err_disable_rxclk:
+	clk_disable_unprepare(*rx_clk);
+err_disable_txclk:
+	clk_disable_unprepare(*tx_clk);
+err_disable_axiclk:
+	clk_disable_unprepare(*axi_clk);
+
+	return err;
+}
+
+static int axicdma_clk_init(struct platform_device *pdev, struct clk **axi_clk,
+			    struct clk **dev_clk, struct clk **tmp_clk,
+			    struct clk **tmp1_clk, struct clk **tmp2_clk)
+{
+	int err;
+
+	*tmp_clk = NULL;
+	*tmp1_clk = NULL;
+	*tmp2_clk = NULL;
+
+	*axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
+	if (IS_ERR(*axi_clk)) {
+		err = PTR_ERR(*axi_clk);
+		dev_err(&pdev->dev, "failed to get axi_clk (%u)\n", err);
+		return err;
+	}
+
+	*dev_clk = devm_clk_get(&pdev->dev, "m_axi_aclk");
+	if (IS_ERR(*dev_clk)) {
+		err = PTR_ERR(*dev_clk);
+		dev_err(&pdev->dev, "failed to get dev_clk (%u)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*axi_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axi_clk (%u)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*dev_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable dev_clk (%u)\n", err);
+		goto err_disable_axiclk;
+	}
+
+	return 0;
+
+err_disable_axiclk:
+	clk_disable_unprepare(*axi_clk);
+
+	return err;
+}
+
+static int axivdma_clk_init(struct platform_device *pdev, struct clk **axi_clk,
+			    struct clk **tx_clk, struct clk **txs_clk,
+			    struct clk **rx_clk, struct clk **rxs_clk)
+{
+	int err;
+
+	*axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
+	if (IS_ERR(*axi_clk)) {
+		err = PTR_ERR(*axi_clk);
+		dev_err(&pdev->dev, "failed to get axi_aclk (%u)\n", err);
+		return err;
+	}
+
+	*tx_clk = devm_clk_get(&pdev->dev, "m_axi_mm2s_aclk");
+	if (IS_ERR(*tx_clk))
+		*tx_clk = NULL;
+
+	*txs_clk = devm_clk_get(&pdev->dev, "m_axis_mm2s_aclk");
+	if (IS_ERR(*txs_clk))
+		*txs_clk = NULL;
+
+	*rx_clk = devm_clk_get(&pdev->dev, "m_axi_s2mm_aclk");
+	if (IS_ERR(*rx_clk))
+		*rx_clk = NULL;
+
+	*rxs_clk = devm_clk_get(&pdev->dev, "s_axis_s2mm_aclk");
+	if (IS_ERR(*rxs_clk))
+		*rxs_clk = NULL;
+
+	err = clk_prepare_enable(*axi_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axi_clk (%u)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*tx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
+		goto err_disable_axiclk;
+	}
+
+	err = clk_prepare_enable(*txs_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable txs_clk (%u)\n", err);
+		goto err_disable_txclk;
+	}
+
+	err = clk_prepare_enable(*rx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable rx_clk (%u)\n", err);
+		goto err_disable_txsclk;
+	}
+
+	err = clk_prepare_enable(*rxs_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable rxs_clk (%u)\n", err);
+		goto err_disable_rxclk;
+	}
+
+	return 0;
+
+err_disable_rxclk:
+	clk_disable_unprepare(*rx_clk);
+err_disable_txsclk:
+	clk_disable_unprepare(*txs_clk);
+err_disable_txclk:
+	clk_disable_unprepare(*tx_clk);
+err_disable_axiclk:
+	clk_disable_unprepare(*axi_clk);
+
+	return err;
+}
+
+static void xdma_disable_allclks(struct xilinx_dma_device *xdev)
+{
+	clk_disable_unprepare(xdev->rxs_clk);
+	clk_disable_unprepare(xdev->rx_clk);
+	clk_disable_unprepare(xdev->txs_clk);
+	clk_disable_unprepare(xdev->tx_clk);
+	clk_disable_unprepare(xdev->axi_clk);
+}
+
 /**
  * xilinx_dma_chan_probe - Per Channel Probing
  * It get channel features from the device tree entry and
@@ -1899,14 +2104,17 @@ static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec,
 
 static const struct xilinx_dma_config axidma_config = {
 	.dmatype = XDMA_TYPE_AXIDMA,
+	.clk_init = axidma_clk_init,
 };
 
 static const struct xilinx_dma_config axicdma_config = {
 	.dmatype = XDMA_TYPE_CDMA,
+	.clk_init = axicdma_clk_init,
 };
 
 static const struct xilinx_dma_config axivdma_config = {
 	.dmatype = XDMA_TYPE_VDMA,
+	.clk_init = axivdma_clk_init,
 };
 
 static const struct of_device_id xilinx_dma_of_ids[] = {
@@ -1925,6 +2133,9 @@ MODULE_DEVICE_TABLE(of, xilinx_dma_of_ids);
  */
 static int xilinx_dma_probe(struct platform_device *pdev)
 {
+	int (*clk_init)(struct platform_device *, struct clk **, struct clk **,
+			struct clk **, struct clk **, struct clk **)
+					= axivdma_clk_init;
 	struct device_node *node = pdev->dev.of_node;
 	struct xilinx_dma_device *xdev;
 	struct device_node *child, *np = pdev->dev.of_node;
@@ -1942,10 +2153,17 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 		const struct of_device_id *match;
 
 		match = of_match_node(xilinx_dma_of_ids, np);
-		if (match && match->data)
+		if (match && match->data) {
 			xdev->dma_config = match->data;
+			clk_init = xdev->dma_config->clk_init;
+		}
 	}
 
+	err = clk_init(pdev, &xdev->axi_clk, &xdev->tx_clk, &xdev->txs_clk,
+		       &xdev->rx_clk, &xdev->rxs_clk);
+	if (err)
+		return err;
+
 	/* Request and map I/O memory */
 	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	xdev->regs = devm_ioremap_resource(&pdev->dev, io);
@@ -2018,7 +2236,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 	for_each_child_of_node(node, child) {
 		err = xilinx_dma_chan_probe(xdev, child);
 		if (err < 0)
-			goto error;
+			goto disable_clks;
 	}
 
 	if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
@@ -2042,6 +2260,8 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 
 	return 0;
 
+disable_clks:
+	xdma_disable_allclks(xdev);
 error:
 	for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
 		if (xdev->chan[i])
@@ -2069,6 +2289,8 @@ static int xilinx_dma_remove(struct platform_device *pdev)
 		if (xdev->chan[i])
 			xilinx_dma_chan_remove(xdev->chan[i]);
 
+	xdma_disable_allclks(xdev);
+
 	return 0;
 }
 
-- 
2.1.1



From appana.durga.rao at xilinx.com  Fri May 13 00:03:52 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Fri, 13 May 2016 12:33:52 +0530
Subject: [PATCH v9 1/2] Documentation: DT: dma: Add Xilinx zynqmp dma device
 tree binding documentation
Message-ID: <1463123033-5443-1-git-send-email-appanad@xilinx.com>

Device-tree binding documentation for Xilinx zynqmp dma engine
used in Zynq UltraScale+ MPSoC.

Signed-off-by: Punnaiah Choudary Kalluri <punnaia at xilinx.com>
Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
Changs in v9:
- Removed include sg runtime configuration parameter
  from the binding doc as suggested by Lars.
Changes in v8:
- Removed all the software runtime configuration parameters
  from the binding doc as suggested by the Lars.
Changes in v7:
- None.
Changes in v6:
- Removed desc-axi-cache/dst-axi-cache/src-axi-cache properties
  from the binding doc as it allow broken combinations when dma-coherent
  is set as suggested by Rob.
- Fixed minor comments given by Rob related coding(lower case DT node name).
Changes in v5:
- Use dma-coherent flag for coherent transfers as suggested by rob.
- Removed unnecessary properties from binding doc as suggested by Rob.
Changes in v4:
- None
Changes in v3:
- None
Changes in v2:
- None.

 .../devicetree/bindings/dma/xilinx/zynqmp_dma.txt  | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/xilinx/zynqmp_dma.txt

diff --git a/Documentation/devicetree/bindings/dma/xilinx/zynqmp_dma.txt b/Documentation/devicetree/bindings/dma/xilinx/zynqmp_dma.txt
new file mode 100644
index 0000000..a784cdd
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/xilinx/zynqmp_dma.txt
@@ -0,0 +1,27 @@
+Xilinx ZynqMP DMA engine, it does support memory to memory transfers,
+memory to device and device to memory transfers. It also has flow
+control and rate control support for slave/peripheral dma access.
+
+Required properties:
+- compatible		: Should be "xlnx,zynqmp-dma-1.0"
+- reg			: Memory map for gdma/adma module access.
+- interrupt-parent	: Interrupt controller the interrupt is routed through
+- interrupts		: Should contain DMA channel interrupt.
+- xlnx,bus-width	: Axi buswidth in bits. Should contain 128 or 64
+- clock-names		: List of input clocks "clk_main", "clk_apb"
+			  (see clock bindings for details)
+
+Optional properties:
+- dma-coherent		: Present if dma operations are coherent.
+
+Example:
+++++++++
+fpd_dma_chan1: dma at fd500000 {
+	compatible = "xlnx,zynqmp-dma-1.0";
+	reg = <0x0 0xFD500000 0x1000>;
+	interrupt-parent = <&gic>;
+	interrupts = <0 117 4>;
+	clock-names = "clk_main", "clk_apb";
+	xlnx,bus-width = <128>;
+	dma-coherent;
+};
-- 
2.1.1



From appana.durga.rao at xilinx.com  Fri May 13 00:03:53 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Fri, 13 May 2016 12:33:53 +0530
Subject: [PATCH v9 2/2] dmaengine: Add Xilinx zynqmp dma engine driver support
In-Reply-To: <1463123033-5443-1-git-send-email-appanad@xilinx.com>
References: <1463123033-5443-1-git-send-email-appanad@xilinx.com>
Message-ID: <1463123033-5443-2-git-send-email-appanad@xilinx.com>

Added the driver for zynqmp dma engine used in Zynq
UltraScale+ MPSoC. This dma controller supports memory to memory
and memory to I/O buffer transfers.

Signed-off-by: Punnaiah Choudary Kalluri <punnaia at xilinx.com>
Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
Changes for v9:
- Derive the include sg software runtime configuration parameter
  through config strucutre as suggested by the Lars.
Changes for v8:
- Derive the software runtime configuration parameters
  through config strucutre and configure them during transfer
  as suggested by the Lars.
Changes for v7:
- Fixed kbuild compilation warnings.
- Fixed {src,dst}_addr_widths are supposed to be a bitmask of
  supported slave device widths as suggested by Rob.
Changes in v6:
- Removed unnecessary axcache properties from the driver
- Fixed compilation issues
Changes in v5:
- Removed in_interrupt check from the tasklet cleanup as
  suggested by the vinod/lars.
Changes in v4:
- Modified the defines to start with ZYNQMP_DMA perfix
- Changed the zynqmp_dma_alloc_chan_resources to return number of
  allocated descriptors
- Changed the zynqmp_dma_device variable name
- Released the locks before calling user callback
- freeup irq in zynqmp_dma_chan_remove function.
Changes in v3:
- Modified the zynqmp_dma_chan_is_idle function return type to bool
Changes in v2:
- Corrected the function header documentation
- Framework expects bus-width value in bytes. so, fixed it
- Removed magic numbers for bus-width

 drivers/dma/Kconfig             |    6 +
 drivers/dma/xilinx/Makefile     |    1 +
 drivers/dma/xilinx/zynqmp_dma.c | 1262 +++++++++++++++++++++++++++++++++++++++
 include/linux/dma/xilinx_dma.h  |   21 +-
 4 files changed, 1289 insertions(+), 1 deletion(-)
 create mode 100644 drivers/dma/xilinx/zynqmp_dma.c

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index f843dd5..6758417 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -527,6 +527,12 @@ config ZX_DMA
 	help
 	  Support the DMA engine for ZTE ZX296702 platform devices.
 
+config XILINX_ZYNQMP_DMA
+	tristate "Xilinx ZynqMP DMA Engine"
+	depends on (ARCH_ZYNQ || MICROBLAZE || ARM64)
+	select DMA_ENGINE
+	help
+	  Enable support for Xilinx ZynqMP DMA controller.
 
 # driver files
 source "drivers/dma/bestcomm/Kconfig"
diff --git a/drivers/dma/xilinx/Makefile b/drivers/dma/xilinx/Makefile
index 3c4e9f2..95469dc 100644
--- a/drivers/dma/xilinx/Makefile
+++ b/drivers/dma/xilinx/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_XILINX_VDMA) += xilinx_vdma.o
+obj-$(CONFIG_XILINX_ZYNQMP_DMA) += zynqmp_dma.o
diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
new file mode 100644
index 0000000..9964dcb
--- /dev/null
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -0,0 +1,1262 @@
+/*
+ * DMA driver for Xilinx ZynqMP DMA Engine
+ *
+ * Copyright (C) 2016 Xilinx, Inc. All rights reserved.
+ *
+ * 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.
+ */
+
+#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma/xilinx_dma.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_dma.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#include "../dmaengine.h"
+
+/* Register Offsets */
+#define ZYNQMP_DMA_ISR			0x100
+#define ZYNQMP_DMA_IMR			0x104
+#define ZYNQMP_DMA_IER			0x108
+#define ZYNQMP_DMA_IDS			0x10C
+#define ZYNQMP_DMA_CTRL0		0x110
+#define ZYNQMP_DMA_CTRL1		0x114
+#define ZYNQMP_DMA_DATA_ATTR		0x120
+#define ZYNQMP_DMA_DSCR_ATTR		0x124
+#define ZYNQMP_DMA_SRC_DSCR_WRD0	0x128
+#define ZYNQMP_DMA_SRC_DSCR_WRD1	0x12C
+#define ZYNQMP_DMA_SRC_DSCR_WRD2	0x130
+#define ZYNQMP_DMA_SRC_DSCR_WRD3	0x134
+#define ZYNQMP_DMA_DST_DSCR_WRD0	0x138
+#define ZYNQMP_DMA_DST_DSCR_WRD1	0x13C
+#define ZYNQMP_DMA_DST_DSCR_WRD2	0x140
+#define ZYNQMP_DMA_DST_DSCR_WRD3	0x144
+#define ZYNQMP_DMA_SRC_START_LSB	0x158
+#define ZYNQMP_DMA_SRC_START_MSB	0x15C
+#define ZYNQMP_DMA_DST_START_LSB	0x160
+#define ZYNQMP_DMA_DST_START_MSB	0x164
+#define ZYNQMP_DMA_RATE_CTRL		0x18C
+#define ZYNQMP_DMA_IRQ_SRC_ACCT		0x190
+#define ZYNQMP_DMA_IRQ_DST_ACCT		0x194
+#define ZYNQMP_DMA_CTRL2		0x200
+
+/* Interrupt registers bit field definitions */
+#define ZYNQMP_DMA_DONE			BIT(10)
+#define ZYNQMP_DMA_AXI_WR_DATA		BIT(9)
+#define ZYNQMP_DMA_AXI_RD_DATA		BIT(8)
+#define ZYNQMP_DMA_AXI_RD_DST_DSCR	BIT(7)
+#define ZYNQMP_DMA_AXI_RD_SRC_DSCR	BIT(6)
+#define ZYNQMP_DMA_IRQ_DST_ACCT_ERR	BIT(5)
+#define ZYNQMP_DMA_IRQ_SRC_ACCT_ERR	BIT(4)
+#define ZYNQMP_DMA_BYTE_CNT_OVRFL	BIT(3)
+#define ZYNQMP_DMA_DST_DSCR_DONE	BIT(2)
+#define ZYNQMP_DMA_INV_APB		BIT(0)
+
+/* Control 0 register bit field definitions */
+#define ZYNQMP_DMA_OVR_FETCH		BIT(7)
+#define ZYNQMP_DMA_POINT_TYPE_SG	BIT(6)
+#define ZYNQMP_DMA_RATE_CTRL_EN		BIT(3)
+
+/* Control 1 register bit field definitions */
+#define ZYNQMP_DMA_SRC_ISSUE		GENMASK(4, 0)
+
+/* Data Attribute register bit field definitions */
+#define ZYNQMP_DMA_ARBURST		GENMASK(27, 26)
+#define ZYNQMP_DMA_ARCACHE		GENMASK(25, 22)
+#define ZYNQMP_DMA_ARCACHE_OFST		22
+#define ZYNQMP_DMA_ARQOS		GENMASK(21, 18)
+#define ZYNQMP_DMA_ARQOS_OFST		18
+#define ZYNQMP_DMA_ARLEN		GENMASK(17, 14)
+#define ZYNQMP_DMA_ARLEN_OFST		14
+#define ZYNQMP_DMA_AWBURST		GENMASK(13, 12)
+#define ZYNQMP_DMA_AWCACHE		GENMASK(11, 8)
+#define ZYNQMP_DMA_AWCACHE_OFST		8
+#define ZYNQMP_DMA_AWQOS		GENMASK(7, 4)
+#define ZYNQMP_DMA_AWQOS_OFST		4
+#define ZYNQMP_DMA_AWLEN		GENMASK(3, 0)
+#define ZYNQMP_DMA_AWLEN_OFST		0
+
+/* Descriptor Attribute register bit field definitions */
+#define ZYNQMP_DMA_AXCOHRNT		BIT(8)
+#define ZYNQMP_DMA_AXCACHE		GENMASK(7, 4)
+#define ZYNQMP_DMA_AXCACHE_OFST		4
+#define ZYNQMP_DMA_AXQOS		GENMASK(3, 0)
+#define ZYNQMP_DMA_AXQOS_OFST		0
+
+/* Control register 2 bit field definitions */
+#define ZYNQMP_DMA_ENABLE		BIT(0)
+
+/* Buffer Descriptor definitions */
+#define ZYNQMP_DMA_DESC_CTRL_STOP	0x10
+#define ZYNQMP_DMA_DESC_CTRL_COMP_INT	0x4
+#define ZYNQMP_DMA_DESC_CTRL_SIZE_256	0x2
+#define ZYNQMP_DMA_DESC_CTRL_COHRNT	0x1
+
+/* Interrupt Mask specific definitions */
+#define ZYNQMP_DMA_INT_ERR	(ZYNQMP_DMA_AXI_RD_DATA | \
+				ZYNQMP_DMA_AXI_WR_DATA | \
+				ZYNQMP_DMA_AXI_RD_DST_DSCR | \
+				ZYNQMP_DMA_AXI_RD_SRC_DSCR | \
+				ZYNQMP_DMA_INV_APB)
+#define ZYNQMP_DMA_INT_OVRFL	(ZYNQMP_DMA_BYTE_CNT_OVRFL | \
+				ZYNQMP_DMA_IRQ_SRC_ACCT_ERR | \
+				ZYNQMP_DMA_IRQ_DST_ACCT_ERR)
+#define ZYNQMP_DMA_INT_DONE	(ZYNQMP_DMA_DONE | ZYNQMP_DMA_DST_DSCR_DONE)
+#define ZYNQMP_DMA_INT_EN_DEFAULT_MASK	(ZYNQMP_DMA_INT_DONE | \
+					ZYNQMP_DMA_INT_ERR | \
+					ZYNQMP_DMA_INT_OVRFL | \
+					ZYNQMP_DMA_DST_DSCR_DONE)
+
+/* Max number of descriptors per channel */
+#define ZYNQMP_DMA_NUM_DESCS	32
+
+/* Max transfer size per descriptor */
+#define ZYNQMP_DMA_MAX_TRANS_LEN	0x40000000
+
+/* Reset values for data attributes */
+#define ZYNQMP_DMA_AXCACHE_VAL		0xF
+#define ZYNQMP_DMA_ARLEN_RST_VAL	0xF
+#define ZYNQMP_DMA_AWLEN_RST_VAL	0xF
+
+#define ZYNQMP_DMA_SRC_ISSUE_RST_VAL	0x1F
+
+#define ZYNQMP_DMA_IDS_DEFAULT_MASK	0xFFF
+
+/* Bus width in bits */
+#define ZYNQMP_DMA_BUS_WIDTH_64		64
+#define ZYNQMP_DMA_BUS_WIDTH_128	128
+
+#define ZYNQMP_DMA_DESC_SIZE(chan)	(chan->desc_size)
+
+#define to_chan(chan)		container_of(chan, struct zynqmp_dma_chan, \
+					     common)
+#define tx_to_desc(tx)		container_of(tx, struct zynqmp_dma_desc_sw, \
+					     async_tx)
+
+/**
+ * struct zynqmp_dma_desc_ll - Hw linked list descriptor
+ * @addr: Buffer address
+ * @size: Size of the buffer
+ * @ctrl: Control word
+ * @nxtdscraddr: Next descriptor base address
+ * @rsvd: Reserved field and for Hw internal use.
+ */
+struct zynqmp_dma_desc_ll {
+	u64 addr;
+	u32 size;
+	u32 ctrl;
+	u64 nxtdscraddr;
+	u64 rsvd;
+}; __aligned(64)
+
+/**
+ * struct zynqmp_dma_desc_sw - Per Transaction structure
+ * @src: Source address for simple mode dma
+ * @dst: Destination address for simple mode dma
+ * @len: Transfer length for simple mode dma
+ * @node: Node in the channel descriptor list
+ * @tx_list: List head for the current transfer
+ * @async_tx: Async transaction descriptor
+ * @src_v: Virtual address of the src descriptor
+ * @src_p: Physical address of the src descriptor
+ * @dst_v: Virtual address of the dst descriptor
+ * @dst_p: Physical address of the dst descriptor
+ */
+struct zynqmp_dma_desc_sw {
+	u64 src;
+	u64 dst;
+	u32 len;
+	struct list_head node;
+	struct list_head tx_list;
+	struct dma_async_tx_descriptor async_tx;
+	struct zynqmp_dma_desc_ll *src_v;
+	dma_addr_t src_p;
+	struct zynqmp_dma_desc_ll *dst_v;
+	dma_addr_t dst_p;
+};
+
+/**
+ * struct zynqmp_dma_chan - Driver specific DMA channel structure
+ * @zdev: Driver specific device structure
+ * @regs: Control registers offset
+ * @lock: Descriptor operation lock
+ * @pending_list: Descriptors waiting
+ * @free_list: Descriptors free
+ * @active_list: Descriptors active
+ * @sw_desc_pool: SW descriptor pool
+ * @done_list: Complete descriptors
+ * @common: DMA common channel
+ * @desc_pool_v: Statically allocated descriptor base
+ * @desc_pool_p: Physical allocated descriptor base
+ * @desc_free_cnt: Descriptor available count
+ * @dev: The dma device
+ * @irq: Channel IRQ
+ * @is_dmacoherent: Tells whether dma operations are coherent or not
+ * @tasklet: Cleanup work after irq
+ * @idle : Channel status;
+ * @desc_size: Size of the low level descriptor
+ * @err: Channel has errors
+ * @bus_width: Bus width
+ * @clk_main: Pointer to main clock
+ * @clk_apb: Pointer to apb clock
+ * @config: Device configuration info
+ */
+struct zynqmp_dma_chan {
+	struct zynqmp_dma_device *zdev;
+	void __iomem *regs;
+	spinlock_t lock;
+	struct list_head pending_list;
+	struct list_head free_list;
+	struct list_head active_list;
+	struct zynqmp_dma_desc_sw *sw_desc_pool;
+	struct list_head done_list;
+	struct dma_chan common;
+	void *desc_pool_v;
+	dma_addr_t desc_pool_p;
+	u32 desc_free_cnt;
+	struct device *dev;
+	int irq;
+	bool is_dmacoherent;
+	struct tasklet_struct tasklet;
+	bool idle;
+	u32 desc_size;
+	bool err;
+	u32 bus_width;
+	struct clk *clk_main;
+	struct clk *clk_apb;
+	struct zynqmp_dma_config config;
+};
+
+/**
+ * struct zynqmp_dma_device - DMA device structure
+ * @dev: Device Structure
+ * @common: DMA device structure
+ * @chan: Driver specific DMA channel
+ */
+struct zynqmp_dma_device {
+	struct device *dev;
+	struct dma_device common;
+	struct zynqmp_dma_chan *chan;
+};
+
+/**
+ * zynqmp_dma_chan_is_idle - Provides the channel idle status
+ * @chan: ZynqMP DMA DMA channel pointer
+ *
+ * Return: 'true' if the channel is idle otherwise 'false'
+ */
+static inline bool zynqmp_dma_chan_is_idle(struct zynqmp_dma_chan *chan)
+{
+	return chan->idle;
+
+}
+
+/**
+ * zynqmp_dma_update_desc_to_ctrlr - Updates descriptor to the controller
+ * @chan: ZynqMP DMA DMA channel pointer
+ * @desc: Transaction descriptor pointer
+ */
+static void zynqmp_dma_update_desc_to_ctrlr(struct zynqmp_dma_chan *chan,
+				      struct zynqmp_dma_desc_sw *desc)
+{
+	dma_addr_t addr;
+
+	addr = desc->src_p;
+	writel(addr, chan->regs + ZYNQMP_DMA_SRC_START_LSB);
+	writel(upper_32_bits(addr), chan->regs + ZYNQMP_DMA_SRC_START_MSB);
+	addr = desc->dst_p;
+	writel(addr, chan->regs + ZYNQMP_DMA_DST_START_LSB);
+	writel(upper_32_bits(addr), chan->regs + ZYNQMP_DMA_DST_START_MSB);
+}
+
+/**
+ * zynqmp_dma_desc_config_eod - Mark the descriptor as end descriptor
+ * @chan: ZynqMP DMA channel pointer
+ * @desc: Hw descriptor pointer
+ */
+static void zynqmp_dma_desc_config_eod(struct zynqmp_dma_chan *chan, void *desc)
+{
+	struct zynqmp_dma_desc_ll *hw = (struct zynqmp_dma_desc_ll *)desc;
+
+	hw->ctrl |= ZYNQMP_DMA_DESC_CTRL_STOP;
+	hw++;
+	hw->ctrl |= ZYNQMP_DMA_DESC_CTRL_COMP_INT | ZYNQMP_DMA_DESC_CTRL_STOP;
+}
+
+/**
+ * zynqmp_dma_config_simple_desc - Configure the transfer parameters
+ * @chan: ZynqMP DMA channel pointer
+ * @src: Source buffer address
+ * @dst: Destination buffer address
+ * @len: Transfer length
+ */
+static void zynqmp_dma_config_simple_desc(struct zynqmp_dma_chan *chan,
+					  dma_addr_t src, dma_addr_t dst,
+					  size_t len)
+{
+	u32 val;
+
+	writel(src, chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD0);
+	writel(upper_32_bits(src), chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD1);
+	writel(len, chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD2);
+
+	if (chan->is_dmacoherent)
+		writel(ZYNQMP_DMA_DESC_CTRL_COHRNT,
+			chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD3);
+	else
+		writel(0, chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD3);
+
+	writel(dst, chan->regs + ZYNQMP_DMA_DST_DSCR_WRD0);
+	writel(upper_32_bits(dst), chan->regs + ZYNQMP_DMA_DST_DSCR_WRD1);
+	writel(len, chan->regs + ZYNQMP_DMA_DST_DSCR_WRD2);
+
+	if (chan->is_dmacoherent)
+		val = ZYNQMP_DMA_DESC_CTRL_COHRNT |
+				ZYNQMP_DMA_DESC_CTRL_COMP_INT;
+	else
+		val = ZYNQMP_DMA_DESC_CTRL_COMP_INT;
+	writel(val, chan->regs + ZYNQMP_DMA_DST_DSCR_WRD3);
+}
+
+/**
+ * zynqmp_dma_config_sg_ll_desc - Configure the linked list descriptor
+ * @chan: ZynqMP DMA channel pointer
+ * @sdesc: Hw descriptor pointer
+ * @src: Source buffer address
+ * @dst: Destination buffer address
+ * @len: Transfer length
+ * @prev: Previous hw descriptor pointer
+ */
+static void zynqmp_dma_config_sg_ll_desc(struct zynqmp_dma_chan *chan,
+				   struct zynqmp_dma_desc_ll *sdesc,
+				   dma_addr_t src, dma_addr_t dst, size_t len,
+				   struct zynqmp_dma_desc_ll *prev)
+{
+	struct zynqmp_dma_desc_ll *ddesc = sdesc + 1;
+
+	sdesc->size = ddesc->size = len;
+	sdesc->addr = src;
+	ddesc->addr = dst;
+
+	sdesc->ctrl = ddesc->ctrl = ZYNQMP_DMA_DESC_CTRL_SIZE_256;
+	if (chan->is_dmacoherent) {
+		sdesc->ctrl |= ZYNQMP_DMA_DESC_CTRL_COHRNT;
+		ddesc->ctrl |= ZYNQMP_DMA_DESC_CTRL_COHRNT;
+	}
+
+	if (prev) {
+		dma_addr_t addr = chan->desc_pool_p +
+			    ((dma_addr_t)sdesc - (dma_addr_t)chan->desc_pool_v);
+		ddesc = prev + 1;
+		prev->nxtdscraddr = addr;
+		ddesc->nxtdscraddr = addr + ZYNQMP_DMA_DESC_SIZE(chan);
+	}
+}
+
+/**
+ * zynqmp_dma_init - Initialize the channel
+ * @chan: ZynqMP DMA channel pointer
+ */
+static void zynqmp_dma_init(struct zynqmp_dma_chan *chan)
+{
+	u32 val;
+
+	writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS);
+	val = readl(chan->regs + ZYNQMP_DMA_ISR);
+	writel(val, chan->regs + ZYNQMP_DMA_ISR);
+
+	val = 0;
+	if (chan->config.has_sg)
+		val |= ZYNQMP_DMA_POINT_TYPE_SG;
+	writel(val, chan->regs + ZYNQMP_DMA_CTRL0);
+
+	val = 0;
+	if (chan->is_dmacoherent) {
+		val |= ZYNQMP_DMA_AXCOHRNT;
+		val = (val & ~ZYNQMP_DMA_AXCACHE) |
+			(ZYNQMP_DMA_AXCACHE_VAL << ZYNQMP_DMA_AXCACHE_OFST);
+	}
+	writel(val, chan->regs + ZYNQMP_DMA_DSCR_ATTR);
+
+	val = readl(chan->regs + ZYNQMP_DMA_DATA_ATTR);
+	if (chan->is_dmacoherent) {
+		val = (val & ~ZYNQMP_DMA_ARCACHE) |
+			(ZYNQMP_DMA_AXCACHE_VAL << ZYNQMP_DMA_ARCACHE_OFST);
+		val = (val & ~ZYNQMP_DMA_AWCACHE) |
+			(ZYNQMP_DMA_AXCACHE_VAL << ZYNQMP_DMA_AWCACHE_OFST);
+	}
+	writel(val, chan->regs + ZYNQMP_DMA_DATA_ATTR);
+
+	/* Clearing the interrupt account rgisters */
+	val = readl(chan->regs + ZYNQMP_DMA_IRQ_SRC_ACCT);
+	val = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
+
+	chan->idle = true;
+}
+
+/**
+ * zynqmp_dma_tx_submit - Submit DMA transaction
+ * @tx: Async transaction descriptor pointer
+ *
+ * Return: cookie value
+ */
+static dma_cookie_t zynqmp_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct zynqmp_dma_chan *chan = to_chan(tx->chan);
+	struct zynqmp_dma_desc_sw *desc, *new;
+	dma_cookie_t cookie;
+
+	new = tx_to_desc(tx);
+	spin_lock_bh(&chan->lock);
+	cookie = dma_cookie_assign(tx);
+
+	if (!list_empty(&chan->pending_list) && chan->config.has_sg) {
+		desc = list_last_entry(&chan->pending_list,
+				     struct zynqmp_dma_desc_sw, node);
+		if (!list_empty(&desc->tx_list))
+			desc = list_last_entry(&desc->tx_list,
+					       struct zynqmp_dma_desc_sw, node);
+		desc->src_v->nxtdscraddr = new->src_p;
+		desc->src_v->ctrl &= ~ZYNQMP_DMA_DESC_CTRL_STOP;
+		desc->dst_v->nxtdscraddr = new->dst_p;
+		desc->dst_v->ctrl &= ~ZYNQMP_DMA_DESC_CTRL_STOP;
+	}
+
+	list_add_tail(&new->node, &chan->pending_list);
+	spin_unlock_bh(&chan->lock);
+
+	return cookie;
+}
+
+/**
+ * zynqmp_dma_get_descriptor - Get the sw descriptor from the pool
+ * @chan: ZynqMP DMA channel pointer
+ *
+ * Return: The sw descriptor
+ */
+static struct zynqmp_dma_desc_sw *
+zynqmp_dma_get_descriptor(struct zynqmp_dma_chan *chan)
+{
+	struct zynqmp_dma_desc_sw *desc;
+
+	spin_lock_bh(&chan->lock);
+	desc = list_first_entry(&chan->free_list, struct zynqmp_dma_desc_sw,
+				 node);
+	list_del(&desc->node);
+	spin_unlock_bh(&chan->lock);
+
+	INIT_LIST_HEAD(&desc->tx_list);
+	/* Clear the src and dst descriptor memory */
+	if (chan->config.has_sg) {
+		memset((void *)desc->src_v, 0, ZYNQMP_DMA_DESC_SIZE(chan));
+		memset((void *)desc->dst_v, 0, ZYNQMP_DMA_DESC_SIZE(chan));
+	}
+
+	return desc;
+}
+
+/**
+ * zynqmp_dma_free_descriptor - Issue pending transactions
+ * @chan: ZynqMP DMA channel pointer
+ * @sdesc: Transaction descriptor pointer
+ */
+static void zynqmp_dma_free_descriptor(struct zynqmp_dma_chan *chan,
+				 struct zynqmp_dma_desc_sw *sdesc)
+{
+	struct zynqmp_dma_desc_sw *child, *next;
+
+	chan->desc_free_cnt++;
+	list_add_tail(&sdesc->node, &chan->free_list);
+	list_for_each_entry_safe(child, next, &sdesc->tx_list, node) {
+		chan->desc_free_cnt++;
+		INIT_LIST_HEAD(&child->tx_list);
+		list_move_tail(&child->node, &chan->free_list);
+	}
+	INIT_LIST_HEAD(&sdesc->tx_list);
+}
+
+/**
+ * zynqmp_dma_free_desc_list - Free descriptors list
+ * @chan: ZynqMP DMA channel pointer
+ * @list: List to parse and delete the descriptor
+ */
+static void zynqmp_dma_free_desc_list(struct zynqmp_dma_chan *chan,
+				      struct list_head *list)
+{
+	struct zynqmp_dma_desc_sw *desc, *next;
+
+	list_for_each_entry_safe(desc, next, list, node)
+		zynqmp_dma_free_descriptor(chan, desc);
+}
+
+/**
+ * zynqmp_dma_alloc_chan_resources - Allocate channel resources
+ * @dchan: DMA channel
+ *
+ * Return: Number of descriptors on success and failure value on error
+ */
+static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan)
+{
+	struct zynqmp_dma_chan *chan = to_chan(dchan);
+	struct zynqmp_dma_desc_sw *desc;
+	int i;
+
+	chan->sw_desc_pool = kzalloc(sizeof(*desc) * ZYNQMP_DMA_NUM_DESCS,
+				     GFP_KERNEL);
+	if (!chan->sw_desc_pool)
+		return -ENOMEM;
+	chan->idle = true;
+	chan->desc_free_cnt = ZYNQMP_DMA_NUM_DESCS;
+
+	INIT_LIST_HEAD(&chan->free_list);
+
+	for (i = 0; i < ZYNQMP_DMA_NUM_DESCS; i++) {
+		desc = chan->sw_desc_pool + i;
+		dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
+		desc->async_tx.tx_submit = zynqmp_dma_tx_submit;
+		list_add_tail(&desc->node, &chan->free_list);
+	}
+
+	chan->desc_pool_v = dma_zalloc_coherent(chan->dev,
+				(2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS),
+				&chan->desc_pool_p, GFP_KERNEL);
+	if (!chan->desc_pool_v)
+		return -ENOMEM;
+
+	for (i = 0; i < ZYNQMP_DMA_NUM_DESCS; i++) {
+		desc = chan->sw_desc_pool + i;
+		desc->src_v = (struct zynqmp_dma_desc_ll *) (chan->desc_pool_v +
+					(i * ZYNQMP_DMA_DESC_SIZE(chan) * 2));
+		desc->dst_v = (struct zynqmp_dma_desc_ll *) (desc->src_v + 1);
+		desc->src_p = chan->desc_pool_p +
+				(i * ZYNQMP_DMA_DESC_SIZE(chan) * 2);
+		desc->dst_p = desc->src_p + ZYNQMP_DMA_DESC_SIZE(chan);
+	}
+
+	return ZYNQMP_DMA_NUM_DESCS;
+}
+
+/**
+ * zynqmp_dma_start - Start DMA channel
+ * @chan: ZynqMP DMA channel pointer
+ */
+static void zynqmp_dma_start(struct zynqmp_dma_chan *chan)
+{
+	writel(ZYNQMP_DMA_INT_EN_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IER);
+	chan->idle = false;
+	writel(ZYNQMP_DMA_ENABLE, chan->regs + ZYNQMP_DMA_CTRL2);
+}
+
+/**
+ * zynqmp_dma_handle_ovfl_int - Process the overflow interrupt
+ * @chan: ZynqMP DMA channel pointer
+ * @status: Interrupt status value
+ */
+static void zynqmp_dma_handle_ovfl_int(struct zynqmp_dma_chan *chan, u32 status)
+{
+	u32 val;
+
+	if (status & ZYNQMP_DMA_IRQ_DST_ACCT_ERR)
+		val = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
+	if (status & ZYNQMP_DMA_IRQ_SRC_ACCT_ERR)
+		val = readl(chan->regs + ZYNQMP_DMA_IRQ_SRC_ACCT);
+}
+
+static void zynqmp_dma_config(struct zynqmp_dma_chan *chan)
+{
+	u32 val;
+
+	val = readl(chan->regs + ZYNQMP_DMA_CTRL0);
+	if (chan->config.ovrfetch)
+		val |= ZYNQMP_DMA_OVR_FETCH;
+	if (chan->config.ratectrl) {
+		val |= ZYNQMP_DMA_RATE_CTRL_EN;
+		writel(chan->config.ratectrl, chan->regs +
+		       ZYNQMP_DMA_RATE_CTRL);
+	}
+	writel(val, chan->regs + ZYNQMP_DMA_CTRL0);
+
+	val = readl(chan->regs + ZYNQMP_DMA_CTRL1);
+	if (chan->config.src_issue)
+		val = (val & ~ZYNQMP_DMA_SRC_ISSUE) | chan->config.src_issue;
+	else
+		val |= ZYNQMP_DMA_SRC_ISSUE_RST_VAL;
+	writel(val, chan->regs + ZYNQMP_DMA_CTRL1);
+
+	val = readl(chan->regs + ZYNQMP_DMA_DATA_ATTR);
+	if (chan->config.src_burst_len)
+		val = (val & ~ZYNQMP_DMA_ARLEN) |
+			(chan->config.src_burst_len << ZYNQMP_DMA_ARLEN_OFST);
+	else
+		val |= ZYNQMP_DMA_ARLEN_RST_VAL;
+
+	if (chan->config.dst_burst_len)
+		val = (val & ~ZYNQMP_DMA_AWLEN) |
+			(chan->config.dst_burst_len << ZYNQMP_DMA_AWLEN_OFST);
+	else
+		val |= ZYNQMP_DMA_AWLEN_RST_VAL;
+	writel(val, chan->regs + ZYNQMP_DMA_DATA_ATTR);
+
+}
+
+/**
+ * zynqmp_dma_start_transfer - Initiate the new transfer
+ * @chan: ZynqMP DMA channel pointer
+ */
+static void zynqmp_dma_start_transfer(struct zynqmp_dma_chan *chan)
+{
+	struct zynqmp_dma_desc_sw *desc;
+
+	if (!zynqmp_dma_chan_is_idle(chan))
+		return;
+
+	zynqmp_dma_config(chan);
+
+	desc = list_first_entry_or_null(&chan->pending_list,
+					struct zynqmp_dma_desc_sw, node);
+	if (!desc)
+		return;
+
+	if (chan->config.has_sg)
+		list_splice_tail_init(&chan->pending_list, &chan->active_list);
+	else
+		list_move_tail(&desc->node, &chan->active_list);
+
+	if (chan->config.has_sg)
+		zynqmp_dma_update_desc_to_ctrlr(chan, desc);
+	else
+		zynqmp_dma_config_simple_desc(chan, desc->src, desc->dst,
+					      desc->len);
+
+	zynqmp_dma_start(chan);
+}
+
+
+/**
+ * zynqmp_dma_chan_desc_cleanup - Cleanup the completed descriptors
+ * @chan: ZynqMP DMA channel
+ */
+static void zynqmp_dma_chan_desc_cleanup(struct zynqmp_dma_chan *chan)
+{
+	struct zynqmp_dma_desc_sw *desc, *next;
+
+	list_for_each_entry_safe(desc, next, &chan->done_list, node) {
+		dma_async_tx_callback callback;
+		void *callback_param;
+
+		list_del(&desc->node);
+
+		callback = desc->async_tx.callback;
+		callback_param = desc->async_tx.callback_param;
+		if (callback) {
+			spin_unlock(&chan->lock);
+			callback(callback_param);
+			spin_lock(&chan->lock);
+		}
+
+		/* Run any dependencies, then free the descriptor */
+		zynqmp_dma_free_descriptor(chan, desc);
+	}
+}
+
+/**
+ * zynqmp_dma_complete_descriptor - Mark the active descriptor as complete
+ * @chan: ZynqMP DMA channel pointer
+ */
+static void zynqmp_dma_complete_descriptor(struct zynqmp_dma_chan *chan)
+{
+	struct zynqmp_dma_desc_sw *desc;
+
+	desc = list_first_entry_or_null(&chan->active_list,
+					struct zynqmp_dma_desc_sw, node);
+	if (!desc)
+		return;
+	list_del(&desc->node);
+	dma_cookie_complete(&desc->async_tx);
+	list_add_tail(&desc->node, &chan->done_list);
+}
+
+/**
+ * zynqmp_dma_issue_pending - Issue pending transactions
+ * @dchan: DMA channel pointer
+ */
+static void zynqmp_dma_issue_pending(struct dma_chan *dchan)
+{
+	struct zynqmp_dma_chan *chan = to_chan(dchan);
+
+	spin_lock_bh(&chan->lock);
+	zynqmp_dma_start_transfer(chan);
+	spin_unlock_bh(&chan->lock);
+}
+
+/**
+ * zynqmp_dma_free_descriptors - Free channel descriptors
+ * @dchan: DMA channel pointer
+ */
+static void zynqmp_dma_free_descriptors(struct zynqmp_dma_chan *chan)
+{
+	zynqmp_dma_free_desc_list(chan, &chan->active_list);
+	zynqmp_dma_free_desc_list(chan, &chan->pending_list);
+	zynqmp_dma_free_desc_list(chan, &chan->done_list);
+}
+
+/**
+ * zynqmp_dma_free_chan_resources - Free channel resources
+ * @dchan: DMA channel pointer
+ */
+static void zynqmp_dma_free_chan_resources(struct dma_chan *dchan)
+{
+	struct zynqmp_dma_chan *chan = to_chan(dchan);
+
+	spin_lock_bh(&chan->lock);
+	zynqmp_dma_free_descriptors(chan);
+	spin_unlock_bh(&chan->lock);
+	dma_free_coherent(chan->dev,
+		(2 * ZYNQMP_DMA_DESC_SIZE(chan) * ZYNQMP_DMA_NUM_DESCS),
+		chan->desc_pool_v, chan->desc_pool_p);
+	kfree(chan->sw_desc_pool);
+}
+
+/**
+ * zynqmp_dma_tx_status - Get dma transaction status
+ * @dchan: DMA channel pointer
+ * @cookie: Transaction identifier
+ * @txstate: Transaction state
+ *
+ * Return: DMA transaction status
+ */
+static enum dma_status zynqmp_dma_tx_status(struct dma_chan *dchan,
+				      dma_cookie_t cookie,
+				      struct dma_tx_state *txstate)
+{
+	return dma_cookie_status(dchan, cookie, txstate);
+}
+
+/**
+ * zynqmp_dma_reset - Reset the channel
+ * @chan: ZynqMP DMA channel pointer
+ */
+static void zynqmp_dma_reset(struct zynqmp_dma_chan *chan)
+{
+	writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS);
+
+	zynqmp_dma_complete_descriptor(chan);
+	zynqmp_dma_chan_desc_cleanup(chan);
+	zynqmp_dma_free_descriptors(chan);
+	zynqmp_dma_init(chan);
+}
+
+/**
+ * zynqmp_dma_irq_handler - ZynqMP DMA Interrupt handler
+ * @irq: IRQ number
+ * @data: Pointer to the ZynqMP DMA channel structure
+ *
+ * Return: IRQ_HANDLED/IRQ_NONE
+ */
+static irqreturn_t zynqmp_dma_irq_handler(int irq, void *data)
+{
+	struct zynqmp_dma_chan *chan = (struct zynqmp_dma_chan *)data;
+	u32 isr, imr, status;
+	irqreturn_t ret = IRQ_NONE;
+
+	isr = readl(chan->regs + ZYNQMP_DMA_ISR);
+	imr = readl(chan->regs + ZYNQMP_DMA_IMR);
+	status = isr & ~imr;
+
+	writel(isr, chan->regs + ZYNQMP_DMA_ISR);
+	if (status & ZYNQMP_DMA_INT_DONE) {
+		tasklet_schedule(&chan->tasklet);
+		ret = IRQ_HANDLED;
+	}
+
+	if (status & ZYNQMP_DMA_DONE)
+		chan->idle = true;
+
+	if (status & ZYNQMP_DMA_INT_ERR) {
+		chan->err = true;
+		tasklet_schedule(&chan->tasklet);
+		dev_err(chan->dev, "Channel %p has errors\n", chan);
+		ret = IRQ_HANDLED;
+	}
+
+	if (status & ZYNQMP_DMA_INT_OVRFL) {
+		zynqmp_dma_handle_ovfl_int(chan, status);
+		dev_info(chan->dev, "Channel %p overflow interrupt\n", chan);
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+/**
+ * zynqmp_dma_do_tasklet - Schedule completion tasklet
+ * @data: Pointer to the ZynqMP DMA channel structure
+ */
+static void zynqmp_dma_do_tasklet(unsigned long data)
+{
+	struct zynqmp_dma_chan *chan = (struct zynqmp_dma_chan *)data;
+	u32 count;
+
+	spin_lock(&chan->lock);
+
+	if (chan->err) {
+		zynqmp_dma_reset(chan);
+		chan->err = false;
+		goto unlock;
+	}
+
+	count = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
+
+	while (count) {
+		zynqmp_dma_complete_descriptor(chan);
+		zynqmp_dma_chan_desc_cleanup(chan);
+		count--;
+	}
+
+	if (chan->idle)
+		zynqmp_dma_start_transfer(chan);
+
+unlock:
+	spin_unlock(&chan->lock);
+}
+
+/**
+ * zynqmp_dma_device_terminate_all - Aborts all transfers on a channel
+ * @dchan: DMA channel pointer
+ *
+ * Return: Always '0'
+ */
+static int zynqmp_dma_device_terminate_all(struct dma_chan *dchan)
+{
+	struct zynqmp_dma_chan *chan = to_chan(dchan);
+
+	spin_lock_bh(&chan->lock);
+	writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS);
+	zynqmp_dma_free_descriptors(chan);
+	spin_unlock_bh(&chan->lock);
+
+	return 0;
+}
+
+/**
+ * zynqmp_dma_prep_memcpy - prepare descriptors for memcpy transaction
+ * @dchan: DMA channel
+ * @dma_dst: Destination buffer address
+ * @dma_src: Source buffer address
+ * @len: Transfer length
+ * @flags: transfer ack flags
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
+ */
+static struct dma_async_tx_descriptor *zynqmp_dma_prep_memcpy(
+				struct dma_chan *dchan, dma_addr_t dma_dst,
+				dma_addr_t dma_src, size_t len, ulong flags)
+{
+	struct zynqmp_dma_chan *chan;
+	struct zynqmp_dma_desc_sw *new, *first = NULL;
+	void *desc = NULL, *prev = NULL;
+	size_t copy;
+	u32 desc_cnt;
+
+	chan = to_chan(dchan);
+
+	if ((len > ZYNQMP_DMA_MAX_TRANS_LEN) && !chan->config.has_sg)
+		return NULL;
+
+	desc_cnt = DIV_ROUND_UP(len, ZYNQMP_DMA_MAX_TRANS_LEN);
+
+	spin_lock_bh(&chan->lock);
+	if ((desc_cnt > chan->desc_free_cnt) && chan->config.has_sg) {
+		spin_unlock_bh(&chan->lock);
+		dev_dbg(chan->dev, "chan %p descs are not available\n", chan);
+		return NULL;
+	}
+	chan->desc_free_cnt = chan->desc_free_cnt - desc_cnt;
+	spin_unlock_bh(&chan->lock);
+
+	do {
+		/* Allocate and populate the descriptor */
+		new = zynqmp_dma_get_descriptor(chan);
+
+		copy = min_t(size_t, len, ZYNQMP_DMA_MAX_TRANS_LEN);
+		if (chan->config.has_sg) {
+			desc = (struct zynqmp_dma_desc_ll *)new->src_v;
+			zynqmp_dma_config_sg_ll_desc(chan, desc, dma_src,
+						     dma_dst, copy, prev);
+		} else {
+			new->src = dma_src;
+			new->dst = dma_dst;
+			new->len = len;
+		}
+
+		prev = desc;
+		len -= copy;
+		dma_src += copy;
+		dma_dst += copy;
+		if (!first)
+			first = new;
+		else
+			list_add_tail(&new->node, &first->tx_list);
+	} while (len);
+
+	if (chan->config.has_sg)
+		zynqmp_dma_desc_config_eod(chan, desc);
+
+	async_tx_ack(&first->async_tx);
+	first->async_tx.flags = flags;
+	return &first->async_tx;
+}
+
+/**
+ * zynqmp_dma_prep_slave_sg - prepare descriptors for a memory sg transaction
+ * @dchan: DMA channel
+ * @dst_sg: Destination scatter list
+ * @dst_sg_len: Number of entries in destination scatter list
+ * @src_sg: Source scatter list
+ * @src_sg_len: Number of entries in source scatter list
+ * @flags: transfer ack flags
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
+ */
+static struct dma_async_tx_descriptor *zynqmp_dma_prep_sg(
+			struct dma_chan *dchan, struct scatterlist *dst_sg,
+			unsigned int dst_sg_len, struct scatterlist *src_sg,
+			unsigned int src_sg_len, unsigned long flags)
+{
+	struct zynqmp_dma_desc_sw *new, *first = NULL;
+	struct zynqmp_dma_chan *chan = to_chan(dchan);
+	void *desc = NULL, *prev = NULL;
+	size_t len, dst_avail, src_avail;
+	dma_addr_t dma_dst, dma_src;
+	u32 desc_cnt = 0, i;
+	struct scatterlist *sg;
+
+	if (!chan->config.has_sg)
+		return NULL;
+
+	for_each_sg(src_sg, sg, src_sg_len, i)
+		desc_cnt += DIV_ROUND_UP(sg_dma_len(sg),
+					 ZYNQMP_DMA_MAX_TRANS_LEN);
+
+	spin_lock_bh(&chan->lock);
+	if (desc_cnt > chan->desc_free_cnt) {
+		spin_unlock_bh(&chan->lock);
+		dev_dbg(chan->dev, "chan %p descs are not available\n", chan);
+		return NULL;
+	}
+	chan->desc_free_cnt = chan->desc_free_cnt - desc_cnt;
+	spin_unlock_bh(&chan->lock);
+
+	dst_avail = sg_dma_len(dst_sg);
+	src_avail = sg_dma_len(src_sg);
+
+	/* Run until we are out of scatterlist entries */
+	while (true) {
+		/* Allocate and populate the descriptor */
+		new = zynqmp_dma_get_descriptor(chan);
+		desc = (struct zynqmp_dma_desc_ll *)new->src_v;
+		len = min_t(size_t, src_avail, dst_avail);
+		len = min_t(size_t, len, ZYNQMP_DMA_MAX_TRANS_LEN);
+		if (len == 0)
+			goto fetch;
+		dma_dst = sg_dma_address(dst_sg) + sg_dma_len(dst_sg) -
+			dst_avail;
+		dma_src = sg_dma_address(src_sg) + sg_dma_len(src_sg) -
+			src_avail;
+
+		zynqmp_dma_config_sg_ll_desc(chan, desc, dma_src, dma_dst,
+					     len, prev);
+		prev = desc;
+		dst_avail -= len;
+		src_avail -= len;
+
+		if (!first)
+			first = new;
+		else
+			list_add_tail(&new->node, &first->tx_list);
+fetch:
+		/* Fetch the next dst scatterlist entry */
+		if (dst_avail == 0) {
+			if (dst_sg_len == 0)
+				break;
+			dst_sg = sg_next(dst_sg);
+			if (dst_sg == NULL)
+				break;
+			dst_sg_len--;
+			dst_avail = sg_dma_len(dst_sg);
+		}
+		/* Fetch the next src scatterlist entry */
+		if (src_avail == 0) {
+			if (src_sg_len == 0)
+				break;
+			src_sg = sg_next(src_sg);
+			if (src_sg == NULL)
+				break;
+			src_sg_len--;
+			src_avail = sg_dma_len(src_sg);
+		}
+	}
+
+	zynqmp_dma_desc_config_eod(chan, desc);
+	first->async_tx.flags = flags;
+	return &first->async_tx;
+}
+
+/**
+ * zynqmp_dma_channel_set_config - Configure ZYNQMP DMA channel
+ * @dchan: DMA channel
+ * @cfg: ZYNQMP DMA device configuration pointer
+ *
+ * Return: '0' always
+ */
+int zynqmp_dma_channel_set_config(struct dma_chan *dchan,
+				  struct zynqmp_dma_config *cfg)
+{
+	struct zynqmp_dma_chan *chan = to_chan(dchan);
+
+	chan->config.ovrfetch = cfg->ovrfetch;
+	chan->config.has_sg = cfg->has_sg;
+	chan->config.ratectrl = cfg->ratectrl;
+	chan->config.src_issue = cfg->src_issue;
+	chan->config.src_burst_len = cfg->src_burst_len;
+	chan->config.dst_burst_len = cfg->dst_burst_len;
+
+	return 0;
+}
+EXPORT_SYMBOL(zynqmp_dma_channel_set_config);
+
+/**
+ * zynqmp_dma_chan_remove - Channel remove function
+ * @chan: ZynqMP DMA channel pointer
+ */
+static void zynqmp_dma_chan_remove(struct zynqmp_dma_chan *chan)
+{
+	if (!chan)
+		return;
+
+	devm_free_irq(chan->zdev->dev, chan->irq, chan);
+	tasklet_kill(&chan->tasklet);
+	list_del(&chan->common.device_node);
+	clk_disable_unprepare(chan->clk_apb);
+	clk_disable_unprepare(chan->clk_main);
+}
+
+/**
+ * zynqmp_dma_chan_probe - Per Channel Probing
+ * @zdev: Driver specific device structure
+ * @pdev: Pointer to the platform_device structure
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev,
+			   struct platform_device *pdev)
+{
+	struct zynqmp_dma_chan *chan;
+	struct resource *res;
+	struct device_node *node = pdev->dev.of_node;
+	int err;
+
+	chan = devm_kzalloc(zdev->dev, sizeof(*chan), GFP_KERNEL);
+	if (!chan)
+		return -ENOMEM;
+	chan->dev = zdev->dev;
+	chan->zdev = zdev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	chan->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(chan->regs))
+		return PTR_ERR(chan->regs);
+
+	chan->bus_width = ZYNQMP_DMA_BUS_WIDTH_64;
+	chan->config.src_issue = ZYNQMP_DMA_SRC_ISSUE_RST_VAL;
+	chan->config.dst_burst_len = ZYNQMP_DMA_AWLEN_RST_VAL;
+	chan->config.src_burst_len = ZYNQMP_DMA_ARLEN_RST_VAL;
+	err = of_property_read_u32(node, "xlnx,bus-width", &chan->bus_width);
+	if ((err < 0) && ((chan->bus_width != ZYNQMP_DMA_BUS_WIDTH_64) ||
+			  (chan->bus_width != ZYNQMP_DMA_BUS_WIDTH_128))) {
+		dev_err(zdev->dev, "invalid bus-width value");
+		return err;
+	}
+
+	chan->bus_width = chan->bus_width / 8;
+	chan->is_dmacoherent =  of_property_read_bool(node, "dma-coherent");
+
+	zdev->chan = chan;
+	tasklet_init(&chan->tasklet, zynqmp_dma_do_tasklet, (ulong)chan);
+	spin_lock_init(&chan->lock);
+	INIT_LIST_HEAD(&chan->active_list);
+	INIT_LIST_HEAD(&chan->pending_list);
+	INIT_LIST_HEAD(&chan->done_list);
+	INIT_LIST_HEAD(&chan->free_list);
+
+	dma_cookie_init(&chan->common);
+	chan->common.device = &zdev->common;
+	list_add_tail(&chan->common.device_node, &zdev->common.channels);
+
+	zynqmp_dma_init(chan);
+	chan->irq = platform_get_irq(pdev, 0);
+	if (chan->irq < 0)
+		return -ENXIO;
+	err = devm_request_irq(&pdev->dev, chan->irq, zynqmp_dma_irq_handler, 0,
+			       "zynqmp-dma", chan);
+	if (err)
+		return err;
+	chan->clk_main = devm_clk_get(&pdev->dev, "clk_main");
+	if (IS_ERR(chan->clk_main)) {
+		dev_err(&pdev->dev, "main clock not found.\n");
+		return PTR_ERR(chan->clk_main);
+	}
+
+	chan->clk_apb = devm_clk_get(&pdev->dev, "clk_apb");
+	if (IS_ERR(chan->clk_apb)) {
+		dev_err(&pdev->dev, "apb clock not found.\n");
+		return PTR_ERR(chan->clk_apb);
+	}
+
+	err = clk_prepare_enable(chan->clk_main);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to enable main clock.\n");
+		return err;
+	}
+
+	err = clk_prepare_enable(chan->clk_apb);
+	if (err) {
+		clk_disable_unprepare(chan->clk_main);
+		dev_err(&pdev->dev, "Unable to enable apb clock.\n");
+		return err;
+	}
+
+	chan->desc_size = sizeof(struct zynqmp_dma_desc_ll);
+	chan->idle = true;
+	return 0;
+}
+
+/**
+ * of_zynqmp_dma_xlate - Translation function
+ * @dma_spec: Pointer to DMA specifier as found in the device tree
+ * @ofdma: Pointer to DMA controller data
+ *
+ * Return: DMA channel pointer on success and NULL on error
+ */
+static struct dma_chan *of_zynqmp_dma_xlate(struct of_phandle_args *dma_spec,
+					    struct of_dma *ofdma)
+{
+	struct zynqmp_dma_device *zdev = ofdma->of_dma_data;
+
+	return dma_get_slave_channel(&zdev->chan->common);
+}
+
+/**
+ * zynqmp_dma_probe - Driver probe function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int zynqmp_dma_probe(struct platform_device *pdev)
+{
+	struct zynqmp_dma_device *zdev;
+	struct dma_device *p;
+	int ret;
+
+	zdev = devm_kzalloc(&pdev->dev, sizeof(*zdev), GFP_KERNEL);
+	if (!zdev)
+		return -ENOMEM;
+
+	zdev->dev = &pdev->dev;
+	INIT_LIST_HEAD(&zdev->common.channels);
+
+	dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
+	dma_cap_set(DMA_SG, zdev->common.cap_mask);
+	dma_cap_set(DMA_MEMCPY, zdev->common.cap_mask);
+
+	p = &zdev->common;
+	p->device_prep_dma_sg = zynqmp_dma_prep_sg;
+	p->device_prep_dma_memcpy = zynqmp_dma_prep_memcpy;
+	p->device_terminate_all = zynqmp_dma_device_terminate_all;
+	p->device_issue_pending = zynqmp_dma_issue_pending;
+	p->device_alloc_chan_resources = zynqmp_dma_alloc_chan_resources;
+	p->device_free_chan_resources = zynqmp_dma_free_chan_resources;
+	p->device_tx_status = zynqmp_dma_tx_status;
+	p->dev = &pdev->dev;
+
+	platform_set_drvdata(pdev, zdev);
+
+	ret = zynqmp_dma_chan_probe(zdev, pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Probing channel failed\n");
+		goto free_chan_resources;
+	}
+
+	p->dst_addr_widths = BIT(zdev->chan->bus_width);
+	p->src_addr_widths = BIT(zdev->chan->bus_width);
+
+	dma_async_device_register(&zdev->common);
+
+	ret = of_dma_controller_register(pdev->dev.of_node,
+					 of_zynqmp_dma_xlate, zdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to register DMA to DT\n");
+		dma_async_device_unregister(&zdev->common);
+		goto free_chan_resources;
+	}
+
+	dev_info(&pdev->dev, "ZynqMP DMA driver Probe success\n");
+
+	return 0;
+
+free_chan_resources:
+	zynqmp_dma_chan_remove(zdev->chan);
+	return ret;
+}
+
+/**
+ * zynqmp_dma_remove - Driver remove function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * Return: Always '0'
+ */
+static int zynqmp_dma_remove(struct platform_device *pdev)
+{
+	struct zynqmp_dma_device *zdev = platform_get_drvdata(pdev);
+
+	of_dma_controller_free(pdev->dev.of_node);
+	dma_async_device_unregister(&zdev->common);
+
+	zynqmp_dma_chan_remove(zdev->chan);
+
+	return 0;
+}
+
+static const struct of_device_id zynqmp_dma_of_match[] = {
+	{ .compatible = "xlnx,zynqmp-dma-1.0", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, zynqmp_dma_of_match);
+
+static struct platform_driver zynqmp_dma_driver = {
+	.driver = {
+		.name = "xilinx-zynqmp-dma",
+		.of_match_table = zynqmp_dma_of_match,
+	},
+	.probe = zynqmp_dma_probe,
+	.remove = zynqmp_dma_remove,
+};
+
+module_platform_driver(zynqmp_dma_driver);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx ZynqMP DMA driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/dma/xilinx_dma.h b/include/linux/dma/xilinx_dma.h
index 3ae3000..7d7312f 100644
--- a/include/linux/dma/xilinx_dma.h
+++ b/include/linux/dma/xilinx_dma.h
@@ -42,6 +42,24 @@ struct xilinx_vdma_config {
 };
 
 /**
+ * struct zynqmp_dma_config - ZYNQMP DMA Configuration structure
+ * @ovrfetch: Overfetch status
+ * @has_sg: Support scatter gather transfers
+ * @ratectrl: Rate control value
+ * @src_issue: Out standing transactions on source
+ * @src_burst_len: Source burst length
+ * @dst_burst_len: Dest burst length
+ */
+struct zynqmp_dma_config {
+	bool ovrfetch;
+	bool has_sg;
+	u32 ratectrl;
+	u32 src_issue;
+	u32 src_burst_len;
+	u32 dst_burst_len;
+};
+
+/**
  * enum xdma_ip_type: DMA IP type.
  *
  * XDMA_TYPE_AXIDMA: Axi dma ip.
@@ -57,5 +75,6 @@ enum xdma_ip_type {
 
 int xilinx_vdma_channel_set_config(struct dma_chan *dchan,
 					struct xilinx_vdma_config *cfg);
-
+int zynqmp_dma_channel_set_config(struct dma_chan *dchan,
+					struct zynqmp_dma_config *cfg);
 #endif
-- 
2.1.1



From dev at lynxeye.de  Fri May 13 00:25:31 2016
From: dev at lynxeye.de (Lucas Stach)
Date: Fri, 13 May 2016 09:25:31 +0200
Subject: [PATCH] ARM: tegra: beaver: allow SD card voltage to be changed
In-Reply-To: <1456779678-20173-1-git-send-email-dev@lynxeye.de>
References: <1456779678-20173-1-git-send-email-dev@lynxeye.de>
Message-ID: <1463124331.2459.0.camel@lynxeye.de>

Am Montag, den 29.02.2016, 22:01 +0100 schrieb Lucas Stach:
> This allows to switch the card signal voltage level to 1.8V,
> which is needed for any ultra high speed modes to work.
> 
> Signed-off-by: Lucas Stach <dev at lynxeye.de>
> ---
> This needs the SDMMC memcomp pad calibration patches I just
> sent out to be applied, otherwise the card voltage change will
> fail with a message in the kernel log and a fall back to
> high speed operation.

The patches this one depends on have been applied for some time now.
Please pick up this patch.

Thanks,
Lucas
> ---
> ?arch/arm/boot/dts/tegra30-beaver.dts | 3 ++-
> ?1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/tegra30-beaver.dts
> b/arch/arm/boot/dts/tegra30-beaver.dts
> index 1daed40..6b237f2 100644
> --- a/arch/arm/boot/dts/tegra30-beaver.dts
> +++ b/arch/arm/boot/dts/tegra30-beaver.dts
> @@ -1848,7 +1848,7 @@
> ?
> ?				ldo5_reg: ldo5 {
> ?					regulator-name =
> "vddio_sdmmc,avdd_vdac";
> -					regulator-min-microvolt =
> <3300000>;
> +					regulator-min-microvolt =
> <1800000>;
> ?					regulator-max-microvolt =
> <3300000>;
> ?					regulator-always-on;
> ?				};
> @@ -1919,6 +1919,7 @@
> ?
> ?	sdhci at 78000000 {
> ?		status = "okay";
> +		vqmmc-supply = <&ldo5_reg>;
> ?		cd-gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
> ?		wp-gpios = <&gpio TEGRA_GPIO(T, 3)
> GPIO_ACTIVE_HIGH>;
> ?		power-gpios = <&gpio TEGRA_GPIO(D, 7)
> GPIO_ACTIVE_HIGH>;


From geert+renesas at glider.be  Fri May 13 00:38:33 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:38:33 +0200
Subject: [PATCH] ARM: dts: r8a7790: Correct unit names for cpu nodes
Message-ID: <1463125113-28885-1-git-send-email-geert+renesas@glider.be>

Make the unit names for the cpu nodes match their reg properties.

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7790.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 83cf23cd26bb51e6..3b9e98be2f7b3122 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -92,7 +92,7 @@
 			next-level-cache = <&L2_CA15>;
 		};
 
-		cpu4: cpu at 4 {
+		cpu4: cpu at 100 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a7";
 			reg = <0x100>;
@@ -101,7 +101,7 @@
 			next-level-cache = <&L2_CA7>;
 		};
 
-		cpu5: cpu at 5 {
+		cpu5: cpu at 101 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a7";
 			reg = <0x101>;
@@ -110,7 +110,7 @@
 			next-level-cache = <&L2_CA7>;
 		};
 
-		cpu6: cpu at 6 {
+		cpu6: cpu at 102 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a7";
 			reg = <0x102>;
@@ -119,7 +119,7 @@
 			next-level-cache = <&L2_CA7>;
 		};
 
-		cpu7: cpu at 7 {
+		cpu7: cpu at 103 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a7";
 			reg = <0x103>;
-- 
1.9.1



From shawn.lin at rock-chips.com  Fri May 13 00:46:54 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Fri, 13 May 2016 15:46:54 +0800
Subject: [PATCH 2/2] clk: rockchip: fix the rk3399 sdmmc sample shift
In-Reply-To: <CAD=FV=WEAOwhDDBHBtuzSz35i0XRZw4LbFEnFCFYd-4NVH5d-g@mail.gmail.com>
References: <1463076197-15900-1-git-send-email-dianders@chromium.org>
 <1463076197-15900-2-git-send-email-dianders@chromium.org>
 <20160512231023.GA63308@google.com>
 <84673e7c-dd64-b2ca-5c7c-5c7f34d239d8@rock-chips.com>
 <CAD=FV=WEAOwhDDBHBtuzSz35i0XRZw4LbFEnFCFYd-4NVH5d-g@mail.gmail.com>
Message-ID: <0261c4b4-7398-fe15-5e26-f92bfbe79f3c@rock-chips.com>

? 2016/5/13 12:36, Doug Anderson ??:
> Shawn,
>
> On Thu, May 12, 2016 at 4:47 PM, Shawn Lin <shawn.lin at rock-chips.com> wrote:
>> ? 2016/5/13 7:10, Brian Norris ??:
>>>
>>> On Thu, May 12, 2016 at 11:03:17AM -0700, Doug Anderson wrote:
>>>>
>>>> Just like every other Rockhip device, the MMC "_sample" clocks should
>>>> have a shift of 0, not a shift of 1.  The rk3399 TRM agrees.  Presumably
>>>> these values were set to 0 because of a typo.
>>>
>>>
>>> I'll semi-disagree about the TRM: the TRM doesn't seem to agree with
>>> itself, so it sometimes agrees with you and sometimes doesn't :)
>>>
>>> On page 79 of the 2nd (?) book, it looks like {SDMMC,SDIO}_CON{0,}[2:1]
>>> are {drv,sample}_degree. But on page 208 of the 1st book, those are put
>>> at bits [1:0].
>>>
>>
>>
>> Please refer to Mobile Strorage Host Controller section for anything
>> about sdmmc/sdio. So shift should be 1.
>>
>> Sometime I also get bothered to address it. Anyway, I will always keep
>> a eye on it from now on.....
>
> I still in general have mistrust for TRM docs for things like this.
> Have you verified that this was an intentional change for rk3399, or
> could it be a  typo?  Typically SoCs don't change this type of stuff
> for no reason.
>

Typically it doesn't, but the reality is that {SDMMC,SDIO}_CON{0,}[2:1]
for drv/sample_degree both. Obviously they want to make drv stuff the
same layout as sampe stuff...

> This should be possible to verify in one of two ways.  If the TRM has
> a typo and things truly _do_ start at 0 instead of 1, then:
>
> 1. There will be roughly mirrors of valid ranges.
> 2. Things won't match up if we change tuning to use 180 course offsets
> and the rest fine offsets.
>
> It would be ideal if you could confirm with the chip guys, but if you

I have checked it before Xing upstreamed the code, but as your question 
on the TRM, I check it with the  chip guys again.

So the answer is that drv/sample stuff should refer to  Mobile Strorage
Host Controller section, and it will fit the future Socs from now on.


> can't I'll try to do more tests tomorrow.



>
>
>


-- 
Best Regards
Shawn Lin



From maxime.ripard at free-electrons.com  Fri May 13 00:48:23 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Fri, 13 May 2016 09:48:23 +0200
Subject: [PATCHv2] devicetree: sunxi: Add OLinuXino Lime2 eMMC to the
 Makefile
In-Reply-To: <1463047851-2039-1-git-send-email-oliver@schinagl.nl>
References: <1463047851-2039-1-git-send-email-oliver@schinagl.nl>
Message-ID: <20160513074823.GA3733@lukather>

Hi Olliver,

On Thu, May 12, 2016 at 12:10:51PM +0200, Olliver Schinagl wrote:
> commit 27dd9af6bc (ARM: dts: sunxi: Add a olinuxino-lime2-emmc added the new
> emmc equipped) lime2 but forgot its Makefile.

This is still not the right commit format, the commit title should be
around double quotes. checkpatch both reports an error for this and
tells you what the proper format is, so please remember to use it
before you're sending a patch.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160513/401ee930/attachment.sig>

From maxime.ripard at free-electrons.com  Fri May 13 00:50:00 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Fri, 13 May 2016 09:50:00 +0200
Subject: [PATCH 01/16] clk: fix critical clock locking
In-Reply-To: <20160509221146.GS3492@codeaurora.org>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-2-git-send-email-maxime.ripard@free-electrons.com>
 <20160509221146.GS3492@codeaurora.org>
Message-ID: <20160513075000.GB3733@lukather>

Hi Stephen,

On Mon, May 09, 2016 at 03:11:46PM -0700, Stephen Boyd wrote:
> On 05/08, Maxime Ripard wrote:
> > The critical clock handling in __clk_core_init isn't taking the enable lock
> > before calling clk_core_enable, which in turns triggers the warning in the
> > lockdep_assert_held call in that function when lockep is enabled.
> > 
> > Add the calls to clk_enable_lock/unlock to make sure it doesn't happen.
> > 
> > Fixes: 32b9b1096186 ("clk: Allow clocks to be marked as CRITICAL")
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> 
> Why is this patch hiding in this series?

Sorry, I discovered it while working on this, and somehow it slipped
in there. I'll resend it separately.

> 
> >  drivers/clk/clk.c | 7 +++++++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index ce39add5a258..16a38df3c688 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -2404,8 +2404,15 @@ static int __clk_core_init(struct clk_core *core)
> >  		core->ops->init(core->hw);
> >  
> >  	if (core->flags & CLK_IS_CRITICAL) {
> > +		unsigned long flags;
> > +
> > +		clk_prepare_lock();
> >  		clk_core_prepare(core);
> > +		clk_prepare_unlock();
> 
> It looks like we already hold the prepare lock at this point.

You're right. I thought I removed it, but obviously I didn't.

I'll send a v2.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160513/b4592f8e/attachment.sig>

From christoffer.dall at linaro.org  Fri May 13 00:51:32 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 13 May 2016 09:51:32 +0200
Subject: [PATCH v3 45/55] KVM: arm/arm64: vgic-new: Add userland access
 to VGIC dist registers
In-Reply-To: <5734D51D.3000105@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-46-git-send-email-andre.przywara@arm.com>
 <20160512184110.GK27623@cbox> <5734D51D.3000105@arm.com>
Message-ID: <20160513075132.GE27623@cbox>

On Thu, May 12, 2016 at 08:10:21PM +0100, Andre Przywara wrote:
> Hi,
> 
> On 12/05/16 19:41, Christoffer Dall wrote:
> > On Fri, May 06, 2016 at 11:45:58AM +0100, Andre Przywara wrote:
> >> Userland may want to save and restore the state of the in-kernel VGIC,
> >> so we provide the code which takes a userland request and translate
> >> that into calls to our MMIO framework.
> >>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >>  virt/kvm/arm/vgic/vgic-kvm-device.c | 50 ++++++++++++++++++++++++++++++++++++-
> >>  1 file changed, 49 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> >> index c952f6f..bb33af8 100644
> >> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> >> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> >> @@ -264,7 +264,55 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
> > 
> > come to think of it, this is GICv2 specific right?
> > 
> > why don't we call it vgic_v2_attr_regs_access then?
> > 
> > and should it really live in this file?
> 
> Mmmh, at the moment every userland access is v2 specific, but
> potentially this function should cover GICv3 as well, I think. We might
> need some adjustments once this will be implemented, but in general I
> don't see anything too v2 specific in here?


the defines being used below are v2 specific and it's going to stay that
way.  But ok, if you think it will be reworked to cater for both v2 and
v3, fine.

> 
> >>  				 struct kvm_device_attr *attr,
> >>  				 u32 *reg, bool is_write)
> >>  {
> >> -	return -ENXIO;
> >> +	gpa_t addr;
> >> +	int cpuid, ret, c;
> >> +	struct kvm_vcpu *vcpu, *tmp_vcpu;
> >> +
> >> +	cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
> >> +		 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
> >> +	vcpu = kvm_get_vcpu(dev->kvm, cpuid);
> >> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
> >> +
> >> +	mutex_lock(&dev->kvm->lock);
> >> +
> >> +	ret = vgic_init(dev->kvm);
> >> +	if (ret)
> >> +		goto out;
> >> +
> >> +	if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
> >> +		ret = -EINVAL;
> >> +		goto out;
> >> +	}
> >> +
> >> +	/*
> >> +	 * Ensure that no other VCPU is running by checking the vcpu->cpu
> >> +	 * field.  If no other VPCUs are running we can safely access the VGIC
> >> +	 * state, because even if another VPU is run after this point, that
> >> +	 * VCPU will not touch the vgic state, because it will block on
> >> +	 * getting the vgic->lock in kvm_vgic_sync_hwstate().
> >> +	 */
> > 
> > eh, I don't see us grabbing any vgic->lock (does that still exist?)
> > here?
> 
> Yeah, that scared me the other day too.
> In fact I think we cannot guarantee this requirement anymore with our
> existing locks - but maybe we can pause the guest explicitly as we do
> now for the clear-active handler?
> 

I think that should work, yes.

Even if you're doing a restore of the state before actually running your
VCPUs, the make all requests wouldn't do anything and your VCPUs would
block in the early part of the run loop.  They will call
first_run_init() though, but I can't easily make that out to be a
problem.

An alternative is to do something similar to kvm_vgic_create(), perhaps
factor out that logic, which grabs the mutexes of all vcpus.

-Christoffer


From christoffer.dall at linaro.org  Fri May 13 00:53:23 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 13 May 2016 09:53:23 +0200
Subject: [PATCH v3 47/55] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <5734D0F6.9090406@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-48-git-send-email-andre.przywara@arm.com>
 <20160512184740.GM27623@cbox> <5734D0F6.9090406@arm.com>
Message-ID: <20160513075323.GF27623@cbox>

On Thu, May 12, 2016 at 07:52:38PM +0100, Andre Przywara wrote:
> Hi,
> 
> On 12/05/16 19:47, Christoffer Dall wrote:
> > On Fri, May 06, 2016 at 11:46:00AM +0100, Andre Przywara wrote:
> >> Using the VMCR accessors we provide access to GIC CPU interface state
> >> to userland by wiring it up to the existing userland interface.
> >> [Marc: move and make VMCR accessors static, streamline MMIO handlers]
> > 
> > does this mean Marc did this and serves as credit or is it a lost
> > reminder?
> 
> It was meant as credit. I thought that is the usual annotation for this?
> 

I'm not sure if that's the usual way, I read it as a reminder, but it's
not too important.  Mostly wanting to make sure we're not forgetting
some todo item.

> >>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> >> ---
> >> Changelog v2 .. v3:
> >> - total rework, moving into vgic-mmio-v2.c
> >> - move vmcr accessor wrapper functions into this file
> >> - use the register description table for CPU i/f registers as well
> >> - add RAZ/WI handling for the active priority registers
> >> - streamline MMIO handler functions
> >>
> >>  virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
> >>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 104 ++++++++++++++++++++++++++++++++++++
> >>  virt/kvm/arm/vgic/vgic.h            |   2 +
> >>  3 files changed, 107 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> >> index bb33af8..2122ff2 100644
> >> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> >> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> >> @@ -300,7 +300,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
> >>  
> >>  	switch (attr->group) {
> >>  	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> >> -		ret = -EINVAL;
> >> +		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
> >>  		break;
> >>  	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> >>  		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> index c453e6f..0060539 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> @@ -206,6 +206,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
> >>  	}
> >>  }
> >>  
> >> +static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> >> +{
> >> +	if (kvm_vgic_global_state.type == VGIC_V2)
> >> +		vgic_v2_set_vmcr(vcpu, vmcr);
> >> +	else
> >> +		vgic_v3_set_vmcr(vcpu, vmcr);
> >> +}
> >> +
> >> +static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> >> +{
> >> +	if (kvm_vgic_global_state.type == VGIC_V2)
> >> +		vgic_v2_get_vmcr(vcpu, vmcr);
> >> +	else
> >> +		vgic_v3_get_vmcr(vcpu, vmcr);
> >> +}
> >> +
> >> +#define GICC_ARCH_VERSION_V2	0x2
> >> +
> >> +/* These are for userland accesses only, there is no guest-facing emulation. */
> >> +static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
> >> +					   gpa_t addr, unsigned int len)
> >> +{
> >> +	struct vgic_vmcr vmcr;
> >> +	u32 val;
> >> +
> >> +	vgic_get_vmcr(vcpu, &vmcr);
> >> +
> >> +	switch (addr & 0xff) {
> >> +	case GIC_CPU_CTRL:
> >> +		val = vmcr.ctlr;
> >> +		break;
> >> +	case GIC_CPU_PRIMASK:
> >> +		val = vmcr.pmr;
> >> +		break;
> >> +	case GIC_CPU_BINPOINT:
> >> +		val = vmcr.bpr;
> >> +		break;
> >> +	case GIC_CPU_ALIAS_BINPOINT:
> >> +		val = vmcr.abpr;
> >> +		break;
> >> +	case GIC_CPU_IDENT:
> >> +		val = ((PRODUCT_ID_KVM << 20) |
> >> +		       (GICC_ARCH_VERSION_V2 << 16) |
> >> +		       IMPLEMENTER_ARM);
> >> +		break;
> >> +	default:
> >> +		return 0;
> >> +	}
> >> +
> >> +	return extract_bytes(val, addr & 3, len);
> > 
> > I don't think we allow anything than a full 32-bit aligned accesses
> > from userspace - we shouldn't at least.
> 
> Indeed - I think userland was always 32-bit only. And since last night
> we even enforce this. So potentially there are more extract_bytes()
> calls that can go.
> 
Right.

-Christoffer


From geert+renesas at glider.be  Fri May 13 00:55:42 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:42 +0200
Subject: [PATCH 02/23] ARM: dts: r8a73a4: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-3-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /cache-controller at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /cache-controller at 1 has a unit name, but no reg property

Move the cache-controller nodes under the cpus node, and make their
unit names and reg properties match the MPIDR values.

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a73a4.dtsi | 34 ++++++++++++++++++----------------
 1 file changed, 18 insertions(+), 16 deletions(-)

diff --git a/arch/arm/boot/dts/r8a73a4.dtsi b/arch/arm/boot/dts/r8a73a4.dtsi
index 6954912a37537939..357d29d2c04b4c08 100644
--- a/arch/arm/boot/dts/r8a73a4.dtsi
+++ b/arch/arm/boot/dts/r8a73a4.dtsi
@@ -31,6 +31,24 @@
 			power-domains = <&pd_a2sl>;
 			next-level-cache = <&L2_CA15>;
 		};
+
+		L2_CA15: cache-controller at 0 {
+			compatible = "cache";
+			reg = <0>;
+			clocks = <&cpg_clocks R8A73A4_CLK_Z>;
+			power-domains = <&pd_a3sm>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		L2_CA7: cache-controller at 100 {
+			compatible = "cache";
+			reg = <100>;
+			clocks = <&cpg_clocks R8A73A4_CLK_Z2>;
+			power-domains = <&pd_a3km>;
+			cache-unified;
+			cache-level = <2>;
+		};
 	};
 
 	ptm {
@@ -46,22 +64,6 @@
 			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
 	};
 
-	L2_CA15: cache-controller at 0 {
-		compatible = "cache";
-		clocks = <&cpg_clocks R8A73A4_CLK_Z>;
-		power-domains = <&pd_a3sm>;
-		cache-unified;
-		cache-level = <2>;
-	};
-
-	L2_CA7: cache-controller at 1 {
-		compatible = "cache";
-		clocks = <&cpg_clocks R8A73A4_CLK_Z2>;
-		power-domains = <&pd_a3km>;
-		cache-unified;
-		cache-level = <2>;
-	};
-
 	dbsc1: memory-controller at e6790000 {
 		compatible = "renesas,dbsc-r8a73a4";
 		reg = <0 0xe6790000 0 0x10000>;
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:55:51 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:51 +0200
Subject: [PATCH 11/23] ARM: dts: armadillo800eva: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-12-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
Warning (unit_address_vs_reg): Node /regulator at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 2 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 3 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /i2c at 2 has a unit name, but no reg property

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7740-armadillo800eva.dts | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
index 2c82dab2b6f45f9c..b3f0ac4b99bd5a3d 100644
--- a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
+++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
@@ -28,12 +28,12 @@
 		stdout-path = &scifa1;
 	};
 
-	memory {
+	memory at 40000000 {
 		device_type = "memory";
 		reg = <0x40000000 0x20000000>;
 	};
 
-	reg_3p3v: regulator at 0 {
+	reg_3p3v: regulator-3p3v {
 		compatible = "regulator-fixed";
 		regulator-name = "fixed-3.3V";
 		regulator-min-microvolt = <3300000>;
@@ -42,7 +42,7 @@
 		regulator-boot-on;
 	};
 
-	vcc_sdhi0: regulator at 1 {
+	vcc_sdhi0: regulator-vcc-sdhi0 {
 		compatible = "regulator-fixed";
 
 		regulator-name = "SDHI0 Vcc";
@@ -53,7 +53,7 @@
 		enable-active-high;
 	};
 
-	vccq_sdhi0: regulator at 2 {
+	vccq_sdhi0: regulator-vccq-sdhi0 {
 		compatible = "regulator-gpio";
 
 		regulator-name = "SDHI0 VccQ";
@@ -69,7 +69,7 @@
 		enable-active-high;
 	};
 
-	reg_5p0v: regulator at 3 {
+	reg_5p0v: regulator-5p0v {
 		compatible = "regulator-fixed";
 		regulator-name = "fixed-5.0V";
 		regulator-min-microvolt = <5000000>;
@@ -127,7 +127,7 @@
 		};
 	};
 
-	i2c2: i2c at 2 {
+	i2c2: i2c2 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "i2c-gpio";
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:55:45 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:45 +0200
Subject: [PATCH 05/23] ARM: dts: r8a7790: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-6-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /cache-controller at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /cache-controller at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,dvc/dvc at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,dvc/dvc at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,mix/mix at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,mix/mix at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ctu/ctu at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ctu/ctu at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ctu/ctu at 2 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ctu/ctu at 3 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ctu/ctu at 4 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ctu/ctu at 5 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ctu/ctu at 6 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ctu/ctu at 7 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,src/src at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,src/src at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,src/src at 2 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,src/src at 3 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,src/src at 4 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,src/src at 5 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,src/src at 6 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,src/src at 7 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,src/src at 8 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,src/src at 9 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ssi/ssi at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ssi/ssi at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ssi/ssi at 2 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ssi/ssi at 3 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ssi/ssi at 4 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ssi/ssi at 5 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ssi/ssi at 6 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ssi/ssi at 7 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ssi/ssi at 8 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ssi/ssi at 9 has a unit name, but no reg property

Move the cache-controller nodes under the cpus node, and make their unit
names and reg properties match the MPIDR values.

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7790.dtsi | 94 +++++++++++++++++++++---------------------
 1 file changed, 48 insertions(+), 46 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 3b9e98be2f7b3122..66ab056c7f212929 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -127,6 +127,22 @@
 			power-domains = <&sysc R8A7790_PD_CA7_CPU3>;
 			next-level-cache = <&L2_CA7>;
 		};
+
+		L2_CA15: cache-controller at 0 {
+			compatible = "cache";
+			reg = <0>;
+			power-domains = <&sysc R8A7790_PD_CA15_SCU>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		L2_CA7: cache-controller at 100 {
+			compatible = "cache";
+			reg = <100>;
+			power-domains = <&sysc R8A7790_PD_CA7_SCU>;
+			cache-unified;
+			cache-level = <2>;
+		};
 	};
 
 	thermal-zones {
@@ -148,20 +164,6 @@
 		};
 	};
 
-	L2_CA15: cache-controller at 0 {
-		compatible = "cache";
-		power-domains = <&sysc R8A7790_PD_CA15_SCU>;
-		cache-unified;
-		cache-level = <2>;
-	};
-
-	L2_CA7: cache-controller at 1 {
-		compatible = "cache";
-		power-domains = <&sysc R8A7790_PD_CA7_SCU>;
-		cache-unified;
-		cache-level = <2>;
-	};
-
 	gic: interrupt-controller at f1001000 {
 		compatible = "arm,gic-400";
 		#interrupt-cells = <3>;
@@ -1702,79 +1704,79 @@
 		status = "disabled";
 
 		rcar_sound,dvc {
-			dvc0: dvc at 0 {
+			dvc0: dvc-0 {
 				dmas = <&audma0 0xbc>;
 				dma-names = "tx";
 			};
-			dvc1: dvc at 1 {
+			dvc1: dvc-1 {
 				dmas = <&audma0 0xbe>;
 				dma-names = "tx";
 			};
 		};
 
 		rcar_sound,mix {
-			mix0: mix at 0 { };
-			mix1: mix at 1 { };
+			mix0: mix-0 { };
+			mix1: mix-1 { };
 		};
 
 		rcar_sound,ctu {
-			ctu00: ctu at 0 { };
-			ctu01: ctu at 1 { };
-			ctu02: ctu at 2 { };
-			ctu03: ctu at 3 { };
-			ctu10: ctu at 4 { };
-			ctu11: ctu at 5 { };
-			ctu12: ctu at 6 { };
-			ctu13: ctu at 7 { };
+			ctu00: ctu-0 { };
+			ctu01: ctu-1 { };
+			ctu02: ctu-2 { };
+			ctu03: ctu-3 { };
+			ctu10: ctu-4 { };
+			ctu11: ctu-5 { };
+			ctu12: ctu-6 { };
+			ctu13: ctu-7 { };
 		};
 
 		rcar_sound,src {
-			src0: src at 0 {
+			src0: src-0 {
 				interrupts = <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x85>, <&audma1 0x9a>;
 				dma-names = "rx", "tx";
 			};
-			src1: src at 1 {
+			src1: src-1 {
 				interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x87>, <&audma1 0x9c>;
 				dma-names = "rx", "tx";
 			};
-			src2: src at 2 {
+			src2: src-2 {
 				interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x89>, <&audma1 0x9e>;
 				dma-names = "rx", "tx";
 			};
-			src3: src at 3 {
+			src3: src-3 {
 				interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x8b>, <&audma1 0xa0>;
 				dma-names = "rx", "tx";
 			};
-			src4: src at 4 {
+			src4: src-4 {
 				interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x8d>, <&audma1 0xb0>;
 				dma-names = "rx", "tx";
 			};
-			src5: src at 5 {
+			src5: src-5 {
 				interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x8f>, <&audma1 0xb2>;
 				dma-names = "rx", "tx";
 			};
-			src6: src at 6 {
+			src6: src-6 {
 				interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x91>, <&audma1 0xb4>;
 				dma-names = "rx", "tx";
 			};
-			src7: src at 7 {
+			src7: src-7 {
 				interrupts = <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x93>, <&audma1 0xb6>;
 				dma-names = "rx", "tx";
 			};
-			src8: src at 8 {
+			src8: src-8 {
 				interrupts = <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x95>, <&audma1 0xb8>;
 				dma-names = "rx", "tx";
 			};
-			src9: src at 9 {
+			src9: src-9 {
 				interrupts = <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x97>, <&audma1 0xba>;
 				dma-names = "rx", "tx";
@@ -1782,52 +1784,52 @@
 		};
 
 		rcar_sound,ssi {
-			ssi0: ssi at 0 {
+			ssi0: ssi-0 {
 				interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi1: ssi at 1 {
+			ssi1: ssi-1 {
 				 interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x03>, <&audma1 0x04>, <&audma0 0x49>, <&audma1 0x4a>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi2: ssi at 2 {
+			ssi2: ssi-2 {
 				interrupts = <GIC_SPI 372 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x05>, <&audma1 0x06>, <&audma0 0x63>, <&audma1 0x64>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi3: ssi at 3 {
+			ssi3: ssi-3 {
 				interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x07>, <&audma1 0x08>, <&audma0 0x6f>, <&audma1 0x70>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi4: ssi at 4 {
+			ssi4: ssi-4 {
 				interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x09>, <&audma1 0x0a>, <&audma0 0x71>, <&audma1 0x72>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi5: ssi at 5 {
+			ssi5: ssi-5 {
 				interrupts = <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x0b>, <&audma1 0x0c>, <&audma0 0x73>, <&audma1 0x74>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi6: ssi at 6 {
+			ssi6: ssi-6 {
 				interrupts = <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x0d>, <&audma1 0x0e>, <&audma0 0x75>, <&audma1 0x76>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi7: ssi at 7 {
+			ssi7: ssi-7 {
 				interrupts = <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x0f>, <&audma1 0x10>, <&audma0 0x79>, <&audma1 0x7a>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi8: ssi at 8 {
+			ssi8: ssi-8 {
 				interrupts = <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x11>, <&audma1 0x12>, <&audma0 0x7b>, <&audma1 0x7c>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi9: ssi at 9 {
+			ssi9: ssi-9 {
 				interrupts = <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x13>, <&audma1 0x14>, <&audma0 0x7d>, <&audma1 0x7e>;
 				dma-names = "rx", "tx", "rxu", "txu";
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:55:53 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:53 +0200
Subject: [PATCH 13/23] ARM: dts: genmai: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-14-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r7s72100-genmai.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/r7s72100-genmai.dts b/arch/arm/boot/dts/r7s72100-genmai.dts
index a9da7a89fc4ba65a..05ba9953b4d8d9ec 100644
--- a/arch/arm/boot/dts/r7s72100-genmai.dts
+++ b/arch/arm/boot/dts/r7s72100-genmai.dts
@@ -25,7 +25,7 @@
 		stdout-path = &scif2;
 	};
 
-	memory {
+	memory at 8000000 {
 		device_type = "memory";
 		reg = <0x08000000 0x08000000>;
 	};
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:56:03 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:56:03 +0200
Subject: [PATCH 23/23] arm64: dts: salvator-x: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-24-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /regulator at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 2 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 3 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 4 has a unit name, but no reg property

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
index 76bc94a528aab23c..b2437a90925065fe 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
+++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
@@ -62,7 +62,7 @@
 		clock-frequency = <24576000>;
 	};
 
-	vcc_sdhi0: regulator at 1 {
+	vcc_sdhi0: regulator-vcc-sdhi0 {
 		compatible = "regulator-fixed";
 
 		regulator-name = "SDHI0 Vcc";
@@ -73,7 +73,7 @@
 		enable-active-high;
 	};
 
-	vccq_sdhi0: regulator at 2 {
+	vccq_sdhi0: regulator-vccq-sdhi0 {
 		compatible = "regulator-gpio";
 
 		regulator-name = "SDHI0 VccQ";
@@ -86,7 +86,7 @@
 			  1800000 0>;
 	};
 
-	vcc_sdhi3: regulator at 3 {
+	vcc_sdhi3: regulator-vcc-sdhi3 {
 		compatible = "regulator-fixed";
 
 		regulator-name = "SDHI3 Vcc";
@@ -97,7 +97,7 @@
 		enable-active-high;
 	};
 
-	vccq_sdhi3: regulator at 4 {
+	vccq_sdhi3: regulator-vccq-sdhi3 {
 		compatible = "regulator-gpio";
 
 		regulator-name = "SDHI3 VccQ";
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:55:59 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:59 +0200
Subject: [PATCH 19/23] ARM: dts: marzen: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-20-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
Warning (unit_address_vs_reg): Node /fixedregulator at 0 has a unit name, but no reg property

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7779-marzen.dts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7779-marzen.dts b/arch/arm/boot/dts/r8a7779-marzen.dts
index b795da6f5503d224..d9f3dba882f01181 100644
--- a/arch/arm/boot/dts/r8a7779-marzen.dts
+++ b/arch/arm/boot/dts/r8a7779-marzen.dts
@@ -28,12 +28,12 @@
 		stdout-path = &scif2;
 	};
 
-	memory {
+	memory at 60000000 {
 		device_type = "memory";
 		reg = <0x60000000 0x40000000>;
 	};
 
-	fixedregulator3v3: fixedregulator at 0 {
+	fixedregulator3v3: fixedregulator3v3 {
 		compatible = "regulator-fixed";
 		regulator-name = "fixed-3.3V";
 		regulator-min-microvolt = <3300000>;
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:55:48 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:48 +0200
Subject: [PATCH 08/23] ARM: dts: r8a7794: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-9-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /cache-controller at 1 has a unit name, but no reg property

Move the cache-controller node under the cpus node, and make its unit
name and reg property match the MPIDR value.

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7794.dtsi | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi
index f334a3a715f27d12..cff1c5aa0ec48950 100644
--- a/arch/arm/boot/dts/r8a7794.dtsi
+++ b/arch/arm/boot/dts/r8a7794.dtsi
@@ -55,13 +55,14 @@
 			power-domains = <&sysc R8A7794_PD_CA7_CPU1>;
 			next-level-cache = <&L2_CA7>;
 		};
-	};
 
-	L2_CA7: cache-controller at 1 {
-		compatible = "cache";
-		power-domains = <&sysc R8A7794_PD_CA7_SCU>;
-		cache-unified;
-		cache-level = <2>;
+		L2_CA7: cache-controller at 0 {
+			compatible = "cache";
+			reg = <0>;
+			power-domains = <&sysc R8A7794_PD_CA7_SCU>;
+			cache-unified;
+			cache-level = <2>;
+		};
 	};
 
 	gic: interrupt-controller at f1001000 {
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:56:00 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:56:00 +0200
Subject: [PATCH 20/23] ARM: dts: porter: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-21-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /regulator at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 2 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 3 has a unit name, but no reg property

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7791-porter.dts | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7791-porter.dts b/arch/arm/boot/dts/r8a7791-porter.dts
index 6a1bb1a8209be296..e9151e946da8099b 100644
--- a/arch/arm/boot/dts/r8a7791-porter.dts
+++ b/arch/arm/boot/dts/r8a7791-porter.dts
@@ -46,7 +46,7 @@
 		reg = <2 0x00000000 0 0x40000000>;
 	};
 
-	vcc_sdhi0: regulator at 0 {
+	vcc_sdhi0: regulator-vcc-sdhi0 {
 		compatible = "regulator-fixed";
 
 		regulator-name = "SDHI0 Vcc";
@@ -55,7 +55,7 @@
 		regulator-always-on;
 	};
 
-	vccq_sdhi0: regulator at 1 {
+	vccq_sdhi0: regulator-vccq-sdhi0 {
 		compatible = "regulator-gpio";
 
 		regulator-name = "SDHI0 VccQ";
@@ -68,7 +68,7 @@
 			  1800000 0>;
 	};
 
-	vcc_sdhi2: regulator at 2 {
+	vcc_sdhi2: regulator-vcc-sdhi2 {
 		compatible = "regulator-fixed";
 
 		regulator-name = "SDHI2 Vcc";
@@ -77,7 +77,7 @@
 		regulator-always-on;
 	};
 
-	vccq_sdhi2: regulator at 3 {
+	vccq_sdhi2: regulator-vccq-sdhi2 {
 		compatible = "regulator-gpio";
 
 		regulator-name = "SDHI2 VccQ";
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:55:43 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:43 +0200
Subject: [PATCH 03/23] ARM: dts: r8a7740: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-4-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /cache-controller has a reg or ranges property, but no unit name

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7740.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi
index 39b2f88ad151e434..159e04eb1b9e55da 100644
--- a/arch/arm/boot/dts/r8a7740.dtsi
+++ b/arch/arm/boot/dts/r8a7740.dtsi
@@ -39,7 +39,7 @@
 		      <0xc2000000 0x1000>;
 	};
 
-	L2: cache-controller {
+	L2: cache-controller at f0100000 {
 		compatible = "arm,pl310-cache";
 		reg = <0xf0100000 0x1000>;
 		interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:55:40 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:40 +0200
Subject: [PATCH 00/23] ARM/arm64: dts: renesas: Fix W=1 dtc warnings
Message-ID: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>

	Hi Simon, Magnus, Morimoto-san, Rob,

This patch series fixes the new warnings related to Renesas arm32/arm64
DTSes that can be seen in -next using "make W=1 dtbs", courtesy of
commit b993734718c01064 ("scripts/dtc: Update to upstream version
53bf130b1cdd") in Rob herring's for-next branch. They're all of the
form:

    Warning (unit_address_vs_reg): Node /cache-controller at 0 has a unit name, but no reg property
    Warning (unit_address_vs_reg): Node /cache-controller has a reg or ranges property, but no unit name
    Warning (unit_address_vs_reg): Node /clocks at e0110000/iic0_sclkdiv has a reg or ranges property, but no unit name
    Warning (unit_address_vs_reg): Node /i2c at 2 has a unit name, but no reg property
    Warning (unit_address_vs_reg): Node /keyboard/button at 1 has a unit name, but no reg property
    Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
    Warning (unit_address_vs_reg): Node /pfc at e0140200/serial at e1030000 has a unit name, but no reg property
    Warning (unit_address_vs_reg): Node /regulator at 0 has a unit name, but no reg property
    Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ctu/ctu at 0 has a unit name, but no reg property
    Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,dvc/dvc at 0 has a unit name, but no reg property
    Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,mix/mix at 0 has a unit name, but no reg property
    Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,src/src at 0 has a unit name, but no reg property
    Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ssi/ssi at 0 has a unit name, but no reg property

Fixes:
  - For cache-controllers of Cortex A7, A15, A53, and A57, I moved them
    inside the /cpus node, and made their unit names and reg properties
    match the MPIDR values,
  - For clocks, I added the missing unit names,
  - For regulators, i2c-gpios buses, and sound nodes, I (more-or-less)
    replaced the '@' by a dash,
  - For buttons, I changed the node name to match the key events,
  - For pinctrl, I changed the node name to the device name.

Note that to get rid of all warnings for the /memory node,
arch/arm/boot/dts/skeleton.dtsi should be fixed, too.

Morimoto-san: If this is accepted, the examples in
Documentation/devicetree/bindings/sound/renesas,rsnd.txt should be
updated, too.

Boot-tested on r8a73a4/ape6evm, r8a7740/armadillo, r8a7791/koelsch,
sh73a0/kzm9g, r8a7795/salvator-x. I didn't test sound, but the kernel
log didn't show any failures.

The patches are against renesas-devel-20160509-v4.6-rc7.

Thanks for your comments!

Geert Uytterhoeven (23):
  ARM: dts: emev2: Fix W=1 dtc warnings
  ARM: dts: r8a73a4: Fix W=1 dtc warnings
  ARM: dts: r8a7740: Fix W=1 dtc warnings
  ARM: dts: r8a7778: Fix W=1 dtc warnings
  ARM: dts: r8a7790: Fix W=1 dtc warnings
  ARM: dts: r8a7791: Fix W=1 dtc warnings
  ARM: dts: r8a7793: Fix W=1 dtc warnings
  ARM: dts: r8a7794: Fix W=1 dtc warnings
  ARM: dts: sh73a0: Fix W=1 dtc warnings
  ARM: dts: ape6evm: Fix W=1 dtc warnings
  ARM: dts: armadillo800eva: Fix W=1 dtc warnings
  ARM: dts: bockw: Fix W=1 dtc warnings
  ARM: dts: genmai: Fix W=1 dtc warnings
  ARM: dts: gose: Fix W=1 dtc warnings
  ARM: dts: koelsch: Fix W=1 dtc warnings
  ARM: dts: kzm9d: Fix W=1 dtc warnings
  ARM: dts: kzm9g: Fix W=1 dtc warnings
  ARM: dts: lager: Fix W=1 dtc warnings
  ARM: dts: marzen: Fix W=1 dtc warnings
  ARM: dts: porter: Fix W=1 dtc warnings
  ARM: dts: silk: Fix W=1 dtc warnings
  arm64: dts: r8a7795: Fix W=1 dtc warnings
  arm64: dts: salvator-x: Fix W=1 dtc warnings

 arch/arm/boot/dts/emev2-kzm9d.dts                  | 16 ++--
 arch/arm/boot/dts/emev2.dtsi                       | 26 +++---
 arch/arm/boot/dts/r7s72100-genmai.dts              |  2 +-
 arch/arm/boot/dts/r8a73a4-ape6evm.dts              |  8 +-
 arch/arm/boot/dts/r8a73a4.dtsi                     | 34 ++++----
 arch/arm/boot/dts/r8a7740-armadillo800eva.dts      | 12 +--
 arch/arm/boot/dts/r8a7740.dtsi                     |  2 +-
 arch/arm/boot/dts/r8a7778-bockw.dts                |  4 +-
 arch/arm/boot/dts/r8a7778.dtsi                     | 28 +++----
 arch/arm/boot/dts/r8a7779-marzen.dts               |  4 +-
 arch/arm/boot/dts/r8a7790-lager.dts                | 20 ++---
 arch/arm/boot/dts/r8a7790.dtsi                     | 94 +++++++++++-----------
 arch/arm/boot/dts/r8a7791-koelsch.dts              | 12 +--
 arch/arm/boot/dts/r8a7791-porter.dts               |  8 +-
 arch/arm/boot/dts/r8a7791.dtsi                     | 79 +++++++++---------
 arch/arm/boot/dts/r8a7793-gose.dts                 | 12 +--
 arch/arm/boot/dts/r8a7793.dtsi                     | 59 +++++++-------
 arch/arm/boot/dts/r8a7794-silk.dts                 |  6 +-
 arch/arm/boot/dts/r8a7794.dtsi                     | 13 +--
 arch/arm/boot/dts/sh73a0-kzm9g.dts                 | 10 +--
 arch/arm/boot/dts/sh73a0.dtsi                      |  2 +-
 arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts |  8 +-
 arch/arm64/boot/dts/renesas/r8a7795.dtsi           | 70 ++++++++--------
 23 files changed, 269 insertions(+), 260 deletions(-)

-- 
1.9.1

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 geert+renesas at glider.be  Fri May 13 00:56:01 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:56:01 +0200
Subject: [PATCH 21/23] ARM: dts: silk: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-22-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /regulator at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 3 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 4 has a unit name, but no reg property

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7794-silk.dts | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts
index 56d98d5b21850cd2..b8c7a63c5ec456bc 100644
--- a/arch/arm/boot/dts/r8a7794-silk.dts
+++ b/arch/arm/boot/dts/r8a7794-silk.dts
@@ -32,7 +32,7 @@
 		reg = <0 0x40000000 0 0x40000000>;
 	};
 
-	d3_3v: regulator at 0 {
+	d3_3v: regulator-d3-3v {
 		compatible = "regulator-fixed";
 		regulator-name = "D3.3V";
 		regulator-min-microvolt = <3300000>;
@@ -41,7 +41,7 @@
 		regulator-always-on;
 	};
 
-	vcc_sdhi1: regulator at 3 {
+	vcc_sdhi1: regulator-vcc-sdhi1 {
 		compatible = "regulator-fixed";
 
 		regulator-name = "SDHI1 Vcc";
@@ -52,7 +52,7 @@
 		enable-active-high;
 	};
 
-	vccq_sdhi1: regulator at 4 {
+	vccq_sdhi1: regulator-vccq-sdhi1 {
 		compatible = "regulator-gpio";
 
 		regulator-name = "SDHI1 VccQ";
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:55:50 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:50 +0200
Subject: [PATCH 10/23] ARM: dts: ape6evm: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-11-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /regulator at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 2 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 3 has a unit name, but no reg property

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a73a4-ape6evm.dts | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts
index 93ace33e3e361af0..740e5d23f7c70843 100644
--- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts
+++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts
@@ -36,7 +36,7 @@
 		reg = <2 0x00000000 0 0x40000000>;
 	};
 
-	vcc_mmc0: regulator at 0 {
+	vcc_mmc0: regulator-mmc0 {
 		compatible = "regulator-fixed";
 		regulator-name = "MMC0 Vcc";
 		regulator-min-microvolt = <2800000>;
@@ -44,7 +44,7 @@
 		regulator-always-on;
 	};
 
-	vcc_sdhi0: regulator at 1 {
+	vcc_sdhi0: regulator-sdhi0 {
 		compatible = "regulator-fixed";
 
 		regulator-name = "SDHI0 Vcc";
@@ -56,7 +56,7 @@
 	};
 
 	/* Common 1.8V and 3.3V rails, used by several devices on APE6EVM */
-	ape6evm_fixed_1v8: regulator at 2 {
+	ape6evm_fixed_1v8: regulator-1v8 {
 		compatible = "regulator-fixed";
 		regulator-name = "1V8";
 		regulator-min-microvolt = <1800000>;
@@ -64,7 +64,7 @@
 		regulator-always-on;
 	};
 
-	ape6evm_fixed_3v3: regulator at 3 {
+	ape6evm_fixed_3v3: regulator-3v3 {
 		compatible = "regulator-fixed";
 		regulator-name = "3V3";
 		regulator-min-microvolt = <3300000>;
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:55:56 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:56 +0200
Subject: [PATCH 16/23] ARM: dts: kzm9d: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-17-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
Warning (unit_address_vs_reg): Node /pfc at e0140200/serial at e1030000 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /gpio_keys/button at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /gpio_keys/button at 2 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /gpio_keys/button at 3 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /gpio_keys/button at 4 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 1 has a unit name, but no reg property

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/emev2-kzm9d.dts | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/arm/boot/dts/emev2-kzm9d.dts b/arch/arm/boot/dts/emev2-kzm9d.dts
index a35b851e1cd7678a..9eb86f8f32c5afc0 100644
--- a/arch/arm/boot/dts/emev2-kzm9d.dts
+++ b/arch/arm/boot/dts/emev2-kzm9d.dts
@@ -18,7 +18,7 @@
 	model = "EMEV2 KZM9D Board";
 	compatible = "renesas,kzm9d", "renesas,emev2";
 
-	memory {
+	memory at 40000000 {
 		device_type = "memory";
 		reg = <0x40000000 0x8000000>;
 	};
@@ -33,28 +33,28 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		button at 1 {
+		one {
 			debounce_interval = <50>;
 			wakeup-source;
 			label = "DSW2-1";
 			linux,code = <KEY_1>;
 			gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
 		};
-		button at 2 {
+		two {
 			debounce_interval = <50>;
 			wakeup-source;
 			label = "DSW2-2";
 			linux,code = <KEY_2>;
 			gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
 		};
-		button at 3 {
+		three {
 			debounce_interval = <50>;
 			wakeup-source;
 			label = "DSW2-3";
 			linux,code = <KEY_3>;
 			gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
 		};
-		button at 4 {
+		four {
 			debounce_interval = <50>;
 			wakeup-source;
 			label = "DSW2-4";
@@ -63,7 +63,7 @@
 		};
 	};
 
-	reg_1p8v: regulator at 0 {
+	reg_1p8v: regulator-1p8v {
 		compatible = "regulator-fixed";
 		regulator-name = "fixed-1.8V";
 		regulator-min-microvolt = <1800000>;
@@ -72,7 +72,7 @@
 		regulator-boot-on;
 	};
 
-	reg_3p3v: regulator at 1 {
+	reg_3p3v: regulator-3p3v {
 		compatible = "regulator-fixed";
 		regulator-name = "fixed-3.3V";
 		regulator-min-microvolt = <3300000>;
@@ -104,7 +104,7 @@
 };
 
 &pfc {
-	uart1_pins: serial at e1030000 {
+	uart1_pins: uart1 {
 		groups = "uart1_ctrl", "uart1_data";
 		function = "uart1";
 	};
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:55:58 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:58 +0200
Subject: [PATCH 18/23] ARM: dts: lager: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-19-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /keyboard/button at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /keyboard/button at 2 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /keyboard/button at 3 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /keyboard/button at 4 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /fixedregulator at 0 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 2 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 3 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 4 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /i2c at 8 has a unit name, but no reg property

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7790-lager.dts | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index 749ba02b6a53a9de..c01e27868083147a 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -76,28 +76,28 @@
 	keyboard {
 		compatible = "gpio-keys";
 
-		button at 1 {
+		one {
 			linux,code = <KEY_1>;
 			label = "SW2-1";
 			wakeup-source;
 			debounce-interval = <20>;
 			gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
 		};
-		button at 2 {
+		two {
 			linux,code = <KEY_2>;
 			label = "SW2-2";
 			wakeup-source;
 			debounce-interval = <20>;
 			gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
 		};
-		button at 3 {
+		three {
 			linux,code = <KEY_3>;
 			label = "SW2-3";
 			wakeup-source;
 			debounce-interval = <20>;
 			gpios = <&gpio1 26 GPIO_ACTIVE_LOW>;
 		};
-		button at 4 {
+		four {
 			linux,code = <KEY_4>;
 			label = "SW2-4";
 			wakeup-source;
@@ -119,7 +119,7 @@
 		};
 	};
 
-	fixedregulator3v3: fixedregulator at 0 {
+	fixedregulator3v3: fixedregulator3v3 {
 		compatible = "regulator-fixed";
 		regulator-name = "fixed-3.3V";
 		regulator-min-microvolt = <3300000>;
@@ -128,7 +128,7 @@
 		regulator-always-on;
 	};
 
-	vcc_sdhi0: regulator at 1 {
+	vcc_sdhi0: regulator-vcc-sdhi0 {
 		compatible = "regulator-fixed";
 
 		regulator-name = "SDHI0 Vcc";
@@ -139,7 +139,7 @@
 		enable-active-high;
 	};
 
-	vccq_sdhi0: regulator at 2 {
+	vccq_sdhi0: regulator-vccq-sdhi0 {
 		compatible = "regulator-gpio";
 
 		regulator-name = "SDHI0 VccQ";
@@ -152,7 +152,7 @@
 			  1800000 0>;
 	};
 
-	vcc_sdhi2: regulator at 3 {
+	vcc_sdhi2: regulator-vcc-sdhi2 {
 		compatible = "regulator-fixed";
 
 		regulator-name = "SDHI2 Vcc";
@@ -163,7 +163,7 @@
 		enable-active-high;
 	};
 
-	vccq_sdhi2: regulator at 4 {
+	vccq_sdhi2: regulator-vccq-sdhi2 {
 		compatible = "regulator-gpio";
 
 		regulator-name = "SDHI2 VccQ";
@@ -263,7 +263,7 @@
 	 * instantiate the slave device at runtime according to the documentation.
 	 * You can then communicate with the slave via IIC3.
 	 */
-	i2cexio: i2c at 8 {
+	i2cexio: i2c-8 {
 		compatible = "i2c-demux-pinctrl";
 		i2c-parent = <&iic0>, <&i2c0>;
 		i2c-bus-name = "i2c-exio";
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:55:44 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:44 +0200
Subject: [PATCH 04/23] ARM: dts: r8a7778: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-5-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,src/src at 3 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,src/src at 4 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,src/src at 5 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,src/src at 6 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,src/src at 7 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,src/src at 8 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,src/src at 9 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,ssi/ssi at 3 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,ssi/ssi at 4 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,ssi/ssi at 5 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,ssi/ssi at 6 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,ssi/ssi at 7 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,ssi/ssi at 8 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /sound at ffd90000/rcar_sound,ssi/ssi at 9 has a unit name, but no reg property

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7778.dtsi | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi
index fe787b4751d2cf05..e571d66ea0fe1721 100644
--- a/arch/arm/boot/dts/r8a7778.dtsi
+++ b/arch/arm/boot/dts/r8a7778.dtsi
@@ -276,23 +276,23 @@
 		status = "disabled";
 
 		rcar_sound,src {
-			src3: src at 3 { };
-			src4: src at 4 { };
-			src5: src at 5 { };
-			src6: src at 6 { };
-			src7: src at 7 { };
-			src8: src at 8 { };
-			src9: src at 9 { };
+			src3: src-3 { };
+			src4: src-4 { };
+			src5: src-5 { };
+			src6: src-6 { };
+			src7: src-7 { };
+			src8: src-8 { };
+			src9: src-9 { };
 		};
 
 		rcar_sound,ssi {
-			ssi3: ssi at 3 { interrupts = <GIC_SPI 0x85 IRQ_TYPE_LEVEL_HIGH>; };
-			ssi4: ssi at 4 { interrupts = <GIC_SPI 0x85 IRQ_TYPE_LEVEL_HIGH>; };
-			ssi5: ssi at 5 { interrupts = <GIC_SPI 0x86 IRQ_TYPE_LEVEL_HIGH>; };
-			ssi6: ssi at 6 { interrupts = <GIC_SPI 0x86 IRQ_TYPE_LEVEL_HIGH>; };
-			ssi7: ssi at 7 { interrupts = <GIC_SPI 0x86 IRQ_TYPE_LEVEL_HIGH>; };
-			ssi8: ssi at 8 { interrupts = <GIC_SPI 0x86 IRQ_TYPE_LEVEL_HIGH>; };
-			ssi9: ssi at 9 { interrupts = <GIC_SPI 0x86 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi3: ssi-3 { interrupts = <GIC_SPI 0x85 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi4: ssi-4 { interrupts = <GIC_SPI 0x85 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi5: ssi-5 { interrupts = <GIC_SPI 0x86 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi6: ssi-6 { interrupts = <GIC_SPI 0x86 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi7: ssi-7 { interrupts = <GIC_SPI 0x86 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi8: ssi-8 { interrupts = <GIC_SPI 0x86 IRQ_TYPE_LEVEL_HIGH>; };
+			ssi9: ssi-9 { interrupts = <GIC_SPI 0x86 IRQ_TYPE_LEVEL_HIGH>; };
 		};
 	};
 
-- 
1.9.1



From geert+renesas at glider.be  Fri May 13 00:55:52 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 13 May 2016 09:55:52 +0200
Subject: [PATCH 12/23] ARM: dts: bockw: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463126163-29423-13-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
Warning (unit_address_vs_reg): Node /fixedregulator at 0 has a unit name, but no reg property

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/r8a7778-bockw.dts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7778-bockw.dts b/arch/arm/boot/dts/r8a7778-bockw.dts
index 982a237ea6222a59..5c1891ab7103b102 100644
--- a/arch/arm/boot/dts/r8a7778-bockw.dts
+++ b/arch/arm/boot/dts/r8a7778-bockw.dts
@@ -32,12 +32,12 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory at 60000000 {
 		device_type = "memory";
 		reg = <0x60000000 0x10000000>;
 	};
 
-	fixedregulator3v3: fixedregulator at 0 {
+	fixedregulator3v3: fixedregulator3v3 {
 		compatible = "regulator-fixed";
 		regulator-name = "fixed-3.3V";
 		regulator-min-microvolt = <3300000>;
-- 
1.9.1



From marc.zyngier at arm.com  Fri May 13 01:02:24 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Fri, 13 May 2016 09:02:24 +0100
Subject: [PATCH v2] KVM: arm/arm64: vgic-new: Switch to
 firmware-independent probing
In-Reply-To: <20160512190216.GO27623@cbox>
References: <1462869983-5410-1-git-send-email-marc.zyngier@arm.com>
 <20160512190216.GO27623@cbox>
Message-ID: <57358A10.8070404@arm.com>

On 12/05/16 20:02, Christoffer Dall wrote:
> On Tue, May 10, 2016 at 09:46:23AM +0100, Marc Zyngier wrote:
>> As we did for the legacy code, switch the new VGIC implementation
>> the firmware-independent probing, giving us ACPI support for free.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> 
> So just remembered you wrote this after sending my comments to patch 48.
> 
> Are we planning to squash this into the series so I can review in
> completeness/with context, or?

This should indeed be squashed in the existing series, no need for an
intermediate step.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From henryc.chen at mediatek.com  Fri May 13 01:04:20 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Fri, 13 May 2016 16:04:20 +0800
Subject: [PATCH RESEND 2/2] regulator: mt6397: Add buck change mode
 regulator interface for mt6397
In-Reply-To: <20160511145046.GI6261@sirena.org.uk>
References: <1462959090-2877-1-git-send-email-henryc.chen@mediatek.com>
 <1462959090-2877-3-git-send-email-henryc.chen@mediatek.com>
 <20160511145046.GI6261@sirena.org.uk>
Message-ID: <1463126660.2821.9.camel@mtksdaap41>

Hi Mark,

On Wed, 2016-05-11 at 15:50 +0100, Mark Brown wrote:
> On Wed, May 11, 2016 at 05:31:30PM +0800, Henry Chen wrote:
> 
> > +The possible values for "regulator-supported-modes" are:
> > +	0: PWM mode, mapping to regulator fast mode, allow the
> > +	converter to remain in the PWM mode regardless of the load current, so
> > +	that the noise spectrum of the converter can be minimized for certain
> > +	highly-noise-sensitive handset applications.
> > +	1: Auto mode, mapping to regulator normal mode, mode switch by current
> > +	loading. At light load currents, the converter automatically enters
> > +	PFM mode to save power and improve light load efficiency. At heavy
> > +	load currents, the converter automatically enters PWM mode to minimiz
> > +	the noise spectrum of the converter.
> 
> The details of how this maps onto Linux shouldn't be in the bindings.
> 
> > +				regulator-allow-change-mode;
> > +				regulator-supported-modes = <0 1>;
> 
> These are problematic too as covered in my other mail. 
> 
> > -static struct regulator_ops mt6397_volt_range_ops = {
> > +static const struct regulator_ops mt6397_volt_range_ops = {
> 
> The constification is fine but an unrelated change.  Otherwise this
> looks fine from a code point of view, let's get that merged separately.

Okay, although we didn't have conclusion and solution for regulator
operation mode, as you said that we can get some patch merged
separately, so I will resend the patch which clean up comments from
you and Daniel.



From oliver at schinagl.nl  Fri May 13 01:07:07 2016
From: oliver at schinagl.nl (Olliver Schinagl)
Date: Fri, 13 May 2016 10:07:07 +0200
Subject: [PATCHv2] devicetree: sunxi: Add OLinuXino Lime2 eMMC to the
 Makefile
In-Reply-To: <20160513074823.GA3733@lukather>
References: <1463047851-2039-1-git-send-email-oliver@schinagl.nl>
 <20160513074823.GA3733@lukather>
Message-ID: <57358B2B.1010703@schinagl.nl>

and now i'm embarrassed and ashamed. Teaches me not to rush things, 
right? i'll correct it and take some time to do it right. sorry maxime!

On 13-05-16 09:48, Maxime Ripard wrote:
> Hi Olliver,
>
> On Thu, May 12, 2016 at 12:10:51PM +0200, Olliver Schinagl wrote:
>> commit 27dd9af6bc (ARM: dts: sunxi: Add a olinuxino-lime2-emmc added the new
>> emmc equipped) lime2 but forgot its Makefile.
> This is still not the right commit format, the commit title should be
> around double quotes. checkpatch both reports an error for this and
> tells you what the proper format is, so please remember to use it
> before you're sending a patch.
>
> Thanks!
> Maxime
>



From bamvor.zhangjian at huawei.com  Fri May 13 01:11:23 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Fri, 13 May 2016 16:11:23 +0800
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160512152805.GJ11226@e104818-lin.cambridge.arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
 <20160512134431.GB30205@yury-N73SV>
 <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
 <20160512142457.GC30205@yury-N73SV>
 <20160512152805.GJ11226@e104818-lin.cambridge.arm.com>
Message-ID: <57358C2B.1010106@huawei.com>

Hi,

On 2016/5/12 23:28, Catalin Marinas wrote:
> On Thu, May 12, 2016 at 05:24:57PM +0300, Yury Norov wrote:
>> On Thu, May 12, 2016 at 03:07:35PM +0100, Catalin Marinas wrote:
>>> On Thu, May 12, 2016 at 04:44:31PM +0300, Yury Norov wrote:
>>>> On Thu, May 12, 2016 at 02:35:34PM +0100, Catalin Marinas wrote:
>>>>> On Thu, May 12, 2016 at 03:20:00AM +0300, Yury Norov wrote:
>>>>>> I debugged preadv02 and pwritev02 failures and found very weird bug.
>>>>>> Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
>>>>>> of vector, and kernel reports successful read/write.
>>>>>>
>>>>>> There are 2 problems:
>>>>>> 1. How kernel allows such address to be passed to fs subsystem;
>>>>>> 2. How fs successes to read/write at non-mapped, and in fact non-user
>>>>>> address.
>>>>>>
>>>>>> I don't know the answer on 2'nd question, and it might be something
>>>>>> generic. But I investigated first problem.
>>>>>>
>>>>>> The problem is that compat_rw_copy_check_uvector() uses access_ok() to
>>>>>> validate user address, and on arm64 it ends up with checking buffer
>>>>>> end against current_thread_info()->addr_limit.
>>>>>>
>>>>>> current_thread_info()->addr_limit for ilp32, and most probably for
>>>>>> aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
>>>>>> It happens because on thread creation we call flush_old_exec() to set
>>>>>> addr_limit, and completely ignore compat mode there.
>>>
>>> [...]
>>>
>>>>>> --- a/arch/arm64/kernel/binfmt_elf32.c
>>>>>> +++ b/arch/arm64/kernel/binfmt_elf32.c
>>>>>> @@ -12,6 +12,7 @@
>>>>>>   do {						\
>>>>>>   	clear_thread_flag(TIF_32BIT_AARCH64);	\
>>>>>>   	set_thread_flag(TIF_32BIT);		\
>>>>>> +	set_fs(TASK_SIZE_32);			\
>>>>>>   } while (0)
>>>>>>
>>>>>>   #define COMPAT_ARCH_DLINFO
>>>>>> diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
>>>>>> index a934fd4..a8599c6 100644
>>>>>> --- a/arch/arm64/kernel/binfmt_ilp32.c
>>>>>> +++ b/arch/arm64/kernel/binfmt_ilp32.c
>>>>>> @@ -59,6 +59,7 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
>>>>>>   do {									\
>>>>>>   	set_thread_flag(TIF_32BIT_AARCH64);				\
>>>>>>   	clear_thread_flag(TIF_32BIT);					\
>>>>>> +	set_fs(TASK_SIZE_32);						\
>>>>>>   } while (0)
>>>>>
>>>>> I don't think we need these two. AFAICT, flush_old_exec() takes care of
>>>>> setting the USER_DS for the new thread.
>>>>
>>>> That's true, but USER_DS depends on personality which is not set yet
>>>> for new thread, as I wrote above. In fact, I tried correct USER_DS
>>>> only, and it doesn't work
>>>
>>> Ah, it looks like load_elf_binary() sets the personality after
>>> flush_old_exec(). Looking at powerpc and x86, they set USER_DS to the
>>> maximum 64-bit task value, so they should have a similar issue with
>>> native 32-bit vs compat behaviour.
>>
>> Hmmm. If so, it means we'd introduce generic fix. It would be removing
>> set_fs() from flush_old_exec() and appending it to load_elf_binary()
>> after SET_PERSONALITY(). But I think it should be agreed with other
>> arches developers.
>
> The set_fs() in flush_old_exec() is probably fine, it may be meant to
> re-set the USER_DS for the old thread.
>
> It appears that at least powerpc and x86 don't have different USER_DS
> setting for native and compat, so moving the set_fs() call further down
> would not make any difference for them, nor will it fix the preadv02 LTP
> test (if it fails for them, I haven't checked).
>
>> I've sent standalone patch for aarch64 (you in CC) so let's move
>> discussion there.
>
> I've seen the patch but we would lose some discussion history here. I
> think we should continue this thread and just summarise the conclusion
> in reply to the other patch. This thread is also available on
> linux-arch, in case other architecture maintainers follow it.
>
>>> So what exactly is LTP complaining about? Is different error (like
>>> EFAULT vs EINVAL) or not getting an error at all.
>>
>> It should be EINVAL, but it succeed. The other problem is that
>> following fs routines does not complain on wrong address.
>
> I see. The test asks the kernel to write a single byte (out of maximum
> 64) to the user address 0xffffffff.
What address We should set for this limitation, TASK_SIZE or STACK_TOP?
It is same for 64bit application. But STACK_TOP(0xffff0000) is below
TASK_SIZE in 32bit application. The address above STACK_TOP is preserved
for 32bit application.

Regards

Bamvor

 > In the absence of the access_ok()
> check, this operation succeeds. If the preadv syscall gets 2 bytes as
> the count, then it would fail with EFAULT.
>
> While it's not really a bug, I agree that for matching the native 32-bit
> behavior (basically for other syscalls like those involving vfs_read()),
> the simplest fix would be to have a dynamic USER_DS.



>



From vladimir.murzin at arm.com  Fri May 13 01:35:18 2016
From: vladimir.murzin at arm.com (Vladimir Murzin)
Date: Fri, 13 May 2016 09:35:18 +0100
Subject: [PATCH] serial: Make SERIAL_MPS2_UART depend on ARCH_MPS2
In-Reply-To: <1462906570-27684-1-git-send-email-geert+renesas@glider.be>
References: <1462906570-27684-1-git-send-email-geert+renesas@glider.be>
Message-ID: <573591C6.1070106@arm.com>

On 10/05/16 19:56, Geert Uytterhoeven wrote:
> Enabling support for the UART on the ARM MPS2 platform only make sense
> when compiling for the ARM MPS2 platform, unless compile-testing.

What you said is true, but looking around (see SERIAL_STM32 for example)
I'm wondering what makes MPS2 so special flake?

I was under impression that architecture/board specific guard must have
only if we have something like

#include <asm/xyz.h>

or

#include <mach/xyz.h>

which is not a case for device-tree driven MPS2 uart.

I have no idea what is practice for such things, so would be grateful to
get it known.

Cheers
Vladimir

> 
> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
> ---
>  drivers/tty/serial/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index b84810aa8621d8b1..3def7478ca44f573 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -1457,7 +1457,7 @@ config SERIAL_MPS2_UART_CONSOLE
>  
>  config SERIAL_MPS2_UART
>  	bool "MPS2 UART port"
> -	depends on ARM || COMPILE_TEST
> +	depends on ARCH_MPS2 || COMPILE_TEST
>  	select SERIAL_CORE
>  	help
>  	  This driver support the UART ports on ARM MPS2.
> 



From geert at linux-m68k.org  Fri May 13 01:57:56 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Fri, 13 May 2016 10:57:56 +0200
Subject: [PATCH] serial: Make SERIAL_MPS2_UART depend on ARCH_MPS2
In-Reply-To: <573591C6.1070106@arm.com>
References: <1462906570-27684-1-git-send-email-geert+renesas@glider.be>
 <573591C6.1070106@arm.com>
Message-ID: <CAMuHMdUCAyrK5hC+erph+6km8LL__3vd7Vr6SMo1N3FLN3zxHw@mail.gmail.com>

Hi Vladimir,

On Fri, May 13, 2016 at 10:35 AM, Vladimir Murzin
<vladimir.murzin at arm.com> wrote:
> On 10/05/16 19:56, Geert Uytterhoeven wrote:
>> Enabling support for the UART on the ARM MPS2 platform only make sense
>> when compiling for the ARM MPS2 platform, unless compile-testing.
>
> What you said is true, but looking around (see SERIAL_STM32 for example)
> I'm wondering what makes MPS2 so special flake?

Nothing. SERIAL_STM32 should be fixed, too.
I only fixed SERIAL_MPS2_UART, as it was a newly-introduced symbol.

> I was under impression that architecture/board specific guard must have
> only if we have something like
>
> #include <asm/xyz.h>
>
> or
>
> #include <mach/xyz.h>
>
> which is not a case for device-tree driven MPS2 uart.
>
> I have no idea what is practice for such things, so would be grateful to
> get it known.

That's why there's an "|| COMPILE_TEST" in the dependency.

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 marcel.ziswiler at toradex.com  Fri May 13 02:06:38 2016
From: marcel.ziswiler at toradex.com (Marcel Ziswiler)
Date: Fri, 13 May 2016 09:06:38 +0000
Subject: [PATCH 3/3] mmc: core: support hs speed mode if hs200 mode fails
In-Reply-To: <1461171092-30631-3-git-send-email-aisheng.dong@nxp.com>
References: <1461171092-30631-1-git-send-email-aisheng.dong@nxp.com>
 <1461171092-30631-3-git-send-email-aisheng.dong@nxp.com>
Message-ID: <1463130397.3151.13.camel@toradex.com>

On Thu, 2016-04-21 at 00:51 +0800, Dong Aisheng wrote:
> Currently if mmc_select_hs200 mode switch fails, MMC core
> can only use legacy mode to run the card.
> Let's retry HS speed mode if HS200 fails.
> 
> Before the fix:
> mmc0: mmc_select_hs200 failed, error -74
> : switch to mmc0 failed
> mmc0: new MMC card at address 0001
> mmcblk0: mmc0:0001 Q2J55L 7.12 GiB
> mmcblk0boot0: mmc0:0001 Q2J55L partition 1 2.00 MiB
> mmcblk0boot1: mmc0:0001 Q2J55L partition 2 2.00 MiB
> mmcblk0rpmb: mmc0:0001 Q2J55L partition 3 4.00 MiB
> ?mmcblk0: p1 p2
> 
> After the fix:
> mmc0: mmc_select_hs200 failed, error -74
> mmc0: new DDR MMC card at address 0001
> mmcblk0: mmc0:0001 Q2J55L 7.12 GiB
> mmcblk0boot0: mmc0:0001 Q2J55L partition 1 2.00 MiB
> mmcblk0boot1: mmc0:0001 Q2J55L partition 2 2.00 MiB
> mmcblk0rpmb: mmc0:0001 Q2J55L partition 3 4.00 MiB
> ?mmcblk0: p1 p2
> 
> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
> ---
> ?drivers/mmc/core/mmc.c | 3 ++-
> ?1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 55c8201..b573dc7 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -1315,7 +1315,8 @@ static int mmc_select_timing(struct mmc_card
> *card)
> ?
> ?	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
> ?		err = mmc_select_hs200(card);
> -	else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
> +
> +	if (err && (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS))
> ?		err = mmc_select_hs(card);
> ?
> ?	if (err && err != -EBADMSG)


This seems to break on TK1 where eMMC so far was detected as an 8-bit
high speed MMC card. With this patch it reverts to detecting a 1-bit only
MMC card! This has been observed both on a NVIDIA's Jetson TK1 as well as
our new Toradex Apalis TK1?(CC Tegra mailing list,?Jon Hunter and?Lucas
Stach as well). So far T30 is not affected as there we are still doing
full HS200 with whatever issues that has.

Before:
[????3.726894] sdhci: Secure Digital Host Controller Interface driver
[????3.733081] sdhci: Copyright(c) Pierre Ossman
[????3.737462] sdhci-pltfm: SDHCI platform and OF driver helper
[????3.753411] mmc0: Unknown controller version (3). You may experience
 problems.
[????3.768345] mmc0: Invalid maximum block size, assuming 512 bytes
[????3.814896] mmc0: SDHCI controller on 700b0600.sdhci [700b0600.sdhci]
 using ADMA 64-bit
[????3.892088] mmc0: new high speed MMC card at address 0001
[????3.899194] mmcblk0: mmc0:0001 SEM16G 14.7 GiB
[????3.904217] mmcblk0boot0: mmc0:0001 SEM16G partition 1 4.00 MiB
[????3.910645] mmcblk0boot1: mmc0:0001 SEM16G partition 2 4.00 MiB
[????3.917119] mmcblk0rpmb: mmc0:0001 SEM16G partition 3 4.00 MiB
[????3.926006]??mmcblk0: p1 p2 p3 p4 p5 p6 p7 p8 p9
root at jetson_tk1:~# cat /sys/kernel/debug/mmc0/ios?
clock:??????????52000000 Hz
actual clock:???51000000 Hz
vdd:????????????21 (3.3 ~ 3.4 V)
bus mode:???????2 (push-pull)
chip select:????0 (don't care)
power mode:?????2 (on)
bus width:??????3 (8 bits)
timing spec:????1 (mmc high-speed)
signal voltage: 0 (3.30 V)
driver type:????0 (driver type B)

After:
[????3.899918] mmc0: new MMC card at address 0001
root at jetson_tk1:~# cat /sys/kernel/debug/mmc0/ios?
clock:??????????25000000 Hz
actual clock:???24727273 Hz
vdd:????????????21 (3.3 ~ 3.4 V)
bus mode:???????2 (push-pull)
chip select:????0 (don't care)
power mode:?????2 (on)
bus width:??????0 (1 bits)
timing spec:????0 (legacy)
signal voltage: 0 (3.30 V)
driver type:????0 (driver type B)


From linux at armlinux.org.uk  Fri May 13 02:15:07 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Fri, 13 May 2016 10:15:07 +0100
Subject: [PATCH] sched/core: don't include asm/mmu_context from drivers
In-Reply-To: <CALCETrV_wgy0vpWiLYRJn1Q41C6adKKgbEOFthoAXiG601JPYQ@mail.gmail.com>
References: <1461919995-21001-1-git-send-email-arnd@arndb.de>
 <20160429094218.61b26849@gandalf.local.home>
 <CALCETrV_wgy0vpWiLYRJn1Q41C6adKKgbEOFthoAXiG601JPYQ@mail.gmail.com>
Message-ID: <20160513091506.GS19428@n2100.arm.linux.org.uk>

On Thu, May 12, 2016 at 10:46:56PM -0700, Andy Lutomirski wrote:
> On Fri, Apr 29, 2016 at 6:42 AM, Steven Rostedt <rostedt at goodmis.org> wrote:
> > On Fri, 29 Apr 2016 10:52:32 +0200
> > Arnd Bergmann <arnd at arndb.de> wrote:
> >
> >> This reverts the earlier fix attempt and works around the problem
> >> by including both linux/mmu_context.h and asm/mmu_context.h from
> >> kernel/sched/core.c. This is not a good solution but seems less
> >> hacky than the alternatives.
> >
> > What about simply not compiling finish_arch_post_lock_switch() when
> > building modules?
> >
> > (untested, not compiled or anything)
> >
> > Signed-off-by: Steven Rostedt <rostedt at goodmis.org>
> > ---
> > diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h
> > index fa5b42d44985..3f22d1b6bac8 100644
> > --- a/arch/arm/include/asm/mmu_context.h
> > +++ b/arch/arm/include/asm/mmu_context.h
> > @@ -66,6 +66,7 @@ static inline void check_and_switch_context(struct mm_struct *mm,
> >                 cpu_switch_mm(mm->pgd, mm);
> >  }
> >
> > +#ifndef MODULE
> >  #define finish_arch_post_lock_switch \
> >         finish_arch_post_lock_switch
> >  static inline void finish_arch_post_lock_switch(void)
> > @@ -87,6 +88,7 @@ static inline void finish_arch_post_lock_switch(void)
> >                 preempt_enable_no_resched();
> >         }
> >  }
> > +#endif /* !MODULE */
> >
> >  #endif /* CONFIG_MMU */
> >
> 
> 
> Can someone in arm land ack this so Ingo can apply it?

Sorry, I'm simply unable to read every message that comes in.

Acked-by: Russell King <rmk+kernel at arm.linux.org.uk>

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From charanya at codeaurora.org  Fri May 13 02:18:27 2016
From: charanya at codeaurora.org (charanya at codeaurora.org)
Date: Fri, 13 May 2016 14:48:27 +0530
Subject: [PATCH] tty: serial: msm: Disable restoring Rx interrupts for DMA
 Mode
In-Reply-To: <20160512050245.GD8453@hector.attlocal.net>
References: <1462896580-11554-1-git-send-email-absahu@codeaurora.org>
 <20160512014126.GK3492@codeaurora.org>
 <20160512050245.GD8453@hector.attlocal.net>
Message-ID: <5cce36b3c1d62816feffb4048f782b20@codeaurora.org>

On 2016-05-12 10:32, Andy Gross wrote:
> On Wed, May 11, 2016 at 06:41:26PM -0700, Stephen Boyd wrote:
>> On 05/10, Abhishek Sahu wrote:
>> > From: Charanya <charanya at codeaurora.org>
>> 
>> Was it intentional to only have one name here?
>> 
>> >
>> > The Data loss was happening with current QCOM MSM serial driver during
>> > large file transfer due to simultaneous enabling of both UART and
>> > DMA interrupt. When UART operates in DMA mode, RXLEV (Rx FIFO over
>> > watermark) or RXSTALE (stale interrupts) should not be enabled,
>> > since these conditions will be handled by DMA controller itself.
>> > If these interrupts are enabled then normal UART ISR will read some
>> > bytes of data from Rx Buffer and DMA controller will not receive
>> > these bytes of data, which will cause data loss.
>> >
>> > Now this patch removed the code for enabling of RXLEV and RXSTALE
>> > interrupt in DMA Rx completion routine.
>> 
>> I'm lost, we keep both these irqs masked (well only if uartdm
>> version is 1.4 or greater) pretty much the entire time we're
>> using DMA for RX. msm_start_rx_dma() will mask them and then when
>> the callback completes we'll unmask them (the part that's deleted
>> in this patch), but then we'll go back and remask them almost
>> immediately because we call msm_start_rx_dma() from the dma
>> completion handler.
>> 
>> Can you clearly describe how this is actually fixing any
>> problems? What's the sequence of events that happens to cause
>> corruption?
>> 
>> This does raise the question though why we ever mask/unmask these
>> interrupts if we're always going to keep them masked while doing
>> DMA RX. Presumably if we can use DMA to RX, we can always use it
>> and set things up properly at startup time instead of later on.
> 
> Thats probably the right thing to do.  We shouldn't be 
> masking/unmasking
> the unused IRQs to begin with.
Hi Stephen/Andy,

If both Tx and Rx are used simultaneously, restoring Rx interrupts in
msm_complete_rx_dma could lead to RXSTALE interrupt being triggered, 
when
the ISR execution for TXLEV interrupt is completed, since msm_port->imr 
is
rewritten to UART_IMR in msm_uart_irq. Hence, we do not have to restore
Rx interrupts since Rx is always in DMA mode once enabled.

Thanks.
Charanya.


From ludovic.desroches at atmel.com  Fri May 13 02:22:11 2016
From: ludovic.desroches at atmel.com (Ludovic Desroches)
Date: Fri, 13 May 2016 11:22:11 +0200
Subject: [PATCH] i2c: at91: change log when dma configuration fails
Message-ID: <1463131331-6136-1-git-send-email-ludovic.desroches@atmel.com>

When the DMA configuration fails, there is a log reporting that we can't
use DMA and indicating the error number. When booting the kernel, it is
annoying to see this error number. Moreover, people can think something
is going wrong. It is not the case, it means that DMA can't be used but
it doesn't prevent to use i2c.

Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>
---
 drivers/i2c/busses/i2c-at91.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 921d32b..f2a7457 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -1013,7 +1013,9 @@ static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
 
 error:
 	if (ret != -EPROBE_DEFER)
-		dev_info(dev->dev, "can't use DMA, error %d\n", ret);
+		dev_info(dev->dev,
+			 "can't request DMA channels, continue without DMA support\n",
+			 ret);
 	if (dma->chan_rx)
 		dma_release_channel(dma->chan_rx);
 	if (dma->chan_tx)
-- 
2.5.0



From will.deacon at arm.com  Fri May 13 02:24:20 2016
From: will.deacon at arm.com (Will Deacon)
Date: Fri, 13 May 2016 10:24:20 +0100
Subject: [PATCH] arm64: fix current_thread_info()->addr_limit setup
In-Reply-To: <1463052414-29033-1-git-send-email-ynorov@caviumnetworks.com>
References: <1463052414-29033-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <20160513092419.GA13689@arm.com>

On Thu, May 12, 2016 at 02:26:54PM +0300, Yury Norov wrote:
> At elf loading in flush_old_exec() in fs/exec.c, generic code sets
> current_thread_info()->addr_limit to one that corresponds aarch64 value,
> and ignores compat mode there as corresponding status setup happens
> later on in load_elf_binary() by SET_PERSONALITY() macro. As result,
> compat task has wrong addr_limit, and it may cause various bugs.
> 
> This patch fixes it. It also fixes USER_DS macro to return different
> values depending on compat at runtime.
> 
> It was discovered during ilp32 development. See details here:
> https://lkml.org/lkml/2016/5/11/975

It looks like that thread is ongoing, with discussion around a generic
fix and a related issue with our TLS handling:

  https://lkml.org/lkml/2016/5/12/513
  https://lkml.org/lkml/2016/5/12/515

so I'm going to hold off on this until there's some agreement on the
right way forward. Whatever we end up doing, we should probably cc
stable too.

> Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
> ---
>  arch/arm64/include/asm/elf.h     | 11 +++++++++--
>  arch/arm64/include/asm/uaccess.h |  2 +-
>  2 files changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
> index 24ed037..fda75ce 100644
> --- a/arch/arm64/include/asm/elf.h
> +++ b/arch/arm64/include/asm/elf.h
> @@ -138,7 +138,10 @@ typedef struct user_fpsimd_state elf_fpregset_t;
>   */
>  #define ELF_PLAT_INIT(_r, load_addr)	(_r)->regs[0] = 0
>  
> -#define SET_PERSONALITY(ex)		clear_thread_flag(TIF_32BIT);
> +#define SET_PERSONALITY(ex) do {					\
> +	clear_thread_flag(TIF_32BIT);					\
> +	set_fs(TASK_SIZE_64);						\

You could just use USER_DS for both of the SET_PERSONALITY macros.

Will


From vinod.koul at intel.com  Fri May 13 02:30:40 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Fri, 13 May 2016 15:00:40 +0530
Subject: [PATCH v5 0/3] dmaengine: Add clock support for AXI DMAS
In-Reply-To: <1463123011-4911-1-git-send-email-appanad@xilinx.com>
References: <1463123011-4911-1-git-send-email-appanad@xilinx.com>
Message-ID: <20160513093040.GI2274@localhost>

On Fri, May 13, 2016 at 12:33:28PM +0530, Kedareswara rao Appana wrote:
> This patch series adds basic clock support for AXI DMAS
> This patch series is created on top of the dma-next branch.

Applied, thanks

-- 
~Vinod


From catalin.marinas at arm.com  Fri May 13 02:28:03 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 13 May 2016 09:28:03 +0000
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <57358C2B.1010106@huawei.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
 <20160512134431.GB30205@yury-N73SV>
 <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
 <20160512142457.GC30205@yury-N73SV>
 <20160512152805.GJ11226@e104818-lin.cambridge.arm.com>
 <57358C2B.1010106@huawei.com>
Message-ID: <20160513092802.GA13400@localhost.localdomain>

On Fri, May 13, 2016 at 04:11:23PM +0800, Zhangjian (Bamvor) wrote:
> On 2016/5/12 23:28, Catalin Marinas wrote:
> >On Thu, May 12, 2016 at 05:24:57PM +0300, Yury Norov wrote:
> >>On Thu, May 12, 2016 at 03:07:35PM +0100, Catalin Marinas wrote:
> >>>On Thu, May 12, 2016 at 04:44:31PM +0300, Yury Norov wrote:
> >>>>On Thu, May 12, 2016 at 02:35:34PM +0100, Catalin Marinas wrote:
> >>>>>On Thu, May 12, 2016 at 03:20:00AM +0300, Yury Norov wrote:
> >>>>>>I debugged preadv02 and pwritev02 failures and found very weird bug.
> >>>>>>Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> >>>>>>of vector, and kernel reports successful read/write.
> >>>>>>
> >>>>>>There are 2 problems:
> >>>>>>1. How kernel allows such address to be passed to fs subsystem;
> >>>>>>2. How fs successes to read/write at non-mapped, and in fact non-user
> >>>>>>address.
> >>>>>>
> >>>>>>I don't know the answer on 2'nd question, and it might be something
> >>>>>>generic. But I investigated first problem.
> >>>>>>
> >>>>>>The problem is that compat_rw_copy_check_uvector() uses access_ok() to
> >>>>>>validate user address, and on arm64 it ends up with checking buffer
> >>>>>>end against current_thread_info()->addr_limit.
> >>>>>>
> >>>>>>current_thread_info()->addr_limit for ilp32, and most probably for
> >>>>>>aarch32 is equal to aarch64 one, and so adress_ok() doesn't fail.
> >>>>>>It happens because on thread creation we call flush_old_exec() to set
> >>>>>>addr_limit, and completely ignore compat mode there.
[...]
> >>>>That's true, but USER_DS depends on personality which is not set yet
> >>>>for new thread, as I wrote above. In fact, I tried correct USER_DS
> >>>>only, and it doesn't work
> >>>
> >>>Ah, it looks like load_elf_binary() sets the personality after
> >>>flush_old_exec(). Looking at powerpc and x86, they set USER_DS to the
> >>>maximum 64-bit task value, so they should have a similar issue with
> >>>native 32-bit vs compat behaviour.
[...]
> >>>So what exactly is LTP complaining about? Is different error (like
> >>>EFAULT vs EINVAL) or not getting an error at all.
> >>
> >>It should be EINVAL, but it succeed. The other problem is that
> >>following fs routines does not complain on wrong address.
> >
> >I see. The test asks the kernel to write a single byte (out of maximum
> >64) to the user address 0xffffffff.
> 
> What address We should set for this limitation, TASK_SIZE or STACK_TOP?
> It is same for 64bit application. But STACK_TOP(0xffff0000) is below
> TASK_SIZE in 32bit application. The address above STACK_TOP is preserved
> for 32bit application.

The discussion is mainly around whether USER_DS for 32-bit compat apps
should be the same as USER_DS for native 32-bit apps. Even for native
32-bit kernels, we don't use STACK_TOP as addr_limit. A read/write from
0xffffffff would fail in both cases anyway. I think the LTP test doesn't
even try to access such memory but only to probe the range validity (I
haven't managed to build the latest LTP yet).

-- 
Catalin


From arnd at arndb.de  Fri May 13 02:28:26 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 13 May 2016 11:28:26 +0200
Subject: [PATCH] sched/core: don't include asm/mmu_context from drivers
In-Reply-To: <CALCETrV_wgy0vpWiLYRJn1Q41C6adKKgbEOFthoAXiG601JPYQ@mail.gmail.com>
References: <1461919995-21001-1-git-send-email-arnd@arndb.de>
 <20160429094218.61b26849@gandalf.local.home>
 <CALCETrV_wgy0vpWiLYRJn1Q41C6adKKgbEOFthoAXiG601JPYQ@mail.gmail.com>
Message-ID: <8253941.065j8toVxx@wuerfel>

On Thursday 12 May 2016 22:46:56 Andy Lutomirski wrote:
> On Fri, Apr 29, 2016 at 6:42 AM, Steven Rostedt <rostedt at goodmis.org> wrote:
> > On Fri, 29 Apr 2016 10:52:32 +0200
> > Arnd Bergmann <arnd at arndb.de> wrote:
> >
> >> This reverts the earlier fix attempt and works around the problem
> >> by including both linux/mmu_context.h and asm/mmu_context.h from
> >> kernel/sched/core.c. This is not a good solution but seems less
> >> hacky than the alternatives.
> >
> > What about simply not compiling finish_arch_post_lock_switch() when
> > building modules?
> >
> > (untested, not compiled or anything)
> >
> > Signed-off-by: Steven Rostedt <rostedt at goodmis.org>
> > ---
> > diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h
> > index fa5b42d44985..3f22d1b6bac8 100644
> > --- a/arch/arm/include/asm/mmu_context.h
> > +++ b/arch/arm/include/asm/mmu_context.h
> > @@ -66,6 +66,7 @@ static inline void check_and_switch_context(struct mm_struct *mm,
> >                 cpu_switch_mm(mm->pgd, mm);
> >  }
> >
> > +#ifndef MODULE
> >  #define finish_arch_post_lock_switch \
> >         finish_arch_post_lock_switch
> >  static inline void finish_arch_post_lock_switch(void)
> > @@ -87,6 +88,7 @@ static inline void finish_arch_post_lock_switch(void)
> >                 preempt_enable_no_resched();
> >         }
> >  }
> > +#endif /* !MODULE */
> >
> >  #endif /* CONFIG_MMU */
> >
> 
> 
> Can someone in arm land ack this so Ingo can apply it?
> 

Sorry I forgot about this when I had my original patch in the
randconfig patch stack. I've reverted this now and am testing
with Steve's version. If I see no other regressions, I'll resend
this with a proper changelog and Russell's Ack.

	Arnd


From moinejf at free.fr  Fri May 13 02:45:59 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Fri, 13 May 2016 11:45:59 +0200
Subject: [PATCH 15/16] clk: sunxi-ng: Add H3 clocks
In-Reply-To: <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <20160513114559.786221e415ce5956e161dd5b@free.fr>

On Sun,  8 May 2016 22:01:50 +0200
Maxime Ripard <maxime.ripard at free-electrons.com> wrote:

> Add the list of clocks and resets found in the H3 CCU.

Hi Maxime,

Nice job. I like this new way for defining the sunxi clocks.
But it does not yet fully work for the H3 (apart the other already
signalled errors). See below.

> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile        |   2 +
>  drivers/clk/sunxi-ng/ccu-sun8i-h3.c  | 757 +++++++++++++++++++++++++++++++++++
>  include/dt-bindings/clock/sun8i-h3.h | 162 ++++++++
>  include/dt-bindings/reset/sun8i-h3.h | 103 +++++
>  4 files changed, 1024 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.c
>  create mode 100644 include/dt-bindings/clock/sun8i-h3.h
>  create mode 100644 include/dt-bindings/reset/sun8i-h3.h
> 
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index c794f57b6fb1..67ff6a92f124 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -13,3 +13,5 @@ obj-y += ccu_nkmp.o
>  obj-y += ccu_nm.o
>  obj-y += ccu_p.o
>  obj-y += ccu_phase.o
> +
> +obj-y += ccu-sun8i-h3.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> new file mode 100644
> index 000000000000..5ce699e95c32
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> @@ -0,0 +1,757 @@
	[snip]
> +static struct ccu_nkmp pll_cpux_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +
> +	.m		= SUNXI_CLK_FACTOR(0, 2),
> +	.k		= SUNXI_CLK_FACTOR(4, 2),
> +	.n		= SUNXI_CLK_FACTOR(8, 5),
> +	.p		= SUNXI_CLK_FACTOR(16, 2),
> +
> +	.common		= {
> +		.reg		= 0x000,
> +		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,

It seems to me that these flags are redondant with the .enable
and .lock fields (always != 0 when used).

> +		.hw.init	= SUNXI_HW_INIT("pll-cpux",
> +						"osc24M",
> +						&ccu_nkmp_ops,
> +						0),
> +	},
> +};

The 'p' factor must be used only for very low rates (< 288MHz).
I think that it should be ignored.

> +
> +static struct ccu_nm pll_audio_base_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +
> +	.m		= SUNXI_CLK_FACTOR(0, 5),
> +	.n		= SUNXI_CLK_FACTOR(8, 7),
> +
> +	.common		= {
> +		.reg		= 0x008,
> +		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> +		.hw.init	= SUNXI_HW_INIT("pll-audio-base",
> +						"osc24M",
> +						&ccu_nm_ops,
> +						0),
> +	},
> +};
> +
> +static SUNXI_CCU_M(pll_audio_clk, "pll-audio", "pll-audio-base",
> +		   0x008, 16, 4, 0);
> +
> +static SUNXI_CCU_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
> +			      "pll-audio-base", 2, 1, 0);
> +static SUNXI_CCU_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
> +			      "pll-audio-base", 1, 1, 0);
> +static SUNXI_CCU_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
> +			      "pll-audio-base", 1, 2, 0);

Forcing the post divider 'p' to 4 would simplify this PLL.

> +
> +static struct ccu_nm pll_video_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +
> +	.m		= SUNXI_CLK_FACTOR(0, 4),
> +	.n		= SUNXI_CLK_FACTOR(8, 7),
> +
> +	.common		= {
> +		.reg		= 0x010,
> +		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> +		.hw.init	= SUNXI_HW_INIT("pll-video",
> +						"osc24M",
> +						&ccu_nm_ops,
> +						0),
> +	},
> +};

The legacy u-boot I use (lichee) forces this PLL to 297MHz in
fractional mode (FRAC_CLK_OUT = 1 and PLL_MODE_SEL = 0).
As these bits are not managed, getting the rate is false and setting it
is not possible.

	[snip]
> +
> +static struct ccu_nk pll_periph0_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +
> +	.k		= SUNXI_CLK_FACTOR(4, 2),
> +	.n		= SUNXI_CLK_FACTOR(8, 5),
> +	.fixed_post_div	= 2,
> +
> +	.common		= {
> +		.reg		= 0x028,
> +		.features	= (CCU_FEATURE_GATE |
> +				   CCU_FEATURE_LOCK |
> +				   CCU_FEATURE_FIXED_POSTDIV),
> +		.hw.init	= SUNXI_HW_INIT("pll-periph0",
> +						"osc24M",
> +						&ccu_nk_ops,
> +						0),
> +	},
> +};

As told previously, the H3 documentation says:

 Note: The PLL Output should be fixed to 600MHz, it is not recommended to
 vary this value arbitrarily.

So, is it useful to offer the possibility to change the rate of this PLL
(and same for pll-periph1)?
(I force the rate in the DT with assigned-clock-rates to avoid any problem)

> +
> +static SUNXI_CCU_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
> +			      "pll-periph0", 1, 2, 0);
> +
	[snip]
> +static const char * const nand_parents[] = { "osc24M", "pll-periph0",
> +					     "pll-periph1" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", nand_parents, 0x080,
> +				  0, 4,		/* M */
> +				  16, 2,	/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);

The mux width is 2, meaning there may be 4 parents. Then, there may be
an access out of the parent array (and same for mmcx and spix).

> +
> +static const char * const mmc0_parents[] = { "osc24M", "pll-periph0",
> +					     "pll-periph1" };

The parent tables of nand, mmcx and spix are the same. One table should
be enough.

> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_parents, 0x088,
> +				  0, 4,		/* M */
> +				  16, 2,	/* P */
> +				  24, 2,	/* mux */
> +				  BIT(31),	/* gate */
> +				  0);
> +
> +static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0",
> +		       0x088, 20, 3, 0);
> +static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0",
> +		       0x088, 8, 3, 0);
	[snip]
> +static const char * const i2s0_parents[] = { "pll-audio-8x", "pll-audio-4x",
> +					     "pll-audio-2x" , "pll-audio" };
> +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s0_parents,
> +			       0x0b0, 16, 2, BIT(31), 0);
> +
> +static const char * const i2s1_parents[] = { "pll-audio-8x", "pll-audio-4x",
> +					     "pll-audio-2x" , "pll-audio" };
> +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s1_parents,
> +			       0x0b4, 16, 2, BIT(31), 0);
> +
> +static const char * const i2s2_parents[] = { "pll-audio-8x", "pll-audio-4x",
> +					     "pll-audio-2x" , "pll-audio" };
> +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s2_parents,
> +			       0x0b8, 16, 2, BIT(31), 0);
	[snip]

Same parent tables.
This occurs for other clocks.

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From will.deacon at arm.com  Fri May 13 02:57:19 2016
From: will.deacon at arm.com (Will Deacon)
Date: Fri, 13 May 2016 10:57:19 +0100
Subject: [PATCH] arm64: bpf: jit JMP_JSET_{X,K}
In-Reply-To: <1463121478-18484-1-git-send-email-zlim.lnx@gmail.com>
References: <1463121478-18484-1-git-send-email-zlim.lnx@gmail.com>
Message-ID: <20160513095718.GB13689@arm.com>

On Thu, May 12, 2016 at 11:37:58PM -0700, Zi Shen Lim wrote:
> Original implementation commit e54bcde3d69d ("arm64: eBPF JIT compiler")
> had the relevant code paths, but due to an oversight always fail jiting.
> 
> As a result, we had been falling back to BPF interpreter whenever a BPF
> program has JMP_JSET_{X,K} instructions.
> 
> With this fix, we confirm that the corresponding tests in lib/test_bpf
> continue to pass, and also jited.
> 
> ...
> [    2.784553] test_bpf: #30 JSET jited:1 188 192 197 PASS
> [    2.791373] test_bpf: #31 tcpdump port 22 jited:1 325 677 625 PASS
> [    2.808800] test_bpf: #32 tcpdump complex jited:1 323 731 991 PASS
> ...
> [    3.190759] test_bpf: #237 JMP_JSET_K: if (0x3 & 0x2) return 1 jited:1 110 PASS
> [    3.192524] test_bpf: #238 JMP_JSET_K: if (0x3 & 0xffffffff) return 1 jited:1 98 PASS
> [    3.211014] test_bpf: #249 JMP_JSET_X: if (0x3 & 0x2) return 1 jited:1 120 PASS
> [    3.212973] test_bpf: #250 JMP_JSET_X: if (0x3 & 0xffffffff) return 1 jited:1 89 PASS
> ...
> 
> Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler")
> Signed-off-by: Zi Shen Lim <zlim.lnx at gmail.com>
> ---
>  arch/arm64/net/bpf_jit_comp.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
> index 031ed08..d0d5190 100644
> --- a/arch/arm64/net/bpf_jit_comp.c
> +++ b/arch/arm64/net/bpf_jit_comp.c
> @@ -478,6 +478,7 @@ emit_cond_jmp:
>  		case BPF_JGE:
>  			jmp_cond = A64_COND_CS;
>  			break;
> +		case BPF_JSET:
>  		case BPF_JNE:
>  			jmp_cond = A64_COND_NE;
>  			break;

Are you sure about this? filter.txt says:

jne  - Jump on K != A
...
jset - Jump on k & A

so it looks weird wiring them both to the same thing. I'm not sure you
can express this as a simple CMP + B.<cond>.

Will


From will.deacon at arm.com  Fri May 13 03:03:07 2016
From: will.deacon at arm.com (Will Deacon)
Date: Fri, 13 May 2016 11:03:07 +0100
Subject: [PATCH] arm64: bpf: jit JMP_JSET_{X,K}
In-Reply-To: <20160513095718.GB13689@arm.com>
References: <1463121478-18484-1-git-send-email-zlim.lnx@gmail.com>
 <20160513095718.GB13689@arm.com>
Message-ID: <20160513100307.GC13689@arm.com>

On Fri, May 13, 2016 at 10:57:18AM +0100, Will Deacon wrote:
> On Thu, May 12, 2016 at 11:37:58PM -0700, Zi Shen Lim wrote:
> > Original implementation commit e54bcde3d69d ("arm64: eBPF JIT compiler")
> > had the relevant code paths, but due to an oversight always fail jiting.
> > 
> > As a result, we had been falling back to BPF interpreter whenever a BPF
> > program has JMP_JSET_{X,K} instructions.
> > 
> > With this fix, we confirm that the corresponding tests in lib/test_bpf
> > continue to pass, and also jited.
> > 
> > ...
> > [    2.784553] test_bpf: #30 JSET jited:1 188 192 197 PASS
> > [    2.791373] test_bpf: #31 tcpdump port 22 jited:1 325 677 625 PASS
> > [    2.808800] test_bpf: #32 tcpdump complex jited:1 323 731 991 PASS
> > ...
> > [    3.190759] test_bpf: #237 JMP_JSET_K: if (0x3 & 0x2) return 1 jited:1 110 PASS
> > [    3.192524] test_bpf: #238 JMP_JSET_K: if (0x3 & 0xffffffff) return 1 jited:1 98 PASS
> > [    3.211014] test_bpf: #249 JMP_JSET_X: if (0x3 & 0x2) return 1 jited:1 120 PASS
> > [    3.212973] test_bpf: #250 JMP_JSET_X: if (0x3 & 0xffffffff) return 1 jited:1 89 PASS
> > ...
> > 
> > Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler")
> > Signed-off-by: Zi Shen Lim <zlim.lnx at gmail.com>
> > ---
> >  arch/arm64/net/bpf_jit_comp.c | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
> > index 031ed08..d0d5190 100644
> > --- a/arch/arm64/net/bpf_jit_comp.c
> > +++ b/arch/arm64/net/bpf_jit_comp.c
> > @@ -478,6 +478,7 @@ emit_cond_jmp:
> >  		case BPF_JGE:
> >  			jmp_cond = A64_COND_CS;
> >  			break;
> > +		case BPF_JSET:
> >  		case BPF_JNE:
> >  			jmp_cond = A64_COND_NE;
> >  			break;
> 
> Are you sure about this? filter.txt says:
> 
> jne  - Jump on K != A
> ...
> jset - Jump on k & A
> 
> so it looks weird wiring them both to the same thing. I'm not sure you
> can express this as a simple CMP + B.<cond>.

Ah, sorry, I see how this works now. I overlooked the BPF_JMP | BPF_JSET |
BPF_X case emitting a TST instruction. In which case:

Acked-by: Will Deacon <will.deacon at arm.com>

I'm assuming David will queue this?

Will


From catalin.marinas at arm.com  Fri May 13 03:05:56 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 13 May 2016 11:05:56 +0100
Subject: [PATCH v2] arm64: fix current_thread_info()->addr_limit setup
In-Reply-To: <20160512175154.GA13383@yury-N73SV>
References: <1463069163-374-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512172203.GL11226@e104818-lin.cambridge.arm.com>
 <20160512175154.GA13383@yury-N73SV>
Message-ID: <20160513100556.GA27232@e104818-lin.cambridge.arm.com>

On Thu, May 12, 2016 at 09:03:42PM +0300, Yury Norov wrote:
> On Thu, May 12, 2016 at 06:22:03PM +0100, Catalin Marinas wrote:
> > On Thu, May 12, 2016 at 07:06:03PM +0300, Yury Norov wrote:
> > > diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
> > > index 24ed037..fda75ce 100644
> > > --- a/arch/arm64/include/asm/elf.h
> > > +++ b/arch/arm64/include/asm/elf.h
> > > @@ -138,7 +138,10 @@ typedef struct user_fpsimd_state elf_fpregset_t;
> > >   */
> > >  #define ELF_PLAT_INIT(_r, load_addr)	(_r)->regs[0] = 0
> > >  
> > > -#define SET_PERSONALITY(ex)		clear_thread_flag(TIF_32BIT);
> > > +#define SET_PERSONALITY(ex) do {					\
> > > +	clear_thread_flag(TIF_32BIT);					\
> > > +	set_fs(TASK_SIZE_64);						\
> > > +} while (0)
> > >  
> > >  #define ARCH_DLINFO							\
> > >  do {									\
> > > @@ -181,7 +184,11 @@ typedef compat_elf_greg_t		compat_elf_gregset_t[COMPAT_ELF_NGREG];
> > >  					 ((x)->e_flags & EF_ARM_EABI_MASK))
> > >  
> > >  #define compat_start_thread		compat_start_thread
> > > -#define COMPAT_SET_PERSONALITY(ex)	set_thread_flag(TIF_32BIT);
> > > +#define COMPAT_SET_PERSONALITY(ex) do {					\
> > > +	set_thread_flag(TIF_32BIT);					\
> > > +	set_fs(TASK_SIZE_32);						\
> > > +} while (0)
> > > +
> > >  #define COMPAT_ARCH_DLINFO
> > >  extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
> > >  				      int uses_interp);
> > > diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
> > > index 0685d74..5b269e6 100644
> > > --- a/arch/arm64/include/asm/uaccess.h
> > > +++ b/arch/arm64/include/asm/uaccess.h
> > > @@ -60,7 +60,7 @@ extern int fixup_exception(struct pt_regs *regs);
> > >  #define KERNEL_DS	(-1UL)
> > >  #define get_ds()	(KERNEL_DS)
> > >  
> > > -#define USER_DS		TASK_SIZE_64
> > > +#define USER_DS		TASK_SIZE
> > 
> > We can avoid the USER_DS change as long as SET_PERSONALITY updates the
> > thread's addr_limit. There are very few explicit set_fs(USER_DS) calls
> > and they are on the thread exit path (or exec).
> > 
> > That's unless we try to make a generic set_fs(USER_DS) addition to
> > something like setup_new_exec() and we wouldn't need the SET_PERSONALITY
> > changes:
> 
> I think we'd better leave it fixed. Just because it's correct. Now it
> looks like we have fixed early usages (before SET_PERSONALITY()) of
> set_fs() explicitly, and normal usages (and possible in future) by
> fixing USER_DS.

Thinking some more, let's first try to change USER_DS to the dynamic
TASK_SIZE and add a generic set_fs(USER_DS) call in setup_new_exec() as
below:

> > diff --git a/fs/exec.c b/fs/exec.c
> > index c4010b8207a1..54cc537f5986 100644
> > --- a/fs/exec.c
> > +++ b/fs/exec.c
> > @@ -1226,6 +1226,9 @@ EXPORT_SYMBOL(would_dump);
> >  
> >  void setup_new_exec(struct linux_binprm * bprm)
> >  {
> > +	/* set the address limit for the new executable */
> > +	set_fs(USER_DS);
> > +
> >  	arch_pick_mmap_layout(current->mm);
> >  
> >  	/* This is the point of no return */
> > 

Cc'ing Al Viro for his opinion here.

In summary: access_ok() behaves differently on native 32-bit kernels vs
64-bit + compat applications because for the latter USER_DS is always
set to the maximum 64-bit TASK_SIZE (x86 and powerpc seem to do
something similar). Changing USER_DS alone in the arch code does not
help since the set_fs(USER_DS) in flush_old_exec() is called prior to
COMPAT_SET_PERSONALITY().

(it's not a serious bug, just some LTP tests failing when they test an
address range going beyond the 4GB limit)

Thanks.

-- 
Catalin


From christoffer.dall at linaro.org  Fri May 13 03:11:47 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 13 May 2016 12:11:47 +0200
Subject: [PATCH v3 38/55] KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM
 device ops registration
In-Reply-To: <1462531568-9799-39-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-39-git-send-email-andre.przywara@arm.com>
Message-ID: <20160513101147.GA16274@cbox>

On Fri, May 06, 2016 at 11:45:51AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> This patch introduces the skeleton for the KVM device operations
> associated to KVM_DEV_TYPE_ARM_VGIC_V2 and KVM_DEV_TYPE_ARM_VGIC_V3.
> 
> At that stage kvm_vgic_create is stubbed.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Fri May 13 03:11:53 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 13 May 2016 12:11:53 +0200
Subject: [PATCH v3 39/55] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_NR_IRQS
In-Reply-To: <1462531568-9799-40-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-40-git-send-email-andre.przywara@arm.com>
Message-ID: <20160513101153.GB16274@cbox>

On Fri, May 06, 2016 at 11:45:52AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> This patch implements the KVM_DEV_ARM_VGIC_GRP_NR_IRQS group. This
> modality is supported by both VGIC V2 and V3 KVM device as will be
> other groups, hence the introduction of common helpers.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-kvm-device.c | 83 +++++++++++++++++++++++++++++++++++--
>  1 file changed, 79 insertions(+), 4 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index ff332f3..05ff925 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -15,9 +15,69 @@
>   */
>  #include <linux/kvm_host.h>
>  #include <kvm/arm_vgic.h>
> +#include <linux/uaccess.h>
> +#include "vgic.h"
>  
>  /* common helpers */
>  
> +static int vgic_set_common_attr(struct kvm_device *dev,
> +				struct kvm_device_attr *attr)
> +{
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
> +		u32 val;
> +		int ret = 0;
> +
> +		if (get_user(val, uaddr))
> +			return -EFAULT;
> +
> +		/*
> +		 * We require:
> +		 * - at least 32 SPIs on top of the 16 SGIs and 16 PPIs
> +		 * - at most 1024 interrupts
> +		 * - a multiple of 32 interrupts
> +		 */
> +		if (val < (VGIC_NR_PRIVATE_IRQS + 32) ||
> +		    val > VGIC_MAX_RESERVED ||
> +		    (val & 31))
> +			return -EINVAL;
> +
> +		mutex_lock(&dev->kvm->lock);
> +
> +		if (vgic_ready(dev->kvm) || dev->kvm->arch.vgic.nr_spis)
> +			ret = -EBUSY;
> +		else
> +			dev->kvm->arch.vgic.nr_spis =
> +				val - VGIC_NR_PRIVATE_IRQS;
> +
> +		mutex_unlock(&dev->kvm->lock);
> +
> +		return ret;
> +	}
> +	}
> +
> +	return -ENXIO;
> +}
> +
> +static int vgic_get_common_attr(struct kvm_device *dev,
> +				struct kvm_device_attr *attr)
> +{
> +	int r = -ENXIO;
> +
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
> +
> +		r = put_user(dev->kvm->arch.vgic.nr_spis +
> +			     VGIC_NR_PRIVATE_IRQS, uaddr);
> +		break;
> +	}
> +	}
> +
> +	return r;
> +}
> +
>  static int vgic_create(struct kvm_device *dev, u32 type)
>  {
>  	return kvm_vgic_create(dev->kvm, type);
> @@ -49,18 +109,29 @@ void kvm_register_vgic_device(unsigned long type)
>  static int vgic_v2_set_attr(struct kvm_device *dev,
>  			    struct kvm_device_attr *attr)
>  {
> -	return -ENXIO;
> +	int ret;
> +
> +	ret = vgic_set_common_attr(dev, attr);
> +	return ret;
> +
>  }
>  
>  static int vgic_v2_get_attr(struct kvm_device *dev,
>  			    struct kvm_device_attr *attr)
>  {
> -	return -ENXIO;
> +	int ret;
> +
> +	ret = vgic_get_common_attr(dev, attr);
> +	return ret;
>  }
>  
>  static int vgic_v2_has_attr(struct kvm_device *dev,
>  			    struct kvm_device_attr *attr)
>  {
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
> +		return 0;
> +	}
>  	return -ENXIO;
>  }
>  
> @@ -80,18 +151,22 @@ struct kvm_device_ops kvm_arm_vgic_v2_ops = {
>  static int vgic_v3_set_attr(struct kvm_device *dev,
>  			    struct kvm_device_attr *attr)
>  {
> -	return -ENXIO;
> +	return vgic_set_common_attr(dev, attr);
>  }
>  
>  static int vgic_v3_get_attr(struct kvm_device *dev,
>  			    struct kvm_device_attr *attr)
>  {
> -	return -ENXIO;
> +	return vgic_get_common_attr(dev, attr);
>  }
>  
>  static int vgic_v3_has_attr(struct kvm_device *dev,
>  			    struct kvm_device_attr *attr)
>  {
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
> +		return 0;
> +	}
>  	return -ENXIO;
>  }
>  
> -- 
> 2.7.3
> 

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Fri May 13 03:11:58 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 13 May 2016 12:11:58 +0200
Subject: [PATCH v3 40/55] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_CTRL
In-Reply-To: <1462531568-9799-41-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-41-git-send-email-andre.przywara@arm.com>
Message-ID: <20160513101158.GC16274@cbox>

On Fri, May 06, 2016 at 11:45:53AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> This patch implements the KVM_DEV_ARM_VGIC_GRP_CTRL group API
> featuring KVM_DEV_ARM_VGIC_CTRL_INIT attribute. The vgic_init
> function is not yet implemented though.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-kvm-device.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index 05ff925..e153f12 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -23,6 +23,8 @@
>  static int vgic_set_common_attr(struct kvm_device *dev,
>  				struct kvm_device_attr *attr)
>  {
> +	int r;
> +
>  	switch (attr->group) {
>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
>  		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
> @@ -55,6 +57,16 @@ static int vgic_set_common_attr(struct kvm_device *dev,
>  
>  		return ret;
>  	}
> +	case KVM_DEV_ARM_VGIC_GRP_CTRL: {
> +		switch (attr->attr) {
> +		case KVM_DEV_ARM_VGIC_CTRL_INIT:
> +			mutex_lock(&dev->kvm->lock);
> +			r = vgic_init(dev->kvm);
> +			mutex_unlock(&dev->kvm->lock);
> +			return r;
> +		}
> +		break;
> +	}
>  	}
>  
>  	return -ENXIO;
> @@ -131,6 +143,11 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
>  	switch (attr->group) {
>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
>  		return 0;
> +	case KVM_DEV_ARM_VGIC_GRP_CTRL:
> +		switch (attr->attr) {
> +		case KVM_DEV_ARM_VGIC_CTRL_INIT:
> +			return 0;
> +		}
>  	}
>  	return -ENXIO;
>  }
> @@ -166,6 +183,11 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
>  	switch (attr->group) {
>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
>  		return 0;
> +	case KVM_DEV_ARM_VGIC_GRP_CTRL:
> +		switch (attr->attr) {
> +		case KVM_DEV_ARM_VGIC_CTRL_INIT:
> +			return 0;
> +		}
>  	}
>  	return -ENXIO;
>  }
> -- 
> 2.7.3
> 
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Fri May 13 03:12:04 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 13 May 2016 12:12:04 +0200
Subject: [PATCH v3 41/55] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 implement kvm_vgic_addr
In-Reply-To: <1462531568-9799-42-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-42-git-send-email-andre.przywara@arm.com>
Message-ID: <20160513101204.GD16274@cbox>

On Fri, May 06, 2016 at 11:45:54AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> kvm_vgic_addr is used by the userspace to set the base address of
> the following register regions, as seen by the guest:
> - distributor(v2 and v3),
> - re-distributors (v3),
> - CPU interface (v2).
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  include/kvm/vgic/vgic.h             |   2 +
>  virt/kvm/arm/vgic/vgic-kvm-device.c | 112 ++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h            |   3 +
>  3 files changed, 117 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 2c43eb8..73cab36 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -194,6 +194,8 @@ struct vgic_cpu {
>  	u64 live_lrs;
>  };
>  
> +int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
> +
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  			bool level);
>  
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index e153f12..493e941 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -16,10 +16,122 @@
>  #include <linux/kvm_host.h>
>  #include <kvm/arm_vgic.h>
>  #include <linux/uaccess.h>
> +#include <asm/kvm_mmu.h>
>  #include "vgic.h"
>  
>  /* common helpers */
>  
> +static int vgic_ioaddr_overlap(struct kvm *kvm)
> +{
> +	phys_addr_t dist = kvm->arch.vgic.vgic_dist_base;
> +	phys_addr_t cpu = kvm->arch.vgic.vgic_cpu_base;
> +
> +	if (IS_VGIC_ADDR_UNDEF(dist) || IS_VGIC_ADDR_UNDEF(cpu))
> +		return 0;
> +	if ((dist <= cpu && dist + KVM_VGIC_V2_DIST_SIZE > cpu) ||
> +	    (cpu <= dist && cpu + KVM_VGIC_V2_CPU_SIZE > dist))
> +		return -EBUSY;
> +	return 0;
> +}
> +
> +static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
> +			      phys_addr_t addr, phys_addr_t size)
> +{
> +	int ret;
> +
> +	if (addr & ~KVM_PHYS_MASK)
> +		return -E2BIG;
> +
> +	if (addr & (SZ_4K - 1))
> +		return -EINVAL;
> +
> +	if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
> +		return -EEXIST;
> +	if (addr + size < addr)
> +		return -EINVAL;
> +
> +	*ioaddr = addr;
> +	ret = vgic_ioaddr_overlap(kvm);
> +	if (ret)
> +		*ioaddr = VGIC_ADDR_UNDEF;
> +
> +	return ret;
> +}
> +
> +/**
> + * kvm_vgic_addr - set or get vgic VM base addresses
> + * @kvm:   pointer to the vm struct
> + * @type:  the VGIC addr type, one of KVM_VGIC_V[23]_ADDR_TYPE_XXX
> + * @addr:  pointer to address value
> + * @write: if true set the address in the VM address space, if false read the
> + *          address
> + *
> + * Set or get the vgic base addresses for the distributor and the virtual CPU
> + * interface in the VM physical address space.  These addresses are properties
> + * of the emulated core/SoC and therefore user space initially knows this
> + * information.
> + */
> +int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
> +{
> +	int r = 0;
> +	struct vgic_dist *vgic = &kvm->arch.vgic;
> +	int type_needed;
> +	phys_addr_t *addr_ptr, block_size;
> +	phys_addr_t alignment;
> +
> +	mutex_lock(&kvm->lock);
> +	switch (type) {
> +	case KVM_VGIC_V2_ADDR_TYPE_DIST:
> +		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
> +		addr_ptr = &vgic->vgic_dist_base;
> +		block_size = KVM_VGIC_V2_DIST_SIZE;
> +		alignment = SZ_4K;
> +		break;
> +	case KVM_VGIC_V2_ADDR_TYPE_CPU:
> +		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
> +		addr_ptr = &vgic->vgic_cpu_base;
> +		block_size = KVM_VGIC_V2_CPU_SIZE;
> +		alignment = SZ_4K;
> +		break;
> +#ifdef CONFIG_KVM_ARM_VGIC_V3
> +	case KVM_VGIC_V3_ADDR_TYPE_DIST:
> +		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
> +		addr_ptr = &vgic->vgic_dist_base;
> +		block_size = KVM_VGIC_V3_DIST_SIZE;
> +		alignment = SZ_64K;
> +		break;
> +	case KVM_VGIC_V3_ADDR_TYPE_REDIST:
> +		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
> +		addr_ptr = &vgic->vgic_redist_base;
> +		block_size = KVM_VGIC_V3_REDIST_SIZE;
> +		alignment = SZ_64K;
> +		break;
> +#endif
> +	default:
> +		r = -ENODEV;
> +		goto out;
> +	}
> +
> +	if (vgic->vgic_model != type_needed) {
> +		r = -ENODEV;
> +		goto out;
> +	}
> +
> +	if (write) {
> +		if (!IS_ALIGNED(*addr, alignment))
> +			r = -EINVAL;
> +		else
> +			r = vgic_ioaddr_assign(kvm, addr_ptr,
> +					       *addr, block_size);
> +	} else {
> +		*addr = *addr_ptr;
> +	}
> +
> +out:
> +	mutex_unlock(&kvm->lock);
> +	return r;
> +}
> +
>  static int vgic_set_common_attr(struct kvm_device *dev,
>  				struct kvm_device_attr *attr)
>  {
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index e7c66a5..c44ee01 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -19,6 +19,9 @@
>  #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
>  #define IMPLEMENTER_ARM		0x43b
>  
> +#define VGIC_ADDR_UNDEF		(-1)
> +#define IS_VGIC_ADDR_UNDEF(_x)  ((_x) == VGIC_ADDR_UNDEF)
> +
>  #define INTERRUPT_ID_BITS_SPIS	10
>  
>  #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
> -- 
> 2.7.3
> 
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Fri May 13 03:12:37 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 13 May 2016 12:12:37 +0200
Subject: [PATCH v3 42/55] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_ADDR
In-Reply-To: <1462531568-9799-43-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-43-git-send-email-andre.przywara@arm.com>
Message-ID: <20160513101237.GE16274@cbox>

On Fri, May 06, 2016 at 11:45:55AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> This patch implements the KVM_DEV_ARM_VGIC_GRP_ADDR group which
> enables to set the base address of GIC regions as seen by the guest.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-kvm-device.c | 38 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 38 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index 493e941..0189c13 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -138,6 +138,17 @@ static int vgic_set_common_attr(struct kvm_device *dev,
>  	int r;
>  
>  	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
> +		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> +		u64 addr;
> +		unsigned long type = (unsigned long)attr->attr;
> +
> +		if (copy_from_user(&addr, uaddr, sizeof(addr)))
> +			return -EFAULT;
> +
> +		r = kvm_vgic_addr(dev->kvm, type, &addr, true);
> +		return (r == -ENODEV) ? -ENXIO : r;
> +	}
>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
>  		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
>  		u32 val;
> @@ -190,6 +201,19 @@ static int vgic_get_common_attr(struct kvm_device *dev,
>  	int r = -ENXIO;
>  
>  	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
> +		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> +		u64 addr;
> +		unsigned long type = (unsigned long)attr->attr;
> +
> +		r = kvm_vgic_addr(dev->kvm, type, &addr, false);
> +		if (r)
> +			return (r == -ENODEV) ? -ENXIO : r;
> +
> +		if (copy_to_user(uaddr, &addr, sizeof(addr)))
> +			return -EFAULT;
> +		break;
> +	}
>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
>  		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
>  
> @@ -253,6 +277,13 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
>  			    struct kvm_device_attr *attr)
>  {
>  	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_ADDR:
> +		switch (attr->attr) {
> +		case KVM_VGIC_V2_ADDR_TYPE_DIST:
> +		case KVM_VGIC_V2_ADDR_TYPE_CPU:
> +			return 0;
> +		}
> +		break;
>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
>  		return 0;
>  	case KVM_DEV_ARM_VGIC_GRP_CTRL:
> @@ -293,6 +324,13 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
>  			    struct kvm_device_attr *attr)
>  {
>  	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_ADDR:
> +		switch (attr->attr) {
> +		case KVM_VGIC_V3_ADDR_TYPE_DIST:
> +		case KVM_VGIC_V3_ADDR_TYPE_REDIST:
> +			return 0;
> +		}
> +		break;
>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
>  		return 0;
>  	case KVM_DEV_ARM_VGIC_GRP_CTRL:
> -- 
> 2.7.3
> 
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From marc.zyngier at arm.com  Fri May 13 03:24:41 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Fri, 13 May 2016 11:24:41 +0100
Subject: [PATCH v2 1/2] ARM64: arch_timer: Work around QorIQ Erratum
 A-008585
In-Reply-To: <1463114260-8724-1-git-send-email-oss@buserror.net>
References: <1463114260-8724-1-git-send-email-oss@buserror.net>
Message-ID: <20160513112441.200f4349@arm.com>

On Thu, 12 May 2016 23:37:39 -0500
Scott Wood <oss at buserror.net> wrote:

Hi Scott,

> Erratum A-008585 says that the ARM generic timer counter "has the
> potential to contain an erroneous value for a small number of core
> clock cycles every time the timer value changes".  Accesses to TVAL
> (both read and write) are also affected due to the implicit counter
> read.  Accesses to CVAL are not affected.
> 
> The workaround is to reread TVAL and count registers until successive reads
> return the same value, and when writing TVAL to retry until counter
> reads before and after the write return the same value.
> 
> This erratum can be found on LS1043A and LS2080A.
> 
> Signed-off-by: Scott Wood <oss at buserror.net>
> ---
> v2:
> Significant rework based on feedback, including using static_key,
> disabling VDSO counter access rather than adding the workaround to the
> VDSO, and uninlining the loops.
> 
> Dropped the separate property for indicating that writes to TVAL are
> affected, as I believe that's just a side effect of the implicit
> counter read being corrupted, and thus a chip that is affected by one
> will always be affected by the other.
> 
> Dropped the arm32 portion as it seems there was confusion about whether
> LS1021A is affected.  Currently I am being told that it is not
> affected.
> 
> I considered writing to CVAL rather than looping on TVAL writes, but
> that would still have required separate set_next_event() code for the
> erratum, and adding CVAL to the enum would have required a bunch of
> extra handlers in switch statements (even where unused, due to compiler
> warnings about unhandled enum values) including in an arm32 header.  It
> seemed better to avoid the arm32 interaction and new untested
> accessors.
> ---
>  .../devicetree/bindings/arm/arch_timer.txt         |   6 ++
>  arch/arm64/include/asm/arch_timer.h                |  37 +++++--
>  drivers/clocksource/arm_arch_timer.c               | 110 +++++++++++++++++++++
>  3 files changed, 144 insertions(+), 9 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
> index e774128..ef5fbe9 100644
> --- a/Documentation/devicetree/bindings/arm/arch_timer.txt
> +++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
> @@ -25,6 +25,12 @@ to deliver its interrupts via SPIs.
>  - always-on : a boolean property. If present, the timer is powered through an
>    always-on power domain, therefore it never loses context.
>  
> +- fsl,erratum-a008585 : A boolean property. Indicates the presence of
> +  QorIQ erratum A-008585, which says that reading the counter is
> +  unreliable unless the same value is returned by back-to-back reads.
> +  This also affects writes to the tval register, due to the implicit
> +  counter read.
> +
>  ** Optional properties:
>  
>  - arm,cpu-registers-not-fw-configured : Firmware does not initialize

This should be part of a separate patch. Also, errata should be
documented in Documentation/arm64/silicon-errata.txt.

> diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
> index fbe0ca3..9715e85 100644
> --- a/arch/arm64/include/asm/arch_timer.h
> +++ b/arch/arm64/include/asm/arch_timer.h
> @@ -23,10 +23,33 @@
>  
>  #include <linux/bug.h>
>  #include <linux/init.h>
> +#include <linux/jump_label.h>
>  #include <linux/types.h>
>  
>  #include <clocksource/arm_arch_timer.h>
>  
> +extern struct static_key_false arch_timer_read_ool_enabled;
> +
> +#define ARCH_TIMER_REG_READ(reg, func) \
> +extern u64 func##_ool(void); \
> +static inline u64 __##func(void) \
> +{ \
> +	u64 val; \
> +	asm volatile("mrs %0, " reg : "=r" (val)); \
> +	return val; \
> +} \
> +static inline u64 _##func(void) \
> +{ \
> +	if (static_branch_unlikely(&arch_timer_read_ool_enabled)) \
> +		return func##_ool(); \
> +	else \
> +		return __##func(); \
> +}
> +
> +ARCH_TIMER_REG_READ("cntp_tval_el0", arch_timer_get_ptval)
> +ARCH_TIMER_REG_READ("cntv_tval_el0", arch_timer_get_vtval)
> +ARCH_TIMER_REG_READ("cntvct_el0", arch_counter_get_cntvct)
> +

Given that this will have a (small) impact on non-affected platforms,
it'd be good to have this guarded by a erratum-specific config option
(CONFIG_FSL_ERRATUM_008585?) and turn it into trivial accessors when not
defined.

>  /*
>   * These register accessors are marked inline so the compiler can
>   * nicely work out which register we want, and chuck away the rest of
> @@ -66,19 +89,19 @@ u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
>  	if (access == ARCH_TIMER_PHYS_ACCESS) {
>  		switch (reg) {
>  		case ARCH_TIMER_REG_CTRL:
> -			asm volatile("mrs %0,  cntp_ctl_el0" : "=r" (val));
> +			asm volatile("mrs %0, cntp_ctl_el0" : "=r" (val));

Spurious change?

>  			break;
>  		case ARCH_TIMER_REG_TVAL:
> -			asm volatile("mrs %0, cntp_tval_el0" : "=r" (val));
> +			val = _arch_timer_get_ptval();
>  			break;
>  		}
>  	} else if (access == ARCH_TIMER_VIRT_ACCESS) {
>  		switch (reg) {
>  		case ARCH_TIMER_REG_CTRL:
> -			asm volatile("mrs %0,  cntv_ctl_el0" : "=r" (val));
> +			asm volatile("mrs %0, cntv_ctl_el0" : "=r" (val));

Same here.

>  			break;
>  		case ARCH_TIMER_REG_TVAL:
> -			asm volatile("mrs %0, cntv_tval_el0" : "=r" (val));
> +			val = _arch_timer_get_vtval();
>  			break;
>  		}
>  	}
> @@ -116,12 +139,8 @@ static inline u64 arch_counter_get_cntpct(void)
>  
>  static inline u64 arch_counter_get_cntvct(void)
>  {
> -	u64 cval;
> -
>  	isb();
> -	asm volatile("mrs %0, cntvct_el0" : "=r" (cval));
> -
> -	return cval;
> +	return _arch_counter_get_cntvct();
>  }
>  
>  static inline int arch_timer_arch_init(void)
> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> index 5152b38..6f78831 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -79,10 +79,52 @@ static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI;
>  static bool arch_timer_c3stop;
>  static bool arch_timer_mem_use_virtual;
>  
> +DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled);
> +EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled);
> +

Once you have a config option, this can move to the guarded section
below...

>  /*
>   * Architected system timer support.
>   */
>  
> +#ifdef CONFIG_ARM64

which can become CONFIG_FSL_ERRATUM_008585

> +/*
> + * __always_inline is used to ensure that func() is not an actual function
> + * pointer, which would result in the register accesses potentially being too
> + * far apart for the loop to work.
> + */
> +static __always_inline u64 arch_timer_reread(u64 (*func)(void))

This is quite a generic function name. I'd expect something that refers
to the erratum number.

> +{
> +	u64 cval_old, cval_new;
> +	int timeout = 200;

Can we have a comment on how this value has been chosen? 

> +
> +	do {
> +		isb();
> +		cval_old = func();
> +		cval_new = func();
> +		timeout--;
> +	} while (cval_old != cval_new && timeout);
> +
> +	WARN_ON_ONCE(!timeout);
> +	return cval_new;
> +}
> +
> +u64 arch_counter_get_cntvct_ool(void)
> +{
> +	return arch_timer_reread(__arch_counter_get_cntvct);
> +}
> +
> +u64 arch_timer_get_vtval_ool(void)
> +{
> +	return arch_timer_reread(__arch_timer_get_vtval);
> +}
> +
> +u64 arch_timer_get_ptval_ool(void)
> +{
> +	return arch_timer_reread(__arch_timer_get_ptval);
> +}
> +
> +#endif /* ARM64 */
> +
>  static __always_inline
>  void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val,
>  			  struct clock_event_device *clk)
> @@ -232,6 +274,50 @@ static __always_inline void set_next_event(const int access, unsigned long evt,
>  	arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
>  }
>  
> +#ifdef CONFIG_ARM64
> +static __always_inline void rewrite_tval(const int access,
> +		unsigned long evt, struct clock_event_device *clk)
> +{
> +	u64 cval_old, cval_new;
> +	int timeout = 200;
> +
> +	do {
> +		cval_old = __arch_counter_get_cntvct();
> +		arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt, clk);
> +		cval_new = __arch_counter_get_cntvct();

Don't you need to guarantee the order of accesses here?

> +		timeout--;
> +	} while (cval_old != cval_new && timeout);
> +
> +	WARN_ON_ONCE(!timeout);
> +}
> +
> +static __always_inline void set_next_event_errata(const int access,
> +		unsigned long evt, struct clock_event_device *clk)
> +{
> +	unsigned long ctrl;
> +
> +	ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);
> +	ctrl |= ARCH_TIMER_CTRL_ENABLE;
> +	ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
> +	rewrite_tval(access, evt, clk);
> +	arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
> +}
> +
> +static int arch_timer_set_next_event_virt_errata(unsigned long evt,
> +						 struct clock_event_device *clk)
> +{
> +	set_next_event_errata(ARCH_TIMER_VIRT_ACCESS, evt, clk);
> +	return 0;
> +}
> +
> +static int arch_timer_set_next_event_phys_errata(unsigned long evt,
> +						 struct clock_event_device *clk)
> +{
> +	set_next_event_errata(ARCH_TIMER_PHYS_ACCESS, evt, clk);
> +	return 0;
> +}

Same comment about the function names.

> +#endif /* ARM64 */
> +
>  static int arch_timer_set_next_event_virt(unsigned long evt,
>  					  struct clock_event_device *clk)
>  {
> @@ -277,6 +363,13 @@ static void __arch_timer_setup(unsigned type,
>  			clk->set_state_shutdown = arch_timer_shutdown_virt;
>  			clk->set_state_oneshot_stopped = arch_timer_shutdown_virt;
>  			clk->set_next_event = arch_timer_set_next_event_virt;
> +
> +#ifdef CONFIG_ARM64
> +			if (static_branch_unlikely(&arch_timer_read_ool_enabled))
> +				clk->set_next_event =
> +					arch_timer_set_next_event_virt_errata;

On the same line, please. You could also rewrite this as a helper
function that would populate the set_next_event field in all cases.

> +#endif
> +
>  			break;
>  		case PHYS_SECURE_PPI:
>  		case PHYS_NONSECURE_PPI:
> @@ -284,6 +377,13 @@ static void __arch_timer_setup(unsigned type,
>  			clk->set_state_shutdown = arch_timer_shutdown_phys;
>  			clk->set_state_oneshot_stopped = arch_timer_shutdown_phys;
>  			clk->set_next_event = arch_timer_set_next_event_phys;
> +
> +#ifdef CONFIG_ARM64
> +			if (static_branch_unlikely(&arch_timer_read_ool_enabled))
> +				clk->set_next_event =
> +					arch_timer_set_next_event_phys_errata;

Same here.

> +#endif
> +
>  			break;
>  		default:
>  			BUG();
> @@ -485,6 +585,13 @@ static void __init arch_counter_register(unsigned type)
>  			arch_timer_read_counter = arch_counter_get_cntvct;
>  		else
>  			arch_timer_read_counter = arch_counter_get_cntpct;
> +
> +		/*
> +		 * Don't use the vdso fastpath if errata require using
> +		 * the out-of-line counter accessor.
> +		 */
> +		if (static_branch_unlikely(&arch_timer_read_ool_enabled))
> +			clocksource_counter.name = "arch_sys_counter_ool";

This looks really ugly. How about telling the vdso subsystem directly?
Will, do you have a preference?

>  	} else {
>  		arch_timer_read_counter = arch_counter_get_cntvct_mem;
>  
> @@ -763,6 +870,9 @@ static void __init arch_timer_of_init(struct device_node *np)
>  
>  	arch_timer_c3stop = !of_property_read_bool(np, "always-on");
>  
> +	if (of_property_read_bool(np, "fsl,erratum-a008585"))
> +		static_branch_enable(&arch_timer_read_ool_enabled);
> +
>  	/*
>  	 * If we cannot rely on firmware initializing the timer registers then
>  	 * we should use the physical timers instead.

An outstanding question is how we're going to deal with this in KVM,
because a guest absolutely needs to know about it (I can definitely see
time jumping in guests running on a LS2080).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.


From lorenzo.pieralisi at arm.com  Fri May 13 03:32:50 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Fri, 13 May 2016 11:32:50 +0100
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <CAJZ5v0jOAOWLNab0vMOVyciwOhtkuPdqZt3wkFbprq+PkEQNVg@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
 <CAJZ5v0hM8WAr9GGku89zKgiVKt6ArHf=9CntRUyBjyMNUvie2A@mail.gmail.com>
 <20160511101101.GA16101@red-moon>
 <CAJZ5v0hgw929W5PjF0PqT+ssiOHd8TeJoSQcz4NUiAovZY2pfQ@mail.gmail.com>
 <20160511224314.GD28812@localhost>
 <CAKc_7PW8BqQSTn01zDVsec4KXunQUKfcEft8=MH-E0xsmheo3w@mail.gmail.com>
 <CAJZ5v0jOAOWLNab0vMOVyciwOhtkuPdqZt3wkFbprq+PkEQNVg@mail.gmail.com>
Message-ID: <20160513103239.GA17873@red-moon>

On Thu, May 12, 2016 at 01:27:23PM +0200, Rafael J. Wysocki wrote:
> On Thu, May 12, 2016 at 12:43 PM, Jayachandran C <jchandra at broadcom.com> wrote:
> > On Thu, May 12, 2016 at 4:13 AM, Bjorn Helgaas <helgaas at kernel.org> wrote:
> >> On Wed, May 11, 2016 at 10:30:51PM +0200, Rafael J. Wysocki wrote:
> >>> On Wed, May 11, 2016 at 12:11 PM, Lorenzo Pieralisi
> >>> <lorenzo.pieralisi at arm.com> wrote:
> >>> > On Tue, May 10, 2016 at 08:37:00PM +0200, Rafael J. Wysocki wrote:
> >>> >> On Tue, May 10, 2016 at 5:19 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> 
> [cut]
> 
> >
> > If we are moving the ACPI/PCI code from drivers/acpi to
> > arch/arm64/ , there is an issue in having the header file
> > ecam.h in drivers/pci
> >
> > The current include of "../pci/ecam.h" is slightly ugly (Arnd
> > and David had already noted this), but including the driver
> > header from arch code would be even worse.
> >
> > I can either merge ecam.h into include/linux/pci.h
> > or move it to a new file include/linux/pci-ecam.h, any
> > suggestion on which is preferable?
> 
> My preference would be pci-ecam.h as we did a similar thing for
> pci-dma.h, for example, but basically this is up to Bjorn.

A word of caution for all interested parties, what we may move
to arch/arm64 (if Catalin and Will are ok with that) here is content
of drivers/acpi/pci_root_generic.c, not drivers/acpi/pci_mcfg.c (and
definitely not the MCFG quirks handling that is coming up next on top
of this series).

I just wanted to make sure we understand that MCFG quirks handling
like eg:

https://lkml.org/lkml/2016/4/28/790

that is coming up following this series has no chance whatsoever to
be handled within arch/arm64, it is just not going to happen.

Maybe I am jumping the gun, I just want to make sure that everyone is
aware that moving part of this series to arch/arm64 has implications,
(and that's why I said that moving part of this code to arch/arm64 is
not as simple as it looks) it may be ok to have an ACPI PCI
implementation that is arch/arm64 specific (mostly for IO space and PCI
resources assignment handling that unfortunately is not uniform across
X86, IA64 and ARM64), but MCFG quirks and related platform code stay out
of arch/arm64 I guess we are all aware of that, just wanted to make
sure :)

Lorenzo


From LW at KARO-electronics.de  Fri May 13 03:33:36 2016
From: LW at KARO-electronics.de (Lothar =?UTF-8?B?V2HDn21hbm4=?=)
Date: Fri, 13 May 2016 12:33:36 +0200
Subject: imx-drm: regression due to commit 503fe87bd0a8 ("gpu: ipu-v3: Fix
 imx-ipuv3-crtc module autoloading")
Message-ID: <20160513123336.6996dd89@ipc1.ka-ro>

Hi,

the commit 503fe87bd0a8 ("gpu: ipu-v3: Fix imx-ipuv3-crtc module autoloading")
indeed fixes the autoloading issue, but completely breaks the driver in
non-modular mode (at least with the parallel-display driver I didn't
yet check with the imx-ldb driver.
Can anyone confirm that the imx-drm driver in current linux-next
(next-20160512) works for them with any i.MX6 or i.MX53 board?

I'm always very suspicious when seeing code moving of_node's from
one device to another or assigning of_node's to platform devices that
weren't instantiated via DT.


Lothar Wa?mann


From wsa at the-dreams.de  Fri May 13 03:41:32 2016
From: wsa at the-dreams.de (Wolfram Sang)
Date: Fri, 13 May 2016 12:41:32 +0200
Subject: [PATCH] i2c: st: Implement bus clear
In-Reply-To: <1462983719-342-1-git-send-email-peter.griffin@linaro.org>
References: <1462983719-342-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <20160513104132.GG1778@katana>

On Wed, May 11, 2016 at 05:21:59PM +0100, Peter Griffin wrote:
> From I2C specifications:
>       http://www.nxp.com/documents/user_manual/UM10204.pdf
> 
> Chapter 3.1.16, when the i2c device held the SDA line low, the master
> should send 9 clocks pulses to try to recover.
> 
> Signed-off-by: Frederic Pillon <frederic.pillon at st.com>
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>

Applied to for-next, thanks! Please us PATCH V<n> next time.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160513/6f945531/attachment.sig>

From andre.przywara at arm.com  Fri May 13 03:44:38 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri, 13 May 2016 11:44:38 +0100
Subject: [PATCH v3 47/55] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <20160513075323.GF27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-48-git-send-email-andre.przywara@arm.com>
 <20160512184740.GM27623@cbox> <5734D0F6.9090406@arm.com>
 <20160513075323.GF27623@cbox>
Message-ID: <5735B016.50207@arm.com>

Hi,

On 13/05/16 08:53, Christoffer Dall wrote:
> On Thu, May 12, 2016 at 07:52:38PM +0100, Andre Przywara wrote:
>> Hi,
>>
>> On 12/05/16 19:47, Christoffer Dall wrote:
>>> On Fri, May 06, 2016 at 11:46:00AM +0100, Andre Przywara wrote:
>>>> Using the VMCR accessors we provide access to GIC CPU interface state
>>>> to userland by wiring it up to the existing userland interface.
>>>> [Marc: move and make VMCR accessors static, streamline MMIO handlers]
>>>
>>> does this mean Marc did this and serves as credit or is it a lost
>>> reminder?
>>
>> It was meant as credit. I thought that is the usual annotation for this?
>>
> 
> I'm not sure if that's the usual way, I read it as a reminder, but it's
> not too important.  Mostly wanting to make sure we're not forgetting
> some todo item.
> 
>>>>
>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>>> ---
>>>> Changelog v2 .. v3:
>>>> - total rework, moving into vgic-mmio-v2.c
>>>> - move vmcr accessor wrapper functions into this file
>>>> - use the register description table for CPU i/f registers as well
>>>> - add RAZ/WI handling for the active priority registers
>>>> - streamline MMIO handler functions
>>>>
>>>>  virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
>>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 104 ++++++++++++++++++++++++++++++++++++
>>>>  virt/kvm/arm/vgic/vgic.h            |   2 +
>>>>  3 files changed, 107 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
>>>> index bb33af8..2122ff2 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
>>>> @@ -300,7 +300,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
>>>>  
>>>>  	switch (attr->group) {
>>>>  	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>>>> -		ret = -EINVAL;
>>>> +		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
>>>>  		break;
>>>>  	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>>>>  		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> index c453e6f..0060539 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> @@ -206,6 +206,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
>>>>  	}
>>>>  }
>>>>  
>>>> +static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
>>>> +{
>>>> +	if (kvm_vgic_global_state.type == VGIC_V2)
>>>> +		vgic_v2_set_vmcr(vcpu, vmcr);
>>>> +	else
>>>> +		vgic_v3_set_vmcr(vcpu, vmcr);
>>>> +}
>>>> +
>>>> +static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
>>>> +{
>>>> +	if (kvm_vgic_global_state.type == VGIC_V2)
>>>> +		vgic_v2_get_vmcr(vcpu, vmcr);
>>>> +	else
>>>> +		vgic_v3_get_vmcr(vcpu, vmcr);
>>>> +}
>>>> +
>>>> +#define GICC_ARCH_VERSION_V2	0x2
>>>> +
>>>> +/* These are for userland accesses only, there is no guest-facing emulation. */
>>>> +static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
>>>> +					   gpa_t addr, unsigned int len)
>>>> +{
>>>> +	struct vgic_vmcr vmcr;
>>>> +	u32 val;
>>>> +
>>>> +	vgic_get_vmcr(vcpu, &vmcr);
>>>> +
>>>> +	switch (addr & 0xff) {
>>>> +	case GIC_CPU_CTRL:
>>>> +		val = vmcr.ctlr;
>>>> +		break;
>>>> +	case GIC_CPU_PRIMASK:
>>>> +		val = vmcr.pmr;
>>>> +		break;
>>>> +	case GIC_CPU_BINPOINT:
>>>> +		val = vmcr.bpr;
>>>> +		break;
>>>> +	case GIC_CPU_ALIAS_BINPOINT:
>>>> +		val = vmcr.abpr;
>>>> +		break;
>>>> +	case GIC_CPU_IDENT:
>>>> +		val = ((PRODUCT_ID_KVM << 20) |
>>>> +		       (GICC_ARCH_VERSION_V2 << 16) |
>>>> +		       IMPLEMENTER_ARM);
>>>> +		break;
>>>> +	default:
>>>> +		return 0;
>>>> +	}
>>>> +
>>>> +	return extract_bytes(val, addr & 3, len);
>>>
>>> I don't think we allow anything than a full 32-bit aligned accesses
>>> from userspace - we shouldn't at least.
>>
>> Indeed - I think userland was always 32-bit only. And since last night
>> we even enforce this. So potentially there are more extract_bytes()
>> calls that can go.
>>
> Right.

So can I replace every call to extract_bytes() with just a "return val;"
for every register that allows 32-bit accesses only?
I think that's safe now, just checking ...

Cheers,
Andre.


From linux at armlinux.org.uk  Fri May 13 03:44:37 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Fri, 13 May 2016 11:44:37 +0100
Subject: imx-drm: regression due to commit 503fe87bd0a8 ("gpu: ipu-v3:
 Fix imx-ipuv3-crtc module autoloading")
In-Reply-To: <20160513123336.6996dd89@ipc1.ka-ro>
References: <20160513123336.6996dd89@ipc1.ka-ro>
Message-ID: <20160513104437.GT19428@n2100.arm.linux.org.uk>

On Fri, May 13, 2016 at 12:33:36PM +0200, Lothar Wa?mann wrote:
> I'm always very suspicious when seeing code moving of_node's from
> one device to another or assigning of_node's to platform devices that
> weren't instantiated via DT.

It's completely wrong to add an of_node to a device on the same bus
that already has a device with the same of_node - doing so means
that the bus matching code will match the same device driver to both
devices, which may not be what you want to happen.

Just don't do it, it's a bug waiting to happen.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From linux at armlinux.org.uk  Fri May 13 03:48:02 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Fri, 13 May 2016 11:48:02 +0100
Subject: [PATCH 0/3] Clean up svc mode register state
Message-ID: <20160513104802.GU19428@n2100.arm.linux.org.uk>

Three patches to clean up the saved register state for SW PAN:

* get rid of S_FRAME_SIZE, replacing it with PT_REGS_SIZE (which
  is what all cases of this constant actually was describing).
* provide svc_pt_regs to describe the SVC mode stack layout, which
  may contain the additional DACR register above the pt_regs.
* get rid of the horrid saved DACR access in __show_regs

 arch/arm/include/asm/assembler.h |  4 ++--
 arch/arm/include/asm/ptrace.h    | 10 ++++++++++
 arch/arm/kernel/asm-offsets.c    |  4 +++-
 arch/arm/kernel/entry-armv.S     | 12 ++++++------
 arch/arm/kernel/entry-common.S   |  2 +-
 arch/arm/kernel/entry-header.S   |  8 ++++----
 arch/arm/kernel/entry-v7m.S      |  2 +-
 arch/arm/kernel/process.c        |  2 +-
 8 files changed, 28 insertions(+), 16 deletions(-)

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From rmk+kernel at armlinux.org.uk  Fri May 13 03:49:02 2016
From: rmk+kernel at armlinux.org.uk (Russell King)
Date: Fri, 13 May 2016 11:49:02 +0100
Subject: [PATCH 2/3] ARM: introduce svc_pt_regs structure
In-Reply-To: <20160513104802.GU19428@n2100.arm.linux.org.uk>
References: <20160513104802.GU19428@n2100.arm.linux.org.uk>
Message-ID: <E1b1AeU-0005DK-6E@rmk-PC.arm.linux.org.uk>

Since the privileged mode pt_regs are an extended version of the saved
userland pt_regs, introduce a new svc_pt_regs structure to describe this
layout.

Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
---
 arch/arm/include/asm/assembler.h | 4 ++--
 arch/arm/include/asm/ptrace.h    | 8 ++++++++
 arch/arm/kernel/asm-offsets.c    | 2 ++
 arch/arm/kernel/entry-armv.S     | 4 ++--
 4 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 60d9c5471eb6..4eaea2173bf8 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -480,13 +480,13 @@ THUMB(	orr	\reg , \reg , #PSR_T_BIT	)
 	.macro	uaccess_save, tmp
 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
 	mrc	p15, 0, \tmp, c3, c0, 0
-	str	\tmp, [sp, #PT_REGS_SIZE]
+	str	\tmp, [sp, #SVC_DACR]
 #endif
 	.endm
 
 	.macro	uaccess_restore
 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
-	ldr	r0, [sp, #PT_REGS_SIZE]
+	ldr	r0, [sp, #SVC_DACR]
 	mcr	p15, 0, r0, c3, c0, 0
 #endif
 	.endm
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 51622ba7c4a6..5194cf79c90f 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -13,10 +13,18 @@
 #include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
+#include <linux/types.h>
+
 struct pt_regs {
 	unsigned long uregs[18];
 };
 
+struct svc_pt_regs {
+	struct pt_regs regs;
+	u32 dacr;
+	u32 unused;
+};
+
 #define user_mode(regs)	\
 	(((regs)->ARM_cpsr & 0xf) == 0)
 
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 2841c9980bcd..9a8ce342cd82 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -108,6 +108,8 @@ int main(void)
   DEFINE(S_PSR,			offsetof(struct pt_regs, ARM_cpsr));
   DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));
   DEFINE(PT_REGS_SIZE,		sizeof(struct pt_regs));
+  DEFINE(SVC_DACR,		offsetof(struct svc_pt_regs, dacr));
+  DEFINE(SVC_REGS_SIZE,		sizeof(struct svc_pt_regs));
   BLANK();
 #ifdef CONFIG_CACHE_L2X0
   DEFINE(L2X0_R_PHY_BASE,	offsetof(struct l2x0_regs, phy_base));
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index a6cb019d9920..0d6f5413be18 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -152,7 +152,7 @@ ENDPROC(__und_invalid)
 	.macro	svc_entry, stack_hole=0, trace=1, uaccess=1
  UNWIND(.fnstart		)
  UNWIND(.save {r0 - pc}		)
-	sub	sp, sp, #(PT_REGS_SIZE + 8 + \stack_hole - 4)
+	sub	sp, sp, #(SVC_REGS_SIZE + \stack_hole - 4)
 #ifdef CONFIG_THUMB2_KERNEL
  SPFIX(	str	r0, [sp]	)	@ temporarily saved
  SPFIX(	mov	r0, sp		)
@@ -167,7 +167,7 @@ ENDPROC(__und_invalid)
 	ldmia	r0, {r3 - r5}
 	add	r7, sp, #S_SP - 4	@ here for interlock avoidance
 	mov	r6, #-1			@  ""  ""      ""       ""
-	add	r2, sp, #(PT_REGS_SIZE + 8 + \stack_hole - 4)
+	add	r2, sp, #(SVC_REGS_SIZE + \stack_hole - 4)
  SPFIX(	addeq	r2, r2, #4	)
 	str	r3, [sp, #-4]!		@ save the "real" r0 copied
 					@ from the exception stack
-- 
2.1.0



From rmk+kernel at armlinux.org.uk  Fri May 13 03:49:07 2016
From: rmk+kernel at armlinux.org.uk (Russell King)
Date: Fri, 13 May 2016 11:49:07 +0100
Subject: [PATCH 3/3] ARM: get rid of horrible *(unsigned int *)(regs + 1)
In-Reply-To: <20160513104802.GU19428@n2100.arm.linux.org.uk>
References: <20160513104802.GU19428@n2100.arm.linux.org.uk>
Message-ID: <E1b1AeZ-0005DQ-9o@rmk-PC.arm.linux.org.uk>

Get rid of the horrible "*(unsigned int *)(regs + 1)" to get at the
parent context domain access register value, instead using the newly
introduced svc_pt_regs structure.

Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
---
 arch/arm/include/asm/ptrace.h | 2 ++
 arch/arm/kernel/process.c     | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 5194cf79c90f..0ef0093800f2 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -25,6 +25,8 @@ struct svc_pt_regs {
 	u32 unused;
 };
 
+#define to_svc_pt_regs(r) container_of(r, struct svc_pt_regs, regs)
+
 #define user_mode(regs)	\
 	(((regs)->ARM_cpsr & 0xf) == 0)
 
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 4adfb46e3ee9..05a5e44721a0 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -106,7 +106,7 @@ void __show_regs(struct pt_regs *regs)
 	if (user_mode(regs))
 		domain = DACR_UACCESS_ENABLE;
 	else
-		domain = *(unsigned int *)(regs + 1);
+		domain = to_svc_pt_regs(regs)->dacr;
 #else
 	domain = get_domain();
 #endif
-- 
2.1.0



From rmk+kernel at armlinux.org.uk  Fri May 13 03:48:57 2016
From: rmk+kernel at armlinux.org.uk (Russell King)
Date: Fri, 13 May 2016 11:48:57 +0100
Subject: [PATCH 1/3] ARM: rename S_FRAME_SIZE to PT_REGS_SIZE
In-Reply-To: <20160513104802.GU19428@n2100.arm.linux.org.uk>
References: <20160513104802.GU19428@n2100.arm.linux.org.uk>
Message-ID: <E1b1AeO-0005DE-W5@rmk-PC.arm.linux.org.uk>

S_FRAME_SIZE is no longer the size of the kernel stack frame, so this
name is misleading.  It is the size of the kernel pt_regs structure.
Name it so.

Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
---
 arch/arm/include/asm/assembler.h |  4 ++--
 arch/arm/kernel/asm-offsets.c    |  2 +-
 arch/arm/kernel/entry-armv.S     | 12 ++++++------
 arch/arm/kernel/entry-common.S   |  2 +-
 arch/arm/kernel/entry-header.S   |  8 ++++----
 arch/arm/kernel/entry-v7m.S      |  2 +-
 6 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index b2bc8e11471d..60d9c5471eb6 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -480,13 +480,13 @@ THUMB(	orr	\reg , \reg , #PSR_T_BIT	)
 	.macro	uaccess_save, tmp
 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
 	mrc	p15, 0, \tmp, c3, c0, 0
-	str	\tmp, [sp, #S_FRAME_SIZE]
+	str	\tmp, [sp, #PT_REGS_SIZE]
 #endif
 	.endm
 
 	.macro	uaccess_restore
 #ifdef CONFIG_CPU_SW_DOMAIN_PAN
-	ldr	r0, [sp, #S_FRAME_SIZE]
+	ldr	r0, [sp, #PT_REGS_SIZE]
 	mcr	p15, 0, r0, c3, c0, 0
 #endif
 	.endm
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 27d05813ff09..2841c9980bcd 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -107,7 +107,7 @@ int main(void)
   DEFINE(S_PC,			offsetof(struct pt_regs, ARM_pc));
   DEFINE(S_PSR,			offsetof(struct pt_regs, ARM_cpsr));
   DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));
-  DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
+  DEFINE(PT_REGS_SIZE,		sizeof(struct pt_regs));
   BLANK();
 #ifdef CONFIG_CACHE_L2X0
   DEFINE(L2X0_R_PHY_BASE,	offsetof(struct l2x0_regs, phy_base));
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index e2550500486d..a6cb019d9920 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -92,7 +92,7 @@
  * Invalid mode handlers
  */
 	.macro	inv_entry, reason
-	sub	sp, sp, #S_FRAME_SIZE
+	sub	sp, sp, #PT_REGS_SIZE
  ARM(	stmib	sp, {r1 - lr}		)
  THUMB(	stmia	sp, {r0 - r12}		)
  THUMB(	str	sp, [sp, #S_SP]		)
@@ -152,7 +152,7 @@ ENDPROC(__und_invalid)
 	.macro	svc_entry, stack_hole=0, trace=1, uaccess=1
  UNWIND(.fnstart		)
  UNWIND(.save {r0 - pc}		)
-	sub	sp, sp, #(S_FRAME_SIZE + 8 + \stack_hole - 4)
+	sub	sp, sp, #(PT_REGS_SIZE + 8 + \stack_hole - 4)
 #ifdef CONFIG_THUMB2_KERNEL
  SPFIX(	str	r0, [sp]	)	@ temporarily saved
  SPFIX(	mov	r0, sp		)
@@ -167,7 +167,7 @@ ENDPROC(__und_invalid)
 	ldmia	r0, {r3 - r5}
 	add	r7, sp, #S_SP - 4	@ here for interlock avoidance
 	mov	r6, #-1			@  ""  ""      ""       ""
-	add	r2, sp, #(S_FRAME_SIZE + 8 + \stack_hole - 4)
+	add	r2, sp, #(PT_REGS_SIZE + 8 + \stack_hole - 4)
  SPFIX(	addeq	r2, r2, #4	)
 	str	r3, [sp, #-4]!		@ save the "real" r0 copied
 					@ from the exception stack
@@ -366,17 +366,17 @@ ENDPROC(__fiq_abt)
 /*
  * User mode handlers
  *
- * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE
+ * EABI note: sp_svc is always 64-bit aligned here, so should PT_REGS_SIZE
  */
 
-#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7)
+#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (PT_REGS_SIZE & 7)
 #error "sizeof(struct pt_regs) must be a multiple of 8"
 #endif
 
 	.macro	usr_entry, trace=1, uaccess=1
  UNWIND(.fnstart	)
  UNWIND(.cantunwind	)	@ don't unwind the user space
-	sub	sp, sp, #S_FRAME_SIZE
+	sub	sp, sp, #PT_REGS_SIZE
  ARM(	stmib	sp, {r1 - r12}	)
  THUMB(	stmia	sp, {r0 - r12}	)
 
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 30a7228eaceb..10c3283d6c19 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -145,7 +145,7 @@ ENTRY(vector_swi)
 #ifdef CONFIG_CPU_V7M
 	v7m_exception_entry
 #else
-	sub	sp, sp, #S_FRAME_SIZE
+	sub	sp, sp, #PT_REGS_SIZE
 	stmia	sp, {r0 - r12}			@ Calling r0 - r12
  ARM(	add	r8, sp, #S_PC		)
  ARM(	stmdb	r8, {sp, lr}^		)	@ Calling sp, lr
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 0d22ad206d52..5e1d029147cb 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -90,7 +90,7 @@
 	@ Linux expects to have irqs off. Do it here before taking stack space
 	cpsid	i
 
-	sub	sp, #S_FRAME_SIZE-S_IP
+	sub	sp, #PT_REGS_SIZE-S_IP
 	stmdb	sp!, {r0-r11}
 
 	@ load saved r12, lr, return address and xPSR.
@@ -160,7 +160,7 @@
 	ldmia	sp!, {r0-r11}
 
 	@ restore main sp
-	add	sp, sp, #S_FRAME_SIZE-S_IP
+	add	sp, sp, #PT_REGS_SIZE-S_IP
 
 	cpsie	i
 	bx	lr
@@ -307,7 +307,7 @@
 	.endif
 	mov	r0, r0				@ ARMv5T and earlier require a nop
 						@ after ldm {}^
-	add	sp, sp, #\offset + S_FRAME_SIZE
+	add	sp, sp, #\offset + PT_REGS_SIZE
 	movs	pc, lr				@ return & move spsr_svc into cpsr
 #elif defined(CONFIG_CPU_V7M)
 	@ V7M restore.
@@ -334,7 +334,7 @@
 	.else
 	ldmdb	sp, {r0 - r12}			@ get calling r0 - r12
 	.endif
-	add	sp, sp, #S_FRAME_SIZE - S_SP
+	add	sp, sp, #PT_REGS_SIZE - S_SP
 	movs	pc, lr				@ return & move spsr_svc into cpsr
 #endif	/* !CONFIG_THUMB2_KERNEL */
 	.endm
diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S
index 907534f97053..abcf47848525 100644
--- a/arch/arm/kernel/entry-v7m.S
+++ b/arch/arm/kernel/entry-v7m.S
@@ -73,7 +73,7 @@ __irq_entry:
 	@ correctness they don't need to be restored. So only r8-r11 must be
 	@ restored here. The easiest way to do so is to restore r0-r7, too.
 	ldmia	sp!, {r0-r11}
-	add	sp, #S_FRAME_SIZE-S_IP
+	add	sp, #PT_REGS_SIZE-S_IP
 	cpsie	i
 	bx	lr
 ENDPROC(__irq_entry)
-- 
2.1.0



From ynorov at caviumnetworks.com  Fri May 13 03:51:15 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Fri, 13 May 2016 13:51:15 +0300
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160513092802.GA13400@localhost.localdomain>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
 <20160512134431.GB30205@yury-N73SV>
 <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
 <20160512142457.GC30205@yury-N73SV>
 <20160512152805.GJ11226@e104818-lin.cambridge.arm.com>
 <57358C2B.1010106@huawei.com>
 <20160513092802.GA13400@localhost.localdomain>
Message-ID: <20160513105115.GA16672@yury-N73SV>

On Fri, May 13, 2016 at 09:28:03AM +0000, Catalin Marinas wrote:
> 
> The discussion is mainly around whether USER_DS for 32-bit compat apps
> should be the same as USER_DS for native 32-bit apps. Even for native
> 32-bit kernels, we don't use STACK_TOP as addr_limit. A read/write from
> 0xffffffff would fail in both cases anyway. I think the LTP test doesn't
> even try to access such memory but only to probe the range validity (I
> haven't managed to build the latest LTP yet).

This fix lets me build it (on top of 7b3ef3b0b)
Of course, it's not 'official'. :)

---
 testcases/kernel/syscalls/fstatat/fstatat01.c  | 1 +
 testcases/kernel/syscalls/preadv/preadv.h      | 1 +
 testcases/kernel/syscalls/pwritev/pwritev.h    | 1 +
 testcases/kernel/syscalls/request_key/Makefile | 2 +-
 4 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/testcases/kernel/syscalls/fstatat/fstatat01.c b/testcases/kernel/syscalls/fstatat/fstatat01.c
index 128f6dd..6e23c9e 100644
--- a/testcases/kernel/syscalls/fstatat/fstatat01.c
+++ b/testcases/kernel/syscalls/fstatat/fstatat01.c
@@ -59,6 +59,7 @@ static const char *filenames[TEST_CASES];
 static const int expected_errno[] = { 0, 0, ENOTDIR, EBADF, EINVAL, 0 };
 static const int flags[] = { 0, 0, 0, 0, 9999, 0 };
 
+#define HAVE_FSTATAT
 #if !defined(HAVE_FSTATAT)
 #if (__NR_fstatat64 > 0)
 int fstatat(int dirfd, const char *filename, struct stat64 *statbuf, int flags)
diff --git a/testcases/kernel/syscalls/preadv/preadv.h b/testcases/kernel/syscalls/preadv/preadv.h
index f3ac30d..b001389 100644
--- a/testcases/kernel/syscalls/preadv/preadv.h
+++ b/testcases/kernel/syscalls/preadv/preadv.h
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "linux_syscall_numbers.h"
 
+#define HAVE_PREADV
 #if !defined(HAVE_PREADV)
 int preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
 {
diff --git a/testcases/kernel/syscalls/pwritev/pwritev.h b/testcases/kernel/syscalls/pwritev/pwritev.h
index ae9d999..2a4d188 100644
--- a/testcases/kernel/syscalls/pwritev/pwritev.h
+++ b/testcases/kernel/syscalls/pwritev/pwritev.h
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "linux_syscall_numbers.h"
 
+#define HAVE_PWRITEV
 #if !defined(HAVE_PWRITEV)
 int pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
 {
diff --git a/testcases/kernel/syscalls/request_key/Makefile b/testcases/kernel/syscalls/request_key/Makefile
index 9add429..2e8a37c 100644
--- a/testcases/kernel/syscalls/request_key/Makefile
+++ b/testcases/kernel/syscalls/request_key/Makefile
@@ -19,6 +19,6 @@ top_srcdir		?= ../../../..
 
 include $(top_srcdir)/include/mk/testcases.mk
 
-LDLIBS		+= $(KEYUTILS_LIBS)
+LDLIBS		+= $(lkeyutils)
 
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
-- 
2.5.0


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


From t-kristo at ti.com  Fri May 13 03:58:44 2016
From: t-kristo at ti.com (Tero Kristo)
Date: Fri, 13 May 2016 13:58:44 +0300
Subject: [PATCHv2 00/28] ARM: OMAP2+: hwmod module clock type support
In-Reply-To: <20160512233935.GN3492@codeaurora.org>
References: <1460632097-25727-1-git-send-email-t-kristo@ti.com>
 <20160512233935.GN3492@codeaurora.org>
Message-ID: <5735B364.9000504@ti.com>

On 13/05/16 02:39, Stephen Boyd wrote:
> On 04/14, Tero Kristo wrote:
>> Hi,
>>
>> v2 contains following changes in comparison to v1:
>>
>> - Patch ordering changed a bit, clk/ti, mach-omap2, dts patches are now
>>    mostly grouped together, with the exception of the introduction of
>>    clock helper API, which is needed by everything else. Please note
>>    that the ordering must be preserved between mach-omap2/clk-driver/dts
>>    to avoid boot problems.
>> - Dropped hwmod data removal patches for now, this allows booting with
>>    either new or old DTS data.
>> - Fixed a typo in the hwmod clock driver timeout handling, the comparison
>>    for timeout against ktime_us_delta was wrong causing too short
>>    timeouts, this was apparent with cpuidle enabled on OMAP4
>> - Added patch #6 to fetch hwmod main clock based on the hwmod name itself,
>>    if found, ignore main_clk / clkctrl setup for the hwmod
>> - Added patch #7 to fix issue in omap2 timer caused by patch #6, with
>>    dynamic parsing of main clock, the hwmod must be setup before attempting
>>    to access main_clk.
>
> What's the general design goal of this series? This cover letter
> is more like a change and test log instead of an overall argument
> for why the series should be merged so I'm left to piecing
> together the commit text from the 28 different patches. I suspect
> it's to get rid of DT_CLK macros and do something with hwmod in a
> more generic way, but that's all I got.

Sorry I think this was lost someone along the series, and looking back I 
did not explain it that well at any point either.

The major motivation of this series is to get rid of the hwmod database 
from kernel eventually, Tony is working on an interconnect driver which 
will provide most of the other functionality currently done by hwmod, 
but he is going to depend on the clkctrl part being done with this 
series. Another important aspect of the series is that hwmod clkctrl is 
now done with proper clock nodes, which provides multiple benefits like 
usecounting, better debugging capabilities, better hierarchy support etc.

-Tero



From gnurou at gmail.com  Fri May 13 03:59:11 2016
From: gnurou at gmail.com (Alexandre Courbot)
Date: Fri, 13 May 2016 19:59:11 +0900
Subject: [PATCH v9 1/2] gpio: mmio: add DT support for memory-mapped GPIOs
In-Reply-To: <4114007.EkZL1biBx8@debian64>
References: <cover.1462911225.git.chunkeey@googlemail.com>
 <2c0675cd6f67bd487105c46c38c72d49d84d4df8.1462911225.git.chunkeey@googlemail.com>
 <0a1ab2b6-b4c5-44d7-abb4-ce1e9da7e477@gmail.com> <4114007.EkZL1biBx8@debian64>
Message-ID: <CAAVeFu+kJk10FE0S9NMvbv1pXL=4sRHtLrRM_ApG-53MuxWVng@mail.gmail.com>

On Thu, May 12, 2016 at 9:07 PM, Christian Lamparter
<chunkeey at googlemail.com> wrote:
> On Thursday, May 12, 2016 07:26:32 PM Alexandre Courbot wrote:
>> On Wednesday, May 11, 2016 6:34:34 PM JST, Christian Lamparter wrote:
>> > From: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
>> >
>> > This patch adds support for defining memory-mapped GPIOs which
>> > are compatible with the existing gpio-mmio interface. The generic
>> > library provides support for many memory-mapped GPIO controllers
>> > that are found in various on-board FPGA and ASIC solutions that
>> > are used to control board's switches, LEDs, chip-selects,
>> > Ethernet/USB PHY power, etc.
>> >
>> > For setting GPIO's there are three configurations:
>>
>> s/GPIO's/GPIOs
> OK
>
>> >     1. single input/output register resource (named "dat"),
>> >     2. set/clear pair (named "set" and "clr"),
>> >     3. single output register resource and single input resource
>> >        ("set" and dat").
>> >
>> > The configuration is detected by which resources are present.
>> > For the single output register, this drives a 1 by setting a bit
>> > and a zero by clearing a bit.  For the set clr pair, this drives
>> > a 1 by setting a bit in the set register and clears it by setting
>> > a bit in the clear register. The configuration is detected by
>> > which resources are present.
>>
>> The last sentence of this paragraph repeats for first one.
> Ok
>
>> >
>> > For setting the GPIO direction, there are three configurations:
>> >     a. simple bidirectional GPIOs that requires no configuration.
>> >     b. an output direction register (named "dirout")
>> >        where a 1 bit indicates the GPIO is an output.
>> >     c. an input direction register (named "dirin")
>> >        where a 1 bit indicates the GPIO is an input.
>> >
>> > The first user for this binding is "wd,mbl-gpio".
>> >
>> > Reviewed-by: Andy Shevchenko <andy.shevchenko at gmail.com>
>> > Signed-off-by: ?lvaro Fern?ndez Rojas <noltari at gmail.com>
>> > Signed-off-by: Christian Lamparter <chunkeey at googlemail.com>
>> > ---
>> >  static void bgpio_write8(void __iomem *reg, unsigned long data)
>> >  {
>> > @@ -569,6 +571,58 @@ static void __iomem *bgpio_map(struct
>> > platform_device *pdev,
>> >     return devm_ioremap_resource(&pdev->dev, r);
>> >  }
>> >
>> > +#ifdef CONFIG_OF
>> > +static int bgpio_basic_mmio_parse_dt(struct platform_device *pdev,
>> > +                                struct bgpio_pdata *pdata,
>> > +                                unsigned long *flags)
>> > +{
>> > +   struct device *dev = &pdev->dev;
>> > +
>> > +   pdata->base = -1;
>> > +
>> > +   if (of_property_read_bool(dev->of_node, "no-output"))
>> > +           *flags |= BGPIOF_NO_OUTPUT;
>>
>> I don't think it is a good idea to add "generic" properties. Whether a
>> controller is capable of output or not should be determined by its
>> compatible string only, and not a vague property.
>
> Well, meet the gpios on the MBL. If you want to figure out how WD wired
> up these two GPIOs (one is input, the other output), I can sent you a
> built-yourself MBL kit. It just needs a 3,5" drive and a 12V 2A power
> plug with a standard 5.5mm plug.
>
>> > +
>> > +   return 0;
>> > +}
>> > +
>> > +static const struct of_device_id bgpio_of_match[] = {
>> > +   { .compatible = "wd,mbl-gpio", .data = bgpio_basic_mmio_parse_dt },
>>
>> Mmm cannot you determine whether your controller is capable of output or
>> not just from the compatible property here? If so, the
>> bgpio_basic_mmio_parse_dt seems to be unneeded. If not, then this is
>> dependent on the wd,mbl-gpio binding and should be renamed accordingly.
> Sadly I don't know of any method. The device has two GPIOs one at 0x4e0000000.
> The other one is at 0x4e0100000. The address tells me that there are two
> external chips connected to the EBC (memory bank - RAM, ROM and DMA chips
> go here according to IBM's documentations). Which is not the place you
> would expect peripherals.

Ok, if you have no way of figuring that out then this is legit.

>
>> > @@ -646,6 +709,7 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table);
>> >  static struct platform_driver bgpio_driver = {
>> >     .driver = {
>> >             .name = "basic-mmio-gpio",
>> > +           .of_match_table = of_match_ptr(bgpio_of_match),
>> >     },
>> >     .id_table = bgpio_id_table,
>> >     .probe = bgpio_pdev_probe,
>>
>> It seems to me that this patch does two things:
>>
>> 1) Add code to support device tree lookup
>> 2) Add support for "wd,mbl-gpio".
>>
>> If true, these two things should be in their own patches. You should also
>> have another patch that adds the DT bindings for "wd,mbl-gpio", so I would
>> do things in that order:
>
> The DT bindings have been merged. That's why I dropped it from the rebase.
>
>> 1/3: DT support for basic-mmio-gpio
> Sadly, adding the "basic-mmio-gpio" binding is not possible without a ACK from
> the device tree maintainers. They have voiced their concerns. I think this was
> your post of the discussion on it:
> <http://www.spinics.net/lists/devicetree/msg124613.html>
>
> That's why the series was updated around v5 and v6 to use the "wd,mbl-gpio"
> binding.
>
> So yes, I wanted to go this route in the beginning as well. But no go.
> If we find more devices we could have a "basic-mmio-gpio" class. But
> for now, we have to start somewhere.

Ah, I was not suggesting that you add a "basic-mmio-gpio" compatible
property, but that the first patch of the series should add the
infrastructure code required for "wd,mbl-gpio" and the drivers you are
moving to use it in 2/2. That way you separate the addition of support
code to the actual device support.

>> 2/3: DT bindings for "wd,mbl-gpio" (and have them validated by the DT
>> people - e.g. do you really need a "reg" property or is it here just to fit
>> with what bgpio_pdev_probe expects? More about this on 2/2)
>> 3/3: Support for "wd,mbl-gpio" in basic-mmio-gpio
> Yes, that would have been nice. And I agree it was the way to do it. But
> without the wd,mbl-gpio mapping I would add the bgpio_parse_dt function
> without any caller. (As I can't add the compatible = "basic-mmio-gpio", ...)

bgpio_parse_dt() is called from bgpio_pdev_probe(), so whether you
have the mapping or not should not matter, does it?

It's just that there is no reason to add support for WD-MBL in this
patch, and convert other drivers in the next - both are equal users of
the infrastructure code you are adding.

Note that my comments on the next patch suggest deeper changes to this
one - you may want to read them as well (I will ignore v9.1 for now).


From catalin.marinas at arm.com  Fri May 13 04:03:03 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 13 May 2016 12:03:03 +0100
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160513105115.GA16672@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
 <20160512134431.GB30205@yury-N73SV>
 <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
 <20160512142457.GC30205@yury-N73SV>
 <20160512152805.GJ11226@e104818-lin.cambridge.arm.com>
 <57358C2B.1010106@huawei.com>
 <20160513092802.GA13400@localhost.localdomain>
 <20160513105115.GA16672@yury-N73SV>
Message-ID: <20160513110302.GB27232@e104818-lin.cambridge.arm.com>

On Fri, May 13, 2016 at 01:51:15PM +0300, Yury Norov wrote:
> On Fri, May 13, 2016 at 09:28:03AM +0000, Catalin Marinas wrote:
> > The discussion is mainly around whether USER_DS for 32-bit compat apps
> > should be the same as USER_DS for native 32-bit apps. Even for native
> > 32-bit kernels, we don't use STACK_TOP as addr_limit. A read/write from
> > 0xffffffff would fail in both cases anyway. I think the LTP test doesn't
> > even try to access such memory but only to probe the range validity (I
> > haven't managed to build the latest LTP yet).
> 
> This fix lets me build it (on top of 7b3ef3b0b)
> Of course, it's not 'official'. :)
[...]
> --- a/testcases/kernel/syscalls/fstatat/fstatat01.c
> +++ b/testcases/kernel/syscalls/fstatat/fstatat01.c
> @@ -59,6 +59,7 @@ static const char *filenames[TEST_CASES];
>  static const int expected_errno[] = { 0, 0, ENOTDIR, EBADF, EINVAL, 0 };
>  static const int flags[] = { 0, 0, 0, 0, 9999, 0 };
>  
> +#define HAVE_FSTATAT
>  #if !defined(HAVE_FSTATAT)
>  #if (__NR_fstatat64 > 0)
>  int fstatat(int dirfd, const char *filename, struct stat64 *statbuf, int flags)
> diff --git a/testcases/kernel/syscalls/preadv/preadv.h b/testcases/kernel/syscalls/preadv/preadv.h
> index f3ac30d..b001389 100644
> --- a/testcases/kernel/syscalls/preadv/preadv.h
> +++ b/testcases/kernel/syscalls/preadv/preadv.h
> @@ -21,6 +21,7 @@
>  #include "config.h"
>  #include "linux_syscall_numbers.h"
>  
> +#define HAVE_PREADV
>  #if !defined(HAVE_PREADV)
>  int preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
>  {
> diff --git a/testcases/kernel/syscalls/pwritev/pwritev.h b/testcases/kernel/syscalls/pwritev/pwritev.h
> index ae9d999..2a4d188 100644
> --- a/testcases/kernel/syscalls/pwritev/pwritev.h
> +++ b/testcases/kernel/syscalls/pwritev/pwritev.h
> @@ -21,6 +21,7 @@
>  #include "config.h"
>  #include "linux_syscall_numbers.h"
>  
> +#define HAVE_PWRITEV
>  #if !defined(HAVE_PWRITEV)
>  int pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
>  {

I didn't need any of these defines as they are automatically generated
in include/config.h for AArch32. However, I need to run autoreconf to
generate the configure script prior to building (archlinuxarm
filesystem)

-- 
Catalin


From p.zabel at pengutronix.de  Fri May 13 04:04:12 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Fri, 13 May 2016 13:04:12 +0200
Subject: imx-drm: regression due to commit 503fe87bd0a8 ("gpu: ipu-v3:
 Fix imx-ipuv3-crtc module autoloading")
In-Reply-To: <20160513123336.6996dd89@ipc1.ka-ro>
References: <20160513123336.6996dd89@ipc1.ka-ro>
Message-ID: <1463137452.3544.5.camel@pengutronix.de>

Hi Lothar,

Am Freitag, den 13.05.2016, 12:33 +0200 schrieb Lothar Wa?mann:
> Hi,
> 
> the commit 503fe87bd0a8 ("gpu: ipu-v3: Fix imx-ipuv3-crtc module autoloading")
> indeed fixes the autoloading issue, but completely breaks the driver in
> non-modular mode (at least with the parallel-display driver I didn't
> yet check with the imx-ldb driver.
> Can anyone confirm that the imx-drm driver in current linux-next
> (next-20160512) works for them with any i.MX6 or i.MX53 board?

I have sent a patch: https://patchwork.kernel.org/patch/9081661/
that I'd appreciate your input on.

regards
Philipp



From mark.rutland at arm.com  Fri May 13 04:20:36 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Fri, 13 May 2016 12:20:36 +0100
Subject: [PATCH] arm64: enable CONFIG_SET_MODULE_RONX by default
Message-ID: <1463138436-5073-1-git-send-email-mark.rutland@arm.com>

The SET_MODULE_RONX protections are effectively the same as the
DEBUG_RODATA protections we enabled by default back in commit
57efac2f7108e325 ("arm64: enable CONFIG_DEBUG_RODATA by default"). It
seems unusual to have one but not the other.

As evidenced by the help text, the rationale appears to be that
SET_MODULE_RONX interacts poorly with tracing and patching, but both of
these make use of the insn framework, which takes SET_MODULE_RONX into
account. Any remaining issues are bugs which should be fixed regardless
of the default state of the option.

This patch enables DEBUG_SET_MODULE_RONX by default, and replaces the
help text with a new wording derived from the DEBUG_RODATA help text,
which better describes the functionality. Previously, the DEBUG_RODATA
entry was inconsistently indented with spaces, which are replaced with
tabs as with the other Kconfig entries.

Additionally, the wording of recommended defaults is made consistent for
all options. These are placed in a new paragraph, unquoted, as a full
sentence (with a period/full stop) as this appears to be the most common
form per $(git grep 'in doubt').

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Kees Cook <keescook at chromium.org>
Cc: Laura Abbott <labbott at fedoraproject.org>
Cc: Will Deacon <will.deacon at arm.com>
---
 arch/arm64/Kconfig.debug | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
index 710fde4..0cc758c 100644
--- a/arch/arm64/Kconfig.debug
+++ b/arch/arm64/Kconfig.debug
@@ -12,7 +12,8 @@ config ARM64_PTDUMP
 	  who are working in architecture specific areas of the kernel.
 	  It is probably not a good idea to enable this feature in a production
 	  kernel.
-	  If in doubt, say "N"
+
+	  If in doubt, say N.
 
 config PID_IN_CONTEXTIDR
 	bool "Write the current PID to the CONTEXTIDR register"
@@ -38,15 +39,15 @@ config ARM64_RANDOMIZE_TEXT_OFFSET
 	  value.
 
 config DEBUG_SET_MODULE_RONX
-        bool "Set loadable kernel module data as NX and text as RO"
-        depends on MODULES
-        help
-          This option helps catch unintended modifications to loadable
-          kernel module's text and read-only data. It also prevents execution
-          of module data. Such protection may interfere with run-time code
-          patching and dynamic kernel tracing - and they might also protect
-          against certain classes of kernel exploits.
-          If in doubt, say "N".
+	bool "Set loadable kernel module data as NX and text as RO"
+	depends on MODULES
+	default y
+	help
+	  Is this is set, kernel module text and rodata will be made read-only.
+	  This is to help catch accidental or malicious attempts to change the
+	  kernel's executable code.
+
+	  If in doubt, say Y.
 
 config DEBUG_RODATA
 	bool "Make kernel text and rodata read-only"
@@ -56,7 +57,7 @@ config DEBUG_RODATA
 	  is to help catch accidental or malicious attempts to change the
 	  kernel's executable code.
 
-	  If in doubt, say Y
+	  If in doubt, say Y.
 
 config DEBUG_ALIGN_RODATA
 	depends on DEBUG_RODATA
@@ -69,7 +70,7 @@ config DEBUG_ALIGN_RODATA
 	  alignment and potentially wasted space. Turn on this option if
 	  performance is more important than memory pressure.
 
-	  If in doubt, say N
+	  If in doubt, say N.
 
 source "drivers/hwtracing/coresight/Kconfig"
 
-- 
1.9.1



From jchandra at broadcom.com  Fri May 13 04:25:48 2016
From: jchandra at broadcom.com (Jayachandran C)
Date: Fri, 13 May 2016 16:55:48 +0530
Subject: [PATCH V7 08/11] pci, acpi: Support for ACPI based generic PCI
 host controller
In-Reply-To: <1462893601-8937-9-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-9-git-send-email-tn@semihalf.com>
Message-ID: <CAKc_7PVJmhiD8x=zw4N3sSDPD-jZz-wh8TPTuuTYEdxn3v78og@mail.gmail.com>

On Tue, May 10, 2016 at 8:49 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> This patch is going to implement generic PCI host controller for
> ACPI world, similar to what pci-host-generic.c driver does for DT world.
>
> All such drivers, which we have seen so far, were implemented within
> arch/ directory since they had some arch assumptions (x86 and ia64).
> However, they all are doing similar thing, so it makes sense to find
> some common code and abstract it into the generic driver.
>
> In order to handle PCI config space regions properly, we define new
> MCFG interface which does sanity checks on MCFG table and keeps its
> root pointer. User is able to lookup MCFG regions based on that root
> pointer and specified domain:bus_start:bus_end touple. We are using
> pci_mmcfg_late_init old prototype to avoid another function name.
>
> The implementation of pci_acpi_scan_root() looks up the MCFG entries
> and sets up a new mapping (regions are not mapped until host controller ask
> for it). Generic PCI functions are used for accessing config space.
> Driver selects PCI_ECAM and uses functions from drivers/pci/ecam.h
> to create and access ECAM mappings.
>
> As mentioned in Kconfig help section, ACPI_PCI_HOST_GENERIC choice
> should be made on a per-architecture basis.
>
> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
> ---
[....]

> diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
> index 1ad2176..1cccf57 100644
> --- a/drivers/pci/ecam.h
> +++ b/drivers/pci/ecam.h
> @@ -45,6 +45,11 @@ struct pci_config_window {
>                 void __iomem            *win;   /* 64-bit single mapping */
>                 void __iomem            **winp; /* 32-bit per bus mapping */
>         };
> +#ifdef CONFIG_ACPI_PCI_HOST_GENERIC
> +       struct acpi_device              *companion; /* ACPI companion device */
> +#endif
> +       int                             domain;
> +
>  };

Using struct pci_config_window to pass along domain and
companion looks bad.  I think there are two possible options
to do this better:

1. add a 'struct fwnode_handle *' or 'struct device *parent_dev'
   instead of the companion and domain fields above. In case of
   ACPI either of them can be used to get the acpi_device and
   both  domain and companion can be set from that.

2. make pci_config_window fully embeddable by moving allocation
   out of pci_ecam_create to its callers. Then it can be embedded
   into acpi_pci_generic_root_info, and container_of can be used
   to get acpi info from ->sysdata.

The first option should be easier to implement but the second may
be better on long run. I would leave it to the Bjorn or Rafael to
suggest which is preferred.

JC.


From shc_work at mail.ru  Fri May 13 04:26:26 2016
From: shc_work at mail.ru (Alexander Shiyan)
Date: Fri, 13 May 2016 14:26:26 +0300
Subject: [PATCH 1/3] ARM: clps711x: Reduce static map size
In-Reply-To: <1463138788-5390-1-git-send-email-shc_work@mail.ru>
References: <1463138788-5390-1-git-send-email-shc_work@mail.ru>
Message-ID: <1463138788-5390-2-git-send-email-shc_work@mail.ru>

Last CLPS711X CPU register is PLLR has 0xa5a8 address, so we can reduce
the map to 48k and align the end of the static at VMALLOC_START.

Signed-off-by: Alexander Shiyan <shc_work at mail.ru>
---
 arch/arm/include/debug/clps711x.S              | 4 ++--
 arch/arm/mach-clps711x/common.c                | 6 +++---
 arch/arm/mach-clps711x/include/mach/hardware.h | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/include/debug/clps711x.S b/arch/arm/include/debug/clps711x.S
index abe2254..c17ac5c 100644
--- a/arch/arm/include/debug/clps711x.S
+++ b/arch/arm/include/debug/clps711x.S
@@ -9,10 +9,10 @@
 
 #ifndef CONFIG_DEBUG_CLPS711X_UART2
 #define CLPS711X_UART_PADDR	(0x80000000 + 0x0000)
-#define CLPS711X_UART_VADDR	(0xfeff0000 + 0x0000)
+#define CLPS711X_UART_VADDR	(0xfeff4000 + 0x0000)
 #else
 #define CLPS711X_UART_PADDR	(0x80000000 + 0x1000)
-#define CLPS711X_UART_VADDR	(0xfeff0000 + 0x1000)
+#define CLPS711X_UART_VADDR	(0xfeff4000 + 0x1000)
 #endif
 
 #define SYSFLG		(0x0140)
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c
index 671acc5a..bf62211 100644
--- a/arch/arm/mach-clps711x/common.c
+++ b/arch/arm/mach-clps711x/common.c
@@ -37,9 +37,9 @@ static struct map_desc clps711x_io_desc[] __initdata = {
 	{
 		.virtual	= (unsigned long)CLPS711X_VIRT_BASE,
 		.pfn		= __phys_to_pfn(CLPS711X_PHYS_BASE),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE
-	}
+		.length		= 48 * SZ_1K,
+		.type		= MT_DEVICE,
+	},
 };
 
 void __init clps711x_map_io(void)
diff --git a/arch/arm/mach-clps711x/include/mach/hardware.h b/arch/arm/mach-clps711x/include/mach/hardware.h
index 833129c..cfd0e2c 100644
--- a/arch/arm/mach-clps711x/include/mach/hardware.h
+++ b/arch/arm/mach-clps711x/include/mach/hardware.h
@@ -24,7 +24,7 @@
 
 #include <mach/clps711x.h>
 
-#define CLPS711X_VIRT_BASE	IOMEM(0xfeff0000)
+#define CLPS711X_VIRT_BASE	IOMEM(0xfeff4000)
 
 #ifndef __ASSEMBLY__
 #define clps_readb(off)		readb(CLPS711X_VIRT_BASE + (off))
-- 
2.4.9



From shc_work at mail.ru  Fri May 13 04:26:25 2016
From: shc_work at mail.ru (Alexander Shiyan)
Date: Fri, 13 May 2016 14:26:25 +0300
Subject: [PATCH 0/3] ARM: clps711x: Initial DT support
Message-ID: <1463138788-5390-1-git-send-email-shc_work@mail.ru>

This small series of patches adds initial DT support for Cirrus Logic
ARMv4T processors.

Alexander Shiyan (3):
  ARM: clps711x: Reduce static map size
  ARM: clps711x: Add basic DT support
  ARM: dts: clps711x: Add basic Cirrus Logic CDB89712 Development board

 arch/arm/Kconfig                               |   2 +
 arch/arm/boot/dts/Makefile                     |   2 +
 arch/arm/boot/dts/clps711x-cdb89712.dts        |  56 +++++++
 arch/arm/boot/dts/clps711x.dtsi                | 201 +++++++++++++++++++++++++
 arch/arm/include/debug/clps711x.S              |   4 +-
 arch/arm/mach-clps711x/Kconfig                 |   7 +
 arch/arm/mach-clps711x/common.c                |  20 ++-
 arch/arm/mach-clps711x/devices.c               |   6 +
 arch/arm/mach-clps711x/devices.h               |   1 +
 arch/arm/mach-clps711x/include/mach/hardware.h |   2 +-
 10 files changed, 295 insertions(+), 6 deletions(-)
 create mode 100644 arch/arm/boot/dts/clps711x-cdb89712.dts
 create mode 100644 arch/arm/boot/dts/clps711x.dtsi

-- 
2.4.9



From shc_work at mail.ru  Fri May 13 04:26:27 2016
From: shc_work at mail.ru (Alexander Shiyan)
Date: Fri, 13 May 2016 14:26:27 +0300
Subject: [PATCH 2/3] ARM: clps711x: Add basic DT support
In-Reply-To: <1463138788-5390-1-git-send-email-shc_work@mail.ru>
References: <1463138788-5390-1-git-send-email-shc_work@mail.ru>
Message-ID: <1463138788-5390-3-git-send-email-shc_work@mail.ru>

This patch adds basic support to run Cirrus Logic ARMv4T CPUs
with device-tree support.

Signed-off-by: Alexander Shiyan <shc_work at mail.ru>
---
 arch/arm/Kconfig                 |  2 ++
 arch/arm/mach-clps711x/Kconfig   |  7 +++++++
 arch/arm/mach-clps711x/common.c  | 14 ++++++++++++++
 arch/arm/mach-clps711x/devices.c |  6 ++++++
 arch/arm/mach-clps711x/devices.h |  1 +
 5 files changed, 30 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index cdfa6c2..afc1eaf 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -357,10 +357,12 @@ config ARCH_CLPS711X
 	select ARCH_REQUIRE_GPIOLIB
 	select AUTO_ZRELADDR
 	select CLKSRC_MMIO
+	select CLKSRC_OF if OF
 	select COMMON_CLK
 	select CPU_ARM720T
 	select GENERIC_CLOCKEVENTS
 	select MFD_SYSCON
+	select OF_IRQ if OF
 	select SOC_BUS
 	help
 	  Support for Cirrus Logic 711x/721x/731x based boards.
diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
index f711498..3e11390 100644
--- a/arch/arm/mach-clps711x/Kconfig
+++ b/arch/arm/mach-clps711x/Kconfig
@@ -2,6 +2,13 @@ if ARCH_CLPS711X
 
 menu "CLPS711X/EP721X/EP731X Implementations"
 
+config MACH_CLPS711X_DT
+	bool "Device-tree support"
+	select USE_OF
+	help
+	  Select this if you want to experiment device-tree with
+	  ARMv4T Cirrus Logic chips.
+
 config ARCH_AUTCPU12
 	bool "AUTCPU12"
 	help
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c
index bf62211..df0fdf8 100644
--- a/arch/arm/mach-clps711x/common.c
+++ b/arch/arm/mach-clps711x/common.c
@@ -23,12 +23,14 @@
 #include <linux/init.h>
 #include <linux/sizes.h>
 
+#include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 
 #include <mach/hardware.h>
 
 #include "common.h"
+#include "devices.h"
 
 /*
  * This maps the generic CLPS711x registers
@@ -63,3 +65,15 @@ void clps711x_restart(enum reboot_mode mode, const char *cmd)
 {
 	soft_restart(0);
 }
+
+static const char *clps711x_dt_compat[] __initconst = {
+	"cirrus,clps711x",
+	NULL
+};
+
+DT_MACHINE_START(CLPS711X_DT, "Cirrus Logic CLPS711X (Device Tree Support)")
+	.dt_compat	= clps711x_dt_compat,
+	.map_io		= clps711x_map_io,
+	.init_late	= clps711x_devices_init_dt,
+	.restart	= clps711x_restart,
+MACHINE_END
diff --git a/arch/arm/mach-clps711x/devices.c b/arch/arm/mach-clps711x/devices.c
index 77a9617..9ba5095 100644
--- a/arch/arm/mach-clps711x/devices.c
+++ b/arch/arm/mach-clps711x/devices.c
@@ -147,3 +147,9 @@ void __init clps711x_devices_init(void)
 	clps711x_add_uart();
 	clps711x_soc_init();
 }
+
+void __init clps711x_devices_init_dt(void)
+{
+	clps711x_add_cpuidle();
+	clps711x_soc_init();
+};
diff --git a/arch/arm/mach-clps711x/devices.h b/arch/arm/mach-clps711x/devices.h
index a5efc17..47378cd 100644
--- a/arch/arm/mach-clps711x/devices.h
+++ b/arch/arm/mach-clps711x/devices.h
@@ -10,3 +10,4 @@
  */
 
 void clps711x_devices_init(void);
+void clps711x_devices_init_dt(void);
-- 
2.4.9



From shc_work at mail.ru  Fri May 13 04:26:28 2016
From: shc_work at mail.ru (Alexander Shiyan)
Date: Fri, 13 May 2016 14:26:28 +0300
Subject: [PATCH 3/3] ARM: dts: clps711x: Add basic Cirrus Logic CDB89712
 Development board
In-Reply-To: <1463138788-5390-1-git-send-email-shc_work@mail.ru>
References: <1463138788-5390-1-git-send-email-shc_work@mail.ru>
Message-ID: <1463138788-5390-4-git-send-email-shc_work@mail.ru>

This adds the Cirrus Logic CLPS711X DT template and support for
CDB89712 Development board.
http://www.cirrus.com/en/pubs/manual/cdb89712-2.pdf

Signed-off-by: Alexander Shiyan <shc_work at mail.ru>
---
 arch/arm/boot/dts/Makefile              |   2 +
 arch/arm/boot/dts/clps711x-cdb89712.dts |  56 +++++++++
 arch/arm/boot/dts/clps711x.dtsi         | 201 ++++++++++++++++++++++++++++++++
 3 files changed, 259 insertions(+)
 create mode 100644 arch/arm/boot/dts/clps711x-cdb89712.dts
 create mode 100644 arch/arm/boot/dts/clps711x.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 95c1923..69de1d5 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -104,6 +104,8 @@ dtb-$(CONFIG_ARCH_BERLIN) += \
 	berlin2q-marvell-dmp.dtb
 dtb-$(CONFIG_ARCH_BRCMSTB) += \
 	bcm7445-bcm97445svmb.dtb
+dtb-$(CONFIG_ARCH_CLPS711X) += \
+	clps711x-cdb89712.dtb
 dtb-$(CONFIG_ARCH_DAVINCI) += \
 	da850-enbw-cmc.dtb \
 	da850-evm.dtb
diff --git a/arch/arm/boot/dts/clps711x-cdb89712.dts b/arch/arm/boot/dts/clps711x-cdb89712.dts
new file mode 100644
index 0000000..eaffd7c
--- /dev/null
+++ b/arch/arm/boot/dts/clps711x-cdb89712.dts
@@ -0,0 +1,56 @@
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ */
+
+#include "clps711x.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Cirrus Logic CS89712 Development Board";
+	compatible = "cirrus,cdb89712", "cirrus,cs89712", "cirrus,clps711x";
+
+	memory {
+		reg = <0xc0000000 0x01000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		pd0 {
+			label = "diagnostic";
+			gpios = <&portd 0 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&bus {
+	flash: root at 00000000 {
+		compatible = "cfi-flash";
+		reg = <0 0x00000000 0x01000000>;
+		bank-width = <2>;
+		linux,mtd-name = "physmap-flash.0";
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+
+	boot: boot at 0x70000000 {
+		compatible = "cfi-flash";
+		reg = <7 0x00000000 0x00000080>;
+		bank-width = <2>;
+		linux,mtd-name = "physmap-flash.1";
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
+
+&uart1 {
+	cts-gpios = <&mctrl 0 GPIO_ACTIVE_LOW>;
+	dsr-gpios = <&mctrl 1 GPIO_ACTIVE_LOW>;
+	dcd-gpios = <&mctrl 2 GPIO_ACTIVE_LOW>;
+	rts-gpios = <&portb 1 GPIO_ACTIVE_LOW>;
+	rng-gpios = <&portb 2 GPIO_ACTIVE_LOW>;
+};
diff --git a/arch/arm/boot/dts/clps711x.dtsi b/arch/arm/boot/dts/clps711x.dtsi
new file mode 100644
index 0000000..791eeee
--- /dev/null
+++ b/arch/arm/boot/dts/clps711x.dtsi
@@ -0,0 +1,201 @@
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ */
+
+/dts-v1/;
+
+#include "skeleton.dtsi"
+
+#include <dt-bindings/clock/clps711x-clock.h>
+
+/ {
+	model = "Cirrus Logic CLPS711X";
+	compatible = "cirrus,clps711x";
+
+	aliases {
+		gpio0 = &porta;
+		gpio1 = &portb;
+		gpio2 = &portc;
+		gpio3 = &portd;
+		gpio4 = &porte;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		spi0 = &spi;
+		timer0 = &timer1;
+		timer1 = &timer2;
+	};
+
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			device_type = "cpu";
+			compatible = "arm,arm720t";
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		clks: clks at 80000000 {
+			#clock-cells = <1>;
+			compatible = "cirrus,clps711x-clk";
+			reg = <0x80000000 0xc000>;
+			startup-frequency = <73728000>;
+		};
+
+		intc: intc at 80000000 {
+			compatible = "cirrus,clps711x-intc";
+			reg = <0x80000000 0x4000>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		porta: gpio at 80000000 {
+			compatible = "cirrus,clps711x-gpio";
+			reg = <0x80000000 0x1 0x80000040 0x1>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		portb: gpio at 80000001 {
+			compatible = "cirrus,clps711x-gpio";
+			reg = <0x80000001 0x1 0x80000041 0x1>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		portc: gpio at 80000002 {
+			compatible = "cirrus,clps711x-gpio";
+			reg = <0x80000002 0x1 0x80000042 0x1>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			status = "disabled";
+		};
+
+		portd: gpio at 80000003 {
+			compatible = "cirrus,clps711x-gpio";
+			reg = <0x80000003 0x1 0x80000043 0x1>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		porte: gpio at 80000083 {
+			compatible = "cirrus,clps711x-gpio";
+			reg = <0x80000083 0x1 0x800000c3 0x1>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		syscon1: syscon at 80000100 {
+			compatible = "cirrus,clps711x-syscon1", "syscon";
+			reg = <0x80000100 0x80>;
+		};
+
+		bus: bus at 80000180 {
+			#address-cells = <2>;
+			#size-cells = <1>;
+			compatible = "cirrus,clps711x-bus", "simple-bus";
+			clocks = <&clks CLPS711X_CLK_BUS>;
+			reg = <0x80000180 0x80>;
+			ranges = <
+				0 0 0x00000000 0x10000000
+				1 0 0x10000000 0x10000000
+				2 0 0x20000000 0x10000000
+				3 0 0x30000000 0x10000000
+				4 0 0x40000000 0x10000000
+				5 0 0x50000000 0x10000000
+				6 0 0x60000000 0x0000c000
+				7 0 0x70000000 0x00000080
+			>;
+		};
+
+		fb: fb at 800002c0 {
+			compatible = "cirrus,clps711x-fb";
+			reg = <0x800002c0 0xd44>, <0x60000000 0xc000>;
+			clocks = <&clks CLPS711X_CLK_BUS>;
+			status = "disabled";
+		};
+
+		timer1: timer at 80000300 {
+			compatible = "cirrus,clps711x-timer";
+			reg = <0x80000300 0x4>;
+			clocks = <&clks CLPS711X_CLK_TIMER1>;
+			interrupts = <8>;
+		};
+
+		timer2: timer at 80000340 {
+			compatible = "cirrus,clps711x-timer";
+			reg = <0x80000340 0x4>;
+			clocks = <&clks CLPS711X_CLK_TIMER2>;
+			interrupts = <9>;
+		};
+
+		pwm: pwm at 80000400 {
+			compatible = "cirrus,clps711x-pwm";
+			reg = <0x80000400 0x4>;
+			clocks = <&clks CLPS711X_CLK_PWM>;
+			#pwm-cells = <1>;
+		};
+
+		uart1: uart at 80000480 {
+			compatible = "cirrus,clps711x-uart";
+			reg = <0x80000480 0x80>;
+			interrupts = <12 13>;
+			clocks = <&clks CLPS711X_CLK_UART>;
+			syscon = <&syscon1>;
+		};
+
+		spi: spi at 80000500 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "cirrus,clps711x-spi";
+			reg = <0x80000500 0x4>;
+			interrupts = <15>;
+			clocks = <&clks CLPS711X_CLK_SPI>;
+			status = "disabled";
+		};
+
+		syscon2: syscon at 80001100 {
+			compatible = "cirrus,clps711x-syscon2", "syscon";
+			reg = <0x80001100 0x80>;
+		};
+
+		uart2: uart at 80001480 {
+			compatible = "cirrus,clps711x-uart";
+			reg = <0x80001480 0x80>;
+			interrupts = <28 29>;
+			clocks = <&clks CLPS711X_CLK_UART>;
+			syscon = <&syscon2>;
+		};
+
+		dai: dai at 80002000 {
+			#sound-dai-cells = <0>;
+			compatible = "cirrus,clps711x-dai";
+			reg = <0x80002000 0x604>;
+			clocks = <&clks CLPS711X_CLK_PLL>;
+			clock-names = "pll";
+			interrupts = <32>;
+			status = "disabled";
+		};
+
+		syscon3: syscon at 80002200 {
+			compatible = "cirrus,clps711x-syscon3", "syscon";
+			reg = <0x80002200 0x40>;
+		};
+	};
+
+	mctrl: mctrl {
+		compatible = "cirrus,clps711x-mctrl-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+};
-- 
2.4.9



From rafael at kernel.org  Fri May 13 04:31:31 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Fri, 13 May 2016 13:31:31 +0200
Subject: [PATCH V7 08/11] pci, acpi: Support for ACPI based generic PCI
 host controller
In-Reply-To: <CAKc_7PVJmhiD8x=zw4N3sSDPD-jZz-wh8TPTuuTYEdxn3v78og@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-9-git-send-email-tn@semihalf.com>
 <CAKc_7PVJmhiD8x=zw4N3sSDPD-jZz-wh8TPTuuTYEdxn3v78og@mail.gmail.com>
Message-ID: <CAJZ5v0jov37JErfRqw1bAkJzkyoGn+BsZLNLR5N=J3ZYu203GQ@mail.gmail.com>

On Fri, May 13, 2016 at 1:25 PM, Jayachandran C <jchandra at broadcom.com> wrote:
> On Tue, May 10, 2016 at 8:49 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
>> This patch is going to implement generic PCI host controller for
>> ACPI world, similar to what pci-host-generic.c driver does for DT world.
>>
>> All such drivers, which we have seen so far, were implemented within
>> arch/ directory since they had some arch assumptions (x86 and ia64).
>> However, they all are doing similar thing, so it makes sense to find
>> some common code and abstract it into the generic driver.
>>
>> In order to handle PCI config space regions properly, we define new
>> MCFG interface which does sanity checks on MCFG table and keeps its
>> root pointer. User is able to lookup MCFG regions based on that root
>> pointer and specified domain:bus_start:bus_end touple. We are using
>> pci_mmcfg_late_init old prototype to avoid another function name.
>>
>> The implementation of pci_acpi_scan_root() looks up the MCFG entries
>> and sets up a new mapping (regions are not mapped until host controller ask
>> for it). Generic PCI functions are used for accessing config space.
>> Driver selects PCI_ECAM and uses functions from drivers/pci/ecam.h
>> to create and access ECAM mappings.
>>
>> As mentioned in Kconfig help section, ACPI_PCI_HOST_GENERIC choice
>> should be made on a per-architecture basis.
>>
>> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
>> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
>> ---
> [....]
>
>> diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
>> index 1ad2176..1cccf57 100644
>> --- a/drivers/pci/ecam.h
>> +++ b/drivers/pci/ecam.h
>> @@ -45,6 +45,11 @@ struct pci_config_window {
>>                 void __iomem            *win;   /* 64-bit single mapping */
>>                 void __iomem            **winp; /* 32-bit per bus mapping */
>>         };
>> +#ifdef CONFIG_ACPI_PCI_HOST_GENERIC
>> +       struct acpi_device              *companion; /* ACPI companion device */
>> +#endif
>> +       int                             domain;
>> +
>>  };
>
> Using struct pci_config_window to pass along domain and
> companion looks bad.  I think there are two possible options
> to do this better:
>
> 1. add a 'struct fwnode_handle *' or 'struct device *parent_dev'
>    instead of the companion and domain fields above. In case of
>    ACPI either of them can be used to get the acpi_device and
>    both  domain and companion can be set from that.
>
> 2. make pci_config_window fully embeddable by moving allocation
>    out of pci_ecam_create to its callers. Then it can be embedded
>    into acpi_pci_generic_root_info, and container_of can be used
>    to get acpi info from ->sysdata.
>
> The first option should be easier to implement but the second may
> be better on long run. I would leave it to the Bjorn or Rafael to
> suggest which is preferred.

Personally, I'd probably try to use fwnode_handle, but the second
option makes sense too in principle.


From sergei.shtylyov at cogentembedded.com  Fri May 13 04:38:29 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Fri, 13 May 2016 14:38:29 +0300
Subject: [PATCH 19/23] ARM: dts: marzen: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-20-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
 <1463126163-29423-20-git-send-email-geert+renesas@glider.be>
Message-ID: <9a8e0721-6489-f245-feda-e52badcdc557@cogentembedded.com>

Hello.

On 5/13/2016 10:55 AM, Geert Uytterhoeven wrote:

> Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
> Warning (unit_address_vs_reg): Node /fixedregulator at 0 has a unit name, but no reg property
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
> ---
>  arch/arm/boot/dts/r8a7779-marzen.dts | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/boot/dts/r8a7779-marzen.dts b/arch/arm/boot/dts/r8a7779-marzen.dts
> index b795da6f5503d224..d9f3dba882f01181 100644
> --- a/arch/arm/boot/dts/r8a7779-marzen.dts
> +++ b/arch/arm/boot/dts/r8a7779-marzen.dts
> @@ -28,12 +28,12 @@
>  		stdout-path = &scif2;
>  	};
>
> -	memory {
> +	memory at 60000000 {
>  		device_type = "memory";
>  		reg = <0x60000000 0x40000000>;
>  	};
>
> -	fixedregulator3v3: fixedregulator at 0 {
> +	fixedregulator3v3: fixedregulator3v3 {

    Could you drop "fixed" prefix from the name, while at it?

>  		compatible = "regulator-fixed";
>  		regulator-name = "fixed-3.3V";
>  		regulator-min-microvolt = <3300000>;

MBR, Sergei



From sergei.shtylyov at cogentembedded.com  Fri May 13 04:40:31 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Fri, 13 May 2016 14:40:31 +0300
Subject: [PATCH 18/23] ARM: dts: lager: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-19-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
 <1463126163-29423-19-git-send-email-geert+renesas@glider.be>
Message-ID: <749bd9bd-aeb9-49fe-b1f9-31da008ae696@cogentembedded.com>

On 5/13/2016 10:55 AM, Geert Uytterhoeven wrote:

> Warning (unit_address_vs_reg): Node /keyboard/button at 1 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /keyboard/button at 2 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /keyboard/button at 3 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /keyboard/button at 4 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /fixedregulator at 0 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /regulator at 1 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /regulator at 2 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /regulator at 3 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /regulator at 4 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /i2c at 8 has a unit name, but no reg property
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
> ---
>  arch/arm/boot/dts/r8a7790-lager.dts | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
> index 749ba02b6a53a9de..c01e27868083147a 100644
> --- a/arch/arm/boot/dts/r8a7790-lager.dts
> +++ b/arch/arm/boot/dts/r8a7790-lager.dts
[...]
> @@ -119,7 +119,7 @@
>  		};
>  	};
>
> -	fixedregulator3v3: fixedregulator at 0 {
> +	fixedregulator3v3: fixedregulator3v3 {

    Likewise, could you drop "fixed"?

[...]

MBR, Sergei



From tn at semihalf.com  Fri May 13 04:42:09 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Fri, 13 May 2016 13:42:09 +0200
Subject: [PATCH V7 08/11] pci, acpi: Support for ACPI based generic PCI
 host controller
In-Reply-To: <CAJZ5v0jov37JErfRqw1bAkJzkyoGn+BsZLNLR5N=J3ZYu203GQ@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-9-git-send-email-tn@semihalf.com>
 <CAKc_7PVJmhiD8x=zw4N3sSDPD-jZz-wh8TPTuuTYEdxn3v78og@mail.gmail.com>
 <CAJZ5v0jov37JErfRqw1bAkJzkyoGn+BsZLNLR5N=J3ZYu203GQ@mail.gmail.com>
Message-ID: <5735BD91.3020206@semihalf.com>



On 13.05.2016 13:31, Rafael J. Wysocki wrote:
> On Fri, May 13, 2016 at 1:25 PM, Jayachandran C <jchandra at broadcom.com> wrote:
>> On Tue, May 10, 2016 at 8:49 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
>>> This patch is going to implement generic PCI host controller for
>>> ACPI world, similar to what pci-host-generic.c driver does for DT world.
>>>
>>> All such drivers, which we have seen so far, were implemented within
>>> arch/ directory since they had some arch assumptions (x86 and ia64).
>>> However, they all are doing similar thing, so it makes sense to find
>>> some common code and abstract it into the generic driver.
>>>
>>> In order to handle PCI config space regions properly, we define new
>>> MCFG interface which does sanity checks on MCFG table and keeps its
>>> root pointer. User is able to lookup MCFG regions based on that root
>>> pointer and specified domain:bus_start:bus_end touple. We are using
>>> pci_mmcfg_late_init old prototype to avoid another function name.
>>>
>>> The implementation of pci_acpi_scan_root() looks up the MCFG entries
>>> and sets up a new mapping (regions are not mapped until host controller ask
>>> for it). Generic PCI functions are used for accessing config space.
>>> Driver selects PCI_ECAM and uses functions from drivers/pci/ecam.h
>>> to create and access ECAM mappings.
>>>
>>> As mentioned in Kconfig help section, ACPI_PCI_HOST_GENERIC choice
>>> should be made on a per-architecture basis.
>>>
>>> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
>>> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
>>> ---
>> [....]
>>
>>> diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
>>> index 1ad2176..1cccf57 100644
>>> --- a/drivers/pci/ecam.h
>>> +++ b/drivers/pci/ecam.h
>>> @@ -45,6 +45,11 @@ struct pci_config_window {
>>>                  void __iomem            *win;   /* 64-bit single mapping */
>>>                  void __iomem            **winp; /* 32-bit per bus mapping */
>>>          };
>>> +#ifdef CONFIG_ACPI_PCI_HOST_GENERIC
>>> +       struct acpi_device              *companion; /* ACPI companion device */
>>> +#endif
>>> +       int                             domain;
>>> +
>>>   };
>>
>> Using struct pci_config_window to pass along domain and
>> companion looks bad.  I think there are two possible options
>> to do this better:
>>
>> 1. add a 'struct fwnode_handle *' or 'struct device *parent_dev'
>>     instead of the companion and domain fields above. In case of
>>     ACPI either of them can be used to get the acpi_device and
>>     both  domain and companion can be set from that.
>>
>> 2. make pci_config_window fully embeddable by moving allocation
>>     out of pci_ecam_create to its callers. Then it can be embedded
>>     into acpi_pci_generic_root_info, and container_of can be used
>>     to get acpi info from ->sysdata.
>>
>> The first option should be easier to implement but the second may
>> be better on long run. I would leave it to the Bjorn or Rafael to
>> suggest which is preferred.
>
> Personally, I'd probably try to use fwnode_handle, but the second
> option makes sense too in principle.
>

Thanks for suggestions. I will try to use fwnode_handle

Tomasz


From wsa at the-dreams.de  Fri May 13 04:44:36 2016
From: wsa at the-dreams.de (Wolfram Sang)
Date: Fri, 13 May 2016 13:44:36 +0200
Subject: [PATCH V2 0/2] drivers: i2c: qup: Some misc fixes
In-Reply-To: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>
References: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <20160513114436.GH1778@katana>

On Fri, May 06, 2016 at 05:01:12PM +0530, Sricharan R wrote:
> One for fixing the bug with CONFIG_DEBUG_SG enabled and another
> to suspend the transfer for all errors instead of just for nack.

You haven't stated what was changed in V2.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160513/b5db5a4b/attachment.sig>

From peter.ujfalusi at ti.com  Fri May 13 04:45:34 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Fri, 13 May 2016 14:45:34 +0300
Subject: [PATCH v3 0/7] ARM/ASoC: OMAP3: Fix McBSP2/3 sidetone support
In-Reply-To: <20160512164201.GQ5995@atomide.com>
References: <1461927202-17677-1-git-send-email-peter.ujfalusi@ti.com>
 <69ff65ee-e5d1-09fb-fd91-8d7b4d8fdda4@ti.com>
 <20160512164201.GQ5995@atomide.com>
Message-ID: <f7af7b30-563a-0048-9696-6ad0125d8f68@ti.com>

On 05/12/16 19:42, Tony Lindgren wrote:
> * Peter Ujfalusi <peter.ujfalusi at ti.com> [160511 01:46]:
>> Tony, Paul,
>>
>> On 04/29/16 13:53, Peter Ujfalusi wrote:
>>> Hi,
>>>
>>> Based on the ongoing discussion on v2 (ARM: OMAP3: Fix McBSP2/3 hwmod setup for
>>> sidetone) I have dropped the removal of the sidetone hwmod and only corrected
>>> it. The series now includes all related changes needed to have correct sidetone
>>> support whenever we boot in legacy or in DT mode.
>>>
>>> This time the ASoC part have dependency on earlier patches so they can not be
>>> applied separately.
>>
>> How should we proceed from here? I don't want to start designing the ST
>> separation infrastructure which would be based on this series, but if there
>> are outstanding issues found on this, I would need to go back to the drawing
>> board.
>> The separation will be mostly new code and code shuffle in ASoC, but for
>> legacy I will need to build up something in arch as well, so I would need at
>> least one release cycle to start with things.
> 
> Well looks like we have all the acks, so I can apply these. We have
> not heard from Paul on this for a while, so let's wait few days for
> that.
> 
> Meanwhile, Mark wanted to fix the subject for one of the patches, care
> to repost that at least? Or the whole series with acks, could be a
> pull request too against v4.6-rc1 :)

Thanks, I'll wait for couple of days for Paul to review and I will prepare v4
and a pull request.

-- 
P?ter


From wsa at the-dreams.de  Fri May 13 04:47:17 2016
From: wsa at the-dreams.de (Wolfram Sang)
Date: Fri, 13 May 2016 13:47:17 +0200
Subject: [PATCH V2 1/2] drivers: i2c: qup: Fix broken dma when
 CONFIG_DEBUG_SG is enabled
In-Reply-To: <1462534274-28925-2-git-send-email-sricharan@codeaurora.org>
References: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>
 <1462534274-28925-2-git-send-email-sricharan@codeaurora.org>
Message-ID: <20160513114716.GI1778@katana>

On Fri, May 06, 2016 at 05:01:13PM +0530, Sricharan R wrote:
> With CONFIG_DEBUG_SG is enabled and when dma mode is used, below dump is seen, 
> 
> ------------[ cut here ]------------ 
> kernel BUG at include/linux/scatterlist.h:140! 
> Internal error: Oops - BUG: 0 [#1] PREEMPT SMP 
> Modules linked in: 
> CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.0-00459-g9f087b9-dirty #7 
> Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT) 
> task: ffffffc036868000 ti: ffffffc036870000 task.ti: ffffffc036870000 
> PC is at qup_sg_set_buf.isra.13+0x138/0x154 
> LR is at qup_sg_set_buf.isra.13+0x50/0x154 
> pc : [<ffffffc0005a0ed8>] lr : [<ffffffc0005a0df0>] pstate: 60000145 
> sp : ffffffc0368735c0 
> x29: ffffffc0368735c0 x28: ffffffc036873752 
> x27: ffffffc035233018 x26: ffffffc000c4e000 
> x25: 0000000000000000 x24: 0000000000000004 
> x23: 0000000000000000 x22: ffffffc035233668 
> x21: ffffff80004e3000 x20: ffffffc0352e0018 
> x19: 0000004000000000 x18: 0000000000000028 
> x17: 0000000000000004 x16: ffffffc0017a39c8 
> x15: 0000000000001cdf x14: ffffffc0019929d8 
> x13: ffffffc0352e0018 x12: 0000000000000000 
> x11: 0000000000000001 x10: 0000000000000001 
> x9 : ffffffc0012b2d70 x8 : ffffff80004e3000 
> x7 : 0000000000000018 x6 : 0000000030000000 
> x5 : ffffffc00199f018 x4 : ffffffc035233018 
> x3 : 0000000000000004 x2 : 00000000c0000000 
> x1 : 0000000000000003 x0 : 0000000000000000 
> 
> Process swapper/0 (pid: 1, stack limit = 0xffffffc036870020) 
> Stack: (0xffffffc0368735c0 to 0xffffffc036874000) 
> 
> Change allocation of sg buffers from dma_coherent memory to kzalloc 
> to fix the issue. 

This description describes what you do. But not why it is the correct
solution to the OOPS. The OOPS  neither describes it. Please add some
more explanation.

> 
> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> Reviewed-by: Andy Gross <andy.gross at linaro.org>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160513/800326b8/attachment.sig>

From wsa at the-dreams.de  Fri May 13 04:48:23 2016
From: wsa at the-dreams.de (Wolfram Sang)
Date: Fri, 13 May 2016 13:48:23 +0200
Subject: [PATCH V2 2/2] drivers: i2c: qup: Fix error handling
In-Reply-To: <1462534274-28925-3-git-send-email-sricharan@codeaurora.org>
References: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>
 <1462534274-28925-3-git-send-email-sricharan@codeaurora.org>
Message-ID: <20160513114823.GJ1778@katana>

On Fri, May 06, 2016 at 05:01:14PM +0530, Sricharan R wrote:
> Among the bus errors reported from the QUP_MASTER_STATUS register
> only NACK is considered and transfer gets suspended, while
> other errors are ignored. Correct this and suspend the transfer
> for other errors as well. This avoids unnessecary 'timeouts' which
> happens when waiting for events that would never happen when there
> is already an error condition on the bus.
> 
> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> Reviewed-by: Andy Gross <andy.gross at linaro.org>

Please check Documentation/i2c/fault-codes for proper fault codes.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160513/ddc2df3f/attachment-0001.sig>

From wsa at the-dreams.de  Fri May 13 04:50:21 2016
From: wsa at the-dreams.de (Wolfram Sang)
Date: Fri, 13 May 2016 13:50:21 +0200
Subject: [PATCH V2 2/2] drivers: i2c: qup: Fix error handling
In-Reply-To: <20160513114823.GJ1778@katana>
References: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>
 <1462534274-28925-3-git-send-email-sricharan@codeaurora.org>
 <20160513114823.GJ1778@katana>
Message-ID: <20160513115021.GK1778@katana>

On Fri, May 13, 2016 at 01:48:23PM +0200, Wolfram Sang wrote:
> On Fri, May 06, 2016 at 05:01:14PM +0530, Sricharan R wrote:
> > Among the bus errors reported from the QUP_MASTER_STATUS register
> > only NACK is considered and transfer gets suspended, while
> > other errors are ignored. Correct this and suspend the transfer
> > for other errors as well. This avoids unnessecary 'timeouts' which
> > happens when waiting for events that would never happen when there
> > is already an error condition on the bus.
> > 
> > Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> > Reviewed-by: Andy Gross <andy.gross at linaro.org>
> 
> Please check Documentation/i2c/fault-codes for proper fault codes.

And while we are here: NACK is not an error but a valid response. Can
you remove the dev_err related to that? Otherwise tools like i2cdetect
will probably flood your log.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160513/9cb5f28c/attachment.sig>

From christoffer.dall at linaro.org  Fri May 13 04:54:19 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 13 May 2016 13:54:19 +0200
Subject: [PATCH v3 47/55] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <5735B016.50207@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-48-git-send-email-andre.przywara@arm.com>
 <20160512184740.GM27623@cbox> <5734D0F6.9090406@arm.com>
 <20160513075323.GF27623@cbox> <5735B016.50207@arm.com>
Message-ID: <20160513115419.GH27623@cbox>

On Fri, May 13, 2016 at 11:44:38AM +0100, Andre Przywara wrote:
> Hi,
> 
> On 13/05/16 08:53, Christoffer Dall wrote:
> > On Thu, May 12, 2016 at 07:52:38PM +0100, Andre Przywara wrote:
> >> Hi,
> >>
> >> On 12/05/16 19:47, Christoffer Dall wrote:
> >>> On Fri, May 06, 2016 at 11:46:00AM +0100, Andre Przywara wrote:
> >>>> Using the VMCR accessors we provide access to GIC CPU interface state
> >>>> to userland by wiring it up to the existing userland interface.
> >>>> [Marc: move and make VMCR accessors static, streamline MMIO handlers]
> >>>
> >>> does this mean Marc did this and serves as credit or is it a lost
> >>> reminder?
> >>
> >> It was meant as credit. I thought that is the usual annotation for this?
> >>
> > 
> > I'm not sure if that's the usual way, I read it as a reminder, but it's
> > not too important.  Mostly wanting to make sure we're not forgetting
> > some todo item.
> > 
> >>>>
> >>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> >>>> ---
> >>>> Changelog v2 .. v3:
> >>>> - total rework, moving into vgic-mmio-v2.c
> >>>> - move vmcr accessor wrapper functions into this file
> >>>> - use the register description table for CPU i/f registers as well
> >>>> - add RAZ/WI handling for the active priority registers
> >>>> - streamline MMIO handler functions
> >>>>
> >>>>  virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
> >>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 104 ++++++++++++++++++++++++++++++++++++
> >>>>  virt/kvm/arm/vgic/vgic.h            |   2 +
> >>>>  3 files changed, 107 insertions(+), 1 deletion(-)
> >>>>
> >>>> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> >>>> index bb33af8..2122ff2 100644
> >>>> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> >>>> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> >>>> @@ -300,7 +300,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
> >>>>  
> >>>>  	switch (attr->group) {
> >>>>  	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> >>>> -		ret = -EINVAL;
> >>>> +		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
> >>>>  		break;
> >>>>  	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> >>>>  		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
> >>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >>>> index c453e6f..0060539 100644
> >>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >>>> @@ -206,6 +206,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
> >>>>  	}
> >>>>  }
> >>>>  
> >>>> +static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> >>>> +{
> >>>> +	if (kvm_vgic_global_state.type == VGIC_V2)
> >>>> +		vgic_v2_set_vmcr(vcpu, vmcr);
> >>>> +	else
> >>>> +		vgic_v3_set_vmcr(vcpu, vmcr);
> >>>> +}
> >>>> +
> >>>> +static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> >>>> +{
> >>>> +	if (kvm_vgic_global_state.type == VGIC_V2)
> >>>> +		vgic_v2_get_vmcr(vcpu, vmcr);
> >>>> +	else
> >>>> +		vgic_v3_get_vmcr(vcpu, vmcr);
> >>>> +}
> >>>> +
> >>>> +#define GICC_ARCH_VERSION_V2	0x2
> >>>> +
> >>>> +/* These are for userland accesses only, there is no guest-facing emulation. */
> >>>> +static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
> >>>> +					   gpa_t addr, unsigned int len)
> >>>> +{
> >>>> +	struct vgic_vmcr vmcr;
> >>>> +	u32 val;
> >>>> +
> >>>> +	vgic_get_vmcr(vcpu, &vmcr);
> >>>> +
> >>>> +	switch (addr & 0xff) {
> >>>> +	case GIC_CPU_CTRL:
> >>>> +		val = vmcr.ctlr;
> >>>> +		break;
> >>>> +	case GIC_CPU_PRIMASK:
> >>>> +		val = vmcr.pmr;
> >>>> +		break;
> >>>> +	case GIC_CPU_BINPOINT:
> >>>> +		val = vmcr.bpr;
> >>>> +		break;
> >>>> +	case GIC_CPU_ALIAS_BINPOINT:
> >>>> +		val = vmcr.abpr;
> >>>> +		break;
> >>>> +	case GIC_CPU_IDENT:
> >>>> +		val = ((PRODUCT_ID_KVM << 20) |
> >>>> +		       (GICC_ARCH_VERSION_V2 << 16) |
> >>>> +		       IMPLEMENTER_ARM);
> >>>> +		break;
> >>>> +	default:
> >>>> +		return 0;
> >>>> +	}
> >>>> +
> >>>> +	return extract_bytes(val, addr & 3, len);
> >>>
> >>> I don't think we allow anything than a full 32-bit aligned accesses
> >>> from userspace - we shouldn't at least.
> >>
> >> Indeed - I think userland was always 32-bit only. And since last night
> >> we even enforce this. So potentially there are more extract_bytes()
> >> calls that can go.
> >>
> > Right.
> 
> So can I replace every call to extract_bytes() with just a "return val;"
> for every register that allows 32-bit accesses only?
> I think that's safe now, just checking ...

yes, I think the way we do it now, you simply return val (asuming you
build that variable at the right offset, even for byte accesses).

The only exception is for 32-bit accesses to 64-bit registers, where you
have to return either the upper or lower 32-bits.  I think you can still
use extract_bytes() there should you be so inclined.

-Christoffer



From ard.biesheuvel at linaro.org  Fri May 13 05:00:09 2016
From: ard.biesheuvel at linaro.org (Ard Biesheuvel)
Date: Fri, 13 May 2016 14:00:09 +0200
Subject: [PATCH] arm64: enable CONFIG_SET_MODULE_RONX by default
In-Reply-To: <1463138436-5073-1-git-send-email-mark.rutland@arm.com>
References: <1463138436-5073-1-git-send-email-mark.rutland@arm.com>
Message-ID: <CAKv+Gu_uofTP9df8wk1MT3eajebzUcbKeEaamO3yRBDDsyCuGg@mail.gmail.com>

On 13 May 2016 at 13:20, Mark Rutland <mark.rutland at arm.com> wrote:
> The SET_MODULE_RONX protections are effectively the same as the
> DEBUG_RODATA protections we enabled by default back in commit
> 57efac2f7108e325 ("arm64: enable CONFIG_DEBUG_RODATA by default"). It
> seems unusual to have one but not the other.
>
> As evidenced by the help text, the rationale appears to be that
> SET_MODULE_RONX interacts poorly with tracing and patching, but both of
> these make use of the insn framework, which takes SET_MODULE_RONX into
> account. Any remaining issues are bugs which should be fixed regardless
> of the default state of the option.
>
> This patch enables DEBUG_SET_MODULE_RONX by default, and replaces the
> help text with a new wording derived from the DEBUG_RODATA help text,
> which better describes the functionality. Previously, the DEBUG_RODATA
> entry was inconsistently indented with spaces, which are replaced with
> tabs as with the other Kconfig entries.
>
> Additionally, the wording of recommended defaults is made consistent for
> all options. These are placed in a new paragraph, unquoted, as a full
> sentence (with a period/full stop) as this appears to be the most common
> form per $(git grep 'in doubt').
>
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Kees Cook <keescook at chromium.org>
> Cc: Laura Abbott <labbott at fedoraproject.org>
> Cc: Will Deacon <will.deacon at arm.com>

Acked-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>

> ---
>  arch/arm64/Kconfig.debug | 25 +++++++++++++------------
>  1 file changed, 13 insertions(+), 12 deletions(-)
>
> diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
> index 710fde4..0cc758c 100644
> --- a/arch/arm64/Kconfig.debug
> +++ b/arch/arm64/Kconfig.debug
> @@ -12,7 +12,8 @@ config ARM64_PTDUMP
>           who are working in architecture specific areas of the kernel.
>           It is probably not a good idea to enable this feature in a production
>           kernel.
> -         If in doubt, say "N"
> +
> +         If in doubt, say N.
>
>  config PID_IN_CONTEXTIDR
>         bool "Write the current PID to the CONTEXTIDR register"
> @@ -38,15 +39,15 @@ config ARM64_RANDOMIZE_TEXT_OFFSET
>           value.
>
>  config DEBUG_SET_MODULE_RONX
> -        bool "Set loadable kernel module data as NX and text as RO"
> -        depends on MODULES
> -        help
> -          This option helps catch unintended modifications to loadable
> -          kernel module's text and read-only data. It also prevents execution
> -          of module data. Such protection may interfere with run-time code
> -          patching and dynamic kernel tracing - and they might also protect
> -          against certain classes of kernel exploits.
> -          If in doubt, say "N".
> +       bool "Set loadable kernel module data as NX and text as RO"
> +       depends on MODULES
> +       default y
> +       help
> +         Is this is set, kernel module text and rodata will be made read-only.
> +         This is to help catch accidental or malicious attempts to change the
> +         kernel's executable code.
> +
> +         If in doubt, say Y.
>
>  config DEBUG_RODATA
>         bool "Make kernel text and rodata read-only"
> @@ -56,7 +57,7 @@ config DEBUG_RODATA
>           is to help catch accidental or malicious attempts to change the
>           kernel's executable code.
>
> -         If in doubt, say Y
> +         If in doubt, say Y.
>
>  config DEBUG_ALIGN_RODATA
>         depends on DEBUG_RODATA
> @@ -69,7 +70,7 @@ config DEBUG_ALIGN_RODATA
>           alignment and potentially wasted space. Turn on this option if
>           performance is more important than memory pressure.
>
> -         If in doubt, say N
> +         If in doubt, say N.
>
>  source "drivers/hwtracing/coresight/Kconfig"
>
> --
> 1.9.1
>


From arnd at arndb.de  Fri May 13 05:00:35 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 13 May 2016 14:00:35 +0200
Subject: [PATCH 3/3] ARM: dts: clps711x: Add basic Cirrus Logic CDB89712
 Development board
In-Reply-To: <1463138788-5390-4-git-send-email-shc_work@mail.ru>
References: <1463138788-5390-1-git-send-email-shc_work@mail.ru>
 <1463138788-5390-4-git-send-email-shc_work@mail.ru>
Message-ID: <9407200.bOeiVUkGKT@wuerfel>

On Friday 13 May 2016 14:26:28 Alexander Shiyan wrote:
> +&bus {
> +	flash: root at 00000000 {
> +		compatible = "cfi-flash";
> +		reg = <0 0x00000000 0x01000000>;
> +		bank-width = <2>;
> +		linux,mtd-name = "physmap-flash.0";
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +	};

I've never seen the linux,mtd-name property before, but I think it's
meant to refer to the name of the flash chip, not the
name of the linux device.

> +	aliases {
> +		gpio0 = &porta;
> +		gpio1 = &portb;
> +		gpio2 = &portc;
> +		gpio3 = &portd;
> +		gpio4 = &porte;
> +		serial0 = &uart1;
> +		serial1 = &uart2;
> +		spi0 = &spi;
> +		timer0 = &timer1;
> +		timer1 = &timer2;
> +	};

Please move this into the .dts file: not all boards necessarily have
all of the above.

> +	soc {
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		compatible = "simple-bus";
> +		interrupt-parent = <&intc>;
> +		ranges;

All child devices seem to be in the 0x80000000-0x90000000
range, maybe set the ranges property accordingly?

> +		clks: clks at 80000000 {
> +			#clock-cells = <1>;
> +			compatible = "cirrus,clps711x-clk";
> +			reg = <0x80000000 0xc000>;
> +			startup-frequency = <73728000>;
> +		};

Please fix the compatible strings for all devices to not
have 'x' for wildcards. Normally you'd use the name of hte
first chip to have this particular IP block.

> +		intc: intc at 80000000 {
> +			compatible = "cirrus,clps711x-intc";
> +			reg = <0x80000000 0x4000>;
> +			interrupt-controller;
> +			#interrupt-cells = <1>;
> +		};

Better make the register ranges non-overlapping. This appears
to start at the same place as the 'clks' node.

> +		porta: gpio at 80000000 {
> +			compatible = "cirrus,clps711x-gpio";
> +			reg = <0x80000000 0x1 0x80000040 0x1>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		portb: gpio at 80000001 {
> +			compatible = "cirrus,clps711x-gpio";
> +			reg = <0x80000001 0x1 0x80000041 0x1>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		portc: gpio at 80000002 {
> +			compatible = "cirrus,clps711x-gpio";
> +			reg = <0x80000002 0x1 0x80000042 0x1>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +			status = "disabled";
> +		};
> +
> +		portd: gpio at 80000003 {
> +			compatible = "cirrus,clps711x-gpio";
> +			reg = <0x80000003 0x1 0x80000043 0x1>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};

These are all just single bytes. My guess is that there is
actually one IP block that contains all the gpios, not
four identical blocks.

> +		bus: bus at 80000180 {
> +			#address-cells = <2>;
> +			#size-cells = <1>;
> +			compatible = "cirrus,clps711x-bus", "simple-bus";
> +			clocks = <&clks CLPS711X_CLK_BUS>;
> +			reg = <0x80000180 0x80>;

If it has registers, it's not a 'simple-bus'. Is this an external
bus controller perhaps?

	Arnd


From jszhang at marvell.com  Fri May 13 04:57:30 2016
From: jszhang at marvell.com (Jisheng Zhang)
Date: Fri, 13 May 2016 19:57:30 +0800
Subject: [PATCH 2/2] net: pxa168_eth: Use dma_wmb/rmb where appropriate
In-Reply-To: <1463140650-7038-1-git-send-email-jszhang@marvell.com>
References: <1463140650-7038-1-git-send-email-jszhang@marvell.com>
Message-ID: <1463140650-7038-3-git-send-email-jszhang@marvell.com>

Update the pxa168_eth driver to use the dma_rmb/wmb calls instead of the
full barriers in order to improve performance: reduced 97ns/39ns on
average in tx/rx path on Marvell BG4CT platform.

Signed-off-by: Jisheng Zhang <jszhang at marvell.com>
---
 drivers/net/ethernet/marvell/pxa168_eth.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index db774e3..728a115 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -342,9 +342,9 @@ static void rxq_refill(struct net_device *dev)
 		pep->rx_skb[used_rx_desc] = skb;
 
 		/* Return the descriptor to DMA ownership */
-		wmb();
+		dma_wmb();
 		p_used_rx_desc->cmd_sts = BUF_OWNED_BY_DMA | RX_EN_INT;
-		wmb();
+		dma_wmb();
 
 		/* Move the used descriptor pointer to the next descriptor */
 		pep->rx_used_desc_q = (used_rx_desc + 1) % pep->rx_ring_size;
@@ -794,7 +794,7 @@ static int rxq_process(struct net_device *dev, int budget)
 		rx_used_desc = pep->rx_used_desc_q;
 		rx_desc = &pep->p_rx_desc_area[rx_curr_desc];
 		cmd_sts = rx_desc->cmd_sts;
-		rmb();
+		dma_rmb();
 		if (cmd_sts & (BUF_OWNED_BY_DMA))
 			break;
 		skb = pep->rx_skb[rx_curr_desc];
@@ -1289,7 +1289,7 @@ static int pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	skb_tx_timestamp(skb);
 
-	wmb();
+	dma_wmb();
 	desc->cmd_sts = BUF_OWNED_BY_DMA | TX_GEN_CRC | TX_FIRST_DESC |
 			TX_ZERO_PADDING | TX_LAST_DESC | TX_EN_INT;
 	wmb();
-- 
2.8.1



From jszhang at marvell.com  Fri May 13 04:57:29 2016
From: jszhang at marvell.com (Jisheng Zhang)
Date: Fri, 13 May 2016 19:57:29 +0800
Subject: [PATCH 1/2] net: pxa168_eth: use {readl|writel}_relaxed instead of
 readl/writel
In-Reply-To: <1463140650-7038-1-git-send-email-jszhang@marvell.com>
References: <1463140650-7038-1-git-send-email-jszhang@marvell.com>
Message-ID: <1463140650-7038-2-git-send-email-jszhang@marvell.com>

Since appropriate memory barriers are already there, use the relaxed
version to improve performance a bit.

Signed-off-by: Jisheng Zhang <jszhang at marvell.com>
---
 drivers/net/ethernet/marvell/pxa168_eth.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index c442f6a..db774e3 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -286,12 +286,12 @@ static int pxa168_eth_stop(struct net_device *dev);
 
 static inline u32 rdl(struct pxa168_eth_private *pep, int offset)
 {
-	return readl(pep->base + offset);
+	return readl_relaxed(pep->base + offset);
 }
 
 static inline void wrl(struct pxa168_eth_private *pep, int offset, u32 data)
 {
-	writel(data, pep->base + offset);
+	writel_relaxed(data, pep->base + offset);
 }
 
 static void abort_dma(struct pxa168_eth_private *pep)
-- 
2.8.1



From jszhang at marvell.com  Fri May 13 04:57:28 2016
From: jszhang at marvell.com (Jisheng Zhang)
Date: Fri, 13 May 2016 19:57:28 +0800
Subject: [PATCH 0/2] net: pxa168_eth: improve performance
Message-ID: <1463140650-7038-1-git-send-email-jszhang@marvell.com>

This series is to improve the pxa168_eth driver performance by using
{readl|writel}_relaxed or appropriate memory barriers.

Jisheng Zhang (2):
  net: pxa168_eth: use {readl|writel}_relaxed instead of readl/writel
  net: pxa168_eth: Use dma_wmb/rmb where appropriate

 drivers/net/ethernet/marvell/pxa168_eth.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

-- 
2.8.1



From robin.murphy at arm.com  Fri May 13 05:03:00 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Fri, 13 May 2016 13:03:00 +0100
Subject: [PATCH v3 00/27] ARM: dts: exynos: Add initial support for Odroid
 XU
In-Reply-To: <1462910970-1812-1-git-send-email-krzk@kernel.org>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
Message-ID: <5735C274.50504@arm.com>

Hi Krzysztof,

On 10/05/16 21:09, Krzysztof Kozlowski wrote:
> Hi,
>
> Patchset adds necessary clocks, reorganizes existing stuff and finally
> adds Odroid XU support.
>
>
> Changes since v2
> ================
> 1. Got global-ack from Stephen for the clock changes. I think merging
>     everything through arm-soc might be the easiest but:
>     a. In such case I will prepare a tag with clock changes,
>     b. Anyway I will wait for response from Sylwester and Tomasz.
> 2. Applied comments from Javier and added his Reviewed-by.
> 3. Patch 22: added ack from Rob.
> 4. Minor improvements in existing patches.
> 5. Five new patches at the end: 23-27 (not reviewed yet).
>     Some of them could be squashed with existing ones but existing
>     changes got reviews. Although the final Odroid XU DTS works fine but
>     in general this is still work-in-progress so I suspect it will grow.
>     I am releasing it early following Linux concept. :)
>
> Patchset is available at my private repo @github:
> https://github.com/krzk/linux.git for-next/odroid-xu-v3

Since I have one of these gathering dust on my desk, it's really cool to 
see this series, thanks!

I've successfully booted that branch to a filesystem on SD card, but USB 
clearly isn't quite right - the USB 2.0 hub is powered up, but only the 
bottom right port will actually enumerate devices; the ethernet is 
nowhere to be seen. However, if I drop into the bootloader and do a "usb 
start" beforehand, it all keeps working into the kernel. As for the USB 
3.0, though, the ports report over-current conditions shortly after the 
XHCI probe despite having nothing plugged in :(

Robin.

> (previous version is in for-next/odroid-xu-v2 branch, if someone would
> like to compare them)
>
>
> Changes since v1
> ================
> 1. A lot of new patches.
> 2. Removed some TODO notes (eMMC 4.5 so no RCLK pin).
> 3. New clocks, more reorganization.
> 4. New common DTSI: exynos54xx.dtsi. I know, it is getting more
>     and more complicated but this might help removing duplications
>     and keeping everything under control.
>
>
>
> Merging strategy
> ================
> Complicated! The clock dt-bindings and driver changes can go to clock
> tree. However there are three DTS patches in the middle.
> a. This has to go in before adding "fin_pll_new" to clock driver:
>     - [PATCH v2 03/22] ARM: dts: exynos: Add fin_pll node for clock driver
>
> b. This should go in before renaming "fin_pll_new" back to original name:
>     - [PATCH v2 05/22] ARM: dts: exynos: Switch MCT node to a new fin_pll clock
>     - [PATCH v2 06/22] ARM: dts: exynos: Remove old fixed-clock provider on SMDK5410
>
> The order of patches in the patchset is really how it should go in
> to reduce any bisectability glitches.
>
>
> Best regards,
> Krzysztof
>
>
> Krzysztof Kozlowski (27):
>    dt-bindings: clock: Add license and reformat Exynos5410 clock IDs
>    dt-bindings: clock: Add PWM and USB clock IDs to Exynos5410
>    ARM: dts: exynos: Add fin_pll node for clock driver
>    clk: samsung: exynos5410: Provide fin_pll external fixed clock
>    ARM: dts: exynos: Switch MCT node to a new fin_pll clock
>    ARM: dts: exynos: Remove old fixed-clock provider on SMDK5410
>    clk: samsung: exynos5410: Rename fin_pll from temporary to regular
>      name
>    clk: samsung: exynos5410: Add serial3, USB and PWM clocks
>    ARM: dts: exynos: Re-order alphabetically Exynos5420 SD0/SD1 pinctrl
>      nodes
>    ARM: dts: exynos: Use lowercase for Exynos5410 CPU node labels
>    ARM: dts: exynos: Configure Exynos5410 pinctrl for eMMC and SD card
>    ARM: dts: exynos: Split Odroid XU3 LEDs to separate DTSI
>    ARM: dts: exynos: Move common nodes to exynos5.dtsi
>    ARM: dts: exynos: Prepare for inclusion of exynos5.dtsi in
>      exynos5410.dtsi
>    ARM: dts: exynos: Use phandle to get parent node in exynos5250-snow
>    ARM: dts: exynos: Move Exynos5250 and Exynos5420 nodes under soc
>    ARM: dts: exynos: Include common exynos5 in exynos5410.dtsi
>    ARM: dts: exynos: Enable UART3 on Exynos5410
>    ARM: dts: exynos: MCT is not an interrupt controller and extend length
>      of iomap
>    ARM: dts: exynos: Move common Exynos5410/542x/5800 nodes to new DTSI
>    ARM: dts: exynos: Add USB to Exynos5410
>    ARM: dts: exynos: Add initial support for Odroid XU board
>    dt-bindings: clock: Add I2C, HSI2C and RTC clock IDs to Exynos5410
>    clk: samsung: exynos5410: Add I2C, HSI2C and RTC clocks
>    ARM: dts: exynos: Move HSI2C nodes to exynos54xx.dtsi
>    ARM: dts: exynos: Add I2C, PWM and UART pinctrl to Exynos5410
>    ARM: dts: exynos: Add RTC and I2C to Exynos5410
>
>   .../bindings/arm/samsung/samsung-boards.txt        |    1 +
>   arch/arm/boot/dts/Makefile                         |    1 +
>   arch/arm/boot/dts/exynos5.dtsi                     |  215 ++-
>   arch/arm/boot/dts/exynos5250-snow-common.dtsi      |    2 +-
>   arch/arm/boot/dts/exynos5250.dtsi                  | 1701 ++++++++---------
>   arch/arm/boot/dts/exynos5410-odroidxu.dts          |  121 ++
>   arch/arm/boot/dts/exynos5410-pinctrl.dtsi          |  210 +++
>   arch/arm/boot/dts/exynos5410-smdk5410.dts          |   16 +-
>   arch/arm/boot/dts/exynos5410.dtsi                  |  270 +--
>   arch/arm/boot/dts/exynos5420-pinctrl.dtsi          |   12 +-
>   arch/arm/boot/dts/exynos5420.dtsi                  | 1992 +++++++++-----------
>   arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts    |   35 +-
>   arch/arm/boot/dts/exynos5422-odroidxu3.dts         |   35 +-
>   arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi    |   50 +
>   arch/arm/boot/dts/exynos54xx.dtsi                  |  188 ++
>   drivers/clk/samsung/clk-exynos5410.c               |   61 +
>   include/dt-bindings/clock/exynos5410.h             |   73 +-
>   17 files changed, 2758 insertions(+), 2225 deletions(-)
>   create mode 100644 arch/arm/boot/dts/exynos5410-odroidxu.dts
>   create mode 100644 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
>   create mode 100644 arch/arm/boot/dts/exynos54xx.dtsi
>



From jszhang at marvell.com  Fri May 13 04:59:19 2016
From: jszhang at marvell.com (Jisheng Zhang)
Date: Fri, 13 May 2016 19:59:19 +0800
Subject: [PATCH 1/2] net: mv643xx_eth: use {readl|writel}_relaxed instead of
 readl/writel
In-Reply-To: <1463140760-7128-1-git-send-email-jszhang@marvell.com>
References: <1463140760-7128-1-git-send-email-jszhang@marvell.com>
Message-ID: <1463140760-7128-2-git-send-email-jszhang@marvell.com>

Since appropriate memory barriers are already there, use the relaxed
version to improve performance a bit.

Signed-off-by: Jisheng Zhang <jszhang at marvell.com>
---
 drivers/net/ethernet/marvell/mv643xx_eth.c | 33 +++++++++++++++---------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 5583118..c6d8124 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -433,22 +433,22 @@ struct mv643xx_eth_private {
 /* port register accessors **************************************************/
 static inline u32 rdl(struct mv643xx_eth_private *mp, int offset)
 {
-	return readl(mp->shared->base + offset);
+	return readl_relaxed(mp->shared->base + offset);
 }
 
 static inline u32 rdlp(struct mv643xx_eth_private *mp, int offset)
 {
-	return readl(mp->base + offset);
+	return readl_relaxed(mp->base + offset);
 }
 
 static inline void wrl(struct mv643xx_eth_private *mp, int offset, u32 data)
 {
-	writel(data, mp->shared->base + offset);
+	writel_relaxed(data, mp->shared->base + offset);
 }
 
 static inline void wrlp(struct mv643xx_eth_private *mp, int offset, u32 data)
 {
-	writel(data, mp->base + offset);
+	writel_relaxed(data, mp->base + offset);
 }
 
 
@@ -2642,10 +2642,10 @@ mv643xx_eth_conf_mbus_windows(struct mv643xx_eth_shared_private *msp,
 	int i;
 
 	for (i = 0; i < 6; i++) {
-		writel(0, base + WINDOW_BASE(i));
-		writel(0, base + WINDOW_SIZE(i));
+		writel_relaxed(0, base + WINDOW_BASE(i));
+		writel_relaxed(0, base + WINDOW_SIZE(i));
 		if (i < 4)
-			writel(0, base + WINDOW_REMAP_HIGH(i));
+			writel_relaxed(0, base + WINDOW_REMAP_HIGH(i));
 	}
 
 	win_enable = 0x3f;
@@ -2654,16 +2654,17 @@ mv643xx_eth_conf_mbus_windows(struct mv643xx_eth_shared_private *msp,
 	for (i = 0; i < dram->num_cs; i++) {
 		const struct mbus_dram_window *cs = dram->cs + i;
 
-		writel((cs->base & 0xffff0000) |
+		writel_relaxed((cs->base & 0xffff0000) |
 			(cs->mbus_attr << 8) |
 			dram->mbus_dram_target_id, base + WINDOW_BASE(i));
-		writel((cs->size - 1) & 0xffff0000, base + WINDOW_SIZE(i));
+		writel_relaxed((cs->size - 1) & 0xffff0000,
+			base + WINDOW_SIZE(i));
 
 		win_enable &= ~(1 << i);
 		win_protect |= 3 << (2 * i);
 	}
 
-	writel(win_enable, base + WINDOW_BAR_ENABLE);
+	writel_relaxed(win_enable, base + WINDOW_BAR_ENABLE);
 	msp->win_protect = win_protect;
 }
 
@@ -2674,8 +2675,8 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp)
 	 * [21:8], or a 16-bit coal limit in bits [25,21:7] of the
 	 * SDMA config register.
 	 */
-	writel(0x02000000, msp->base + 0x0400 + SDMA_CONFIG);
-	if (readl(msp->base + 0x0400 + SDMA_CONFIG) & 0x02000000)
+	writel_relaxed(0x02000000, msp->base + 0x0400 + SDMA_CONFIG);
+	if (readl_relaxed(msp->base + 0x0400 + SDMA_CONFIG) & 0x02000000)
 		msp->extended_rx_coal_limit = 1;
 	else
 		msp->extended_rx_coal_limit = 0;
@@ -2685,12 +2686,12 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp)
 	 * yes, whether its associated registers are in the old or
 	 * the new place.
 	 */
-	writel(1, msp->base + 0x0400 + TX_BW_MTU_MOVED);
-	if (readl(msp->base + 0x0400 + TX_BW_MTU_MOVED) & 1) {
+	writel_relaxed(1, msp->base + 0x0400 + TX_BW_MTU_MOVED);
+	if (readl_relaxed(msp->base + 0x0400 + TX_BW_MTU_MOVED) & 1) {
 		msp->tx_bw_control = TX_BW_CONTROL_NEW_LAYOUT;
 	} else {
-		writel(7, msp->base + 0x0400 + TX_BW_RATE);
-		if (readl(msp->base + 0x0400 + TX_BW_RATE) & 7)
+		writel_relaxed(7, msp->base + 0x0400 + TX_BW_RATE);
+		if (readl_relaxed(msp->base + 0x0400 + TX_BW_RATE) & 7)
 			msp->tx_bw_control = TX_BW_CONTROL_OLD_LAYOUT;
 		else
 			msp->tx_bw_control = TX_BW_CONTROL_ABSENT;
-- 
2.8.1



From jszhang at marvell.com  Fri May 13 04:59:18 2016
From: jszhang at marvell.com (Jisheng Zhang)
Date: Fri, 13 May 2016 19:59:18 +0800
Subject: [PATCH 0/2] net: mv643xx_eth: improve performance
Message-ID: <1463140760-7128-1-git-send-email-jszhang@marvell.com>

This series is to improve the mv643xx_eth driver performance by using
{readl|writel}_relaxed or appropriate memory barriers.

Since I have no mv643xx_eth platforms, tests are appreciated!

Jisheng Zhang (2):
  net: mv643xx_eth: use {readl|writel}_relaxed instead of readl/writel
  net: mv643xx_eth: use dma_wmb/rmb where appropriate

 drivers/net/ethernet/marvell/mv643xx_eth.c | 43 +++++++++++++++---------------
 1 file changed, 22 insertions(+), 21 deletions(-)

-- 
2.8.1



From jszhang at marvell.com  Fri May 13 04:59:20 2016
From: jszhang at marvell.com (Jisheng Zhang)
Date: Fri, 13 May 2016 19:59:20 +0800
Subject: [PATCH 2/2] net: mv643xx_eth: use dma_wmb/rmb where appropriate
In-Reply-To: <1463140760-7128-1-git-send-email-jszhang@marvell.com>
References: <1463140760-7128-1-git-send-email-jszhang@marvell.com>
Message-ID: <1463140760-7128-3-git-send-email-jszhang@marvell.com>

Update the mv643xx_eth driver to use the dma_rmb/wmb calls instead of
the full barriers in order to improve performance.

Signed-off-by: Jisheng Zhang <jszhang at marvell.com>
---
 drivers/net/ethernet/marvell/mv643xx_eth.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index c6d8124..13b71e3 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -536,7 +536,7 @@ static int rxq_process(struct rx_queue *rxq, int budget)
 		cmd_sts = rx_desc->cmd_sts;
 		if (cmd_sts & BUFFER_OWNED_BY_DMA)
 			break;
-		rmb();
+		dma_rmb();
 
 		skb = rxq->rx_skb[rxq->rx_curr_desc];
 		rxq->rx_skb[rxq->rx_curr_desc] = NULL;
@@ -647,9 +647,9 @@ static int rxq_refill(struct rx_queue *rxq, int budget)
 						  DMA_FROM_DEVICE);
 		rx_desc->buf_size = size;
 		rxq->rx_skb[rx] = skb;
-		wmb();
+		dma_wmb();
 		rx_desc->cmd_sts = BUFFER_OWNED_BY_DMA | RX_ENABLE_INTERRUPT;
-		wmb();
+		dma_wmb();
 
 		/*
 		 * The hardware automatically prepends 2 bytes of
@@ -889,7 +889,7 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
 	skb_tx_timestamp(skb);
 
 	/* ensure all other descriptors are written before first cmd_sts */
-	wmb();
+	dma_wmb();
 	first_tx_desc->cmd_sts = first_cmd_sts;
 
 	/* clear TX_END status */
@@ -994,7 +994,7 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb,
 	skb_tx_timestamp(skb);
 
 	/* ensure all other descriptors are written before first cmd_sts */
-	wmb();
+	dma_wmb();
 	desc->cmd_sts = cmd_sts;
 
 	/* clear TX_END status */
-- 
2.8.1



From arnd at arndb.de  Fri May 13 05:09:43 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 13 May 2016 14:09:43 +0200
Subject: [PATCH 1/2] net: mv643xx_eth: use {readl|writel}_relaxed instead
 of readl/writel
In-Reply-To: <1463140760-7128-2-git-send-email-jszhang@marvell.com>
References: <1463140760-7128-1-git-send-email-jszhang@marvell.com>
 <1463140760-7128-2-git-send-email-jszhang@marvell.com>
Message-ID: <3966837.tFk2PD8QFb@wuerfel>

On Friday 13 May 2016 19:59:19 Jisheng Zhang wrote:
>  /* port register accessors **************************************************/
>  static inline u32 rdl(struct mv643xx_eth_private *mp, int offset)
>  {
> -	return readl(mp->shared->base + offset);
> +	return readl_relaxed(mp->shared->base + offset);
>  }
>  
>  static inline u32 rdlp(struct mv643xx_eth_private *mp, int offset)
>  {
> -	return readl(mp->base + offset);
> +	return readl_relaxed(mp->base + offset);
>  }

I'd recommend not changing these in general, but introducing new 'rdl_relaxed()'
and 'rdlp_relaxed()' etc variants that you use in the code that actually
is performance sensitive, but use the normal non-relaxed versions by
default.

Then add a comment to each use of the relaxed accessors on how you know
that it's safe for that caller. This usually is just needed for the xmit()
function and for the interrupt handler.
  
> @@ -2642,10 +2642,10 @@ mv643xx_eth_conf_mbus_windows(struct mv643xx_eth_shared_private *msp,
>  	int i;
>  
>  	for (i = 0; i < 6; i++) {
> -		writel(0, base + WINDOW_BASE(i));
> -		writel(0, base + WINDOW_SIZE(i));
> +		writel_relaxed(0, base + WINDOW_BASE(i));
> +		writel_relaxed(0, base + WINDOW_SIZE(i));
>  		if (i < 4)
> -			writel(0, base + WINDOW_REMAP_HIGH(i));
> +			writel_relaxed(0, base + WINDOW_REMAP_HIGH(i));
>  	}
>  
>  	win_enable = 0x3f;

Configuring the mbus for instance is clearly not an operation in which
performance matters at all, so better not touch that.

> @@ -2674,8 +2675,8 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp)
>  	 * [21:8], or a 16-bit coal limit in bits [25,21:7] of the
>  	 * SDMA config register.
>  	 */
> -	writel(0x02000000, msp->base + 0x0400 + SDMA_CONFIG);
> -	if (readl(msp->base + 0x0400 + SDMA_CONFIG) & 0x02000000)
> +	writel_relaxed(0x02000000, msp->base + 0x0400 + SDMA_CONFIG);
> +	if (readl_relaxed(msp->base + 0x0400 + SDMA_CONFIG) & 0x02000000)
>  		msp->extended_rx_coal_limit = 1;
>  	else
>  		msp->extended_rx_coal_limit = 0;


This also seems to be configuration, rather than in the packet rx/tx hotpath.

	Arnd


From krzk at kernel.org  Fri May 13 05:11:54 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 13 May 2016 14:11:54 +0200
Subject: [PATCH v3 00/27] ARM: dts: exynos: Add initial support for Odroid
 XU
In-Reply-To: <5735C274.50504@arm.com>
References: <1462910970-1812-1-git-send-email-krzk@kernel.org>
 <5735C274.50504@arm.com>
Message-ID: <5735C48A.6030508@kernel.org>

On 05/13/2016 02:03 PM, Robin Murphy wrote:
> Hi Krzysztof,
> 
> On 10/05/16 21:09, Krzysztof Kozlowski wrote:
>> Hi,
>>
>> Patchset adds necessary clocks, reorganizes existing stuff and finally
>> adds Odroid XU support.
>>
>>
>> Changes since v2
>> ================
>> 1. Got global-ack from Stephen for the clock changes. I think merging
>>     everything through arm-soc might be the easiest but:
>>     a. In such case I will prepare a tag with clock changes,
>>     b. Anyway I will wait for response from Sylwester and Tomasz.
>> 2. Applied comments from Javier and added his Reviewed-by.
>> 3. Patch 22: added ack from Rob.
>> 4. Minor improvements in existing patches.
>> 5. Five new patches at the end: 23-27 (not reviewed yet).
>>     Some of them could be squashed with existing ones but existing
>>     changes got reviews. Although the final Odroid XU DTS works fine but
>>     in general this is still work-in-progress so I suspect it will grow.
>>     I am releasing it early following Linux concept. :)
>>
>> Patchset is available at my private repo @github:
>> https://github.com/krzk/linux.git for-next/odroid-xu-v3
> 
> Since I have one of these gathering dust on my desk, it's really cool to
> see this series, thanks!
> 
> I've successfully booted that branch to a filesystem on SD card, but USB
> clearly isn't quite right - the USB 2.0 hub is powered up, but only the
> bottom right port will actually enumerate devices; the ethernet is
> nowhere to be seen. However, if I drop into the bootloader and do a "usb
> start" beforehand, it all keeps working into the kernel.

Thanks for letting me know. I am testing the board from TFTP boot which
means "usb start" in Uboot. I'll add it to my todo-list.

> As for the USB
> 3.0, though, the ports report over-current conditions shortly after the
> XHCI probe despite having nothing plugged in :(

Yes, I am seeing this as well. Maybe the cause is lack regulator supplies?

Best regards,
Krzysztof


From andre.przywara at arm.com  Fri May 13 05:23:02 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri, 13 May 2016 13:23:02 +0100
Subject: [PATCH v3 47/55] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <20160513115419.GH27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-48-git-send-email-andre.przywara@arm.com>
 <20160512184740.GM27623@cbox> <5734D0F6.9090406@arm.com>
 <20160513075323.GF27623@cbox> <5735B016.50207@arm.com>
 <20160513115419.GH27623@cbox>
Message-ID: <5735C726.6050003@arm.com>

Hi,

On 13/05/16 12:54, Christoffer Dall wrote:
> On Fri, May 13, 2016 at 11:44:38AM +0100, Andre Przywara wrote:
>> Hi,
>>
>> On 13/05/16 08:53, Christoffer Dall wrote:
>>> On Thu, May 12, 2016 at 07:52:38PM +0100, Andre Przywara wrote:
>>>> Hi,
>>>>
>>>> On 12/05/16 19:47, Christoffer Dall wrote:
>>>>> On Fri, May 06, 2016 at 11:46:00AM +0100, Andre Przywara wrote:
>>>>>> Using the VMCR accessors we provide access to GIC CPU interface state
>>>>>> to userland by wiring it up to the existing userland interface.
>>>>>> [Marc: move and make VMCR accessors static, streamline MMIO handlers]
>>>>>
>>>>> does this mean Marc did this and serves as credit or is it a lost
>>>>> reminder?
>>>>
>>>> It was meant as credit. I thought that is the usual annotation for this?
>>>>
>>>
>>> I'm not sure if that's the usual way, I read it as a reminder, but it's
>>> not too important.  Mostly wanting to make sure we're not forgetting
>>> some todo item.
>>>
>>>>>>
>>>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>>>>> ---
>>>>>> Changelog v2 .. v3:
>>>>>> - total rework, moving into vgic-mmio-v2.c
>>>>>> - move vmcr accessor wrapper functions into this file
>>>>>> - use the register description table for CPU i/f registers as well
>>>>>> - add RAZ/WI handling for the active priority registers
>>>>>> - streamline MMIO handler functions
>>>>>>
>>>>>>  virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
>>>>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 104 ++++++++++++++++++++++++++++++++++++
>>>>>>  virt/kvm/arm/vgic/vgic.h            |   2 +
>>>>>>  3 files changed, 107 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
>>>>>> index bb33af8..2122ff2 100644
>>>>>> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
>>>>>> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
>>>>>> @@ -300,7 +300,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
>>>>>>  
>>>>>>  	switch (attr->group) {
>>>>>>  	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>>>>>> -		ret = -EINVAL;
>>>>>> +		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
>>>>>>  		break;
>>>>>>  	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>>>>>>  		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
>>>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>>>> index c453e6f..0060539 100644
>>>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>>>> @@ -206,6 +206,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
>>>>>>  	}
>>>>>>  }
>>>>>>  
>>>>>> +static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
>>>>>> +{
>>>>>> +	if (kvm_vgic_global_state.type == VGIC_V2)
>>>>>> +		vgic_v2_set_vmcr(vcpu, vmcr);
>>>>>> +	else
>>>>>> +		vgic_v3_set_vmcr(vcpu, vmcr);
>>>>>> +}
>>>>>> +
>>>>>> +static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
>>>>>> +{
>>>>>> +	if (kvm_vgic_global_state.type == VGIC_V2)
>>>>>> +		vgic_v2_get_vmcr(vcpu, vmcr);
>>>>>> +	else
>>>>>> +		vgic_v3_get_vmcr(vcpu, vmcr);
>>>>>> +}
>>>>>> +
>>>>>> +#define GICC_ARCH_VERSION_V2	0x2
>>>>>> +
>>>>>> +/* These are for userland accesses only, there is no guest-facing emulation. */
>>>>>> +static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
>>>>>> +					   gpa_t addr, unsigned int len)
>>>>>> +{
>>>>>> +	struct vgic_vmcr vmcr;
>>>>>> +	u32 val;
>>>>>> +
>>>>>> +	vgic_get_vmcr(vcpu, &vmcr);
>>>>>> +
>>>>>> +	switch (addr & 0xff) {
>>>>>> +	case GIC_CPU_CTRL:
>>>>>> +		val = vmcr.ctlr;
>>>>>> +		break;
>>>>>> +	case GIC_CPU_PRIMASK:
>>>>>> +		val = vmcr.pmr;
>>>>>> +		break;
>>>>>> +	case GIC_CPU_BINPOINT:
>>>>>> +		val = vmcr.bpr;
>>>>>> +		break;
>>>>>> +	case GIC_CPU_ALIAS_BINPOINT:
>>>>>> +		val = vmcr.abpr;
>>>>>> +		break;
>>>>>> +	case GIC_CPU_IDENT:
>>>>>> +		val = ((PRODUCT_ID_KVM << 20) |
>>>>>> +		       (GICC_ARCH_VERSION_V2 << 16) |
>>>>>> +		       IMPLEMENTER_ARM);
>>>>>> +		break;
>>>>>> +	default:
>>>>>> +		return 0;
>>>>>> +	}
>>>>>> +
>>>>>> +	return extract_bytes(val, addr & 3, len);
>>>>>
>>>>> I don't think we allow anything than a full 32-bit aligned accesses
>>>>> from userspace - we shouldn't at least.
>>>>
>>>> Indeed - I think userland was always 32-bit only. And since last night
>>>> we even enforce this. So potentially there are more extract_bytes()
>>>> calls that can go.
>>>>
>>> Right.
>>
>> So can I replace every call to extract_bytes() with just a "return val;"
>> for every register that allows 32-bit accesses only?
>> I think that's safe now, just checking ...
> 
> yes, I think the way we do it now, you simply return val (asuming you
> build that variable at the right offset, even for byte accesses).

??? If we only have word accesses, then we don't need to care about byte
accesses? Or do I got something wrong here?

> The only exception is for 32-bit accesses to 64-bit registers, where you
> have to return either the upper or lower 32-bits.  I think you can still
> use extract_bytes() there should you be so inclined.

Yeah, in fact GICR_TYPER and GICD_IROUTER are the only users remaining
afterwards. So I moved the declaration into vgic-mmio-v3.c and renamed
it to extract_words() on the way.
Will send the patch in a minute ...

Cheers,
Andre.


From andre.przywara at arm.com  Fri May 13 05:24:07 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Fri, 13 May 2016 13:24:07 +0100
Subject: [PATCH v3 43/55] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 access to VGIC registers
In-Reply-To: <20160512183016.GJ27623@cbox>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-44-git-send-email-andre.przywara@arm.com>
 <20160512183016.GJ27623@cbox>
Message-ID: <5735C767.7030807@arm.com>

Hi,

On 12/05/16 19:30, Christoffer Dall wrote:
> On Fri, May 06, 2016 at 11:45:56AM +0100, Andre Przywara wrote:
>> From: Eric Auger <eric.auger at linaro.org>
>>
>> This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
>> and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
>> access VGIC registers.
>>
>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>>  virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
>>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 34 ++++++++++++++++++++++++
>>  virt/kvm/arm/vgic/vgic.h            |  1 +
>>  3 files changed, 86 insertions(+), 2 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> index 0189c13..c952f6f 100644
>> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
>> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> @@ -252,6 +252,21 @@ void kvm_register_vgic_device(unsigned long type)
>>  	}
>>  }
>>  
>> +/** vgic_attr_regs_access: allows user space to read/write VGIC registers
>> + *
>> + * @dev: kvm device handle
>> + * @attr: kvm device attribute
>> + * @reg: address the value is read or written
>> + * @is_write: write flag
>> + *
>> + */
>> +static int vgic_attr_regs_access(struct kvm_device *dev,
>> +				 struct kvm_device_attr *attr,
>> +				 u32 *reg, bool is_write)
>> +{
>> +	return -ENXIO;
>> +}
>> +
>>  /* V2 ops */
>>  
>>  static int vgic_v2_set_attr(struct kvm_device *dev,
>> @@ -260,8 +275,23 @@ static int vgic_v2_set_attr(struct kvm_device *dev,
>>  	int ret;
>>  
>>  	ret = vgic_set_common_attr(dev, attr);
>> -	return ret;
>> +	if (ret != -ENXIO)
>> +		return ret;
>> +
>> +	switch (attr->group) {
>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
>> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
>> +		u32 reg;
>> +
>> +		if (get_user(reg, uaddr))
>> +			return -EFAULT;
>>  
>> +		return vgic_attr_regs_access(dev, attr, &reg, true);
>> +	}
>> +	}
>> +
>> +	return -ENXIO;
>>  }
>>  
>>  static int vgic_v2_get_attr(struct kvm_device *dev,
>> @@ -270,7 +300,23 @@ static int vgic_v2_get_attr(struct kvm_device *dev,
>>  	int ret;
>>  
>>  	ret = vgic_get_common_attr(dev, attr);
>> -	return ret;
>> +	if (ret != -ENXIO)
>> +		return ret;
>> +
>> +	switch (attr->group) {
>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
>> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
>> +		u32 reg = 0;
>> +
>> +		ret = vgic_attr_regs_access(dev, attr, &reg, false);
>> +		if (ret)
>> +			return ret;
>> +		return put_user(reg, uaddr);
>> +	}
>> +	}
>> +
>> +	return -ENXIO;
>>  }
>>  
>>  static int vgic_v2_has_attr(struct kvm_device *dev,
>> @@ -284,6 +330,9 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
>>  			return 0;
>>  		}
>>  		break;
>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>> +		return vgic_v2_has_attr_regs(dev, attr);
>>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
>>  		return 0;
>>  	case KVM_DEV_ARM_VGIC_GRP_CTRL:
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> index 8006ac0..cf8fee9 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> @@ -246,3 +246,37 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
>>  
>>  	return SZ_4K;
>>  }
>> +
>> +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
>> +{
>> +	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
>> +	const struct vgic_register_region *regions;
>> +	gpa_t addr;
>> +	int nr_regions, i, len;
>> +
>> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
>> +
>> +	switch (attr->group) {
>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>> +		regions = vgic_v2_dist_registers;
>> +		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
>> +		break;
>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>> +		return -ENXIO;		/* TODO: describe CPU i/f regs also */
>> +	default:
>> +		return -ENXIO;
>> +	}
>> +
>> +	for (i = 0; i < nr_regions; i++) {
>> +		if (regions[i].bits_per_irq)
>> +			len = (regions[i].bits_per_irq * nr_irqs) / 8;
>> +		else
>> +			len = regions[i].len;
>> +
>> +		if (regions[i].reg_offset <= addr &&
>> +		    regions[i].reg_offset + len > addr)
>> +			return 0;
> 
> should we check if addr is word-aligned ?

Do we care here? This is just the function that says whether we support
this register or not, so I don't see so much benefit in checking here.
A check would be more useful in get/set_attr, if this isn't even
enforced before.

Cheers,
Andre.


From ludovic.desroches at atmel.com  Fri May 13 05:24:21 2016
From: ludovic.desroches at atmel.com (Ludovic Desroches)
Date: Fri, 13 May 2016 14:24:21 +0200
Subject: [PATCH v2] i2c: at91: change log when dma configuration fails
Message-ID: <1463142261-26321-1-git-send-email-ludovic.desroches@atmel.com>

When the DMA configuration fails, there is a log reporting that we can't
use DMA and indicating the error number. When booting the kernel, it is
annoying to see this error number. Moreover, people can think something
is going wrong. It is not the case, it means that DMA can't be used but
it doesn't prevent to use i2c.

Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>
---
 drivers/i2c/busses/i2c-at91.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Changes:
- v2:
  - remove ret parameter

diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 921d32b..6384d08 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -1013,7 +1013,7 @@ static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
 
 error:
 	if (ret != -EPROBE_DEFER)
-		dev_info(dev->dev, "can't use DMA, error %d\n", ret);
+		dev_info(dev->dev, "can't request DMA channels, continue without DMA support\n");
 	if (dma->chan_rx)
 		dma_release_channel(dma->chan_rx);
 	if (dma->chan_tx)
-- 
2.5.0



From jszhang at marvell.com  Fri May 13 05:19:55 2016
From: jszhang at marvell.com (Jisheng Zhang)
Date: Fri, 13 May 2016 20:19:55 +0800
Subject: [PATCH 1/2] net: mv643xx_eth: use {readl|writel}_relaxed
 instead of readl/writel
In-Reply-To: <3966837.tFk2PD8QFb@wuerfel>
References: <1463140760-7128-1-git-send-email-jszhang@marvell.com>
 <1463140760-7128-2-git-send-email-jszhang@marvell.com>
 <3966837.tFk2PD8QFb@wuerfel>
Message-ID: <20160513201955.256e5169@xhacker>

Dear Arnd,

On Fri, 13 May 2016 14:09:43 +0200 Arnd Bergmann wrote:

> On Friday 13 May 2016 19:59:19 Jisheng Zhang wrote:
> >  /* port register accessors **************************************************/
> >  static inline u32 rdl(struct mv643xx_eth_private *mp, int offset)
> >  {
> > -	return readl(mp->shared->base + offset);
> > +	return readl_relaxed(mp->shared->base + offset);
> >  }
> >  
> >  static inline u32 rdlp(struct mv643xx_eth_private *mp, int offset)
> >  {
> > -	return readl(mp->base + offset);
> > +	return readl_relaxed(mp->base + offset);
> >  }  
> 
> I'd recommend not changing these in general, but introducing new 'rdl_relaxed()'
> and 'rdlp_relaxed()' etc variants that you use in the code that actually
> is performance sensitive, but use the normal non-relaxed versions by
> default.
> 
> Then add a comment to each use of the relaxed accessors on how you know
> that it's safe for that caller. This usually is just needed for the xmit()
> function and for the interrupt handler.

Got your points and I do think it makes sense. But could we always use the
relaxed version to save some LoCs, although I have no mv643xx_eth platform
but I can confirm similar relaxed version changes in pxa168_eth is safe and
this is what we do in product's kernel.

Above is just my humble opinion, comments are welcome.

Thanks,
Jisheng

>   
> > @@ -2642,10 +2642,10 @@ mv643xx_eth_conf_mbus_windows(struct mv643xx_eth_shared_private *msp,
> >  	int i;
> >  
> >  	for (i = 0; i < 6; i++) {
> > -		writel(0, base + WINDOW_BASE(i));
> > -		writel(0, base + WINDOW_SIZE(i));
> > +		writel_relaxed(0, base + WINDOW_BASE(i));
> > +		writel_relaxed(0, base + WINDOW_SIZE(i));
> >  		if (i < 4)
> > -			writel(0, base + WINDOW_REMAP_HIGH(i));
> > +			writel_relaxed(0, base + WINDOW_REMAP_HIGH(i));
> >  	}
> >  
> >  	win_enable = 0x3f;  
> 
> Configuring the mbus for instance is clearly not an operation in which
> performance matters at all, so better not touch that.
> 
> > @@ -2674,8 +2675,8 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp)
> >  	 * [21:8], or a 16-bit coal limit in bits [25,21:7] of the
> >  	 * SDMA config register.
> >  	 */
> > -	writel(0x02000000, msp->base + 0x0400 + SDMA_CONFIG);
> > -	if (readl(msp->base + 0x0400 + SDMA_CONFIG) & 0x02000000)
> > +	writel_relaxed(0x02000000, msp->base + 0x0400 + SDMA_CONFIG);
> > +	if (readl_relaxed(msp->base + 0x0400 + SDMA_CONFIG) & 0x02000000)
> >  		msp->extended_rx_coal_limit = 1;
> >  	else
> >  		msp->extended_rx_coal_limit = 0;  
> 
> 
> This also seems to be configuration, rather than in the packet rx/tx hotpath.
> 
> 	Arnd



From nicolas.ferre at atmel.com  Fri May 13 05:27:14 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Fri, 13 May 2016 14:27:14 +0200
Subject: [PATCH 1/3] dmaengine: at_xdmac: align descriptors on 64 bits
In-Reply-To: <1463064854-6719-1-git-send-email-ludovic.desroches@atmel.com>
References: <1463064854-6719-1-git-send-email-ludovic.desroches@atmel.com>
Message-ID: <5735C822.7000503@atmel.com>

Le 12/05/2016 16:54, Ludovic Desroches a ?crit :
> Having descriptors aligned on 64 bits allows update CNDA and CUBC in an
> atomic way.
> 
> Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>
> Fixes: e1f7c9eee707 ("dmaengine: at_xdmac: creation of the atmel
> eXtended DMA Controller driver")
> Cc: stable at vger.kernel.org #v4.1 and later

Reviewed-by: Nicolas Ferre <nicolas.ferre at atmel.com>

> ---
>  drivers/dma/at_xdmac.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
> index 8e304b1..ba9b0b7 100644
> --- a/drivers/dma/at_xdmac.c
> +++ b/drivers/dma/at_xdmac.c
> @@ -242,7 +242,7 @@ struct at_xdmac_lld {
>  	u32		mbr_dus;	/* Destination Microblock Stride Register */
>  };
>  
> -
> +/* 64-bit alignment needed to update CNDA and CUBC registers in an atomic way. */
>  struct at_xdmac_desc {
>  	struct at_xdmac_lld		lld;
>  	enum dma_transfer_direction	direction;
> @@ -253,7 +253,7 @@ struct at_xdmac_desc {
>  	unsigned int			xfer_size;
>  	struct list_head		descs_list;
>  	struct list_head		xfer_node;
> -};
> +} __aligned(sizeof(u64));
>  
>  static inline void __iomem *at_xdmac_chan_reg_base(struct at_xdmac *atxdmac, unsigned int chan_nb)
>  {
> 


-- 
Nicolas Ferre


From nicolas.ferre at atmel.com  Fri May 13 05:27:37 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Fri, 13 May 2016 14:27:37 +0200
Subject: [PATCH 2/3] dmaengine: at_xdmac: fix residue corruption
In-Reply-To: <1463064854-6719-2-git-send-email-ludovic.desroches@atmel.com>
References: <1463064854-6719-1-git-send-email-ludovic.desroches@atmel.com>
 <1463064854-6719-2-git-send-email-ludovic.desroches@atmel.com>
Message-ID: <5735C839.8070304@atmel.com>

Le 12/05/2016 16:54, Ludovic Desroches a ?crit :
> An unexpected value of CUBC can lead to a corrupted residue. A more
> complex sequence is needed to detect an inaccurate value for NCA or CUBC.
> 
> Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>
> Fixes: e1f7c9eee707 ("dmaengine: at_xdmac: creation of the atmel
> eXtended DMA Controller driver")
> Cc: stable at vger.kernel.org #v4.1 and later

Reviewed-by: Nicolas Ferre <nicolas.ferre at atmel.com>

> ---
>  drivers/dma/at_xdmac.c | 54 ++++++++++++++++++++++++++++++--------------------
>  1 file changed, 32 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
> index ba9b0b7..b02494e 100644
> --- a/drivers/dma/at_xdmac.c
> +++ b/drivers/dma/at_xdmac.c
> @@ -1400,6 +1400,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
>  	u32			cur_nda, check_nda, cur_ubc, mask, value;
>  	u8			dwidth = 0;
>  	unsigned long		flags;
> +	bool			initd;
>  
>  	ret = dma_cookie_status(chan, cookie, txstate);
>  	if (ret == DMA_COMPLETE)
> @@ -1435,34 +1436,43 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
>  	}
>  
>  	/*
> -	 * When processing the residue, we need to read two registers but we
> -	 * can't do it in an atomic way. AT_XDMAC_CNDA is used to find where
> -	 * we stand in the descriptor list and AT_XDMAC_CUBC is used
> -	 * to know how many data are remaining for the current descriptor.
> -	 * Since the dma channel is not paused to not loose data, between the
> -	 * AT_XDMAC_CNDA and AT_XDMAC_CUBC read, we may have change of
> -	 * descriptor.
> -	 * For that reason, after reading AT_XDMAC_CUBC, we check if we are
> -	 * still using the same descriptor by reading a second time
> -	 * AT_XDMAC_CNDA. If AT_XDMAC_CNDA has changed, it means we have to
> -	 * read again AT_XDMAC_CUBC.
> +	 * The easiest way to compute the residue should be to pause the DMA
> +	 * but doing this can lead to miss some data as some devices don't
> +	 * have FIFO.
> +	 * We need to read several registers because:
> +	 * - DMA is running therefore a descriptor change is possible while
> +	 * reading these registers
> +	 * - When the block transfer is done, the value of the CUBC register
> +	 * is set to its initial value until the fetch of the next descriptor.
> +	 * This value will corrupt the residue calculation so we have to skip
> +	 * it.
> +	 *
> +	 * INITD --------                    ------------
> +	 *              |____________________|
> +	 *       _______________________  _______________
> +	 * NDA       @desc2             \/   @desc3
> +	 *       _______________________/\_______________
> +	 *       __________  ___________  _______________
> +	 * CUBC       0    \/ MAX desc1 \/  MAX desc2
> +	 *       __________/\___________/\_______________
> +	 *
> +	 * Since descriptors are aligned on 64 bits, we can assume that
> +	 * the update of NDA and CUBC is atomic.
>  	 * Memory barriers are used to ensure the read order of the registers.
> -	 * A max number of retries is set because unlikely it can never ends if
> -	 * we are transferring a lot of data with small buffers.
> +	 * A max number of retries is set because unlikely it could never ends.
>  	 */
> -	cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
> -	rmb();
> -	cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
>  	for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
> -		rmb();
>  		check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
> -
> -		if (likely(cur_nda == check_nda))
> -			break;
> -
> -		cur_nda = check_nda;
> +		rmb();
> +		initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
>  		rmb();
>  		cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
> +		rmb();
> +		cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
> +		rmb();
> +
> +		if ((check_nda == cur_nda) && initd)
> +			break;
>  	}
>  
>  	if (unlikely(retry >= AT_XDMAC_RESIDUE_MAX_RETRIES)) {
> 


-- 
Nicolas Ferre


From nicolas.ferre at atmel.com  Fri May 13 05:28:22 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Fri, 13 May 2016 14:28:22 +0200
Subject: [PATCH 3/3] dmaengine: at_xdmac: double FIFO flush needed to
 compute residue
In-Reply-To: <1463064854-6719-3-git-send-email-ludovic.desroches@atmel.com>
References: <1463064854-6719-1-git-send-email-ludovic.desroches@atmel.com>
 <1463064854-6719-3-git-send-email-ludovic.desroches@atmel.com>
Message-ID: <5735C866.70800@atmel.com>

Le 12/05/2016 16:54, Ludovic Desroches a ?crit :
> Due to the way CUBC register is updated, a double flush is needed to
> compute an accurate residue. First flush aim is to get data from the DMA
> FIFO and second one ensures that we won't report data which are not in
> memory.
> 
> Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>
> Fixes: e1f7c9eee707 ("dmaengine: at_xdmac: creation of the atmel
> eXtended DMA Controller driver")
> Cc: stable at vger.kernel.org #v4.1 and later

Reviewed-by: Nicolas Ferre <nicolas.ferre at atmel.com>

> ---
>  drivers/dma/at_xdmac.c | 24 +++++++++++++++++++++++-
>  1 file changed, 23 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
> index b02494e..75bd662 100644
> --- a/drivers/dma/at_xdmac.c
> +++ b/drivers/dma/at_xdmac.c
> @@ -1425,7 +1425,16 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
>  	residue = desc->xfer_size;
>  	/*
>  	 * Flush FIFO: only relevant when the transfer is source peripheral
> -	 * synchronized.
> +	 * synchronized. Flush is needed before reading CUBC because data in
> +	 * the FIFO are not reported by CUBC. Reporting a residue of the
> +	 * transfer length while we have data in FIFO can cause issue.
> +	 * Usecase: atmel USART has a timeout which means I have received
> +	 * characters but there is no more character received for a while. On
> +	 * timeout, it requests the residue. If the data are in the DMA FIFO,
> +	 * we will return a residue of the transfer length. It means no data
> +	 * received. If an application is waiting for these data, it will hang
> +	 * since we won't have another USART timeout without receiving new
> +	 * data.
>  	 */
>  	mask = AT_XDMAC_CC_TYPE | AT_XDMAC_CC_DSYNC;
>  	value = AT_XDMAC_CC_TYPE_PER_TRAN | AT_XDMAC_CC_DSYNC_PER2MEM;
> @@ -1481,6 +1490,19 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
>  	}
>  
>  	/*
> +	 * Flush FIFO: only relevant when the transfer is source peripheral
> +	 * synchronized. Another flush is needed here because CUBC is updated
> +	 * when the controller sends the data write command. It can lead to
> +	 * report data that are not written in the memory or the device. The
> +	 * FIFO flush ensures that data are really written.
> +	 */
> +	if ((desc->lld.mbr_cfg & mask) == value) {
> +		at_xdmac_write(atxdmac, AT_XDMAC_GSWF, atchan->mask);
> +		while (!(at_xdmac_chan_read(atchan, AT_XDMAC_CIS) & AT_XDMAC_CIS_FIS))
> +			cpu_relax();
> +	}
> +
> +	/*
>  	 * Remove size of all microblocks already transferred and the current
>  	 * one. Then add the remaining size to transfer of the current
>  	 * microblock.
> 


-- 
Nicolas Ferre


From christoffer.dall at linaro.org  Fri May 13 05:29:40 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 13 May 2016 14:29:40 +0200
Subject: [PATCH v3 43/55] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 access to VGIC registers
In-Reply-To: <5735C767.7030807@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-44-git-send-email-andre.przywara@arm.com>
 <20160512183016.GJ27623@cbox> <5735C767.7030807@arm.com>
Message-ID: <20160513122940.GJ27623@cbox>

On Fri, May 13, 2016 at 01:24:07PM +0100, Andre Przywara wrote:
> Hi,
> 
> On 12/05/16 19:30, Christoffer Dall wrote:
> > On Fri, May 06, 2016 at 11:45:56AM +0100, Andre Przywara wrote:
> >> From: Eric Auger <eric.auger at linaro.org>
> >>
> >> This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
> >> and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
> >> access VGIC registers.
> >>
> >> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

[...]

> >> +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
> >> +{
> >> +	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
> >> +	const struct vgic_register_region *regions;
> >> +	gpa_t addr;
> >> +	int nr_regions, i, len;
> >> +
> >> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
> >> +
> >> +	switch (attr->group) {
> >> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> >> +		regions = vgic_v2_dist_registers;
> >> +		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
> >> +		break;
> >> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> >> +		return -ENXIO;		/* TODO: describe CPU i/f regs also */
> >> +	default:
> >> +		return -ENXIO;
> >> +	}
> >> +
> >> +	for (i = 0; i < nr_regions; i++) {
> >> +		if (regions[i].bits_per_irq)
> >> +			len = (regions[i].bits_per_irq * nr_irqs) / 8;
> >> +		else
> >> +			len = regions[i].len;
> >> +
> >> +		if (regions[i].reg_offset <= addr &&
> >> +		    regions[i].reg_offset + len > addr)
> >> +			return 0;
> > 
> > should we check if addr is word-aligned ?
> 
> Do we care here? This is just the function that says whether we support
> this register or not, so I don't see so much benefit in checking here.
> A check would be more useful in get/set_attr, if this isn't even
> enforced before.
> 

It's kind of weird that you can ask 'do you have an attribute with
offset 0x2' and be told, 'yes', and then if you try to get it, you get
'this attribute doesn't exist'.

Thanks,
-Christoffer


From marc.zyngier at arm.com  Fri May 13 05:30:28 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Fri, 13 May 2016 13:30:28 +0100
Subject: [PATCH v3 43/55] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 access to VGIC registers
In-Reply-To: <5735C767.7030807@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-44-git-send-email-andre.przywara@arm.com>
 <20160512183016.GJ27623@cbox> <5735C767.7030807@arm.com>
Message-ID: <5735C8E4.9030308@arm.com>

On 13/05/16 13:24, Andre Przywara wrote:
> Hi,
> 
> On 12/05/16 19:30, Christoffer Dall wrote:
>> On Fri, May 06, 2016 at 11:45:56AM +0100, Andre Przywara wrote:
>>> From: Eric Auger <eric.auger at linaro.org>
>>>
>>> This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
>>> and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
>>> access VGIC registers.
>>>
>>> Signed-off-by: Eric Auger <eric.auger at linaro.org>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>>  virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 34 ++++++++++++++++++++++++
>>>  virt/kvm/arm/vgic/vgic.h            |  1 +
>>>  3 files changed, 86 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
>>> index 0189c13..c952f6f 100644
>>> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
>>> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
>>> @@ -252,6 +252,21 @@ void kvm_register_vgic_device(unsigned long type)
>>>  	}
>>>  }
>>>  
>>> +/** vgic_attr_regs_access: allows user space to read/write VGIC registers
>>> + *
>>> + * @dev: kvm device handle
>>> + * @attr: kvm device attribute
>>> + * @reg: address the value is read or written
>>> + * @is_write: write flag
>>> + *
>>> + */
>>> +static int vgic_attr_regs_access(struct kvm_device *dev,
>>> +				 struct kvm_device_attr *attr,
>>> +				 u32 *reg, bool is_write)
>>> +{
>>> +	return -ENXIO;
>>> +}
>>> +
>>>  /* V2 ops */
>>>  
>>>  static int vgic_v2_set_attr(struct kvm_device *dev,
>>> @@ -260,8 +275,23 @@ static int vgic_v2_set_attr(struct kvm_device *dev,
>>>  	int ret;
>>>  
>>>  	ret = vgic_set_common_attr(dev, attr);
>>> -	return ret;
>>> +	if (ret != -ENXIO)
>>> +		return ret;
>>> +
>>> +	switch (attr->group) {
>>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
>>> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
>>> +		u32 reg;
>>> +
>>> +		if (get_user(reg, uaddr))
>>> +			return -EFAULT;
>>>  
>>> +		return vgic_attr_regs_access(dev, attr, &reg, true);
>>> +	}
>>> +	}
>>> +
>>> +	return -ENXIO;
>>>  }
>>>  
>>>  static int vgic_v2_get_attr(struct kvm_device *dev,
>>> @@ -270,7 +300,23 @@ static int vgic_v2_get_attr(struct kvm_device *dev,
>>>  	int ret;
>>>  
>>>  	ret = vgic_get_common_attr(dev, attr);
>>> -	return ret;
>>> +	if (ret != -ENXIO)
>>> +		return ret;
>>> +
>>> +	switch (attr->group) {
>>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
>>> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
>>> +		u32 reg = 0;
>>> +
>>> +		ret = vgic_attr_regs_access(dev, attr, &reg, false);
>>> +		if (ret)
>>> +			return ret;
>>> +		return put_user(reg, uaddr);
>>> +	}
>>> +	}
>>> +
>>> +	return -ENXIO;
>>>  }
>>>  
>>>  static int vgic_v2_has_attr(struct kvm_device *dev,
>>> @@ -284,6 +330,9 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
>>>  			return 0;
>>>  		}
>>>  		break;
>>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>>> +		return vgic_v2_has_attr_regs(dev, attr);
>>>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
>>>  		return 0;
>>>  	case KVM_DEV_ARM_VGIC_GRP_CTRL:
>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> index 8006ac0..cf8fee9 100644
>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>> @@ -246,3 +246,37 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
>>>  
>>>  	return SZ_4K;
>>>  }
>>> +
>>> +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
>>> +{
>>> +	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
>>> +	const struct vgic_register_region *regions;
>>> +	gpa_t addr;
>>> +	int nr_regions, i, len;
>>> +
>>> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
>>> +
>>> +	switch (attr->group) {
>>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>>> +		regions = vgic_v2_dist_registers;
>>> +		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
>>> +		break;
>>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>>> +		return -ENXIO;		/* TODO: describe CPU i/f regs also */
>>> +	default:
>>> +		return -ENXIO;
>>> +	}
>>> +
>>> +	for (i = 0; i < nr_regions; i++) {
>>> +		if (regions[i].bits_per_irq)
>>> +			len = (regions[i].bits_per_irq * nr_irqs) / 8;
>>> +		else
>>> +			len = regions[i].len;
>>> +
>>> +		if (regions[i].reg_offset <= addr &&
>>> +		    regions[i].reg_offset + len > addr)
>>> +			return 0;
>>
>> should we check if addr is word-aligned ?
> 
> Do we care here? This is just the function that says whether we support
> this register or not, so I don't see so much benefit in checking here.

There definitely is value in checking the alignment. When you reply OK
to a "has_attr" request, you form a contract with userspace that the
same value will can be used for a get or set operation.

Here, has_attr will succeed while get/set will fail, and that's not an
acceptable behaviour.

> A check would be more useful in get/set_attr, if this isn't even
> enforced before.

Don't we already have that check by virtue of using the same accessors
as the MMIO path?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From shc_work at mail.ru  Fri May 13 05:30:23 2016
From: shc_work at mail.ru (=?UTF-8?B?QWxleGFuZGVyIFNoaXlhbg==?=)
Date: Fri, 13 May 2016 15:30:23 +0300
Subject: =?UTF-8?B?UmU6IFtQQVRDSCAzLzNdIEFSTTogZHRzOiBjbHBzNzExeDogQWRkIGJhc2lj?=
 =?UTF-8?B?IENpcnJ1cyBMb2dpYyBDREI4OTcxMiBEZXZlbG9wbWVudCBib2FyZA==?=
In-Reply-To: <9407200.bOeiVUkGKT@wuerfel>
References: <1463138788-5390-1-git-send-email-shc_work@mail.ru>
 <1463138788-5390-4-git-send-email-shc_work@mail.ru>
 <9407200.bOeiVUkGKT@wuerfel>
Message-ID: <1463142623.38124260@f381.i.mail.ru>

Hello.

> ???????, 13 ??? 2016, 15:00 +03:00 ?? Arnd Bergmann <arnd at arndb.de>:
> 
> On Friday 13 May 2016 14:26:28 Alexander Shiyan wrote:
...
> > +	soc {
> > +		#address-cells = <1>;
> > +		#size-cells = <1>;
> > +		compatible = "simple-bus";
> > +		interrupt-parent = <&intc>;
> > +		ranges;
> 
> All child devices seem to be in the 0x80000000-0x90000000
> range, maybe set the ranges property accordingly?

I do not quite understand that you want to change here.

> 
> > +		clks: clks at 80000000 {
> > +			#clock-cells = <1>;
> > +			compatible = "cirrus,clps711x-clk";
> > +			reg = <0x80000000 0xc000>;
> > +			startup-frequency = <73728000>;
> > +		};
...
> > +		intc: intc at 80000000 {
> > +			compatible = "cirrus,clps711x-intc";
> > +			reg = <0x80000000 0x4000>;
> > +			interrupt-controller;
> > +			#interrupt-cells = <1>;
> > +		};
> 
> Better make the register ranges non-overlapping. This appears
> to start at the same place as the 'clks' node.

CLK driver uses:
#define CLPS711X_SYSCON1 (0x0100)
#define CLPS711X_SYSCON2 (0x1100)
...
#define CLPS711X_PLLR (0xa5a8)

IRQCHIP driver uses:
#define CLPS711X_INTSR1 (0x0240)
...
#define CLPS711X_INTSR2 (0x1240)
...
#define CLPS711X_INTMR3 (0x2280)

So there is no way to do any else.

> > +		porta: gpio at 80000000 {
> > +			compatible = "cirrus,clps711x-gpio";
> > +			reg = <0x80000000 0x1 0x80000040 0x1>;
> > +			gpio-controller;
> > +			#gpio-cells = <2>;
> > +		};
> > +
> > +		portb: gpio at 80000001 {
> > +			compatible = "cirrus,clps711x-gpio";
> > +			reg = <0x80000001 0x1 0x80000041 0x1>;
> > +			gpio-controller;
> > +			#gpio-cells = <2>;
> > +		};
> > +
> > +		portc: gpio at 80000002 {
> > +			compatible = "cirrus,clps711x-gpio";
> > +			reg = <0x80000002 0x1 0x80000042 0x1>;
> > +			gpio-controller;
> > +			#gpio-cells = <2>;
> > +			status = "disabled";
> > +		};
> > +
> > +		portd: gpio at 80000003 {
> > +			compatible = "cirrus,clps711x-gpio";
> > +			reg = <0x80000003 0x1 0x80000043 0x1>;
> > +			gpio-controller;
> > +			#gpio-cells = <2>;
> > +		};
> 
> These are all just single bytes. My guess is that there is
> actually one IP block that contains all the gpios, not
> four identical blocks.

These is a 8-bit registers with different properties, which parses in the
GPIO driver depending of alias (GPIO count, inverted logic etc.).

Thanks.

---


From christoffer.dall at linaro.org  Fri May 13 05:32:29 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 13 May 2016 14:32:29 +0200
Subject: [PATCH v3 47/55] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <5735C726.6050003@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-48-git-send-email-andre.przywara@arm.com>
 <20160512184740.GM27623@cbox> <5734D0F6.9090406@arm.com>
 <20160513075323.GF27623@cbox> <5735B016.50207@arm.com>
 <20160513115419.GH27623@cbox> <5735C726.6050003@arm.com>
Message-ID: <20160513123229.GK27623@cbox>

On Fri, May 13, 2016 at 01:23:02PM +0100, Andre Przywara wrote:
> Hi,
> 
> On 13/05/16 12:54, Christoffer Dall wrote:
> > On Fri, May 13, 2016 at 11:44:38AM +0100, Andre Przywara wrote:
> >> Hi,
> >>
> >> On 13/05/16 08:53, Christoffer Dall wrote:
> >>> On Thu, May 12, 2016 at 07:52:38PM +0100, Andre Przywara wrote:
> >>>> Hi,
> >>>>
> >>>> On 12/05/16 19:47, Christoffer Dall wrote:
> >>>>> On Fri, May 06, 2016 at 11:46:00AM +0100, Andre Przywara wrote:
> >>>>>> Using the VMCR accessors we provide access to GIC CPU interface state
> >>>>>> to userland by wiring it up to the existing userland interface.
> >>>>>> [Marc: move and make VMCR accessors static, streamline MMIO handlers]
> >>>>>
> >>>>> does this mean Marc did this and serves as credit or is it a lost
> >>>>> reminder?
> >>>>
> >>>> It was meant as credit. I thought that is the usual annotation for this?
> >>>>
> >>>
> >>> I'm not sure if that's the usual way, I read it as a reminder, but it's
> >>> not too important.  Mostly wanting to make sure we're not forgetting
> >>> some todo item.
> >>>
> >>>>>>
> >>>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >>>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> >>>>>> ---
> >>>>>> Changelog v2 .. v3:
> >>>>>> - total rework, moving into vgic-mmio-v2.c
> >>>>>> - move vmcr accessor wrapper functions into this file
> >>>>>> - use the register description table for CPU i/f registers as well
> >>>>>> - add RAZ/WI handling for the active priority registers
> >>>>>> - streamline MMIO handler functions
> >>>>>>
> >>>>>>  virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
> >>>>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 104 ++++++++++++++++++++++++++++++++++++
> >>>>>>  virt/kvm/arm/vgic/vgic.h            |   2 +
> >>>>>>  3 files changed, 107 insertions(+), 1 deletion(-)
> >>>>>>
> >>>>>> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> >>>>>> index bb33af8..2122ff2 100644
> >>>>>> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> >>>>>> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> >>>>>> @@ -300,7 +300,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
> >>>>>>  
> >>>>>>  	switch (attr->group) {
> >>>>>>  	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> >>>>>> -		ret = -EINVAL;
> >>>>>> +		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
> >>>>>>  		break;
> >>>>>>  	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> >>>>>>  		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
> >>>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >>>>>> index c453e6f..0060539 100644
> >>>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >>>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >>>>>> @@ -206,6 +206,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
> >>>>>>  	}
> >>>>>>  }
> >>>>>>  
> >>>>>> +static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> >>>>>> +{
> >>>>>> +	if (kvm_vgic_global_state.type == VGIC_V2)
> >>>>>> +		vgic_v2_set_vmcr(vcpu, vmcr);
> >>>>>> +	else
> >>>>>> +		vgic_v3_set_vmcr(vcpu, vmcr);
> >>>>>> +}
> >>>>>> +
> >>>>>> +static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> >>>>>> +{
> >>>>>> +	if (kvm_vgic_global_state.type == VGIC_V2)
> >>>>>> +		vgic_v2_get_vmcr(vcpu, vmcr);
> >>>>>> +	else
> >>>>>> +		vgic_v3_get_vmcr(vcpu, vmcr);
> >>>>>> +}
> >>>>>> +
> >>>>>> +#define GICC_ARCH_VERSION_V2	0x2
> >>>>>> +
> >>>>>> +/* These are for userland accesses only, there is no guest-facing emulation. */
> >>>>>> +static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
> >>>>>> +					   gpa_t addr, unsigned int len)
> >>>>>> +{
> >>>>>> +	struct vgic_vmcr vmcr;
> >>>>>> +	u32 val;
> >>>>>> +
> >>>>>> +	vgic_get_vmcr(vcpu, &vmcr);
> >>>>>> +
> >>>>>> +	switch (addr & 0xff) {
> >>>>>> +	case GIC_CPU_CTRL:
> >>>>>> +		val = vmcr.ctlr;
> >>>>>> +		break;
> >>>>>> +	case GIC_CPU_PRIMASK:
> >>>>>> +		val = vmcr.pmr;
> >>>>>> +		break;
> >>>>>> +	case GIC_CPU_BINPOINT:
> >>>>>> +		val = vmcr.bpr;
> >>>>>> +		break;
> >>>>>> +	case GIC_CPU_ALIAS_BINPOINT:
> >>>>>> +		val = vmcr.abpr;
> >>>>>> +		break;
> >>>>>> +	case GIC_CPU_IDENT:
> >>>>>> +		val = ((PRODUCT_ID_KVM << 20) |
> >>>>>> +		       (GICC_ARCH_VERSION_V2 << 16) |
> >>>>>> +		       IMPLEMENTER_ARM);
> >>>>>> +		break;
> >>>>>> +	default:
> >>>>>> +		return 0;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	return extract_bytes(val, addr & 3, len);
> >>>>>
> >>>>> I don't think we allow anything than a full 32-bit aligned accesses
> >>>>> from userspace - we shouldn't at least.
> >>>>
> >>>> Indeed - I think userland was always 32-bit only. And since last night
> >>>> we even enforce this. So potentially there are more extract_bytes()
> >>>> calls that can go.
> >>>>
> >>> Right.
> >>
> >> So can I replace every call to extract_bytes() with just a "return val;"
> >> for every register that allows 32-bit accesses only?
> >> I think that's safe now, just checking ...
> > 
> > yes, I think the way we do it now, you simply return val (asuming you
> > build that variable at the right offset, even for byte accesses).
> 
> ??? If we only have word accesses, then we don't need to care about byte
> accesses? Or do I got something wrong here?
> 

Ah right, we're talking about the userspace API here, never mind.

> > The only exception is for 32-bit accesses to 64-bit registers, where you
> > have to return either the upper or lower 32-bits.  I think you can still
> > use extract_bytes() there should you be so inclined.
> 
> Yeah, in fact GICR_TYPER and GICD_IROUTER are the only users remaining
> afterwards. So I moved the declaration into vgic-mmio-v3.c and renamed
> it to extract_words() on the way.

did you modify it to only work on words and let len specify the length
in words then, or?

> Will send the patch in a minute ...
> 
I guess I can comment on it there.

-Christoffer


From ladis at linux-mips.org  Fri May 13 05:37:18 2016
From: ladis at linux-mips.org (Ladislav Michl)
Date: Fri, 13 May 2016 14:37:18 +0200
Subject: [PATCH 2/2] ARM: dts: igep0020: Add SD card write-protect pin.
In-Reply-To: <1462568554-7868-2-git-send-email-enric.balletbo@collabora.com>
References: <1462568554-7868-1-git-send-email-enric.balletbo@collabora.com>
 <1462568554-7868-2-git-send-email-enric.balletbo@collabora.com>
Message-ID: <20160513123718.GA2841@localhost.localdomain>

Hi Enric!

On Fri, May 06, 2016 at 11:02:34PM +0200, Enric Balletbo i Serra wrote:
> A host device that supports write protection should refuse to write to
> an SD card that is designated read-only when write-protect is set. This
> is an optional feature of the SD specification.

Does it ever work on any IGEPv2? I have similar patch in my repo and there
is no difference when enabling write protection on SD card. Also schemantics
shows GPIO29 constantly pulled up with a resistor. Is there any board
revision with working WP? I'm just curious as patch is of course correct.

Best regards,
	ladis

> Signed-off-by: Enric Balletbo i Serra <enric.balletbo at collabora.com>
> ---
>  arch/arm/boot/dts/omap3-igep0020-common.dtsi | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/omap3-igep0020-common.dtsi b/arch/arm/boot/dts/omap3-igep0020-common.dtsi
> index d6f839c..b697106 100644
> --- a/arch/arm/boot/dts/omap3-igep0020-common.dtsi
> +++ b/arch/arm/boot/dts/omap3-igep0020-common.dtsi
> @@ -194,6 +194,12 @@
>  			OMAP3630_CORE2_IOPAD(0x25f8, PIN_OUTPUT | MUX_MODE4) /* etk_d14.gpio_28 */
>  		>;
>  	};
> +
> +	mmc1_wp_pins: pinmux_mmc1_cd_pins {
> +		pinctrl-single,pins = <
> +			OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT | MUX_MODE4)   /* etk_d15.gpio_29 */
> +		>;
> +	};
>  };
>  
>  &i2c3 {
> @@ -250,3 +256,8 @@
>  		};
>  	};
>  };
> +
> +&mmc1 {
> +	pinctrl-0 = <&mmc1_pins &mmc1_wp_pins>;
> +	wp-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;	/* gpio_29 */
> +};


From broonie at kernel.org  Fri May 13 05:38:08 2016
From: broonie at kernel.org (Mark Brown)
Date: Fri, 13 May 2016 13:38:08 +0100
Subject: Applied "spi: orion: Add direct access mode" to the spi tree
In-Reply-To: <1462254791-5694-1-git-send-email-sr@denx.de>
Message-ID: <E1b1CM4-00006Y-SE@finisterre>

The patch

   spi: orion: Add direct access mode

has been applied to the spi tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From dbf24b7c0d94d0744f975dd618f4f357dad2647f Mon Sep 17 00:00:00 2001
From: Stefan Roese <sr at denx.de>
Date: Tue, 3 May 2016 07:53:11 +0200
Subject: [PATCH] spi: orion: Add direct access mode

This patch adds support for the direct access mode to the Orion SPI
driver which is used on the Marvell Armada based SoCs. In this direct
mode, all data written to (or read from) a specifically mapped MBus
window (linked to one SPI chip-select on one of the SPI controllers)
will be transferred directly to the SPI bus. Without the need to control
the SPI registers in between. This can improve the SPI transfer rate in
such cases.

Both, direct-read and -write mode are supported. But only the write
mode has been tested. This mode especially benefits from the SPI direct
mode, as the data bytes are written head-to-head to the SPI bus,
without any additional addresses.

One use-case for this direct write mode is, programming a FPGA bitstream
image into the FPGA connected to the SPI bus at maximum speed.

This mode is described in chapter "22.5.2 Direct Write to SPI" in the
Marvell Armada XP Functional Spec Datasheet.

Signed-off-by: Stefan Roese <sr at denx.de>
Acked-by: Arnd Bergmann <arnd at arndb.de>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 .../devicetree/bindings/spi/spi-orion.txt          | 49 +++++++++++-
 drivers/spi/spi-orion.c                            | 87 ++++++++++++++++++++++
 2 files changed, 135 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-orion.txt b/Documentation/devicetree/bindings/spi/spi-orion.txt
index 98bc69815eb3..4f629cc7634a 100644
--- a/Documentation/devicetree/bindings/spi/spi-orion.txt
+++ b/Documentation/devicetree/bindings/spi/spi-orion.txt
@@ -8,7 +8,15 @@ Required properties:
     - "marvell,armada-380-spi", for the Armada 38x SoCs
     - "marvell,armada-390-spi", for the Armada 39x SoCs
     - "marvell,armada-xp-spi", for the Armada XP SoCs
-- reg : offset and length of the register set for the device
+- reg : offset and length of the register set for the device.
+	This property can optionally have additional entries to configure
+	the SPI direct access mode that some of the Marvell SoCs support
+	additionally to the normal indirect access (PIO) mode. The values
+	for the MBus "target" and "attribute" are defined in the Marvell
+	SoC "Functional Specifications" Manual in the chapter "Marvell
+	Core Processor Address Decoding".
+	The eight register sets following the control registers refer to
+	chip-select lines 0 through 7 respectively.
 - cell-index : Which of multiple SPI controllers is this.
 Optional properties:
 - interrupts : Is currently not used.
@@ -23,3 +31,42 @@ Example:
 	       interrupts = <23>;
 	       status = "disabled";
        };
+
+Example with SPI direct mode support (optionally):
+	spi0: spi at 10600 {
+		compatible = "marvell,orion-spi";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cell-index = <0>;
+		reg = <MBUS_ID(0xf0, 0x01) 0x10600 0x28>, /* control */
+		      <MBUS_ID(0x01, 0x1e) 0 0xffffffff>, /* CS0 */
+		      <MBUS_ID(0x01, 0x5e) 0 0xffffffff>, /* CS1 */
+		      <MBUS_ID(0x01, 0x9e) 0 0xffffffff>, /* CS2 */
+		      <MBUS_ID(0x01, 0xde) 0 0xffffffff>, /* CS3 */
+		      <MBUS_ID(0x01, 0x1f) 0 0xffffffff>, /* CS4 */
+		      <MBUS_ID(0x01, 0x5f) 0 0xffffffff>, /* CS5 */
+		      <MBUS_ID(0x01, 0x9f) 0 0xffffffff>, /* CS6 */
+		      <MBUS_ID(0x01, 0xdf) 0 0xffffffff>; /* CS7 */
+		interrupts = <23>;
+		status = "disabled";
+	};
+
+To enable the direct mode, the board specific 'ranges' property in the
+'soc' node needs to add the entries for the desired SPI controllers
+and its chip-selects that are used in the direct mode instead of PIO
+mode. Here an example for this (SPI controller 0, device 1 and SPI
+controller 1, device 2 are used in direct mode. All other SPI device
+are used in the default indirect (PIO) mode):
+	soc {
+		/*
+		 * Enable the SPI direct access by configuring an entry
+		 * here in the board-specific ranges property
+		 */
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000>,	/* internal regs */
+			 <MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>,	/* BootROM       */
+			 <MBUS_ID(0x01, 0x5e) 0 0 0xf1100000 0x10000>,	/* SPI0-DEV1 */
+			 <MBUS_ID(0x01, 0x9a) 0 0 0xf1110000 0x10000>;	/* SPI1-DEV2 */
+
+For further information on the MBus bindings, please see the MBus
+DT documentation:
+Documentation/devicetree/bindings/bus/mvebu-mbus.txt
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index a87cfd4ba17b..604b5dd5d678 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/clk.h>
 #include <linux/sizes.h>
@@ -43,6 +44,9 @@
 #define ORION_SPI_INT_CAUSE_REG		0x10
 #define ORION_SPI_TIMING_PARAMS_REG	0x18
 
+/* Register for the "Direct Mode" */
+#define SPI_DIRECT_WRITE_CONFIG_REG	0x20
+
 #define ORION_SPI_TMISO_SAMPLE_MASK	(0x3 << 6)
 #define ORION_SPI_TMISO_SAMPLE_1	(1 << 6)
 #define ORION_SPI_TMISO_SAMPLE_2	(2 << 6)
@@ -78,11 +82,18 @@ struct orion_spi_dev {
 	bool			is_errata_50mhz_ac;
 };
 
+struct orion_direct_acc {
+	void __iomem		*vaddr;
+	u32			size;
+};
+
 struct orion_spi {
 	struct spi_master	*master;
 	void __iomem		*base;
 	struct clk              *clk;
 	const struct orion_spi_dev *devdata;
+
+	struct orion_direct_acc	direct_access[ORION_NUM_CHIPSELECTS];
 };
 
 static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
@@ -372,10 +383,38 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
 {
 	unsigned int count;
 	int word_len;
+	struct orion_spi *orion_spi;
+	int cs = spi->chip_select;
 
 	word_len = spi->bits_per_word;
 	count = xfer->len;
 
+	orion_spi = spi_master_get_devdata(spi->master);
+
+	/*
+	 * Use SPI direct write mode if base address is available. Otherwise
+	 * fall back to PIO mode for this transfer.
+	 */
+	if ((orion_spi->direct_access[cs].vaddr) && (xfer->tx_buf) &&
+	    (word_len == 8)) {
+		unsigned int cnt = count / 4;
+		unsigned int rem = count % 4;
+
+		/*
+		 * Send the TX-data to the SPI device via the direct
+		 * mapped address window
+		 */
+		writesl(orion_spi->direct_access[cs].vaddr, xfer->tx_buf, cnt);
+		if (rem) {
+			u32 *buf = (u32 *)xfer->tx_buf;
+
+			writesb(orion_spi->direct_access[cs].vaddr, &buf[cnt],
+				rem);
+		}
+
+		return count;
+	}
+
 	if (word_len == 8) {
 		const u8 *tx = xfer->tx_buf;
 		u8 *rx = xfer->rx_buf;
@@ -425,6 +464,10 @@ static int orion_spi_reset(struct orion_spi *orion_spi)
 {
 	/* Verify that the CS is deasserted */
 	orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+
+	/* Don't deassert CS between the direct mapped SPI transfers */
+	writel(0, spi_reg(orion_spi, SPI_DIRECT_WRITE_CONFIG_REG));
+
 	return 0;
 }
 
@@ -504,6 +547,7 @@ static int orion_spi_probe(struct platform_device *pdev)
 	struct resource *r;
 	unsigned long tclk_hz;
 	int status = 0;
+	struct device_node *np;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(*spi));
 	if (master == NULL) {
@@ -576,6 +620,49 @@ static int orion_spi_probe(struct platform_device *pdev)
 		goto out_rel_clk;
 	}
 
+	/* Scan all SPI devices of this controller for direct mapped devices */
+	for_each_available_child_of_node(pdev->dev.of_node, np) {
+		u32 cs;
+
+		/* Get chip-select number from the "reg" property */
+		status = of_property_read_u32(np, "reg", &cs);
+		if (status) {
+			dev_err(&pdev->dev,
+				"%s has no valid 'reg' property (%d)\n",
+				np->full_name, status);
+			status = 0;
+			continue;
+		}
+
+		/*
+		 * Check if an address is configured for this SPI device. If
+		 * not, the MBus mapping via the 'ranges' property in the 'soc'
+		 * node is not configured and this device should not use the
+		 * direct mode. In this case, just continue with the next
+		 * device.
+		 */
+		status = of_address_to_resource(pdev->dev.of_node, cs + 1, r);
+		if (status)
+			continue;
+
+		/*
+		 * Only map one page for direct access. This is enough for the
+		 * simple TX transfer which only writes to the first word.
+		 * This needs to get extended for the direct SPI-NOR / SPI-NAND
+		 * support, once this gets implemented.
+		 */
+		spi->direct_access[cs].vaddr = devm_ioremap(&pdev->dev,
+							    r->start,
+							    PAGE_SIZE);
+		if (IS_ERR(spi->direct_access[cs].vaddr)) {
+			status = PTR_ERR(spi->direct_access[cs].vaddr);
+			goto out_rel_clk;
+		}
+		spi->direct_access[cs].size = PAGE_SIZE;
+
+		dev_info(&pdev->dev, "CS%d configured for direct access\n", cs);
+	}
+
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
-- 
2.8.1



From harninder.rai at nxp.com  Fri May 13 05:45:04 2016
From: harninder.rai at nxp.com (Harninder Rai)
Date: Fri, 13 May 2016 12:45:04 +0000
Subject: Help needed with kexec on arm64
In-Reply-To: <20160511005334.GA8417@linaro.org>
References: <DB5PR04MB168845795D86B4CE5BA5656FE68B0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <1458230896.3391.18.camel@infradead.org>
 <CAB5YjtBEO=efjhcFdVOaZqG13qK3uzCbS5SFym5hhw-n+_QLhw@mail.gmail.com>
 <DB5PR04MB1688A6D4385B76DAFF71D364E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org>
 <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160511005334.GA8417@linaro.org>
Message-ID: <DB5PR04MB1688C3F122091109E6BD9B68E6740@DB5PR04MB1688.eurprd04.prod.outlook.com>

Hello Takahiro Akashi,

> 
> Apparently lack of memory is a cause of OOM killer, but the core file has
> nothing to do with this issue.
> I think that you don't have enough memory for the system yet.
> 
> -Takahiro AKASHI


I moved to SD card based rootfs for booting the crash kernel but when I try to load the dump kernel, I get the following message
Is there limitation with kexec that the crash kernel cannot be booted from anything apart from RAM?

kexec -p ./vmlinux --initrd=./ramdisk_ls1012_openwrt.cpio.gz --append='console=ttyS1,115200 root=/dev/mmcblk0p1 earlycon=uart8250,mmio,0x21c0600ramdisk_size=0x2000000 default_hugepagesz=2m hugepagesz=2m hugepages=256 crashkernel=64M at 2240M memblock=debug'
Memory for crashkernel is not reserved
Please reserve memory by passing"crashkernel=X at Y" parameter to kernel
Then try to loading kdump kernel

Regards
Harry++


From mark.rutland at arm.com  Fri May 13 05:56:07 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Fri, 13 May 2016 13:56:07 +0100
Subject: [PATCH v2 4/6] arm64: mm: dump: make page table dumping reusable
In-Reply-To: <20160425110757.GI16065@arm.com>
References: <1461343688-8552-1-git-send-email-ard.biesheuvel@linaro.org>
 <1461343688-8552-5-git-send-email-ard.biesheuvel@linaro.org>
 <20160425110757.GI16065@arm.com>
Message-ID: <20160513125606.GB4088@leverpostej>

On Mon, Apr 25, 2016 at 12:07:57PM +0100, Will Deacon wrote:
> Hi Ard, Mark,
> 
> On Fri, Apr 22, 2016 at 06:48:06PM +0200, Ard Biesheuvel wrote:
> > From: Mark Rutland <mark.rutland at arm.com>
> > 
> > For debugging purposes, it would be nice if we could export page tables
> > other than the swapper_pg_dir to userspace. To enable this, this patch
> > refactors the arm64 page table dumping code such that multiple tables
> > may be registered with the framework, and exported under debugfs.
> > 
> > Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> > ---
> >  arch/arm64/include/asm/ptdump.h | 44 ++++++++++++++++++++
> >  arch/arm64/mm/dump.c            | 32 ++++++++------
> >  2 files changed, 64 insertions(+), 12 deletions(-)
> 
> Could you reorder this with patch 3, please? I'm unsure about the benefit
> of the very specific string literal changes, but the ptdump stuff here
> certainly looks beneficial.

I'm sure this is far too late, but for posterity I've rebased patch 4
below atop of pathes 1 & 2 as queued in the arm64 for-next/core branch,
without patch 3. It builds cleanly, and I've given it a spin on
Juno.

Will, I guess I should rebase and resend this after we hit v4.7-rc1?

Thanks,
Mark.

---->8----
>From f17b52c0f004614027c356c848fd21308f4177c1 Mon Sep 17 00:00:00 2001
From: Mark Rutland <mark.rutland at arm.com>
Date: Fri, 22 Apr 2016 18:48:06 +0200
Subject: [PATCH] arm64: mm: dump: make page table dumping reusable

For debugging purposes, it would be nice if we could export page tables
other than the swapper_pg_dir to userspace. To enable this, this patch
refactors the arm64 page table dumping code such that multiple tables
may be registered with the framework, and exported under debugfs.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
---
 arch/arm64/include/asm/ptdump.h | 44 +++++++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/dump.c            | 32 +++++++++++++++++++-----------
 2 files changed, 64 insertions(+), 12 deletions(-)
 create mode 100644 arch/arm64/include/asm/ptdump.h

diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
new file mode 100644
index 0000000..07b8ed0
--- /dev/null
+++ b/arch/arm64/include/asm/ptdump.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PTDUMP_H
+#define __ASM_PTDUMP_H
+
+#ifdef CONFIG_ARM64_PTDUMP
+
+#include <linux/mm_types.h>
+
+struct addr_marker {
+	unsigned long start_address;
+	char *name;
+};
+
+struct ptdump_info {
+	struct mm_struct		*mm;
+	const struct addr_marker	*markers;
+	unsigned long			base_addr;
+	unsigned long			max_addr;
+};
+
+int ptdump_register(struct ptdump_info *info, const char *name);
+
+#else
+static inline int ptdump_register(struct ptdump_info *info, const char *name)
+{
+	return 0;
+}
+#endif /* CONFIG_ARM64_PTDUMP */
+
+#endif /* __ASM_PTDUMP_H */
diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
index 8404190..a56a7ad 100644
--- a/arch/arm64/mm/dump.c
+++ b/arch/arm64/mm/dump.c
@@ -27,11 +27,7 @@
 #include <asm/memory.h>
 #include <asm/pgtable.h>
 #include <asm/pgtable-hwdef.h>
-
-struct addr_marker {
-	unsigned long start_address;
-	const char *name;
-};
+#include <asm/ptdump.h>
 
 static const struct addr_marker address_markers[] = {
 #ifdef CONFIG_KASAN
@@ -284,7 +280,8 @@ static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
 	}
 }
 
-static void walk_pgd(struct pg_state *st, struct mm_struct *mm, unsigned long start)
+static void walk_pgd(struct pg_state *st, struct mm_struct *mm,
+		     unsigned long start)
 {
 	pgd_t *pgd = pgd_offset(mm, 0UL);
 	unsigned i;
@@ -303,12 +300,13 @@ static void walk_pgd(struct pg_state *st, struct mm_struct *mm, unsigned long st
 
 static int ptdump_show(struct seq_file *m, void *v)
 {
+	struct ptdump_info *info = m->private;
 	struct pg_state st = {
 		.seq = m,
-		.marker = address_markers,
+		.marker = info->markers,
 	};
 
-	walk_pgd(&st, &init_mm, VA_START);
+	walk_pgd(&st, info->mm, info->base_addr);
 
 	note_page(&st, 0, 0, 0);
 	return 0;
@@ -316,7 +314,7 @@ static int ptdump_show(struct seq_file *m, void *v)
 
 static int ptdump_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ptdump_show, NULL);
+	return single_open(file, ptdump_show, inode->i_private);
 }
 
 static const struct file_operations ptdump_fops = {
@@ -326,7 +324,7 @@ static const struct file_operations ptdump_fops = {
 	.release	= single_release,
 };
 
-static int ptdump_init(void)
+int ptdump_register(struct ptdump_info *info, const char *name)
 {
 	struct dentry *pe;
 	unsigned i, j;
@@ -336,8 +334,18 @@ static int ptdump_init(void)
 			for (j = 0; j < pg_level[i].num; j++)
 				pg_level[i].mask |= pg_level[i].bits[j].mask;
 
-	pe = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL,
-				 &ptdump_fops);
+	pe = debugfs_create_file(name, 0400, NULL, info, &ptdump_fops);
 	return pe ? 0 : -ENOMEM;
 }
+
+static struct ptdump_info kernel_ptdump_info = {
+	.mm		= &init_mm,
+	.markers	= address_markers,
+	.base_addr	= VA_START,
+};
+
+static int ptdump_init(void)
+{
+	return ptdump_register(&kernel_ptdump_info, "kernel_page_tables");
+}
 device_initcall(ptdump_init);
-- 
1.9.1



From kernel at martin.sperl.org  Fri May 13 06:13:01 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Fri, 13 May 2016 13:13:01 +0000
Subject: [PATCH-V2 0/5] bcm2835: add thermal driver
Message-ID: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add a thermal driver for the TSENSE device of the bcm2835 SOC.

If the firmware enables the HW, then the configuration is not touched.
In case the firmware has not enabled the device, then we try to set
it up correctly (which unfortunately can not get tested).

It exposes temperature and a critical trip point
(using a hardcoded default of 80C or the temperature configured
in the control register by the firmware - reads as 0 currently)

The calibrations are (potentially) different for bcm2835, bcm2836
and bcm2837 and can get selected by the compatiblity property
in the device tree.

The driver also exposes the registers via debugfs.

Possible future enhancements:
* the device has the ability to trigger interrupts on reaching
  the programmed critical temperature.
  I have no knowledge which interrupt could be responsible
  for this on the ARM side, so if we get to know which irq
  it is we can implement that
* the device can also reset the HW after the trip point
  has been reached (also with some delay, so that corrective
  actions can get taken) - this is currently not enabled by the
  firmware, but could.
* we could define more trip points for THERMAL_TRIP_HOT
* make the trip point limits modifiable (ops.set_trip_temp)

Changelog:
 V1 -> V2: renamed dt-binding documentation file
       	   added specific settings depending on compatiblity
	   added trip point based on register
	   setting up ctrl-register if HW is not enabled by firmware
	     as per recommendation of Eric (untested)
	   check that clock frequency is in range
	     (1.9 - 5MHz - as per comment in clk-bcm2835.c)
 	   added driver to multi_v7_defconfig

Martin Sperl (5):
  dt: bindings: add thermal device driver for bcm2835
  thermal: bcm2835: add thermal driver for bcm2835 soc
  ARM: bcm2835: add thermal node to device-tree of bcm283x
  ARM: bcm2835: add thermal driver to default_config
  ARM: multi_v7_defconfig: bcm2835: add bcm2835-thermal driver

 .../bindings/thermal/brcm,bcm2835-thermal.txt      |  17 ++
 arch/arm/boot/dts/bcm283x.dtsi                     |   6 +
 arch/arm/configs/bcm2835_defconfig                 |   2 +
 arch/arm/configs/multi_v7_defconfig                |   1 +
 drivers/thermal/Kconfig                            |   5 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/bcm/Kconfig                        |   4 +
 drivers/thermal/bcm/Makefile                       |   1 +
 drivers/thermal/bcm/bcm2835_thermal.c              | 326 +++++++++++++++++++++
 9 files changed, 363 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
 create mode 100644 drivers/thermal/bcm/Kconfig
 create mode 100644 drivers/thermal/bcm/Makefile
 create mode 100644 drivers/thermal/bcm/bcm2835_thermal.c

--
2.1.4


From kernel at martin.sperl.org  Fri May 13 06:13:02 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Fri, 13 May 2016 13:13:02 +0000
Subject: [PATCH-V2 1/5] dt: bindings: add thermal device driver for bcm2835
In-Reply-To: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
References: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463145186-12906-2-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add documentation for bcm2835 SOC thermal sensor.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
Acked-by: Eric Anholt <eric at anholt.net>

Changelog:
 V1 -> V2: renamed file to follow naming conventions
---
 .../bindings/thermal/brcm,bcm2835-thermal.txt           | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt

diff --git a/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
new file mode 100644
index 0000000..09de164
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
@@ -0,0 +1,17 @@
+Binding for Thermal Sensor driver for BCM2835 SoCs.
+
+Required parameters:
+-------------------
+
+compatible: 	should be one of: "brcm,bcm2835-thermal",
+		"brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
+reg:		Address range of the thermal registers.
+clocks: 	Phandle of the clock used by the thermal sensor.
+
+Example:
+
+thermal: thermal at 0x7e212000 {
+	compatible = "brcm,bcm2835-thermal";
+	reg = <0x7e212000 0x8>;
+	clocks = <&clocks BCM2835_CLOCK_TSENS>;
+};
--
2.1.4


From kernel at martin.sperl.org  Fri May 13 06:13:03 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Fri, 13 May 2016 13:13:03 +0000
Subject: [PATCH-V2 2/5] thermal: bcm2835: add thermal driver for bcm2835 soc
In-Reply-To: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
References: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463145186-12906-3-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add basic thermal driver for bcm2835 SOC.

This driver currently relies on the firmware setting up the
tsense HW block and does not set it up itself.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>

ChangeLog:
 V1 -> V2: added specific settings depending on compatiblity
	   added trip point based on register
	   setting up ctrl-register if HW is not enabled by firmware
	     as per recommendation of Eric (untested)
	   check that clock frequency is in range
	     (1.9 - 5MHz - as per comment in clk-bcm2835.c)
---
 drivers/thermal/Kconfig               |   5 +
 drivers/thermal/Makefile              |   1 +
 drivers/thermal/bcm/Kconfig           |   4 +
 drivers/thermal/bcm/Makefile          |   1 +
 drivers/thermal/bcm/bcm2835_thermal.c | 326 ++++++++++++++++++++++++++++++++++
 5 files changed, 337 insertions(+)
 create mode 100644 drivers/thermal/bcm/Kconfig
 create mode 100644 drivers/thermal/bcm/Makefile
 create mode 100644 drivers/thermal/bcm/bcm2835_thermal.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 3c3dc4a..5b63d45 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -383,6 +383,11 @@ config MTK_THERMAL
 	  Enable this option if you want to have support for thermal management
 	  controller present in Mediatek SoCs
 
+menu "Broadcom thermal drivers"
+depends on ARCH_BCM || COMPILE_TEST
+source "drivers/thermal/bcm/Kconfig"
+endmenu
+
 menu "Texas Instruments thermal drivers"
 depends on ARCH_HAS_BANDGAP || COMPILE_TEST
 depends on HAS_IOMEM
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 8e9cbc3..6df1aa3 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -49,3 +49,4 @@ obj-$(CONFIG_ST_THERMAL)	+= st/
 obj-$(CONFIG_TEGRA_SOCTHERM)	+= tegra_soctherm.o
 obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
 obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
+obj-y				+= bcm/
diff --git a/drivers/thermal/bcm/Kconfig b/drivers/thermal/bcm/Kconfig
new file mode 100644
index 0000000..62245ae
--- /dev/null
+++ b/drivers/thermal/bcm/Kconfig
@@ -0,0 +1,4 @@
+config BCM2835_THERMAL
+       tristate "Thermal sensors on bcm2835 SoC"
+       help
+         Support for thermal sensors on Broadcom bcm2835 SoCs.
diff --git a/drivers/thermal/bcm/Makefile b/drivers/thermal/bcm/Makefile
new file mode 100644
index 0000000..13456d2
--- /dev/null
+++ b/drivers/thermal/bcm/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_BCM2835_THERMAL)		:= bcm2835_thermal.o
diff --git a/drivers/thermal/bcm/bcm2835_thermal.c b/drivers/thermal/bcm/bcm2835_thermal.c
new file mode 100644
index 0000000..73138cb
--- /dev/null
+++ b/drivers/thermal/bcm/bcm2835_thermal.c
@@ -0,0 +1,326 @@
+/*
+ * Driver for Broadcom BCM2835 soc temperature sensor
+ *
+ * Copyright (C) 2015 Martin Sperl
+ *
+ * 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.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+
+#define BCM2835_TS_TSENSCTL			0x00
+#define BCM2835_TS_TSENSSTAT			0x04
+
+#define BCM2835_TS_TSENSCTL_PRWDW		BIT(0)
+#define BCM2835_TS_TSENSCTL_RSTB		BIT(1)
+#define BCM2835_TS_TSENSCTL_CTRL_BITS		3
+#define BCM2835_TS_TSENSCTL_CTRL_SHIFT		2
+#define BCM2835_TS_TSENSCTL_CTRL_MASK		    \
+	GENMASK(BCM2835_TS_TSENSCTL_CTRL_BITS +     \
+		BCM2835_TS_TSENSCTL_CTRL_SHIFT - 1, \
+		BCM2835_TS_TSENSCTL_CTRL_SHIFT)
+#define BCM2835_TS_TSENSCTL_CTRL_DEFAULT	1
+#define BCM2835_TS_TSENSCTL_EN_INT		BIT(5)
+#define BCM2835_TS_TSENSCTL_DIRECT		BIT(6)
+#define BCM2835_TS_TSENSCTL_CLR_INT		BIT(7)
+#define BCM2835_TS_TSENSCTL_THOLD_SHIFT		8
+#define BCM2835_TS_TSENSCTL_THOLD_BITS		10
+#define BCM2835_TS_TSENSCTL_THOLD_MASK		     \
+	GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS +     \
+		BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \
+		BCM2835_TS_TSENSCTL_THOLD_SHIFT)
+#define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT	18
+#define BCM2835_TS_TSENSCTL_RSTDELAY_BITS	8
+#define BCM2835_TS_TSENSCTL_RSTDELAY_DEFAULT	14
+#define BCM2835_TS_TSENSCTL_REGULEN		BIT(26)
+
+#define BCM2835_TS_TSENSSTAT_DATA_BITS		10
+#define BCM2835_TS_TSENSSTAT_DATA_SHIFT		0
+#define BCM2835_TS_TSENSSTAT_DATA_MASK		     \
+	GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS +     \
+		BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \
+		BCM2835_TS_TSENSSTAT_DATA_SHIFT)
+#define BCM2835_TS_TSENSSTAT_VALID		BIT(10)
+#define BCM2835_TS_TSENSSTAT_INTERRUPT		BIT(11)
+
+struct bcm2835_thermal_info {
+	int offset;
+	int slope;
+	int trip_temp;
+};
+
+struct bcm2835_thermal_data {
+	const struct bcm2835_thermal_info *info;
+	void __iomem *regs;
+	struct clk *clk;
+	struct dentry *debugfsdir;
+};
+
+static int bcm2835_thermal_adc2temp(
+	const struct bcm2835_thermal_info *info, u32 adc)
+{
+	return info->offset + (adc * info->slope);
+}
+
+static int bcm2835_thermal_temp2adc(
+	const struct bcm2835_thermal_info *info, int temp)
+{
+	temp -= info->offset;
+	temp /= info->slope;
+
+	if (temp < 0)
+		temp = 0;
+	if (temp >= BIT(BCM2835_TS_TSENSSTAT_DATA_BITS))
+		temp = BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1;
+
+	return temp;
+}
+
+static int bcm2835_thermal_get_trip_type(
+	struct thermal_zone_device *tz, int trip,
+	enum thermal_trip_type *type)
+{
+	*type = THERMAL_TRIP_CRITICAL;
+	return 0;
+}
+
+static int bcm2835_thermal_get_trip_temp(
+	struct thermal_zone_device *tz, int trip, int *temp)
+{
+	struct bcm2835_thermal_data *data = tz->devdata;
+	u32 val = readl(data->regs + BCM2835_TS_TSENSCTL);
+
+	/* get the THOLD bits */
+	val &= BCM2835_TS_TSENSCTL_THOLD_MASK;
+	val >>= BCM2835_TS_TSENSCTL_THOLD_SHIFT;
+
+	/* if it is zero then use the info value */
+	if (val)
+		*temp = bcm2835_thermal_adc2temp(data->info, val);
+	else
+		*temp = data->info->trip_temp;
+
+	return 0;
+}
+
+static int bcm2835_thermal_get_temp(struct thermal_zone_device *tz,
+				    int *temp)
+{
+	struct bcm2835_thermal_data *data = tz->devdata;
+	u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT);
+
+	if (!(val & BCM2835_TS_TSENSSTAT_VALID))
+		return -EIO;
+
+	/* mask the relevant bits */
+	val &= BCM2835_TS_TSENSSTAT_DATA_MASK;
+
+	*temp = bcm2835_thermal_adc2temp(data->info, val);
+
+	return 0;
+}
+
+static const struct debugfs_reg32 bcm2835_thermal_regs[] = {
+	{
+		.name = "ctl",
+		.offset = 0
+	},
+	{
+		.name = "stat",
+		.offset = 4
+	}
+};
+
+static void bcm2835_thermal_debugfs(struct platform_device *pdev)
+{
+	struct thermal_zone_device *tz = platform_get_drvdata(pdev);
+	struct bcm2835_thermal_data *data = tz->devdata;
+	struct debugfs_regset32 *regset;
+
+	data->debugfsdir = debugfs_create_dir("bcm2835_thermal", NULL);
+	if (!data->debugfsdir)
+		return;
+
+	regset = devm_kzalloc(&pdev->dev, sizeof(*regset), GFP_KERNEL);
+	if (!regset)
+		return;
+
+	regset->regs = bcm2835_thermal_regs;
+	regset->nregs = ARRAY_SIZE(bcm2835_thermal_regs);
+	regset->base = data->regs;
+
+	debugfs_create_regset32("regset", S_IRUGO,
+				data->debugfsdir, regset);
+}
+
+static struct thermal_zone_device_ops bcm2835_thermal_ops  = {
+	.get_temp = bcm2835_thermal_get_temp,
+	.get_trip_temp = bcm2835_thermal_get_trip_temp,
+	.get_trip_type = bcm2835_thermal_get_trip_type,
+};
+
+static const struct of_device_id bcm2835_thermal_of_match_table[];
+static int bcm2835_thermal_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct thermal_zone_device *tz;
+	struct bcm2835_thermal_data *data;
+	struct resource *res;
+	int err;
+	u32 val;
+	unsigned long rate;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	match = of_match_device(bcm2835_thermal_of_match_table,
+				&pdev->dev);
+	if (!match)
+		return -EINVAL;
+	data->info = match->data;
+
+	/* get registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(data->regs)) {
+		err = PTR_ERR(data->regs);
+		dev_err(&pdev->dev, "Could not get registers: %d\n", err);
+		return err;
+	}
+
+	/* get clock */
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk)) {
+		err = PTR_ERR(data->clk);
+		if (err != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Could not get clk: %d\n", err);
+		return err;
+	}
+
+	/* set up registers if not already done by the fw */
+	val = readl(data->regs + BCM2835_TS_TSENSCTL);
+	if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {
+		/* the basic required flags */
+		val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT <<
+		       BCM2835_TS_TSENSCTL_CTRL_SHIFT) |
+		      BCM2835_TS_TSENSCTL_REGULEN;
+
+		/* reset delay */
+		val |= (BCM2835_TS_TSENSCTL_RSTDELAY_DEFAULT <<
+			BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);
+
+		/*  trip_adc value from info */
+		val |= bcm2835_thermal_temp2adc(data->info,
+						data->info->trip_temp) <<
+			BCM2835_TS_TSENSCTL_THOLD_SHIFT;
+
+		/* write the value back to the register as 2 steps */
+		writel(val, data->regs + BCM2835_TS_TSENSCTL);
+		val |= BCM2835_TS_TSENSCTL_RSTB;
+		writel(val, data->regs + BCM2835_TS_TSENSCTL);
+	}
+
+	/* enable clock and check rate */
+	clk_prepare_enable(data->clk);
+	rate = clk_get_rate(data->clk);
+	if ((rate < 1920000) || (rate > 5000000)) {
+		dev_warn(&pdev->dev,
+			 "Clock %pCn is running at %pCr Hz, which is outside the recommended range of 1.9 to 5.0 MHz\n",
+			 data->clk, data->clk);
+	}
+
+	/* register it */
+	tz = thermal_zone_device_register("bcm2835_thermal",
+					  1, 0, data,
+					  &bcm2835_thermal_ops,
+					  NULL, 0, 0);
+	if (IS_ERR(tz)) {
+		clk_disable_unprepare(data->clk);
+		err = PTR_ERR(tz);
+		dev_err(&pdev->dev,
+			"Failed to register the thermal device: %d\n",
+			err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, tz);
+
+	bcm2835_thermal_debugfs(pdev);
+
+	return 0;
+}
+
+static int bcm2835_thermal_remove(struct platform_device *pdev)
+{
+	struct thermal_zone_device *tz = platform_get_drvdata(pdev);
+	struct bcm2835_thermal_data *data = tz->devdata;
+
+	debugfs_remove_recursive(data->debugfsdir);
+	thermal_zone_device_unregister(tz);
+
+	return 0;
+}
+
+static const struct of_device_id bcm2835_thermal_of_match_table[] = {
+	{
+		.compatible = "brcm,bcm2835-thermal",
+		.data = &(struct bcm2835_thermal_info) {
+			.offset = 407000,
+			.slope = -538,
+			.trip_temp = 80000
+		}
+	},
+	{
+		.compatible = "brcm,bcm2836-thermal",
+		.data = &(struct bcm2835_thermal_info) {
+			.offset = 407000,
+			.slope = -538,
+			.trip_temp = 80000
+		}
+	},
+	{
+		.compatible = "brcm,bcm2837-thermal",
+		.data = &(struct bcm2835_thermal_info) {
+			/* the bcm2837 needs adjustment of +5C */
+			.offset = 407000 + 5000,
+			.slope = -538,
+			.trip_temp = 80000
+		}
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);
+
+static struct platform_driver bcm2835_thermal_driver = {
+	.probe = bcm2835_thermal_probe,
+	.remove = bcm2835_thermal_remove,
+	.driver = {
+		.name = "bcm2835_thermal",
+		.of_match_table = bcm2835_thermal_of_match_table,
+	},
+};
+module_platform_driver(bcm2835_thermal_driver);
+
+MODULE_AUTHOR("Martin Sperl");
+MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");
+MODULE_LICENSE("GPL");
-- 
2.1.4



From kernel at martin.sperl.org  Fri May 13 06:13:04 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Fri, 13 May 2016 13:13:04 +0000
Subject: [PATCH-V2 3/5] ARM: bcm2835: add thermal node to device-tree of
 bcm283x
In-Reply-To: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
References: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463145186-12906-4-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add the node for the thermal sensor of the bcm2835-soc
to the device tree.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
Reviewed-by: Eric Anholt <eric at anholt.net>
---
 arch/arm/boot/dts/bcm283x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index 8aaf193..2b5cbc6 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
+++ b/arch/arm/boot/dts/bcm283x.dtsi
@@ -153,6 +153,12 @@
 			status = "disabled";
 		};
 
+		thermal: thermal at 0x7e212000 {
+			compatible = "brcm,bcm2835-thermal";
+			reg = <0x7e212000 0x8>;
+			clocks = <&clocks BCM2835_CLOCK_TSENS>;
+		};
+
 		aux: aux at 0x7e215000 {
 			compatible = "brcm,bcm2835-aux";
 			#clock-cells = <1>;
-- 
2.1.4



From kernel at martin.sperl.org  Fri May 13 06:13:05 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Fri, 13 May 2016 13:13:05 +0000
Subject: [PATCH-V2 4/5] ARM: bcm2835: add thermal driver to default_config
In-Reply-To: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
References: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463145186-12906-5-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add the thermal driver to list of compiled modules
in the default config for bcm2835.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
Reviewed-by: Eric Anholt <eric at anholt.net>
---
 arch/arm/configs/bcm2835_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index 1ef69fc..f254d6b 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -71,6 +71,8 @@ CONFIG_SPI_BCM2835=y
 CONFIG_SPI_BCM2835AUX=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_BCM2835_THERMAL=y
 CONFIG_WATCHDOG=y
 CONFIG_BCM2835_WDT=y
 CONFIG_FB=y
-- 
2.1.4



From kernel at martin.sperl.org  Fri May 13 06:13:06 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Fri, 13 May 2016 13:13:06 +0000
Subject: [PATCH-V2 5/5] ARM: multi_v7_defconfig: bcm2835: add bcm2835-thermal
 driver
In-Reply-To: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
References: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463145186-12906-6-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add the thermal driver to list of compiled modules in
multi_v7_defconfig.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 2823490..5f0f5a3 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -422,6 +422,7 @@ CONFIG_CPU_THERMAL=y
 CONFIG_ROCKCHIP_THERMAL=y
 CONFIG_RCAR_THERMAL=y
 CONFIG_ARMADA_THERMAL=y
+CONFIG_BCM2835_THERMAL=y
 CONFIG_DAVINCI_WATCHDOG=m
 CONFIG_EXYNOS_THERMAL=m
 CONFIG_ST_THERMAL_SYSCFG=y
-- 
2.1.4



From arnd at arndb.de  Fri May 13 06:30:13 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 13 May 2016 15:30:13 +0200
Subject: [PATCH] ARM: hide finish_arch_post_lock_switch from modules
Message-ID: <1463146234-161304-1-git-send-email-arnd@arndb.de>

From: Steven Rostedt <rostedt at goodmis.org>

The introduction of switch_mm_irqs_off() brought back an old bug
regarding the use of preempt_enable_no_resched:

As part of 62b94a08da1b ("sched/preempt: Take away
preempt_enable_no_resched() from modules"), the definition of
preempt_enable_no_resched() is only available in built-in code,
not in loadable modules, so we can't generally use it from header
files. However, the ARM version of finish_arch_post_lock_switch()
calls preempt_enable_no_resched() and is defined as a static
inline function in asm/mmu_context.h. This in turn means we cannot
include asm/mmu_context.h from modules.

With today's tip tree, asm/mmu_context.h gets included from
linux/mmu_context.h, which is normally the exact pattern one would
expect, but unfortunately, linux/mmu_context.h can be included from
the vhost driver that is a loadable module, now causing this compile
time error:

In file included from ../include/linux/mmu_context.h:4:0,
                 from ../drivers/vhost/vhost.c:18:
../arch/arm/include/asm/mmu_context.h: In function 'finish_arch_post_lock_switch':
../arch/arm/include/asm/mmu_context.h:88:3: error: implicit declaration of function 'preempt_enable_no_resched' [-Werror=implicit-function-declaration]
   preempt_enable_no_resched();

Andy already tried to fix the bug by including linux/preempt.h
from asm/mmu_context.h, but that didn't help. I suggested reordering
the header files, which wasn't popular, but Steve came up with this
workaround instead:

The finish_arch_post_lock_switch() definition is now also hidden
inside of #ifdef MODULE, so we don't see anything referencing
preempt_enable_no_resched() from a header file. I've built a
few hundred randconfig kernels with this, and did not see any
new problems.

Fixes: f98db6013c55 ("sched/core: Add switch_mm_irqs_off() and use it in the scheduler")
Signed-off-by: Steven Rostedt <rostedt at goodmis.org>
Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Acked-by: Russell King <rmk+kernel at arm.linux.org.uk>
---
 arch/arm/include/asm/mmu_context.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h
index ed73babc0dc9..3cc14dd8587c 100644
--- a/arch/arm/include/asm/mmu_context.h
+++ b/arch/arm/include/asm/mmu_context.h
@@ -67,6 +67,7 @@ static inline void check_and_switch_context(struct mm_struct *mm,
 		cpu_switch_mm(mm->pgd, mm);
 }
 
+#ifndef MODULE
 #define finish_arch_post_lock_switch \
 	finish_arch_post_lock_switch
 static inline void finish_arch_post_lock_switch(void)
@@ -88,6 +89,7 @@ static inline void finish_arch_post_lock_switch(void)
 		preempt_enable_no_resched();
 	}
 }
+#endif /* !MODULE */
 
 #endif	/* CONFIG_MMU */
 
-- 
2.7.0



From catalin.marinas at arm.com  Fri May 13 06:32:12 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 13 May 2016 14:32:12 +0100
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <20160513092802.GA13400@localhost.localdomain>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <20160512002000.GA30997@yury-N73SV>
 <20160512133533.GF11226@e104818-lin.cambridge.arm.com>
 <20160512134431.GB30205@yury-N73SV>
 <20160512140734.GG11226@e104818-lin.cambridge.arm.com>
 <20160512142457.GC30205@yury-N73SV>
 <20160512152805.GJ11226@e104818-lin.cambridge.arm.com>
 <57358C2B.1010106@huawei.com>
 <20160513092802.GA13400@localhost.localdomain>
Message-ID: <20160513133212.GC27232@e104818-lin.cambridge.arm.com>

On Fri, May 13, 2016 at 09:28:03AM +0000, Catalin Marinas wrote:
> > >>>>>On Thu, May 12, 2016 at 03:20:00AM +0300, Yury Norov wrote:
> > >>>>>>I debugged preadv02 and pwritev02 failures and found very weird bug.
> > >>>>>>Test passes {iovec_base = 0xffffffff, iovec_len = 64} as one element
> > >>>>>>of vector, and kernel reports successful read/write.
[...]
> The discussion is mainly around whether USER_DS for 32-bit compat apps
> should be the same as USER_DS for native 32-bit apps. Even for native
> 32-bit kernels, we don't use STACK_TOP as addr_limit. A read/write from
> 0xffffffff would fail in both cases anyway. I think the LTP test doesn't
> even try to access such memory but only to probe the range validity (I
> haven't managed to build the latest LTP yet).

OK, so I managed to get the latest LTP (tag 20160510) built for AArch32
but the preadv02 does not fail:

-----------------------------
# uname -m
aarch64

# file ./testcases/bin/preadv02
./testcases/bin/preadv02: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=98066291426e1d3ee49d8504ce2a5bd721ab7fe8, not stripped

# ./testcases/bin/preadv02
preadv02.c:97: PASS: preadv() failed as expected: EINVAL
preadv02.c:97: PASS: preadv() failed as expected: EINVAL
preadv02.c:97: PASS: preadv() failed as expected: EINVAL
preadv02.c:97: PASS: preadv() failed as expected: EFAULT
preadv02.c:97: PASS: preadv() failed as expected: EBADF
preadv02.c:97: PASS: preadv() failed as expected: EBADF
preadv02.c:97: PASS: preadv() failed as expected: EISDIR
preadv02.c:97: PASS: preadv() failed as expected: ESPIPE

Summary:
passed   8
failed   0
skipped  0
warnings 0
-----------------------------

It's the 4th test above which passes iovec_base as -1 and expects
EFAULT. However, it seems to get the expected error. I guess that even
if access_ok() passes, the access to that location by the kernel would
fail since there isn't anything mapped.

With ILP32, however, STACK_TOP is TASK_SIZE and you may have the address
mapped already. I still think the USER_DS fix is useful, though I need
another way to check that it's actually a fix.

-- 
Catalin


From arnd at arndb.de  Fri May 13 06:41:11 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 13 May 2016 15:41:11 +0200
Subject: [PATCH 3/3] ARM: dts: clps711x: Add basic Cirrus Logic CDB89712
 Development board
In-Reply-To: <1463142623.38124260@f381.i.mail.ru>
References: <1463138788-5390-1-git-send-email-shc_work@mail.ru>
 <9407200.bOeiVUkGKT@wuerfel> <1463142623.38124260@f381.i.mail.ru>
Message-ID: <6057172.X40sTfvRlk@wuerfel>

On Friday 13 May 2016 15:30:23 Alexander Shiyan wrote:
> Hello.
> 
> > ???????, 13 ??? 2016, 15:00 +03:00 ?? Arnd Bergmann <arnd at arndb.de>:
> > 
> > On Friday 13 May 2016 14:26:28 Alexander Shiyan wrote:
> ...
> > > +	soc {
> > > +		#address-cells = <1>;
> > > +		#size-cells = <1>;
> > > +		compatible = "simple-bus";
> > > +		interrupt-parent = <&intc>;
> > > +		ranges;
> > 
> > All child devices seem to be in the 0x80000000-0x90000000
> > range, maybe set the ranges property accordingly?
> 
> I do not quite understand that you want to change here.

I meant using the ranges property to describe the bus addresses
without the 0x80000000 offset, like

	ranges = <0 0x8000000 0xc000>;

and then adapting the registers under the node to be based
on the bus address.


> > > +		clks: clks at 80000000 {
> > > +			#clock-cells = <1>;
> > > +			compatible = "cirrus,clps711x-clk";
> > > +			reg = <0x80000000 0xc000>;
> > > +			startup-frequency = <73728000>;
> > > +		};
> ...
> > > +		intc: intc at 80000000 {
> > > +			compatible = "cirrus,clps711x-intc";
> > > +			reg = <0x80000000 0x4000>;
> > > +			interrupt-controller;
> > > +			#interrupt-cells = <1>;
> > > +		};
> > 
> > Better make the register ranges non-overlapping. This appears
> > to start at the same place as the 'clks' node.
> 
> CLK driver uses:
> #define CLPS711X_SYSCON1 (0x0100)
> #define CLPS711X_SYSCON2 (0x1100)
> ...
> #define CLPS711X_PLLR (0xa5a8)
> 
> IRQCHIP driver uses:
> #define CLPS711X_INTSR1 (0x0240)
> ...
> #define CLPS711X_INTSR2 (0x1240)
> ...
> #define CLPS711X_INTMR3 (0x2280)
> 
> So there is no way to do any else.

It sounds like what you have is a large system controller that
has registers everywhere. Could you use syscon to access the
individual registers instead?

> > > +		porta: gpio at 80000000 {
> > > +			compatible = "cirrus,clps711x-gpio";
> > > +			reg = <0x80000000 0x1 0x80000040 0x1>;
> > > +			gpio-controller;
> > > +			#gpio-cells = <2>;
> > > +		};
> > > +
> > > +		portb: gpio at 80000001 {
> > > +			compatible = "cirrus,clps711x-gpio";
> > > +			reg = <0x80000001 0x1 0x80000041 0x1>;
> > > +			gpio-controller;
> > > +			#gpio-cells = <2>;
> > > +		};
> > > +
> > > +		portc: gpio at 80000002 {
> > > +			compatible = "cirrus,clps711x-gpio";
> > > +			reg = <0x80000002 0x1 0x80000042 0x1>;
> > > +			gpio-controller;
> > > +			#gpio-cells = <2>;
> > > +			status = "disabled";
> > > +		};
> > > +
> > > +		portd: gpio at 80000003 {
> > > +			compatible = "cirrus,clps711x-gpio";
> > > +			reg = <0x80000003 0x1 0x80000043 0x1>;
> > > +			gpio-controller;
> > > +			#gpio-cells = <2>;
> > > +		};
> > 
> > These are all just single bytes. My guess is that there is
> > actually one IP block that contains all the gpios, not
> > four identical blocks.
> 
> These is a 8-bit registers with different properties, which parses in the
> GPIO driver depending of alias (GPIO count, inverted logic etc.).

The alias should not influence the interpretation of the registers.
If each byte in there behaves differently, it would be better to
have separate "compatible" strings instead. I still don't see why
you can't just have one device node for all the registers and
then create multiple gpio_chip instances from that though.

	Arnd


From k.kozlowski at samsung.com  Fri May 13 06:44:26 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 13 May 2016 15:44:26 +0200
Subject: [PATCH] arm64: dts: exynos: Use human-friendly symbols for timer
 interrupt flags
Message-ID: <1463147066-8902-1-git-send-email-k.kozlowski@samsung.com>

Replace hex flags with human-readable symbols from arm-gic.h header
which makes it easier to recognize what is configured.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm64/boot/dts/exynos/exynos7.dtsi | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi
index ca663dfe5189..8d7ce97c0ddb 100644
--- a/arch/arm64/boot/dts/exynos/exynos7.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi
@@ -10,6 +10,7 @@
  */
 
 #include <dt-bindings/clock/exynos7-clk.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 
 / {
 	compatible = "samsung,exynos7";
@@ -473,10 +474,14 @@
 
 		timer {
 			compatible = "arm,armv8-timer";
-			interrupts = <1 13 0xff01>,
-				     <1 14 0xff01>,
-				     <1 11 0xff01>,
-				     <1 10 0xff01>;
+			interrupts = <GIC_PPI 13
+					(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_EDGE_RISING)>,
+				     <GIC_PPI 14
+					(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_EDGE_RISING)>,
+				     <GIC_PPI 11
+					(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_EDGE_RISING)>,
+				     <GIC_PPI 10
+					(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_EDGE_RISING)>;
 		};
 
 		pmu_system_controller: system-controller at 105c0000 {
-- 
1.9.1



From linux at roeck-us.net  Fri May 13 06:51:05 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 13 May 2016 06:51:05 -0700
Subject: [PATCH] ARM: hide finish_arch_post_lock_switch from modules
In-Reply-To: <1463146234-161304-1-git-send-email-arnd@arndb.de>
References: <1463146234-161304-1-git-send-email-arnd@arndb.de>
Message-ID: <5735DBC9.10204@roeck-us.net>

On 05/13/2016 06:30 AM, Arnd Bergmann wrote:
> From: Steven Rostedt <rostedt at goodmis.org>
>
> The introduction of switch_mm_irqs_off() brought back an old bug
> regarding the use of preempt_enable_no_resched:
>
> As part of 62b94a08da1b ("sched/preempt: Take away
> preempt_enable_no_resched() from modules"), the definition of
> preempt_enable_no_resched() is only available in built-in code,
> not in loadable modules, so we can't generally use it from header
> files. However, the ARM version of finish_arch_post_lock_switch()
> calls preempt_enable_no_resched() and is defined as a static
> inline function in asm/mmu_context.h. This in turn means we cannot
> include asm/mmu_context.h from modules.
>
> With today's tip tree, asm/mmu_context.h gets included from
> linux/mmu_context.h, which is normally the exact pattern one would
> expect, but unfortunately, linux/mmu_context.h can be included from
> the vhost driver that is a loadable module, now causing this compile
> time error:
>
> In file included from ../include/linux/mmu_context.h:4:0,
>                   from ../drivers/vhost/vhost.c:18:
> ../arch/arm/include/asm/mmu_context.h: In function 'finish_arch_post_lock_switch':
> ../arch/arm/include/asm/mmu_context.h:88:3: error: implicit declaration of function 'preempt_enable_no_resched' [-Werror=implicit-function-declaration]
>     preempt_enable_no_resched();
>
> Andy already tried to fix the bug by including linux/preempt.h
> from asm/mmu_context.h, but that didn't help. I suggested reordering
> the header files, which wasn't popular, but Steve came up with this
> workaround instead:
>
> The finish_arch_post_lock_switch() definition is now also hidden
> inside of #ifdef MODULE, so we don't see anything referencing
> preempt_enable_no_resched() from a header file. I've built a
> few hundred randconfig kernels with this, and did not see any
> new problems.
>
> Fixes: f98db6013c55 ("sched/core: Add switch_mm_irqs_off() and use it in the scheduler")
> Signed-off-by: Steven Rostedt <rostedt at goodmis.org>
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Acked-by: Russell King <rmk+kernel at arm.linux.org.uk>

Tested-by: Guenter Roeck <linux at roeck-us.net>

> ---
>   arch/arm/include/asm/mmu_context.h | 2 ++
>   1 file changed, 2 insertions(+)
>
> diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h
> index ed73babc0dc9..3cc14dd8587c 100644
> --- a/arch/arm/include/asm/mmu_context.h
> +++ b/arch/arm/include/asm/mmu_context.h
> @@ -67,6 +67,7 @@ static inline void check_and_switch_context(struct mm_struct *mm,
>   		cpu_switch_mm(mm->pgd, mm);
>   }
>
> +#ifndef MODULE
>   #define finish_arch_post_lock_switch \
>   	finish_arch_post_lock_switch
>   static inline void finish_arch_post_lock_switch(void)
> @@ -88,6 +89,7 @@ static inline void finish_arch_post_lock_switch(void)
>   		preempt_enable_no_resched();
>   	}
>   }
> +#endif /* !MODULE */
>
>   #endif	/* CONFIG_MMU */
>
>



From arnd at arndb.de  Fri May 13 06:53:38 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 13 May 2016 15:53:38 +0200
Subject: [PATCH] pinctrl: stm32: fix debugfs format string
Message-ID: <1463147643-568615-1-git-send-email-arnd@arndb.de>

The newly added stm32_pconf_dbg_show function has an incorrect format
string that does not match the arguments, as reported by the gcc warning:

drivers/pinctrl/stm32/pinctrl-stm32.c: In function 'stm32_pconf_dbg_show':
drivers/pinctrl/stm32/pinctrl-stm32.c:797:17: error: too many arguments for format [-Werror=format-extra-args]

This changes the format string in a way that gets rid of the warning.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 3beed93c1617 ("pinctrl: stm32: Implement .pin_config_dbg_show()")
---
I could not find a documentation for the debugfs format, so no
idea if this is the intended format.
---
 drivers/pinctrl/stm32/pinctrl-stm32.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index e51c1cf5270b..4ffbe9551299 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -794,7 +794,7 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
 	case 2:
 		drive = stm32_pconf_get_driving(bank, offset);
 		speed = stm32_pconf_get_speed(bank, offset);
-		seq_printf(s, "%d - %s -%s", alt,
+		seq_printf(s, "%d - %s - %s - %s %s ", alt,
 			   drive ? "open drain" : "push pull",
 			   biasing[bias],
 			   speeds[speed], "speed");
-- 
2.7.0



From ulf.hansson at linaro.org  Fri May 13 06:59:59 2016
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Fri, 13 May 2016 15:59:59 +0200
Subject: [PATCH] PM / Runtime: Defer resuming of the device in
 pm_runtime_force_resume()
In-Reply-To: <CAJZ5v0jTAM74asCM5gG5wBWn+gvSQ21_W6dY9WQD+cMybUnEEg@mail.gmail.com>
References: <1461234842-22820-1-git-send-email-ulf.hansson@linaro.org>
 <5465506.Z3sjI0lQh6@avalon>
 <CAPDyKFpOxabizwQqhtKb-h0vGpTRtrCa0nPxAKMY22rnjLCouw@mail.gmail.com>
 <4661739.p5SU9QcIps@avalon>
 <CAJZ5v0jTAM74asCM5gG5wBWn+gvSQ21_W6dY9WQD+cMybUnEEg@mail.gmail.com>
Message-ID: <CAPDyKFqJqq7hUFBvo91hc-5H7fwu2WfcOzxGO25VopZ3CwNoXA@mail.gmail.com>

On 12 May 2016 at 22:28, Rafael J. Wysocki <rafael at kernel.org> wrote:
> On Thu, May 12, 2016 at 9:01 PM, Laurent Pinchart
> <laurent.pinchart at ideasonboard.com> wrote:
>> Hello,
>>
>> On Wednesday 27 Apr 2016 16:23:49 Ulf Hansson wrote:
>>> [...]
>>>
>>> >> Following you reasoning, I agree!
>>> >>
>>> >> Let's put this patch on hold for a little while. I am already working
>>> >> on changing genpd, so it shouldn't take long before I can post some
>>> >> additional genpd patches improving the behaviour.
>>> >
>>> > I'd like to see something merged for v4.7 if possible. I agree that my
>>> > patch isn't a long term solution (we want to avoid adding additional
>>> > fields to the device power structure), but it has the benefit of being
>>> > available now and fixing the problem I ran into with drivers that would
>>> > be broken on v4.7 without a fix. Do you think you could get a better fix
>>> > ready in time for v4.7 ? If so I'm fine with dropping this patch, but
>>> > otherwise I'd prefer to get it merged and reverted as part of your better
>>> > implementation for v4.8.
>>>
>>> My impression was that devices becomes unnecessary resumed when they
>>> don't need to. They won't stay resumed as the PM core invokes
>>> pm_runtime_put() in the system PM complete phase.
>>>
>>> So, in the end I think we are trying to optimize a behaviour here, but
>>> not fix something that is "broken", correct?
>>>
>>> Anyway, I have no objections to your proposed solution, so I leave it
>>> to Rafael and Kevin to decide what to do.
>>
>> Kevin, Rafael, any comment ? I need to fix PM support in a driver that is
>> currently broken partly due to this issue. Which of "PM / Runtime: Only force-
>> resume device if it has been force-suspended" and this patch should we merge,
>> if any ?
>
> My and Kevin's assumption was that Ulf would provide a better fix
> shortly, but I'm not sure how realistic that is.

First, is this really a fix we are talking about or an optimization? Laurent?

Second, I currently have patches for genpd etc that I think may deals
with this better, although I need a day or two before I can post them.

Additionally, "[PATCH v3 1/2] PM / Domains: Allow genpd to power on
during the system PM phases", has been posted [1] already.
That change, will prevent Laurent's approach to work and it's because
genpd will force a runtime resume of the device in the system PM
prepare phase. This means pm_genpd_force_resume() will anyway *always*
resume the device.

Kind regards
Uffe

[1]
http://www.spinics.net/lists/dri-devel/msg107210.html


From narmstrong at baylibre.com  Fri May 13 07:00:09 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 13 May 2016 16:00:09 +0200
Subject: [RFC PATCH 0/3] Amlogic: GXBB: Add reset controller
Message-ID: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>

Patchset to add and enable the reset controller driver on GXBB platforms.

Neil Armstrong (3):
  reset: Add support for the Amlogic Meson GXBB Reset Controller
  dt-bindings: reset: Add bindings for the Meson GXBB Reset Controller
  ARM64: dts: amlogic: Enable Reset Controller on GXBB-based platforms

 .../bindings/reset/amlogic,meson-gxbb-reset.txt    |  16 +++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   6 +
 drivers/reset/Kconfig                              |   6 +
 drivers/reset/Makefile                             |   1 +
 drivers/reset/reset-meson-gxbb.c                   | 160 +++++++++++++++++++++
 .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 160 +++++++++++++++++++++
 6 files changed, 349 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/amlogic,meson-gxbb-reset.txt
 create mode 100644 drivers/reset/reset-meson-gxbb.c
 create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h

-- 
2.7.0



From narmstrong at baylibre.com  Fri May 13 07:00:10 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 13 May 2016 16:00:10 +0200
Subject: [RFC PATCH 1/3] reset: Add support for the Amlogic Meson GXBB Reset
 Controller
In-Reply-To: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>
References: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1463148012-25988-2-git-send-email-narmstrong@baylibre.com>

This patch adds the platform driver for the Amlogic Meson GXBB Reset
Controller.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/reset/Kconfig            |   6 ++
 drivers/reset/Makefile           |   1 +
 drivers/reset/reset-meson-gxbb.c | 160 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 167 insertions(+)
 create mode 100644 drivers/reset/reset-meson-gxbb.c

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index df37212..4ac5c4d 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -12,5 +12,11 @@ menuconfig RESET_CONTROLLER
 
 	  If unsure, say no.
 
+config MESON_GXBB_RESET
+	tristate "Amlogic Meson GXBB Reset Driver"
+	depends on (ARCH_MESON && RESET_CONTROLLER)
+	help
+	  Build the Amlogic Meson GxBB reset driver.
+
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index a1fc8ed..5ff83a1 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
 obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
 obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
 obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o
+obj-$(CONFIG_MESON_GXBB_RESET) += reset-meson-gxbb.o
 obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_HISI) += hisilicon/
diff --git a/drivers/reset/reset-meson-gxbb.c b/drivers/reset/reset-meson-gxbb.c
new file mode 100644
index 0000000..798fdf9
--- /dev/null
+++ b/drivers/reset/reset-meson-gxbb.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * 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 <linux/err.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define REG_COUNT	7
+#define BITS_PER_REG	16
+
+struct meson_gxbb_reset {
+	void *reg_base;
+	struct reset_controller_dev rcdev;
+};
+
+static int meson_gxbb_reset_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct meson_gxbb_reset *data =
+		container_of(rcdev, struct meson_gxbb_reset, rcdev);
+	unsigned int bank = id / BITS_PER_REG;
+	unsigned int offset = id % BITS_PER_REG;
+	void *reg_addr = data->reg_base + (bank << 2);
+
+	if (bank >= REG_COUNT)
+		return -EINVAL;
+
+	writel(readl(reg_addr) | BIT(offset), reg_addr);
+
+	return 0;
+}
+
+static int meson_gxbb_reset_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct meson_gxbb_reset *data =
+		container_of(rcdev, struct meson_gxbb_reset, rcdev);
+	unsigned int bank = id / BITS_PER_REG;
+	unsigned int offset = id % BITS_PER_REG;
+	void *reg_addr = data->reg_base + (bank << 2);
+
+	if (bank >= REG_COUNT)
+		return -EINVAL;
+
+	writel(readl(reg_addr) & ~BIT(offset), reg_addr);
+
+	return 0;
+}
+
+static int meson_gxbb_reset_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	int err;
+
+	err = meson_gxbb_reset_assert(rcdev, id);
+	if (err)
+		return err;
+
+	return meson_gxbb_reset_deassert(rcdev, id);
+}
+
+static const struct reset_control_ops meson_gxbb_reset_ops = {
+	.reset		= meson_gxbb_reset_reset,
+	.assert		= meson_gxbb_reset_assert,
+	.deassert	= meson_gxbb_reset_deassert,
+};
+
+static const struct of_device_id meson_gxbb_reset_dt_ids[] = {
+	 { .compatible = "amlogic,meson-gxbb-reset", },
+	 { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, meson_gxbb_reset_dt_ids);
+
+static int meson_gxbb_reset_probe(struct platform_device *pdev)
+{
+	struct meson_gxbb_reset *data;
+	struct resource *res;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(data->reg_base))
+		return PTR_ERR(data->reg_base);
+
+	platform_set_drvdata(pdev, data);
+
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = REG_COUNT * BITS_PER_REG;
+	data->rcdev.ops = &meson_gxbb_reset_ops;
+	data->rcdev.of_node = pdev->dev.of_node;
+
+	return reset_controller_register(&data->rcdev);
+}
+
+static int meson_gxbb_reset_remove(struct platform_device *pdev)
+{
+	struct meson_gxbb_reset *data = platform_get_drvdata(pdev);
+
+	reset_controller_unregister(&data->rcdev);
+
+	return 0;
+}
+
+static struct platform_driver meson_gxbb_reset_driver = {
+	.probe	= meson_gxbb_reset_probe,
+	.remove	= meson_gxbb_reset_remove,
+	.driver = {
+		.name		= "meson_gxbb_reset",
+		.of_match_table	= meson_gxbb_reset_dt_ids,
+	},
+};
+
+module_platform_driver(meson_gxbb_reset_driver);
-- 
2.7.0



From narmstrong at baylibre.com  Fri May 13 07:00:11 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 13 May 2016 16:00:11 +0200
Subject: [RFC PATCH 2/3] dt-bindings: reset: Add bindings for the Meson GXBB
 Reset Controller
In-Reply-To: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>
References: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1463148012-25988-3-git-send-email-narmstrong@baylibre.com>

Add DT bindings for the Meson GXBB SoC Reset Controller documentation and the
associated include file.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 .../bindings/reset/amlogic,meson-gxbb-reset.txt    |  16 +++
 .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 160 +++++++++++++++++++++
 2 files changed, 176 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/amlogic,meson-gxbb-reset.txt
 create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h

diff --git a/Documentation/devicetree/bindings/reset/amlogic,meson-gxbb-reset.txt b/Documentation/devicetree/bindings/reset/amlogic,meson-gxbb-reset.txt
new file mode 100644
index 0000000..8761317
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/amlogic,meson-gxbb-reset.txt
@@ -0,0 +1,16 @@
+Amlogic Meson GXBB SoC Reset Controller
+=======================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "amlogic,meson-gxbb-reset"
+- #reset-cells: 1, see below
+
+example:
+
+reset: reset-controller {
+	compatible = "amlogic,meson-gxbb-reset";
+	#reset-cells = <1>;
+};
diff --git a/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
new file mode 100644
index 0000000..44e73b8
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * 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.
+ */
+
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
+
+#define RESET_VCBUS		0
+/*				1	*/
+/*				2	*/
+#define RESET_GIC		3
+#define RESET_CAPB3_DECODE	4
+#define RESET_NAND_CAPB3	5
+#define RESET_HDMITX_CAPB3	6
+#define RESET_MALI_CAPB3	7
+#define RESET_DOS_CAPB3		8
+#define RESET_SYS_CPU_CAPB3	9
+#define RESET_CBUS_CAPB3	10
+#define RESET_AHB_CNTL		11
+#define RESET_AHB_DATA		12
+#define RESET_VCBUS_CLK81	13
+#define RESET_MMC		14
+#define RESET_MIPI		15
+#define RESET_PARSER		16
+#define RESET_BLKMV		17
+#define RESET_ISA		18
+#define RESET_Ethernet		19
+#define RESET_SD_EMMC_A		20
+#define RESET_SD_EMMC_B		21
+#define RESET_SD_EMMC_C		22
+#define RESET_ROM_BOOT		23
+#define RESET_SYS_CPU_3_0	24
+#define RESET_SYS_CPU_CORE_3_0	25
+#define RESET_SYS_PLL_DIV	26
+#define RESET_SYS_CPU_AXI	27
+#define RESET_SYS_CPU_L2	28
+#define RESET_SYS_CPU_P		29
+#define RESET_SYS_CPU_MBIST	30
+/*				31	*/
+#define RESET_VD_RMEM		32
+#define RESET_AUDIN		33
+#define RESET_HDMI_TX		34
+/*				35	*/
+/*				36	*/
+/*				37	*/
+#define RESET_GE2D		38
+#define RESET_PARSER_REG	39
+#define RESET_PARSER_FETCH	40
+#define RESET_PARSER_CTL	41
+#define RESET_PARSER_TOP	42
+/*				43	*/
+/*				44	*/
+#define RESET_AO_CPU_RESET	45
+#define RESET_MALI		46
+#define RESET_HDMI_SYSTEM_RESET	47
+#define RESET_RING_OSCILLATOR	48
+#define RESET_SYS_CPU		49
+#define RESET_EFUSE		50
+#define RESET_SYS_CPU_BVCI	51
+#define RESET_AIFIFO		52
+#define RESET_TVFE		53
+#define RESET_AHB_BRIDGE_CNTL	54
+/*				55	*/
+#define RESET_AUDIO_DAC		56
+#define RESET_DEMUX_TOP		57
+#define RESET_DEMUX_DES		58
+#define RESET_DEMUX_S2P_0	59
+#define RESET_DEMUX_S2P_1	60
+#define RESET_DEMUX_RESET_0	61
+#define RESET_DEMUX_RESET_1	62
+#define RESET_DEMUX_RESET_2	63
+#define RESET_DDR_PLL		64
+#define RESET_MISC_PLL		65
+/*				66	*/
+/*				67	*/
+#define RESET_DVIN_RESET	68
+#define RESET_RDMA		69
+#define RESET_VENCI		70
+#define RESET_VENCP		71
+/*				72	*/
+#define RESET_VDAC		73
+#define RESET_RTC		74
+/*				75	*/
+#define RESET_VDI6		76
+#define RESET_VENCL		77
+#define RESET_I2C_MASTER_2	78
+#define RESET_I2C_MASTER_1	79
+#define RESET_PERIPHS_GENERAL	80
+#define RESET_PERIPHS_SPICC	81
+#define RESET_PERIPHS_SMART_CARD	82
+#define RESET_PERIPHS_SAR_ADC	83
+#define RESET_PERIPHS_I2C_MASTER_0	84
+#define RESET_SANA		85
+/*				86	*/
+#define RESET_PERIPHS_STREAM_INTERFACE	87
+#define RESET_PERIPHS_SDIO	88
+#define RESET_PERIPHS_UART_0	89
+#define RESET_PERIPHS_UART_1_2	90
+#define RESET_PERIPHS_ASYNC_0	91
+#define RESET_PERIPHS_ASYNC_1	92
+#define RESET_PERIPHS_SPI_0	93
+#define RESET_PERIPHS_SDHC	94
+#define RESET_UART_SLIP		95
+#define RESET_USB_DDR_0		96
+#define RESET_USB_DDR_1		97
+#define RESET_USB_DDR_2		98
+#define RESET_USB_DDR_3		99
+/*				100	*/
+#define RESET_DEVICE_MMC_ARB	101
+/*				102	*/
+#define RESET_VID_LOCK		103
+#define RESET_A9_DMC_PIPEL	104
+/*				105	*/
+/*				106	*/
+/*				107	*/
+/*				108	*/
+/*				109	*/
+/*				110	*/
+/*				111	*/
+
+#endif
-- 
2.7.0



From narmstrong at baylibre.com  Fri May 13 07:00:12 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 13 May 2016 16:00:12 +0200
Subject: [RFC PATCH 3/3] ARM64: dts: amlogic: Enable Reset Controller on
 GXBB-based platforms
In-Reply-To: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>
References: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1463148012-25988-4-git-send-email-narmstrong@baylibre.com>

Update DTSI file to add the reset controller node.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 832815d..2b8fc0d 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -122,6 +122,12 @@
 		#size-cells = <2>;
 		ranges;
 
+		reset: reset-controller at c1004404 {
+			compatible = "amlogic,meson-gxbb-reset";
+			reg = <0x0 0xc1004404 0x0 0x1c>;
+			#reset-cells = <1>;
+		};
+
 		cbus: cbus at c1100000 {
 			compatible = "simple-bus";
 			reg = <0x0 0xc1100000 0x0 0x100000>;
-- 
2.7.0



From sre at kernel.org  Fri May 13 07:01:31 2016
From: sre at kernel.org (Sebastian Reichel)
Date: Fri, 13 May 2016 16:01:31 +0200
Subject: [PATCH 4/7] [media] ir-rx51: add DT support to driver
In-Reply-To: <5735710A.6060404@gmail.com>
References: <1462634508-24961-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <1462634508-24961-5-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <20160509200657.GA3379@rob-hp-laptop> <5730F8BA.5000402@gmail.com>
 <CAL_JsqJPZS1ne_xAuBFtCc5L1HKFJf0LDUJ7CRSFXhc3adkTfA@mail.gmail.com>
 <20160510021826.GE1129@earth> <20160511141429.GA5894@rob-hp-laptop>
 <5735710A.6060404@gmail.com>
Message-ID: <20160513140130.GA30391@earth>

Hi,

On Fri, May 13, 2016 at 09:15:38AM +0300, Ivaylo Dimitrov wrote:
> I prefer the shorter "nokia,n900-ir", will resend the series with
> it used, unless someone has concerns about it.

Sounds fine to me.

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160513/fe032d61/attachment.sig>

From christoffer.dall at linaro.org  Fri May 13 07:43:57 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 13 May 2016 16:43:57 +0200
Subject: [PATCH v3] KVM: arm/arm64: Add VGICv3 save/restore API documentation
Message-ID: <1463150637-6896-1-git-send-email-christoffer.dall@linaro.org>

Factor out the GICv3-specific documentation into a separate
documentation file.  Add description for how to access distributor,
redistributor, and CPU interface registers for GICv3 in this new file,
and add a group for accesing level triggered IRQ information for GICv3
as well.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changes since v2:
 - Changed distributor access to be 32-bits in size
 - Clearly specified data type pointed to by addr field
 - Specified exception behavior for STATUSR registers
 - Added group for level-triggered IRQ status info
 - Removed acks from Marc/Peter as content has changed

 Documentation/virtual/kvm/devices/arm-vgic-v3.txt | 176 ++++++++++++++++++++++
 Documentation/virtual/kvm/devices/arm-vgic.txt    |  21 +--
 2 files changed, 180 insertions(+), 17 deletions(-)
 create mode 100644 Documentation/virtual/kvm/devices/arm-vgic-v3.txt

diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
new file mode 100644
index 0000000..69201e8
--- /dev/null
+++ b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
@@ -0,0 +1,176 @@
+ARM Virtual Generic Interrupt Controller v3 and later (VGICv3)
+==============================================================
+
+
+Device types supported:
+  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
+
+Only one VGIC instance may be instantiated through this API.  The created VGIC
+will act as the VM interrupt controller, requiring emulated user-space devices
+to inject interrupts to the VGIC instead of directly to CPUs.  It is not
+possible to create both a GICv3 and GICv2 on the same VM.
+
+Creating a guest GICv3 device requires a host GICv3 as well.
+
+Groups:
+  KVM_DEV_ARM_VGIC_GRP_ADDR
+  Attributes:
+    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
+      Base address in the guest physical address space of the GICv3 distributor
+      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
+      This address needs to be 64K aligned and the region covers 64 KByte.
+
+    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
+      Base address in the guest physical address space of the GICv3
+      redistributor register mappings. There are two 64K pages for each
+      VCPU and all of the redistributor pages are contiguous.
+      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
+      This address needs to be 64K aligned.
+
+
+  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
+  KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
+  Attributes:
+    The attr field of kvm_device_attr encodes two values:
+    bits:     | 63   ....  32  |  31   ....    0 |
+    values:   |      mpidr     |      offset     |
+
+    All distributor regs are (rw, 32-bit) and kvm_device_attr.addr points to a
+    __u32 value.  64-bit registers must be accessed by separately accessing the
+    lower and higher word.
+
+    Writes to read-only registers can be ignored by the kernel.
+
+    KVM_DEV_ARM_VGIC_GRP_DIST_REGS accesses the main distributor registers.
+    KVM_DEV_ARM_VGIC_GRP_REDIST_REGS accesses the redistributor of the CPU
+    specified by the mpidr.
+
+    The offset is relative to the "[Re]Distributor base address" as defined
+    in the GICv3/4 specs.  Getting or setting such a register has the same
+    effect as reading or writing the register on real hardware (except for
+    GICD_STATUS and GICR_STATUSR, see blow), and the mpidr field is used to
+    specify which redistributor is accessed.  The mpidr is ignored for the
+    distributor.
+
+    The mpidr encoding is based on the affinity information in the
+    architecture defined MPIDR, and the field is encoded as follows:
+      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
+      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
+
+    Note that distributor fields are not banked, but return the same value
+    regardless of the mpidr used to access the register.
+
+    The GICD_STATUSR and GICR_STATUSR registers are architecturally defined such
+    that a write of a clear bit has no effect, whereas a write with a set bit
+    clears that value.  To allow userspace to freely set the values of these two
+    registers, setting the attributes with the register offsets for these two
+    registers simply sets the non-reserved bits to the value written.
+  Limitations:
+    - Priorities are not implemented, and registers are RAZ/WI
+  Errors:
+    -ENXIO: Getting or setting this register is not yet supported
+    -EBUSY: One or more VCPUs are running
+
+
+  KVM_DEV_ARM_VGIC_CPU_SYSREGS
+  Attributes:
+    The attr field of kvm_device_attr encodes two values:
+    bits:     | 63      ....       32 | 31  ....  16 | 15  ....  0 |
+    values:   |         mpidr         |      RES     |    instr    |
+
+    The mpidr field encodes the CPU ID based on the affinity information in the
+    architecture defined MPIDR, and the field is encoded as follows:
+      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
+      |    Aff3    |    Aff2    |    Aff1    |    Aff0   |
+
+    The instr field encodes the system register to access based on the fields
+    defined in the A64 instruction set encoding for system register access
+    (RES means the bits are reserved for future use and should be zero):
+
+      | 15 ... 14 | 13 ... 11 | 10 ... 7 | 6 ... 3 | 2 ... 0 |
+      |   Op 0    |    Op1    |    CRn   |   CRm   |   Op2   |
+
+    All system regs accessed through this API are (rw, 64-bit) and
+    kvm_device_attr.addr points to a __u64 value.
+
+    KVM_DEV_ARM_VGIC_CPU_SYSREGS accesses the CPU interface registers for the
+    CPU specified by the mpidr field.
+
+
+  Limitations:
+    - Priorities are not implemented, and registers are RAZ/WI
+  Errors:
+    -ENXIO: Getting or setting this register is not yet supported
+    -EBUSY: VCPU is running
+    -EINVAL: Invalid mpidr supplied
+
+
+  KVM_DEV_ARM_VGIC_GRP_NR_IRQS
+  Attributes:
+    A value describing the number of interrupts (SGI, PPI and SPI) for
+    this GIC instance, ranging from 64 to 1024, in increments of 32.
+
+    kvm_device_attr.addr points to a __u32 value.
+
+  Errors:
+    -EINVAL: Value set is out of the expected range
+    -EBUSY: Value has already be set.
+
+
+  KVM_DEV_ARM_VGIC_GRP_CTRL
+  Attributes:
+    KVM_DEV_ARM_VGIC_CTRL_INIT
+      request the initialization of the VGIC, no additional parameter in
+      kvm_device_attr.addr.
+  Errors:
+    -ENXIO: VGIC not properly configured as required prior to calling
+     this attribute
+    -ENODEV: no online VCPU
+    -ENOMEM: memory shortage when allocating vgic internal data
+
+
+  KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO
+  Attributes:
+    The attr field of kvm_device_attr encodes the following values:
+    bits:     | 63      ....       32 | 31   ....    10 | 9  ....  0 |
+    values:   |         mpidr         |      info       |   vINTID   |
+
+    The vINTID specifies which set of IRQs is reported on.
+
+    The info field specifies which information userspace wants to get or set
+    using this interface.  Currently we support two different pieces of
+    information:
+
+      VGIC_LEVEL_INFO_LINE_LEVEL:
+        Get/Set the intput level of the IRQ line for a given IRQ.
+	vINTID must be a multiple of 32.
+
+        kvm_device_attr.addr points to a __u32 value which will contain a
+	bitmap where a set bit means the interrupt level is asserted.
+
+	Bit[n] indicates the status for interrupt vINTID + n.
+
+
+      VGIC_LEVEL_INFO_SOFT_PENDING
+        Get/Set the latch state of a GIVEN level-triggered IRQ as manipulated by
+	guest writes to GICD_SPENDR.
+	vINTID must be a multiple of 32.
+
+        kvm_device_attr.addr points to a __u32 value which will contain a
+	bitmap where a set bit means the guest has set the interrupt by writing
+	to the SPENDR.
+
+	Bit[n] indicates the status for interrupt vINTID + n.
+
+
+    SGIs and any interrupt with a higher ID than the number of interrupts
+    supported, will be RAZ/WI.  LPIs are always edge-triggered and are
+    therefore not supported by this interface.
+
+    PPIs are reported per VCPU as specified in the mpidr field, and SPIs are
+    reported with the same value regardless of the mpidr specified.
+
+    The mpidr field encodes the CPU ID based on the affinity information in the
+    architecture defined MPIDR, and the field is encoded as follows:
+      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
+      |    Aff3    |    Aff2    |    Aff1    |    Aff0   |
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
index 59541d4..257b854 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic.txt
+++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
@@ -3,16 +3,16 @@ ARM Virtual Generic Interrupt Controller (VGIC)
 
 Device types supported:
   KVM_DEV_TYPE_ARM_VGIC_V2     ARM Generic Interrupt Controller v2.0
-  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
 
 Only one VGIC instance may be instantiated through either this API or the
 legacy KVM_CREATE_IRQCHIP api.  The created VGIC will act as the VM interrupt
 controller, requiring emulated user-space devices to inject interrupts to the
 VGIC instead of directly to CPUs.
 
-Creating a guest GICv3 device requires a host GICv3 as well.
-GICv3 implementations with hardware compatibility support allow a guest GICv2
-as well.
+GICv3 implementations with hardware compatibility support allow creating a
+guest GICv2 through this interface.  For information on creating a guest GICv3
+device, see arm-vgic-v3.txt.  It is not possible to create both a GICv3 and
+GICv2 device on the same VM.
 
 Groups:
   KVM_DEV_ARM_VGIC_GRP_ADDR
@@ -27,19 +27,6 @@ Groups:
       interface register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2.
       This address needs to be 4K aligned and the region covers 4 KByte.
 
-    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
-      Base address in the guest physical address space of the GICv3 distributor
-      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
-      This address needs to be 64K aligned and the region covers 64 KByte.
-
-    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
-      Base address in the guest physical address space of the GICv3
-      redistributor register mappings. There are two 64K pages for each
-      VCPU and all of the redistributor pages are contiguous.
-      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
-      This address needs to be 64K aligned.
-
-
   KVM_DEV_ARM_VGIC_GRP_DIST_REGS
   Attributes:
     The attr field of kvm_device_attr encodes two values:
-- 
2.1.2.330.g565301e.dirty



From marc.zyngier at arm.com  Fri May 13 08:05:19 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Fri, 13 May 2016 16:05:19 +0100
Subject: [PATCH v3] KVM: arm/arm64: Add VGICv3 save/restore API
 documentation
In-Reply-To: <1463150637-6896-1-git-send-email-christoffer.dall@linaro.org>
References: <1463150637-6896-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <5735ED2F.4030104@arm.com>

On 13/05/16 15:43, Christoffer Dall wrote:
> Factor out the GICv3-specific documentation into a separate
> documentation file.  Add description for how to access distributor,
> redistributor, and CPU interface registers for GICv3 in this new file,
> and add a group for accesing level triggered IRQ information for GICv3

accessing

> as well.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> ---
> Changes since v2:
>  - Changed distributor access to be 32-bits in size
>  - Clearly specified data type pointed to by addr field
>  - Specified exception behavior for STATUSR registers
>  - Added group for level-triggered IRQ status info
>  - Removed acks from Marc/Peter as content has changed
> 
>  Documentation/virtual/kvm/devices/arm-vgic-v3.txt | 176 ++++++++++++++++++++++
>  Documentation/virtual/kvm/devices/arm-vgic.txt    |  21 +--
>  2 files changed, 180 insertions(+), 17 deletions(-)
>  create mode 100644 Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> 
> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> new file mode 100644
> index 0000000..69201e8
> --- /dev/null
> +++ b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> @@ -0,0 +1,176 @@
> +ARM Virtual Generic Interrupt Controller v3 and later (VGICv3)
> +==============================================================
> +
> +
> +Device types supported:
> +  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
> +
> +Only one VGIC instance may be instantiated through this API.  The created VGIC
> +will act as the VM interrupt controller, requiring emulated user-space devices
> +to inject interrupts to the VGIC instead of directly to CPUs.  It is not
> +possible to create both a GICv3 and GICv2 on the same VM.
> +
> +Creating a guest GICv3 device requires a host GICv3 as well.
> +
> +Groups:
> +  KVM_DEV_ARM_VGIC_GRP_ADDR
> +  Attributes:
> +    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
> +      Base address in the guest physical address space of the GICv3 distributor
> +      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> +      This address needs to be 64K aligned and the region covers 64 KByte.
> +
> +    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
> +      Base address in the guest physical address space of the GICv3
> +      redistributor register mappings. There are two 64K pages for each
> +      VCPU and all of the redistributor pages are contiguous.
> +      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> +      This address needs to be 64K aligned.
> +
> +
> +  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
> +  KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
> +  Attributes:
> +    The attr field of kvm_device_attr encodes two values:
> +    bits:     | 63   ....  32  |  31   ....    0 |
> +    values:   |      mpidr     |      offset     |
> +
> +    All distributor regs are (rw, 32-bit) and kvm_device_attr.addr points to a
> +    __u32 value.  64-bit registers must be accessed by separately accessing the
> +    lower and higher word.
> +
> +    Writes to read-only registers can be ignored by the kernel.
> +
> +    KVM_DEV_ARM_VGIC_GRP_DIST_REGS accesses the main distributor registers.
> +    KVM_DEV_ARM_VGIC_GRP_REDIST_REGS accesses the redistributor of the CPU
> +    specified by the mpidr.
> +
> +    The offset is relative to the "[Re]Distributor base address" as defined
> +    in the GICv3/4 specs.  Getting or setting such a register has the same
> +    effect as reading or writing the register on real hardware (except for
> +    GICD_STATUS and GICR_STATUSR, see blow), and the mpidr field is used to

                                         below

> +    specify which redistributor is accessed.  The mpidr is ignored for the
> +    distributor.
> +
> +    The mpidr encoding is based on the affinity information in the
> +    architecture defined MPIDR, and the field is encoded as follows:
> +      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
> +      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
> +
> +    Note that distributor fields are not banked, but return the same value
> +    regardless of the mpidr used to access the register.
> +
> +    The GICD_STATUSR and GICR_STATUSR registers are architecturally defined such
> +    that a write of a clear bit has no effect, whereas a write with a set bit
> +    clears that value.  To allow userspace to freely set the values of these two
> +    registers, setting the attributes with the register offsets for these two
> +    registers simply sets the non-reserved bits to the value written.
> +  Limitations:
> +    - Priorities are not implemented, and registers are RAZ/WI
> +  Errors:
> +    -ENXIO: Getting or setting this register is not yet supported
> +    -EBUSY: One or more VCPUs are running
> +
> +
> +  KVM_DEV_ARM_VGIC_CPU_SYSREGS
> +  Attributes:
> +    The attr field of kvm_device_attr encodes two values:
> +    bits:     | 63      ....       32 | 31  ....  16 | 15  ....  0 |
> +    values:   |         mpidr         |      RES     |    instr    |
> +
> +    The mpidr field encodes the CPU ID based on the affinity information in the
> +    architecture defined MPIDR, and the field is encoded as follows:
> +      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
> +      |    Aff3    |    Aff2    |    Aff1    |    Aff0   |
> +
> +    The instr field encodes the system register to access based on the fields
> +    defined in the A64 instruction set encoding for system register access
> +    (RES means the bits are reserved for future use and should be zero):

Should we call this field RES0 in order to match the various
architecture documents?

> +
> +      | 15 ... 14 | 13 ... 11 | 10 ... 7 | 6 ... 3 | 2 ... 0 |
> +      |   Op 0    |    Op1    |    CRn   |   CRm   |   Op2   |
> +
> +    All system regs accessed through this API are (rw, 64-bit) and
> +    kvm_device_attr.addr points to a __u64 value.
> +
> +    KVM_DEV_ARM_VGIC_CPU_SYSREGS accesses the CPU interface registers for the
> +    CPU specified by the mpidr field.
> +
> +
> +  Limitations:
> +    - Priorities are not implemented, and registers are RAZ/WI

Is that still true? We should also document the lack of Group0 support.

> +  Errors:
> +    -ENXIO: Getting or setting this register is not yet supported
> +    -EBUSY: VCPU is running
> +    -EINVAL: Invalid mpidr supplied
> +
> +
> +  KVM_DEV_ARM_VGIC_GRP_NR_IRQS
> +  Attributes:
> +    A value describing the number of interrupts (SGI, PPI and SPI) for
> +    this GIC instance, ranging from 64 to 1024, in increments of 32.
> +
> +    kvm_device_attr.addr points to a __u32 value.
> +
> +  Errors:
> +    -EINVAL: Value set is out of the expected range
> +    -EBUSY: Value has already be set.
> +
> +
> +  KVM_DEV_ARM_VGIC_GRP_CTRL
> +  Attributes:
> +    KVM_DEV_ARM_VGIC_CTRL_INIT
> +      request the initialization of the VGIC, no additional parameter in
> +      kvm_device_attr.addr.
> +  Errors:
> +    -ENXIO: VGIC not properly configured as required prior to calling
> +     this attribute
> +    -ENODEV: no online VCPU
> +    -ENOMEM: memory shortage when allocating vgic internal data
> +
> +
> +  KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO
> +  Attributes:
> +    The attr field of kvm_device_attr encodes the following values:
> +    bits:     | 63      ....       32 | 31   ....    10 | 9  ....  0 |
> +    values:   |         mpidr         |      info       |   vINTID   |
> +
> +    The vINTID specifies which set of IRQs is reported on.
> +
> +    The info field specifies which information userspace wants to get or set
> +    using this interface.  Currently we support two different pieces of
> +    information:
> +
> +      VGIC_LEVEL_INFO_LINE_LEVEL:
> +        Get/Set the intput level of the IRQ line for a given IRQ.
> +	vINTID must be a multiple of 32.

Is it for a single interrupt, or a set of 32 interrupts? I believe this
is the latter, so the "for a given IRQ" is a bit misleading ("for a set
of 32 contiguous interrupts"?).

> +
> +        kvm_device_attr.addr points to a __u32 value which will contain a
> +	bitmap where a set bit means the interrupt level is asserted.
> +
> +	Bit[n] indicates the status for interrupt vINTID + n.
> +
> +
> +      VGIC_LEVEL_INFO_SOFT_PENDING
> +        Get/Set the latch state of a GIVEN level-triggered IRQ as manipulated by
> +	guest writes to GICD_SPENDR.
> +	vINTID must be a multiple of 32.

Same here. Also, can you clear the soft-pending bit through this
interface? If so, this is not equivalent to a write to GICD_SPENDR.

> +
> +        kvm_device_attr.addr points to a __u32 value which will contain a
> +	bitmap where a set bit means the guest has set the interrupt by writing
> +	to the SPENDR.
> +
> +	Bit[n] indicates the status for interrupt vINTID + n.
> +
> +
> +    SGIs and any interrupt with a higher ID than the number of interrupts

                                            INTID

> +    supported, will be RAZ/WI.  LPIs are always edge-triggered and are
> +    therefore not supported by this interface.
> +
> +    PPIs are reported per VCPU as specified in the mpidr field, and SPIs are
> +    reported with the same value regardless of the mpidr specified.
> +
> +    The mpidr field encodes the CPU ID based on the affinity information in the
> +    architecture defined MPIDR, and the field is encoded as follows:
> +      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
> +      |    Aff3    |    Aff2    |    Aff1    |    Aff0   |
> diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
> index 59541d4..257b854 100644
> --- a/Documentation/virtual/kvm/devices/arm-vgic.txt
> +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
> @@ -3,16 +3,16 @@ ARM Virtual Generic Interrupt Controller (VGIC)
>  
>  Device types supported:
>    KVM_DEV_TYPE_ARM_VGIC_V2     ARM Generic Interrupt Controller v2.0
> -  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
>  
>  Only one VGIC instance may be instantiated through either this API or the
>  legacy KVM_CREATE_IRQCHIP api.  The created VGIC will act as the VM interrupt
>  controller, requiring emulated user-space devices to inject interrupts to the
>  VGIC instead of directly to CPUs.
>  
> -Creating a guest GICv3 device requires a host GICv3 as well.
> -GICv3 implementations with hardware compatibility support allow a guest GICv2
> -as well.
> +GICv3 implementations with hardware compatibility support allow creating a
> +guest GICv2 through this interface.  For information on creating a guest GICv3
> +device, see arm-vgic-v3.txt.  It is not possible to create both a GICv3 and
> +GICv2 device on the same VM.
>  
>  Groups:
>    KVM_DEV_ARM_VGIC_GRP_ADDR
> @@ -27,19 +27,6 @@ Groups:
>        interface register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2.
>        This address needs to be 4K aligned and the region covers 4 KByte.
>  
> -    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
> -      Base address in the guest physical address space of the GICv3 distributor
> -      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> -      This address needs to be 64K aligned and the region covers 64 KByte.
> -
> -    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
> -      Base address in the guest physical address space of the GICv3
> -      redistributor register mappings. There are two 64K pages for each
> -      VCPU and all of the redistributor pages are contiguous.
> -      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> -      This address needs to be 64K aligned.
> -
> -
>    KVM_DEV_ARM_VGIC_GRP_DIST_REGS
>    Attributes:
>      The attr field of kvm_device_attr encodes two values:
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From andrew at lunn.ch  Fri May 13 08:24:31 2016
From: andrew at lunn.ch (Andrew Lunn)
Date: Fri, 13 May 2016 17:24:31 +0200
Subject: [PATCH 1/2] net: mv643xx_eth: use {readl|writel}_relaxed instead
 of readl/writel
In-Reply-To: <20160513201955.256e5169@xhacker>
References: <1463140760-7128-1-git-send-email-jszhang@marvell.com>
 <1463140760-7128-2-git-send-email-jszhang@marvell.com>
 <3966837.tFk2PD8QFb@wuerfel> <20160513201955.256e5169@xhacker>
Message-ID: <20160513152431.GA4136@lunn.ch>

On Fri, May 13, 2016 at 08:19:55PM +0800, Jisheng Zhang wrote:
> Dear Arnd,
> 
> On Fri, 13 May 2016 14:09:43 +0200 Arnd Bergmann wrote:
> 
> > On Friday 13 May 2016 19:59:19 Jisheng Zhang wrote:
> > >  /* port register accessors **************************************************/
> > >  static inline u32 rdl(struct mv643xx_eth_private *mp, int offset)
> > >  {
> > > -	return readl(mp->shared->base + offset);
> > > +	return readl_relaxed(mp->shared->base + offset);
> > >  }
> > >  
> > >  static inline u32 rdlp(struct mv643xx_eth_private *mp, int offset)
> > >  {
> > > -	return readl(mp->base + offset);
> > > +	return readl_relaxed(mp->base + offset);
> > >  }  
> > 
> > I'd recommend not changing these in general, but introducing new 'rdl_relaxed()'
> > and 'rdlp_relaxed()' etc variants that you use in the code that actually
> > is performance sensitive, but use the normal non-relaxed versions by
> > default.
> > 
> > Then add a comment to each use of the relaxed accessors on how you know
> > that it's safe for that caller. This usually is just needed for the xmit()
> > function and for the interrupt handler.
> 
> Got your points and I do think it makes sense. But could we always use the
> relaxed version to save some LoCs.

It is a trade off between lines of code and hard to find bugs. Getting
this wrong can introduce subtle bugs.

Best be paranoid and only touch the fast path, where this actually
matters.

     Andrew



From peter.maydell at linaro.org  Fri May 13 08:28:44 2016
From: peter.maydell at linaro.org (Peter Maydell)
Date: Fri, 13 May 2016 16:28:44 +0100
Subject: [PATCH v3] KVM: arm/arm64: Add VGICv3 save/restore API
 documentation
In-Reply-To: <1463150637-6896-1-git-send-email-christoffer.dall@linaro.org>
References: <1463150637-6896-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <CAFEAcA8fcxo18HhfboE5j=SC8TyrPXqmpsPNymM8zw4PhMTRDw@mail.gmail.com>

On 13 May 2016 at 15:43, Christoffer Dall <christoffer.dall at linaro.org> wrote:
> Factor out the GICv3-specific documentation into a separate
> documentation file.  Add description for how to access distributor,
> redistributor, and CPU interface registers for GICv3 in this new file,
> and add a group for accesing level triggered IRQ information for GICv3
> as well.
>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> ---
> Changes since v2:
>  - Changed distributor access to be 32-bits in size
>  - Clearly specified data type pointed to by addr field
>  - Specified exception behavior for STATUSR registers
>  - Added group for level-triggered IRQ status info
>  - Removed acks from Marc/Peter as content has changed

Hi; I have one substantial point and a few typos to point out.

>  Documentation/virtual/kvm/devices/arm-vgic-v3.txt | 176 ++++++++++++++++++++++
>  Documentation/virtual/kvm/devices/arm-vgic.txt    |  21 +--
>  2 files changed, 180 insertions(+), 17 deletions(-)
>  create mode 100644 Documentation/virtual/kvm/devices/arm-vgic-v3.txt
>
> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> new file mode 100644
> index 0000000..69201e8
> --- /dev/null
> +++ b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> @@ -0,0 +1,176 @@
> +ARM Virtual Generic Interrupt Controller v3 and later (VGICv3)
> +==============================================================
> +
> +
> +Device types supported:
> +  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
> +
> +Only one VGIC instance may be instantiated through this API.  The created VGIC
> +will act as the VM interrupt controller, requiring emulated user-space devices
> +to inject interrupts to the VGIC instead of directly to CPUs.  It is not
> +possible to create both a GICv3 and GICv2 on the same VM.
> +
> +Creating a guest GICv3 device requires a host GICv3 as well.
> +
> +Groups:
> +  KVM_DEV_ARM_VGIC_GRP_ADDR
> +  Attributes:
> +    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
> +      Base address in the guest physical address space of the GICv3 distributor
> +      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> +      This address needs to be 64K aligned and the region covers 64 KByte.
> +
> +    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
> +      Base address in the guest physical address space of the GICv3
> +      redistributor register mappings. There are two 64K pages for each
> +      VCPU and all of the redistributor pages are contiguous.
> +      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> +      This address needs to be 64K aligned.
> +
> +
> +  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
> +  KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
> +  Attributes:
> +    The attr field of kvm_device_attr encodes two values:
> +    bits:     | 63   ....  32  |  31   ....    0 |
> +    values:   |      mpidr     |      offset     |
> +
> +    All distributor regs are (rw, 32-bit) and kvm_device_attr.addr points to a
> +    __u32 value.  64-bit registers must be accessed by separately accessing the
> +    lower and higher word.
> +
> +    Writes to read-only registers can be ignored by the kernel.

Presumably "are ignored".

> +
> +    KVM_DEV_ARM_VGIC_GRP_DIST_REGS accesses the main distributor registers.
> +    KVM_DEV_ARM_VGIC_GRP_REDIST_REGS accesses the redistributor of the CPU
> +    specified by the mpidr.
> +
> +    The offset is relative to the "[Re]Distributor base address" as defined
> +    in the GICv3/4 specs.  Getting or setting such a register has the same
> +    effect as reading or writing the register on real hardware (except for
> +    GICD_STATUS and GICR_STATUSR, see blow), and the mpidr field is used to

"GICD_STATUSR". "below".

> +    specify which redistributor is accessed.  The mpidr is ignored for the
> +    distributor.
> +
> +    The mpidr encoding is based on the affinity information in the
> +    architecture defined MPIDR, and the field is encoded as follows:
> +      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
> +      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
> +
> +    Note that distributor fields are not banked, but return the same value
> +    regardless of the mpidr used to access the register.
> +
> +    The GICD_STATUSR and GICR_STATUSR registers are architecturally defined such
> +    that a write of a clear bit has no effect, whereas a write with a set bit
> +    clears that value.  To allow userspace to freely set the values of these two
> +    registers, setting the attributes with the register offsets for these two
> +    registers simply sets the non-reserved bits to the value written.
> +  Limitations:
> +    - Priorities are not implemented, and registers are RAZ/WI
> +  Errors:
> +    -ENXIO: Getting or setting this register is not yet supported
> +    -EBUSY: One or more VCPUs are running
> +
> +
> +  KVM_DEV_ARM_VGIC_CPU_SYSREGS
> +  Attributes:
> +    The attr field of kvm_device_attr encodes two values:
> +    bits:     | 63      ....       32 | 31  ....  16 | 15  ....  0 |
> +    values:   |         mpidr         |      RES     |    instr    |
> +
> +    The mpidr field encodes the CPU ID based on the affinity information in the
> +    architecture defined MPIDR, and the field is encoded as follows:
> +      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
> +      |    Aff3    |    Aff2    |    Aff1    |    Aff0   |

ASCII art diagram missing a space after "Aff0" ?

> +
> +  KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO
> +  Attributes:
> +    The attr field of kvm_device_attr encodes the following values:
> +    bits:     | 63      ....       32 | 31   ....    10 | 9  ....  0 |
> +    values:   |         mpidr         |      info       |   vINTID   |
> +
> +    The vINTID specifies which set of IRQs is reported on.
> +
> +    The info field specifies which information userspace wants to get or set
> +    using this interface.  Currently we support two different pieces of
> +    information:
> +
> +      VGIC_LEVEL_INFO_LINE_LEVEL:
> +        Get/Set the intput level of the IRQ line for a given IRQ.

"input"

> +       vINTID must be a multiple of 32.
> +
> +        kvm_device_attr.addr points to a __u32 value which will contain a
> +       bitmap where a set bit means the interrupt level is asserted.
> +
> +       Bit[n] indicates the status for interrupt vINTID + n.
> +
> +
> +      VGIC_LEVEL_INFO_SOFT_PENDING
> +        Get/Set the latch state of a GIVEN level-triggered IRQ as manipulated by

Why is "given" capitalised?

I would like this to simply get/set the latch state regardless of whether
the interrupt is edge triggered or level triggered. (Obviously if the
interrupt is edge triggered this is equivalent to accessing the
ISPENDR/ICPENDR registers, but I don't want in userspace to have to
manually look at whether each interrupt is edge or level in order to
identify whether to use ISPENDR or this API, when in fact the state
in the kernel is exactly the same. I just want a straightforward
get/set accessor to the underlying state.)

thanks
-- PMM


From arnd at arndb.de  Fri May 13 09:16:05 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 13 May 2016 18:16:05 +0200
Subject: [GIT PULL] ARM: SoC fixes for 4.6
Message-ID: <2596349.2VGvIuv4pS@wuerfel>

The following changes since commit 44549e8f5eea4e0a41b487b63e616cb089922b99:

  Linux 4.6-rc7 (2016-05-08 14:38:32 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/fixes-for-linus

for you to fetch changes up to 8a934ccbf90959877beec27780469e85f1c3f101:

  Merge tag 'at91-fixes2' of git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91 into fixes (2016-05-12 17:44:53 +0200)

----------------------------------------------------------------
Three more bug fixes for ARM SoCs this week:

- The Atmel sama5d2 was registering the wrong NFC device type
- On Atmel sam9x5, the power management controller had an incorrect
  register area size
- On ARM64 Allwinner machine was not secting the generic irqchip
  code, causing build errors in some configurations

----------------------------------------------------------------
Arnd Bergmann (2):
      Merge tag 'at91-fixes' of git://git.kernel.org/.../nferre/linux-at91 into fixes
      Merge tag 'at91-fixes2' of git://git.kernel.org/.../nferre/linux-at91 into fixes

Boris Brezillon (1):
      ARM: dts: at91: sam9x5: Fix the memory range assigned to the PMC

Suzuki K Poulose (1):
      arm64/sunxi: 4.6-rc1: Add dependency on generic irq chip

Wenyou Yang (1):
      ARM: dts: at91: sama5d2: use "atmel,sama5d3-nfc" compatible for nfc

 arch/arm/boot/dts/at91sam9x5.dtsi | 2 +-
 arch/arm/boot/dts/sama5d2.dtsi    | 2 +-
 arch/arm64/Kconfig.platforms      | 1 +
 3 files changed, 3 insertions(+), 2 deletions(-)



From yang.shi at linaro.org  Fri May 13 09:23:02 2016
From: yang.shi at linaro.org (Shi, Yang)
Date: Fri, 13 May 2016 09:23:02 -0700
Subject: [PATCH] arm64: bpf: jit JMP_JSET_{X,K}
In-Reply-To: <1463121478-18484-1-git-send-email-zlim.lnx@gmail.com>
References: <1463121478-18484-1-git-send-email-zlim.lnx@gmail.com>
Message-ID: <5a03c0b4-7686-6232-9c64-c6ec0f30edae@linaro.org>

On 5/12/2016 11:37 PM, Zi Shen Lim wrote:
> Original implementation commit e54bcde3d69d ("arm64: eBPF JIT compiler")
> had the relevant code paths, but due to an oversight always fail jiting.
>
> As a result, we had been falling back to BPF interpreter whenever a BPF
> program has JMP_JSET_{X,K} instructions.
>
> With this fix, we confirm that the corresponding tests in lib/test_bpf
> continue to pass, and also jited.
>
> ...
> [    2.784553] test_bpf: #30 JSET jited:1 188 192 197 PASS
> [    2.791373] test_bpf: #31 tcpdump port 22 jited:1 325 677 625 PASS
> [    2.808800] test_bpf: #32 tcpdump complex jited:1 323 731 991 PASS
> ...
> [    3.190759] test_bpf: #237 JMP_JSET_K: if (0x3 & 0x2) return 1 jited:1 110 PASS
> [    3.192524] test_bpf: #238 JMP_JSET_K: if (0x3 & 0xffffffff) return 1 jited:1 98 PASS
> [    3.211014] test_bpf: #249 JMP_JSET_X: if (0x3 & 0x2) return 1 jited:1 120 PASS
> [    3.212973] test_bpf: #250 JMP_JSET_X: if (0x3 & 0xffffffff) return 1 jited:1 89 PASS
> ...
>
> Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler")
> Signed-off-by: Zi Shen Lim <zlim.lnx at gmail.com>

Acked-by: Yang Shi <yang.shi at linaro.org>

Thanks,
Yang

> ---
>  arch/arm64/net/bpf_jit_comp.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
> index 031ed08..d0d5190 100644
> --- a/arch/arm64/net/bpf_jit_comp.c
> +++ b/arch/arm64/net/bpf_jit_comp.c
> @@ -478,6 +478,7 @@ emit_cond_jmp:
>  		case BPF_JGE:
>  			jmp_cond = A64_COND_CS;
>  			break;
> +		case BPF_JSET:
>  		case BPF_JNE:
>  			jmp_cond = A64_COND_NE;
>  			break;
>



From keescook at chromium.org  Fri May 13 09:36:45 2016
From: keescook at chromium.org (Kees Cook)
Date: Fri, 13 May 2016 09:36:45 -0700
Subject: [PATCH] arm64: enable CONFIG_SET_MODULE_RONX by default
In-Reply-To: <CAKv+Gu_uofTP9df8wk1MT3eajebzUcbKeEaamO3yRBDDsyCuGg@mail.gmail.com>
References: <1463138436-5073-1-git-send-email-mark.rutland@arm.com>
 <CAKv+Gu_uofTP9df8wk1MT3eajebzUcbKeEaamO3yRBDDsyCuGg@mail.gmail.com>
Message-ID: <CAGXu5jLbGXCdpQVcemajRu0EchBKfxZ9BS0hW+aHHVDd6RdGzQ@mail.gmail.com>

On Fri, May 13, 2016 at 5:00 AM, Ard Biesheuvel
<ard.biesheuvel at linaro.org> wrote:
> On 13 May 2016 at 13:20, Mark Rutland <mark.rutland at arm.com> wrote:
>> The SET_MODULE_RONX protections are effectively the same as the
>> DEBUG_RODATA protections we enabled by default back in commit
>> 57efac2f7108e325 ("arm64: enable CONFIG_DEBUG_RODATA by default"). It
>> seems unusual to have one but not the other.
>>
>> As evidenced by the help text, the rationale appears to be that
>> SET_MODULE_RONX interacts poorly with tracing and patching, but both of
>> these make use of the insn framework, which takes SET_MODULE_RONX into
>> account. Any remaining issues are bugs which should be fixed regardless
>> of the default state of the option.
>>
>> This patch enables DEBUG_SET_MODULE_RONX by default, and replaces the
>> help text with a new wording derived from the DEBUG_RODATA help text,
>> which better describes the functionality. Previously, the DEBUG_RODATA
>> entry was inconsistently indented with spaces, which are replaced with
>> tabs as with the other Kconfig entries.
>>
>> Additionally, the wording of recommended defaults is made consistent for
>> all options. These are placed in a new paragraph, unquoted, as a full
>> sentence (with a period/full stop) as this appears to be the most common
>> form per $(git grep 'in doubt').
>>
>> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
>> Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org>
>> Cc: Catalin Marinas <catalin.marinas at arm.com>
>> Cc: Kees Cook <keescook at chromium.org>
>> Cc: Laura Abbott <labbott at fedoraproject.org>
>> Cc: Will Deacon <will.deacon at arm.com>
>
> Acked-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>

Yay! :)

Acked-by: Kees Cook <keescook at chromium.org>

-Kees

>
>> ---
>>  arch/arm64/Kconfig.debug | 25 +++++++++++++------------
>>  1 file changed, 13 insertions(+), 12 deletions(-)
>>
>> diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
>> index 710fde4..0cc758c 100644
>> --- a/arch/arm64/Kconfig.debug
>> +++ b/arch/arm64/Kconfig.debug
>> @@ -12,7 +12,8 @@ config ARM64_PTDUMP
>>           who are working in architecture specific areas of the kernel.
>>           It is probably not a good idea to enable this feature in a production
>>           kernel.
>> -         If in doubt, say "N"
>> +
>> +         If in doubt, say N.
>>
>>  config PID_IN_CONTEXTIDR
>>         bool "Write the current PID to the CONTEXTIDR register"
>> @@ -38,15 +39,15 @@ config ARM64_RANDOMIZE_TEXT_OFFSET
>>           value.
>>
>>  config DEBUG_SET_MODULE_RONX
>> -        bool "Set loadable kernel module data as NX and text as RO"
>> -        depends on MODULES
>> -        help
>> -          This option helps catch unintended modifications to loadable
>> -          kernel module's text and read-only data. It also prevents execution
>> -          of module data. Such protection may interfere with run-time code
>> -          patching and dynamic kernel tracing - and they might also protect
>> -          against certain classes of kernel exploits.
>> -          If in doubt, say "N".
>> +       bool "Set loadable kernel module data as NX and text as RO"
>> +       depends on MODULES
>> +       default y
>> +       help
>> +         Is this is set, kernel module text and rodata will be made read-only.
>> +         This is to help catch accidental or malicious attempts to change the
>> +         kernel's executable code.
>> +
>> +         If in doubt, say Y.
>>
>>  config DEBUG_RODATA
>>         bool "Make kernel text and rodata read-only"
>> @@ -56,7 +57,7 @@ config DEBUG_RODATA
>>           is to help catch accidental or malicious attempts to change the
>>           kernel's executable code.
>>
>> -         If in doubt, say Y
>> +         If in doubt, say Y.
>>
>>  config DEBUG_ALIGN_RODATA
>>         depends on DEBUG_RODATA
>> @@ -69,7 +70,7 @@ config DEBUG_ALIGN_RODATA
>>           alignment and potentially wasted space. Turn on this option if
>>           performance is more important than memory pressure.
>>
>> -         If in doubt, say N
>> +         If in doubt, say N.
>>
>>  source "drivers/hwtracing/coresight/Kconfig"
>>
>> --
>> 1.9.1
>>



-- 
Kees Cook
Chrome OS & Brillo Security


From dianders at chromium.org  Fri May 13 09:38:16 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 13 May 2016 09:38:16 -0700
Subject: [PATCH 2/2] clk: rockchip: fix the rk3399 sdmmc sample shift
In-Reply-To: <0261c4b4-7398-fe15-5e26-f92bfbe79f3c@rock-chips.com>
References: <1463076197-15900-1-git-send-email-dianders@chromium.org>
 <1463076197-15900-2-git-send-email-dianders@chromium.org>
 <20160512231023.GA63308@google.com>
 <84673e7c-dd64-b2ca-5c7c-5c7f34d239d8@rock-chips.com>
 <CAD=FV=WEAOwhDDBHBtuzSz35i0XRZw4LbFEnFCFYd-4NVH5d-g@mail.gmail.com>
 <0261c4b4-7398-fe15-5e26-f92bfbe79f3c@rock-chips.com>
Message-ID: <CAD=FV=UNVHrGeKj0N_1WQvL+PNBTrPTj1xmk-63F4hJhPuvkug@mail.gmail.com>

Shawn,

On Fri, May 13, 2016 at 12:46 AM, Shawn Lin <shawn.lin at rock-chips.com> wrote:
>> This should be possible to verify in one of two ways.  If the TRM has
>> a typo and things truly _do_ start at 0 instead of 1, then:
>>
>> 1. There will be roughly mirrors of valid ranges.
>> 2. Things won't match up if we change tuning to use 180 course offsets
>> and the rest fine offsets.
>>
>> It would be ideal if you could confirm with the chip guys, but if you
>
>
> I have checked it before Xing upstreamed the code, but as your question on
> the TRM, I check it with the  chip guys again.
>
> So the answer is that drv/sample stuff should refer to  Mobile Strorage
> Host Controller section, and it will fit the future Socs from now on.

OK, awesome.  I also did more quick tests by forcing dw_mmc to give me
extra details about the tuning.  These tests agree with you.

Please consider this patch abandoned.  Note that the previous patch
(1/2) is still good as far as I know, so just this patch (2/2) should
be abandoned.

Thanks!  :)

-Doug


From tony at atomide.com  Fri May 13 09:40:53 2016
From: tony at atomide.com (Tony Lindgren)
Date: Fri, 13 May 2016 09:40:53 -0700
Subject: [PATCH] clk: ti: Add support for basic clk_set_rate for dm814x and
 j5-eco ADPLL
Message-ID: <1463157653-9404-1-git-send-email-tony@atomide.com>

Here's basic clk_set_rate support for the dm814x and j5-eco ADPLL.

Note that to clk_get the ADPLL clocks without a DTS phandle, you need to
use the generated names like "pll1a0dco", "pll1a0m2" and "pll1a0clkout".
The ADPLL driver is now enabled for dm814x and j5-eco starting with
v4.6-rc6, so there are no longer other pending dependencies.

Signed-off-by: Tony Lindgren <tony at atomide.com>
---
 drivers/clk/ti/adpll.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 182 insertions(+)

diff --git a/drivers/clk/ti/adpll.c b/drivers/clk/ti/adpll.c
index 255cafb..ff8ecfa 100644
--- a/drivers/clk/ti/adpll.c
+++ b/drivers/clk/ti/adpll.c
@@ -17,6 +17,7 @@
 #include <linux/math64.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/rational.h>
 #include <linux/string.h>
 
 #define ADPLL_PLLSS_MMR_LOCK_OFFSET	0x00	/* Managed by MPPULL */
@@ -54,12 +55,17 @@
 #define ADPLL_M2NDIV_M2			16
 #define ADPLL_M2NDIV_M2_ADPLL_S_WIDTH	5
 #define ADPLL_M2NDIV_M2_ADPLL_LJ_WIDTH	7
+#define TI_ADPLL_DIV_N_MAX		GENMASK(7, 0)
 
 #define ADPLL_MN2DIV_OFFSET		0x14
 #define ADPLL_MN2DIV_N2			16
+#define TI_ADPLL_MIN_MULT_M		2
+#define TI_ADPLL_MULT_M_MAX		(GENMASK(11, 0) + 1)
 
 #define ADPLL_FRACDIV_OFFSET		0x18
 #define ADPLL_FRACDIV_REGSD		24
+#define TI814X_ADPLLJ_MIN_SD_DIV	2
+#define TI814X_ADPLLJ_MAX_SD_DIV	255
 #define ADPLL_FRACDIV_FRACTIONALM	0
 #define ADPLL_FRACDIV_FRACTIONALM_MASK	0x3ffff
 
@@ -480,6 +486,180 @@ static unsigned long ti_adpll_recalc_rate(struct clk_hw *hw,
 	return rate;
 }
 
+static long ti_adpll_calc_n_m(struct ti_adpll_dco_data *dco,
+			      unsigned long rate,
+			      unsigned long parent_rate,
+			      u8 *div_n, u16 *mult_m, u16 *frac_m)
+{
+	struct ti_adpll_data *d = to_adpll(dco);
+	unsigned long dcorate, m, n;
+	u32 v;
+	u64 tmp64;
+
+	if (!rate)
+		return 0;
+
+	dcorate = parent_rate;
+	if (d->c->is_type_s) {
+		v = readl_relaxed(d->regs + ADPLL_CLKCTRL_OFFSET);
+		if (v & BIT(ADPLL_CLKCTRL_REGM4XEN_ADPLL_S))
+			dcorate /= 4;
+		dcorate /= 2;
+	}
+
+	/* TRM table "DPLLLJ Frequency Factors" sets the minimum M at 2 */
+	if (rate < TI_ADPLL_MIN_MULT_M * dcorate)
+		return 0;
+
+	/* Ratio for integer multiplier M and pre-divider N */
+	rational_best_approximation(rate, dcorate, TI_ADPLL_MULT_M_MAX,
+				    TI_ADPLL_DIV_N_MAX, &m, &n);
+	if (m < TI_ADPLL_MIN_MULT_M) {
+		m = TI_ADPLL_MIN_MULT_M;
+		n = rate / (dcorate * m);
+		if (n > TI_ADPLL_DIV_N_MAX) {
+			dev_err(d->dev, "div_n overflow for rate %li\n", rate);
+			return 0;
+		}
+	}
+
+	/* Calculate fractional part for multiplier M */
+	dcorate /= n;
+	tmp64 = rate % dcorate;
+	tmp64 *= 10000000;
+	do_div(tmp64, dcorate);
+
+	*div_n = n - 1;
+	*mult_m = m;
+	*frac_m = tmp64;
+
+	return rate;
+}
+
+/*
+ * Sets the sigma-delta divider targeting near 250Mhz. Adapted
+ * from TI 2.6.37 kernel tree adpll_ti814x.c. Maybe we can
+ * make the SD_DIV_TARGET_MHZ configurable also?
+ */
+#define SD_DIV_TARGET_MHZ	250
+static int ti_adpll_lookup_sddiv(struct ti_adpll_data *d,
+				 unsigned long parent_rate,
+				 u8 *sd_div, u16 m, u8 n)
+{
+	unsigned long clkinp, sd;
+	int mod1, mod2;
+
+	clkinp = parent_rate / 100000;
+	mod1 = (clkinp * m) % (SD_DIV_TARGET_MHZ * n);
+	sd = (clkinp * m) / (SD_DIV_TARGET_MHZ * n);
+	mod2 = sd % 10;
+	sd /= 10;
+
+	if (mod1 || mod2)
+		sd++;
+	if ((sd >= TI814X_ADPLLJ_MIN_SD_DIV) &&
+	    (sd <= TI814X_ADPLLJ_MAX_SD_DIV)) {
+		*sd_div = sd;
+		return 0;
+	}
+
+	*sd_div = 0;
+	dev_err(d->dev, "sigma-delta out of range: %li\n", sd);
+
+	return -EINVAL;
+}
+
+static long ti_adpll_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *parent_rate)
+{
+	struct ti_adpll_dco_data *dco = to_dco(hw);
+	struct ti_adpll_data *d = to_adpll(dco);
+	long sd_min_rate;
+	u16 mult_m, frac_m;
+	u8 div_n;
+
+	sd_min_rate = (SD_DIV_TARGET_MHZ + 10) * 1000000;
+	/* Limited by sigma-delta somewhere, see above */
+	if (!d->c->is_type_s && rate < sd_min_rate) {
+		dev_warn(d->dev, "unsupported rate: %lu\n", rate);
+		return sd_min_rate;
+	}
+
+	return ti_adpll_calc_n_m(dco, rate, *parent_rate, &div_n,
+				 &mult_m, &frac_m);
+}
+
+static int ti_adpll_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	struct ti_adpll_dco_data *dco = to_dco(hw);
+	struct ti_adpll_data *d = to_adpll(dco);
+	u16 mult_m, frac_m = 0;
+	u8 div_n, div_sd = 0;
+	unsigned long flags;
+	long new_rate;
+	int err;
+	u32 v;
+
+	new_rate = ti_adpll_calc_n_m(dco, rate, parent_rate,
+				     &div_n, &mult_m, &frac_m);
+	ti_adpll_set_idle_bypass(d);
+
+	spin_lock_irqsave(&d->lock, flags);
+	writeb_relaxed(0, d->regs + ADPLL_CLKCTRL_OFFSET);
+
+	/* Check sigma-delta divider, otherwise PLL won't lock */
+	if (!d->c->is_type_s) {
+		err = ti_adpll_lookup_sddiv(d, parent_rate,
+					    &div_sd, mult_m, div_n + 1);
+		if (err)
+			goto fail;
+	}
+
+	/* Set integer multiplier M */
+	writew_relaxed(mult_m, d->regs + ADPLL_MN2DIV_OFFSET);
+
+	/* Set ractional multiplier M and sigma-delta divider */
+	v = frac_m;
+	v |= (div_sd << 24);
+	writel_relaxed(v, d->regs + ADPLL_FRACDIV_OFFSET);
+
+	/* Configure SELFREQDCO */
+	if (!d->c->is_type_s) {
+		if (rate < 1000000000)
+			v = 2;
+		else
+			v = 4;
+		writeb_relaxed(v << 2, d->regs + ADPLL_CLKCTRL_OFFSET + 1);
+	}
+
+	dev_info(d->dev,
+		 "clkin: dco: %lu %lu N: %i + 1 M: %i Mf: %i sddiv: %i r: %i\n",
+		 parent_rate, rate, div_n, mult_m, frac_m, div_sd, v);
+
+	/* Set pre-devider N */
+	writeb_relaxed(div_n, d->regs + ADPLL_M2NDIV_OFFSET);
+
+	writeb_relaxed(1, d->regs + ADPLL_TENABLE_OFFSET);
+	writeb_relaxed(0, d->regs + ADPLL_TENABLE_OFFSET);
+	writeb_relaxed(1, d->regs + ADPLL_TENABLEDIV_OFFSET);
+	writeb_relaxed(0, d->regs + ADPLL_TENABLEDIV_OFFSET);
+	writeb_relaxed(1, d->regs + ADPLL_CLKCTRL_OFFSET);
+	spin_unlock_irqrestore(&d->lock, flags);
+
+	ti_adpll_clear_idle_bypass(d);
+
+	return ti_adpll_wait_lock(d);
+
+fail:
+	writeb_relaxed(1, d->regs + ADPLL_CLKCTRL_OFFSET);
+	spin_unlock_irqrestore(&d->lock, flags);
+	ti_adpll_clear_idle_bypass(d);
+	ti_adpll_wait_lock(d);
+
+	return err;
+}
+
 /* PLL parent is always clkinp, bypass only affects the children */
 static u8 ti_adpll_get_parent(struct clk_hw *hw)
 {
@@ -491,6 +671,8 @@ static struct clk_ops ti_adpll_ops = {
 	.unprepare = ti_adpll_unprepare,
 	.is_prepared = ti_adpll_is_prepared,
 	.recalc_rate = ti_adpll_recalc_rate,
+	.round_rate = ti_adpll_round_rate,
+	.set_rate = ti_adpll_set_rate,
 	.get_parent = ti_adpll_get_parent,
 };
 
-- 
2.8.1



From tony at atomide.com  Fri May 13 10:11:40 2016
From: tony at atomide.com (Tony Lindgren)
Date: Fri, 13 May 2016 10:11:40 -0700
Subject: [GIT PULL 1/2] omap fixes for v4.7 merge window
Message-ID: <pull-1463159315-251654>

The following changes since commit 7472931f7f1e9d91f761dce30107ae345b61a5c3:

  ARM: dts: omap5: fix range of permitted wakeup pinmux registers (2016-04-26 10:16:12 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v4.7/fixes-v2

for you to fetch changes up to 65db875d110b8e517f81fa71c57a65fc6d0019ac:

  ARM: OMAP2+: AM43XX: Enable fixes for Cortex-A9 errata (2016-05-12 13:47:51 -0700)

----------------------------------------------------------------
Two fixes for omaps for v4.7 merge window, one to enable
ARM errata for am437x, and the other to add ARM errtum
workaround for dra7.

AFAIK these both can wait for v4.7, we can then request them
for stable kernels as needed.

----------------------------------------------------------------
Dave Gerlach (1):
      ARM: OMAP2+: AM43XX: Enable fixes for Cortex-A9 errata

Nishanth Menon (1):
      ARM: OMAP5 / DRA7: Introduce workaround for 801819

 arch/arm/mach-omap2/Kconfig       | 10 ++++++++
 arch/arm/mach-omap2/omap-secure.h |  1 +
 arch/arm/mach-omap2/omap-smp.c    | 48 +++++++++++++++++++++++++++++++++++----
 3 files changed, 54 insertions(+), 5 deletions(-)


From tony at atomide.com  Fri May 13 10:11:41 2016
From: tony at atomide.com (Tony Lindgren)
Date: Fri, 13 May 2016 10:11:41 -0700
Subject: [GIT PULL 2/2] omap dts fixes for v4.7 merge window
In-Reply-To: <pull-1463159315-251654>
References: <pull-1463159315-251654>
Message-ID: <pull-1463159315-251654-2>

The following changes since commit 5b6042237dc85b7e2dc26806957ebf95d205e864:

  ARM: dts: am57xx-idk: Include Industrial grade  thermal thresholds (2016-04-28 08:08:48 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v4.7-dts-fixes1

for you to fetch changes up to a1f6ad14176d466c00e6a687f9c78ec6c7ad6bf8:

  ARM: dts: igep0020: Add SD card write-protect pin. (2016-05-12 13:52:25 -0700)

----------------------------------------------------------------
DTS fixes for omaps for v4.7 merge window for issues noted
with patches in Linux next:

- Fix omap5 and am57xx-idk input voltages to fix micro-sd
  probing at least for some omap5-uevm configurations

- Fix unhandled fault for igepv5 audio

- Fix UART wakeirqs for omap5 by removing WAKUP_EN flags,
  those are managed by the wakeirq and can currently confuse
  the wakeirqs as there is no handler necessarily registered

- Fix LDO7 source for igepv5

Also included are few minor changes not strictly fixes
are good to have merged:

- Fix HP T410 boot time warnings for eMMC and disable the
  unused MMC interfaces while at it

- Add dra7 gpmc dma channel

- Add igep00x0 SD card detect and write protect GPIOs

----------------------------------------------------------------
Enric Balletbo i Serra (2):
      ARM: dts: igep00x0: Add SD card-detect.
      ARM: dts: igep0020: Add SD card write-protect pin.

Franklin S Cooper Jr (1):
      ARM: dts: dra7: Add gpmc dma channel

Nicolas Chauvet (2):
      ARM: dts: Add non-removable to hsmmc on hp-t410
      ARM: dts: disable mmc by default and enable when needed for dm814x

Nishanth Menon (2):
      ARM: dts: omap5-board-common: Describe the voltage supply mapping accurately
      ARM: dts: am57xx-idk-common: Fix input supply names

Tony Lindgren (3):
      ARM: dts: Fix igepv5 audiopwon-gpio
      ARM: dts: Fix uart wakeirq on omap5 by removing WAKEUP_EN for omaps
      ARM: dts: Fix ldo7 source for HDMI on igepv5

 arch/arm/boot/dts/am57xx-idk-common.dtsi     | 32 ++++++++++---------
 arch/arm/boot/dts/dm8148-evm.dts             |  8 +++++
 arch/arm/boot/dts/dm8148-t410.dts            |  9 ++++++
 arch/arm/boot/dts/dra7.dtsi                  |  2 ++
 arch/arm/boot/dts/omap3-evm-37xx.dts         |  2 +-
 arch/arm/boot/dts/omap3-igep.dtsi            |  1 +
 arch/arm/boot/dts/omap3-igep0020-common.dtsi | 11 +++++++
 arch/arm/boot/dts/omap3-n900.dts             |  4 +--
 arch/arm/boot/dts/omap3-n950-n9.dtsi         |  6 ++--
 arch/arm/boot/dts/omap3-zoom3.dts            |  6 ++--
 arch/arm/boot/dts/omap5-board-common.dtsi    | 48 ++++++++++++++++++++++++++--
 arch/arm/boot/dts/omap5-igep0050.dts         | 26 +++++++++++++++
 arch/arm/boot/dts/omap5-uevm.dts             | 10 ++++++
 13 files changed, 139 insertions(+), 26 deletions(-)


From thierry.reding at gmail.com  Fri May 13 10:27:04 2016
From: thierry.reding at gmail.com (Thierry Reding)
Date: Fri, 13 May 2016 19:27:04 +0200
Subject: [PATCH] ARM: tegra: beaver: allow SD card voltage to be changed
In-Reply-To: <1463124331.2459.0.camel@lynxeye.de>
References: <1456779678-20173-1-git-send-email-dev@lynxeye.de>
 <1463124331.2459.0.camel@lynxeye.de>
Message-ID: <20160513172704.GA498@ulmo.ba.sec>

On Fri, May 13, 2016 at 09:25:31AM +0200, Lucas Stach wrote:
> Am Montag, den 29.02.2016, 22:01 +0100 schrieb Lucas Stach:
> > This allows to switch the card signal voltage level to 1.8V,
> > which is needed for any ultra high speed modes to work.
> > 
> > Signed-off-by: Lucas Stach <dev at lynxeye.de>
> > ---
> > This needs the SDMMC memcomp pad calibration patches I just
> > sent out to be applied, otherwise the card voltage change will
> > fail with a message in the kernel log and a fall back to
> > high speed operation.
> 
> The patches this one depends on have been applied for some time now.
> Please pick up this patch.

My understanding is that UHS modes currently cause problems on Beaver.
What I don't understand about that is how it will even try those modes
if the voltage regulator can't be set to 1.8 V? Shouldn't that actively
prevent those modes from even being attempted?

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

From b-liu at ti.com  Fri May 13 11:35:02 2016
From: b-liu at ti.com (Bin Liu)
Date: Fri, 13 May 2016 13:35:02 -0500
Subject: [PATCH 2/2] musb: sunxi: Set state to A_WAIT_VRISE when enabling
 VBus
In-Reply-To: <1463077869-13224-2-git-send-email-hdegoede@redhat.com>
References: <1463077869-13224-1-git-send-email-hdegoede@redhat.com>
 <1463077869-13224-2-git-send-email-hdegoede@redhat.com>
Message-ID: <20160513183428.GA1665@uda0271908>

Hi,

On Thu, May 12, 2016 at 08:31:09PM +0200, Hans de Goede wrote:
> When the board is powering attached usb devices via the otg port
> sometimes / on some devices it takes slightly too long for the VBus
> detection code in phy-sun4i-usb.c to signal that VBus is high after
> enabling VBus and the musb hardware signals a MUSB_INTR_VBUSERROR
> interrupt.
> 
> This commit sets the otg state to A_WAIT_VRISE upon enabling Vbus
> making musb_stage0_irq() ignore the first VBUSERR_RETRY_COUNT
> VBUSERROR interrupts, fixing connection issues in these cases.
> 
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> ---
>  drivers/usb/musb/sunxi.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
> index 2c33d9b..2ee48fb 100644
> --- a/drivers/usb/musb/sunxi.c
> +++ b/drivers/usb/musb/sunxi.c
> @@ -112,7 +112,7 @@ static void sunxi_musb_work(struct work_struct *work)
>  		if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
>  			set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
>  			musb->xceiv->otg->default_a = 1;
> -			musb->xceiv->otg->state = OTG_STATE_A_IDLE;
> +			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
>  			MUSB_HST_MODE(musb);
>  			devctl |= MUSB_DEVCTL_SESSION;
>  		} else {
> @@ -145,9 +145,10 @@ static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
>  {
>  	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
>  
> -	if (is_on)
> +	if (is_on) {
>  		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
> -	else
> +		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;

Why this has to be set in both sunxi_musb_work() and here? Only setting
it in the work is not efficient?

Regards,
-Bin.

> +	} else
>  		clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
>  
>  	schedule_work(&glue->work);
> @@ -325,6 +326,7 @@ static int sunxi_set_mode(struct musb *musb, u8 mode)
>  		set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
>  		/* Stop musb work from turning vbus off again */
>  		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
> +		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
>  	}
>  
>  	return 0;
> -- 
> 2.7.4
> 


From briannorris at chromium.org  Fri May 13 11:42:16 2016
From: briannorris at chromium.org (Brian Norris)
Date: Fri, 13 May 2016 11:42:16 -0700
Subject: [PATCH 1/2] clk: rockchip: mark rk3399 GIC clocks as critical
Message-ID: <1463164937-91089-1-git-send-email-briannorris@chromium.org>

We never want to kill the GIC.

Noticed when making other clock fixups, and seeing the newly-constructed
clock tree try to disable cpll, where we had this parent structure:

  aclk_gic <------\
                  |--- aclk_gic_pre <-- cpll <-- pll_cpll
  aclk_gic_noc <--/

Signed-off-by: Brian Norris <briannorris at chromium.org>
---
 drivers/clk/rockchip/clk-rk3399.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
index 291543f52caa..145756c4f3c8 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -1466,6 +1466,8 @@ static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = {
 
 static const char *const rk3399_cru_critical_clocks[] __initconst = {
 	"aclk_cci_pre",
+	"aclk_gic",
+	"aclk_gic_noc",
 	"pclk_perilp0",
 	"pclk_perilp0",
 	"hclk_perilp0",
-- 
2.8.0.rc3.226.g39d4020



From briannorris at chromium.org  Fri May 13 11:42:17 2016
From: briannorris at chromium.org (Brian Norris)
Date: Fri, 13 May 2016 11:42:17 -0700
Subject: [PATCH 2/2] clk: rockchip: fix incorrect parent for rk3399's {c,
 g}pll_aclk_perihp_src
In-Reply-To: <1463164937-91089-1-git-send-email-briannorris@chromium.org>
References: <1463164937-91089-1-git-send-email-briannorris@chromium.org>
Message-ID: <1463164937-91089-2-git-send-email-briannorris@chromium.org>

From: Xing Zheng <zhengxing at rock-chips.com>

There was a typo, swapping 'c' <--> 'g'.

Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
Signed-off-by: Brian Norris <briannorris at chromium.org>
---
 drivers/clk/rockchip/clk-rk3399.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
index 145756c4f3c8..9f86bfef70f7 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -832,9 +832,9 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
 			RK3399_CLKGATE_CON(13), 1, GFLAGS),
 
 	/* perihp */
-	GATE(0, "cpll_aclk_perihp_src", "gpll", CLK_IGNORE_UNUSED,
+	GATE(0, "cpll_aclk_perihp_src", "cpll", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(5), 0, GFLAGS),
-	GATE(0, "gpll_aclk_perihp_src", "cpll", CLK_IGNORE_UNUSED,
+	GATE(0, "gpll_aclk_perihp_src", "gpll", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(5), 1, GFLAGS),
 	COMPOSITE(ACLK_PERIHP, "aclk_perihp", mux_aclk_perihp_p, CLK_IGNORE_UNUSED,
 			RK3399_CLKSEL_CON(14), 7, 1, MFLAGS, 0, 5, DFLAGS,
-- 
2.8.0.rc3.226.g39d4020



From dianders at chromium.org  Fri May 13 11:46:33 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 13 May 2016 11:46:33 -0700
Subject: [PATCH 2/4] phy: rockchip-emmc: configure frequency range and
 drive impedance
In-Reply-To: <3695875b-09c3-cd80-3062-55d985e51f70@rock-chips.com>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
 <1463092986-61777-2-git-send-email-briannorris@chromium.org>
 <3695875b-09c3-cd80-3062-55d985e51f70@rock-chips.com>
Message-ID: <CAD=FV=UwocUy_bOUrJZB47taHWdV1KGkvi5CyZf74Y8cvGgVmw@mail.gmail.com>

Shawn,

On Thu, May 12, 2016 at 6:02 PM, Shawn Lin <shawn.lin at rock-chips.com> wrote:
> Hi Brian,
>
>
> On 2016/5/13 6:43, Brian Norris wrote:
>>
>> From: Shawn Lin <shawn.lin at rock-chips.com>
>>
>> Signal integrity analysis has suggested we set these values. Do this in
>> power_on(), so that they get reconfigured after suspend/resume.
>>
>> Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
>> Signed-off-by: Brian Norris <briannorris at chromium.org>
>> ---
>>  drivers/phy/phy-rockchip-emmc.c | 27 +++++++++++++++++++++++++++
>>  1 file changed, 27 insertions(+)
>>
>> diff --git a/drivers/phy/phy-rockchip-emmc.c
>> b/drivers/phy/phy-rockchip-emmc.c
>> index 48cbe691a889..5641dede32f6 100644
>> --- a/drivers/phy/phy-rockchip-emmc.c
>> +++ b/drivers/phy/phy-rockchip-emmc.c
>> @@ -56,6 +56,19 @@
>>  #define PHYCTRL_DLLRDY_SHIFT   0x5
>>  #define PHYCTRL_DLLRDY_DONE    0x1
>>  #define PHYCTRL_DLLRDY_GOING   0x0
>> +#define PHYCTRL_FREQSEL_200M   0x0
>> +#define PHYCTRL_FREQSEL_50M    0x1
>> +#define PHYCTRL_FREQSEL_100M   0x2
>> +#define PHYCTRL_FREQSEL_150M   0x3
>> +#define PHYCTRL_FREQSEL_MASK   0x3
>> +#define PHYCTRL_FREQSEL_SHIFT  0xc
>> +#define PHYCTRL_DR_MASK                0x7
>> +#define PHYCTRL_DR_SHIFT       0x4
>> +#define PHYCTRL_DR_50OHM       0x0
>> +#define PHYCTRL_DR_33OHM       0x1
>> +#define PHYCTRL_DR_66OHM       0x2
>> +#define PHYCTRL_DR_100OHM      0x3
>> +#define PHYCTRL_DR_40OHM       0x4
>>
>>  struct rockchip_emmc_phy {
>>         unsigned int    reg_offset;
>> @@ -154,6 +167,20 @@ static int rockchip_emmc_phy_power_on(struct phy
>> *phy)
>>         struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
>>         int ret = 0;
>>
>> +       /* DLL operation: 170 to 200 MHz */
>
>
> What is 170 here? Should we expose them to dt instead of hardcoding
> them?

This was probably my fault.  I did some searching and found
<https://arasan.com/wp-content/media/eMMC-5-1-Total-Solution_Rev-1-3.pdf>.
It appears to be docs for a similar (but not identical) PHY.  We were
looking at it to try to get more clarity on some bits that were hard
to understand in the docs we had.

In that doc there appear to be 3 bits for selecting the DLL operation
and they have ranges defined.  In Rockchip's PHY there are only 2
bits.  Thus things don't map totally properly.

Anyway, comment should probably be removed.


I _think_ that this just needs to match the input clock rate of the
eMMC, right?  So presumably the PHY should get a reference to the same
clock that was given to the controller clock.  It can check the clock
at probe time and then register a notifier to keep the in sync (if we
expect the clock to change).

IMHO adding all of that complexity seems like it could wait for a
followup patch.  For now we can assume 200 MHz I think?


> Per the commit msg, signal may vary from board to board, so I guess
> 50ohm may not always be the best selection?

Starting out with something sane like 50 ohms seems like it makes
sense for now.  It's OK to start with a default for now to get things
basically working and then add device tree support once we have a
second user.


When we're ready to make this more generic, IMHO we might consider
having the PHY implement the pinctrl API and officially be a pin
controller and we use those bindings.  We are controlling pins so
using the pinctrl API seems like it might make sense?

I _think_ that perhaps what we're specifying here is actually slew
rate, but feel free to correct me if I'm wrong.  It looks as if "drive
strength" is supposed to be specified in terms of mA and the docs I
find show that we're actually controlling how fast the pins will
toggle.

I'm not 100% certain I know how the pinctrl bindings apply in this
case (maybe Heiko has ideas, or maybe we should send a proposal to
Linus W?), but from the bindings they look like they offer some
flexibility.

Maybe this would look like below (or maybe you need some extra sub-nodes)

       sdhci: sdhci at fe330000 {
               compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
               reg = <0x0 0xfe330000 0x0 0x10000>;
               interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
               clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;
               clock-names = "clk_xin", "clk_ahb";
               assigned-clocks = <&cru SCLK_EMMC>;
               assigned-clock-rates = <200000000>;
               phys = <&emmc_phy>;
               phy-names = "phy_arasan";
               pinctrl-names = "default";
               pinctrl-0 = <&pcfg_emmc_slew_rate_x1_00>;
               status = "disabled";
       };

               emmc_phy: phy at f780 {
                       compatible = "rockchip,rk3399-emmc-phy";
                       reg = <0xf780 0x20>;
                       #phy-cells = <0>;
                       status = "disabled";

                       pcfg_emmc_slew_rate_x1_00: pcfg-emmc-slew-rate-x1-00 {
                               slew-rate = <100>;
                       };
                       pcfg_emmc_slew_rate_x1_50: pcfg-emmc-slew-rate-x1-50 {
                               slew-rate = <150>;
                       };
                       pcfg_emmc_slew_rate_x0_75: pcfg-emmc-slew-rate-x0-75 {
                               slew-rate = <75>;
                       };
                       pcfg_emmc_slew_rate_x0_50: pcfg-emmc-slew-rate-x0-50 {
                               slew-rate = <50>;
                       };
                       pcfg_emmc_slew_rate_x1_20: pcfg-emmc-slew-rate-x1-20 {
                               slew-rate = <120>;
                       };
                       pcfg_emmc_slew_rate_x1_20: pcfg-emmc-slew-rate-x1-20 {
                               slew-rate = <120>;
                       };
           };

The nice thing about using the pinctrl API is that:

* It allows us to _also_ control pullups / pulldowns.  We probably
want to control those also since some boards may use external pullups
and others may want to use the internal ones.

* If SDHCI needs to dynamically adjust things (like turning on pulls,
adjusting drive strengths, etc) it can do it in a sane API.



> Another thing I need to elaborate more here is that emmc phy only
> supports 50/100/150/200Mhz. Presumably people love to use the highest
> speed mode with its upper limiting frequency, but in case of some
> special requirement or bad board design, they want to add max-frequency
> in dts for emmc controller. In this case PHYCTRL_FREQSEL_XXXM should
> meet the actual max-frequency, take 100M for example, otherwise
> emmc_phy's  tuning block will use 200M to do some calculation but it
> certainly should be 100M. This leads emmc_phy to choose the wrong
> phase. Finally maybe you will see triggering re-tune easily or some
> worse case of even tuning failure when probing card.

Sounds like this should be handled as per above: make sure that the
PHY has access to the clock and can check it's rate.

---

So overall:

* Should re-spin and remove the comment about 170 MHz.

* I think this could land as-is other than the comment.

* Long term someone (hopefully at Rockchip) should think about making
the driver auto-adjust using the clock API.

* Long term someone (hopefully at Rockchip) should think about trying
to use the pinctrl API to allow adjusting drive strengths and pullups.


-Doug


From dave.long at linaro.org  Fri May 13 12:07:41 2016
From: dave.long at linaro.org (David Long)
Date: Fri, 13 May 2016 15:07:41 -0400
Subject: [PATCH v12 01/10] arm64: Add HAVE_REGS_AND_STACK_ACCESS_API
 feature
In-Reply-To: <57223593.1000503@arm.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-2-git-send-email-dave.long@linaro.org>
 <57223593.1000503@arm.com>
Message-ID: <573625FD.4020004@linaro.org>

On 04/28/2016 12:08 PM, Marc Zyngier wrote:
> On 27/04/16 19:52, David Long wrote:
>> From: "David A. Long" <dave.long at linaro.org>
>>
>> Add HAVE_REGS_AND_STACK_ACCESS_API feature for arm64.
>
> And clearly a lot more.
>
>>
>> Signed-off-by: David A. Long <dave.long at linaro.org>
>> ---
>>   arch/arm64/Kconfig              |   1 +
>>   arch/arm64/include/asm/ptrace.h |  33 ++++++++++-
>>   arch/arm64/kernel/ptrace.c      | 118 ++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 151 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 4f43622..8f662fd 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -80,6 +80,7 @@ config ARM64
>>   	select HAVE_PERF_EVENTS
>>   	select HAVE_PERF_REGS
>>   	select HAVE_PERF_USER_STACK_DUMP
>> +	select HAVE_REGS_AND_STACK_ACCESS_API
>>   	select HAVE_RCU_TABLE_FREE
>>   	select HAVE_SYSCALL_TRACEPOINTS
>>   	select IOMMU_DMA if IOMMU_SUPPORT
>> diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
>> index a307eb6..ee02637 100644
>> --- a/arch/arm64/include/asm/ptrace.h
>> +++ b/arch/arm64/include/asm/ptrace.h
>> @@ -119,6 +119,8 @@ struct pt_regs {
>>   	u64 syscallno;
>>   };
>>
>> +#define MAX_REG_OFFSET offsetof(struct pt_regs, pstate)
>> +
>>   #define arch_has_single_step()	(1)
>>
>>   #ifdef CONFIG_COMPAT
>> @@ -147,6 +149,35 @@ struct pt_regs {
>>   #define user_stack_pointer(regs) \
>>   	(!compat_user_mode(regs) ? (regs)->sp : (regs)->compat_sp)
>>
>> +extern int regs_query_register_offset(const char *name);
>> +extern const char *regs_query_register_name(unsigned int offset);
>> +extern bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr);
>> +extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
>> +					       unsigned int n);
>> +
>> +/**
>> + * regs_get_register() - get register value from its offset
>> + * @regs:	   pt_regs from which register value is gotten
>> + * @offset:    offset number of the register.
>
> Is it the offset? or the number?
>

I've removed "number" from the description.

>> + *
>> + * regs_get_register returns the value of a register whose offset from @regs.
>> + * The @offset is the offset of the register in struct pt_regs.
>> + * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
>> + */
>> +static inline u64 regs_get_register(struct pt_regs *regs,
>> +					      unsigned int offset)
>> +{
>> +	if (unlikely(offset > MAX_REG_OFFSET))
>> +		return 0;
>> +	return *(u64 *)((u64)regs + offset);
>
> So clearly it is the offset. But is 3 a valid value? I don't think so.
> How about something slightly more type safe:
>
> 	u64 val = 0;
>
> 	WARN_ON(offset & 7);
>
> 	offset >>= 3;
> 	switch (offset) {
> 	case	0 ... 30:
> 		val = regs->reg[offset];
> 		break;
> 	case	31:
> 		val = regs->sp;
> 		break;
> 	case	32:
> 		val = regs->pc;
> 		break;
> 	case	33:
>   		val = regs->pstate;
> 		break;
> 	}
>
> 	return val;
>
> I'm pretty sure you could replace 31/32/33 with macros using offsetof().
> The compiler may even optimize this to something similar to what you
> already have.
>
> Thanks,
>
> 	M.
>

I'm not sure this makes sense to me since my best understanding of this 
suite of functions makes the "offset" argument effectively an opaque 
type with a value returned from looking up the register by name in a 
compiled in table that reliably determines the offset within the pt_regs 
structure (i.e.:  regs_query_register_offset() and 
regs_query_register_name()).  Now this change introduces the assumption 
that the gp registers start at the beginning of the structure, 
presumably for the future use of someone hardcoding their own number for 
"offset".

Nonetheless in the interest of moving forward I currently have this 
change sitting in my next patch set.

Thanks,
-dl



From dev at lynxeye.de  Fri May 13 12:08:50 2016
From: dev at lynxeye.de (Lucas Stach)
Date: Fri, 13 May 2016 21:08:50 +0200
Subject: [PATCH] ARM: tegra: beaver: allow SD card voltage to be changed
In-Reply-To: <20160513172704.GA498@ulmo.ba.sec>
References: <1456779678-20173-1-git-send-email-dev@lynxeye.de>
 <1463124331.2459.0.camel@lynxeye.de> <20160513172704.GA498@ulmo.ba.sec>
Message-ID: <1463166530.2556.5.camel@lynxeye.de>

Am Freitag, den 13.05.2016, 19:27 +0200 schrieb Thierry Reding:
> On Fri, May 13, 2016 at 09:25:31AM +0200, Lucas Stach wrote:
> > 
> > Am Montag, den 29.02.2016, 22:01 +0100 schrieb Lucas Stach:
> > > 
> > > This allows to switch the card signal voltage level to 1.8V,
> > > which is needed for any ultra high speed modes to work.
> > > 
> > > Signed-off-by: Lucas Stach <dev at lynxeye.de>
> > > ---
> > > This needs the SDMMC memcomp pad calibration patches I just
> > > sent out to be applied, otherwise the card voltage change will
> > > fail with a message in the kernel log and a fall back to
> > > high speed operation.
> > The patches this one depends on have been applied for some time
> > now.
> > Please pick up this patch.
> My understanding is that UHS modes currently cause problems on
> Beaver.
> What I don't understand about that is how it will even try those
> modes
> if the voltage regulator can't be set to 1.8 V? Shouldn't that
> actively
> prevent those modes from even being attempted?
> 
AFAIK this is right. I haven't re-tested with v4.6 yet, but on v4.5
without this change the high-speed modes using 1.8V signaling would not
be used on the SD card. As eMMC doesn't need the voltage switch, this
one will work in high-speed mode on Beaver.

Regards,
Lucas


From dianders at chromium.org  Fri May 13 12:43:25 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 13 May 2016 12:43:25 -0700
Subject: [PATCH 1/2] clk: rockchip: mark rk3399 GIC clocks as critical
In-Reply-To: <1463164937-91089-1-git-send-email-briannorris@chromium.org>
References: <1463164937-91089-1-git-send-email-briannorris@chromium.org>
Message-ID: <CAD=FV=UjPy-n-53nhxr7yC1t1j+eD6pRt0_i5_6hhY=Rnz6xsw@mail.gmail.com>

Brian,

On Fri, May 13, 2016 at 11:42 AM, Brian Norris <briannorris at chromium.org> wrote:
> We never want to kill the GIC.
>
> Noticed when making other clock fixups, and seeing the newly-constructed
> clock tree try to disable cpll, where we had this parent structure:
>
>   aclk_gic <------\
>                   |--- aclk_gic_pre <-- cpll <-- pll_cpll
>   aclk_gic_noc <--/
>
> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
>  drivers/clk/rockchip/clk-rk3399.c | 2 ++
>  1 file changed, 2 insertions(+)

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


From oliver at schinagl.nl  Fri May 13 12:57:16 2016
From: oliver at schinagl.nl (Olliver Schinagl)
Date: Fri, 13 May 2016 21:57:16 +0200
Subject: [PATCH 1/1] devicetree: sunxi: Add OLinuXino Lime2 eMMC to the
 Makefile
Message-ID: <1463169436-6170-1-git-send-email-oliver@schinagl.nl>

commit 27dd9af6bc000ab21fd ("ARM: dts: sunxi: Add a olinuxino-lime2-emmc")
added the new emmc equipped lime2 but forgot its Makefile.

This patch adds an entry to the Makefile.

Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>
---
Changes since v1:
  Added proper commit reference (again).
Changes since v0:
  Added proper commit reference.
 arch/arm/boot/dts/Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 95c1923..07f4cf8 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -695,6 +695,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \
 	sun7i-a20-olimex-som-evb.dtb \
 	sun7i-a20-olinuxino-lime.dtb \
 	sun7i-a20-olinuxino-lime2.dtb \
+	sun7i-a20-olinuxino-lime2-emmc.dtb \
 	sun7i-a20-olinuxino-micro.dtb \
 	sun7i-a20-orangepi.dtb \
 	sun7i-a20-orangepi-mini.dtb \
-- 
2.8.1



From dave.long at linaro.org  Fri May 13 13:02:12 2016
From: dave.long at linaro.org (David Long)
Date: Fri, 13 May 2016 16:02:12 -0400
Subject: [PATCH v12 00/10] arm64: Add kernel probes (kprobes) support
In-Reply-To: <5733E9E0.1060504@huawei.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <573350B2.4010701@arm.com> <5733E9E0.1060504@huawei.com>
Message-ID: <573632C4.9010501@linaro.org>

On 05/11/2016 10:26 PM, Li Bin wrote:
>
>
> on 2016/5/11 23:33, James Morse wrote:
>> Hi David,
>>
>> On 27/04/16 19:52, David Long wrote:
>>> From: "David A. Long" <dave.long at linaro.org>
>>>
>>> This patchset is heavily based on Sandeepa Prabhu's ARM v8 kprobes patches,
>>> first seen in October 2013. This version attempts to address concerns raised by
>>> reviewers and also fixes problems discovered during testing.
>>>
>>> This patchset adds support for kernel probes(kprobes), jump probes(jprobes)
>>> and return probes(kretprobes) support for ARM64.
>>>
>>> The kprobes mechanism makes use of software breakpoint and single stepping
>>> support available in the ARM v8 kernel.
>>
>> I applied this series on v4.6-rc7, and built the sample kprobes. They work fine,
>> unless I throw ftrace into the mix too.
>>
>> I enabled the function_graph tracer, then tried to load the jprobe example module:
>> -------------------------%<-------------------------
>> root at ubuntu:/sys/kernel/debug/tracing# insmod /root/jprobe_example.ko
>> Planted jprobe at ffffff80080c8f20, handler addr ffffff8000bb3000
>> root at ubuntu:/sys/kernel/debug/tracing# jprobe: clone_flags = 0x1200011, stack_st
>> art = 0x0 stack_size = 0x0
>> Bad mode in Synchronous Abort handler detected, code 0x86000005 -- IABT (current
>>   EL)
>> CPU: 5 PID: 1047 Comm: systemd-udevd Not tainted 4.6.0-rc7+ #4064
>> Hardware name: ARM Juno development board (r1) (DT)
>> task: ffffffc975948300 ti: ffffffc974e4c000 task.ti: ffffffc974e4c000
>> PC is at 0x0
>> LR is at 0x0
>>
>> pc : [<0000000000000000>] lr : [<0000000000000000>] pstate: 60000145
>> sp : ffffffc974e4ff00
>> x29: 0000000001200011 x28: ffffffc974e4c000
>> x27: ffffff80088d0000 x26: 00000000000000dc
>> x25: 0000000000000120 x24: 0000000000000015
>> x23: 0000000060000000 x22: 0000007fa1b40e60
>> x21: 0000007fa1ce70d0 x20: 0000000000000000
>> x19: 0000000000000000 x18: 0000000000000a03
>> x17: 0000007fa1b40d90 x16: ffffff80080c9708
>> x15: 003b9aca00000000 x14: 0000007fddb7e5c0
>> x13: 0000007fa1b40e2c x12: 0000000000d00ff0
>> x11: ffffff8009c4d000 x10: ffffff800920c000
>> x9 : ffffff8008f5c000 x8 : ffffffc976c06800
>> x7 : 000000000006daf2 x6 : 0000000000000015
>> x5 : 0000000000000004 x4 : ffffffc96e8690a0
>> x3 : 0000001ed7cbab74 x2 : ffffffc96e869000
>> x1 : 0000000000000000 x0 : 0000000000000000
>>
>> Internal error: Oops - bad mode: 0 [#1] PREEMPT SMP
>> Modules linked in: jprobe_example
>> CPU: 5 PID: 1047 Comm: systemd-udevd Not tainted 4.6.0-rc7+ #4064
>> Hardware name: ARM Juno development board (r1) (DT)
>> task: ffffffc975948300 ti: ffffffc974e4c000 task.ti: ffffffc974e4c000
>> PC is at 0x0
>> LR is at 0x0
>>
>> pc : [<0000000000000000>] lr : [<0000000000000000>] pstate: 60000145
>> sp : ffffffc974e4ff00
>> x29: 0000000001200011 x28: ffffffc974e4c000
>> x27: ffffff80088d0000 x26: 00000000000000dc
>> x25: 0000000000000120 x24: 0000000000000015
>> x23: 0000000060000000 x22: 0000007fa1b40e60
>> x21: 0000007fa1ce70d0 x20: 0000000000000000
>> x19: 0000000000000000 x18: 0000000000000a03
>> x17: 0000007fa1b40d90 x16: ffffff80080c9708
>> x15: 003b9aca00000000 x14: 0000007fddb7e5c0
>> x13: 0000007fa1b40e2c x12: 0000000000d00ff0
>> x11: ffffff8009c4d000 x10: ffffff800920c000
>> x9 : ffffff8008f5c000 x8 : ffffffc976c06800
>> x7 : 000000000006daf2 x6 : 0000000000000015
>> x5 : 0000000000000004 x4 : ffffffc96e8690a0
>> x3 : 0000001ed7cbab74 x2 : ffffffc96e869000
>> x1 : 0000000000000000 x0 : 0000000000000000
>>
>> Process systemd-udevd (pid: 1047, stack limit = 0xffffffc974e4c020)
>> Stack: (0xffffffc974e4ff00 to 0xffffffc974e50000)
>> ff00: 0000000000000417 0000007fa1ce76f0 00000000000000dc 0000000000000417
>> ff20: 00000000ffffffff 0000007fddb7ecf8 0000000000000005 ffffffffffffffff
>> ff40: 00000000ff000001 003b9aca00000000 000000555b3868b0 0000007fa1b40d90
>> ff60: 0000000000000a03 0000007fddb7e5c0 0000000000000000 0000007fddb7e5e0
>> ff80: 000000555b358000 000000558f56f0e0 0000000000000000 000000558f574f00
>> ffa0: 000000558f574f00 00000000000004fa 000000558f56f010 0000007fddb7e600
>> ffc0: 0000007fa1b40e2c 0000007fddb7e5c0 0000007fa1b40e60 0000000060000000
>> ffe0: 0000000001200011 00000000000000dc 0004000084000200 0800000002000000
>> Call trace:
>> [<          (null)>]           (null)
>> Code: bad PC value
>> ---[ end trace 35d24aad799c2941 ]---
>> -------------------------%<-------------------------
>>
>
> To solve this, it should pause function tracing before the jprobe handler is called
> and unpause it before it returns back to the function it probed.
>
> diff --git a/arch/arm64/kernel/kprobes.c b/arch/arm64/kernel/kprobes.c
> index db2d95c..b21ed00 100644
> --- a/arch/arm64/kernel/kprobes.c
> +++ b/arch/arm64/kernel/kprobes.c
> @@ -714,6 +714,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
>
>          instruction_pointer_set(regs, (long)jp->entry);
>          preempt_disable();
> +       pause_graph_tracing();
>          return 1;
>   }
>
> @@ -757,6 +758,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
>                          show_regs(regs);
>                          BUG();
>                  }
> +               unpause_graph_tracing();
>                  *regs = kcb->jprobe_saved_regs;
>                  memcpy((void *)stack_addr, kcb->jprobes_stack,
>                         MIN_STACK_SIZE(stack_addr));
>
>
> Li Bin
>
>>
>> Thanks,
>>
>>
>> James


Thanks for the suggested fix.

-dl




From dianders at chromium.org  Fri May 13 13:10:57 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 13 May 2016 13:10:57 -0700
Subject: [PATCH 2/2] clk: rockchip: fix incorrect parent for rk3399's {c,
 g}pll_aclk_perihp_src
In-Reply-To: <1463164937-91089-2-git-send-email-briannorris@chromium.org>
References: <1463164937-91089-1-git-send-email-briannorris@chromium.org>
 <1463164937-91089-2-git-send-email-briannorris@chromium.org>
Message-ID: <CAD=FV=XstYhqpStSGw5PObWvpsvd3Nwp_hfEE-56bpFoVUyu+g@mail.gmail.com>

Hi,

On Fri, May 13, 2016 at 11:42 AM, Brian Norris <briannorris at chromium.org> wrote:
> From: Xing Zheng <zhengxing at rock-chips.com>
>
> There was a typo, swapping 'c' <--> 'g'.
>
> Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
>  drivers/clk/rockchip/clk-rk3399.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
> index 145756c4f3c8..9f86bfef70f7 100644
> --- a/drivers/clk/rockchip/clk-rk3399.c
> +++ b/drivers/clk/rockchip/clk-rk3399.c
> @@ -832,9 +832,9 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
>                         RK3399_CLKGATE_CON(13), 1, GFLAGS),
>
>         /* perihp */
> -       GATE(0, "cpll_aclk_perihp_src", "gpll", CLK_IGNORE_UNUSED,
> +       GATE(0, "cpll_aclk_perihp_src", "cpll", CLK_IGNORE_UNUSED,
>                         RK3399_CLKGATE_CON(5), 0, GFLAGS),
> -       GATE(0, "gpll_aclk_perihp_src", "cpll", CLK_IGNORE_UNUSED,
> +       GATE(0, "gpll_aclk_perihp_src", "gpll", CLK_IGNORE_UNUSED,
>                         RK3399_CLKGATE_CON(5), 1, GFLAGS),
>         COMPOSITE(ACLK_PERIHP, "aclk_perihp", mux_aclk_perihp_p, CLK_IGNORE_UNUSED,
>                         RK3399_CLKSEL_CON(14), 7, 1, MFLAGS, 0, 5, DFLAGS,

Definitely there was a bug since this table itself was inconsistent.
...and I _think_ this fix is correct, but I'll note that the TRM has
more inconsistency here.

In the big clock table 'CRU Clock Architecture Diagram', I see:
  CLK 4 is CPLL
  CLK 5 is GPLL
  CLK 125 is aclk_perihp_cpll_src and has 4 (CPLL) as source, with
g5[0] as the bit
  CLK 126 is aclk_perihp_gpll_src and has 5 (GPLL) as source, with
g5[1] as the bit

In the definition of CRU_CLKGATE_CON5:
  bit 0 shows aclk_perihp_gpll_src_en
  bit 1 shows aclk_perihp_cpll_src_en


Thus the table shows CPLL as gate5[0] and GPLL as gate5[1].  The
register definition shows the opposite.  I'll tend to believe the
table over the register definition, but I figured I'd bring it up
anyway.


Xing Zheng: can you confirm that the table is correct and ask
documentation folks to fix the register definition for
CRU_CLKGATE_CON5?



Thanks!

-Doug


From briannorris at chromium.org  Fri May 13 13:50:18 2016
From: briannorris at chromium.org (Brian Norris)
Date: Fri, 13 May 2016 13:50:18 -0700
Subject: [PATCH] ARM64: dts: rockchip: assign default rates for core rk3399
 clocks
Message-ID: <1463172618-96001-1-git-send-email-briannorris@chromium.org>

From: Xing Zheng <zhengxing at rock-chips.com>

These clocks are all core clocks used by many blocks/peripherals, many
of whose drivers don't set their clock rates at all. Let's assign
reasonable default clock rates for these core clocks, so that these
peripherals get something reasonable by default, and also so that if
child devices want to select a clock rate themselves, their muxes have
some reasonable parent clock rates to branch off of (rather than just
the boot-time defaults).

This helps the eMMC PHY, for one, to get a reasonable ACLK rate.

Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
Signed-off-by: Brian Norris <briannorris at chromium.org>
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 46f325a143b0..6fa9cc332482 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -478,6 +478,22 @@
 		reg = <0x0 0xff760000 0x0 0x1000>;
 		#clock-cells = <1>;
 		#reset-cells = <1>;
+		assigned-clocks =
+			<&cru PLL_GPLL>, <&cru PLL_CPLL>,
+			<&cru PLL_NPLL>,
+			<&cru ACLK_PERIHP>, <&cru HCLK_PERIHP>,
+			<&cru PCLK_PERIHP>,
+			<&cru ACLK_PERILP0>, <&cru HCLK_PERILP0>,
+			<&cru PCLK_PERILP0>,
+			<&cru HCLK_PERILP1>, <&cru PCLK_PERILP1>;
+		assigned-clock-rates =
+			 <594000000>,  <800000000>,
+			<1000000000>,
+			 <150000000>,   <75000000>,
+			  <37500000>,
+			 <100000000>,  <100000000>,
+			  <50000000>,
+			 <100000000>,   <50000000>;
 	};
 
 	grf: syscon at ff770000 {
-- 
2.8.0.rc3.226.g39d4020



From arnd at arndb.de  Fri May 13 14:01:11 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 13 May 2016 23:01:11 +0200
Subject: linux-next: build failure after merge of the net-next tree
In-Reply-To: <20160510183934.GJ1256@tuxbot>
References: <20160510112905.5bffcad8@canb.auug.org.au>
 <20160510183934.GJ1256@tuxbot>
Message-ID: <2606282.lG9qK7uBW0@wuerfel>

On Tuesday 10 May 2016 11:39:34 Bjorn Andersson wrote:
> On Mon 09 May 18:29 PDT 2016, Stephen Rothwell wrote:
> 
> > Hi all,
> > 
> > After merging the net-next tree, today's linux-next build (x86_64
> > allmodconfig) failed like this:
> > 
> > net/qrtr/smd.c:106:14: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
> >   .callback = qcom_smd_qrtr_callback,
> >               ^
> > net/qrtr/smd.c:106:14: note: (near initialization for 'qcom_smd_qrtr_driver.callback')
> > 
> > Caused by commit
> > 
> >   bdabad3e363d ("net: Add Qualcomm IPC router")
> > 
> > interacting with commit
> > 
> >   b853cb9628bf ("soc: qcom: smd: Make callback pass channel reference")
> > 
> > from the arm-soc tree.
> > 
> > I added the following merge fix patch (and it turned out I needed the
> > new stubs).
> > 
> 
> Sorry for not spotting this issue earlier, I missed Andy's second pull
> request towards arm-soc and thought the SMD changes missed this cycle.
> 
> 
> Your patch looks good, but I'm not sure how we should approach the merge
> window; Andy can't pick the patch because he doesn't have the qrtr code
> and David doesn't have the SMD patches coming through Andy.
> 
> FWIW, Reviewed-by: Bjorn Andersson <bjorn.andersson at linaro.org>
> 
> 
> I assume we could have the QRTR go through Andy and arm-soc, with
> David's approval and this fix squashed in. But we're running rather late
> in this cycle, perhaps we should just back the QRTR patches out and I
> can respin and resend them after the merge window (for v4.8 instead)?

I'd suggest you do a merge of next-next with the qcom/soc-2 branch that
we have in arm-soc and resolve the conflict in the merge, then send
a pull request with the merge to davem.

Alternatively, in case Linus merges net-next before we get that fix
in, I could send Stephen's fix to Linus along with the pull requests.

	Arnd


From briannorris at chromium.org  Fri May 13 14:04:40 2016
From: briannorris at chromium.org (Brian Norris)
Date: Fri, 13 May 2016 14:04:40 -0700
Subject: [PATCH 2/4] phy: rockchip-emmc: configure frequency range and
 drive impedance
In-Reply-To: <CAD=FV=UwocUy_bOUrJZB47taHWdV1KGkvi5CyZf74Y8cvGgVmw@mail.gmail.com>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
 <1463092986-61777-2-git-send-email-briannorris@chromium.org>
 <3695875b-09c3-cd80-3062-55d985e51f70@rock-chips.com>
 <CAD=FV=UwocUy_bOUrJZB47taHWdV1KGkvi5CyZf74Y8cvGgVmw@mail.gmail.com>
Message-ID: <20160513210440.GA99074@google.com>

On Fri, May 13, 2016 at 11:46:33AM -0700, Doug Anderson wrote:
> On Thu, May 12, 2016 at 6:02 PM, Shawn Lin <shawn.lin at rock-chips.com> wrote:
> > On 2016/5/13 6:43, Brian Norris wrote:
> >> @@ -154,6 +167,20 @@ static int rockchip_emmc_phy_power_on(struct phy
> >> *phy)
> >>         struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
> >>         int ret = 0;
> >>
> >> +       /* DLL operation: 170 to 200 MHz */
> >
> >
> > What is 170 here? Should we expose them to dt instead of hardcoding
> > them?
> 
> This was probably my fault.  I did some searching and found
> <https://arasan.com/wp-content/media/eMMC-5-1-Total-Solution_Rev-1-3.pdf>.
> It appears to be docs for a similar (but not identical) PHY.  We were
> looking at it to try to get more clarity on some bits that were hard
> to understand in the docs we had.
> 
> In that doc there appear to be 3 bits for selecting the DLL operation
> and they have ranges defined.  In Rockchip's PHY there are only 2
> bits.  Thus things don't map totally properly.
> 
> Anyway, comment should probably be removed.

[...]

> So overall:
> 
> * Should re-spin and remove the comment about 170 MHz.
> 
> * I think this could land as-is other than the comment.

Right, will fix the first bullet point.

Brian


From briannorris at chromium.org  Fri May 13 14:09:43 2016
From: briannorris at chromium.org (Brian Norris)
Date: Fri, 13 May 2016 14:09:43 -0700
Subject: [PATCH v2 2/4] phy: rockchip-emmc: configure frequency range and
 drive impedance
In-Reply-To: <1463092986-61777-2-git-send-email-briannorris@chromium.org>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
 <1463092986-61777-2-git-send-email-briannorris@chromium.org>
Message-ID: <20160513210943.GB99074@google.com>

From: Shawn Lin <shawn.lin at rock-chips.com>

Signal integrity analysis has suggested we set these values. Do this in
power_on(), so that they get reconfigured after suspend/resume.

Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
Signed-off-by: Brian Norris <briannorris at chromium.org>
---
v2:
 * Sent only patch 2/4 with version 2, to avoid spamming; will move on to v3
   for all patches if I need to send another
 * Drop 170 MHz comment; this was only applicable to a subtly different Arasan
   PHY

 drivers/phy/phy-rockchip-emmc.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/phy-rockchip-emmc.c
index 48cbe691a889..f2f75cf69af1 100644
--- a/drivers/phy/phy-rockchip-emmc.c
+++ b/drivers/phy/phy-rockchip-emmc.c
@@ -56,6 +56,19 @@
 #define PHYCTRL_DLLRDY_SHIFT	0x5
 #define PHYCTRL_DLLRDY_DONE	0x1
 #define PHYCTRL_DLLRDY_GOING	0x0
+#define PHYCTRL_FREQSEL_200M	0x0
+#define PHYCTRL_FREQSEL_50M	0x1
+#define PHYCTRL_FREQSEL_100M	0x2
+#define PHYCTRL_FREQSEL_150M	0x3
+#define PHYCTRL_FREQSEL_MASK	0x3
+#define PHYCTRL_FREQSEL_SHIFT	0xc
+#define PHYCTRL_DR_MASK		0x7
+#define PHYCTRL_DR_SHIFT	0x4
+#define PHYCTRL_DR_50OHM	0x0
+#define PHYCTRL_DR_33OHM	0x1
+#define PHYCTRL_DR_66OHM	0x2
+#define PHYCTRL_DR_100OHM	0x3
+#define PHYCTRL_DR_40OHM	0x4
 
 struct rockchip_emmc_phy {
 	unsigned int	reg_offset;
@@ -154,6 +167,20 @@ static int rockchip_emmc_phy_power_on(struct phy *phy)
 	struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy);
 	int ret = 0;
 
+	/* DLL operation: 200 MHz */
+	regmap_write(rk_phy->reg_base,
+		     rk_phy->reg_offset + GRF_EMMCPHY_CON0,
+		     HIWORD_UPDATE(PHYCTRL_FREQSEL_200M,
+				   PHYCTRL_FREQSEL_MASK,
+				   PHYCTRL_FREQSEL_SHIFT));
+
+	/* Drive impedance: 50 Ohm */
+	regmap_write(rk_phy->reg_base,
+		     rk_phy->reg_offset + GRF_EMMCPHY_CON6,
+		     HIWORD_UPDATE(PHYCTRL_DR_50OHM,
+				   PHYCTRL_DR_MASK,
+				   PHYCTRL_DR_SHIFT));
+
 	/* Power up emmc phy analog blocks */
 	ret = rockchip_emmc_phy_power(rk_phy, PHYCTRL_PDB_PWR_ON);
 	if (ret)
-- 
2.8.0.rc3.226.g39d4020



From dianders at chromium.org  Fri May 13 14:20:42 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 13 May 2016 14:20:42 -0700
Subject: [PATCH] ARM64: dts: rockchip: assign default rates for core
 rk3399 clocks
In-Reply-To: <1463172618-96001-1-git-send-email-briannorris@chromium.org>
References: <1463172618-96001-1-git-send-email-briannorris@chromium.org>
Message-ID: <CAD=FV=V+AmXzHmB06=Lp6w5wGBCYUgZr5gsbSKwsVSOTq=tNYw@mail.gmail.com>

Hi,

On Fri, May 13, 2016 at 1:50 PM, Brian Norris <briannorris at chromium.org> wrote:
> From: Xing Zheng <zhengxing at rock-chips.com>
>
> These clocks are all core clocks used by many blocks/peripherals, many
> of whose drivers don't set their clock rates at all. Let's assign
> reasonable default clock rates for these core clocks, so that these
> peripherals get something reasonable by default, and also so that if
> child devices want to select a clock rate themselves, their muxes have
> some reasonable parent clock rates to branch off of (rather than just
> the boot-time defaults).
>
> This helps the eMMC PHY, for one, to get a reasonable ACLK rate.
>
> Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
>  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> index 46f325a143b0..6fa9cc332482 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -478,6 +478,22 @@
>                 reg = <0x0 0xff760000 0x0 0x1000>;
>                 #clock-cells = <1>;
>                 #reset-cells = <1>;
> +               assigned-clocks =
> +                       <&cru PLL_GPLL>, <&cru PLL_CPLL>,
> +                       <&cru PLL_NPLL>,
> +                       <&cru ACLK_PERIHP>, <&cru HCLK_PERIHP>,
> +                       <&cru PCLK_PERIHP>,
> +                       <&cru ACLK_PERILP0>, <&cru HCLK_PERILP0>,
> +                       <&cru PCLK_PERILP0>,
> +                       <&cru HCLK_PERILP1>, <&cru PCLK_PERILP1>;
> +               assigned-clock-rates =
> +                        <594000000>,  <800000000>,
> +                       <1000000000>,
> +                        <150000000>,   <75000000>,
> +                         <37500000>,
> +                        <100000000>,  <100000000>,
> +                         <50000000>,
> +                        <100000000>,   <50000000>;

I agree that
* this is sane information to have in this node (like in rk3288)
* the rates look sane (similar to rk3288 but two are double)
* these rates match what I see in Rockchip's kernel

So:

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


From dianders at chromium.org  Fri May 13 14:42:06 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 13 May 2016 14:42:06 -0700
Subject: [PATCH v2 1/2] ARM64: dts: rockchip: add sdhci/emmc for rk3399
In-Reply-To: <1463092552-60696-1-git-send-email-briannorris@chromium.org>
References: <1463092552-60696-1-git-send-email-briannorris@chromium.org>
Message-ID: <CAD=FV=UwtHu+DmJZqeWDQ8B9wMVdKODRignqDdZ4rknnmQru3g@mail.gmail.com>

Hi,

On Thu, May 12, 2016 at 3:35 PM, Brian Norris <briannorris at chromium.org> wrote:
> Add description for the SDHCI v5.1 eMMC controller on rk3399. Fix it to
> 200 MHz, to support all supported timing modes.
>
> Note that 'rockchip,rk3399-sdhci-5.1' is not documented; we presumably
> have a compliant Arasan controller, but let's have a rockchip property
> as the canonical backup/precautionary measure. Per Heiko's previous
> suggestion, let's not clutter the arasan doc with it.
>
> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
> v2:
>
>  * improved commit message
>  * assign eMMC clock to 200 MHz
>
>  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 25 ++++++++++++++++++++++++-
>  1 file changed, 24 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> index 46f325a143b0..9980c2eab4e9 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -215,6 +215,19 @@
>                 status = "disabled";
>         };
>
> +       sdhci: sdhci at fe330000 {
> +               compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
> +               reg = <0x0 0xfe330000 0x0 0x10000>;
> +               interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
> +               clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;
> +               clock-names = "clk_xin", "clk_ahb";
> +               assigned-clocks = <&cru SCLK_EMMC>;
> +               assigned-clock-rates = <200000000>;
> +               phys = <&emmc_phy>;
> +               phy-names = "phy_arasan";
> +               status = "disabled";
> +       };
> +
>         usb_host0_ehci: usb at fe380000 {
>                 compatible = "generic-ehci";
>                 reg = <0x0 0xfe380000 0x0 0x20000>;
> @@ -481,8 +494,18 @@
>         };
>
>         grf: syscon at ff770000 {
> -               compatible = "rockchip,rk3399-grf", "syscon";
> +               compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
>                 reg = <0x0 0xff770000 0x0 0x10000>;
> +
> +               #address-cells = <1>;
> +               #size-cells = <1>;
> +
> +               emmc_phy: phy at f780 {
> +                       compatible = "rockchip,rk3399-emmc-phy";
> +                       reg = <0xf780 0x20>;

This is slightly wrong.  It should be:

reg = <0xf780 0x24>;

The status register is at an offset of 0x20 and is 4 bytes big, so we
need room for it.


After that is fixed, feel free to add my Reviewed-by tag.

-Doug


From briannorris at chromium.org  Fri May 13 14:47:24 2016
From: briannorris at chromium.org (Brian Norris)
Date: Fri, 13 May 2016 14:47:24 -0700
Subject: [PATCH v3 1/2] ARM64: dts: rockchip: add sdhci/emmc for rk3399
Message-ID: <1463176045-109748-1-git-send-email-briannorris@chromium.org>

Add description for the SDHCI v5.1 eMMC controller on rk3399. Fix it to
200 MHz, to support all supported timing modes.

Note that 'rockchip,rk3399-sdhci-5.1' is not documented; we presumably
have a compliant Arasan controller, but let's have a rockchip property
as the canonical backup/precautionary measure. Per Heiko's previous
suggestion, let's not clutter the arasan doc with it.

Signed-off-by: Brian Norris <briannorris at chromium.org>
Reviewed-by: Doug Anderson <dianders at chromium.org>
Reviewed-by: Shawn Lin <shawn.lin at rock-chips.com>
---
v3:

 * correct emmc_phy reg length to 0x24

v2:

 * improved commit message
 * assign eMMC clock to 200 MHz


 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 46f325a143b0..99078f5ebeb9 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -215,6 +215,19 @@
 		status = "disabled";
 	};
 
+	sdhci: sdhci at fe330000 {
+		compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
+		reg = <0x0 0xfe330000 0x0 0x10000>;
+		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;
+		clock-names = "clk_xin", "clk_ahb";
+		assigned-clocks = <&cru SCLK_EMMC>;
+		assigned-clock-rates = <200000000>;
+		phys = <&emmc_phy>;
+		phy-names = "phy_arasan";
+		status = "disabled";
+	};
+
 	usb_host0_ehci: usb at fe380000 {
 		compatible = "generic-ehci";
 		reg = <0x0 0xfe380000 0x0 0x20000>;
@@ -481,8 +494,18 @@
 	};
 
 	grf: syscon at ff770000 {
-		compatible = "rockchip,rk3399-grf", "syscon";
+		compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
 		reg = <0x0 0xff770000 0x0 0x10000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		emmc_phy: phy at f780 {
+			compatible = "rockchip,rk3399-emmc-phy";
+			reg = <0xf780 0x24>;
+			#phy-cells = <0>;
+			status = "disabled";
+		};
 	};
 
 	watchdog at ff840000 {
-- 
2.8.0.rc3.226.g39d4020



From briannorris at chromium.org  Fri May 13 14:47:25 2016
From: briannorris at chromium.org (Brian Norris)
Date: Fri, 13 May 2016 14:47:25 -0700
Subject: [PATCH v3 2/2] ARM64: dts: rockchip: enable eMMC for rk3399 EVB
In-Reply-To: <1463176045-109748-1-git-send-email-briannorris@chromium.org>
References: <1463176045-109748-1-git-send-email-briannorris@chromium.org>
Message-ID: <1463176045-109748-2-git-send-email-briannorris@chromium.org>

Rockchip's rk3399 evaluation board has eMMC. Let's enable the
newly-added node.

Signed-off-by: Brian Norris <briannorris at chromium.org>
---
v3:

 * no change

v2:

 * better commit description

 arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
index 1a3eb1482050..0b27d91084c4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
@@ -89,6 +89,18 @@
 	status = "okay";
 };
 
+&emmc_phy {
+	status = "okay";
+};
+
+&sdhci {
+	bus-width = <8>;
+	mmc-hs400-1_8v;
+	mmc-hs400-enhanced-strobe;
+	non-removable;
+	status = "okay";
+};
+
 &uart2 {
 	status = "okay";
 };
-- 
2.8.0.rc3.226.g39d4020



From heiko at sntech.de  Fri May 13 14:47:57 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Fri, 13 May 2016 23:47:57 +0200
Subject: [PATCH v2 1/2] ARM64: dts: rockchip: add sdhci/emmc for rk3399
In-Reply-To: <1463092552-60696-1-git-send-email-briannorris@chromium.org>
References: <1463092552-60696-1-git-send-email-briannorris@chromium.org>
Message-ID: <5607915.FAWxOoA1QB@phil>

Am Donnerstag, 12. Mai 2016, 15:35:51 schrieb Brian Norris:
> Add description for the SDHCI v5.1 eMMC controller on rk3399. Fix it to
> 200 MHz, to support all supported timing modes.
> 
> Note that 'rockchip,rk3399-sdhci-5.1' is not documented; we presumably
> have a compliant Arasan controller, but let's have a rockchip property
> as the canonical backup/precautionary measure. Per Heiko's previous
> suggestion, let's not clutter the arasan doc with it.
> 
> Signed-off-by: Brian Norris <briannorris at chromium.org>

At least one split is necessary.
So please at least split out the simple-mfd addition into a separate patch
(I should've seen that in v1 already, but sadly didn't)

I'm undecided if the emmc-phy addition also should get its own patch, but I 
guess it can stay together with the emmc controller.

> ---
> v2:
> 
>  * improved commit message
>  * assign eMMC clock to 200 MHz
> 
>  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 25 ++++++++++++++++++++++++-
>  1 file changed, 24 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index
> 46f325a143b0..9980c2eab4e9 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -215,6 +215,19 @@
>  		status = "disabled";
>  	};
> 
> +	sdhci: sdhci at fe330000 {
> +		compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
> +		reg = <0x0 0xfe330000 0x0 0x10000>;
> +		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;
> +		clock-names = "clk_xin", "clk_ahb";
> +		assigned-clocks = <&cru SCLK_EMMC>;
> +		assigned-clock-rates = <200000000>;
> +		phys = <&emmc_phy>;
> +		phy-names = "phy_arasan";
> +		status = "disabled";
> +	};
> +
>  	usb_host0_ehci: usb at fe380000 {
>  		compatible = "generic-ehci";
>  		reg = <0x0 0xfe380000 0x0 0x20000>;
> @@ -481,8 +494,18 @@
>  	};
> 
>  	grf: syscon at ff770000 {
> -		compatible = "rockchip,rk3399-grf", "syscon";
> +		compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
>  		reg = <0x0 0xff770000 0x0 0x10000>;
> +
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +
> +		emmc_phy: phy at f780 {
> +			compatible = "rockchip,rk3399-emmc-phy";
> +			reg = <0xf780 0x20>;
> +			#phy-cells = <0>;
> +			status = "disabled";
> +		};
>  	};
> 
>  	watchdog at ff840000 {



From briannorris at chromium.org  Fri May 13 14:48:15 2016
From: briannorris at chromium.org (Brian Norris)
Date: Fri, 13 May 2016 14:48:15 -0700
Subject: [PATCH v2 1/2] ARM64: dts: rockchip: add sdhci/emmc for rk3399
In-Reply-To: <CAD=FV=UwtHu+DmJZqeWDQ8B9wMVdKODRignqDdZ4rknnmQru3g@mail.gmail.com>
References: <1463092552-60696-1-git-send-email-briannorris@chromium.org>
 <CAD=FV=UwtHu+DmJZqeWDQ8B9wMVdKODRignqDdZ4rknnmQru3g@mail.gmail.com>
Message-ID: <20160513214815.GA109473@google.com>

On Fri, May 13, 2016 at 02:42:06PM -0700, Doug Anderson wrote:
> On Thu, May 12, 2016 at 3:35 PM, Brian Norris <briannorris at chromium.org> wrote:
> > +               emmc_phy: phy at f780 {
> > +                       compatible = "rockchip,rk3399-emmc-phy";
> > +                       reg = <0xf780 0x20>;
> 
> This is slightly wrong.  It should be:
> 
> reg = <0xf780 0x24>;
> 
> The status register is at an offset of 0x20 and is 4 bytes big, so we
> need room for it.

Fixed.

> After that is fixed, feel free to add my Reviewed-by tag.

Done.

Thanks for the review.

Brian


From heiko at sntech.de  Fri May 13 14:49:52 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Fri, 13 May 2016 23:49:52 +0200
Subject: [PATCH v2 2/2] ARM64: dts: rockchip: enable eMMC for rk3399 EVB
In-Reply-To: <1463092552-60696-2-git-send-email-briannorris@chromium.org>
References: <1463092552-60696-1-git-send-email-briannorris@chromium.org>
 <1463092552-60696-2-git-send-email-briannorris@chromium.org>
Message-ID: <1537214.5jQgtQP16t@phil>

Am Donnerstag, 12. Mai 2016, 15:35:52 schrieb Brian Norris:
> Rockchip's rk3399 evaluation board has eMMC. Let's enable the
> newly-added node.
> 
> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
> v2:
> 
>  * better commit description
> 
>  arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts index
> 1a3eb1482050..0b27d91084c4 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
> @@ -89,6 +89,18 @@
>  	status = "okay";
>  };
> 
> +&emmc_phy {
> +	status = "okay";
> +};

another thing I should've seen yesterday, emmc_phy should not be below the 
&pwm nodes (aka alphabetically please)


Heiko

> +&sdhci {
> +	bus-width = <8>;
> +	mmc-hs400-1_8v;
> +	mmc-hs400-enhanced-strobe;
> +	non-removable;
> +	status = "okay";
> +};
> +
>  &uart2 {
>  	status = "okay";
>  };



From briannorris at chromium.org  Fri May 13 14:57:24 2016
From: briannorris at chromium.org (Brian Norris)
Date: Fri, 13 May 2016 14:57:24 -0700
Subject: [PATCH v2 1/2] ARM64: dts: rockchip: add sdhci/emmc for rk3399
In-Reply-To: <5607915.FAWxOoA1QB@phil>
References: <1463092552-60696-1-git-send-email-briannorris@chromium.org>
 <5607915.FAWxOoA1QB@phil>
Message-ID: <20160513215724.GB109473@google.com>

On Fri, May 13, 2016 at 11:47:57PM +0200, Heiko Stuebner wrote:
> Am Donnerstag, 12. Mai 2016, 15:35:51 schrieb Brian Norris:
> > Add description for the SDHCI v5.1 eMMC controller on rk3399. Fix it to
> > 200 MHz, to support all supported timing modes.
> > 
> > Note that 'rockchip,rk3399-sdhci-5.1' is not documented; we presumably
> > have a compliant Arasan controller, but let's have a rockchip property
> > as the canonical backup/precautionary measure. Per Heiko's previous
> > suggestion, let's not clutter the arasan doc with it.
> > 
> > Signed-off-by: Brian Norris <briannorris at chromium.org>
> 
> At least one split is necessary.
> So please at least split out the simple-mfd addition into a separate patch

Will do.

BTW, should this be noted in
Documentation/devicetree/bindings/soc/rockchip/grf.txt now?

> (I should've seen that in v1 already, but sadly didn't)

No problem.

> I'm undecided if the emmc-phy addition also should get its own patch, but I 
> guess it can stay together with the emmc controller.

I think it makes sense for them to stay together. What's a phy without a
controller to use it? :)

Brian


From dianders at chromium.org  Fri May 13 15:01:56 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 13 May 2016 15:01:56 -0700
Subject: [PATCH 1/4] phy: rockchip-emmc: give DLL some extra time to be
 ready
In-Reply-To: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
Message-ID: <CAD=FV=WxWz4wyFPJ=gt7bzQb-cvkASB2aRm+e-2wPrUQ6ZaSEw@mail.gmail.com>

Hi,

On Thu, May 12, 2016 at 3:43 PM, Brian Norris <briannorris at chromium.org> wrote:
> From: Shawn Lin <shawn.lin at rock-chips.com>
>
> According to the databook, 10.2us is the max time for dll to be ready to
> work. However in testing, some chips need 20us for dll to be ready. This
> patch adds some extra margin for dllrdy to be ready, fixing our
> -ETIMEDOUT issues.
>
> Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
>  drivers/phy/phy-rockchip-emmc.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/phy-rockchip-emmc.c
> index 6ebcf3e41c46..48cbe691a889 100644
> --- a/drivers/phy/phy-rockchip-emmc.c
> +++ b/drivers/phy/phy-rockchip-emmc.c
> @@ -119,10 +119,11 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy,
>                                    PHYCTRL_ENDLL_MASK,
>                                    PHYCTRL_ENDLL_SHIFT));
>         /*
> -        * After enable analog DLL circuits, we need extra 10.2us
> -        * for dll to be ready for work.
> +        * After enable analog DLL circuits, we need an extra 10.2us
> +        * for dll to be ready for work. But according to testing, we
> +        * find some chips need more than 25us.
>          */
> -       udelay(11);
> +       udelay(30);
>         regmap_read(rk_phy->reg_base,
>                     rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
>                     &dllrdy);

Seems sane.  This is a "random delay" but you've documented it well,
and an extra 19 microseconds won't be the end of the world.

If we truly trusted the "DLLRDY" bit we could actually do a loop here,
but it's probably not worth it...

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


From dianders at chromium.org  Fri May 13 15:04:53 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 13 May 2016 15:04:53 -0700
Subject: [PATCH v2 2/4] phy: rockchip-emmc: configure frequency range and
 drive impedance
In-Reply-To: <20160513210943.GB99074@google.com>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
 <1463092986-61777-2-git-send-email-briannorris@chromium.org>
 <20160513210943.GB99074@google.com>
Message-ID: <CAD=FV=VyzaPEQvY57AF65VGzv600uBZT9jQy4N=s4Z_YPzphxw@mail.gmail.com>

Hi,

On Fri, May 13, 2016 at 2:09 PM, Brian Norris <briannorris at chromium.org> wrote:
> From: Shawn Lin <shawn.lin at rock-chips.com>
>
> Signal integrity analysis has suggested we set these values. Do this in
> power_on(), so that they get reconfigured after suspend/resume.
>
> Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
> v2:
>  * Sent only patch 2/4 with version 2, to avoid spamming; will move on to v3
>    for all patches if I need to send another
>  * Drop 170 MHz comment; this was only applicable to a subtly different Arasan
>    PHY
>
>  drivers/phy/phy-rockchip-emmc.c | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)

As per my comments on v1, this is a sane starting point and seems like
a good idea to land.  Hopefully someone at Rockchip can pick things up
and continue making this more configurable.

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


From matt at codeblueprint.co.uk  Fri May 13 15:09:23 2016
From: matt at codeblueprint.co.uk (Matt Fleming)
Date: Fri, 13 May 2016 23:09:23 +0100
Subject: [PATCH v2] Xen: EFI: Parse DT parameters for Xen specific UEFI
In-Reply-To: <1463055594-14980-1-git-send-email-zhaoshenglong@huawei.com>
References: <1463055594-14980-1-git-send-email-zhaoshenglong@huawei.com>
Message-ID: <20160513220923.GA5178@codeblueprint.co.uk>

(Including more folks, quoting entire patch)

On Thu, 12 May, at 08:19:54PM, Shannon Zhao wrote:
> From: Shannon Zhao <shannon.zhao at linaro.org>
> 
> The EFI DT parameters for bare metal are located under /chosen node,
> while for Xen Dom0 they are located under /hyperviosr/uefi node. These
> parameters under /chosen and /hyperviosr/uefi are not expected to appear
> at the same time.
> Parse these EFI parameters and initialize EFI like the way for bare
> metal except the runtime services because the runtime services for Xen
> Dom0 are available through hypercalls and they are always enabled. So it
> sets the EFI_RUNTIME_SERVICES flag if it finds /hyperviosr/uefi node and
> bails out in arm_enable_runtime_services() when EFI_RUNTIME_SERVICES
> flag is set already.
> 
> CC: Matt Fleming <matt at codeblueprint.co.uk>
> Signed-off-by: Shannon Zhao <shannon.zhao at linaro.org>
> ---
> v2: rebase it on top of EFI and Xen next branch, add some comments to
> explain the codes. 
> ---
>  arch/arm/xen/enlighten.c           | 22 +++++++++++
>  drivers/firmware/efi/arm-runtime.c |  5 +++
>  drivers/firmware/efi/efi.c         | 81 ++++++++++++++++++++++++++++++--------
>  3 files changed, 92 insertions(+), 16 deletions(-)
 
This looks good to me. Thanks for all the work Shannon.

Stefan, OK, let's figure out how to deal with this.

What I've done is merge xen/linux-next into the 'efi/xen-arm' topic
branch and applied this patch here,

  https://git.kernel.org/cgit/linux/kernel/git/mfleming/efi.git/log/?h=efi/arm-xen

Yes, the merge includes some Xen patches that are not actually needed
for any of the EFI patches, but Linus has complained about picking
random commits of a tree to merge. At least this way this is all the
Xen linux-next material.

If you're OK with this, and assuming no one else has any preferred
methods, I'll send out a pull request to tip over the weekend.

> diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
> index 13e3e9f..d4f36eb 100644
> --- a/arch/arm/xen/enlighten.c
> +++ b/arch/arm/xen/enlighten.c
> @@ -15,7 +15,9 @@
>  #include <asm/paravirt.h>
>  #include <asm/xen/hypervisor.h>
>  #include <asm/xen/hypercall.h>
> +#include <asm/xen/xen-ops.h>
>  #include <asm/system_misc.h>
> +#include <asm/efi.h>
>  #include <linux/interrupt.h>
>  #include <linux/irqreturn.h>
>  #include <linux/module.h>
> @@ -261,6 +263,19 @@ static int __init fdt_find_hyper_node(unsigned long node, const char *uname,
>  	    !strncmp(hyper_node.prefix, s, strlen(hyper_node.prefix)))
>  		hyper_node.version = s + strlen(hyper_node.prefix);
>  
> +	/*
> +	 * Check if Xen supports EFI by checking whether there is the
> +	 * "/hypervisor/uefi" node in DT. If so, runtime services are available
> +	 * through proxy functions (e.g. in case of Xen dom0 EFI implementation
> +	 * they call special hypercall which executes relevant EFI functions)
> +	 * and that is why they are always enabled.
> +	 */
> +	if (IS_ENABLED(CONFIG_XEN_EFI)) {
> +		if ((of_get_flat_dt_subnode_by_name(node, "uefi") > 0) &&
> +		    !efi_runtime_disabled())
> +			set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
> +	}
> +
>  	return 0;
>  }
>  
> @@ -352,6 +367,13 @@ static int __init xen_guest_init(void)
>  		return -ENODEV;
>  	}
>  
> +	/*
> +	 * The fdt parsing codes have set EFI_RUNTIME_SERVICES if Xen EFI
> +	 * parameters are found. Force enable runtime services.
> +	 */
> +	if (efi_enabled(EFI_RUNTIME_SERVICES))
> +		xen_efi_runtime_setup();
> +
>  	shared_info_page = (struct shared_info *)get_zeroed_page(GFP_KERNEL);
>  
>  	if (!shared_info_page) {
> diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
> index 17ccf0a..c394b81 100644
> --- a/drivers/firmware/efi/arm-runtime.c
> +++ b/drivers/firmware/efi/arm-runtime.c
> @@ -107,6 +107,11 @@ static int __init arm_enable_runtime_services(void)
>  		return 0;
>  	}
>  
> +	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
> +		pr_info("EFI runtime services access via paravirt.\n");
> +		return 0;
> +	}
> +
>  	pr_info("Remapping and enabling EFI services.\n");
>  
>  	mapsize = efi.memmap.map_end - efi.memmap.map;
> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index 05509f3..1c6f9dd 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -472,12 +472,14 @@ device_initcall(efi_load_efivars);
>  		FIELD_SIZEOF(struct efi_fdt_params, field) \
>  	}
>  
> -static __initdata struct {
> +struct params {
>  	const char name[32];
>  	const char propname[32];
>  	int offset;
>  	int size;
> -} dt_params[] = {
> +};
> +
> +static __initdata struct params fdt_params[] = {
>  	UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
>  	UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
>  	UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
> @@ -485,44 +487,91 @@ static __initdata struct {
>  	UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
>  };
>  
> +static __initdata struct params xen_fdt_params[] = {
> +	UEFI_PARAM("System Table", "xen,uefi-system-table", system_table),
> +	UEFI_PARAM("MemMap Address", "xen,uefi-mmap-start", mmap),
> +	UEFI_PARAM("MemMap Size", "xen,uefi-mmap-size", mmap_size),
> +	UEFI_PARAM("MemMap Desc. Size", "xen,uefi-mmap-desc-size", desc_size),
> +	UEFI_PARAM("MemMap Desc. Version", "xen,uefi-mmap-desc-ver", desc_ver)
> +};
> +
> +#define EFI_FDT_PARAMS_SIZE	ARRAY_SIZE(fdt_params)
> +
> +static __initdata struct {
> +	const char *uname;
> +	const char *subnode;
> +	struct params *params;
> +} dt_params[] = {
> +	{ "hypervisor", "uefi", xen_fdt_params },
> +	{ "chosen", NULL, fdt_params },
> +};
> +
>  struct param_info {
>  	int found;
>  	void *params;
> +	const char *missing;
>  };
>  
> -static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
> -				       int depth, void *data)
> +static int __init __find_uefi_params(unsigned long node,
> +				     struct param_info *info,
> +				     struct params *params)
>  {
> -	struct param_info *info = data;
>  	const void *prop;
>  	void *dest;
>  	u64 val;
>  	int i, len;
>  
> -	if (depth != 1 || strcmp(uname, "chosen") != 0)
> -		return 0;
> -
> -	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
> -		prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
> -		if (!prop)
> +	for (i = 0; i < EFI_FDT_PARAMS_SIZE; i++) {
> +		prop = of_get_flat_dt_prop(node, params[i].propname, &len);
> +		if (!prop) {
> +			info->missing = params[i].name;
>  			return 0;
> -		dest = info->params + dt_params[i].offset;
> +		}
> +
> +		dest = info->params + params[i].offset;
>  		info->found++;
>  
>  		val = of_read_number(prop, len / sizeof(u32));
>  
> -		if (dt_params[i].size == sizeof(u32))
> +		if (params[i].size == sizeof(u32))
>  			*(u32 *)dest = val;
>  		else
>  			*(u64 *)dest = val;
>  
>  		if (efi_enabled(EFI_DBG))
> -			pr_info("  %s: 0x%0*llx\n", dt_params[i].name,
> -				dt_params[i].size * 2, val);
> +			pr_info("  %s: 0x%0*llx\n", params[i].name,
> +				params[i].size * 2, val);
>  	}
> +
>  	return 1;
>  }
>  
> +static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
> +				       int depth, void *data)
> +{
> +	struct param_info *info = data;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
> +		const char *subnode = dt_params[i].subnode;
> +
> +		if (depth != 1 || strcmp(uname, dt_params[i].uname) != 0) {
> +			info->missing = dt_params[i].params[0].name;
> +			continue;
> +		}
> +
> +		if (subnode) {
> +			node = of_get_flat_dt_subnode_by_name(node, subnode);
> +			if (node < 0)
> +				return 0;
> +		}
> +
> +		return __find_uefi_params(node, info, dt_params[i].params);
> +	}
> +
> +	return 0;
> +}
> +
>  int __init efi_get_fdt_params(struct efi_fdt_params *params)
>  {
>  	struct param_info info;
> @@ -538,7 +587,7 @@ int __init efi_get_fdt_params(struct efi_fdt_params *params)
>  		pr_info("UEFI not found.\n");
>  	else if (!ret)
>  		pr_err("Can't find '%s' in device tree!\n",
> -		       dt_params[info.found].name);
> +		       info.missing);
>  
>  	return ret;
>  }
> -- 
> 2.0.4
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-efi" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From briannorris at chromium.org  Fri May 13 15:12:02 2016
From: briannorris at chromium.org (Brian Norris)
Date: Fri, 13 May 2016 15:12:02 -0700
Subject: [PATCH v4 1/3] ARM64: dts: rockchip: make rk3399's grf a "simple-mfd"
Message-ID: <1463177524-113856-1-git-send-email-briannorris@chromium.org>

Per the examples in
Documentation/devicetree/bindings/phy/rockchip-emmc-phy.txt, we need the
grf node to be a simple-mfd in order to properly enumerate child devices
like our eMMC PHY.

Signed-off-by: Brian Norris <briannorris at chromium.org>
---
v4:

 * New, split out of patch 2, per Heiko's recommendation

 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 46f325a143b0..e1c3667a9bea 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -481,8 +481,11 @@
 	};
 
 	grf: syscon at ff770000 {
-		compatible = "rockchip,rk3399-grf", "syscon";
+		compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
 		reg = <0x0 0xff770000 0x0 0x10000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
 	};
 
 	watchdog at ff840000 {
-- 
2.8.0.rc3.226.g39d4020



From briannorris at chromium.org  Fri May 13 15:12:04 2016
From: briannorris at chromium.org (Brian Norris)
Date: Fri, 13 May 2016 15:12:04 -0700
Subject: [PATCH v4 3/3] ARM64: dts: rockchip: enable eMMC for rk3399 EVB
In-Reply-To: <1463177524-113856-1-git-send-email-briannorris@chromium.org>
References: <1463177524-113856-1-git-send-email-briannorris@chromium.org>
Message-ID: <1463177524-113856-3-git-send-email-briannorris@chromium.org>

Rockchip's rk3399 evaluation board has eMMC. Let's enable the
newly-added nodes.

Signed-off-by: Brian Norris <briannorris at chromium.org>
---
v4:

 * alphabetize &node references

v3:

 * no change

v2:

 * better commit description

 arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
index 1a3eb1482050..d33aa06d46f5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
@@ -77,6 +77,10 @@
 	};
 };
 
+&emmc_phy {
+	status = "okay";
+};
+
 &pwm0 {
 	status = "okay";
 };
@@ -89,6 +93,14 @@
 	status = "okay";
 };
 
+&sdhci {
+	bus-width = <8>;
+	mmc-hs400-1_8v;
+	mmc-hs400-enhanced-strobe;
+	non-removable;
+	status = "okay";
+};
+
 &uart2 {
 	status = "okay";
 };
-- 
2.8.0.rc3.226.g39d4020



From briannorris at chromium.org  Fri May 13 15:12:03 2016
From: briannorris at chromium.org (Brian Norris)
Date: Fri, 13 May 2016 15:12:03 -0700
Subject: [PATCH v4 2/3] ARM64: dts: rockchip: add sdhci/emmc for rk3399
In-Reply-To: <1463177524-113856-1-git-send-email-briannorris@chromium.org>
References: <1463177524-113856-1-git-send-email-briannorris@chromium.org>
Message-ID: <1463177524-113856-2-git-send-email-briannorris@chromium.org>

Add description for the SDHCI v5.1 eMMC controller on rk3399. Fix it to
200 MHz, to support all supported timing modes.

Note that 'rockchip,rk3399-sdhci-5.1' is not documented; we presumably
have a compliant Arasan controller, but let's have a rockchip property
as the canonical backup/precautionary measure. Per Heiko's previous
suggestion, let's not clutter the arasan doc with it.

Signed-off-by: Brian Norris <briannorris at chromium.org>
---
v4:

 * split "simple-mfd" out into patch 1

v3:

 * correct emmc_phy reg length to 0x24

v2:

 * improved commit message
 * assign eMMC clock to 200 MHz

 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index e1c3667a9bea..99078f5ebeb9 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -215,6 +215,19 @@
 		status = "disabled";
 	};
 
+	sdhci: sdhci at fe330000 {
+		compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
+		reg = <0x0 0xfe330000 0x0 0x10000>;
+		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;
+		clock-names = "clk_xin", "clk_ahb";
+		assigned-clocks = <&cru SCLK_EMMC>;
+		assigned-clock-rates = <200000000>;
+		phys = <&emmc_phy>;
+		phy-names = "phy_arasan";
+		status = "disabled";
+	};
+
 	usb_host0_ehci: usb at fe380000 {
 		compatible = "generic-ehci";
 		reg = <0x0 0xfe380000 0x0 0x20000>;
@@ -486,6 +499,13 @@
 
 		#address-cells = <1>;
 		#size-cells = <1>;
+
+		emmc_phy: phy at f780 {
+			compatible = "rockchip,rk3399-emmc-phy";
+			reg = <0xf780 0x24>;
+			#phy-cells = <0>;
+			status = "disabled";
+		};
 	};
 
 	watchdog at ff840000 {
-- 
2.8.0.rc3.226.g39d4020



From heiko at sntech.de  Fri May 13 15:14:40 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 14 May 2016 00:14:40 +0200
Subject: [PATCH v2 1/2] ARM64: dts: rockchip: add sdhci/emmc for rk3399
In-Reply-To: <20160513215724.GB109473@google.com>
References: <1463092552-60696-1-git-send-email-briannorris@chromium.org>
 <5607915.FAWxOoA1QB@phil> <20160513215724.GB109473@google.com>
Message-ID: <1647746.RHuiZHceXs@phil>

Am Freitag, 13. Mai 2016, 14:57:24 schrieb Brian Norris:
> On Fri, May 13, 2016 at 11:47:57PM +0200, Heiko Stuebner wrote:
> > Am Donnerstag, 12. Mai 2016, 15:35:51 schrieb Brian Norris:
> > > Add description for the SDHCI v5.1 eMMC controller on rk3399. Fix it
> > > to
> > > 200 MHz, to support all supported timing modes.
> > > 
> > > Note that 'rockchip,rk3399-sdhci-5.1' is not documented; we presumably
> > > have a compliant Arasan controller, but let's have a rockchip property
> > > as the canonical backup/precautionary measure. Per Heiko's previous
> > > suggestion, let's not clutter the arasan doc with it.
> > > 
> > > Signed-off-by: Brian Norris <briannorris at chromium.org>
> > 
> > At least one split is necessary.
> > So please at least split out the simple-mfd addition into a separate
> > patch
> Will do.
> 
> BTW, should this be noted in
> Documentation/devicetree/bindings/soc/rockchip/grf.txt now?

The simple-mfd is already documented in mfd/mfd.txt in a general way, so I 
don't think every instance needs to have that, especially as it mainly 
affects sub-nodes alone.




From mikecyr at linux.vnet.ibm.com  Fri May 13 15:15:41 2016
From: mikecyr at linux.vnet.ibm.com (Michael Cyr)
Date: Fri, 13 May 2016 17:15:41 -0500
Subject: [PATCH] Fix for hang of Ordered task in TCM
Message-ID: <1463177741-4385-1-git-send-email-mikecyr@linux.vnet.ibm.com>

If a command with a Simple task attribute is failed due to a Unit
Attention, then a subsequent command with an Ordered task attribute will
hang forever.  The reason for this is that the Unit Attention status is
checked for in target_setup_cmd_from_cdb, before the call to
target_execute_cmd, which calls target_handle_task_attr, which in turn
increments dev->simple_cmds.  However, transport_generic_request_failure
still calls transport_complete_task_attr, which will decrement
dev->simple_cmds.  In this case, simple_cmds is now -1.  So when a
command with the Ordered task attribute is sent, target_handle_task_attr
sees that dev->simple_cmds is not 0, so it decides it can't execute the
command until all the (nonexistent) Simple commands have completed.

The solution I've implemented is to move target_scsi3_ua_check, as well as
target_alua_state_check and target_check_reservation, into
target_execute_cmd, after the call to target_handle_task_attr.  I believe
this is actually the correct way this should be handled.  According to
SAM-4 r14, under section 5.14:

"h) if a command other than INQUIRY, REPORT LUNS, REQUEST SENSE, or NOTIFY
DATA TRANSFER DEVICE enters the enabled command state while a unit
attention condition exists for the SCSI initiator port associated with
the I_T nexus on which the command was received, the device server shall
terminate the command with a CHECK CONDITION status. The device server
shall provide sense data that reports a unit attention condition for the
SCSI initiator port that sent the command on the I_T nexus."

But according to section 8.5 and 8.6, a command which is not yet executed
because of the presence of other tasks in the task set (i.e., one for
which target_handle_task_attr returns true) would not enter the enabled
command state; it would be in the dormant command state.
target_execute_cmd would get called when a command entered the enabled
command state, and thus that is the appropriate place to check for Unit
Attenion.  Similarly, though not quite as explicit, section 5.3.3 tells
us that a Reservation Conflict status has a lower precedence than a Unit
Attention, and so this would also seem to be the appropriate place to
call target_check_reservation.  I'm less sure about
target_alua_state_check, since I'm not very familiar with ALUA.

Signed-off-by: Michael Cyr <mikecyr at linux.vnet.ibm.com>
---
 drivers/target/target_core_transport.c | 41 ++++++++++++++++++++--------------
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 6c089af..2ee5502 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1303,23 +1303,6 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
 
 	trace_target_sequencer_start(cmd);
 
-	/*
-	 * Check for an existing UNIT ATTENTION condition
-	 */
-	ret = target_scsi3_ua_check(cmd);
-	if (ret)
-		return ret;
-
-	ret = target_alua_state_check(cmd);
-	if (ret)
-		return ret;
-
-	ret = target_check_reservation(cmd);
-	if (ret) {
-		cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
-		return ret;
-	}
-
 	ret = dev->transport->parse_cdb(cmd);
 	if (ret == TCM_UNSUPPORTED_SCSI_OPCODE)
 		pr_warn_ratelimited("%s/%s: Unsupported SCSI Opcode 0x%02x, sending CHECK_CONDITION.\n",
@@ -1865,6 +1848,8 @@ static int __transport_check_aborted_status(struct se_cmd *, int);
 
 void target_execute_cmd(struct se_cmd *cmd)
 {
+	sense_reason_t ret;
+
 	/*
 	 * Determine if frontend context caller is requesting the stopping of
 	 * this command for frontend exceptions.
@@ -1899,6 +1884,28 @@ void target_execute_cmd(struct se_cmd *cmd)
 		return;
 	}
 
+	/*
+	 * Check for an existing UNIT ATTENTION condition
+	 */
+	ret = target_scsi3_ua_check(cmd);
+	if (ret) {
+		transport_generic_request_failure(cmd, ret);
+		return;
+	}
+
+	ret = target_alua_state_check(cmd);
+	if (ret) {
+		transport_generic_request_failure(cmd, ret);
+		return;
+	}
+
+	ret = target_check_reservation(cmd);
+	if (ret) {
+		cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
+		transport_generic_request_failure(cmd, ret);
+		return;
+	}
+
 	__target_execute_cmd(cmd);
 }
 EXPORT_SYMBOL(target_execute_cmd);
-- 
2.5.0



From bjorn.andersson at linaro.org  Fri May 13 15:19:09 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Fri, 13 May 2016 15:19:09 -0700
Subject: QRTR merge conflict resolution (was: Re: linux-next: build failure
 after merge of the net-next tree)
In-Reply-To: <2606282.lG9qK7uBW0@wuerfel>
References: <20160510112905.5bffcad8@canb.auug.org.au>
 <20160510183934.GJ1256@tuxbot> <2606282.lG9qK7uBW0@wuerfel>
Message-ID: <20160513221909.GC1256@tuxbot>

On Fri 13 May 14:01 PDT 2016, Arnd Bergmann wrote:

> On Tuesday 10 May 2016 11:39:34 Bjorn Andersson wrote:
[..]
> > I assume we could have the QRTR go through Andy and arm-soc, with
> > David's approval and this fix squashed in. But we're running rather late
> > in this cycle, perhaps we should just back the QRTR patches out and I
> > can respin and resend them after the merge window (for v4.8 instead)?
> 
> I'd suggest you do a merge of next-next with the qcom/soc-2 branch that
> we have in arm-soc and resolve the conflict in the merge, then send
> a pull request with the merge to davem.
> 

Hi David,

In case you missed this thread, linux-next highlighted an upcoming merge
conflict between the net-next and one of the branches included in the
arm-soc trees.

I have prepared the merge of net-next and the conflicting tag from the
Qualcomm SOC, please include this in your pull towards Linus to avoid
the merge conflict.

Regards,
Bjorn

The following changes since commit ed7cbbce544856b20e5811de373cf92e92499771:

  udp: Resolve NULL pointer dereference over flow-based vxlan device (2016-05-13 01:56:14 -0400)

are available in the git repository at:

  git://github.com/andersson/kernel tags/net-next-qcom-soc-4.7-2-merge

for you to fetch changes up to f79a917e69e1f5cd86e864b67f06147f1b0340f4:

  Merge tag 'qcom-soc-for-4.7-2' into net-next (2016-05-13 14:42:23 -0700)

----------------------------------------------------------------
Merge tag 'qcom-soc-for-4.7-2' into net-next

This merges the Qualcomm SOC tree with the net-next, solving the
merge conflict in the SMD API between the two.

----------------------------------------------------------------
Andy Gross (1):
      Merge tag 'qcom-soc-for-4.7' into soc-for-4.7-p2

Bjorn Andersson (9):
      soc: qcom: smem_state: Add stubs for disabled smem_state
      soc: qcom: smd: Introduce callback setter
      soc: qcom: smd: Split discovery and state change work
      soc: qcom: smd: Refactor channel open and close handling
      soc: qcom: smd: Support multiple channels per sdev
      soc: qcom: smd: Support opening additional channels
      soc: qcom: smem: Use write-combine remap for SMEM
      soc: qcom: smd: Make callback pass channel reference
      Merge tag 'qcom-soc-for-4.7-2' into net-next

Lina Iyer (1):
      drivers: qcom: spm: avoid module usage in non-modular SPM driver

Srinivas Kandagatla (2):
      MAINTAINERS: add qcom i2c and spi drivers to list
      MAINTAINERS: add qcom clocks to the maintainers list

 MAINTAINERS                         |   3 +
 drivers/soc/qcom/smd-rpm.c          |   9 +-
 drivers/soc/qcom/smd.c              | 247 +++++++++++++++++++++++++++---------
 drivers/soc/qcom/smem.c             |   3 +-
 drivers/soc/qcom/spm.c              |   8 +-
 drivers/soc/qcom/wcnss_ctrl.c       |   8 +-
 include/linux/soc/qcom/smd.h        |  33 ++++-
 include/linux/soc/qcom/smem_state.h |  35 +++++
 net/qrtr/smd.c                      |   9 +-
 9 files changed, 278 insertions(+), 77 deletions(-)

> Alternatively, in case Linus merges net-next before we get that fix
> in, I could send Stephen's fix to Linus along with the pull requests.
> 
> 	Arnd


From dianders at chromium.org  Fri May 13 15:25:30 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 13 May 2016 15:25:30 -0700
Subject: [PATCH 3/4] phy: rockchip-emmc: configure default output tap delay
In-Reply-To: <1463092986-61777-3-git-send-email-briannorris@chromium.org>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
 <1463092986-61777-3-git-send-email-briannorris@chromium.org>
Message-ID: <CAD=FV=WupNv+z86BgmR1n8bj+b6GKA5Ew7U9hgoAxV9dxF7gjQ@mail.gmail.com>

Hi,

On Thu, May 12, 2016 at 3:43 PM, Brian Norris <briannorris at chromium.org> wrote:
> The output tap delay controls helps maintain the hold requirements for
> eMMC. The exact value is dependent on the SoC and other factors, though
> it isn't really an exact science. But the default of 0 is not very good,
> as it doesn't give the eMMC much hold time, so let's bump up to 4
> (approx 90 degree phase?). If we need to configure this any further
> (e.g., based on board or speed factors), we may need to consider a
> device tree representation.

As I understand it, this solves much the same problem as my patch in
<https://patchwork.kernel.org/patch/9085581/>, but for the eMMC port
on rk3399 (which doesn't use dw_mmc).  As argued in that patch and
also in the discussion from
<https://patchwork.kernel.org/patch/9030621/>, if we eventually end up
needing to put something in the device tree we need to be really
careful.  Specifically to get the exact right value here I think you
need to consider the input clock, speed mode, and any SoC-specific
delays differences between the clock and the data lines.  That would
imply that, if anything, the device tree data would only contain
information about the SoC-specific delay differences and all other
work to set this value would involve coordination between the PHY and
the SDHCI controller.


However, as also discussed previously, we don't appear to need to be
very exact about the value here.  It seems like setting this to 4 (~90
degrees?) is a much better starting point than leaving it at the
default of 0.


...so I'd be all for landing this patch.  Perhaps Shawn can chime in
and confirm that our understanding is correct and possibly we can
update the commit message.  Then presumably someone at Rockchip can
keep working to find a better way to set this long term.

Sound good?


-Doug


From dianders at chromium.org  Fri May 13 15:26:37 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 13 May 2016 15:26:37 -0700
Subject: [PATCH 4/4] phy: rockchip-emmc: reindent the register definitions
In-Reply-To: <1463092986-61777-4-git-send-email-briannorris@chromium.org>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
 <1463092986-61777-4-git-send-email-briannorris@chromium.org>
Message-ID: <CAD=FV=XkJTrUD-+KBCoZkzyN9_XRH+uE=AjEiVvaNf5iad=jow@mail.gmail.com>

Hi,

On Thu, May 12, 2016 at 3:43 PM, Brian Norris <briannorris at chromium.org> wrote:
> Some of the spacing was wrong (spaces instead of tabs), and due to
> longer entries added later, the columns weren't aligned. Let's get
> everything consistent.
>
> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
>  drivers/phy/phy-rockchip-emmc.c | 76 ++++++++++++++++++++---------------------
>  1 file changed, 38 insertions(+), 38 deletions(-)

Sure, why not?

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


From andy.gross at linaro.org  Fri May 13 15:47:17 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Fri, 13 May 2016 17:47:17 -0500
Subject: QRTR merge conflict resolution (was: Re: linux-next: build
 failure after merge of the net-next tree)
In-Reply-To: <20160513221909.GC1256@tuxbot>
References: <20160510112905.5bffcad8@canb.auug.org.au>
 <20160510183934.GJ1256@tuxbot> <2606282.lG9qK7uBW0@wuerfel>
 <20160513221909.GC1256@tuxbot>
Message-ID: <CAPBZ5Qfa+b1LLgqpxfKGysY5jXVrzmBzhga=ZYtpdDAKC9hnTQ@mail.gmail.com>

On 13 May 2016 at 17:19, Bjorn Andersson <bjorn.andersson at linaro.org> wrote:
> On Fri 13 May 14:01 PDT 2016, Arnd Bergmann wrote:
>
>> On Tuesday 10 May 2016 11:39:34 Bjorn Andersson wrote:
> [..]
>> > I assume we could have the QRTR go through Andy and arm-soc, with
>> > David's approval and this fix squashed in. But we're running rather late
>> > in this cycle, perhaps we should just back the QRTR patches out and I
>> > can respin and resend them after the merge window (for v4.8 instead)?
>>
>> I'd suggest you do a merge of next-next with the qcom/soc-2 branch that
>> we have in arm-soc and resolve the conflict in the merge, then send
>> a pull request with the merge to davem.
>>
>
> Hi David,
>
> In case you missed this thread, linux-next highlighted an upcoming merge
> conflict between the net-next and one of the branches included in the
> arm-soc trees.
>
> I have prepared the merge of net-next and the conflicting tag from the
> Qualcomm SOC, please include this in your pull towards Linus to avoid
> the merge conflict.
>
> Regards,
> Bjorn
>
> The following changes since commit ed7cbbce544856b20e5811de373cf92e92499771:
>
>   udp: Resolve NULL pointer dereference over flow-based vxlan device (2016-05-13 01:56:14 -0400)


OK. The contents look good to me.

Acked-by: Andy Gross <andy.gross at linaro.org>


From dianders at chromium.org  Fri May 13 15:53:14 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 13 May 2016 15:53:14 -0700
Subject: [PATCH v4 1/3] ARM64: dts: rockchip: make rk3399's grf a
 "simple-mfd"
In-Reply-To: <1463177524-113856-1-git-send-email-briannorris@chromium.org>
References: <1463177524-113856-1-git-send-email-briannorris@chromium.org>
Message-ID: <CAD=FV=UGbNsneP_Vm_YYOrjWYn=zVKB5pZYvOOJczKAuRztCkw@mail.gmail.com>

Hi,

On Fri, May 13, 2016 at 3:12 PM, Brian Norris <briannorris at chromium.org> wrote:
> Per the examples in
> Documentation/devicetree/bindings/phy/rockchip-emmc-phy.txt, we need the
> grf node to be a simple-mfd in order to properly enumerate child devices
> like our eMMC PHY.
>
> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
> v4:
>
>  * New, split out of patch 2, per Heiko's recommendation
>
>  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)

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


From dianders at chromium.org  Fri May 13 15:54:35 2016
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 13 May 2016 15:54:35 -0700
Subject: [PATCH v4 3/3] ARM64: dts: rockchip: enable eMMC for rk3399 EVB
In-Reply-To: <1463177524-113856-3-git-send-email-briannorris@chromium.org>
References: <1463177524-113856-1-git-send-email-briannorris@chromium.org>
 <1463177524-113856-3-git-send-email-briannorris@chromium.org>
Message-ID: <CAD=FV=VffvTEVyCpVn20rRsGRYKPVy_6qjTBoiOvMX4EjeWFrQ@mail.gmail.com>

Hi,

On Fri, May 13, 2016 at 3:12 PM, Brian Norris <briannorris at chromium.org> wrote:
> Rockchip's rk3399 evaluation board has eMMC. Let's enable the
> newly-added nodes.
>
> Signed-off-by: Brian Norris <briannorris at chromium.org>
> ---
> v4:
>
>  * alphabetize &node references
>
> v3:
>
>  * no change
>
> v2:
>
>  * better commit description
>
>  arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 12 ++++++++++++
>  1 file changed, 12 insertions(+)

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


From bjorn.andersson at linaro.org  Fri May 13 16:32:01 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Fri, 13 May 2016 16:32:01 -0700
Subject: [Patch v5 1/8] dt/bindings: firmware: Add Qualcomm SCM binding
In-Reply-To: <1463111221-6963-2-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
 <1463111221-6963-2-git-send-email-andy.gross@linaro.org>
Message-ID: <20160513233201.GE1256@tuxbot>

On Thu 12 May 20:46 PDT 2016, Andy Gross wrote:

> This patch adds the device tree support for the Qualcomm SCM firmware.
> 
> Signed-off-by: Andy Gross <andy.gross at linaro.org>

Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>

Regards,
Bjorn


From bjorn.andersson at linaro.org  Fri May 13 16:33:06 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Fri, 13 May 2016 16:33:06 -0700
Subject: [Patch v5 2/8] firmware: qcom: scm: Convert SCM to platform driver
In-Reply-To: <1463111221-6963-3-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
 <1463111221-6963-3-git-send-email-andy.gross@linaro.org>
Message-ID: <20160513233306.GF1256@tuxbot>

On Thu 12 May 20:46 PDT 2016, Andy Gross wrote:

> This patch converts the Qualcomm SCM firmware driver into a platform
> driver.
> 
> Signed-off-by: Andy Gross <andy.gross at linaro.org>

Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>

Regards,
Bjorn


From bjorn.andersson at linaro.org  Fri May 13 16:37:14 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Fri, 13 May 2016 16:37:14 -0700
Subject: [Patch v5 3/8] firmware: qcom: scm: Use atomic SCM for cold boot
In-Reply-To: <1463111221-6963-4-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
 <1463111221-6963-4-git-send-email-andy.gross@linaro.org>
Message-ID: <20160513233714.GG1256@tuxbot>

On Thu 12 May 20:46 PDT 2016, Andy Gross wrote:

> This patch changes the cold_set_boot_addr function to use atomic SCM
> calls.  cold_set_boot_addr required adding qcom_scm_call_atomic2 to
> support the two arguments going to the smc call.  Using atomic removes
> the need for memory allocation and instead places all arguments in
> registers.
> 
> Signed-off-by: Andy Gross <andy.gross at linaro.org>

Acked-by: Bjorn Andersson <bjorn.andersson at linaro.org>

Regards,
Bjorn


From bjorn.andersson at linaro.org  Fri May 13 16:48:52 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Fri, 13 May 2016 16:48:52 -0700
Subject: [Patch v5 5/8] firmware: qcom: scm: Convert to streaming DMA APIS
In-Reply-To: <1463111221-6963-6-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
 <1463111221-6963-6-git-send-email-andy.gross@linaro.org>
Message-ID: <20160513234852.GH1256@tuxbot>

On Thu 12 May 20:46 PDT 2016, Andy Gross wrote:

> This patch converts the Qualcomm SCM driver to use the streaming DMA APIs
> for communication buffers.
> 
> Signed-off-by: Andy Gross <andy.gross at linaro.org>
> ---
>  drivers/firmware/qcom_scm-32.c | 189 +++++++++++------------------------------
>  drivers/firmware/qcom_scm.c    |   6 +-
>  drivers/firmware/qcom_scm.h    |  10 ++-
>  3 files changed, 59 insertions(+), 146 deletions(-)
> 
> diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
[..]
> +static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
> +			 const void *cmd_buf, size_t cmd_len, void *resp_buf,
> +			 size_t resp_len)
>  {
>  	int ret;
>  	struct qcom_scm_command *cmd;
>  	struct qcom_scm_response *rsp;
> -	unsigned long start, end;
> +	size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len;
> +	dma_addr_t cmd_phys;
>  
> -	cmd = alloc_qcom_scm_command(cmd_len, resp_len);
> +	cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
>  	if (!cmd)
>  		return -ENOMEM;
>  
> +	cmd->len = cpu_to_le32(alloc_len);
> +	cmd->buf_offset = cpu_to_le32(sizeof(*cmd));
> +	cmd->resp_hdr_offset = cpu_to_le32(sizeof(*cmd) + cmd_len);
> +
>  	cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
>  	if (cmd_buf)
> -		memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len);
> +		memcpy(cmd->buf, cmd_buf, cmd_len);
> +
> +	rsp = (void *)cmd->buf + le32_to_cpu(cmd->resp_hdr_offset);

I believe resp_hdr_offset counts from the beginning of the buffer and
that this therefor is supposed to be:

	rsp = (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);

With that corrected, feel free to add:

Reviewed-by: Bjorn Andersson <bjorn.andersson at linaro.org>

Regards,
Bjorn


From bjorn.andersson at linaro.org  Fri May 13 16:50:57 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Fri, 13 May 2016 16:50:57 -0700
Subject: [Patch v5 6/8] firmware: qcom: scm: Add support for ARM64 SoCs
In-Reply-To: <1463111221-6963-7-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
 <1463111221-6963-7-git-send-email-andy.gross@linaro.org>
Message-ID: <20160513235057.GI1256@tuxbot>

On Thu 12 May 20:46 PDT 2016, Andy Gross wrote:

> From: Kumar Gala <galak at codeaurora.org>
> 
> Add an implementation of the SCM interface that works on ARM64 SoCs.  This
> is used by things like determine if we have HDCP support or not on the
> system.
> 
> Signed-off-by: Kumar Gala <galak at codeaurora.org>
> Signed-off-by: Andy Gross <andy.gross at linaro.org>

Reviewed-by: Bjorn Andersson <bjorn.andersson at linaro.org>

Regards,
Bjorn


From isubramanian at apm.com  Fri May 13 16:52:56 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 13 May 2016 16:52:56 -0700
Subject: [PATCH v2 0/5] drivers: net: xgene: Bug fixes
Message-ID: <1463183581-30475-1-git-send-email-isubramanian@apm.com>

This patch set addresses the following bug fixes that were found during testing.

  1. IPv4 forward test crash
    - drivers: net: xgene: fix IPv4 forward crash

  2. Sharing of irqs
    - drivers: net: xgene: fix sharing of irqs

  3. Ununiform latency across queues
    - drivers: net: xgene: fix ununiform latency across queues

  4. Fix statistics counters race condition
    - drivers: net: xgene: fix statistics counters race condition

  5. Correcting register offset and field lengths
    - drivers: net: xgene: fix register offset

v2: Address review comments from v1
- Defer TSO fix, and reposting all other patches from v1

v1:
- Initial version

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
---

Iyappan Subramanian (5):
  drivers: net: xgene: fix IPv4 forward crash
  drivers: net: xgene: fix sharing of irqs
  drivers: net: xgene: fix ununiform latency across queues
  drivers: net: xgene: fix statistics counters race condition
  drivers: net: xgene: fix register offset

 drivers/net/ethernet/apm/xgene/xgene_enet_cle.c   | 11 ++--
 drivers/net/ethernet/apm/xgene/xgene_enet_cle.h   |  2 +
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    | 19 +++---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    |  8 ++-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 75 +++++++++++++++++------
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  | 18 ++++--
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h |  2 +-
 7 files changed, 94 insertions(+), 41 deletions(-)

-- 
1.9.1



From isubramanian at apm.com  Fri May 13 16:52:57 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 13 May 2016 16:52:57 -0700
Subject: [PATCH v2 1/5] drivers: net: xgene: fix IPv4 forward crash
In-Reply-To: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
References: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
Message-ID: <1463183581-30475-2-git-send-email-isubramanian@apm.com>

This patch fixes the crash observed during IPv4 forward test by
setting the drop field in the dbptr.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_cle.c | 11 ++++++-----
 drivers/net/ethernet/apm/xgene/xgene_enet_cle.h |  2 ++
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
index 6479288..472c0fb 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
@@ -43,6 +43,7 @@ static void xgene_cle_idt_to_hw(u32 dstqid, u32 fpsel,
 static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata,
 				  struct xgene_cle_dbptr *dbptr, u32 *buf)
 {
+	buf[0] = SET_VAL(CLE_DROP, dbptr->drop);
 	buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) |
 		 SET_VAL(CLE_DSTQIDL, dbptr->dstqid);
 
@@ -412,7 +413,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 			.branch = {
 				{
 					/* IPV4 */
-					.valid = 0,
+					.valid = 1,
 					.next_packet_pointer = 22,
 					.jump_bw = JMP_FW,
 					.jump_rel = JMP_ABS,
@@ -420,7 +421,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 					.next_node = PKT_PROT_NODE,
 					.next_branch = 0,
 					.data = 0x8,
-					.mask = 0xffff
+					.mask = 0x0
 				},
 				{
 					.valid = 0,
@@ -456,7 +457,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 					.next_node = RSS_IPV4_TCP_NODE,
 					.next_branch = 0,
 					.data = 0x0600,
-					.mask = 0xffff
+					.mask = 0x00ff
 				},
 				{
 					/* UDP */
@@ -468,7 +469,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 					.next_node = RSS_IPV4_UDP_NODE,
 					.next_branch = 0,
 					.data = 0x1100,
-					.mask = 0xffff
+					.mask = 0x00ff
 				},
 				{
 					.valid = 0,
@@ -642,7 +643,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 				{
 					/* TCP DST Port */
 					.valid = 0,
-					.next_packet_pointer = 256,
+					.next_packet_pointer = 258,
 					.jump_bw = JMP_FW,
 					.jump_rel = JMP_ABS,
 					.operation = EQT,
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
index 13e829a..33c5f6b 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
@@ -83,6 +83,8 @@
 #define CLE_TYPE_POS		0
 #define CLE_TYPE_LEN		2
 
+#define CLE_DROP_POS		28
+#define CLE_DROP_LEN		1
 #define CLE_DSTQIDL_POS		25
 #define CLE_DSTQIDL_LEN		7
 #define CLE_DSTQIDH_POS		0
-- 
1.9.1



From isubramanian at apm.com  Fri May 13 16:52:59 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 13 May 2016 16:52:59 -0700
Subject: [PATCH v2 3/5] drivers: net: xgene: fix ununiform latency across
 queues
In-Reply-To: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
References: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
Message-ID: <1463183581-30475-4-git-send-email-isubramanian@apm.com>

This patch addresses ununiform latency across queues by adding
more queues to match with, upto number of CPU cores.

Also, number of interrupts are increased and the channel numbers
are reordered.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 30 ++++++++++++++++++------
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h |  8 +++----
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index ed90664..e75d1a9 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1247,6 +1247,13 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata)
 	for (i = 0; i < max_irqs; i++) {
 		ret = platform_get_irq(pdev, i);
 		if (ret <= 0) {
+			if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
+				max_irqs = i;
+				pdata->rxq_cnt = max_irqs / 2;
+				pdata->txq_cnt = max_irqs / 2;
+				pdata->cq_cnt = max_irqs / 2;
+				break;
+			}
 			dev_err(dev, "Unable to get ENET IRQ\n");
 			ret = ret ? : -ENXIO;
 			return ret;
@@ -1450,19 +1457,28 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
 		pdata->port_ops = &xgene_xgport_ops;
 		pdata->cle_ops = &xgene_cle3in_ops;
 		pdata->rm = RM0;
-		pdata->rxq_cnt = XGENE_NUM_RX_RING;
-		pdata->txq_cnt = XGENE_NUM_TX_RING;
-		pdata->cq_cnt = XGENE_NUM_TXC_RING;
+		if (!pdata->rxq_cnt) {
+			pdata->rxq_cnt = XGENE_NUM_RX_RING;
+			pdata->txq_cnt = XGENE_NUM_TX_RING;
+			pdata->cq_cnt = XGENE_NUM_TXC_RING;
+		}
 		break;
 	}
 
 	if (pdata->enet_id == XGENE_ENET1) {
 		switch (pdata->port_id) {
 		case 0:
-			pdata->cpu_bufnum = START_CPU_BUFNUM_0;
-			pdata->eth_bufnum = START_ETH_BUFNUM_0;
-			pdata->bp_bufnum = START_BP_BUFNUM_0;
-			pdata->ring_num = START_RING_NUM_0;
+			if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
+				pdata->cpu_bufnum = X2_START_CPU_BUFNUM_0;
+				pdata->eth_bufnum = X2_START_ETH_BUFNUM_0;
+				pdata->bp_bufnum = X2_START_BP_BUFNUM_0;
+				pdata->ring_num = START_RING_NUM_0;
+			} else {
+				pdata->cpu_bufnum = START_CPU_BUFNUM_0;
+				pdata->eth_bufnum = START_ETH_BUFNUM_0;
+				pdata->bp_bufnum = START_BP_BUFNUM_0;
+				pdata->ring_num = START_RING_NUM_0;
+			}
 			break;
 		case 1:
 			if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 0a2887b..cc40c30 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -49,10 +49,10 @@
 #define XGENE_ENET_MSS	1448
 #define XGENE_MIN_ENET_FRAME_SIZE	60
 
-#define XGENE_MAX_ENET_IRQ	8
-#define XGENE_NUM_RX_RING	4
-#define XGENE_NUM_TX_RING	4
-#define XGENE_NUM_TXC_RING	4
+#define XGENE_MAX_ENET_IRQ	16
+#define XGENE_NUM_RX_RING	8
+#define XGENE_NUM_TX_RING	8
+#define XGENE_NUM_TXC_RING	8
 
 #define START_CPU_BUFNUM_0	0
 #define START_ETH_BUFNUM_0	2
-- 
1.9.1



From isubramanian at apm.com  Fri May 13 16:52:58 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 13 May 2016 16:52:58 -0700
Subject: [PATCH v2 2/5] drivers: net: xgene: fix sharing of irqs
In-Reply-To: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
References: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
Message-ID: <1463183581-30475-3-git-send-email-isubramanian@apm.com>

Since hardware doesn't allow sharing of interrupts,
this patch fixes the same by removing IRQF_SHARED flag.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index aa87049..ed90664 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -630,7 +630,7 @@ static int xgene_enet_register_irq(struct net_device *ndev)
 		ring = pdata->rx_ring[i];
 		irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
 		ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
-				       IRQF_SHARED, ring->irq_name, ring);
+				       0, ring->irq_name, ring);
 		if (ret) {
 			netdev_err(ndev, "Failed to request irq %s\n",
 				   ring->irq_name);
@@ -641,7 +641,7 @@ static int xgene_enet_register_irq(struct net_device *ndev)
 		ring = pdata->tx_ring[i]->cp_ring;
 		irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
 		ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
-				       IRQF_SHARED, ring->irq_name, ring);
+				       0, ring->irq_name, ring);
 		if (ret) {
 			netdev_err(ndev, "Failed to request irq %s\n",
 				   ring->irq_name);
-- 
1.9.1



From isubramanian at apm.com  Fri May 13 16:53:00 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 13 May 2016 16:53:00 -0700
Subject: [PATCH v2 4/5] drivers: net: xgene: fix statistics counters race
 condition
In-Reply-To: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
References: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
Message-ID: <1463183581-30475-5-git-send-email-isubramanian@apm.com>

This patch fixes the race condition on updating the statistics
counters by moving the counters to the ring structure.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c   | 19 ++++++-----
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h   |  2 ++
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 41 +++++++++++++++++-------
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 10 ++++++
 4 files changed, 53 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 457f745..2f5638f 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -219,27 +219,30 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
 			    struct xgene_enet_pdata *pdata,
 			    enum xgene_enet_err_code status)
 {
-	struct rtnl_link_stats64 *stats = &pdata->stats;
-
 	switch (status) {
 	case INGRESS_CRC:
-		stats->rx_crc_errors++;
+		ring->rx_crc_errors++;
+		ring->rx_dropped++;
 		break;
 	case INGRESS_CHECKSUM:
 	case INGRESS_CHECKSUM_COMPUTE:
-		stats->rx_errors++;
+		ring->rx_errors++;
+		ring->rx_dropped++;
 		break;
 	case INGRESS_TRUNC_FRAME:
-		stats->rx_frame_errors++;
+		ring->rx_frame_errors++;
+		ring->rx_dropped++;
 		break;
 	case INGRESS_PKT_LEN:
-		stats->rx_length_errors++;
+		ring->rx_length_errors++;
+		ring->rx_dropped++;
 		break;
 	case INGRESS_PKT_UNDER:
-		stats->rx_frame_errors++;
+		ring->rx_frame_errors++;
+		ring->rx_dropped++;
 		break;
 	case INGRESS_FIFO_OVERRUN:
-		stats->rx_fifo_errors++;
+		ring->rx_fifo_errors++;
 		break;
 	default:
 		break;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index ba7da98..ecfeffe 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -201,6 +201,8 @@ enum xgene_enet_rm {
 #define USERINFO_LEN			32
 #define FPQNUM_POS			32
 #define FPQNUM_LEN			12
+#define ELERR_POS                       46
+#define ELERR_LEN                       2
 #define NV_POS				50
 #define NV_LEN				1
 #define LL_POS				51
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index e75d1a9..d208b17 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -443,8 +443,8 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
 
 	skb_tx_timestamp(skb);
 
-	pdata->stats.tx_packets++;
-	pdata->stats.tx_bytes += skb->len;
+	tx_ring->tx_packets++;
+	tx_ring->tx_bytes += skb->len;
 
 	pdata->ring_ops->wr_cmd(tx_ring, count);
 	return NETDEV_TX_OK;
@@ -483,12 +483,12 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
 	skb = buf_pool->rx_skb[skb_index];
 
 	/* checking for error */
-	status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
+	status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) ||
+		  GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
 	if (unlikely(status > 2)) {
 		dev_kfree_skb_any(skb);
 		xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
 				       status);
-		pdata->stats.rx_dropped++;
 		ret = -EIO;
 		goto out;
 	}
@@ -506,8 +506,8 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
 		xgene_enet_skip_csum(skb);
 	}
 
-	pdata->stats.rx_packets++;
-	pdata->stats.rx_bytes += datalen;
+	rx_ring->rx_packets++;
+	rx_ring->rx_bytes += datalen;
 	napi_gro_receive(&rx_ring->napi, skb);
 out:
 	if (--rx_ring->nbufpool == 0) {
@@ -1127,12 +1127,31 @@ static struct rtnl_link_stats64 *xgene_enet_get_stats64(
 {
 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
 	struct rtnl_link_stats64 *stats = &pdata->stats;
+	struct xgene_enet_desc_ring *ring;
+	int i;
+
+	memset(stats, 0, sizeof(struct rtnl_link_stats64));
+	for (i = 0; i < pdata->txq_cnt; i++) {
+		ring = pdata->tx_ring[i];
+		if (ring) {
+			stats->tx_packets += ring->tx_packets;
+			stats->tx_bytes += ring->tx_bytes;
+		}
+	}
 
-	stats->rx_errors += stats->rx_length_errors +
-			    stats->rx_crc_errors +
-			    stats->rx_frame_errors +
-			    stats->rx_fifo_errors;
-	memcpy(storage, &pdata->stats, sizeof(struct rtnl_link_stats64));
+	for (i = 0; i < pdata->rxq_cnt; i++) {
+		ring = pdata->rx_ring[i];
+		if (ring) {
+			stats->rx_packets += ring->rx_packets;
+			stats->rx_bytes += ring->rx_bytes;
+			stats->rx_errors += ring->rx_length_errors +
+				ring->rx_crc_errors +
+				ring->rx_frame_errors +
+				ring->rx_fifo_errors;
+			stats->rx_dropped += ring->rx_dropped;
+		}
+	}
+	memcpy(storage, stats, sizeof(struct rtnl_link_stats64));
 
 	return storage;
 }
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index cc40c30..092fbec 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -121,6 +121,16 @@ struct xgene_enet_desc_ring {
 		struct xgene_enet_raw_desc16 *raw_desc16;
 	};
 	__le64 *exp_bufs;
+	u64 tx_packets;
+	u64 tx_bytes;
+	u64 rx_packets;
+	u64 rx_bytes;
+	u64 rx_dropped;
+	u64 rx_errors;
+	u64 rx_length_errors;
+	u64 rx_crc_errors;
+	u64 rx_frame_errors;
+	u64 rx_fifo_errors;
 };
 
 struct xgene_mac_ops {
-- 
1.9.1



From isubramanian at apm.com  Fri May 13 16:53:01 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 13 May 2016 16:53:01 -0700
Subject: [PATCH v2 5/5] drivers: net: xgene: fix register offset
In-Reply-To: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
References: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
Message-ID: <1463183581-30475-6-git-send-email-isubramanian@apm.com>

This patch fixes SG_RX_DV_GATE_REG_0_ADDR register offset
and ring state field lengths.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    | 6 +++---
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index ecfeffe..45220be 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -86,7 +86,7 @@ enum xgene_enet_rm {
 #define RINGADDRL_POS		5
 #define RINGADDRL_LEN		27
 #define RINGADDRH_POS		0
-#define RINGADDRH_LEN		6
+#define RINGADDRH_LEN		7
 #define RINGSIZE_POS		23
 #define RINGSIZE_LEN		3
 #define RINGTYPE_POS		19
@@ -94,9 +94,9 @@ enum xgene_enet_rm {
 #define RINGMODE_POS		20
 #define RINGMODE_LEN		3
 #define RECOMTIMEOUTL_POS	28
-#define RECOMTIMEOUTL_LEN	3
+#define RECOMTIMEOUTL_LEN	4
 #define RECOMTIMEOUTH_POS	0
-#define RECOMTIMEOUTH_LEN	2
+#define RECOMTIMEOUTH_LEN	3
 #define NUMMSGSINQ_POS		1
 #define NUMMSGSINQ_LEN		16
 #define ACCEPTLERR		BIT(19)
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
index 29a71b4..002df5a 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
@@ -33,7 +33,7 @@
 #define LINK_STATUS			BIT(2)
 #define LINK_UP				BIT(15)
 #define MPA_IDLE_WITH_QMI_EMPTY		BIT(12)
-#define SG_RX_DV_GATE_REG_0_ADDR	0x0dfc
+#define SG_RX_DV_GATE_REG_0_ADDR	0x05fc
 
 extern const struct xgene_mac_ops xgene_sgmac_ops;
 extern const struct xgene_port_ops xgene_sgport_ops;
-- 
1.9.1



From davem at davemloft.net  Fri May 13 18:12:26 2016
From: davem at davemloft.net (David Miller)
Date: Fri, 13 May 2016 21:12:26 -0400 (EDT)
Subject: [PATCH v2 0/5] drivers: net: xgene: Bug fixes
In-Reply-To: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
References: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
Message-ID: <20160513.211226.1164377917890147208.davem@davemloft.net>

From: Iyappan Subramanian <isubramanian at apm.com>
Date: Fri, 13 May 2016 16:52:56 -0700

> This patch set addresses the following bug fixes that were found during testing.
> 
>   1. IPv4 forward test crash
>     - drivers: net: xgene: fix IPv4 forward crash
> 
>   2. Sharing of irqs
>     - drivers: net: xgene: fix sharing of irqs
> 
>   3. Ununiform latency across queues
>     - drivers: net: xgene: fix ununiform latency across queues
> 
>   4. Fix statistics counters race condition
>     - drivers: net: xgene: fix statistics counters race condition
> 
>   5. Correcting register offset and field lengths
>     - drivers: net: xgene: fix register offset
> 
> v2: Address review comments from v1
> - Defer TSO fix, and reposting all other patches from v1
> 
> v1:
> - Initial version
> 
> Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>

Series applied, thanks.


From eric.dumazet at gmail.com  Fri May 13 18:41:44 2016
From: eric.dumazet at gmail.com (Eric Dumazet)
Date: Fri, 13 May 2016 18:41:44 -0700
Subject: [PATCH v2 4/5] drivers: net: xgene: fix statistics counters
 race condition
In-Reply-To: <1463183581-30475-5-git-send-email-isubramanian@apm.com>
References: <1463183581-30475-1-git-send-email-isubramanian@apm.com>
 <1463183581-30475-5-git-send-email-isubramanian@apm.com>
Message-ID: <1463190104.18194.3.camel@edumazet-glaptop3.roam.corp.google.com>

On Fri, 2016-05-13 at 16:53 -0700, Iyappan Subramanian wrote:
> This patch fixes the race condition on updating the statistics
> counters by moving the counters to the ring structure.
> 

...

> @@ -1127,12 +1127,31 @@ static struct rtnl_link_stats64 *xgene_enet_get_stats64(
>  {
>  	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
>  	struct rtnl_link_stats64 *stats = &pdata->stats;
> +	struct xgene_enet_desc_ring *ring;
> +	int i;
> +
> +	memset(stats, 0, sizeof(struct rtnl_link_stats64));

The memset() should already be done in the caller.

> +	for (i = 0; i < pdata->txq_cnt; i++) {
> +		ring = pdata->tx_ring[i];
> +		if (ring) {
> +			stats->tx_packets += ring->tx_packets;
> +			stats->tx_bytes += ring->tx_bytes;
> +		}
> +	}
>  
> -	stats->rx_errors += stats->rx_length_errors +
> -			    stats->rx_crc_errors +
> -			    stats->rx_frame_errors +
> -			    stats->rx_fifo_errors;


Right, this piece was completely buggy.

Not a race, but rx_errors was growing every time stats were fetched on
this device.


stats->rx_errors =   sum(...)    was probably the intent.



> -	memcpy(storage, &pdata->stats, sizeof(struct rtnl_link_stats64));
> +	for (i = 0; i < pdata->rxq_cnt; i++) {
> +		ring = pdata->rx_ring[i];
> +		if (ring) {
> +			stats->rx_packets += ring->rx_packets;
> +			stats->rx_bytes += ring->rx_bytes;
> +			stats->rx_errors += ring->rx_length_errors +
> +				ring->rx_crc_errors +
> +				ring->rx_frame_errors +
> +				ring->rx_fifo_errors;
> +			stats->rx_dropped += ring->rx_dropped;
> +		}
> +	}
> +	memcpy(storage, stats, sizeof(struct rtnl_link_stats64));
>  
>  	return storage;
>  }
> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
> index cc40c30..092fbec 100644
> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
> @@ -121,6 +121,16 @@ struct xgene_enet_desc_ring {
>  		struct xgene_enet_raw_desc16 *raw_desc16;
>  	};
>  	__le64 *exp_bufs;
> +	u64 tx_packets;
> +	u64 tx_bytes;
> +	u64 rx_packets;
> +	u64 rx_bytes;
> +	u64 rx_dropped;
> +	u64 rx_errors;
> +	u64 rx_length_errors;
> +	u64 rx_crc_errors;
> +	u64 rx_frame_errors;
> +	u64 rx_fifo_errors;

Note that there is still a race on 32bit arches.

It seems this driver should really use "unsigned long" counters and
provide standard ndo_get_stats()





From zhengxing at rock-chips.com  Fri May 13 20:36:14 2016
From: zhengxing at rock-chips.com (Xing Zheng)
Date: Sat, 14 May 2016 11:36:14 +0800
Subject: [PATCH 2/2] clk: rockchip: fix incorrect parent for rk3399's
 {c,g}pll_aclk_perihp_src
In-Reply-To: <CAD=FV=XstYhqpStSGw5PObWvpsvd3Nwp_hfEE-56bpFoVUyu+g@mail.gmail.com>
References: <1463164937-91089-1-git-send-email-briannorris@chromium.org>
 <1463164937-91089-2-git-send-email-briannorris@chromium.org>
 <CAD=FV=XstYhqpStSGw5PObWvpsvd3Nwp_hfEE-56bpFoVUyu+g@mail.gmail.com>
Message-ID: <57369D2E.3030002@rock-chips.com>

Hi Doug,

On 2016?05?14? 04:10, Doug Anderson wrote:
> Hi,
>
> On Fri, May 13, 2016 at 11:42 AM, Brian Norris <briannorris at chromium.org> wrote:
>> From: Xing Zheng <zhengxing at rock-chips.com>
>>
>> There was a typo, swapping 'c' <--> 'g'.
>>
>> Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
>> Signed-off-by: Brian Norris <briannorris at chromium.org>
>> ---
>>   drivers/clk/rockchip/clk-rk3399.c | 4 ++--
>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
>> index 145756c4f3c8..9f86bfef70f7 100644
>> --- a/drivers/clk/rockchip/clk-rk3399.c
>> +++ b/drivers/clk/rockchip/clk-rk3399.c
>> @@ -832,9 +832,9 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
>>                          RK3399_CLKGATE_CON(13), 1, GFLAGS),
>>
>>          /* perihp */
>> -       GATE(0, "cpll_aclk_perihp_src", "gpll", CLK_IGNORE_UNUSED,
>> +       GATE(0, "cpll_aclk_perihp_src", "cpll", CLK_IGNORE_UNUSED,
>>                          RK3399_CLKGATE_CON(5), 0, GFLAGS),
>> -       GATE(0, "gpll_aclk_perihp_src", "cpll", CLK_IGNORE_UNUSED,
>> +       GATE(0, "gpll_aclk_perihp_src", "gpll", CLK_IGNORE_UNUSED,
>>                          RK3399_CLKGATE_CON(5), 1, GFLAGS),
>>          COMPOSITE(ACLK_PERIHP, "aclk_perihp", mux_aclk_perihp_p, CLK_IGNORE_UNUSED,
>>                          RK3399_CLKSEL_CON(14), 7, 1, MFLAGS, 0, 5, DFLAGS,
> Definitely there was a bug since this table itself was inconsistent.
> ...and I _think_ this fix is correct, but I'll note that the TRM has
> more inconsistency here.
>
> In the big clock table 'CRU Clock Architecture Diagram', I see:
>    CLK 4 is CPLL
>    CLK 5 is GPLL
>    CLK 125 is aclk_perihp_cpll_src and has 4 (CPLL) as source, with
> g5[0] as the bit
>    CLK 126 is aclk_perihp_gpll_src and has 5 (GPLL) as source, with
> g5[1] as the bit
>
> In the definition of CRU_CLKGATE_CON5:
>    bit 0 shows aclk_perihp_gpll_src_en
>    bit 1 shows aclk_perihp_cpll_src_en
>
>
> Thus the table shows CPLL as gate5[0] and GPLL as gate5[1].  The
> register definition shows the opposite.  I'll tend to believe the
> table over the register definition, but I figured I'd bring it up
> anyway.
>
>
> Xing Zheng: can you confirm that the table is correct and ask
> documentation folks to fix the register definition for
> CRU_CLKGATE_CON5?
Yes, previously, our IC & DOC partner confirmed that the definition of 
CRU_CLKGATE_CON5 should be:
   bit 0 shows aclk_perihp_cpll_src_en
   bit 1 shows aclk_perihp_gpll_src_en

Sorry to the incorrect register definition, we will fix them and review 
the TRM again.

Thanks.

-- 
- Xing Zheng




From vinod.koul at intel.com  Fri May 13 23:25:16 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Sat, 14 May 2016 11:55:16 +0530
Subject: [PATCH V18 0/3] dmaengine: add Qualcomm Technologies HIDMA driver
In-Reply-To: <1462076728-14367-1-git-send-email-okaya@codeaurora.org>
References: <1462076728-14367-1-git-send-email-okaya@codeaurora.org>
Message-ID: <20160514062516.GL2274@localhost>

On Sun, May 01, 2016 at 12:25:25AM -0400, Sinan Kaya wrote:
> The Qualcomm Technologies HIDMA device has been designed
> to support virtualization technology. The driver has been
> divided into two to follow the hardware design.
> 
> 1. HIDMA Management driver
> 2. HIDMA Channel driver
> 
> Each HIDMA HW consists of multiple channels. These channels
> share some set of common parameters. These parameters are
> initialized by the management driver during power up.
> Same management driver is used for monitoring the execution
> of the channels. Management driver can change the performance
> behavior dynamically such as bandwidth allocation and
> prioritization in the future.
> 
> The management driver is executed in host context and
> is the main management entity for all channels provided by
> the device.
> 
> ------------------------
> What's new
> ------------------------
> - Get rid of hidma_ll_resume function
> - Rename hidma_ll_pause to hidma_ll_disable
> - Remove tx_status_list and attach the err_code and err_info to the TRE
> - Create a hidma_handle_tre_completion function to make error path and
>   success path common.
> - More style corrections

Applied, thanks

-- 
~Vinod


From robert.jarzmik at free.fr  Sat May 14 01:13:05 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Sat, 14 May 2016 10:13:05 +0200
Subject: [RFC PATCH 0/7] AC97 device/driver model revamp
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <s5hlh3j8uwg.wl-tiwai@suse.de>
Message-ID: <87y47dhxbi.fsf@belgarion.home>

Takashi Iwai <tiwai at suse.de> writes:

> On Sat, 30 Apr 2016 23:15:32 +0200,
> Robert Jarzmik wrote:
>> 
>> Well, this is a long term effort, which might need a complete rewrite according
>> to the comments it'll get. Let's expose it for comments and see how I can
>> progress with it.
>
> I think it's good in general.  The implementation looks fairly simple
> and thin enough.
Thanks.

> An open question is whether migrating the former AC97 layer into the
> new bus.  I'm not sure about this.  Transition to a new layer always
> brings subtle bugs, especially when the target devices are in wide
> range of legacy ones...   If any, we should start just wrapping via
> the new bus ops.
I agree, the migration to the new layer will bring bugs. And the test might be
impossible to carry out by lack of testers.

The wrapping of bus operations is the goal of sound/ac97/snd_ac97_compat.c.

> Some other nitpicks:
> - We usually use snd_ prefix for sound stuff.  Better to keep this for
>   exported symbols at least.
Of course, for RFC v2.

> - I don't see much value in the usefulness of compat_* stuff.
That's mainly the bus operation wrapping and backward compatibility. The idea is
to be able to convert only the probing/removal/suspend/resume of an ac97 codec
or controller without changing its main code in a first patch, and then consider
surgery (if applicable) to convert it wholly.

>   For example, it doesn't cover the actual reset procedure or such
>   done as in the old ac97 code.
Ah then my code is incomplete and I must work on it.

For the reset procedure I have ported snd_ac97_reset(), as well as the
snd_ac97_us_ops operation wrappers. Would you give me an example of the reset
I'm missing (a file and a function) ?

> So it won't work compatibly.  If it's a few lines of changes, the direct call
> would be likely simpler in the end.

>
> - The order of patches needs reconsideration.  The current patchset
>   will break the build, as the hook to sound/ac97/* is done in the
>   last patch, while you're already building against to the new stuff
>   beforehand.
Very true. kbuild robot objected as well :) For RFC v2.

Cheers.

-- 
Robert


From hdegoede at redhat.com  Sat May 14 02:07:51 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 14 May 2016 11:07:51 +0200
Subject: [linux-sunxi] Re: [PATCH 2/2] musb: sunxi: Set state to
 A_WAIT_VRISE when enabling VBus
In-Reply-To: <20160513183428.GA1665@uda0271908>
References: <1463077869-13224-1-git-send-email-hdegoede@redhat.com>
 <1463077869-13224-2-git-send-email-hdegoede@redhat.com>
 <20160513183428.GA1665@uda0271908>
Message-ID: <8765c9b5-1e40-2967-ac2c-da751b7d9019@redhat.com>

Hi,

On 13-05-16 20:35, Bin Liu wrote:
> Hi,
>
> On Thu, May 12, 2016 at 08:31:09PM +0200, Hans de Goede wrote:
>> When the board is powering attached usb devices via the otg port
>> sometimes / on some devices it takes slightly too long for the VBus
>> detection code in phy-sun4i-usb.c to signal that VBus is high after
>> enabling VBus and the musb hardware signals a MUSB_INTR_VBUSERROR
>> interrupt.
>>
>> This commit sets the otg state to A_WAIT_VRISE upon enabling Vbus
>> making musb_stage0_irq() ignore the first VBUSERR_RETRY_COUNT
>> VBUSERROR interrupts, fixing connection issues in these cases.
>>
>> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
>> ---
>>  drivers/usb/musb/sunxi.c | 8 +++++---
>>  1 file changed, 5 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
>> index 2c33d9b..2ee48fb 100644
>> --- a/drivers/usb/musb/sunxi.c
>> +++ b/drivers/usb/musb/sunxi.c
>> @@ -112,7 +112,7 @@ static void sunxi_musb_work(struct work_struct *work)
>>  		if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
>>  			set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
>>  			musb->xceiv->otg->default_a = 1;
>> -			musb->xceiv->otg->state = OTG_STATE_A_IDLE;
>> +			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
>>  			MUSB_HST_MODE(musb);
>>  			devctl |= MUSB_DEVCTL_SESSION;
>>  		} else {
>> @@ -145,9 +145,10 @@ static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
>>  {
>>  	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
>>
>> -	if (is_on)
>> +	if (is_on) {
>>  		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
>> -	else
>> +		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
>
> Why this has to be set in both sunxi_musb_work() and here? Only setting
> it in the work is not efficient?

Different code paths, sunxi_musb_work sets it when the id pin changes
(gets pulled low), this function gets called by musb_core in response
to a session-request interrupt.

Regards,

Hans


>
> Regards,
> -Bin.
>
>> +	} else
>>  		clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
>>
>>  	schedule_work(&glue->work);
>> @@ -325,6 +326,7 @@ static int sunxi_set_mode(struct musb *musb, u8 mode)
>>  		set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
>>  		/* Stop musb work from turning vbus off again */
>>  		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
>> +		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
>>  	}
>>
>>  	return 0;
>> --
>> 2.7.4
>>


From jchandra at broadcom.com  Sat May 14 02:07:45 2016
From: jchandra at broadcom.com (Jayachandran C)
Date: Sat, 14 May 2016 14:37:45 +0530
Subject: [PATCH V7 08/11] pci, acpi: Support for ACPI based generic PCI
 host controller
In-Reply-To: <1462893601-8937-9-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-9-git-send-email-tn@semihalf.com>
Message-ID: <CAKc_7PVz8rgCTqMVuR7g944nonSHExAhx5rNsjiP3J=9LfA99g@mail.gmail.com>

On Tue, May 10, 2016 at 8:49 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> This patch is going to implement generic PCI host controller for
> ACPI world, similar to what pci-host-generic.c driver does for DT world.
>
> All such drivers, which we have seen so far, were implemented within
> arch/ directory since they had some arch assumptions (x86 and ia64).
> However, they all are doing similar thing, so it makes sense to find
> some common code and abstract it into the generic driver.
>
> In order to handle PCI config space regions properly, we define new
> MCFG interface which does sanity checks on MCFG table and keeps its
> root pointer. User is able to lookup MCFG regions based on that root
> pointer and specified domain:bus_start:bus_end touple. We are using
> pci_mmcfg_late_init old prototype to avoid another function name.
>
> The implementation of pci_acpi_scan_root() looks up the MCFG entries
> and sets up a new mapping (regions are not mapped until host controller ask
> for it). Generic PCI functions are used for accessing config space.
> Driver selects PCI_ECAM and uses functions from drivers/pci/ecam.h
> to create and access ECAM mappings.
>
> As mentioned in Kconfig help section, ACPI_PCI_HOST_GENERIC choice
> should be made on a per-architecture basis.

Looking thru the new code, I see a few issues, please see below

> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
> ---
>  drivers/acpi/Kconfig            |   8 +++
>  drivers/acpi/Makefile           |   1 +
>  drivers/acpi/pci_mcfg.c         |  97 ++++++++++++++++++++++++++
>  drivers/acpi/pci_root_generic.c | 149 ++++++++++++++++++++++++++++++++++++++++
>  drivers/pci/ecam.h              |   5 ++
>  include/linux/pci-acpi.h        |   5 ++
>  include/linux/pci.h             |   5 +-
>  7 files changed, 269 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/acpi/pci_mcfg.c
>  create mode 100644 drivers/acpi/pci_root_generic.c
>
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index 183ffa3..44afc76 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -346,6 +346,14 @@ config ACPI_PCI_SLOT
>           i.e., segment/bus/device/function tuples, with physical slots in
>           the system.  If you are unsure, say N.
>
> +config ACPI_PCI_HOST_GENERIC
> +       bool
> +       select PCI_ECAM
> +       help
> +         Select this config option from the architecture Kconfig,
> +         if it is preferred to enable ACPI PCI host controller driver which
> +         has no arch-specific assumptions.
> +
>  config X86_PM_TIMER
>         bool "Power Management Timer Support" if EXPERT
>         depends on X86
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 81e5cbc..627a2b7 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -40,6 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
>  acpi-y                         += ec.o
>  acpi-$(CONFIG_ACPI_DOCK)       += dock.o
>  acpi-y                         += pci_root.o pci_link.o pci_irq.o
> +obj-$(CONFIG_ACPI_PCI_HOST_GENERIC)    += pci_root_generic.o pci_mcfg.o
>  acpi-y                         += acpi_lpss.o acpi_apd.o
>  acpi-y                         += acpi_platform.o
>  acpi-y                         += acpi_pnp.o
> diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
> new file mode 100644
> index 0000000..373d079
> --- /dev/null
> +++ b/drivers/acpi/pci_mcfg.c
> @@ -0,0 +1,97 @@
> +/*
> + * Copyright (C) 2016 Broadcom
> + *     Author: Jayachandran C <jchandra at broadcom.com>
> + * Copyright (C) 2016 Semihalf
> + *     Author: Tomasz Nowicki <tn at semihalf.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, version 2, as
> + * published by the Free Software Foundation (the "GPL").
> + *
> + * 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 version 2 (GPLv2) for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * version 2 (GPLv2) along with this source code.
> + */
> +#include <linux/kernel.h>
> +#include <linux/pci.h>
> +#include <linux/pci-acpi.h>
> +
> +#define PREFIX "ACPI: "
> +
> +/* Root pointer to the mapped MCFG table */
> +static struct acpi_table_mcfg *mcfg_table;
> +
> +#define MCFG_ENTRIES(mcfg_ptr) (((mcfg_ptr)->header.length -           \
> +                               sizeof(struct acpi_table_mcfg)) /       \
> +                               sizeof(struct acpi_mcfg_allocation))

It would be better if you used static inline function here.

> +static phys_addr_t pci_mcfg_lookup_static(u16 seg, u8 bus_start, u8 bus_end)
> +{
> +       struct acpi_mcfg_allocation *mptr;
> +       int i;
> +
> +       if (!mcfg_table) {
> +               pr_err(PREFIX "MCFG table not available, lookup failed\n");
> +               return -ENXIO;
> +       }
> +
> +       mptr = (struct acpi_mcfg_allocation *) &mcfg_table[1];
> +
> +       /*
> +        * We expect exact match, unless MCFG entry end bus covers more than
> +        * specified by caller.
> +        */
> +       for (i = 0; i < MCFG_ENTRIES(mcfg_table); i++, mptr++) {
> +               if (mptr->pci_segment == seg &&
> +                   mptr->start_bus_number == bus_start &&
> +                   mptr->end_bus_number >= bus_end) {
> +                       return mptr->address;
> +               }
> +       }

There is an issue here, the bus range is obtained if different
ways. If the _CRS has it, this should be fine. But if it is _BBN-0xff
or the default 0-0xff, then I would think taking the MCFG entry end
would be better. This would require updating the bus resource end.

Also (trivial), the braces are not needed.

> +       return -ENXIO;
> +}
> +
> +phys_addr_t pci_mcfg_lookup(struct acpi_device *device, u16 seg,
> +                           struct resource *bus_res)
> +{
> +       phys_addr_t addr;
> +
> +       addr = acpi_pci_root_get_mcfg_addr(device->handle);
> +       if (addr)
> +               return addr;

When you have address from _CBA, you are assuming that the
bus range is also set correctly (from _CRS or as _BBN-0xff). Is
this assumption correct?

(this was discussed earlier)  you are doing the _CBA call again,
I think cleaning up the _CBA, _BBN, _CRS and MCFG based
ECAM area resources and defaults should be a different patch,
which would need changes to pci_root.c. We should use
root->mcfg_addr in this patchset.

> +
> +       return pci_mcfg_lookup_static(seg, bus_res->start, bus_res->end);

There is no need to have a separate function for this, based on by
above comment, you might need to change bus_res, so having it here
would be better.

> +}
> +
> +static __init int pci_mcfg_parse(struct acpi_table_header *header)
> +{
> +       struct acpi_table_mcfg *mcfg;
> +       int n;
> +
> +       if (!header)
> +               return -EINVAL;

This is not needed, the handler is not called if header is NULL

> +
> +       mcfg = (struct acpi_table_mcfg *)header;
> +       n = MCFG_ENTRIES(mcfg);
> +       if (n <= 0 || n > 255) {
> +               pr_err(PREFIX "MCFG has incorrect entries (%d).\n", n);
> +               return -EINVAL;
> +       }
>
> +       mcfg_table = mcfg;

Saving a reference of ACPI mapping seems dangerous, acpi_parse_table
calles early_acpi_os_unmap_memory() after calling handler, which does
not do anything since acpi_gbl_permanent_mmap is set.

I would suggest copying the entries.

> +       pr_info(PREFIX "MCFG table loaded, %d entries detected\n", n);
> +       return 0;
> +}
> +
> +/* Interface called by ACPI - parse and save MCFG table */
> +void __init pci_mmcfg_late_init(void)
> +{
> +       int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse);
> +       if (err)
> +               pr_err(PREFIX "Failed to parse MCFG (%d)\n", err);
> +}


JC.


From robert.jarzmik at free.fr  Sat May 14 02:50:50 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Sat, 14 May 2016 11:50:50 +0200
Subject: [RFC PATCH 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <s5hk2j38tmf.wl-tiwai@suse.de> (Takashi Iwai's message of "Mon,
 09 May 2016 11:31:52 +0200")
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
 <s5hk2j38tmf.wl-tiwai@suse.de>
Message-ID: <87twi1hssl.fsf@belgarion.home>

Takashi Iwai <tiwai at suse.de> writes:

> On Sat, 30 Apr 2016 23:15:34 +0200,
> Robert Jarzmik wrote:
>> 
>> diff --git a/include/sound/ac97/codec.h b/include/sound/ac97/codec.h
>> new file mode 100644
>> index 000000000000..4b8b3e570892
>> --- /dev/null
>> +++ b/include/sound/ac97/codec.h
>> @@ -0,0 +1,98 @@
>> +/*
>> + *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
>> + *
>> + * 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.
>> + */
>> +#ifndef AC97_CODEC_H
>> +#define AC97_CODEC_H
>
> Let's be careful about the choice of the guard.
Ok, would _SND_AC97_CODEC_H be better ?

>> +#define AC97_ID(vendor_id1, vendor_id2) \
>> +	(((vendor_id1 & 0xffff) << 16) | (vendor_id2 & 0xffff))
>> +#define AC97_DRIVER_ID(vendor_id1, vendor_id2, mask_id1, mask_id2, _data) \
>> +	{ .id = ((vendor_id1 & 0xffff) << 16) | (vendor_id2 & 0xffff), \
>> +	  .mask = ((mask_id1 & 0xffff) << 16) | (mask_id2 & 0xffff), \
>> +	  .data = _data }
>
> Give parentheses around the macro arguments.
Right, for RFC v2.

>> +struct ac97_codec_device {
>> +	struct device		dev;	/* Must stay first member */
>
> This doesn't have to be the first element as long as you use container_of().
Ah yes, that's a leftover from a former idea, I'll remove that comment.

In the initial code I'd done "struct ac97_codec_device" was hidden from this
file (ie. there was only a "struct ac97_codec_device;" statement), the body of
the struct was contained in sound/ac97/ac97_core.h.

The only provided macro to access the "struct device" inside "struct
ac97_codec_device" was relying on this "trick" (that's a bit like in the
video4linux area).

Anyway, good point, I'll remove that.

>> +struct ac97_codec_driver {
>> +	struct device_driver	driver;
>> +	int			(*probe)(struct ac97_codec_device *);
>> +	int			(*remove)(struct ac97_codec_device *);
>> +	int			(*suspend)(struct ac97_codec_device *);
>> +	int			(*resume)(struct ac97_codec_device *);
>> +	void			(*shutdown)(struct ac97_codec_device *);
>> +	struct ac97_id		*id_table;
>
> Missing const?
Ah no, unfortunately not, or rather not yet.

I tried that one, not very hard, but at least ac97_bus_match() with the pair
"struct ac97_id *id = adrv->id_table" and "do { } while (++id->id);" is not
possible AFAIK with a const.

I will see if I can come up with something better for ac97_bus_match, such as
array usage instead of pointer arithmetics.

>> +};
>> +
>> +int ac97_codec_driver_register(struct ac97_codec_driver *drv);
>> +void ac97_codec_driver_unregister(struct ac97_codec_driver *drv);
>> +
>> +static inline struct device *
>> +ac97_codec_dev2dev(const struct ac97_codec_device *adev)
>> +{
>> +	return (struct device *)(adev);
>
> What's wrong with the simple &adev->dev ?  Cast looks scary.
The same leftover than above, I'll change that for RFC v2.

>> +struct ac97_controller {
>> +	const struct ac97_controller_ops *ops;
>> +	struct list_head controllers;
>> +	struct device *dev;
>> +	int bus_idx;
>
> What is this bus_idx for?
Initially it was to distinguish 2 different AC97 controllers. In the current
patchset state, it's not usefull anymore AFAICS.
So let's remove it.

>> +	int bound_codecs;
The same comment would apply here. I don't think that information is important
anymore. I thought I would use that to prevent AC97 controler removal while
codecs are still bound.

In a second thought what would be better is to have get_device() called for each
bound codec which will prevent ac97_digital_controller_unregister() to succeed
(-EBUSY).

>> +	struct list_head codecs;
>> +};
>> +
>> +int ac97_digital_controller_register(const struct ac97_controller_ops *ops,
>> +				     struct device *dev);
>> +int ac97_digital_controller_unregister(const struct device *dev);
>> +
>> +#endif
>> diff --git a/sound/ac97/Kconfig b/sound/ac97/Kconfig
>> new file mode 100644
>> index 000000000000..fd2c2d031e62
>> --- /dev/null
>> +++ b/sound/ac97/Kconfig
>> @@ -0,0 +1,9 @@
>> +#
>> +# PCI configuration
>> +#
>  
> Still only for PCI? :)
Ouch ;) I'll amend that for RFC v2.
>
>> +
>> +config AC97
>> +	bool "AC97 bus"
>> +	help
>> +	   Say Y here if you want to have AC97 devices, which are sound oriented
>> +	   devices around an AC-Link.
>> diff --git a/sound/ac97/Makefile b/sound/ac97/Makefile
>> new file mode 100644
>> index 000000000000..5575909d46e2
>> --- /dev/null
>> +++ b/sound/ac97/Makefile
>> @@ -0,0 +1,5 @@
>> +#
>> +# make for AC97 bus drivers
>> +#
>> +
>> +obj-y	+= bus.o codec.o snd_ac97_compat.o
>
> No possibility for modules?
There should be, so I'll put that on my TODO list for RFC v2.

>> +static struct ac97_codec_device *
>> +ac97_codec_find(struct ac97_controller *ac97_ctrl, int codec_num)
>> +{
>> +	struct ac97_codec_device *codec;
>> +
>> +	list_for_each_entry(codec, &ac97_ctrl->codecs, list)
>> +		if (codec->num == codec_num)
>> +			return codec;
>> +
>> +	return NULL;
>> +}
>
> It's a question whether we need to manage the codecs in the linked
> list.  There can be at most 4 codecs, so it fits in an array well,
> too.  Then some codes like this would be simpler. (And it'll even
> reduce the footprint, too.)
Agreed. For RFC v2.

>> +unsigned int ac97_bus_scan_one(struct ac97_controller *ac97,
>> +				      int codec_num)
>> +{
>> +	struct ac97_codec_device codec;
>> +	unsigned short vid1, vid2;
>> +	int ret;
>> +
>> +	codec.dev = *ac97->dev;
>> +	codec.num = codec_num;
>> +	ret = ac97->ops->read(&codec, AC97_VENDOR_ID1);
>> +	vid1 = (ret & 0xffff);
>> +	if (ret < 0)
>> +		return 0;
>
> Hmm.  This looks pretty hackish and dangerous.
You mean returning 0 even if the read failed, right ?
A better prototype would probably be (for RFC v2):
  int ac97_bus_scan_one(struct ac97_controller *ac97, int codec_num,
                        unsigned int *vendor_id);

>> +static int ac97_bus_scan(struct ac97_controller *ac97_ctrl)
>> +{
>> +	int ret, i;
>> +	unsigned int vendor_id;
>> +
>> +	for (i = 0; i < AC97_BUS_MAX_CODECS; i++) {
>> +		if (ac97_codec_find(ac97_ctrl, i))
>> +			continue;
>> +		vendor_id = ac97_bus_scan_one(ac97_ctrl, i);
>> +		if (!vendor_id)
>> +			continue;
>> +
>> +		ret = ac97_codec_add(ac97_ctrl, i, vendor_id);
>> +		if (ret < 0)
>> +			return ret;
>
> This is one of concerns: we don't know whether the device really
> reacts well if you access to a non-existing slot.  At least, it'd be
> safer to have the masks for the devices we already know the slots.

Ah you mean upon ac97 controller registration, the
ac97_digital_controller_register() should provide the information for each of
the 4 slots :
 - does the controller enable this slot (default yes)
 - does the controller support auto-scan for this slot (default yes)
   I'm not sure this "feature" is required, it looks a bit over-engineered.

That could be a matter of 1 or 2 masks as input parameters to
ac97_digital_controller_register().

>> +static int ac97_bus_reset(struct ac97_controller *ac97_ctrl)
>> +{
>> +	struct ac97_codec_device codec;
>> +
>> +	memset(&codec, 0, sizeof(codec));
>> +	codec.dev = *ac97_ctrl->dev;
>> +
>> +	ac97_ctrl->ops->reset(&codec);
>
> So, this assumes that reset ops is mandatory?  Then document it at
> least.
Ok, for RFC v2.

Thanks for your review and feedbacks Takashi, I'll work on both Mark and your
comments in the next weeks.

Cheers.

-- 
Robert


From appana.durga.rao at xilinx.com  Sat May 14 03:20:31 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Sat, 14 May 2016 15:50:31 +0530
Subject: [PATCH] dmaengine: vdma: Add support for cyclic dma mode
Message-ID: <1463221231-30374-1-git-send-email-appanad@xilinx.com>

This patch adds support for AXI DMA cyclic dma mode.
In cyclic mode, DMA fetches and processes the same
BDs without interruption. The DMA continues to fetch and process
until it is stopped or reset.

Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
 drivers/dma/xilinx/xilinx_vdma.c | 179 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 174 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
index df91185..5a43409 100644
--- a/drivers/dma/xilinx/xilinx_vdma.c
+++ b/drivers/dma/xilinx/xilinx_vdma.c
@@ -157,6 +157,7 @@
 /* AXI DMA Specific Masks/Bit fields */
 #define XILINX_DMA_MAX_TRANS_LEN	GENMASK(22, 0)
 #define XILINX_DMA_CR_COALESCE_MAX	GENMASK(23, 16)
+#define XILINX_DMA_CR_CYCLIC_BD_EN_MASK	BIT(4)
 #define XILINX_DMA_CR_COALESCE_SHIFT	16
 #define XILINX_DMA_BD_SOP		BIT(27)
 #define XILINX_DMA_BD_EOP		BIT(26)
@@ -278,11 +279,13 @@ struct xilinx_cdma_tx_segment {
  * @async_tx: Async transaction descriptor
  * @segments: TX segments list
  * @node: Node in the channel descriptors list
+ * @cyclic: Check for cyclic transfers.
  */
 struct xilinx_dma_tx_descriptor {
 	struct dma_async_tx_descriptor async_tx;
 	struct list_head segments;
 	struct list_head node;
+	bool cyclic;
 };
 
 /**
@@ -302,6 +305,7 @@ struct xilinx_dma_tx_descriptor {
  * @direction: Transfer direction
  * @num_frms: Number of frames
  * @has_sg: Support scatter transfers
+ * @cyclic: Check for cyclic transfers.
  * @genlock: Support genlock mode
  * @err: Channel has errors
  * @tasklet: Cleanup work after irq
@@ -312,6 +316,7 @@ struct xilinx_dma_tx_descriptor {
  * @desc_submitcount: Descriptor h/w submitted count
  * @residue: Residue for AXI DMA
  * @seg_v: Statically allocated segments base
+ * @cyclic_seg_v: Statically allocated segment base for cyclic transfers
  * @start_transfer: Differentiate b/w DMA IP's transfer
  */
 struct xilinx_dma_chan {
@@ -330,6 +335,7 @@ struct xilinx_dma_chan {
 	enum dma_transfer_direction direction;
 	int num_frms;
 	bool has_sg;
+	bool cyclic;
 	bool genlock;
 	bool err;
 	struct tasklet_struct tasklet;
@@ -340,6 +346,7 @@ struct xilinx_dma_chan {
 	u32 desc_submitcount;
 	u32 residue;
 	struct xilinx_axidma_tx_segment *seg_v;
+	struct xilinx_axidma_tx_segment *cyclic_seg_v;
 	void (*start_transfer)(struct xilinx_dma_chan *chan);
 };
 
@@ -474,6 +481,7 @@ xilinx_vdma_alloc_tx_segment(struct xilinx_dma_chan *chan)
 	if (!segment)
 		return NULL;
 
+	memset(segment, 0, sizeof(*segment));
 	segment->phys = phys;
 
 	return segment;
@@ -660,13 +668,37 @@ static void xilinx_dma_free_chan_resources(struct dma_chan *dchan)
 	dev_dbg(chan->dev, "Free all channel resources.\n");
 
 	xilinx_dma_free_descriptors(chan);
-	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
+		xilinx_dma_free_tx_segment(chan, chan->cyclic_seg_v);
 		xilinx_dma_free_tx_segment(chan, chan->seg_v);
+	}
 	dma_pool_destroy(chan->desc_pool);
 	chan->desc_pool = NULL;
 }
 
 /**
+ * xilinx_dma_chan_handle_cyclic - Cyclic dma callback
+ * @chan: Driver specific dma channel
+ * @desc: dma transaction descriptor
+ * @flags: flags for spin lock
+ */
+static void xilinx_dma_chan_handle_cyclic(struct xilinx_dma_chan *chan,
+					  struct xilinx_dma_tx_descriptor *desc,
+					  unsigned long *flags)
+{
+	dma_async_tx_callback callback;
+	void *callback_param;
+
+	callback = desc->async_tx.callback;
+	callback_param = desc->async_tx.callback_param;
+	if (callback) {
+		spin_unlock_irqrestore(&chan->lock, *flags);
+		callback(callback_param);
+		spin_lock_irqsave(&chan->lock, *flags);
+	}
+}
+
+/**
  * xilinx_dma_chan_desc_cleanup - Clean channel descriptors
  * @chan: Driver specific DMA channel
  */
@@ -681,6 +713,11 @@ static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan)
 		dma_async_tx_callback callback;
 		void *callback_param;
 
+		if (desc->cyclic) {
+			xilinx_dma_chan_handle_cyclic(chan, desc, &flags);
+			break;
+		}
+
 		/* Remove from the list of running transactions */
 		list_del(&desc->node);
 
@@ -757,7 +794,7 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 		return -ENOMEM;
 	}
 
-	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		/*
 		 * For AXI DMA case after submitting a pending_list, keep
 		 * an extra segment allocated so that the "next descriptor"
@@ -768,6 +805,15 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 		 */
 		chan->seg_v = xilinx_axidma_alloc_tx_segment(chan);
 
+		/*
+		 * For cyclic DMA mode we need to program the tail Descriptor
+		 * register with a value which is not a part of the BD chain
+		 * so allocating a desc segment during channel allocation for
+		 * programming tail descriptor.
+		 */
+		chan->cyclic_seg_v = xilinx_axidma_alloc_tx_segment(chan);
+	}
+
 	dma_cookie_init(dchan);
 
 	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
@@ -1157,8 +1203,12 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
 
 	/* Start the transfer */
 	if (chan->has_sg) {
-		dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
-			       tail_segment->phys);
+		if (chan->cyclic)
+			dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
+				       chan->cyclic_seg_v->phys);
+		else
+			dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
+				       tail_segment->phys);
 	} else {
 		struct xilinx_axidma_tx_segment *segment;
 		struct xilinx_axidma_desc_hw *hw;
@@ -1209,7 +1259,8 @@ static void xilinx_dma_complete_descriptor(struct xilinx_dma_chan *chan)
 
 	list_for_each_entry_safe(desc, next, &chan->active_list, node) {
 		list_del(&desc->node);
-		dma_cookie_complete(&desc->async_tx);
+		if (!desc->cyclic)
+			dma_cookie_complete(&desc->async_tx);
 		list_add_tail(&desc->node, &chan->done_list);
 	}
 }
@@ -1397,6 +1448,11 @@ static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 	unsigned long flags;
 	int err;
 
+	if (chan->cyclic) {
+		xilinx_dma_free_tx_descriptor(chan, desc);
+		return -EBUSY;
+	}
+
 	if (chan->err) {
 		/*
 		 * If reset fails, need to hard reset the system.
@@ -1414,6 +1470,9 @@ static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 	/* Put this transaction onto the tail of the pending queue */
 	append_desc_queue(chan, desc);
 
+	if (desc->cyclic)
+		chan->cyclic = true;
+
 	spin_unlock_irqrestore(&chan->lock, flags);
 
 	return cookie;
@@ -1669,12 +1728,112 @@ error:
 }
 
 /**
+ * xilinx_dma_prep_dma_cyclic - prepare descriptors for a DMA_SLAVE transaction
+ * @chan: DMA channel
+ * @sgl: scatterlist to transfer to/from
+ * @sg_len: number of entries in @scatterlist
+ * @direction: DMA direction
+ * @flags: transfer ack flags
+ */
+static struct dma_async_tx_descriptor *xilinx_dma_prep_dma_cyclic(
+	struct dma_chan *dchan, dma_addr_t buf_addr, size_t buf_len,
+	size_t period_len, enum dma_transfer_direction direction,
+	unsigned long flags)
+{
+	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_dma_tx_descriptor *desc;
+	struct xilinx_axidma_tx_segment *segment, *head_segment, *prev = NULL;
+	size_t copy, sg_used;
+	unsigned int num_periods;
+	int i;
+	u32 reg;
+
+	num_periods = buf_len / period_len;
+
+	if (!is_slave_direction(direction))
+		return NULL;
+
+	/* Allocate a transaction descriptor. */
+	desc = xilinx_dma_alloc_tx_descriptor(chan);
+	if (!desc)
+		return NULL;
+
+	chan->direction = direction;
+	dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
+	desc->async_tx.tx_submit = xilinx_dma_tx_submit;
+
+	for (i = 0; i < num_periods; ++i) {
+		sg_used = 0;
+
+		while (sg_used < period_len) {
+			struct xilinx_axidma_desc_hw *hw;
+
+			/* Get a free segment */
+			segment = xilinx_axidma_alloc_tx_segment(chan);
+			if (!segment)
+				goto error;
+
+			/*
+			 * Calculate the maximum number of bytes to transfer,
+			 * making sure it is less than the hw limit
+			 */
+			copy = min_t(size_t, period_len - sg_used,
+				     XILINX_DMA_MAX_TRANS_LEN);
+			hw = &segment->hw;
+			hw->buf_addr = buf_addr + sg_used + (period_len * i);
+			hw->control = copy;
+
+			if (prev)
+				prev->hw.next_desc = segment->phys;
+
+			prev = segment;
+			sg_used += copy;
+
+			/*
+			 * Insert the segment into the descriptor segments
+			 * list.
+			 */
+			list_add_tail(&segment->node, &desc->segments);
+		}
+	}
+
+	head_segment = list_first_entry(&desc->segments,
+				   struct xilinx_axidma_tx_segment, node);
+	desc->async_tx.phys = head_segment->phys;
+
+	desc->cyclic = true;
+	reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
+	reg |= XILINX_DMA_CR_CYCLIC_BD_EN_MASK;
+	dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
+
+	/* For the last DMA_MEM_TO_DEV transfer, set EOP */
+	if (direction == DMA_MEM_TO_DEV) {
+		segment->hw.control |= XILINX_DMA_BD_SOP;
+		segment = list_last_entry(&desc->segments,
+					  struct xilinx_axidma_tx_segment,
+					  node);
+		segment->hw.control |= XILINX_DMA_BD_EOP;
+		segment->hw.next_desc = (u32) head_segment->phys;
+	}
+
+	return &desc->async_tx;
+
+error:
+	xilinx_dma_free_tx_descriptor(chan, desc);
+	return NULL;
+}
+
+/**
  * xilinx_dma_terminate_all - Halt the channel and free descriptors
  * @chan: Driver specific DMA Channel pointer
  */
 static int xilinx_dma_terminate_all(struct dma_chan *dchan)
 {
 	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
+	u32 reg;
+
+	if (chan->cyclic)
+		xilinx_dma_chan_reset(chan);
 
 	/* Halt the DMA engine */
 	xilinx_dma_halt(chan);
@@ -1682,6 +1841,13 @@ static int xilinx_dma_terminate_all(struct dma_chan *dchan)
 	/* Remove and free all of the descriptors in the lists */
 	xilinx_dma_free_descriptors(chan);
 
+	if (chan->cyclic) {
+		reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
+		reg &= ~XILINX_DMA_CR_CYCLIC_BD_EN_MASK;
+		dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
+		chan->cyclic = false;
+	}
+
 	return 0;
 }
 
@@ -2218,7 +2384,10 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 	xdev->common.device_tx_status = xilinx_dma_tx_status;
 	xdev->common.device_issue_pending = xilinx_dma_issue_pending;
 	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
+		dma_cap_set(DMA_CYCLIC, xdev->common.cap_mask);
 		xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg;
+		xdev->common.device_prep_dma_cyclic =
+					  xilinx_dma_prep_dma_cyclic;
 		/* Residue calculation is supported by only AXI DMA */
 		xdev->common.residue_granularity =
 					  DMA_RESIDUE_GRANULARITY_SEGMENT;
-- 
2.1.2



From heiko at sntech.de  Sat May 14 04:30:41 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 14 May 2016 13:30:41 +0200
Subject: [PATCH v9 0/8] add i2c driver supported for rk3399
In-Reply-To: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
References: <1463039586-8134-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1649653.55gUf8lt1c@phil>

Am Donnerstag, 12. Mai 2016, 15:52:58 schrieb David Wu:
> There are three points differert from others:
>  - new method to caculate i2c timings for rk3399
>  - pclk and function clk are separated at rk3399
>  - add fast-plus mode supported for rk3399

On a rk3288

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

to make sure nothing currently working broke - and everything is running 
still fine.


Heiko


From heiko at sntech.de  Sat May 14 04:57:12 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 14 May 2016 13:57:12 +0200
Subject: [PATCH] ARM64: dts: rockchip: assign default rates for core
 rk3399 clocks
In-Reply-To: <1463172618-96001-1-git-send-email-briannorris@chromium.org>
References: <1463172618-96001-1-git-send-email-briannorris@chromium.org>
Message-ID: <25672526.OH6Oxq7zkd@phil>

Am Freitag, 13. Mai 2016, 13:50:18 schrieb Brian Norris:
> From: Xing Zheng <zhengxing at rock-chips.com>
> 
> These clocks are all core clocks used by many blocks/peripherals, many
> of whose drivers don't set their clock rates at all. Let's assign
> reasonable default clock rates for these core clocks, so that these
> peripherals get something reasonable by default, and also so that if
> child devices want to select a clock rate themselves, their muxes have
> some reasonable parent clock rates to branch off of (rather than just
> the boot-time defaults).
> 
> This helps the eMMC PHY, for one, to get a reasonable ACLK rate.
> 
> Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
> Signed-off-by: Brian Norris <briannorris at chromium.org>

applied for 4.8 with Doug's review-tag (after making the ARM64 lower-case)


From hdegoede at redhat.com  Sat May 14 05:45:05 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 14 May 2016 14:45:05 +0200
Subject: [PATCH v2 2/2] musb: sunxi: Set state to A_WAIT_VRISE when enabling
 Vbus
In-Reply-To: <1463229905-26387-1-git-send-email-hdegoede@redhat.com>
References: <1463229905-26387-1-git-send-email-hdegoede@redhat.com>
Message-ID: <1463229905-26387-2-git-send-email-hdegoede@redhat.com>

When the board is powering attached usb devices via the otg port
sometimes / on some devices it takes slightly too long for the Vbus
detection code in phy-sun4i-usb.c to signal that Vbus is high after
enabling Vbus and the musb hardware signals a MUSB_INTR_VBUSERROR
interrupt.

This commit sets the otg state to A_WAIT_VRISE upon enabling Vbus
making musb_stage0_irq() ignore the first VBUSERR_RETRY_COUNT
VBUSERROR interrupts, fixing connection issues in these cases.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
Changes in v2:
-Use curly-braces in both branches of if-else
---
 drivers/usb/musb/sunxi.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index 2c33d9b..e7d4617 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -112,7 +112,7 @@ static void sunxi_musb_work(struct work_struct *work)
 		if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
 			set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 			musb->xceiv->otg->default_a = 1;
-			musb->xceiv->otg->state = OTG_STATE_A_IDLE;
+			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
 			MUSB_HST_MODE(musb);
 			devctl |= MUSB_DEVCTL_SESSION;
 		} else {
@@ -145,10 +145,12 @@ static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
 {
 	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 
-	if (is_on)
+	if (is_on) {
 		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
-	else
+		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
+	} else {
 		clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+	}
 
 	schedule_work(&glue->work);
 }
@@ -325,6 +327,7 @@ static int sunxi_set_mode(struct musb *musb, u8 mode)
 		set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
 		/* Stop musb work from turning vbus off again */
 		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
 	}
 
 	return 0;
-- 
2.7.4



From hdegoede at redhat.com  Sat May 14 05:45:04 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 14 May 2016 14:45:04 +0200
Subject: [PATCH v2 1/2] musb: sunxi: Add set_mode platform function
Message-ID: <1463229905-26387-1-git-send-email-hdegoede@redhat.com>

Move the mode handling to the platform_set_mode callback.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
Changes in v2:
-No changes
---
 drivers/usb/musb/sunxi.c | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index fdab423..2c33d9b 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -264,15 +264,6 @@ static int sunxi_musb_init(struct musb *musb)
 	if (ret)
 		goto error_unregister_notifier;
 
-	if (musb->port_mode == MUSB_PORT_MODE_HOST) {
-		ret = phy_power_on(glue->phy);
-		if (ret)
-			goto error_phy_exit;
-		set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
-		/* Stop musb work from turning vbus off again */
-		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
-	}
-
 	musb->isr = sunxi_musb_interrupt;
 
 	/* Stop the musb-core from doing runtime pm (not supported on sunxi) */
@@ -280,8 +271,6 @@ static int sunxi_musb_init(struct musb *musb)
 
 	return 0;
 
-error_phy_exit:
-	phy_exit(glue->phy);
 error_unregister_notifier:
 	if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
 		extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
@@ -323,6 +312,24 @@ static int sunxi_musb_exit(struct musb *musb)
 	return 0;
 }
 
+static int sunxi_set_mode(struct musb *musb, u8 mode)
+{
+	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+	int ret;
+
+	if (mode == MUSB_HOST) {
+		ret = phy_power_on(glue->phy);
+		if (ret)
+			return ret;
+
+		set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
+		/* Stop musb work from turning vbus off again */
+		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+	}
+
+	return 0;
+}
+
 static void sunxi_musb_enable(struct musb *musb)
 {
 	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
@@ -569,6 +576,7 @@ static const struct musb_platform_ops sunxi_musb_ops = {
 	.exit		= sunxi_musb_exit,
 	.enable		= sunxi_musb_enable,
 	.disable	= sunxi_musb_disable,
+	.set_mode	= sunxi_set_mode,
 	.fifo_offset	= sunxi_musb_fifo_offset,
 	.ep_offset	= sunxi_musb_ep_offset,
 	.busctl_offset	= sunxi_musb_busctl_offset,
-- 
2.7.4



From ynorov at caviumnetworks.com  Sat May 14 05:49:50 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Sat, 14 May 2016 15:49:50 +0300
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <20160512131948.GA30205@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <2733875.IzutTZKHMc@wuerfel> <57347BD4.8010105@huawei.com>
 <4521594.dSmlmmAdFg@wuerfel> <20160512131948.GA30205@yury-N73SV>
Message-ID: <20160514124950.GA27841@yury-N73SV>

On Thu, May 12, 2016 at 04:19:48PM +0300, Yury Norov wrote:

[...]

> > I think that's a good idea. The function used to be slightly different
> > for each architecture, but now it seems we have a significant number
> > of identical implementations that we could just merge them together
> > into one.
> > 
> > sys_mmap_pgoff was originally introduced as the common implementation
> > and it reduced the amount of duplication a lot, but as its units
> > are based on PAGE_SIZE rather than hardwired 4096 bytes, it's
> > not as useful.
> > 
> 
> microblaze and mips (twice) are doing like this. And aarh32 as well,
> in arch/arm64/kernel/entry32.S
> 
> In previous submissions it was a patch that shares aarch32 code to
> ilp32. If we decided turn around again, I think, we'd pick up that patch.
> 
> The other option is to make this hack generic, as so many arches use it.

Hi again,

I picked up that old patch from Jan, and found that it doesn't delouse
addr and length, which is wrong for ilp32. So now I think we'd pick
Bamvor version.

Jan's patch (rebased) is attached for reference.

Yury.


>From 02ad258662c40d457ac041634e67e1cbdbb800f3 Mon Sep 17 00:00:00 2001
From: Jan Dakinevich <jan.dakinevich at gmail.com>
Date: Tue, 3 Nov 2015 02:30:41 +0300
Subject: ilp32: common 32-bit wrappers

Signed-off-by: Jan Dakinevich <jan.dakinevich at gmail.com>
Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>

diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 9dfdf86..2319042 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -30,6 +30,7 @@ arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   ../../arm/kernel/opcodes.o binfmt_elf32.o
 arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
+arm64-obj-$(CONFIG_COMPAT)		+= entry32-common.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
 arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o perf_callchain.o
diff --git a/arch/arm64/kernel/entry32-common.S b/arch/arm64/kernel/entry32-common.S
new file mode 100644
index 0000000..1a0abe3
--- /dev/null
+++ b/arch/arm64/kernel/entry32-common.S
@@ -0,0 +1,23 @@
+#include <linux/linkage.h>
+#include <linux/const.h>
+
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/errno.h>
+#include <asm/page.h>
+
+/*
+ * Note: off_4k (w5) is always in units of 4K. If we can't do the
+ * requested offset because it is not page-aligned, we return -EINVAL.
+ */
+ENTRY(compat_sys_mmap2_wrapper)
+#if PAGE_SHIFT > 12
+	tst	w5, #~PAGE_MASK >> 12
+	b.ne	1f
+	lsr	w5, w5, #PAGE_SHIFT - 12
+#endif
+	b	sys_mmap_pgoff
+1:	mov	x0, #-EINVAL
+	ret
+ENDPROC(compat_sys_mmap2_wrapper)
+
diff --git a/arch/arm64/kernel/entry32.S b/arch/arm64/kernel/entry32.S
index f332d5d..58cb5b0 100644
--- a/arch/arm64/kernel/entry32.S
+++ b/arch/arm64/kernel/entry32.S
@@ -55,21 +55,6 @@ ENTRY(compat_sys_fstatfs64_wrapper)
 ENDPROC(compat_sys_fstatfs64_wrapper)
 
 /*
- * Note: off_4k (w5) is always in units of 4K. If we can't do the
- * requested offset because it is not page-aligned, we return -EINVAL.
- */
-ENTRY(compat_sys_mmap2_wrapper)
-#if PAGE_SHIFT > 12
-	tst	w5, #~PAGE_MASK >> 12
-	b.ne	1f
-	lsr	w5, w5, #PAGE_SHIFT - 12
-#endif
-	b	sys_mmap_pgoff
-1:	mov	x0, #-EINVAL
-	ret
-ENDPROC(compat_sys_mmap2_wrapper)
-
-/*
  * Wrappers for AArch32 syscalls that either take 64-bit parameters
  * in registers or that take 32-bit parameters which require sign
  * extension.


From khilman at baylibre.com  Sat May 14 07:45:23 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Sat, 14 May 2016 16:45:23 +0200
Subject: [RFC PATCH 2/3] dt-bindings: reset: Add bindings for the Meson
 GXBB Reset Controller
In-Reply-To: <1463148012-25988-3-git-send-email-narmstrong@baylibre.com> (Neil
 Armstrong's message of "Fri, 13 May 2016 16:00:11 +0200")
References: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>
 <1463148012-25988-3-git-send-email-narmstrong@baylibre.com>
Message-ID: <m2vb2g1yws.fsf@baylibre.com>

Neil Armstrong <narmstrong at baylibre.com> writes:

> Add DT bindings for the Meson GXBB SoC Reset Controller documentation and the
> associated include file.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>

[...]

> +#define RESET_Ethernet		19

nit: all the others are all uppercase.  This should be as well for
consistency.

Kevin


From ynorov at caviumnetworks.com  Sat May 14 08:03:52 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Sat, 14 May 2016 18:03:52 +0300
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <1459894127-17698-21-git-send-email-ynorov@caviumnetworks.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1459894127-17698-21-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <20160514150352.GA30533@yury-N73SV>

So, after all discussions, this patch is looking like this.

Changes:
 - assembler part reworked to be more clear, as Catalin recommended;
 - mmap now points to mmap2, as in 1st versions (suggested by Bamvor),
   and ilp32 wrapper delouses required arguments;
 - pread64 and pwrite64 wrappers introduced to delouse args as well;
 - removed unneeded #undefs;

Did I miss something?

diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 2971dea..5ea18ef 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -13,9 +13,18 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+
+#ifdef CONFIG_COMPAT
+#define __ARCH_WANT_COMPAT_STAT64
+#endif
+
+#ifdef CONFIG_ARM64_ILP32
+#define __ARCH_WANT_COMPAT_SYS_PREADV64
+#define __ARCH_WANT_COMPAT_SYS_PWRITEV64
+#endif
+
 #ifdef CONFIG_AARCH32_EL0
 #define __ARCH_WANT_COMPAT_SYS_GETDENTS64
-#define __ARCH_WANT_COMPAT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_GETPGRP
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 9dfdf86..7aa65ea 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -28,7 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
 					   ../../arm/kernel/opcodes.o binfmt_elf32.o
-arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
+arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index cf4d1ae..0f651bc 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -500,6 +500,7 @@ el0_svc_compat:
 	 * AArch32 syscall handling
 	 */
 	adrp	stbl, compat_sys_call_table	// load compat syscall table pointer
+	ldr     x16, [tsk, #TI_FLAGS]
 	uxtw	scno, w7			// syscall number in w7 (r7)
 	mov     sc_nr, #__NR_compat_syscalls
 	b	el0_svc_naked
@@ -716,15 +717,20 @@ ENDPROC(ret_from_fork)
 	.align	6
 el0_svc:
 	adrp	stbl, sys_call_table		// load syscall table pointer
+	ldr	x16, [tsk, #TI_FLAGS]
 	uxtw	scno, w8			// syscall number in w8
 	mov	sc_nr, #__NR_syscalls
+#ifdef CONFIG_ARM64_ILP32
+	adrp	x17, sys_call_ilp32_table	// load ilp32 syscall table pointer
+	tst	x16, #_TIF_32BIT_AARCH64
+	csel    stbl, stbl, x17, eq		// We are using ILP32
+#endif
 el0_svc_naked:					// compat entry point
 	stp	x0, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
 	enable_dbg_and_irq
 	ct_user_exit 1
 
-	ldr	x16, [tsk, #TI_FLAGS]		// check for syscall hooks
-	tst	x16, #_TIF_SYSCALL_WORK
+	tst	x16, #_TIF_SYSCALL_WORK		// check for syscall hooks
 	b.ne	__sys_trace
 	cmp     scno, sc_nr                     // check upper syscall limit
 	b.hs	ni_sys
diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
new file mode 100644
index 0000000..64db612
--- /dev/null
+++ b/arch/arm64/kernel/sys_ilp32.c
@@ -0,0 +1,84 @@
+/*
+ * AArch64- ILP32 specific system calls implementation
+ *
+ * Copyright (C) 2016 Cavium Inc.
+ * Author: Andrew Pinski <apinski at cavium.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define __SYSCALL_COMPAT
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/msg.h>
+#include <linux/export.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/compat.h>
+#include <asm-generic/syscalls.h>
+
+/* Using non-compat syscalls where necessary */
+#define compat_sys_fadvise64_64        sys_fadvise64_64
+#define compat_sys_fallocate           sys_fallocate
+#define compat_sys_ftruncate64         sys_ftruncate
+#define compat_sys_lookup_dcookie      sys_lookup_dcookie
+#define compat_sys_readahead           sys_readahead
+#define compat_sys_shmat               sys_shmat
+#define compat_sys_sync_file_range     sys_sync_file_range
+#define compat_sys_truncate64          sys_truncate
+#define sys_llseek                     sys_lseek
+
+SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
+       unsigned long, prot, unsigned long, flags, unsigned long, fd,
+       unsigned long, pgoff)
+{
+       if (pgoff & (~PAGE_MASK >> 12))
+               return -EINVAL;
+
+       return sys_mmap_pgoff((compat_uptr_t) addr, (compat_size_t) len,
+		       (int) prot, (int) flags, (int) fd,
+		       pgoff >> (PAGE_SHIFT-12));
+}
+
+COMPAT_SYSCALL_DEFINE4(pread64, unsigned int, fd, compat_uptr_t __user *, ubuf,
+		       compat_size_t, count, off_t, offset)
+{
+	return sys_pread64(fd, (char *) ubuf, count, offset);
+}
+
+COMPAT_SYSCALL_DEFINE4(pwrite64, unsigned int, fd, compat_uptr_t __user *, ubuf,
+		       compat_size_t, count, off_t, offset)
+{
+	return sys_pwrite64(fd, (char *) ubuf, count, offset);
+}
+
+#include <asm/syscall.h>
+
+#undef __SYSCALL
+#undef __SC_WRAP
+
+#define __SYSCALL(nr, sym)	[nr] = sym,
+#define __SC_WRAP(nr, sym)	[nr] = compat_##sym,
+
+/*
+ * The sys_call_ilp32_table array must be 4K aligned to be accessible from
+ * kernel/entry.S.
+ */
+void *sys_call_ilp32_table[__NR_syscalls] __aligned(4096) = {
+	[0 ... __NR_syscalls - 1] = sys_ni_syscall,
+#include <asm/unistd.h>
+};


From khilman at baylibre.com  Sat May 14 08:07:02 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Sat, 14 May 2016 17:07:02 +0200
Subject: [RFC PATCH 1/3] reset: Add support for the Amlogic Meson GXBB
 Reset Controller
In-Reply-To: <1463148012-25988-2-git-send-email-narmstrong@baylibre.com> (Neil
 Armstrong's message of "Fri, 13 May 2016 16:00:10 +0200")
References: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>
 <1463148012-25988-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <m2oa881xwp.fsf@baylibre.com>

Neil Armstrong <narmstrong at baylibre.com> writes:

> This patch adds the platform driver for the Amlogic Meson GXBB Reset
> Controller.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>

[...]

> +static int meson_gxbb_reset_assert(struct reset_controller_dev *rcdev,
> +			      unsigned long id)
> +{
> +	struct meson_gxbb_reset *data =
> +		container_of(rcdev, struct meson_gxbb_reset, rcdev);
> +	unsigned int bank = id / BITS_PER_REG;
> +	unsigned int offset = id % BITS_PER_REG;
> +	void *reg_addr = data->reg_base + (bank << 2);
> +
> +	if (bank >= REG_COUNT)
> +		return -EINVAL;
> +
> +	writel(readl(reg_addr) | BIT(offset), reg_addr);

The spec lists these registers as 16-bit registers, so probably readw/writew
are more appropriate here.

> +	return 0;
> +}
> +
> +static int meson_gxbb_reset_deassert(struct reset_controller_dev *rcdev,
> +				unsigned long id)
> +{
> +	struct meson_gxbb_reset *data =
> +		container_of(rcdev, struct meson_gxbb_reset, rcdev);
> +	unsigned int bank = id / BITS_PER_REG;
> +	unsigned int offset = id % BITS_PER_REG;
> +	void *reg_addr = data->reg_base + (bank << 2);
> +
> +	if (bank >= REG_COUNT)
> +		return -EINVAL;
> +
> +	writel(readl(reg_addr) & ~BIT(offset), reg_addr);

and here.

> +	return 0;
> +}

Kevin


From khilman at baylibre.com  Sat May 14 08:09:47 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Sat, 14 May 2016 17:09:47 +0200
Subject: [RFC PATCH 0/3] Amlogic: GXBB: Add reset controller
In-Reply-To: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com> (Neil
 Armstrong's message of "Fri, 13 May 2016 16:00:09 +0200")
References: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <m2h9e01xs4.fsf@baylibre.com>

Hi Neil,

Neil Armstrong <narmstrong at baylibre.com> writes:

> Patchset to add and enable the reset controller driver on GXBB platforms.

Looking closer at the vendor BSP reset driver, I realized that that
kernel doesn't seem to be using this reset IP at all.  Their reset
driver is actually just using clock gating in the HHI_GCLK_MPEGx
registers.

I'm not sure I understand why they made that choice (I've asked
off-list), but we'll need to keep in mind that any usage of the reset
driver in the vendor DTs corresponds do clock gating, and not this reset
IP.

In any case, other than the minor comments, this looks like a good
driver for the reset IP in the S905/GXBB.

Also, I gave this driver a quick test with the network driver support I
recently posted.  When the network driver is loaded, it deasserts the
reset and when unloaded, it asserts the reset.  Interestingly, the
assert cases a full system lockup. :(

I've asked some Amlogic folks off-list about this issue too, and hope to
get some more clarifcation (and ideally docs) about this reset IP soon.

Kevin


From khilman at baylibre.com  Sat May 14 08:11:20 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Sat, 14 May 2016 17:11:20 +0200
Subject: [RFC PATCH 0/3] Amlogic: GXBB: Add reset controller
In-Reply-To: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com> (Neil
 Armstrong's message of "Fri, 13 May 2016 16:00:09 +0200")
References: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <m2eg941xpj.fsf@baylibre.com>

Hi Neil,

Neil Armstrong <narmstrong at baylibre.com> writes:

> Patchset to add and enable the reset controller driver on GXBB platforms.

Looking closer at the vendor BSP reset driver, I realized that that
kernel doesn't seem to be using this reset IP at all.  Their reset
driver is actually just using clock gating in the HHI_GCLK_MPEGx
registers.

I'm not sure I understand why they made that choice (I've asked
off-list), but we'll need to keep in mind that any usage of the reset
driver in the vendor DTs corresponds do clock gating, and not this reset
IP.

In any case, other than the minor comments, this looks like a good
driver for the reset IP in the S905/GXBB.

Also, I gave this driver a quick test with the network driver support I
recently posted.  When the network driver is loaded, it deasserts the
reset and when unloaded, it asserts the reset.  Interestingly, the
assert cases a full system lockup. :(

I've asked some Amlogic folks off-list about this issue too, and hope to
get some more clarifcation (and ideally docs) about this reset IP soon.

Kevin


From tiwai at suse.de  Sat May 14 08:13:42 2016
From: tiwai at suse.de (Takashi Iwai)
Date: Sat, 14 May 2016 17:13:42 +0200
Subject: [RFC PATCH 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <87twi1hssl.fsf@belgarion.home>
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
 <s5hk2j38tmf.wl-tiwai@suse.de> <87twi1hssl.fsf@belgarion.home>
Message-ID: <s5hy47c7jvd.wl-tiwai@suse.de>

On Sat, 14 May 2016 11:50:50 +0200,
Robert Jarzmik wrote:
> >> +unsigned int ac97_bus_scan_one(struct ac97_controller *ac97,
> >> +				      int codec_num)
> >> +{
> >> +	struct ac97_codec_device codec;
> >> +	unsigned short vid1, vid2;
> >> +	int ret;
> >> +
> >> +	codec.dev = *ac97->dev;
> >> +	codec.num = codec_num;
> >> +	ret = ac97->ops->read(&codec, AC97_VENDOR_ID1);
> >> +	vid1 = (ret & 0xffff);
> >> +	if (ret < 0)
> >> +		return 0;
> >
> > Hmm.  This looks pretty hackish and dangerous.
> You mean returning 0 even if the read failed, right ?

No, my concern is that it's creating a dummy codec object temporarily
on the stack just by copying some fields and calling the ops with it.
(And actually the current code may work wrongly because lack of
 zero-clear of the object.)

IMO, a cleaner way would be to define the ops passed with both
controller and codec objects as arguments, and pass NULL codec here.


Takashi


From corbet at lwn.net  Sat May 14 09:15:31 2016
From: corbet at lwn.net (Jonathan Corbet)
Date: Sat, 14 May 2016 10:15:31 -0600
Subject: [PATCH -trivial 1/3] Documentation: vm: Spelling
 s/paltform/platform/g
In-Reply-To: <1462906798-27993-1-git-send-email-geert+renesas@glider.be>
References: <1462906798-27993-1-git-send-email-geert+renesas@glider.be>
Message-ID: <20160514101531.1b13c542@lwn.net>

On Tue, 10 May 2016 20:59:56 +0200
Geert Uytterhoeven <geert+renesas at glider.be> wrote:

> diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
> index 54dd9b9c6c31aeed..6f3b3fa35613d900 100644
> --- a/Documentation/vm/hugetlbpage.txt
> +++ b/Documentation/vm/hugetlbpage.txt
> @@ -275,10 +275,10 @@ This command mounts a (pseudo) filesystem of type hugetlbfs on the directory
>  options sets the owner and group of the root of the file system.  By default
>  the uid and gid of the current process are taken.  The mode option sets the
>  mode of root of file system to value & 01777.  This value is given in octal.
> -By default the value 0755 is picked. If the paltform supports multiple huge
> +By default the value 0755 is picked. If the platform supports multiple huge

Applied to the docs tree, thanks.

jon


From heiko at sntech.de  Sat May 14 10:01:23 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 14 May 2016 19:01:23 +0200
Subject: [PATCH v4 1/3] ARM64: dts: rockchip: make rk3399's grf a
 "simple-mfd"
In-Reply-To: <1463177524-113856-1-git-send-email-briannorris@chromium.org>
References: <1463177524-113856-1-git-send-email-briannorris@chromium.org>
Message-ID: <2246118.hzaJHK3UnE@phil>

Am Freitag, 13. Mai 2016, 15:12:02 schrieb Brian Norris:
> Per the examples in
> Documentation/devicetree/bindings/phy/rockchip-emmc-phy.txt, we need the
> grf node to be a simple-mfd in order to properly enumerate child devices
> like our eMMC PHY.
> 
> Signed-off-by: Brian Norris <briannorris at chromium.org>

applied all 3 for 4.8 with the received Reviews.

Please keep the arm64 lower-case and carry over already received 
Acks/Reviews (Shawn and Doug on patch2 in v2).


Thanks
Heiko


From khilman at baylibre.com  Sat May 14 10:45:54 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Sat, 14 May 2016 10:45:54 -0700
Subject: [RFC PATCH 1/3] reset: Add support for the Amlogic Meson GXBB
 Reset Controller
In-Reply-To: <1463148012-25988-2-git-send-email-narmstrong@baylibre.com> (Neil
 Armstrong's message of "Fri, 13 May 2016 16:00:10 +0200")
References: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>
 <1463148012-25988-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <7hzirsh6st.fsf@baylibre.com>

Neil Armstrong <narmstrong at baylibre.com> writes:

> This patch adds the platform driver for the Amlogic Meson GXBB Reset
> Controller.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>

[...]

> +struct meson_gxbb_reset {
> +	void *reg_base;

nit: along wit the readw/writel, this should be void __iomem *.

> +	struct reset_controller_dev rcdev;
> +};

Kevin


From hdegoede at redhat.com  Sat May 14 10:51:27 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 14 May 2016 19:51:27 +0200
Subject: [PATCH 1/3] power: axp20x_usb: Add support for usb power-supply on
 axp22x pmics
Message-ID: <1463248289-16456-1-git-send-email-hdegoede@redhat.com>

The usb power-supply on the axp22x pmics is mostly identical to the
one on the axp20x pmics. One significant difference is that it cannot
measure / monitor the usb voltage / current.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 drivers/power/axp20x_usb_power.c | 99 +++++++++++++++++++++++++++++++---------
 1 file changed, 77 insertions(+), 22 deletions(-)

diff --git a/drivers/power/axp20x_usb_power.c b/drivers/power/axp20x_usb_power.c
index 421a90b..b3c1d8e 100644
--- a/drivers/power/axp20x_usb_power.c
+++ b/drivers/power/axp20x_usb_power.c
@@ -42,6 +42,7 @@
 #define AXP20X_VBUS_MON_VBUS_VALID	BIT(3)
 
 struct axp20x_usb_power {
+	struct axp20x_dev *axp20x;
 	struct regmap *regmap;
 	struct power_supply *supply;
 };
@@ -85,7 +86,15 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
 
 		switch (v & AXP20X_VBUS_CLIMIT_MASK) {
 		case AXP20X_VBUC_CLIMIT_100mA:
-			val->intval = 100000;
+			switch (power->axp20x->variant) {
+			case AXP202_ID:
+			case AXP209_ID:
+				val->intval = 100000;
+				break;
+			default:
+				val->intval = -1; /* No 100mA limit */
+				break;
+			}
 			break;
 		case AXP20X_VBUC_CLIMIT_500mA:
 			val->intval = 500000;
@@ -122,16 +131,23 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
 			break;
 		}
 
-		ret = regmap_read(power->regmap, AXP20X_USB_OTG_STATUS, &v);
-		if (ret)
-			return ret;
+		val->intval = POWER_SUPPLY_HEALTH_GOOD;
 
-		if (!(v & AXP20X_USB_STATUS_VBUS_VALID)) {
-			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+		switch (power->axp20x->variant) {
+		case AXP202_ID:
+		case AXP209_ID:
+			ret = regmap_read(power->regmap,
+					  AXP20X_USB_OTG_STATUS, &v);
+			if (ret)
+				return ret;
+
+			if (!(v & AXP20X_USB_STATUS_VBUS_VALID))
+				val->intval =
+					POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+			break;
+		default:
 			break;
 		}
-
-		val->intval = POWER_SUPPLY_HEALTH_GOOD;
 		break;
 	case POWER_SUPPLY_PROP_PRESENT:
 		val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);
@@ -156,6 +172,14 @@ static enum power_supply_property axp20x_usb_power_properties[] = {
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 };
 
+static enum power_supply_property axp22x_usb_power_properties[] = {
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN,
+	POWER_SUPPLY_PROP_CURRENT_MAX,
+};
+
 static const struct power_supply_desc axp20x_usb_power_desc = {
 	.name = "axp20x-usb",
 	.type = POWER_SUPPLY_TYPE_USB,
@@ -164,13 +188,25 @@ static const struct power_supply_desc axp20x_usb_power_desc = {
 	.get_property = axp20x_usb_power_get_property,
 };
 
+static const struct power_supply_desc axp22x_usb_power_desc = {
+	.name = "axp20x-usb",
+	.type = POWER_SUPPLY_TYPE_USB,
+	.properties = axp22x_usb_power_properties,
+	.num_properties = ARRAY_SIZE(axp22x_usb_power_properties),
+	.get_property = axp20x_usb_power_get_property,
+};
+
 static int axp20x_usb_power_probe(struct platform_device *pdev)
 {
 	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
 	struct power_supply_config psy_cfg = {};
 	struct axp20x_usb_power *power;
-	static const char * const irq_names[] = { "VBUS_PLUGIN",
-		"VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID" };
+	static const char * const axp20x_irq_names[] = { "VBUS_PLUGIN",
+		"VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID", NULL };
+	static const char * const axp22x_irq_names[] = {
+		"VBUS_PLUGIN", "VBUS_REMOVAL", NULL };
+	static const char * const *irq_names;
+	const struct power_supply_desc *usb_power_desc;
 	int i, irq, ret;
 
 	if (!of_device_is_available(pdev->dev.of_node))
@@ -185,31 +221,50 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
 	if (!power)
 		return -ENOMEM;
 
+	power->axp20x = axp20x;
 	power->regmap = axp20x->regmap;
 
-	/* Enable vbus valid checking */
-	ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
-		    AXP20X_VBUS_MON_VBUS_VALID, AXP20X_VBUS_MON_VBUS_VALID);
-	if (ret)
-		return ret;
+	switch (power->axp20x->variant) {
+	case AXP202_ID:
+	case AXP209_ID:
+		/* Enable vbus valid checking */
+		ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
+					 AXP20X_VBUS_MON_VBUS_VALID,
+					 AXP20X_VBUS_MON_VBUS_VALID);
+		if (ret)
+			return ret;
 
-	/* Enable vbus voltage and current measurement */
-	ret = regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
+		/* Enable vbus voltage and current measurement */
+		ret = regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
 			AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT,
 			AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT);
-	if (ret)
-		return ret;
+		if (ret)
+			return ret;
+
+		usb_power_desc = &axp20x_usb_power_desc;
+		irq_names = axp20x_irq_names;
+		break;
+	case AXP221_ID:
+	case AXP223_ID:
+		usb_power_desc = &axp22x_usb_power_desc;
+		irq_names = axp22x_irq_names;
+		break;
+	default:
+		dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
+			axp20x->variant);
+		return -EINVAL;
+	}
 
 	psy_cfg.of_node = pdev->dev.of_node;
 	psy_cfg.drv_data = power;
 
-	power->supply = devm_power_supply_register(&pdev->dev,
-					&axp20x_usb_power_desc, &psy_cfg);
+	power->supply = devm_power_supply_register(&pdev->dev, usb_power_desc,
+						   &psy_cfg);
 	if (IS_ERR(power->supply))
 		return PTR_ERR(power->supply);
 
 	/* Request irqs after registering, as irqs may trigger immediately */
-	for (i = 0; i < ARRAY_SIZE(irq_names); i++) {
+	for (i = 0; irq_names[i]; i++) {
 		irq = platform_get_irq_byname(pdev, irq_names[i]);
 		if (irq < 0) {
 			dev_warn(&pdev->dev, "No IRQ for %s: %d\n",
-- 
2.7.4



From hdegoede at redhat.com  Sat May 14 10:51:28 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 14 May 2016 19:51:28 +0200
Subject: [PATCH 2/3] mfd: axp20x: Extend axp22x_volatile_ranges
In-Reply-To: <1463248289-16456-1-git-send-email-hdegoede@redhat.com>
References: <1463248289-16456-1-git-send-email-hdegoede@redhat.com>
Message-ID: <1463248289-16456-2-git-send-email-hdegoede@redhat.com>

The axp22x pmic has a bunch of volatile registers besides the interrupt
ones, extend axp22x_volatile_ranges with these.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 drivers/mfd/axp20x.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index e4e3297..ca04361 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -93,7 +93,10 @@ static const struct regmap_range axp22x_writeable_ranges[] = {
 };
 
 static const struct regmap_range axp22x_volatile_ranges[] = {
+	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
 	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
+	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
+	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
 };
 
 static const struct regmap_access_table axp22x_writeable_table = {
-- 
2.7.4



From hdegoede at redhat.com  Sat May 14 10:51:29 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 14 May 2016 19:51:29 +0200
Subject: [PATCH 3/3] mfd: axp20x: Add axp20x-usb-power-supply for axp22x pmics
In-Reply-To: <1463248289-16456-1-git-send-email-hdegoede@redhat.com>
References: <1463248289-16456-1-git-send-email-hdegoede@redhat.com>
Message-ID: <1463248289-16456-3-git-send-email-hdegoede@redhat.com>

Add axp20x-usb-power-supply for axp22x pmics.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 drivers/mfd/axp20x.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index ca04361..d62209d 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -160,6 +160,11 @@ static struct resource axp20x_usb_power_supply_resources[] = {
 	DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"),
 };
 
+static struct resource axp22x_usb_power_supply_resources[] = {
+	DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
+	DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
+};
+
 static struct resource axp22x_pek_resources[] = {
 	{
 		.name   = "PEK_DBR",
@@ -527,6 +532,11 @@ static struct mfd_cell axp22x_cells[] = {
 		.resources		= axp22x_pek_resources,
 	}, {
 		.name			= "axp20x-regulator",
+	}, {
+		.name		= "axp20x-usb-power-supply",
+		.of_compatible	= "x-powers,axp202-usb-power-supply",
+		.num_resources	= ARRAY_SIZE(axp22x_usb_power_supply_resources),
+		.resources	= axp22x_usb_power_supply_resources,
 	},
 };
 
-- 
2.7.4



From hdegoede at redhat.com  Sat May 14 10:55:45 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 14 May 2016 19:55:45 +0200
Subject: [PATCH] regulator: axp20x: Add support for the (external) drivebus
 regulator
Message-ID: <1463248545-16543-1-git-send-email-hdegoede@redhat.com>

The axp20x pmics have 2 power inputs, one called ACIN which is intended
for to be supplied via a powerbarrel on the board and one called VBUS
which is intended to be supplied via an otg connector.

In the VBUS case the pmic needs to know if the board is supplying power
to the otg connector, because then it should not take any power from
its VBUS pin. The axp209 pmic has a N_VBUSEN input pin via which the
board can signal to the pmic whether the board is supplying power to the
otg connector or not.

On the axp221/axp223 this pin can alternatively be used as an output
which controls an external regulator which (optionally) supplies
power to the otg connector from the board. When the pin is used as
output it is called DRIVEBUS in the datasheet.

This commit adds support for the DRIVEBUS pin as an extra pmic
controlled regulator. Since this is optional a new x-powers,drivebus dt
property is added. When this is present the misc-control register is
written to change the N_VBUSEN input pin to DRIVEBUS output pin mode and
the extra drivebus regulator is registered with the regulator subsystem.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 Documentation/devicetree/bindings/mfd/axp20x.txt |  5 ++++
 drivers/regulator/axp20x-regulator.c             | 30 ++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
index d20b103..7a88479 100644
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
@@ -22,6 +22,11 @@ Optional properties:
 		      AXP152/20X: range:  750-1875, Default: 1.5 MHz
 		      AXP22X/80X: range: 1800-4050, Default: 3   MHz
 
+- x-powers,drivebus: axp221 / axp223 only boolean, set this when the N_VBUSEN
+                  pin is used as an output pin to control an external regulator
+                  to drive the OTG VBus, rather then as an input pin which
+                  signals whether the board is driving OTG VBus or not.
+
 - <input>-supply: a phandle to the regulator supply node. May be omitted if
 		  inputs are unregulated, such as using the IPSOUT output
 		  from the PMIC.
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 514a5e8..2422ddd 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -36,6 +36,8 @@
 
 #define AXP20X_FREQ_DCDC_MASK		0x0f
 
+#define AXP22X_MISC_N_VBUSEN_FUNC	BIT(4)
+
 #define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,	\
 		    _vmask, _ereg, _emask, _enable_val, _disable_val)		\
 	[_family##_##_id] = {							\
@@ -230,6 +232,18 @@ static const struct regulator_desc axp22x_regulators[] = {
 	AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
 };
 
+static const struct regulator_desc axp22x_drivebus_regulator = {
+	.name		= "drivebus",
+	.supply_name	= "ips",
+	.of_match	= of_match_ptr("drivebus"),
+	.regulators_node = of_match_ptr("regulators"),
+	.type		= REGULATOR_VOLTAGE,
+	.owner		= THIS_MODULE,
+	.enable_reg	= AXP20X_VBUS_IPSOUT_MGMT,
+	.enable_mask	= BIT(2),
+	.ops		= &axp20x_ops_sw,
+};
+
 static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
 {
 	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
@@ -354,6 +368,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 	u32 workmode;
 	const char *axp22x_dc1_name = axp22x_regulators[AXP22X_DCDC1].name;
 	const char *axp22x_dc5_name = axp22x_regulators[AXP22X_DCDC5].name;
+	bool drivebus = false;
 
 	switch (axp20x->variant) {
 	case AXP202_ID:
@@ -365,6 +380,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 	case AXP223_ID:
 		regulators = axp22x_regulators;
 		nregulators = AXP22X_REG_ID_MAX;
+		drivebus = of_property_read_bool(pdev->dev.parent->of_node,
+						 "x-powers,drivebus");
 		break;
 	default:
 		dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
@@ -439,6 +456,19 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		}
 	}
 
+	if (drivebus) {
+		/* Change N_VBUSEN sense pin to DRIVEBUS output pin */
+		regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP,
+				   AXP22X_MISC_N_VBUSEN_FUNC, 0);
+		rdev = devm_regulator_register(&pdev->dev,
+					       &axp22x_drivebus_regulator,
+					       &config);
+		if (IS_ERR(rdev)) {
+			dev_err(&pdev->dev, "Failed to register drivebus\n");
+			return PTR_ERR(rdev);
+		}
+	}
+
 	return 0;
 }
 
-- 
2.7.4



From hdegoede at redhat.com  Sat May 14 10:57:28 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 14 May 2016 19:57:28 +0200
Subject: [PATCH 2/4] ARM: dts: axp22x.dtsi: Add usb_power_supply node
In-Reply-To: <1463248650-16611-1-git-send-email-hdegoede@redhat.com>
References: <1463248650-16611-1-git-send-email-hdegoede@redhat.com>
Message-ID: <1463248650-16611-2-git-send-email-hdegoede@redhat.com>

Add a node describing the (optional) usbpower-supply of the
axp221 / axp223 pmic.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 arch/arm/boot/dts/axp22x.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/axp22x.dtsi b/arch/arm/boot/dts/axp22x.dtsi
index 0cfec50..cbafca6 100644
--- a/arch/arm/boot/dts/axp22x.dtsi
+++ b/arch/arm/boot/dts/axp22x.dtsi
@@ -142,4 +142,9 @@
 			regulator-name = "rtc_ldo";
 		};
 	};
+
+	usb_power_supply: usb_power_supply {
+		compatible = "x-powers,axp202-usb-power-supply";
+		status = "disabled";
+	};
 };
-- 
2.7.4



From hdegoede at redhat.com  Sat May 14 10:57:27 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 14 May 2016 19:57:27 +0200
Subject: [PATCH 1/4] ARM: dts: axp22x.dtsi: Disable axp22x ldo_io# regulators
 by default
Message-ID: <1463248650-16611-1-git-send-email-hdegoede@redhat.com>

Use of these as regulators conflicts with use of the gpio pins as
gpios, so disabled the ldo_io# regulators by default, this avoids
the regulator core touching them when the pins are used as gpios.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 arch/arm/boot/dts/axp22x.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/axp22x.dtsi b/arch/arm/boot/dts/axp22x.dtsi
index 76302f5..0cfec50 100644
--- a/arch/arm/boot/dts/axp22x.dtsi
+++ b/arch/arm/boot/dts/axp22x.dtsi
@@ -126,10 +126,12 @@
 
 		reg_ldo_io0: ldo_io0 {
 			regulator-name = "ldo_io0";
+			status = "disabled";
 		};
 
 		reg_ldo_io1: ldo_io1 {
 			regulator-name = "ldo_io1";
+			status = "disabled";
 		};
 
 		reg_rtc_ldo: rtc_ldo {
-- 
2.7.4



From hdegoede at redhat.com  Sat May 14 10:57:29 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 14 May 2016 19:57:29 +0200
Subject: [PATCH 3/4] ARM: dts: axp22x.dtsi: Add reg_drivebus node
In-Reply-To: <1463248650-16611-1-git-send-email-hdegoede@redhat.com>
References: <1463248650-16611-1-git-send-email-hdegoede@redhat.com>
Message-ID: <1463248650-16611-3-git-send-email-hdegoede@redhat.com>

Add a node describing the drivebus regulator which is an (optional)
part of the axp221/axp223 pmic. Since this regulator may not be
available at all depending on the board, mark it as disabled by
default.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 arch/arm/boot/dts/axp22x.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/axp22x.dtsi b/arch/arm/boot/dts/axp22x.dtsi
index cbafca6..6903d471 100644
--- a/arch/arm/boot/dts/axp22x.dtsi
+++ b/arch/arm/boot/dts/axp22x.dtsi
@@ -141,6 +141,11 @@
 			regulator-max-microvolt = <3000000>;
 			regulator-name = "rtc_ldo";
 		};
+
+		reg_drivebus: drivebus {
+			regulator-name = "drivebus";
+			status = "disabled";
+		};
 	};
 
 	usb_power_supply: usb_power_supply {
-- 
2.7.4



From hdegoede at redhat.com  Sat May 14 10:57:30 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 14 May 2016 19:57:30 +0200
Subject: [PATCH 4/4] ARM: dts: sun8i-a?3-q8-tablet.dts: Add full otg support
In-Reply-To: <1463248650-16611-1-git-send-email-hdegoede@redhat.com>
References: <1463248650-16611-1-git-send-email-hdegoede@redhat.com>
Message-ID: <1463248650-16611-4-git-send-email-hdegoede@redhat.com>

Now that we've all the necessary bits in place we can enable
full otg support on these tablets.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 arch/arm/boot/dts/sun8i-a23-q8-tablet.dts | 15 ---------------
 arch/arm/boot/dts/sun8i-a33-q8-tablet.dts | 15 ---------------
 arch/arm/boot/dts/sun8i-q8-common.dtsi    | 31 +++++++++++++++++++++++++++++++
 3 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts b/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts
index 6062ea7..956320a 100644
--- a/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts
+++ b/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts
@@ -48,18 +48,3 @@
 	model = "Q8 A23 Tablet";
 	compatible = "allwinner,q8-a23", "allwinner,sun8i-a23";
 };
-
-/*
- * FIXME for now we only support host mode and rely on u-boot to have
- * turned on Vbus which is controlled by the axp223 pmic on the board.
- *
- * Once we have axp223 support we should switch to fully supporting otg.
- */
-&usb_otg {
-	dr_mode = "host";
-	status = "okay";
-};
-
-&usbphy {
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/sun8i-a33-q8-tablet.dts b/arch/arm/boot/dts/sun8i-a33-q8-tablet.dts
index 44b3229..b0bc236 100644
--- a/arch/arm/boot/dts/sun8i-a33-q8-tablet.dts
+++ b/arch/arm/boot/dts/sun8i-a33-q8-tablet.dts
@@ -48,18 +48,3 @@
 	model = "Q8 A33 Tablet";
 	compatible = "allwinner,q8-a33", "allwinner,sun8i-a33";
 };
-
-/*
- * FIXME for now we only support host mode and rely on u-boot to have
- * turned on Vbus which is controlled by the axp223 pmic on the board.
- *
- * Once we have axp223 support we should switch to fully supporting otg.
- */
-&usb_otg {
-	dr_mode = "host";
-	status = "okay";
-};
-
-&usbphy {
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/sun8i-q8-common.dtsi b/arch/arm/boot/dts/sun8i-q8-common.dtsi
index 346a49d..2e2cbf5 100644
--- a/arch/arm/boot/dts/sun8i-q8-common.dtsi
+++ b/arch/arm/boot/dts/sun8i-q8-common.dtsi
@@ -87,6 +87,13 @@
 		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
 	};
+
+	usb0_id_detect_pin: usb0_id_detect_pin at 0 {
+		allwinner,pins = "PH8";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+	};
 };
 
 &r_rsb {
@@ -98,6 +105,7 @@
 		interrupt-parent = <&nmi_intc>;
 		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
 		eldoin-supply = <&reg_dcdc1>;
+		x-powers,drivebus;
 	};
 };
 
@@ -163,6 +171,11 @@
 	regulator-name = "vcc-dram";
 };
 
+&reg_drivebus {
+	regulator-name = "usb0-vbus";
+	status = "okay";
+};
+
 &reg_rtc_ldo {
 	regulator-name = "vcc-rtc";
 };
@@ -176,3 +189,21 @@
 &simplefb_lcd {
 	vcc-lcd-supply = <&reg_dc1sw>;
 };
+
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usb_power_supply {
+	status = "okay";
+};
+
+&usbphy {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb0_id_detect_pin>;
+	usb0_id_det-gpio = <&pio 7 8 GPIO_ACTIVE_HIGH>; /* PH8 */
+	usb0_vbus_power-supply = <&usb_power_supply>;
+	usb0_vbus-supply = <&reg_drivebus>;
+	status = "okay";
+};
-- 
2.7.4



From matt at codeblueprint.co.uk  Sat May 14 12:04:10 2016
From: matt at codeblueprint.co.uk (Matt Fleming)
Date: Sat, 14 May 2016 20:04:10 +0100
Subject: [GIT PULL] EFI ARM Xen support
Message-ID: <20160514190410.GA2283@codeblueprint.co.uk>

Folks,

Please pull the following branch which contains support for Xen on ARM
EFI platforms.

This merge includes a merge of Stefano's xen/linux-next branch to pull
in the prerequisites required for Shannon's commit:

  11ee5491e5ff ("Xen: EFI: Parse DT parameters for Xen specific UEFI")

as it needs both the latest changes in the EFI 'next' branch (now
tip/efi/core) and xen/linux-next.

I have intentionally not included the individual patches as I would
normally do in a pull request, so that commit history created by my
merging of Stefano's branch is preserved, and so that there's no way
to accidentally apply the patches individually.

The following changes since commit 6c5450ef66816216e574885cf8d3ddb31ef77428:

  efivarfs: Make efivarfs_file_ioctl() static (2016-05-07 07:06:13 +0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git efi/arm-xen

for you to fetch changes up to 11ee5491e5ff519e0d3a7018eb21351cb6955a98:

  Xen: EFI: Parse DT parameters for Xen specific UEFI (2016-05-14 19:31:01 +0100)

----------------------------------------------------------------
David Vrabel (1):
      xen/gntdev: reduce copy batch size to 16

Matt Fleming (1):
      Merge branch 'xen/linux-next' into efi/arm-xen

Shannon Zhao (16):
      Xen: ACPI: Hide UART used by Xen
      xen/grant-table: Move xlated_setup_gnttab_pages to common place
      Xen: xlate: Use page_to_xen_pfn instead of page_to_pfn
      arm/xen: Use xen_xlate_map_ballooned_pages to setup grant table
      xen: memory : Add new XENMAPSPACE type XENMAPSPACE_dev_mmio
      Xen: ARM: Add support for mapping platform device mmio
      Xen: ARM: Add support for mapping AMBA device mmio
      Xen: public/hvm: sync changes of HVM_PARAM_CALLBACK_VIA ABI from Xen
      xen/hvm/params: Add a new delivery type for event-channel in HVM_PARAM_CALLBACK_IRQ
      arm/xen: Get event-channel irq through HVM_PARAM when booting with ACPI
      ARM: XEN: Move xen_early_init() before efi_init()
      ARM: Xen: Document UEFI support on Xen ARM virtual platforms
      XEN: EFI: Move x86 specific codes to architecture directory
      ARM64: XEN: Add a function to initialize Xen specific UEFI runtime services
      FDT: Add a helper to get the subnode by given name
      Xen: EFI: Parse DT parameters for Xen specific UEFI

Stefano Stabellini (1):
      xen/x86: don't lose event interrupts

 Documentation/devicetree/bindings/arm/xen.txt |  35 +++++
 arch/arm/include/asm/xen/xen-ops.h            |   6 +
 arch/arm/kernel/setup.c                       |   2 +-
 arch/arm/xen/Makefile                         |   1 +
 arch/arm/xen/efi.c                            |  40 ++++++
 arch/arm/xen/enlighten.c                      | 125 ++++++++++++----
 arch/arm64/include/asm/xen/xen-ops.h          |   6 +
 arch/arm64/kernel/setup.c                     |   2 +-
 arch/arm64/xen/Makefile                       |   1 +
 arch/x86/xen/efi.c                            | 111 +++++++++++++++
 arch/x86/xen/grant-table.c                    |  57 +-------
 arch/x86/xen/time.c                           |   6 +-
 drivers/acpi/scan.c                           |  74 ++++++++++
 drivers/firmware/efi/arm-runtime.c            |   5 +
 drivers/firmware/efi/efi.c                    |  81 ++++++++---
 drivers/of/fdt.c                              |  13 ++
 drivers/xen/Kconfig                           |   2 +-
 drivers/xen/Makefile                          |   1 +
 drivers/xen/arm-device.c                      | 196 ++++++++++++++++++++++++++
 drivers/xen/efi.c                             | 173 +++++------------------
 drivers/xen/gntdev.c                          |   2 +-
 drivers/xen/xlate_mmu.c                       |  77 ++++++++++
 include/linux/of_fdt.h                        |   2 +
 include/xen/interface/hvm/params.h            |  40 +++++-
 include/xen/interface/memory.h                |   1 +
 include/xen/xen-ops.h                         |  32 +++--
 26 files changed, 840 insertions(+), 251 deletions(-)
 create mode 100644 arch/arm/include/asm/xen/xen-ops.h
 create mode 100644 arch/arm/xen/efi.c
 create mode 100644 arch/arm64/include/asm/xen/xen-ops.h
 create mode 100644 drivers/xen/arm-device.c


From pthomas8589 at gmail.com  Sat May 14 12:11:21 2016
From: pthomas8589 at gmail.com (Paul Thomas)
Date: Sat, 14 May 2016 15:11:21 -0400
Subject: [PATCH v4 3/5] dmaengine: vdma: Add Support for Xilinx AXI Direct
 Memory Access Engine
In-Reply-To: <C246CAC1457055469EF09E3A7AC4E11A4A5813F2@XAP-PVEXMBX01.xlnx.xilinx.com>
References: <1460006985-14805-1-git-send-email-appanad@xilinx.com>
 <1460006985-14805-4-git-send-email-appanad@xilinx.com>
 <CAD56B7fQWeDZDtKz2BgzpWSCMVdAGyUTBjUiuVnZ_8j51-SpoA@mail.gmail.com>
 <C246CAC1457055469EF09E3A7AC4E11A4A5813F2@XAP-PVEXMBX01.xlnx.xilinx.com>
Message-ID: <CAD56B7emtyPjHRXRoDPYORLCM5i5ZE5dW-B6rqkHpv7SF4KJrg@mail.gmail.com>

On Fri, May 13, 2016 at 12:36 AM, Appana Durga Kedareswara Rao
<appana.durga.rao at xilinx.com> wrote:
> Hi Paul,
>
>>
>> Nice Kedar!
>>
>> Is this getting applied? I would really like to see this get into the mainline.
>
> This patch got applied to the dma-next branch...
> Here @ http://git.kernel.org/cgit/linux/kernel/git/vkoul/slave-dma.git/log/?h=next
>
> Thanks,
> Kedar.
>

I see, thanks!

-Paul


From arnd at arndb.de  Sat May 14 12:47:11 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Sat, 14 May 2016 21:47:11 +0200
Subject: QRTR merge conflict resolution (was: Re: linux-next: build
 failure after merge of the net-next tree)
In-Reply-To: <CAPBZ5Qfa+b1LLgqpxfKGysY5jXVrzmBzhga=ZYtpdDAKC9hnTQ@mail.gmail.com>
References: <20160510112905.5bffcad8@canb.auug.org.au>
 <20160513221909.GC1256@tuxbot>
 <CAPBZ5Qfa+b1LLgqpxfKGysY5jXVrzmBzhga=ZYtpdDAKC9hnTQ@mail.gmail.com>
Message-ID: <3145757.u11669EZop@wuerfel>

On Friday 13 May 2016 17:47:17 Andy Gross wrote:
> On 13 May 2016 at 17:19, Bjorn Andersson <bjorn.andersson at linaro.org> wrote:
> > On Fri 13 May 14:01 PDT 2016, Arnd Bergmann wrote:
> >
> >> On Tuesday 10 May 2016 11:39:34 Bjorn Andersson wrote:
> > [..]
> >> > I assume we could have the QRTR go through Andy and arm-soc, with
> >> > David's approval and this fix squashed in. But we're running rather late
> >> > in this cycle, perhaps we should just back the QRTR patches out and I
> >> > can respin and resend them after the merge window (for v4.8 instead)?
> >>
> >> I'd suggest you do a merge of next-next with the qcom/soc-2 branch that
> >> we have in arm-soc and resolve the conflict in the merge, then send
> >> a pull request with the merge to davem.
> >>
> >
> > Hi David,
> >
> > In case you missed this thread, linux-next highlighted an upcoming merge
> > conflict between the net-next and one of the branches included in the
> > arm-soc trees.
> >
> > I have prepared the merge of net-next and the conflicting tag from the
> > Qualcomm SOC, please include this in your pull towards Linus to avoid
> > the merge conflict.
> >
> > Regards,
> > Bjorn
> >
> > The following changes since commit ed7cbbce544856b20e5811de373cf92e92499771:
> >
> >   udp: Resolve NULL pointer dereference over flow-based vxlan device (2016-05-13 01:56:14 -0400)
> 
> 
> OK. The contents look good to me.
> 
> Acked-by: Andy Gross <andy.gross at linaro.org>

Acked-by: Arnd Bergmann <arnd at arndb.de>


From davem at davemloft.net  Sat May 14 13:12:06 2016
From: davem at davemloft.net (David Miller)
Date: Sat, 14 May 2016 16:12:06 -0400 (EDT)
Subject: [PATCH] arm64: bpf: jit JMP_JSET_{X,K}
In-Reply-To: <20160513100307.GC13689@arm.com>
References: <1463121478-18484-1-git-send-email-zlim.lnx@gmail.com>
 <20160513095718.GB13689@arm.com> <20160513100307.GC13689@arm.com>
Message-ID: <20160514.161206.373725987038622109.davem@davemloft.net>

From: Will Deacon <will.deacon at arm.com>
Date: Fri, 13 May 2016 11:03:07 +0100

> On Fri, May 13, 2016 at 10:57:18AM +0100, Will Deacon wrote:
>> On Thu, May 12, 2016 at 11:37:58PM -0700, Zi Shen Lim wrote:
>> > Original implementation commit e54bcde3d69d ("arm64: eBPF JIT compiler")
>> > had the relevant code paths, but due to an oversight always fail jiting.
>> > 
>> > As a result, we had been falling back to BPF interpreter whenever a BPF
>> > program has JMP_JSET_{X,K} instructions.
>> > 
>> > With this fix, we confirm that the corresponding tests in lib/test_bpf
>> > continue to pass, and also jited.
>> > 
>> > ...
>> > [    2.784553] test_bpf: #30 JSET jited:1 188 192 197 PASS
>> > [    2.791373] test_bpf: #31 tcpdump port 22 jited:1 325 677 625 PASS
>> > [    2.808800] test_bpf: #32 tcpdump complex jited:1 323 731 991 PASS
>> > ...
>> > [    3.190759] test_bpf: #237 JMP_JSET_K: if (0x3 & 0x2) return 1 jited:1 110 PASS
>> > [    3.192524] test_bpf: #238 JMP_JSET_K: if (0x3 & 0xffffffff) return 1 jited:1 98 PASS
>> > [    3.211014] test_bpf: #249 JMP_JSET_X: if (0x3 & 0x2) return 1 jited:1 120 PASS
>> > [    3.212973] test_bpf: #250 JMP_JSET_X: if (0x3 & 0xffffffff) return 1 jited:1 89 PASS
>> > ...
>> > 
>> > Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler")
>> > Signed-off-by: Zi Shen Lim <zlim.lnx at gmail.com>
 ...
> Acked-by: Will Deacon <will.deacon at arm.com>
> 
> I'm assuming David will queue this?

Yep I got this, applied, thanks.


From heiko at sntech.de  Sat May 14 13:19:43 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 14 May 2016 22:19:43 +0200
Subject: [PATCH] iommu/rockchip: fix zap cache during device attach
In-Reply-To: <20160510155046.24515-1-john@metanate.com>
References: <20160510155046.24515-1-john@metanate.com>
Message-ID: <11003810.ccjcAXkzhi@phil>

Am Dienstag, 10. Mai 2016, 16:50:46 schrieb John Keeping:
> rk_iommu_command() takes a struct rk_iommu and iterates over the slave
> MMUs, so this is doubly wrong in that we're passing in the wrong pointer
> and talking to MMUs that we shouldn't be.
> 
> Fixes: cd6438c5f844 ("iommu/rockchip: Reconstruct to support multi
> slaves") Signed-off-by: John Keeping <john at metanate.com>

on a rk3288-veyron
Tested-by: Heiko Stuebner <heiko at sntech.de>
Reviewed-by: Heiko Stuebner <heiko at sntech.de>

I was wondering for a short time why this didn't spew warnings until I 
realized that the iommu->bases[i] is of course a void* .


Heiko


From linux at roeck-us.net  Sat May 14 14:34:50 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Sat, 14 May 2016 14:34:50 -0700
Subject: [PATCH v2 2/2] watchdog: Add Aspeed watchdog driver
In-Reply-To: <1463062631-16432-3-git-send-email-joel@jms.id.au>
References: <1462797277-14969-1-git-send-email-joel@jms.id.au>
 <1463062631-16432-1-git-send-email-joel@jms.id.au>
 <1463062631-16432-3-git-send-email-joel@jms.id.au>
Message-ID: <573799FA.7090207@roeck-us.net>

On 05/12/2016 07:17 AM, Joel Stanley wrote:
> Provides generic watchdog features as well as reboot support for the
> Apeed SoC.
>
> Signed-off-by: Joel Stanley <joel at jms.id.au>
> ---
>   drivers/watchdog/Kconfig      |  13 +++
>   drivers/watchdog/Makefile     |   1 +
>   drivers/watchdog/aspeed_wdt.c | 209 ++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 223 insertions(+)
>   create mode 100644 drivers/watchdog/aspeed_wdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index fb947655badd..4f0e2ded4785 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -661,6 +661,19 @@ config ATLAS7_WATCHDOG
>   	  To compile this driver as a module, choose M here: the
>   	  module will be called atlas7_wdt.
>
> +config ASPEED_WATCHDOG
> +	tristate "Aspeed watchdog support"
> +	depends on ARCH_ASPEED || COMPILE_TEST
> +	select WATCHDOG_CORE
> +	help
> +	  Say Y here to include support for the watchdog timer
> +	  in Apseed BMC SoCs.
> +
> +	  This driver is required to reboot the SoC.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called aspeed_wdt.
> +
>   # AVR32 Architecture
>
>   config AT32AP700X_WDT
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index feb6270fdbde..36855375e0ce 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -73,6 +73,7 @@ obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
>   obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
>   obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
>   obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o
> +obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o
>
>   # AVR32 Architecture
>   obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
> diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
> new file mode 100644
> index 000000000000..f7ae41ef4121
> --- /dev/null
> +++ b/drivers/watchdog/aspeed_wdt.c
> @@ -0,0 +1,209 @@
> +/*
> + * Copyright 2016 IBM Corporation
> + *
> + * Joel Stanley <joel at jms.id.au>
> + *
> + * Based on the qcom-watchdog driver
> + *
> + * 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.
> + */
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/watchdog.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +
> +struct aspeed_wdt {
> +	struct watchdog_device	wdd;
> +	unsigned long		rate;

I still don't see why you need this variable. Why not just use
WDT_1MHZ_CLOCK directly ?

> +	void __iomem		*base;
> +	u32			ctrl;
> +};
> +
> +static const struct of_device_id aspeed_wdt_of_table[] = {
> +	{ .compatible = "aspeed,ast2400-wdt" },
> +	{ .compatible = "aspeed,ast2500-wdt" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
> +
> +#define WDT_STATUS		0x00
> +#define WDT_RELOAD_VALUE	0x04
> +#define WDT_RESTART		0x08
> +#define WDT_CTRL		0x0C
> +#define   WDT_CTRL_RESET_MODE_SOC	(0x00 << 5)
> +#define   WDT_CTRL_RESET_MODE_FULL_CHIP	(0x01 << 5)
> +#define   WDT_CTRL_1MHZ_CLK		BIT(4)
> +#define   WDT_CTRL_WDT_EXT		BIT(3)
> +#define   WDT_CTRL_WDT_INTR		BIT(2)
> +#define   WDT_CTRL_RESET_SYSTEM		BIT(1)
> +#define   WDT_CTRL_ENABLE		BIT(0)
> +
> +#define WDT_RESTART_MAGIC	0x4755
> +
> +#define WDT_MIN_TIMEOUT		1
> +/* 32 bits at 1MHz, in milliseconds */
> +#define WDT_MAX_TIMEOUT_MS	4294967
> +#define WDT_DEFAULT_TIMEOUT	30
> +#define WDT_1MHZ_CLOCK		1000000
> +
> +static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd)
> +{
> +	return container_of(wdd, struct aspeed_wdt, wdd);
> +}
> +
> +static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
> +{
> +	wdt->ctrl |= WDT_CTRL_ENABLE;
> +
> +	writel(0, wdt->base + WDT_CTRL);
> +	writel(count, wdt->base + WDT_RELOAD_VALUE);
> +	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
> +	writel(wdt->ctrl, wdt->base + WDT_CTRL);
> +}
> +
> +static int aspeed_wdt_start(struct watchdog_device *wdd)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +
> +	aspeed_wdt_enable(wdt, wdd->timeout * wdt->rate);
> +
> +	return 0;
> +}
> +
> +static int aspeed_wdt_stop(struct watchdog_device *wdd)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +
> +	wdt->ctrl &= ~WDT_CTRL_ENABLE;
> +	writel(wdt->ctrl, wdt->base + WDT_CTRL);
> +
> +	return 0;
> +}
> +
> +static int aspeed_wdt_ping(struct watchdog_device *wdd)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +
> +	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
> +
> +	return 0;
> +}
> +
> +static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
> +				  unsigned int timeout)
> +{
> +	wdd->timeout = timeout;
> +
> +	return aspeed_wdt_start(wdd);

The watchdog can be stopped here (with WDIOC_SETOPTIONS/WDIOS_DISABLECARD).
An implicit enable is not really a good idea; neither the infrastructure
nor user space would in this case be aware that the watchdog is running.

> +}
> +
> +static int aspeed_wdt_restart(struct watchdog_device *wdd,
> +			      unsigned long action, void *data)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +
> +	aspeed_wdt_enable(wdt, 128 * wdt->rate / 1000);
> +

Is that the smallest accepted value, or is there some other reason
not to make it smaller ?

It is also quite common to wait here to let the reset 'catch'
before returning. This would ensure that the system doesn't trigger
a lower priority reset.

> +	return 0;
> +}
> +
> +static const struct watchdog_ops aspeed_wdt_ops = {
> +	.start		= aspeed_wdt_start,
> +	.stop		= aspeed_wdt_stop,
> +	.ping		= aspeed_wdt_ping,
> +	.set_timeout	= aspeed_wdt_set_timeout,
> +	.restart	= aspeed_wdt_restart,
> +	.owner		= THIS_MODULE,
> +};
> +
> +static const struct watchdog_info aspeed_wdt_info = {
> +	.options	= WDIOF_KEEPALIVEPING
> +			| WDIOF_MAGICCLOSE
> +			| WDIOF_SETTIMEOUT,
> +	.identity	= KBUILD_MODNAME,
> +};
> +
> +static int aspeed_wdt_remove(struct platform_device *pdev)
> +{
> +	struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
> +
> +	watchdog_unregister_device(&wdt->wdd);
> +
> +	return 0;
> +}
> +
> +static int aspeed_wdt_probe(struct platform_device *pdev)
> +{
> +	struct aspeed_wdt *wdt;
> +	struct resource *res;
> +	int ret;
> +
> +	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
> +	if (!wdt)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	wdt->base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(wdt->base))
> +		return PTR_ERR(wdt->base);
> +
> +	/*
> +	 * The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only
> +	 * runs at 1MHz. We chose to always run at 1MHz, as there's no
> +	 * good reason to have a faster watchdog counter.
> +	 */
> +	wdt->rate = WDT_1MHZ_CLOCK;
> +	wdt->wdd.info = &aspeed_wdt_info;
> +	wdt->wdd.ops = &aspeed_wdt_ops;
> +	wdt->wdd.min_timeout = WDT_MIN_TIMEOUT;
> +	wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS;
> +	wdt->wdd.parent = &pdev->dev;
> +
> +	wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT;
> +	watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
> +
> +	/*
> +	 * Control reset on a per-device basis to ensure the
> +	 * host is not affected by a BMC reboot, so only reset
> +	 * the SOC and not the full chip
> +	 */
> +	wdt->ctrl = WDT_CTRL_RESET_MODE_SOC |
> +		WDT_CTRL_1MHZ_CLK |
> +		WDT_CTRL_RESET_SYSTEM;
> +
> +	if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_ENABLE)  {
> +		aspeed_wdt_start(&wdt->wdd);
> +		set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
> +	}
> +
> +	ret = watchdog_register_device(&wdt->wdd);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to register\n");
> +		return ret;
> +	}
> +
> +	dev_info(&pdev->dev, "rate %lu, max timeout %u, timeout %d\n",
> +		 wdt->rate, wdt->wdd.max_timeout, wdt->wdd.timeout);
> +

'rate 1000000' doesn't seem very informative. All it does is to expose
an implementation detail which no one really cares about. Even if you
were to add 'Hz', I would argue that no one will even understand
what it means without looking into the driver, but then it will be
understood without the message.

> +	platform_set_drvdata(pdev, wdt);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver aspeed_watchdog_driver = {
> +	.probe = aspeed_wdt_probe,
> +	.remove = aspeed_wdt_remove,
> +	.driver = {
> +		.name = KBUILD_MODNAME,
> +		.of_match_table = of_match_ptr(aspeed_wdt_of_table),
> +	},
> +};
> +module_platform_driver(aspeed_watchdog_driver);
> +
> +MODULE_DESCRIPTION("Aspeed Watchdog Driver");
> +MODULE_LICENSE("GPL");
>



From zajec5 at gmail.com  Sat May 14 15:44:35 2016
From: zajec5 at gmail.com (=?UTF-8?B?UmFmYcWCIE1pxYJlY2tp?=)
Date: Sun, 15 May 2016 00:44:35 +0200
Subject: Unclear BSD licensing (headers, MODULE_LICENSE, versions)
Message-ID: <CACna6ryZS1Q8=kBMMePAE_A377OReaYJdx8azZBrqG2jG+eMJg@mail.gmail.com>

Hi,

I recently received a hint that it would be nice/expected to have DTS
files licensed under BSD. I had no experience with BSD, so I started
looking at this and the way kernel parts use it.

Obviously Linux kernel is licensed under GPLv2, so all its code has to
use GPLv2 compatible license. I found 3 BSD licenses in use by kernel
code:
1) BSD 3-clause license
2) BSD 2-clause license
3) Clear BSD license

Unfortunately in many cases (of source files) I wasn't able to clearly
determine used BSD license.

First of all, an accepted ident "Dual BSD/GPL" doesn't specify BSD
version. All I can read in include/linux/module.h is "[GNU Public
License v2 or BSD license choice]". It could mean any (of GPLv2
compatible) BSD versions.


I guess ideally (in current situation) every file using "Dual BSD/GPL"
should specify BSD license version in a header. However this isn't the
case.

1) Some "Dual BSD/GPL" sources mention GPL in a header forgetting about BSD.
Can we treat such files as BSD-licensed at all? Few examples:
arch/arm/mach-pxa/am300epd.c
drivers/fmc/fmc-trivial.c
drivers/net/ppp/ppp_deflate.c
drivers/scsi/a100u2w.c
drivers/xen/xen-scsiback.c

2) Some "Dual BSD/GPL" sources don't specify BSD version in a header.
E.g. all you can find in a header is "All rights reserved. Licensed
under dual BSD/GPL license.". Two examples:
drivers/char/pcmcia/cm4000_cs.c
drivers/char/pcmcia/cm4040_cs.c


Another problem is text of BSD license

1) Some BSD 2-clause licensed sources don't link to its content.

In case of GPLv2 some sources simply mention this license and refer to
COPYING. Few examples:
a) drivers/bcma/main.c
"Licensed under the GNU/GPL. See COPYING for details."
b) drivers/block/umem.c
"This driver is released to the public under the terms of the GNU
GENERAL PUBLIC LICENSE version 2
c) drivers/mfd/tps6507x.c
"For licencing details see kernel-base/COPYING"

I believe the same could be done for BSD 2-clause license, however
there is no file that can be pointed. It results in some sources
specifying 2-clause license in a header without really providing the
content. Example:
arch/arm/boot/dts/lpc4350.dtsi

2) Some BSD 3-clause or Clear BSD licensed sources don't provide needed text

Many templates of BSD 3-clause license I found contain <organization>
that should be replaced by a proper organization/company. That makes
me suspect we can't have a generic text of BSD 3-clause or Clear BSD
in any shared file like COPYING. However there are sources that
specify one of above licenses without providing or linking its text.
Few examples:
arch/blackfin/mach-bf609/include/mach/anomaly.h
drivers/block/zram/zram_drv.c


I'm wondering how we could improve this situation. I got 2 main ideas:

1) Extend MODULE_LICENSE
We could add new acceptable entries specifying BSD version. We could
try to improve checkpatch.pl to look for a full license in a header
(it seems to be required as it has to provide <organization>). Maybe
we could figure out (with some lawyers?) how to treat sources using
"Dual BSD/GPL" mentioning GPL only (without BSD) in their header.

2) Get clear rules on how to write a header
If you find extending MODULE_LICENSE a bad idea, maybe we can simply
help people write proper headers. Explain the problem, provide
examples, maybe add some check in checkpatch.pl.

What do you think about this?

-- 
Rafa?


From tytso at mit.edu  Sat May 14 19:43:27 2016
From: tytso at mit.edu (Theodore Ts'o)
Date: Sat, 14 May 2016 22:43:27 -0400
Subject: Unclear BSD licensing (headers, MODULE_LICENSE, versions)
In-Reply-To: <CACna6ryZS1Q8=kBMMePAE_A377OReaYJdx8azZBrqG2jG+eMJg@mail.gmail.com>
References: <CACna6ryZS1Q8=kBMMePAE_A377OReaYJdx8azZBrqG2jG+eMJg@mail.gmail.com>
Message-ID: <20160515024327.GB7799@thunk.org>

On Sun, May 15, 2016 at 12:44:35AM +0200, Rafa? Mi?ecki wrote:
> 
> I recently received a hint that it would be nice/expected to have DTS
> files licensed under BSD. I had no experience with BSD, so I started
> looking at this and the way kernel parts use it.

There is a lot of sloppiness in some of the driver code.
Unfortunately, fixing it is something that really has to be done by
the copyright holder, or whoever submitted the kernel in the first
place and who has clear knowledge of what the copyright holder had
intended.

There is also a fairly wide range of seriousness of the various
defects you've listed.  On one extreme, although it's true that some
license, such as the ClearBSD license has <Organization> in its
template, when the original code file you've referenced has in its header:

 * Copyright 2004-2012 Analog Devices Inc.
 * Licensed under the Clear BSD license.

....tt's pretty obvious that Organization should be "Analog Devices Inc".

In other cases, it's pretty clear that someone copied the drivers from
some out-of-tree distribution (e.g., "see kernel-base/COPYING...") and
where finding the original distribution and then adding the Copyright
permission statement is a pretty easy thing to do.  (And in case where
a third party can easily show proof that the intent of the copyright
holder is clearly expressed, that third party probably is able to
submit a patch to fix up the source file.

> I'm wondering how we could improve this situation. I got 2 main ideas:
> 
> 1) Extend MODULE_LICENSE
> We could add new acceptable entries specifying BSD version. We could
> try to improve checkpatch.pl to look for a full license in a header
> (it seems to be required as it has to provide <organization>). Maybe
> we could figure out (with some lawyers?) how to treat sources using
> "Dual BSD/GPL" mentioning GPL only (without BSD) in their header.

I'm not a fan of this approach.  MODULE_LICENSE puts a hint about the
copyright license of a module where it can be found by the module
loader.  This is useful to enforce things like GPL_SYMBOL_EXPORT, but
I don't think we should try to make MODULE_LICESE to be more than
that.

> 2) Get clear rules on how to write a header
> If you find extending MODULE_LICENSE a bad idea, maybe we can simply
> help people write proper headers. Explain the problem, provide
> examples, maybe add some check in checkpatch.pl.

Adding more text about how to add a proper copyright notice and
license permission statement to the SubmittingDrivers file seems like
a good idea.

I doubt we can make checkpatch.pl smart enough to handle this
situation cleanly.

Cheers,

						- Ted


From matthijsvanduin at gmail.com  Sat May 14 21:00:28 2016
From: matthijsvanduin at gmail.com (Matthijs van Duin)
Date: Sun, 15 May 2016 06:00:28 +0200
Subject: [PATCH] clk: ti: Add support for basic clk_set_rate for dm814x
 and j5-eco ADPLL
In-Reply-To: <1463157653-9404-1-git-send-email-tony@atomide.com>
References: <1463157653-9404-1-git-send-email-tony@atomide.com>
Message-ID: <20160515040028.GA20983@squirrel.local>

On Fri, May 13, 2016 at 09:40:53AM -0700, Tony Lindgren wrote:
> +#define TI_ADPLL_DIV_N_MAX		GENMASK(7, 0)
> +#define TI_ADPLL_MULT_M_MAX		(GENMASK(11, 0) + 1)

These are PLL-type dependent, also the +1 is wrong since M isn't
off-by-one like N and N2 are.  (consistency? who needs that anyway?)

Here's what my own header says:

			//		PLLS	PLLLJ
/*10*/	u16 prediv;	// aka N	0..127	0..255	(off by one)
/*12*/	u16 postdiv;	// aka M2	1..31	1..127  (but see note below)
/*14*/	u16 mult;	// aka M	2..2047	2..4095
/*16*/	u16 bypassdiv;	// aka N2	0..15	0..15	(off by one)

the "note below" referred to being:

// Using the fractional multiplier increases jitter (presumably more for PLLS
// than for PLLLJ) and imposes constraints on the multiplier:
//	PLLLJ:  mult < 4094
//	PLLS:	mult < 2046 && mult >= 20
// Other docs say mult > 100 is required for PLLS for max 2.5% period jitter.


> +	/* Ratio for integer multiplier M and pre-divider N */
> +	rational_best_approximation(rate, dcorate, TI_ADPLL_MULT_M_MAX,
> +				    TI_ADPLL_DIV_N_MAX, &m, &n);

I'm seeing all sorts of problems here...

"dcorate" is a rather misleading name since I would expect that to
refer to the rate of the dco, obviously, while in fact it's the input
clock adjusted to account for an implicit factor of 2 (or 8 if you
enable M4XEN, the utility of which I do not see).

It makes no sense to use rational_best_approximation on the integer
part and then calculate the fractional part separately.  Not only is the
calculation wrong, it's needlessly complicated.  You could just have
passed TI_ADPLL_MULT_M_MAX << 18 to rational_best_approximation and then
split m into integer and fractional part.

The biggest problem however is that the best rational approximation does
not guarantee the refclk and dcoclk are within valid range.  This is
unlikely to be a problem for PLLS, but PLLLJ has quite narrow ranges:
0.5-2.5 MHz for refclk and 0.5-2.0 GHz for dcoclk.

I don't really have much time right now to spend on this, I suggest
checking previous threads on the 814x PLLs since I'm pretty sure the
complications/constraints for setting them have been discussed.


> + *                                            Maybe we can
> + * make the SD_DIV_TARGET_MHZ configurable also?

What use would it have?  All docs I've ever seen say sddiv must be set
to ceil(dcoclk / 250_MHz) and none of the docs contain any background
information whatsoever on how this thing works, so there's no informed
way to choose an alternate value.

> +	if ((sd >= TI814X_ADPLLJ_MIN_SD_DIV) &&
> +	    (sd <= TI814X_ADPLLJ_MAX_SD_DIV)) {

always true due to the limited range permitted for dcoclk.


From matthijsvanduin at gmail.com  Sat May 14 21:05:01 2016
From: matthijsvanduin at gmail.com (Matthijs van Duin)
Date: Sun, 15 May 2016 06:05:01 +0200
Subject: [PATCH] clk: ti: Add support for basic clk_set_rate for dm814x
 and j5-eco ADPLL
In-Reply-To: <20160515040028.GA20983@squirrel.local>
References: <1463157653-9404-1-git-send-email-tony@atomide.com>
 <20160515040028.GA20983@squirrel.local>
Message-ID: <20160515040501.GB20983@squirrel.local>

On Sun, May 15, 2016 at 06:00:28AM +0200, Matthijs van Duin wrote:
> /*12*/  u16 postdiv;    // aka M2       1..31   1..127  (but see note below)
> /*14*/  u16 mult;       // aka M        2..2047 2..4095

I just noticed that should have been

> /*12*/  u16 postdiv;    // aka M2       1..31   1..127
> /*14*/  u16 mult;       // aka M        2..2047 2..4095 (but see note below)

obviously :)


From b-liu at ti.com  Sat May 14 21:22:23 2016
From: b-liu at ti.com (Bin Liu)
Date: Sat, 14 May 2016 23:22:23 -0500
Subject: [linux-sunxi] Re: [PATCH 2/2] musb: sunxi: Set state to
 A_WAIT_VRISE when enabling VBus
In-Reply-To: <8765c9b5-1e40-2967-ac2c-da751b7d9019@redhat.com>
References: <1463077869-13224-1-git-send-email-hdegoede@redhat.com>
 <1463077869-13224-2-git-send-email-hdegoede@redhat.com>
 <20160513183428.GA1665@uda0271908>
 <8765c9b5-1e40-2967-ac2c-da751b7d9019@redhat.com>
Message-ID: <20160515042223.GA20689@uda0271908>

Hi,

On Sat, May 14, 2016 at 11:07:51AM +0200, Hans de Goede wrote:
> Hi,
> 
> On 13-05-16 20:35, Bin Liu wrote:
> >Hi,
> >
> >On Thu, May 12, 2016 at 08:31:09PM +0200, Hans de Goede wrote:
> >>When the board is powering attached usb devices via the otg port
> >>sometimes / on some devices it takes slightly too long for the VBus
> >>detection code in phy-sun4i-usb.c to signal that VBus is high after
> >>enabling VBus and the musb hardware signals a MUSB_INTR_VBUSERROR
> >>interrupt.
> >>
> >>This commit sets the otg state to A_WAIT_VRISE upon enabling Vbus
> >>making musb_stage0_irq() ignore the first VBUSERR_RETRY_COUNT
> >>VBUSERROR interrupts, fixing connection issues in these cases.
> >>
> >>Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> >>---
> >> drivers/usb/musb/sunxi.c | 8 +++++---
> >> 1 file changed, 5 insertions(+), 3 deletions(-)
> >>
> >>diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
> >>index 2c33d9b..2ee48fb 100644
> >>--- a/drivers/usb/musb/sunxi.c
> >>+++ b/drivers/usb/musb/sunxi.c
> >>@@ -112,7 +112,7 @@ static void sunxi_musb_work(struct work_struct *work)
> >> 		if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
> >> 			set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
> >> 			musb->xceiv->otg->default_a = 1;
> >>-			musb->xceiv->otg->state = OTG_STATE_A_IDLE;
> >>+			musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
> >> 			MUSB_HST_MODE(musb);
> >> 			devctl |= MUSB_DEVCTL_SESSION;
> >> 		} else {
> >>@@ -145,9 +145,10 @@ static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
> >> {
> >> 	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
> >>
> >>-	if (is_on)
> >>+	if (is_on) {
> >> 		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
> >>-	else
> >>+		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
> >
> >Why this has to be set in both sunxi_musb_work() and here? Only setting
> >it in the work is not efficient?
> 
> Different code paths, sunxi_musb_work sets it when the id pin changes
> (gets pulled low), this function gets called by musb_core in response
> to a session-request interrupt.

Ok, I see what I missed. An interrupt could happen right after
_set_vbus() but before _musb_work().

Regards,
-Bin.

> 
> Regards,
> 
> Hans
> 
> 
> >
> >Regards,
> >-Bin.
> >
> >>+	} else
> >> 		clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
> >>
> >> 	schedule_work(&glue->work);
> >>@@ -325,6 +326,7 @@ static int sunxi_set_mode(struct musb *musb, u8 mode)
> >> 		set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
> >> 		/* Stop musb work from turning vbus off again */
> >> 		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
> >>+		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
> >> 	}
> >>
> >> 	return 0;
> >>--
> >>2.7.4
> >>


From shc_work at mail.ru  Sat May 14 23:07:48 2016
From: shc_work at mail.ru (Alexander Shiyan)
Date: Sun, 15 May 2016 09:07:48 +0300
Subject: [PATCH 3/3] ARM: dts: clps711x: Add basic Cirrus Logic CDB89712
 Development board
In-Reply-To: <6057172.X40sTfvRlk@wuerfel>
References: <1463138788-5390-1-git-send-email-shc_work@mail.ru>
 <9407200.bOeiVUkGKT@wuerfel> <1463142623.38124260@f381.i.mail.ru>
 <6057172.X40sTfvRlk@wuerfel>
Message-ID: <20160515090748.05db9e6cdff743f26bd6c1fb@mail.ru>

On Fri, 13 May 2016 15:41:11 +0200
Arnd Bergmann <arnd at arndb.de> wrote:

> On Friday 13 May 2016 15:30:23 Alexander Shiyan wrote:
> > Hello.
> > 
> > > ???????, 13 ??? 2016, 15:00 +03:00 ?? Arnd Bergmann <arnd at arndb.de>:
> > > 
> > > On Friday 13 May 2016 14:26:28 Alexander Shiyan wrote:
> > ...
...
> > > > +		clks: clks at 80000000 {
> > > > +			#clock-cells = <1>;
> > > > +			compatible = "cirrus,clps711x-clk";
> > > > +			reg = <0x80000000 0xc000>;
> > > > +			startup-frequency = <73728000>;
> > > > +		};
> > ...
> > > > +		intc: intc at 80000000 {
> > > > +			compatible = "cirrus,clps711x-intc";
> > > > +			reg = <0x80000000 0x4000>;
> > > > +			interrupt-controller;
> > > > +			#interrupt-cells = <1>;
> > > > +		};
> > > 
> > > Better make the register ranges non-overlapping. This appears
> > > to start at the same place as the 'clks' node.
> > 
> > CLK driver uses:
> > #define CLPS711X_SYSCON1 (0x0100)
> > #define CLPS711X_SYSCON2 (0x1100)
> > ...
> > #define CLPS711X_PLLR (0xa5a8)
> > 
> > IRQCHIP driver uses:
> > #define CLPS711X_INTSR1 (0x0240)
> > ...
> > #define CLPS711X_INTSR2 (0x1240)
> > ...
> > #define CLPS711X_INTMR3 (0x2280)
> > 
> > So there is no way to do any else.
> 
> It sounds like what you have is a large system controller that
> has registers everywhere. Could you use syscon to access the
> individual registers instead?

There are several problems:
- The syscon driver must be initialized before any other devices,
  including the interrupt controller and clk/clocksource subsystems.
- A slight performance impact will be observed in the interrupt handler.
- SYSCON (regmap) is designed to use with equal the width of registers,
  while we need to use different widths (8/16/32) for some subsystems.

-- 
Alexander Shiyan <shc_work at mail.ru>


From zajec5 at gmail.com  Sun May 15 02:58:43 2016
From: zajec5 at gmail.com (=?UTF-8?B?UmFmYcWCIE1pxYJlY2tp?=)
Date: Sun, 15 May 2016 11:58:43 +0200
Subject: Unclear BSD licensing (headers, MODULE_LICENSE, versions)
In-Reply-To: <20160515024327.GB7799@thunk.org>
References: <CACna6ryZS1Q8=kBMMePAE_A377OReaYJdx8azZBrqG2jG+eMJg@mail.gmail.com>
 <20160515024327.GB7799@thunk.org>
Message-ID: <CACna6rzY4O=mqDsfrCtVxuKnyWrNn+_HBW+jsQn3UnVXAzna7Q@mail.gmail.com>

[Adding linux-doc@ which I probably should use from the beginning]

On 15 May 2016 at 04:43, Theodore Ts'o <tytso at mit.edu> wrote:
> On Sun, May 15, 2016 at 12:44:35AM +0200, Rafa? Mi?ecki wrote:
>>
>> I recently received a hint that it would be nice/expected to have DTS
>> files licensed under BSD. I had no experience with BSD, so I started
>> looking at this and the way kernel parts use it.
>
> There is a lot of sloppiness in some of the driver code.
> Unfortunately, fixing it is something that really has to be done by
> the copyright holder, or whoever submitted the kernel in the first
> place and who has clear knowledge of what the copyright holder had
> intended.
>
> There is also a fairly wide range of seriousness of the various
> defects you've listed.  On one extreme, although it's true that some
> license, such as the ClearBSD license has <Organization> in its
> template, when the original code file you've referenced has in its header:
>
>  * Copyright 2004-2012 Analog Devices Inc.
>  * Licensed under the Clear BSD license.
>
> ....tt's pretty obvious that Organization should be "Analog Devices Inc".
>
> In other cases, it's pretty clear that someone copied the drivers from
> some out-of-tree distribution (e.g., "see kernel-base/COPYING...") and
> where finding the original distribution and then adding the Copyright
> permission statement is a pretty easy thing to do.  (And in case where
> a third party can easily show proof that the intent of the copyright
> holder is clearly expressed, that third party probably is able to
> submit a patch to fix up the source file.

Thanks for your comments. I think I will try to contact authors of
unclear drivers once we get requirements described a bit better.
Hopefully at least some of them will respond.


>> I'm wondering how we could improve this situation. I got 2 main ideas:
>>
>> 1) Extend MODULE_LICENSE
>> We could add new acceptable entries specifying BSD version. We could
>> try to improve checkpatch.pl to look for a full license in a header
>> (it seems to be required as it has to provide <organization>). Maybe
>> we could figure out (with some lawyers?) how to treat sources using
>> "Dual BSD/GPL" mentioning GPL only (without BSD) in their header.
>
> I'm not a fan of this approach.  MODULE_LICENSE puts a hint about the
> copyright license of a module where it can be found by the module
> loader.  This is useful to enforce things like GPL_SYMBOL_EXPORT, but
> I don't think we should try to make MODULE_LICESE to be more than
> that.

OK, if others agree, I'm fine with leaving MODULE_LICENSE as is.


>> 2) Get clear rules on how to write a header
>> If you find extending MODULE_LICENSE a bad idea, maybe we can simply
>> help people write proper headers. Explain the problem, provide
>> examples, maybe add some check in checkpatch.pl.
>
> Adding more text about how to add a proper copyright notice and
> license permission statement to the SubmittingDrivers file seems like
> a good idea.
>
> I doubt we can make checkpatch.pl smart enough to handle this
> situation cleanly.

Thanks, I'll prepare & send patch updating SubmittingDrivers and maybe
some related files (if needed).

However there are some questions I need to ask first:


1) Can we add COPYING-BSD-2-CLAUSE (or similar)?

We already have GPL drivers with headers like:
a) "Licensed under the GNU/GPL. See COPYING for details."
b) "This driver is released to the public under the terms of the GNU
GENERAL PUBLIC LICENSE version 2"

Adding a similar file (e.g. COPYING-BSD-2-CLAUSE) would allow BSD
drivers to reference it as well, e.g.:
"Licensed under the BSD 2-clause. See COPYING-BSD-2-CLAUSE for details."
or similar.
As described earlier, there are some drivers /mentioning/ usage of BSD
license (in a header or with MODULE_LICENSE) without providing its
text at all.


2) How about sharing BSD 3-clause license?

Does it make sense to add anything like COPYING-BSD-3-CLAUSE? Should
we leave <organization> in license text in such file? Or should we
replace it with "author" as some drivers do? How drivers could
reference such file? Would a simple
"Licensed under the BSD 3-clause. See COPYING-BSD-3-CLAUSE for details."
be enough? Or should it be more specific like "With <organization>
being Foo Company"?

Or maybe we shouldn't add anything like COPYING-BSD-3-CLAUSE at all
and just require all drivers to attach whole text of BSD 3-clause
license in a header?

The same questions apply to Clear BSD license which also has
<organization> in its text.

-- 
Rafa?


From john at metanate.com  Sun May 15 04:16:39 2016
From: john at metanate.com (John Keeping)
Date: Sun, 15 May 2016 12:16:39 +0100
Subject: [PATCH] iommu/rockchip: fix zap cache during device attach
In-Reply-To: <11003810.ccjcAXkzhi@phil>
References: <20160510155046.24515-1-john@metanate.com>
 <11003810.ccjcAXkzhi@phil>
Message-ID: <20160515111638.GA9715@river>

On Sat, May 14, 2016 at 10:19:43PM +0200, Heiko Stuebner wrote:
> Am Dienstag, 10. Mai 2016, 16:50:46 schrieb John Keeping:
> > rk_iommu_command() takes a struct rk_iommu and iterates over the slave
> > MMUs, so this is doubly wrong in that we're passing in the wrong pointer
> > and talking to MMUs that we shouldn't be.
> > 
> > Fixes: cd6438c5f844 ("iommu/rockchip: Reconstruct to support multi
> > slaves") Signed-off-by: John Keeping <john at metanate.com>
> 
> on a rk3288-veyron
> Tested-by: Heiko Stuebner <heiko at sntech.de>
> Reviewed-by: Heiko Stuebner <heiko at sntech.de>
> 
> I was wondering for a short time why this didn't spew warnings until I 
> realized that the iommu->bases[i] is of course a void* .

Yes, although sparse catches it because iommu->bases[i] is __iomem so it
shows up as a namespace warning.


From hauke at hauke-m.de  Sun May 15 05:29:29 2016
From: hauke at hauke-m.de (Hauke Mehrtens)
Date: Sun, 15 May 2016 14:29:29 +0200
Subject: Unclear BSD licensing (headers, MODULE_LICENSE, versions)
In-Reply-To: <CACna6ryZS1Q8=kBMMePAE_A377OReaYJdx8azZBrqG2jG+eMJg@mail.gmail.com>
References: <CACna6ryZS1Q8=kBMMePAE_A377OReaYJdx8azZBrqG2jG+eMJg@mail.gmail.com>
Message-ID: <57386BA9.9030607@hauke-m.de>



On 05/15/2016 12:44 AM, Rafa? Mi?ecki wrote:
> Hi,

......

> Another problem is text of BSD license
> 
> 1) Some BSD 2-clause licensed sources don't link to its content.
> 
> In case of GPLv2 some sources simply mention this license and refer to
> COPYING. Few examples:
> a) drivers/bcma/main.c
> "Licensed under the GNU/GPL. See COPYING for details."
> b) drivers/block/umem.c
> "This driver is released to the public under the terms of the GNU
> GENERAL PUBLIC LICENSE version 2
> c) drivers/mfd/tps6507x.c
> "For licencing details see kernel-base/COPYING"

When I talked to some lawyers they did not like it when you only
reference a file and do not explicitly specify which license you are
using. The problem is that the code could be moved to an other project
with a different COPYING file. They were fine with b) because that
explicitly says which license text you mean. When you move this to
somewhere else you can still find our which license was meant here.

> I believe the same could be done for BSD 2-clause license, however
> there is no file that can be pointed. It results in some sources
> specifying 2-clause license in a header without really providing the
> content. Example:
> arch/arm/boot/dts/lpc4350.dtsi
> 
> 2) Some BSD 3-clause or Clear BSD licensed sources don't provide needed text
> 
> Many templates of BSD 3-clause license I found contain <organization>
> that should be replaced by a proper organization/company. That makes
> me suspect we can't have a generic text of BSD 3-clause or Clear BSD
> in any shared file like COPYING. However there are sources that
> specify one of above licenses without providing or linking its text.
> Few examples:
> arch/blackfin/mach-bf609/include/mach/anomaly.h
> drivers/block/zram/zram_drv.c

I like the text of the ISC license:
https://en.wikipedia.org/wiki/ISC_license
This license is a BSD license, but it does not have <organization> in it
and is even shorter that the ofter BSD licenses. Qualcomm Atheros used
this license text for ath9k and some other code. The main purpose was to
make it possible to integrate this code into *BSD. You can also put such
a short license text directly into your code.

This also allowed you to use the code in proprietary operating systems
like VxWorks.

> I'm wondering how we could improve this situation. I got 2 main ideas:
> 
> 1) Extend MODULE_LICENSE
> We could add new acceptable entries specifying BSD version. We could
> try to improve checkpatch.pl to look for a full license in a header
> (it seems to be required as it has to provide <organization>). Maybe
> we could figure out (with some lawyers?) how to treat sources using
> "Dual BSD/GPL" mentioning GPL only (without BSD) in their header.
> 
> 2) Get clear rules on how to write a header
> If you find extending MODULE_LICENSE a bad idea, maybe we can simply
> help people write proper headers. Explain the problem, provide
> examples, maybe add some check in checkpatch.pl.

I see MODULE_LICENSE more as a hint not as a legal binding thing. You
could also have a module which uses a file which is licensed under GPL
and one which is licensed under BSD license. Then the compiled module is
GPL, but parts of the cod is still BSD. I prefer to have the license
information in each source file, as a reference to a license (not some
generic file) or directly the license text.

Hauke


From andrew at lunn.ch  Sun May 15 08:39:29 2016
From: andrew at lunn.ch (Andrew Lunn)
Date: Sun, 15 May 2016 17:39:29 +0200
Subject: Unclear BSD licensing (headers, MODULE_LICENSE, versions)
In-Reply-To: <CACna6ryZS1Q8=kBMMePAE_A377OReaYJdx8azZBrqG2jG+eMJg@mail.gmail.com>
References: <CACna6ryZS1Q8=kBMMePAE_A377OReaYJdx8azZBrqG2jG+eMJg@mail.gmail.com>
Message-ID: <20160515153929.GC9021@lunn.ch>

On Sun, May 15, 2016 at 12:44:35AM +0200, Rafa?? Mi??ecki wrote:
> Hi,
> 
> I recently received a hint that it would be nice/expected to have DTS
> files licensed under BSD.

I've not done a count, but i think you will find that most device tree
files use X11 as the second license, not BSD.

      Andrew


From carlo at caione.org  Sun May 15 11:10:45 2016
From: carlo at caione.org (Carlo Caione)
Date: Sun, 15 May 2016 20:10:45 +0200
Subject: [RFC PATCH] soc: Amlogic: Add secure monitor driver
Message-ID: <1463335845-23534-1-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Introduce a driver to provide calls into secure monitor mode.

In the Amlogic SoCs these calls are used for multiple reasons: access to
NVMEM, reboot, set USB boot, enable JTAG, etc...

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi |   4 +
 drivers/soc/Kconfig                         |   1 +
 drivers/soc/Makefile                        |   1 +
 drivers/soc/amlogic/Kconfig                 |   8 ++
 drivers/soc/amlogic/Makefile                |   1 +
 drivers/soc/amlogic/meson_sm.c              | 141 ++++++++++++++++++++++++++++
 include/linux/soc/amlogic/meson_sm.h        |  57 +++++++++++
 7 files changed, 213 insertions(+)
 create mode 100644 drivers/soc/amlogic/Kconfig
 create mode 100644 drivers/soc/amlogic/Makefile
 create mode 100644 drivers/soc/amlogic/meson_sm.c
 create mode 100644 include/linux/soc/amlogic/meson_sm.h

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 76b3b6d..e4017c3 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -98,6 +98,10 @@
 		method = "smc";
 	};
 
+	sm {
+		compatible = "amlogic,meson-sm";
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cb58ef0..637af69 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -1,5 +1,6 @@
 menu "SOC (System On Chip) specific Drivers"
 
+source "drivers/soc/amlogic/Kconfig"
 source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/brcmstb/Kconfig"
 source "drivers/soc/fsl/qe/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 5ade713..2eb6fd5 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_ARCH_DOVE)		+= dove/
 obj-$(CONFIG_MACH_DOVE)		+= dove/
 obj-y				+= fsl/
 obj-$(CONFIG_ARCH_MEDIATEK)	+= mediatek/
+obj-$(CONFIG_ARCH_MESON)	+= amlogic/
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
 obj-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip/
 obj-$(CONFIG_SOC_SAMSUNG)	+= samsung/
diff --git a/drivers/soc/amlogic/Kconfig b/drivers/soc/amlogic/Kconfig
new file mode 100644
index 0000000..fff11a3
--- /dev/null
+++ b/drivers/soc/amlogic/Kconfig
@@ -0,0 +1,8 @@
+#
+# Amlogic Secure Monitor driver
+#
+config MESON_SM
+	bool
+	default ARCH_MESON
+	help
+	  Say y here to enable the Amlogic secure monitor driver
diff --git a/drivers/soc/amlogic/Makefile b/drivers/soc/amlogic/Makefile
new file mode 100644
index 0000000..9ab3884
--- /dev/null
+++ b/drivers/soc/amlogic/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MESON_SM) +=	meson_sm.o
diff --git a/drivers/soc/amlogic/meson_sm.c b/drivers/soc/amlogic/meson_sm.c
new file mode 100644
index 0000000..e6f9c4f
--- /dev/null
+++ b/drivers/soc/amlogic/meson_sm.c
@@ -0,0 +1,141 @@
+/*
+ * Amlogic Secure Monitor driver
+ *
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <stdarg.h>
+#include <asm/cacheflush.h>
+#include <asm/compiler.h>
+#include <linux/arm-smccc.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/smp.h>
+
+#include <linux/soc/amlogic/meson_sm.h>
+
+#define SM_MEM_SIZE			0x1000
+
+/*
+ * To read from / write to the secure monitor we use two bounce buffers. The
+ * physical addresses of the two buffers are obtained by querying the secure
+ * monitor itself.
+ */
+
+static u32 sm_phy_in_base;
+static u32 sm_phy_out_base;
+
+static void __iomem *sm_sharemem_in_base;
+static void __iomem *sm_sharemem_out_base;
+
+struct meson_sm_data {
+	unsigned int cmd;
+	unsigned int arg0;
+	unsigned int arg1;
+	unsigned int arg2;
+	unsigned int arg3;
+	unsigned int arg4;
+	unsigned int ret;
+};
+
+static void __meson_sm_call(void *info)
+{
+	struct meson_sm_data *data = info;
+	struct arm_smccc_res res;
+
+	arm_smccc_smc(data->cmd,
+		      data->arg0, data->arg1, data->arg2,
+		      data->arg3, data->arg4, 0, 0, &res);
+	data->ret = res.a0;
+}
+
+unsigned int meson_sm_call(unsigned int cmd, unsigned int arg0,
+			   unsigned int arg1, unsigned int arg2,
+			   unsigned int arg3, unsigned int arg4)
+{
+	struct meson_sm_data data;
+
+	data.cmd = cmd;
+	data.arg0 = arg0;
+	data.arg1 = arg1;
+	data.arg2 = arg2;
+	data.arg3 = arg3;
+	data.arg4 = arg4;
+	data.ret = 0;
+
+	smp_call_function_single(0, __meson_sm_call, &data, 1);
+
+	return data.ret;
+}
+
+unsigned int meson_sm_call_read(void *buffer, unsigned int cmd,
+				unsigned int arg0, unsigned int arg1,
+				unsigned int arg2, unsigned int arg3,
+				unsigned int arg4)
+{
+	unsigned int size;
+
+	size = meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
+
+	if (size != 0)
+		memcpy(buffer, sm_sharemem_out_base, size);
+
+	return size;
+}
+
+unsigned int meson_sm_call_write(void *buffer, unsigned int size,
+				 unsigned int cmd, unsigned int arg0,
+				 unsigned int arg1, unsigned int arg2,
+				 unsigned int arg3, unsigned int arg4)
+{
+	memcpy(sm_sharemem_in_base, buffer, size);
+
+	return meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
+}
+
+static int meson_sm_probe(struct platform_device *pdev)
+{
+	sm_phy_in_base = meson_sm_call(SM_GET_SHARE_MEM_INPUT_BASE, 0, 0, 0, 0, 0);
+
+	sm_sharemem_in_base = ioremap_cache(sm_phy_in_base, SM_MEM_SIZE);
+	if (!sm_sharemem_in_base)
+		return -EINVAL;
+
+	sm_phy_out_base = meson_sm_call(SM_GET_SHARE_MEM_OUTPUT_BASE, 0, 0, 0, 0, 0);
+
+	sm_sharemem_out_base = ioremap_cache(sm_phy_out_base, SM_MEM_SIZE);
+	if (!sm_sharemem_out_base)
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct of_device_id meson_sm_ids[] = {
+	{ .compatible = "amlogic,meson-sm" },
+	{ /* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, meson_sm_ids);
+
+static struct platform_driver meson_sm_platform_driver = {
+	.probe	= meson_sm_probe,
+	.driver	= {
+		.name		= "secmon",
+		.of_match_table	= meson_sm_ids,
+	},
+};
+module_platform_driver(meson_sm_platform_driver);
+
+MODULE_AUTHOR("Carlo Caione <carlo at endlessm.com>");
+MODULE_DESCRIPTION("Amlogic secure monitor driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/soc/amlogic/meson_sm.h b/include/linux/soc/amlogic/meson_sm.h
new file mode 100644
index 0000000..68b943f
--- /dev/null
+++ b/include/linux/soc/amlogic/meson_sm.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MESON_SM_H_
+#define _MESON_SM_H_
+
+#define SM_GET_SHARE_MEM_INPUT_BASE		0x82000020
+#define SM_GET_SHARE_MEM_OUTPUT_BASE		0x82000021
+#define SM_GET_REBOOT_REASON			0x82000022
+#define SM_GET_SHARE_STORAGE_IN_BASE		0x82000023
+#define SM_GET_SHARE_STORAGE_OUT_BASE		0x82000024
+#define SM_GET_SHARE_STORAGE_BLOCK_BASE		0x82000025
+#define SM_GET_SHARE_STORAGE_MESSAGE_BASE	0x82000026
+#define SM_GET_SHARE_STORAGE_BLOCK_SIZE		0x82000027
+#define SM_EFUSE_READ				0x82000030
+#define SM_EFUSE_WRITE				0x82000031
+#define SM_EFUSE_WRITE_PATTERN			0x82000032
+#define SM_EFUSE_USER_MAX			0x82000033
+#define SM_JTAG_ON				0x82000040
+#define SM_JTAG_OFF				0x82000041
+#define SM_SET_USB_BOOT_FUNC			0x82000043
+#define SM_SECURITY_KEY_QUERY			0x82000060
+#define SM_SECURITY_KEY_READ			0x82000061
+#define SM_SECURITY_KEY_WRITE			0x82000062
+#define SM_SECURITY_KEY_TELL			0x82000063
+#define SM_SECURITY_KEY_VERIFY			0x82000064
+#define SM_SECURITY_KEY_STATUS			0x82000065
+#define SM_SECURITY_KEY_NOTIFY			0x82000066
+#define SM_SECURITY_KEY_LIST			0x82000067
+#define SM_SECURITY_KEY_REMOVE			0x82000068
+#define SM_DEBUG_EFUSE_WRITE_PATTERN		0x820000F0
+#define SM_DEBUG_EFUSE_READ_PATTERN		0x820000F1
+#define SM_AML_DATA_PROCESS			0x820000FF
+#define SM_PSCI_SYS_REBOOT			0x84000009
+
+unsigned int meson_sm_call(unsigned int cmd, unsigned int arg0,
+			   unsigned int arg1, unsigned int arg2,
+			   unsigned int arg3, unsigned int arg4);
+unsigned int meson_sm_call_read(void *buffer, unsigned int cmd,
+				unsigned int arg0, unsigned int arg1,
+				unsigned int arg2, unsigned int arg3,
+				unsigned int arg4);
+unsigned int meson_sm_call_write(void *buffer, unsigned int size,
+				 unsigned int cmd, unsigned int arg0,
+				 unsigned int arg1, unsigned int arg2,
+				 unsigned int arg3, unsigned int arg4);
+
+#endif /* _MESON_SM_H_ */
-- 
2.7.4



From pavel at ucw.cz  Sun May 15 12:31:06 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Sun, 15 May 2016 21:31:06 +0200
Subject: Can not play audio with screen off
Message-ID: <20160515193106.GA18685@amd>

Hi!

I'm playing some more with N900, this time I'd like to use it as a
alarm clock...

And now I realized I can not, because system performance is so
horrible with screen off that mpg123 + pulseaudio skips horribly. This
is without tweaking serial parameters, so CPU is definitely not going
into the idle/off modes.

Loading CPU fixes the issue (I used cat /dev/zero > /dev/null).

Hmm. And it seems to work better if I ssh in and launch mpg123
remotely. Weird.

Kernel 4.5-rc0. Will try on different ones.

Any ideas? Is there interface to tell kernel that better performance
is needed for a while?

Thanks,

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From krzk at kernel.org  Sun May 15 13:13:41 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:41 +0200
Subject: [PATCH v4 00/22] ARM: dts: exynos: Add initial support for Odroid XU
Message-ID: <1463343243-26429-1-git-send-email-krzk@kernel.org>


Hi,

Patchset adds necessary clocks, reorganizes existing stuff and finally
adds Odroid XU support.


Changes since v3
================
1. Get rid of 5 patches changing the fin_pll after talk with Tomasz
   Figa. The existing definition of oscillator in exynos5410.dtsi
   is preferred over solution chosen for Exynos5420.
   This simplifies also the merging strategy.
2. Add tags from Javier (tested and reviewed).

Patchset is available at my private repo @github:
https://github.com/krzk/linux.git for-next/odroid-xu-v4
(I have some more changes coming but I think it is easier for
reviewers if the patchset does not grow infinitely)


Changes since v2
================
1. Got global-ack from Stephen for the clock changes. I think merging
   everything through arm-soc might be the easiest but:
   a. In such case I will prepare a tag with clock changes,
   b. Anyway I will wait for response from Sylwester and Tomasz.
2. Applied comments from Javier and added his Reviewed-by.
3. Patch 22: added ack from Rob.
4. Minor improvements in existing patches.
5. Five new patches at the end: 23-27 (not reviewed yet).
   Some of them could be squashed with existing ones but existing
   changes got reviews. Although the final Odroid XU DTS works fine but
   in general this is still work-in-progress so I suspect it will grow.
   I am releasing it early following Linux concept. :)


Changes since v1
================
1. A lot of new patches.
2. Removed some TODO notes (eMMC 4.5 so no RCLK pin).
3. New clocks, more reorganization.
4. New common DTSI: exynos54xx.dtsi. I know, it is getting more
   and more complicated but this might help removing duplications
   and keeping everything under control.



Merging strategy
================
The clock changes can go to clock tree. ARM changes to samsung-soc tree.
Please provide me a tag with include/dt-bindings/clock commits so I can
merge it.


Best regards,
Krzysztof

Krzysztof Kozlowski (22):
  dt-bindings: clock: Add license and reformat Exynos5410 clock IDs
  dt-bindings: clock: Add PWM and USB clock IDs to Exynos5410
  clk: samsung: exynos5410: Add serial3, USB and PWM clocks
  ARM: dts: exynos: Re-order alphabetically Exynos5420 SD0/SD1 pinctrl
    nodes
  ARM: dts: exynos: Use lowercase for Exynos5410 CPU node labels
  ARM: dts: exynos: Configure Exynos5410 pinctrl for eMMC and SD card
  ARM: dts: exynos: Split Odroid XU3 LEDs to separate DTSI
  ARM: dts: exynos: Move common nodes to exynos5.dtsi
  ARM: dts: exynos: Prepare for inclusion of exynos5.dtsi in
    exynos5410.dtsi
  ARM: dts: exynos: Use phandle to get parent node in exynos5250-snow
  ARM: dts: exynos: Move Exynos5250 and Exynos5420 nodes under soc
  ARM: dts: exynos: Include common exynos5 in exynos5410.dtsi
  ARM: dts: exynos: Enable UART3 on Exynos5410
  ARM: dts: exynos: MCT is not an interrupt controller and extend length
    of iomap
  ARM: dts: exynos: Move common Exynos5410/542x/5800 nodes to new DTSI
  ARM: dts: exynos: Add USB to Exynos5410
  ARM: dts: exynos: Add initial support for Odroid XU board
  dt-bindings: clock: Add I2C, HSI2C and RTC clock IDs to Exynos5410
  clk: samsung: exynos5410: Add I2C, HSI2C and RTC clocks
  ARM: dts: exynos: Move HSI2C nodes to exynos54xx.dtsi
  ARM: dts: exynos: Add I2C, PWM and UART pinctrl to Exynos5410
  ARM: dts: exynos: Add RTC and I2C to Exynos5410

 .../bindings/arm/samsung/samsung-boards.txt        |    1 +
 arch/arm/boot/dts/Makefile                         |    1 +
 arch/arm/boot/dts/exynos5.dtsi                     |  215 ++-
 arch/arm/boot/dts/exynos5250-snow-common.dtsi      |    2 +-
 arch/arm/boot/dts/exynos5250.dtsi                  | 1701 ++++++++---------
 arch/arm/boot/dts/exynos5410-odroidxu.dts          |  121 ++
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi          |  210 +++
 arch/arm/boot/dts/exynos5410-smdk5410.dts          |    6 +-
 arch/arm/boot/dts/exynos5410.dtsi                  |  267 +--
 arch/arm/boot/dts/exynos5420-pinctrl.dtsi          |   12 +-
 arch/arm/boot/dts/exynos5420.dtsi                  | 1992 +++++++++-----------
 arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts    |   35 +-
 arch/arm/boot/dts/exynos5422-odroidxu3.dts         |   35 +-
 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi    |   50 +
 arch/arm/boot/dts/exynos54xx.dtsi                  |  188 ++
 drivers/clk/samsung/clk-exynos5410.c               |   45 +
 include/dt-bindings/clock/exynos5410.h             |   73 +-
 17 files changed, 2734 insertions(+), 2220 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos5410-odroidxu.dts
 create mode 100644 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
 create mode 100644 arch/arm/boot/dts/exynos54xx.dtsi

-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:42 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:42 +0200
Subject: [PATCH v4 01/22] dt-bindings: clock: Add license and reformat
 Exynos5410 clock IDs
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-2-git-send-email-krzk@kernel.org>

Add license and copyrights (file introduced in 2014) to header with
Exynos5410 clock IDs. Additionally reformat it to improve readability.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 include/dt-bindings/clock/exynos5410.h | 54 ++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 9b180f032e2d..213f19e02870 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -1,33 +1,43 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics 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.
+ *
+ * Device Tree binding constants for Exynos5421 clock controller.
+*/
+
 #ifndef _DT_BINDINGS_CLOCK_EXYNOS_5410_H
 #define _DT_BINDINGS_CLOCK_EXYNOS_5410_H
 
 /* core clocks */
-#define CLK_FIN_PLL 1
-#define CLK_FOUT_APLL 2
-#define CLK_FOUT_CPLL 3
-#define CLK_FOUT_MPLL 4
-#define CLK_FOUT_BPLL 5
-#define CLK_FOUT_KPLL 6
+#define CLK_FIN_PLL		1
+#define CLK_FOUT_APLL		2
+#define CLK_FOUT_CPLL		3
+#define CLK_FOUT_MPLL		4
+#define CLK_FOUT_BPLL		5
+#define CLK_FOUT_KPLL		6
 
 /* gate for special clocks (sclk) */
-#define CLK_SCLK_UART0 128
-#define CLK_SCLK_UART1 129
-#define CLK_SCLK_UART2 130
-#define CLK_SCLK_UART3 131
-#define CLK_SCLK_MMC0 132
-#define CLK_SCLK_MMC1 133
-#define CLK_SCLK_MMC2 134
+#define CLK_SCLK_UART0		128
+#define CLK_SCLK_UART1		129
+#define CLK_SCLK_UART2		130
+#define CLK_SCLK_UART3		131
+#define CLK_SCLK_MMC0		132
+#define CLK_SCLK_MMC1		133
+#define CLK_SCLK_MMC2		134
 
 /* gate clocks */
-#define CLK_UART0 257
-#define CLK_UART1 258
-#define CLK_UART2 259
-#define CLK_UART3 260
-#define CLK_MCT 315
-#define CLK_MMC0 351
-#define CLK_MMC1 352
-#define CLK_MMC2 353
+#define CLK_UART0		257
+#define CLK_UART1		258
+#define CLK_UART2		259
+#define CLK_UART3		260
+#define CLK_MCT			315
+#define CLK_MMC0		351
+#define CLK_MMC1		352
+#define CLK_MMC2		353
 
-#define CLK_NR_CLKS 512
+#define CLK_NR_CLKS		512
 
 #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5410_H */
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:43 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:43 +0200
Subject: [PATCH v4 02/22] dt-bindings: clock: Add PWM and USB clock IDs to
 Exynos5410
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-3-git-send-email-krzk@kernel.org>

Add IDs for PWM and USB clocks to Exynos5410. Use the same number as for
Exynos5420 just in case in future these drivers were merged.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 include/dt-bindings/clock/exynos5410.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 213f19e02870..34c8e96987a1 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 Krzysztof Kozlowski
  *
  * 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
@@ -27,16 +28,25 @@
 #define CLK_SCLK_MMC0		132
 #define CLK_SCLK_MMC1		133
 #define CLK_SCLK_MMC2		134
+#define CLK_SCLK_USBD300	150
+#define CLK_SCLK_USBD301	151
+#define CLK_SCLK_USBPHY300	152
+#define CLK_SCLK_USBPHY301	153
+#define CLK_SCLK_PWM		155
 
 /* gate clocks */
 #define CLK_UART0		257
 #define CLK_UART1		258
 #define CLK_UART2		259
 #define CLK_UART3		260
+#define CLK_PWM			279
 #define CLK_MCT			315
 #define CLK_MMC0		351
 #define CLK_MMC1		352
 #define CLK_MMC2		353
+#define CLK_USBH20		365
+#define CLK_USBD300		366
+#define CLK_USBD301		367
 
 #define CLK_NR_CLKS		512
 
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:44 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:44 +0200
Subject: [PATCH v4 03/22] clk: samsung: exynos5410: Add serial3,
 USB and PWM clocks
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-4-git-send-email-krzk@kernel.org>

Just like other Exynos5 family SoCs, this one has four UARTs. Add
missing UART3 clocks to the Exynos5410 clock driver.

Add clocks for USB and PWM.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 drivers/clk/samsung/clk-exynos5410.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index d5d5dcabc4a9..5f892128849a 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -33,9 +33,11 @@
 #define SRC_CPERI1		0x4204
 #define DIV_TOP0		0x10510
 #define DIV_TOP1		0x10514
+#define DIV_FSYS0		0x10548
 #define DIV_FSYS1		0x1054c
 #define DIV_FSYS2		0x10550
 #define DIV_PERIC0		0x10558
+#define DIV_PERIC3		0x10564
 #define SRC_TOP0		0x10210
 #define SRC_TOP1		0x10214
 #define SRC_TOP2		0x10218
@@ -44,6 +46,8 @@
 #define SRC_MASK_FSYS		0x10340
 #define SRC_MASK_PERIC0		0x10350
 #define GATE_BUS_FSYS0		0x10740
+#define GATE_TOP_SCLK_FSYS	0x10840
+#define GATE_TOP_SCLK_PERIC	0x10850
 #define GATE_IP_FSYS		0x10944
 #define GATE_IP_PERIC		0x10950
 #define GATE_IP_PERIS		0x10960
@@ -71,6 +75,7 @@ PNAME(mout_kfc_p)	= { "mout_kpll", "sclk_mpll", };
 PNAME(mpll_user_p)	= { "fin_pll", "sclk_mpll", };
 PNAME(bpll_user_p)	= { "fin_pll", "sclk_bpll", };
 PNAME(mpll_bpll_p)	= { "sclk_mpll_muxed", "sclk_bpll_muxed", };
+PNAME(sclk_mpll_bpll_p)	= { "sclk_mpll_bpll", "fin_pll", };
 
 PNAME(group2_p)		= { "fin_pll", "fin_pll", "none", "none",
 			"none", "none", "sclk_mpll_bpll",
@@ -96,10 +101,14 @@ static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
 	MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4),
 	MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4),
 	MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4),
+	MUX(0, "mout_usbd300", sclk_mpll_bpll_p, SRC_FSYS, 28, 1),
+	MUX(0, "mout_usbd301", sclk_mpll_bpll_p, SRC_FSYS, 29, 1),
 
 	MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4),
 	MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4),
 	MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4),
+	MUX(0, "mout_uart3", group2_p, SRC_PERIC0, 12, 4),
+	MUX(0, "mout_pwm", group2_p, SRC_PERIC0, 24, 4),
 
 	MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1),
 	MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1),
@@ -121,6 +130,11 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 	DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3),
 	DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
 
+	DIV(0, "dout_usbphy300", "mout_usbd300", DIV_FSYS0, 16, 4),
+	DIV(0, "dout_usbphy301", "mout_usbd301", DIV_FSYS0, 20, 4),
+	DIV(0, "dout_usbd300", "mout_usbd300", DIV_FSYS0, 24, 4),
+	DIV(0, "dout_usbd301", "mout_usbd301", DIV_FSYS0, 28, 4),
+
 	DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
 	DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
 	DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
@@ -137,6 +151,8 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 	DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
 	DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
 
+	DIV(0, "dout_pwm", "mout_pwm", DIV_PERIC3, 0, 4),
+
 	DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
 	DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3),
 };
@@ -155,9 +171,23 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 	GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0),
 	GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0),
 
+	GATE(CLK_SCLK_USBPHY301, "sclk_usbphy301", "dout_usbphy301",
+	     GATE_TOP_SCLK_FSYS, 7, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_USBPHY300, "sclk_usbphy300", "dout_usbphy300",
+	     GATE_TOP_SCLK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_USBD300, "sclk_usbd300", "dout_usbd300",
+	     GATE_TOP_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_USBD301, "sclk_usbd301", "dout_usbd301",
+	     GATE_TOP_SCLK_FSYS, 10, CLK_SET_RATE_PARENT, 0),
+
+	GATE(CLK_SCLK_PWM, "sclk_pwm", "dout_pwm",
+	     GATE_TOP_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0),
+
 	GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
 	GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
 	GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
+	GATE(CLK_UART3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0),
+	GATE(CLK_PWM, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0),
 
 	GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
 			SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
@@ -165,6 +195,12 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 			SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
 			SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_UART3, "sclk_uart3", "div_uart3",
+			SRC_MASK_PERIC0, 12, CLK_SET_RATE_PARENT, 0),
+
+	GATE(CLK_USBH20, "usbh20", "aclk200_fsys", GATE_IP_FSYS, 18, 0, 0),
+	GATE(CLK_USBD300, "usbd300", "aclk200_fsys", GATE_IP_FSYS, 19, 0, 0),
+	GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_IP_FSYS, 20, 0, 0),
 };
 
 static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:45 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:45 +0200
Subject: [PATCH v4 04/22] ARM: dts: exynos: Re-order alphabetically Exynos5420
 SD0/SD1 pinctrl nodes
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-5-git-send-email-krzk@kernel.org>

The 'sd0_rclk' was put in the middle of SD1 nodes. Remove the confusion.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
index 130563b2ca95..14beb7e07323 100644
--- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
@@ -193,17 +193,17 @@
 		samsung,pin-drv = <3>;
 	};
 
-	sd1_clk: sd1-clk {
-		samsung,pins = "gpc1-0";
+	sd0_rclk: sd0-rclk {
+		samsung,pins = "gpc0-7";
 		samsung,pin-function = <2>;
-		samsung,pin-pud = <0>;
+		samsung,pin-pud = <1>;
 		samsung,pin-drv = <3>;
 	};
 
-	sd0_rclk: sd0-rclk {
-		samsung,pins = "gpc0-7";
+	sd1_clk: sd1-clk {
+		samsung,pins = "gpc1-0";
 		samsung,pin-function = <2>;
-		samsung,pin-pud = <1>;
+		samsung,pin-pud = <0>;
 		samsung,pin-drv = <3>;
 	};
 
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:47 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:47 +0200
Subject: [PATCH v4 06/22] ARM: dts: exynos: Configure Exynos5410 pinctrl for
 eMMC and SD card
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-7-git-send-email-krzk@kernel.org>

Configure the pinctrl for MMC0 (eMMC) and MMC2 (microSD card).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

Important changes since v2:
1. Re-order the eMMC pins by pin-name, not by label.
---
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 77 +++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
index f9aa6bb55464..ddacafa1e907 100644
--- a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
@@ -277,6 +277,83 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
+
+	sd0_clk: sd0-clk {
+		samsung,pins = "gpc0-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cmd: sd0-cmd {
+		samsung,pins = "gpc0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cd: sd0-cd {
+		samsung,pins = "gpc0-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus1: sd0-bus-width1 {
+		samsung,pins = "gpc0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus4: sd0-bus-width4 {
+		samsung,pins = "gpc0-4", "gpc0-5", "gpc0-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_clk: sd2-clk {
+		samsung,pins = "gpc2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cmd: sd2-cmd {
+		samsung,pins = "gpc2-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cd: sd2-cd {
+		samsung,pins = "gpc2-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus1: sd2-bus-width1 {
+		samsung,pins = "gpc2-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus4: sd2-bus-width4 {
+		samsung,pins = "gpc2-4", "gpc2-5", "gpc2-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus8: sd0-bus-width8 {
+		samsung,pins = "gpc3-0", "gpc3-1", "gpc3-2", "gpc3-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
 };
 
 &pinctrl_1 {
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:46 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:46 +0200
Subject: [PATCH v4 05/22] ARM: dts: exynos: Use lowercase for Exynos5410 CPU
 node labels
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-6-git-send-email-krzk@kernel.org>

For consistency lowercase node labels are used.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 7a56aec2c5ba..8de8c644f42e 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -35,28 +35,28 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		CPU0: cpu at 0 {
+		cpu0: cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU1: cpu at 1 {
+		cpu1: cpu at 1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x1>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU2: cpu at 2 {
+		cpu2: cpu at 2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x2>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU3: cpu at 3 {
+		cpu3: cpu at 3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x3>;
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:48 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:48 +0200
Subject: [PATCH v4 07/22] ARM: dts: exynos: Split Odroid XU3 LEDs to separate
 DTSI
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-8-git-send-email-krzk@kernel.org>

The LED nodes can be shared between Odroid XU3, XU3-Lite and XU (not yet
added) thus removing duplication.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts | 35 +----------------
 arch/arm/boot/dts/exynos5422-odroidxu3.dts      | 35 +----------------
 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi | 50 +++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 68 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi

diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
index 2ae1cf41dcb6..03fa88c45426 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
@@ -14,44 +14,11 @@
 /dts-v1/;
 #include "exynos5422-odroidxu3-common.dtsi"
 #include "exynos5422-odroidxu3-audio.dtsi"
+#include "exynos54xx-odroidxu-leds.dtsi"
 
 / {
 	model = "Hardkernel Odroid XU3 Lite";
 	compatible = "hardkernel,odroid-xu3-lite", "samsung,exynos5800", "samsung,exynos5";
-
-	pwmleds {
-		compatible = "pwm-leds";
-
-		greenled {
-			label = "green:mmc0";
-			pwms = <&pwm 1 2000000 0>;
-			pwm-names = "pwm1";
-			/*
-			 * Green LED is much brighter than the others
-			 * so limit its max brightness
-			 */
-			max_brightness = <127>;
-			linux,default-trigger = "mmc0";
-		};
-
-		blueled {
-			label = "blue:heartbeat";
-			pwms = <&pwm 2 2000000 0>;
-			pwm-names = "pwm2";
-			max_brightness = <255>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-
-	gpioleds {
-		compatible = "gpio-leds";
-		redled {
-			label = "red:microSD";
-			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
-			default-state = "off";
-			linux,default-trigger = "mmc1";
-		};
-	};
 };
 
 &pwm {
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
index 432406db85de..9ed6564acfb0 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
@@ -13,44 +13,11 @@
 /dts-v1/;
 #include "exynos5422-odroidxu3-common.dtsi"
 #include "exynos5422-odroidxu3-audio.dtsi"
+#include "exynos54xx-odroidxu-leds.dtsi"
 
 / {
 	model = "Hardkernel Odroid XU3";
 	compatible = "hardkernel,odroid-xu3", "samsung,exynos5800", "samsung,exynos5";
-
-	pwmleds {
-		compatible = "pwm-leds";
-
-		greenled {
-			label = "green:mmc0";
-			pwms = <&pwm 1 2000000 0>;
-			pwm-names = "pwm1";
-			/*
-			 * Green LED is much brighter than the others
-			 * so limit its max brightness
-			 */
-			max_brightness = <127>;
-			linux,default-trigger = "mmc0";
-		};
-
-		blueled {
-			label = "blue:heartbeat";
-			pwms = <&pwm 2 2000000 0>;
-			pwm-names = "pwm2";
-			max_brightness = <255>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-
-	gpioleds {
-		compatible = "gpio-leds";
-		redled {
-			label = "red:microSD";
-			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
-			default-state = "off";
-			linux,default-trigger = "mmc1";
-		};
-	};
 };
 
 &i2c_0 {
diff --git a/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi b/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
new file mode 100644
index 000000000000..0ed30206625c
--- /dev/null
+++ b/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
@@ -0,0 +1,50 @@
+/*
+ * Hardkernel Odroid XU/XU3 LED device tree source
+ *
+ * Copyright (c) 2015,2016 Krzysztof Kozlowski
+ * Copyright (c) 2014 Collabora Ltd.
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	pwmleds {
+		compatible = "pwm-leds";
+
+		greenled {
+			label = "green:mmc0";
+			pwms = <&pwm 1 2000000 0>;
+			pwm-names = "pwm1";
+			/*
+			 * Green LED is much brighter than the others
+			 * so limit its max brightness
+			 */
+			max_brightness = <127>;
+			linux,default-trigger = "mmc0";
+		};
+
+		blueled {
+			label = "blue:heartbeat";
+			pwms = <&pwm 2 2000000 0>;
+			pwm-names = "pwm2";
+			max_brightness = <255>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	gpioleds {
+		compatible = "gpio-leds";
+		redled {
+			label = "red:microSD";
+			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "mmc1";
+		};
+	};
+};
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:51 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:51 +0200
Subject: [PATCH v4 10/22] ARM: dts: exynos: Use phandle to get parent node in
 exynos5250-snow
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-11-git-send-email-krzk@kernel.org>

The i2c-arbitrator node in exynos5250-snow-common used absolute path to
reference other node (the i2c parent). Use phandle instead, because the
depth of the other node may be changed (like moving it under 'soc'
node).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5250-snow-common.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5250-snow-common.dtsi b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
index ddfe1f558c10..419d59da1751 100644
--- a/arch/arm/boot/dts/exynos5250-snow-common.dtsi
+++ b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
@@ -61,7 +61,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		i2c-parent = <&{/i2c at 12CA0000}>;
+		i2c-parent = <&i2c_4>;
 
 		our-claim-gpio = <&gpf0 3 GPIO_ACTIVE_LOW>;
 		their-claim-gpios = <&gpe0 4 GPIO_ACTIVE_LOW>;
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:49 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:49 +0200
Subject: [PATCH v4 08/22] ARM: dts: exynos: Move common nodes to exynos5.dtsi
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-9-git-send-email-krzk@kernel.org>

Exynos5420 and Exynos5250 share some nodes: the PWM, syscon
(sysreg_system_controller) and first four I2C controllers. Move them to
parent DTSI to avoid duplication.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

Important changes since v2:
1. Move also i2c[0123] to exynos5.dtsi.
---
 arch/arm/boot/dts/exynos5.dtsi    |  56 ++++++++++++++++++++
 arch/arm/boot/dts/exynos5250.dtsi | 108 ++++++++++++--------------------------
 arch/arm/boot/dts/exynos5420.dtsi | 108 ++++++++++++--------------------------
 3 files changed, 124 insertions(+), 148 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index d5c0f18a4223..c5d198c70b86 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -20,6 +20,10 @@
 	interrupt-parent = <&gic>;
 
 	aliases {
+		i2c0 = &i2c_0;
+		i2c1 = &i2c_1;
+		i2c2 = &i2c_2;
+		i2c3 = &i2c_3;
 		serial0 = &serial_0;
 		serial1 = &serial_1;
 		serial2 = &serial_2;
@@ -63,6 +67,11 @@
 		interrupts = <1 9 0xf04>;
 	};
 
+	sysreg_system_controller: syscon at 10050000 {
+		compatible = "samsung,exynos5-sysreg", "syscon";
+		reg = <0x10050000 0x5000>;
+	};
+
 	serial_0: serial at 12C00000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C00000 0x100>;
@@ -87,6 +96,53 @@
 		interrupts = <0 54 0>;
 	};
 
+	i2c_0: i2c at 12C60000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C60000 0x100>;
+		interrupts = <0 56 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,sysreg-phandle = <&sysreg_system_controller>;
+		status = "disabled";
+	};
+
+	i2c_1: i2c at 12C70000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C70000 0x100>;
+		interrupts = <0 57 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,sysreg-phandle = <&sysreg_system_controller>;
+		status = "disabled";
+	};
+
+	i2c_2: i2c at 12C80000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C80000 0x100>;
+		interrupts = <0 58 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,sysreg-phandle = <&sysreg_system_controller>;
+		status = "disabled";
+	};
+
+	i2c_3: i2c at 12C90000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C90000 0x100>;
+		interrupts = <0 59 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,sysreg-phandle = <&sysreg_system_controller>;
+		status = "disabled";
+	};
+
+	pwm: pwm at 12DD0000 {
+		compatible = "samsung,exynos4210-pwm";
+		reg = <0x12DD0000 0x100>;
+		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
+		#pwm-cells = <3>;
+	};
+
 	rtc: rtc at 101E0000 {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x101E0000 0x100>;
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index c7158b2fb213..ae4970d1c74f 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -37,10 +37,6 @@
 		mshc1 = &mmc_1;
 		mshc2 = &mmc_2;
 		mshc3 = &mmc_3;
-		i2c0 = &i2c_0;
-		i2c1 = &i2c_1;
-		i2c2 = &i2c_2;
-		i2c3 = &i2c_3;
 		i2c4 = &i2c_4;
 		i2c5 = &i2c_5;
 		i2c6 = &i2c_6;
@@ -235,11 +231,6 @@
 		interrupt-parent = <&gic>;
 	};
 
-	sysreg_system_controller: syscon at 10050000 {
-		compatible = "samsung,exynos5-sysreg", "syscon";
-		reg = <0x10050000 0x5000>;
-	};
-
 	watchdog at 101D0000 {
 		compatible = "samsung,exynos5250-wdt";
 		reg = <0x101D0000 0x100>;
@@ -328,62 +319,7 @@
 		status = "disabled";
 	};
 
-	i2c_0: i2c at 12C60000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C60000 0x100>;
-		interrupts = <0 56 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C0>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c0_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_1: i2c at 12C70000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C70000 0x100>;
-		interrupts = <0 57 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C1>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c1_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_2: i2c at 12C80000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C80000 0x100>;
-		interrupts = <0 58 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C2>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c2_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_3: i2c at 12C90000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C90000 0x100>;
-		interrupts = <0 59 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C3>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c3_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
+	/* i2c_0-3 are defined in exynos5.dtsi */
 	i2c_4: i2c at 12CA0000 {
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x12CA0000 0x100>;
@@ -662,15 +598,6 @@
 		samsung,pmureg-phandle = <&pmu_system_controller>;
 	};
 
-	pwm: pwm at 12dd0000 {
-		compatible = "samsung,exynos4210-pwm";
-		reg = <0x12dd0000 0x100>;
-		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
-		#pwm-cells = <3>;
-		clocks = <&clock CLK_PWM>;
-		clock-names = "timers";
-	};
-
 	amba {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -1070,6 +997,39 @@
 	iommus = <&sysmmu_fimd1>;
 };
 
+&i2c_0 {
+	clocks = <&clock CLK_I2C0>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_bus>;
+};
+
+&i2c_1 {
+	clocks = <&clock CLK_I2C1>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_bus>;
+};
+
+&i2c_2 {
+	clocks = <&clock CLK_I2C2>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_bus>;
+};
+
+&i2c_3 {
+	clocks = <&clock CLK_I2C3>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_bus>;
+};
+
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
+
 &rtc {
 	clocks = <&clock CLK_RTC>;
 	clock-names = "rtc";
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 549ebf23fee0..f2e8e6482888 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -30,10 +30,6 @@
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
 		pinctrl4 = &pinctrl_4;
-		i2c0 = &i2c_0;
-		i2c1 = &i2c_1;
-		i2c2 = &i2c_2;
-		i2c3 = &i2c_3;
 		i2c4 = &hsi2c_4;
 		i2c5 = &hsi2c_5;
 		i2c6 = &hsi2c_6;
@@ -542,15 +538,6 @@
 		status = "disabled";
 	};
 
-	pwm: pwm at 12dd0000 {
-		compatible = "samsung,exynos4210-pwm";
-		reg = <0x12dd0000 0x100>;
-		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
-		#pwm-cells = <3>;
-		clocks = <&clock CLK_PWM>;
-		clock-names = "timers";
-	};
-
 	dp_phy: dp-video-phy {
 		compatible = "samsung,exynos5420-dp-video-phy";
 		samsung,pmu-syscon = <&pmu_system_controller>;
@@ -588,62 +575,7 @@
 		status = "disabled";
 	};
 
-	i2c_0: i2c at 12C60000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C60000 0x100>;
-		interrupts = <0 56 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C0>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c0_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_1: i2c at 12C70000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C70000 0x100>;
-		interrupts = <0 57 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C1>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c1_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_2: i2c at 12C80000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C80000 0x100>;
-		interrupts = <0 58 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C2>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c2_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_3: i2c at 12C90000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C90000 0x100>;
-		interrupts = <0 59 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C3>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c3_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
+	/* i2c_0-3 are defined in exynos5.dtsi */
 	hsi2c_4: i2c at 12CA0000 {
 		compatible = "samsung,exynos5250-hsi2c";
 		reg = <0x12CA0000 0x1000>;
@@ -823,11 +755,6 @@
 		interrupt-parent = <&gic>;
 	};
 
-	sysreg_system_controller: syscon at 10050000 {
-		compatible = "samsung,exynos5-sysreg", "syscon";
-		reg = <0x10050000 0x5000>;
-	};
-
 	tmu_cpu0: tmu at 10060000 {
 		compatible = "samsung,exynos5420-tmu";
 		reg = <0x10060000 0x100>;
@@ -1207,6 +1134,39 @@
 	iommu-names = "m0", "m1";
 };
 
+&i2c_0 {
+	clocks = <&clock CLK_I2C0>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_bus>;
+};
+
+&i2c_1 {
+	clocks = <&clock CLK_I2C1>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_bus>;
+};
+
+&i2c_2 {
+	clocks = <&clock CLK_I2C2>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_bus>;
+};
+
+&i2c_3 {
+	clocks = <&clock CLK_I2C3>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_bus>;
+};
+
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
+
 &rtc {
 	clocks = <&clock CLK_RTC>;
 	clock-names = "rtc";
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:50 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:50 +0200
Subject: [PATCH v4 09/22] ARM: dts: exynos: Prepare for inclusion of
 exynos5.dtsi in exynos5410.dtsi
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-10-git-send-email-krzk@kernel.org>

Add 'sromc' label to SROM memory controller in common exynos5.dtsi so it
can be referenced by inheriting DTSI.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index c5d198c70b86..30a0b63b06c9 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -35,7 +35,7 @@
 		reg = <0x10000000 0x100>;
 	};
 
-	memory-controller at 12250000 {
+	sromc: memory-controller at 12250000 {
 		compatible = "samsung,exynos4210-srom";
 		reg = <0x12250000 0x14>;
 	};
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:54 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:54 +0200
Subject: [PATCH v4 13/22] ARM: dts: exynos: Enable UART3 on Exynos5410
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-14-git-send-email-krzk@kernel.org>

Just like other Exynos5 family SoCs, this one has four UARTs. Configure
clocks for UART3 and enable it.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index c8f2e4881667..0edcd7022293 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -215,7 +215,8 @@
 };
 
 &serial_3 {
-	status = "disabled";
+	clocks = <&clock CLK_UART3>, <&clock CLK_SCLK_UART3>;
+	clock-names = "uart", "clk_uart_baud0";
 };
 
 &sromc {
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:55 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:55 +0200
Subject: [PATCH v4 14/22] ARM: dts: exynos: MCT is not an interrupt controller
 and extend length of iomap
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-15-git-send-email-krzk@kernel.org>

Multi-Core Timer generates interrupts but it is not really an interrupt
controller so remove the "interrupt-controller" and "interrupt-cells"
properties. Additionally extend the length of mapped memory to cover all
registers (last SFR is at 0x0A40).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5420.dtsi | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 4b16a9376a24..872dadf0f2d4 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -263,9 +263,7 @@
 
 		mct: mct at 101C0000 {
 			compatible = "samsung,exynos4210-mct";
-			reg = <0x101C0000 0x800>;
-			interrupt-controller;
-			#interrupt-cells = <1>;
+			reg = <0x101C0000 0xB00>;
 			interrupt-parent = <&mct_map>;
 			interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
 					<8>, <9>, <10>, <11>;
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:57 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:57 +0200
Subject: [PATCH v4 16/22] ARM: dts: exynos: Add USB to Exynos5410
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-17-git-send-email-krzk@kernel.org>

Move USB 3.0 DWC and 2.0 EHCI/OHCI nodes from exynos5420.dtsi to
exynos54xx.dtsi common for entire family. For Exynos542x/5800 this
should not have functional impact but for Exynos5410 this effectively
adds USB support.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi |  39 +++++++++++
 arch/arm/boot/dts/exynos5420.dtsi | 133 +++++++++++---------------------------
 arch/arm/boot/dts/exynos54xx.dtsi |  79 ++++++++++++++++++++++
 3 files changed, 157 insertions(+), 94 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index dba6875572f2..37bd8d419c5d 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -185,4 +185,43 @@
 		  3 0 0x07000000 0x20000>;
 };
 
+&usbdrd3_0 {
+	clocks = <&clock CLK_USBD300>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy0 {
+	clocks = <&clock CLK_USBD300>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbdrd3_1 {
+	clocks = <&clock CLK_USBD301>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy1 {
+	clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbhost1 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usbhost2 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usb2_phy {
+	clocks = <&clock CLK_USBH20>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,sysreg-phandle = <&sysreg_system_controller>;
+	samsung,pmureg-phandle = <&pmu_system_controller>;
+};
+
 #include "exynos5410-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index ebf2ed3c5ff8..8fa65eb8027d 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -41,8 +41,6 @@
 		spi0 = &spi_0;
 		spi1 = &spi_1;
 		spi2 = &spi_2;
-		usbdrdphy0 = &usbdrd_phy0;
-		usbdrdphy1 = &usbdrd_phy1;
 	};
 
 	/*
@@ -770,98 +768,6 @@
 			clock-names = "secss";
 		};
 
-		usbdrd3_0: usb3-0 {
-			compatible = "samsung,exynos5250-dwusb3";
-			clocks = <&clock CLK_USBD300>;
-			clock-names = "usbdrd30";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
-
-			usbdrd_dwc3_0: dwc3 at 12000000 {
-				compatible = "snps,dwc3";
-				reg = <0x12000000 0x10000>;
-				interrupts = <0 72 0>;
-				phys = <&usbdrd_phy0 0>, <&usbdrd_phy0 1>;
-				phy-names = "usb2-phy", "usb3-phy";
-			};
-		};
-
-		usbdrd_phy0: phy at 12100000 {
-			compatible = "samsung,exynos5420-usbdrd-phy";
-			reg = <0x12100000 0x100>;
-			clocks = <&clock CLK_USBD300>, <&clock CLK_SCLK_USBPHY300>;
-			clock-names = "phy", "ref";
-			samsung,pmu-syscon = <&pmu_system_controller>;
-			#phy-cells = <1>;
-		};
-
-		usbdrd3_1: usb3-1 {
-			compatible = "samsung,exynos5250-dwusb3";
-			clocks = <&clock CLK_USBD301>;
-			clock-names = "usbdrd30";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
-
-			usbdrd_dwc3_1: dwc3 at 12400000 {
-				compatible = "snps,dwc3";
-				reg = <0x12400000 0x10000>;
-				interrupts = <0 73 0>;
-				phys = <&usbdrd_phy1 0>, <&usbdrd_phy1 1>;
-				phy-names = "usb2-phy", "usb3-phy";
-			};
-		};
-
-		usbdrd_phy1: phy at 12500000 {
-			compatible = "samsung,exynos5420-usbdrd-phy";
-			reg = <0x12500000 0x100>;
-			clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
-			clock-names = "phy", "ref";
-			samsung,pmu-syscon = <&pmu_system_controller>;
-			#phy-cells = <1>;
-		};
-
-		usbhost2: usb at 12110000 {
-			compatible = "samsung,exynos4210-ehci";
-			reg = <0x12110000 0x100>;
-			interrupts = <0 71 0>;
-
-			clocks = <&clock CLK_USBH20>;
-			clock-names = "usbhost";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			port at 0 {
-				reg = <0>;
-				phys = <&usb2_phy 1>;
-			};
-		};
-
-		usbhost1: usb at 12120000 {
-			compatible = "samsung,exynos4210-ohci";
-			reg = <0x12120000 0x100>;
-			interrupts = <0 71 0>;
-
-			clocks = <&clock CLK_USBH20>;
-			clock-names = "usbhost";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			port at 0 {
-				reg = <0>;
-				phys = <&usb2_phy 1>;
-			};
-		};
-
-		usb2_phy: phy at 12130000 {
-			compatible = "samsung,exynos5250-usb2-phy";
-			reg = <0x12130000 0x100>;
-			clocks = <&clock CLK_USBH20>, <&clock CLK_SCLK_USBPHY300>;
-			clock-names = "phy", "ref";
-			#phy-cells = <1>;
-			samsung,sysreg-phandle = <&sysreg_system_controller>;
-			samsung,pmureg-phandle = <&pmu_system_controller>;
-		};
-
 		sysmmu_g2dr: sysmmu at 0x10A60000 {
 			compatible = "samsung,exynos-sysmmu";
 			reg = <0x10A60000 0x1000>;
@@ -1153,4 +1059,43 @@
 	clock-names = "uart", "clk_uart_baud0";
 };
 
+&usbdrd3_0 {
+	clocks = <&clock CLK_USBD300>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy0 {
+	clocks = <&clock CLK_USBD300>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbdrd3_1 {
+	clocks = <&clock CLK_USBD301>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy1 {
+	clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbhost1 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usbhost2 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usb2_phy {
+	clocks = <&clock CLK_USBH20>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,sysreg-phandle = <&sysreg_system_controller>;
+	samsung,pmureg-phandle = <&pmu_system_controller>;
+};
+
 #include "exynos5420-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi
index 9ce625bd79c1..a9a062708237 100644
--- a/arch/arm/boot/dts/exynos54xx.dtsi
+++ b/arch/arm/boot/dts/exynos54xx.dtsi
@@ -20,6 +20,11 @@
 / {
 	compatible = "samsung,exynos5";
 
+	aliases {
+		usbdrdphy0 = &usbdrd_phy0;
+		usbdrdphy1 = &usbdrd_phy1;
+	};
+
 	soc: soc {
 		sysram at 02020000 {
 			compatible = "mmio-sram";
@@ -64,5 +69,79 @@
 						<11 &gic 0 131 0>;
 			};
 		};
+
+		usbdrd3_0: usb3-0 {
+			compatible = "samsung,exynos5250-dwusb3";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			usbdrd_dwc3_0: dwc3 at 12000000 {
+				compatible = "snps,dwc3";
+				reg = <0x12000000 0x10000>;
+				interrupts = <0 72 0>;
+				phys = <&usbdrd_phy0 0>, <&usbdrd_phy0 1>;
+				phy-names = "usb2-phy", "usb3-phy";
+			};
+		};
+
+		usbdrd_phy0: phy at 12100000 {
+			compatible = "samsung,exynos5420-usbdrd-phy";
+			reg = <0x12100000 0x100>;
+			#phy-cells = <1>;
+		};
+
+		usbdrd3_1: usb3-1 {
+			compatible = "samsung,exynos5250-dwusb3";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			usbdrd_dwc3_1: dwc3 at 12400000 {
+				compatible = "snps,dwc3";
+				reg = <0x12400000 0x10000>;
+				interrupts = <0 73 0>;
+				phys = <&usbdrd_phy1 0>, <&usbdrd_phy1 1>;
+				phy-names = "usb2-phy", "usb3-phy";
+			};
+		};
+
+		usbdrd_phy1: phy at 12500000 {
+			compatible = "samsung,exynos5420-usbdrd-phy";
+			reg = <0x12500000 0x100>;
+			#phy-cells = <1>;
+		};
+
+		usbhost2: usb at 12110000 {
+			compatible = "samsung,exynos4210-ehci";
+			reg = <0x12110000 0x100>;
+			interrupts = <0 71 0>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port at 0 {
+				reg = <0>;
+				phys = <&usb2_phy 1>;
+			};
+		};
+
+		usbhost1: usb at 12120000 {
+			compatible = "samsung,exynos4210-ohci";
+			reg = <0x12120000 0x100>;
+			interrupts = <0 71 0>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port at 0 {
+				reg = <0>;
+				phys = <&usb2_phy 1>;
+			};
+		};
+
+		usb2_phy: phy at 12130000 {
+			compatible = "samsung,exynos5250-usb2-phy";
+			reg = <0x12130000 0x100>;
+			#phy-cells = <1>;
+		};
 	};
 };
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:59 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:59 +0200
Subject: [PATCH v4 18/22] dt-bindings: clock: Add I2C,
 HSI2C and RTC clock IDs to Exynos5410
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-19-git-send-email-krzk@kernel.org>

Add IDs for I2C, USI (HSI2C) and RTC clocks to Exynos5410. Use the same
number as for Exynos5420 just in case in future these drivers were
merged.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 include/dt-bindings/clock/exynos5410.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 34c8e96987a1..e94b7bbfd6af 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -38,9 +38,18 @@
 #define CLK_UART0		257
 #define CLK_UART1		258
 #define CLK_UART2		259
+#define CLK_I2C0		261
+#define CLK_I2C1		262
+#define CLK_I2C2		263
+#define CLK_I2C3		264
+#define CLK_USI0		265
+#define CLK_USI1		266
+#define CLK_USI2		267
+#define CLK_USI3		268
 #define CLK_UART3		260
 #define CLK_PWM			279
 #define CLK_MCT			315
+#define CLK_RTC			317
 #define CLK_MMC0		351
 #define CLK_MMC1		352
 #define CLK_MMC2		353
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:14:01 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:14:01 +0200
Subject: [PATCH v4 20/22] ARM: dts: exynos: Move HSI2C nodes to exynos54xx.dtsi
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-21-git-send-email-krzk@kernel.org>

The USI/HSI2C nodes can be mostly shared between Exynos5420 and
Exynos5410 so move them to common DTSI.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5420.dtsi | 32 ++++++++++++++++++++++++++----
 arch/arm/boot/dts/exynos54xx.dtsi | 41 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 8fa65eb8027d..791243694aa5 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -29,10 +29,6 @@
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
 		pinctrl4 = &pinctrl_4;
-		i2c4 = &hsi2c_4;
-		i2c5 = &hsi2c_5;
-		i2c6 = &hsi2c_6;
-		i2c7 = &hsi2c_7;
 		i2c8 = &hsi2c_8;
 		i2c9 = &hsi2c_9;
 		i2c10 = &hsi2c_10;
@@ -1022,6 +1018,34 @@
 	pinctrl-0 = <&i2c3_bus>;
 };
 
+&hsi2c_4 {
+	clocks = <&clock CLK_USI0>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_hs_bus>;
+};
+
+&hsi2c_5 {
+	clocks = <&clock CLK_USI1>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c5_hs_bus>;
+};
+
+&hsi2c_6 {
+	clocks = <&clock CLK_USI2>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c6_hs_bus>;
+};
+
+&hsi2c_7 {
+	clocks = <&clock CLK_USI3>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c7_hs_bus>;
+};
+
 &mct {
 	clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
 	clock-names = "fin_pll", "mct";
diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi
index a9a062708237..317612089b50 100644
--- a/arch/arm/boot/dts/exynos54xx.dtsi
+++ b/arch/arm/boot/dts/exynos54xx.dtsi
@@ -21,6 +21,10 @@
 	compatible = "samsung,exynos5";
 
 	aliases {
+		i2c4 = &hsi2c_4;
+		i2c5 = &hsi2c_5;
+		i2c6 = &hsi2c_6;
+		i2c7 = &hsi2c_7;
 		usbdrdphy0 = &usbdrd_phy0;
 		usbdrdphy1 = &usbdrd_phy1;
 	};
@@ -70,6 +74,43 @@
 			};
 		};
 
+		/* i2c_0-3 are defined in exynos5.dtsi */
+		hsi2c_4: i2c at 12CA0000 {
+			compatible = "samsung,exynos5250-hsi2c";
+			reg = <0x12CA0000 0x1000>;
+			interrupts = <0 60 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		hsi2c_5: i2c at 12CB0000 {
+			compatible = "samsung,exynos5250-hsi2c";
+			reg = <0x12CB0000 0x1000>;
+			interrupts = <0 61 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		hsi2c_6: i2c at 12CC0000 {
+			compatible = "samsung,exynos5250-hsi2c";
+			reg = <0x12CC0000 0x1000>;
+			interrupts = <0 62 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		hsi2c_7: i2c at 12CD0000 {
+			compatible = "samsung,exynos5250-hsi2c";
+			reg = <0x12CD0000 0x1000>;
+			interrupts = <0 63 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		usbdrd3_0: usb3-0 {
 			compatible = "samsung,exynos5250-dwusb3";
 			#address-cells = <1>;
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:53 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:53 +0200
Subject: [PATCH v4 12/22] ARM: dts: exynos: Include common exynos5 in
 exynos5410.dtsi
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-13-git-send-email-krzk@kernel.org>

The exynos5.dtsi is used for common nodes shared between Exynos5250 and
Exynos542x. Since Exynos5410 is very similar to Exynos5420 it can
include the common file as well to remove duplication and make
everything more consistent.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410-smdk5410.dts |   6 +-
 arch/arm/boot/dts/exynos5410.dtsi         | 103 ++++++++++--------------------
 2 files changed, 35 insertions(+), 74 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts
index 0f6429e1b75c..777fcf2edd79 100644
--- a/arch/arm/boot/dts/exynos5410-smdk5410.dts
+++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts
@@ -102,14 +102,14 @@
 	};
 };
 
-&uart0 {
+&serial_0 {
 	status = "okay";
 };
 
-&uart1 {
+&serial_1 {
 	status = "okay";
 };
 
-&uart2 {
+&serial_2 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 8de8c644f42e..c8f2e4881667 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -14,6 +14,7 @@
  */
 
 #include "skeleton.dtsi"
+#include "exynos5.dtsi"
 #include "exynos-syscon-restart.dtsi"
 #include <dt-bindings/clock/exynos5410.h>
 
@@ -26,9 +27,6 @@
 		pinctrl1 = &pinctrl_1;
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
-		serial0 = &uart0;
-		serial1 = &uart1;
-		serial2 = &uart2;
 	};
 
 	cpus {
@@ -70,49 +68,6 @@
 		#size-cells = <1>;
 		ranges;
 
-		combiner: interrupt-controller at 10440000 {
-			compatible = "samsung,exynos4210-combiner";
-			#interrupt-cells = <2>;
-			interrupt-controller;
-			samsung,combiner-nr = <32>;
-			reg = <0x10440000 0x1000>;
-			interrupts =	<0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
-					<0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
-					<0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
-					<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
-					<0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-					<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
-					<0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-					<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
-		};
-
-		gic: interrupt-controller at 10481000 {
-			compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
-			#interrupt-cells = <3>;
-			interrupt-controller;
-			reg =	<0x10481000 0x1000>,
-				<0x10482000 0x1000>,
-				<0x10484000 0x2000>,
-				<0x10486000 0x2000>;
-			interrupts = <1 9 0xf04>;
-		};
-
-		chipid at 10000000 {
-			compatible = "samsung,exynos4210-chipid";
-			reg = <0x10000000 0x100>;
-		};
-
-		sromc: memory-controller at 12250000 {
-			compatible = "samsung,exynos4210-srom";
-			reg = <0x12250000 0x14>;
-			#address-cells = <2>;
-			#size-cells = <1>;
-			ranges = <0 0 0x04000000 0x20000
-				  1 0 0x05000000 0x20000
-				  2 0 0x06000000 0x20000
-				  3 0 0x07000000 0x20000>;
-		};
-
 		pmu_system_controller: system-controller at 10040000 {
 			compatible = "samsung,exynos5410-pmu", "syscon";
 			reg = <0x10040000 0x5000>;
@@ -236,34 +191,40 @@
 			reg = <0x03860000 0x1000>;
 			interrupts = <0 47 0>;
 		};
+	};
+};
 
-		uart0: serial at 12C00000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C00000 0x100>;
-			interrupts = <0 51 0>;
-			clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
 
-		uart1: serial at 12C10000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C10000 0x100>;
-			interrupts = <0 52 0>;
-			clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
+&serial_0 {
+	clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
+	clock-names = "uart", "clk_uart_baud0";
+};
 
-		uart2: serial at 12C20000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C20000 0x100>;
-			interrupts = <0 53 0>;
-			clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
-	};
+&serial_1 {
+	clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
+	clock-names = "uart", "clk_uart_baud0";
+};
+
+&serial_2 {
+	clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
+	clock-names = "uart", "clk_uart_baud0";
+};
+
+&serial_3 {
+	status = "disabled";
+};
+
+&sromc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	ranges = <0 0 0x04000000 0x20000
+		  1 0 0x05000000 0x20000
+		  2 0 0x06000000 0x20000
+		  3 0 0x07000000 0x20000>;
 };
 
 #include "exynos5410-pinctrl.dtsi"
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:14:03 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:14:03 +0200
Subject: [PATCH v4 22/22] ARM: dts: exynos: Add RTC and I2C to Exynos5410
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-23-git-send-email-krzk@kernel.org>

Configure Exynos5410-specific properties of RTC, I2C and HSI2C nodes.
This still does not enable them on the board level though.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 63 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 37bd8d419c5d..46607d88cf53 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -146,6 +146,62 @@
 	};
 };
 
+&i2c_0 {
+	clocks = <&clock CLK_I2C0>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_bus>;
+};
+
+&i2c_1 {
+	clocks = <&clock CLK_I2C1>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_bus>;
+};
+
+&i2c_2 {
+	clocks = <&clock CLK_I2C2>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_bus>;
+};
+
+&i2c_3 {
+	clocks = <&clock CLK_I2C3>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_bus>;
+};
+
+&hsi2c_4 {
+	clocks = <&clock CLK_USI0>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_hs_bus>;
+};
+
+&hsi2c_5 {
+	clocks = <&clock CLK_USI1>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c5_hs_bus>;
+};
+
+&hsi2c_6 {
+	clocks = <&clock CLK_USI2>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c6_hs_bus>;
+};
+
+&hsi2c_7 {
+	clocks = <&clock CLK_USI3>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c7_hs_bus>;
+};
+
 &mct {
 	clocks = <&fin_pll>, <&clock CLK_MCT>;
 	clock-names = "fin_pll", "mct";
@@ -156,6 +212,13 @@
 	clock-names = "timers";
 };
 
+&rtc {
+	clocks = <&clock CLK_RTC>;
+	clock-names = "rtc";
+	interrupt-parent = <&pmu_system_controller>;
+	status = "disabled";
+};
+
 &serial_0 {
 	clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
 	clock-names = "uart", "clk_uart_baud0";
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:14:02 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:14:02 +0200
Subject: [PATCH v4 21/22] ARM: dts: exynos: Add I2C,
 PWM and UART pinctrl to Exynos5410
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-22-git-send-email-krzk@kernel.org>

Add pincontrol groups for HSI2C (USI), I2C, PWM and UART to Exynos5410.
This allows configuring these pins to specific functions.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 133 ++++++++++++++++++++++++++++++
 1 file changed, 133 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
index ddacafa1e907..b58a0f29f42c 100644
--- a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
@@ -278,6 +278,139 @@
 		#interrupt-cells = <2>;
 	};
 
+	uart0_data: uart0-data {
+		samsung,pins = "gpa0-0", "gpa0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart0_fctl: uart0-fctl {
+		samsung,pins = "gpa0-2", "gpa0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart1_data: uart1-data {
+		samsung,pins = "gpa0-4", "gpa0-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart1_fctl: uart1-fctl {
+		samsung,pins = "gpa0-6", "gpa0-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c2_bus: i2c2-bus {
+		samsung,pins = "gpa0-6", "gpa0-7";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart2_data: uart2-data {
+		samsung,pins = "gpa1-0", "gpa1-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart2_fctl: uart2-fctl {
+		samsung,pins = "gpa1-2", "gpa1-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c3_bus: i2c3-bus {
+		samsung,pins = "gpa1-2", "gpa1-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart3_data: uart3-data {
+		samsung,pins = "gpa1-4", "gpa1-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c4_hs_bus: i2c4-hs-bus {
+		samsung,pins = "gpa2-0", "gpa2-1";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c5_hs_bus: i2c5-hs-bus {
+		samsung,pins = "gpa2-2", "gpa2-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c6_hs_bus: i2c6-hs-bus {
+		samsung,pins = "gpb1-3", "gpb1-4";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm0_out: pwm0-out {
+		samsung,pins = "gpb2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm1_out: pwm1-out {
+		samsung,pins = "gpb2-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm2_out: pwm2-out {
+		samsung,pins = "gpb2-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm3_out: pwm3-out {
+		samsung,pins = "gpb2-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c7_hs_bus: i2c7-hs-bus {
+		samsung,pins = "gpb2-2", "gpb2-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c0_bus: i2c0-bus {
+		samsung,pins = "gpb3-0", "gpb3-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c1_bus: i2c1-bus {
+		samsung,pins = "gpb3-2", "gpb3-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
 	sd0_clk: sd0-clk {
 		samsung,pins = "gpc0-0";
 		samsung,pin-function = <2>;
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:56 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:56 +0200
Subject: [PATCH v4 15/22] ARM: dts: exynos: Move common Exynos5410/542x/5800
 nodes to new DTSI
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-16-git-send-email-krzk@kernel.org>

The Exynos5410/542x/5800 are very similar designs. Create a new
DTSI with common nodes to remove DTS duplication. Although currently
only MCT and SysRAM are shared but in future more nodes will be added to
the common file.

The patch should not have functional impact.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 55 ++++---------------------------
 arch/arm/boot/dts/exynos5420.dtsi | 54 ++++---------------------------
 arch/arm/boot/dts/exynos54xx.dtsi | 68 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+), 97 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos54xx.dtsi

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 0edcd7022293..dba6875572f2 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -13,8 +13,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "skeleton.dtsi"
-#include "exynos5.dtsi"
+#include "exynos54xx.dtsi"
 #include "exynos-syscon-restart.dtsi"
 #include <dt-bindings/clock/exynos5410.h>
 
@@ -73,53 +72,6 @@
 			reg = <0x10040000 0x5000>;
 		};
 
-		mct: mct at 101C0000 {
-			compatible = "samsung,exynos4210-mct";
-			reg = <0x101C0000 0xB00>;
-			interrupt-parent = <&interrupt_map>;
-			interrupts = <0>, <1>, <2>, <3>,
-				<4>, <5>, <6>, <7>,
-				<8>, <9>, <10>, <11>;
-			clocks = <&fin_pll>, <&clock CLK_MCT>;
-			clock-names = "fin_pll", "mct";
-
-			interrupt_map: interrupt-map {
-				#interrupt-cells = <1>;
-				#address-cells = <0>;
-				#size-cells = <0>;
-				interrupt-map = <0 &combiner 23 3>,
-						<1 &combiner 23 4>,
-						<2 &combiner 25 2>,
-						<3 &combiner 25 3>,
-						<4 &gic 0 120 0>,
-						<5 &gic 0 121 0>,
-						<6 &gic 0 122 0>,
-						<7 &gic 0 123 0>,
-						<8 &gic 0 128 0>,
-						<9 &gic 0 129 0>,
-						<10 &gic 0 130 0>,
-						<11 &gic 0 131 0>;
-			};
-		};
-
-		sysram at 02020000 {
-			compatible = "mmio-sram";
-			reg = <0x02020000 0x54000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x02020000 0x54000>;
-
-			smp-sysram at 0 {
-				compatible = "samsung,exynos4210-sysram";
-				reg = <0x0 0x1000>;
-			};
-
-			smp-sysram at 53000 {
-				compatible = "samsung,exynos4210-sysram-ns";
-				reg = <0x53000 0x1000>;
-			};
-		};
-
 		clock: clock-controller at 10010000 {
 			compatible = "samsung,exynos5410-clock";
 			reg = <0x10010000 0x30000>;
@@ -194,6 +146,11 @@
 	};
 };
 
+&mct {
+	clocks = <&fin_pll>, <&clock CLK_MCT>;
+	clock-names = "fin_pll", "mct";
+};
+
 &pwm {
 	clocks = <&clock CLK_PWM>;
 	clock-names = "timers";
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 872dadf0f2d4..ebf2ed3c5ff8 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -13,9 +13,8 @@
  * published by the Free Software Foundation.
  */
 
+#include "exynos54xx.dtsi"
 #include <dt-bindings/clock/exynos5420.h>
-#include "exynos5.dtsi"
-
 #include <dt-bindings/clock/exynos-audss-clk.h>
 
 / {
@@ -181,24 +180,6 @@
 			};
 		};
 
-		sysram at 02020000 {
-			compatible = "mmio-sram";
-			reg = <0x02020000 0x54000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x02020000 0x54000>;
-
-			smp-sysram at 0 {
-				compatible = "samsung,exynos4210-sysram";
-				reg = <0x0 0x1000>;
-			};
-
-			smp-sysram at 53000 {
-				compatible = "samsung,exynos4210-sysram-ns";
-				reg = <0x53000 0x1000>;
-			};
-		};
-
 		clock: clock-controller at 10010000 {
 			compatible = "samsung,exynos5420-clock";
 			reg = <0x10010000 0x30000>;
@@ -261,34 +242,6 @@
 			status = "disabled";
 		};
 
-		mct: mct at 101C0000 {
-			compatible = "samsung,exynos4210-mct";
-			reg = <0x101C0000 0xB00>;
-			interrupt-parent = <&mct_map>;
-			interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
-					<8>, <9>, <10>, <11>;
-			clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
-			clock-names = "fin_pll", "mct";
-
-			mct_map: mct-map {
-				#interrupt-cells = <1>;
-				#address-cells = <0>;
-				#size-cells = <0>;
-				interrupt-map = <0 &combiner 23 3>,
-						<1 &combiner 23 4>,
-						<2 &combiner 25 2>,
-						<3 &combiner 25 3>,
-						<4 &gic 0 120 0>,
-						<5 &gic 0 121 0>,
-						<6 &gic 0 122 0>,
-						<7 &gic 0 123 0>,
-						<8 &gic 0 128 0>,
-						<9 &gic 0 129 0>,
-						<10 &gic 0 130 0>,
-						<11 &gic 0 131 0>;
-			};
-		};
-
 		gsc_pd: power-domain at 10044000 {
 			compatible = "samsung,exynos4210-pd";
 			reg = <0x10044000 0x20>;
@@ -1163,6 +1116,11 @@
 	pinctrl-0 = <&i2c3_bus>;
 };
 
+&mct {
+	clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
+	clock-names = "fin_pll", "mct";
+};
+
 &pwm {
 	clocks = <&clock CLK_PWM>;
 	clock-names = "timers";
diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi
new file mode 100644
index 000000000000..9ce625bd79c1
--- /dev/null
+++ b/arch/arm/boot/dts/exynos54xx.dtsi
@@ -0,0 +1,68 @@
+/*
+ * Samsung's Exynos54xx SoC series common device tree source
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2016 Krzysztof Kozlowski
+ *
+ * Device nodes common for Samsung Exynos5410/5420/5422/5800. Specific
+ * Exynos 54xx SoCs should include this file and customize it further
+ * (e.g. with clocks).
+ *
+ * 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 "skeleton.dtsi"
+#include "exynos5.dtsi"
+
+/ {
+	compatible = "samsung,exynos5";
+
+	soc: soc {
+		sysram at 02020000 {
+			compatible = "mmio-sram";
+			reg = <0x02020000 0x54000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x02020000 0x54000>;
+
+			smp-sysram at 0 {
+				compatible = "samsung,exynos4210-sysram";
+				reg = <0x0 0x1000>;
+			};
+
+			smp-sysram at 53000 {
+				compatible = "samsung,exynos4210-sysram-ns";
+				reg = <0x53000 0x1000>;
+			};
+		};
+
+		mct: mct at 101C0000 {
+			compatible = "samsung,exynos4210-mct";
+			reg = <0x101C0000 0xB00>;
+			interrupt-parent = <&mct_map>;
+			interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
+					<8>, <9>, <10>, <11>;
+
+			mct_map: mct-map {
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = <0 &combiner 23 3>,
+						<1 &combiner 23 4>,
+						<2 &combiner 25 2>,
+						<3 &combiner 25 3>,
+						<4 &gic 0 120 0>,
+						<5 &gic 0 121 0>,
+						<6 &gic 0 122 0>,
+						<7 &gic 0 123 0>,
+						<8 &gic 0 128 0>,
+						<9 &gic 0 129 0>,
+						<10 &gic 0 130 0>,
+						<11 &gic 0 131 0>;
+			};
+		};
+	};
+};
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:13:58 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:13:58 +0200
Subject: [PATCH v4 17/22] ARM: dts: exynos: Add initial support for Odroid XU
 board
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-18-git-send-email-krzk@kernel.org>

The Hardkernel's Odroid XU board was first design with big.LITTLE SoC
from Samsung: the Exynos5410. Comparing the board to more popular now
Odroid XU3, the differences are:
1. Exynos5410 instead of 5422,
2. MIPI DSI LCD connector,
3. Main PMIC: Maxim 77802 instead of S2MPS11,
4. USB3503+LAN9730 instead of integrated LAN9514,
5. eMMC 4.5 instead of eMMC 5.0,

This patch adds initial support for the XU board with working basic
functions, eMMC/SD and USB (including attached ethernet adapter).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Rob Herring <robh at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 .../bindings/arm/samsung/samsung-boards.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/exynos5410-odroidxu.dts          | 121 +++++++++++++++++++++
 3 files changed, 123 insertions(+)
 create mode 100644 arch/arm/boot/dts/exynos5410-odroidxu.dts

diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
index f5deace2b380..0ea7f14ef294 100644
--- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
+++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
@@ -47,6 +47,7 @@ Required root node properties:
 	- "hardkernel,odroid-u3"  - for Exynos4412-based Hardkernel Odroid U3.
 	- "hardkernel,odroid-x"   - for Exynos4412-based Hardkernel Odroid X.
 	- "hardkernel,odroid-x2"  - for Exynos4412-based Hardkernel Odroid X2.
+	- "hardkernel,odroid-xu"  - for Exynos5410-based Hardkernel Odroid XU.
 	- "hardkernel,odroid-xu3" - for Exynos5422-based Hardkernel Odroid XU3.
 	- "hardkernel,odroid-xu3-lite" - for Exynos5422-based Hardkernel
 					 Odroid XU3 Lite board.
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 5aeb10674370..9ed1c7abedb1 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -134,6 +134,7 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \
 	exynos5250-snow-rev5.dtb \
 	exynos5250-spring.dtb \
 	exynos5260-xyref5260.dtb \
+	exynos5410-odroidxu.dtb \
 	exynos5410-smdk5410.dtb \
 	exynos5420-arndale-octa.dtb \
 	exynos5420-peach-pit.dtb \
diff --git a/arch/arm/boot/dts/exynos5410-odroidxu.dts b/arch/arm/boot/dts/exynos5410-odroidxu.dts
new file mode 100644
index 000000000000..9fe04500ecaf
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5410-odroidxu.dts
@@ -0,0 +1,121 @@
+/*
+ * Hardkernel Odroid XU board device tree source
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2016 Krzysztof Kozlowski
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include "exynos5410.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "exynos54xx-odroidxu-leds.dtsi"
+
+/ {
+	model = "Hardkernel Odroid XU";
+	compatible = "hardkernel,odroid-xu", "samsung,exynos5410", "samsung,exynos5";
+
+	memory {
+		reg = <0x40000000 0x7ea00000>;
+	};
+
+	chosen {
+		linux,stdout-path = &serial_2;
+	};
+
+	emmc_pwrseq: pwrseq {
+		pinctrl-0 = <&emmc_nrst_pin>;
+		pinctrl-names = "default";
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpd1 0 GPIO_ACTIVE_LOW>;
+	};
+
+	fan0: pwm-fan {
+		compatible = "pwm-fan";
+		pwms = <&pwm 0 20972 0>;
+		cooling-min-state = <0>;
+		cooling-max-state = <3>;
+		#cooling-cells = <2>;
+		cooling-levels = <0 130 170 230>;
+	};
+
+	fin_pll: xxti {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "fin_pll";
+		#clock-cells = <0>;
+	};
+
+	firmware at 02073000 {
+		compatible = "samsung,secure-firmware";
+		reg = <0x02073000 0x1000>;
+	};
+};
+
+&mmc_0 {
+	status = "okay";
+	mmc-pwrseq = <&emmc_pwrseq>;
+	cd-gpios = <&gpc0 2 GPIO_ACTIVE_LOW>;
+	card-detect-delay = <200>;
+	samsung,dw-mshc-ciu-div = <3>;
+	samsung,dw-mshc-sdr-timing = <0 4>;
+	samsung,dw-mshc-ddr-timing = <0 2>;
+	samsung,dw-mshc-hs400-timing = <0 2>;
+	samsung,read-strobe-delay = <90>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8 &sd0_cd>;
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
+};
+
+&mmc_2 {
+	status = "okay";
+	card-detect-delay = <200>;
+	samsung,dw-mshc-ciu-div = <3>;
+	samsung,dw-mshc-sdr-timing = <0 4>;
+	samsung,dw-mshc-ddr-timing = <0 2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
+	bus-width = <4>;
+	cap-sd-highspeed;
+};
+
+&pinctrl_0 {
+	emmc_nrst_pin: emmc-nrst {
+		samsung,pins = "gpd1-0";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+};
+
+&serial_0 {
+	status = "okay";
+};
+
+&serial_1 {
+	status = "okay";
+};
+
+&serial_2 {
+	status = "okay";
+};
+
+&serial_3 {
+	status = "okay";
+};
+
+&usbdrd_dwc3_0 {
+	dr_mode = "host";
+};
+
+&usbdrd_dwc3_1 {
+	dr_mode = "peripheral";
+};
-- 
2.5.0



From krzk at kernel.org  Sun May 15 13:14:00 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 15 May 2016 22:14:00 +0200
Subject: [PATCH v4 19/22] clk: samsung: exynos5410: Add I2C,
 HSI2C and RTC clocks
In-Reply-To: <1463343243-26429-1-git-send-email-krzk@kernel.org>
References: <1463343243-26429-1-git-send-email-krzk@kernel.org>
Message-ID: <1463343243-26429-20-git-send-email-krzk@kernel.org>

Add clocks for I2C, USI (HSI2C) and RTC to the Exynos5410 clock driver.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 drivers/clk/samsung/clk-exynos5410.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index 5f892128849a..6c2e59c576ee 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -159,6 +159,7 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 
 static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 	GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
+	GATE(CLK_RTC, "rtc", "aclk66", GATE_IP_PERIS, 20, 0, 0),
 
 	GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
 			SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
@@ -187,6 +188,14 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 	GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
 	GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
 	GATE(CLK_UART3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0),
+	GATE(CLK_I2C0, "i2c0", "aclk66", GATE_IP_PERIC, 6, 0, 0),
+	GATE(CLK_I2C1, "i2c1", "aclk66", GATE_IP_PERIC, 7, 0, 0),
+	GATE(CLK_I2C2, "i2c2", "aclk66", GATE_IP_PERIC, 8, 0, 0),
+	GATE(CLK_I2C3, "i2c3", "aclk66", GATE_IP_PERIC, 9, 0, 0),
+	GATE(CLK_USI0, "usi0", "aclk66", GATE_IP_PERIC, 10, 0, 0),
+	GATE(CLK_USI1, "usi1", "aclk66", GATE_IP_PERIC, 11, 0, 0),
+	GATE(CLK_USI2, "usi2", "aclk66", GATE_IP_PERIC, 12, 0, 0),
+	GATE(CLK_USI3, "usi3", "aclk66", GATE_IP_PERIC, 13, 0, 0),
 	GATE(CLK_PWM, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0),
 
 	GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
-- 
2.5.0



From robert.jarzmik at free.fr  Sun May 15 14:29:27 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Sun, 15 May 2016 23:29:27 +0200
Subject: [RFC PATCH 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <s5hy47c7jvd.wl-tiwai@suse.de> (Takashi Iwai's message of "Sat,
 14 May 2016 17:13:42 +0200")
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
 <s5hk2j38tmf.wl-tiwai@suse.de> <87twi1hssl.fsf@belgarion.home>
 <s5hy47c7jvd.wl-tiwai@suse.de>
Message-ID: <87mvnrhux4.fsf@belgarion.home>

Takashi Iwai <tiwai at suse.de> writes:

> On Sat, 14 May 2016 11:50:50 +0200,
> Robert Jarzmik wrote:
>> >> +unsigned int ac97_bus_scan_one(struct ac97_controller *ac97,
>> >> +				      int codec_num)
>> >> +{
>> >> +	struct ac97_codec_device codec;
>> >> +	unsigned short vid1, vid2;
>> >> +	int ret;
>> >> +
>> >> +	codec.dev = *ac97->dev;
>> >> +	codec.num = codec_num;
>> >> +	ret = ac97->ops->read(&codec, AC97_VENDOR_ID1);
>> >> +	vid1 = (ret & 0xffff);
>> >> +	if (ret < 0)
>> >> +		return 0;
>> >
>> > Hmm.  This looks pretty hackish and dangerous.
>> You mean returning 0 even if the read failed, right ?
>
> No, my concern is that it's creating a dummy codec object temporarily
> on the stack just by copying some fields and calling the ops with it.
> (And actually the current code may work wrongly because lack of
>  zero-clear of the object.)
Ah yes, I remember now, the on-stack generated device, indeed ugly.

> IMO, a cleaner way would be to define the ops passed with both
> controller and codec objects as arguments, and pass NULL codec here.
It's rather unusual to need both the device and its controller in bus
operations. I must admit I have no better idea so far, so I'll try that just to
see how it looks like, and let's see next ...

Cheers.

-- 
Robert


From kuninori.morimoto.gx at renesas.com  Sun May 15 17:29:14 2016
From: kuninori.morimoto.gx at renesas.com (Kuninori Morimoto)
Date: Mon, 16 May 2016 00:29:14 +0000
Subject: [PATCH 00/23] ARM/arm64: dts: renesas: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <87wpmuetqv.wl%kuninori.morimoto.gx@renesas.com>


Hi Geert

> This patch series fixes the new warnings related to Renesas arm32/arm64
> DTSes that can be seen in -next using "make W=1 dtbs", courtesy of
> commit b993734718c01064 ("scripts/dtc: Update to upstream version
> 53bf130b1cdd") in Rob herring's for-next branch. They're all of the
> form:
> 
>     Warning (unit_address_vs_reg): Node /cache-controller at 0 has a unit name, but no reg property
>     Warning (unit_address_vs_reg): Node /cache-controller has a reg or ranges property, but no unit name
>     Warning (unit_address_vs_reg): Node /clocks at e0110000/iic0_sclkdiv has a reg or ranges property, but no unit name
>     Warning (unit_address_vs_reg): Node /i2c at 2 has a unit name, but no reg property
>     Warning (unit_address_vs_reg): Node /keyboard/button at 1 has a unit name, but no reg property
>     Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
>     Warning (unit_address_vs_reg): Node /pfc at e0140200/serial at e1030000 has a unit name, but no reg property
>     Warning (unit_address_vs_reg): Node /regulator at 0 has a unit name, but no reg property
>     Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ctu/ctu at 0 has a unit name, but no reg property
>     Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,dvc/dvc at 0 has a unit name, but no reg property
>     Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,mix/mix at 0 has a unit name, but no reg property
>     Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,src/src at 0 has a unit name, but no reg property
>     Warning (unit_address_vs_reg): Node /sound at ec500000/rcar_sound,ssi/ssi at 0 has a unit name, but no reg property
(snip)
> Morimoto-san: If this is accepted, the examples in
> Documentation/devicetree/bindings/sound/renesas,rsnd.txt should be
> updated, too.

Thanks. will do.

Best regards
---
Kuninori Morimoto


From wangkefeng.wang at huawei.com  Sun May 15 18:11:33 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Mon, 16 May 2016 09:11:33 +0800
Subject: [PATCH 1/2] arm64: dts: NS2: Add all of the UARTs
In-Reply-To: <CAC3K-4oXcwR--879sCFR=MCG1Uman7DoGvaHLVXWr+0QH2WeJg@mail.gmail.com>
References: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
 <57341FCE.6050403@huawei.com>
 <CAC3K-4qbkt3DCgd6qurNo3V+++x70bbFC--aunR0DbCTBvBNZg@mail.gmail.com>
 <57353761.5020409@huawei.com>
 <CAC3K-4oXcwR--879sCFR=MCG1Uman7DoGvaHLVXWr+0QH2WeJg@mail.gmail.com>
Message-ID: <57391E45.8010209@huawei.com>



On 2016/5/14 0:49, Jon Mason wrote:
> 
> 
> On Thu, May 12, 2016 at 10:09 PM, Kefeng Wang <wangkefeng.wang at huawei.com <mailto:wangkefeng.wang at huawei.com>> wrote:
> 
> 
> 
>     On 2016/5/12 22:46, Jon Mason wrote:
>     >
>     >
>     > On Thu, May 12, 2016 at 2:16 AM, Kefeng Wang <wangkefeng.wang at huawei.com <mailto:wangkefeng.wang at huawei.com> <mailto:wangkefeng.wang at huawei.com <mailto:wangkefeng.wang at huawei.com>>> wrote:
>     >
>     >
>     >
>     >     On 2016/5/12 6:56, Jon Mason wrote:
>     >     > Add all of the UARTs present on NS2 and enable them in the SVK device
>     >     > tree file.  Also, do some magic to make sure that uart3 is discovered as
>     >     > ttyS0 (as that is the console UART).
>     >     >
>     >     > Signed-off-by: Jon Mason <jonmason at broadcom.com <mailto:jonmason at broadcom.com> <mailto:jonmason at broadcom.com <mailto:jonmason at broadcom.com>>>
>     >     > ---
>     >     >  arch/arm64/boot/dts/broadcom/ns2-svk.dts | 16 ++++++++++++++++
>     >     >  arch/arm64/boot/dts/broadcom/ns2.dtsi    | 30 ++++++++++++++++++++++++++++++
>     >     >  2 files changed, 46 insertions(+)
>     >     >
>     >     > diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
>     >     > index 7cd3640..b062a44 100644
>     >     > --- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts
>     >     > +++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
>     >     > @@ -40,10 +40,14 @@
>     >     >
>     >     >       aliases {
>     >     >               serial0 = &uart3;
>     >     > +             serial1 = &uart0;
>     >     > +             serial2 = &uart1;
>     >     > +             serial3 = &uart2;
>     >     >       };
>     >     >
>     >     >       chosen {
>     >     >               stdout-path = "serial0:115200n8";
>     >     > +             bootargs = "earlycon=uart8250,mmio32,0x66130000";
>     >
>     >     Hi Jon,
>     >
>     >     I submit a patch[1], with it, we can use earlycon without option to enable early console
>     >     for "snps,dw-apb-uart", could you help me to test it, thanks.
>     >
>     >
>     > Adding your change and removing the line above does not cause earlycon to work for me.  Is there any additional changes necessary for this to work?
>     With my patch, the bootargs still need contain earlycon, but no need uart8250,mmio32,0x66130000;
> 
>     chosen {
>             stdout-path = "serial0:115200n8";
>             bootargs = "earlycon";
>     }
> 
>     Hope it would work.
> 
> 
> I can confirm that with your change and the change to the bootargs you describe above, it works as desired.  Was your change already accepted?
> 

Great, thanks a lot. it is still being reviewing for now and waiting for response for now.

BRs,
Kefeng

> Thanks,
> Jon
>  
> 
> 
>     BRs,
>     Kefeng
> 
>     >
>     > Thanks,
>     > Jon
>     >
>     >
>     >
>     >     BRs,
>     >     Kefeng
>     >
>     >
>     >     [1] https://lkml.org/lkml/2016/5/11/34
>     >
>     >     >       };
>     >     >
>     >     >       memory {
>     >     > @@ -68,6 +72,18 @@
>     >     >       status = "ok";
>     >     >  };
>     >     >
>     >     > +&uart0 {
>     >     > +     status = "ok";
>     >     > +};
>     >     > +
>     >     > +&uart1 {
>     >     > +     status = "ok";
>     >     > +};
>     >     > +
>     >     > +&uart2 {
>     >     > +     status = "ok";
>     >     > +};
>     >     > +
>     >     >  &uart3 {
>     >     >       status = "ok";
>     >     >  };
>     >     > diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi
>     >     > index 788ed8f..c77a9e8 100644
>     >     > --- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
>     >     > +++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
>     >     > @@ -357,6 +357,36 @@
>     >     >                       status = "disabled";
>     >     >               };
>     >     >
>     >     > +             uart0: serial at 66100000 {
>     >     > +                     compatible = "snps,dw-apb-uart";
>     >     > +                     reg = <0x66100000 0x100>;
>     >     > +                     interrupts = <GIC_SPI 390 IRQ_TYPE_LEVEL_HIGH>;
>     >     > +                     clocks = <&iprocslow>;
>     >     > +                     reg-shift = <2>;
>     >     > +                     reg-io-width = <4>;
>     >     > +                     status = "disabled";
>     >     > +             };
>     >     > +
>     >     > +             uart1: serial at 66110000 {
>     >     > +                     compatible = "snps,dw-apb-uart";
>     >     > +                     reg = <0x66110000 0x100>;
>     >     > +                     interrupts = <GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH>;
>     >     > +                     clocks = <&iprocslow>;
>     >     > +                     reg-shift = <2>;
>     >     > +                     reg-io-width = <4>;
>     >     > +                     status = "disabled";
>     >     > +             };
>     >     > +
>     >     > +             uart2: serial at 66120000 {
>     >     > +                     compatible = "snps,dw-apb-uart";
>     >     > +                     reg = <0x66120000 0x100>;
>     >     > +                     interrupts = <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH>;
>     >     > +                     clocks = <&iprocslow>;
>     >     > +                     reg-shift = <2>;
>     >     > +                     reg-io-width = <4>;
>     >     > +                     status = "disabled";
>     >     > +             };
>     >     > +
>     >     >               uart3: serial at 66130000 {
>     >     >                       compatible = "snps,dw-apb-uart";
>     >     >                       reg = <0x66130000 0x100>;
>     >     >
>     >
>     >
> 
> 



From okaya at codeaurora.org  Sun May 15 19:13:35 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sun, 15 May 2016 22:13:35 -0400
Subject: [PATCH V5 2/6] vfio: platform: move reset call to a common function
In-Reply-To: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1463364819-477-3-git-send-email-okaya@codeaurora.org>

The reset call sequence seems to replicate itself multiple times
across the file. Grouping them together for maintenance reasons.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_platform_common.c | 31 ++++++++++++++--------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 08fd7c2..cb91dd3 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -134,6 +134,18 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
 	kfree(vdev->regions);
 }
 
+static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
+{
+	if (vdev->of_reset) {
+		dev_info(vdev->device, "reset\n");
+		vdev->of_reset(vdev);
+		return 0;
+	}
+
+	dev_warn(vdev->device, "no reset function found!\n");
+	return -EINVAL;
+}
+
 static void vfio_platform_release(void *device_data)
 {
 	struct vfio_platform_device *vdev = device_data;
@@ -141,12 +153,7 @@ static void vfio_platform_release(void *device_data)
 	mutex_lock(&driver_lock);
 
 	if (!(--vdev->refcnt)) {
-		if (vdev->of_reset) {
-			dev_info(vdev->device, "reset\n");
-			vdev->of_reset(vdev);
-		} else {
-			dev_warn(vdev->device, "no reset function found!\n");
-		}
+		vfio_platform_call_reset(vdev);
 		vfio_platform_regions_cleanup(vdev);
 		vfio_platform_irq_cleanup(vdev);
 	}
@@ -175,12 +182,7 @@ static int vfio_platform_open(void *device_data)
 		if (ret)
 			goto err_irq;
 
-		if (vdev->of_reset) {
-			dev_info(vdev->device, "reset\n");
-			vdev->of_reset(vdev);
-		} else {
-			dev_warn(vdev->device, "no reset function found!\n");
-		}
+		vfio_platform_call_reset(vdev);
 	}
 
 	vdev->refcnt++;
@@ -312,10 +314,7 @@ static long vfio_platform_ioctl(void *device_data,
 		return ret;
 
 	} else if (cmd == VFIO_DEVICE_RESET) {
-		if (vdev->of_reset)
-			return vdev->of_reset(vdev);
-		else
-			return -EINVAL;
+		return vfio_platform_call_reset(vdev);
 	}
 
 	return -ENOTTY;
-- 
1.8.2.1



From okaya at codeaurora.org  Sun May 15 19:13:34 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sun, 15 May 2016 22:13:34 -0400
Subject: [PATCH V5 1/6] vfio: platform: rename reset function
In-Reply-To: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1463364819-477-2-git-send-email-okaya@codeaurora.org>

Renaming the reset function to of_reset as it is only used
by the device tree based platforms.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_platform_common.c  | 30 +++++++++++++--------------
 drivers/vfio/platform/vfio_platform_private.h |  6 +++---
 2 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index e65b142..08fd7c2 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -41,7 +41,7 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 		if (!strcmp(iter->compat, compat) &&
 			try_module_get(iter->owner)) {
 			*module = iter->owner;
-			reset_fn = iter->reset;
+			reset_fn = iter->of_reset;
 			break;
 		}
 	}
@@ -51,18 +51,18 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 
 static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
-	vdev->reset = vfio_platform_lookup_reset(vdev->compat,
-						&vdev->reset_module);
-	if (!vdev->reset) {
+	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
+						    &vdev->reset_module);
+	if (!vdev->of_reset) {
 		request_module("vfio-reset:%s", vdev->compat);
-		vdev->reset = vfio_platform_lookup_reset(vdev->compat,
-							 &vdev->reset_module);
+		vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
+							&vdev->reset_module);
 	}
 }
 
 static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
 {
-	if (vdev->reset)
+	if (vdev->of_reset)
 		module_put(vdev->reset_module);
 }
 
@@ -141,9 +141,9 @@ static void vfio_platform_release(void *device_data)
 	mutex_lock(&driver_lock);
 
 	if (!(--vdev->refcnt)) {
-		if (vdev->reset) {
+		if (vdev->of_reset) {
 			dev_info(vdev->device, "reset\n");
-			vdev->reset(vdev);
+			vdev->of_reset(vdev);
 		} else {
 			dev_warn(vdev->device, "no reset function found!\n");
 		}
@@ -175,9 +175,9 @@ static int vfio_platform_open(void *device_data)
 		if (ret)
 			goto err_irq;
 
-		if (vdev->reset) {
+		if (vdev->of_reset) {
 			dev_info(vdev->device, "reset\n");
-			vdev->reset(vdev);
+			vdev->of_reset(vdev);
 		} else {
 			dev_warn(vdev->device, "no reset function found!\n");
 		}
@@ -213,7 +213,7 @@ static long vfio_platform_ioctl(void *device_data,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		if (vdev->reset)
+		if (vdev->of_reset)
 			vdev->flags |= VFIO_DEVICE_FLAGS_RESET;
 		info.flags = vdev->flags;
 		info.num_regions = vdev->num_regions;
@@ -312,8 +312,8 @@ static long vfio_platform_ioctl(void *device_data,
 		return ret;
 
 	} else if (cmd == VFIO_DEVICE_RESET) {
-		if (vdev->reset)
-			return vdev->reset(vdev);
+		if (vdev->of_reset)
+			return vdev->of_reset(vdev);
 		else
 			return -EINVAL;
 	}
@@ -611,7 +611,7 @@ void vfio_platform_unregister_reset(const char *compat,
 
 	mutex_lock(&driver_lock);
 	list_for_each_entry_safe(iter, temp, &reset_list, link) {
-		if (!strcmp(iter->compat, compat) && (iter->reset == fn)) {
+		if (!strcmp(iter->compat, compat) && (iter->of_reset == fn)) {
 			list_del(&iter->link);
 			break;
 		}
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 42816dd..71ed7d1 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -71,7 +71,7 @@ struct vfio_platform_device {
 	struct resource*
 		(*get_resource)(struct vfio_platform_device *vdev, int i);
 	int	(*get_irq)(struct vfio_platform_device *vdev, int i);
-	int	(*reset)(struct vfio_platform_device *vdev);
+	int	(*of_reset)(struct vfio_platform_device *vdev);
 };
 
 typedef int (*vfio_platform_reset_fn_t)(struct vfio_platform_device *vdev);
@@ -80,7 +80,7 @@ struct vfio_platform_reset_node {
 	struct list_head link;
 	char *compat;
 	struct module *owner;
-	vfio_platform_reset_fn_t reset;
+	vfio_platform_reset_fn_t of_reset;
 };
 
 extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
@@ -103,7 +103,7 @@ extern void vfio_platform_unregister_reset(const char *compat,
 static struct vfio_platform_reset_node __reset ## _node = {	\
 	.owner = THIS_MODULE,					\
 	.compat = __compat,					\
-	.reset = __reset,					\
+	.of_reset = __reset,					\
 };								\
 __vfio_platform_register_reset(&__reset ## _node)
 
-- 
1.8.2.1



From okaya at codeaurora.org  Sun May 15 19:13:33 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sun, 15 May 2016 22:13:33 -0400
Subject: [PATCH V5 0/6] vfio, platform: add ACPI support
Message-ID: <1463364819-477-1-git-send-email-okaya@codeaurora.org>

The device tree code checks for the presence of a reset driver and calls
the of_reset function pointer by looking up the reset driver as a module.

ACPI defines _RST method to perform device level reset. After the _RST
method is executed, the OS can resume using the device.

This patch checks the presence of _RST method and calls the _RST
method when reset is requested.

Changes:
1. No functional changes. Just divide the patches into subpatches for easy
review.

Sinan Kaya (6):
  vfio: platform: rename reset function
  vfio: platform: move reset call to a common function
  vfio: platform: determine reset capability
  vfio: platform: add support for ACPI probe
  vfio: platform: call _RST method when using ACPI
  vfio, platform: make reset driver a requirement by default

 drivers/vfio/platform/vfio_amba.c             |   5 +
 drivers/vfio/platform/vfio_platform.c         |   5 +
 drivers/vfio/platform/vfio_platform_common.c  | 170 +++++++++++++++++++++-----
 drivers/vfio/platform/vfio_platform_private.h |   8 +-
 4 files changed, 153 insertions(+), 35 deletions(-)

-- 
1.8.2.1



From okaya at codeaurora.org  Sun May 15 19:13:36 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sun, 15 May 2016 22:13:36 -0400
Subject: [PATCH V5 3/6] vfio: platform: determine reset capability
In-Reply-To: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1463364819-477-4-git-send-email-okaya@codeaurora.org>

Creating a new function to determine if this driver supports reset
function or not. This is an attempt to abstract device tree calls
from the rest of the code.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_platform_common.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index cb91dd3..25378bd 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -49,6 +49,11 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 	return reset_fn;
 }
 
+static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
+{
+	return vdev->of_reset ? true : false;
+}
+
 static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
 	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
@@ -215,7 +220,7 @@ static long vfio_platform_ioctl(void *device_data,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		if (vdev->of_reset)
+		if (vfio_platform_has_reset(vdev))
 			vdev->flags |= VFIO_DEVICE_FLAGS_RESET;
 		info.flags = vdev->flags;
 		info.num_regions = vdev->num_regions;
-- 
1.8.2.1



From okaya at codeaurora.org  Sun May 15 19:13:37 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sun, 15 May 2016 22:13:37 -0400
Subject: [PATCH V5 4/6] vfio: platform: add support for ACPI probe
In-Reply-To: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1463364819-477-5-git-send-email-okaya@codeaurora.org>

The code is using the compatible DT string to associate a reset driver
with the actual device itself. The compatible string does not exist on
ACPI based systems. HID is the unique identifier for a device driver
instead.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_platform_common.c  | 58 ++++++++++++++++++++++++---
 drivers/vfio/platform/vfio_platform_private.h |  1 +
 2 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 25378bd..d859d3b 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/acpi.h>
 #include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -49,6 +50,37 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 	return reset_fn;
 }
 
+#ifdef CONFIG_ACPI
+int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
+			     struct device *dev)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	if (!adev) {
+		pr_err("VFIO: ACPI companion device not found for %s\n",
+			vdev->name);
+		return -ENODEV;
+	}
+
+	vdev->acpihid = acpi_device_hid(adev);
+	if (!vdev->acpihid) {
+		pr_err("VFIO: cannot find ACPI HID for %s\n",
+		       vdev->name);
+		return -ENODEV;
+	}
+	return 0;
+}
+#else
+int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
+			     struct device *dev)
+{
+	return -EINVAL;
+}
+#endif
+
 static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
 {
 	return vdev->of_reset ? true : false;
@@ -548,6 +580,21 @@ static const struct vfio_device_ops vfio_platform_ops = {
 	.mmap		= vfio_platform_mmap,
 };
 
+int vfio_platform_of_probe(struct vfio_platform_device *vdev,
+			   struct device *dev)
+{
+	int ret;
+
+	ret = device_property_read_string(dev, "compatible",
+					  &vdev->compat);
+	if (ret) {
+		pr_err("VFIO: cannot retrieve compat for %s\n",
+			vdev->name);
+		return ret;
+	}
+	return 0;
+}
+
 int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 			       struct device *dev)
 {
@@ -557,11 +604,12 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 	if (!vdev)
 		return -EINVAL;
 
-	ret = device_property_read_string(dev, "compatible", &vdev->compat);
-	if (ret) {
-		pr_err("VFIO: cannot retrieve compat for %s\n", vdev->name);
-		return -EINVAL;
-	}
+	ret = vfio_platform_acpi_probe(vdev, dev);
+	if (ret)
+		ret = vfio_platform_of_probe(vdev, dev);
+
+	if (ret)
+		return ret;
 
 	vdev->device = dev;
 
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 71ed7d1..ba9e4f8 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -58,6 +58,7 @@ struct vfio_platform_device {
 	struct mutex			igate;
 	struct module			*parent_module;
 	const char			*compat;
+	const char			*acpihid;
 	struct module			*reset_module;
 	struct device			*device;
 
-- 
1.8.2.1



From okaya at codeaurora.org  Sun May 15 19:13:38 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sun, 15 May 2016 22:13:38 -0400
Subject: [PATCH V5 5/6] vfio: platform: call _RST method when using ACPI
In-Reply-To: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1463364819-477-6-git-send-email-okaya@codeaurora.org>

The device tree code checks for the presence of a reset driver and calls
the of_reset function pointer by looking up the reset driver as a module.

ACPI defines _RST method to perform device level reset. After the _RST
method is executed, the OS can resume using the device.

This patch checks the presence of _RST method and calls the _RST
method when reset is requested.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_platform_common.c | 44 ++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index d859d3b..095d5b7 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -73,21 +73,59 @@ int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
 	}
 	return 0;
 }
+
+static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
+{
+	struct device *dev = vdev->device;
+	acpi_handle handle = ACPI_HANDLE(dev);
+	acpi_status acpi_ret;
+	unsigned long long val;
+
+	acpi_ret = acpi_evaluate_integer(handle, "_RST", NULL, &val);
+	if (ACPI_FAILURE(acpi_ret))
+		return -EINVAL;
+
+	return 0;
+}
+
+static bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
+{
+	struct device *dev = vdev->device;
+	acpi_handle handle = ACPI_HANDLE(dev);
+
+	return acpi_has_method(handle, "_RST");
+}
 #else
 int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
 			     struct device *dev)
 {
 	return -EINVAL;
 }
+
+static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
+{
+	return -EINVAL;
+}
+
+static bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
+{
+	return false;
+}
 #endif
 
 static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
 {
+	if (vdev->acpihid)
+		return vfio_platform_acpi_has_reset(vdev);
+
 	return vdev->of_reset ? true : false;
 }
 
 static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
+	if (vdev->acpihid)
+		return;
+
 	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
 						    &vdev->reset_module);
 	if (!vdev->of_reset) {
@@ -99,6 +137,9 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 
 static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
 {
+	if (vdev->acpihid)
+		return;
+
 	if (vdev->of_reset)
 		module_put(vdev->reset_module);
 }
@@ -177,6 +218,9 @@ static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
 		dev_info(vdev->device, "reset\n");
 		vdev->of_reset(vdev);
 		return 0;
+	} else if (vdev->acpihid) {
+		dev_info(vdev->device, "reset\n");
+		return vfio_platform_acpi_call_reset(vdev);
 	}
 
 	dev_warn(vdev->device, "no reset function found!\n");
-- 
1.8.2.1



From okaya at codeaurora.org  Sun May 15 19:13:39 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sun, 15 May 2016 22:13:39 -0400
Subject: [PATCH V5 6/6] vfio,
 platform: make reset driver a requirement by default
In-Reply-To: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1463364819-477-7-git-send-email-okaya@codeaurora.org>

The code was allowing platform devices to be used without a supporting
VFIO reset driver. The hardware can be left in some inconsistent state
after a guest machine abort.

The reset driver will put the hardware back to safe state and disable
interrupts before returning the control back to the host machine.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_amba.c             |  5 +++++
 drivers/vfio/platform/vfio_platform.c         |  5 +++++
 drivers/vfio/platform/vfio_platform_common.c  | 18 ++++++++++++++----
 drivers/vfio/platform/vfio_platform_private.h |  1 +
 4 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c
index a66479b..7585902 100644
--- a/drivers/vfio/platform/vfio_amba.c
+++ b/drivers/vfio/platform/vfio_amba.c
@@ -23,6 +23,10 @@
 #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis at virtualopensystems.com>"
 #define DRIVER_DESC     "VFIO for AMBA devices - User Level meta-driver"
 
+static bool reset_required = true;
+module_param(reset_required, bool, 0644);
+MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)");
+
 /* probing devices from the AMBA bus */
 
 static struct resource *get_amba_resource(struct vfio_platform_device *vdev,
@@ -68,6 +72,7 @@ static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
 	vdev->get_resource = get_amba_resource;
 	vdev->get_irq = get_amba_irq;
 	vdev->parent_module = THIS_MODULE;
+	vdev->reset_required = reset_required;
 
 	ret = vfio_platform_probe_common(vdev, &adev->dev);
 	if (ret) {
diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
index b1cc3a7..ef89146 100644
--- a/drivers/vfio/platform/vfio_platform.c
+++ b/drivers/vfio/platform/vfio_platform.c
@@ -23,6 +23,10 @@
 #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis at virtualopensystems.com>"
 #define DRIVER_DESC     "VFIO for platform devices - User Level meta-driver"
 
+static bool reset_required = true;
+module_param(reset_required, bool, 0644);
+MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)");
+
 /* probing devices from the linux platform bus */
 
 static struct resource *get_platform_resource(struct vfio_platform_device *vdev,
@@ -66,6 +70,7 @@ static int vfio_platform_probe(struct platform_device *pdev)
 	vdev->get_resource = get_platform_resource;
 	vdev->get_irq = get_platform_irq;
 	vdev->parent_module = THIS_MODULE;
+	vdev->reset_required = reset_required;
 
 	ret = vfio_platform_probe_common(vdev, &pdev->dev);
 	if (ret)
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 095d5b7..89fb18f 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -121,10 +121,10 @@ static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
 	return vdev->of_reset ? true : false;
 }
 
-static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
+static int vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
 	if (vdev->acpihid)
-		return;
+		return vfio_platform_acpi_has_reset(vdev) ? 0 : -EINVAL;
 
 	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
 						    &vdev->reset_module);
@@ -133,6 +133,8 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 		vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
 							&vdev->reset_module);
 	}
+
+	return vdev->of_reset ? 0 : -EINVAL;
 }
 
 static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
@@ -263,7 +265,9 @@ static int vfio_platform_open(void *device_data)
 		if (ret)
 			goto err_irq;
 
-		vfio_platform_call_reset(vdev);
+		ret = vfio_platform_call_reset(vdev);
+		if (ret && vdev->reset_required)
+			goto err_irq;
 	}
 
 	vdev->refcnt++;
@@ -669,7 +673,13 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 		return ret;
 	}
 
-	vfio_platform_get_reset(vdev);
+	ret = vfio_platform_get_reset(vdev);
+	if (ret && vdev->reset_required) {
+		pr_err("vfio: no reset function found for device %s\n",
+		       vdev->name);
+		iommu_group_put(group);
+		return ret;
+	}
 
 	mutex_init(&vdev->igate);
 
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index ba9e4f8..68fbc00 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -50,6 +50,7 @@ struct vfio_platform_region {
 };
 
 struct vfio_platform_device {
+	bool				reset_required;
 	struct vfio_platform_region	*regions;
 	u32				num_regions;
 	struct vfio_platform_irq	*irqs;
-- 
1.8.2.1



From jun.nie at linaro.org  Sun May 15 19:31:37 2016
From: jun.nie at linaro.org (Jun Nie)
Date: Mon, 16 May 2016 10:31:37 +0800
Subject: [PATCH v2] serial: amba-pl011: complete support to ZTE uart
In-Reply-To: <20160428201106.GA2924@kroah.com>
References: <1458717126-20814-1-git-send-email-jun.nie@linaro.org>
 <CABymUCN_Os0gxoWjfwB_8V4kEkwBqKcrCCRjH8+-gm-Xt3-tYQ@mail.gmail.com>
 <570CF1B3.8080305@linaro.org>
 <CABymUCPvayLkc5h-3e0671pEEO_SshNJazk7W0B_oAUfL-6r0w@mail.gmail.com>
 <20160428201106.GA2924@kroah.com>
Message-ID: <CABymUCPH1CwxhBxGq5_epgn-19j9WrfrxxG8zuzpZnXk26Ps9A@mail.gmail.com>

2016-04-29 4:11 GMT+08:00 Greg KH <greg at kroah.com>:
> On Mon, Apr 25, 2016 at 02:53:02PM +0800, Jun Nie wrote:
>> 2016-04-12 21:01 GMT+08:00 Jun Nie <jun.nie at linaro.org>:
>> > On 2016?04?01? 17:53, Jun Nie wrote:
>> >>
>> >> 2016-03-23 15:12 GMT+08:00 Jun Nie <jun.nie at linaro.org>:
>> >>>
>> >>> Complete support to ZTE uart with adding specific registers
>> >>> mask.
>> >>> We use a magic amba periphid value as pl011 device on ZTE
>> >>> does not have a periphid value in register. The magic value
>> >>> should also be feed via device tree "arm,primecell-periphid"
>> >>> property to match pl011 driver and get ZTE uart data.
>> >>>
>> >>> Signed-off-by: Jun Nie <jun.nie at linaro.org>
>> >>> ---
>> >>>   drivers/tty/serial/amba-pl011.c | 73
>> >>> +++++++++++++++++++++++++++++++++--------
>> >>>   include/linux/amba/serial.h     |  4 +++
>> >>>   2 files changed, 64 insertions(+), 13 deletions(-)
>> >>>
>> >>> diff --git a/drivers/tty/serial/amba-pl011.c
>> >>> b/drivers/tty/serial/amba-pl011.c
>> >>> index 7c198e0..696ee0c 100644
>> >>> --- a/drivers/tty/serial/amba-pl011.c
>> >>> +++ b/drivers/tty/serial/amba-pl011.c
>> >>> @@ -93,6 +93,10 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
>> >>>   struct vendor_data {
>> >>>          const u16               *reg_offset;
>> >>>          unsigned int            ifls;
>> >>> +       unsigned int            fr_busy;
>> >>> +       unsigned int            fr_dsr;
>> >>> +       unsigned int            fr_cts;
>> >>> +       unsigned int            fr_ri;
>> >>>          bool                    access_32b;
>> >>>          bool                    oversampling;
>> >>>          bool                    dma_threshold;
>> >>> @@ -111,6 +115,10 @@ static unsigned int get_fifosize_arm(struct
>> >>> amba_device *dev)
>> >>>   static struct vendor_data vendor_arm = {
>> >>>          .reg_offset             = pl011_std_offsets,
>> >>>          .ifls                   = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
>> >>> +       .fr_busy                = UART01x_FR_BUSY,
>> >>> +       .fr_dsr                 = UART01x_FR_DSR,
>> >>> +       .fr_cts                 = UART01x_FR_CTS,
>> >>> +       .fr_ri                  = UART011_FR_RI,
>> >>>          .oversampling           = false,
>> >>>          .dma_threshold          = false,
>> >>>          .cts_event_workaround   = false,
>> >>> @@ -121,6 +129,10 @@ static struct vendor_data vendor_arm = {
>> >>>
>> >>>   static struct vendor_data vendor_sbsa = {
>> >>>          .reg_offset             = pl011_std_offsets,
>> >>> +       .fr_busy                = UART01x_FR_BUSY,
>> >>> +       .fr_dsr                 = UART01x_FR_DSR,
>> >>> +       .fr_cts                 = UART01x_FR_CTS,
>> >>> +       .fr_ri                  = UART011_FR_RI,
>> >>>          .oversampling           = false,
>> >>>          .dma_threshold          = false,
>> >>>          .cts_event_workaround   = false,
>> >>> @@ -163,6 +175,10 @@ static unsigned int get_fifosize_st(struct
>> >>> amba_device *dev)
>> >>>   static struct vendor_data vendor_st = {
>> >>>          .reg_offset             = pl011_st_offsets,
>> >>>          .ifls                   =
>> >>> UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
>> >>> +       .fr_busy                = UART01x_FR_BUSY,
>> >>> +       .fr_dsr                 = UART01x_FR_DSR,
>> >>> +       .fr_cts                 = UART01x_FR_CTS,
>> >>> +       .fr_ri                  = UART011_FR_RI,
>> >>>          .oversampling           = true,
>> >>>          .dma_threshold          = true,
>> >>>          .cts_event_workaround   = true,
>> >>> @@ -187,11 +203,25 @@ static const u16 pl011_zte_offsets[REG_ARRAY_SIZE]
>> >>> = {
>> >>>          [REG_DMACR] = ZX_UART011_DMACR,
>> >>>   };
>> >>>
>> >>> +static unsigned int get_fifosize_zte(struct amba_device *dev)
>> >>> +{
>> >>> +       return 16;
>> >>> +}
>> >>> +
>> >>>   static struct vendor_data vendor_zte __maybe_unused = {
>> >>>          .reg_offset             = pl011_zte_offsets,
>> >>>          .access_32b             = true,
>> >>>          .ifls                   = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
>> >>> -       .get_fifosize           = get_fifosize_arm,
>> >>> +       .fr_busy                = ZX_UART01x_FR_BUSY,
>> >>> +       .fr_dsr                 = ZX_UART01x_FR_DSR,
>> >>> +       .fr_cts                 = ZX_UART01x_FR_CTS,
>> >>> +       .fr_ri                  = ZX_UART011_FR_RI,
>> >>> +       .oversampling           = false,
>> >>> +       .dma_threshold          = false,
>> >>> +       .cts_event_workaround   = false,
>> >>> +       .always_enabled         = false,
>> >>> +       .fixed_options          = false,
>> >>> +       .get_fifosize           = get_fifosize_zte,
>> >>>   };
>> >>>
>> >>>   /* Deals with DMA transactions */
>> >>> @@ -236,6 +266,10 @@ struct uart_amba_port {
>> >>>          unsigned int            im;             /* interrupt mask */
>> >>>          unsigned int            old_status;
>> >>>          unsigned int            fifosize;       /* vendor-specific */
>> >>> +       unsigned int            fr_busy;        /* vendor-specific */
>> >>> +       unsigned int            fr_dsr;         /* vendor-specific */
>> >>> +       unsigned int            fr_cts;         /* vendor-specific */
>> >>> +       unsigned int            fr_ri;          /* vendor-specific */
>> >>>          unsigned int            old_cr;         /* state during shutdown
>> >>> */
>> >>>          bool                    autorts;
>> >>>          unsigned int            fixed_baud;     /* vendor-set fixed baud
>> >>> rate */
>> >>> @@ -1166,7 +1200,7 @@ static void pl011_dma_shutdown(struct
>> >>> uart_amba_port *uap)
>> >>>                  return;
>> >>>
>> >>>          /* Disable RX and TX DMA */
>> >>> -       while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY)
>> >>> +       while (pl011_read(uap, REG_FR) & uap->fr_busy)
>> >>>                  cpu_relax();
>> >>>
>> >>>          spin_lock_irq(&uap->port.lock);
>> >>> @@ -1415,11 +1449,11 @@ static void pl011_modem_status(struct
>> >>> uart_amba_port *uap)
>> >>>          if (delta & UART01x_FR_DCD)
>> >>>                  uart_handle_dcd_change(&uap->port, status &
>> >>> UART01x_FR_DCD);
>> >>>
>> >>> -       if (delta & UART01x_FR_DSR)
>> >>> +       if (delta & uap->fr_dsr)
>> >>>                  uap->port.icount.dsr++;
>> >>>
>> >>> -       if (delta & UART01x_FR_CTS)
>> >>> -               uart_handle_cts_change(&uap->port, status &
>> >>> UART01x_FR_CTS);
>> >>> +       if (delta & uap->fr_cts)
>> >>> +               uart_handle_cts_change(&uap->port, status & uap->fr_cts);
>> >>>
>> >>>          wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
>> >>>   }
>> >>> @@ -1492,7 +1526,7 @@ static unsigned int pl011_tx_empty(struct uart_port
>> >>> *port)
>> >>>          struct uart_amba_port *uap =
>> >>>              container_of(port, struct uart_amba_port, port);
>> >>>          unsigned int status = pl011_read(uap, REG_FR);
>> >>> -       return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 :
>> >>> TIOCSER_TEMT;
>> >>> +       return status & (uap->fr_busy | UART01x_FR_TXFF) ? 0 :
>> >>> TIOCSER_TEMT;
>> >>>   }
>> >>>
>> >>>   static unsigned int pl011_get_mctrl(struct uart_port *port)
>> >>> @@ -1507,9 +1541,9 @@ static unsigned int pl011_get_mctrl(struct
>> >>> uart_port *port)
>> >>>                  result |= tiocmbit
>> >>>
>> >>>          TIOCMBIT(UART01x_FR_DCD, TIOCM_CAR);
>> >>> -       TIOCMBIT(UART01x_FR_DSR, TIOCM_DSR);
>> >>> -       TIOCMBIT(UART01x_FR_CTS, TIOCM_CTS);
>> >>> -       TIOCMBIT(UART011_FR_RI, TIOCM_RNG);
>> >>> +       TIOCMBIT(uap->fr_dsr, TIOCM_DSR);
>> >>> +       TIOCMBIT(uap->fr_cts, TIOCM_CTS);
>> >>> +       TIOCMBIT(uap->fr_ri, TIOCM_RNG);
>> >>>   #undef TIOCMBIT
>> >>>          return result;
>> >>>   }
>> >>> @@ -2086,7 +2120,7 @@ static int pl011_verify_port(struct uart_port
>> >>> *port, struct serial_struct *ser)
>> >>>          return ret;
>> >>>   }
>> >>>
>> >>> -static struct uart_ops amba_pl011_pops = {
>> >>> +static const struct uart_ops amba_pl011_pops = {
>> >>>          .tx_empty       = pl011_tx_empty,
>> >>>          .set_mctrl      = pl011_set_mctrl,
>> >>>          .get_mctrl      = pl011_get_mctrl,
>> >>> @@ -2190,7 +2224,7 @@ pl011_console_write(struct console *co, const char
>> >>> *s, unsigned int count)
>> >>>           *      Finally, wait for transmitter to become empty
>> >>>           *      and restore the TCR
>> >>>           */
>> >>> -       while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY)
>> >>> +       while (pl011_read(uap, REG_FR) & uap->fr_busy)
>> >>>                  cpu_relax();
>> >>>          if (!uap->vendor->always_enabled)
>> >>>                  pl011_write(old_cr, uap, REG_CR);
>> >>> @@ -2472,8 +2506,12 @@ static int pl011_probe(struct amba_device *dev,
>> >>> const struct amba_id *id)
>> >>>                  return PTR_ERR(uap->clk);
>> >>>
>> >>>          uap->reg_offset = vendor->reg_offset;
>> >>> -       uap->vendor = vendor;
>> >>> -       uap->fifosize = vendor->get_fifosize(dev);
>> >>> +       uap->vendor     = vendor;
>> >>> +       uap->fifosize   = vendor->get_fifosize(dev);
>> >>> +       uap->fr_busy    = vendor->fr_busy;
>> >>> +       uap->fr_dsr     = vendor->fr_dsr;
>> >>> +       uap->fr_cts     = vendor->fr_cts;
>> >>> +       uap->fr_ri      = vendor->fr_ri;
>> >>>          uap->port.iotype = vendor->access_32b ? UPIO_MEM32 : UPIO_MEM;
>> >>>          uap->port.irq = dev->irq[0];
>> >>>          uap->port.ops = &amba_pl011_pops;
>> >>> @@ -2555,6 +2593,10 @@ static int sbsa_uart_probe(struct platform_device
>> >>> *pdev)
>> >>>          uap->reg_offset = vendor_sbsa.reg_offset;
>> >>>          uap->vendor     = &vendor_sbsa;
>> >>>          uap->fifosize   = 32;
>> >>> +       uap->fr_busy    = vendor_sbsa.fr_busy;
>> >>> +       uap->fr_dsr     = vendor_sbsa.fr_dsr;
>> >>> +       uap->fr_cts     = vendor_sbsa.fr_cts;
>> >>> +       uap->fr_ri      = vendor_sbsa.fr_ri;
>> >>>          uap->port.iotype = vendor_sbsa.access_32b ? UPIO_MEM32 :
>> >>> UPIO_MEM;
>> >>>          uap->port.irq   = platform_get_irq(pdev, 0);
>> >>>          uap->port.ops   = &sbsa_uart_pops;
>> >>> @@ -2615,6 +2657,11 @@ static struct amba_id pl011_ids[] = {
>> >>>                  .mask   = 0x00ffffff,
>> >>>                  .data   = &vendor_st,
>> >>>          },
>> >>> +       {
>> >>> +               .id     = 0xfefefe,
>> >>> +               .mask   = 0xffffff,
>> >>> +               .data   = &vendor_zte,
>> >>> +       },
>> >>>          { 0, 0 },
>> >>>   };
>> >>>
>> >>> diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
>> >>> index d76a19b..750f2ef 100644
>> >>> --- a/include/linux/amba/serial.h
>> >>> +++ b/include/linux/amba/serial.h
>> >>> @@ -103,6 +103,10 @@
>> >>>   #define UART01x_FR_DSR                 0x002
>> >>>   #define UART01x_FR_CTS                 0x001
>> >>>   #define UART01x_FR_TMSK                (UART01x_FR_TXFF +
>> >>> UART01x_FR_BUSY)
>> >>> +#define ZX_UART01x_FR_BUSY     0x300
>> >>> +#define ZX_UART01x_FR_DSR      0x008
>> >>> +#define ZX_UART01x_FR_CTS      0x002
>> >>> +#define ZX_UART011_FR_RI       0x001
>> >>>
>> >>>   #define UART011_CR_CTSEN       0x8000  /* CTS hardware flow control */
>> >>>   #define UART011_CR_RTSEN       0x4000  /* RTS hardware flow control */
>> >>> --
>> >>> 1.9.1
>> >>>
>> >
>> > Russell,
>> >
>> > Do you have any comments to these change?
>> >
>> > Jun
>>
>> Greg,
>>
>> Do you have any idea on how to drive review on this patch? Seems
>> maintainer Russell is too busy and missing for this thread and others
>> do not have comments. Your comments are appreciated!
>
> I would like to get Russell's opinion of this before merging it.
>
> thanks,
>
> greg k-h

Russell,

Could you help have a look at this patch? Thanks!

Jun


From shawn.lin at rock-chips.com  Sun May 15 21:15:29 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Mon, 16 May 2016 12:15:29 +0800
Subject: [PATCH 3/4] phy: rockchip-emmc: configure default output tap delay
In-Reply-To: <CAD=FV=WupNv+z86BgmR1n8bj+b6GKA5Ew7U9hgoAxV9dxF7gjQ@mail.gmail.com>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
 <1463092986-61777-3-git-send-email-briannorris@chromium.org>
 <CAD=FV=WupNv+z86BgmR1n8bj+b6GKA5Ew7U9hgoAxV9dxF7gjQ@mail.gmail.com>
Message-ID: <52567d92-d1d3-f089-65c2-a30f3a00386b@rock-chips.com>

Hi Doug,

On 2016/5/14 6:25, Doug Anderson wrote:
> Hi,
>
> On Thu, May 12, 2016 at 3:43 PM, Brian Norris <briannorris at chromium.org> wrote:
>> The output tap delay controls helps maintain the hold requirements for
>> eMMC. The exact value is dependent on the SoC and other factors, though
>> it isn't really an exact science. But the default of 0 is not very good,
>> as it doesn't give the eMMC much hold time, so let's bump up to 4
>> (approx 90 degree phase?). If we need to configure this any further
>> (e.g., based on board or speed factors), we may need to consider a
>> device tree representation.
>
> As I understand it, this solves much the same problem as my patch in
> <https://patchwork.kernel.org/patch/9085581/>, but for the eMMC port
> on rk3399 (which doesn't use dw_mmc).  As argued in that patch and
> also in the discussion from
> <https://patchwork.kernel.org/patch/9030621/>, if we eventually end up
> needing to put something in the device tree we need to be really
> careful.  Specifically to get the exact right value here I think you
> need to consider the input clock, speed mode, and any SoC-specific
> delays differences between the clock and the data lines.  That would
> imply that, if anything, the device tree data would only contain
> information about the SoC-specific delay differences and all other
> work to set this value would involve coordination between the PHY and
> the SDHCI controller.
>
>
> However, as also discussed previously, we don't appear to need to be
> very exact about the value here.  It seems like setting this to 4 (~90
> degrees?) is a much better starting point than leaving it at the
> default of 0.

The value, 4, is based on real silicon test observed from the
oscilloscope, and of course it meets the requirement of speed modes.
For arasan't phy, its phase is very accurate, so the real timing of
the value you set almost won't vary too much for different Socs.

So explicitly assigning 4 here looks sane currently except for crazy
PCB layout...


>
>
> ...so I'd be all for landing this patch.  Perhaps Shawn can chime in
> and confirm that our understanding is correct and possibly we can
> update the commit message.  Then presumably someone at Rockchip can
> keep working to find a better way to set this long term.
>
> Sound good?
>
>
> -Doug
>
>
>


-- 
Best Regards
Shawn Lin



From andy.gross at linaro.org  Sun May 15 22:08:04 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Mon, 16 May 2016 00:08:04 -0500
Subject: [Patch v5 5/8] firmware: qcom: scm: Convert to streaming DMA APIS
In-Reply-To: <20160513234852.GH1256@tuxbot>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
 <1463111221-6963-6-git-send-email-andy.gross@linaro.org>
 <20160513234852.GH1256@tuxbot>
Message-ID: <20160516050804.GB32019@hector>

On Fri, May 13, 2016 at 04:48:52PM -0700, Bjorn Andersson wrote:
> > +	cmd->len = cpu_to_le32(alloc_len);
> > +	cmd->buf_offset = cpu_to_le32(sizeof(*cmd));
> > +	cmd->resp_hdr_offset = cpu_to_le32(sizeof(*cmd) + cmd_len);
> > +
> >  	cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
> >  	if (cmd_buf)
> > -		memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len);
> > +		memcpy(cmd->buf, cmd_buf, cmd_len);
> > +
> > +	rsp = (void *)cmd->buf + le32_to_cpu(cmd->resp_hdr_offset);
> 
> I believe resp_hdr_offset counts from the beginning of the buffer and
> that this therefor is supposed to be:
> 
> 	rsp = (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
> 
> With that corrected, feel free to add:
> 
> Reviewed-by: Bjorn Andersson <bjorn.andersson at linaro.org>

I'll fix that up.  Thanks for the review.


Andy


From sricharan at codeaurora.org  Sun May 15 22:13:50 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Mon, 16 May 2016 10:43:50 +0530
Subject: [PATCH V2 0/2] drivers: i2c: qup: Some misc fixes
In-Reply-To: <20160513114436.GH1778@katana>
References: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>
 <20160513114436.GH1778@katana>
Message-ID: <000601d1af31$c07bc450$41734cf0$@codeaurora.org>

Hi,

> > One for fixing the bug with CONFIG_DEBUG_SG enabled and another to
> > suspend the transfer for all errors instead of just for nack.
> 
> You haven't stated what was changed in V2.
    ah, sorry, will resend..

Regards,
 Sricharan



From sricharan at codeaurora.org  Sun May 15 22:19:04 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Mon, 16 May 2016 10:49:04 +0530
Subject: [PATCH V2 1/2] drivers: i2c: qup: Fix broken dma when
 CONFIG_DEBUG_SG is enabled
In-Reply-To: <20160513114716.GI1778@katana>
References: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>
 <1462534274-28925-2-git-send-email-sricharan@codeaurora.org>
 <20160513114716.GI1778@katana>
Message-ID: <000e01d1af32$7c05de40$74119ac0$@codeaurora.org>

Hi,
> > With CONFIG_DEBUG_SG is enabled and when dma mode is used, below
> dump
> > is seen,
> >
> > ------------[ cut here ]------------
> > kernel BUG at include/linux/scatterlist.h:140!
> > Internal error: Oops - BUG: 0 [#1] PREEMPT SMP Modules linked in:
> > CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.0-00459-g9f087b9-dirty
> > #7 Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
> > task: ffffffc036868000 ti: ffffffc036870000 task.ti: ffffffc036870000
> > PC is at qup_sg_set_buf.isra.13+0x138/0x154
> > LR is at qup_sg_set_buf.isra.13+0x50/0x154 pc : [<ffffffc0005a0ed8>]
> > lr : [<ffffffc0005a0df0>] pstate: 60000145 sp : ffffffc0368735c0
> > x29: ffffffc0368735c0 x28: ffffffc036873752
> > x27: ffffffc035233018 x26: ffffffc000c4e000
> > x25: 0000000000000000 x24: 0000000000000004
> > x23: 0000000000000000 x22: ffffffc035233668
> > x21: ffffff80004e3000 x20: ffffffc0352e0018
> > x19: 0000004000000000 x18: 0000000000000028
> > x17: 0000000000000004 x16: ffffffc0017a39c8
> > x15: 0000000000001cdf x14: ffffffc0019929d8
> > x13: ffffffc0352e0018 x12: 0000000000000000
> > x11: 0000000000000001 x10: 0000000000000001
> > x9 : ffffffc0012b2d70 x8 : ffffff80004e3000
> > x7 : 0000000000000018 x6 : 0000000030000000
> > x5 : ffffffc00199f018 x4 : ffffffc035233018
> > x3 : 0000000000000004 x2 : 00000000c0000000
> > x1 : 0000000000000003 x0 : 0000000000000000
> >
> > Process swapper/0 (pid: 1, stack limit = 0xffffffc036870020)
> > Stack: (0xffffffc0368735c0 to 0xffffffc036874000)
> >
> > Change allocation of sg buffers from dma_coherent memory to kzalloc to
> > fix the issue.
> 
> This description describes what you do. But not why it is the correct
solution
> to the OOPS. The OOPS  neither describes it. Please add some more
> explanation.
> 
   Ok,will describe it more. The reason it oops is sg_set_bug expects that
the
   buf parameter passed in should be a from the lowmem and a valid
pageframe.
  This is not true for pages from dma_alloc_coherent which can be carveouts,
hence
  the check fails. Allocating buffers using kzalloc fixes the issue.

Regards,
 Sricharan
  



From vigneshr at ti.com  Sun May 15 22:25:03 2016
From: vigneshr at ti.com (Vignesh R)
Date: Mon, 16 May 2016 10:55:03 +0530
Subject: [PATCH] ARM: DRA7: hwmod: Remove QSPI address space entry from hwmod
Message-ID: <1463376303-22267-1-git-send-email-vigneshr@ti.com>

QSPI address space information is passed from device tree. Therefore
remove legacy way of passing address space via hwmod data.

Signed-off-by: Vignesh R <vigneshr at ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
index d0e7e5259ec3..fac0a2044da4 100644
--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
@@ -3410,21 +3410,11 @@ static struct omap_hwmod_ocp_if dra7xx_l4_cfg__pciess2 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space dra7xx_qspi_addrs[] = {
-	{
-		.pa_start	= 0x4b300000,
-		.pa_end		= 0x4b30007f,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
 /* l3_main_1 -> qspi */
 static struct omap_hwmod_ocp_if dra7xx_l3_main_1__qspi = {
 	.master		= &dra7xx_l3_main_1_hwmod,
 	.slave		= &dra7xx_qspi_hwmod,
 	.clk		= "l3_iclk_div",
-	.addr		= dra7xx_qspi_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-- 
2.8.2



From tiwai at suse.de  Sun May 15 22:40:56 2016
From: tiwai at suse.de (Takashi Iwai)
Date: Mon, 16 May 2016 07:40:56 +0200
Subject: [RFC PATCH 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <87mvnrhux4.fsf@belgarion.home>
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
 <s5hk2j38tmf.wl-tiwai@suse.de> <87twi1hssl.fsf@belgarion.home>
 <s5hy47c7jvd.wl-tiwai@suse.de> <87mvnrhux4.fsf@belgarion.home>
Message-ID: <s5hoa867e6v.wl-tiwai@suse.de>

On Sun, 15 May 2016 23:29:27 +0200,
Robert Jarzmik wrote:
> 
> Takashi Iwai <tiwai at suse.de> writes:
> 
> > On Sat, 14 May 2016 11:50:50 +0200,
> > Robert Jarzmik wrote:
> >> >> +unsigned int ac97_bus_scan_one(struct ac97_controller *ac97,
> >> >> +				      int codec_num)
> >> >> +{
> >> >> +	struct ac97_codec_device codec;
> >> >> +	unsigned short vid1, vid2;
> >> >> +	int ret;
> >> >> +
> >> >> +	codec.dev = *ac97->dev;
> >> >> +	codec.num = codec_num;
> >> >> +	ret = ac97->ops->read(&codec, AC97_VENDOR_ID1);
> >> >> +	vid1 = (ret & 0xffff);
> >> >> +	if (ret < 0)
> >> >> +		return 0;
> >> >
> >> > Hmm.  This looks pretty hackish and dangerous.
> >> You mean returning 0 even if the read failed, right ?
> >
> > No, my concern is that it's creating a dummy codec object temporarily
> > on the stack just by copying some fields and calling the ops with it.
> > (And actually the current code may work wrongly because lack of
> >  zero-clear of the object.)
> Ah yes, I remember now, the on-stack generated device, indeed ugly.
> 
> > IMO, a cleaner way would be to define the ops passed with both
> > controller and codec objects as arguments, and pass NULL codec here.
> It's rather unusual to need both the device and its controller in bus
> operations. I must admit I have no better idea so far, so I'll try that just to
> see how it looks like, and let's see next ...

Thinking of this again, I wonder now why we need to pass the codec
object at all.  It's the read/write ops via ac97, so we just need the
ac97_controller object and the address slot of the accessed codec?


Takashi


From sricharan at codeaurora.org  Sun May 15 22:59:25 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Mon, 16 May 2016 11:29:25 +0530
Subject: [PATCH V2 2/2] drivers: i2c: qup: Fix error handling
In-Reply-To: <20160513115021.GK1778@katana>
References: <1462534274-28925-1-git-send-email-sricharan@codeaurora.org>
 <1462534274-28925-3-git-send-email-sricharan@codeaurora.org>
 <20160513114823.GJ1778@katana> <20160513115021.GK1778@katana>
Message-ID: <002201d1af38$1eb3e330$5c1ba990$@codeaurora.org>

Hi,
> > > Among the bus errors reported from the QUP_MASTER_STATUS register
> > > only NACK is considered and transfer gets suspended, while other
> > > errors are ignored. Correct this and suspend the transfer for other
> > > errors as well. This avoids unnessecary 'timeouts' which happens
> > > when waiting for events that would never happen when there is
> > > already an error condition on the bus.
> > >
> > > Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> > > Reviewed-by: Andy Gross <andy.gross at linaro.org>
> >
> > Please check Documentation/i2c/fault-codes for proper fault codes.
> 
    Ok, Thanks for pointing this out. So, for NACK I think it is more
appropriate to
    return -ENXIO and -EIO for other errors. Will correct this.

> And while we are here: NACK is not an error but a valid response. Can you
> remove the dev_err related to that? Otherwise tools like i2cdetect will
> probably flood your log.
  Ok, will correct this.

Regards,
 Sricharan         



From sricharan at codeaurora.org  Sun May 15 23:48:54 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon, 16 May 2016 12:18:54 +0530
Subject: [PATCH V4 0/7] iommu/msm: Add DT adaptation and generic bindings
 support
Message-ID: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>

The msm_iommu.c driver currently works based on platform data.
A single master device can be connected to more than one iommu and multiple
contexts in each of the iommu. This association between master and iommus was
represented from platform data using parent/child devices. The master drivers
were responsible for attaching all of the iommus/context to a domain. Now the
platform data support is removed and DT support is added. The master/iommus are
added through generic iommu bindings.

This is essentially rework of the patch posted earlier by
Rob Clark <robdclark at gmail.com>. This series folds the changes in to the
existing driver with the addition of generic bindings.

        http://www.spinics.net/lists/linux-arm-msm/msg10077.html

Tested this series on ifc6410 board.

[V4] Addressed comments for making the iommu compatible binding more soc
     specific and updated the documentation for the iommu clocks.

[V3] Addressed comments to correct the usage
     of the #iommu-cells binding, improve the flush_iotlb_range function,
     added a new patch to use writel_relaxed for register access and split
     up the documentation patch.

[V2] Adapted the driver to use generic ARMV7S short descriptor pagetable ops
     and addressed comments.

[V1]
   https://lists.linuxfoundation.org/pipermail/iommu/2015-August/014074.html

Sricharan R (7):
  iommu/msm: Add DT adaptation
  documentation: iommu: Add bindings for msm,iommu-v0 ip
  iommu/msm: Move the contents from msm_iommu_dev.c to msm_iommu.c
  iommu/msm: Add support for generic master bindings
  iommu/msm: use generic ARMV7S short descriptor pagetable ops
  iommu/msm: Use writel_relaxed and add a barrier
  iommu/msm: Remove driver BROKEN

 .../devicetree/bindings/iommu/msm,iommu-v0.txt     |  64 ++
 drivers/iommu/Kconfig                              |   2 +-
 drivers/iommu/Makefile                             |   2 +-
 drivers/iommu/msm_iommu.c                          | 872 +++++++++++----------
 drivers/iommu/msm_iommu.h                          |  73 +-
 drivers/iommu/msm_iommu_dev.c                      | 381 ---------
 drivers/iommu/msm_iommu_hw-8xxx.h                  |   7 +-
 7 files changed, 569 insertions(+), 832 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
 delete mode 100644 drivers/iommu/msm_iommu_dev.c

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May 15 23:48:55 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon, 16 May 2016 12:18:55 +0530
Subject: [PATCH V4 1/7] iommu/msm: Add DT adaptation
In-Reply-To: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463381341-30498-2-git-send-email-sricharan@codeaurora.org>

The driver currently works based on platform data. Remove this
and add support for DT. A single master can have multiple ports
connected to more than one iommu.

                      master
                        |
                        |
                        |
           ------------------------
           |                      |
         IOMMU0                 IOMMU1
           |                      |
      ctx0   ctx1            ctx0   ctx1

This association of master and iommus/contexts were previously
represented by platform data parent/child device details. The client
drivers were responsible for programming all of the iommus/contexts
for the device. Now while adapting to generic DT bindings we maintain the
list of iommus, contexts that each master domain is connected to and
program all of them on attach/detach.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/msm_iommu.c     | 252 ++++++++++++++++++---------------
 drivers/iommu/msm_iommu.h     |  73 ++++------
 drivers/iommu/msm_iommu_dev.c | 315 ++++++++++--------------------------------
 3 files changed, 237 insertions(+), 403 deletions(-)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index e321fa5..bc1a4e3 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -48,6 +48,7 @@ __asm__ __volatile__ (							\
 static int msm_iommu_tex_class[4];
 
 DEFINE_SPINLOCK(msm_iommu_lock);
+static LIST_HEAD(qcom_iommu_devices);
 
 struct msm_priv {
 	unsigned long *pgtable;
@@ -60,35 +61,37 @@ static struct msm_priv *to_msm_priv(struct iommu_domain *dom)
 	return container_of(dom, struct msm_priv, domain);
 }
 
-static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
+static int __enable_clocks(struct msm_iommu_dev *iommu)
 {
 	int ret;
 
-	ret = clk_enable(drvdata->pclk);
+	ret = clk_enable(iommu->pclk);
 	if (ret)
 		goto fail;
 
-	if (drvdata->clk) {
-		ret = clk_enable(drvdata->clk);
+	if (iommu->clk) {
+		ret = clk_enable(iommu->clk);
 		if (ret)
-			clk_disable(drvdata->pclk);
+			clk_disable(iommu->pclk);
 	}
 fail:
 	return ret;
 }
 
-static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
+static void __disable_clocks(struct msm_iommu_dev *iommu)
 {
-	clk_disable(drvdata->clk);
-	clk_disable(drvdata->pclk);
+	if (iommu->clk)
+		clk_disable(iommu->clk);
+	clk_disable(iommu->pclk);
 }
 
 static int __flush_iotlb(struct iommu_domain *domain)
 {
 	struct msm_priv *priv = to_msm_priv(domain);
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	struct msm_iommu_dev *iommu = NULL;
+	struct msm_iommu_ctx_dev *master;
 	int ret = 0;
+
 #ifndef CONFIG_IOMMU_PGTABLES_L2
 	unsigned long *fl_table = priv->pgtable;
 	int i;
@@ -105,24 +108,67 @@ static int __flush_iotlb(struct iommu_domain *domain)
 	}
 #endif
 
-	list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
-
-		BUG_ON(!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent);
-
-		iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
-		BUG_ON(!iommu_drvdata);
-
-		ret = __enable_clocks(iommu_drvdata);
+	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
+		ret = __enable_clocks(iommu);
 		if (ret)
 			goto fail;
 
-		SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
-		__disable_clocks(iommu_drvdata);
+		list_for_each_entry(master, &iommu->ctx_list, list)
+			SET_CTX_TLBIALL(iommu->base, master->num, 0);
+
+		__disable_clocks(iommu);
 	}
 fail:
 	return ret;
 }
 
+static int msm_iommu_alloc_ctx(unsigned long *map, int start, int end)
+{
+	int idx;
+
+	do {
+		idx = find_next_zero_bit(map, end, start);
+		if (idx == end)
+			return -ENOSPC;
+	} while (test_and_set_bit(idx, map));
+
+	return idx;
+}
+
+static void msm_iommu_free_ctx(unsigned long *map, int idx)
+{
+	clear_bit(idx, map);
+}
+
+static void config_mids(struct msm_iommu_dev *iommu,
+			struct msm_iommu_ctx_dev *master)
+{
+	int mid, ctx, i;
+
+	for (i = 0; i < master->num_mids; i++) {
+		mid = master->mids[i];
+		ctx = master->num;
+
+		SET_M2VCBR_N(iommu->base, mid, 0);
+		SET_CBACR_N(iommu->base, ctx, 0);
+
+		/* Set VMID = 0 */
+		SET_VMID(iommu->base, mid, 0);
+
+		/* Set the context number for that MID to this context */
+		SET_CBNDX(iommu->base, mid, ctx);
+
+		/* Set MID associated with this context bank to 0*/
+		SET_CBVMID(iommu->base, ctx, 0);
+
+		/* Set the ASID for TLB tagging for this context */
+		SET_CONTEXTIDR_ASID(iommu->base, ctx, ctx);
+
+		/* Set security bit override to be Non-secure */
+		SET_NSCFG(iommu->base, mid, 3);
+	}
+}
+
 static void __reset_context(void __iomem *base, int ctx)
 {
 	SET_BPRCOSH(base, ctx, 0);
@@ -272,94 +318,76 @@ static void msm_iommu_domain_free(struct iommu_domain *domain)
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
-	struct msm_priv *priv;
-	struct msm_iommu_ctx_dev *ctx_dev;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-	struct msm_iommu_ctx_drvdata *tmp_drvdata;
 	int ret = 0;
 	unsigned long flags;
+	struct msm_iommu_dev *iommu;
+	struct msm_priv *priv = to_msm_priv(domain);
+	struct msm_iommu_ctx_dev *master;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	priv = to_msm_priv(domain);
-
-	if (!dev) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	iommu_drvdata = dev_get_drvdata(dev->parent);
-	ctx_drvdata = dev_get_drvdata(dev);
-	ctx_dev = dev->platform_data;
-
-	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (!list_empty(&ctx_drvdata->attached_elm)) {
-		ret = -EBUSY;
-		goto fail;
-	}
-
-	list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
-		if (tmp_drvdata == ctx_drvdata) {
-			ret = -EBUSY;
-			goto fail;
+	list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) {
+		master = list_first_entry(&iommu->ctx_list,
+					  struct msm_iommu_ctx_dev,
+					  list);
+		if (master->of_node == dev->of_node) {
+			ret = __enable_clocks(iommu);
+			if (ret)
+				goto fail;
+
+			list_for_each_entry(master, &iommu->ctx_list, list) {
+				if (master->num) {
+					dev_err(dev, "domain already attached");
+					ret = -EEXIST;
+					goto fail;
+				}
+				master->num =
+					msm_iommu_alloc_ctx(iommu->context_map,
+							    0, iommu->ncb);
+					if (IS_ERR_VALUE(master->num)) {
+						ret = -ENODEV;
+						goto fail;
+					}
+				config_mids(iommu, master);
+				__program_context(iommu->base, master->num,
+						  __pa(priv->pgtable));
+			}
+			__disable_clocks(iommu);
+			list_add(&iommu->dom_node, &priv->list_attached);
 		}
+	}
 
-	ret = __enable_clocks(iommu_drvdata);
-	if (ret)
-		goto fail;
-
-	__program_context(iommu_drvdata->base, ctx_dev->num,
-			  __pa(priv->pgtable));
-
-	__disable_clocks(iommu_drvdata);
-	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
 	ret = __flush_iotlb(domain);
-
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+
 	return ret;
 }
 
 static void msm_iommu_detach_dev(struct iommu_domain *domain,
 				 struct device *dev)
 {
-	struct msm_priv *priv;
-	struct msm_iommu_ctx_dev *ctx_dev;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	struct msm_priv *priv = to_msm_priv(domain);
 	unsigned long flags;
+	struct msm_iommu_dev *iommu;
+	struct msm_iommu_ctx_dev *master;
 	int ret;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
-	priv = to_msm_priv(domain);
-
-	if (!dev)
-		goto fail;
-
-	iommu_drvdata = dev_get_drvdata(dev->parent);
-	ctx_drvdata = dev_get_drvdata(dev);
-	ctx_dev = dev->platform_data;
-
-	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
-		goto fail;
-
 	ret = __flush_iotlb(domain);
 	if (ret)
 		goto fail;
 
-	ret = __enable_clocks(iommu_drvdata);
-	if (ret)
-		goto fail;
-
-	__reset_context(iommu_drvdata->base, ctx_dev->num);
-	__disable_clocks(iommu_drvdata);
-	list_del_init(&ctx_drvdata->attached_elm);
+	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
+		ret = __enable_clocks(iommu);
+		if (ret)
+			goto fail;
 
+		list_for_each_entry(master, &iommu->ctx_list, list) {
+			msm_iommu_free_ctx(iommu->context_map, master->num);
+			__reset_context(iommu->base, master->num);
+		}
+		__disable_clocks(iommu);
+	}
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 }
@@ -555,47 +583,46 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
 					  dma_addr_t va)
 {
 	struct msm_priv *priv;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	struct msm_iommu_dev *iommu;
+	struct msm_iommu_ctx_dev *master;
 	unsigned int par;
 	unsigned long flags;
-	void __iomem *base;
 	phys_addr_t ret = 0;
-	int ctx;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
 
 	priv = to_msm_priv(domain);
-	if (list_empty(&priv->list_attached))
-		goto fail;
+	iommu = list_first_entry(&priv->list_attached,
+				 struct msm_iommu_dev, dom_node);
 
-	ctx_drvdata = list_entry(priv->list_attached.next,
-				 struct msm_iommu_ctx_drvdata, attached_elm);
-	iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+	if (list_empty(&iommu->ctx_list))
+		goto fail;
 
-	base = iommu_drvdata->base;
-	ctx = ctx_drvdata->num;
+	master = list_first_entry(&iommu->ctx_list,
+				  struct msm_iommu_ctx_dev, list);
+	if (!master)
+		goto fail;
 
-	ret = __enable_clocks(iommu_drvdata);
+	ret = __enable_clocks(iommu);
 	if (ret)
 		goto fail;
 
 	/* Invalidate context TLB */
-	SET_CTX_TLBIALL(base, ctx, 0);
-	SET_V2PPR(base, ctx, va & V2Pxx_VA);
+	SET_CTX_TLBIALL(iommu->base, master->num, 0);
+	SET_V2PPR(iommu->base, master->num, va & V2Pxx_VA);
 
-	par = GET_PAR(base, ctx);
+	par = GET_PAR(iommu->base, master->num);
 
 	/* We are dealing with a supersection */
-	if (GET_NOFAULT_SS(base, ctx))
+	if (GET_NOFAULT_SS(iommu->base, master->num))
 		ret = (par & 0xFF000000) | (va & 0x00FFFFFF);
 	else	/* Upper 20 bits from PAR, lower 12 from VA */
 		ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
 
-	if (GET_FAULT(base, ctx))
+	if (GET_FAULT(iommu->base, master->num))
 		ret = 0;
 
-	__disable_clocks(iommu_drvdata);
+	__disable_clocks(iommu);
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
@@ -635,37 +662,34 @@ static void print_ctx_regs(void __iomem *base, int ctx)
 
 irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 {
-	struct msm_iommu_drvdata *drvdata = dev_id;
-	void __iomem *base;
+	struct msm_iommu_dev *iommu = dev_id;
 	unsigned int fsr;
 	int i, ret;
 
 	spin_lock(&msm_iommu_lock);
 
-	if (!drvdata) {
+	if (!iommu) {
 		pr_err("Invalid device ID in context interrupt handler\n");
 		goto fail;
 	}
 
-	base = drvdata->base;
-
 	pr_err("Unexpected IOMMU page fault!\n");
-	pr_err("base = %08x\n", (unsigned int) base);
+	pr_err("base = %08x\n", (unsigned int)iommu->base);
 
-	ret = __enable_clocks(drvdata);
+	ret = __enable_clocks(iommu);
 	if (ret)
 		goto fail;
 
-	for (i = 0; i < drvdata->ncb; i++) {
-		fsr = GET_FSR(base, i);
+	for (i = 0; i < iommu->ncb; i++) {
+		fsr = GET_FSR(iommu->base, i);
 		if (fsr) {
 			pr_err("Fault occurred in context %d.\n", i);
 			pr_err("Interesting registers:\n");
-			print_ctx_regs(base, i);
-			SET_FSR(base, i, 0x4000000F);
+			print_ctx_regs(iommu->base, i);
+			SET_FSR(iommu->base, i, 0x4000000F);
 		}
 	}
-	__disable_clocks(drvdata);
+	__disable_clocks(iommu);
 fail:
 	spin_unlock(&msm_iommu_lock);
 	return 0;
diff --git a/drivers/iommu/msm_iommu.h b/drivers/iommu/msm_iommu.h
index 5c7c955..4ca25d5 100644
--- a/drivers/iommu/msm_iommu.h
+++ b/drivers/iommu/msm_iommu.h
@@ -42,74 +42,53 @@
  */
 #define MAX_NUM_MIDS	32
 
+/* Maximum number of context banks that can be present in IOMMU */
+#define IOMMU_MAX_CBS	128
+
 /**
  * struct msm_iommu_dev - a single IOMMU hardware instance
- * name		Human-readable name given to this IOMMU HW instance
  * ncb		Number of context banks present on this IOMMU HW instance
+ * dev:		IOMMU device
+ * irq:		Interrupt number
+ * clk:		The bus clock for this IOMMU hardware instance
+ * pclk:	The clock for the IOMMU bus interconnect
+ * dev_node:	list head in qcom_iommu_device_list
+ * dom_node:	list head for domain
+ * ctx_list:	list of 'struct msm_iommu_ctx_dev'
+ * context_map: Bitmap to track allocated context banks
  */
 struct msm_iommu_dev {
-	const char *name;
+	void __iomem *base;
 	int ncb;
+	struct device *dev;
+	int irq;
+	struct clk *clk;
+	struct clk *pclk;
+	struct list_head dev_node;
+	struct list_head dom_node;
+	struct list_head ctx_list;
+	DECLARE_BITMAP(context_map, IOMMU_MAX_CBS);
 };
 
 /**
  * struct msm_iommu_ctx_dev - an IOMMU context bank instance
- * name		Human-readable name given to this context bank
+ * of_node	node ptr of client device
  * num		Index of this context bank within the hardware
  * mids		List of Machine IDs that are to be mapped into this context
  *		bank, terminated by -1. The MID is a set of signals on the
  *		AXI bus that identifies the function associated with a specific
  *		memory request. (See ARM spec).
+ * num_mids	Total number of mids
+ * node		list head in ctx_list
  */
 struct msm_iommu_ctx_dev {
-	const char *name;
+	struct device_node *of_node;
 	int num;
 	int mids[MAX_NUM_MIDS];
+	int num_mids;
+	struct list_head list;
 };
 
-
-/**
- * struct msm_iommu_drvdata - A single IOMMU hardware instance
- * @base:	IOMMU config port base address (VA)
- * @ncb		The number of contexts on this IOMMU
- * @irq:	Interrupt number
- * @clk:	The bus clock for this IOMMU hardware instance
- * @pclk:	The clock for the IOMMU bus interconnect
- *
- * A msm_iommu_drvdata holds the global driver data about a single piece
- * of an IOMMU hardware instance.
- */
-struct msm_iommu_drvdata {
-	void __iomem *base;
-	int irq;
-	int ncb;
-	struct clk *clk;
-	struct clk *pclk;
-};
-
-/**
- * struct msm_iommu_ctx_drvdata - an IOMMU context bank instance
- * @num:		Hardware context number of this context
- * @pdev:		Platform device associated wit this HW instance
- * @attached_elm:	List element for domains to track which devices are
- *			attached to them
- *
- * A msm_iommu_ctx_drvdata holds the driver data for a single context bank
- * within each IOMMU hardware instance
- */
-struct msm_iommu_ctx_drvdata {
-	int num;
-	struct platform_device *pdev;
-	struct list_head attached_elm;
-};
-
-/*
- * Look up an IOMMU context device by its context name. NULL if none found.
- * Useful for testing and drivers that do not yet fully have IOMMU stuff in
- * their platform devices.
- */
-struct device *msm_iommu_get_ctx(const char *ctx_name);
-
 /*
  * Interrupt handler for the IOMMU context fault interrupt. Hooking the
  * interrupt is not supported in the API yet, but this will print an error
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
index 4b09e81..9f1e760 100644
--- a/drivers/iommu/msm_iommu_dev.c
+++ b/drivers/iommu/msm_iommu_dev.c
@@ -30,60 +30,6 @@
 #include "msm_iommu_hw-8xxx.h"
 #include "msm_iommu.h"
 
-struct iommu_ctx_iter_data {
-	/* input */
-	const char *name;
-
-	/* output */
-	struct device *dev;
-};
-
-static struct platform_device *msm_iommu_root_dev;
-
-static int each_iommu_ctx(struct device *dev, void *data)
-{
-	struct iommu_ctx_iter_data *res = data;
-	struct msm_iommu_ctx_dev *c = dev->platform_data;
-
-	if (!res || !c || !c->name || !res->name)
-		return -EINVAL;
-
-	if (!strcmp(res->name, c->name)) {
-		res->dev = dev;
-		return 1;
-	}
-	return 0;
-}
-
-static int each_iommu(struct device *dev, void *data)
-{
-	return device_for_each_child(dev, data, each_iommu_ctx);
-}
-
-struct device *msm_iommu_get_ctx(const char *ctx_name)
-{
-	struct iommu_ctx_iter_data r;
-	int found;
-
-	if (!msm_iommu_root_dev) {
-		pr_err("No root IOMMU device.\n");
-		goto fail;
-	}
-
-	r.name = ctx_name;
-	found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
-
-	if (!found) {
-		pr_err("Could not find context <%s>\n", ctx_name);
-		goto fail;
-	}
-
-	return r.dev;
-fail:
-	return NULL;
-}
-EXPORT_SYMBOL(msm_iommu_get_ctx);
-
 static void msm_iommu_reset(void __iomem *base, int ncb)
 {
 	int ctx;
@@ -128,237 +74,122 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
 static int msm_iommu_probe(struct platform_device *pdev)
 {
 	struct resource *r;
-	struct clk *iommu_clk;
-	struct clk *iommu_pclk;
-	struct msm_iommu_drvdata *drvdata;
-	struct msm_iommu_dev *iommu_dev = dev_get_platdata(&pdev->dev);
-	void __iomem *regs_base;
-	int ret, irq, par;
+	struct msm_iommu_dev *iommu;
+	int ret, par, val;
 
-	if (pdev->id == -1) {
-		msm_iommu_root_dev = pdev;
-		return 0;
-	}
+	iommu = devm_kzalloc(&pdev->dev, sizeof(*iommu), GFP_KERNEL);
+	if (!iommu)
+		return -ENODEV;
 
-	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+	iommu->dev = &pdev->dev;
+	INIT_LIST_HEAD(&iommu->ctx_list);
 
-	if (!drvdata) {
-		ret = -ENOMEM;
-		goto fail;
+	iommu->pclk = devm_clk_get(iommu->dev, "smmu_pclk");
+	if (IS_ERR(iommu->pclk)) {
+		dev_err(iommu->dev, "could not get smmu_pclk\n");
+		return PTR_ERR(iommu->pclk);
 	}
 
-	if (!iommu_dev) {
-		ret = -ENODEV;
-		goto fail;
+	ret = clk_prepare(iommu->pclk);
+	if (ret) {
+		dev_err(iommu->dev, "could not prepare smmu_pclk\n");
+		return ret;
 	}
 
-	iommu_pclk = clk_get(NULL, "smmu_pclk");
-	if (IS_ERR(iommu_pclk)) {
-		ret = -ENODEV;
-		goto fail;
+	iommu->clk = devm_clk_get(iommu->dev, "iommu_clk");
+	if (IS_ERR(iommu->clk)) {
+		dev_err(iommu->dev, "could not get iommu_clk\n");
+		clk_unprepare(iommu->pclk);
+		return PTR_ERR(iommu->clk);
 	}
 
-	ret = clk_prepare_enable(iommu_pclk);
-	if (ret)
-		goto fail_enable;
-
-	iommu_clk = clk_get(&pdev->dev, "iommu_clk");
-
-	if (!IS_ERR(iommu_clk))	{
-		if (clk_get_rate(iommu_clk) == 0)
-			clk_set_rate(iommu_clk, 1);
-
-		ret = clk_prepare_enable(iommu_clk);
-		if (ret) {
-			clk_put(iommu_clk);
-			goto fail_pclk;
-		}
-	} else
-		iommu_clk = NULL;
+	ret = clk_prepare(iommu->clk);
+	if (ret) {
+		dev_err(iommu->dev, "could not prepare iommu_clk\n");
+		clk_unprepare(iommu->pclk);
+		return ret;
+	}
 
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");
-	regs_base = devm_ioremap_resource(&pdev->dev, r);
-	if (IS_ERR(regs_base)) {
-		ret = PTR_ERR(regs_base);
-		goto fail_clk;
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	iommu->base = devm_ioremap_resource(iommu->dev, r);
+	if (IS_ERR(iommu->base)) {
+		dev_err(iommu->dev, "could not get iommu base\n");
+		ret = PTR_ERR(iommu->base);
+		goto fail;
 	}
 
-	irq = platform_get_irq_byname(pdev, "secure_irq");
-	if (irq < 0) {
+	iommu->irq = platform_get_irq(pdev, 0);
+	if (iommu->irq < 0) {
+		dev_err(iommu->dev, "could not get iommu irq\n");
 		ret = -ENODEV;
-		goto fail_clk;
+		goto fail;
 	}
 
-	msm_iommu_reset(regs_base, iommu_dev->ncb);
+	ret = of_property_read_u32(iommu->dev->of_node, "ncb", &val);
+	if (ret) {
+		dev_err(iommu->dev, "could not get ncb\n");
+		goto fail;
+	}
+	iommu->ncb = val;
 
-	SET_M(regs_base, 0, 1);
-	SET_PAR(regs_base, 0, 0);
-	SET_V2PCFG(regs_base, 0, 1);
-	SET_V2PPR(regs_base, 0, 0);
-	par = GET_PAR(regs_base, 0);
-	SET_V2PCFG(regs_base, 0, 0);
-	SET_M(regs_base, 0, 0);
+	msm_iommu_reset(iommu->base, iommu->ncb);
+	SET_M(iommu->base, 0, 1);
+	SET_PAR(iommu->base, 0, 0);
+	SET_V2PCFG(iommu->base, 0, 1);
+	SET_V2PPR(iommu->base, 0, 0);
+	par = GET_PAR(iommu->base, 0);
+	SET_V2PCFG(iommu->base, 0, 0);
+	SET_M(iommu->base, 0, 0);
 
 	if (!par) {
-		pr_err("%s: Invalid PAR value detected\n", iommu_dev->name);
+		pr_err("Invalid PAR value detected\n");
 		ret = -ENODEV;
-		goto fail_clk;
+		goto fail;
 	}
 
-	ret = request_irq(irq, msm_iommu_fault_handler, 0,
-			"msm_iommu_secure_irpt_handler", drvdata);
+	ret = devm_request_threaded_irq(iommu->dev, iommu->irq, NULL,
+					msm_iommu_fault_handler,
+					IRQF_ONESHOT | IRQF_SHARED,
+					"msm_iommu_secure_irpt_handler",
+					iommu);
 	if (ret) {
-		pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
-		goto fail_clk;
+		pr_err("Request IRQ %d failed with ret=%d\n", iommu->irq, ret);
+		goto fail;
 	}
 
+	list_add(&iommu->dev_node, &qcom_iommu_devices);
 
-	drvdata->pclk = iommu_pclk;
-	drvdata->clk = iommu_clk;
-	drvdata->base = regs_base;
-	drvdata->irq = irq;
-	drvdata->ncb = iommu_dev->ncb;
-
-	pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
-		iommu_dev->name, regs_base, irq, iommu_dev->ncb);
-
-	platform_set_drvdata(pdev, drvdata);
-
-	clk_disable(iommu_clk);
-
-	clk_disable(iommu_pclk);
-
-	return 0;
-fail_clk:
-	if (iommu_clk) {
-		clk_disable(iommu_clk);
-		clk_put(iommu_clk);
-	}
-fail_pclk:
-	clk_disable_unprepare(iommu_pclk);
-fail_enable:
-	clk_put(iommu_pclk);
+	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
+		iommu->base, iommu->irq, iommu->ncb);
 fail:
-	kfree(drvdata);
+	clk_unprepare(iommu->clk);
+	clk_unprepare(iommu->pclk);
 	return ret;
 }
 
+static const struct of_device_id msm_iommu_dt_match[] = {
+	{ .compatible = "qcom,iommu-v0-apq8064" },
+	{}
+};
+
 static int msm_iommu_remove(struct platform_device *pdev)
 {
-	struct msm_iommu_drvdata *drv = NULL;
+	struct msm_iommu_dev *iommu = platform_get_drvdata(pdev);
 
-	drv = platform_get_drvdata(pdev);
-	if (drv) {
-		if (drv->clk) {
-			clk_unprepare(drv->clk);
-			clk_put(drv->clk);
-		}
-		clk_unprepare(drv->pclk);
-		clk_put(drv->pclk);
-		memset(drv, 0, sizeof(*drv));
-		kfree(drv);
-	}
-	return 0;
-}
-
-static int msm_iommu_ctx_probe(struct platform_device *pdev)
-{
-	struct msm_iommu_ctx_dev *c = dev_get_platdata(&pdev->dev);
-	struct msm_iommu_drvdata *drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-	int i, ret;
-
-	if (!c || !pdev->dev.parent)
-		return -EINVAL;
-
-	drvdata = dev_get_drvdata(pdev->dev.parent);
-	if (!drvdata)
-		return -ENODEV;
-
-	ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL);
-	if (!ctx_drvdata)
-		return -ENOMEM;
-
-	ctx_drvdata->num = c->num;
-	ctx_drvdata->pdev = pdev;
-
-	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
-	platform_set_drvdata(pdev, ctx_drvdata);
-
-	ret = clk_prepare_enable(drvdata->pclk);
-	if (ret)
-		goto fail;
-
-	if (drvdata->clk) {
-		ret = clk_prepare_enable(drvdata->clk);
-		if (ret) {
-			clk_disable_unprepare(drvdata->pclk);
-			goto fail;
-		}
-	}
-
-	/* Program the M2V tables for this context */
-	for (i = 0; i < MAX_NUM_MIDS; i++) {
-		int mid = c->mids[i];
-		if (mid == -1)
-			break;
-
-		SET_M2VCBR_N(drvdata->base, mid, 0);
-		SET_CBACR_N(drvdata->base, c->num, 0);
-
-		/* Set VMID = 0 */
-		SET_VMID(drvdata->base, mid, 0);
-
-		/* Set the context number for that MID to this context */
-		SET_CBNDX(drvdata->base, mid, c->num);
-
-		/* Set MID associated with this context bank to 0*/
-		SET_CBVMID(drvdata->base, c->num, 0);
-
-		/* Set the ASID for TLB tagging for this context */
-		SET_CONTEXTIDR_ASID(drvdata->base, c->num, c->num);
-
-		/* Set security bit override to be Non-secure */
-		SET_NSCFG(drvdata->base, mid, 3);
-	}
-
-	clk_disable(drvdata->clk);
-	clk_disable(drvdata->pclk);
-
-	dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
-	return 0;
-fail:
-	kfree(ctx_drvdata);
-	return ret;
-}
-
-static int msm_iommu_ctx_remove(struct platform_device *pdev)
-{
-	struct msm_iommu_ctx_drvdata *drv = NULL;
-	drv = platform_get_drvdata(pdev);
-	if (drv) {
-		memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
-		kfree(drv);
-	}
+	clk_unprepare(iommu->clk);
+	clk_unprepare(iommu->pclk);
 	return 0;
 }
 
 static struct platform_driver msm_iommu_driver = {
 	.driver = {
 		.name	= "msm_iommu",
+		.of_match_table = msm_iommu_dt_match,
 	},
 	.probe		= msm_iommu_probe,
 	.remove		= msm_iommu_remove,
 };
 
-static struct platform_driver msm_iommu_ctx_driver = {
-	.driver = {
-		.name	= "msm_iommu_ctx",
-	},
-	.probe		= msm_iommu_ctx_probe,
-	.remove		= msm_iommu_ctx_remove,
-};
-
 static struct platform_driver * const drivers[] = {
 	&msm_iommu_driver,
 	&msm_iommu_ctx_driver,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May 15 23:48:56 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon, 16 May 2016 12:18:56 +0530
Subject: [PATCH V4 2/7] documentation: iommu: Add bindings for msm, iommu-v0 ip
In-Reply-To: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463381341-30498-3-git-send-email-sricharan@codeaurora.org>

The MSM IOMMU is an implementation compatible with the ARM VMSA short
descriptor page tables. It provides address translation for bus masters outside
of the CPU, each connected to the IOMMU through a port called micro-TLB.
Adding the DT bindings for the same.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 .../devicetree/bindings/iommu/msm,iommu-v0.txt     | 64 ++++++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt

diff --git a/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
new file mode 100644
index 0000000..b22c607
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
@@ -0,0 +1,64 @@
+* QCOM IOMMU
+
+The MSM IOMMU is an implementation compatible with the ARM VMSA short
+descriptor page tables. It provides address translation for bus masters outside
+of the CPU, each connected to the IOMMU through a port called micro-TLB.
+
+Required Properties:
+
+  - compatible: Must contain "qcom,iommu-v0-apq8064".
+  - reg: Base address and size of the IOMMU registers.
+  - interrupts: Specifiers for the MMU fault interrupts. For instances that
+    support secure mode two interrupts must be specified, for non-secure and
+    secure mode, in that order. For instances that don't support secure mode a
+    single interrupt must be specified.
+  - #iommu-cells: The number of cells needed to specify the stream id. This
+		  is always 1.
+  - qcom,ncb:	  The total number of context banks in the IOMMU.
+  - clocks	: List of clocks to be used during SMMU register access. See
+		  Documentation/devicetree/bindings/clock/clock-bindings.txt
+		  for information about the format. For each clock specified
+		  here, there must be a corresponding entry in clock-names
+		  (see below).
+
+  - clock-names	: List of clock names corresponding to the clocks specified in
+		  the "clocks" property (above).
+		  Should be "smmu_pclk" for specifying the interface clock
+		  required for iommu's register accesses.
+		  Should be "smmu_clk" for specifying the functional clock
+		  required by iommu for bus accesses.
+
+Each bus master connected to an IOMMU must reference the IOMMU in its device
+node with the following property:
+
+  - iommus: A reference to the IOMMU in multiple cells. The first cell is a
+	    phandle to the IOMMU and the second cell is the stream id.
+	    A single master device can be connected to more than one iommu
+	    and multiple contexts in each of the iommu. So multiple entries
+	    are required to list all the iommus and the stream ids that the
+	    master is connected to.
+
+Example: mdp iommu and its bus master
+
+                mdp_port0: iommu at 7500000 {
+			compatible = "qcom,iommu-v0-apq8064";
+			#iommu-cells = <1>;
+			clock-names =
+			    "smmu_pclk",
+			    "smmu_clk";
+			clocks =
+			    <&mmcc SMMU_AHB_CLK>,
+			    <&mmcc MDP_AXI_CLK>;
+			reg = <0x07500000 0x100000>;
+			interrupts =
+			    <GIC_SPI 63 0>,
+			    <GIC_SPI 64 0>;
+			qcom,ncb = <2>;
+		};
+
+		mdp: qcom,mdp at 5100000 {
+			compatible = "qcom,mdp";
+			...
+			iommus = <&mdp_port0 0
+				  &mdp_port0 2>;
+		};
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May 15 23:48:57 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon, 16 May 2016 12:18:57 +0530
Subject: [PATCH V4 3/7] iommu/msm: Move the contents from msm_iommu_dev.c to
 msm_iommu.c
In-Reply-To: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463381341-30498-4-git-send-email-sricharan@codeaurora.org>

There are only two functions left in msm_iommu_dev.c. Move it to
msm_iommu.c and delete the file.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/Makefile        |   2 +-
 drivers/iommu/msm_iommu.c     | 182 ++++++++++++++++++++++++++++++++++++
 drivers/iommu/msm_iommu_dev.c | 212 ------------------------------------------
 3 files changed, 183 insertions(+), 213 deletions(-)
 delete mode 100644 drivers/iommu/msm_iommu_dev.c

diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index e7b64d1..6de2fb1 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
-obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
+obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
 obj-$(CONFIG_QCOM_IOMMU_V1) += qcom/
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index bc1a4e3..f532c9f 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/iommu.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
@@ -85,6 +86,47 @@ static void __disable_clocks(struct msm_iommu_dev *iommu)
 	clk_disable(iommu->pclk);
 }
 
+static void msm_iommu_reset(void __iomem *base, int ncb)
+{
+	int ctx;
+
+	SET_RPUE(base, 0);
+	SET_RPUEIE(base, 0);
+	SET_ESRRESTORE(base, 0);
+	SET_TBE(base, 0);
+	SET_CR(base, 0);
+	SET_SPDMBE(base, 0);
+	SET_TESTBUSCR(base, 0);
+	SET_TLBRSW(base, 0);
+	SET_GLOBAL_TLBIALL(base, 0);
+	SET_RPU_ACR(base, 0);
+	SET_TLBLKCRWE(base, 1);
+
+	for (ctx = 0; ctx < ncb; ctx++) {
+		SET_BPRCOSH(base, ctx, 0);
+		SET_BPRCISH(base, ctx, 0);
+		SET_BPRCNSH(base, ctx, 0);
+		SET_BPSHCFG(base, ctx, 0);
+		SET_BPMTCFG(base, ctx, 0);
+		SET_ACTLR(base, ctx, 0);
+		SET_SCTLR(base, ctx, 0);
+		SET_FSRRESTORE(base, ctx, 0);
+		SET_TTBR0(base, ctx, 0);
+		SET_TTBR1(base, ctx, 0);
+		SET_TTBCR(base, ctx, 0);
+		SET_BFBCR(base, ctx, 0);
+		SET_PAR(base, ctx, 0);
+		SET_FAR(base, ctx, 0);
+		SET_CTX_TLBIALL(base, ctx, 0);
+		SET_TLBFLPTER(base, ctx, 0);
+		SET_TLBSLPTER(base, ctx, 0);
+		SET_TLBLKCR(base, ctx, 0);
+		SET_PRRR(base, ctx, 0);
+		SET_NMRR(base, ctx, 0);
+		SET_CONTEXTIDR(base, ctx, 0);
+	}
+}
+
 static int __flush_iotlb(struct iommu_domain *domain)
 {
 	struct msm_priv *priv = to_msm_priv(domain);
@@ -708,6 +750,146 @@ static const struct iommu_ops msm_iommu_ops = {
 	.pgsize_bitmap = MSM_IOMMU_PGSIZES,
 };
 
+static int msm_iommu_probe(struct platform_device *pdev)
+{
+	struct resource *r;
+	struct msm_iommu_dev *iommu;
+	int ret, par, val;
+
+	iommu = devm_kzalloc(&pdev->dev, sizeof(*iommu), GFP_KERNEL);
+	if (!iommu)
+		return -ENODEV;
+
+	iommu->dev = &pdev->dev;
+	INIT_LIST_HEAD(&iommu->ctx_list);
+
+	iommu->pclk = devm_clk_get(iommu->dev, "smmu_pclk");
+	if (IS_ERR(iommu->pclk)) {
+		dev_err(iommu->dev, "could not get smmu_pclk\n");
+		return PTR_ERR(iommu->pclk);
+	}
+
+	ret = clk_prepare(iommu->pclk);
+	if (ret) {
+		dev_err(iommu->dev, "could not prepare smmu_pclk\n");
+		return ret;
+	}
+
+	iommu->clk = devm_clk_get(iommu->dev, "iommu_clk");
+	if (IS_ERR(iommu->clk)) {
+		dev_err(iommu->dev, "could not get iommu_clk\n");
+		clk_unprepare(iommu->pclk);
+		return PTR_ERR(iommu->clk);
+	}
+
+	ret = clk_prepare(iommu->clk);
+	if (ret) {
+		dev_err(iommu->dev, "could not prepare iommu_clk\n");
+		clk_unprepare(iommu->pclk);
+		return ret;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	iommu->base = devm_ioremap_resource(iommu->dev, r);
+	if (IS_ERR(iommu->base)) {
+		dev_err(iommu->dev, "could not get iommu base\n");
+		ret = PTR_ERR(iommu->base);
+		goto fail;
+	}
+
+	iommu->irq = platform_get_irq(pdev, 0);
+	if (iommu->irq < 0) {
+		dev_err(iommu->dev, "could not get iommu irq\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	ret = of_property_read_u32(iommu->dev->of_node, "qcom,ncb", &val);
+	if (ret) {
+		dev_err(iommu->dev, "could not get ncb\n");
+		goto fail;
+	}
+	iommu->ncb = val;
+
+	msm_iommu_reset(iommu->base, iommu->ncb);
+	SET_M(iommu->base, 0, 1);
+	SET_PAR(iommu->base, 0, 0);
+	SET_V2PCFG(iommu->base, 0, 1);
+	SET_V2PPR(iommu->base, 0, 0);
+	par = GET_PAR(iommu->base, 0);
+	SET_V2PCFG(iommu->base, 0, 0);
+	SET_M(iommu->base, 0, 0);
+
+	if (!par) {
+		pr_err("Invalid PAR value detected\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	ret = devm_request_threaded_irq(iommu->dev, iommu->irq, NULL,
+					msm_iommu_fault_handler,
+					IRQF_ONESHOT | IRQF_SHARED,
+					"msm_iommu_secure_irpt_handler",
+					iommu);
+	if (ret) {
+		pr_err("Request IRQ %d failed with ret=%d\n", iommu->irq, ret);
+		goto fail;
+	}
+
+	list_add(&iommu->dev_node, &qcom_iommu_devices);
+
+	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
+		iommu->base, iommu->irq, iommu->ncb);
+
+	return ret;
+fail:
+	clk_unprepare(iommu->clk);
+	clk_unprepare(iommu->pclk);
+	return ret;
+}
+
+static const struct of_device_id msm_iommu_dt_match[] = {
+	{ .compatible = "qcom,iommu-v0-apq8064" },
+	{}
+};
+
+static int msm_iommu_remove(struct platform_device *pdev)
+{
+	struct msm_iommu_dev *iommu = platform_get_drvdata(pdev);
+
+	clk_unprepare(iommu->clk);
+	clk_unprepare(iommu->pclk);
+	return 0;
+}
+
+static struct platform_driver msm_iommu_driver = {
+	.driver = {
+		.name	= "msm_iommu",
+		.of_match_table = msm_iommu_dt_match,
+	},
+	.probe		= msm_iommu_probe,
+	.remove		= msm_iommu_remove,
+};
+
+static int __init msm_iommu_driver_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&msm_iommu_driver);
+	if (ret != 0)
+		pr_err("Failed to register IOMMU driver\n");
+
+	return ret;
+}
+
+static void __exit msm_iommu_driver_exit(void)
+{
+	platform_driver_unregister(&msm_iommu_driver);
+}
+
+subsys_initcall(msm_iommu_driver_init);
+module_exit(msm_iommu_driver_exit);
+
 static int __init get_tex_class(int icp, int ocp, int mt, int nos)
 {
 	int i = 0;
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
deleted file mode 100644
index 9f1e760..0000000
--- a/drivers/iommu/msm_iommu_dev.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/iommu.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-#include "msm_iommu_hw-8xxx.h"
-#include "msm_iommu.h"
-
-static void msm_iommu_reset(void __iomem *base, int ncb)
-{
-	int ctx;
-
-	SET_RPUE(base, 0);
-	SET_RPUEIE(base, 0);
-	SET_ESRRESTORE(base, 0);
-	SET_TBE(base, 0);
-	SET_CR(base, 0);
-	SET_SPDMBE(base, 0);
-	SET_TESTBUSCR(base, 0);
-	SET_TLBRSW(base, 0);
-	SET_GLOBAL_TLBIALL(base, 0);
-	SET_RPU_ACR(base, 0);
-	SET_TLBLKCRWE(base, 1);
-
-	for (ctx = 0; ctx < ncb; ctx++) {
-		SET_BPRCOSH(base, ctx, 0);
-		SET_BPRCISH(base, ctx, 0);
-		SET_BPRCNSH(base, ctx, 0);
-		SET_BPSHCFG(base, ctx, 0);
-		SET_BPMTCFG(base, ctx, 0);
-		SET_ACTLR(base, ctx, 0);
-		SET_SCTLR(base, ctx, 0);
-		SET_FSRRESTORE(base, ctx, 0);
-		SET_TTBR0(base, ctx, 0);
-		SET_TTBR1(base, ctx, 0);
-		SET_TTBCR(base, ctx, 0);
-		SET_BFBCR(base, ctx, 0);
-		SET_PAR(base, ctx, 0);
-		SET_FAR(base, ctx, 0);
-		SET_CTX_TLBIALL(base, ctx, 0);
-		SET_TLBFLPTER(base, ctx, 0);
-		SET_TLBSLPTER(base, ctx, 0);
-		SET_TLBLKCR(base, ctx, 0);
-		SET_PRRR(base, ctx, 0);
-		SET_NMRR(base, ctx, 0);
-		SET_CONTEXTIDR(base, ctx, 0);
-	}
-}
-
-static int msm_iommu_probe(struct platform_device *pdev)
-{
-	struct resource *r;
-	struct msm_iommu_dev *iommu;
-	int ret, par, val;
-
-	iommu = devm_kzalloc(&pdev->dev, sizeof(*iommu), GFP_KERNEL);
-	if (!iommu)
-		return -ENODEV;
-
-	iommu->dev = &pdev->dev;
-	INIT_LIST_HEAD(&iommu->ctx_list);
-
-	iommu->pclk = devm_clk_get(iommu->dev, "smmu_pclk");
-	if (IS_ERR(iommu->pclk)) {
-		dev_err(iommu->dev, "could not get smmu_pclk\n");
-		return PTR_ERR(iommu->pclk);
-	}
-
-	ret = clk_prepare(iommu->pclk);
-	if (ret) {
-		dev_err(iommu->dev, "could not prepare smmu_pclk\n");
-		return ret;
-	}
-
-	iommu->clk = devm_clk_get(iommu->dev, "iommu_clk");
-	if (IS_ERR(iommu->clk)) {
-		dev_err(iommu->dev, "could not get iommu_clk\n");
-		clk_unprepare(iommu->pclk);
-		return PTR_ERR(iommu->clk);
-	}
-
-	ret = clk_prepare(iommu->clk);
-	if (ret) {
-		dev_err(iommu->dev, "could not prepare iommu_clk\n");
-		clk_unprepare(iommu->pclk);
-		return ret;
-	}
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	iommu->base = devm_ioremap_resource(iommu->dev, r);
-	if (IS_ERR(iommu->base)) {
-		dev_err(iommu->dev, "could not get iommu base\n");
-		ret = PTR_ERR(iommu->base);
-		goto fail;
-	}
-
-	iommu->irq = platform_get_irq(pdev, 0);
-	if (iommu->irq < 0) {
-		dev_err(iommu->dev, "could not get iommu irq\n");
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	ret = of_property_read_u32(iommu->dev->of_node, "ncb", &val);
-	if (ret) {
-		dev_err(iommu->dev, "could not get ncb\n");
-		goto fail;
-	}
-	iommu->ncb = val;
-
-	msm_iommu_reset(iommu->base, iommu->ncb);
-	SET_M(iommu->base, 0, 1);
-	SET_PAR(iommu->base, 0, 0);
-	SET_V2PCFG(iommu->base, 0, 1);
-	SET_V2PPR(iommu->base, 0, 0);
-	par = GET_PAR(iommu->base, 0);
-	SET_V2PCFG(iommu->base, 0, 0);
-	SET_M(iommu->base, 0, 0);
-
-	if (!par) {
-		pr_err("Invalid PAR value detected\n");
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	ret = devm_request_threaded_irq(iommu->dev, iommu->irq, NULL,
-					msm_iommu_fault_handler,
-					IRQF_ONESHOT | IRQF_SHARED,
-					"msm_iommu_secure_irpt_handler",
-					iommu);
-	if (ret) {
-		pr_err("Request IRQ %d failed with ret=%d\n", iommu->irq, ret);
-		goto fail;
-	}
-
-	list_add(&iommu->dev_node, &qcom_iommu_devices);
-
-	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
-		iommu->base, iommu->irq, iommu->ncb);
-fail:
-	clk_unprepare(iommu->clk);
-	clk_unprepare(iommu->pclk);
-	return ret;
-}
-
-static const struct of_device_id msm_iommu_dt_match[] = {
-	{ .compatible = "qcom,iommu-v0-apq8064" },
-	{}
-};
-
-static int msm_iommu_remove(struct platform_device *pdev)
-{
-	struct msm_iommu_dev *iommu = platform_get_drvdata(pdev);
-
-	clk_unprepare(iommu->clk);
-	clk_unprepare(iommu->pclk);
-	return 0;
-}
-
-static struct platform_driver msm_iommu_driver = {
-	.driver = {
-		.name	= "msm_iommu",
-		.of_match_table = msm_iommu_dt_match,
-	},
-	.probe		= msm_iommu_probe,
-	.remove		= msm_iommu_remove,
-};
-
-static struct platform_driver * const drivers[] = {
-	&msm_iommu_driver,
-	&msm_iommu_ctx_driver,
-};
-
-static int __init msm_iommu_driver_init(void)
-{
-	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
-}
-
-static void __exit msm_iommu_driver_exit(void)
-{
-	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
-}
-
-subsys_initcall(msm_iommu_driver_init);
-module_exit(msm_iommu_driver_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Stepan Moskovchenko <stepanm at codeaurora.org>");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May 15 23:48:58 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon, 16 May 2016 12:18:58 +0530
Subject: [PATCH V4 4/7] iommu/msm: Add support for generic master bindings
In-Reply-To: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463381341-30498-5-git-send-email-sricharan@codeaurora.org>

This adds the xlate callback which gets invoked during
device registration from DT. The master devices gets added
through this.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/msm_iommu.c | 61 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 59 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index f532c9f..a90a121 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -28,6 +28,7 @@
 #include <linux/iommu.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/of_iommu.h>
 
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
@@ -702,6 +703,54 @@ static void print_ctx_regs(void __iomem *base, int ctx)
 	       GET_PRRR(base, ctx), GET_NMRR(base, ctx));
 }
 
+static void insert_iommu_master(struct device *dev,
+				struct msm_iommu_dev **iommu,
+				struct of_phandle_args *spec)
+{
+	struct msm_iommu_ctx_dev *master = dev->archdata.iommu;
+	int sid;
+
+	if (list_empty(&(*iommu)->ctx_list)) {
+		master = kzalloc(sizeof(*master), GFP_ATOMIC);
+		master->of_node = dev->of_node;
+		list_add(&master->list, &(*iommu)->ctx_list);
+		dev->archdata.iommu = master;
+	}
+
+	for (sid = 0; sid < master->num_mids; sid++)
+		if (master->mids[sid] == spec->args[0]) {
+			dev_warn(dev, "Stream ID 0x%hx repeated; ignoring\n",
+				 sid);
+			return;
+		}
+
+	master->mids[master->num_mids++] = spec->args[0];
+}
+
+static int qcom_iommu_of_xlate(struct device *dev,
+			       struct of_phandle_args *spec)
+{
+	struct msm_iommu_dev *iommu;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+	list_for_each_entry(iommu, &qcom_iommu_devices, dev_node)
+		if (iommu->dev->of_node == spec->np)
+			break;
+
+	if (!iommu || iommu->dev->of_node != spec->np) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	insert_iommu_master(dev, &iommu, spec);
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+
+	return ret;
+}
+
 irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 {
 	struct msm_iommu_dev *iommu = dev_id;
@@ -737,7 +786,7 @@ fail:
 	return 0;
 }
 
-static const struct iommu_ops msm_iommu_ops = {
+static struct iommu_ops msm_iommu_ops = {
 	.capable = msm_iommu_capable,
 	.domain_alloc = msm_iommu_domain_alloc,
 	.domain_free = msm_iommu_domain_free,
@@ -748,6 +797,7 @@ static const struct iommu_ops msm_iommu_ops = {
 	.map_sg = default_iommu_map_sg,
 	.iova_to_phys = msm_iommu_iova_to_phys,
 	.pgsize_bitmap = MSM_IOMMU_PGSIZES,
+	.of_xlate = qcom_iommu_of_xlate,
 };
 
 static int msm_iommu_probe(struct platform_device *pdev)
@@ -837,6 +887,7 @@ static int msm_iommu_probe(struct platform_device *pdev)
 	}
 
 	list_add(&iommu->dev_node, &qcom_iommu_devices);
+	of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops);
 
 	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
 		iommu->base, iommu->irq, iommu->ncb);
@@ -935,7 +986,13 @@ static int __init msm_iommu_init(void)
 	return 0;
 }
 
-subsys_initcall(msm_iommu_init);
+static int __init msm_iommu_of_setup(struct device_node *np)
+{
+	msm_iommu_init();
+	return 0;
+}
+
+IOMMU_OF_DECLARE(msm_iommu_of, "msm,iommu-v0", msm_iommu_of_setup);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Stepan Moskovchenko <stepanm at codeaurora.org>");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May 15 23:48:59 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon, 16 May 2016 12:18:59 +0530
Subject: [PATCH V4 5/7] iommu/msm: use generic ARMV7S short descriptor
 pagetable ops
In-Reply-To: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463381341-30498-6-git-send-email-sricharan@codeaurora.org>

This iommu uses the armv7 short descriptor format. So use the
generic ARMV7S pagetable ops instead of rewriting the same stuff
in the driver.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/Kconfig     |   1 +
 drivers/iommu/msm_iommu.c | 400 ++++++++++++----------------------------------
 2 files changed, 104 insertions(+), 297 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 55b2b3a..1f5d496 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -92,6 +92,7 @@ config MSM_IOMMU
 	depends on ARCH_MSM8X60 || ARCH_MSM8960 || COMPILE_TEST
 	depends on BROKEN
 	select IOMMU_API
+	select IOMMU_IO_PGTABLE_ARMV7S
 	help
 	  Support for the IOMMUs found on certain Qualcomm SOCs.
 	  These IOMMUs allow virtualization of the address space used by most
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index a90a121..f7b4c11 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -35,27 +35,27 @@
 
 #include "msm_iommu_hw-8xxx.h"
 #include "msm_iommu.h"
+#include "io-pgtable.h"
 
 #define MRC(reg, processor, op1, crn, crm, op2)				\
 __asm__ __volatile__ (							\
 "   mrc   "   #processor "," #op1 ", %0,"  #crn "," #crm "," #op2 "\n"  \
 : "=r" (reg))
 
-#define RCP15_PRRR(reg)		MRC(reg, p15, 0, c10, c2, 0)
-#define RCP15_NMRR(reg)		MRC(reg, p15, 0, c10, c2, 1)
-
 /* bitmap of the page sizes currently supported */
 #define MSM_IOMMU_PGSIZES	(SZ_4K | SZ_64K | SZ_1M | SZ_16M)
 
-static int msm_iommu_tex_class[4];
-
 DEFINE_SPINLOCK(msm_iommu_lock);
 static LIST_HEAD(qcom_iommu_devices);
+static struct iommu_ops msm_iommu_ops;
 
 struct msm_priv {
-	unsigned long *pgtable;
 	struct list_head list_attached;
 	struct iommu_domain domain;
+	struct io_pgtable_cfg	cfg;
+	struct io_pgtable_ops	*iop;
+	struct device		*dev;
+	spinlock_t		pgtlock; /* pagetable lock */
 };
 
 static struct msm_priv *to_msm_priv(struct iommu_domain *dom)
@@ -122,49 +122,74 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
 		SET_TLBFLPTER(base, ctx, 0);
 		SET_TLBSLPTER(base, ctx, 0);
 		SET_TLBLKCR(base, ctx, 0);
-		SET_PRRR(base, ctx, 0);
-		SET_NMRR(base, ctx, 0);
 		SET_CONTEXTIDR(base, ctx, 0);
 	}
 }
 
-static int __flush_iotlb(struct iommu_domain *domain)
+static void __flush_iotlb(void *cookie)
 {
-	struct msm_priv *priv = to_msm_priv(domain);
+	struct msm_priv *priv = cookie;
 	struct msm_iommu_dev *iommu = NULL;
 	struct msm_iommu_ctx_dev *master;
 	int ret = 0;
 
-#ifndef CONFIG_IOMMU_PGTABLES_L2
-	unsigned long *fl_table = priv->pgtable;
-	int i;
+	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
+		ret = __enable_clocks(iommu);
+		if (ret)
+			goto fail;
 
-	if (!list_empty(&priv->list_attached)) {
-		dmac_flush_range(fl_table, fl_table + SZ_16K);
+		list_for_each_entry(master, &iommu->ctx_list, list)
+			SET_CTX_TLBIALL(iommu->base, master->num, 0);
 
-		for (i = 0; i < NUM_FL_PTE; i++)
-			if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) {
-				void *sl_table = __va(fl_table[i] &
-								FL_BASE_MASK);
-				dmac_flush_range(sl_table, sl_table + SZ_4K);
-			}
+		__disable_clocks(iommu);
 	}
-#endif
+fail:
+	return;
+}
+
+static void __flush_iotlb_range(unsigned long iova, size_t size,
+				size_t granule, bool leaf, void *cookie)
+{
+	struct msm_priv *priv = cookie;
+	struct msm_iommu_dev *iommu = NULL;
+	struct msm_iommu_ctx_dev *master;
+	int ret = 0;
+	int temp_size;
 
 	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
 		ret = __enable_clocks(iommu);
 		if (ret)
 			goto fail;
 
-		list_for_each_entry(master, &iommu->ctx_list, list)
-			SET_CTX_TLBIALL(iommu->base, master->num, 0);
+		list_for_each_entry(master, &iommu->ctx_list, list) {
+			temp_size = size;
+			do {
+				iova &= TLBIVA_VA;
+				iova |= GET_CONTEXTIDR_ASID(iommu->base,
+							    master->num);
+				SET_TLBIVA(iommu->base, master->num, iova);
+				iova += granule;
+			} while (temp_size -= granule);
+		}
 
 		__disable_clocks(iommu);
 	}
+
 fail:
-	return ret;
+	return;
+}
+
+static void __flush_iotlb_sync(void *cookie)
+{
+	/* To avoid a null function pointer */
 }
 
+static const struct iommu_gather_ops msm_iommu_gather_ops = {
+	.tlb_flush_all = __flush_iotlb,
+	.tlb_add_flush = __flush_iotlb_range,
+	.tlb_sync = __flush_iotlb_sync,
+};
+
 static int msm_iommu_alloc_ctx(unsigned long *map, int start, int end)
 {
 	int idx;
@@ -232,15 +257,17 @@ static void __reset_context(void __iomem *base, int ctx)
 	SET_TLBFLPTER(base, ctx, 0);
 	SET_TLBSLPTER(base, ctx, 0);
 	SET_TLBLKCR(base, ctx, 0);
-	SET_PRRR(base, ctx, 0);
-	SET_NMRR(base, ctx, 0);
 }
 
-static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
+static void __program_context(void __iomem *base, int ctx,
+			      struct msm_priv *priv)
 {
-	unsigned int prrr, nmrr;
 	__reset_context(base, ctx);
 
+	/* Turn on TEX Remap */
+	SET_TRE(base, ctx, 1);
+	SET_AFE(base, ctx, 1);
+
 	/* Set up HTW mode */
 	/* TLB miss configuration: perform HTW on miss */
 	SET_TLBMCFG(base, ctx, 0x3);
@@ -248,8 +275,13 @@ static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
 	/* V2P configuration: HTW for access */
 	SET_V2PCFG(base, ctx, 0x3);
 
-	SET_TTBCR(base, ctx, 0);
-	SET_TTBR0_PA(base, ctx, (pgtable >> 14));
+	SET_TTBCR(base, ctx, priv->cfg.arm_v7s_cfg.tcr);
+	SET_TTBR0(base, ctx, priv->cfg.arm_v7s_cfg.ttbr[0]);
+	SET_TTBR1(base, ctx, priv->cfg.arm_v7s_cfg.ttbr[1]);
+
+	/* Set prrr and nmrr */
+	SET_PRRR(base, ctx, priv->cfg.arm_v7s_cfg.prrr);
+	SET_NMRR(base, ctx, priv->cfg.arm_v7s_cfg.nmrr);
 
 	/* Invalidate the TLB for this context */
 	SET_CTX_TLBIALL(base, ctx, 0);
@@ -268,38 +300,9 @@ static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
 	SET_RCOSH(base, ctx, 1);
 	SET_RCNSH(base, ctx, 1);
 
-	/* Turn on TEX Remap */
-	SET_TRE(base, ctx, 1);
-
-	/* Set TEX remap attributes */
-	RCP15_PRRR(prrr);
-	RCP15_NMRR(nmrr);
-	SET_PRRR(base, ctx, prrr);
-	SET_NMRR(base, ctx, nmrr);
-
 	/* Turn on BFB prefetch */
 	SET_BFBDFE(base, ctx, 1);
 
-#ifdef CONFIG_IOMMU_PGTABLES_L2
-	/* Configure page tables as inner-cacheable and shareable to reduce
-	 * the TLB miss penalty.
-	 */
-	SET_TTBR0_SH(base, ctx, 1);
-	SET_TTBR1_SH(base, ctx, 1);
-
-	SET_TTBR0_NOS(base, ctx, 1);
-	SET_TTBR1_NOS(base, ctx, 1);
-
-	SET_TTBR0_IRGNH(base, ctx, 0); /* WB, WA */
-	SET_TTBR0_IRGNL(base, ctx, 1);
-
-	SET_TTBR1_IRGNH(base, ctx, 0); /* WB, WA */
-	SET_TTBR1_IRGNL(base, ctx, 1);
-
-	SET_TTBR0_ORGN(base, ctx, 1); /* WB, WA */
-	SET_TTBR1_ORGN(base, ctx, 1); /* WB, WA */
-#endif
-
 	/* Enable the MMU */
 	SET_M(base, ctx, 1);
 }
@@ -316,13 +319,6 @@ static struct iommu_domain *msm_iommu_domain_alloc(unsigned type)
 		goto fail_nomem;
 
 	INIT_LIST_HEAD(&priv->list_attached);
-	priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL,
-							  get_order(SZ_16K));
-
-	if (!priv->pgtable)
-		goto fail_nomem;
-
-	memset(priv->pgtable, 0, SZ_16K);
 
 	priv->domain.geometry.aperture_start = 0;
 	priv->domain.geometry.aperture_end   = (1ULL << 32) - 1;
@@ -339,24 +335,35 @@ static void msm_iommu_domain_free(struct iommu_domain *domain)
 {
 	struct msm_priv *priv;
 	unsigned long flags;
-	unsigned long *fl_table;
-	int i;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
 	priv = to_msm_priv(domain);
+	kfree(priv);
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+}
 
-	fl_table = priv->pgtable;
+static int msm_iommu_domain_config(struct msm_priv *priv)
+{
+	spin_lock_init(&priv->pgtlock);
 
-	for (i = 0; i < NUM_FL_PTE; i++)
-		if ((fl_table[i] & 0x03) == FL_TYPE_TABLE)
-			free_page((unsigned long) __va(((fl_table[i]) &
-							FL_BASE_MASK)));
+	priv->cfg = (struct io_pgtable_cfg) {
+		.quirks = IO_PGTABLE_QUIRK_TLBI_ON_MAP,
+		.pgsize_bitmap = msm_iommu_ops.pgsize_bitmap,
+		.ias = 32,
+		.oas = 32,
+		.tlb = &msm_iommu_gather_ops,
+		.iommu_dev = priv->dev,
+	};
 
-	free_pages((unsigned long)priv->pgtable, get_order(SZ_16K));
-	priv->pgtable = NULL;
+	priv->iop = alloc_io_pgtable_ops(ARM_V7S, &priv->cfg, priv);
+	if (!priv->iop) {
+		dev_err(priv->dev, "Failed to allocate pgtable\n");
+		return -EINVAL;
+	}
 
-	kfree(priv);
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	msm_iommu_ops.pgsize_bitmap = priv->cfg.pgsize_bitmap;
+
+	return 0;
 }
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -367,6 +374,9 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 	struct msm_priv *priv = to_msm_priv(domain);
 	struct msm_iommu_ctx_dev *master;
 
+	priv->dev = dev;
+	msm_iommu_domain_config(priv);
+
 	spin_lock_irqsave(&msm_iommu_lock, flags);
 	list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) {
 		master = list_first_entry(&iommu->ctx_list,
@@ -392,14 +402,13 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 					}
 				config_mids(iommu, master);
 				__program_context(iommu->base, master->num,
-						  __pa(priv->pgtable));
+						  priv);
 			}
 			__disable_clocks(iommu);
 			list_add(&iommu->dom_node, &priv->list_attached);
 		}
 	}
 
-	ret = __flush_iotlb(domain);
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 
@@ -415,11 +424,9 @@ static void msm_iommu_detach_dev(struct iommu_domain *domain,
 	struct msm_iommu_ctx_dev *master;
 	int ret;
 
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-	ret = __flush_iotlb(domain);
-	if (ret)
-		goto fail;
+	free_io_pgtable_ops(priv->iop);
 
+	spin_lock_irqsave(&msm_iommu_lock, flags);
 	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
 		ret = __enable_clocks(iommu);
 		if (ret)
@@ -435,190 +442,30 @@ fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 }
 
-static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
+static int msm_iommu_map(struct iommu_domain *domain, unsigned long iova,
 			 phys_addr_t pa, size_t len, int prot)
 {
-	struct msm_priv *priv;
+	struct msm_priv *priv = to_msm_priv(domain);
 	unsigned long flags;
-	unsigned long *fl_table;
-	unsigned long *fl_pte;
-	unsigned long fl_offset;
-	unsigned long *sl_table;
-	unsigned long *sl_pte;
-	unsigned long sl_offset;
-	unsigned int pgprot;
-	int ret = 0, tex, sh;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	sh = (prot & MSM_IOMMU_ATTR_SH) ? 1 : 0;
-	tex = msm_iommu_tex_class[prot & MSM_IOMMU_CP_MASK];
-
-	if (tex < 0 || tex > NUM_TEX_CLASS - 1) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	priv = to_msm_priv(domain);
-
-	fl_table = priv->pgtable;
-
-	if (len != SZ_16M && len != SZ_1M &&
-	    len != SZ_64K && len != SZ_4K) {
-		pr_debug("Bad size: %d\n", len);
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (!fl_table) {
-		pr_debug("Null page table\n");
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (len == SZ_16M || len == SZ_1M) {
-		pgprot = sh ? FL_SHARED : 0;
-		pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0;
-		pgprot |= tex & 0x02 ? FL_CACHEABLE : 0;
-		pgprot |= tex & 0x04 ? FL_TEX0 : 0;
-	} else	{
-		pgprot = sh ? SL_SHARED : 0;
-		pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0;
-		pgprot |= tex & 0x02 ? SL_CACHEABLE : 0;
-		pgprot |= tex & 0x04 ? SL_TEX0 : 0;
-	}
-
-	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
-	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
-
-	if (len == SZ_16M) {
-		int i = 0;
-		for (i = 0; i < 16; i++)
-			*(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
-				  FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
-				  FL_SHARED | FL_NG | pgprot;
-	}
-
-	if (len == SZ_1M)
-		*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE | FL_NG |
-					    FL_TYPE_SECT | FL_SHARED | pgprot;
-
-	/* Need a 2nd level table */
-	if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) {
-		unsigned long *sl;
-		sl = (unsigned long *) __get_free_pages(GFP_ATOMIC,
-							get_order(SZ_4K));
-
-		if (!sl) {
-			pr_debug("Could not allocate second level table\n");
-			ret = -ENOMEM;
-			goto fail;
-		}
-
-		memset(sl, 0, SZ_4K);
-		*fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | FL_TYPE_TABLE);
-	}
-
-	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
-	sl_offset = SL_OFFSET(va);
-	sl_pte = sl_table + sl_offset;
-
-
-	if (len == SZ_4K)
-		*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | SL_NG |
-					  SL_SHARED | SL_TYPE_SMALL | pgprot;
-
-	if (len == SZ_64K) {
-		int i;
+	int ret;
 
-		for (i = 0; i < 16; i++)
-			*(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
-			    SL_NG | SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
-	}
+	spin_lock_irqsave(&priv->pgtlock, flags);
+	ret = priv->iop->map(priv->iop, iova, pa, len, prot);
+	spin_unlock_irqrestore(&priv->pgtlock, flags);
 
-	ret = __flush_iotlb(domain);
-fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
 }
 
-static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
-			    size_t len)
+static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
+			      size_t len)
 {
-	struct msm_priv *priv;
+	struct msm_priv *priv = to_msm_priv(domain);
 	unsigned long flags;
-	unsigned long *fl_table;
-	unsigned long *fl_pte;
-	unsigned long fl_offset;
-	unsigned long *sl_table;
-	unsigned long *sl_pte;
-	unsigned long sl_offset;
-	int i, ret = 0;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	priv = to_msm_priv(domain);
 
-	fl_table = priv->pgtable;
+	spin_lock_irqsave(&priv->pgtlock, flags);
+	len = priv->iop->unmap(priv->iop, iova, len);
+	spin_unlock_irqrestore(&priv->pgtlock, flags);
 
-	if (len != SZ_16M && len != SZ_1M &&
-	    len != SZ_64K && len != SZ_4K) {
-		pr_debug("Bad length: %d\n", len);
-		goto fail;
-	}
-
-	if (!fl_table) {
-		pr_debug("Null page table\n");
-		goto fail;
-	}
-
-	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
-	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
-
-	if (*fl_pte == 0) {
-		pr_debug("First level PTE is 0\n");
-		goto fail;
-	}
-
-	/* Unmap supersection */
-	if (len == SZ_16M)
-		for (i = 0; i < 16; i++)
-			*(fl_pte+i) = 0;
-
-	if (len == SZ_1M)
-		*fl_pte = 0;
-
-	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
-	sl_offset = SL_OFFSET(va);
-	sl_pte = sl_table + sl_offset;
-
-	if (len == SZ_64K) {
-		for (i = 0; i < 16; i++)
-			*(sl_pte+i) = 0;
-	}
-
-	if (len == SZ_4K)
-		*sl_pte = 0;
-
-	if (len == SZ_4K || len == SZ_64K) {
-		int used = 0;
-
-		for (i = 0; i < NUM_SL_PTE; i++)
-			if (sl_table[i])
-				used = 1;
-		if (!used) {
-			free_page((unsigned long)sl_table);
-			*fl_pte = 0;
-		}
-	}
-
-	ret = __flush_iotlb(domain);
-
-fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
-
-	/* the IOMMU API requires us to return how many bytes were unmapped */
-	len = ret ? 0 : len;
 	return len;
 }
 
@@ -699,8 +546,6 @@ static void print_ctx_regs(void __iomem *base, int ctx)
 	       GET_TTBR0(base, ctx), GET_TTBR1(base, ctx));
 	pr_err("SCTLR  = %08x    ACTLR  = %08x\n",
 	       GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
-	pr_err("PRRR   = %08x    NMRR   = %08x\n",
-	       GET_PRRR(base, ctx), GET_NMRR(base, ctx));
 }
 
 static void insert_iommu_master(struct device *dev,
@@ -941,47 +786,8 @@ static void __exit msm_iommu_driver_exit(void)
 subsys_initcall(msm_iommu_driver_init);
 module_exit(msm_iommu_driver_exit);
 
-static int __init get_tex_class(int icp, int ocp, int mt, int nos)
-{
-	int i = 0;
-	unsigned int prrr = 0;
-	unsigned int nmrr = 0;
-	int c_icp, c_ocp, c_mt, c_nos;
-
-	RCP15_PRRR(prrr);
-	RCP15_NMRR(nmrr);
-
-	for (i = 0; i < NUM_TEX_CLASS; i++) {
-		c_nos = PRRR_NOS(prrr, i);
-		c_mt = PRRR_MT(prrr, i);
-		c_icp = NMRR_ICP(nmrr, i);
-		c_ocp = NMRR_OCP(nmrr, i);
-
-		if (icp == c_icp && ocp == c_ocp && c_mt == mt && c_nos == nos)
-			return i;
-	}
-
-	return -ENODEV;
-}
-
-static void __init setup_iommu_tex_classes(void)
-{
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_NONCACHED] =
-			get_tex_class(CP_NONCACHED, CP_NONCACHED, MT_NORMAL, 1);
-
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_WA] =
-			get_tex_class(CP_WB_WA, CP_WB_WA, MT_NORMAL, 1);
-
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_NWA] =
-			get_tex_class(CP_WB_NWA, CP_WB_NWA, MT_NORMAL, 1);
-
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WT] =
-			get_tex_class(CP_WT, CP_WT, MT_NORMAL, 1);
-}
-
 static int __init msm_iommu_init(void)
 {
-	setup_iommu_tex_classes();
 	bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
 	return 0;
 }
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May 15 23:49:01 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon, 16 May 2016 12:19:01 +0530
Subject: [PATCH V4 7/7] iommu/msm: Remove driver BROKEN
In-Reply-To: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463381341-30498-8-git-send-email-sricharan@codeaurora.org>

Now that the driver is DT adapted, bus_set_iommu gets called only
when on compatible matching. So the driver should not break multiplatform
builds now. So remove the BROKEN config.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 1f5d496..b81a0bb 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -90,7 +90,6 @@ config MSM_IOMMU
 	bool "MSM IOMMU Support"
 	depends on ARM
 	depends on ARCH_MSM8X60 || ARCH_MSM8960 || COMPILE_TEST
-	depends on BROKEN
 	select IOMMU_API
 	select IOMMU_IO_PGTABLE_ARMV7S
 	help
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Sun May 15 23:49:00 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Mon, 16 May 2016 12:19:00 +0530
Subject: [PATCH V4 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463381341-30498-7-git-send-email-sricharan@codeaurora.org>

While using the generic pagetable ops the tlb maintenance
operation gets completed in the sync callback. So use writel_relaxed
for all register access and add a mb() at appropriate places.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/msm_iommu.c         | 11 ++++++++---
 drivers/iommu/msm_iommu_hw-8xxx.h |  7 ++++---
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index f7b4c11..1240a5a 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -124,6 +124,7 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
 		SET_TLBLKCR(base, ctx, 0);
 		SET_CONTEXTIDR(base, ctx, 0);
 	}
+	mb(); /* sync */
 }
 
 static void __flush_iotlb(void *cookie)
@@ -143,6 +144,7 @@ static void __flush_iotlb(void *cookie)
 
 		__disable_clocks(iommu);
 	}
+	mb(); /* sync */
 fail:
 	return;
 }
@@ -181,7 +183,7 @@ fail:
 
 static void __flush_iotlb_sync(void *cookie)
 {
-	/* To avoid a null function pointer */
+	mb(); /* sync */
 }
 
 static const struct iommu_gather_ops msm_iommu_gather_ops = {
@@ -235,6 +237,7 @@ static void config_mids(struct msm_iommu_dev *iommu,
 		/* Set security bit override to be Non-secure */
 		SET_NSCFG(iommu->base, mid, 3);
 	}
+	mb(); /* sync */
 }
 
 static void __reset_context(void __iomem *base, int ctx)
@@ -257,6 +260,7 @@ static void __reset_context(void __iomem *base, int ctx)
 	SET_TLBFLPTER(base, ctx, 0);
 	SET_TLBSLPTER(base, ctx, 0);
 	SET_TLBLKCR(base, ctx, 0);
+	mb(); /* sync */
 }
 
 static void __program_context(void __iomem *base, int ctx,
@@ -305,6 +309,7 @@ static void __program_context(void __iomem *base, int ctx,
 
 	/* Enable the MMU */
 	SET_M(base, ctx, 1);
+	mb(); /* sync */
 }
 
 static struct iommu_domain *msm_iommu_domain_alloc(unsigned type)
@@ -500,7 +505,7 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
 	/* Invalidate context TLB */
 	SET_CTX_TLBIALL(iommu->base, master->num, 0);
 	SET_V2PPR(iommu->base, master->num, va & V2Pxx_VA);
-
+	mb(); /* sync */
 	par = GET_PAR(iommu->base, master->num);
 
 	/* We are dealing with a supersection */
@@ -714,7 +719,7 @@ static int msm_iommu_probe(struct platform_device *pdev)
 	par = GET_PAR(iommu->base, 0);
 	SET_V2PCFG(iommu->base, 0, 0);
 	SET_M(iommu->base, 0, 0);
-
+	mb(); /* sync */
 	if (!par) {
 		pr_err("Invalid PAR value detected\n");
 		ret = -ENODEV;
diff --git a/drivers/iommu/msm_iommu_hw-8xxx.h b/drivers/iommu/msm_iommu_hw-8xxx.h
index 84ba5739..161036c 100644
--- a/drivers/iommu/msm_iommu_hw-8xxx.h
+++ b/drivers/iommu/msm_iommu_hw-8xxx.h
@@ -24,10 +24,10 @@
 #define GET_CTX_REG(reg, base, ctx) \
 				(readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
 
-#define SET_GLOBAL_REG(reg, base, val)	writel((val), ((base) + (reg)))
+#define SET_GLOBAL_REG(reg, base, val)	writel_relaxed((val), ((base) + (reg)))
 
 #define SET_CTX_REG(reg, base, ctx, val) \
-			writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
+		writel_relaxed((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
 
 /* Wrappers for numbered registers */
 #define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG(b, ((r) + (n << 2)), (v))
@@ -48,7 +48,8 @@
 #define SET_FIELD(addr, mask, shift, v) \
 do { \
 	int t = readl(addr); \
-	writel((t & ~((mask) << (shift))) + (((v) & (mask)) << (shift)), addr);\
+	writel_relaxed((t & ~((mask) << (shift))) + \
+		       (((v) & (mask)) << (shift)), addr);\
 } while (0)
 
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From maxime.ripard at free-electrons.com  Sun May 15 11:51:12 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun, 15 May 2016 20:51:12 +0200
Subject: [PATCH 08/16] clk: sunxi-ng: Add M-factor clock support
In-Reply-To: <20160511084633.29b56effa514996ffafd56ef@free.fr>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-9-git-send-email-maxime.ripard@free-electrons.com>
 <20160511084633.29b56effa514996ffafd56ef@free.fr>
Message-ID: <20160515185112.GB27618@lukather>

On Wed, May 11, 2016 at 08:46:33AM +0200, Jean-Francois Moine wrote:
> On Sun,  8 May 2016 22:01:43 +0200
> Maxime Ripard <maxime.ripard at free-electrons.com> wrote:
> 
> > Introduce support for clocks that divide by a linear factor.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/clk/sunxi-ng/Makefile |   1 +
> >  drivers/clk/sunxi-ng/ccu_m.c  | 135 ++++++++++++++++++++++++++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu_m.h  | 101 +++++++++++++++++++++++++++++++
> >  3 files changed, 237 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_m.c
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_m.h
> > 
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> > index a47a3bbdf285..f41de901c607 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -4,5 +4,6 @@ obj-y += ccu_reset.o
> >  obj-y += ccu_div_table.o
> >  obj-y += ccu_fixed_factor.o
> >  obj-y += ccu_gate.o
> > +obj-y += ccu_m.o
> >  obj-y += ccu_mux.o
> >  obj-y += ccu_phase.o
> > diff --git a/drivers/clk/sunxi-ng/ccu_m.c b/drivers/clk/sunxi-ng/ccu_m.c
> > new file mode 100644
> > index 000000000000..424eb6da0d5b
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_m.c
> > @@ -0,0 +1,135 @@
> > +/*
> > + * Copyright (C) 2016 Maxime Ripard
> > + * Maxime Ripard <maxime.ripard at free-electrons.com>
> > + *
> > + * 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.
> > + */
> 	[snip]
> > +static int ccu_m_set_rate(struct clk_hw *hw, unsigned long rate,
> > +			  unsigned long parent_rate)
> > +{
> > +	struct ccu_m *cm = hw_to_ccu_m(hw);
> > +	unsigned long flags;
> > +	unsigned int m;
> > +	u32 reg;
> > +
> > +	ccu_m_find_best(parent_rate, rate, 1 << cm->m.width, &m);
> > +
> > +	spin_lock_irqsave(cm->common.lock, flags);
> > +
> > +	reg = readl(cm->common.base + cm->common.reg);
> > +	reg &= ((1 << cm->m.width) - 1) << cm->m.shift;
> 
> Bug:
> 	reg &= ~GENMASK(cm->m.width + cm->m.shift, cm->m.shift);

Indeed, this one slipped in, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160515/4a3c02f5/attachment.sig>

From maxime.ripard at free-electrons.com  Sun May 15 12:08:18 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun, 15 May 2016 21:08:18 +0200
Subject: [PATCH 13/16] clk: sunxi-ng: Add N-K-M Factor clock
In-Reply-To: <20160511104556.037a2c17e3a6a0503a26fbf0@free.fr>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-14-git-send-email-maxime.ripard@free-electrons.com>
 <20160511104556.037a2c17e3a6a0503a26fbf0@free.fr>
Message-ID: <20160515190818.GD27618@lukather>

On Wed, May 11, 2016 at 10:45:56AM +0200, Jean-Francois Moine wrote:
> On Sun,  8 May 2016 22:01:48 +0200
> Maxime Ripard <maxime.ripard at free-electrons.com> wrote:
> 
> > Introduce support for clocks that multiply and divide using two linear
> > multipliers and one linear divider.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/clk/sunxi-ng/Makefile  |   1 +
> >  drivers/clk/sunxi-ng/ccu_nkm.c | 144 +++++++++++++++++++++++++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu_nkm.h |  42 ++++++++++++
> >  3 files changed, 187 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_nkm.c
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_nkm.h
> > 
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> > index fba64c7f4fcd..2bb8bc22e907 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -8,6 +8,7 @@ obj-y += ccu_m.o
> >  obj-y += ccu_mp.o
> >  obj-y += ccu_mux.o
> >  obj-y += ccu_nk.o
> > +obj-y += ccu_nkm.o
> >  obj-y += ccu_nm.o
> >  obj-y += ccu_p.o
> >  obj-y += ccu_phase.o
> > diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
> > new file mode 100644
> > index 000000000000..9019c7f6988c
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_nkm.c
> 	[snip]
> > @@ -0,0 +1,144 @@
> > +/*
> > + * Copyright (C) 2016 Maxime Ripard
> > + * Maxime Ripard <maxime.ripard at free-electrons.com>
> > + *
> > + * 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.
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/rational.h>
> > +
> > +#include "ccu_gate.h"
> > +#include "ccu_nkm.h"
> > +
> > +void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
> > +		       unsigned long max_n, unsigned long max_k, unsigned long max_m,
> > +		       unsigned long *n, unsigned long *k, unsigned long *m)
> 
> Should be static
> 
> 	[snip]
> 
> > +static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
> > +			   unsigned long parent_rate)
> > +{
> > +	struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
> > +	unsigned long n, k, m;
> > +	unsigned long flags;
> > +	u32 reg;
> > +
> > +	ccu_nkm_find_best(parent_rate, rate, 1 << nkm->n.width,
> > +			  1 << nkm->k.width, 1 << nkm->m.width,
> > +			  &n, &k, &m);
> > +
> > +	spin_lock_irqsave(nkm->common.lock, flags);
> > +
> > +	reg = readl(nkm->common.base + nkm->common.reg);
> > +	reg &= ~GENMASK(nkm->n.width + nkm->n.shift, nkm->n.shift);
> > +	reg &= ~GENMASK(nkm->k.width + nkm->k.shift, nkm->k.shift);
> > +	reg &= ~GENMASK(nkm->m.width + nkm->m.shift, nkm->m.shift);
> > +
> > +	reg |= (n - 1) << nkm->m.shift;
> > +	reg |= (k - 1) << nkm->m.shift;
> > +	reg |= (m - 1) << nkm->m.shift;
> 
> 	reg |= (n - 1) << nkm->n.shift;
> 	reg |= (k - 1) << nkm->k.shift;

Good catches, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160515/2cefa15f/attachment.sig>

From maxime.ripard at free-electrons.com  Sun May 15 12:18:32 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun, 15 May 2016 21:18:32 +0200
Subject: [PATCH 15/16] clk: sunxi-ng: Add H3 clocks
In-Reply-To: <20160509093958.26e9549f8ce78888c0e9586a@free.fr>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
 <20160509093958.26e9549f8ce78888c0e9586a@free.fr>
Message-ID: <20160515191832.GE27618@lukather>

On Mon, May 09, 2016 at 09:39:58AM +0200, Jean-Francois Moine wrote:
> On Sun,  8 May 2016 22:01:50 +0200
> Maxime Ripard <maxime.ripard at free-electrons.com> wrote:
> 
> > Add the list of clocks and resets found in the H3 CCU.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/clk/sunxi-ng/Makefile        |   2 +
> >  drivers/clk/sunxi-ng/ccu-sun8i-h3.c  | 757 +++++++++++++++++++++++++++++++++++
> >  include/dt-bindings/clock/sun8i-h3.h | 162 ++++++++
> >  include/dt-bindings/reset/sun8i-h3.h | 103 +++++
> >  4 files changed, 1024 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> >  create mode 100644 include/dt-bindings/clock/sun8i-h3.h
> >  create mode 100644 include/dt-bindings/reset/sun8i-h3.h
> > 
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> > index c794f57b6fb1..67ff6a92f124 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -13,3 +13,5 @@ obj-y += ccu_nkmp.o
> >  obj-y += ccu_nm.o
> >  obj-y += ccu_p.o
> >  obj-y += ccu_phase.o
> > +
> > +obj-y += ccu-sun8i-h3.o
> 
> +obj-$(CONFIG_MACH_SUN8I) += ccu-sun8i-h3.o
> 
> should be better.

Indeed, changed.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160515/bfedb768/attachment-0001.sig>

From maxime.ripard at free-electrons.com  Sun May 15 12:04:15 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun, 15 May 2016 21:04:15 +0200
Subject: [PATCH 12/16] clk: sunxi-ng: Add N-M-factor clock support
In-Reply-To: <20160509092421.a36252139fd6b00b2cd32f24@free.fr>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-13-git-send-email-maxime.ripard@free-electrons.com>
 <20160509092421.a36252139fd6b00b2cd32f24@free.fr>
Message-ID: <20160515190415.GC27618@lukather>

Hi,

On Mon, May 09, 2016 at 09:24:21AM +0200, Jean-Francois Moine wrote:
> On Sun,  8 May 2016 22:01:47 +0200
> Maxime Ripard <maxime.ripard at free-electrons.com> wrote:
> 
> > Introduce support for clocks that multiply and divide using linear factors.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/clk/sunxi-ng/Makefile |   1 +
> >  drivers/clk/sunxi-ng/ccu_nm.c | 103 ++++++++++++++++++++++++++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu_nm.h |  41 +++++++++++++++++
> >  3 files changed, 145 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_nm.c
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_nm.h
> 	[snip]
> > diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
> > new file mode 100644
> > index 000000000000..268637db137b
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_nm.c
> > @@ -0,0 +1,103 @@
> 	[snip]
> > +static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
> > +			      unsigned long *parent_rate)
> > +{
> > +	struct ccu_nm *nm = hw_to_ccu_nm(hw);
> > +	unsigned long n, m;
> > +
> > +	rational_best_approximation(rate, *parent_rate,
> > +				    nm->n.width, nm->m.width, &n, &m);
> 
> Should be
> 			1 << nm->n.width, 1 << nm->m.width, &n, &m);
> 
> > +
> > +	return *parent_rate * n / m;
> > +}
> > +
> > +static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
> > +			   unsigned long parent_rate)
> > +{
> > +	struct ccu_nm *nm = hw_to_ccu_nm(hw);
> > +	unsigned long flags;
> > +	unsigned long n, m;
> > +	u32 reg;
> > +
> > +	rational_best_approximation(rate, parent_rate,
> > +				    nm->n.width, nm->m.width, &n, &m);
> 
> Idem

Indeed, fixed.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160515/3b0e96e4/attachment.sig>

From maxime.ripard at free-electrons.com  Sun May 15 11:31:22 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun, 15 May 2016 20:31:22 +0200
Subject: [PATCH 02/16] clk: sunxi-ng: Add common infrastructure
In-Reply-To: <CAGb2v67XWt6tjG_xXWgGatTaiN5uYQb2_Q6bgixMDUkHfVHLHg@mail.gmail.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-3-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v67XWt6tjG_xXWgGatTaiN5uYQb2_Q6bgixMDUkHfVHLHg@mail.gmail.com>
Message-ID: <20160515183122.GA27618@lukather>

Hi,

On Mon, May 09, 2016 at 06:01:45PM +0800, Chen-Yu Tsai wrote:
> On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
> <maxime.ripard at free-electrons.com> wrote:
> > Start our new clock infrastructure by adding the registration code, common
> > structure and common code.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/clk/Makefile              |   1 +
> >  drivers/clk/sunxi-ng/Makefile     |   2 +
> >  drivers/clk/sunxi-ng/ccu_common.c | 108 ++++++++++++++++++++++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu_common.h |  74 ++++++++++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu_factor.h |  15 ++++++
> >  drivers/clk/sunxi-ng/ccu_mux.h    |  20 +++++++
> >  drivers/clk/sunxi-ng/ccu_reset.c  |  55 +++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu_reset.h  |  40 ++++++++++++++
> >  8 files changed, 315 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/Makefile
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_common.c
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_common.h
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_factor.h
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_mux.h
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_reset.c
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_reset.h
> >
> > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> > index 4ef71a13ab37..83a93cd9e21d 100644
> > --- a/drivers/clk/Makefile
> > +++ b/drivers/clk/Makefile
> > @@ -78,6 +78,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)            += socfpga/
> >  obj-$(CONFIG_PLAT_SPEAR)               += spear/
> >  obj-$(CONFIG_ARCH_STI)                 += st/
> >  obj-$(CONFIG_ARCH_SUNXI)               += sunxi/
> > +obj-$(CONFIG_ARCH_SUNXI)               += sunxi-ng/
> >  obj-$(CONFIG_ARCH_TEGRA)               += tegra/
> >  obj-y                                  += ti/
> >  obj-$(CONFIG_ARCH_U8500)               += ux500/
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> > new file mode 100644
> > index 000000000000..bd3461b0f38c
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -0,0 +1,2 @@
> > +obj-y += ccu_common.o
> > +obj-y += ccu_reset.o
> > diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c
> > new file mode 100644
> > index 000000000000..1d9242566fbd
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_common.c
> > @@ -0,0 +1,108 @@
> > +/*
> > + * Copyright 2016 Maxime Ripard
> > + *
> > + * Maxime Ripard <maxime.ripard at free-electrons.com>
> > + *
> > + * 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/iopoll.h>
> > +#include <linux/of_address.h>
> > +#include <linux/slab.h>
> > +
> > +#include "ccu_common.h"
> > +#include "ccu_reset.h"
> > +
> > +static DEFINE_SPINLOCK(ccu_lock);
> > +
> > +void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
> > +{
> > +       u32 reg;
> > +
> > +       if (!(common->features & CCU_FEATURE_LOCK))
> > +               return;
> > +
> > +       WARN_ON(readl_relaxed_poll_timeout(common->base + common->reg, reg,
> > +                                          !(reg & lock), 0, 500));
> 
>                                     no delay between reads? ^

Yes, I intended it to be a simple busy waiting loop since I don't
expect it to be very long. Do yu have any more data on how much time
it usually takes?

> 
> > +int sunxi_ccu_probe(struct device_node *node,
> > +                   const struct sunxi_ccu_desc *desc)
> > +{
> > +       struct ccu_common **cclks = desc->clks;
> > +       size_t num_clks = desc->num_clks;
> > +       struct clk_onecell_data *data;
> > +       struct ccu_reset *reset;
> > +       struct clk **clks;
> > +       void __iomem *reg;
> > +       int i, ret;
> > +
> > +       reg = of_iomap(node, 0);
> 
> Why not of_io_request_and_map?

Because initially I still had some old clocks that were probing, which
was leading to some issues. This is obviously not the case anymore,
I'll switch to it.

> 
> > +       if (IS_ERR(reg)) {
> 
> And of_iomap returns NULL on error. This is for of_io_request_and_map.
> 
> > +               pr_err("%s: Could not map the clock registers\n",
> > +                      of_node_full_name(node));
> > +               return PTR_ERR(reg);
> > +       }
> > +
> > +       data = kzalloc(sizeof(*data), GFP_KERNEL);
> > +       if (!data)
> > +               return -ENOMEM;
> > +
> > +       clks = kcalloc(num_clks, sizeof(struct clk *), GFP_KERNEL);
> > +       if (!clks)
> > +               return -ENOMEM;
> > +
> > +       data->clks = clks;
> > +       data->clk_num = num_clks;
> > +
> > +       for (i = 0; i < num_clks; i++) {
> > +               struct ccu_common *cclk = cclks[i];
> > +               struct clk *clk;
> > +
> > +               if (!cclk) {
> > +                       cclk = ERR_PTR(-ENOENT);
> 
> This seems redundant, unless you intended to use it elsewhere?

Yeah, that was supposed to be clks[i] = ERR_PTR(..);

I'll fix it.

> 
> > +                       continue;
> > +               }
> > +
> > +               cclk->base = reg;
> > +               cclk->lock = &ccu_lock;
> > +
> > +               clk = clk_register(NULL, &cclk->hw);
> > +               if (IS_ERR(clk))
> > +                       continue;
> > +
> > +               clks[i] = clk;
> > +       }
> > +
> > +       ret = of_clk_add_provider(node, of_clk_src_onecell_get, data);
> > +       if (ret)
> > +               goto err_clk_unreg;
> > +
> > +       reset = kzalloc(sizeof(*reset), GFP_KERNEL);
> > +       reset->rcdev.of_node = node;
> > +       reset->rcdev.ops = &ccu_reset_ops;
> > +       reset->rcdev.owner = THIS_MODULE;
> > +       reset->rcdev.nr_resets = desc->num_resets;
> > +       reset->base = reg;
> > +       reset->lock = &ccu_lock;
> > +       reset->reset_map = desc->resets;
> > +
> > +       ret = reset_controller_register(&reset->rcdev);
> > +       if (ret)
> > +               goto err_of_clk_unreg;
> > +
> > +       return 0;
> > +
> > +err_of_clk_unreg:
> > +err_clk_unreg:
> > +       return ret;
> > +}
> > diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
> > new file mode 100644
> > index 000000000000..e8b477fcd320
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_common.h
> > @@ -0,0 +1,74 @@
> > +/*
> > + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef _COMMON_H_
> > +#define _COMMON_H_
> > +
> > +#include <linux/compiler.h>
> > +#include <linux/clk-provider.h>
> > +
> > +#define CCU_FEATURE_GATE               BIT(0)
> > +#define CCU_FEATURE_LOCK               BIT(1)
> 
> *_PLL_LOCK would be clearer that this implements a PLL lock indicator.
> Or maybe a comment.

I'll change it for PLL_LOCK

> 
> > +#define CCU_FEATURE_FRACTIONAL         BIT(2)
> > +#define CCU_FEATURE_VARIABLE_PREDIV    BIT(3)
> > +#define CCU_FEATURE_FIXED_PREDIV       BIT(4)
> > +#define CCU_FEATURE_FIXED_POSTDIV      BIT(5)
> > +
> > +struct device_node;
> > +
> > +#define SUNXI_HW_INIT(_name, _parent, _ops, _flags)                    \
> > +       &(struct clk_init_data) {                                       \
> > +               .flags          = _flags,                               \
> > +               .name           = _name,                                \
> > +               .parent_names   = (const char *[]) { _parent },         \
> > +               .num_parents    = 1,                                    \
> > +               .ops            = _ops,                                 \
> > +       }
> > +
> > +#define SUNXI_HW_INIT_PARENTS(_name, _parents, _ops, _flags)           \
> > +       &(struct clk_init_data) {                                       \
> > +               .flags          = _flags,                               \
> > +               .name           = _name,                                \
> > +               .parent_names   = _parents,                             \
> > +               .num_parents    = ARRAY_SIZE(_parents),                 \
> > +               .ops            = _ops,                                 \
> > +       }
> > +
> > +struct ccu_common {
> > +       void __iomem    *base;
> > +       unsigned long   reg;
> 
> This seems quite large, considering the address space of the CCU,
> and you using u16 or u32 for the same thing on the reset control side.

Indeed, what about u16?

> 
> > +
> > +       unsigned long   features;
> > +       spinlock_t      *lock;
> > +       struct clk_hw   hw;
> > +};
> > +
> > +static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)
> > +{
> > +       return container_of(hw, struct ccu_common, hw);
> > +}
> > +
> > +struct sunxi_ccu_desc {
> > +       struct ccu_common       **clks;
> > +       unsigned long           num_clks;
> > +
> > +       struct ccu_reset_map    *resets;
> > +       unsigned long           num_resets;
> > +};
> > +
> > +void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock);
> > +
> > +int sunxi_ccu_probe(struct device_node *node,
> > +                   const struct sunxi_ccu_desc *desc);
> > +
> > +#endif /* _COMMON_H_ */
> > diff --git a/drivers/clk/sunxi-ng/ccu_factor.h b/drivers/clk/sunxi-ng/ccu_factor.h
> > new file mode 100644
> > index 000000000000..e7cc564aaea0
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_factor.h
> > @@ -0,0 +1,15 @@
> > +#ifndef _CLK_FACTOR_H_
> > +#define _CLK_FACTOR_H_
> > +
> > +struct ccu_factor {
> > +       u8      shift;
> > +       u8      width;
> > +};
> > +
> > +#define SUNXI_CLK_FACTOR(_shift, _width)       \
> > +       {                                       \
> > +               .shift  = _shift,               \
> > +               .width  = _width,               \
> > +       }
> > +
> > +#endif /* _CLK_FACTOR_H_ */
> > diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
> > new file mode 100644
> > index 000000000000..17cedad4e433
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_mux.h
> 
> As far as I can tell there are no users of this file within this patch or the
> following patches before the mux clock support one. It'd be easier to understand
> if this part was moved to the mux clock patch.

Will do.

> 
> > @@ -0,0 +1,20 @@
> > +#ifndef _CCU_MUX_H_
> > +#define _CCU_MUX_H_
> > +
> > +#include "common.h"
> > +
> > +struct ccu_mux_internal {
> > +       u8      shift;
> > +       u8      width;
> > +
> > +       u8      *map;
> 
> I assume map is a table?
> 
> > +};
> > +
> > +#define SUNXI_CLK_MUX(_shift, _width, _map)    \
> > +       {                                       \
> > +               .map    = _map,                 \
> > +               .shift  = _shift,               \
> > +               .width  = _width,               \
> > +       }
> > +
> > +#endif /* _CCU_MUX_H_ */
> > diff --git a/drivers/clk/sunxi-ng/ccu_reset.c b/drivers/clk/sunxi-ng/ccu_reset.c
> > new file mode 100644
> > index 000000000000..6c31d48783a7
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_reset.c
> > @@ -0,0 +1,55 @@
> > +/*
> > + * Copyright (C) 2016 Maxime Ripard
> > + * Maxime Ripard <maxime.ripard at free-electrons.com>
> > + *
> > + * 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.
> > + */
> > +
> > +#include <linux/io.h>
> > +#include <linux/reset-controller.h>
> > +
> > +#include "ccu_reset.h"
> > +
> > +static int ccu_reset_assert(struct reset_controller_dev *rcdev,
> > +                           unsigned long id)
> > +{
> > +       struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
> > +       const struct ccu_reset_map *map = &ccu->reset_map[id];
> > +       unsigned long flags;
> > +       u32 reg;
> > +
> > +       spin_lock_irqsave(ccu->lock, flags);
> > +
> > +       reg = readl(ccu->base + map->reg);
> > +       writel(reg & ~map->bit, ccu->base + map->reg);
> > +
> > +       spin_unlock_irqrestore(ccu->lock, flags);
> > +
> > +       return 0;
> > +}
> > +
> > +static int ccu_reset_deassert(struct reset_controller_dev *rcdev,
> > +                             unsigned long id)
> > +{
> > +       struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
> > +       const struct ccu_reset_map *map = &ccu->reset_map[id];
> > +       unsigned long flags;
> > +       u32 reg;
> > +
> > +       spin_lock_irqsave(ccu->lock, flags);
> > +
> > +       reg = readl(ccu->base + map->reg);
> > +       writel(reg | map->bit, ccu->base + map->reg);
> > +
> > +       spin_unlock_irqrestore(ccu->lock, flags);
> > +
> > +       return 0;
> > +}
> > +
> > +const struct reset_control_ops ccu_reset_ops = {
> > +       .assert         = ccu_reset_assert,
> > +       .deassert       = ccu_reset_deassert,
> > +};
> > diff --git a/drivers/clk/sunxi-ng/ccu_reset.h b/drivers/clk/sunxi-ng/ccu_reset.h
> > new file mode 100644
> > index 000000000000..36a4679210bd
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_reset.h
> > @@ -0,0 +1,40 @@
> > +/*
> > + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef _CCU_RESET_H_
> > +#define _CCU_RESET_H_
> > +
> > +#include <linux/reset-controller.h>
> > +
> > +struct ccu_reset_map {
> > +       u16     reg;
> > +       u32     bit;
> > +};
> > +
> > +
> > +struct ccu_reset {
> > +       void __iomem                    *base;
> > +       struct ccu_reset_map            *reset_map;
> > +       spinlock_t                      *lock;
> > +
> > +       struct reset_controller_dev     rcdev;
> > +};
> > +
> > +static inline struct ccu_reset *rcdev_to_ccu_reset(struct reset_controller_dev *rcdev)
> > +{
> > +       return container_of(rcdev, struct ccu_reset, rcdev);
> > +}
> > +
> > +extern const struct reset_control_ops ccu_reset_ops;
> > +
> > +#endif /* _CCU_RESET_H_ */
> 
> The reset control code looks good.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160515/f96ad50b/attachment.sig>

From wens at csie.org  Mon May 16 00:02:13 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 16 May 2016 15:02:13 +0800
Subject: [PATCH 02/16] clk: sunxi-ng: Add common infrastructure
In-Reply-To: <20160515183122.GA27618@lukather>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-3-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v67XWt6tjG_xXWgGatTaiN5uYQb2_Q6bgixMDUkHfVHLHg@mail.gmail.com>
 <20160515183122.GA27618@lukather>
Message-ID: <CAGb2v64kgPOw3_fQDpZyBxW34s3QF6M4sfbgpMTduojb9FPhFQ@mail.gmail.com>

On Mon, May 16, 2016 at 2:31 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Hi,
>
> On Mon, May 09, 2016 at 06:01:45PM +0800, Chen-Yu Tsai wrote:
>> On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
>> <maxime.ripard at free-electrons.com> wrote:
>> > Start our new clock infrastructure by adding the registration code, common
>> > structure and common code.
>> >
>> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
>> > ---
>> >  drivers/clk/Makefile              |   1 +
>> >  drivers/clk/sunxi-ng/Makefile     |   2 +
>> >  drivers/clk/sunxi-ng/ccu_common.c | 108 ++++++++++++++++++++++++++++++++++++++
>> >  drivers/clk/sunxi-ng/ccu_common.h |  74 ++++++++++++++++++++++++++
>> >  drivers/clk/sunxi-ng/ccu_factor.h |  15 ++++++
>> >  drivers/clk/sunxi-ng/ccu_mux.h    |  20 +++++++
>> >  drivers/clk/sunxi-ng/ccu_reset.c  |  55 +++++++++++++++++++
>> >  drivers/clk/sunxi-ng/ccu_reset.h  |  40 ++++++++++++++
>> >  8 files changed, 315 insertions(+)
>> >  create mode 100644 drivers/clk/sunxi-ng/Makefile
>> >  create mode 100644 drivers/clk/sunxi-ng/ccu_common.c
>> >  create mode 100644 drivers/clk/sunxi-ng/ccu_common.h
>> >  create mode 100644 drivers/clk/sunxi-ng/ccu_factor.h
>> >  create mode 100644 drivers/clk/sunxi-ng/ccu_mux.h
>> >  create mode 100644 drivers/clk/sunxi-ng/ccu_reset.c
>> >  create mode 100644 drivers/clk/sunxi-ng/ccu_reset.h
>> >
>> > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> > index 4ef71a13ab37..83a93cd9e21d 100644
>> > --- a/drivers/clk/Makefile
>> > +++ b/drivers/clk/Makefile
>> > @@ -78,6 +78,7 @@ obj-$(CONFIG_ARCH_SOCFPGA)            += socfpga/
>> >  obj-$(CONFIG_PLAT_SPEAR)               += spear/
>> >  obj-$(CONFIG_ARCH_STI)                 += st/
>> >  obj-$(CONFIG_ARCH_SUNXI)               += sunxi/
>> > +obj-$(CONFIG_ARCH_SUNXI)               += sunxi-ng/
>> >  obj-$(CONFIG_ARCH_TEGRA)               += tegra/
>> >  obj-y                                  += ti/
>> >  obj-$(CONFIG_ARCH_U8500)               += ux500/
>> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
>> > new file mode 100644
>> > index 000000000000..bd3461b0f38c
>> > --- /dev/null
>> > +++ b/drivers/clk/sunxi-ng/Makefile
>> > @@ -0,0 +1,2 @@
>> > +obj-y += ccu_common.o
>> > +obj-y += ccu_reset.o
>> > diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c
>> > new file mode 100644
>> > index 000000000000..1d9242566fbd
>> > --- /dev/null
>> > +++ b/drivers/clk/sunxi-ng/ccu_common.c
>> > @@ -0,0 +1,108 @@
>> > +/*
>> > + * Copyright 2016 Maxime Ripard
>> > + *
>> > + * Maxime Ripard <maxime.ripard at free-electrons.com>
>> > + *
>> > + * 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/iopoll.h>
>> > +#include <linux/of_address.h>
>> > +#include <linux/slab.h>
>> > +
>> > +#include "ccu_common.h"
>> > +#include "ccu_reset.h"
>> > +
>> > +static DEFINE_SPINLOCK(ccu_lock);
>> > +
>> > +void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
>> > +{
>> > +       u32 reg;
>> > +
>> > +       if (!(common->features & CCU_FEATURE_LOCK))
>> > +               return;
>> > +
>> > +       WARN_ON(readl_relaxed_poll_timeout(common->base + common->reg, reg,
>> > +                                          !(reg & lock), 0, 500));
>>
>>                                     no delay between reads? ^
>
> Yes, I intended it to be a simple busy waiting loop since I don't
> expect it to be very long. Do yu have any more data on how much time
> it usually takes?
>
>>
>> > +int sunxi_ccu_probe(struct device_node *node,
>> > +                   const struct sunxi_ccu_desc *desc)
>> > +{
>> > +       struct ccu_common **cclks = desc->clks;
>> > +       size_t num_clks = desc->num_clks;
>> > +       struct clk_onecell_data *data;
>> > +       struct ccu_reset *reset;
>> > +       struct clk **clks;
>> > +       void __iomem *reg;
>> > +       int i, ret;
>> > +
>> > +       reg = of_iomap(node, 0);
>>
>> Why not of_io_request_and_map?
>
> Because initially I still had some old clocks that were probing, which
> was leading to some issues. This is obviously not the case anymore,
> I'll switch to it.
>
>>
>> > +       if (IS_ERR(reg)) {
>>
>> And of_iomap returns NULL on error. This is for of_io_request_and_map.
>>
>> > +               pr_err("%s: Could not map the clock registers\n",
>> > +                      of_node_full_name(node));
>> > +               return PTR_ERR(reg);
>> > +       }
>> > +
>> > +       data = kzalloc(sizeof(*data), GFP_KERNEL);
>> > +       if (!data)
>> > +               return -ENOMEM;
>> > +
>> > +       clks = kcalloc(num_clks, sizeof(struct clk *), GFP_KERNEL);
>> > +       if (!clks)
>> > +               return -ENOMEM;
>> > +
>> > +       data->clks = clks;
>> > +       data->clk_num = num_clks;
>> > +
>> > +       for (i = 0; i < num_clks; i++) {
>> > +               struct ccu_common *cclk = cclks[i];
>> > +               struct clk *clk;
>> > +
>> > +               if (!cclk) {
>> > +                       cclk = ERR_PTR(-ENOENT);
>>
>> This seems redundant, unless you intended to use it elsewhere?
>
> Yeah, that was supposed to be clks[i] = ERR_PTR(..);
>
> I'll fix it.
>
>>
>> > +                       continue;
>> > +               }
>> > +
>> > +               cclk->base = reg;
>> > +               cclk->lock = &ccu_lock;
>> > +
>> > +               clk = clk_register(NULL, &cclk->hw);
>> > +               if (IS_ERR(clk))
>> > +                       continue;
>> > +
>> > +               clks[i] = clk;
>> > +       }
>> > +
>> > +       ret = of_clk_add_provider(node, of_clk_src_onecell_get, data);
>> > +       if (ret)
>> > +               goto err_clk_unreg;
>> > +
>> > +       reset = kzalloc(sizeof(*reset), GFP_KERNEL);
>> > +       reset->rcdev.of_node = node;
>> > +       reset->rcdev.ops = &ccu_reset_ops;
>> > +       reset->rcdev.owner = THIS_MODULE;
>> > +       reset->rcdev.nr_resets = desc->num_resets;
>> > +       reset->base = reg;
>> > +       reset->lock = &ccu_lock;
>> > +       reset->reset_map = desc->resets;
>> > +
>> > +       ret = reset_controller_register(&reset->rcdev);
>> > +       if (ret)
>> > +               goto err_of_clk_unreg;
>> > +
>> > +       return 0;
>> > +
>> > +err_of_clk_unreg:
>> > +err_clk_unreg:
>> > +       return ret;
>> > +}
>> > diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
>> > new file mode 100644
>> > index 000000000000..e8b477fcd320
>> > --- /dev/null
>> > +++ b/drivers/clk/sunxi-ng/ccu_common.h
>> > @@ -0,0 +1,74 @@
>> > +/*
>> > + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
>> > + *
>> > + * This software is licensed under the terms of the GNU General Public
>> > + * License version 2, as published by the Free Software Foundation, and
>> > + * may be copied, distributed, and modified under those terms.
>> > + *
>> > + * This program is distributed in the hope that it will be useful,
>> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> > + * GNU General Public License for more details.
>> > + */
>> > +
>> > +#ifndef _COMMON_H_
>> > +#define _COMMON_H_
>> > +
>> > +#include <linux/compiler.h>
>> > +#include <linux/clk-provider.h>
>> > +
>> > +#define CCU_FEATURE_GATE               BIT(0)
>> > +#define CCU_FEATURE_LOCK               BIT(1)
>>
>> *_PLL_LOCK would be clearer that this implements a PLL lock indicator.
>> Or maybe a comment.
>
> I'll change it for PLL_LOCK
>
>>
>> > +#define CCU_FEATURE_FRACTIONAL         BIT(2)
>> > +#define CCU_FEATURE_VARIABLE_PREDIV    BIT(3)
>> > +#define CCU_FEATURE_FIXED_PREDIV       BIT(4)
>> > +#define CCU_FEATURE_FIXED_POSTDIV      BIT(5)
>> > +
>> > +struct device_node;
>> > +
>> > +#define SUNXI_HW_INIT(_name, _parent, _ops, _flags)                    \
>> > +       &(struct clk_init_data) {                                       \
>> > +               .flags          = _flags,                               \
>> > +               .name           = _name,                                \
>> > +               .parent_names   = (const char *[]) { _parent },         \
>> > +               .num_parents    = 1,                                    \
>> > +               .ops            = _ops,                                 \
>> > +       }
>> > +
>> > +#define SUNXI_HW_INIT_PARENTS(_name, _parents, _ops, _flags)           \
>> > +       &(struct clk_init_data) {                                       \
>> > +               .flags          = _flags,                               \
>> > +               .name           = _name,                                \
>> > +               .parent_names   = _parents,                             \
>> > +               .num_parents    = ARRAY_SIZE(_parents),                 \
>> > +               .ops            = _ops,                                 \
>> > +       }
>> > +
>> > +struct ccu_common {
>> > +       void __iomem    *base;
>> > +       unsigned long   reg;
>>
>> This seems quite large, considering the address space of the CCU,
>> and you using u16 or u32 for the same thing on the reset control side.
>
> Indeed, what about u16?

Either u16 or u32 will do. I suspect u16 will get bumped up to u32 due to
alignment issues of the struct.

ChenYu

>>
>> > +
>> > +       unsigned long   features;
>> > +       spinlock_t      *lock;
>> > +       struct clk_hw   hw;
>> > +};
>> > +
>> > +static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)
>> > +{
>> > +       return container_of(hw, struct ccu_common, hw);
>> > +}
>> > +
>> > +struct sunxi_ccu_desc {
>> > +       struct ccu_common       **clks;
>> > +       unsigned long           num_clks;
>> > +
>> > +       struct ccu_reset_map    *resets;
>> > +       unsigned long           num_resets;
>> > +};
>> > +
>> > +void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock);
>> > +
>> > +int sunxi_ccu_probe(struct device_node *node,
>> > +                   const struct sunxi_ccu_desc *desc);
>> > +
>> > +#endif /* _COMMON_H_ */
>> > diff --git a/drivers/clk/sunxi-ng/ccu_factor.h b/drivers/clk/sunxi-ng/ccu_factor.h
>> > new file mode 100644
>> > index 000000000000..e7cc564aaea0
>> > --- /dev/null
>> > +++ b/drivers/clk/sunxi-ng/ccu_factor.h
>> > @@ -0,0 +1,15 @@
>> > +#ifndef _CLK_FACTOR_H_
>> > +#define _CLK_FACTOR_H_
>> > +
>> > +struct ccu_factor {
>> > +       u8      shift;
>> > +       u8      width;
>> > +};
>> > +
>> > +#define SUNXI_CLK_FACTOR(_shift, _width)       \
>> > +       {                                       \
>> > +               .shift  = _shift,               \
>> > +               .width  = _width,               \
>> > +       }
>> > +
>> > +#endif /* _CLK_FACTOR_H_ */
>> > diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
>> > new file mode 100644
>> > index 000000000000..17cedad4e433
>> > --- /dev/null
>> > +++ b/drivers/clk/sunxi-ng/ccu_mux.h
>>
>> As far as I can tell there are no users of this file within this patch or the
>> following patches before the mux clock support one. It'd be easier to understand
>> if this part was moved to the mux clock patch.
>
> Will do.
>
>>
>> > @@ -0,0 +1,20 @@
>> > +#ifndef _CCU_MUX_H_
>> > +#define _CCU_MUX_H_
>> > +
>> > +#include "common.h"
>> > +
>> > +struct ccu_mux_internal {
>> > +       u8      shift;
>> > +       u8      width;
>> > +
>> > +       u8      *map;
>>
>> I assume map is a table?
>>
>> > +};
>> > +
>> > +#define SUNXI_CLK_MUX(_shift, _width, _map)    \
>> > +       {                                       \
>> > +               .map    = _map,                 \
>> > +               .shift  = _shift,               \
>> > +               .width  = _width,               \
>> > +       }
>> > +
>> > +#endif /* _CCU_MUX_H_ */
>> > diff --git a/drivers/clk/sunxi-ng/ccu_reset.c b/drivers/clk/sunxi-ng/ccu_reset.c
>> > new file mode 100644
>> > index 000000000000..6c31d48783a7
>> > --- /dev/null
>> > +++ b/drivers/clk/sunxi-ng/ccu_reset.c
>> > @@ -0,0 +1,55 @@
>> > +/*
>> > + * Copyright (C) 2016 Maxime Ripard
>> > + * Maxime Ripard <maxime.ripard at free-electrons.com>
>> > + *
>> > + * 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.
>> > + */
>> > +
>> > +#include <linux/io.h>
>> > +#include <linux/reset-controller.h>
>> > +
>> > +#include "ccu_reset.h"
>> > +
>> > +static int ccu_reset_assert(struct reset_controller_dev *rcdev,
>> > +                           unsigned long id)
>> > +{
>> > +       struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
>> > +       const struct ccu_reset_map *map = &ccu->reset_map[id];
>> > +       unsigned long flags;
>> > +       u32 reg;
>> > +
>> > +       spin_lock_irqsave(ccu->lock, flags);
>> > +
>> > +       reg = readl(ccu->base + map->reg);
>> > +       writel(reg & ~map->bit, ccu->base + map->reg);
>> > +
>> > +       spin_unlock_irqrestore(ccu->lock, flags);
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +static int ccu_reset_deassert(struct reset_controller_dev *rcdev,
>> > +                             unsigned long id)
>> > +{
>> > +       struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
>> > +       const struct ccu_reset_map *map = &ccu->reset_map[id];
>> > +       unsigned long flags;
>> > +       u32 reg;
>> > +
>> > +       spin_lock_irqsave(ccu->lock, flags);
>> > +
>> > +       reg = readl(ccu->base + map->reg);
>> > +       writel(reg | map->bit, ccu->base + map->reg);
>> > +
>> > +       spin_unlock_irqrestore(ccu->lock, flags);
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +const struct reset_control_ops ccu_reset_ops = {
>> > +       .assert         = ccu_reset_assert,
>> > +       .deassert       = ccu_reset_deassert,
>> > +};
>> > diff --git a/drivers/clk/sunxi-ng/ccu_reset.h b/drivers/clk/sunxi-ng/ccu_reset.h
>> > new file mode 100644
>> > index 000000000000..36a4679210bd
>> > --- /dev/null
>> > +++ b/drivers/clk/sunxi-ng/ccu_reset.h
>> > @@ -0,0 +1,40 @@
>> > +/*
>> > + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
>> > + *
>> > + * This software is licensed under the terms of the GNU General Public
>> > + * License version 2, as published by the Free Software Foundation, and
>> > + * may be copied, distributed, and modified under those terms.
>> > + *
>> > + * This program is distributed in the hope that it will be useful,
>> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> > + * GNU General Public License for more details.
>> > + */
>> > +
>> > +#ifndef _CCU_RESET_H_
>> > +#define _CCU_RESET_H_
>> > +
>> > +#include <linux/reset-controller.h>
>> > +
>> > +struct ccu_reset_map {
>> > +       u16     reg;
>> > +       u32     bit;
>> > +};
>> > +
>> > +
>> > +struct ccu_reset {
>> > +       void __iomem                    *base;
>> > +       struct ccu_reset_map            *reset_map;
>> > +       spinlock_t                      *lock;
>> > +
>> > +       struct reset_controller_dev     rcdev;
>> > +};
>> > +
>> > +static inline struct ccu_reset *rcdev_to_ccu_reset(struct reset_controller_dev *rcdev)
>> > +{
>> > +       return container_of(rcdev, struct ccu_reset, rcdev);
>> > +}
>> > +
>> > +extern const struct reset_control_ops ccu_reset_ops;
>> > +
>> > +#endif /* _CCU_RESET_H_ */
>>
>> The reset control code looks good.
>
> Thanks!
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com


From wens at csie.org  Mon May 16 00:07:55 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 16 May 2016 15:07:55 +0800
Subject: [PATCH 1/3] power: axp20x_usb: Add support for usb power-supply
 on axp22x pmics
In-Reply-To: <1463248289-16456-1-git-send-email-hdegoede@redhat.com>
References: <1463248289-16456-1-git-send-email-hdegoede@redhat.com>
Message-ID: <CAGb2v67N7R5U_+dZ4ZO+VuGKo6wbVALnrMq3=Ceec8J122LiDA@mail.gmail.com>

Hi,

On Sun, May 15, 2016 at 1:51 AM, Hans de Goede <hdegoede at redhat.com> wrote:
> The usb power-supply on the axp22x pmics is mostly identical to the
> one on the axp20x pmics. One significant difference is that it cannot
> measure / monitor the usb voltage / current.
>
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> ---
>  drivers/power/axp20x_usb_power.c | 99 +++++++++++++++++++++++++++++++---------
>  1 file changed, 77 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/power/axp20x_usb_power.c b/drivers/power/axp20x_usb_power.c
> index 421a90b..b3c1d8e 100644
> --- a/drivers/power/axp20x_usb_power.c
> +++ b/drivers/power/axp20x_usb_power.c
> @@ -42,6 +42,7 @@
>  #define AXP20X_VBUS_MON_VBUS_VALID     BIT(3)
>
>  struct axp20x_usb_power {
> +       struct axp20x_dev *axp20x;
>         struct regmap *regmap;
>         struct power_supply *supply;
>  };
> @@ -85,7 +86,15 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
>
>                 switch (v & AXP20X_VBUS_CLIMIT_MASK) {
>                 case AXP20X_VBUC_CLIMIT_100mA:
> -                       val->intval = 100000;
> +                       switch (power->axp20x->variant) {
> +                       case AXP202_ID:
> +                       case AXP209_ID:
> +                               val->intval = 100000;
> +                               break;
> +                       default:
> +                               val->intval = -1; /* No 100mA limit */
> +                               break;
> +                       }

Given this hardware actually has DT bindings, I'd prefer matching against the
compatible string, and keeping the variant part in axp20x_usb_power. You could
still use the AXPXXX_ID constants, but just the ones used in the bindings. This
could potentially make adding support for newer PMICs easier by only needing a
compatible DT entry.

>                         break;
>                 case AXP20X_VBUC_CLIMIT_500mA:
>                         val->intval = 500000;
> @@ -122,16 +131,23 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
>                         break;
>                 }
>
> -               ret = regmap_read(power->regmap, AXP20X_USB_OTG_STATUS, &v);
> -               if (ret)
> -                       return ret;
> +               val->intval = POWER_SUPPLY_HEALTH_GOOD;
>
> -               if (!(v & AXP20X_USB_STATUS_VBUS_VALID)) {
> -                       val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
> +               switch (power->axp20x->variant) {
> +               case AXP202_ID:
> +               case AXP209_ID:
> +                       ret = regmap_read(power->regmap,
> +                                         AXP20X_USB_OTG_STATUS, &v);
> +                       if (ret)
> +                               return ret;
> +
> +                       if (!(v & AXP20X_USB_STATUS_VBUS_VALID))
> +                               val->intval =
> +                                       POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
> +                       break;
> +               default:

It seems like you'd return only POWER_SUPPLY_HEALTH_GOOD for AXP22x, even if
VBUS is actually disconnected.

>                         break;
>                 }
> -
> -               val->intval = POWER_SUPPLY_HEALTH_GOOD;
>                 break;
>         case POWER_SUPPLY_PROP_PRESENT:
>                 val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);
> @@ -156,6 +172,14 @@ static enum power_supply_property axp20x_usb_power_properties[] = {
>         POWER_SUPPLY_PROP_CURRENT_NOW,
>  };
>
> +static enum power_supply_property axp22x_usb_power_properties[] = {
> +       POWER_SUPPLY_PROP_HEALTH,
> +       POWER_SUPPLY_PROP_PRESENT,
> +       POWER_SUPPLY_PROP_ONLINE,
> +       POWER_SUPPLY_PROP_VOLTAGE_MIN,
> +       POWER_SUPPLY_PROP_CURRENT_MAX,
> +};
> +
>  static const struct power_supply_desc axp20x_usb_power_desc = {
>         .name = "axp20x-usb",
>         .type = POWER_SUPPLY_TYPE_USB,
> @@ -164,13 +188,25 @@ static const struct power_supply_desc axp20x_usb_power_desc = {
>         .get_property = axp20x_usb_power_get_property,
>  };
>
> +static const struct power_supply_desc axp22x_usb_power_desc = {
> +       .name = "axp20x-usb",
> +       .type = POWER_SUPPLY_TYPE_USB,
> +       .properties = axp22x_usb_power_properties,
> +       .num_properties = ARRAY_SIZE(axp22x_usb_power_properties),
> +       .get_property = axp20x_usb_power_get_property,
> +};
> +
>  static int axp20x_usb_power_probe(struct platform_device *pdev)
>  {
>         struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
>         struct power_supply_config psy_cfg = {};
>         struct axp20x_usb_power *power;
> -       static const char * const irq_names[] = { "VBUS_PLUGIN",
> -               "VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID" };
> +       static const char * const axp20x_irq_names[] = { "VBUS_PLUGIN",
> +               "VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID", NULL };
> +       static const char * const axp22x_irq_names[] = {
> +               "VBUS_PLUGIN", "VBUS_REMOVAL", NULL };
> +       static const char * const *irq_names;
> +       const struct power_supply_desc *usb_power_desc;
>         int i, irq, ret;
>
>         if (!of_device_is_available(pdev->dev.of_node))
> @@ -185,31 +221,50 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
>         if (!power)
>                 return -ENOMEM;
>
> +       power->axp20x = axp20x;
>         power->regmap = axp20x->regmap;
>
> -       /* Enable vbus valid checking */
> -       ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
> -                   AXP20X_VBUS_MON_VBUS_VALID, AXP20X_VBUS_MON_VBUS_VALID);
> -       if (ret)
> -               return ret;
> +       switch (power->axp20x->variant) {
> +       case AXP202_ID:
> +       case AXP209_ID:
> +               /* Enable vbus valid checking */
> +               ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
> +                                        AXP20X_VBUS_MON_VBUS_VALID,
> +                                        AXP20X_VBUS_MON_VBUS_VALID);
> +               if (ret)
> +                       return ret;
>
> -       /* Enable vbus voltage and current measurement */
> -       ret = regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
> +               /* Enable vbus voltage and current measurement */
> +               ret = regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
>                         AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT,
>                         AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT);
> -       if (ret)
> -               return ret;
> +               if (ret)
> +                       return ret;
> +
> +               usb_power_desc = &axp20x_usb_power_desc;
> +               irq_names = axp20x_irq_names;
> +               break;
> +       case AXP221_ID:
> +       case AXP223_ID:
> +               usb_power_desc = &axp22x_usb_power_desc;
> +               irq_names = axp22x_irq_names;
> +               break;
> +       default:
> +               dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
> +                       axp20x->variant);
> +               return -EINVAL;
> +       }

As mentioned above, I'd prefer using the compatible string.

Regards
ChenYu

>
>         psy_cfg.of_node = pdev->dev.of_node;
>         psy_cfg.drv_data = power;
>
> -       power->supply = devm_power_supply_register(&pdev->dev,
> -                                       &axp20x_usb_power_desc, &psy_cfg);
> +       power->supply = devm_power_supply_register(&pdev->dev, usb_power_desc,
> +                                                  &psy_cfg);
>         if (IS_ERR(power->supply))
>                 return PTR_ERR(power->supply);
>
>         /* Request irqs after registering, as irqs may trigger immediately */
> -       for (i = 0; i < ARRAY_SIZE(irq_names); i++) {
> +       for (i = 0; irq_names[i]; i++) {
>                 irq = platform_get_irq_byname(pdev, irq_names[i]);
>                 if (irq < 0) {
>                         dev_warn(&pdev->dev, "No IRQ for %s: %d\n",
> --
> 2.7.4
>


From michal.simek at xilinx.com  Mon May 16 00:17:32 2016
From: michal.simek at xilinx.com (Michal Simek)
Date: Mon, 16 May 2016 09:17:32 +0200
Subject: [PATCH] ZynqMP: Align gic ranges for 64k in device tree
In-Reply-To: <1463053441-57572-1-git-send-email-agraf@suse.de>
References: <1463053441-57572-1-git-send-email-agraf@suse.de>
Message-ID: <5739740C.10901@xilinx.com>

On 12.5.2016 13:44, Alexander Graf wrote:
> The GIC ranges in the zynqmp device tree are only 4kb aligned. Since
> commit 12e14066f we automatically deal with aliases GIC regions though,
> so we can map them transparently into guests even on 64kb page size
> systems.
> 
> This patch makes use of that features and sets GICC and GICV to 64kb
> aligned and sized regions.
> 
> Signed-off-by: Alexander Graf <agraf at suse.de>
> ---
>  arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
> index e595f22..38c4310 100644
> --- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
> +++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
> @@ -81,9 +81,9 @@
>  			compatible = "arm,gic-400", "arm,cortex-a15-gic";
>  			#interrupt-cells = <3>;
>  			reg = <0x0 0xf9010000 0x10000>,
> -			      <0x0 0xf902f000 0x2000>,
> +			      <0x0 0xf9020000 0x20000>,
>  			      <0x0 0xf9040000 0x20000>,
> -			      <0x0 0xf906f000 0x2000>;
> +			      <0x0 0xf9060000 0x20000>;
>  			interrupt-controller;
>  			interrupt-parent = <&gic>;
>  			interrupts = <1 9 0xf04>;
> 

Applied to zynqmp/dt with changed subject prefix ARM64: zynqmp:

Thanks,
Michal


From michal.simek at xilinx.com  Mon May 16 00:26:08 2016
From: michal.simek at xilinx.com (Michal Simek)
Date: Mon, 16 May 2016 09:26:08 +0200
Subject: [PATCH v2] ARM64: zynqmp: Use 64bit size cell format
Message-ID: <7dbe1a3398fb0dc2ab6ecaec7d5736c691db0f37.1463383564.git.michal.simek@xilinx.com>

Use 64bit size cell format instead of 32bit for memory
description.

Signed-off-by: Michal Simek <michal.simek at xilinx.com>
---

Changes in v2:
- Use ranges for PS amba busses instead of changing them to
  64 size cell

 arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts | 2 +-
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi      | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
index acb0527fdc4a..358089687a69 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
@@ -29,7 +29,7 @@
 
 	memory {
 		device_type = "memory";
-		reg = <0x0 0x0 0x40000000>;
+		reg = <0x0 0x0 0x0 0x40000000>;
 	};
 };
 
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index 38c43103d610..cb8f09cb03cf 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -14,7 +14,7 @@
 / {
 	compatible = "xlnx,zynqmp";
 	#address-cells = <2>;
-	#size-cells = <1>;
+	#size-cells = <2>;
 
 	cpus {
 		#address-cells = <1>;
@@ -75,7 +75,7 @@
 		compatible = "simple-bus";
 		#address-cells = <2>;
 		#size-cells = <1>;
-		ranges;
+		ranges = <0 0 0 0 0xffffffff>;
 
 		gic: interrupt-controller at f9010000 {
 			compatible = "arm,gic-400", "arm,cortex-a15-gic";
@@ -94,7 +94,7 @@
 		compatible = "simple-bus";
 		#address-cells = <2>;
 		#size-cells = <1>;
-		ranges;
+		ranges = <0 0 0 0 0xffffffff>;
 
 		can0: can at ff060000 {
 			compatible = "xlnx,zynq-can-1.0";
-- 
1.9.1



From jesper.nilsson at axis.com  Mon May 16 01:00:11 2016
From: jesper.nilsson at axis.com (Jesper Nilsson)
Date: Mon, 16 May 2016 10:00:11 +0200
Subject: [PATCH v4 06/18] cris: Remove unnecessary of_platform_populate
 with default match table
In-Reply-To: <1463054775-18170-7-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463054775-18170-7-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <20160516080011.GB24250@axis.com>

On Thu, May 12, 2016 at 08:06:03PM +0800, Kefeng Wang wrote:
> After patch "of/platform: Add common method to populate default bus",
> it is possible for arch code to remove unnecessary callers about the
> of_platform_populate with default match table.
> 
> Cc: Mikael Starvik <starvik at axis.com>

Acked-by: Jesper Nilsson <jesper.nilsson at axis.com>

> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> ---
>  arch/cris/kernel/setup.c | 8 --------
>  1 file changed, 8 deletions(-)

/^JN - Jesper Nilsson
-- 
               Jesper Nilsson -- jesper.nilsson at axis.com


From horms at verge.net.au  Mon May 16 01:01:55 2016
From: horms at verge.net.au (Simon Horman)
Date: Mon, 16 May 2016 17:01:55 +0900
Subject: [PATCH] ARM: dts: r8a7790: Correct unit names for cpu nodes
In-Reply-To: <1463125113-28885-1-git-send-email-geert+renesas@glider.be>
References: <1463125113-28885-1-git-send-email-geert+renesas@glider.be>
Message-ID: <20160516080154.GA4955@verge.net.au>

On Fri, May 13, 2016 at 09:38:33AM +0200, Geert Uytterhoeven wrote:
> Make the unit names for the cpu nodes match their reg properties.
> 
> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>

Thanks, I have queued this up.


From moinejf at free.fr  Mon May 16 01:02:39 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Mon, 16 May 2016 10:02:39 +0200
Subject: [PATCH 02/16] clk: sunxi-ng: Add common infrastructure
In-Reply-To: <20160515183122.GA27618@lukather>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-3-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v67XWt6tjG_xXWgGatTaiN5uYQb2_Q6bgixMDUkHfVHLHg@mail.gmail.com>
 <20160515183122.GA27618@lukather>
Message-ID: <20160516100239.a93a238b0d458b38a3689a95@free.fr>

On Sun, 15 May 2016 20:31:22 +0200
Maxime Ripard <maxime.ripard at free-electrons.com> wrote:

> > > +void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
> > > +{
> > > +       u32 reg;
> > > +
> > > +       if (!(common->features & CCU_FEATURE_LOCK))
> > > +               return;
> > > +
> > > +       WARN_ON(readl_relaxed_poll_timeout(common->base + common->reg, reg,
> > > +                                          !(reg & lock), 0, 500));
> > 
> >                                     no delay between reads? ^
> 
> Yes, I intended it to be a simple busy waiting loop since I don't
> expect it to be very long. Do yu have any more data on how much time
> it usually takes?

I have a Soc in which the rate of the audio clock is stable after a
good second.

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From horms at verge.net.au  Mon May 16 01:11:08 2016
From: horms at verge.net.au (Simon Horman)
Date: Mon, 16 May 2016 17:11:08 +0900
Subject: [PATCHv4 0/4] Reference both DMA controllers
In-Reply-To: <1463043285-14702-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1463043285-14702-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <20160516081108.GB4955@verge.net.au>

On Thu, May 12, 2016 at 10:54:41AM +0200, Niklas S?derlund wrote:
> Hi,
> 
> R-Car Gen2 have two DMA controllers, which are equivalent. However DMA
> slaves were tied only to a single DMA controller in .dtsi. This series
> add references to to both DMA controllers for all nodes that previously
> only referenced one of them. It also adds dma references to the SDHI
> nodes for r8a7794 which according to the datasheet should work but I
> have not access to HW to verify.
> 
> Tested on Koelsch (r8a7791) by altering the compatible value of either
> dmac0 or dmac1 and verifying that the DMA slaves pick the DMA controller
> that is available.

Thanks, I have queued these up.


From horms at verge.net.au  Mon May 16 01:12:57 2016
From: horms at verge.net.au (Simon Horman)
Date: Mon, 16 May 2016 17:12:57 +0900
Subject: [PATCH] arm64: dts: r8a7795: Increase the size of GIC-400 mapped
 registers
In-Reply-To: <5728E470.7050408@gmail.com>
References: <1461047395-6532-1-git-send-email-dirk.behme@de.bosch.com>
 <20160427233028.GA5155@verge.net.au>
 <5721A2A5.9010908@de.bosch.com>
 <20160428234345.GD18128@verge.net.au>
 <20160429113515.333c42ef@arm.com> <5728E470.7050408@gmail.com>
Message-ID: <20160516081257.GC4955@verge.net.au>

Hi Dirk,

On Tue, May 03, 2016 at 07:48:32PM +0200, Dirk Behme wrote:
> Hi Simon,
> 
> On 29.04.2016 12:35, Marc Zyngier wrote:
> >On Fri, 29 Apr 2016 09:43:45 +1000
> >Simon Horman <horms at verge.net.au> wrote:
> >
> >>[Cc Mark Zyngier, linux-arm-kernel]
> >>
> >>Hi Dirk,
> >>
> >>On Thu, Apr 28, 2016 at 07:41:57AM +0200, Dirk Behme wrote:
> >>>Hi Simon,
> >>>
> >>>On 28.04.2016 01:30, Simon Horman wrote:
> >>>>Hi Dirk,
> >>>>
> >>>>I understand that there is an issue here but I'm not yet able
> >>>>to convince myself that this is the correct solution.
> >>>>
> >>>>In revision r0p1 of the CoreLink GIC-400 Generic Interrupt Controller
> >>>>Technical Reference Manual[1] I see in Section 3.2. "GIC-400 register map"
> >>>>that the size of both the CPU interfaces and Virtual CPU interfaces are
> >>>>0x2000 bytes. And assuming that the hardware follows the specification it
> >>>>appears that DT is correctly describing the hardware.
> >>>
> >>>
> >>>I think you are missing the details described by ARM in
> >>>
> >>>http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=21550029f709072aacf3b9
> >>>
> >>>
> >>>Maybe Julien could help if you have some more doubts?
> >>
> >>I guess I am confused.
> >>
> >>I see that there is now handling of the case where the region size is
> >>128Kbytes. But I'm still not seeing the bit which describes that the
> >>GIC-400  has a region size of 128Kbytes. Perhaps the later is somehow
> >>implied by the former. Or perhaps I need to check with the hw team.
> >
> >Please have a look at the SBSA document, and in particular the
> >Appendix-F (registration and selling your soul required - only kidding):
> >
> >http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0029/index.html
> >
> >This requires that, in order for the two halves of GICV to be trappable
> >*separately* by a hypervisor using 64kB pages at Stage-2, the two 4kB
> >pages that describe that region are aliased as such:
> >- the first 4kB page is aliased 16 times over a 64kB region
> >- the second 4kB page is aliased 16 times over another contiguous 64kB
> >   region
> >
> >This means that your GIC is indeed covering a 128kB region, with the
> >mapping corresponding to the GICv2 memory map located at offset 0xf000
> >from the base of that 128kB region. Also, this GICV requirement also
> >applies to GICC (most likely because the two regions use the same
> >decoding logic).
> >
> >The OS must of course be aware of this (see gic_check_eoimode in the
> >GIC driver). Of course, almost nobody got that right (I only know of
> >the APM Xgene-1 so far). If you actually did, great!
> >
> >Also, the ACPI spec fails to recognize this by not providing the length
> >of the region, meaning that those who got it right with DT are likely
> >to get it wrong with ACPI, and vice-versa.
> >
> >It's a wonderful world.
> 
> 
> Could this patch be applied, then?

Yes I have now done so :)


From geert at linux-m68k.org  Mon May 16 01:15:33 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 16 May 2016 10:15:33 +0200
Subject: [PATCH 05/23] ARM: dts: r8a7790: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-6-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
 <1463126163-29423-6-git-send-email-geert+renesas@glider.be>
Message-ID: <CAMuHMdXxNS309-wB3tsuBzps9vqYDvqq2bd=9H_XXemELvcFSA@mail.gmail.com>

On Fri, May 13, 2016 at 9:55 AM, Geert Uytterhoeven
<geert+renesas at glider.be> wrote:
> --- a/arch/arm/boot/dts/r8a7790.dtsi
> +++ b/arch/arm/boot/dts/r8a7790.dtsi
> @@ -127,6 +127,22 @@
>                         power-domains = <&sysc R8A7790_PD_CA7_CPU3>;
>                         next-level-cache = <&L2_CA7>;
>                 };
> +
> +               L2_CA15: cache-controller at 0 {
> +                       compatible = "cache";
> +                       reg = <0>;
> +                       power-domains = <&sysc R8A7790_PD_CA15_SCU>;
> +                       cache-unified;
> +                       cache-level = <2>;
> +               };
> +
> +               L2_CA7: cache-controller at 100 {
> +                       compatible = "cache";
> +                       reg = <100>;

Oops, <0x100>

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 geert at linux-m68k.org  Mon May 16 01:15:52 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 16 May 2016 10:15:52 +0200
Subject: [PATCH 02/23] ARM: dts: r8a73a4: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-3-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
 <1463126163-29423-3-git-send-email-geert+renesas@glider.be>
Message-ID: <CAMuHMdVvQGgdfT+ddu7gun7awkm0P4C85cBJq6SZQxoY7ua4XQ@mail.gmail.com>

On Fri, May 13, 2016 at 9:55 AM, Geert Uytterhoeven
<geert+renesas at glider.be> wrote:
> --- a/arch/arm/boot/dts/r8a73a4.dtsi
> +++ b/arch/arm/boot/dts/r8a73a4.dtsi
> @@ -31,6 +31,24 @@
>                         power-domains = <&pd_a2sl>;
>                         next-level-cache = <&L2_CA15>;
>                 };
> +
> +               L2_CA15: cache-controller at 0 {
> +                       compatible = "cache";
> +                       reg = <0>;
> +                       clocks = <&cpg_clocks R8A73A4_CLK_Z>;
> +                       power-domains = <&pd_a3sm>;
> +                       cache-unified;
> +                       cache-level = <2>;
> +               };
> +
> +               L2_CA7: cache-controller at 100 {
> +                       compatible = "cache";
> +                       reg = <100>;

Oops, <0x100>

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 geert at linux-m68k.org  Mon May 16 01:16:24 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 16 May 2016 10:16:24 +0200
Subject: [PATCH 22/23] arm64: dts: r8a7795: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-23-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
 <1463126163-29423-23-git-send-email-geert+renesas@glider.be>
Message-ID: <CAMuHMdV6QwYwWkNfnBZZZdJG7=19ip81kYRKB4MTKH_K857fKA@mail.gmail.com>

On Fri, May 13, 2016 at 9:56 AM, Geert Uytterhoeven
<geert+renesas at glider.be> wrote:
> --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
> +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
> @@ -69,20 +69,22 @@
>                         next-level-cache = <&L2_CA57>;
>                         enable-method = "psci";
>                 };
> -       };
>
> -       L2_CA57: cache-controller at 0 {
> -               compatible = "cache";
> -               power-domains = <&sysc R8A7795_PD_CA57_SCU>;
> -               cache-unified;
> -               cache-level = <2>;
> -       };
> +               L2_CA57: cache-controller at 0 {
> +                       compatible = "cache";
> +                       reg = <0>;
> +                       power-domains = <&sysc R8A7795_PD_CA57_SCU>;
> +                       cache-unified;
> +                       cache-level = <2>;
> +               };
>
> -       L2_CA53: cache-controller at 1 {
> -               compatible = "cache";
> -               power-domains = <&sysc R8A7795_PD_CA53_SCU>;
> -               cache-unified;
> -               cache-level = <2>;
> +               L2_CA53: cache-controller at 100 {
> +                       compatible = "cache";
> +                       reg = <100>;

Oops, <0x100>

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 k.kozlowski at samsung.com  Mon May 16 01:26:48 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 16 May 2016 10:26:48 +0200
Subject: [PATCH 2/2] ARM: dts: exynos: Enable CLKOUT on Exynos5410
In-Reply-To: <1463387208-9277-1-git-send-email-k.kozlowski@samsung.com>
References: <1463387208-9277-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1463387208-9277-2-git-send-email-k.kozlowski@samsung.com>

The CLKOUT (which control is provided by PMU) is necessary for some of
the drivers using this as a clock, e.g. usb3503 USB HUB on Odroid XU
board.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index e9564ab5b5d3..f1effd3f03c4 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -70,6 +70,9 @@
 		pmu_system_controller: system-controller at 10040000 {
 			compatible = "samsung,exynos5410-pmu", "syscon";
 			reg = <0x10040000 0x5000>;
+			clock-names = "clkout16";
+			clocks = <&fin_pll>;
+			#clock-cells = <1>;
 		};
 
 		clock: clock-controller at 10010000 {
-- 
1.9.1



From k.kozlowski at samsung.com  Mon May 16 01:26:47 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 16 May 2016 10:26:47 +0200
Subject: [PATCH 1/2] clk: samsung: clkout: Add support for Exynos5410
Message-ID: <1463387208-9277-1-git-send-email-k.kozlowski@samsung.com>

Add compatible for Exynos5410 so the PMU on this SoC would provide
CLKOUT.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos-clkout.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c
index 7cd02ff37a1f..96fab6cfb202 100644
--- a/drivers/clk/samsung/clk-exynos-clkout.c
+++ b/drivers/clk/samsung/clk-exynos-clkout.c
@@ -151,6 +151,8 @@ static void __init exynos5_clkout_init(struct device_node *node)
 }
 CLK_OF_DECLARE(exynos5250_clkout, "samsung,exynos5250-pmu",
 		exynos5_clkout_init);
+CLK_OF_DECLARE(exynos5410_clkout, "samsung,exynos5410-pmu",
+		exynos5_clkout_init);
 CLK_OF_DECLARE(exynos5420_clkout, "samsung,exynos5420-pmu",
 		exynos5_clkout_init);
 CLK_OF_DECLARE(exynos5433_clkout, "samsung,exynos5433-pmu",
-- 
1.9.1



From gnurou at gmail.com  Mon May 16 01:34:26 2016
From: gnurou at gmail.com (Alexandre Courbot)
Date: Mon, 16 May 2016 17:34:26 +0900
Subject: [PATCH v9 2/2] gpio: move clps711x, moxart,
 ts4800 and gpio-ge =?iso-8859-1?Q?into_gpio-mmio?=
In-Reply-To: <1626318.aFfl1tphqe@debian64>
References: <cover.1462911225.git.chunkeey@googlemail.com>
 <85c74586dbd0023306f012764b85d6aa168b4ae7.1462911225.git.chunkeey@googlemail.com>
 <3c67e0ca-43eb-4a77-90ef-f8e2757c8edd@gmail.com>
 <1626318.aFfl1tphqe@debian64>
Message-ID: <0447d450-b538-4dbe-9290-98ad9dfcd3b1@gmail.com>

On Thursday, May 12, 2016 10:07:06 PM JST, Christian Lamparter wrote:
> On Thursday, May 12, 2016 07:30:05 PM Alexandre Courbot wrote:
>> On Wednesday, May 11, 2016 6:34:35 PM JST, Christian Lamparter wrote: ...
> [...]
>>> ...
>> Ouch, I don't like this. Also the probability that the "if (!res->name || 
>> ...)" condition is not met is so small that I would not bother 
>> with it and 
>> do the kstrdup unconditionally. But maybe we can remove this altogether - 
>> see below... ...
>
> The !res->name check is simply there because the kernel's strcmp doesn't
> check for NULL... the res->name will be coming from the device tree.
> Yes it should always be initialized but again: it's not within 
> the functions 
> control so it better be prepared for it. The "dir_reg_name" is part of the
> function so we can guarantee that it's not NULL or a invalid string. 
>
> About the leakage: I use devm_kstrdup unlike the dump strdup, it does bind
> the dupped string to the device. This way the resource is not leaked even
> if the module is loaded and unloaded, it stays with the device. (Until
> it is destroyed).

What I wanted to point out is that it is probably ok to just duplicate the 
string at all times, since the probability that res->name will not be NULL 
*and* the string will already match what we expect is very low (and could 
only come from a device tree that is aware of this patch).

Leakage is not a concern thanks to devm, as you have pointed out.

>  
> Note: The strcmp is there to check if resource name was already updated
> so even if the module was loaded multiple times it will dup the string
> just once.

Mmm, is this how things really work? My understanding is that 
devm-allocated resources will be freed after the driver's remove function 
is called (see slides 11/12 of 
http://haifux.org/lectures/323/haifux-devres.pdf). I.e. when the module is 
unloaded, your string will be destroyed. So unless I am missing something 
you would still need to duplicate it the next time the device is probed.

So here it seems to me that to be on the safe side you either need to 
restore the previous value of res->name on device destruction, or always 
duplicate the string when probing it. But with this later solution there is 
still the risk that if you then load *another* driver to probe this device, 
which will then find a valid pointer on res->name, only to find invalid 
content when following it... So in the end I'd recommend against messing 
with resources like that - it just creates potential for invalid states.

Hopefully is my following suggestion is valid, you won't need to.

>
> Doing a direct assignment like I did in the earlier versions would lead
> to issues since the device resources are part of the the device and not
> with the driver module.
>
>>> ...
>> Ok, so this is getting quite complex, with two of_device_id 
>> tables and two 
>> levels of hooks, mainly because you want to use the bgpio_pdev_probe() 
>> function which relies on named memory resources. ...
> I think I need more here. The bgpio_pdev_probe() also sets up 
> the bgpio_maps()
> (there are 6 and I'm using 4 at the moment for all compat chips). 
> The bgpio_pdev_probe() also deals with devm_gpiochip_add_data() 
> and allocates
> the memory for the gpiochip structure... as well as  and the error handling.
> etc...
>
> That's why I reused the existing code as much as possible.
> (But let's get to the main issue here:)
>> This function is here for basic platform devices, and you are not obliged 
>> to rely on it for DT. Feel free to write your own function (or 
>> rather split 
>> bgpio_pdev_probe() in two code paths) if it can reduce the 
>> amount of black 
>> magic you need to do (especially the renaming of resources on-the-fly).
>> 
>> At the end of the day what you want is a function that calls 
>> bgpio_init()  ...
>
> The main issue why this got so complicated was keeping compatibility with
> the existing drivers.
>
> If you look at "clps711x_parse_dt". You will see that it supports 5 GPIOs.
> The thing that makes it really ugly is that it uses the dt alias as a way
> to identify each port (A-E). The Port is then used to encode the number of
> gpios the controller has and whenever it is dirin or dirout... 
> I argued that this information should be put in the dts and I made patch
> for it. But updating the dts was not the way to go. as Rob explained
> in <http://www.spinics.net/lists/devicetree/msg124538.html>.
>
> This means that unless you can make a single structure that would encode
> everything these compat drivers do, (look at the call_back functions of
> the other drivers, each of the compat drivers also has a little bit of
> extra code associated to setup stuff like a label or have an extra ngpios
> property parser, etc...). I cannot see how you could make this any better
> without breaking compatibility. This was the sole reason why there are
> these individual parsers. (In RFC v4? I had that parser in their original
> files - I don't know if this would have worked any better, but feedback
> indicated that everything should be moved to the gpio-mmio.c). 
>
> So, what's your take on it?

I think your problem can be summarized as follows: for each device, you 
need to call bgpio_init() with the proper parameters. Your goal is to infer 
the right parameters for a variety a devices that make a different use of 
the device tree.

Because of this, you *will* need device-specific DT-parsing functions, and 
your current patch already contains them (like clps711x_parse_dt()). My 
suggestion is to not rely on bgpio_pdev_probe() for these specific devices, 
as this function expects resources, and forces you to so some unclear 
hacking. Instead, how about something like the following (warning, this is 
dirty and just to let you get the idea):

/* Params to bgpio_init()  */
struct bgpio_params {
    unsigned long sz;
    void __iomem *dat;
    void __iomem *set;
    void __iomem *clr;
    void __iomem *dirout;
    void __iomem *dirin;
    unsigned long flags;

    struct bgpio_pdata pdata;
};

static int clps711x_parse_dt(struct platform_device *pdev,
		struct bgpio_params *params)
{
	struct device_node *np = pdev->dev.of_node;
	struct resource *res;
	void __iomem *mem;
	int id = np ? of_alias_get_id(np, "gpio") : pdev->id;

	params->pdata.base = id * 8;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -EINVAL;
	params->dat = devm_ioremap_resource(&pdev->dev, res);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (!res)
		return -EINVAL;
	mem = devm_ioremap_resource(&pdev->dev, res);

	switch (id) {
	case 0:
	case 1:
	case 2:
		pdata->ngpio = 0; /* determined by register width */
		params->dirout = mem;
		break;
	case 3:
		pdata->ngpio = 0; /* determined by register width */
		/* PORTD is inverted logic for direction register */
		params->dirin = mem;
		break;
	case 4:
		pdata->ngpio = 3; /* PORTE is 3 lines only */
		params->dirout = mem;
		break;
	default:
		return -ENODEV;
	}

	return 0;
}

static int bgpio_pdev_probe(struct platform_device *pdev)
{
    /* clear params out */
    struct bgpio_params params = { 0 };
    const int (*parse_dt)(struct platform_device *,
                          struct bgpio_params *);

    parse_dt = of_device_get_match_data(&pdev->dev);
    /* We are not instanciated from the DT, do regular probe using 
resources */
    if (!parse_dt) {
        struct resource *r;

        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
        if (!r)
                return -EINVAL;

        params.sz = resource_size(r);

        params.dat = bgpio_map(pdev, "dat", sz);
        if (IS_ERR(params.dat))
                return PTR_ERR(params.dat);

        /* etc, fill in params by doing what bgpio_pdev_probe initially did 
*/
    } else {
        /* instanciated from DT, fill in params with the device-specific 
function */
        parse_dt(pdev, &params);
        pdata = &params.pdata;
    }

    ....
 
    err = bgpio_init(gc, dev, params.sz, params.dat, params.set, 
params.clr, params.dirout, params.dirin, params.flags);
    ....
}

... or something like that, it is probably possible to make this cleaner by 
refactoring the code a bit (bgpio_pdata and my new params structure can 
probably be merged, for instance).

You get the same result, but without messing with resources in dangerous 
ways, and also removing one level of callback (and some hard-to-follow 
macros). Of course parse_dt functions can be shared across devices when 
they are compatible. Feel also free to adopt another approach (like 
returning the struct resource in bgpio_params instead of the mapped 
resource so you can call a modified bgpio_map() on them in 
bgpio_pdev_probe()) if you find this more elegant. The idea I want to 
convey is that you don't need to rely on the named resources at all times.

Hope this clarifies!

Alex.



From narmstrong at baylibre.com  Mon May 16 01:49:13 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 16 May 2016 10:49:13 +0200
Subject: [RFC PATCH 1/3] reset: Add support for the Amlogic Meson GXBB
 Reset Controller
In-Reply-To: <m2oa881xwp.fsf@baylibre.com>
References: <1463148012-25988-1-git-send-email-narmstrong@baylibre.com>
 <1463148012-25988-2-git-send-email-narmstrong@baylibre.com>
 <m2oa881xwp.fsf@baylibre.com>
Message-ID: <57398989.2020207@baylibre.com>

On 05/14/2016 05:07 PM, Kevin Hilman wrote:
> Neil Armstrong <narmstrong at baylibre.com> writes:
>> +	writel(readl(reg_addr) | BIT(offset), reg_addr);
> 
> The spec lists these registers as 16-bit registers, so probably readw/writew
> are more appropriate here.


Looking at the datasheet, the reset controller is an APB3 module, thus 32bit would be the only data width configured.

Sure, it's strange to only have 16 used bits per registers...

> 
>> +	return 0;
>> +}
>> +
>> +static int meson_gxbb_reset_deassert(struct reset_controller_dev *rcdev,
>> +				unsigned long id)
>> +{
>> +	struct meson_gxbb_reset *data =
>> +		container_of(rcdev, struct meson_gxbb_reset, rcdev);
>> +	unsigned int bank = id / BITS_PER_REG;
>> +	unsigned int offset = id % BITS_PER_REG;
>> +	void *reg_addr = data->reg_base + (bank << 2);
>> +
>> +	if (bank >= REG_COUNT)
>> +		return -EINVAL;
>> +
>> +	writel(readl(reg_addr) & ~BIT(offset), reg_addr);
> 
> and here.
> 
>> +	return 0;
>> +}
> 
> Kevin
> 

Neil


From robert.jarzmik at free.fr  Mon May 16 01:53:56 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Mon, 16 May 2016 10:53:56 +0200
Subject: [RFC PATCH 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <s5hoa867e6v.wl-tiwai@suse.de> (Takashi Iwai's message of "Mon,
 16 May 2016 07:40:56 +0200")
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
 <s5hk2j38tmf.wl-tiwai@suse.de> <87twi1hssl.fsf@belgarion.home>
 <s5hy47c7jvd.wl-tiwai@suse.de> <87mvnrhux4.fsf@belgarion.home>
 <s5hoa867e6v.wl-tiwai@suse.de>
Message-ID: <87inyeidsr.fsf@belgarion.home>

Takashi Iwai <tiwai at suse.de> writes:

> On Sun, 15 May 2016 23:29:27 +0200,
> Robert Jarzmik wrote:
>> 
>> Takashi Iwai <tiwai at suse.de> writes:
>> 
>> > On Sat, 14 May 2016 11:50:50 +0200,
>> >
>> > No, my concern is that it's creating a dummy codec object temporarily
>> > on the stack just by copying some fields and calling the ops with it.
>> > (And actually the current code may work wrongly because lack of
>> >  zero-clear of the object.)
>> Ah yes, I remember now, the on-stack generated device, indeed ugly.
>> 
>> > IMO, a cleaner way would be to define the ops passed with both
>> > controller and codec objects as arguments, and pass NULL codec here.
>> It's rather unusual to need both the device and its controller in bus
>> operations. I must admit I have no better idea so far, so I'll try that just to
>> see how it looks like, and let's see next ...
>
> Thinking of this again, I wonder now why we need to pass the codec
> object at all.  It's the read/write ops via ac97, so we just need the
> ac97_controller object and the address slot of the accessed codec?
So far it would work. The only objection I would see is if in the future the bus
operation needs a specialization which is ac97 codec dependent, such as a flag
or a mask in ac97_codec_device structure.

Even if I'd like to not have these in bus operations, the struct snd_ac97 had a
need for a 'caps', 'ext_id', ... fields for example. Yet these could be
contained in the ac97_codec_device structure and not exposed to bus operations.

Another worry is the pattern (as an example) in atmel_ac97c_write() in
sound/atmel/ac97.c, where the codec structure is used to get the controller
through a container_of() type call. Yet passing the controller to bus operations
takes care of this one.

>From a "purely API" point of view the couple (ac97_controller, ac97_slot_id) is
what will route an ac97 bus operation, be that a read/write/reset/..., the
remaining question is will it cover the cases we've not thought of ?

Cheers.

-- 
Robert


From ulf.hansson at linaro.org  Mon May 16 02:32:41 2016
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Mon, 16 May 2016 11:32:41 +0200
Subject: [PATCH 3/3] mmc: core: support hs speed mode if hs200 mode fails
In-Reply-To: <1463130397.3151.13.camel@toradex.com>
References: <1461171092-30631-1-git-send-email-aisheng.dong@nxp.com>
 <1461171092-30631-3-git-send-email-aisheng.dong@nxp.com>
 <1463130397.3151.13.camel@toradex.com>
Message-ID: <CAPDyKFqyZRYbSoRMcJuMks+GMWAH9wDpusY+cvcH=GfVCNwSeg@mail.gmail.com>

On 13 May 2016 at 11:06, Marcel Ziswiler <marcel.ziswiler at toradex.com> wrote:
> On Thu, 2016-04-21 at 00:51 +0800, Dong Aisheng wrote:
>> Currently if mmc_select_hs200 mode switch fails, MMC core
>> can only use legacy mode to run the card.
>> Let's retry HS speed mode if HS200 fails.
>>
>> Before the fix:
>> mmc0: mmc_select_hs200 failed, error -74
>> : switch to mmc0 failed
>> mmc0: new MMC card at address 0001
>> mmcblk0: mmc0:0001 Q2J55L 7.12 GiB
>> mmcblk0boot0: mmc0:0001 Q2J55L partition 1 2.00 MiB
>> mmcblk0boot1: mmc0:0001 Q2J55L partition 2 2.00 MiB
>> mmcblk0rpmb: mmc0:0001 Q2J55L partition 3 4.00 MiB
>>  mmcblk0: p1 p2
>>
>> After the fix:
>> mmc0: mmc_select_hs200 failed, error -74
>> mmc0: new DDR MMC card at address 0001
>> mmcblk0: mmc0:0001 Q2J55L 7.12 GiB
>> mmcblk0boot0: mmc0:0001 Q2J55L partition 1 2.00 MiB
>> mmcblk0boot1: mmc0:0001 Q2J55L partition 2 2.00 MiB
>> mmcblk0rpmb: mmc0:0001 Q2J55L partition 3 4.00 MiB
>>  mmcblk0: p1 p2
>>
>> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
>> ---
>>  drivers/mmc/core/mmc.c | 3 ++-
>>  1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>> index 55c8201..b573dc7 100644
>> --- a/drivers/mmc/core/mmc.c
>> +++ b/drivers/mmc/core/mmc.c
>> @@ -1315,7 +1315,8 @@ static int mmc_select_timing(struct mmc_card
>> *card)
>>
>>       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
>>               err = mmc_select_hs200(card);
>> -     else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
>> +
>> +     if (err && (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS))
>>               err = mmc_select_hs(card);
>>
>>       if (err && err != -EBADMSG)
>
>
> This seems to break on TK1 where eMMC so far was detected as an 8-bit
> high speed MMC card. With this patch it reverts to detecting a 1-bit only
> MMC card! This has been observed both on a NVIDIA's Jetson TK1 as well as
> our new Toradex Apalis TK1 (CC Tegra mailing list, Jon Hunter and Lucas
> Stach as well). So far T30 is not affected as there we are still doing
> full HS200 with whatever issues that has.
>
> Before:
> [    3.726894] sdhci: Secure Digital Host Controller Interface driver
> [    3.733081] sdhci: Copyright(c) Pierre Ossman
> [    3.737462] sdhci-pltfm: SDHCI platform and OF driver helper
> [    3.753411] mmc0: Unknown controller version (3). You may experience
>  problems.
> [    3.768345] mmc0: Invalid maximum block size, assuming 512 bytes
> [    3.814896] mmc0: SDHCI controller on 700b0600.sdhci [700b0600.sdhci]
>  using ADMA 64-bit
> [    3.892088] mmc0: new high speed MMC card at address 0001
> [    3.899194] mmcblk0: mmc0:0001 SEM16G 14.7 GiB
> [    3.904217] mmcblk0boot0: mmc0:0001 SEM16G partition 1 4.00 MiB
> [    3.910645] mmcblk0boot1: mmc0:0001 SEM16G partition 2 4.00 MiB
> [    3.917119] mmcblk0rpmb: mmc0:0001 SEM16G partition 3 4.00 MiB
> [    3.926006]  mmcblk0: p1 p2 p3 p4 p5 p6 p7 p8 p9
> root at jetson_tk1:~# cat /sys/kernel/debug/mmc0/ios
> clock:          52000000 Hz
> actual clock:   51000000 Hz
> vdd:            21 (3.3 ~ 3.4 V)
> bus mode:       2 (push-pull)
> chip select:    0 (don't care)
> power mode:     2 (on)
> bus width:      3 (8 bits)
> timing spec:    1 (mmc high-speed)
> signal voltage: 0 (3.30 V)
> driver type:    0 (driver type B)
>
> After:
> [    3.899918] mmc0: new MMC card at address 0001
> root at jetson_tk1:~# cat /sys/kernel/debug/mmc0/ios
> clock:          25000000 Hz
> actual clock:   24727273 Hz
> vdd:            21 (3.3 ~ 3.4 V)
> bus mode:       2 (push-pull)
> chip select:    0 (don't care)
> power mode:     2 (on)
> bus width:      0 (1 bits)
> timing spec:    0 (legacy)
> signal voltage: 0 (3.30 V)
> driver type:    0 (driver type B)
>

Thanks for testing and reporting. I have dropped this patch from my
next branch for now.

Kind regards
Uffe


From jamesjj.liao at mediatek.com  Mon May 16 02:28:10 2016
From: jamesjj.liao at mediatek.com (James Liao)
Date: Mon, 16 May 2016 17:28:10 +0800
Subject: [PATCH v7 0/4] Mediatek MT2701 SCPSYS power domain support 
Message-ID: <1463390894-32062-1-git-send-email-jamesjj.liao@mediatek.com>

This series is based on v4.6-rc1 and adds scpsys power domain support
for Mediatek MT2701.

To share the code between MT2701 and MT8173, this patchset also refined
original mtk-scpsys.c to separate common codes and platform codes, so
that mtk-scpsys.c can support new SoCs more easily.

MT8173 and MT2701 scpsys init level are now subsys_init. Please refer to [1]
to see discussion details.

changes since v6:
- Minor changes in the dt-binding document.

changes since v5:
- Rebase to v4.6-rc1.
- Add dependent clocks for MFG, ISP, ETH and HIF power domains.
- Add "ethif" as a dependent clock in scpsys dt-binding document.

changes since v4:
- Rebase to v4.5-rc4.
- Remove mtk-scpsys.h and Merge its code into mtk-scpsys.c.
- Add names for every controlling registers and bits.
- Include dt-bindings headers at the beginning of mtk-scpsys.c.
- Sort compatible string in dt-binding documents.

changes since v3:
- Implement MT8173 and MT2701 scpsys drivers in a signle file.
- Remove naming of registers that can't be shared among SoCs.

changes since v2:
- Rebase to mbgg/linux-mediatek v4.4-next/soc [1].
- Remove MTK_SCPSYS_MT8173 and MTK_SCPSYS_MT2701.
- Modify scpsys dt-binding document to support MT2701.

changes since v1:
- Make MTK_SCPSYS in Kconfig invisible from users.
- Add comments for changing scpsys init level to subsys_init.

[1] http://lists.infradead.org/pipermail/linux-mediatek/2015-December/003416.html

James Liao (2):
  soc: mediatek: Refine scpsys to support multiple platform
  soc: mediatek: Init MT8173 scpsys driver earlier

Shunli Wang (2):
  soc: mediatek: Add MT2701 power dt-bindings
  soc: mediatek: Add MT2701 scpsys driver

 .../devicetree/bindings/soc/mediatek/scpsys.txt    |  13 +-
 drivers/soc/mediatek/Kconfig                       |   2 +-
 drivers/soc/mediatek/mtk-scpsys.c                  | 497 +++++++++++++++------
 include/dt-bindings/power/mt2701-power.h           |  27 ++
 4 files changed, 388 insertions(+), 151 deletions(-)
 create mode 100644 include/dt-bindings/power/mt2701-power.h

--
1.9.1



From jamesjj.liao at mediatek.com  Mon May 16 02:28:14 2016
From: jamesjj.liao at mediatek.com (James Liao)
Date: Mon, 16 May 2016 17:28:14 +0800
Subject: [PATCH v7 4/4] soc: mediatek: Add MT2701 scpsys driver
In-Reply-To: <1463390894-32062-1-git-send-email-jamesjj.liao@mediatek.com>
References: <1463390894-32062-1-git-send-email-jamesjj.liao@mediatek.com>
Message-ID: <1463390894-32062-5-git-send-email-jamesjj.liao@mediatek.com>

From: Shunli Wang <shunli.wang at mediatek.com>

Add scpsys driver for MT2701.

mtk-scpsys now supports MT8173 (arm64) and MT2701 (arm). So it should
be enabled on both arm64 and arm platforms.

Signed-off-by: Shunli Wang <shunli.wang at mediatek.com>
Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Reviewed-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/soc/mediatek/Kconfig      |   2 +-
 drivers/soc/mediatek/mtk-scpsys.c | 117 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 116 insertions(+), 3 deletions(-)

diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 0a4ea80..609bb34 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -23,7 +23,7 @@ config MTK_PMIC_WRAP
 config MTK_SCPSYS
 	bool "MediaTek SCPSYS Support"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
-	default ARM64 && ARCH_MEDIATEK
+	default ARCH_MEDIATEK
 	select REGMAP
 	select MTK_INFRACFG
 	select PM_GENERIC_DOMAINS if PM
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 00c0adb..f4d1230 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -20,6 +20,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/soc/mediatek/infracfg.h>
 
+#include <dt-bindings/power/mt2701-power.h>
 #include <dt-bindings/power/mt8173-power.h>
 
 #define SPM_VDE_PWR_CON			0x0210
@@ -27,8 +28,13 @@
 #define SPM_VEN_PWR_CON			0x0230
 #define SPM_ISP_PWR_CON			0x0238
 #define SPM_DIS_PWR_CON			0x023c
+#define SPM_CONN_PWR_CON		0x0280
 #define SPM_VEN2_PWR_CON		0x0298
-#define SPM_AUDIO_PWR_CON		0x029c
+#define SPM_AUDIO_PWR_CON		0x029c	/* MT8173 */
+#define SPM_BDP_PWR_CON			0x029c	/* MT2701 */
+#define SPM_ETH_PWR_CON			0x02a0
+#define SPM_HIF_PWR_CON			0x02a4
+#define SPM_IFR_MSC_PWR_CON		0x02a8
 #define SPM_MFG_2D_PWR_CON		0x02c0
 #define SPM_MFG_ASYNC_PWR_CON		0x02c4
 #define SPM_USB_PWR_CON			0x02cc
@@ -42,10 +48,15 @@
 #define PWR_ON_2ND_BIT			BIT(3)
 #define PWR_CLK_DIS_BIT			BIT(4)
 
+#define PWR_STATUS_CONN			BIT(1)
 #define PWR_STATUS_DISP			BIT(3)
 #define PWR_STATUS_MFG			BIT(4)
 #define PWR_STATUS_ISP			BIT(5)
 #define PWR_STATUS_VDEC			BIT(7)
+#define PWR_STATUS_BDP			BIT(14)
+#define PWR_STATUS_ETH			BIT(15)
+#define PWR_STATUS_HIF			BIT(16)
+#define PWR_STATUS_IFR_MSC		BIT(17)
 #define PWR_STATUS_VENC_LT		BIT(20)
 #define PWR_STATUS_VENC			BIT(21)
 #define PWR_STATUS_MFG_2D		BIT(22)
@@ -59,6 +70,7 @@ enum clk_id {
 	CLK_MFG,
 	CLK_VENC,
 	CLK_VENC_LT,
+	CLK_ETHIF,
 	CLK_MAX,
 };
 
@@ -321,7 +333,8 @@ static void init_clks(struct platform_device *pdev, struct clk *clk[CLK_MAX])
 		CLK_MM,
 		CLK_MFG,
 		CLK_VENC,
-		CLK_VENC_LT
+		CLK_VENC_LT,
+		CLK_ETHIF
 	};
 
 	static const char * const clk_names[] = {
@@ -329,6 +342,7 @@ static void init_clks(struct platform_device *pdev, struct clk *clk[CLK_MAX])
 		"mfg",
 		"venc",
 		"venc_lt",
+		"ethif",
 	};
 
 	int i;
@@ -459,6 +473,102 @@ static void mtk_register_power_domains(struct platform_device *pdev,
 }
 
 /*
+ * MT2701 power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt2701[] = {
+	[MT2701_POWER_DOMAIN_CONN] = {
+		.name = "conn",
+		.sta_mask = PWR_STATUS_CONN,
+		.ctl_offs = SPM_CONN_PWR_CON,
+		.bus_prot_mask = 0x0104,
+		.active_wakeup = true,
+	},
+	[MT2701_POWER_DOMAIN_DISP] = {
+		.name = "disp",
+		.sta_mask = PWR_STATUS_DISP,
+		.ctl_offs = SPM_DIS_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.clk_id = {CLK_MM},
+		.bus_prot_mask = 0x0002,
+		.active_wakeup = true,
+	},
+	[MT2701_POWER_DOMAIN_MFG] = {
+		.name = "mfg",
+		.sta_mask = PWR_STATUS_MFG,
+		.ctl_offs = SPM_MFG_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.clk_id = {CLK_MFG},
+		.active_wakeup = true,
+	},
+	[MT2701_POWER_DOMAIN_VDEC] = {
+		.name = "vdec",
+		.sta_mask = PWR_STATUS_VDEC,
+		.ctl_offs = SPM_VDE_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.clk_id = {CLK_MM},
+		.active_wakeup = true,
+	},
+	[MT2701_POWER_DOMAIN_ISP] = {
+		.name = "isp",
+		.sta_mask = PWR_STATUS_ISP,
+		.ctl_offs = SPM_ISP_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(13, 12),
+		.clk_id = {CLK_MM},
+		.active_wakeup = true,
+	},
+	[MT2701_POWER_DOMAIN_BDP] = {
+		.name = "bdp",
+		.sta_mask = PWR_STATUS_BDP,
+		.ctl_offs = SPM_BDP_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.active_wakeup = true,
+	},
+	[MT2701_POWER_DOMAIN_ETH] = {
+		.name = "eth",
+		.sta_mask = PWR_STATUS_ETH,
+		.ctl_offs = SPM_ETH_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.clk_id = {CLK_ETHIF},
+		.active_wakeup = true,
+	},
+	[MT2701_POWER_DOMAIN_HIF] = {
+		.name = "hif",
+		.sta_mask = PWR_STATUS_HIF,
+		.ctl_offs = SPM_HIF_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.clk_id = {CLK_ETHIF},
+		.active_wakeup = true,
+	},
+	[MT2701_POWER_DOMAIN_IFR_MSC] = {
+		.name = "ifr_msc",
+		.sta_mask = PWR_STATUS_IFR_MSC,
+		.ctl_offs = SPM_IFR_MSC_PWR_CON,
+		.active_wakeup = true,
+	},
+};
+
+#define NUM_DOMAINS_MT2701	ARRAY_SIZE(scp_domain_data_mt2701)
+
+static int __init scpsys_probe_mt2701(struct platform_device *pdev)
+{
+	struct scp *scp;
+
+	scp = init_scp(pdev, scp_domain_data_mt2701, NUM_DOMAINS_MT2701);
+	if (IS_ERR(scp))
+		return PTR_ERR(scp);
+
+	mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT2701);
+
+	return 0;
+}
+
+/*
  * MT8173 power domain support
  */
 
@@ -587,6 +697,9 @@ static int __init scpsys_probe_mt8173(struct platform_device *pdev)
 
 static const struct of_device_id of_scpsys_match_tbl[] = {
 	{
+		.compatible = "mediatek,mt2701-scpsys",
+		.data = scpsys_probe_mt2701,
+	}, {
 		.compatible = "mediatek,mt8173-scpsys",
 		.data = scpsys_probe_mt8173,
 	}, {
-- 
1.9.1



From jamesjj.liao at mediatek.com  Mon May 16 02:28:12 2016
From: jamesjj.liao at mediatek.com (James Liao)
Date: Mon, 16 May 2016 17:28:12 +0800
Subject: [PATCH v7 2/4] soc: mediatek: Init MT8173 scpsys driver earlier
In-Reply-To: <1463390894-32062-1-git-send-email-jamesjj.liao@mediatek.com>
References: <1463390894-32062-1-git-send-email-jamesjj.liao@mediatek.com>
Message-ID: <1463390894-32062-3-git-send-email-jamesjj.liao@mediatek.com>

Some power domain comsumers may init before module_init.
So the power domain provider (scpsys) need to be initialized
earlier too.

Take an example for our IOMMU (M4U) and SMI. SMI is a bridge
between IOMMU and multimedia HW. SMI is responsible to
enable/disable iommu and help transfer data for each multimedia
HW. Both of them have to wait until the power and clocks are
enabled.

So scpsys driver should be initialized before SMI, and SMI should
be initialized before IOMMU, and then init IOMMU consumers
(display/vdec/venc/camera etc.).

IOMMU is subsys_init by default. So we need to init scpsys driver
before subsys_init.

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Reviewed-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 5870a24..00c0adb 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -617,4 +617,21 @@ static struct platform_driver scpsys_drv = {
 		.of_match_table = of_match_ptr(of_scpsys_match_tbl),
 	},
 };
-builtin_platform_driver(scpsys_drv);
+
+static int __init scpsys_drv_init(void)
+{
+	return platform_driver_register(&scpsys_drv);
+}
+
+/*
+ * There are some Mediatek drivers which depend on the power domain driver need
+ * to probe in earlier initcall levels. So scpsys driver also need to probe
+ * earlier.
+ *
+ * IOMMU(M4U) and SMI drivers for example. SMI is a bridge between IOMMU and
+ * multimedia HW. IOMMU depends on SMI, and SMI is a power domain consumer,
+ * so the proper probe sequence should be scpsys -> SMI -> IOMMU driver.
+ * IOMMU drivers are initialized during subsys_init by default, so we need to
+ * move SMI and scpsys drivers to subsys_init or earlier init levels.
+ */
+subsys_initcall(scpsys_drv_init);
-- 
1.9.1



From jamesjj.liao at mediatek.com  Mon May 16 02:28:13 2016
From: jamesjj.liao at mediatek.com (James Liao)
Date: Mon, 16 May 2016 17:28:13 +0800
Subject: [PATCH v7 3/4] soc: mediatek: Add MT2701 power dt-bindings
In-Reply-To: <1463390894-32062-1-git-send-email-jamesjj.liao@mediatek.com>
References: <1463390894-32062-1-git-send-email-jamesjj.liao@mediatek.com>
Message-ID: <1463390894-32062-4-git-send-email-jamesjj.liao@mediatek.com>

From: Shunli Wang <shunli.wang at mediatek.com>

Add power dt-bindings for MT2701.

Signed-off-by: Shunli Wang <shunli.wang at mediatek.com>
Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Acked-by: Rob Herring <robh at kernel.org>
Reviewed-by: Kevin Hilman <khilman at baylibre.com>
---
 .../devicetree/bindings/soc/mediatek/scpsys.txt    | 13 +++++++----
 include/dt-bindings/power/mt2701-power.h           | 27 ++++++++++++++++++++++
 2 files changed, 35 insertions(+), 5 deletions(-)
 create mode 100644 include/dt-bindings/power/mt2701-power.h

diff --git a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
index e8f15e3..16fe94d 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
+++ b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
@@ -9,17 +9,20 @@ domain control.
 
 The driver implements the Generic PM domain bindings described in
 power/power_domain.txt. It provides the power domains defined in
-include/dt-bindings/power/mt8173-power.h.
+include/dt-bindings/power/mt8173-power.h and mt2701-power.h.
 
 Required properties:
-- compatible: Must be "mediatek,mt8173-scpsys"
+- compatible: Should be one of:
+	- "mediatek,mt2701-scpsys"
+	- "mediatek,mt8173-scpsys"
 - #power-domain-cells: Must be 1
 - reg: Address range of the SCPSYS unit
 - infracfg: must contain a phandle to the infracfg controller
 - clock, clock-names: clocks according to the common clock binding.
-                      The clocks needed "mm", "mfg", "venc" and "venc_lt".
-		      These are the clocks which hardware needs to be enabled
-		      before enabling certain power domains.
+                      These are clocks which hardware needs to be
+                      enabled before enabling certain power domains.
+	Required clocks for MT2701: "mm", "mfg", "ethif"
+	Required clocks for MT8173: "mm", "mfg", "venc", "venc_lt"
 
 Optional properties:
 - vdec-supply: Power supply for the vdec power domain
diff --git a/include/dt-bindings/power/mt2701-power.h b/include/dt-bindings/power/mt2701-power.h
new file mode 100644
index 0000000..64cc826
--- /dev/null
+++ b/include/dt-bindings/power/mt2701-power.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2015 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_POWER_MT2701_POWER_H
+#define _DT_BINDINGS_POWER_MT2701_POWER_H
+
+#define MT2701_POWER_DOMAIN_CONN	0
+#define MT2701_POWER_DOMAIN_DISP	1
+#define MT2701_POWER_DOMAIN_MFG		2
+#define MT2701_POWER_DOMAIN_VDEC	3
+#define MT2701_POWER_DOMAIN_ISP		4
+#define MT2701_POWER_DOMAIN_BDP		5
+#define MT2701_POWER_DOMAIN_ETH		6
+#define MT2701_POWER_DOMAIN_HIF		7
+#define MT2701_POWER_DOMAIN_IFR_MSC	8
+
+#endif /* _DT_BINDINGS_POWER_MT2701_POWER_H */
-- 
1.9.1



From jamesjj.liao at mediatek.com  Mon May 16 02:28:11 2016
From: jamesjj.liao at mediatek.com (James Liao)
Date: Mon, 16 May 2016 17:28:11 +0800
Subject: [PATCH v7 1/4] soc: mediatek: Refine scpsys to support multiple
 platform
In-Reply-To: <1463390894-32062-1-git-send-email-jamesjj.liao@mediatek.com>
References: <1463390894-32062-1-git-send-email-jamesjj.liao@mediatek.com>
Message-ID: <1463390894-32062-2-git-send-email-jamesjj.liao@mediatek.com>

Refine scpsys driver common code to support multiple SoC / platform.

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Reviewed-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/soc/mediatek/mtk-scpsys.c | 363 +++++++++++++++++++++++---------------
 1 file changed, 220 insertions(+), 143 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 57e781c..5870a24 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -11,17 +11,15 @@
  * GNU General Public License for more details.
  */
 #include <linux/clk.h>
-#include <linux/delay.h>
+#include <linux/init.h>
 #include <linux/io.h>
-#include <linux/kernel.h>
 #include <linux/mfd/syscon.h>
-#include <linux/init.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
-#include <linux/regmap.h>
-#include <linux/soc/mediatek/infracfg.h>
 #include <linux/regulator/consumer.h>
+#include <linux/soc/mediatek/infracfg.h>
+
 #include <dt-bindings/power/mt8173-power.h>
 
 #define SPM_VDE_PWR_CON			0x0210
@@ -34,6 +32,7 @@
 #define SPM_MFG_2D_PWR_CON		0x02c0
 #define SPM_MFG_ASYNC_PWR_CON		0x02c4
 #define SPM_USB_PWR_CON			0x02cc
+
 #define SPM_PWR_STATUS			0x060c
 #define SPM_PWR_STATUS_2ND		0x0610
 
@@ -55,12 +54,12 @@
 #define PWR_STATUS_USB			BIT(25)
 
 enum clk_id {
-	MT8173_CLK_NONE,
-	MT8173_CLK_MM,
-	MT8173_CLK_MFG,
-	MT8173_CLK_VENC,
-	MT8173_CLK_VENC_LT,
-	MT8173_CLK_MAX,
+	CLK_NONE,
+	CLK_MM,
+	CLK_MFG,
+	CLK_VENC,
+	CLK_VENC_LT,
+	CLK_MAX,
 };
 
 #define MAX_CLKS	2
@@ -76,98 +75,6 @@ struct scp_domain_data {
 	bool active_wakeup;
 };
 
-static const struct scp_domain_data scp_domain_data[] = {
-	[MT8173_POWER_DOMAIN_VDEC] = {
-		.name = "vdec",
-		.sta_mask = PWR_STATUS_VDEC,
-		.ctl_offs = SPM_VDE_PWR_CON,
-		.sram_pdn_bits = GENMASK(11, 8),
-		.sram_pdn_ack_bits = GENMASK(12, 12),
-		.clk_id = {MT8173_CLK_MM},
-	},
-	[MT8173_POWER_DOMAIN_VENC] = {
-		.name = "venc",
-		.sta_mask = PWR_STATUS_VENC,
-		.ctl_offs = SPM_VEN_PWR_CON,
-		.sram_pdn_bits = GENMASK(11, 8),
-		.sram_pdn_ack_bits = GENMASK(15, 12),
-		.clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC},
-	},
-	[MT8173_POWER_DOMAIN_ISP] = {
-		.name = "isp",
-		.sta_mask = PWR_STATUS_ISP,
-		.ctl_offs = SPM_ISP_PWR_CON,
-		.sram_pdn_bits = GENMASK(11, 8),
-		.sram_pdn_ack_bits = GENMASK(13, 12),
-		.clk_id = {MT8173_CLK_MM},
-	},
-	[MT8173_POWER_DOMAIN_MM] = {
-		.name = "mm",
-		.sta_mask = PWR_STATUS_DISP,
-		.ctl_offs = SPM_DIS_PWR_CON,
-		.sram_pdn_bits = GENMASK(11, 8),
-		.sram_pdn_ack_bits = GENMASK(12, 12),
-		.clk_id = {MT8173_CLK_MM},
-		.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
-			MT8173_TOP_AXI_PROT_EN_MM_M1,
-	},
-	[MT8173_POWER_DOMAIN_VENC_LT] = {
-		.name = "venc_lt",
-		.sta_mask = PWR_STATUS_VENC_LT,
-		.ctl_offs = SPM_VEN2_PWR_CON,
-		.sram_pdn_bits = GENMASK(11, 8),
-		.sram_pdn_ack_bits = GENMASK(15, 12),
-		.clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC_LT},
-	},
-	[MT8173_POWER_DOMAIN_AUDIO] = {
-		.name = "audio",
-		.sta_mask = PWR_STATUS_AUDIO,
-		.ctl_offs = SPM_AUDIO_PWR_CON,
-		.sram_pdn_bits = GENMASK(11, 8),
-		.sram_pdn_ack_bits = GENMASK(15, 12),
-		.clk_id = {MT8173_CLK_NONE},
-	},
-	[MT8173_POWER_DOMAIN_USB] = {
-		.name = "usb",
-		.sta_mask = PWR_STATUS_USB,
-		.ctl_offs = SPM_USB_PWR_CON,
-		.sram_pdn_bits = GENMASK(11, 8),
-		.sram_pdn_ack_bits = GENMASK(15, 12),
-		.clk_id = {MT8173_CLK_NONE},
-		.active_wakeup = true,
-	},
-	[MT8173_POWER_DOMAIN_MFG_ASYNC] = {
-		.name = "mfg_async",
-		.sta_mask = PWR_STATUS_MFG_ASYNC,
-		.ctl_offs = SPM_MFG_ASYNC_PWR_CON,
-		.sram_pdn_bits = GENMASK(11, 8),
-		.sram_pdn_ack_bits = 0,
-		.clk_id = {MT8173_CLK_MFG},
-	},
-	[MT8173_POWER_DOMAIN_MFG_2D] = {
-		.name = "mfg_2d",
-		.sta_mask = PWR_STATUS_MFG_2D,
-		.ctl_offs = SPM_MFG_2D_PWR_CON,
-		.sram_pdn_bits = GENMASK(11, 8),
-		.sram_pdn_ack_bits = GENMASK(13, 12),
-		.clk_id = {MT8173_CLK_NONE},
-	},
-	[MT8173_POWER_DOMAIN_MFG] = {
-		.name = "mfg",
-		.sta_mask = PWR_STATUS_MFG,
-		.ctl_offs = SPM_MFG_PWR_CON,
-		.sram_pdn_bits = GENMASK(13, 8),
-		.sram_pdn_ack_bits = GENMASK(21, 16),
-		.clk_id = {MT8173_CLK_NONE},
-		.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
-			MT8173_TOP_AXI_PROT_EN_MFG_M0 |
-			MT8173_TOP_AXI_PROT_EN_MFG_M1 |
-			MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
-	},
-};
-
-#define NUM_DOMAINS	ARRAY_SIZE(scp_domain_data)
-
 struct scp;
 
 struct scp_domain {
@@ -179,7 +86,7 @@ struct scp_domain {
 };
 
 struct scp {
-	struct scp_domain domains[NUM_DOMAINS];
+	struct scp_domain *domains;
 	struct genpd_onecell_data pd_data;
 	struct device *dev;
 	void __iomem *base;
@@ -408,57 +315,69 @@ static bool scpsys_active_wakeup(struct device *dev)
 	return scpd->data->active_wakeup;
 }
 
-static int scpsys_probe(struct platform_device *pdev)
+static void init_clks(struct platform_device *pdev, struct clk *clk[CLK_MAX])
+{
+	enum clk_id clk_ids[] = {
+		CLK_MM,
+		CLK_MFG,
+		CLK_VENC,
+		CLK_VENC_LT
+	};
+
+	static const char * const clk_names[] = {
+		"mm",
+		"mfg",
+		"venc",
+		"venc_lt",
+	};
+
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clk_ids); i++)
+		clk[clk_ids[i]] = devm_clk_get(&pdev->dev, clk_names[i]);
+}
+
+static struct scp *init_scp(struct platform_device *pdev,
+			const struct scp_domain_data *scp_domain_data, int num)
 {
 	struct genpd_onecell_data *pd_data;
 	struct resource *res;
-	int i, j, ret;
+	int i, j;
 	struct scp *scp;
-	struct clk *clk[MT8173_CLK_MAX];
+	struct clk *clk[CLK_MAX];
 
 	scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
 	if (!scp)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	scp->dev = &pdev->dev;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	scp->base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(scp->base))
-		return PTR_ERR(scp->base);
-
-	pd_data = &scp->pd_data;
-
-	pd_data->domains = devm_kzalloc(&pdev->dev,
-			sizeof(*pd_data->domains) * NUM_DOMAINS, GFP_KERNEL);
-	if (!pd_data->domains)
-		return -ENOMEM;
-
-	clk[MT8173_CLK_MM] = devm_clk_get(&pdev->dev, "mm");
-	if (IS_ERR(clk[MT8173_CLK_MM]))
-		return PTR_ERR(clk[MT8173_CLK_MM]);
-
-	clk[MT8173_CLK_MFG] = devm_clk_get(&pdev->dev, "mfg");
-	if (IS_ERR(clk[MT8173_CLK_MFG]))
-		return PTR_ERR(clk[MT8173_CLK_MFG]);
-
-	clk[MT8173_CLK_VENC] = devm_clk_get(&pdev->dev, "venc");
-	if (IS_ERR(clk[MT8173_CLK_VENC]))
-		return PTR_ERR(clk[MT8173_CLK_VENC]);
-
-	clk[MT8173_CLK_VENC_LT] = devm_clk_get(&pdev->dev, "venc_lt");
-	if (IS_ERR(clk[MT8173_CLK_VENC_LT]))
-		return PTR_ERR(clk[MT8173_CLK_VENC_LT]);
+		return ERR_CAST(scp->base);
 
 	scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
 			"infracfg");
 	if (IS_ERR(scp->infracfg)) {
 		dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
 				PTR_ERR(scp->infracfg));
-		return PTR_ERR(scp->infracfg);
+		return ERR_CAST(scp->infracfg);
 	}
 
-	for (i = 0; i < NUM_DOMAINS; i++) {
+	scp->domains = devm_kzalloc(&pdev->dev,
+				sizeof(*scp->domains) * num, GFP_KERNEL);
+	if (!scp->domains)
+		return ERR_PTR(-ENOMEM);
+
+	pd_data = &scp->pd_data;
+
+	pd_data->domains = devm_kzalloc(&pdev->dev,
+			sizeof(*pd_data->domains) * num, GFP_KERNEL);
+	if (!pd_data->domains)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < num; i++) {
 		struct scp_domain *scpd = &scp->domains[i];
 		const struct scp_domain_data *data = &scp_domain_data[i];
 
@@ -467,28 +386,54 @@ static int scpsys_probe(struct platform_device *pdev)
 			if (PTR_ERR(scpd->supply) == -ENODEV)
 				scpd->supply = NULL;
 			else
-				return PTR_ERR(scpd->supply);
+				return ERR_CAST(scpd->supply);
 		}
 	}
 
-	pd_data->num_domains = NUM_DOMAINS;
+	pd_data->num_domains = num;
 
-	for (i = 0; i < NUM_DOMAINS; i++) {
+	init_clks(pdev, clk);
+
+	for (i = 0; i < num; i++) {
 		struct scp_domain *scpd = &scp->domains[i];
 		struct generic_pm_domain *genpd = &scpd->genpd;
 		const struct scp_domain_data *data = &scp_domain_data[i];
 
+		for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
+			struct clk *c = clk[data->clk_id[j]];
+
+			if (IS_ERR(c)) {
+				dev_err(&pdev->dev, "%s: clk unavailable\n",
+					data->name);
+				return ERR_CAST(c);
+			}
+
+			scpd->clk[j] = c;
+		}
+
 		pd_data->domains[i] = genpd;
 		scpd->scp = scp;
 
 		scpd->data = data;
-		for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++)
-			scpd->clk[j] = clk[data->clk_id[j]];
 
 		genpd->name = data->name;
 		genpd->power_off = scpsys_power_off;
 		genpd->power_on = scpsys_power_on;
 		genpd->dev_ops.active_wakeup = scpsys_active_wakeup;
+	}
+
+	return scp;
+}
+
+static void mtk_register_power_domains(struct platform_device *pdev,
+				struct scp *scp, int num)
+{
+	struct genpd_onecell_data *pd_data;
+	int i, ret;
+
+	for (i = 0; i < num; i++) {
+		struct scp_domain *scpd = &scp->domains[i];
+		struct generic_pm_domain *genpd = &scpd->genpd;
 
 		/*
 		 * With CONFIG_PM disabled turn on all domains to make the
@@ -506,6 +451,123 @@ static int scpsys_probe(struct platform_device *pdev)
 	 * valid.
 	 */
 
+	pd_data = &scp->pd_data;
+
+	ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
+	if (ret)
+		dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
+}
+
+/*
+ * MT8173 power domain support
+ */
+
+static const struct scp_domain_data scp_domain_data_mt8173[] = {
+	[MT8173_POWER_DOMAIN_VDEC] = {
+		.name = "vdec",
+		.sta_mask = PWR_STATUS_VDEC,
+		.ctl_offs = SPM_VDE_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.clk_id = {CLK_MM},
+	},
+	[MT8173_POWER_DOMAIN_VENC] = {
+		.name = "venc",
+		.sta_mask = PWR_STATUS_VENC,
+		.ctl_offs = SPM_VEN_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.clk_id = {CLK_MM, CLK_VENC},
+	},
+	[MT8173_POWER_DOMAIN_ISP] = {
+		.name = "isp",
+		.sta_mask = PWR_STATUS_ISP,
+		.ctl_offs = SPM_ISP_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(13, 12),
+		.clk_id = {CLK_MM},
+	},
+	[MT8173_POWER_DOMAIN_MM] = {
+		.name = "mm",
+		.sta_mask = PWR_STATUS_DISP,
+		.ctl_offs = SPM_DIS_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(12, 12),
+		.clk_id = {CLK_MM},
+		.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
+			MT8173_TOP_AXI_PROT_EN_MM_M1,
+	},
+	[MT8173_POWER_DOMAIN_VENC_LT] = {
+		.name = "venc_lt",
+		.sta_mask = PWR_STATUS_VENC_LT,
+		.ctl_offs = SPM_VEN2_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.clk_id = {CLK_MM, CLK_VENC_LT},
+	},
+	[MT8173_POWER_DOMAIN_AUDIO] = {
+		.name = "audio",
+		.sta_mask = PWR_STATUS_AUDIO,
+		.ctl_offs = SPM_AUDIO_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.clk_id = {CLK_NONE},
+	},
+	[MT8173_POWER_DOMAIN_USB] = {
+		.name = "usb",
+		.sta_mask = PWR_STATUS_USB,
+		.ctl_offs = SPM_USB_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(15, 12),
+		.clk_id = {CLK_NONE},
+		.active_wakeup = true,
+	},
+	[MT8173_POWER_DOMAIN_MFG_ASYNC] = {
+		.name = "mfg_async",
+		.sta_mask = PWR_STATUS_MFG_ASYNC,
+		.ctl_offs = SPM_MFG_ASYNC_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = 0,
+		.clk_id = {CLK_MFG},
+	},
+	[MT8173_POWER_DOMAIN_MFG_2D] = {
+		.name = "mfg_2d",
+		.sta_mask = PWR_STATUS_MFG_2D,
+		.ctl_offs = SPM_MFG_2D_PWR_CON,
+		.sram_pdn_bits = GENMASK(11, 8),
+		.sram_pdn_ack_bits = GENMASK(13, 12),
+		.clk_id = {CLK_NONE},
+	},
+	[MT8173_POWER_DOMAIN_MFG] = {
+		.name = "mfg",
+		.sta_mask = PWR_STATUS_MFG,
+		.ctl_offs = SPM_MFG_PWR_CON,
+		.sram_pdn_bits = GENMASK(13, 8),
+		.sram_pdn_ack_bits = GENMASK(21, 16),
+		.clk_id = {CLK_NONE},
+		.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
+			MT8173_TOP_AXI_PROT_EN_MFG_M0 |
+			MT8173_TOP_AXI_PROT_EN_MFG_M1 |
+			MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
+	},
+};
+
+#define NUM_DOMAINS_MT8173	ARRAY_SIZE(scp_domain_data_mt8173)
+
+static int __init scpsys_probe_mt8173(struct platform_device *pdev)
+{
+	struct scp *scp;
+	struct genpd_onecell_data *pd_data;
+	int ret;
+
+	scp = init_scp(pdev, scp_domain_data_mt8173, NUM_DOMAINS_MT8173);
+	if (IS_ERR(scp))
+		return PTR_ERR(scp);
+
+	mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT8173);
+
+	pd_data = &scp->pd_data;
+
 	ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC],
 		pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]);
 	if (ret && IS_ENABLED(CONFIG_PM))
@@ -516,21 +578,36 @@ static int scpsys_probe(struct platform_device *pdev)
 	if (ret && IS_ENABLED(CONFIG_PM))
 		dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
 
-	ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
-	if (ret)
-		dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
-
 	return 0;
 }
 
+/*
+ * scpsys driver init
+ */
+
 static const struct of_device_id of_scpsys_match_tbl[] = {
 	{
 		.compatible = "mediatek,mt8173-scpsys",
+		.data = scpsys_probe_mt8173,
 	}, {
 		/* sentinel */
 	}
 };
 
+static int scpsys_probe(struct platform_device *pdev)
+{
+	int (*probe)(struct platform_device *);
+	const struct of_device_id *of_id;
+
+	of_id = of_match_node(of_scpsys_match_tbl, pdev->dev.of_node);
+	if (!of_id || !of_id->data)
+		return -EINVAL;
+
+	probe = of_id->data;
+
+	return probe(pdev);
+}
+
 static struct platform_driver scpsys_drv = {
 	.probe = scpsys_probe,
 	.driver = {
-- 
1.9.1



From andre.przywara at arm.com  Mon May 16 02:52:49 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:52:49 +0100
Subject: [PATCH v4 01/56] KVM: arm/arm64: vgic: streamline
 vgic_update_irq_pending() interface
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-2-git-send-email-andre.przywara@arm.com>

We actually don't use the irq_phys_map parameter in
vgic_update_irq_pending(), so let's just remove it.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 virt/kvm/arm/vgic.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 60668a7..f6c6172 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1521,7 +1521,6 @@ static int vgic_validate_injection(struct kvm_vcpu *vcpu, int irq, int level)
 }
 
 static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
-				   struct irq_phys_map *map,
 				   unsigned int irq_num, bool level)
 {
 	struct vgic_dist *dist = &kvm->arch.vgic;
@@ -1660,7 +1659,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 	if (map)
 		return -EINVAL;
 
-	return vgic_update_irq_pending(kvm, cpuid, NULL, irq_num, level);
+	return vgic_update_irq_pending(kvm, cpuid, irq_num, level);
 }
 
 /**
@@ -1686,7 +1685,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 	if (ret)
 		return ret;
 
-	return vgic_update_irq_pending(kvm, cpuid, map, map->virt_irq, level);
+	return vgic_update_irq_pending(kvm, cpuid, map->virt_irq, level);
 }
 
 static irqreturn_t vgic_maintenance_handler(int irq, void *data)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:52:52 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:52:52 +0100
Subject: [PATCH v4 04/56] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_unmap_phys_irq()
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-5-git-send-email-andre.przywara@arm.com>

kvm_vgic_unmap_phys_irq() only needs the virtual IRQ number, so let's
just pass that between the arch timer and the VGIC to get rid of
the irq_phys_map pointer.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 include/kvm/arm_vgic.h    |  2 +-
 virt/kvm/arm/arch_timer.c |  2 +-
 virt/kvm/arm/vgic.c       | 11 ++++-------
 3 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 9830232..c7bb184 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -347,7 +347,7 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 					   int virt_irq, int irq);
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 37f82c1..962b442 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -486,7 +486,7 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 
 	timer_disarm(timer);
 	if (timer->map)
-		kvm_vgic_unmap_phys_irq(vcpu, timer->map);
+		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
 }
 
 void kvm_timer_enable(struct kvm *kvm)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 2fd43a6..06abd59 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1812,25 +1812,22 @@ static void vgic_free_phys_irq_map_rcu(struct rcu_head *rcu)
 /**
  * kvm_vgic_unmap_phys_irq - Remove a virtual to physical IRQ mapping
  * @vcpu: The VCPU pointer
- * @map: The pointer to a mapping obtained through kvm_vgic_map_phys_irq
+ * @virt_irq: The virtual IRQ number to be unmapped
  *
  * Remove an existing mapping between virtual and physical interrupts.
  */
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map)
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct irq_phys_map_entry *entry;
 	struct list_head *root;
 
-	if (!map)
-		return -EINVAL;
-
-	root = vgic_get_irq_phys_map_list(vcpu, map->virt_irq);
+	root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 
 	spin_lock(&dist->irq_phys_map_lock);
 
 	list_for_each_entry(entry, root, entry) {
-		if (&entry->map == map) {
+		if (entry->map.virt_irq == virt_irq) {
 			list_del_rcu(&entry->entry);
 			call_rcu(&entry->rcu, vgic_free_phys_irq_map_rcu);
 			break;
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:52:51 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:52:51 +0100
Subject: [PATCH v4 03/56] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_map_is_active()
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-4-git-send-email-andre.przywara@arm.com>

For getting the active state of a mapped IRQ, we actually only need
the virtual IRQ number, not the pointer to the mapping entry.
Pass the virtual IRQ number from the arch timer to the VGIC directly.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- rewrap phys_active determination to fit in 80 characters

 include/kvm/arm_vgic.h    | 2 +-
 virt/kvm/arm/arch_timer.c | 6 ++----
 virt/kvm/arm/vgic.c       | 6 +++---
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index e22f015..9830232 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -348,7 +348,7 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 					   int virt_irq, int irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index a9c6c1c..37f82c1 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -274,10 +274,8 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* to ensure that hardware interrupts from the timer triggers a guest
 	* exit.
 	*/
-	if (timer->irq.level || kvm_vgic_map_is_active(vcpu, timer->map))
-		phys_active = true;
-	else
-		phys_active = false;
+	phys_active = timer->irq.level ||
+			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
 
 	/*
 	 * We want to avoid hitting the (re)distributor as much as
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 81c557c..2fd43a6 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1102,18 +1102,18 @@ static bool dist_active_irq(struct kvm_vcpu *vcpu)
 	return test_bit(vcpu->vcpu_id, dist->irq_active_on_cpu);
 }
 
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map)
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	int i;
 
 	for (i = 0; i < vcpu->arch.vgic_cpu.nr_lr; i++) {
 		struct vgic_lr vlr = vgic_get_lr(vcpu, i);
 
-		if (vlr.irq == map->virt_irq && vlr.state & LR_STATE_ACTIVE)
+		if (vlr.irq == virt_irq && vlr.state & LR_STATE_ACTIVE)
 			return true;
 	}
 
-	return vgic_irq_is_active(vcpu, map->virt_irq);
+	return vgic_irq_is_active(vcpu, virt_irq);
 }
 
 /*
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:52:48 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:52:48 +0100
Subject: [PATCH v4 00/56] KVM: arm/arm64: Rework virtual GIC emulation
Message-ID: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>

Hi,

a new update for the new VGIC series.
A lot of fixes this time: comments fixed, clarified and updated, some
no longer needed code pieces from the old VGIC have been removed.
The MMIO dispatching has been improved to allow only the access types
that are mandatory in the spec, so 32-bit accesses only for most registers
with some additionally accessible by byte or 64-bit accesses as well.
This allows for some simplification in many handler functions.
The vgic_queue_irq_unlock() function was reworked a bit and is now used
by the set-active handler as well. The clear-active handler has been
extended to basically halt the guest and make sure we clear the respective
active bit in the LR (and not only in our structure). There is a new patch
introducing the KVM core bits of this feature.
Also we now detect when the redistributor and distributor regions overlap
and complain about it.
As this series is now based on kvmarm/next, we also gained the firmware
independent probing feature, which is in turn also used in this series.
This should enable ACPI machines.
A more detailed changelog can be found in the respective patches.

As this new VGIC emulation will probably become the default very shortly,
please test it full steam on whatever setup you have access to.
Any reports are warmly welcome.

This series is now based on kvmarm/next, which will be merged shortly into
Linus' kernel.
A git tree containing this series can be found on linux-arm.org:

git://linux-arm.org/linux-ap.git	branch: vgic-new/v4
http://www.linux-arm.org/git?p=linux-ap.git;a=log;h=refs/heads/vgic-new/v4

Cheers,
Andre.

===========================
This series is a joint effort to re-implement KVM's GIC emulation.
Many patches as in here have been effectively authored by multiple
people and authorship isn't clear in every case, especially since
many of the patches have been stashed together or splitted apart in
the process. So take the Author: tag with a grain of salt.

While the current VGIC implementation is centered around providing
efficient MMIO emulation, the hot path for most guests is actually
the guest entry and exit, which currently is rather costly.
Also the existing emulation has a global distributor lock, which
quickly becomes a bottleneck once the number of VCPUs increases.
Additionally the emulation was originally designed for GICv2, adding
GICv3 ITS emulation support to this proved to be rather painful.
Last, but not least the existing code became less and less
maintainable, with many special cases handled explicitly.

The new implementation is build around a struct vgic_irq data
structure, which holds all information about a virtual interrupt.
Interruts which should be injected are held in a per-VCPU list, this
make the entry/exit path much more efficient. Also the new structure
allows to have more fine grained locking - per IRQ and per VCPU -
getting rid of the global distributor lock.
As a result of the new design ITS emulation fits in more nicely, the
respective code will be provided as a follow-up series.

This series implements the same feature set as the existing emulation,
as a goodie we now implement priorities correctly.
To allow an easy transition with good test coverage, but still maintain
stability, both implementations live side by side, selectable via a
Kconfig option. The default is the new implementation.
If this code proves to be reliable, we will later remove the current
implementation with an extra patch set.

Please have a look at the series, review it and give the code some
serious testing (and possibly debugging). All feedback is appreciated.

Cheers,
Andre.

Andre Przywara (29):
  KVM: arm/arm64: vgic: streamline vgic_update_irq_pending() interface
  KVM: arm/arm64: vgic: avoid map in kvm_vgic_inject_mapped_irq()
  KVM: arm/arm64: vgic: avoid map in kvm_vgic_map_is_active()
  KVM: arm/arm64: vgic: avoid map in kvm_vgic_unmap_phys_irq()
  KVM: arm/arm64: arch_timer: Remove irq_phys_map
  KVM: arm/arm64: vgic: Remove irq_phys_map from interface
  KVM: arm/arm64: pmu: abstract access to number of SPIs
  KVM: arm/arm64: move GICv2 emulation defines into arm-gic-v3.h
  KVM: arm/arm64: vgic-new: Add GICv2 MMIO handling framework
  KVM: arm/arm64: vgic-new: Add ENABLE registers handlers
  KVM: arm/arm64: vgic-new: Add PENDING registers handlers
  KVM: arm/arm64: vgic-new: Add ACTIVE registers handlers
  KVM: arm/arm64: vgic-new: Add PRIORITY registers handlers
  KVM: arm/arm64: vgic-new: Add CONFIG registers handlers
  KVM: arm/arm64: vgic-new: Add TARGET registers handlers
  KVM: arm/arm64: vgic-new: Add SGIR register handler
  KVM: arm/arm64: vgic-new: Add SGIPENDR register handlers
  KVM: arm/arm64: vgic-new: Add GICv3 MMIO handling framework
  KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR, TYPER handlers
  KVM: arm/arm64: vgic-new: Add GICv3 redistributor IIDR and TYPER
    handler
  KVM: arm/arm64: vgic-new: Add GICv3 IDREGS register handler
  KVM: arm/arm64: vgic-new: Add GICv3 IROUTER register handlers
  KVM: arm/arm64: vgic-new: Add GICv3 SGI system register trap handler
  KVM: arm/arm64: vgic-new: Add userland access to VGIC dist registers
  KVM: arm/arm64: vgic-new: Add GICH_VMCR accessors
  KVM: arm/arm64: vgic-new: Add userland GIC CPU interface access
  KVM: arm/arm64: vgic-new: Wire up irqfd injection
  KVM: arm/arm64: vgic-new: implement mapped IRQ handling
  KVM: arm/arm64: vgic-new: enable build

Christoffer Dall (10):
  KVM: arm/arm64: Remove the IRQ field from struct irq_phys_map
  KVM: arm/arm64: Get rid of vgic_cpu->nr_lr
  KVM: arm/arm64: Fix MMIO emulation data handling
  KVM: arm/arm64: Export mmio_read/write_bus
  KVM: arm/arm64: Provide functionality to pause and resume a guest
  KVM: arm/arm64: vgic-new: Add data structure definitions
  KVM: arm/arm64: vgic-new: Add acccessor to new struct vgic_irq
    instance
  KVM: arm/arm64: vgic-new: Implement virtual IRQ injection
  KVM: arm/arm64: vgic-new: Add IRQ sorting
  KVM: arm/arm64: vgic-new: Export register access interface

Eric Auger (12):
  KVM: arm/arm64: vgic-new: Implement kvm_vgic_vcpu_pending_irq
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM device ops registration
  KVM: arm/arm64: vgic-new: vgic_kvm_device:
    KVM_DEV_ARM_VGIC_GRP_NR_IRQS
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_CTRL
  KVM: arm/arm64: vgic-new: vgic_kvm_device: implement kvm_vgic_addr
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_ADDR
  KVM: arm/arm64: vgic-new: vgic_kvm_device: access to VGIC registers
  KVM: arm/arm64: vgic-new: vgic_init: implement kvm_vgic_hyp_init
  KVM: arm/arm64: vgic-new: vgic_init: implement vgic_create
  KVM: arm/arm64: vgic-new: vgic_init: implement vgic_init
  KVM: arm/arm64: vgic-new: vgic_init: implement map_resources
  KVM: arm/arm64: vgic-new: Add vgic_v2/v3_enable

Marc Zyngier (5):
  KVM: arm/arm64: vgic-new: Add IRQ sync/flush framework
  KVM: arm/arm64: vgic-new: Add GICv2 world switch backend
  KVM: arm/arm64: vgic-new: Add GICv3 world switch backend
  KVM: arm/arm64: vgic-new: Add MMIO handling framework
  KVM: arm/arm64: vgic-new: Add CTLR, TYPER and IIDR handlers

 arch/arm/include/asm/kvm_host.h     |   4 +
 arch/arm/include/asm/kvm_mmio.h     |   3 +
 arch/arm/kvm/Kconfig                |   7 +
 arch/arm/kvm/Makefile               |  11 +
 arch/arm/kvm/arm.c                  |  25 +-
 arch/arm/kvm/mmio.c                 |  24 +-
 arch/arm64/include/asm/kvm_host.h   |   4 +
 arch/arm64/include/asm/kvm_mmio.h   |   3 +
 arch/arm64/kvm/Kconfig              |   7 +
 arch/arm64/kvm/Makefile             |  12 +
 include/kvm/arm_arch_timer.h        |   3 -
 include/kvm/arm_vgic.h              |  20 +-
 include/kvm/vgic/vgic.h             | 246 +++++++++++++++
 include/linux/irqchip/arm-gic-v3.h  |   6 +
 include/linux/irqchip/arm-gic.h     |   2 +
 virt/kvm/arm/arch_timer.c           |  42 ++-
 virt/kvm/arm/hyp/vgic-v2-sr.c       |  17 +-
 virt/kvm/arm/pmu.c                  |  25 +-
 virt/kvm/arm/vgic-v2.c              |   4 +-
 virt/kvm/arm/vgic-v3.c              |   8 +-
 virt/kvm/arm/vgic.c                 |  86 ++---
 virt/kvm/arm/vgic/vgic-init.c       | 452 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-irqfd.c      |  52 +++
 virt/kvm/arm/vgic/vgic-kvm-device.c | 426 +++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 446 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio-v3.c    | 451 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c       | 499 +++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h       | 138 ++++++++
 virt/kvm/arm/vgic/vgic-v2.c         | 352 +++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c         | 330 +++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c            | 615 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            | 131 ++++++++
 32 files changed, 4314 insertions(+), 137 deletions(-)
 create mode 100644 include/kvm/vgic/vgic.h
 create mode 100644 virt/kvm/arm/vgic/vgic-init.c
 create mode 100644 virt/kvm/arm/vgic/vgic-irqfd.c
 create mode 100644 virt/kvm/arm/vgic/vgic-kvm-device.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v2.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h
 create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
 create mode 100644 virt/kvm/arm/vgic/vgic-v3.c
 create mode 100644 virt/kvm/arm/vgic/vgic.c
 create mode 100644 virt/kvm/arm/vgic/vgic.h

-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:52:50 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:52:50 +0100
Subject: [PATCH v4 02/56] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_inject_mapped_irq()
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-3-git-send-email-andre.przywara@arm.com>

When we want to inject a hardware mapped IRQ into a guest, we actually
only need the virtual IRQ number from the irq_phys_map.
So let's pass this number directly from the arch timer to the VGIC
to avoid using the map as a parameter.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 include/kvm/arm_vgic.h    | 2 +-
 virt/kvm/arm/arch_timer.c | 2 +-
 virt/kvm/arm/vgic.c       | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index be6037a..e22f015 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -342,7 +342,7 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 			bool level);
 int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
-			       struct irq_phys_map *map, bool level);
+			       unsigned int virt_irq, bool level);
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 409db33..a9c6c1c 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -177,7 +177,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
 				   timer->irq.level);
 	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->map,
+					 timer->map->virt_irq,
 					 timer->irq.level);
 	WARN_ON(ret);
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index f6c6172..81c557c 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1666,7 +1666,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
  * kvm_vgic_inject_mapped_irq - Inject a physically mapped IRQ to the vgic
  * @kvm:     The VM structure pointer
  * @cpuid:   The CPU for PPIs
- * @map:     Pointer to a irq_phys_map structure describing the mapping
+ * @virt_irq: The virtual IRQ to be injected
  * @level:   Edge-triggered:  true:  to trigger the interrupt
  *			      false: to ignore the call
  *	     Level-sensitive  true:  raise the input signal
@@ -1677,7 +1677,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
  * being HIGH and 0 being LOW and all devices being active-HIGH.
  */
 int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
-			       struct irq_phys_map *map, bool level)
+			       unsigned int virt_irq, bool level)
 {
 	int ret;
 
@@ -1685,7 +1685,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 	if (ret)
 		return ret;
 
-	return vgic_update_irq_pending(kvm, cpuid, map->virt_irq, level);
+	return vgic_update_irq_pending(kvm, cpuid, virt_irq, level);
 }
 
 static irqreturn_t vgic_maintenance_handler(int irq, void *data)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:52:54 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:52:54 +0100
Subject: [PATCH v4 06/56] KVM: arm/arm64: arch_timer: Remove irq_phys_map
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-7-git-send-email-andre.przywara@arm.com>

Now that the interface between the arch timer and the VGIC does not
require passing the irq_phys_map entry pointer anymore, let's remove
it from the virtual arch timer and use the virtual IRQ number instead
directly.
The remaining pointer returned by kvm_vgic_map_phys_irq() will be
removed in the following patch.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- remove extra virt_irq member from struct, instead use irq.irq directly

Changelog v2 .. v3:
- remove bogus validity check from kvm_vgic_unmap_phys_irq()

 include/kvm/arm_arch_timer.h |  3 ---
 virt/kvm/arm/arch_timer.c    | 10 ++++------
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index b651aed..a47b7de 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -53,9 +53,6 @@ struct arch_timer_cpu {
 	/* Timer IRQ */
 	struct kvm_irq_level		irq;
 
-	/* VGIC mapping */
-	struct irq_phys_map		*map;
-
 	/* Active IRQ state caching */
 	bool				active_cleared_last;
 };
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index e45895a..458d4d8 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -175,10 +175,10 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 
 	timer->active_cleared_last = false;
 	timer->irq.level = new_level;
-	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
+	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
 				   timer->irq.level);
 	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->map->virt_irq,
+					 timer->irq.irq,
 					 timer->irq.level);
 	WARN_ON(ret);
 }
@@ -276,7 +276,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* exit.
 	*/
 	phys_active = timer->irq.level ||
-			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
+			kvm_vgic_map_is_active(vcpu, timer->irq.irq);
 
 	/*
 	 * We want to avoid hitting the (re)distributor as much as
@@ -378,7 +378,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	if (WARN_ON(IS_ERR(map)))
 		return PTR_ERR(map);
 
-	timer->map = map;
 	return 0;
 }
 
@@ -504,8 +503,7 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 
 	timer_disarm(timer);
-	if (timer->map)
-		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
+	kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq);
 }
 
 void kvm_timer_enable(struct kvm *kvm)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:52:56 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:52:56 +0100
Subject: [PATCH v4 08/56] KVM: arm/arm64: Get rid of vgic_cpu->nr_lr
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-9-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

The number of list registers is a property of the underlying system, not
of emulated VGIC CPU interface.

As we are about to move this variable to global state in the new vgic
for clarity, move it from the legacy implementation as well to make the
merge of the new code easier.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 include/kvm/arm_vgic.h        |  3 ---
 virt/kvm/arm/hyp/vgic-v2-sr.c | 12 +++++++-----
 virt/kvm/arm/vgic-v2.c        |  4 +++-
 virt/kvm/arm/vgic.c           | 12 ++----------
 4 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 3e17fb4..67a6637 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -304,9 +304,6 @@ struct vgic_cpu {
 	unsigned long   *active_shared;
 	unsigned long   *pend_act_shared;
 
-	/* Number of list registers on this CPU */
-	int		nr_lr;
-
 	/* CPU vif control registers for world switch */
 	union {
 		struct vgic_v2_cpu_if	vgic_v2;
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index 674bdf8..caac41f 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -21,11 +21,13 @@
 
 #include <asm/kvm_hyp.h>
 
+extern struct vgic_params vgic_v2_params;
+
 static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 					    void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	u32 eisr0, eisr1;
 	int i;
 	bool expect_mi;
@@ -67,7 +69,7 @@ static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	u32 elrsr0, elrsr1;
 
 	elrsr0 = readl_relaxed(base + GICH_ELRSR0);
@@ -86,7 +88,7 @@ static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
 static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	int i;
 
 	for (i = 0; i < nr_lr; i++) {
@@ -141,13 +143,13 @@ void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
 	struct vgic_dist *vgic = &kvm->arch.vgic;
 	void __iomem *base = kern_hyp_va(vgic->vctrl_base);
-	int i, nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
+	int i;
 	u64 live_lrs = 0;
 
 	if (!base)
 		return;
 
-	nr_lr = vcpu->arch.vgic_cpu.nr_lr;
 
 	for (i = 0; i < nr_lr; i++)
 		if (cpu_if->vgic_lr[i] & GICH_LR_STATE)
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
index 7e826c9..334cd7a 100644
--- a/virt/kvm/arm/vgic-v2.c
+++ b/virt/kvm/arm/vgic-v2.c
@@ -171,7 +171,7 @@ static const struct vgic_ops vgic_v2_ops = {
 	.enable			= vgic_v2_enable,
 };
 
-static struct vgic_params vgic_v2_params;
+struct vgic_params __section(.hyp.text) vgic_v2_params;
 
 static void vgic_cpu_init_lrs(void *params)
 {
@@ -201,6 +201,8 @@ int vgic_v2_probe(const struct gic_kvm_info *gic_kvm_info,
 	const struct resource *vctrl_res = &gic_kvm_info->vctrl;
 	const struct resource *vcpu_res = &gic_kvm_info->vcpu;
 
+	memset(vgic, 0, sizeof(*vgic));
+
 	if (!gic_kvm_info->maint_irq) {
 		kvm_err("error getting vgic maintenance irq\n");
 		ret = -ENXIO;
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 91d42a8..f76bb64 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -690,12 +690,11 @@ bool vgic_handle_cfg_reg(u32 *reg, struct kvm_exit_mmio *mmio,
  */
 void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
 {
-	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
 	u64 elrsr = vgic_get_elrsr(vcpu);
 	unsigned long *elrsr_ptr = u64_to_bitmask(&elrsr);
 	int i;
 
-	for_each_clear_bit(i, elrsr_ptr, vgic_cpu->nr_lr) {
+	for_each_clear_bit(i, elrsr_ptr, vgic->nr_lr) {
 		struct vgic_lr lr = vgic_get_lr(vcpu, i);
 
 		/*
@@ -1106,7 +1105,7 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	int i;
 
-	for (i = 0; i < vcpu->arch.vgic_cpu.nr_lr; i++) {
+	for (i = 0; i < vgic->nr_lr; i++) {
 		struct vgic_lr vlr = vgic_get_lr(vcpu, i);
 
 		if (vlr.irq == virt_irq && vlr.state & LR_STATE_ACTIVE)
@@ -1866,13 +1865,6 @@ static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
 		return -ENOMEM;
 	}
 
-	/*
-	 * Store the number of LRs per vcpu, so we don't have to go
-	 * all the way to the distributor structure to find out. Only
-	 * assembly code should use this one.
-	 */
-	vgic_cpu->nr_lr = vgic->nr_lr;
-
 	return 0;
 }
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:00 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:00 +0100
Subject: [PATCH v4 12/56] KVM: arm/arm64: Provide functionality to pause and
 resume a guest
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-13-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

For some rare corner cases in our VGIC emulation later we have to stop
the guest to make sure the VGIC state is consistent.
Provide the necessary framework to pause and resume a guest.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/include/asm/kvm_host.h   |  4 ++++
 arch/arm/kvm/arm.c                | 25 +++++++++++++------------
 arch/arm64/include/asm/kvm_host.h |  4 ++++
 3 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 3850701..832be03 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -41,6 +41,8 @@
 
 #define KVM_MAX_VCPUS VGIC_V2_MAX_CPUS
 
+#define KVM_REQ_VCPU_EXIT	8
+
 u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode);
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
@@ -225,6 +227,8 @@ static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
 
 struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
+void kvm_arm_halt_guest(struct kvm *kvm);
+void kvm_arm_resume_guest(struct kvm *kvm);
 
 int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
 unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index be4b639..3b4fd03 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -492,30 +492,31 @@ bool kvm_arch_intc_initialized(struct kvm *kvm)
 	return vgic_initialized(kvm);
 }
 
-static void kvm_arm_halt_guest(struct kvm *kvm) __maybe_unused;
-static void kvm_arm_resume_guest(struct kvm *kvm) __maybe_unused;
-
-static void kvm_arm_halt_guest(struct kvm *kvm)
+void kvm_arm_halt_guest(struct kvm *kvm)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
 
 	kvm_for_each_vcpu(i, vcpu, kvm)
 		vcpu->arch.pause = true;
-	force_vm_exit(cpu_all_mask);
+	kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT);
+}
+
+static void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
+{
+	struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
+
+	vcpu->arch.pause = false;
+	swake_up(wq);
 }
 
-static void kvm_arm_resume_guest(struct kvm *kvm)
+void kvm_arm_resume_guest(struct kvm *kvm)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
 
-	kvm_for_each_vcpu(i, vcpu, kvm) {
-		struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
-
-		vcpu->arch.pause = false;
-		swake_up(wq);
-	}
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_arm_resume_vcpu(vcpu);
 }
 
 static void vcpu_sleep(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 4cd4196..fa94f91 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -44,6 +44,8 @@
 
 #define KVM_VCPU_MAX_FEATURES 4
 
+#define KVM_REQ_VCPU_EXIT	8
+
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
 int kvm_arch_dev_ioctl_check_extension(long ext);
@@ -325,6 +327,8 @@ static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
 
 struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
+void kvm_arm_halt_guest(struct kvm *kvm);
+void kvm_arm_resume_guest(struct kvm *kvm);
 
 u64 __kvm_call_hyp(void *hypfn, ...);
 #define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:52:58 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:52:58 +0100
Subject: [PATCH v4 10/56] KVM: arm/arm64: Export mmio_read/write_bus
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-11-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Rename mmio_{read,write}_bus to kvm_mmio_{read,write}_bus and export
them out of mmio.c.
This will be needed later for the new VGIC implementation.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm/include/asm/kvm_mmio.h   |  3 +++
 arch/arm/kvm/mmio.c               | 10 +++++-----
 arch/arm64/include/asm/kvm_mmio.h |  3 +++
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmio.h b/arch/arm/include/asm/kvm_mmio.h
index d8e90c8..f3a7de7 100644
--- a/arch/arm/include/asm/kvm_mmio.h
+++ b/arch/arm/include/asm/kvm_mmio.h
@@ -28,6 +28,9 @@ struct kvm_decode {
 	bool sign_extend;
 };
 
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
+
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		 phys_addr_t fault_ipa);
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 0158e9e..10f80a6 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -23,7 +23,7 @@
 
 #include "trace.h"
 
-static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data)
 {
 	void *datap = NULL;
 	union {
@@ -55,7 +55,7 @@ static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
 	memcpy(buf, datap, len);
 }
 
-static unsigned long mmio_read_buf(char *buf, unsigned int len)
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len)
 {
 	unsigned long data = 0;
 	union {
@@ -66,7 +66,7 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len)
 
 	switch (len) {
 	case 1:
-		data = buf[0];
+		data = *(u8 *)buf;
 		break;
 	case 2:
 		memcpy(&tmp.hword, buf, len);
@@ -103,7 +103,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		if (len > sizeof(unsigned long))
 			return -EINVAL;
 
-		data = mmio_read_buf(run->mmio.data, len);
+		data = kvm_mmio_read_buf(run->mmio.data, len);
 
 		if (vcpu->arch.mmio_decode.sign_extend &&
 		    len < sizeof(unsigned long)) {
@@ -189,7 +189,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 					       len);
 
 		trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data);
-		mmio_write_buf(data_buf, len, data);
+		kvm_mmio_write_buf(data_buf, len, data);
 
 		ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
 				       data_buf);
diff --git a/arch/arm64/include/asm/kvm_mmio.h b/arch/arm64/include/asm/kvm_mmio.h
index fe612a9..75ea420 100644
--- a/arch/arm64/include/asm/kvm_mmio.h
+++ b/arch/arm64/include/asm/kvm_mmio.h
@@ -30,6 +30,9 @@ struct kvm_decode {
 	bool sign_extend;
 };
 
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
+
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		 phys_addr_t fault_ipa);
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:52:55 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:52:55 +0100
Subject: [PATCH v4 07/56] KVM: arm/arm64: vgic: Remove irq_phys_map from
 interface
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-8-git-send-email-andre.przywara@arm.com>

Now that the virtual arch timer does not care about the irq_phys_map
anymore, let's rework kvm_vgic_map_phys_irq() to return an error
value instead. Any reference to that mapping can later be done by
passing the correct combination of VCPU and virtual IRQ number.
This makes the irq_phys_map handling completely private to the
VGIC code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- adaptations to changes in previous patches (removal of virt_irq)

Changelog v2 .. v3:
- simplify return in kvm_timer_vcpu_reset()

 include/kvm/arm_vgic.h    |  3 +--
 virt/kvm/arm/arch_timer.c |  7 +------
 virt/kvm/arm/vgic.c       | 15 +++++++--------
 3 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 9ad7625..3e17fb4 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -344,8 +344,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 			       unsigned int virt_irq, bool level);
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
-struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int phys_irq);
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, int virt_irq, int phys_irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 458d4d8..3232105 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -333,7 +333,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 			 const struct kvm_irq_level *irq)
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-	struct irq_phys_map *map;
 	struct irq_desc *desc;
 	struct irq_data *data;
 	int phys_irq;
@@ -374,11 +373,7 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	 * Tell the VGIC that the virtual interrupt is tied to a
 	 * physical interrupt. We do that once per VCPU.
 	 */
-	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
-	if (WARN_ON(IS_ERR(map)))
-		return PTR_ERR(map);
-
-	return 0;
+	return kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
 }
 
 void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index a7e496a..91d42a8 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1719,21 +1719,20 @@ static struct list_head *vgic_get_irq_phys_map_list(struct kvm_vcpu *vcpu,
  * the physical interrupt represented by @phys_irq. This mapping can be
  * established multiple times as long as the parameters are the same.
  *
- * Returns a valid pointer on success, and an error pointer otherwise
+ * Returns 0 on success or an error value otherwise.
  */
-struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int phys_irq)
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, int virt_irq, int phys_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct list_head *root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 	struct irq_phys_map *map;
 	struct irq_phys_map_entry *entry;
-
+	int ret = 0;
 
 	/* Create a new mapping */
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	spin_lock(&dist->irq_phys_map_lock);
 
@@ -1742,7 +1741,7 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	if (map) {
 		/* Make sure this mapping matches */
 		if (map->phys_irq != phys_irq)
-			map = ERR_PTR(-EINVAL);
+			ret = -EINVAL;
 
 		/* Found an existing, valid mapping */
 		goto out;
@@ -1758,9 +1757,9 @@ out:
 	spin_unlock(&dist->irq_phys_map_lock);
 	/* If we've found a hit in the existing list, free the useless
 	 * entry */
-	if (IS_ERR(map) || map != &entry->map)
+	if (ret || map != &entry->map)
 		kfree(entry);
-	return map;
+	return ret;
 }
 
 static struct irq_phys_map *vgic_irq_map_search(struct kvm_vcpu *vcpu,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:05 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:05 +0100
Subject: [PATCH v4 17/56] KVM: arm/arm64: vgic-new: Add IRQ sorting
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-18-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Adds the sorting function to cover the case where you have more IRQs
to consider than you have LRs. We now consider priorities.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/vgic/vgic.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 62fede6..1bc8f92 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -16,6 +16,7 @@
 
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <linux/list_sort.h>
 
 #include "vgic.h"
 
@@ -103,6 +104,62 @@ static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
 }
 
 /*
+ * The order of items in the ap_lists defines how we'll pack things in LRs as
+ * well, the first items in the list being the first things populated in the
+ * LRs.
+ *
+ * A hard rule is that active interrupts can never be pushed out of the LRs
+ * (and therefore take priority) since we cannot reliably trap on deactivation
+ * of IRQs and therefore they have to be present in the LRs.
+ *
+ * Otherwise things should be sorted by the priority field and the GIC
+ * hardware support will take care of preemption of priority groups etc.
+ *
+ * Return negative if "a" sorts before "b", 0 to preserve order, and positive
+ * to sort "b" before "a".
+ */
+static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+	struct vgic_irq *irqa = container_of(a, struct vgic_irq, ap_list);
+	struct vgic_irq *irqb = container_of(b, struct vgic_irq, ap_list);
+	bool penda, pendb;
+	int ret;
+
+	spin_lock(&irqa->irq_lock);
+	spin_lock(&irqb->irq_lock);
+
+	if (irqa->active || irqb->active) {
+		ret = (int)irqb->active - (int)irqa->active;
+		goto out;
+	}
+
+	penda = irqa->enabled && irqa->pending;
+	pendb = irqb->enabled && irqb->pending;
+
+	if (!penda || !pendb) {
+		ret = (int)pendb - (int)penda;
+		goto out;
+	}
+
+	/* Both pending and enabled, sort by priority */
+	ret = irqa->priority - irqb->priority;
+out:
+	spin_unlock(&irqb->irq_lock);
+	spin_unlock(&irqa->irq_lock);
+	return ret;
+}
+
+/* Must be called with the ap_list_lock held */
+static void vgic_sort_ap_list(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	list_sort(NULL, &vgic_cpu->ap_list_head, vgic_irq_cmp);
+}
+
+/*
  * Only valid injection if changing level for level-triggered IRQs or for a
  * rising edge.
  */
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:52:53 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:52:53 +0100
Subject: [PATCH v4 05/56] KVM: arm/arm64: Remove the IRQ field from struct
 irq_phys_map
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-6-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

The communication of a Linux IRQ number from outside the VGIC to the
vgic was a leftover from the day when the vgic code cared about how a
particular device injects virtual interrupts mapped to a physical
interrupt.

We can safely remove this notion, leaving all physical IRQ handling to
be done in the device driver (the arch timer in this case), which makes
room for a saner API for the new VGIC.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- update kerneldoc comments on kvm_vgic_map_phys_irq()

Changelog v2 .. v3:
- include <linux/irq.h>

 include/kvm/arm_vgic.h    |  3 +--
 virt/kvm/arm/arch_timer.c | 23 +++++++++++++++++++++--
 virt/kvm/arm/vgic.c       | 28 ++++++----------------------
 3 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index c7bb184..9ad7625 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -158,7 +158,6 @@ struct vgic_io_device {
 struct irq_phys_map {
 	u32			virt_irq;
 	u32			phys_irq;
-	u32			irq;
 };
 
 struct irq_phys_map_entry {
@@ -346,7 +345,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int irq);
+					   int virt_irq, int phys_irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 962b442..e45895a 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -20,6 +20,7 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <clocksource/arm_arch_timer.h>
 #include <asm/arch_timer.h>
@@ -300,7 +301,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	if (timer->active_cleared_last && !phys_active)
 		return;
 
-	ret = irq_set_irqchip_state(timer->map->irq,
+	ret = irq_set_irqchip_state(host_vtimer_irq,
 				    IRQCHIP_STATE_ACTIVE,
 				    phys_active);
 	WARN_ON(ret);
@@ -333,6 +334,9 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 	struct irq_phys_map *map;
+	struct irq_desc *desc;
+	struct irq_data *data;
+	int phys_irq;
 
 	/*
 	 * The vcpu timer irq number cannot be determined in
@@ -352,10 +356,25 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	kvm_timer_update_state(vcpu);
 
 	/*
+	 * Find the physical IRQ number corresponding to the host_vtimer_irq
+	 */
+	desc = irq_to_desc(host_vtimer_irq);
+	if (!desc) {
+		kvm_err("%s: no interrupt descriptor\n", __func__);
+		return -EINVAL;
+	}
+
+	data = irq_desc_get_irq_data(desc);
+	while (data->parent_data)
+		data = data->parent_data;
+
+	phys_irq = data->hwirq;
+
+	/*
 	 * Tell the VGIC that the virtual interrupt is tied to a
 	 * physical interrupt. We do that once per VCPU.
 	 */
-	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, host_vtimer_irq);
+	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
 	if (WARN_ON(IS_ERR(map)))
 		return PTR_ERR(map);
 
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 06abd59..a7e496a 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1711,38 +1711,24 @@ static struct list_head *vgic_get_irq_phys_map_list(struct kvm_vcpu *vcpu,
 /**
  * kvm_vgic_map_phys_irq - map a virtual IRQ to a physical IRQ
  * @vcpu: The VCPU pointer
- * @virt_irq: The virtual irq number
- * @irq: The Linux IRQ number
+ * @virt_irq: The virtual IRQ number for the guest
+ * @phys_irq: The hardware IRQ number of the host
  *
  * Establish a mapping between a guest visible irq (@virt_irq) and a
- * Linux irq (@irq). On injection, @virt_irq will be associated with
- * the physical interrupt represented by @irq. This mapping can be
+ * hardware irq (@phys_irq). On injection, @virt_irq will be associated with
+ * the physical interrupt represented by @phys_irq. This mapping can be
  * established multiple times as long as the parameters are the same.
  *
  * Returns a valid pointer on success, and an error pointer otherwise
  */
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int irq)
+					   int virt_irq, int phys_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct list_head *root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 	struct irq_phys_map *map;
 	struct irq_phys_map_entry *entry;
-	struct irq_desc *desc;
-	struct irq_data *data;
-	int phys_irq;
 
-	desc = irq_to_desc(irq);
-	if (!desc) {
-		kvm_err("%s: no interrupt descriptor\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
-
-	data = irq_desc_get_irq_data(desc);
-	while (data->parent_data)
-		data = data->parent_data;
-
-	phys_irq = data->hwirq;
 
 	/* Create a new mapping */
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
@@ -1755,8 +1741,7 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	map = vgic_irq_map_search(vcpu, virt_irq);
 	if (map) {
 		/* Make sure this mapping matches */
-		if (map->phys_irq != phys_irq	||
-		    map->irq      != irq)
+		if (map->phys_irq != phys_irq)
 			map = ERR_PTR(-EINVAL);
 
 		/* Found an existing, valid mapping */
@@ -1766,7 +1751,6 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	map           = &entry->map;
 	map->virt_irq = virt_irq;
 	map->phys_irq = phys_irq;
-	map->irq      = irq;
 
 	list_add_tail_rcu(&entry->entry, root);
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:02 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:02 +0100
Subject: [PATCH v4 14/56] KVM: arm/arm64: vgic-new: Add data structure
 definitions
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-15-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Add a new header file for the new and improved GIC implementation.
The big change is that we now have a struct vgic_irq per IRQ instead
of spreading all the information over various bitmaps.

We include this new header conditionally from within the old header
file for the time being to avoid touching all the users.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changes RFC .. v1:
- adapt to 4.6-rc (adding live_lrs member)
- elaborate on ap_list usage

Changes v1 .. v2:
- change data type of dist->enabled to bool

Changelog v3 .. v4:
- fix comment typos

 include/kvm/arm_vgic.h  |   5 ++
 include/kvm/vgic/vgic.h | 201 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 206 insertions(+)
 create mode 100644 include/kvm/vgic/vgic.h

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index ade7005..da0a5248 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -19,6 +19,10 @@
 #ifndef __ASM_ARM_KVM_VGIC_H
 #define __ASM_ARM_KVM_VGIC_H
 
+#ifdef CONFIG_KVM_NEW_VGIC
+#include <kvm/vgic/vgic.h>
+#else
+
 #include <linux/kernel.h>
 #include <linux/kvm.h>
 #include <linux/irqreturn.h>
@@ -367,4 +371,5 @@ static inline int vgic_v3_probe(const struct gic_kvm_info *gic_kvm_info,
 }
 #endif
 
+#endif	/* old VGIC include */
 #endif
diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
new file mode 100644
index 0000000..6ca0781
--- /dev/null
+++ b/include/kvm/vgic/vgic.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_ARM_KVM_VGIC_VGIC_H
+#define __ASM_ARM_KVM_VGIC_VGIC_H
+
+#include <linux/kernel.h>
+#include <linux/kvm.h>
+#include <linux/irqreturn.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <kvm/iodev.h>
+
+#define VGIC_V3_MAX_CPUS	255
+#define VGIC_V2_MAX_CPUS	8
+#define VGIC_NR_IRQS_LEGACY     256
+#define VGIC_NR_SGIS		16
+#define VGIC_NR_PPIS		16
+#define VGIC_NR_PRIVATE_IRQS	(VGIC_NR_SGIS + VGIC_NR_PPIS)
+#define VGIC_MAX_PRIVATE	(VGIC_NR_PRIVATE_IRQS - 1)
+#define VGIC_MAX_SPI		1019
+#define VGIC_MAX_RESERVED	1023
+#define VGIC_MIN_LPI		8192
+
+enum vgic_type {
+	VGIC_V2,		/* Good ol' GICv2 */
+	VGIC_V3,		/* New fancy GICv3 */
+};
+
+/* same for all guests, as depending only on the _host's_ GIC model */
+struct vgic_global {
+	/* type of the host GIC */
+	enum vgic_type		type;
+
+	/* Physical address of vgic virtual cpu interface */
+	phys_addr_t		vcpu_base;
+
+	/* virtual control interface mapping */
+	void __iomem		*vctrl_base;
+
+	/* Number of implemented list registers */
+	int			nr_lr;
+
+	/* Maintenance IRQ number */
+	unsigned int		maint_irq;
+
+	/* maximum number of VCPUs allowed (GICv2 limits us to 8) */
+	int			max_gic_vcpus;
+
+	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
+	bool			can_emulate_gicv2;
+};
+
+extern struct vgic_global kvm_vgic_global_state;
+
+#define VGIC_V2_MAX_LRS		(1 << 6)
+#define VGIC_V3_MAX_LRS		16
+#define VGIC_V3_LR_INDEX(lr)	(VGIC_V3_MAX_LRS - 1 - lr)
+
+enum vgic_irq_config {
+	VGIC_CONFIG_EDGE = 0,
+	VGIC_CONFIG_LEVEL
+};
+
+struct vgic_irq {
+	spinlock_t irq_lock;		/* Protects the content of the struct */
+	struct list_head ap_list;
+
+	struct kvm_vcpu *vcpu;		/* SGIs and PPIs: The VCPU
+					 * SPIs and LPIs: The VCPU whose ap_list
+					 * this is queued on.
+					 */
+
+	struct kvm_vcpu *target_vcpu;	/* The VCPU that this interrupt should
+					 * be sent to, as a result of the
+					 * targets reg (v2) or the
+					 * affinity reg (v3).
+					 */
+
+	u32 intid;			/* Guest visible INTID */
+	bool pending;
+	bool line_level;		/* Level only */
+	bool soft_pending;		/* Level only */
+	bool active;			/* not used for LPIs */
+	bool enabled;
+	bool hw;			/* Tied to HW IRQ */
+	u32 hwintid;			/* HW INTID number */
+	union {
+		u8 targets;			/* GICv2 target VCPUs mask */
+		u32 mpidr;			/* GICv3 target VCPU */
+	};
+	u8 source;			/* GICv2 SGIs only */
+	u8 priority;
+	enum vgic_irq_config config;	/* Level or edge */
+};
+
+struct vgic_dist {
+	bool			in_kernel;
+	bool			ready;
+
+	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
+	u32			vgic_model;
+
+	int			nr_spis;
+
+	/* TODO: Consider moving to global state */
+	/* Virtual control interface mapping */
+	void __iomem		*vctrl_base;
+
+	/* base addresses in guest physical address space: */
+	gpa_t			vgic_dist_base;		/* distributor */
+	union {
+		/* either a GICv2 CPU interface */
+		gpa_t			vgic_cpu_base;
+		/* or a number of GICv3 redistributor regions */
+		gpa_t			vgic_redist_base;
+	};
+
+	/* distributor enabled */
+	bool			enabled;
+
+	struct vgic_irq		*spis;
+};
+
+struct vgic_v2_cpu_if {
+	u32		vgic_hcr;
+	u32		vgic_vmcr;
+	u32		vgic_misr;	/* Saved only */
+	u64		vgic_eisr;	/* Saved only */
+	u64		vgic_elrsr;	/* Saved only */
+	u32		vgic_apr;
+	u32		vgic_lr[VGIC_V2_MAX_LRS];
+};
+
+struct vgic_v3_cpu_if {
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	u32		vgic_hcr;
+	u32		vgic_vmcr;
+	u32		vgic_sre;	/* Restored only, change ignored */
+	u32		vgic_misr;	/* Saved only */
+	u32		vgic_eisr;	/* Saved only */
+	u32		vgic_elrsr;	/* Saved only */
+	u32		vgic_ap0r[4];
+	u32		vgic_ap1r[4];
+	u64		vgic_lr[VGIC_V3_MAX_LRS];
+#endif
+};
+
+struct vgic_cpu {
+	/* CPU vif control registers for world switch */
+	union {
+		struct vgic_v2_cpu_if	vgic_v2;
+		struct vgic_v3_cpu_if	vgic_v3;
+	};
+
+	unsigned int used_lrs;
+	struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
+
+	spinlock_t ap_list_lock;	/* Protects the ap_list */
+
+	/*
+	 * List of IRQs that this VCPU should consider because they are either
+	 * Active or Pending (hence the name; AP list), or because they recently
+	 * were one of the two and need to be migrated off this list to another
+	 * VCPU.
+	 */
+	struct list_head ap_list_head;
+
+	u64 live_lrs;
+};
+
+#define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
+#define vgic_initialized(k)	(false)
+#define vgic_ready(k)		((k)->arch.vgic.ready)
+#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
+			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
+
+/**
+ * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
+ *
+ * The host's GIC naturally limits the maximum amount of VCPUs a guest
+ * can use.
+ */
+static inline int kvm_vgic_get_max_vcpus(void)
+{
+	return kvm_vgic_global_state.max_gic_vcpus;
+}
+
+#endif /* __ASM_ARM_KVM_VGIC_VGIC_H */
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:03 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:03 +0100
Subject: [PATCH v4 15/56] KVM: arm/arm64: vgic-new: Add acccessor to new
 struct vgic_irq instance
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-16-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

The new VGIC implementation centers around a struct vgic_irq instance
per virtual IRQ.
Provide a function to retrieve the right instance for a given IRQ
number and (in case of private interrupts) the right VCPU.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/vgic/vgic.c | 41 +++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h | 22 ++++++++++++++++++++++
 2 files changed, 63 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic.c
 create mode 100644 virt/kvm/arm/vgic/vgic.h

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
new file mode 100644
index 0000000..fb45537
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
+
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
+			      u32 intid)
+{
+	/* SGIs and PPIs */
+	if (intid <= VGIC_MAX_PRIVATE)
+		return &vcpu->arch.vgic_cpu.private_irqs[intid];
+
+	/* SPIs */
+	if (intid <= VGIC_MAX_SPI)
+		return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS];
+
+	/* LPIs are not yet covered */
+	if (intid >= VGIC_MIN_LPI)
+		return NULL;
+
+	WARN(1, "Looking up struct vgic_irq for reserved INTID");
+	return NULL;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
new file mode 100644
index 0000000..61b8d22
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __KVM_ARM_VGIC_NEW_H__
+#define __KVM_ARM_VGIC_NEW_H__
+
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
+			      u32 intid);
+
+#endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:52:57 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:52:57 +0100
Subject: [PATCH v4 09/56] KVM: arm/arm64: Fix MMIO emulation data handling
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-10-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

When the kernel was handling a guest MMIO read access internally, we
need to copy the emulation result into the run->mmio structure in order
for the kvm_handle_mmio_return() function to pick it up and inject the
	result back into the guest.

Currently the only user of kvm_io_bus for ARM is the VGIC, which did
this copying itself, so this was not causing issues so far.

But with the upcoming new vgic implementation we need this done
properly.

Update the kvm_handle_mmio_return description and cleanup the code to
only perform a single copying when needed.

Code and commit message inspired by Andre Przywara.

Reported-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm/kvm/mmio.c | 14 +++++++-------
 virt/kvm/arm/vgic.c |  7 -------
 2 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 0f6600f..0158e9e 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -87,11 +87,10 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len)
 
 /**
  * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation
+ *			     or in-kernel IO emulation
+ *
  * @vcpu: The VCPU pointer
  * @run:  The VCPU run struct containing the mmio data
- *
- * This should only be called after returning from userspace for MMIO load
- * emulation.
  */
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
@@ -206,18 +205,19 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 	run->mmio.is_write	= is_write;
 	run->mmio.phys_addr	= fault_ipa;
 	run->mmio.len		= len;
-	if (is_write)
-		memcpy(run->mmio.data, data_buf, len);
 
 	if (!ret) {
 		/* We handled the access successfully in the kernel. */
+		if (!is_write)
+			memcpy(run->mmio.data, data_buf, len);
 		vcpu->stat.mmio_exit_kernel++;
 		kvm_handle_mmio_return(vcpu, run);
 		return 1;
-	} else {
-		vcpu->stat.mmio_exit_user++;
 	}
 
+	if (is_write)
+		memcpy(run->mmio.data, data_buf, len);
+	vcpu->stat.mmio_exit_user++;
 	run->exit_reason	= KVM_EXIT_MMIO;
 	return 0;
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index f76bb64..c3bfbb9 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -819,7 +819,6 @@ static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct vgic_io_device *iodev = container_of(this,
 						    struct vgic_io_device, dev);
-	struct kvm_run *run = vcpu->run;
 	const struct vgic_io_range *range;
 	struct kvm_exit_mmio mmio;
 	bool updated_state;
@@ -848,12 +847,6 @@ static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
 		updated_state = false;
 	}
 	spin_unlock(&dist->lock);
-	run->mmio.is_write	= is_write;
-	run->mmio.len		= len;
-	run->mmio.phys_addr	= addr;
-	memcpy(run->mmio.data, val, len);
-
-	kvm_handle_mmio_return(vcpu, run);
 
 	if (updated_state)
 		vgic_kick_vcpus(vcpu->kvm);
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:08 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:08 +0100
Subject: [PATCH v4 20/56] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-21-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

As the GICv3 virtual interface registers differ from their GICv2
siblings, we need different handlers for processing maintenance
interrupts and reading/writing to the LRs.
Implement the respective handler functions and connect them to
existing code to be called if the host is using a GICv3.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- remove outdated comment about the dist_lock
- add WARN_ON about LR_STATE not being 0 in maintenance interrupts

Changelog v1 .. v2:
- inject the IRQ priority into the list register

Changelog v2 .. v3:
- remove no longer needed irqchip/arm-gic.h inclusion

Changelog v3 .. v4:
- remove ELRSR bit set during process_maintenance()
- refine comment about Group1 interrupts
- remove wrong comment about ap_list_lock in vgic_v3_fold_lr_state()

 include/linux/irqchip/arm-gic-v3.h |   1 +
 virt/kvm/arm/vgic/vgic-v3.c        | 162 +++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c           |  25 ++++--
 virt/kvm/arm/vgic/vgic.h           |  29 +++++++
 4 files changed, 212 insertions(+), 5 deletions(-)
 create mode 100644 virt/kvm/arm/vgic/vgic-v3.c

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index ec938d1..35e93cf 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -275,6 +275,7 @@
 #define ICH_LR_ACTIVE_BIT		(1ULL << 63)
 #define ICH_LR_PHYS_ID_SHIFT		32
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
+#define ICH_LR_PRIORITY_SHIFT		48
 
 /* These are for GICv2 emulation only */
 #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
new file mode 100644
index 0000000..fb547da
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -0,0 +1,162 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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/irqchip/arm-gic-v3.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+
+	if (cpuif->vgic_misr & ICH_MISR_EOI) {
+		unsigned long eisr_bmap = cpuif->vgic_eisr;
+		int lr;
+
+		for_each_set_bit(lr, &eisr_bmap, kvm_vgic_global_state.nr_lr) {
+			u32 intid;
+			u64 val = cpuif->vgic_lr[lr];
+
+			if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+				intid = val & ICH_LR_VIRTUAL_ID_MASK;
+			else
+				intid = val & GICH_LR_VIRTUALID;
+
+			WARN_ON(cpuif->vgic_lr[lr] & ICH_LR_STATE);
+
+			kvm_notify_acked_irq(vcpu->kvm, 0,
+					     intid - VGIC_NR_PRIVATE_IRQS);
+		}
+
+		/*
+		 * In the next iterations of the vcpu loop, if we sync
+		 * the vgic state after flushing it, but before
+		 * entering the guest (this happens for pending
+		 * signals and vmid rollovers), then make sure we
+		 * don't pick up any old maintenance interrupts here.
+		 */
+		cpuif->vgic_eisr = 0;
+	}
+
+	cpuif->vgic_hcr &= ~ICH_HCR_UIE;
+}
+
+void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+
+	cpuif->vgic_hcr |= ICH_HCR_UIE;
+}
+
+void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+	int lr;
+
+	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
+		u64 val = cpuif->vgic_lr[lr];
+		u32 intid;
+		struct vgic_irq *irq;
+
+		if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+			intid = val & ICH_LR_VIRTUAL_ID_MASK;
+		else
+			intid = val & GICH_LR_VIRTUALID;
+		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+
+		/* Always preserve the active bit */
+		irq->active = !!(val & ICH_LR_ACTIVE_BIT);
+
+		/* Edge is the only case where we preserve the pending bit */
+		if (irq->config == VGIC_CONFIG_EDGE &&
+		    (val & ICH_LR_PENDING_BIT)) {
+			irq->pending = true;
+
+			if (vgic_irq_is_sgi(intid) &&
+			    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
+
+				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+				irq->source |= (1 << cpuid);
+			}
+		}
+
+		/* Clear soft pending state when level irqs have been acked */
+		if (irq->config == VGIC_CONFIG_LEVEL &&
+		    !(val & ICH_LR_PENDING_BIT)) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+/* Requires the irq to be locked already */
+void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
+{
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+	u64 val = irq->intid;
+
+	if (irq->pending) {
+		val |= ICH_LR_PENDING_BIT;
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			irq->pending = false;
+
+		if (vgic_irq_is_sgi(irq->intid) &&
+		    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+			u32 src = ffs(irq->source);
+
+			BUG_ON(!src);
+			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
+			irq->source &= ~(1 << (src - 1));
+			if (irq->source)
+				irq->pending = true;
+		}
+	}
+
+	if (irq->active)
+		val |= ICH_LR_ACTIVE_BIT;
+
+	if (irq->hw) {
+		val |= ICH_LR_HW;
+		val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
+	} else {
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			val |= ICH_LR_EOI;
+	}
+
+	/*
+	 * We currently only support Group1 interrupts, which is a
+	 * known defect. This needs to be addressed at some point.
+	 */
+	if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+		val |= ICH_LR_GROUP;
+
+	val |= (u64)irq->priority << ICH_LR_PRIORITY_SHIFT;
+
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = val;
+}
+
+void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 7d85398..eca3cd0 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -399,12 +399,18 @@ retry:
 
 static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_process_maintenance(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_process_maintenance(vcpu);
+	else
+		vgic_v3_process_maintenance(vcpu);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_fold_lr_state(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_fold_lr_state(vcpu);
+	else
+		vgic_v3_fold_lr_state(vcpu);
 }
 
 /* Requires the irq_lock to be held. */
@@ -413,17 +419,26 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
 {
 	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
 
-	vgic_v2_populate_lr(vcpu, irq, lr);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_populate_lr(vcpu, irq, lr);
+	else
+		vgic_v3_populate_lr(vcpu, irq, lr);
 }
 
 static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
-	vgic_v2_clear_lr(vcpu, lr);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_clear_lr(vcpu, lr);
+	else
+		vgic_v3_clear_lr(vcpu, lr);
 }
 
 static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_set_underflow(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_set_underflow(vcpu);
+	else
+		vgic_v3_set_underflow(vcpu);
 }
 
 /* Requires the ap_list_lock to be held. */
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 0db490e..81b1a20 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -28,4 +28,33 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
+void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
+void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
+void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
+void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+#else
+static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_v3_populate_lr(struct kvm_vcpu *vcpu,
+				       struct vgic_irq *irq, int lr)
+{
+}
+
+static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+}
+
+static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
+{
+}
+#endif
+
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:11 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:11 +0100
Subject: [PATCH v4 23/56] KVM: arm/arm64: vgic-new: Add GICv2 MMIO handling
 framework
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-24-git-send-email-andre.przywara@arm.com>

Create vgic-mmio-v2.c to describe GICv2 emulation specific handlers
using the initializer macros provided by the VGIC MMIO framework.
Provide a function to register the GICv2 distributor registers to
the kvm_io_bus framework.
The actual handler functions are still stubs in this patch.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v1 .. v2:
- new patch, split out from the generic MMIO framework patch
- use a separate file to hold GICv2 emulation specific handlers
- replace _nyi stub functions with raz/wi versions

Changelog v2 .. v3:
- replace kvm/vgic/vgic.h with kvm/arm_vgic.h
- add vgic_register_dist_iodev() prototype

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 76 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c    | 26 ++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  2 ++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 4 files changed, 106 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v2.c

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
new file mode 100644
index 0000000..a3e31a9
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -0,0 +1,76 @@
+/*
+ * VGICv2 MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irqchip/arm-gic.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+static const struct vgic_register_region vgic_v2_dist_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 12,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 2,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+};
+
+unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
+{
+	dev->regions = vgic_v2_dist_registers;
+	dev->nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
+
+	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
+
+	return SZ_4K;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 012b82b..1a97765 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -182,3 +182,29 @@ struct kvm_io_device_ops kvm_io_gic_ops = {
 	.read = dispatch_mmio_read,
 	.write = dispatch_mmio_write,
 };
+
+int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
+			     enum vgic_type type)
+{
+	struct vgic_io_device *io_device = &kvm->arch.vgic.dist_iodev;
+	int ret = 0;
+	unsigned int len;
+
+	switch (type) {
+	case VGIC_V2:
+		len = vgic_v2_init_dist_iodev(io_device);
+		break;
+	default:
+		BUG_ON(1);
+	}
+
+	io_device->base_addr = dist_base_address;
+	io_device->redist_vcpu = NULL;
+
+	mutex_lock(&kvm->slots_lock);
+	ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address,
+				      len, &io_device->dev);
+	mutex_unlock(&kvm->slots_lock);
+
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 855b1db..10404ac 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -84,4 +84,6 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
 void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 			unsigned int len, unsigned long val);
 
+unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
+
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 81b1a20..fd9acaa 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -27,6 +27,8 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
+			     enum vgic_type);
 
 #ifdef CONFIG_KVM_ARM_VGIC_V3
 void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:17 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:17 +0100
Subject: [PATCH v4 29/56] KVM: arm/arm64: vgic-new: Add CONFIG registers
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-30-git-send-email-andre.przywara@arm.com>

The config register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro
- replace extract_bytes() with simple return

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 46 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  7 ++++++
 3 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index d564a30..bb7389e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -96,7 +96,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 2,
+		vgic_mmio_read_config, vgic_mmio_write_config, 2,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 5c8af05..5fe6896 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -277,6 +277,52 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 2);
+	u32 value = 0;
+	int i;
+
+	for (i = 0; i < len * 4; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			value |= (2U << (i * 2));
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
+			    gpa_t addr, unsigned int len,
+			    unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 2);
+	int i;
+
+	for (i = 0; i < len * 4; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (intid + i < 16)
+			continue;
+
+		/*
+		 * The spec says that interrupts must be disabled before
+		 * changing the configuration to avoid UNDEFINED behaviour.
+		 */
+
+		spin_lock(&irq->irq_lock);
+		if (test_bit(i * 2 + 1, &val)) {
+			irq->config = VGIC_CONFIG_EDGE;
+		} else {
+			irq->config = VGIC_CONFIG_LEVEL;
+			irq->pending = irq->line_level | irq->soft_pending;
+		}
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 6983922..0bd0ece 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -124,6 +124,13 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
 			      gpa_t addr, unsigned int len,
 			      unsigned long val);
 
+unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
+			    gpa_t addr, unsigned int len,
+			    unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:20 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:20 +0100
Subject: [PATCH v4 32/56] KVM: arm/arm64: vgic-new: Add SGIPENDR register
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-33-git-send-email-andre.przywara@arm.com>

As this register is v2 specific, its implementation lives entirely
in vgic-mmio-v2.c.
This register allows setting the source mask of an IPI.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- remove IRQ lock from read handler
- update pending bit on setting the first / clearing the last bit
- queue virtual IRQ if necessary

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 60 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index c884e9b..3925d4c 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -146,6 +146,64 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->source << (i * 8);
+	}
+	return val;
+}
+
+static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len,
+				     unsigned long val)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->source &= ~((val >> (i * 8)) & 0xff);
+		if (!irq->source)
+			irq->pending = false;
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len,
+				     unsigned long val)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->source |= (val >> (i * 8)) & 0xff;
+
+		if (irq->source) {
+			irq->pending = true;
+			vgic_queue_irq_unlock(vcpu->kvm, irq);
+		} else {
+			spin_unlock(&irq->irq_lock);
+		}
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
@@ -184,10 +242,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		vgic_mmio_read_sgipend, vgic_mmio_write_sgipendc, 16,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 };
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:16 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:16 +0100
Subject: [PATCH v4 28/56] KVM: arm/arm64: vgic-new: Add PRIORITY registers
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-29-git-send-email-andre.przywara@arm.com>

The priority register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.
There is a corner case when we change the priority of a pending
interrupt which we don't handle at the moment.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 40 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  7 +++++++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 4 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 12e101b..d564a30 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -90,7 +90,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 74d140e..5c8af05 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -237,6 +237,46 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
+				      gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->priority << (i * 8);
+	}
+
+	return val;
+}
+
+/*
+ * We currently don't handle changing the priority of an interrupt that
+ * is already pending on a VCPU. If there is a need for this, we would
+ * need to make this VCPU exit and re-evaluate the priorities, potentially
+ * leading to this interrupt getting presented now to the guest (if it has
+ * been masked by the priority mask before).
+ */
+void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		/* Narrow the priority range to what we actually support */
+		irq->priority = (val >> (i * 8)) & GENMASK(7, 8 - VGIC_PRI_BITS);
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index dd96a71..6983922 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -117,6 +117,13 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val);
 
+unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
+				      gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index cf62015..e57f8d5 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,8 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define VGIC_PRI_BITS		5
+
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:27 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:27 +0100
Subject: [PATCH v4 39/56] KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM
 device ops registration
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-40-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch introduces the skeleton for the KVM device operations
associated to KVM_DEV_TYPE_ARM_VGIC_V2 and KVM_DEV_TYPE_ARM_VGIC_V3.

At that stage kvm_vgic_create is stubbed.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v1 .. v2:
- rename vgic_kvm_device.c to vgic-kvm-device.c

Changelog v2 .. v3:
- replace inclusion of vgic/vgic.h with arm_vgic.h
- add kvm_register_vgic_device() prototype to this patch

 virt/kvm/arm/vgic/vgic-kvm-device.c | 108 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |   2 +
 2 files changed, 110 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-kvm-device.c

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
new file mode 100644
index 0000000..ff332f3
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -0,0 +1,108 @@
+/*
+ * VGIC: KVM DEVICE API
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ * Author: Marc Zyngier <marc.zyngier at arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+
+/* common helpers */
+
+static int vgic_create(struct kvm_device *dev, u32 type)
+{
+	return kvm_vgic_create(dev->kvm, type);
+}
+
+static void vgic_destroy(struct kvm_device *dev)
+{
+	kfree(dev);
+}
+
+void kvm_register_vgic_device(unsigned long type)
+{
+	switch (type) {
+	case KVM_DEV_TYPE_ARM_VGIC_V2:
+		kvm_register_device_ops(&kvm_arm_vgic_v2_ops,
+					KVM_DEV_TYPE_ARM_VGIC_V2);
+		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case KVM_DEV_TYPE_ARM_VGIC_V3:
+		kvm_register_device_ops(&kvm_arm_vgic_v3_ops,
+					KVM_DEV_TYPE_ARM_VGIC_V3);
+		break;
+#endif
+	}
+}
+
+/* V2 ops */
+
+static int vgic_v2_set_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v2_get_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v2_has_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+struct kvm_device_ops kvm_arm_vgic_v2_ops = {
+	.name = "kvm-arm-vgic-v2",
+	.create = vgic_create,
+	.destroy = vgic_destroy,
+	.set_attr = vgic_v2_set_attr,
+	.get_attr = vgic_v2_get_attr,
+	.has_attr = vgic_v2_has_attr,
+};
+
+/* V3 ops */
+
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+
+static int vgic_v3_set_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v3_get_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v3_has_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+struct kvm_device_ops kvm_arm_vgic_v3_ops = {
+	.name = "kvm-arm-vgic-v3",
+	.create = vgic_create,
+	.destroy = vgic_destroy,
+	.set_attr = vgic_v3_set_attr,
+	.get_attr = vgic_v3_get_attr,
+	.has_attr = vgic_v3_has_attr,
+};
+
+#endif /* CONFIG_KVM_ARM_VGIC_V3 */
+
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 44c6a1b..77b0ab3 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -73,4 +73,6 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 }
 #endif
 
+void kvm_register_vgic_device(unsigned long type);
+
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:21 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:21 +0100
Subject: [PATCH v4 33/56] KVM: arm/arm64: vgic-new: Add GICv3 MMIO handling
 framework
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-34-git-send-email-andre.przywara@arm.com>

Create a new file called vgic-mmio-v3.c and describe the GICv3
distributor and redistributor registers there.
This adds a special macro to deal with the split of SGI/PPI in the
redistributor and SPIs in the distributor, which allows us to reuse
the existing GICv2 handlers for those registers which are compatible.
Also we provide a function to deal with the registration of the two
separate redistributor frames per VCPU.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog RFC..v1:
- adapt to new MMIO registration approach:
  register one device for the distributor and two for each VCPU
- implement special handling for private interrupts
- remove empty stub functions
- make IGROUPR return RAO

Changelog v1 .. v2:
- adapt to new framework, introduce vgic-mmio-v3.c
- remove userland register access functions (for now)
- precompute .len when describing a VGIC register
- add missed pointer incrementation on registering redist regions
- replace _nyi stub functions with raz/wi versions

Changelog v2 .. v3:
- replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h
- add prototype and stub code for vgic_register_redist_iodevs
- rename register struct variables _rdbase_ and _sgibase_

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 224 +++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
 virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
 virt/kvm/arm/vgic/vgic.h         |   7 ++
 4 files changed, 238 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
new file mode 100644
index 0000000..31f1a13
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -0,0 +1,224 @@
+/*
+ * VGICv3 MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irqchip/arm-gic-v3.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include <asm/kvm_emulate.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+/*
+ * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
+ * redistributors, while SPIs are covered by registers in the distributor
+ * block. Trying to set private IRQs in this block gets ignored.
+ * We take some special care here to fix the calculation of the register
+ * offset.
+ */
+#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, rd, wr, bpi, acc)	\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = bpi,					\
+		.len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8,		\
+		.access_flags = acc,					\
+		.read = vgic_mmio_read_raz,				\
+		.write = vgic_mmio_write_wi,				\
+	}, {								\
+		.reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8,	\
+		.bits_per_irq = bpi,					\
+		.len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
+		.access_flags = acc,					\
+		.read = rd,						\
+		.write = wr,						\
+	}
+
+static const struct vgic_register_region vgic_v3_dist_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
+		vgic_mmio_read_config, vgic_mmio_write_config, 2,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		VGIC_ACCESS_32bit),
+};
+
+static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		VGIC_ACCESS_32bit),
+};
+
+static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 32,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
+		vgic_mmio_read_config, vgic_mmio_write_config, 8,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+};
+
+unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
+{
+	dev->regions = vgic_v3_dist_registers;
+	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
+
+	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
+
+	return SZ_64K;
+}
+
+int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
+{
+	int nr_vcpus = atomic_read(&kvm->online_vcpus);
+	struct kvm_vcpu *vcpu;
+	struct vgic_io_device *devices;
+	int c, ret = 0;
+
+	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
+			  GFP_KERNEL);
+	if (!devices)
+		return -ENOMEM;
+
+	kvm_for_each_vcpu(c, vcpu, kvm) {
+		gpa_t rd_base = redist_base_address + c * SZ_64K * 2;
+		gpa_t sgi_base = rd_base + SZ_64K;
+		struct vgic_io_device *rd_dev = &devices[c * 2];
+		struct vgic_io_device *sgi_dev = &devices[c * 2 + 1];
+
+		kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops);
+		rd_dev->base_addr = rd_base;
+		rd_dev->regions = vgic_v3_rdbase_registers;
+		rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
+		rd_dev->redist_vcpu = vcpu;
+
+		mutex_lock(&kvm->slots_lock);
+		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base,
+					      SZ_64K, &rd_dev->dev);
+		mutex_unlock(&kvm->slots_lock);
+
+		if (ret)
+			break;
+
+		kvm_iodevice_init(&sgi_dev->dev, &kvm_io_gic_ops);
+		sgi_dev->base_addr = sgi_base;
+		sgi_dev->regions = vgic_v3_sgibase_registers;
+		sgi_dev->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
+		sgi_dev->redist_vcpu = vcpu;
+
+		mutex_lock(&kvm->slots_lock);
+		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, sgi_base,
+					      SZ_64K, &sgi_dev->dev);
+		mutex_unlock(&kvm->slots_lock);
+		if (ret) {
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2].dev);
+			break;
+		}
+	}
+
+	if (ret) {
+		/* The current c failed, so we start with the previous one. */
+		for (c--; c >= 0; c--) {
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2].dev);
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2 + 1].dev);
+		}
+		kfree(devices);
+	} else {
+		kvm->arch.vgic.redist_iodevs = devices;
+	}
+
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 5fe6896..35f49f4 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -478,6 +478,11 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 	case VGIC_V2:
 		len = vgic_v2_init_dist_iodev(io_device);
 		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case VGIC_V3:
+		len = vgic_v3_init_dist_iodev(io_device);
+		break;
+#endif
 	default:
 		BUG_ON(1);
 	}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 0bd0ece..a59f95d 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -133,4 +133,6 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
 
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
+unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
+
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index e57f8d5..6742b11 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -42,6 +42,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
 {
@@ -63,6 +64,12 @@ static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 }
+
+static inline int vgic_register_redist_iodevs(struct kvm *kvm,
+					      gpa_t dist_base_address)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:14 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:14 +0100
Subject: [PATCH v4 26/56] KVM: arm/arm64: vgic-new: Add PENDING registers
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-27-git-send-email-andre.przywara@arm.com>

The pending register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be easily
referenced from the v3 emulation as well later.
For level triggered interrupts the real line level is unaffected by
this write, so we keep this state separate and combine it with the
device's level to get the actual pending state.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog RFC..v1:
- remove IRQ lock from read handler
- remove TODO from clear pending handler

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro
- replace extract_bytes() with simple return

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
 virt/kvm/arm/vgic/vgic-mmio.c    | 60 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 12 ++++++++
 3 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index d5355b5..c13a708 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -78,10 +78,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 32ed8db..d8dc8f6 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -95,6 +95,66 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->pending)
+			value |= (1U << i);
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			irq->soft_pending = true;
+
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
+void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		if (irq->config == VGIC_CONFIG_LEVEL) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		} else {
+			irq->pending = false;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 66fd6fa..01db98a 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -95,6 +95,18 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val);
 
+unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
+void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:33 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:33 +0100
Subject: [PATCH v4 45/56] KVM: arm/arm64: vgic-new: Export register access
 interface
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-46-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Userland can access the emulated GIC to save and restore its state
for initialization or migration purposes.
The kvm_io_bus API requires an absolute gpa, which does not fit the
KVM_DEV_ARM_VGIC_GRP_DIST_REGS user API, that only provides relative
offsets. So we provide a wrapper to plug into our MMIO framework and
find the respective register handler.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework
- handle endianess explicitly

Changelog v2 .. v3:
- wrap accessor function for easier reusage later
- moved from earlier in the series

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 36 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 2 files changed, 38 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 7189690..a255122 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -296,3 +296,39 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 
 	return -ENXIO;
 }
+
+/*
+ * When userland tries to access the VGIC register handlers, we need to
+ * create a usable struct vgic_io_device to be passed to the handlers and we
+ * have to set up a buffer similar to what would have happened if a guest MMIO
+ * access occurred, including doing endian conversions on BE systems.
+ */
+static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
+			bool is_write, int offset, u32 *val)
+{
+	unsigned int len = 4;
+	u8 buf[4];
+	int ret;
+
+	if (is_write) {
+		vgic_data_host_to_mmio_bus(buf, len, *val);
+		ret = kvm_io_gic_ops.write(vcpu, &dev->dev, offset, len, buf);
+	} else {
+		ret = kvm_io_gic_ops.read(vcpu, &dev->dev, offset, len, buf);
+		if (!ret)
+			*val = vgic_data_mmio_bus_to_host(buf, len);
+	}
+
+	return ret;
+}
+
+int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			 int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_dist_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_dist_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index a264c5f..f826026 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -38,6 +38,8 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
+int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			 int offset, u32 *val);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:06 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:06 +0100
Subject: [PATCH v4 18/56] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-19-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Implement the framework for syncing IRQs between our emulation and
the list registers, which represent the guest's view of IRQs.
This is done in kvm_vgic_flush_hwstate and kvm_vgic_sync_hwstate,
which gets called on guest entry and exit.
The code talking to the actual GICv2/v3 hardware is added in the
following patches.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- split out vgic_clear_lr() from vgic_populate_lr()
- rename vgic_populate_lrs() to vgic_flush_lr_state()
- clean all LRs when the distributor is disabled
- use list_del() instead of list_del_init()
- add comments to explain the direction of sync/flush_hwstate
- remove unneeded BUG_ON(in_interrupt()

Changelog v2 .. v3:
- remove bogus v2 specific rebase leftovers

Changelog v3 .. v4:
- amend locks requirements

 include/kvm/vgic/vgic.h  |   4 +
 virt/kvm/arm/vgic/vgic.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h |   2 +
 3 files changed, 197 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 7b6ca90..9506267 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -190,6 +190,10 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
 			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
 
+bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
+void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
+void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
+
 /**
  * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
  *
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 1bc8f92..613fbd1 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -307,3 +307,194 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 {
 	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
 }
+
+/**
+ * vgic_prune_ap_list - Remove non-relevant interrupts from the list
+ *
+ * @vcpu: The VCPU pointer
+ *
+ * Go over the list of "interesting" interrupts, and prune those that we
+ * won't have to consider in the near future.
+ */
+static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq, *tmp;
+
+retry:
+	spin_lock(&vgic_cpu->ap_list_lock);
+
+	list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
+		struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
+
+		spin_lock(&irq->irq_lock);
+
+		BUG_ON(vcpu != irq->vcpu);
+
+		target_vcpu = vgic_target_oracle(irq);
+
+		if (!target_vcpu) {
+			/*
+			 * We don't need to process this interrupt any
+			 * further, move it off the list.
+			 */
+			list_del(&irq->ap_list);
+			irq->vcpu = NULL;
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		if (target_vcpu == vcpu) {
+			/* We're on the right CPU */
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		/* This interrupt looks like it has to be migrated. */
+
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vgic_cpu->ap_list_lock);
+
+		/*
+		 * Ensure locking order by always locking the smallest
+		 * ID first.
+		 */
+		if (vcpu->vcpu_id < target_vcpu->vcpu_id) {
+			vcpuA = vcpu;
+			vcpuB = target_vcpu;
+		} else {
+			vcpuA = target_vcpu;
+			vcpuB = vcpu;
+		}
+
+		spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+		spin_lock(&vcpuB->arch.vgic_cpu.ap_list_lock);
+		spin_lock(&irq->irq_lock);
+
+		/*
+		 * If the affinity has been preserved, move the
+		 * interrupt around. Otherwise, it means things have
+		 * changed while the interrupt was unlocked, and we
+		 * need to replay this.
+		 *
+		 * In all cases, we cannot trust the list not to have
+		 * changed, so we restart from the beginning.
+		 */
+		if (target_vcpu == vgic_target_oracle(irq)) {
+			struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;
+
+			list_del(&irq->ap_list);
+			irq->vcpu = target_vcpu;
+			list_add_tail(&irq->ap_list, &new_cpu->ap_list_head);
+		}
+
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
+		spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+		goto retry;
+	}
+
+	spin_unlock(&vgic_cpu->ap_list_lock);
+}
+
+static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+}
+
+/* Requires the irq_lock to be held. */
+static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
+				    struct vgic_irq *irq, int lr)
+{
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+}
+
+static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+}
+
+static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
+{
+}
+
+/* Requires the ap_list_lock to be held. */
+static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	int count = 0;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+		/* GICv2 SGIs can count for more than one... */
+		if (vgic_irq_is_sgi(irq->intid) && irq->source)
+			count += hweight8(irq->source);
+		else
+			count++;
+		spin_unlock(&irq->irq_lock);
+	}
+	return count;
+}
+
+/* Requires the VCPU's ap_list_lock to be held. */
+static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	int count = 0;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	if (compute_ap_list_depth(vcpu) > kvm_vgic_global_state.nr_lr) {
+		vgic_set_underflow(vcpu);
+		vgic_sort_ap_list(vcpu);
+	}
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+
+		if (unlikely(vgic_target_oracle(irq) != vcpu))
+			goto next;
+
+		/*
+		 * If we get an SGI with multiple sources, try to get
+		 * them in all at once.
+		 */
+		do {
+			vgic_populate_lr(vcpu, irq, count++);
+		} while (irq->source && count < kvm_vgic_global_state.nr_lr);
+
+next:
+		spin_unlock(&irq->irq_lock);
+
+		if (count == kvm_vgic_global_state.nr_lr)
+			break;
+	}
+
+	vcpu->arch.vgic_cpu.used_lrs = count;
+
+	/* Nuke remaining LRs */
+	for ( ; count < kvm_vgic_global_state.nr_lr; count++)
+		vgic_clear_lr(vcpu, count);
+}
+
+/* Sync back the hardware VGIC state into our emulation after a guest's run. */
+void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
+{
+	vgic_process_maintenance_interrupt(vcpu);
+	vgic_fold_lr_state(vcpu);
+	vgic_prune_ap_list(vcpu);
+}
+
+/* Flush our emulation state into the GIC hardware before entering the guest. */
+void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
+{
+	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+	vgic_flush_lr_state(vcpu);
+	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index c625767..29b96b9 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,6 +16,8 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:36 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:36 +0100
Subject: [PATCH v4 48/56] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-49-git-send-email-andre.przywara@arm.com>

Using the VMCR accessors we provide access to GIC CPU interface state
to userland by wiring it up to the existing userland interface.
[Marc: move and make VMCR accessors static, streamline MMIO handlers]

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog v2 .. v3:
- total rework, moving into vgic-mmio-v2.c
- move vmcr accessor wrapper functions into this file
- use the register description table for CPU i/f registers as well
- add RAZ/WI handling for the active priority registers
- streamline MMIO handler functions

Changelog v3 .. v4:
- advertise CPU interface registers to userland
- specify accessor width
- replace call to extract_bytes() with a simple return

 virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 114 +++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.h            |   2 +
 3 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index c3ec453..237d753 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -274,7 +274,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		ret = -EINVAL;
+		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
 		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index a255122..a213936 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -204,6 +204,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_set_vmcr(vcpu, vmcr);
+	else
+		vgic_v3_set_vmcr(vcpu, vmcr);
+}
+
+static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_get_vmcr(vcpu, vmcr);
+	else
+		vgic_v3_get_vmcr(vcpu, vmcr);
+}
+
+#define GICC_ARCH_VERSION_V2	0x2
+
+/* These are for userland accesses only, there is no guest-facing emulation. */
+static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
+					   gpa_t addr, unsigned int len)
+{
+	struct vgic_vmcr vmcr;
+	u32 val;
+
+	vgic_get_vmcr(vcpu, &vmcr);
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		val = vmcr.ctlr;
+		break;
+	case GIC_CPU_PRIMASK:
+		val = vmcr.pmr;
+		break;
+	case GIC_CPU_BINPOINT:
+		val = vmcr.bpr;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		val = vmcr.abpr;
+		break;
+	case GIC_CPU_IDENT:
+		val = ((PRODUCT_ID_KVM << 20) |
+		       (GICC_ARCH_VERSION_V2 << 16) |
+		       IMPLEMENTER_ARM);
+		break;
+	default:
+		return 0;
+	}
+
+	return val;
+}
+
+static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
+				   gpa_t addr, unsigned int len,
+				   unsigned long val)
+{
+	struct vgic_vmcr vmcr;
+
+	vgic_get_vmcr(vcpu, &vmcr);
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		vmcr.ctlr = val;
+		break;
+	case GIC_CPU_PRIMASK:
+		vmcr.pmr = val;
+		break;
+	case GIC_CPU_BINPOINT:
+		vmcr.bpr = val;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		vmcr.abpr = val;
+		break;
+	}
+
+	vgic_set_vmcr(vcpu, &vmcr);
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
@@ -249,6 +327,27 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 };
 
+static const struct vgic_register_region vgic_v2_cpu_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_CTRL,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_PRIMASK,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ALIAS_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ACTIVEPRIO,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_IDENT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+};
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
 {
 	dev->regions = vgic_v2_dist_registers;
@@ -274,7 +373,9 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		return -ENXIO;		/* TODO: describe CPU i/f regs also */
+		regions = vgic_v2_cpu_registers;
+		nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers);
+		break;
 	default:
 		return -ENXIO;
 	}
@@ -322,6 +423,17 @@ static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
 	return ret;
 }
 
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_cpu_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
+
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val)
 {
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index d2c1fd5..de9dc71 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -47,6 +47,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val);
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:22 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:22 +0100
Subject: [PATCH v4 34/56] KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR,
 TYPER handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-35-git-send-email-andre.przywara@arm.com>

As in the GICv2 emulation we handle those three registers in one
function.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- kick VCPUs if distributor gets enabled

Changelog v1 .. v2:
- rewrite write handler to use switch statement

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 48 +++++++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.h         |  1 +
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 31f1a13..f11ef46 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -22,6 +22,52 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 value = 0;
+
+	switch (addr & 0x0c) {
+	case GICD_CTLR:
+		if (vcpu->kvm->arch.vgic.enabled)
+			value |= GICD_CTLR_ENABLE_SS_G1;
+		value |= GICD_CTLR_ARE_NS | GICD_CTLR_DS;
+		break;
+	case GICD_TYPER:
+		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+		value = (value >> 5) - 1;
+		value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19;
+		break;
+	case GICD_IIDR:
+		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+		break;
+	default:
+		return 0;
+	}
+
+	return value;
+}
+
+static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+	bool was_enabled = dist->enabled;
+
+	switch (addr & 0x0c) {
+	case GICD_CTLR:
+		dist->enabled = val & GICD_CTLR_ENABLE_SS_G1;
+
+		if (!was_enabled && dist->enabled)
+			vgic_kick_vcpus(vcpu->kvm);
+		break;
+	case GICD_TYPER:
+	case GICD_IIDR:
+		return;
+	}
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -48,7 +94,7 @@
 
 static const struct vgic_register_region vgic_v3_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc, 16,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 6742b11..44c6a1b 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,7 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define INTERRUPT_ID_BITS_SPIS	10
 #define VGIC_PRI_BITS		5
 
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:38 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:38 +0100
Subject: [PATCH v4 50/56] KVM: arm/arm64: vgic-new: vgic_init: implement
 vgic_create
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-51-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the vgic_creation function which is
called on CREATE_IRQCHIP VM IOCTL (v2 only) or KVM_CREATE_DEVICE

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v3 .. v4:
- fix comment

 include/kvm/vgic/vgic.h       |  1 +
 virt/kvm/arm/vgic/vgic-init.c | 84 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 393489f..0634d89 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -195,6 +195,7 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+int kvm_vgic_create(struct kvm *kvm, u32 type);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 4523beb..15d5428 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -22,6 +22,90 @@
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
+/* CREATION */
+
+/**
+ * kvm_vgic_create: triggered by the instantiation of the VGIC device by
+ * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only)
+ * or through the generic KVM_CREATE_DEVICE API ioctl.
+ * irqchip_in_kernel() tells you if this function succeeded or not.
+ */
+int kvm_vgic_create(struct kvm *kvm, u32 type)
+{
+	int i, vcpu_lock_idx = -1, ret;
+	struct kvm_vcpu *vcpu;
+
+	mutex_lock(&kvm->lock);
+
+	if (irqchip_in_kernel(kvm)) {
+		ret = -EEXIST;
+		goto out;
+	}
+
+	/*
+	 * This function is also called by the KVM_CREATE_IRQCHIP handler,
+	 * which had no chance yet to check the availability of the GICv2
+	 * emulation. So check this here again. KVM_CREATE_DEVICE does
+	 * the proper checks already.
+	 */
+	if (type == KVM_DEV_TYPE_ARM_VGIC_V2 &&
+		!kvm_vgic_global_state.can_emulate_gicv2) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/*
+	 * Any time a vcpu is run, vcpu_load is called which tries to grab the
+	 * vcpu->mutex.  By grabbing the vcpu->mutex of all VCPUs we ensure
+	 * that no other VCPUs are run while we create the vgic.
+	 */
+	ret = -EBUSY;
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		if (!mutex_trylock(&vcpu->mutex))
+			goto out_unlock;
+		vcpu_lock_idx = i;
+	}
+
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		if (vcpu->arch.has_run_once)
+			goto out_unlock;
+	}
+	ret = 0;
+
+	if (type == KVM_DEV_TYPE_ARM_VGIC_V2)
+		kvm->arch.max_vcpus = VGIC_V2_MAX_CPUS;
+	else
+		kvm->arch.max_vcpus = VGIC_V3_MAX_CPUS;
+
+	if (atomic_read(&kvm->online_vcpus) > kvm->arch.max_vcpus) {
+		ret = -E2BIG;
+		goto out_unlock;
+	}
+
+	kvm->arch.vgic.in_kernel = true;
+	kvm->arch.vgic.vgic_model = type;
+
+	/*
+	 * kvm_vgic_global_state.vctrl_base is set on vgic probe (kvm_arch_init)
+	 * it is stored in distributor struct for asm save/restore purpose
+	 */
+	kvm->arch.vgic.vctrl_base = kvm_vgic_global_state.vctrl_base;
+
+	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
+	kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
+	kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
+
+out_unlock:
+	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
+		vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
+		mutex_unlock(&vcpu->mutex);
+	}
+
+out:
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:40 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:40 +0100
Subject: [PATCH v4 52/56] KVM: arm/arm64: vgic-new: vgic_init: implement
 map_resources
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-53-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

map_resources is the last initialization step. It is executed on
first VCPU run. At that stage the code checks that userspace has provided
the base addresses for the relevant VGIC regions, which depend on the
type of VGIC that is exposed to the guest.  Also we check if the two
regions overlap.
If the checks succeeded, we register the respective register frames with
the kvm_io_bus framework.

If we emulate a GICv2, the function also forces vgic_init execution if
it has not been executed yet. Also we map the virtual GIC CPU interface
onto the guest's CPU interface.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v3 .. v4:
- add overlap check (moved from kvm_vgic_addr())
- reword commit message
- improve comment

 include/kvm/vgic/vgic.h       |  1 +
 virt/kvm/arm/vgic/vgic-init.c | 28 +++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   | 69 +++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c   | 71 +++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h      |  7 +++++
 5 files changed, 176 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index e7ae36b..17b2a73 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -201,6 +201,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type);
 void kvm_vgic_destroy(struct kvm *kvm);
 void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
+int kvm_vgic_map_resources(struct kvm *kvm);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index bed3240..a1442f7 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -323,6 +323,34 @@ int vgic_lazy_init(struct kvm *kvm)
 	return ret;
 }
 
+/* RESOURCE MAPPING */
+
+/**
+ * Map the MMIO regions depending on the VGIC model exposed to the guest
+ * called on the first VCPU run.
+ * Also map the virtual CPU interface into the VM.
+ * v2/v3 derivatives call vgic_init if not already done.
+ * vgic_ready() returns true if this function has succeeded.
+ * @kvm: kvm struct pointer
+ */
+int kvm_vgic_map_resources(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	int ret = 0;
+
+	mutex_lock(&kvm->lock);
+	if (!irqchip_in_kernel(kvm))
+		goto out;
+
+	if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+		ret = vgic_v2_map_resources(kvm);
+	else
+		ret = vgic_v3_map_resources(kvm);
+out:
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index fcbfa38..1fe031b 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -211,6 +211,75 @@ void vgic_v2_enable(struct kvm_vcpu *vcpu)
 {
 }
 
+/* check for overlapping regions and for regions crossing the end of memory */
+static bool vgic_v2_check_base(gpa_t dist_base, gpa_t cpu_base)
+{
+	if (dist_base + KVM_VGIC_V2_DIST_SIZE < dist_base)
+		return false;
+	if (cpu_base + KVM_VGIC_V2_CPU_SIZE < cpu_base)
+		return false;
+
+	if (dist_base + KVM_VGIC_V2_DIST_SIZE <= cpu_base)
+		return true;
+	if (cpu_base + KVM_VGIC_V2_CPU_SIZE <= dist_base)
+		return true;
+
+	return false;
+}
+
+int vgic_v2_map_resources(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	int ret = 0;
+
+	if (vgic_ready(kvm))
+		goto out;
+
+	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
+	    IS_VGIC_ADDR_UNDEF(dist->vgic_cpu_base)) {
+		kvm_err("Need to set vgic cpu and dist addresses first\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	if (!vgic_v2_check_base(dist->vgic_dist_base, dist->vgic_cpu_base)) {
+		kvm_err("VGIC CPU and dist frames overlap\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Initialize the vgic if this hasn't already been done on demand by
+	 * accessing the vgic state from userspace.
+	 */
+	ret = vgic_init(kvm);
+	if (ret) {
+		kvm_err("Unable to initialize VGIC dynamic data structures\n");
+		goto out;
+	}
+
+	ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V2);
+	if (ret) {
+		kvm_err("Unable to register VGIC MMIO regions\n");
+		goto out;
+	}
+
+	ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base,
+				    kvm_vgic_global_state.vcpu_base,
+				    KVM_VGIC_V2_CPU_SIZE, true);
+	if (ret) {
+		kvm_err("Unable to remap VGIC CPU to VCPU\n");
+		goto out;
+	}
+
+	dist->ready = true;
+
+out:
+	if (ret)
+		kvm_vgic_destroy(kvm);
+	return ret;
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index d1c0285..637ff2b 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -191,6 +191,77 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
 }
 
+/* check for overlapping regions and for regions crossing the end of memory */
+static bool vgic_v3_check_base(struct kvm *kvm)
+{
+	struct vgic_dist *d = &kvm->arch.vgic;
+	gpa_t redist_size = KVM_VGIC_V3_REDIST_SIZE;
+
+	redist_size *= atomic_read(&kvm->online_vcpus);
+
+	if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base)
+		return false;
+	if (d->vgic_redist_base + redist_size < d->vgic_redist_base)
+		return false;
+
+	if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE <= d->vgic_redist_base)
+		return true;
+	if (d->vgic_redist_base + redist_size <= d->vgic_dist_base)
+		return true;
+
+	return false;
+}
+
+int vgic_v3_map_resources(struct kvm *kvm)
+{
+	int ret = 0;
+	struct vgic_dist *dist = &kvm->arch.vgic;
+
+	if (vgic_ready(kvm))
+		goto out;
+
+	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
+	    IS_VGIC_ADDR_UNDEF(dist->vgic_redist_base)) {
+		kvm_err("Need to set vgic distributor addresses first\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	if (!vgic_v3_check_base(kvm)) {
+		kvm_err("VGIC redist and dist frames overlap\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * For a VGICv3 we require the userland to explicitly initialize
+	 * the VGIC before we need to use it.
+	 */
+	if (!vgic_initialized(kvm)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V3);
+	if (ret) {
+		kvm_err("Unable to register VGICv3 dist MMIO regions\n");
+		goto out;
+	}
+
+	ret = vgic_register_redist_iodevs(kvm, dist->vgic_redist_base);
+	if (ret) {
+		kvm_err("Unable to register VGICv3 redist MMIO regions\n");
+		goto out;
+	}
+
+	dist->ready = true;
+
+out:
+	if (ret)
+		kvm_vgic_destroy(kvm);
+	return ret;
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 5951551..7b300ca 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -55,6 +55,7 @@ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_enable(struct kvm_vcpu *vcpu);
 int vgic_v2_probe(const struct gic_kvm_info *info);
+int vgic_v2_map_resources(struct kvm *kvm);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -68,6 +69,7 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_enable(struct kvm_vcpu *vcpu);
 int vgic_v3_probe(const struct gic_kvm_info *info);
+int vgic_v3_map_resources(struct kvm *kvm);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -110,6 +112,11 @@ static inline int vgic_v3_probe(const struct gic_kvm_info *info)
 	return -ENODEV;
 }
 
+static inline int vgic_v3_map_resources(struct kvm *kvm)
+{
+	return -ENODEV;
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:37 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:37 +0100
Subject: [PATCH v4 49/56] KVM: arm/arm64: vgic-new: vgic_init: implement
 kvm_vgic_hyp_init
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-50-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

Implements kvm_vgic_hyp_init and vgic_probe function.
This uses the new firmware independent VGIC probing to support both ACPI
and DT based systems (code from Marc Zyngier).

The vgic_global struct is enriched with new fields populated
by those functions.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- rename vgic_init.c to vgic-init.c

Changelog v2 .. v3:
- include kvm/arm_vgic.h instead of kvm/vgic/vgic.h
- move ich_vtr_el2 variable into probe function

Changelog v3 .. v4:
- improve nr_lr determination in GICv2 probe
- switching to firmware-independent probing

 include/kvm/vgic/vgic.h       |   1 +
 virt/kvm/arm/vgic/vgic-init.c | 123 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   |  64 ++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c   |  49 +++++++++++++++++
 virt/kvm/arm/vgic/vgic.h      |   9 ++++
 5 files changed, 246 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-init.c

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 3689b9b..393489f 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -195,6 +195,7 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
new file mode 100644
index 0000000..4523beb
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/cpu.h>
+#include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
+#include "vgic.h"
+
+/* GENERIC PROBE */
+
+static void vgic_init_maintenance_interrupt(void *info)
+{
+	enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0);
+}
+
+static int vgic_cpu_notify(struct notifier_block *self,
+			   unsigned long action, void *cpu)
+{
+	switch (action) {
+	case CPU_STARTING:
+	case CPU_STARTING_FROZEN:
+		vgic_init_maintenance_interrupt(NULL);
+		break;
+	case CPU_DYING:
+	case CPU_DYING_FROZEN:
+		disable_percpu_irq(kvm_vgic_global_state.maint_irq);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block vgic_cpu_nb = {
+	.notifier_call = vgic_cpu_notify,
+};
+
+static irqreturn_t vgic_maintenance_handler(int irq, void *data)
+{
+	/*
+	 * We cannot rely on the vgic maintenance interrupt to be
+	 * delivered synchronously. This means we can only use it to
+	 * exit the VM, and we perform the handling of EOIed
+	 * interrupts on the exit path (see vgic_process_maintenance).
+	 */
+	return IRQ_HANDLED;
+}
+
+/**
+ * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable
+ * according to the host GIC model. Accordingly calls either
+ * vgic_v2/v3_probe which registers the KVM_DEVICE that can be
+ * instantiated by a guest later on .
+ */
+int kvm_vgic_hyp_init(void)
+{
+	const struct gic_kvm_info *gic_kvm_info;
+	int ret;
+
+	gic_kvm_info = gic_get_kvm_info();
+	if (!gic_kvm_info)
+		return -ENODEV;
+
+	if (!gic_kvm_info->maint_irq) {
+		kvm_err("No vgic maintenance irq\n");
+		return -ENXIO;
+	}
+
+	switch (gic_kvm_info->type) {
+	case GIC_V2:
+		ret = vgic_v2_probe(gic_kvm_info);
+		break;
+	case GIC_V3:
+		ret = vgic_v3_probe(gic_kvm_info);
+		break;
+	default:
+		ret = -ENODEV;
+	};
+
+	if (ret)
+		return ret;
+
+	kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
+	ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
+				 vgic_maintenance_handler,
+				 "vgic", kvm_get_running_vcpus());
+	if (ret) {
+		kvm_err("Cannot register interrupt %d\n",
+			kvm_vgic_global_state.maint_irq);
+		return ret;
+	}
+
+	ret = __register_cpu_notifier(&vgic_cpu_nb);
+	if (ret) {
+		kvm_err("Cannot register vgic CPU notifier\n");
+		goto out_free_irq;
+	}
+
+	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
+
+	kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq);
+	return 0;
+
+out_free_irq:
+	free_percpu_irq(kvm_vgic_global_state.maint_irq,
+			kvm_get_running_vcpus());
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index d943059..09777c8 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -17,6 +17,8 @@
 #include <linux/irqchip/arm-gic.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
 
 #include "vgic.h"
 
@@ -203,3 +205,65 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
 			GICH_VMCR_PRIMASK_SHIFT;
 }
+
+/**
+ * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
+ * @node:	pointer to the DT node
+ *
+ * Returns 0 if a GICv2 has been found, returns an error code otherwise
+ */
+int vgic_v2_probe(const struct gic_kvm_info *info)
+{
+	int ret;
+	u32 vtr;
+
+	if (!info->vctrl.start) {
+		kvm_err("GICH not present in the firmware table\n");
+		return -ENXIO;
+	}
+
+	if (!PAGE_ALIGNED(info->vcpu.start)) {
+		kvm_err("GICV physical address 0x%llx not page aligned\n",
+			(unsigned long long)info->vcpu.start);
+		return -ENXIO;
+	}
+
+	if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
+		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+			(unsigned long long)resource_size(&info->vcpu),
+			PAGE_SIZE);
+		return -ENXIO;
+	}
+
+	kvm_vgic_global_state.vctrl_base = ioremap(info->vctrl.start,
+						   resource_size(&info->vctrl));
+	if (!kvm_vgic_global_state.vctrl_base) {
+		kvm_err("Cannot ioremap GICH\n");
+		return -ENOMEM;
+	}
+
+	vtr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
+	kvm_vgic_global_state.nr_lr = (vtr & 0x3f) + 1;
+
+	ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
+				     kvm_vgic_global_state.vctrl_base +
+					 resource_size(&info->vctrl),
+				     info->vctrl.start);
+
+	if (ret) {
+		kvm_err("Cannot map VCTRL into hyp\n");
+		iounmap(kvm_vgic_global_state.vctrl_base);
+		return ret;
+	}
+
+	kvm_vgic_global_state.can_emulate_gicv2 = true;
+	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+
+	kvm_vgic_global_state.vcpu_base = info->vcpu.start;
+	kvm_vgic_global_state.type = VGIC_V2;
+	kvm_vgic_global_state.max_gic_vcpus = VGIC_V2_MAX_CPUS;
+
+	kvm_info("vgic-v2@%llx\n", info->vctrl.start);
+
+	return 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 8548297..de0e8e0 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -15,6 +15,9 @@
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
+#include <asm/kvm_asm.h>
 
 #include "vgic.h"
 
@@ -182,3 +185,49 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
+
+/**
+ * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
+ * @node:	pointer to the DT node
+ *
+ * Returns 0 if a GICv3 has been found, returns an error code otherwise
+ */
+int vgic_v3_probe(const struct gic_kvm_info *info)
+{
+	u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
+
+	/*
+	 * The ListRegs field is 5 bits, but there is a architectural
+	 * maximum of 16 list registers. Just ignore bit 4...
+	 */
+	kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
+	kvm_vgic_global_state.can_emulate_gicv2 = false;
+
+	if (!info->vcpu.start) {
+		kvm_info("GICv3: no GICV resource entry\n");
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else if (!PAGE_ALIGNED(info->vcpu.start)) {
+		pr_warn("GICV physical address 0x%llx not page aligned\n",
+			(unsigned long long)info->vcpu.start);
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
+		pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+			(unsigned long long)resource_size(&info->vcpu),
+			PAGE_SIZE);
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else {
+		kvm_vgic_global_state.vcpu_base = info->vcpu.start;
+		kvm_vgic_global_state.can_emulate_gicv2 = true;
+		kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+		kvm_info("vgic-v2@%llx\n", info->vcpu.start);
+	}
+	if (kvm_vgic_global_state.vcpu_base == 0)
+		kvm_info("disabling GICv2 emulation\n");
+	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V3);
+
+	kvm_vgic_global_state.vctrl_base = NULL;
+	kvm_vgic_global_state.type = VGIC_V3;
+	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
+
+	return 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index de9dc71..f4244b6 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,6 +16,8 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#include <linux/irqchip/arm-gic-common.h>
+
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
@@ -51,6 +53,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+int vgic_v2_probe(const struct gic_kvm_info *info);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -62,6 +65,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+int vgic_v3_probe(const struct gic_kvm_info *info);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -95,6 +99,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
 {
 }
 
+static inline int vgic_v3_probe(const struct gic_kvm_info *info)
+{
+	return -ENODEV;
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:41 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:41 +0100
Subject: [PATCH v4 53/56] KVM: arm/arm64: vgic-new: Add vgic_v2/v3_enable
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-54-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

Enable the VGIC operation by properly initialising the registers
in the hypervisor GIC interface.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-v2.c | 11 ++++++++++-
 virt/kvm/arm/vgic/vgic-v3.c | 23 ++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 1fe031b..8ad42c2 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -206,9 +206,18 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 			GICH_VMCR_PRIMASK_SHIFT;
 }
 
-/* not yet implemented */
 void vgic_v2_enable(struct kvm_vcpu *vcpu)
 {
+	/*
+	 * By forcing VMCR to zero, the GIC will restore the binary
+	 * points to their reset values. Anything else resets to zero
+	 * anyway.
+	 */
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = 0;
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr = ~0;
+
+	/* Get the show on the road... */
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr = GICH_HCR_EN;
 }
 
 /* check for overlapping regions and for regions crossing the end of memory */
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 637ff2b..336a461 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -186,9 +186,30 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
 
-/* not yet implemented */
 void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
+	struct vgic_v3_cpu_if *vgic_v3 = &vcpu->arch.vgic_cpu.vgic_v3;
+
+	/*
+	 * By forcing VMCR to zero, the GIC will restore the binary
+	 * points to their reset values. Anything else resets to zero
+	 * anyway.
+	 */
+	vgic_v3->vgic_vmcr = 0;
+	vgic_v3->vgic_elrsr = ~0;
+
+	/*
+	 * If we are emulating a GICv3, we do it in an non-GICv2-compatible
+	 * way, so we force SRE to 1 to demonstrate this to the guest.
+	 * This goes with the spec allowing the value to be RAO/WI.
+	 */
+	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+		vgic_v3->vgic_sre = ICC_SRE_EL1_SRE;
+	else
+		vgic_v3->vgic_sre = 0;
+
+	/* Get the show on the road... */
+	vgic_v3->vgic_hcr = ICH_HCR_EN;
 }
 
 /* check for overlapping regions and for regions crossing the end of memory */
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:42 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:42 +0100
Subject: [PATCH v4 54/56] KVM: arm/arm64: vgic-new: Wire up irqfd injection
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-55-git-send-email-andre.przywara@arm.com>

Connect to the new VGIC to the irqfd framework, so that we can
inject IRQs.
GSI routing and MSI routing is not yet implemented.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-irqfd.c | 52 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-irqfd.c

diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
new file mode 100644
index 0000000..c675513
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/kvm.h>
+#include <linux/kvm_host.h>
+#include <trace/events/kvm.h>
+
+int kvm_irq_map_gsi(struct kvm *kvm,
+		    struct kvm_kernel_irq_routing_entry *entries,
+		    int gsi)
+{
+	return 0;
+}
+
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned int irqchip,
+			 unsigned int pin)
+{
+	return pin;
+}
+
+int kvm_set_irq(struct kvm *kvm, int irq_source_id,
+		u32 irq, int level, bool line_status)
+{
+	unsigned int spi = irq + VGIC_NR_PRIVATE_IRQS;
+
+	trace_kvm_set_irq(irq, level, irq_source_id);
+
+	BUG_ON(!vgic_initialized(kvm));
+
+	return kvm_vgic_inject_irq(kvm, 0, spi, level);
+}
+
+/* MSI not implemented yet */
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
+		struct kvm *kvm, int irq_source_id,
+		int level, bool line_status)
+{
+	return 0;
+}
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:39 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:39 +0100
Subject: [PATCH v4 51/56] KVM: arm/arm64: vgic-new: vgic_init: implement
 vgic_init
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-52-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch allocates and initializes the data structures used
to model the vgic distributor and virtual cpu interfaces. At that
stage the number of IRQs and number of virtual CPUs is frozen.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- initialize v2/v3 default CPU affinities explicitly

Changelog v1 .. v2:
- move lazy_init() into vgic_update_irq_pending()

Changelog v3 .. v4:
- fix comments
- make local functions static
- adapt to new firmware independent probing

 include/kvm/vgic/vgic.h       |   7 +-
 virt/kvm/arm/vgic/vgic-init.c | 217 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   |   5 +
 virt/kvm/arm/vgic/vgic-v3.c   |   5 +
 virt/kvm/arm/vgic/vgic.c      |   4 +
 virt/kvm/arm/vgic/vgic.h      |   8 ++
 6 files changed, 245 insertions(+), 1 deletion(-)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 0634d89..e7ae36b 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -119,6 +119,7 @@ struct vgic_io_device {
 struct vgic_dist {
 	bool			in_kernel;
 	bool			ready;
+	bool			initialized;
 
 	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
 	u32			vgic_model;
@@ -195,7 +196,11 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+void kvm_vgic_early_init(struct kvm *kvm);
 int kvm_vgic_create(struct kvm *kvm, u32 type);
+void kvm_vgic_destroy(struct kvm *kvm);
+void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
+void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
@@ -204,7 +209,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
-#define vgic_initialized(k)	(false)
+#define vgic_initialized(k)	((k)->arch.vgic.initialized)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
 #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
 			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 15d5428..bed3240 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -22,6 +22,42 @@
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
+/*
+ * Initialization rules: there are multiple stages to the vgic
+ * initialization, both for the distributor and the CPU interfaces.
+ *
+ * Distributor:
+ *
+ * - kvm_vgic_early_init(): initialization of static data that doesn't
+ *   depend on any sizing information or emulation type. No allocation
+ *   is allowed there.
+ *
+ * - vgic_init(): allocation and initialization of the generic data
+ *   structures that depend on sizing information (number of CPUs,
+ *   number of interrupts). Also initializes the vcpu specific data
+ *   structures. Can be executed lazily for GICv2.
+ *
+ * CPU Interface:
+ *
+ * - kvm_vgic_cpu_early_init(): initialization of static data that
+ *   doesn't depend on any sizing information or emulation type. No
+ *   allocation is allowed there.
+ */
+
+/* EARLY INIT */
+
+/*
+ * Those 2 functions should not be needed anymore but they
+ * still are called from arm.c
+ */
+void kvm_vgic_early_init(struct kvm *kvm)
+{
+}
+
+void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu)
+{
+}
+
 /* CREATION */
 
 /**
@@ -29,6 +65,8 @@
  * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only)
  * or through the generic KVM_CREATE_DEVICE API ioctl.
  * irqchip_in_kernel() tells you if this function succeeded or not.
+ * @kvm: kvm struct pointer
+ * @type: KVM_DEV_TYPE_ARM_VGIC_V[23]
  */
 int kvm_vgic_create(struct kvm *kvm, u32 type)
 {
@@ -106,6 +144,185 @@ out:
 	return ret;
 }
 
+/* INIT/DESTROY */
+
+/**
+ * kvm_vgic_dist_init: initialize the dist data structures
+ * @kvm: kvm struct pointer
+ * @nr_spis: number of spis, frozen by caller
+ */
+static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct kvm_vcpu *vcpu0 = kvm_get_vcpu(kvm, 0);
+	int i;
+
+	dist->spis = kcalloc(nr_spis, sizeof(struct vgic_irq), GFP_KERNEL);
+	if (!dist->spis)
+		return  -ENOMEM;
+
+	/*
+	 * In the following code we do not take the irq struct lock since
+	 * no other action on irq structs can happen while the VGIC is
+	 * not initialized yet:
+	 * If someone wants to inject an interrupt or does a MMIO access, we
+	 * require prior initialization in case of a virtual GICv3 or trigger
+	 * initialization when using a virtual GICv2.
+	 */
+	for (i = 0; i < nr_spis; i++) {
+		struct vgic_irq *irq = &dist->spis[i];
+
+		irq->intid = i + VGIC_NR_PRIVATE_IRQS;
+		INIT_LIST_HEAD(&irq->ap_list);
+		spin_lock_init(&irq->irq_lock);
+		irq->vcpu = NULL;
+		irq->target_vcpu = vcpu0;
+		if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+			irq->targets = 0;
+		else
+			irq->mpidr = 0;
+	}
+	return 0;
+}
+
+/**
+ * kvm_vgic_vcpu_init: initialize the vcpu data structures and
+ * enable the VCPU interface
+ * @vcpu: the VCPU which's VGIC should be initialized
+ */
+static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	int i;
+
+	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
+	spin_lock_init(&vgic_cpu->ap_list_lock);
+
+	/*
+	 * Enable and configure all SGIs to be edge-triggered and
+	 * configure all PPIs as level-triggered.
+	 */
+	for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
+		struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
+
+		INIT_LIST_HEAD(&irq->ap_list);
+		spin_lock_init(&irq->irq_lock);
+		irq->intid = i;
+		irq->vcpu = NULL;
+		irq->target_vcpu = vcpu;
+		irq->targets = 1U << vcpu->vcpu_id;
+		if (vgic_irq_is_sgi(i)) {
+			/* SGIs */
+			irq->enabled = 1;
+			irq->config = VGIC_CONFIG_EDGE;
+		} else {
+			/* PPIs */
+			irq->config = VGIC_CONFIG_LEVEL;
+		}
+	}
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_enable(vcpu);
+	else
+		vgic_v3_enable(vcpu);
+}
+
+/*
+ * vgic_init: allocates and initializes dist and vcpu data structures
+ * depending on two dimensioning parameters:
+ * - the number of spis
+ * - the number of vcpus
+ * The function is generally called when nr_spis has been explicitly set
+ * by the guest through the KVM DEVICE API. If not nr_spis is set to 256.
+ * vgic_initialized() returns true when this function has succeeded.
+ * Must be called with kvm->lock held!
+ */
+int vgic_init(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct kvm_vcpu *vcpu;
+	int ret = 0, i;
+
+	if (vgic_initialized(kvm))
+		return 0;
+
+	/* freeze the number of spis */
+	if (!dist->nr_spis)
+		dist->nr_spis = VGIC_NR_IRQS_LEGACY - VGIC_NR_PRIVATE_IRQS;
+
+	ret = kvm_vgic_dist_init(kvm, dist->nr_spis);
+	if (ret)
+		goto out;
+
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_vgic_vcpu_init(vcpu);
+
+	dist->initialized = true;
+out:
+	return ret;
+}
+
+static void kvm_vgic_dist_destroy(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+
+	mutex_lock(&kvm->lock);
+
+	dist->ready = false;
+	dist->initialized = false;
+
+	kfree(dist->spis);
+	kfree(dist->redist_iodevs);
+	dist->nr_spis = 0;
+
+	mutex_unlock(&kvm->lock);
+}
+
+void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
+}
+
+void kvm_vgic_destroy(struct kvm *kvm)
+{
+	struct kvm_vcpu *vcpu;
+	int i;
+
+	kvm_vgic_dist_destroy(kvm);
+
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_vgic_vcpu_destroy(vcpu);
+}
+
+/**
+ * vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest
+ * is a GICv2. A GICv3 must be explicitly initialized by the guest using the
+ * KVM_DEV_ARM_VGIC_GRP_CTRL KVM_DEVICE group.
+ * @kvm: kvm struct pointer
+ */
+int vgic_lazy_init(struct kvm *kvm)
+{
+	int ret = 0;
+
+	if (unlikely(!vgic_initialized(kvm))) {
+		/*
+		 * We only provide the automatic initialization of the VGIC
+		 * for the legacy case of a GICv2. Any other type must
+		 * be explicitly initialized once setup with the respective
+		 * KVM device call.
+		 */
+		if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2)
+			return -EBUSY;
+
+		mutex_lock(&kvm->lock);
+		ret = vgic_init(kvm);
+		mutex_unlock(&kvm->lock);
+	}
+
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 09777c8..fcbfa38 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -206,6 +206,11 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 			GICH_VMCR_PRIMASK_SHIFT;
 }
 
+/* not yet implemented */
+void vgic_v2_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index de0e8e0..d1c0285 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -186,6 +186,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
 
+/* not yet implemented */
+void vgic_v3_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 2a41028..fd2cac3 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -257,6 +257,10 @@ static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
 
 	trace_vgic_update_irq_pending(cpuid, intid, level);
 
+	ret = vgic_lazy_init(kvm);
+	if (ret)
+		return ret;
+
 	vcpu = kvm_get_vcpu(kvm, cpuid);
 	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
 		return -EINVAL;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index f4244b6..5951551 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -53,6 +53,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v2_enable(struct kvm_vcpu *vcpu);
 int vgic_v2_probe(const struct gic_kvm_info *info);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
@@ -65,6 +66,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v3_enable(struct kvm_vcpu *vcpu);
 int vgic_v3_probe(const struct gic_kvm_info *info);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
@@ -99,6 +101,10 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
 {
 }
 
+static inline void vgic_v3_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 static inline int vgic_v3_probe(const struct gic_kvm_info *info)
 {
 	return -ENODEV;
@@ -112,5 +118,7 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 #endif
 
 void kvm_register_vgic_device(unsigned long type);
+int vgic_lazy_init(struct kvm *kvm);
+int vgic_init(struct kvm *kvm);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:43 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:43 +0100
Subject: [PATCH v4 55/56] KVM: arm/arm64: vgic-new: implement mapped IRQ
 handling
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-56-git-send-email-andre.przywara@arm.com>

We now store the mapped hardware IRQ number in our struct, so we
don't need the irq_phys_map for the new VGIC.
Implement the hardware IRQ mapping on top of the reworked arch
timer interface.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- adapt to new arch_timer mapped IRQ interface
- implement inject_mapped_irq() as a macro (since it is identical to
  the "un-mapped" IRQ implementation)

Changelog v1 .. v2:
- replace inject_mapped_irq() macro with a separate implementation,
  which only allows mapped IRQs to be injected via this interface

 include/kvm/vgic/vgic.h  |  5 +++++
 virt/kvm/arm/vgic/vgic.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 17b2a73..3fbd175 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -206,6 +206,11 @@ int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
+int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			       bool level);
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq);
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index fd2cac3..c22f7e2 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -312,6 +312,44 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
 }
 
+int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			       bool level)
+{
+	return vgic_update_irq_pending(kvm, cpuid, intid, level, true);
+}
+
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+
+	BUG_ON(!irq);
+
+	spin_lock(&irq->irq_lock);
+
+	irq->hw = true;
+	irq->hwintid = phys_irq;
+
+	spin_unlock(&irq->irq_lock);
+
+	return 0;
+}
+
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+
+	BUG_ON(!irq);
+
+	spin_lock(&irq->irq_lock);
+
+	irq->hw = false;
+	irq->hwintid = 0;
+
+	spin_unlock(&irq->irq_lock);
+
+	return 0;
+}
+
 /**
  * vgic_prune_ap_list - Remove non-relevant interrupts from the list
  *
@@ -563,3 +601,15 @@ void vgic_kick_vcpus(struct kvm *kvm)
 			kvm_vcpu_kick(vcpu);
 	}
 }
+
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+	bool map_is_active;
+
+	spin_lock(&irq->irq_lock);
+	map_is_active = irq->hw && irq->active;
+	spin_unlock(&irq->irq_lock);
+
+	return map_is_active;
+}
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:44 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:44 +0100
Subject: [PATCH v4 56/56] KVM: arm/arm64: vgic-new: enable build
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-57-git-send-email-andre.przywara@arm.com>

Now that the new VGIC implementation has reached feature parity with
the old one, add the new files to the build system and add a Kconfig
option to switch between the two versions.
We set the default to the new version to get maximum test coverage,
in case people experience problems they can switch back to the old
behaviour if needed.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adjust the changed filenames in the Makefiles
- add vgic-mmio-v2.c and vgic-mmio-v3.c to the Makefiles

 arch/arm/kvm/Kconfig          |  7 +++++++
 arch/arm/kvm/Makefile         | 11 +++++++++++
 arch/arm64/kvm/Kconfig        |  7 +++++++
 arch/arm64/kvm/Makefile       | 12 ++++++++++++
 virt/kvm/arm/hyp/vgic-v2-sr.c |  5 +++++
 5 files changed, 42 insertions(+)

diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 95a0005..02abfff 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -46,6 +46,13 @@ config KVM_ARM_HOST
 	---help---
 	  Provides host support for ARM processors.
 
+config KVM_NEW_VGIC
+	bool "New VGIC implementation"
+	depends on KVM
+	default y
+	---help---
+	  uses the new VGIC implementation
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index eb1bf43..a596b58 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -21,7 +21,18 @@ obj-$(CONFIG_KVM_ARM_HOST) += hyp/
 obj-y += kvm-arm.o init.o interrupts.o
 obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
+
+ifeq ($(CONFIG_KVM_NEW_VGIC),y)
+obj-y += $(KVM)/arm/vgic/vgic.o
+obj-y += $(KVM)/arm/vgic/vgic-init.o
+obj-y += $(KVM)/arm/vgic/vgic-irqfd.o
+obj-y += $(KVM)/arm/vgic/vgic-v2.o
+obj-y += $(KVM)/arm/vgic/vgic-mmio.o
+obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
+obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
+else
 obj-y += $(KVM)/arm/vgic.o
 obj-y += $(KVM)/arm/vgic-v2.o
 obj-y += $(KVM)/arm/vgic-v2-emul.o
+endif
 obj-y += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index aa2e34e..c4f26ef 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -54,6 +54,13 @@ config KVM_ARM_PMU
 	  Adds support for a virtual Performance Monitoring Unit (PMU) in
 	  virtual machines.
 
+config KVM_NEW_VGIC
+	bool "New VGIC implementation"
+	depends on KVM
+	default y
+        ---help---
+          uses the new VGIC implementation
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 122cff4..a7a958c 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -20,10 +20,22 @@ kvm-$(CONFIG_KVM_ARM_HOST) += emulate.o inject_fault.o regmap.o
 kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
 kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
 
+ifeq ($(CONFIG_KVM_NEW_VGIC),y)
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-irqfd.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
+else
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2-emul.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3-emul.o
+endif
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
 kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index caac41f..a3f12b3 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -21,7 +21,12 @@
 
 #include <asm/kvm_hyp.h>
 
+#ifdef CONFIG_KVM_NEW_VGIC
+extern struct vgic_global kvm_vgic_global_state;
+#define vgic_v2_params kvm_vgic_global_state
+#else
 extern struct vgic_params vgic_v2_params;
+#endif
 
 static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 					    void __iomem *base)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:52 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:52 +0100
Subject: [PATCH v4 07/56] KVM: arm/arm64: vgic: Remove irq_phys_map from
 interface
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-65-git-send-email-andre.przywara@arm.com>

Now that the virtual arch timer does not care about the irq_phys_map
anymore, let's rework kvm_vgic_map_phys_irq() to return an error
value instead. Any reference to that mapping can later be done by
passing the correct combination of VCPU and virtual IRQ number.
This makes the irq_phys_map handling completely private to the
VGIC code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- adaptations to changes in previous patches (removal of virt_irq)

Changelog v2 .. v3:
- simplify return in kvm_timer_vcpu_reset()

 include/kvm/arm_vgic.h    |  3 +--
 virt/kvm/arm/arch_timer.c |  7 +------
 virt/kvm/arm/vgic.c       | 15 +++++++--------
 3 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 9ad7625..3e17fb4 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -344,8 +344,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 			       unsigned int virt_irq, bool level);
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
-struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int phys_irq);
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, int virt_irq, int phys_irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 458d4d8..3232105 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -333,7 +333,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 			 const struct kvm_irq_level *irq)
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-	struct irq_phys_map *map;
 	struct irq_desc *desc;
 	struct irq_data *data;
 	int phys_irq;
@@ -374,11 +373,7 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	 * Tell the VGIC that the virtual interrupt is tied to a
 	 * physical interrupt. We do that once per VCPU.
 	 */
-	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
-	if (WARN_ON(IS_ERR(map)))
-		return PTR_ERR(map);
-
-	return 0;
+	return kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
 }
 
 void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index a7e496a..91d42a8 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1719,21 +1719,20 @@ static struct list_head *vgic_get_irq_phys_map_list(struct kvm_vcpu *vcpu,
  * the physical interrupt represented by @phys_irq. This mapping can be
  * established multiple times as long as the parameters are the same.
  *
- * Returns a valid pointer on success, and an error pointer otherwise
+ * Returns 0 on success or an error value otherwise.
  */
-struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int phys_irq)
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, int virt_irq, int phys_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct list_head *root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 	struct irq_phys_map *map;
 	struct irq_phys_map_entry *entry;
-
+	int ret = 0;
 
 	/* Create a new mapping */
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	spin_lock(&dist->irq_phys_map_lock);
 
@@ -1742,7 +1741,7 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	if (map) {
 		/* Make sure this mapping matches */
 		if (map->phys_irq != phys_irq)
-			map = ERR_PTR(-EINVAL);
+			ret = -EINVAL;
 
 		/* Found an existing, valid mapping */
 		goto out;
@@ -1758,9 +1757,9 @@ out:
 	spin_unlock(&dist->irq_phys_map_lock);
 	/* If we've found a hit in the existing list, free the useless
 	 * entry */
-	if (IS_ERR(map) || map != &entry->map)
+	if (ret || map != &entry->map)
 		kfree(entry);
-	return map;
+	return ret;
 }
 
 static struct irq_phys_map *vgic_irq_map_search(struct kvm_vcpu *vcpu,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:00 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:00 +0100
Subject: [PATCH v4 15/56] KVM: arm/arm64: vgic-new: Add acccessor to new
 struct vgic_irq instance
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-73-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

The new VGIC implementation centers around a struct vgic_irq instance
per virtual IRQ.
Provide a function to retrieve the right instance for a given IRQ
number and (in case of private interrupts) the right VCPU.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/vgic/vgic.c | 41 +++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h | 22 ++++++++++++++++++++++
 2 files changed, 63 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic.c
 create mode 100644 virt/kvm/arm/vgic/vgic.h

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
new file mode 100644
index 0000000..fb45537
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
+
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
+			      u32 intid)
+{
+	/* SGIs and PPIs */
+	if (intid <= VGIC_MAX_PRIVATE)
+		return &vcpu->arch.vgic_cpu.private_irqs[intid];
+
+	/* SPIs */
+	if (intid <= VGIC_MAX_SPI)
+		return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS];
+
+	/* LPIs are not yet covered */
+	if (intid >= VGIC_MIN_LPI)
+		return NULL;
+
+	WARN(1, "Looking up struct vgic_irq for reserved INTID");
+	return NULL;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
new file mode 100644
index 0000000..61b8d22
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __KVM_ARM_VGIC_NEW_H__
+#define __KVM_ARM_VGIC_NEW_H__
+
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
+			      u32 intid);
+
+#endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:01 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:01 +0100
Subject: [PATCH v4 13/56] KVM: arm/arm64: move GICv2 emulation defines into
 arm-gic-v3.h
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-14-git-send-email-andre.przywara@arm.com>

As (some) GICv3 hosts can emulate a GICv2, some GICv2 specific masks
for the list register definition also apply to GICv3 LRs.
At the moment we have those definitions in the KVM VGICv3
implementation, so let's move them into the GICv3 header file to
have them automatically defined.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
---
 include/linux/irqchip/arm-gic-v3.h | 5 +++++
 virt/kvm/arm/vgic-v3.c             | 8 +-------
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index d5d798b..ec938d1 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -276,6 +276,11 @@
 #define ICH_LR_PHYS_ID_SHIFT		32
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
 
+/* These are for GICv2 emulation only */
+#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
+#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
+#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
+
 #define ICH_MISR_EOI			(1 << 0)
 #define ICH_MISR_U			(1 << 1)
 
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index c02a1b1..75b02fa 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -29,12 +29,6 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmu.h>
 
-/* These are for GICv2 emulation only */
-#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
-#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
-#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
-#define ICH_LR_VIRTUALID_MASK		(BIT_ULL(32) - 1)
-
 static u32 ich_vtr_el2;
 
 static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
@@ -43,7 +37,7 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
 	u64 val = vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr];
 
 	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
-		lr_desc.irq = val & ICH_LR_VIRTUALID_MASK;
+		lr_desc.irq = val & ICH_LR_VIRTUAL_ID_MASK;
 	else
 		lr_desc.irq = val & GICH_LR_VIRTUALID;
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:23 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:23 +0100
Subject: [PATCH v4 35/56] KVM: arm/arm64: vgic-new: Add GICv3 redistributor
 IIDR and TYPER handler
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-36-git-send-email-andre.przywara@arm.com>

The redistributor TYPER tells the OS about the associated MPIDR,
also the LAST bit is crucial to determine the number of redistributors.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- add extract_bytes() as static (moved from an earlier patch)
- replace one extract_bytes() access with a simple return

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index f11ef46..28de16a 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -22,6 +22,13 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+/* extract @num bytes at @offset bytes offset in data */
+static unsigned long extract_bytes(unsigned long data, unsigned int offset,
+				   unsigned int num)
+{
+	return (data >> (offset * 8)) & GENMASK_ULL(num * 8 - 1, 0);
+}
+
 static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
 					    gpa_t addr, unsigned int len)
 {
@@ -68,6 +75,27 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
+					      gpa_t addr, unsigned int len)
+{
+	unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
+	int target_vcpu_id = vcpu->vcpu_id;
+	u64 value;
+
+	value = (mpidr & GENMASK(23, 0)) << 32;
+	value |= ((target_vcpu_id & 0xffff) << 8);
+	if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
+		value |= GICR_TYPER_LAST;
+
+	return extract_bytes(value, addr & 7, len);
+}
+
+static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
+					     gpa_t addr, unsigned int len)
+{
+	return (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -142,10 +170,10 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		vgic_mmio_read_v3r_iidr, vgic_mmio_write_wi, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, 8,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:05 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:05 +0100
Subject: [PATCH v4 20/56] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-78-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

As the GICv3 virtual interface registers differ from their GICv2
siblings, we need different handlers for processing maintenance
interrupts and reading/writing to the LRs.
Implement the respective handler functions and connect them to
existing code to be called if the host is using a GICv3.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- remove outdated comment about the dist_lock
- add WARN_ON about LR_STATE not being 0 in maintenance interrupts

Changelog v1 .. v2:
- inject the IRQ priority into the list register

Changelog v2 .. v3:
- remove no longer needed irqchip/arm-gic.h inclusion

Changelog v3 .. v4:
- remove ELRSR bit set during process_maintenance()
- refine comment about Group1 interrupts
- remove wrong comment about ap_list_lock in vgic_v3_fold_lr_state()

 include/linux/irqchip/arm-gic-v3.h |   1 +
 virt/kvm/arm/vgic/vgic-v3.c        | 162 +++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c           |  25 ++++--
 virt/kvm/arm/vgic/vgic.h           |  29 +++++++
 4 files changed, 212 insertions(+), 5 deletions(-)
 create mode 100644 virt/kvm/arm/vgic/vgic-v3.c

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index ec938d1..35e93cf 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -275,6 +275,7 @@
 #define ICH_LR_ACTIVE_BIT		(1ULL << 63)
 #define ICH_LR_PHYS_ID_SHIFT		32
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
+#define ICH_LR_PRIORITY_SHIFT		48
 
 /* These are for GICv2 emulation only */
 #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
new file mode 100644
index 0000000..fb547da
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -0,0 +1,162 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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/irqchip/arm-gic-v3.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+
+	if (cpuif->vgic_misr & ICH_MISR_EOI) {
+		unsigned long eisr_bmap = cpuif->vgic_eisr;
+		int lr;
+
+		for_each_set_bit(lr, &eisr_bmap, kvm_vgic_global_state.nr_lr) {
+			u32 intid;
+			u64 val = cpuif->vgic_lr[lr];
+
+			if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+				intid = val & ICH_LR_VIRTUAL_ID_MASK;
+			else
+				intid = val & GICH_LR_VIRTUALID;
+
+			WARN_ON(cpuif->vgic_lr[lr] & ICH_LR_STATE);
+
+			kvm_notify_acked_irq(vcpu->kvm, 0,
+					     intid - VGIC_NR_PRIVATE_IRQS);
+		}
+
+		/*
+		 * In the next iterations of the vcpu loop, if we sync
+		 * the vgic state after flushing it, but before
+		 * entering the guest (this happens for pending
+		 * signals and vmid rollovers), then make sure we
+		 * don't pick up any old maintenance interrupts here.
+		 */
+		cpuif->vgic_eisr = 0;
+	}
+
+	cpuif->vgic_hcr &= ~ICH_HCR_UIE;
+}
+
+void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+
+	cpuif->vgic_hcr |= ICH_HCR_UIE;
+}
+
+void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+	int lr;
+
+	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
+		u64 val = cpuif->vgic_lr[lr];
+		u32 intid;
+		struct vgic_irq *irq;
+
+		if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+			intid = val & ICH_LR_VIRTUAL_ID_MASK;
+		else
+			intid = val & GICH_LR_VIRTUALID;
+		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+
+		/* Always preserve the active bit */
+		irq->active = !!(val & ICH_LR_ACTIVE_BIT);
+
+		/* Edge is the only case where we preserve the pending bit */
+		if (irq->config == VGIC_CONFIG_EDGE &&
+		    (val & ICH_LR_PENDING_BIT)) {
+			irq->pending = true;
+
+			if (vgic_irq_is_sgi(intid) &&
+			    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
+
+				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+				irq->source |= (1 << cpuid);
+			}
+		}
+
+		/* Clear soft pending state when level irqs have been acked */
+		if (irq->config == VGIC_CONFIG_LEVEL &&
+		    !(val & ICH_LR_PENDING_BIT)) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+/* Requires the irq to be locked already */
+void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
+{
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+	u64 val = irq->intid;
+
+	if (irq->pending) {
+		val |= ICH_LR_PENDING_BIT;
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			irq->pending = false;
+
+		if (vgic_irq_is_sgi(irq->intid) &&
+		    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+			u32 src = ffs(irq->source);
+
+			BUG_ON(!src);
+			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
+			irq->source &= ~(1 << (src - 1));
+			if (irq->source)
+				irq->pending = true;
+		}
+	}
+
+	if (irq->active)
+		val |= ICH_LR_ACTIVE_BIT;
+
+	if (irq->hw) {
+		val |= ICH_LR_HW;
+		val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
+	} else {
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			val |= ICH_LR_EOI;
+	}
+
+	/*
+	 * We currently only support Group1 interrupts, which is a
+	 * known defect. This needs to be addressed at some point.
+	 */
+	if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+		val |= ICH_LR_GROUP;
+
+	val |= (u64)irq->priority << ICH_LR_PRIORITY_SHIFT;
+
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = val;
+}
+
+void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 7d85398..eca3cd0 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -399,12 +399,18 @@ retry:
 
 static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_process_maintenance(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_process_maintenance(vcpu);
+	else
+		vgic_v3_process_maintenance(vcpu);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_fold_lr_state(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_fold_lr_state(vcpu);
+	else
+		vgic_v3_fold_lr_state(vcpu);
 }
 
 /* Requires the irq_lock to be held. */
@@ -413,17 +419,26 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
 {
 	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
 
-	vgic_v2_populate_lr(vcpu, irq, lr);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_populate_lr(vcpu, irq, lr);
+	else
+		vgic_v3_populate_lr(vcpu, irq, lr);
 }
 
 static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
-	vgic_v2_clear_lr(vcpu, lr);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_clear_lr(vcpu, lr);
+	else
+		vgic_v3_clear_lr(vcpu, lr);
 }
 
 static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_set_underflow(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_set_underflow(vcpu);
+	else
+		vgic_v3_set_underflow(vcpu);
 }
 
 /* Requires the ap_list_lock to be held. */
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 0db490e..81b1a20 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -28,4 +28,33 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
+void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
+void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
+void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
+void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+#else
+static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_v3_populate_lr(struct kvm_vcpu *vcpu,
+				       struct vgic_irq *irq, int lr)
+{
+}
+
+static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+}
+
+static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
+{
+}
+#endif
+
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:17 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:17 +0100
Subject: [PATCH v4 32/56] KVM: arm/arm64: vgic-new: Add SGIPENDR register
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-90-git-send-email-andre.przywara@arm.com>

As this register is v2 specific, its implementation lives entirely
in vgic-mmio-v2.c.
This register allows setting the source mask of an IPI.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- remove IRQ lock from read handler
- update pending bit on setting the first / clearing the last bit
- queue virtual IRQ if necessary

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 60 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index c884e9b..3925d4c 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -146,6 +146,64 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->source << (i * 8);
+	}
+	return val;
+}
+
+static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len,
+				     unsigned long val)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->source &= ~((val >> (i * 8)) & 0xff);
+		if (!irq->source)
+			irq->pending = false;
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len,
+				     unsigned long val)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->source |= (val >> (i * 8)) & 0xff;
+
+		if (irq->source) {
+			irq->pending = true;
+			vgic_queue_irq_unlock(vcpu->kvm, irq);
+		} else {
+			spin_unlock(&irq->irq_lock);
+		}
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
@@ -184,10 +242,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		vgic_mmio_read_sgipend, vgic_mmio_write_sgipendc, 16,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 };
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:02 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:02 +0100
Subject: [PATCH v4 17/56] KVM: arm/arm64: vgic-new: Add IRQ sorting
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-75-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Adds the sorting function to cover the case where you have more IRQs
to consider than you have LRs. We now consider priorities.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/vgic/vgic.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 62fede6..1bc8f92 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -16,6 +16,7 @@
 
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <linux/list_sort.h>
 
 #include "vgic.h"
 
@@ -103,6 +104,62 @@ static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
 }
 
 /*
+ * The order of items in the ap_lists defines how we'll pack things in LRs as
+ * well, the first items in the list being the first things populated in the
+ * LRs.
+ *
+ * A hard rule is that active interrupts can never be pushed out of the LRs
+ * (and therefore take priority) since we cannot reliably trap on deactivation
+ * of IRQs and therefore they have to be present in the LRs.
+ *
+ * Otherwise things should be sorted by the priority field and the GIC
+ * hardware support will take care of preemption of priority groups etc.
+ *
+ * Return negative if "a" sorts before "b", 0 to preserve order, and positive
+ * to sort "b" before "a".
+ */
+static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+	struct vgic_irq *irqa = container_of(a, struct vgic_irq, ap_list);
+	struct vgic_irq *irqb = container_of(b, struct vgic_irq, ap_list);
+	bool penda, pendb;
+	int ret;
+
+	spin_lock(&irqa->irq_lock);
+	spin_lock(&irqb->irq_lock);
+
+	if (irqa->active || irqb->active) {
+		ret = (int)irqb->active - (int)irqa->active;
+		goto out;
+	}
+
+	penda = irqa->enabled && irqa->pending;
+	pendb = irqb->enabled && irqb->pending;
+
+	if (!penda || !pendb) {
+		ret = (int)pendb - (int)penda;
+		goto out;
+	}
+
+	/* Both pending and enabled, sort by priority */
+	ret = irqa->priority - irqb->priority;
+out:
+	spin_unlock(&irqb->irq_lock);
+	spin_unlock(&irqa->irq_lock);
+	return ret;
+}
+
+/* Must be called with the ap_list_lock held */
+static void vgic_sort_ap_list(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	list_sort(NULL, &vgic_cpu->ap_list_head, vgic_irq_cmp);
+}
+
+/*
  * Only valid injection if changing level for level-triggered IRQs or for a
  * rising edge.
  */
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:21 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:21 +0100
Subject: [PATCH v4 36/56] KVM: arm/arm64: vgic-new: Add GICv3 IDREGS register
 handler
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-94-git-send-email-andre.przywara@arm.com>

We implement the only one ID register that is required by the
architecture, also this is the one that Linux actually checks.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 28de16a..b893284 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -96,6 +96,18 @@ static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
 	return (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
 }
 
+static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu,
+					      gpa_t addr, unsigned int len)
+{
+	switch (addr & 0xffff) {
+	case GICD_PIDR2:
+		/* report a GICv3 compliant implementation */
+		return 0x3b;
+	}
+
+	return 0;
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -161,7 +173,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
 		VGIC_ACCESS_32bit),
 };
 
@@ -182,7 +194,7 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
 		VGIC_ACCESS_32bit),
 };
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:22 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:22 +0100
Subject: [PATCH v4 37/56] KVM: arm/arm64: vgic-new: Add GICv3 IROUTER register
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-95-git-send-email-andre.przywara@arm.com>

Since GICv3 supports much more than the 8 CPUs the GICv2 ITARGETSR
register can handle, the new IROUTER register covers the whole range
of possible target (V)CPUs by using the same MPIDR that the cores
report themselves.
In addition to translating this MPIDR into a vcpu pointer we store
the originally written value as well. The architecture allows to
write any values into the register, which must be read back as written.

Since we don't support affinity level 3, we don't need to take care
about the upper word of this 64-bit register, which simplifies the
handling a bit.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- fold in and simplify vgic_v3_irq_change_affinity

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- move accessor width check into dispatcher
- use IRQ number accessor macro

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index b893284..7b9340b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -75,6 +75,41 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	int intid = VGIC_ADDR_TO_INTID(addr, 64);
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+
+	if (!irq)
+		return 0;
+
+	return extract_bytes(READ_ONCE(irq->mpidr), addr & 7, len);
+}
+
+static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	int intid = VGIC_ADDR_TO_INTID(addr, 64);
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+
+	if (!irq)
+		return;
+
+	/* The upper word is WI for us since we don't implement Aff3. */
+	if (addr & 4)
+		return;
+
+	spin_lock(&irq->irq_lock);
+
+	/* We only care about and preserve Aff0, Aff1 and Aff2. */
+	irq->mpidr = val & GENMASK(23, 0);
+	irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, irq->mpidr);
+
+	spin_unlock(&irq->irq_lock);
+}
+
 static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
 					      gpa_t addr, unsigned int len)
 {
@@ -170,7 +205,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
+		vgic_mmio_read_irouter, vgic_mmio_write_irouter, 64,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
 		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:10 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:10 +0100
Subject: [PATCH v4 25/56] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-83-git-send-email-andre.przywara@arm.com>

As the enable register handlers are shared between the v2 and v3
emulation, their implementation goes into vgic-mmio.c, to be easily
referenced from the v3 emulation as well later.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog RFC..v1:
- use lower bits of address to determine IRQ number
- remove TODO, confirmed to be fine

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro
- replace extract_bytes() with simple return

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
 virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
 3 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index d812c93..d5355b5 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -72,10 +72,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 1a97765..32ed8db 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -39,6 +39,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 	/* Ignore */
 }
 
+/*
+ * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
+ * of the enabled bit, so there is only one function for both here.
+ */
+unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->enabled)
+			value |= (1U << i);
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		irq->enabled = true;
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
+void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->enabled = false;
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 10404ac..66fd6fa 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -84,6 +84,17 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
 void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 			unsigned int len, unsigned long val);
 
+unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
+void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:38 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:38 +0100
Subject: [PATCH v4 53/56] KVM: arm/arm64: vgic-new: Add vgic_v2/v3_enable
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-111-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

Enable the VGIC operation by properly initialising the registers
in the hypervisor GIC interface.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-v2.c | 11 ++++++++++-
 virt/kvm/arm/vgic/vgic-v3.c | 23 ++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 1fe031b..8ad42c2 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -206,9 +206,18 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 			GICH_VMCR_PRIMASK_SHIFT;
 }
 
-/* not yet implemented */
 void vgic_v2_enable(struct kvm_vcpu *vcpu)
 {
+	/*
+	 * By forcing VMCR to zero, the GIC will restore the binary
+	 * points to their reset values. Anything else resets to zero
+	 * anyway.
+	 */
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = 0;
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr = ~0;
+
+	/* Get the show on the road... */
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr = GICH_HCR_EN;
 }
 
 /* check for overlapping regions and for regions crossing the end of memory */
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 637ff2b..336a461 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -186,9 +186,30 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
 
-/* not yet implemented */
 void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
+	struct vgic_v3_cpu_if *vgic_v3 = &vcpu->arch.vgic_cpu.vgic_v3;
+
+	/*
+	 * By forcing VMCR to zero, the GIC will restore the binary
+	 * points to their reset values. Anything else resets to zero
+	 * anyway.
+	 */
+	vgic_v3->vgic_vmcr = 0;
+	vgic_v3->vgic_elrsr = ~0;
+
+	/*
+	 * If we are emulating a GICv3, we do it in an non-GICv2-compatible
+	 * way, so we force SRE to 1 to demonstrate this to the guest.
+	 * This goes with the spec allowing the value to be RAO/WI.
+	 */
+	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+		vgic_v3->vgic_sre = ICC_SRE_EL1_SRE;
+	else
+		vgic_v3->vgic_sre = 0;
+
+	/* Get the show on the road... */
+	vgic_v3->vgic_hcr = ICH_HCR_EN;
 }
 
 /* check for overlapping regions and for regions crossing the end of memory */
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:29 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:29 +0100
Subject: [PATCH v4 44/56] KVM: arm/arm64: vgic-new: vgic_kvm_device: access to
 VGIC registers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-102-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
access VGIC registers.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v3 .. v4:
- check for proper alignment on userland GIC accesses

 virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 38 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |  1 +
 3 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index a709097..78621283 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -226,6 +226,21 @@ void kvm_register_vgic_device(unsigned long type)
 	}
 }
 
+/** vgic_attr_regs_access: allows user space to read/write VGIC registers
+ *
+ * @dev: kvm device handle
+ * @attr: kvm device attribute
+ * @reg: address the value is read or written
+ * @is_write: write flag
+ *
+ */
+static int vgic_attr_regs_access(struct kvm_device *dev,
+				 struct kvm_device_attr *attr,
+				 u32 *reg, bool is_write)
+{
+	return -ENXIO;
+}
+
 /* V2 ops */
 
 static int vgic_v2_set_attr(struct kvm_device *dev,
@@ -234,8 +249,23 @@ static int vgic_v2_set_attr(struct kvm_device *dev,
 	int ret;
 
 	ret = vgic_set_common_attr(dev, attr);
-	return ret;
+	if (ret != -ENXIO)
+		return ret;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 reg;
+
+		if (get_user(reg, uaddr))
+			return -EFAULT;
 
+		return vgic_attr_regs_access(dev, attr, &reg, true);
+	}
+	}
+
+	return -ENXIO;
 }
 
 static int vgic_v2_get_attr(struct kvm_device *dev,
@@ -244,7 +274,23 @@ static int vgic_v2_get_attr(struct kvm_device *dev,
 	int ret;
 
 	ret = vgic_get_common_attr(dev, attr);
-	return ret;
+	if (ret != -ENXIO)
+		return ret;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 reg = 0;
+
+		ret = vgic_attr_regs_access(dev, attr, &reg, false);
+		if (ret)
+			return ret;
+		return put_user(reg, uaddr);
+	}
+	}
+
+	return -ENXIO;
 }
 
 static int vgic_v2_has_attr(struct kvm_device *dev,
@@ -258,6 +304,9 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 			return 0;
 		}
 		break;
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		return vgic_v2_has_attr_regs(dev, attr);
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 3925d4c..7189690 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -258,3 +258,41 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
 
 	return SZ_4K;
 }
+
+int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+	const struct vgic_register_region *regions;
+	gpa_t addr;
+	int nr_regions, i, len;
+
+	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+		regions = vgic_v2_dist_registers;
+		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
+		break;
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		return -ENXIO;		/* TODO: describe CPU i/f regs also */
+	default:
+		return -ENXIO;
+	}
+
+	/* We only support aligned 32-bit accesses. */
+	if (addr & 3)
+		return -ENXIO;
+
+	for (i = 0; i < nr_regions; i++) {
+		if (regions[i].bits_per_irq)
+			len = (regions[i].bits_per_irq * nr_irqs) / 8;
+		else
+			len = regions[i].len;
+
+		if (regions[i].reg_offset <= addr &&
+		    regions[i].reg_offset + len > addr)
+			return 0;
+	}
+
+	return -ENXIO;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 6abc9a3..a264c5f 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -37,6 +37,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:37 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:37 +0100
Subject: [PATCH v4 52/56] KVM: arm/arm64: vgic-new: vgic_init: implement
 map_resources
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-110-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

map_resources is the last initialization step. It is executed on
first VCPU run. At that stage the code checks that userspace has provided
the base addresses for the relevant VGIC regions, which depend on the
type of VGIC that is exposed to the guest.  Also we check if the two
regions overlap.
If the checks succeeded, we register the respective register frames with
the kvm_io_bus framework.

If we emulate a GICv2, the function also forces vgic_init execution if
it has not been executed yet. Also we map the virtual GIC CPU interface
onto the guest's CPU interface.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v3 .. v4:
- add overlap check (moved from kvm_vgic_addr())
- reword commit message
- improve comment

 include/kvm/vgic/vgic.h       |  1 +
 virt/kvm/arm/vgic/vgic-init.c | 28 +++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   | 69 +++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c   | 71 +++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h      |  7 +++++
 5 files changed, 176 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index e7ae36b..17b2a73 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -201,6 +201,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type);
 void kvm_vgic_destroy(struct kvm *kvm);
 void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
+int kvm_vgic_map_resources(struct kvm *kvm);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index bed3240..a1442f7 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -323,6 +323,34 @@ int vgic_lazy_init(struct kvm *kvm)
 	return ret;
 }
 
+/* RESOURCE MAPPING */
+
+/**
+ * Map the MMIO regions depending on the VGIC model exposed to the guest
+ * called on the first VCPU run.
+ * Also map the virtual CPU interface into the VM.
+ * v2/v3 derivatives call vgic_init if not already done.
+ * vgic_ready() returns true if this function has succeeded.
+ * @kvm: kvm struct pointer
+ */
+int kvm_vgic_map_resources(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	int ret = 0;
+
+	mutex_lock(&kvm->lock);
+	if (!irqchip_in_kernel(kvm))
+		goto out;
+
+	if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+		ret = vgic_v2_map_resources(kvm);
+	else
+		ret = vgic_v3_map_resources(kvm);
+out:
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index fcbfa38..1fe031b 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -211,6 +211,75 @@ void vgic_v2_enable(struct kvm_vcpu *vcpu)
 {
 }
 
+/* check for overlapping regions and for regions crossing the end of memory */
+static bool vgic_v2_check_base(gpa_t dist_base, gpa_t cpu_base)
+{
+	if (dist_base + KVM_VGIC_V2_DIST_SIZE < dist_base)
+		return false;
+	if (cpu_base + KVM_VGIC_V2_CPU_SIZE < cpu_base)
+		return false;
+
+	if (dist_base + KVM_VGIC_V2_DIST_SIZE <= cpu_base)
+		return true;
+	if (cpu_base + KVM_VGIC_V2_CPU_SIZE <= dist_base)
+		return true;
+
+	return false;
+}
+
+int vgic_v2_map_resources(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	int ret = 0;
+
+	if (vgic_ready(kvm))
+		goto out;
+
+	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
+	    IS_VGIC_ADDR_UNDEF(dist->vgic_cpu_base)) {
+		kvm_err("Need to set vgic cpu and dist addresses first\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	if (!vgic_v2_check_base(dist->vgic_dist_base, dist->vgic_cpu_base)) {
+		kvm_err("VGIC CPU and dist frames overlap\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Initialize the vgic if this hasn't already been done on demand by
+	 * accessing the vgic state from userspace.
+	 */
+	ret = vgic_init(kvm);
+	if (ret) {
+		kvm_err("Unable to initialize VGIC dynamic data structures\n");
+		goto out;
+	}
+
+	ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V2);
+	if (ret) {
+		kvm_err("Unable to register VGIC MMIO regions\n");
+		goto out;
+	}
+
+	ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base,
+				    kvm_vgic_global_state.vcpu_base,
+				    KVM_VGIC_V2_CPU_SIZE, true);
+	if (ret) {
+		kvm_err("Unable to remap VGIC CPU to VCPU\n");
+		goto out;
+	}
+
+	dist->ready = true;
+
+out:
+	if (ret)
+		kvm_vgic_destroy(kvm);
+	return ret;
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index d1c0285..637ff2b 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -191,6 +191,77 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
 }
 
+/* check for overlapping regions and for regions crossing the end of memory */
+static bool vgic_v3_check_base(struct kvm *kvm)
+{
+	struct vgic_dist *d = &kvm->arch.vgic;
+	gpa_t redist_size = KVM_VGIC_V3_REDIST_SIZE;
+
+	redist_size *= atomic_read(&kvm->online_vcpus);
+
+	if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base)
+		return false;
+	if (d->vgic_redist_base + redist_size < d->vgic_redist_base)
+		return false;
+
+	if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE <= d->vgic_redist_base)
+		return true;
+	if (d->vgic_redist_base + redist_size <= d->vgic_dist_base)
+		return true;
+
+	return false;
+}
+
+int vgic_v3_map_resources(struct kvm *kvm)
+{
+	int ret = 0;
+	struct vgic_dist *dist = &kvm->arch.vgic;
+
+	if (vgic_ready(kvm))
+		goto out;
+
+	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
+	    IS_VGIC_ADDR_UNDEF(dist->vgic_redist_base)) {
+		kvm_err("Need to set vgic distributor addresses first\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	if (!vgic_v3_check_base(kvm)) {
+		kvm_err("VGIC redist and dist frames overlap\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * For a VGICv3 we require the userland to explicitly initialize
+	 * the VGIC before we need to use it.
+	 */
+	if (!vgic_initialized(kvm)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V3);
+	if (ret) {
+		kvm_err("Unable to register VGICv3 dist MMIO regions\n");
+		goto out;
+	}
+
+	ret = vgic_register_redist_iodevs(kvm, dist->vgic_redist_base);
+	if (ret) {
+		kvm_err("Unable to register VGICv3 redist MMIO regions\n");
+		goto out;
+	}
+
+	dist->ready = true;
+
+out:
+	if (ret)
+		kvm_vgic_destroy(kvm);
+	return ret;
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 5951551..7b300ca 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -55,6 +55,7 @@ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_enable(struct kvm_vcpu *vcpu);
 int vgic_v2_probe(const struct gic_kvm_info *info);
+int vgic_v2_map_resources(struct kvm *kvm);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -68,6 +69,7 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_enable(struct kvm_vcpu *vcpu);
 int vgic_v3_probe(const struct gic_kvm_info *info);
+int vgic_v3_map_resources(struct kvm *kvm);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -110,6 +112,11 @@ static inline int vgic_v3_probe(const struct gic_kvm_info *info)
 	return -ENODEV;
 }
 
+static inline int vgic_v3_map_resources(struct kvm *kvm)
+{
+	return -ENODEV;
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:36 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:36 +0100
Subject: [PATCH v4 51/56] KVM: arm/arm64: vgic-new: vgic_init: implement
 vgic_init
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-109-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch allocates and initializes the data structures used
to model the vgic distributor and virtual cpu interfaces. At that
stage the number of IRQs and number of virtual CPUs is frozen.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- initialize v2/v3 default CPU affinities explicitly

Changelog v1 .. v2:
- move lazy_init() into vgic_update_irq_pending()

Changelog v3 .. v4:
- fix comments
- make local functions static
- adapt to new firmware independent probing

 include/kvm/vgic/vgic.h       |   7 +-
 virt/kvm/arm/vgic/vgic-init.c | 217 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   |   5 +
 virt/kvm/arm/vgic/vgic-v3.c   |   5 +
 virt/kvm/arm/vgic/vgic.c      |   4 +
 virt/kvm/arm/vgic/vgic.h      |   8 ++
 6 files changed, 245 insertions(+), 1 deletion(-)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 0634d89..e7ae36b 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -119,6 +119,7 @@ struct vgic_io_device {
 struct vgic_dist {
 	bool			in_kernel;
 	bool			ready;
+	bool			initialized;
 
 	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
 	u32			vgic_model;
@@ -195,7 +196,11 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+void kvm_vgic_early_init(struct kvm *kvm);
 int kvm_vgic_create(struct kvm *kvm, u32 type);
+void kvm_vgic_destroy(struct kvm *kvm);
+void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
+void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
@@ -204,7 +209,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
-#define vgic_initialized(k)	(false)
+#define vgic_initialized(k)	((k)->arch.vgic.initialized)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
 #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
 			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 15d5428..bed3240 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -22,6 +22,42 @@
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
+/*
+ * Initialization rules: there are multiple stages to the vgic
+ * initialization, both for the distributor and the CPU interfaces.
+ *
+ * Distributor:
+ *
+ * - kvm_vgic_early_init(): initialization of static data that doesn't
+ *   depend on any sizing information or emulation type. No allocation
+ *   is allowed there.
+ *
+ * - vgic_init(): allocation and initialization of the generic data
+ *   structures that depend on sizing information (number of CPUs,
+ *   number of interrupts). Also initializes the vcpu specific data
+ *   structures. Can be executed lazily for GICv2.
+ *
+ * CPU Interface:
+ *
+ * - kvm_vgic_cpu_early_init(): initialization of static data that
+ *   doesn't depend on any sizing information or emulation type. No
+ *   allocation is allowed there.
+ */
+
+/* EARLY INIT */
+
+/*
+ * Those 2 functions should not be needed anymore but they
+ * still are called from arm.c
+ */
+void kvm_vgic_early_init(struct kvm *kvm)
+{
+}
+
+void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu)
+{
+}
+
 /* CREATION */
 
 /**
@@ -29,6 +65,8 @@
  * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only)
  * or through the generic KVM_CREATE_DEVICE API ioctl.
  * irqchip_in_kernel() tells you if this function succeeded or not.
+ * @kvm: kvm struct pointer
+ * @type: KVM_DEV_TYPE_ARM_VGIC_V[23]
  */
 int kvm_vgic_create(struct kvm *kvm, u32 type)
 {
@@ -106,6 +144,185 @@ out:
 	return ret;
 }
 
+/* INIT/DESTROY */
+
+/**
+ * kvm_vgic_dist_init: initialize the dist data structures
+ * @kvm: kvm struct pointer
+ * @nr_spis: number of spis, frozen by caller
+ */
+static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct kvm_vcpu *vcpu0 = kvm_get_vcpu(kvm, 0);
+	int i;
+
+	dist->spis = kcalloc(nr_spis, sizeof(struct vgic_irq), GFP_KERNEL);
+	if (!dist->spis)
+		return  -ENOMEM;
+
+	/*
+	 * In the following code we do not take the irq struct lock since
+	 * no other action on irq structs can happen while the VGIC is
+	 * not initialized yet:
+	 * If someone wants to inject an interrupt or does a MMIO access, we
+	 * require prior initialization in case of a virtual GICv3 or trigger
+	 * initialization when using a virtual GICv2.
+	 */
+	for (i = 0; i < nr_spis; i++) {
+		struct vgic_irq *irq = &dist->spis[i];
+
+		irq->intid = i + VGIC_NR_PRIVATE_IRQS;
+		INIT_LIST_HEAD(&irq->ap_list);
+		spin_lock_init(&irq->irq_lock);
+		irq->vcpu = NULL;
+		irq->target_vcpu = vcpu0;
+		if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+			irq->targets = 0;
+		else
+			irq->mpidr = 0;
+	}
+	return 0;
+}
+
+/**
+ * kvm_vgic_vcpu_init: initialize the vcpu data structures and
+ * enable the VCPU interface
+ * @vcpu: the VCPU which's VGIC should be initialized
+ */
+static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	int i;
+
+	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
+	spin_lock_init(&vgic_cpu->ap_list_lock);
+
+	/*
+	 * Enable and configure all SGIs to be edge-triggered and
+	 * configure all PPIs as level-triggered.
+	 */
+	for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
+		struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
+
+		INIT_LIST_HEAD(&irq->ap_list);
+		spin_lock_init(&irq->irq_lock);
+		irq->intid = i;
+		irq->vcpu = NULL;
+		irq->target_vcpu = vcpu;
+		irq->targets = 1U << vcpu->vcpu_id;
+		if (vgic_irq_is_sgi(i)) {
+			/* SGIs */
+			irq->enabled = 1;
+			irq->config = VGIC_CONFIG_EDGE;
+		} else {
+			/* PPIs */
+			irq->config = VGIC_CONFIG_LEVEL;
+		}
+	}
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_enable(vcpu);
+	else
+		vgic_v3_enable(vcpu);
+}
+
+/*
+ * vgic_init: allocates and initializes dist and vcpu data structures
+ * depending on two dimensioning parameters:
+ * - the number of spis
+ * - the number of vcpus
+ * The function is generally called when nr_spis has been explicitly set
+ * by the guest through the KVM DEVICE API. If not nr_spis is set to 256.
+ * vgic_initialized() returns true when this function has succeeded.
+ * Must be called with kvm->lock held!
+ */
+int vgic_init(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct kvm_vcpu *vcpu;
+	int ret = 0, i;
+
+	if (vgic_initialized(kvm))
+		return 0;
+
+	/* freeze the number of spis */
+	if (!dist->nr_spis)
+		dist->nr_spis = VGIC_NR_IRQS_LEGACY - VGIC_NR_PRIVATE_IRQS;
+
+	ret = kvm_vgic_dist_init(kvm, dist->nr_spis);
+	if (ret)
+		goto out;
+
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_vgic_vcpu_init(vcpu);
+
+	dist->initialized = true;
+out:
+	return ret;
+}
+
+static void kvm_vgic_dist_destroy(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+
+	mutex_lock(&kvm->lock);
+
+	dist->ready = false;
+	dist->initialized = false;
+
+	kfree(dist->spis);
+	kfree(dist->redist_iodevs);
+	dist->nr_spis = 0;
+
+	mutex_unlock(&kvm->lock);
+}
+
+void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
+}
+
+void kvm_vgic_destroy(struct kvm *kvm)
+{
+	struct kvm_vcpu *vcpu;
+	int i;
+
+	kvm_vgic_dist_destroy(kvm);
+
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_vgic_vcpu_destroy(vcpu);
+}
+
+/**
+ * vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest
+ * is a GICv2. A GICv3 must be explicitly initialized by the guest using the
+ * KVM_DEV_ARM_VGIC_GRP_CTRL KVM_DEVICE group.
+ * @kvm: kvm struct pointer
+ */
+int vgic_lazy_init(struct kvm *kvm)
+{
+	int ret = 0;
+
+	if (unlikely(!vgic_initialized(kvm))) {
+		/*
+		 * We only provide the automatic initialization of the VGIC
+		 * for the legacy case of a GICv2. Any other type must
+		 * be explicitly initialized once setup with the respective
+		 * KVM device call.
+		 */
+		if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2)
+			return -EBUSY;
+
+		mutex_lock(&kvm->lock);
+		ret = vgic_init(kvm);
+		mutex_unlock(&kvm->lock);
+	}
+
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 09777c8..fcbfa38 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -206,6 +206,11 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 			GICH_VMCR_PRIMASK_SHIFT;
 }
 
+/* not yet implemented */
+void vgic_v2_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index de0e8e0..d1c0285 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -186,6 +186,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
 
+/* not yet implemented */
+void vgic_v3_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 2a41028..fd2cac3 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -257,6 +257,10 @@ static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
 
 	trace_vgic_update_irq_pending(cpuid, intid, level);
 
+	ret = vgic_lazy_init(kvm);
+	if (ret)
+		return ret;
+
 	vcpu = kvm_get_vcpu(kvm, cpuid);
 	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
 		return -EINVAL;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index f4244b6..5951551 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -53,6 +53,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v2_enable(struct kvm_vcpu *vcpu);
 int vgic_v2_probe(const struct gic_kvm_info *info);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
@@ -65,6 +66,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v3_enable(struct kvm_vcpu *vcpu);
 int vgic_v3_probe(const struct gic_kvm_info *info);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
@@ -99,6 +101,10 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
 {
 }
 
+static inline void vgic_v3_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 static inline int vgic_v3_probe(const struct gic_kvm_info *info)
 {
 	return -ENODEV;
@@ -112,5 +118,7 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 #endif
 
 void kvm_register_vgic_device(unsigned long type);
+int vgic_lazy_init(struct kvm *kvm);
+int vgic_init(struct kvm *kvm);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:40 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:40 +0100
Subject: [PATCH v4 55/56] KVM: arm/arm64: vgic-new: implement mapped IRQ
 handling
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-113-git-send-email-andre.przywara@arm.com>

We now store the mapped hardware IRQ number in our struct, so we
don't need the irq_phys_map for the new VGIC.
Implement the hardware IRQ mapping on top of the reworked arch
timer interface.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- adapt to new arch_timer mapped IRQ interface
- implement inject_mapped_irq() as a macro (since it is identical to
  the "un-mapped" IRQ implementation)

Changelog v1 .. v2:
- replace inject_mapped_irq() macro with a separate implementation,
  which only allows mapped IRQs to be injected via this interface

 include/kvm/vgic/vgic.h  |  5 +++++
 virt/kvm/arm/vgic/vgic.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 17b2a73..3fbd175 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -206,6 +206,11 @@ int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
+int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			       bool level);
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq);
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index fd2cac3..c22f7e2 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -312,6 +312,44 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
 }
 
+int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			       bool level)
+{
+	return vgic_update_irq_pending(kvm, cpuid, intid, level, true);
+}
+
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+
+	BUG_ON(!irq);
+
+	spin_lock(&irq->irq_lock);
+
+	irq->hw = true;
+	irq->hwintid = phys_irq;
+
+	spin_unlock(&irq->irq_lock);
+
+	return 0;
+}
+
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+
+	BUG_ON(!irq);
+
+	spin_lock(&irq->irq_lock);
+
+	irq->hw = false;
+	irq->hwintid = 0;
+
+	spin_unlock(&irq->irq_lock);
+
+	return 0;
+}
+
 /**
  * vgic_prune_ap_list - Remove non-relevant interrupts from the list
  *
@@ -563,3 +601,15 @@ void vgic_kick_vcpus(struct kvm *kvm)
 			kvm_vcpu_kick(vcpu);
 	}
 }
+
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+	bool map_is_active;
+
+	spin_lock(&irq->irq_lock);
+	map_is_active = irq->hw && irq->active;
+	spin_unlock(&irq->irq_lock);
+
+	return map_is_active;
+}
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:52:59 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:52:59 +0100
Subject: [PATCH v4 11/56] KVM: arm/arm64: pmu: abstract access to number of
 SPIs
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-12-git-send-email-andre.przywara@arm.com>

Currently the PMU uses a member of the struct vgic_dist directly,
which not only breaks abstraction, but will fail with the new VGIC.
Abstract this access in the VGIC header file and refactor the validity
check in the PMU code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v3 .. v4:
- fix logic to allow PPIs again
- refactor IRQ validity check

 include/kvm/arm_vgic.h |  2 ++
 virt/kvm/arm/pmu.c     | 25 ++++++++++++++-----------
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 67a6637..ade7005 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -348,6 +348,8 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
 #define vgic_ready(k)		((k)->arch.vgic.ready)
+#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
+				 ((i) < (k)->arch.vgic.nr_irqs))
 
 int vgic_v2_probe(const struct gic_kvm_info *gic_kvm_info,
 		  const struct vgic_ops **ops,
diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
index 575c7aa..a027569 100644
--- a/virt/kvm/arm/pmu.c
+++ b/virt/kvm/arm/pmu.c
@@ -436,7 +436,14 @@ static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
-static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
+#define irq_is_ppi(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS)
+
+/*
+ * For one VM the interrupt type must be same for each vcpu.
+ * As a PPI, the interrupt number is the same for all vcpus,
+ * while as an SPI it must be a separate number per vcpu.
+ */
+static bool pmu_irq_is_valid(struct kvm *kvm, int irq)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
@@ -445,7 +452,7 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
 		if (!kvm_arm_pmu_irq_initialized(vcpu))
 			continue;
 
-		if (is_ppi) {
+		if (irq_is_ppi(irq)) {
 			if (vcpu->arch.pmu.irq_num != irq)
 				return false;
 		} else {
@@ -457,7 +464,6 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
 	return true;
 }
 
-
 int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 {
 	switch (attr->attr) {
@@ -471,14 +477,11 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 		if (get_user(irq, uaddr))
 			return -EFAULT;
 
-		/*
-		 * The PMU overflow interrupt could be a PPI or SPI, but for one
-		 * VM the interrupt type must be same for each vcpu. As a PPI,
-		 * the interrupt number is the same for all vcpus, while as an
-		 * SPI it must be a separate number per vcpu.
-		 */
-		if (irq < VGIC_NR_SGIS || irq >= vcpu->kvm->arch.vgic.nr_irqs ||
-		    !irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
+		/* The PMU overflow interrupt can be a PPI or a valid SPI. */
+		if (!(irq_is_ppi(irq) || vgic_valid_spi(vcpu->kvm, irq)))
+			return -EINVAL;
+
+		if (!pmu_irq_is_valid(vcpu->kvm, irq))
 			return -EINVAL;
 
 		if (kvm_arm_pmu_irq_initialized(vcpu))
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:24 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:24 +0100
Subject: [PATCH v4 36/56] KVM: arm/arm64: vgic-new: Add GICv3 IDREGS register
 handler
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-37-git-send-email-andre.przywara@arm.com>

We implement the only one ID register that is required by the
architecture, also this is the one that Linux actually checks.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 28de16a..b893284 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -96,6 +96,18 @@ static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
 	return (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
 }
 
+static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu,
+					      gpa_t addr, unsigned int len)
+{
+	switch (addr & 0xffff) {
+	case GICD_PIDR2:
+		/* report a GICv3 compliant implementation */
+		return 0x3b;
+	}
+
+	return 0;
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -161,7 +173,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
 		VGIC_ACCESS_32bit),
 };
 
@@ -182,7 +194,7 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
 		VGIC_ACCESS_32bit),
 };
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:25 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:25 +0100
Subject: [PATCH v4 37/56] KVM: arm/arm64: vgic-new: Add GICv3 IROUTER register
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-38-git-send-email-andre.przywara@arm.com>

Since GICv3 supports much more than the 8 CPUs the GICv2 ITARGETSR
register can handle, the new IROUTER register covers the whole range
of possible target (V)CPUs by using the same MPIDR that the cores
report themselves.
In addition to translating this MPIDR into a vcpu pointer we store
the originally written value as well. The architecture allows to
write any values into the register, which must be read back as written.

Since we don't support affinity level 3, we don't need to take care
about the upper word of this 64-bit register, which simplifies the
handling a bit.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- fold in and simplify vgic_v3_irq_change_affinity

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- move accessor width check into dispatcher
- use IRQ number accessor macro

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index b893284..7b9340b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -75,6 +75,41 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	int intid = VGIC_ADDR_TO_INTID(addr, 64);
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+
+	if (!irq)
+		return 0;
+
+	return extract_bytes(READ_ONCE(irq->mpidr), addr & 7, len);
+}
+
+static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	int intid = VGIC_ADDR_TO_INTID(addr, 64);
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+
+	if (!irq)
+		return;
+
+	/* The upper word is WI for us since we don't implement Aff3. */
+	if (addr & 4)
+		return;
+
+	spin_lock(&irq->irq_lock);
+
+	/* We only care about and preserve Aff0, Aff1 and Aff2. */
+	irq->mpidr = val & GENMASK(23, 0);
+	irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, irq->mpidr);
+
+	spin_unlock(&irq->irq_lock);
+}
+
 static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
 					      gpa_t addr, unsigned int len)
 {
@@ -170,7 +205,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
+		vgic_mmio_read_irouter, vgic_mmio_write_irouter, 64,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
 		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:10 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:10 +0100
Subject: [PATCH v4 22/56] KVM: arm/arm64: vgic-new: Add MMIO handling framework
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-23-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Add an MMIO handling framework to the VGIC emulation:
Each register is described by its offset, size (or number of bits per
IRQ, if applicable) and the read/write handler functions. We provide
initialization macros to describe each GIC register later easily.

Separate dispatch functions for read and write accesses are connected
to the kvm_io_bus framework and binary-search for the responsible
register handler based on the offset address within the region.
We convert the incoming data (referenced by a pointer) to the host's
endianess and use pass-by-value to hand the data over to the actual
handler functions.

The register handler prototype and the endianess conversion are
courtesy of Christoffer Dall.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- rework MMIO dispatching to use only one kvm_io_bus device
- document purpose of register region macros
- rename "this" parameter to "dev"
- change IGROUPR to be RAO (returning 1 => Group1 IRQs)

Changelog v1 .. v2:
* MASSIVE rework:
- store register_region pointer in kvm_io_bus linked struct
- replace write_mask_xxx functions with extract_bytes() implementation
- change handler functions' prototypes to take and return unsigned long
- use binary search to find matching register handler
- convert endianess of input data in dispatch_mmio_xxx functions
- improve readability of register initializer macros
- remove any GICv2/GICv3 specific functions from vgic-mmio.c
- rename file from vgic_mmio.c to vgic-mmio.c

Changelog v2 .. v3:
- replace inclusion of vgic/vgic.h with arm_vgic.h

Changelog v3 .. v4:
- add IRQ number accessor macro
- check access width in dispatcher
- treat non-covered MMIO addresses as RAZ/WI
- remove extract_bytes() (re-introduced as static later in the series)

 include/kvm/vgic/vgic.h       |  13 +++
 virt/kvm/arm/vgic/vgic-mmio.c | 184 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h |  87 ++++++++++++++++++++
 3 files changed, 284 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index f663288..ff3f9c2 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -106,6 +106,16 @@ struct vgic_irq {
 	enum vgic_irq_config config;	/* Level or edge */
 };
 
+struct vgic_register_region;
+
+struct vgic_io_device {
+	gpa_t base_addr;
+	struct kvm_vcpu *redist_vcpu;
+	const struct vgic_register_region *regions;
+	int nr_regions;
+	struct kvm_io_device dev;
+};
+
 struct vgic_dist {
 	bool			in_kernel;
 	bool			ready;
@@ -132,6 +142,9 @@ struct vgic_dist {
 	bool			enabled;
 
 	struct vgic_irq		*spis;
+
+	struct vgic_io_device	dist_iodev;
+	struct vgic_io_device	*redist_iodevs;
 };
 
 struct vgic_v2_cpu_if {
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
new file mode 100644
index 0000000..012b82b
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -0,0 +1,184 @@
+/*
+ * VGIC MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/bsearch.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len)
+{
+	return 0;
+}
+
+unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len)
+{
+	return -1UL;
+}
+
+void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
+			unsigned int len, unsigned long val)
+{
+	/* Ignore */
+}
+
+static int match_region(const void *key, const void *elt)
+{
+	const unsigned int offset = (unsigned long)key;
+	const struct vgic_register_region *region = elt;
+
+	if (offset < region->reg_offset)
+		return -1;
+
+	if (offset >= region->reg_offset + region->len)
+		return 1;
+
+	return 0;
+}
+
+/* Find the proper register handler entry given a certain address offset. */
+static const struct vgic_register_region *
+vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
+		      unsigned int offset)
+{
+	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
+		       sizeof(region[0]), match_region);
+}
+
+/*
+ * kvm_mmio_read_buf() returns a value in a format where it can be converted
+ * to a byte array and be directly observed as the guest wanted it to appear
+ * in memory if it had done the store itself, which is LE for the GIC, as the
+ * guest knows the GIC is always LE.
+ *
+ * We convert this value to the CPUs native format to deal with it as a data
+ * value.
+ */
+unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len)
+{
+	unsigned long data = kvm_mmio_read_buf(val, len);
+
+	switch (len) {
+	case 1:
+		return data;
+	case 2:
+		return le16_to_cpu(data);
+	case 4:
+		return le32_to_cpu(data);
+	default:
+		return le64_to_cpu(data);
+	}
+}
+
+/*
+ * kvm_mmio_write_buf() expects a value in a format such that if converted to
+ * a byte array it is observed as the guest would see it if it could perform
+ * the load directly.  Since the GIC is LE, and the guest knows this, the
+ * guest expects a value in little endian format.
+ *
+ * We convert the data value from the CPUs native format to LE so that the
+ * value is returned in the proper format.
+ */
+void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
+				unsigned long data)
+{
+	switch (len) {
+	case 1:
+		break;
+	case 2:
+		data = cpu_to_le16(data);
+		break;
+	case 4:
+		data = cpu_to_le32(data);
+		break;
+	default:
+		data = cpu_to_le64(data);
+	}
+
+	kvm_mmio_write_buf(buf, len, data);
+}
+
+static
+struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
+{
+	return container_of(dev, struct vgic_io_device, dev);
+}
+
+static bool check_region(const struct vgic_register_region *region,
+			 gpa_t addr, int len)
+{
+	if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1)
+		return true;
+	if ((region->access_flags & VGIC_ACCESS_32bit) &&
+	    len == sizeof(u32) && !(addr & 3))
+		return true;
+	if ((region->access_flags & VGIC_ACCESS_64bit) &&
+	    len == sizeof(u64) && !(addr & 7))
+		return true;
+
+	return false;
+}
+
+static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
+			      gpa_t addr, int len, void *val)
+{
+	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
+	const struct vgic_register_region *region;
+	struct kvm_vcpu *r_vcpu;
+	unsigned long data;
+
+	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
+				       addr - iodev->base_addr);
+	if (!region || !check_region(region, addr, len)) {
+		memset(val, 0, len);
+		return 0;
+	}
+
+	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
+	data = region->read(r_vcpu, addr, len);
+	vgic_data_host_to_mmio_bus(val, len, data);
+	return 0;
+}
+
+static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
+			       gpa_t addr, int len, const void *val)
+{
+	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
+	const struct vgic_register_region *region;
+	struct kvm_vcpu *r_vcpu;
+	unsigned long data = vgic_data_mmio_bus_to_host(val, len);
+
+	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
+				       addr - iodev->base_addr);
+	if (!region)
+		return 0;
+
+	if (!check_region(region, addr, len))
+		return 0;
+
+	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
+	region->write(r_vcpu, addr, len, data);
+	return 0;
+}
+
+struct kvm_io_device_ops kvm_io_gic_ops = {
+	.read = dispatch_mmio_read,
+	.write = dispatch_mmio_write,
+};
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
new file mode 100644
index 0000000..855b1db
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __KVM_ARM_VGIC_MMIO_H__
+#define __KVM_ARM_VGIC_MMIO_H__
+
+struct vgic_register_region {
+	unsigned int reg_offset;
+	unsigned int len;
+	unsigned int bits_per_irq;
+	unsigned int access_flags;
+	unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr,
+			      unsigned int len);
+	void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
+		      unsigned long val);
+};
+
+extern struct kvm_io_device_ops kvm_io_gic_ops;
+
+#define VGIC_ACCESS_8bit	1
+#define VGIC_ACCESS_32bit	2
+#define VGIC_ACCESS_64bit	4
+
+/* generate a mask that covers 1024 interrupts with <b> bits per IRQ */
+#define VGIC_ADDR_IRQ_MASK(b) GENMASK_ULL(ilog2(b) + ilog2(1024) - \
+					  ilog2(BITS_PER_BYTE) - 1, 0)
+#define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
+					64 / (bits) / 8)
+
+/*
+ * Some VGIC registers store per-IRQ information, with a different number
+ * of bits per IRQ. For those registers this macro is used.
+ * The _WITH_LENGTH version instantiates registers with a fixed length
+ * and is mutually exclusive with the _PER_IRQ version.
+ */
+#define REGISTER_DESC_WITH_BITS_PER_IRQ(off, rd, wr, bpi, acc)		\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = bpi,					\
+		.len = bpi * 1024 / 8,					\
+		.access_flags = acc,					\
+		.read = rd,						\
+		.write = wr,						\
+	}
+
+#define REGISTER_DESC_WITH_LENGTH(off, rd, wr, length, acc)		\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = 0,					\
+		.len = length,						\
+		.access_flags = acc,					\
+		.read = rd,						\
+		.write = wr,						\
+	}
+
+int kvm_vgic_register_mmio_region(struct kvm *kvm, struct kvm_vcpu *vcpu,
+				  struct vgic_register_region *reg_desc,
+				  struct vgic_io_device *region,
+				  int nr_irqs, bool offset_private);
+
+unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len);
+
+void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
+				unsigned long data);
+
+unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len);
+
+unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
+			unsigned int len, unsigned long val);
+
+#endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:26 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:26 +0100
Subject: [PATCH v4 38/56] KVM: arm/arm64: vgic-new: Add GICv3 SGI system
 register trap handler
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-39-git-send-email-andre.przywara@arm.com>

In contrast to GICv2 SGIs in a GICv3 implementation are not triggered
by a MMIO write, but with a system register write. KVM knows about
that register already, we just need to implement the handler and wire
it up to the core KVM/ARM code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- add comment about SGI_AFFINITY_LEVEL macro

 include/kvm/vgic/vgic.h          |   8 +++
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 106 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index ff3f9c2..00e3dca 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -209,6 +209,14 @@ bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
 
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
+#else
+static inline void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
+{
+}
+#endif
+
 /**
  * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
  *
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 7b9340b..63b8550 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -343,3 +343,109 @@ int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
 
 	return ret;
 }
+
+/*
+ * Compare a given affinity (level 1-3 and a level 0 mask, from the SGI
+ * generation register ICC_SGI1R_EL1) with a given VCPU.
+ * If the VCPU's MPIDR matches, return the level0 affinity, otherwise
+ * return -1.
+ */
+static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct kvm_vcpu *vcpu)
+{
+	unsigned long affinity;
+	int level0;
+
+	/*
+	 * Split the current VCPU's MPIDR into affinity level 0 and the
+	 * rest as this is what we have to compare against.
+	 */
+	affinity = kvm_vcpu_get_mpidr_aff(vcpu);
+	level0 = MPIDR_AFFINITY_LEVEL(affinity, 0);
+	affinity &= ~MPIDR_LEVEL_MASK;
+
+	/* bail out if the upper three levels don't match */
+	if (sgi_aff != affinity)
+		return -1;
+
+	/* Is this VCPU's bit set in the mask ? */
+	if (!(sgi_cpu_mask & BIT(level0)))
+		return -1;
+
+	return level0;
+}
+
+/*
+ * The ICC_SGI* registers encode the affinity differently from the MPIDR,
+ * so provide a wrapper to use the existing defines to isolate a certain
+ * affinity level.
+ */
+#define SGI_AFFINITY_LEVEL(reg, level) \
+	((((reg) & ICC_SGI1R_AFFINITY_## level ##_MASK) \
+	>> ICC_SGI1R_AFFINITY_## level ##_SHIFT) << MPIDR_LEVEL_SHIFT(level))
+
+/**
+ * vgic_v3_dispatch_sgi - handle SGI requests from VCPUs
+ * @vcpu: The VCPU requesting a SGI
+ * @reg: The value written into the ICC_SGI1R_EL1 register by that VCPU
+ *
+ * With GICv3 (and ARE=1) CPUs trigger SGIs by writing to a system register.
+ * This will trap in sys_regs.c and call this function.
+ * This ICC_SGI1R_EL1 register contains the upper three affinity levels of the
+ * target processors as well as a bitmask of 16 Aff0 CPUs.
+ * If the interrupt routing mode bit is not set, we iterate over all VCPUs to
+ * check for matching ones. If this bit is set, we signal all, but not the
+ * calling VCPU.
+ */
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
+{
+	struct kvm *kvm = vcpu->kvm;
+	struct kvm_vcpu *c_vcpu;
+	u16 target_cpus;
+	u64 mpidr;
+	int sgi, c;
+	int vcpu_id = vcpu->vcpu_id;
+	bool broadcast;
+
+	sgi = (reg & ICC_SGI1R_SGI_ID_MASK) >> ICC_SGI1R_SGI_ID_SHIFT;
+	broadcast = reg & BIT(ICC_SGI1R_IRQ_ROUTING_MODE_BIT);
+	target_cpus = (reg & ICC_SGI1R_TARGET_LIST_MASK) >> ICC_SGI1R_TARGET_LIST_SHIFT;
+	mpidr = SGI_AFFINITY_LEVEL(reg, 3);
+	mpidr |= SGI_AFFINITY_LEVEL(reg, 2);
+	mpidr |= SGI_AFFINITY_LEVEL(reg, 1);
+
+	/*
+	 * We iterate over all VCPUs to find the MPIDRs matching the request.
+	 * If we have handled one CPU, we clear its bit to detect early
+	 * if we are already finished. This avoids iterating through all
+	 * VCPUs when most of the times we just signal a single VCPU.
+	 */
+	kvm_for_each_vcpu(c, c_vcpu, kvm) {
+		struct vgic_irq *irq;
+
+		/* Exit early if we have dealt with all requested CPUs */
+		if (!broadcast && target_cpus == 0)
+			break;
+
+		/* Don't signal the calling VCPU */
+		if (broadcast && c == vcpu_id)
+			continue;
+
+		if (!broadcast) {
+			int level0;
+
+			level0 = match_mpidr(mpidr, target_cpus, c_vcpu);
+			if (level0 == -1)
+				continue;
+
+			/* remove this matching VCPU from the mask */
+			target_cpus &= ~BIT(level0);
+		}
+
+		irq = vgic_get_irq(vcpu->kvm, c_vcpu, sgi);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:28 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:28 +0100
Subject: [PATCH v4 40/56] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_NR_IRQS
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-41-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_NR_IRQS group. This
modality is supported by both VGIC V2 and V3 KVM device as will be
other groups, hence the introduction of common helpers.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 83 +++++++++++++++++++++++++++++++++++--
 1 file changed, 79 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index ff332f3..05ff925 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -15,9 +15,69 @@
  */
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
+#include <linux/uaccess.h>
+#include "vgic.h"
 
 /* common helpers */
 
+static int vgic_set_common_attr(struct kvm_device *dev,
+				struct kvm_device_attr *attr)
+{
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 val;
+		int ret = 0;
+
+		if (get_user(val, uaddr))
+			return -EFAULT;
+
+		/*
+		 * We require:
+		 * - at least 32 SPIs on top of the 16 SGIs and 16 PPIs
+		 * - at most 1024 interrupts
+		 * - a multiple of 32 interrupts
+		 */
+		if (val < (VGIC_NR_PRIVATE_IRQS + 32) ||
+		    val > VGIC_MAX_RESERVED ||
+		    (val & 31))
+			return -EINVAL;
+
+		mutex_lock(&dev->kvm->lock);
+
+		if (vgic_ready(dev->kvm) || dev->kvm->arch.vgic.nr_spis)
+			ret = -EBUSY;
+		else
+			dev->kvm->arch.vgic.nr_spis =
+				val - VGIC_NR_PRIVATE_IRQS;
+
+		mutex_unlock(&dev->kvm->lock);
+
+		return ret;
+	}
+	}
+
+	return -ENXIO;
+}
+
+static int vgic_get_common_attr(struct kvm_device *dev,
+				struct kvm_device_attr *attr)
+{
+	int r = -ENXIO;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+
+		r = put_user(dev->kvm->arch.vgic.nr_spis +
+			     VGIC_NR_PRIVATE_IRQS, uaddr);
+		break;
+	}
+	}
+
+	return r;
+}
+
 static int vgic_create(struct kvm_device *dev, u32 type)
 {
 	return kvm_vgic_create(dev->kvm, type);
@@ -49,18 +109,29 @@ void kvm_register_vgic_device(unsigned long type)
 static int vgic_v2_set_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	int ret;
+
+	ret = vgic_set_common_attr(dev, attr);
+	return ret;
+
 }
 
 static int vgic_v2_get_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	int ret;
+
+	ret = vgic_get_common_attr(dev, attr);
+	return ret;
 }
 
 static int vgic_v2_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
+		return 0;
+	}
 	return -ENXIO;
 }
 
@@ -80,18 +151,22 @@ struct kvm_device_ops kvm_arm_vgic_v2_ops = {
 static int vgic_v3_set_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	return vgic_set_common_attr(dev, attr);
 }
 
 static int vgic_v3_get_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	return vgic_get_common_attr(dev, attr);
 }
 
 static int vgic_v3_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
+		return 0;
+	}
 	return -ENXIO;
 }
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:30 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:30 +0100
Subject: [PATCH v4 42/56] KVM: arm/arm64: vgic-new: vgic_kvm_device: implement
 kvm_vgic_addr
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-43-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

kvm_vgic_addr is used by the userspace to set the base address of
the following register regions, as seen by the guest:
- distributor(v2 and v3),
- re-distributors (v3),
- CPU interface (v2).

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v3 .. v4:
- move overlap check to init time (cannot work with GICv3 here)
- refactor remaining address sanity checks

 include/kvm/vgic/vgic.h             |  2 +
 virt/kvm/arm/vgic/vgic-kvm-device.c | 86 +++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |  3 ++
 3 files changed, 91 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 00e3dca..3689b9b 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -194,6 +194,8 @@ struct vgic_cpu {
 	u64 live_lrs;
 };
 
+int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
 
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index e153f12..082829a 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -16,10 +16,96 @@
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
 #include <linux/uaccess.h>
+#include <asm/kvm_mmu.h>
 #include "vgic.h"
 
 /* common helpers */
 
+static int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
+			     phys_addr_t addr, phys_addr_t alignment)
+{
+	if (addr & ~KVM_PHYS_MASK)
+		return -E2BIG;
+
+	if (!IS_ALIGNED(addr, alignment))
+		return -EINVAL;
+
+	if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
+		return -EEXIST;
+
+	return 0;
+}
+
+/**
+ * kvm_vgic_addr - set or get vgic VM base addresses
+ * @kvm:   pointer to the vm struct
+ * @type:  the VGIC addr type, one of KVM_VGIC_V[23]_ADDR_TYPE_XXX
+ * @addr:  pointer to address value
+ * @write: if true set the address in the VM address space, if false read the
+ *          address
+ *
+ * Set or get the vgic base addresses for the distributor and the virtual CPU
+ * interface in the VM physical address space.  These addresses are properties
+ * of the emulated core/SoC and therefore user space initially knows this
+ * information.
+ * Check them for sanity (alignment, double assignment). We can't check for
+ * overlapping regions in case of a virtual GICv3 here, since we don't know
+ * the number of VCPUs yet, so we defer this check to map_resources().
+ */
+int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
+{
+	int r = 0;
+	struct vgic_dist *vgic = &kvm->arch.vgic;
+	int type_needed;
+	phys_addr_t *addr_ptr, alignment;
+
+	mutex_lock(&kvm->lock);
+	switch (type) {
+	case KVM_VGIC_V2_ADDR_TYPE_DIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+		addr_ptr = &vgic->vgic_dist_base;
+		alignment = SZ_4K;
+		break;
+	case KVM_VGIC_V2_ADDR_TYPE_CPU:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+		addr_ptr = &vgic->vgic_cpu_base;
+		alignment = SZ_4K;
+		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case KVM_VGIC_V3_ADDR_TYPE_DIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+		addr_ptr = &vgic->vgic_dist_base;
+		alignment = SZ_64K;
+		break;
+	case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+		addr_ptr = &vgic->vgic_redist_base;
+		alignment = SZ_64K;
+		break;
+#endif
+	default:
+		r = -ENODEV;
+		goto out;
+	}
+
+	if (vgic->vgic_model != type_needed) {
+		r = -ENODEV;
+		goto out;
+	}
+
+	if (write) {
+		r = vgic_check_ioaddr(kvm, addr_ptr, *addr, alignment);
+		if (!r)
+			*addr_ptr = *addr;
+	} else {
+		*addr = *addr_ptr;
+	}
+
+out:
+	mutex_unlock(&kvm->lock);
+	return r;
+}
+
 static int vgic_set_common_attr(struct kvm_device *dev,
 				struct kvm_device_attr *attr)
 {
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 77b0ab3..6abc9a3 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,9 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define VGIC_ADDR_UNDEF		(-1)
+#define IS_VGIC_ADDR_UNDEF(_x)  ((_x) == VGIC_ADDR_UNDEF)
+
 #define INTERRUPT_ID_BITS_SPIS	10
 #define VGIC_PRI_BITS		5
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:31 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:31 +0100
Subject: [PATCH v4 43/56] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_ADDR
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-44-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_ADDR group which
enables to set the base address of GIC regions as seen by the guest.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 38 +++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 082829a..a709097 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -112,6 +112,17 @@ static int vgic_set_common_attr(struct kvm_device *dev,
 	int r;
 
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 addr;
+		unsigned long type = (unsigned long)attr->attr;
+
+		if (copy_from_user(&addr, uaddr, sizeof(addr)))
+			return -EFAULT;
+
+		r = kvm_vgic_addr(dev->kvm, type, &addr, true);
+		return (r == -ENODEV) ? -ENXIO : r;
+	}
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
 		u32 val;
@@ -164,6 +175,19 @@ static int vgic_get_common_attr(struct kvm_device *dev,
 	int r = -ENXIO;
 
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 addr;
+		unsigned long type = (unsigned long)attr->attr;
+
+		r = kvm_vgic_addr(dev->kvm, type, &addr, false);
+		if (r)
+			return (r == -ENODEV) ? -ENXIO : r;
+
+		if (copy_to_user(uaddr, &addr, sizeof(addr)))
+			return -EFAULT;
+		break;
+	}
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
 
@@ -227,6 +251,13 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR:
+		switch (attr->attr) {
+		case KVM_VGIC_V2_ADDR_TYPE_DIST:
+		case KVM_VGIC_V2_ADDR_TYPE_CPU:
+			return 0;
+		}
+		break;
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
@@ -267,6 +298,13 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR:
+		switch (attr->attr) {
+		case KVM_VGIC_V3_ADDR_TYPE_DIST:
+		case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+			return 0;
+		}
+		break;
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:09 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:09 +0100
Subject: [PATCH v4 21/56] KVM: arm/arm64: vgic-new: Implement
 kvm_vgic_vcpu_pending_irq
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-22-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

Tell KVM whether a particular VCPU has an IRQ that needs handling
in the guest. This is used to decide whether a VCPU is runnable.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog RFC..v1:
- return false if distributor is disabled
- add vgic_kick_vcpus() implementations

Changelog v2 .. v3:
- remove vgic_kick_vcpus() implementation from this patch

 include/kvm/vgic/vgic.h  |  2 ++
 virt/kvm/arm/vgic/vgic.c | 25 +++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 9506267..f663288 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -184,6 +184,8 @@ struct vgic_cpu {
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
 
+int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
+
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(false)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index eca3cd0..bea8d3b 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -519,3 +519,28 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 	vgic_flush_lr_state(vcpu);
 	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
 }
+
+int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	bool pending = false;
+
+	if (!vcpu->kvm->arch.vgic.enabled)
+		return false;
+
+	spin_lock(&vgic_cpu->ap_list_lock);
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+		pending = irq->pending && irq->enabled;
+		spin_unlock(&irq->irq_lock);
+
+		if (pending)
+			break;
+	}
+
+	spin_unlock(&vgic_cpu->ap_list_lock);
+
+	return pending;
+}
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:15 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:15 +0100
Subject: [PATCH v4 27/56] KVM: arm/arm64: vgic-new: Add ACTIVE registers
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-28-git-send-email-andre.przywara@arm.com>

The active register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.
Since activation/deactivation of an interrupt may happen entirely
in the guest without it ever exiting, we need some extra logic to
properly track the active state.
Putting it on an ap_list on activation is similar to the normal case
handled by vgic_queue_irq_unlock(), but differs in some details that
make a separate implementation worthwhile.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- handling queueing in write handler
- remove IRQ lock from read handler

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro
- drop elaborate write_sactive handler and use new vgic_queue_irq_unlock()
- properly emulate clear active by halting the guest (Christoffer)
- replace extract_bytes() with simple return

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 82 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 10 +++++
 3 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index c13a708..12e101b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -84,10 +84,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index d8dc8f6..74d140e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -155,6 +155,88 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->active)
+			value |= (1U << i);
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	kvm_arm_halt_guest(vcpu->kvm);
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		/*
+		 * If this virtual IRQ was written into a list register, we
+		 * have to make sure the CPU that runs the VCPU thread has
+		 * synced back LR state to the struct vgic_irq.  We can only
+		 * know this for sure, when either this irq is not assigned to
+		 * anyone's AP list anymore, or the VCPU thread is not
+		 * running on any CPUs.
+		 *
+		 * In the opposite case, we know the VCPU thread may be on its
+		 * way back from the guest and still has to sync back this
+		 * IRQ, so we release and re-acquire the spin_lock to let the
+		 * other thread sync back the IRQ.
+		 */
+		while (irq->vcpu && /* IRQ may have state in an LR somewhere */
+		       irq->vcpu->cpu != -1) /* VCPU thread is running */
+			cond_resched_lock(&irq->irq_lock);
+
+		irq->active = false;
+		spin_unlock(&irq->irq_lock);
+	}
+	kvm_arm_resume_guest(vcpu->kvm);
+}
+
+void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		/*
+		 * If the IRQ was already active or it was on a VCPU before
+		 * or there is no target VCPU assigned at the moment, then
+		 * just proceed.
+		 */
+		if (irq->active || irq->vcpu || !irq->target_vcpu) {
+			irq->active = true;
+
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		irq->active = true;
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 01db98a..dd96a71 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -106,6 +106,16 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
 			      gpa_t addr, unsigned int len,
 			      unsigned long val);
 
+unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
+void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
 
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:13 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:13 +0100
Subject: [PATCH v4 25/56] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-26-git-send-email-andre.przywara@arm.com>

As the enable register handlers are shared between the v2 and v3
emulation, their implementation goes into vgic-mmio.c, to be easily
referenced from the v3 emulation as well later.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog RFC..v1:
- use lower bits of address to determine IRQ number
- remove TODO, confirmed to be fine

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro
- replace extract_bytes() with simple return

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
 virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
 3 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index d812c93..d5355b5 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -72,10 +72,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 1a97765..32ed8db 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -39,6 +39,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 	/* Ignore */
 }
 
+/*
+ * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
+ * of the enabled bit, so there is only one function for both here.
+ */
+unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->enabled)
+			value |= (1U << i);
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		irq->enabled = true;
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
+void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->enabled = false;
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 10404ac..66fd6fa 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -84,6 +84,17 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
 void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 			unsigned int len, unsigned long val);
 
+unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
+void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:12 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:12 +0100
Subject: [PATCH v4 24/56] KVM: arm/arm64: vgic-new: Add CTLR,
 TYPER and IIDR handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-25-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Those three registers are v2 emulation specific, so their implementation
lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
as their implementation is pretty simple.
When the guest enables the distributor, we kick all VCPUs to get
potentially pending interrupts serviced.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- kick VCPUs is the distributor gets enabled
- improve comment

Changelog v1 .. v2:
- adapt to new MMIO framework
- use switch() statements to improve readability

Changelog v2 .. v3:
- add vgic_kick_vcpus() implementation

Changelog v3 .. v4;
- specify accessor width
- simplify CTLR write access
- replace extract_bytes() with simple return

 include/linux/irqchip/arm-gic.h  |  1 +
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 46 +++++++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
 virt/kvm/arm/vgic/vgic.h         |  4 ++++
 4 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index be0d26f..fd05185 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -33,6 +33,7 @@
 
 #define GIC_DIST_CTRL			0x000
 #define GIC_DIST_CTR			0x004
+#define GIC_DIST_IIDR			0x008
 #define GIC_DIST_IGROUP			0x080
 #define GIC_DIST_ENABLE_SET		0x100
 #define GIC_DIST_ENABLE_CLEAR		0x180
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index a3e31a9..d812c93 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -20,9 +20,53 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 value;
+
+	switch (addr & 0x0c) {
+	case GIC_DIST_CTRL:
+		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
+		break;
+	case GIC_DIST_CTR:
+		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+		value = (value >> 5) - 1;
+		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
+		break;
+	case GIC_DIST_IIDR:
+		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+		break;
+	default:
+		return 0;
+	}
+
+	return value;
+}
+
+static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+	bool was_enabled = dist->enabled;
+
+	switch (addr & 0x0c) {
+	case GIC_DIST_CTRL:
+		dist->enabled = val & GICD_ENABLE;
+		if (!was_enabled && dist->enabled)
+			vgic_kick_vcpus(vcpu->kvm);
+		break;
+	case GIC_DIST_CTR:
+	case GIC_DIST_IIDR:
+		/* Nothing to do */
+		return;
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 12,
+		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index bea8d3b..2a41028 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -544,3 +544,18 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 
 	return pending;
 }
+
+void vgic_kick_vcpus(struct kvm *kvm)
+{
+	struct kvm_vcpu *vcpu;
+	int c;
+
+	/*
+	 * We've injected an interrupt, time to find out who deserves
+	 * a good kick...
+	 */
+	kvm_for_each_vcpu(c, vcpu, kvm) {
+		if (kvm_vgic_vcpu_pending_irq(vcpu))
+			kvm_vcpu_kick(vcpu);
+	}
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index fd9acaa..cf62015 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,11 +16,15 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
+#define IMPLEMENTER_ARM		0x43b
+
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
+void vgic_kick_vcpus(struct kvm *kvm);
 
 void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
 void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:04 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:04 +0100
Subject: [PATCH v4 16/56] KVM: arm/arm64: vgic-new: Implement virtual IRQ
 injection
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-17-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Provide a vgic_queue_irq_unlock() function which decides whether a
given IRQ needs to be queued to a VCPU's ap_list.
This should be called whenever an IRQ becomes pending or enabled,
either as a result of userspace injection, from in-kernel emulated
devices like the architected timer or from MMIO accesses to the
distributor emulation.
Also provides the necessary functions to allow userland to inject an
IRQ to a guest.
Since this is the first code that starts using our locking mechanism, we
add some (hopefully) clear documentation of our locking strategy and
requirements along with this patch.

[Andre: refactor out vgic_queue_irq_unlock()]

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- add spinlock checks protected by CONFIG_DEBUG_SPINLOCK
- add more comments to vgic_target_oracle
- remove BUG_ON() if IRQ is neither edge or level
- rename vgic_queue_irq() to vgic_queue_irq_unlock()
- simplify initial check in vgic_queue_irq_unlock()
- extend retry loop to ask the oracle again
- minor comment fixes

Changelog v1 .. v2:
- move most IRQ injection code into vgic_update_irq_pending()

Changelog v3 .. v4:
- simplify vgic_queue_irq_unlock() to allow reusage later

 include/kvm/vgic/vgic.h  |   3 +
 virt/kvm/arm/vgic/vgic.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h |   1 +
 3 files changed, 215 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 6ca0781..7b6ca90 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -181,6 +181,9 @@ struct vgic_cpu {
 	u64 live_lrs;
 };
 
+int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			bool level);
+
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(false)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index fb45537..62fede6 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -19,8 +19,31 @@
 
 #include "vgic.h"
 
+#define CREATE_TRACE_POINTS
+#include "../trace.h"
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+#define DEBUG_SPINLOCK_BUG_ON(p) BUG_ON(p)
+#else
+#define DEBUG_SPINLOCK_BUG_ON(p)
+#endif
+
 struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
 
+/*
+ * Locking order is always:
+ *   vgic_cpu->ap_list_lock
+ *     vgic_irq->irq_lock
+ *
+ * (that is, always take the ap_list_lock before the struct vgic_irq lock).
+ *
+ * When taking more than one ap_list_lock at the same time, always take the
+ * lowest numbered VCPU's ap_list_lock first, so:
+ *   vcpuX->vcpu_id < vcpuY->vcpu_id:
+ *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
+ *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
+ */
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid)
 {
@@ -39,3 +62,191 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 	WARN(1, "Looking up struct vgic_irq for reserved INTID");
 	return NULL;
 }
+
+/**
+ * kvm_vgic_target_oracle - compute the target vcpu for an irq
+ *
+ * @irq:	The irq to route. Must be already locked.
+ *
+ * Based on the current state of the interrupt (enabled, pending,
+ * active, vcpu and target_vcpu), compute the next vcpu this should be
+ * given to. Return NULL if this shouldn't be injected at all.
+ *
+ * Requires the IRQ lock to be held.
+ */
+static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
+{
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+	/* If the interrupt is active, it must stay on the current vcpu */
+	if (irq->active)
+		return irq->vcpu;
+
+	/*
+	 * If the IRQ is not active but enabled and pending, we should direct
+	 * it to its configured target VCPU.
+	 * If the distributor is disabled, pending interrupts shouldn't be
+	 * forwarded.
+	 */
+	if (irq->enabled && irq->pending) {
+		if (unlikely(irq->target_vcpu &&
+			     !irq->target_vcpu->kvm->arch.vgic.enabled))
+			return NULL;
+
+		return irq->target_vcpu;
+	}
+
+	/* If neither active nor pending and enabled, then this IRQ should not
+	 * be queued to any VCPU.
+	 */
+	return NULL;
+}
+
+/*
+ * Only valid injection if changing level for level-triggered IRQs or for a
+ * rising edge.
+ */
+static bool vgic_validate_injection(struct vgic_irq *irq, bool level)
+{
+	switch (irq->config) {
+	case VGIC_CONFIG_LEVEL:
+		return irq->line_level != level;
+	case VGIC_CONFIG_EDGE:
+		return level;
+	}
+
+	return false;
+}
+
+/*
+ * Check whether an IRQ needs to (and can) be queued to a VCPU's ap list.
+ * Do the queuing if necessary, taking the right locks in the right order.
+ * Returns true when the IRQ was queued, false otherwise.
+ *
+ * Needs to be entered with the IRQ lock already held, but will return
+ * with all locks dropped.
+ */
+bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq)
+{
+	struct kvm_vcpu *vcpu;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+retry:
+	vcpu = vgic_target_oracle(irq);
+	if (irq->vcpu || !vcpu) {
+		/*
+		 * If this IRQ is already on a VCPU's ap_list, then it
+		 * cannot be moved or modified and there is no more work for
+		 * us to do.
+		 *
+		 * Otherwise, if the irq is not pending and enabled, it does
+		 * not need to be inserted into an ap_list and there is also
+		 * no more work for us to do.
+		 */
+		spin_unlock(&irq->irq_lock);
+		return false;
+	}
+
+	/*
+	 * We must unlock the irq lock to take the ap_list_lock where
+	 * we are going to insert this new pending interrupt.
+	 */
+	spin_unlock(&irq->irq_lock);
+
+	/* someone can do stuff here, which we re-check below */
+
+	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+	spin_lock(&irq->irq_lock);
+
+	/*
+	 * Did something change behind our backs?
+	 *
+	 * There are two cases:
+	 * 1) The irq lost its pending state or was disabled behind our
+	 *    backs and/or it was queued to another VCPU's ap_list.
+	 *    Then drop the locks and return.
+	 * 2) Someone changed the affinity on this irq behind our
+	 *    backs and we are now holding the wrong ap_list_lock.
+	 *    Then drop the locks and try the new VCPU.
+	 */
+
+	if (unlikely(irq->vcpu || vcpu != vgic_target_oracle(irq))) {
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+		spin_lock(&irq->irq_lock);
+		goto retry;
+	}
+
+	list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
+	irq->vcpu = vcpu;
+
+	spin_unlock(&irq->irq_lock);
+	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+	kvm_vcpu_kick(vcpu);
+
+	return true;
+}
+
+static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
+				   unsigned int intid, bool level,
+				   bool mapped_irq)
+{
+	struct kvm_vcpu *vcpu;
+	struct vgic_irq *irq;
+	int ret;
+
+	trace_vgic_update_irq_pending(cpuid, intid, level);
+
+	vcpu = kvm_get_vcpu(kvm, cpuid);
+	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
+		return -EINVAL;
+
+	irq = vgic_get_irq(kvm, vcpu, intid);
+	if (!irq)
+		return -EINVAL;
+
+	if (irq->hw != mapped_irq)
+		return -EINVAL;
+
+	spin_lock(&irq->irq_lock);
+
+	if (!vgic_validate_injection(irq, level)) {
+		/* Nothing to see here, move along... */
+		spin_unlock(&irq->irq_lock);
+		return 0;
+	}
+
+	if (irq->config == VGIC_CONFIG_LEVEL) {
+		irq->line_level = level;
+		irq->pending = level || irq->soft_pending;
+	} else {
+		irq->pending = true;
+	}
+
+	vgic_queue_irq_unlock(kvm, irq);
+
+	return 0;
+}
+
+/**
+ * kvm_vgic_inject_irq - Inject an IRQ from a device to the vgic
+ * @kvm:     The VM structure pointer
+ * @cpuid:   The CPU for PPIs
+ * @intid:   The INTID to inject a new state to.
+ * @level:   Edge-triggered:  true:  to trigger the interrupt
+ *			      false: to ignore the call
+ *	     Level-sensitive  true:  raise the input signal
+ *			      false: lower the input signal
+ *
+ * The VGIC is not concerned with devices being active-LOW or active-HIGH for
+ * level-sensitive interrupts.  You can think of the level parameter as 1
+ * being HIGH and 0 being LOW and all devices being active-HIGH.
+ */
+int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			bool level)
+{
+	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 61b8d22..c625767 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -18,5 +18,6 @@
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
+bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:45 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:45 +0100
Subject: [PATCH v4 00/56] KVM: arm/arm64: Rework virtual GIC emulation
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-58-git-send-email-andre.przywara@arm.com>

Hi,

a new update for the new VGIC series.
A lot of fixes this time: comments fixed, clarified and updated, some
no longer needed code pieces from the old VGIC have been removed.
The MMIO dispatching has been improved to allow only the access types
that are mandatory in the spec, so 32-bit accesses only for most registers
with some additionally accessible by byte or 64-bit accesses as well.
This allows for some simplification in many handler functions.
The vgic_queue_irq_unlock() function was reworked a bit and is now used
by the set-active handler as well. The clear-active handler has been
extended to basically halt the guest and make sure we clear the respective
active bit in the LR (and not only in our structure). There is a new patch
introducing the KVM core bits of this feature.
Also we now detect when the redistributor and distributor regions overlap
and complain about it.
As this series is now based on kvmarm/next, we also gained the firmware
independent probing feature, which is in turn also used in this series.
This should enable ACPI machines.
A more detailed changelog can be found in the respective patches.

As this new VGIC emulation will probably become the default very shortly,
please test it full steam on whatever setup you have access to.
Any reports are warmly welcome.

This series is now based on kvmarm/next, which will be merged shortly into
Linus' kernel.
A git tree containing this series can be found on linux-arm.org:

git://linux-arm.org/linux-ap.git	branch: vgic-new/v4
http://www.linux-arm.org/git?p=linux-ap.git;a=log;h=refs/heads/vgic-new/v4

Cheers,
Andre.

===========================
This series is a joint effort to re-implement KVM's GIC emulation.
Many patches as in here have been effectively authored by multiple
people and authorship isn't clear in every case, especially since
many of the patches have been stashed together or splitted apart in
the process. So take the Author: tag with a grain of salt.

While the current VGIC implementation is centered around providing
efficient MMIO emulation, the hot path for most guests is actually
the guest entry and exit, which currently is rather costly.
Also the existing emulation has a global distributor lock, which
quickly becomes a bottleneck once the number of VCPUs increases.
Additionally the emulation was originally designed for GICv2, adding
GICv3 ITS emulation support to this proved to be rather painful.
Last, but not least the existing code became less and less
maintainable, with many special cases handled explicitly.

The new implementation is build around a struct vgic_irq data
structure, which holds all information about a virtual interrupt.
Interruts which should be injected are held in a per-VCPU list, this
make the entry/exit path much more efficient. Also the new structure
allows to have more fine grained locking - per IRQ and per VCPU -
getting rid of the global distributor lock.
As a result of the new design ITS emulation fits in more nicely, the
respective code will be provided as a follow-up series.

This series implements the same feature set as the existing emulation,
as a goodie we now implement priorities correctly.
To allow an easy transition with good test coverage, but still maintain
stability, both implementations live side by side, selectable via a
Kconfig option. The default is the new implementation.
If this code proves to be reliable, we will later remove the current
implementation with an extra patch set.

Please have a look at the series, review it and give the code some
serious testing (and possibly debugging). All feedback is appreciated.

Cheers,
Andre.

Andre Przywara (29):
  KVM: arm/arm64: vgic: streamline vgic_update_irq_pending() interface
  KVM: arm/arm64: vgic: avoid map in kvm_vgic_inject_mapped_irq()
  KVM: arm/arm64: vgic: avoid map in kvm_vgic_map_is_active()
  KVM: arm/arm64: vgic: avoid map in kvm_vgic_unmap_phys_irq()
  KVM: arm/arm64: arch_timer: Remove irq_phys_map
  KVM: arm/arm64: vgic: Remove irq_phys_map from interface
  KVM: arm/arm64: pmu: abstract access to number of SPIs
  KVM: arm/arm64: move GICv2 emulation defines into arm-gic-v3.h
  KVM: arm/arm64: vgic-new: Add GICv2 MMIO handling framework
  KVM: arm/arm64: vgic-new: Add ENABLE registers handlers
  KVM: arm/arm64: vgic-new: Add PENDING registers handlers
  KVM: arm/arm64: vgic-new: Add ACTIVE registers handlers
  KVM: arm/arm64: vgic-new: Add PRIORITY registers handlers
  KVM: arm/arm64: vgic-new: Add CONFIG registers handlers
  KVM: arm/arm64: vgic-new: Add TARGET registers handlers
  KVM: arm/arm64: vgic-new: Add SGIR register handler
  KVM: arm/arm64: vgic-new: Add SGIPENDR register handlers
  KVM: arm/arm64: vgic-new: Add GICv3 MMIO handling framework
  KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR, TYPER handlers
  KVM: arm/arm64: vgic-new: Add GICv3 redistributor IIDR and TYPER
    handler
  KVM: arm/arm64: vgic-new: Add GICv3 IDREGS register handler
  KVM: arm/arm64: vgic-new: Add GICv3 IROUTER register handlers
  KVM: arm/arm64: vgic-new: Add GICv3 SGI system register trap handler
  KVM: arm/arm64: vgic-new: Add userland access to VGIC dist registers
  KVM: arm/arm64: vgic-new: Add GICH_VMCR accessors
  KVM: arm/arm64: vgic-new: Add userland GIC CPU interface access
  KVM: arm/arm64: vgic-new: Wire up irqfd injection
  KVM: arm/arm64: vgic-new: implement mapped IRQ handling
  KVM: arm/arm64: vgic-new: enable build

Christoffer Dall (10):
  KVM: arm/arm64: Remove the IRQ field from struct irq_phys_map
  KVM: arm/arm64: Get rid of vgic_cpu->nr_lr
  KVM: arm/arm64: Fix MMIO emulation data handling
  KVM: arm/arm64: Export mmio_read/write_bus
  KVM: arm/arm64: Provide functionality to pause and resume a guest
  KVM: arm/arm64: vgic-new: Add data structure definitions
  KVM: arm/arm64: vgic-new: Add acccessor to new struct vgic_irq
    instance
  KVM: arm/arm64: vgic-new: Implement virtual IRQ injection
  KVM: arm/arm64: vgic-new: Add IRQ sorting
  KVM: arm/arm64: vgic-new: Export register access interface

Eric Auger (12):
  KVM: arm/arm64: vgic-new: Implement kvm_vgic_vcpu_pending_irq
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM device ops registration
  KVM: arm/arm64: vgic-new: vgic_kvm_device:
    KVM_DEV_ARM_VGIC_GRP_NR_IRQS
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_CTRL
  KVM: arm/arm64: vgic-new: vgic_kvm_device: implement kvm_vgic_addr
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_ADDR
  KVM: arm/arm64: vgic-new: vgic_kvm_device: access to VGIC registers
  KVM: arm/arm64: vgic-new: vgic_init: implement kvm_vgic_hyp_init
  KVM: arm/arm64: vgic-new: vgic_init: implement vgic_create
  KVM: arm/arm64: vgic-new: vgic_init: implement vgic_init
  KVM: arm/arm64: vgic-new: vgic_init: implement map_resources
  KVM: arm/arm64: vgic-new: Add vgic_v2/v3_enable

Marc Zyngier (5):
  KVM: arm/arm64: vgic-new: Add IRQ sync/flush framework
  KVM: arm/arm64: vgic-new: Add GICv2 world switch backend
  KVM: arm/arm64: vgic-new: Add GICv3 world switch backend
  KVM: arm/arm64: vgic-new: Add MMIO handling framework
  KVM: arm/arm64: vgic-new: Add CTLR, TYPER and IIDR handlers

 arch/arm/include/asm/kvm_host.h     |   4 +
 arch/arm/include/asm/kvm_mmio.h     |   3 +
 arch/arm/kvm/Kconfig                |   7 +
 arch/arm/kvm/Makefile               |  11 +
 arch/arm/kvm/arm.c                  |  25 +-
 arch/arm/kvm/mmio.c                 |  24 +-
 arch/arm64/include/asm/kvm_host.h   |   4 +
 arch/arm64/include/asm/kvm_mmio.h   |   3 +
 arch/arm64/kvm/Kconfig              |   7 +
 arch/arm64/kvm/Makefile             |  12 +
 include/kvm/arm_arch_timer.h        |   3 -
 include/kvm/arm_vgic.h              |  20 +-
 include/kvm/vgic/vgic.h             | 246 +++++++++++++++
 include/linux/irqchip/arm-gic-v3.h  |   6 +
 include/linux/irqchip/arm-gic.h     |   2 +
 virt/kvm/arm/arch_timer.c           |  42 ++-
 virt/kvm/arm/hyp/vgic-v2-sr.c       |  17 +-
 virt/kvm/arm/pmu.c                  |  25 +-
 virt/kvm/arm/vgic-v2.c              |   4 +-
 virt/kvm/arm/vgic-v3.c              |   8 +-
 virt/kvm/arm/vgic.c                 |  86 ++---
 virt/kvm/arm/vgic/vgic-init.c       | 452 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-irqfd.c      |  52 +++
 virt/kvm/arm/vgic/vgic-kvm-device.c | 426 +++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 446 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio-v3.c    | 451 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c       | 499 +++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h       | 138 ++++++++
 virt/kvm/arm/vgic/vgic-v2.c         | 352 +++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c         | 330 +++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c            | 615 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            | 131 ++++++++
 32 files changed, 4314 insertions(+), 137 deletions(-)
 create mode 100644 include/kvm/vgic/vgic.h
 create mode 100644 virt/kvm/arm/vgic/vgic-init.c
 create mode 100644 virt/kvm/arm/vgic/vgic-irqfd.c
 create mode 100644 virt/kvm/arm/vgic/vgic-kvm-device.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v2.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h
 create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
 create mode 100644 virt/kvm/arm/vgic/vgic-v3.c
 create mode 100644 virt/kvm/arm/vgic/vgic.c
 create mode 100644 virt/kvm/arm/vgic/vgic.h

-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:58 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:58 +0100
Subject: [PATCH v4 13/56] KVM: arm/arm64: move GICv2 emulation defines into
 arm-gic-v3.h
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-71-git-send-email-andre.przywara@arm.com>

As (some) GICv3 hosts can emulate a GICv2, some GICv2 specific masks
for the list register definition also apply to GICv3 LRs.
At the moment we have those definitions in the KVM VGICv3
implementation, so let's move them into the GICv3 header file to
have them automatically defined.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
---
 include/linux/irqchip/arm-gic-v3.h | 5 +++++
 virt/kvm/arm/vgic-v3.c             | 8 +-------
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index d5d798b..ec938d1 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -276,6 +276,11 @@
 #define ICH_LR_PHYS_ID_SHIFT		32
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
 
+/* These are for GICv2 emulation only */
+#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
+#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
+#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
+
 #define ICH_MISR_EOI			(1 << 0)
 #define ICH_MISR_U			(1 << 1)
 
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index c02a1b1..75b02fa 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -29,12 +29,6 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmu.h>
 
-/* These are for GICv2 emulation only */
-#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
-#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
-#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
-#define ICH_LR_VIRTUALID_MASK		(BIT_ULL(32) - 1)
-
 static u32 ich_vtr_el2;
 
 static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
@@ -43,7 +37,7 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
 	u64 val = vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr];
 
 	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
-		lr_desc.irq = val & ICH_LR_VIRTUALID_MASK;
+		lr_desc.irq = val & ICH_LR_VIRTUAL_ID_MASK;
 	else
 		lr_desc.irq = val & GICH_LR_VIRTUALID;
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:47 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:47 +0100
Subject: [PATCH v4 02/56] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_inject_mapped_irq()
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-60-git-send-email-andre.przywara@arm.com>

When we want to inject a hardware mapped IRQ into a guest, we actually
only need the virtual IRQ number from the irq_phys_map.
So let's pass this number directly from the arch timer to the VGIC
to avoid using the map as a parameter.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 include/kvm/arm_vgic.h    | 2 +-
 virt/kvm/arm/arch_timer.c | 2 +-
 virt/kvm/arm/vgic.c       | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index be6037a..e22f015 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -342,7 +342,7 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 			bool level);
 int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
-			       struct irq_phys_map *map, bool level);
+			       unsigned int virt_irq, bool level);
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 409db33..a9c6c1c 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -177,7 +177,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
 				   timer->irq.level);
 	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->map,
+					 timer->map->virt_irq,
 					 timer->irq.level);
 	WARN_ON(ret);
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index f6c6172..81c557c 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1666,7 +1666,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
  * kvm_vgic_inject_mapped_irq - Inject a physically mapped IRQ to the vgic
  * @kvm:     The VM structure pointer
  * @cpuid:   The CPU for PPIs
- * @map:     Pointer to a irq_phys_map structure describing the mapping
+ * @virt_irq: The virtual IRQ to be injected
  * @level:   Edge-triggered:  true:  to trigger the interrupt
  *			      false: to ignore the call
  *	     Level-sensitive  true:  raise the input signal
@@ -1677,7 +1677,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
  * being HIGH and 0 being LOW and all devices being active-HIGH.
  */
 int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
-			       struct irq_phys_map *map, bool level)
+			       unsigned int virt_irq, bool level)
 {
 	int ret;
 
@@ -1685,7 +1685,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 	if (ret)
 		return ret;
 
-	return vgic_update_irq_pending(kvm, cpuid, map->virt_irq, level);
+	return vgic_update_irq_pending(kvm, cpuid, virt_irq, level);
 }
 
 static irqreturn_t vgic_maintenance_handler(int irq, void *data)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:59 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:59 +0100
Subject: [PATCH v4 14/56] KVM: arm/arm64: vgic-new: Add data structure
 definitions
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-72-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Add a new header file for the new and improved GIC implementation.
The big change is that we now have a struct vgic_irq per IRQ instead
of spreading all the information over various bitmaps.

We include this new header conditionally from within the old header
file for the time being to avoid touching all the users.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changes RFC .. v1:
- adapt to 4.6-rc (adding live_lrs member)
- elaborate on ap_list usage

Changes v1 .. v2:
- change data type of dist->enabled to bool

Changelog v3 .. v4:
- fix comment typos

 include/kvm/arm_vgic.h  |   5 ++
 include/kvm/vgic/vgic.h | 201 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 206 insertions(+)
 create mode 100644 include/kvm/vgic/vgic.h

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index ade7005..da0a5248 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -19,6 +19,10 @@
 #ifndef __ASM_ARM_KVM_VGIC_H
 #define __ASM_ARM_KVM_VGIC_H
 
+#ifdef CONFIG_KVM_NEW_VGIC
+#include <kvm/vgic/vgic.h>
+#else
+
 #include <linux/kernel.h>
 #include <linux/kvm.h>
 #include <linux/irqreturn.h>
@@ -367,4 +371,5 @@ static inline int vgic_v3_probe(const struct gic_kvm_info *gic_kvm_info,
 }
 #endif
 
+#endif	/* old VGIC include */
 #endif
diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
new file mode 100644
index 0000000..6ca0781
--- /dev/null
+++ b/include/kvm/vgic/vgic.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_ARM_KVM_VGIC_VGIC_H
+#define __ASM_ARM_KVM_VGIC_VGIC_H
+
+#include <linux/kernel.h>
+#include <linux/kvm.h>
+#include <linux/irqreturn.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <kvm/iodev.h>
+
+#define VGIC_V3_MAX_CPUS	255
+#define VGIC_V2_MAX_CPUS	8
+#define VGIC_NR_IRQS_LEGACY     256
+#define VGIC_NR_SGIS		16
+#define VGIC_NR_PPIS		16
+#define VGIC_NR_PRIVATE_IRQS	(VGIC_NR_SGIS + VGIC_NR_PPIS)
+#define VGIC_MAX_PRIVATE	(VGIC_NR_PRIVATE_IRQS - 1)
+#define VGIC_MAX_SPI		1019
+#define VGIC_MAX_RESERVED	1023
+#define VGIC_MIN_LPI		8192
+
+enum vgic_type {
+	VGIC_V2,		/* Good ol' GICv2 */
+	VGIC_V3,		/* New fancy GICv3 */
+};
+
+/* same for all guests, as depending only on the _host's_ GIC model */
+struct vgic_global {
+	/* type of the host GIC */
+	enum vgic_type		type;
+
+	/* Physical address of vgic virtual cpu interface */
+	phys_addr_t		vcpu_base;
+
+	/* virtual control interface mapping */
+	void __iomem		*vctrl_base;
+
+	/* Number of implemented list registers */
+	int			nr_lr;
+
+	/* Maintenance IRQ number */
+	unsigned int		maint_irq;
+
+	/* maximum number of VCPUs allowed (GICv2 limits us to 8) */
+	int			max_gic_vcpus;
+
+	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
+	bool			can_emulate_gicv2;
+};
+
+extern struct vgic_global kvm_vgic_global_state;
+
+#define VGIC_V2_MAX_LRS		(1 << 6)
+#define VGIC_V3_MAX_LRS		16
+#define VGIC_V3_LR_INDEX(lr)	(VGIC_V3_MAX_LRS - 1 - lr)
+
+enum vgic_irq_config {
+	VGIC_CONFIG_EDGE = 0,
+	VGIC_CONFIG_LEVEL
+};
+
+struct vgic_irq {
+	spinlock_t irq_lock;		/* Protects the content of the struct */
+	struct list_head ap_list;
+
+	struct kvm_vcpu *vcpu;		/* SGIs and PPIs: The VCPU
+					 * SPIs and LPIs: The VCPU whose ap_list
+					 * this is queued on.
+					 */
+
+	struct kvm_vcpu *target_vcpu;	/* The VCPU that this interrupt should
+					 * be sent to, as a result of the
+					 * targets reg (v2) or the
+					 * affinity reg (v3).
+					 */
+
+	u32 intid;			/* Guest visible INTID */
+	bool pending;
+	bool line_level;		/* Level only */
+	bool soft_pending;		/* Level only */
+	bool active;			/* not used for LPIs */
+	bool enabled;
+	bool hw;			/* Tied to HW IRQ */
+	u32 hwintid;			/* HW INTID number */
+	union {
+		u8 targets;			/* GICv2 target VCPUs mask */
+		u32 mpidr;			/* GICv3 target VCPU */
+	};
+	u8 source;			/* GICv2 SGIs only */
+	u8 priority;
+	enum vgic_irq_config config;	/* Level or edge */
+};
+
+struct vgic_dist {
+	bool			in_kernel;
+	bool			ready;
+
+	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
+	u32			vgic_model;
+
+	int			nr_spis;
+
+	/* TODO: Consider moving to global state */
+	/* Virtual control interface mapping */
+	void __iomem		*vctrl_base;
+
+	/* base addresses in guest physical address space: */
+	gpa_t			vgic_dist_base;		/* distributor */
+	union {
+		/* either a GICv2 CPU interface */
+		gpa_t			vgic_cpu_base;
+		/* or a number of GICv3 redistributor regions */
+		gpa_t			vgic_redist_base;
+	};
+
+	/* distributor enabled */
+	bool			enabled;
+
+	struct vgic_irq		*spis;
+};
+
+struct vgic_v2_cpu_if {
+	u32		vgic_hcr;
+	u32		vgic_vmcr;
+	u32		vgic_misr;	/* Saved only */
+	u64		vgic_eisr;	/* Saved only */
+	u64		vgic_elrsr;	/* Saved only */
+	u32		vgic_apr;
+	u32		vgic_lr[VGIC_V2_MAX_LRS];
+};
+
+struct vgic_v3_cpu_if {
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	u32		vgic_hcr;
+	u32		vgic_vmcr;
+	u32		vgic_sre;	/* Restored only, change ignored */
+	u32		vgic_misr;	/* Saved only */
+	u32		vgic_eisr;	/* Saved only */
+	u32		vgic_elrsr;	/* Saved only */
+	u32		vgic_ap0r[4];
+	u32		vgic_ap1r[4];
+	u64		vgic_lr[VGIC_V3_MAX_LRS];
+#endif
+};
+
+struct vgic_cpu {
+	/* CPU vif control registers for world switch */
+	union {
+		struct vgic_v2_cpu_if	vgic_v2;
+		struct vgic_v3_cpu_if	vgic_v3;
+	};
+
+	unsigned int used_lrs;
+	struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
+
+	spinlock_t ap_list_lock;	/* Protects the ap_list */
+
+	/*
+	 * List of IRQs that this VCPU should consider because they are either
+	 * Active or Pending (hence the name; AP list), or because they recently
+	 * were one of the two and need to be migrated off this list to another
+	 * VCPU.
+	 */
+	struct list_head ap_list_head;
+
+	u64 live_lrs;
+};
+
+#define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
+#define vgic_initialized(k)	(false)
+#define vgic_ready(k)		((k)->arch.vgic.ready)
+#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
+			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
+
+/**
+ * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
+ *
+ * The host's GIC naturally limits the maximum amount of VCPUs a guest
+ * can use.
+ */
+static inline int kvm_vgic_get_max_vcpus(void)
+{
+	return kvm_vgic_global_state.max_gic_vcpus;
+}
+
+#endif /* __ASM_ARM_KVM_VGIC_VGIC_H */
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:01 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:01 +0100
Subject: [PATCH v4 16/56] KVM: arm/arm64: vgic-new: Implement virtual IRQ
 injection
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-74-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Provide a vgic_queue_irq_unlock() function which decides whether a
given IRQ needs to be queued to a VCPU's ap_list.
This should be called whenever an IRQ becomes pending or enabled,
either as a result of userspace injection, from in-kernel emulated
devices like the architected timer or from MMIO accesses to the
distributor emulation.
Also provides the necessary functions to allow userland to inject an
IRQ to a guest.
Since this is the first code that starts using our locking mechanism, we
add some (hopefully) clear documentation of our locking strategy and
requirements along with this patch.

[Andre: refactor out vgic_queue_irq_unlock()]

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- add spinlock checks protected by CONFIG_DEBUG_SPINLOCK
- add more comments to vgic_target_oracle
- remove BUG_ON() if IRQ is neither edge or level
- rename vgic_queue_irq() to vgic_queue_irq_unlock()
- simplify initial check in vgic_queue_irq_unlock()
- extend retry loop to ask the oracle again
- minor comment fixes

Changelog v1 .. v2:
- move most IRQ injection code into vgic_update_irq_pending()

Changelog v3 .. v4:
- simplify vgic_queue_irq_unlock() to allow reusage later

 include/kvm/vgic/vgic.h  |   3 +
 virt/kvm/arm/vgic/vgic.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h |   1 +
 3 files changed, 215 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 6ca0781..7b6ca90 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -181,6 +181,9 @@ struct vgic_cpu {
 	u64 live_lrs;
 };
 
+int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			bool level);
+
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(false)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index fb45537..62fede6 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -19,8 +19,31 @@
 
 #include "vgic.h"
 
+#define CREATE_TRACE_POINTS
+#include "../trace.h"
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+#define DEBUG_SPINLOCK_BUG_ON(p) BUG_ON(p)
+#else
+#define DEBUG_SPINLOCK_BUG_ON(p)
+#endif
+
 struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
 
+/*
+ * Locking order is always:
+ *   vgic_cpu->ap_list_lock
+ *     vgic_irq->irq_lock
+ *
+ * (that is, always take the ap_list_lock before the struct vgic_irq lock).
+ *
+ * When taking more than one ap_list_lock at the same time, always take the
+ * lowest numbered VCPU's ap_list_lock first, so:
+ *   vcpuX->vcpu_id < vcpuY->vcpu_id:
+ *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
+ *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
+ */
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid)
 {
@@ -39,3 +62,191 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 	WARN(1, "Looking up struct vgic_irq for reserved INTID");
 	return NULL;
 }
+
+/**
+ * kvm_vgic_target_oracle - compute the target vcpu for an irq
+ *
+ * @irq:	The irq to route. Must be already locked.
+ *
+ * Based on the current state of the interrupt (enabled, pending,
+ * active, vcpu and target_vcpu), compute the next vcpu this should be
+ * given to. Return NULL if this shouldn't be injected at all.
+ *
+ * Requires the IRQ lock to be held.
+ */
+static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
+{
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+	/* If the interrupt is active, it must stay on the current vcpu */
+	if (irq->active)
+		return irq->vcpu;
+
+	/*
+	 * If the IRQ is not active but enabled and pending, we should direct
+	 * it to its configured target VCPU.
+	 * If the distributor is disabled, pending interrupts shouldn't be
+	 * forwarded.
+	 */
+	if (irq->enabled && irq->pending) {
+		if (unlikely(irq->target_vcpu &&
+			     !irq->target_vcpu->kvm->arch.vgic.enabled))
+			return NULL;
+
+		return irq->target_vcpu;
+	}
+
+	/* If neither active nor pending and enabled, then this IRQ should not
+	 * be queued to any VCPU.
+	 */
+	return NULL;
+}
+
+/*
+ * Only valid injection if changing level for level-triggered IRQs or for a
+ * rising edge.
+ */
+static bool vgic_validate_injection(struct vgic_irq *irq, bool level)
+{
+	switch (irq->config) {
+	case VGIC_CONFIG_LEVEL:
+		return irq->line_level != level;
+	case VGIC_CONFIG_EDGE:
+		return level;
+	}
+
+	return false;
+}
+
+/*
+ * Check whether an IRQ needs to (and can) be queued to a VCPU's ap list.
+ * Do the queuing if necessary, taking the right locks in the right order.
+ * Returns true when the IRQ was queued, false otherwise.
+ *
+ * Needs to be entered with the IRQ lock already held, but will return
+ * with all locks dropped.
+ */
+bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq)
+{
+	struct kvm_vcpu *vcpu;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+retry:
+	vcpu = vgic_target_oracle(irq);
+	if (irq->vcpu || !vcpu) {
+		/*
+		 * If this IRQ is already on a VCPU's ap_list, then it
+		 * cannot be moved or modified and there is no more work for
+		 * us to do.
+		 *
+		 * Otherwise, if the irq is not pending and enabled, it does
+		 * not need to be inserted into an ap_list and there is also
+		 * no more work for us to do.
+		 */
+		spin_unlock(&irq->irq_lock);
+		return false;
+	}
+
+	/*
+	 * We must unlock the irq lock to take the ap_list_lock where
+	 * we are going to insert this new pending interrupt.
+	 */
+	spin_unlock(&irq->irq_lock);
+
+	/* someone can do stuff here, which we re-check below */
+
+	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+	spin_lock(&irq->irq_lock);
+
+	/*
+	 * Did something change behind our backs?
+	 *
+	 * There are two cases:
+	 * 1) The irq lost its pending state or was disabled behind our
+	 *    backs and/or it was queued to another VCPU's ap_list.
+	 *    Then drop the locks and return.
+	 * 2) Someone changed the affinity on this irq behind our
+	 *    backs and we are now holding the wrong ap_list_lock.
+	 *    Then drop the locks and try the new VCPU.
+	 */
+
+	if (unlikely(irq->vcpu || vcpu != vgic_target_oracle(irq))) {
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+		spin_lock(&irq->irq_lock);
+		goto retry;
+	}
+
+	list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
+	irq->vcpu = vcpu;
+
+	spin_unlock(&irq->irq_lock);
+	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+	kvm_vcpu_kick(vcpu);
+
+	return true;
+}
+
+static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
+				   unsigned int intid, bool level,
+				   bool mapped_irq)
+{
+	struct kvm_vcpu *vcpu;
+	struct vgic_irq *irq;
+	int ret;
+
+	trace_vgic_update_irq_pending(cpuid, intid, level);
+
+	vcpu = kvm_get_vcpu(kvm, cpuid);
+	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
+		return -EINVAL;
+
+	irq = vgic_get_irq(kvm, vcpu, intid);
+	if (!irq)
+		return -EINVAL;
+
+	if (irq->hw != mapped_irq)
+		return -EINVAL;
+
+	spin_lock(&irq->irq_lock);
+
+	if (!vgic_validate_injection(irq, level)) {
+		/* Nothing to see here, move along... */
+		spin_unlock(&irq->irq_lock);
+		return 0;
+	}
+
+	if (irq->config == VGIC_CONFIG_LEVEL) {
+		irq->line_level = level;
+		irq->pending = level || irq->soft_pending;
+	} else {
+		irq->pending = true;
+	}
+
+	vgic_queue_irq_unlock(kvm, irq);
+
+	return 0;
+}
+
+/**
+ * kvm_vgic_inject_irq - Inject an IRQ from a device to the vgic
+ * @kvm:     The VM structure pointer
+ * @cpuid:   The CPU for PPIs
+ * @intid:   The INTID to inject a new state to.
+ * @level:   Edge-triggered:  true:  to trigger the interrupt
+ *			      false: to ignore the call
+ *	     Level-sensitive  true:  raise the input signal
+ *			      false: lower the input signal
+ *
+ * The VGIC is not concerned with devices being active-LOW or active-HIGH for
+ * level-sensitive interrupts.  You can think of the level parameter as 1
+ * being HIGH and 0 being LOW and all devices being active-HIGH.
+ */
+int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			bool level)
+{
+	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 61b8d22..c625767 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -18,5 +18,6 @@
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
+bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:51 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:51 +0100
Subject: [PATCH v4 06/56] KVM: arm/arm64: arch_timer: Remove irq_phys_map
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-64-git-send-email-andre.przywara@arm.com>

Now that the interface between the arch timer and the VGIC does not
require passing the irq_phys_map entry pointer anymore, let's remove
it from the virtual arch timer and use the virtual IRQ number instead
directly.
The remaining pointer returned by kvm_vgic_map_phys_irq() will be
removed in the following patch.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- remove extra virt_irq member from struct, instead use irq.irq directly

Changelog v2 .. v3:
- remove bogus validity check from kvm_vgic_unmap_phys_irq()

 include/kvm/arm_arch_timer.h |  3 ---
 virt/kvm/arm/arch_timer.c    | 10 ++++------
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index b651aed..a47b7de 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -53,9 +53,6 @@ struct arch_timer_cpu {
 	/* Timer IRQ */
 	struct kvm_irq_level		irq;
 
-	/* VGIC mapping */
-	struct irq_phys_map		*map;
-
 	/* Active IRQ state caching */
 	bool				active_cleared_last;
 };
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index e45895a..458d4d8 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -175,10 +175,10 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 
 	timer->active_cleared_last = false;
 	timer->irq.level = new_level;
-	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
+	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
 				   timer->irq.level);
 	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->map->virt_irq,
+					 timer->irq.irq,
 					 timer->irq.level);
 	WARN_ON(ret);
 }
@@ -276,7 +276,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* exit.
 	*/
 	phys_active = timer->irq.level ||
-			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
+			kvm_vgic_map_is_active(vcpu, timer->irq.irq);
 
 	/*
 	 * We want to avoid hitting the (re)distributor as much as
@@ -378,7 +378,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	if (WARN_ON(IS_ERR(map)))
 		return PTR_ERR(map);
 
-	timer->map = map;
 	return 0;
 }
 
@@ -504,8 +503,7 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 
 	timer_disarm(timer);
-	if (timer->map)
-		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
+	kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq);
 }
 
 void kvm_timer_enable(struct kvm *kvm)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:03 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:03 +0100
Subject: [PATCH v4 18/56] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-76-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Implement the framework for syncing IRQs between our emulation and
the list registers, which represent the guest's view of IRQs.
This is done in kvm_vgic_flush_hwstate and kvm_vgic_sync_hwstate,
which gets called on guest entry and exit.
The code talking to the actual GICv2/v3 hardware is added in the
following patches.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- split out vgic_clear_lr() from vgic_populate_lr()
- rename vgic_populate_lrs() to vgic_flush_lr_state()
- clean all LRs when the distributor is disabled
- use list_del() instead of list_del_init()
- add comments to explain the direction of sync/flush_hwstate
- remove unneeded BUG_ON(in_interrupt()

Changelog v2 .. v3:
- remove bogus v2 specific rebase leftovers

Changelog v3 .. v4:
- amend locks requirements

 include/kvm/vgic/vgic.h  |   4 +
 virt/kvm/arm/vgic/vgic.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h |   2 +
 3 files changed, 197 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 7b6ca90..9506267 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -190,6 +190,10 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
 			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
 
+bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
+void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
+void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
+
 /**
  * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
  *
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 1bc8f92..613fbd1 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -307,3 +307,194 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 {
 	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
 }
+
+/**
+ * vgic_prune_ap_list - Remove non-relevant interrupts from the list
+ *
+ * @vcpu: The VCPU pointer
+ *
+ * Go over the list of "interesting" interrupts, and prune those that we
+ * won't have to consider in the near future.
+ */
+static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq, *tmp;
+
+retry:
+	spin_lock(&vgic_cpu->ap_list_lock);
+
+	list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
+		struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
+
+		spin_lock(&irq->irq_lock);
+
+		BUG_ON(vcpu != irq->vcpu);
+
+		target_vcpu = vgic_target_oracle(irq);
+
+		if (!target_vcpu) {
+			/*
+			 * We don't need to process this interrupt any
+			 * further, move it off the list.
+			 */
+			list_del(&irq->ap_list);
+			irq->vcpu = NULL;
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		if (target_vcpu == vcpu) {
+			/* We're on the right CPU */
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		/* This interrupt looks like it has to be migrated. */
+
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vgic_cpu->ap_list_lock);
+
+		/*
+		 * Ensure locking order by always locking the smallest
+		 * ID first.
+		 */
+		if (vcpu->vcpu_id < target_vcpu->vcpu_id) {
+			vcpuA = vcpu;
+			vcpuB = target_vcpu;
+		} else {
+			vcpuA = target_vcpu;
+			vcpuB = vcpu;
+		}
+
+		spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+		spin_lock(&vcpuB->arch.vgic_cpu.ap_list_lock);
+		spin_lock(&irq->irq_lock);
+
+		/*
+		 * If the affinity has been preserved, move the
+		 * interrupt around. Otherwise, it means things have
+		 * changed while the interrupt was unlocked, and we
+		 * need to replay this.
+		 *
+		 * In all cases, we cannot trust the list not to have
+		 * changed, so we restart from the beginning.
+		 */
+		if (target_vcpu == vgic_target_oracle(irq)) {
+			struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;
+
+			list_del(&irq->ap_list);
+			irq->vcpu = target_vcpu;
+			list_add_tail(&irq->ap_list, &new_cpu->ap_list_head);
+		}
+
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
+		spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+		goto retry;
+	}
+
+	spin_unlock(&vgic_cpu->ap_list_lock);
+}
+
+static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+}
+
+/* Requires the irq_lock to be held. */
+static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
+				    struct vgic_irq *irq, int lr)
+{
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+}
+
+static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+}
+
+static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
+{
+}
+
+/* Requires the ap_list_lock to be held. */
+static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	int count = 0;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+		/* GICv2 SGIs can count for more than one... */
+		if (vgic_irq_is_sgi(irq->intid) && irq->source)
+			count += hweight8(irq->source);
+		else
+			count++;
+		spin_unlock(&irq->irq_lock);
+	}
+	return count;
+}
+
+/* Requires the VCPU's ap_list_lock to be held. */
+static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	int count = 0;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	if (compute_ap_list_depth(vcpu) > kvm_vgic_global_state.nr_lr) {
+		vgic_set_underflow(vcpu);
+		vgic_sort_ap_list(vcpu);
+	}
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+
+		if (unlikely(vgic_target_oracle(irq) != vcpu))
+			goto next;
+
+		/*
+		 * If we get an SGI with multiple sources, try to get
+		 * them in all at once.
+		 */
+		do {
+			vgic_populate_lr(vcpu, irq, count++);
+		} while (irq->source && count < kvm_vgic_global_state.nr_lr);
+
+next:
+		spin_unlock(&irq->irq_lock);
+
+		if (count == kvm_vgic_global_state.nr_lr)
+			break;
+	}
+
+	vcpu->arch.vgic_cpu.used_lrs = count;
+
+	/* Nuke remaining LRs */
+	for ( ; count < kvm_vgic_global_state.nr_lr; count++)
+		vgic_clear_lr(vcpu, count);
+}
+
+/* Sync back the hardware VGIC state into our emulation after a guest's run. */
+void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
+{
+	vgic_process_maintenance_interrupt(vcpu);
+	vgic_fold_lr_state(vcpu);
+	vgic_prune_ap_list(vcpu);
+}
+
+/* Flush our emulation state into the GIC hardware before entering the guest. */
+void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
+{
+	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+	vgic_flush_lr_state(vcpu);
+	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index c625767..29b96b9 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,6 +16,8 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:04 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:04 +0100
Subject: [PATCH v4 19/56] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-77-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Processing maintenance interrupts and accessing the list registers
are dependent on the host's GIC version.
Introduce vgic-v2.c to contain GICv2 specific functions.
Implement the GICv2 specific code for syncing the emulation state
into the VGIC registers.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog RFC..v1:
- remove explicit LR_STATE clearing on maintenance interrupt handling
- improve documentation for vgic_v2_populate_lr()
- remove WARN_ON on non-edge IRQs in maintenance interrupts
- simplify multi-CPU source SGI handling

Changelog v1 .. v2:
- inject the IRQ priority into the list register

Changelog v2 .. v3:
- cleanup diff containing rebase artifacts

Changelog v3 .. v4:
- remove ELRSR bit set during process_maintenance()

 include/linux/irqchip/arm-gic.h |   1 +
 virt/kvm/arm/vgic/vgic-v2.c     | 176 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c        |   6 ++
 virt/kvm/arm/vgic/vgic.h        |   6 ++
 4 files changed, 189 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-v2.c

diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 9c94026..be0d26f 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -76,6 +76,7 @@
 #define GICH_LR_VIRTUALID		(0x3ff << 0)
 #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
 #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
+#define GICH_LR_PRIORITY_SHIFT		23
 #define GICH_LR_STATE			(3 << 28)
 #define GICH_LR_PENDING_BIT		(1 << 28)
 #define GICH_LR_ACTIVE_BIT		(1 << 29)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
new file mode 100644
index 0000000..fb5e65c
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/irqchip/arm-gic.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+/*
+ * Call this function to convert a u64 value to an unsigned long * bitmask
+ * in a way that works on both 32-bit and 64-bit LE and BE platforms.
+ *
+ * Warning: Calling this function may modify *val.
+ */
+static unsigned long *u64_to_bitmask(u64 *val)
+{
+#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
+	*val = (*val >> 32) | (*val << 32);
+#endif
+	return (unsigned long *)val;
+}
+
+void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+
+	if (cpuif->vgic_misr & GICH_MISR_EOI) {
+		u64 eisr = cpuif->vgic_eisr;
+		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
+		int lr;
+
+		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
+			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
+
+			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
+
+			kvm_notify_acked_irq(vcpu->kvm, 0,
+					     intid - VGIC_NR_PRIVATE_IRQS);
+		}
+	}
+
+	/* check and disable underflow maintenance IRQ */
+	cpuif->vgic_hcr &= ~GICH_HCR_UIE;
+
+	/*
+	 * In the next iterations of the vcpu loop, if we sync the
+	 * vgic state after flushing it, but before entering the guest
+	 * (this happens for pending signals and vmid rollovers), then
+	 * make sure we don't pick up any old maintenance interrupts
+	 * here.
+	 */
+	cpuif->vgic_eisr = 0;
+}
+
+void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+
+	cpuif->vgic_hcr |= GICH_HCR_UIE;
+}
+
+/*
+ * transfer the content of the LRs back into the corresponding ap_list:
+ * - active bit is transferred as is
+ * - pending bit is
+ *   - transferred as is in case of edge sensitive IRQs
+ *   - set to the line-level (resample time) for level sensitive IRQs
+ */
+void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+	int lr;
+
+	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
+		u32 val = cpuif->vgic_lr[lr];
+		u32 intid = val & GICH_LR_VIRTUALID;
+		struct vgic_irq *irq;
+
+		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+
+		/* Always preserve the active bit */
+		irq->active = !!(val & GICH_LR_ACTIVE_BIT);
+
+		/* Edge is the only case where we preserve the pending bit */
+		if (irq->config == VGIC_CONFIG_EDGE &&
+		    (val & GICH_LR_PENDING_BIT)) {
+			irq->pending = true;
+
+			if (vgic_irq_is_sgi(intid)) {
+				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
+
+				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+				irq->source |= (1 << cpuid);
+			}
+		}
+
+		/* Clear soft pending state when level IRQs have been acked */
+		if (irq->config == VGIC_CONFIG_LEVEL &&
+		    !(val & GICH_LR_PENDING_BIT)) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+/*
+ * Populates the particular LR with the state of a given IRQ:
+ * - for an edge sensitive IRQ the pending state is cleared in struct vgic_irq
+ * - for a level sensitive IRQ the pending state value is unchanged;
+ *   it is dictated directly by the input level
+ *
+ * If @irq describes an SGI with multiple sources, we choose the
+ * lowest-numbered source VCPU and clear that bit in the source bitmap.
+ *
+ * The irq_lock must be held by the caller.
+ */
+void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
+{
+	u32 val = irq->intid;
+
+	if (irq->pending) {
+		val |= GICH_LR_PENDING_BIT;
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			irq->pending = false;
+
+		if (vgic_irq_is_sgi(irq->intid)) {
+			u32 src = ffs(irq->source);
+
+			BUG_ON(!src);
+			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
+			irq->source &= ~(1 << (src - 1));
+			if (irq->source)
+				irq->pending = true;
+		}
+	}
+
+	if (irq->active)
+		val |= GICH_LR_ACTIVE_BIT;
+
+	if (irq->hw) {
+		val |= GICH_LR_HW;
+		val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
+	} else {
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			val |= GICH_LR_EOI;
+	}
+
+	/* The GICv2 LR only holds five bits of priority. */
+	val |= (irq->priority >> 3) << GICH_LR_PRIORITY_SHIFT;
+
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = val;
+}
+
+void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 613fbd1..7d85398 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -399,10 +399,12 @@ retry:
 
 static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_process_maintenance(vcpu);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_fold_lr_state(vcpu);
 }
 
 /* Requires the irq_lock to be held. */
@@ -410,14 +412,18 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
 				    struct vgic_irq *irq, int lr)
 {
 	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+	vgic_v2_populate_lr(vcpu, irq, lr);
 }
 
 static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
+	vgic_v2_clear_lr(vcpu, lr);
 }
 
 static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_set_underflow(vcpu);
 }
 
 /* Requires the ap_list_lock to be held. */
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 29b96b9..0db490e 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -22,4 +22,10 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
 
+void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
+void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
+void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
+void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
+void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:55 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:55 +0100
Subject: [PATCH v4 10/56] KVM: arm/arm64: Export mmio_read/write_bus
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-68-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Rename mmio_{read,write}_bus to kvm_mmio_{read,write}_bus and export
them out of mmio.c.
This will be needed later for the new VGIC implementation.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm/include/asm/kvm_mmio.h   |  3 +++
 arch/arm/kvm/mmio.c               | 10 +++++-----
 arch/arm64/include/asm/kvm_mmio.h |  3 +++
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmio.h b/arch/arm/include/asm/kvm_mmio.h
index d8e90c8..f3a7de7 100644
--- a/arch/arm/include/asm/kvm_mmio.h
+++ b/arch/arm/include/asm/kvm_mmio.h
@@ -28,6 +28,9 @@ struct kvm_decode {
 	bool sign_extend;
 };
 
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
+
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		 phys_addr_t fault_ipa);
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 0158e9e..10f80a6 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -23,7 +23,7 @@
 
 #include "trace.h"
 
-static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data)
 {
 	void *datap = NULL;
 	union {
@@ -55,7 +55,7 @@ static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
 	memcpy(buf, datap, len);
 }
 
-static unsigned long mmio_read_buf(char *buf, unsigned int len)
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len)
 {
 	unsigned long data = 0;
 	union {
@@ -66,7 +66,7 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len)
 
 	switch (len) {
 	case 1:
-		data = buf[0];
+		data = *(u8 *)buf;
 		break;
 	case 2:
 		memcpy(&tmp.hword, buf, len);
@@ -103,7 +103,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		if (len > sizeof(unsigned long))
 			return -EINVAL;
 
-		data = mmio_read_buf(run->mmio.data, len);
+		data = kvm_mmio_read_buf(run->mmio.data, len);
 
 		if (vcpu->arch.mmio_decode.sign_extend &&
 		    len < sizeof(unsigned long)) {
@@ -189,7 +189,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 					       len);
 
 		trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data);
-		mmio_write_buf(data_buf, len, data);
+		kvm_mmio_write_buf(data_buf, len, data);
 
 		ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
 				       data_buf);
diff --git a/arch/arm64/include/asm/kvm_mmio.h b/arch/arm64/include/asm/kvm_mmio.h
index fe612a9..75ea420 100644
--- a/arch/arm64/include/asm/kvm_mmio.h
+++ b/arch/arm64/include/asm/kvm_mmio.h
@@ -30,6 +30,9 @@ struct kvm_decode {
 	bool sign_extend;
 };
 
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
+
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		 phys_addr_t fault_ipa);
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:53 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:53 +0100
Subject: [PATCH v4 08/56] KVM: arm/arm64: Get rid of vgic_cpu->nr_lr
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-66-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

The number of list registers is a property of the underlying system, not
of emulated VGIC CPU interface.

As we are about to move this variable to global state in the new vgic
for clarity, move it from the legacy implementation as well to make the
merge of the new code easier.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 include/kvm/arm_vgic.h        |  3 ---
 virt/kvm/arm/hyp/vgic-v2-sr.c | 12 +++++++-----
 virt/kvm/arm/vgic-v2.c        |  4 +++-
 virt/kvm/arm/vgic.c           | 12 ++----------
 4 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 3e17fb4..67a6637 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -304,9 +304,6 @@ struct vgic_cpu {
 	unsigned long   *active_shared;
 	unsigned long   *pend_act_shared;
 
-	/* Number of list registers on this CPU */
-	int		nr_lr;
-
 	/* CPU vif control registers for world switch */
 	union {
 		struct vgic_v2_cpu_if	vgic_v2;
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index 674bdf8..caac41f 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -21,11 +21,13 @@
 
 #include <asm/kvm_hyp.h>
 
+extern struct vgic_params vgic_v2_params;
+
 static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 					    void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	u32 eisr0, eisr1;
 	int i;
 	bool expect_mi;
@@ -67,7 +69,7 @@ static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	u32 elrsr0, elrsr1;
 
 	elrsr0 = readl_relaxed(base + GICH_ELRSR0);
@@ -86,7 +88,7 @@ static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
 static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	int i;
 
 	for (i = 0; i < nr_lr; i++) {
@@ -141,13 +143,13 @@ void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
 	struct vgic_dist *vgic = &kvm->arch.vgic;
 	void __iomem *base = kern_hyp_va(vgic->vctrl_base);
-	int i, nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
+	int i;
 	u64 live_lrs = 0;
 
 	if (!base)
 		return;
 
-	nr_lr = vcpu->arch.vgic_cpu.nr_lr;
 
 	for (i = 0; i < nr_lr; i++)
 		if (cpu_if->vgic_lr[i] & GICH_LR_STATE)
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
index 7e826c9..334cd7a 100644
--- a/virt/kvm/arm/vgic-v2.c
+++ b/virt/kvm/arm/vgic-v2.c
@@ -171,7 +171,7 @@ static const struct vgic_ops vgic_v2_ops = {
 	.enable			= vgic_v2_enable,
 };
 
-static struct vgic_params vgic_v2_params;
+struct vgic_params __section(.hyp.text) vgic_v2_params;
 
 static void vgic_cpu_init_lrs(void *params)
 {
@@ -201,6 +201,8 @@ int vgic_v2_probe(const struct gic_kvm_info *gic_kvm_info,
 	const struct resource *vctrl_res = &gic_kvm_info->vctrl;
 	const struct resource *vcpu_res = &gic_kvm_info->vcpu;
 
+	memset(vgic, 0, sizeof(*vgic));
+
 	if (!gic_kvm_info->maint_irq) {
 		kvm_err("error getting vgic maintenance irq\n");
 		ret = -ENXIO;
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 91d42a8..f76bb64 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -690,12 +690,11 @@ bool vgic_handle_cfg_reg(u32 *reg, struct kvm_exit_mmio *mmio,
  */
 void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
 {
-	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
 	u64 elrsr = vgic_get_elrsr(vcpu);
 	unsigned long *elrsr_ptr = u64_to_bitmask(&elrsr);
 	int i;
 
-	for_each_clear_bit(i, elrsr_ptr, vgic_cpu->nr_lr) {
+	for_each_clear_bit(i, elrsr_ptr, vgic->nr_lr) {
 		struct vgic_lr lr = vgic_get_lr(vcpu, i);
 
 		/*
@@ -1106,7 +1105,7 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	int i;
 
-	for (i = 0; i < vcpu->arch.vgic_cpu.nr_lr; i++) {
+	for (i = 0; i < vgic->nr_lr; i++) {
 		struct vgic_lr vlr = vgic_get_lr(vcpu, i);
 
 		if (vlr.irq == virt_irq && vlr.state & LR_STATE_ACTIVE)
@@ -1866,13 +1865,6 @@ static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
 		return -ENOMEM;
 	}
 
-	/*
-	 * Store the number of LRs per vcpu, so we don't have to go
-	 * all the way to the distributor structure to find out. Only
-	 * assembly code should use this one.
-	 */
-	vgic_cpu->nr_lr = vgic->nr_lr;
-
 	return 0;
 }
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:06 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:06 +0100
Subject: [PATCH v4 21/56] KVM: arm/arm64: vgic-new: Implement
 kvm_vgic_vcpu_pending_irq
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-79-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

Tell KVM whether a particular VCPU has an IRQ that needs handling
in the guest. This is used to decide whether a VCPU is runnable.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog RFC..v1:
- return false if distributor is disabled
- add vgic_kick_vcpus() implementations

Changelog v2 .. v3:
- remove vgic_kick_vcpus() implementation from this patch

 include/kvm/vgic/vgic.h  |  2 ++
 virt/kvm/arm/vgic/vgic.c | 25 +++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 9506267..f663288 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -184,6 +184,8 @@ struct vgic_cpu {
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
 
+int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
+
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(false)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index eca3cd0..bea8d3b 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -519,3 +519,28 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 	vgic_flush_lr_state(vcpu);
 	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
 }
+
+int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	bool pending = false;
+
+	if (!vcpu->kvm->arch.vgic.enabled)
+		return false;
+
+	spin_lock(&vgic_cpu->ap_list_lock);
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+		pending = irq->pending && irq->enabled;
+		spin_unlock(&irq->irq_lock);
+
+		if (pending)
+			break;
+	}
+
+	spin_unlock(&vgic_cpu->ap_list_lock);
+
+	return pending;
+}
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:08 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:08 +0100
Subject: [PATCH v4 23/56] KVM: arm/arm64: vgic-new: Add GICv2 MMIO handling
 framework
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-81-git-send-email-andre.przywara@arm.com>

Create vgic-mmio-v2.c to describe GICv2 emulation specific handlers
using the initializer macros provided by the VGIC MMIO framework.
Provide a function to register the GICv2 distributor registers to
the kvm_io_bus framework.
The actual handler functions are still stubs in this patch.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v1 .. v2:
- new patch, split out from the generic MMIO framework patch
- use a separate file to hold GICv2 emulation specific handlers
- replace _nyi stub functions with raz/wi versions

Changelog v2 .. v3:
- replace kvm/vgic/vgic.h with kvm/arm_vgic.h
- add vgic_register_dist_iodev() prototype

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 76 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c    | 26 ++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  2 ++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 4 files changed, 106 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v2.c

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
new file mode 100644
index 0000000..a3e31a9
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -0,0 +1,76 @@
+/*
+ * VGICv2 MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irqchip/arm-gic.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+static const struct vgic_register_region vgic_v2_dist_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 12,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 2,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+};
+
+unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
+{
+	dev->regions = vgic_v2_dist_registers;
+	dev->nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
+
+	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
+
+	return SZ_4K;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 012b82b..1a97765 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -182,3 +182,29 @@ struct kvm_io_device_ops kvm_io_gic_ops = {
 	.read = dispatch_mmio_read,
 	.write = dispatch_mmio_write,
 };
+
+int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
+			     enum vgic_type type)
+{
+	struct vgic_io_device *io_device = &kvm->arch.vgic.dist_iodev;
+	int ret = 0;
+	unsigned int len;
+
+	switch (type) {
+	case VGIC_V2:
+		len = vgic_v2_init_dist_iodev(io_device);
+		break;
+	default:
+		BUG_ON(1);
+	}
+
+	io_device->base_addr = dist_base_address;
+	io_device->redist_vcpu = NULL;
+
+	mutex_lock(&kvm->slots_lock);
+	ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address,
+				      len, &io_device->dev);
+	mutex_unlock(&kvm->slots_lock);
+
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 855b1db..10404ac 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -84,4 +84,6 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
 void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 			unsigned int len, unsigned long val);
 
+unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
+
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 81b1a20..fd9acaa 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -27,6 +27,8 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
+			     enum vgic_type);
 
 #ifdef CONFIG_KVM_ARM_VGIC_V3
 void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:57 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:57 +0100
Subject: [PATCH v4 12/56] KVM: arm/arm64: Provide functionality to pause and
 resume a guest
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-70-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

For some rare corner cases in our VGIC emulation later we have to stop
the guest to make sure the VGIC state is consistent.
Provide the necessary framework to pause and resume a guest.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/include/asm/kvm_host.h   |  4 ++++
 arch/arm/kvm/arm.c                | 25 +++++++++++++------------
 arch/arm64/include/asm/kvm_host.h |  4 ++++
 3 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 3850701..832be03 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -41,6 +41,8 @@
 
 #define KVM_MAX_VCPUS VGIC_V2_MAX_CPUS
 
+#define KVM_REQ_VCPU_EXIT	8
+
 u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode);
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
@@ -225,6 +227,8 @@ static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
 
 struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
+void kvm_arm_halt_guest(struct kvm *kvm);
+void kvm_arm_resume_guest(struct kvm *kvm);
 
 int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
 unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index be4b639..3b4fd03 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -492,30 +492,31 @@ bool kvm_arch_intc_initialized(struct kvm *kvm)
 	return vgic_initialized(kvm);
 }
 
-static void kvm_arm_halt_guest(struct kvm *kvm) __maybe_unused;
-static void kvm_arm_resume_guest(struct kvm *kvm) __maybe_unused;
-
-static void kvm_arm_halt_guest(struct kvm *kvm)
+void kvm_arm_halt_guest(struct kvm *kvm)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
 
 	kvm_for_each_vcpu(i, vcpu, kvm)
 		vcpu->arch.pause = true;
-	force_vm_exit(cpu_all_mask);
+	kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT);
+}
+
+static void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
+{
+	struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
+
+	vcpu->arch.pause = false;
+	swake_up(wq);
 }
 
-static void kvm_arm_resume_guest(struct kvm *kvm)
+void kvm_arm_resume_guest(struct kvm *kvm)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
 
-	kvm_for_each_vcpu(i, vcpu, kvm) {
-		struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
-
-		vcpu->arch.pause = false;
-		swake_up(wq);
-	}
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_arm_resume_vcpu(vcpu);
 }
 
 static void vcpu_sleep(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 4cd4196..fa94f91 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -44,6 +44,8 @@
 
 #define KVM_VCPU_MAX_FEATURES 4
 
+#define KVM_REQ_VCPU_EXIT	8
+
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
 int kvm_arch_dev_ioctl_check_extension(long ext);
@@ -325,6 +327,8 @@ static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
 
 struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
+void kvm_arm_halt_guest(struct kvm *kvm);
+void kvm_arm_resume_guest(struct kvm *kvm);
 
 u64 __kvm_call_hyp(void *hypfn, ...);
 #define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:11 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:11 +0100
Subject: [PATCH v4 26/56] KVM: arm/arm64: vgic-new: Add PENDING registers
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-84-git-send-email-andre.przywara@arm.com>

The pending register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be easily
referenced from the v3 emulation as well later.
For level triggered interrupts the real line level is unaffected by
this write, so we keep this state separate and combine it with the
device's level to get the actual pending state.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog RFC..v1:
- remove IRQ lock from read handler
- remove TODO from clear pending handler

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro
- replace extract_bytes() with simple return

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
 virt/kvm/arm/vgic/vgic-mmio.c    | 60 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 12 ++++++++
 3 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index d5355b5..c13a708 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -78,10 +78,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 32ed8db..d8dc8f6 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -95,6 +95,66 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->pending)
+			value |= (1U << i);
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			irq->soft_pending = true;
+
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
+void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		if (irq->config == VGIC_CONFIG_LEVEL) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		} else {
+			irq->pending = false;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 66fd6fa..01db98a 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -95,6 +95,18 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val);
 
+unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
+void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:09 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:09 +0100
Subject: [PATCH v4 24/56] KVM: arm/arm64: vgic-new: Add CTLR,
 TYPER and IIDR handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-82-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Those three registers are v2 emulation specific, so their implementation
lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
as their implementation is pretty simple.
When the guest enables the distributor, we kick all VCPUs to get
potentially pending interrupts serviced.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- kick VCPUs is the distributor gets enabled
- improve comment

Changelog v1 .. v2:
- adapt to new MMIO framework
- use switch() statements to improve readability

Changelog v2 .. v3:
- add vgic_kick_vcpus() implementation

Changelog v3 .. v4;
- specify accessor width
- simplify CTLR write access
- replace extract_bytes() with simple return

 include/linux/irqchip/arm-gic.h  |  1 +
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 46 +++++++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
 virt/kvm/arm/vgic/vgic.h         |  4 ++++
 4 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index be0d26f..fd05185 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -33,6 +33,7 @@
 
 #define GIC_DIST_CTRL			0x000
 #define GIC_DIST_CTR			0x004
+#define GIC_DIST_IIDR			0x008
 #define GIC_DIST_IGROUP			0x080
 #define GIC_DIST_ENABLE_SET		0x100
 #define GIC_DIST_ENABLE_CLEAR		0x180
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index a3e31a9..d812c93 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -20,9 +20,53 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 value;
+
+	switch (addr & 0x0c) {
+	case GIC_DIST_CTRL:
+		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
+		break;
+	case GIC_DIST_CTR:
+		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+		value = (value >> 5) - 1;
+		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
+		break;
+	case GIC_DIST_IIDR:
+		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+		break;
+	default:
+		return 0;
+	}
+
+	return value;
+}
+
+static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+	bool was_enabled = dist->enabled;
+
+	switch (addr & 0x0c) {
+	case GIC_DIST_CTRL:
+		dist->enabled = val & GICD_ENABLE;
+		if (!was_enabled && dist->enabled)
+			vgic_kick_vcpus(vcpu->kvm);
+		break;
+	case GIC_DIST_CTR:
+	case GIC_DIST_IIDR:
+		/* Nothing to do */
+		return;
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 12,
+		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index bea8d3b..2a41028 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -544,3 +544,18 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 
 	return pending;
 }
+
+void vgic_kick_vcpus(struct kvm *kvm)
+{
+	struct kvm_vcpu *vcpu;
+	int c;
+
+	/*
+	 * We've injected an interrupt, time to find out who deserves
+	 * a good kick...
+	 */
+	kvm_for_each_vcpu(c, vcpu, kvm) {
+		if (kvm_vgic_vcpu_pending_irq(vcpu))
+			kvm_vcpu_kick(vcpu);
+	}
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index fd9acaa..cf62015 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,11 +16,15 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
+#define IMPLEMENTER_ARM		0x43b
+
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
+void vgic_kick_vcpus(struct kvm *kvm);
 
 void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
 void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:13 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:13 +0100
Subject: [PATCH v4 28/56] KVM: arm/arm64: vgic-new: Add PRIORITY registers
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-86-git-send-email-andre.przywara@arm.com>

The priority register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.
There is a corner case when we change the priority of a pending
interrupt which we don't handle at the moment.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 40 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  7 +++++++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 4 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 12e101b..d564a30 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -90,7 +90,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 74d140e..5c8af05 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -237,6 +237,46 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
+				      gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->priority << (i * 8);
+	}
+
+	return val;
+}
+
+/*
+ * We currently don't handle changing the priority of an interrupt that
+ * is already pending on a VCPU. If there is a need for this, we would
+ * need to make this VCPU exit and re-evaluate the priorities, potentially
+ * leading to this interrupt getting presented now to the guest (if it has
+ * been masked by the priority mask before).
+ */
+void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		/* Narrow the priority range to what we actually support */
+		irq->priority = (val >> (i * 8)) & GENMASK(7, 8 - VGIC_PRI_BITS);
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index dd96a71..6983922 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -117,6 +117,13 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val);
 
+unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
+				      gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index cf62015..e57f8d5 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,8 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define VGIC_PRI_BITS		5
+
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:14 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:14 +0100
Subject: [PATCH v4 29/56] KVM: arm/arm64: vgic-new: Add CONFIG registers
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-87-git-send-email-andre.przywara@arm.com>

The config register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro
- replace extract_bytes() with simple return

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 46 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  7 ++++++
 3 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index d564a30..bb7389e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -96,7 +96,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 2,
+		vgic_mmio_read_config, vgic_mmio_write_config, 2,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 5c8af05..5fe6896 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -277,6 +277,52 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 2);
+	u32 value = 0;
+	int i;
+
+	for (i = 0; i < len * 4; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			value |= (2U << (i * 2));
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
+			    gpa_t addr, unsigned int len,
+			    unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 2);
+	int i;
+
+	for (i = 0; i < len * 4; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (intid + i < 16)
+			continue;
+
+		/*
+		 * The spec says that interrupts must be disabled before
+		 * changing the configuration to avoid UNDEFINED behaviour.
+		 */
+
+		spin_lock(&irq->irq_lock);
+		if (test_bit(i * 2 + 1, &val)) {
+			irq->config = VGIC_CONFIG_EDGE;
+		} else {
+			irq->config = VGIC_CONFIG_LEVEL;
+			irq->pending = irq->line_level | irq->soft_pending;
+		}
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 6983922..0bd0ece 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -124,6 +124,13 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
 			      gpa_t addr, unsigned int len,
 			      unsigned long val);
 
+unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
+			    gpa_t addr, unsigned int len,
+			    unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:12 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:12 +0100
Subject: [PATCH v4 27/56] KVM: arm/arm64: vgic-new: Add ACTIVE registers
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-85-git-send-email-andre.przywara@arm.com>

The active register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.
Since activation/deactivation of an interrupt may happen entirely
in the guest without it ever exiting, we need some extra logic to
properly track the active state.
Putting it on an ap_list on activation is similar to the normal case
handled by vgic_queue_irq_unlock(), but differs in some details that
make a separate implementation worthwhile.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- handling queueing in write handler
- remove IRQ lock from read handler

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro
- drop elaborate write_sactive handler and use new vgic_queue_irq_unlock()
- properly emulate clear active by halting the guest (Christoffer)
- replace extract_bytes() with simple return

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 82 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 10 +++++
 3 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index c13a708..12e101b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -84,10 +84,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index d8dc8f6..74d140e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -155,6 +155,88 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->active)
+			value |= (1U << i);
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	kvm_arm_halt_guest(vcpu->kvm);
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		/*
+		 * If this virtual IRQ was written into a list register, we
+		 * have to make sure the CPU that runs the VCPU thread has
+		 * synced back LR state to the struct vgic_irq.  We can only
+		 * know this for sure, when either this irq is not assigned to
+		 * anyone's AP list anymore, or the VCPU thread is not
+		 * running on any CPUs.
+		 *
+		 * In the opposite case, we know the VCPU thread may be on its
+		 * way back from the guest and still has to sync back this
+		 * IRQ, so we release and re-acquire the spin_lock to let the
+		 * other thread sync back the IRQ.
+		 */
+		while (irq->vcpu && /* IRQ may have state in an LR somewhere */
+		       irq->vcpu->cpu != -1) /* VCPU thread is running */
+			cond_resched_lock(&irq->irq_lock);
+
+		irq->active = false;
+		spin_unlock(&irq->irq_lock);
+	}
+	kvm_arm_resume_guest(vcpu->kvm);
+}
+
+void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		/*
+		 * If the IRQ was already active or it was on a VCPU before
+		 * or there is no target VCPU assigned at the moment, then
+		 * just proceed.
+		 */
+		if (irq->active || irq->vcpu || !irq->target_vcpu) {
+			irq->active = true;
+
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		irq->active = true;
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 01db98a..dd96a71 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -106,6 +106,16 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
 			      gpa_t addr, unsigned int len,
 			      unsigned long val);
 
+unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
+void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
 
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:18 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:18 +0100
Subject: [PATCH v4 33/56] KVM: arm/arm64: vgic-new: Add GICv3 MMIO handling
 framework
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-91-git-send-email-andre.przywara@arm.com>

Create a new file called vgic-mmio-v3.c and describe the GICv3
distributor and redistributor registers there.
This adds a special macro to deal with the split of SGI/PPI in the
redistributor and SPIs in the distributor, which allows us to reuse
the existing GICv2 handlers for those registers which are compatible.
Also we provide a function to deal with the registration of the two
separate redistributor frames per VCPU.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog RFC..v1:
- adapt to new MMIO registration approach:
  register one device for the distributor and two for each VCPU
- implement special handling for private interrupts
- remove empty stub functions
- make IGROUPR return RAO

Changelog v1 .. v2:
- adapt to new framework, introduce vgic-mmio-v3.c
- remove userland register access functions (for now)
- precompute .len when describing a VGIC register
- add missed pointer incrementation on registering redist regions
- replace _nyi stub functions with raz/wi versions

Changelog v2 .. v3:
- replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h
- add prototype and stub code for vgic_register_redist_iodevs
- rename register struct variables _rdbase_ and _sgibase_

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 224 +++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
 virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
 virt/kvm/arm/vgic/vgic.h         |   7 ++
 4 files changed, 238 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
new file mode 100644
index 0000000..31f1a13
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -0,0 +1,224 @@
+/*
+ * VGICv3 MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irqchip/arm-gic-v3.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include <asm/kvm_emulate.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+/*
+ * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
+ * redistributors, while SPIs are covered by registers in the distributor
+ * block. Trying to set private IRQs in this block gets ignored.
+ * We take some special care here to fix the calculation of the register
+ * offset.
+ */
+#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, rd, wr, bpi, acc)	\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = bpi,					\
+		.len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8,		\
+		.access_flags = acc,					\
+		.read = vgic_mmio_read_raz,				\
+		.write = vgic_mmio_write_wi,				\
+	}, {								\
+		.reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8,	\
+		.bits_per_irq = bpi,					\
+		.len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
+		.access_flags = acc,					\
+		.read = rd,						\
+		.write = wr,						\
+	}
+
+static const struct vgic_register_region vgic_v3_dist_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
+		vgic_mmio_read_config, vgic_mmio_write_config, 2,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		VGIC_ACCESS_32bit),
+};
+
+static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		VGIC_ACCESS_32bit),
+};
+
+static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 32,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
+		vgic_mmio_read_config, vgic_mmio_write_config, 8,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+};
+
+unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
+{
+	dev->regions = vgic_v3_dist_registers;
+	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
+
+	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
+
+	return SZ_64K;
+}
+
+int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
+{
+	int nr_vcpus = atomic_read(&kvm->online_vcpus);
+	struct kvm_vcpu *vcpu;
+	struct vgic_io_device *devices;
+	int c, ret = 0;
+
+	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
+			  GFP_KERNEL);
+	if (!devices)
+		return -ENOMEM;
+
+	kvm_for_each_vcpu(c, vcpu, kvm) {
+		gpa_t rd_base = redist_base_address + c * SZ_64K * 2;
+		gpa_t sgi_base = rd_base + SZ_64K;
+		struct vgic_io_device *rd_dev = &devices[c * 2];
+		struct vgic_io_device *sgi_dev = &devices[c * 2 + 1];
+
+		kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops);
+		rd_dev->base_addr = rd_base;
+		rd_dev->regions = vgic_v3_rdbase_registers;
+		rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
+		rd_dev->redist_vcpu = vcpu;
+
+		mutex_lock(&kvm->slots_lock);
+		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base,
+					      SZ_64K, &rd_dev->dev);
+		mutex_unlock(&kvm->slots_lock);
+
+		if (ret)
+			break;
+
+		kvm_iodevice_init(&sgi_dev->dev, &kvm_io_gic_ops);
+		sgi_dev->base_addr = sgi_base;
+		sgi_dev->regions = vgic_v3_sgibase_registers;
+		sgi_dev->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
+		sgi_dev->redist_vcpu = vcpu;
+
+		mutex_lock(&kvm->slots_lock);
+		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, sgi_base,
+					      SZ_64K, &sgi_dev->dev);
+		mutex_unlock(&kvm->slots_lock);
+		if (ret) {
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2].dev);
+			break;
+		}
+	}
+
+	if (ret) {
+		/* The current c failed, so we start with the previous one. */
+		for (c--; c >= 0; c--) {
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2].dev);
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2 + 1].dev);
+		}
+		kfree(devices);
+	} else {
+		kvm->arch.vgic.redist_iodevs = devices;
+	}
+
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 5fe6896..35f49f4 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -478,6 +478,11 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 	case VGIC_V2:
 		len = vgic_v2_init_dist_iodev(io_device);
 		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case VGIC_V3:
+		len = vgic_v3_init_dist_iodev(io_device);
+		break;
+#endif
 	default:
 		BUG_ON(1);
 	}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 0bd0ece..a59f95d 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -133,4 +133,6 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
 
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
+unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
+
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index e57f8d5..6742b11 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -42,6 +42,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
 {
@@ -63,6 +64,12 @@ static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 }
+
+static inline int vgic_register_redist_iodevs(struct kvm *kvm,
+					      gpa_t dist_base_address)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:25 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:25 +0100
Subject: [PATCH v4 40/56] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_NR_IRQS
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-98-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_NR_IRQS group. This
modality is supported by both VGIC V2 and V3 KVM device as will be
other groups, hence the introduction of common helpers.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 83 +++++++++++++++++++++++++++++++++++--
 1 file changed, 79 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index ff332f3..05ff925 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -15,9 +15,69 @@
  */
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
+#include <linux/uaccess.h>
+#include "vgic.h"
 
 /* common helpers */
 
+static int vgic_set_common_attr(struct kvm_device *dev,
+				struct kvm_device_attr *attr)
+{
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 val;
+		int ret = 0;
+
+		if (get_user(val, uaddr))
+			return -EFAULT;
+
+		/*
+		 * We require:
+		 * - at least 32 SPIs on top of the 16 SGIs and 16 PPIs
+		 * - at most 1024 interrupts
+		 * - a multiple of 32 interrupts
+		 */
+		if (val < (VGIC_NR_PRIVATE_IRQS + 32) ||
+		    val > VGIC_MAX_RESERVED ||
+		    (val & 31))
+			return -EINVAL;
+
+		mutex_lock(&dev->kvm->lock);
+
+		if (vgic_ready(dev->kvm) || dev->kvm->arch.vgic.nr_spis)
+			ret = -EBUSY;
+		else
+			dev->kvm->arch.vgic.nr_spis =
+				val - VGIC_NR_PRIVATE_IRQS;
+
+		mutex_unlock(&dev->kvm->lock);
+
+		return ret;
+	}
+	}
+
+	return -ENXIO;
+}
+
+static int vgic_get_common_attr(struct kvm_device *dev,
+				struct kvm_device_attr *attr)
+{
+	int r = -ENXIO;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+
+		r = put_user(dev->kvm->arch.vgic.nr_spis +
+			     VGIC_NR_PRIVATE_IRQS, uaddr);
+		break;
+	}
+	}
+
+	return r;
+}
+
 static int vgic_create(struct kvm_device *dev, u32 type)
 {
 	return kvm_vgic_create(dev->kvm, type);
@@ -49,18 +109,29 @@ void kvm_register_vgic_device(unsigned long type)
 static int vgic_v2_set_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	int ret;
+
+	ret = vgic_set_common_attr(dev, attr);
+	return ret;
+
 }
 
 static int vgic_v2_get_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	int ret;
+
+	ret = vgic_get_common_attr(dev, attr);
+	return ret;
 }
 
 static int vgic_v2_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
+		return 0;
+	}
 	return -ENXIO;
 }
 
@@ -80,18 +151,22 @@ struct kvm_device_ops kvm_arm_vgic_v2_ops = {
 static int vgic_v3_set_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	return vgic_set_common_attr(dev, attr);
 }
 
 static int vgic_v3_get_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	return vgic_get_common_attr(dev, attr);
 }
 
 static int vgic_v3_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
+		return 0;
+	}
 	return -ENXIO;
 }
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:15 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:15 +0100
Subject: [PATCH v4 30/56] KVM: arm/arm64: vgic-new: Add TARGET registers
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-88-git-send-email-andre.przywara@arm.com>

The target register handlers are v2 emulation specific, so their
implementation lives entirely in vgic-mmio-v2.c.
We copy the old VGIC behaviour of assigning an IRQ to the first VCPU
set in the target mask instead of making it possibly pending on
multiple VCPUs.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- remove runtime VCPU determination from this v2-only register
- fold in implementation of vgic_v2_irq_change_affinity()
- replace ffs() with __ffs()

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index bb7389e..52389ff 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -64,6 +64,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
+					   gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->targets << (i * 8);
+	}
+
+	return val;
+}
+
+static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
+				   gpa_t addr, unsigned int len,
+				   unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+
+	/* GICD_ITARGETSR[0-7] are read-only */
+	if (intid < VGIC_NR_PRIVATE_IRQS)
+		return;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
+		int target;
+
+		spin_lock(&irq->irq_lock);
+
+		irq->targets = (val >> (i * 8)) & 0xff;
+		target = irq->targets ? __ffs(irq->targets) : 0;
+		irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target);
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
@@ -93,7 +134,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		vgic_mmio_read_target, vgic_mmio_write_target, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
 		vgic_mmio_read_config, vgic_mmio_write_config, 2,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:07 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:07 +0100
Subject: [PATCH v4 22/56] KVM: arm/arm64: vgic-new: Add MMIO handling framework
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-80-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Add an MMIO handling framework to the VGIC emulation:
Each register is described by its offset, size (or number of bits per
IRQ, if applicable) and the read/write handler functions. We provide
initialization macros to describe each GIC register later easily.

Separate dispatch functions for read and write accesses are connected
to the kvm_io_bus framework and binary-search for the responsible
register handler based on the offset address within the region.
We convert the incoming data (referenced by a pointer) to the host's
endianess and use pass-by-value to hand the data over to the actual
handler functions.

The register handler prototype and the endianess conversion are
courtesy of Christoffer Dall.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- rework MMIO dispatching to use only one kvm_io_bus device
- document purpose of register region macros
- rename "this" parameter to "dev"
- change IGROUPR to be RAO (returning 1 => Group1 IRQs)

Changelog v1 .. v2:
* MASSIVE rework:
- store register_region pointer in kvm_io_bus linked struct
- replace write_mask_xxx functions with extract_bytes() implementation
- change handler functions' prototypes to take and return unsigned long
- use binary search to find matching register handler
- convert endianess of input data in dispatch_mmio_xxx functions
- improve readability of register initializer macros
- remove any GICv2/GICv3 specific functions from vgic-mmio.c
- rename file from vgic_mmio.c to vgic-mmio.c

Changelog v2 .. v3:
- replace inclusion of vgic/vgic.h with arm_vgic.h

Changelog v3 .. v4:
- add IRQ number accessor macro
- check access width in dispatcher
- treat non-covered MMIO addresses as RAZ/WI
- remove extract_bytes() (re-introduced as static later in the series)

 include/kvm/vgic/vgic.h       |  13 +++
 virt/kvm/arm/vgic/vgic-mmio.c | 184 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h |  87 ++++++++++++++++++++
 3 files changed, 284 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index f663288..ff3f9c2 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -106,6 +106,16 @@ struct vgic_irq {
 	enum vgic_irq_config config;	/* Level or edge */
 };
 
+struct vgic_register_region;
+
+struct vgic_io_device {
+	gpa_t base_addr;
+	struct kvm_vcpu *redist_vcpu;
+	const struct vgic_register_region *regions;
+	int nr_regions;
+	struct kvm_io_device dev;
+};
+
 struct vgic_dist {
 	bool			in_kernel;
 	bool			ready;
@@ -132,6 +142,9 @@ struct vgic_dist {
 	bool			enabled;
 
 	struct vgic_irq		*spis;
+
+	struct vgic_io_device	dist_iodev;
+	struct vgic_io_device	*redist_iodevs;
 };
 
 struct vgic_v2_cpu_if {
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
new file mode 100644
index 0000000..012b82b
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -0,0 +1,184 @@
+/*
+ * VGIC MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/bsearch.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len)
+{
+	return 0;
+}
+
+unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len)
+{
+	return -1UL;
+}
+
+void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
+			unsigned int len, unsigned long val)
+{
+	/* Ignore */
+}
+
+static int match_region(const void *key, const void *elt)
+{
+	const unsigned int offset = (unsigned long)key;
+	const struct vgic_register_region *region = elt;
+
+	if (offset < region->reg_offset)
+		return -1;
+
+	if (offset >= region->reg_offset + region->len)
+		return 1;
+
+	return 0;
+}
+
+/* Find the proper register handler entry given a certain address offset. */
+static const struct vgic_register_region *
+vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
+		      unsigned int offset)
+{
+	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
+		       sizeof(region[0]), match_region);
+}
+
+/*
+ * kvm_mmio_read_buf() returns a value in a format where it can be converted
+ * to a byte array and be directly observed as the guest wanted it to appear
+ * in memory if it had done the store itself, which is LE for the GIC, as the
+ * guest knows the GIC is always LE.
+ *
+ * We convert this value to the CPUs native format to deal with it as a data
+ * value.
+ */
+unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len)
+{
+	unsigned long data = kvm_mmio_read_buf(val, len);
+
+	switch (len) {
+	case 1:
+		return data;
+	case 2:
+		return le16_to_cpu(data);
+	case 4:
+		return le32_to_cpu(data);
+	default:
+		return le64_to_cpu(data);
+	}
+}
+
+/*
+ * kvm_mmio_write_buf() expects a value in a format such that if converted to
+ * a byte array it is observed as the guest would see it if it could perform
+ * the load directly.  Since the GIC is LE, and the guest knows this, the
+ * guest expects a value in little endian format.
+ *
+ * We convert the data value from the CPUs native format to LE so that the
+ * value is returned in the proper format.
+ */
+void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
+				unsigned long data)
+{
+	switch (len) {
+	case 1:
+		break;
+	case 2:
+		data = cpu_to_le16(data);
+		break;
+	case 4:
+		data = cpu_to_le32(data);
+		break;
+	default:
+		data = cpu_to_le64(data);
+	}
+
+	kvm_mmio_write_buf(buf, len, data);
+}
+
+static
+struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
+{
+	return container_of(dev, struct vgic_io_device, dev);
+}
+
+static bool check_region(const struct vgic_register_region *region,
+			 gpa_t addr, int len)
+{
+	if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1)
+		return true;
+	if ((region->access_flags & VGIC_ACCESS_32bit) &&
+	    len == sizeof(u32) && !(addr & 3))
+		return true;
+	if ((region->access_flags & VGIC_ACCESS_64bit) &&
+	    len == sizeof(u64) && !(addr & 7))
+		return true;
+
+	return false;
+}
+
+static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
+			      gpa_t addr, int len, void *val)
+{
+	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
+	const struct vgic_register_region *region;
+	struct kvm_vcpu *r_vcpu;
+	unsigned long data;
+
+	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
+				       addr - iodev->base_addr);
+	if (!region || !check_region(region, addr, len)) {
+		memset(val, 0, len);
+		return 0;
+	}
+
+	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
+	data = region->read(r_vcpu, addr, len);
+	vgic_data_host_to_mmio_bus(val, len, data);
+	return 0;
+}
+
+static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
+			       gpa_t addr, int len, const void *val)
+{
+	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
+	const struct vgic_register_region *region;
+	struct kvm_vcpu *r_vcpu;
+	unsigned long data = vgic_data_mmio_bus_to_host(val, len);
+
+	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
+				       addr - iodev->base_addr);
+	if (!region)
+		return 0;
+
+	if (!check_region(region, addr, len))
+		return 0;
+
+	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
+	region->write(r_vcpu, addr, len, data);
+	return 0;
+}
+
+struct kvm_io_device_ops kvm_io_gic_ops = {
+	.read = dispatch_mmio_read,
+	.write = dispatch_mmio_write,
+};
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
new file mode 100644
index 0000000..855b1db
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __KVM_ARM_VGIC_MMIO_H__
+#define __KVM_ARM_VGIC_MMIO_H__
+
+struct vgic_register_region {
+	unsigned int reg_offset;
+	unsigned int len;
+	unsigned int bits_per_irq;
+	unsigned int access_flags;
+	unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr,
+			      unsigned int len);
+	void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
+		      unsigned long val);
+};
+
+extern struct kvm_io_device_ops kvm_io_gic_ops;
+
+#define VGIC_ACCESS_8bit	1
+#define VGIC_ACCESS_32bit	2
+#define VGIC_ACCESS_64bit	4
+
+/* generate a mask that covers 1024 interrupts with <b> bits per IRQ */
+#define VGIC_ADDR_IRQ_MASK(b) GENMASK_ULL(ilog2(b) + ilog2(1024) - \
+					  ilog2(BITS_PER_BYTE) - 1, 0)
+#define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
+					64 / (bits) / 8)
+
+/*
+ * Some VGIC registers store per-IRQ information, with a different number
+ * of bits per IRQ. For those registers this macro is used.
+ * The _WITH_LENGTH version instantiates registers with a fixed length
+ * and is mutually exclusive with the _PER_IRQ version.
+ */
+#define REGISTER_DESC_WITH_BITS_PER_IRQ(off, rd, wr, bpi, acc)		\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = bpi,					\
+		.len = bpi * 1024 / 8,					\
+		.access_flags = acc,					\
+		.read = rd,						\
+		.write = wr,						\
+	}
+
+#define REGISTER_DESC_WITH_LENGTH(off, rd, wr, length, acc)		\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = 0,					\
+		.len = length,						\
+		.access_flags = acc,					\
+		.read = rd,						\
+		.write = wr,						\
+	}
+
+int kvm_vgic_register_mmio_region(struct kvm *kvm, struct kvm_vcpu *vcpu,
+				  struct vgic_register_region *reg_desc,
+				  struct vgic_io_device *region,
+				  int nr_irqs, bool offset_private);
+
+unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len);
+
+void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
+				unsigned long data);
+
+unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len);
+
+unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
+			unsigned int len, unsigned long val);
+
+#endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:16 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:16 +0100
Subject: [PATCH v4 31/56] KVM: arm/arm64: vgic-new: Add SGIR register handler
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-89-git-send-email-andre.przywara@arm.com>

Triggering an IPI via this register is v2 specific, so the
implementation lives entirely in vgic-mmio-v2.c.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- silently return on illegal TargetListFilter value (=3)

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 52389ff..c884e9b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -64,6 +64,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
+				 gpa_t addr, unsigned int len,
+				 unsigned long val)
+{
+	int nr_vcpus = atomic_read(&source_vcpu->kvm->online_vcpus);
+	int intid = val & 0xf;
+	int targets = (val >> 16) & 0xff;
+	int mode = (val >> 24) & 0x03;
+	int c;
+	struct kvm_vcpu *vcpu;
+
+	switch (mode) {
+	case 0x0:		/* as specified by targets */
+		break;
+	case 0x1:
+		targets = (1U << nr_vcpus) - 1;			/* all, ... */
+		targets &= ~(1U << source_vcpu->vcpu_id);	/* but self */
+		break;
+	case 0x2:		/* this very vCPU only */
+		targets = (1U << source_vcpu->vcpu_id);
+		break;
+	case 0x3:		/* reserved */
+		return;
+	}
+
+	kvm_for_each_vcpu(c, vcpu, source_vcpu->kvm) {
+		struct vgic_irq *irq;
+
+		if (!(targets & (1U << c)))
+			continue;
+
+		irq = vgic_get_irq(source_vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+		irq->source |= 1U << source_vcpu->vcpu_id;
+
+		vgic_queue_irq_unlock(source_vcpu->kvm, irq);
+	}
+}
+
 static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
 					   gpa_t addr, unsigned int len)
 {
@@ -140,7 +181,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_config, vgic_mmio_write_config, 2,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:31 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:31 +0100
Subject: [PATCH v4 46/56] KVM: arm/arm64: vgic-new: Add userland access to
 VGIC dist registers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-104-git-send-email-andre.przywara@arm.com>

Userland may want to save and restore the state of the in-kernel VGIC,
so we provide the code which takes a userland request and translate
that into calls to our MMIO framework.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 50 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 78621283..c3ec453 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -238,7 +238,55 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 				 struct kvm_device_attr *attr,
 				 u32 *reg, bool is_write)
 {
-	return -ENXIO;
+	gpa_t addr;
+	int cpuid, ret, c;
+	struct kvm_vcpu *vcpu, *tmp_vcpu;
+
+	cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
+		 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
+	vcpu = kvm_get_vcpu(dev->kvm, cpuid);
+	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+	mutex_lock(&dev->kvm->lock);
+
+	ret = vgic_init(dev->kvm);
+	if (ret)
+		goto out;
+
+	if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Ensure that no other VCPU is running by checking the vcpu->cpu
+	 * field.  If no other VPCUs are running we can safely access the VGIC
+	 * state, because even if another VPU is run after this point, that
+	 * VCPU will not touch the vgic state, because it will block on
+	 * getting the vgic->lock in kvm_vgic_sync_hwstate().
+	 */
+	kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm) {
+		if (unlikely(tmp_vcpu->cpu != -1)) {
+			ret = -EBUSY;
+			goto out;
+		}
+	}
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		ret = -EINVAL;
+		break;
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+out:
+	mutex_unlock(&dev->kvm->lock);
+	return ret;
 }
 
 /* V2 ops */
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:30 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:30 +0100
Subject: [PATCH v4 45/56] KVM: arm/arm64: vgic-new: Export register access
 interface
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-103-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Userland can access the emulated GIC to save and restore its state
for initialization or migration purposes.
The kvm_io_bus API requires an absolute gpa, which does not fit the
KVM_DEV_ARM_VGIC_GRP_DIST_REGS user API, that only provides relative
offsets. So we provide a wrapper to plug into our MMIO framework and
find the respective register handler.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework
- handle endianess explicitly

Changelog v2 .. v3:
- wrap accessor function for easier reusage later
- moved from earlier in the series

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 36 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 2 files changed, 38 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 7189690..a255122 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -296,3 +296,39 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 
 	return -ENXIO;
 }
+
+/*
+ * When userland tries to access the VGIC register handlers, we need to
+ * create a usable struct vgic_io_device to be passed to the handlers and we
+ * have to set up a buffer similar to what would have happened if a guest MMIO
+ * access occurred, including doing endian conversions on BE systems.
+ */
+static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
+			bool is_write, int offset, u32 *val)
+{
+	unsigned int len = 4;
+	u8 buf[4];
+	int ret;
+
+	if (is_write) {
+		vgic_data_host_to_mmio_bus(buf, len, *val);
+		ret = kvm_io_gic_ops.write(vcpu, &dev->dev, offset, len, buf);
+	} else {
+		ret = kvm_io_gic_ops.read(vcpu, &dev->dev, offset, len, buf);
+		if (!ret)
+			*val = vgic_data_mmio_bus_to_host(buf, len);
+	}
+
+	return ret;
+}
+
+int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			 int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_dist_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_dist_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index a264c5f..f826026 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -38,6 +38,8 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
+int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			 int offset, u32 *val);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:34 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:34 +0100
Subject: [PATCH v4 49/56] KVM: arm/arm64: vgic-new: vgic_init: implement
 kvm_vgic_hyp_init
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-107-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

Implements kvm_vgic_hyp_init and vgic_probe function.
This uses the new firmware independent VGIC probing to support both ACPI
and DT based systems (code from Marc Zyngier).

The vgic_global struct is enriched with new fields populated
by those functions.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- rename vgic_init.c to vgic-init.c

Changelog v2 .. v3:
- include kvm/arm_vgic.h instead of kvm/vgic/vgic.h
- move ich_vtr_el2 variable into probe function

Changelog v3 .. v4:
- improve nr_lr determination in GICv2 probe
- switching to firmware-independent probing

 include/kvm/vgic/vgic.h       |   1 +
 virt/kvm/arm/vgic/vgic-init.c | 123 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   |  64 ++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c   |  49 +++++++++++++++++
 virt/kvm/arm/vgic/vgic.h      |   9 ++++
 5 files changed, 246 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-init.c

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 3689b9b..393489f 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -195,6 +195,7 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
new file mode 100644
index 0000000..4523beb
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/cpu.h>
+#include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
+#include "vgic.h"
+
+/* GENERIC PROBE */
+
+static void vgic_init_maintenance_interrupt(void *info)
+{
+	enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0);
+}
+
+static int vgic_cpu_notify(struct notifier_block *self,
+			   unsigned long action, void *cpu)
+{
+	switch (action) {
+	case CPU_STARTING:
+	case CPU_STARTING_FROZEN:
+		vgic_init_maintenance_interrupt(NULL);
+		break;
+	case CPU_DYING:
+	case CPU_DYING_FROZEN:
+		disable_percpu_irq(kvm_vgic_global_state.maint_irq);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block vgic_cpu_nb = {
+	.notifier_call = vgic_cpu_notify,
+};
+
+static irqreturn_t vgic_maintenance_handler(int irq, void *data)
+{
+	/*
+	 * We cannot rely on the vgic maintenance interrupt to be
+	 * delivered synchronously. This means we can only use it to
+	 * exit the VM, and we perform the handling of EOIed
+	 * interrupts on the exit path (see vgic_process_maintenance).
+	 */
+	return IRQ_HANDLED;
+}
+
+/**
+ * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable
+ * according to the host GIC model. Accordingly calls either
+ * vgic_v2/v3_probe which registers the KVM_DEVICE that can be
+ * instantiated by a guest later on .
+ */
+int kvm_vgic_hyp_init(void)
+{
+	const struct gic_kvm_info *gic_kvm_info;
+	int ret;
+
+	gic_kvm_info = gic_get_kvm_info();
+	if (!gic_kvm_info)
+		return -ENODEV;
+
+	if (!gic_kvm_info->maint_irq) {
+		kvm_err("No vgic maintenance irq\n");
+		return -ENXIO;
+	}
+
+	switch (gic_kvm_info->type) {
+	case GIC_V2:
+		ret = vgic_v2_probe(gic_kvm_info);
+		break;
+	case GIC_V3:
+		ret = vgic_v3_probe(gic_kvm_info);
+		break;
+	default:
+		ret = -ENODEV;
+	};
+
+	if (ret)
+		return ret;
+
+	kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
+	ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
+				 vgic_maintenance_handler,
+				 "vgic", kvm_get_running_vcpus());
+	if (ret) {
+		kvm_err("Cannot register interrupt %d\n",
+			kvm_vgic_global_state.maint_irq);
+		return ret;
+	}
+
+	ret = __register_cpu_notifier(&vgic_cpu_nb);
+	if (ret) {
+		kvm_err("Cannot register vgic CPU notifier\n");
+		goto out_free_irq;
+	}
+
+	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
+
+	kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq);
+	return 0;
+
+out_free_irq:
+	free_percpu_irq(kvm_vgic_global_state.maint_irq,
+			kvm_get_running_vcpus());
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index d943059..09777c8 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -17,6 +17,8 @@
 #include <linux/irqchip/arm-gic.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
 
 #include "vgic.h"
 
@@ -203,3 +205,65 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
 			GICH_VMCR_PRIMASK_SHIFT;
 }
+
+/**
+ * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
+ * @node:	pointer to the DT node
+ *
+ * Returns 0 if a GICv2 has been found, returns an error code otherwise
+ */
+int vgic_v2_probe(const struct gic_kvm_info *info)
+{
+	int ret;
+	u32 vtr;
+
+	if (!info->vctrl.start) {
+		kvm_err("GICH not present in the firmware table\n");
+		return -ENXIO;
+	}
+
+	if (!PAGE_ALIGNED(info->vcpu.start)) {
+		kvm_err("GICV physical address 0x%llx not page aligned\n",
+			(unsigned long long)info->vcpu.start);
+		return -ENXIO;
+	}
+
+	if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
+		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+			(unsigned long long)resource_size(&info->vcpu),
+			PAGE_SIZE);
+		return -ENXIO;
+	}
+
+	kvm_vgic_global_state.vctrl_base = ioremap(info->vctrl.start,
+						   resource_size(&info->vctrl));
+	if (!kvm_vgic_global_state.vctrl_base) {
+		kvm_err("Cannot ioremap GICH\n");
+		return -ENOMEM;
+	}
+
+	vtr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
+	kvm_vgic_global_state.nr_lr = (vtr & 0x3f) + 1;
+
+	ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
+				     kvm_vgic_global_state.vctrl_base +
+					 resource_size(&info->vctrl),
+				     info->vctrl.start);
+
+	if (ret) {
+		kvm_err("Cannot map VCTRL into hyp\n");
+		iounmap(kvm_vgic_global_state.vctrl_base);
+		return ret;
+	}
+
+	kvm_vgic_global_state.can_emulate_gicv2 = true;
+	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+
+	kvm_vgic_global_state.vcpu_base = info->vcpu.start;
+	kvm_vgic_global_state.type = VGIC_V2;
+	kvm_vgic_global_state.max_gic_vcpus = VGIC_V2_MAX_CPUS;
+
+	kvm_info("vgic-v2@%llx\n", info->vctrl.start);
+
+	return 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 8548297..de0e8e0 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -15,6 +15,9 @@
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
+#include <asm/kvm_asm.h>
 
 #include "vgic.h"
 
@@ -182,3 +185,49 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
+
+/**
+ * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
+ * @node:	pointer to the DT node
+ *
+ * Returns 0 if a GICv3 has been found, returns an error code otherwise
+ */
+int vgic_v3_probe(const struct gic_kvm_info *info)
+{
+	u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
+
+	/*
+	 * The ListRegs field is 5 bits, but there is a architectural
+	 * maximum of 16 list registers. Just ignore bit 4...
+	 */
+	kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
+	kvm_vgic_global_state.can_emulate_gicv2 = false;
+
+	if (!info->vcpu.start) {
+		kvm_info("GICv3: no GICV resource entry\n");
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else if (!PAGE_ALIGNED(info->vcpu.start)) {
+		pr_warn("GICV physical address 0x%llx not page aligned\n",
+			(unsigned long long)info->vcpu.start);
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
+		pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+			(unsigned long long)resource_size(&info->vcpu),
+			PAGE_SIZE);
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else {
+		kvm_vgic_global_state.vcpu_base = info->vcpu.start;
+		kvm_vgic_global_state.can_emulate_gicv2 = true;
+		kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+		kvm_info("vgic-v2@%llx\n", info->vcpu.start);
+	}
+	if (kvm_vgic_global_state.vcpu_base == 0)
+		kvm_info("disabling GICv2 emulation\n");
+	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V3);
+
+	kvm_vgic_global_state.vctrl_base = NULL;
+	kvm_vgic_global_state.type = VGIC_V3;
+	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
+
+	return 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index de9dc71..f4244b6 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,6 +16,8 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#include <linux/irqchip/arm-gic-common.h>
+
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
@@ -51,6 +53,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+int vgic_v2_probe(const struct gic_kvm_info *info);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -62,6 +65,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+int vgic_v3_probe(const struct gic_kvm_info *info);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -95,6 +99,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
 {
 }
 
+static inline int vgic_v3_probe(const struct gic_kvm_info *info)
+{
+	return -ENODEV;
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:23 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:23 +0100
Subject: [PATCH v4 38/56] KVM: arm/arm64: vgic-new: Add GICv3 SGI system
 register trap handler
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-96-git-send-email-andre.przywara@arm.com>

In contrast to GICv2 SGIs in a GICv3 implementation are not triggered
by a MMIO write, but with a system register write. KVM knows about
that register already, we just need to implement the handler and wire
it up to the core KVM/ARM code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- add comment about SGI_AFFINITY_LEVEL macro

 include/kvm/vgic/vgic.h          |   8 +++
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 106 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index ff3f9c2..00e3dca 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -209,6 +209,14 @@ bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
 
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
+#else
+static inline void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
+{
+}
+#endif
+
 /**
  * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
  *
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 7b9340b..63b8550 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -343,3 +343,109 @@ int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
 
 	return ret;
 }
+
+/*
+ * Compare a given affinity (level 1-3 and a level 0 mask, from the SGI
+ * generation register ICC_SGI1R_EL1) with a given VCPU.
+ * If the VCPU's MPIDR matches, return the level0 affinity, otherwise
+ * return -1.
+ */
+static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct kvm_vcpu *vcpu)
+{
+	unsigned long affinity;
+	int level0;
+
+	/*
+	 * Split the current VCPU's MPIDR into affinity level 0 and the
+	 * rest as this is what we have to compare against.
+	 */
+	affinity = kvm_vcpu_get_mpidr_aff(vcpu);
+	level0 = MPIDR_AFFINITY_LEVEL(affinity, 0);
+	affinity &= ~MPIDR_LEVEL_MASK;
+
+	/* bail out if the upper three levels don't match */
+	if (sgi_aff != affinity)
+		return -1;
+
+	/* Is this VCPU's bit set in the mask ? */
+	if (!(sgi_cpu_mask & BIT(level0)))
+		return -1;
+
+	return level0;
+}
+
+/*
+ * The ICC_SGI* registers encode the affinity differently from the MPIDR,
+ * so provide a wrapper to use the existing defines to isolate a certain
+ * affinity level.
+ */
+#define SGI_AFFINITY_LEVEL(reg, level) \
+	((((reg) & ICC_SGI1R_AFFINITY_## level ##_MASK) \
+	>> ICC_SGI1R_AFFINITY_## level ##_SHIFT) << MPIDR_LEVEL_SHIFT(level))
+
+/**
+ * vgic_v3_dispatch_sgi - handle SGI requests from VCPUs
+ * @vcpu: The VCPU requesting a SGI
+ * @reg: The value written into the ICC_SGI1R_EL1 register by that VCPU
+ *
+ * With GICv3 (and ARE=1) CPUs trigger SGIs by writing to a system register.
+ * This will trap in sys_regs.c and call this function.
+ * This ICC_SGI1R_EL1 register contains the upper three affinity levels of the
+ * target processors as well as a bitmask of 16 Aff0 CPUs.
+ * If the interrupt routing mode bit is not set, we iterate over all VCPUs to
+ * check for matching ones. If this bit is set, we signal all, but not the
+ * calling VCPU.
+ */
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
+{
+	struct kvm *kvm = vcpu->kvm;
+	struct kvm_vcpu *c_vcpu;
+	u16 target_cpus;
+	u64 mpidr;
+	int sgi, c;
+	int vcpu_id = vcpu->vcpu_id;
+	bool broadcast;
+
+	sgi = (reg & ICC_SGI1R_SGI_ID_MASK) >> ICC_SGI1R_SGI_ID_SHIFT;
+	broadcast = reg & BIT(ICC_SGI1R_IRQ_ROUTING_MODE_BIT);
+	target_cpus = (reg & ICC_SGI1R_TARGET_LIST_MASK) >> ICC_SGI1R_TARGET_LIST_SHIFT;
+	mpidr = SGI_AFFINITY_LEVEL(reg, 3);
+	mpidr |= SGI_AFFINITY_LEVEL(reg, 2);
+	mpidr |= SGI_AFFINITY_LEVEL(reg, 1);
+
+	/*
+	 * We iterate over all VCPUs to find the MPIDRs matching the request.
+	 * If we have handled one CPU, we clear its bit to detect early
+	 * if we are already finished. This avoids iterating through all
+	 * VCPUs when most of the times we just signal a single VCPU.
+	 */
+	kvm_for_each_vcpu(c, c_vcpu, kvm) {
+		struct vgic_irq *irq;
+
+		/* Exit early if we have dealt with all requested CPUs */
+		if (!broadcast && target_cpus == 0)
+			break;
+
+		/* Don't signal the calling VCPU */
+		if (broadcast && c == vcpu_id)
+			continue;
+
+		if (!broadcast) {
+			int level0;
+
+			level0 = match_mpidr(mpidr, target_cpus, c_vcpu);
+			if (level0 == -1)
+				continue;
+
+			/* remove this matching VCPU from the mask */
+			target_cpus &= ~BIT(level0);
+		}
+
+		irq = vgic_get_irq(vcpu->kvm, c_vcpu, sgi);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:26 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:26 +0100
Subject: [PATCH v4 41/56] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_CTRL
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-99-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_CTRL group API
featuring KVM_DEV_ARM_VGIC_CTRL_INIT attribute. The vgic_init
function is not yet implemented though.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 05ff925..e153f12 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -23,6 +23,8 @@
 static int vgic_set_common_attr(struct kvm_device *dev,
 				struct kvm_device_attr *attr)
 {
+	int r;
+
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
@@ -55,6 +57,16 @@ static int vgic_set_common_attr(struct kvm_device *dev,
 
 		return ret;
 	}
+	case KVM_DEV_ARM_VGIC_GRP_CTRL: {
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			mutex_lock(&dev->kvm->lock);
+			r = vgic_init(dev->kvm);
+			mutex_unlock(&dev->kvm->lock);
+			return r;
+		}
+		break;
+	}
 	}
 
 	return -ENXIO;
@@ -131,6 +143,11 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
+	case KVM_DEV_ARM_VGIC_GRP_CTRL:
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			return 0;
+		}
 	}
 	return -ENXIO;
 }
@@ -166,6 +183,11 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
+	case KVM_DEV_ARM_VGIC_GRP_CTRL:
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			return 0;
+		}
 	}
 	return -ENXIO;
 }
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:33 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:33 +0100
Subject: [PATCH v4 48/56] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-106-git-send-email-andre.przywara@arm.com>

Using the VMCR accessors we provide access to GIC CPU interface state
to userland by wiring it up to the existing userland interface.
[Marc: move and make VMCR accessors static, streamline MMIO handlers]

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog v2 .. v3:
- total rework, moving into vgic-mmio-v2.c
- move vmcr accessor wrapper functions into this file
- use the register description table for CPU i/f registers as well
- add RAZ/WI handling for the active priority registers
- streamline MMIO handler functions

Changelog v3 .. v4:
- advertise CPU interface registers to userland
- specify accessor width
- replace call to extract_bytes() with a simple return

 virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 114 +++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.h            |   2 +
 3 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index c3ec453..237d753 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -274,7 +274,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		ret = -EINVAL;
+		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
 		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index a255122..a213936 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -204,6 +204,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_set_vmcr(vcpu, vmcr);
+	else
+		vgic_v3_set_vmcr(vcpu, vmcr);
+}
+
+static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_get_vmcr(vcpu, vmcr);
+	else
+		vgic_v3_get_vmcr(vcpu, vmcr);
+}
+
+#define GICC_ARCH_VERSION_V2	0x2
+
+/* These are for userland accesses only, there is no guest-facing emulation. */
+static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
+					   gpa_t addr, unsigned int len)
+{
+	struct vgic_vmcr vmcr;
+	u32 val;
+
+	vgic_get_vmcr(vcpu, &vmcr);
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		val = vmcr.ctlr;
+		break;
+	case GIC_CPU_PRIMASK:
+		val = vmcr.pmr;
+		break;
+	case GIC_CPU_BINPOINT:
+		val = vmcr.bpr;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		val = vmcr.abpr;
+		break;
+	case GIC_CPU_IDENT:
+		val = ((PRODUCT_ID_KVM << 20) |
+		       (GICC_ARCH_VERSION_V2 << 16) |
+		       IMPLEMENTER_ARM);
+		break;
+	default:
+		return 0;
+	}
+
+	return val;
+}
+
+static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
+				   gpa_t addr, unsigned int len,
+				   unsigned long val)
+{
+	struct vgic_vmcr vmcr;
+
+	vgic_get_vmcr(vcpu, &vmcr);
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		vmcr.ctlr = val;
+		break;
+	case GIC_CPU_PRIMASK:
+		vmcr.pmr = val;
+		break;
+	case GIC_CPU_BINPOINT:
+		vmcr.bpr = val;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		vmcr.abpr = val;
+		break;
+	}
+
+	vgic_set_vmcr(vcpu, &vmcr);
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
@@ -249,6 +327,27 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 };
 
+static const struct vgic_register_region vgic_v2_cpu_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_CTRL,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_PRIMASK,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ALIAS_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ACTIVEPRIO,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_IDENT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+};
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
 {
 	dev->regions = vgic_v2_dist_registers;
@@ -274,7 +373,9 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		return -ENXIO;		/* TODO: describe CPU i/f regs also */
+		regions = vgic_v2_cpu_registers;
+		nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers);
+		break;
 	default:
 		return -ENXIO;
 	}
@@ -322,6 +423,17 @@ static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
 	return ret;
 }
 
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_cpu_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
+
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val)
 {
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index d2c1fd5..de9dc71 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -47,6 +47,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val);
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:35 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:35 +0100
Subject: [PATCH v4 50/56] KVM: arm/arm64: vgic-new: vgic_init: implement
 vgic_create
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-108-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the vgic_creation function which is
called on CREATE_IRQCHIP VM IOCTL (v2 only) or KVM_CREATE_DEVICE

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v3 .. v4:
- fix comment

 include/kvm/vgic/vgic.h       |  1 +
 virt/kvm/arm/vgic/vgic-init.c | 84 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 393489f..0634d89 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -195,6 +195,7 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+int kvm_vgic_create(struct kvm *kvm, u32 type);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 4523beb..15d5428 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -22,6 +22,90 @@
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
+/* CREATION */
+
+/**
+ * kvm_vgic_create: triggered by the instantiation of the VGIC device by
+ * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only)
+ * or through the generic KVM_CREATE_DEVICE API ioctl.
+ * irqchip_in_kernel() tells you if this function succeeded or not.
+ */
+int kvm_vgic_create(struct kvm *kvm, u32 type)
+{
+	int i, vcpu_lock_idx = -1, ret;
+	struct kvm_vcpu *vcpu;
+
+	mutex_lock(&kvm->lock);
+
+	if (irqchip_in_kernel(kvm)) {
+		ret = -EEXIST;
+		goto out;
+	}
+
+	/*
+	 * This function is also called by the KVM_CREATE_IRQCHIP handler,
+	 * which had no chance yet to check the availability of the GICv2
+	 * emulation. So check this here again. KVM_CREATE_DEVICE does
+	 * the proper checks already.
+	 */
+	if (type == KVM_DEV_TYPE_ARM_VGIC_V2 &&
+		!kvm_vgic_global_state.can_emulate_gicv2) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/*
+	 * Any time a vcpu is run, vcpu_load is called which tries to grab the
+	 * vcpu->mutex.  By grabbing the vcpu->mutex of all VCPUs we ensure
+	 * that no other VCPUs are run while we create the vgic.
+	 */
+	ret = -EBUSY;
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		if (!mutex_trylock(&vcpu->mutex))
+			goto out_unlock;
+		vcpu_lock_idx = i;
+	}
+
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		if (vcpu->arch.has_run_once)
+			goto out_unlock;
+	}
+	ret = 0;
+
+	if (type == KVM_DEV_TYPE_ARM_VGIC_V2)
+		kvm->arch.max_vcpus = VGIC_V2_MAX_CPUS;
+	else
+		kvm->arch.max_vcpus = VGIC_V3_MAX_CPUS;
+
+	if (atomic_read(&kvm->online_vcpus) > kvm->arch.max_vcpus) {
+		ret = -E2BIG;
+		goto out_unlock;
+	}
+
+	kvm->arch.vgic.in_kernel = true;
+	kvm->arch.vgic.vgic_model = type;
+
+	/*
+	 * kvm_vgic_global_state.vctrl_base is set on vgic probe (kvm_arch_init)
+	 * it is stored in distributor struct for asm save/restore purpose
+	 */
+	kvm->arch.vgic.vctrl_base = kvm_vgic_global_state.vctrl_base;
+
+	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
+	kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
+	kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
+
+out_unlock:
+	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
+		vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
+		mutex_unlock(&vcpu->mutex);
+	}
+
+out:
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 03:14:14 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 11:14:14 +0100
Subject: [PATCH v4 00/56] KVM: arm/arm64: Rework virtual GIC emulation
In-Reply-To: <1463392481-26583-58-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-58-git-send-email-andre.przywara@arm.com>
Message-ID: <57399D76.4090209@arm.com>

On 16/05/16 10:53, Andre Przywara wrote:
> Hi,
> 
> a new update for the new VGIC series.
....

Oh dear,
apologies for the (double) spam!
Having the file name pattern _twice_ on the git send-email command line
really results in having everything send out twice ;-)
As those series are actually identical, please ignore/delete this one
(the mails sent out later).

Sorry for the inconvenience!
Andre.


From andre.przywara at arm.com  Mon May 16 02:53:29 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:29 +0100
Subject: [PATCH v4 41/56] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_CTRL
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-42-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_CTRL group API
featuring KVM_DEV_ARM_VGIC_CTRL_INIT attribute. The vgic_init
function is not yet implemented though.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 05ff925..e153f12 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -23,6 +23,8 @@
 static int vgic_set_common_attr(struct kvm_device *dev,
 				struct kvm_device_attr *attr)
 {
+	int r;
+
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
@@ -55,6 +57,16 @@ static int vgic_set_common_attr(struct kvm_device *dev,
 
 		return ret;
 	}
+	case KVM_DEV_ARM_VGIC_GRP_CTRL: {
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			mutex_lock(&dev->kvm->lock);
+			r = vgic_init(dev->kvm);
+			mutex_unlock(&dev->kvm->lock);
+			return r;
+		}
+		break;
+	}
 	}
 
 	return -ENXIO;
@@ -131,6 +143,11 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
+	case KVM_DEV_ARM_VGIC_GRP_CTRL:
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			return 0;
+		}
 	}
 	return -ENXIO;
 }
@@ -166,6 +183,11 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
+	case KVM_DEV_ARM_VGIC_GRP_CTRL:
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			return 0;
+		}
 	}
 	return -ENXIO;
 }
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:19 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:19 +0100
Subject: [PATCH v4 31/56] KVM: arm/arm64: vgic-new: Add SGIR register handler
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-32-git-send-email-andre.przywara@arm.com>

Triggering an IPI via this register is v2 specific, so the
implementation lives entirely in vgic-mmio-v2.c.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- silently return on illegal TargetListFilter value (=3)

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 52389ff..c884e9b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -64,6 +64,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
+				 gpa_t addr, unsigned int len,
+				 unsigned long val)
+{
+	int nr_vcpus = atomic_read(&source_vcpu->kvm->online_vcpus);
+	int intid = val & 0xf;
+	int targets = (val >> 16) & 0xff;
+	int mode = (val >> 24) & 0x03;
+	int c;
+	struct kvm_vcpu *vcpu;
+
+	switch (mode) {
+	case 0x0:		/* as specified by targets */
+		break;
+	case 0x1:
+		targets = (1U << nr_vcpus) - 1;			/* all, ... */
+		targets &= ~(1U << source_vcpu->vcpu_id);	/* but self */
+		break;
+	case 0x2:		/* this very vCPU only */
+		targets = (1U << source_vcpu->vcpu_id);
+		break;
+	case 0x3:		/* reserved */
+		return;
+	}
+
+	kvm_for_each_vcpu(c, vcpu, source_vcpu->kvm) {
+		struct vgic_irq *irq;
+
+		if (!(targets & (1U << c)))
+			continue;
+
+		irq = vgic_get_irq(source_vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+		irq->source |= 1U << source_vcpu->vcpu_id;
+
+		vgic_queue_irq_unlock(source_vcpu->kvm, irq);
+	}
+}
+
 static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
 					   gpa_t addr, unsigned int len)
 {
@@ -140,7 +181,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_config, vgic_mmio_write_config, 2,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:07 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:07 +0100
Subject: [PATCH v4 19/56] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-20-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Processing maintenance interrupts and accessing the list registers
are dependent on the host's GIC version.
Introduce vgic-v2.c to contain GICv2 specific functions.
Implement the GICv2 specific code for syncing the emulation state
into the VGIC registers.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog RFC..v1:
- remove explicit LR_STATE clearing on maintenance interrupt handling
- improve documentation for vgic_v2_populate_lr()
- remove WARN_ON on non-edge IRQs in maintenance interrupts
- simplify multi-CPU source SGI handling

Changelog v1 .. v2:
- inject the IRQ priority into the list register

Changelog v2 .. v3:
- cleanup diff containing rebase artifacts

Changelog v3 .. v4:
- remove ELRSR bit set during process_maintenance()

 include/linux/irqchip/arm-gic.h |   1 +
 virt/kvm/arm/vgic/vgic-v2.c     | 176 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c        |   6 ++
 virt/kvm/arm/vgic/vgic.h        |   6 ++
 4 files changed, 189 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-v2.c

diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 9c94026..be0d26f 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -76,6 +76,7 @@
 #define GICH_LR_VIRTUALID		(0x3ff << 0)
 #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
 #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
+#define GICH_LR_PRIORITY_SHIFT		23
 #define GICH_LR_STATE			(3 << 28)
 #define GICH_LR_PENDING_BIT		(1 << 28)
 #define GICH_LR_ACTIVE_BIT		(1 << 29)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
new file mode 100644
index 0000000..fb5e65c
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/irqchip/arm-gic.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+/*
+ * Call this function to convert a u64 value to an unsigned long * bitmask
+ * in a way that works on both 32-bit and 64-bit LE and BE platforms.
+ *
+ * Warning: Calling this function may modify *val.
+ */
+static unsigned long *u64_to_bitmask(u64 *val)
+{
+#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
+	*val = (*val >> 32) | (*val << 32);
+#endif
+	return (unsigned long *)val;
+}
+
+void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+
+	if (cpuif->vgic_misr & GICH_MISR_EOI) {
+		u64 eisr = cpuif->vgic_eisr;
+		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
+		int lr;
+
+		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
+			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
+
+			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
+
+			kvm_notify_acked_irq(vcpu->kvm, 0,
+					     intid - VGIC_NR_PRIVATE_IRQS);
+		}
+	}
+
+	/* check and disable underflow maintenance IRQ */
+	cpuif->vgic_hcr &= ~GICH_HCR_UIE;
+
+	/*
+	 * In the next iterations of the vcpu loop, if we sync the
+	 * vgic state after flushing it, but before entering the guest
+	 * (this happens for pending signals and vmid rollovers), then
+	 * make sure we don't pick up any old maintenance interrupts
+	 * here.
+	 */
+	cpuif->vgic_eisr = 0;
+}
+
+void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+
+	cpuif->vgic_hcr |= GICH_HCR_UIE;
+}
+
+/*
+ * transfer the content of the LRs back into the corresponding ap_list:
+ * - active bit is transferred as is
+ * - pending bit is
+ *   - transferred as is in case of edge sensitive IRQs
+ *   - set to the line-level (resample time) for level sensitive IRQs
+ */
+void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+	int lr;
+
+	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
+		u32 val = cpuif->vgic_lr[lr];
+		u32 intid = val & GICH_LR_VIRTUALID;
+		struct vgic_irq *irq;
+
+		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+
+		/* Always preserve the active bit */
+		irq->active = !!(val & GICH_LR_ACTIVE_BIT);
+
+		/* Edge is the only case where we preserve the pending bit */
+		if (irq->config == VGIC_CONFIG_EDGE &&
+		    (val & GICH_LR_PENDING_BIT)) {
+			irq->pending = true;
+
+			if (vgic_irq_is_sgi(intid)) {
+				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
+
+				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+				irq->source |= (1 << cpuid);
+			}
+		}
+
+		/* Clear soft pending state when level IRQs have been acked */
+		if (irq->config == VGIC_CONFIG_LEVEL &&
+		    !(val & GICH_LR_PENDING_BIT)) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+/*
+ * Populates the particular LR with the state of a given IRQ:
+ * - for an edge sensitive IRQ the pending state is cleared in struct vgic_irq
+ * - for a level sensitive IRQ the pending state value is unchanged;
+ *   it is dictated directly by the input level
+ *
+ * If @irq describes an SGI with multiple sources, we choose the
+ * lowest-numbered source VCPU and clear that bit in the source bitmap.
+ *
+ * The irq_lock must be held by the caller.
+ */
+void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
+{
+	u32 val = irq->intid;
+
+	if (irq->pending) {
+		val |= GICH_LR_PENDING_BIT;
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			irq->pending = false;
+
+		if (vgic_irq_is_sgi(irq->intid)) {
+			u32 src = ffs(irq->source);
+
+			BUG_ON(!src);
+			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
+			irq->source &= ~(1 << (src - 1));
+			if (irq->source)
+				irq->pending = true;
+		}
+	}
+
+	if (irq->active)
+		val |= GICH_LR_ACTIVE_BIT;
+
+	if (irq->hw) {
+		val |= GICH_LR_HW;
+		val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
+	} else {
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			val |= GICH_LR_EOI;
+	}
+
+	/* The GICv2 LR only holds five bits of priority. */
+	val |= (irq->priority >> 3) << GICH_LR_PRIORITY_SHIFT;
+
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = val;
+}
+
+void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 613fbd1..7d85398 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -399,10 +399,12 @@ retry:
 
 static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_process_maintenance(vcpu);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_fold_lr_state(vcpu);
 }
 
 /* Requires the irq_lock to be held. */
@@ -410,14 +412,18 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
 				    struct vgic_irq *irq, int lr)
 {
 	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+	vgic_v2_populate_lr(vcpu, irq, lr);
 }
 
 static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
+	vgic_v2_clear_lr(vcpu, lr);
 }
 
 static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_set_underflow(vcpu);
 }
 
 /* Requires the ap_list_lock to be held. */
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 29b96b9..0db490e 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -22,4 +22,10 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
 
+void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
+void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
+void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
+void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
+void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:46 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:46 +0100
Subject: [PATCH v4 01/56] KVM: arm/arm64: vgic: streamline
 vgic_update_irq_pending() interface
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-59-git-send-email-andre.przywara@arm.com>

We actually don't use the irq_phys_map parameter in
vgic_update_irq_pending(), so let's just remove it.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 virt/kvm/arm/vgic.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 60668a7..f6c6172 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1521,7 +1521,6 @@ static int vgic_validate_injection(struct kvm_vcpu *vcpu, int irq, int level)
 }
 
 static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
-				   struct irq_phys_map *map,
 				   unsigned int irq_num, bool level)
 {
 	struct vgic_dist *dist = &kvm->arch.vgic;
@@ -1660,7 +1659,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 	if (map)
 		return -EINVAL;
 
-	return vgic_update_irq_pending(kvm, cpuid, NULL, irq_num, level);
+	return vgic_update_irq_pending(kvm, cpuid, irq_num, level);
 }
 
 /**
@@ -1686,7 +1685,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 	if (ret)
 		return ret;
 
-	return vgic_update_irq_pending(kvm, cpuid, map, map->virt_irq, level);
+	return vgic_update_irq_pending(kvm, cpuid, map->virt_irq, level);
 }
 
 static irqreturn_t vgic_maintenance_handler(int irq, void *data)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:34 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:34 +0100
Subject: [PATCH v4 46/56] KVM: arm/arm64: vgic-new: Add userland access to
 VGIC dist registers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-47-git-send-email-andre.przywara@arm.com>

Userland may want to save and restore the state of the in-kernel VGIC,
so we provide the code which takes a userland request and translate
that into calls to our MMIO framework.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 50 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 78621283..c3ec453 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -238,7 +238,55 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 				 struct kvm_device_attr *attr,
 				 u32 *reg, bool is_write)
 {
-	return -ENXIO;
+	gpa_t addr;
+	int cpuid, ret, c;
+	struct kvm_vcpu *vcpu, *tmp_vcpu;
+
+	cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
+		 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
+	vcpu = kvm_get_vcpu(dev->kvm, cpuid);
+	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+	mutex_lock(&dev->kvm->lock);
+
+	ret = vgic_init(dev->kvm);
+	if (ret)
+		goto out;
+
+	if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Ensure that no other VCPU is running by checking the vcpu->cpu
+	 * field.  If no other VPCUs are running we can safely access the VGIC
+	 * state, because even if another VPU is run after this point, that
+	 * VCPU will not touch the vgic state, because it will block on
+	 * getting the vgic->lock in kvm_vgic_sync_hwstate().
+	 */
+	kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm) {
+		if (unlikely(tmp_vcpu->cpu != -1)) {
+			ret = -EBUSY;
+			goto out;
+		}
+	}
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		ret = -EINVAL;
+		break;
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+out:
+	mutex_unlock(&dev->kvm->lock);
+	return ret;
 }
 
 /* V2 ops */
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:32 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:32 +0100
Subject: [PATCH v4 44/56] KVM: arm/arm64: vgic-new: vgic_kvm_device: access to
 VGIC registers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-45-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
access VGIC registers.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v3 .. v4:
- check for proper alignment on userland GIC accesses

 virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 38 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |  1 +
 3 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index a709097..78621283 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -226,6 +226,21 @@ void kvm_register_vgic_device(unsigned long type)
 	}
 }
 
+/** vgic_attr_regs_access: allows user space to read/write VGIC registers
+ *
+ * @dev: kvm device handle
+ * @attr: kvm device attribute
+ * @reg: address the value is read or written
+ * @is_write: write flag
+ *
+ */
+static int vgic_attr_regs_access(struct kvm_device *dev,
+				 struct kvm_device_attr *attr,
+				 u32 *reg, bool is_write)
+{
+	return -ENXIO;
+}
+
 /* V2 ops */
 
 static int vgic_v2_set_attr(struct kvm_device *dev,
@@ -234,8 +249,23 @@ static int vgic_v2_set_attr(struct kvm_device *dev,
 	int ret;
 
 	ret = vgic_set_common_attr(dev, attr);
-	return ret;
+	if (ret != -ENXIO)
+		return ret;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 reg;
+
+		if (get_user(reg, uaddr))
+			return -EFAULT;
 
+		return vgic_attr_regs_access(dev, attr, &reg, true);
+	}
+	}
+
+	return -ENXIO;
 }
 
 static int vgic_v2_get_attr(struct kvm_device *dev,
@@ -244,7 +274,23 @@ static int vgic_v2_get_attr(struct kvm_device *dev,
 	int ret;
 
 	ret = vgic_get_common_attr(dev, attr);
-	return ret;
+	if (ret != -ENXIO)
+		return ret;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 reg = 0;
+
+		ret = vgic_attr_regs_access(dev, attr, &reg, false);
+		if (ret)
+			return ret;
+		return put_user(reg, uaddr);
+	}
+	}
+
+	return -ENXIO;
 }
 
 static int vgic_v2_has_attr(struct kvm_device *dev,
@@ -258,6 +304,9 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 			return 0;
 		}
 		break;
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		return vgic_v2_has_attr_regs(dev, attr);
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 3925d4c..7189690 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -258,3 +258,41 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
 
 	return SZ_4K;
 }
+
+int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+	const struct vgic_register_region *regions;
+	gpa_t addr;
+	int nr_regions, i, len;
+
+	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+		regions = vgic_v2_dist_registers;
+		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
+		break;
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		return -ENXIO;		/* TODO: describe CPU i/f regs also */
+	default:
+		return -ENXIO;
+	}
+
+	/* We only support aligned 32-bit accesses. */
+	if (addr & 3)
+		return -ENXIO;
+
+	for (i = 0; i < nr_regions; i++) {
+		if (regions[i].bits_per_irq)
+			len = (regions[i].bits_per_irq * nr_irqs) / 8;
+		else
+			len = regions[i].len;
+
+		if (regions[i].reg_offset <= addr &&
+		    regions[i].reg_offset + len > addr)
+			return 0;
+	}
+
+	return -ENXIO;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 6abc9a3..a264c5f 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -37,6 +37,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:35 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:35 +0100
Subject: [PATCH v4 47/56] KVM: arm/arm64: vgic-new: Add GICH_VMCR accessors
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-48-git-send-email-andre.przywara@arm.com>

Since the GIC CPU interface is always virtualized by the hardware,
we don't have CPU interface state information readily available in our
emulation if userland wants to save or restore it.
Fortunately the GIC hypervisor interface provides the VMCR register to
access the required virtual CPU interface bits.
Provide wrappers for GICv2 and GICv3 hosts to have access to this
register.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v2 .. v3:
- remove exported v2/v3 selector functions (as per Marc's patch)

Changelog v3 .. v4:
- move struct vgic_vmcr into the VGIC's private header file

 virt/kvm/arm/vgic/vgic-v2.c | 29 +++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c | 22 ++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h    | 21 +++++++++++++++++++++
 3 files changed, 72 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index fb5e65c..d943059 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -174,3 +174,32 @@ void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
 	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
 }
+
+void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr;
+
+	vmcr  = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK;
+	vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) &
+		GICH_VMCR_ALIAS_BINPOINT_MASK;
+	vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) &
+		GICH_VMCR_BINPOINT_MASK;
+	vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) &
+		GICH_VMCR_PRIMASK_MASK;
+
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = vmcr;
+}
+
+void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr;
+
+	vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >>
+			GICH_VMCR_CTRL_SHIFT;
+	vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >>
+			GICH_VMCR_ALIAS_BINPOINT_SHIFT;
+	vmcrp->bpr  = (vmcr & GICH_VMCR_BINPOINT_MASK) >>
+			GICH_VMCR_BINPOINT_SHIFT;
+	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
+			GICH_VMCR_PRIMASK_SHIFT;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index fb547da..8548297 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -160,3 +160,25 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
 	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
 }
+
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr;
+
+	vmcr  = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK;
+	vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
+	vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
+	vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
+
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
+}
+
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
+
+	vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT;
+	vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
+	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
+	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index f826026..d2c1fd5 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -27,6 +27,13 @@
 
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
+struct vgic_vmcr {
+	u32	ctlr;
+	u32	abpr;
+	u32	bpr;
+	u32	pmr;
+};
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
@@ -40,6 +47,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val);
+void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -49,6 +58,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -72,6 +83,16 @@ static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 }
 
+static inline
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+}
+
+static inline
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:48 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:48 +0100
Subject: [PATCH v4 03/56] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_map_is_active()
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-61-git-send-email-andre.przywara@arm.com>

For getting the active state of a mapped IRQ, we actually only need
the virtual IRQ number, not the pointer to the mapping entry.
Pass the virtual IRQ number from the arch timer to the VGIC directly.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- rewrap phys_active determination to fit in 80 characters

 include/kvm/arm_vgic.h    | 2 +-
 virt/kvm/arm/arch_timer.c | 6 ++----
 virt/kvm/arm/vgic.c       | 6 +++---
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index e22f015..9830232 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -348,7 +348,7 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 					   int virt_irq, int irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index a9c6c1c..37f82c1 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -274,10 +274,8 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* to ensure that hardware interrupts from the timer triggers a guest
 	* exit.
 	*/
-	if (timer->irq.level || kvm_vgic_map_is_active(vcpu, timer->map))
-		phys_active = true;
-	else
-		phys_active = false;
+	phys_active = timer->irq.level ||
+			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
 
 	/*
 	 * We want to avoid hitting the (re)distributor as much as
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 81c557c..2fd43a6 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1102,18 +1102,18 @@ static bool dist_active_irq(struct kvm_vcpu *vcpu)
 	return test_bit(vcpu->vcpu_id, dist->irq_active_on_cpu);
 }
 
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map)
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	int i;
 
 	for (i = 0; i < vcpu->arch.vgic_cpu.nr_lr; i++) {
 		struct vgic_lr vlr = vgic_get_lr(vcpu, i);
 
-		if (vlr.irq == map->virt_irq && vlr.state & LR_STATE_ACTIVE)
+		if (vlr.irq == virt_irq && vlr.state & LR_STATE_ACTIVE)
 			return true;
 	}
 
-	return vgic_irq_is_active(vcpu, map->virt_irq);
+	return vgic_irq_is_active(vcpu, virt_irq);
 }
 
 /*
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:49 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:49 +0100
Subject: [PATCH v4 04/56] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_unmap_phys_irq()
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-62-git-send-email-andre.przywara@arm.com>

kvm_vgic_unmap_phys_irq() only needs the virtual IRQ number, so let's
just pass that between the arch timer and the VGIC to get rid of
the irq_phys_map pointer.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 include/kvm/arm_vgic.h    |  2 +-
 virt/kvm/arm/arch_timer.c |  2 +-
 virt/kvm/arm/vgic.c       | 11 ++++-------
 3 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 9830232..c7bb184 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -347,7 +347,7 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 					   int virt_irq, int irq);
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 37f82c1..962b442 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -486,7 +486,7 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 
 	timer_disarm(timer);
 	if (timer->map)
-		kvm_vgic_unmap_phys_irq(vcpu, timer->map);
+		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
 }
 
 void kvm_timer_enable(struct kvm *kvm)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 2fd43a6..06abd59 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1812,25 +1812,22 @@ static void vgic_free_phys_irq_map_rcu(struct rcu_head *rcu)
 /**
  * kvm_vgic_unmap_phys_irq - Remove a virtual to physical IRQ mapping
  * @vcpu: The VCPU pointer
- * @map: The pointer to a mapping obtained through kvm_vgic_map_phys_irq
+ * @virt_irq: The virtual IRQ number to be unmapped
  *
  * Remove an existing mapping between virtual and physical interrupts.
  */
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map)
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct irq_phys_map_entry *entry;
 	struct list_head *root;
 
-	if (!map)
-		return -EINVAL;
-
-	root = vgic_get_irq_phys_map_list(vcpu, map->virt_irq);
+	root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 
 	spin_lock(&dist->irq_phys_map_lock);
 
 	list_for_each_entry(entry, root, entry) {
-		if (&entry->map == map) {
+		if (entry->map.virt_irq == virt_irq) {
 			list_del_rcu(&entry->entry);
 			call_rcu(&entry->rcu, vgic_free_phys_irq_map_rcu);
 			break;
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:18 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:18 +0100
Subject: [PATCH v4 30/56] KVM: arm/arm64: vgic-new: Add TARGET registers
 handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-31-git-send-email-andre.przywara@arm.com>

The target register handlers are v2 emulation specific, so their
implementation lives entirely in vgic-mmio-v2.c.
We copy the old VGIC behaviour of assigning an IRQ to the first VCPU
set in the target mask instead of making it possibly pending on
multiple VCPUs.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- remove runtime VCPU determination from this v2-only register
- fold in implementation of vgic_v2_irq_change_affinity()
- replace ffs() with __ffs()

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index bb7389e..52389ff 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -64,6 +64,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
+					   gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->targets << (i * 8);
+	}
+
+	return val;
+}
+
+static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
+				   gpa_t addr, unsigned int len,
+				   unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+
+	/* GICD_ITARGETSR[0-7] are read-only */
+	if (intid < VGIC_NR_PRIVATE_IRQS)
+		return;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
+		int target;
+
+		spin_lock(&irq->irq_lock);
+
+		irq->targets = (val >> (i * 8)) & 0xff;
+		target = irq->targets ? __ffs(irq->targets) : 0;
+		irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target);
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
@@ -93,7 +134,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		vgic_mmio_read_target, vgic_mmio_write_target, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
 		vgic_mmio_read_config, vgic_mmio_write_config, 2,
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:50 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:50 +0100
Subject: [PATCH v4 05/56] KVM: arm/arm64: Remove the IRQ field from struct
 irq_phys_map
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-63-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

The communication of a Linux IRQ number from outside the VGIC to the
vgic was a leftover from the day when the vgic code cared about how a
particular device injects virtual interrupts mapped to a physical
interrupt.

We can safely remove this notion, leaving all physical IRQ handling to
be done in the device driver (the arch timer in this case), which makes
room for a saner API for the new VGIC.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- update kerneldoc comments on kvm_vgic_map_phys_irq()

Changelog v2 .. v3:
- include <linux/irq.h>

 include/kvm/arm_vgic.h    |  3 +--
 virt/kvm/arm/arch_timer.c | 23 +++++++++++++++++++++--
 virt/kvm/arm/vgic.c       | 28 ++++++----------------------
 3 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index c7bb184..9ad7625 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -158,7 +158,6 @@ struct vgic_io_device {
 struct irq_phys_map {
 	u32			virt_irq;
 	u32			phys_irq;
-	u32			irq;
 };
 
 struct irq_phys_map_entry {
@@ -346,7 +345,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int irq);
+					   int virt_irq, int phys_irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 962b442..e45895a 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -20,6 +20,7 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <clocksource/arm_arch_timer.h>
 #include <asm/arch_timer.h>
@@ -300,7 +301,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	if (timer->active_cleared_last && !phys_active)
 		return;
 
-	ret = irq_set_irqchip_state(timer->map->irq,
+	ret = irq_set_irqchip_state(host_vtimer_irq,
 				    IRQCHIP_STATE_ACTIVE,
 				    phys_active);
 	WARN_ON(ret);
@@ -333,6 +334,9 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 	struct irq_phys_map *map;
+	struct irq_desc *desc;
+	struct irq_data *data;
+	int phys_irq;
 
 	/*
 	 * The vcpu timer irq number cannot be determined in
@@ -352,10 +356,25 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	kvm_timer_update_state(vcpu);
 
 	/*
+	 * Find the physical IRQ number corresponding to the host_vtimer_irq
+	 */
+	desc = irq_to_desc(host_vtimer_irq);
+	if (!desc) {
+		kvm_err("%s: no interrupt descriptor\n", __func__);
+		return -EINVAL;
+	}
+
+	data = irq_desc_get_irq_data(desc);
+	while (data->parent_data)
+		data = data->parent_data;
+
+	phys_irq = data->hwirq;
+
+	/*
 	 * Tell the VGIC that the virtual interrupt is tied to a
 	 * physical interrupt. We do that once per VCPU.
 	 */
-	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, host_vtimer_irq);
+	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
 	if (WARN_ON(IS_ERR(map)))
 		return PTR_ERR(map);
 
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 06abd59..a7e496a 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1711,38 +1711,24 @@ static struct list_head *vgic_get_irq_phys_map_list(struct kvm_vcpu *vcpu,
 /**
  * kvm_vgic_map_phys_irq - map a virtual IRQ to a physical IRQ
  * @vcpu: The VCPU pointer
- * @virt_irq: The virtual irq number
- * @irq: The Linux IRQ number
+ * @virt_irq: The virtual IRQ number for the guest
+ * @phys_irq: The hardware IRQ number of the host
  *
  * Establish a mapping between a guest visible irq (@virt_irq) and a
- * Linux irq (@irq). On injection, @virt_irq will be associated with
- * the physical interrupt represented by @irq. This mapping can be
+ * hardware irq (@phys_irq). On injection, @virt_irq will be associated with
+ * the physical interrupt represented by @phys_irq. This mapping can be
  * established multiple times as long as the parameters are the same.
  *
  * Returns a valid pointer on success, and an error pointer otherwise
  */
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int irq)
+					   int virt_irq, int phys_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct list_head *root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 	struct irq_phys_map *map;
 	struct irq_phys_map_entry *entry;
-	struct irq_desc *desc;
-	struct irq_data *data;
-	int phys_irq;
 
-	desc = irq_to_desc(irq);
-	if (!desc) {
-		kvm_err("%s: no interrupt descriptor\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
-
-	data = irq_desc_get_irq_data(desc);
-	while (data->parent_data)
-		data = data->parent_data;
-
-	phys_irq = data->hwirq;
 
 	/* Create a new mapping */
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
@@ -1755,8 +1741,7 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	map = vgic_irq_map_search(vcpu, virt_irq);
 	if (map) {
 		/* Make sure this mapping matches */
-		if (map->phys_irq != phys_irq	||
-		    map->irq      != irq)
+		if (map->phys_irq != phys_irq)
 			map = ERR_PTR(-EINVAL);
 
 		/* Found an existing, valid mapping */
@@ -1766,7 +1751,6 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	map           = &entry->map;
 	map->virt_irq = virt_irq;
 	map->phys_irq = phys_irq;
-	map->irq      = irq;
 
 	list_add_tail_rcu(&entry->entry, root);
 
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:54 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:54 +0100
Subject: [PATCH v4 09/56] KVM: arm/arm64: Fix MMIO emulation data handling
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-67-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

When the kernel was handling a guest MMIO read access internally, we
need to copy the emulation result into the run->mmio structure in order
for the kvm_handle_mmio_return() function to pick it up and inject the
	result back into the guest.

Currently the only user of kvm_io_bus for ARM is the VGIC, which did
this copying itself, so this was not causing issues so far.

But with the upcoming new vgic implementation we need this done
properly.

Update the kvm_handle_mmio_return description and cleanup the code to
only perform a single copying when needed.

Code and commit message inspired by Andre Przywara.

Reported-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm/kvm/mmio.c | 14 +++++++-------
 virt/kvm/arm/vgic.c |  7 -------
 2 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 0f6600f..0158e9e 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -87,11 +87,10 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len)
 
 /**
  * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation
+ *			     or in-kernel IO emulation
+ *
  * @vcpu: The VCPU pointer
  * @run:  The VCPU run struct containing the mmio data
- *
- * This should only be called after returning from userspace for MMIO load
- * emulation.
  */
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
@@ -206,18 +205,19 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 	run->mmio.is_write	= is_write;
 	run->mmio.phys_addr	= fault_ipa;
 	run->mmio.len		= len;
-	if (is_write)
-		memcpy(run->mmio.data, data_buf, len);
 
 	if (!ret) {
 		/* We handled the access successfully in the kernel. */
+		if (!is_write)
+			memcpy(run->mmio.data, data_buf, len);
 		vcpu->stat.mmio_exit_kernel++;
 		kvm_handle_mmio_return(vcpu, run);
 		return 1;
-	} else {
-		vcpu->stat.mmio_exit_user++;
 	}
 
+	if (is_write)
+		memcpy(run->mmio.data, data_buf, len);
+	vcpu->stat.mmio_exit_user++;
 	run->exit_reason	= KVM_EXIT_MMIO;
 	return 0;
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index f76bb64..c3bfbb9 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -819,7 +819,6 @@ static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct vgic_io_device *iodev = container_of(this,
 						    struct vgic_io_device, dev);
-	struct kvm_run *run = vcpu->run;
 	const struct vgic_io_range *range;
 	struct kvm_exit_mmio mmio;
 	bool updated_state;
@@ -848,12 +847,6 @@ static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
 		updated_state = false;
 	}
 	spin_unlock(&dist->lock);
-	run->mmio.is_write	= is_write;
-	run->mmio.len		= len;
-	run->mmio.phys_addr	= addr;
-	memcpy(run->mmio.data, val, len);
-
-	kvm_handle_mmio_return(vcpu, run);
 
 	if (updated_state)
 		vgic_kick_vcpus(vcpu->kvm);
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:53:56 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:53:56 +0100
Subject: [PATCH v4 11/56] KVM: arm/arm64: pmu: abstract access to number of
 SPIs
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-69-git-send-email-andre.przywara@arm.com>

Currently the PMU uses a member of the struct vgic_dist directly,
which not only breaks abstraction, but will fail with the new VGIC.
Abstract this access in the VGIC header file and refactor the validity
check in the PMU code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v3 .. v4:
- fix logic to allow PPIs again
- refactor IRQ validity check

 include/kvm/arm_vgic.h |  2 ++
 virt/kvm/arm/pmu.c     | 25 ++++++++++++++-----------
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 67a6637..ade7005 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -348,6 +348,8 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
 #define vgic_ready(k)		((k)->arch.vgic.ready)
+#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
+				 ((i) < (k)->arch.vgic.nr_irqs))
 
 int vgic_v2_probe(const struct gic_kvm_info *gic_kvm_info,
 		  const struct vgic_ops **ops,
diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
index 575c7aa..a027569 100644
--- a/virt/kvm/arm/pmu.c
+++ b/virt/kvm/arm/pmu.c
@@ -436,7 +436,14 @@ static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
-static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
+#define irq_is_ppi(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS)
+
+/*
+ * For one VM the interrupt type must be same for each vcpu.
+ * As a PPI, the interrupt number is the same for all vcpus,
+ * while as an SPI it must be a separate number per vcpu.
+ */
+static bool pmu_irq_is_valid(struct kvm *kvm, int irq)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
@@ -445,7 +452,7 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
 		if (!kvm_arm_pmu_irq_initialized(vcpu))
 			continue;
 
-		if (is_ppi) {
+		if (irq_is_ppi(irq)) {
 			if (vcpu->arch.pmu.irq_num != irq)
 				return false;
 		} else {
@@ -457,7 +464,6 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
 	return true;
 }
 
-
 int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 {
 	switch (attr->attr) {
@@ -471,14 +477,11 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 		if (get_user(irq, uaddr))
 			return -EFAULT;
 
-		/*
-		 * The PMU overflow interrupt could be a PPI or SPI, but for one
-		 * VM the interrupt type must be same for each vcpu. As a PPI,
-		 * the interrupt number is the same for all vcpus, while as an
-		 * SPI it must be a separate number per vcpu.
-		 */
-		if (irq < VGIC_NR_SGIS || irq >= vcpu->kvm->arch.vgic.nr_irqs ||
-		    !irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
+		/* The PMU overflow interrupt can be a PPI or a valid SPI. */
+		if (!(irq_is_ppi(irq) || vgic_valid_spi(vcpu->kvm, irq)))
+			return -EINVAL;
+
+		if (!pmu_irq_is_valid(vcpu->kvm, irq))
 			return -EINVAL;
 
 		if (kvm_arm_pmu_irq_initialized(vcpu))
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:32 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:32 +0100
Subject: [PATCH v4 47/56] KVM: arm/arm64: vgic-new: Add GICH_VMCR accessors
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-105-git-send-email-andre.przywara@arm.com>

Since the GIC CPU interface is always virtualized by the hardware,
we don't have CPU interface state information readily available in our
emulation if userland wants to save or restore it.
Fortunately the GIC hypervisor interface provides the VMCR register to
access the required virtual CPU interface bits.
Provide wrappers for GICv2 and GICv3 hosts to have access to this
register.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v2 .. v3:
- remove exported v2/v3 selector functions (as per Marc's patch)

Changelog v3 .. v4:
- move struct vgic_vmcr into the VGIC's private header file

 virt/kvm/arm/vgic/vgic-v2.c | 29 +++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c | 22 ++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h    | 21 +++++++++++++++++++++
 3 files changed, 72 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index fb5e65c..d943059 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -174,3 +174,32 @@ void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
 	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
 }
+
+void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr;
+
+	vmcr  = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK;
+	vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) &
+		GICH_VMCR_ALIAS_BINPOINT_MASK;
+	vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) &
+		GICH_VMCR_BINPOINT_MASK;
+	vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) &
+		GICH_VMCR_PRIMASK_MASK;
+
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = vmcr;
+}
+
+void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr;
+
+	vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >>
+			GICH_VMCR_CTRL_SHIFT;
+	vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >>
+			GICH_VMCR_ALIAS_BINPOINT_SHIFT;
+	vmcrp->bpr  = (vmcr & GICH_VMCR_BINPOINT_MASK) >>
+			GICH_VMCR_BINPOINT_SHIFT;
+	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
+			GICH_VMCR_PRIMASK_SHIFT;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index fb547da..8548297 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -160,3 +160,25 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
 	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
 }
+
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr;
+
+	vmcr  = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK;
+	vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
+	vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
+	vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
+
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
+}
+
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
+
+	vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT;
+	vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
+	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
+	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index f826026..d2c1fd5 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -27,6 +27,13 @@
 
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
+struct vgic_vmcr {
+	u32	ctlr;
+	u32	abpr;
+	u32	bpr;
+	u32	pmr;
+};
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
@@ -40,6 +47,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val);
+void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -49,6 +58,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -72,6 +83,16 @@ static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 }
 
+static inline
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+}
+
+static inline
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:24 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:24 +0100
Subject: [PATCH v4 39/56] KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM
 device ops registration
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-97-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch introduces the skeleton for the KVM device operations
associated to KVM_DEV_TYPE_ARM_VGIC_V2 and KVM_DEV_TYPE_ARM_VGIC_V3.

At that stage kvm_vgic_create is stubbed.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v1 .. v2:
- rename vgic_kvm_device.c to vgic-kvm-device.c

Changelog v2 .. v3:
- replace inclusion of vgic/vgic.h with arm_vgic.h
- add kvm_register_vgic_device() prototype to this patch

 virt/kvm/arm/vgic/vgic-kvm-device.c | 108 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |   2 +
 2 files changed, 110 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-kvm-device.c

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
new file mode 100644
index 0000000..ff332f3
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -0,0 +1,108 @@
+/*
+ * VGIC: KVM DEVICE API
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ * Author: Marc Zyngier <marc.zyngier at arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+
+/* common helpers */
+
+static int vgic_create(struct kvm_device *dev, u32 type)
+{
+	return kvm_vgic_create(dev->kvm, type);
+}
+
+static void vgic_destroy(struct kvm_device *dev)
+{
+	kfree(dev);
+}
+
+void kvm_register_vgic_device(unsigned long type)
+{
+	switch (type) {
+	case KVM_DEV_TYPE_ARM_VGIC_V2:
+		kvm_register_device_ops(&kvm_arm_vgic_v2_ops,
+					KVM_DEV_TYPE_ARM_VGIC_V2);
+		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case KVM_DEV_TYPE_ARM_VGIC_V3:
+		kvm_register_device_ops(&kvm_arm_vgic_v3_ops,
+					KVM_DEV_TYPE_ARM_VGIC_V3);
+		break;
+#endif
+	}
+}
+
+/* V2 ops */
+
+static int vgic_v2_set_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v2_get_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v2_has_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+struct kvm_device_ops kvm_arm_vgic_v2_ops = {
+	.name = "kvm-arm-vgic-v2",
+	.create = vgic_create,
+	.destroy = vgic_destroy,
+	.set_attr = vgic_v2_set_attr,
+	.get_attr = vgic_v2_get_attr,
+	.has_attr = vgic_v2_has_attr,
+};
+
+/* V3 ops */
+
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+
+static int vgic_v3_set_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v3_get_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v3_has_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+struct kvm_device_ops kvm_arm_vgic_v3_ops = {
+	.name = "kvm-arm-vgic-v3",
+	.create = vgic_create,
+	.destroy = vgic_destroy,
+	.set_attr = vgic_v3_set_attr,
+	.get_attr = vgic_v3_get_attr,
+	.has_attr = vgic_v3_has_attr,
+};
+
+#endif /* CONFIG_KVM_ARM_VGIC_V3 */
+
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 44c6a1b..77b0ab3 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -73,4 +73,6 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 }
 #endif
 
+void kvm_register_vgic_device(unsigned long type);
+
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:39 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:39 +0100
Subject: [PATCH v4 54/56] KVM: arm/arm64: vgic-new: Wire up irqfd injection
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-112-git-send-email-andre.przywara@arm.com>

Connect to the new VGIC to the irqfd framework, so that we can
inject IRQs.
GSI routing and MSI routing is not yet implemented.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-irqfd.c | 52 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-irqfd.c

diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
new file mode 100644
index 0000000..c675513
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/kvm.h>
+#include <linux/kvm_host.h>
+#include <trace/events/kvm.h>
+
+int kvm_irq_map_gsi(struct kvm *kvm,
+		    struct kvm_kernel_irq_routing_entry *entries,
+		    int gsi)
+{
+	return 0;
+}
+
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned int irqchip,
+			 unsigned int pin)
+{
+	return pin;
+}
+
+int kvm_set_irq(struct kvm *kvm, int irq_source_id,
+		u32 irq, int level, bool line_status)
+{
+	unsigned int spi = irq + VGIC_NR_PRIVATE_IRQS;
+
+	trace_kvm_set_irq(irq, level, irq_source_id);
+
+	BUG_ON(!vgic_initialized(kvm));
+
+	return kvm_vgic_inject_irq(kvm, 0, spi, level);
+}
+
+/* MSI not implemented yet */
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
+		struct kvm *kvm, int irq_source_id,
+		int level, bool line_status)
+{
+	return 0;
+}
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:27 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:27 +0100
Subject: [PATCH v4 42/56] KVM: arm/arm64: vgic-new: vgic_kvm_device: implement
 kvm_vgic_addr
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-100-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

kvm_vgic_addr is used by the userspace to set the base address of
the following register regions, as seen by the guest:
- distributor(v2 and v3),
- re-distributors (v3),
- CPU interface (v2).

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v3 .. v4:
- move overlap check to init time (cannot work with GICv3 here)
- refactor remaining address sanity checks

 include/kvm/vgic/vgic.h             |  2 +
 virt/kvm/arm/vgic/vgic-kvm-device.c | 86 +++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |  3 ++
 3 files changed, 91 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 00e3dca..3689b9b 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -194,6 +194,8 @@ struct vgic_cpu {
 	u64 live_lrs;
 };
 
+int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
 
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index e153f12..082829a 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -16,10 +16,96 @@
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
 #include <linux/uaccess.h>
+#include <asm/kvm_mmu.h>
 #include "vgic.h"
 
 /* common helpers */
 
+static int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
+			     phys_addr_t addr, phys_addr_t alignment)
+{
+	if (addr & ~KVM_PHYS_MASK)
+		return -E2BIG;
+
+	if (!IS_ALIGNED(addr, alignment))
+		return -EINVAL;
+
+	if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
+		return -EEXIST;
+
+	return 0;
+}
+
+/**
+ * kvm_vgic_addr - set or get vgic VM base addresses
+ * @kvm:   pointer to the vm struct
+ * @type:  the VGIC addr type, one of KVM_VGIC_V[23]_ADDR_TYPE_XXX
+ * @addr:  pointer to address value
+ * @write: if true set the address in the VM address space, if false read the
+ *          address
+ *
+ * Set or get the vgic base addresses for the distributor and the virtual CPU
+ * interface in the VM physical address space.  These addresses are properties
+ * of the emulated core/SoC and therefore user space initially knows this
+ * information.
+ * Check them for sanity (alignment, double assignment). We can't check for
+ * overlapping regions in case of a virtual GICv3 here, since we don't know
+ * the number of VCPUs yet, so we defer this check to map_resources().
+ */
+int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
+{
+	int r = 0;
+	struct vgic_dist *vgic = &kvm->arch.vgic;
+	int type_needed;
+	phys_addr_t *addr_ptr, alignment;
+
+	mutex_lock(&kvm->lock);
+	switch (type) {
+	case KVM_VGIC_V2_ADDR_TYPE_DIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+		addr_ptr = &vgic->vgic_dist_base;
+		alignment = SZ_4K;
+		break;
+	case KVM_VGIC_V2_ADDR_TYPE_CPU:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+		addr_ptr = &vgic->vgic_cpu_base;
+		alignment = SZ_4K;
+		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case KVM_VGIC_V3_ADDR_TYPE_DIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+		addr_ptr = &vgic->vgic_dist_base;
+		alignment = SZ_64K;
+		break;
+	case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+		addr_ptr = &vgic->vgic_redist_base;
+		alignment = SZ_64K;
+		break;
+#endif
+	default:
+		r = -ENODEV;
+		goto out;
+	}
+
+	if (vgic->vgic_model != type_needed) {
+		r = -ENODEV;
+		goto out;
+	}
+
+	if (write) {
+		r = vgic_check_ioaddr(kvm, addr_ptr, *addr, alignment);
+		if (!r)
+			*addr_ptr = *addr;
+	} else {
+		*addr = *addr_ptr;
+	}
+
+out:
+	mutex_unlock(&kvm->lock);
+	return r;
+}
+
 static int vgic_set_common_attr(struct kvm_device *dev,
 				struct kvm_device_attr *attr)
 {
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 77b0ab3..6abc9a3 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,9 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define VGIC_ADDR_UNDEF		(-1)
+#define IS_VGIC_ADDR_UNDEF(_x)  ((_x) == VGIC_ADDR_UNDEF)
+
 #define INTERRUPT_ID_BITS_SPIS	10
 #define VGIC_PRI_BITS		5
 
-- 
2.8.2



From sstabellini at kernel.org  Mon May 16 03:18:03 2016
From: sstabellini at kernel.org (Stefano Stabellini)
Date: Mon, 16 May 2016 11:18:03 +0100 (BST)
Subject: [PATCH v2] Xen: EFI: Parse DT parameters for Xen specific UEFI
In-Reply-To: <20160513220923.GA5178@codeblueprint.co.uk>
References: <1463055594-14980-1-git-send-email-zhaoshenglong@huawei.com>
 <20160513220923.GA5178@codeblueprint.co.uk>
Message-ID: <alpine.DEB.2.10.1605161117280.2494@sstabellini-ThinkPad-X260>

On Fri, 13 May 2016, Matt Fleming wrote:
> (Including more folks, quoting entire patch)
> 
> On Thu, 12 May, at 08:19:54PM, Shannon Zhao wrote:
> > From: Shannon Zhao <shannon.zhao at linaro.org>
> > 
> > The EFI DT parameters for bare metal are located under /chosen node,
> > while for Xen Dom0 they are located under /hyperviosr/uefi node. These
> > parameters under /chosen and /hyperviosr/uefi are not expected to appear
> > at the same time.
> > Parse these EFI parameters and initialize EFI like the way for bare
> > metal except the runtime services because the runtime services for Xen
> > Dom0 are available through hypercalls and they are always enabled. So it
> > sets the EFI_RUNTIME_SERVICES flag if it finds /hyperviosr/uefi node and
> > bails out in arm_enable_runtime_services() when EFI_RUNTIME_SERVICES
> > flag is set already.
> > 
> > CC: Matt Fleming <matt at codeblueprint.co.uk>
> > Signed-off-by: Shannon Zhao <shannon.zhao at linaro.org>
> > ---
> > v2: rebase it on top of EFI and Xen next branch, add some comments to
> > explain the codes. 
> > ---
> >  arch/arm/xen/enlighten.c           | 22 +++++++++++
> >  drivers/firmware/efi/arm-runtime.c |  5 +++
> >  drivers/firmware/efi/efi.c         | 81 ++++++++++++++++++++++++++++++--------
> >  3 files changed, 92 insertions(+), 16 deletions(-)
>  
> This looks good to me. Thanks for all the work Shannon.
> 
> Stefan, OK, let's figure out how to deal with this.
> 
> What I've done is merge xen/linux-next into the 'efi/xen-arm' topic
> branch and applied this patch here,
> 
>   https://git.kernel.org/cgit/linux/kernel/git/mfleming/efi.git/log/?h=efi/arm-xen
> 
> Yes, the merge includes some Xen patches that are not actually needed
> for any of the EFI patches, but Linus has complained about picking
> random commits of a tree to merge. At least this way this is all the
> Xen linux-next material.
> 
> If you're OK with this, and assuming no one else has any preferred
> methods, I'll send out a pull request to tip over the weekend.

I am OK with it. Thanks!


> > diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
> > index 13e3e9f..d4f36eb 100644
> > --- a/arch/arm/xen/enlighten.c
> > +++ b/arch/arm/xen/enlighten.c
> > @@ -15,7 +15,9 @@
> >  #include <asm/paravirt.h>
> >  #include <asm/xen/hypervisor.h>
> >  #include <asm/xen/hypercall.h>
> > +#include <asm/xen/xen-ops.h>
> >  #include <asm/system_misc.h>
> > +#include <asm/efi.h>
> >  #include <linux/interrupt.h>
> >  #include <linux/irqreturn.h>
> >  #include <linux/module.h>
> > @@ -261,6 +263,19 @@ static int __init fdt_find_hyper_node(unsigned long node, const char *uname,
> >  	    !strncmp(hyper_node.prefix, s, strlen(hyper_node.prefix)))
> >  		hyper_node.version = s + strlen(hyper_node.prefix);
> >  
> > +	/*
> > +	 * Check if Xen supports EFI by checking whether there is the
> > +	 * "/hypervisor/uefi" node in DT. If so, runtime services are available
> > +	 * through proxy functions (e.g. in case of Xen dom0 EFI implementation
> > +	 * they call special hypercall which executes relevant EFI functions)
> > +	 * and that is why they are always enabled.
> > +	 */
> > +	if (IS_ENABLED(CONFIG_XEN_EFI)) {
> > +		if ((of_get_flat_dt_subnode_by_name(node, "uefi") > 0) &&
> > +		    !efi_runtime_disabled())
> > +			set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
> > +	}
> > +
> >  	return 0;
> >  }
> >  
> > @@ -352,6 +367,13 @@ static int __init xen_guest_init(void)
> >  		return -ENODEV;
> >  	}
> >  
> > +	/*
> > +	 * The fdt parsing codes have set EFI_RUNTIME_SERVICES if Xen EFI
> > +	 * parameters are found. Force enable runtime services.
> > +	 */
> > +	if (efi_enabled(EFI_RUNTIME_SERVICES))
> > +		xen_efi_runtime_setup();
> > +
> >  	shared_info_page = (struct shared_info *)get_zeroed_page(GFP_KERNEL);
> >  
> >  	if (!shared_info_page) {
> > diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
> > index 17ccf0a..c394b81 100644
> > --- a/drivers/firmware/efi/arm-runtime.c
> > +++ b/drivers/firmware/efi/arm-runtime.c
> > @@ -107,6 +107,11 @@ static int __init arm_enable_runtime_services(void)
> >  		return 0;
> >  	}
> >  
> > +	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
> > +		pr_info("EFI runtime services access via paravirt.\n");
> > +		return 0;
> > +	}
> > +
> >  	pr_info("Remapping and enabling EFI services.\n");
> >  
> >  	mapsize = efi.memmap.map_end - efi.memmap.map;
> > diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> > index 05509f3..1c6f9dd 100644
> > --- a/drivers/firmware/efi/efi.c
> > +++ b/drivers/firmware/efi/efi.c
> > @@ -472,12 +472,14 @@ device_initcall(efi_load_efivars);
> >  		FIELD_SIZEOF(struct efi_fdt_params, field) \
> >  	}
> >  
> > -static __initdata struct {
> > +struct params {
> >  	const char name[32];
> >  	const char propname[32];
> >  	int offset;
> >  	int size;
> > -} dt_params[] = {
> > +};
> > +
> > +static __initdata struct params fdt_params[] = {
> >  	UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
> >  	UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
> >  	UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
> > @@ -485,44 +487,91 @@ static __initdata struct {
> >  	UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
> >  };
> >  
> > +static __initdata struct params xen_fdt_params[] = {
> > +	UEFI_PARAM("System Table", "xen,uefi-system-table", system_table),
> > +	UEFI_PARAM("MemMap Address", "xen,uefi-mmap-start", mmap),
> > +	UEFI_PARAM("MemMap Size", "xen,uefi-mmap-size", mmap_size),
> > +	UEFI_PARAM("MemMap Desc. Size", "xen,uefi-mmap-desc-size", desc_size),
> > +	UEFI_PARAM("MemMap Desc. Version", "xen,uefi-mmap-desc-ver", desc_ver)
> > +};
> > +
> > +#define EFI_FDT_PARAMS_SIZE	ARRAY_SIZE(fdt_params)
> > +
> > +static __initdata struct {
> > +	const char *uname;
> > +	const char *subnode;
> > +	struct params *params;
> > +} dt_params[] = {
> > +	{ "hypervisor", "uefi", xen_fdt_params },
> > +	{ "chosen", NULL, fdt_params },
> > +};
> > +
> >  struct param_info {
> >  	int found;
> >  	void *params;
> > +	const char *missing;
> >  };
> >  
> > -static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
> > -				       int depth, void *data)
> > +static int __init __find_uefi_params(unsigned long node,
> > +				     struct param_info *info,
> > +				     struct params *params)
> >  {
> > -	struct param_info *info = data;
> >  	const void *prop;
> >  	void *dest;
> >  	u64 val;
> >  	int i, len;
> >  
> > -	if (depth != 1 || strcmp(uname, "chosen") != 0)
> > -		return 0;
> > -
> > -	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
> > -		prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
> > -		if (!prop)
> > +	for (i = 0; i < EFI_FDT_PARAMS_SIZE; i++) {
> > +		prop = of_get_flat_dt_prop(node, params[i].propname, &len);
> > +		if (!prop) {
> > +			info->missing = params[i].name;
> >  			return 0;
> > -		dest = info->params + dt_params[i].offset;
> > +		}
> > +
> > +		dest = info->params + params[i].offset;
> >  		info->found++;
> >  
> >  		val = of_read_number(prop, len / sizeof(u32));
> >  
> > -		if (dt_params[i].size == sizeof(u32))
> > +		if (params[i].size == sizeof(u32))
> >  			*(u32 *)dest = val;
> >  		else
> >  			*(u64 *)dest = val;
> >  
> >  		if (efi_enabled(EFI_DBG))
> > -			pr_info("  %s: 0x%0*llx\n", dt_params[i].name,
> > -				dt_params[i].size * 2, val);
> > +			pr_info("  %s: 0x%0*llx\n", params[i].name,
> > +				params[i].size * 2, val);
> >  	}
> > +
> >  	return 1;
> >  }
> >  
> > +static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
> > +				       int depth, void *data)
> > +{
> > +	struct param_info *info = data;
> > +	int i;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
> > +		const char *subnode = dt_params[i].subnode;
> > +
> > +		if (depth != 1 || strcmp(uname, dt_params[i].uname) != 0) {
> > +			info->missing = dt_params[i].params[0].name;
> > +			continue;
> > +		}
> > +
> > +		if (subnode) {
> > +			node = of_get_flat_dt_subnode_by_name(node, subnode);
> > +			if (node < 0)
> > +				return 0;
> > +		}
> > +
> > +		return __find_uefi_params(node, info, dt_params[i].params);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  int __init efi_get_fdt_params(struct efi_fdt_params *params)
> >  {
> >  	struct param_info info;
> > @@ -538,7 +587,7 @@ int __init efi_get_fdt_params(struct efi_fdt_params *params)
> >  		pr_info("UEFI not found.\n");
> >  	else if (!ret)
> >  		pr_err("Can't find '%s' in device tree!\n",
> > -		       dt_params[info.found].name);
> > +		       info.missing);
> >  
> >  	return ret;
> >  }
> > -- 
> > 2.0.4
> > 
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-efi" in
> > the body of a message to majordomo at vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


From yt.shen at mediatek.com  Mon May 16 03:27:02 2016
From: yt.shen at mediatek.com (YT Shen)
Date: Mon, 16 May 2016 18:27:02 +0800
Subject: [RFC 1/3] dt-bindings: drm/mediatek: Add display binding for
 Mediatek SoC MT2701
In-Reply-To: <1463065184.17225.2.camel@mtksdaap41>
References: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
 <1463053795-55455-2-git-send-email-yt.shen@mediatek.com>
 <1463065184.17225.2.camel@mtksdaap41>
Message-ID: <1463394422.28394.5.camel@mtksdaap41>

Hi Yingjoe,

On Thu, 2016-05-12 at 22:59 +0800, Yingjoe Chen wrote:
> On Thu, 2016-05-12 at 19:49 +0800, yt.shen at mediatek.com wrote:
> > From: YT Shen <yt.shen at mediatek.com>
> > 
> > Add device tree binding documentation for the display subsystem in
> > Mediatek SoC MT2701
> > 
> > Signed-off-by: YT Shen <yt.shen at mediatek.com>
> > ---
> >  .../bindings/display/mediatek/mediatek,disp.txt    |    1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
> > index db6e77e..53b3cc3 100644
> > --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
> > +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
> > @@ -40,6 +40,7 @@ Required properties (all function blocks):
> >  	"mediatek,<chip>-dpi"        - DPI controller, see mediatek,dpi.txt
> >  	"mediatek,<chip>-disp-mutex" - display mutex
> >  	"mediatek,<chip>-disp-od"    - overdrive
> > +	"mediatek,<chip>-disp-bls"   - backlight
> >  - reg: Physical base address and length of the function block register space
> >  - interrupts: The interrupt signal from the function block (required, except for
> >    merge and split function blocks).
> 
> 
> Hi,
> 
> This one is in conflict with "Support Mediatek Soc MT2701 disp pwm"
> series Weiqing sent last week, which add disp-bls support to display pwm
> driver.
> 
> Joe.C

Thanks, I will remove this part and update it in the next version.

Regards,
yt.shen




From andre.przywara at arm.com  Mon May 16 02:54:41 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:41 +0100
Subject: [PATCH v4 56/56] KVM: arm/arm64: vgic-new: enable build
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-114-git-send-email-andre.przywara@arm.com>

Now that the new VGIC implementation has reached feature parity with
the old one, add the new files to the build system and add a Kconfig
option to switch between the two versions.
We set the default to the new version to get maximum test coverage,
in case people experience problems they can switch back to the old
behaviour if needed.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adjust the changed filenames in the Makefiles
- add vgic-mmio-v2.c and vgic-mmio-v3.c to the Makefiles

 arch/arm/kvm/Kconfig          |  7 +++++++
 arch/arm/kvm/Makefile         | 11 +++++++++++
 arch/arm64/kvm/Kconfig        |  7 +++++++
 arch/arm64/kvm/Makefile       | 12 ++++++++++++
 virt/kvm/arm/hyp/vgic-v2-sr.c |  5 +++++
 5 files changed, 42 insertions(+)

diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 95a0005..02abfff 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -46,6 +46,13 @@ config KVM_ARM_HOST
 	---help---
 	  Provides host support for ARM processors.
 
+config KVM_NEW_VGIC
+	bool "New VGIC implementation"
+	depends on KVM
+	default y
+	---help---
+	  uses the new VGIC implementation
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index eb1bf43..a596b58 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -21,7 +21,18 @@ obj-$(CONFIG_KVM_ARM_HOST) += hyp/
 obj-y += kvm-arm.o init.o interrupts.o
 obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
+
+ifeq ($(CONFIG_KVM_NEW_VGIC),y)
+obj-y += $(KVM)/arm/vgic/vgic.o
+obj-y += $(KVM)/arm/vgic/vgic-init.o
+obj-y += $(KVM)/arm/vgic/vgic-irqfd.o
+obj-y += $(KVM)/arm/vgic/vgic-v2.o
+obj-y += $(KVM)/arm/vgic/vgic-mmio.o
+obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
+obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
+else
 obj-y += $(KVM)/arm/vgic.o
 obj-y += $(KVM)/arm/vgic-v2.o
 obj-y += $(KVM)/arm/vgic-v2-emul.o
+endif
 obj-y += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index aa2e34e..c4f26ef 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -54,6 +54,13 @@ config KVM_ARM_PMU
 	  Adds support for a virtual Performance Monitoring Unit (PMU) in
 	  virtual machines.
 
+config KVM_NEW_VGIC
+	bool "New VGIC implementation"
+	depends on KVM
+	default y
+        ---help---
+          uses the new VGIC implementation
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 122cff4..a7a958c 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -20,10 +20,22 @@ kvm-$(CONFIG_KVM_ARM_HOST) += emulate.o inject_fault.o regmap.o
 kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
 kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
 
+ifeq ($(CONFIG_KVM_NEW_VGIC),y)
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-irqfd.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
+else
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2-emul.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3-emul.o
+endif
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
 kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index caac41f..a3f12b3 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -21,7 +21,12 @@
 
 #include <asm/kvm_hyp.h>
 
+#ifdef CONFIG_KVM_NEW_VGIC
+extern struct vgic_global kvm_vgic_global_state;
+#define vgic_v2_params kvm_vgic_global_state
+#else
 extern struct vgic_params vgic_v2_params;
+#endif
 
 static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 					    void __iomem *base)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:28 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:28 +0100
Subject: [PATCH v4 43/56] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_ADDR
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-101-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_ADDR group which
enables to set the base address of GIC regions as seen by the guest.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 38 +++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 082829a..a709097 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -112,6 +112,17 @@ static int vgic_set_common_attr(struct kvm_device *dev,
 	int r;
 
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 addr;
+		unsigned long type = (unsigned long)attr->attr;
+
+		if (copy_from_user(&addr, uaddr, sizeof(addr)))
+			return -EFAULT;
+
+		r = kvm_vgic_addr(dev->kvm, type, &addr, true);
+		return (r == -ENODEV) ? -ENXIO : r;
+	}
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
 		u32 val;
@@ -164,6 +175,19 @@ static int vgic_get_common_attr(struct kvm_device *dev,
 	int r = -ENXIO;
 
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 addr;
+		unsigned long type = (unsigned long)attr->attr;
+
+		r = kvm_vgic_addr(dev->kvm, type, &addr, false);
+		if (r)
+			return (r == -ENODEV) ? -ENXIO : r;
+
+		if (copy_to_user(uaddr, &addr, sizeof(addr)))
+			return -EFAULT;
+		break;
+	}
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
 
@@ -227,6 +251,13 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR:
+		switch (attr->attr) {
+		case KVM_VGIC_V2_ADDR_TYPE_DIST:
+		case KVM_VGIC_V2_ADDR_TYPE_CPU:
+			return 0;
+		}
+		break;
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
@@ -267,6 +298,13 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR:
+		switch (attr->attr) {
+		case KVM_VGIC_V3_ADDR_TYPE_DIST:
+		case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+			return 0;
+		}
+		break;
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:19 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:19 +0100
Subject: [PATCH v4 34/56] KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR,
 TYPER handlers
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-92-git-send-email-andre.przywara@arm.com>

As in the GICv2 emulation we handle those three registers in one
function.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- kick VCPUs if distributor gets enabled

Changelog v1 .. v2:
- rewrite write handler to use switch statement

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 48 +++++++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.h         |  1 +
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 31f1a13..f11ef46 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -22,6 +22,52 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 value = 0;
+
+	switch (addr & 0x0c) {
+	case GICD_CTLR:
+		if (vcpu->kvm->arch.vgic.enabled)
+			value |= GICD_CTLR_ENABLE_SS_G1;
+		value |= GICD_CTLR_ARE_NS | GICD_CTLR_DS;
+		break;
+	case GICD_TYPER:
+		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+		value = (value >> 5) - 1;
+		value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19;
+		break;
+	case GICD_IIDR:
+		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+		break;
+	default:
+		return 0;
+	}
+
+	return value;
+}
+
+static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+	bool was_enabled = dist->enabled;
+
+	switch (addr & 0x0c) {
+	case GICD_CTLR:
+		dist->enabled = val & GICD_CTLR_ENABLE_SS_G1;
+
+		if (!was_enabled && dist->enabled)
+			vgic_kick_vcpus(vcpu->kvm);
+		break;
+	case GICD_TYPER:
+	case GICD_IIDR:
+		return;
+	}
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -48,7 +94,7 @@
 
 static const struct vgic_register_region vgic_v3_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc, 16,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 6742b11..44c6a1b 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,7 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define INTERRUPT_ID_BITS_SPIS	10
 #define VGIC_PRI_BITS		5
 
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
-- 
2.8.2



From andre.przywara at arm.com  Mon May 16 02:54:20 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Mon, 16 May 2016 10:54:20 +0100
Subject: [PATCH v4 35/56] KVM: arm/arm64: vgic-new: Add GICv3 redistributor
 IIDR and TYPER handler
In-Reply-To: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463392481-26583-93-git-send-email-andre.przywara@arm.com>

The redistributor TYPER tells the OS about the associated MPIDR,
also the LAST bit is crucial to determine the number of redistributors.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- add extract_bytes() as static (moved from an earlier patch)
- replace one extract_bytes() access with a simple return

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index f11ef46..28de16a 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -22,6 +22,13 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+/* extract @num bytes at @offset bytes offset in data */
+static unsigned long extract_bytes(unsigned long data, unsigned int offset,
+				   unsigned int num)
+{
+	return (data >> (offset * 8)) & GENMASK_ULL(num * 8 - 1, 0);
+}
+
 static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
 					    gpa_t addr, unsigned int len)
 {
@@ -68,6 +75,27 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
+					      gpa_t addr, unsigned int len)
+{
+	unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
+	int target_vcpu_id = vcpu->vcpu_id;
+	u64 value;
+
+	value = (mpidr & GENMASK(23, 0)) << 32;
+	value |= ((target_vcpu_id & 0xffff) << 8);
+	if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
+		value |= GICR_TYPER_LAST;
+
+	return extract_bytes(value, addr & 7, len);
+}
+
+static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
+					     gpa_t addr, unsigned int len)
+{
+	return (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -142,10 +170,10 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		vgic_mmio_read_v3r_iidr, vgic_mmio_write_wi, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, 8,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
-- 
2.8.2



From wens at csie.org  Mon May 16 04:13:17 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 16 May 2016 19:13:17 +0800
Subject: [PATCH 2/3] mfd: axp20x: Extend axp22x_volatile_ranges
In-Reply-To: <1463248289-16456-2-git-send-email-hdegoede@redhat.com>
References: <1463248289-16456-1-git-send-email-hdegoede@redhat.com>
 <1463248289-16456-2-git-send-email-hdegoede@redhat.com>
Message-ID: <CAGb2v65nuj4Uh9jNSS4wk8CWkgN6iiuGR2vz4Kat=8QT68EE6Q@mail.gmail.com>

On Sun, May 15, 2016 at 1:51 AM, Hans de Goede <hdegoede at redhat.com> wrote:
> The axp22x pmic has a bunch of volatile registers besides the interrupt
> ones, extend axp22x_volatile_ranges with these.
>
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>

Acked-by: Chen-Yu Tsai <wens at csie.org>


From wens at csie.org  Mon May 16 04:14:15 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 16 May 2016 19:14:15 +0800
Subject: [PATCH 3/3] mfd: axp20x: Add axp20x-usb-power-supply for axp22x
 pmics
In-Reply-To: <1463248289-16456-3-git-send-email-hdegoede@redhat.com>
References: <1463248289-16456-1-git-send-email-hdegoede@redhat.com>
 <1463248289-16456-3-git-send-email-hdegoede@redhat.com>
Message-ID: <CAGb2v65cxMBgO7W2bHx1S+LbffHdh7VVaQA+sB4gws9Rt_Qj8g@mail.gmail.com>

Hi,

On Sun, May 15, 2016 at 1:51 AM, Hans de Goede <hdegoede at redhat.com> wrote:
> Add axp20x-usb-power-supply for axp22x pmics.
>
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> ---
>  drivers/mfd/axp20x.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> index ca04361..d62209d 100644
> --- a/drivers/mfd/axp20x.c
> +++ b/drivers/mfd/axp20x.c
> @@ -160,6 +160,11 @@ static struct resource axp20x_usb_power_supply_resources[] = {
>         DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"),
>  };
>
> +static struct resource axp22x_usb_power_supply_resources[] = {
> +       DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
> +       DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
> +};
> +
>  static struct resource axp22x_pek_resources[] = {
>         {
>                 .name   = "PEK_DBR",
> @@ -527,6 +532,11 @@ static struct mfd_cell axp22x_cells[] = {
>                 .resources              = axp22x_pek_resources,
>         }, {
>                 .name                   = "axp20x-regulator",
> +       }, {
> +               .name           = "axp20x-usb-power-supply",
> +               .of_compatible  = "x-powers,axp202-usb-power-supply",

As mentioned in the power supply patch, could you use a new compatible for the
axp22x variant? Thanks.

ChenYu

> +               .num_resources  = ARRAY_SIZE(axp22x_usb_power_supply_resources),
> +               .resources      = axp22x_usb_power_supply_resources,
>         },
>  };
>
> --
> 2.7.4
>


From mark.rutland at arm.com  Mon May 16 04:33:34 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 16 May 2016 12:33:34 +0100
Subject: [RFC PATCH] soc: Amlogic: Add secure monitor driver
In-Reply-To: <1463335845-23534-1-git-send-email-carlo@caione.org>
References: <1463335845-23534-1-git-send-email-carlo@caione.org>
Message-ID: <20160516113333.GG656@leverpostej>

On Sun, May 15, 2016 at 08:10:45PM +0200, Carlo Caione wrote:
> From: Carlo Caione <carlo at endlessm.com>
> 
> Introduce a driver to provide calls into secure monitor mode.
> 
> In the Amlogic SoCs these calls are used for multiple reasons: access to
> NVMEM, reboot, set USB boot, enable JTAG, etc...
> 
> Signed-off-by: Carlo Caione <carlo at endlessm.com>
> ---
>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi |   4 +
>  drivers/soc/Kconfig                         |   1 +
>  drivers/soc/Makefile                        |   1 +
>  drivers/soc/amlogic/Kconfig                 |   8 ++
>  drivers/soc/amlogic/Makefile                |   1 +
>  drivers/soc/amlogic/meson_sm.c              | 141 ++++++++++++++++++++++++++++
>  include/linux/soc/amlogic/meson_sm.h        |  57 +++++++++++
>  7 files changed, 213 insertions(+)

The binding is missing documentation.

Is there any documentation of the actual interface?

Are there any restrictions on how it's used? It looks like calls are
only expected to happen from the boot CPU, per the code below.

There are no users in this patch. Are there any example uses (i.e.
specific code rather than the high-level examples above)?

>  create mode 100644 drivers/soc/amlogic/Kconfig
>  create mode 100644 drivers/soc/amlogic/Makefile
>  create mode 100644 drivers/soc/amlogic/meson_sm.c
>  create mode 100644 include/linux/soc/amlogic/meson_sm.h
> 
> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> index 76b3b6d..e4017c3 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> @@ -98,6 +98,10 @@
>  		method = "smc";
>  	};
>  
> +	sm {
> +		compatible = "amlogic,meson-sm";
> +	};

We should have more specific strings, at least in addition to this.

> +
>  	timer {
>  		compatible = "arm,armv8-timer";
>  		interrupts = <GIC_PPI 13
> diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> index cb58ef0..637af69 100644
> --- a/drivers/soc/Kconfig
> +++ b/drivers/soc/Kconfig
> @@ -1,5 +1,6 @@
>  menu "SOC (System On Chip) specific Drivers"
>  
> +source "drivers/soc/amlogic/Kconfig"
>  source "drivers/soc/bcm/Kconfig"
>  source "drivers/soc/brcmstb/Kconfig"
>  source "drivers/soc/fsl/qe/Kconfig"
> diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
> index 5ade713..2eb6fd5 100644
> --- a/drivers/soc/Makefile
> +++ b/drivers/soc/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_ARCH_DOVE)		+= dove/
>  obj-$(CONFIG_MACH_DOVE)		+= dove/
>  obj-y				+= fsl/
>  obj-$(CONFIG_ARCH_MEDIATEK)	+= mediatek/
> +obj-$(CONFIG_ARCH_MESON)	+= amlogic/
>  obj-$(CONFIG_ARCH_QCOM)		+= qcom/
>  obj-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip/
>  obj-$(CONFIG_SOC_SAMSUNG)	+= samsung/
> diff --git a/drivers/soc/amlogic/Kconfig b/drivers/soc/amlogic/Kconfig
> new file mode 100644
> index 0000000..fff11a3
> --- /dev/null
> +++ b/drivers/soc/amlogic/Kconfig
> @@ -0,0 +1,8 @@
> +#
> +# Amlogic Secure Monitor driver
> +#
> +config MESON_SM
> +	bool
> +	default ARCH_MESON
> +	help
> +	  Say y here to enable the Amlogic secure monitor driver
> diff --git a/drivers/soc/amlogic/Makefile b/drivers/soc/amlogic/Makefile
> new file mode 100644
> index 0000000..9ab3884
> --- /dev/null
> +++ b/drivers/soc/amlogic/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_MESON_SM) +=	meson_sm.o
> diff --git a/drivers/soc/amlogic/meson_sm.c b/drivers/soc/amlogic/meson_sm.c
> new file mode 100644
> index 0000000..e6f9c4f
> --- /dev/null
> +++ b/drivers/soc/amlogic/meson_sm.c
> @@ -0,0 +1,141 @@
> +/*
> + * Amlogic Secure Monitor driver
> + *
> + * Copyright (C) 2016 Endless Mobile, Inc.
> + * Author: Carlo Caione <carlo at endlessm.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * 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 <stdarg.h>
> +#include <asm/cacheflush.h>
> +#include <asm/compiler.h>
> +#include <linux/arm-smccc.h>
> +#include <linux/io.h>
> +#include <linux/ioport.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/smp.h>
> +
> +#include <linux/soc/amlogic/meson_sm.h>
> +
> +#define SM_MEM_SIZE			0x1000
> +
> +/*
> + * To read from / write to the secure monitor we use two bounce buffers. The
> + * physical addresses of the two buffers are obtained by querying the secure
> + * monitor itself.
> + */
> +
> +static u32 sm_phy_in_base;
> +static u32 sm_phy_out_base;
> +
> +static void __iomem *sm_sharemem_in_base;
> +static void __iomem *sm_sharemem_out_base;
> +
> +struct meson_sm_data {
> +	unsigned int cmd;
> +	unsigned int arg0;
> +	unsigned int arg1;
> +	unsigned int arg2;
> +	unsigned int arg3;
> +	unsigned int arg4;
> +	unsigned int ret;
> +};

Please be explicit and use u32 rather than unsigned int.

It looks like all the calls you care about are SMC32 SiP calls, per the
IDs in the header.

> +
> +static void __meson_sm_call(void *info)
> +{
> +	struct meson_sm_data *data = info;
> +	struct arm_smccc_res res;
> +
> +	arm_smccc_smc(data->cmd,
> +		      data->arg0, data->arg1, data->arg2,
> +		      data->arg3, data->arg4, 0, 0, &res);
> +	data->ret = res.a0;
> +}
> +
> +unsigned int meson_sm_call(unsigned int cmd, unsigned int arg0,
> +			   unsigned int arg1, unsigned int arg2,
> +			   unsigned int arg3, unsigned int arg4)
> +{
> +	struct meson_sm_data data;
> +
> +	data.cmd = cmd;
> +	data.arg0 = arg0;
> +	data.arg1 = arg1;
> +	data.arg2 = arg2;
> +	data.arg3 = arg3;
> +	data.arg4 = arg4;
> +	data.ret = 0;
> +
> +	smp_call_function_single(0, __meson_sm_call, &data, 1);

Why must this occur on a particular CPU?

With kexec and so on logical CPU 0 is not necessarily the CPU that the
FW brought out of reset.

Can the core with the secure OS be powered down, or is that prevented
with the usual PSCI machinery (e.g. MIGRATE, MIGRATE_INFO_TYPE,
MIGRATE_INFO_UP_CPU)

I would recommend that any CPU restriction were described explicitly in
the DT, or detected dynamically based on the MIGRATE_INFO_UP_CPU value.

> +
> +	return data.ret;
> +}
> +
> +unsigned int meson_sm_call_read(void *buffer, unsigned int cmd,
> +				unsigned int arg0, unsigned int arg1,
> +				unsigned int arg2, unsigned int arg3,
> +				unsigned int arg4)
> +{
> +	unsigned int size;
> +
> +	size = meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
> +
> +	if (size != 0)

Is the size guaranteed to never be > SM_MEM_SIZE? Can we sanity-check
that?

The call can't return an error code?

> +		memcpy(buffer, sm_sharemem_out_base, size);

Is the buffer completely opaque to this layer?

Are there any endianness concerns, for example?

> +
> +	return size;
> +}
> +
> +unsigned int meson_sm_call_write(void *buffer, unsigned int size,
> +				 unsigned int cmd, unsigned int arg0,
> +				 unsigned int arg1, unsigned int arg2,
> +				 unsigned int arg3, unsigned int arg4)
> +{
> +	memcpy(sm_sharemem_in_base, buffer, size);
> +
> +	return meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
> +}
> +
> +static int meson_sm_probe(struct platform_device *pdev)
> +{
> +	sm_phy_in_base = meson_sm_call(SM_GET_SHARE_MEM_INPUT_BASE, 0, 0, 0, 0, 0);
> +
> +	sm_sharemem_in_base = ioremap_cache(sm_phy_in_base, SM_MEM_SIZE);
> +	if (!sm_sharemem_in_base)
> +		return -EINVAL;

Are the attributes used for ioremap_cache guaranteed to match and not
cause a mismatched alias against the firmware's mapping?

Which precise memory attributes does the secure firmware use for the
shared memory?

> +
> +	sm_phy_out_base = meson_sm_call(SM_GET_SHARE_MEM_OUTPUT_BASE, 0, 0, 0, 0, 0);
> +
> +	sm_sharemem_out_base = ioremap_cache(sm_phy_out_base, SM_MEM_SIZE);
> +	if (!sm_sharemem_out_base)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id meson_sm_ids[] = {
> +	{ .compatible = "amlogic,meson-sm" },
> +	{ /* sentinel */},
> +};
> +MODULE_DEVICE_TABLE(of, meson_sm_ids);
> +
> +static struct platform_driver meson_sm_platform_driver = {
> +	.probe	= meson_sm_probe,
> +	.driver	= {
> +		.name		= "secmon",
> +		.of_match_table	= meson_sm_ids,
> +	},
> +};
> +module_platform_driver(meson_sm_platform_driver);
> +
> +MODULE_AUTHOR("Carlo Caione <carlo at endlessm.com>");
> +MODULE_DESCRIPTION("Amlogic secure monitor driver");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/soc/amlogic/meson_sm.h b/include/linux/soc/amlogic/meson_sm.h
> new file mode 100644
> index 0000000..68b943f
> --- /dev/null
> +++ b/include/linux/soc/amlogic/meson_sm.h
> @@ -0,0 +1,57 @@
> +/*
> + * Copyright (C) 2016 Endless Mobile, Inc.
> + * Author: Carlo Caione <carlo at endlessm.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef _MESON_SM_H_
> +#define _MESON_SM_H_
> +
> +#define SM_GET_SHARE_MEM_INPUT_BASE		0x82000020
> +#define SM_GET_SHARE_MEM_OUTPUT_BASE		0x82000021
> +#define SM_GET_REBOOT_REASON			0x82000022
> +#define SM_GET_SHARE_STORAGE_IN_BASE		0x82000023
> +#define SM_GET_SHARE_STORAGE_OUT_BASE		0x82000024
> +#define SM_GET_SHARE_STORAGE_BLOCK_BASE		0x82000025
> +#define SM_GET_SHARE_STORAGE_MESSAGE_BASE	0x82000026
> +#define SM_GET_SHARE_STORAGE_BLOCK_SIZE		0x82000027
> +#define SM_EFUSE_READ				0x82000030
> +#define SM_EFUSE_WRITE				0x82000031
> +#define SM_EFUSE_WRITE_PATTERN			0x82000032
> +#define SM_EFUSE_USER_MAX			0x82000033
> +#define SM_JTAG_ON				0x82000040
> +#define SM_JTAG_OFF				0x82000041
> +#define SM_SET_USB_BOOT_FUNC			0x82000043
> +#define SM_SECURITY_KEY_QUERY			0x82000060
> +#define SM_SECURITY_KEY_READ			0x82000061
> +#define SM_SECURITY_KEY_WRITE			0x82000062
> +#define SM_SECURITY_KEY_TELL			0x82000063
> +#define SM_SECURITY_KEY_VERIFY			0x82000064
> +#define SM_SECURITY_KEY_STATUS			0x82000065
> +#define SM_SECURITY_KEY_NOTIFY			0x82000066
> +#define SM_SECURITY_KEY_LIST			0x82000067
> +#define SM_SECURITY_KEY_REMOVE			0x82000068
> +#define SM_DEBUG_EFUSE_WRITE_PATTERN		0x820000F0
> +#define SM_DEBUG_EFUSE_READ_PATTERN		0x820000F1
> +#define SM_AML_DATA_PROCESS			0x820000FF

Is there any documentation for these functions?

> +#define SM_PSCI_SYS_REBOOT			0x84000009

The existing PCSI code should be the only caller of this. This should
not be used here.

Thanks,
Mark.


From yt.shen at mediatek.com  Mon May 16 04:39:41 2016
From: yt.shen at mediatek.com (YT Shen)
Date: Mon, 16 May 2016 19:39:41 +0800
Subject: [RFC 2/3] drm/mediatek: add support for Mediatek SoC MT2701
In-Reply-To: <1463111956.12239.15.camel@mtksdaap41>
References: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
 <1463053795-55455-3-git-send-email-yt.shen@mediatek.com>
 <1463111956.12239.15.camel@mtksdaap41>
Message-ID: <1463398781.13038.4.camel@mtksdaap41>

Hi CK,
On Fri, 2016-05-13 at 11:59 +0800, CK Hu wrote:
> Hi, YT:
> 
> On Thu, 2016-05-12 at 19:49 +0800, yt.shen at mediatek.com wrote:
> > From: YT Shen <yt.shen at mediatek.com>
> > 
> > This patch add support for the Mediatek MT2701 DISP subsystem.
> > There is only one OVL engine in MT2701, and we have shadow
> > register support here.
> > 
> > Signed-off-by: YT Shen <yt.shen at mediatek.com>
> > ---
> 
> > @@ -385,12 +422,16 @@ static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc,
> >  		mtk_crtc->event = state->base.event;
> >  		state->base.event = NULL;
> >  	}
> > +
> > +	if (priv->data->shadow_register)
> > +		mtk_disp_mutex_acquire(mtk_crtc->mutex);
> >  }
> >  
> > @@ -409,6 +450,11 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
> >  	}
> >  	if (pending_planes)
> >  		mtk_crtc->pending_planes = true;
> > +
> > +	if (priv->data->shadow_register) {
> > +		mtk_crtc_ddp_config(crtc);
> > +		mtk_disp_mutex_release(mtk_crtc->mutex);
> > +	}
> >  }
> >  
> 
> I think it's better to call mtk_disp_mutex_acquire() and
> mtk_disp_mutex_release() as near as possible to prevent mutex locked for
> a long time. All HW register access of this atomic setting is in
> mtk_crtc_ddp_config(), so it's better to move mtk_disp_mutex_acquire()
> just before mtk_crtc_ddp_config().
> 
> Regards,
> CK
I'll do this in the next version.  Thanks for the review.

Regards,
yt.shen



From jonathanh at nvidia.com  Mon May 16 05:08:38 2016
From: jonathanh at nvidia.com (Jon Hunter)
Date: Mon, 16 May 2016 13:08:38 +0100
Subject: Tegra baseline test results for v4.6-rc7
Message-ID: <5739B846.8040106@nvidia.com>

Here are some basic Tegra test results for Linux v4.6-rc7.
Logs and other details at:

    https://nvtb.github.io//linux/test_v4.6-rc7/20160508150104/


Test summary
------------

Build: zImage:
    Pass: ( 2/ 2): multi_v7_defconfig, tegra_defconfig

Build: Image:
    Pass: ( 1/ 1): defconfig

Boot to userspace: defconfig:
    Pass: ( 3/ 3): qemu-vexpress64, tegra132-norrin,
		   tegra210-p2371-0000

Boot to userspace: multi_v7_defconfig:
    Pass: ( 4/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra20-trimslice, tegra30-beaver

Boot to userspace: tegra_defconfig:
    Pass: ( 4/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra20-trimslice, tegra30-beaver

PM: System suspend: multi_v7_defconfig:
    FAIL: ( 1/ 4): tegra30-beaver
    Pass: ( 3/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra20-trimslice

PM: System suspend: tegra_defconfig:
    Pass: ( 4/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra20-trimslice, tegra30-beaver


vmlinux object size
(delta in bytes from test_v4.6-rc6 (04974df8049fc4240d22759a91e035082ccd18b4)):
   text     data      bss    total  kernel
      0        0        0        0  defconfig
   +332        0        0     +332  multi_v7_defconfig
   +464        0        0     +464  tegra_defconfig


Boot-time memory difference
(delta in bytes from test_v4.6-rc6 (04974df8049fc4240d22759a91e035082ccd18b4))
    avail    rsrvd     high    freed                board              kconfig                  dtb
        .        .        .        .      qemu-vexpress64            defconfig           __internal
        .        .        .        . tegra114-dalmore-a04   multi_v7_defconfig     tegra114-dalmore
        .        .        .        . tegra114-dalmore-a04      tegra_defconfig     tegra114-dalmore
        .        .        .        .  tegra124-jetson-tk1   multi_v7_defconfig  tegra124-jetson-tk1
        .        .        .        .  tegra124-jetson-tk1      tegra_defconfig  tegra124-jetson-tk1
        .        .        .        .      tegra132-norrin            defconfig      tegra132-norrin
        .        .        .        .    tegra20-trimslice   multi_v7_defconfig    tegra20-trimslice
        .        .        .        .    tegra20-trimslice      tegra_defconfig    tegra20-trimslice
        .        .        .        .  tegra210-p2371-0000            defconfig  tegra210-p2371-0000
        .        .        .        .       tegra30-beaver   multi_v7_defconfig       tegra30-beaver
        .        .        .        .       tegra30-beaver      tegra_defconfig       tegra30-beaver

--
nvpublic


From jonathanh at nvidia.com  Mon May 16 05:13:20 2016
From: jonathanh at nvidia.com (Jon Hunter)
Date: Mon, 16 May 2016 13:13:20 +0100
Subject: Tegra baseline test results for v4.6-rc7
In-Reply-To: <5739B846.8040106@nvidia.com>
References: <5739B846.8040106@nvidia.com>
Message-ID: <5739B960.2010202@nvidia.com>


On 16/05/16 13:08, Jon Hunter wrote:
> Here are some basic Tegra test results for Linux v4.6-rc7.
> Logs and other details at:
> 
>     https://nvtb.github.io//linux/test_v4.6-rc7/20160508150104/
> 
> 
> Test summary
> ------------
> 
> Build: zImage:
>     Pass: ( 2/ 2): multi_v7_defconfig, tegra_defconfig
> 
> Build: Image:
>     Pass: ( 1/ 1): defconfig
> 
> Boot to userspace: defconfig:
>     Pass: ( 3/ 3): qemu-vexpress64, tegra132-norrin,
> 		   tegra210-p2371-0000
> 
> Boot to userspace: multi_v7_defconfig:
>     Pass: ( 4/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
> 		   tegra20-trimslice, tegra30-beaver
> 
> Boot to userspace: tegra_defconfig:
>     Pass: ( 4/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
> 		   tegra20-trimslice, tegra30-beaver
> 
> PM: System suspend: multi_v7_defconfig:
>     FAIL: ( 1/ 4): tegra30-beaver

This failure does not appear to be specific to v4.6. An SD card has been
inserted into this board and since then suspend fails sometimes.
Unfortunately, this appears to be an issue that has been around for a
long time (many kernel releases) and only seems to impact certain SD
cards. We are currently investigating this issue.

Jon

--
nvpublic


From jonathanh at nvidia.com  Mon May 16 05:15:48 2016
From: jonathanh at nvidia.com (Jon Hunter)
Date: Mon, 16 May 2016 13:15:48 +0100
Subject: Tegra baseline test results for v4.6
Message-ID: <5739B9F4.1060400@nvidia.com>

Here are some basic Tegra test results for Linux v4.6.
Logs and other details at:

    https://nvtb.github.io//linux/test_v4.6/20160515160102/


Test summary
------------

Build: zImage:
    Pass: ( 2/ 2): multi_v7_defconfig, tegra_defconfig

Build: Image:
    Pass: ( 1/ 1): defconfig

Boot to userspace: defconfig:
    Pass: ( 3/ 3): qemu-vexpress64, tegra132-norrin,
		   tegra210-p2371-0000

Boot to userspace: multi_v7_defconfig:
    Pass: ( 4/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra20-trimslice, tegra30-beaver

Boot to userspace: tegra_defconfig:
    Pass: ( 4/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra20-trimslice, tegra30-beaver

PM: System suspend: multi_v7_defconfig:
    FAIL: ( 1/ 4): tegra30-beaver
    Pass: ( 3/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra20-trimslice

PM: System suspend: tegra_defconfig:
    Pass: ( 4/ 4): tegra114-dalmore-a04, tegra124-jetson-tk1,
		   tegra20-trimslice, tegra30-beaver


vmlinux object size
(delta in bytes from test_v4.6-rc7 (44549e8f5eea4e0a41b487b63e616cb089922b99)):
   text     data      bss    total  kernel
  +4103    -4096        0       +7  defconfig
  +2247        0        0    +2247  multi_v7_defconfig
  +1287        0        0    +1287  tegra_defconfig


Boot-time memory difference
(delta in bytes from test_v4.6-rc7 (44549e8f5eea4e0a41b487b63e616cb089922b99))
    avail    rsrvd     high    freed                board              kconfig                  dtb
        .        .        .        .      qemu-vexpress64            defconfig           __internal
        .        .        .        . tegra114-dalmore-a04   multi_v7_defconfig     tegra114-dalmore
        .        .        .        . tegra114-dalmore-a04      tegra_defconfig     tegra114-dalmore
        .        .        .        .  tegra124-jetson-tk1   multi_v7_defconfig  tegra124-jetson-tk1
        .        .        .        .  tegra124-jetson-tk1      tegra_defconfig  tegra124-jetson-tk1
        .        .        .        .      tegra132-norrin            defconfig      tegra132-norrin
        .        .        .        .    tegra20-trimslice   multi_v7_defconfig    tegra20-trimslice
        .        .        .        .    tegra20-trimslice      tegra_defconfig    tegra20-trimslice
        .        .        .        .  tegra210-p2371-0000            defconfig  tegra210-p2371-0000
        .        .        .        .       tegra30-beaver   multi_v7_defconfig       tegra30-beaver
        .        .        .        .       tegra30-beaver      tegra_defconfig       tegra30-beaver

--
nvpublic


From maxime.ripard at free-electrons.com  Mon May 16 05:47:11 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:11 +0200
Subject: [PATCH 11/20] drm/sun4i: Convert to connector register helpers
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-12-git-send-email-maxime.ripard@free-electrons.com>

Now that connector register helpers have been created, switch to them.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c | 31 ++-----------------------------
 1 file changed, 2 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index af62b24c39b1..257d2b4f3645 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -24,34 +24,6 @@
 #include "sun4i_layer.h"
 #include "sun4i_tcon.h"
 
-static int sun4i_drv_connector_plug_all(struct drm_device *drm)
-{
-	struct drm_connector *connector, *failed;
-	int ret;
-
-	mutex_lock(&drm->mode_config.mutex);
-	list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
-		ret = drm_connector_register(connector);
-		if (ret) {
-			failed = connector;
-			goto err;
-		}
-	}
-	mutex_unlock(&drm->mode_config.mutex);
-	return 0;
-
-err:
-	list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
-		if (failed == connector)
-			break;
-
-		drm_connector_unregister(connector);
-	}
-	mutex_unlock(&drm->mode_config.mutex);
-
-	return ret;
-}
-
 static int sun4i_drv_enable_vblank(struct drm_device *drm, unsigned int pipe)
 {
 	struct sun4i_drv *drv = drm->dev_private;
@@ -206,7 +178,7 @@ static int sun4i_drv_bind(struct device *dev)
 	if (ret)
 		goto free_drm;
 
-	ret = sun4i_drv_connector_plug_all(drm);
+	ret = drm_connector_register_all(drm);
 	if (ret)
 		goto unregister_drm;
 
@@ -223,6 +195,7 @@ static void sun4i_drv_unbind(struct device *dev)
 {
 	struct drm_device *drm = dev_get_drvdata(dev);
 
+	drm_connector_unregister_all(drm);
 	drm_dev_unregister(drm);
 	drm_kms_helper_poll_fini(drm);
 	sun4i_framebuffer_free(drm);
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:10 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:10 +0200
Subject: [PATCH 10/20] drm/sun4i: remove simplefb at probe
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-11-git-send-email-maxime.ripard@free-electrons.com>

If simplefb was setup by our bootloader and enabled in the DT, we will have
a first framebuffer loaded in our system.

However, as soon as our DRM driver will load, it will reset the controller,
initialise it and, if the framebuffer emulation is enabled, register a
second framebuffer device.

This is obviously pretty bad, since the first framebuffer will be some kind
of a black hole, with memory still reserved that we can write to safely,
but not displayed anywhere.

Make sure we remove that framebuffer when we probe so we don't end up in
that situation.

Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")
Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 76e922bb60e5..af62b24c39b1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -125,6 +125,22 @@ static struct drm_driver sun4i_drv_driver = {
 	.disable_vblank		= sun4i_drv_disable_vblank,
 };
 
+static void sun4i_remove_framebuffers(void)
+{
+	struct apertures_struct *ap;
+
+	ap = alloc_apertures(1);
+	if (!ap)
+		return;
+
+	/* The framebuffer can be located anywhere in RAM */
+	ap->ranges[0].base = 0;
+	ap->ranges[0].size = ~0;
+
+	remove_conflicting_framebuffers(ap, "sun4i-drm-fb", false);
+	kfree(ap);
+}
+
 static int sun4i_drv_bind(struct device *dev)
 {
 	struct drm_device *drm;
@@ -172,6 +188,9 @@ static int sun4i_drv_bind(struct device *dev)
 	}
 	drm->irq_enabled = true;
 
+	/* Remove early framebuffers (ie. simplefb) */
+	sun4i_remove_framebuffers();
+
 	/* Create our framebuffer */
 	drv->fbdev = sun4i_framebuffer_init(drm);
 	if (IS_ERR(drv->fbdev)) {
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:00 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:00 +0200
Subject: [PATCH 00/20] drm: Add Support for Passive RGB to VGA bridges
Message-ID: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>

Hi,

This serie is about adding support for the RGB to VGA bridge found in
the A13-Olinuxino and the CHIP VGA adapter.

Both these boards rely on an entirely passive bridge made out of
resitor ladders that do not require any initialisation. The only thing
needed is to get the timings from the screen if available (and if not,
fall back on XGA standards), set up the display pipeline to output on
the RGB bus with the proper timings, and you're done.

This serie also fixes a bunch of bugs uncovered when trying to
increase the resolution, and hence the pixel clock, of our
pipeline. It also fixes a few bugs in the DRM driver itself that went
unnoticed before.

Let me know what you think,
Maxime

Maxime Ripard (20):
  clk: fixed-factor: Pass clk rates change to the parent
  clk: multiplier: Prevent the multiplier from under / over flowing
  clk: sunxi: tcon-ch1: Do not return a negative error in get_parent
  clk: sunxi: display: Add per-clock flags
  drm/sun4i: request exact rates to our parents
  drm/sun4i: allow dclk to modify its parent rate
  drm/sun4i: rgb: Validate the clock rate
  drm/sun4i: rgb: panel is an error pointer
  drm/sun4i: defer only if we didn't find our panel
  drm/sun4i: remove simplefb at probe
  drm/sun4i: Convert to connector register helpers
  drm/sun4i: Add bridge support
  drm/bridge: Add RGB to VGA bridge support
  ARM: sun5i: a13: Add LCD pins
  ARM: sun5i: Move display blocks to A13
  ARM: sun5i: a13-olinuxino: Enable VGA bridge
  ARM: multi_v7: Enable sun4i DRM driver
  ARM: multi_v7: enable VGA bridge
  ARM: sunxi: Enable sun4i DRM driver
  ARM: sunxi: Enable VGA bridge

 .../bindings/display/bridge/dumb-vga.txt           |  40 +++++
 arch/arm/boot/dts/sun5i-a13-olinuxino.dts          |  34 ++++
 arch/arm/boot/dts/sun5i-a13.dtsi                   | 122 ++++++++++++++
 arch/arm/boot/dts/sun5i-r8.dtsi                    | 120 +------------
 arch/arm/configs/multi_v7_defconfig                |   2 +
 arch/arm/configs/sunxi_defconfig                   |   3 +
 drivers/clk/clk-fixed-factor.c                     |   3 +-
 drivers/clk/clk-multiplier.c                       |  20 ++-
 drivers/clk/sunxi/clk-sun4i-display.c              |   5 +-
 drivers/clk/sunxi/clk-sun4i-tcon-ch1.c             |   3 -
 drivers/gpu/drm/bridge/Kconfig                     |   6 +
 drivers/gpu/drm/bridge/Makefile                    |   1 +
 drivers/gpu/drm/bridge/dumb-vga.c                  | 186 +++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun4i_dotclock.c             |  31 +++-
 drivers/gpu/drm/sun4i/sun4i_drv.c                  |  54 +++---
 drivers/gpu/drm/sun4i/sun4i_rgb.c                  |  70 ++++++--
 drivers/gpu/drm/sun4i/sun4i_tcon.c                 |  59 +++++--
 drivers/gpu/drm/sun4i/sun4i_tcon.h                 |   1 +
 18 files changed, 578 insertions(+), 182 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
 create mode 100644 drivers/gpu/drm/bridge/dumb-vga.c

-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:12 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:12 +0200
Subject: [PATCH 12/20] drm/sun4i: Add bridge support
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-13-git-send-email-maxime.ripard@free-electrons.com>

Our RGB bus can be either connected to a bridge or a panel. While the panel
support was already there, the bridge was not.

Fix that.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c  |  4 +--
 drivers/gpu/drm/sun4i/sun4i_rgb.c  | 56 +++++++++++++++++++++++++++-----------
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 48 ++++++++++++++++++++++++++++----
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  1 +
 4 files changed, 86 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 257d2b4f3645..1f9e00db747d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -268,8 +268,8 @@ static int sun4i_drv_add_endpoints(struct device *dev,
 		}
 
 		/*
-		 * If the node is our TCON, the first port is used for our
-		 * panel, and will not be part of the
+		 * If the node is our TCON, the first port is used for
+		 * panel or bridges, and will not be part of the
 		 * component framework.
 		 */
 		if (sun4i_drv_node_is_tcon(node)) {
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index b46d2c15dc95..c3c611b08269 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -161,7 +161,12 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
 
 	DRM_DEBUG_DRIVER("Enabling RGB output\n");
 
-	drm_panel_enable(tcon->panel);
+	if (!IS_ERR(tcon->panel))
+		drm_panel_enable(tcon->panel);
+
+	if (!IS_ERR(tcon->bridge))
+		drm_bridge_enable(tcon->bridge);
+
 	sun4i_tcon_channel_enable(tcon, 0);
 }
 
@@ -174,7 +179,12 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
 	DRM_DEBUG_DRIVER("Disabling RGB output\n");
 
 	sun4i_tcon_channel_disable(tcon, 0);
-	drm_panel_disable(tcon->panel);
+
+	if (!IS_ERR(tcon->bridge))
+		drm_bridge_disable(tcon->bridge);
+
+	if (!IS_ERR(tcon->panel))
+		drm_panel_disable(tcon->panel);
 }
 
 static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
@@ -216,10 +226,6 @@ int sun4i_rgb_init(struct drm_device *drm)
 	struct sun4i_rgb *rgb;
 	int ret;
 
-	/* If we don't have a panel, there's no point in going on */
-	if (IS_ERR(tcon->panel))
-		return -ENODEV;
-
 	rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL);
 	if (!rgb)
 		return -ENOMEM;
@@ -240,19 +246,37 @@ int sun4i_rgb_init(struct drm_device *drm)
 	/* The RGB encoder can only work with the TCON channel 0 */
 	rgb->encoder.possible_crtcs = BIT(0);
 
-	drm_connector_helper_add(&rgb->connector,
-				 &sun4i_rgb_con_helper_funcs);
-	ret = drm_connector_init(drm, &rgb->connector,
-				 &sun4i_rgb_con_funcs,
-				 DRM_MODE_CONNECTOR_Unknown);
-	if (ret) {
-		dev_err(drm->dev, "Couldn't initialise the rgb connector\n");
-		goto err_cleanup_connector;
+	if (!IS_ERR(tcon->panel)) {
+		drm_connector_helper_add(&rgb->connector,
+					 &sun4i_rgb_con_helper_funcs);
+		ret = drm_connector_init(drm, &rgb->connector,
+					 &sun4i_rgb_con_funcs,
+					 DRM_MODE_CONNECTOR_Unknown);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't initialise the rgb connector\n");
+			goto err_cleanup_connector;
+		}
+
+		drm_mode_connector_attach_encoder(&rgb->connector,
+						  &rgb->encoder);
+
+		ret = drm_panel_attach(tcon->panel, &rgb->connector);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't attach our panel\n");
+			goto err_cleanup_connector;
+		}
 	}
 
-	drm_mode_connector_attach_encoder(&rgb->connector, &rgb->encoder);
+	if (!IS_ERR(tcon->bridge)) {
+		rgb->encoder.bridge = tcon->bridge;
+		tcon->bridge->encoder = &rgb->encoder;
 
-	drm_panel_attach(tcon->panel, &rgb->connector);
+		ret = drm_bridge_attach(drm, tcon->bridge);
+		if (ret) {
+			dev_err(drm->dev, "Couldn't attach our bridge\n");
+			goto err_cleanup_connector;
+		}
+	}
 
 	return 0;
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index eed6a9e8d9a6..4618d98913b4 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -432,6 +432,40 @@ static struct drm_panel *sun4i_tcon_find_panel(struct device_node *node)
 	return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER);
 }
 
+static struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node)
+{
+	struct device_node *port, *remote, *child;
+	struct device_node *end_node = NULL;
+
+	/* Inputs are listed first, then outputs */
+	port = of_graph_get_port_by_id(node, 1);
+
+	/*
+	 * Our first output is the RGB interface where the panel will
+	 * be connected.
+	 */
+	for_each_child_of_node(port, child) {
+		u32 reg;
+
+		of_property_read_u32(child, "reg", &reg);
+		if (reg == 0)
+			end_node = child;
+	}
+
+	if (!end_node) {
+		DRM_DEBUG_DRIVER("Missing bridge endpoint\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	remote = of_graph_get_remote_port_parent(end_node);
+	if (!remote) {
+		DRM_DEBUG_DRIVER("Enable to parse remote node\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	return of_drm_find_bridge(remote) ?: ERR_PTR(-EPROBE_DEFER);
+}
+
 static int sun4i_tcon_bind(struct device *dev, struct device *master,
 			   void *data)
 {
@@ -485,8 +519,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 	}
 
 	tcon->panel = sun4i_tcon_find_panel(dev->of_node);
-	if (IS_ERR(tcon->panel)) {
-		dev_info(dev, "No panel found... RGB output disabled\n");
+	tcon->bridge = sun4i_tcon_find_bridge(dev->of_node);
+	if (IS_ERR(tcon->panel) && IS_ERR(tcon->bridge)) {
+		dev_info(dev, "No panel or bridge found... RGB output disabled\n");
 		return 0;
 	}
 
@@ -515,19 +550,22 @@ static struct component_ops sun4i_tcon_ops = {
 static int sun4i_tcon_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
+	struct drm_bridge *bridge;
 	struct drm_panel *panel;
 
 	/*
-	 * The panel is not ready.
+	 * Neither the bridge or the panel is ready.
 	 * Defer the probe.
 	 */
 	panel = sun4i_tcon_find_panel(node);
+	bridge = sun4i_tcon_find_bridge(node);
 
 	/*
 	 * If we don't have a panel endpoint, just go on
 	 */
-	if (PTR_ERR(panel) == -EPROBE_DEFER) {
-		DRM_DEBUG_DRIVER("Still waiting for our panel. Deferring...\n");
+	if ((PTR_ERR(panel) == -EPROBE_DEFER) &&
+	    (PTR_ERR(bridge) == -EPROBE_DEFER)) {
+		DRM_DEBUG_DRIVER("Still waiting for our panel/bridge. Deferring...\n");
 		return -EPROBE_DEFER;
 	}
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 0e0b11db401b..31069027d7fb 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -162,6 +162,7 @@ struct sun4i_tcon {
 	/* Platform adjustments */
 	bool				has_mux;
 
+	struct drm_bridge		*bridge;
 	struct drm_panel		*panel;
 };
 
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:05 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:05 +0200
Subject: [PATCH 05/20] drm/sun4i: request exact rates to our parents
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-6-git-send-email-maxime.ripard@free-electrons.com>

Our pixel clock currently only tries to deal with the current parent rate.

While that works when the resolution is the same than the one already
program, or when we can compute directly the rate from the current parent
rate, it cannot work in most situation when we want to change the
frequency, and we end up with an improper pixel clock rate, which obviously
doesn't work as expected.

Ask our parent for all the possible dividers if it can reach that
frequency, and return the best parent rate to the clock framework so that
we can use it.

Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")
Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_dotclock.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
index 6c9c090a8006..1ddf6d7a7107 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
@@ -72,14 +72,40 @@ static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw,
 static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
 				  unsigned long *parent_rate)
 {
-	return *parent_rate / DIV_ROUND_CLOSEST(*parent_rate, rate);
+	unsigned long best_parent = 0;
+	u8 best_div = 1;
+	int i;
+
+	for (i = 6; i < 127; i++) {
+		unsigned long ideal = rate * i;
+		unsigned long rounded;
+
+		rounded = clk_hw_round_rate(clk_hw_get_parent(hw),
+					    ideal);
+
+		if (rounded == ideal) {
+			best_parent = rounded;
+			best_div = i;
+			goto out;
+		}
+
+		if ((rounded < ideal) && (rounded > best_parent)) {
+			best_parent = rounded;
+			best_div = i;
+		}
+	}
+
+out:
+	*parent_rate = best_parent;
+
+	return best_parent / best_div;
 }
 
 static int sun4i_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
 			       unsigned long parent_rate)
 {
 	struct sun4i_dclk *dclk = hw_to_dclk(hw);
-	int div = DIV_ROUND_CLOSEST(parent_rate, rate);
+	u8 div = parent_rate / rate;
 
 	return regmap_update_bits(dclk->regmap, SUN4I_TCON0_DCLK_REG,
 				  GENMASK(6, 0), div);
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:13 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:13 +0200
Subject: [PATCH 13/20] drm/bridge: Add RGB to VGA bridge support
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-14-git-send-email-maxime.ripard@free-electrons.com>

Some boards have an entirely passive RGB to VGA bridge, based on either
DACs or resistor ladders.

Those might or might not have an i2c bus routed to the VGA connector in
order to access the screen EDIDs.

Add a bridge that doesn't do anything but expose the modes available on the
screen, either based on the EDIDs if available, or based on the XGA
standards.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 .../bindings/display/bridge/dumb-vga.txt           |  40 +++++
 drivers/gpu/drm/bridge/Kconfig                     |   6 +
 drivers/gpu/drm/bridge/Makefile                    |   1 +
 drivers/gpu/drm/bridge/dumb-vga.c                  | 186 +++++++++++++++++++++
 4 files changed, 233 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
 create mode 100644 drivers/gpu/drm/bridge/dumb-vga.c

diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
new file mode 100644
index 000000000000..757f04de97f3
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
@@ -0,0 +1,40 @@
+Passive RGB to VGA bridge
+-------------------------
+
+This binding is aimed for entirely passive RGB to VGA bridges that do not
+require any configuration.
+
+Required properties:
+
+- compatible: Should be "dumb-vga-bridge"
+
+Optional properties:
+
+- ddc-i2c-bus: phandle to the i2c bus used to communicate with the monitor
+
+Required nodes:
+
+This device has one video port. Its connection is modelled using the OF
+graph bindings specified in Documentation/devicetree/bindings/graph.txt. This
+connection is meant to be the RGB input bus.
+
+
+Example
+-------
+
+bridge {
+        compatible = "dumb-vga-bridge";
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        port at 0 {
+                reg = <0>;
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                vga_input: endpoint at 0 {
+                        reg = <0>;
+                        remote-endpoint = <&tcon0_out_vga>;
+               };
+        };
+};
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 8f7423f18da5..cf279956cbec 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -17,6 +17,12 @@ config DRM_ANALOGIX_ANX78XX
 	  the HDMI output of an application processor to MyDP
 	  or DisplayPort.
 
+config DRM_DUMB_VGA
+	tristate "Dumb RGB to VGA Bridge support"
+	select DRM_KMS_HELPER
+	help
+	  Support for passive RGB to VGA bridges
+
 config DRM_DW_HDMI
 	tristate
 	select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 96b13b30e6ab..63f21120e8f8 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,6 +1,7 @@
 ccflags-y := -Iinclude/drm
 
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
+obj-$(CONFIG_DRM_DUMB_VGA) += dumb-vga.o
 obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
 obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
diff --git a/drivers/gpu/drm/bridge/dumb-vga.c b/drivers/gpu/drm/bridge/dumb-vga.c
new file mode 100644
index 000000000000..2864fa535bf8
--- /dev/null
+++ b/drivers/gpu/drm/bridge/dumb-vga.c
@@ -0,0 +1,186 @@
+
+#include <linux/module.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+
+struct dumb_vga {
+	struct drm_bridge	bridge;
+	struct drm_connector	connector;
+
+	struct i2c_adapter	*ddc;
+};
+
+static inline struct dumb_vga *
+drm_bridge_to_dumb_vga(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct dumb_vga, bridge);
+}
+
+static inline struct dumb_vga *
+drm_connector_to_dumb_vga(struct drm_connector *connector)
+{
+	return container_of(connector, struct dumb_vga, connector);
+}
+
+static int dumb_vga_get_modes(struct drm_connector *connector)
+{
+	struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
+	struct edid *edid;
+	int ret;
+
+	if (!vga->ddc)
+		goto fallback;
+
+	edid = drm_get_edid(connector, vga->ddc);
+	if (!edid) {
+		DRM_INFO("EDID readout failed, falling back to standard modes\n");
+		goto fallback;
+	}
+
+	drm_mode_connector_update_edid_property(connector, edid);
+	return drm_add_edid_modes(connector, edid);
+
+fallback:
+	/*
+	 * In case we cannot retrieve the EDIDs (broken or missing i2c
+	 * bus), fallback on the XGA standards
+	 */
+	ret = drm_add_modes_noedid(connector, 1920, 1200);
+
+	/* And prefer a mode pretty much anyone can handle */
+	drm_set_preferred_mode(connector, 1024, 768);
+
+	return ret;
+}
+
+static struct drm_encoder *
+dumb_vga_best_encoder(struct drm_connector *connector)
+{
+	struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
+
+	return vga->bridge.encoder;
+}
+
+static struct drm_connector_helper_funcs dumb_vga_con_helper_funcs = {
+	.get_modes	= dumb_vga_get_modes,
+	.best_encoder	= dumb_vga_best_encoder,
+};
+
+static enum drm_connector_status
+dumb_vga_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static void
+dumb_vga_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_cleanup(connector);
+}
+
+static struct drm_connector_funcs dumb_vga_con_funcs = {
+	.dpms			= drm_atomic_helper_connector_dpms,
+	.detect			= dumb_vga_connector_detect,
+	.fill_modes		= drm_helper_probe_single_connector_modes,
+	.destroy		= dumb_vga_connector_destroy,
+	.reset			= drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+};
+
+static int dumb_vga_attach(struct drm_bridge *bridge)
+{
+	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+	int ret;
+
+	if (!bridge->encoder) {
+		DRM_ERROR("Missing encoder\n");
+		return -ENODEV;
+	}
+
+	drm_connector_helper_add(&vga->connector,
+				 &dumb_vga_con_helper_funcs);
+	ret = drm_connector_init(bridge->dev, &vga->connector,
+				 &dumb_vga_con_funcs, DRM_MODE_CONNECTOR_VGA);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector\n");
+		return ret;
+	}
+
+	drm_mode_connector_attach_encoder(&vga->connector,
+					  bridge->encoder);
+
+	return 0;
+}
+
+static void dumb_vga_nop(struct drm_bridge *bridge) {};
+
+static struct drm_bridge_funcs dumb_vga_bridge_funcs = {
+	.attach		= dumb_vga_attach,
+	.enable		= dumb_vga_nop,
+	.disable	= dumb_vga_nop,
+	.pre_enable	= dumb_vga_nop,
+	.post_disable	= dumb_vga_nop,
+};
+
+static int dumb_vga_probe(struct platform_device *pdev)
+{
+	struct dumb_vga *vga;
+	struct device_node *ddc;
+
+	vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL);
+	if (!vga)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, vga);
+
+	ddc = of_parse_phandle(pdev->dev.of_node, "ddc-i2c-bus", 0);
+	if (ddc) {
+		vga->ddc = of_find_i2c_adapter_by_node(ddc);
+		of_node_put(ddc);
+
+		if (!vga->ddc) {
+			dev_err(&pdev->dev, "Couldn't retrieve i2c bus\n");
+			return -EPROBE_DEFER;
+		}
+	} else {
+		dev_info(&pdev->dev,
+			 "No i2c bus specified... Disabling EDID readout\n");
+	}
+
+	vga->bridge.funcs = &dumb_vga_bridge_funcs;
+	vga->bridge.of_node = pdev->dev.of_node;
+
+	return drm_bridge_add(&vga->bridge);
+}
+
+static int dumb_vga_remove(struct platform_device *pdev)
+{
+	struct dumb_vga *vga = platform_get_drvdata(pdev);
+
+	drm_bridge_remove(&vga->bridge);
+
+	return 0;
+}
+
+static const struct of_device_id dumb_vga_match[] = {
+	{ .compatible = "dumb-vga-bridge" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dumb_vga_match);
+
+struct platform_driver dumb_vga_driver = {
+	.probe	= dumb_vga_probe,
+	.remove	= dumb_vga_remove,
+	.driver		= {
+		.name		= "dumb-vga-bridge",
+		.of_match_table	= dumb_vga_match,
+	},
+};
+module_platform_driver(dumb_vga_driver);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard at free-electrons.com>");
+MODULE_DESCRIPTION("Dumb RGB to VGA bridge driver");
+MODULE_LICENSE("GPL");
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:02 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:02 +0200
Subject: [PATCH 02/20] clk: multiplier: Prevent the multiplier from under /
 over flowing
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-3-git-send-email-maxime.ripard@free-electrons.com>

In the current multiplier base clock implementation, if the
CLK_SET_RATE_PARENT flag isn't set, the code will not make sure that the
multiplier computed remains within the boundaries of our clock.

This means that if the clock we want to reach is below the parent rate,
or if the multiplier is above the maximum that we can reach, we will end up
with a completely bogus one that the clock cannot achieve.

Fixes: f2e0a53271a4 ("clk: Add a basic multiplier clock")
Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/clk-multiplier.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk-multiplier.c b/drivers/clk/clk-multiplier.c
index 9e449c7b751c..dc037c957acd 100644
--- a/drivers/clk/clk-multiplier.c
+++ b/drivers/clk/clk-multiplier.c
@@ -52,14 +52,28 @@ static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
 				unsigned long *best_parent_rate,
 				u8 width, unsigned long flags)
 {
+	struct clk_multiplier *mult = to_clk_multiplier(hw);
 	unsigned long orig_parent_rate = *best_parent_rate;
 	unsigned long parent_rate, current_rate, best_rate = ~0;
 	unsigned int i, bestmult = 0;
+	unsigned int maxmult = (1 << width) - 1;
+
+	if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
+		bestmult = rate / orig_parent_rate;
+
+		/* Make sure we don't end up with a 0 multiplier */
+		if ((bestmult == 0) &&
+		    !(mult->flags & CLK_MULTIPLIER_ZERO_BYPASS))
+			bestmult = 1;
 
-	if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT))
-		return rate / *best_parent_rate;
+		/* Make sure we don't overflow the multiplier */
+		if (bestmult > maxmult)
+			bestmult = maxmult;
+
+		return bestmult;
+	}
 
-	for (i = 1; i < ((1 << width) - 1); i++) {
+	for (i = 1; i < maxmult; i++) {
 		if (rate == orig_parent_rate * i) {
 			/*
 			 * This is the best case for us if we have a
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:01 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:01 +0200
Subject: [PATCH 01/20] clk: fixed-factor: Pass clk rates change to the parent
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-2-git-send-email-maxime.ripard@free-electrons.com>

A fixed factor clock, if it needs to change its rate, by definition do not
have any choice but to modify its parent rate.

Add the CLK_SET_RATE_PARENT flag to that clock so that it can happen

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/clk-fixed-factor.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index 75cd6c792cb8..3363abd9b4ae 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -167,7 +167,8 @@ void __init of_fixed_factor_clk_setup(struct device_node *node)
 	of_property_read_string(node, "clock-output-names", &clk_name);
 	parent_name = of_clk_get_parent_name(node, 0);
 
-	clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0,
+	clk = clk_register_fixed_factor(NULL, clk_name, parent_name,
+					CLK_SET_RATE_PARENT,
 					mult, div);
 	if (!IS_ERR(clk))
 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:08 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:08 +0200
Subject: [PATCH 08/20] drm/sun4i: rgb: panel is an error pointer
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-9-git-send-email-maxime.ripard@free-electrons.com>

In case of an error, our pointer to the drm_panel structure attached to our
encoder will hold an error pointer, not a NULL pointer.

Make sure we check the right thing.

Fixes: 29e57fab97fc ("drm: sun4i: Add RGB output")
Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_rgb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index 923f55039cb1..b46d2c15dc95 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -217,7 +217,7 @@ int sun4i_rgb_init(struct drm_device *drm)
 	int ret;
 
 	/* If we don't have a panel, there's no point in going on */
-	if (!tcon->panel)
+	if (IS_ERR(tcon->panel))
 		return -ENODEV;
 
 	rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL);
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:03 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:03 +0200
Subject: [PATCH 03/20] clk: sunxi: tcon-ch1: Do not return a negative error in
 get_parent
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-4-git-send-email-maxime.ripard@free-electrons.com>

get_parent is supposed to return an unsigned 8 bit integer, so returning
-EINVAL is a bad idea.

Remove it.

Reported-by: Dan Carpenter <dan.carpenter at oracle.com>
Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi/clk-sun4i-tcon-ch1.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c b/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c
index 98a4582de56a..248585238b1c 100644
--- a/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c
+++ b/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c
@@ -85,9 +85,6 @@ static u8 tcon_ch1_get_parent(struct clk_hw *hw)
 	reg = readl(tclk->reg) >> TCON_CH1_SCLK2_MUX_SHIFT;
 	reg &= reg >> TCON_CH1_SCLK2_MUX_MASK;
 
-	if (reg >= num_parents)
-		return -EINVAL;
-
 	return reg;
 }
 
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:06 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:06 +0200
Subject: [PATCH 06/20] drm/sun4i: allow dclk to modify its parent rate
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-7-git-send-email-maxime.ripard@free-electrons.com>

The pixel clock being only a divider of its parent clock, depending on the
resolution, it's expected to change its parent rate. Add that flag so that
the clock framework knows it.

Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")
Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_dotclock.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
index 1ddf6d7a7107..5b3463197c48 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
@@ -170,6 +170,7 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
 	init.ops = &sun4i_dclk_ops;
 	init.parent_names = &parent_name;
 	init.num_parents = 1;
+	init.flags = CLK_SET_RATE_PARENT;
 
 	dclk->regmap = tcon->regs;
 	dclk->hw.init = &init;
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:04 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:04 +0200
Subject: [PATCH 04/20] clk: sunxi: display: Add per-clock flags
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-5-git-send-email-maxime.ripard@free-electrons.com>

The TCON channel 0 clock that is the parent clock of our pixel clock is
expected to change its rate depending on the resolution we want to output
in our display engine.

However, since it's only a mux, the only way it can do that is by changing
its parents rate.

Allow to give flags in our display clocks description, and add the
CLK_SET_RATE_PARENT flag for the TCON channel 0 flag.

Fixes: a3b4956ee6d9 ("clk: sunxi: display: Add per-clock flags")
Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/clk/sunxi/clk-sun4i-display.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi/clk-sun4i-display.c b/drivers/clk/sunxi/clk-sun4i-display.c
index 445a7498d6df..9780fac6d029 100644
--- a/drivers/clk/sunxi/clk-sun4i-display.c
+++ b/drivers/clk/sunxi/clk-sun4i-display.c
@@ -33,6 +33,8 @@ struct sun4i_a10_display_clk_data {
 
 	u8	width_div;
 	u8	width_mux;
+
+	u32	flags;
 };
 
 struct reset_data {
@@ -166,7 +168,7 @@ static void __init sun4i_a10_display_init(struct device_node *node,
 				     data->has_div ? &div->hw : NULL,
 				     data->has_div ? &clk_divider_ops : NULL,
 				     &gate->hw, &clk_gate_ops,
-				     0);
+				     data->flags);
 	if (IS_ERR(clk)) {
 		pr_err("%s: Couldn't register the clock\n", clk_name);
 		goto free_div;
@@ -232,6 +234,7 @@ static const struct sun4i_a10_display_clk_data sun4i_a10_tcon_ch0_data __initcon
 	.offset_rst	= 29,
 	.offset_mux	= 24,
 	.width_mux	= 2,
+	.flags		= CLK_SET_RATE_PARENT,
 };
 
 static void __init sun4i_a10_tcon_ch0_setup(struct device_node *node)
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:16 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:16 +0200
Subject: [PATCH 16/20] ARM: sun5i: a13-olinuxino: Enable VGA bridge
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-17-git-send-email-maxime.ripard@free-electrons.com>

Now that we have support for the VGA bridges using our DRM driver, enable
the display engine for the Olimex A13-Olinuxino.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 34 +++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
index b3c234c65ea1..b3298d231258 100644
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
@@ -72,6 +72,27 @@
 			default-state = "on";
 		};
 	};
+
+	bridge {
+		compatible = "dumb-vga-bridge";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port at 0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			vga_input: endpoint at 0 {
+				reg = <0>;
+				remote-endpoint = <&tcon0_out_vga>;
+			};
+		};
+	};
+};
+
+&be0 {
+	status = "okay";
 };
 
 &ehci0 {
@@ -211,6 +232,19 @@
 	status = "okay";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_rgb666_pins>;
+	status = "okay";
+};
+
+&tcon0_out {
+	tcon0_out_vga: endpoint at 0 {
+		reg = <0>;
+		remote-endpoint = <&vga_input>;
+	};
+};
+
 &uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart1_pins_b>;
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:19 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:19 +0200
Subject: [PATCH 19/20] ARM: sunxi: Enable sun4i DRM driver
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-20-git-send-email-maxime.ripard@free-electrons.com>

Enable the new DRM driver in the sunxi default configuration

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 arch/arm/configs/sunxi_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index e20ae3925e36..6a1447cf8feb 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -97,6 +97,8 @@ CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_RC_SUPPORT=y
 CONFIG_RC_DEVICES=y
 CONFIG_IR_SUNXI=y
+CONFIG_DRM=y
+CONFIG_DRM_SUN4I=y
 CONFIG_FB=y
 CONFIG_FB_SIMPLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:14 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:14 +0200
Subject: [PATCH 14/20] ARM: sun5i: a13: Add LCD pins
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-15-git-send-email-maxime.ripard@free-electrons.com>

The RGB bus can be used in several configurations, one of which being the
RGB666.

Add a pinctrl group for that case.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 arch/arm/boot/dts/sun5i-a13.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index 263d46dbc7e6..79b5d513c142 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -237,6 +237,16 @@
 &pio {
 	compatible = "allwinner,sun5i-a13-pinctrl";
 
+	lcd_rgb666_pins: lcd_rgb666 at 0 {
+		allwinner,pins = "PD2", "PD3", "PD4", "PD5", "PD6", "PD7",
+				 "PD10", "PD11", "PD12", "PD13", "PD14", "PD15",
+				 "PD18", "PD19", "PD20", "PD21", "PD22", "PD23",
+				 "PD24", "PD25", "PD26", "PD27";
+		allwinner,function = "lcd0";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
 	uart1_pins_a: uart1 at 0 {
 		allwinner,pins = "PE10", "PE11";
 		allwinner,function = "uart1";
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:07 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:07 +0200
Subject: [PATCH 07/20] drm/sun4i: rgb: Validate the clock rate
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-8-git-send-email-maxime.ripard@free-electrons.com>

Our pixel clock cannot reach a high enough rate for some rather high while
common resolutions (like 1080p60).

Make sure we filter the resolutions we cannot reach in our mode_valid
function.

Fixes: 29e57fab97fc ("drm: sun4i: Add RGB output")
Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_rgb.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index ab6494818050..923f55039cb1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -54,8 +54,13 @@ static int sun4i_rgb_get_modes(struct drm_connector *connector)
 static int sun4i_rgb_mode_valid(struct drm_connector *connector,
 				struct drm_display_mode *mode)
 {
+	struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector);
+	struct sun4i_drv *drv = rgb->drv;
+	struct sun4i_tcon *tcon = drv->tcon;
 	u32 hsync = mode->hsync_end - mode->hsync_start;
 	u32 vsync = mode->vsync_end - mode->vsync_start;
+	unsigned long rate = mode->crtc_clock * 1000;
+	long rounded_rate;
 
 	DRM_DEBUG_DRIVER("Validating modes...\n");
 
@@ -87,6 +92,15 @@ static int sun4i_rgb_mode_valid(struct drm_connector *connector,
 
 	DRM_DEBUG_DRIVER("Vertical parameters OK\n");
 
+	rounded_rate = clk_round_rate(tcon->dclk, rate);
+	if (rounded_rate < rate)
+		return MODE_CLOCK_LOW;
+
+	if (rounded_rate > rate)
+		return MODE_CLOCK_HIGH;
+
+	DRM_DEBUG_DRIVER("Clock rate OK\n");
+
 	return MODE_OK;
 }
 
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:18 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:18 +0200
Subject: [PATCH 18/20] ARM: multi_v7: enable VGA bridge
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-19-git-send-email-maxime.ripard@free-electrons.com>

Enable the RGB to VGA bridge driver in the defconfig

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 80591f3e867e..5987688dea81 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -536,6 +536,7 @@ CONFIG_DRM=y
 CONFIG_DRM_I2C_ADV7511=m
 # CONFIG_DRM_I2C_CH7006 is not set
 # CONFIG_DRM_I2C_SIL164 is not set
+CONFIG_DRM_DUMB_VGA=m
 CONFIG_DRM_NXP_PTN3460=m
 CONFIG_DRM_PARADE_PS8622=m
 CONFIG_DRM_NOUVEAU=m
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:15 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:15 +0200
Subject: [PATCH 15/20] ARM: sun5i: Move display blocks to A13
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-16-git-send-email-maxime.ripard@free-electrons.com>

Most of the display engine is shared between the R8 and the A13. Move the
common parts to the ?13 DTSI.

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 arch/arm/boot/dts/sun5i-a13.dtsi | 112 ++++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/sun5i-r8.dtsi  | 120 ++-------------------------------------
 2 files changed, 117 insertions(+), 115 deletions(-)

diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index 79b5d513c142..e012890e0cf2 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -207,7 +207,50 @@
 		};
 	};
 
+	display-engine {
+		compatible = "allwinner,sun5i-a13-display-engine";
+		allwinner,pipelines = <&fe0>;
+	};
+
 	soc at 01c00000 {
+		tcon0: lcd-controller at 01c0c000 {
+			compatible = "allwinner,sun5i-a13-tcon";
+			reg = <0x01c0c000 0x1000>;
+			interrupts = <44>;
+			resets = <&tcon_ch0_clk 1>;
+			reset-names = "lcd";
+			clocks = <&ahb_gates 36>,
+				 <&tcon_ch0_clk>,
+				 <&tcon_ch1_clk>;
+			clock-names = "ahb",
+				      "tcon-ch0",
+				      "tcon-ch1";
+			clock-output-names = "tcon-pixel-clock";
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon0_in: port at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					tcon0_in_be0: endpoint at 0 {
+						reg = <0>;
+						remote-endpoint = <&be0_out_tcon0>;
+					};
+				};
+
+				tcon0_out: port at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+			};
+		};
+
 		pwm: pwm at 01c20e00 {
 			compatible = "allwinner,sun5i-a13-pwm";
 			reg = <0x01c20e00 0xc>;
@@ -215,6 +258,75 @@
 			#pwm-cells = <3>;
 			status = "disabled";
 		};
+
+		fe0: display-frontend at 01e00000 {
+			compatible = "allwinner,sun5i-a13-display-frontend";
+			reg = <0x01e00000 0x20000>;
+			interrupts = <47>;
+			clocks = <&ahb_gates 46>, <&de_fe_clk>,
+				 <&dram_gates 25>;
+			clock-names = "ahb", "mod",
+				      "ram";
+			resets = <&de_fe_clk>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				fe0_out: port at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					fe0_out_be0: endpoint at 0 {
+						reg = <0>;
+						remote-endpoint = <&be0_in_fe0>;
+					};
+				};
+			};
+		};
+
+		be0: display-backend at 01e60000 {
+			compatible = "allwinner,sun5i-a13-display-backend";
+			reg = <0x01e60000 0x10000>;
+			clocks = <&ahb_gates 44>, <&de_be_clk>,
+				 <&dram_gates 26>;
+			clock-names = "ahb", "mod",
+				      "ram";
+			resets = <&de_be_clk>;
+			status = "disabled";
+
+			assigned-clocks = <&de_be_clk>;
+			assigned-clock-rates = <300000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				be0_in: port at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					be0_in_fe0: endpoint at 0 {
+						reg = <0>;
+						remote-endpoint = <&fe0_out_be0>;
+					};
+				};
+
+				be0_out: port at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					be0_out_tcon0: endpoint at 0 {
+						reg = <0>;
+						remote-endpoint = <&tcon0_in_be0>;
+					};
+				};
+			};
+		};
 	};
 };
 
diff --git a/arch/arm/boot/dts/sun5i-r8.dtsi b/arch/arm/boot/dts/sun5i-r8.dtsi
index c04cf690b858..8b058f53b7dc 100644
--- a/arch/arm/boot/dts/sun5i-r8.dtsi
+++ b/arch/arm/boot/dts/sun5i-r8.dtsi
@@ -76,122 +76,12 @@
 				};
 			};
 		};
-
-		tcon0: lcd-controller at 01c0c000 {
-			compatible = "allwinner,sun5i-a13-tcon";
-			reg = <0x01c0c000 0x1000>;
-			interrupts = <44>;
-			resets = <&tcon_ch0_clk 1>;
-			reset-names = "lcd";
-			clocks = <&ahb_gates 36>,
-				 <&tcon_ch0_clk>,
-				 <&tcon_ch1_clk>;
-			clock-names = "ahb",
-				      "tcon-ch0",
-				      "tcon-ch1";
-			clock-output-names = "tcon-pixel-clock";
-			status = "disabled";
-
-			ports {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				tcon0_in: port at 0 {
-					#address-cells = <1>;
-					#size-cells = <0>;
-					reg = <0>;
-
-					tcon0_in_be0: endpoint at 0 {
-						reg = <0>;
-						remote-endpoint = <&be0_out_tcon0>;
-					};
-				};
-
-				tcon0_out: port at 1 {
-					#address-cells = <1>;
-					#size-cells = <0>;
-					reg = <1>;
-
-					tcon0_out_tve0: endpoint at 1 {
-						reg = <1>;
-						remote-endpoint = <&tve0_in_tcon0>;
-					};
-				};
-			};
-		};
-
-		fe0: display-frontend at 01e00000 {
-			compatible = "allwinner,sun5i-a13-display-frontend";
-			reg = <0x01e00000 0x20000>;
-			interrupts = <47>;
-			clocks = <&ahb_gates 46>, <&de_fe_clk>,
-				 <&dram_gates 25>;
-			clock-names = "ahb", "mod",
-				      "ram";
-			resets = <&de_fe_clk>;
-			status = "disabled";
-
-			ports {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				fe0_out: port at 1 {
-					#address-cells = <1>;
-					#size-cells = <0>;
-					reg = <1>;
-
-					fe0_out_be0: endpoint at 0 {
-						reg = <0>;
-						remote-endpoint = <&be0_in_fe0>;
-					};
-				};
-			};
-		};
-
-		be0: display-backend at 01e60000 {
-			compatible = "allwinner,sun5i-a13-display-backend";
-			reg = <0x01e60000 0x10000>;
-			clocks = <&ahb_gates 44>, <&de_be_clk>,
-				 <&dram_gates 26>;
-			clock-names = "ahb", "mod",
-				      "ram";
-			resets = <&de_be_clk>;
-			status = "disabled";
-
-			assigned-clocks = <&de_be_clk>;
-			assigned-clock-rates = <300000000>;
-
-			ports {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				be0_in: port at 0 {
-					#address-cells = <1>;
-					#size-cells = <0>;
-					reg = <0>;
-
-					be0_in_fe0: endpoint at 0 {
-						reg = <0>;
-						remote-endpoint = <&fe0_out_be0>;
-					};
-				};
-
-				be0_out: port at 1 {
-					#address-cells = <1>;
-					#size-cells = <0>;
-					reg = <1>;
-
-					be0_out_tcon0: endpoint at 0 {
-						reg = <0>;
-						remote-endpoint = <&tcon0_in_be0>;
-					};
-				};
-			};
-		};
 	};
+};
 
-	display-engine {
-		compatible = "allwinner,sun5i-a13-display-engine";
-		allwinner,pipelines = <&fe0>;
+&tcon0_out {
+	tcon0_out_tve0: endpoint at 1 {
+		reg = <1>;
+		remote-endpoint = <&tve0_in_tcon0>;
 	};
 };
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:17 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:17 +0200
Subject: [PATCH 17/20] ARM: multi_v7: Enable sun4i DRM driver
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-18-git-send-email-maxime.ripard@free-electrons.com>

Enable the new DRM driver in the multi_v7 defconfig

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index f7e0d49b515a..80591f3e867e 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -552,6 +552,7 @@ CONFIG_DRM_ATMEL_HLCDC=m
 CONFIG_DRM_RCAR_DU=m
 CONFIG_DRM_RCAR_HDMI=y
 CONFIG_DRM_RCAR_LVDS=y
+CONFIG_DRM_SUN4I=m
 CONFIG_DRM_TEGRA=y
 CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=m
 CONFIG_DRM_PANEL_SIMPLE=y
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:09 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:09 +0200
Subject: [PATCH 09/20] drm/sun4i: defer only if we didn't find our panel
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-10-git-send-email-maxime.ripard@free-electrons.com>

Our code currently defers our probe on any error, even if we were not
expecting to have one at all.

Make sure we return -EPROBE_DEFER only when we were supposed to have a
panel, but it's not probed yet.

Fixes: 29e57fab97fc ("drm: sun4i: Add RGB output")
Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 9f19b0e08560..eed6a9e8d9a6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -429,7 +429,7 @@ static struct drm_panel *sun4i_tcon_find_panel(struct device_node *node)
 		return ERR_PTR(-EINVAL);
 	}
 
-	return of_drm_find_panel(remote);
+	return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER);
 }
 
 static int sun4i_tcon_bind(struct device *dev, struct device *master,
@@ -522,12 +522,13 @@ static int sun4i_tcon_probe(struct platform_device *pdev)
 	 * Defer the probe.
 	 */
 	panel = sun4i_tcon_find_panel(node);
-	if (IS_ERR(panel)) {
-		/*
-		 * If we don't have a panel endpoint, just go on
-		 */
-		if (PTR_ERR(panel) != -ENODEV)
-			return -EPROBE_DEFER;
+
+	/*
+	 * If we don't have a panel endpoint, just go on
+	 */
+	if (PTR_ERR(panel) == -EPROBE_DEFER) {
+		DRM_DEBUG_DRIVER("Still waiting for our panel. Deferring...\n");
+		return -EPROBE_DEFER;
 	}
 
 	return component_add(&pdev->dev, &sun4i_tcon_ops);
-- 
2.8.2



From maxime.ripard at free-electrons.com  Mon May 16 05:47:20 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 14:47:20 +0200
Subject: [PATCH 20/20] ARM: sunxi: Enable VGA bridge
In-Reply-To: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1463402840-17062-21-git-send-email-maxime.ripard@free-electrons.com>

Enable the VGA bridge used on the A13-Olinuxino in the sunxi defconfig

Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
---
 arch/arm/configs/sunxi_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index 6a1447cf8feb..3676cc2db2eb 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -98,6 +98,7 @@ CONFIG_MEDIA_RC_SUPPORT=y
 CONFIG_RC_DEVICES=y
 CONFIG_IR_SUNXI=y
 CONFIG_DRM=y
+CONFIG_DRM_DUMB_VGA=y
 CONFIG_DRM_SUN4I=y
 CONFIG_FB=y
 CONFIG_FB_SIMPLE=y
-- 
2.8.2



From matt.evans at arm.com  Mon May 16 05:54:56 2016
From: matt.evans at arm.com (Matt Evans)
Date: Mon, 16 May 2016 13:54:56 +0100
Subject: [PATCH] kvm: arm64: Fix EC field in inject_abt64
Message-ID: <5739C320.6010602@arm.com>

The EC field of the constructed ESR is conditionally modified by ORing in
ESR_ELx_EC_DABT_LOW for a data abort.  However, ESR_ELx_EC_SHIFT is missing
from this condition.

Signed-off-by: Matt Evans <matt.evans at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Cc: <stable at vger.kernel.org>
---
 arch/arm64/kvm/inject_fault.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index 4d1ac81..e9e0e6d 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -162,7 +162,7 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
 		esr |= (ESR_ELx_EC_IABT_CUR << ESR_ELx_EC_SHIFT);
 
 	if (!is_iabt)
-		esr |= ESR_ELx_EC_DABT_LOW;
+		esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
 
 	vcpu_sys_reg(vcpu, ESR_EL1) = esr | ESR_ELx_FSC_EXTABT;
 }
-- 
1.9.1



From tiwai at suse.de  Mon May 16 05:58:13 2016
From: tiwai at suse.de (Takashi Iwai)
Date: Mon, 16 May 2016 14:58:13 +0200
Subject: [RFC PATCH 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <87inyeidsr.fsf@belgarion.home>
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
 <s5hk2j38tmf.wl-tiwai@suse.de> <87twi1hssl.fsf@belgarion.home>
 <s5hy47c7jvd.wl-tiwai@suse.de> <87mvnrhux4.fsf@belgarion.home>
 <s5hoa867e6v.wl-tiwai@suse.de> <87inyeidsr.fsf@belgarion.home>
Message-ID: <s5h1t526ty2.wl-tiwai@suse.de>

On Mon, 16 May 2016 10:53:56 +0200,
Robert Jarzmik wrote:
> 
> Takashi Iwai <tiwai at suse.de> writes:
> 
> > On Sun, 15 May 2016 23:29:27 +0200,
> > Robert Jarzmik wrote:
> >> 
> >> Takashi Iwai <tiwai at suse.de> writes:
> >> 
> >> > On Sat, 14 May 2016 11:50:50 +0200,
> >> >
> >> > No, my concern is that it's creating a dummy codec object temporarily
> >> > on the stack just by copying some fields and calling the ops with it.
> >> > (And actually the current code may work wrongly because lack of
> >> >  zero-clear of the object.)
> >> Ah yes, I remember now, the on-stack generated device, indeed ugly.
> >> 
> >> > IMO, a cleaner way would be to define the ops passed with both
> >> > controller and codec objects as arguments, and pass NULL codec here.
> >> It's rather unusual to need both the device and its controller in bus
> >> operations. I must admit I have no better idea so far, so I'll try that just to
> >> see how it looks like, and let's see next ...
> >
> > Thinking of this again, I wonder now why we need to pass the codec
> > object at all.  It's the read/write ops via ac97, so we just need the
> > ac97_controller object and the address slot of the accessed codec?
> So far it would work. The only objection I would see is if in the future the bus
> operation needs a specialization which is ac97 codec dependent, such as a flag
> or a mask in ac97_codec_device structure.
> 
> Even if I'd like to not have these in bus operations, the struct snd_ac97 had a
> need for a 'caps', 'ext_id', ... fields for example. Yet these could be
> contained in the ac97_codec_device structure and not exposed to bus operations.

Do we have any example of such exceptions?  For AC97, we don't need to
think of future extensions at all.

If any, we may provide two levels of ops abstractions: the lower
ac97_controller_ops.read/write, and the upper ac97_codec_ops
read/write that may override if defined, but as default it just wraps 
over controller ops.  But I don't think we'd need such unless we
really see the demand to be exposed outside the codec driver itself.

> Another worry is the pattern (as an example) in atmel_ac97c_write() in
> sound/atmel/ac97.c, where the codec structure is used to get the controller
> through a container_of() type call. Yet passing the controller to bus operations
> takes care of this one.

Right.

> From a "purely API" point of view the couple (ac97_controller, ac97_slot_id) is
> what will route an ac97 bus operation, be that a read/write/reset/..., the
> remaining question is will it cover the cases we've not thought of ?

The remaining ops are rather codec-specific operations, and they don't
have to be implemented in the bus (controller) level.  We should keep
the bus ops as small as possible.


thanks,

Takashi


From daniel at ffwll.ch  Mon May 16 06:12:15 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Mon, 16 May 2016 15:12:15 +0200
Subject: [PATCH 12/20] drm/sun4i: Add bridge support
In-Reply-To: <1463402840-17062-13-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-13-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAKMK7uG-uq7XSqyesVnPtx0Ajx-FQjVKm_QzjEZgWJQDn8EkPA@mail.gmail.com>

On Mon, May 16, 2016 at 2:47 PM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Our RGB bus can be either connected to a bridge or a panel. While the panel
> support was already there, the bridge was not.
>
> Fix that.
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>

For bridge support the only thing you need is to set
drm_encoder->bridge. Why do you need to hand-roll your own bridge
support? That pretty muchmeans you'll do it slightly differently (e.g.
you don't bother with a lot of the calls), which will make sharing
bridge drivers ever so harder. And also reviewing code, since using
shared code but slightly differently is really confusing.
-Daniel

> ---
>  drivers/gpu/drm/sun4i/sun4i_drv.c  |  4 +--
>  drivers/gpu/drm/sun4i/sun4i_rgb.c  | 56 +++++++++++++++++++++++++++-----------
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 48 ++++++++++++++++++++++++++++----
>  drivers/gpu/drm/sun4i/sun4i_tcon.h |  1 +
>  4 files changed, 86 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
> index 257d2b4f3645..1f9e00db747d 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> @@ -268,8 +268,8 @@ static int sun4i_drv_add_endpoints(struct device *dev,
>                 }
>
>                 /*
> -                * If the node is our TCON, the first port is used for our
> -                * panel, and will not be part of the
> +                * If the node is our TCON, the first port is used for
> +                * panel or bridges, and will not be part of the
>                  * component framework.
>                  */
>                 if (sun4i_drv_node_is_tcon(node)) {
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index b46d2c15dc95..c3c611b08269 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -161,7 +161,12 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
>
>         DRM_DEBUG_DRIVER("Enabling RGB output\n");
>
> -       drm_panel_enable(tcon->panel);
> +       if (!IS_ERR(tcon->panel))
> +               drm_panel_enable(tcon->panel);
> +
> +       if (!IS_ERR(tcon->bridge))
> +               drm_bridge_enable(tcon->bridge);
> +
>         sun4i_tcon_channel_enable(tcon, 0);
>  }
>
> @@ -174,7 +179,12 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
>         DRM_DEBUG_DRIVER("Disabling RGB output\n");
>
>         sun4i_tcon_channel_disable(tcon, 0);
> -       drm_panel_disable(tcon->panel);
> +
> +       if (!IS_ERR(tcon->bridge))
> +               drm_bridge_disable(tcon->bridge);
> +
> +       if (!IS_ERR(tcon->panel))
> +               drm_panel_disable(tcon->panel);
>  }
>
>  static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
> @@ -216,10 +226,6 @@ int sun4i_rgb_init(struct drm_device *drm)
>         struct sun4i_rgb *rgb;
>         int ret;
>
> -       /* If we don't have a panel, there's no point in going on */
> -       if (IS_ERR(tcon->panel))
> -               return -ENODEV;
> -
>         rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL);
>         if (!rgb)
>                 return -ENOMEM;
> @@ -240,19 +246,37 @@ int sun4i_rgb_init(struct drm_device *drm)
>         /* The RGB encoder can only work with the TCON channel 0 */
>         rgb->encoder.possible_crtcs = BIT(0);
>
> -       drm_connector_helper_add(&rgb->connector,
> -                                &sun4i_rgb_con_helper_funcs);
> -       ret = drm_connector_init(drm, &rgb->connector,
> -                                &sun4i_rgb_con_funcs,
> -                                DRM_MODE_CONNECTOR_Unknown);
> -       if (ret) {
> -               dev_err(drm->dev, "Couldn't initialise the rgb connector\n");
> -               goto err_cleanup_connector;
> +       if (!IS_ERR(tcon->panel)) {
> +               drm_connector_helper_add(&rgb->connector,
> +                                        &sun4i_rgb_con_helper_funcs);
> +               ret = drm_connector_init(drm, &rgb->connector,
> +                                        &sun4i_rgb_con_funcs,
> +                                        DRM_MODE_CONNECTOR_Unknown);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't initialise the rgb connector\n");
> +                       goto err_cleanup_connector;
> +               }
> +
> +               drm_mode_connector_attach_encoder(&rgb->connector,
> +                                                 &rgb->encoder);
> +
> +               ret = drm_panel_attach(tcon->panel, &rgb->connector);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't attach our panel\n");
> +                       goto err_cleanup_connector;
> +               }
>         }
>
> -       drm_mode_connector_attach_encoder(&rgb->connector, &rgb->encoder);
> +       if (!IS_ERR(tcon->bridge)) {
> +               rgb->encoder.bridge = tcon->bridge;
> +               tcon->bridge->encoder = &rgb->encoder;
>
> -       drm_panel_attach(tcon->panel, &rgb->connector);
> +               ret = drm_bridge_attach(drm, tcon->bridge);
> +               if (ret) {
> +                       dev_err(drm->dev, "Couldn't attach our bridge\n");
> +                       goto err_cleanup_connector;
> +               }
> +       }
>
>         return 0;
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index eed6a9e8d9a6..4618d98913b4 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -432,6 +432,40 @@ static struct drm_panel *sun4i_tcon_find_panel(struct device_node *node)
>         return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER);
>  }
>
> +static struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node)
> +{
> +       struct device_node *port, *remote, *child;
> +       struct device_node *end_node = NULL;
> +
> +       /* Inputs are listed first, then outputs */
> +       port = of_graph_get_port_by_id(node, 1);
> +
> +       /*
> +        * Our first output is the RGB interface where the panel will
> +        * be connected.
> +        */
> +       for_each_child_of_node(port, child) {
> +               u32 reg;
> +
> +               of_property_read_u32(child, "reg", &reg);
> +               if (reg == 0)
> +                       end_node = child;
> +       }
> +
> +       if (!end_node) {
> +               DRM_DEBUG_DRIVER("Missing bridge endpoint\n");
> +               return ERR_PTR(-ENODEV);
> +       }
> +
> +       remote = of_graph_get_remote_port_parent(end_node);
> +       if (!remote) {
> +               DRM_DEBUG_DRIVER("Enable to parse remote node\n");
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       return of_drm_find_bridge(remote) ?: ERR_PTR(-EPROBE_DEFER);
> +}
> +
>  static int sun4i_tcon_bind(struct device *dev, struct device *master,
>                            void *data)
>  {
> @@ -485,8 +519,9 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>         }
>
>         tcon->panel = sun4i_tcon_find_panel(dev->of_node);
> -       if (IS_ERR(tcon->panel)) {
> -               dev_info(dev, "No panel found... RGB output disabled\n");
> +       tcon->bridge = sun4i_tcon_find_bridge(dev->of_node);
> +       if (IS_ERR(tcon->panel) && IS_ERR(tcon->bridge)) {
> +               dev_info(dev, "No panel or bridge found... RGB output disabled\n");
>                 return 0;
>         }
>
> @@ -515,19 +550,22 @@ static struct component_ops sun4i_tcon_ops = {
>  static int sun4i_tcon_probe(struct platform_device *pdev)
>  {
>         struct device_node *node = pdev->dev.of_node;
> +       struct drm_bridge *bridge;
>         struct drm_panel *panel;
>
>         /*
> -        * The panel is not ready.
> +        * Neither the bridge or the panel is ready.
>          * Defer the probe.
>          */
>         panel = sun4i_tcon_find_panel(node);
> +       bridge = sun4i_tcon_find_bridge(node);
>
>         /*
>          * If we don't have a panel endpoint, just go on
>          */
> -       if (PTR_ERR(panel) == -EPROBE_DEFER) {
> -               DRM_DEBUG_DRIVER("Still waiting for our panel. Deferring...\n");
> +       if ((PTR_ERR(panel) == -EPROBE_DEFER) &&
> +           (PTR_ERR(bridge) == -EPROBE_DEFER)) {
> +               DRM_DEBUG_DRIVER("Still waiting for our panel/bridge. Deferring...\n");
>                 return -EPROBE_DEFER;
>         }
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> index 0e0b11db401b..31069027d7fb 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> @@ -162,6 +162,7 @@ struct sun4i_tcon {
>         /* Platform adjustments */
>         bool                            has_mux;
>
> +       struct drm_bridge               *bridge;
>         struct drm_panel                *panel;
>  };
>
> --
> 2.8.2
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel



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


From broonie at kernel.org  Mon May 16 06:12:27 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 16 May 2016 14:12:27 +0100
Subject: [RFC PATCH 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <s5h1t526ty2.wl-tiwai@suse.de>
References: <1462050939-27940-1-git-send-email-robert.jarzmik@free.fr>
 <1462050939-27940-3-git-send-email-robert.jarzmik@free.fr>
 <s5hk2j38tmf.wl-tiwai@suse.de> <87twi1hssl.fsf@belgarion.home>
 <s5hy47c7jvd.wl-tiwai@suse.de> <87mvnrhux4.fsf@belgarion.home>
 <s5hoa867e6v.wl-tiwai@suse.de> <87inyeidsr.fsf@belgarion.home>
 <s5h1t526ty2.wl-tiwai@suse.de>
Message-ID: <20160516131227.GL2953@sirena.org.uk>

On Mon, May 16, 2016 at 02:58:13PM +0200, Takashi Iwai wrote:
> Robert Jarzmik wrote:

> > Even if I'd like to not have these in bus operations, the struct snd_ac97 had a
> > need for a 'caps', 'ext_id', ... fields for example. Yet these could be
> > contained in the ac97_codec_device structure and not exposed to bus operations.

> Do we have any example of such exceptions?  For AC97, we don't need to
> think of future extensions at all.

I can't think of any, even for some of the more fancy CODECs used in
embedded systems.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160516/56fd982c/attachment.sig>

From moinejf at free.fr  Mon May 16 06:15:01 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Mon, 16 May 2016 15:15:01 +0200
Subject: [PATCH 03/16] clk: sunxi-ng: Add fixed factor clock support
In-Reply-To: <CAGb2v65LcXnMj7B-0q2MYESM9vGd9k-yChjvFdX--EivSYdVJg@mail.gmail.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-4-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v65LcXnMj7B-0q2MYESM9vGd9k-yChjvFdX--EivSYdVJg@mail.gmail.com>
Message-ID: <20160516151501.0dccc69384c08d6d646acac1@free.fr>

On Mon, 9 May 2016 18:05:20 +0800
Chen-Yu Tsai <wens at csie.org> wrote:

> > +}
> > +
> > +static long ccu_fixed_factor_round_rate(struct clk_hw *hw,
> > +                                       unsigned long rate,
> > +                                       unsigned long *parent_rate)
> > +{
> > +       struct ccu_fixed_factor *fix = hw_to_ccu_fixed_factor(hw);
> > +
> > +       return *parent_rate / fix->div * fix->mult;
> 
> Why is this the other way around? With integer math it shouldn't be
> interchangeable. (Though it seems clk_fixed_factor does the same...)
> 
> Also, clk_fixed_factor handles CLK_SET_RATE_PARENT. Do we need to do the
> same here?

Agree. Otherwise, sound in the H3 does not work.

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From k.kozlowski at samsung.com  Mon May 16 06:22:29 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 16 May 2016 15:22:29 +0200
Subject: [PATCH v5 0/2] Introducing Exynos ChipId driver
In-Reply-To: <1418285264-21763-1-git-send-email-pankaj.dubey@samsung.com>
References: <1418285264-21763-1-git-send-email-pankaj.dubey@samsung.com>
Message-ID: <CAJKOXPdteY4DH_QpCztbnuY6Njhxb4nvKt14gOundwGdHyb+cQ@mail.gmail.com>

On Thu, Dec 11, 2014 at 9:07 AM, Pankaj Dubey <pankaj.dubey at samsung.com> wrote:
> This patch series introduces Exynos Chipid platform driver.
> Each Exynos SoC has ChipID block which can give information about SoC's
> product Id and revision number.
> At the same time it reduces dependency of mach-exynos files from plat-samsung,
> by removing samsung_rev API, similar API is introduced in chipid driver itself
> to get revision number and product id.
>
> This patch series is based on Kukjin Kim's for-next having SHA_ID:
> 9db7d78aca2c7fbc19a26ce2ef01c805dc010c72
>
> It can also be cleanly applied on latest (next-20141209) linux-next.
>
> This has been tested against both tree on Exynos3250 and Exynos5250 (SMDK) board.
>
> Revision 4 and it's discussion can be found here
>  - https://lkml.org/lkml/2014/12/3/115
>
> Changes since v4:
>  - Removed custom sysfs entries as they were not providing any new information
>    as pointed out by Arnd.
>  - Removed functions exporting product_id and revision, instead we will export
>    exynos_chipid_info structure. It will be helpfull when we need to provide more
>    fields of chipid outside of chipid, as commented by Yadwinder
>  - Converted all funcions as __init.
>
> Change since v3:
>  - This patch set contains 5/6 and 6/6 patch from v3 series.
>  - Made EXYNOS_CHIPID config option non-user selectable,
>    as suggested by Tomasz Figa.
>  - Made uniform macro for EXYNOS4/5_SOC_MASK as EXYNOS_SOC_MASK as
>    suggested by Tomasz Figa.
>  - Made local variables static in chipid driver.
>  - Added existing SoC's product id's.
>  - Added platform driver support.
>
> Changes since v2:
>  - Reorganized patches as suggested by Tomasz Figa.
>  - Addressed review comments of Tomasz Figa in i2c-s3c2410.c file.
>
> Changes since v1:
>  - Added patch to move i2c interrupt re-configuration code from exynos.c
>    to i2c driver, as suggested by Arnd.
>  - After above patch only user of SYS_I2C_CFG register is pm.c so moving
>    save/restore of this register also into i2c driver.
>  - Spiltted up exynos4 and exynos5 machine descriptors to get rid from
>    soc_is_exynos4/exynos5 kind of macros, as suggested by Arnd.
>  - Changed location of chipid driver to "drivers/soc".
>  - Added drivers/base/soc.c provided infrastructure to make SoC specific
>    information avaible to user space via sysfs entry, as suggested by Arnd.
>
>
> Pankaj Dubey (2):
>   soc: samsung: add exynos chipid driver support
>   ARM: EXYNOS: refactoring of mach-exynos to enable chipid driver

Hi,

This is quite old patchset and apparently was not merged. I quickly
looked at previous discussions (for previous versions) and it seems
all review feedback was addressed.

Any other obstacles?

Pankaj, maybe you could respin this (after merge window)?

Best regards,
Krzysztof


From laurent.pinchart at ideasonboard.com  Mon May 16 06:24:15 2016
From: laurent.pinchart at ideasonboard.com (Laurent Pinchart)
Date: Mon, 16 May 2016 16:24:15 +0300
Subject: [PATCH 13/20] drm/bridge: Add RGB to VGA bridge support
In-Reply-To: <1463402840-17062-14-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-14-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <1773896.kpi58ilqqm@avalon>

Hi Maxime,

Thank you for the patch.

On Monday 16 May 2016 14:47:13 Maxime Ripard wrote:
> Some boards have an entirely passive RGB to VGA bridge, based on either
> DACs or resistor ladders.
> 
> Those might or might not have an i2c bus routed to the VGA connector in
> order to access the screen EDIDs.
> 
> Add a bridge that doesn't do anything but expose the modes available on the
> screen, either based on the EDIDs if available, or based on the XGA
> standards.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  .../bindings/display/bridge/dumb-vga.txt           |  40 +++++
>  drivers/gpu/drm/bridge/Kconfig                     |   6 +
>  drivers/gpu/drm/bridge/Makefile                    |   1 +
>  drivers/gpu/drm/bridge/dumb-vga.c                  | 186 ++++++++++++++++++
>  4 files changed, 233 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/display/bridge/dumb-vga.txt create mode
> 100644 drivers/gpu/drm/bridge/dumb-vga.c
> 
> diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
> b/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt new file
> mode 100644
> index 000000000000..757f04de97f3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
> @@ -0,0 +1,40 @@
> +Passive RGB to VGA bridge
> +-------------------------
> +
> +This binding is aimed for entirely passive RGB to VGA bridges that do not
> +require any configuration.
> +
> +Required properties:
> +
> +- compatible: Should be "dumb-vga-bridge"
> +
> +Optional properties:
> +
> +- ddc-i2c-bus: phandle to the i2c bus used to communicate with the monitor
> +
> +Required nodes:
> +
> +This device has one video port. Its connection is modelled using the OF
> +graph bindings specified in Documentation/devicetree/bindings/graph.txt.
> This +connection is meant to be the RGB input bus.

Should the bridge have two ports, one input port connected to a display engine 
and one output port connected to a VGA connector ?

> +
> +
> +Example
> +-------
> +
> +bridge {
> +        compatible = "dumb-vga-bridge";
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        port at 0 {
> +                reg = <0>;
> +                #address-cells = <1>;
> +                #size-cells = <0>;
> +
> +                vga_input: endpoint at 0 {
> +                        reg = <0>;
> +                        remote-endpoint = <&tcon0_out_vga>;
> +               };
> +        };
> +};
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index 8f7423f18da5..cf279956cbec 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -17,6 +17,12 @@ config DRM_ANALOGIX_ANX78XX
>  	  the HDMI output of an application processor to MyDP
>  	  or DisplayPort.
> 
> +config DRM_DUMB_VGA
> +	tristate "Dumb RGB to VGA Bridge support"
> +	select DRM_KMS_HELPER
> +	help
> +	  Support for passive RGB to VGA bridges
> +
>  config DRM_DW_HDMI
>  	tristate
>  	select DRM_KMS_HELPER
> diff --git a/drivers/gpu/drm/bridge/Makefile
> b/drivers/gpu/drm/bridge/Makefile index 96b13b30e6ab..63f21120e8f8 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -1,6 +1,7 @@
>  ccflags-y := -Iinclude/drm
> 
>  obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
> +obj-$(CONFIG_DRM_DUMB_VGA) += dumb-vga.o
>  obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
>  obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
>  obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
> diff --git a/drivers/gpu/drm/bridge/dumb-vga.c
> b/drivers/gpu/drm/bridge/dumb-vga.c new file mode 100644
> index 000000000000..2864fa535bf8
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/dumb-vga.c
> @@ -0,0 +1,186 @@
> +
> +#include <linux/module.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +
> +struct dumb_vga {
> +	struct drm_bridge	bridge;
> +	struct drm_connector	connector;
> +
> +	struct i2c_adapter	*ddc;
> +};
> +
> +static inline struct dumb_vga *
> +drm_bridge_to_dumb_vga(struct drm_bridge *bridge)
> +{
> +	return container_of(bridge, struct dumb_vga, bridge);
> +}
> +
> +static inline struct dumb_vga *
> +drm_connector_to_dumb_vga(struct drm_connector *connector)
> +{
> +	return container_of(connector, struct dumb_vga, connector);
> +}
> +
> +static int dumb_vga_get_modes(struct drm_connector *connector)
> +{
> +	struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
> +	struct edid *edid;
> +	int ret;
> +
> +	if (!vga->ddc)
> +		goto fallback;
> +
> +	edid = drm_get_edid(connector, vga->ddc);
> +	if (!edid) {
> +		DRM_INFO("EDID readout failed, falling back to standard modes\n");
> +		goto fallback;
> +	}
> +
> +	drm_mode_connector_update_edid_property(connector, edid);
> +	return drm_add_edid_modes(connector, edid);
> +
> +fallback:
> +	/*
> +	 * In case we cannot retrieve the EDIDs (broken or missing i2c
> +	 * bus), fallback on the XGA standards
> +	 */
> +	ret = drm_add_modes_noedid(connector, 1920, 1200);

The DRM core adds modes up to 1024x768 in 
drm_helper_probe_single_connector_modes(). I wonder if it really makes sense 
to override that in drivers, compared to increasing the maximum resolution in 
the core. What we can reasonable expect from a VGA monitor doesn't really 
depend on which display engine it is connected to.

> +	/* And prefer a mode pretty much anyone can handle */
> +	drm_set_preferred_mode(connector, 1024, 768);
> +
> +	return ret;
> +}
> +
> +static struct drm_encoder *
> +dumb_vga_best_encoder(struct drm_connector *connector)
> +{
> +	struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
> +
> +	return vga->bridge.encoder;
> +}
> +
> +static struct drm_connector_helper_funcs dumb_vga_con_helper_funcs = {
> +	.get_modes	= dumb_vga_get_modes,
> +	.best_encoder	= dumb_vga_best_encoder,
> +};
> +
> +static enum drm_connector_status
> +dumb_vga_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	return connector_status_connected;

Shouldn't that be connector_status_unknown if you have no information about 
the connection status ?

Would it make sense to add an optional GPIO-based connection detection to this 
driver ?

> +}
> +
> +static void
> +dumb_vga_connector_destroy(struct drm_connector *connector)
> +{
> +	drm_connector_cleanup(connector);
> +}
> +
> +static struct drm_connector_funcs dumb_vga_con_funcs = {
> +	.dpms			= drm_atomic_helper_connector_dpms,
> +	.detect			= dumb_vga_connector_detect,
> +	.fill_modes		= drm_helper_probe_single_connector_modes,
> +	.destroy		= dumb_vga_connector_destroy,
> +	.reset			= drm_atomic_helper_connector_reset,
> +	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int dumb_vga_attach(struct drm_bridge *bridge)
> +{
> +	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
> +	int ret;
> +
> +	if (!bridge->encoder) {
> +		DRM_ERROR("Missing encoder\n");
> +		return -ENODEV;
> +	}
> +
> +	drm_connector_helper_add(&vga->connector,
> +				 &dumb_vga_con_helper_funcs);
> +	ret = drm_connector_init(bridge->dev, &vga->connector,
> +				 &dumb_vga_con_funcs, DRM_MODE_CONNECTOR_VGA);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize connector\n");
> +		return ret;
> +	}
> +
> +	drm_mode_connector_attach_encoder(&vga->connector,
> +					  bridge->encoder);
> +
> +	return 0;
> +}
> +
> +static void dumb_vga_nop(struct drm_bridge *bridge) {};
> +
> +static struct drm_bridge_funcs dumb_vga_bridge_funcs = {
> +	.attach		= dumb_vga_attach,
> +	.enable		= dumb_vga_nop,
> +	.disable	= dumb_vga_nop,
> +	.pre_enable	= dumb_vga_nop,
> +	.post_disable	= dumb_vga_nop,
> +};
> +
> +static int dumb_vga_probe(struct platform_device *pdev)
> +{
> +	struct dumb_vga *vga;
> +	struct device_node *ddc;
> +
> +	vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL);
> +	if (!vga)
> +		return -ENOMEM;
> +	platform_set_drvdata(pdev, vga);
> +
> +	ddc = of_parse_phandle(pdev->dev.of_node, "ddc-i2c-bus", 0);
> +	if (ddc) {
> +		vga->ddc = of_find_i2c_adapter_by_node(ddc);

You're leaking the reference to the I2C adapter.

Also, shouldn't you use of_get_i2c_adapter_by_node() ? Otherwise you won't 
take a reference to the adapter module.

> +		of_node_put(ddc);
> +
> +		if (!vga->ddc) {
> +			dev_err(&pdev->dev, "Couldn't retrieve i2c bus\n");
> +			return -EPROBE_DEFER;
> +		}
> +	} else {
> +		dev_info(&pdev->dev,
> +			 "No i2c bus specified... Disabling EDID readout\n");
> +	}
> +
> +	vga->bridge.funcs = &dumb_vga_bridge_funcs;
> +	vga->bridge.of_node = pdev->dev.of_node;
> +
> +	return drm_bridge_add(&vga->bridge);
> +}
> +
> +static int dumb_vga_remove(struct platform_device *pdev)
> +{
> +	struct dumb_vga *vga = platform_get_drvdata(pdev);
> +
> +	drm_bridge_remove(&vga->bridge);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id dumb_vga_match[] = {
> +	{ .compatible = "dumb-vga-bridge" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, dumb_vga_match);
> +
> +struct platform_driver dumb_vga_driver = {
> +	.probe	= dumb_vga_probe,
> +	.remove	= dumb_vga_remove,
> +	.driver		= {
> +		.name		= "dumb-vga-bridge",
> +		.of_match_table	= dumb_vga_match,
> +	},
> +};
> +module_platform_driver(dumb_vga_driver);
> +
> +MODULE_AUTHOR("Maxime Ripard <maxime.ripard at free-electrons.com>");
> +MODULE_DESCRIPTION("Dumb RGB to VGA bridge driver");
> +MODULE_LICENSE("GPL");

-- 
Regards,

Laurent Pinchart



From moinejf at free.fr  Mon May 16 06:47:39 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Mon, 16 May 2016 15:47:39 +0200
Subject: [PATCH 15/16] clk: sunxi-ng: Add H3 clocks
In-Reply-To: <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <20160516154739.d87e0a9891a7fb5fed051a89@free.fr>

On Sun,  8 May 2016 22:01:50 +0200
Maxime Ripard <maxime.ripard at free-electrons.com> wrote:

> Add the list of clocks and resets found in the H3 CCU.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile        |   2 +
>  drivers/clk/sunxi-ng/ccu-sun8i-h3.c  | 757 +++++++++++++++++++++++++++++++++++
>  include/dt-bindings/clock/sun8i-h3.h | 162 ++++++++
>  include/dt-bindings/reset/sun8i-h3.h | 103 +++++
>  4 files changed, 1024 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.c
>  create mode 100644 include/dt-bindings/clock/sun8i-h3.h
>  create mode 100644 include/dt-bindings/reset/sun8i-h3.h
> 
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index c794f57b6fb1..67ff6a92f124 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -13,3 +13,5 @@ obj-y += ccu_nkmp.o
>  obj-y += ccu_nm.o
>  obj-y += ccu_p.o
>  obj-y += ccu_phase.o
> +
> +obj-y += ccu-sun8i-h3.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> new file mode 100644
> index 000000000000..5ce699e95c32
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> @@ -0,0 +1,757 @@
	[snip]
> +static struct ccu_nm pll_audio_base_clk = {
> +	.enable		= BIT(31),
> +	.lock		= BIT(28),
> +
> +	.m		= SUNXI_CLK_FACTOR(0, 5),
> +	.n		= SUNXI_CLK_FACTOR(8, 7),
> +
> +	.common		= {
> +		.reg		= 0x008,
> +		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> +		.hw.init	= SUNXI_HW_INIT("pll-audio-base",
> +						"osc24M",
> +						&ccu_nm_ops,
> +						0),
> +	},
> +};
> +
> +static SUNXI_CCU_M(pll_audio_clk, "pll-audio", "pll-audio-base",
> +		   0x008, 16, 4, 0);
> +
> +static SUNXI_CCU_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
> +			      "pll-audio-base", 2, 1, 0);
> +static SUNXI_CCU_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
> +			      "pll-audio-base", 1, 1, 0);
> +static SUNXI_CCU_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
> +			      "pll-audio-base", 1, 2, 0);
> +
	[snip]

The pll-audio-{2,4,8}x clocks lack the CLK_SET_RATE_PARENT.

Also, in my implementation of the sound on HDMI, I set pll-audio as the
parent of the i2s2 clock. Then, as the pll-audio clock is defined here,
setting its rate is always wrong (only 'M' is changed, and with a bad
value - BTW, DIV_ROUND_UP would be welcome in ccu_m_find_best()).

As the pre-divider 'M' is set to 4 by default, there is no need to
change it. Then, audio works fine for me with:

static SUNXI_CCU_FIXED_FACTOR(pll_audio, "pll-audio",
			      "pll-audio-base", 4, 1,
				CLK_SET_RATE_PARENT);

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From robh+dt at kernel.org  Mon May 16 07:07:18 2016
From: robh+dt at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 09:07:18 -0500
Subject: [PATCH 13/20] drm/bridge: Add RGB to VGA bridge support
In-Reply-To: <1463402840-17062-14-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-14-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAL_JsqKMJ7X2MU7vF9n7_MmAUQJ2v+yKyazcmMurgbTxYGfw_Q@mail.gmail.com>

On Mon, May 16, 2016 at 7:47 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Some boards have an entirely passive RGB to VGA bridge, based on either
> DACs or resistor ladders.
>
> Those might or might not have an i2c bus routed to the VGA connector in
> order to access the screen EDIDs.
>
> Add a bridge that doesn't do anything but expose the modes available on the
> screen, either based on the EDIDs if available, or based on the XGA
> standards.
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  .../bindings/display/bridge/dumb-vga.txt           |  40 +++++
>  drivers/gpu/drm/bridge/Kconfig                     |   6 +
>  drivers/gpu/drm/bridge/Makefile                    |   1 +
>  drivers/gpu/drm/bridge/dumb-vga.c                  | 186 +++++++++++++++++++++
>  4 files changed, 233 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
>  create mode 100644 drivers/gpu/drm/bridge/dumb-vga.c
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
> new file mode 100644
> index 000000000000..757f04de97f3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
> @@ -0,0 +1,40 @@
> +Passive RGB to VGA bridge
> +-------------------------
> +
> +This binding is aimed for entirely passive RGB to VGA bridges that do not
> +require any configuration.

No reset or enable lines or regulators?

> +
> +Required properties:
> +
> +- compatible: Should be "dumb-vga-bridge"
> +
> +Optional properties:
> +
> +- ddc-i2c-bus: phandle to the i2c bus used to communicate with the monitor

The i2c bus is a property of the connector, not the bridge chip, so it
belongs in a VGA connector node (which we already have binding for).

I think for the really "dumb" (or transparent case), you should only
have a connector. For anything more complex, then you should have both
a DAC and connector node.

On the driver side, I think we could handle multiple connectors with a
single driver. Ideally, that would work with any DRM driver that has a
connector node.

> +
> +Required nodes:
> +
> +This device has one video port. Its connection is modelled using the OF
> +graph bindings specified in Documentation/devicetree/bindings/graph.txt. This
> +connection is meant to be the RGB input bus.
> +
> +
> +Example
> +-------
> +
> +bridge {
> +        compatible = "dumb-vga-bridge";
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        port at 0 {
> +                reg = <0>;
> +                #address-cells = <1>;
> +                #size-cells = <0>;
> +
> +                vga_input: endpoint at 0 {
> +                        reg = <0>;
> +                        remote-endpoint = <&tcon0_out_vga>;
> +               };
> +        };
> +};


From david.wu at rock-chips.com  Mon May 16 06:57:35 2016
From: david.wu at rock-chips.com (David Wu)
Date: Mon, 16 May 2016 21:57:35 +0800
Subject: [PATCH v10 0/8] add i2c driver supported for rk3399
Message-ID: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>

There are three points differert from others:
 - new method to caculate i2c timings for rk3399
 - pclk and function clk are separated at rk3399
 - add fast-plus mode supported for rk3399

David Wu (8):
  i2c: rk3x: add documentation to fields in "struct rk3x_i2c"
  i2c: rk3x: use struct "rk3x_i2c_calced_timings"
  i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd()
  i2c: rk3x: Change SoC data to not use array
  i2c: rk3x: Move spec timing data to "static const" structs
  dt-bindings: i2c: rk3x: add support for rk3399
  i2c: rk3x: add i2c support for rk3399 soc
  i2c: rk3x: support fast-mode plus for rk3399

 Documentation/devicetree/bindings/i2c/i2c-rk3x.txt |  16 +-
 drivers/i2c/busses/i2c-rk3x.c                      | 498 +++++++++++++++++----
 2 files changed, 434 insertions(+), 80 deletions(-)

-- 
1.9.1




From david.wu at rock-chips.com  Mon May 16 06:57:36 2016
From: david.wu at rock-chips.com (David Wu)
Date: Mon, 16 May 2016 21:57:36 +0800
Subject: [PATCH v10 1/8] i2c: rk3x: add documentation to fields in "struct
 rk3x_i2c"
In-Reply-To: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
References: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463407063-41218-2-git-send-email-david.wu@rock-chips.com>

Add kernel-doc documentation for the elements of the previously
undocumented struct rk3x_i2c.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Heiko Stuebner <heiko at sntech.de>
Tested-by: Heiko Stuebner <heiko at sntech.de>
---
Change in v10:
- none

Change in v9:
- add commit description.

Change in v8:
- none

 drivers/i2c/busses/i2c-rk3x.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 80bed02..7e45d51 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -90,6 +90,26 @@ struct rk3x_i2c_soc_data {
 	int grf_offset;
 };
 
+/**
+ * struct rk3x_i2c - private data of the controller
+ * @adap: corresponding I2C adapter
+ * @dev: device for this controller
+ * @soc_data: related soc data struct
+ * @regs: virtual memory area
+ * @clk: clock of i2c bus
+ * @clk_rate_nb: i2c clk rate change notify
+ * @t: I2C known timing information
+ * @lock: spinlock for the i2c bus
+ * @wait: the waitqueue to wait for i2c transfer
+ * @busy: the condition for the event to wait for
+ * @msg: current i2c message
+ * @addr: addr of i2c slave device
+ * @mode: mode of i2c transfer
+ * @is_last_msg: flag determines whether it is the last msg in this transfer
+ * @state: state of i2c transfer
+ * @processed: byte length which has been send or received
+ * @error: error code for i2c transfer
+ */
 struct rk3x_i2c {
 	struct i2c_adapter adap;
 	struct device *dev;
@@ -116,7 +136,7 @@ struct rk3x_i2c {
 
 	/* I2C state machine */
 	enum rk3x_i2c_state state;
-	unsigned int processed; /* sent/received bytes */
+	unsigned int processed;
 	int error;
 };
 
-- 
1.9.1




From david.wu at rock-chips.com  Mon May 16 06:57:37 2016
From: david.wu at rock-chips.com (David Wu)
Date: Mon, 16 May 2016 21:57:37 +0800
Subject: [PATCH v10 2/8] i2c: rk3x: use struct "rk3x_i2c_calced_timings"
In-Reply-To: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
References: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463407063-41218-3-git-send-email-david.wu@rock-chips.com>

The "div_high" and "div_low" values are always used together.
Group them into a structure to make it easier to pass them
both around. This structure also provides a place for future
calculated timings.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Tested-by: Heiko Stuebner <heiko at sntech.de>
---
Change in v10:
- none

Change in v9:
- none

Change in v8:
- add commit description.

 drivers/i2c/busses/i2c-rk3x.c | 55 +++++++++++++++++++++++++------------------
 1 file changed, 32 insertions(+), 23 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 7e45d51..1e2677a 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -75,6 +75,16 @@ enum {
 #define WAIT_TIMEOUT      1000 /* ms */
 #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */
 
+/**
+ * struct rk3x_i2c_calced_timings:
+ * @div_low: Divider output for low
+ * @div_high: Divider output for high
+ */
+struct rk3x_i2c_calced_timings {
+	unsigned long div_low;
+	unsigned long div_high;
+};
+
 enum rk3x_i2c_state {
 	STATE_IDLE,
 	STATE_START,
@@ -454,9 +464,8 @@ out:
  * Calculate divider values for desired SCL frequency
  *
  * @clk_rate: I2C input clock rate
- * @t: Known I2C timing information.
- * @div_low: Divider output for low
- * @div_high: Divider output for high
+ * @t: Known I2C timing information
+ * @t_calc: Caculated rk3x private timings that would be written into regs
  *
  * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
  * a best-effort divider value is returned in divs. If the target rate is
@@ -464,8 +473,7 @@ out:
  */
 static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 			      struct i2c_timings *t,
-			      unsigned long *div_low,
-			      unsigned long *div_high)
+			      struct rk3x_i2c_calced_timings *t_calc)
 {
 	unsigned long spec_min_low_ns, spec_min_high_ns;
 	unsigned long spec_setup_start, spec_max_data_hold_ns;
@@ -572,8 +580,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 		 * Time needed to meet hold requirements is important.
 		 * Just use that.
 		 */
-		*div_low = min_low_div;
-		*div_high = min_high_div;
+		t_calc->div_low = min_low_div;
+		t_calc->div_high = min_high_div;
 	} else {
 		/*
 		 * We've got to distribute some time among the low and high
@@ -602,25 +610,25 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 
 		/* Give low the "ideal" and give high whatever extra is left */
 		extra_low_div = ideal_low_div - min_low_div;
-		*div_low = ideal_low_div;
-		*div_high = min_high_div + (extra_div - extra_low_div);
+		t_calc->div_low = ideal_low_div;
+		t_calc->div_high = min_high_div + (extra_div - extra_low_div);
 	}
 
 	/*
 	 * Adjust to the fact that the hardware has an implicit "+1".
 	 * NOTE: Above calculations always produce div_low > 0 and div_high > 0.
 	 */
-	*div_low = *div_low - 1;
-	*div_high = *div_high - 1;
+	t_calc->div_low--;
+	t_calc->div_high--;
 
 	/* Maximum divider supported by hw is 0xffff */
-	if (*div_low > 0xffff) {
-		*div_low = 0xffff;
+	if (t_calc->div_low > 0xffff) {
+		t_calc->div_low = 0xffff;
 		ret = -EINVAL;
 	}
 
-	if (*div_high > 0xffff) {
-		*div_high = 0xffff;
+	if (t_calc->div_high > 0xffff) {
+		t_calc->div_high = 0xffff;
 		ret = -EINVAL;
 	}
 
@@ -630,19 +638,21 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
 {
 	struct i2c_timings *t = &i2c->t;
-	unsigned long div_low, div_high;
+	struct rk3x_i2c_calced_timings calc;
 	u64 t_low_ns, t_high_ns;
 	int ret;
 
-	ret = rk3x_i2c_calc_divs(clk_rate, t, &div_low, &div_high);
+	ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
 	WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
 
 	clk_enable(i2c->clk);
-	i2c_writel(i2c, (div_high << 16) | (div_low & 0xffff), REG_CLKDIV);
+	i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
+		   REG_CLKDIV);
 	clk_disable(i2c->clk);
 
-	t_low_ns = div_u64(((u64)div_low + 1) * 8 * 1000000000, clk_rate);
-	t_high_ns = div_u64(((u64)div_high + 1) * 8 * 1000000000, clk_rate);
+	t_low_ns = div_u64(((u64)calc.div_low + 1) * 8 * 1000000000, clk_rate);
+	t_high_ns = div_u64(((u64)calc.div_high + 1) * 8 * 1000000000,
+			    clk_rate);
 	dev_dbg(i2c->dev,
 		"CLK %lukhz, Req %uns, Act low %lluns high %lluns\n",
 		clk_rate / 1000,
@@ -672,12 +682,11 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
 {
 	struct clk_notifier_data *ndata = data;
 	struct rk3x_i2c *i2c = container_of(nb, struct rk3x_i2c, clk_rate_nb);
-	unsigned long div_low, div_high;
+	struct rk3x_i2c_calced_timings calc;
 
 	switch (event) {
 	case PRE_RATE_CHANGE:
-		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t,
-				       &div_low, &div_high) != 0)
+		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &calc) != 0)
 			return NOTIFY_STOP;
 
 		/* scale up */
-- 
1.9.1




From david.wu at rock-chips.com  Mon May 16 06:57:38 2016
From: david.wu at rock-chips.com (David Wu)
Date: Mon, 16 May 2016 21:57:38 +0800
Subject: [PATCH v10 3/8] i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd()
In-Reply-To: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
References: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463407063-41218-4-git-send-email-david.wu@rock-chips.com>

rk3x_i2c_setup() gets called directly before rk3x_i2c_start(),
and the last thing in setup was to clean the IPD, so no reason
to do it at the beginning of start.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Heiko Stuebner <heiko at sntech.de>
Tested-by: Heiko Stuebner <heiko at sntech.de>
---
Change in v10:
- none

Change in v9:
- modify commit message

Change in v8:
- none

 drivers/i2c/busses/i2c-rk3x.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 1e2677a..9eeb4e5 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -174,7 +174,6 @@ static void rk3x_i2c_start(struct rk3x_i2c *i2c)
 {
 	u32 val;
 
-	rk3x_i2c_clean_ipd(i2c);
 	i2c_writel(i2c, REG_INT_START, REG_IEN);
 
 	/* enable adapter with correct mode, send START condition */
-- 
1.9.1




From david.wu at rock-chips.com  Mon May 16 06:57:39 2016
From: david.wu at rock-chips.com (David Wu)
Date: Mon, 16 May 2016 21:57:39 +0800
Subject: [PATCH v10 4/8] i2c: rk3x: Change SoC data to not use array
In-Reply-To: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
References: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463407063-41218-5-git-send-email-david.wu@rock-chips.com>

Specifying the i2c SoC data in an array provides very little benefit and
gets unwieldly / confusing as the array grows since the next bit of code
needs to refer to elements in the array by their raw integral index.

Let's just create a single 'static const' structure for each SoC so that
we can refer to these structures by ID.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Heiko Stuebner <heiko at sntech.de>
Suggested-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Tested-by: Heiko Stuebner <heiko at sntech.de>
---
Change in v10:
- none

Change in v9:
- none

Change in v8:
- add commit description.

 drivers/i2c/busses/i2c-rk3x.c | 38 ++++++++++++++++++++++++++++++--------
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 9eeb4e5..d7a871f 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -864,17 +864,39 @@ static const struct i2c_algorithm rk3x_i2c_algorithm = {
 	.functionality		= rk3x_i2c_func,
 };
 
-static struct rk3x_i2c_soc_data soc_data[3] = {
-	{ .grf_offset = 0x154 }, /* rk3066 */
-	{ .grf_offset = 0x0a4 }, /* rk3188 */
-	{ .grf_offset = -1 },    /* no I2C switching needed */
+static const struct rk3x_i2c_soc_data rk3066_soc_data = {
+	.grf_offset = 0x154,
+};
+
+static const struct rk3x_i2c_soc_data rk3188_soc_data = {
+	.grf_offset = 0x0a4,
+};
+
+static const struct rk3x_i2c_soc_data rk3228_soc_data = {
+	.grf_offset = -1,
+};
+
+static const struct rk3x_i2c_soc_data rk3288_soc_data = {
+	.grf_offset = -1,
 };
 
 static const struct of_device_id rk3x_i2c_match[] = {
-	{ .compatible = "rockchip,rk3066-i2c", .data = (void *)&soc_data[0] },
-	{ .compatible = "rockchip,rk3188-i2c", .data = (void *)&soc_data[1] },
-	{ .compatible = "rockchip,rk3228-i2c", .data = (void *)&soc_data[2] },
-	{ .compatible = "rockchip,rk3288-i2c", .data = (void *)&soc_data[2] },
+	{
+		.compatible = "rockchip,rk3066-i2c",
+		.data = (void *)&rk3066_soc_data
+	},
+	{
+		.compatible = "rockchip,rk3188-i2c",
+		.data = (void *)&rk3188_soc_data
+	},
+	{
+		.compatible = "rockchip,rk3228-i2c",
+		.data = (void *)&rk3228_soc_data
+	},
+	{
+		.compatible = "rockchip,rk3288-i2c",
+		.data = (void *)&rk3288_soc_data
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, rk3x_i2c_match);
-- 
1.9.1




From david.wu at rock-chips.com  Mon May 16 07:03:24 2016
From: david.wu at rock-chips.com (David Wu)
Date: Mon, 16 May 2016 22:03:24 +0800
Subject: [PATCH v10 5/8] i2c: rk3x: Move spec timing data to "static const"
 structs
In-Reply-To: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
References: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463407404-41370-1-git-send-email-david.wu@rock-chips.com>

The i2c timing specs are really just constant data. There's no reason
to write code to init them, so move them out to structures. This not
only is a cleaner solution but it will reduce code duplication when we
introduce a new variant of rk3x_i2c_calc_divs() in a future patch.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Suggested-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Tested-by: Heiko Stuebner <heiko at sntech.de>
---
Change in v10:
- none

Change in v9:
- none

Changes in v8:
- add commit description.
- remove the spec values that were not needed, then
  introduce the additional values in the rk3399 patch. 

 drivers/i2c/busses/i2c-rk3x.c | 83 ++++++++++++++++++++++++++++---------------
 1 file changed, 55 insertions(+), 28 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index d7a871f..9791797 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -76,6 +76,34 @@ enum {
 #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */
 
 /**
+ * struct i2c_spec_values:
+ * @min_low_ns: min LOW period of the SCL clock
+ * @min_high_ns: min HIGH period of the SCL cloc
+ * @min_setup_start_ns: min set-up time for a repeated START conditio
+ * @max_data_hold_ns: max data hold time
+ */
+struct i2c_spec_values {
+	unsigned long min_low_ns;
+	unsigned long min_high_ns;
+	unsigned long min_setup_start_ns;
+	unsigned long max_data_hold_ns;
+};
+
+static const struct i2c_spec_values standard_mode_spec = {
+	.min_low_ns = 4700,
+	.min_high_ns = 4000,
+	.min_setup_start_ns = 4700,
+	.max_data_hold_ns = 3450,
+};
+
+static const struct i2c_spec_values fast_mode_spec = {
+	.min_low_ns = 1300,
+	.min_high_ns = 600,
+	.min_setup_start_ns = 600,
+	.max_data_hold_ns = 900,
+};
+
+/**
  * struct rk3x_i2c_calced_timings:
  * @div_low: Divider output for low
  * @div_high: Divider output for high
@@ -460,6 +488,21 @@ out:
 }
 
 /**
+ * Get timing values of I2C specification
+ *
+ * @speed: Desired SCL frequency
+ *
+ * Returns: Matched i2c spec values.
+ */
+static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
+{
+	if (speed <= 100000)
+		return &standard_mode_spec;
+	else
+		return &fast_mode_spec;
+}
+
+/**
  * Calculate divider values for desired SCL frequency
  *
  * @clk_rate: I2C input clock rate
@@ -474,10 +517,6 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 			      struct i2c_timings *t,
 			      struct rk3x_i2c_calced_timings *t_calc)
 {
-	unsigned long spec_min_low_ns, spec_min_high_ns;
-	unsigned long spec_setup_start, spec_max_data_hold_ns;
-	unsigned long data_hold_buffer_ns;
-
 	unsigned long min_low_ns, min_high_ns;
 	unsigned long max_low_ns, min_total_ns;
 
@@ -489,6 +528,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	unsigned long min_div_for_hold, min_total_div;
 	unsigned long extra_div, extra_low_div, ideal_low_div;
 
+	unsigned long data_hold_buffer_ns = 50;
+	const struct i2c_spec_values *spec;
 	int ret = 0;
 
 	/* Only support standard-mode and fast-mode */
@@ -511,22 +552,8 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	 *	 This is because the i2c host on Rockchip holds the data line
 	 *	 for half the low time.
 	 */
-	if (t->bus_freq_hz <= 100000) {
-		/* Standard-mode */
-		spec_min_low_ns = 4700;
-		spec_setup_start = 4700;
-		spec_min_high_ns = 4000;
-		spec_max_data_hold_ns = 3450;
-		data_hold_buffer_ns = 50;
-	} else {
-		/* Fast-mode */
-		spec_min_low_ns = 1300;
-		spec_setup_start = 600;
-		spec_min_high_ns = 600;
-		spec_max_data_hold_ns = 900;
-		data_hold_buffer_ns = 50;
-	}
-	min_high_ns = t->scl_rise_ns + spec_min_high_ns;
+	spec = rk3x_i2c_get_spec(t->bus_freq_hz);
+	min_high_ns = t->scl_rise_ns + spec->min_high_ns;
 
 	/*
 	 * Timings for repeated start:
@@ -536,14 +563,14 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	 * We need to account for those rules in picking our "high" time so
 	 * we meet tSU;STA and tHD;STA times.
 	 */
-	min_high_ns = max(min_high_ns,
-		DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start) * 1000, 875));
-	min_high_ns = max(min_high_ns,
-		DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start +
-			      t->sda_fall_ns + spec_min_high_ns), 2));
-
-	min_low_ns = t->scl_fall_ns + spec_min_low_ns;
-	max_low_ns = spec_max_data_hold_ns * 2 - data_hold_buffer_ns;
+	min_high_ns = max(min_high_ns, DIV_ROUND_UP(
+		(t->scl_rise_ns + spec->min_setup_start_ns) * 1000, 875));
+	min_high_ns = max(min_high_ns, DIV_ROUND_UP(
+		(t->scl_rise_ns + spec->min_setup_start_ns + t->sda_fall_ns +
+		spec->min_high_ns), 2));
+
+	min_low_ns = t->scl_fall_ns + spec->min_low_ns;
+	max_low_ns =  spec->max_data_hold_ns * 2 - data_hold_buffer_ns;
 	min_total_ns = min_low_ns + min_high_ns;
 
 	/* Adjust to avoid overflow */
-- 
1.9.1




From david.wu at rock-chips.com  Mon May 16 07:04:12 2016
From: david.wu at rock-chips.com (David Wu)
Date: Mon, 16 May 2016 22:04:12 +0800
Subject: [PATCH v10 6/8] dt-bindings: i2c: rk3x: add support for rk3399
In-Reply-To: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
References: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463407452-41418-1-git-send-email-david.wu@rock-chips.com>

The bus clock and function clock are separated at rk3399,
and others use one clock as the bus clock and function clock.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Reviewed-by: Heiko Stuebner <heiko at sntech.de>
Tested-by: Heiko Stuebner <heiko at sntech.de>
---
Change in v10:
- none

Change in v9:
- remove unnecessary "REQUIRED".

Change in v8:
- remove error description.

 Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
index 0b4a85f..bbc5a1e 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt
@@ -6,10 +6,20 @@ RK3xxx SoCs.
 Required properties :
 
  - reg : Offset and length of the register set for the device
- - compatible : should be "rockchip,rk3066-i2c", "rockchip,rk3188-i2c",
-		"rockchip,rk3228-i2c" or "rockchip,rk3288-i2c".
+ - compatible: should be one of the following:
+   - "rockchip,rk3066-i2c": for rk3066
+   - "rockchip,rk3188-i2c": for rk3188
+   - "rockchip,rk3228-i2c": for rk3228
+   - "rockchip,rk3288-i2c": for rk3288
+   - "rockchip,rk3399-i2c": for rk3399
  - interrupts : interrupt number
- - clocks : parent clock
+ - clocks: See ../clock/clock-bindings.txt
+   - For older hardware (rk3066, rk3188, rk3228, rk3288):
+     - There is one clock that's used both to derive the functional clock
+       for the device and as the bus clock.
+   - For newer hardware (rk3399): specified by name
+     - "i2c": This is used to derive the functional clock.
+     - "pclk": This is the bus clock.
 
 Required on RK3066, RK3188 :
 
-- 
1.9.1




From david.wu at rock-chips.com  Mon May 16 07:05:03 2016
From: david.wu at rock-chips.com (David Wu)
Date: Mon, 16 May 2016 22:05:03 +0800
Subject: [PATCH v10 7/8] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
References: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463407503-41466-1-git-send-email-david.wu@rock-chips.com>

- new method to caculate i2c timings for rk3399:
  There was an timing issue about "repeated start" time at the I2C
  controller of version0, controller appears to drop SDA at .875x (7/8)
  programmed clk high. On version 1 of the controller, the rule(.875x)
  isn't enough to meet tSU;STA
  requirements on 100k's Standard-mode. To resolve this issue,
  sda_update_config, start_setup_config and stop_setup_config for I2C
  timing information are added, new rules are designed to calculate
  the timing information at new v1.
- pclk and function clk are separated at rk3399

Signed-off-by: David Wu <david.wu at rock-chips.com>
Tested-by: Caesar Wang <wxt at rock-chips.com>
Tested-by: Heiko Stuebner <heiko at sntech.de>
---
Change in v10:
- fix the clean of con register in rk3x_i2c_stop()

Change in v9:
- add spin lock for tuning updated in rk3x_i2c_adapt_div() (Doug) 

Changes in v8:
- update tuning in RKI2C_CON register by doing a read-modify-write (Doug)
- new method to use pclk and clk (Doug)

Changes in v7:
- transform into a 9 series patches (Doug)
- drop highspeed with mastercode, and support fast-mode plus (Doug)

 drivers/i2c/busses/i2c-rk3x.c | 294 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 274 insertions(+), 20 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 9791797..a96b516 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -58,6 +58,12 @@ enum {
 #define REG_CON_LASTACK   BIT(5) /* 1: send NACK after last received byte */
 #define REG_CON_ACTACK    BIT(6) /* 1: stop if NACK is received */
 
+#define REG_CON_TUNING_MASK GENMASK(15, 8)
+
+#define REG_CON_SDA_CFG(cfg) ((cfg) << 8)
+#define REG_CON_STA_CFG(cfg) ((cfg) << 12)
+#define REG_CON_STO_CFG(cfg) ((cfg) << 14)
+
 /* REG_MRXADDR bits */
 #define REG_MRXADDR_VALID(x) BIT(24 + (x)) /* [x*8+7:x*8] of MRX[R]ADDR valid */
 
@@ -77,40 +83,62 @@ enum {
 
 /**
  * struct i2c_spec_values:
+ * @min_hold_start_ns: min hold time (repeated) START condition
  * @min_low_ns: min LOW period of the SCL clock
  * @min_high_ns: min HIGH period of the SCL cloc
  * @min_setup_start_ns: min set-up time for a repeated START conditio
  * @max_data_hold_ns: max data hold time
+ * @min_data_setup_ns: min data set-up time
+ * @min_setup_stop_ns: min set-up time for STOP condition
+ * @min_hold_buffer_ns: min bus free time between a STOP and
+ * START condition
  */
 struct i2c_spec_values {
+	unsigned long min_hold_start_ns;
 	unsigned long min_low_ns;
 	unsigned long min_high_ns;
 	unsigned long min_setup_start_ns;
 	unsigned long max_data_hold_ns;
+	unsigned long min_data_setup_ns;
+	unsigned long min_setup_stop_ns;
+	unsigned long min_hold_buffer_ns;
 };
 
 static const struct i2c_spec_values standard_mode_spec = {
+	.min_hold_start_ns = 4000,
 	.min_low_ns = 4700,
 	.min_high_ns = 4000,
 	.min_setup_start_ns = 4700,
 	.max_data_hold_ns = 3450,
+	.min_data_setup_ns = 250,
+	.min_setup_stop_ns = 4000,
+	.min_hold_buffer_ns = 4700,
 };
 
 static const struct i2c_spec_values fast_mode_spec = {
+	.min_hold_start_ns = 600,
 	.min_low_ns = 1300,
 	.min_high_ns = 600,
 	.min_setup_start_ns = 600,
 	.max_data_hold_ns = 900,
+	.min_data_setup_ns = 100,
+	.min_setup_stop_ns = 600,
+	.min_hold_buffer_ns = 1300,
 };
 
 /**
  * struct rk3x_i2c_calced_timings:
  * @div_low: Divider output for low
  * @div_high: Divider output for high
+ * @tuning: Used to adjust setup/hold data time,
+ * setup/hold start time and setup stop time for
+ * v1's calc_timings, the tuning should all be 0
+ * for old hardware anyone using v0's calc_timings.
  */
 struct rk3x_i2c_calced_timings {
 	unsigned long div_low;
 	unsigned long div_high;
+	unsigned int tuning;
 };
 
 enum rk3x_i2c_state {
@@ -123,9 +151,12 @@ enum rk3x_i2c_state {
 
 /**
  * @grf_offset: offset inside the grf regmap for setting the i2c type
+ * @calc_timings: Callback function for i2c timing information calculated
  */
 struct rk3x_i2c_soc_data {
 	int grf_offset;
+	int (*calc_timings)(unsigned long, struct i2c_timings *,
+			    struct rk3x_i2c_calced_timings *);
 };
 
 /**
@@ -134,7 +165,8 @@ struct rk3x_i2c_soc_data {
  * @dev: device for this controller
  * @soc_data: related soc data struct
  * @regs: virtual memory area
- * @clk: clock of i2c bus
+ * @clk: function clk for rk3399 or function & Bus clks for others
+ * @pclk: Bus clk for rk3399
  * @clk_rate_nb: i2c clk rate change notify
  * @t: I2C known timing information
  * @lock: spinlock for the i2c bus
@@ -156,6 +188,7 @@ struct rk3x_i2c {
 	/* Hardware resources */
 	void __iomem *regs;
 	struct clk *clk;
+	struct clk *pclk;
 	struct notifier_block clk_rate_nb;
 
 	/* Settings */
@@ -200,12 +233,12 @@ static inline void rk3x_i2c_clean_ipd(struct rk3x_i2c *i2c)
  */
 static void rk3x_i2c_start(struct rk3x_i2c *i2c)
 {
-	u32 val;
+	u32 val = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK;
 
 	i2c_writel(i2c, REG_INT_START, REG_IEN);
 
 	/* enable adapter with correct mode, send START condition */
-	val = REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START;
+	val |= REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START;
 
 	/* if we want to react to NACK, set ACTACK bit */
 	if (!(i2c->msg->flags & I2C_M_IGNORE_NAK))
@@ -246,7 +279,8 @@ static void rk3x_i2c_stop(struct rk3x_i2c *i2c, int error)
 		 * get the intended effect by resetting its internal state
 		 * and issuing an ordinary START.
 		 */
-		i2c_writel(i2c, 0, REG_CON);
+		ctrl = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK;
+		i2c_writel(i2c, ctrl, REG_CON);
 
 		/* signal that we are finished with the current msg */
 		wake_up(&i2c->wait);
@@ -513,9 +547,9 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
  * a best-effort divider value is returned in divs. If the target rate is
  * too high, we silently use the highest possible rate.
  */
-static int rk3x_i2c_calc_divs(unsigned long clk_rate,
-			      struct i2c_timings *t,
-			      struct rk3x_i2c_calced_timings *t_calc)
+static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate,
+				    struct i2c_timings *t,
+				    struct rk3x_i2c_calced_timings *t_calc)
 {
 	unsigned long min_low_ns, min_high_ns;
 	unsigned long max_low_ns, min_total_ns;
@@ -661,20 +695,191 @@ static int rk3x_i2c_calc_divs(unsigned long clk_rate,
 	return ret;
 }
 
+/**
+ * Calculate timing values for desired SCL frequency
+ *
+ * @clk_rate: I2C input clock rate
+ * @t: Known I2C timing information
+ * @t_calc: Caculated rk3x private timings that would be written into regs
+ *
+ * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
+ * a best-effort divider value is returned in divs. If the target rate is
+ * too high, we silently use the highest possible rate.
+ * The following formulas are v1's method to calculate timings.
+ *
+ * l = divl + 1;
+ * h = divh + 1;
+ * s = sda_update_config + 1;
+ * u = start_setup_config + 1;
+ * p = stop_setup_config + 1;
+ * T = Tclk_i2c;
+ *
+ * tHigh = 8 * h * T;
+ * tLow = 8 * l * T;
+ *
+ * tHD;sda = (l * s + 1) * T;
+ * tSU;sda = [(8 - s) * l + 1] * T;
+ * tI2C = 8 * (l + h) * T;
+ *
+ * tSU;sta = (8h * u + 1) * T;
+ * tHD;sta = [8h * (u + 1) - 1] * T;
+ * tSU;sto = (8h * p + 1) * T;
+ */
+static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
+				    struct i2c_timings *t,
+				    struct rk3x_i2c_calced_timings *t_calc)
+{
+	unsigned long min_low_ns, min_high_ns, min_total_ns;
+	unsigned long min_setup_start_ns, min_setup_data_ns;
+	unsigned long min_setup_stop_ns, max_hold_data_ns;
+
+	unsigned long clk_rate_khz, scl_rate_khz;
+
+	unsigned long min_low_div, min_high_div;
+
+	unsigned long min_div_for_hold, min_total_div;
+	unsigned long extra_div, extra_low_div;
+	unsigned long sda_update_cfg, stp_sta_cfg, stp_sto_cfg;
+
+	const struct i2c_spec_values *spec;
+	int ret = 0;
+
+	/* Support standard-mode and fast-mode */
+	if (WARN_ON(t->bus_freq_hz > 400000))
+		t->bus_freq_hz = 400000;
+
+	/* prevent scl_rate_khz from becoming 0 */
+	if (WARN_ON(t->bus_freq_hz < 1000))
+		t->bus_freq_hz = 1000;
+
+	/*
+	 * min_low_ns: The minimum number of ns we need to hold low to
+	 *	       meet I2C specification, should include fall time.
+	 * min_high_ns: The minimum number of ns we need to hold high to
+	 *	        meet I2C specification, should include rise time.
+	 */
+	spec = rk3x_i2c_get_spec(t->bus_freq_hz);
+
+	/* calculate min-divh and min-divl */
+	clk_rate_khz = DIV_ROUND_UP(clk_rate, 1000);
+	scl_rate_khz = t->bus_freq_hz / 1000;
+	min_total_div = DIV_ROUND_UP(clk_rate_khz, scl_rate_khz * 8);
+
+	min_high_ns = t->scl_rise_ns + spec->min_high_ns;
+	min_high_div = DIV_ROUND_UP(clk_rate_khz * min_high_ns, 8 * 1000000);
+
+	min_low_ns = t->scl_fall_ns + spec->min_low_ns;
+	min_low_div = DIV_ROUND_UP(clk_rate_khz * min_low_ns, 8 * 1000000);
+
+	/*
+	 * Final divh and divl must be greater than 0, otherwise the
+	 * hardware would not output the i2c clk.
+	 */
+	min_high_div = (min_high_div < 1) ? 2 : min_high_div;
+	min_low_div = (min_low_div < 1) ? 2 : min_low_div;
+
+	/* These are the min dividers needed for min hold times. */
+	min_div_for_hold = (min_low_div + min_high_div);
+	min_total_ns = min_low_ns + min_high_ns;
+
+	/*
+	 * This is the maximum divider so we don't go over the maximum.
+	 * We don't round up here (we round down) since this is a maximum.
+	 */
+	 if (min_div_for_hold >= min_total_div) {
+		/*
+		 * Time needed to meet hold requirements is important.
+		 * Just use that.
+		 */
+		t_calc->div_low = min_low_div;
+		t_calc->div_high = min_high_div;
+	} else {
+		/*
+		 * We've got to distribute some time among the low and high
+		 * so we don't run too fast.
+		 * We'll try to split things up by the scale of min_low_div and
+		 * min_high_div, biasing slightly towards having a higher div
+		 * for low (spend more time low).
+		 */
+		extra_div = min_total_div - min_div_for_hold;
+		extra_low_div = DIV_ROUND_UP(min_low_div * extra_div,
+					     min_div_for_hold);
+
+		t_calc->div_low = min_low_div + extra_low_div;
+		t_calc->div_high = min_high_div + (extra_div - extra_low_div);
+	}
+
+	/*
+	 * calculate sda data hold count by the rules, data_upd_st:3
+	 * is a appropriate value to reduce calculated times.
+	 */
+	for (sda_update_cfg = 3; sda_update_cfg > 0; sda_update_cfg--) {
+		max_hold_data_ns =  DIV_ROUND_UP((sda_update_cfg
+						 * (t_calc->div_low) + 1)
+						 * 1000000, clk_rate_khz);
+		min_setup_data_ns =  DIV_ROUND_UP(((8 - sda_update_cfg)
+						 * (t_calc->div_low) + 1)
+						 * 1000000, clk_rate_khz);
+		if ((max_hold_data_ns < spec->max_data_hold_ns) &&
+		    (min_setup_data_ns > spec->min_data_setup_ns))
+			break;
+	}
+
+	/* calculate setup start config */
+	min_setup_start_ns = t->scl_rise_ns + spec->min_setup_start_ns;
+	stp_sta_cfg = DIV_ROUND_UP(clk_rate_khz * min_setup_start_ns
+			   - 1000000, 8 * 1000000 * (t_calc->div_high));
+
+	/* calculate setup stop config */
+	min_setup_stop_ns = t->scl_rise_ns + spec->min_setup_stop_ns;
+	stp_sto_cfg = DIV_ROUND_UP(clk_rate_khz * min_setup_stop_ns
+			   - 1000000, 8 * 1000000 * (t_calc->div_high));
+
+	t_calc->tuning = REG_CON_SDA_CFG(--sda_update_cfg) |
+			 REG_CON_STA_CFG(--stp_sta_cfg) |
+			 REG_CON_STO_CFG(--stp_sto_cfg);
+
+	t_calc->div_low--;
+	t_calc->div_high--;
+
+	/* Maximum divider supported by hw is 0xffff */
+	if (t_calc->div_low > 0xffff) {
+		t_calc->div_low = 0xffff;
+		ret = -EINVAL;
+	}
+
+	if (t_calc->div_high > 0xffff) {
+		t_calc->div_high = 0xffff;
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
 static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
 {
 	struct i2c_timings *t = &i2c->t;
 	struct rk3x_i2c_calced_timings calc;
 	u64 t_low_ns, t_high_ns;
+	unsigned long flags;
+	u32 val;
 	int ret;
 
-	ret = rk3x_i2c_calc_divs(clk_rate, t, &calc);
+	ret = i2c->soc_data->calc_timings(clk_rate, t, &calc);
 	WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
 
-	clk_enable(i2c->clk);
+	clk_enable(i2c->pclk);
+
+	spin_lock_irqsave(&i2c->lock, flags);
+	val = i2c_readl(i2c, REG_CON);
+	val &= ~REG_CON_TUNING_MASK;
+	val |= calc.tuning;
+	i2c_writel(i2c, val, REG_CON);
 	i2c_writel(i2c, (calc.div_high << 16) | (calc.div_low & 0xffff),
 		   REG_CLKDIV);
-	clk_disable(i2c->clk);
+	spin_unlock_irqrestore(&i2c->lock, flags);
+
+	clk_disable(i2c->pclk);
 
 	t_low_ns = div_u64(((u64)calc.div_low + 1) * 8 * 1000000000, clk_rate);
 	t_high_ns = div_u64(((u64)calc.div_high + 1) * 8 * 1000000000,
@@ -712,7 +917,13 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
 
 	switch (event) {
 	case PRE_RATE_CHANGE:
-		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t, &calc) != 0)
+		/*
+		 * Try the calculation (but don't store the result) ahead of
+		 * time to see if we need to block the clock change.  Timings
+		 * shouldn't actually take effect until rk3x_i2c_adapt_div().
+		 */
+		if (i2c->soc_data->calc_timings(ndata->new_rate, &i2c->t,
+						&calc) != 0)
 			return NOTIFY_STOP;
 
 		/* scale up */
@@ -822,12 +1033,14 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
 {
 	struct rk3x_i2c *i2c = (struct rk3x_i2c *)adap->algo_data;
 	unsigned long timeout, flags;
+	u32 val;
 	int ret = 0;
 	int i;
 
 	spin_lock_irqsave(&i2c->lock, flags);
 
 	clk_enable(i2c->clk);
+	clk_enable(i2c->pclk);
 
 	i2c->is_last_msg = false;
 
@@ -861,7 +1074,9 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
 
 			/* Force a STOP condition without interrupt */
 			i2c_writel(i2c, 0, REG_IEN);
-			i2c_writel(i2c, REG_CON_EN | REG_CON_STOP, REG_CON);
+			val = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK;
+			val |= REG_CON_EN | REG_CON_STOP;
+			i2c_writel(i2c, val, REG_CON);
 
 			i2c->state = STATE_IDLE;
 
@@ -875,7 +1090,9 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
 		}
 	}
 
+	clk_disable(i2c->pclk);
 	clk_disable(i2c->clk);
+
 	spin_unlock_irqrestore(&i2c->lock, flags);
 
 	return ret < 0 ? ret : num;
@@ -893,18 +1110,27 @@ static const struct i2c_algorithm rk3x_i2c_algorithm = {
 
 static const struct rk3x_i2c_soc_data rk3066_soc_data = {
 	.grf_offset = 0x154,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
 };
 
 static const struct rk3x_i2c_soc_data rk3188_soc_data = {
 	.grf_offset = 0x0a4,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
 };
 
 static const struct rk3x_i2c_soc_data rk3228_soc_data = {
 	.grf_offset = -1,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
 };
 
 static const struct rk3x_i2c_soc_data rk3288_soc_data = {
 	.grf_offset = -1,
+	.calc_timings = rk3x_i2c_v0_calc_timings,
+};
+
+static const struct rk3x_i2c_soc_data rk3399_soc_data = {
+	.grf_offset = -1,
+	.calc_timings = rk3x_i2c_v1_calc_timings,
 };
 
 static const struct of_device_id rk3x_i2c_match[] = {
@@ -924,6 +1150,10 @@ static const struct of_device_id rk3x_i2c_match[] = {
 		.compatible = "rockchip,rk3288-i2c",
 		.data = (void *)&rk3288_soc_data
 	},
+	{
+		.compatible = "rockchip,rk3399-i2c",
+		.data = (void *)&rk3399_soc_data
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, rk3x_i2c_match);
@@ -963,12 +1193,6 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 	spin_lock_init(&i2c->lock);
 	init_waitqueue_head(&i2c->wait);
 
-	i2c->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(i2c->clk)) {
-		dev_err(&pdev->dev, "cannot get clock\n");
-		return PTR_ERR(i2c->clk);
-	}
-
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	i2c->regs = devm_ioremap_resource(&pdev->dev, mem);
 	if (IS_ERR(i2c->regs))
@@ -1022,17 +1246,44 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, i2c);
 
+	if (i2c->soc_data->calc_timings == rk3x_i2c_v0_calc_timings) {
+		/* Only one clock to use for bus clock and peripheral clock */
+		i2c->clk = devm_clk_get(&pdev->dev, NULL);
+		i2c->pclk = i2c->clk;
+	} else {
+		i2c->clk = devm_clk_get(&pdev->dev, "i2c");
+		i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
+	}
+
+	if (IS_ERR(i2c->clk)) {
+		ret = PTR_ERR(i2c->clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Can't get bus clk: %d\n", ret);
+		return ret;
+	}
+	if (IS_ERR(i2c->pclk)) {
+		ret = PTR_ERR(i2c->pclk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Can't get periph clk: %d\n", ret);
+		return ret;
+	}
+
 	ret = clk_prepare(i2c->clk);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "Could not prepare clock\n");
+		dev_err(&pdev->dev, "Can't prepare bus clk: %d\n", ret);
 		return ret;
 	}
+	ret = clk_prepare(i2c->pclk);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Can't prepare periph clock: %d\n", ret);
+		goto err_clk;
+	}
 
 	i2c->clk_rate_nb.notifier_call = rk3x_i2c_clk_notifier_cb;
 	ret = clk_notifier_register(i2c->clk, &i2c->clk_rate_nb);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Unable to register clock notifier\n");
-		goto err_clk;
+		goto err_pclk;
 	}
 
 	clk_rate = clk_get_rate(i2c->clk);
@@ -1050,6 +1301,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 
 err_clk_notifier:
 	clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb);
+err_pclk:
+	clk_unprepare(i2c->pclk);
 err_clk:
 	clk_unprepare(i2c->clk);
 	return ret;
@@ -1062,6 +1315,7 @@ static int rk3x_i2c_remove(struct platform_device *pdev)
 	i2c_del_adapter(&i2c->adap);
 
 	clk_notifier_unregister(i2c->clk, &i2c->clk_rate_nb);
+	clk_unprepare(i2c->pclk);
 	clk_unprepare(i2c->clk);
 
 	return 0;
-- 
1.9.1




From david.wu at rock-chips.com  Mon May 16 07:06:29 2016
From: david.wu at rock-chips.com (David Wu)
Date: Mon, 16 May 2016 22:06:29 +0800
Subject: [PATCH v10 8/8] i2c: rk3x: support fast-mode plus for rk3399
In-Reply-To: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
References: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <1463407589-41520-1-git-send-email-david.wu@rock-chips.com>

Implement fast mode plus that allows bus speeds of up to 1MHz.

Signed-off-by: David Wu <david.wu at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Tested-by: Caesar Wang <wxt at rock-chips.com>
Reviewed-by: Heiko Stuebner <heiko at sntech.de>
Tested-by: Heiko Stuebner <heiko at sntech.de>
---
Change in v10:
- none

Change in v9:
- add commit message

Change in v8:
- none

 drivers/i2c/busses/i2c-rk3x.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index a96b516..2938616 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -126,6 +126,17 @@ static const struct i2c_spec_values fast_mode_spec = {
 	.min_hold_buffer_ns = 1300,
 };
 
+static const struct i2c_spec_values fast_mode_plus_spec = {
+	.min_hold_start_ns = 260,
+	.min_low_ns = 500,
+	.min_high_ns = 260,
+	.min_setup_start_ns = 260,
+	.max_data_hold_ns = 400,
+	.min_data_setup_ns = 50,
+	.min_setup_stop_ns = 260,
+	.min_hold_buffer_ns = 500,
+};
+
 /**
  * struct rk3x_i2c_calced_timings:
  * @div_low: Divider output for low
@@ -532,8 +543,10 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
 {
 	if (speed <= 100000)
 		return &standard_mode_spec;
-	else
+	else if (speed <= 400000)
 		return &fast_mode_spec;
+	else
+		return &fast_mode_plus_spec;
 }
 
 /**
@@ -744,9 +757,9 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
 	const struct i2c_spec_values *spec;
 	int ret = 0;
 
-	/* Support standard-mode and fast-mode */
-	if (WARN_ON(t->bus_freq_hz > 400000))
-		t->bus_freq_hz = 400000;
+	/* Support standard-mode, fast-mode and fast-mode plus */
+	if (WARN_ON(t->bus_freq_hz > 1000000))
+		t->bus_freq_hz = 1000000;
 
 	/* prevent scl_rate_khz from becoming 0 */
 	if (WARN_ON(t->bus_freq_hz < 1000))
-- 
1.9.1




From nm at ti.com  Mon May 16 07:22:46 2016
From: nm at ti.com (Nishanth Menon)
Date: Mon, 16 May 2016 09:22:46 -0500
Subject: Can not play audio with screen off
In-Reply-To: <20160515193106.GA18685@amd>
References: <20160515193106.GA18685@amd>
Message-ID: <5739D7B6.7060102@ti.com>

On 05/15/2016 02:31 PM, Pavel Machek wrote:
> Hi!
> 
> I'm playing some more with N900, this time I'd like to use it as a
> alarm clock...
> 
> And now I realized I can not, because system performance is so
> horrible with screen off that mpg123 + pulseaudio skips horribly. This
> is without tweaking serial parameters, so CPU is definitely not going
> into the idle/off modes.
> 
> Loading CPU fixes the issue (I used cat /dev/zero > /dev/null).
> 
> Hmm. And it seems to work better if I ssh in and launch mpg123
> remotely. Weird.
> 
> Kernel 4.5-rc0. Will try on different ones.
> 
> Any ideas? Is there interface to tell kernel that better performance
> is needed for a while?
> 

pm_qos cpu_dma_latency? Drivers will have to be properly instrumented
with appropriate latency values -> this will control the depth in C
states that the system will attempt. NOTE: it is a dual edged sword,
bad configurations can result in none of the C-states being entered.


-- 
Regards,
Nishanth Menon


From maxime.ripard at free-electrons.com  Mon May 16 07:45:52 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 16:45:52 +0200
Subject: [PATCH 1/1] devicetree: sunxi: Add OLinuXino Lime2 eMMC to the
 Makefile
In-Reply-To: <1463169436-6170-1-git-send-email-oliver@schinagl.nl>
References: <1463169436-6170-1-git-send-email-oliver@schinagl.nl>
Message-ID: <20160516144552.GH27618@lukather>

On Fri, May 13, 2016 at 09:57:16PM +0200, Olliver Schinagl wrote:
> commit 27dd9af6bc000ab21fd ("ARM: dts: sunxi: Add a olinuxino-lime2-emmc")
> added the new emmc equipped lime2 but forgot its Makefile.
> 
> This patch adds an entry to the Makefile.
> 
> Signed-off-by: Olliver Schinagl <oliver at schinagl.nl>

Having the version of the patch would be nice too.

Acked-by: Maxime Ripard <maxime.ripard at free-electrons.com>

Arnd, Kevin, Olof, could you apply that patch directly for 4.7?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160516/4b9a8049/attachment.sig>

From robh at kernel.org  Mon May 16 07:48:47 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 09:48:47 -0500
Subject: [PATCH 2/8] Documentation: regulator: tps65218: Update examples
In-Reply-To: <1462945691-904-3-git-send-email-j-keerthy@ti.com>
References: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
 <1462945691-904-3-git-send-email-j-keerthy@ti.com>
Message-ID: <20160516144847.GA26659@rob-hp-laptop>

On Wed, May 11, 2016 at 11:18:05AM +0530, Keerthy wrote:
> This updates the device tree according to the preferred way of parsing
> the nodes using the regulator framework.
> 
> Signed-off-by: Keerthy <j-keerthy at ti.com>
> ---
>  .../devicetree/bindings/regulator/tps65218.txt     | 87 ++++++++++++++++++----
>  1 file changed, 71 insertions(+), 16 deletions(-)

It wasn't exactly clear that the compatible string "added" here is 
already used, so it looked like you were breaking compatibility at 
first. Otherwise,

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


From robh at kernel.org  Mon May 16 07:52:57 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 09:52:57 -0500
Subject: [PATCH v2 2/2] dt-bindings: Add Oxford Semiconductor OXNAS
 pinctrl and gpio bindings
In-Reply-To: <1462952062-5316-3-git-send-email-narmstrong@baylibre.com>
References: <1462952062-5316-1-git-send-email-narmstrong@baylibre.com>
 <1462952062-5316-3-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160516145257.GA31044@rob-hp-laptop>

On Wed, May 11, 2016 at 09:34:22AM +0200, Neil Armstrong wrote:
> Add pinctrl and gpio DT bindings for Oxford Semiconductor OXNAS SoC Family.
> This version supports the ARM926EJ-S based OX810SE SoC with 34 IO pins.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  .../devicetree/bindings/gpio/gpio_oxnas.txt        | 47 ++++++++++++++++++
>  .../devicetree/bindings/pinctrl/oxnas,pinctrl.txt  | 57 ++++++++++++++++++++++
>  2 files changed, 104 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt

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


From robh at kernel.org  Mon May 16 07:59:22 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 09:59:22 -0500
Subject: [PATCH v8 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <1462961588-23004-3-git-send-email-boris.brezillon@free-electrons.com>
References: <1462961588-23004-1-git-send-email-boris.brezillon@free-electrons.com>
 <1462961588-23004-3-git-send-email-boris.brezillon@free-electrons.com>
Message-ID: <20160516145922.GA2133@rob-hp-laptop>

On Wed, May 11, 2016 at 12:13:08PM +0200, Boris Brezillon wrote:
> The EBI (External Bus Interface) is used to access external peripherals
> (NOR, SRAM, NAND, and other specific devices like ethernet controllers).
> Each device is assigned a CS line and an address range and can have its
> own configuration (timings, access mode, bus width, ...).
> This driver provides a generic DT binding to configure a device according
> to its requirements.
> For specific device controllers (like the NAND one) the SMC timings
> should be configured by the controller driver through the matrix and smc
> syscon regmaps.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> ---
>  .../bindings/memory-controllers/atmel,ebi.txt      | 136 +++++++++++++++++++++
>  1 file changed, 136 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> 
> diff --git a/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> new file mode 100644
> index 0000000..2fe9b5b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
> @@ -0,0 +1,136 @@

[...]

> +Children device nodes are representing device connected to the EBI bus.
> +
> +Required device node properties:
> +
> +- #reg:			Contains the chip-select id, the offset and the length

Still need to fix #reg.

Otherwise,

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


From wens at csie.org  Mon May 16 08:01:26 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 16 May 2016 23:01:26 +0800
Subject: [PATCH 19/20] ARM: sunxi: Enable sun4i DRM driver
In-Reply-To: <1463402840-17062-20-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-20-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v64EGkfgqiZ=PYd-SZLOfnvkoEUDfB5bo__qca5sR5H0mQ@mail.gmail.com>

On Mon, May 16, 2016 at 8:47 PM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Enable the new DRM driver in the sunxi default configuration
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>

Acked-by: Chen-Yu Tsai <wens at csie.org>


From robh at kernel.org  Mon May 16 08:04:40 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 10:04:40 -0500
Subject: [PATCH 1/5] dt-bindings: Document the STM32 I2C bindings
In-Reply-To: <1462980974-22091-2-git-send-email-cedric.madianga@gmail.com>
References: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
 <1462980974-22091-2-git-send-email-cedric.madianga@gmail.com>
Message-ID: <20160516150440.GA6312@rob-hp-laptop>

On Wed, May 11, 2016 at 05:36:10PM +0200, M'boumba Cedric Madianga wrote:
> This patch adds documentation of device tree bindings for the STM32 I2C
> controller.
> 
> Signed-off-by: M'boumba Cedric Madianga <cedric.madianga at gmail.com>
> ---
>  .../devicetree/bindings/i2c/i2c-stm32.txt          | 33 ++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-stm32.txt
> 
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-stm32.txt b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt
> new file mode 100644
> index 0000000..73215c6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt
> @@ -0,0 +1,33 @@
> +* I2C controller embedded in STMicroelectronics STM32 I2C platform
> +
> +Required properties :
> +- compatible : Must be "st,i2c-stm32f4"

Normal order is st,stm32f4-i2c

Rob


From pavel at ucw.cz  Mon May 16 08:06:50 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Mon, 16 May 2016 17:06:50 +0200
Subject: Can not play audio with screen off
In-Reply-To: <5739D7B6.7060102@ti.com>
References: <20160515193106.GA18685@amd>
 <5739D7B6.7060102@ti.com>
Message-ID: <20160516150650.GA14639@amd>

Hi!

> > I'm playing some more with N900, this time I'd like to use it as a
> > alarm clock...
> > 
> > And now I realized I can not, because system performance is so
> > horrible with screen off that mpg123 + pulseaudio skips horribly. This
> > is without tweaking serial parameters, so CPU is definitely not going
> > into the idle/off modes.
> > 
> > Loading CPU fixes the issue (I used cat /dev/zero > /dev/null).
> > 
> > Hmm. And it seems to work better if I ssh in and launch mpg123
> > remotely. Weird.
> > 
> > Kernel 4.5-rc0. Will try on different ones.
> > 
> > Any ideas? Is there interface to tell kernel that better performance
> > is needed for a while?

> pm_qos cpu_dma_latency? Drivers will have to be properly instrumented
> with appropriate latency values -> this will control the depth in C
> states that the system will attempt. NOTE: it is a dual edged sword,
> bad configurations can result in none of the C-states being entered.

Ok, so far it looks like artefact of -rc0 kernel. Lets see if it
reappers...

Thanks,
									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From dianders at chromium.org  Mon May 16 08:12:57 2016
From: dianders at chromium.org (Doug Anderson)
Date: Mon, 16 May 2016 08:12:57 -0700
Subject: [PATCH 3/4] phy: rockchip-emmc: configure default output tap delay
In-Reply-To: <52567d92-d1d3-f089-65c2-a30f3a00386b@rock-chips.com>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
 <1463092986-61777-3-git-send-email-briannorris@chromium.org>
 <CAD=FV=WupNv+z86BgmR1n8bj+b6GKA5Ew7U9hgoAxV9dxF7gjQ@mail.gmail.com>
 <52567d92-d1d3-f089-65c2-a30f3a00386b@rock-chips.com>
Message-ID: <CAD=FV=Xq3=B0NC7of-h_q8vCUDGz=33MU4vjY6EyQxQS+CC8=Q@mail.gmail.com>

Hi,

On Sun, May 15, 2016 at 9:15 PM, Shawn Lin <shawn.lin at rock-chips.com> wrote:
> Hi Doug,
>
>
> On 2016/5/14 6:25, Doug Anderson wrote:
>>
>> Hi,
>>
>> On Thu, May 12, 2016 at 3:43 PM, Brian Norris <briannorris at chromium.org>
>> wrote:
>>>
>>> The output tap delay controls helps maintain the hold requirements for
>>> eMMC. The exact value is dependent on the SoC and other factors, though
>>> it isn't really an exact science. But the default of 0 is not very good,
>>> as it doesn't give the eMMC much hold time, so let's bump up to 4
>>> (approx 90 degree phase?). If we need to configure this any further
>>> (e.g., based on board or speed factors), we may need to consider a
>>> device tree representation.
>>
>>
>> As I understand it, this solves much the same problem as my patch in
>> <https://patchwork.kernel.org/patch/9085581/>, but for the eMMC port
>> on rk3399 (which doesn't use dw_mmc).  As argued in that patch and
>> also in the discussion from
>> <https://patchwork.kernel.org/patch/9030621/>, if we eventually end up
>> needing to put something in the device tree we need to be really
>> careful.  Specifically to get the exact right value here I think you
>> need to consider the input clock, speed mode, and any SoC-specific
>> delays differences between the clock and the data lines.  That would
>> imply that, if anything, the device tree data would only contain
>> information about the SoC-specific delay differences and all other
>> work to set this value would involve coordination between the PHY and
>> the SDHCI controller.
>>
>>
>> However, as also discussed previously, we don't appear to need to be
>> very exact about the value here.  It seems like setting this to 4 (~90
>> degrees?) is a much better starting point than leaving it at the
>> default of 0.
>
>
> The value, 4, is based on real silicon test observed from the
> oscilloscope, and of course it meets the requirement of speed modes.
> For arasan't phy, its phase is very accurate, so the real timing of
> the value you set almost won't vary too much for different Socs.
>
> So explicitly assigning 4 here looks sane currently except for crazy
> PCB layout...

Great to hear.  So we can probably just use your email as the basis of
the commit message?  How about this for the commit text then:

The output tap delay controls helps maintain the hold requirements for
eMMC.  The value, 4, is based on real silicon test observed from the
oscilloscope, and of course it meets the requirement of speed modes.
For arasan't phy, its phase is very accurate, so the real timing of
the value you set won't vary too much for different SoCs.

If / when we find an instance of a crazy PCB layout that needs a value
different than 4, we will figure out how to best specify that,
possibly using the device tree in some way.

-Doug


From tn at semihalf.com  Mon May 16 08:15:34 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 16 May 2016 17:15:34 +0200
Subject: [RFC PATCH 09/11] drivers: acpi: implement acpi_dma_configure
In-Reply-To: <5714BA5A.2040008@arm.com>
References: <1460654743-7896-1-git-send-email-lorenzo.pieralisi@arm.com>
 <1460654743-7896-10-git-send-email-lorenzo.pieralisi@arm.com>
 <CAOZdJXXtZq6uyE+5sseX7M_6Kq8wFG+37qd5TNSusKj=0gd8zA@mail.gmail.com>
 <5714BA5A.2040008@arm.com>
Message-ID: <5739E416.6000501@semihalf.com>

On 18.04.2016 12:43, Robin Murphy wrote:
> On 15/04/16 19:29, Timur Tabi wrote:
>> On Thu, Apr 14, 2016 at 12:25 PM, Lorenzo Pieralisi
>> <lorenzo.pieralisi at arm.com> wrote:
>>> +void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
>>> +{
>>> +       struct iommu_ops *iommu;
>>> +
>>> +       iommu = iort_iommu_configure(dev);
>>> +
>>> +       /*
>>> +        * Assume dma valid range starts at 0 and covers the whole
>>> +        * coherent_dma_mask.
>>> +        */
>>> +       arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
>>> +                          attr == DEV_DMA_COHERENT);
>>> +}
>>
>> I have a network driver that is impacted by this code, so thank you
>> for posting this. (See
>> https://www.mail-archive.com/netdev at vger.kernel.org/msg106249.html).
>>
>> One one SOC, the driver needs to set the mask to 32 bits.  On another
>> SOC, it needs to set it to 64 bits.  On device tree, the driver will
>> use dma-ranges.
>
> That's the wrong way to look at it - the driver isn't _using_
> dma-ranges, you're merely relying on the OF code setting the _default_
> DMA mask differently based on the property. If your driver is in the
> minority of those which actually care about DMA masks, then it should be
> calling dma_set_mask_and_coherent() appropriately and not relying on the
> default.

I don't see the clear strategy for setting DMA mask as well.

Lets consider DT boot method example:
1. SMMUv2 supports 48bit translation and 1:1 address map
dma-ranges = <0x0 0x0 0x0 0x0 0x00010000 0x0>;
and we are adding PCI device:

pci_device_add -> DMA_BIT_MASK(32) by default
   pci_dma_configure
     of_dma_configure -> reads dma-ranges and calculates 48bit DMA mask, 
but it picks minimum, we stay with DMA_BIT_MASK(32)

now PCI dev turns out to be e1000e NIC:
e1000_probe
   dma_set_mask_and_coherent -> tries to set DMA_BIT_MASK(64)
     dma_set_mask -> there is no set_dma_mask ops for SMMUv2 so we let 
it be DMA_BIT_MASK(64). From that point on, we let to use memory which 
SMMUv2 cannot work with.

Does lack of set_dma_mask is the only missing thing here?

Thanks,
Tomasz


From robh at kernel.org  Mon May 16 08:16:12 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 10:16:12 -0500
Subject: [PATCH v2 3/6] docs: Document BCM23550 bindings
In-Reply-To: <1463002582-6875-4-git-send-email-chris.brand@broadcom.com>
References: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
 <1463002582-6875-4-git-send-email-chris.brand@broadcom.com>
Message-ID: <20160516151612.GA7348@rob-hp-laptop>

On Wed, May 11, 2016 at 02:36:19PM -0700, Chris Brand wrote:
> Add binding document for Broadcom BCM23550 SoC.
> 
> BCM23550 has a Cluster Dormant Control IP block that holds cores
> in an idle state. Introduce a new CPU enable method in which the CDC is
> accessed to bring the core online.
> 
> Signed-off-by: Chris Brand <chris.brand at broadcom.com>
> ---
>  .../bindings/arm/bcm/brcm,bcm23550-cpu-method.txt  | 36 ++++++++++++++++++++++
>  .../devicetree/bindings/arm/bcm/brcm,bcm23550.txt  | 15 +++++++++
>  Documentation/devicetree/bindings/arm/cpus.txt     |  1 +
>  3 files changed, 52 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550-cpu-method.txt
>  create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,bcm23550.txt

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


From wens at csie.org  Mon May 16 08:21:41 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 16 May 2016 23:21:41 +0800
Subject: [PATCH 04/20] clk: sunxi: display: Add per-clock flags
In-Reply-To: <1463402840-17062-5-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-5-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v66-GzV=1wrJnHBObLVPVHPk87o0PaJtNyYasp2wFsZabw@mail.gmail.com>

Hi,

On Mon, May 16, 2016 at 8:47 PM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> The TCON channel 0 clock that is the parent clock of our pixel clock is
> expected to change its rate depending on the resolution we want to output
> in our display engine.
>
> However, since it's only a mux, the only way it can do that is by changing
> its parents rate.
>
> Allow to give flags in our display clocks description, and add the
> CLK_SET_RATE_PARENT flag for the TCON channel 0 flag.
>
> Fixes: a3b4956ee6d9 ("clk: sunxi: display: Add per-clock flags")
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi/clk-sun4i-display.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/clk/sunxi/clk-sun4i-display.c b/drivers/clk/sunxi/clk-sun4i-display.c
> index 445a7498d6df..9780fac6d029 100644
> --- a/drivers/clk/sunxi/clk-sun4i-display.c
> +++ b/drivers/clk/sunxi/clk-sun4i-display.c
> @@ -33,6 +33,8 @@ struct sun4i_a10_display_clk_data {
>
>         u8      width_div;
>         u8      width_mux;
> +

Don't really need this separator, but I'm ok either way.

> +       u32     flags;
>  };
>
>  struct reset_data {
> @@ -166,7 +168,7 @@ static void __init sun4i_a10_display_init(struct device_node *node,
>                                      data->has_div ? &div->hw : NULL,
>                                      data->has_div ? &clk_divider_ops : NULL,
>                                      &gate->hw, &clk_gate_ops,
> -                                    0);
> +                                    data->flags);
>         if (IS_ERR(clk)) {
>                 pr_err("%s: Couldn't register the clock\n", clk_name);
>                 goto free_div;
> @@ -232,6 +234,7 @@ static const struct sun4i_a10_display_clk_data sun4i_a10_tcon_ch0_data __initcon
>         .offset_rst     = 29,
>         .offset_mux     = 24,
>         .width_mux      = 2,
> +       .flags          = CLK_SET_RATE_PARENT,
>  };
>
>  static void __init sun4i_a10_tcon_ch0_setup(struct device_node *node)
> --
> 2.8.2
>

Acked-by: Chen-Yu Tsai <wens at csie.org>


From tn at semihalf.com  Mon May 16 08:26:03 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 16 May 2016 17:26:03 +0200
Subject: [RFC PATCH 09/11] drivers: acpi: implement acpi_dma_configure
In-Reply-To: <5739E416.6000501@semihalf.com>
References: <1460654743-7896-1-git-send-email-lorenzo.pieralisi@arm.com>
 <1460654743-7896-10-git-send-email-lorenzo.pieralisi@arm.com>
 <CAOZdJXXtZq6uyE+5sseX7M_6Kq8wFG+37qd5TNSusKj=0gd8zA@mail.gmail.com>
 <5714BA5A.2040008@arm.com> <5739E416.6000501@semihalf.com>
Message-ID: <5739E68B.2080907@semihalf.com>



On 16.05.2016 17:15, Tomasz Nowicki wrote:
> On 18.04.2016 12:43, Robin Murphy wrote:
>> On 15/04/16 19:29, Timur Tabi wrote:
>>> On Thu, Apr 14, 2016 at 12:25 PM, Lorenzo Pieralisi
>>> <lorenzo.pieralisi at arm.com> wrote:
>>>> +void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
>>>> +{
>>>> +       struct iommu_ops *iommu;
>>>> +
>>>> +       iommu = iort_iommu_configure(dev);
>>>> +
>>>> +       /*
>>>> +        * Assume dma valid range starts at 0 and covers the whole
>>>> +        * coherent_dma_mask.
>>>> +        */
>>>> +       arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
>>>> +                          attr == DEV_DMA_COHERENT);
>>>> +}
>>>
>>> I have a network driver that is impacted by this code, so thank you
>>> for posting this. (See
>>> https://www.mail-archive.com/netdev at vger.kernel.org/msg106249.html).
>>>
>>> One one SOC, the driver needs to set the mask to 32 bits.  On another
>>> SOC, it needs to set it to 64 bits.  On device tree, the driver will
>>> use dma-ranges.
>>
>> That's the wrong way to look at it - the driver isn't _using_
>> dma-ranges, you're merely relying on the OF code setting the _default_
>> DMA mask differently based on the property. If your driver is in the
>> minority of those which actually care about DMA masks, then it should be
>> calling dma_set_mask_and_coherent() appropriately and not relying on the
>> default.
>
> I don't see the clear strategy for setting DMA mask as well.
>
> Lets consider DT boot method example:
> 1. SMMUv2 supports 48bit translation and 1:1 address map
> dma-ranges = <0x0 0x0 0x0 0x0 0x00010000 0x0>;
> and we are adding PCI device:
>
> pci_device_add -> DMA_BIT_MASK(32) by default
>    pci_dma_configure
>      of_dma_configure -> reads dma-ranges and calculates 48bit DMA mask,
> but it picks minimum, we stay with DMA_BIT_MASK(32)
>
> now PCI dev turns out to be e1000e NIC:
> e1000_probe
>    dma_set_mask_and_coherent -> tries to set DMA_BIT_MASK(64)
>      dma_set_mask -> there is no set_dma_mask ops for SMMUv2 so we let

Sorry, there is no .set_dma_mask ops for ARM64 (not SMMUv2)

Tomasz


From tony at atomide.com  Mon May 16 08:36:00 2016
From: tony at atomide.com (Tony Lindgren)
Date: Mon, 16 May 2016 08:36:00 -0700
Subject: [PATCH] clk: ti: Add support for basic clk_set_rate for dm814x
 and j5-eco ADPLL
In-Reply-To: <20160515040028.GA20983@squirrel.local>
References: <1463157653-9404-1-git-send-email-tony@atomide.com>
 <20160515040028.GA20983@squirrel.local>
Message-ID: <20160516153600.GK5995@atomide.com>

* Matthijs van Duin <matthijsvanduin at gmail.com> [160514 21:02]:
> On Fri, May 13, 2016 at 09:40:53AM -0700, Tony Lindgren wrote:
> > +#define TI_ADPLL_DIV_N_MAX		GENMASK(7, 0)
> > +#define TI_ADPLL_MULT_M_MAX		(GENMASK(11, 0) + 1)
> 
> These are PLL-type dependent, also the +1 is wrong since M isn't
> off-by-one like N and N2 are.  (consistency? who needs that anyway?)
> 
> Here's what my own header says:
> 
> 			//		PLLS	PLLLJ
> /*10*/	u16 prediv;	// aka N	0..127	0..255	(off by one)
> /*12*/	u16 postdiv;	// aka M2	1..31	1..127  (but see note below)
> /*14*/	u16 mult;	// aka M	2..2047	2..4095
> /*16*/	u16 bypassdiv;	// aka N2	0..15	0..15	(off by one)
> 
> the "note below" referred to being:
> 
> // Using the fractional multiplier increases jitter (presumably more for PLLS
> // than for PLLLJ) and imposes constraints on the multiplier:
> //	PLLLJ:  mult < 4094
> //	PLLS:	mult < 2046 && mult >= 20
> // Other docs say mult > 100 is required for PLLS for max 2.5% period jitter.

OK thanks for that info.

> > +	/* Ratio for integer multiplier M and pre-divider N */
> > +	rational_best_approximation(rate, dcorate, TI_ADPLL_MULT_M_MAX,
> > +				    TI_ADPLL_DIV_N_MAX, &m, &n);
> 
> I'm seeing all sorts of problems here...
> 
> "dcorate" is a rather misleading name since I would expect that to
> refer to the rate of the dco, obviously, while in fact it's the input
> clock adjusted to account for an implicit factor of 2 (or 8 if you
> enable M4XEN, the utility of which I do not see).
> 
> It makes no sense to use rational_best_approximation on the integer
> part and then calculate the fractional part separately.  Not only is the
> calculation wrong, it's needlessly complicated.  You could just have
> passed TI_ADPLL_MULT_M_MAX << 18 to rational_best_approximation and then
> split m into integer and fractional part.

Hmm I guess I was trying to only change the integer part separately
if possible but the code is not even doing that.. I guess there's no
advantage to that and we have the the post divider to play with. I'll
update the patch for what you're suggesting.

> The biggest problem however is that the best rational approximation does
> not guarantee the refclk and dcoclk are within valid range.  This is
> unlikely to be a problem for PLLS, but PLLLJ has quite narrow ranges:
> 0.5-2.5 MHz for refclk and 0.5-2.0 GHz for dcoclk.

Yeah that's a concern :) Some of this can be corrected by manually
changing the multiplier and divider values, maybe not all cases
though.

Seems strange if we already don't have a decent piece of code to use
here.. Anybody got code stashed away for the PLLS and PLLLJ set_rate
handling?

> I don't really have much time right now to spend on this, I suggest
> checking previous threads on the 814x PLLs since I'm pretty sure the
> complications/constraints for setting them have been discussed.

OK sure, thanks a lot for your comments though!

> > + *                                            Maybe we can
> > + * make the SD_DIV_TARGET_MHZ configurable also?
> 
> What use would it have?  All docs I've ever seen say sddiv must be set
> to ceil(dcoclk / 250_MHz) and none of the docs contain any background
> information whatsoever on how this thing works, so there's no informed
> way to choose an alternate value.
> 
> > +	if ((sd >= TI814X_ADPLLJ_MIN_SD_DIV) &&
> > +	    (sd <= TI814X_ADPLLJ_MAX_SD_DIV)) {
> 
> always true due to the limited range permitted for dcoclk.

OK in that case I'll update the comments to reflect that :)

Regards,

Tony


From robh at kernel.org  Mon May 16 08:37:31 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 10:37:31 -0500
Subject: [PATCH v2 4/9] dt-bindings: Add a binding for Mediatek Video
 Decoder
In-Reply-To: <1463052250-38262-5-git-send-email-tiffany.lin@mediatek.com>
References: <1463052250-38262-1-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-2-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-3-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-4-git-send-email-tiffany.lin@mediatek.com>
 <1463052250-38262-5-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <20160516153731.GA22492@rob-hp-laptop>

On Thu, May 12, 2016 at 07:24:05PM +0800, Tiffany Lin wrote:
> Add a DT binding documentation of Video Decoder for the
> MT8173 SoC from Mediatek.
> 
> Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
> ---
>  .../devicetree/bindings/media/mediatek-vcodec.txt  |   50 ++++++++++++++++++--
>  1 file changed, 46 insertions(+), 4 deletions(-)

Please add acks when posting new versions.


From dianders at chromium.org  Mon May 16 08:49:01 2016
From: dianders at chromium.org (Doug Anderson)
Date: Mon, 16 May 2016 08:49:01 -0700
Subject: [PATCH 2/2] clk: rockchip: fix incorrect parent for rk3399's {c,
 g}pll_aclk_perihp_src
In-Reply-To: <57369D2E.3030002@rock-chips.com>
References: <1463164937-91089-1-git-send-email-briannorris@chromium.org>
 <1463164937-91089-2-git-send-email-briannorris@chromium.org>
 <CAD=FV=XstYhqpStSGw5PObWvpsvd3Nwp_hfEE-56bpFoVUyu+g@mail.gmail.com>
 <57369D2E.3030002@rock-chips.com>
Message-ID: <CAD=FV=Wda=kXYf4MnjXsW6g8sPAAEv7JO1ZoGXOnJW=aL0yv-w@mail.gmail.com>

Hi,

On Fri, May 13, 2016 at 8:36 PM, Xing Zheng <zhengxing at rock-chips.com> wrote:
> Hi Doug,
>
>
> On 2016?05?14? 04:10, Doug Anderson wrote:
>>
>> Hi,
>>
>> On Fri, May 13, 2016 at 11:42 AM, Brian Norris <briannorris at chromium.org>
>> wrote:
>>>
>>> From: Xing Zheng <zhengxing at rock-chips.com>
>>>
>>> There was a typo, swapping 'c' <--> 'g'.
>>>
>>> Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
>>> Signed-off-by: Brian Norris <briannorris at chromium.org>
>>> ---
>>>   drivers/clk/rockchip/clk-rk3399.c | 4 ++--
>>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/clk/rockchip/clk-rk3399.c
>>> b/drivers/clk/rockchip/clk-rk3399.c
>>> index 145756c4f3c8..9f86bfef70f7 100644
>>> --- a/drivers/clk/rockchip/clk-rk3399.c
>>> +++ b/drivers/clk/rockchip/clk-rk3399.c
>>> @@ -832,9 +832,9 @@ static struct rockchip_clk_branch
>>> rk3399_clk_branches[] __initdata = {
>>>                          RK3399_CLKGATE_CON(13), 1, GFLAGS),
>>>
>>>          /* perihp */
>>> -       GATE(0, "cpll_aclk_perihp_src", "gpll", CLK_IGNORE_UNUSED,
>>> +       GATE(0, "cpll_aclk_perihp_src", "cpll", CLK_IGNORE_UNUSED,
>>>                          RK3399_CLKGATE_CON(5), 0, GFLAGS),
>>> -       GATE(0, "gpll_aclk_perihp_src", "cpll", CLK_IGNORE_UNUSED,
>>> +       GATE(0, "gpll_aclk_perihp_src", "gpll", CLK_IGNORE_UNUSED,
>>>                          RK3399_CLKGATE_CON(5), 1, GFLAGS),
>>>          COMPOSITE(ACLK_PERIHP, "aclk_perihp", mux_aclk_perihp_p,
>>> CLK_IGNORE_UNUSED,
>>>                          RK3399_CLKSEL_CON(14), 7, 1, MFLAGS, 0, 5,
>>> DFLAGS,
>>
>> Definitely there was a bug since this table itself was inconsistent.
>> ...and I _think_ this fix is correct, but I'll note that the TRM has
>> more inconsistency here.
>>
>> In the big clock table 'CRU Clock Architecture Diagram', I see:
>>    CLK 4 is CPLL
>>    CLK 5 is GPLL
>>    CLK 125 is aclk_perihp_cpll_src and has 4 (CPLL) as source, with
>> g5[0] as the bit
>>    CLK 126 is aclk_perihp_gpll_src and has 5 (GPLL) as source, with
>> g5[1] as the bit
>>
>> In the definition of CRU_CLKGATE_CON5:
>>    bit 0 shows aclk_perihp_gpll_src_en
>>    bit 1 shows aclk_perihp_cpll_src_en
>>
>>
>> Thus the table shows CPLL as gate5[0] and GPLL as gate5[1].  The
>> register definition shows the opposite.  I'll tend to believe the
>> table over the register definition, but I figured I'd bring it up
>> anyway.
>>
>>
>> Xing Zheng: can you confirm that the table is correct and ask
>> documentation folks to fix the register definition for
>> CRU_CLKGATE_CON5?
>
> Yes, previously, our IC & DOC partner confirmed that the definition of
> CRU_CLKGATE_CON5 should be:
>   bit 0 shows aclk_perihp_cpll_src_en
>   bit 1 shows aclk_perihp_gpll_src_en
>
> Sorry to the incorrect register definition, we will fix them and review the
> TRM again.

Great!

Since we now have extra confirmation that Brian's patch is indeed correct:

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


From robh at kernel.org  Mon May 16 08:55:42 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 10:55:42 -0500
Subject: [PATCH] arm: tegra: initial support for apalis tk1
In-Reply-To: <1463056032-25888-1-git-send-email-marcel.ziswiler@toradex.com>
References: <1463056032-25888-1-git-send-email-marcel.ziswiler@toradex.com>
Message-ID: <20160516155542.GA25949@rob-hp-laptop>

On Thu, May 12, 2016 at 02:27:12PM +0200, Marcel Ziswiler wrote:
> This patch adds the device tree to support Toradex Apalis TK1 a
> computer on module which can be used on different carrier boards.
> 
> The module consists of a Tegra TK1 SoC, a PMIC solution, 2 GB of DDR3L
> RAM, a bunch of level shifters, an eMMC, a TMP451 temperature sensor
> chip and an I210 gigabit Ethernet controller. Furthermore, there is an
> SGTL5000 audio codec plus a Kinetis MK20DN512 companion micro
> controller for analogue, CAN and resistive touch functionality which
> are not yet supported. Anything that is not self contained on the
> module is disabled by default.
> 
> The device tree for the Evaluation Board includes the module's device
> tree and enables the supported peripherals of the carrier board (the
> Evaluation Board supports almost all of them).
> 
> While at it also add the device tree binding documentation for Apalis
> TK1 as well as for Colibri T30 which was missing so far.

"While at it" and "also" are keywords for put in a separate patch.

> 
> Signed-off-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>
> 
> ---
> 
>  Documentation/devicetree/bindings/arm/tegra.txt |    4 +
>  arch/arm/boot/dts/Makefile                      |    1 +
>  arch/arm/boot/dts/tegra124-apalis-emc.dtsi      | 2462 +++++++++++++++++++++++
>  arch/arm/boot/dts/tegra124-apalis-eval.dts      |  283 +++
>  arch/arm/boot/dts/tegra124-apalis.dtsi          | 2058 +++++++++++++++++++
>  5 files changed, 4808 insertions(+)
>  create mode 100644 arch/arm/boot/dts/tegra124-apalis-emc.dtsi
>  create mode 100644 arch/arm/boot/dts/tegra124-apalis-eval.dts
>  create mode 100644 arch/arm/boot/dts/tegra124-apalis.dtsi
> 
> diff --git a/Documentation/devicetree/bindings/arm/tegra.txt b/Documentation/devicetree/bindings/arm/tegra.txt
> index 73278c6..7709f3d 100644
> --- a/Documentation/devicetree/bindings/arm/tegra.txt
> +++ b/Documentation/devicetree/bindings/arm/tegra.txt
> @@ -31,8 +31,12 @@ board-specific compatible values:
>    nvidia,ventana
>    nvidia,whistler
>    toradex,apalis_t30
> +  toradex,apalis_tk1
>    toradex,apalis_t30-eval
> +  toradex,apalis_tk1-eval
>    toradex,colibri_t20-512
> +  toradex,colibri_t30
> +  toradex,colibri_t30-eval-v3
>    toradex,iris

Please use '-' rather than '_' for new strings even if that's what 
previous strings have. For ones that already in use in upstream dts 
files, then keep the underscore.

>  
>  Trusted Foundations
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index 06b6c2d..3a13d4f 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -793,6 +793,7 @@ dtb-$(CONFIG_ARCH_TEGRA_114_SOC) += \
>  	tegra114-roth.dtb \
>  	tegra114-tn7.dtb
>  dtb-$(CONFIG_ARCH_TEGRA_124_SOC) += \
> +	tegra124-apalis-eval.dtb \
>  	tegra124-jetson-tk1.dtb \
>  	tegra124-nyan-big.dtb \
>  	tegra124-nyan-blaze.dtb \
> diff --git a/arch/arm/boot/dts/tegra124-apalis-emc.dtsi b/arch/arm/boot/dts/tegra124-apalis-emc.dtsi
> new file mode 100644
> index 0000000..31b31ea
> --- /dev/null
> +++ b/arch/arm/boot/dts/tegra124-apalis-emc.dtsi
> @@ -0,0 +1,2462 @@
> +/*
> + * Copyright 2016 Toradex AG
> + *
> + * 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
> + *     version 2 as published by the Free Software Foundation.
> + *
> + *     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 , 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.
> + */
> +
> +/ {
> +	clock at 0,60006000 {

All these commas should be dropped. These have been fixed in -next and 
will go into 4.7.

> +		emc-timings-1 {
> +			nvidia,ram-code = <1>;
> +
> +			timing-12750000 {
> +				clock-frequency = <12750000>;
> +				nvidia,parent-clock-frequency = <408000000>;
> +				clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
> +				clock-names = "emc-parent";
> +			};
> +			timing-20400000 {
> +				clock-frequency = <20400000>;
> +				nvidia,parent-clock-frequency = <408000000>;
> +				clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
> +				clock-names = "emc-parent";
> +			};
> +			timing-40800000 {
> +				clock-frequency = <40800000>;
> +				nvidia,parent-clock-frequency = <408000000>;
> +				clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
> +				clock-names = "emc-parent";
> +			};
> +			timing-68000000 {
> +				clock-frequency = <68000000>;
> +				nvidia,parent-clock-frequency = <408000000>;
> +				clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
> +				clock-names = "emc-parent";
> +			};
> +			timing-102000000 {
> +				clock-frequency = <102000000>;
> +				nvidia,parent-clock-frequency = <408000000>;
> +				clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
> +				clock-names = "emc-parent";
> +			};
> +			timing-204000000 {
> +				clock-frequency = <204000000>;
> +				nvidia,parent-clock-frequency = <408000000>;
> +				clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
> +				clock-names = "emc-parent";
> +			};
> +			timing-300000000 {
> +				clock-frequency = <300000000>;
> +				nvidia,parent-clock-frequency = <600000000>;
> +				clocks = <&tegra_car TEGRA124_CLK_PLL_C>;
> +				clock-names = "emc-parent";
> +			};
> +			timing-396000000 {
> +				clock-frequency = <396000000>;
> +				nvidia,parent-clock-frequency = <792000000>;
> +				clocks = <&tegra_car TEGRA124_CLK_PLL_M>;
> +				clock-names = "emc-parent";
> +			};
> +			timing-528000000 {
> +				clock-frequency = <528000000>;
> +				nvidia,parent-clock-frequency = <528000000>;
> +				clocks = <&tegra_car TEGRA124_CLK_PLL_M_UD>;
> +				clock-names = "emc-parent";
> +			};
> +			timing-600000000 {
> +				clock-frequency = <600000000>;
> +				nvidia,parent-clock-frequency = <600000000>;
> +				clocks = <&tegra_car TEGRA124_CLK_PLL_C_UD>;
> +				clock-names = "emc-parent";
> +			};
> +			timing-792000000 {
> +				clock-frequency = <792000000>;
> +				nvidia,parent-clock-frequency = <792000000>;
> +				clocks = <&tegra_car TEGRA124_CLK_PLL_M_UD>;
> +				clock-names = "emc-parent";
> +			};
> +			timing-924000000 {
> +				clock-frequency = <924000000>;
> +				nvidia,parent-clock-frequency = <924000000>;
> +				clocks = <&tegra_car TEGRA124_CLK_PLL_M_UD>;
> +				clock-names = "emc-parent";
> +			};
> +		};
> +	};
> +
> +	emc at 0,7001b000 {
> +		emc-timings-1 {
> +			nvidia,ram-code = <1>;
> +
> +			timing-12750000 {
> +				clock-frequency = <12750000>;
> +
> +				nvidia,emc-auto-cal-config = <0xa1430000>;
> +				nvidia,emc-auto-cal-config2 = <0x00000000>;
> +				nvidia,emc-auto-cal-config3 = <0x00000000>;
> +				nvidia,emc-auto-cal-interval = <0x001fffff>;
> +				nvidia,emc-bgbias-ctl0 = <0x00000008>;
> +				nvidia,emc-cfg = <0x73240000>;
> +				nvidia,emc-cfg-2 = <0x000008c5>;
> +				nvidia,emc-ctt-term-ctrl = <0x00000802>;
> +				nvidia,emc-mode-1 = <0x80100003>;
> +				nvidia,emc-mode-2 = <0x80200008>;
> +				nvidia,emc-mode-4 = <0x00000000>;
> +				nvidia,emc-mode-reset = <0x80001221>;
> +				nvidia,emc-mrs-wait-cnt = <0x000e000e>;
> +				nvidia,emc-sel-dpd-ctrl = <0x00040128>;
> +				nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
> +				nvidia,emc-zcal-cnt-long = <0x00000042>;
> +				nvidia,emc-zcal-interval = <0x00000000>;
> +
> +				nvidia,emc-configuration = <
> +					0x00000000
> +					0x00000003

This is a bit long. Do multiple values per line.

> +					0x00000000
> +					0x00000000
> +					0x00000000
> +					0x00000004
> +					0x0000000a
> +					0x00000005


From robh at kernel.org  Mon May 16 09:04:17 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 11:04:17 -0500
Subject: [PATCH 1/4] dt: bindings: add bcm2835-memory-controller
 documentation
In-Reply-To: <1463056732-5607-2-git-send-email-kernel@martin.sperl.org>
References: <1463056732-5607-1-git-send-email-kernel@martin.sperl.org>
 <1463056732-5607-2-git-send-email-kernel@martin.sperl.org>
Message-ID: <20160516160417.GA1278@rob-hp-laptop>

On Thu, May 12, 2016 at 12:38:49PM +0000, kernel at martin.sperl.org wrote:
> From: Martin Sperl <kernel at martin.sperl.org>
> 
> Add memory controller dt-binding documentation for the
> bcm2835 soc.
> 
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
> ---
>  .../bindings/memory-controllers/brcm,bcm2835-sdram.txt   | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/memory-controllers/brcm,bcm2835-sdram.txt

I'd suspect a DDR controller has more than one clock, but otherwise 
looks fine. And this binding is pretty much independent of the 
discussion for this series.

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


From wens at csie.org  Mon May 16 09:05:18 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 00:05:18 +0800
Subject: [PATCH 03/20] clk: sunxi: tcon-ch1: Do not return a negative
 error in get_parent
In-Reply-To: <1463402840-17062-4-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-4-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v64GxTFnnx40Jy9Cz9e+c+T2j2QcbFznZ4-Lm-tdHFgcXg@mail.gmail.com>

On Mon, May 16, 2016 at 8:47 PM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> get_parent is supposed to return an unsigned 8 bit integer, so returning
> -EINVAL is a bad idea.
>
> Remove it.
>
> Reported-by: Dan Carpenter <dan.carpenter at oracle.com>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>

Acked-by: Chen-Yu Tsai <wens at csie.org>


From robh at kernel.org  Mon May 16 09:09:55 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 11:09:55 -0500
Subject: [Patch v5 1/8] dt/bindings: firmware: Add Qualcomm SCM binding
In-Reply-To: <1463111221-6963-2-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
 <1463111221-6963-2-git-send-email-andy.gross@linaro.org>
Message-ID: <20160516160955.GA8467@rob-hp-laptop>

On Thu, May 12, 2016 at 10:46:54PM -0500, Andy Gross wrote:
> This patch adds the device tree support for the Qualcomm SCM firmware.
> 
> Signed-off-by: Andy Gross <andy.gross at linaro.org>
> ---
>  .../devicetree/bindings/firmware/qcom,scm.txt      | 28 ++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/firmware/qcom,scm.txt

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


From robh at kernel.org  Mon May 16 09:14:33 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 11:14:33 -0500
Subject: [PATCH v2 1/2] ARM64: arch_timer: Work around QorIQ Erratum
 A-008585
In-Reply-To: <1463114260-8724-1-git-send-email-oss@buserror.net>
References: <1463114260-8724-1-git-send-email-oss@buserror.net>
Message-ID: <20160516161433.GA9247@rob-hp-laptop>

On Thu, May 12, 2016 at 11:37:39PM -0500, Scott Wood wrote:
> Erratum A-008585 says that the ARM generic timer counter "has the
> potential to contain an erroneous value for a small number of core
> clock cycles every time the timer value changes".  Accesses to TVAL
> (both read and write) are also affected due to the implicit counter
> read.  Accesses to CVAL are not affected.
> 
> The workaround is to reread TVAL and count registers until successive reads
> return the same value, and when writing TVAL to retry until counter
> reads before and after the write return the same value.
> 
> This erratum can be found on LS1043A and LS2080A.
> 
> Signed-off-by: Scott Wood <oss at buserror.net>
> ---
> v2:
> Significant rework based on feedback, including using static_key,
> disabling VDSO counter access rather than adding the workaround to the
> VDSO, and uninlining the loops.
> 
> Dropped the separate property for indicating that writes to TVAL are
> affected, as I believe that's just a side effect of the implicit
> counter read being corrupted, and thus a chip that is affected by one
> will always be affected by the other.
> 
> Dropped the arm32 portion as it seems there was confusion about whether
> LS1021A is affected.  Currently I am being told that it is not
> affected.
> 
> I considered writing to CVAL rather than looping on TVAL writes, but
> that would still have required separate set_next_event() code for the
> erratum, and adding CVAL to the enum would have required a bunch of
> extra handlers in switch statements (even where unused, due to compiler
> warnings about unhandled enum values) including in an arm32 header.  It
> seemed better to avoid the arm32 interaction and new untested
> accessors.
> ---
>  .../devicetree/bindings/arm/arch_timer.txt         |   6 ++

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

>  arch/arm64/include/asm/arch_timer.h                |  37 +++++--
>  drivers/clocksource/arm_arch_timer.c               | 110 +++++++++++++++++++++
>  3 files changed, 144 insertions(+), 9 deletions(-)


From hotran at apm.com  Mon May 16 09:17:24 2016
From: hotran at apm.com (Hoan Tran)
Date: Mon, 16 May 2016 09:17:24 -0700
Subject: [PATCH 0/3] Add support for X-Gene hwmon driver
Message-ID: <1463415447-29903-1-git-send-email-hotran@apm.com>

This patch set adds hardware temperature and power reading support ?for
APM X-Gene SoC's using the mailbox communication interface.
For device tree, it is the standard DT mailbox.
For ACPI, it is the PCC mailbox.

For ACPI, tested with this patch[1] which supports PCC subspace 2
[1] https://lkml.org/lkml/2016/5/6/482
 - [PATCH v2] mailbox: pcc: Support HW-Reduced Communication Subspace Type 2

Hoan Tran (3):
  Documentation: dtb: xgene: Add hwmon dts binding documentation
  hwmon: xgene: Adds hwmon driver
  arm64: dts: apm: Add X-Gene SoC hwmon to device tree

 .../devicetree/bindings/hwmon/apm-xgene-hwmon.txt  |  14 +
 Documentation/hwmon/xgene-hwmon                    |  32 +
 arch/arm64/boot/dts/apm/apm-shadowcat.dtsi         |   5 +
 arch/arm64/boot/dts/apm/apm-storm.dtsi             |   5 +
 drivers/hwmon/Kconfig                              |   7 +
 drivers/hwmon/Makefile                             |   1 +
 drivers/hwmon/xgene-hwmon.c                        | 801 +++++++++++++++++++++
 7 files changed, 865 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt
 create mode 100644 Documentation/hwmon/xgene-hwmon
 create mode 100644 drivers/hwmon/xgene-hwmon.c

-- 
1.9.1



From hotran at apm.com  Mon May 16 09:17:25 2016
From: hotran at apm.com (Hoan Tran)
Date: Mon, 16 May 2016 09:17:25 -0700
Subject: [PATCH 1/3] Documentation: dtb: xgene: Add hwmon dts binding
 documentation
In-Reply-To: <1463415447-29903-1-git-send-email-hotran@apm.com>
References: <1463415447-29903-1-git-send-email-hotran@apm.com>
Message-ID: <1463415447-29903-2-git-send-email-hotran@apm.com>

This patch adds the APM X-Gene hwmon device tree node documentation.

Signed-off-by: Hoan Tran <hotran at apm.com>
---
 .../devicetree/bindings/hwmon/apm-xgene-hwmon.txt          | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt

diff --git a/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt b/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt
new file mode 100644
index 0000000..49a482e
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt
@@ -0,0 +1,14 @@
+APM X-Gene hwmon driver
+
+Hwmon driver accesses sensors over the "SLIMpro" mailbox.
+
+Required properties :
+ - compatible : should be "apm,xgene-slimpro-hwmon"
+ - mboxes : use the label reference for the mailbox as the first parameter.
+	    The second parameter is the channel number.
+
+Example :
+	hwmonslimpro {
+		compatible = "apm,xgene-slimpro-hwmon";
+		mboxes = <&mailbox 7>;
+	};
-- 
1.9.1



From hotran at apm.com  Mon May 16 09:17:27 2016
From: hotran at apm.com (Hoan Tran)
Date: Mon, 16 May 2016 09:17:27 -0700
Subject: [PATCH 3/3] arm64: dts: apm: Add X-Gene SoC hwmon to device tree
In-Reply-To: <1463415447-29903-1-git-send-email-hotran@apm.com>
References: <1463415447-29903-1-git-send-email-hotran@apm.com>
Message-ID: <1463415447-29903-4-git-send-email-hotran@apm.com>

This patch adds DT node to enable hwmon driver for APM X-Gene SoC.

Signed-off-by: Hoan Tran <hotran at apm.com>
---
 arch/arm64/boot/dts/apm/apm-shadowcat.dtsi | 5 +++++
 arch/arm64/boot/dts/apm/apm-storm.dtsi     | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
index a055a5d..672c0ce 100644
--- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
@@ -472,6 +472,11 @@
 			mboxes = <&mailbox 0>;
 		};
 
+		hwmonslimpro {
+			compatible = "apm,xgene-slimpro-hwmon";
+			mboxes = <&mailbox 7>;
+		};
+
 		serial0: serial at 10600000 {
 			device_type = "serial";
 			compatible = "ns16550";
diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi
index ae4a173..7a59159 100644
--- a/arch/arm64/boot/dts/apm/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi
@@ -716,6 +716,11 @@
 			mboxes = <&mailbox 0>;
 		};
 
+		hwmonslimpro {
+			compatible = "apm,xgene-slimpro-hwmon";
+			mboxes = <&mailbox 7>;
+		};
+
 		serial0: serial at 1c020000 {
 			status = "disabled";
 			device_type = "serial";
-- 
1.9.1



From hotran at apm.com  Mon May 16 09:17:26 2016
From: hotran at apm.com (Hoan Tran)
Date: Mon, 16 May 2016 09:17:26 -0700
Subject: [PATCH 2/3] hwmon: xgene: Adds hwmon driver
In-Reply-To: <1463415447-29903-1-git-send-email-hotran@apm.com>
References: <1463415447-29903-1-git-send-email-hotran@apm.com>
Message-ID: <1463415447-29903-3-git-send-email-hotran@apm.com>

This patch adds hardware temperature and power reading support for
APM X-Gene SoC's using the mailbox communication interface.

Signed-off-by: Hoan Tran <hotran at apm.com>
---
 Documentation/hwmon/xgene-hwmon |  32 ++
 drivers/hwmon/Kconfig           |   7 +
 drivers/hwmon/Makefile          |   1 +
 drivers/hwmon/xgene-hwmon.c     | 801 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 841 insertions(+)
 create mode 100644 Documentation/hwmon/xgene-hwmon
 create mode 100644 drivers/hwmon/xgene-hwmon.c

diff --git a/Documentation/hwmon/xgene-hwmon b/Documentation/hwmon/xgene-hwmon
new file mode 100644
index 0000000..040a7f2
--- /dev/null
+++ b/Documentation/hwmon/xgene-hwmon
@@ -0,0 +1,32 @@
+Kernel driver xgene-hwmon
+========================
+
+Supported chips:
+ * APM X-Gene SoC
+
+Description
+-----------
+
+This driver adds hardware temperature and power reading support for
+APM X-Gene SoC's using the mailbox communication interface.
+For device tree, it is the standard DT mailbox.
+For ACPI, it is the PCC mailbox.
+
+The following sensors are supported
+
+  * Temperature
+    - SoC on-die temperature in milli-degree
+    - Alarm when high/over temperature occurs
+  * Power
+    - CPU power in uW
+    - IO power in uW
+    - CPU and IO power in uW
+
+sysfs-Interface
+---------------
+
+temp1_input - SoC on-die temperature (milli-degree C)
+temp1_critical_alarm - An 1 would indicates on-die temperature exceeded threshold
+power1_input - CPU power in (uW)
+power2_input - IO power in (uW)
+power3_input - CPU and IO power in (uW)
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 5c2d13a..91c3056 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1776,6 +1776,13 @@ config SENSORS_ULTRA45
 	  This driver provides support for the Ultra45 workstation environmental
 	  sensors.
 
+config SENSORS_XGENE
+	tristate "APM X-Gene SoC hardware monitoring driver"
+	depends on XGENE_SLIMPRO_MBOX || PCC
+	help
+	  If you say yes here you get support for the temperature
+	  and power sensors for APM X-Gene SoC.
+
 if ACPI
 
 comment "ACPI drivers"
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 58cc3ac..668d0f1 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -161,6 +161,7 @@ obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
 obj-$(CONFIG_SENSORS_W83L786NG)	+= w83l786ng.o
 obj-$(CONFIG_SENSORS_WM831X)	+= wm831x-hwmon.o
 obj-$(CONFIG_SENSORS_WM8350)	+= wm8350-hwmon.o
+obj-$(CONFIG_SENSORS_XGENE)	+= xgene-hwmon.o
 
 obj-$(CONFIG_PMBUS)		+= pmbus/
 
diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c
new file mode 100644
index 0000000..bc4ad29
--- /dev/null
+++ b/drivers/hwmon/xgene-hwmon.c
@@ -0,0 +1,801 @@
+/*
+ * APM X-Gene SoC Hardware Monitoring Driver
+ *
+ * Copyright (c) 2016, Applied Micro Circuits Corporation
+ * Author: Loc Ho <lho at apm.com>
+ *         Hoan Tran <hotran at apm.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * This driver provides the following features:
+ *  - Retrieve CPU's total power (uW)
+ *  - Retrieve IO's total power (uW)
+ *  - Retrieve SoC total power (uW)
+ *  - Retrieve SoC temperature (milli-degree C) and alarm
+ */
+#include <linux/acpi.h>
+#include <linux/dma-mapping.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/kfifo.h>
+#include <linux/interrupt.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <acpi/cppc_acpi.h>
+
+/* SLIMpro message defines */
+#define SLIMPRO_MSG_TYPE_DBG_ID		0
+#define SLIMPRO_MSG_TYPE_ERR_ID		7
+#define SLIMPRO_MSG_TYPE_PWRMGMT_ID	9
+
+#define SLIMPRO_MSG_TYPE(v)		(((v) & 0xF0000000) >> 28)
+#define SLIMPRO_MSG_TYPE_SET(v)		(((v) << 28) & 0xF0000000)
+#define SLIMPRO_MSG_SUBTYPE(v)		(((v) & 0x0F000000) >> 24)
+#define SLIMPRO_MSG_SUBTYPE_SET(v)	(((v) << 24) & 0x0F000000)
+
+#define SLIMPRO_DBG_SUBTYPE_SENSOR_READ	4
+#define SLIMPRO_SENSOR_READ_MSG		0x04FFE902
+#define SLIMPRO_SENSOR_READ_ENCODE_ADDR(a) \
+	((a) & 0x000FFFFF)
+#define PMD_PWR_MW_REG			0x26
+#define SOC_PWR_REG			0x21
+#define SOC_TEMP_REG			0x10
+
+#define SLIMPRO_PWRMGMT_SUBTYPE_TPC	1
+#define SLIMPRO_TPC_ALARM		2
+#define SLIMPRO_TPC_GET_ALARM		3
+#define SLIMPRO_TPC_CMD(v)		(((v) & 0x00FF0000) >> 16)
+#define SLIMPRO_TPC_CMD_SET(v)		(((v) << 16) & 0x00FF0000)
+#define SLIMPRO_TPC_ENCODE_MSG(hndl, cmd, type) \
+	(SLIMPRO_MSG_TYPE_SET(SLIMPRO_MSG_TYPE_PWRMGMT_ID) | \
+	SLIMPRO_MSG_SUBTYPE_SET(hndl) | \
+	SLIMPRO_TPC_CMD_SET(cmd) | \
+	type)
+
+/* PCC defines */
+#define SLIMPRO_MSG_PCC_SUBSPACE	7
+#define PCC_SIGNATURE_MASK		0x50424300
+#define PCCC_GENERATE_DB_INT		BIT(15)
+#define PCCS_CMD_COMPLETE		BIT(0)
+#define PCCS_SCI_DOORBEL		BIT(1)
+#define PCCS_PLATFORM_NOTIFICATION	BIT(3)
+/*
+ * Arbitrary retries in case the remote processor is slow to respond
+ * to PCC commands
+ */
+#define PCC_NUM_RETRIES			500
+
+#define ASYNC_MSG_FIFO_SIZE		16
+#define MBOX_HWMON_INDEX		0
+#define MBOX_OP_TIMEOUTMS		1000
+
+#define SOC_TEMP			0
+#define CPU_POWER			0
+#define IO_POWER			1
+#define SOC_POWER			2
+
+#define WATT_TO_mWATT(x)		((x) * 1000)
+#define mWATT_TO_uWATT(x)		((x) * 1000)
+#define WATT_TO_uWATT(x)		((x) * 1000000)
+#define CELSIUS_TO_mCELSIUS(x)		((x) * 1000)
+
+#define to_xgene_hwmon_dev(cl)		\
+	container_of(cl, struct xgene_hwmon_dev, mbox_client)
+
+struct slimpro_resp_msg {
+	u32 msg;
+	u32 param1;
+	u32 param2;
+} __packed;
+
+struct xgene_hwmon_dev {
+	struct device		*dev;
+	struct mbox_chan	*mbox_chan;
+	struct mbox_client	mbox_client;
+
+	spinlock_t		lock;
+	struct completion	rd_complete;
+	int			resp_pending;
+	struct slimpro_resp_msg sync_msg;
+
+	struct work_struct	workq;
+	struct kfifo_rec_ptr_1	async_msg_fifo;
+
+	struct device		*hwmon_dev;
+	bool			temp_critical_alarm;
+
+	phys_addr_t		comm_base_addr;
+	void			*pcc_comm_addr;
+	u64			usecs_lat;
+};
+
+/*
+ * This function tests and clears a bitmask then returns its old value
+ */
+static u16 xgene_word_tst_and_clr(u16 *addr, u16 mask)
+{
+	u16 ret, val;
+
+	val = readw_relaxed(addr);
+	ret = val & mask;
+	val &= ~mask;
+	writew_relaxed(val, addr);
+
+	return ret;
+}
+
+static int xgene_hwmon_pcc_rd(struct xgene_hwmon_dev *ctx, u32 *msg)
+{
+	struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr;
+	void *ptr = generic_comm_base + 1;
+	unsigned long flags;
+	u16 val;
+	int rc;
+
+	spin_lock_irqsave(&ctx->lock, flags);
+	if (ctx->resp_pending) {
+		spin_unlock_irqrestore(&ctx->lock, flags);
+		return -EAGAIN;
+	}
+
+	init_completion(&ctx->rd_complete);
+	ctx->resp_pending = true;
+
+	/* Write signature for subspace */
+	writel_relaxed(PCC_SIGNATURE_MASK | SLIMPRO_MSG_PCC_SUBSPACE,
+		       &generic_comm_base->signature);
+
+	/* Write to the shared command region */
+	writew_relaxed(SLIMPRO_MSG_TYPE(msg[0]) | PCCC_GENERATE_DB_INT,
+		       &generic_comm_base->command);
+
+	/* Flip CMD COMPLETE bit */
+	val = readw_relaxed(&generic_comm_base->status);
+	val &= ~PCCS_CMD_COMPLETE;
+	writew_relaxed(val, &generic_comm_base->status);
+
+	/* Copy the message to the PCC comm space */
+	memcpy(ptr, msg, sizeof(struct slimpro_resp_msg));
+
+	/* Ring the doorbell */
+	rc = mbox_send_message(ctx->mbox_chan, msg);
+	if (rc < 0) {
+		dev_err(ctx->dev, "Mailbox send error %d\n", rc);
+		goto err;
+	}
+	spin_unlock_irqrestore(&ctx->lock, flags);
+	if (!wait_for_completion_timeout(&ctx->rd_complete,
+					 usecs_to_jiffies(ctx->usecs_lat))) {
+		spin_lock_irqsave(&ctx->lock, flags);
+		dev_err(ctx->dev, "Mailbox operation timed out\n");
+		rc = -EIO;
+		goto err;
+	}
+	spin_lock_irqsave(&ctx->lock, flags);
+
+	/* Check for invalid data or no device */
+	if (SLIMPRO_MSG_TYPE(ctx->sync_msg.msg) == SLIMPRO_MSG_TYPE_ERR_ID ||
+	    ctx->sync_msg.msg == 0xffffffff) {
+		rc = -ENODEV;
+		goto err;
+	}
+
+	msg[0] = ctx->sync_msg.msg;
+	msg[1] = ctx->sync_msg.param1;
+	msg[2] = ctx->sync_msg.param2;
+
+err:
+	mbox_chan_txdone(ctx->mbox_chan, 0);
+	ctx->resp_pending = false;
+	spin_unlock_irqrestore(&ctx->lock, flags);
+	return rc;
+}
+
+static int xgene_hwmon_rd(struct xgene_hwmon_dev *ctx, u32 *msg)
+{
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&ctx->lock, flags);
+	if (ctx->resp_pending) {
+		spin_unlock_irqrestore(&ctx->lock, flags);
+		return -EAGAIN;
+	}
+
+	init_completion(&ctx->rd_complete);
+	ctx->resp_pending = true;
+	rc = mbox_send_message(ctx->mbox_chan, msg);
+	if (rc < 0) {
+		dev_err(ctx->dev, "Mailbox send error %d\n", rc);
+		goto err;
+	}
+	spin_unlock_irqrestore(&ctx->lock, flags);
+
+	if (!wait_for_completion_timeout(&ctx->rd_complete,
+					 msecs_to_jiffies(MBOX_OP_TIMEOUTMS))) {
+		spin_lock_irqsave(&ctx->lock, flags);
+		dev_err(ctx->dev, "Mailbox operation timed out\n");
+		rc = -EIO;
+		goto err;
+	}
+	spin_lock_irqsave(&ctx->lock, flags);
+
+	/* Check for invalid data or no device */
+	if (SLIMPRO_MSG_TYPE(ctx->sync_msg.msg) == SLIMPRO_MSG_TYPE_ERR_ID ||
+	    ctx->sync_msg.msg == 0xffffffff) {
+		rc = -ENODEV;
+		goto err;
+	}
+
+	msg[0] = ctx->sync_msg.msg;
+	msg[1] = ctx->sync_msg.param1;
+	msg[2] = ctx->sync_msg.param2;
+
+err:
+	ctx->resp_pending = false;
+	spin_unlock_irqrestore(&ctx->lock, flags);
+	return rc;
+}
+
+static int xgene_hwmon_reg_map_rd(struct xgene_hwmon_dev *ctx, u32 addr,
+				  u32 *data)
+{
+	u32 msg[3];
+	int rc;
+
+	msg[0] = SLIMPRO_SENSOR_READ_MSG;
+	msg[1] = SLIMPRO_SENSOR_READ_ENCODE_ADDR(addr);
+	msg[2] = 0;
+
+	if (ACPI_COMPANION(ctx->dev))
+		rc = xgene_hwmon_pcc_rd(ctx, msg);
+	else
+		rc = xgene_hwmon_rd(ctx, msg);
+	if (rc < 0) {
+		/* To support compatibility with firmware, return 0 */
+		dev_err(ctx->dev, "SLIMpro register 0x%02X read error %d\n",
+			addr, rc);
+		*data = 0;
+		return rc;
+	}
+	*data = msg[1];
+
+	return rc;
+}
+
+static int xgene_hwmon_get_notification_msg(struct xgene_hwmon_dev *ctx,
+					    u32 *amsg)
+{
+	u32 msg[3];
+	int rc;
+
+	msg[0] = SLIMPRO_TPC_ENCODE_MSG(SLIMPRO_PWRMGMT_SUBTYPE_TPC,
+					SLIMPRO_TPC_GET_ALARM, 0);
+	msg[1] = 0;
+	msg[2] = 0;
+
+	rc = xgene_hwmon_pcc_rd(ctx, msg);
+	if (rc < 0) {
+		dev_err(ctx->dev, "PCC Alarm read error %d\n", rc);
+		return rc;
+	}
+	amsg[0] = msg[0];
+	amsg[1] = msg[1];
+	amsg[2] = msg[2];
+
+	return rc;
+}
+
+static int xgene_hwmon_get_cpu_pwr(struct xgene_hwmon_dev *ctx, u32 *val)
+{
+	return xgene_hwmon_reg_map_rd(ctx, PMD_PWR_MW_REG, val);
+}
+
+static int xgene_hwmon_get_io_pwr(struct xgene_hwmon_dev *ctx, u32 *val)
+{
+	return xgene_hwmon_reg_map_rd(ctx, SOC_PWR_REG, val);
+}
+
+static int xgene_hwmon_get_soc_power(struct xgene_hwmon_dev *ctx, u32 *val)
+{
+	u32 pmd_vrm_power;
+	u32 io_vrm_power;
+	int rc;
+
+	rc = xgene_hwmon_get_cpu_pwr(ctx, &pmd_vrm_power);
+	if (rc < 0)
+		return rc;
+
+	rc = xgene_hwmon_get_io_pwr(ctx, &io_vrm_power);
+	if (rc < 0)
+		return rc;
+
+	*val = pmd_vrm_power + WATT_TO_mWATT(io_vrm_power);
+
+	return 0;
+}
+
+static int xgene_hwmon_get_temp(struct xgene_hwmon_dev *ctx, u32 *val)
+{
+	return xgene_hwmon_reg_map_rd(ctx, SOC_TEMP_REG, val);
+}
+
+/*
+ * Sensor temperature/power functions
+ */
+static const char * const sensor_temp_input_names[] = {
+	[SOC_TEMP] = "SoC Temperature",
+};
+
+static const char * const sensor_pwr_input_names[] = {
+	[CPU_POWER] = "CPU's power",
+	[IO_POWER] = "IO's power",
+	[SOC_POWER] = "SoC power"
+};
+
+static ssize_t xgene_hwmon_show_name(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "APM X-Gene\n");
+}
+
+static ssize_t xgene_hwmon_show_temp(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
+	u32 val;
+	int rc;
+
+	rc = xgene_hwmon_get_temp(ctx, &val);
+	if (rc < 0)
+		return rc;
+
+	val = CELSIUS_TO_mCELSIUS(val);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t xgene_hwmon_show_temp_label(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	int channel = to_sensor_dev_attr(attr)->index - 1;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			sensor_temp_input_names[channel]);
+}
+
+static ssize_t xgene_hwmon_show_temp_critical_alarm(struct device *dev,
+						    struct device_attribute *devattr,
+						    char *buf)
+{
+	struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", ctx->temp_critical_alarm);
+}
+
+static ssize_t xgene_hwmon_show_pwr_label(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	int channel = to_sensor_dev_attr(attr)->index - 1;
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			sensor_pwr_input_names[channel]);
+}
+
+static ssize_t xgene_hwmon_show_pwr(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
+	int channel = to_sensor_dev_attr(attr)->index - 1;
+	u32 val;
+	int rc;
+
+	switch (channel) {
+	case CPU_POWER:
+		rc = xgene_hwmon_get_cpu_pwr(ctx, &val);
+		break;
+	case IO_POWER:
+		rc = xgene_hwmon_get_io_pwr(ctx, &val);
+		break;
+	case SOC_POWER:
+		rc = xgene_hwmon_get_soc_power(ctx, &val);
+		break;
+	default:
+		rc = -EINVAL;
+		break;
+	}
+	if (rc < 0)
+		return rc;
+
+	if (channel == IO_POWER)
+		val = WATT_TO_uWATT(val);
+	else
+		val = mWATT_TO_uWATT(val);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+/* Chip name, required by hwmon */
+static DEVICE_ATTR(name, S_IRUGO, xgene_hwmon_show_name, NULL);
+
+#define SENSOR_ATTR_TEMP(index) \
+	static SENSOR_DEVICE_ATTR(temp##index##_label, S_IRUGO, \
+				  xgene_hwmon_show_temp_label, NULL, index); \
+	static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, \
+				  xgene_hwmon_show_temp, NULL, index); \
+	static SENSOR_DEVICE_ATTR(temp##index##_critical_alarm, S_IRUGO, \
+				  xgene_hwmon_show_temp_critical_alarm, NULL, \
+				  index);
+#define SENSOR_ATTR_PWR(index) \
+	static SENSOR_DEVICE_ATTR(power##index##_label, S_IRUGO, \
+				  xgene_hwmon_show_pwr_label, NULL, index); \
+	static SENSOR_DEVICE_ATTR(power##index##_input, S_IRUGO, \
+				  xgene_hwmon_show_pwr, NULL, index);
+
+#define APM_TEMP_SENSOR_ATTR(index) \
+	&sensor_dev_attr_temp##index##_input.dev_attr.attr, \
+	&sensor_dev_attr_temp##index##_label.dev_attr.attr, \
+	&sensor_dev_attr_temp##index##_critical_alarm.dev_attr.attr
+#define APM_PWR_SENSOR_ATTR(index) \
+	&sensor_dev_attr_power##index##_input.dev_attr.attr, \
+	&sensor_dev_attr_power##index##_label.dev_attr.attr
+
+SENSOR_ATTR_TEMP(1); /* SoC temperature */
+SENSOR_ATTR_PWR(1);  /* CPU power */
+SENSOR_ATTR_PWR(2);  /* IO power */
+SENSOR_ATTR_PWR(3);  /* SoC power */
+
+static struct attribute *xgene_hwmon_attributes[] = {
+	&dev_attr_name.attr,
+	APM_TEMP_SENSOR_ATTR(1),
+	APM_PWR_SENSOR_ATTR(1),
+	APM_PWR_SENSOR_ATTR(2),
+	APM_PWR_SENSOR_ATTR(3),
+	NULL,
+};
+
+static const struct attribute_group xgene_hwmon_attr_group = {
+	.attrs	= xgene_hwmon_attributes,
+};
+
+static int xgene_hwmon_tpc_alarm(struct xgene_hwmon_dev *ctx,
+				 struct slimpro_resp_msg *amsg)
+{
+	char name[40];
+
+	ctx->temp_critical_alarm = amsg->param2 ? true : false;
+	snprintf(name, sizeof(name), "temp%d_critical_alarm", SOC_TEMP + 1);
+	sysfs_notify(&ctx->dev->kobj, NULL, name);
+	dev_alert(ctx->dev, "SoC temperature alarm at %d degree\n",
+		  amsg->param1);
+	return 0;
+}
+
+static void xgene_hwmon_process_pwrmsg(struct xgene_hwmon_dev *ctx,
+				       struct slimpro_resp_msg *amsg)
+{
+	switch (SLIMPRO_MSG_SUBTYPE(amsg->msg)) {
+	case SLIMPRO_PWRMGMT_SUBTYPE_TPC:
+		switch (SLIMPRO_TPC_CMD(amsg->msg)) {
+		case SLIMPRO_TPC_ALARM:
+			xgene_hwmon_tpc_alarm(ctx, amsg);
+			break;
+		default:
+			dev_warn(ctx->dev,
+				 "Un-supported TPC message received 0x%08X\n",
+				 amsg->msg);
+			break;
+		}
+		break;
+	default:
+		dev_warn(ctx->dev, "Un-supported message received 0x%08X\n",
+			 amsg->msg);
+		break;
+	}
+}
+
+/*
+ * This function is called to process async work queue
+ */
+static void xgene_hwmon_evt_work(struct work_struct *work)
+{
+	struct slimpro_resp_msg amsg;
+	struct xgene_hwmon_dev *ctx;
+	int ret;
+
+	ctx = container_of(work, struct xgene_hwmon_dev, workq);
+	while (kfifo_out_spinlocked(&ctx->async_msg_fifo, &amsg,
+				    sizeof(struct slimpro_resp_msg),
+				    &ctx->lock)) {
+		/*
+		 * If PCC, send a consumer command to Platform to get info
+		 * If Slimpro Mailbox, get message from specific FIFO
+		 */
+		if (ACPI_COMPANION(ctx->dev)) {
+			ret = xgene_hwmon_get_notification_msg(ctx,
+							       (u32 *)&amsg);
+			if (ret < 0)
+				continue;
+		}
+		switch (SLIMPRO_MSG_TYPE(amsg.msg)) {
+		case SLIMPRO_MSG_TYPE_PWRMGMT_ID:
+			xgene_hwmon_process_pwrmsg(ctx, &amsg);
+			break;
+		default:
+			dev_warn(ctx->dev,
+				 "Invalid mailbox msg received 0x%08X 0x%08X 0x%08X\n",
+				 amsg.msg, amsg.param1, amsg.param2);
+			break;
+		}
+	}
+}
+
+/*
+ * This function is called when the SLIMpro/PCC Mailbox received a message
+ */
+static void xgene_hwmon_rx_cb(struct mbox_client *cl, void *msg)
+{
+	struct xgene_hwmon_dev *ctx = to_xgene_hwmon_dev(cl);
+	struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr;
+	struct slimpro_resp_msg amsg;
+
+	/* If PCC mailbox controller, get msg from shared memory */
+	if (ACPI_COMPANION(ctx->dev)) {
+		msg = generic_comm_base + 1;
+		/* Check if platform sends interrupt */
+		if (!xgene_word_tst_and_clr(&generic_comm_base->status,
+					    PCCS_SCI_DOORBEL))
+			return;
+	}
+
+	/*
+	 * Response message format:
+	 * msg[0] is the return code of the operation
+	 * msg[1] is the first parameter word
+	 * msg[2] is the second parameter word
+	 *
+	 * As message only supports dword size, just assign it.
+	 */
+
+	/* Check for sync query */
+	if (ctx->resp_pending &&
+	    ((SLIMPRO_MSG_TYPE(((u32 *) msg)[0]) == SLIMPRO_MSG_TYPE_ERR_ID) ||
+	     (SLIMPRO_MSG_TYPE(((u32 *) msg)[0]) == SLIMPRO_MSG_TYPE_DBG_ID &&
+	      SLIMPRO_MSG_SUBTYPE(((u32 *) msg)[0]) == SLIMPRO_DBG_SUBTYPE_SENSOR_READ) ||
+	     (SLIMPRO_MSG_TYPE(((u32 *) msg)[0]) == SLIMPRO_MSG_TYPE_PWRMGMT_ID &&
+	      SLIMPRO_MSG_SUBTYPE(((u32 *) msg)[0]) == SLIMPRO_PWRMGMT_SUBTYPE_TPC &&
+	      SLIMPRO_TPC_CMD(((u32 *) msg)[0]) == SLIMPRO_TPC_ALARM))) {
+		if (ACPI_COMPANION(ctx->dev)) {
+			/* Check if platform completes command */
+			if (!xgene_word_tst_and_clr(&generic_comm_base->status,
+						    PCCS_CMD_COMPLETE))
+				goto notify;
+		}
+		ctx->sync_msg.msg = ((u32 *) msg)[0];
+		ctx->sync_msg.param1 = ((u32 *) msg)[1];
+		ctx->sync_msg.param2 = ((u32 *) msg)[2];
+
+		/* Operation waiting for response */
+		complete(&ctx->rd_complete);
+
+		return;
+	}
+
+	/*
+	 * If PCC, platform notifies interrupt to OSPM.
+	 * OPSM schedules a consumer command to get this information
+	 * in a workqueue. Platform must wait until OSPM has issued
+	 * a consumer command that serves this notification.
+	 */
+notify:
+	if (ACPI_COMPANION(ctx->dev)) {
+		/* Check and clear Platform Notification bit */
+		if (!xgene_word_tst_and_clr(&generic_comm_base->status,
+					    PCCS_PLATFORM_NOTIFICATION))
+			return;
+	} else {
+		amsg.msg   = ((u32 *) msg)[0];
+		amsg.param1 = ((u32 *) msg)[1];
+		amsg.param2 = ((u32 *) msg)[2];
+	}
+
+	/* Enqueue to the FIFO */
+	kfifo_in_spinlocked(&ctx->async_msg_fifo, &amsg,
+			    sizeof(struct slimpro_resp_msg), &ctx->lock);
+	/* Schedule the bottom handler */
+	schedule_work(&ctx->workq);
+}
+
+static void xgene_hwmon_tx_done(struct mbox_client *cl, void *msg, int ret)
+{
+	if (ret) {
+		dev_dbg(cl->dev, "TX did not complete: CMD sent:%x, ret:%d\n",
+			*(u16 *) msg, ret);
+	} else {
+		dev_dbg(cl->dev, "TX completed. CMD sent:%x, ret:%d\n",
+			*(u16 *) msg, ret);
+	}
+}
+
+static int __init xgene_hwmon_probe(struct platform_device *pdev)
+{
+	struct xgene_hwmon_dev *ctx;
+	struct mbox_client *cl;
+	int rc;
+
+	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->dev = &pdev->dev;
+	platform_set_drvdata(pdev, ctx);
+	cl = &ctx->mbox_client;
+
+	/* Request mailbox channel */
+	cl->dev = &pdev->dev;
+	cl->rx_callback = xgene_hwmon_rx_cb;
+	cl->tx_done = xgene_hwmon_tx_done;
+	cl->tx_block = false;
+	cl->tx_tout = MBOX_OP_TIMEOUTMS;
+	cl->knows_txdone = false;
+	if (!ACPI_COMPANION(cl->dev)) {
+		ctx->mbox_chan = mbox_request_channel(cl, MBOX_HWMON_INDEX);
+		if (IS_ERR(ctx->mbox_chan)) {
+			dev_err(&pdev->dev,
+				"SLIMpro mailbox channel request failed\n");
+			return PTR_ERR(ctx->mbox_chan);
+		}
+	} else {
+		struct acpi_pcct_hw_reduced *cppc_ss;
+
+		ctx->mbox_chan =
+			pcc_mbox_request_channel(cl, SLIMPRO_MSG_PCC_SUBSPACE);
+		if (IS_ERR(ctx->mbox_chan)) {
+			dev_err(&pdev->dev,
+				"PPC channel request failed\n");
+			return PTR_ERR(ctx->mbox_chan);
+		}
+
+		/*
+		 * The PCC mailbox controller driver should
+		 * have parsed the PCCT (global table of all
+		 * PCC channels) and stored pointers to the
+		 * subspace communication region in con_priv.
+		 */
+		cppc_ss = ctx->mbox_chan->con_priv;
+		if (!cppc_ss) {
+			dev_err(&pdev->dev, "PPC subspace not found\n");
+			rc = -ENODEV;
+			goto out_mbox_free;
+		}
+
+		if (!ctx->mbox_chan->mbox->txdone_irq) {
+			dev_err(&pdev->dev, "PCC IRQ not supported\n");
+			rc = -ENODEV;
+			goto out_mbox_free;
+		}
+
+		/*
+		 * This is the shared communication region
+		 * for the OS and Platform to communicate over.
+		 */
+		ctx->comm_base_addr = cppc_ss->base_address;
+		if (ctx->comm_base_addr) {
+			ctx->pcc_comm_addr =
+					acpi_os_ioremap(ctx->comm_base_addr,
+							cppc_ss->length);
+		} else {
+			dev_err(&pdev->dev, "Failed to get PCC comm region\n");
+			rc = -ENODEV;
+			goto out_mbox_free;
+		}
+
+		if (!ctx->pcc_comm_addr) {
+			dev_err(&pdev->dev,
+				"Failed to ioremap PCC comm region\n");
+			rc = -ENOMEM;
+			goto out_mbox_free;
+		}
+
+		/*
+		 * cppc_ss->latency is just a Nominal value. In reality
+		 * the remote processor could be much slower to reply.
+		 * So add an arbitrary amount of wait on top of Nominal.
+		 */
+		ctx->usecs_lat = PCC_NUM_RETRIES * cppc_ss->latency;
+	}
+
+	spin_lock_init(&ctx->lock);
+
+	rc = kfifo_alloc(&ctx->async_msg_fifo,
+			 sizeof(struct slimpro_resp_msg) * ASYNC_MSG_FIFO_SIZE,
+			 GFP_KERNEL);
+	if (rc)
+		goto out_mbox_free;
+
+	INIT_WORK(&ctx->workq, xgene_hwmon_evt_work);
+
+	/* Hook up sysfs for sensor monitor */
+	rc = sysfs_create_group(&pdev->dev.kobj, &xgene_hwmon_attr_group);
+	if (rc) {
+		dev_err(&pdev->dev, "Fail to create sysfs\n");
+		goto out_kfifo_free;
+	}
+
+	ctx->hwmon_dev = hwmon_device_register(ctx->dev);
+	if (IS_ERR(ctx->hwmon_dev)) {
+		dev_err(&pdev->dev, "Failed to register HW monitor device\n");
+		rc = PTR_ERR(ctx->hwmon_dev);
+		goto out;
+	}
+
+	dev_info(&pdev->dev, "APM X-Gene SoC HW monitor driver registered\n");
+
+	return rc;
+
+out:
+	sysfs_remove_group(&pdev->dev.kobj, &xgene_hwmon_attr_group);
+out_kfifo_free:
+	kfifo_free(&ctx->async_msg_fifo);
+out_mbox_free:
+	mbox_free_channel(ctx->mbox_chan);
+
+	return rc;
+}
+
+static int xgene_hwmon_remove(struct platform_device *pdev)
+{
+	struct xgene_hwmon_dev *ctx = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(ctx->hwmon_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &xgene_hwmon_attr_group);
+	kfifo_free(&ctx->async_msg_fifo);
+	mbox_free_channel(ctx->mbox_chan);
+
+	return 0;
+}
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id xgene_hwmon_acpi_match[] = {
+	{"APMC0D29", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, xgene_hwmon_acpi_match);
+#endif
+
+static const struct of_device_id xgene_hwmon_of_match[] = {
+	{.compatible = "apm,xgene-slimpro-hwmon"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, xgene_hwmon_of_match);
+
+static struct platform_driver xgene_hwmon_driver __refdata = {
+	.probe = xgene_hwmon_probe,
+	.remove = xgene_hwmon_remove,
+	.driver = {
+		.name = "xgene-slimpro-hwmon",
+		.of_match_table = xgene_hwmon_of_match,
+		.acpi_match_table = ACPI_PTR(xgene_hwmon_acpi_match),
+	},
+};
+module_platform_driver(xgene_hwmon_driver);
+
+MODULE_DESCRIPTION("APM X-Gene SoC hardware monitor");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From robh at kernel.org  Mon May 16 09:22:05 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 11:22:05 -0500
Subject: [PATCH v9 1/2] Documentation: DT: dma: Add Xilinx zynqmp dma
 device tree binding documentation
In-Reply-To: <1463123033-5443-1-git-send-email-appanad@xilinx.com>
References: <1463123033-5443-1-git-send-email-appanad@xilinx.com>
Message-ID: <20160516162205.GA11930@rob-hp-laptop>

On Fri, May 13, 2016 at 12:33:52PM +0530, Kedareswara rao Appana wrote:
> Device-tree binding documentation for Xilinx zynqmp dma engine
> used in Zynq UltraScale+ MPSoC.
> 
> Signed-off-by: Punnaiah Choudary Kalluri <punnaia at xilinx.com>
> Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
> ---
> Changs in v9:
> - Removed include sg runtime configuration parameter
>   from the binding doc as suggested by Lars.
> Changes in v8:
> - Removed all the software runtime configuration parameters
>   from the binding doc as suggested by the Lars.
> Changes in v7:
> - None.
> Changes in v6:
> - Removed desc-axi-cache/dst-axi-cache/src-axi-cache properties
>   from the binding doc as it allow broken combinations when dma-coherent
>   is set as suggested by Rob.
> - Fixed minor comments given by Rob related coding(lower case DT node name).
> Changes in v5:
> - Use dma-coherent flag for coherent transfers as suggested by rob.
> - Removed unnecessary properties from binding doc as suggested by Rob.
> Changes in v4:
> - None
> Changes in v3:
> - None
> Changes in v2:
> - None.
> 
>  .../devicetree/bindings/dma/xilinx/zynqmp_dma.txt  | 27 ++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/dma/xilinx/zynqmp_dma.txt

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


From catalin.marinas at arm.com  Mon May 16 09:27:58 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Mon, 16 May 2016 16:27:58 +0000
Subject: [PATCH] ARM: Fix A15 798181 errata initialization
In-Reply-To: <5734FA64.6040501@nokia.com>
References: <5734FA64.6040501@nokia.com>
Message-ID: <20160516162757.GA29346@localhost.localdomain>

On Thu, May 12, 2016 at 11:49:24PM +0200, Matija Glavinic Pecotic wrote:
> And here is proposed handling from the same documents [1,2]:
> 
> * In r3p2 and earlier versions with REVIDR[4]= 0,the full workaround is
>   required.
> * In r3p2 and earlier versions with REVIDR[4]=1, REVIDR[9]=0, only the
>   portion of the workaround up to the end of step 6 is required.
> * In r3p2 and earlier versions with REVIDR[4]=1, REVIDR[9]=1, no
>   workaround is required.
> * In r3p3, if REVIDR[9]=0, only the portion of the workaround up
>   to the end of step 6 is required.
> * In r3p3, if REVIDR[9]=1, no workaround is required.
> 
> These imply following:
> 
> REVIDR[9] set -> No WA

The errata documents haven't been updated yet but my reading of the
corresponding ARM support case is that the "REVIDR[9] set" case only
refers to r2p4. It should be a safe assumption for r3pX as well since
REVIDR[9] is an update to the previous REVIDR[4] ECO. Anyway, I asked
ARM support for clarification and get back to you.

> REVIDR[4] set, REVIDR[9] cleared -> Partial WA
> Both cleared -> Full WA

[...]

> diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
> index 2e72be4..b624758 100644
> --- a/arch/arm/kernel/smp_tlb.c
> +++ b/arch/arm/kernel/smp_tlb.c
> @@ -93,17 +93,30 @@ void erratum_a15_798181_init(void)
>  	unsigned int revidr = read_cpuid(CPUID_REVIDR);
>  
>  	/* Brahma-B15 r0p0..r0p2 affected
> -	 * Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
> -	if ((midr & 0xff0ffff0) == 0x420f00f0 && midr <= 0x420f00f2)
> +	 * Cortex-A15 r0p0..r3p3 w/o ECO fix affected
> +	 */

Please add the rXpY ranges and corresponding REVIDR combinations to the
comment above. It makes it easier to read the code later without having
to dig into the commit logs.

> +	if ((midr & 0xff0ffff0) == 0x420f00f0 && midr <= 0x420f00f2) {
>  		erratum_a15_798181_handler = erratum_a15_798181_broadcast;
> -	else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr <= 0x413fc0f2 &&
> -		 (revidr & 0x210) != 0x210) {
> +	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x412fc0f2) {
> +		erratum_a15_798181_handler = erratum_a15_798181_broadcast;
> +	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x412fc0f4) {
>  		if (revidr & 0x10)
>  			erratum_a15_798181_handler =
>  				erratum_a15_798181_partial;
>  		else
>  			erratum_a15_798181_handler =
>  				erratum_a15_798181_broadcast;
> +	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x413fc0f3) {
> +		if ((revidr & 0x210) == 0)
> +			erratum_a15_798181_handler =
> +				erratum_a15_798181_broadcast;
> +		else if (revidr & 0x10)
> +			erratum_a15_798181_handler =
> +				erratum_a15_798181_partial;
> +	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x414fc0f0) {
> +		if ((revidr & 0x200) == 0)
> +			erratum_a15_798181_handler =
> +				erratum_a15_798181_partial;

This looks fine (once ARM support confirms the REVIDR[9] assumption
above.

-- 
Catalin


From robh at kernel.org  Mon May 16 09:32:43 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 11:32:43 -0500
Subject: [PATCH-V2 1/5] dt: bindings: add thermal device driver for bcm2835
In-Reply-To: <1463145186-12906-2-git-send-email-kernel@martin.sperl.org>
References: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
 <1463145186-12906-2-git-send-email-kernel@martin.sperl.org>
Message-ID: <20160516163243.GA20435@rob-hp-laptop>

On Fri, May 13, 2016 at 01:13:02PM +0000, kernel at martin.sperl.org wrote:
> From: Martin Sperl <kernel at martin.sperl.org>
> 
> Add documentation for bcm2835 SOC thermal sensor.
> 
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
> Acked-by: Eric Anholt <eric at anholt.net>
> 
> Changelog:
>  V1 -> V2: renamed file to follow naming conventions
> ---
>  .../bindings/thermal/brcm,bcm2835-thermal.txt           | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
> 
> diff --git a/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
> new file mode 100644
> index 0000000..09de164
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
> @@ -0,0 +1,17 @@
> +Binding for Thermal Sensor driver for BCM2835 SoCs.
> +
> +Required parameters:
> +-------------------
> +
> +compatible: 	should be one of: "brcm,bcm2835-thermal",
> +		"brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
> +reg:		Address range of the thermal registers.
> +clocks: 	Phandle of the clock used by the thermal sensor.
> +
> +Example:
> +
> +thermal: thermal at 0x7e212000 {

Drop the '0x'. Otherwise,

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

> +	compatible = "brcm,bcm2835-thermal";
> +	reg = <0x7e212000 0x8>;
> +	clocks = <&clocks BCM2835_CLOCK_TSENS>;
> +};
> --
> 2.1.4


From robh at kernel.org  Mon May 16 09:41:56 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 11:41:56 -0500
Subject: [PATCH] regulator: axp20x: Add support for the (external)
 drivebus regulator
In-Reply-To: <1463248545-16543-1-git-send-email-hdegoede@redhat.com>
References: <1463248545-16543-1-git-send-email-hdegoede@redhat.com>
Message-ID: <20160516164156.GA24677@rob-hp-laptop>

On Sat, May 14, 2016 at 07:55:45PM +0200, Hans de Goede wrote:
> The axp20x pmics have 2 power inputs, one called ACIN which is intended
> for to be supplied via a powerbarrel on the board and one called VBUS
> which is intended to be supplied via an otg connector.
> 
> In the VBUS case the pmic needs to know if the board is supplying power
> to the otg connector, because then it should not take any power from
> its VBUS pin. The axp209 pmic has a N_VBUSEN input pin via which the
> board can signal to the pmic whether the board is supplying power to the
> otg connector or not.
> 
> On the axp221/axp223 this pin can alternatively be used as an output
> which controls an external regulator which (optionally) supplies
> power to the otg connector from the board. When the pin is used as
> output it is called DRIVEBUS in the datasheet.
> 
> This commit adds support for the DRIVEBUS pin as an extra pmic
> controlled regulator. Since this is optional a new x-powers,drivebus dt
> property is added. When this is present the misc-control register is
> written to change the N_VBUSEN input pin to DRIVEBUS output pin mode and
> the extra drivebus regulator is registered with the regulator subsystem.
> 
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> ---
>  Documentation/devicetree/bindings/mfd/axp20x.txt |  5 ++++
>  drivers/regulator/axp20x-regulator.c             | 30 ++++++++++++++++++++++++
>  2 files changed, 35 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
> index d20b103..7a88479 100644
> --- a/Documentation/devicetree/bindings/mfd/axp20x.txt
> +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
> @@ -22,6 +22,11 @@ Optional properties:
>  		      AXP152/20X: range:  750-1875, Default: 1.5 MHz
>  		      AXP22X/80X: range: 1800-4050, Default: 3   MHz
>  
> +- x-powers,drivebus: axp221 / axp223 only boolean, set this when the N_VBUSEN

x-powers,drive-vbus-en

> +                  pin is used as an output pin to control an external regulator
> +                  to drive the OTG VBus, rather then as an input pin which
> +                  signals whether the board is driving OTG VBus or not.
> +
>  - <input>-supply: a phandle to the regulator supply node. May be omitted if
>  		  inputs are unregulated, such as using the IPSOUT output
>  		  from the PMIC.


From f.fainelli at gmail.com  Mon May 16 09:43:24 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Mon, 16 May 2016 09:43:24 -0700
Subject: [PATCH-V2 5/5] ARM: multi_v7_defconfig: bcm2835: add
 bcm2835-thermal driver
In-Reply-To: <1463145186-12906-6-git-send-email-kernel@martin.sperl.org>
References: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
 <1463145186-12906-6-git-send-email-kernel@martin.sperl.org>
Message-ID: <5739F8AC.8080003@gmail.com>

On 05/13/2016 06:13 AM, kernel at martin.sperl.org wrote:
> From: Martin Sperl <kernel at martin.sperl.org>
> 
> Add the thermal driver to list of compiled modules in
> multi_v7_defconfig.
> 
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
> ---
>  arch/arm/configs/multi_v7_defconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> index 2823490..5f0f5a3 100644
> --- a/arch/arm/configs/multi_v7_defconfig
> +++ b/arch/arm/configs/multi_v7_defconfig
> @@ -422,6 +422,7 @@ CONFIG_CPU_THERMAL=y
>  CONFIG_ROCKCHIP_THERMAL=y
>  CONFIG_RCAR_THERMAL=y
>  CONFIG_ARMADA_THERMAL=y
> +CONFIG_BCM2835_THERMAL=y

Does this need to be built into the kernel?
-- 
Florian


From robh at kernel.org  Mon May 16 09:44:14 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 11:44:14 -0500
Subject: [PATCH V4 2/7] documentation: iommu: Add bindings for
 msm,iommu-v0 ip
In-Reply-To: <1463381341-30498-3-git-send-email-sricharan@codeaurora.org>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
 <1463381341-30498-3-git-send-email-sricharan@codeaurora.org>
Message-ID: <20160516164414.GA25899@rob-hp-laptop>

On Mon, May 16, 2016 at 12:18:56PM +0530, Sricharan R wrote:
> The MSM IOMMU is an implementation compatible with the ARM VMSA short
> descriptor page tables. It provides address translation for bus masters outside
> of the CPU, each connected to the IOMMU through a port called micro-TLB.
> Adding the DT bindings for the same.
> 
> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> ---
>  .../devicetree/bindings/iommu/msm,iommu-v0.txt     | 64 ++++++++++++++++++++++
>  1 file changed, 64 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
> 
> diff --git a/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
> new file mode 100644
> index 0000000..b22c607
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
> @@ -0,0 +1,64 @@
> +* QCOM IOMMU
> +
> +The MSM IOMMU is an implementation compatible with the ARM VMSA short
> +descriptor page tables. It provides address translation for bus masters outside
> +of the CPU, each connected to the IOMMU through a port called micro-TLB.
> +
> +Required Properties:
> +
> +  - compatible: Must contain "qcom,iommu-v0-apq8064".

qcom,apq8064-iommu would be the preferred order and I think you can drop 
the v0.


From robh at kernel.org  Mon May 16 09:45:38 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 16 May 2016 11:45:38 -0500
Subject: [PATCH v10 6/8] dt-bindings: i2c: rk3x: add support for rk3399
In-Reply-To: <1463407452-41418-1-git-send-email-david.wu@rock-chips.com>
References: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
 <1463407452-41418-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <20160516164538.GA27178@rob-hp-laptop>

On Mon, May 16, 2016 at 10:04:12PM +0800, David Wu wrote:
> The bus clock and function clock are separated at rk3399,
> and others use one clock as the bus clock and function clock.
> 
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> Reviewed-by: Douglas Anderson <dianders at chromium.org>
> Reviewed-by: Heiko Stuebner <heiko at sntech.de>
> Tested-by: Heiko Stuebner <heiko at sntech.de>
> ---
> Change in v10:
> - none
> 
> Change in v9:
> - remove unnecessary "REQUIRED".
> 
> Change in v8:
> - remove error description.
> 
>  Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 16 +++++++++++++---
>  1 file changed, 13 insertions(+), 3 deletions(-)

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


From catalin.marinas at arm.com  Mon May 16 10:06:05 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Mon, 16 May 2016 18:06:05 +0100
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <20160514150352.GA30533@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1459894127-17698-21-git-send-email-ynorov@caviumnetworks.com>
 <20160514150352.GA30533@yury-N73SV>
Message-ID: <20160516170605.GB19290@e104818-lin.cambridge.arm.com>

On Sat, May 14, 2016 at 06:03:52PM +0300, Yury Norov wrote:
> +SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
> +       unsigned long, prot, unsigned long, flags, unsigned long, fd,
> +       unsigned long, pgoff)

To avoid the types confusion we could add __SC_WRAP to mmap2 in unistd.h
and use COMPAT_SYSCALL_DEFINE6 here (together with compat_ptr_t etc.).

> +{
> +       if (pgoff & (~PAGE_MASK >> 12))
> +               return -EINVAL;
> +
> +       return sys_mmap_pgoff((compat_uptr_t) addr, (compat_size_t) len,
> +		       (int) prot, (int) flags, (int) fd,
> +		       pgoff >> (PAGE_SHIFT-12));

Then we wouldn't need the explicit casting here.

> +}
> +
> +COMPAT_SYSCALL_DEFINE4(pread64, unsigned int, fd, compat_uptr_t __user *, ubuf,
> +		       compat_size_t, count, off_t, offset)
> +{
> +	return sys_pread64(fd, (char *) ubuf, count, offset);
> +}
> +
> +COMPAT_SYSCALL_DEFINE4(pwrite64, unsigned int, fd, compat_uptr_t __user *, ubuf,
> +		       compat_size_t, count, off_t, offset)
> +{
> +	return sys_pwrite64(fd, (char *) ubuf, count, offset);

Nitpick: no space between cast type and variable name: (char *)ubuf, ...

We can also make these functions static as they are not used outside
this file.

-- 
Catalin


From wens at csie.org  Mon May 16 10:06:32 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 01:06:32 +0800
Subject: [PATCH] regulator: axp20x: Add support for the (external)
 drivebus regulator
In-Reply-To: <1463248545-16543-1-git-send-email-hdegoede@redhat.com>
References: <1463248545-16543-1-git-send-email-hdegoede@redhat.com>
Message-ID: <CAGb2v67iPsUAG=Sgk8z-G3KjVb4WoMUutUPKdQ9s=OOCk_jgqg@mail.gmail.com>

Hi,

On Sun, May 15, 2016 at 1:55 AM, Hans de Goede <hdegoede at redhat.com> wrote:
> The axp20x pmics have 2 power inputs, one called ACIN which is intended
> for to be supplied via a powerbarrel on the board and one called VBUS
> which is intended to be supplied via an otg connector.
>
> In the VBUS case the pmic needs to know if the board is supplying power
> to the otg connector, because then it should not take any power from
> its VBUS pin. The axp209 pmic has a N_VBUSEN input pin via which the
> board can signal to the pmic whether the board is supplying power to the
> otg connector or not.
>
> On the axp221/axp223 this pin can alternatively be used as an output
> which controls an external regulator which (optionally) supplies
> power to the otg connector from the board. When the pin is used as
> output it is called DRIVEBUS in the datasheet.

The datasheet actually calls it DRIVEVBUS. DRIVEBUS seems to be some
typo Allwinner has in their code.

>
> This commit adds support for the DRIVEBUS pin as an extra pmic
> controlled regulator. Since this is optional a new x-powers,drivebus dt
> property is added. When this is present the misc-control register is
> written to change the N_VBUSEN input pin to DRIVEBUS output pin mode and
> the extra drivebus regulator is registered with the regulator subsystem.
>
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> ---
>  Documentation/devicetree/bindings/mfd/axp20x.txt |  5 ++++
>  drivers/regulator/axp20x-regulator.c             | 30 ++++++++++++++++++++++++
>  2 files changed, 35 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
> index d20b103..7a88479 100644
> --- a/Documentation/devicetree/bindings/mfd/axp20x.txt
> +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
> @@ -22,6 +22,11 @@ Optional properties:
>                       AXP152/20X: range:  750-1875, Default: 1.5 MHz
>                       AXP22X/80X: range: 1800-4050, Default: 3   MHz
>
> +- x-powers,drivebus: axp221 / axp223 only boolean, set this when the N_VBUSEN
> +                  pin is used as an output pin to control an external regulator
> +                  to drive the OTG VBus, rather then as an input pin which
> +                  signals whether the board is driving OTG VBus or not.
> +

You should also add it to the regulators table further down in the binding.
And, as Rob mentioned, x-powers,drive-vbus-en (or drivevbus-en) is better
for a boolean property.

>  - <input>-supply: a phandle to the regulator supply node. May be omitted if
>                   inputs are unregulated, such as using the IPSOUT output
>                   from the PMIC.
> diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
> index 514a5e8..2422ddd 100644
> --- a/drivers/regulator/axp20x-regulator.c
> +++ b/drivers/regulator/axp20x-regulator.c
> @@ -36,6 +36,8 @@
>
>  #define AXP20X_FREQ_DCDC_MASK          0x0f
>
> +#define AXP22X_MISC_N_VBUSEN_FUNC      BIT(4)
> +
>  #define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,   \
>                     _vmask, _ereg, _emask, _enable_val, _disable_val)           \
>         [_family##_##_id] = {                                                   \
> @@ -230,6 +232,18 @@ static const struct regulator_desc axp22x_regulators[] = {
>         AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
>  };
>
> +static const struct regulator_desc axp22x_drivebus_regulator = {
> +       .name           = "drivebus",
> +       .supply_name    = "ips",

Given that you are approximating a gpio (in this case, the
N_VBUSEN/DRIVEVBUS pin)
controlled fixed voltage regulator, it would be better if you could:

a) have some way to specify the output voltage, so it looks like a fixed voltage
   regulator that can be turned on/off.

And

b) have a separate supply name for this so it properly propagates enable/disable
   calls. It would also pass the upstream voltage, thus behaving like a switch
   you intended with the axp20x_ops_sw below.


Regards
ChenYu

> +       .of_match       = of_match_ptr("drivebus"),
> +       .regulators_node = of_match_ptr("regulators"),
> +       .type           = REGULATOR_VOLTAGE,
> +       .owner          = THIS_MODULE,
> +       .enable_reg     = AXP20X_VBUS_IPSOUT_MGMT,
> +       .enable_mask    = BIT(2),
> +       .ops            = &axp20x_ops_sw,
> +};
> +
>  static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
>  {
>         struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
> @@ -354,6 +368,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
>         u32 workmode;
>         const char *axp22x_dc1_name = axp22x_regulators[AXP22X_DCDC1].name;
>         const char *axp22x_dc5_name = axp22x_regulators[AXP22X_DCDC5].name;
> +       bool drivebus = false;
>
>         switch (axp20x->variant) {
>         case AXP202_ID:
> @@ -365,6 +380,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
>         case AXP223_ID:
>                 regulators = axp22x_regulators;
>                 nregulators = AXP22X_REG_ID_MAX;
> +               drivebus = of_property_read_bool(pdev->dev.parent->of_node,
> +                                                "x-powers,drivebus");
>                 break;
>         default:
>                 dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
> @@ -439,6 +456,19 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
>                 }
>         }
>
> +       if (drivebus) {
> +               /* Change N_VBUSEN sense pin to DRIVEBUS output pin */
> +               regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP,
> +                                  AXP22X_MISC_N_VBUSEN_FUNC, 0);
> +               rdev = devm_regulator_register(&pdev->dev,
> +                                              &axp22x_drivebus_regulator,
> +                                              &config);
> +               if (IS_ERR(rdev)) {
> +                       dev_err(&pdev->dev, "Failed to register drivebus\n");
> +                       return PTR_ERR(rdev);
> +               }
> +       }
> +
>         return 0;
>  }
>
> --
> 2.7.4
>


From wens at csie.org  Mon May 16 10:13:01 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 01:13:01 +0800
Subject: [PATCH 14/20] ARM: sun5i: a13: Add LCD pins
In-Reply-To: <1463402840-17062-15-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-15-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v66g_xZEyOf8ky_TKpT70D_EQwirVKNMQbubT5U2cD8rnw@mail.gmail.com>

On Mon, May 16, 2016 at 8:47 PM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> The RGB bus can be used in several configurations, one of which being the
> RGB666.
>
> Add a pinctrl group for that case.
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>

Acked-by: Chen-Yu Tsai <wens at csie.org>

> ---
>  arch/arm/boot/dts/sun5i-a13.dtsi | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
> index 263d46dbc7e6..79b5d513c142 100644
> --- a/arch/arm/boot/dts/sun5i-a13.dtsi
> +++ b/arch/arm/boot/dts/sun5i-a13.dtsi
> @@ -237,6 +237,16 @@
>  &pio {
>         compatible = "allwinner,sun5i-a13-pinctrl";
>
> +       lcd_rgb666_pins: lcd_rgb666 at 0 {
> +               allwinner,pins = "PD2", "PD3", "PD4", "PD5", "PD6", "PD7",
> +                                "PD10", "PD11", "PD12", "PD13", "PD14", "PD15",
> +                                "PD18", "PD19", "PD20", "PD21", "PD22", "PD23",
> +                                "PD24", "PD25", "PD26", "PD27";
> +               allwinner,function = "lcd0";
> +               allwinner,drive = <SUN4I_PINCTRL_10_MA>;

Just a thought: would we ever need to increase the drive strength for very high
resolutions?

> +               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
> +       };
> +
>         uart1_pins_a: uart1 at 0 {
>                 allwinner,pins = "PE10", "PE11";
>                 allwinner,function = "uart1";
> --
> 2.8.2
>


From Liviu.Dudau at arm.com  Mon May 16 10:17:46 2016
From: Liviu.Dudau at arm.com (Liviu Dudau)
Date: Mon, 16 May 2016 18:17:46 +0100
Subject: Juno r0 fails to boot with linux-next 20160516
Message-ID: <20160516171745.GB26180@e106497-lin.cambridge.arm.com>

Hi Mathieu,

I was trying to boot linux-next 20150516 today on Juno r0 and it gets stuck
after printing the message:

Serial: AMBA PL011 UART driver

Bisecting shows commit d02e8a63733ff9121 as the culprit:

commit d02e8a63733ff912128c04a091c0de75be8df1ab
Author: Mathieu Poirier <mathieu.poirier at linaro.org>
Date:   Sun Oct 18 16:50:48 2015 -0600

    coresight: Add support for Juno platform
    
    This patch adds support for ARM's juno platform.  More
    specifically it has definitions for the A53/57 tracers,
    the A53/57 cluster funnels, the main funnel and the ETF
    in circular buffer mode.
    
    Support for all the other coresight IP blocks is not
    addressed.
    
    Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>

Juno r1 is not affected as you are modifying only the juno.dts file. Also,
if I have the DSTREAM unit connected to the boot core the kernel boots fine,
which leads me to believe that there is some power domain issue at play (?).
Also, reverting the patch gets r0 to boot again.

This is the bisection log:

$ git bisect start HEAD v4.6-rc7
Bisecting: 5755 revisions left to test after this (roughly 13 steps)
[027e278cc4d21e4718be4ea5bb14e360ff259174] Merge remote-tracking branch 'crypto/master'
$ git bisect good
Bisecting: 2836 revisions left to test after this (roughly 12 steps)
[b14343bae9270c97b7b6b4652157577d2786c591] Merge remote-tracking branch 'tip/auto-latest'
$ git bisect good
Bisecting: 1350 revisions left to test after this (roughly 11 steps)
[98efb6a2745524fc404211e266f54bf409063364] Merge remote-tracking branch 'staging/staging-next'
$ git bisect good
Bisecting: 687 revisions left to test after this (roughly 9 steps)
[ecf549d34f211f9bae0dfab98f994825b0891648] Merge remote-tracking branch 'pwm/for-next'
$ git bisect good
Bisecting: 343 revisions left to test after this (roughly 9 steps)
[fb86798c5cdd615f5c9780eca36a232434f4d63b] nilfs2: fix white space issue in nilfs_mount()
$ git bisect good
Bisecting: 158 revisions left to test after this (roughly 8 steps)
[ae82fd28e602ddab3381d76603a0af9e87a5e2aa] Merge remote-tracking branch 'coresight/next'
$ git bisect bad
Bisecting: 92 revisions left to test after this (roughly 7 steps)
[98b8525abb7f0d9a5ab942a2e044011d7e635490] clk: sunxi: Add display and TCON0 clocks driver
$ git bisect good
Bisecting: 51 revisions left to test after this (roughly 6 steps)
[6d9122078097233dbfc4ad3a45512393cddf8540] Merge branch 'for-4.7/core' into for-next
$ git bisect good
Bisecting: 25 revisions left to test after this (roughly 5 steps)
[25d894772abc89f78512cf640250514be87a3b46] coresight: tmc: introducing new header file
$ git bisect bad
Bisecting: 12 revisions left to test after this (roughly 4 steps)
[63f09f1d779856b615768a97c641ab26126c9183] coresight: no need to do the forced type conversion
$ git bisect bad
Bisecting: 6 revisions left to test after this (roughly 3 steps)
[0cce003868b664547d9e5dd1f586b902cca43784] coresight: etm4x: unlocking tracers in default arch init
$ git bisect bad
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[dd7ebddfdad8d379887f9e2f74d0ba207b59cb77] coresight: etm4x: adding config and traceid registers
$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 1 step)
[d03196055ea8b535a346239307dfa797bc4059d2] coresight: etm4x: moving sysFS entries to a dedicated file
$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[d02e8a63733ff912128c04a091c0de75be8df1ab] coresight: Add support for Juno platform


Best regards,
Liviu

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ?\_(?)_/?


From wens at csie.org  Mon May 16 10:18:44 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 01:18:44 +0800
Subject: [PATCH 06/20] drm/sun4i: allow dclk to modify its parent rate
In-Reply-To: <1463402840-17062-7-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-7-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v65tiUt9FvmJ2RaZdXaAFEznKZZjycO+tZcP-4spOAjObQ@mail.gmail.com>

Hi,

On Mon, May 16, 2016 at 8:47 PM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> The pixel clock being only a divider of its parent clock, depending on the
> resolution, it's expected to change its parent rate. Add that flag so that
> the clock framework knows it.

This should be squashed into the previous patch. Otherwise, the previous one
doesn't really fix things, and probably makes things worse as it assumes the
parent clock would be changed.

ChenYu

> Fixes: 9026e0d122ac ("drm: Add Allwinner A10 Display Engine support")
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_dotclock.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
> index 1ddf6d7a7107..5b3463197c48 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
> @@ -170,6 +170,7 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
>         init.ops = &sun4i_dclk_ops;
>         init.parent_names = &parent_name;
>         init.num_parents = 1;
> +       init.flags = CLK_SET_RATE_PARENT;
>
>         dclk->regmap = tcon->regs;
>         dclk->hw.init = &init;
> --
> 2.8.2
>


From dianders at chromium.org  Mon May 16 10:22:41 2016
From: dianders at chromium.org (Doug Anderson)
Date: Mon, 16 May 2016 10:22:41 -0700
Subject: [PATCH v10 7/8] i2c: rk3x: add i2c support for rk3399 soc
In-Reply-To: <1463407503-41466-1-git-send-email-david.wu@rock-chips.com>
References: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
 <1463407503-41466-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=UZ+HF-21UJv1xS4a-yssYGC5Y71ngn2=wGSOkceiV+yQ@mail.gmail.com>

David,

On Mon, May 16, 2016 at 7:05 AM, David Wu <david.wu at rock-chips.com> wrote:
> - new method to caculate i2c timings for rk3399:
>   There was an timing issue about "repeated start" time at the I2C
>   controller of version0, controller appears to drop SDA at .875x (7/8)
>   programmed clk high. On version 1 of the controller, the rule(.875x)
>   isn't enough to meet tSU;STA
>   requirements on 100k's Standard-mode. To resolve this issue,
>   sda_update_config, start_setup_config and stop_setup_config for I2C
>   timing information are added, new rules are designed to calculate
>   the timing information at new v1.
> - pclk and function clk are separated at rk3399
>
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> Tested-by: Caesar Wang <wxt at rock-chips.com>
> Tested-by: Heiko Stuebner <heiko at sntech.de>
> ---
> Change in v10:
> - fix the clean of con register in rk3x_i2c_stop()
>
> Change in v9:
> - add spin lock for tuning updated in rk3x_i2c_adapt_div() (Doug)
>
> Changes in v8:
> - update tuning in RKI2C_CON register by doing a read-modify-write (Doug)
> - new method to use pclk and clk (Doug)
>
> Changes in v7:
> - transform into a 9 series patches (Doug)
> - drop highspeed with mastercode, and support fast-mode plus (Doug)
>
>  drivers/i2c/busses/i2c-rk3x.c | 294 +++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 274 insertions(+), 20 deletions(-)

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


From davem at davemloft.net  Mon May 16 10:40:14 2016
From: davem at davemloft.net (David Miller)
Date: Mon, 16 May 2016 13:40:14 -0400 (EDT)
Subject: [PATCH 0/2] net: pxa168_eth: improve performance
In-Reply-To: <1463140650-7038-1-git-send-email-jszhang@marvell.com>
References: <1463140650-7038-1-git-send-email-jszhang@marvell.com>
Message-ID: <20160516.134014.1782979464569219380.davem@davemloft.net>

From: Jisheng Zhang <jszhang at marvell.com>
Date: Fri, 13 May 2016 19:57:28 +0800

> This series is to improve the pxa168_eth driver performance by using
> {readl|writel}_relaxed or appropriate memory barriers.

Applied.


From festevam at gmail.com  Mon May 16 10:42:45 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 16 May 2016 14:42:45 -0300
Subject: [PATCH v3 1/2] dt-bindings: Add vendor prefix for TechNexion
In-Reply-To: <1461636753-9567-1-git-send-email-festevam@gmail.com>
References: <1461636753-9567-1-git-send-email-festevam@gmail.com>
Message-ID: <CAOMZO5Av+3EmimGwn-hCvXS9kztpoeSEueAa83gKrAiTqVHdTA@mail.gmail.com>

On Mon, Apr 25, 2016 at 11:12 PM, Fabio Estevam <festevam at gmail.com> wrote:
> From: Fabio Estevam <fabio.estevam at nxp.com>
>
> TechNexion designs and manufactures embedded computing systems:
> http://www.technexion.com/
>
> Cc: Rob Herring <robh at kernel.org>

Rob,

Any comments?


> Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
> ---
> Changes since v2:
> - Fix Rob's email address
> Changes since v1:
> - None
>
>  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 41f6152..5c943fc 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -246,6 +246,7 @@ synology    Synology, Inc.
>  SUNW   Sun Microsystems, Inc
>  tbs    TBS Technologies
>  tcl    Toby Churchill Ltd.
> +technexion     TechNexion
>  technologic    Technologic Systems
>  thine  THine Electronics, Inc.
>  ti     Texas Instruments
> --
> 1.9.1
>


From will.deacon at arm.com  Mon May 16 10:48:23 2016
From: will.deacon at arm.com (Will Deacon)
Date: Mon, 16 May 2016 18:48:23 +0100
Subject: [GIT PULL] arm64: updates for 4.7
Message-ID: <20160516174823.GA22358@arm.com>

Hi Linus,

Here's the arm64 queue for 4.7 -- the highlights are detailed in the tag.

There are a few changes here outside of arch/arm64/ as a result of
dependencies (all acked by the relevant maintainers), but these have
generated some conflicts in linux-next:

  1. KVM: There is a conflict in arch/arm/kvm/arm.c with mainline
     (06a71a24bae5). The resolution is small, but slightly confusing,
     since the conflict is around a register_cpu_notifier and the
     resolution removes the corresponding unregister_cpu_notifier.

  2. Xen: Minor conflict due to everybody changing their initialisation
     order in setup_arch.

  3. EFI: Minor conflict with removal of global 'memmap' symbol

  4. Irqchip: Churn in the GIC driver (ARM's interrupt controller)
     conflicting with the rework of our CPU feature interface, which
     is used to detect broken firmware/hardware.

I've included the resolutions from linux-next in order below. The pull
request follows the resolutions.

Thanks,

Will

--->8

diff --cc arch/arm/kvm/arm.c
index dded1b763c16,1687e1450c3a..000000000000
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@@ -1198,8 -1226,6 +1233,7 @@@ static void teardown_hyp_mode(void
  	free_hyp_pgds();
  	for_each_possible_cpu(cpu)
  		free_page(per_cpu(kvm_arm_hyp_stack_page, cpu));
- 	unregister_cpu_notifier(&hyp_init_cpu_nb);
 +	hyp_cpu_pm_exit();
  }
  
  static int init_vhe_mode(void)

--->8

diff --cc arch/arm64/kernel/setup.c
index 65f515949baa,7cf992fe6684..000000000000
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@@ -277,13 -336,13 +278,11 @@@ void __init setup_arch(char **cmdline_p
  
  	early_ioremap_reset();
  
 -	if (acpi_disabled) {
 -		unflatten_device_tree();
 +	if (acpi_disabled)
  		psci_dt_init();
 -	} else {
 +	else
  		psci_acpi_init();
 -	}
  
- 	xen_early_init();
- 
  	cpu_read_bootcpu_ops();
  	smp_init_cpus();
  	smp_build_mpidr_hash();

--->8

diff --cc drivers/firmware/efi/arm-init.c
index fac567c3b66a,ef90f0c4b70a..000000000000
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@@ -143,15 -178,7 +178,15 @@@ static __init void reserve_regions(void
  	if (efi_enabled(EFI_DBG))
  		pr_info("Processing EFI memory map:\n");
  
 +	/*
 +	 * Discard memblocks discovered so far: if there are any at this
 +	 * point, they originate from memory nodes in the DT, and UEFI
 +	 * uses its own memory map instead.
 +	 */
 +	memblock_dump_all();
 +	memblock_remove(0, (phys_addr_t)ULLONG_MAX);
 +
- 	for_each_efi_memory_desc(&memmap, md) {
+ 	for_each_efi_memory_desc(md) {
  		paddr = md->phys_addr;
  		npages = md->num_pages;

--->8

diff --cc drivers/irqchip/irq-gic.c
index 095bb5b5c3f2,113e2d02c812..000000000000
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@@ -489,8 -486,9 +486,10 @@@ static int gic_cpu_init(struct gic_chip
  		/*
  		 * Get what the GIC says our CPU mask is.
  		 */
- 		BUG_ON(cpu >= NR_GIC_CPU_IF);
+ 		if (WARN_ON(cpu >= NR_GIC_CPU_IF))
+ 			return -EINVAL;
+ 
 +		gic_check_cpu_features();
  		cpu_mask = gic_get_cpumask(gic);
  		gic_cpu_map[cpu] = cpu_mask;
  
@@@ -1012,24 -1029,28 +1030,26 @@@ static const struct irq_domain_ops gic_
  	.unmap = gic_irq_domain_unmap,
  };
  
- static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
- 			   void __iomem *dist_base, void __iomem *cpu_base,
- 			   u32 percpu_offset, struct fwnode_handle *handle)
+ static int __init __gic_init_bases(struct gic_chip_data *gic, int irq_start,
+ 				   struct fwnode_handle *handle)
  {
  	irq_hw_number_t hwirq_base;
- 	struct gic_chip_data *gic;
- 	int gic_irqs, irq_base, i;
- 
- 	BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
+ 	int gic_irqs, irq_base, i, ret;
  
- 	gic = &gic_data[gic_nr];
+ 	if (WARN_ON(!gic || gic->domain))
+ 		return -EINVAL;
  
 -	gic_check_cpu_features();
 -
  	/* Initialize irq_chip */
- 	if (static_key_true(&supports_deactivate) && gic_nr == 0) {
- 		gic->chip = gic_eoimode1_chip;
+ 	gic->chip = gic_chip;
+ 
+ 	if (static_key_true(&supports_deactivate) && gic == &gic_data[0]) {
+ 		gic->chip.irq_mask = gic_eoimode1_mask_irq;
+ 		gic->chip.irq_eoi = gic_eoimode1_eoi_irq;
+ 		gic->chip.irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity;
+ 		gic->chip.name = kasprintf(GFP_KERNEL, "GICv2");
  	} else {
- 		gic->chip = gic_chip;
- 		gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d", gic_nr);
+ 		gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d",
+ 					   (int)(gic - &gic_data[0]));
  	}
  
  #ifdef CONFIG_SMP

--->8

The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:

  Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git tags/arm64-upstream

for you to fetch changes up to e6d9a52543338603e25e71e0e4942f05dae0dd8a:

  arm64: do not enforce strict 16 byte alignment to stack pointer (2016-05-12 14:20:49 +0100)

----------------------------------------------------------------
arm64 updates for 4.7:

- virt_to_page/page_address optimisations

- Support for NUMA systems described using device-tree

- Support for hibernate/suspend-to-disk

- Proper support for maxcpus= command line parameter

- Detection and graceful handling of AArch64-only CPUs

- Miscellaneous cleanups and non-critical fixes

----------------------------------------------------------------
AKASHI Takahiro (1):
      arm64: kvm: allows kvm cpu hotplug

Anna-Maria Gleixner (2):
      arm64/debug: Remove superfluous SMP function call
      arm64: hw-breakpoint: Remove superfluous SMP function call

Ard Biesheuvel (30):
      arm64/mm: ensure memstart_addr remains sufficiently aligned
      arm64: choose memstart_addr based on minimum sparsemem section alignment
      Revert "arm64: account for sparsemem section alignment when choosing vmemmap offset"
      arm64: add the initrd region to the linear mapping explicitly
      arm64: remove the now unneeded relocate_initrd()
      arm64: vdso: avoid virt_to_page() translations on kernel symbols
      arm64: mm: free __init memory via the linear mapping
      arm64: mm: avoid virt_to_page() translation for the zero page
      arm64: insn: avoid virt_to_page() translations on core kernel symbols
      arm64: mm: move vmemmap region right below the linear region
      arm64: mm: restrict virt_to_page() to the linear mapping
      arm64: use 'segment' rather than 'chunk' to describe mapped kernel regions
      arm64: move early boot code to the .init segment
      arm64: cover the .head.text section in the .text segment mapping
      arm64: simplify kernel segment mapping granularity
      efi: ARM/arm64: ignore DT memory nodes instead of removing them
      nios2: use correct void* return type for page_to_virt()
      openrisc: drop wrongly typed definition of page_to_virt()
      mm: replace open coded page to virt conversion with page_to_virt()
      arm64: ptdump: use static initializers for vmemmap region boundaries
      arm64: ptdump: add region marker for kasan shadow region
      arm64: kernel: don't export local symbols from head.S
      arm64: kernel: use literal for relocated address of __secondary_switched
      arm64: kernel: perform relocation processing from ID map
      arm64: introduce mov_q macro to move a constant into a 64-bit register
      arm64: kernel: replace early 64-bit literal loads with move-immediates
      arm64: don't map TEXT_OFFSET bytes below the kernel if we can avoid it
      arm64: relocatable: deal with physically misaligned kernel images
      arm64: acpi: add acpi=on cmdline option to prefer ACPI boot over DT
      arm64: kaslr: increase randomization granularity

Arnd Bergmann (1):
      efi: ARM: avoid warning about phys_addr_t cast

Catalin Marinas (5):
      arm64: Implement ptep_set_access_flags() for hardware AF/DBM
      arm64: Fix typo in the pmdp_huge_get_and_clear() definition
      arm64: Implement pmdp_set_access_flags() for hardware AF/DBM
      arm64: Replace hard-coded values in the pmd/pud_bad() macros
      arm64: Ensure pmd_present() returns false after pmd_mknotpresent()

Colin Ian King (1):
      arm64: do not enforce strict 16 byte alignment to stack pointer

David Daney (2):
      of, numa: Add NUMA of binding implementation.
      arm64: Move unflatten_device_tree() call earlier.

Ezequiel Garcia (1):
      arm64: kconfig: drop CONFIG_RTC_LIB dependency

Ganapatrao Kulkarni (3):
      Documentation, dt, numa: dt bindings for NUMA.
      arm64, numa: Add NUMA support for arm64 platforms.
      arm64, mm, numa: Add NUMA balancing support for arm64.

Geoff Levand (4):
      arm64: Fold proc-macros.S into assembler.h
      arm64: Cleanup SCTLR flags
      arm64: hyp/kvm: Make hyp-stub extensible
      arm64: Add new asm macro copy_page

Huang Shijie (1):
      arm64: mm: remove the redundant code

James Morse (11):
      arm64: mm: Add trace_irqflags annotations to do_debug_exception()
      arm64: kvm: Move lr save/restore from do_el2_call into EL1
      arm64: hyp/kvm: Make hyp-stub reject kvm_call_hyp()
      arm64: kernel: Rework finisher callback out of __cpu_suspend_enter()
      arm64: Change cpu_resume() to enable mmu early then access sleep_sp by va
      arm64: kernel: Include _AC definition in page.h
      arm64: Promote KERNEL_START/KERNEL_END definitions to a header file
      PM / Hibernate: Call flush_icache_range() on pages restored in-place
      arm64: kernel: Add support for hibernate/suspend-to-disk
      arm64: hibernate: Refuse to hibernate if the boot cpu is offline
      arm64: kvm: Fix kvm teardown for systems using the extended idmap

Jan Glauber (1):
      arm64: Reduce verbosity on SMP CPU stop

Jisheng Zhang (1):
      arm64: cpuidle: make arm_cpuidle_suspend() a bit more efficient

Julien Grall (1):
      arm64: cpuinfo: Missing NULL terminator in compat_hwcap_str

Kees Cook (1):
      arm64: kernel: Fix incorrect brk randomization

Kefeng Wang (3):
      arm64: cpufeature: append additional id_aa64mmfr2 fields to cpufeature
      arm64: mm: make pr_cont() per line in Virtual kernel memory layout
      arm64: mm: Show bss segment in kernel memory layout

Marc Zyngier (2):
      arm64: Allow a capability to be checked on a single CPU
      irqchip/gic: Restore CPU interface checking

Mark Rutland (2):
      arm64: asm: remove unused push/pop macros
      arm64: make dt_scan_depth1_nodes more readable

Robin Murphy (2):
      arm64/dma-mapping: Extend DMA ops workaround to PCI devices
      arm64/dma-mapping: Remove default domain workaround

Shannon Zhao (1):
      ARM64: ACPI: Check if it runs on Xen to enable or disable ACPI

Suzuki K Poulose (12):
      arm64: Add cpu_panic_kernel helper
      arm64: vhe: Verify CPU Exception Levels
      arm64: hwcaps: Cleanup naming
      arm64: HWCAP: Split COMPAT HWCAP table entries
      arm64: Add helpers for detecting AArch32 support at EL0
      arm64: cpufeature: Check availability of AArch32
      arm64: cpufeature: Track 32bit EL0 support
      arm64: compat: Check for AArch32 state
      arm64: cpufeature: Add scope for capability check
      arm64: Verify CPU errata work arounds on hotplugged CPU
      arm64: Fix behavior of maxcpus=N
      arm64: secondary_start_kernel: Remove unnecessary barrier

Will Deacon (1):
      arm64: make ARCH_SUPPORTS_DEBUG_PAGEALLOC depend on !HIBERNATION

Yang Shi (3):
      arm64: Kconfig: remove redundant HAVE_ARCH_TRANSPARENT_HUGEPAGE definition
      arm64: always use STRICT_MM_TYPECHECKS
      arm64: mm: remove unnecessary EXPORT_SYMBOL_GPL

 Documentation/arm64/booting.txt            |   4 +
 Documentation/devicetree/bindings/numa.txt | 275 ++++++++++++++++
 Documentation/kernel-parameters.txt        |   6 +-
 arch/arm/include/asm/kvm_host.h            |  10 +-
 arch/arm/include/asm/kvm_mmu.h             |   1 +
 arch/arm/kvm/arm.c                         | 119 ++++---
 arch/arm/kvm/mmu.c                         |   5 +
 arch/arm64/Kconfig                         |  45 ++-
 arch/arm64/Kconfig.debug                   |   2 +-
 arch/arm64/include/asm/assembler.h         | 133 +++++++-
 arch/arm64/include/asm/cpufeature.h        |  27 +-
 arch/arm64/include/asm/elf.h               |   3 +-
 arch/arm64/include/asm/kernel-pgtable.h    |  21 +-
 arch/arm64/include/asm/kvm_arm.h           |  11 -
 arch/arm64/include/asm/kvm_asm.h           |   3 +
 arch/arm64/include/asm/kvm_host.h          |  14 +-
 arch/arm64/include/asm/kvm_mmu.h           |   1 +
 arch/arm64/include/asm/memory.h            |  33 +-
 arch/arm64/include/asm/mmu.h               |   1 +
 arch/arm64/include/asm/mmzone.h            |  12 +
 arch/arm64/include/asm/numa.h              |  45 +++
 arch/arm64/include/asm/page.h              |   2 +
 arch/arm64/include/asm/pgtable-hwdef.h     |   1 -
 arch/arm64/include/asm/pgtable-types.h     |  32 --
 arch/arm64/include/asm/pgtable.h           |  62 ++--
 arch/arm64/include/asm/smp.h               |  11 +
 arch/arm64/include/asm/suspend.h           |  32 +-
 arch/arm64/include/asm/sysreg.h            |  24 +-
 arch/arm64/include/asm/topology.h          |  10 +
 arch/arm64/include/asm/virt.h              |  22 ++
 arch/arm64/kernel/Makefile                 |   1 +
 arch/arm64/kernel/acpi.c                   |  33 +-
 arch/arm64/kernel/asm-offsets.c            |  10 +-
 arch/arm64/kernel/cpu_errata.c             |  24 +-
 arch/arm64/kernel/cpufeature.c             | 343 ++++++++++++--------
 arch/arm64/kernel/cpuidle.c                |   9 +-
 arch/arm64/kernel/cpuinfo.c                |  40 +--
 arch/arm64/kernel/debug-monitors.c         |   3 +-
 arch/arm64/kernel/efi-entry.S              |   2 +-
 arch/arm64/kernel/head.S                   | 165 +++++-----
 arch/arm64/kernel/hibernate-asm.S          | 176 +++++++++++
 arch/arm64/kernel/hibernate.c              | 487 +++++++++++++++++++++++++++++
 arch/arm64/kernel/hw_breakpoint.c          |   8 +-
 arch/arm64/kernel/hyp-stub.S               |  45 ++-
 arch/arm64/kernel/image.h                  |   2 +
 arch/arm64/kernel/insn.c                   |   2 +-
 arch/arm64/kernel/kaslr.c                  |   6 +-
 arch/arm64/kernel/pci.c                    |  10 +
 arch/arm64/kernel/process.c                |  18 +-
 arch/arm64/kernel/setup.c                  |  81 +----
 arch/arm64/kernel/sleep.S                  | 157 ++++------
 arch/arm64/kernel/smp.c                    |  78 +++--
 arch/arm64/kernel/suspend.c                | 102 +++---
 arch/arm64/kernel/sys.c                    |  10 +
 arch/arm64/kernel/vdso.c                   |   4 +-
 arch/arm64/kernel/vmlinux.lds.S            |  48 ++-
 arch/arm64/kvm/handle_exit.c               |   7 +
 arch/arm64/kvm/hyp-init.S                  |  48 ++-
 arch/arm64/kvm/hyp.S                       |  11 +-
 arch/arm64/kvm/hyp/entry.S                 |  19 ++
 arch/arm64/kvm/hyp/hyp-entry.S             |  10 +-
 arch/arm64/kvm/reset.c                     |  30 ++
 arch/arm64/mm/Makefile                     |   1 +
 arch/arm64/mm/cache.S                      |   2 -
 arch/arm64/mm/context.c                    |   3 +-
 arch/arm64/mm/dma-mapping.c                |  56 +---
 arch/arm64/mm/dump.c                       |  52 +--
 arch/arm64/mm/fault.c                      |  87 +++++-
 arch/arm64/mm/init.c                       | 112 +++++--
 arch/arm64/mm/mm.h                         |   1 -
 arch/arm64/mm/mmap.c                       |   2 -
 arch/arm64/mm/mmu.c                        |  24 +-
 arch/arm64/mm/numa.c                       | 396 +++++++++++++++++++++++
 arch/arm64/mm/proc-macros.S                |  98 ------
 arch/arm64/mm/proc.S                       |  56 ++--
 arch/nios2/include/asm/io.h                |   1 -
 arch/nios2/include/asm/page.h              |   2 +-
 arch/nios2/include/asm/pgtable.h           |   2 +-
 arch/openrisc/include/asm/page.h           |   2 -
 drivers/firmware/efi/arm-init.c            |   8 +
 drivers/firmware/efi/libstub/arm64-stub.c  |  15 +-
 drivers/firmware/efi/libstub/fdt.c         |  24 +-
 drivers/irqchip/irq-gic.c                  |   5 +-
 drivers/of/Kconfig                         |   3 +
 drivers/of/Makefile                        |   1 +
 drivers/of/of_numa.c                       | 211 +++++++++++++
 include/linux/mm.h                         |   6 +-
 include/linux/of.h                         |   9 +
 kernel/power/swap.c                        |  18 ++
 89 files changed, 3127 insertions(+), 1026 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/numa.txt
 create mode 100644 arch/arm64/include/asm/mmzone.h
 create mode 100644 arch/arm64/include/asm/numa.h
 create mode 100644 arch/arm64/kernel/hibernate-asm.S
 create mode 100644 arch/arm64/kernel/hibernate.c
 create mode 100644 arch/arm64/mm/numa.c
 delete mode 100644 arch/arm64/mm/proc-macros.S
 create mode 100644 drivers/of/of_numa.c


From will.deacon at arm.com  Mon May 16 10:50:46 2016
From: will.deacon at arm.com (Will Deacon)
Date: Mon, 16 May 2016 18:50:46 +0100
Subject: [GIT PULL] arm64: perf updates for 4.7
Message-ID: <20160516175046.GB22358@arm.com>

Hi Linus,

Please pull the following arm64 perf updates for 4.7. The main addition
here is support for Broadcom's Vulcan core using the architected ID
registers for discovering supported events.

Cheers,

Will

--->8

The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:

  Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git tags/arm64-perf

for you to fetch changes up to 4ba2578fa7b557012b8f59ad7a9284ff15394338:

  arm64: perf: don't expose CHAIN event in sysfs (2016-04-25 15:05:24 +0100)

----------------------------------------------------------------
arm64 perf updates for 4.7

- Support for the PMU in Broadcom's Vulcan CPU

- Dynamic event detection using the PMCEIDn_EL0 ID registers

----------------------------------------------------------------
Ashok Kumar (7):
      Documentation: arm64: pmu: Add Broadcom Vulcan PMU binding
      arm64: dts: Add Broadcom Vulcan PMU in dts
      arm64/perf: Changed events naming as per the ARM ARM
      arm64/perf: Define complete ARMv8 recommended implementation defined events
      arm64/perf: Access pmu register using <read/write>_sys_reg
      arm64/perf: Filter common events based on PMCEIDn_EL0
      arm64/perf: Add Broadcom Vulcan PMU support

Will Deacon (1):
      arm64: perf: don't expose CHAIN event in sysfs

 Documentation/devicetree/bindings/arm/pmu.txt |   3 +-
 arch/arm64/boot/dts/broadcom/vulcan.dtsi      |   2 +-
 arch/arm64/kernel/perf_event.c                | 553 +++++++++++++++++---------
 include/linux/perf/arm_pmu.h                  |   2 +
 4 files changed, 370 insertions(+), 190 deletions(-)


From kernel at martin.sperl.org  Mon May 16 11:17:45 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Mon, 16 May 2016 20:17:45 +0200
Subject: [PATCH-V2 5/5] ARM: multi_v7_defconfig: bcm2835: add
 bcm2835-thermal driver
In-Reply-To: <5739F8AC.8080003@gmail.com>
References: <1463145186-12906-1-git-send-email-kernel@martin.sperl.org>
 <1463145186-12906-6-git-send-email-kernel@martin.sperl.org>
 <5739F8AC.8080003@gmail.com>
Message-ID: <40E50EF4-240B-4E40-8344-1F9042EC1473@martin.sperl.org>


> On 16.05.2016, at 18:43, Florian Fainelli <f.fainelli at gmail.com> wrote:
> 
> On 05/13/2016 06:13 AM, kernel at martin.sperl.org wrote:
>> From: Martin Sperl <kernel at martin.sperl.org>
>> 
>> Add the thermal driver to list of compiled modules in
>> multi_v7_defconfig.
>> 
>> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
>> ---
>> arch/arm/configs/multi_v7_defconfig | 1 +
>> 1 file changed, 1 insertion(+)
>> 
>> diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
>> index 2823490..5f0f5a3 100644
>> --- a/arch/arm/configs/multi_v7_defconfig
>> +++ b/arch/arm/configs/multi_v7_defconfig
>> @@ -422,6 +422,7 @@ CONFIG_CPU_THERMAL=y
>> CONFIG_ROCKCHIP_THERMAL=y
>> CONFIG_RCAR_THERMAL=y
>> CONFIG_ARMADA_THERMAL=y
>> +CONFIG_BCM2835_THERMAL=y
> 
> Does this need to be built into the kernel?
> 
Not necessarily, but as most other drivers in this context
are built in this one was added as such as well.

If the policy is different, then I can change it...




From paulmck at linux.vnet.ibm.com  Mon May 16 11:48:44 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon, 16 May 2016 11:48:44 -0700
Subject: [PATCH omap v2 0/6] Fix OMAP uses of RCU from idle loop
Message-ID: <20160516184844.GA20144@linux.vnet.ibm.com>

Hello!

The following series fixes a number of uses of RCU from the idle loop.
These are all due to tracing, so the fix is simply to append _rcuidle
to the event-tracing call.

Changes since v1: Fix commit-log subjects and add maintainers on CC.

							Thanx, Paul

------------------------------------------------------------------------

 arch/arm/kernel/smp.c             |    2 +-
 arch/arm/mach-omap2/powerdomain.c |    9 +++++----
 drivers/base/power/runtime.c      |   14 +++++++-------
 drivers/clk/clk.c                 |    8 ++++----
 4 files changed, 17 insertions(+), 16 deletions(-)



From paulmck at linux.vnet.ibm.com  Mon May 16 11:50:03 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon, 16 May 2016 11:50:03 -0700
Subject: [PATCH v2 omap 1/6] arm: Use _rcuidle tracepoint to allow use from
 idle
In-Reply-To: <20160516184844.GA20144@linux.vnet.ibm.com>
References: <20160516184844.GA20144@linux.vnet.ibm.com>
Message-ID: <1463424608-20237-1-git-send-email-paulmck@linux.vnet.ibm.com>

Testing on ARM encountered the following pair of lockdep-RCU splats:

------------------------------------------------------------------------

===============================
[ INFO: suspicious RCU usage. ]
4.6.0-rc4-next-20160422 #1 Not tainted
-------------------------------
include/trace/events/power.h:328 suspicious rcu_dereference_check() usage!

other info that might help us debug this:

RCU used illegally from idle CPU!
rcu_scheduler_active = 1, debug_locks = 0
RCU used illegally from extended quiescent state!
no locks held by swapper/0/0.

stack backtrace:
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc4-next-20160422 #1
Hardware name: Generic OMAP3-GP (Flattened Device Tree)
[<c010f55c>] (unwind_backtrace) from [<c010b64c>] (show_stack+0x10/0x14)
[<c010b64c>] (show_stack) from [<c047acbc>] (dump_stack+0xa8/0xe0)
[<c047acbc>] (dump_stack) from [<c012bc10>] (pwrdm_set_next_pwrst+0xf8/0x1cc)
[<c012bc10>] (pwrdm_set_next_pwrst) from [<c01269fc>] (omap3_enter_idle_bm+0x1b8/0x1e8)
[<c01269fc>] (omap3_enter_idle_bm) from [<c05fa0b8>] (cpuidle_enter_state+0x84/0x408)
[<c05fa0b8>] (cpuidle_enter_state) from [<c0182c1c>] (cpu_startup_entry+0x1c8/0x3f0)
[<c0182c1c>] (cpu_startup_entry) from [<c0b00c20>] (start_kernel+0x354/0x3cc)

------------------------------------------------------------------------

[<c010f55c>] (unwind_backtrace) from [<c010b64c>] (show_stack+0x10/0x14)
[<c010b64c>] (show_stack) from [<c047ac3c>] (dump_stack+0xa8/0xe0)
[<c047ac3c>] (dump_stack) from [<c012c340>] (_pwrdm_state_switch+0x188/0x32c)
[<c012c340>] (_pwrdm_state_switch) from [<c012c4f0>] (_pwrdm_post_transition_cb+0xc/0x14)
[<c012c4f0>] (_pwrdm_post_transition_cb) from [<c012ba74>] (pwrdm_for_each+0x30/0x5c)
[<c012ba74>] (pwrdm_for_each) from [<c012c72c>] (pwrdm_post_transition+0x24/0x30)
[<c012c72c>] (pwrdm_post_transition) from [<c012548c>] (omap_sram_idle+0xfc/0x240)
[<c012548c>] (omap_sram_idle) from [<c0126934>] (omap3_enter_idle_bm+0xf0/0x1e8)
[<c0126934>] (omap3_enter_idle_bm) from [<c05fa038>] (cpuidle_enter_state+0x84/0x408)
[<c05fa038>] (cpuidle_enter_state) from [<c0182b90>] (cpu_startup_entry+0x1c8/0x3f0)
[<c0182b90>] (cpu_startup_entry) from [<c0b00c20>] (start_kernel+0x354/0x3cc)

------------------------------------------------------------------------

These are caused by event tracing from the idle loop, and they were
exposed by commit 293e2421fe25 ("rcu: Remove superfluous versions of
rcu_read_lock_sched_held()"), which suppressed some false negatives.
The current commit therefore adds the _rcuidle suffix to make RCU aware
of this implicit use of RCU by event tracing, thus preventing both splats.

Reported-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Tested-by: Guenter Roeck <linux at roeck-us.net>
Tested-by: Tony Lindgren <tony at atomide.com>
Cc: Russell King <linux at arm.linux.org.uk>
Reviewed-by: Steven Rostedt <rostedt at goodmis.org>
Cc: <linux-omap at vger.kernel.org>
Cc: <linux-arm-kernel at lists.infradead.org>
---
 arch/arm/mach-omap2/powerdomain.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 78af6d8cf2e2..daf2753de7aa 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -186,8 +186,9 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 			trace_state = (PWRDM_TRACE_STATES_FLAG |
 				       ((next & OMAP_POWERSTATE_MASK) << 8) |
 				       ((prev & OMAP_POWERSTATE_MASK) << 0));
-			trace_power_domain_target(pwrdm->name, trace_state,
-						  smp_processor_id());
+			trace_power_domain_target_rcuidle(pwrdm->name,
+							  trace_state,
+							  smp_processor_id());
 		}
 		break;
 	default:
@@ -523,8 +524,8 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 
 	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) {
 		/* Trace the pwrdm desired target state */
-		trace_power_domain_target(pwrdm->name, pwrst,
-					  smp_processor_id());
+		trace_power_domain_target_rcuidle(pwrdm->name, pwrst,
+						  smp_processor_id());
 		/* Program the pwrdm desired target state */
 		ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
 	}
-- 
2.5.2



From paulmck at linux.vnet.ibm.com  Mon May 16 11:50:06 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon, 16 May 2016 11:50:06 -0700
Subject: [PATCH v2 omap 4/6] arm: Add _rcuidle suffix to allow rpm_idle() use
 from idle
In-Reply-To: <20160516184844.GA20144@linux.vnet.ibm.com>
References: <20160516184844.GA20144@linux.vnet.ibm.com>
Message-ID: <1463424608-20237-4-git-send-email-paulmck@linux.vnet.ibm.com>

This commit appends a few _rcuidle suffixes to fix the following
RCU-used-from-idle bug:

> ===============================
> [ INFO: suspicious RCU usage. ]
> 4.6.0-rc5-next-20160426+ #1116 Not tainted
> -------------------------------
> include/trace/events/rpm.h:95 suspicious rcu_dereference_check() usage!
>
> other info that might help us debug this:
>
>
> RCU used illegally from idle CPU!
> rcu_scheduler_active = 1, debug_locks = 0
> RCU used illegally from extended quiescent state!
> 1 lock held by swapper/0/0:
>  #0:  (&(&dev->power.lock)->rlock){-.-...}, at: [<c052cc2c>] __rpm_callback+0x58/0x60
>
> stack backtrace:
> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1116
> Hardware name: Generic OMAP36xx (Flattened Device Tree)
> [<c0110290>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
> [<c010c3a8>] (show_stack) from [<c047fd68>] (dump_stack+0xb0/0xe4)
> [<c047fd68>] (dump_stack) from [<c052d5d0>] (rpm_suspend+0x580/0x768)
> [<c052d5d0>] (rpm_suspend) from [<c052ec58>] (__pm_runtime_suspend+0x64/0x84)
> [<c052ec58>] (__pm_runtime_suspend) from [<c04bf25c>] (omap2_gpio_prepare_for_idle+0x5c/0x70)
> [<c04bf25c>] (omap2_gpio_prepare_for_idle) from [<c0125568>] (omap_sram_idle+0x140/0x244)
> [<c0125568>] (omap_sram_idle) from [<c01269dc>] (omap3_enter_idle_bm+0xfc/0x1ec)
> [<c01269dc>] (omap3_enter_idle_bm) from [<c0601bdc>] (cpuidle_enter_state+0x80/0x3d4)
> [<c0601bdc>] (cpuidle_enter_state) from [<c0183b08>] (cpu_startup_entry+0x198/0x3a0)
> [<c0183b08>] (cpu_startup_entry) from [<c0b00c0c>] (start_kernel+0x354/0x3c8)
> [<c0b00c0c>] (start_kernel) from [<8000807c>] (0x8000807c)

In the immortal words of Steven Rostedt, "*Whack* *Whack* *Whack*!!!"

Reported-by: Tony Lindgren <tony at atomide.com>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Tested-by: Tony Lindgren <tony at atomide.com>
Cc: Russell King <linux at arm.linux.org.uk>
WhACKED-by: Steven Rostedt <rostedt at goodmis.org>
Cc: "Rafael J. Wysocki" <rjw at rjwysocki.net>
Cc: <linux-omap at vger.kernel.org>
Cc: <linux-arm-kernel at lists.infradead.org>
Cc: <linux-pm at vger.kernel.org>
---
 drivers/base/power/runtime.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index ad115568ce58..e4c2b8fdeff3 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -301,7 +301,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
 	int (*callback)(struct device *);
 	int retval;
 
-	trace_rpm_idle(dev, rpmflags);
+	trace_rpm_idle_rcuidle(dev, rpmflags);
 	retval = rpm_check_suspend_allowed(dev);
 	if (retval < 0)
 		;	/* Conditions are wrong. */
@@ -337,7 +337,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
 			dev->power.request_pending = true;
 			queue_work(pm_wq, &dev->power.work);
 		}
-		trace_rpm_return_int(dev, _THIS_IP_, 0);
+		trace_rpm_return_int_rcuidle(dev, _THIS_IP_, 0);
 		return 0;
 	}
 
@@ -352,7 +352,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
 	wake_up_all(&dev->power.wait_queue);
 
  out:
-	trace_rpm_return_int(dev, _THIS_IP_, retval);
+	trace_rpm_return_int_rcuidle(dev, _THIS_IP_, retval);
 	return retval ? retval : rpm_suspend(dev, rpmflags | RPM_AUTO);
 }
 
-- 
2.5.2



From paulmck at linux.vnet.ibm.com  Mon May 16 11:50:05 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon, 16 May 2016 11:50:05 -0700
Subject: [PATCH v2 omap 3/6] arm: Add _rcuidle tracepoints to allow
 clk_core_disable() use from idle
In-Reply-To: <20160516184844.GA20144@linux.vnet.ibm.com>
References: <20160516184844.GA20144@linux.vnet.ibm.com>
Message-ID: <1463424608-20237-3-git-send-email-paulmck@linux.vnet.ibm.com>

This commit adds an _rcuidle suffix to a pair of trace events to
prevent the following splat:

> ===============================
> [ INFO: suspicious RCU usage. ]
> 4.6.0-rc5-next-20160426+ #1114 Not tainted
> -------------------------------
> include/trace/events/clk.h:59 suspicious rcu_dereference_check() usage!
>
> other info that might help us debug this:
>
>
> RCU used illegally from idle CPU!
> rcu_scheduler_active = 1, debug_locks = 0
> RCU used illegally from extended quiescent state!
> 2 locks held by swapper/0/0:
>  #0:  (&oh->hwmod_key#30){......}, at: [<c0121b40>] omap_hwmod_idle+0x18/0x44
>  #1:  (enable_lock){......}, at: [<c0630998>] clk_enable_lock+0x18/0x124
>
> stack backtrace:
> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1114
> Hardware name: Generic OMAP36xx (Flattened Device Tree)
> [<c0110290>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
> [<c010c3a8>] (show_stack) from [<c047fd68>] (dump_stack+0xb0/0xe4)
> [<c047fd68>] (dump_stack) from [<c0631618>] (clk_core_disable+0x17c/0x348)
> [<c0631618>] (clk_core_disable) from [<c0632774>] (clk_disable+0x24/0x30)
> [<c0632774>] (clk_disable) from [<c0120590>] (_disable_clocks+0x18/0x7c)
> [<c0120590>] (_disable_clocks) from [<c0121680>] (_idle+0x12c/0x230)
> [<c0121680>] (_idle) from [<c0121b4c>] (omap_hwmod_idle+0x24/0x44)
> [<c0121b4c>] (omap_hwmod_idle) from [<c0122c24>] (omap_device_idle+0x3c/0x90)
> [<c0122c24>] (omap_device_idle) from [<c052cc00>] (__rpm_callback+0x2c/0x60)
> [<c052cc00>] (__rpm_callback) from [<c052cc54>] (rpm_callback+0x20/0x80)
> [<c052cc54>] (rpm_callback) from [<c052d150>] (rpm_suspend+0x100/0x768)
> [<c052d150>] (rpm_suspend) from [<c052ec58>] (__pm_runtime_suspend+0x64/0x84)
> [<c052ec58>] (__pm_runtime_suspend) from [<c04bf25c>] (omap2_gpio_prepare_for_idle+0x5
> c/0x70)
> [<c04bf25c>] (omap2_gpio_prepare_for_idle) from [<c0125568>] (omap_sram_idle+0x140/0x2
> 44)
> [<c0125568>] (omap_sram_idle) from [<c01269dc>] (omap3_enter_idle_bm+0xfc/0x1ec)
> [<c01269dc>] (omap3_enter_idle_bm) from [<c0601bdc>] (cpuidle_enter_state+0x80/0x3d4)
> [<c0601bdc>] (cpuidle_enter_state) from [<c0183b08>] (cpu_startup_entry+0x198/0x3a0)
> [<c0183b08>] (cpu_startup_entry) from [<c0b00c0c>] (start_kernel+0x354/0x3c8)
> [<c0b00c0c>] (start_kernel) from [<8000807c>] (0x8000807c)

Reported-by: Tony Lindgren <tony at atomide.com>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Tested-by: Tony Lindgren <tony at atomide.com>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Steven Rostedt <rostedt at goodmis.org>
Cc: Michael Turquette <mturquette at baylibre.com>
Cc: Stephen Boyd <sboyd at codeaurora.org>
Cc: <linux-omap at vger.kernel.org>
Cc: <linux-arm-kernel at lists.infradead.org>
Cc: <linux-clk at vger.kernel.org>
---
 drivers/clk/clk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index fb74dc1f7520..4fa43c02d682 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -682,12 +682,12 @@ static void clk_core_disable(struct clk_core *core)
 	if (--core->enable_count > 0)
 		return;
 
-	trace_clk_disable(core);
+	trace_clk_disable_rcuidle(core);
 
 	if (core->ops->disable)
 		core->ops->disable(core->hw);
 
-	trace_clk_disable_complete(core);
+	trace_clk_disable_complete_rcuidle(core);
 
 	clk_core_disable(core->parent);
 }
-- 
2.5.2



From paulmck at linux.vnet.ibm.com  Mon May 16 11:50:04 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon, 16 May 2016 11:50:04 -0700
Subject: [PATCH v2 omap 2/6] arm: Use _rcuidle for suspend/resume tracepoints
In-Reply-To: <20160516184844.GA20144@linux.vnet.ibm.com>
References: <20160516184844.GA20144@linux.vnet.ibm.com>
Message-ID: <1463424608-20237-2-git-send-email-paulmck@linux.vnet.ibm.com>

Further testing with false negatives suppressed by commit 293e2421fe25
("rcu: Remove superfluous versions of rcu_read_lock_sched_held()")
identified a few more unprotected uses of RCU from the idle loop.
Because RCU actively ignores idle-loop code (for energy-efficiency
reasons, among other things), using RCU from the idle loop can result
in too-short grace periods, in turn resulting in arbitrary misbehavior.

The affected functions are smp_cross_call() and rpm_suspend().

The resulting lockdep-RCU splats are as follows:

------------------------------------------------------------------------

===============================
[ INFO: suspicious RCU usage. ]
4.6.0-rc5-next-20160426+ #1112 Not tainted
-------------------------------
include/trace/events/ipi.h:35 suspicious rcu_dereference_check() usage!

other info that might help us debug this:

RCU used illegally from idle CPU!
rcu_scheduler_active = 1, debug_locks = 0
RCU used illegally from extended quiescent state!
no locks held by swapper/0/0.

stack backtrace:
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1112
Hardware name: Generic OMAP4 (Flattened Device Tree)
[<c0110308>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
[<c010c3a8>] (show_stack) from [<c047fec8>] (dump_stack+0xb0/0xe4)
[<c047fec8>] (dump_stack) from [<c010dcfc>] (smp_cross_call+0xbc/0x188)
[<c010dcfc>] (smp_cross_call) from [<c01c9e28>] (generic_exec_single+0x9c/0x15c)
[<c01c9e28>] (generic_exec_single) from [<c01ca0a0>] (smp_call_function_single_async+0 x38/0x9c)
[<c01ca0a0>] (smp_call_function_single_async) from [<c0603728>] (cpuidle_coupled_poke_others+0x8c/0xa8)
[<c0603728>] (cpuidle_coupled_poke_others) from [<c0603c10>] (cpuidle_enter_state_coupled+0x26c/0x390)
[<c0603c10>] (cpuidle_enter_state_coupled) from [<c0183c74>] (cpu_startup_entry+0x198/0x3a0)
[<c0183c74>] (cpu_startup_entry) from [<c0b00c0c>] (start_kernel+0x354/0x3c8)
[<c0b00c0c>] (start_kernel) from [<8000807c>] (0x8000807c)

------------------------------------------------------------------------

Warning from omap3
===============================
[ INFO: suspicious RCU usage. ]
4.6.0-rc5-next-20160426+ #1112 Not tainted
-------------------------------
include/trace/events/rpm.h:63 suspicious rcu_dereference_check() usage!

other info that might help us debug this:

RCU used illegally from idle CPU!
rcu_scheduler_active = 1, debug_locks = 0
RCU used illegally from extended quiescent state!
1 lock held by swapper/0/0:
 #0:  (&(&dev->power.lock)->rlock){-.-...}, at: [<c052ee24>] __pm_runtime_suspend+0x54/0x84

stack backtrace:
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1112
Hardware name: Generic OMAP36xx (Flattened Device Tree)
[<c0110308>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
[<c010c3a8>] (show_stack) from [<c047fec8>] (dump_stack+0xb0/0xe4)
[<c047fec8>] (dump_stack) from [<c052d7b4>] (rpm_suspend+0x604/0x7e4)
[<c052d7b4>] (rpm_suspend) from [<c052ee34>] (__pm_runtime_suspend+0x64/0x84)
[<c052ee34>] (__pm_runtime_suspend) from [<c04bf3bc>] (omap2_gpio_prepare_for_idle+0x5c/0x70)
[<c04bf3bc>] (omap2_gpio_prepare_for_idle) from [<c01255e8>] (omap_sram_idle+0x140/0x244)
[<c01255e8>] (omap_sram_idle) from [<c0126b48>] (omap3_enter_idle_bm+0xfc/0x1ec)
[<c0126b48>] (omap3_enter_idle_bm) from [<c0601db8>] (cpuidle_enter_state+0x80/0x3d4)
[<c0601db8>] (cpuidle_enter_state) from [<c0183c74>] (cpu_startup_entry+0x198/0x3a0)
[<c0183c74>] (cpu_startup_entry) from [<c0b00c0c>] (start_kernel+0x354/0x3c8)
[<c0b00c0c>] (start_kernel) from [<8000807c>] (0x8000807c)

------------------------------------------------------------------------

Reported-by: Tony Lindgren <tony at atomide.com>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Tested-by: Tony Lindgren <tony at atomide.com>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Steven Rostedt <rostedt at goodmis.org>
Cc: "Rafael J. Wysocki" <rjw at rjwysocki.net>
Cc: Pavel Machek <pavel at ucw.cz>
Cc: <linux-omap at vger.kernel.org>
Cc: <linux-arm-kernel at lists.infradead.org>
Cc: <linux-pm at vger.kernel.org>
---
 arch/arm/kernel/smp.c        | 2 +-
 drivers/base/power/runtime.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index baee70267f29..7afe48ae5d76 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -486,7 +486,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = {
 
 static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
 {
-	trace_ipi_raise(target, ipi_types[ipinr]);
+	trace_ipi_raise_rcuidle(target, ipi_types[ipinr]);
 	__smp_cross_call(target, ipinr);
 }
 
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 4c7055009bd6..ad115568ce58 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -419,7 +419,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
 	struct device *parent = NULL;
 	int retval;
 
-	trace_rpm_suspend(dev, rpmflags);
+	trace_rpm_suspend_rcuidle(dev, rpmflags);
 
  repeat:
 	retval = rpm_check_suspend_allowed(dev);
@@ -549,7 +549,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
 	}
 
  out:
-	trace_rpm_return_int(dev, _THIS_IP_, retval);
+	trace_rpm_return_int_rcuidle(dev, _THIS_IP_, retval);
 
 	return retval;
 
-- 
2.5.2



From paulmck at linux.vnet.ibm.com  Mon May 16 11:50:08 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon, 16 May 2016 11:50:08 -0700
Subject: [PATCH v2 omap 6/6] arm: Use _rcuidle suffix to allow
 clk_core_enable() to used from idle
In-Reply-To: <20160516184844.GA20144@linux.vnet.ibm.com>
References: <20160516184844.GA20144@linux.vnet.ibm.com>
Message-ID: <1463424608-20237-6-git-send-email-paulmck@linux.vnet.ibm.com>

This commit fixes the RCU use-from-idle bug corresponding the following
splat:

> [ INFO: suspicious RCU usage. ]
> 4.6.0-rc5-next-20160426+ #1127 Not tainted
> -------------------------------
> include/trace/events/clk.h:45 suspicious rcu_dereference_check() usage!
>
> other info that might help us debug this:
>
>
> RCU used illegally from idle CPU!
> rcu_scheduler_active = 1, debug_locks = 0
> RCU used illegally from extended quiescent state!
> 2 locks held by swapper/0/0:
>  #0:  (&oh->hwmod_key#30){......}, at: [<c0121afc>] omap_hwmod_enable+0x18/0x44
>  #1:  (enable_lock){......}, at: [<c0630684>] clk_enable_lock+0x18/0x124
>
> stack backtrace:
> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1127
> Hardware name: Generic OMAP36xx (Flattened Device Tree)
> [<c0110290>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
> [<c010c3a8>] (show_stack) from [<c047fd68>] (dump_stack+0xb0/0xe4)
> [<c047fd68>] (dump_stack) from [<c06315c0>] (clk_core_enable+0x1e0/0x36c)
> [<c06315c0>] (clk_core_enable) from [<c0632298>] (clk_enable+0x1c/0x38)
> [<c0632298>] (clk_enable) from [<c01204e0>] (_enable_clocks+0x18/0x7c)
> [<c01204e0>] (_enable_clocks) from [<c012137c>] (_enable+0x114/0x2ec)
> [<c012137c>] (_enable) from [<c0121b08>] (omap_hwmod_enable+0x24/0x44)
> [<c0121b08>] (omap_hwmod_enable) from [<c0122ad0>] (omap_device_enable+0x3c/0x90)
> [<c0122ad0>] (omap_device_enable) from [<c0122b34>] (_od_runtime_resume+0x10/0x38)
> [<c0122b34>] (_od_runtime_resume) from [<c052cc00>] (__rpm_callback+0x2c/0x60)
> [<c052cc00>] (__rpm_callback) from [<c052cc54>] (rpm_callback+0x20/0x80)
> [<c052cc54>] (rpm_callback) from [<c052df7c>] (rpm_resume+0x3d0/0x6f0)
> [<c052df7c>] (rpm_resume) from [<c052e2e8>] (__pm_runtime_resume+0x4c/0x64)
> [<c052e2e8>] (__pm_runtime_resume) from [<c04bf2c4>] (omap2_gpio_resume_after_idle+0x54/0x68)
> [<c04bf2c4>] (omap2_gpio_resume_after_idle) from [<c01269dc>] (omap3_enter_idle_bm+0xfc/0x1ec)
> [<c01269dc>] (omap3_enter_idle_bm) from [<c0601888>] (cpuidle_enter_state+0x80/0x3d4)
> [<c0601888>] (cpuidle_enter_state) from [<c0183b08>] (cpu_startup_entry+0x198/0x3a0)
> [<c0183b08>] (cpu_startup_entry) from [<c0b00c0c>] (start_kernel+0x354/0x3c8)
> [<c0b00c0c>] (start_kernel) from [<8000807c>] (0x8000807c)

Reported-by: Tony Lindgren <tony at atomide.com>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Tested-by: Tony Lindgren <tony at atomide.com>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Steven Rostedt <rostedt at goodmis.org>
Cc: Michael Turquette <mturquette at baylibre.com>
Cc: Stephen Boyd <sboyd at codeaurora.org>
Cc: <linux-omap at vger.kernel.org>
Cc: <linux-arm-kernel at lists.infradead.org>
Cc: <linux-clk at vger.kernel.org>
---
 drivers/clk/clk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 4fa43c02d682..ec83f404c1d2 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -735,12 +735,12 @@ static int clk_core_enable(struct clk_core *core)
 		if (ret)
 			return ret;
 
-		trace_clk_enable(core);
+		trace_clk_enable_rcuidle(core);
 
 		if (core->ops->enable)
 			ret = core->ops->enable(core->hw);
 
-		trace_clk_enable_complete(core);
+		trace_clk_enable_complete_rcuidle(core);
 
 		if (ret) {
 			clk_core_disable(core->parent);
-- 
2.5.2



From paulmck at linux.vnet.ibm.com  Mon May 16 11:50:07 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Mon, 16 May 2016 11:50:07 -0700
Subject: [PATCH v2 omap 5/6] arm: Add _rcuidle suffix to allow rpm_resume() to
 be called from idle
In-Reply-To: <20160516184844.GA20144@linux.vnet.ibm.com>
References: <20160516184844.GA20144@linux.vnet.ibm.com>
Message-ID: <1463424608-20237-5-git-send-email-paulmck@linux.vnet.ibm.com>

This commit applies another _rcuidle suffix to fix an RCU use from
idle.

> ===============================
> [ INFO: suspicious RCU usage. ]
> 4.6.0-rc5-next-20160426+ #1122 Not tainted
> -------------------------------
> include/trace/events/rpm.h:69 suspicious rcu_dereference_check() usage!
>
> other info that might help us debug this:
>
>
> RCU used illegally from idle CPU!
> rcu_scheduler_active = 1, debug_locks = 0
> RCU used illegally from extended quiescent state!
> 1 lock held by swapper/0/0:
>  #0:  (&(&dev->power.lock)->rlock){-.-...}, at: [<c052e3dc>] __pm_runtime_resume+0x3c/0x64
>
> stack backtrace:
> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1122
> Hardware name: Generic OMAP36xx (Flattened Device Tree)
> [<c0110290>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
> [<c010c3a8>] (show_stack) from [<c047fd68>] (dump_stack+0xb0/0xe4)
> [<c047fd68>] (dump_stack) from [<c052e178>] (rpm_resume+0x5cc/0x7f4)
> [<c052e178>] (rpm_resume) from [<c052e3ec>] (__pm_runtime_resume+0x4c/0x64)
> [<c052e3ec>] (__pm_runtime_resume) from [<c04bf2c4>] (omap2_gpio_resume_after_idle+0x54/0x68)
> [<c04bf2c4>] (omap2_gpio_resume_after_idle) from [<c01269dc>] (omap3_enter_idle_bm+0xfc/0x1ec)
> [<c01269dc>] (omap3_enter_idle_bm) from [<c060198c>] (cpuidle_enter_state+0x80/0x3d4)
> [<c060198c>] (cpuidle_enter_state) from [<c0183b08>] (cpu_startup_entry+0x198/0x3a0)
> [<c0183b08>] (cpu_startup_entry) from [<c0b00c0c>] (start_kernel+0x354/0x3c8)
> [<c0b00c0c>] (start_kernel) from [<8000807c>] (0x8000807c)

Reported-by: Tony Lindgren <tony at atomide.com>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Tested-by: Tony Lindgren <tony at atomide.com>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Steven Rostedt <rostedt at goodmis.org>
Cc: "Rafael J. Wysocki" <rjw at rjwysocki.net>
Cc: <linux-omap at vger.kernel.org>
Cc: <linux-arm-kernel at lists.infradead.org>
Cc: <linux-pm at vger.kernel.org>
---
 drivers/base/power/runtime.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index e4c2b8fdeff3..15b6d5b199d4 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -601,7 +601,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
 	struct device *parent = NULL;
 	int retval = 0;
 
-	trace_rpm_resume(dev, rpmflags);
+	trace_rpm_resume_rcuidle(dev, rpmflags);
 
  repeat:
 	if (dev->power.runtime_error)
@@ -764,7 +764,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
 		spin_lock_irq(&dev->power.lock);
 	}
 
-	trace_rpm_return_int(dev, _THIS_IP_, retval);
+	trace_rpm_return_int_rcuidle(dev, _THIS_IP_, retval);
 
 	return retval;
 }
-- 
2.5.2



From ivo.g.dimitrov.75 at gmail.com  Mon May 16 12:34:08 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Mon, 16 May 2016 22:34:08 +0300
Subject: [PATCH v2 0/6] ir-rx51 driver fixes
Message-ID: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>

ir-rx51 is a driver for Nokia N900 IR transmitter. The current series
fixes the remaining problems in the driver:

 - replace GP timer 9 with PWM framework usage
 - replace pulse width timer dmtimer usage with hrtimer
 - add DT support to the driver
 - add driver to the board DTS

Pathe 2 is needed so the driver to function correctly, without it PWM
refuses to set the needed carrier frequency.

Changes compared to v1:
 - removed [PATCH 5/7] ARM: OMAP: dmtimer: Do not call PM runtime
   functions when not needed.
 - DT compatible string changed to "nokia,n900-ir"

Ivaylo Dimitrov (5):
  pwm: omap-dmtimer: Allow for setting dmtimer clock source
  ir-rx51: use PWM framework instead of OMAP dmtimer
  ir-rx51: add DT support to driver
  ir-rx51: use hrtimer instead of dmtimer
  ARM: dts: n900: enable lirc-rx51 driver

Tony Lindgren (1):
  ir-rx51: Fix build after multiarch changes broke it

 .../devicetree/bindings/media/nokia,n900-ir        |  20 ++
 .../devicetree/bindings/pwm/pwm-omap-dmtimer.txt   |   4 +
 arch/arm/boot/dts/omap3-n900.dts                   |  12 ++
 arch/arm/mach-omap2/board-rx51-peripherals.c       |   5 -
 arch/arm/mach-omap2/pdata-quirks.c                 |  10 +-
 drivers/media/rc/Kconfig                           |   2 +-
 drivers/media/rc/ir-rx51.c                         | 229 +++++++--------------
 drivers/pwm/pwm-omap-dmtimer.c                     |  12 +-
 include/linux/platform_data/media/ir-rx51.h        |   3 -
 9 files changed, 123 insertions(+), 174 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/nokia,n900-ir

-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Mon May 16 12:34:09 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Mon, 16 May 2016 22:34:09 +0300
Subject: [PATCH v2 1/6] ir-rx51: Fix build after multiarch changes broke it
In-Reply-To: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1463427254-7728-2-git-send-email-ivo.g.dimitrov.75@gmail.com>

From: Tony Lindgren <tony at atomide.com>

The ir-rx51 driver for n900 has been disabled since the multiarch
changes as plat include directory no longer is SoC specific.

Let's fix it with minimal changes to pass the dmtimer calls in
pdata. Then the following changes can be done while things can
be tested to be working for each change:

1. Change the non-pwm dmtimer to use just hrtimer if possible

2. Change the pwm dmtimer to use Linux PWM API with the new
   drivers/pwm/pwm-omap-dmtimer.c and remove the direct calls
   to dmtimer functions

3. Parse configuration from device tree and drop the pdata

Note compilation of this depends on the previous patch
"ARM: OMAP2+: Add more functions to pwm pdata for ir-rx51".

Cc: Mauro Carvalho Chehab <mchehab at osg.samsung.com>
Cc: Neil Armstrong <narmstrong at baylibre.com>
Cc: linux-media at vger.kernel.org
Signed-off-by: Tony Lindgren <tony at atomide.com>
---
 drivers/media/rc/Kconfig   |  2 +-
 drivers/media/rc/ir-rx51.c | 99 +++++++++++++++++++++++++---------------------
 2 files changed, 54 insertions(+), 47 deletions(-)

diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index bd4d685..370e16e 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -336,7 +336,7 @@ config IR_TTUSBIR
 
 config IR_RX51
 	tristate "Nokia N900 IR transmitter diode"
-	depends on OMAP_DM_TIMER && ARCH_OMAP2PLUS && LIRC && !ARCH_MULTIPLATFORM
+	depends on OMAP_DM_TIMER && PWM_OMAP_DMTIMER && ARCH_OMAP2PLUS && LIRC
 	---help---
 	   Say Y or M here if you want to enable support for the IR
 	   transmitter diode built in the Nokia N900 (RX51) device.
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 4e1711a..da839c3 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -19,6 +19,7 @@
  *
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/uaccess.h>
@@ -26,11 +27,9 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 
-#include <plat/dmtimer.h>
-#include <plat/clock.h>
-
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
+#include <linux/platform_data/pwm_omap_dmtimer.h>
 #include <linux/platform_data/media/ir-rx51.h>
 
 #define LIRC_RX51_DRIVER_FEATURES (LIRC_CAN_SET_SEND_DUTY_CYCLE |	\
@@ -44,8 +43,9 @@
 #define TIMER_MAX_VALUE 0xffffffff
 
 struct lirc_rx51 {
-	struct omap_dm_timer *pwm_timer;
-	struct omap_dm_timer *pulse_timer;
+	pwm_omap_dmtimer *pwm_timer;
+	pwm_omap_dmtimer *pulse_timer;
+	struct pwm_omap_dmtimer_pdata *dmtimer;
 	struct device	     *dev;
 	struct lirc_rx51_platform_data *pdata;
 	wait_queue_head_t     wqueue;
@@ -63,14 +63,14 @@ struct lirc_rx51 {
 
 static void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
 {
-	omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1,
-			      OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+	lirc_rx51->dmtimer->set_pwm(lirc_rx51->pwm_timer, 0, 1,
+				PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
 }
 
 static void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
 {
-	omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1,
-			      OMAP_TIMER_TRIGGER_NONE);
+	lirc_rx51->dmtimer->set_pwm(lirc_rx51->pwm_timer, 0, 1,
+				    PWM_OMAP_DMTIMER_TRIGGER_NONE);
 }
 
 static int init_timing_params(struct lirc_rx51 *lirc_rx51)
@@ -79,12 +79,12 @@ static int init_timing_params(struct lirc_rx51 *lirc_rx51)
 
 	load = -(lirc_rx51->fclk_khz * 1000 / lirc_rx51->freq);
 	match = -(lirc_rx51->duty_cycle * -load / 100);
-	omap_dm_timer_set_load(lirc_rx51->pwm_timer, 1, load);
-	omap_dm_timer_set_match(lirc_rx51->pwm_timer, 1, match);
-	omap_dm_timer_write_counter(lirc_rx51->pwm_timer, TIMER_MAX_VALUE - 2);
-	omap_dm_timer_start(lirc_rx51->pwm_timer);
-	omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
-	omap_dm_timer_start(lirc_rx51->pulse_timer);
+	lirc_rx51->dmtimer->set_load(lirc_rx51->pwm_timer, 1, load);
+	lirc_rx51->dmtimer->set_match(lirc_rx51->pwm_timer, 1, match);
+	lirc_rx51->dmtimer->write_counter(lirc_rx51->pwm_timer, TIMER_MAX_VALUE - 2);
+	lirc_rx51->dmtimer->start(lirc_rx51->pwm_timer);
+	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
+	lirc_rx51->dmtimer->start(lirc_rx51->pulse_timer);
 
 	lirc_rx51->match = 0;
 
@@ -100,15 +100,15 @@ static int pulse_timer_set_timeout(struct lirc_rx51 *lirc_rx51, int usec)
 	BUG_ON(usec < 0);
 
 	if (lirc_rx51->match == 0)
-		counter = omap_dm_timer_read_counter(lirc_rx51->pulse_timer);
+		counter = lirc_rx51->dmtimer->read_counter(lirc_rx51->pulse_timer);
 	else
 		counter = lirc_rx51->match;
 
 	counter += (u32)(lirc_rx51->fclk_khz * usec / (1000));
-	omap_dm_timer_set_match(lirc_rx51->pulse_timer, 1, counter);
-	omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer,
-				     OMAP_TIMER_INT_MATCH);
-	if (tics_after(omap_dm_timer_read_counter(lirc_rx51->pulse_timer),
+	lirc_rx51->dmtimer->set_match(lirc_rx51->pulse_timer, 1, counter);
+	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer,
+					   PWM_OMAP_DMTIMER_INT_MATCH);
+	if (tics_after(lirc_rx51->dmtimer->read_counter(lirc_rx51->pulse_timer),
 		       counter)) {
 		return 1;
 	}
@@ -120,18 +120,18 @@ static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
 	unsigned int retval;
 	struct lirc_rx51 *lirc_rx51 = ptr;
 
-	retval = omap_dm_timer_read_status(lirc_rx51->pulse_timer);
+	retval = lirc_rx51->dmtimer->read_status(lirc_rx51->pulse_timer);
 	if (!retval)
 		return IRQ_NONE;
 
-	if (retval & ~OMAP_TIMER_INT_MATCH)
+	if (retval & ~PWM_OMAP_DMTIMER_INT_MATCH)
 		dev_err_ratelimited(lirc_rx51->dev,
 				": Unexpected interrupt source: %x\n", retval);
 
-	omap_dm_timer_write_status(lirc_rx51->pulse_timer,
-				OMAP_TIMER_INT_MATCH	|
-				OMAP_TIMER_INT_OVERFLOW	|
-				OMAP_TIMER_INT_CAPTURE);
+	lirc_rx51->dmtimer->write_status(lirc_rx51->pulse_timer,
+					 PWM_OMAP_DMTIMER_INT_MATCH |
+					 PWM_OMAP_DMTIMER_INT_OVERFLOW |
+					 PWM_OMAP_DMTIMER_INT_CAPTURE);
 	if (lirc_rx51->wbuf_index < 0) {
 		dev_err_ratelimited(lirc_rx51->dev,
 				": BUG wbuf_index has value of %i\n",
@@ -165,9 +165,9 @@ end:
 	/* Stop TX here */
 	lirc_rx51_off(lirc_rx51);
 	lirc_rx51->wbuf_index = -1;
-	omap_dm_timer_stop(lirc_rx51->pwm_timer);
-	omap_dm_timer_stop(lirc_rx51->pulse_timer);
-	omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
+	lirc_rx51->dmtimer->stop(lirc_rx51->pwm_timer);
+	lirc_rx51->dmtimer->stop(lirc_rx51->pulse_timer);
+	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
 	wake_up_interruptible(&lirc_rx51->wqueue);
 
 	return IRQ_HANDLED;
@@ -178,28 +178,29 @@ static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 	struct clk *clk_fclk;
 	int retval, pwm_timer = lirc_rx51->pwm_timer_num;
 
-	lirc_rx51->pwm_timer = omap_dm_timer_request_specific(pwm_timer);
+	lirc_rx51->pwm_timer = lirc_rx51->dmtimer->request_specific(pwm_timer);
 	if (lirc_rx51->pwm_timer == NULL) {
 		dev_err(lirc_rx51->dev, ": Error requesting GPT%d timer\n",
 			pwm_timer);
 		return -EBUSY;
 	}
 
-	lirc_rx51->pulse_timer = omap_dm_timer_request();
+	lirc_rx51->pulse_timer = lirc_rx51->dmtimer->request();
 	if (lirc_rx51->pulse_timer == NULL) {
 		dev_err(lirc_rx51->dev, ": Error requesting pulse timer\n");
 		retval = -EBUSY;
 		goto err1;
 	}
 
-	omap_dm_timer_set_source(lirc_rx51->pwm_timer, OMAP_TIMER_SRC_SYS_CLK);
-	omap_dm_timer_set_source(lirc_rx51->pulse_timer,
-				OMAP_TIMER_SRC_SYS_CLK);
+	lirc_rx51->dmtimer->set_source(lirc_rx51->pwm_timer,
+				       PWM_OMAP_DMTIMER_SRC_SYS_CLK);
+	lirc_rx51->dmtimer->set_source(lirc_rx51->pulse_timer,
+				       PWM_OMAP_DMTIMER_SRC_SYS_CLK);
 
-	omap_dm_timer_enable(lirc_rx51->pwm_timer);
-	omap_dm_timer_enable(lirc_rx51->pulse_timer);
+	lirc_rx51->dmtimer->enable(lirc_rx51->pwm_timer);
+	lirc_rx51->dmtimer->enable(lirc_rx51->pulse_timer);
 
-	lirc_rx51->irq_num = omap_dm_timer_get_irq(lirc_rx51->pulse_timer);
+	lirc_rx51->irq_num = lirc_rx51->dmtimer->get_irq(lirc_rx51->pulse_timer);
 	retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler,
 			     IRQF_SHARED, "lirc_pulse_timer", lirc_rx51);
 	if (retval) {
@@ -207,28 +208,28 @@ static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 		goto err2;
 	}
 
-	clk_fclk = omap_dm_timer_get_fclk(lirc_rx51->pwm_timer);
-	lirc_rx51->fclk_khz = clk_fclk->rate / 1000;
+	clk_fclk = lirc_rx51->dmtimer->get_fclk(lirc_rx51->pwm_timer);
+	lirc_rx51->fclk_khz = clk_get_rate(clk_fclk) / 1000;
 
 	return 0;
 
 err2:
-	omap_dm_timer_free(lirc_rx51->pulse_timer);
+	lirc_rx51->dmtimer->free(lirc_rx51->pulse_timer);
 err1:
-	omap_dm_timer_free(lirc_rx51->pwm_timer);
+	lirc_rx51->dmtimer->free(lirc_rx51->pwm_timer);
 
 	return retval;
 }
 
 static int lirc_rx51_free_port(struct lirc_rx51 *lirc_rx51)
 {
-	omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
+	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
 	free_irq(lirc_rx51->irq_num, lirc_rx51);
 	lirc_rx51_off(lirc_rx51);
-	omap_dm_timer_disable(lirc_rx51->pwm_timer);
-	omap_dm_timer_disable(lirc_rx51->pulse_timer);
-	omap_dm_timer_free(lirc_rx51->pwm_timer);
-	omap_dm_timer_free(lirc_rx51->pulse_timer);
+	lirc_rx51->dmtimer->disable(lirc_rx51->pwm_timer);
+	lirc_rx51->dmtimer->disable(lirc_rx51->pulse_timer);
+	lirc_rx51->dmtimer->free(lirc_rx51->pwm_timer);
+	lirc_rx51->dmtimer->free(lirc_rx51->pulse_timer);
 	lirc_rx51->wbuf_index = -1;
 
 	return 0;
@@ -446,7 +447,13 @@ static int lirc_rx51_probe(struct platform_device *dev)
 {
 	lirc_rx51_driver.features = LIRC_RX51_DRIVER_FEATURES;
 	lirc_rx51.pdata = dev->dev.platform_data;
+	if (!lirc_rx51.pdata->dmtimer) {
+		dev_err(&dev->dev, "no dmtimer?\n");
+		return -ENODEV;
+	}
+
 	lirc_rx51.pwm_timer_num = lirc_rx51.pdata->pwm_timer;
+	lirc_rx51.dmtimer = lirc_rx51.pdata->dmtimer;
 	lirc_rx51.dev = &dev->dev;
 	lirc_rx51_driver.dev = &dev->dev;
 	lirc_rx51_driver.minor = lirc_register_driver(&lirc_rx51_driver);
-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Mon May 16 12:34:10 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Mon, 16 May 2016 22:34:10 +0300
Subject: [PATCH v2 2/6] pwm: omap-dmtimer: Allow for setting dmtimer clock
 source
In-Reply-To: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1463427254-7728-3-git-send-email-ivo.g.dimitrov.75@gmail.com>

OMAP GP timers can have different input clocks that allow different PWM
frequencies. However, there is no other way of setting the clock source but
through clocks or clock-names properties of the timer itself. This limits
PWM functionality to only the frequencies allowed by the particular clock
source. Allowing setting the clock source by PWM rather than by timer
allows different PWMs to have different ranges by not hard-wiring the clock
source to the timer.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 Documentation/devicetree/bindings/pwm/pwm-omap-dmtimer.txt |  4 ++++
 drivers/pwm/pwm-omap-dmtimer.c                             | 12 +++++++-----
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-omap-dmtimer.txt b/Documentation/devicetree/bindings/pwm/pwm-omap-dmtimer.txt
index 5befb53..2e53324 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-omap-dmtimer.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-omap-dmtimer.txt
@@ -9,6 +9,10 @@ Required properties:
 
 Optional properties:
 - ti,prescaler: Should be a value between 0 and 7, see the timers datasheet
+- ti,clock-source: Set dmtimer parent clock, values between 0 and 2:
+  - 0x00 - high-frequency system clock (timer_sys_ck)
+  - 0x01 - 32-kHz always-on clock (timer_32k_ck)
+  - 0x02 - external clock (timer_ext_ck, OMAP2 only)
 
 Example:
 	pwm9: dmtimer-pwm at 9 {
diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
index b7e6ecb..95964c6 100644
--- a/drivers/pwm/pwm-omap-dmtimer.c
+++ b/drivers/pwm/pwm-omap-dmtimer.c
@@ -245,7 +245,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
 	struct pwm_omap_dmtimer_chip *omap;
 	struct pwm_omap_dmtimer_pdata *pdata;
 	pwm_omap_dmtimer *dm_timer;
-	u32 prescaler;
+	u32 v;
 	int status;
 
 	pdata = dev_get_platdata(&pdev->dev);
@@ -306,10 +306,12 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
 	if (pm_runtime_active(&omap->dm_timer_pdev->dev))
 		omap->pdata->stop(omap->dm_timer);
 
-	/* setup dmtimer prescaler */
-	if (!of_property_read_u32(pdev->dev.of_node, "ti,prescaler",
-				&prescaler))
-		omap->pdata->set_prescaler(omap->dm_timer, prescaler);
+	if (!of_property_read_u32(pdev->dev.of_node, "ti,prescaler", &v))
+		omap->pdata->set_prescaler(omap->dm_timer, v);
+
+	/* setup dmtimer clock source */
+	if (!of_property_read_u32(pdev->dev.of_node, "ti,clock-source", &v))
+		omap->pdata->set_source(omap->dm_timer, v);
 
 	omap->chip.dev = &pdev->dev;
 	omap->chip.ops = &pwm_omap_dmtimer_ops;
-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Mon May 16 12:34:11 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Mon, 16 May 2016 22:34:11 +0300
Subject: [PATCH v2 3/6] ir-rx51: use PWM framework instead of OMAP dmtimer
In-Reply-To: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1463427254-7728-4-git-send-email-ivo.g.dimitrov.75@gmail.com>

Convert driver to use PWM framework instead of calling dmtimer functions
directly for PWM timer. Remove paragraph about writing to the Free Software
Foundation's mailing address while at it.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
---
 arch/arm/mach-omap2/board-rx51-peripherals.c |  1 -
 arch/arm/mach-omap2/pdata-quirks.c           |  1 -
 drivers/media/rc/ir-rx51.c                   | 85 ++++++++++++++--------------
 include/linux/platform_data/media/ir-rx51.h  |  2 -
 4 files changed, 44 insertions(+), 45 deletions(-)

diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 9a70739..e487575 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -1242,7 +1242,6 @@ static struct pwm_omap_dmtimer_pdata __maybe_unused pwm_dmtimer_pdata = {
 #if defined(CONFIG_IR_RX51) || defined(CONFIG_IR_RX51_MODULE)
 static struct lirc_rx51_platform_data rx51_lirc_data = {
 	.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
-	.pwm_timer = 9, /* Use GPT 9 for CIR */
 #if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
 	.dmtimer = &pwm_dmtimer_pdata,
 #endif
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index ea3a7d5..af65781 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -491,7 +491,6 @@ static struct pwm_omap_dmtimer_pdata pwm_dmtimer_pdata = {
 
 static struct lirc_rx51_platform_data __maybe_unused rx51_lirc_data = {
 	.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
-	.pwm_timer = 9, /* Use GPT 9 for CIR */
 #if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
 	.dmtimer = &pwm_dmtimer_pdata,
 #endif
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index da839c3..5096ef3 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -12,13 +12,7 @@
  *  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, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
  */
-
 #include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -26,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
+#include <linux/pwm.h>
 
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
@@ -43,7 +38,7 @@
 #define TIMER_MAX_VALUE 0xffffffff
 
 struct lirc_rx51 {
-	pwm_omap_dmtimer *pwm_timer;
+	struct pwm_device *pwm;
 	pwm_omap_dmtimer *pulse_timer;
 	struct pwm_omap_dmtimer_pdata *dmtimer;
 	struct device	     *dev;
@@ -58,32 +53,28 @@ struct lirc_rx51 {
 	int		wbuf[WBUF_LEN];
 	int		wbuf_index;
 	unsigned long	device_is_open;
-	int		pwm_timer_num;
 };
 
 static void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
 {
-	lirc_rx51->dmtimer->set_pwm(lirc_rx51->pwm_timer, 0, 1,
-				PWM_OMAP_DMTIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+	pwm_enable(lirc_rx51->pwm);
 }
 
 static void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
 {
-	lirc_rx51->dmtimer->set_pwm(lirc_rx51->pwm_timer, 0, 1,
-				    PWM_OMAP_DMTIMER_TRIGGER_NONE);
+	pwm_disable(lirc_rx51->pwm);
 }
 
 static int init_timing_params(struct lirc_rx51 *lirc_rx51)
 {
-	u32 load, match;
-
-	load = -(lirc_rx51->fclk_khz * 1000 / lirc_rx51->freq);
-	match = -(lirc_rx51->duty_cycle * -load / 100);
-	lirc_rx51->dmtimer->set_load(lirc_rx51->pwm_timer, 1, load);
-	lirc_rx51->dmtimer->set_match(lirc_rx51->pwm_timer, 1, match);
-	lirc_rx51->dmtimer->write_counter(lirc_rx51->pwm_timer, TIMER_MAX_VALUE - 2);
-	lirc_rx51->dmtimer->start(lirc_rx51->pwm_timer);
+	struct pwm_device *pwm = lirc_rx51->pwm;
+	int duty, period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, lirc_rx51->freq);
+
+	duty = DIV_ROUND_CLOSEST(lirc_rx51->duty_cycle * period, 100);
 	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
+
+	pwm_config(pwm, duty, period);
+
 	lirc_rx51->dmtimer->start(lirc_rx51->pulse_timer);
 
 	lirc_rx51->match = 0;
@@ -165,7 +156,7 @@ end:
 	/* Stop TX here */
 	lirc_rx51_off(lirc_rx51);
 	lirc_rx51->wbuf_index = -1;
-	lirc_rx51->dmtimer->stop(lirc_rx51->pwm_timer);
+
 	lirc_rx51->dmtimer->stop(lirc_rx51->pulse_timer);
 	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
 	wake_up_interruptible(&lirc_rx51->wqueue);
@@ -176,13 +167,13 @@ end:
 static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 {
 	struct clk *clk_fclk;
-	int retval, pwm_timer = lirc_rx51->pwm_timer_num;
+	int retval;
 
-	lirc_rx51->pwm_timer = lirc_rx51->dmtimer->request_specific(pwm_timer);
-	if (lirc_rx51->pwm_timer == NULL) {
-		dev_err(lirc_rx51->dev, ": Error requesting GPT%d timer\n",
-			pwm_timer);
-		return -EBUSY;
+	lirc_rx51->pwm = pwm_get(lirc_rx51->dev, NULL);
+	if (IS_ERR(lirc_rx51->pwm)) {
+		retval = PTR_ERR(lirc_rx51->pwm);
+		dev_err(lirc_rx51->dev, ": pwm_get failed: %d\n", retval);
+		return retval;
 	}
 
 	lirc_rx51->pulse_timer = lirc_rx51->dmtimer->request();
@@ -192,15 +183,11 @@ static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 		goto err1;
 	}
 
-	lirc_rx51->dmtimer->set_source(lirc_rx51->pwm_timer,
-				       PWM_OMAP_DMTIMER_SRC_SYS_CLK);
 	lirc_rx51->dmtimer->set_source(lirc_rx51->pulse_timer,
 				       PWM_OMAP_DMTIMER_SRC_SYS_CLK);
-
-	lirc_rx51->dmtimer->enable(lirc_rx51->pwm_timer);
 	lirc_rx51->dmtimer->enable(lirc_rx51->pulse_timer);
-
-	lirc_rx51->irq_num = lirc_rx51->dmtimer->get_irq(lirc_rx51->pulse_timer);
+	lirc_rx51->irq_num =
+			lirc_rx51->dmtimer->get_irq(lirc_rx51->pulse_timer);
 	retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler,
 			     IRQF_SHARED, "lirc_pulse_timer", lirc_rx51);
 	if (retval) {
@@ -208,7 +195,7 @@ static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 		goto err2;
 	}
 
-	clk_fclk = lirc_rx51->dmtimer->get_fclk(lirc_rx51->pwm_timer);
+	clk_fclk = lirc_rx51->dmtimer->get_fclk(lirc_rx51->pulse_timer);
 	lirc_rx51->fclk_khz = clk_get_rate(clk_fclk) / 1000;
 
 	return 0;
@@ -216,7 +203,7 @@ static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
 err2:
 	lirc_rx51->dmtimer->free(lirc_rx51->pulse_timer);
 err1:
-	lirc_rx51->dmtimer->free(lirc_rx51->pwm_timer);
+	pwm_put(lirc_rx51->pwm);
 
 	return retval;
 }
@@ -226,11 +213,10 @@ static int lirc_rx51_free_port(struct lirc_rx51 *lirc_rx51)
 	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
 	free_irq(lirc_rx51->irq_num, lirc_rx51);
 	lirc_rx51_off(lirc_rx51);
-	lirc_rx51->dmtimer->disable(lirc_rx51->pwm_timer);
 	lirc_rx51->dmtimer->disable(lirc_rx51->pulse_timer);
-	lirc_rx51->dmtimer->free(lirc_rx51->pwm_timer);
 	lirc_rx51->dmtimer->free(lirc_rx51->pulse_timer);
 	lirc_rx51->wbuf_index = -1;
+	pwm_put(lirc_rx51->pwm);
 
 	return 0;
 }
@@ -387,7 +373,6 @@ static int lirc_rx51_release(struct inode *inode, struct file *file)
 }
 
 static struct lirc_rx51 lirc_rx51 = {
-	.freq		= 38000,
 	.duty_cycle	= 50,
 	.wbuf_index	= -1,
 };
@@ -445,14 +430,34 @@ static int lirc_rx51_resume(struct platform_device *dev)
 
 static int lirc_rx51_probe(struct platform_device *dev)
 {
+	struct pwm_device *pwm;
+
 	lirc_rx51_driver.features = LIRC_RX51_DRIVER_FEATURES;
 	lirc_rx51.pdata = dev->dev.platform_data;
+
+	if (!lirc_rx51.pdata) {
+		dev_err(&dev->dev, "Platform Data is missing\n");
+		return -ENXIO;
+	}
+
 	if (!lirc_rx51.pdata->dmtimer) {
 		dev_err(&dev->dev, "no dmtimer?\n");
 		return -ENODEV;
 	}
 
-	lirc_rx51.pwm_timer_num = lirc_rx51.pdata->pwm_timer;
+	pwm = pwm_get(&dev->dev, NULL);
+	if (IS_ERR(pwm)) {
+		int err = PTR_ERR(pwm);
+
+		if (err != -EPROBE_DEFER)
+			dev_err(&dev->dev, "pwm_get failed: %d\n", err);
+		return err;
+	}
+
+	/* Use default, in case userspace does not set the carrier */
+	lirc_rx51.freq = DIV_ROUND_CLOSEST(pwm_get_period(pwm), NSEC_PER_SEC);
+	pwm_put(pwm);
+
 	lirc_rx51.dmtimer = lirc_rx51.pdata->dmtimer;
 	lirc_rx51.dev = &dev->dev;
 	lirc_rx51_driver.dev = &dev->dev;
@@ -464,8 +469,6 @@ static int lirc_rx51_probe(struct platform_device *dev)
 		       lirc_rx51_driver.minor);
 		return lirc_rx51_driver.minor;
 	}
-	dev_info(lirc_rx51.dev, "registration ok, minor: %d, pwm: %d\n",
-		 lirc_rx51_driver.minor, lirc_rx51.pwm_timer_num);
 
 	return 0;
 }
diff --git a/include/linux/platform_data/media/ir-rx51.h b/include/linux/platform_data/media/ir-rx51.h
index 3038120..6acf22d 100644
--- a/include/linux/platform_data/media/ir-rx51.h
+++ b/include/linux/platform_data/media/ir-rx51.h
@@ -2,8 +2,6 @@
 #define _LIRC_RX51_H
 
 struct lirc_rx51_platform_data {
-	int pwm_timer;
-
 	int(*set_max_mpu_wakeup_lat)(struct device *dev, long t);
 	struct pwm_omap_dmtimer_pdata *dmtimer;
 };
-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Mon May 16 12:34:12 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Mon, 16 May 2016 22:34:12 +0300
Subject: [PATCH v2 4/6] ir-rx51: add DT support to driver
In-Reply-To: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1463427254-7728-5-git-send-email-ivo.g.dimitrov.75@gmail.com>

With the upcoming removal of legacy boot, lets add support to one of the
last N900 drivers remaining without it. As the driver still uses omap
dmtimer, add auxdata as well.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
---
 .../devicetree/bindings/media/nokia,n900-ir          | 20 ++++++++++++++++++++
 arch/arm/mach-omap2/pdata-quirks.c                   |  6 +-----
 drivers/media/rc/ir-rx51.c                           | 11 ++++++++++-
 3 files changed, 31 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/nokia,n900-ir

diff --git a/Documentation/devicetree/bindings/media/nokia,n900-ir b/Documentation/devicetree/bindings/media/nokia,n900-ir
new file mode 100644
index 0000000..13a18ce
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/nokia,n900-ir
@@ -0,0 +1,20 @@
+Device-Tree bindings for LIRC TX driver for Nokia N900(RX51)
+
+Required properties:
+	- compatible: should be "nokia,n900-ir".
+	- pwms: specifies PWM used for IR signal transmission.
+
+Example node:
+
+	pwm9: dmtimer-pwm at 9 {
+		compatible = "ti,omap-dmtimer-pwm";
+		ti,timers = <&timer9>;
+		ti,clock-source = <0x00>; /* timer_sys_ck */
+		#pwm-cells = <3>;
+	};
+
+	ir: n900-ir {
+		compatible = "nokia,n900-ir";
+
+		pwms = <&pwm9 0 26316 0>; /* 38000 Hz */
+	};
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index af65781..436c6e6 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -273,8 +273,6 @@ static struct platform_device omap3_rom_rng_device = {
 	},
 };
 
-static struct platform_device rx51_lirc_device;
-
 static void __init nokia_n900_legacy_init(void)
 {
 	hsmmc2_internal_input_clk();
@@ -293,10 +291,7 @@ static void __init nokia_n900_legacy_init(void)
 
 		pr_info("RX-51: Registering OMAP3 HWRNG device\n");
 		platform_device_register(&omap3_rom_rng_device);
-
 	}
-
-	platform_device_register(&rx51_lirc_device);
 }
 
 static void __init omap3_tao3530_legacy_init(void)
@@ -534,6 +529,7 @@ static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 		       &omap3_iommu_pdata),
 	OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x4809c000, "4809c000.mmc", &mmc_pdata[0]),
 	OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x480b4000, "480b4000.mmc", &mmc_pdata[1]),
+	OF_DEV_AUXDATA("nokia,n900-ir", 0, "n900-ir", &rx51_lirc_data),
 	/* Only on am3517 */
 	OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
 	OF_DEV_AUXDATA("ti,am3517-emac", 0x5c000000, "davinci_emac.0",
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 5096ef3..1cbb43d 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -21,6 +21,7 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/pwm.h>
+#include <linux/of.h>
 
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
@@ -478,6 +479,14 @@ static int lirc_rx51_remove(struct platform_device *dev)
 	return lirc_unregister_driver(lirc_rx51_driver.minor);
 }
 
+static const struct of_device_id lirc_rx51_match[] = {
+	{
+		.compatible = "nokia,n900-ir",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, lirc_rx51_match);
+
 struct platform_driver lirc_rx51_platform_driver = {
 	.probe		= lirc_rx51_probe,
 	.remove		= lirc_rx51_remove,
@@ -485,7 +494,7 @@ struct platform_driver lirc_rx51_platform_driver = {
 	.resume		= lirc_rx51_resume,
 	.driver		= {
 		.name	= DRIVER_NAME,
-		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(lirc_rx51_match),
 	},
 };
 module_platform_driver(lirc_rx51_platform_driver);
-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Mon May 16 12:34:13 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Mon, 16 May 2016 22:34:13 +0300
Subject: [PATCH v2 5/6] ir-rx51: use hrtimer instead of dmtimer
In-Reply-To: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1463427254-7728-6-git-send-email-ivo.g.dimitrov.75@gmail.com>

Drop dmtimer usage for pulse timer in favor of hrtimer. That allows
removing PWM dmitimer platform data usage.

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
---
 arch/arm/mach-omap2/board-rx51-peripherals.c |   4 -
 arch/arm/mach-omap2/pdata-quirks.c           |   3 -
 drivers/media/rc/ir-rx51.c                   | 166 ++++++---------------------
 include/linux/platform_data/media/ir-rx51.h  |   1 -
 4 files changed, 37 insertions(+), 137 deletions(-)

diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index e487575..a5ab712 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -1242,10 +1242,6 @@ static struct pwm_omap_dmtimer_pdata __maybe_unused pwm_dmtimer_pdata = {
 #if defined(CONFIG_IR_RX51) || defined(CONFIG_IR_RX51_MODULE)
 static struct lirc_rx51_platform_data rx51_lirc_data = {
 	.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
-#if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
-	.dmtimer = &pwm_dmtimer_pdata,
-#endif
-
 };
 
 static struct platform_device rx51_lirc_device = {
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 436c6e6..8739d5c 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -486,9 +486,6 @@ static struct pwm_omap_dmtimer_pdata pwm_dmtimer_pdata = {
 
 static struct lirc_rx51_platform_data __maybe_unused rx51_lirc_data = {
 	.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
-#if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
-	.dmtimer = &pwm_dmtimer_pdata,
-#endif
 };
 
 static struct platform_device __maybe_unused rx51_lirc_device = {
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 1cbb43d..82fb6f2 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -22,10 +22,10 @@
 #include <linux/wait.h>
 #include <linux/pwm.h>
 #include <linux/of.h>
+#include <linux/hrtimer.h>
 
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
-#include <linux/platform_data/pwm_omap_dmtimer.h>
 #include <linux/platform_data/media/ir-rx51.h>
 
 #define LIRC_RX51_DRIVER_FEATURES (LIRC_CAN_SET_SEND_DUTY_CYCLE |	\
@@ -36,32 +36,26 @@
 
 #define WBUF_LEN 256
 
-#define TIMER_MAX_VALUE 0xffffffff
-
 struct lirc_rx51 {
 	struct pwm_device *pwm;
-	pwm_omap_dmtimer *pulse_timer;
-	struct pwm_omap_dmtimer_pdata *dmtimer;
+	struct hrtimer timer;
 	struct device	     *dev;
 	struct lirc_rx51_platform_data *pdata;
 	wait_queue_head_t     wqueue;
 
-	unsigned long	fclk_khz;
 	unsigned int	freq;		/* carrier frequency */
 	unsigned int	duty_cycle;	/* carrier duty cycle */
-	unsigned int	irq_num;
-	unsigned int	match;
 	int		wbuf[WBUF_LEN];
 	int		wbuf_index;
 	unsigned long	device_is_open;
 };
 
-static void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
+static inline void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
 {
 	pwm_enable(lirc_rx51->pwm);
 }
 
-static void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
+static inline void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
 {
 	pwm_disable(lirc_rx51->pwm);
 }
@@ -72,61 +66,21 @@ static int init_timing_params(struct lirc_rx51 *lirc_rx51)
 	int duty, period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, lirc_rx51->freq);
 
 	duty = DIV_ROUND_CLOSEST(lirc_rx51->duty_cycle * period, 100);
-	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
 
 	pwm_config(pwm, duty, period);
 
-	lirc_rx51->dmtimer->start(lirc_rx51->pulse_timer);
-
-	lirc_rx51->match = 0;
-
 	return 0;
 }
 
-#define tics_after(a, b) ((long)(b) - (long)(a) < 0)
-
-static int pulse_timer_set_timeout(struct lirc_rx51 *lirc_rx51, int usec)
+static enum hrtimer_restart lirc_rx51_timer_cb(struct hrtimer *timer)
 {
-	int counter;
-
-	BUG_ON(usec < 0);
-
-	if (lirc_rx51->match == 0)
-		counter = lirc_rx51->dmtimer->read_counter(lirc_rx51->pulse_timer);
-	else
-		counter = lirc_rx51->match;
-
-	counter += (u32)(lirc_rx51->fclk_khz * usec / (1000));
-	lirc_rx51->dmtimer->set_match(lirc_rx51->pulse_timer, 1, counter);
-	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer,
-					   PWM_OMAP_DMTIMER_INT_MATCH);
-	if (tics_after(lirc_rx51->dmtimer->read_counter(lirc_rx51->pulse_timer),
-		       counter)) {
-		return 1;
-	}
-	return 0;
-}
+	struct lirc_rx51 *lirc_rx51 =
+			container_of(timer, struct lirc_rx51, timer);
+	ktime_t now;
 
-static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
-{
-	unsigned int retval;
-	struct lirc_rx51 *lirc_rx51 = ptr;
-
-	retval = lirc_rx51->dmtimer->read_status(lirc_rx51->pulse_timer);
-	if (!retval)
-		return IRQ_NONE;
-
-	if (retval & ~PWM_OMAP_DMTIMER_INT_MATCH)
-		dev_err_ratelimited(lirc_rx51->dev,
-				": Unexpected interrupt source: %x\n", retval);
-
-	lirc_rx51->dmtimer->write_status(lirc_rx51->pulse_timer,
-					 PWM_OMAP_DMTIMER_INT_MATCH |
-					 PWM_OMAP_DMTIMER_INT_OVERFLOW |
-					 PWM_OMAP_DMTIMER_INT_CAPTURE);
 	if (lirc_rx51->wbuf_index < 0) {
 		dev_err_ratelimited(lirc_rx51->dev,
-				": BUG wbuf_index has value of %i\n",
+				"BUG wbuf_index has value of %i\n",
 				lirc_rx51->wbuf_index);
 		goto end;
 	}
@@ -136,6 +90,8 @@ static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
 	 * pulses until we catch up.
 	 */
 	do {
+		u64 ns;
+
 		if (lirc_rx51->wbuf_index >= WBUF_LEN)
 			goto end;
 		if (lirc_rx51->wbuf[lirc_rx51->wbuf_index] == -1)
@@ -146,80 +102,24 @@ static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
 		else
 			lirc_rx51_on(lirc_rx51);
 
-		retval = pulse_timer_set_timeout(lirc_rx51,
-					lirc_rx51->wbuf[lirc_rx51->wbuf_index]);
+		ns = 1000 * lirc_rx51->wbuf[lirc_rx51->wbuf_index];
+		hrtimer_add_expires_ns(timer, ns);
+
 		lirc_rx51->wbuf_index++;
 
-	} while (retval);
+		now = timer->base->get_time();
+
+	} while (hrtimer_get_expires_tv64(timer) < now.tv64);
 
-	return IRQ_HANDLED;
+	return HRTIMER_RESTART;
 end:
 	/* Stop TX here */
 	lirc_rx51_off(lirc_rx51);
 	lirc_rx51->wbuf_index = -1;
 
-	lirc_rx51->dmtimer->stop(lirc_rx51->pulse_timer);
-	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
 	wake_up_interruptible(&lirc_rx51->wqueue);
 
-	return IRQ_HANDLED;
-}
-
-static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
-{
-	struct clk *clk_fclk;
-	int retval;
-
-	lirc_rx51->pwm = pwm_get(lirc_rx51->dev, NULL);
-	if (IS_ERR(lirc_rx51->pwm)) {
-		retval = PTR_ERR(lirc_rx51->pwm);
-		dev_err(lirc_rx51->dev, ": pwm_get failed: %d\n", retval);
-		return retval;
-	}
-
-	lirc_rx51->pulse_timer = lirc_rx51->dmtimer->request();
-	if (lirc_rx51->pulse_timer == NULL) {
-		dev_err(lirc_rx51->dev, ": Error requesting pulse timer\n");
-		retval = -EBUSY;
-		goto err1;
-	}
-
-	lirc_rx51->dmtimer->set_source(lirc_rx51->pulse_timer,
-				       PWM_OMAP_DMTIMER_SRC_SYS_CLK);
-	lirc_rx51->dmtimer->enable(lirc_rx51->pulse_timer);
-	lirc_rx51->irq_num =
-			lirc_rx51->dmtimer->get_irq(lirc_rx51->pulse_timer);
-	retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler,
-			     IRQF_SHARED, "lirc_pulse_timer", lirc_rx51);
-	if (retval) {
-		dev_err(lirc_rx51->dev, ": Failed to request interrupt line\n");
-		goto err2;
-	}
-
-	clk_fclk = lirc_rx51->dmtimer->get_fclk(lirc_rx51->pulse_timer);
-	lirc_rx51->fclk_khz = clk_get_rate(clk_fclk) / 1000;
-
-	return 0;
-
-err2:
-	lirc_rx51->dmtimer->free(lirc_rx51->pulse_timer);
-err1:
-	pwm_put(lirc_rx51->pwm);
-
-	return retval;
-}
-
-static int lirc_rx51_free_port(struct lirc_rx51 *lirc_rx51)
-{
-	lirc_rx51->dmtimer->set_int_enable(lirc_rx51->pulse_timer, 0);
-	free_irq(lirc_rx51->irq_num, lirc_rx51);
-	lirc_rx51_off(lirc_rx51);
-	lirc_rx51->dmtimer->disable(lirc_rx51->pulse_timer);
-	lirc_rx51->dmtimer->free(lirc_rx51->pulse_timer);
-	lirc_rx51->wbuf_index = -1;
-	pwm_put(lirc_rx51->pwm);
-
-	return 0;
+	return HRTIMER_NORESTART;
 }
 
 static ssize_t lirc_rx51_write(struct file *file, const char *buf,
@@ -258,8 +158,9 @@ static ssize_t lirc_rx51_write(struct file *file, const char *buf,
 
 	lirc_rx51_on(lirc_rx51);
 	lirc_rx51->wbuf_index = 1;
-	pulse_timer_set_timeout(lirc_rx51, lirc_rx51->wbuf[0]);
-
+	hrtimer_start(&lirc_rx51->timer,
+		      ns_to_ktime(1000 * lirc_rx51->wbuf[0]),
+		      HRTIMER_MODE_REL);
 	/*
 	 * Don't return back to the userspace until the transfer has
 	 * finished
@@ -359,14 +260,24 @@ static int lirc_rx51_open(struct inode *inode, struct file *file)
 	if (test_and_set_bit(1, &lirc_rx51->device_is_open))
 		return -EBUSY;
 
-	return lirc_rx51_init_port(lirc_rx51);
+	lirc_rx51->pwm = pwm_get(lirc_rx51->dev, NULL);
+	if (IS_ERR(lirc_rx51->pwm)) {
+		int res = PTR_ERR(lirc_rx51->pwm);
+
+		dev_err(lirc_rx51->dev, "pwm_get failed: %d\n", res);
+		return res;
+	}
+
+	return 0;
 }
 
 static int lirc_rx51_release(struct inode *inode, struct file *file)
 {
 	struct lirc_rx51 *lirc_rx51 = file->private_data;
 
-	lirc_rx51_free_port(lirc_rx51);
+	hrtimer_cancel(&lirc_rx51->timer);
+	lirc_rx51_off(lirc_rx51);
+	pwm_put(lirc_rx51->pwm);
 
 	clear_bit(1, &lirc_rx51->device_is_open);
 
@@ -441,11 +352,6 @@ static int lirc_rx51_probe(struct platform_device *dev)
 		return -ENXIO;
 	}
 
-	if (!lirc_rx51.pdata->dmtimer) {
-		dev_err(&dev->dev, "no dmtimer?\n");
-		return -ENODEV;
-	}
-
 	pwm = pwm_get(&dev->dev, NULL);
 	if (IS_ERR(pwm)) {
 		int err = PTR_ERR(pwm);
@@ -459,7 +365,9 @@ static int lirc_rx51_probe(struct platform_device *dev)
 	lirc_rx51.freq = DIV_ROUND_CLOSEST(pwm_get_period(pwm), NSEC_PER_SEC);
 	pwm_put(pwm);
 
-	lirc_rx51.dmtimer = lirc_rx51.pdata->dmtimer;
+	hrtimer_init(&lirc_rx51.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	lirc_rx51.timer.function = lirc_rx51_timer_cb;
+
 	lirc_rx51.dev = &dev->dev;
 	lirc_rx51_driver.dev = &dev->dev;
 	lirc_rx51_driver.minor = lirc_register_driver(&lirc_rx51_driver);
diff --git a/include/linux/platform_data/media/ir-rx51.h b/include/linux/platform_data/media/ir-rx51.h
index 6acf22d..812d873 100644
--- a/include/linux/platform_data/media/ir-rx51.h
+++ b/include/linux/platform_data/media/ir-rx51.h
@@ -3,7 +3,6 @@
 
 struct lirc_rx51_platform_data {
 	int(*set_max_mpu_wakeup_lat)(struct device *dev, long t);
-	struct pwm_omap_dmtimer_pdata *dmtimer;
 };
 
 #endif
-- 
1.9.1



From ivo.g.dimitrov.75 at gmail.com  Mon May 16 12:34:14 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Mon, 16 May 2016 22:34:14 +0300
Subject: [PATCH v2 6/6] ARM: dts: n900: enable lirc-rx51 driver
In-Reply-To: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <1463427254-7728-7-git-send-email-ivo.g.dimitrov.75@gmail.com>

Add the needed DT data to enable IR TX driver

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
---
 arch/arm/boot/dts/omap3-n900.dts | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts
index b3c26a9..cb3878a 100644
--- a/arch/arm/boot/dts/omap3-n900.dts
+++ b/arch/arm/boot/dts/omap3-n900.dts
@@ -143,6 +143,18 @@
 		io-channels = <&twl_madc 0>, <&twl_madc 4>, <&twl_madc 12>;
 		io-channel-names = "temp", "bsi", "vbat";
 	};
+
+	pwm9: dmtimer-pwm at 9 {
+		compatible = "ti,omap-dmtimer-pwm";
+		#pwm-cells = <3>;
+		ti,timers = <&timer9>;
+		ti,clock-source = <0x00>; /* timer_sys_ck */
+	};
+
+	ir: n900-ir {
+		compatible = "nokia,n900-ir";
+		pwms = <&pwm9 0 26316 0>; /* 38000 Hz */
+	};
 };
 
 &omap3_pmx_core {
-- 
1.9.1



From dianders at chromium.org  Mon May 16 13:09:31 2016
From: dianders at chromium.org (Douglas Anderson)
Date: Mon, 16 May 2016 13:09:31 -0700
Subject: [PATCH] arm64: dts: rockchip: add i2c nodes for rk3399
Message-ID: <1463429371-10950-1-git-send-email-dianders@chromium.org>

From: David Wu <david.wu at rock-chips.com>

We've got 9 (count em!) i2c controllers on rk3399, some of which are in
the PMU power domain and some of which are normal peripherals.  Add them
all to the main rk3399 dtsi file so future patches can turn them on in
the board dts files.

Note: by default we try to set the i2c clock rate to 200 MHz so that we
can achieve good i2c functional clock rates.  200 MHz gives us the
ability to make very close to 100 kHz / 400 kHz / 1 MHz rates.  If
boards want to tune clock rates further they can always override.
Possibly boards could want to tune this if:
- they wanted to save an infinitesimal amount of power and they knew
  their i2c bus was slow anyway.  Since we gate the functional clock
  when the i2c bus is not active, power savings would only be while i2c
  transfers were happening and probably won't be very big anyway.
- they wanted to eek out a bit more speed by carefully tuning the source
  clock to make divisions work out perfectly, accounting for the rise /
  fall time measured on an actual board.

Note also that we still request 200 MHz for the PMU i2c busses even
though we expect that we won't make that exactly (currently PPLL is 676
MHz which gives us 169 MHz).

Signed-off-by: David Wu <david.wu at rock-chips.com>
Signed-off-by: Jianqun Xu <jay.xu at rock-chips.com>
[dianders: wrote desc; put in assigned-clocks; reordered nodes]
Signed-off-by: Douglas Anderson <dianders at chromium.org>
---
Note: this patch is based upon David Wu's patch series to add rk3399
support to i2c-rk3x.c and shouldn't land until at least device tree
bindings land.

 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 144 +++++++++++++++++++++++++++++++
 1 file changed, 144 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 46f325a143b0..753a91728b4c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -54,6 +54,15 @@
 	#size-cells = <2>;
 
 	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+		i2c6 = &i2c6;
+		i2c7 = &i2c7;
+		i2c8 = &i2c8;
 		serial0 = &uart0;
 		serial1 = &uart1;
 		serial2 = &uart2;
@@ -272,6 +281,96 @@
 		};
 	};
 
+	i2c1: i2c at ff110000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff110000 0x0 0x1000>;
+		assigned-clocks = <&cru SCLK_I2C1>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c2: i2c at ff120000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff120000 0x0 0x1000>;
+		assigned-clocks = <&cru SCLK_I2C2>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c2_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c3: i2c at ff130000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff130000 0x0 0x1000>;
+		assigned-clocks = <&cru SCLK_I2C3>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c3_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c5: i2c at ff140000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff140000 0x0 0x1000>;
+		assigned-clocks = <&cru SCLK_I2C5>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_I2C5>, <&cru PCLK_I2C5>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c5_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c6: i2c at ff150000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff150000 0x0 0x1000>;
+		assigned-clocks = <&cru SCLK_I2C6>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_I2C6>, <&cru PCLK_I2C6>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c6_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c7: i2c at ff160000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff160000 0x0 0x1000>;
+		assigned-clocks = <&cru SCLK_I2C7>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&cru SCLK_I2C7>, <&cru PCLK_I2C7>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c7_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
 	uart0: serial at ff180000 {
 		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
 		reg = <0x0 0xff180000 0x0 0x100>;
@@ -420,6 +519,51 @@
 		status = "disabled";
 	};
 
+	i2c0: i2c at ff3c0000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff3c0000 0x0 0x1000>;
+		assigned-clocks = <&pmucru SCLK_I2C0_PMU>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&pmucru SCLK_I2C0_PMU>, <&pmucru PCLK_I2C0_PMU>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c0_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c4: i2c at ff3d0000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff3d0000 0x0 0x1000>;
+		assigned-clocks = <&pmucru SCLK_I2C4_PMU>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&pmucru SCLK_I2C4_PMU>, <&pmucru PCLK_I2C4_PMU>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c4_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c8: i2c at ff3e0000 {
+		compatible = "rockchip,rk3399-i2c";
+		reg = <0x0 0xff3e0000 0x0 0x1000>;
+		assigned-clocks = <&pmucru SCLK_I2C8_PMU>;
+		assigned-clock-rates = <200000000>;
+		clocks = <&pmucru SCLK_I2C8_PMU>, <&pmucru PCLK_I2C8_PMU>;
+		clock-names = "i2c", "pclk";
+		interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c8_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
 	pwm0: pwm at ff420000 {
 		compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
 		reg = <0x0 0xff420000 0x0 0x10>;
-- 
2.8.0.rc3.226.g39d4020



From b-liu at ti.com  Mon May 16 13:11:34 2016
From: b-liu at ti.com (Bin Liu)
Date: Mon, 16 May 2016 15:11:34 -0500
Subject: [PATCH v2 1/2] musb: sunxi: Add set_mode platform function
In-Reply-To: <1463229905-26387-2-git-send-email-hdegoede@redhat.com>
 <1463229905-26387-1-git-send-email-hdegoede@redhat.com>
Message-ID: <20160516201059.GA9927@uda0271908>

On Sat, May 14, 2016 at 02:45:04PM +0200, Hans de Goede wrote:
> Move the mode handling to the platform_set_mode callback.
> 
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>

Signed-off-by: Bin Liu <b-liu at ti.com>

Regards,
-Bin.


From maxime.ripard at free-electrons.com  Mon May 16 13:15:09 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 22:15:09 +0200
Subject: [PATCH 02/16] clk: sunxi-ng: Add common infrastructure
In-Reply-To: <20160516100239.a93a238b0d458b38a3689a95@free.fr>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-3-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v67XWt6tjG_xXWgGatTaiN5uYQb2_Q6bgixMDUkHfVHLHg@mail.gmail.com>
 <20160515183122.GA27618@lukather>
 <20160516100239.a93a238b0d458b38a3689a95@free.fr>
Message-ID: <20160516201509.GL27618@lukather>

Hi Jean-Francois,

On Mon, May 16, 2016 at 10:02:39AM +0200, Jean-Francois Moine wrote:
> On Sun, 15 May 2016 20:31:22 +0200
> Maxime Ripard <maxime.ripard at free-electrons.com> wrote:
> 
> > > > +void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
> > > > +{
> > > > +       u32 reg;
> > > > +
> > > > +       if (!(common->features & CCU_FEATURE_LOCK))
> > > > +               return;
> > > > +
> > > > +       WARN_ON(readl_relaxed_poll_timeout(common->base + common->reg, reg,
> > > > +                                          !(reg & lock), 0, 500));
> > > 
> > >                                     no delay between reads? ^
> > 
> > Yes, I intended it to be a simple busy waiting loop since I don't
> > expect it to be very long. Do yu have any more data on how much time
> > it usually takes?
> 
> I have a Soc in which the rate of the audio clock is stable after a
> good second.

You mean before the clock is actually stable, or before the lock bit
is cleared?

Which SoC is it? As far as I've seen, only the H3 allows to configure
the stable time, and while by default it will take 16us, you can
configure as high as 66ms (which is still way higher than the current
limit).

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160516/c43f8041/attachment.sig>

From b-liu at ti.com  Mon May 16 13:15:12 2016
From: b-liu at ti.com (Bin Liu)
Date: Mon, 16 May 2016 15:15:12 -0500
Subject: [PATCH v2 2/2] musb: sunxi: Set state to A_WAIT_VRISE when
 enabling Vbus
In-Reply-To: <1463229905-26387-2-git-send-email-hdegoede@redhat.com>
References: <1463229905-26387-1-git-send-email-hdegoede@redhat.com>
 <1463229905-26387-2-git-send-email-hdegoede@redhat.com>
Message-ID: <20160516201512.GB9927@uda0271908>

On Sat, May 14, 2016 at 02:45:05PM +0200, Hans de Goede wrote:
> When the board is powering attached usb devices via the otg port
> sometimes / on some devices it takes slightly too long for the Vbus
> detection code in phy-sun4i-usb.c to signal that Vbus is high after
> enabling Vbus and the musb hardware signals a MUSB_INTR_VBUSERROR
> interrupt.
> 
> This commit sets the otg state to A_WAIT_VRISE upon enabling Vbus
> making musb_stage0_irq() ignore the first VBUSERR_RETRY_COUNT
> VBUSERROR interrupts, fixing connection issues in these cases.
> 
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>

Signed-off-by: Bin Liu <b-liu at ti.com>

Regards,
-Bin.



From davidm at egauge.net  Mon May 16 13:17:10 2016
From: davidm at egauge.net (David Mosberger-Tang)
Date: Mon, 16 May 2016 14:17:10 -0600
Subject: [PATCH] drivers: nvmem: atmel-secumod: New driver for Atmel Secumod
 nvram
In-Reply-To: <alpine.LNX.2.00.1605121505320.21379@nippy.intranet>
References: <alpine.LNX.2.00.1605121505320.21379@nippy.intranet>
Message-ID: <1463429830-20539-1-git-send-email-davidm@egauge.net>

Signed-off-by: David Mosberger <davidm at egauge.net>
---
 .../devicetree/bindings/nvmem/atmel-secumod.txt    |  46 ++++++++
 drivers/nvmem/atmel-secumod.c                      | 125 +++++++++++++++++++++
 2 files changed, 171 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
 create mode 100644 drivers/nvmem/atmel-secumod.c

diff --git a/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
new file mode 100644
index 0000000..85db709
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
@@ -0,0 +1,46 @@
+= Atmel Secumod device tree bindings =
+
+This binding is intended to represent Atmel's Secumod which is found
+in SAMA5D2 and perhaps others.
+
+Required properties:
+- compatible: should be "atmel,sama5d2-secumod"
+- reg: Should contain registers location and length of the RAM, followed
+       by register location and length of the Secumod controller.
+
+= Data cells =
+Are child nodes of secumod, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example:
+
+    secumod at fc040000 {
+            compatible = "atmel,sama5d2-secumod";
+            reg = <0xf8044000 0x1420
+                   0xfc040000 0x4000>;
+            status = "okay";
+
+            #address-cells = <1>;
+            #size-cells = <1>;
+
+            secram_auto_erasable at 0000 {
+                    reg = <0x0000 0x1000>;
+            };
+            secram at 1000 {
+                    reg = <0x1000 0x400>;
+            };
+            ram at 1400 {
+                    reg = <0x1400 0x20>;
+            };
+    };
+
+= Data consumers =
+Are device nodes which consume nvmem data cells.
+
+For example:
+
+	ram {
+		...
+		nvmem-cells = <&ram>;
+		nvmem-cell-names = "RAM";
+	};
diff --git a/drivers/nvmem/atmel-secumod.c b/drivers/nvmem/atmel-secumod.c
new file mode 100644
index 0000000..fda83c9
--- /dev/null
+++ b/drivers/nvmem/atmel-secumod.c
@@ -0,0 +1,125 @@
+/*
+ * Driver for SAMA5D2 secure module (SECUMOD).
+ *
+ * Copyright (C) 2016 eGauge Systems LLC
+ *
+ * David Mosberger <davidm at egauge.net>
+ *
+ * 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/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+static struct regmap_config secumod_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4
+};
+
+static struct nvmem_config econfig = {
+	.name = "secumod",
+	.owner = THIS_MODULE,
+};
+
+/*
+ * Security-module register definitions:
+ */
+#define SECUMOD_RAMRDY	0x0014
+
+/*
+ * Since the secure module may need to automatically erase some of the
+ * RAM, it may take a while for it to be ready.  As far as I know,
+ * it's not documented how long this might take in the worst-case.
+ */
+static void
+secumod_wait_ready (void *regs)
+{
+	unsigned long start, stop;
+
+	start = jiffies;
+	while (!(readl(regs + SECUMOD_RAMRDY) & 1))
+		msleep_interruptible(1);
+	stop = jiffies;
+	if (stop != start)
+		pr_info("nvmem-atmel-secumod: it took %u msec for SECUMOD "
+			"to become ready...\n", jiffies_to_msecs(stop - start));
+	else
+		pr_info("nvmem-atmel-secumod: ready\n");
+}
+
+static int secumod_remove(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+	return nvmem_unregister(nvmem);
+}
+
+static int secumod_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct nvmem_device *nvmem;
+	struct regmap *regmap;
+	void __iomem *base;
+
+	/*
+	 * Map controller address temporarily so we can ensure that
+	 * the hardware is ready:
+	 */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	secumod_wait_ready(base);
+	devm_iounmap(dev, base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	secumod_regmap_config.max_register = resource_size(res) - 1;
+
+	regmap = devm_regmap_init_mmio(dev, base, &secumod_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "%s: regmap init failed\n", __func__);
+		return PTR_ERR(regmap);
+	}
+	econfig.dev = dev;
+	nvmem = nvmem_register(&econfig);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
+
+	platform_set_drvdata(pdev, nvmem);
+
+	return 0;
+}
+
+static const struct of_device_id secumod_of_match[] = {
+	{ .compatible = "atmel,sama5d2-secumod",},
+	{/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, secumod_of_match);
+
+static struct platform_driver secumod_driver = {
+	.probe = secumod_probe,
+	.remove = secumod_remove,
+	.driver = {
+		.name = "atmel,sama5d2-secumod",
+		.of_match_table = secumod_of_match,
+	},
+};
+module_platform_driver(secumod_driver);
+MODULE_AUTHOR("David Mosberger <davidm at egauge.net>");
+MODULE_DESCRIPTION("Atmel Secumod driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1



From dianders at chromium.org  Mon May 16 13:17:38 2016
From: dianders at chromium.org (Doug Anderson)
Date: Mon, 16 May 2016 13:17:38 -0700
Subject: [PATCH v10 0/8] add i2c driver supported for rk3399
In-Reply-To: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
References: <1463407063-41218-1-git-send-email-david.wu@rock-chips.com>
Message-ID: <CAD=FV=VqEpmODcnKOGb5P=Fu84c5pBOJXD9pfFMRc2aERfWmRg@mail.gmail.com>

Hi,

On Mon, May 16, 2016 at 6:57 AM, David Wu <david.wu at rock-chips.com> wrote:
> There are three points differert from others:
>  - new method to caculate i2c timings for rk3399
>  - pclk and function clk are separated at rk3399
>  - add fast-plus mode supported for rk3399
>
> David Wu (8):
>   i2c: rk3x: add documentation to fields in "struct rk3x_i2c"
>   i2c: rk3x: use struct "rk3x_i2c_calced_timings"
>   i2c: rk3x: Remove redundant rk3x_i2c_clean_ipd()
>   i2c: rk3x: Change SoC data to not use array
>   i2c: rk3x: Move spec timing data to "static const" structs
>   dt-bindings: i2c: rk3x: add support for rk3399
>   i2c: rk3x: add i2c support for rk3399 soc
>   i2c: rk3x: support fast-mode plus for rk3399
>
>  Documentation/devicetree/bindings/i2c/i2c-rk3x.txt |  16 +-
>  drivers/i2c/busses/i2c-rk3x.c                      | 498 +++++++++++++++++----
>  2 files changed, 434 insertions(+), 80 deletions(-)

I haven't put these on the scope or anything, but I have:

* Tested that my i2c busses on rk3288-veyron still seem to work OK
after these patches.

* Tested that my i2c busses on an rk3399 board seem to work after
these patches (plus device tree changes).

Thus, for the series:

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

...possibly could leave off the Tested-by tag for the last in the
series since I have no Fast Mode Plus devices to test against.  ;)

-Doug


From matija.glavinic-pecotic.ext at nokia.com  Mon May 16 13:29:59 2016
From: matija.glavinic-pecotic.ext at nokia.com (Matija Glavinic Pecotic)
Date: Mon, 16 May 2016 22:29:59 +0200
Subject: [PATCH] ARM: Fix A15 798181 errata initialization
In-Reply-To: <20160516162757.GA29346@localhost.localdomain>
References: <5734FA64.6040501@nokia.com>
 <20160516162757.GA29346@localhost.localdomain>
Message-ID: <573A2DC7.8080901@nokia.com>

On 05/16/2016 06:27 PM, EXT Catalin Marinas wrote:
> The errata documents haven't been updated yet but my reading of the
> corresponding ARM support case is that the "REVIDR[9] set" case only
> refers to r2p4. It should be a safe assumption for r3pX as well since
> REVIDR[9] is an update to the previous REVIDR[4] ECO. Anyway, I asked
> ARM support for clarification and get back to you.

I see it possible for at least r3p3 as well since there revidr[4] is reserved. But yes, more clarification is for sure welcomed.

BTW, I do not know which support case you refer to.

> Please add the rXpY ranges and corresponding REVIDR combinations to the
> comment above. It makes it easier to read the code later without having
> to dig into the commit logs.

Ok, will do.

Thanks,

Matija


From carlo at caione.org  Mon May 16 13:30:50 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 16 May 2016 22:30:50 +0200
Subject: [RFC PATCH] soc: Amlogic: Add secure monitor driver
In-Reply-To: <20160516113333.GG656@leverpostej>
References: <1463335845-23534-1-git-send-email-carlo@caione.org>
 <20160516113333.GG656@leverpostej>
Message-ID: <CAOQ7t2aCccyqtzQGQ0q+Q4+toAwrVVVLG5=idgZ1eGOLyJMY2g@mail.gmail.com>

On Mon, May 16, 2016 at 1:33 PM, Mark Rutland <mark.rutland at arm.com> wrote:
> On Sun, May 15, 2016 at 08:10:45PM +0200, Carlo Caione wrote:
>> From: Carlo Caione <carlo at endlessm.com>
>>
>> Introduce a driver to provide calls into secure monitor mode.
>>
>> In the Amlogic SoCs these calls are used for multiple reasons: access to
>> NVMEM, reboot, set USB boot, enable JTAG, etc...
>>
>> Signed-off-by: Carlo Caione <carlo at endlessm.com>
>> ---
>>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi |   4 +
>>  drivers/soc/Kconfig                         |   1 +
>>  drivers/soc/Makefile                        |   1 +
>>  drivers/soc/amlogic/Kconfig                 |   8 ++
>>  drivers/soc/amlogic/Makefile                |   1 +
>>  drivers/soc/amlogic/meson_sm.c              | 141 ++++++++++++++++++++++++++++
>>  include/linux/soc/amlogic/meson_sm.h        |  57 +++++++++++
>>  7 files changed, 213 insertions(+)
>
> The binding is missing documentation.

Yes, not much to document for this RFC.

> Is there any documentation of the actual interface?

There isn't or at least I do not have it. This driver has been written
by reverse engineering the Amlogic driver shipped in their SDK [1]

> Are there any restrictions on how it's used? It looks like calls are
> only expected to happen from the boot CPU, per the code below.

Yes, that's what I could infer from the Amlogic code here [2] but then
I checked this better and it seems that's not the case (see below).

> There are no users in this patch. Are there any example uses (i.e.
> specific code rather than the high-level examples above)?

I use it already to read the NVMEM. It works fine.
I'll submit the NVMEM driver as soon as I have this merged (if ever)

>>  create mode 100644 drivers/soc/amlogic/Kconfig
>>  create mode 100644 drivers/soc/amlogic/Makefile
>>  create mode 100644 drivers/soc/amlogic/meson_sm.c
>>  create mode 100644 include/linux/soc/amlogic/meson_sm.h
>>
>> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>> index 76b3b6d..e4017c3 100644
>> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>> @@ -98,6 +98,10 @@
>>               method = "smc";
>>       };
>>
>> +     sm {
>> +             compatible = "amlogic,meson-sm";
>> +     };
>
> We should have more specific strings, at least in addition to this.

Agree, not sure what I can add though.

[...]
>> +struct meson_sm_data {
>> +     unsigned int cmd;
>> +     unsigned int arg0;
>> +     unsigned int arg1;
>> +     unsigned int arg2;
>> +     unsigned int arg3;
>> +     unsigned int arg4;
>> +     unsigned int ret;
>> +};
>
> Please be explicit and use u32 rather than unsigned int.

Ok

> It looks like all the calls you care about are SMC32 SiP calls, per the
> IDs in the header.

Yes, all the SMC function identifiers I gathered from the Amlogic
sources are SMC32 SiP calls

>> +
>> +static void __meson_sm_call(void *info)
>> +{
>> +     struct meson_sm_data *data = info;
>> +     struct arm_smccc_res res;
>> +
>> +     arm_smccc_smc(data->cmd,
>> +                   data->arg0, data->arg1, data->arg2,
>> +                   data->arg3, data->arg4, 0, 0, &res);
>> +     data->ret = res.a0;
>> +}
>> +
>> +unsigned int meson_sm_call(unsigned int cmd, unsigned int arg0,
>> +                        unsigned int arg1, unsigned int arg2,
>> +                        unsigned int arg3, unsigned int arg4)
>> +{
>> +     struct meson_sm_data data;
>> +
>> +     data.cmd = cmd;
>> +     data.arg0 = arg0;
>> +     data.arg1 = arg1;
>> +     data.arg2 = arg2;
>> +     data.arg3 = arg3;
>> +     data.arg4 = arg4;
>> +     data.ret = 0;
>> +
>> +     smp_call_function_single(0, __meson_sm_call, &data, 1);
>
> Why must this occur on a particular CPU?
>
> With kexec and so on logical CPU 0 is not necessarily the CPU that the
> FW brought out of reset.

You are right. I tried to move this to a different CPU and it keeps
working fine. Still I wonder why Amlogic has something like [2]

> Can the core with the secure OS be powered down, or is that prevented
> with the usual PSCI machinery (e.g. MIGRATE, MIGRATE_INFO_TYPE,
> MIGRATE_INFO_UP_CPU)
>
> I would recommend that any CPU restriction were described explicitly in
> the DT, or detected dynamically based on the MIGRATE_INFO_UP_CPU value.

MIGRATE_INFO_TYPE returns PSCI_0_2_TOS_MP. Does this confirm that the
SMC calls can happen not only from the CPU 0?

>> +
>> +     return data.ret;
>> +}
>> +
>> +unsigned int meson_sm_call_read(void *buffer, unsigned int cmd,
>> +                             unsigned int arg0, unsigned int arg1,
>> +                             unsigned int arg2, unsigned int arg3,
>> +                             unsigned int arg4)
>> +{
>> +     unsigned int size;
>> +
>> +     size = meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
>> +
>> +     if (size != 0)
>
> Is the size guaranteed to never be > SM_MEM_SIZE? Can we sanity-check
> that?

Fix in v2

> The call can't return an error code?

0 in R0 is considered error that we return back.

>> +             memcpy(buffer, sm_sharemem_out_base, size);
>
> Is the buffer completely opaque to this layer?
>
> Are there any endianness concerns, for example?

The best answer I can give you here is: not that I know of.
The driver works fine when reading from the NVMEM, so I assume there
isn't any endiness issue.

>> +
>> +     return size;
>> +}
>> +
>> +unsigned int meson_sm_call_write(void *buffer, unsigned int size,
>> +                              unsigned int cmd, unsigned int arg0,
>> +                              unsigned int arg1, unsigned int arg2,
>> +                              unsigned int arg3, unsigned int arg4)
>> +{
>> +     memcpy(sm_sharemem_in_base, buffer, size);
>> +
>> +     return meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
>> +}
>> +
>> +static int meson_sm_probe(struct platform_device *pdev)
>> +{
>> +     sm_phy_in_base = meson_sm_call(SM_GET_SHARE_MEM_INPUT_BASE, 0, 0, 0, 0, 0);
>> +
>> +     sm_sharemem_in_base = ioremap_cache(sm_phy_in_base, SM_MEM_SIZE);
>> +     if (!sm_sharemem_in_base)
>> +             return -EINVAL;
>
> Are the attributes used for ioremap_cache guaranteed to match and not
> cause a mismatched alias against the firmware's mapping?
>
> Which precise memory attributes does the secure firmware use for the
> shared memory?

Again I wish I had more information. Is there any way I can check this?
The only reasonable answer I can give you right now is that this is
how it is done in the original Amlogic driver in [1]

[...]
>> +#define SM_GET_SHARE_MEM_INPUT_BASE          0x82000020
>> +#define SM_GET_SHARE_MEM_OUTPUT_BASE         0x82000021
>> +#define SM_GET_REBOOT_REASON                 0x82000022
>> +#define SM_GET_SHARE_STORAGE_IN_BASE         0x82000023
>> +#define SM_GET_SHARE_STORAGE_OUT_BASE                0x82000024
>> +#define SM_GET_SHARE_STORAGE_BLOCK_BASE              0x82000025
>> +#define SM_GET_SHARE_STORAGE_MESSAGE_BASE    0x82000026
>> +#define SM_GET_SHARE_STORAGE_BLOCK_SIZE              0x82000027
>> +#define SM_EFUSE_READ                                0x82000030
>> +#define SM_EFUSE_WRITE                               0x82000031
>> +#define SM_EFUSE_WRITE_PATTERN                       0x82000032
>> +#define SM_EFUSE_USER_MAX                    0x82000033
>> +#define SM_JTAG_ON                           0x82000040
>> +#define SM_JTAG_OFF                          0x82000041
>> +#define SM_SET_USB_BOOT_FUNC                 0x82000043
>> +#define SM_SECURITY_KEY_QUERY                        0x82000060
>> +#define SM_SECURITY_KEY_READ                 0x82000061
>> +#define SM_SECURITY_KEY_WRITE                        0x82000062
>> +#define SM_SECURITY_KEY_TELL                 0x82000063
>> +#define SM_SECURITY_KEY_VERIFY                       0x82000064
>> +#define SM_SECURITY_KEY_STATUS                       0x82000065
>> +#define SM_SECURITY_KEY_NOTIFY                       0x82000066
>> +#define SM_SECURITY_KEY_LIST                 0x82000067
>> +#define SM_SECURITY_KEY_REMOVE                       0x82000068
>> +#define SM_DEBUG_EFUSE_WRITE_PATTERN         0x820000F0
>> +#define SM_DEBUG_EFUSE_READ_PATTERN          0x820000F1
>> +#define SM_AML_DATA_PROCESS                  0x820000FF
>
> Is there any documentation for these functions?

Unfortunately there isn't.
I could restrict the list to those functions I know how to use
(*_EFUSE) maybe adding the remaining ones when we actually use them.

>> +#define SM_PSCI_SYS_REBOOT                   0x84000009
>
> The existing PCSI code should be the only caller of this. This should
> not be used here.

Ups, that slipped through when pasting the list.

Thank you for reviewing this RFC, I'll submit a v2 soon.

Cheers,

[1] https://github.com/hardkernel/linux/blob/odroidc2-3.14.y/drivers/amlogic/secmon/secmon.c
[2] https://github.com/hardkernel/linux/blob/odroidc2-3.14.y/drivers/amlogic/efuse/efuse_hw64.c#L94

-- 
Carlo Caione


From maxime.ripard at free-electrons.com  Mon May 16 14:08:03 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 16 May 2016 23:08:03 +0200
Subject: [PATCH 03/16] clk: sunxi-ng: Add fixed factor clock support
In-Reply-To: <CAGb2v65LcXnMj7B-0q2MYESM9vGd9k-yChjvFdX--EivSYdVJg@mail.gmail.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-4-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v65LcXnMj7B-0q2MYESM9vGd9k-yChjvFdX--EivSYdVJg@mail.gmail.com>
Message-ID: <20160516210803.GM27618@lukather>

On Mon, May 09, 2016 at 06:05:20PM +0800, Chen-Yu Tsai wrote:
> Hi,
> 
> On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
> <maxime.ripard at free-electrons.com> wrote:
> > Some clocks in the Allwinner SoCs clock units are direct, fixed,
> > multipliers or dividers from their parent.
> >
> > Add support for such clocks.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/clk/sunxi-ng/Makefile           |  2 ++
> >  drivers/clk/sunxi-ng/ccu_fixed_factor.c | 42 +++++++++++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu_fixed_factor.h | 50 +++++++++++++++++++++++++++++++++
> >  3 files changed, 94 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_fixed_factor.c
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_fixed_factor.h
> >
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> > index bd3461b0f38c..d76276736765 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -1,2 +1,4 @@
> >  obj-y += ccu_common.o
> >  obj-y += ccu_reset.o
> > +
> > +obj-y += ccu_fixed_factor.o
> > diff --git a/drivers/clk/sunxi-ng/ccu_fixed_factor.c b/drivers/clk/sunxi-ng/ccu_fixed_factor.c
> > new file mode 100644
> > index 000000000000..75df8a854db5
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_fixed_factor.c
> > @@ -0,0 +1,42 @@
> > +/*
> > + * Copyright (C) 2016 Maxime Ripard
> > + * Maxime Ripard <maxime.ripard at free-electrons.com>
> > + *
> > + * 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.
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +
> > +#include "ccu_fixed_factor.h"
> > +
> > +static unsigned long ccu_fixed_factor_recalc_rate(struct clk_hw *hw,
> > +                                                 unsigned long parent_rate)
> > +{
> > +       struct ccu_fixed_factor *fix = hw_to_ccu_fixed_factor(hw);
> > +
> > +       return parent_rate * fix->mult / fix->div;
> 
> do_div (from include/asm-generic/div64.h) is better, since this is an
> 64 bit value.

unsigned long is 32 bits, but that's true.

> 
> > +}
> > +
> > +static long ccu_fixed_factor_round_rate(struct clk_hw *hw,
> > +                                       unsigned long rate,
> > +                                       unsigned long *parent_rate)
> > +{
> > +       struct ccu_fixed_factor *fix = hw_to_ccu_fixed_factor(hw);
> > +
> > +       return *parent_rate / fix->div * fix->mult;
> 
> Why is this the other way around? With integer math it shouldn't be
> interchangeable. (Though it seems clk_fixed_factor does the same...)

I'm guessing this is so that it doesn't trip over UINT_MAX, but it
doesn't really apply in our case. I'll make it consistant.

> 
> Also, clk_fixed_factor handles CLK_SET_RATE_PARENT. Do we need to do the
> same here?

Indeed, I'll add it.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160516/4b467868/attachment.sig>

From yang.shi at linaro.org  Mon May 16 16:09:53 2016
From: yang.shi at linaro.org (Yang Shi)
Date: Mon, 16 May 2016 16:09:53 -0700
Subject: [PATCH net-next] bpf: arm64: remove callee-save registers use for tmp
 registers
Message-ID: <1463440193-31934-1-git-send-email-yang.shi@linaro.org>

In the current implementation of ARM64 eBPF JIT, R23 and R24 are used for
tmp registers, which are callee-saved registers. This leads to variable size
of JIT prologue and epilogue. The latest blinding constant change prefers to
constant size of prologue and epilogue. AAPCS reserves R9 ~ R15 for temp
registers which not need to be saved/restored during function call. So, replace
R23 and R24 to R10 and R11, and remove tmp_used flag.

CC: Zi Shen Lim <zlim.lnx at gmail.com>
CC: Daniel Borkmann <daniel at iogearbox.net>
Signed-off-by: Yang Shi <yang.shi at linaro.org>
---
Apply on top of Daniel's blinding constant patchset.

 arch/arm64/net/bpf_jit_comp.c | 32 ++++----------------------------
 1 file changed, 4 insertions(+), 28 deletions(-)

diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index d0d5190..ef3055a 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -51,9 +51,9 @@ static const int bpf2a64[] = {
 	[BPF_REG_9] = A64_R(22),
 	/* read-only frame pointer to access stack */
 	[BPF_REG_FP] = A64_R(25),
-	/* temporary register for internal BPF JIT */
-	[TMP_REG_1] = A64_R(23),
-	[TMP_REG_2] = A64_R(24),
+	/* temporary registers for internal BPF JIT */
+	[TMP_REG_1] = A64_R(10),
+	[TMP_REG_2] = A64_R(11),
 	/* temporary register for blinding constants */
 	[BPF_REG_AX] = A64_R(9),
 };
@@ -61,7 +61,6 @@ static const int bpf2a64[] = {
 struct jit_ctx {
 	const struct bpf_prog *prog;
 	int idx;
-	int tmp_used;
 	int epilogue_offset;
 	int *offset;
 	u32 *image;
@@ -154,8 +153,6 @@ static void build_prologue(struct jit_ctx *ctx)
 	const u8 r8 = bpf2a64[BPF_REG_8];
 	const u8 r9 = bpf2a64[BPF_REG_9];
 	const u8 fp = bpf2a64[BPF_REG_FP];
-	const u8 tmp1 = bpf2a64[TMP_REG_1];
-	const u8 tmp2 = bpf2a64[TMP_REG_2];
 
 	/*
 	 * BPF prog stack layout
@@ -189,8 +186,6 @@ static void build_prologue(struct jit_ctx *ctx)
 	/* Save callee-saved register */
 	emit(A64_PUSH(r6, r7, A64_SP), ctx);
 	emit(A64_PUSH(r8, r9, A64_SP), ctx);
-	if (ctx->tmp_used)
-		emit(A64_PUSH(tmp1, tmp2, A64_SP), ctx);
 
 	/* Save fp (x25) and x26. SP requires 16 bytes alignment */
 	emit(A64_PUSH(fp, A64_R(26), A64_SP), ctx);
@@ -210,8 +205,6 @@ static void build_epilogue(struct jit_ctx *ctx)
 	const u8 r8 = bpf2a64[BPF_REG_8];
 	const u8 r9 = bpf2a64[BPF_REG_9];
 	const u8 fp = bpf2a64[BPF_REG_FP];
-	const u8 tmp1 = bpf2a64[TMP_REG_1];
-	const u8 tmp2 = bpf2a64[TMP_REG_2];
 
 	/* We're done with BPF stack */
 	emit(A64_ADD_I(1, A64_SP, A64_SP, STACK_SIZE), ctx);
@@ -220,8 +213,6 @@ static void build_epilogue(struct jit_ctx *ctx)
 	emit(A64_POP(fp, A64_R(26), A64_SP), ctx);
 
 	/* Restore callee-saved register */
-	if (ctx->tmp_used)
-		emit(A64_POP(tmp1, tmp2, A64_SP), ctx);
 	emit(A64_POP(r8, r9, A64_SP), ctx);
 	emit(A64_POP(r6, r7, A64_SP), ctx);
 
@@ -317,7 +308,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
 			emit(A64_UDIV(is64, dst, dst, src), ctx);
 			break;
 		case BPF_MOD:
-			ctx->tmp_used = 1;
 			emit(A64_UDIV(is64, tmp, dst, src), ctx);
 			emit(A64_MUL(is64, tmp, tmp, src), ctx);
 			emit(A64_SUB(is64, dst, dst, tmp), ctx);
@@ -390,49 +380,41 @@ emit_bswap_uxt:
 	/* dst = dst OP imm */
 	case BPF_ALU | BPF_ADD | BPF_K:
 	case BPF_ALU64 | BPF_ADD | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_ADD(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_SUB | BPF_K:
 	case BPF_ALU64 | BPF_SUB | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_SUB(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_AND | BPF_K:
 	case BPF_ALU64 | BPF_AND | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_AND(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_OR | BPF_K:
 	case BPF_ALU64 | BPF_OR | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_ORR(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_XOR | BPF_K:
 	case BPF_ALU64 | BPF_XOR | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_EOR(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_MUL | BPF_K:
 	case BPF_ALU64 | BPF_MUL | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_MUL(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_DIV | BPF_K:
 	case BPF_ALU64 | BPF_DIV | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_UDIV(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_MOD | BPF_K:
 	case BPF_ALU64 | BPF_MOD | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp2, imm, ctx);
 		emit(A64_UDIV(is64, tmp, dst, tmp2), ctx);
 		emit(A64_MUL(is64, tmp, tmp, tmp2), ctx);
@@ -503,12 +485,10 @@ emit_cond_jmp:
 	case BPF_JMP | BPF_JNE | BPF_K:
 	case BPF_JMP | BPF_JSGT | BPF_K:
 	case BPF_JMP | BPF_JSGE | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp, imm, ctx);
 		emit(A64_CMP(1, dst, tmp), ctx);
 		goto emit_cond_jmp;
 	case BPF_JMP | BPF_JSET | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp, imm, ctx);
 		emit(A64_TST(1, dst, tmp), ctx);
 		goto emit_cond_jmp;
@@ -518,7 +498,6 @@ emit_cond_jmp:
 		const u8 r0 = bpf2a64[BPF_REG_0];
 		const u64 func = (u64)__bpf_call_base + imm;
 
-		ctx->tmp_used = 1;
 		emit_a64_mov_i64(tmp, func, ctx);
 		emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx);
 		emit(A64_MOV(1, A64_FP, A64_SP), ctx);
@@ -564,7 +543,6 @@ emit_cond_jmp:
 	case BPF_LDX | BPF_MEM | BPF_H:
 	case BPF_LDX | BPF_MEM | BPF_B:
 	case BPF_LDX | BPF_MEM | BPF_DW:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp, off, ctx);
 		switch (BPF_SIZE(code)) {
 		case BPF_W:
@@ -588,7 +566,6 @@ emit_cond_jmp:
 	case BPF_ST | BPF_MEM | BPF_B:
 	case BPF_ST | BPF_MEM | BPF_DW:
 		/* Load imm to a register then store it */
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp2, off, ctx);
 		emit_a64_mov_i(1, tmp, imm, ctx);
 		switch (BPF_SIZE(code)) {
@@ -612,7 +589,6 @@ emit_cond_jmp:
 	case BPF_STX | BPF_MEM | BPF_H:
 	case BPF_STX | BPF_MEM | BPF_B:
 	case BPF_STX | BPF_MEM | BPF_DW:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp, off, ctx);
 		switch (BPF_SIZE(code)) {
 		case BPF_W:
@@ -798,7 +774,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
 
 	/* 1. Initial fake pass to compute ctx->idx. */
 
-	/* Fake pass to fill in ctx->offset and ctx->tmp_used. */
+	/* Fake pass to fill in ctx->offset. */
 	if (build_body(&ctx)) {
 		prog = orig_prog;
 		goto out_off;
-- 
2.0.2



From alexey.klimov at arm.com  Mon May 16 16:44:42 2016
From: alexey.klimov at arm.com (Alexey Klimov)
Date: Tue, 17 May 2016 00:44:42 +0100
Subject: [PATCH v5 0/1] ARM64: ACPI: Update documentation for latest
 specification version
In-Reply-To: <3b6d5be3-40ab-94dc-2590-8b2638cbdc15@redhat.com>
Message-ID: <20160516234441.GA7425@arm.com>

On Mon, May 2, 2016 at 09:19 PM, Al Stone wrote:
> On 04/25/2016 03:21 PM, Al Stone wrote:
> > The ACPI 6.1 specification was recently released at the end of January
> > 2016, but the arm64 kernel documentation for the use of ACPI was written
> > for the 5.1 version of the spec.  There were significant additions to the
> > spec that had not yet been mentioned -- for example, the 6.0 mechanisms
> > added to make it easier to define processors and low power idle states,
> > as well as the 6.1 addition allowing regular interrupts (not just from
> > GPIO) be used to signal ACPI general purpose events.
> >
> > This patch reflects going back through and examining the specs in detail
> > and updating content appropriately.  Whilst there, a few odds and ends of
> > typos were caught as well.  This brings the documentation up to date with
> > ACPI 6.1 for arm64.
> >
> > Changes for v5:
> >    -- Miscellaneous typos and corrections (Lorenzo Pieralisi)
> >    -- Add linux-acpi@ ML to the distribution list (Alexey Klimov)
> >    -- Corrections to CPPC information (Alexey Klimov)
> >    -- ACK from Lorenzo Pieralisi
> >    -- Updated bibliographic info (Al Stone)
> >
> > Changes for v4:
> >    -- Clarify that IORT can sometimes be optional (Jon Masters).
> >    -- Remove "Use as needed" descriptions of ACPI objects; they provide
> >       no substantive information and doing so simplifies maintenance of
> >       this document over time.  These have been replaced with a simpler
> >       notice that states that unless otherwise noted, do what the ACPI
> >       specification says is needed.
> >    -- Corrected the _OSI object usage recommendation; it described kernel
> >       behavior that does not exist (Al Stone).
> >
> > Changes for v3:
> >    -- Clarify use of _LPI/_RDI (Vikas Sajjan)
> >    -- Whitespace cleanup as pointed out by checkpatch
> >
> > Changes for v2:
> >    -- Clean up white space (Harb Abdulhahmid)
> >    -- Clarification on _CCA usage (Harb Abdulhamid)
> >    -- IORT moved to required from recommended (Hanjun Guo)
> >    -- Clarify IORT description (Hanjun Guo)
> >
> >
> > Al Stone (1):
> >   ARM64: ACPI: Update documentation for latest specification version
> >
> >  Documentation/arm64/acpi_object_usage.txt | 343 ++++++++++++++++--------------
> >  Documentation/arm64/arm-acpi.txt          |  40 ++--
> >  2 files changed, 213 insertions(+), 170 deletions(-)
> >
> 
> Ping?  If there are no further comments, can this be pulled in through
> either the documentation or arm64 tree?
> 
> Thanks.

Hi Al,
sorry for delay.

CPPC and PCC corrections look fine. Thanks.


This comment is not to block your patch (maybe some to-do):
I greped sources and your patch and I don't see description of _PSD object.
This P-state dependancy object is optional but it's presense and correct data
are extremely useful for CPPC and can potentially descrease number of performance
changing requests.

ACPI spec in section about CPPC tells that it may use _PSD (page 503 if I remember
correctly) to specify domain belongings of CPUs.

You may consider to add description of _PSD object later.

Best regards,
Alexey.


From zlim.lnx at gmail.com  Mon May 16 16:45:19 2016
From: zlim.lnx at gmail.com (Z Lim)
Date: Mon, 16 May 2016 16:45:19 -0700
Subject: [PATCH net-next] bpf: arm64: remove callee-save registers use for
 tmp registers
In-Reply-To: <1463440193-31934-1-git-send-email-yang.shi@linaro.org>
References: <1463440193-31934-1-git-send-email-yang.shi@linaro.org>
Message-ID: <CABg9mcv8ekAxy98VZqq-Aev3rv3wx7UJDM++6AjOJqscJUN5NQ@mail.gmail.com>

Hi Yang,

On Mon, May 16, 2016 at 4:09 PM, Yang Shi <yang.shi at linaro.org> wrote:
> In the current implementation of ARM64 eBPF JIT, R23 and R24 are used for
> tmp registers, which are callee-saved registers. This leads to variable size
> of JIT prologue and epilogue. The latest blinding constant change prefers to
> constant size of prologue and epilogue. AAPCS reserves R9 ~ R15 for temp
> registers which not need to be saved/restored during function call. So, replace
> R23 and R24 to R10 and R11, and remove tmp_used flag.
>
> CC: Zi Shen Lim <zlim.lnx at gmail.com>
> CC: Daniel Borkmann <daniel at iogearbox.net>
> Signed-off-by: Yang Shi <yang.shi at linaro.org>
> ---

Couple suggestions, but otherwise:
Acked-by: Zi Shen Lim <zlim.lnx at gmail.com>

1. Update the diagram. I think it should now be:

-        * BPF fp register => -80:+-----+ <= (BPF_FP)
+        * BPF fp register => -64:+-----+ <= (BPF_FP)

2. Add a comment in commit log along the lines of: this is an
optimization saving 2 instructions per jited BPF program.

Thanks :)

z

> Apply on top of Daniel's blinding constant patchset.
>
>  arch/arm64/net/bpf_jit_comp.c | 32 ++++----------------------------
>  1 file changed, 4 insertions(+), 28 deletions(-)
>


From yang.shi at linaro.org  Mon May 16 16:47:41 2016
From: yang.shi at linaro.org (Shi, Yang)
Date: Mon, 16 May 2016 16:47:41 -0700
Subject: [PATCH net-next] bpf: arm64: remove callee-save registers use for
 tmp registers
In-Reply-To: <CABg9mcv8ekAxy98VZqq-Aev3rv3wx7UJDM++6AjOJqscJUN5NQ@mail.gmail.com>
References: <1463440193-31934-1-git-send-email-yang.shi@linaro.org>
 <CABg9mcv8ekAxy98VZqq-Aev3rv3wx7UJDM++6AjOJqscJUN5NQ@mail.gmail.com>
Message-ID: <8d153729-f2c8-adc2-f10f-6f9a2318746c@linaro.org>

On 5/16/2016 4:45 PM, Z Lim wrote:
> Hi Yang,
>
> On Mon, May 16, 2016 at 4:09 PM, Yang Shi <yang.shi at linaro.org> wrote:
>> In the current implementation of ARM64 eBPF JIT, R23 and R24 are used for
>> tmp registers, which are callee-saved registers. This leads to variable size
>> of JIT prologue and epilogue. The latest blinding constant change prefers to
>> constant size of prologue and epilogue. AAPCS reserves R9 ~ R15 for temp
>> registers which not need to be saved/restored during function call. So, replace
>> R23 and R24 to R10 and R11, and remove tmp_used flag.
>>
>> CC: Zi Shen Lim <zlim.lnx at gmail.com>
>> CC: Daniel Borkmann <daniel at iogearbox.net>
>> Signed-off-by: Yang Shi <yang.shi at linaro.org>
>> ---
>
> Couple suggestions, but otherwise:
> Acked-by: Zi Shen Lim <zlim.lnx at gmail.com>
>
> 1. Update the diagram. I think it should now be:
>
> -        * BPF fp register => -80:+-----+ <= (BPF_FP)
> +        * BPF fp register => -64:+-----+ <= (BPF_FP)

Nice catch. I forgot the stack diagram.

>
> 2. Add a comment in commit log along the lines of: this is an
> optimization saving 2 instructions per jited BPF program.

Sure, will address in V2.

Thanks,
Yang

>
> Thanks :)
>
> z
>
>> Apply on top of Daniel's blinding constant patchset.
>>
>>  arch/arm64/net/bpf_jit_comp.c | 32 ++++----------------------------
>>  1 file changed, 4 insertions(+), 28 deletions(-)
>>



From yang.shi at linaro.org  Mon May 16 16:36:26 2016
From: yang.shi at linaro.org (Yang Shi)
Date: Mon, 16 May 2016 16:36:26 -0700
Subject: [PATCH v2 net-next] bpf: arm64: remove callee-save registers use for
 tmp registers
Message-ID: <1463441786-32224-1-git-send-email-yang.shi@linaro.org>

In the current implementation of ARM64 eBPF JIT, R23 and R24 are used for
tmp registers, which are callee-saved registers. This leads to variable size
of JIT prologue and epilogue. The latest blinding constant change prefers to
constant size of prologue and epilogue. AAPCS reserves R9 ~ R15 for temp
registers which not need to be saved/restored during function call. So, replace
R23 and R24 to R10 and R11, and remove tmp_used flag to save 2 instructions for
some jited BPF program.

CC: Daniel Borkmann <daniel at iogearbox.net>
Acked-by: Zi Shen Lim <zlim.lnx at gmail.com>
Signed-off-by: Yang Shi <yang.shi at linaro.org>
---
Changelog v1 --> v2:
  * Updated stack diagram
  * Added the comment from Zi for the commit log
  * Added Zi's Acked-by

Apply on top of Daniel's blinding constant patchset

 arch/arm64/net/bpf_jit_comp.c | 34 +++++-----------------------------
 1 file changed, 5 insertions(+), 29 deletions(-)

diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index d0d5190..49ba37e 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -51,9 +51,9 @@ static const int bpf2a64[] = {
 	[BPF_REG_9] = A64_R(22),
 	/* read-only frame pointer to access stack */
 	[BPF_REG_FP] = A64_R(25),
-	/* temporary register for internal BPF JIT */
-	[TMP_REG_1] = A64_R(23),
-	[TMP_REG_2] = A64_R(24),
+	/* temporary registers for internal BPF JIT */
+	[TMP_REG_1] = A64_R(10),
+	[TMP_REG_2] = A64_R(11),
 	/* temporary register for blinding constants */
 	[BPF_REG_AX] = A64_R(9),
 };
@@ -61,7 +61,6 @@ static const int bpf2a64[] = {
 struct jit_ctx {
 	const struct bpf_prog *prog;
 	int idx;
-	int tmp_used;
 	int epilogue_offset;
 	int *offset;
 	u32 *image;
@@ -154,8 +153,6 @@ static void build_prologue(struct jit_ctx *ctx)
 	const u8 r8 = bpf2a64[BPF_REG_8];
 	const u8 r9 = bpf2a64[BPF_REG_9];
 	const u8 fp = bpf2a64[BPF_REG_FP];
-	const u8 tmp1 = bpf2a64[TMP_REG_1];
-	const u8 tmp2 = bpf2a64[TMP_REG_2];
 
 	/*
 	 * BPF prog stack layout
@@ -167,7 +164,7 @@ static void build_prologue(struct jit_ctx *ctx)
 	 *                        | ... | callee saved registers
 	 *                        +-----+
 	 *                        |     | x25/x26
-	 * BPF fp register => -80:+-----+ <= (BPF_FP)
+	 * BPF fp register => -64:+-----+ <= (BPF_FP)
 	 *                        |     |
 	 *                        | ... | BPF prog stack
 	 *                        |     |
@@ -189,8 +186,6 @@ static void build_prologue(struct jit_ctx *ctx)
 	/* Save callee-saved register */
 	emit(A64_PUSH(r6, r7, A64_SP), ctx);
 	emit(A64_PUSH(r8, r9, A64_SP), ctx);
-	if (ctx->tmp_used)
-		emit(A64_PUSH(tmp1, tmp2, A64_SP), ctx);
 
 	/* Save fp (x25) and x26. SP requires 16 bytes alignment */
 	emit(A64_PUSH(fp, A64_R(26), A64_SP), ctx);
@@ -210,8 +205,6 @@ static void build_epilogue(struct jit_ctx *ctx)
 	const u8 r8 = bpf2a64[BPF_REG_8];
 	const u8 r9 = bpf2a64[BPF_REG_9];
 	const u8 fp = bpf2a64[BPF_REG_FP];
-	const u8 tmp1 = bpf2a64[TMP_REG_1];
-	const u8 tmp2 = bpf2a64[TMP_REG_2];
 
 	/* We're done with BPF stack */
 	emit(A64_ADD_I(1, A64_SP, A64_SP, STACK_SIZE), ctx);
@@ -220,8 +213,6 @@ static void build_epilogue(struct jit_ctx *ctx)
 	emit(A64_POP(fp, A64_R(26), A64_SP), ctx);
 
 	/* Restore callee-saved register */
-	if (ctx->tmp_used)
-		emit(A64_POP(tmp1, tmp2, A64_SP), ctx);
 	emit(A64_POP(r8, r9, A64_SP), ctx);
 	emit(A64_POP(r6, r7, A64_SP), ctx);
 
@@ -317,7 +308,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
 			emit(A64_UDIV(is64, dst, dst, src), ctx);
 			break;
 		case BPF_MOD:
-			ctx->tmp_used = 1;
 			emit(A64_UDIV(is64, tmp, dst, src), ctx);
 			emit(A64_MUL(is64, tmp, tmp, src), ctx);
 			emit(A64_SUB(is64, dst, dst, tmp), ctx);
@@ -390,49 +380,41 @@ emit_bswap_uxt:
 	/* dst = dst OP imm */
 	case BPF_ALU | BPF_ADD | BPF_K:
 	case BPF_ALU64 | BPF_ADD | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_ADD(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_SUB | BPF_K:
 	case BPF_ALU64 | BPF_SUB | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_SUB(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_AND | BPF_K:
 	case BPF_ALU64 | BPF_AND | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_AND(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_OR | BPF_K:
 	case BPF_ALU64 | BPF_OR | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_ORR(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_XOR | BPF_K:
 	case BPF_ALU64 | BPF_XOR | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_EOR(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_MUL | BPF_K:
 	case BPF_ALU64 | BPF_MUL | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_MUL(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_DIV | BPF_K:
 	case BPF_ALU64 | BPF_DIV | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_UDIV(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_MOD | BPF_K:
 	case BPF_ALU64 | BPF_MOD | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp2, imm, ctx);
 		emit(A64_UDIV(is64, tmp, dst, tmp2), ctx);
 		emit(A64_MUL(is64, tmp, tmp, tmp2), ctx);
@@ -503,12 +485,10 @@ emit_cond_jmp:
 	case BPF_JMP | BPF_JNE | BPF_K:
 	case BPF_JMP | BPF_JSGT | BPF_K:
 	case BPF_JMP | BPF_JSGE | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp, imm, ctx);
 		emit(A64_CMP(1, dst, tmp), ctx);
 		goto emit_cond_jmp;
 	case BPF_JMP | BPF_JSET | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp, imm, ctx);
 		emit(A64_TST(1, dst, tmp), ctx);
 		goto emit_cond_jmp;
@@ -518,7 +498,6 @@ emit_cond_jmp:
 		const u8 r0 = bpf2a64[BPF_REG_0];
 		const u64 func = (u64)__bpf_call_base + imm;
 
-		ctx->tmp_used = 1;
 		emit_a64_mov_i64(tmp, func, ctx);
 		emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx);
 		emit(A64_MOV(1, A64_FP, A64_SP), ctx);
@@ -564,7 +543,6 @@ emit_cond_jmp:
 	case BPF_LDX | BPF_MEM | BPF_H:
 	case BPF_LDX | BPF_MEM | BPF_B:
 	case BPF_LDX | BPF_MEM | BPF_DW:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp, off, ctx);
 		switch (BPF_SIZE(code)) {
 		case BPF_W:
@@ -588,7 +566,6 @@ emit_cond_jmp:
 	case BPF_ST | BPF_MEM | BPF_B:
 	case BPF_ST | BPF_MEM | BPF_DW:
 		/* Load imm to a register then store it */
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp2, off, ctx);
 		emit_a64_mov_i(1, tmp, imm, ctx);
 		switch (BPF_SIZE(code)) {
@@ -612,7 +589,6 @@ emit_cond_jmp:
 	case BPF_STX | BPF_MEM | BPF_H:
 	case BPF_STX | BPF_MEM | BPF_B:
 	case BPF_STX | BPF_MEM | BPF_DW:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp, off, ctx);
 		switch (BPF_SIZE(code)) {
 		case BPF_W:
@@ -798,7 +774,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
 
 	/* 1. Initial fake pass to compute ctx->idx. */
 
-	/* Fake pass to fill in ctx->offset and ctx->tmp_used. */
+	/* Fake pass to fill in ctx->offset. */
 	if (build_body(&ctx)) {
 		prog = orig_prog;
 		goto out_off;
-- 
2.0.2



From f.fainelli at gmail.com  Mon May 16 18:50:08 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Mon, 16 May 2016 18:50:08 -0700
Subject: [PATCH v2 2/2] pci: host: Add Broadcom STB PCIE RC controller
In-Reply-To: <8520D5D51A55D047800579B094147198258955D9@XAP-PVEXMBX01.xlnx.xilinx.com>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
 <1462475700-1654-3-git-send-email-f.fainelli@gmail.com>
 <8520D5D51A55D047800579B094147198258955D9@XAP-PVEXMBX01.xlnx.xilinx.com>
Message-ID: <573A78D0.9090000@gmail.com>

On 05/11/2016 07:47 AM, Bharat Kumar Gogada wrote:

[snip]

>> +	/* Get the value for the log2 of the scb sizes. Subtract 15 from
>> +	 * each because the target register field has 0==disabled and 1==6KB.
>> +	 */
>> +	log2_scb_sizes = of_get_property(dn, "brcm,log2-scb-sizes", &rlen);
>> +	if (log2_scb_sizes) {
>> +		for (i = 0; i < rlen / sizeof(u32); i++) {
>> +			pcie->scb_size_vals[i]
>> +				= (int)of_read_number(log2_scb_sizes + i, 1)
>> +					- 15;
>> +			pcie->num_memc++;
>> +		}
>> +	}
> In your device tree documentation this is required property, what if this property 
> is missing ?

If you look at the driver, you will see that it assumes a 1GB SCB window
size if this property is absent.

PS: Do you mind trimming your replies in the future just to quote the
relevant part? Pretty much like I just did, this greatly improves the
ability to jump right to where the comments are. Thanks
-- 
Florian


From f.fainelli at gmail.com  Mon May 16 18:52:31 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Mon, 16 May 2016 18:52:31 -0700
Subject: [PATCH v2 1/2] Documentation: DT: bindings: Add Broadcom STB PCIe
 bindings
In-Reply-To: <8520D5D51A55D047800579B094147198258955CE@XAP-PVEXMBX01.xlnx.xilinx.com>
References: <1462475700-1654-1-git-send-email-f.fainelli@gmail.com>
 <1462475700-1654-2-git-send-email-f.fainelli@gmail.com>
 <8520D5D51A55D047800579B094147198258955CE@XAP-PVEXMBX01.xlnx.xilinx.com>
Message-ID: <573A795F.2040209@gmail.com>

On 05/11/2016 07:45 AM, Bharat Kumar Gogada wrote:
>> +- brcm,log2-scb-sizes: log2 size of the SCB window that is mapped to
>> +PCIe space
>> +  there must be exactly one value per memory controller present in the
>> +system
>> +  (ranges from 1 to 3)
> 
> Can you please give more insight on what does this property do ?

There is another part of the thread that should tell you a bit more what
this is about, here is where it starts:

http://www.spinics.net/lists/linux-pci/msg50973.html

And this is where we discuss what we should be doing about it:

http://www.spinics.net/lists/linux-pci/msg51070.html
-- 
Florian


From chunfeng.yun at mediatek.com  Mon May 16 19:00:06 2016
From: chunfeng.yun at mediatek.com (chunfeng yun)
Date: Tue, 17 May 2016 10:00:06 +0800
Subject: [PATCH] usb: xhci-mtk: fixup mouse wakeup failure during system
 suspend
In-Reply-To: <87mvo6dojx.fsf@intel.com>
References: <1461204293-18243-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462261458.11651.7.camel@mhfsdcap03> <87vb2vfujq.fsf@intel.com>
 <1462266591.11651.34.camel@mhfsdcap03> <87mvo7fpuc.fsf@intel.com>
 <1462324873.11651.57.camel@mhfsdcap03> <871t5ifdxk.fsf@intel.com>
 <1462359261.11651.69.camel@mhfsdcap03> <87mvo6dojx.fsf@intel.com>
Message-ID: <1463450406.11651.134.camel@mhfsdcap03>

On Wed, 2016-05-04 at 14:56 +0300, Felipe Balbi wrote:
> Hi,
> 
> chunfeng yun <chunfeng.yun at mediatek.com> writes:
> >> chunfeng yun <chunfeng.yun at mediatek.com> writes:
> >> > On Tue, 2016-05-03 at 12:33 +0300, Felipe Balbi wrote:
> >> >> Hi,
> >> >> 
> >> >> chunfeng yun <chunfeng.yun at mediatek.com> writes:
> >> >> >> chunfeng yun <chunfeng.yun at mediatek.com> writes:
> >> >> >> > On Thu, 2016-04-21 at 10:04 +0800, Chunfeng Yun wrote:
> >> >> >> >> Click mouse after xhci suspend completion but before system suspend
> >> >> >> >> completion, system will not be waken up by mouse if the duration of
> >> >> >> >> them is larger than 20ms which is the device UFP's resume signaling
> >> >> >> 
> >> >> >> what is "them" here ? The duration of what is longer than 20ms ?
> >> >> > They are "xhci suspend completion" and "system suspend completion";
> >> >> >
> >> >> > It's time duration
> >> >> 
> >> >> okay. So if xhci suspend takes longer than 20ms your SPM doesn't see a
> >> >> wakeup ?
> >> > It is not the time of xhci suspend consumed, but is the time of duration
> >> > from xhci suspend completion to system suspend completion(after BOOT-CPU
> >> > is turned off, SPM will be enabled to receive wakeup event)
> >> 
> >> Okay, so SPM will be the entity actually handling wakeups, right ? I'm
> >> assuming something like this happens:
> >> 
> >> echo mem > /sys/power/state
> >>  /* start suspending devices */
> >>   xhci_suspend()
> >>  /* all devices suspended */
> >>  enable_spm()
> >> 
> >> so, if a mouse button is pressed after xhci_suspend() returns but before
> >> enable_spm() runs, then we're gonna miss that event, am I right ?
> > Yes, you are right.
> >> 
> >> I can't think of any way to sort this out. Let's ask on linux-pm (I've
> >> added linux-pm to Cc list)
> > Thanks
> >> 
> >> >> >> >> lasted. Another reason is that the SPM is not enabled before system
> >> >> >> 
> >> >> >> what's SPM ?
> >> >> > It is System Power Management which is powered off when system is
> >> >> > running in normal mode, and is powered on when system enters suspend
> >> >> > mode. It is used to wakeup system when some wakeup sources, such as
> >> >> > bluetooth or powerkey etc, tigger wakeup event.
> >> >> 
> >> >> okay, thanks
> >> >> 
> >> >> >> >> suspend compeltion, this causes SPM also not notice the resume signal.
> >> >> >>            ^^^^^^^^^^
> >> >> >>            completion
> >> >> >> 
> >> >> >> >> So in order to reduce the duration less than 20ms, make use of
> >> >> >> >> syscore's suspend/resume interface.
> >> >> >> 
> >> >> >> no, this is the wrong approach
> >> >> > But it seems only one workable approach from software side
> >> >> 
> >> >> I wouldn't say that. It seems to me SPM should be enabled earlier.
> >> > Yes, but normally SPM should be enabled after all CPUS are turned off,
> >> > so it's difficult to do that, I mean enable SPM before turning off CPUS
> >> 
> >> is it a requirement that SPM should be enabled only after all CPUs are
> >> turned off ? If that's the case, then any device in the system might
> >> have missed wakeups. This doesn't seem like a good design to me; unless
> >> I'm missing something...
> > Yes, it's a requirement.
> >
> > If the wakeup source is level trigger, and will keep it until SPM notice
> > it. Although USB wakeup is level trigger, but it just last at most 20ms
> > and clear itself automatically.
> 
> who's clearing USB wakeup after 20ms ? Sure, it's a requirement by the
> USB spec that host should drive reset for *at least* 20ms, but I don't
> remember the exact wordings WRT remote wakeup
> 
> /me reads
> 
> Okay, here it is, section 7.1.7.7 of USB 2.0 Spec states:
> 
> 	"The remote wakeup device must hold the resume signaling for at
>         least 1 ms but for no more than 15 ms (TDRSMUP). At the end of
>         this period, the device stops driving the bus (puts its drivers
>         into the high-impedance state and does not drive the bus to the
>         J state)."
> 
> IOW, the mouse is not at fault here. Remote wakeup can last anywhere
> between 1ms and 15ms. If your system can't cope with it, then I'd say
> it's a problem with your system and you shouldn't allow XHCI to go to
> such deep power states until SPM is enabled.
Yes

> 
> I really tried finding the correct piece of code which does this for PCI
> devices, but basically it's treated as an IRQ and as long as
> enable_irq_wake() or the sysfs file is set to true, then PME gets
> enabled (hopefully PCI folks can confirm this statement).
> 
> Very recently Tony Lindgren added proper handling of wakeup signals as
> IRQs for non-PCI systems too (see 4990d4fe327b PM / Wakeirq: Add
> automated device wake IRQ handling), wonder if you could treat SPM
> similarly.
We can't make use of device's interrupt as wake IRQ, because there is no
IRQ when xHCI enters suspend mode.

Thanks
> 




From liudongdong3 at huawei.com  Mon May 16 20:11:41 2016
From: liudongdong3 at huawei.com (Dongdong Liu)
Date: Tue, 17 May 2016 11:11:41 +0800
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <1462893601-8937-8-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
Message-ID: <573A8BED.7030908@huawei.com>

Hi Tomasz

I used the patchset and added "PATCH V6 11/13 specic quirks", tested on HiSilicon D02 board but met the below problem.

[    2.614115] [<ffffff80083b13bc>] hisi_pcie_init+0x6c/0x1ec
[    2.619571] [<ffffff80083ab060>] pci_ecam_create+0x130/0x1ec
[    2.625209] [<ffffff80083f3764>] pci_acpi_scan_root+0x160/0x218
[    2.631096] [<ffffff80083d1f6c>] acpi_pci_root_add+0x36c/0x42c
[    2.636897] [<ffffff80083ce36c>] acpi_bus_attach+0xe4/0x1a8
[    2.642438] [<ffffff80083ce3d8>] acpi_bus_attach+0x150/0x1a8
[    2.648066] [<ffffff80083ce3d8>] acpi_bus_attach+0x150/0x1a8
[    2.653693] [<ffffff80083ce55c>] acpi_bus_scan+0x64/0x74
[    2.658975] [<ffffff8008ae665c>] acpi_scan_init+0x5c/0x19c
[    2.664429] [<ffffff8008ae6408>] acpi_init+0x280/0x2a4
[    2.669538] [<ffffff80080829e8>] do_one_initcall+0x8c/0x19c
[    2.675080] [<ffffff8008ac3af8>] kernel_init_freeable+0x14c/0x1ec
[    2.681139] [<ffffff80087a8438>] kernel_init+0x10/0xfc
[    2.686248] [<ffffff8008085e10>] ret_from_fork+0x10/0x40

In hisi_pcie_init, I used "struct acpi_device *device = ACPI_COMPANION(dev);".
I found the reason is V7 lack the below code. I added the below code, it worked ok.

[PATCH V6 01/13] pci, acpi, x86, ia64: Move ACPI host bridge device companion assignment to core code.
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -564,6 +564,11 @@ static int acpi_pci_root_add(struct acpi_device *device,
  		}
  	}

+	/*
+	 * pci_create_root_bus() needs to detect the parent device type,
+	 * so initialize its companion data accordingly.
+	 */
+	ACPI_COMPANION_SET(&device->dev, device);

This code will be upstreamed with the "PATCH V6 11/13 specic quirks" in next time after the patchset is accepted.
Right ?

? 2016/5/10 23:19, Tomasz Nowicki ??:
> This patch provides a way to set the ACPI companion in PCI code.
> We define acpi_pci_set_companion() to set the ACPI companion pointer and
> call it from PCI core code. The function is stub for now.
>
> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> ---
>   drivers/pci/probe.c      | 2 ++
>   include/linux/pci-acpi.h | 4 ++++
>   2 files changed, 6 insertions(+)
>
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 8004f67..fb0b752 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -12,6 +12,7 @@
>   #include <linux/slab.h>
>   #include <linux/module.h>
>   #include <linux/cpumask.h>
> +#include <linux/pci-acpi.h>
>   #include <linux/pci-aspm.h>
>   #include <linux/aer.h>
>   #include <linux/acpi.h>
> @@ -2141,6 +2142,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
>   	bridge->dev.parent = parent;
>   	bridge->dev.release = pci_release_host_bridge_dev;
>   	dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
> +	acpi_pci_set_companion(bridge);
>   	error = pcibios_root_bridge_prepare(bridge);
>   	if (error) {
>   		kfree(bridge);
> diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
> index 09f9f02..1baa515 100644
> --- a/include/linux/pci-acpi.h
> +++ b/include/linux/pci-acpi.h
> @@ -111,6 +111,10 @@ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
>   static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
>   #endif	/* CONFIG_ACPI */
>
> +static inline void acpi_pci_set_companion(struct pci_host_bridge *bridge)
> +{
> +}
> +
>   static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus)
>   {
>   	return 0;
>



From a0393675 at ti.com  Mon May 16 20:22:06 2016
From: a0393675 at ti.com (Keerthy)
Date: Tue, 17 May 2016 08:52:06 +0530
Subject: [PATCH 2/8] Documentation: regulator: tps65218: Update examples
In-Reply-To: <20160516144847.GA26659@rob-hp-laptop>
References: <1462945691-904-1-git-send-email-j-keerthy@ti.com>
 <1462945691-904-3-git-send-email-j-keerthy@ti.com>
 <20160516144847.GA26659@rob-hp-laptop>
Message-ID: <573A8E5E.2080809@ti.com>



On Monday 16 May 2016 08:18 PM, Rob Herring wrote:
> On Wed, May 11, 2016 at 11:18:05AM +0530, Keerthy wrote:
>> This updates the device tree according to the preferred way of parsing
>> the nodes using the regulator framework.
>>
>> Signed-off-by: Keerthy <j-keerthy at ti.com>
>> ---
>>   .../devicetree/bindings/regulator/tps65218.txt     | 87 ++++++++++++++++++----
>>   1 file changed, 71 insertions(+), 16 deletions(-)
>
> It wasn't exactly clear that the compatible string "added" here is
> already used, so it looked like you were breaking compatibility at
> first. Otherwise,
>
> Acked-by: Rob Herring <robh at kernel.org>

Thanks Rob.

>


From wens at csie.org  Mon May 16 20:36:27 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 11:36:27 +0800
Subject: [PATCH 17/20] ARM: multi_v7: Enable sun4i DRM driver
In-Reply-To: <1463402840-17062-18-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-18-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v67_wpUiVVP9C2k040GDqe03JCAw_N2i+0QsAasHE11wfQ@mail.gmail.com>

On Mon, May 16, 2016 at 8:47 PM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Enable the new DRM driver in the multi_v7 defconfig
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>

Acked-by: Chen-Yu Tsai <wens at csie.org>


From wens at csie.org  Mon May 16 20:51:36 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 11:51:36 +0800
Subject: [PATCH 08/20] drm/sun4i: rgb: panel is an error pointer
In-Reply-To: <1463402840-17062-9-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-9-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v6485nF_e9GeANLsy2Rq1XOn4nV5wD_eWskTmL2ME316+w@mail.gmail.com>

Hi,

On Mon, May 16, 2016 at 8:47 PM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> In case of an error, our pointer to the drm_panel structure attached to our
> encoder will hold an error pointer, not a NULL pointer.
>
> Make sure we check the right thing.
>
> Fixes: 29e57fab97fc ("drm: sun4i: Add RGB output")
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_rgb.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index 923f55039cb1..b46d2c15dc95 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -217,7 +217,7 @@ int sun4i_rgb_init(struct drm_device *drm)
>         int ret;
>
>         /* If we don't have a panel, there's no point in going on */
> -       if (!tcon->panel)
> +       if (IS_ERR(tcon->panel))

Without the next patch, tcon->panel could be the result of of_drm_find_panel(),
which could be NULL.

Use IS_ERR_OR_NULL here, or reorder/squash the patches.

Regards
ChenYu

>                 return -ENODEV;
>
>         rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL);
> --
> 2.8.2
>


From wens at csie.org  Mon May 16 20:52:10 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 11:52:10 +0800
Subject: [PATCH 09/20] drm/sun4i: defer only if we didn't find our panel
In-Reply-To: <1463402840-17062-10-git-send-email-maxime.ripard@free-electrons.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-10-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v655q_w8s7Eg8xnpzdX9PDxSEhRLvMu3bNOd==U4APgg0Q@mail.gmail.com>

Hi,

On Mon, May 16, 2016 at 8:47 PM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Our code currently defers our probe on any error, even if we were not
> expecting to have one at all.
>
> Make sure we return -EPROBE_DEFER only when we were supposed to have a
> panel, but it's not probed yet.
>
> Fixes: 29e57fab97fc ("drm: sun4i: Add RGB output")
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 15 ++++++++-------
>  1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 9f19b0e08560..eed6a9e8d9a6 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -429,7 +429,7 @@ static struct drm_panel *sun4i_tcon_find_panel(struct device_node *node)
>                 return ERR_PTR(-EINVAL);
>         }
>
> -       return of_drm_find_panel(remote);
> +       return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER);

There's also a typo in the DRM_DEBUG_DRIVER call a few lines up. Could you
fix it as well?

ChenYu

>  }
>
>  static int sun4i_tcon_bind(struct device *dev, struct device *master,
> @@ -522,12 +522,13 @@ static int sun4i_tcon_probe(struct platform_device *pdev)
>          * Defer the probe.
>          */
>         panel = sun4i_tcon_find_panel(node);
> -       if (IS_ERR(panel)) {
> -               /*
> -                * If we don't have a panel endpoint, just go on
> -                */
> -               if (PTR_ERR(panel) != -ENODEV)
> -                       return -EPROBE_DEFER;
> +
> +       /*
> +        * If we don't have a panel endpoint, just go on
> +        */
> +       if (PTR_ERR(panel) == -EPROBE_DEFER) {
> +               DRM_DEBUG_DRIVER("Still waiting for our panel. Deferring...\n");
> +               return -EPROBE_DEFER;
>         }
>
>         return component_add(&pdev->dev, &sun4i_tcon_ops);
> --
> 2.8.2
>


From ritesh.list at gmail.com  Mon May 16 21:31:54 2016
From: ritesh.list at gmail.com (Ritesh Harjani)
Date: Tue, 17 May 2016 10:01:54 +0530
Subject: [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during
 no data transfer
In-Reply-To: <573184F3.50201@intel.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-10-git-send-email-aisheng.dong@nxp.com>
 <573184F3.50201@intel.com>
Message-ID: <CALk7dXpDXS2R0RJ9KNTaMFxBC+VVvrJ+U1X5Z_kZJNxwxrC6iQ@mail.gmail.com>

On Tue, May 10, 2016 at 12:21 PM, Adrian Hunter <adrian.hunter at intel.com> wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
>> Current code will report the wrong data interrupt got when no
>> data operation in progress assumed by getting !host->data in
>> sdhci_data_irq().
>>
>> For a data command handling process, the driver will call
>> sdhci_finish_data() and clear host->data in case any data error,
>> then card finish_tasklet will do the rest controller reset work.
>>
>> Before the tasklet got run, however, controllers may report the
>> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
>> than data CRC error and data end bit error interrupts for single
>> block transfer or the last block of multiblock transfer.

What if the controller generates Transfer complete interrupt bit more slower
and the tasklet do get a chance to run. In that case even host->mrq
will become NULL.
Actually if that happens it's even more worse since the driver may
start issuing other commands to controller.

Are we covering that case here? Do you think that this case is possible?


>>
>> Controller usually detects and generates data CRC/end bit error
>> interrupts once one block on the bus is transferred completely.
>> For single block transfer, since there's only one bock to transfer,
>> the controller will report transfer complete interrupt as well,
>> but until the data in controller FIFO has been successfully
>> transferred to memory. The time gap of TC and CRC interrupt depends on
>> the system busy state at that point and memory bus access speed.
>>
>> So it is possible when TC interrupt generated, host->data is already
>> equal to NULL due to cleared by former CRC/Data End Bit error which
>> is reasonable.
>>
>> Thus we DO NOT report the weird data interrupt event for this case.
>>
>> Else we may easily see warning below during SD3.0 card manually tuning
>> process (calling mmc_send_tuning() which is a single block transfer)
>> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
>>
>> The detailed command log is as follows:
>> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
>> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
>> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
>> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
>> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
>> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
>> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
>> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
>> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
>> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
>> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
>> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
>> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
>> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
>> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
>> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
>> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
>> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
>> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
>> [ 1657.929995] sdhci: ===========================================
>> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
>> [ 1657.930179] mmc0:     0 bytes transferred: -84
>>
>> It shows we first have a data CRC error interrupt then a data transfer
>> complete interrupt.
>> Then we got the !host->data case in sdhci_data_irq().
>>
>> CC: stable <stable at vger.kernel.org>
>> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
>> ---
>>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>>  1 file changed, 11 insertions(+)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 40e3551..2eb0e34 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>>                       }
>>               }
>>
>> +             /*
>> +              * The "data complete" interrupt is possible to happen a bit
>> +              * later than CRC error and data end bit error interrupts
>> +              * separately for single block transfer or the last block of
>> +              * multiblock transfer. For this case, we DO NOT report the
>> +              * weird data interrupt event.
>> +              */
>> +             if ((intmask & SDHCI_INT_DATA_END) &&
>> +                 (host->mrq && host->mrq->data && host->mrq->data->error))
>> +                     return;
>
> This could be generalized a bit more i.e. what about:
>
>                 /*
>                  * After an error and before the the data circuit is reset in
>                  * sdhci_tasklet_finish, we could get more interrupts, but we
>                  * already have an error, so ignore them.
>                  */
>                 if (host->mrq && host->mrq->data && host->mrq->data->error)
>                         return;
>
>> +
>>               pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
>>                      mmc_hostname(host->mmc), (unsigned)intmask);
>>               sdhci_dumpregs(host);
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From erin.lo at mediatek.com  Mon May 16 22:05:01 2016
From: erin.lo at mediatek.com (Erin Lo)
Date: Tue, 17 May 2016 13:05:01 +0800
Subject: [PATCH v8 0/10] Add clock support for Mediatek MT2701
Message-ID: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>

This series is based on clk-next, add clock and reset controller support
for Mediatek MT2701.

This series also refined makefile and Kconfig to support configurable
multiple SoC clock support.

There some code borrowed from [2] in clk-mtk.h, and may need to resolve
conflicts while merging these two series.

changes since v7:
- Rebase to clk-next.
- Implement subsystem clocks in seperated files.
- Replace critical clock enabling with CLK_IS_CRITICAL flag.
- Reduce most clock registrations in CLK_OF_DECLARE().
- Remove __init and __initconst from most init fucntions and data,
  and replace driver registration with platform_driver_register().
- Replace some common function or variable names with unique names.
- Use real clock for UARTs.

changes since v6:
- Rebase to v4.6-rc1.
- Register subsystem clocks in probe() instead of CLK_OF_DECLARE().
- Add clocks that referred by subsystem clocks.
- Fix clk_data size of apmixedsys.
- Add config options for each subsystem clock provider.

changes since v5:
- Rebase to v4.5-rc1 and [1].
- Enable critical clocks for MT2701
- Refine dt-binding documents, add reset controller support for hifsys.

changes since v4:
- Rebase to v4.5-rc1.
- Remove CLK_SET_RATE_PARENT from divider flags.
- Add img_jpgdec_smi clock.
- Move clk/mediatek/Kconfig into menu section in clk/Kconfig.

changes since v3:
- Change the parent of mm_mdp_bls_26m from clk26m to pwm_sel.

changes since v2:
- Fix ethsys definition.
- Replace read-modify-write with regmap_update_bits() in clock operations.
- Move mt2701-resets.h to include/dt-bindings/reset/.
- Add hifsys reset patch from John Crispin.

changes since v1:
- Document MT2701 compatible strings.

[1] https://patchwork.kernel.org/patch/8147901/
[2] http://www.spinics.net/lists/dri-devel/msg106726.html

Erin Lo (1):
  arm: dts: mt2701: Use real clock for UARTs

James Liao (5):
  clk: fix initial state of critical clock's parents
  clk: mediatek: remove __init from clk registration functions
  clk: mediatek: Refine the makefile to support multiple clock drivers
  dt-bindings: ARM: Mediatek: Document bindings for MT2701
  arm: dts: mt2701: Add clock controller device nodes

Shunli Wang (4):
  clk: mediatek: Add dt-bindings for MT2701 clocks
  clk: mediatek: Add MT2701 clock support
  reset: mediatek: Add MT2701 reset controller dt-binding file
  reset: mediatek: Add MT2701 reset driver

 .../bindings/arm/mediatek/mediatek,apmixedsys.txt  |    3 +-
 .../bindings/arm/mediatek/mediatek,bdpsys.txt      |   22 +
 .../bindings/arm/mediatek/mediatek,ethsys.txt      |   22 +
 .../bindings/arm/mediatek/mediatek,hifsys.txt      |   24 +
 .../bindings/arm/mediatek/mediatek,imgsys.txt      |    3 +-
 .../bindings/arm/mediatek/mediatek,infracfg.txt    |    3 +-
 .../bindings/arm/mediatek/mediatek,mmsys.txt       |    3 +-
 .../bindings/arm/mediatek/mediatek,pericfg.txt     |    3 +-
 .../bindings/arm/mediatek/mediatek,topckgen.txt    |    3 +-
 .../bindings/arm/mediatek/mediatek,vdecsys.txt     |    3 +-
 arch/arm/boot/dts/mt2701.dtsi                      |   50 +-
 drivers/clk/Kconfig                                |    1 +
 drivers/clk/clk.c                                  |    9 +-
 drivers/clk/mediatek/Kconfig                       |   73 ++
 drivers/clk/mediatek/Makefile                      |   13 +-
 drivers/clk/mediatek/clk-gate.c                    |   54 +-
 drivers/clk/mediatek/clk-gate.h                    |    2 +
 drivers/clk/mediatek/clk-mt2701-bdp.c              |  140 +++
 drivers/clk/mediatek/clk-mt2701-eth.c              |   82 ++
 drivers/clk/mediatek/clk-mt2701-hif.c              |   81 ++
 drivers/clk/mediatek/clk-mt2701-img.c              |   82 ++
 drivers/clk/mediatek/clk-mt2701-mm.c               |  125 +++
 drivers/clk/mediatek/clk-mt2701-vdec.c             |   93 ++
 drivers/clk/mediatek/clk-mt2701.c                  | 1037 ++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.c                     |   52 +-
 drivers/clk/mediatek/clk-mtk.h                     |   52 +-
 drivers/clk/mediatek/clk-pll.c                     |    3 +-
 include/dt-bindings/clock/mt2701-clk.h             |  486 +++++++++
 include/dt-bindings/reset/mt2701-resets.h          |   83 ++
 29 files changed, 2578 insertions(+), 29 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt
 create mode 100644 drivers/clk/mediatek/Kconfig
 create mode 100644 drivers/clk/mediatek/clk-mt2701-bdp.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-eth.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-hif.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-img.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-mm.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-vdec.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701.c
 create mode 100644 include/dt-bindings/clock/mt2701-clk.h
 create mode 100644 include/dt-bindings/reset/mt2701-resets.h

--
1.9.1



From erin.lo at mediatek.com  Mon May 16 22:05:02 2016
From: erin.lo at mediatek.com (Erin Lo)
Date: Tue, 17 May 2016 13:05:02 +0800
Subject: [PATCH v8 01/10] clk: fix initial state of critical clock's parents
In-Reply-To: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
References: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
Message-ID: <1463461511-25019-2-git-send-email-erin.lo@mediatek.com>

From: James Liao <jamesjj.liao at mediatek.com>

This patch fixed wrong state of parent clocks if they are registered
after critical clocks.

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
---
 drivers/clk/clk.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index ce39add..bf80e39 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2388,8 +2388,15 @@ static int __clk_core_init(struct clk_core *core)
 	hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
 		struct clk_core *parent = __clk_init_parent(orphan);
 
-		if (parent)
+		if (parent) {
 			clk_core_reparent(orphan, parent);
+
+			if (orphan->prepare_count)
+				clk_core_prepare(parent);
+
+			if (orphan->enable_count)
+				clk_core_enable(parent);
+		}
 	}
 
 	/*
-- 
1.9.1



From erin.lo at mediatek.com  Mon May 16 22:05:08 2016
From: erin.lo at mediatek.com (Erin Lo)
Date: Tue, 17 May 2016 13:05:08 +0800
Subject: [PATCH v8 07/10] reset: mediatek: Add MT2701 reset controller
 dt-binding file
In-Reply-To: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
References: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
Message-ID: <1463461511-25019-8-git-send-email-erin.lo@mediatek.com>

From: Shunli Wang <shunli.wang at mediatek.com>

Dt-binding file about reset controller is used to provide
kinds of definition, which is referenced by dts file and
IC-specified reset controller driver code.

Signed-off-by: Shunli Wang <shunli.wang at mediatek.com>
Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Tested-by: John Crispin <blogic at openwrt.org>
Acked-by: Philipp Zabel <p.zabel at pengutronix.de>
---
 include/dt-bindings/reset/mt2701-resets.h | 83 +++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)
 create mode 100644 include/dt-bindings/reset/mt2701-resets.h

diff --git a/include/dt-bindings/reset/mt2701-resets.h b/include/dt-bindings/reset/mt2701-resets.h
new file mode 100644
index 0000000..aaf0305
--- /dev/null
+++ b/include/dt-bindings/reset/mt2701-resets.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015 MediaTek, Shunli Wang <shunli.wang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT2701
+#define _DT_BINDINGS_RESET_CONTROLLER_MT2701
+
+/* INFRACFG resets */
+#define MT2701_INFRA_EMI_REG_RST		0
+#define MT2701_INFRA_DRAMC0_A0_RST		1
+#define MT2701_INFRA_FHCTL_RST			2
+#define MT2701_INFRA_APCIRQ_EINT_RST		3
+#define MT2701_INFRA_APXGPT_RST			4
+#define MT2701_INFRA_SCPSYS_RST			5
+#define MT2701_INFRA_KP_RST			6
+#define MT2701_INFRA_PMIC_WRAP_RST		7
+#define MT2701_INFRA_MIPI_RST			8
+#define MT2701_INFRA_IRRX_RST			9
+#define MT2701_INFRA_CEC_RST			10
+#define MT2701_INFRA_EMI_RST			32
+#define MT2701_INFRA_DRAMC0_RST			34
+#define MT2701_INFRA_TRNG_RST			37
+#define MT2701_INFRA_SYSIRQ_RST			38
+
+/*  PERICFG resets */
+#define MT2701_PERI_UART0_SW_RST		0
+#define MT2701_PERI_UART1_SW_RST		1
+#define MT2701_PERI_UART2_SW_RST		2
+#define MT2701_PERI_UART3_SW_RST		3
+#define MT2701_PERI_GCPU_SW_RST			5
+#define MT2701_PERI_BTIF_SW_RST			6
+#define MT2701_PERI_PWM_SW_RST			8
+#define MT2701_PERI_AUXADC_SW_RST		10
+#define MT2701_PERI_DMA_SW_RST			11
+#define MT2701_PERI_NFI_SW_RST			14
+#define MT2701_PERI_NLI_SW_RST			15
+#define MT2701_PERI_THERM_SW_RST		16
+#define MT2701_PERI_MSDC2_SW_RST		17
+#define MT2701_PERI_MSDC0_SW_RST		19
+#define MT2701_PERI_MSDC1_SW_RST		20
+#define MT2701_PERI_I2C0_SW_RST			22
+#define MT2701_PERI_I2C1_SW_RST			23
+#define MT2701_PERI_I2C2_SW_RST			24
+#define MT2701_PERI_I2C3_SW_RST			25
+#define MT2701_PERI_USB_SW_RST			28
+#define MT2701_PERI_ETH_SW_RST			29
+#define MT2701_PERI_SPI0_SW_RST			33
+
+/* TOPRGU resets */
+#define MT2701_TOPRGU_INFRA_RST			0
+#define MT2701_TOPRGU_MM_RST			1
+#define MT2701_TOPRGU_MFG_RST			2
+#define MT2701_TOPRGU_ETHDMA_RST		3
+#define MT2701_TOPRGU_VDEC_RST			4
+#define MT2701_TOPRGU_VENC_IMG_RST		5
+#define MT2701_TOPRGU_DDRPHY_RST		6
+#define MT2701_TOPRGU_MD_RST			7
+#define MT2701_TOPRGU_INFRA_AO_RST		8
+#define MT2701_TOPRGU_CONN_RST			9
+#define MT2701_TOPRGU_APMIXED_RST		10
+#define MT2701_TOPRGU_HIFSYS_RST		11
+#define MT2701_TOPRGU_CONN_MCU_RST		12
+#define MT2701_TOPRGU_BDP_DISP_RST		13
+
+/* HIFSYS resets */
+#define MT2701_HIFSYS_UHOST0_RST		3
+#define MT2701_HIFSYS_UHOST1_RST		4
+#define MT2701_HIFSYS_UPHY0_RST			21
+#define MT2701_HIFSYS_UPHY1_RST			22
+#define MT2701_HIFSYS_PCIE0_RST			24
+#define MT2701_HIFSYS_PCIE1_RST			25
+#define MT2701_HIFSYS_PCIE2_RST			26
+
+#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT2701 */
-- 
1.9.1



From erin.lo at mediatek.com  Mon May 16 22:05:04 2016
From: erin.lo at mediatek.com (Erin Lo)
Date: Tue, 17 May 2016 13:05:04 +0800
Subject: [PATCH v8 03/10] clk: mediatek: Refine the makefile to support
 multiple clock drivers
In-Reply-To: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
References: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
Message-ID: <1463461511-25019-4-git-send-email-erin.lo@mediatek.com>

From: James Liao <jamesjj.liao at mediatek.com>

Add a Kconfig to define clock configuration for each SoC, and
modify the Makefile to build drivers that only selected in config.

Signed-off-by: Shunli Wang <shunli.wang at mediatek.com>
Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Tested-by: John Crispin <blogic at openwrt.org>
Reviewed-by: Matthias Brugger <matthias.bgg at gmail.com>
---
 drivers/clk/Kconfig           |  1 +
 drivers/clk/mediatek/Kconfig  | 23 +++++++++++++++++++++++
 drivers/clk/mediatek/Makefile |  6 +++---
 3 files changed, 27 insertions(+), 3 deletions(-)
 create mode 100644 drivers/clk/mediatek/Kconfig

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 2dd371d..34c6aa9 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -205,6 +205,7 @@ config COMMON_CLK_OXNAS
 
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
+source "drivers/clk/mediatek/Kconfig"
 source "drivers/clk/mvebu/Kconfig"
 source "drivers/clk/qcom/Kconfig"
 source "drivers/clk/renesas/Kconfig"
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
new file mode 100644
index 0000000..dc224e6
--- /dev/null
+++ b/drivers/clk/mediatek/Kconfig
@@ -0,0 +1,23 @@
+#
+# MediaTek SoC drivers
+#
+config COMMON_CLK_MEDIATEK
+	bool
+	---help---
+	  Mediatek SoCs' clock support.
+
+config COMMON_CLK_MT8135
+	bool "Clock driver for Mediatek MT8135"
+	depends on COMMON_CLK
+	select COMMON_CLK_MEDIATEK
+	default ARCH_MEDIATEK
+	---help---
+	  This driver supports Mediatek MT8135 clocks.
+
+config COMMON_CLK_MT8173
+	bool "Clock driver for Mediatek MT8173"
+	depends on COMMON_CLK
+	select COMMON_CLK_MEDIATEK
+	default ARCH_MEDIATEK
+	---help---
+	  This driver supports Mediatek MT8173 clocks.
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 95fdfac..32e7222 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,4 +1,4 @@
-obj-y += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
+obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
-obj-y += clk-mt8135.o
-obj-y += clk-mt8173.o
+obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
+obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
-- 
1.9.1



From erin.lo at mediatek.com  Mon May 16 22:05:03 2016
From: erin.lo at mediatek.com (Erin Lo)
Date: Tue, 17 May 2016 13:05:03 +0800
Subject: [PATCH v8 02/10] clk: mediatek: remove __init from clk registration
 functions
In-Reply-To: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
References: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
Message-ID: <1463461511-25019-3-git-send-email-erin.lo@mediatek.com>

From: James Liao <jamesjj.liao at mediatek.com>

Remove __init from functions that will be used by init functions
that support probe deferral.

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
---
 drivers/clk/mediatek/clk-gate.c |  2 +-
 drivers/clk/mediatek/clk-mtk.c  | 12 ++++++------
 drivers/clk/mediatek/clk-pll.c  |  2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
index 2a76901..d8787bf 100644
--- a/drivers/clk/mediatek/clk-gate.c
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -97,7 +97,7 @@ const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
 	.disable	= mtk_cg_disable_inv,
 };
 
-struct clk * __init mtk_clk_register_gate(
+struct clk *mtk_clk_register_gate(
 		const char *name,
 		const char *parent_name,
 		struct regmap *regmap,
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index 5ada644..bb30f70 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -24,7 +24,7 @@
 #include "clk-mtk.h"
 #include "clk-gate.h"
 
-struct clk_onecell_data * __init mtk_alloc_clk_data(unsigned int clk_num)
+struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
 {
 	int i;
 	struct clk_onecell_data *clk_data;
@@ -49,7 +49,7 @@ err_out:
 	return NULL;
 }
 
-void __init mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
+void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
 		int num, struct clk_onecell_data *clk_data)
 {
 	int i;
@@ -72,7 +72,7 @@ void __init mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
 	}
 }
 
-void __init mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
+void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
 		int num, struct clk_onecell_data *clk_data)
 {
 	int i;
@@ -95,7 +95,7 @@ void __init mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
 	}
 }
 
-int __init mtk_clk_register_gates(struct device_node *node,
+int mtk_clk_register_gates(struct device_node *node,
 		const struct mtk_gate *clks,
 		int num, struct clk_onecell_data *clk_data)
 {
@@ -135,7 +135,7 @@ int __init mtk_clk_register_gates(struct device_node *node,
 	return 0;
 }
 
-struct clk * __init mtk_clk_register_composite(const struct mtk_composite *mc,
+struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
 		void __iomem *base, spinlock_t *lock)
 {
 	struct clk *clk;
@@ -222,7 +222,7 @@ err_out:
 	return ERR_PTR(ret);
 }
 
-void __init mtk_clk_register_composites(const struct mtk_composite *mcs,
+void mtk_clk_register_composites(const struct mtk_composite *mcs,
 		int num, void __iomem *base, spinlock_t *lock,
 		struct clk_onecell_data *clk_data)
 {
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index 966cab1..0c2deac 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -313,7 +313,7 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
 	return clk;
 }
 
-void __init mtk_clk_register_plls(struct device_node *node,
+void mtk_clk_register_plls(struct device_node *node,
 		const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
 {
 	void __iomem *base;
-- 
1.9.1



From erin.lo at mediatek.com  Mon May 16 22:05:05 2016
From: erin.lo at mediatek.com (Erin Lo)
Date: Tue, 17 May 2016 13:05:05 +0800
Subject: [PATCH v8 04/10] dt-bindings: ARM: Mediatek: Document bindings for
 MT2701
In-Reply-To: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
References: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
Message-ID: <1463461511-25019-5-git-send-email-erin.lo@mediatek.com>

From: James Liao <jamesjj.liao at mediatek.com>

This patch adds the binding documentation for apmixedsys, bdpsys,
ethsys, hifsys, imgsys, infracfg, mmsys, pericfg, topckgen and
vdecsys for Mediatek MT2701.

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Tested-by: John Crispin <blogic at openwrt.org>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../bindings/arm/mediatek/mediatek,apmixedsys.txt  |  3 ++-
 .../bindings/arm/mediatek/mediatek,bdpsys.txt      | 22 ++++++++++++++++++++
 .../bindings/arm/mediatek/mediatek,ethsys.txt      | 22 ++++++++++++++++++++
 .../bindings/arm/mediatek/mediatek,hifsys.txt      | 24 ++++++++++++++++++++++
 .../bindings/arm/mediatek/mediatek,imgsys.txt      |  3 ++-
 .../bindings/arm/mediatek/mediatek,infracfg.txt    |  3 ++-
 .../bindings/arm/mediatek/mediatek,mmsys.txt       |  3 ++-
 .../bindings/arm/mediatek/mediatek,pericfg.txt     |  3 ++-
 .../bindings/arm/mediatek/mediatek,topckgen.txt    |  3 ++-
 .../bindings/arm/mediatek/mediatek,vdecsys.txt     |  3 ++-
 10 files changed, 82 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt

diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
index 936166f..cb0054a 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
@@ -5,7 +5,8 @@ The Mediatek apmixedsys controller provides the PLLs to the system.
 
 Required Properties:
 
-- compatible: Should be:
+- compatible: Should be one of:
+	- "mediatek,mt2701-apmixedsys"
 	- "mediatek,mt8135-apmixedsys"
 	- "mediatek,mt8173-apmixedsys"
 - #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt
new file mode 100644
index 0000000..4137196
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt
@@ -0,0 +1,22 @@
+Mediatek bdpsys controller
+============================
+
+The Mediatek bdpsys controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt2701-bdpsys", "syscon"
+- #clock-cells: Must be 1
+
+The bdpsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+bdpsys: clock-controller at 1c000000 {
+	compatible = "mediatek,mt2701-bdpsys", "syscon";
+	reg = <0 0x1c000000 0 0x1000>;
+	#clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt
new file mode 100644
index 0000000..768f3a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt
@@ -0,0 +1,22 @@
+Mediatek ethsys controller
+============================
+
+The Mediatek ethsys controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt2701-ethsys", "syscon"
+- #clock-cells: Must be 1
+
+The ethsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+ethsys: clock-controller at 1b000000 {
+	compatible = "mediatek,mt2701-ethsys", "syscon";
+	reg = <0 0x1b000000 0 0x1000>;
+	#clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt
new file mode 100644
index 0000000..beed7b5
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt
@@ -0,0 +1,24 @@
+Mediatek hifsys controller
+============================
+
+The Mediatek hifsys controller provides various clocks and reset
+outputs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt2701-hifsys", "syscon"
+- #clock-cells: Must be 1
+
+The hifsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+hifsys: clock-controller at 1a000000 {
+	compatible = "mediatek,mt2701-hifsys", "syscon";
+	reg = <0 0x1a000000 0 0x1000>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
index b1f2ce1..f6a9166 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
@@ -5,7 +5,8 @@ The Mediatek imgsys controller provides various clocks to the system.
 
 Required Properties:
 
-- compatible: Should be:
+- compatible: Should be one of:
+	- "mediatek,mt2701-imgsys", "syscon"
 	- "mediatek,mt8173-imgsys", "syscon"
 - #clock-cells: Must be 1
 
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
index aaf8d14..1620ec2 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
@@ -6,7 +6,8 @@ outputs to the system.
 
 Required Properties:
 
-- compatible: Should be:
+- compatible: Should be one of:
+	- "mediatek,mt2701-infracfg", "syscon"
 	- "mediatek,mt8135-infracfg", "syscon"
 	- "mediatek,mt8173-infracfg", "syscon"
 - #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
index 4385946..67dd2e4 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
@@ -5,7 +5,8 @@ The Mediatek mmsys controller provides various clocks to the system.
 
 Required Properties:
 
-- compatible: Should be:
+- compatible: Should be one of:
+	- "mediatek,mt2701-mmsys", "syscon"
 	- "mediatek,mt8173-mmsys", "syscon"
 - #clock-cells: Must be 1
 
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
index 2f6ff86..e494366 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
@@ -6,7 +6,8 @@ outputs to the system.
 
 Required Properties:
 
-- compatible: Should be:
+- compatible: Should be one of:
+	- "mediatek,mt2701-pericfg", "syscon"
 	- "mediatek,mt8135-pericfg", "syscon"
 	- "mediatek,mt8173-pericfg", "syscon"
 - #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
index f9e9179..9f2fe78 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
@@ -5,7 +5,8 @@ The Mediatek topckgen controller provides various clocks to the system.
 
 Required Properties:
 
-- compatible: Should be:
+- compatible: Should be one of:
+	- "mediatek,mt2701-topckgen"
 	- "mediatek,mt8135-topckgen"
 	- "mediatek,mt8173-topckgen"
 - #clock-cells: Must be 1
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
index 1faacf1..2440f73 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
@@ -5,7 +5,8 @@ The Mediatek vdecsys controller provides various clocks to the system.
 
 Required Properties:
 
-- compatible: Should be:
+- compatible: Should be one of:
+	- "mediatek,mt2701-vdecsys", "syscon"
 	- "mediatek,mt8173-vdecsys", "syscon"
 - #clock-cells: Must be 1
 
-- 
1.9.1



From erin.lo at mediatek.com  Mon May 16 22:05:10 2016
From: erin.lo at mediatek.com (Erin Lo)
Date: Tue, 17 May 2016 13:05:10 +0800
Subject: [PATCH v8 09/10] arm: dts: mt2701: Add clock controller device nodes
In-Reply-To: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
References: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
Message-ID: <1463461511-25019-10-git-send-email-erin.lo@mediatek.com>

From: James Liao <jamesjj.liao at mediatek.com>

Add clock controller nodes for MT2701, include topckgen, infracfg,
pericfg, apmixedsys, mmsys, imgsys, vdecsys, hifsys, ethsys and
bdpsys. This patch also add two oscillators that provide clocks for
MT2701.

Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
---
 arch/arm/boot/dts/mt2701.dtsi | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 8343768..171d4da 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -12,6 +12,7 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/clock/mt2701-clk.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include "skeleton64.dtsi"
@@ -76,6 +77,20 @@
 		#clock-cells = <0>;
 	};
 
+	clk26m: oscillator at 0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+		clock-output-names = "clk26m";
+	};
+
+	rtc32k: oscillator at 1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32000>;
+		clock-output-names = "rtc32k";
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		interrupt-parent = <&gic>;
@@ -85,6 +100,26 @@
 			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
 	};
 
+	topckgen: syscon at 10000000 {
+		compatible = "mediatek,mt2701-topckgen", "syscon";
+		reg = <0 0x10000000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	infracfg: syscon at 10001000 {
+		compatible = "mediatek,mt2701-infracfg", "syscon";
+		reg = <0 0x10001000 0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	pericfg: syscon at 10003000 {
+		compatible = "mediatek,mt2701-pericfg", "syscon";
+		reg = <0 0x10003000 0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
 	watchdog: watchdog at 10007000 {
 		compatible = "mediatek,mt2701-wdt",
 			     "mediatek,mt6589-wdt";
@@ -109,6 +144,13 @@
 		reg = <0 0x10200100 0 0x1c>;
 	};
 
+	apmixedsys: syscon at 10209000 {
+		compatible = "mediatek,mt2701-apmixedsys", "syscon";
+		reg = <0 0x10209000 0 0x1000>;
+		mediatek,hdmi-ibias = <0xa>;
+		#clock-cells = <1>;
+	};
+
 	gic: interrupt-controller at 10211000 {
 		compatible = "arm,cortex-a7-gic";
 		interrupt-controller;
-- 
1.9.1



From erin.lo at mediatek.com  Mon May 16 22:05:09 2016
From: erin.lo at mediatek.com (Erin Lo)
Date: Tue, 17 May 2016 13:05:09 +0800
Subject: [PATCH v8 08/10] reset: mediatek: Add MT2701 reset driver
In-Reply-To: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
References: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
Message-ID: <1463461511-25019-9-git-send-email-erin.lo@mediatek.com>

From: Shunli Wang <shunli.wang at mediatek.com>

In infrasys and perifsys, there are many reset
control bits for kinds of modules. These bits are
used as actual reset controllers to be registered
into kernel's generic reset controller framework.

Signed-off-by: Shunli Wang <shunli.wang at mediatek.com>
Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Tested-by: John Crispin <blogic at openwrt.org>
Acked-by: Philipp Zabel <p.zabel at pengutronix.de>
---
 drivers/clk/mediatek/clk-mt2701-hif.c | 2 ++
 drivers/clk/mediatek/clk-mt2701.c     | 4 ++++
 2 files changed, 6 insertions(+)

diff --git a/drivers/clk/mediatek/clk-mt2701-hif.c b/drivers/clk/mediatek/clk-mt2701-hif.c
index 3f6cea2..28014bf 100644
--- a/drivers/clk/mediatek/clk-mt2701-hif.c
+++ b/drivers/clk/mediatek/clk-mt2701-hif.c
@@ -55,6 +55,8 @@ static void mtk_hifsys_init(struct device_node *node)
 	if (r)
 		pr_err("%s(): could not register clock provider: %d\n",
 			__func__, r);
+
+	mtk_register_reset_controller(node, 1, 0x34);
 }
 
 static const struct of_device_id of_match_clk_mt2701_hif[] = {
diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
index 08a2954..b3cde20 100644
--- a/drivers/clk/mediatek/clk-mt2701.c
+++ b/drivers/clk/mediatek/clk-mt2701.c
@@ -791,6 +791,8 @@ static void mtk_infrasys_init(struct device_node *node)
 	if (r)
 		pr_err("%s(): could not register clock provider: %d\n",
 			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0x30);
 }
 
 static const struct mtk_gate_regs peri0_cg_regs = {
@@ -911,6 +913,8 @@ static void mtk_pericfg_init(struct device_node *node)
 	if (r)
 		pr_err("%s(): could not register clock provider: %d\n",
 			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0x0);
 }
 
 #define MT8590_PLL_FMAX		(2000 * MHZ)
-- 
1.9.1



From erin.lo at mediatek.com  Mon May 16 22:05:11 2016
From: erin.lo at mediatek.com (Erin Lo)
Date: Tue, 17 May 2016 13:05:11 +0800
Subject: [PATCH v8 10/10] arm: dts: mt2701: Use real clock for UARTs
In-Reply-To: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
References: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
Message-ID: <1463461511-25019-11-git-send-email-erin.lo@mediatek.com>

We used to use a fixed rate clock for the UARTs. Now that we have clock
support we can associate the correct clocks to the UARTs and drop the
26MHz fixed rate UART clock.

Signed-off-by: Erin Lo <erin.lo at mediatek.com>
---
 arch/arm/boot/dts/mt2701.dtsi | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 171d4da..e79e88f 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -71,12 +71,6 @@
 		#clock-cells = <0>;
 	};
 
-	uart_clk: dummy26m {
-		compatible = "fixed-clock";
-		clock-frequency = <26000000>;
-		#clock-cells = <0>;
-	};
-
 	clk26m: oscillator at 0 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
@@ -167,7 +161,8 @@
 			     "mediatek,mt6577-uart";
 		reg = <0 0x11002000 0 0x400>;
 		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&pericfg CLK_PERI_UART0_SEL>, <&pericfg CLK_PERI_UART0>;
+		clock-names = "baud", "bus";
 		status = "disabled";
 	};
 
@@ -176,7 +171,8 @@
 			     "mediatek,mt6577-uart";
 		reg = <0 0x11003000 0 0x400>;
 		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&pericfg CLK_PERI_UART1_SEL>, <&pericfg CLK_PERI_UART1>;
+		clock-names = "baud", "bus";
 		status = "disabled";
 	};
 
@@ -185,7 +181,8 @@
 			     "mediatek,mt6577-uart";
 		reg = <0 0x11004000 0 0x400>;
 		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&pericfg CLK_PERI_UART2_SEL>, <&pericfg CLK_PERI_UART2>;
+		clock-names = "baud", "bus";
 		status = "disabled";
 	};
 
@@ -194,7 +191,8 @@
 			     "mediatek,mt6577-uart";
 		reg = <0 0x11005000 0 0x400>;
 		interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&pericfg CLK_PERI_UART3_SEL>, <&pericfg CLK_PERI_UART3>;
+		clock-names = "baud", "bus";
 		status = "disabled";
 	};
 };
-- 
1.9.1



From erin.lo at mediatek.com  Mon May 16 22:05:06 2016
From: erin.lo at mediatek.com (Erin Lo)
Date: Tue, 17 May 2016 13:05:06 +0800
Subject: [PATCH v8 05/10] clk: mediatek: Add dt-bindings for MT2701 clocks
In-Reply-To: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
References: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
Message-ID: <1463461511-25019-6-git-send-email-erin.lo@mediatek.com>

From: Shunli Wang <shunli.wang at mediatek.com>

Add MT2701 clock dt-bindings, include topckgen, apmixedsys,
infracfg, pericfg and subsystem clocks.

Signed-off-by: Shunli Wang <shunli.wang at mediatek.com>
Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Tested-by: John Crispin <blogic at openwrt.org>
Reviewed-by: Matthias Brugger <matthias.bgg at gmail.com>
---
 include/dt-bindings/clock/mt2701-clk.h | 486 +++++++++++++++++++++++++++++++++
 1 file changed, 486 insertions(+)
 create mode 100644 include/dt-bindings/clock/mt2701-clk.h

diff --git a/include/dt-bindings/clock/mt2701-clk.h b/include/dt-bindings/clock/mt2701-clk.h
new file mode 100644
index 0000000..2062c67
--- /dev/null
+++ b/include/dt-bindings/clock/mt2701-clk.h
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT2701_H
+#define _DT_BINDINGS_CLK_MT2701_H
+
+/* TOPCKGEN */
+#define CLK_TOP_SYSPLL				1
+#define CLK_TOP_SYSPLL_D2			2
+#define CLK_TOP_SYSPLL_D3			3
+#define CLK_TOP_SYSPLL_D5			4
+#define CLK_TOP_SYSPLL_D7			5
+#define CLK_TOP_SYSPLL1_D2			6
+#define CLK_TOP_SYSPLL1_D4			7
+#define CLK_TOP_SYSPLL1_D8			8
+#define CLK_TOP_SYSPLL1_D16			9
+#define CLK_TOP_SYSPLL2_D2			10
+#define CLK_TOP_SYSPLL2_D4			11
+#define CLK_TOP_SYSPLL2_D8			12
+#define CLK_TOP_SYSPLL3_D2			13
+#define CLK_TOP_SYSPLL3_D4			14
+#define CLK_TOP_SYSPLL4_D2			15
+#define CLK_TOP_SYSPLL4_D4			16
+#define CLK_TOP_UNIVPLL				17
+#define CLK_TOP_UNIVPLL_D2			18
+#define CLK_TOP_UNIVPLL_D3			19
+#define CLK_TOP_UNIVPLL_D5			20
+#define CLK_TOP_UNIVPLL_D7			21
+#define CLK_TOP_UNIVPLL_D26			22
+#define CLK_TOP_UNIVPLL_D52			23
+#define CLK_TOP_UNIVPLL_D108			24
+#define CLK_TOP_USB_PHY48M			25
+#define CLK_TOP_UNIVPLL1_D2			26
+#define CLK_TOP_UNIVPLL1_D4			27
+#define CLK_TOP_UNIVPLL1_D8			28
+#define CLK_TOP_UNIVPLL2_D2			29
+#define CLK_TOP_UNIVPLL2_D4			30
+#define CLK_TOP_UNIVPLL2_D8			31
+#define CLK_TOP_UNIVPLL2_D16			32
+#define CLK_TOP_UNIVPLL2_D32			33
+#define CLK_TOP_UNIVPLL3_D2			34
+#define CLK_TOP_UNIVPLL3_D4			35
+#define CLK_TOP_UNIVPLL3_D8			36
+#define CLK_TOP_MSDCPLL				37
+#define CLK_TOP_MSDCPLL_D2			38
+#define CLK_TOP_MSDCPLL_D4			39
+#define CLK_TOP_MSDCPLL_D8			40
+#define CLK_TOP_MMPLL				41
+#define CLK_TOP_MMPLL_D2			42
+#define CLK_TOP_DMPLL				43
+#define CLK_TOP_DMPLL_D2			44
+#define CLK_TOP_DMPLL_D4			45
+#define CLK_TOP_DMPLL_X2			46
+#define CLK_TOP_TVDPLL				47
+#define CLK_TOP_TVDPLL_D2			48
+#define CLK_TOP_TVDPLL_D4			49
+#define CLK_TOP_TVD2PLL				50
+#define CLK_TOP_TVD2PLL_D2			51
+#define CLK_TOP_HADDS2PLL_98M			52
+#define CLK_TOP_HADDS2PLL_294M			53
+#define CLK_TOP_HADDS2_FB			54
+#define CLK_TOP_MIPIPLL_D2			55
+#define CLK_TOP_MIPIPLL_D4			56
+#define CLK_TOP_HDMIPLL				57
+#define CLK_TOP_HDMIPLL_D2			58
+#define CLK_TOP_HDMIPLL_D3			59
+#define CLK_TOP_HDMI_SCL_RX			60
+#define CLK_TOP_HDMI_0_PIX340M			61
+#define CLK_TOP_HDMI_0_DEEP340M			62
+#define CLK_TOP_HDMI_0_PLL340M			63
+#define CLK_TOP_AUD1PLL_98M			64
+#define CLK_TOP_AUD2PLL_90M			65
+#define CLK_TOP_AUDPLL				66
+#define CLK_TOP_AUDPLL_D4			67
+#define CLK_TOP_AUDPLL_D8			68
+#define CLK_TOP_AUDPLL_D16			69
+#define CLK_TOP_AUDPLL_D24			70
+#define CLK_TOP_ETHPLL_500M			71
+#define CLK_TOP_VDECPLL				72
+#define CLK_TOP_VENCPLL				73
+#define CLK_TOP_MIPIPLL				74
+#define CLK_TOP_ARMPLL_1P3G			75
+
+#define CLK_TOP_MM_SEL				76
+#define CLK_TOP_DDRPHYCFG_SEL			77
+#define CLK_TOP_MEM_SEL				78
+#define CLK_TOP_AXI_SEL				79
+#define CLK_TOP_CAMTG_SEL			80
+#define CLK_TOP_MFG_SEL				81
+#define CLK_TOP_VDEC_SEL			82
+#define CLK_TOP_PWM_SEL				83
+#define CLK_TOP_MSDC30_0_SEL			84
+#define CLK_TOP_USB20_SEL			85
+#define CLK_TOP_SPI0_SEL			86
+#define CLK_TOP_UART_SEL			87
+#define CLK_TOP_AUDINTBUS_SEL			88
+#define CLK_TOP_AUDIO_SEL			89
+#define CLK_TOP_MSDC30_2_SEL			90
+#define CLK_TOP_MSDC30_1_SEL			91
+#define CLK_TOP_DPI1_SEL			92
+#define CLK_TOP_DPI0_SEL			93
+#define CLK_TOP_SCP_SEL				94
+#define CLK_TOP_PMICSPI_SEL			95
+#define CLK_TOP_APLL_SEL			96
+#define CLK_TOP_HDMI_SEL			97
+#define CLK_TOP_TVE_SEL				98
+#define CLK_TOP_EMMC_HCLK_SEL			99
+#define CLK_TOP_NFI2X_SEL			100
+#define CLK_TOP_RTC_SEL				101
+#define CLK_TOP_OSD_SEL				102
+#define CLK_TOP_NR_SEL				103
+#define CLK_TOP_DI_SEL				104
+#define CLK_TOP_FLASH_SEL			105
+#define CLK_TOP_ASM_M_SEL			106
+#define CLK_TOP_ASM_I_SEL			107
+#define CLK_TOP_INTDIR_SEL			108
+#define CLK_TOP_HDMIRX_BIST_SEL			109
+#define CLK_TOP_ETHIF_SEL			110
+#define CLK_TOP_MS_CARD_SEL			111
+#define CLK_TOP_ASM_H_SEL			112
+#define CLK_TOP_SPI1_SEL			113
+#define CLK_TOP_CMSYS_SEL			114
+#define CLK_TOP_MSDC30_3_SEL			115
+#define CLK_TOP_HDMIRX26_24_SEL			116
+#define CLK_TOP_AUD2DVD_SEL			117
+#define CLK_TOP_8BDAC_SEL			118
+#define CLK_TOP_SPI2_SEL			119
+#define CLK_TOP_AUD_MUX1_SEL			120
+#define CLK_TOP_AUD_MUX2_SEL			121
+#define CLK_TOP_AUDPLL_MUX_SEL			122
+#define CLK_TOP_AUD_K1_SRC_SEL			123
+#define CLK_TOP_AUD_K2_SRC_SEL			124
+#define CLK_TOP_AUD_K3_SRC_SEL			125
+#define CLK_TOP_AUD_K4_SRC_SEL			126
+#define CLK_TOP_AUD_K5_SRC_SEL			127
+#define CLK_TOP_AUD_K6_SRC_SEL			128
+#define CLK_TOP_PADMCLK_SEL			129
+#define CLK_TOP_AUD_EXTCK1_DIV			130
+#define CLK_TOP_AUD_EXTCK2_DIV			131
+#define CLK_TOP_AUD_MUX1_DIV			132
+#define CLK_TOP_AUD_MUX2_DIV			133
+#define CLK_TOP_AUD_K1_SRC_DIV			134
+#define CLK_TOP_AUD_K2_SRC_DIV			135
+#define CLK_TOP_AUD_K3_SRC_DIV			136
+#define CLK_TOP_AUD_K4_SRC_DIV			137
+#define CLK_TOP_AUD_K5_SRC_DIV			138
+#define CLK_TOP_AUD_K6_SRC_DIV			139
+#define CLK_TOP_AUD_I2S1_MCLK			140
+#define CLK_TOP_AUD_I2S2_MCLK			141
+#define CLK_TOP_AUD_I2S3_MCLK			142
+#define CLK_TOP_AUD_I2S4_MCLK			143
+#define CLK_TOP_AUD_I2S5_MCLK			144
+#define CLK_TOP_AUD_I2S6_MCLK			145
+#define CLK_TOP_AUD_48K_TIMING			146
+#define CLK_TOP_AUD_44K_TIMING			147
+
+#define CLK_TOP_32K_INTERNAL			148
+#define CLK_TOP_32K_EXTERNAL			149
+#define CLK_TOP_CLK26M_D8			150
+#define CLK_TOP_8BDAC				151
+#define CLK_TOP_WBG_DIG_416M			152
+#define CLK_TOP_DPI				153
+#define CLK_TOP_HDMITX_CLKDIG_CTS		154
+#define CLK_TOP_DSI0_LNTC_DSI			155
+#define CLK_TOP_AUD_EXT1			156
+#define CLK_TOP_AUD_EXT2			157
+#define CLK_TOP_NFI1X_PAD			158
+#define CLK_TOP_NR				159
+
+/* APMIXEDSYS */
+
+#define CLK_APMIXED_ARMPLL			1
+#define CLK_APMIXED_MAINPLL			2
+#define CLK_APMIXED_UNIVPLL			3
+#define CLK_APMIXED_MMPLL			4
+#define CLK_APMIXED_MSDCPLL			5
+#define CLK_APMIXED_TVDPLL			6
+#define CLK_APMIXED_AUD1PLL			7
+#define CLK_APMIXED_TRGPLL			8
+#define CLK_APMIXED_ETHPLL			9
+#define CLK_APMIXED_VDECPLL			10
+#define CLK_APMIXED_HADDS2PLL			11
+#define CLK_APMIXED_AUD2PLL			12
+#define CLK_APMIXED_TVD2PLL			13
+#define CLK_APMIXED_NR				14
+
+/* DDRPHY */
+
+#define CLK_DDRPHY_VENCPLL			1
+#define CLK_DDRPHY_NR				2
+
+/* INFRACFG */
+
+#define CLK_INFRA_DBG				1
+#define CLK_INFRA_SMI				2
+#define CLK_INFRA_QAXI_CM4			3
+#define CLK_INFRA_AUD_SPLIN_B			4
+#define CLK_INFRA_AUDIO				5
+#define CLK_INFRA_EFUSE				6
+#define CLK_INFRA_L2C_SRAM			7
+#define CLK_INFRA_M4U				8
+#define CLK_INFRA_CONNMCU			9
+#define CLK_INFRA_TRNG				10
+#define CLK_INFRA_RAMBUFIF			11
+#define CLK_INFRA_CPUM				12
+#define CLK_INFRA_KP				13
+#define CLK_INFRA_CEC				14
+#define CLK_INFRA_IRRX				15
+#define CLK_INFRA_PMICSPI			16
+#define CLK_INFRA_PMICWRAP			17
+#define CLK_INFRA_DDCCI				18
+#define CLK_INFRA_CLK_13M			19
+#define CLK_INFRA_NR				20
+
+/* PERICFG */
+
+#define CLK_PERI_NFI				1
+#define CLK_PERI_THERM				2
+#define CLK_PERI_PWM1				3
+#define CLK_PERI_PWM2				4
+#define CLK_PERI_PWM3				5
+#define CLK_PERI_PWM4				6
+#define CLK_PERI_PWM5				7
+#define CLK_PERI_PWM6				8
+#define CLK_PERI_PWM7				9
+#define CLK_PERI_PWM				10
+#define CLK_PERI_USB0				11
+#define CLK_PERI_USB1				12
+#define CLK_PERI_AP_DMA				13
+#define CLK_PERI_MSDC30_0			14
+#define CLK_PERI_MSDC30_1			15
+#define CLK_PERI_MSDC30_2			16
+#define CLK_PERI_MSDC30_3			17
+#define CLK_PERI_MSDC50_3			18
+#define CLK_PERI_NLI				19
+#define CLK_PERI_UART0				20
+#define CLK_PERI_UART1				21
+#define CLK_PERI_UART2				22
+#define CLK_PERI_UART3				23
+#define CLK_PERI_BTIF				24
+#define CLK_PERI_I2C0				25
+#define CLK_PERI_I2C1				26
+#define CLK_PERI_I2C2				27
+#define CLK_PERI_I2C3				28
+#define CLK_PERI_AUXADC				29
+#define CLK_PERI_SPI0				30
+#define CLK_PERI_ETH				31
+#define CLK_PERI_USB0_MCU			32
+
+#define CLK_PERI_USB1_MCU			33
+#define CLK_PERI_USB_SLV			34
+#define CLK_PERI_GCPU				35
+#define CLK_PERI_NFI_ECC			36
+#define CLK_PERI_NFI_PAD			37
+#define CLK_PERI_FLASH				38
+#define CLK_PERI_HOST89_INT			39
+#define CLK_PERI_HOST89_SPI			40
+#define CLK_PERI_HOST89_DVD			41
+#define CLK_PERI_SPI1				42
+#define CLK_PERI_SPI2				43
+#define CLK_PERI_FCI				44
+
+#define CLK_PERI_UART0_SEL			45
+#define CLK_PERI_UART1_SEL			46
+#define CLK_PERI_UART2_SEL			47
+#define CLK_PERI_UART3_SEL			48
+#define CLK_PERI_NR				49
+
+/* AUDIO */
+
+#define CLK_AUD_AFE				1
+#define CLK_AUD_LRCK_DETECT			2
+#define CLK_AUD_I2S				3
+#define CLK_AUD_APLL_TUNER			4
+#define CLK_AUD_HDMI				5
+#define CLK_AUD_SPDF				6
+#define CLK_AUD_SPDF2				7
+#define CLK_AUD_APLL				8
+#define CLK_AUD_TML				9
+#define CLK_AUD_AHB_IDLE_EXT			10
+#define CLK_AUD_AHB_IDLE_INT			11
+
+#define CLK_AUD_I2SIN1				12
+#define CLK_AUD_I2SIN2				13
+#define CLK_AUD_I2SIN3				14
+#define CLK_AUD_I2SIN4				15
+#define CLK_AUD_I2SIN5				16
+#define CLK_AUD_I2SIN6				17
+#define CLK_AUD_I2SO1				18
+#define CLK_AUD_I2SO2				19
+#define CLK_AUD_I2SO3				20
+#define CLK_AUD_I2SO4				21
+#define CLK_AUD_I2SO5				22
+#define CLK_AUD_I2SO6				23
+#define CLK_AUD_ASRCI1				24
+#define CLK_AUD_ASRCI2				25
+#define CLK_AUD_ASRCO1				26
+#define CLK_AUD_ASRCO2				27
+#define CLK_AUD_ASRC11				28
+#define CLK_AUD_ASRC12				29
+#define CLK_AUD_HDMIRX				30
+#define CLK_AUD_INTDIR				31
+#define CLK_AUD_A1SYS				32
+#define CLK_AUD_A2SYS				33
+#define CLK_AUD_AFE_CONN			34
+#define CLK_AUD_AFE_PCMIF			35
+#define CLK_AUD_AFE_MRGIF			36
+
+#define CLK_AUD_MMIF_UL1			37
+#define CLK_AUD_MMIF_UL2			38
+#define CLK_AUD_MMIF_UL3			39
+#define CLK_AUD_MMIF_UL4			40
+#define CLK_AUD_MMIF_UL5			41
+#define CLK_AUD_MMIF_UL6			42
+#define CLK_AUD_MMIF_DL1			43
+#define CLK_AUD_MMIF_DL2			44
+#define CLK_AUD_MMIF_DL3			45
+#define CLK_AUD_MMIF_DL4			46
+#define CLK_AUD_MMIF_DL5			47
+#define CLK_AUD_MMIF_DL6			48
+#define CLK_AUD_MMIF_DLMCH			49
+#define CLK_AUD_MMIF_ARB1			50
+#define CLK_AUD_MMIF_AWB1			51
+#define CLK_AUD_MMIF_AWB2			52
+#define CLK_AUD_MMIF_DAI			53
+
+#define CLK_AUD_DMIC1				54
+#define CLK_AUD_DMIC2				55
+#define CLK_AUD_ASRCI3				56
+#define CLK_AUD_ASRCI4				57
+#define CLK_AUD_ASRCI5				58
+#define CLK_AUD_ASRCI6				59
+#define CLK_AUD_ASRCO3				60
+#define CLK_AUD_ASRCO4				61
+#define CLK_AUD_ASRCO5				62
+#define CLK_AUD_ASRCO6				63
+#define CLK_AUD_MEM_ASRC1			64
+#define CLK_AUD_MEM_ASRC2			65
+#define CLK_AUD_MEM_ASRC3			66
+#define CLK_AUD_MEM_ASRC4			67
+#define CLK_AUD_MEM_ASRC5			68
+#define CLK_AUD_DSD_ENC				69
+#define CLK_AUD_ASRC_BRG			70
+#define CLK_AUD_NR				71
+
+/* MMSYS */
+
+#define CLK_MM_SMI_COMMON			1
+#define CLK_MM_SMI_LARB0			2
+#define CLK_MM_CMDQ				3
+#define CLK_MM_MUTEX				4
+#define CLK_MM_DISP_COLOR			5
+#define CLK_MM_DISP_BLS				6
+#define CLK_MM_DISP_WDMA			7
+#define CLK_MM_DISP_RDMA			8
+#define CLK_MM_DISP_OVL				9
+#define CLK_MM_MDP_TDSHP			10
+#define CLK_MM_MDP_WROT				11
+#define CLK_MM_MDP_WDMA				12
+#define CLK_MM_MDP_RSZ1				13
+#define CLK_MM_MDP_RSZ0				14
+#define CLK_MM_MDP_RDMA				15
+#define CLK_MM_MDP_BLS_26M			16
+#define CLK_MM_CAM_MDP				17
+#define CLK_MM_FAKE_ENG				18
+#define CLK_MM_MUTEX_32K			19
+#define CLK_MM_DISP_RDMA1			20
+#define CLK_MM_DISP_UFOE			21
+
+#define CLK_MM_DSI_ENGINE			22
+#define CLK_MM_DSI_DIG				23
+#define CLK_MM_DPI_DIGL				24
+#define CLK_MM_DPI_ENGINE			25
+#define CLK_MM_DPI1_DIGL			26
+#define CLK_MM_DPI1_ENGINE			27
+#define CLK_MM_TVE_OUTPUT			28
+#define CLK_MM_TVE_INPUT			29
+#define CLK_MM_HDMI_PIXEL			30
+#define CLK_MM_HDMI_PLL				31
+#define CLK_MM_HDMI_AUDIO			32
+#define CLK_MM_HDMI_SPDIF			33
+#define CLK_MM_TVE_FMM				34
+#define CLK_MM_NR				35
+
+/* IMGSYS */
+
+#define CLK_IMG_SMI_COMM			1
+#define CLK_IMG_RESZ				2
+#define CLK_IMG_JPGDEC_SMI			3
+#define CLK_IMG_JPGDEC				4
+#define CLK_IMG_VENC_LT				5
+#define CLK_IMG_VENC				6
+#define CLK_IMG_NR				7
+
+/* VDEC */
+
+#define CLK_VDEC_CKGEN				1
+#define CLK_VDEC_LARB				2
+#define CLK_VDEC_NR				3
+
+/* HIFSYS */
+
+#define CLK_HIFSYS_USB0PHY			1
+#define CLK_HIFSYS_USB1PHY			2
+#define CLK_HIFSYS_PCIE0			3
+#define CLK_HIFSYS_PCIE1			4
+#define CLK_HIFSYS_PCIE2			5
+#define CLK_HIFSYS_NR				6
+
+/* ETHSYS */
+#define CLK_ETHSYS_HSDMA			1
+#define CLK_ETHSYS_ESW				2
+#define CLK_ETHSYS_GP2				3
+#define CLK_ETHSYS_GP1				4
+#define CLK_ETHSYS_PCM				5
+#define CLK_ETHSYS_GDMA				6
+#define CLK_ETHSYS_I2S				7
+#define CLK_ETHSYS_CRYPTO			8
+#define CLK_ETHSYS_NR				9
+
+/* BDP */
+
+#define CLK_BDP_BRG_BA				1
+#define CLK_BDP_BRG_DRAM			2
+#define CLK_BDP_LARB_DRAM			3
+#define CLK_BDP_WR_VDI_PXL			4
+#define CLK_BDP_WR_VDI_DRAM			5
+#define CLK_BDP_WR_B				6
+#define CLK_BDP_DGI_IN				7
+#define CLK_BDP_DGI_OUT				8
+#define CLK_BDP_FMT_MAST_27			9
+#define CLK_BDP_FMT_B				10
+#define CLK_BDP_OSD_B				11
+#define CLK_BDP_OSD_DRAM			12
+#define CLK_BDP_OSD_AGENT			13
+#define CLK_BDP_OSD_PXL				14
+#define CLK_BDP_RLE_B				15
+#define CLK_BDP_RLE_AGENT			16
+#define CLK_BDP_RLE_DRAM			17
+#define CLK_BDP_F27M				18
+#define CLK_BDP_F27M_VDOUT			19
+#define CLK_BDP_F27_74_74			20
+#define CLK_BDP_F2FS				21
+#define CLK_BDP_F2FS74_148			22
+#define CLK_BDP_FB				23
+#define CLK_BDP_VDO_DRAM			24
+#define CLK_BDP_VDO_2FS				25
+#define CLK_BDP_VDO_B				26
+#define CLK_BDP_WR_DI_PXL			27
+#define CLK_BDP_WR_DI_DRAM			28
+#define CLK_BDP_WR_DI_B				29
+#define CLK_BDP_NR_PXL				30
+#define CLK_BDP_NR_DRAM				31
+#define CLK_BDP_NR_B				32
+
+#define CLK_BDP_RX_F				33
+#define CLK_BDP_RX_X				34
+#define CLK_BDP_RXPDT				35
+#define CLK_BDP_RX_CSCL_N			36
+#define CLK_BDP_RX_CSCL				37
+#define CLK_BDP_RX_DDCSCL_N			38
+#define CLK_BDP_RX_DDCSCL			39
+#define CLK_BDP_RX_VCO				40
+#define CLK_BDP_RX_DP				41
+#define CLK_BDP_RX_P				42
+#define CLK_BDP_RX_M				43
+#define CLK_BDP_RX_PLL				44
+#define CLK_BDP_BRG_RT_B			45
+#define CLK_BDP_BRG_RT_DRAM			46
+#define CLK_BDP_LARBRT_DRAM			47
+#define CLK_BDP_TMDS_SYN			48
+#define CLK_BDP_HDMI_MON			49
+#define CLK_BDP_NR				50
+
+#endif /* _DT_BINDINGS_CLK_MT2701_H */
-- 
1.9.1



From erin.lo at mediatek.com  Mon May 16 22:05:07 2016
From: erin.lo at mediatek.com (Erin Lo)
Date: Tue, 17 May 2016 13:05:07 +0800
Subject: [PATCH v8 06/10] clk: mediatek: Add MT2701 clock support
In-Reply-To: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
References: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
Message-ID: <1463461511-25019-7-git-send-email-erin.lo@mediatek.com>

From: Shunli Wang <shunli.wang at mediatek.com>

Add MT2701 clock support, include topckgen, apmixedsys,
infracfg, pericfg and subsystem clocks.

Signed-off-by: Shunli Wang <shunli.wang at mediatek.com>
Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
Tested-by: John Crispin <blogic at openwrt.org>
---
 drivers/clk/mediatek/Kconfig           |   50 ++
 drivers/clk/mediatek/Makefile          |    7 +
 drivers/clk/mediatek/clk-gate.c        |   52 ++
 drivers/clk/mediatek/clk-gate.h        |    2 +
 drivers/clk/mediatek/clk-mt2701-bdp.c  |  140 +++++
 drivers/clk/mediatek/clk-mt2701-eth.c  |   82 +++
 drivers/clk/mediatek/clk-mt2701-hif.c  |   79 +++
 drivers/clk/mediatek/clk-mt2701-img.c  |   82 +++
 drivers/clk/mediatek/clk-mt2701-mm.c   |  125 ++++
 drivers/clk/mediatek/clk-mt2701-vdec.c |   93 +++
 drivers/clk/mediatek/clk-mt2701.c      | 1033 ++++++++++++++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.c         |   40 ++
 drivers/clk/mediatek/clk-mtk.h         |   52 +-
 drivers/clk/mediatek/clk-pll.c         |    1 +
 14 files changed, 1833 insertions(+), 5 deletions(-)
 create mode 100644 drivers/clk/mediatek/clk-mt2701-bdp.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-eth.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-hif.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-img.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-mm.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701-vdec.c
 create mode 100644 drivers/clk/mediatek/clk-mt2701.c

diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index dc224e6..5aa6204 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -6,6 +6,56 @@ config COMMON_CLK_MEDIATEK
 	---help---
 	  Mediatek SoCs' clock support.
 
+config COMMON_CLK_MT2701
+	bool "Clock driver for Mediatek MT2701"
+	depends on COMMON_CLK
+	select COMMON_CLK_MEDIATEK
+	default ARCH_MEDIATEK
+	---help---
+	  This driver supports Mediatek MT2701 basic clocks.
+
+config COMMON_CLK_MT2701_MMSYS
+	bool "Clock driver for Mediatek MT2701 mmsys"
+	depends on COMMON_CLK
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 mmsys clocks.
+
+config COMMON_CLK_MT2701_IMGSYS
+	bool "Clock driver for Mediatek MT2701 imgsys"
+	depends on COMMON_CLK
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 imgsys clocks.
+
+config COMMON_CLK_MT2701_VDECSYS
+	bool "Clock driver for Mediatek MT2701 vdecsys"
+	depends on COMMON_CLK
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 vdecsys clocks.
+
+config COMMON_CLK_MT2701_HIFSYS
+	bool "Clock driver for Mediatek MT2701 hifsys"
+	depends on COMMON_CLK
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 hifsys clocks.
+
+config COMMON_CLK_MT2701_ETHSYS
+	bool "Clock driver for Mediatek MT2701 ethsys"
+	depends on COMMON_CLK
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 ethsys clocks.
+
+config COMMON_CLK_MT2701_BDPSYS
+	bool "Clock driver for Mediatek MT2701 bdpsys"
+	depends on COMMON_CLK
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 bdpsys clocks.
+
 config COMMON_CLK_MT8135
 	bool "Clock driver for Mediatek MT8135"
 	depends on COMMON_CLK
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 32e7222..19ae7ef 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,4 +1,11 @@
 obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o
+obj-$(CONFIG_COMMON_CLK_MT2701_BDPSYS) += clk-mt2701-bdp.o
+obj-$(CONFIG_COMMON_CLK_MT2701_ETHSYS) += clk-mt2701-eth.o
+obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
+obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o
+obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o
+obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o
 obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
 obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
index d8787bf..934bf0e 100644
--- a/drivers/clk/mediatek/clk-gate.c
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -61,6 +61,22 @@ static void mtk_cg_clr_bit(struct clk_hw *hw)
 	regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
 }
 
+static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+	u32 cgbit = BIT(cg->bit);
+
+	regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, cgbit);
+}
+
+static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+	u32 cgbit = BIT(cg->bit);
+
+	regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, 0);
+}
+
 static int mtk_cg_enable(struct clk_hw *hw)
 {
 	mtk_cg_clr_bit(hw);
@@ -85,6 +101,30 @@ static void mtk_cg_disable_inv(struct clk_hw *hw)
 	mtk_cg_clr_bit(hw);
 }
 
+static int mtk_cg_enable_no_setclr(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit_no_setclr(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable_no_setclr(struct clk_hw *hw)
+{
+	mtk_cg_set_bit_no_setclr(hw);
+}
+
+static int mtk_cg_enable_inv_no_setclr(struct clk_hw *hw)
+{
+	mtk_cg_set_bit_no_setclr(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable_inv_no_setclr(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit_no_setclr(hw);
+}
+
 const struct clk_ops mtk_clk_gate_ops_setclr = {
 	.is_enabled	= mtk_cg_bit_is_cleared,
 	.enable		= mtk_cg_enable,
@@ -97,6 +137,18 @@ const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
 	.disable	= mtk_cg_disable_inv,
 };
 
+const struct clk_ops mtk_clk_gate_ops_no_setclr = {
+	.is_enabled	= mtk_cg_bit_is_cleared,
+	.enable		= mtk_cg_enable_no_setclr,
+	.disable	= mtk_cg_disable_no_setclr,
+};
+
+const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = {
+	.is_enabled	= mtk_cg_bit_is_set,
+	.enable		= mtk_cg_enable_inv_no_setclr,
+	.disable	= mtk_cg_disable_inv_no_setclr,
+};
+
 struct clk *mtk_clk_register_gate(
 		const char *name,
 		const char *parent_name,
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
index b182160..72ef89b 100644
--- a/drivers/clk/mediatek/clk-gate.h
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -36,6 +36,8 @@ static inline struct mtk_clk_gate *to_mtk_clk_gate(struct clk_hw *hw)
 
 extern const struct clk_ops mtk_clk_gate_ops_setclr;
 extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
+extern const struct clk_ops mtk_clk_gate_ops_no_setclr;
+extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv;
 
 struct clk *mtk_clk_register_gate(
 		const char *name,
diff --git a/drivers/clk/mediatek/clk-mt2701-bdp.c b/drivers/clk/mediatek/clk-mt2701-bdp.c
new file mode 100644
index 0000000..81f628c
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-bdp.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs bdp0_cg_regs = {
+	.set_ofs = 0x0104,
+	.clr_ofs = 0x0108,
+	.sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs bdp1_cg_regs = {
+	.set_ofs = 0x0114,
+	.clr_ofs = 0x0118,
+	.sta_ofs = 0x0110,
+};
+
+#define GATE_BDP0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &bdp0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_BDP1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &bdp1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+static const struct mtk_gate bdp_clks[] = {
+	GATE_BDP0(CLK_BDP_BRG_BA, "brg_baclk", "mm_sel", 0),
+	GATE_BDP0(CLK_BDP_BRG_DRAM, "brg_dram", "mm_sel", 1),
+	GATE_BDP0(CLK_BDP_LARB_DRAM, "larb_dram", "mm_sel", 2),
+	GATE_BDP0(CLK_BDP_WR_VDI_PXL, "wr_vdi_pxl", "hdmi_0_deep340m", 3),
+	GATE_BDP0(CLK_BDP_WR_VDI_DRAM, "wr_vdi_dram", "mm_sel", 4),
+	GATE_BDP0(CLK_BDP_WR_B, "wr_bclk", "mm_sel", 5),
+	GATE_BDP0(CLK_BDP_DGI_IN, "dgi_in", "dpi1_sel", 6),
+	GATE_BDP0(CLK_BDP_DGI_OUT, "dgi_out", "dpi1_sel", 7),
+	GATE_BDP0(CLK_BDP_FMT_MAST_27, "fmt_mast_27", "dpi1_sel", 8),
+	GATE_BDP0(CLK_BDP_FMT_B, "fmt_bclk", "mm_sel", 9),
+	GATE_BDP0(CLK_BDP_OSD_B, "osd_bclk", "mm_sel", 10),
+	GATE_BDP0(CLK_BDP_OSD_DRAM, "osd_dram", "mm_sel", 11),
+	GATE_BDP0(CLK_BDP_OSD_AGENT, "osd_agent", "osd_sel", 12),
+	GATE_BDP0(CLK_BDP_OSD_PXL, "osd_pxl", "dpi1_sel", 13),
+	GATE_BDP0(CLK_BDP_RLE_B, "rle_bclk", "mm_sel", 14),
+	GATE_BDP0(CLK_BDP_RLE_AGENT, "rle_agent", "mm_sel", 15),
+	GATE_BDP0(CLK_BDP_RLE_DRAM, "rle_dram", "mm_sel", 16),
+	GATE_BDP0(CLK_BDP_F27M, "f27m", "di_sel", 17),
+	GATE_BDP0(CLK_BDP_F27M_VDOUT, "f27m_vdout", "di_sel", 18),
+	GATE_BDP0(CLK_BDP_F27_74_74, "f27_74_74", "di_sel", 19),
+	GATE_BDP0(CLK_BDP_F2FS, "f2fs", "di_sel", 20),
+	GATE_BDP0(CLK_BDP_F2FS74_148, "f2fs74_148", "di_sel", 21),
+	GATE_BDP0(CLK_BDP_FB, "fbclk", "mm_sel", 22),
+	GATE_BDP0(CLK_BDP_VDO_DRAM, "vdo_dram", "mm_sel", 23),
+	GATE_BDP0(CLK_BDP_VDO_2FS, "vdo_2fs", "di_sel", 24),
+	GATE_BDP0(CLK_BDP_VDO_B, "vdo_bclk", "mm_sel", 25),
+	GATE_BDP0(CLK_BDP_WR_DI_PXL, "wr_di_pxl", "di_sel", 26),
+	GATE_BDP0(CLK_BDP_WR_DI_DRAM, "wr_di_dram", "mm_sel", 27),
+	GATE_BDP0(CLK_BDP_WR_DI_B, "wr_di_bclk", "mm_sel", 28),
+	GATE_BDP0(CLK_BDP_NR_PXL, "nr_pxl", "nr_sel", 29),
+	GATE_BDP0(CLK_BDP_NR_DRAM, "nr_dram", "mm_sel", 30),
+	GATE_BDP0(CLK_BDP_NR_B, "nr_bclk", "mm_sel", 31),
+	GATE_BDP1(CLK_BDP_RX_F, "rx_fclk", "hadds2_fbclk", 0),
+	GATE_BDP1(CLK_BDP_RX_X, "rx_xclk", "clk26m", 1),
+	GATE_BDP1(CLK_BDP_RXPDT, "rxpdtclk", "hdmi_0_pix340m", 2),
+	GATE_BDP1(CLK_BDP_RX_CSCL_N, "rx_cscl_n", "clk26m", 3),
+	GATE_BDP1(CLK_BDP_RX_CSCL, "rx_cscl", "clk26m", 4),
+	GATE_BDP1(CLK_BDP_RX_DDCSCL_N, "rx_ddcscl_n", "hdmi_scl_rx", 5),
+	GATE_BDP1(CLK_BDP_RX_DDCSCL, "rx_ddcscl", "hdmi_scl_rx", 6),
+	GATE_BDP1(CLK_BDP_RX_VCO, "rx_vcoclk", "hadds2pll_294m", 7),
+	GATE_BDP1(CLK_BDP_RX_DP, "rx_dpclk", "hdmi_0_pll340m", 8),
+	GATE_BDP1(CLK_BDP_RX_P, "rx_pclk", "hdmi_0_pll340m", 9),
+	GATE_BDP1(CLK_BDP_RX_M, "rx_mclk", "hadds2pll_294m", 10),
+	GATE_BDP1(CLK_BDP_RX_PLL, "rx_pllclk", "hdmi_0_pix340m", 11),
+	GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12),
+	GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13),
+	GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14),
+	GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15),
+	GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_pll340m", 16),
+};
+
+static void mtk_bdpsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_BDP_NR);
+
+	mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+
+static const struct of_device_id of_match_clk_mt2701_bdp[] = {
+	{ .compatible = "mediatek,mt2701-bdpsys", },
+	{}
+};
+
+static int clk_mt2701_bdp_probe(struct platform_device *pdev)
+{
+	mtk_bdpsys_init(pdev->dev.of_node);
+	return 0;
+}
+
+static struct platform_driver clk_mt2701_bdp_drv = {
+	.probe = clk_mt2701_bdp_probe,
+	.driver = {
+		.name = "clk-mt2701-bdp",
+		.of_match_table = of_match_clk_mt2701_bdp,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_bdp_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-eth.c b/drivers/clk/mediatek/clk-mt2701-eth.c
new file mode 100644
index 0000000..22163eb
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-eth.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs eth_cg_regs = {
+	.sta_ofs = 0x0030,
+};
+
+#define GATE_ETH(_id, _name, _parent, _shift) {		\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &eth_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,	\
+	}
+
+static const struct mtk_gate eth_clks[] = {
+	GATE_ETH(CLK_ETHSYS_HSDMA, "hsdma_clk", "ethif_sel", 5),
+	GATE_ETH(CLK_ETHSYS_ESW, "esw_clk", "ethpll_500m_ck", 6),
+	GATE_ETH(CLK_ETHSYS_GP2, "gp2_clk", "trgpll", 7),
+	GATE_ETH(CLK_ETHSYS_GP1, "gp1_clk", "ethpll_500m_ck", 8),
+	GATE_ETH(CLK_ETHSYS_PCM, "pcm_clk", "ethif_sel", 11),
+	GATE_ETH(CLK_ETHSYS_GDMA, "gdma_clk", "ethif_sel", 14),
+	GATE_ETH(CLK_ETHSYS_I2S, "i2s_clk", "ethif_sel", 17),
+	GATE_ETH(CLK_ETHSYS_CRYPTO, "crypto_clk", "ethif_sel", 29),
+};
+
+static void mtk_ethsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR);
+
+	mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+
+static const struct of_device_id of_match_clk_mt2701_eth[] = {
+	{ .compatible = "mediatek,mt2701-ethsys", },
+	{}
+};
+
+static int clk_mt2701_eth_probe(struct platform_device *pdev)
+{
+	mtk_ethsys_init(pdev->dev.of_node);
+	return 0;
+}
+
+static struct platform_driver clk_mt2701_eth_drv = {
+	.probe = clk_mt2701_eth_probe,
+	.driver = {
+		.name = "clk-mt2701-eth",
+		.of_match_table = of_match_clk_mt2701_eth,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_eth_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-hif.c b/drivers/clk/mediatek/clk-mt2701-hif.c
new file mode 100644
index 0000000..3f6cea2
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-hif.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs hif_cg_regs = {
+	.sta_ofs = 0x0008,
+};
+
+#define GATE_HIF(_id, _name, _parent, _shift) {		\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &hif_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,	\
+	}
+
+static const struct mtk_gate hif_clks[] = {
+	GATE_HIF(CLK_HIFSYS_USB0PHY, "usb0_phy_clk", "ethpll_500m_ck", 21),
+	GATE_HIF(CLK_HIFSYS_USB1PHY, "usb1_phy_clk", "ethpll_500m_ck", 22),
+	GATE_HIF(CLK_HIFSYS_PCIE0, "pcie0_clk", "ethpll_500m_ck", 24),
+	GATE_HIF(CLK_HIFSYS_PCIE1, "pcie1_clk", "ethpll_500m_ck", 25),
+	GATE_HIF(CLK_HIFSYS_PCIE2, "pcie2_clk", "ethpll_500m_ck", 26),
+};
+
+static void mtk_hifsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR);
+
+	mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+
+static const struct of_device_id of_match_clk_mt2701_hif[] = {
+	{ .compatible = "mediatek,mt2701-hifsys", },
+	{}
+};
+
+static int clk_mt2701_hif_probe(struct platform_device *pdev)
+{
+	mtk_hifsys_init(pdev->dev.of_node);
+	return 0;
+}
+
+static struct platform_driver clk_mt2701_hif_drv = {
+	.probe = clk_mt2701_hif_probe,
+	.driver = {
+		.name = "clk-mt2701-hif",
+		.of_match_table = of_match_clk_mt2701_hif,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_hif_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-img.c b/drivers/clk/mediatek/clk-mt2701-img.c
new file mode 100644
index 0000000..e324079
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-img.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs img_cg_regs = {
+	.set_ofs = 0x0004,
+	.clr_ofs = 0x0008,
+	.sta_ofs = 0x0000,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift) {		\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &img_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate img_clks[] = {
+	GATE_IMG(CLK_IMG_SMI_COMM, "img_smi_comm", "mm_sel", 0),
+	GATE_IMG(CLK_IMG_RESZ, "img_resz", "mm_sel", 1),
+	GATE_IMG(CLK_IMG_JPGDEC_SMI, "img_jpgdec_smi", "mm_sel", 5),
+	GATE_IMG(CLK_IMG_JPGDEC, "img_jpgdec", "mm_sel", 6),
+	GATE_IMG(CLK_IMG_VENC_LT, "img_venc_lt", "mm_sel", 8),
+	GATE_IMG(CLK_IMG_VENC, "img_venc", "mm_sel", 9),
+};
+
+static void mtk_imgsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
+
+	mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+
+static const struct of_device_id of_match_clk_mt2701_img[] = {
+	{ .compatible = "mediatek,mt2701-imgsys", },
+	{}
+};
+
+static int clk_mt2701_img_probe(struct platform_device *pdev)
+{
+	mtk_imgsys_init(pdev->dev.of_node);
+	return 0;
+}
+
+static struct platform_driver clk_mt2701_img_drv = {
+	.probe = clk_mt2701_img_probe,
+	.driver = {
+		.name = "clk-mt2701-img",
+		.of_match_table = of_match_clk_mt2701_img,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_img_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-mm.c b/drivers/clk/mediatek/clk-mt2701-mm.c
new file mode 100644
index 0000000..b1711f8
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-mm.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs disp0_cg_regs = {
+	.set_ofs = 0x0104,
+	.clr_ofs = 0x0108,
+	.sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs disp1_cg_regs = {
+	.set_ofs = 0x0114,
+	.clr_ofs = 0x0118,
+	.sta_ofs = 0x0110,
+};
+
+#define GATE_DISP0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &disp0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_DISP1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &disp1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate mm_clks[] = {
+	GATE_DISP0(CLK_MM_SMI_COMMON, "mm_smi_comm", "mm_sel", 0),
+	GATE_DISP0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
+	GATE_DISP0(CLK_MM_CMDQ, "mm_cmdq", "mm_sel", 2),
+	GATE_DISP0(CLK_MM_MUTEX, "mm_mutex", "mm_sel", 3),
+	GATE_DISP0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 4),
+	GATE_DISP0(CLK_MM_DISP_BLS, "mm_disp_bls", "mm_sel", 5),
+	GATE_DISP0(CLK_MM_DISP_WDMA, "mm_disp_wdma", "mm_sel", 6),
+	GATE_DISP0(CLK_MM_DISP_RDMA, "mm_disp_rdma", "mm_sel", 7),
+	GATE_DISP0(CLK_MM_DISP_OVL, "mm_disp_ovl", "mm_sel", 8),
+	GATE_DISP0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9),
+	GATE_DISP0(CLK_MM_MDP_WROT, "mm_mdp_wrot", "mm_sel", 10),
+	GATE_DISP0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
+	GATE_DISP0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 12),
+	GATE_DISP0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 13),
+	GATE_DISP0(CLK_MM_MDP_RDMA, "mm_mdp_rdma", "mm_sel", 14),
+	GATE_DISP0(CLK_MM_MDP_BLS_26M, "mm_mdp_bls_26m", "pwm_sel", 15),
+	GATE_DISP0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 16),
+	GATE_DISP0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 17),
+	GATE_DISP0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 18),
+	GATE_DISP0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
+	GATE_DISP0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 20),
+	GATE_DISP1(CLK_MM_DSI_ENGINE, "mm_dsi_eng", "mm_sel", 0),
+	GATE_DISP1(CLK_MM_DSI_DIG, "mm_dsi_dig", "dsi0_lntc_dsi", 1),
+	GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2),
+	GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3),
+	GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4),
+	GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5),
+	GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6),
+	GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7),
+	GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8),
+	GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9),
+	GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10),
+	GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11),
+	GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14),
+};
+
+static void mtk_mmsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_MM_NR);
+
+	mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+
+static const struct of_device_id of_match_clk_mt2701_mm[] = {
+	{ .compatible = "mediatek,mt2701-mmsys", },
+	{}
+};
+
+static int clk_mt2701_mm_probe(struct platform_device *pdev)
+{
+	mtk_mmsys_init(pdev->dev.of_node);
+	return 0;
+}
+
+static struct platform_driver clk_mt2701_mm_drv = {
+	.probe = clk_mt2701_mm_probe,
+	.driver = {
+		.name = "clk-mt2701-mm",
+		.of_match_table = of_match_clk_mt2701_mm,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_mm_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701-vdec.c b/drivers/clk/mediatek/clk-mt2701-vdec.c
new file mode 100644
index 0000000..613bb33
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701-vdec.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs vdec0_cg_regs = {
+	.set_ofs = 0x0000,
+	.clr_ofs = 0x0004,
+	.sta_ofs = 0x0000,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x000c,
+	.sta_ofs = 0x0008,
+};
+
+#define GATE_VDEC0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vdec0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VDEC1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vdec1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+static const struct mtk_gate vdec_clks[] = {
+	GATE_VDEC0(CLK_VDEC_CKGEN, "vdec_cken", "vdec_sel", 0),
+	GATE_VDEC1(CLK_VDEC_LARB, "vdec_larb_cken", "mm_sel", 0),
+};
+
+static void mtk_vdecsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
+
+	mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+
+static const struct of_device_id of_match_clk_mt2701_vdec[] = {
+	{ .compatible = "mediatek,mt2701-vdecsys", },
+	{}
+};
+
+static int clk_mt2701_vdec_probe(struct platform_device *pdev)
+{
+	mtk_vdecsys_init(pdev->dev.of_node);
+	return 0;
+}
+
+static struct platform_driver clk_mt2701_vdec_drv = {
+	.probe = clk_mt2701_vdec_probe,
+	.driver = {
+		.name = "clk-mt2701-vdec",
+		.of_match_table = of_match_clk_mt2701_vdec,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_vdec_drv);
diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
new file mode 100644
index 0000000..08a2954
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt2701.c
@@ -0,0 +1,1033 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+/*
+ * For some clocks, we don't care what their actual rates are. And these
+ * clocks may change their rate on different products or different scenarios.
+ * So we model these clocks' rate as 0, to denote it's not an actual rate.
+ */
+#define DUMMY_RATE		0
+
+static DEFINE_SPINLOCK(lock);
+
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+	FIXED_CLK(CLK_TOP_DPI, "dpi_ck", "clk26m",
+		108 * MHZ),
+	FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", "clk26m",
+		400 * MHZ),
+	FIXED_CLK(CLK_TOP_VENCPLL, "vencpll_ck", "clk26m",
+		295750000),
+	FIXED_CLK(CLK_TOP_HDMI_0_PIX340M, "hdmi_0_pix340m", "clk26m",
+		340 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_0_DEEP340M, "hdmi_0_deep340m", "clk26m",
+		340 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_0_PLL340M, "hdmi_0_pll340m", "clk26m",
+		340 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_dig_cts", "clk26m",
+		300 * MHZ),
+	FIXED_CLK(CLK_TOP_HADDS2_FB, "hadds2_fbclk", "clk26m",
+		27 * MHZ),
+	FIXED_CLK(CLK_TOP_WBG_DIG_416M, "wbg_dig_ck_416m", "clk26m",
+		416 * MHZ),
+	FIXED_CLK(CLK_TOP_DSI0_LNTC_DSI, "dsi0_lntc_dsi", "clk26m",
+		143 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_SCL_RX, "hdmi_scl_rx", "clk26m",
+		27 * MHZ),
+	FIXED_CLK(CLK_TOP_AUD_EXT1, "aud_ext1", "clk26m",
+		DUMMY_RATE),
+	FIXED_CLK(CLK_TOP_AUD_EXT2, "aud_ext2", "clk26m",
+		DUMMY_RATE),
+	FIXED_CLK(CLK_TOP_NFI1X_PAD, "nfi1x_pad", "clk26m",
+		DUMMY_RATE),
+};
+
+static const struct mtk_fixed_factor top_fixed_divs[] = {
+	FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
+	FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
+	FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7),
+	FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8),
+	FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16),
+	FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8),
+	FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4),
+
+	FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+	FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+	FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+	FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26),
+	FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll", 1, 52),
+	FACTOR(CLK_TOP_UNIVPLL_D108, "univpll_d108", "univpll", 1, 108),
+	FACTOR(CLK_TOP_USB_PHY48M, "usb_phy48m_ck", "univpll", 1, 26),
+	FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8),
+	FACTOR(CLK_TOP_8BDAC, "8bdac_ck", "univpll_d2", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll_d3", 1, 16),
+	FACTOR(CLK_TOP_UNIVPLL2_D32, "univpll2_d32", "univpll_d3", 1, 32),
+	FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8),
+
+	FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
+	FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+	FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+	FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, 8),
+
+	FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
+	FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+
+	FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "dmpll_ck", 1, 2),
+	FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "dmpll_ck", 1, 4),
+	FACTOR(CLK_TOP_DMPLL_X2, "dmpll_x2", "dmpll_ck", 1, 1),
+
+	FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, 1),
+	FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2),
+	FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
+
+	FACTOR(CLK_TOP_VDECPLL, "vdecpll_ck", "vdecpll", 1, 1),
+	FACTOR(CLK_TOP_TVD2PLL, "tvd2pll_ck", "tvd2pll", 1, 1),
+	FACTOR(CLK_TOP_TVD2PLL_D2, "tvd2pll_d2", "tvd2pll", 1, 2),
+
+	FACTOR(CLK_TOP_MIPIPLL, "mipipll", "dpi_ck", 1, 1),
+	FACTOR(CLK_TOP_MIPIPLL_D2, "mipipll_d2", "dpi_ck", 1, 2),
+	FACTOR(CLK_TOP_MIPIPLL_D4, "mipipll_d4", "dpi_ck", 1, 4),
+
+	FACTOR(CLK_TOP_HDMIPLL, "hdmipll_ck", "hdmitx_dig_cts", 1, 1),
+	FACTOR(CLK_TOP_HDMIPLL_D2, "hdmipll_d2", "hdmitx_dig_cts", 1, 2),
+	FACTOR(CLK_TOP_HDMIPLL_D3, "hdmipll_d3", "hdmitx_dig_cts", 1, 3),
+
+	FACTOR(CLK_TOP_ARMPLL_1P3G, "armpll_1p3g_ck", "armpll", 1, 1),
+
+	FACTOR(CLK_TOP_AUDPLL, "audpll", "audpll_sel", 1, 1),
+	FACTOR(CLK_TOP_AUDPLL_D4, "audpll_d4", "audpll_sel", 1, 4),
+	FACTOR(CLK_TOP_AUDPLL_D8, "audpll_d8", "audpll_sel", 1, 8),
+	FACTOR(CLK_TOP_AUDPLL_D16, "audpll_d16", "audpll_sel", 1, 16),
+	FACTOR(CLK_TOP_AUDPLL_D24, "audpll_d24", "audpll_sel", 1, 24),
+
+	FACTOR(CLK_TOP_AUD1PLL_98M, "aud1pll_98m_ck", "aud1pll", 1, 3),
+	FACTOR(CLK_TOP_AUD2PLL_90M, "aud2pll_90m_ck", "aud2pll", 1, 3),
+	FACTOR(CLK_TOP_HADDS2PLL_98M, "hadds2pll_98m", "hadds2pll", 1, 3),
+	FACTOR(CLK_TOP_HADDS2PLL_294M, "hadds2pll_294m", "hadds2pll", 1, 1),
+	FACTOR(CLK_TOP_ETHPLL_500M, "ethpll_500m_ck", "ethpll", 1, 1),
+	FACTOR(CLK_TOP_CLK26M_D8, "clk26m_d8", "clk26m", 1, 8),
+	FACTOR(CLK_TOP_32K_INTERNAL, "32k_internal", "clk26m", 1, 793),
+	FACTOR(CLK_TOP_32K_EXTERNAL, "32k_external", "rtc32k", 1, 1),
+};
+
+static const char * const axi_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"mmpll_d2",
+	"dmpll_d2"
+};
+
+static const char * const mem_parents[] = {
+	"clk26m",
+	"dmpll_ck"
+};
+
+static const char * const ddrphycfg_parents[] = {
+	"clk26m",
+	"syspll1_d8"
+};
+
+static const char * const mm_parents[] = {
+	"clk26m",
+	"vencpll_ck",
+	"syspll1_d2",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_ck"
+};
+
+static const char * const pwm_parents[] = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll3_d2",
+	"univpll1_d4",
+};
+
+static const char * const vdec_parents[] = {
+	"clk26m",
+	"vdecpll_ck",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"vencpll_ck",
+	"msdcpll_d2",
+	"mmpll_d2"
+};
+
+static const char * const mfg_parents[] = {
+	"clk26m",
+	"mmpll_ck",
+	"dmpll_x2_ck",
+	"msdcpll_ck",
+	"clk26m",
+	"syspll_d3",
+	"univpll_d3",
+	"univpll1_d2"
+};
+
+static const char * const camtg_parents[] = {
+	"clk26m",
+	"univpll_d26",
+	"univpll2_d2",
+	"syspll3_d2",
+	"syspll3_d4",
+	"msdcpll_d2",
+	"mmpll_d2"
+};
+
+static const char * const uart_parents[] = {
+	"clk26m",
+	"univpll2_d8"
+};
+
+static const char * const spi_parents[] = {
+	"clk26m",
+	"syspll3_d2",
+	"syspll4_d2",
+	"univpll2_d4",
+	"univpll1_d8"
+};
+
+static const char * const usb20_parents[] = {
+	"clk26m",
+	"univpll1_d8",
+	"univpll3_d4"
+};
+
+static const char * const msdc30_parents[] = {
+	"clk26m",
+	"msdcpll_d2",
+	"syspll2_d2",
+	"syspll1_d4",
+	"univpll1_d4",
+	"univpll2_d4"
+};
+
+static const char * const audio_parents[] = {
+	"clk26m",
+	"syspll1_d16"
+};
+
+static const char * const aud_intbus_parents[] = {
+	"clk26m",
+	"syspll1_d4",
+	"syspll3_d2",
+	"syspll4_d2",
+	"univpll3_d2",
+	"univpll2_d4"
+};
+
+static const char * const pmicspi_parents[] = {
+	"clk26m",
+	"syspll1_d8",
+	"syspll2_d4",
+	"syspll4_d2",
+	"syspll3_d4",
+	"syspll2_d8",
+	"syspll1_d16",
+	"univpll3_d4",
+	"univpll_d26",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const scp_parents[] = {
+	"clk26m",
+	"syspll1_d8",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const dpi0_parents[] = {
+	"clk26m",
+	"mipipll",
+	"mipipll_d2",
+	"mipipll_d4",
+	"clk26m",
+	"tvdpll_ck",
+	"tvdpll_d2",
+	"tvdpll_d4"
+};
+
+static const char * const dpi1_parents[] = {
+	"clk26m",
+	"tvdpll_ck",
+	"tvdpll_d2",
+	"tvdpll_d4"
+};
+
+static const char * const tve_parents[] = {
+	"clk26m",
+	"mipipll",
+	"mipipll_d2",
+	"mipipll_d4",
+	"clk26m",
+	"tvdpll_ck",
+	"tvdpll_d2",
+	"tvdpll_d4"
+};
+
+static const char * const hdmi_parents[] = {
+	"clk26m",
+	"hdmipll_ck",
+	"hdmipll_d2",
+	"hdmipll_d3"
+};
+
+static const char * const apll_parents[] = {
+	"clk26m",
+	"audpll",
+	"audpll_d4",
+	"audpll_d8",
+	"audpll_d16",
+	"audpll_d24",
+	"clk26m",
+	"clk26m"
+};
+
+static const char * const rtc_parents[] = {
+	"32k_internal",
+	"32k_external",
+	"clk26m",
+	"univpll3_d8"
+};
+
+static const char * const nfi2x_parents[] = {
+	"clk26m",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll3_d2",
+	"syspll2_d4",
+	"univpll3_d4",
+	"syspll4_d4",
+	"clk26m"
+};
+
+static const char * const emmc_hclk_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll1_d4",
+	"syspll2_d2"
+};
+
+static const char * const flash_parents[] = {
+	"clk26m_d8",
+	"clk26m",
+	"syspll2_d8",
+	"syspll3_d4",
+	"univpll3_d4",
+	"syspll4_d2",
+	"syspll2_d4",
+	"univpll2_d4"
+};
+
+static const char * const di_parents[] = {
+	"clk26m",
+	"tvd2pll_ck",
+	"tvd2pll_d2",
+	"clk26m"
+};
+
+static const char * const nr_osd_parents[] = {
+	"clk26m",
+	"vencpll_ck",
+	"syspll1_d2",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_ck"
+};
+
+static const char * const hdmirx_bist_parents[] = {
+	"clk26m",
+	"syspll_d3",
+	"clk26m",
+	"syspll1_d16",
+	"syspll4_d2",
+	"syspll1_d4",
+	"vencpll_ck",
+	"clk26m"
+};
+
+static const char * const intdir_parents[] = {
+	"clk26m",
+	"mmpll_ck",
+	"syspll_d2",
+	"univpll_d2"
+};
+
+static const char * const asm_parents[] = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll2_d2",
+	"syspll_d5"
+};
+
+static const char * const ms_card_parents[] = {
+	"clk26m",
+	"univpll3_d8",
+	"syspll4_d4"
+};
+
+static const char * const ethif_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll1_d2",
+	"dmpll_ck",
+	"dmpll_d2"
+};
+
+static const char * const hdmirx_parents[] = {
+	"clk26m",
+	"univpll_d52"
+};
+
+static const char * const cmsys_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"univpll1_d2",
+	"univpll_d5",
+	"syspll_d5",
+	"syspll2_d2",
+	"syspll1_d4",
+	"syspll3_d2",
+	"syspll2_d4",
+	"syspll1_d8",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m"
+};
+
+static const char * const clk_8bdac_parents[] = {
+	"32k_internal",
+	"8bdac_ck",
+	"clk26m",
+	"clk26m"
+};
+
+static const char * const aud2dvd_parents[] = {
+	"a1sys_hp_ck",
+	"a2sys_hp_ck"
+};
+
+static const char * const padmclk_parents[] = {
+	"clk26m",
+	"univpll_d26",
+	"univpll_d52",
+	"univpll_d108",
+	"univpll2_d8",
+	"univpll2_d16",
+	"univpll2_d32"
+};
+
+static const char * const aud_mux_parents[] = {
+	"clk26m",
+	"aud1pll_98m_ck",
+	"aud2pll_90m_ck",
+	"hadds2pll_98m",
+	"audio_ext1_ck",
+	"audio_ext2_ck"
+};
+
+static const char * const aud_src_parents[] = {
+	"aud_mux1_sel",
+	"aud_mux2_sel"
+};
+
+static const char * const cpu_parents[] = {
+	"clk26m",
+	"armpll",
+	"mainpll",
+	"mmpll"
+};
+
+static const struct mtk_composite top_muxes[] = {
+	MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
+		0x0040, 0, 3, INVALID_MUX_GATE_BIT, CLK_IS_CRITICAL),
+	MUX_GATE_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents,
+		0x0040, 8, 1, 15, CLK_IS_CRITICAL),
+	MUX_GATE_FLAGS(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel",
+		ddrphycfg_parents, 0x0040, 16, 1, 23, CLK_IS_CRITICAL),
+	MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents,
+		0x0040, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents,
+		0x0050, 0, 2, 7),
+	MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents,
+		0x0050, 8, 4, 15),
+	MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents,
+		0x0050, 16, 3, 23),
+	MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents,
+		0x0050, 24, 3, 31),
+	MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents,
+		0x0060, 0, 1, 7),
+
+	MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi_parents,
+		0x0060, 8, 3, 15),
+	MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents,
+		0x0060, 16, 2, 23),
+	MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents,
+		0x0060, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents,
+		0x0070, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents,
+		0x0070, 8, 3, 15),
+	MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", msdc30_parents,
+		0x0070, 16, 1, 23),
+	MUX_GATE(CLK_TOP_AUDINTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
+		0x0070, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents,
+		0x0080, 0, 4, 7),
+	MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents,
+		0x0080, 8, 2, 15),
+	MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents,
+		0x0080, 16, 3, 23),
+	MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents,
+		0x0080, 24, 2, 31),
+
+	MUX_GATE(CLK_TOP_TVE_SEL, "tve_sel", tve_parents,
+		0x0090, 0, 3, 7),
+	MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents,
+		0x0090, 8, 2, 15),
+	MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents,
+		0x0090, 16, 3, 23),
+
+	MUX_GATE_FLAGS(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents,
+		0x00A0, 0, 2, 7, CLK_IS_CRITICAL),
+	MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents,
+		0x00A0, 8, 3, 15),
+	MUX_GATE(CLK_TOP_EMMC_HCLK_SEL, "emmc_hclk_sel", emmc_hclk_parents,
+		0x00A0, 24, 2, 31),
+
+	MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents,
+		0x00B0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_DI_SEL, "di_sel", di_parents,
+		0x00B0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_NR_SEL, "nr_sel", nr_osd_parents,
+		0x00B0, 16, 3, 23),
+	MUX_GATE(CLK_TOP_OSD_SEL, "osd_sel", nr_osd_parents,
+		0x00B0, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_HDMIRX_BIST_SEL, "hdmirx_bist_sel",
+		hdmirx_bist_parents, 0x00C0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents,
+		0x00C0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_ASM_I_SEL, "asm_i_sel", asm_parents,
+		0x00C0, 16, 2, 23),
+	MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_parents,
+		0x00C0, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_parents,
+		0x00D0, 0, 2, 7),
+	MUX_GATE(CLK_TOP_MS_CARD_SEL, "ms_card_sel", ms_card_parents,
+		0x00D0, 16, 2, 23),
+	MUX_GATE(CLK_TOP_ETHIF_SEL, "ethif_sel", ethif_parents,
+		0x00D0, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_HDMIRX26_24_SEL, "hdmirx26_24_sel", hdmirx_parents,
+		0x00E0, 0, 1, 7),
+	MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents,
+		0x00E0, 8, 3, 15),
+	MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel", cmsys_parents,
+		0x00E0, 16, 4, 23),
+
+	MUX_GATE(CLK_TOP_SPI1_SEL, "spi2_sel", spi_parents,
+		0x00E0, 24, 3, 31),
+	MUX_GATE(CLK_TOP_SPI2_SEL, "spi1_sel", spi_parents,
+		0x00F0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_8BDAC_SEL, "8bdac_sel", clk_8bdac_parents,
+		0x00F0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_AUD2DVD_SEL, "aud2dvd_sel", aud2dvd_parents,
+		0x00F0, 16, 1, 23),
+
+	MUX(CLK_TOP_PADMCLK_SEL, "padmclk_sel", padmclk_parents,
+		0x0100, 0, 3),
+
+	MUX(CLK_TOP_AUD_MUX1_SEL, "aud_mux1_sel", aud_mux_parents,
+		0x012c, 0, 3),
+	MUX(CLK_TOP_AUD_MUX2_SEL, "aud_mux2_sel", aud_mux_parents,
+		0x012c, 3, 3),
+	MUX(CLK_TOP_AUDPLL_MUX_SEL, "audpll_sel", aud_mux_parents,
+		0x012c, 6, 3),
+	MUX_GATE(CLK_TOP_AUD_K1_SRC_SEL, "aud_k1_src_sel", aud_src_parents,
+		0x012c, 15, 1, 23),
+	MUX_GATE(CLK_TOP_AUD_K2_SRC_SEL, "aud_k2_src_sel", aud_src_parents,
+		0x012c, 16, 1, 24),
+	MUX_GATE(CLK_TOP_AUD_K3_SRC_SEL, "aud_k3_src_sel", aud_src_parents,
+		0x012c, 17, 1, 25),
+	MUX_GATE(CLK_TOP_AUD_K4_SRC_SEL, "aud_k4_src_sel", aud_src_parents,
+		0x012c, 18, 1, 26),
+	MUX_GATE(CLK_TOP_AUD_K5_SRC_SEL, "aud_k5_src_sel", aud_src_parents,
+		0x012c, 19, 1, 27),
+	MUX_GATE(CLK_TOP_AUD_K6_SRC_SEL, "aud_k6_src_sel", aud_src_parents,
+		0x012c, 20, 1, 28),
+};
+
+static const struct mtk_clk_divider top_adj_divs[] = {
+	DIV_ADJ(CLK_TOP_AUD_EXTCK1_DIV, "audio_ext1_ck", "aud_ext1",
+		0x0120, 0, 8),
+	DIV_ADJ(CLK_TOP_AUD_EXTCK2_DIV, "audio_ext2_ck", "aud_ext2",
+		0x0120, 8, 8),
+	DIV_ADJ(CLK_TOP_AUD_MUX1_DIV, "aud_mux1_div", "aud_mux1_sel",
+		0x0120, 16, 8),
+	DIV_ADJ(CLK_TOP_AUD_MUX2_DIV, "aud_mux2_div", "aud_mux2_sel",
+		0x0120, 24, 8),
+	DIV_ADJ(CLK_TOP_AUD_K1_SRC_DIV, "aud_k1_src_div", "aud_k1_src_sel",
+		0x0124, 0, 8),
+	DIV_ADJ(CLK_TOP_AUD_K2_SRC_DIV, "aud_k2_src_div", "aud_k2_src_sel",
+		0x0124, 8, 8),
+	DIV_ADJ(CLK_TOP_AUD_K3_SRC_DIV, "aud_k3_src_div", "aud_k3_src_sel",
+		0x0124, 16, 8),
+	DIV_ADJ(CLK_TOP_AUD_K4_SRC_DIV, "aud_k4_src_div", "aud_k4_src_sel",
+		0x0124, 24, 8),
+	DIV_ADJ(CLK_TOP_AUD_K5_SRC_DIV, "aud_k5_src_div", "aud_k5_src_sel",
+		0x0128, 0, 8),
+	DIV_ADJ(CLK_TOP_AUD_K6_SRC_DIV, "aud_k6_src_div", "aud_k6_src_sel",
+		0x0128, 8, 8),
+};
+
+static const struct mtk_gate_regs top_aud_cg_regs = {
+	.sta_ofs = 0x012C,
+};
+
+#define GATE_TOP_AUD(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &top_aud_cg_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr,	\
+	}
+
+static const struct mtk_gate top_clks[] = {
+	GATE_TOP_AUD(CLK_TOP_AUD_48K_TIMING, "a1sys_hp_ck", "aud_mux1_div",
+		21),
+	GATE_TOP_AUD(CLK_TOP_AUD_44K_TIMING, "a2sys_hp_ck", "aud_mux2_div",
+		22),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S1_MCLK, "aud_i2s1_mclk", "aud_k1_src_div",
+		23),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S2_MCLK, "aud_i2s2_mclk", "aud_k2_src_div",
+		24),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S3_MCLK, "aud_i2s3_mclk", "aud_k3_src_div",
+		25),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S4_MCLK, "aud_i2s4_mclk", "aud_k4_src_div",
+		26),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S5_MCLK, "aud_i2s5_mclk", "aud_k5_src_div",
+		27),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S6_MCLK, "aud_i2s6_mclk", "aud_k6_src_div",
+		28),
+};
+
+static void mtk_topckgen_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+
+	mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
+								clk_data);
+
+	mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
+								clk_data);
+
+	mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes),
+				base, &lock, clk_data);
+
+	mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs),
+				base, &lock, clk_data);
+
+	mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+
+static const struct mtk_gate_regs infra_cg_regs = {
+	.set_ofs = 0x0040,
+	.clr_ofs = 0x0044,
+	.sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) {		\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &infra_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate infra_clks[] = {
+	GATE_ICG(CLK_INFRA_DBG, "dbgclk", "axi_sel", 0),
+	GATE_ICG(CLK_INFRA_SMI, "smi_ck", "mm_sel", 1),
+	GATE_ICG(CLK_INFRA_QAXI_CM4, "cm4_ck", "axi_sel", 2),
+	GATE_ICG(CLK_INFRA_AUD_SPLIN_B, "audio_splin_bck", "hadds2pll_294m", 4),
+	GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "clk26m", 5),
+	GATE_ICG(CLK_INFRA_EFUSE, "efuse_ck", "clk26m", 6),
+	GATE_ICG(CLK_INFRA_L2C_SRAM, "l2c_sram_ck", "mm_sel", 7),
+	GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
+	GATE_ICG(CLK_INFRA_CONNMCU, "connsys_bus", "wbg_dig_ck_416m", 12),
+	GATE_ICG(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 13),
+	GATE_ICG(CLK_INFRA_RAMBUFIF, "rambufif_ck", "mem_sel", 14),
+	GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "mem_sel", 15),
+	GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
+	GATE_ICG(CLK_INFRA_CEC, "cec_ck", "rtc_sel", 18),
+	GATE_ICG(CLK_INFRA_IRRX, "irrx_ck", "axi_sel", 19),
+	GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
+	GATE_ICG(CLK_INFRA_PMICWRAP, "pmicwrap_ck", "axi_sel", 23),
+	GATE_ICG(CLK_INFRA_DDCCI, "ddcci_ck", "axi_sel", 24),
+};
+
+static const struct mtk_fixed_factor infra_fixed_divs[] = {
+	FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2),
+};
+
+static struct clk_onecell_data *infra_clk_data;
+
+static void __init mtk_infrasys_init_early(struct device_node *node)
+{
+	int r, i;
+
+	if (!infra_clk_data) {
+		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+
+		for (i = 0; i < CLK_INFRA_NR; i++)
+			infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
+	}
+
+	mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+						infra_clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+CLK_OF_DECLARE(mtk_infra, "mediatek,mt2701-infracfg", mtk_infrasys_init_early);
+
+static void mtk_infrasys_init(struct device_node *node)
+{
+	int r, i;
+
+	if (!infra_clk_data) {
+		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+	} else {
+		for (i = 0; i < CLK_INFRA_NR; i++) {
+			if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
+				infra_clk_data->clks[i] = ERR_PTR(-ENOENT);
+		}
+	}
+
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+						infra_clk_data);
+	mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+						infra_clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x0010,
+	.sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0x000c,
+	.clr_ofs = 0x0014,
+	.sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &peri0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_PERI1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &peri1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate peri_clks[] = {
+	GATE_PERI1(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 31),
+	GATE_PERI1(CLK_PERI_ETH, "eth_ck", "clk26m", 30),
+	GATE_PERI1(CLK_PERI_SPI0, "spi0_ck", "spi0_sel", 29),
+	GATE_PERI1(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 28),
+	GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "clk26m", 27),
+	GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 26),
+	GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 25),
+	GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 24),
+	GATE_PERI0(CLK_PERI_BTIF, "bitif_ck", "axi_sel", 23),
+	GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 22),
+	GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 21),
+	GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 20),
+	GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 19),
+	GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 18),
+	GATE_PERI0(CLK_PERI_MSDC50_3, "msdc50_3_ck", "emmc_hclk_sel", 17),
+	GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_3_sel", 16),
+	GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_2_sel", 15),
+	GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_1_sel", 14),
+	GATE_PERI0(CLK_PERI_MSDC30_0, "msdc30_0_ck", "msdc30_0_sel", 13),
+	GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
+	GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
+	GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
+	GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
+	GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
+	GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
+	GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
+	GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
+	GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
+	GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
+	GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
+	GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
+	GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "nfi2x_sel", 0),
+
+	GATE_PERI1(CLK_PERI_FCI, "fci_ck", "ms_card_sel", 11),
+	GATE_PERI1(CLK_PERI_SPI2, "spi2_ck", "spi2_sel", 10),
+	GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi1_sel", 9),
+	GATE_PERI1(CLK_PERI_HOST89_DVD, "host89_dvd_ck", "aud2dvd_sel", 8),
+	GATE_PERI1(CLK_PERI_HOST89_SPI, "host89_spi_ck", "spi0_sel", 7),
+	GATE_PERI1(CLK_PERI_HOST89_INT, "host89_int_ck", "axi_sel", 6),
+	GATE_PERI1(CLK_PERI_FLASH, "flash_ck", "nfi2x_sel", 5),
+	GATE_PERI1(CLK_PERI_NFI_PAD, "nfi_pad_ck", "nfi1x_pad", 4),
+	GATE_PERI1(CLK_PERI_NFI_ECC, "nfi_ecc_ck", "nfi1x_pad", 3),
+	GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "axi_sel", 2),
+	GATE_PERI1(CLK_PERI_USB_SLV, "usbslv_ck", "axi_sel", 1),
+	GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 0),
+};
+
+static const char * const uart_ck_sel_parents[] = {
+	"clk26m",
+	"uart_sel",
+};
+
+static const struct mtk_composite peri_muxs[] = {
+	MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents,
+		0x40c, 0, 1),
+	MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents,
+		0x40c, 1, 1),
+	MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents,
+		0x40c, 2, 1),
+	MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents,
+		0x40c, 3, 1),
+};
+
+static void mtk_pericfg_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_PERI_NR);
+
+	mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
+						clk_data);
+
+	mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base,
+			&lock, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+
+#define MT8590_PLL_FMAX		(2000 * MHZ)
+#define CON0_MT8590_RST_BAR	BIT(27)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \
+			_pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) {	\
+		.id = _id,						\
+		.name = _name,						\
+		.reg = _reg,						\
+		.pwr_reg = _pwr_reg,					\
+		.en_mask = _en_mask,					\
+		.flags = _flags,					\
+		.rst_bar_mask = CON0_MT8590_RST_BAR,			\
+		.fmax = MT8590_PLL_FMAX,				\
+		.pcwbits = _pcwbits,					\
+		.pd_reg = _pd_reg,					\
+		.pd_shift = _pd_shift,					\
+		.tuner_reg = _tuner_reg,				\
+		.pcw_reg = _pcw_reg,					\
+		.pcw_shift = _pcw_shift,				\
+	}
+
+static const struct mtk_pll_data apmixed_plls[] = {
+	PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x80000001,
+			PLL_AO, 21, 0x204, 24, 0x0, 0x204, 0),
+	PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0xf0000001,
+		  HAVE_RST_BAR, 21, 0x210, 4, 0x0, 0x214, 0),
+	PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xf3000001,
+		  HAVE_RST_BAR, 7, 0x220, 4, 0x0, 0x224, 14),
+	PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0x00000001, 0,
+				21, 0x230, 4, 0x0, 0x234, 0),
+	PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0,
+				21, 0x240, 4, 0x0, 0x244, 0),
+	PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x250, 0x25c, 0x00000001, 0,
+				21, 0x250, 4, 0x0, 0x254, 0),
+	PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x270, 0x27c, 0x00000001, 0,
+				31, 0x270, 4, 0x0, 0x274, 0),
+	PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x280, 0x28c, 0x00000001, 0,
+				31, 0x280, 4, 0x0, 0x284, 0),
+	PLL(CLK_APMIXED_ETHPLL, "ethpll", 0x290, 0x29c, 0x00000001, 0,
+				31, 0x290, 4, 0x0, 0x294, 0),
+	PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x2a0, 0x2ac, 0x00000001, 0,
+				31, 0x2a0, 4, 0x0, 0x2a4, 0),
+	PLL(CLK_APMIXED_HADDS2PLL, "hadds2pll", 0x2b0, 0x2bc, 0x00000001, 0,
+				31, 0x2b0, 4, 0x0, 0x2b4, 0),
+	PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x2c0, 0x2cc, 0x00000001, 0,
+				31, 0x2c0, 4, 0x0, 0x2c4, 0),
+	PLL(CLK_APMIXED_TVD2PLL, "tvd2pll", 0x2d0, 0x2dc, 0x00000001, 0,
+				21, 0x2d0, 4, 0x0, 0x2d4, 0),
+};
+
+static void mtk_apmixedsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR);
+	if (!clk_data)
+		return;
+
+	mtk_clk_register_plls(node, apmixed_plls, ARRAY_SIZE(apmixed_plls),
+								clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+
+static const struct of_device_id of_match_clk_mt2701[] = {
+	{
+		.compatible = "mediatek,mt2701-topckgen",
+		.data = mtk_topckgen_init,
+	}, {
+		.compatible = "mediatek,mt2701-infracfg",
+		.data = mtk_infrasys_init,
+	}, {
+		.compatible = "mediatek,mt2701-pericfg",
+		.data = mtk_pericfg_init,
+	}, {
+		.compatible = "mediatek,mt2701-apmixedsys",
+		.data = mtk_apmixedsys_init,
+	}, {
+		/* sentinel */
+	}
+};
+
+static int clk_mt2701_probe(struct platform_device *pdev)
+{
+	void (*clk_init)(struct device_node *);
+	const struct of_device_id *of_id;
+
+	pr_warn("%s():%d: %s\n", __func__, __LINE__, pdev->name);
+
+	of_id = of_match_node(of_match_clk_mt2701, pdev->dev.of_node);
+	if (!of_id || !of_id->data)
+		return -EINVAL;
+
+	clk_init = of_id->data;
+	clk_init(pdev->dev.of_node);
+
+	return 0;
+}
+
+static struct platform_driver clk_mt2701_drv = {
+	.probe = clk_mt2701_probe,
+	.driver = {
+		.name = "clk-mt2701",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_clk_mt2701,
+	},
+};
+
+static int __init clk_mt2701_init(void)
+{
+	return platform_driver_register(&clk_mt2701_drv);
+}
+
+arch_initcall(clk_mt2701_init);
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index bb30f70..6a015a8 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -58,6 +58,9 @@ void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
 	for (i = 0; i < num; i++) {
 		const struct mtk_fixed_clk *rc = &clks[i];
 
+		if (!IS_ERR_OR_NULL(clk_data->clks[rc->id]))
+			continue;
+
 		clk = clk_register_fixed_rate(NULL, rc->name, rc->parent, 0,
 					      rc->rate);
 
@@ -81,6 +84,9 @@ void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
 	for (i = 0; i < num; i++) {
 		const struct mtk_fixed_factor *ff = &clks[i];
 
+		if (!IS_ERR_OR_NULL(clk_data->clks[ff->id]))
+			continue;
+
 		clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
 				CLK_SET_RATE_PARENT, ff->mult, ff->div);
 
@@ -116,6 +122,9 @@ int mtk_clk_register_gates(struct device_node *node,
 	for (i = 0; i < num; i++) {
 		const struct mtk_gate *gate = &clks[i];
 
+		if (!IS_ERR_OR_NULL(clk_data->clks[gate->id]))
+			continue;
+
 		clk = mtk_clk_register_gate(gate->name, gate->parent_name,
 				regmap,
 				gate->regs->set_ofs,
@@ -232,6 +241,9 @@ void mtk_clk_register_composites(const struct mtk_composite *mcs,
 	for (i = 0; i < num; i++) {
 		const struct mtk_composite *mc = &mcs[i];
 
+		if (!IS_ERR_OR_NULL(clk_data->clks[mc->id]))
+			continue;
+
 		clk = mtk_clk_register_composite(mc, base, lock);
 
 		if (IS_ERR(clk)) {
@@ -244,3 +256,31 @@ void mtk_clk_register_composites(const struct mtk_composite *mcs,
 			clk_data->clks[mc->id] = clk;
 	}
 }
+
+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
+			int num, void __iomem *base, spinlock_t *lock,
+				struct clk_onecell_data *clk_data)
+{
+	struct clk *clk;
+	int i;
+
+	for (i = 0; i <  num; i++) {
+		const struct mtk_clk_divider *mcd = &mcds[i];
+
+		if (!IS_ERR_OR_NULL(clk_data->clks[mcd->id]))
+			continue;
+
+		clk = clk_register_divider(NULL, mcd->name, mcd->parent_name,
+			mcd->flags, base +  mcd->div_reg, mcd->div_shift,
+			mcd->div_width, mcd->clk_divider_flags, lock);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+				mcd->name, PTR_ERR(clk));
+			continue;
+		}
+
+		if (clk_data)
+			clk_data->clks[mcd->id] = clk;
+	}
+}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index 32d2e45..f5d6b70 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -83,7 +83,12 @@ struct mtk_composite {
 	signed char num_parents;
 };
 
-#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) {	\
+/*
+ * In case the rate change propagation to parent clocks is undesirable,
+ * this macro allows to specify the clock flags manually.
+ */
+#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,	\
+			_gate, _flags) {				\
 		.id = _id,						\
 		.name = _name,						\
 		.mux_reg = _reg,					\
@@ -94,9 +99,17 @@ struct mtk_composite {
 		.divider_shift = -1,					\
 		.parent_names = _parents,				\
 		.num_parents = ARRAY_SIZE(_parents),			\
-		.flags = CLK_SET_RATE_PARENT,				\
+		.flags = _flags,					\
 	}
 
+/*
+ * Unless necessary, all MUX_GATE clocks propagate rate changes to their
+ * parent clock by default.
+ */
+#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate)	\
+	MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,	\
+		_gate, CLK_SET_RATE_PARENT)
+
 #define MUX(_id, _name, _parents, _reg, _shift, _width) {		\
 		.id = _id,						\
 		.name = _name,						\
@@ -110,7 +123,8 @@ struct mtk_composite {
 		.flags = CLK_SET_RATE_PARENT,				\
 	}
 
-#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) {	\
+#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg,	\
+					_div_width, _div_shift) {	\
 		.id = _id,						\
 		.parent = _parent,					\
 		.name = _name,						\
@@ -145,12 +159,40 @@ struct mtk_gate {
 	const struct clk_ops *ops;
 };
 
-int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
-		int num, struct clk_onecell_data *clk_data);
+int mtk_clk_register_gates(struct device_node *node,
+			const struct mtk_gate *clks, int num,
+			struct clk_onecell_data *clk_data);
+
+struct mtk_clk_divider {
+	int id;
+	const char *name;
+	const char *parent_name;
+	unsigned long flags;
+
+	u32 div_reg;
+	unsigned char div_shift;
+	unsigned char div_width;
+	unsigned char clk_divider_flags;
+	const struct clk_div_table *clk_div_table;
+};
+
+#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.div_reg = _reg,				\
+		.div_shift = _shift,				\
+		.div_width = _width,				\
+}
+
+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
+			int num, void __iomem *base, spinlock_t *lock,
+				struct clk_onecell_data *clk_data);
 
 struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
 
 #define HAVE_RST_BAR	BIT(0)
+#define PLL_AO		BIT(1)
 
 struct mtk_pll_div_table {
 	u32 div;
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index 0c2deac..a409142 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -301,6 +301,7 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
 	pll->data = data;
 
 	init.name = data->name;
+	init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0;
 	init.ops = &mtk_pll_ops;
 	init.parent_names = &parent_name;
 	init.num_parents = 1;
-- 
1.9.1



From dyoung at redhat.com  Mon May 16 22:42:16 2016
From: dyoung at redhat.com (Dave Young)
Date: Tue, 17 May 2016 13:42:16 +0800
Subject: [PATCH v15 00/20] arm64 kexec kernel patches v15
In-Reply-To: <1459535954.20121.3.camel@infradead.org>
References: <cover.1457977401.git.geoff@infradead.org>
 <20160401015947.GA3835@dhcp-128-65.nay.redhat.com>
 <1459535954.20121.3.camel@infradead.org>
Message-ID: <20160517054216.GA12543@dhcp-128-65.nay.redhat.com>

Marc, it has been discussed for long time, I think kdump code can be
logically splitted from this series so that we can get the kexec
done first? 

On 04/01/16 at 11:39am, Geoff Levand wrote:
> Hi,
> 
> On Fri, 2016-04-01 at 09:59 +0800, Dave Young wrote:
> > Geoff, for easier to review maybe you can send kexec patches first
> > then AKASHI Takahiro
> > can send the kdump patches as a standalone patchset?
> 
> Marc Zyngier specifically asked for an integrated set
> of patches for easier review.  I will keep it that way
> for now.
> 
> -Geoff


From hramrach at gmail.com  Mon May 16 22:44:36 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: Tue, 17 May 2016 07:44:36 +0200
Subject: [linux-sunxi] Re: [PATCH 4/9] spi: sun4i: add DMA support
In-Reply-To: <20150820185850.GQ12027@sirena.org.uk>
References: <cover.1440080122.git.hramrach@gmail.com>
 <ccf776869b0d7fe2c78bcc41d6cd1896bf732296.1440080122.git.hramrach@gmail.com>
 <20150820185850.GQ12027@sirena.org.uk>
Message-ID: <CAOMqctQPUDm3XDf_YAVubzq2op=j6Qs6R4hjjCaa=ELoeHzjhQ@mail.gmail.com>

On 20 August 2015 at 16:56, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:

>> +             /* Enable Dedicated DMA requests */
>> +             reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
>> +             reg |= SUN4I_CTL_DMAMC_DEDICATED;
>> +             sun4i_spi_write(sspi, SUN4I_CTL_REG, reg);
>> +             sun4i_spi_write(sspi, SUN4I_DMA_CTL_REG, trigger);
>> +     } else {
>> +             dev_dbg(&sspi->master->dev, "Using PIO mode for transfer\n");
>> +
>> +             /* Disable DMA requests */
>> +             reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
>> +             sun4i_spi_write(sspi, SUN4I_CTL_REG,
>> +                             reg & ~SUN4I_CTL_DMAMC_DEDICATED);
>> +             sun4i_spi_write(sspi, SUN4I_DMA_CTL_REG, 0);
>> +
>> +             /* Fill the TX FIFO */
>> +             /* Filling the fifo fully causes timeout for some reason
>> +              * at least on spi2 on a10s */
>> +             sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH - 1);
>> +     }
>> +
>>       /* Start the transfer */
>>       reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
>>       sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
>> @@ -303,7 +363,12 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
>>               goto out;
>>       }
>>
>> -     sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
>> +     if (sun4i_spi_can_dma(master, spi, tfr) && desc_rx) {
>> +             /* The receive transfer should be the last one to finish */
>> +             dma_wait_for_async_tx(desc_rx);
>
> Nope, this is only meant for async_tx. You should register a callback
> in your transfer that will mark the completion structure as completed,
> and then drain the FIFO only if not using DMA.

What exactly is wrong with this?

I did not observe data corruption. Passing desc_rx to
dma_wait_for_async_tx looks odd on closer inspection, though. Will
look through some other spi driver code.

>> -     init_completion(&sspi->done);
>> +     master->dma_tx = dma_request_slave_channel_reason(&pdev->dev, "tx");
>> +     if (IS_ERR(master->dma_tx)) {
>> +             dev_err(&pdev->dev, "Unable to acquire DMA channel TX\n");
>> +             ret = PTR_ERR(master->dma_tx);
>> +             goto err_free_master;
>> +     }
>> +
>> +     dma_sconfig.direction = DMA_MEM_TO_DEV;
>> +     dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
>> +     dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
>> +     dma_sconfig.dst_addr = res->start + SUN4I_TXDATA_REG;
>> +     dma_sconfig.src_maxburst = 1;
>> +     dma_sconfig.dst_maxburst = 1;
>> +
>> +     ret = dmaengine_slave_config(master->dma_tx, &dma_sconfig);
>> +     if (ret) {
>> +             dev_err(&pdev->dev, "Unable to configure TX DMA slave\n");
>> +             goto err_tx_dma_release;
>> +     }
>> +
>> +     master->dma_rx = dma_request_slave_channel_reason(&pdev->dev, "rx");
>> +     if (IS_ERR(master->dma_rx)) {
>> +             dev_err(&pdev->dev, "Unable to acquire DMA channel RX\n");
>> +             ret = PTR_ERR(master->dma_rx);
>> +             goto err_tx_dma_release;
>> +     }
>> +
>> +     dma_sconfig.direction = DMA_DEV_TO_MEM;
>> +     dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
>> +     dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
>> +     dma_sconfig.src_addr = res->start + SUN4I_RXDATA_REG;
>> +     dma_sconfig.src_maxburst = 1;
>> +     dma_sconfig.dst_maxburst = 1;
>
> We can't use a higher bust size?

Who actually does?

It accomplishes the transfer with burst size of 1 so that's good enough.

Researching alignment requirements and other oddities of Chinese
controllers when larger burst size is used can be topic for another
patch.


On 20 August 2015 at 20:58, Mark Brown <broonie at kernel.org> wrote:
> On Thu, Aug 20, 2015 at 02:19:46PM -0000, Emilio L?pez wrote:
>
>> -     sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
>> +     if (sun4i_spi_can_dma(master, spi, tfr) && desc_rx) {
>> +             /* The receive transfer should be the last one to finish */
>> +             dma_wait_for_async_tx(desc_rx);
>
> What if it's a transmit only transfer?  We'll fall over to this...
>
>> +     } else {
>> +             sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
>> +     }
>
> ...which manually reads data from the FIFO which doesn't seem like what
... which should be empty since RX is not enabled.
> we want, won't it conflict with the DMA?
It does not seem to conflict in practice.


Thanks

Michal


From k.kozlowski at samsung.com  Mon May 16 23:02:06 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 17 May 2016 08:02:06 +0200
Subject: [PATCH] pinctrl: samsung: Suppress unbinding to prevent theoretical
 attacks
Message-ID: <1463464926-17482-1-git-send-email-k.kozlowski@samsung.com>

Although unbinding a pinctrl driver requires root privileges but it
still might be used theoretically in certain attacks (by triggering NULL
pointer exception or memory corruption).

Samsung pincontrol drivers are essential for system operation so their
removal is not expected. They do not implement remove() driver callback
and they are not buildable as modules.

Suppression of the unbinding will prevent triggering NULL pointer
exception like this (Odroid XU3):

  $ echo 13400000.pinctrl > /sys/bus/platform/drivers/samsung-pinctrl/unbind
  $ cat /sys/kernel/debug/gpio

  Unable to handle kernel NULL pointer dereference at virtual address 00000c44
  pgd = ec41c000
  [00000c44] *pgd=6d448835, *pte=00000000, *ppte=00000000
  Internal error: Oops: 17 [#1] PREEMPT SMP ARM
    (samsung_gpio_get) from [<c034f9a0>] (gpiolib_seq_show+0x1b0/0x26c)
    (gpiolib_seq_show) from [<c01fb8c0>] (seq_read+0x304/0x4b8)
    (seq_read) from [<c02dbc78>] (full_proxy_read+0x4c/0x64)
    (full_proxy_read) from [<c01d9fb0>] (__vfs_read+0x2c/0x110)
    (__vfs_read) from [<c01db400>] (vfs_read+0x8c/0x110)
    (vfs_read) from [<c01db4c4>] (SyS_read+0x40/0x8c)
    (SyS_read) from [<c01078c0>] (ret_fast_syscall+0x0/0x3c)

Suggested-by: Marek Szyprowski <m.szyprowski at samsung.com>
Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/pinctrl/samsung/pinctrl-exynos5440.c | 1 +
 drivers/pinctrl/samsung/pinctrl-samsung.c    | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
index fb71fc3e5aa0..3000df80709f 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
@@ -998,6 +998,7 @@ static struct platform_driver exynos5440_pinctrl_driver = {
 	.driver = {
 		.name	= "exynos5440-pinctrl",
 		.of_match_table = exynos5440_pinctrl_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index ed0b70881e19..513fe6b23248 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1274,6 +1274,7 @@ static struct platform_driver samsung_pinctrl_driver = {
 	.driver = {
 		.name	= "samsung-pinctrl",
 		.of_match_table = samsung_pinctrl_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
-- 
1.9.1



From adrian.hunter at intel.com  Mon May 16 22:58:59 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Tue, 17 May 2016 08:58:59 +0300
Subject: [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during
 no data transfer
In-Reply-To: <CALk7dXpDXS2R0RJ9KNTaMFxBC+VVvrJ+U1X5Z_kZJNxwxrC6iQ@mail.gmail.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-10-git-send-email-aisheng.dong@nxp.com>
 <573184F3.50201@intel.com>
 <CALk7dXpDXS2R0RJ9KNTaMFxBC+VVvrJ+U1X5Z_kZJNxwxrC6iQ@mail.gmail.com>
Message-ID: <573AB323.1080207@intel.com>

On 17/05/16 07:31, Ritesh Harjani wrote:
> On Tue, May 10, 2016 at 12:21 PM, Adrian Hunter <adrian.hunter at intel.com> wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> Current code will report the wrong data interrupt got when no
>>> data operation in progress assumed by getting !host->data in
>>> sdhci_data_irq().
>>>
>>> For a data command handling process, the driver will call
>>> sdhci_finish_data() and clear host->data in case any data error,
>>> then card finish_tasklet will do the rest controller reset work.
>>>
>>> Before the tasklet got run, however, controllers may report the
>>> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
>>> than data CRC error and data end bit error interrupts for single
>>> block transfer or the last block of multiblock transfer.
> 
> What if the controller generates Transfer complete interrupt bit more slower
> and the tasklet do get a chance to run. In that case even host->mrq
> will become NULL.
> Actually if that happens it's even more worse since the driver may
> start issuing other commands to controller.
> 
> Are we covering that case here? Do you think that this case is possible?

After data error, the host driver resets the controller so there will be no
more interrupts relating to that mrq.

This patch is avoiding unnecessary warnings until that happens.

> 
> 
>>>
>>> Controller usually detects and generates data CRC/end bit error
>>> interrupts once one block on the bus is transferred completely.
>>> For single block transfer, since there's only one bock to transfer,
>>> the controller will report transfer complete interrupt as well,
>>> but until the data in controller FIFO has been successfully
>>> transferred to memory. The time gap of TC and CRC interrupt depends on
>>> the system busy state at that point and memory bus access speed.
>>>
>>> So it is possible when TC interrupt generated, host->data is already
>>> equal to NULL due to cleared by former CRC/Data End Bit error which
>>> is reasonable.
>>>
>>> Thus we DO NOT report the weird data interrupt event for this case.
>>>
>>> Else we may easily see warning below during SD3.0 card manually tuning
>>> process (calling mmc_send_tuning() which is a single block transfer)
>>> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
>>>
>>> The detailed command log is as follows:
>>> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
>>> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
>>> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
>>> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
>>> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
>>> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
>>> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
>>> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
>>> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
>>> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
>>> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
>>> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
>>> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
>>> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
>>> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
>>> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
>>> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
>>> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
>>> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
>>> [ 1657.929995] sdhci: ===========================================
>>> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
>>> [ 1657.930179] mmc0:     0 bytes transferred: -84
>>>
>>> It shows we first have a data CRC error interrupt then a data transfer
>>> complete interrupt.
>>> Then we got the !host->data case in sdhci_data_irq().
>>>
>>> CC: stable <stable at vger.kernel.org>
>>> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
>>> ---
>>>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>>>  1 file changed, 11 insertions(+)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 40e3551..2eb0e34 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>>>                       }
>>>               }
>>>
>>> +             /*
>>> +              * The "data complete" interrupt is possible to happen a bit
>>> +              * later than CRC error and data end bit error interrupts
>>> +              * separately for single block transfer or the last block of
>>> +              * multiblock transfer. For this case, we DO NOT report the
>>> +              * weird data interrupt event.
>>> +              */
>>> +             if ((intmask & SDHCI_INT_DATA_END) &&
>>> +                 (host->mrq && host->mrq->data && host->mrq->data->error))
>>> +                     return;
>>
>> This could be generalized a bit more i.e. what about:
>>
>>                 /*
>>                  * After an error and before the the data circuit is reset in
>>                  * sdhci_tasklet_finish, we could get more interrupts, but we
>>                  * already have an error, so ignore them.
>>                  */
>>                 if (host->mrq && host->mrq->data && host->mrq->data->error)
>>                         return;
>>
>>> +
>>>               pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
>>>                      mmc_hostname(host->mmc), (unsigned)intmask);
>>>               sdhci_dumpregs(host);
>>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 



From moinejf at free.fr  Mon May 16 23:54:27 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Tue, 17 May 2016 08:54:27 +0200
Subject: [PATCH 02/16] clk: sunxi-ng: Add common infrastructure
In-Reply-To: <20160516201509.GL27618@lukather>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-3-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v67XWt6tjG_xXWgGatTaiN5uYQb2_Q6bgixMDUkHfVHLHg@mail.gmail.com>
 <20160515183122.GA27618@lukather>
 <20160516100239.a93a238b0d458b38a3689a95@free.fr>
 <20160516201509.GL27618@lukather>
Message-ID: <20160517085427.f2f3aa0c66686f8f5f6318ff@free.fr>

On Mon, 16 May 2016 22:15:09 +0200
Maxime Ripard <maxime.ripard at free-electrons.com> wrote:

> > > Yes, I intended it to be a simple busy waiting loop since I don't
> > > expect it to be very long. Do yu have any more data on how much time
> > > it usually takes?
> > 
> > I have a Soc in which the rate of the audio clock is stable after a
> > good second.
> 
> You mean before the clock is actually stable, or before the lock bit
> is cleared?
> 
> Which SoC is it? As far as I've seen, only the H3 allows to configure
> the stable time, and while by default it will take 16us, you can
> configure as high as 66ms (which is still way higher than the current
> limit).

Hi Maxime,

Well, it is not a SoC, but an external chip, the SI5351 (in the Dove
Cubox). There is no lock bit, but as it is used for audio, and as I did
not set any delay at streaming start time, I can hear when the clock is
stable.

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From erin.lo at mediatek.com  Tue May 17 00:10:30 2016
From: erin.lo at mediatek.com (erin.lo)
Date: Tue, 17 May 2016 15:10:30 +0800
Subject: [PATCH v8 0/10] Add clock support for Mediatek MT2701
In-Reply-To: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
References: <1463461511-25019-1-git-send-email-erin.lo@mediatek.com>
Message-ID: <1463469030.20236.13.camel@mtksdaap41>

On Tue, 2016-05-17 at 13:05 +0800, Erin Lo wrote:
> This series is based on clk-next, add clock and reset controller support
> for Mediatek MT2701.
> 
> This series also refined makefile and Kconfig to support configurable
> multiple SoC clock support.
> 
> There some code borrowed from [2] in clk-mtk.h, and may need to resolve
> conflicts while merging these two series.
> 
> changes since v7:
> - Rebase to clk-next.
> - Implement subsystem clocks in seperated files.
> - Replace critical clock enabling with CLK_IS_CRITICAL flag.
> - Reduce most clock registrations in CLK_OF_DECLARE().
> - Remove __init and __initconst from most init fucntions and data,
>   and replace driver registration with platform_driver_register().
> - Replace some common function or variable names with unique names.
> - Use real clock for UARTs.

If we have clock support, we must associate the correct clocks to UARTs.
Otherwise it will cause booting issue.
They should be sent together.
I work with James Liao to prepare these patches.

> 
> changes since v6:
> - Rebase to v4.6-rc1.
> - Register subsystem clocks in probe() instead of CLK_OF_DECLARE().
> - Add clocks that referred by subsystem clocks.
> - Fix clk_data size of apmixedsys.
> - Add config options for each subsystem clock provider.
> 
> changes since v5:
> - Rebase to v4.5-rc1 and [1].
> - Enable critical clocks for MT2701
> - Refine dt-binding documents, add reset controller support for hifsys.
> 
> changes since v4:
> - Rebase to v4.5-rc1.
> - Remove CLK_SET_RATE_PARENT from divider flags.
> - Add img_jpgdec_smi clock.
> - Move clk/mediatek/Kconfig into menu section in clk/Kconfig.
> 
> changes since v3:
> - Change the parent of mm_mdp_bls_26m from clk26m to pwm_sel.
> 
> changes since v2:
> - Fix ethsys definition.
> - Replace read-modify-write with regmap_update_bits() in clock operations.
> - Move mt2701-resets.h to include/dt-bindings/reset/.
> - Add hifsys reset patch from John Crispin.
> 
> changes since v1:
> - Document MT2701 compatible strings.
> 
> [1] https://patchwork.kernel.org/patch/8147901/
> [2] http://www.spinics.net/lists/dri-devel/msg106726.html
> 
> Erin Lo (1):
>   arm: dts: mt2701: Use real clock for UARTs
> 
> James Liao (5):
>   clk: fix initial state of critical clock's parents
>   clk: mediatek: remove __init from clk registration functions
>   clk: mediatek: Refine the makefile to support multiple clock drivers
>   dt-bindings: ARM: Mediatek: Document bindings for MT2701
>   arm: dts: mt2701: Add clock controller device nodes
> 
> Shunli Wang (4):
>   clk: mediatek: Add dt-bindings for MT2701 clocks
>   clk: mediatek: Add MT2701 clock support
>   reset: mediatek: Add MT2701 reset controller dt-binding file
>   reset: mediatek: Add MT2701 reset driver
> 
>  .../bindings/arm/mediatek/mediatek,apmixedsys.txt  |    3 +-
>  .../bindings/arm/mediatek/mediatek,bdpsys.txt      |   22 +
>  .../bindings/arm/mediatek/mediatek,ethsys.txt      |   22 +
>  .../bindings/arm/mediatek/mediatek,hifsys.txt      |   24 +
>  .../bindings/arm/mediatek/mediatek,imgsys.txt      |    3 +-
>  .../bindings/arm/mediatek/mediatek,infracfg.txt    |    3 +-
>  .../bindings/arm/mediatek/mediatek,mmsys.txt       |    3 +-
>  .../bindings/arm/mediatek/mediatek,pericfg.txt     |    3 +-
>  .../bindings/arm/mediatek/mediatek,topckgen.txt    |    3 +-
>  .../bindings/arm/mediatek/mediatek,vdecsys.txt     |    3 +-
>  arch/arm/boot/dts/mt2701.dtsi                      |   50 +-
>  drivers/clk/Kconfig                                |    1 +
>  drivers/clk/clk.c                                  |    9 +-
>  drivers/clk/mediatek/Kconfig                       |   73 ++
>  drivers/clk/mediatek/Makefile                      |   13 +-
>  drivers/clk/mediatek/clk-gate.c                    |   54 +-
>  drivers/clk/mediatek/clk-gate.h                    |    2 +
>  drivers/clk/mediatek/clk-mt2701-bdp.c              |  140 +++
>  drivers/clk/mediatek/clk-mt2701-eth.c              |   82 ++
>  drivers/clk/mediatek/clk-mt2701-hif.c              |   81 ++
>  drivers/clk/mediatek/clk-mt2701-img.c              |   82 ++
>  drivers/clk/mediatek/clk-mt2701-mm.c               |  125 +++
>  drivers/clk/mediatek/clk-mt2701-vdec.c             |   93 ++
>  drivers/clk/mediatek/clk-mt2701.c                  | 1037 ++++++++++++++++++++
>  drivers/clk/mediatek/clk-mtk.c                     |   52 +-
>  drivers/clk/mediatek/clk-mtk.h                     |   52 +-
>  drivers/clk/mediatek/clk-pll.c                     |    3 +-
>  include/dt-bindings/clock/mt2701-clk.h             |  486 +++++++++
>  include/dt-bindings/reset/mt2701-resets.h          |   83 ++
>  29 files changed, 2578 insertions(+), 29 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,bdpsys.txt
>  create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,ethsys.txt
>  create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,hifsys.txt
>  create mode 100644 drivers/clk/mediatek/Kconfig
>  create mode 100644 drivers/clk/mediatek/clk-mt2701-bdp.c
>  create mode 100644 drivers/clk/mediatek/clk-mt2701-eth.c
>  create mode 100644 drivers/clk/mediatek/clk-mt2701-hif.c
>  create mode 100644 drivers/clk/mediatek/clk-mt2701-img.c
>  create mode 100644 drivers/clk/mediatek/clk-mt2701-mm.c
>  create mode 100644 drivers/clk/mediatek/clk-mt2701-vdec.c
>  create mode 100644 drivers/clk/mediatek/clk-mt2701.c
>  create mode 100644 include/dt-bindings/clock/mt2701-clk.h
>  create mode 100644 include/dt-bindings/reset/mt2701-resets.h
> 
> --
> 1.9.1
> 
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek




From cedric.madianga at gmail.com  Tue May 17 00:21:31 2016
From: cedric.madianga at gmail.com (M'boumba Cedric Madianga)
Date: Tue, 17 May 2016 09:21:31 +0200
Subject: [PATCH 1/5] dt-bindings: Document the STM32 I2C bindings
In-Reply-To: <20160516150440.GA6312@rob-hp-laptop>
References: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
 <1462980974-22091-2-git-send-email-cedric.madianga@gmail.com>
 <20160516150440.GA6312@rob-hp-laptop>
Message-ID: <CAOAejn3VJX4ZZZ9nXN+YOs_s-sXBOnGkvRXhZwP3undVnDjXMA@mail.gmail.com>

 Hi,

2016-05-16 17:04 GMT+02:00 Rob Herring <robh at kernel.org>:
> On Wed, May 11, 2016 at 05:36:10PM +0200, M'boumba Cedric Madianga wrote:
>> This patch adds documentation of device tree bindings for the STM32 I2C
>> controller.
>>
>> Signed-off-by: M'boumba Cedric Madianga <cedric.madianga at gmail.com>
>> ---
>>  .../devicetree/bindings/i2c/i2c-stm32.txt          | 33 ++++++++++++++++++++++
>>  1 file changed, 33 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-stm32.txt
>>
>> diff --git a/Documentation/devicetree/bindings/i2c/i2c-stm32.txt b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt
>> new file mode 100644
>> index 0000000..73215c6
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt
>> @@ -0,0 +1,33 @@
>> +* I2C controller embedded in STMicroelectronics STM32 I2C platform
>> +
>> +Required properties :
>> +- compatible : Must be "st,i2c-stm32f4"
>
> Normal order is st,stm32f4-i2c
Ok Thanks, I will correct it in the V2.

>
> Rob

Cedric


From k.kozlowski at samsung.com  Tue May 17 00:26:14 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 17 May 2016 09:26:14 +0200
Subject: [PATCH] clk: samsung: Suppress unbinding to prevent theoretical
 attacks
Message-ID: <1463469974-13340-1-git-send-email-k.kozlowski@samsung.com>

Although unbinding a driver requires root privileges but it still might
be used theoretically in certain attacks (by triggering NULL pointer
exception or memory corruption if driver does not provide proper remove
callbacks or core does not handle it).

Samsung clock drivers are essential for system operation so their
removal is not expected. More over, the Exynos3250 ISP clock driver does
not implement remove() driver callback and it is not buildable as
modules.

Suppress the unbind interface for Exynos3250 ISP and S3C2410 DCLK clock
drivers.

Suggested-by: Marek Szyprowski <m.szyprowski at samsung.com>
Cc: Marek Szyprowski <m.szyprowski at samsung.com>
Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/clk/samsung/clk-exynos3250.c   | 1 +
 drivers/clk/samsung/clk-s3c2410-dclk.c | 5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index 16575ee874cb..dc4d493e61c2 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -1087,6 +1087,7 @@ static const struct of_device_id exynos3250_cmu_isp_of_match[] = {
 static struct platform_driver exynos3250_cmu_isp_driver = {
 	.driver = {
 		.name = "exynos3250-cmu-isp",
+		.suppress_bind_attrs = true,
 		.of_match_table = exynos3250_cmu_isp_of_match,
 	},
 };
diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c
index ec6fb14d951c..ae9a595c72d0 100644
--- a/drivers/clk/samsung/clk-s3c2410-dclk.c
+++ b/drivers/clk/samsung/clk-s3c2410-dclk.c
@@ -428,8 +428,9 @@ MODULE_DEVICE_TABLE(platform, s3c24xx_dclk_driver_ids);
 
 static struct platform_driver s3c24xx_dclk_driver = {
 	.driver = {
-		.name		= "s3c24xx-dclk",
-		.pm		= &s3c24xx_dclk_pm_ops,
+		.name			= "s3c24xx-dclk",
+		.pm			= &s3c24xx_dclk_pm_ops,
+		.suppress_bind_attrs	= true,
 	},
 	.probe = s3c24xx_dclk_probe,
 	.remove = s3c24xx_dclk_remove,
-- 
1.9.1



From patrice.chotard at st.com  Tue May 17 00:43:18 2016
From: patrice.chotard at st.com (Patrice Chotard)
Date: Tue, 17 May 2016 09:43:18 +0200
Subject: [PATCH] pinctrl: stm32: fix debugfs format string
In-Reply-To: <1463147643-568615-1-git-send-email-arnd@arndb.de>
References: <1463147643-568615-1-git-send-email-arnd@arndb.de>
Message-ID: <573ACB96.6030808@st.com>

Hi Arnd

I have already send a fix for this on the mailing list on 12th may 
([PATCH 0/2] pinctrl: stm32: .pin_config_dbg_show fixes).
I don't know if Linus will merged it on his pinctrl branch.

Sorry

Patrice

On 05/13/2016 03:53 PM, Arnd Bergmann wrote:
> The newly added stm32_pconf_dbg_show function has an incorrect format
> string that does not match the arguments, as reported by the gcc warning:
>
> drivers/pinctrl/stm32/pinctrl-stm32.c: In function 'stm32_pconf_dbg_show':
> drivers/pinctrl/stm32/pinctrl-stm32.c:797:17: error: too many arguments for format [-Werror=format-extra-args]
>
> This changes the format string in a way that gets rid of the warning.
>
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Fixes: 3beed93c1617 ("pinctrl: stm32: Implement .pin_config_dbg_show()")
> ---
> I could not find a documentation for the debugfs format, so no
> idea if this is the intended format.
> ---
>   drivers/pinctrl/stm32/pinctrl-stm32.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
> index e51c1cf5270b..4ffbe9551299 100644
> --- a/drivers/pinctrl/stm32/pinctrl-stm32.c
> +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
> @@ -794,7 +794,7 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
>   	case 2:
>   		drive = stm32_pconf_get_driving(bank, offset);
>   		speed = stm32_pconf_get_speed(bank, offset);
> -		seq_printf(s, "%d - %s -%s", alt,
> +		seq_printf(s, "%d - %s - %s - %s %s ", alt,
>   			   drive ? "open drain" : "push pull",
>   			   biasing[bias],
>   			   speeds[speed], "speed");



From nsekhar at ti.com  Tue May 17 00:59:53 2016
From: nsekhar at ti.com (Sekhar Nori)
Date: Tue, 17 May 2016 13:29:53 +0530
Subject: [PATCH v4 12/18] arm: use of_platform_default_populate() to
 populate
In-Reply-To: <1463054775-18170-13-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463054775-18170-13-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <573ACF79.1090600@ti.com>

On Thursday 12 May 2016 05:36 PM, Kefeng Wang wrote:
> Use helper of_platform_default_populate() in linux/of_platform
> when possible, instead of calling of_platform_populate() with
> the default match table.
> 
> Cc: Nicolas Ferre <nicolas.ferre at atmel.com>
> Cc: Krzysztof Halasa <khalasa at piap.pl>
> Cc: Sekhar Nori <nsekhar at ti.com>
> Cc: Shawn Guo <shawnguo at kernel.org>
> Cc: Russell King <linux at arm.linux.org.uk>
> Cc: Roland Stigge <stigge at antcom.de>
> Cc: Jason Cooper <jason at lakedaemon.net>
> Cc: Ray Jui <rjui at broadcom.com>
> Cc: Viresh Kumar <vireshk at kernel.org>
> Cc: Stephen Warren <swarren at wwwdotorg.org>
> Cc: Rob Herring <robh at kernel.org>
> Cc: Michal Simek <michal.simek at xilinx.com>
> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> ---

> diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c
> index c4b5808..da46dc7 100644
> --- a/arch/arm/mach-davinci/da8xx-dt.c
> +++ b/arch/arm/mach-davinci/da8xx-dt.c
> @@ -54,8 +54,7 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
>  
>  static void __init da850_init_machine(void)
>  {
> -	of_platform_populate(NULL, of_default_bus_match_table,
> -			     da850_auxdata_lookup, NULL);
> +	of_platform_default_populate(NULL, da850_auxdata_lookup, NULL);
>  
>  }

The mach-davinci change is already queued for v4.7

Thanks,
Sekhar


From eballetbo at gmail.com  Tue May 17 01:06:22 2016
From: eballetbo at gmail.com (Enric Balletbo Serra)
Date: Tue, 17 May 2016 10:06:22 +0200
Subject: [PATCH 2/2] ARM: dts: igep0020: Add SD card write-protect pin.
In-Reply-To: <20160513123718.GA2841@localhost.localdomain>
References: <1462568554-7868-1-git-send-email-enric.balletbo@collabora.com>
 <1462568554-7868-2-git-send-email-enric.balletbo@collabora.com>
 <20160513123718.GA2841@localhost.localdomain>
Message-ID: <CAFqH_535Zd8etbAjrSq_fj73p9cJFzqOqbcbH3UcnpfjNy7efw@mail.gmail.com>

Hi Ladislav,

2016-05-13 14:37 GMT+02:00 Ladislav Michl <ladis at linux-mips.org>:
> Hi Enric!
>
> On Fri, May 06, 2016 at 11:02:34PM +0200, Enric Balletbo i Serra wrote:
>> A host device that supports write protection should refuse to write to
>> an SD card that is designated read-only when write-protect is set. This
>> is an optional feature of the SD specification.
>
> Does it ever work on any IGEPv2? I have similar patch in my repo and there
> is no difference when enabling write protection on SD card. Also schemantics
> shows GPIO29 constantly pulled up with a resistor. Is there any board
> revision with working WP? I'm just curious as patch is of course correct.
>

Note that the microSD formats do not support a write protection
switch, a host device that supports write protection should refuse to
write to an SD card that is designated read-only in this way, which is
an optional feature of the SD specification. As far as I know there is
only a use case for the IGEPv2, the TP close to the SD card can be
used as a write-protection switch, this is not an usual use case and
of course, this needs some wiring, but it's a feature used by someone.

> Best regards,
>         ladis
>
>> Signed-off-by: Enric Balletbo i Serra <enric.balletbo at collabora.com>
>> ---
>>  arch/arm/boot/dts/omap3-igep0020-common.dtsi | 11 +++++++++++
>>  1 file changed, 11 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/omap3-igep0020-common.dtsi b/arch/arm/boot/dts/omap3-igep0020-common.dtsi
>> index d6f839c..b697106 100644
>> --- a/arch/arm/boot/dts/omap3-igep0020-common.dtsi
>> +++ b/arch/arm/boot/dts/omap3-igep0020-common.dtsi
>> @@ -194,6 +194,12 @@
>>                       OMAP3630_CORE2_IOPAD(0x25f8, PIN_OUTPUT | MUX_MODE4) /* etk_d14.gpio_28 */
>>               >;
>>       };
>> +
>> +     mmc1_wp_pins: pinmux_mmc1_cd_pins {
>> +             pinctrl-single,pins = <
>> +                     OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT | MUX_MODE4)   /* etk_d15.gpio_29 */
>> +             >;
>> +     };
>>  };
>>
>>  &i2c3 {
>> @@ -250,3 +256,8 @@
>>               };
>>       };
>>  };
>> +
>> +&mmc1 {
>> +     pinctrl-0 = <&mmc1_pins &mmc1_wp_pins>;
>> +     wp-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>; /* gpio_29 */
>> +};


From marc.zyngier at arm.com  Tue May 17 01:06:54 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 17 May 2016 09:06:54 +0100
Subject: [PATCH v15 00/20] arm64 kexec kernel patches v15
In-Reply-To: <20160517054216.GA12543@dhcp-128-65.nay.redhat.com>
References: <cover.1457977401.git.geoff@infradead.org>
 <20160401015947.GA3835@dhcp-128-65.nay.redhat.com>
 <1459535954.20121.3.camel@infradead.org>
 <20160517054216.GA12543@dhcp-128-65.nay.redhat.com>
Message-ID: <573AD11E.1030301@arm.com>

Hi Dave,

On 17/05/16 06:42, Dave Young wrote:
> Marc, it has been discussed for long time, I think kdump code can be
> logically splitted from this series so that we can get the kexec
> done first? 

The basis for kexec are already on their way to mainline, as part of the
hibernate series that James has put together.

I'd expect someone to:

1) rebase the remaining kexec/kdump patches based on the current
arm64/for-next/core,
2) post these patches when -rc1 gets cut in two weeks from now,
3) address the review comments in a timely manner,
4) update the series once a week so that we see some actual progress

If this happens, I can't see any reason why this code wouldn't get
merged. But keeping kexec and kdump together is not what has prevented
the code from getting merged until now.

Thanks,

	M.
> 
> On 04/01/16 at 11:39am, Geoff Levand wrote:
>> Hi,
>>
>> On Fri, 2016-04-01 at 09:59 +0800, Dave Young wrote:
>>> Geoff, for easier to review maybe you can send kexec patches first
>>> then AKASHI Takahiro
>>> can send the kdump patches as a standalone patchset?
>>
>> Marc Zyngier specifically asked for an integrated set
>> of patches for easier review.  I will keep it that way
>> for now.
>>
>> -Geoff
> 


-- 
Jazz is not dead. It just smells funny...


From tn at semihalf.com  Tue May 17 01:07:30 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 17 May 2016 10:07:30 +0200
Subject: [RFC PATCH 09/11] drivers: acpi: implement acpi_dma_configure
In-Reply-To: <1460654743-7896-10-git-send-email-lorenzo.pieralisi@arm.com>
References: <1460654743-7896-1-git-send-email-lorenzo.pieralisi@arm.com>
 <1460654743-7896-10-git-send-email-lorenzo.pieralisi@arm.com>
Message-ID: <573AD142.6020107@semihalf.com>

Hi Lorenzo,

On 14.04.2016 19:25, Lorenzo Pieralisi wrote:
> On DT based systems, the of_dma_configure() API implements DMA configuration
> for a given device. On ACPI systems an API equivalent to of_dma_configure()
> is missing which implies that it is currently not possible to set-up DMA
> operations for devices through the ACPI generic kernel layer.
>
> This patch fills the gap by introducing acpi_dma_configure/deconfigure()
> calls, that carry out IOMMU configuration through IORT (on systems where
> it is present) and call arch_setup_dma_ops(...) with the retrieved
> parameters.
>
> The DMA range size passed to arch_setup_dma_ops() is sized according
> to the device coherent_dma_mask (starting at address 0x0), mirroring the
> DT probing path behaviour when a dma-ranges property is not provided
> for the device being probed; this changes the current arch_setup_dma_ops()
> call parameters in the ACPI probing case, but since arch_setup_dma_ops()
> is a NOP on all architectures but ARM/ARM64 this patch does not change
> the current kernel behaviour on them.
>
> This patch updates ACPI and PCI core code to use the newly introduced
> acpi_dma_configure function, providing the same functionality
> as of_dma_configure on ARM systems and leaving behaviour unchanged
> for all other arches.
>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
> Cc: Bjorn Helgaas <bhelgaas at google.com>
> Cc: Robin Murphy <robin.murphy at arm.com>
> Cc: Tomasz Nowicki <tn at semihalf.com>
> Cc: Joerg Roedel <joro at 8bytes.org>
> Cc: "Rafael J. Wysocki" <rjw at rjwysocki.net>
> ---
>   drivers/acpi/glue.c     |  4 +--
>   drivers/acpi/iort.c     | 85 +++++++++++++++++++++++++++++++++++++++++++++++++
>   drivers/acpi/scan.c     | 29 +++++++++++++++++
>   drivers/pci/probe.c     |  3 +-
>   include/acpi/acpi_bus.h |  2 ++
>   include/linux/acpi.h    |  5 +++
>   include/linux/iort.h    |  9 ++++++
>   7 files changed, 133 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
> index 5ea5dc2..f8d6564 100644
> --- a/drivers/acpi/glue.c
> +++ b/drivers/acpi/glue.c
> @@ -227,8 +227,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
>
>   	attr = acpi_get_dma_attr(acpi_dev);
>   	if (attr != DEV_DMA_NOT_SUPPORTED)
> -		arch_setup_dma_ops(dev, 0, 0, NULL,
> -				   attr == DEV_DMA_COHERENT);
> +		acpi_dma_configure(dev, attr);
>
>   	acpi_physnode_link_name(physical_node_name, node_id);
>   	retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
> @@ -251,6 +250,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
>   	return 0;
>
>    err:
> +	acpi_dma_deconfigure(dev);
>   	ACPI_COMPANION_SET(dev, NULL);
>   	put_device(dev);
>   	put_device(&acpi_dev->dev);
> diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
> index 2b5ce65..b1bb8fb 100644
> --- a/drivers/acpi/iort.c
> +++ b/drivers/acpi/iort.c
> @@ -72,6 +72,31 @@ int iort_iommu_set_node(struct iommu_ops *ops, struct acpi_iort_node *node,
>   	return 0;
>   }
>
> +/**
> + * iort_iommu_get_node - Retrieve iort_iommu_node associated with an IORT node.
> + *
> + * @node: IORT table node to be looked-up
> + *
> + * Returns: iort_iommu_node pointer on success
> + *          NULL on failure
> + */
> +static struct iort_iommu_node *iort_iommu_get_node(struct acpi_iort_node *node)
> +{
> +	struct iort_iommu_node *iommu_node;
> +
> +	spin_lock(&iort_iommu_lock);
> +	list_for_each_entry(iommu_node, &iort_iommu_list, list) {
> +		if (iommu_node->node == node)
> +			goto found;
> +	}
> +
> +	iommu_node = NULL;
> +found:
> +	spin_unlock(&iort_iommu_lock);
> +
> +	return iommu_node;
> +}
> +
>   typedef acpi_status (*iort_find_node_callback)
>   	(struct acpi_iort_node *node, void *context);
>
> @@ -405,6 +430,66 @@ iort_pci_get_domain(struct pci_dev *pdev, u32 req_id)
>   	return domain_handle;
>   }
>
> +static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
> +{
> +	u32 *rid = data;
> +
> +	*rid = alias;
> +	return 0;
> +}
> +
> +/**
> + * iort_iommu_configure - Set-up IOMMU configuration for a device.
> + *
> + * @dev: device that requires IOMMU set-up
> + *
> + * Returns: iommu_ops pointer on configuration success
> + *          NULL on configuration failure
> + */
> +struct iommu_ops *iort_iommu_configure(struct device *dev)
> +{
> +	struct acpi_iort_node *node, *parent;
> +	struct iommu_ops *ops = NULL;
> +	struct iommu_fwspec fwspec;
> +	struct iort_iommu_node *iommu_node;
> +	u32 rid = 0, devid = 0;
> +
> +	if (dev_is_pci(dev)) {
> +		struct pci_bus *bus = to_pci_dev(dev)->bus;
> +
> +		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
> +				       &rid);
> +
> +		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
> +				      iort_find_dev_callback, &bus->dev);
> +	} else
> +		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
> +				      iort_find_dev_callback, dev);

I think this will not work for finding host bridge stream ID. We still 
need to use ACPI_IORT_NODE_PCI_ROOT_COMPLEX but 'dev' is not PCI device, 
right?

Thanks,
Tomasz


From tomi.valkeinen at ti.com  Tue May 17 01:07:47 2016
From: tomi.valkeinen at ti.com (Tomi Valkeinen)
Date: Tue, 17 May 2016 11:07:47 +0300
Subject: More build fixes for omapdrm in current -next
In-Reply-To: <1462982509-342936-1-git-send-email-arnd@arndb.de>
References: <1462982509-342936-1-git-send-email-arnd@arndb.de>
Message-ID: <573AD153.4060200@ti.com>

On 11/05/16 19:01, Arnd Bergmann wrote:
> A couple more errors showed up in linux-next in the last few
> days, all because of missing header files. I have not seen these
> before, and most configurations appear to be fine. There
> must have been an implicit inclusion somewhere before that
> just got removed, but I couldn't find it and doing the
> explicit #include should always be better here.

Thanks. I picked the first one as is, and third one with some conflict
resolutions. A patch similar to the second one was already queued.

 Tomi

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160517/6a3a8145/attachment.sig>

From wens at csie.org  Tue May 17 01:50:30 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 16:50:30 +0800
Subject: [PATCH 1/4] ARM: dts: axp22x.dtsi: Disable axp22x ldo_io#
 regulators by default
In-Reply-To: <1463248650-16611-1-git-send-email-hdegoede@redhat.com>
References: <1463248650-16611-1-git-send-email-hdegoede@redhat.com>
Message-ID: <CAGb2v66em6Zm8JyRn0kfcfhb8hY+5vGd-mQSgH7dBq=Ghv9MKw@mail.gmail.com>

On Sun, May 15, 2016 at 1:57 AM, Hans de Goede <hdegoede at redhat.com> wrote:
> Use of these as regulators conflicts with use of the gpio pins as
> gpios, so disabled the ldo_io# regulators by default, this avoids
> the regulator core touching them when the pins are used as gpios.
>
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>

Acked-by: Chen-Yu Tsai <wens at csie.org>


From shijie.huang at arm.com  Tue May 17 01:58:09 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Tue, 17 May 2016 16:58:09 +0800
Subject: [PATCH v12 05/10] arm64: Kprobes with single stepping support
In-Reply-To: <1461783185-9056-6-git-send-email-dave.long@linaro.org>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-6-git-send-email-dave.long@linaro.org>
Message-ID: <20160517085807.GA842@sha-win-210.asiapac.arm.com>

On Wed, Apr 27, 2016 at 02:53:00PM -0400, David Long wrote:
> +
> +/*
> + * Interrupts need to be disabled before single-step mode is set, and not
> + * reenabled until after single-step mode ends.
> + * Without disabling interrupt on local CPU, there is a chance of
> + * interrupt occurrence in the period of exception return and  start of
> + * out-of-line single-step, that result in wrongly single stepping
> + * into the interrupt handler.
> + */
> +static void __kprobes kprobes_save_local_irqflag(struct pt_regs *regs)
> +{
> +     struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();

Why not add a parameter for this function to save the @kcb?

> +
> +     kcb->saved_irqflag = regs->pstate;
> +     regs->pstate |= PSR_I_BIT;
> +}
> +
> +static void __kprobes kprobes_restore_local_irqflag(struct pt_regs *regs)
> +{
> +     struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
ditto.

> +
> +     if (kcb->saved_irqflag & PSR_I_BIT)
> +             regs->pstate |= PSR_I_BIT;
> +     else
> +             regs->pstate &= ~PSR_I_BIT;
> +}
> +
> +static void __kprobes
> +set_ss_context(struct kprobe_ctlblk *kcb, unsigned long addr)
> +{
> +     kcb->ss_ctx.ss_pending = true;
> +     kcb->ss_ctx.match_addr = addr + sizeof(kprobe_opcode_t);
> +}
> +
> +static void __kprobes clear_ss_context(struct kprobe_ctlblk *kcb)
> +{
> +     kcb->ss_ctx.ss_pending = false;
> +     kcb->ss_ctx.match_addr = 0;
> +}
> +
> +static void __kprobes setup_singlestep(struct kprobe *p,
> +                                    struct pt_regs *regs,
> +                                    struct kprobe_ctlblk *kcb, int reenter)
> +{
> +     unsigned long slot;
> +
> +     if (reenter) {
> +             save_previous_kprobe(kcb);
> +             set_current_kprobe(p);
> +             kcb->kprobe_status = KPROBE_REENTER;
> +     } else {
> +             kcb->kprobe_status = KPROBE_HIT_SS;
> +     }
> +
> +     if (p->ainsn.insn) {
> +             /* prepare for single stepping */
> +             slot = (unsigned long)p->ainsn.insn;
> +
> +             set_ss_context(kcb, slot);      /* mark pending ss */
> +
> +             if (kcb->kprobe_status == KPROBE_REENTER)
> +                     spsr_set_debug_flag(regs, 0);
> +
> +             /* IRQs and single stepping do not mix well. */
> +             kprobes_save_local_irqflag(regs);
> +             kernel_enable_single_step(regs);
> +             instruction_pointer(regs) = slot;
> +     } else  {
> +             BUG();
> +     }
> +}
> +
> +static int __kprobes reenter_kprobe(struct kprobe *p,
> +                                 struct pt_regs *regs,
> +                                 struct kprobe_ctlblk *kcb)
> +{
> +     switch (kcb->kprobe_status) {
> +     case KPROBE_HIT_SSDONE:
> +     case KPROBE_HIT_ACTIVE:
> +             kprobes_inc_nmissed_count(p);
> +             setup_singlestep(p, regs, kcb, 1);
> +             break;
> +     case KPROBE_HIT_SS:
> +     case KPROBE_REENTER:
> +             pr_warn("Unrecoverable kprobe detected at %p.\n", p->addr);
> +             dump_kprobe(p);
> +             BUG();
> +             break;
> +     default:
> +             WARN_ON(1);
> +             return 0;
> +     }
> +
> +     return 1;
> +}
> +
> +static void __kprobes
> +post_kprobe_handler(struct kprobe_ctlblk *kcb, struct pt_regs *regs)
> +{
> +     struct kprobe *cur = kprobe_running();
> +
> +     if (!cur)
> +             return;
> +
> +     /* return addr restore if non-branching insn */
> +     if (cur->ainsn.restore.type == RESTORE_PC) {
> +             instruction_pointer(regs) = cur->ainsn.restore.addr;
> +             if (!instruction_pointer(regs))
> +                     BUG();
> +     }
> +
> +     /* restore back original saved kprobe variables and continue */
> +     if (kcb->kprobe_status == KPROBE_REENTER) {
> +             restore_previous_kprobe(kcb);
> +             return;
> +     }
> +     /* call post handler */
> +     kcb->kprobe_status = KPROBE_HIT_SSDONE;
> +     if (cur->post_handler)  {
> +             /* post_handler can hit breakpoint and single step
> +              * again, so we enable D-flag for recursive exception.
> +              */
> +             cur->post_handler(cur, regs, 0);
> +     }
> +
> +     reset_current_kprobe();
> +}
> +
> +int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
> +{
> +     struct kprobe *cur = kprobe_running();
> +     struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
> +
> +     switch (kcb->kprobe_status) {
> +     case KPROBE_HIT_SS:
> +     case KPROBE_REENTER:
> +             /*
> +              * We are here because the instruction being single
> +              * stepped caused a page fault. We reset the current
> +              * kprobe and the ip points back to the probe address
> +              * and allow the page fault handler to continue as a
> +              * normal page fault.
> +              */
> +             instruction_pointer(regs) = (unsigned long)cur->addr;
> +             if (!instruction_pointer(regs))
> +                     BUG();
> +             if (kcb->kprobe_status == KPROBE_REENTER)
> +                     restore_previous_kprobe(kcb);
> +             else
> +                     reset_current_kprobe();
> +
> +             break;
> +     case KPROBE_HIT_ACTIVE:
> +     case KPROBE_HIT_SSDONE:
> +             /*
> +              * We increment the nmissed count for accounting,
> +              * we can also use npre/npostfault count for accounting
> +              * these specific fault cases.
> +              */
> +             kprobes_inc_nmissed_count(cur);
> +
> +             /*
> +              * We come here because instructions in the pre/post
> +              * handler caused the page_fault, this could happen
> +              * if handler tries to access user space by
> +              * copy_from_user(), get_user() etc. Let the
> +              * user-specified handler try to fix it first.
> +              */
> +             if (cur->fault_handler && cur->fault_handler(cur, regs, fsr))
> +                     return 1;
> +
> +             /*
> +              * In case the user-specified fault handler returned
> +              * zero, try to fix up.
> +              */
> +             if (fixup_exception(regs))
> +                     return 1;
> +     }
> +     return 0;
> +}
> +
> +int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
> +                                    unsigned long val, void *data)
> +{
> +     return NOTIFY_DONE;
> +}
> +
> +static void __kprobes kprobe_handler(struct pt_regs *regs)
> +{
> +     struct kprobe *p, *cur_kprobe;
> +     struct kprobe_ctlblk *kcb;
> +     unsigned long addr = instruction_pointer(regs);
> +
> +     kcb = get_kprobe_ctlblk();
> +     cur_kprobe = kprobe_running();
> +
> +     p = get_kprobe((kprobe_opcode_t *) addr);
> +
> +     if (p) {
> +             if (cur_kprobe) {
> +                     if (reenter_kprobe(p, regs, kcb))
> +                             return;
> +             } else {
> +                     /* Probe hit */
> +                     set_current_kprobe(p);
> +                     kcb->kprobe_status = KPROBE_HIT_ACTIVE;
> +
> +                     /*
> +                      * If we have no pre-handler or it returned 0, we
> +                      * continue with normal processing.  If we have a
> +                      * pre-handler and it returned non-zero, it prepped
> +                      * for calling the break_handler below on re-entry,
> +                      * so get out doing nothing more here.
> +                      *
> +                      * pre_handler can hit a breakpoint and can step thru
> +                      * before return, keep PSTATE D-flag enabled until
> +                      * pre_handler return back.
> +                      */
> +                     if (!p->pre_handler || !p->pre_handler(p, regs)) {
> +                             kcb->kprobe_status = KPROBE_HIT_SS;
The above line is duplicated.
You will set KPROBE_HIT_SS in the setup_singlestep.

> +                             setup_singlestep(p, regs, kcb, 0);
> +                             return;
> +                     }
> +             }
> +     } else if ((le32_to_cpu(*(kprobe_opcode_t *) addr) ==
> +         BRK64_OPCODE_KPROBES) && cur_kprobe) {
> +             /* We probably hit a jprobe.  Call its break handler. */
> +             if (cur_kprobe->break_handler  &&
> +                  cur_kprobe->break_handler(cur_kprobe, regs)) {
> +                     kcb->kprobe_status = KPROBE_HIT_SS;
ditto
> +                     setup_singlestep(cur_kprobe, regs, kcb, 0);
> +                     return;
> +             }
> +     }
> +     /*
> +      * The breakpoint instruction was removed right
> +      * after we hit it.  Another cpu has removed
> +      * either a probepoint or a debugger breakpoint
> +      * at this address.  In either case, no further
> +      * handling of this interrupt is appropriate.
> +      * Return back to original instruction, and continue.
> +      */
> +}
thanks
Huang Shijie
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.



From takahiro.akashi at linaro.org  Tue May 17 02:07:53 2016
From: takahiro.akashi at linaro.org (AKASHI Takahiro)
Date: Tue, 17 May 2016 18:07:53 +0900
Subject: [PATCH v15 00/20] arm64 kexec kernel patches v15
In-Reply-To: <573AD11E.1030301@arm.com>
References: <cover.1457977401.git.geoff@infradead.org>
 <20160401015947.GA3835@dhcp-128-65.nay.redhat.com>
 <1459535954.20121.3.camel@infradead.org>
 <20160517054216.GA12543@dhcp-128-65.nay.redhat.com>
 <573AD11E.1030301@arm.com>
Message-ID: <20160517090602.GA31879@linaro.org>

Marc, Dave

On Tue, May 17, 2016 at 09:06:54AM +0100, Marc Zyngier wrote:
> Hi Dave,
> 
> On 17/05/16 06:42, Dave Young wrote:
> > Marc, it has been discussed for long time, I think kdump code can be
> > logically splitted from this series so that we can get the kexec
> > done first? 
> 
> The basis for kexec are already on their way to mainline, as part of the
> hibernate series that James has put together.
> 
> I'd expect someone to:
> 
> 1) rebase the remaining kexec/kdump patches based on the current
> arm64/for-next/core,

Done. At the time of last week.
The only issue that I have now is a support for KASLR, but this is not
a kernel issue, but tool's. I'm now talking with Dave Anderson (RedHat)
about how we should fix it.

> 2) post these patches when -rc1 gets cut in two weeks from now,

Yes, we are planning to do so.

> 3) address the review comments in a timely manner,

I'd like to expect the code to be reviewed in a timely manner, too.
In v4.6, we have not got any comments (nor ack's) on kexec/kdump-specific
part of patches. If this happens again, it will make the turnaround of our
re-spinning even longer.

> 4) update the series once a week so that we see some actual progress

Yes if we have updates.

> If this happens, I can't see any reason why this code wouldn't get
> merged. But keeping kexec and kdump together is not what has prevented
> the code from getting merged until now.

Yeah, agree.

Thanks,
-Takahiro AKASHI

> 
> Thanks,
> 
> 	M.
> > 
> > On 04/01/16 at 11:39am, Geoff Levand wrote:
> >> Hi,
> >>
> >> On Fri, 2016-04-01 at 09:59 +0800, Dave Young wrote:
> >>> Geoff, for easier to review maybe you can send kexec patches first
> >>> then AKASHI Takahiro
> >>> can send the kdump patches as a standalone patchset?
> >>
> >> Marc Zyngier specifically asked for an integrated set
> >> of patches for easier review.  I will keep it that way
> >> for now.
> >>
> >> -Geoff
> > 
> 
> 
> -- 
> Jazz is not dead. It just smells funny...


From shijie.huang at arm.com  Tue May 17 02:10:12 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Tue, 17 May 2016 17:10:12 +0800
Subject: [PATCH v12 05/10] arm64: Kprobes with single stepping support
In-Reply-To: <1461783185-9056-6-git-send-email-dave.long@linaro.org>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-6-git-send-email-dave.long@linaro.org>
Message-ID: <20160517091009.GA5082@sha-win-210.asiapac.arm.com>

On Wed, Apr 27, 2016 at 02:53:00PM -0400, David Long wrote:
> From: Sandeepa Prabhu <sandeepa.s.prabhu at gmail.com>
> +
> +static bool __kprobes aarch64_insn_is_steppable(u32 insn)

Could we add more comment for this function? In the comment, we can tell
that which type of instructions are steppable, which are not.

> +{
> +	if (aarch64_get_insn_class(insn) == AARCH64_INSN_CLS_BR_SYS) {
> +		if (aarch64_insn_is_branch(insn) ||
> +		    aarch64_insn_is_msr_imm(insn) ||
> +		    aarch64_insn_is_msr_reg(insn) ||
> +		    aarch64_insn_is_exception(insn))
> +			return false;
> +
> +		if (aarch64_insn_is_mrs(insn))
> +			return aarch64_insn_extract_system_reg(insn)
> +			     != AARCH64_INSN_SPCLREG_DAIF;
> +
> +		if (aarch64_insn_is_hint(insn))
> +			return aarch64_insn_is_nop(insn);
> +
> +		return true;
> +	}
> +
> +	if (aarch64_insn_uses_literal(insn) ||
> +	    aarch64_insn_is_exclusive(insn))
> +		return false;
> +
> +	return true;

Thanks
Huang Shijie



From boris.brezillon at free-electrons.com  Tue May 17 02:12:32 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 17 May 2016 11:12:32 +0200
Subject: [PATCH] pwm: atmel-hlcdc: Fix default PWM polarity
Message-ID: <1463476352-7485-1-git-send-email-boris.brezillon@free-electrons.com>

The PWM device exposed by the HLCDC IP is configured with an inverted
polarity by default. Registering the PWM chip with the normal polarity
was not a problem before commit 42e8992c58d4 ("pwm: Add core
infrastructure to allow atomic updates") because the ->set_polarity()
hook was called no matter the current polarity state, but this is no longer
the case.

Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
Fixes: 42e8992c58d4 ("pwm: Add core infrastructure to allow atomic updates")
---
 drivers/pwm/pwm-atmel-hlcdc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c
index f994c7e..14fc011 100644
--- a/drivers/pwm/pwm-atmel-hlcdc.c
+++ b/drivers/pwm/pwm-atmel-hlcdc.c
@@ -272,7 +272,7 @@ static int atmel_hlcdc_pwm_probe(struct platform_device *pdev)
 	chip->chip.of_pwm_n_cells = 3;
 	chip->chip.can_sleep = 1;
 
-	ret = pwmchip_add(&chip->chip);
+	ret = pwmchip_add_with_polarity(&chip->chip, PWM_POLARITY_INVERSED);
 	if (ret) {
 		clk_disable_unprepare(hlcdc->periph_clk);
 		return ret;
-- 
2.7.4



From nicolas.ferre at atmel.com  Tue May 17 02:14:45 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Tue, 17 May 2016 11:14:45 +0200
Subject: [PATCH v4 12/18] arm: use of_platform_default_populate() to
 populate
In-Reply-To: <1463054775-18170-13-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463054775-18170-13-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <573AE105.7080200@atmel.com>

Le 12/05/2016 14:06, Kefeng Wang a ?crit :
> Use helper of_platform_default_populate() in linux/of_platform
> when possible, instead of calling of_platform_populate() with
> the default match table.
> 
> Cc: Nicolas Ferre <nicolas.ferre at atmel.com>
> Cc: Krzysztof Halasa <khalasa at piap.pl>
> Cc: Sekhar Nori <nsekhar at ti.com>
> Cc: Shawn Guo <shawnguo at kernel.org>
> Cc: Russell King <linux at arm.linux.org.uk>
> Cc: Roland Stigge <stigge at antcom.de>
> Cc: Jason Cooper <jason at lakedaemon.net>
> Cc: Ray Jui <rjui at broadcom.com>
> Cc: Viresh Kumar <vireshk at kernel.org>
> Cc: Stephen Warren <swarren at wwwdotorg.org>
> Cc: Rob Herring <robh at kernel.org>
> Cc: Michal Simek <michal.simek at xilinx.com>
> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> ---
>  arch/arm/mach-at91/at91rm9200.c          | 2 +-
>  arch/arm/mach-at91/at91sam9.c            | 2 +-
>  arch/arm/mach-at91/sama5.c               | 2 +-

Acked-by: Nicolas Ferre <nicolas.ferre at atmel.com>

Best regards,
-- 
Nicolas Ferre


From shijie.huang at arm.com  Tue May 17 02:14:47 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Tue, 17 May 2016 17:14:47 +0800
Subject: [PATCH v12 01/10] arm64: Add HAVE_REGS_AND_STACK_ACCESS_API
 feature
In-Reply-To: <1461783185-9056-2-git-send-email-dave.long@linaro.org>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-2-git-send-email-dave.long@linaro.org>
Message-ID: <20160517091446.GB5082@sha-win-210.asiapac.arm.com>

On Wed, Apr 27, 2016 at 02:52:56PM -0400, David Long wrote:
> From: "David A. Long" <dave.long at linaro.org>
> +/**
> + * regs_within_kernel_stack() - check the address in the stack
> + * @regs:      pt_regs which contains kernel stack pointer.
> + * @addr:      address which is checked.
> + *
> + * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
> + * If @addr is within the kernel stack, it returns true. If not, returns false.
> + */
> +bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
> +{
> +	return ((addr & ~(THREAD_SIZE - 1))  ==
> +		(kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))) ||
> +		on_irq_stack(addr, raw_smp_processor_id());
> +}
> +
> +/**
> + * regs_get_kernel_stack_nth() - get Nth entry of the stack
> + * @regs:	pt_regs which contains kernel stack pointer.
> + * @n:		stack entry number.
> + *
> + * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
> + * is specified by @regs. If the @n th entry is NOT in the kernel stack,
> + * this returns 0.
> + */
> +unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
> +{
> +	unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
> +
> +	addr += n;
> +	if (regs_within_kernel_stack(regs, (unsigned long)addr))
If the @addr fall in the interrupt stack, the regs_within_kernel_stack()
will return true. But Is it what we want?

thanks
Huang Shijie



From mcoquelin.stm32 at gmail.com  Tue May 17 02:20:16 2016
From: mcoquelin.stm32 at gmail.com (Maxime Coquelin)
Date: Tue, 17 May 2016 11:20:16 +0200
Subject: [RESEND PATCH v6 0/6] Add Ethernet support on STM32F429
In-Reply-To: <20160509.150634.213732321950308841.davem@davemloft.net>
References: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
 <20160509.150634.213732321950308841.davem@davemloft.net>
Message-ID: <CALszF6Cfs02-tGvFqpyJpUy7jSfjGTY8fVaaLQ8iQaGfCxvDtQ@mail.gmail.com>

Hi David,

2016-05-09 21:06 GMT+02:00 David Miller <davem at davemloft.net>:
> From: Alexandre TORGUE <alexandre.torgue at gmail.com>
> Date: Mon,  9 May 2016 12:31:33 +0200
>
>> STM32F429 Chip embeds a Synopsys 3.50a MAC IP.
>> This series:
>>  -enhance current stmmac driver to control it (code already
>> available) and adds basic glue for STM32F429 chip.
>>  -Enable basic Net config in kernel.
>
> I assume this will go via the ARM tree, for the networking bits:
I would expect patches 1, 2 & 3 to got via your tree, to avoid conflicts.

> Acked-by: David S. Miller <davem at davemloft.net>

Thanks,
Maxime


From mcoquelin.stm32 at gmail.com  Tue May 17 02:48:08 2016
From: mcoquelin.stm32 at gmail.com (Maxime Coquelin)
Date: Tue, 17 May 2016 11:48:08 +0200
Subject: [PATCH 2/5] i2c: Add STM32F4 I2C driver
In-Reply-To: <1462980974-22091-3-git-send-email-cedric.madianga@gmail.com>
References: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
 <1462980974-22091-3-git-send-email-cedric.madianga@gmail.com>
Message-ID: <CALszF6A-jiCBtSO1RFDdgHKTKmsonRXFVs0x2zHha1LJ3UhwtQ@mail.gmail.com>

Hi Cedric,

2016-05-11 17:36 GMT+02:00 M'boumba Cedric Madianga <cedric.madianga at gmail.com>:
> This patch adds support for the STM32F4 I2C controller.
>
> Signed-off-by: M'boumba Cedric Madianga <cedric.madianga at gmail.com>
> ---
>  drivers/i2c/busses/Kconfig       |  10 +
>  drivers/i2c/busses/Makefile      |   1 +
>  drivers/i2c/busses/i2c-stm32f4.c | 872 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 883 insertions(+)
>  create mode 100644 drivers/i2c/busses/i2c-stm32f4.c
>
...
> diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c
> new file mode 100644
> index 0000000..4692213
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-stm32f4.c
...
> +enum stm32f4_i2c_speed {
> +       STM32F4_I2C_SPEED_STANDARD, /* 100 kHz */
> +       STM32F4_I2C_SPEED_FAST, /* 400 kHz */
> +       STM32F4_I2C_SPEED_END,
> +};
> +
> +/**
> + * struct stm32f4_i2c_timings - per-Mode tuning parameters
> + * @rate: I2C bus rate
> + * @duty: Fast mode duty cycle
> + */
> +struct stm32f4_i2c_timings {
> +       u32 rate;
> +       u32 duty;
> +};
...
> +/**
> + * struct stm32f4_i2c_dev - private data of the controller
> + * @adap: I2C adapter for this controller
> + * @dev: device for this controller
> + * @base: virtual memory area
> + * @complete: completion of I2C message
> + * @irq_event: interrupt event line for the controller
> + * @irq_error: interrupt error line for the controller
> + * @clk: hw i2c clock
> + * speed: I2C clock frequency of the controller. Standard or Fast only supported
> + * @client: I2C transfer information
> + * @busy: I2C transfer on-going
> + * @rst: I2C reset line
> + */
> +struct stm32f4_i2c_dev {
> +       struct i2c_adapter              adap;
> +       struct device                   *dev;
> +       void __iomem                    *base;
> +       struct completion               complete;
> +       int                             irq_event;
> +       int                             irq_error;
> +       struct clk                      *clk;
> +       int                             speed;
> +       struct stm32f4_i2c_client       client;
> +       bool                            busy;
> +       struct reset_control            *rst;
> +};
> +
> +static struct stm32f4_i2c_timings i2c_timings[] = {
> +       [STM32F4_I2C_SPEED_STANDARD] = {
> +               .rate                   = 100000,
> +               .duty                   = 0,
> +       },
> +       [STM32F4_I2C_SPEED_FAST] = {
> +               .rate                   = 400000,
> +               .duty                   = 0,
> +       },
> +};
Is this table really needed?
As duty value seems to always be 0, couldn't you just store the rate
in the speed field?


> +static void stm32f4_i2c_set_rise_time(struct stm32f4_i2c_dev *i2c_dev)
> +{
> +       u32 trise, freq, cr2;
> +
> +       cr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
> +       freq = cr2 & STM32F4_I2C_CR2_FREQ_MASK;
> +
> +       trise = readl_relaxed(i2c_dev->base + STM32F4_I2C_TRISE);
> +       trise &= ~STM32F4_I2C_TRISE_TRISE_MASK;
> +
> +       if (i2c_dev->speed == STM32F4_I2C_SPEED_STANDARD)
> +               trise |= STM32F4_I2C_TRISE_TRISE((freq + 1));
> +       else
> +               trise |= STM32F4_I2C_TRISE_TRISE((((freq * 300) / 1000) + 1));
Or if you keep the timings struct, maybe the rise time should be part of it.
Doing, that, you will avoid the if/else

> +
> +       writel_relaxed(trise, i2c_dev->base + STM32F4_I2C_TRISE);
> +}
> +
> +static void stm32f4_i2c_set_speed_mode(struct stm32f4_i2c_dev *i2c_dev)
> +{
> +       struct stm32f4_i2c_timings *t = &i2c_timings[i2c_dev->speed];
> +       u32 ccr, val, clk_rate;
> +
> +       ccr = readl_relaxed(i2c_dev->base + STM32F4_I2C_CCR);
> +       ccr &= ~(STM32F4_I2C_CCR_FS | STM32F4_I2C_CCR_DUTY |
> +                STM32F4_I2C_CCR_CCR_MASK);
> +
> +       clk_rate = clk_get_rate(i2c_dev->clk);
> +
> +       switch (i2c_dev->speed) {
> +       case STM32F4_I2C_SPEED_STANDARD:
> +               val = clk_rate / t->rate * 2;
> +               if (val < STM32F4_I2C_MIN_CCR)
> +                       ccr |= STM32F4_I2C_CCR_CCR(STM32F4_I2C_MIN_CCR);
> +               else
> +                       ccr |= STM32F4_I2C_CCR_CCR(val);
> +               break;
> +       case STM32F4_I2C_SPEED_FAST:
> +               ccr |= STM32F4_I2C_CCR_FS;
> +               if (t->duty) {
> +                       ccr |= STM32F4_I2C_CCR_DUTY;
> +                       ccr |= STM32F4_I2C_CCR_CCR(clk_rate / t->rate * 25);
> +               } else {
> +                       ccr |= STM32F4_I2C_CCR_CCR(clk_rate / t->rate * 3);
> +               }
Is it really useful since duty seems to always be 0?

> +               break;
> +       default:
> +               dev_err(i2c_dev->dev, "I2C speed mode not supported\n");
> +       }
> +
> +       writel_relaxed(ccr, i2c_dev->base + STM32F4_I2C_CCR);
> +}
> +
> +static void stm32f4_i2c_set_filter(struct stm32f4_i2c_dev *i2c_dev)
> +{
> +       u32 filter;
> +
> +       /* Enable analog noise filter and disable digital noise filter */
Maybe a stupid question, but is it always what we want?
Are there some cases we would prefer to use the digital noise filter
instead of the analog one?

> +       filter = readl_relaxed(i2c_dev->base + STM32F4_I2C_FLTR);
> +       filter &= ~(STM32F4_I2C_FLTR_ANOFF | STM32F4_I2C_FLTR_DNF_MASK);
> +       writel_relaxed(filter, i2c_dev->base + STM32F4_I2C_FLTR);
> +}
> +
> +/**
> + * stm32f4_i2c_hw_config() - Prepare I2C block
> + * @i2c_dev: Controller's private data
> + */
> +static void stm32f4_i2c_hw_config(struct stm32f4_i2c_dev *i2c_dev)
> +{
> +       void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
> +
> +       /* Disable I2C */
> +       stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_PE);
> +
> +       stm32f4_i2c_set_periph_clk_freq(i2c_dev);
> +
> +       stm32f4_i2c_set_rise_time(i2c_dev);
> +
> +       stm32f4_i2c_set_speed_mode(i2c_dev);
> +
> +       stm32f4_i2c_set_filter(i2c_dev);
> +
> +       /* Enable I2C */
> +       stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_PE);
> +}
> +
> +static int stm32f4_i2c_wait_free_bus(struct stm32f4_i2c_dev *i2c_dev)
> +{
> +       u32 status;
> +       int ret;
> +
> +       ret = readl_relaxed_poll_timeout(i2c_dev->base + STM32F4_I2C_SR2,
> +                                        status,
> +                                        !(status & STM32F4_I2C_SR2_BUSY),
> +                                        10, 1000);
> +       if (ret) {
> +               dev_err(i2c_dev->dev, "bus not free\n");
> +               ret = -EBUSY;
> +       }
> +
> +       return ret;
> +}
> +
> +/**
> + * stm32f4_i2c_write_ byte() - Write a byte in the data register
> + * @i2c_dev: Controller's private data
> + * @byte: Data to write in the register
> + */
> +static void stm32f4_i2c_write_byte(struct stm32f4_i2c_dev *i2c_dev, u8 byte)
> +{
> +       writel_relaxed(byte, i2c_dev->base + STM32F4_I2C_DR);
> +}
> +
> +/**
> + * stm32f4_i2c_write_msg() - Fill the data register in write mode
> + * @i2c_dev: Controller's private data
> + *
> + * This function fills the data register with I2C transfer buffer
> + */
> +static void stm32f4_i2c_write_msg(struct stm32f4_i2c_dev *i2c_dev)
> +{
> +       struct stm32f4_i2c_client *c = &i2c_dev->client;
> +
> +       stm32f4_i2c_write_byte(i2c_dev, *c->buf++);
> +       c->count--;
> +}
> +
> +static void stm32f4_i2c_read_msg(struct stm32f4_i2c_dev *i2c_dev)
> +{
> +       struct stm32f4_i2c_client *c = &i2c_dev->client;
> +       u32 rbuf;
> +
> +       rbuf = readl_relaxed(i2c_dev->base + STM32F4_I2C_DR);
> +       *c->buf++ = (u8)rbuf & 0xff;
> +       c->count--;
> +}
> +
> +static void stm32f4_i2c_terminate_xfer(struct stm32f4_i2c_dev *i2c_dev)
> +{
> +       struct stm32f4_i2c_client *c = &i2c_dev->client;
> +       void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
> +
> +       /* Disable all interrupts */
> +       stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_IRQ_MASK);
> +
> +       /* Set STOP or REPSTART */
> +       reg = i2c_dev->base + STM32F4_I2C_CR1;
> +       if (c->stop)
> +               stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
> +       else
> +               stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
> +
> +       complete(&i2c_dev->complete);
> +}
> +
> +/**
> + * stm32f4_i2c_handle_write() - Handle FIFO empty interrupt in case of write
> + * @i2c_dev: Controller's private data
> + */
> +static void stm32f4_i2c_handle_write(struct stm32f4_i2c_dev *i2c_dev)
> +{
> +       struct stm32f4_i2c_client *c = &i2c_dev->client;
> +       void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
> +
> +       if (c->count) {
> +               stm32f4_i2c_write_msg(i2c_dev);
> +               if (!c->count) {
> +                       /* Disable BUF interrupt */
> +                       stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
> +               }
> +       } else {
> +               stm32f4_i2c_terminate_xfer(i2c_dev);
> +       }
> +}
> +
> +/**
> + * stm32f4_i2c_handle_tx_btf() - Handle byte transfer finished interrupt
> + * in case of write
> + * @i2c_dev: Controller's private data
> + */
> +static void stm32f4_i2c_handle_tx_btf(struct stm32f4_i2c_dev *i2c_dev)
> +{
> +       struct stm32f4_i2c_client *c = &i2c_dev->client;
> +
> +       if (c->count)
> +               stm32f4_i2c_write_msg(i2c_dev);
> +       else
> +               stm32f4_i2c_terminate_xfer(i2c_dev);
> +}
The two functions above look very similar.
Isn't there a way to factorize?

> +
> +/**
> + * stm32f4_i2c_handle_read() - Handle FIFO enmpty interrupt in case of read
s/enmpty/empty/


...
> +
> +/**
> + * stm32f4_i2c_xfer() - Transfer combined I2C message
> + * @i2c_adap: Adapter pointer to the controller
> + * @msgs: Pointer to data to be written.
> + * @num: Number of messages to be executed
> + */
> +static int stm32f4_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
> +                           int num)
> +{
> +       struct stm32f4_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
> +       int ret, i;
> +
> +       i2c_dev->busy = true;
> +
> +       ret = clk_prepare_enable(i2c_dev->clk);
> +       if (ret) {
> +               dev_err(i2c_dev->dev, "Failed to prepare_enable clock\n");
> +               return ret;
> +       }
> +
> +       stm32f4_i2c_hw_config(i2c_dev);
Maybe you could call this only at probe and resume time?
You would save some register accesses.

> +
> +       for (i = 0; i < num && !ret; i++)
> +               ret = stm32f4_i2c_xfer_msg(i2c_dev, &msgs[i], i == 0,
> +                                          i == num - 1);
> +
> +       clk_disable_unprepare(i2c_dev->clk);
> +
> +       i2c_dev->busy = false;
> +
> +       return (ret < 0) ? ret : i;
> +}
> +

Thanks!
Maxime


From emil.l.velikov at gmail.com  Tue May 17 02:55:43 2016
From: emil.l.velikov at gmail.com (Emil Velikov)
Date: Tue, 17 May 2016 10:55:43 +0100
Subject: [RFC 2/3] drm/mediatek: add support for Mediatek SoC MT2701
In-Reply-To: <1463053795-55455-3-git-send-email-yt.shen@mediatek.com>
References: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
 <1463053795-55455-3-git-send-email-yt.shen@mediatek.com>
Message-ID: <CACvgo52qc4E=MAGLoCaUH+GZuyvPexHchZnvuv-fF8P23e_1Uw@mail.gmail.com>

Hi YT Shen,

On 12 May 2016 at 12:49,  <yt.shen at mediatek.com> wrote:
> From: YT Shen <yt.shen at mediatek.com>
>
> This patch add support for the Mediatek MT2701 DISP subsystem.
> There is only one OVL engine in MT2701, and we have shadow
> register support here.
>
> Signed-off-by: YT Shen <yt.shen at mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.c     |   49 ++++++---
>  drivers/gpu/drm/mediatek/mtk_disp_rdma.c    |   36 +++++--
>  drivers/gpu/drm/mediatek/mtk_drm_crtc.c     |   78 +++++++++-----
>  drivers/gpu/drm/mediatek/mtk_drm_ddp.c      |  151 ++++++++++++++++++++-------
>  drivers/gpu/drm/mediatek/mtk_drm_ddp.h      |    2 +
>  drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c |   63 +++++++++--
>  drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |   15 +++
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c      |   72 +++++++++++--
>  drivers/gpu/drm/mediatek/mtk_drm_drv.h      |    9 ++
>  drivers/gpu/drm/mediatek/mtk_drm_gem.c      |    4 +
>  10 files changed, 373 insertions(+), 106 deletions(-)
>
This patch does a bit too many things at once imho
 - Renames existing macros
 - Factors out helper functions - mtk_crtc_ddp_config and alike.
 - Introduces *driver_data for existing hardware and uses it
 - and adds support for the different hardware.

I'm no expert in the area, but it feels like you want to split things
roughly as per above.
A rather serious mali note and some "this should be const" follow
suggestions inline.


>
> +static struct mtk_ddp_comp_driver_data mt2701_ovl_driver_data = {
> +       .ovl = {0x0040, 1 << 12, 0}
> +};
> +
> +static struct mtk_ddp_comp_driver_data mt8173_ovl_driver_data = {
> +       .ovl = {0x0f40, 0, 1 << 12}
> +};
> +
These two should be const right ?


>
> +static struct mtk_ddp_comp_driver_data mt2701_rdma_driver_data = {
> +       .rdma_fifo_pseudo_size = SZ_4K,
> +};
> +
> +static struct mtk_ddp_comp_driver_data mt8173_rdma_driver_data = {
> +       .rdma_fifo_pseudo_size = SZ_8K,
> +};
> +
Same here.


>
> -#define MUTEX_MOD_DISP_OVL0            BIT(11)
> -#define MUTEX_MOD_DISP_OVL1            BIT(12)
> -#define MUTEX_MOD_DISP_RDMA0           BIT(13)
> -#define MUTEX_MOD_DISP_RDMA1           BIT(14)
> -#define MUTEX_MOD_DISP_RDMA2           BIT(15)
> -#define MUTEX_MOD_DISP_WDMA0           BIT(16)
> -#define MUTEX_MOD_DISP_WDMA1           BIT(17)
> -#define MUTEX_MOD_DISP_COLOR0          BIT(18)
> -#define MUTEX_MOD_DISP_COLOR1          BIT(19)
> -#define MUTEX_MOD_DISP_AAL             BIT(20)
> -#define MUTEX_MOD_DISP_GAMMA           BIT(21)
> -#define MUTEX_MOD_DISP_UFOE            BIT(22)
> -#define MUTEX_MOD_DISP_PWM0            BIT(23)
> -#define MUTEX_MOD_DISP_PWM1            BIT(24)
> -#define MUTEX_MOD_DISP_OD              BIT(25)
> +#define MUTEX_MOD_MT8173_DISP_OVL0             BIT(11)
> +#define MUTEX_MOD_MT8173_DISP_OVL1             BIT(12)
> +#define MUTEX_MOD_MT8173_DISP_RDMA0            BIT(13)
> +#define MUTEX_MOD_MT8173_DISP_RDMA1            BIT(14)
> +#define MUTEX_MOD_MT8173_DISP_RDMA2            BIT(15)
> +#define MUTEX_MOD_MT8173_DISP_WDMA0            BIT(16)
> +#define MUTEX_MOD_MT8173_DISP_WDMA1            BIT(17)
> +#define MUTEX_MOD_MT8173_DISP_COLOR0           BIT(18)
> +#define MUTEX_MOD_MT8173_DISP_COLOR1           BIT(19)
> +#define MUTEX_MOD_MT8173_DISP_AAL              BIT(20)
> +#define MUTEX_MOD_MT8173_DISP_GAMMA            BIT(21)
> +#define MUTEX_MOD_MT8173_DISP_UFOE             BIT(22)
> +#define MUTEX_MOD_MT8173_DISP_PWM0             BIT(23)
> +#define MUTEX_MOD_MT8173_DISP_PWM1             BIT(24)
> +#define MUTEX_MOD_MT8173_DISP_OD               BIT(25)
> +
> +#define MUTEX_MOD_MT2701_DISP_OVL              BIT(3)
> +#define MUTEX_MOD_MT2701_DISP_WDMA             BIT(6)
> +#define MUTEX_MOD_MT2701_DISP_COLOR            BIT(7)
> +#define MUTEX_MOD_MT2701_DISP_BLS              BIT(9)
> +#define MUTEX_MOD_MT2701_DISP_RDMA0            BIT(10)
> +#define MUTEX_MOD_MT2701_DISP_RDMA1            BIT(12)
>
Even though the driver not does use a unique prefix/namespace for
these macros (which it should imho), it's better to keep the hardware
name/part first. Ideally the rename will be a separate patch.


> @@ -131,6 +153,32 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
>         [DDP_COMPONENT_WDMA1]   = { MTK_DISP_WDMA,      1, NULL },
>  };
>
> +static struct mtk_ddp_comp_driver_data mt2701_color_driver_data = {
> +       .color_offset = 0x0f00,
> +};
> +
> +static struct mtk_ddp_comp_driver_data mt8173_color_driver_data = {
> +       .color_offset = 0x0c00,
> +};
> +
const again ? You can even tweak the *_get_driver_data helpers, to
return const struct foo*, and resolve the odd warning that the
compiler will give you.


>  struct mtk_ddp_comp {
>         struct clk *clk;
>         void __iomem *regs;
> @@ -82,6 +96,7 @@ struct mtk_ddp_comp {
>         struct device *larb_dev;
>         enum mtk_ddp_comp_id id;
>         const struct mtk_ddp_comp_funcs *funcs;
> +       struct mtk_ddp_comp_driver_data *data;
const


> +static struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
> +       .main_path = mtk_ddp_main_2701,
> +       .main_len = ARRAY_SIZE(mtk_ddp_main_2701),
> +       .ext_path = mtk_ddp_ext_2701,
> +       .ext_len = ARRAY_SIZE(mtk_ddp_ext_2701),
> +       .shadow_register = true,
> +};
> +
> +static struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
> +       .main_path = mtk_ddp_main_8173,
> +       .main_len = ARRAY_SIZE(mtk_ddp_main_8173),
> +       .ext_path = mtk_ddp_ext_8173,
> +       .ext_len = ARRAY_SIZE(mtk_ddp_ext_8173),
> +       .shadow_register = false,
> +};
> +
const


> @@ -40,6 +48,7 @@ struct mtk_drm_private {
>         void __iomem *config_regs;
>         struct device_node *comp_node[DDP_COMPONENT_ID_MAX];
>         struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX];
> +       struct mtk_mmsys_driver_data *data;
const ?


> @@ -108,6 +108,10 @@ int mtk_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
>         int ret;
>
>         args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
> +       /*
> +       * align to 8 bytes since Mali requires it.
> +       */
> +       args->pitch = ALIGN(args->pitch, 8);
Are you sure we need this, based on the line just above ?

Iirc we had a chat earlier that upstream kernel code should not be
tailoured for the needs to closed source userspace... seems like the
comment got removed but the code remained. Philipp Zabel I believe you
were the person who did the original upstreaming - can we remove this
hack/workaround and keep it downstream until we have an open-source
user that requires it ?

Can we have a MAINTAINERS entry for this driver ?

Thanks
Emil


From shijie.huang at arm.com  Tue May 17 02:57:33 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Tue, 17 May 2016 17:57:33 +0800
Subject: [PATCH v12 10/10] kprobes: Add arm64 case in kprobe example module
In-Reply-To: <1461783185-9056-11-git-send-email-dave.long@linaro.org>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-11-git-send-email-dave.long@linaro.org>
Message-ID: <20160517095714.GA25167@sha-win-210.asiapac.arm.com>

On Wed, Apr 27, 2016 at 02:53:05PM -0400, David Long wrote:
> From: Sandeepa Prabhu <sandeepa.s.prabhu at gmail.com>
> 
> Add info prints in sample kprobe handlers for ARM64
> 
> Signed-off-by: Sandeepa Prabhu <sandeepa.s.prabhu at gmail.com>
> ---
>  samples/kprobes/kprobe_example.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/samples/kprobes/kprobe_example.c b/samples/kprobes/kprobe_example.c
> index 727eb21..0c72b8a 100644
> --- a/samples/kprobes/kprobe_example.c
> +++ b/samples/kprobes/kprobe_example.c
> @@ -42,6 +42,10 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs)
>  			" ex1 = 0x%lx\n",
>  		p->addr, regs->pc, regs->ex1);
>  #endif
> +#ifdef CONFIG_ARM64
> +	pr_info("pre_handler: p->addr = 0x%p, pc = 0x%lx\n",

I think you miss the KERN_INFO here.

> +		p->addr, (long)regs->pc);
> +#endif
>  
>  	/* A dump_stack() here will give a stack backtrace */
>  	return 0;
> @@ -67,6 +71,10 @@ static void handler_post(struct kprobe *p, struct pt_regs *regs,
>  	printk(KERN_INFO "post_handler: p->addr = 0x%p, ex1 = 0x%lx\n",
>  		p->addr, regs->ex1);
>  #endif
> +#ifdef CONFIG_ARM64
> +	pr_info("post_handler: p->addr = 0x%p, pc = 0x%lx\n",
ditto.
> +		p->addr, (long)regs->pc);
> +#endif
thanks
Huang Shijie



From sstabellini at kernel.org  Tue May 17 03:12:40 2016
From: sstabellini at kernel.org (Stefano Stabellini)
Date: Tue, 17 May 2016 11:12:40 +0100 (BST)
Subject: [GIT PULL] EFI ARM Xen support
In-Reply-To: <20160514190410.GA2283@codeblueprint.co.uk>
References: <20160514190410.GA2283@codeblueprint.co.uk>
Message-ID: <alpine.DEB.2.10.1605171109170.2494@sstabellini-ThinkPad-X260>

On Sat, 14 May 2016, Matt Fleming wrote:
> Folks,
> 
> Please pull the following branch which contains support for Xen on ARM
> EFI platforms.
> 
> This merge includes a merge of Stefano's xen/linux-next branch to pull
> in the prerequisites required for Shannon's commit:
> 
>   11ee5491e5ff ("Xen: EFI: Parse DT parameters for Xen specific UEFI")
> 
> as it needs both the latest changes in the EFI 'next' branch (now
> tip/efi/core) and xen/linux-next.
> 
> I have intentionally not included the individual patches as I would
> normally do in a pull request, so that commit history created by my
> merging of Stefano's branch is preserved, and so that there's no way
> to accidentally apply the patches individually.
> 
> The following changes since commit 6c5450ef66816216e574885cf8d3ddb31ef77428:
> 
>   efivarfs: Make efivarfs_file_ioctl() static (2016-05-07 07:06:13 +0200)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git efi/arm-xen
> 
> for you to fetch changes up to 11ee5491e5ff519e0d3a7018eb21351cb6955a98:
> 
>   Xen: EFI: Parse DT parameters for Xen specific UEFI (2016-05-14 19:31:01 +0100)

Is this arrangement working for everybody, in particular the tip
maintainers?

I am asking because I didn't receive any replies to this or to
http://marc.info/?l=linux-kernel&m=146317737928595&w=2.



> David Vrabel (1):
>       xen/gntdev: reduce copy batch size to 16
> 
> Matt Fleming (1):
>       Merge branch 'xen/linux-next' into efi/arm-xen
> 
> Shannon Zhao (16):
>       Xen: ACPI: Hide UART used by Xen
>       xen/grant-table: Move xlated_setup_gnttab_pages to common place
>       Xen: xlate: Use page_to_xen_pfn instead of page_to_pfn
>       arm/xen: Use xen_xlate_map_ballooned_pages to setup grant table
>       xen: memory : Add new XENMAPSPACE type XENMAPSPACE_dev_mmio
>       Xen: ARM: Add support for mapping platform device mmio
>       Xen: ARM: Add support for mapping AMBA device mmio
>       Xen: public/hvm: sync changes of HVM_PARAM_CALLBACK_VIA ABI from Xen
>       xen/hvm/params: Add a new delivery type for event-channel in HVM_PARAM_CALLBACK_IRQ
>       arm/xen: Get event-channel irq through HVM_PARAM when booting with ACPI
>       ARM: XEN: Move xen_early_init() before efi_init()
>       ARM: Xen: Document UEFI support on Xen ARM virtual platforms
>       XEN: EFI: Move x86 specific codes to architecture directory
>       ARM64: XEN: Add a function to initialize Xen specific UEFI runtime services
>       FDT: Add a helper to get the subnode by given name
>       Xen: EFI: Parse DT parameters for Xen specific UEFI
> 
> Stefano Stabellini (1):
>       xen/x86: don't lose event interrupts
> 
>  Documentation/devicetree/bindings/arm/xen.txt |  35 +++++
>  arch/arm/include/asm/xen/xen-ops.h            |   6 +
>  arch/arm/kernel/setup.c                       |   2 +-
>  arch/arm/xen/Makefile                         |   1 +
>  arch/arm/xen/efi.c                            |  40 ++++++
>  arch/arm/xen/enlighten.c                      | 125 ++++++++++++----
>  arch/arm64/include/asm/xen/xen-ops.h          |   6 +
>  arch/arm64/kernel/setup.c                     |   2 +-
>  arch/arm64/xen/Makefile                       |   1 +
>  arch/x86/xen/efi.c                            | 111 +++++++++++++++
>  arch/x86/xen/grant-table.c                    |  57 +-------
>  arch/x86/xen/time.c                           |   6 +-
>  drivers/acpi/scan.c                           |  74 ++++++++++
>  drivers/firmware/efi/arm-runtime.c            |   5 +
>  drivers/firmware/efi/efi.c                    |  81 ++++++++---
>  drivers/of/fdt.c                              |  13 ++
>  drivers/xen/Kconfig                           |   2 +-
>  drivers/xen/Makefile                          |   1 +
>  drivers/xen/arm-device.c                      | 196 ++++++++++++++++++++++++++
>  drivers/xen/efi.c                             | 173 +++++------------------
>  drivers/xen/gntdev.c                          |   2 +-
>  drivers/xen/xlate_mmu.c                       |  77 ++++++++++
>  include/linux/of_fdt.h                        |   2 +
>  include/xen/interface/hvm/params.h            |  40 +++++-
>  include/xen/interface/memory.h                |   1 +
>  include/xen/xen-ops.h                         |  32 +++--
>  26 files changed, 840 insertions(+), 251 deletions(-)
>  create mode 100644 arch/arm/include/asm/xen/xen-ops.h
>  create mode 100644 arch/arm/xen/efi.c
>  create mode 100644 arch/arm64/include/asm/xen/xen-ops.h
>  create mode 100644 drivers/xen/arm-device.c
> 


From broonie at kernel.org  Tue May 17 03:24:27 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 17 May 2016 11:24:27 +0100
Subject: [PATCH v12 10/10] kprobes: Add arm64 case in kprobe example module
In-Reply-To: <20160517095714.GA25167@sha-win-210.asiapac.arm.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-11-git-send-email-dave.long@linaro.org>
 <20160517095714.GA25167@sha-win-210.asiapac.arm.com>
Message-ID: <20160517102427.GD8104@sirena.org.uk>

On Tue, May 17, 2016 at 05:57:33PM +0800, Huang Shijie wrote:
> On Wed, Apr 27, 2016 at 02:53:05PM -0400, David Long wrote:

> > +#ifdef CONFIG_ARM64
> > +	pr_info("pre_handler: p->addr = 0x%p, pc = 0x%lx\n",

> I think you miss the KERN_INFO here.

That's what pr_info() does over printk() - it adds the KERN_INFO more
cleanly.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160517/07f2ea4b/attachment.sig>

From boris.brezillon at free-electrons.com  Tue May 17 03:35:32 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 17 May 2016 12:35:32 +0200
Subject: [PATCH] pwm: Fill pwm->args before calling pwm_request_from_chip()
Message-ID: <1463481333-23438-1-git-send-email-boris.brezillon@free-electrons.com>

Commit e39c0df1be5a ("pwm: Introduce the pwm_args concept"), moved the
period and polarity initialization steps into pwm_request_device() (called
by pwm_request_from_chip()) based on the pwm->args information.
Make sure we fill pwm->args fields before calling pwm_request_from_chip().

Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
Reported-by: Mika Penttil? <mika.penttila at nextfour.com>
Fixes: e39c0df1be5a ("pwm: Introduce the pwm_args concept")
---
Mika,

Can you test after applying this patch and let me know if it fixes your
bug.

Thanks,

Boris

 drivers/pwm/core.c    | 12 ++++++------
 drivers/pwm/pwm-pxa.c |  4 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 427142d..3d2eeaa 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -143,10 +143,6 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
 	if (args->args[0] >= pc->npwm)
 		return ERR_PTR(-EINVAL);
 
-	pwm = pwm_request_from_chip(pc, args->args[0], NULL);
-	if (IS_ERR(pwm))
-		return pwm;
-
 	pwm->args.period = args->args[1];
 
 	if (args->args[2] & PWM_POLARITY_INVERTED)
@@ -154,6 +150,10 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
 	else
 		pwm->args.polarity = PWM_POLARITY_NORMAL;
 
+	pwm = pwm_request_from_chip(pc, args->args[0], NULL);
+	if (IS_ERR(pwm))
+		return pwm;
+
 	return pwm;
 }
 EXPORT_SYMBOL_GPL(of_pwm_xlate_with_flags);
@@ -169,12 +169,12 @@ of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
 	if (args->args[0] >= pc->npwm)
 		return ERR_PTR(-EINVAL);
 
+	pwm->args.period = args->args[1];
+
 	pwm = pwm_request_from_chip(pc, args->args[0], NULL);
 	if (IS_ERR(pwm))
 		return pwm;
 
-	pwm->args.period = args->args[1];
-
 	return pwm;
 }
 
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index 58b709f..c33bd42 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -156,12 +156,12 @@ pxa_pwm_of_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
 {
 	struct pwm_device *pwm;
 
+	pwm->args.period = args->args[0];
+
 	pwm = pwm_request_from_chip(pc, 0, NULL);
 	if (IS_ERR(pwm))
 		return pwm;
 
-	pwm->args.period = args->args[0];
-
 	return pwm;
 }
 
-- 
2.7.4



From boris.brezillon at free-electrons.com  Tue May 17 03:35:33 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 17 May 2016 12:35:33 +0200
Subject: [PATCH] pwm: Fill pwm->args before calling pwm_request_from_chip()
In-Reply-To: <1463481333-23438-1-git-send-email-boris.brezillon@free-electrons.com>
References: <1463481333-23438-1-git-send-email-boris.brezillon@free-electrons.com>
Message-ID: <1463481333-23438-2-git-send-email-boris.brezillon@free-electrons.com>

Commit e39c0df1be5a ("pwm: Introduce the pwm_args concept"), moved the
period and polarity initialization steps into pwm_request_device() (called
by pwm_request_from_chip()) based on the pwm->args information.
Make sure we fill pwm->args fields before calling pwm_request_from_chip().

Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
Reported-by: Mika Penttil? <mika.penttila at nextfour.com>
Fixes: e39c0df1be5a ("pwm: Introduce the pwm_args concept")
---
Mika,

Can you test after applying this patch and let me know if it fixes your
bug.

Thanks,

Boris

 drivers/pwm/core.c    | 12 ++++++------
 drivers/pwm/pwm-pxa.c |  4 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 427142d..3d2eeaa 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -143,10 +143,6 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
 	if (args->args[0] >= pc->npwm)
 		return ERR_PTR(-EINVAL);
 
-	pwm = pwm_request_from_chip(pc, args->args[0], NULL);
-	if (IS_ERR(pwm))
-		return pwm;
-
 	pwm->args.period = args->args[1];
 
 	if (args->args[2] & PWM_POLARITY_INVERTED)
@@ -154,6 +150,10 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
 	else
 		pwm->args.polarity = PWM_POLARITY_NORMAL;
 
+	pwm = pwm_request_from_chip(pc, args->args[0], NULL);
+	if (IS_ERR(pwm))
+		return pwm;
+
 	return pwm;
 }
 EXPORT_SYMBOL_GPL(of_pwm_xlate_with_flags);
@@ -169,12 +169,12 @@ of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
 	if (args->args[0] >= pc->npwm)
 		return ERR_PTR(-EINVAL);
 
+	pwm->args.period = args->args[1];
+
 	pwm = pwm_request_from_chip(pc, args->args[0], NULL);
 	if (IS_ERR(pwm))
 		return pwm;
 
-	pwm->args.period = args->args[1];
-
 	return pwm;
 }
 
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index 58b709f..c33bd42 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -156,12 +156,12 @@ pxa_pwm_of_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
 {
 	struct pwm_device *pwm;
 
+	pwm->args.period = args->args[0];
+
 	pwm = pwm_request_from_chip(pc, 0, NULL);
 	if (IS_ERR(pwm))
 		return pwm;
 
-	pwm->args.period = args->args[0];
-
 	return pwm;
 }
 
-- 
2.7.4



From david.vrabel at citrix.com  Tue May 17 03:40:14 2016
From: david.vrabel at citrix.com (David Vrabel)
Date: Tue, 17 May 2016 11:40:14 +0100
Subject: [Xen-devel] [GIT PULL] EFI ARM Xen support
In-Reply-To: <alpine.DEB.2.10.1605171109170.2494@sstabellini-ThinkPad-X260>
References: <20160514190410.GA2283@codeblueprint.co.uk>
 <alpine.DEB.2.10.1605171109170.2494@sstabellini-ThinkPad-X260>
Message-ID: <573AF50E.9090206@citrix.com>

On 17/05/16 11:12, Stefano Stabellini wrote:
> On Sat, 14 May 2016, Matt Fleming wrote:
>> Folks,
>>
>> Please pull the following branch which contains support for Xen on ARM
>> EFI platforms.
>>
>> This merge includes a merge of Stefano's xen/linux-next branch to pull
>> in the prerequisites required for Shannon's commit:
>>
>>   11ee5491e5ff ("Xen: EFI: Parse DT parameters for Xen specific UEFI")
>>
>> as it needs both the latest changes in the EFI 'next' branch (now
>> tip/efi/core) and xen/linux-next.
>>
>> I have intentionally not included the individual patches as I would
>> normally do in a pull request, so that commit history created by my
>> merging of Stefano's branch is preserved, and so that there's no way
>> to accidentally apply the patches individually.
>>
>> The following changes since commit 6c5450ef66816216e574885cf8d3ddb31ef77428:
>>
>>   efivarfs: Make efivarfs_file_ioctl() static (2016-05-07 07:06:13 +0200)
>>
>> are available in the git repository at:
>>
>>   git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git efi/arm-xen
>>
>> for you to fetch changes up to 11ee5491e5ff519e0d3a7018eb21351cb6955a98:
>>
>>   Xen: EFI: Parse DT parameters for Xen specific UEFI (2016-05-14 19:31:01 +0100)
> 
> Is this arrangement working for everybody, in particular the tip
> maintainers?

Yes.

David


From marc.zyngier at arm.com  Tue May 17 03:55:29 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 17 May 2016 11:55:29 +0100
Subject: [PATCH v4 18/56] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <1463392481-26583-19-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-19-git-send-email-andre.przywara@arm.com>
Message-ID: <573AF8A1.2080506@arm.com>

On 16/05/16 10:53, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Implement the framework for syncing IRQs between our emulation and
> the list registers, which represent the guest's view of IRQs.
> This is done in kvm_vgic_flush_hwstate and kvm_vgic_sync_hwstate,
> which gets called on guest entry and exit.
> The code talking to the actual GICv2/v3 hardware is added in the
> following patches.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Reviewed-by: Eric Auger <eric.auger at linaro.org>
> Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
> ---
> Changelog RFC..v1:
> - split out vgic_clear_lr() from vgic_populate_lr()
> - rename vgic_populate_lrs() to vgic_flush_lr_state()
> - clean all LRs when the distributor is disabled
> - use list_del() instead of list_del_init()
> - add comments to explain the direction of sync/flush_hwstate
> - remove unneeded BUG_ON(in_interrupt()
> 
> Changelog v2 .. v3:
> - remove bogus v2 specific rebase leftovers
> 
> Changelog v3 .. v4:
> - amend locks requirements
> 
>  include/kvm/vgic/vgic.h  |   4 +
>  virt/kvm/arm/vgic/vgic.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h |   2 +
>  3 files changed, 197 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 7b6ca90..9506267 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -190,6 +190,10 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
>  			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
>  
> +bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
> +void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
> +void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
> +
>  /**
>   * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
>   *
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 1bc8f92..613fbd1 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -307,3 +307,194 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  {
>  	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
>  }
> +
> +/**
> + * vgic_prune_ap_list - Remove non-relevant interrupts from the list
> + *
> + * @vcpu: The VCPU pointer
> + *
> + * Go over the list of "interesting" interrupts, and prune those that we
> + * won't have to consider in the near future.
> + */
> +static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq, *tmp;
> +
> +retry:
> +	spin_lock(&vgic_cpu->ap_list_lock);
> +
> +	list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
> +		struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		BUG_ON(vcpu != irq->vcpu);
> +
> +		target_vcpu = vgic_target_oracle(irq);
> +
> +		if (!target_vcpu) {
> +			/*
> +			 * We don't need to process this interrupt any
> +			 * further, move it off the list.
> +			 */
> +			list_del(&irq->ap_list);
> +			irq->vcpu = NULL;
> +			spin_unlock(&irq->irq_lock);
> +			continue;
> +		}
> +
> +		if (target_vcpu == vcpu) {
> +			/* We're on the right CPU */
> +			spin_unlock(&irq->irq_lock);
> +			continue;
> +		}
> +
> +		/* This interrupt looks like it has to be migrated. */
> +
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vgic_cpu->ap_list_lock);
> +
> +		/*
> +		 * Ensure locking order by always locking the smallest
> +		 * ID first.
> +		 */
> +		if (vcpu->vcpu_id < target_vcpu->vcpu_id) {
> +			vcpuA = vcpu;
> +			vcpuB = target_vcpu;
> +		} else {
> +			vcpuA = target_vcpu;
> +			vcpuB = vcpu;
> +		}
> +
> +		spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
> +		spin_lock(&vcpuB->arch.vgic_cpu.ap_list_lock);
> +		spin_lock(&irq->irq_lock);
> +
> +		/*
> +		 * If the affinity has been preserved, move the
> +		 * interrupt around. Otherwise, it means things have
> +		 * changed while the interrupt was unlocked, and we
> +		 * need to replay this.
> +		 *
> +		 * In all cases, we cannot trust the list not to have
> +		 * changed, so we restart from the beginning.
> +		 */
> +		if (target_vcpu == vgic_target_oracle(irq)) {
> +			struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;
> +
> +			list_del(&irq->ap_list);
> +			irq->vcpu = target_vcpu;
> +			list_add_tail(&irq->ap_list, &new_cpu->ap_list_head);
> +		}
> +
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
> +		spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
> +		goto retry;
> +	}
> +
> +	spin_unlock(&vgic_cpu->ap_list_lock);
> +}
> +
> +static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +/* Requires the irq_lock to be held. */
> +static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
> +				    struct vgic_irq *irq, int lr)
> +{
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
> +}
> +
> +static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
> +{
> +}
> +
> +static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
> +{
> +}
> +
> +/* Requires the ap_list_lock to be held. */
> +static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq;
> +	int count = 0;
> +
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
> +
> +	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
> +		spin_lock(&irq->irq_lock);
> +		/* GICv2 SGIs can count for more than one... */
> +		if (vgic_irq_is_sgi(irq->intid) && irq->source)
> +			count += hweight8(irq->source);
> +		else
> +			count++;
> +		spin_unlock(&irq->irq_lock);
> +	}
> +	return count;
> +}
> +
> +/* Requires the VCPU's ap_list_lock to be held. */
> +static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
> +{
> +	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
> +	struct vgic_irq *irq;
> +	int count = 0;
> +
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
> +
> +	if (compute_ap_list_depth(vcpu) > kvm_vgic_global_state.nr_lr) {
> +		vgic_set_underflow(vcpu);
> +		vgic_sort_ap_list(vcpu);
> +	}
> +
> +	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
> +		spin_lock(&irq->irq_lock);
> +
> +		if (unlikely(vgic_target_oracle(irq) != vcpu))
> +			goto next;
> +
> +		/*
> +		 * If we get an SGI with multiple sources, try to get
> +		 * them in all at once.
> +		 */

Nit: this comment is out of place, and is a duplicate of the one in
compute_ap_list_depth().

> +		do {
> +			vgic_populate_lr(vcpu, irq, count++);
> +		} while (irq->source && count < kvm_vgic_global_state.nr_lr);
> +
> +next:
> +		spin_unlock(&irq->irq_lock);
> +
> +		if (count == kvm_vgic_global_state.nr_lr)
> +			break;
> +	}
> +
> +	vcpu->arch.vgic_cpu.used_lrs = count;
> +
> +	/* Nuke remaining LRs */
> +	for ( ; count < kvm_vgic_global_state.nr_lr; count++)
> +		vgic_clear_lr(vcpu, count);
> +}
> +
> +/* Sync back the hardware VGIC state into our emulation after a guest's run. */
> +void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
> +{
> +	vgic_process_maintenance_interrupt(vcpu);
> +	vgic_fold_lr_state(vcpu);
> +	vgic_prune_ap_list(vcpu);
> +}
> +
> +/* Flush our emulation state into the GIC hardware before entering the guest. */
> +void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
> +{
> +	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +	vgic_flush_lr_state(vcpu);
> +	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index c625767..29b96b9 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -16,6 +16,8 @@
>  #ifndef __KVM_ARM_VGIC_NEW_H__
>  #define __KVM_ARM_VGIC_NEW_H__
>  
> +#define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
> +
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid);
>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From thierry.reding at gmail.com  Tue May 17 04:00:05 2016
From: thierry.reding at gmail.com (Thierry Reding)
Date: Tue, 17 May 2016 13:00:05 +0200
Subject: [PATCH] pwm: atmel-hlcdc: Fix default PWM polarity
In-Reply-To: <1463476352-7485-1-git-send-email-boris.brezillon@free-electrons.com>
References: <1463476352-7485-1-git-send-email-boris.brezillon@free-electrons.com>
Message-ID: <20160517110005.GA26166@ulmo.ba.sec>

On Tue, May 17, 2016 at 11:12:32AM +0200, Boris Brezillon wrote:
> The PWM device exposed by the HLCDC IP is configured with an inverted
> polarity by default. Registering the PWM chip with the normal polarity
> was not a problem before commit 42e8992c58d4 ("pwm: Add core
> infrastructure to allow atomic updates") because the ->set_polarity()
> hook was called no matter the current polarity state, but this is no longer
> the case.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> Fixes: 42e8992c58d4 ("pwm: Add core infrastructure to allow atomic updates")

That's not technically correct, because it's the driver that has the
bug. The core change merely exposes it. How about if I sort this into
the pwm-atomic branch and reword the commit message accordingly? That
way things should all stay bisectible.

Then again, given the breakage caused by the pwm_args patch I suppose
it doesn't matter much because that's part of a stable branch that I
can't rebase.

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

From boris.brezillon at free-electrons.com  Tue May 17 04:04:09 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 17 May 2016 13:04:09 +0200
Subject: [PATCH] pwm: atmel-hlcdc: Fix default PWM polarity
In-Reply-To: <20160517110005.GA26166@ulmo.ba.sec>
References: <1463476352-7485-1-git-send-email-boris.brezillon@free-electrons.com>
 <20160517110005.GA26166@ulmo.ba.sec>
Message-ID: <20160517130409.0670a94f@bbrezillon>

On Tue, 17 May 2016 13:00:05 +0200
Thierry Reding <thierry.reding at gmail.com> wrote:

> On Tue, May 17, 2016 at 11:12:32AM +0200, Boris Brezillon wrote:
> > The PWM device exposed by the HLCDC IP is configured with an inverted
> > polarity by default. Registering the PWM chip with the normal polarity
> > was not a problem before commit 42e8992c58d4 ("pwm: Add core
> > infrastructure to allow atomic updates") because the ->set_polarity()
> > hook was called no matter the current polarity state, but this is no longer
> > the case.
> > 
> > Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> > Fixes: 42e8992c58d4 ("pwm: Add core infrastructure to allow atomic updates")  
> 
> That's not technically correct, because it's the driver that has the
> bug. The core change merely exposes it.

Agree.

> How about if I sort this into
> the pwm-atomic branch and reword the commit message accordingly? That
> way things should all stay bisectible.

As you wish.

> 
> Then again, given the breakage caused by the pwm_args patch I suppose
> it doesn't matter much because that's part of a stable branch that I
> can't rebase.

Yep, I know :-(.


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


From thierry.reding at gmail.com  Tue May 17 04:04:38 2016
From: thierry.reding at gmail.com (Thierry Reding)
Date: Tue, 17 May 2016 13:04:38 +0200
Subject: [PATCH] pwm: Fill pwm->args before calling pwm_request_from_chip()
In-Reply-To: <1463481333-23438-2-git-send-email-boris.brezillon@free-electrons.com>
References: <1463481333-23438-1-git-send-email-boris.brezillon@free-electrons.com>
 <1463481333-23438-2-git-send-email-boris.brezillon@free-electrons.com>
Message-ID: <20160517110438.GB26166@ulmo.ba.sec>

On Tue, May 17, 2016 at 12:35:33PM +0200, Boris Brezillon wrote:
[...]
> diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
> index 427142d..3d2eeaa 100644
> --- a/drivers/pwm/core.c
> +++ b/drivers/pwm/core.c
> @@ -143,10 +143,6 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
>  	if (args->args[0] >= pc->npwm)
>  		return ERR_PTR(-EINVAL);
>  
> -	pwm = pwm_request_from_chip(pc, args->args[0], NULL);
> -	if (IS_ERR(pwm))
> -		return pwm;
> -
>  	pwm->args.period = args->args[1];
>  
>  	if (args->args[2] & PWM_POLARITY_INVERTED)
> @@ -154,6 +150,10 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
>  	else
>  		pwm->args.polarity = PWM_POLARITY_NORMAL;
>  
> +	pwm = pwm_request_from_chip(pc, args->args[0], NULL);
> +	if (IS_ERR(pwm))
> +		return pwm;
> +

Can't do that, because now you're dereferencing an uninitialized
pointer.

>  	return pwm;
>  }
>  EXPORT_SYMBOL_GPL(of_pwm_xlate_with_flags);
> @@ -169,12 +169,12 @@ of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
>  	if (args->args[0] >= pc->npwm)
>  		return ERR_PTR(-EINVAL);
>  
> +	pwm->args.period = args->args[1];

Same here.

> diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
> index 58b709f..c33bd42 100644
> --- a/drivers/pwm/pwm-pxa.c
> +++ b/drivers/pwm/pwm-pxa.c
> @@ -156,12 +156,12 @@ pxa_pwm_of_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
>  {
>  	struct pwm_device *pwm;
>  
> +	pwm->args.period = args->args[0];

And here.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160517/13bee631/attachment-0001.sig>

From boris.brezillon at free-electrons.com  Tue May 17 04:11:47 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 17 May 2016 13:11:47 +0200
Subject: [PATCH] pwm: Fill pwm->args before calling pwm_request_from_chip()
In-Reply-To: <20160517110438.GB26166@ulmo.ba.sec>
References: <1463481333-23438-1-git-send-email-boris.brezillon@free-electrons.com>
 <1463481333-23438-2-git-send-email-boris.brezillon@free-electrons.com>
 <20160517110438.GB26166@ulmo.ba.sec>
Message-ID: <20160517131147.7f505f2b@bbrezillon>

On Tue, 17 May 2016 13:04:38 +0200
Thierry Reding <thierry.reding at gmail.com> wrote:

> On Tue, May 17, 2016 at 12:35:33PM +0200, Boris Brezillon wrote:
> [...]
> > diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
> > index 427142d..3d2eeaa 100644
> > --- a/drivers/pwm/core.c
> > +++ b/drivers/pwm/core.c
> > @@ -143,10 +143,6 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
> >  	if (args->args[0] >= pc->npwm)
> >  		return ERR_PTR(-EINVAL);
> >  
> > -	pwm = pwm_request_from_chip(pc, args->args[0], NULL);
> > -	if (IS_ERR(pwm))
> > -		return pwm;
> > -
> >  	pwm->args.period = args->args[1];
> >  
> >  	if (args->args[2] & PWM_POLARITY_INVERTED)
> > @@ -154,6 +150,10 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
> >  	else
> >  		pwm->args.polarity = PWM_POLARITY_NORMAL;
> >  
> > +	pwm = pwm_request_from_chip(pc, args->args[0], NULL);
> > +	if (IS_ERR(pwm))
> > +		return pwm;
> > +  
> 
> Can't do that, because now you're dereferencing an uninitialized
> pointer.

Yes, forget this patch, it's not needed anyway since all PWM users are
now directly calling pwm_apply_args() after requesting the PWM. The bad
news is I broke bisectibilty :-(.

Still does not explain the bug reported by Mika.

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


From catalin.marinas at arm.com  Tue May 17 04:13:34 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 17 May 2016 12:13:34 +0100
Subject: [PATCH v2 net-next] bpf: arm64: remove callee-save registers use
 for tmp registers
In-Reply-To: <1463441786-32224-1-git-send-email-yang.shi@linaro.org>
References: <1463441786-32224-1-git-send-email-yang.shi@linaro.org>
Message-ID: <20160517111334.GD23555@e104818-lin.cambridge.arm.com>

On Mon, May 16, 2016 at 04:36:26PM -0700, Yang Shi wrote:
> In the current implementation of ARM64 eBPF JIT, R23 and R24 are used for
> tmp registers, which are callee-saved registers. This leads to variable size
> of JIT prologue and epilogue. The latest blinding constant change prefers to
> constant size of prologue and epilogue. AAPCS reserves R9 ~ R15 for temp
> registers which not need to be saved/restored during function call. So, replace
> R23 and R24 to R10 and R11, and remove tmp_used flag to save 2 instructions for
> some jited BPF program.
> 
> CC: Daniel Borkmann <daniel at iogearbox.net>
> Acked-by: Zi Shen Lim <zlim.lnx at gmail.com>
> Signed-off-by: Yang Shi <yang.shi at linaro.org>

Acked-by: Catalin Marinas <catalin.marinas at arm.com>


From daniel at iogearbox.net  Tue May 17 04:52:19 2016
From: daniel at iogearbox.net (Daniel Borkmann)
Date: Tue, 17 May 2016 13:52:19 +0200
Subject: [PATCH v2 net-next] bpf: arm64: remove callee-save registers
 use for tmp registers
In-Reply-To: <1463441786-32224-1-git-send-email-yang.shi@linaro.org>
References: <1463441786-32224-1-git-send-email-yang.shi@linaro.org>
Message-ID: <573B05F3.7000009@iogearbox.net>

On 05/17/2016 01:36 AM, Yang Shi wrote:
> In the current implementation of ARM64 eBPF JIT, R23 and R24 are used for
> tmp registers, which are callee-saved registers. This leads to variable size
> of JIT prologue and epilogue. The latest blinding constant change prefers to
> constant size of prologue and epilogue. AAPCS reserves R9 ~ R15 for temp
> registers which not need to be saved/restored during function call. So, replace
> R23 and R24 to R10 and R11, and remove tmp_used flag to save 2 instructions for
> some jited BPF program.
>
> CC: Daniel Borkmann <daniel at iogearbox.net>
> Acked-by: Zi Shen Lim <zlim.lnx at gmail.com>
> Signed-off-by: Yang Shi <yang.shi at linaro.org>

LGTM, thanks!

Acked-by: Daniel Borkmann <daniel at iogearbox.net>


From oneukum at suse.com  Tue May 17 04:53:56 2016
From: oneukum at suse.com (Oliver Neukum)
Date: Tue, 17 May 2016 13:53:56 +0200
Subject: [PSCI DISCUSS] How to implement standby and suspend-to-ram by PSCI
In-Reply-To: <DB3PR04MB08125A628F5034749F8109D884730@DB3PR04MB0812.eurprd04.prod.outlook.com>
References: <DB3PR04MB0812DAA98F71C30E8A8832E3847D0@DB3PR04MB0812.eurprd04.prod.outlook.com>
 <572C9BF2.9010004@arm.com>
 <DB3PR04MB08125A628F5034749F8109D884730@DB3PR04MB0812.eurprd04.prod.outlook.com>
Message-ID: <1463486036.19237.9.camel@suse.com>

On Thu, 2016-05-12 at 09:42 +0000, Hongbo Zhang wrote:
> On our platform we have some shallow states which maps to cpuidle
> well, 
> and we have two more deeper states:
> 
> Sleep state:
> All cores are in WFI state,
> Core cluster is in standby state, e.g. L2 cache is flushed then stops 
> snooping,
> Only those modules which are required to wake up the device still have
> a 
> running clock, other device modules in chip are clock gated.
> 
> Deep sleep state:
> ARM cores and DDR controller are switched off,
> DDR is in self-refresh mode,
> VDD power to off domain IPs are removed, Only the blocks needed to 
> detect wake up and sequence the chip out of deep sleep are on.

For the pm module of the core kernel a low power state is a sleep
state if even one of three conditions is met:

a) a device that can be used for input is not a source of wake ups
b) tasks need to be frozen to enter it
c) the display goes off, while it should be on

Generally runtime PM is better if you can get the same results.
Going to a system sleep state is a necessary evil.

	Regards
		Oliver




From aleksey.makarov at linaro.org  Tue May 17 05:06:00 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Tue, 17 May 2016 15:06:00 +0300
Subject: [PATCH 0/3] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
Message-ID: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>

This patchset adds support for ACPI_TABLE_UPGRADE for ARM64

It refactors the code introduced by the patches by Lv Zheng [1], fixes access to
the destination of new ACPI tables as suggested by Mark Rutland [2] and enables
the feature for ARM64

It was first sent by Jon Masters [3] to linaro-acpi in December 2015

Tested on QEMU (arm64 and x86) and ThunderX
Should be applied to next-20160517

[1] https://lkml.kernel.org/g/cover.1460340514.git.lv.zheng at intel.com
[2] https://lists.linaro.org/pipermail/linaro-acpi/2015-December/006101.html
[3] https://lists.linaro.org/pipermail/linaro-acpi/2015-December/006099.html

Aleksey Makarov (2):
  ACPI: table upgrade: use cacheable map for tables
  ACPI: table upgrade: move early_initrd_acpi_init() to header file

Jon Masters (1):
  ACPI: ARM64: support for ACPI_TABLE_UPGRADE

 arch/arm64/kernel/setup.c |  6 ++++--
 arch/x86/kernel/setup.c   |  7 -------
 drivers/acpi/Kconfig      |  2 +-
 drivers/acpi/tables.c     | 21 ++++++++++++++++-----
 include/linux/acpi.h      |  4 ++--
 5 files changed, 23 insertions(+), 17 deletions(-)

-- 
2.8.2



From aleksey.makarov at linaro.org  Tue May 17 05:06:01 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Tue, 17 May 2016 15:06:01 +0300
Subject: [PATCH 1/3] ACPI: table upgrade: use cacheable map for tables
In-Reply-To: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1463486765-31827-2-git-send-email-aleksey.makarov@linaro.org>

The new memory allocated in acpi_table_initrd_init() is used to
copy the upgraded tables to it.  So it should be mapped with
early_memunmap() instead of early_ioremap().

This is critical for ARM.

Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
---
 drivers/acpi/tables.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index a372f9e..449a649 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -578,10 +578,10 @@ static void __init acpi_table_initrd_init(void *data, size_t size)
 			clen = size;
 			if (clen > MAP_CHUNK_SIZE - slop)
 				clen = MAP_CHUNK_SIZE - slop;
-			dest_p = early_ioremap(dest_addr & PAGE_MASK,
+			dest_p = early_memremap(dest_addr & PAGE_MASK,
 						 clen + slop);
 			memcpy(dest_p + slop, src_p, clen);
-			early_iounmap(dest_p, clen + slop);
+			early_memunmap(dest_p, clen + slop);
 			src_p += clen;
 			dest_addr += clen;
 			size -= clen;
-- 
2.8.2



From aleksey.makarov at linaro.org  Tue May 17 05:06:02 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Tue, 17 May 2016 15:06:02 +0300
Subject: [PATCH 2/3] ACPI: table upgrade: move early_initrd_acpi_init() to
 header file
In-Reply-To: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1463486765-31827-3-git-send-email-aleksey.makarov@linaro.org>

Move early_initrd_acpi_init() to header file so that
it can be used with architectures other than X86

Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
---
 arch/x86/kernel/setup.c | 7 -------
 drivers/acpi/tables.c   | 7 +++++--
 include/linux/acpi.h    | 4 ++--
 3 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index c4e7b39..5ddbbfd 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -399,10 +399,6 @@ static void __init reserve_initrd(void)
 	memblock_free(ramdisk_image, ramdisk_end - ramdisk_image);
 }
 
-static void __init early_initrd_acpi_init(void)
-{
-	early_acpi_table_init((void *)initrd_start, initrd_end - initrd_start);
-}
 #else
 static void __init early_reserve_initrd(void)
 {
@@ -410,9 +406,6 @@ static void __init early_reserve_initrd(void)
 static void __init reserve_initrd(void)
 {
 }
-static void __init early_initrd_acpi_init(void)
-{
-}
 #endif /* CONFIG_BLK_DEV_INITRD */
 
 static void __init parse_setup_data(void)
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 449a649..82be84a 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -34,6 +34,7 @@
 #include <linux/bootmem.h>
 #include <linux/earlycpio.h>
 #include <linux/memblock.h>
+#include <linux/initrd.h>
 #include "internal.h"
 
 #ifdef CONFIG_ACPI_CUSTOM_DSDT
@@ -742,9 +743,11 @@ acpi_os_table_override(struct acpi_table_header *existing_table,
 	return AE_OK;
 }
 
-void __init early_acpi_table_init(void *data, size_t size)
+void __init early_initrd_acpi_init(void)
 {
-	acpi_table_initrd_init(data, size);
+#ifdef CONFIG_BLK_DEV_INITRD
+	acpi_table_initrd_init((void *)initrd_start, initrd_end - initrd_start);
+#endif
 }
 
 /*
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 288fac5..cb700c1 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -208,7 +208,7 @@ void acpi_boot_table_init (void);
 int acpi_mps_check (void);
 int acpi_numa_init (void);
 
-void early_acpi_table_init(void *data, size_t size);
+void early_initrd_acpi_init(void);
 int acpi_table_init (void);
 int acpi_table_parse(char *id, acpi_tbl_table_handler handler);
 int __init acpi_parse_entries(char *id, unsigned long table_size,
@@ -588,7 +588,7 @@ static inline const char *acpi_dev_name(struct acpi_device *adev)
 	return NULL;
 }
 
-static inline void early_acpi_table_init(void *data, size_t size) { }
+static inline void early_initrd_acpi_init(void) { }
 static inline void acpi_early_init(void) { }
 static inline void acpi_subsystem_init(void) { }
 
-- 
2.8.2



From aleksey.makarov at linaro.org  Tue May 17 05:06:03 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Tue, 17 May 2016 15:06:03 +0300
Subject: [PATCH 3/3] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
In-Reply-To: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1463486765-31827-4-git-send-email-aleksey.makarov@linaro.org>

From: Jon Masters <jcm at redhat.com>

This patch adds support for ACPI_TABLE_UPGRADE for ARM64

To access initrd image we need to move initialization
of linear mapping a bit earlier.

Signed-off-by: Jon Masters <jcm at redhat.com>
Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
---
 arch/arm64/kernel/setup.c |  6 ++++--
 drivers/acpi/Kconfig      |  2 +-
 drivers/acpi/tables.c     | 10 +++++++++-
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index feab2ee..1d5e24f 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -261,11 +261,13 @@ void __init setup_arch(char **cmdline_p)
 	efi_init();
 	arm64_memblock_init();
 
+	paging_init();
+
+	early_initrd_acpi_init();
+
 	/* Parse the ACPI tables for possible boot-time configuration */
 	acpi_boot_table_init();
 
-	paging_init();
-
 	if (acpi_disabled)
 		unflatten_device_tree();
 
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index c204344..ec694c0 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -313,7 +313,7 @@ config ACPI_CUSTOM_DSDT
 
 config ACPI_TABLE_UPGRADE
 	bool "Allow upgrading ACPI tables via initrd"
-	depends on BLK_DEV_INITRD && X86
+	depends on BLK_DEV_INITRD && (X86 || ARM64)
 	default y
 	help
 	  This option provides functionality to upgrade arbitrary ACPI tables
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 82be84a..c35034d8 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -482,6 +482,14 @@ static DECLARE_BITMAP(acpi_initrd_installed, NR_ACPI_INITRD_TABLES);
 
 #define MAP_CHUNK_SIZE   (NR_FIX_BTMAPS << PAGE_SHIFT)
 
+#if defined(CONFIG_X86)
+#define MAX_PHYS_ACPI_TABLES (max_low_pfn_mapped << PAGE_SHIFT)
+#elif defined(CONFIG_ARM64)
+#define MAX_PHYS_ACPI_TABLES PFN_PHYS(max_pfn)
+#else
+#error "MAX_PHYS_ACPI_TABLES is not defiend for this architecture"
+#endif
+
 static void __init acpi_table_initrd_init(void *data, size_t size)
 {
 	int sig, no, table_nr = 0, total_offset = 0;
@@ -541,7 +549,7 @@ static void __init acpi_table_initrd_init(void *data, size_t size)
 		return;
 
 	acpi_tables_addr =
-		memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
+		memblock_find_in_range(0, MAX_PHYS_ACPI_TABLES,
 				       all_tables_size, PAGE_SIZE);
 	if (!acpi_tables_addr) {
 		WARN_ON(1);
-- 
2.8.2



From boris.brezillon at free-electrons.com  Tue May 17 05:08:03 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 17 May 2016 14:08:03 +0200
Subject: [PATCH] pwm: atmel-hlcdc: Fix default PWM polarity
In-Reply-To: <20160517110005.GA26166@ulmo.ba.sec>
References: <1463476352-7485-1-git-send-email-boris.brezillon@free-electrons.com>
 <20160517110005.GA26166@ulmo.ba.sec>
Message-ID: <20160517140803.078e3f5e@bbrezillon>

Hi Thierry,

On Tue, 17 May 2016 13:00:05 +0200
Thierry Reding <thierry.reding at gmail.com> wrote:

> On Tue, May 17, 2016 at 11:12:32AM +0200, Boris Brezillon wrote:
> > The PWM device exposed by the HLCDC IP is configured with an inverted
> > polarity by default. Registering the PWM chip with the normal polarity
> > was not a problem before commit 42e8992c58d4 ("pwm: Add core
> > infrastructure to allow atomic updates") because the ->set_polarity()
> > hook was called no matter the current polarity state, but this is no longer
> > the case.
> > 
> > Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> > Fixes: 42e8992c58d4 ("pwm: Add core infrastructure to allow atomic updates")  
> 
> That's not technically correct, because it's the driver that has the
> bug. The core change merely exposes it. How about if I sort this into
> the pwm-atomic branch and reword the commit message accordingly? That
> way things should all stay bisectible.
> 
> Then again, given the breakage caused by the pwm_args patch I suppose
> it doesn't matter much because that's part of a stable branch that I
> can't rebase.

If I understood correctly, you plan to rebase your pwm-atomic branch to
insert this commit before commit 42e8992c58d4 ("pwm: Add core
infrastructure to allow atomic updates").

Could you consider taking the following commit (or something similar if
you already have a fix) as the first commit of your pwm-atomic branch?

Sorry for the mess around the introduction of pwm_args and pwm_state
(that's not an excuse, but I've reworked this series so many time that I
forgot to check bisectibility on the last versions :-().

---
From ad73fa3a56c7320979425d64ab54c09b9d83d4cf Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon at free-electrons.com>
Date: Tue, 17 May 2016 13:55:02 +0200
Subject: [PATCH] pwm: Fix pwm_apply_args() call sites

pwm_apply_args() is supposed to initialize a PWM device according to the
arguments provided by the DT or the PWM lookup, but this function was
called inside pwm_device_request(), which in turn was called before the
core had a chance to initialize the pwm->args fields.

Fix that by calling pwm_apply_args directly in pwm_get() and of_pwm_get()
after initializing pwm->args field.

This commit also fixes an invalid pointer dereference introduced by
commit e39c0df1be5a ("pwm: Introduce the pwm_args concept").

Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
Fixes: e39c0df1be5a ("pwm: Introduce the pwm_args concept")
---
 drivers/pwm/core.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 680fbc7..22cf395 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -128,13 +128,6 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label)
 	set_bit(PWMF_REQUESTED, &pwm->flags);
 	pwm->label = label;
 
-	/*
-	 * FIXME: This should be removed once all PWM users properly make use
-	 * of struct pwm_args to initialize the PWM device. As long as this is
-	 * here, the PWM state and hardware state can get out of sync.
-	 */
-	pwm_apply_args(pwm);
-
 	return 0;
 }
 
@@ -627,6 +620,13 @@ struct pwm_device *of_pwm_get(struct device_node *np, const char *con_id)
 
 	pwm->label = con_id;
 
+	/*
+	 * FIXME: This should be removed once all PWM users properly make use
+	 * of struct pwm_args to initialize the PWM device. As long as this is
+	 * here, the PWM state and hardware state can get out of sync.
+	 */
+	pwm_apply_args(pwm);
+
 put:
 	of_node_put(args.np);
 
@@ -754,13 +754,20 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
 	if (!chip)
 		goto out;
 
-	pwm->args.period = chosen->period;
-	pwm->args.polarity = chosen->polarity;
-
 	pwm = pwm_request_from_chip(chip, chosen->index, con_id ?: dev_id);
 	if (IS_ERR(pwm))
 		goto out;
 
+	pwm->args.period = chosen->period;
+	pwm->args.polarity = chosen->polarity;
+
+	/*
+	 * FIXME: This should be removed once all PWM users properly make use
+	 * of struct pwm_args to initialize the PWM device. As long as this is
+	 * here, the PWM state and hardware state can get out of sync.
+	 */
+	pwm_apply_args(pwm);
+
 out:
 	mutex_unlock(&pwm_lookup_lock);
 	return pwm;


From szabolcs.nagy at arm.com  Tue May 17 05:10:53 2016
From: szabolcs.nagy at arm.com (Szabolcs Nagy)
Date: Tue, 17 May 2016 13:10:53 +0100
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <573B0A4D.4090704@arm.com>

On 05/04/16 23:08, Yury Norov wrote:
> This version is rebased on kernel v4.6-rc2, and has fixes in signal subsystem.
> It works with updated glibc [1] (though very draft), and tested with LTP.
> 
> It was tested on QEMU and ThunderX machines. No major difference found.
> This is RFC because ILP32 is not tested in big-endian mode.
> 
>  v3: https://lkml.org/lkml/2014/9/3/704
>  v4: https://lkml.org/lkml/2015/4/13/691
>  v5: https://lkml.org/lkml/2015/9/29/911
> 
>  v6:
>  - time_t, __kenel_off_t and other types turned to be 32-bit
>    for compatibility reasons (after v5 discussion);

i added libc-alpha to cc, the thread is at
https://lkml.org/lkml/2016/4/5/872
or http://thread.gmane.org/gmane.linux.kernel.cross-arch/31449

the kernel position seems to be that the aarch64 ilp32 syscall abi
will follow regular 32bit abis (apart from signal context and ptrace
related things and syscalls will take 64bit arguments).

i think the reasoning is that this allows legacy (non-64bit-safe)
software to use this abi on aarch64 without trouble.

i think this design should be ok for glibc.

there are some interop issues between processes following different abis
(e.g. shared mutexes, abi specific file formats, lib paths,..) which apply,
but i assume it is no different from existing 32bit vs 64bit issues.

the 32bit time_t and off_t are ugly and i wonder if 32bit __kernel_off_t
is really necessary. (i don't see where that is changed: it is supposed
to be __kernel_long_t which is 64bit).

i think even legacy software should be able to deal with 64bit off_t,
so we could avoid having two sets of filesystem apis or is 64bit-only
off_t more work to do in linux/glibc?

>  - related changes applied to ILP32 syscall table and handlers;
>  - ILP32 VDSO code excluded. It's not mandatory, and caused questions
>    during review process. We definitely make sure we will follow up
>    with a VDSO later on because it is needed for performance reasons;
>  - fixed build issues with different combinations of AARCH32 / ILP32
>    enabling in config;
>  - ILP32 TLS bug fixed;
>  - entry32-common.S introduced to hold wrappers needed for both ILP32
>    and AARCH32_EL0;
>  - documentation updated according to latest changes;
>  - rebased to the current head;
>  - coding style re-checked;
>  - ILP32 syscall table turned around.
> 
>    rfc3:
>  - all structures and system calls are just like AARCH32 ones now. with 2
>    exceptions: syscalls that take 64-bit parameter in 2 32-bit regosters
>    are replaced with LP64 version; struct rt_sigframe is constructed both
>    from LP64 and AARCH32 fields to be consistent with AARCH64 register set;
>  - documentation rewritten accordingly;
>  - common code for all 3 ABIs is moved to separated files for easy use,
>    new headers and objects are introduced, incl: is_compat.h, thread_bits.h,
>    signal_common.h, signal32_common.h.
>  - ILP32 VDSO code restored, Nathans comments are addressed;
>  - patch "arm64: ilp32: force IPC_64 in msgctl, shmctl, semctl" removed, as
>    Arnd suggested general solution for IPC_64 problem.
> 
>    rfc4:
>  - sys_ilp32.c syscall list is fixed according to comments;
>  - binfmt_elf32.c and binfmt_ilp32.c are introduced to host the code handling
>    corresponding formats;
>  - statfs64, fstsatfs64 and mmap wrappers are removed;
>  - rebased on v4.4-rc8 + http://www.spinics.net/lists/kernel/msg2151759.html
> 
>  rfc5:
>  - addressed rfc4 comments;
>  - turned s390 compat wrappers to be generic and applied it to arm64/ilp32.
>    Heiko Carsten and Martin Schwidefsky added to CC as s390 maintainers.
> 
>  rfc6:
>  - glibc follows new ABI, [1];
>  - significant rework for signal subsystem (patches 21, 23) - struct ucontext
>    is now corresponds user representation;
>  - compat wrappers and 32-bit off_t patchsets are joined with this patchset,
>    as for now ilp32 is the only user for them;
>  - moved to kernel v4.6-rc2;
>  - few minor bugfixes.
> 
> [1] https://github.com/norov/glibc/tree/new-api
> 
> Andrew Pinski (7):
>   arm64: ensure the kernel is compiled for LP64
>   arm64: rename COMPAT to AARCH32_EL0 in Kconfig
>   arm64: change some CONFIG_COMPAT over to use CONFIG_AARCH32_EL0
>     instead
>   arm64:uapi: set __BITS_PER_LONG correctly for ILP32 and LP64
>   arm64:ilp32: add sys_ilp32.c and a separate table (in entry.S) to use
>     it
>   arm64: ilp32: introduce ilp32-specific handlers for sigframe and
>     ucontext
>   arm64:ilp32: add ARM64_ILP32 to Kconfig
> 
> Bamvor Jian Zhang (1):
>   arm64: compat: change config dependences to aarch32
> 
> Philipp Tomsich (1):
>   arm64:ilp32: add vdso-ilp32 and use for signal return
> 
> Yury Norov (16):
>   all: syscall wrappers: add documentation
>   all: introduce COMPAT_WRAPPER option and enable it for s390
>   all: s390: move wrapper infrastructure to generic headers
>   all: s390: move compat_wrappers.c from arch/s390/kernel to kernel/
>   all: wrap needed syscalls in generic unistd
>   compat ABI: use non-compat openat and open_by_handle_at variants
>   32-bit ABI: introduce ARCH_32BIT_OFF_T config option
>   arm64: ilp32: add documentation on the ILP32 ABI for ARM64
>   thread: move thread bits accessors to separated file
>   arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)
>   arm64: ilp32: add is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64
>   arm64: introduce binfmt_elf32.c
>   arm64: ilp32: introduce binfmt_ilp32.c
>   arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32
>   arm64: signal: share lp64 signal routines to ilp32
>   arm64: signal32: move ilp32 and aarch32 common code to separated file
> 
>  Documentation/adding-syscalls.txt             |  32 +++
>  Documentation/arm64/ilp32.txt                 |  13 ++
>  arch/Kconfig                                  |   8 +
>  arch/arc/Kconfig                              |   1 +
>  arch/arm/Kconfig                              |   1 +
>  arch/arm64/Kconfig                            |  17 +-
>  arch/arm64/Makefile                           |   5 +
>  arch/arm64/include/asm/compat.h               |  19 +-
>  arch/arm64/include/asm/elf.h                  |  35 +---
>  arch/arm64/include/asm/fpsimd.h               |   2 +-
>  arch/arm64/include/asm/ftrace.h               |   2 +-
>  arch/arm64/include/asm/hwcap.h                |   6 +-
>  arch/arm64/include/asm/is_compat.h            |  84 ++++++++
>  arch/arm64/include/asm/memory.h               |   3 +-
>  arch/arm64/include/asm/processor.h            |  11 +-
>  arch/arm64/include/asm/ptrace.h               |   2 +-
>  arch/arm64/include/asm/signal32.h             |   6 +-
>  arch/arm64/include/asm/signal32_common.h      |  25 +++
>  arch/arm64/include/asm/signal_common.h        |  33 +++
>  arch/arm64/include/asm/signal_ilp32.h         |  34 ++++
>  arch/arm64/include/asm/syscall.h              |   2 +-
>  arch/arm64/include/asm/thread_info.h          |   3 +-
>  arch/arm64/include/asm/unistd.h               |  11 +-
>  arch/arm64/include/asm/unistd32.h             |   2 +-
>  arch/arm64/include/asm/vdso.h                 |   6 +
>  arch/arm64/include/uapi/asm/bitsperlong.h     |   9 +-
>  arch/arm64/kernel/Makefile                    |  12 +-
>  arch/arm64/kernel/asm-offsets.c               |   2 +-
>  arch/arm64/kernel/binfmt_elf32.c              |  33 +++
>  arch/arm64/kernel/binfmt_ilp32.c              |  91 +++++++++
>  arch/arm64/kernel/cpufeature.c                |   8 +-
>  arch/arm64/kernel/cpuinfo.c                   |   4 +-
>  arch/arm64/kernel/entry.S                     |  18 +-
>  arch/arm64/kernel/entry_ilp32.S               |  23 +++
>  arch/arm64/kernel/head.S                      |   2 +-
>  arch/arm64/kernel/hw_breakpoint.c             |  10 +-
>  arch/arm64/kernel/perf_regs.c                 |   2 +-
>  arch/arm64/kernel/process.c                   |   7 +-
>  arch/arm64/kernel/ptrace.c                    |  67 ++++++-
>  arch/arm64/kernel/signal.c                    | 100 ++++++----
>  arch/arm64/kernel/signal32.c                  |  85 --------
>  arch/arm64/kernel/signal32_common.c           | 115 +++++++++++
>  arch/arm64/kernel/signal_ilp32.c              | 192 ++++++++++++++++++
>  arch/arm64/kernel/sys32.c                     |   1 +
>  arch/arm64/kernel/sys_ilp32.c                 |  68 +++++++
>  arch/arm64/kernel/traps.c                     |   5 +-
>  arch/arm64/kernel/vdso-ilp32/.gitignore       |   2 +
>  arch/arm64/kernel/vdso-ilp32/Makefile         |  72 +++++++
>  arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S     |  33 +++
>  arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S |  95 +++++++++
>  arch/arm64/kernel/vdso.c                      |  65 ++++--
>  arch/blackfin/Kconfig                         |   1 +
>  arch/cris/Kconfig                             |   1 +
>  arch/frv/Kconfig                              |   1 +
>  arch/h8300/Kconfig                            |   1 +
>  arch/hexagon/Kconfig                          |   1 +
>  arch/m32r/Kconfig                             |   1 +
>  arch/m68k/Kconfig                             |   1 +
>  arch/metag/Kconfig                            |   1 +
>  arch/microblaze/Kconfig                       |   1 +
>  arch/mips/Kconfig                             |   1 +
>  arch/mn10300/Kconfig                          |   1 +
>  arch/nios2/Kconfig                            |   1 +
>  arch/openrisc/Kconfig                         |   1 +
>  arch/parisc/Kconfig                           |   1 +
>  arch/powerpc/Kconfig                          |   1 +
>  arch/s390/Kconfig                             |   1 +
>  arch/s390/include/asm/compat.h                |  17 +-
>  arch/s390/kernel/Makefile                     |   2 +-
>  arch/s390/kernel/compat_linux.c               |   4 +
>  arch/s390/kernel/compat_wrapper.c             | 180 -----------------
>  arch/score/Kconfig                            |   1 +
>  arch/sh/Kconfig                               |   1 +
>  arch/sparc/Kconfig                            |   1 +
>  arch/tile/Kconfig                             |   1 +
>  arch/tile/kernel/compat.c                     |   3 +
>  arch/unicore32/Kconfig                        |   1 +
>  arch/x86/Kconfig                              |   1 +
>  arch/x86/um/Kconfig                           |   1 +
>  arch/xtensa/Kconfig                           |   1 +
>  drivers/clocksource/arm_arch_timer.c          |   2 +-
>  include/linux/compat.h                        | 277 ++++++++++++++++++++++++++
>  include/linux/fcntl.h                         |   2 +-
>  include/linux/ptrace.h                        |   6 +
>  include/linux/syscalls.h                      |  57 +-----
>  include/linux/syscalls_structs.h              |  60 ++++++
>  include/linux/thread_bits.h                   |  55 +++++
>  include/linux/thread_info.h                   |  44 +---
>  include/uapi/asm-generic/unistd.h             | 231 ++++++++++-----------
>  kernel/Makefile                               |   1 +
>  kernel/compat_wrapper.c                       | 175 ++++++++++++++++
>  kernel/ptrace.c                               |  10 +-
>  92 files changed, 1997 insertions(+), 637 deletions(-)
>  create mode 100644 Documentation/arm64/ilp32.txt
>  create mode 100644 arch/arm64/include/asm/is_compat.h
>  create mode 100644 arch/arm64/include/asm/signal32_common.h
>  create mode 100644 arch/arm64/include/asm/signal_common.h
>  create mode 100644 arch/arm64/include/asm/signal_ilp32.h
>  create mode 100644 arch/arm64/kernel/binfmt_elf32.c
>  create mode 100644 arch/arm64/kernel/binfmt_ilp32.c
>  create mode 100644 arch/arm64/kernel/entry_ilp32.S
>  create mode 100644 arch/arm64/kernel/signal32_common.c
>  create mode 100644 arch/arm64/kernel/signal_ilp32.c
>  create mode 100644 arch/arm64/kernel/sys_ilp32.c
>  create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore
>  create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile
>  create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
>  create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
>  delete mode 100644 arch/s390/kernel/compat_wrapper.c
>  create mode 100644 include/linux/syscalls_structs.h
>  create mode 100644 include/linux/thread_bits.h
>  create mode 100644 kernel/compat_wrapper.c
> 



From thierry.reding at gmail.com  Tue May 17 05:19:17 2016
From: thierry.reding at gmail.com (Thierry Reding)
Date: Tue, 17 May 2016 14:19:17 +0200
Subject: [PATCH] pwm: atmel-hlcdc: Fix default PWM polarity
In-Reply-To: <20160517140803.078e3f5e@bbrezillon>
References: <1463476352-7485-1-git-send-email-boris.brezillon@free-electrons.com>
 <20160517110005.GA26166@ulmo.ba.sec>
 <20160517140803.078e3f5e@bbrezillon>
Message-ID: <20160517121917.GD26166@ulmo.ba.sec>

On Tue, May 17, 2016 at 02:08:03PM +0200, Boris Brezillon wrote:
> Hi Thierry,
> 
> On Tue, 17 May 2016 13:00:05 +0200
> Thierry Reding <thierry.reding at gmail.com> wrote:
> 
> > On Tue, May 17, 2016 at 11:12:32AM +0200, Boris Brezillon wrote:
> > > The PWM device exposed by the HLCDC IP is configured with an inverted
> > > polarity by default. Registering the PWM chip with the normal polarity
> > > was not a problem before commit 42e8992c58d4 ("pwm: Add core
> > > infrastructure to allow atomic updates") because the ->set_polarity()
> > > hook was called no matter the current polarity state, but this is no longer
> > > the case.
> > > 
> > > Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> > > Fixes: 42e8992c58d4 ("pwm: Add core infrastructure to allow atomic updates")  
> > 
> > That's not technically correct, because it's the driver that has the
> > bug. The core change merely exposes it. How about if I sort this into
> > the pwm-atomic branch and reword the commit message accordingly? That
> > way things should all stay bisectible.
> > 
> > Then again, given the breakage caused by the pwm_args patch I suppose
> > it doesn't matter much because that's part of a stable branch that I
> > can't rebase.
> 
> If I understood correctly, you plan to rebase your pwm-atomic branch to
> insert this commit before commit 42e8992c58d4 ("pwm: Add core
> infrastructure to allow atomic updates").
> 
> Could you consider taking the following commit (or something similar if
> you already have a fix) as the first commit of your pwm-atomic branch?
> 
> Sorry for the mess around the introduction of pwm_args and pwm_state
> (that's not an excuse, but I've reworked this series so many time that I
> forgot to check bisectibility on the last versions :-().
> 
> ---
> From ad73fa3a56c7320979425d64ab54c09b9d83d4cf Mon Sep 17 00:00:00 2001
> From: Boris Brezillon <boris.brezillon at free-electrons.com>
> Date: Tue, 17 May 2016 13:55:02 +0200
> Subject: [PATCH] pwm: Fix pwm_apply_args() call sites
> 
> pwm_apply_args() is supposed to initialize a PWM device according to the
> arguments provided by the DT or the PWM lookup, but this function was
> called inside pwm_device_request(), which in turn was called before the
> core had a chance to initialize the pwm->args fields.
> 
> Fix that by calling pwm_apply_args directly in pwm_get() and of_pwm_get()
> after initializing pwm->args field.
> 
> This commit also fixes an invalid pointer dereference introduced by
> commit e39c0df1be5a ("pwm: Introduce the pwm_args concept").
> 
> Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> Fixes: e39c0df1be5a ("pwm: Introduce the pwm_args concept")
> ---
>  drivers/pwm/core.c | 27 +++++++++++++++++----------
>  1 file changed, 17 insertions(+), 10 deletions(-)

This looks good to me. However I can't easily apply this because git
gets confused by the existing headers. Also manually copying out the
patch yields patch corruption that I don't exactly know how to fix.

I think you can inline patches by using a scissor mark (--- >8 ---)
instead of the signature separator (---). Or you can attach the patch
with "Content-Disposition: inline".

Rather than putting this into the pwm-atomic branch, I'll probably stick
it into the pwm-args branch on top of the existing patch. Technically
only the existing patch needs to be stable, so the branch can still
evolve.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160517/596c6957/attachment.sig>

From boris.brezillon at free-electrons.com  Tue May 17 05:27:25 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Tue, 17 May 2016 14:27:25 +0200
Subject: [PATCH] pwm: atmel-hlcdc: Fix default PWM polarity
In-Reply-To: <20160517121917.GD26166@ulmo.ba.sec>
References: <1463476352-7485-1-git-send-email-boris.brezillon@free-electrons.com>
 <20160517110005.GA26166@ulmo.ba.sec>
 <20160517140803.078e3f5e@bbrezillon>
 <20160517121917.GD26166@ulmo.ba.sec>
Message-ID: <20160517142725.7f7c82b4@bbrezillon>

On Tue, 17 May 2016 14:19:17 +0200
Thierry Reding <thierry.reding at gmail.com> wrote:

> On Tue, May 17, 2016 at 02:08:03PM +0200, Boris Brezillon wrote:
> > Hi Thierry,
> > 
> > On Tue, 17 May 2016 13:00:05 +0200
> > Thierry Reding <thierry.reding at gmail.com> wrote:
> >   
> > > On Tue, May 17, 2016 at 11:12:32AM +0200, Boris Brezillon wrote:  
> > > > The PWM device exposed by the HLCDC IP is configured with an inverted
> > > > polarity by default. Registering the PWM chip with the normal polarity
> > > > was not a problem before commit 42e8992c58d4 ("pwm: Add core
> > > > infrastructure to allow atomic updates") because the ->set_polarity()
> > > > hook was called no matter the current polarity state, but this is no longer
> > > > the case.
> > > > 
> > > > Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> > > > Fixes: 42e8992c58d4 ("pwm: Add core infrastructure to allow atomic updates")    
> > > 
> > > That's not technically correct, because it's the driver that has the
> > > bug. The core change merely exposes it. How about if I sort this into
> > > the pwm-atomic branch and reword the commit message accordingly? That
> > > way things should all stay bisectible.
> > > 
> > > Then again, given the breakage caused by the pwm_args patch I suppose
> > > it doesn't matter much because that's part of a stable branch that I
> > > can't rebase.  
> > 
> > If I understood correctly, you plan to rebase your pwm-atomic branch to
> > insert this commit before commit 42e8992c58d4 ("pwm: Add core
> > infrastructure to allow atomic updates").
> > 
> > Could you consider taking the following commit (or something similar if
> > you already have a fix) as the first commit of your pwm-atomic branch?
> > 
> > Sorry for the mess around the introduction of pwm_args and pwm_state
> > (that's not an excuse, but I've reworked this series so many time that I
> > forgot to check bisectibility on the last versions :-().
> > 
> > ---
> > From ad73fa3a56c7320979425d64ab54c09b9d83d4cf Mon Sep 17 00:00:00 2001
> > From: Boris Brezillon <boris.brezillon at free-electrons.com>
> > Date: Tue, 17 May 2016 13:55:02 +0200
> > Subject: [PATCH] pwm: Fix pwm_apply_args() call sites
> > 
> > pwm_apply_args() is supposed to initialize a PWM device according to the
> > arguments provided by the DT or the PWM lookup, but this function was
> > called inside pwm_device_request(), which in turn was called before the
> > core had a chance to initialize the pwm->args fields.
> > 
> > Fix that by calling pwm_apply_args directly in pwm_get() and of_pwm_get()
> > after initializing pwm->args field.
> > 
> > This commit also fixes an invalid pointer dereference introduced by
> > commit e39c0df1be5a ("pwm: Introduce the pwm_args concept").
> > 
> > Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> > Fixes: e39c0df1be5a ("pwm: Introduce the pwm_args concept")
> > ---
> >  drivers/pwm/core.c | 27 +++++++++++++++++----------
> >  1 file changed, 17 insertions(+), 10 deletions(-)  
> 
> This looks good to me. However I can't easily apply this because git
> gets confused by the existing headers. Also manually copying out the
> patch yields patch corruption that I don't exactly know how to fix.
> 
> I think you can inline patches by using a scissor mark (--- >8 ---)
> instead of the signature separator (---). Or you can attach the patch
> with "Content-Disposition: inline".

Ok, it's my PEBKAC day. Here it is with the scissor mark. As mentioned
on IRC, you'll also have to squash those changes [1] into 93c0d9b
("pwm: Keep PWM state in sync with hardware state").

> 
> Rather than putting this into the pwm-atomic branch, I'll probably stick
> it into the pwm-args branch on top of the existing patch. Technically
> only the existing patch needs to be stable, so the branch can still
> evolve.

Ok, great!

Thanks,

Boris

[1]http://code.bulix.org/egoo4y-98645

--->8---
From ad73fa3a56c7320979425d64ab54c09b9d83d4cf Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon at free-electrons.com>
Date: Tue, 17 May 2016 13:55:02 +0200
Subject: [PATCH] pwm: Fix pwm_apply_args() call sites

pwm_apply_args() is supposed to initialize a PWM device according to the
arguments provided by the DT or the PWM lookup, but this function was
called inside pwm_device_request(), which in turn was called before the
core had a chance to initialize the pwm->args fields.

Fix that by calling pwm_apply_args directly in pwm_get() and of_pwm_get()
after initializing pwm->args field.

This commit also fixes an invalid pointer dereference introduced by
commit e39c0df1be5a ("pwm: Introduce the pwm_args concept").

Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
Fixes: e39c0df1be5a ("pwm: Introduce the pwm_args concept")
---
 drivers/pwm/core.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 680fbc7..22cf395 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -128,13 +128,6 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label)
 	set_bit(PWMF_REQUESTED, &pwm->flags);
 	pwm->label = label;
 
-	/*
-	 * FIXME: This should be removed once all PWM users properly make use
-	 * of struct pwm_args to initialize the PWM device. As long as this is
-	 * here, the PWM state and hardware state can get out of sync.
-	 */
-	pwm_apply_args(pwm);
-
 	return 0;
 }
 
@@ -627,6 +620,13 @@ struct pwm_device *of_pwm_get(struct device_node *np, const char *con_id)
 
 	pwm->label = con_id;
 
+	/*
+	 * FIXME: This should be removed once all PWM users properly make use
+	 * of struct pwm_args to initialize the PWM device. As long as this is
+	 * here, the PWM state and hardware state can get out of sync.
+	 */
+	pwm_apply_args(pwm);
+
 put:
 	of_node_put(args.np);
 
@@ -754,13 +754,20 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
 	if (!chip)
 		goto out;
 
-	pwm->args.period = chosen->period;
-	pwm->args.polarity = chosen->polarity;
-
 	pwm = pwm_request_from_chip(chip, chosen->index, con_id ?: dev_id);
 	if (IS_ERR(pwm))
 		goto out;
 
+	pwm->args.period = chosen->period;
+	pwm->args.polarity = chosen->polarity;
+
+	/*
+	 * FIXME: This should be removed once all PWM users properly make use
+	 * of struct pwm_args to initialize the PWM device. As long as this is
+	 * here, the PWM state and hardware state can get out of sync.
+	 */
+	pwm_apply_args(pwm);
+
 out:
 	mutex_unlock(&pwm_lookup_lock);
 	return pwm;


From tn at semihalf.com  Tue May 17 05:32:19 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 17 May 2016 14:32:19 +0200
Subject: [RFC PATCH 09/11] drivers: acpi: implement acpi_dma_configure
In-Reply-To: <573AD142.6020107@semihalf.com>
References: <1460654743-7896-1-git-send-email-lorenzo.pieralisi@arm.com>
 <1460654743-7896-10-git-send-email-lorenzo.pieralisi@arm.com>
 <573AD142.6020107@semihalf.com>
Message-ID: <573B0F53.109@semihalf.com>



On 17.05.2016 10:07, Tomasz Nowicki wrote:
> Hi Lorenzo,
>
> On 14.04.2016 19:25, Lorenzo Pieralisi wrote:
>> On DT based systems, the of_dma_configure() API implements DMA
>> configuration
>> for a given device. On ACPI systems an API equivalent to
>> of_dma_configure()
>> is missing which implies that it is currently not possible to set-up DMA
>> operations for devices through the ACPI generic kernel layer.
>>
>> This patch fills the gap by introducing acpi_dma_configure/deconfigure()
>> calls, that carry out IOMMU configuration through IORT (on systems where
>> it is present) and call arch_setup_dma_ops(...) with the retrieved
>> parameters.
>>
>> The DMA range size passed to arch_setup_dma_ops() is sized according
>> to the device coherent_dma_mask (starting at address 0x0), mirroring the
>> DT probing path behaviour when a dma-ranges property is not provided
>> for the device being probed; this changes the current
>> arch_setup_dma_ops()
>> call parameters in the ACPI probing case, but since arch_setup_dma_ops()
>> is a NOP on all architectures but ARM/ARM64 this patch does not change
>> the current kernel behaviour on them.
>>
>> This patch updates ACPI and PCI core code to use the newly introduced
>> acpi_dma_configure function, providing the same functionality
>> as of_dma_configure on ARM systems and leaving behaviour unchanged
>> for all other arches.
>>
>> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
>> Cc: Bjorn Helgaas <bhelgaas at google.com>
>> Cc: Robin Murphy <robin.murphy at arm.com>
>> Cc: Tomasz Nowicki <tn at semihalf.com>
>> Cc: Joerg Roedel <joro at 8bytes.org>
>> Cc: "Rafael J. Wysocki" <rjw at rjwysocki.net>
>> ---
>>   drivers/acpi/glue.c     |  4 +--
>>   drivers/acpi/iort.c     | 85
>> +++++++++++++++++++++++++++++++++++++++++++++++++
>>   drivers/acpi/scan.c     | 29 +++++++++++++++++
>>   drivers/pci/probe.c     |  3 +-
>>   include/acpi/acpi_bus.h |  2 ++
>>   include/linux/acpi.h    |  5 +++
>>   include/linux/iort.h    |  9 ++++++
>>   7 files changed, 133 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
>> index 5ea5dc2..f8d6564 100644
>> --- a/drivers/acpi/glue.c
>> +++ b/drivers/acpi/glue.c
>> @@ -227,8 +227,7 @@ int acpi_bind_one(struct device *dev, struct
>> acpi_device *acpi_dev)
>>
>>       attr = acpi_get_dma_attr(acpi_dev);
>>       if (attr != DEV_DMA_NOT_SUPPORTED)
>> -        arch_setup_dma_ops(dev, 0, 0, NULL,
>> -                   attr == DEV_DMA_COHERENT);
>> +        acpi_dma_configure(dev, attr);
>>
>>       acpi_physnode_link_name(physical_node_name, node_id);
>>       retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
>> @@ -251,6 +250,7 @@ int acpi_bind_one(struct device *dev, struct
>> acpi_device *acpi_dev)
>>       return 0;
>>
>>    err:
>> +    acpi_dma_deconfigure(dev);
>>       ACPI_COMPANION_SET(dev, NULL);
>>       put_device(dev);
>>       put_device(&acpi_dev->dev);
>> diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
>> index 2b5ce65..b1bb8fb 100644
>> --- a/drivers/acpi/iort.c
>> +++ b/drivers/acpi/iort.c
>> @@ -72,6 +72,31 @@ int iort_iommu_set_node(struct iommu_ops *ops,
>> struct acpi_iort_node *node,
>>       return 0;
>>   }
>>
>> +/**
>> + * iort_iommu_get_node - Retrieve iort_iommu_node associated with an
>> IORT node.
>> + *
>> + * @node: IORT table node to be looked-up
>> + *
>> + * Returns: iort_iommu_node pointer on success
>> + *          NULL on failure
>> + */
>> +static struct iort_iommu_node *iort_iommu_get_node(struct
>> acpi_iort_node *node)
>> +{
>> +    struct iort_iommu_node *iommu_node;
>> +
>> +    spin_lock(&iort_iommu_lock);
>> +    list_for_each_entry(iommu_node, &iort_iommu_list, list) {
>> +        if (iommu_node->node == node)
>> +            goto found;
>> +    }
>> +
>> +    iommu_node = NULL;
>> +found:
>> +    spin_unlock(&iort_iommu_lock);
>> +
>> +    return iommu_node;
>> +}
>> +
>>   typedef acpi_status (*iort_find_node_callback)
>>       (struct acpi_iort_node *node, void *context);
>>
>> @@ -405,6 +430,66 @@ iort_pci_get_domain(struct pci_dev *pdev, u32
>> req_id)
>>       return domain_handle;
>>   }
>>
>> +static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
>> +{
>> +    u32 *rid = data;
>> +
>> +    *rid = alias;
>> +    return 0;
>> +}
>> +
>> +/**
>> + * iort_iommu_configure - Set-up IOMMU configuration for a device.
>> + *
>> + * @dev: device that requires IOMMU set-up
>> + *
>> + * Returns: iommu_ops pointer on configuration success
>> + *          NULL on configuration failure
>> + */
>> +struct iommu_ops *iort_iommu_configure(struct device *dev)
>> +{
>> +    struct acpi_iort_node *node, *parent;
>> +    struct iommu_ops *ops = NULL;
>> +    struct iommu_fwspec fwspec;
>> +    struct iort_iommu_node *iommu_node;
>> +    u32 rid = 0, devid = 0;
>> +
>> +    if (dev_is_pci(dev)) {
>> +        struct pci_bus *bus = to_pci_dev(dev)->bus;
>> +
>> +        pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
>> +                       &rid);
>> +
>> +        node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
>> +                      iort_find_dev_callback, &bus->dev);
>> +    } else
>> +        node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
>> +                      iort_find_dev_callback, dev);
>
> I think this will not work for finding host bridge stream ID. We still
> need to use ACPI_IORT_NODE_PCI_ROOT_COMPLEX but 'dev' is not PCI device,
> right?

After private conversation, I think this part is OK.

Thanks,
Tomasz


From mark.rutland at arm.com  Tue May 17 05:46:29 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 17 May 2016 13:46:29 +0100
Subject: [PATCH 3/3] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
In-Reply-To: <1463486765-31827-4-git-send-email-aleksey.makarov@linaro.org>
References: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
 <1463486765-31827-4-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <20160517124629.GE14955@leverpostej>

On Tue, May 17, 2016 at 03:06:03PM +0300, Aleksey Makarov wrote:
> From: Jon Masters <jcm at redhat.com>
> 
> This patch adds support for ACPI_TABLE_UPGRADE for ARM64

This feels like a tool to paper over problems rather than solve them.

If vendors are shipping horrendously broken tables today, clearly no
software has ever really supported them. So why add workarounds?

Why is this necessary? Is there a particular case for this, or is this
just for parity with x86?

IMO it would be better to put pressure on vendors to fix their FW and
provide sensible OS-agnostic update mechanisms.

> To access initrd image we need to move initialization
> of linear mapping a bit earlier.
> 
> Signed-off-by: Jon Masters <jcm at redhat.com>
> Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
> ---
>  arch/arm64/kernel/setup.c |  6 ++++--
>  drivers/acpi/Kconfig      |  2 +-
>  drivers/acpi/tables.c     | 10 +++++++++-
>  3 files changed, 14 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
> index feab2ee..1d5e24f 100644
> --- a/arch/arm64/kernel/setup.c
> +++ b/arch/arm64/kernel/setup.c
> @@ -261,11 +261,13 @@ void __init setup_arch(char **cmdline_p)
>  	efi_init();
>  	arm64_memblock_init();
>  
> +	paging_init();
> +
> +	early_initrd_acpi_init();

Do we actually need full paging up here?

Why can we not use fixmap based copying as we do for the other cases
prior to paging_init?

> +
>  	/* Parse the ACPI tables for possible boot-time configuration */
>  	acpi_boot_table_init();
>  
> -	paging_init();
> -
>  	if (acpi_disabled)
>  		unflatten_device_tree();
>  
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index c204344..ec694c0 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -313,7 +313,7 @@ config ACPI_CUSTOM_DSDT
>  
>  config ACPI_TABLE_UPGRADE
>  	bool "Allow upgrading ACPI tables via initrd"
> -	depends on BLK_DEV_INITRD && X86
> +	depends on BLK_DEV_INITRD && (X86 || ARM64)
>  	default y
>  	help

Perhaps ARCH_HAS_ACPI_TABLE_UPGRADE?

>  	  This option provides functionality to upgrade arbitrary ACPI tables
> diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
> index 82be84a..c35034d8 100644
> --- a/drivers/acpi/tables.c
> +++ b/drivers/acpi/tables.c
> @@ -482,6 +482,14 @@ static DECLARE_BITMAP(acpi_initrd_installed, NR_ACPI_INITRD_TABLES);
>  
>  #define MAP_CHUNK_SIZE   (NR_FIX_BTMAPS << PAGE_SHIFT)
>  
> +#if defined(CONFIG_X86)
> +#define MAX_PHYS_ACPI_TABLES (max_low_pfn_mapped << PAGE_SHIFT)
> +#elif defined(CONFIG_ARM64)
> +#define MAX_PHYS_ACPI_TABLES PFN_PHYS(max_pfn)
> +#else
> +#error "MAX_PHYS_ACPI_TABLES is not defiend for this architecture"
> +#endif

s/defiend/defined/

This should be defined in an arch-specific header if it is actually
arch-specific.

Thanks,
Mark.

> +
>  static void __init acpi_table_initrd_init(void *data, size_t size)
>  {
>  	int sig, no, table_nr = 0, total_offset = 0;
> @@ -541,7 +549,7 @@ static void __init acpi_table_initrd_init(void *data, size_t size)
>  		return;
>  
>  	acpi_tables_addr =
> -		memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
> +		memblock_find_in_range(0, MAX_PHYS_ACPI_TABLES,
>  				       all_tables_size, PAGE_SIZE);
>  	if (!acpi_tables_addr) {
>  		WARN_ON(1);
> -- 
> 2.8.2
> 


From sstabellini at kernel.org  Tue May 17 05:57:24 2016
From: sstabellini at kernel.org (Stefano Stabellini)
Date: Tue, 17 May 2016 13:57:24 +0100 (BST)
Subject: [Xen-devel] [GIT PULL] EFI ARM Xen support
In-Reply-To: <573AF50E.9090206@citrix.com>
References: <20160514190410.GA2283@codeblueprint.co.uk>
 <alpine.DEB.2.10.1605171109170.2494@sstabellini-ThinkPad-X260>
 <573AF50E.9090206@citrix.com>
Message-ID: <alpine.DEB.2.10.1605171153070.2494@sstabellini-ThinkPad-X260>

On Tue, 17 May 2016, David Vrabel wrote:
> On 17/05/16 11:12, Stefano Stabellini wrote:
> > On Sat, 14 May 2016, Matt Fleming wrote:
> >> Folks,
> >>
> >> Please pull the following branch which contains support for Xen on ARM
> >> EFI platforms.
> >>
> >> This merge includes a merge of Stefano's xen/linux-next branch to pull
> >> in the prerequisites required for Shannon's commit:
> >>
> >>   11ee5491e5ff ("Xen: EFI: Parse DT parameters for Xen specific UEFI")
> >>
> >> as it needs both the latest changes in the EFI 'next' branch (now
> >> tip/efi/core) and xen/linux-next.
> >>
> >> I have intentionally not included the individual patches as I would
> >> normally do in a pull request, so that commit history created by my
> >> merging of Stefano's branch is preserved, and so that there's no way
> >> to accidentally apply the patches individually.
> >>
> >> The following changes since commit 6c5450ef66816216e574885cf8d3ddb31ef77428:
> >>
> >>   efivarfs: Make efivarfs_file_ioctl() static (2016-05-07 07:06:13 +0200)
> >>
> >> are available in the git repository at:
> >>
> >>   git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git efi/arm-xen
> >>
> >> for you to fetch changes up to 11ee5491e5ff519e0d3a7018eb21351cb6955a98:
> >>
> >>   Xen: EFI: Parse DT parameters for Xen specific UEFI (2016-05-14 19:31:01 +0100)
> > 
> > Is this arrangement working for everybody, in particular the tip
> > maintainers?
> 
> Yes.

I meant the x86 tip maintainers (Thomas, Peter and Ingo).


From marc.zyngier at arm.com  Tue May 17 06:33:36 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 17 May 2016 14:33:36 +0100
Subject: [PATCH v4 22/56] KVM: arm/arm64: vgic-new: Add MMIO handling
 framework
In-Reply-To: <1463392481-26583-23-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-23-git-send-email-andre.przywara@arm.com>
Message-ID: <573B1DB0.7030901@arm.com>

On 16/05/16 10:53, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Add an MMIO handling framework to the VGIC emulation:
> Each register is described by its offset, size (or number of bits per
> IRQ, if applicable) and the read/write handler functions. We provide
> initialization macros to describe each GIC register later easily.
> 
> Separate dispatch functions for read and write accesses are connected
> to the kvm_io_bus framework and binary-search for the responsible
> register handler based on the offset address within the region.
> We convert the incoming data (referenced by a pointer) to the host's
> endianess and use pass-by-value to hand the data over to the actual
> handler functions.
> 
> The register handler prototype and the endianess conversion are
> courtesy of Christoffer Dall.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - rework MMIO dispatching to use only one kvm_io_bus device
> - document purpose of register region macros
> - rename "this" parameter to "dev"
> - change IGROUPR to be RAO (returning 1 => Group1 IRQs)
> 
> Changelog v1 .. v2:
> * MASSIVE rework:
> - store register_region pointer in kvm_io_bus linked struct
> - replace write_mask_xxx functions with extract_bytes() implementation
> - change handler functions' prototypes to take and return unsigned long
> - use binary search to find matching register handler
> - convert endianess of input data in dispatch_mmio_xxx functions
> - improve readability of register initializer macros
> - remove any GICv2/GICv3 specific functions from vgic-mmio.c
> - rename file from vgic_mmio.c to vgic-mmio.c
> 
> Changelog v2 .. v3:
> - replace inclusion of vgic/vgic.h with arm_vgic.h
> 
> Changelog v3 .. v4:
> - add IRQ number accessor macro
> - check access width in dispatcher
> - treat non-covered MMIO addresses as RAZ/WI
> - remove extract_bytes() (re-introduced as static later in the series)
> 
>  include/kvm/vgic/vgic.h       |  13 +++
>  virt/kvm/arm/vgic/vgic-mmio.c | 184 ++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h |  87 ++++++++++++++++++++
>  3 files changed, 284 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index f663288..ff3f9c2 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -106,6 +106,16 @@ struct vgic_irq {
>  	enum vgic_irq_config config;	/* Level or edge */
>  };
>  
> +struct vgic_register_region;
> +
> +struct vgic_io_device {
> +	gpa_t base_addr;
> +	struct kvm_vcpu *redist_vcpu;
> +	const struct vgic_register_region *regions;
> +	int nr_regions;
> +	struct kvm_io_device dev;
> +};
> +
>  struct vgic_dist {
>  	bool			in_kernel;
>  	bool			ready;
> @@ -132,6 +142,9 @@ struct vgic_dist {
>  	bool			enabled;
>  
>  	struct vgic_irq		*spis;
> +
> +	struct vgic_io_device	dist_iodev;
> +	struct vgic_io_device	*redist_iodevs;
>  };
>  
>  struct vgic_v2_cpu_if {
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> new file mode 100644
> index 0000000..012b82b
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -0,0 +1,184 @@
> +/*
> + * VGIC MMIO handling functions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/bsearch.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/iodev.h>
> +#include <kvm/arm_vgic.h>
> +
> +#include "vgic.h"
> +#include "vgic-mmio.h"
> +
> +unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
> +				 gpa_t addr, unsigned int len)
> +{
> +	return 0;
> +}
> +
> +unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
> +				 gpa_t addr, unsigned int len)
> +{
> +	return -1UL;
> +}
> +
> +void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> +			unsigned int len, unsigned long val)
> +{
> +	/* Ignore */
> +}
> +
> +static int match_region(const void *key, const void *elt)
> +{
> +	const unsigned int offset = (unsigned long)key;
> +	const struct vgic_register_region *region = elt;
> +
> +	if (offset < region->reg_offset)
> +		return -1;
> +
> +	if (offset >= region->reg_offset + region->len)
> +		return 1;
> +
> +	return 0;
> +}
> +
> +/* Find the proper register handler entry given a certain address offset. */
> +static const struct vgic_register_region *
> +vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
> +		      unsigned int offset)
> +{
> +	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
> +		       sizeof(region[0]), match_region);
> +}
> +
> +/*
> + * kvm_mmio_read_buf() returns a value in a format where it can be converted
> + * to a byte array and be directly observed as the guest wanted it to appear
> + * in memory if it had done the store itself, which is LE for the GIC, as the
> + * guest knows the GIC is always LE.
> + *
> + * We convert this value to the CPUs native format to deal with it as a data
> + * value.
> + */
> +unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len)
> +{
> +	unsigned long data = kvm_mmio_read_buf(val, len);
> +
> +	switch (len) {
> +	case 1:
> +		return data;
> +	case 2:
> +		return le16_to_cpu(data);
> +	case 4:
> +		return le32_to_cpu(data);
> +	default:
> +		return le64_to_cpu(data);
> +	}
> +}
> +
> +/*
> + * kvm_mmio_write_buf() expects a value in a format such that if converted to
> + * a byte array it is observed as the guest would see it if it could perform
> + * the load directly.  Since the GIC is LE, and the guest knows this, the
> + * guest expects a value in little endian format.
> + *
> + * We convert the data value from the CPUs native format to LE so that the
> + * value is returned in the proper format.
> + */
> +void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
> +				unsigned long data)
> +{
> +	switch (len) {
> +	case 1:
> +		break;
> +	case 2:
> +		data = cpu_to_le16(data);
> +		break;
> +	case 4:
> +		data = cpu_to_le32(data);
> +		break;
> +	default:
> +		data = cpu_to_le64(data);
> +	}
> +
> +	kvm_mmio_write_buf(buf, len, data);
> +}
> +
> +static
> +struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
> +{
> +	return container_of(dev, struct vgic_io_device, dev);
> +}
> +
> +static bool check_region(const struct vgic_register_region *region,
> +			 gpa_t addr, int len)
> +{
> +	if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1)
> +		return true;
> +	if ((region->access_flags & VGIC_ACCESS_32bit) &&
> +	    len == sizeof(u32) && !(addr & 3))
> +		return true;
> +	if ((region->access_flags & VGIC_ACCESS_64bit) &&
> +	    len == sizeof(u64) && !(addr & 7))
> +		return true;
> +
> +	return false;
> +}
> +
> +static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
> +			      gpa_t addr, int len, void *val)
> +{
> +	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
> +	const struct vgic_register_region *region;
> +	struct kvm_vcpu *r_vcpu;
> +	unsigned long data;
> +
> +	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
> +				       addr - iodev->base_addr);
> +	if (!region || !check_region(region, addr, len)) {
> +		memset(val, 0, len);
> +		return 0;
> +	}
> +
> +	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
> +	data = region->read(r_vcpu, addr, len);
> +	vgic_data_host_to_mmio_bus(val, len, data);
> +	return 0;
> +}
> +
> +static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
> +			       gpa_t addr, int len, const void *val)
> +{
> +	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
> +	const struct vgic_register_region *region;
> +	struct kvm_vcpu *r_vcpu;
> +	unsigned long data = vgic_data_mmio_bus_to_host(val, len);
> +
> +	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
> +				       addr - iodev->base_addr);
> +	if (!region)
> +		return 0;
> +
> +	if (!check_region(region, addr, len))
> +		return 0;
> +
> +	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
> +	region->write(r_vcpu, addr, len, data);
> +	return 0;
> +}
> +
> +struct kvm_io_device_ops kvm_io_gic_ops = {
> +	.read = dispatch_mmio_read,
> +	.write = dispatch_mmio_write,
> +};
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> new file mode 100644
> index 0000000..855b1db
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -0,0 +1,87 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef __KVM_ARM_VGIC_MMIO_H__
> +#define __KVM_ARM_VGIC_MMIO_H__
> +
> +struct vgic_register_region {
> +	unsigned int reg_offset;
> +	unsigned int len;
> +	unsigned int bits_per_irq;
> +	unsigned int access_flags;
> +	unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr,
> +			      unsigned int len);
> +	void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
> +		      unsigned long val);
> +};
> +
> +extern struct kvm_io_device_ops kvm_io_gic_ops;
> +
> +#define VGIC_ACCESS_8bit	1
> +#define VGIC_ACCESS_32bit	2
> +#define VGIC_ACCESS_64bit	4
> +
> +/* generate a mask that covers 1024 interrupts with <b> bits per IRQ */

Hmmm. I'd appreciate some additional comments, specially when it comes
to the various restrictions. May I'd suggest something like:

/*
 * Generate a mask that covers the number of bytes required to address
 * up to 1024 interrupts, each represented by <b> bits. This assumes
 * that <b> is a power of two.
 *
 * ilog2(b) + ilog2(1024) is the number of bits required to bit-address
 * 1024 interrupts, each represented by b bits. Minus ilog2(8) converts
 * this to a byte address.
 */

> +#define VGIC_ADDR_IRQ_MASK(b) GENMASK_ULL(ilog2(b) + ilog2(1024) - \
> +					  ilog2(BITS_PER_BYTE) - 1, 0)

/*
 * Convert a base address into a base interrupt (each interrupt
 * represented by <bits> bits. This assumes that <bits> is a power
 * of two, that <addr> both part of a memory region aligned on a
 * <b> bits boundary, and itself aligned on that same boundary
 * (for regions that describe an interrupt with more than a single
 * byte of data).
 */

> +#define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
> +					64 / (bits) / 8)
> +
> +/*
> + * Some VGIC registers store per-IRQ information, with a different number
> + * of bits per IRQ. For those registers this macro is used.
> + * The _WITH_LENGTH version instantiates registers with a fixed length
> + * and is mutually exclusive with the _PER_IRQ version.
> + */
> +#define REGISTER_DESC_WITH_BITS_PER_IRQ(off, rd, wr, bpi, acc)		\
> +	{								\
> +		.reg_offset = off,					\
> +		.bits_per_irq = bpi,					\
> +		.len = bpi * 1024 / 8,					\
> +		.access_flags = acc,					\
> +		.read = rd,						\
> +		.write = wr,						\
> +	}
> +
> +#define REGISTER_DESC_WITH_LENGTH(off, rd, wr, length, acc)		\
> +	{								\
> +		.reg_offset = off,					\
> +		.bits_per_irq = 0,					\
> +		.len = length,						\
> +		.access_flags = acc,					\
> +		.read = rd,						\
> +		.write = wr,						\
> +	}
> +
> +int kvm_vgic_register_mmio_region(struct kvm *kvm, struct kvm_vcpu *vcpu,
> +				  struct vgic_register_region *reg_desc,
> +				  struct vgic_io_device *region,
> +				  int nr_irqs, bool offset_private);
> +
> +unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len);
> +
> +void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
> +				unsigned long data);
> +
> +unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
> +				 gpa_t addr, unsigned int len);
> +
> +unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
> +				 gpa_t addr, unsigned int len);
> +
> +void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> +			unsigned int len, unsigned long val);
> +
> +#endif
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From tn at semihalf.com  Tue May 17 06:44:47 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 17 May 2016 15:44:47 +0200
Subject: [PATCH V7 07/11] pci, acpi: Handle ACPI companion assignment.
In-Reply-To: <573A8BED.7030908@huawei.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-8-git-send-email-tn@semihalf.com>
 <573A8BED.7030908@huawei.com>
Message-ID: <573B204F.9040001@semihalf.com>

On 17.05.2016 05:11, Dongdong Liu wrote:
> Hi Tomasz
>
> I used the patchset and added "PATCH V6 11/13 specic quirks", tested on
> HiSilicon D02 board but met the below problem.
>
> [    2.614115] [<ffffff80083b13bc>] hisi_pcie_init+0x6c/0x1ec
> [    2.619571] [<ffffff80083ab060>] pci_ecam_create+0x130/0x1ec
> [    2.625209] [<ffffff80083f3764>] pci_acpi_scan_root+0x160/0x218
> [    2.631096] [<ffffff80083d1f6c>] acpi_pci_root_add+0x36c/0x42c
> [    2.636897] [<ffffff80083ce36c>] acpi_bus_attach+0xe4/0x1a8
> [    2.642438] [<ffffff80083ce3d8>] acpi_bus_attach+0x150/0x1a8
> [    2.648066] [<ffffff80083ce3d8>] acpi_bus_attach+0x150/0x1a8
> [    2.653693] [<ffffff80083ce55c>] acpi_bus_scan+0x64/0x74
> [    2.658975] [<ffffff8008ae665c>] acpi_scan_init+0x5c/0x19c
> [    2.664429] [<ffffff8008ae6408>] acpi_init+0x280/0x2a4
> [    2.669538] [<ffffff80080829e8>] do_one_initcall+0x8c/0x19c
> [    2.675080] [<ffffff8008ac3af8>] kernel_init_freeable+0x14c/0x1ec
> [    2.681139] [<ffffff80087a8438>] kernel_init+0x10/0xfc
> [    2.686248] [<ffffff8008085e10>] ret_from_fork+0x10/0x40
>
> In hisi_pcie_init, I used "struct acpi_device *device =
> ACPI_COMPANION(dev);".
> I found the reason is V7 lack the below code. I added the below code, it
> worked ok.
>
> [PATCH V6 01/13] pci, acpi, x86, ia64: Move ACPI host bridge device
> companion assignment to core code.
> --- a/drivers/acpi/pci_root.c
> +++ b/drivers/acpi/pci_root.c
> @@ -564,6 +564,11 @@ static int acpi_pci_root_add(struct acpi_device
> *device,
>           }
>       }
>
> +    /*
> +     * pci_create_root_bus() needs to detect the parent device type,
> +     * so initialize its companion data accordingly.
> +     */
> +    ACPI_COMPANION_SET(&device->dev, device);
>
> This code will be upstreamed with the "PATCH V6 11/13 specic quirks" in
> next time after the patchset is accepted.
> Right ?

We had that patch in previous series to retrieve PCI domain nicely. But 
that has bad implication to userspace. See:
https://lkml.org/lkml/2016/5/9/918

I understand that:
[PATCH V6 01/13] pci, acpi, x86, ia64: Move ACPI host bridge device 
companion assignment to core code.
helps to get firmware specific info in hisi_pcie_init but we need to 
figure out something better for quirk handling too.

Tomasz


From arnd at arndb.de  Tue May 17 06:52:17 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 17 May 2016 15:52:17 +0200
Subject: [PATCH V4 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <1463381341-30498-7-git-send-email-sricharan@codeaurora.org>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
 <1463381341-30498-7-git-send-email-sricharan@codeaurora.org>
Message-ID: <3070591.xyl7SB8DB7@wuerfel>

On Monday 16 May 2016 12:19:00 Sricharan R wrote:
> diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
> index f7b4c11..1240a5a 100644
> --- a/drivers/iommu/msm_iommu.c
> +++ b/drivers/iommu/msm_iommu.c
> @@ -124,6 +124,7 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
>                 SET_TLBLKCR(base, ctx, 0);
>                 SET_CONTEXTIDR(base, ctx, 0);
>         }
> +       mb(); /* sync */
>  }
>  
>  static void __flush_iotlb(void *cookie)
> @@ -143,6 +144,7 @@ static void __flush_iotlb(void *cookie)
>  
>                 __disable_clocks(iommu);
>         }
> +       mb(); /* sync */
>  fail:
>         return;
>  }

These comments are completely useless. What is the specific race
that you are protecting against, and why are the implicit barriers
not sufficient here? Please find a better way to document what
is going on.

> diff --git a/drivers/iommu/msm_iommu_hw-8xxx.h b/drivers/iommu/msm_iommu_hw-8xxx.h
> index 84ba5739..161036c 100644
> --- a/drivers/iommu/msm_iommu_hw-8xxx.h
> +++ b/drivers/iommu/msm_iommu_hw-8xxx.h
> @@ -24,10 +24,10 @@
>  #define GET_CTX_REG(reg, base, ctx) \
>                                 (readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
>  
> -#define SET_GLOBAL_REG(reg, base, val) writel((val), ((base) + (reg)))
> +#define SET_GLOBAL_REG(reg, base, val) writel_relaxed((val), ((base) + (reg)))
>  
>  #define SET_CTX_REG(reg, base, ctx, val) \
> -                       writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
> +               writel_relaxed((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
>  
>  /* Wrappers for numbered registers */
>  #define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG(b, ((r) + (n << 2)), (v))
> @@ -48,7 +48,8 @@
>  #define SET_FIELD(addr, mask, shift, v) \
>  do { \
>         int t = readl(addr); \
> -       writel((t & ~((mask) << (shift))) + (((v) & (mask)) << (shift)), addr);\
> +       writel_relaxed((t & ~((mask) << (shift))) + \
> +                      (((v) & (mask)) << (shift)), addr);\
>  } while (0)

No, please add a new macro for the relaxed accessors and then add comments
in the places where those are used, to document why you can take shortcuts
in those places.

	Arnd


From marcel.ziswiler at toradex.com  Tue May 17 07:27:00 2016
From: marcel.ziswiler at toradex.com (Marcel Ziswiler)
Date: Tue, 17 May 2016 14:27:00 +0000
Subject: imx-drm: regression due to commit 503fe87bd0a8 ("gpu: ipu-v3: Fix
 imx-ipuv3-crtc module autoloading")
In-Reply-To: <20160513123336.6996dd89@ipc1.ka-ro>
References: <20160513123336.6996dd89@ipc1.ka-ro>
Message-ID: <1463495219.3210.6.camel@toradex.com>

Hi there

On Fri, 2016-05-13 at 12:33 +0200, Lothar Wa?mann wrote:
> Hi,
> 
> the commit 503fe87bd0a8 ("gpu: ipu-v3: Fix imx-ipuv3-crtc module
> autoloading")
> indeed fixes the autoloading issue, but completely breaks the driver
> in
> non-modular mode (at least with the parallel-display driver I didn't
> yet check with the imx-ldb driver.
> Can anyone confirm that the imx-drm driver in current linux-next
> (next-20160512) works for them with any i.MX6 or i.MX53 board?

I can confirm that this is actually broken both in v4.6 and next-
20160517. Reverting commit 407c9eba7897 ("drm/imx: Remove of_node
assignment from ipuv3-crtc driver probe") in both cases makes regular
imx_v6_v7_defconfig work again.

> I'm always very suspicious when seeing code moving of_node's from
> one device to another or assigning of_node's to platform devices that
> weren't instantiated via DT.
> 
> 
> Lothar Wa?mann

Cheers

Marcel

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

From kernel at martin.sperl.org  Tue May 17 07:35:48 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Tue, 17 May 2016 14:35:48 +0000
Subject: [PATCH V3 0/5] bcm2835: add thermal driver
Message-ID: <1463495753-967-1-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add a thermal driver for the TSENSE device of the bcm2835 SOC.

If the firmware enables the HW, then the configuration is not touched.
In case the firmware has not enabled the device, then we try to set
it up correctly (which unfortunately can not get tested).

It exposes temperature and a critical trip point
(using a hardcoded default of 80C or the temperature configured
in the control register by the firmware, which reads as
407C currently)

The calibrations are (potentially) different for bcm2835, bcm2836
and bcm2837 and can get selected by the compatible property
in the device tree.

The driver also exposes the registers via debugfs.

Possible future enhancements:
* the device has the ability to trigger interrupts on reaching
  the programmed critical temperature.
  I have no knowledge which interrupt could be responsible
  for this on the ARM side, so if we get to know which irq
  it is we can implement that
* the device can also reset the HW after the trip point
  has been reached (also with some delay, so that corrective
  actions can get taken) - this is currently not enabled by the
  firmware, but could.
* we could define more trip points for THERMAL_TRIP_HOT
* make the trip point limits modifiable (ops.set_trip_temp)

Changelog:
 V1 -> V2: renamed dt-binding documentation file
       	   added specific settings depending on compatible
	   added trip point based on register
	   setting up ctrl-register if HW is not enabled by firmware
	     as per recommendation of Eric (untested)
	   check that clock frequency is in range
	     (1.9 - 5MHz - as per comment in clk-bcm2835.c)
 	   added driver to multi_v7_defconfig
 V2 -> V3: made a module in multi_v7_defconfig
           fixed typo in dt-binding document

Martin Sperl (5):
  dt: bindings: add thermal device driver for bcm2835
  thermal: bcm2835: add thermal driver for bcm2835 soc
  ARM: bcm2835: add thermal node to device-tree of bcm283x
  ARM: bcm2835: add thermal driver to default_config
  ARM: multi_v7_defconfig: bcm2835: add bcm2835-thermal driver

 .../bindings/thermal/brcm,bcm2835-thermal.txt      |  17 ++
 arch/arm/boot/dts/bcm283x.dtsi                     |   6 +
 arch/arm/configs/bcm2835_defconfig                 |   2 +
 arch/arm/configs/multi_v7_defconfig                |   1 +
 drivers/thermal/Kconfig                            |   5 +
 drivers/thermal/Makefile                           |   1 +
 drivers/thermal/bcm/Kconfig                        |   4 +
 drivers/thermal/bcm/Makefile                       |   1 +
 drivers/thermal/bcm/bcm2835_thermal.c              | 326 +++++++++++++++++++++
 9 files changed, 363 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
 create mode 100644 drivers/thermal/bcm/Kconfig
 create mode 100644 drivers/thermal/bcm/Makefile
 create mode 100644 drivers/thermal/bcm/bcm2835_thermal.c

--
2.1.4


From kernel at martin.sperl.org  Tue May 17 07:35:49 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Tue, 17 May 2016 14:35:49 +0000
Subject: [PATCH V3 1/5] dt: bindings: add thermal device driver for bcm2835
In-Reply-To: <1463495753-967-1-git-send-email-kernel@martin.sperl.org>
References: <1463495753-967-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463495753-967-2-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add dt-binding documentation for bcm2835 SOC thermal sensor.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
Acked-by: Eric Anholt <eric at anholt.net>
Acked-by: Rob Herring <robh at kernel.org>

Changelog:
 V1 -> V2: renamed file to follow naming conventions
 V2 -> V3: removed 0x in node name
---
 .../bindings/thermal/brcm,bcm2835-thermal.txt           | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt

diff --git a/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
new file mode 100644
index 0000000..474531d
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
@@ -0,0 +1,17 @@
+Binding for Thermal Sensor driver for BCM2835 SoCs.
+
+Required parameters:
+-------------------
+
+compatible: 	should be one of: "brcm,bcm2835-thermal",
+		"brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
+reg:		Address range of the thermal registers.
+clocks: 	Phandle of the clock used by the thermal sensor.
+
+Example:
+
+thermal: thermal at 7e212000 {
+	compatible = "brcm,bcm2835-thermal";
+	reg = <0x7e212000 0x8>;
+	clocks = <&clocks BCM2835_CLOCK_TSENS>;
+};
--
2.1.4


From kernel at martin.sperl.org  Tue May 17 07:35:50 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Tue, 17 May 2016 14:35:50 +0000
Subject: [PATCH V3 2/5] thermal: bcm2835: add thermal driver for bcm2835 soc
In-Reply-To: <1463495753-967-1-git-send-email-kernel@martin.sperl.org>
References: <1463495753-967-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463495753-967-3-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add basic thermal driver for bcm2835 SOC.

This driver currently relies on the firmware setting up the
tsense HW block and does not set it up itself.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>

ChangeLog:
 V1 -> V2: added specific settings depending on compatiblity
	   added trip point based on register
	   setting up ctrl-register if HW is not enabled by firmware
	     as per recommendation of Eric (untested)
	   check that clock frequency is in range
	     (1.9 - 5MHz - as per comment in clk-bcm2835.c)
---
 drivers/thermal/Kconfig               |   5 +
 drivers/thermal/Makefile              |   1 +
 drivers/thermal/bcm/Kconfig           |   4 +
 drivers/thermal/bcm/Makefile          |   1 +
 drivers/thermal/bcm/bcm2835_thermal.c | 326 ++++++++++++++++++++++++++++++++++
 5 files changed, 337 insertions(+)
 create mode 100644 drivers/thermal/bcm/Kconfig
 create mode 100644 drivers/thermal/bcm/Makefile
 create mode 100644 drivers/thermal/bcm/bcm2835_thermal.c

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 3c3dc4a..5b63d45 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -383,6 +383,11 @@ config MTK_THERMAL
 	  Enable this option if you want to have support for thermal management
 	  controller present in Mediatek SoCs
 
+menu "Broadcom thermal drivers"
+depends on ARCH_BCM || COMPILE_TEST
+source "drivers/thermal/bcm/Kconfig"
+endmenu
+
 menu "Texas Instruments thermal drivers"
 depends on ARCH_HAS_BANDGAP || COMPILE_TEST
 depends on HAS_IOMEM
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 8e9cbc3..6df1aa3 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -49,3 +49,4 @@ obj-$(CONFIG_ST_THERMAL)	+= st/
 obj-$(CONFIG_TEGRA_SOCTHERM)	+= tegra_soctherm.o
 obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
 obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
+obj-y				+= bcm/
diff --git a/drivers/thermal/bcm/Kconfig b/drivers/thermal/bcm/Kconfig
new file mode 100644
index 0000000..62245ae
--- /dev/null
+++ b/drivers/thermal/bcm/Kconfig
@@ -0,0 +1,4 @@
+config BCM2835_THERMAL
+       tristate "Thermal sensors on bcm2835 SoC"
+       help
+         Support for thermal sensors on Broadcom bcm2835 SoCs.
diff --git a/drivers/thermal/bcm/Makefile b/drivers/thermal/bcm/Makefile
new file mode 100644
index 0000000..13456d2
--- /dev/null
+++ b/drivers/thermal/bcm/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_BCM2835_THERMAL)		:= bcm2835_thermal.o
diff --git a/drivers/thermal/bcm/bcm2835_thermal.c b/drivers/thermal/bcm/bcm2835_thermal.c
new file mode 100644
index 0000000..73138cb
--- /dev/null
+++ b/drivers/thermal/bcm/bcm2835_thermal.c
@@ -0,0 +1,326 @@
+/*
+ * Driver for Broadcom BCM2835 soc temperature sensor
+ *
+ * Copyright (C) 2015 Martin Sperl
+ *
+ * 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.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+
+#define BCM2835_TS_TSENSCTL			0x00
+#define BCM2835_TS_TSENSSTAT			0x04
+
+#define BCM2835_TS_TSENSCTL_PRWDW		BIT(0)
+#define BCM2835_TS_TSENSCTL_RSTB		BIT(1)
+#define BCM2835_TS_TSENSCTL_CTRL_BITS		3
+#define BCM2835_TS_TSENSCTL_CTRL_SHIFT		2
+#define BCM2835_TS_TSENSCTL_CTRL_MASK		    \
+	GENMASK(BCM2835_TS_TSENSCTL_CTRL_BITS +     \
+		BCM2835_TS_TSENSCTL_CTRL_SHIFT - 1, \
+		BCM2835_TS_TSENSCTL_CTRL_SHIFT)
+#define BCM2835_TS_TSENSCTL_CTRL_DEFAULT	1
+#define BCM2835_TS_TSENSCTL_EN_INT		BIT(5)
+#define BCM2835_TS_TSENSCTL_DIRECT		BIT(6)
+#define BCM2835_TS_TSENSCTL_CLR_INT		BIT(7)
+#define BCM2835_TS_TSENSCTL_THOLD_SHIFT		8
+#define BCM2835_TS_TSENSCTL_THOLD_BITS		10
+#define BCM2835_TS_TSENSCTL_THOLD_MASK		     \
+	GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS +     \
+		BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \
+		BCM2835_TS_TSENSCTL_THOLD_SHIFT)
+#define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT	18
+#define BCM2835_TS_TSENSCTL_RSTDELAY_BITS	8
+#define BCM2835_TS_TSENSCTL_RSTDELAY_DEFAULT	14
+#define BCM2835_TS_TSENSCTL_REGULEN		BIT(26)
+
+#define BCM2835_TS_TSENSSTAT_DATA_BITS		10
+#define BCM2835_TS_TSENSSTAT_DATA_SHIFT		0
+#define BCM2835_TS_TSENSSTAT_DATA_MASK		     \
+	GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS +     \
+		BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \
+		BCM2835_TS_TSENSSTAT_DATA_SHIFT)
+#define BCM2835_TS_TSENSSTAT_VALID		BIT(10)
+#define BCM2835_TS_TSENSSTAT_INTERRUPT		BIT(11)
+
+struct bcm2835_thermal_info {
+	int offset;
+	int slope;
+	int trip_temp;
+};
+
+struct bcm2835_thermal_data {
+	const struct bcm2835_thermal_info *info;
+	void __iomem *regs;
+	struct clk *clk;
+	struct dentry *debugfsdir;
+};
+
+static int bcm2835_thermal_adc2temp(
+	const struct bcm2835_thermal_info *info, u32 adc)
+{
+	return info->offset + (adc * info->slope);
+}
+
+static int bcm2835_thermal_temp2adc(
+	const struct bcm2835_thermal_info *info, int temp)
+{
+	temp -= info->offset;
+	temp /= info->slope;
+
+	if (temp < 0)
+		temp = 0;
+	if (temp >= BIT(BCM2835_TS_TSENSSTAT_DATA_BITS))
+		temp = BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1;
+
+	return temp;
+}
+
+static int bcm2835_thermal_get_trip_type(
+	struct thermal_zone_device *tz, int trip,
+	enum thermal_trip_type *type)
+{
+	*type = THERMAL_TRIP_CRITICAL;
+	return 0;
+}
+
+static int bcm2835_thermal_get_trip_temp(
+	struct thermal_zone_device *tz, int trip, int *temp)
+{
+	struct bcm2835_thermal_data *data = tz->devdata;
+	u32 val = readl(data->regs + BCM2835_TS_TSENSCTL);
+
+	/* get the THOLD bits */
+	val &= BCM2835_TS_TSENSCTL_THOLD_MASK;
+	val >>= BCM2835_TS_TSENSCTL_THOLD_SHIFT;
+
+	/* if it is zero then use the info value */
+	if (val)
+		*temp = bcm2835_thermal_adc2temp(data->info, val);
+	else
+		*temp = data->info->trip_temp;
+
+	return 0;
+}
+
+static int bcm2835_thermal_get_temp(struct thermal_zone_device *tz,
+				    int *temp)
+{
+	struct bcm2835_thermal_data *data = tz->devdata;
+	u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT);
+
+	if (!(val & BCM2835_TS_TSENSSTAT_VALID))
+		return -EIO;
+
+	/* mask the relevant bits */
+	val &= BCM2835_TS_TSENSSTAT_DATA_MASK;
+
+	*temp = bcm2835_thermal_adc2temp(data->info, val);
+
+	return 0;
+}
+
+static const struct debugfs_reg32 bcm2835_thermal_regs[] = {
+	{
+		.name = "ctl",
+		.offset = 0
+	},
+	{
+		.name = "stat",
+		.offset = 4
+	}
+};
+
+static void bcm2835_thermal_debugfs(struct platform_device *pdev)
+{
+	struct thermal_zone_device *tz = platform_get_drvdata(pdev);
+	struct bcm2835_thermal_data *data = tz->devdata;
+	struct debugfs_regset32 *regset;
+
+	data->debugfsdir = debugfs_create_dir("bcm2835_thermal", NULL);
+	if (!data->debugfsdir)
+		return;
+
+	regset = devm_kzalloc(&pdev->dev, sizeof(*regset), GFP_KERNEL);
+	if (!regset)
+		return;
+
+	regset->regs = bcm2835_thermal_regs;
+	regset->nregs = ARRAY_SIZE(bcm2835_thermal_regs);
+	regset->base = data->regs;
+
+	debugfs_create_regset32("regset", S_IRUGO,
+				data->debugfsdir, regset);
+}
+
+static struct thermal_zone_device_ops bcm2835_thermal_ops  = {
+	.get_temp = bcm2835_thermal_get_temp,
+	.get_trip_temp = bcm2835_thermal_get_trip_temp,
+	.get_trip_type = bcm2835_thermal_get_trip_type,
+};
+
+static const struct of_device_id bcm2835_thermal_of_match_table[];
+static int bcm2835_thermal_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct thermal_zone_device *tz;
+	struct bcm2835_thermal_data *data;
+	struct resource *res;
+	int err;
+	u32 val;
+	unsigned long rate;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	match = of_match_device(bcm2835_thermal_of_match_table,
+				&pdev->dev);
+	if (!match)
+		return -EINVAL;
+	data->info = match->data;
+
+	/* get registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(data->regs)) {
+		err = PTR_ERR(data->regs);
+		dev_err(&pdev->dev, "Could not get registers: %d\n", err);
+		return err;
+	}
+
+	/* get clock */
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk)) {
+		err = PTR_ERR(data->clk);
+		if (err != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Could not get clk: %d\n", err);
+		return err;
+	}
+
+	/* set up registers if not already done by the fw */
+	val = readl(data->regs + BCM2835_TS_TSENSCTL);
+	if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {
+		/* the basic required flags */
+		val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT <<
+		       BCM2835_TS_TSENSCTL_CTRL_SHIFT) |
+		      BCM2835_TS_TSENSCTL_REGULEN;
+
+		/* reset delay */
+		val |= (BCM2835_TS_TSENSCTL_RSTDELAY_DEFAULT <<
+			BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);
+
+		/*  trip_adc value from info */
+		val |= bcm2835_thermal_temp2adc(data->info,
+						data->info->trip_temp) <<
+			BCM2835_TS_TSENSCTL_THOLD_SHIFT;
+
+		/* write the value back to the register as 2 steps */
+		writel(val, data->regs + BCM2835_TS_TSENSCTL);
+		val |= BCM2835_TS_TSENSCTL_RSTB;
+		writel(val, data->regs + BCM2835_TS_TSENSCTL);
+	}
+
+	/* enable clock and check rate */
+	clk_prepare_enable(data->clk);
+	rate = clk_get_rate(data->clk);
+	if ((rate < 1920000) || (rate > 5000000)) {
+		dev_warn(&pdev->dev,
+			 "Clock %pCn is running at %pCr Hz, which is outside the recommended range of 1.9 to 5.0 MHz\n",
+			 data->clk, data->clk);
+	}
+
+	/* register it */
+	tz = thermal_zone_device_register("bcm2835_thermal",
+					  1, 0, data,
+					  &bcm2835_thermal_ops,
+					  NULL, 0, 0);
+	if (IS_ERR(tz)) {
+		clk_disable_unprepare(data->clk);
+		err = PTR_ERR(tz);
+		dev_err(&pdev->dev,
+			"Failed to register the thermal device: %d\n",
+			err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, tz);
+
+	bcm2835_thermal_debugfs(pdev);
+
+	return 0;
+}
+
+static int bcm2835_thermal_remove(struct platform_device *pdev)
+{
+	struct thermal_zone_device *tz = platform_get_drvdata(pdev);
+	struct bcm2835_thermal_data *data = tz->devdata;
+
+	debugfs_remove_recursive(data->debugfsdir);
+	thermal_zone_device_unregister(tz);
+
+	return 0;
+}
+
+static const struct of_device_id bcm2835_thermal_of_match_table[] = {
+	{
+		.compatible = "brcm,bcm2835-thermal",
+		.data = &(struct bcm2835_thermal_info) {
+			.offset = 407000,
+			.slope = -538,
+			.trip_temp = 80000
+		}
+	},
+	{
+		.compatible = "brcm,bcm2836-thermal",
+		.data = &(struct bcm2835_thermal_info) {
+			.offset = 407000,
+			.slope = -538,
+			.trip_temp = 80000
+		}
+	},
+	{
+		.compatible = "brcm,bcm2837-thermal",
+		.data = &(struct bcm2835_thermal_info) {
+			/* the bcm2837 needs adjustment of +5C */
+			.offset = 407000 + 5000,
+			.slope = -538,
+			.trip_temp = 80000
+		}
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);
+
+static struct platform_driver bcm2835_thermal_driver = {
+	.probe = bcm2835_thermal_probe,
+	.remove = bcm2835_thermal_remove,
+	.driver = {
+		.name = "bcm2835_thermal",
+		.of_match_table = bcm2835_thermal_of_match_table,
+	},
+};
+module_platform_driver(bcm2835_thermal_driver);
+
+MODULE_AUTHOR("Martin Sperl");
+MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");
+MODULE_LICENSE("GPL");
-- 
2.1.4



From kernel at martin.sperl.org  Tue May 17 07:35:51 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Tue, 17 May 2016 14:35:51 +0000
Subject: [PATCH V3 3/5] ARM: bcm2835: add thermal node to device-tree of
 bcm283x
In-Reply-To: <1463495753-967-1-git-send-email-kernel@martin.sperl.org>
References: <1463495753-967-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463495753-967-4-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add the node for the thermal sensor of the bcm2835-soc
to the device tree.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
Reviewed-by: Eric Anholt <eric at anholt.net>
---
 arch/arm/boot/dts/bcm283x.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index 37b35eb..6f6949b 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
+++ b/arch/arm/boot/dts/bcm283x.dtsi
@@ -153,6 +153,12 @@
 			status = "disabled";
 		};
 
+		thermal: thermal at 0x7e212000 {
+			compatible = "brcm,bcm2835-thermal";
+			reg = <0x7e212000 0x8>;
+			clocks = <&clocks BCM2835_CLOCK_TSENS>;
+		};
+
 		aux: aux at 0x7e215000 {
 			compatible = "brcm,bcm2835-aux";
 			#clock-cells = <1>;
-- 
2.1.4



From kernel at martin.sperl.org  Tue May 17 07:35:52 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Tue, 17 May 2016 14:35:52 +0000
Subject: [PATCH V3 4/5] ARM: bcm2835: add thermal driver to default_config
In-Reply-To: <1463495753-967-1-git-send-email-kernel@martin.sperl.org>
References: <1463495753-967-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463495753-967-5-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add the thermal driver to list of compiled modules
in the default config for bcm2835.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
Reviewed-by: Eric Anholt <eric at anholt.net>
---
 arch/arm/configs/bcm2835_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index 29a44bd..634e07e 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -71,6 +71,8 @@ CONFIG_SPI_BCM2835=y
 CONFIG_SPI_BCM2835AUX=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_BCM2835_THERMAL=y
 CONFIG_WATCHDOG=y
 CONFIG_BCM2835_WDT=y
 CONFIG_FB=y
-- 
2.1.4



From kernel at martin.sperl.org  Tue May 17 07:35:53 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Tue, 17 May 2016 14:35:53 +0000
Subject: [PATCH V3 5/5] ARM: multi_v7_defconfig: bcm2835: add bcm2835-thermal
 driver
In-Reply-To: <1463495753-967-1-git-send-email-kernel@martin.sperl.org>
References: <1463495753-967-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463495753-967-6-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add the thermal driver to list of compiled modules in
multi_v7_defconfig.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>

Changelog:
 V1 -> V2: added this patch
 V2 -> V3: made driver compile as a module not in-kernel
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 1e799fe..bd6d400 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -422,6 +422,7 @@ CONFIG_CPU_THERMAL=y
 CONFIG_ROCKCHIP_THERMAL=y
 CONFIG_RCAR_THERMAL=y
 CONFIG_ARMADA_THERMAL=y
+CONFIG_BCM2835_THERMAL=m
 CONFIG_DAVINCI_WATCHDOG=m
 CONFIG_EXYNOS_THERMAL=m
 CONFIG_ST_THERMAL_SYSCFG=y
--
2.1.4


From mathieu.poirier at linaro.org  Tue May 17 07:50:30 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue, 17 May 2016 08:50:30 -0600
Subject: Juno r0 fails to boot with linux-next 20160516
In-Reply-To: <20160516171745.GB26180@e106497-lin.cambridge.arm.com>
References: <20160516171745.GB26180@e106497-lin.cambridge.arm.com>
Message-ID: <CANLsYkwE1x3w2-Yuf0ts9YnE+LA9b2yBQfnSnDx0EBXKu2BY4w@mail.gmail.com>

On 16 May 2016 at 11:17, Liviu Dudau <Liviu.Dudau at arm.com> wrote:
> Hi Mathieu,
>
> I was trying to boot linux-next 20150516 today on Juno r0 and it gets stuck
> after printing the message:
>
> Serial: AMBA PL011 UART driver
>
> Bisecting shows commit d02e8a63733ff9121 as the culprit:
>
> commit d02e8a63733ff912128c04a091c0de75be8df1ab
> Author: Mathieu Poirier <mathieu.poirier at linaro.org>
> Date:   Sun Oct 18 16:50:48 2015 -0600
>
>     coresight: Add support for Juno platform
>
>     This patch adds support for ARM's juno platform.  More
>     specifically it has definitions for the A53/57 tracers,
>     the A53/57 cluster funnels, the main funnel and the ETF
>     in circular buffer mode.
>
>     Support for all the other coresight IP blocks is not
>     addressed.
>
>     Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
>
> Juno r1 is not affected as you are modifying only the juno.dts file. Also,
> if I have the DSTREAM unit connected to the boot core the kernel boots fine,
> which leads me to believe that there is some power domain issue at play (?).
> Also, reverting the patch gets r0 to boot again.
>
> This is the bisection log:
>
> $ git bisect start HEAD v4.6-rc7
> Bisecting: 5755 revisions left to test after this (roughly 13 steps)
> [027e278cc4d21e4718be4ea5bb14e360ff259174] Merge remote-tracking branch 'crypto/master'
> $ git bisect good
> Bisecting: 2836 revisions left to test after this (roughly 12 steps)
> [b14343bae9270c97b7b6b4652157577d2786c591] Merge remote-tracking branch 'tip/auto-latest'
> $ git bisect good
> Bisecting: 1350 revisions left to test after this (roughly 11 steps)
> [98efb6a2745524fc404211e266f54bf409063364] Merge remote-tracking branch 'staging/staging-next'
> $ git bisect good
> Bisecting: 687 revisions left to test after this (roughly 9 steps)
> [ecf549d34f211f9bae0dfab98f994825b0891648] Merge remote-tracking branch 'pwm/for-next'
> $ git bisect good
> Bisecting: 343 revisions left to test after this (roughly 9 steps)
> [fb86798c5cdd615f5c9780eca36a232434f4d63b] nilfs2: fix white space issue in nilfs_mount()
> $ git bisect good
> Bisecting: 158 revisions left to test after this (roughly 8 steps)
> [ae82fd28e602ddab3381d76603a0af9e87a5e2aa] Merge remote-tracking branch 'coresight/next'
> $ git bisect bad
> Bisecting: 92 revisions left to test after this (roughly 7 steps)
> [98b8525abb7f0d9a5ab942a2e044011d7e635490] clk: sunxi: Add display and TCON0 clocks driver
> $ git bisect good
> Bisecting: 51 revisions left to test after this (roughly 6 steps)
> [6d9122078097233dbfc4ad3a45512393cddf8540] Merge branch 'for-4.7/core' into for-next
> $ git bisect good
> Bisecting: 25 revisions left to test after this (roughly 5 steps)
> [25d894772abc89f78512cf640250514be87a3b46] coresight: tmc: introducing new header file
> $ git bisect bad
> Bisecting: 12 revisions left to test after this (roughly 4 steps)
> [63f09f1d779856b615768a97c641ab26126c9183] coresight: no need to do the forced type conversion
> $ git bisect bad
> Bisecting: 6 revisions left to test after this (roughly 3 steps)
> [0cce003868b664547d9e5dd1f586b902cca43784] coresight: etm4x: unlocking tracers in default arch init
> $ git bisect bad
> Bisecting: 2 revisions left to test after this (roughly 2 steps)
> [dd7ebddfdad8d379887f9e2f74d0ba207b59cb77] coresight: etm4x: adding config and traceid registers
> $ git bisect bad
> Bisecting: 0 revisions left to test after this (roughly 1 step)
> [d03196055ea8b535a346239307dfa797bc4059d2] coresight: etm4x: moving sysFS entries to a dedicated file
> $ git bisect bad
> Bisecting: 0 revisions left to test after this (roughly 0 steps)
> [d02e8a63733ff912128c04a091c0de75be8df1ab] coresight: Add support for Juno platform
>
>
> Best regards,
> Liviu

Thank you for pointing this out.  The faulty patch should not have
made it to my next tree in the first place.  I have corrected the
problem.

Regards,
Mathieu

>
> --
> ====================
> | I would like to |
> | fix the world,  |
> | but they're not |
> | giving me the   |
>  \ source code!  /
>   ---------------
>     ?\_(?)_/?


From konrad.wilk at oracle.com  Tue May 17 07:50:02 2016
From: konrad.wilk at oracle.com (Konrad Rzeszutek Wilk)
Date: Tue, 17 May 2016 10:50:02 -0400
Subject: [PATCHv6 2/8] dma-debug: add support for resource mappings
In-Reply-To: <1462812247-3414-3-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <1462812247-3414-3-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <20160517145002.GD4074@char.us.oracle.com>

> +void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size,
> +			    int direction, dma_addr_t dma_addr)
> +{
> +	struct dma_debug_entry *entry;
> +
> +	if (unlikely(dma_debug_disabled()))
> +		return;
> +
> +	entry = dma_entry_alloc();
> +	if (!entry)
> +		return;
> +
> +	entry->type		= dma_debug_resource;
> +	entry->dev		= dev;
> +	entry->pfn		= __phys_to_pfn(addr);
> +	entry->offset		= addr - PHYS_PFN(entry->pfn);

Is that right? 

__phys_to_pfn(addr) is PHYS_PFN(addr), so what you get here is

addr - PHYS_PFN(PHYS_PFN(addr)) ?


> +	entry->size		= size;
> +	entry->dev_addr		= dma_addr;
> +	entry->direction	= direction;
> +	entry->map_err_type	= MAP_ERR_NOT_CHECKED;
> +
> +	add_dma_entry(entry);
> +}
> +EXPORT_SYMBOL(debug_dma_map_resource);
> +


From konrad.wilk at oracle.com  Tue May 17 07:54:45 2016
From: konrad.wilk at oracle.com (Konrad Rzeszutek Wilk)
Date: Tue, 17 May 2016 10:54:45 -0400
Subject: [PATCHv6 3/8] dma-mapping: add dma_{map,unmap}_resource
In-Reply-To: <1462812247-3414-4-git-send-email-niklas.soderlund+renesas@ragnatech.se>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <1462812247-3414-4-git-send-email-niklas.soderlund+renesas@ragnatech.se>
Message-ID: <20160517145445.GE4074@char.us.oracle.com>

>  
> -In some circumstances dma_map_single() and dma_map_page() will fail to create
> -a mapping. A driver can check for these errors by testing the returned
> -DMA address with dma_mapping_error(). A non-zero return value means the mapping
> -could not be created and the driver should take appropriate action (e.g.
> -reduce current DMA mapping usage or delay and try again later).
> +In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
> +will fail to create a mapping. A driver can check for these errors by testing
> +the returned DMA address with dma_mapping_error(). A non-zero return value
> +means the mapping could not be created and the driver should take appropriate
> +action (e.g. reduce current DMA mapping usage or delay and try again later).

This looks like it belongs to another patch?


From geert+renesas at glider.be  Tue May 17 08:15:33 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Tue, 17 May 2016 17:15:33 +0200
Subject: [PATCH] ARM: shmobile: rcar-gen2: Use ICRAM1 for jump stub on all SoCs
Message-ID: <1463498133-23918-1-git-send-email-geert+renesas@glider.be>

Currently the different SoCs in the R-Car Gen2 family use different
types of on-chip RAM for the jump stub:
  - R-Car H2 uses Media RAM,
  - R-Car M2-W uses another type of optional On-chip RAM, as it doesn't
    have Media RAM,
  - R-Car M2-N uses Inter Connect RAM in Magnus Damm's "ARM: shmobile:
    r8a7793 boot address update".

As all R-Car Gen2 SoCs have 4 KiB of Inter Connect RAM, consolidate the
code by always using that.

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
Tested on r8a7790/lager and r8a7791/koelsch.
---
 arch/arm/mach-shmobile/pm-rcar-gen2.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-shmobile/pm-rcar-gen2.c b/arch/arm/mach-shmobile/pm-rcar-gen2.c
index 691ac166a277c03f..61361dac6068210a 100644
--- a/arch/arm/mach-shmobile/pm-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/pm-rcar-gen2.c
@@ -26,8 +26,7 @@
 #define CA7RESCNT	0x0044
 
 /* On-chip RAM */
-#define MERAM		0xe8080000
-#define RAM		0xe6300000
+#define ICRAM1		0xe63c0000	/* Inter Connect RAM1 (4 KiB) */
 
 /* SYSC */
 #define SYSCIER 0x0c
@@ -58,7 +57,7 @@ void __init rcar_gen2_pm_init(void)
 	struct device_node *np, *cpus;
 	bool has_a7 = false;
 	bool has_a15 = false;
-	phys_addr_t boot_vector_addr = 0;
+	phys_addr_t boot_vector_addr = ICRAM1;
 	u32 syscier = 0;
 
 	if (once++)
@@ -75,14 +74,10 @@ void __init rcar_gen2_pm_init(void)
 			has_a7 = true;
 	}
 
-	if (of_machine_is_compatible("renesas,r8a7790")) {
-		boot_vector_addr = MERAM;
+	if (of_machine_is_compatible("renesas,r8a7790"))
 		syscier = 0x013111ef;
-
-	} else if (of_machine_is_compatible("renesas,r8a7791")) {
-		boot_vector_addr = RAM;
+	else if (of_machine_is_compatible("renesas,r8a7791"))
 		syscier = 0x00111003;
-	}
 
 	/* RAM for jump stub, because BAR requires 256KB aligned address */
 	p = ioremap_nocache(boot_vector_addr, shmobile_boot_size);
-- 
1.9.1



From arnd at arndb.de  Tue May 17 08:37:55 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 17 May 2016 17:37:55 +0200
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <573B0A4D.4090704@arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <573B0A4D.4090704@arm.com>
Message-ID: <4173531.IRSphtVpg9@wuerfel>

On Tuesday 17 May 2016 13:10:53 Szabolcs Nagy wrote:
> On 05/04/16 23:08, Yury Norov wrote:
> > This version is rebased on kernel v4.6-rc2, and has fixes in signal subsystem.
> > It works with updated glibc [1] (though very draft), and tested with LTP.
> > 
> > It was tested on QEMU and ThunderX machines. No major difference found.
> > This is RFC because ILP32 is not tested in big-endian mode.
> > 
> >  v3: https://lkml.org/lkml/2014/9/3/704
> >  v4: https://lkml.org/lkml/2015/4/13/691
> >  v5: https://lkml.org/lkml/2015/9/29/911
> > 
> >  v6:
> >  - time_t, __kenel_off_t and other types turned to be 32-bit
> >    for compatibility reasons (after v5 discussion);
> 
> i added libc-alpha to cc, the thread is at
> https://lkml.org/lkml/2016/4/5/872
> or http://thread.gmane.org/gmane.linux.kernel.cross-arch/31449
> 
> the kernel position seems to be that the aarch64 ilp32 syscall abi
> will follow regular 32bit abis (apart from signal context and ptrace
> related things and syscalls will take 64bit arguments).
> 
> i think the reasoning is that this allows legacy (non-64bit-safe)
> software to use this abi on aarch64 without trouble.
> 
> i think this design should be ok for glibc.
> 
> there are some interop issues between processes following different abis
> (e.g. shared mutexes, abi specific file formats, lib paths,..) which apply,
> but i assume it is no different from existing 32bit vs 64bit issues.
> 
> the 32bit time_t and off_t are ugly and i wonder if 32bit __kernel_off_t
> is really necessary. (i don't see where that is changed: it is supposed
> to be __kernel_long_t which is 64bit).

__kernel_off_t and __kernel_ino_t are always 'long' and 'unsigned long'
for historic reasons, but they are not used at all on modern architectures.
We could add a few lines with #ifdef to the kernel headers to hide the
definition on architectures that don't use them, but that seems pointless
given that glibc just defines its own version.

For time_t, I'm working on the same thing in the long run: there will
be a 64 bit __kernel_time64_t that is always used on all architectures,
and a __kernel_time_t that is provided for backwards compatibility
with old libc on architectures that started out having it.

__kernel_long_t should not be 64 bit on 32-bit architectures, it is the
size of the 'long' type in the ABI and defining it as 'long long' on
x32 keeps causing problems that we should not add on new architectures.

> i think even legacy software should be able to deal with 64bit off_t,
> so we could avoid having two sets of filesystem apis or is 64bit-only
> off_t more work to do in linux/glibc?

All architectures that got merged in the last 10 years only support
64-bit __kernel_loff_t in the kernel but not __kernel_off_t, this
includes arc, c6x, h8300, hexagon, metag, nios2, openrisc, tile and
unicore32. However, glibc implements 32-bit off_t on top of the
64-bit syscall interfaces. I believe this was done to keep the code
looking more like the older 32-bit architectures.

I think it has become easier to override now and we just need to
update sysdeps/unix/sysv/linux/generic/bits/typesizes.h to set

#define __INO64_T_TYPE          __UQUAD_TYPE
#define __OFF64_T_TYPE          __UQUAD_TYPE
#define __OFF_T_MATCHES_OFF64_T        1
#define __INO_T_MATCHES_INO64_T        1

for new architectures (obviously not the ones that already use the
32-bit types). I haven't tries this, so there may be other things
that are required.

	Arnd


From joseph at codesourcery.com  Tue May 17 08:40:47 2016
From: joseph at codesourcery.com (Joseph Myers)
Date: Tue, 17 May 2016 15:40:47 +0000
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <573B0A4D.4090704@arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <573B0A4D.4090704@arm.com>
Message-ID: <alpine.DEB.2.20.1605171538040.24255@digraph.polyomino.org.uk>

On Tue, 17 May 2016, Szabolcs Nagy wrote:

> i think even legacy software should be able to deal with 64bit off_t,
> so we could avoid having two sets of filesystem apis or is 64bit-only
> off_t more work to do in linux/glibc?

wordsize-64 directories generally expect 64-bit interfaces.  wordsize-32 
directories generally expect that there are two sets of filesystem APIs 
which are not aliased (at the userspace level - the versions for the 
generic syscall API deal with setting EOVERFLOW in userspace as needed).

The "wordsize" concept is not wonderfully well-defined and could do with 
being split up into multiple better-defined concepts, but that's obvious 
something pretty tricky to get right, involving a very careful analysis of 
the existing code.

-- 
Joseph S. Myers
joseph at codesourcery.com


From joseph at codesourcery.com  Tue May 17 08:45:11 2016
From: joseph at codesourcery.com (Joseph Myers)
Date: Tue, 17 May 2016 15:45:11 +0000
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <4173531.IRSphtVpg9@wuerfel>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <573B0A4D.4090704@arm.com> <4173531.IRSphtVpg9@wuerfel>
Message-ID: <alpine.DEB.2.20.1605171542340.24255@digraph.polyomino.org.uk>

On Tue, 17 May 2016, Arnd Bergmann wrote:

> I think it has become easier to override now and we just need to
> update sysdeps/unix/sysv/linux/generic/bits/typesizes.h to set
> 
> #define __INO64_T_TYPE          __UQUAD_TYPE
> #define __OFF64_T_TYPE          __UQUAD_TYPE
> #define __OFF_T_MATCHES_OFF64_T        1
> #define __INO_T_MATCHES_INO64_T        1
> 
> for new architectures (obviously not the ones that already use the
> 32-bit types). I haven't tries this, so there may be other things
> that are required.

I think more than that would be needed to get struct stat to match and get 
things aliased for that (which is presumably desirable).

-- 
Joseph S. Myers
joseph at codesourcery.com


From julien.grall at arm.com  Tue May 17 08:50:11 2016
From: julien.grall at arm.com (Julien Grall)
Date: Tue, 17 May 2016 16:50:11 +0100
Subject: [PATCH v4 49/56] KVM: arm/arm64: vgic-new: vgic_init: implement
 kvm_vgic_hyp_init
In-Reply-To: <1463392481-26583-107-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-107-git-send-email-andre.przywara@arm.com>
Message-ID: <573B3DB3.80707@arm.com>

Hi Andre,

On 16/05/16 10:54, Andre Przywara wrote:
> +
> +/**
> + * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
> + * @node:	pointer to the DT node

This needs to be updated to match the parameters of vgic_v2_probe.

> + *
> + * Returns 0 if a GICv2 has been found, returns an error code otherwise
> + */
> +int vgic_v2_probe(const struct gic_kvm_info *info)

[...]

> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 8548297..de0e8e0 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -15,6 +15,9 @@
>   #include <linux/irqchip/arm-gic-v3.h>
>   #include <linux/kvm.h>
>   #include <linux/kvm_host.h>
> +#include <kvm/arm_vgic.h>
> +#include <asm/kvm_mmu.h>
> +#include <asm/kvm_asm.h>
>
>   #include "vgic.h"
>
> @@ -182,3 +185,49 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>   	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
>   	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
>   }
> +
> +/**
> + * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
> + * @node:	pointer to the DT node

This needs to be updated to match the parameters of vgic_v3_probe.

> + *
> + * Returns 0 if a GICv3 has been found, returns an error code otherwise
> + */
> +int vgic_v3_probe(const struct gic_kvm_info *info)

Regards,

-- 
Julien Grall


From wens at csie.org  Tue May 17 08:56:06 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 23:56:06 +0800
Subject: [PATCH 1/6] drm: sun4i: do cleanup if RGB output init fails
In-Reply-To: <1463500571-28970-1-git-send-email-wens@csie.org>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
Message-ID: <1463500571-28970-2-git-send-email-wens@csie.org>

sun4i_rgb_init() can fail, which results in TCON failing to bind.
In this case we need to do cleanup, specificly unregistering the
dotclock, which is regmap based, and the regmap is registered as
part of the sun4i_tcon_bind().

Failing to do so results in a NULL pointer reference when the CCF
tries to turn off unused clocks.

Fixes: 29e57fab97fc ("drm: sun4i: Add RGB output")
Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 9f19b0e08560..dea673275356 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -490,7 +490,11 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		return 0;
 	}
 
-	return sun4i_rgb_init(drm);
+	ret = sun4i_rgb_init(drm);
+	if (ret < 0)
+		goto err_free_clocks;
+
+	return 0;
 
 err_free_clocks:
 	sun4i_tcon_free_clocks(tcon);
-- 
2.8.1



From wens at csie.org  Tue May 17 08:56:05 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 23:56:05 +0800
Subject: [PATCH 0/6] ARM: dts: sun5i: q8-common: Enable various peripherals
Message-ID: <1463500571-28970-1-git-send-email-wens@csie.org>

Hi everyone,

This series enables more peripherals for Allwinner A13-based Q8 devices.
The peripherals include the WiFi, the PMIC's micro-usb power supply
(driver), audio codec (headphone and speaker), and full display support
with the new DRM KMS driver. The series is based on parts of Maxime's
"drm: Add Support for Passive RGB to VGA bridges" series, specifically
the clk and drm fixes, and common DTS bits.

Hans, since you have a collection of q8 tablets, I'm hoping you could
test these bits and provide some feedback.


Patch 1 is a small fix for part of the init failure path.

Patch 2 disables ldo5 on the axp209 by default. This regulator output is
muxed with a gpio, and the regulator on/off settings override the gpio.

Patch 3 enables the USB WiFi module found.

Patch 4 enables the USB/VBUS power supply of the PMIC.

Patch 5 enables the audio codec, with support for the speaker amp.

Patch 6 enables the LCD panel with the display pipeline.


Regards
ChenYu


Chen-Yu Tsai (6):
  drm: sun4i: do cleanup if RGB output init fails
  ARM: dts: axp209: Disable ldo5 by default
  ARM: dts: sun5i: q8-common: Enable USB-based WiFi
  ARM: dts: sun5i: q8-common: Enable USB power supply
  ARM: dts: sun5i: q8-common: Enable audio codec
  ARM: dts: sun5i: q8-common: Enable display pipeline and LCD display

 arch/arm/boot/dts/axp209.dtsi          |  1 +
 arch/arm/boot/dts/sun5i-q8-common.dtsi | 62 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun4i_tcon.c     |  6 +++-
 3 files changed, 68 insertions(+), 1 deletion(-)

-- 
2.8.1



From wens at csie.org  Tue May 17 08:56:08 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 23:56:08 +0800
Subject: [PATCH 3/6] ARM: dts: sun5i: q8-common: Enable USB-based WiFi
In-Reply-To: <1463500571-28970-1-git-send-email-wens@csie.org>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
Message-ID: <1463500571-28970-4-git-send-email-wens@csie.org>

The early A13 Q8 tablets all use a Realtek WiFi module connected to
USB1. The module is powered by AXP209's LDO3 at 3.3V.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 arch/arm/boot/dts/sun5i-q8-common.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i-q8-common.dtsi b/arch/arm/boot/dts/sun5i-q8-common.dtsi
index a78e189f6653..dcaaa085ac77 100644
--- a/arch/arm/boot/dts/sun5i-q8-common.dtsi
+++ b/arch/arm/boot/dts/sun5i-q8-common.dtsi
@@ -154,6 +154,12 @@
 	regulator-name = "avcc";
 };
 
+&reg_ldo3 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-wifi";
+};
+
 &reg_usb0_vbus {
 	gpio = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
 	status = "okay";
@@ -176,5 +182,6 @@
 	usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
 	usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
 	usb0_vbus-supply = <&reg_usb0_vbus>;
+	usb1_vbus-supply = <&reg_ldo3>;
 	status = "okay";
 };
-- 
2.8.1



From wens at csie.org  Tue May 17 08:56:07 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 23:56:07 +0800
Subject: [PATCH 2/6] ARM: dts: axp209: Disable ldo5 by default
In-Reply-To: <1463500571-28970-1-git-send-email-wens@csie.org>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
Message-ID: <1463500571-28970-3-git-send-email-wens@csie.org>

The output pin of LDO is also a GPIO pin, and the on/off settings of the
regulator are actually pinmux settings.

Disable it by default so it doesn't conflict with GPIO usage.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 arch/arm/boot/dts/axp209.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/axp209.dtsi b/arch/arm/boot/dts/axp209.dtsi
index 051ab3ba9a65..afbe89c01df5 100644
--- a/arch/arm/boot/dts/axp209.dtsi
+++ b/arch/arm/boot/dts/axp209.dtsi
@@ -87,6 +87,7 @@
 
 		reg_ldo5: ldo5 {
 			regulator-name = "ldo5";
+			status = "disabled";
 		};
 	};
 
-- 
2.8.1



From wens at csie.org  Tue May 17 08:56:09 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 23:56:09 +0800
Subject: [PATCH 4/6] ARM: dts: sun5i: q8-common: Enable USB power supply
In-Reply-To: <1463500571-28970-1-git-send-email-wens@csie.org>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
Message-ID: <1463500571-28970-5-git-send-email-wens@csie.org>

On the A13 Q8 tablets, the PMIC's USB power supply (VBUS) is connected
to the external OTG port. This can be used to provide power and OTG VBUS
sensing.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 arch/arm/boot/dts/sun5i-q8-common.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i-q8-common.dtsi b/arch/arm/boot/dts/sun5i-q8-common.dtsi
index dcaaa085ac77..8fc1b6110fb8 100644
--- a/arch/arm/boot/dts/sun5i-q8-common.dtsi
+++ b/arch/arm/boot/dts/sun5i-q8-common.dtsi
@@ -176,11 +176,16 @@
 	status = "okay";
 };
 
+&usb_power_supply {
+	status = "okay";
+};
+
 &usbphy {
 	pinctrl-names = "default";
 	pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
 	usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
 	usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
+	usb0_vbus_power-supply = <&usb_power_supply>;
 	usb0_vbus-supply = <&reg_usb0_vbus>;
 	usb1_vbus-supply = <&reg_ldo3>;
 	status = "okay";
-- 
2.8.1



From wens at csie.org  Tue May 17 08:56:11 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 23:56:11 +0800
Subject: [PATCH 6/6] ARM: dts: sun5i: q8-common: Enable display pipeline and
 LCD display
In-Reply-To: <1463500571-28970-1-git-send-email-wens@csie.org>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
Message-ID: <1463500571-28970-7-git-send-email-wens@csie.org>

Q8 form factor A13 tablets have a 7" LCD panel. Unfortunately we
don't know the exact model of the panel. Just pick a panel with
display timings close to what we know.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 arch/arm/boot/dts/sun5i-q8-common.dtsi | 36 ++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i-q8-common.dtsi b/arch/arm/boot/dts/sun5i-q8-common.dtsi
index 5b065fd542f0..a5de28d12b16 100644
--- a/arch/arm/boot/dts/sun5i-q8-common.dtsi
+++ b/arch/arm/boot/dts/sun5i-q8-common.dtsi
@@ -59,6 +59,29 @@
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
+
+	panel: panel {
+		compatible = "urt,umsh-8596md-t", "simple-panel";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port at 0 {
+			reg = <0>;
+			/* TODO: lcd panel uses axp gpio0 as enable pin */
+			backlight = <&backlight>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			panel_input: endpoint at 0 {
+				reg = <0>;
+				remote-endpoint = <&tcon0_out_lcd>;
+			};
+		};
+	};
+};
+
+&be0 {
+	status = "okay";
 };
 
 &codec {
@@ -179,6 +202,19 @@
 	status = "okay";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_rgb666_pins>;
+	status = "okay";
+};
+
+&tcon0_out {
+	tcon0_out_lcd: endpoint at 0 {
+		reg = <0>;
+		remote-endpoint = <&panel_input>;
+	};
+};
+
 &uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart1_pins_b>;
-- 
2.8.1



From wens at csie.org  Tue May 17 08:56:10 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 17 May 2016 23:56:10 +0800
Subject: [PATCH 5/6] ARM: dts: sun5i: q8-common: Enable audio codec
In-Reply-To: <1463500571-28970-1-git-send-email-wens@csie.org>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
Message-ID: <1463500571-28970-6-git-send-email-wens@csie.org>

The Q8 tablets use the audio codec to provide audio output via a
headphone jack or a small mono speaker. A GPIO output is used to
control speaker amp.

The tablets may or may not have an internal microphone.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 arch/arm/boot/dts/sun5i-q8-common.dtsi | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i-q8-common.dtsi b/arch/arm/boot/dts/sun5i-q8-common.dtsi
index 8fc1b6110fb8..5b065fd542f0 100644
--- a/arch/arm/boot/dts/sun5i-q8-common.dtsi
+++ b/arch/arm/boot/dts/sun5i-q8-common.dtsi
@@ -61,6 +61,13 @@
 	};
 };
 
+&codec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&codec_pa_pin>;
+	allwinner,pa-gpios = <&pio 6 10 GPIO_ACTIVE_HIGH>; /* PG10 */
+	status = "okay";
+};
+
 &cpu0 {
 	cpu-supply = <&reg_dcdc2>;
 };
@@ -100,6 +107,13 @@
 };
 
 &pio {
+	codec_pa_pin: codec_pa_pin at 0 {
+		allwinner,pins = "PG10";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
 	mmc0_cd_pin_q8: mmc0_cd_pin at 0 {
 		allwinner,pins = "PG0";
 		allwinner,function = "gpio_in";
-- 
2.8.1



From slash.tmp at free.fr  Tue May 17 08:56:44 2016
From: slash.tmp at free.fr (Mason)
Date: Tue, 17 May 2016 17:56:44 +0200
Subject: CONFIG_ZBOOT_ROM_TEXT and CONFIG_ZBOOT_ROM_BSS in defconfig
Message-ID: <573B3F3C.80800@free.fr>

Hello,

When reviewing my platform's defconfig, these two entries jumped out:

CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0

I found it odd that they would appear in the defconfig, since I don't
care about them, and left them at their default value -- as most
platforms seem to do:

$ git grep CONFIG_ZBOOT_ROM_TEXT=0x0 arch/arm/configs | wc -l
83

# Compressed boot loader in ROM.  Yes, we really want to ask about
# TEXT and BSS so we preserve their values in the config files.
config ZBOOT_ROM_TEXT
	hex "Compressed ROM boot loader base address"
	default "0"

It seems 'make savedefconfig' doesn't consider 0 and 0x0 to be equivalent.

I can submit a patch changing the default from 0 to 0x0, i.e.
no functional change. The two entries would then disappear
from defconfigs.

Arnd didn't seem to like the idea. How do others feel?

Regards.


From schwab at suse.de  Tue May 17 09:02:36 2016
From: schwab at suse.de (Andreas Schwab)
Date: Tue, 17 May 2016 18:02:36 +0200
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <alpine.DEB.2.20.1605171542340.24255@digraph.polyomino.org.uk>
 (Joseph Myers's message of "Tue, 17 May 2016 15:45:11 +0000")
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <573B0A4D.4090704@arm.com> <4173531.IRSphtVpg9@wuerfel>
 <alpine.DEB.2.20.1605171542340.24255@digraph.polyomino.org.uk>
Message-ID: <mvm1t50ad0j.fsf@hawking.suse.de>

Joseph Myers <joseph at codesourcery.com> writes:

> On Tue, 17 May 2016, Arnd Bergmann wrote:
>
>> I think it has become easier to override now and we just need to
>> update sysdeps/unix/sysv/linux/generic/bits/typesizes.h to set
>> 
>> #define __INO64_T_TYPE          __UQUAD_TYPE
>> #define __OFF64_T_TYPE          __UQUAD_TYPE
>> #define __OFF_T_MATCHES_OFF64_T        1
>> #define __INO_T_MATCHES_INO64_T        1
>> 
>> for new architectures (obviously not the ones that already use the
>> 32-bit types). I haven't tries this, so there may be other things
>> that are required.
>
> I think more than that would be needed to get struct stat to match and get 
> things aliased for that (which is presumably desirable).

Looking at sysdeps/unix/sysv/linux/generic/bits/stat.h, there is at
least blkcnt_t that differs between stat and stat64.  And you probably
want to alias statfs and statfs64 as well, ie. fs{blk,fil}cnt_t.

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab at suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."


From davem at davemloft.net  Tue May 17 09:25:27 2016
From: davem at davemloft.net (David Miller)
Date: Tue, 17 May 2016 12:25:27 -0400 (EDT)
Subject: [RESEND PATCH v6 0/6] Add Ethernet support on STM32F429
In-Reply-To: <CALszF6Cfs02-tGvFqpyJpUy7jSfjGTY8fVaaLQ8iQaGfCxvDtQ@mail.gmail.com>
References: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
 <20160509.150634.213732321950308841.davem@davemloft.net>
 <CALszF6Cfs02-tGvFqpyJpUy7jSfjGTY8fVaaLQ8iQaGfCxvDtQ@mail.gmail.com>
Message-ID: <20160517.122527.1937360418899371800.davem@davemloft.net>

From: Maxime Coquelin <mcoquelin.stm32 at gmail.com>
Date: Tue, 17 May 2016 11:20:16 +0200

> Hi David,
> 
> 2016-05-09 21:06 GMT+02:00 David Miller <davem at davemloft.net>:
>> From: Alexandre TORGUE <alexandre.torgue at gmail.com>
>> Date: Mon,  9 May 2016 12:31:33 +0200
>>
>>> STM32F429 Chip embeds a Synopsys 3.50a MAC IP.
>>> This series:
>>>  -enhance current stmmac driver to control it (code already
>>> available) and adds basic glue for STM32F429 chip.
>>>  -Enable basic Net config in kernel.
>>
>> I assume this will go via the ARM tree, for the networking bits:
> I would expect patches 1, 2 & 3 to got via your tree, to avoid conflicts.

I don't think putting them all via the ARM tree is going to create much
in the way of conflicts, and right now during the merge window offloading
that work from me would really help my backlog a lot.

Thanks.


From colin.king at canonical.com  Tue May 17 09:26:55 2016
From: colin.king at canonical.com (Colin King)
Date: Tue, 17 May 2016 17:26:55 +0100
Subject: [PATCH] pinctrl: stm32: fix incorrect pinctl format message
Message-ID: <1463502415-17920-1-git-send-email-colin.king@canonical.com>

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

There are missing string format specifiers in the seq_printf
that are causing a build warning.  Add these missing string
format specifiers to fix this.

Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
 drivers/pinctrl/stm32/pinctrl-stm32.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index e51c1cf..ae9fab8 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -794,7 +794,7 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
 	case 2:
 		drive = stm32_pconf_get_driving(bank, offset);
 		speed = stm32_pconf_get_speed(bank, offset);
-		seq_printf(s, "%d - %s -%s", alt,
+		seq_printf(s, "%d - %s - %s - %s %s", alt,
 			   drive ? "open drain" : "push pull",
 			   biasing[bias],
 			   speeds[speed], "speed");
-- 
2.8.1



From al.stone at linaro.org  Tue May 17 09:30:34 2016
From: al.stone at linaro.org (Al Stone)
Date: Tue, 17 May 2016 10:30:34 -0600
Subject: [PATCH v5 0/1] ARM64: ACPI: Update documentation for latest
 specification version
In-Reply-To: <20160516234441.GA7425@arm.com>
References: <20160516234441.GA7425@arm.com>
Message-ID: <44cda485-1c43-f7c3-676b-f9c47785daf6@linaro.org>

On 05/16/2016 05:44 PM, Alexey Klimov wrote:
> On Mon, May 2, 2016 at 09:19 PM, Al Stone wrote:
>> On 04/25/2016 03:21 PM, Al Stone wrote:
>>> The ACPI 6.1 specification was recently released at the end of January
>>> 2016, but the arm64 kernel documentation for the use of ACPI was written
>>> for the 5.1 version of the spec.  There were significant additions to the
>>> spec that had not yet been mentioned -- for example, the 6.0 mechanisms
>>> added to make it easier to define processors and low power idle states,
>>> as well as the 6.1 addition allowing regular interrupts (not just from
>>> GPIO) be used to signal ACPI general purpose events.
>>>
>>> This patch reflects going back through and examining the specs in detail
>>> and updating content appropriately.  Whilst there, a few odds and ends of
>>> typos were caught as well.  This brings the documentation up to date with
>>> ACPI 6.1 for arm64.
>>>
>>> Changes for v5:
>>>    -- Miscellaneous typos and corrections (Lorenzo Pieralisi)
>>>    -- Add linux-acpi@ ML to the distribution list (Alexey Klimov)
>>>    -- Corrections to CPPC information (Alexey Klimov)
>>>    -- ACK from Lorenzo Pieralisi
>>>    -- Updated bibliographic info (Al Stone)
>>>
>>> Changes for v4:
>>>    -- Clarify that IORT can sometimes be optional (Jon Masters).
>>>    -- Remove "Use as needed" descriptions of ACPI objects; they provide
>>>       no substantive information and doing so simplifies maintenance of
>>>       this document over time.  These have been replaced with a simpler
>>>       notice that states that unless otherwise noted, do what the ACPI
>>>       specification says is needed.
>>>    -- Corrected the _OSI object usage recommendation; it described kernel
>>>       behavior that does not exist (Al Stone).
>>>
>>> Changes for v3:
>>>    -- Clarify use of _LPI/_RDI (Vikas Sajjan)
>>>    -- Whitespace cleanup as pointed out by checkpatch
>>>
>>> Changes for v2:
>>>    -- Clean up white space (Harb Abdulhahmid)
>>>    -- Clarification on _CCA usage (Harb Abdulhamid)
>>>    -- IORT moved to required from recommended (Hanjun Guo)
>>>    -- Clarify IORT description (Hanjun Guo)
>>>
>>>
>>> Al Stone (1):
>>>   ARM64: ACPI: Update documentation for latest specification version
>>>
>>>  Documentation/arm64/acpi_object_usage.txt | 343 ++++++++++++++++--------------
>>>  Documentation/arm64/arm-acpi.txt          |  40 ++--
>>>  2 files changed, 213 insertions(+), 170 deletions(-)
>>>
>>
>> Ping?  If there are no further comments, can this be pulled in through
>> either the documentation or arm64 tree?
>>
>> Thanks.
> 
> Hi Al,
> sorry for delay.
> 
> CPPC and PCC corrections look fine. Thanks.
> 
> 
> This comment is not to block your patch (maybe some to-do):
> I greped sources and your patch and I don't see description of _PSD object.
> This P-state dependancy object is optional but it's presense and correct data
> are extremely useful for CPPC and can potentially descrease number of performance
> changing requests.
> 
> ACPI spec in section about CPPC tells that it may use _PSD (page 503 if I remember
> correctly) to specify domain belongings of CPUs.
> 
> You may consider to add description of _PSD object later.
> 
> Best regards,
> Alexey.
> 

Hrm.  Thanks, Alexey.  I'll take a look.  _PSD may be in one of
the gray areas where we expect people to read the spec and follow
it properly, but it may make sense to be very explicit about what
they need to do to use it properly.  Perhaps this would make a good
FWTS test, too.

-- 
ciao,
al
-----------------------------------
Al Stone
Software Engineer
Linaro Enterprise Group
al.stone at linaro.org
-----------------------------------


From jcm at redhat.com  Tue May 17 09:44:02 2016
From: jcm at redhat.com (Jon Masters)
Date: Tue, 17 May 2016 12:44:02 -0400
Subject: [PATCH 3/3] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
In-Reply-To: <20160517124629.GE14955@leverpostej>
References: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
 <1463486765-31827-4-git-send-email-aleksey.makarov@linaro.org>
 <20160517124629.GE14955@leverpostej>
Message-ID: <f0bf43ef-0be5-484c-5066-ab1929105b82@redhat.com>

Hi Mark,

On 05/17/2016 08:46 AM, Mark Rutland wrote:
> On Tue, May 17, 2016 at 03:06:03PM +0300, Aleksey Makarov wrote:
>> From: Jon Masters <jcm at redhat.com>
>>
>> This patch adds support for ACPI_TABLE_UPGRADE for ARM64
> 
> This feels like a tool to paper over problems rather than solve them.

Generally, it's an arrow in the quiver used to triage problems, and then
solve them by getting firmware updates made.

> If vendors are shipping horrendously broken tables today, clearly no
> software has ever really supported them. So why add workarounds?

That's not (always) the case. These patches help with:

1). During development of a platform, it is much easier to debug
problems with tables if you can test replacement ones without having to
respin the firmware. In the server world, you usually don't have the
firmware source code, so to get it respun could be days-weeks even if
you are working with the authors closely. We have practically used this
feature on a number of platforms already and it will continue.

2). They empower (advanced) users and developers to work around problems
that they find on platforms. Sure, we want firmware to always be fixed
and working well, but it is better if folks have the tools.

> Why is this necessary? Is there a particular case for this, or is this
> just for parity with x86?

The use cases are as above. It's also required for parity with x86
functionality on servers.

> IMO it would be better to put pressure on vendors to fix their FW and
> provide sensible OS-agnostic update mechanisms.

It's easier to put pressure on them after we know what the problems are.
I agree that alternative update mechanisms are also good. We also have
the ability (but it is not implemented on ARM) in GRUB2 to override ACPI
tables, BUT it's kinda atrophied on all arches and requires that you
rebuild GRUB with an additional module. The reality is that by
incorporating this feature we are able to provide the same capability
that already exists on x86 systems for ACPI table triage.

Jon.

-- 
Computer Architect | Sent from my Fedora powered laptop


From jcm at redhat.com  Tue May 17 09:48:53 2016
From: jcm at redhat.com (Jon Masters)
Date: Tue, 17 May 2016 12:48:53 -0400
Subject: [PATCH 3/3] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
In-Reply-To: <f0bf43ef-0be5-484c-5066-ab1929105b82@redhat.com>
References: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
 <1463486765-31827-4-git-send-email-aleksey.makarov@linaro.org>
 <20160517124629.GE14955@leverpostej>
 <f0bf43ef-0be5-484c-5066-ab1929105b82@redhat.com>
Message-ID: <b0933a59-239d-536f-4f63-a65e469f62a1@redhat.com>

On 05/17/2016 12:44 PM, Jon Masters wrote:

> 1). During development of a platform, it is much easier to debug
> problems with tables if you can test replacement ones without having to
> respin the firmware. In the server world, you usually don't have the
> firmware source code, so to get it respun could be days-weeks even if
> you are working with the authors closely. We have practically used this
> feature on a number of platforms already and it will continue.

For example, on one platform we were unable to fully boot RHEL(SA) due
to a bug in one of the ACPI tables. But I was able to boot the system to
a ramdisk containing a uuencode library and then write out the content
of the tables over the serial port, then decompile/patch/recompile, and
override replacement tables on the system. Then we beat the vendor up
with the fixes and the official firmware was corrected.


-- 
Computer Architect | Sent from my Fedora powered laptop


From davem at davemloft.net  Tue May 17 11:03:46 2016
From: davem at davemloft.net (David Miller)
Date: Tue, 17 May 2016 14:03:46 -0400 (EDT)
Subject: [PATCH v2 net-next] bpf: arm64: remove callee-save registers
 use for tmp registers
In-Reply-To: <1463441786-32224-1-git-send-email-yang.shi@linaro.org>
References: <1463441786-32224-1-git-send-email-yang.shi@linaro.org>
Message-ID: <20160517.140346.1420108193136786648.davem@davemloft.net>

From: Yang Shi <yang.shi at linaro.org>
Date: Mon, 16 May 2016 16:36:26 -0700

> In the current implementation of ARM64 eBPF JIT, R23 and R24 are used for
> tmp registers, which are callee-saved registers. This leads to variable size
> of JIT prologue and epilogue. The latest blinding constant change prefers to
> constant size of prologue and epilogue. AAPCS reserves R9 ~ R15 for temp
> registers which not need to be saved/restored during function call. So, replace
> R23 and R24 to R10 and R11, and remove tmp_used flag to save 2 instructions for
> some jited BPF program.
> 
> CC: Daniel Borkmann <daniel at iogearbox.net>
> Acked-by: Zi Shen Lim <zlim.lnx at gmail.com>
> Signed-off-by: Yang Shi <yang.shi at linaro.org>

Applied.


From davem at davemloft.net  Tue May 17 11:11:54 2016
From: davem at davemloft.net (David Miller)
Date: Tue, 17 May 2016 14:11:54 -0400 (EDT)
Subject: QRTR merge conflict resolution
In-Reply-To: <20160513221909.GC1256@tuxbot>
References: <20160510183934.GJ1256@tuxbot> <2606282.lG9qK7uBW0@wuerfel>
 <20160513221909.GC1256@tuxbot>
Message-ID: <20160517.141154.1511755950068252376.davem@davemloft.net>

From: Bjorn Andersson <bjorn.andersson at linaro.org>
Date: Fri, 13 May 2016 15:19:09 -0700

> I have prepared the merge of net-next and the conflicting tag from the
> Qualcomm SOC, please include this in your pull towards Linus to avoid
> the merge conflict.

Pulled, thanks.


From pavel at ucw.cz  Tue May 17 11:19:27 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Tue, 17 May 2016 20:19:27 +0200
Subject: [PATCH] support for AD5820 camera auto-focus coil
Message-ID: <20160517181927.GA28741@amd>

This adds support for AD5820 autofocus coil, found for example in
Nokia N900 smartphone.

Signed-off-by: Pavel Machek <pavel at ucw.cz>


diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 993dc50..77313a1 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -279,6 +279,13 @@ config VIDEO_ML86V7667
 	  To compile this driver as a module, choose M here: the
 	  module will be called ml86v7667.
 
+config VIDEO_AD5820
+	tristate "AD5820 lens voice coil support"
+	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+	---help---
+	  This is a driver for the AD5820 camera lens voice coil.
+	  It is used for example in Nokia N900 (RX-51).
+
 config VIDEO_SAA7110
 	tristate "Philips SAA7110 video decoder"
 	depends on VIDEO_V4L2 && I2C
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 94f2c99..34434ae 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -19,6 +20,7 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
 obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
 obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
+obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o
 obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
 obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
 obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
new file mode 100644
index 0000000..b71cc11
--- /dev/null
+++ b/drivers/media/i2c/ad5820.c
@@ -0,0 +1,435 @@
+/*
+ * drivers/media/i2c/ad5820.c
+ *
+ * AD5820 DAC driver for camera voice coil focus.
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2007 Texas Instruments
+ * Copyright (C) 2016 Pavel Machek <pavel at ucw.cz>
+ *
+ * Contact: Tuukka Toivonen
+ *          Sakari Ailus
+ *
+ * Based on af_d88.c by Texas Instruments.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/regulator/consumer.h>
+
+#include <media/ad5820.h>
+#include <media/v4l2-device.h>
+
+#define CODE_TO_RAMP_US(s)	((s) == 0 ? 0 : (1 << ((s) - 1)) * 50)
+#define RAMP_US_TO_CODE(c)	fls(((c) + ((c)>>1)) / 50)
+
+/**
+ * @brief I2C write using i2c_transfer().
+ * @param coil - the driver data structure
+ * @param data - register value to be written
+ * @returns nonnegative on success, negative if failed
+ */
+static int ad5820_write(struct ad5820_device *coil, u16 data)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&coil->subdev);
+	struct i2c_msg msg;
+	int r;
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	data = cpu_to_be16(data);
+	msg.addr  = client->addr;
+	msg.flags = 0;
+	msg.len   = 2;
+	msg.buf   = (u8 *)&data;
+
+	r = i2c_transfer(client->adapter, &msg, 1);
+	if (r < 0) {
+		dev_err(&client->dev, "write failed, error %d\n", r);
+		return r;
+	}
+
+	return 0;
+}
+
+/*
+ * Calculate status word and write it to the device based on current
+ * values of V4L2 controls. It is assumed that the stored V4L2 control
+ * values are properly limited and rounded.
+ */
+static int ad5820_update_hw(struct ad5820_device *coil)
+{
+	u16 status;
+
+	status = RAMP_US_TO_CODE(coil->focus_ramp_time);
+	status |= coil->focus_ramp_mode
+		? AD5820_RAMP_MODE_64_16 : AD5820_RAMP_MODE_LINEAR;
+	status |= coil->focus_absolute << AD5820_DAC_SHIFT;
+
+	if (coil->standby)
+		status |= AD5820_POWER_DOWN;
+
+	return ad5820_write(coil, status);
+}
+
+/*
+ * Power handling
+ */
+static int ad5820_power_off(struct ad5820_device *coil, int standby)
+{
+	int ret = 0;
+
+	/*
+	 * Go to standby first as real power off my be denied by the hardware
+	 * (single power line control for both coil and sensor).
+	 */
+	if (standby) {
+		coil->standby = 1;
+		ret = ad5820_update_hw(coil);
+	}
+
+	ret |= regulator_disable(coil->vana);
+
+	return ret;
+}
+
+static int ad5820_power_on(struct ad5820_device *coil, int restore)
+{
+	int ret;
+
+	printk("ad5820_power_on: 1\n");
+	ret = regulator_enable(coil->vana);
+	if (ret < 0)
+		return ret;
+
+	if (restore) {
+		/* Restore the hardware settings. */
+		coil->standby = 0;
+		ret = ad5820_update_hw(coil);
+		if (ret)
+			goto fail;
+	}
+	return 0;
+
+fail:
+	coil->standby = 1;
+	regulator_disable(coil->vana);
+
+	return ret;
+}
+
+/*
+ * V4L2 controls
+ */
+static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ad5820_device *coil =
+		container_of(ctrl->handler, struct ad5820_device, ctrls);
+	u32 code;
+	int r = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_FOCUS_ABSOLUTE:
+		coil->focus_absolute = ctrl->val;
+		return ad5820_update_hw(coil);
+
+	case V4L2_CID_FOCUS_AD5820_RAMP_TIME:
+		code = RAMP_US_TO_CODE(ctrl->val);
+		ctrl->val = CODE_TO_RAMP_US(code);
+		coil->focus_ramp_time = ctrl->val;
+		break;
+
+	case V4L2_CID_FOCUS_AD5820_RAMP_MODE:
+		coil->focus_ramp_mode = ctrl->val;
+		break;
+	}
+
+	return r;
+}
+
+static const struct v4l2_ctrl_ops ad5820_ctrl_ops = {
+	.s_ctrl = ad5820_set_ctrl,
+};
+
+static const char *ad5820_focus_menu[] = {
+	"Linear ramp",
+	"64/16 ramp",
+};
+
+static const struct v4l2_ctrl_config ad5820_ctrls[] = {
+	{
+		.ops		= &ad5820_ctrl_ops,
+		.id		= V4L2_CID_FOCUS_AD5820_RAMP_TIME,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Focus ramping time [us]",
+		.min		= 0,
+		.max		= 3200,
+		.step		= 50,
+		.def		= 0,
+		.flags		= 0,
+	},
+	{
+		.ops		= &ad5820_ctrl_ops,
+		.id		= V4L2_CID_FOCUS_AD5820_RAMP_MODE,
+		.type		= V4L2_CTRL_TYPE_MENU,
+		.name		= "Focus ramping mode",
+		.min		= 0,
+		.max		= ARRAY_SIZE(ad5820_focus_menu),
+		.step		= 0,
+		.def		= 0,
+		.flags		= 0,
+		.qmenu		= ad5820_focus_menu,
+	},
+};
+
+
+static int ad5820_init_controls(struct ad5820_device *coil)
+{
+	unsigned int i;
+
+	v4l2_ctrl_handler_init(&coil->ctrls, ARRAY_SIZE(ad5820_ctrls) + 1);
+
+	/*
+	 * V4L2_CID_FOCUS_ABSOLUTE
+	 *
+	 * Minimum current is 0 mA, maximum is 100 mA. Thus, 1 code is
+	 * equivalent to 100/1023 = 0.0978 mA. Nevertheless, we do not use [mA]
+	 * for focus position, because it is meaningless for user. Meaningful
+	 * would be to use focus distance or even its inverse, but since the
+	 * driver doesn't have sufficiently knowledge to do the conversion, we
+	 * will just use abstract codes here. In any case, smaller value = focus
+	 * position farther from camera. The default zero value means focus at
+	 * infinity, and also least current consumption.
+	 */
+	v4l2_ctrl_new_std(&coil->ctrls, &ad5820_ctrl_ops,
+			  V4L2_CID_FOCUS_ABSOLUTE, 0, 1023, 1, 0);
+
+	/* V4L2_CID_TEST_PATTERN and V4L2_CID_MODE_* */
+	for (i = 0; i < ARRAY_SIZE(ad5820_ctrls); ++i)
+		v4l2_ctrl_new_custom(&coil->ctrls, &ad5820_ctrls[i], NULL);
+
+	if (coil->ctrls.error)
+		return coil->ctrls.error;
+
+	coil->focus_absolute = 0;
+	coil->focus_ramp_time = 0;
+	coil->focus_ramp_mode = 0;
+
+	coil->subdev.ctrl_handler = &coil->ctrls;
+	return 0;
+}
+
+/*
+ * V4L2 subdev operations
+ */
+static int ad5820_registered(struct v4l2_subdev *subdev)
+{
+	static const int CHECK_VALUE = 0x3FF0;
+
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+
+	coil->vana = regulator_get(&client->dev, "VANA");
+	if (IS_ERR(coil->vana)) {
+		dev_err(&client->dev, "could not get regulator for vana\n");
+		return -ENODEV;
+	}
+
+	return ad5820_init_controls(coil);
+}
+
+static int
+ad5820_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+	int ret = 0;
+
+	mutex_lock(&coil->power_lock);
+
+	/*
+	 * If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (coil->power_count == !on) {
+		ret = on ? ad5820_power_on(coil, 1) : ad5820_power_off(coil, 1);
+		if (ret < 0)
+			goto done;
+	}
+
+	/* Update the power count. */
+	coil->power_count += on ? 1 : -1;
+	WARN_ON(coil->power_count < 0);
+
+done:
+	mutex_unlock(&coil->power_lock);
+	return ret;
+}
+
+static int ad5820_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return ad5820_set_power(sd, 1);
+}
+
+static int ad5820_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return ad5820_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_core_ops ad5820_core_ops = {
+	.s_power = ad5820_set_power,
+};
+
+static const struct v4l2_subdev_ops ad5820_ops = {
+	.core = &ad5820_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops ad5820_internal_ops = {
+	.registered = ad5820_registered,
+	.open = ad5820_open,
+	.close = ad5820_close,
+};
+
+/*
+ * I2C driver
+ */
+#ifdef CONFIG_PM
+
+static int ad5820_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	if (!coil->power_count)
+		return 0;
+
+	return ad5820_power_off(coil, 0);
+}
+
+static int ad5820_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	if (!coil->power_count)
+		return 0;
+
+	return ad5820_power_on(coil, 1);
+}
+
+#else
+
+#define ad5820_suspend	NULL
+#define ad5820_resume	NULL
+
+#endif /* CONFIG_PM */
+
+static int ad5820_probe(struct i2c_client *client,
+			const struct i2c_device_id *devid)
+{
+	struct ad5820_device *coil;
+	int ret = 0;
+
+	coil = kzalloc(sizeof(*coil), GFP_KERNEL);
+	if (coil == NULL)
+		return -ENOMEM;
+
+	mutex_init(&coil->power_lock);
+
+	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
+	coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	coil->subdev.internal_ops = &ad5820_internal_ops;
+	strcpy(coil->subdev.name, "ad5820 focus");
+
+	ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
+	if (ret < 0) {
+		kfree(coil);
+		return ret;
+	}
+
+	ret = v4l2_async_register_subdev(&coil->subdev);
+	if (ret < 0)
+		kfree(coil);
+
+	return ret;
+}
+
+static int __exit ad5820_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	v4l2_device_unregister_subdev(&coil->subdev);
+	v4l2_ctrl_handler_free(&coil->ctrls);
+	media_entity_cleanup(&coil->subdev.entity);
+	if (coil->vana)
+		regulator_put(coil->vana);
+
+	kfree(coil);
+	return 0;
+}
+
+static const struct i2c_device_id ad5820_id_table[] = {
+	{ AD5820_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ad5820_id_table);
+
+static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume);
+
+static struct i2c_driver ad5820_i2c_driver = {
+	.driver		= {
+		.name	= AD5820_NAME,
+		.pm	= &ad5820_pm,
+	},
+	.probe		= ad5820_probe,
+	.remove		= __exit_p(ad5820_remove),
+	.id_table	= ad5820_id_table,
+};
+
+static int __init ad5820_init(void)
+{
+	int rval;
+
+	rval = i2c_add_driver(&ad5820_i2c_driver);
+	if (rval)
+		printk(KERN_INFO "%s: failed registering " AD5820_NAME "\n",
+		       __func__);
+
+	return rval;
+}
+
+static void __exit ad5820_exit(void)
+{
+	i2c_del_driver(&ad5820_i2c_driver);
+}
+
+
+module_init(ad5820_init);
+module_exit(ad5820_exit);
+
+MODULE_AUTHOR("Tuukka Toivonen");
+MODULE_DESCRIPTION("AD5820 camera lens driver");
+MODULE_LICENSE("GPL");

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From marcus.folkesson at gmail.com  Tue May 17 11:33:40 2016
From: marcus.folkesson at gmail.com (Marcus Folkesson)
Date: Tue, 17 May 2016 20:33:40 +0200
Subject: [PATCH] support for AD5820 camera auto-focus coil
In-Reply-To: <20160517181927.GA28741@amd>
References: <20160517181927.GA28741@amd>
Message-ID: <20160517183340.GA10358@gmail.com>

Hi Pavel,

On Tue, May 17, 2016 at 08:19:27PM +0200, Pavel Machek wrote:
> +static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +	struct ad5820_device *coil =
> +		container_of(ctrl->handler, struct ad5820_device, ctrls);
> +	u32 code;
> +	int r = 0;
> +
> +	switch (ctrl->id) {
> +	case V4L2_CID_FOCUS_ABSOLUTE:
> +		coil->focus_absolute = ctrl->val;
> +		return ad5820_update_hw(coil);
> +
> +	case V4L2_CID_FOCUS_AD5820_RAMP_TIME:
> +		code = RAMP_US_TO_CODE(ctrl->val);
> +		ctrl->val = CODE_TO_RAMP_US(code);
> +		coil->focus_ramp_time = ctrl->val;
> +		break;
> +
> +	case V4L2_CID_FOCUS_AD5820_RAMP_MODE:
> +		coil->focus_ramp_mode = ctrl->val;
> +		break;
> +	}
> +
> +	return r;

Just return 0 instead, r is not used.

> +static int ad5820_registered(struct v4l2_subdev *subdev)
> +{
> +	static const int CHECK_VALUE = 0x3FF0;

CHECK_VALUE is not used?

> +static int ad5820_probe(struct i2c_client *client,
> +			const struct i2c_device_id *devid)
> +{
> +	struct ad5820_device *coil;
> +	int ret = 0;
> +
> +	coil = kzalloc(sizeof(*coil), GFP_KERNEL);
> +	if (coil == NULL)
> +		return -ENOMEM;
> +
> +	mutex_init(&coil->power_lock);
> +
> +	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
> +	coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> +	coil->subdev.internal_ops = &ad5820_internal_ops;
> +	strcpy(coil->subdev.name, "ad5820 focus");
> +
> +	ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
> +	if (ret < 0) {
> +		kfree(coil);
> +		return ret;
> +	}
> +
> +	ret = v4l2_async_register_subdev(&coil->subdev);
> +	if (ret < 0)

Do we need to call media_entity_cleanup() here?

> +static int __init ad5820_init(void)
> +{
> +	int rval;
> +
> +	rval = i2c_add_driver(&ad5820_i2c_driver);
> +	if (rval)
> +		printk(KERN_INFO "%s: failed registering " AD5820_NAME "\n",
> +		       __func__);
> +
> +	return rval;
> +}
> +
> +static void __exit ad5820_exit(void)
> +{
> +	i2c_del_driver(&ad5820_i2c_driver);
> +}
> +
> +
> +module_init(ad5820_init);
> +module_exit(ad5820_exit);


Use module_i2c_driver() instead.


Cheers
Marcus Folkesson



From ynorov at caviumnetworks.com  Tue May 17 12:05:26 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 17 May 2016 22:05:26 +0300
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <20160516170605.GB19290@e104818-lin.cambridge.arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1459894127-17698-21-git-send-email-ynorov@caviumnetworks.com>
 <20160514150352.GA30533@yury-N73SV>
 <20160516170605.GB19290@e104818-lin.cambridge.arm.com>
Message-ID: <20160517190526.GA3731@yury-N73SV>

On Mon, May 16, 2016 at 06:06:05PM +0100, Catalin Marinas wrote:
> On Sat, May 14, 2016 at 06:03:52PM +0300, Yury Norov wrote:
> > +SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
> > +       unsigned long, prot, unsigned long, flags, unsigned long, fd,
> > +       unsigned long, pgoff)
> 
> To avoid the types confusion we could add __SC_WRAP to mmap2 in unistd.h
> and use COMPAT_SYSCALL_DEFINE6 here (together with compat_ptr_t etc.).
> 
> > +{
> > +       if (pgoff & (~PAGE_MASK >> 12))
> > +               return -EINVAL;
> > +
> > +       return sys_mmap_pgoff((compat_uptr_t) addr, (compat_size_t) len,
> > +		       (int) prot, (int) flags, (int) fd,
> > +		       pgoff >> (PAGE_SHIFT-12));
> 
> Then we wouldn't need the explicit casting here.

See below

> 
> > +}
> > +
> > +COMPAT_SYSCALL_DEFINE4(pread64, unsigned int, fd, compat_uptr_t __user *, ubuf,
> > +		       compat_size_t, count, off_t, offset)
> > +{
> > +	return sys_pread64(fd, (char *) ubuf, count, offset);
> > +}
> > +
> > +COMPAT_SYSCALL_DEFINE4(pwrite64, unsigned int, fd, compat_uptr_t __user *, ubuf,
> > +		       compat_size_t, count, off_t, offset)
> > +{
> > +	return sys_pwrite64(fd, (char *) ubuf, count, offset);
> 
> Nitpick: no space between cast type and variable name: (char *)ubuf, ...

I think it's really a matter of taste. I prefer to have a space, and
there's no solid rule in coding style.

And there are 13032 insertions of my version vs 35030 of yours:
~/work/linux$ git grep ' \*)[a-zA-Z]'|wc -l
35030
~/work/linux$ git grep ' \*) [a-zA-Z]'|wc -l
13032

Of course, I will change it if you insist.

> We can also make these functions static as they are not used outside
> this file.

If it's OK, we can use just compat_sys_xxx() instead of
COMPAT_SYSCALL_DEFINEx(xxx), and for mmap2 we'll not need to change 
_SYSCALL to _SC_WRAP in unistd.h that way.

> > -- 
> Catalin


From f.fainelli at gmail.com  Tue May 17 12:29:57 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Tue, 17 May 2016 12:29:57 -0700
Subject: [PATCH 1/3] ARM: dts: NSP: Add MSI support on PCI
In-Reply-To: <1462490972-13566-1-git-send-email-jonmason@broadcom.com>
References: <1462490972-13566-1-git-send-email-jonmason@broadcom.com>
Message-ID: <573B7135.2050604@gmail.com>

On 05/05/2016 04:29 PM, Jon Mason wrote:
> Add MSI support to the PCI driver of the Northstar Plus SoC.  This uses
> the existing pcie-iproc driver.  So, all that is needed is device tree
> entries in the DTS.
> 
> Signed-off-by: Jon Mason <jonmason at broadcom.com>

All applied, thanks! Just for next time, can you include a cover letter
for multi series patches?
-- 
Florian


From bluekvirus at gmail.com  Tue May 17 12:41:11 2016
From: bluekvirus at gmail.com (Zhiyuan Liu)
Date: Tue, 17 May 2016 12:41:11 -0700
Subject: Regarding auto reset 4B back to 3B for spi-flash before reboot.
Message-ID: <CANN9mDGhp++hHV_XituWwdCXr+7kjUenekKyBm89xX9i9O43Kg@mail.gmail.com>

Hi Mike, Guys,

I'm working on an embedded arm project for gateways and stuff, my
board has an spi-flash which utilizes

mtd/devices/m25p80.c

and it needs to reset with the exit 4B cmd before rebooting or else
the bootrom on marvell 6820 dev board won't find it again without a
hard reset (power cycling).

Currently I have added a .shutdown to issue flash cmd directly to the
chip for that but, I was just wondering if there is a better way of
doing it? My goal is to just change the devicetree not the kernel
drivers.

Have you already designed a way of doing it that I'm not aware of? Or
simply because the majority of the vendor flash chips don't need it?

Again, I'm not planning to suggest any changes accordingly, just
trying to learn from the better minds.

Many thanks,
Tim.


From xypron.glpk at gmx.de  Tue May 17 12:40:38 2016
From: xypron.glpk at gmx.de (Heinrich Schuchardt)
Date: Tue, 17 May 2016 21:40:38 +0200
Subject: [PATCH 1/1] net: thunderx: avoid null pointer dereference
Message-ID: <1463514038-9008-1-git-send-email-xypron.glpk@gmx.de>

In function bgx_lmac_handler only use a member of
lmac after checking it is not null.

Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
 drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index d20539a..3ed2198 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -274,12 +274,14 @@ static void bgx_sgmii_change_link_state(struct lmac *lmac)
 static void bgx_lmac_handler(struct net_device *netdev)
 {
 	struct lmac *lmac = container_of(netdev, struct lmac, netdev);
-	struct phy_device *phydev = lmac->phydev;
+	struct phy_device *phydev;
 	int link_changed = 0;
 
 	if (!lmac)
 		return;
 
+	phydev = lmac->phydev;
+
 	if (!phydev->link && lmac->last_link)
 		link_changed = -1;
 
-- 
2.1.4



From marek at goldelico.com  Tue May 17 12:48:49 2016
From: marek at goldelico.com (Marek Belisko)
Date: Tue, 17 May 2016 21:48:49 +0200
Subject: [PATCH 3/5] ARM: dta: omap3-gta04: Define and use itg3200  irq pin
In-Reply-To: <1463514531-7235-1-git-send-email-marek@goldelico.com>
References: <1463514531-7235-1-git-send-email-marek@goldelico.com>
Message-ID: <1463514531-7235-4-git-send-email-marek@goldelico.com>

From: "H. Nikolaus Schaller" <hns at goldelico.com>

Define pinmux and usage if irq pin + fix irq edge.

Signed-off-by: H. Nikolaus Schaller <hns at goldelico.com>
---
 arch/arm/boot/dts/omap3-gta04.dtsi | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi
index e0520cf..094e5e1 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -256,6 +256,12 @@
 			OMAP3_CORE1_IOPAD(0x213a, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio115 */
 		>;
 	};
+
+	itg3200_pins: pinmux_itg3200_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x20b8, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio56 */
+		>;
+	};
 };
 
 &omap3_pmx_core2 {
@@ -336,8 +342,10 @@
 	itg3200 at 68 {
 		compatible = "invensense,itg3200";
 		reg = <0x68>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&itg3200_pins>;
 		interrupt-parent = <&gpio2>;
-		interrupts = <24 0>; /* GPIO_56 */
+		interrupts = <24 IRQ_TYPE_EDGE_FALLING>; /* GPIO_56 */
 	};
 
 	/* leds */
-- 
2.5.0



From marek at goldelico.com  Tue May 17 12:48:46 2016
From: marek at goldelico.com (Marek Belisko)
Date: Tue, 17 May 2016 21:48:46 +0200
Subject: [PATCH 0/5] ARM: dts: omap3-gta04: Various updates
Message-ID: <1463514531-7235-1-git-send-email-marek@goldelico.com>

Add various improvements for gta04 device (wifi, backlight, irq lines for sensors)

H. Nikolaus Schaller (4):
  ARM: dts: omap3-gta04: Define and use bma180 irq pin
  ARM: dta: omap3-gta04: Define and use itg3200  irq pin
  ARM: dta: omap3-gta04: Define and use hmc5843 irq pin
  ARM: dts: omap3-gat04: Fix wifi handling

Marek Belisko (1):
  ARM: dts: omap3-gta04: Add backlight support

 arch/arm/boot/dts/omap3-gta04.dtsi | 60 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 3 deletions(-)

-- 
2.5.0



From marek at goldelico.com  Tue May 17 12:48:47 2016
From: marek at goldelico.com (Marek Belisko)
Date: Tue, 17 May 2016 21:48:47 +0200
Subject: [PATCH 1/5] ARM: dts: omap3-gta04: Add backlight support
In-Reply-To: <1463514531-7235-1-git-send-email-marek@goldelico.com>
References: <1463514531-7235-1-git-send-email-marek@goldelico.com>
Message-ID: <1463514531-7235-2-git-send-email-marek@goldelico.com>

Define pwm backlight node which is using dmtimer pwm.

Signed-off-by: Marek Belisko <marek at goldelico.com>
---
 arch/arm/boot/dts/omap3-gta04.dtsi | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi
index ab9fb8f..cef8b23 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -100,6 +100,22 @@
 		};
 	};
 
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm11 0 2000000 0>;
+		pwm-names = "backlight";
+		brightness-levels = <0 11 20 30 40 50 60 70 80 90 100>;
+		default-brightness-level = <9>;	/* => 90 */
+		pinctrl-names = "default";
+		pinctrl-0 = <&backlight_pins>;
+	};
+
+	pwm11: dmtimer-pwm at 11 {
+		compatible = "ti,omap-dmtimer-pwm";
+		ti,timers = <&timer11>;
+		#pwm-cells = <3>;
+	};
+
 	hsusb2_phy: hsusb2_phy {
 		compatible = "usb-nop-xceiv";
 		reset-gpios = <&gpio6 14 GPIO_ACTIVE_LOW>;
@@ -190,6 +206,12 @@
 		>;
 	};
 
+	backlight_pins: backlight_pins_pimnux {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x20ba, MUX_MODE3)		/* gpt11/gpio57 */
+		>;
+	};
+
 	dss_dpi_pins: pinmux_dss_dpi_pins {
                pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0)   /* dss_pclk.dss_pclk */
-- 
2.5.0



From marek at goldelico.com  Tue May 17 12:48:50 2016
From: marek at goldelico.com (Marek Belisko)
Date: Tue, 17 May 2016 21:48:50 +0200
Subject: [PATCH 4/5] ARM: dta: omap3-gta04: Define and use hmc5843 irq pin
In-Reply-To: <1463514531-7235-1-git-send-email-marek@goldelico.com>
References: <1463514531-7235-1-git-send-email-marek@goldelico.com>
Message-ID: <1463514531-7235-5-git-send-email-marek@goldelico.com>

From: "H. Nikolaus Schaller" <hns at goldelico.com>

Define pinmux and usage if irq pin.

Signed-off-by: H. Nikolaus Schaller <hns at goldelico.com>
---
 arch/arm/boot/dts/omap3-gta04.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi
index 094e5e1..55b6b88 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -262,6 +262,12 @@
 			OMAP3_CORE1_IOPAD(0x20b8, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio56 */
 		>;
 	};
+
+	hmc5843_pins: pinmux_hmc5843_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2134, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio112 */
+		>;
+	};
 };
 
 &omap3_pmx_core2 {
@@ -389,6 +395,10 @@
 	hmc5843 at 1e {
 		compatible = "honeywell,hmc5883l";
 		reg = <0x1e>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&hmc5843_pins>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <16 IRQ_TYPE_EDGE_FALLING>;	/* gpio112 */
 	};
 
 	/* touchscreen */
-- 
2.5.0



From marek at goldelico.com  Tue May 17 12:48:48 2016
From: marek at goldelico.com (Marek Belisko)
Date: Tue, 17 May 2016 21:48:48 +0200
Subject: [PATCH 2/5] ARM: dts: omap3-gta04: Define and use bma180 irq pin
In-Reply-To: <1463514531-7235-1-git-send-email-marek@goldelico.com>
References: <1463514531-7235-1-git-send-email-marek@goldelico.com>
Message-ID: <1463514531-7235-3-git-send-email-marek@goldelico.com>

From: "H. Nikolaus Schaller" <hns at goldelico.com>

Add pinmux and usage of bma180 irq pin.

Signed-off-by: H. Nikolaus Schaller <hns at goldelico.com>
---
 arch/arm/boot/dts/omap3-gta04.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi
index cef8b23..e0520cf 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -250,6 +250,12 @@
 			OMAP3_CORE1_IOPAD(0x21c6, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda.hdq */
 		>;
 	};
+
+	bma180_pins: pinmux_bma180_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x213a, PIN_INPUT_PULLUP | MUX_MODE4) /* gpio115 */
+		>;
+	};
 };
 
 &omap3_pmx_core2 {
@@ -320,6 +326,8 @@
 	bma180 at 41 {
 		compatible = "bosch,bma180";
 		reg = <0x41>;
+		pinctrl-names = "default";
+		pintcrl-0 = <&bma180_pins>;
 		interrupt-parent = <&gpio4>;
 		interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; /* GPIO_115 */
 	};
-- 
2.5.0



From marek at goldelico.com  Tue May 17 12:48:51 2016
From: marek at goldelico.com (Marek Belisko)
Date: Tue, 17 May 2016 21:48:51 +0200
Subject: [PATCH 5/5] ARM: dts: omap3-gat04: Fix wifi handling
In-Reply-To: <1463514531-7235-1-git-send-email-marek@goldelico.com>
References: <1463514531-7235-1-git-send-email-marek@goldelico.com>
Message-ID: <1463514531-7235-6-git-send-email-marek@goldelico.com>

From: "H. Nikolaus Schaller" <hns at goldelico.com>

Without that change wifi card isn't probed because pwrseq is necessary for
libertas chip.

Signed-off-by: H. Nikolaus Schaller <hns at goldelico.com>
---
 arch/arm/boot/dts/omap3-gta04.dtsi | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi
index 55b6b88..6349257 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -155,6 +155,11 @@
 			};
 		};
 	};
+
+	wifi_pwrseq: wifi_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&tca6507 0 GPIO_ACTIVE_LOW>;	/* W2CBW003 reset through tca6507 */
+	};
 };
 
 &omap3_pmx_core {
@@ -354,8 +359,8 @@
 		interrupts = <24 IRQ_TYPE_EDGE_FALLING>; /* GPIO_56 */
 	};
 
-	/* leds */
-	tca6507 at 45 {
+	/* leds + gpios */
+	tca6507: tca6507 at 45 {
 		compatible = "ti,tca6507";
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -446,6 +451,7 @@
 	bus-width = <4>;
 	ti,non-removable;
 	cap-power-off-card;
+	mmc-pwrseq = <&wifi_pwrseq>;
 };
 
 &mmc3 {
-- 
2.5.0



From f.fainelli at gmail.com  Tue May 17 12:55:08 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Tue, 17 May 2016 12:55:08 -0700
Subject: [PATCH v7 0/3] ASoC: cygnus: Add audio support for Broadcom
 Cygnus SoC
In-Reply-To: <1463514382-20930-1-git-send-email-simran.rai@broadcom.com>
References: <1463514382-20930-1-git-send-email-simran.rai@broadcom.com>
Message-ID: <573B771C.9020905@gmail.com>

On 05/17/2016 12:46 PM, Simran Rai wrote:
> From: Simran <ssimran at lbrmn-ssimran-lnxub64.ric.broadcom.com>

Please fix your git email address and resubmit.
-- 
Florian


From f.fainelli at gmail.com  Tue May 17 12:56:15 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Tue, 17 May 2016 12:56:15 -0700
Subject: [PATCH 1/2] arm64: dts: NS2: Add all of the UARTs
In-Reply-To: <57391E45.8010209@huawei.com>
References: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
 <57341FCE.6050403@huawei.com>
 <CAC3K-4qbkt3DCgd6qurNo3V+++x70bbFC--aunR0DbCTBvBNZg@mail.gmail.com>
 <57353761.5020409@huawei.com>
 <CAC3K-4oXcwR--879sCFR=MCG1Uman7DoGvaHLVXWr+0QH2WeJg@mail.gmail.com>
 <57391E45.8010209@huawei.com>
Message-ID: <573B775F.4060503@gmail.com>

On 05/15/2016 06:11 PM, Kefeng Wang wrote:
>> I can confirm that with your change and the change to the bootargs you describe above, it works as desired.  Was your change already accepted?
>>
> 
> Great, thanks a lot. it is still being reviewing for now and waiting for response for now.

Then I would be inclined to take Jon's patch as-is, and follow up with
an additional patch to the NS2 DTS once yours lands in.
-- 
Florian


From damien.riegel at savoirfairelinux.com  Tue May 17 13:16:29 2016
From: damien.riegel at savoirfairelinux.com (Damien Riegel)
Date: Tue, 17 May 2016 16:16:29 -0400
Subject: [PATCH 1/2] ARM: dts: TS-4800: add FPGA's IRQ controller support
Message-ID: <1463516190-10606-1-git-send-email-damien.riegel@savoirfairelinux.com>

Enable FPGA's IRQ controller. It is in charge of dispatching interrupts
generated by IPs in the FPGA. The SoC is notified that an interrupt
occurred through a GPIO.

Signed-off-by: Damien Riegel <damien.riegel at savoirfairelinux.com>
---
 arch/arm/boot/dts/imx51-ts4800.dts | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm/boot/dts/imx51-ts4800.dts b/arch/arm/boot/dts/imx51-ts4800.dts
index 0ff76a1..2c89988 100644
--- a/arch/arm/boot/dts/imx51-ts4800.dts
+++ b/arch/arm/boot/dts/imx51-ts4800.dts
@@ -149,6 +149,19 @@
 		#size-cells = <1>;
 		ranges = <0 0 0 0x1d000>;
 
+		fpga_irqc: fpga_irqc at 0,15000 {
+			compatible = "technologic,ts4800-irqc";
+			reg = <0x15000 0x1000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_interrupt_fpga>;
+
+			interrupt-parent = <&gpio2>;
+			interrupts= <9 IRQ_TYPE_LEVEL_HIGH>;
+
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
 		syscon: syscon at b0010000 {
 			compatible = "syscon", "simple-mfd";
 			reg = <0x10000 0x3d>;
@@ -228,6 +241,12 @@
 		>;
 	};
 
+	pinctrl_interrupt_fpga: fpgaicgrp {
+		fsl,pins = <
+			MX51_PAD_EIM_D27__GPIO2_9		0xe5
+		>;
+	};
+
 	pinctrl_lcd: lcdgrp {
 		fsl,pins = <
 			MX51_PAD_DISP1_DAT0__DISP1_DAT0		0x5
-- 
2.5.0



From damien.riegel at savoirfairelinux.com  Tue May 17 13:16:30 2016
From: damien.riegel at savoirfairelinux.com (Damien Riegel)
Date: Tue, 17 May 2016 16:16:30 -0400
Subject: [PATCH 2/2] ARM: dts: TS-4800: add CAN support
In-Reply-To: <1463516190-10606-1-git-send-email-damien.riegel@savoirfairelinux.com>
References: <1463516190-10606-1-git-send-email-damien.riegel@savoirfairelinux.com>
Message-ID: <1463516190-10606-2-git-send-email-damien.riegel@savoirfairelinux.com>

This enables support for the CAN controller located in the FPGA.

Signed-off-by: Damien Riegel <damien.riegel at savoirfairelinux.com>
---
 arch/arm/boot/dts/imx51-ts4800.dts | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/imx51-ts4800.dts b/arch/arm/boot/dts/imx51-ts4800.dts
index 2c89988..41be82e 100644
--- a/arch/arm/boot/dts/imx51-ts4800.dts
+++ b/arch/arm/boot/dts/imx51-ts4800.dts
@@ -149,6 +149,16 @@
 		#size-cells = <1>;
 		ranges = <0 0 0 0x1d000>;
 
+		can at 0,1a000 {
+			compatible = "technologic,sja1000";
+			reg = <0x1a000 0x00000100>;
+			interrupt-parent = <&fpga_irqc>;
+			interrupts = <1>;
+			reg-io-width = <2>;
+			nxp,tx-output-config = <0x06>;
+			nxp,external-clock-frequency = <24000000>;
+		};
+
 		fpga_irqc: fpga_irqc at 0,15000 {
 			compatible = "technologic,ts4800-irqc";
 			reg = <0x15000 0x1000>;
-- 
2.5.0



From ddaney at caviumnetworks.com  Tue May 17 13:21:13 2016
From: ddaney at caviumnetworks.com (David Daney)
Date: Tue, 17 May 2016 13:21:13 -0700
Subject: [PATCH 1/1] net: thunderx: avoid null pointer dereference
In-Reply-To: <1463514038-9008-1-git-send-email-xypron.glpk@gmx.de>
References: <1463514038-9008-1-git-send-email-xypron.glpk@gmx.de>
Message-ID: <573B7D39.9050305@caviumnetworks.com>

On 05/17/2016 12:40 PM, Heinrich Schuchardt wrote:
> In function bgx_lmac_handler only use a member of
> lmac after checking it is not null.
>

Were you seeing and actual OOPs, or is this only a theoretical problem 
flagged by some sort of static code checker?

> Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>

In any event, it seems sane to make this change, so:

Acked-by: David Daney <david.daney at cavium.com>


> ---
>   drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 4 +++-
>   1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
> index d20539a..3ed2198 100644
> --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
> +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
> @@ -274,12 +274,14 @@ static void bgx_sgmii_change_link_state(struct lmac *lmac)
>   static void bgx_lmac_handler(struct net_device *netdev)
>   {
>   	struct lmac *lmac = container_of(netdev, struct lmac, netdev);
> -	struct phy_device *phydev = lmac->phydev;
> +	struct phy_device *phydev;
>   	int link_changed = 0;
>
>   	if (!lmac)
>   		return;
>
> +	phydev = lmac->phydev;
> +
>   	if (!phydev->link && lmac->last_link)
>   		link_changed = -1;
>
>



From cov at codeaurora.org  Tue May 17 13:36:06 2016
From: cov at codeaurora.org (Christopher Covington)
Date: Tue, 17 May 2016 16:36:06 -0400
Subject: [PATCH v2 2/2] arm64/efi: esrt: add missing call to
 efi_esrt_init()
In-Reply-To: <56C385D3.3090308@codeaurora.org>
References: <1455535953-5056-1-git-send-email-ard.biesheuvel@linaro.org>
 <1455535953-5056-3-git-send-email-ard.biesheuvel@linaro.org>
 <56C385D3.3090308@codeaurora.org>
Message-ID: <573B80B6.2010108@codeaurora.org>

Hi Ard,

On 02/16/2016 03:25 PM, Baicar, Tyler wrote:
> On 2/15/2016 4:32 AM, Ard Biesheuvel wrote:
>> ESRT support is built by default for all architectures that define
>> CONFIG_EFI. However, this support was not wired up yet for ARM/arm64,
>> since efi_esrt_init() was never called. So add the missing call.
>>
>> Since efi_esrt_init() uses efi_mem_desc_lookup(), which in turn relies
>> on efi.memmap having been assigned and populated completetely, add the
>> missing assignments of efi.memmap and efi.memmap->nr_map.
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
>> ---
>>   drivers/firmware/efi/arm-init.c | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/drivers/firmware/efi/arm-init.c
>> b/drivers/firmware/efi/arm-init.c
>> index 9e15d571b53c..5c5e799bdb50 100644
>> --- a/drivers/firmware/efi/arm-init.c
>> +++ b/drivers/firmware/efi/arm-init.c
>> @@ -197,10 +197,13 @@ void __init efi_init(void)
>>       memmap.map_end = memmap.map + params.mmap_size;
>>       memmap.desc_size = params.desc_size;
>>       memmap.desc_version = params.desc_ver;
>> +    memmap.nr_map = params.mmap_size / params.desc_size;
>> +    efi.memmap = &memmap;
>>         if (uefi_init() < 0)
>>           return;
>>   +    efi_esrt_init();
> This call to efi_esrt_init() is failing because efi.flags does not have
> EFI_MEMMAP set. This flag gets set at the end of reserve_regions(). I
> tested moving the set_bit() call from reserve_regions() to just before
> efi_esrt_init() and also tested moving efi_esrt_init() to just after
> reserve_regions(). Both of these options worked.
>>       reserve_regions();
>>       early_memunmap(memmap.map, params.mmap_size);
>>       memblock_mark_nomap(params.mmap & PAGE_MASK,

Do you expect to respin this patch in the near future?

Thanks,
Cov

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


From heiko at sntech.de  Tue May 17 14:10:51 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue, 17 May 2016 23:10:51 +0200
Subject: [PATCH 1/2] clk: rockchip: mark rk3399 GIC clocks as critical
In-Reply-To: <1463164937-91089-1-git-send-email-briannorris@chromium.org>
References: <1463164937-91089-1-git-send-email-briannorris@chromium.org>
Message-ID: <2111538.t2M7m4hXj2@phil>

Am Freitag, 13. Mai 2016, 11:42:16 schrieb Brian Norris:
> We never want to kill the GIC.
> 
> Noticed when making other clock fixups, and seeing the newly-constructed
> clock tree try to disable cpll, where we had this parent structure:
> 
>   aclk_gic <------\
> 
>                   |--- aclk_gic_pre <-- cpll <-- pll_cpll
> 
>   aclk_gic_noc <--/
> 
> Signed-off-by: Brian Norris <briannorris at chromium.org>

applied both patches to my clk-fixes branch with Dougs review-tags.


Thanks
Heiko


From xypron.glpk at gmx.de  Tue May 17 14:37:11 2016
From: xypron.glpk at gmx.de (Heinrich Schuchardt)
Date: Tue, 17 May 2016 23:37:11 +0200
Subject: [PATCH 1/1] net: thunderx: avoid null pointer dereference
In-Reply-To: <573B7D39.9050305@caviumnetworks.com>
References: <1463514038-9008-1-git-send-email-xypron.glpk@gmx.de>
 <573B7D39.9050305@caviumnetworks.com>
Message-ID: <573B8F07.6080600@gmx.de>



On 05/17/2016 10:21 PM, David Daney wrote:
> On 05/17/2016 12:40 PM, Heinrich Schuchardt wrote:
>> In function bgx_lmac_handler only use a member of
>> lmac after checking it is not null.
>>
> 
> Were you seeing and actual OOPs, or is this only a theoretical problem
> flagged by some sort of static code checker?

Cppcheck identified the code inconsistency.

If the struct netdev * parameter cannot be NULL, you could eliminate the
check.

Other drivers do no have check against a NULL parameter in the
adjust_link handler function (e.g. bgmac_adjust_link,
pxa168_eth_adjust_link).

Best regards

Heinrich

> 
>> Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
> 
> In any event, it seems sane to make this change, so:
> 
> Acked-by: David Daney <david.daney at cavium.com>
> 
> 
>> ---
>>   drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 4 +++-
>>   1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
>> b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
>> index d20539a..3ed2198 100644
>> --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
>> +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
>> @@ -274,12 +274,14 @@ static void bgx_sgmii_change_link_state(struct
>> lmac *lmac)
>>   static void bgx_lmac_handler(struct net_device *netdev)
>>   {
>>       struct lmac *lmac = container_of(netdev, struct lmac, netdev);
>> -    struct phy_device *phydev = lmac->phydev;
>> +    struct phy_device *phydev;
>>       int link_changed = 0;
>>
>>       if (!lmac)
>>           return;
>>
>> +    phydev = lmac->phydev;
>> +
>>       if (!phydev->link && lmac->last_link)
>>           link_changed = -1;
>>
>>
> 
> 


From heiko at sntech.de  Tue May 17 14:56:44 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue, 17 May 2016 23:56:44 +0200
Subject: [PATCH 1/2] Revert "clk: rockchip: reset init state before mmc
 card initialization"
In-Reply-To: <1463076197-15900-1-git-send-email-dianders@chromium.org>
References: <1463076197-15900-1-git-send-email-dianders@chromium.org>
Message-ID: <1546506.kPA2J5E1Tb@phil>

Am Donnerstag, 12. Mai 2016, 11:03:16 schrieb Douglas Anderson:
> This reverts commit 7a03fe6f48f3 ("clk: rockchip: reset init state
> before mmc card initialization").
> 
> Though not totally obvious from the commit message nor from the source
> code, that commit appears to be trying to reset the "_drv" MMC clocks to
> 90 degrees (note that the "_sample" MMC clocks have a shift of 0 so are
> not touched).
> 
> The major problem here is that it doesn't properly reset things.  The
> phase is a two bit field and the commit only touches one of the two
> bits.  Thus the commit had the following affect:
> - phase   0  => phase  90
> - phase  90  => phase  90
> - phase 180  => phase 270
> - phase 270  => phase 270
> 
> Things get even weirder if you happen to have a bootloader that was
> actually using delay elements (should be no reason to, but you never
> know), since those are additional bits that weren't touched by the
> original patch.
> 
> This is unlikely to be what we actually want.  Checking on rk3288-veyron
> devices, I can see that the bootloader leaves these clocks as:
> - emmc:  phase 180
> - sdmmc: phase 90
> - sdio0: phase 90
> 
> Thus on rk3288-veyron devices the commit we're reverting had the effect
> of changing the eMMC clock to phase 270.  This probably explains the
> scattered reports I've heard of eMMC devices not working on some veyron
> devices when using the upstream kernel.
> 
> The original commit was presumably made because previously the kernel
> didn't touch the "_drv" phase at all and relied on whatever value was
> there when the kernel started.  If someone was using a bootloader that
> touched the "_drv" phase then, indeed, we should have code in the kernel
> to fix that.  ...and also, to get ideal timings, we should also have the
> kernel change the phase depending on the speed mode.  In fact, that's
> the subject of a recent patch I posted at
> <https://patchwork.kernel.org/patch/9075141/>.
> 
> Ideally, we should take both the patch posted to dw_mmc and this
> revert.  Since those will likely go through different trees, here I
> describe behavior with the combos:
> 
> 1. Just this revert: likely will fix rk3288-veyron eMMC on some devices
>    + other cases; might break someone with a strange bootloader that
>    sets the phase to 0 or one that uses delay elements (pretty
>    unpredicable what would happen in that case).
> 2. Just dw_mmc patch: fixes everyone.  Effectly the dw_mmc patch will
>    totally override the broken patch and fix everything.
> 3. Both patches: fixes everyone.  Once dw_mmc is initting properly then
>    any defaults from the clock code doesn't mattery.
> 
> Fixes: 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card
> initialization") Signed-off-by: Douglas Anderson <dianders at chromium.org>

I've tested this revert myself on rk3288-veyron-jerry and rk3288-firefly 
[everything still works] and have put it temporarily into my clk-fixes branch 
to hopefully get a report from kernelci for rk3288-rock2, but may drop it 
again if necessary.


Heiko


From arnd at arndb.de  Tue May 17 15:24:54 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 00:24:54 +0200
Subject: [GIT PULL 6/7] ARM: SoC defconfig updates for v4.7
In-Reply-To: <8749147.ztcb6kVhye@wuerfel>
References: <8749147.ztcb6kVhye@wuerfel>
Message-ID: <2717085.7it4MHH99U@wuerfel>

The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:

  Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/armsoc-defconfig

for you to fetch changes up to 0ef659a30055e5ec914b51f5294789ea2a92b08c:

  ARM: aspeed: adapt defconfigs for new CONFIG_PRINTK_TIME (2016-05-11 14:11:13 +0200)

----------------------------------------------------------------
ARM: SoC defconfig updates for v4.7

As usual, a bunch of commits, mostly adding drivers and other options to
defconfigs.

We are adding three new defconfig files for the newly added 32-bit
machines (aspeed and mps2), the rest is mainly housekeeping.

The changes outside of arch/arm/config/ are for a Kconfig symbol
that got renamed.

----------------------------------------------------------------
Arnd Bergmann (14):
      Merge tag 'samsung-defconfig-4.7' of git://git.kernel.org/.../krzk/linux into next/defconfig
      Merge tag 'mvebu-defconfig-4.7-1' of git://git.infradead.org/linux-mvebu into next/defconfig
      Merge tag 'arm-soc/for-4.7/defconfig' of http://github.com/Broadcom/stblinux into next/defconfig
      Merge tag 'keystone_config_for_4.7' of git://git.kernel.org/.../ssantosh/linux-keystone into next/defconfig
      Merge tag 'renesas-pci-defconfig-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/defconfig
      Merge tag 'lpc32xx-defconfig-4.7' of git://github.com/vzapolskiy/linux-lpc32xx into next/defconfig
      Merge tag 'omap-for-v4.7/defconfig-signed' of git://git.kernel.org/.../tmlind/linux-omap into next/defconfig
      Merge tag 'davinci-for-v4.7/defconfig' of git://git.kernel.org/.../nsekhar/linux-davinci into next/defconfig
      Merge tag 'tegra-for-4.7-defconfig' of git://git.kernel.org/.../tegra/linux into next/defconfig
      Merge tag 'imx-defconfig-4.7' of git://git.kernel.org/.../shawnguo/linux into next/defconfig
      Merge tag 'ux500-defconfig-armsoc2' of git://git.kernel.org/.../linusw/linux-stericsson into next/defconfig
      Merge tag 'aspeed-for-4.7-defconfig' of https://github.com/shenki/linux into next/defconfig
      Merge tag 'at91-defconfig2' of git://git.kernel.org/.../nferre/linux-at91 into next/defconfig
      ARM: aspeed: adapt defconfigs for new CONFIG_PRINTK_TIME

Boris Brezillon (1):
      ARM: multi_v7_defconfig: add HLCDC drivers as modules

Eric Anholt (7):
      ARM: multi_v7_defconfig: Add more BCM2835 support
      ARM: multi_v7_defconfig: Switch BCM2835 to sdhci-iproc.c for MMC
      ARM: multi_v7_defconfig: Build in DWC2 USB support
      ARM: bcm2835: Switch BCM2835 to sdhci-iproc.c for MMC
      ARM: bcm2835: Enable CONFIG_PM.
      ARM: bcm2835: Enable the VC4 graphics driver in the defconfig
      ARM: bcm2835: Enable NFS root support.

Florian Fainelli (1):
      Merge tag 'bcm2835-defconfig-next-2016-04-20' into defconfig/next

Gary Bisson (3):
      ARM: imx_v6_v7_defconfig: add FT5x06 and TSC2004 touch support
      ARM: imx_v6_v7_defconfig: add CONFIG_I2C_MUX_GPIO
      ARM: imx_v6_v7_defconfig: add CONFIG_RTC_DRV_M41T80

Heiko Stuebner (2):
      ARM: multi_v7_defconfig: Enable Rockchip displayport phy
      ARM: multi_v7_defconfig: Enable new Rockchip display-controller drivers

Jan Luebbe (2):
      ARM: multi_v5_defconfig: Enable support for MX21/MX27
      ARM: multi_v5_defconfig: Enable recommended options for systemd

Javier Martinez Canillas (3):
      ARM: exynos_defconfig: Enable CPUFreq governors as modules
      ARM: multi_v7_defconfig: Enable CPUFreq governors as modules
      ARM: omap2plus_defconfig: Fix warning due invalid RXKAD symbol value

Joel Stanley (2):
      arm/configs/multi_v5: Add Aspeed ast2400
      arm/configs: Add Aspeed defconfig

Keerthy (1):
      ARM: configs: keystone: Add CPU Hotplug related options

Kevin Hilman (1):
      ARM: davinci_all_defconfig: enable SPI and NOR as modules

Krzysztof Kozlowski (1):
      ARM: exynos_defconfig: Enable Trats2 audio codec, touchscreen and sensors

Lee Jones (5):
      ARM: multi_v7_defconfig: Enable ST's PWM driver
      ARM: multi_v7_defconfig: Enable ST's Power Reset driver
      ARM: multi_v7_defconfig: Enable support for PWM Regulators
      ARM: multi_v7_defconfig: Enable ST's HW Random Number Generator
      ARM: multi_v7_defconfig: Remove unused Kconfig option MACH_UX500_DT

Linus Walleij (2):
      ARM: u8500_defconfig: remove staging from defconfig
      ARM: u8500_defconfig: update sensor config

Lokesh Vutla (1):
      ARM: omap2plus_defconfig: Enable GPIO_TPIC2810

Marcel Ziswiler (2):
      ARM: imx_v6_v7_defconfig: add CONFIG_I2C_GPIO
      ARM: imx_v6_v7_defconfig: add CONFIG_MICREL_PHY

Marek Vasut (1):
      ARM: at91: sama5: Update defconfig

Masahiro Yamada (1):
      ARM: multi_v7_defconfig: enable Denali NAND controller

Nicolas Ferre (8):
      ARM: at91/defconfig: add the HDMA controller to sama5_defconfig
      ARM: at91/defconfig: add HLCDC driver to sama5_defconfig
      ARM: at91/defconfig: add PDMIC driver to sama5_defconfig
      ARM: multi_v7_defconfig: add Atmel watchdog timers
      ARM: multi_v7_defconfig: add Atmel ISI (Image Sensor Interface) driver
      ARM: multi_v7_defconfig: add the Atmel Audio microphone interface PDMIC
      ARM: multi_v7_defconfig: add the Atmel sama5d2-compatible ADC driver
      ARM: at91/defconfig: sama5: add CONFIG_FHANDLE

Nishanth Menon (1):
      ARM: omap2plus_defconfig: Enable DP83867 support

Olof Johansson (2):
      Merge tag 'renesas-defconfig-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/defconfig
      Merge tag 'sti-defconfig-for-v4.7-1' of git://git.kernel.org/.../mcoquelin/sti into next/defconfig

Romain Perier (3):
      ARM: mvebu_v7_defconfig: Enabling the new Marvell's cryptographic engine driver
      ARM: multi_v7_defconfig: Enabling the new Marvell's cryptographic engine driver
      ARM: mvebu_v5_defconfig: Switching to the new Marvell's cryptographic engine driver

Sekhar Nori (2):
      ARM: davinci_all_defconfig: enable GPIO_SYSFS
      ARM: davinci_all_defconfig: support systemd

Simon Horman (1):
      PCI: rcar-pcie: Remove Gen2 designation from Kconfig

Thierry Reding (2):
      ARM: tegra: Enable XUSB controller in defconfig
      ARM: multi_v7: Enable Tegra XUSB controller in defconfig

Thomas Petazzoni (1):
      MAINTAINERS: attach arch/arm/configs/mvebu_*_defconfig to relevant maintainers

Tony Lindgren (3):
      ARM: omap2plus_defconfig: Update with make savedefconfig
      ARM: omap2plus_defconfig: Enable twl6030 USB phy as loadable module
      ARM: omap2plus_defconfig: Enable PWM and ir-rx51 as loadable modules

Vladimir Murzin (1):
      ARM: configs: add MPS2 defconfig

Vladimir Zapolskiy (2):
      ARM: LPC32xx: defconfig update
      ARM: LPC32xx: add PL175 memory controller driver to defconfig

Wolfram Sang (2):
      ARM: multi_v7_defconfig: enable I2C demultiplexer and slave eeprom
      ARM: shmobile: defconfig: enable I2C demultiplexer and slave eeprom

Yegor Yefremov (1):
      ARM: omap2plus_defconfig: Enable MDIO Bus/PHY emulation support

 MAINTAINERS                            |   2 +-
 arch/arm/configs/aspeed_g4_defconfig   |  86 ++++++++++++++++++++++++++
 arch/arm/configs/aspeed_g5_defconfig   |  88 ++++++++++++++++++++++++++
 arch/arm/configs/bcm2835_defconfig     |  11 ++--
 arch/arm/configs/davinci_all_defconfig |   7 ++-
 arch/arm/configs/exynos_defconfig      |  11 ++++
 arch/arm/configs/imx_v6_v7_defconfig   |   6 ++
 arch/arm/configs/keystone_defconfig    |   2 +
 arch/arm/configs/lpc32xx_defconfig     |  29 ++++-----
 arch/arm/configs/mps2_defconfig        | 109 +++++++++++++++++++++++++++++++++
 arch/arm/configs/multi_v5_defconfig    |  29 +++++++--
 arch/arm/configs/multi_v7_defconfig    |  37 +++++++++--
 arch/arm/configs/mvebu_v5_defconfig    |   2 +-
 arch/arm/configs/mvebu_v7_defconfig    |   1 +
 arch/arm/configs/omap2plus_defconfig   |  66 +++++++++-----------
 arch/arm/configs/sama5_defconfig       |  13 +++-
 arch/arm/configs/shmobile_defconfig    |   5 +-
 arch/arm/configs/tegra_defconfig       |   2 +
 arch/arm/configs/u8500_defconfig       |   5 +-
 arch/arm64/configs/defconfig           |   2 +-
 drivers/pci/host/Kconfig               |   4 +-
 drivers/pci/host/Makefile              |   2 +-
 22 files changed, 437 insertions(+), 82 deletions(-)
 create mode 100644 arch/arm/configs/aspeed_g4_defconfig
 create mode 100644 arch/arm/configs/aspeed_g5_defconfig
 create mode 100644 arch/arm/configs/mps2_defconfig



From arnd at arndb.de  Tue May 17 15:26:08 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 00:26:08 +0200
Subject: [GIT PULL 7/7] ARM: SoC driver updates for v4.7
In-Reply-To: <8749147.ztcb6kVhye@wuerfel>
References: <8749147.ztcb6kVhye@wuerfel>
Message-ID: <2633732.4xlcotETON@wuerfel>

The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:

  Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/armsoc-drivers

for you to fetch changes up to 5420f9fd159761b88978c312c3b350546f8615bb:

  arm-ccn: Enable building as module (2016-05-09 16:36:03 +0200)

----------------------------------------------------------------
ARM: SoC driver updates for v4.7

Driver updates for ARM SoCs, these contain various things that touch
the drivers/ directory but got merged through arm-soc for practical
reasons. For the most part, this is now related to power management
controllers, which have not yet been abstracted into a separate
subsystem, and typically require some code in drivers/soc or arch/arm
to control the power domains.

Another large chunk here is a rework of the NVIDIA Tegra USB3.0
support, which was surprisingly tricky and took a long time to
get done.

Finally, reset controller handling as always gets merged through here
as well.

----------------------------------------------------------------
Andrew Bresticker (1):
      clk: tegra: Add interface to enable hardware control of SATA/XUSB PLLs

Andy Gross (1):
      Merge tag 'qcom-soc-for-4.7' into soc-for-4.7-p2

Arnd Bergmann (16):
      Merge tag 'versatile-flash-for-arm-soc' of git://git.kernel.org/.../linusw/linux-integrator into next/drivers
      Merge tag 'tegra-for-4.7-soc' of git://git.kernel.org/.../tegra/linux into next/drivers
      Merge tag 'arm-soc/for-4.7/drivers' of http://github.com/Broadcom/stblinux into next/drivers
      Merge tag 'qcom-soc-for-4.7-2' of git://git.kernel.org/.../agross/linux into next/drivers
      soc: brcmstb: select SOC_BUS
      physmap_of: ensure versatile code is reachable
      drivers: firmware: psci: make two helper functions inline
      Merge tag 'renesas-rcar-sysc2-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/drivers
      Merge tag 'samsung-drivers-exynos-srom-4.7' of git://git.kernel.org/.../krzk/linux into next/drivers
      Merge tag 'v4.7-rockchip-drivers-2' of git://git.kernel.org/.../mmind/linux-rockchip into next/drivers
      Merge tag 'tegra-for-4.7-phy' of git://git.kernel.org/.../tegra/linux into next/drivers
      Merge tag 'tegra-for-4.7-pci' of git://git.kernel.org/.../tegra/linux into next/drivers
      Merge tag 'tegra-for-4.7-xhci' of git://git.kernel.org/.../tegra/linux into next/drivers
      Merge tag 'tegra-for-4.7-genpd' of git://git.kernel.org/.../tegra/linux into next/drivers
      Merge tag 'v4.6-next-soc' of https://github.com/mbgg/linux-mediatek into next/drivers
      Merge tag 'reset-for-4.7-2' of git://git.pengutronix.de/git/pza/linux into next/drivers

Bjorn Andersson (8):
      soc: qcom: smem_state: Add stubs for disabled smem_state
      soc: qcom: smd: Introduce callback setter
      soc: qcom: smd: Split discovery and state change work
      soc: qcom: smd: Refactor channel open and close handling
      soc: qcom: smd: Support multiple channels per sdev
      soc: qcom: smd: Support opening additional channels
      soc: qcom: smem: Use write-combine remap for SMEM
      soc: qcom: smd: Make callback pass channel reference

Daniel Lezcano (1):
      reset: Add missing function stub for device_reset

Elaine Zhang (8):
      soc: rockchip: power-domain: make idle handling optional
      soc: rockchip: power-domain: allow domains only handling idle requests
      soc: rockchip: power-domain: add support for sub-power domains
      dt-bindings: add power-domain header for RK3399 SoCs
      dt-bindings: add binding for rk3399 power domains
      soc: rockchip: power-domain: Modify power domain driver for rk3399
      dt-bindings: modify document of Rockchip power domains
      soc: rockchip: power-domain: support qos save and restore

Florian Fainelli (2):
      bus: brcmstb_gisb: Rework dependencies
      soc: brcmstb: Unmap sun_top_ctrl_base on errors

Geert Uytterhoeven (24):
      clk: renesas: mstp: Drop check for CONFIG_PM_GENERIC_DOMAINS_OF
      clk: renesas: cpg-mssr: Drop check for CONFIG_PM_GENERIC_DOMAINS_OF
      clk: renesas: mstp: Clarify cpg_mstp_{at,de}tach_dev() domain parameter
      PM / Domains: Add DT bindings for the R-Car System Controller
      soc: renesas: Add r8a7779 SYSC PM Domain Binding Definitions
      soc: renesas: Add r8a7790 SYSC PM Domain Binding Definitions
      soc: renesas: Add r8a7791 SYSC PM Domain Binding Definitions
      soc: renesas: Add r8a7793 SYSC PM Domain Binding Definitions
      soc: renesas: Add r8a7794 SYSC PM Domain Binding Definitions
      soc: renesas: Add r8a7795 SYSC PM Domain Binding Definitions
      clk: renesas: Provide Kconfig symbols for CPG/MSSR and CPG/MSTP support
      clk: renesas: mstp: Provide dummy attach/detach_dev callbacks
      clk: renesas: cpg-mssr: Export cpg_mssr_{at,de}tach_dev()
      soc: renesas: Move pm-rcar to drivers/soc/renesas/rcar-sysc
      soc: renesas: rcar-sysc: Improve rcar_sysc_power() debug info
      soc: renesas: rcar-sysc: Add DT support for SYSC PM domains
      soc: renesas: rcar-sysc: Make rcar_sysc_power_is_off() static
      soc: renesas: rcar-sysc: Enable Clock Domain for I/O devices
      soc: renesas: rcar-sysc: Add support for R-Car H1 power areas
      soc: renesas: rcar-sysc: Add support for R-Car H2 power areas
      soc: renesas: rcar-sysc: Add support for R-Car M2-W power areas
      soc: renesas: rcar-sysc: Add support for R-Car M2-N power areas
      soc: renesas: rcar-sysc: Add support for R-Car E2 power areas
      soc: renesas: rcar-sysc: Add support for R-Car H3 power areas

Hans de Goede (3):
      reset: Make [of_]reset_control_get[_foo] functions wrappers
      reset: Share struct reset_control between reset_control_get calls
      reset: Add support for shared reset controls

Heiko Stuebner (1):
      Merge branch 'v4.7-shared/pdids' into v4.7-armsoc/drivers

Jisheng Zhang (2):
      drivers: firmware: psci: drop duplicate const from psci_of_match
      drivers: firmware: psci: make two helper functions static

Joachim Eastwood (1):
      reset: lpc18xx: get rid of global variables for restart notifier

John Crispin (11):
      soc: mediatek: PMIC wrap: don't duplicate the wrapper data
      soc: mediatek: PMIC wrap: add wrapper callbacks for init_reg_clock
      soc: mediatek: PMIC wrap: split SoC specific init into callback
      soc: mediatek: PMIC wrap: WRAP_INT_EN needs a different bitmask for MT2701/7623
      soc: mediatek: PMIC wrap: SPI_WRITE needs a different bitmask for MT2701/7623
      soc: mediatek: PMIC wrap: move wdt_src into the pmic_wrapper_type struct
      soc: mediatek: PMIC wrap: remove pwrap_is_mt8135() and pwrap_is_mt8173()
      soc: mediatek: PMIC wrap: add a slave specific struct
      soc: mediatek: PMIC wrap: add mt6323 slave support
      soc: mediatek: PMIC wrap: add MT2701/7623 support
      ARM: mediatek: enable gpt6 on boot up to make arch timer work on mt7623

Jon Hunter (16):
      soc/tegra: pmc: Add missing structure members to kernel-doc
      soc/tegra: pmc: Fix sparse warning for tegra_pmc_init_tsense_reset()
      soc/tegra: pmc: Remove debugfs entry on probe failure
      soc/tegra: pmc: Remove non-existing power partitions for Tegra210
      soc/tegra: pmc: Remove non-existing L2 partition for Tegra124
      soc/tegra: pmc: Restore base address on probe failure
      soc/tegra: pmc: Protect public functions from potential race conditions
      soc/tegra: pmc: Change powergate and rail IDs to be an unsigned type
      soc/tegra: pmc: Fix testing of powergate state
      soc/tegra: pmc: Fix verification of valid partitions
      soc/tegra: pmc: Remove additional check for a valid partition
      soc/tegra: pmc: Ensure GPU partition can be toggled on/off by PMC
      soc/tegra: pmc: Wait for powergate state to change
      dt-bindings: Update NVIDIA PMC for Tegra
      dt-bindings: Add power domain info for NVIDIA PMC
      soc/tegra: pmc: Add generic PM domain support

Justin Chen (1):
      soc: brcmstb: add SoC driver to brcmstb

Krzysztof Kozlowski (1):
      Merge tag 'samsung-dt-exynos-srom-fixup-4.7' into for-v4.7/drivers-memory-exynos-srom

Lina Iyer (1):
      drivers: qcom: spm: avoid module usage in non-modular SPM driver

Linus Walleij (4):
      mtd: physmap_of: add a hook for Versatile write protection
      mtd: augment the "arm,versatile-flash" bindings
      ARM: versatile: move flash registration to the device tree
      ARM: integrator: move flash registration to device tree

Neil Armstrong (2):
      reset: Add Oxford Semiconductor Reset Controller driver
      dt-bindings: Add Oxford Semiconductor Reset Controller bindings

Olof Johansson (4):
      Merge tag 'qcom-soc-for-4.7' of git://git.kernel.org/.../agross/linux into next/drivers
      Merge tag 'reset-for-4.7' of git://git.pengutronix.de/git/pza/linux into next/drivers
      Merge tag 'renesas-simple-pm-bus-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/drivers
      Merge tag 'v4.7-rockchip-drivers-1' of git://git.kernel.org/.../mmind/linux-rockchip into next/drivers

Pankaj Dubey (5):
      ARM: dts: change SROM node compatible from generic to model specific
      dt-bindings: EXYNOS: Add exynos-srom device tree binding
      memory: Add support for Exynos SROM driver
      MAINTAINERS: Add maintainers entry for drivers/memory/samsung
      ARM: EXYNOS: Remove SROM related register settings from mach-exynos

Pavel Fedin (1):
      memory: samsung: exynos-srom: Add support for bank configuration

Shawn Lin (1):
      soc: rockchip: power-domain: check the existing of regmap

Simon Horman (2):
      bus: simple-pm-bus: Use ARCH_RENESAS
      Merge tag 'clk-renesas-for-v4.7-tag2' of git://git.kernel.org/.../geert/renesas-drivers into rcar-sysc-for-v4.7

Srinivas Kandagatla (2):
      MAINTAINERS: add qcom i2c and spi drivers to list
      MAINTAINERS: add qcom clocks to the maintainers list

Suzuki K Poulose (1):
      arm-ccn: Enable building as module

Thierry Reding (15):
      Merge branch 'for-4.7/soc' into for-4.7/genpd
      Merge branch 'for-4.7/clk' into for-4.7/phy
      phy: core: Allow children node to be overridden
      dt-bindings: phy: Add NVIDIA Tegra XUSB pad controller binding
      dt-bindings: phy: tegra-xusb-padctl: Add Tegra210 support
      phy: Add Tegra XUSB pad controller support
      phy: tegra: Add Tegra210 support
      Merge branch 'for-4.7/phy' into for-4.7/pci
      dt-bindings: pci: tegra: Update for per-lane PHYs
      PCI: tegra: Support per-lane PHYs
      Merge branch 'for-4.7/phy' into for-4.7/xhci
      dt-bindings: usb: Add NVIDIA Tegra XUSB controller binding
      dt-bindings: usb: xhci-tegra: Add Tegra210 XUSB controller support
      usb: xhci: Add NVIDIA Tegra XUSB controller driver
      usb: xhci: tegra: Add Tegra210 support

Ulrich Hecht (1):
      clk: renesas: r8a7795: add PWM clock

Wolfram Sang (5):
      clk: renesas: r8a7795: make SD clk definition specific for GEN3
      clk: renesas: cpg-mssr: add generic support for read-only DIV6 clocks
      clk: renesas: r8a7795: add OSC and RINT clocks
      clk: renesas: r8a7795: add R clk
      clk: renesas: r8a7795: add RWDT clock

 .../bindings/arm/tegra/nvidia,tegra20-pmc.txt      |   92 +-
 .../bindings/memory-controllers/exynos-srom.txt    |   79 +
 .../devicetree/bindings/mtd/arm-versatile.txt      |   20 +-
 .../bindings/pci/nvidia,tegra20-pcie.txt           |  224 ++-
 .../bindings/phy/nvidia,tegra124-xusb-padctl.txt   |  733 +++++++
 .../pinctrl/nvidia,tegra124-xusb-padctl.txt        |    6 +
 .../bindings/power/renesas,rcar-sysc.txt           |   48 +
 .../devicetree/bindings/reset/oxnas,reset.txt      |   58 +
 .../bindings/soc/rockchip/power_domain.txt         |   47 +
 .../bindings/usb/nvidia,tegra124-xusb.txt          |  120 ++
 Documentation/phy.txt                              |   16 +-
 MAINTAINERS                                        |    8 +
 arch/arm/boot/dts/exynos4.dtsi                     |    4 +-
 arch/arm/boot/dts/exynos5.dtsi                     |    4 +-
 arch/arm/boot/dts/exynos5410-smdk5410.dts          |    2 +-
 arch/arm/boot/dts/exynos5410.dtsi                  |    4 +-
 arch/arm/boot/dts/integrator.dtsi                  |    3 +-
 arch/arm/boot/dts/versatile-ab.dts                 |    5 +-
 arch/arm/mach-bcm/Kconfig                          |    2 +-
 arch/arm/mach-exynos/Kconfig                       |    3 +
 arch/arm/mach-exynos/exynos.c                      |   17 -
 arch/arm/mach-exynos/include/mach/map.h            |    3 -
 arch/arm/mach-exynos/regs-srom.h                   |   53 -
 arch/arm/mach-exynos/suspend.c                     |   20 +-
 arch/arm/mach-integrator/integrator_ap.c           |   62 -
 arch/arm/mach-integrator/integrator_cp.c           |   51 -
 arch/arm/mach-mediatek/mediatek.c                  |    1 +
 arch/arm/mach-shmobile/Kconfig                     |   11 +-
 arch/arm/mach-shmobile/Makefile                    |    1 -
 arch/arm/mach-shmobile/pm-r8a7779.c                |    3 +-
 arch/arm/mach-shmobile/pm-rcar-gen2.c              |    2 +-
 arch/arm/mach-shmobile/pm-rcar.c                   |  164 --
 arch/arm/mach-shmobile/smp-r8a7779.c               |    2 +-
 arch/arm/mach-shmobile/smp-r8a7790.c               |    2 +-
 arch/arm/mach-tegra/platsmp.c                      |   16 +-
 arch/arm/mach-versatile/versatile_dt.c             |   47 -
 arch/arm/plat-samsung/include/plat/map-s5p.h       |    1 -
 drivers/bus/Kconfig                                |    5 +-
 drivers/bus/arm-ccn.c                              |    7 +-
 drivers/clk/Kconfig                                |    1 +
 drivers/clk/renesas/Kconfig                        |   16 +
 drivers/clk/renesas/Makefile                       |   26 +-
 drivers/clk/renesas/clk-mstp.c                     |    7 +-
 drivers/clk/renesas/r8a7795-cpg-mssr.c             |   34 +-
 drivers/clk/renesas/renesas-cpg-mssr.c             |   47 +-
 drivers/clk/renesas/renesas-cpg-mssr.h             |    6 +-
 drivers/clk/tegra/clk-tegra210.c                   |   58 +
 drivers/firmware/psci.c                            |    6 +-
 drivers/gpu/drm/tegra/drm.h                        |    2 +-
 drivers/memory/Kconfig                             |    1 +
 drivers/memory/Makefile                            |    1 +
 drivers/memory/samsung/Kconfig                     |   13 +
 drivers/memory/samsung/Makefile                    |    1 +
 drivers/memory/samsung/exynos-srom.c               |  231 +++
 drivers/memory/samsung/exynos-srom.h               |   51 +
 drivers/mtd/maps/Kconfig                           |   10 +
 drivers/mtd/maps/Makefile                          |    3 +
 drivers/mtd/maps/physmap_of.c                      |    6 +
 drivers/mtd/maps/physmap_of_versatile.c            |  255 +++
 drivers/mtd/maps/physmap_of_versatile.h            |   16 +
 drivers/pci/host/pci-tegra.c                       |  244 ++-
 drivers/phy/Kconfig                                |    2 +
 drivers/phy/Makefile                               |    2 +
 drivers/phy/phy-core.c                             |   50 +-
 drivers/phy/tegra/Kconfig                          |    8 +
 drivers/phy/tegra/Makefile                         |    6 +
 drivers/phy/tegra/xusb-tegra124.c                  | 1752 +++++++++++++++++
 drivers/phy/tegra/xusb-tegra210.c                  | 2045 ++++++++++++++++++++
 drivers/phy/tegra/xusb.c                           | 1021 ++++++++++
 drivers/phy/tegra/xusb.h                           |  421 ++++
 drivers/pinctrl/tegra/pinctrl-tegra-xusb.c         |   20 +-
 drivers/reset/Kconfig                              |    3 +
 drivers/reset/Makefile                             |    1 +
 drivers/reset/core.c                               |  217 ++-
 drivers/reset/reset-lpc18xx.c                      |   22 +-
 drivers/reset/reset-oxnas.c                        |  136 ++
 drivers/soc/Makefile                               |    3 +-
 drivers/soc/brcmstb/Kconfig                        |    1 +
 drivers/soc/brcmstb/common.c                       |   66 +
 drivers/soc/mediatek/mtk-pmic-wrap.c               |  544 ++++--
 drivers/soc/qcom/smd-rpm.c                         |    9 +-
 drivers/soc/qcom/smd.c                             |  247 ++-
 drivers/soc/qcom/smem.c                            |    3 +-
 drivers/soc/qcom/spm.c                             |    8 +-
 drivers/soc/qcom/wcnss_ctrl.c                      |    8 +-
 drivers/soc/renesas/Makefile                       |    7 +
 drivers/soc/renesas/r8a7779-sysc.c                 |   34 +
 drivers/soc/renesas/r8a7790-sysc.c                 |   48 +
 drivers/soc/renesas/r8a7791-sysc.c                 |   33 +
 drivers/soc/renesas/r8a7794-sysc.c                 |   33 +
 drivers/soc/renesas/r8a7795-sysc.c                 |   56 +
 drivers/soc/renesas/rcar-sysc.c                    |  401 ++++
 drivers/soc/renesas/rcar-sysc.h                    |   58 +
 drivers/soc/rockchip/pm_domains.c                  |  247 ++-
 drivers/soc/tegra/pmc.c                            |  613 +++++-
 drivers/usb/host/Kconfig                           |    9 +
 drivers/usb/host/Makefile                          |    1 +
 drivers/usb/host/xhci-tegra.c                      | 1331 +++++++++++++
 include/dt-bindings/power/r8a7779-sysc.h           |   27 +
 include/dt-bindings/power/r8a7790-sysc.h           |   34 +
 include/dt-bindings/power/r8a7791-sysc.h           |   26 +
 include/dt-bindings/power/r8a7793-sysc.h           |   28 +
 include/dt-bindings/power/r8a7794-sysc.h           |   26 +
 include/dt-bindings/power/r8a7795-sysc.h           |   42 +
 include/dt-bindings/power/rk3399-power.h           |   53 +
 include/linux/clk/renesas.h                        |   16 +-
 include/linux/clk/tegra.h                          |    5 +
 include/linux/phy/phy.h                            |   31 +-
 include/linux/phy/tegra/xusb.h                     |   30 +
 include/linux/psci.h                               |    2 -
 include/linux/reset-controller.h                   |    2 +
 include/linux/reset.h                              |  194 +-
 include/linux/soc/qcom/smd.h                       |   11 +-
 include/linux/soc/qcom/smem_state.h                |   35 +
 .../linux/soc/renesas/rcar-sysc.h                  |    9 +-
 include/soc/tegra/fuse.h                           |    1 +
 include/soc/tegra/pmc.h                            |   36 +-
 117 files changed, 11999 insertions(+), 1056 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt
 create mode 100644 Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
 create mode 100644 Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt
 create mode 100644 Documentation/devicetree/bindings/reset/oxnas,reset.txt
 create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.txt
 delete mode 100644 arch/arm/mach-exynos/regs-srom.h
 delete mode 100644 arch/arm/mach-shmobile/pm-rcar.c
 create mode 100644 drivers/clk/renesas/Kconfig
 create mode 100644 drivers/memory/samsung/Kconfig
 create mode 100644 drivers/memory/samsung/Makefile
 create mode 100644 drivers/memory/samsung/exynos-srom.c
 create mode 100644 drivers/memory/samsung/exynos-srom.h
 create mode 100644 drivers/mtd/maps/physmap_of_versatile.c
 create mode 100644 drivers/mtd/maps/physmap_of_versatile.h
 create mode 100644 drivers/phy/tegra/Kconfig
 create mode 100644 drivers/phy/tegra/Makefile
 create mode 100644 drivers/phy/tegra/xusb-tegra124.c
 create mode 100644 drivers/phy/tegra/xusb-tegra210.c
 create mode 100644 drivers/phy/tegra/xusb.c
 create mode 100644 drivers/phy/tegra/xusb.h
 create mode 100644 drivers/reset/reset-oxnas.c
 create mode 100644 drivers/soc/renesas/Makefile
 create mode 100644 drivers/soc/renesas/r8a7779-sysc.c
 create mode 100644 drivers/soc/renesas/r8a7790-sysc.c
 create mode 100644 drivers/soc/renesas/r8a7791-sysc.c
 create mode 100644 drivers/soc/renesas/r8a7794-sysc.c
 create mode 100644 drivers/soc/renesas/r8a7795-sysc.c
 create mode 100644 drivers/soc/renesas/rcar-sysc.c
 create mode 100644 drivers/soc/renesas/rcar-sysc.h
 create mode 100644 drivers/usb/host/xhci-tegra.c
 create mode 100644 include/dt-bindings/power/r8a7779-sysc.h
 create mode 100644 include/dt-bindings/power/r8a7790-sysc.h
 create mode 100644 include/dt-bindings/power/r8a7791-sysc.h
 create mode 100644 include/dt-bindings/power/r8a7793-sysc.h
 create mode 100644 include/dt-bindings/power/r8a7794-sysc.h
 create mode 100644 include/dt-bindings/power/r8a7795-sysc.h
 create mode 100644 include/dt-bindings/power/rk3399-power.h
 create mode 100644 include/linux/phy/tegra/xusb.h
 rename arch/arm/mach-shmobile/pm-rcar.h => include/linux/soc/renesas/rcar-sysc.h (60%)



From arnd at arndb.de  Tue May 17 15:24:13 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 00:24:13 +0200
Subject: [GIT PULL 5/7] ARM: 64-bit DT updates for v4.7
In-Reply-To: <8749147.ztcb6kVhye@wuerfel>
References: <8749147.ztcb6kVhye@wuerfel>
Message-ID: <2552078.Axrq2ryspa@wuerfel>

The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:

  Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/armsoc-dt64

for you to fetch changes up to 9910f5b199621aecfbdb0b63feb31ddd41fd63e2:

  Merge tag 'imx-dt64-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into next/dt64 (2016-05-10 22:19:36 +0200)

----------------------------------------------------------------
ARM: 64-bit DT updates for v4.7

We continue ramping up platform support for 64-bit ARM machines,
with 111 individual non-merge changesets touching 21 platforms.

The LG1312 platform is completely new and is the first ARM
platform by LG that we support in the mainline kernel. Two other
SoCs got added that are updated versions of existing SoC
families, so the port mainly consists of new dts files:
- The Hisilicon Hip06/D03 is the latest server platform
  from Huawei/Hisilicon, and follows the Hip05/D02 platform.
- Rockchip RK3399 follows the 32-bit RK3288 that is popular
  in low-end Chromebooks and the 64-bit RK3368 that is mainly
  found in chinese Android TV boxes.

The 96Boards HiKey based on the Hisilicon Hi6220 (Kirin 620)
gets a long-awaited overhaul with a lot of devices enabled in
the DT, so it should be much more usable with a mainline kernel
now. See also
https://plus.google.com/111524780435806926688/posts/PeGb2VsNhJd

A lot of work went into enabling new device drivers on existing
machines, but we also have a couple of new commercially
available machines:

- Google Pixel C laptop based on Tegra210
- Hardkernel Odroid C2 Based on Amlogic Meson GXBB (S905)
- Geekbuying GeekBox based on Rockchip RK3368

And finally, a couple of reference or development platforms
that are not end-user platforms but are used for trying out
the respective SoC platforms:

- Amlogic Meson GXBB P200 and P201 development systems
- NXP Layerscape 1043A QDS development board
- Hisilicon Hip06 D03 server board, as mentioned above
- LG1312 Reference Design
- RK3399 Evaluation Board

----------------------------------------------------------------
Alexandre Courbot (5):
      dt-bindings: gk20a: Fix typo in compatible name
      dt-bindings: gk20a: Document iommus property
      dt-bindings: Add documentation for GM20B GPU
      arm64: tegra: Add reference clock to GM20B on Tegra210
      arm64: tegra: Add IOMMU node to GM20B on Tegra210

Alim Akhtar (2):
      arm64: dts: exynos: Add TMU node for exynos7
      arm64: dts: Add nodes for pdma0 and pdma1 for exynos7

Andreas F?rber (9):
      dt-bindings: Add vendor prefix for GeekBuying.com
      arm64: dts: rockchip: Clean up gpio-keys nodes
      ARM64: dts: amlogic: Clean up Vega S95 /memory nodes
      arm64: dts: rockchip: Add rk3368 GeekBox dts
      Documentation: devicetree: rockchip: Document rk3368-GeekBox
      arm64: dts: marvell: clean up armada-7040-db
      arm64: dts: marvell: rename armada-ap806 XOR nodes
      arm64: dts: marvell: Clean up armada-3720-db
      arm64: dts: marvell: Rename armada-37xx USB node

Anup Patel (4):
      arm64: dts: Add ARM PL330 DMA DT node for NS2
      arm64: dts: Add maintenance interrupt for GIC in NS2 DT
      arm64: dts: Move NS2 clock DT nodes to separate DT file
      arm64: dts: Add ARM PL022 SPI DT nodes for NS2

Arnd Bergmann (15):
      Merge tag 'samsung-dt64-4.7' of git://git.kernel.org/.../krzk/linux into next/dt64
      Merge tag 'tegra-for-4.7-arm64' of git://git.kernel.org/.../tegra/linux into next/dt64
      Merge tag 'juno-for-v4.7/dt-updates' of git://git.kernel.org/.../sudeep.holla/linux into next/dt64
      Merge tag 'hi6220-dt-for-4.7' of git://github.com/hisilicon/linux-hisi into next/dt64
      Merge tag 'xgene-dts-for-v4.7-part1' of https://github.com/AppliedMicro/xgene-next into next/dt64
      Merge tag 'arm-soc/for-4.7/devicetree-arm64' of http://github.com/Broadcom/stblinux into next/dt64
      Merge tag 'renesas-arm64-dt2-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/dt64
      Merge tag 'hip0x-dt-for-4.7' of git://github.com/hisilicon/linux-hisi into next/dt64
      Merge branch 'renesas/fixes-2' into next/dt64
      Merge tag 'v4.7-rockchip-dts64-2' of git://git.kernel.org/.../mmind/linux-rockchip into next/dt64
      Merge tag 'mvebu-dt64-4.7-1' of git://git.infradead.org/linux-mvebu into next/dt64
      Merge tag 'tegra-for-4.7-gpio' of git://git.kernel.org/.../tegra/linux into next/dt64
      Merge tag 'tegra-for-4.7-gm20b' of git://git.kernel.org/.../tegra/linux into next/dt64
      Merge tag 'v4.6-next-dts64' of https://github.com/mbgg/linux-mediatek into next/dt64
      Merge tag 'imx-dt64-4.7' of git://git.kernel.org/.../shawnguo/linux into next/dt64

Brian Starkey (1):
      arm64: dts: juno: Add external expansion bus to DT

Caesar Wang (3):
      arm64: dts: rockchip: fix the incorrect otp-out pin on rk3368
      arm64: dts: rockchip: Add rk3368 mailbox device nodes
      arm64: dts: rockchip: move the rk3368 thermal data into rk3368.dtsi

Chanho Min (1):
      arm64: dts: Add dts files for LG Electronics's lg1312 SoC

Chen Feng (1):
      arm64: dts: hikey: Add hi655x pmic dts node

Geert Uytterhoeven (3):
      ARM: shmobile: timer: Fix preset_lpj leading to too short delays
      arm64: dts: r8a7795: Don't disable referenced optional scif clock
      arm64: dts: r8a7795: Don't disable referenced optional clocks

Gregory CLEMENT (2):
      arm64: dts: marvell: Use a SoC-specific compatible for xHCI on Armada37xx
      arm64: dts: marvell: add XOR node for Armada 3700 SoC

Guodong Xu (4):
      arm64: dts: hikey: enable i2c0 and i2c1 for working with mezzanine boards
      arm64: dts: hi6220: add pinctrl for uarts and enable them
      arm64: dts: add LED nodes for hi6220-hikey
      arm64: dts: add wifi nodes support for hi6220-hikey

Heiko Stuebner (2):
      clk: rockchip: fix checkpatch errors in rk3399 dt-binding header
      Merge branch 'v4.7-shared/clkids' into v4.7-armsoc/dts64

Hou Zhiqiang (1):
      Documentation: DT: Add entry for Freescale LS1043a-QDS board

Jianqun Xu (3):
      arm64: dts: rockchip: add core dtsi file for RK3399 SoCs
      arm64: dts: rockchip: add dts file for RK3399 evaluation board
      dt-bindings: document rockchip rk3399-evb board

Jon Hunter (3):
      arm64: tegra: Add support for Google Pixel C
      arm64: tegra: Remove unused #power-domain-cells property
      arm64: tegra: Add stdout-path for various boards

Kefeng Wang (4):
      arm64: dts: hip05: fix its node without msi-cells
      arm64: dts: hip05: Add nor flash support
      arm64: dts: Add initial dts for Hisilicon Hip06 D03 board
      Documentation: arm64: Add Hisilicon Hip06 D03 dts binding

Kevin Hilman (4):
      ARM64: dts: amlogic: update serial aliases
      Documentation: devicetree: amlogic: Document P20x and ODROID-C2 boards
      ARM64: dts: amlogic: add Hardkernel ODROID-C2
      ARM64: dts: amlogic: Add P200/P201 boards

Laxman Dewangan (1):
      arm64: tegra: Enable power and volume keys on Jetson TX1

Leo Yan (8):
      arm64: dts: Reserve memory regions for hi6220
      arm64: dts: add sp804 timer node for Hi6220
      arm64: dts: enable idle states for Hi6220
      arm64: dts: add mailbox node for Hi6220
      arm64: dts: add Hi6220's stub clock node
      arm64: dts: register Hi6220's thermal sensor
      arm64: dts: register Hi6220's thermal zone for power allocator
      arm64: dts: Add L2 cache topology to Hi6220

Liu Gang (2):
      arm64: dts: ls1043a: Add compatible "fsl,qoriq-gpio" for ls1043a gpio nodes
      arm64: dts: ls2080a: Add compatible "fsl,ls2080a-gpio" for ls2080a gpio nodes

Luke Starrett (1):
      arm64: dts: NS2 secondary core enablement via PSCI

Masahiro Yamada (2):
      arm64: dts: uniphier: use Daughter board on PH1-LD20 reference board
      arm64: dts: uniphier: add reference clock node for PH1-LD20

Olof Johansson (3):
      Merge tag 'gxbb-dt64' of https://github.com/carlocaione/linux-meson into next/dt64
      Merge tag 'renesas-arm64-cleanup-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/dt64
      Merge tag 'v4.7-rockchip-dts64-1' of git://git.kernel.org/.../mmind/linux-rockchip into next/dt64

Phil Edworthy (2):
      arm64: dts: r8a7795: Add PCIe nodes
      arm64: dts: r8a7795: enable PCIe on Salvator-X

Ramesh Shanmugasundaram (2):
      arm64: dts: r8a7795: Add CAN external clock support
      arm64: dts: r8a7795: Add CAN support

Rameshwar Prasad Sahu (1):
      arm64: dts: apm: Fix compatible string for X-Gene 2 SATA controller DTS node

Rhyland Klein (3):
      arm64: tegra: Add gpio-keys nodes for Smaug
      arm64: tegra: Add pinmux for Smaug board
      arm64: tegra: Enable cros-ec and charger on Smaug

Sascha Hauer (1):
      ARM64: dts: mt8173: Add thermal/auxadc device nodes

Shaohui Xie (1):
      arm64: dts: add LS1043a-QDS board support

Shawn Lin (2):
      arm64: dts: rockchip: remove broken-cd from emmc and sdio
      dt-bindings: rockchip-dw-mshc: add description for rk3399

Simon Horman (2):
      arm64: dts: salvator-x: use generic pinctrl properties
      arm64: dts: r8a7795: Use USB3.0 fallback compatibility string

Sjoerd Simons (2):
      ARM: dts: r8a7791: Don't disable referenced optional clocks
      Revert "ARM: dts: porter: Enable SCIF_CLK frequency and pins"

Stephen Warren (2):
      ARM: tegra: Fix naming in GPIO DT binding header
      ARM: tegra: Add DT binding for Tegra186 GPIO controllers

Stuart Yoder (2):
      Documentation: fsl-mc: binding updates for MSIs, ranges, PHYs
      arm64: dts: ls2080a: fsl-mc dt node updates

Sudeep Holla (1):
      arm64: tegra: Replace legacy *,wakeup property with wakeup-source

Thierry Reding (2):
      arm64: tegra: Remove 0, prefix from unit-addresses
      arm64: tegra: Fix copy/paste typo in several DTS includes

Thomas Petazzoni (6):
      arm64: dts: marvell: add UART aliases and define stdout-path
      arm64: dts: marvell: use new clock binding on Armada AP806
      arm64: dts: marvell: improve SPI flash description on Armada 7040-DB
      arm64: dts: marvell: use the proper I2C controller compatible string for 7K/8K
      arm64: dts: marvell: initial DT description of Armada 7K/8K CP110 master
      arm64: dts: marvell: enable several CP interfaces on Armada 7040-DB

Wolfram Sang (1):
      arm64: dts: salvator-x: populate EXTALR

Xing Zheng (4):
      clk: rockchip: add dt-binding header for rk3399
      clk: rockchip: add general gpu soft-reset on rk3399
      clk: rockchip: rename rga clock-id on rk3399
      clk: rockchip: export some necessary rk3399 clock ids

Xinwei Kong (2):
      arm64: dts: add all hi6220 i2c nodes
      arm64: dts: add dwmmc nodes for hi6220

Yuan Yao (4):
      Documentation: fsl: dspi: Add fsl,ls2080a-dspi compatible string
      arm64: dts: ls2080a: update the DTS for QSPI and DSPI support
      Documentation: fsl-quadspi: Add fsl,ls1043a-qspi compatible string
      arm64: dts: ls1043a: add the DTS node for QSPI support

Yunhui Cui (1):
      arm64: dts: ls1043a-rdb: add the DTS for DSPI support

Zhangfei Gao (1):
      arm64: dts: Add hi6220 usb node

Zhong Kaihua (3):
      arm64: dts: Add Hi6220 gpio configuration nodes
      arm64: dts: add Hi6220 pinctrl configuration nodes
      arm64: dts: add Hi6220 spi configuration nodes

dawei.chien at mediatek.com (1):
      arm64: dts: mt8173: Add thermal zone node.

 Documentation/devicetree/bindings/arm/amlogic.txt  |    3 +
 Documentation/devicetree/bindings/arm/fsl.txt      |    4 +
 .../bindings/arm/hisilicon/hisilicon.txt           |   20 +-
 Documentation/devicetree/bindings/arm/rockchip.txt |   10 +-
 .../bindings/gpio/nvidia,tegra186-gpio.txt         |  161 +++
 .../devicetree/bindings/gpu/nvidia,gk20a.txt       |   37 +-
 .../devicetree/bindings/misc/fsl,qoriq-mc.txt      |   81 +-
 .../devicetree/bindings/mmc/rockchip-dw-mshc.txt   |    1 +
 .../devicetree/bindings/mtd/fsl-quadspi.txt        |    3 +-
 .../devicetree/bindings/spi/spi-fsl-dspi.txt       |    5 +-
 Documentation/devicetree/bindings/usb/usb-xhci.txt |    1 +
 .../devicetree/bindings/vendor-prefixes.txt        |    1 +
 arch/arm/boot/dts/r8a7791-koelsch.dts              |    1 +
 arch/arm/boot/dts/r8a7791-porter.dts               |   14 +-
 arch/arm/boot/dts/r8a7791.dtsi                     |    5 +-
 arch/arm/mach-shmobile/timer.c                     |   28 +-
 arch/arm64/boot/dts/Makefile                       |    1 +
 arch/arm64/boot/dts/amlogic/Makefile               |    3 +
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts |   69 +
 arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts    |   52 +
 arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts    |   52 +
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi   |   65 +
 .../boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts  |    2 +-
 .../boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts   |    2 +-
 .../boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts |    2 +-
 .../boot/dts/amlogic/meson-gxbb-vega-s95.dtsi      |    4 +
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |    5 -
 arch/arm64/boot/dts/apm/apm-shadowcat.dtsi         |    6 +-
 arch/arm64/boot/dts/arm/juno-base.dtsi             |   10 +
 arch/arm64/boot/dts/broadcom/ns2-clock.dtsi        |  105 ++
 arch/arm64/boot/dts/broadcom/ns2-svk.dts           |   45 +
 arch/arm64/boot/dts/broadcom/ns2.dtsi              |  155 +--
 .../boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi   |   25 +
 .../arm64/boot/dts/exynos/exynos7-trip-points.dtsi |   54 +
 arch/arm64/boot/dts/exynos/exynos7.dtsi            |   49 +
 arch/arm64/boot/dts/freescale/Makefile             |    3 +-
 arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts  |  181 +++
 arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts  |   13 +
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi     |   22 +-
 arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts  |    9 +-
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi     |  110 +-
 arch/arm64/boot/dts/hisilicon/Makefile             |    4 +-
 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |  200 ++-
 arch/arm64/boot/dts/hisilicon/hi6220.dtsi          |  623 +++++++++
 arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi   |  705 ++++++++++
 arch/arm64/boot/dts/hisilicon/hip05-d02.dts        |   34 +
 arch/arm64/boot/dts/hisilicon/hip05.dtsi           |   10 +
 arch/arm64/boot/dts/hisilicon/hip06-d03.dts        |   34 +
 arch/arm64/boot/dts/hisilicon/hip06.dtsi           |  307 +++++
 arch/arm64/boot/dts/lg/Makefile                    |    5 +
 arch/arm64/boot/dts/lg/lg1312-ref.dts              |   36 +
 arch/arm64/boot/dts/lg/lg1312.dtsi                 |  351 +++++
 arch/arm64/boot/dts/marvell/armada-3720-db.dts     |   32 +-
 arch/arm64/boot/dts/marvell/armada-372x.dtsi       |    1 -
 arch/arm64/boot/dts/marvell/armada-37xx.dtsi       |   20 +-
 arch/arm64/boot/dts/marvell/armada-7020.dtsi       |    1 +
 arch/arm64/boot/dts/marvell/armada-7040-db.dts     |  108 +-
 arch/arm64/boot/dts/marvell/armada-7040.dtsi       |    1 +
 arch/arm64/boot/dts/marvell/armada-8020.dtsi       |    1 +
 arch/arm64/boot/dts/marvell/armada-8040.dtsi       |    1 +
 arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi |    1 -
 arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi |    2 -
 arch/arm64/boot/dts/marvell/armada-ap806.dtsi      |   56 +-
 .../boot/dts/marvell/armada-cp110-master.dtsi      |  228 ++++
 arch/arm64/boot/dts/mediatek/mt8173.dtsi           |   60 +
 arch/arm64/boot/dts/nvidia/Makefile                |    1 +
 arch/arm64/boot/dts/nvidia/tegra132-norrin.dts     |   55 +-
 arch/arm64/boot/dts/nvidia/tegra132.dtsi           |  120 +-
 arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi     |    8 +-
 arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi     |   14 +-
 arch/arm64/boot/dts/nvidia/tegra210-p2571.dts      |    2 +-
 arch/arm64/boot/dts/nvidia/tegra210-p2595.dtsi     |    2 +-
 arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi     |   30 +-
 arch/arm64/boot/dts/nvidia/tegra210-smaug.dts      | 1424 ++++++++++++++++++++
 arch/arm64/boot/dts/nvidia/tegra210.dtsi           |  130 +-
 arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts |   63 +-
 arch/arm64/boot/dts/renesas/r8a7795.dtsi           |   98 +-
 arch/arm64/boot/dts/rockchip/Makefile              |    2 +
 arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi       |    8 +-
 arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts    |  319 +++++
 arch/arm64/boot/dts/rockchip/rk3368-r88.dts        |    8 +-
 arch/arm64/boot/dts/rockchip/rk3368.dtsi           |   82 +-
 .../{rk3368-thermal.dtsi => rk3399-evb.dts}        |  124 +-
 arch/arm64/boot/dts/rockchip/rk3399.dtsi           | 1013 ++++++++++++++
 .../boot/dts/socionext/uniphier-ph1-ld20-ref.dts   |    1 +
 .../boot/dts/socionext/uniphier-ph1-ld20.dtsi      |    6 +
 .../boot/dts/socionext/uniphier-ref-daughter.dtsi  |    1 +
 include/dt-bindings/clock/rk3399-cru.h             |  755 +++++++++++
 include/dt-bindings/gpio/tegra-gpio.h              |   68 +-
 include/dt-bindings/gpio/tegra186-gpio.h           |   56 +
 include/dt-bindings/pinctrl/hisi.h                 |   59 +
 91 files changed, 8132 insertions(+), 557 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
 create mode 100644 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
 create mode 100644 arch/arm64/boot/dts/broadcom/ns2-clock.dtsi
 create mode 100644 arch/arm64/boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi
 create mode 100644 arch/arm64/boot/dts/exynos/exynos7-trip-points.dtsi
 create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
 create mode 100644 arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi
 create mode 100644 arch/arm64/boot/dts/hisilicon/hip06-d03.dts
 create mode 100644 arch/arm64/boot/dts/hisilicon/hip06.dtsi
 create mode 100644 arch/arm64/boot/dts/lg/Makefile
 create mode 100644 arch/arm64/boot/dts/lg/lg1312-ref.dts
 create mode 100644 arch/arm64/boot/dts/lg/lg1312.dtsi
 create mode 100644 arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
 create mode 100644 arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts
 rename arch/arm64/boot/dts/rockchip/{rk3368-thermal.dtsi => rk3399-evb.dts} (55%)
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3399.dtsi
 create mode 120000 arch/arm64/boot/dts/socionext/uniphier-ref-daughter.dtsi
 create mode 100644 include/dt-bindings/clock/rk3399-cru.h
 create mode 100644 include/dt-bindings/gpio/tegra186-gpio.h
 create mode 100644 include/dt-bindings/pinctrl/hisi.h



From arnd at arndb.de  Tue May 17 15:21:59 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 00:21:59 +0200
Subject: [GIT PULL 3/7] ARM: SoC 64-bit changes for v4.7
In-Reply-To: <8749147.ztcb6kVhye@wuerfel>
References: <8749147.ztcb6kVhye@wuerfel>
Message-ID: <2939699.o6fZg7I3Ka@wuerfel>

The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:

  Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/armsoc-arm64

for you to fetch changes up to da4a95d23beea1c3d1d131480f681b0b276e207e:

  Merge tag 'mvebu-defconfig64-4.7-1' of git://git.infradead.org/linux-mvebu into next/arm64 (2016-05-10 17:46:15 +0200)

----------------------------------------------------------------
ARM: SoC 64-bit changes for v4.7

One new platform gets added this time: The Cortex-A53 based LG Electronics
LG1K platform used in digital TVs.

The other changes are mostly smaller updates to the defconfig files, to
enable additional platform specific drivers, as they get merged through
the subsystem trees.

----------------------------------------------------------------
Akira Tsukamoto (1):
      arm64: defconfig: enable several common USB network adapters

Alim Akhtar (1):
      arm64: defconfig: Enable PL330 DMA controller

Andre Przywara (1):
      arm64: defconfig: Add Juno SATA controller

Arnd Bergmann (6):
      Merge tag 'samsung-defconfig64-4.7' of git://git.kernel.org/.../krzk/linux into next/arm64
      Merge tag 'hi6220-config-for-4.7v3' of git://github.com/hisilicon/linux-hisi into next/arm64
      Merge tag 'renesas-arm64-defconfig-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/arm64
      Merge tag 'imx-defconfig64-4.7' of git://git.kernel.org/.../shawnguo/linux into next/arm64
      Merge tag 'mvebu-arm64-4.7-1' of git://git.infradead.org/linux-mvebu into next/arm64
      Merge tag 'mvebu-defconfig64-4.7-1' of git://git.infradead.org/linux-mvebu into next/arm64

Chanho Min (3):
      arm64: add Kconfig entry for LG1K SoC family
      arm64: defconfig: enable ARCH_LG1K
      MAINTAINERS: add Chanho Min as ARM/LG1K maintainer

Guodong Xu (3):
      arm64: defconfig: Enable the PMIC and regulator for Hi6220 and 96boards HiKey
      arm64: defconfig: add CONFIG_SPI_SPIDEV as module
      arm64: defconfig: enable configs for WLAN and TI WL1835 as modules

Kevin Hilman (1):
      arm64: defconfig: enable basic boot for Amlogic meson

Leo Yan (1):
      arm64: Kconfig: select sp804 timer for ARCH_HISI

Olof Johansson (1):
      Merge tag 'gxbb-arm64' of https://github.com/carlocaione/linux-meson into next/arm64

Stuart Yoder (3):
      arm64: defconfig: cleanup the defconfig
      arm64: defconfig: enable 48-bit virtual addresses
      arm64: defconfig: enable freescale/nxp config options

Thomas Petazzoni (3):
      arm64: marvell: enable AP806 and CP110 syscon driver
      MAINTAINERS: update entry for Marvell ARM platform maintainers
      arm64: configs: add options useful for Armada 7K/8K support

Yoshihiro Shimoda (1):
      arm64: defconfig: Add Renesas R-Car USB 3.0 driver support

 MAINTAINERS                  |  8 +++++++-
 arch/arm64/Kconfig.platforms | 10 ++++++++--
 arch/arm64/configs/defconfig | 45 +++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 55 insertions(+), 8 deletions(-)



From arnd at arndb.de  Tue May 17 15:23:15 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 00:23:15 +0200
Subject: [GIT PULL 4/7] ARM: DT updates for v4.7
In-Reply-To: <8749147.ztcb6kVhye@wuerfel>
References: <8749147.ztcb6kVhye@wuerfel>
Message-ID: <4897774.QfBWDn1tQ5@wuerfel>

The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:

  Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/armsoc-dt

for you to fetch changes up to ec42083b98bc7a85c736a8ae1b4c045901ed259e:

  ARM: dts: tango4: Import watchdog node (2016-05-10 16:12:00 +0200)

----------------------------------------------------------------
ARM: DT updates for v4.7

These are all the updates to device tree files for 32-bit platforms,
which as usual makes up the bulk of the ARM SoC changes: 462 non-merge
changesets, 450 files changed, 23340 insertions, 5216 deletions.

The three platforms that are added with the "soc" branch are here as well,
and we add some related machine files:

- For Aspeed AST2400/AST2500, we get the evaluation platform and
  the Tyan Palmetto POWER8 mainboard that uses the AST2400 BMC
- For Oxnas 810SE, the Western Digital "My Book World Edition"
  is added as the only platform at the moment.
- For ARM MPS2, the AN385 (Cortex-M3) and AN399 (Cortex-M7)
  are supported

On the ARM Realview development platform, we now support all machines
with device tree, previously only the board files were supported, which
in turn will likely be removed soon.

Qualcomm IPQ4019 is the second generation ARM based "Internet Processor",
following the IPQ806x that is used in many high-end WiFi routers. This one
integrates two ath10k wifi radios that were previously on separate chips.

Other boards that got added for existing chips are:

- On Ti OMAP family:
  - Amazon Kindle Fire, first generation, tablet and ebook reader
  - OnRISC Baltos iR 2110 and 3220 embedded industrial PCs
  - TI AM5728 IDK, TI AM3359 ICE-V2, and TI DRA722 Rev C EVM
    development systems

- On Samsung EXYNOS platform:
  - Samsung ARTIK5 evaluation board, see
    https://www.artik.io/modules/overview/artik-5/

- On NXP i.MX platforms:
  - Ka-Ro electronics TX6S-8034, TX6S-8035, TX6U-8033, TX6U-81xx,
    TX6Q-1036, TX6Q-1110/-1130, TXUL-0010 and TXUL-0011 industrial
    SoM modules
  - Embest MarS Board i.MX6Dual DIY platform
  - Boundary Devices i.MX6 Quad Plus Nitrogen6_MAX and
    SoloX Nitrogen6sx embedded boards
  - Technexion Pico i.MX6UL compute module
  - ZII VF610 Development Board

- On Marvell embedded (mvebu, orion, kirkwood) platforms:
  - Linksys Viper (E4200v2 / EA4500) WiFi router
  - Buffalo Kurobox Pro NAS

- On Qualcomm Snapdragon:
  - Arrow DragonBoard 600c (96boards) with APQ8064 Snapdragon 600

- On Rockchips platform:
  - mqmaker MiQi single-board computer

- On Altera SoCFPGA:
  - samtec VIN|ING 1000 vehicle communication interface

- On Allwinner Sunxi platforms:
  - Dserve DSRV9703C tablet
  - Difrnce DIT4350 tablet
  - Colorfly E708 Q1 tablet
  - Polaroid MID2809PXE04 tablet
  - Olimex A20 OLinuXino LIME2 single board computer
  - Xunlong Orange Pi 2, Orange Pi One, and Orange Pi PC
    single board computers

Across many platforms, bug fixes went in to address warnings that
dtc now emits with 'make dtbs W=1'. Further changes for device enablement
went into Ti OMAP, bcm283x (Raspberry Pi), bcm47xx (wifi router),
Ti Davinci, Samsung EXYNOS, Marvell mvebu/kirkwood/orion, NXP i.MX/Vybrid
NXP LPC18xx, NXP LPC32xx, Renesas shmobile/r-mobile/r-car, Rockchips
rk3xxx, ST Ux500, ST STi, Atmel AT91/SAMA5, Altera SoCFPGA, Allwinner
Sunxi, Sigma Designs Tango, NVIDIA Tegra, Socionext Uniphier and ARM
Versatile Express.

----------------------------------------------------------------
Adam Baker (1):
      ARM: dts: kirkwood: Add the hardware monitor to the NSA320 device tree

Akshay Bhat (5):
      ARM: dts: imx6q-ba16: Remove unused vqmmc-supply
      ARM: dts: imx6q-b850v3: Remove ldb panel
      ARM: dts: imx6q-b850v3: Update display clock source
      ARM: dts: imx: b450/b650v3: Move ldb_di clk assignment
      ARM: dts: imx6q-ba16: use wdog external reset

Alexander Kurz (1):
      ARM: dts: i.MX3x: add keypad port devicetree nodes

Alexander Stein (1):
      ARM: dts: ls1021a: DSPI has 6 chip-selects

Andrew Lunn (8):
      ARM: dts: kirkwood: Remove button address and fixup names
      ARM: dts: kirkwood: Remove node address from leds
      ARM: dts: kirkwood: Remove address from dsa unit name
      ARM: dts: kirkwood: Add address to ethernet-phy unit name
      ARM: dts: kirkwood: Fixup pcie DT warnings
      ARM: dts: kirkwood: Remove address from gpio-i2c unit name
      ARM: dts: kirkwood: Add address to mbus unit name
      ARM: dts: kirkwood: Add address go regulator unit name

Arnd Bergmann (34):
      Merge tag 'samsung-dt-exynos3250-artik5-4.7' of git://git.kernel.org/.../krzk/linux into next/dt
      Merge tag 'samsung-dt-4.7' of git://git.kernel.org/.../krzk/linux into next/dt
      Merge tag 'mvebu-dt-4.7-1' of git://git.infradead.org/linux-mvebu into next/dt
      Merge tag 'nomadik-dts-v4.7' of git://git.kernel.org/.../linusw/linux-nomadik into next/dt
      Merge tag 'davinci-for-v4.7/dt' of git://git.kernel.org/.../nsekhar/linux-davinci into next/dt
      Merge tag 'tegra-for-4.7-arm' of git://git.kernel.org/.../tegra/linux into next/dt
      Merge tag 'imx-dt-4.7' of git://git.kernel.org/.../shawnguo/linux into next/dt
      Merge tag 'renesas-rcar-sysc-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/dt
      Merge tag 'omap-for-v4.7/dt-part1' of git://git.kernel.org/.../tmlind/linux-omap into next/dt
      Merge tag 'arm-soc/for-4.7/devicetree' of http://github.com/Broadcom/stblinux into next/dt
      Merge tag 'qcom-dt-for-4.7' of git://git.kernel.org/.../agross/linux into next/dt
      Merge tag 'renesas-dt-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/dt
      Merge tag 'vexpress-for-v4.7/updates' of git://git.kernel.org/.../sudeep.holla/linux into next/dt
      Merge tag 'keystone_dts_for_4.7' of git://git.kernel.org/.../ssantosh/linux-keystone into next/dt
      Merge tag 'omap-for-v4.6/dt-ti81xx-signed' of git://git.kernel.org/.../tmlind/linux-omap into next/dt
      Merge tag 'renesas-fixes-for-v4.6' of git://git.kernel.org/.../horms/renesas into next/dt
      Merge tag 'ox810se-arm-dt-v4.6-rc3' of https://github.com/superna9999/linux into next/dt
      Merge tag 'sti-dt-for-v4.7b-1' of git://git.kernel.org/.../mcoquelin/sti into next/dt
      Merge tag 'at91-dt2' of git://git.kernel.org/.../nferre/linux-at91 into next/dt
      Merge tag 'lpc32xx-dt-4.7' of git://github.com/vzapolskiy/linux-lpc32xx into next/dt
      Merge tag 'renesas-dt2-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/dt
      Merge tag 'samsung-dt-4.7-2' of git://git.kernel.org/.../krzk/linux into next/dt
      Merge tag 'socfpga_dts_for_v4.7_part_2' of git://git.kernel.org/.../dinguyen/linux into next/dt
      Merge tag 'samsung-dt-exynos-srom-fixup-4.7' of git://git.kernel.org/.../krzk/linux into next/dt
      Merge tag 'omap-for-v4.7/dt-signed' of git://git.kernel.org/.../tmlind/linux-omap into next/dt
      Merge tag 'v4.7-rockchip-dts32-2' of git://git.kernel.org/.../mmind/linux-rockchip into next/dt
      Merge tag 'davinci-for-v4.7/dt-part2' of git://git.kernel.org/.../nsekhar/linux-davinci into next/dt
      Merge tag 'sunxi-dt-for-4.7' of https://git.kernel.org/.../mripard/linux into next/dt
      Merge tag 'v4.6-next-dts' of https://github.com/mbgg/linux-mediatek into next/dt
      Merge tag 'imx-dt-4.7-2' of git://git.kernel.org/.../shawnguo/linux into next/dt
      Merge tag 'ux500-armsoc-v4.7' of git://git.kernel.org/.../linusw/linux-stericsson into next/dt
      Merge tag 'at91-dt3' of git://git.kernel.org/.../nferre/linux-at91 into next/dt
      Merge tag 'aspeed-for-4.7-dts' of https://github.com/shenki/linux into next/dt
      Merge tag 'sunxi-dt-for-4.7-2' of https://git.kernel.org/.../mripard/linux into next/dt

Ben Hutchings (2):
      ARM: dts: dra7xx: Fix compatible string for PCF8575 chip
      ARM: dts: r8a7790: Set maximum frequencies for SDHI clocks

Bert Vermeulen (1):
      ARM: dts: kirkwood: Add DTS for Linksys EA4200v2/EA4500

Biao Huang (1):
      arm: dts: Add pinctrl/GPIO/EINT node for mt2701

Bjorn Andersson (6):
      ARM: dts: msm8974: Split efs in rfsa and rmtfs
      ARM: dts: msm8974: Add node for second i2c from blsp1
      ARM: dts: msm8974: Add modem smp2p and smd nodes
      ARM: dts: qcom: apq8064: Add syscon for sic-non-secure
      ARM: dts: qcom: apq8064: Add complete smsm node
      ARM: dts: qcom: apq8064: Add smd node and all edges

Brian Starkey (1):
      ARM: dts: vexpress: Add external expansion bus to DT

Caesar Wang (7):
      ARM: dts: rockchip: add vop device node for rk3036
      ARM: dts: rockchip: add hdmi device node for rk3036
      ARM: dts: rockchip: enable graphics support on rk3036-kylin
      ARM: dts: rockchip: add the thermal main info found on rk3228
      ARM: dts: rockchip: enable the tsadc for rk3228 evb
      ARM: dts: rockchip: add rk3288-veyron-jaq backlight and panel overrides
      ARM: dts: rockchip: move the rk3288 thermal data into rk3288.dtsi

Chanho Park (1):
      ARM: dts: exynos: Add exynos5420-fimd compatible

Chanwoo Choi (6):
      dt-bindings: Add the clock id of UART2 and MMC2 for Exynos3250
      clk: samsung: exynos3250: Add MMC2 clock
      ARM: dts: exynos: Add initial pin configuration for exynos3250-rinato
      ARM: dts: exynos: Add initial gpio setting of MMC2 device for exynos3250-monk
      ARM: dts: exynos: Add MSHC2 DT node for Exynos3250 SoC
      ARM: dts: exynos: Add exynos3250-artik5 dtsi file for ARTIK5 module

Chen-Yu Tsai (1):
      ARM: dts: sun8i: Add Orange Pi PC support

Christopher Spinrath (1):
      ARM: dts: sun7i: Enable S/PDIF on the Cubietruck

Cory Tusar (1):
      ARM: dts: vf610-zii-dev: Add ZII development board.

Cyrille Pitchen (1):
      ARM: dts: at91: sama5d2: add SFR node

David Lechner (5):
      ARM: dts: davinci: use proper address after @
      ARM: dts: da850: add spi0 to device tree
      ARM: davinci: da8xx-dt: Add spi0 lookup for clock matching
      ARM: dts: da850: disable mdio and eth0 in da850.dtsi
      ARM: dts: da850: There are 101 interrupts.

Dinh Nguyen (3):
      ARM: dts: socfpga: add cap-sd-highspeed for SD/MMC node
      ARM: dts: socfpga: add the clk-phase property for sd/mmc clock
      ARM: dts: socfpga: add reset control for USB

Eric Anholt (2):
      drm/vc4: Kick out the simplefb framebuffer before we set up KMS.
      ARM: bcm2835: Add VC4 to the device tree.

Fabio Estevam (14):
      ARM: dts: imx6qdl-sabresd: Pass the hannstar panel compatible string
      ARM: dts: imx6sx: Fix SAI DMA index
      ARM: dts: imx6sx: Remove unused property
      bindings: fsl-imx-sdma: Document 'fsl,sdma-event-remap' property
      ARM: dts: imx6sx-sdb: Add SAI support
      ARM: dts: imx6ul: Fix operating points
      ARM: dts: imx6sx: Add 198MHz operating point
      ARM: dts: imx6dl: Fix the VDD_ARM_CAP voltage for 396MHz operation
      ARM: dts: imx6: Do not hardcode the CLKO clock
      ARM: dts: imx6ul-pico-hobbit: Add initial support
      ARM: dts: imx28-m28: Remove unneeded partition nodes
      ARM: dts: imx6sx-sdb: Add 198MHz operational point
      ARM: dts: imx6qdl: Remove unneeded unit-addresses
      ARM: dts: imx6ul-14x14-evk: Add audio support

Filip Matijevi? (2):
      ARM: dts: N9/N950: Add support for 1GHz CPU clock
      ARM: dts: N9/N950: Add support for accelerometer

Florian Fainelli (1):
      Merge tag 'bcm2835-dt-next-2016-04-20' into devicetree/next

Florian Vallee (1):
      ARM: dts: at91: fix typo in sama5d2 PIN_PD24 description

Franklin S Cooper Jr (1):
      ARM: dts: da850/am4372/am33xx: Use generic node name for ehrpwm

Gary Bisson (2):
      ARM: dts: imx: add Boundary Devices Nitrogen6_MAX QP board
      ARM: dts: imx: add Boundary Devices Nitrogen6_SoloX board

Geert Uytterhoeven (21):
      PM / Domains: Add DT bindings for the R-Car System Controller
      soc: renesas: Add r8a7779 SYSC PM Domain Binding Definitions
      soc: renesas: Add r8a7790 SYSC PM Domain Binding Definitions
      soc: renesas: Add r8a7791 SYSC PM Domain Binding Definitions
      soc: renesas: Add r8a7793 SYSC PM Domain Binding Definitions
      soc: renesas: Add r8a7794 SYSC PM Domain Binding Definitions
      soc: renesas: Add r8a7795 SYSC PM Domain Binding Definitions
      ARM: shmobile: timer: Fix preset_lpj leading to too short delays
      ARM: dts: r8a7790: Add SCIF2 clock
      ARM: dts: r8a7790: Add SCIF2 device node
      ARM: dts: sh73a0: Correct interrupt type for ARM TWD
      ARM: dts: r8a7779: Correct interrupt type for ARM TWD
      ARM: dts: kzm9g: Configure NMI key as wake-up source
      ARM: dts: omap5-board-common: DT spelling s/interrupt-name/interrupt-names/
      ARM: dts: omap5-cm-t54: DT spelling s/interrupt-name/interrupt-names/
      ARM: dts: OMAP36xx: : DT spelling s/#address-cell/#address-cells/
      ARM: dts: r8a7778: Don't disable referenced optional clocks
      ARM: dts: r8a7779: Don't disable referenced optional clocks
      ARM: dts: r8a7790: Don't disable referenced optional clocks
      ARM: dts: r8a7793: Don't disable referenced optional clocks
      ARM: dts: r8a7794: Don't disable referenced optional clocks

Graham Moore (1):
      ARM: dts: socfpga: Add missing clock and interrupt fields for Arria10 DMA

H. Nikolaus Schaller (2):
      ARM: dts: twl6030: describe gpadc
      ARM: dts: omap5-board-common: describe gpadc for Palmas

Hans de Goede (19):
      ARM: dts: sun5i-a13-inet98v-rev2: Remove mmc2 node
      ARM: dts: sun5i-a13-empire-electronix-d709: Remove mmc2 node
      ARM: dts: sun5i: Add dts for Difrence DIT4350 tablet
      ARM: dts: sun6i: Add dts for colorfly e708 q1 tablet
      ARM: dts: sun8i: Add pmic nodes to sun8i-a23-gt90h-v4
      ARM: dts: sun8i: Add backlight / pwm nodes to sun8i-a23-gt90h-v4
      ARM: dts: sun8i: Fix wrong Quad core / a33 compat for sun8i-a23-gt90h-v4
      ARM: dts: sun8i: Fix regulator for mmc0 for sun8i-a23-gt90h-v4
      ARM: dts: sun8i: Add dts file for the Polaroid MID2809PXE4 tablet
      ARM: dts: sun4i: Add dts file for Dserve DSRV9703C tablet
      ARM: dts: sun8i: Add mmc2_8bit_pins to sun8i-h3.dtsi
      ARM: dts: sun8i: Enable IR receiver on Orangepi Plus boards
      ARM: dts: sun8i: Add wifi dt node on Orangepi Plus boards
      ARM: dts: sun8i: Add eMMC dt node on Orangepi Plus boards
      ARM: dts: sun8i: Fix pio nodes Orangepi Plus dts
      ARM: dts: sun8i: Add dts for Orange Pi 2 SBC
      ARM: dts: sun8i: Orangepi plus gpio keys fixes and improvements
      ARM: dts: sun8i: Base Orange Pi Plus dts on the Orange Pi 2 dts
      ARM: dts: sun8i: Add dts file for the Orange Pi One SBC

Heiko Stuebner (20):
      ARM: dts: rockchip: update rk3288-veyron cpu operating points
      ARM: dts: rockchip: fix rk3288 power-domain unit names
      ARM: dts: rockchip: fix missing usbphy unit-names
      ARM: dts: rockchip: clean up gpio-keys nodes
      ARM: dts: rockchip: drop unneeded properties from mipi node
      ARM: dts: rockchip: add missing unitname to cpu_leakage efuse
      ARM: dts: rockchip: add rk3288 edp-phy node
      ARM: dts: rockchip: add rk3288 displayport controller node
      ARM: dts: rockchip: move edp-hpd pin definition into common location
      ARM: dts: rockchip: add startup delay to rk3288-veyron panel-regulators
      ARM: dts: rockchip: add core rk3288-veyron backlight and panel nodes
      ARM: dts: rockchip: add rk3288-veyron-minnie backlight and panel settings
      ARM: dts: rockchip: override edp hpd handling on veyron-pinky and speedy
      ARM: dts: rockchip: simple panel and backlight supplies on veyron boards
      ARM: dts: rockchip: enable the eDP on rk3288 veyron devices
      ARM: dts: rockchip: move rk3036 memory definition to board files
      ARM: dts: rockchip: make rk3288-grf a simple-mfd
      ARM: dts: rockchip: move rk3288 edp phy under the GRF
      dt-bindings: add vendor-prefix for mqmaker
      ARM: dts: rockchip: add MiQi board from mqmaker

Heinrich Schuchardt (2):
      ARM: dts: kirkwood: add kirkwood-ds112.dtb to Makefile
      ARM: dts: kirkwood: add kirkwood-nsa320.dtb to Makefile

Imre Kaloz (1):
      ARM: mvebu: fix GPIO config on the Linksys boards

JM Friedt (1):
      ARM: dts: sun5i-a13-olinuxino-micro: enable USB DRC

Jaehoon Chung (1):
      ARM: dts: exynos: Add MSHC2 DT node for SD card for exynos3250-artik5-eval board

Javier Martinez Canillas (5):
      ARM: dts: omap: add missing unit name to pbias regulator nodes
      ARM: dts: n8x0: remove unneeded unit name for i2c node
      ARM: dts: omap3: add missing unit name to PMU node
      ARM: dts: omap: remove unneeded unit name for sound nodes
      ARM: dts: omap: add missing unit names to bandgap nodes

Jens Kuske (1):
      ARM: dts: sun8i: Enable USB host controllers on Orangepi Plus boards

Jianqun Xu (1):
      dt-bindings: add bindings for Rockchip grf

Joachim Eastwood (12):
      ARM: dts: lpc18xx: add creg-clk node
      ARM: dts: lpc18xx: add rtc node
      ARM: dts: lpc18xx: add adc nodes
      ARM: dts: lpc18xx: add dac node
      ARM: dts: lpc4357-ea4357: add adc0
      ARM: dts: lpc4357-ea4357: add dac
      ARM: dts: lpc4350-hitex-eval: add adc1
      ARM: dts: armv7-m: add unit name to interrupt-controller
      ARM: dts: lpc18xx: remove unit addresses from creg childs
      ARM: dts: lpc4357-ea4357: fix unit name warnings from dtc
      ARM: dts: lpc4350-hitex-eval: fix unit name warnings from dtc
      dt-bindings: phy-lpc18xx-usb-otg: remove unit address from binding

Joel Stanley (3):
      doc/devicetree: Add Aspeed and Tyan to vendor-prefixes
      arm/dts: Add Aspeed ast2400 device tree
      arm/dst: Add Aspeed ast2500 device tree

John Crispin (1):
      dt-bindings: ARM: Mediatek: add MT2701/7623 string to the PMIC wrapper doc

John Keeping (3):
      ARM: dts: rockchip: fix MIPI interrupt on rk3288
      ARM: dts: rockchip: fix audio interrupts on rk3288
      ARM: dts: rockchip: add mipi_dsi to VIO power domain on rk3288

John Stultz (1):
      device-tree: nexus7: Add bq27541 battery interface to dts

Jon Hunter (2):
      ARM: tegra: Add stdout-path for various boards
      ARM: tegra: Correct interrupt type for ARM TWD

Joshua Clayton (1):
      ARM: dts: imx6: fix dtc warnings for ipu endpoints

Justin Waters (2):
      ARM: dts: imx: ba16: Add correct PCIe Tx Values
      ARM: dts: imx6q-ba16: Disable pwm2 by default

Kamil Debski (2):
      ARM: dts: exynos: Add HDMI CEC pin definition to exynos4 pinctrl
      ARM: dts: exynos: Add node for the HDMI CEC device to exynos4

Keerthy (4):
      ARM: dts: am57xx: Introduce commercial grade thermal thresholds
      ARM: dts: am57xx: Introduce industrial grade thermal thresholds
      ARM: dts: am57xx-beagle-x15: Include the commercial grade thresholds
      ARM: dts: am57xx-idk: Include Industrial grade  thermal thresholds

Krzysztof Kozlowski (18):
      ARM: dts: exynos: Add Security SubSystem node to Exynos4
      ARM: dts: exynos: Enable SSS on Trats2
      ARM: dts: exynos: Enable SSS on Odroid X/X2/U3 family
      Merge tag 'clk-v4.7-exynos3250' of git://linuxtv.org/snawrocki/samsung into for-v4.7/dt-exynos3250-artik5
      Merge tag 'samsung-dt-exynos3250-artik5-4.7' into next/dt
      ARM: dts: exynos: Fix DTC unit name warnings in cros-adc-thermistors
      ARM: dts: exynos: Fix DTC unit name warnings in Exynos3250
      ARM: dts: exynos: Fix DTC unit name warnings in Exynos4
      ARM: dts: exynos: Fix DTC unit name warnings in Trats2 board
      ARM: dts: exynos: Fix DTC unit name warnings in Exynos4x12
      ARM: dts: exynos: Fix DTC unit name warnings in Exynos5250
      ARM: dts: exynos: Fix DTC unit name warnings in Exynos542x
      ARM: dts: exynos: Fix DTC unit name warnings in Peach Pit
      ARM: dts: exynos: Fix DTC unit name warnings in SMDK5420
      ARM: dts: exynos: Fix DTC unit name warnings in Exynos5440
      ARM: dts: s5p: Fix DTC unit name warnings in SMDKv210 board
      ARM: dts: exynos: Remove unsupported s2mps11 regulator bindings from Exynos5420 boards
      ARM: dts: exynos: Enable PRNG and SSS for all Exynos4 devices

Lars Persson (1):
      ARM: dts: artpec: update clock bindings in artpec6.dtsi

Lee Jones (8):
      ARM: dts: STi: STiH407: Provide generic (safe) DVFS configuration
      ARM: dts: STi: STiH407: Provide CPU with clocking information
      ARM: dts: STi: STiH407: Link CPU with its voltage supply
      ARM: dts: STi: STiH407: Provide CPU with a means to look-up Major number
      ARM: dts: STi: stih407-family: Add nodes for Mailbox
      ARM: dts: STiH407: Add nodes for RemoteProc
      ARM: dts: STiH407: Move over to using the 'reserved-memory' API for obtaining DMA memory
      ARM: dts: STi: STih407: Switch LPC mode from RTC to Clocksource

Linus Walleij (10):
      ARM: dts: ux500: use the GPIO DT header
      ARM: dts: ux500: use the GIC include header
      Documentation/DT: add blurb for IB2 syscon to Versatile
      ARM: dts: realview: PB11MPCore: define a standard VGA panel
      ARM: dts: realview: PB1176: define a standard VGA panel
      ARM: dts: realview: support all the RealView EB board variants
      ARM: dts: realview: DT support for the PBA8 and PBX-A9
      ARM: dts: nomadik: add accelerometer IRQ and pin setting
      ARM: dts: nomadik: add DMA engine and some channels
      ARM: dts: ux500: configure the accelerometers open drain

Liu Gang (1):
      ARM: dts: ls1021a: Add gpio support for ls1021a platform

Lokesh Vutla (1):
      ARM: dts: am335x: Add initial support for ICEv2 board

Lothar Wa?mann (12):
      ARM: dts: imx6ul: add support for Ka-Ro electronics TXUL modules
      ARM: dts: imx6ul: add support for Ka-Ro electronics TXUL mainboard
      ARM: dts: imx6-tx6: Relicense the Ka-Ro DT files under GPLv2/X11
      ARM: dts: imx6-tx6: cleanup; no functional change
      ARM: dts: imx6-tx6: disable the spi node by default
      ARM: dts: imx6-tx6: remove container node around pinctrl nodes
      ARM: dts: imx6qdl-tx6: add mdio node for ethernet phy
      ARM: dts: imx6-tx6: remove regulator bus
      ARM: dts: imx6-tx6: remove LED pinctrl setting from hoggrp
      ARM: dts: imx6-tx6: enable support for rtscts on UARTs
      ARM: dts: imx6: add support for more Ka-Ro electronics modules
      ARM: dts: imx6: add support for the Ka-Ro electronics 'MB7' baseboard

Ludovic Desroches (1):
      ARM: dts: at91: sama5d2: add chipid node

Maarten Lankhorst (1):
      ARM: tegra: Enable watchdog support for Tegra114 and Tegra124

Maciej S. Szmigiero (1):
      ARM: dts: imx6qdl-udoo: add 7 inch LCD touchscreen panel support

Marc Gonzalez (4):
      ARM: dts: tango4: Initial thermal support
      ARM: dts: tango4: Update DT to match clk driver
      ARM: dts: tango4: Update cpus node for cpufreq
      ARM: dts: tango4: Import watchdog node

Marcel Ziswiler (1):
      ARM: dts: imx6: apalis: parallel lcd display support on ixora

Marcin Niestroj (3):
      ARM: dts: am335x-chili*: Move uart0 description from SOM to board
      ARM: dts: am335x-chili*: Move Ethernet MAC description from SOM to board
      ARM: dts: am335x-chilisom: Enable poweroff PMIC sequence using RTC signal

Marcus Cooper (8):
      ARM: dts: sun4i: Add SPDIF TX pin to the A10
      ARM: dts: sun7i: Add SPDIF TX pin to the A20
      ARM: dts: sun4i: Add the SPDIF clk to the A10
      ARM: dts: sun7i: Add the SPDIF clk to the A20
      ARM: dts: sun4i: Add the SPDIF block to the A10
      ARM: dts: sun7i: Add the SPDIF block to the A20
      ARM: dts: sun4i: Add SPDIF to the Mele A1000
      ARM: dts: sun7i: Add SPDIF to the Itead Ibox

Marek Szyprowski (1):
      ARM: dts: exynos: Enable the HDMI CEC device on Exynos4412 Odroid boards

Marek Vasut (6):
      ARM: dts: socfpga: Drop phy-addr OF property from CV dtsi
      ARM: dts: socfpga: Drop gmac0 from CV dtsi
      ARM: dts: socfpga: Add support for HPS LEDs on SoCKit
      ARM: dts: socfpga: Add support for HPS KEYs/SWs on SoCKit
      ARM: dts: socfpga: Add samtec VIN|ING board
      ARM: mx5: dts: Enable USB OTG on M53EVK

Markus Reichl (1):
      ARM: dts: exynos: Add eMMC and SD regulator supplies to Odroid XU3/XU4

Martin Sperl (1):
      dt/bindings: bcm2835: correct description for DMA-int

Masahiro Yamada (2):
      ARM: tegra: Remove redundant ARM_L1_CACHE_SHIFT_6 select
      ARM: dts: uniphier: add NAND pinmux node

Matthew McClintock (10):
      qcom: ipq4019: Add basic board/dts support for IPQ4019 SoC
      dts: ipq4019: Add support for IPQ4019 DK01 board
      qcom: ipq4019: add acc and saw nodes to bring up secondary cores
      qcom: ipq4019: add watchdog node to ipq4019 SoC and DK01 device tree
      qcom: ipq4019: add support for reset via qcom,ps-hold
      qcom: ipq4019: add spi node to ipq4019 SoC and DK01 device tree
      qcom: ipq4019: add i2c node to ipq4019 SoC and DK01 device tree
      qcom: ipq4019: add cpu operating points for cpufreq support
      qcom: ipq4019: add crypto nodes to ipq4019 SoC and DK01 device tree
      qcom: ipq4019: add DMA nodes to ipq4019 SoC and DK01 device tree

Maxime Ripard (6):
      ARM: sun5i: dt: Add pll3 and pll7 clocks
      ARM: sun5i: Add TV encoder gate to the DTSI
      ARM: sun5i: Add DRAM gates
      ARM: sun5i: a13: Add display and TCON clocks
      ARM: sun5i: r8: Add display blocks to the DTSI
      ARM: sun5i: chip: Enable the TV Encoder

Mike Williams (3):
      ARM: dts: at91: sama5d2: add trng node
      ARM: dts: at91: sama5d3: add trng node
      ARM: dts: at91: sama5d4: add trng node

Minghuan Lian (1):
      ARM: dts: ls1021a: add SCFG MSI dts node

Misael Lopez Cruz (1):
      ARM: dts: dra7: Use eDMA and add DAT port address for McASP3

Neil Armstrong (6):
      dt-bindings: irq: arm,versatile-fpga: add compatible string for OX810SE SoC
      dt-bindings: Add Oxford Semiconductor to vendor prefixes
      ARM: boot: dts: Add Oxford Semiconductor OX810SE dtsi
      dt-bindings: Add OXNAS bindings
      dt-bindings: Add Western Digital to vendor prefixes
      ARM: boot: dts: Add Western Digital My Book World Edition device tree

Nicolas Ferre (6):
      ARM: dts: at91: sama5d2: add LCD controller
      ARM: dts: at91: sama5d4: add watchdog interrupt property
      ARM: dts: at91: sama5d2: add shutdown controller node
      ARM: dts: at91: sama5d2: add slow clock to watchdog node
      ARM: dts: at91: VInCo: fix phy reset gpio flag
      ARM: dts: at91: at91sam9g45 family: reduce the trng register map size

Nishanth Menon (4):
      ARM: dts: dra7-evm: Add missing regulators
      ARM: dts: k2*: Rename the k2* files to keystone-k2* files
      ARM: dts: Add support for dra72-evm rev C (SR2.0)
      ARM: dts: AM57xx/DRA7: Update SoC voltage rail limits to match data sheet

Olliver Schinagl (1):
      ARM: dts: sunxi: Add a olinuxino-lime2-emmc

Olof Johansson (7):
      Merge tag 'at91-dt' of git://git.kernel.org/.../nferre/linux-at91 into next/dt
      Merge tag 'renesas-arm64-dt-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/dt
      Merge tag 'renesas-cleanup-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/dt
      Merge tag 'versatile-dts-1' of git://git.kernel.org/.../linusw/linux-integrator into next/dt
      Merge tag 'lpc18xx_dts_for_4.7' of https://github.com/manabian/linux-lpc into next/dt
      Merge tag 'socfpga_dts_for_v4.7' of git://git.kernel.org/.../dinguyen/linux into next/dt
      Merge tag 'v4.7-rockchip-dts32-1' of git://git.kernel.org/.../mmind/linux-rockchip into next/dt

Pankaj Dubey (3):
      clk: samsung: exynos3250: Add UART2 clock
      ARM: dts: exynos: Add UART2 DT node for Exynos3250 SoC
      ARM: dts: change SROM node compatible from generic to model specific

Paul Kocialkowski (5):
      devicetree: bindings: Add vendor prefix for Amazon.com, Inc.
      ARM: dts: Amazon Kindle Fire (first generation) codename kc1 basic support
      ARM: dts: omap4-kc1: USB OTG support
      ARM: dts: omap4-kc1: LEDs support
      ARM: dts: omap4-kc1: Power off support

Peter Ujfalusi (8):
      ARM: dts: dra7: Move the sDMA crossbar node under l4_cfg/scm
      ARM: dts: dra7: Enable eDMA
      ARM: dts: dra7-evm: Enable AFIFO use for McASP3
      ARM: dts: dra72-evm: Enable AFIFO use for McASP3
      ARM: dts: am57xx-beagle-x15: Move clkout2 source selection to codec node
      ARM: dts: am57xx-beagle-x15: Enable AFIFO use for McASP3
      ARM: dts: dra7xx: Correct mcasp8_ahclkx_mux name
      ARM: dts: dra7: Add nodes for McASP1/2/4/5/6/7/8

Petr Kulhavy (3):
      ARM: DTS: da850: fix missing #gpio-cells in gpio node
      ARM: DTS: da850: add node for i2c1
      ARM: davinci: da8xx-dt: add OF_DEV_AUXDATA entry for i2c1

Priit Laes (4):
      ARM: sun4i: dt: Enable dram gate 5 (tve0 clock) for simplefb TV output
      ARM: sun7i: dt: Enable dram gate 5 (tve0 clock) for simplefb TV output
      ARM: sun4i: dt: Add pll3 and pll7 clocks
      ARM: sun7i: dt: Add pll3 and pll7 clocks

Rafa? Mi?ecki (3):
      ARM: BCM5301X: Set vcc-gpio for USB controllers of few devices
      ARM: BCM5301X: Enable earlycon on tested devices
      ARM: BCM5301X: Add DT entry for SPI controller and NOR flash

Ralf Ramsauer (2):
      ARM: tegra: Fix copy/paste typo in several DTS includes
      ARM: tegra: Add high speed UARTs to Jetson TK1 device tree

Ramesh Shanmugasundaram (2):
      arm64: dts: r8a7795: Add CAN external clock support
      arm64: dts: r8a7795: Add CAN support

Reinder de Haan (2):
      ARM: dts: sun8i: Add support for H3 usb clocks
      ARM: dts: sun8i: Add usbphy and usb host controller nodes

Roger Quadros (15):
      ARM: dts: dra7-evm: Fix comment about NAND configuration
      ARM: dts: omap24xx: Enable gpio and interrupt controller for GPMC
      ARM: dts: omap4: Enable gpio and interrupt controller for GPMC
      ARM: dts: omap5: Enable gpio and interrupt controller for GPMC
      ARM: dts: dra7: Enable gpio controller for GPMC
      ARM: dts: am335x: Enable gpio controller for GPMC
      ARM: dts: am4372: Enable gpio controller for GPMC
      ARM: dts: omap3: Enable gpio controller for GPMC
      ARM: dts: dm814x: Enable gpio controller for GPMC
      ARM: dts: dm816x: Enable gpio controller for GPMC
      ARM: dts: dra7x-evm: Provide NAND ready pin
      ARM: dts: am437x: Provide NAND ready pin
      ARM: dts: am335x: Provide NAND ready pin
      ARM: dts: omap3-beagle: Provide NAND ready pin
      ARM: dts: dra7xx: Fix compatible string for PCF8575 chip

Roger Shimizu (1):
      ARM: dts: orion5x: add device tree for kurobox-pro

Sascha Hauer (1):
      dt-bindings: MediaTek: Add binding document for the AUXADC

Schuyler Patton (1):
      ARM: dts: AM572x-IDK Initial Support

Sebastian Reichel (5):
      ARM: dts: n9/n950: regulator configuration
      ARM: dts: OMAP3-N950: Add Keypad Matrix
      ARM: dts: OMAP3-N950: Add Vibrator
      ARM: dts: Enable N950 keyboard sleep leds by default
      ARM: dts: OMAP3-N950: Add Keypad Slide Switch

Sergio Prado (1):
      ARM: dts: imx6: Add dts for Embest MarS Board

Shawn Lin (1):
      ARM: dts: rockchip: remove broken-cd from emmc and sdio

Simon Horman (39):
      arm64: dts: r8a7795: Use USB3.0 fallback compatibility string
      ARM: dts: lager: use generic pinctrl properties
      ARM: dts: ape6evm: use generic pinctrl properties
      ARM: dts: armadillo800eva: use generic pinctrl properties
      ARM: dts: bockw: use generic pinctrl properties
      ARM: dts: marzen: use generic pinctrl properties
      ARM: dts: koelsch: use generic pinctrl properties
      ARM: dts: porter: use generic pinctrl properties
      ARM: dts: gose: use generic pinctrl properties
      ARM: dts: alt: use generic pinctrl properties
      ARM: dts: silk: use generic pinctrl properties
      ARM: dts: kzm9g: use generic pinctrl properties
      ARM: dts: kzm9d: use generic pinctrl properties
      ARM: dts: r8a7790: Remove unnecessary clock-output-names properties
      ARM: dts: r7s72100: Remove unnecessary clock-output-names properties
      ARM: dts: r8a7740: Remove unnecessary clock-output-names properties
      ARM: dts: r8a7778: Remove unnecessary clock-output-names properties
      ARM: dts: r8a7779: Remove unnecessary clock-output-names properties
      ARM: dts: r8a7791: Remove unnecessary clock-output-names properties
      ARM: dts: r8a7793: Remove unnecessary clock-output-names properties
      ARM: dts: r8a7794: Remove unnecessary clock-output-names properties
      ARM: dts: gose: Remove unnecessary clock-output-names properties
      ARM: dts: koelsch: Remove unnecessary clock-output-names properties
      ARM: dts: porter: Remove unnecessary clock-output-names properties
      ARM: dts: lager: Remove unnecessary clock-output-names properties
      ARM: dts: r8a73a4: Remove unnecessary clock-output-names properties
      ARM: dts: sh73a0: Remove unnecessary clock-output-names properties
      ARM: dts: r8a7790: use fallback jpu compatibility string
      ARM: dts: r8a7791: use fallback jpu compatibility string
      ARM: dts: r8a7791: use fallback can compatibility string
      ARM: dts: r8a7790: use fallback can compatibility string
      ARM: dts: r8a7794: add CAN clocks to device tree
      ARM: dts: r8a7794: add CAN nodes to device tree
      ARM: dts: r8a7793: add CAN clocks to device tree
      ARM: dts: r8a7793: add CAN nodes to device tree
      ARM: dts: r8a7794: add IIC clocks
      ARM: dts: r8a7794: Add IIC nodes
      ARM: dts: r8a7790: Use USB3.0 fallback compatibility string
      ARM: dts: r8a7791: Use USB3.0 fallback compatibility string

Sjoerd Simons (2):
      ARM: dts: r8a7791: Don't disable referenced optional clocks
      Revert "ARM: dts: porter: Enable SCIF_CLK frequency and pins"

Soeren Moch (1):
      ARM: dts: imx6q-tbs2910: fix fec reset polarity

Srinivas Kandagatla (13):
      ARM: dts: apq8064: fix the pinctrls for i2c and spi
      ARM: dts: apq8064: add support to gsbi1 uart
      ARM: dts: apq8064: add gsbi7 i2c support
      ARM: dts: db600c: add board support with serial
      ARM: dts: db600c: add pmic regulator supplies
      ARM: dts: db600c: Add eMMC and SD card support
      ARM: dts: db600c: add usb support
      ARM: dts: db600c: add pcie support
      ARM: dts: db600c: add on board sata support.
      ARM: dts: db600c: Add on board leds support
      ARM: dts: db600c: add i2c support
      ARM: dts: db600c: add spi support
      ARM: dts: db600c: add support to magnetometer

Stefan Agner (4):
      ARM: dts: vf-colibri: alias the primary FEC as ethernet0
      ARM: dts: vf-colibri: increase NAND clock speed
      ARM: dts: vfxxx: add missing reg properties
      ARM: dts: ls1021a: add pix clock to DCU dts node

Stefan Wahren (1):
      ARM: bcm2835: add CPU node for ARM core

Sudeep Holla (2):
      ARM: tegra: Replace legacy *,wakeup property with wakeup-source
      ARM: dts: vexpress: fix node name unit-address presence warnings

Suman Anna (2):
      ARM: dts: DRA7: Enable Timers 13 through 16
      ARM: dts: DRA7: Add timer12 node

Sylvain Lemieux (3):
      ARM: dts: lpc32xx: add clock properties to spi nodes
      ARM: dts: phy3250: enable ssp0
      ARM: dts: lpc32xx: disabled ssp0/spi1 & ssp1/spi2 by default

Tero Kristo (9):
      ARM: dts: omap3: fix clock node definitions to avoid build warnings
      ARM: dts: omap2: fix clock node definitions to avoid build warnings
      ARM: dts: omap4: fix clock node definitions to avoid build warnings
      ARM: dts: am33xx: fix clock node definitions to avoid build warnings
      ARM: dts: am43xx: fix clock node definitions to avoid build warnings
      ARM: dts: dm81x: fix clock node definitions to avoid build warnings
      ARM: dts: dra7: fix clock node definitions to avoid build warnings
      ARM: dts: omap5: fix clock node definitions to avoid build warnings
      ARM: dts: am43xx: add support for clkout1 clock

Thor Thayer (2):
      ARM: dts: socfpga: Add Altera Arria10 L2 Cache EDAC devicetree entry
      ARM: dts: socfpga: Add Altera Arria10 OCRAM EDAC devicetree entry

Tony Lindgren (1):
      ARM: dts: Add clocks for dm814x ADPLL

Ulrich Hecht (2):
      ARM: dts: r8a7793: Add SDHI controllers
      ARM: dts: gose: Enable SDHI controllers

Uwe Kleine-K?nig (3):
      ARM: dts: imx25-pinfunc: add all UART mux modes
      ARM: dts: imx25-pinfunc: remove SION for pins with an UART handshaking input mode
      ARM: dts: imx28: add alternative pinmuxing for mac0

Vignesh R (3):
      ARM: dts: keystone: Add aliases for SPI nodes
      ARM: dts: dra7x: Remove QSPI pinmux
      ARM: dts: dra7x: Support QSPI MODE-0 operation at 64MHz

Vitaly Andrianov (1):
      ARM: keystone: dts: add psci command definition

Vladimir Murzin (2):
      ARM: dts: introduce MPS2 AN385/AN386
      ARM: dts: introduce MPS2 AN399/AN400

Vladimir Zapolskiy (10):
      ARM: dts: lpc32xx: set default clock rate of HCLK PLL
      dt-bindings: interrupt-controllers: add description of SIC1 and SIC2
      ARM: dts: lpc32xx: reparent SIC1 and SIC2 interrupts from MIC
      ARM: dts: lpc32xx: ea3250: avoid extension of device nodes by absolute path
      ARM: dts: lpc32xx: ea3250: add NAND partitions device node
      ARM: dts: lpc32xx: ea3250: fix Atmel at24 eeprom vendor
      ARM: dts: lpc32xx: ea3250: add SoC name prefix to board dts file
      ARM: dts: lpc32xx: phy3250: avoid extension of device nodes by absolute path
      ARM: dts: lpc32xx: phy3250: add NAND partitions device node
      ARM: dts: lpc32xx: phy3250: add SoC name prefix to board dts file

Wolfram Sang (2):
      ARM: dts: r8a7790: lager: Enable UHS-I SDR-50
      ARM: dts: r8a7790: fix max-frequency for SDHI

Yakir Yang (1):
      ARM: dts: rockchip: add i2c nodes for RK3228 SoCs

Yegor Yefremov (4):
      ARM: dts: am335x-baltos-ir5221: use dedicated RTS/CTS signals
      ARM: dts: split am335x-baltos-ir5221 into dts and dtsi files
      ARM: dts: add DTS for Baltos IR3220
      ARM: dts: add DTS for Baltos IR2110

 Documentation/devicetree/bindings/arm/arm-boards   |   8 +
 .../devicetree/bindings/arm/atmel-at91.txt         |   2 +-
 .../devicetree/bindings/arm/omap/omap.txt          |   6 +
 Documentation/devicetree/bindings/arm/oxnas.txt    |   9 +
 Documentation/devicetree/bindings/arm/rockchip.txt |   4 +
 .../bindings/arm/samsung/samsung-boards.txt        |   2 +
 .../devicetree/bindings/dma/fsl-imx-sdma.txt       |  27 +
 .../arm,versatile-fpga-irq.txt                     |   2 +-
 .../brcm,bcm2835-armctrl-ic.txt                    |   4 +-
 .../interrupt-controller/nxp,lpc3220-mic.txt       |  70 +-
 .../bindings/phy/phy-lpc18xx-usb-otg.txt           |   2 +-
 .../bindings/power/renesas,rcar-sysc.txt           |  48 +
 .../devicetree/bindings/soc/mediatek/auxadc.txt    |  21 +
 .../devicetree/bindings/soc/mediatek/pwrap.txt     |   1 +
 .../devicetree/bindings/soc/rockchip/grf.txt       |  35 +
 Documentation/devicetree/bindings/spi/ti_qspi.txt  |   7 +
 .../devicetree/bindings/vendor-prefixes.txt        |   6 +
 MAINTAINERS                                        |   2 +-
 arch/arm/boot/dts/Makefile                         |  67 +-
 arch/arm/boot/dts/am335x-baltos-ir2110.dts         |  71 ++
 arch/arm/boot/dts/am335x-baltos-ir3220.dts         | 119 +++
 arch/arm/boot/dts/am335x-baltos-ir5221.dts         | 398 +--------
 arch/arm/boot/dts/am335x-baltos.dtsi               | 408 +++++++++
 arch/arm/boot/dts/am335x-chiliboard.dts            |  75 ++
 arch/arm/boot/dts/am335x-chilisom.dtsi             |  77 +-
 arch/arm/boot/dts/am335x-cm-t335.dts               |   1 +
 arch/arm/boot/dts/am335x-evm.dts                   |   1 +
 arch/arm/boot/dts/am335x-icev2.dts                 | 306 +++++++
 arch/arm/boot/dts/am335x-igep0033.dtsi             |   1 +
 arch/arm/boot/dts/am335x-phycore-som.dtsi          |   1 +
 arch/arm/boot/dts/am335x-shc.dts                   |   2 +-
 arch/arm/boot/dts/am33xx-clocks.dtsi               |  90 +-
 arch/arm/boot/dts/am33xx.dtsi                      |   8 +-
 arch/arm/boot/dts/am35xx-clocks.dtsi               |  20 +-
 arch/arm/boot/dts/am4372.dtsi                      |  14 +-
 arch/arm/boot/dts/am437x-gp-evm.dts                |   3 +-
 arch/arm/boot/dts/am43x-epos-evm.dts               |   3 +-
 arch/arm/boot/dts/am43xx-clocks.dtsi               | 170 ++--
 arch/arm/boot/dts/am572x-idk.dts                   |  85 ++
 arch/arm/boot/dts/am57xx-beagle-x15.dts            |  14 +-
 arch/arm/boot/dts/am57xx-cl-som-am57x.dts          |   2 +-
 arch/arm/boot/dts/am57xx-commercial-grade.dtsi     |  23 +
 arch/arm/boot/dts/am57xx-idk-common.dtsi           | 304 +++++++
 arch/arm/boot/dts/am57xx-industrial-grade.dtsi     |  23 +
 arch/arm/boot/dts/arm-realview-eb-11mp-revb.dts    |  93 ++
 arch/arm/boot/dts/arm-realview-eb-11mp.dts         |  74 ++
 arch/arm/boot/dts/arm-realview-eb-a9mp.dts         |  70 ++
 arch/arm/boot/dts/arm-realview-eb-mp.dtsi          | 225 +++++
 arch/arm/boot/dts/arm-realview-eb.dts              | 166 ++++
 arch/arm/boot/dts/arm-realview-eb.dtsi             | 453 ++++++++++
 arch/arm/boot/dts/arm-realview-pb1176.dts          |  40 +
 arch/arm/boot/dts/arm-realview-pb11mp.dts          |  19 +-
 arch/arm/boot/dts/arm-realview-pba8.dts            | 178 ++++
 arch/arm/boot/dts/arm-realview-pbx-a9.dts          | 229 +++++
 arch/arm/boot/dts/arm-realview-pbx.dtsi            | 542 ++++++++++++
 arch/arm/boot/dts/armada-385-linksys.dtsi          |   6 +-
 arch/arm/boot/dts/armada-xp-linksys-mamba.dts      |   4 +-
 arch/arm/boot/dts/armv7-m.dtsi                     |   2 +-
 arch/arm/boot/dts/artpec6.dtsi                     |  99 +--
 arch/arm/boot/dts/aspeed-ast2500-evb.dts           |  25 +
 arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts      |  25 +
 arch/arm/boot/dts/aspeed-g4.dtsi                   | 161 ++++
 arch/arm/boot/dts/aspeed-g5.dtsi                   | 170 ++++
 arch/arm/boot/dts/at91-sama5d2_xplained.dts        |   9 +
 arch/arm/boot/dts/at91-vinco.dts                   |   4 +-
 arch/arm/boot/dts/at91sam9g45.dtsi                 |   2 +-
 arch/arm/boot/dts/bcm2835-rpi-a-plus.dts           |   4 +
 arch/arm/boot/dts/bcm2835-rpi-a.dts                |   4 +
 arch/arm/boot/dts/bcm2835-rpi-b-plus.dts           |   4 +
 arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts           |   4 +
 arch/arm/boot/dts/bcm2835-rpi-b.dts                |   4 +
 arch/arm/boot/dts/bcm2835-rpi.dtsi                 |   9 +
 arch/arm/boot/dts/bcm2835.dtsi                     |  11 +
 arch/arm/boot/dts/bcm2836-rpi-2-b.dts              |   4 +
 arch/arm/boot/dts/bcm283x.dtsi                     |  47 +
 arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts  |  10 +-
 arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts       |   6 +-
 arch/arm/boot/dts/bcm4708-netgear-r6250.dts        |  17 +-
 arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts      |   6 +-
 arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts |   2 +-
 arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts  |   5 +
 arch/arm/boot/dts/bcm4709-netgear-r8000.dts        |   8 +
 arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts      |   6 +-
 arch/arm/boot/dts/bcm5301x.dtsi                    |  32 +
 arch/arm/boot/dts/cros-adc-thermistors.dtsi        |   8 +-
 arch/arm/boot/dts/da850-enbw-cmc.dts               |  14 +-
 arch/arm/boot/dts/da850-evm.dts                    |  26 +-
 arch/arm/boot/dts/da850.dtsi                       |  95 +-
 arch/arm/boot/dts/dm814x-clocks.dtsi               | 253 +++++-
 arch/arm/boot/dts/dm814x.dtsi                      |   2 +
 arch/arm/boot/dts/dm816x-clocks.dtsi               |  42 +-
 arch/arm/boot/dts/dm816x.dtsi                      |   2 +
 arch/arm/boot/dts/dra62x-clocks.dtsi               |  26 +
 arch/arm/boot/dts/dra7-evm.dts                     |  70 +-
 arch/arm/boot/dts/dra7.dtsi                        | 200 ++++-
 arch/arm/boot/dts/dra72-evm-common.dtsi            | 817 +++++++++++++++++
 arch/arm/boot/dts/dra72-evm-revc.dts               |  73 ++
 arch/arm/boot/dts/dra72-evm.dts                    | 835 +-----------------
 arch/arm/boot/dts/dra7xx-clocks.dtsi               | 376 ++++----
 arch/arm/boot/dts/emev2-kzm9d.dts                  |   4 +-
 arch/arm/boot/dts/exynos3250-artik5-eval.dts       |  43 +
 arch/arm/boot/dts/exynos3250-artik5.dtsi           | 334 +++++++
 arch/arm/boot/dts/exynos3250-monk.dts              |  12 +-
 arch/arm/boot/dts/exynos3250-pinctrl.dtsi          |  80 ++
 arch/arm/boot/dts/exynos3250-rinato.dts            |  71 +-
 arch/arm/boot/dts/exynos3250.dtsi                  |  27 +-
 arch/arm/boot/dts/exynos4.dtsi                     |  27 +-
 arch/arm/boot/dts/exynos4210-pinctrl.dtsi          |   7 +
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi    |   4 +
 arch/arm/boot/dts/exynos4412-trats2.dts            |  16 +-
 arch/arm/boot/dts/exynos4x12-pinctrl.dtsi          |   7 +
 arch/arm/boot/dts/exynos4x12.dtsi                  |   2 +-
 arch/arm/boot/dts/exynos5.dtsi                     |   4 +-
 arch/arm/boot/dts/exynos5250-arndale.dts           |   2 +-
 arch/arm/boot/dts/exynos5250-smdk5250.dts          |   8 +-
 arch/arm/boot/dts/exynos5250-snow-common.dtsi      |  12 +-
 arch/arm/boot/dts/exynos5250-spring.dts            |   2 +-
 arch/arm/boot/dts/exynos5250.dtsi                  |  10 +-
 arch/arm/boot/dts/exynos5410-smdk5410.dts          |   2 +-
 arch/arm/boot/dts/exynos5410.dtsi                  |   4 +-
 arch/arm/boot/dts/exynos5420-arndale-octa.dts      |   7 -
 arch/arm/boot/dts/exynos5420-peach-pit.dts         |   6 +-
 arch/arm/boot/dts/exynos5420-smdk5420.dts          |   9 +-
 arch/arm/boot/dts/exynos5420.dtsi                  |  13 +-
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |  24 +-
 arch/arm/boot/dts/exynos5440.dtsi                  |   4 +-
 arch/arm/boot/dts/imx25-pinfunc.h                  | 124 +--
 arch/arm/boot/dts/imx28-m28.dtsi                   |  26 -
 arch/arm/boot/dts/imx28.dtsi                       |  26 +
 arch/arm/boot/dts/imx31.dtsi                       |   8 +
 arch/arm/boot/dts/imx35.dtsi                       |   8 +
 arch/arm/boot/dts/imx53-m53evk.dts                 |  21 +-
 arch/arm/boot/dts/imx6dl-riotboard.dts             |   2 +-
 arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts          |  42 +-
 arch/arm/boot/dts/imx6dl-tx6s-8034.dts             | 237 +++++
 arch/arm/boot/dts/imx6dl-tx6s-8035.dts             | 253 ++++++
 arch/arm/boot/dts/imx6dl-tx6u-801x.dts             |  42 +-
 arch/arm/boot/dts/imx6dl-tx6u-8033.dts             | 248 ++++++
 arch/arm/boot/dts/imx6dl-tx6u-811x.dts             |  60 +-
 arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts         | 255 ++++++
 arch/arm/boot/dts/imx6dl.dtsi                      |   2 +-
 arch/arm/boot/dts/imx6q-apalis-ixora.dts           |  45 +
 arch/arm/boot/dts/imx6q-b450v3.dts                 |   5 +-
 arch/arm/boot/dts/imx6q-b650v3.dts                 |   5 +-
 arch/arm/boot/dts/imx6q-b850v3.dts                 |  33 +-
 arch/arm/boot/dts/imx6q-ba16.dtsi                  |   6 +-
 arch/arm/boot/dts/imx6q-gw5400-a.dts               |   2 +-
 arch/arm/boot/dts/imx6q-marsboard.dts              | 403 +++++++++
 arch/arm/boot/dts/imx6q-tbs2910.dts                |   4 +-
 arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts       |  42 +-
 arch/arm/boot/dts/imx6q-tx6q-1010.dts              |  42 +-
 arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts       |  72 +-
 arch/arm/boot/dts/imx6q-tx6q-1020.dts              |  72 +-
 arch/arm/boot/dts/imx6q-tx6q-1036.dts              | 252 ++++++
 arch/arm/boot/dts/imx6q-tx6q-1110.dts              |  60 +-
 arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts          | 264 ++++++
 arch/arm/boot/dts/imx6q.dtsi                       |  18 +-
 arch/arm/boot/dts/imx6qdl-apalis.dtsi              |   2 +-
 arch/arm/boot/dts/imx6qdl-apf6dev.dtsi             |   2 +-
 arch/arm/boot/dts/imx6qdl-gw52xx.dtsi              |   2 +-
 arch/arm/boot/dts/imx6qdl-gw53xx.dtsi              |   2 +-
 arch/arm/boot/dts/imx6qdl-gw54xx.dtsi              |   2 +-
 arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi           |   2 +-
 arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi       |   2 +-
 arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi          |   2 +-
 arch/arm/boot/dts/imx6qdl-rex.dtsi                 |   2 +-
 arch/arm/boot/dts/imx6qdl-sabrelite.dtsi           |   2 +-
 arch/arm/boot/dts/imx6qdl-sabresd.dtsi             |  30 +-
 arch/arm/boot/dts/imx6qdl-tx6.dtsi                 | 788 +++++++++--------
 arch/arm/boot/dts/imx6qdl-udoo.dtsi                |  98 ++-
 arch/arm/boot/dts/imx6qdl-wandboard.dtsi           |   2 +-
 arch/arm/boot/dts/imx6qdl.dtsi                     |  32 +-
 arch/arm/boot/dts/imx6qp-nitrogen6_max.dts         |  59 ++
 arch/arm/boot/dts/imx6sx-nitrogen6sx.dts           | 709 +++++++++++++++
 arch/arm/boot/dts/imx6sx-sdb-sai.dts               |  67 ++
 arch/arm/boot/dts/imx6sx-sdb.dts                   |   2 +
 arch/arm/boot/dts/imx6sx-sdb.dtsi                  |  16 +
 arch/arm/boot/dts/imx6sx.dtsi                      |   8 +-
 arch/arm/boot/dts/imx6ul-14x14-evk.dts             |  74 ++
 arch/arm/boot/dts/imx6ul-pico-hobbit.dts           | 516 +++++++++++
 arch/arm/boot/dts/imx6ul-tx6ul-0010.dts            |  53 ++
 arch/arm/boot/dts/imx6ul-tx6ul-0011.dts            |  68 ++
 arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts       | 271 ++++++
 arch/arm/boot/dts/imx6ul-tx6ul.dtsi                | 973 +++++++++++++++++++++
 arch/arm/boot/dts/imx6ul.dtsi                      |  12 +-
 .../{k2e-clocks.dtsi => keystone-k2e-clocks.dtsi}  |   0
 .../boot/dts/{k2e-evm.dts => keystone-k2e-evm.dts} |   2 +-
 .../{k2e-netcp.dtsi => keystone-k2e-netcp.dtsi}    |   0
 arch/arm/boot/dts/{k2e.dtsi => keystone-k2e.dtsi}  |   4 +-
 ...{k2hk-clocks.dtsi => keystone-k2hk-clocks.dtsi} |   0
 .../dts/{k2hk-evm.dts => keystone-k2hk-evm.dts}    |   2 +-
 .../{k2hk-netcp.dtsi => keystone-k2hk-netcp.dtsi}  |   0
 .../arm/boot/dts/{k2hk.dtsi => keystone-k2hk.dtsi} |   4 +-
 .../{k2l-clocks.dtsi => keystone-k2l-clocks.dtsi}  |   0
 .../boot/dts/{k2l-evm.dts => keystone-k2l-evm.dts} |   2 +-
 .../{k2l-netcp.dtsi => keystone-k2l-netcp.dtsi}    |   0
 arch/arm/boot/dts/{k2l.dtsi => keystone-k2l.dtsi}  |   4 +-
 arch/arm/boot/dts/keystone.dtsi                    |  11 +
 arch/arm/boot/dts/kirkwood-6192.dtsi               |   4 +-
 arch/arm/boot/dts/kirkwood-6281.dtsi               |   4 +-
 arch/arm/boot/dts/kirkwood-6282.dtsi               |   4 +-
 arch/arm/boot/dts/kirkwood-98dx4122.dtsi           |   4 +-
 arch/arm/boot/dts/kirkwood-b3.dts                  |  19 +-
 arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts   |   4 +-
 arch/arm/boot/dts/kirkwood-cloudbox.dts            |   2 +-
 arch/arm/boot/dts/kirkwood-db-88f6281.dts          |  14 +-
 arch/arm/boot/dts/kirkwood-db-88f6282.dts          |  20 +-
 arch/arm/boot/dts/kirkwood-dir665.dts              |  20 +-
 arch/arm/boot/dts/kirkwood-dnskw.dtsi              |   6 +-
 arch/arm/boot/dts/kirkwood-ds111.dts               |   2 +-
 arch/arm/boot/dts/kirkwood-ds112.dts               |   6 +-
 arch/arm/boot/dts/kirkwood-ds212.dts               |   2 +-
 arch/arm/boot/dts/kirkwood-ds411.dts               |   6 +-
 arch/arm/boot/dts/kirkwood-ds411slim.dts           |   2 +-
 arch/arm/boot/dts/kirkwood-ib62x0.dts              |   4 +-
 arch/arm/boot/dts/kirkwood-iconnect.dts            |  22 +-
 arch/arm/boot/dts/kirkwood-km_common.dtsi          |  20 +-
 arch/arm/boot/dts/kirkwood-laplug.dts              |  19 +-
 arch/arm/boot/dts/kirkwood-linkstation.dtsi        |  17 +-
 arch/arm/boot/dts/kirkwood-linksys-viper.dts       | 240 +++++
 arch/arm/boot/dts/kirkwood-lsxl.dtsi               |  16 +-
 arch/arm/boot/dts/kirkwood-mplcec4.dts             |  18 +-
 arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts     |  24 +-
 arch/arm/boot/dts/kirkwood-nas2big.dts             |  18 +-
 .../boot/dts/kirkwood-netgear_readynas_duo_v2.dts  |  20 +-
 .../boot/dts/kirkwood-netgear_readynas_nv+_v2.dts  |  23 +-
 arch/arm/boot/dts/kirkwood-netxbig.dtsi            |   8 +-
 arch/arm/boot/dts/kirkwood-ns2-common.dtsi         |   4 +-
 arch/arm/boot/dts/kirkwood-nsa310.dts              |  18 +-
 arch/arm/boot/dts/kirkwood-nsa320.dts              |  31 +-
 arch/arm/boot/dts/kirkwood-nsa325.dts              |  17 +-
 arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi      |  24 +-
 arch/arm/boot/dts/kirkwood-openblocks_a6.dts       |   2 +-
 arch/arm/boot/dts/kirkwood-openblocks_a7.dts       |   2 +-
 arch/arm/boot/dts/kirkwood-openrd.dtsi             |  14 +-
 arch/arm/boot/dts/kirkwood-pogoplug-series-4.dts   |   2 +-
 arch/arm/boot/dts/kirkwood-rd88f6192.dts           |  20 +-
 arch/arm/boot/dts/kirkwood-rd88f6281-a.dts         |   2 +-
 arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts        |   2 +-
 arch/arm/boot/dts/kirkwood-rd88f6281.dtsi          |  20 +-
 arch/arm/boot/dts/kirkwood-rs212.dts               |   6 +-
 arch/arm/boot/dts/kirkwood-synology.dtsi           |  22 +-
 arch/arm/boot/dts/kirkwood-t5325.dts               |  22 +-
 arch/arm/boot/dts/kirkwood-ts219-6281.dts          |   4 +-
 arch/arm/boot/dts/kirkwood-ts219-6282.dts          |  16 +-
 arch/arm/boot/dts/kirkwood-ts219.dtsi              |  20 +-
 arch/arm/boot/dts/kirkwood-ts419-6282.dts          |  15 +-
 arch/arm/boot/dts/kirkwood-ts419.dtsi              |   4 +-
 arch/arm/boot/dts/kirkwood.dtsi                    |   2 +-
 arch/arm/boot/dts/lpc18xx.dtsi                     |  47 +-
 .../boot/dts/{ea3250.dts => lpc3250-ea3250.dts}    | 230 +++--
 arch/arm/boot/dts/lpc3250-phy3250.dts              | 226 +++++
 arch/arm/boot/dts/lpc32xx.dtsi                     |  77 +-
 arch/arm/boot/dts/lpc4350-hitex-eval.dts           |  41 +-
 arch/arm/boot/dts/lpc4357-ea4357-devkit.dts        |  29 +-
 arch/arm/boot/dts/ls1021a.dtsi                     |  65 +-
 .../dts/{rk3288-thermal.dtsi => mps2-an385.dts}    |  96 +-
 arch/arm/boot/dts/mps2-an399.dts                   |  92 ++
 arch/arm/boot/dts/mps2.dtsi                        | 241 +++++
 arch/arm/boot/dts/mt2701.dtsi                      |  19 +
 arch/arm/boot/dts/omap2420-clocks.dtsi             |  38 +-
 arch/arm/boot/dts/omap2420-n8x0-common.dtsi        |   2 +-
 arch/arm/boot/dts/omap2420.dtsi                    |   4 +
 arch/arm/boot/dts/omap2430-clocks.dtsi             |  58 +-
 arch/arm/boot/dts/omap2430.dtsi                    |   6 +-
 arch/arm/boot/dts/omap24xx-clocks.dtsi             | 228 ++---
 arch/arm/boot/dts/omap3-beagle.dts                 |   1 +
 arch/arm/boot/dts/omap3-n9.dts                     |  14 +
 arch/arm/boot/dts/omap3-n950-n9.dtsi               | 151 ++++
 arch/arm/boot/dts/omap3-n950.dts                   |  99 +++
 arch/arm/boot/dts/omap3.dtsi                       |   6 +-
 arch/arm/boot/dts/omap3430es1-clocks.dtsi          |  30 +-
 arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi    |  44 +-
 arch/arm/boot/dts/omap34xx.dtsi                    |   2 +-
 .../omap36xx-am35xx-omap3430es2plus-clocks.dtsi    |  32 +-
 arch/arm/boot/dts/omap36xx-clocks.dtsi             |  14 +-
 .../boot/dts/omap36xx-omap3430es2plus-clocks.dtsi  |  14 +-
 arch/arm/boot/dts/omap36xx.dtsi                    |   4 +-
 arch/arm/boot/dts/omap3xxx-clocks.dtsi             | 276 +++---
 arch/arm/boot/dts/omap4-kc1.dts                    | 182 ++++
 arch/arm/boot/dts/omap4-var-som-om44.dtsi          |   2 +-
 arch/arm/boot/dts/omap4.dtsi                       |   6 +-
 arch/arm/boot/dts/omap443x-clocks.dtsi             |   2 +-
 arch/arm/boot/dts/omap443x.dtsi                    |   2 +-
 arch/arm/boot/dts/omap4460.dtsi                    |   2 +-
 arch/arm/boot/dts/omap446x-clocks.dtsi             |   4 +-
 arch/arm/boot/dts/omap44xx-clocks.dtsi             | 316 +++----
 arch/arm/boot/dts/omap5-board-common.dtsi          |  12 +-
 arch/arm/boot/dts/omap5-cm-t54.dts                 |   2 +-
 arch/arm/boot/dts/omap5.dtsi                       |   6 +-
 arch/arm/boot/dts/omap54xx-clocks.dtsi             | 260 +++---
 arch/arm/boot/dts/orion5x-kuroboxpro.dts           | 127 +++
 arch/arm/boot/dts/ox810se.dtsi                     | 336 +++++++
 arch/arm/boot/dts/phy3250.dts                      | 227 -----
 .../boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi   |  52 ++
 arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts    | 349 ++++++++
 arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts |   6 +
 arch/arm/boot/dts/qcom-apq8064-pins.dtsi           |  39 +
 arch/arm/boot/dts/qcom-apq8064.dtsi                | 135 ++-
 arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts    |  22 +
 arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi      | 112 +++
 arch/arm/boot/dts/qcom-ipq4019.dtsi                | 267 ++++++
 arch/arm/boot/dts/qcom-msm8974.dtsi                |  52 +-
 arch/arm/boot/dts/r7s72100.dtsi                    |  15 +-
 arch/arm/boot/dts/r8a73a4-ape6evm.dts              |  20 +-
 arch/arm/boot/dts/r8a73a4.dtsi                     |  75 +-
 arch/arm/boot/dts/r8a7740-armadillo800eva.dts      |  34 +-
 arch/arm/boot/dts/r8a7740.dtsi                     |  57 +-
 arch/arm/boot/dts/r8a7778-bockw.dts                |  40 +-
 arch/arm/boot/dts/r8a7778.dtsi                     |  22 +-
 arch/arm/boot/dts/r8a7779-marzen.dts               |  36 +-
 arch/arm/boot/dts/r8a7779.dtsi                     |  18 +-
 arch/arm/boot/dts/r8a7790-lager.dts                | 117 +--
 arch/arm/boot/dts/r8a7790.dtsi                     | 125 ++-
 arch/arm/boot/dts/r8a7791-koelsch.dts              |  72 +-
 arch/arm/boot/dts/r8a7791-porter.dts               |  73 +-
 arch/arm/boot/dts/r8a7791.dtsi                     |  92 +-
 arch/arm/boot/dts/r8a7793-gose.dts                 | 162 +++-
 arch/arm/boot/dts/r8a7793.dtsi                     | 127 ++-
 arch/arm/boot/dts/r8a7794-alt.dts                  |  32 +-
 arch/arm/boot/dts/r8a7794-silk.dts                 |  44 +-
 arch/arm/boot/dts/r8a7794.dtsi                     | 158 ++--
 arch/arm/boot/dts/rk3036-evb.dts                   |   5 +
 arch/arm/boot/dts/rk3036-kylin.dts                 |  18 +-
 arch/arm/boot/dts/rk3036.dtsi                      |  71 +-
 arch/arm/boot/dts/rk3066a-bqcurie2.dts             |  11 +-
 arch/arm/boot/dts/rk3066a-rayeager.dts             |   9 +-
 arch/arm/boot/dts/rk3066a.dtsi                     |   6 +-
 arch/arm/boot/dts/rk3188-radxarock.dts             |   7 +-
 arch/arm/boot/dts/rk3188.dtsi                      |   6 +-
 arch/arm/boot/dts/rk3228-evb.dts                   |   8 +-
 arch/arm/boot/dts/rk3228.dtsi                      | 149 ++++
 arch/arm/boot/dts/rk3288-evb.dtsi                  |   8 +-
 arch/arm/boot/dts/rk3288-firefly.dtsi              |   9 +-
 arch/arm/boot/dts/rk3288-miqi.dts                  | 472 ++++++++++
 arch/arm/boot/dts/rk3288-popmetal.dts              |   9 +-
 arch/arm/boot/dts/rk3288-r89.dts                   |   7 +-
 arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi    | 100 +++
 arch/arm/boot/dts/rk3288-veyron-jaq.dts            |  49 +-
 arch/arm/boot/dts/rk3288-veyron-jerry.dts          |   9 +
 arch/arm/boot/dts/rk3288-veyron-minnie.dts         |  44 +
 arch/arm/boot/dts/rk3288-veyron-pinky.dts          |   7 +
 arch/arm/boot/dts/rk3288-veyron-speedy.dts         |  16 +
 arch/arm/boot/dts/rk3288-veyron.dtsi               |  18 +-
 arch/arm/boot/dts/rk3288.dtsi                      | 158 +++-
 arch/arm/boot/dts/s5pv210-smdkv210.dts             |   2 +-
 arch/arm/boot/dts/sama5d2-pinfunc.h                |   4 +-
 arch/arm/boot/dts/sama5d2.dtsi                     |  53 ++
 arch/arm/boot/dts/sama5d3.dtsi                     |   7 +
 arch/arm/boot/dts/sama5d4.dtsi                     |   8 +
 arch/arm/boot/dts/sh73a0-kzm9g.dts                 |  37 +-
 arch/arm/boot/dts/sh73a0.dtsi                      |  89 +-
 arch/arm/boot/dts/socfpga.dtsi                     |   4 +
 arch/arm/boot/dts/socfpga_arria10.dtsi             |  32 +-
 arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts  |   1 +
 arch/arm/boot/dts/socfpga_cyclone5.dtsi            |   6 -
 arch/arm/boot/dts/socfpga_cyclone5_sockit.dts      |  94 +-
 arch/arm/boot/dts/socfpga_cyclone5_socrates.dts    |   1 +
 arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts | 310 +++++++
 arch/arm/boot/dts/ste-ccu9540.dts                  |   2 +-
 arch/arm/boot/dts/ste-dbx5x0.dtsi                  |  92 +-
 arch/arm/boot/dts/ste-href-stuib.dtsi              |   4 +-
 arch/arm/boot/dts/ste-href-tvk1281618.dtsi         |  16 +-
 arch/arm/boot/dts/ste-hrefprev60.dtsi              |   8 +-
 arch/arm/boot/dts/ste-hrefv60plus.dtsi             |   6 +-
 arch/arm/boot/dts/ste-nomadik-nhk15.dts            |  13 +-
 arch/arm/boot/dts/ste-nomadik-stn8815.dtsi         |  38 +
 arch/arm/boot/dts/ste-snowball.dts                 |  19 +-
 arch/arm/boot/dts/stih407-family.dtsi              | 126 ++-
 arch/arm/boot/dts/sun4i-a10-a1000.dts              |  24 +
 arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts   | 281 ++++++
 arch/arm/boot/dts/sun4i-a10.dtsi                   |  76 +-
 arch/arm/boot/dts/sun5i-a13-difrnce-dit4350.dts    | 226 +++++
 .../boot/dts/sun5i-a13-empire-electronix-d709.dts  |  19 +-
 arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts      |  15 -
 arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts    |  41 +
 arch/arm/boot/dts/sun5i-a13.dtsi                   |  66 +-
 arch/arm/boot/dts/sun5i-r8-chip.dts                |  12 +
 arch/arm/boot/dts/sun5i-r8.dtsi                    | 142 ++-
 arch/arm/boot/dts/sun5i.dtsi                       |  43 +
 arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts  | 208 +++++
 arch/arm/boot/dts/sun7i-a20-cubietruck.dts         |  24 +
 arch/arm/boot/dts/sun7i-a20-itead-ibox.dts         |  24 +
 .../boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts    |  82 ++
 arch/arm/boot/dts/sun7i-a20.dtsi                   |  77 +-
 arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts           | 120 ++-
 .../boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts   | 243 +++++
 arch/arm/boot/dts/sun8i-h3-orangepi-2.dts          | 186 ++++
 arch/arm/boot/dts/sun8i-h3-orangepi-one.dts        | 145 +++
 arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts         | 167 ++++
 arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts       | 105 +--
 arch/arm/boot/dts/sun8i-h3.dtsi                    | 123 +++
 arch/arm/boot/dts/tango4-common.dtsi               |  16 +-
 arch/arm/boot/dts/tango4-smp8758.dtsi              |  28 +-
 arch/arm/boot/dts/tango4-vantage-1172.dts          |   1 -
 arch/arm/boot/dts/tegra114-dalmore.dts             |   6 +-
 arch/arm/boot/dts/tegra114-roth.dts                |   2 +-
 arch/arm/boot/dts/tegra114-tn7.dts                 |   2 +-
 arch/arm/boot/dts/tegra114.dtsi                    |   4 +-
 arch/arm/boot/dts/tegra124-jetson-tk1.dts          |  32 +-
 arch/arm/boot/dts/tegra124-nyan.dtsi               |   8 +-
 arch/arm/boot/dts/tegra124-venice2.dts             |   6 +-
 arch/arm/boot/dts/tegra124.dtsi                    |   4 +-
 arch/arm/boot/dts/tegra20-harmony.dts              |   6 +-
 arch/arm/boot/dts/tegra20-iris-512.dts             |   4 +
 arch/arm/boot/dts/tegra20-medcom-wide.dts          |   4 +
 arch/arm/boot/dts/tegra20-paz00.dts                |   6 +-
 arch/arm/boot/dts/tegra20-seaboard.dts             |   8 +-
 arch/arm/boot/dts/tegra20-tamonten.dtsi            |   4 +
 arch/arm/boot/dts/tegra20-trimslice.dts            |   6 +-
 arch/arm/boot/dts/tegra20-ventana.dts              |   6 +-
 arch/arm/boot/dts/tegra20-whistler.dts             |   6 +-
 arch/arm/boot/dts/tegra20.dtsi                     |   4 +-
 arch/arm/boot/dts/tegra30-apalis-eval.dts          |   6 +-
 arch/arm/boot/dts/tegra30-beaver.dts               |   4 +
 arch/arm/boot/dts/tegra30-cardhu.dtsi              |   6 +-
 arch/arm/boot/dts/tegra30-colibri-eval-v3.dts      |   6 +-
 arch/arm/boot/dts/tegra30.dtsi                     |   4 +-
 arch/arm/boot/dts/twl6030.dtsi                     |   6 +
 arch/arm/boot/dts/uniphier-pinctrl.dtsi            |  10 +
 arch/arm/boot/dts/vexpress-v2m-rs1.dtsi            |  44 +-
 arch/arm/boot/dts/vexpress-v2m.dtsi                |  44 +-
 arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts        |  47 +-
 arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts         |  57 +-
 arch/arm/boot/dts/vexpress-v2p-ca5s.dts            |  37 +-
 arch/arm/boot/dts/vexpress-v2p-ca9.dts             |  41 +-
 arch/arm/boot/dts/vf-colibri.dtsi                  |   7 +-
 arch/arm/boot/dts/vf500-colibri.dtsi               |   5 +
 arch/arm/boot/dts/vf500.dtsi                       |   1 +
 arch/arm/boot/dts/vf610-colibri.dtsi               |   5 +
 arch/arm/boot/dts/vf610-zii-dev-rev-b.dts          | 734 ++++++++++++++++
 arch/arm/boot/dts/vfxxx.dtsi                       |   2 +
 arch/arm/boot/dts/wd-mbwe.dts                      | 112 +++
 arch/arm/mach-davinci/da8xx-dt.c                   |   2 +
 arch/arm/mach-shmobile/timer.c                     |  28 +-
 arch/arm64/boot/dts/renesas/r8a7795.dtsi           |  42 +-
 drivers/clk/samsung/clk-exynos3250.c               |  15 +
 drivers/clk/ti/clk-7xx.c                           |   2 +-
 drivers/gpu/drm/vc4/vc4_drv.c                      |  20 +
 drivers/soc/tegra/Kconfig                          |   2 -
 include/dt-bindings/clock/exynos3250.h             |  11 +-
 include/dt-bindings/clock/r8a7790-clock.h          |   1 +
 include/dt-bindings/clock/r8a7794-clock.h          |   5 +
 include/dt-bindings/power/r8a7779-sysc.h           |  27 +
 include/dt-bindings/power/r8a7790-sysc.h           |  34 +
 include/dt-bindings/power/r8a7791-sysc.h           |  26 +
 include/dt-bindings/power/r8a7793-sysc.h           |  28 +
 include/dt-bindings/power/r8a7794-sysc.h           |  26 +
 include/dt-bindings/power/r8a7795-sysc.h           |  42 +
 include/soc/at91/atmel-sfr.h                       |  18 +
 450 files changed, 23340 insertions(+), 5216 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/oxnas.txt
 create mode 100644 Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/auxadc.txt
 create mode 100644 Documentation/devicetree/bindings/soc/rockchip/grf.txt
 create mode 100644 arch/arm/boot/dts/am335x-baltos-ir2110.dts
 create mode 100644 arch/arm/boot/dts/am335x-baltos-ir3220.dts
 create mode 100644 arch/arm/boot/dts/am335x-baltos.dtsi
 create mode 100644 arch/arm/boot/dts/am335x-icev2.dts
 create mode 100644 arch/arm/boot/dts/am572x-idk.dts
 create mode 100644 arch/arm/boot/dts/am57xx-commercial-grade.dtsi
 create mode 100644 arch/arm/boot/dts/am57xx-idk-common.dtsi
 create mode 100644 arch/arm/boot/dts/am57xx-industrial-grade.dtsi
 create mode 100644 arch/arm/boot/dts/arm-realview-eb-11mp-revb.dts
 create mode 100644 arch/arm/boot/dts/arm-realview-eb-11mp.dts
 create mode 100644 arch/arm/boot/dts/arm-realview-eb-a9mp.dts
 create mode 100644 arch/arm/boot/dts/arm-realview-eb-mp.dtsi
 create mode 100644 arch/arm/boot/dts/arm-realview-eb.dts
 create mode 100644 arch/arm/boot/dts/arm-realview-eb.dtsi
 create mode 100644 arch/arm/boot/dts/arm-realview-pba8.dts
 create mode 100644 arch/arm/boot/dts/arm-realview-pbx-a9.dts
 create mode 100644 arch/arm/boot/dts/arm-realview-pbx.dtsi
 create mode 100644 arch/arm/boot/dts/aspeed-ast2500-evb.dts
 create mode 100644 arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
 create mode 100644 arch/arm/boot/dts/aspeed-g4.dtsi
 create mode 100644 arch/arm/boot/dts/aspeed-g5.dtsi
 create mode 100644 arch/arm/boot/dts/dra72-evm-common.dtsi
 create mode 100644 arch/arm/boot/dts/dra72-evm-revc.dts
 create mode 100644 arch/arm/boot/dts/exynos3250-artik5-eval.dts
 create mode 100644 arch/arm/boot/dts/exynos3250-artik5.dtsi
 create mode 100644 arch/arm/boot/dts/imx6dl-tx6s-8034.dts
 create mode 100644 arch/arm/boot/dts/imx6dl-tx6s-8035.dts
 create mode 100644 arch/arm/boot/dts/imx6dl-tx6u-8033.dts
 create mode 100644 arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts
 create mode 100644 arch/arm/boot/dts/imx6q-marsboard.dts
 create mode 100644 arch/arm/boot/dts/imx6q-tx6q-1036.dts
 create mode 100644 arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts
 create mode 100644 arch/arm/boot/dts/imx6qp-nitrogen6_max.dts
 create mode 100644 arch/arm/boot/dts/imx6sx-nitrogen6sx.dts
 create mode 100644 arch/arm/boot/dts/imx6sx-sdb-sai.dts
 create mode 100644 arch/arm/boot/dts/imx6ul-pico-hobbit.dts
 create mode 100644 arch/arm/boot/dts/imx6ul-tx6ul-0010.dts
 create mode 100644 arch/arm/boot/dts/imx6ul-tx6ul-0011.dts
 create mode 100644 arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts
 create mode 100644 arch/arm/boot/dts/imx6ul-tx6ul.dtsi
 rename arch/arm/boot/dts/{k2e-clocks.dtsi => keystone-k2e-clocks.dtsi} (100%)
 rename arch/arm/boot/dts/{k2e-evm.dts => keystone-k2e-evm.dts} (98%)
 rename arch/arm/boot/dts/{k2e-netcp.dtsi => keystone-k2e-netcp.dtsi} (100%)
 rename arch/arm/boot/dts/{k2e.dtsi => keystone-k2e.dtsi} (97%)
 rename arch/arm/boot/dts/{k2hk-clocks.dtsi => keystone-k2hk-clocks.dtsi} (100%)
 rename arch/arm/boot/dts/{k2hk-evm.dts => keystone-k2hk-evm.dts} (99%)
 rename arch/arm/boot/dts/{k2hk-netcp.dtsi => keystone-k2hk-netcp.dtsi} (100%)
 rename arch/arm/boot/dts/{k2hk.dtsi => keystone-k2hk.dtsi} (96%)
 rename arch/arm/boot/dts/{k2l-clocks.dtsi => keystone-k2l-clocks.dtsi} (100%)
 rename arch/arm/boot/dts/{k2l-evm.dts => keystone-k2l-evm.dts} (98%)
 rename arch/arm/boot/dts/{k2l-netcp.dtsi => keystone-k2l-netcp.dtsi} (100%)
 rename arch/arm/boot/dts/{k2l.dtsi => keystone-k2l.dtsi} (96%)
 create mode 100644 arch/arm/boot/dts/kirkwood-linksys-viper.dts
 rename arch/arm/boot/dts/{ea3250.dts => lpc3250-ea3250.dts} (61%)
 create mode 100644 arch/arm/boot/dts/lpc3250-phy3250.dts
 rename arch/arm/boot/dts/{rk3288-thermal.dtsi => mps2-an385.dts} (54%)
 create mode 100644 arch/arm/boot/dts/mps2-an399.dts
 create mode 100644 arch/arm/boot/dts/mps2.dtsi
 create mode 100644 arch/arm/boot/dts/omap4-kc1.dts
 create mode 100644 arch/arm/boot/dts/orion5x-kuroboxpro.dts
 create mode 100644 arch/arm/boot/dts/ox810se.dtsi
 delete mode 100644 arch/arm/boot/dts/phy3250.dts
 create mode 100644 arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi
 create mode 100644 arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts
 create mode 100644 arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts
 create mode 100644 arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi
 create mode 100644 arch/arm/boot/dts/qcom-ipq4019.dtsi
 create mode 100644 arch/arm/boot/dts/rk3288-miqi.dts
 create mode 100644 arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
 create mode 100644 arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts
 create mode 100644 arch/arm/boot/dts/sun5i-a13-difrnce-dit4350.dts
 create mode 100644 arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts
 create mode 100644 arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
 create mode 100644 arch/arm/boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts
 create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
 create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
 create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
 create mode 100644 arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
 create mode 100644 arch/arm/boot/dts/wd-mbwe.dts
 create mode 100644 include/dt-bindings/power/r8a7779-sysc.h
 create mode 100644 include/dt-bindings/power/r8a7790-sysc.h
 create mode 100644 include/dt-bindings/power/r8a7791-sysc.h
 create mode 100644 include/dt-bindings/power/r8a7793-sysc.h
 create mode 100644 include/dt-bindings/power/r8a7794-sysc.h
 create mode 100644 include/dt-bindings/power/r8a7795-sysc.h
 create mode 100644 include/soc/at91/atmel-sfr.h



From arnd at arndb.de  Tue May 17 15:20:26 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 00:20:26 +0200
Subject: [GIT PULL 1/7] ARM: SoC cleanups and fixes for v4.7
In-Reply-To: <8749147.ztcb6kVhye@wuerfel>
References: <8749147.ztcb6kVhye@wuerfel>
Message-ID: <3000366.nhqNxgKrjJ@wuerfel>

The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:

  Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/armsoc-cleanups-fixes

for you to fetch changes up to 2e629ebc24d463ffb6c17b15daf908e6f968a1de:

  Merge branches 'next/cleanup' and 'next/fixes-non-critical' into next/cleanups-fixes (2016-05-17 15:06:31 +0200)

----------------------------------------------------------------
ARM: SoC cleanups and fixes for v4.7

Traditionally we've had two separate branches for cleanups and non-critical
bug fixes, but both of these got smaller with each release and the differences
are rather unclear now, so it seems more appropriate to have a combined
branch.

The most notably change is for OMAP, which gets a small rework to simplify
handling of the AUXDATA mechanism used on machines that are not completely
DT based yet, along with other work that is used as preparation for dropping
the legacy board files.

----------------------------------------------------------------
Arnd Bergmann (7):
      ARM: realview: hide unused 'pmu_device' object
      Merge tag 'davinci-for-v4.7/cleanup' of git://git.kernel.org/.../nsekhar/linux-davinci into next/cleanup
      ARM: debug: remove extraneous DEBUG_HI3716_UART option
      Merge tag 'samsung-fixes-non-critical-4.7' of git://git.kernel.org/.../krzk/linux into next/fixes-non-critical
      Merge tag 'omap-for-v4.7/legacy-signed' of git://git.kernel.org/.../tmlind/linux-omap into next/fixes-non-critical
      Merge tag 'omap-for-v4.7/auxdata-signed' of git://git.kernel.org/.../tmlind/linux-omap into next/fixes-non-critical
      Merge branches 'next/cleanup' and 'next/fixes-non-critical' into next/cleanups-fixes

David Lechner (3):
      ARM: davinci: simplify call to of populate
      ARM: davinci: remove unused DA8XX_NUM_UARTS
      ARM: davinci: use IRQCHIP_DECLARE for cp_intc

Javier Martinez Canillas (1):
      ARM: dts: exynos: Add MFC memory banks for Peach boards

Krzysztof Kozlowski (1):
      ARM: EXYNOS: Properly skip unitialized parent clock in power domain on

Linus Walleij (1):
      soc: versatile: dynamically detect RealView HBI numbers

Marek Szyprowski (2):
      ARM: dts: exynos: Fix regulator name to avoid forbidden character on exynos4210-trats
      ARM: dts: exynos: Add interrupt line to MAX8997 PMIC on exynos4210-trats

Olof Johansson (2):
      Merge tag 'versatile-cleanup-1' of git://git.kernel.org/.../linusw/linux-integrator into next/cleanup
      Merge tag 'v4.7-rockchip-soc32-1' of git://git.kernel.org/.../mmind/linux-rockchip into next/cleanup

Peter Griffin (1):
      ARM: rockchip: Fix use of plain integer as NULL pointer

Petr Kulhavy (1):
      ARM: DaVinci USB: removed deprecated properties from MUSB config

Tony Lindgren (4):
      of/platform: Allow secondary compatible match in of_dev_lookup
      ARM: OMAP2+: Simplify auxdata by using the generic match
      ARM: OMAP2+: Add more functions to pwm pdata for ir-rx51
      ARM: OMAP2+: n900 needs MMC slot names for legacy user space

 arch/arm/Kconfig.debug                         |  8 ----
 arch/arm/boot/dts/exynos4210-trats.dts         |  4 +-
 arch/arm/boot/dts/exynos5420-peach-pit.dts     |  5 +++
 arch/arm/boot/dts/exynos5800-peach-pi.dts      |  5 +++
 arch/arm/mach-davinci/cp_intc.c                |  3 ++
 arch/arm/mach-davinci/da8xx-dt.c               | 17 +-------
 arch/arm/mach-davinci/usb.c                    | 16 --------
 arch/arm/mach-exynos/pm_domains.c              |  2 +-
 arch/arm/mach-omap2/board-rx51-peripherals.c   | 35 +++++++++++++++-
 arch/arm/mach-omap2/pdata-quirks.c             | 57 ++++++++++++++++++--------
 arch/arm/mach-realview/realview_pbx.c          |  2 +
 arch/arm/mach-rockchip/platsmp.c               |  2 +-
 drivers/of/platform.c                          | 28 ++++++++++---
 drivers/soc/versatile/soc-realview.c           | 19 ++-------
 include/linux/platform_data/media/ir-rx51.h    |  1 +
 include/linux/platform_data/pwm_omap_dmtimer.h | 21 ++++++++++
 16 files changed, 144 insertions(+), 81 deletions(-)



From arnd at arndb.de  Tue May 17 15:07:24 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 00:07:24 +0200
Subject: [GIT PULL 0/7] ARM: SoC changes for 4.7
Message-ID: <8749147.ztcb6kVhye@wuerfel>

Hi Linus,

These are the first seven pull requests for arm-soc this time, there is
one small follow-up coming once the dependencies for that have landed
in your tree.

Things remain relatively calm for us. We merged 122 pull requests with
822 patches, plus 35 individual patches, which is less than what we used
to have. We are shifting even more towards changing only dts files,
for the most part adding new functionality on existing boards, and adding
new machines, as shown clearly by the dirstat:

   3.4% Documentation/devicetree/bindings/
  56.3% arch/arm/boot/dts/
   0.7% arch/arm/configs/
   0.0% arch/arm/mach-aspeed/
   0.2% arch/arm/mach-at91/
   0.0% arch/arm/mach-bcm/
   0.5% arch/arm/mach-davinci/
   0.0% arch/arm/mach-dove/
   0.1% arch/arm/mach-exynos/
   0.0% arch/arm/mach-imx/
   0.1% arch/arm/mach-integrator/
   0.1% arch/arm/mach-lpc32xx/
   0.0% arch/arm/mach-mediatek/
   0.0% arch/arm/mach-mv78xx0/
   1.3% arch/arm/mach-omap2/
   0.0% arch/arm/mach-orion5x/
   0.0% arch/arm/mach-oxnas/
   0.0% arch/arm/mach-realview/
   0.0% arch/arm/mach-rockchip/
   0.3% arch/arm/mach-shmobile/
   0.0% arch/arm/mach-sti/
   0.0% arch/arm/mach-tegra/
   0.0% arch/arm/mach-uniphier/
   0.0% arch/arm/mach-versatile/
   0.0% arch/arm/mach-vexpress/
   0.0% arch/arm/plat-samsung/
   0.9% arch/arm/
  13.1% arch/arm64/boot/dts/
   0.0% arch/arm64/configs/
   0.0% arch/arm64/
   0.0% drivers/bus/
   0.9% drivers/clk/
   0.0% drivers/firmware/
   0.0% drivers/gpu/drm/tegra/
   0.0% drivers/gpu/drm/vc4/
   0.0% drivers/irqchip/
   0.4% drivers/memory/samsung/
   0.0% drivers/memory/
   0.4% drivers/mtd/maps/
   0.0% drivers/of/
   0.3% drivers/pci/host/
   9.2% drivers/phy/tegra/
   0.1% drivers/phy/
   0.0% drivers/pinctrl/tegra/
   0.6% drivers/reset/
   0.1% drivers/soc/brcmstb/
   1.0% drivers/soc/mediatek/
   0.4% drivers/soc/qcom/
   1.2% drivers/soc/renesas/
   0.4% drivers/soc/rockchip/
   0.7% drivers/soc/tegra/
 730 files changed, 47909 insertions(+), 7916 deletions(-)

My feeling is that the number of dts changes remain constant, but
everything else gets less every time, and that's good.

One part that sticks out this time in the dirstat this time is the
NVIDIA rework for the USB PHY, which had complex interdependencies so
we are merging all the subsystem specific change through arm-soc.

I currently don't see any conflicts against other trees, or between
our branches.

The most active individual developers (15 patches or more) out of the 165 people
that contributed this time were:

     51 Geert Uytterhoeven
     42 Simon Horman
     23 Heiko Stuebner
     22 Hans de Goede
     21 Jon Hunter
     21 Chanwoo Choi
     20 Thierry Reding
     17 Vladimir Zapolskiy
     17 Linus Walleij
     17 Krzysztof Kozlowski
     16 Lee Jones
     15 Srinivas Kandagatla
     15 Roger Quadros
     15 Fabio Estevam

	Arnd


From arnd at arndb.de  Tue May 17 15:21:11 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 00:21:11 +0200
Subject: [GIT PULL 2/7] ARM: SoC platform updates for v4.7
In-Reply-To: <8749147.ztcb6kVhye@wuerfel>
References: <8749147.ztcb6kVhye@wuerfel>
Message-ID: <3208173.oSXZ3kL0Xa@wuerfel>

The following changes since commit bf16200689118d19de1b8d2a3c314fc21f5dc7bb:

  Linux 4.6-rc3 (2016-04-10 17:58:30 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/armsoc-soc

for you to fetch changes up to b54891be1a7785de7ec0e5c1fc9ba597713d22a8:

  Merge tag 'v4.6-next-kconfig' of https://github.com/mbgg/linux-mediatek into next/soc (2016-05-09 16:31:16 +0200)

----------------------------------------------------------------
ARM: SoC platform updates for v4.7

We get support for three new 32-bit SoC platforms this time. The amount
of changes in arch/arm for any of them is miniscule, as all the
interesting code is in device driver subsystems (irqchip, clk, pinctrl,
...) these days. I'm listing them here, as the addition of the Kconfig
statement is the main relevant milestone for a new platform. In each
case, some drivers are are shared with existing platforms, while
other drivers are added for v4.7 as well, or come in a later release.

- The Aspeed platform is probably the most interesting one, this is
  what most whitebox servers use as their baseboard management
  controller. We get support for the very common ast2400 and ast2500
  SoCs. The OpenBMC project focuses on this chip, and the LWN
  article about their ELC 2016 presentation at
  https://lwn.net/Articles/683320/ triggered the submission, but the
  code comes from IBM's OpenPOWER team rather than the team at
  Facebook. There are still a lot more drivers that need to get added
  over time, and I hope both teams can work together on that.

- OXNAS is an old platform for Network Attached Storage devices
  from Oxford Semiconductor. There are models with ARM10 (!) and
  ARM11MPCore cores, but for now, we only support the original ARM9
  based versions.
  The product lineup was subsequently part of PLX, Avago and now the
  new Broadcom Ltd. https://wiki.openwrt.org/doc/hardware/soc/soc.oxnas
  has some more information.

- V2M-MPS2 is a prototyping platform from ARM for their Cortex-M
  cores and is related to the existing Realview / Versatile Express
  lineup, but without MMU. We now support various NOMMU platforms,
  so adding a new one is fairly straightforward.
  http://infocenter.arm.com/help/topic/com.arm.doc.100112_0100_03_en/
  has detailed information about the platform.

Other noteworthy updates:

- Work on LPC32xx has resumed, and Vladimir Zapolskiy and Sylvain Lemieux
  are now maintaining the platform. This is an older ARM9 based
  platform from NXP (not Freescale), but it remains in use in embedded
  markets.

- Kevin Hilman is now co-maintaining the Amlogic Meson platform for both
  32-bit and 64-bit ARM, and started contributing some patches.

- As is often the case, work on the OMAP platforms makes up the bulk of
  the actual SoC code changes in arch/arm, but there isn't a lot of
  that either.

----------------------------------------------------------------
Anna-Maria Gleixner (1):
      ARM: OMAP2+: wakeupgen: Add comment for unhandled FROZEN transitions

Arnd Bergmann (11):
      Merge tag 'davinci-for-v4.7/soc' of git://git.kernel.org/.../nsekhar/linux-davinci into next/soc
      Merge tag 'renesas-soc-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/soc
      Merge tag 'ox810se-arm-v4.6-rc3' of https://github.com/superna9999/linux into next/soc
      Merge tag 'omap-for-v4.7/soc-signed' of git://git.kernel.org/.../tmlind/linux-omap into next/soc
      Merge tag 'lpc32xx-soc-4.7' of git://github.com/vzapolskiy/linux-lpc32xx into next/soc
      Merge tag 'davinci-for-v4.7/soc-part2' of git://git.kernel.org/.../nsekhar/linux-davinci into next/soc
      Merge tag 'mvebu-soc-4.7-1' of git://git.infradead.org/linux-mvebu into next/soc
      Merge tag 'imx-soc-4.7' of git://git.kernel.org/.../shawnguo/linux into next/soc
      Merge tag 'davinci-for-v4.7/doc' of git://git.kernel.org/.../nsekhar/linux-davinci into next/soc
      Merge tag 'aspeed-for-4.7-arch' of https://github.com/shenki/linux into next/soc
      Merge tag 'v4.6-next-kconfig' of https://github.com/mbgg/linux-mediatek into next/soc

David Lechner (7):
      ARM: davinci: simplify call to of populate
      ARM: davinci: remove unused DA8XX_NUM_UARTS
      ARM: davinci: use IRQCHIP_DECLARE for cp_intc
      ARM: davinci: da8xx: move usb code to new file
      ARM: davinci: clk: add set_parent callback for mux clocks
      ARM: davinci: Move clock init after ioremap.
      ARM: davinci: da850: use clk->set_parent for async3

Erin Lo (1):
      ARM: mediatek: Add MT2701 config options for mediatek SoCs.

Geert Uytterhoeven (2):
      ARM: shmobile: timer: Fix preset_lpj leading to too short delays
      ARM: shmobile: timer: Drop support for Cortex A8

Joel Stanley (1):
      arm: Add Aspeed machine

Jonas Rabenstein (1):
      ARM: OMAP2+: remove redundant multiplatform checks

Keerthy (1):
      ARM: DRA7: clockdomain: Implement timer workaround for errata i874

Kevin Hilman (1):
      MAINTAINERS: ARM/Amlogic: add co-maintainer, misc. updates

Lee Jones (3):
      MAINTAINERS: Add ST's CPUFreq driver to the STI file list
      MAINTAINERS: Add ST's Remote Processor Driver to ARM/STI ARCHITECTURE
      ARM: STi: Update platform level menuconfig 'help'

Lokesh Vutla (4):
      ARM: OMAP2+: hwmod: Fix updating of sysconfig register
      ARM: OMAP2+: hwmod: RTC: Add lock and unlock functions
      ARM: DRA7: RTC: Add lock and unlock functions
      ARM: AMx3xx: RTC: Add lock and unlock functions

Ludovic Desroches (2):
      ARM: at91: use chipid device for soc detection
      ARM: at91/soc: reference the whole sama5d2 family

Masahiro Yamada (1):
      ARM: uniphier: correct the call order of of_node_put()

Neil Armstrong (3):
      irqchip: versatile-fpga: add new compatible for OX810SE SoC
      ARM: Add new mach-oxnas
      MAINTAINERS: add maintainer entry for ARM/OXNAS platform

Nishanth Menon (3):
      ARM: OMAP: DRA7: powerdomain data: Erratum i892 workaround: Disable core INA
      ARM: OMAP: DRA7: powerdomain data: Fix "ON" state for memories
      ARM: OMAP: DRA7: powerdomain data: Remove wrong OSWR capability

Olof Johansson (2):
      Merge tag 'at91-soc' of git://git.kernel.org/.../nferre/linux-at91 into next/soc
      Merge tag 'sti-soc-for-v4.7-1' of git://git.kernel.org/.../mcoquelin/sti into next/soc

Peter Ujfalusi (1):
      ARM: DRA7: hwmod: Add data for McASP1/2/4/5/6/7/8

Petr Kulhavy (1):
      ARM: DaVinci USB: removed deprecated properties from MUSB config

Sebastian Andrzej Siewior (1):
      ARM: imx: always use TWD on IMX6Q

Sekhar Nori (1):
      MAINTAINERS: fix stale TI DaVinci entries

Sjoerd Simons (2):
      ARM: dts: r8a7791: Don't disable referenced optional clocks
      Revert "ARM: dts: porter: Enable SCIF_CLK frequency and pins"

Stephen Boyd (3):
      ARM: mv78xx0: Remove CLK_IS_ROOT
      ARM: orion5x: Remove CLK_IS_ROOT
      ARM: dove: Remove CLK_IS_ROOT

Suman Anna (2):
      ARM: DRA7: hwmod: Add data for GPTimer 12
      ARM: OMAP2+: hwmod: fix _idle() hwmod state sanity check sequence

Sylvain Lemieux (1):
      ARM: lpc32xx: remove reboot header file

Tony Lindgren (1):
      Merge tag 'for-v4.7/omap-hwmod-a' of git://git.kernel.org/.../pjw/omap-pending into omap-for-v4.7/soc

Vignesh R (1):
      ARM: OMAP2+: DRA7: Add hwmod entries for PWMSS

Vladimir Murzin (2):
      ARM: vexpress/mps2: introduce MPS2 platform
      MAINTAINERS: Update ARM Versatile Express platform entry

Vladimir Zapolskiy (5):
      ARM: lpc32xx: remove leftovers of legacy clock source and provider drivers
      ARM: lpc32xx: remove duplicate const on lpc32xx_auxdata_lookup
      MAINTAINERS: move ARM/NXP LPC32xx record to ARM section
      MAINTAINERS: add new maintainers of NXP LPC32xx SoC
      MAINTAINERS: add ARM/NXP LPC32XX SoC specific drivers to the section

 .../devicetree/bindings/arm/atmel-at91.txt         |   4 +
 MAINTAINERS                                        |  48 ++-
 arch/arm/Kconfig                                   |  16 +
 arch/arm/Makefile                                  |   1 +
 arch/arm/boot/dts/r8a7791-koelsch.dts              |   1 +
 arch/arm/boot/dts/r8a7791-porter.dts               |  14 +-
 arch/arm/boot/dts/r8a7791.dtsi                     |   5 +-
 arch/arm/mach-aspeed/Kconfig                       |  30 ++
 arch/arm/mach-at91/sama5.c                         |  20 +-
 arch/arm/mach-at91/soc.c                           |  81 ++++-
 arch/arm/mach-at91/soc.h                           |  12 +-
 arch/arm/mach-davinci/Makefile                     |   4 +-
 arch/arm/mach-davinci/clock.c                      |  21 +-
 arch/arm/mach-davinci/clock.h                      |   1 +
 arch/arm/mach-davinci/common.c                     |   6 -
 arch/arm/mach-davinci/cp_intc.c                    |   3 +
 arch/arm/mach-davinci/da830.c                      |   2 +
 arch/arm/mach-davinci/da850.c                      |  83 ++---
 arch/arm/mach-davinci/da8xx-dt.c                   |  17 +-
 arch/arm/mach-davinci/dm355.c                      |   1 +
 arch/arm/mach-davinci/dm365.c                      |   1 +
 arch/arm/mach-davinci/dm644x.c                     |   1 +
 arch/arm/mach-davinci/dm646x.c                     |   1 +
 arch/arm/mach-davinci/usb-da8xx.c                  | 107 ++++++
 arch/arm/mach-davinci/usb.c                        |  89 -----
 arch/arm/mach-dove/common.c                        |   3 +-
 arch/arm/mach-imx/Kconfig                          |   2 +-
 arch/arm/mach-lpc32xx/common.c                     |  95 ------
 arch/arm/mach-lpc32xx/common.h                     |  24 +-
 arch/arm/mach-lpc32xx/phy3250.c                    |   2 +-
 arch/arm/mach-mediatek/Kconfig                     |   4 +
 arch/arm/mach-mv78xx0/common.c                     |   3 +-
 arch/arm/mach-omap2/Makefile                       |   2 +-
 arch/arm/mach-omap2/clockdomains7xx_data.c         |   2 +-
 arch/arm/mach-omap2/omap-wakeupgen.c               |   5 +
 arch/arm/mach-omap2/omap_hwmod.c                   |  20 +-
 arch/arm/mach-omap2/omap_hwmod.h                   |   2 +
 .../mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c |   2 +
 arch/arm/mach-omap2/omap_hwmod_7xx_data.c          | 364 ++++++++++++++++++++-
 arch/arm/mach-omap2/omap_hwmod_reset.c             |  65 ++++
 arch/arm/mach-omap2/powerdomains7xx_data.c         |  82 ++---
 arch/arm/mach-omap2/soc.h                          | 140 ++------
 arch/arm/mach-orion5x/common.c                     |   3 +-
 arch/arm/mach-oxnas/Kconfig                        |  24 ++
 arch/arm/mach-shmobile/timer.c                     |  56 ++--
 arch/arm/mach-sti/Kconfig                          |   9 +-
 arch/arm/mach-uniphier/platsmp.c                   |   4 +-
 arch/arm/mach-vexpress/Makefile                    |   4 +-
 arch/arm/mach-vexpress/Makefile.boot               |   3 +
 arch/arm/mach-vexpress/v2m-mps2.c                  |  21 ++
 drivers/irqchip/irq-versatile-fpga.c               |   1 +
 51 files changed, 957 insertions(+), 554 deletions(-)
 create mode 100644 arch/arm/mach-aspeed/Kconfig
 create mode 100644 arch/arm/mach-davinci/usb-da8xx.c
 create mode 100644 arch/arm/mach-oxnas/Kconfig
 create mode 100644 arch/arm/mach-vexpress/Makefile.boot
 create mode 100644 arch/arm/mach-vexpress/v2m-mps2.c



From arnd at arndb.de  Tue May 17 15:43:58 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 00:43:58 +0200
Subject: [GIT PULL] SoCFPGA DTS updates for v4.7, part3
In-Reply-To: <1462891391-13876-1-git-send-email-dinguyen@kernel.org>
References: <1462891391-13876-1-git-send-email-dinguyen@kernel.org>
Message-ID: <2600031.fLUcj7Vapa@wuerfel>

On Tuesday 10 May 2016 09:43:11 Dinh Nguyen wrote:
> If not too late, please pull in this patch for v4.7.
> 
> Thanks,
> Dinh
> 
> The following changes since commit 02da2d72174c61988eb4456b53f405e3ebdebce4:
> 
>   Linux 4.6-rc5 (2016-04-24 16:17:05 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git socfpga_for_next_v4.7_dts_part_3
> 
> for you to fetch changes up to fca689561e8170ad954b982b9ce2160a06d9435e:
> 
>   ARM: dts: socfpga: add ethernet alias on Arria10 (2016-05-03 09:25:21 -0500)
> 
> ----------------------------------------------------------------
> SoCFPGA DTS update for v4.7, part 3
> - Add ethernet alias on Arria10
> 

I was going to put this into the next/late branch that already has some other
changes, but in the end I decided to drop it because it is based on
a later -rc release than the other branches, and doesn't seem obvious
or important enough.

Just a clarification about the contents of the patch, you write:

    Without having an ethernet alias, ethernet will have a random MAC address,
    versus take an address that was provided from the bootloader.

Why is the alias needed to get the right MAC address? How does the
bootloader pass it?

	Arnd


From arnd at arndb.de  Tue May 17 15:45:51 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 00:45:51 +0200
Subject: [RFC6 PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <mvm1t50ad0j.fsf@hawking.suse.de>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <alpine.DEB.2.20.1605171542340.24255@digraph.polyomino.org.uk>
 <mvm1t50ad0j.fsf@hawking.suse.de>
Message-ID: <4095406.jADDlVRiDg@wuerfel>

On Tuesday 17 May 2016 18:02:36 Andreas Schwab wrote:
> Joseph Myers <joseph at codesourcery.com> writes:
> 
> > On Tue, 17 May 2016, Arnd Bergmann wrote:
> >
> >> I think it has become easier to override now and we just need to
> >> update sysdeps/unix/sysv/linux/generic/bits/typesizes.h to set
> >> 
> >> #define __INO64_T_TYPE          __UQUAD_TYPE
> >> #define __OFF64_T_TYPE          __UQUAD_TYPE
> >> #define __OFF_T_MATCHES_OFF64_T        1
> >> #define __INO_T_MATCHES_INO64_T        1
> >> 
> >> for new architectures (obviously not the ones that already use the
> >> 32-bit types). I haven't tries this, so there may be other things
> >> that are required.
> >
> > I think more than that would be needed to get struct stat to match and get 
> > things aliased for that (which is presumably desirable).
> 
> Looking at sysdeps/unix/sysv/linux/generic/bits/stat.h, there is at
> least blkcnt_t that differs between stat and stat64.  And you probably
> want to alias statfs and statfs64 as well, ie. fs{blk,fil}cnt_t.

Makes sense. Indeed that is a bit more work than I hoped, in particular
if we have to audit the uses of __WORDSIZE as well.

	Arnd


From julian.calaby at gmail.com  Tue May 17 16:15:42 2016
From: julian.calaby at gmail.com (Julian Calaby)
Date: Wed, 18 May 2016 09:15:42 +1000
Subject: [linux-sunxi] Re: PATH[1/3] ARM: axp20x_usb_power.c add device
 tree configuration options for REG 30H: VBUS-IPSOUT
In-Reply-To: <671c7471-b63a-40cc-989f-6b20f00571ee@googlegroups.com>
References: <0f58d2b3-f3d3-45a3-a307-e54df26c1ab1@googlegroups.com>
 <671c7471-b63a-40cc-989f-6b20f00571ee@googlegroups.com>
Message-ID: <CAGRGNgXgfBGi6-kCQMQ4pYQ9jW-06babG2oQar8GnOmcej2Lkg@mail.gmail.com>

Hi Ene,

On Wed, May 18, 2016 at 3:47 AM, Ene Alexandru <ene.alexandru at gmail.com> wrote:
> axp20x_usb_power.c is modified to read those parameters from the device tree
> configuration.
> if a configuration value is not found then the corresponding register value
> is not changed.
>
> also, debug messages are added, controlled by "CONFIG_POWER_SUPPLY_DEBUG" :
>
> Signed-off-by: Ene Alexandru <ene.alexandru at gmail.com>
>
>
> ---
> diff -uprN -X linux-sunxi-original/Documentation/dontdiff
> linux-sunxi-original/drivers/power/axp20x_usb_power.c
> linux-sunxi/drivers/power/axp20x_usb_power.c
> --- linux-sunxi-original/drivers/power/axp20x_usb_power.c  2016-05-09
> 16:51:44.000000000 +0200
> +++ linux-sunxi/drivers/power/axp20x_usb_power.c          2016-05-11
> 13:26:24.444681579 +0200
> @@ -41,6 +41,19 @@
>  #define AXP20X_VBUS_MON_VBUS_VALID       BIT(3)
> +/* bit defines for REG 30H: VBUS-IPSOUT Power Path Management */
> +/* VBUS VHOLD voltage limiting control  */
> +#define AXP20X_VBUS_IPSOUT_MGMT_VHOLD                       BIT(6)
> +#define AXP20X_VBUS_IPSOUT_MGMT_VHOLD_ENA  BIT(6)
> +#define AXP20X_VBUS_IPSOUT_MGMT_VHOLD_DIS    BIT(0)
> +/* VHOLD Set voltage */
> +#define AXP20X_VBUS_IPSOUT_MGMT_VHOLD_SET_MASK (BIT(5)|BIT(4)|BIT(3))
> +#define AXP20X_VBUS_IPSOUT_MGMT_VHOLD_SET_SHIFT (3)
> +/* VBUS current-limit selection */
> +#define AXP20X_VBUS_IPSOUT_MGMT_IBUS_MASK (BIT(1) | BIT(0))
> +
> +
> +

Drop the two extra empty lines here.

> struct axp20x_usb_power {
>            struct regmap *regmap;
>            struct power_supply *supply;
> @@ -164,6 +177,93 @@ static const struct power_supply_desc ax
>            .get_property = axp20x_usb_power_get_property,
> };
> +
> +static int axp20x_usb_power_read_params(const struct device_node *node,
> +                      struct axp20x_usb_power *power, struct
> platform_device *pdev)
> +{
> +          const u32 *prop;
> +          int ret;
> +
> +          /*
> +          * configurable parameters are:
> +          * register VBUS-IPSOUT
> +          * bit 6: VBUS VHOLD voltage limiting control
> +          *           0: No voltage drop limit
> +          *           1: Limit the voltage drop
> +          * bit 5-3 VHOLD Set VHOLD = [4.0+ (Bit5-3) * 0.1] V
> +          * bit 1-0 VBUS current-limit selection
> +          *           00:900mA
> +          *           01:500mA
> +          *           10:100mA
> +          *           11:no limit
> +          */
> +
> +          prop = of_get_property(node, "vhold-enable", NULL);
> +          if (prop) {
> +                      /* either 1 or 0 */
> +#ifdef DEBUG
> +                      dev_info(&pdev->dev, "set vhold-enable property to
> %d",
> +                                  !!(*prop));
> +#endif

Use dev_dbg() instead of wrapping the dev_info() calls in #ifdefs.

> +                      if (!!(*prop)) {
> +                                  ret = regmap_update_bits(power->regmap,
> +
> AXP20X_VBUS_IPSOUT_MGMT,
> +
> AXP20X_VBUS_IPSOUT_MGMT_VHOLD,
> +
> AXP20X_VBUS_IPSOUT_MGMT_VHOLD_ENA);
> +                      } else {
> +                                  ret = regmap_update_bits(power->regmap,
> +
> AXP20X_VBUS_IPSOUT_MGMT,
> +
> AXP20X_VBUS_IPSOUT_MGMT_VHOLD,
> +
> AXP20X_VBUS_IPSOUT_MGMT_VHOLD_DIS);
> +                      }
> +                      if (ret)
> +                                  return ret;
> +          } else {
> +#ifdef DEBUG
> +                      dev_info(&pdev->dev, "no vhold-enable property
> found");
> +#endif

Ditto.

> +          }
> +
> +          prop = of_get_property(node, "vhold-set", NULL);
> +          if (prop) {
> +                      /* from 0b000 to 0b111 */
> +#ifdef DEBUG
> +                      dev_info(&pdev->dev, "set vhold-set property to
> %02X",
> +                                  ((*prop)>>24));
> +#endif

Ditto.

> +                      ret = regmap_update_bits(power->regmap,
> +                                              AXP20X_VBUS_IPSOUT_MGMT,
> +
> AXP20X_VBUS_IPSOUT_MGMT_VHOLD_SET_MASK,
> +                                              ((*prop)>>24) <<
> AXP20X_VBUS_IPSOUT_MGMT_VHOLD_SET_SHIFT);
> +                      if (ret)
> +                                  return ret;
> +          } else {
> +#ifdef DEBUG
> +                      dev_info(&pdev->dev, "no vhold-set property found");
> +#endif

Ditto.

> +          }
> +
> +          prop = of_get_property(node, "ibus-limit", NULL);
> +          if (prop) {
> +                      /* from 0b0 to 0b11 */
> +#ifdef DEBUG
> +                      dev_info(&pdev->dev, "set ibus-limit property to
> %02X",
> +                                  ((*prop)>>24));
> +#endif

Ditto.

> +                      ret = regmap_update_bits(power->regmap,
> AXP20X_VBUS_IPSOUT_MGMT,
> +
> AXP20X_VBUS_IPSOUT_MGMT_IBUS_MASK,
> +                                                          ((*prop)>>24));
> +                      if (ret)
> +                                  return ret;
> +          } else {
> +#ifdef DEBUG
> +                      dev_info(&pdev->dev, "no ibus-limit property found");
> +#endif

Ditto.

> +          }
> +
> +          return 0;
> +}
> +
> static int axp20x_usb_power_probe(struct platform_device *pdev)
> {
>            struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
> @@ -172,6 +272,7 @@ static int axp20x_usb_power_probe(struct
>            static const char * const irq_names[] = { "VBUS_PLUGIN",
>                        "VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID" };
>            int i, irq, ret;
> +          struct device_node *node;
>             if (!of_device_is_available(pdev->dev.of_node))
>                        return -ENODEV;
> @@ -208,6 +309,11 @@ static int axp20x_usb_power_probe(struct
>            if (IS_ERR(power->supply))
>                        return PTR_ERR(power->supply);
> +
> +          /* read DT configurations parameters, if available */
> +          for_each_compatible_node(node, NULL,
> "x-powers,axp202-usb-power-supply")
> +                                  axp20x_usb_power_read_params(node, power,
> pdev);
> +
>            /* Request irqs after registering, as irqs may trigger
> immediately */
>            for (i = 0; i < ARRAY_SIZE(irq_names); i++) {
>                        irq = platform_get_irq_byname(pdev, irq_names[i]);
> ---

Thanks,

-- 
Julian Calaby

Email: julian.calaby at gmail.com
Profile: http://www.google.com/profiles/julian.calaby/


From julian.calaby at gmail.com  Tue May 17 16:21:03 2016
From: julian.calaby at gmail.com (Julian Calaby)
Date: Wed, 18 May 2016 09:21:03 +1000
Subject: [linux-sunxi] Re: PATH[1/3] ARM: axp20x_usb_power.c add device
 tree configuration options for REG 30H: VBUS-IPSOUT
In-Reply-To: <35a39bdc-1304-403d-b56a-a45bb8debf5e@googlegroups.com>
References: <0f58d2b3-f3d3-45a3-a307-e54df26c1ab1@googlegroups.com>
 <671c7471-b63a-40cc-989f-6b20f00571ee@googlegroups.com>
 <35a39bdc-1304-403d-b56a-a45bb8debf5e@googlegroups.com>
Message-ID: <CAGRGNgX7A3bx9Dam2j1ovdf4s8L9GTi3DM4zMeyu0x3b0wwCgA@mail.gmail.com>

Hi Ene,

On Wed, May 18, 2016 at 3:50 AM, Ene Alexandru <ene.alexandru at gmail.com> wrote:
> the documentation is updated to describe how to convert actual values to the
> provided parameters
>
> ---
> diff -uprN -X linux-sunxi-original/Documentation/dontdiff
> linux-sunxi-original/Documentation/devicetree/bindings/power_supply/axp20x_usb_power.txt
> linux-sunxi/Documentation/devicetree/bindings/power_supply/axp20x_usb_power.txt
> ---
> linux-sunxi-original/Documentation/devicetree/bindings/power_supply/axp20x_usb_power.txt
> 2016-05-09 16:48:46.000000000 +0200
> +++
> linux-sunxi/Documentation/devicetree/bindings/power_supply/axp20x_usb_power.txt
> 2016-05-11 13:05:58.995873267 +0200
> @@ -5,6 +5,26 @@ Required Properties:
>  This node is a subnode of the axp20x PMIC.
> +The following 3 parameters are configurable from the device-tree:
> +          - vhold-enable
> +                      - bit 6 of register REG 30H: VBUS-IPSOUT Power Path
> Management

I don't think it's necessary to go into this much detail here.

> +                      - available values are:
> +                                  - 0x00 : VBUS VHOLD voltage limiting
> control disabled
> +                                  - 0x01 : VBUS VHOLD voltage limiting
> control enabled

If these are the only options available, why not make this property a boolean?

> +          - vhold-set
> +                      - bits <5-3> of register REG 30H: VBUS-IPSOUT Power
> Path Management
> +                      - available values are from 0x00 to 0x07
> +                      - VHOLD = [4000000 + ( vhold-set & 0x07 ) * 100000]
> in uV

What does this actually do? Is this the lower limit on the voltage? Is
this the voltage it'll try to maintain?

> +          - ibus-limit
> +                      - bits <1-0> of register REG 30H: VBUS-IPSOUT Power
> Path Management
> +                      - available values are :
> +                                  - 0x00 : 900000uA
> +                                  - 0x01 : 500000uA
> +                                  - 0x02 : 100000uA
> +                                  - 0x03 : unlimited

Again, what does this actually do? It looks like the current limit?

> +
> +

Extra blank line.

> Example:
>  axp209: pmic at 34 {
> @@ -30,5 +50,8 @@ axp209: pmic at 34 {
>             usb-power-supply: usb-power-supply {
>                        compatible = "x-powers,axp202-usb-power-supply";
> +                      vhold-enable = <0x01>;
> +                      vhold-set = <0x04>;
> +                      ibus-limit = <0x01>;
>            };
> };

Thanks,

-- 
Julian Calaby

Email: julian.calaby at gmail.com
Profile: http://www.google.com/profiles/julian.calaby/


From simran.rai at broadcom.com  Tue May 17 17:01:06 2016
From: simran.rai at broadcom.com (Simran Rai)
Date: Tue, 17 May 2016 17:01:06 -0700
Subject: [PATCH v7 0/3] ASoC: cygnus: Add audio support for Broadcom Cygnus SoC
Message-ID: <1463529669-25022-1-git-send-email-simran.rai@broadcom.com>

Hi,

This patchset contains audio support for Broadcom's Cygnus SoC.
It contains DT bindings and core audio driver. The audio driver supports
both capture and playback of Audio PCM samples over I2S/TDM interface and
provides playback support over SPDIF interface.

This patchset is derived from a previously submitted patchset:
http://lkml.iu.edu/hypermail/linux/kernel/1503.3/05434.html

This patchset has been tested on Cygnus wireless audio bcm958305K board.
It is based on v4.6-rc1 and is available from github:

repo: https://github.com/Broadcom/cygnus-linux/tree/cygnus-sound-v7

Changes from v6:
- DT bindings acknowledged by Rob Herring
Changes from v5:
- Fix code style, e.g. change "if" statements to "switch" statements
- Fix SPDIF output enable register field
- Set BUFFER_PAIR_ENABLE for both mono, stereo and TDM modes
- Reflect PCM bit formats for SPDIF, SSP and TDM as supported by
hardware
Changes from v4:
- Fix power suspend function and add power resume function
- Move clock initialization code from audio driver to clock framework
Changes from v3:
- Fix the subject lines to match the style for the subsystem
Changes from v2:
- Split patchset 2/2 from v2 into patchsets 2/3 and 3/3.
- Remove SND_SOC_CYGNUS_DIAG. Diagnostics can be performed using
standard kernel trace infrastructure.
- Fix interrupt handler. Acknowledge only those interrupts that are
handledby ISR.
- Modify configure_vco() and the pll_macro_entry() struct to make it
better readable. The functionality did not change.
- Remove casts on macros
- Remove surround sound channel grouping from the driver.
Changes from v1:
- Address code review comments. Fix print format of type size_t and
pointer.

Simran Rai (3):
  ASoC: cygnus: Add DT bindings for Broadcom Cygnus audio
  ASoC: cygnus: Add Cygnus audio DAI driver
  ASoC: cygnus: Add Cygnus audio DMA driver

 .../bindings/sound/brcm,cygnus-audio.txt           |   67 +
 sound/soc/bcm/Kconfig                              |    9 +
 sound/soc/bcm/Makefile                             |    5 +
 sound/soc/bcm/cygnus-pcm.c                         |  861 +++++++++++
 sound/soc/bcm/cygnus-ssp.c                         | 1529 ++++++++++++++++++++
 sound/soc/bcm/cygnus-ssp.h                         |  139 ++
 6 files changed, 2610 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/brcm,cygnus-audio.txt
 create mode 100644 sound/soc/bcm/cygnus-pcm.c
 create mode 100644 sound/soc/bcm/cygnus-ssp.c
 create mode 100644 sound/soc/bcm/cygnus-ssp.h

-- 
1.9.1



From simran.rai at broadcom.com  Tue May 17 17:01:07 2016
From: simran.rai at broadcom.com (Simran Rai)
Date: Tue, 17 May 2016 17:01:07 -0700
Subject: [PATCH v7 1/3] ASoC: cygnus: Add DT bindings for Broadcom Cygnus audio
In-Reply-To: <1463529669-25022-1-git-send-email-simran.rai@broadcom.com>
References: <1463529669-25022-1-git-send-email-simran.rai@broadcom.com>
Message-ID: <1463529669-25022-2-git-send-email-simran.rai@broadcom.com>

From: Simran Rai <ssimran at broadcom.com>

Add bindings for audio driver in Broadcom Cygnus.

Signed-off-by: Lori Hikichi <lhikichi at broadcom.com>
Signed-off-by: Simran Rai <ssimran at broadcom.com>
Reviewed-by: Ray Jui <rjui at broadcom.com>
Reviewed-by: Scott Branden <sbranden at broadcom.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../bindings/sound/brcm,cygnus-audio.txt           | 67 ++++++++++++++++++++++
 1 file changed, 67 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/brcm,cygnus-audio.txt

diff --git a/Documentation/devicetree/bindings/sound/brcm,cygnus-audio.txt b/Documentation/devicetree/bindings/sound/brcm,cygnus-audio.txt
new file mode 100644
index 0000000..b139e66
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/brcm,cygnus-audio.txt
@@ -0,0 +1,67 @@
+BROADCOM Cygnus Audio I2S/TDM/SPDIF controller
+
+Required properties:
+	- compatible : "brcm,cygnus-audio"
+	- #address-cells: 32bit valued, 1 cell.
+	- #size-cells:  32bit valued, 0 cell.
+	- reg : Should contain audio registers location and length
+	- reg-names: names of the registers listed in "reg" property
+		Valid names are "aud" and "i2s_in". "aud" contains a
+		set of DMA, I2S_OUT and SPDIF registers. "i2s_in" contains
+		a set of I2S_IN registers.
+	- clocks: PLL and leaf clocks used by audio ports
+	- assigned-clocks: PLL and leaf clocks
+	- assigned-clock-parents: parent clocks of the assigned clocks
+		(usually the PLL)
+	- assigned-clock-rates: List of clock frequencies of the
+		assigned clocks
+	- clock-names: names of 3 leaf clocks used by audio ports
+		Valid names are "ch0_audio", "ch1_audio", "ch2_audio"
+	- interrupts: audio DMA interrupt number
+
+SSP Subnode properties:
+- reg: The index of ssp port interface to use
+	Valid value are 0, 1, 2, or 3 (for spdif)
+
+Example:
+	cygnus_audio: audio at 180ae000 {
+		compatible = "brcm,cygnus-audio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x180ae000 0xafd>, <0x180aec00 0x1f8>;
+		reg-names = "aud", "i2s_in";
+		clocks = <&audiopll BCM_CYGNUS_AUDIOPLL_CH0>,
+				<&audiopll BCM_CYGNUS_AUDIOPLL_CH1>,
+				<&audiopll BCM_CYGNUS_AUDIOPLL_CH2>;
+		assigned-clocks = <&audiopll BCM_CYGNUS_AUDIOPLL>,
+							<&audiopll BCM_CYGNUS_AUDIOPLL_CH0>,
+							<&audiopll BCM_CYGNUS_AUDIOPLL_CH1>,
+							<&audiopll BCM_CYGNUS_AUDIOPLL_CH2>;
+		assigned-clock-parents = <&audiopll BCM_CYGNUS_AUDIOPLL>;
+		assigned-clock-rates = <1769470191>,
+								<0>,
+								<0>,
+								<0>;
+		clock-names = "ch0_audio", "ch1_audio", "ch2_audio";
+		interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+
+		ssp0: ssp_port at 0 {
+			reg = <0>;
+			status = "okay";
+		};
+
+		ssp1: ssp_port at 1 {
+			reg = <1>;
+			status = "disabled";
+		};
+
+		ssp2: ssp_port at 2 {
+			reg = <2>;
+			status = "disabled";
+		};
+
+		spdif: spdif_port at 3 {
+			reg = <3>;
+			status = "disabled";
+		};
+	};
-- 
1.9.1



From simran.rai at broadcom.com  Tue May 17 17:01:08 2016
From: simran.rai at broadcom.com (Simran Rai)
Date: Tue, 17 May 2016 17:01:08 -0700
Subject: [PATCH v7 2/3] ASoC: cygnus: Add Cygnus audio DAI driver
In-Reply-To: <1463529669-25022-1-git-send-email-simran.rai@broadcom.com>
References: <1463529669-25022-1-git-send-email-simran.rai@broadcom.com>
Message-ID: <1463529669-25022-3-git-send-email-simran.rai@broadcom.com>

This patch adds Cygnus audio DAI driver. It supports I2S, TDM
and SPDIF modes and uses three clocks derived from PLL.

This patchset has been tested on Cygnus wireless audio
bcm958305K board.

Signed-off-by: Lori Hikichi <lhikichi at broadcom.com>
Signed-off-by: Simran Rai <ssimran at broadcom.com>
Reviewed-by: Ray Jui <rjui at broadcom.com>
Reviewed-by: Arun Parameswaran <arunp at broadcom.com>
Reviewed-by: Scott Branden <sbranden at broadcom.com>
---
 sound/soc/bcm/cygnus-ssp.c | 1529 ++++++++++++++++++++++++++++++++++++++++++++
 sound/soc/bcm/cygnus-ssp.h |  139 ++++
 2 files changed, 1668 insertions(+)
 create mode 100644 sound/soc/bcm/cygnus-ssp.c
 create mode 100644 sound/soc/bcm/cygnus-ssp.h

diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c
new file mode 100644
index 0000000..e710bb0
--- /dev/null
+++ b/sound/soc/bcm/cygnus-ssp.c
@@ -0,0 +1,1529 @@
+/*
+ * Copyright (C) 2014-2015 Broadcom Corporation
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+
+#include "cygnus-ssp.h"
+
+#define DEFAULT_VCO    1354750204
+
+#define CYGNUS_TDM_RATE \
+		(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
+		SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050 | \
+		SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+		SNDRV_PCM_RATE_48000)
+
+#define CAPTURE_FCI_ID_BASE 0x180
+#define CYGNUS_SSP_TRISTATE_MASK 0x001fff
+#define CYGNUS_PLLCLKSEL_MASK 0xf
+
+/* Used with stream_on field to indicate which streams are active */
+#define  PLAYBACK_STREAM_MASK   BIT(0)
+#define  CAPTURE_STREAM_MASK    BIT(1)
+
+#define I2S_STREAM_CFG_MASK      0xff003ff
+#define I2S_CAP_STREAM_CFG_MASK  0xf0
+#define SPDIF_STREAM_CFG_MASK    0x3ff
+#define CH_GRP_STEREO            0x1
+
+/* Begin register offset defines */
+#define AUD_MISC_SEROUT_OE_REG_BASE  0x01c
+#define AUD_MISC_SEROUT_SPDIF_OE  12
+#define AUD_MISC_SEROUT_MCLK_OE   3
+#define AUD_MISC_SEROUT_LRCK_OE   2
+#define AUD_MISC_SEROUT_SCLK_OE   1
+#define AUD_MISC_SEROUT_SDAT_OE   0
+
+/* AUD_FMM_BF_CTRL_xxx regs */
+#define BF_DST_CFG0_OFFSET  0x100
+#define BF_DST_CFG1_OFFSET  0x104
+#define BF_DST_CFG2_OFFSET  0x108
+
+#define BF_DST_CTRL0_OFFSET 0x130
+#define BF_DST_CTRL1_OFFSET 0x134
+#define BF_DST_CTRL2_OFFSET 0x138
+
+#define BF_SRC_CFG0_OFFSET  0x148
+#define BF_SRC_CFG1_OFFSET  0x14c
+#define BF_SRC_CFG2_OFFSET  0x150
+#define BF_SRC_CFG3_OFFSET  0x154
+
+#define BF_SRC_CTRL0_OFFSET 0x1c0
+#define BF_SRC_CTRL1_OFFSET 0x1c4
+#define BF_SRC_CTRL2_OFFSET 0x1c8
+#define BF_SRC_CTRL3_OFFSET 0x1cc
+
+#define BF_SRC_GRP0_OFFSET  0x1fc
+#define BF_SRC_GRP1_OFFSET  0x200
+#define BF_SRC_GRP2_OFFSET  0x204
+#define BF_SRC_GRP3_OFFSET  0x208
+
+#define BF_SRC_GRP_EN_OFFSET        0x320
+#define BF_SRC_GRP_FLOWON_OFFSET    0x324
+#define BF_SRC_GRP_SYNC_DIS_OFFSET  0x328
+
+/* AUD_FMM_IOP_OUT_I2S_xxx regs */
+#define OUT_I2S_0_STREAM_CFG_OFFSET 0xa00
+#define OUT_I2S_0_CFG_OFFSET        0xa04
+#define OUT_I2S_0_MCLK_CFG_OFFSET   0xa0c
+
+#define OUT_I2S_1_STREAM_CFG_OFFSET 0xa40
+#define OUT_I2S_1_CFG_OFFSET        0xa44
+#define OUT_I2S_1_MCLK_CFG_OFFSET   0xa4c
+
+#define OUT_I2S_2_STREAM_CFG_OFFSET 0xa80
+#define OUT_I2S_2_CFG_OFFSET        0xa84
+#define OUT_I2S_2_MCLK_CFG_OFFSET   0xa8c
+
+/* AUD_FMM_IOP_OUT_SPDIF_xxx regs */
+#define SPDIF_STREAM_CFG_OFFSET  0xac0
+#define SPDIF_CTRL_OFFSET        0xac4
+#define SPDIF_FORMAT_CFG_OFFSET  0xad8
+#define SPDIF_MCLK_CFG_OFFSET    0xadc
+
+/* AUD_FMM_IOP_PLL_0_xxx regs */
+#define IOP_PLL_0_MACRO_OFFSET    0xb00
+#define IOP_PLL_0_MDIV_Ch0_OFFSET 0xb14
+#define IOP_PLL_0_MDIV_Ch1_OFFSET 0xb18
+#define IOP_PLL_0_MDIV_Ch2_OFFSET 0xb1c
+
+#define IOP_PLL_0_ACTIVE_MDIV_Ch0_OFFSET 0xb30
+#define IOP_PLL_0_ACTIVE_MDIV_Ch1_OFFSET 0xb34
+#define IOP_PLL_0_ACTIVE_MDIV_Ch2_OFFSET 0xb38
+
+/* AUD_FMM_IOP_xxx regs */
+#define IOP_PLL_0_CONTROL_OFFSET     0xb04
+#define IOP_PLL_0_USER_NDIV_OFFSET   0xb08
+#define IOP_PLL_0_ACTIVE_NDIV_OFFSET 0xb20
+#define IOP_PLL_0_RESET_OFFSET       0xb5c
+
+/* AUD_FMM_IOP_IN_I2S_xxx regs */
+#define IN_I2S_0_STREAM_CFG_OFFSET 0x00
+#define IN_I2S_0_CFG_OFFSET        0x04
+#define IN_I2S_1_STREAM_CFG_OFFSET 0x40
+#define IN_I2S_1_CFG_OFFSET        0x44
+#define IN_I2S_2_STREAM_CFG_OFFSET 0x80
+#define IN_I2S_2_CFG_OFFSET        0x84
+
+/* AUD_FMM_IOP_MISC_xxx regs */
+#define IOP_SW_INIT_LOGIC          0x1c0
+
+/* End register offset defines */
+
+
+/* AUD_FMM_IOP_OUT_I2S_x_MCLK_CFG_0_REG */
+#define I2S_OUT_MCLKRATE_SHIFT 16
+
+/* AUD_FMM_IOP_OUT_I2S_x_MCLK_CFG_REG */
+#define I2S_OUT_PLLCLKSEL_SHIFT  0
+
+/* AUD_FMM_IOP_OUT_I2S_x_STREAM_CFG */
+#define I2S_OUT_STREAM_ENA  31
+#define I2S_OUT_STREAM_CFG_GROUP_ID  20
+#define I2S_OUT_STREAM_CFG_CHANNEL_GROUPING  24
+
+/* AUD_FMM_IOP_IN_I2S_x_CAP */
+#define I2S_IN_STREAM_CFG_CAP_ENA   31
+#define I2S_IN_STREAM_CFG_0_GROUP_ID 4
+
+/* AUD_FMM_IOP_OUT_I2S_x_I2S_CFG_REG */
+#define I2S_OUT_CFGX_CLK_ENA         0
+#define I2S_OUT_CFGX_DATA_ENABLE     1
+#define I2S_OUT_CFGX_DATA_ALIGNMENT  6
+#define I2S_OUT_CFGX_BITS_PER_SLOT  13
+#define I2S_OUT_CFGX_VALID_SLOT     14
+#define I2S_OUT_CFGX_FSYNC_WIDTH    18
+#define I2S_OUT_CFGX_SCLKS_PER_1FS_DIV32 26
+#define I2S_OUT_CFGX_SLAVE_MODE     30
+#define I2S_OUT_CFGX_TDM_MODE       31
+
+/* AUD_FMM_BF_CTRL_SOURCECH_CFGx_REG */
+#define BF_SRC_CFGX_SFIFO_ENA              0
+#define BF_SRC_CFGX_BUFFER_PAIR_ENABLE     1
+#define BF_SRC_CFGX_SAMPLE_CH_MODE         2
+#define BF_SRC_CFGX_SFIFO_SZ_DOUBLE        5
+#define BF_SRC_CFGX_NOT_PAUSE_WHEN_EMPTY  10
+#define BF_SRC_CFGX_BIT_RES               20
+#define BF_SRC_CFGX_PROCESS_SEQ_ID_VALID  31
+
+/* AUD_FMM_BF_CTRL_DESTCH_CFGx_REG */
+#define BF_DST_CFGX_CAP_ENA              0
+#define BF_DST_CFGX_BUFFER_PAIR_ENABLE   1
+#define BF_DST_CFGX_DFIFO_SZ_DOUBLE      2
+#define BF_DST_CFGX_NOT_PAUSE_WHEN_FULL 11
+#define BF_DST_CFGX_FCI_ID              12
+#define BF_DST_CFGX_CAP_MODE            24
+#define BF_DST_CFGX_PROC_SEQ_ID_VALID   31
+
+/* AUD_FMM_IOP_OUT_SPDIF_xxx */
+#define SPDIF_0_OUT_DITHER_ENA     3
+#define SPDIF_0_OUT_STREAM_ENA    31
+
+/* AUD_FMM_IOP_PLL_0_USER */
+#define IOP_PLL_0_USER_NDIV_FRAC   10
+
+/* AUD_FMM_IOP_PLL_0_ACTIVE */
+#define IOP_PLL_0_ACTIVE_NDIV_FRAC 10
+
+
+#define INIT_SSP_REGS(num) (struct cygnus_ssp_regs){ \
+		.i2s_stream_cfg = OUT_I2S_ ##num## _STREAM_CFG_OFFSET, \
+		.i2s_cap_stream_cfg = IN_I2S_ ##num## _STREAM_CFG_OFFSET, \
+		.i2s_cfg = OUT_I2S_ ##num## _CFG_OFFSET, \
+		.i2s_cap_cfg = IN_I2S_ ##num## _CFG_OFFSET, \
+		.i2s_mclk_cfg = OUT_I2S_ ##num## _MCLK_CFG_OFFSET, \
+		.bf_destch_ctrl = BF_DST_CTRL ##num## _OFFSET, \
+		.bf_destch_cfg = BF_DST_CFG ##num## _OFFSET, \
+		.bf_sourcech_ctrl = BF_SRC_CTRL ##num## _OFFSET, \
+		.bf_sourcech_cfg = BF_SRC_CFG ##num## _OFFSET, \
+		.bf_sourcech_grp = BF_SRC_GRP ##num## _OFFSET \
+}
+
+struct pll_macro_entry {
+	u32 mclk;
+	u32 pll_ch_num;
+};
+
+/*
+ * PLL has 3 output channels (1x, 2x, and 4x). Below are
+ * the common MCLK frequencies used by audio driver
+ */
+static const struct pll_macro_entry pll_predef_mclk[] = {
+	{ 4096000, 0},
+	{ 8192000, 1},
+	{16384000, 2},
+
+	{ 5644800, 0},
+	{11289600, 1},
+	{22579200, 2},
+
+	{ 6144000, 0},
+	{12288000, 1},
+	{24576000, 2},
+
+	{12288000, 0},
+	{24576000, 1},
+	{49152000, 2},
+
+	{22579200, 0},
+	{45158400, 1},
+	{90316800, 2},
+
+	{24576000, 0},
+	{49152000, 1},
+	{98304000, 2},
+};
+
+/* List of valid frame sizes for tdm mode */
+static const int ssp_valid_tdm_framesize[] = {32, 64, 128, 256, 512};
+
+/*
+ * Use this relationship to derive the sampling rate (lrclk)
+ * lrclk = (mclk) / ((2*mclk_to_sclk_ratio) * (32 * SCLK))).
+ *
+ * Use mclk and pll_ch from the table above
+ *
+ * Valid SCLK = 0/1/2/4/8/12
+ *
+ * mclk_to_sclk_ratio = number of MCLK per SCLK. Division is twice the
+ * value programmed in this field.
+ * Valid mclk_to_sclk_ratio = 1 through to 15
+ *
+ * eg: To set lrclk = 48khz, set mclk = 12288000, mclk_to_sclk_ratio = 2,
+ * SCLK = 64
+ */
+struct _ssp_clk_coeff {
+	u32 mclk;
+	u32 sclk_rate;
+	u32 rate;
+	u32 mclk_rate;
+};
+
+static const struct _ssp_clk_coeff ssp_clk_coeff[] = {
+	{ 4096000,  32,  16000, 4},
+	{ 4096000,  32,  32000, 2},
+	{ 4096000,  64,   8000, 4},
+	{ 4096000,  64,  16000, 2},
+	{ 4096000,  64,  32000, 1},
+	{ 4096000, 128,   8000, 2},
+	{ 4096000, 128,  16000, 1},
+	{ 4096000, 256,   8000, 1},
+
+	{ 6144000,  32,  16000, 6},
+	{ 6144000,  32,  32000, 3},
+	{ 6144000,  32,  48000, 2},
+	{ 6144000,  32,  96000, 1},
+	{ 6144000,  64,   8000, 6},
+	{ 6144000,  64,  16000, 3},
+	{ 6144000,  64,  48000, 1},
+	{ 6144000, 128,   8000, 3},
+
+	{ 8192000,  32,  32000, 4},
+	{ 8192000,  64,  16000, 4},
+	{ 8192000,  64,  32000, 2},
+	{ 8192000, 128,   8000, 4},
+	{ 8192000, 128,  16000, 2},
+	{ 8192000, 128,  32000, 1},
+	{ 8192000, 256,   8000, 2},
+	{ 8192000, 256,  16000, 1},
+	{ 8192000, 512,   8000, 1},
+
+	{12288000,  32,  32000, 6},
+	{12288000,  32,  48000, 4},
+	{12288000,  32,  96000, 2},
+	{12288000,  32, 192000, 1},
+	{12288000,  64,  16000, 6},
+	{12288000,  64,  32000, 3},
+	{12288000,  64,  48000, 2},
+	{12288000,  64,  96000, 1},
+	{12288000, 128,   8000, 6},
+	{12288000, 128,  16000, 3},
+	{12288000, 128,  48000, 1},
+	{12288000, 256,   8000, 3},
+
+	{16384000,  64,  32000, 4},
+	{16384000, 128,  16000, 4},
+	{16384000, 128,  32000, 2},
+	{16384000, 256,   8000, 4},
+	{16384000, 256,  16000, 2},
+	{16384000, 256,  32000, 1},
+	{16384000, 512,   8000, 2},
+	{16384000, 512,  16000, 1},
+
+	{24576000,  32,  96000, 4},
+	{24576000,  32, 192000, 2},
+	{24576000,  64,  32000, 6},
+	{24576000,  64,  48000, 4},
+	{24576000,  64,  96000, 2},
+	{24576000,  64, 192000, 1},
+	{24576000, 128,  16000, 6},
+	{24576000, 128,  32000, 3},
+	{24576000, 128,  48000, 2},
+	{24576000, 256,   8000, 6},
+	{24576000, 256,  16000, 3},
+	{24576000, 256,  48000, 1},
+	{24576000, 512,   8000, 3},
+
+	{49152000,  32, 192000, 4},
+	{49152000,  64,  96000, 4},
+	{49152000,  64, 192000, 2},
+	{49152000, 128,  32000, 6},
+	{49152000, 128,  48000, 4},
+	{49152000, 128,  96000, 2},
+	{49152000, 128, 192000, 1},
+	{49152000, 256,  16000, 6},
+	{49152000, 256,  32000, 3},
+	{49152000, 256,  48000, 2},
+	{49152000, 256,  96000, 1},
+	{49152000, 512,   8000, 6},
+	{49152000, 512,  16000, 3},
+	{49152000, 512,  48000, 1},
+
+	{ 5644800,  32,  22050, 4},
+	{ 5644800,  32,  44100, 2},
+	{ 5644800,  32,  88200, 1},
+	{ 5644800,  64,  11025, 4},
+	{ 5644800,  64,  22050, 2},
+	{ 5644800,  64,  44100, 1},
+
+	{11289600,  32,  44100, 4},
+	{11289600,  32,  88200, 2},
+	{11289600,  32, 176400, 1},
+	{11289600,  64,  22050, 4},
+	{11289600,  64,  44100, 2},
+	{11289600,  64,  88200, 1},
+	{11289600, 128,  11025, 4},
+	{11289600, 128,  22050, 2},
+	{11289600, 128,  44100, 1},
+
+	{22579200,  32,  88200, 4},
+	{22579200,  32, 176400, 2},
+	{22579200,  64,  44100, 4},
+	{22579200,  64,  88200, 2},
+	{22579200,  64, 176400, 1},
+	{22579200, 128,  22050, 4},
+	{22579200, 128,  44100, 2},
+	{22579200, 128,  88200, 1},
+	{22579200, 256,  11025, 4},
+	{22579200, 256,  22050, 2},
+	{22579200, 256,  44100, 1},
+
+	{45158400,  32, 176400, 4},
+	{45158400,  64,  88200, 4},
+	{45158400,  64, 176400, 2},
+	{45158400, 128,  44100, 4},
+	{45158400, 128,  88200, 2},
+	{45158400, 128, 176400, 1},
+	{45158400, 256,  22050, 4},
+	{45158400, 256,  44100, 2},
+	{45158400, 256,  88200, 1},
+	{45158400, 512,  11025, 4},
+	{45158400, 512,  22050, 2},
+	{45158400, 512,  44100, 1},
+};
+
+static struct cygnus_aio_port *cygnus_dai_get_portinfo(struct snd_soc_dai *dai)
+{
+	struct cygnus_audio *cygaud = snd_soc_dai_get_drvdata(dai);
+
+	return &cygaud->portinfo[dai->id];
+}
+
+static int audio_ssp_init_portregs(struct cygnus_aio_port *aio)
+{
+	u32 value, fci_id;
+	int status = 0;
+
+	switch (aio->port_type) {
+	case PORT_TDM:
+		value = readl(aio->cygaud->audio + aio->regs.i2s_stream_cfg);
+		value &= ~I2S_STREAM_CFG_MASK;
+
+		/* Set Group ID */
+		writel(aio->portnum,
+			aio->cygaud->audio + aio->regs.bf_sourcech_grp);
+
+		/* Configure the AUD_FMM_IOP_OUT_I2S_x_STREAM_CFG reg */
+		value |= aio->portnum << I2S_OUT_STREAM_CFG_GROUP_ID;
+		value |= aio->portnum; /* FCI ID is the port num */
+		value |= CH_GRP_STEREO << I2S_OUT_STREAM_CFG_CHANNEL_GROUPING;
+		writel(value, aio->cygaud->audio + aio->regs.i2s_stream_cfg);
+
+		/* Configure the AUD_FMM_BF_CTRL_SOURCECH_CFGX reg */
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value &= ~BIT(BF_SRC_CFGX_NOT_PAUSE_WHEN_EMPTY);
+		value |= BIT(BF_SRC_CFGX_SFIFO_SZ_DOUBLE);
+		value |= BIT(BF_SRC_CFGX_PROCESS_SEQ_ID_VALID);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+
+		/* Configure the AUD_FMM_IOP_IN_I2S_x_CAP_STREAM_CFG_0 reg */
+		value = readl(aio->cygaud->i2s_in +
+			aio->regs.i2s_cap_stream_cfg);
+		value &= ~I2S_CAP_STREAM_CFG_MASK;
+		value |= aio->portnum << I2S_IN_STREAM_CFG_0_GROUP_ID;
+		writel(value, aio->cygaud->i2s_in +
+			aio->regs.i2s_cap_stream_cfg);
+
+		/* Configure the AUD_FMM_BF_CTRL_DESTCH_CFGX_REG_BASE reg */
+		fci_id = CAPTURE_FCI_ID_BASE + aio->portnum;
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_destch_cfg);
+		value |= BIT(BF_DST_CFGX_DFIFO_SZ_DOUBLE);
+		value &= ~BIT(BF_DST_CFGX_NOT_PAUSE_WHEN_FULL);
+		value |= (fci_id << BF_DST_CFGX_FCI_ID);
+		value |= BIT(BF_DST_CFGX_PROC_SEQ_ID_VALID);
+		writel(value, aio->cygaud->audio + aio->regs.bf_destch_cfg);
+
+		/* Enable the transmit pin for this port */
+		value = readl(aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+		value &= ~BIT((aio->portnum * 4) + AUD_MISC_SEROUT_SDAT_OE);
+		writel(value, aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+		break;
+	case PORT_SPDIF:
+		writel(aio->portnum, aio->cygaud->audio + BF_SRC_GRP3_OFFSET);
+
+		value = readl(aio->cygaud->audio + SPDIF_CTRL_OFFSET);
+		value |= BIT(SPDIF_0_OUT_DITHER_ENA);
+		writel(value, aio->cygaud->audio + SPDIF_CTRL_OFFSET);
+
+		/* Enable and set the FCI ID for the SPDIF channel */
+		value = readl(aio->cygaud->audio + SPDIF_STREAM_CFG_OFFSET);
+		value &= ~SPDIF_STREAM_CFG_MASK;
+		value |= aio->portnum; /* FCI ID is the port num */
+		value |= BIT(SPDIF_0_OUT_STREAM_ENA);
+		writel(value, aio->cygaud->audio + SPDIF_STREAM_CFG_OFFSET);
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value &= ~BIT(BF_SRC_CFGX_NOT_PAUSE_WHEN_EMPTY);
+		value |= BIT(BF_SRC_CFGX_SFIFO_SZ_DOUBLE);
+		value |= BIT(BF_SRC_CFGX_PROCESS_SEQ_ID_VALID);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+
+		/* Enable the spdif output pin */
+		value = readl(aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+		value &= ~BIT(AUD_MISC_SEROUT_SPDIF_OE);
+		writel(value, aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+		break;
+	default:
+		dev_err(aio->cygaud->dev, "Port not supported\n");
+		status = -EINVAL;
+	}
+
+	return status;
+}
+
+static void audio_ssp_in_enable(struct cygnus_aio_port *aio)
+{
+	u32 value;
+
+	value = readl(aio->cygaud->audio + aio->regs.bf_destch_cfg);
+	value |= BIT(BF_DST_CFGX_CAP_ENA);
+	writel(value, aio->cygaud->audio + aio->regs.bf_destch_cfg);
+
+	writel(0x1, aio->cygaud->audio + aio->regs.bf_destch_ctrl);
+
+	value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+	value |= BIT(I2S_OUT_CFGX_CLK_ENA);
+	value |= BIT(I2S_OUT_CFGX_DATA_ENABLE);
+	writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
+
+	value = readl(aio->cygaud->i2s_in + aio->regs.i2s_cap_stream_cfg);
+	value |= BIT(I2S_IN_STREAM_CFG_CAP_ENA);
+	writel(value, aio->cygaud->i2s_in + aio->regs.i2s_cap_stream_cfg);
+
+	aio->streams_on |= CAPTURE_STREAM_MASK;
+}
+
+static void audio_ssp_in_disable(struct cygnus_aio_port *aio)
+{
+	u32 value;
+
+	value = readl(aio->cygaud->i2s_in + aio->regs.i2s_cap_stream_cfg);
+	value &= ~BIT(I2S_IN_STREAM_CFG_CAP_ENA);
+	writel(value, aio->cygaud->i2s_in + aio->regs.i2s_cap_stream_cfg);
+
+	aio->streams_on &= ~CAPTURE_STREAM_MASK;
+
+	/* If both playback and capture are off */
+	if (!aio->streams_on) {
+		value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+		value &= ~BIT(I2S_OUT_CFGX_CLK_ENA);
+		value &= ~BIT(I2S_OUT_CFGX_DATA_ENABLE);
+		writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
+	}
+
+	writel(0x0, aio->cygaud->audio + aio->regs.bf_destch_ctrl);
+
+	value = readl(aio->cygaud->audio + aio->regs.bf_destch_cfg);
+	value &= ~BIT(BF_DST_CFGX_CAP_ENA);
+	writel(value, aio->cygaud->audio + aio->regs.bf_destch_cfg);
+}
+
+static int audio_ssp_out_enable(struct cygnus_aio_port *aio)
+{
+	u32 value;
+	int status = 0;
+
+	switch (aio->port_type) {
+	case PORT_TDM:
+		value = readl(aio->cygaud->audio + aio->regs.i2s_stream_cfg);
+		value |= BIT(I2S_OUT_STREAM_ENA);
+		writel(value, aio->cygaud->audio + aio->regs.i2s_stream_cfg);
+
+		writel(1, aio->cygaud->audio + aio->regs.bf_sourcech_ctrl);
+
+		value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+		value |= BIT(I2S_OUT_CFGX_CLK_ENA);
+		value |= BIT(I2S_OUT_CFGX_DATA_ENABLE);
+		writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value |= BIT(BF_SRC_CFGX_SFIFO_ENA);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+
+		aio->streams_on |= PLAYBACK_STREAM_MASK;
+		break;
+	case PORT_SPDIF:
+		value = readl(aio->cygaud->audio + SPDIF_FORMAT_CFG_OFFSET);
+		value |= 0x3;
+		writel(value, aio->cygaud->audio + SPDIF_FORMAT_CFG_OFFSET);
+
+		writel(1, aio->cygaud->audio + aio->regs.bf_sourcech_ctrl);
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value |= BIT(BF_SRC_CFGX_SFIFO_ENA);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		break;
+	default:
+		dev_err(aio->cygaud->dev,
+			"Port not supported %d\n", aio->portnum);
+		status = -EINVAL;
+	}
+
+	return status;
+}
+
+static int audio_ssp_out_disable(struct cygnus_aio_port *aio)
+{
+	u32 value;
+	int status = 0;
+
+	switch (aio->port_type) {
+	case PORT_TDM:
+		aio->streams_on &= ~PLAYBACK_STREAM_MASK;
+
+		/* If both playback and capture are off */
+		if (!aio->streams_on) {
+			value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+			value &= ~BIT(I2S_OUT_CFGX_CLK_ENA);
+			value &= ~BIT(I2S_OUT_CFGX_DATA_ENABLE);
+			writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
+		}
+
+		/* set group_sync_dis = 1 */
+		value = readl(aio->cygaud->audio + BF_SRC_GRP_SYNC_DIS_OFFSET);
+		value |= BIT(aio->portnum);
+		writel(value, aio->cygaud->audio + BF_SRC_GRP_SYNC_DIS_OFFSET);
+
+		writel(0, aio->cygaud->audio + aio->regs.bf_sourcech_ctrl);
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value &= ~BIT(BF_SRC_CFGX_SFIFO_ENA);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+
+		/* set group_sync_dis = 0 */
+		value = readl(aio->cygaud->audio + BF_SRC_GRP_SYNC_DIS_OFFSET);
+		value &= ~BIT(aio->portnum);
+		writel(value, aio->cygaud->audio + BF_SRC_GRP_SYNC_DIS_OFFSET);
+
+		value = readl(aio->cygaud->audio + aio->regs.i2s_stream_cfg);
+		value &= ~BIT(I2S_OUT_STREAM_ENA);
+		writel(value, aio->cygaud->audio + aio->regs.i2s_stream_cfg);
+
+		/* IOP SW INIT on OUT_I2S_x */
+		value = readl(aio->cygaud->i2s_in + IOP_SW_INIT_LOGIC);
+		value |= BIT(aio->portnum);
+		writel(value, aio->cygaud->i2s_in + IOP_SW_INIT_LOGIC);
+		value &= ~BIT(aio->portnum);
+		writel(value, aio->cygaud->i2s_in + IOP_SW_INIT_LOGIC);
+		break;
+	case PORT_SPDIF:
+		value = readl(aio->cygaud->audio + SPDIF_FORMAT_CFG_OFFSET);
+		value &= ~0x3;
+		writel(value, aio->cygaud->audio + SPDIF_FORMAT_CFG_OFFSET);
+		writel(0, aio->cygaud->audio + aio->regs.bf_sourcech_ctrl);
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value &= ~BIT(BF_SRC_CFGX_SFIFO_ENA);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		break;
+	default:
+		dev_err(aio->cygaud->dev,
+			"Port not supported %d\n", aio->portnum);
+		status = -EINVAL;
+	}
+
+	return status;
+}
+
+static int pll_configure_mclk(struct cygnus_audio *cygaud, u32 mclk,
+	struct cygnus_aio_port *aio)
+{
+	int i = 0, error;
+	bool found = false;
+	const struct pll_macro_entry *p_entry;
+	struct clk *ch_clk;
+
+	for (i = 0; i < ARRAY_SIZE(pll_predef_mclk); i++) {
+		p_entry = &pll_predef_mclk[i];
+		if (p_entry->mclk == mclk) {
+			found = true;
+			break;
+		}
+	}
+	if (!found) {
+		dev_err(cygaud->dev,
+			"%s No valid mclk freq (%u) found!\n", __func__, mclk);
+		return -EINVAL;
+	}
+
+	ch_clk = cygaud->audio_clk[p_entry->pll_ch_num];
+
+	if ((aio->clk_trace.cap_en) && (!aio->clk_trace.cap_clk_en)) {
+		error = clk_prepare_enable(ch_clk);
+		if (error) {
+			dev_err(cygaud->dev, "%s clk_prepare_enable failed %d\n",
+				__func__, error);
+			return error;
+		}
+		aio->clk_trace.cap_clk_en = true;
+	}
+
+	if ((aio->clk_trace.play_en) && (!aio->clk_trace.play_clk_en)) {
+		error = clk_prepare_enable(ch_clk);
+		if (error) {
+			dev_err(cygaud->dev, "%s clk_prepare_enable failed %d\n",
+				__func__, error);
+			return error;
+		}
+		aio->clk_trace.play_clk_en = true;
+	}
+
+	error = clk_set_rate(ch_clk, mclk);
+	if (error) {
+		dev_err(cygaud->dev, "%s Set MCLK rate failed: %d\n",
+			__func__, error);
+		return error;
+	}
+
+	return p_entry->pll_ch_num;
+}
+
+static int cygnus_ssp_set_clocks(struct cygnus_aio_port *aio,
+			struct cygnus_audio *cygaud)
+{
+	u32 value, i = 0;
+	u32 mask = 0xf;
+	u32 sclk;
+	bool found = false;
+	const struct _ssp_clk_coeff *p_entry = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(ssp_clk_coeff); i++) {
+		p_entry = &ssp_clk_coeff[i];
+		if ((p_entry->rate == aio->lrclk) &&
+		    (p_entry->sclk_rate == aio->bit_per_frame) &&
+		    (p_entry->mclk == aio->mclk)) {
+			found = true;
+			break;
+		}
+	}
+	if (!found) {
+		dev_err(aio->cygaud->dev,
+			"No valid match found in ssp_clk_coeff array\n");
+		dev_err(aio->cygaud->dev, "lrclk = %u, bits/frame = %u, mclk = %u\n",
+			aio->lrclk, aio->bit_per_frame, aio->mclk);
+		return -EINVAL;
+	}
+
+	sclk = aio->bit_per_frame;
+	if (sclk == 512)
+		sclk = 0;
+	/* sclks_per_1fs_div = sclk cycles/32 */
+	sclk /= 32;
+	/* Set sclk rate */
+	switch (aio->port_type) {
+	case PORT_TDM:
+		/* Set number of bitclks per frame */
+		value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+		value &= ~(mask << I2S_OUT_CFGX_SCLKS_PER_1FS_DIV32);
+		value |= sclk << I2S_OUT_CFGX_SCLKS_PER_1FS_DIV32;
+		writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
+		dev_dbg(aio->cygaud->dev,
+			"SCLKS_PER_1FS_DIV32 = 0x%x\n", value);
+		break;
+	case PORT_SPDIF:
+		break;
+	default:
+		dev_err(aio->cygaud->dev, "Unknown port type\n");
+		return -EINVAL;
+	}
+
+	/* Set MCLK_RATE ssp port (spdif and ssp are the same) */
+	value = readl(aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
+	value &= ~(0xf << I2S_OUT_MCLKRATE_SHIFT);
+	value |= (p_entry->mclk_rate << I2S_OUT_MCLKRATE_SHIFT);
+	writel(value, aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
+
+	dev_dbg(aio->cygaud->dev, "mclk cfg reg = 0x%x\n", value);
+	dev_dbg(aio->cygaud->dev, "bits per frame = %u, mclk = %u Hz, lrclk = %u Hz\n",
+			aio->bit_per_frame, aio->mclk, aio->lrclk);
+	return 0;
+}
+
+static int cygnus_ssp_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *params,
+				 struct snd_soc_dai *dai)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
+	struct cygnus_audio *cygaud = snd_soc_dai_get_drvdata(dai);
+	int rate, bitres;
+	u32 value;
+	u32 mask = 0x1f;
+	int ret = 0;
+
+	dev_dbg(aio->cygaud->dev, "%s port = %d\n", __func__, aio->portnum);
+	dev_dbg(aio->cygaud->dev, "params_channels %d\n",
+			params_channels(params));
+	dev_dbg(aio->cygaud->dev, "rate %d\n", params_rate(params));
+	dev_dbg(aio->cygaud->dev, "format %d\n", params_format(params));
+
+	rate = params_rate(params);
+
+	switch (aio->mode) {
+	case CYGNUS_SSPMODE_TDM:
+		if ((rate == 192000) && (params_channels(params) > 4)) {
+			dev_err(aio->cygaud->dev, "Cannot run %d channels at %dHz\n",
+				params_channels(params), rate);
+			return -EINVAL;
+		}
+		break;
+	case CYGNUS_SSPMODE_I2S:
+		aio->bit_per_frame = 64; /* I2S must be 64 bit per frame */
+		break;
+	default:
+		dev_err(aio->cygaud->dev,
+			"%s port running in unknown mode\n", __func__);
+		return -EINVAL;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value &= ~BIT(BF_SRC_CFGX_BUFFER_PAIR_ENABLE);
+		/* Configure channels as mono or stereo/TDM */
+		if (params_channels(params) == 1)
+			value |= BIT(BF_SRC_CFGX_SAMPLE_CH_MODE);
+		else
+			value &= ~BIT(BF_SRC_CFGX_SAMPLE_CH_MODE);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+
+		switch (params_format(params)) {
+		case SNDRV_PCM_FORMAT_S8:
+			if (aio->port_type == PORT_SPDIF) {
+				dev_err(aio->cygaud->dev,
+				"SPDIF does not support 8bit format\n");
+				return -EINVAL;
+			}
+			bitres = 8;
+			break;
+
+		case SNDRV_PCM_FORMAT_S16_LE:
+			bitres = 16;
+			break;
+
+		case SNDRV_PCM_FORMAT_S32_LE:
+			/* 32 bit mode is coded as 0 */
+			bitres = 0;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value &= ~(mask << BF_SRC_CFGX_BIT_RES);
+		value |= (bitres << BF_SRC_CFGX_BIT_RES);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+
+	} else {
+
+		switch (params_format(params)) {
+		case SNDRV_PCM_FORMAT_S16_LE:
+			value = readl(aio->cygaud->audio +
+					aio->regs.bf_destch_cfg);
+			value |= BIT(BF_DST_CFGX_CAP_MODE);
+			writel(value, aio->cygaud->audio +
+					aio->regs.bf_destch_cfg);
+			break;
+
+		case SNDRV_PCM_FORMAT_S32_LE:
+			value = readl(aio->cygaud->audio +
+					aio->regs.bf_destch_cfg);
+			value &= ~BIT(BF_DST_CFGX_CAP_MODE);
+			writel(value, aio->cygaud->audio +
+					aio->regs.bf_destch_cfg);
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+
+	aio->lrclk = rate;
+
+	if (!aio->is_slave)
+		ret = cygnus_ssp_set_clocks(aio, cygaud);
+
+	return ret;
+}
+
+/*
+ * This function sets the mclk frequency for pll clock
+ */
+static int cygnus_ssp_set_sysclk(struct snd_soc_dai *dai,
+			int clk_id, unsigned int freq, int dir)
+{
+	int sel;
+	u32 value;
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
+	struct cygnus_audio *cygaud = snd_soc_dai_get_drvdata(dai);
+
+	dev_dbg(aio->cygaud->dev,
+		"%s Enter port = %d\n", __func__, aio->portnum);
+	sel = pll_configure_mclk(cygaud, freq, aio);
+	if (sel < 0) {
+		dev_err(aio->cygaud->dev,
+			"%s Setting mclk failed.\n", __func__);
+		return -EINVAL;
+	}
+
+	aio->mclk = freq;
+
+	dev_dbg(aio->cygaud->dev, "%s Setting MCLKSEL to %d\n", __func__, sel);
+	value = readl(aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
+	value &= ~(0xf << I2S_OUT_PLLCLKSEL_SHIFT);
+	value |= (sel << I2S_OUT_PLLCLKSEL_SHIFT);
+	writel(value, aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
+
+	return 0;
+}
+
+static int cygnus_ssp_startup(struct snd_pcm_substream *substream,
+			       struct snd_soc_dai *dai)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
+
+	snd_soc_dai_set_dma_data(dai, substream, aio);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		aio->clk_trace.play_en = true;
+	else
+		aio->clk_trace.cap_en = true;
+
+	return 0;
+}
+
+static void cygnus_ssp_shutdown(struct snd_pcm_substream *substream,
+			       struct snd_soc_dai *dai)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		aio->clk_trace.play_en = false;
+	else
+		aio->clk_trace.cap_en = false;
+
+	if (!aio->is_slave) {
+		u32 val;
+
+		val = readl(aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
+		val &= CYGNUS_PLLCLKSEL_MASK;
+		if (val >= ARRAY_SIZE(aio->cygaud->audio_clk)) {
+			dev_err(aio->cygaud->dev, "Clk index %u is out of bounds\n",
+				val);
+			return;
+		}
+
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			if (aio->clk_trace.play_clk_en) {
+				clk_disable_unprepare(aio->cygaud->
+						audio_clk[val]);
+				aio->clk_trace.play_clk_en = false;
+			}
+		} else {
+			if (aio->clk_trace.cap_clk_en) {
+				clk_disable_unprepare(aio->cygaud->
+						audio_clk[val]);
+				aio->clk_trace.cap_clk_en = false;
+			}
+		}
+	}
+}
+
+/*
+ * Bit    Update  Notes
+ * 31     Yes     TDM Mode        (1 = TDM, 0 = i2s)
+ * 30     Yes     Slave Mode	  (1 = Slave, 0 = Master)
+ * 29:26  No      Sclks per frame
+ * 25:18  Yes     FS Width
+ * 17:14  No      Valid Slots
+ * 13     No      Bits		  (1 = 16 bits, 0 = 32 bits)
+ * 12:08  No     Bits per samp
+ * 07     Yes     Justifcation    (1 = LSB, 0 = MSB)
+ * 06     Yes     Alignment       (1 = Delay 1 clk, 0 = no delay
+ * 05     Yes     SCLK polarity   (1 = Rising, 0 = Falling)
+ * 04     Yes     LRCLK Polarity  (1 = High for left, 0 = Low for left)
+ * 03:02  Yes     Reserved - write as zero
+ * 01     No      Data Enable
+ * 00     No      CLK Enable
+ */
+#define I2S_OUT_CFG_REG_UPDATE_MASK   0x3C03FF03
+
+/* Input cfg is same as output, but the FS width is not a valid field */
+#define I2S_IN_CFG_REG_UPDATE_MASK  (I2S_OUT_CFG_REG_UPDATE_MASK | 0x03FC0000)
+
+int cygnus_ssp_set_custom_fsync_width(struct snd_soc_dai *cpu_dai, int len)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
+
+	if ((len > 0) && (len < 256)) {
+		aio->fsync_width = len;
+		return 0;
+	} else {
+		return -EINVAL;
+	}
+}
+
+static int cygnus_ssp_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
+	u32 ssp_curcfg;
+	u32 ssp_newcfg;
+	u32 ssp_outcfg;
+	u32 ssp_incfg;
+	u32 val;
+	u32 mask;
+
+	dev_dbg(aio->cygaud->dev, "%s Enter  fmt: %x\n", __func__, fmt);
+
+	if (aio->port_type == PORT_SPDIF)
+		return -EINVAL;
+
+	ssp_newcfg = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		ssp_newcfg |= BIT(I2S_OUT_CFGX_SLAVE_MODE);
+		aio->is_slave = 1;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		ssp_newcfg &= ~BIT(I2S_OUT_CFGX_SLAVE_MODE);
+		aio->is_slave = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		ssp_newcfg |= BIT(I2S_OUT_CFGX_DATA_ALIGNMENT);
+		ssp_newcfg |= BIT(I2S_OUT_CFGX_FSYNC_WIDTH);
+		aio->mode = CYGNUS_SSPMODE_I2S;
+		break;
+
+	case SND_SOC_DAIFMT_DSP_A:
+	case SND_SOC_DAIFMT_DSP_B:
+		ssp_newcfg |= BIT(I2S_OUT_CFGX_TDM_MODE);
+
+		/* DSP_A = data after FS, DSP_B = data during FS */
+		if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A)
+			ssp_newcfg |= BIT(I2S_OUT_CFGX_DATA_ALIGNMENT);
+
+		if ((aio->fsync_width > 0) && (aio->fsync_width < 256))
+			ssp_newcfg |=
+				(aio->fsync_width << I2S_OUT_CFGX_FSYNC_WIDTH);
+		else
+			ssp_newcfg |= BIT(I2S_OUT_CFGX_FSYNC_WIDTH);
+
+		aio->mode = CYGNUS_SSPMODE_TDM;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * SSP out cfg.
+	 * Retain bits we do not want to update, then OR in new bits
+	 */
+	ssp_curcfg = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+	ssp_outcfg = (ssp_curcfg & I2S_OUT_CFG_REG_UPDATE_MASK) | ssp_newcfg;
+	writel(ssp_outcfg, aio->cygaud->audio + aio->regs.i2s_cfg);
+
+	/*
+	 * SSP in cfg.
+	 * Retain bits we do not want to update, then OR in new bits
+	 */
+	ssp_curcfg = readl(aio->cygaud->i2s_in + aio->regs.i2s_cap_cfg);
+	ssp_incfg = (ssp_curcfg & I2S_IN_CFG_REG_UPDATE_MASK) | ssp_newcfg;
+	writel(ssp_incfg, aio->cygaud->i2s_in + aio->regs.i2s_cap_cfg);
+
+	val = readl(aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+
+	/*
+	 * Configure the word clk and bit clk as output or tristate
+	 * Each port has 4 bits for controlling its pins.
+	 * Shift the mask based upon port number.
+	 */
+	mask = BIT(AUD_MISC_SEROUT_LRCK_OE)
+			| BIT(AUD_MISC_SEROUT_SCLK_OE)
+			| BIT(AUD_MISC_SEROUT_MCLK_OE);
+	mask = mask << (aio->portnum * 4);
+	if (aio->is_slave)
+		/* Set bit for tri-state */
+		val |= mask;
+	else
+		/* Clear bit for drive */
+		val &= ~mask;
+
+	dev_dbg(aio->cygaud->dev, "%s  Set OE bits 0x%x\n", __func__, val);
+	writel(val, aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+
+	return 0;
+}
+
+static int cygnus_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
+			       struct snd_soc_dai *dai)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
+	struct cygnus_audio *cygaud = snd_soc_dai_get_drvdata(dai);
+
+	dev_dbg(aio->cygaud->dev,
+		"%s cmd %d at port = %d\n", __func__, cmd, aio->portnum);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			audio_ssp_out_enable(aio);
+		else
+			audio_ssp_in_enable(aio);
+		cygaud->active_ports++;
+
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			audio_ssp_out_disable(aio);
+		else
+			audio_ssp_in_disable(aio);
+		cygaud->active_ports--;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int cygnus_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
+	unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
+	u32 value;
+	int bits_per_slot = 0;     /* default to 32-bits per slot */
+	int frame_bits;
+	unsigned int active_slots;
+	bool found = false;
+	int i;
+
+	if (tx_mask != rx_mask) {
+		dev_err(aio->cygaud->dev,
+			"%s tx_mask must equal rx_mask\n", __func__);
+		return -EINVAL;
+	}
+
+	active_slots = hweight32(tx_mask);
+
+	if ((active_slots < 0) || (active_slots > 16))
+		return -EINVAL;
+
+	/* Slot value must be even */
+	if (active_slots % 2)
+		return -EINVAL;
+
+	/* We encode 16 slots as 0 in the reg */
+	if (active_slots == 16)
+		active_slots = 0;
+
+	/* Slot Width is either 16 or 32 */
+	switch (slot_width) {
+	case 16:
+		bits_per_slot = 1;
+		break;
+	case 32:
+		bits_per_slot = 0;
+		break;
+	default:
+		bits_per_slot = 0;
+		dev_warn(aio->cygaud->dev,
+			"%s Defaulting Slot Width to 32\n", __func__);
+	}
+
+	frame_bits = slots * slot_width;
+
+	for (i = 0; i < ARRAY_SIZE(ssp_valid_tdm_framesize); i++) {
+		if (ssp_valid_tdm_framesize[i] == frame_bits) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		dev_err(aio->cygaud->dev,
+			"%s In TDM mode, frame bits INVALID (%d)\n",
+			__func__, frame_bits);
+		return -EINVAL;
+	}
+
+	aio->bit_per_frame = frame_bits;
+
+	dev_dbg(aio->cygaud->dev, "%s active_slots %u, bits per frame %d\n",
+			__func__, active_slots, frame_bits);
+
+	/* Set capture side of ssp port */
+	value = readl(aio->cygaud->i2s_in + aio->regs.i2s_cap_cfg);
+	value &= ~(0xf << I2S_OUT_CFGX_VALID_SLOT);
+	value |= (active_slots << I2S_OUT_CFGX_VALID_SLOT);
+	value &= ~BIT(I2S_OUT_CFGX_BITS_PER_SLOT);
+	value |= (bits_per_slot << I2S_OUT_CFGX_BITS_PER_SLOT);
+	writel(value, aio->cygaud->i2s_in + aio->regs.i2s_cap_cfg);
+
+	/* Set playback side of ssp port */
+	value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+	value &= ~(0xf << I2S_OUT_CFGX_VALID_SLOT);
+	value |= (active_slots << I2S_OUT_CFGX_VALID_SLOT);
+	value &= ~BIT(I2S_OUT_CFGX_BITS_PER_SLOT);
+	value |= (bits_per_slot << I2S_OUT_CFGX_BITS_PER_SLOT);
+	writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int cygnus_ssp_suspend(struct snd_soc_dai *cpu_dai)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
+
+	if (!aio->is_slave) {
+		u32 val;
+
+		val = readl(aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
+		val &= CYGNUS_PLLCLKSEL_MASK;
+		if (val >= ARRAY_SIZE(aio->cygaud->audio_clk)) {
+			dev_err(aio->cygaud->dev, "Clk index %u is out of bounds\n",
+				val);
+			return -EINVAL;
+		}
+
+		if (aio->clk_trace.cap_clk_en)
+			clk_disable_unprepare(aio->cygaud->audio_clk[val]);
+		if (aio->clk_trace.play_clk_en)
+			clk_disable_unprepare(aio->cygaud->audio_clk[val]);
+
+		aio->pll_clk_num = val;
+	}
+
+	return 0;
+}
+
+static int cygnus_ssp_resume(struct snd_soc_dai *cpu_dai)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
+	int error;
+
+	if (!aio->is_slave) {
+		if (aio->clk_trace.cap_clk_en) {
+			error = clk_prepare_enable(aio->cygaud->
+					audio_clk[aio->pll_clk_num]);
+			if (error) {
+				dev_err(aio->cygaud->dev, "%s clk_prepare_enable failed\n",
+					__func__);
+				return -EINVAL;
+			}
+		}
+		if (aio->clk_trace.play_clk_en) {
+			error = clk_prepare_enable(aio->cygaud->
+					audio_clk[aio->pll_clk_num]);
+			if (error) {
+				if (aio->clk_trace.cap_clk_en)
+					clk_disable_unprepare(aio->cygaud->
+						audio_clk[aio->pll_clk_num]);
+				dev_err(aio->cygaud->dev, "%s clk_prepare_enable failed\n",
+					__func__);
+				return -EINVAL;
+			}
+		}
+	}
+
+	return 0;
+}
+#else
+#define cygnus_ssp_suspend NULL
+#define cygnus_ssp_resume  NULL
+#endif
+
+static const struct snd_soc_dai_ops cygnus_ssp_dai_ops = {
+	.startup	= cygnus_ssp_startup,
+	.shutdown	= cygnus_ssp_shutdown,
+	.trigger	= cygnus_ssp_trigger,
+	.hw_params	= cygnus_ssp_hw_params,
+	.set_fmt	= cygnus_ssp_set_fmt,
+	.set_sysclk	= cygnus_ssp_set_sysclk,
+	.set_tdm_slot	= cygnus_set_dai_tdm_slot,
+};
+
+
+#define INIT_CPU_DAI(num) { \
+	.name = "cygnus-ssp" #num, \
+	.playback = { \
+		.channels_min = 1, \
+		.channels_max = 16, \
+		.rates = CYGNUS_TDM_RATE | SNDRV_PCM_RATE_88200 | \
+			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \
+			SNDRV_PCM_RATE_192000, \
+		.formats = SNDRV_PCM_FMTBIT_S8 | \
+				SNDRV_PCM_FMTBIT_S16_LE | \
+				SNDRV_PCM_FMTBIT_S32_LE, \
+	}, \
+	.capture = { \
+		.channels_min = 2, \
+		.channels_max = 16, \
+		.rates = CYGNUS_TDM_RATE | 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_S32_LE, \
+	}, \
+	.ops = &cygnus_ssp_dai_ops, \
+	.suspend = cygnus_ssp_suspend, \
+	.resume = cygnus_ssp_resume, \
+}
+
+static const struct snd_soc_dai_driver cygnus_ssp_dai_info[] = {
+	INIT_CPU_DAI(0),
+	INIT_CPU_DAI(1),
+	INIT_CPU_DAI(2),
+};
+
+static struct snd_soc_dai_driver cygnus_spdif_dai_info = {
+	.name = "cygnus-spdif",
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = CYGNUS_TDM_RATE | 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_S32_LE,
+	},
+	.ops = &cygnus_ssp_dai_ops,
+	.suspend = cygnus_ssp_suspend,
+	.resume = cygnus_ssp_resume,
+};
+
+static struct snd_soc_dai_driver cygnus_ssp_dai[CYGNUS_MAX_PORTS];
+
+static const struct snd_soc_component_driver cygnus_ssp_component = {
+	.name		= "cygnus-audio",
+};
+
+/*
+ * Return < 0 if error
+ * Return 0 if disabled
+ * Return 1 if enabled and node is parsed successfully
+ */
+static int parse_ssp_child_node(struct platform_device *pdev,
+				struct device_node *dn,
+				struct cygnus_audio *cygaud,
+				struct snd_soc_dai_driver *p_dai)
+{
+	struct cygnus_aio_port *aio;
+	struct cygnus_ssp_regs ssp_regs[3];
+	u32 rawval;
+	int portnum = -1;
+	enum cygnus_audio_port_type port_type;
+
+	if (of_property_read_u32(dn, "reg", &rawval)) {
+		dev_err(&pdev->dev, "Missing reg property\n");
+		return -EINVAL;
+	}
+
+	portnum = rawval;
+	switch (rawval) {
+	case 0:
+		ssp_regs[0] = INIT_SSP_REGS(0);
+		port_type = PORT_TDM;
+		break;
+	case 1:
+		ssp_regs[1] = INIT_SSP_REGS(1);
+		port_type = PORT_TDM;
+		break;
+	case 2:
+		ssp_regs[2] = INIT_SSP_REGS(2);
+		port_type = PORT_TDM;
+		break;
+	case 3:
+		port_type = PORT_SPDIF;
+		break;
+	default:
+		dev_err(&pdev->dev, "Bad value for reg %u\n", rawval);
+		return -EINVAL;
+	}
+
+	aio = &cygaud->portinfo[portnum];
+	aio->cygaud = cygaud;
+	aio->portnum = portnum;
+	aio->port_type = port_type;
+	aio->fsync_width = -1;
+
+	switch (port_type) {
+	case PORT_TDM:
+		aio->regs = ssp_regs[portnum];
+		*p_dai = cygnus_ssp_dai_info[portnum];
+		aio->mode = CYGNUS_SSPMODE_UNKNOWN;
+		break;
+
+	case PORT_SPDIF:
+		aio->regs.bf_sourcech_cfg = BF_SRC_CFG3_OFFSET;
+		aio->regs.bf_sourcech_ctrl = BF_SRC_CTRL3_OFFSET;
+		aio->regs.i2s_mclk_cfg = SPDIF_MCLK_CFG_OFFSET;
+		aio->regs.i2s_stream_cfg = SPDIF_STREAM_CFG_OFFSET;
+		*p_dai = cygnus_spdif_dai_info;
+
+		/* For the purposes of this code SPDIF can be I2S mode */
+		aio->mode = CYGNUS_SSPMODE_I2S;
+		break;
+	default:
+		dev_err(&pdev->dev, "Bad value for port_type %d\n", port_type);
+		return -EINVAL;
+	}
+
+	dev_dbg(&pdev->dev, "%s portnum = %d\n", __func__, aio->portnum);
+	aio->streams_on = 0;
+	aio->cygaud->dev = &pdev->dev;
+	aio->clk_trace.play_en = false;
+	aio->clk_trace.cap_en = false;
+
+	audio_ssp_init_portregs(aio);
+	return 0;
+}
+
+static int audio_clk_init(struct platform_device *pdev,
+						struct cygnus_audio *cygaud)
+{
+	int i;
+	char clk_name[PROP_LEN_MAX];
+
+	for (i = 0; i < ARRAY_SIZE(cygaud->audio_clk); i++) {
+		snprintf(clk_name, PROP_LEN_MAX, "ch%d_audio", i);
+
+		cygaud->audio_clk[i] = devm_clk_get(&pdev->dev, clk_name);
+		if (IS_ERR(cygaud->audio_clk[i]))
+			return PTR_ERR(cygaud->audio_clk[i]);
+	}
+
+	return 0;
+}
+
+static int cygnus_ssp_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *child_node;
+	struct resource *res = pdev->resource;
+	struct cygnus_audio *cygaud;
+	int err = -EINVAL;
+	int node_count;
+	int active_port_count;
+
+	cygaud = devm_kzalloc(dev, sizeof(struct cygnus_audio), GFP_KERNEL);
+	if (!cygaud)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, cygaud);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aud");
+	cygaud->audio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(cygaud->audio))
+		return PTR_ERR(cygaud->audio);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "i2s_in");
+	cygaud->i2s_in = devm_ioremap_resource(dev, res);
+	if (IS_ERR(cygaud->i2s_in))
+		return PTR_ERR(cygaud->i2s_in);
+
+	/* Tri-state all controlable pins until we know that we need them */
+	writel(CYGNUS_SSP_TRISTATE_MASK,
+			cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+
+	node_count = of_get_child_count(pdev->dev.of_node);
+	if ((node_count < 1) || (node_count > CYGNUS_MAX_PORTS)) {
+		dev_err(dev, "child nodes is %d.  Must be between 1 and %d\n",
+			node_count, CYGNUS_MAX_PORTS);
+		return -EINVAL;
+	}
+
+	active_port_count = 0;
+
+	for_each_available_child_of_node(pdev->dev.of_node, child_node) {
+		err = parse_ssp_child_node(pdev, child_node, cygaud,
+					&cygnus_ssp_dai[active_port_count]);
+
+		/* negative is err, 0 is active and good, 1 is disabled */
+		if (err < 0)
+			return err;
+		else if (!err) {
+			dev_dbg(dev, "Activating DAI: %s\n",
+				cygnus_ssp_dai[active_port_count].name);
+			active_port_count++;
+		}
+	}
+
+	cygaud->dev = dev;
+	cygaud->active_ports = 0;
+
+	dev_dbg(dev, "Registering %d DAIs\n", active_port_count);
+	err = snd_soc_register_component(dev, &cygnus_ssp_component,
+				cygnus_ssp_dai, active_port_count);
+	if (err) {
+		dev_err(dev, "snd_soc_register_dai failed\n");
+		return err;
+	}
+
+	cygaud->irq_num = platform_get_irq(pdev, 0);
+	if (cygaud->irq_num <= 0) {
+		dev_err(dev, "platform_get_irq failed\n");
+		err = cygaud->irq_num;
+		goto err_irq;
+	}
+
+	err = audio_clk_init(pdev, cygaud);
+	if (err) {
+		dev_err(dev, "audio clock initialization failed\n");
+		goto err_irq;
+	}
+
+	err = cygnus_soc_platform_register(dev, cygaud);
+	if (err) {
+		dev_err(dev, "platform reg error %d\n", err);
+		goto err_irq;
+	}
+
+	return 0;
+
+err_irq:
+	snd_soc_unregister_component(dev);
+	return err;
+}
+
+static int cygnus_ssp_remove(struct platform_device *pdev)
+{
+	cygnus_soc_platform_unregister(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id cygnus_ssp_of_match[] = {
+	{ .compatible = "brcm,cygnus-audio" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, cygnus_ssp_of_match);
+
+static struct platform_driver cygnus_ssp_driver = {
+	.probe		= cygnus_ssp_probe,
+	.remove		= cygnus_ssp_remove,
+	.driver		= {
+		.name	= "cygnus-ssp",
+		.of_match_table = cygnus_ssp_of_match,
+	},
+};
+
+module_platform_driver(cygnus_ssp_driver);
+
+MODULE_ALIAS("platform:cygnus-ssp");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Cygnus ASoC SSP Interface");
diff --git a/sound/soc/bcm/cygnus-ssp.h b/sound/soc/bcm/cygnus-ssp.h
new file mode 100644
index 0000000..33dd343
--- /dev/null
+++ b/sound/soc/bcm/cygnus-ssp.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2014-2015 Broadcom Corporation
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __CYGNUS_SSP_H__
+#define __CYGNUS_SSP_H__
+
+#define CYGNUS_TDM_DAI_MAX_SLOTS 16
+
+#define CYGNUS_MAX_PLAYBACK_PORTS 4
+#define CYGNUS_MAX_CAPTURE_PORTS 3
+#define CYGNUS_MAX_I2S_PORTS 3
+#define CYGNUS_MAX_PORTS  CYGNUS_MAX_PLAYBACK_PORTS
+#define CYGNUS_AUIDO_MAX_NUM_CLKS 3
+
+#define CYGNUS_SSP_FRAMEBITS_DIV 1
+
+#define CYGNUS_SSPMODE_I2S 0
+#define CYGNUS_SSPMODE_TDM 1
+#define CYGNUS_SSPMODE_UNKNOWN -1
+
+#define CYGNUS_SSP_CLKSRC_PLL      0
+
+/* Max string length of our dt property names */
+#define PROP_LEN_MAX 40
+
+struct ringbuf_regs {
+	unsigned rdaddr;
+	unsigned wraddr;
+	unsigned baseaddr;
+	unsigned endaddr;
+	unsigned fmark;   /* freemark for play, fullmark for caputure */
+	unsigned period_bytes;
+	unsigned buf_size;
+};
+
+#define RINGBUF_REG_PLAYBACK(num) ((struct ringbuf_regs) { \
+	.rdaddr = SRC_RBUF_ ##num## _RDADDR_OFFSET, \
+	.wraddr = SRC_RBUF_ ##num## _WRADDR_OFFSET, \
+	.baseaddr = SRC_RBUF_ ##num## _BASEADDR_OFFSET, \
+	.endaddr = SRC_RBUF_ ##num## _ENDADDR_OFFSET, \
+	.fmark = SRC_RBUF_ ##num## _FREE_MARK_OFFSET, \
+	.period_bytes = 0, \
+	.buf_size = 0, \
+})
+
+#define RINGBUF_REG_CAPTURE(num) ((struct ringbuf_regs)  { \
+	.rdaddr = DST_RBUF_ ##num## _RDADDR_OFFSET, \
+	.wraddr = DST_RBUF_ ##num## _WRADDR_OFFSET, \
+	.baseaddr = DST_RBUF_ ##num## _BASEADDR_OFFSET, \
+	.endaddr = DST_RBUF_ ##num## _ENDADDR_OFFSET, \
+	.fmark = DST_RBUF_ ##num## _FULL_MARK_OFFSET, \
+	.period_bytes = 0, \
+	.buf_size = 0, \
+})
+
+enum cygnus_audio_port_type {
+	PORT_TDM,
+	PORT_SPDIF,
+};
+
+struct cygnus_ssp_regs {
+	u32 i2s_stream_cfg;
+	u32 i2s_cfg;
+	u32 i2s_cap_stream_cfg;
+	u32 i2s_cap_cfg;
+	u32 i2s_mclk_cfg;
+
+	u32 bf_destch_ctrl;
+	u32 bf_destch_cfg;
+	u32 bf_sourcech_ctrl;
+	u32 bf_sourcech_cfg;
+	u32 bf_sourcech_grp;
+};
+
+struct cygnus_track_clk {
+	bool cap_en;
+	bool play_en;
+	bool cap_clk_en;
+	bool play_clk_en;
+};
+
+struct cygnus_aio_port {
+	int portnum;
+	int mode;
+	bool is_slave;
+	int streams_on;   /* will be 0 if both capture and play are off */
+	int fsync_width;
+	int port_type;
+
+	u32 mclk;
+	u32 lrclk;
+	u32 bit_per_frame;
+	u32 pll_clk_num;
+
+	struct cygnus_audio *cygaud;
+	struct cygnus_ssp_regs regs;
+
+	struct ringbuf_regs play_rb_regs;
+	struct ringbuf_regs capture_rb_regs;
+
+	struct snd_pcm_substream *play_stream;
+	struct snd_pcm_substream *capture_stream;
+
+	struct cygnus_track_clk clk_trace;
+};
+
+
+struct cygnus_audio {
+	struct cygnus_aio_port  portinfo[CYGNUS_MAX_PORTS];
+
+	int irq_num;
+	void __iomem *audio;
+	struct device *dev;
+	void __iomem *i2s_in;
+
+	struct clk *audio_clk[CYGNUS_AUIDO_MAX_NUM_CLKS];
+	int active_ports;
+	unsigned long vco_rate;
+};
+
+extern int cygnus_ssp_get_mode(struct snd_soc_dai *cpu_dai);
+extern int cygnus_ssp_add_pll_tweak_controls(struct snd_soc_pcm_runtime *rtd);
+extern int cygnus_ssp_set_custom_fsync_width(struct snd_soc_dai *cpu_dai,
+						int len);
+extern int cygnus_soc_platform_register(struct device *dev,
+					struct cygnus_audio *cygaud);
+extern int cygnus_soc_platform_unregister(struct device *dev);
+extern int cygnus_ssp_set_custom_fsync_width(struct snd_soc_dai *cpu_dai,
+	int len);
+#endif
-- 
1.9.1



From simran.rai at broadcom.com  Tue May 17 17:01:09 2016
From: simran.rai at broadcom.com (Simran Rai)
Date: Tue, 17 May 2016 17:01:09 -0700
Subject: [PATCH v7 3/3] ASoC: cygnus: Add Cygnus audio DMA driver
In-Reply-To: <1463529669-25022-1-git-send-email-simran.rai@broadcom.com>
References: <1463529669-25022-1-git-send-email-simran.rai@broadcom.com>
Message-ID: <1463529669-25022-4-git-send-email-simran.rai@broadcom.com>

From: Simran Rai <ssimran at broadcom.com>

This patch adds Cygnus audio DMA driver. It supports playback
and capture modes and uses ringbuffers for data transfer.

Signed-off-by: Lori Hikichi <lhikichi at broadcom.com>
Signed-off-by: Simran Rai <ssimran at broadcom.com>
Reviewed-by: Ray Jui <rjui at broadcom.com>
Reviewed-by: Arun Parameswaran <arunp at broadcom.com>
Reviewed-by: Scott Branden <sbranden at broadcom.com>
---
 sound/soc/bcm/Kconfig      |   9 +
 sound/soc/bcm/Makefile     |   5 +
 sound/soc/bcm/cygnus-pcm.c | 861 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 875 insertions(+)
 create mode 100644 sound/soc/bcm/cygnus-pcm.c

diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig
index 6a834e1..d528aac 100644
--- a/sound/soc/bcm/Kconfig
+++ b/sound/soc/bcm/Kconfig
@@ -7,3 +7,12 @@ config SND_BCM2835_SOC_I2S
 	  Say Y or M if you want to add support for codecs attached to
 	  the BCM2835 I2S interface. You will also need
 	  to select the audio interfaces to support below.
+
+config SND_SOC_CYGNUS
+	tristate "SoC platform audio for Broadcom Cygnus chips"
+	depends on ARCH_BCM_CYGNUS || COMPILE_TEST
+	help
+	  Say Y if you want to add support for ASoC audio on Broadcom
+	  Cygnus chips (bcm958300, bcm958305, bcm911360)
+
+	  If you don't know what to do here, say N.
\ No newline at end of file
diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile
index bc816b7..fc739d0 100644
--- a/sound/soc/bcm/Makefile
+++ b/sound/soc/bcm/Makefile
@@ -3,3 +3,8 @@ snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o
 
 obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o
 
+# CYGNUS Platform Support
+snd-soc-cygnus-objs := cygnus-pcm.o cygnus-ssp.o
+
+obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o
+
diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c
new file mode 100644
index 0000000..d616e096
--- /dev/null
+++ b/sound/soc/bcm/cygnus-pcm.c
@@ -0,0 +1,861 @@
+/*
+ * Copyright (C) 2014-2015 Broadcom Corporation
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/debugfs.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+
+#include "cygnus-ssp.h"
+
+/* Register offset needed for ASoC PCM module */
+
+#define INTH_R5F_STATUS_OFFSET     0x040
+#define INTH_R5F_CLEAR_OFFSET      0x048
+#define INTH_R5F_MASK_SET_OFFSET   0x050
+#define INTH_R5F_MASK_CLEAR_OFFSET 0x054
+
+#define BF_REARM_FREE_MARK_OFFSET 0x344
+#define BF_REARM_FULL_MARK_OFFSET 0x348
+
+/* Ring Buffer Ctrl Regs --- Start */
+/* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_RDADDR_REG_BASE */
+#define SRC_RBUF_0_RDADDR_OFFSET 0x500
+#define SRC_RBUF_1_RDADDR_OFFSET 0x518
+#define SRC_RBUF_2_RDADDR_OFFSET 0x530
+#define SRC_RBUF_3_RDADDR_OFFSET 0x548
+#define SRC_RBUF_4_RDADDR_OFFSET 0x560
+#define SRC_RBUF_5_RDADDR_OFFSET 0x578
+#define SRC_RBUF_6_RDADDR_OFFSET 0x590
+
+/* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_WRADDR_REG_BASE */
+#define SRC_RBUF_0_WRADDR_OFFSET 0x504
+#define SRC_RBUF_1_WRADDR_OFFSET 0x51c
+#define SRC_RBUF_2_WRADDR_OFFSET 0x534
+#define SRC_RBUF_3_WRADDR_OFFSET 0x54c
+#define SRC_RBUF_4_WRADDR_OFFSET 0x564
+#define SRC_RBUF_5_WRADDR_OFFSET 0x57c
+#define SRC_RBUF_6_WRADDR_OFFSET 0x594
+
+/* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_BASEADDR_REG_BASE */
+#define SRC_RBUF_0_BASEADDR_OFFSET 0x508
+#define SRC_RBUF_1_BASEADDR_OFFSET 0x520
+#define SRC_RBUF_2_BASEADDR_OFFSET 0x538
+#define SRC_RBUF_3_BASEADDR_OFFSET 0x550
+#define SRC_RBUF_4_BASEADDR_OFFSET 0x568
+#define SRC_RBUF_5_BASEADDR_OFFSET 0x580
+#define SRC_RBUF_6_BASEADDR_OFFSET 0x598
+
+/* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_ENDADDR_REG_BASE */
+#define SRC_RBUF_0_ENDADDR_OFFSET 0x50c
+#define SRC_RBUF_1_ENDADDR_OFFSET 0x524
+#define SRC_RBUF_2_ENDADDR_OFFSET 0x53c
+#define SRC_RBUF_3_ENDADDR_OFFSET 0x554
+#define SRC_RBUF_4_ENDADDR_OFFSET 0x56c
+#define SRC_RBUF_5_ENDADDR_OFFSET 0x584
+#define SRC_RBUF_6_ENDADDR_OFFSET 0x59c
+
+/* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_FREE_MARK_REG_BASE */
+#define SRC_RBUF_0_FREE_MARK_OFFSET 0x510
+#define SRC_RBUF_1_FREE_MARK_OFFSET 0x528
+#define SRC_RBUF_2_FREE_MARK_OFFSET 0x540
+#define SRC_RBUF_3_FREE_MARK_OFFSET 0x558
+#define SRC_RBUF_4_FREE_MARK_OFFSET 0x570
+#define SRC_RBUF_5_FREE_MARK_OFFSET 0x588
+#define SRC_RBUF_6_FREE_MARK_OFFSET 0x5a0
+
+/* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_RDADDR_REG_BASE */
+#define DST_RBUF_0_RDADDR_OFFSET 0x5c0
+#define DST_RBUF_1_RDADDR_OFFSET 0x5d8
+#define DST_RBUF_2_RDADDR_OFFSET 0x5f0
+#define DST_RBUF_3_RDADDR_OFFSET 0x608
+#define DST_RBUF_4_RDADDR_OFFSET 0x620
+#define DST_RBUF_5_RDADDR_OFFSET 0x638
+
+/* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_WRADDR_REG_BASE */
+#define DST_RBUF_0_WRADDR_OFFSET 0x5c4
+#define DST_RBUF_1_WRADDR_OFFSET 0x5dc
+#define DST_RBUF_2_WRADDR_OFFSET 0x5f4
+#define DST_RBUF_3_WRADDR_OFFSET 0x60c
+#define DST_RBUF_4_WRADDR_OFFSET 0x624
+#define DST_RBUF_5_WRADDR_OFFSET 0x63c
+
+/* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_BASEADDR_REG_BASE */
+#define DST_RBUF_0_BASEADDR_OFFSET 0x5c8
+#define DST_RBUF_1_BASEADDR_OFFSET 0x5e0
+#define DST_RBUF_2_BASEADDR_OFFSET 0x5f8
+#define DST_RBUF_3_BASEADDR_OFFSET 0x610
+#define DST_RBUF_4_BASEADDR_OFFSET 0x628
+#define DST_RBUF_5_BASEADDR_OFFSET 0x640
+
+/* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_ENDADDR_REG_BASE */
+#define DST_RBUF_0_ENDADDR_OFFSET 0x5cc
+#define DST_RBUF_1_ENDADDR_OFFSET 0x5e4
+#define DST_RBUF_2_ENDADDR_OFFSET 0x5fc
+#define DST_RBUF_3_ENDADDR_OFFSET 0x614
+#define DST_RBUF_4_ENDADDR_OFFSET 0x62c
+#define DST_RBUF_5_ENDADDR_OFFSET 0x644
+
+/* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_FULL_MARK_REG_BASE */
+#define DST_RBUF_0_FULL_MARK_OFFSET 0x5d0
+#define DST_RBUF_1_FULL_MARK_OFFSET 0x5e8
+#define DST_RBUF_2_FULL_MARK_OFFSET 0x600
+#define DST_RBUF_3_FULL_MARK_OFFSET 0x618
+#define DST_RBUF_4_FULL_MARK_OFFSET 0x630
+#define DST_RBUF_5_FULL_MARK_OFFSET 0x648
+/* Ring Buffer Ctrl Regs --- End */
+
+/* Error Status Regs --- Start */
+/* AUD_FMM_BF_ESR_ESRX_STATUS_REG_BASE */
+#define ESR0_STATUS_OFFSET 0x900
+#define ESR1_STATUS_OFFSET 0x918
+#define ESR2_STATUS_OFFSET 0x930
+#define ESR3_STATUS_OFFSET 0x948
+#define ESR4_STATUS_OFFSET 0x960
+
+/* AUD_FMM_BF_ESR_ESRX_STATUS_CLEAR_REG_BASE */
+#define ESR0_STATUS_CLR_OFFSET 0x908
+#define ESR1_STATUS_CLR_OFFSET 0x920
+#define ESR2_STATUS_CLR_OFFSET 0x938
+#define ESR3_STATUS_CLR_OFFSET 0x950
+#define ESR4_STATUS_CLR_OFFSET 0x968
+
+/* AUD_FMM_BF_ESR_ESRX_MASK_REG_BASE */
+#define ESR0_MASK_STATUS_OFFSET 0x90c
+#define ESR1_MASK_STATUS_OFFSET 0x924
+#define ESR2_MASK_STATUS_OFFSET 0x93c
+#define ESR3_MASK_STATUS_OFFSET 0x954
+#define ESR4_MASK_STATUS_OFFSET 0x96c
+
+/* AUD_FMM_BF_ESR_ESRX_MASK_SET_REG_BASE */
+#define ESR0_MASK_SET_OFFSET 0x910
+#define ESR1_MASK_SET_OFFSET 0x928
+#define ESR2_MASK_SET_OFFSET 0x940
+#define ESR3_MASK_SET_OFFSET 0x958
+#define ESR4_MASK_SET_OFFSET 0x970
+
+/* AUD_FMM_BF_ESR_ESRX_MASK_CLEAR_REG_BASE */
+#define ESR0_MASK_CLR_OFFSET 0x914
+#define ESR1_MASK_CLR_OFFSET 0x92c
+#define ESR2_MASK_CLR_OFFSET 0x944
+#define ESR3_MASK_CLR_OFFSET 0x95c
+#define ESR4_MASK_CLR_OFFSET 0x974
+/* Error Status Regs --- End */
+
+#define R5F_ESR0_SHIFT  0    /* esr0 = fifo underflow */
+#define R5F_ESR1_SHIFT  1    /* esr1 = ringbuf underflow */
+#define R5F_ESR2_SHIFT  2    /* esr2 = ringbuf overflow */
+#define R5F_ESR3_SHIFT  3    /* esr3 = freemark */
+#define R5F_ESR4_SHIFT  4    /* esr4 = fullmark */
+
+
+/* Mask for R5F register.  Set all relevant interrupt for playback handler */
+#define ANY_PLAYBACK_IRQ  (BIT(R5F_ESR0_SHIFT) | \
+			   BIT(R5F_ESR1_SHIFT) | \
+			   BIT(R5F_ESR3_SHIFT))
+
+/* Mask for R5F register.  Set all relevant interrupt for capture handler */
+#define ANY_CAPTURE_IRQ   (BIT(R5F_ESR2_SHIFT) | BIT(R5F_ESR4_SHIFT))
+
+/*
+ * PERIOD_BYTES_MIN is the number of bytes to at which the interrupt will tick.
+ * This number should be a multiple of 256. Minimum value is 256
+ */
+#define PERIOD_BYTES_MIN 0x100
+
+static const struct snd_pcm_hardware cygnus_pcm_hw = {
+	.info = SNDRV_PCM_INFO_MMAP |
+			SNDRV_PCM_INFO_MMAP_VALID |
+			SNDRV_PCM_INFO_INTERLEAVED,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE |
+			SNDRV_PCM_FMTBIT_S32_LE,
+
+	/* A period is basically an interrupt */
+	.period_bytes_min = PERIOD_BYTES_MIN,
+	.period_bytes_max = 0x10000,
+
+	/* period_min/max gives range of approx interrupts per buffer */
+	.periods_min = 2,
+	.periods_max = 8,
+
+	/*
+	 * maximum buffer size in bytes = period_bytes_max * periods_max
+	 * We allocate this amount of data for each enabled channel
+	 */
+	.buffer_bytes_max = 4 * 0x8000,
+};
+
+static u64 cygnus_dma_dmamask = DMA_BIT_MASK(32);
+
+static struct cygnus_aio_port *cygnus_dai_get_dma_data(
+				struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+
+	return snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
+}
+
+static void ringbuf_set_initial(void __iomem *audio_io,
+		struct ringbuf_regs *p_rbuf,
+		bool is_playback,
+		u32 start,
+		u32 periodsize,
+		u32 bufsize)
+{
+	u32 initial_rd;
+	u32 initial_wr;
+	u32 end;
+	u32 fmark_val; /* free or full mark */
+
+	p_rbuf->period_bytes = periodsize;
+	p_rbuf->buf_size = bufsize;
+
+	if (is_playback) {
+		/* Set the pointers to indicate full (flip uppermost bit) */
+		initial_rd = start;
+		initial_wr = initial_rd ^ BIT(31);
+	} else {
+		/* Set the pointers to indicate empty */
+		initial_wr = start;
+		initial_rd = initial_wr;
+	}
+
+	end = start + bufsize - 1;
+
+	/*
+	 * The interrupt will fire when free/full mark is *exceeded*
+	 * The fmark value must be multiple of PERIOD_BYTES_MIN so set fmark
+	 * to be PERIOD_BYTES_MIN less than the period size.
+	 */
+	fmark_val = periodsize - PERIOD_BYTES_MIN;
+
+	writel(start, audio_io + p_rbuf->baseaddr);
+	writel(end, audio_io + p_rbuf->endaddr);
+	writel(fmark_val, audio_io + p_rbuf->fmark);
+	writel(initial_rd, audio_io + p_rbuf->rdaddr);
+	writel(initial_wr, audio_io + p_rbuf->wraddr);
+}
+
+static int configure_ringbuf_regs(struct snd_pcm_substream *substream)
+{
+	struct cygnus_aio_port *aio;
+	struct ringbuf_regs *p_rbuf;
+	int status = 0;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	/* Map the ssp portnum to a set of ring buffers. */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		p_rbuf = &aio->play_rb_regs;
+
+		switch (aio->portnum) {
+		case 0:
+			*p_rbuf = RINGBUF_REG_PLAYBACK(0);
+			break;
+		case 1:
+			*p_rbuf = RINGBUF_REG_PLAYBACK(2);
+			break;
+		case 2:
+			*p_rbuf = RINGBUF_REG_PLAYBACK(4);
+			break;
+		case 3: /* SPDIF */
+			*p_rbuf = RINGBUF_REG_PLAYBACK(6);
+			break;
+		default:
+			status = -EINVAL;
+		}
+	} else {
+		p_rbuf = &aio->capture_rb_regs;
+
+		switch (aio->portnum) {
+		case 0:
+			*p_rbuf = RINGBUF_REG_CAPTURE(0);
+			break;
+		case 1:
+			*p_rbuf = RINGBUF_REG_CAPTURE(2);
+			break;
+		case 2:
+			*p_rbuf = RINGBUF_REG_CAPTURE(4);
+			break;
+		default:
+			status = -EINVAL;
+		}
+	}
+
+	return status;
+}
+
+static struct ringbuf_regs *get_ringbuf(struct snd_pcm_substream *substream)
+{
+	struct cygnus_aio_port *aio;
+	struct ringbuf_regs *p_rbuf = NULL;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		p_rbuf = &aio->play_rb_regs;
+	else
+		p_rbuf = &aio->capture_rb_regs;
+
+	return p_rbuf;
+}
+
+static void enable_intr(struct snd_pcm_substream *substream)
+{
+	struct cygnus_aio_port *aio;
+	u32 clear_mask;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	/* The port number maps to the bit position to be cleared */
+	clear_mask = BIT(aio->portnum);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* Clear interrupt status before enabling them */
+		writel(clear_mask, aio->cygaud->audio + ESR0_STATUS_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR1_STATUS_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR3_STATUS_CLR_OFFSET);
+		/* Unmask the interrupts of the given port*/
+		writel(clear_mask, aio->cygaud->audio + ESR0_MASK_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR1_MASK_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR3_MASK_CLR_OFFSET);
+
+		writel(ANY_PLAYBACK_IRQ,
+			aio->cygaud->audio + INTH_R5F_MASK_CLEAR_OFFSET);
+	} else {
+		writel(clear_mask, aio->cygaud->audio + ESR2_STATUS_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR4_STATUS_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR2_MASK_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR4_MASK_CLR_OFFSET);
+
+		writel(ANY_CAPTURE_IRQ,
+			aio->cygaud->audio + INTH_R5F_MASK_CLEAR_OFFSET);
+	}
+
+}
+
+static void disable_intr(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct cygnus_aio_port *aio;
+	u32 set_mask;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	dev_dbg(rtd->cpu_dai->dev, "%s on port %d\n", __func__, aio->portnum);
+
+	/* The port number maps to the bit position to be set */
+	set_mask = BIT(aio->portnum);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* Mask the interrupts of the given port*/
+		writel(set_mask, aio->cygaud->audio + ESR0_MASK_SET_OFFSET);
+		writel(set_mask, aio->cygaud->audio + ESR1_MASK_SET_OFFSET);
+		writel(set_mask, aio->cygaud->audio + ESR3_MASK_SET_OFFSET);
+	} else {
+		writel(set_mask, aio->cygaud->audio + ESR2_MASK_SET_OFFSET);
+		writel(set_mask, aio->cygaud->audio + ESR4_MASK_SET_OFFSET);
+	}
+
+}
+
+static int cygnus_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		enable_intr(substream);
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		disable_intr(substream);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void cygnus_pcm_period_elapsed(struct snd_pcm_substream *substream)
+{
+	struct cygnus_aio_port *aio;
+	struct ringbuf_regs *p_rbuf = NULL;
+	u32 regval;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	p_rbuf = get_ringbuf(substream);
+
+	/*
+	 * If free/full mark interrupt occurs, provide timestamp
+	 * to ALSA and update appropriate idx by period_bytes
+	 */
+	snd_pcm_period_elapsed(substream);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* Set the ring buffer to full */
+		regval = readl(aio->cygaud->audio + p_rbuf->rdaddr);
+		regval = regval ^ BIT(31);
+		writel(regval, aio->cygaud->audio + p_rbuf->wraddr);
+	} else {
+		/* Set the ring buffer to empty */
+		regval = readl(aio->cygaud->audio + p_rbuf->wraddr);
+		writel(regval, aio->cygaud->audio + p_rbuf->rdaddr);
+	}
+}
+
+/*
+ * ESR0/1/3 status  Description
+ *  0x1	I2S0_out port caused interrupt
+ *  0x2	I2S1_out port caused interrupt
+ *  0x4	I2S2_out port caused interrupt
+ *  0x8	SPDIF_out port caused interrupt
+ */
+static void handle_playback_irq(struct cygnus_audio *cygaud)
+{
+	void __iomem *audio_io;
+	u32 port;
+	u32 esr_status0, esr_status1, esr_status3;
+
+	audio_io = cygaud->audio;
+
+	/*
+	 * ESR status gets updates with/without interrupts enabled.
+	 * So, check the ESR mask, which provides interrupt enable/
+	 * disable status and use it to determine which ESR status
+	 * should be serviced.
+	 */
+	esr_status0 = readl(audio_io + ESR0_STATUS_OFFSET);
+	esr_status0 &= ~readl(audio_io + ESR0_MASK_STATUS_OFFSET);
+	esr_status1 = readl(audio_io + ESR1_STATUS_OFFSET);
+	esr_status1 &= ~readl(audio_io + ESR1_MASK_STATUS_OFFSET);
+	esr_status3 = readl(audio_io + ESR3_STATUS_OFFSET);
+	esr_status3 &= ~readl(audio_io + ESR3_MASK_STATUS_OFFSET);
+
+	for (port = 0; port < CYGNUS_MAX_PLAYBACK_PORTS; port++) {
+		u32 esrmask = BIT(port);
+
+		/*
+		 * Ringbuffer or FIFO underflow
+		 * If we get this interrupt then, it is also true that we have
+		 * not yet responded to the freemark interrupt.
+		 * Log a debug message.  The freemark handler below will
+		 * handle getting everything going again.
+		 */
+		if ((esrmask & esr_status1) || (esrmask & esr_status0)) {
+			dev_dbg(cygaud->dev,
+				"Underrun: esr0=0x%x, esr1=0x%x esr3=0x%x\n",
+				esr_status0, esr_status1, esr_status3);
+		}
+
+		/*
+		 * Freemark is hit. This is the normal interrupt.
+		 * In typical operation the read and write regs will be equal
+		 */
+		if (esrmask & esr_status3) {
+			struct snd_pcm_substream *playstr;
+
+			playstr = cygaud->portinfo[port].play_stream;
+			cygnus_pcm_period_elapsed(playstr);
+		}
+	}
+
+	/* Clear ESR interrupt */
+	writel(esr_status0, audio_io + ESR0_STATUS_CLR_OFFSET);
+	writel(esr_status1, audio_io + ESR1_STATUS_CLR_OFFSET);
+	writel(esr_status3, audio_io + ESR3_STATUS_CLR_OFFSET);
+	/* Rearm freemark logic by writing 1 to the correct bit */
+	writel(esr_status3, audio_io + BF_REARM_FREE_MARK_OFFSET);
+}
+
+/*
+ * ESR2/4 status  Description
+ *  0x1	I2S0_in port caused interrupt
+ *  0x2	I2S1_in port caused interrupt
+ *  0x4	I2S2_in port caused interrupt
+ */
+static void handle_capture_irq(struct cygnus_audio *cygaud)
+{
+	void __iomem *audio_io;
+	u32 port;
+	u32 esr_status2, esr_status4;
+
+	audio_io = cygaud->audio;
+
+	/*
+	 * ESR status gets updates with/without interrupts enabled.
+	 * So, check the ESR mask, which provides interrupt enable/
+	 * disable status and use it to determine which ESR status
+	 * should be serviced.
+	 */
+	esr_status2 = readl(audio_io + ESR2_STATUS_OFFSET);
+	esr_status2 &= ~readl(audio_io + ESR2_MASK_STATUS_OFFSET);
+	esr_status4 = readl(audio_io + ESR4_STATUS_OFFSET);
+	esr_status4 &= ~readl(audio_io + ESR4_MASK_STATUS_OFFSET);
+
+	for (port = 0; port < CYGNUS_MAX_CAPTURE_PORTS; port++) {
+		u32 esrmask = BIT(port);
+
+		/*
+		 * Ringbuffer or FIFO overflow
+		 * If we get this interrupt then, it is also true that we have
+		 * not yet responded to the fullmark interrupt.
+		 * Log a debug message.  The fullmark handler below will
+		 * handle getting everything going again.
+		 */
+		if (esrmask & esr_status2)
+			dev_dbg(cygaud->dev,
+				"Overflow: esr2=0x%x\n", esr_status2);
+
+		if (esrmask & esr_status4) {
+			struct snd_pcm_substream *capstr;
+
+			capstr = cygaud->portinfo[port].capture_stream;
+			cygnus_pcm_period_elapsed(capstr);
+		}
+	}
+
+	writel(esr_status2, audio_io + ESR2_STATUS_CLR_OFFSET);
+	writel(esr_status4, audio_io + ESR4_STATUS_CLR_OFFSET);
+	/* Rearm fullmark logic by writing 1 to the correct bit */
+	writel(esr_status4, audio_io + BF_REARM_FULL_MARK_OFFSET);
+}
+
+static irqreturn_t cygnus_dma_irq(int irq, void *data)
+{
+	u32 r5_status;
+	struct cygnus_audio *cygaud = data;
+
+	/*
+	 * R5 status bits	Description
+	 *  0		ESR0 (playback FIFO interrupt)
+	 *  1		ESR1 (playback rbuf interrupt)
+	 *  2		ESR2 (capture rbuf interrupt)
+	 *  3		ESR3 (Freemark play. interrupt)
+	 *  4		ESR4 (Fullmark capt. interrupt)
+	 */
+	r5_status = readl(cygaud->audio + INTH_R5F_STATUS_OFFSET);
+
+	if (!(r5_status & (ANY_PLAYBACK_IRQ | ANY_CAPTURE_IRQ)))
+		return IRQ_NONE;
+
+	/* If playback interrupt happened */
+	if (ANY_PLAYBACK_IRQ & r5_status) {
+		handle_playback_irq(cygaud);
+		writel(ANY_PLAYBACK_IRQ & r5_status,
+			cygaud->audio + INTH_R5F_CLEAR_OFFSET);
+	}
+
+	/* If  capture interrupt happened */
+	if (ANY_CAPTURE_IRQ & r5_status) {
+		handle_capture_irq(cygaud);
+		writel(ANY_CAPTURE_IRQ & r5_status,
+			cygaud->audio + INTH_R5F_CLEAR_OFFSET);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int cygnus_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct cygnus_aio_port *aio;
+	int ret;
+
+	aio = cygnus_dai_get_dma_data(substream);
+	if (!aio)
+		return -ENODEV;
+
+	dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum);
+
+	snd_soc_set_runtime_hwparams(substream, &cygnus_pcm_hw);
+
+	ret = snd_pcm_hw_constraint_step(runtime, 0,
+		SNDRV_PCM_HW_PARAM_PERIOD_BYTES, PERIOD_BYTES_MIN);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_pcm_hw_constraint_step(runtime, 0,
+		SNDRV_PCM_HW_PARAM_BUFFER_BYTES, PERIOD_BYTES_MIN);
+	if (ret < 0)
+		return ret;
+	/*
+	 * Keep track of which substream belongs to which port.
+	 * This info is needed by snd_pcm_period_elapsed() in irq_handler
+	 */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		aio->play_stream = substream;
+	else
+		aio->capture_stream = substream;
+
+	return 0;
+}
+
+static int cygnus_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct cygnus_aio_port *aio;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	dev_dbg(rtd->cpu_dai->dev, "%s  port %d\n", __func__, aio->portnum);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		aio->play_stream = NULL;
+	else
+		aio->capture_stream = NULL;
+
+	if (!aio->play_stream && !aio->capture_stream)
+		dev_dbg(rtd->cpu_dai->dev, "freed  port %d\n", aio->portnum);
+
+	return 0;
+}
+
+static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct cygnus_aio_port *aio;
+	int ret = 0;
+
+	aio = cygnus_dai_get_dma_data(substream);
+	dev_dbg(rtd->cpu_dai->dev, "%s  port %d\n", __func__, aio->portnum);
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+	runtime->dma_bytes = params_buffer_bytes(params);
+
+	return ret;
+}
+
+static int cygnus_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct cygnus_aio_port *aio;
+
+	aio = cygnus_dai_get_dma_data(substream);
+	dev_dbg(rtd->cpu_dai->dev, "%s  port %d\n", __func__, aio->portnum);
+
+	snd_pcm_set_runtime_buffer(substream, NULL);
+	return 0;
+}
+
+static int cygnus_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct cygnus_aio_port *aio;
+	unsigned long bufsize, periodsize;
+	int ret = 0;
+	bool is_play;
+	u32 start;
+	struct ringbuf_regs *p_rbuf = NULL;
+
+	aio = cygnus_dai_get_dma_data(substream);
+	dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum);
+
+	bufsize = snd_pcm_lib_buffer_bytes(substream);
+	periodsize = snd_pcm_lib_period_bytes(substream);
+
+	dev_dbg(rtd->cpu_dai->dev, "%s (buf_size %lu) (period_size %lu)\n",
+			__func__, bufsize, periodsize);
+
+	configure_ringbuf_regs(substream);
+
+	p_rbuf = get_ringbuf(substream);
+
+	start = runtime->dma_addr;
+
+	is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 1 : 0;
+
+	ringbuf_set_initial(aio->cygaud->audio, p_rbuf, is_play, start,
+				periodsize, bufsize);
+
+	return ret;
+}
+
+static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct cygnus_aio_port *aio;
+	unsigned int res = 0, cur = 0, base = 0;
+	struct ringbuf_regs *p_rbuf = NULL;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	/*
+	 * Get the offset of the current read (for playack) or write
+	 * index (for capture).  Report this value back to the asoc framework.
+	 */
+	p_rbuf = get_ringbuf(substream);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		cur = readl(aio->cygaud->audio + p_rbuf->rdaddr);
+	else
+		cur = readl(aio->cygaud->audio + p_rbuf->wraddr);
+
+	base = readl(aio->cygaud->audio + p_rbuf->baseaddr);
+
+	/*
+	 * Mask off the MSB of the rdaddr,wraddr and baseaddr
+	 * since MSB is not part of the address
+	 */
+	res = (cur & 0x7fffffff) - (base & 0x7fffffff);
+
+	return bytes_to_frames(substream->runtime, res);
+}
+
+static int cygnus_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	size_t size;
+
+	size = cygnus_pcm_hw.buffer_bytes_max;
+
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+	buf->area = dma_alloc_coherent(pcm->card->dev, size,
+			&buf->addr, GFP_KERNEL);
+
+	dev_dbg(rtd->cpu_dai->dev, "%s: size 0x%zx @ %pK\n",
+				__func__, size, buf->area);
+
+	if (!buf->area) {
+		dev_err(rtd->cpu_dai->dev, "%s: dma_alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	buf->bytes = size;
+
+	return 0;
+}
+
+
+static const struct snd_pcm_ops cygnus_pcm_ops = {
+	.open		= cygnus_pcm_open,
+	.close		= cygnus_pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= cygnus_pcm_hw_params,
+	.hw_free	= cygnus_pcm_hw_free,
+	.prepare	= cygnus_pcm_prepare,
+	.trigger	= cygnus_pcm_trigger,
+	.pointer	= cygnus_pcm_pointer,
+};
+
+static void cygnus_dma_free_dma_buffers(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_dma_buffer *buf;
+
+	substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	if (substream) {
+		buf = &substream->dma_buffer;
+		if (buf->area) {
+			dma_free_coherent(pcm->card->dev, buf->bytes,
+				buf->area, buf->addr);
+			buf->area = NULL;
+		}
+	}
+
+	substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+	if (substream) {
+		buf = &substream->dma_buffer;
+		if (buf->area) {
+			dma_free_coherent(pcm->card->dev, buf->bytes,
+				buf->area, buf->addr);
+			buf->area = NULL;
+		}
+	}
+}
+
+static int cygnus_dma_new(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_pcm *pcm = rtd->pcm;
+	int ret;
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &cygnus_dma_dmamask;
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+		ret = cygnus_pcm_preallocate_dma_buffer(pcm,
+				SNDRV_PCM_STREAM_PLAYBACK);
+		if (ret)
+			return ret;
+	}
+
+	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+		ret = cygnus_pcm_preallocate_dma_buffer(pcm,
+				SNDRV_PCM_STREAM_CAPTURE);
+		if (ret) {
+			cygnus_dma_free_dma_buffers(pcm);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static struct snd_soc_platform_driver cygnus_soc_platform = {
+	.ops		= &cygnus_pcm_ops,
+	.pcm_new	= cygnus_dma_new,
+	.pcm_free	= cygnus_dma_free_dma_buffers,
+};
+
+int cygnus_soc_platform_register(struct device *dev,
+				 struct cygnus_audio *cygaud)
+{
+	int rc = 0;
+
+	dev_dbg(dev, "%s Enter\n", __func__);
+
+	rc = devm_request_irq(dev, cygaud->irq_num, cygnus_dma_irq,
+				IRQF_SHARED, "cygnus-audio", cygaud);
+	if (rc) {
+		dev_err(dev, "%s request_irq error %d\n", __func__, rc);
+		return rc;
+	}
+
+	rc = snd_soc_register_platform(dev, &cygnus_soc_platform);
+	if (rc) {
+		dev_err(dev, "%s failed\n", __func__);
+		return rc;
+	}
+
+	return 0;
+}
+
+int cygnus_soc_platform_unregister(struct device *dev)
+{
+	snd_soc_unregister_platform(dev);
+
+	return 0;
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Cygnus ASoC PCM module");
-- 
1.9.1



From shankerd at codeaurora.org  Tue May 17 17:40:30 2016
From: shankerd at codeaurora.org (Shanker Donthineni)
Date: Tue, 17 May 2016 19:40:30 -0500
Subject: [PATCH v2 2/5] arm64: efi: apply strict permissons for UEFI
 Runtime Services regions
In-Reply-To: <1459355933-13529-3-git-send-email-ard.biesheuvel@linaro.org>
References: <1459355933-13529-1-git-send-email-ard.biesheuvel@linaro.org>
 <1459355933-13529-3-git-send-email-ard.biesheuvel@linaro.org>
Message-ID: <573BB9FE.7050008@codeaurora.org>

Hi Ard,

This patch causing the kernel boot fail using the UEFI firmware on
Qualcomm Technologies QDF2XXX server platforms.

+	/* RW- */
+	if (attr & EFI_MEMORY_XP || type != EFI_RUNTIME_SERVICES_CODE)
+		return pgprot_val(PAGE_KERNEL);
+

Changing above condition from 'or' to 'and' fixed the problem.Are we
missing something here or intentionally implemented this logic? At least
we need some pr_warn here if UEFI firmware passes EFI_RUNTIME_SEVRICE_CODE
region that has an attribute EFI_MEMORY_XP.



On 03/30/2016 11:38 AM, Ard Biesheuvel wrote:
> Recent UEFI versions expose permission attributes for runtime services
> memory regions, either in the UEFI memory map or in the separate memory
> attributes table. This allows the kernel to map these regions with
> stricter permissions, rather than the RWX permissions that are used by
> default. So wire this up in our mapping routine.
>
> Note that in the absence of permission attributes, we still only map
> regions of type EFI_RUNTIME_SERVICE_CODE with the executable bit set.
> Also, we base the mapping attributes of EFI_MEMORY_MAPPED_IO on the
> type directly rather than on the absence of the EFI_MEMORY_WB attribute.
> This is more correct, but is also required for compatibility with the
> upcoming support for the Memory Attributes Table, which only carries
> permission attributes, not memory type attributes.
>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> ---
>  arch/arm64/kernel/efi.c | 54 +++++++++++++++-----
>  1 file changed, 40 insertions(+), 14 deletions(-)
>
> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
> index b6abc852f2a1..33a6da160a50 100644
> --- a/arch/arm64/kernel/efi.c
> +++ b/arch/arm64/kernel/efi.c
> @@ -17,22 +17,48 @@
>  
>  #include <asm/efi.h>
>  
> -int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t
> *md)
> +/*
> + * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
> + * executable, everything else can be mapped with the XN bits
> + * set. Also take the new (optional) RO/XP bits into account.
> + */
> +static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
>  {
> -	pteval_t prot_val;
> +	u64 attr = md->attribute;
> +	u32 type = md->type;
>  
> -	/*
> -	 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
> -	 * executable, everything else can be mapped with the XN bits
> -	 * set.
> -	 */
> -	if ((md->attribute & EFI_MEMORY_WB) == 0)
> -		prot_val = PROT_DEVICE_nGnRE;
> -	else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
> -		 !PAGE_ALIGNED(md->phys_addr))
> -		prot_val = pgprot_val(PAGE_KERNEL_EXEC);
> -	else
> -		prot_val = pgprot_val(PAGE_KERNEL);
> +	if (type == EFI_MEMORY_MAPPED_IO)
> +		return PROT_DEVICE_nGnRE;
> +
> +	if (WARN_ONCE(!PAGE_ALIGNED(md->phys_addr),
> +		      "UEFI Runtime regions are not aligned to 64 KB --
> buggy firmware?"))
> +		/*
> +		 * If the region is not aligned to the page size of the
> OS, we
> +		 * can not use strict permissions, since that would also
> affect
> +		 * the mapping attributes of the adjacent regions.
> +		 */
> +		return pgprot_val(PAGE_KERNEL_EXEC);
> +
> +	/* R-- */
> +	if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) ==
> +	    (EFI_MEMORY_XP | EFI_MEMORY_RO))
> +		return pgprot_val(PAGE_KERNEL_RO);
> +
> +	/* R-X */
> +	if (attr & EFI_MEMORY_RO)
> +		return pgprot_val(PAGE_KERNEL_ROX);
> +
> +	/* RW- */
> +	if (attr & EFI_MEMORY_XP || type != EFI_RUNTIME_SERVICES_CODE)
> +		return pgprot_val(PAGE_KERNEL);
> +
> +	/* RWX */
> +	return pgprot_val(PAGE_KERNEL_EXEC);
> +}
> +
> +int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t
> *md)
> +{
> +	pteval_t prot_val = create_mapping_protection(md);
>  
>  	create_pgd_mapping(mm, md->phys_addr, md->virt_addr,
>  			   md->num_pages << EFI_PAGE_SHIFT,

-- 
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project



From sfr at canb.auug.org.au  Tue May 17 17:43:20 2016
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Wed, 18 May 2016 10:43:20 +1000
Subject: QRTR merge conflict resolution
In-Reply-To: <20160517.141154.1511755950068252376.davem@davemloft.net>
References: <20160510183934.GJ1256@tuxbot> <2606282.lG9qK7uBW0@wuerfel>
 <20160513221909.GC1256@tuxbot>
 <20160517.141154.1511755950068252376.davem@davemloft.net>
Message-ID: <20160518104320.23ae8557@canb.auug.org.au>

Hi David,

On Tue, 17 May 2016 14:11:54 -0400 (EDT) David Miller <davem at davemloft.net> wrote:
>
> From: Bjorn Andersson <bjorn.andersson at linaro.org>
> Date: Fri, 13 May 2016 15:19:09 -0700
> 
> > I have prepared the merge of net-next and the conflicting tag from the
> > Qualcomm SOC, please include this in your pull towards Linus to avoid
> > the merge conflict.  
> 
> Pulled, thanks.

Except in the merge resolution, the 2 new functions added to
include/linux/soc/qcom/smd.h (qcom_smd_get_drvdata and
qcom_smd_set_drvdata) were not marked "static inline" :-(

-- 
Cheers,
Stephen Rothwell


From dianders at chromium.org  Tue May 17 17:47:34 2016
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 17 May 2016 17:47:34 -0700
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <5502CA4E.9060401@samsung.com>
 <CAD=FV=VX3ix-j4y95W1q8b-aVuVEN+4xsd8WLx2xcE7KPNJwRw@mail.gmail.com>
 <5506707D.40708@samsung.com> <55189F04.8000404@samsung.com>
 <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
Message-ID: <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>

Jaehoon,

On Mon, Mar 30, 2015 at 8:47 AM, Doug Anderson <dianders at chromium.org> wrote:
> Jaehoon,
>
> On Sun, Mar 29, 2015 at 5:55 PM, Jaehoon Chung <jh80.chung at samsung.com> wrote:
>> Dear Doug,
>>
>> I'm considering to control HLE error..So holding this patch.
>> If this is absolutely necessary patch, let me know, plz.
>>
>> Best Regards,
>> Jaehoon Chung
>
> Sounds OK.  I have certainly applied this locally and the driver isn't
> robust against insertions / removals without it, but once the card is
> inserted things are OK so it's probably not urgent that it be applied
> upstream.  Hopefully we can figure out a better solution...

I'm now testing a nice new rebased kernel and I'm hitting this again.

Of course I'll just pick my same patch to my new kernel tree, but
since it's been a year and nobody has done anything better, would you
consider landing my patch?  It is certainly better than nothing.

-Doug


From lv.zheng at intel.com  Tue May 17 18:08:06 2016
From: lv.zheng at intel.com (Zheng, Lv)
Date: Wed, 18 May 2016 01:08:06 +0000
Subject: [PATCH 2/3] ACPI: table upgrade: move early_initrd_acpi_init()
 to header file
In-Reply-To: <1463486765-31827-3-git-send-email-aleksey.makarov@linaro.org>
References: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
 <1463486765-31827-3-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1AE640813FDE7649BE1B193DEA596E883BBA2DBF@SHSMSX101.ccr.corp.intel.com>

Hi,

> From: Aleksey Makarov [mailto:aleksey.makarov at linaro.org]
> Subject: [PATCH 2/3] ACPI: table upgrade: move early_initrd_acpi_init() to
> header file
> 
> Move early_initrd_acpi_init() to header file so that
> it can be used with architectures other than X86
[Lv Zheng] 
The patch looks OK to me.
Except 2 possible improvements.
You can feel free to add Acked-by: Lv Zheng <lv.zheng at intel.com>

> 
> Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
> ---
>  arch/x86/kernel/setup.c | 7 -------
>  drivers/acpi/tables.c   | 7 +++++--
>  include/linux/acpi.h    | 4 ++--
>  3 files changed, 7 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> index c4e7b39..5ddbbfd 100644
> --- a/arch/x86/kernel/setup.c
> +++ b/arch/x86/kernel/setup.c
> @@ -399,10 +399,6 @@ static void __init reserve_initrd(void)
>  	memblock_free(ramdisk_image, ramdisk_end - ramdisk_image);
>  }
> 
> -static void __init early_initrd_acpi_init(void)
> -{
> -	early_acpi_table_init((void *)initrd_start, initrd_end - initrd_start);
> -}
>  #else
>  static void __init early_reserve_initrd(void)
>  {
> @@ -410,9 +406,6 @@ static void __init early_reserve_initrd(void)
>  static void __init reserve_initrd(void)
>  {
>  }
> -static void __init early_initrd_acpi_init(void)
> -{
> -}
>  #endif /* CONFIG_BLK_DEV_INITRD */
> 
>  static void __init parse_setup_data(void)
> diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
> index 449a649..82be84a 100644
> --- a/drivers/acpi/tables.c
> +++ b/drivers/acpi/tables.c
> @@ -34,6 +34,7 @@
>  #include <linux/bootmem.h>
>  #include <linux/earlycpio.h>
>  #include <linux/memblock.h>
> +#include <linux/initrd.h>
>  #include "internal.h"
> 
>  #ifdef CONFIG_ACPI_CUSTOM_DSDT
> @@ -742,9 +743,11 @@ acpi_os_table_override(struct acpi_table_header
> *existing_table,
>  	return AE_OK;
>  }
> 
> -void __init early_acpi_table_init(void *data, size_t size)
> +void __init early_initrd_acpi_init(void)
>  {
> -	acpi_table_initrd_init(data, size);
> +#ifdef CONFIG_BLK_DEV_INITRD
> +	acpi_table_initrd_init((void *)initrd_start, initrd_end - initrd_start);
> +#endif
>  }
[Lv Zheng] 
Please avoid to make #ifdef appearing in a function body.
You may consider a way to maintain #ifdef CONFIG_xxx at function boundary.
The point is:
#ifdef should be maintained at the function boundary, this is an implicit (maybe explicit in Documentation) programming rule in Linux.
This helps to split the "functionality" and the "dependency" to make the code cleaner and easier to follow.

For this case, you may:
#ifdef CONFIG_BLK_DEV_INTRD
#define ACPI_TABLE_INITRD_DATA	(initrd_start)
#define ACPI_TABLE_INITRD_SIZE	(initrd_end - initrd_start)
#else
#define ACPI_TABLE_INITRD_DATA	NULL
#define ACPI_TABLE_INITRD_SIZE	0
#endif

Or you can:
Use initrd_start, inird_end directly in acpi_table_initrd_init, and delete its arguments.
By doing so, you are able to achieve in-function #ifdef elimination by providing a stub for acpi_table_initrd_init().

> 
>  /*
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 288fac5..cb700c1 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -208,7 +208,7 @@ void acpi_boot_table_init (void);
>  int acpi_mps_check (void);
>  int acpi_numa_init (void);
> 
> -void early_acpi_table_init(void *data, size_t size);
> +void early_initrd_acpi_init(void);
>  int acpi_table_init (void);
>  int acpi_table_parse(char *id, acpi_tbl_table_handler handler);
>  int __init acpi_parse_entries(char *id, unsigned long table_size,
> @@ -588,7 +588,7 @@ static inline const char *acpi_dev_name(struct
> acpi_device *adev)
>  	return NULL;
>  }
> 
> -static inline void early_acpi_table_init(void *data, size_t size) { }
> +static inline void early_initrd_acpi_init(void) { }
>  static inline void acpi_early_init(void) { }
>  static inline void acpi_subsystem_init(void) { }
> 
[Lv Zheng] 
You can rename early_initrd_acpi_init to early_acpi_table_init.
We'd prefer not to export "initrd" awareness from acpi.h.

Thanks and best regards
-Lv

> --
> 2.8.2



From shijie.huang at arm.com  Tue May 17 18:31:32 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Wed, 18 May 2016 09:31:32 +0800
Subject: [PATCH v12 10/10] kprobes: Add arm64 case in kprobe example module
In-Reply-To: <20160517102427.GD8104@sirena.org.uk>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-11-git-send-email-dave.long@linaro.org>
 <20160517095714.GA25167@sha-win-210.asiapac.arm.com>
 <20160517102427.GD8104@sirena.org.uk>
Message-ID: <20160518013131.GA29570@sha-win-210.asiapac.arm.com>

On Tue, May 17, 2016 at 11:24:27AM +0100, Mark Brown wrote:
> On Tue, May 17, 2016 at 05:57:33PM +0800, Huang Shijie wrote:
> > On Wed, Apr 27, 2016 at 02:53:05PM -0400, David Long wrote:
> 
> > > +#ifdef CONFIG_ARM64
> > > +	pr_info("pre_handler: p->addr = 0x%p, pc = 0x%lx\n",
> 
> > I think you miss the KERN_INFO here.
> 
> That's what pr_info() does over printk() - it adds the KERN_INFO more
> cleanly.
sorry, I thought the "pr_info" to "printk" when I first read this code.

thanks
Huang Shijie



From shawn.lin at kernel-upstream.org  Tue May 17 18:59:41 2016
From: shawn.lin at kernel-upstream.org (Shawn Lin)
Date: Wed, 18 May 2016 09:59:41 +0800
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <5502CA4E.9060401@samsung.com>
 <CAD=FV=VX3ix-j4y95W1q8b-aVuVEN+4xsd8WLx2xcE7KPNJwRw@mail.gmail.com>
 <5506707D.40708@samsung.com> <55189F04.8000404@samsung.com>
 <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
 <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
Message-ID: <573BCC8D.5090606@kernel-upstream.org>

Hi Doug,

On 2016-5-18 8:47, Doug Anderson wrote:
> Jaehoon,
>
> On Mon, Mar 30, 2015 at 8:47 AM, Doug Anderson <dianders at chromium.org> wrote:
>> Jaehoon,
>>
>> On Sun, Mar 29, 2015 at 5:55 PM, Jaehoon Chung <jh80.chung at samsung.com> wrote:
>>> Dear Doug,
>>>
>>> I'm considering to control HLE error..So holding this patch.
>>> If this is absolutely necessary patch, let me know, plz.
>>>
>>> Best Regards,
>>> Jaehoon Chung
>> Sounds OK.  I have certainly applied this locally and the driver isn't
>> robust against insertions / removals without it, but once the card is
>> inserted things are OK so it's probably not urgent that it be applied
>> upstream.  Hopefully we can figure out a better solution...
> I'm now testing a nice new rebased kernel and I'm hitting this again.
>
> Of course I'll just pick my same patch to my new kernel tree, but
> since it's been a year and nobody has done anything better, would you
> consider landing my patch?  It is certainly better than nothing.

Could you try this patch to see if you can still find HLE?

@@ -2356,12 +2356,22 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
  static void dw_mci_handle_cd(struct dw_mci *host)
  {
         int i;
+       int present;

         for (i = 0; i < host->num_slots; i++) {
                 struct dw_mci_slot *slot = host->slot[i];

                 if (!slot)
                         continue;

+               present = !(mci_readl(slot->host, CDETECT) & (1 << slot->id));
+               if (present)
+                       set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+               else
+                       clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);

                 if (slot->mmc->ops->card_event)
                         slot->mmc->ops->card_event(slot->mmc);


>
> -Doug
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>



From jh80.chung at samsung.com  Tue May 17 19:08:53 2016
From: jh80.chung at samsung.com (Jaehoon Chung)
Date: Wed, 18 May 2016 11:08:53 +0900
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <5502CA4E.9060401@samsung.com>
 <CAD=FV=VX3ix-j4y95W1q8b-aVuVEN+4xsd8WLx2xcE7KPNJwRw@mail.gmail.com>
 <5506707D.40708@samsung.com> <55189F04.8000404@samsung.com>
 <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
 <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
Message-ID: <573BCEB5.8020905@samsung.com>

On 05/18/2016 09:47 AM, Doug Anderson wrote:
> Jaehoon,
> 
> On Mon, Mar 30, 2015 at 8:47 AM, Doug Anderson <dianders at chromium.org> wrote:
>> Jaehoon,
>>
>> On Sun, Mar 29, 2015 at 5:55 PM, Jaehoon Chung <jh80.chung at samsung.com> wrote:
>>> Dear Doug,
>>>
>>> I'm considering to control HLE error..So holding this patch.
>>> If this is absolutely necessary patch, let me know, plz.
>>>
>>> Best Regards,
>>> Jaehoon Chung
>>
>> Sounds OK.  I have certainly applied this locally and the driver isn't
>> robust against insertions / removals without it, but once the card is
>> inserted things are OK so it's probably not urgent that it be applied
>> upstream.  Hopefully we can figure out a better solution...
> 
> I'm now testing a nice new rebased kernel and I'm hitting this again.
> 
> Of course I'll just pick my same patch to my new kernel tree, but
> since it's been a year and nobody has done anything better, would you
> consider landing my patch?  It is certainly better than nothing.

Sure, it's right.
I think that main reason of HLE is wait_prvdata_complete. (I'm guessing..)
On other hands, dwmmc controller is handling something wrong. (I found that HLE is occurred the similar case.)
After find the main solution, it's not bad that your patch is applied on dwmmc controller.

Ulf have sent PR for next..So if we needs to apply this, i will apply on fix.

Best Regards,
Jaehoon Chung

> 
> -Doug
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 



From dyoung at redhat.com  Tue May 17 19:09:17 2016
From: dyoung at redhat.com (Dave Young)
Date: Wed, 18 May 2016 10:09:17 +0800
Subject: [PATCH v15 00/20] arm64 kexec kernel patches v15
In-Reply-To: <573AD11E.1030301@arm.com>
References: <cover.1457977401.git.geoff@infradead.org>
 <20160401015947.GA3835@dhcp-128-65.nay.redhat.com>
 <1459535954.20121.3.camel@infradead.org>
 <20160517054216.GA12543@dhcp-128-65.nay.redhat.com>
 <573AD11E.1030301@arm.com>
Message-ID: <20160518020917.GB3073@dhcp-128-65.nay.redhat.com>

Hi Marc

On 05/17/16 at 09:06am, Marc Zyngier wrote:
> Hi Dave,
> 
> On 17/05/16 06:42, Dave Young wrote:
> > Marc, it has been discussed for long time, I think kdump code can be
> > logically splitted from this series so that we can get the kexec
> > done first? 
> 
> The basis for kexec are already on their way to mainline, as part of the
> hibernate series that James has put together.
> 
> I'd expect someone to:
> 
> 1) rebase the remaining kexec/kdump patches based on the current
> arm64/for-next/core,
> 2) post these patches when -rc1 gets cut in two weeks from now,
> 3) address the review comments in a timely manner,
> 4) update the series once a week so that we see some actual progress
> 
> If this happens, I can't see any reason why this code wouldn't get
> merged. But keeping kexec and kdump together is not what has prevented
> the code from getting merged until now.

Cool, thanks a lot for the clarification about the situation.

Dave


From shijie.huang at arm.com  Tue May 17 19:24:18 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Wed, 18 May 2016 10:24:18 +0800
Subject: [PATCH v12 00/10] arm64: Add kernel probes (kprobes) support
In-Reply-To: <5733E9E0.1060504@huawei.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <573350B2.4010701@arm.com> <5733E9E0.1060504@huawei.com>
Message-ID: <20160518022416.GA27271@sha-win-210.asiapac.arm.com>

On Thu, May 12, 2016 at 10:26:40AM +0800, Li Bin wrote:
> 
> 
> on 2016/5/11 23:33, James Morse wrote:
> > Hi David,
> > 
> > On 27/04/16 19:52, David Long wrote:
> >> From: "David A. Long" <dave.long at linaro.org>
> >>
> >> This patchset is heavily based on Sandeepa Prabhu's ARM v8 kprobes patches,
> >> first seen in October 2013. This version attempts to address concerns raised by
> >> reviewers and also fixes problems discovered during testing.
> >>
> >> This patchset adds support for kernel probes(kprobes), jump probes(jprobes)
> >> and return probes(kretprobes) support for ARM64.
> >>
> >> The kprobes mechanism makes use of software breakpoint and single stepping
> >> support available in the ARM v8 kernel.
> > 
> > I applied this series on v4.6-rc7, and built the sample kprobes. They work fine,
> > unless I throw ftrace into the mix too.
> > 
> > I enabled the function_graph tracer, then tried to load the jprobe example module:
> > -------------------------%<-------------------------
> > root at ubuntu:/sys/kernel/debug/tracing# insmod /root/jprobe_example.ko
> > Planted jprobe at ffffff80080c8f20, handler addr ffffff8000bb3000
> > root at ubuntu:/sys/kernel/debug/tracing# jprobe: clone_flags = 0x1200011, stack_st
> > art = 0x0 stack_size = 0x0
> > Bad mode in Synchronous Abort handler detected, code 0x86000005 -- IABT (current
> >  EL)
> > CPU: 5 PID: 1047 Comm: systemd-udevd Not tainted 4.6.0-rc7+ #4064
> > Hardware name: ARM Juno development board (r1) (DT)
> > task: ffffffc975948300 ti: ffffffc974e4c000 task.ti: ffffffc974e4c000
> > PC is at 0x0
> > LR is at 0x0
> > 
> > pc : [<0000000000000000>] lr : [<0000000000000000>] pstate: 60000145
> > sp : ffffffc974e4ff00
> > x29: 0000000001200011 x28: ffffffc974e4c000
> > x27: ffffff80088d0000 x26: 00000000000000dc
> > x25: 0000000000000120 x24: 0000000000000015
> > x23: 0000000060000000 x22: 0000007fa1b40e60
> > x21: 0000007fa1ce70d0 x20: 0000000000000000
> > x19: 0000000000000000 x18: 0000000000000a03
> > x17: 0000007fa1b40d90 x16: ffffff80080c9708
> > x15: 003b9aca00000000 x14: 0000007fddb7e5c0
> > x13: 0000007fa1b40e2c x12: 0000000000d00ff0
> > x11: ffffff8009c4d000 x10: ffffff800920c000
> > x9 : ffffff8008f5c000 x8 : ffffffc976c06800
> > x7 : 000000000006daf2 x6 : 0000000000000015
> > x5 : 0000000000000004 x4 : ffffffc96e8690a0
> > x3 : 0000001ed7cbab74 x2 : ffffffc96e869000
> > x1 : 0000000000000000 x0 : 0000000000000000
> > 
> > Internal error: Oops - bad mode: 0 [#1] PREEMPT SMP
> > Modules linked in: jprobe_example
> > CPU: 5 PID: 1047 Comm: systemd-udevd Not tainted 4.6.0-rc7+ #4064
> > Hardware name: ARM Juno development board (r1) (DT)
> > task: ffffffc975948300 ti: ffffffc974e4c000 task.ti: ffffffc974e4c000
> > PC is at 0x0
> > LR is at 0x0
> > 
> > pc : [<0000000000000000>] lr : [<0000000000000000>] pstate: 60000145
> > sp : ffffffc974e4ff00
> > x29: 0000000001200011 x28: ffffffc974e4c000
> > x27: ffffff80088d0000 x26: 00000000000000dc
> > x25: 0000000000000120 x24: 0000000000000015
> > x23: 0000000060000000 x22: 0000007fa1b40e60
> > x21: 0000007fa1ce70d0 x20: 0000000000000000
> > x19: 0000000000000000 x18: 0000000000000a03
> > x17: 0000007fa1b40d90 x16: ffffff80080c9708
> > x15: 003b9aca00000000 x14: 0000007fddb7e5c0
> > x13: 0000007fa1b40e2c x12: 0000000000d00ff0
> > x11: ffffff8009c4d000 x10: ffffff800920c000
> > x9 : ffffff8008f5c000 x8 : ffffffc976c06800
> > x7 : 000000000006daf2 x6 : 0000000000000015
> > x5 : 0000000000000004 x4 : ffffffc96e8690a0
> > x3 : 0000001ed7cbab74 x2 : ffffffc96e869000
> > x1 : 0000000000000000 x0 : 0000000000000000
> > 
> > Process systemd-udevd (pid: 1047, stack limit = 0xffffffc974e4c020)
> > Stack: (0xffffffc974e4ff00 to 0xffffffc974e50000)
> > ff00: 0000000000000417 0000007fa1ce76f0 00000000000000dc 0000000000000417
> > ff20: 00000000ffffffff 0000007fddb7ecf8 0000000000000005 ffffffffffffffff
> > ff40: 00000000ff000001 003b9aca00000000 000000555b3868b0 0000007fa1b40d90
> > ff60: 0000000000000a03 0000007fddb7e5c0 0000000000000000 0000007fddb7e5e0
> > ff80: 000000555b358000 000000558f56f0e0 0000000000000000 000000558f574f00
> > ffa0: 000000558f574f00 00000000000004fa 000000558f56f010 0000007fddb7e600
> > ffc0: 0000007fa1b40e2c 0000007fddb7e5c0 0000007fa1b40e60 0000000060000000
> > ffe0: 0000000001200011 00000000000000dc 0004000084000200 0800000002000000
> > Call trace:
> > [<          (null)>]           (null)
> > Code: bad PC value
> > ---[ end trace 35d24aad799c2941 ]---
> > -------------------------%<-------------------------
> > 
> 
> To solve this, it should pause function tracing before the jprobe handler is called
> and unpause it before it returns back to the function it probed.
> 
> diff --git a/arch/arm64/kernel/kprobes.c b/arch/arm64/kernel/kprobes.c
> index db2d95c..b21ed00 100644
> --- a/arch/arm64/kernel/kprobes.c
> +++ b/arch/arm64/kernel/kprobes.c
> @@ -714,6 +714,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
> 
>         instruction_pointer_set(regs, (long)jp->entry);
>         preempt_disable();
> +       pause_graph_tracing();
>         return 1;
>  }
> 
> @@ -757,6 +758,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
>                         show_regs(regs);
>                         BUG();
>                 }
> +               unpause_graph_tracing();
>                 *regs = kcb->jprobe_saved_regs;
>                 memcpy((void *)stack_addr, kcb->jprobes_stack,
>                        MIN_STACK_SIZE(stack_addr));
> 
> 
I tested this fix, it works.

thanks
Huang Shijie



From lv.zheng at intel.com  Tue May 17 20:06:35 2016
From: lv.zheng at intel.com (Zheng, Lv)
Date: Wed, 18 May 2016 03:06:35 +0000
Subject: [PATCH 1/3] ACPI: table upgrade: use cacheable map for tables
In-Reply-To: <1463486765-31827-2-git-send-email-aleksey.makarov@linaro.org>
References: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
 <1463486765-31827-2-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1AE640813FDE7649BE1B193DEA596E883BBA2E5F@SHSMSX101.ccr.corp.intel.com>

Hi,

> From: Aleksey Makarov [mailto:aleksey.makarov at linaro.org]
> Subject: [PATCH 1/3] ACPI: table upgrade: use cacheable map for tables
> 
> The new memory allocated in acpi_table_initrd_init() is used to
> copy the upgraded tables to it.  So it should be mapped with
> early_memunmap() instead of early_ioremap().
> 
> This is critical for ARM.
> 
> Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
[Lv Zheng] 
Acked-by: Lv Zheng <lv.zheng at intel.com>

Thanks
-Lv

> ---
>  drivers/acpi/tables.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
> index a372f9e..449a649 100644
> --- a/drivers/acpi/tables.c
> +++ b/drivers/acpi/tables.c
> @@ -578,10 +578,10 @@ static void __init acpi_table_initrd_init(void *data,
> size_t size)
>  			clen = size;
>  			if (clen > MAP_CHUNK_SIZE - slop)
>  				clen = MAP_CHUNK_SIZE - slop;
> -			dest_p = early_ioremap(dest_addr & PAGE_MASK,
> +			dest_p = early_memremap(dest_addr & PAGE_MASK,
>  						 clen + slop);
>  			memcpy(dest_p + slop, src_p, clen);
> -			early_iounmap(dest_p, clen + slop);
> +			early_memunmap(dest_p, clen + slop);
>  			src_p += clen;
>  			dest_addr += clen;
>  			size -= clen;
> --
> 2.8.2



From mhiramat at kernel.org  Tue May 17 20:29:35 2016
From: mhiramat at kernel.org (Masami Hiramatsu)
Date: Wed, 18 May 2016 12:29:35 +0900
Subject: [PATCH v12 05/10] arm64: Kprobes with single stepping support
In-Reply-To: <20160517085807.GA842@sha-win-210.asiapac.arm.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-6-git-send-email-dave.long@linaro.org>
 <20160517085807.GA842@sha-win-210.asiapac.arm.com>
Message-ID: <20160518122935.39fd7acc63d6f9c17fcbe275@kernel.org>

On Tue, 17 May 2016 16:58:09 +0800
Huang Shijie <shijie.huang at arm.com> wrote:

> On Wed, Apr 27, 2016 at 02:53:00PM -0400, David Long wrote:
> > +
> > +/*
> > + * Interrupts need to be disabled before single-step mode is set, and not
> > + * reenabled until after single-step mode ends.
> > + * Without disabling interrupt on local CPU, there is a chance of
> > + * interrupt occurrence in the period of exception return and  start of
> > + * out-of-line single-step, that result in wrongly single stepping
> > + * into the interrupt handler.
> > + */
> > +static void __kprobes kprobes_save_local_irqflag(struct pt_regs *regs)
> > +{
> > +     struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
> 
> Why not add a parameter for this function to save the @kcb?

Good catch, it should use same kcb of caller.

> 
> > +
> > +     kcb->saved_irqflag = regs->pstate;
> > +     regs->pstate |= PSR_I_BIT;
> > +}
> > +
> > +static void __kprobes kprobes_restore_local_irqflag(struct pt_regs *regs)
> > +{
> > +     struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
> ditto.
> 
> > +
> > +     if (kcb->saved_irqflag & PSR_I_BIT)
> > +             regs->pstate |= PSR_I_BIT;
> > +     else
> > +             regs->pstate &= ~PSR_I_BIT;
> > +}
> > +
> > +static void __kprobes
> > +set_ss_context(struct kprobe_ctlblk *kcb, unsigned long addr)
> > +{
> > +     kcb->ss_ctx.ss_pending = true;
> > +     kcb->ss_ctx.match_addr = addr + sizeof(kprobe_opcode_t);
> > +}
> > +
> > +static void __kprobes clear_ss_context(struct kprobe_ctlblk *kcb)
> > +{
> > +     kcb->ss_ctx.ss_pending = false;
> > +     kcb->ss_ctx.match_addr = 0;
> > +}
> > +
> > +static void __kprobes setup_singlestep(struct kprobe *p,
> > +                                    struct pt_regs *regs,
> > +                                    struct kprobe_ctlblk *kcb, int reenter)
> > +{
> > +     unsigned long slot;
> > +
> > +     if (reenter) {
> > +             save_previous_kprobe(kcb);
> > +             set_current_kprobe(p);
> > +             kcb->kprobe_status = KPROBE_REENTER;
> > +     } else {
> > +             kcb->kprobe_status = KPROBE_HIT_SS;
> > +     }
> > +
> > +     if (p->ainsn.insn) {
> > +             /* prepare for single stepping */
> > +             slot = (unsigned long)p->ainsn.insn;
> > +
> > +             set_ss_context(kcb, slot);      /* mark pending ss */
> > +
> > +             if (kcb->kprobe_status == KPROBE_REENTER)
> > +                     spsr_set_debug_flag(regs, 0);
> > +
> > +             /* IRQs and single stepping do not mix well. */
> > +             kprobes_save_local_irqflag(regs);
> > +             kernel_enable_single_step(regs);
> > +             instruction_pointer(regs) = slot;
> > +     } else  {
> > +             BUG();

You'd better use BUG_ON(!p->ainsn.insn);

> > +     }
> > +}
> > +
> > +static int __kprobes reenter_kprobe(struct kprobe *p,
> > +                                 struct pt_regs *regs,
> > +                                 struct kprobe_ctlblk *kcb)
> > +{
> > +     switch (kcb->kprobe_status) {
> > +     case KPROBE_HIT_SSDONE:
> > +     case KPROBE_HIT_ACTIVE:
> > +             kprobes_inc_nmissed_count(p);
> > +             setup_singlestep(p, regs, kcb, 1);
> > +             break;
> > +     case KPROBE_HIT_SS:
> > +     case KPROBE_REENTER:
> > +             pr_warn("Unrecoverable kprobe detected at %p.\n", p->addr);
> > +             dump_kprobe(p);
> > +             BUG();
> > +             break;
> > +     default:
> > +             WARN_ON(1);
> > +             return 0;
> > +     }
> > +
> > +     return 1;
> > +}
> > +
> > +static void __kprobes
> > +post_kprobe_handler(struct kprobe_ctlblk *kcb, struct pt_regs *regs)
> > +{
> > +     struct kprobe *cur = kprobe_running();
> > +
> > +     if (!cur)
> > +             return;
> > +
> > +     /* return addr restore if non-branching insn */
> > +     if (cur->ainsn.restore.type == RESTORE_PC) {
> > +             instruction_pointer(regs) = cur->ainsn.restore.addr;
> > +             if (!instruction_pointer(regs))
> > +                     BUG();
> > +     }
> > +
> > +     /* restore back original saved kprobe variables and continue */
> > +     if (kcb->kprobe_status == KPROBE_REENTER) {
> > +             restore_previous_kprobe(kcb);
> > +             return;
> > +     }
> > +     /* call post handler */
> > +     kcb->kprobe_status = KPROBE_HIT_SSDONE;
> > +     if (cur->post_handler)  {
> > +             /* post_handler can hit breakpoint and single step
> > +              * again, so we enable D-flag for recursive exception.
> > +              */
> > +             cur->post_handler(cur, regs, 0);
> > +     }
> > +
> > +     reset_current_kprobe();
> > +}
> > +
> > +int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
> > +{
> > +     struct kprobe *cur = kprobe_running();
> > +     struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
> > +
> > +     switch (kcb->kprobe_status) {
> > +     case KPROBE_HIT_SS:
> > +     case KPROBE_REENTER:
> > +             /*
> > +              * We are here because the instruction being single
> > +              * stepped caused a page fault. We reset the current
> > +              * kprobe and the ip points back to the probe address
> > +              * and allow the page fault handler to continue as a
> > +              * normal page fault.
> > +              */
> > +             instruction_pointer(regs) = (unsigned long)cur->addr;
> > +             if (!instruction_pointer(regs))
> > +                     BUG();

This can be BUG_ON(!instruction_pointer(regs)).

> > +             if (kcb->kprobe_status == KPROBE_REENTER)
> > +                     restore_previous_kprobe(kcb);
> > +             else
> > +                     reset_current_kprobe();
> > +
> > +             break;
> > +     case KPROBE_HIT_ACTIVE:
> > +     case KPROBE_HIT_SSDONE:
> > +             /*
> > +              * We increment the nmissed count for accounting,
> > +              * we can also use npre/npostfault count for accounting
> > +              * these specific fault cases.
> > +              */
> > +             kprobes_inc_nmissed_count(cur);
> > +
> > +             /*
> > +              * We come here because instructions in the pre/post
> > +              * handler caused the page_fault, this could happen
> > +              * if handler tries to access user space by
> > +              * copy_from_user(), get_user() etc. Let the
> > +              * user-specified handler try to fix it first.
> > +              */
> > +             if (cur->fault_handler && cur->fault_handler(cur, regs, fsr))
> > +                     return 1;
> > +
> > +             /*
> > +              * In case the user-specified fault handler returned
> > +              * zero, try to fix up.
> > +              */
> > +             if (fixup_exception(regs))
> > +                     return 1;
> > +     }
> > +     return 0;
> > +}
> > +
> > +int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
> > +                                    unsigned long val, void *data)
> > +{
> > +     return NOTIFY_DONE;
> > +}
> > +
> > +static void __kprobes kprobe_handler(struct pt_regs *regs)
> > +{
> > +     struct kprobe *p, *cur_kprobe;
> > +     struct kprobe_ctlblk *kcb;
> > +     unsigned long addr = instruction_pointer(regs);
> > +
> > +     kcb = get_kprobe_ctlblk();
> > +     cur_kprobe = kprobe_running();
> > +
> > +     p = get_kprobe((kprobe_opcode_t *) addr);
> > +
> > +     if (p) {
> > +             if (cur_kprobe) {
> > +                     if (reenter_kprobe(p, regs, kcb))
> > +                             return;
> > +             } else {
> > +                     /* Probe hit */
> > +                     set_current_kprobe(p);
> > +                     kcb->kprobe_status = KPROBE_HIT_ACTIVE;
> > +
> > +                     /*
> > +                      * If we have no pre-handler or it returned 0, we
> > +                      * continue with normal processing.  If we have a
> > +                      * pre-handler and it returned non-zero, it prepped
> > +                      * for calling the break_handler below on re-entry,
> > +                      * so get out doing nothing more here.
> > +                      *
> > +                      * pre_handler can hit a breakpoint and can step thru
> > +                      * before return, keep PSTATE D-flag enabled until
> > +                      * pre_handler return back.
> > +                      */
> > +                     if (!p->pre_handler || !p->pre_handler(p, regs)) {
> > +                             kcb->kprobe_status = KPROBE_HIT_SS;
> The above line is duplicated.
> You will set KPROBE_HIT_SS in the setup_singlestep.

Right.

> 
> > +                             setup_singlestep(p, regs, kcb, 0);
> > +                             return;
> > +                     }
> > +             }
> > +     } else if ((le32_to_cpu(*(kprobe_opcode_t *) addr) ==
> > +         BRK64_OPCODE_KPROBES) && cur_kprobe) {
> > +             /* We probably hit a jprobe.  Call its break handler. */
> > +             if (cur_kprobe->break_handler  &&
> > +                  cur_kprobe->break_handler(cur_kprobe, regs)) {
> > +                     kcb->kprobe_status = KPROBE_HIT_SS;
> ditto
> > +                     setup_singlestep(cur_kprobe, regs, kcb, 0);
> > +                     return;
> > +             }
> > +     }
> > +     /*
> > +      * The breakpoint instruction was removed right
> > +      * after we hit it.  Another cpu has removed
> > +      * either a probepoint or a debugger breakpoint
> > +      * at this address.  In either case, no further
> > +      * handling of this interrupt is appropriate.
> > +      * Return back to original instruction, and continue.
> > +      */
> > +}

Thanks,



-- 
Masami Hiramatsu <mhiramat at kernel.org>


From mhiramat at kernel.org  Tue May 17 21:04:26 2016
From: mhiramat at kernel.org (Masami Hiramatsu)
Date: Wed, 18 May 2016 13:04:26 +0900
Subject: [PATCH v12 05/10] arm64: Kprobes with single stepping support
In-Reply-To: <57349AE2.3060507@arm.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-6-git-send-email-dave.long@linaro.org>
 <57349AE2.3060507@arm.com>
Message-ID: <20160518130426.9f8b409c97a8b98ac230a232@kernel.org>

On Thu, 12 May 2016 16:01:54 +0100
James Morse <james.morse at arm.com> wrote:

> Hi David, Sandeepa,
> 
> On 27/04/16 19:53, David Long wrote:
> > From: Sandeepa Prabhu <sandeepa.s.prabhu at gmail.com>
> 
> > diff --git a/arch/arm64/kernel/kprobes.c b/arch/arm64/kernel/kprobes.c
> > new file mode 100644
> > index 0000000..dfa1b1f
> > --- /dev/null
> > +++ b/arch/arm64/kernel/kprobes.c
> > @@ -0,0 +1,520 @@
> > +/*
> > + * arch/arm64/kernel/kprobes.c
> > + *
> > + * Kprobes support for ARM64
> > + *
> > + * Copyright (C) 2013 Linaro Limited.
> > + * Author: Sandeepa Prabhu <sandeepa.prabhu at linaro.org>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > + * General Public License for more details.
> > + *
> > + */
> > +#include <linux/kernel.h>
> > +#include <linux/kprobes.h>
> > +#include <linux/module.h>
> > +#include <linux/slab.h>
> > +#include <linux/stop_machine.h>
> > +#include <linux/stringify.h>
> > +#include <asm/traps.h>
> > +#include <asm/ptrace.h>
> > +#include <asm/cacheflush.h>
> > +#include <asm/debug-monitors.h>
> > +#include <asm/system_misc.h>
> > +#include <asm/insn.h>
> > +#include <asm/uaccess.h>
> > +
> > +#include "kprobes-arm64.h"
> > +
> > +#define MIN_STACK_SIZE(addr)	min((unsigned long)MAX_STACK_SIZE,	\
> > +	(unsigned long)current_thread_info() + THREAD_START_SP - (addr))
> 
> What if we probe something called on the irq stack?
> This needs the on_irq_stack() checks too, the start/end can be found from the
> per-cpu irq_stack value.
> 
> [ ... ]
> 
> > +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
> > +{
> > +	struct jprobe *jp = container_of(p, struct jprobe, kp);
> > +	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
> > +	long stack_ptr = kernel_stack_pointer(regs);
> > +
> > +	kcb->jprobe_saved_regs = *regs;
> > +	memcpy(kcb->jprobes_stack, (void *)stack_ptr,
> > +	       MIN_STACK_SIZE(stack_ptr));
> 
> I wonder if we need this stack save/restore?
> 
> The comment next to the equivalent code for x86 says:
> > gcc assumes that the callee owns the argument space and could overwrite it,
> > e.g. tailcall optimization. So, to be absolutely safe we also save and
> > restore enough stack bytes to cover the argument area.
> 
> On arm64 the first eight arguments are passed in registers, so we might not need
> this stack copy. (sparc and powerpc work like this too, their versions of this
> function don't copy chunks of the stack).

Hmm, maybe sparc and powerpc implementation should also be fixed...

> ... then I went looking for functions with >8 arguments...
> 
> Looking at the arm64 defconfig dwarf debug data, there are 71 of these that
> don't get inlined, picking at random:
> > rockchip_clk_register_pll() has 13
> > fib_dump_info() has 11
> > vma_merge() has 10
> > vring_create_virtqueue() has 10
> etc...
> 
> So we do need this stack copying, so that we can probe these function without
> risking the arguments being modified.
> 
> It may be worth including a comment to the effect that this stack save/restore
> is needed for functions that pass >8 arguments where the pre-handler may change
> these values on the stack.

Indeed, commenting on this code can help us to understand the reason why.

Thank you!

> 
> 
> > +	preempt_enable_no_resched();
> > +	return 1;
> > +}
> > +
> 
> 
> Thanks,
> 
> James


-- 
Masami Hiramatsu <mhiramat at kernel.org>


From bjorn.andersson at linaro.org  Tue May 17 21:09:43 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Tue, 17 May 2016 21:09:43 -0700
Subject: QRTR merge conflict resolution
In-Reply-To: <20160518104320.23ae8557@canb.auug.org.au>
References: <20160510183934.GJ1256@tuxbot> <2606282.lG9qK7uBW0@wuerfel>
 <20160513221909.GC1256@tuxbot>
 <20160517.141154.1511755950068252376.davem@davemloft.net>
 <20160518104320.23ae8557@canb.auug.org.au>
Message-ID: <20160518040943.GO1256@tuxbot>

On Tue 17 May 17:43 PDT 2016, Stephen Rothwell wrote:

> Hi David,
> 
> On Tue, 17 May 2016 14:11:54 -0400 (EDT) David Miller <davem at davemloft.net> wrote:
> >
> > From: Bjorn Andersson <bjorn.andersson at linaro.org>
> > Date: Fri, 13 May 2016 15:19:09 -0700
> > 
> > > I have prepared the merge of net-next and the conflicting tag from the
> > > Qualcomm SOC, please include this in your pull towards Linus to avoid
> > > the merge conflict.  
> > 
> > Pulled, thanks.
> 
> Except in the merge resolution, the 2 new functions added to
> include/linux/soc/qcom/smd.h (qcom_smd_get_drvdata and
> qcom_smd_set_drvdata) were not marked "static inline" :-(
> 

How silly of me to miss that, sorry about that.

I didn't spot this in my compile testing either, because this is the
only driver in the tree including that file that doesn't depend on
QCOM_SMD.

As there is no immediate problem with moving forward I suggest that I'll
fix this, through arm-soc, once the code has landed.

Regards,
Bjorn


From dianders at chromium.org  Tue May 17 21:12:16 2016
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 17 May 2016 21:12:16 -0700
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <573BCC8D.5090606@kernel-upstream.org>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <5502CA4E.9060401@samsung.com>
 <CAD=FV=VX3ix-j4y95W1q8b-aVuVEN+4xsd8WLx2xcE7KPNJwRw@mail.gmail.com>
 <5506707D.40708@samsung.com> <55189F04.8000404@samsung.com>
 <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
 <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
 <573BCC8D.5090606@kernel-upstream.org>
Message-ID: <CAD=FV=VneQR3wurjezBkRhtQiH+q-FfhDN8=Ym=XqtZpVmsdUw@mail.gmail.com>

Hi,

On Tue, May 17, 2016 at 6:59 PM, Shawn Lin
<shawn.lin at kernel-upstream.org> wrote:
> Could you try this patch to see if you can still find HLE?
>
> @@ -2356,12 +2356,22 @@ static void dw_mci_cmd_interrupt(struct dw_mci
> *host, u32 status)
>  static void dw_mci_handle_cd(struct dw_mci *host)
>  {
>         int i;
> +       int present;
>
>         for (i = 0; i < host->num_slots; i++) {
>                 struct dw_mci_slot *slot = host->slot[i];
>
>                 if (!slot)
>                         continue;
>
> +               present = !(mci_readl(slot->host, CDETECT) & (1 <<
> slot->id));
> +               if (present)
> +                       set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
> +               else
> +                       clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);

No, because we don't use the builtin card detect on veyron.  ;)

We use GPIO card detect because we didn't like the way JTAG and SD
interacted.  Also on rk3288 the builtin card detect line had the wrong
voltage domain (you couldn't detect a card when the IO lines were
powered off).  The builtin card detect line is always driven low on
veyron.


I'm nearly certain that the root cause of my HLE errors is actually
related to the same problem addressed by the commit 7c5209c315ea
("mmc: core: Increase delay for voltage to stabilize from 3.3V to
1.8V").  I think that on minnie we're still on the hairy edge and
sometimes the line doesn't transition fast enough.

It appears that increasing this to 30ms avoids the HLE errors.

I _think_ I can actually fully fix this properly by temporarily
engaging the internal pull-ups while the voltage switch is happening.
This will bleed away the voltage just a little bit faster (since lines
are driven low here).  I'll try to confirm that.


In any case, it seems like we should take this patch since (without
this patch) the failure case when you get HLE errors is that the
interrupt controller fires over and over again (with no printouts) and
your system stalls with no error messages.

-Doug


From dianders at chromium.org  Tue May 17 21:13:12 2016
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 17 May 2016 21:13:12 -0700
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <573BCEB5.8020905@samsung.com>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <5502CA4E.9060401@samsung.com>
 <CAD=FV=VX3ix-j4y95W1q8b-aVuVEN+4xsd8WLx2xcE7KPNJwRw@mail.gmail.com>
 <5506707D.40708@samsung.com> <55189F04.8000404@samsung.com>
 <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
 <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
 <573BCEB5.8020905@samsung.com>
Message-ID: <CAD=FV=XFUKXRRRyVLOTV1ORtYfG1ngEqic-CYLp9S=C=8eJYkw@mail.gmail.com>

Hi,

On Tue, May 17, 2016 at 7:08 PM, Jaehoon Chung <jh80.chung at samsung.com> wrote:
> On 05/18/2016 09:47 AM, Doug Anderson wrote:
>> Jaehoon,
>>
>> On Mon, Mar 30, 2015 at 8:47 AM, Doug Anderson <dianders at chromium.org> wrote:
>>> Jaehoon,
>>>
>>> On Sun, Mar 29, 2015 at 5:55 PM, Jaehoon Chung <jh80.chung at samsung.com> wrote:
>>>> Dear Doug,
>>>>
>>>> I'm considering to control HLE error..So holding this patch.
>>>> If this is absolutely necessary patch, let me know, plz.
>>>>
>>>> Best Regards,
>>>> Jaehoon Chung
>>>
>>> Sounds OK.  I have certainly applied this locally and the driver isn't
>>> robust against insertions / removals without it, but once the card is
>>> inserted things are OK so it's probably not urgent that it be applied
>>> upstream.  Hopefully we can figure out a better solution...
>>
>> I'm now testing a nice new rebased kernel and I'm hitting this again.
>>
>> Of course I'll just pick my same patch to my new kernel tree, but
>> since it's been a year and nobody has done anything better, would you
>> consider landing my patch?  It is certainly better than nothing.
>
> Sure, it's right.
> I think that main reason of HLE is wait_prvdata_complete. (I'm guessing..)
> On other hands, dwmmc controller is handling something wrong. (I found that HLE is occurred the similar case.)
> After find the main solution, it's not bad that your patch is applied on dwmmc controller.
>
> Ulf have sent PR for next..So if we needs to apply this, i will apply on fix.

It's not new, so I'd say just queue it up for the next version
whenever it's convenient.

-Doug


From wangkefeng.wang at huawei.com  Tue May 17 22:50:14 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 18 May 2016 13:50:14 +0800
Subject: [PATCH 1/2] arm64: dts: NS2: Add all of the UARTs
In-Reply-To: <573B775F.4060503@gmail.com>
References: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
 <57341FCE.6050403@huawei.com>
 <CAC3K-4qbkt3DCgd6qurNo3V+++x70bbFC--aunR0DbCTBvBNZg@mail.gmail.com>
 <57353761.5020409@huawei.com>
 <CAC3K-4oXcwR--879sCFR=MCG1Uman7DoGvaHLVXWr+0QH2WeJg@mail.gmail.com>
 <57391E45.8010209@huawei.com> <573B775F.4060503@gmail.com>
Message-ID: <573C0296.1060503@huawei.com>



On 2016/5/18 3:56, Florian Fainelli wrote:
> On 05/15/2016 06:11 PM, Kefeng Wang wrote:
>>> I can confirm that with your change and the change to the bootargs you describe above, it works as desired.  Was your change already accepted?
>>>
>>
>> Great, thanks a lot. it is still being reviewing for now and waiting for response for now.
> 
> Then I would be inclined to take Jon's patch as-is, and follow up with
> an additional patch to the NS2 DTS once yours lands in.
> 

Sure, please.

Kefeng



From nab at linux-iscsi.org  Tue May 17 22:53:45 2016
From: nab at linux-iscsi.org (Nicholas A. Bellinger)
Date: Tue, 17 May 2016 22:53:45 -0700
Subject: [PATCH] Fix for hang of Ordered task in TCM
In-Reply-To: <1463177741-4385-1-git-send-email-mikecyr@linux.vnet.ibm.com>
References: <1463177741-4385-1-git-send-email-mikecyr@linux.vnet.ibm.com>
Message-ID: <1463550825.22249.17.camel@haakon3.risingtidesystems.com>

Hi Michael,

On Fri, 2016-05-13 at 17:15 -0500, Michael Cyr wrote:
> If a command with a Simple task attribute is failed due to a Unit
> Attention, then a subsequent command with an Ordered task attribute will
> hang forever.  The reason for this is that the Unit Attention status is
> checked for in target_setup_cmd_from_cdb, before the call to
> target_execute_cmd, which calls target_handle_task_attr, which in turn
> increments dev->simple_cmds.  However, transport_generic_request_failure
> still calls transport_complete_task_attr, which will decrement
> dev->simple_cmds.  In this case, simple_cmds is now -1.  So when a
> command with the Ordered task attribute is sent, target_handle_task_attr
> sees that dev->simple_cmds is not 0, so it decides it can't execute the
> command until all the (nonexistent) Simple commands have completed.
> 

Thanks for reporting this bug.  Comments below.

> The solution I've implemented is to move target_scsi3_ua_check, as well as
> target_alua_state_check and target_check_reservation, into
> target_execute_cmd, after the call to target_handle_task_attr.  I believe
> this is actually the correct way this should be handled.  According to
> SAM-4 r14, under section 5.14:
> 
> "h) if a command other than INQUIRY, REPORT LUNS, REQUEST SENSE, or NOTIFY
> DATA TRANSFER DEVICE enters the enabled command state while a unit
> attention condition exists for the SCSI initiator port associated with
> the I_T nexus on which the command was received, the device server shall
> terminate the command with a CHECK CONDITION status. The device server
> shall provide sense data that reports a unit attention condition for the
> SCSI initiator port that sent the command on the I_T nexus."
> 
> But according to section 8.5 and 8.6, a command which is not yet executed
> because of the presence of other tasks in the task set (i.e., one for
> which target_handle_task_attr returns true) would not enter the enabled
> command state; it would be in the dormant command state.
> target_execute_cmd would get called when a command entered the enabled
> command state, and thus that is the appropriate place to check for Unit
> Attenion.  Similarly, though not quite as explicit, section 5.3.3 tells
> us that a Reservation Conflict status has a lower precedence than a Unit
> Attention, and so this would also seem to be the appropriate place to
> call target_check_reservation.  I'm less sure about
> target_alua_state_check, since I'm not very familiar with ALUA.
> 
> Signed-off-by: Michael Cyr <mikecyr at linux.vnet.ibm.com>
> ---
>  drivers/target/target_core_transport.c | 41 ++++++++++++++++++++--------------
>  1 file changed, 24 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
> index 6c089af..2ee5502 100644
> --- a/drivers/target/target_core_transport.c
> +++ b/drivers/target/target_core_transport.c
> @@ -1303,23 +1303,6 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
>  
>  	trace_target_sequencer_start(cmd);
>  
> -	/*
> -	 * Check for an existing UNIT ATTENTION condition
> -	 */
> -	ret = target_scsi3_ua_check(cmd);
> -	if (ret)
> -		return ret;
> -
> -	ret = target_alua_state_check(cmd);
> -	if (ret)
> -		return ret;
> -
> -	ret = target_check_reservation(cmd);
> -	if (ret) {
> -		cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
> -		return ret;
> -	}
> -
>  	ret = dev->transport->parse_cdb(cmd);
>  	if (ret == TCM_UNSUPPORTED_SCSI_OPCODE)
>  		pr_warn_ratelimited("%s/%s: Unsupported SCSI Opcode 0x%02x, sending CHECK_CONDITION.\n",
> @@ -1865,6 +1848,8 @@ static int __transport_check_aborted_status(struct se_cmd *, int);
>  
>  void target_execute_cmd(struct se_cmd *cmd)
>  {
> +	sense_reason_t ret;
> +
>  	/*
>  	 * Determine if frontend context caller is requesting the stopping of
>  	 * this command for frontend exceptions.
> @@ -1899,6 +1884,28 @@ void target_execute_cmd(struct se_cmd *cmd)
>  		return;
>  	}
>  
> +	/*
> +	 * Check for an existing UNIT ATTENTION condition
> +	 */
> +	ret = target_scsi3_ua_check(cmd);
> +	if (ret) {
> +		transport_generic_request_failure(cmd, ret);
> +		return;
> +	}
> +
> +	ret = target_alua_state_check(cmd);
> +	if (ret) {
> +		transport_generic_request_failure(cmd, ret);
> +		return;
> +	}
> +
> +	ret = target_check_reservation(cmd);
> +	if (ret) {
> +		cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
> +		transport_generic_request_failure(cmd, ret);
> +		return;
> +	}
> +
>  	__target_execute_cmd(cmd);
>  }
>  EXPORT_SYMBOL(target_execute_cmd);

So AFAICT for delayed commands, the above patch ends up skipping these
three checks subsequently when doing __target_execute_cmd() directly
from target_restart_delayed_cmds(), no..?

After pondering this some more, what about moving these checks into
__target_execute_cmd() to handle both target_core_transport.c cases
instead..?

We'll also need a parameter for internal COMPARE_AND_WRITE usage
within compare_and_write_callback(), to bypass checks upon secondary
->execute_cmd() WRITE payload submission after READ + COMPARE has
completed successfully.

WDYT..?

diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index fc91e85..e2c970a 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -146,6 +146,7 @@ sense_reason_t	target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
 void	target_qf_do_work(struct work_struct *work);
 bool	target_check_wce(struct se_device *dev);
 bool	target_check_fua(struct se_device *dev);
+void	__target_execute_cmd(struct se_cmd *, bool);
 
 /* target_core_stat.c */
 void	target_stat_setup_dev_default_groups(struct se_device *);
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index a9057aa..04f616b 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -602,7 +602,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes
 	cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
 	spin_unlock_irq(&cmd->t_state_lock);
 
-	__target_execute_cmd(cmd);
+	__target_execute_cmd(cmd, false);
 
 	kfree(buf);
 	return ret;
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 6c089af..f3e93dd 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1761,20 +1761,45 @@ queue_full:
 }
 EXPORT_SYMBOL(transport_generic_request_failure);
 
-void __target_execute_cmd(struct se_cmd *cmd)
+void __target_execute_cmd(struct se_cmd *cmd, bool do_checks)
 {
 	sense_reason_t ret;
 
-	if (cmd->execute_cmd) {
-		ret = cmd->execute_cmd(cmd);
-		if (ret) {
-			spin_lock_irq(&cmd->t_state_lock);
-			cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
-			spin_unlock_irq(&cmd->t_state_lock);
+	if (!cmd->execute_cmd) {
+		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+		goto err;
+	}
+	if (do_checks) {
+		/*
+		 * Check for an existing UNIT ATTENTION condition after
+		 * target_handle_task_attr() has done SAM task attr
+		 * checking, and possibly have already defered execution
+		 * out to target_restart_delayed_cmds() context.
+		 */
+		ret = target_scsi3_ua_check(cmd);
+		if (ret)
+			goto err;
 
-			transport_generic_request_failure(cmd, ret);
+		ret = target_alua_state_check(cmd);
+		if (ret)
+			goto err;
+
+		ret = target_check_reservation(cmd);
+		if (ret) {
+			cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
+			goto err;
 		}
 	}
+
+	ret = cmd->execute_cmd(cmd);
+	if (!ret)
+		return;
+err:
+	spin_lock_irq(&cmd->t_state_lock);
+	cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
+	spin_unlock_irq(&cmd->t_state_lock);
+
+	transport_generic_request_failure(cmd, ret);
 }
 
 static int target_write_prot_action(struct se_cmd *cmd)
@@ -1899,7 +1924,7 @@ void target_execute_cmd(struct se_cmd *cmd)
 		return;
 	}
 
-	__target_execute_cmd(cmd);
+	__target_execute_cmd(cmd, true);
 }
 EXPORT_SYMBOL(target_execute_cmd);
 
@@ -1923,7 +1948,7 @@ static void target_restart_delayed_cmds(struct se_device *dev)
 		list_del(&cmd->se_delayed_node);
 		spin_unlock(&dev->delayed_cmd_lock);
 
-		__target_execute_cmd(cmd);
+		__target_execute_cmd(cmd, true);
 
 		if (cmd->sam_task_attr == TCM_ORDERED_TAG)
 			break;
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index ec79da3..334f107 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -163,7 +163,6 @@ int	core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t);
 void	core_tmr_release_req(struct se_tmr_req *);
 int	transport_generic_handle_tmr(struct se_cmd *);
 void	transport_generic_request_failure(struct se_cmd *, sense_reason_t);
-void	__target_execute_cmd(struct se_cmd *);
 int	transport_lookup_tmr_lun(struct se_cmd *, u64);
 void	core_allocate_nexus_loss_ua(struct se_node_acl *acl);
 
-- 
1.9.1



From ard.biesheuvel at linaro.org  Tue May 17 23:18:44 2016
From: ard.biesheuvel at linaro.org (Ard Biesheuvel)
Date: Wed, 18 May 2016 08:18:44 +0200
Subject: [PATCH v2 2/5] arm64: efi: apply strict permissons for UEFI
 Runtime Services regions
In-Reply-To: <573BB9FE.7050008@codeaurora.org>
References: <1459355933-13529-1-git-send-email-ard.biesheuvel@linaro.org>
 <1459355933-13529-3-git-send-email-ard.biesheuvel@linaro.org>
 <573BB9FE.7050008@codeaurora.org>
Message-ID: <CAKv+Gu-Tam+QiXc_f0e+x8hNc4rxP_-59NdaCHkF9h=4Rd+XeA@mail.gmail.com>

On 18 May 2016 at 02:40, Shanker Donthineni <shankerd at codeaurora.org> wrote:
> Hi Ard,
>
> This patch causing the kernel boot fail using the UEFI firmware on
> Qualcomm Technologies QDF2XXX server platforms.
>
> +       /* RW- */
> +       if (attr & EFI_MEMORY_XP || type != EFI_RUNTIME_SERVICES_CODE)
> +               return pgprot_val(PAGE_KERNEL);
> +
>
> Changing above condition from 'or' to 'and' fixed the problem.Are we
> missing something here or intentionally implemented this logic?

The logic is sound, I think. If you need execute permissions on a
non-code region with the XP bit set, there is something wrong in the
firmware, unless you are hitting this case for an MMIO region perhaps?
Could you share the kernel log with efi=debug enabled?

> At least
> we need some pr_warn here if UEFI firmware passes EFI_RUNTIME_SEVRICE_CODE
> region that has an attribute EFI_MEMORY_XP.
>

No. DXE_RUNTIME_DRIVER modules are implemented as PE/COFF binaries,
which are covered completely by EfiRuntimeServicesCode regions.
However, a PE/COFF image consists of .text and .data sections, which
require different permissions, so PE/COFF binaries are represented by
several memory map entries in the memory attributes table, all of
which have a code type, but differ in the permission bits.

>
>
> On 03/30/2016 11:38 AM, Ard Biesheuvel wrote:
>> Recent UEFI versions expose permission attributes for runtime services
>> memory regions, either in the UEFI memory map or in the separate memory
>> attributes table. This allows the kernel to map these regions with
>> stricter permissions, rather than the RWX permissions that are used by
>> default. So wire this up in our mapping routine.
>>
>> Note that in the absence of permission attributes, we still only map
>> regions of type EFI_RUNTIME_SERVICE_CODE with the executable bit set.
>> Also, we base the mapping attributes of EFI_MEMORY_MAPPED_IO on the
>> type directly rather than on the absence of the EFI_MEMORY_WB attribute.
>> This is more correct, but is also required for compatibility with the
>> upcoming support for the Memory Attributes Table, which only carries
>> permission attributes, not memory type attributes.
>>
>> Cc: Mark Rutland <mark.rutland at arm.com>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
>> ---
>>  arch/arm64/kernel/efi.c | 54 +++++++++++++++-----
>>  1 file changed, 40 insertions(+), 14 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
>> index b6abc852f2a1..33a6da160a50 100644
>> --- a/arch/arm64/kernel/efi.c
>> +++ b/arch/arm64/kernel/efi.c
>> @@ -17,22 +17,48 @@
>>
>>  #include <asm/efi.h>
>>
>> -int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t
>> *md)
>> +/*
>> + * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
>> + * executable, everything else can be mapped with the XN bits
>> + * set. Also take the new (optional) RO/XP bits into account.
>> + */
>> +static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
>>  {
>> -     pteval_t prot_val;
>> +     u64 attr = md->attribute;
>> +     u32 type = md->type;
>>
>> -     /*
>> -      * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
>> -      * executable, everything else can be mapped with the XN bits
>> -      * set.
>> -      */
>> -     if ((md->attribute & EFI_MEMORY_WB) == 0)
>> -             prot_val = PROT_DEVICE_nGnRE;
>> -     else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
>> -              !PAGE_ALIGNED(md->phys_addr))
>> -             prot_val = pgprot_val(PAGE_KERNEL_EXEC);
>> -     else
>> -             prot_val = pgprot_val(PAGE_KERNEL);
>> +     if (type == EFI_MEMORY_MAPPED_IO)
>> +             return PROT_DEVICE_nGnRE;
>> +
>> +     if (WARN_ONCE(!PAGE_ALIGNED(md->phys_addr),
>> +                   "UEFI Runtime regions are not aligned to 64 KB --
>> buggy firmware?"))
>> +             /*
>> +              * If the region is not aligned to the page size of the
>> OS, we
>> +              * can not use strict permissions, since that would also
>> affect
>> +              * the mapping attributes of the adjacent regions.
>> +              */
>> +             return pgprot_val(PAGE_KERNEL_EXEC);
>> +
>> +     /* R-- */
>> +     if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) ==
>> +         (EFI_MEMORY_XP | EFI_MEMORY_RO))
>> +             return pgprot_val(PAGE_KERNEL_RO);
>> +
>> +     /* R-X */
>> +     if (attr & EFI_MEMORY_RO)
>> +             return pgprot_val(PAGE_KERNEL_ROX);
>> +
>> +     /* RW- */
>> +     if (attr & EFI_MEMORY_XP || type != EFI_RUNTIME_SERVICES_CODE)
>> +             return pgprot_val(PAGE_KERNEL);
>> +
>> +     /* RWX */
>> +     return pgprot_val(PAGE_KERNEL_EXEC);
>> +}
>> +
>> +int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t
>> *md)
>> +{
>> +     pteval_t prot_val = create_mapping_protection(md);
>>
>>       create_pgd_mapping(mm, md->phys_addr, md->virt_addr,
>>                          md->num_pages << EFI_PAGE_SHIFT,
>
> --
> Shanker Donthineni
> Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
>


From joel at jms.id.au  Tue May 17 23:50:58 2016
From: joel at jms.id.au (Joel Stanley)
Date: Wed, 18 May 2016 16:20:58 +0930
Subject: [PATCH v2 2/2] watchdog: Add Aspeed watchdog driver
In-Reply-To: <573799FA.7090207@roeck-us.net>
References: <1462797277-14969-1-git-send-email-joel@jms.id.au>
 <1463062631-16432-1-git-send-email-joel@jms.id.au>
 <1463062631-16432-3-git-send-email-joel@jms.id.au>
 <573799FA.7090207@roeck-us.net>
Message-ID: <CACPK8XedReKGdEjb=b0ik=wKpCOPCjqFpDGjU-WtNH-sEzzeLA@mail.gmail.com>

On Sun, May 15, 2016 at 7:04 AM, Guenter Roeck <linux at roeck-us.net> wrote:
>> +
>> +struct aspeed_wdt {
>> +       struct watchdog_device  wdd;
>> +       unsigned long           rate;
>
> I still don't see why you need this variable. Why not just use
> WDT_1MHZ_CLOCK directly ?

Yes, I can. It's left over from when the driver ran the device from pclk.

>> +static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
>> +                                 unsigned int timeout)
>> +{
>> +       wdd->timeout = timeout;
>> +
>> +       return aspeed_wdt_start(wdd);
>
> The watchdog can be stopped here (with WDIOC_SETOPTIONS/WDIOS_DISABLECARD).
> An implicit enable is not really a good idea; neither the infrastructure
> nor user space would in this case be aware that the watchdog is running.

Okay, good to know. The documentation does not mention this.

I will change it to write the value but not change the running state.

>> +}
>> +
>> +static int aspeed_wdt_restart(struct watchdog_device *wdd,
>> +                             unsigned long action, void *data)
>> +{
>> +       struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
>> +
>> +       aspeed_wdt_enable(wdt, 128 * wdt->rate / 1000);
>> +
>
>
> Is that the smallest accepted value, or is there some other reason
> not to make it smaller ?

It's what the vendor BSP was using, and it's what we've been using
since I wrote this code (which happens to be one year ago today!).

>
> It is also quite common to wait here to let the reset 'catch'
> before returning. This would ensure that the system doesn't trigger
> a lower priority reset.

Okay. I will add a mdelay(1000) here.

>> +       ret = watchdog_register_device(&wdt->wdd);
>> +       if (ret) {
>> +               dev_err(&pdev->dev, "failed to register\n");
>> +               return ret;
>> +       }
>> +
>> +       dev_info(&pdev->dev, "rate %lu, max timeout %u, timeout %d\n",
>> +                wdt->rate, wdt->wdd.max_timeout, wdt->wdd.timeout);
>> +
>
> 'rate 1000000' doesn't seem very informative. All it does is to expose
> an implementation detail which no one really cares about. Even if you
> were to add 'Hz', I would argue that no one will even understand
> what it means without looking into the driver, but then it will be
> understood without the message.

Okay. I will remove the dev_info all together.

Cheers,

Joel


From yendapally.reddy at broadcom.com  Tue May 17 23:53:59 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Wed, 18 May 2016 02:53:59 -0400
Subject: [PATCH INTERNAL v2 1/3] Documentation: dt: Add Broadcom iproc pwm
 controller binding
In-Reply-To: <1463554441-47982-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1463554441-47982-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1463554441-47982-2-git-send-email-yendapally.reddy@broadcom.com>

Add a binding for Broadcom iproc pwm controller

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
---
 .../devicetree/bindings/pwm/brcm,iproc-pwm.txt      | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt

diff --git a/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt b/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
new file mode 100644
index 0000000..21f75bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
@@ -0,0 +1,21 @@
+Broadcom iProc PWM controller device tree bindings
+
+This controller has 4 channels.
+
+Required Properties :
+- compatible: must be "brcm,iproc-pwm"
+- reg: physical base address and length of the controller's registers
+- clocks: phandle + clock specifier pair for the external clock
+- #pwm-cells: Should be 3. See pwm.txt in this directory for a
+  description of the cells format.
+
+Refer to clocks/clock-bindings.txt for generic clock consumer properties.
+
+Example:
+
+pwm: pwm at 18031000 {
+	compatible = "brcm,iproc-pwm";
+	reg = <0x18031000 0x28>;
+	clocks = <&osc>;
+	#pwm-cells = <3>;
+};
-- 
2.1.0



From yendapally.reddy at broadcom.com  Tue May 17 23:53:58 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Wed, 18 May 2016 02:53:58 -0400
Subject: [PATCH INTERNAL v2 0/3] pwm support for Broadcom iProc SoC's
Message-ID: <1463554441-47982-1-git-send-email-yendapally.reddy@broadcom.com>

This patchset contains the pwm support for the Broadcom's iProc SoC's.

The first patch provides the documentation details and the
second patch contains the controller support details. The third patch
contains the enable method for Northstar Plus SoC.

This patch series has been tested on NSP bcm958625HR board.
The pwm is not enabled for this board as the pins are open and not used.

This patch series is based on v4.6.0-rc1 and is available from github
repo: https://github.com/Broadcom/cygnus-linux.git
branch: iproc-pwm-v2

Changes since v1

Addressed the review comments from Thierry
 1. Use separate driver for iProc SoC's.

Yendapally Reddy Dhananjaya Reddy (3):
  Documentation: dt: Add Broadcom iproc pwm controller binding
  pwm: iproc: Add support for Broadcom iproc pwm controller
  ARM: dts: NSP: Add PWM Support to DT

 .../devicetree/bindings/pwm/brcm,iproc-pwm.txt     |  21 ++
 arch/arm/boot/dts/bcm-nsp.dtsi                     |   8 +
 drivers/pwm/Kconfig                                |  10 +
 drivers/pwm/Makefile                               |   1 +
 drivers/pwm/pwm-bcm-iproc.c                        | 320 +++++++++++++++++++++
 5 files changed, 360 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
 create mode 100644 drivers/pwm/pwm-bcm-iproc.c

-- 
2.1.0



From yendapally.reddy at broadcom.com  Tue May 17 23:54:00 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Wed, 18 May 2016 02:54:00 -0400
Subject: [PATCH INTERNAL v2 2/3] pwm: iproc: Add support for Broadcom iproc
 pwm controller
In-Reply-To: <1463554441-47982-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1463554441-47982-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1463554441-47982-3-git-send-email-yendapally.reddy@broadcom.com>

Add support for Broadcom iproc pwm controller

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
---
 drivers/pwm/Kconfig         |  10 ++
 drivers/pwm/Makefile        |   1 +
 drivers/pwm/pwm-bcm-iproc.c | 320 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 331 insertions(+)
 create mode 100644 drivers/pwm/pwm-bcm-iproc.c

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index c182efc..d298ebd 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -74,6 +74,16 @@ config PWM_ATMEL_TCB
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-atmel-tcb.
 
+config PWM_BCM_IPROC
+	tristate "iProc PWM support"
+	depends on ARCH_BCM_IPROC
+	help
+	  Generic PWM framework driver for Broadcom iProc PWM block. This
+	  block is used in Broadcom iProc SoC's.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-bcm-iproc.
+
 config PWM_BCM_KONA
 	tristate "Kona PWM support"
 	depends on ARCH_BCM_MOBILE
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index dd35bc1..a196d79 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_PWM_AB8500)	+= pwm-ab8500.o
 obj-$(CONFIG_PWM_ATMEL)		+= pwm-atmel.o
 obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM)	+= pwm-atmel-hlcdc.o
 obj-$(CONFIG_PWM_ATMEL_TCB)	+= pwm-atmel-tcb.o
+obj-$(CONFIG_PWM_BCM_IPROC)	+= pwm-bcm-iproc.o
 obj-$(CONFIG_PWM_BCM_KONA)	+= pwm-bcm-kona.o
 obj-$(CONFIG_PWM_BCM2835)	+= pwm-bcm2835.o
 obj-$(CONFIG_PWM_BERLIN)	+= pwm-berlin.o
diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c
new file mode 100644
index 0000000..3ba3ca5
--- /dev/null
+++ b/drivers/pwm/pwm-bcm-iproc.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+
+#define IPROC_PWM_CTRL_OFFSET			(0x00)
+#define IPROC_PWM_CTRL_TYPE_SHIFT(chan)		(15 + (chan))
+#define IPROC_PWM_CTRL_POLARITY_SHIFT(chan)	(8 + (chan))
+#define IPROC_PWM_CTRL_EN_SHIFT(chan)		(chan)
+
+#define IPROC_PWM_PERIOD_OFFSET(chan)		(0x04 + ((chan) << 3))
+#define IPROC_PWM_PERIOD_MIN			(0x02)
+#define IPROC_PWM_PERIOD_MAX			(0xffff)
+
+#define IPROC_PWM_DUTY_CYCLE_OFFSET(chan)	(0x08 + ((chan) << 3))
+#define IPROC_PWM_DUTY_CYCLE_MIN		(0x00)
+#define IPROC_PWM_DUTY_CYCLE_MAX		(0xffff)
+
+#define IPROC_PWM_PRESCALE_OFFSET		(0x24)
+#define IPROC_PWM_PRESCALE_BITS			(0x06)
+#define IPROC_PWM_PRESCALE_SHIFT(chan)		((3 - (chan)) *	\
+						IPROC_PWM_PRESCALE_BITS)
+#define IPROC_PWM_PRESCALE_MASK(chan)		(IPROC_PWM_PRESCALE_MAX << \
+						IPROC_PWM_PRESCALE_SHIFT(chan))
+#define IPROC_PWM_PRESCALE_MIN			(0x00)
+#define IPROC_PWM_PRESCALE_MAX			(0x3f)
+
+#define IPROC_PWM_CHANNEL_COUNT			(0x04)
+
+struct iproc_pwmc {
+	struct pwm_chip chip;
+	void __iomem *base;
+	struct clk *clk;
+};
+
+static inline struct iproc_pwmc *to_iproc_pwmc(struct pwm_chip *_chip)
+{
+	return container_of(_chip, struct iproc_pwmc, chip);
+}
+
+static void iproc_pwmc_unset_enable_bit(struct iproc_pwmc *ip, u32 chan)
+{
+	unsigned int value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+
+	value &= ~(1 << IPROC_PWM_CTRL_EN_SHIFT(chan));
+	writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+	/*
+	 * There must be a min 400ns delay between clearing trigger and setting
+	 * it. Failing to do this may result in no PWM signal.
+	 */
+	ndelay(400);
+}
+
+static void iproc_pwmc_set_enable_bit(struct iproc_pwmc *ip, unsigned int chan)
+{
+	unsigned int value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+
+	/* Set trigger bit to apply new settings */
+	value |= 1 << IPROC_PWM_CTRL_EN_SHIFT(chan);
+	writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+	/* Trigger bit must be held high for at least 400 ns. */
+	ndelay(400);
+}
+
+static int iproc_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm,
+			     int duty_ns, int period_ns)
+{
+	unsigned long prescale = IPROC_PWM_PRESCALE_MIN;
+	struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+	unsigned int value, chan = pwm->hwpwm;
+	unsigned long period_cnt, duty_cnt;
+	u64 val, div, rate;
+
+	rate = clk_get_rate(ip->clk);
+	if (!rate) {
+		dev_err(pwm->chip->dev, "pwm clock has no frequency\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Find period count, duty count and prescale to suit duty_ns and
+	 * period_ns. This is done according to formulas described below:
+	 *
+	 * period_ns = 10^9 * (PRESCALE + 1) * PC / PWM_CLK_RATE
+	 * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
+	 *
+	 * PC = (PWM_CLK_RATE * period_ns) / (10^9 * (PRESCALE + 1))
+	 * DC = (PWM_CLK_RATE * duty_ns) / (10^9 * (PRESCALE + 1))
+	 */
+	while (1) {
+		div = 1000000000;
+		div *= 1 + prescale;
+		val = rate * period_ns;
+		period_cnt = div64_u64(val, div);
+		val = rate * duty_ns;
+		duty_cnt = div64_u64(val, div);
+
+		if (period_cnt < IPROC_PWM_PERIOD_MIN ||
+				duty_cnt < IPROC_PWM_DUTY_CYCLE_MIN)
+			return -EINVAL;
+
+		if (period_cnt <= IPROC_PWM_PERIOD_MAX &&
+				 duty_cnt <= IPROC_PWM_DUTY_CYCLE_MAX)
+			break;
+
+		/* Otherwise, increase prescale and recalculate counts */
+		if (++prescale > IPROC_PWM_PRESCALE_MAX)
+			return -EINVAL;
+	}
+
+	/*
+	 * Don't apply settings if disabled. The period and duty cycle are
+	 * always calculated above to ensure the new values are
+	 * validated immediately instead of on enable.
+	 */
+	if (pwm_is_enabled(pwm)) {
+		iproc_pwmc_unset_enable_bit(ip, chan);
+
+		value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
+		value &= ~IPROC_PWM_PRESCALE_MASK(chan);
+		value |= prescale << IPROC_PWM_PRESCALE_SHIFT(chan);
+
+		writel(value, ip->base + IPROC_PWM_PRESCALE_OFFSET);
+		writel(period_cnt, ip->base + IPROC_PWM_PERIOD_OFFSET(chan));
+		writel(duty_cnt, ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(chan));
+
+		iproc_pwmc_set_enable_bit(ip, chan);
+	}
+
+	return 0;
+}
+
+static int iproc_pwmc_set_polarity(struct pwm_chip *chip,
+				   struct pwm_device *pwm,
+				   enum pwm_polarity polarity)
+{
+	struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+	unsigned int chan = pwm->hwpwm;
+	unsigned int value;
+	int ret;
+
+	ret = clk_prepare_enable(ip->clk);
+	if (ret < 0) {
+		dev_err(chip->dev, "failed to enable clock: %d\n", ret);
+		return ret;
+	}
+
+	iproc_pwmc_unset_enable_bit(ip, chan);
+
+	value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+	if (polarity == PWM_POLARITY_NORMAL)
+		value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(chan);
+	else
+		value &= ~(1 << IPROC_PWM_CTRL_POLARITY_SHIFT(chan));
+	writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+	iproc_pwmc_set_enable_bit(ip, chan);
+
+	clk_disable_unprepare(ip->clk);
+
+	return 0;
+}
+
+static int iproc_pwmc_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+	int ret;
+
+	ret = clk_prepare_enable(ip->clk);
+	if (ret < 0) {
+		dev_err(chip->dev, "failed to enable clock: %d\n", ret);
+		return ret;
+	}
+
+	ret = iproc_pwmc_config(chip, pwm, pwm_get_duty_cycle(pwm),
+						pwm_get_period(pwm));
+	if (ret < 0) {
+		clk_disable_unprepare(ip->clk);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void iproc_pwmc_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+	unsigned int chan = pwm->hwpwm;
+	unsigned int value;
+
+	iproc_pwmc_unset_enable_bit(ip, chan);
+
+	writel(0, ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(chan));
+	writel(0, ip->base + IPROC_PWM_PERIOD_OFFSET(chan));
+
+	/* Set prescale to 0 for this channel */
+	value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
+	value &= ~IPROC_PWM_PRESCALE_MASK(chan);
+	writel(value, ip->base + IPROC_PWM_PRESCALE_OFFSET);
+
+	iproc_pwmc_set_enable_bit(ip, chan);
+
+	clk_disable_unprepare(ip->clk);
+}
+
+static const struct pwm_ops iproc_pwm_ops = {
+	.config = iproc_pwmc_config,
+	.set_polarity = iproc_pwmc_set_polarity,
+	.enable = iproc_pwmc_enable,
+	.disable = iproc_pwmc_disable,
+	.owner = THIS_MODULE,
+};
+
+static int iproc_pwmc_probe(struct platform_device *pdev)
+{
+	struct iproc_pwmc *ip;
+	struct resource *res;
+	unsigned int value;
+	unsigned int chan;
+	int ret;
+
+	ip = devm_kzalloc(&pdev->dev, sizeof(*ip), GFP_KERNEL);
+	if (ip == NULL)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ip);
+
+	ip->chip.dev = &pdev->dev;
+	ip->chip.ops = &iproc_pwm_ops;
+	ip->chip.base = -1;
+	ip->chip.npwm = IPROC_PWM_CHANNEL_COUNT;
+	ip->chip.of_xlate = of_pwm_xlate_with_flags;
+	ip->chip.of_pwm_n_cells = 3;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ip->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ip->base))
+		return PTR_ERR(ip->base);
+
+	ip->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(ip->clk)) {
+		dev_err(&pdev->dev, "failed to get clock: %ld\n",
+			PTR_ERR(ip->clk));
+		return PTR_ERR(ip->clk);
+	}
+
+	ret = clk_prepare_enable(ip->clk);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to enable clock: %d\n", ret);
+		return ret;
+	}
+
+	/* Set full drive and normal polarity for all channels */
+	value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+	for (chan = 0; chan < ip->chip.npwm; chan++) {
+		value &= ~(1 << IPROC_PWM_CTRL_TYPE_SHIFT(chan));
+		value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(chan);
+	}
+	writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+	clk_disable_unprepare(ip->clk);
+
+	ret = pwmchip_add(&ip->chip);
+	if (ret < 0)
+		dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
+
+	return ret;
+}
+
+static int iproc_pwmc_remove(struct platform_device *pdev)
+{
+	struct iproc_pwmc *ip = platform_get_drvdata(pdev);
+	unsigned int chan;
+
+	for (chan = 0; chan < ip->chip.npwm; chan++)
+		if (pwm_is_enabled(&ip->chip.pwms[chan]))
+			clk_disable_unprepare(ip->clk);
+
+	return pwmchip_remove(&ip->chip);
+}
+
+static const struct of_device_id bcm_iproc_pwmc_dt[] = {
+	{ .compatible = "brcm,iproc-pwm" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, bcm_iproc_pwmc_dt);
+
+static struct platform_driver iproc_pwmc_driver = {
+	.driver = {
+		.name = "bcm-iproc-pwm",
+		.of_match_table = bcm_iproc_pwmc_dt,
+	},
+	.probe = iproc_pwmc_probe,
+	.remove = iproc_pwmc_remove,
+};
+module_platform_driver(iproc_pwmc_driver);
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom iProc PWM driver");
+MODULE_LICENSE("GPL v2");
-- 
2.1.0



From yendapally.reddy at broadcom.com  Tue May 17 23:54:01 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Wed, 18 May 2016 02:54:01 -0400
Subject: [PATCH INTERNAL v2 3/3] ARM: dts: NSP: Add PWM Support to DT
In-Reply-To: <1463554441-47982-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1463554441-47982-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1463554441-47982-4-git-send-email-yendapally.reddy@broadcom.com>

Add PWM support to the device tree for the Broadcom Northstar Plus SoC.

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
---
 arch/arm/boot/dts/bcm-nsp.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi
index def9e78..f9c8341 100644
--- a/arch/arm/boot/dts/bcm-nsp.dtsi
+++ b/arch/arm/boot/dts/bcm-nsp.dtsi
@@ -206,6 +206,14 @@
 			brcm,nand-has-wp;
 		};
 
+		pwm: pwm at 31000 {
+			compatible = "brcm,iproc-pwm";
+			reg = <0x31000 0x28>;
+			clocks = <&osc>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
 		ccbtimer0: timer at 34000 {
 			compatible = "arm,sp804";
 			reg = <0x34000 0x1000>;
-- 
2.1.0



From sricharan at codeaurora.org  Wed May 18 00:06:35 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Wed, 18 May 2016 12:36:35 +0530
Subject: [PATCH v2 2/2] i2c: qup: support SMBus block read
In-Reply-To: <1463006736-24652-2-git-send-email-nkaje@codeaurora.org>
References: <1463006736-24652-1-git-send-email-nkaje@codeaurora.org>
 <1463006736-24652-2-git-send-email-nkaje@codeaurora.org>
Message-ID: <000d01d1b0d3$d70e1f30$852a5d90$@codeaurora.org>

Hi,

<snip..>

> +static bool qup_i2c_check_msg_len(struct i2c_msg *msg) {
> +	return ((msg->flags & I2C_M_RD) && (msg->flags &
> I2C_M_RECV_LEN)); }
> +
> +static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev
> *qup,
> +			struct i2c_msg *msg)
> +{
> +	int len = 0;
> +	int data_len = qup_i2c_get_data_len(qup);
> +
> +	if (msg->len > 1) {
> +		tags[len++] = QUP_TAG_V2_DATARD_STOP;
> +		tags[len++] = data_len - 1;
> +	} else {
    So we hit this else part for msg->len = 1 and this case blk.pos = 0
    will always be true right ?

> +		if (qup->blk.pos == 0) {
> +			tags[len++] = QUP_TAG_V2_START;
> +			tags[len++] = addr & 0xff;
> +
> +			if (msg->flags & I2C_M_TEN)
> +				tags[len++] = addr >> 8;
> +		}
> +
> +		tags[len++] = QUP_TAG_V2_DATARD;
> +		/* 0 implies 256 bytes */
> +		if (data_len == QUP_READ_LIMIT)
> +			tags[len++] = 0;
> +		else
> +			tags[len++] = data_len;
> +	}
       Even data_len will always be '1' right ?
> +	return len;
> +}
> +
>  static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
>  			    struct i2c_msg *msg,  int is_dma)  { @@ -526,6
> +559,10 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
> 
>  	int last = (qup->blk.pos == (qup->blk.count - 1)) && (qup->is_last);
> 
> +	/* Handle tags for SMBus block read */
> +	if (qup_i2c_check_msg_len(msg))
> +		return qup_i2c_set_tags_smb(addr, tags, qup, msg);
> +
>  	if (qup->blk.pos == 0) {
>  		tags[len++] = QUP_TAG_V2_START;
>  		tags[len++] = addr & 0xff;
> @@ -1065,9 +1102,17 @@ static int qup_i2c_read_fifo_v2(struct
> qup_i2c_dev *qup,
>  				struct i2c_msg *msg)
>  {
>  	u32 val;
> -	int idx, pos = 0, ret = 0, total;
> +	int idx, pos = 0, ret = 0, total, msg_offset = 0;
> 
> +	/*
> +	 * If the message length is already read in
> +	 * the first byte of the buffer, account for
> +	 * that by setting the offset
> +	 */
> +	if (qup_i2c_check_msg_len(msg) && (msg->len > 1))
> +		msg_offset = 1;
>  	total = qup_i2c_get_data_len(qup);
> +	total -= msg_offset;
> 
>  	/* 2 extra bytes for read tags */
>  	while (pos < (total + 2)) {
> @@ -1087,8 +1132,8 @@ static int qup_i2c_read_fifo_v2(struct
> qup_i2c_dev *qup,
> 
>  			if (pos >= (total + 2))
>  				goto out;
> -
> -			msg->buf[qup->pos++] = val & 0xff;
> +			msg->buf[qup->pos+msg_offset] = val & 0xff;
	A space around '+' ?

> +			qup->pos++;
>  		}
>  	}
> 
> @@ -1128,6 +1173,22 @@ static int qup_i2c_read_one_v2(struct
> qup_i2c_dev *qup, struct i2c_msg *msg)
>  			goto err;
> 
>  		qup->blk.pos++;
> +
> +		/* Handle SMBus block read length */
> +		if (qup_i2c_check_msg_len(msg) && (msg->len == 1)) {
> +			if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
> +				ret = -EPROTO;
> +				goto err;
> +			}
> +			msg->len += msg->buf[0];
> +			qup->pos = 0;
> +			qup_i2c_set_read_mode_v2(qup, msg->len);
> +			qup_i2c_issue_xfer_v2(qup, msg);
> +			ret = qup_i2c_wait_for_complete(qup, msg);
> +			if (ret)
> +				goto err;
		Is the issue_xfer_v2 needed inside this here ? 

> +			qup_i2c_set_blk_data(qup, msg);
> +		}
>  	} while (qup->blk.pos < qup->blk.count);
   Regards,
     Sricharan



From lee.jones at linaro.org  Wed May 18 00:21:45 2016
From: lee.jones at linaro.org (Lee Jones)
Date: Wed, 18 May 2016 08:21:45 +0100
Subject: PATH[1/3] ARM: axp20x_usb_power.c add device tree configuration
 options for REG 30H: VBUS-IPSOUT
In-Reply-To: <0f58d2b3-f3d3-45a3-a307-e54df26c1ab1@googlegroups.com>
References: <0f58d2b3-f3d3-45a3-a307-e54df26c1ab1@googlegroups.com>
Message-ID: <20160518072145.GI17238@dell>

What on earth are all these emails you're sending to the list?

Please read the following documentation to ensure you're using correct
processes to send patches. If you require any help with a particular
aspect, please feel free to ask.

 Documentation/HOWTO 
 Documentation/CodingSytle
 Documentation/email-clients.txt 
 Documentation/SubmittingPatches 

The last one being the most prevalent in this case.

NB: If you use Git to create your patches `git format-patch` and to
email your patches out `git send-email`, then you'll be most of the
way there.

> The AXP20X chips have a configuration register "REG 30H: VBUS-IPSOUT Power 
> Path Management" that provide USB power supply protection.
> The current axp20x_usb_power.c provides support only for reading those 
> values.
> 
> From the datasheet:
> In order not to affect the USB communication, VBUS is always working under 
> Voltage-Limit mode by default. In this mode, AXP209 ensures that VBUS 
> voltage remains above a configurable reference voltage VHOLD which can meet 
> the USB specification. The default VHOLD is 4.4V, adjustable in Reg30H 
> [5:3] register. If the system has limit on current obtained from USB VBUS, 
> a current-limit mode is provided (See REG30H[1] register), with 
> 900mA/500mA/100mA (Reg30H [0]) selectable.
> 
> The following entries are added in the axp209.dtsi 
> file: vhold-enable, vhold-set and ibus-limit
> The chosen default values are the AXP20X reset values, as described in the 
> data sheet.
> 
> Signed-off-by: Ene Alexandru <ene.alexandru at gmail.com>
> 
> 
> ---
> diff -uprN -X linux-sunxi-original/Documentation/dontdiff 
> linux-sunxi-original/arch/arm/boot/dts/axp209.dtsi 
> linux-sunxi/arch/arm/boot/dts/axp209.dtsi
> --- linux-sunxi-original/arch/arm/boot/dts/axp209.dtsi         2016-05-11 
> 09:21:47.470923679 +0200
> +++ linux-sunxi/arch/arm/boot/dts/axp209.dtsi     2016-05-10 
> 18:45:32.795158651 +0200
> @@ -98,5 +98,8 @@
>            usb_power_supply: usb_power_supply {
>                        compatible = "x-powers,axp202-usb-power-supply";
>                        status = "disabled";
> +                      vhold-enable = <0x01>;
> +                      vhold-set = <0x04>;
> +                      ibus-limit = <0x01>;
>            };
> };
> ---
> 


-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


From cedric.madianga at gmail.com  Wed May 18 00:24:50 2016
From: cedric.madianga at gmail.com (M'boumba Cedric Madianga)
Date: Wed, 18 May 2016 09:24:50 +0200
Subject: [PATCH 2/5] i2c: Add STM32F4 I2C driver
In-Reply-To: <CALszF6A-jiCBtSO1RFDdgHKTKmsonRXFVs0x2zHha1LJ3UhwtQ@mail.gmail.com>
References: <1462980974-22091-1-git-send-email-cedric.madianga@gmail.com>
 <1462980974-22091-3-git-send-email-cedric.madianga@gmail.com>
 <CALszF6A-jiCBtSO1RFDdgHKTKmsonRXFVs0x2zHha1LJ3UhwtQ@mail.gmail.com>
Message-ID: <CAOAejn0Fsizp9fK1mNn3BBeL2LeoVgt5_zF5656La4G2uDPH7g@mail.gmail.com>

Hi Maxime,

2016-05-17 11:48 GMT+02:00 Maxime Coquelin <mcoquelin.stm32 at gmail.com>:
> Hi Cedric,
>
> 2016-05-11 17:36 GMT+02:00 M'boumba Cedric Madianga <cedric.madianga at gmail.com>:
>> This patch adds support for the STM32F4 I2C controller.
>>
>> Signed-off-by: M'boumba Cedric Madianga <cedric.madianga at gmail.com>
>> ---
>>  drivers/i2c/busses/Kconfig       |  10 +
>>  drivers/i2c/busses/Makefile      |   1 +
>>  drivers/i2c/busses/i2c-stm32f4.c | 872 +++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 883 insertions(+)
>>  create mode 100644 drivers/i2c/busses/i2c-stm32f4.c
>>
> ...
>> diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c
>> new file mode 100644
>> index 0000000..4692213
>> --- /dev/null
>> +++ b/drivers/i2c/busses/i2c-stm32f4.c
> ...
>> +enum stm32f4_i2c_speed {
>> +       STM32F4_I2C_SPEED_STANDARD, /* 100 kHz */
>> +       STM32F4_I2C_SPEED_FAST, /* 400 kHz */
>> +       STM32F4_I2C_SPEED_END,
>> +};
>> +
>> +/**
>> + * struct stm32f4_i2c_timings - per-Mode tuning parameters
>> + * @rate: I2C bus rate
>> + * @duty: Fast mode duty cycle
>> + */
>> +struct stm32f4_i2c_timings {
>> +       u32 rate;
>> +       u32 duty;
>> +};
> ...
>> +/**
>> + * struct stm32f4_i2c_dev - private data of the controller
>> + * @adap: I2C adapter for this controller
>> + * @dev: device for this controller
>> + * @base: virtual memory area
>> + * @complete: completion of I2C message
>> + * @irq_event: interrupt event line for the controller
>> + * @irq_error: interrupt error line for the controller
>> + * @clk: hw i2c clock
>> + * speed: I2C clock frequency of the controller. Standard or Fast only supported
>> + * @client: I2C transfer information
>> + * @busy: I2C transfer on-going
>> + * @rst: I2C reset line
>> + */
>> +struct stm32f4_i2c_dev {
>> +       struct i2c_adapter              adap;
>> +       struct device                   *dev;
>> +       void __iomem                    *base;
>> +       struct completion               complete;
>> +       int                             irq_event;
>> +       int                             irq_error;
>> +       struct clk                      *clk;
>> +       int                             speed;
>> +       struct stm32f4_i2c_client       client;
>> +       bool                            busy;
>> +       struct reset_control            *rst;
>> +};
>> +
>> +static struct stm32f4_i2c_timings i2c_timings[] = {
>> +       [STM32F4_I2C_SPEED_STANDARD] = {
>> +               .rate                   = 100000,
>> +               .duty                   = 0,
>> +       },
>> +       [STM32F4_I2C_SPEED_FAST] = {
>> +               .rate                   = 400000,
>> +               .duty                   = 0,
>> +       },
>> +};
> Is this table really needed?
> As duty value seems to always be 0, couldn't you just store the rate
> in the speed field?
You are right. I will directly use speed field in the V2

>
>
>> +static void stm32f4_i2c_set_rise_time(struct stm32f4_i2c_dev *i2c_dev)
>> +{
>> +       u32 trise, freq, cr2;
>> +
>> +       cr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
>> +       freq = cr2 & STM32F4_I2C_CR2_FREQ_MASK;
>> +
>> +       trise = readl_relaxed(i2c_dev->base + STM32F4_I2C_TRISE);
>> +       trise &= ~STM32F4_I2C_TRISE_TRISE_MASK;
>> +
>> +       if (i2c_dev->speed == STM32F4_I2C_SPEED_STANDARD)
>> +               trise |= STM32F4_I2C_TRISE_TRISE((freq + 1));
>> +       else
>> +               trise |= STM32F4_I2C_TRISE_TRISE((((freq * 300) / 1000) + 1));
> Or if you keep the timings struct, maybe the rise time should be part of it.
> Doing, that, you will avoid the if/else
As timings struct will be removed, I will keep this piece of code but
thanks for this remark.

>
>> +
>> +       writel_relaxed(trise, i2c_dev->base + STM32F4_I2C_TRISE);
>> +}
>> +
>> +static void stm32f4_i2c_set_speed_mode(struct stm32f4_i2c_dev *i2c_dev)
>> +{
>> +       struct stm32f4_i2c_timings *t = &i2c_timings[i2c_dev->speed];
>> +       u32 ccr, val, clk_rate;
>> +
>> +       ccr = readl_relaxed(i2c_dev->base + STM32F4_I2C_CCR);
>> +       ccr &= ~(STM32F4_I2C_CCR_FS | STM32F4_I2C_CCR_DUTY |
>> +                STM32F4_I2C_CCR_CCR_MASK);
>> +
>> +       clk_rate = clk_get_rate(i2c_dev->clk);
>> +
>> +       switch (i2c_dev->speed) {
>> +       case STM32F4_I2C_SPEED_STANDARD:
>> +               val = clk_rate / t->rate * 2;
>> +               if (val < STM32F4_I2C_MIN_CCR)
>> +                       ccr |= STM32F4_I2C_CCR_CCR(STM32F4_I2C_MIN_CCR);
>> +               else
>> +                       ccr |= STM32F4_I2C_CCR_CCR(val);
>> +               break;
>> +       case STM32F4_I2C_SPEED_FAST:
>> +               ccr |= STM32F4_I2C_CCR_FS;
>> +               if (t->duty) {
>> +                       ccr |= STM32F4_I2C_CCR_DUTY;
>> +                       ccr |= STM32F4_I2C_CCR_CCR(clk_rate / t->rate * 25);
>> +               } else {
>> +                       ccr |= STM32F4_I2C_CCR_CCR(clk_rate / t->rate * 3);
>> +               }
> Is it really useful since duty seems to always be 0?
Agree, I will rework it by directly set duty at 0 in the register.

>
>> +               break;
>> +       default:
>> +               dev_err(i2c_dev->dev, "I2C speed mode not supported\n");
>> +       }
>> +
>> +       writel_relaxed(ccr, i2c_dev->base + STM32F4_I2C_CCR);
>> +}
>> +
>> +static void stm32f4_i2c_set_filter(struct stm32f4_i2c_dev *i2c_dev)
>> +{
>> +       u32 filter;
>> +
>> +       /* Enable analog noise filter and disable digital noise filter */
> Maybe a stupid question, but is it always what we want?
> Are there some cases we would prefer to use the digital noise filter
> instead of the analog one?
I don't have any use case where the digital noise filter is used.
So as I cannot test it, I prefer to only use the default filter (analog)

>
>> +       filter = readl_relaxed(i2c_dev->base + STM32F4_I2C_FLTR);
>> +       filter &= ~(STM32F4_I2C_FLTR_ANOFF | STM32F4_I2C_FLTR_DNF_MASK);
>> +       writel_relaxed(filter, i2c_dev->base + STM32F4_I2C_FLTR);
>> +}
>> +
>> +/**
>> + * stm32f4_i2c_hw_config() - Prepare I2C block
>> + * @i2c_dev: Controller's private data
>> + */
>> +static void stm32f4_i2c_hw_config(struct stm32f4_i2c_dev *i2c_dev)
>> +{
>> +       void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
>> +
>> +       /* Disable I2C */
>> +       stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_PE);
>> +
>> +       stm32f4_i2c_set_periph_clk_freq(i2c_dev);
>> +
>> +       stm32f4_i2c_set_rise_time(i2c_dev);
>> +
>> +       stm32f4_i2c_set_speed_mode(i2c_dev);
>> +
>> +       stm32f4_i2c_set_filter(i2c_dev);
>> +
>> +       /* Enable I2C */
>> +       stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_PE);
>> +}
>> +
>> +static int stm32f4_i2c_wait_free_bus(struct stm32f4_i2c_dev *i2c_dev)
>> +{
>> +       u32 status;
>> +       int ret;
>> +
>> +       ret = readl_relaxed_poll_timeout(i2c_dev->base + STM32F4_I2C_SR2,
>> +                                        status,
>> +                                        !(status & STM32F4_I2C_SR2_BUSY),
>> +                                        10, 1000);
>> +       if (ret) {
>> +               dev_err(i2c_dev->dev, "bus not free\n");
>> +               ret = -EBUSY;
>> +       }
>> +
>> +       return ret;
>> +}
>> +
>> +/**
>> + * stm32f4_i2c_write_ byte() - Write a byte in the data register
>> + * @i2c_dev: Controller's private data
>> + * @byte: Data to write in the register
>> + */
>> +static void stm32f4_i2c_write_byte(struct stm32f4_i2c_dev *i2c_dev, u8 byte)
>> +{
>> +       writel_relaxed(byte, i2c_dev->base + STM32F4_I2C_DR);
>> +}
>> +
>> +/**
>> + * stm32f4_i2c_write_msg() - Fill the data register in write mode
>> + * @i2c_dev: Controller's private data
>> + *
>> + * This function fills the data register with I2C transfer buffer
>> + */
>> +static void stm32f4_i2c_write_msg(struct stm32f4_i2c_dev *i2c_dev)
>> +{
>> +       struct stm32f4_i2c_client *c = &i2c_dev->client;
>> +
>> +       stm32f4_i2c_write_byte(i2c_dev, *c->buf++);
>> +       c->count--;
>> +}
>> +
>> +static void stm32f4_i2c_read_msg(struct stm32f4_i2c_dev *i2c_dev)
>> +{
>> +       struct stm32f4_i2c_client *c = &i2c_dev->client;
>> +       u32 rbuf;
>> +
>> +       rbuf = readl_relaxed(i2c_dev->base + STM32F4_I2C_DR);
>> +       *c->buf++ = (u8)rbuf & 0xff;
>> +       c->count--;
>> +}
>> +
>> +static void stm32f4_i2c_terminate_xfer(struct stm32f4_i2c_dev *i2c_dev)
>> +{
>> +       struct stm32f4_i2c_client *c = &i2c_dev->client;
>> +       void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
>> +
>> +       /* Disable all interrupts */
>> +       stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_IRQ_MASK);
>> +
>> +       /* Set STOP or REPSTART */
>> +       reg = i2c_dev->base + STM32F4_I2C_CR1;
>> +       if (c->stop)
>> +               stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
>> +       else
>> +               stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
>> +
>> +       complete(&i2c_dev->complete);
>> +}
>> +
>> +/**
>> + * stm32f4_i2c_handle_write() - Handle FIFO empty interrupt in case of write
>> + * @i2c_dev: Controller's private data
>> + */
>> +static void stm32f4_i2c_handle_write(struct stm32f4_i2c_dev *i2c_dev)
>> +{
>> +       struct stm32f4_i2c_client *c = &i2c_dev->client;
>> +       void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
>> +
>> +       if (c->count) {
>> +               stm32f4_i2c_write_msg(i2c_dev);
>> +               if (!c->count) {
>> +                       /* Disable BUF interrupt */
>> +                       stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
>> +               }
>> +       } else {
>> +               stm32f4_i2c_terminate_xfer(i2c_dev);
>> +       }
>> +}
>> +
>> +/**
>> + * stm32f4_i2c_handle_tx_btf() - Handle byte transfer finished interrupt
>> + * in case of write
>> + * @i2c_dev: Controller's private data
>> + */
>> +static void stm32f4_i2c_handle_tx_btf(struct stm32f4_i2c_dev *i2c_dev)
>> +{
>> +       struct stm32f4_i2c_client *c = &i2c_dev->client;
>> +
>> +       if (c->count)
>> +               stm32f4_i2c_write_msg(i2c_dev);
>> +       else
>> +               stm32f4_i2c_terminate_xfer(i2c_dev);
>> +}
> The two functions above look very similar.
> Isn't there a way to factorize?
Good point. Thanks. I will do it in the V2.
>
>> +
>> +/**
>> + * stm32f4_i2c_handle_read() - Handle FIFO enmpty interrupt in case of read
> s/enmpty/empty/
OK

>
>
> ...
>> +
>> +/**
>> + * stm32f4_i2c_xfer() - Transfer combined I2C message
>> + * @i2c_adap: Adapter pointer to the controller
>> + * @msgs: Pointer to data to be written.
>> + * @num: Number of messages to be executed
>> + */
>> +static int stm32f4_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
>> +                           int num)
>> +{
>> +       struct stm32f4_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
>> +       int ret, i;
>> +
>> +       i2c_dev->busy = true;
>> +
>> +       ret = clk_prepare_enable(i2c_dev->clk);
>> +       if (ret) {
>> +               dev_err(i2c_dev->dev, "Failed to prepare_enable clock\n");
>> +               return ret;
>> +       }
>> +
>> +       stm32f4_i2c_hw_config(i2c_dev);
> Maybe you could call this only at probe and resume time?
> You would save some register accesses.
Yes of course, I have put this here for test purpose as I wanted to
switch between Standard to Fast mode without compile a new DT and
rebooting the board.
But thanks to device tree overlay, I could easily do it and now I
don't have any reason to set hw config for each transfer.
I will fix it in V2.

>
>> +
>> +       for (i = 0; i < num && !ret; i++)
>> +               ret = stm32f4_i2c_xfer_msg(i2c_dev, &msgs[i], i == 0,
>> +                                          i == num - 1);
>> +
>> +       clk_disable_unprepare(i2c_dev->clk);
>> +
>> +       i2c_dev->busy = false;
>> +
>> +       return (ret < 0) ? ret : i;
>> +}
>> +
>
> Thanks!
> Maxime

 Thanks for your review
Cedric


From shawn.lin at rock-chips.com  Wed May 18 00:25:12 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Wed, 18 May 2016 15:25:12 +0800
Subject: [PATCH 1/2] Revert "clk: rockchip: reset init state before mmc
 card initialization"
In-Reply-To: <1463076197-15900-1-git-send-email-dianders@chromium.org>
References: <1463076197-15900-1-git-send-email-dianders@chromium.org>
Message-ID: <573C18D8.5050508@rock-chips.com>

On 2016-5-13 2:03, Douglas Anderson wrote:
> This reverts commit 7a03fe6f48f3 ("clk: rockchip: reset init state
> before mmc card initialization").
>
> Though not totally obvious from the commit message nor from the source
> code, that commit appears to be trying to reset the "_drv" MMC clocks to
> 90 degrees (note that the "_sample" MMC clocks have a shift of 0 so are
> not touched).
>
> The major problem here is that it doesn't properly reset things.  The
> phase is a two bit field and the commit only touches one of the two
> bits.  Thus the commit had the following affect:
> - phase   0  => phase  90
> - phase  90  => phase  90
> - phase 180  => phase 270
> - phase 270  => phase 270
>
> Things get even weirder if you happen to have a bootloader that was
> actually using delay elements (should be no reason to, but you never
> know), since those are additional bits that weren't touched by the
> original patch.
>
> This is unlikely to be what we actually want.  Checking on rk3288-veyron
> devices, I can see that the bootloader leaves these clocks as:
> - emmc:  phase 180
> - sdmmc: phase 90
> - sdio0: phase 90
>
> Thus on rk3288-veyron devices the commit we're reverting had the effect
> of changing the eMMC clock to phase 270.  This probably explains the
> scattered reports I've heard of eMMC devices not working on some veyron
> devices when using the upstream kernel.
>
> The original commit was presumably made because previously the kernel
> didn't touch the "_drv" phase at all and relied on whatever value was
> there when the kernel started.  If someone was using a bootloader that
> touched the "_drv" phase then, indeed, we should have code in the kernel
> to fix that.  ...and also, to get ideal timings, we should also have the
> kernel change the phase depending on the speed mode.  In fact, that's
> the subject of a recent patch I posted at
> <https://patchwork.kernel.org/patch/9075141/>.
>
> Ideally, we should take both the patch posted to dw_mmc and this
> revert.  Since those will likely go through different trees, here I
> describe behavior with the combos:
>
> 1. Just this revert: likely will fix rk3288-veyron eMMC on some devices
>     + other cases; might break someone with a strange bootloader that
>     sets the phase to 0 or one that uses delay elements (pretty
>     unpredicable what would happen in that case).
> 2. Just dw_mmc patch: fixes everyone.  Effectly the dw_mmc patch will
>     totally override the broken patch and fix everything.
> 3. Both patches: fixes everyone.  Once dw_mmc is initting properly then
>     any defaults from the clock code doesn't mattery.
>
> Fixes: 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card initialization")
> Signed-off-by: Douglas Anderson <dianders at chromium.org>

Thanks for this fix.

Reviewed-by: Shawn Lin <shawn.lin at rock-chips.com>

> ---
>   drivers/clk/rockchip/clk-mmc-phase.c | 11 -----------
>   1 file changed, 11 deletions(-)
>
> diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
> index bc856f21f6b2..5b18265c2306 100644
> --- a/drivers/clk/rockchip/clk-mmc-phase.c
> +++ b/drivers/clk/rockchip/clk-mmc-phase.c
> @@ -41,8 +41,6 @@ static unsigned long rockchip_mmc_recalc(struct clk_hw *hw,
>   #define ROCKCHIP_MMC_DEGREE_MASK 0x3
>   #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
>   #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
> -#define ROCKCHIP_MMC_INIT_STATE_RESET 0x1
> -#define ROCKCHIP_MMC_INIT_STATE_SHIFT 1
>
>   #define PSECS_PER_SEC 1000000000000LL
>
> @@ -162,15 +160,6 @@ struct clk *rockchip_clk_register_mmc(const char *name,
>   	mmc_clock->reg = reg;
>   	mmc_clock->shift = shift;
>
> -	/*
> -	 * Assert init_state to soft reset the CLKGEN
> -	 * for mmc tuning phase and degree
> -	 */
> -	if (mmc_clock->shift == ROCKCHIP_MMC_INIT_STATE_SHIFT)
> -		writel(HIWORD_UPDATE(ROCKCHIP_MMC_INIT_STATE_RESET,
> -				     ROCKCHIP_MMC_INIT_STATE_RESET,
> -				     mmc_clock->shift), mmc_clock->reg);
> -
>   	clk = clk_register(NULL, &mmc_clock->hw);
>   	if (IS_ERR(clk))
>   		kfree(mmc_clock);
>



From appana.durga.rao at xilinx.com  Wed May 18 00:46:43 2016
From: appana.durga.rao at xilinx.com (Appana Durga Kedareswara Rao)
Date: Wed, 18 May 2016 07:46:43 +0000
Subject: [PATCH] dmaengine: vdma: Add support for cyclic dma mode
In-Reply-To: <1463221231-30374-1-git-send-email-appanad@xilinx.com>
References: <1463221231-30374-1-git-send-email-appanad@xilinx.com>
Message-ID: <C246CAC1457055469EF09E3A7AC4E11A4A5968D1@XAP-PVEXMBX01.xlnx.xilinx.com>

>  };
> 
> @@ -474,6 +481,7 @@ xilinx_vdma_alloc_tx_segment(struct xilinx_dma_chan
> *chan)
>  	if (!segment)
>  		return NULL;
> 
> +	memset(segment, 0, sizeof(*segment));

Unrelated change will fix in v2...

>  	segment->phys = phys;
> 
>  	return segment;


From appana.durga.rao at xilinx.com  Wed May 18 00:47:31 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Wed, 18 May 2016 13:17:31 +0530
Subject: [PATCH v2 2/4] dmaengine: vdma: Use dma_pool_zalloc
In-Reply-To: <1463557653-1687-1-git-send-email-appanad@xilinx.com>
References: <1463557653-1687-1-git-send-email-appanad@xilinx.com>
Message-ID: <1463557653-1687-3-git-send-email-appanad@xilinx.com>

dma_pool_zalloc combines dma_pool_alloc and memset 0
this patch updates the driver to use dma_pool_zalloc.

Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
Changes for v2:
--> New patch.

 drivers/dma/xilinx/xilinx_vdma.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
index 3edd454..0f5b38a 100644
--- a/drivers/dma/xilinx/xilinx_vdma.c
+++ b/drivers/dma/xilinx/xilinx_vdma.c
@@ -498,11 +498,10 @@ xilinx_cdma_alloc_tx_segment(struct xilinx_dma_chan *chan)
 	struct xilinx_cdma_tx_segment *segment;
 	dma_addr_t phys;
 
-	segment = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &phys);
+	segment = dma_pool_zalloc(chan->desc_pool, GFP_ATOMIC, &phys);
 	if (!segment)
 		return NULL;
 
-	memset(segment, 0, sizeof(*segment));
 	segment->phys = phys;
 
 	return segment;
@@ -520,11 +519,10 @@ xilinx_axidma_alloc_tx_segment(struct xilinx_dma_chan *chan)
 	struct xilinx_axidma_tx_segment *segment;
 	dma_addr_t phys;
 
-	segment = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &phys);
+	segment = dma_pool_zalloc(chan->desc_pool, GFP_ATOMIC, &phys);
 	if (!segment)
 		return NULL;
 
-	memset(segment, 0, sizeof(*segment));
 	segment->phys = phys;
 
 	return segment;
-- 
2.1.2



From appana.durga.rao at xilinx.com  Wed May 18 00:47:32 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Wed, 18 May 2016 13:17:32 +0530
Subject: [PATCH v2 3/4] dmaengine: vdma: Add 64 bit addressing support for the
 axi dma
In-Reply-To: <1463557653-1687-1-git-send-email-appanad@xilinx.com>
References: <1463557653-1687-1-git-send-email-appanad@xilinx.com>
Message-ID: <1463557653-1687-4-git-send-email-appanad@xilinx.com>

The AXI DMA is a soft ip, which can be programmed to support
32 bit addressing or greater than 32 bit addressing.

When the AXI DMA ip is configured for 32 bit address space
in simple dma mode the buffer address is specified by a single register
(18h for MM2S channel and 48h for S2MM channel). When configured in SG mode
The current descriptor and tail descriptor are specified by a single
Register(08h for curdesc 10h for tail desc for MM2S channel and 38h for
Curdesc and 40h for tail desc for S2MM).

When the  AXI DMA core is configured for an address space greater
than 32 then each buffer address or descriptor address is specified by
a combination of two registers.

The first register specifies the LSB 32 bits of address,
while the next register specifies the MSB 32 bits of address.

For example, 48h will specify the LSB 32 bits while 4Ch will
specify the MSB 32 bits of the first start address.
So we need to program two registers at a time.

This patch adds the 64 bit addressing support for the axidma
IP in the driver.

Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
Changes for v2:
--> New patch.

 drivers/dma/xilinx/xilinx_vdma.c | 79 ++++++++++++++++++++++++++++++----------
 1 file changed, 60 insertions(+), 19 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
index 0f5b38a..9c15451 100644
--- a/drivers/dma/xilinx/xilinx_vdma.c
+++ b/drivers/dma/xilinx/xilinx_vdma.c
@@ -45,6 +45,7 @@
 #include <linux/of_irq.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
 
 #include "../dmaengine.h"
 
@@ -195,22 +196,22 @@ struct xilinx_vdma_desc_hw {
 /**
  * struct xilinx_axidma_desc_hw - Hardware Descriptor for AXI DMA
  * @next_desc: Next Descriptor Pointer @0x00
- * @pad1: Reserved @0x04
+ * @next_desc_msb: MSB of Next Descriptor Pointer @0x04
  * @buf_addr: Buffer address @0x08
- * @pad2: Reserved @0x0C
- * @pad3: Reserved @0x10
- * @pad4: Reserved @0x14
+ * @buf_addr_msb: MSB of Buffer address @0x0C
+ * @pad1: Reserved @0x10
+ * @pad2: Reserved @0x14
  * @control: Control field @0x18
  * @status: Status field @0x1C
  * @app: APP Fields @0x20 - 0x30
  */
 struct xilinx_axidma_desc_hw {
 	u32 next_desc;
-	u32 pad1;
+	u32 next_desc_msb;
 	u32 buf_addr;
+	u32 buf_addr_msb;
+	u32 pad1;
 	u32 pad2;
-	u32 pad3;
-	u32 pad4;
 	u32 control;
 	u32 status;
 	u32 app[XILINX_DMA_NUM_APP_WORDS];
@@ -461,6 +462,11 @@ static inline void vdma_desc_write_64(struct xilinx_dma_chan *chan, u32 reg,
 	writel(value_msb, chan->xdev->regs + chan->desc_offset + reg + 4);
 }
 
+static inline void dma_writeq(struct xilinx_dma_chan *chan, u32 reg, u64 value)
+{
+	lo_hi_writeq(value, chan->xdev->regs + chan->ctrl_offset + reg);
+}
+
 /* -----------------------------------------------------------------------------
  * Descriptors and segments alloc and free
  */
@@ -1189,9 +1195,14 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
 		dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
 	}
 
-	if (chan->has_sg)
-		dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
-			       head_desc->async_tx.phys);
+	if (chan->has_sg) {
+		if (chan->ext_addr)
+			dma_writeq(chan, XILINX_DMA_REG_CURDESC,
+				   head_desc->async_tx.phys);
+		else
+			dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
+				       head_desc->async_tx.phys);
+	}
 
 	xilinx_dma_start(chan);
 
@@ -1200,12 +1211,21 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
 
 	/* Start the transfer */
 	if (chan->has_sg) {
-		if (chan->cyclic)
-			dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
-				       chan->cyclic_seg_v->phys);
-		else
-			dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
-				       tail_segment->phys);
+		if (chan->cyclic) {
+			if (chan->ext_addr)
+				dma_writeq(chan, XILINX_DMA_REG_TAILDESC,
+					   chan->cyclic_seg_v->phys);
+			else
+				dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
+					       chan->cyclic_seg_v->phys);
+		} else {
+			if (chan->ext_addr)
+				dma_writeq(chan, XILINX_DMA_REG_TAILDESC,
+					   tail_segment->phys);
+			else
+				dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
+					       tail_segment->phys);
+		}
 	} else {
 		struct xilinx_axidma_tx_segment *segment;
 		struct xilinx_axidma_desc_hw *hw;
@@ -1215,7 +1235,12 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
 					   node);
 		hw = &segment->hw;
 
-		dma_ctrl_write(chan, XILINX_DMA_REG_SRCDSTADDR, hw->buf_addr);
+		if (chan->ext_addr)
+			dma_writeq(chan, XILINX_DMA_REG_SRCDSTADDR,
+				   hw->buf_addr);
+		else
+			dma_ctrl_write(chan, XILINX_DMA_REG_SRCDSTADDR,
+				       hw->buf_addr);
 
 		/* Start the transfer */
 		dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
@@ -1679,7 +1704,15 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg(
 			hw = &segment->hw;
 
 			/* Fill in the descriptor */
-			hw->buf_addr = sg_dma_address(sg) + sg_used;
+			if (chan->ext_addr) {
+				hw->buf_addr = lower_32_bits(sg_dma_address(sg)
+					       + sg_used);
+				hw->buf_addr_msb =
+						upper_32_bits(sg_dma_address(sg)
+						+ sg_used);
+			} else {
+				hw->buf_addr = sg_dma_address(sg) + sg_used;
+			}
 
 			hw->control = copy;
 
@@ -1777,7 +1810,15 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_dma_cyclic(
 			copy = min_t(size_t, period_len - sg_used,
 				     XILINX_DMA_MAX_TRANS_LEN);
 			hw = &segment->hw;
-			hw->buf_addr = buf_addr + sg_used + (period_len * i);
+			if (chan->ext_addr) {
+				hw->buf_addr = lower_32_bits(buf_addr +
+						sg_used + (period_len * i));
+				hw->buf_addr_msb = upper_32_bits(buf_addr +
+						sg_used + (period_len * i));
+			} else {
+				hw->buf_addr = buf_addr + sg_used +
+					       (period_len * i);
+			}
 			hw->control = copy;
 
 			if (prev)
-- 
2.1.2



From appana.durga.rao at xilinx.com  Wed May 18 00:47:29 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Wed, 18 May 2016 13:17:29 +0530
Subject: [PATCH v2 0/4] dmaengine: vdma: AXI DMA's enhancments
Message-ID: <1463557653-1687-1-git-send-email-appanad@xilinx.com>

This patch series does the following
---> Add support for cyclic DMA mode for the AXI DMA IP.
---> use dma_poll_zalloc instead of dma_pool_alloc.
---> Add 64-bit addressing support for AXI DMA IP.
---> Add 64-bit addressing support for AXI CDMA IP.

Kedareswara rao Appana (4):
  dmaengine: vdma: Add support for cyclic dma mode
  dmaengine: vdma: Use dma_pool_zalloc
  dmaengine: vdma: Add 64 bit addressing support for the axi dma
  dmaengine: vdma: Add 64 bit addressing support for the axi cdma

 drivers/dma/xilinx/xilinx_vdma.c | 293 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 260 insertions(+), 33 deletions(-)

-- 
2.1.2



From appana.durga.rao at xilinx.com  Wed May 18 00:47:33 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Wed, 18 May 2016 13:17:33 +0530
Subject: [PATCH v2 4/4] dmaengine: vdma: Add 64 bit addressing support for the
 axi cdma
In-Reply-To: <1463557653-1687-1-git-send-email-appanad@xilinx.com>
References: <1463557653-1687-1-git-send-email-appanad@xilinx.com>
Message-ID: <1463557653-1687-5-git-send-email-appanad@xilinx.com>

The AXI CDMA is a soft ip, which can be programmed to support
32 bit addressing or greater than 32 bit addressing.

When the AXI CDMA ip is configured for 32 bit address space
in simple dma mode the source/destination buffer address is
specified by a single register(18h for Source buffer address and
20h for Destination buffer address). When configured in SG mode
the current descriptor and tail descriptor are specified by a
Single register(08h for curdesc 10h for tail desc).

When the  AXI CDMA core is configured for an address space greater
than 32 then each buffer address or descriptor address is specified by
a combination of two registers.

The first register specifies the LSB 32 bits of address,
while the next register specifies the MSB 32 bits of address.

For example, 08h will specify the LSB 32 bits while 0Ch will
specify the MSB 32 bits of the first start address.
So we need to program two registers at a time.

This patch adds the 64 bit addressing support to the axicdma
IP in the driver.

Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
Changes for v2:
--> New patch.

 drivers/dma/xilinx/xilinx_vdma.c | 44 +++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
index 9c15451..18360ff 100644
--- a/drivers/dma/xilinx/xilinx_vdma.c
+++ b/drivers/dma/xilinx/xilinx_vdma.c
@@ -220,21 +220,21 @@ struct xilinx_axidma_desc_hw {
 /**
  * struct xilinx_cdma_desc_hw - Hardware Descriptor
  * @next_desc: Next Descriptor Pointer @0x00
- * @pad1: Reserved @0x04
+ * @next_descmsb: Next Descriptor Pointer MSB @0x04
  * @src_addr: Source address @0x08
- * @pad2: Reserved @0x0C
+ * @src_addrmsb: Source address MSB @0x0C
  * @dest_addr: Destination address @0x10
- * @pad3: Reserved @0x14
+ * @dest_addrmsb: Destination address MSB @0x14
  * @control: Control field @0x18
  * @status: Status field @0x1C
  */
 struct xilinx_cdma_desc_hw {
 	u32 next_desc;
-	u32 pad1;
+	u32 next_desc_msb;
 	u32 src_addr;
-	u32 pad2;
+	u32 src_addr_msb;
 	u32 dest_addr;
-	u32 pad3;
+	u32 dest_addr_msb;
 	u32 control;
 	u32 status;
 } __aligned(64);
@@ -1114,12 +1114,20 @@ static void xilinx_cdma_start_transfer(struct xilinx_dma_chan *chan)
 	}
 
 	if (chan->has_sg) {
-		dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
-			   head_desc->async_tx.phys);
+		if (chan->ext_addr)
+			dma_writeq(chan, XILINX_DMA_REG_CURDESC,
+				   head_desc->async_tx.phys);
+		else
+			dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
+				       head_desc->async_tx.phys);
 
 		/* Update tail ptr register which will start the transfer */
-		dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
-			       tail_segment->phys);
+		if (chan->ext_addr)
+			dma_writeq(chan, XILINX_DMA_REG_TAILDESC,
+				   tail_segment->phys);
+		else
+			dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
+				       tail_segment->phys);
 	} else {
 		/* In simple mode */
 		struct xilinx_cdma_tx_segment *segment;
@@ -1131,8 +1139,16 @@ static void xilinx_cdma_start_transfer(struct xilinx_dma_chan *chan)
 
 		hw = &segment->hw;
 
-		dma_ctrl_write(chan, XILINX_CDMA_REG_SRCADDR, hw->src_addr);
-		dma_ctrl_write(chan, XILINX_CDMA_REG_DSTADDR, hw->dest_addr);
+		if (chan->ext_addr) {
+			dma_writeq(chan, XILINX_CDMA_REG_SRCADDR, hw->src_addr);
+			dma_writeq(chan, XILINX_CDMA_REG_DSTADDR,
+				   hw->dest_addr);
+		} else {
+			dma_ctrl_write(chan, XILINX_CDMA_REG_SRCADDR,
+				       hw->src_addr);
+			dma_ctrl_write(chan, XILINX_CDMA_REG_DSTADDR,
+				       hw->dest_addr);
+		}
 
 		/* Start the transfer */
 		dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
@@ -1622,6 +1638,10 @@ xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst,
 	hw->control = len;
 	hw->src_addr = dma_src;
 	hw->dest_addr = dma_dst;
+	if (chan->ext_addr) {
+		hw->src_addr_msb = upper_32_bits(dma_src);
+		hw->dest_addr_msb = upper_32_bits(dma_dst);
+	}
 
 	/* Fill the previous next descriptor with current */
 	prev = list_last_entry(&desc->segments,
-- 
2.1.2



From appana.durga.rao at xilinx.com  Wed May 18 00:47:30 2016
From: appana.durga.rao at xilinx.com (Kedareswara rao Appana)
Date: Wed, 18 May 2016 13:17:30 +0530
Subject: [PATCH v2 1/4] dmaengine: vdma: Add support for cyclic dma mode
In-Reply-To: <1463557653-1687-1-git-send-email-appanad@xilinx.com>
References: <1463557653-1687-1-git-send-email-appanad@xilinx.com>
Message-ID: <1463557653-1687-2-git-send-email-appanad@xilinx.com>

This patch adds support for AXI DMA cyclic dma mode.
In cyclic mode, DMA fetches and processes the same
BDs without interruption. The DMA continues to fetch and process
until it is stopped or reset.

Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
---
Changes for v2:
---> Removed unnecessary memset() call.

 drivers/dma/xilinx/xilinx_vdma.c | 178 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 173 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_vdma.c b/drivers/dma/xilinx/xilinx_vdma.c
index df91185..3edd454 100644
--- a/drivers/dma/xilinx/xilinx_vdma.c
+++ b/drivers/dma/xilinx/xilinx_vdma.c
@@ -157,6 +157,7 @@
 /* AXI DMA Specific Masks/Bit fields */
 #define XILINX_DMA_MAX_TRANS_LEN	GENMASK(22, 0)
 #define XILINX_DMA_CR_COALESCE_MAX	GENMASK(23, 16)
+#define XILINX_DMA_CR_CYCLIC_BD_EN_MASK	BIT(4)
 #define XILINX_DMA_CR_COALESCE_SHIFT	16
 #define XILINX_DMA_BD_SOP		BIT(27)
 #define XILINX_DMA_BD_EOP		BIT(26)
@@ -278,11 +279,13 @@ struct xilinx_cdma_tx_segment {
  * @async_tx: Async transaction descriptor
  * @segments: TX segments list
  * @node: Node in the channel descriptors list
+ * @cyclic: Check for cyclic transfers.
  */
 struct xilinx_dma_tx_descriptor {
 	struct dma_async_tx_descriptor async_tx;
 	struct list_head segments;
 	struct list_head node;
+	bool cyclic;
 };
 
 /**
@@ -302,6 +305,7 @@ struct xilinx_dma_tx_descriptor {
  * @direction: Transfer direction
  * @num_frms: Number of frames
  * @has_sg: Support scatter transfers
+ * @cyclic: Check for cyclic transfers.
  * @genlock: Support genlock mode
  * @err: Channel has errors
  * @tasklet: Cleanup work after irq
@@ -312,6 +316,7 @@ struct xilinx_dma_tx_descriptor {
  * @desc_submitcount: Descriptor h/w submitted count
  * @residue: Residue for AXI DMA
  * @seg_v: Statically allocated segments base
+ * @cyclic_seg_v: Statically allocated segment base for cyclic transfers
  * @start_transfer: Differentiate b/w DMA IP's transfer
  */
 struct xilinx_dma_chan {
@@ -330,6 +335,7 @@ struct xilinx_dma_chan {
 	enum dma_transfer_direction direction;
 	int num_frms;
 	bool has_sg;
+	bool cyclic;
 	bool genlock;
 	bool err;
 	struct tasklet_struct tasklet;
@@ -340,6 +346,7 @@ struct xilinx_dma_chan {
 	u32 desc_submitcount;
 	u32 residue;
 	struct xilinx_axidma_tx_segment *seg_v;
+	struct xilinx_axidma_tx_segment *cyclic_seg_v;
 	void (*start_transfer)(struct xilinx_dma_chan *chan);
 };
 
@@ -660,13 +667,37 @@ static void xilinx_dma_free_chan_resources(struct dma_chan *dchan)
 	dev_dbg(chan->dev, "Free all channel resources.\n");
 
 	xilinx_dma_free_descriptors(chan);
-	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
+		xilinx_dma_free_tx_segment(chan, chan->cyclic_seg_v);
 		xilinx_dma_free_tx_segment(chan, chan->seg_v);
+	}
 	dma_pool_destroy(chan->desc_pool);
 	chan->desc_pool = NULL;
 }
 
 /**
+ * xilinx_dma_chan_handle_cyclic - Cyclic dma callback
+ * @chan: Driver specific dma channel
+ * @desc: dma transaction descriptor
+ * @flags: flags for spin lock
+ */
+static void xilinx_dma_chan_handle_cyclic(struct xilinx_dma_chan *chan,
+					  struct xilinx_dma_tx_descriptor *desc,
+					  unsigned long *flags)
+{
+	dma_async_tx_callback callback;
+	void *callback_param;
+
+	callback = desc->async_tx.callback;
+	callback_param = desc->async_tx.callback_param;
+	if (callback) {
+		spin_unlock_irqrestore(&chan->lock, *flags);
+		callback(callback_param);
+		spin_lock_irqsave(&chan->lock, *flags);
+	}
+}
+
+/**
  * xilinx_dma_chan_desc_cleanup - Clean channel descriptors
  * @chan: Driver specific DMA channel
  */
@@ -681,6 +712,11 @@ static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan)
 		dma_async_tx_callback callback;
 		void *callback_param;
 
+		if (desc->cyclic) {
+			xilinx_dma_chan_handle_cyclic(chan, desc, &flags);
+			break;
+		}
+
 		/* Remove from the list of running transactions */
 		list_del(&desc->node);
 
@@ -757,7 +793,7 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 		return -ENOMEM;
 	}
 
-	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		/*
 		 * For AXI DMA case after submitting a pending_list, keep
 		 * an extra segment allocated so that the "next descriptor"
@@ -768,6 +804,15 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 		 */
 		chan->seg_v = xilinx_axidma_alloc_tx_segment(chan);
 
+		/*
+		 * For cyclic DMA mode we need to program the tail Descriptor
+		 * register with a value which is not a part of the BD chain
+		 * so allocating a desc segment during channel allocation for
+		 * programming tail descriptor.
+		 */
+		chan->cyclic_seg_v = xilinx_axidma_alloc_tx_segment(chan);
+	}
+
 	dma_cookie_init(dchan);
 
 	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
@@ -1157,8 +1202,12 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
 
 	/* Start the transfer */
 	if (chan->has_sg) {
-		dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
-			       tail_segment->phys);
+		if (chan->cyclic)
+			dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
+				       chan->cyclic_seg_v->phys);
+		else
+			dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
+				       tail_segment->phys);
 	} else {
 		struct xilinx_axidma_tx_segment *segment;
 		struct xilinx_axidma_desc_hw *hw;
@@ -1209,7 +1258,8 @@ static void xilinx_dma_complete_descriptor(struct xilinx_dma_chan *chan)
 
 	list_for_each_entry_safe(desc, next, &chan->active_list, node) {
 		list_del(&desc->node);
-		dma_cookie_complete(&desc->async_tx);
+		if (!desc->cyclic)
+			dma_cookie_complete(&desc->async_tx);
 		list_add_tail(&desc->node, &chan->done_list);
 	}
 }
@@ -1397,6 +1447,11 @@ static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 	unsigned long flags;
 	int err;
 
+	if (chan->cyclic) {
+		xilinx_dma_free_tx_descriptor(chan, desc);
+		return -EBUSY;
+	}
+
 	if (chan->err) {
 		/*
 		 * If reset fails, need to hard reset the system.
@@ -1414,6 +1469,9 @@ static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 	/* Put this transaction onto the tail of the pending queue */
 	append_desc_queue(chan, desc);
 
+	if (desc->cyclic)
+		chan->cyclic = true;
+
 	spin_unlock_irqrestore(&chan->lock, flags);
 
 	return cookie;
@@ -1669,12 +1727,112 @@ error:
 }
 
 /**
+ * xilinx_dma_prep_dma_cyclic - prepare descriptors for a DMA_SLAVE transaction
+ * @chan: DMA channel
+ * @sgl: scatterlist to transfer to/from
+ * @sg_len: number of entries in @scatterlist
+ * @direction: DMA direction
+ * @flags: transfer ack flags
+ */
+static struct dma_async_tx_descriptor *xilinx_dma_prep_dma_cyclic(
+	struct dma_chan *dchan, dma_addr_t buf_addr, size_t buf_len,
+	size_t period_len, enum dma_transfer_direction direction,
+	unsigned long flags)
+{
+	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_dma_tx_descriptor *desc;
+	struct xilinx_axidma_tx_segment *segment, *head_segment, *prev = NULL;
+	size_t copy, sg_used;
+	unsigned int num_periods;
+	int i;
+	u32 reg;
+
+	num_periods = buf_len / period_len;
+
+	if (!is_slave_direction(direction))
+		return NULL;
+
+	/* Allocate a transaction descriptor. */
+	desc = xilinx_dma_alloc_tx_descriptor(chan);
+	if (!desc)
+		return NULL;
+
+	chan->direction = direction;
+	dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
+	desc->async_tx.tx_submit = xilinx_dma_tx_submit;
+
+	for (i = 0; i < num_periods; ++i) {
+		sg_used = 0;
+
+		while (sg_used < period_len) {
+			struct xilinx_axidma_desc_hw *hw;
+
+			/* Get a free segment */
+			segment = xilinx_axidma_alloc_tx_segment(chan);
+			if (!segment)
+				goto error;
+
+			/*
+			 * Calculate the maximum number of bytes to transfer,
+			 * making sure it is less than the hw limit
+			 */
+			copy = min_t(size_t, period_len - sg_used,
+				     XILINX_DMA_MAX_TRANS_LEN);
+			hw = &segment->hw;
+			hw->buf_addr = buf_addr + sg_used + (period_len * i);
+			hw->control = copy;
+
+			if (prev)
+				prev->hw.next_desc = segment->phys;
+
+			prev = segment;
+			sg_used += copy;
+
+			/*
+			 * Insert the segment into the descriptor segments
+			 * list.
+			 */
+			list_add_tail(&segment->node, &desc->segments);
+		}
+	}
+
+	head_segment = list_first_entry(&desc->segments,
+				   struct xilinx_axidma_tx_segment, node);
+	desc->async_tx.phys = head_segment->phys;
+
+	desc->cyclic = true;
+	reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
+	reg |= XILINX_DMA_CR_CYCLIC_BD_EN_MASK;
+	dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
+
+	/* For the last DMA_MEM_TO_DEV transfer, set EOP */
+	if (direction == DMA_MEM_TO_DEV) {
+		segment->hw.control |= XILINX_DMA_BD_SOP;
+		segment = list_last_entry(&desc->segments,
+					  struct xilinx_axidma_tx_segment,
+					  node);
+		segment->hw.control |= XILINX_DMA_BD_EOP;
+		segment->hw.next_desc = (u32) head_segment->phys;
+	}
+
+	return &desc->async_tx;
+
+error:
+	xilinx_dma_free_tx_descriptor(chan, desc);
+	return NULL;
+}
+
+/**
  * xilinx_dma_terminate_all - Halt the channel and free descriptors
  * @chan: Driver specific DMA Channel pointer
  */
 static int xilinx_dma_terminate_all(struct dma_chan *dchan)
 {
 	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
+	u32 reg;
+
+	if (chan->cyclic)
+		xilinx_dma_chan_reset(chan);
 
 	/* Halt the DMA engine */
 	xilinx_dma_halt(chan);
@@ -1682,6 +1840,13 @@ static int xilinx_dma_terminate_all(struct dma_chan *dchan)
 	/* Remove and free all of the descriptors in the lists */
 	xilinx_dma_free_descriptors(chan);
 
+	if (chan->cyclic) {
+		reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
+		reg &= ~XILINX_DMA_CR_CYCLIC_BD_EN_MASK;
+		dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
+		chan->cyclic = false;
+	}
+
 	return 0;
 }
 
@@ -2218,7 +2383,10 @@ static int xilinx_dma_probe(struct platform_device *pdev)
 	xdev->common.device_tx_status = xilinx_dma_tx_status;
 	xdev->common.device_issue_pending = xilinx_dma_issue_pending;
 	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
+		dma_cap_set(DMA_CYCLIC, xdev->common.cap_mask);
 		xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg;
+		xdev->common.device_prep_dma_cyclic =
+					  xilinx_dma_prep_dma_cyclic;
 		/* Residue calculation is supported by only AXI DMA */
 		xdev->common.residue_granularity =
 					  DMA_RESIDUE_GRANULARITY_SEGMENT;
-- 
2.1.2



From mcoquelin.stm32 at gmail.com  Wed May 18 00:48:53 2016
From: mcoquelin.stm32 at gmail.com (Maxime Coquelin)
Date: Wed, 18 May 2016 09:48:53 +0200
Subject: [RESEND PATCH v6 0/6] Add Ethernet support on STM32F429
In-Reply-To: <20160517.122527.1937360418899371800.davem@davemloft.net>
References: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
 <20160509.150634.213732321950308841.davem@davemloft.net>
 <CALszF6Cfs02-tGvFqpyJpUy7jSfjGTY8fVaaLQ8iQaGfCxvDtQ@mail.gmail.com>
 <20160517.122527.1937360418899371800.davem@davemloft.net>
Message-ID: <CALszF6AE7jkRX3sSNm=PCvEmkmZM-Sv5LxFSj7J3vMbvi8M5Cg@mail.gmail.com>

2016-05-17 18:25 GMT+02:00 David Miller <davem at davemloft.net>:
> From: Maxime Coquelin <mcoquelin.stm32 at gmail.com>
> Date: Tue, 17 May 2016 11:20:16 +0200
>
>> Hi David,
>>
>> 2016-05-09 21:06 GMT+02:00 David Miller <davem at davemloft.net>:
>>> From: Alexandre TORGUE <alexandre.torgue at gmail.com>
>>> Date: Mon,  9 May 2016 12:31:33 +0200
>>>
>>>> STM32F429 Chip embeds a Synopsys 3.50a MAC IP.
>>>> This series:
>>>>  -enhance current stmmac driver to control it (code already
>>>> available) and adds basic glue for STM32F429 chip.
>>>>  -Enable basic Net config in kernel.
>>>
>>> I assume this will go via the ARM tree, for the networking bits:
>> I would expect patches 1, 2 & 3 to got via your tree, to avoid conflicts.
>
> I don't think putting them all via the ARM tree is going to create much
> in the way of conflicts, and right now during the merge window offloading
> that work from me would really help my backlog a lot.

Ok, I understand this is not the best time to pick it.

Arnd, Olof & Kevin, would you accept to pick the series in your tree?

Regards,
Maxime


From pavel at ucw.cz  Wed May 18 00:49:24 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Wed, 18 May 2016 09:49:24 +0200
Subject: 4.5-rc0 regression: GPRS breaks after very short while
Message-ID: <20160518074924.GA20652@amd>

Hi!

I was afraid another GSM chip desoldered itself in N900, but no, it
seems to be software this time.

In 4.4, GPRS is rock solid, can survive overnight ping.

In 4.5-rc0 and v4.6, modem fails when I use gprs for like a
minute. Phone is not usable.

Best regards,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From songjun.wu at atmel.com  Wed May 18 00:46:27 2016
From: songjun.wu at atmel.com (Songjun Wu)
Date: Wed, 18 May 2016 15:46:27 +0800
Subject: [PATCH v2 0/2] [media] atmel-isc: add driver for Atmel ISC
Message-ID: <1463557590-29318-1-git-send-email-songjun.wu@atmel.com>

The Image Sensor Controller driver includes two parts.
1) Driver code to implement the ISC function.
2) Device tree binding documentation, it describes how
   to add the ISC in device tree.

Changes in v2:
- Add "depends on COMMON_CLK && VIDEO_V4L2_SUBDEV_API"
  in Kconfig file.
- Delete the redundant blank in atmel-isc-regs.h
- Enclose the expression in parentheses in some macros.
- Sort the header file alphabetically.
- Move the 'to_isc_clk(hw)' right after the struct
  isc_clk definition
- Move the global variables into the struct isc_device.
- Change some int variable to unsigned int variable.
- Replace pr_debug() with dev_dbg();
- Delete the loop while in 'isc_clk_enable' function.
- Rename the 'tmp_rate' and 'tmp_diff' to 'rate' and
  'diff' in 'isc_clk_determine_rate' function.
- Delete the inner parentheses in 'isc_clk_register'
  function.
- Delete the variable i in 'isc_parse_dt' function.
- Replace 'hsync_active', 'vsync_active' and 'pclk_sample'
  with 'pfe_cfg0' in struct isc_subdev_entity.
- Move the 'isc_parse_dt'function down right above the
  'atmel_isc_probe' function.
- Add the code to support VIDIOC_CREATE_BUFS in
  'isc_queue_setup' function.
- Replace the variable type 'unsigned long' with 'dma_addr_t'
  in 'isc_start_dma' function.
- Remove the list_del call, turn list_for_each_entry_safe
  into list_for_each entry, and add a INIT_LIST_HEAD after
  the loop in 'isc_start_streaming', 'isc_stop_streaming'
  and 'isc_subdev_cleanup' function.
- Invoke isc_config to configure register in
  'isc_start_streaming' function.
- Add the struct completion 'comp' to synchronize with
  the frame end interrupt in 'isc_stop_streaming' function.
- Check the return value of the clk_prepare_enable
  in 'isc_open' function.
- Set the default format in 'isc_open' function.
- Add an exit condition in the loop while in 'isc_config'.
- Delete the hardware setup operation in 'isc_set_format'.
- Refuse format modification during streaming
  in 'isc_s_fmt_vid_cap' function.
- Invoke v4l2_subdev_alloc_pad_config to allocate and
  initialize the pad config in 'isc_async_complete' function.
- Remove the check of the '!res' since devm_ioremap_resource()
  will check for it.
- Remove the error message in case of failure
  when call devm_ioremap_resource.
- Remove the cast the isc pointer to (void *).
- Remove the '.owner  = THIS_MODULE,' in atmel_isc_driver.
- Replace the module_platform_driver_probe() with
  module_platform_driver().
- Remove the unit address of the endpoint.
- Add the unit address to the clock node.
- Avoid using underscores in node names.
- Drop the "0x" in the unit address of the i2c node.
- Modify the description of "atmel,sensor-preferred".
- Add the description for the ISC internal clock.

Songjun Wu (2):
  [media] atmel-isc: add the Image Sensor Controller code
  [media] atmel-isc: DT binding for Image Sensor Controller driver

 .../devicetree/bindings/media/atmel-isc.txt        |  100 ++
 drivers/media/platform/Kconfig                     |    1 +
 drivers/media/platform/Makefile                    |    2 +
 drivers/media/platform/atmel/Kconfig               |    9 +
 drivers/media/platform/atmel/Makefile              |    1 +
 drivers/media/platform/atmel/atmel-isc-regs.h      |  276 ++++
 drivers/media/platform/atmel/atmel-isc.c           | 1583 ++++++++++++++++++++
 7 files changed, 1972 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/atmel-isc.txt
 create mode 100644 drivers/media/platform/atmel/Kconfig
 create mode 100644 drivers/media/platform/atmel/Makefile
 create mode 100644 drivers/media/platform/atmel/atmel-isc-regs.h
 create mode 100644 drivers/media/platform/atmel/atmel-isc.c

-- 
2.7.4



From songjun.wu at atmel.com  Wed May 18 00:46:28 2016
From: songjun.wu at atmel.com (Songjun Wu)
Date: Wed, 18 May 2016 15:46:28 +0800
Subject: [PATCH v2 1/2] [media] atmel-isc: add the Image Sensor Controller code
In-Reply-To: <1463557590-29318-1-git-send-email-songjun.wu@atmel.com>
References: <1463557590-29318-1-git-send-email-songjun.wu@atmel.com>
Message-ID: <1463557590-29318-2-git-send-email-songjun.wu@atmel.com>

Add driver for the Image Sensor Controller. It manages
incoming data from a parallel based CMOS/CCD sensor.
It has an internal image processor, also integrates a
triple channel direct memory access controller master
interface.

Signed-off-by: Songjun Wu <songjun.wu at atmel.com>
---

Changes in v2:
- Add "depends on COMMON_CLK && VIDEO_V4L2_SUBDEV_API"
  in Kconfig file.
- Delete the redundant blank in atmel-isc-regs.h
- Enclose the expression in parentheses in some macros.
- Sort the header file alphabetically.
- Move the 'to_isc_clk(hw)' right after the struct
  isc_clk definition
- Move the global variables into the struct isc_device.
- Change some int variable to unsigned int variable.
- Replace pr_debug() with dev_dbg();
- Delete the loop while in 'isc_clk_enable' function.
- Rename the 'tmp_rate' and 'tmp_diff' to 'rate' and
  'diff' in 'isc_clk_determine_rate' function.
- Delete the inner parentheses in 'isc_clk_register'
  function.
- Delete the variable i in 'isc_parse_dt' function.
- Replace 'hsync_active', 'vsync_active' and 'pclk_sample'
  with 'pfe_cfg0' in struct isc_subdev_entity.
- Move the 'isc_parse_dt'function down right above the
  'atmel_isc_probe' function.
- Add the code to support VIDIOC_CREATE_BUFS in
  'isc_queue_setup' function.
- Replace the variable type 'unsigned long' with 'dma_addr_t'
  in 'isc_start_dma' function.
- Remove the list_del call, turn list_for_each_entry_safe
  into list_for_each entry, and add a INIT_LIST_HEAD after
  the loop in 'isc_start_streaming', 'isc_stop_streaming'
  and 'isc_subdev_cleanup' function.
- Invoke isc_config to configure register in
  'isc_start_streaming' function.
- Add the struct completion 'comp' to synchronize with
  the frame end interrupt in 'isc_stop_streaming' function.
- Check the return value of the clk_prepare_enable
  in 'isc_open' function.
- Set the default format in 'isc_open' function.
- Add an exit condition in the loop while in 'isc_config'.
- Delete the hardware setup operation in 'isc_set_format'.
- Refuse format modification during streaming
  in 'isc_s_fmt_vid_cap' function.
- Invoke v4l2_subdev_alloc_pad_config to allocate and
  initialize the pad config in 'isc_async_complete' function.
- Remove the check of the '!res' since devm_ioremap_resource()
  will check for it.
- Remove the error message in case of failure
  when call devm_ioremap_resource.
- Remove the cast the isc pointer to (void *).
- Remove the '.owner  = THIS_MODULE,' in atmel_isc_driver.
- Replace the module_platform_driver_probe() with
  module_platform_driver().

 drivers/media/platform/Kconfig                |    1 +
 drivers/media/platform/Makefile               |    2 +
 drivers/media/platform/atmel/Kconfig          |    9 +
 drivers/media/platform/atmel/Makefile         |    1 +
 drivers/media/platform/atmel/atmel-isc-regs.h |  276 +++++
 drivers/media/platform/atmel/atmel-isc.c      | 1583 +++++++++++++++++++++++++
 6 files changed, 1872 insertions(+)
 create mode 100644 drivers/media/platform/atmel/Kconfig
 create mode 100644 drivers/media/platform/atmel/Makefile
 create mode 100644 drivers/media/platform/atmel/atmel-isc-regs.h
 create mode 100644 drivers/media/platform/atmel/atmel-isc.c

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 84e041c..91d7aea 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -110,6 +110,7 @@ source "drivers/media/platform/exynos4-is/Kconfig"
 source "drivers/media/platform/s5p-tv/Kconfig"
 source "drivers/media/platform/am437x/Kconfig"
 source "drivers/media/platform/xilinx/Kconfig"
+source "drivers/media/platform/atmel/Kconfig"
 
 config VIDEO_TI_CAL
 	tristate "TI CAL (Camera Adaptation Layer) driver"
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index bbb7bd1..ad8f471 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -55,4 +55,6 @@ obj-$(CONFIG_VIDEO_AM437X_VPFE)		+= am437x/
 
 obj-$(CONFIG_VIDEO_XILINX)		+= xilinx/
 
+obj-$(CONFIG_VIDEO_ATMEL_ISC)		+= atmel/
+
 ccflags-y += -I$(srctree)/drivers/media/i2c
diff --git a/drivers/media/platform/atmel/Kconfig b/drivers/media/platform/atmel/Kconfig
new file mode 100644
index 0000000..867dca2
--- /dev/null
+++ b/drivers/media/platform/atmel/Kconfig
@@ -0,0 +1,9 @@
+config VIDEO_ATMEL_ISC
+	tristate "ATMEL Image Sensor Controller (ISC) support"
+	depends on VIDEO_V4L2 && COMMON_CLK && VIDEO_V4L2_SUBDEV_API && HAS_DMA
+	depends on ARCH_AT91 || COMPILE_TEST
+	select VIDEOBUF2_DMA_CONTIG
+	select REGMAP_MMIO
+	help
+	   This module makes the ATMEL Image Sensor Controller available
+	   as a v4l2 device.
\ No newline at end of file
diff --git a/drivers/media/platform/atmel/Makefile b/drivers/media/platform/atmel/Makefile
new file mode 100644
index 0000000..9d7c999
--- /dev/null
+++ b/drivers/media/platform/atmel/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_VIDEO_ATMEL_ISC) += atmel-isc.o
diff --git a/drivers/media/platform/atmel/atmel-isc-regs.h b/drivers/media/platform/atmel/atmel-isc-regs.h
new file mode 100644
index 0000000..dda9396
--- /dev/null
+++ b/drivers/media/platform/atmel/atmel-isc-regs.h
@@ -0,0 +1,276 @@
+#ifndef __ATMEL_ISC_REGS_H
+#define __ATMEL_ISC_REGS_H
+
+#include <linux/bitops.h>
+
+/* ISC Control Enable Register 0 */
+#define ISC_CTRLEN      0x00000000
+
+#define ISC_CTRLEN_CAPTURE              BIT(0)
+#define ISC_CTRLEN_CAPTURE_MASK         BIT(0)
+
+#define ISC_CTRLEN_UPPRO                BIT(1)
+#define ISC_CTRLEN_UPPRO_MASK           BIT(1)
+
+#define ISC_CTRLEN_HISREQ               BIT(2)
+#define ISC_CTRLEN_HISREQ_MASK          BIT(2)
+
+#define ISC_CTRLEN_HISCLR               BIT(3)
+#define ISC_CTRLEN_HISCLR_MASK          BIT(3)
+
+/* ISC Control Disable Register 0 */
+#define ISC_CTRLDIS     0x00000004
+
+#define ISC_CTRLDIS_DISABLE             BIT(0)
+#define ISC_CTRLDIS_DISABLE_MASK        BIT(0)
+
+#define ISC_CTRLDIS_SWRST               BIT(8)
+#define ISC_CTRLDIS_SWRST_MASK          BIT(8)
+
+/* ISC Control Status Register 0 */
+#define ISC_CTRLSR      0x00000008
+
+#define ISC_CTRLSR_CAPTURE      BIT(0)
+#define ISC_CTRLSR_UPPRO        BIT(1)
+#define ISC_CTRLSR_HISREQ       BIT(2)
+#define ISC_CTRLSR_FIELD        BIT(4)
+#define ISC_CTRLSR_SIP          BIT(31)
+
+/* ISC Parallel Front End Configuration 0 Register */
+#define ISC_PFE_CFG0    0x0000000c
+
+#define ISC_PFE_CFG0_HPOL_LOW   BIT(0)
+#define ISC_PFE_CFG0_HPOL_HIGH  0x0
+#define ISC_PFE_CFG0_HPOL_MASK  BIT(0)
+
+#define ISC_PFE_CFG0_VPOL_LOW   BIT(1)
+#define ISC_PFE_CFG0_VPOL_HIGH  0x0
+#define ISC_PFE_CFG0_VPOL_MASK  BIT(1)
+
+#define ISC_PFE_CFG0_PPOL_LOW   BIT(2)
+#define ISC_PFE_CFG0_PPOL_HIGH  0x0
+#define ISC_PFE_CFG0_PPOL_MASK  BIT(2)
+
+#define ISC_PFE_CFG0_MODE_PROGRESSIVE   0x0
+#define ISC_PFE_CFG0_MODE_MASK          GENMASK(6, 4)
+
+#define ISC_PFE_CFG0_BPS_EIGHT  (0x4 << 28)
+#define ISC_PFG_CFG0_BPS_NINE   (0x3 << 28)
+#define ISC_PFG_CFG0_BPS_TEN    (0x2 << 28)
+#define ISC_PFG_CFG0_BPS_ELEVEN (0x1 << 28)
+#define ISC_PFG_CFG0_BPS_TWELVE 0x0
+#define ISC_PFE_CFG0_BPS_MASK   GENMASK(30, 28)
+
+/* ISC Clock Enable Register */
+#define ISC_CLKEN               0x00000018
+#define ISC_CLKEN_EN            0x1
+#define ISC_CLKEN_EN_SHIFT(n)   (n)
+#define ISC_CLKEN_EN_MASK(n)    BIT(n)
+
+/* ISC Clock Disable Register */
+#define ISC_CLKDIS              0x0000001c
+#define ISC_CLKDIS_DIS          0x1
+#define ISC_CLKDIS_DIS_SHIFT(n) (n)
+#define ISC_CLKDIS_DIS_MASK(n)  BIT(n)
+
+/* ISC Clock Status Register */
+#define ISC_CLKSR               0x00000020
+#define ISC_CLKSR_CLK_MASK(n)   BIT(n)
+#define ISC_CLKSR_SIP_PROGRESS  BIT(31)
+
+/* ISC Clock Configuration Register */
+#define ISC_CLKCFG              0x00000024
+#define ISC_CLKCFG_DIV_SHIFT(n) ((n)*16)
+#define ISC_CLKCFG_DIV_MASK(n)  GENMASK(((n)*16 + 7), (n)*16)
+#define ISC_CLKCFG_SEL_SHIFT(n) ((n)*16 + 8)
+#define ISC_CLKCFG_SEL_MASK(n)  GENMASK(((n)*17 + 8), ((n)*16 + 8))
+
+/* ISC Interrupt Enable Register */
+#define ISC_INTEN       0x00000028
+
+#define ISC_INTEN_DDONE         BIT(8)
+#define ISC_INTEN_DDONE_MASK    BIT(8)
+
+/* ISC Interrupt Disable Register */
+#define ISC_INTDIS      0x0000002c
+
+#define ISC_INTDIS_DDONE        BIT(8)
+#define ISC_INTDIS_DDONE_MASK   BIT(8)
+
+/* ISC Interrupt Mask Register */
+#define ISC_INTMASK     0x00000030
+
+/* ISC Interrupt Status Register */
+#define ISC_INTSR       0x00000034
+
+#define ISC_INTSR_DDONE         BIT(8)
+
+/* ISC White Balance Control Register */
+#define ISC_WB_CTRL     0x00000058
+
+#define ISC_WB_CTRL_EN          BIT(0)
+#define ISC_WB_CTRL_DIS         0x0
+#define ISC_WB_CTRL_MASK        BIT(0)
+
+/* ISC White Balance Configuration Register */
+#define ISC_WB_CFG      0x0000005c
+
+#define ISC_WB_CFG_BAYCFG_GRGR  0x0
+#define ISC_WB_CFG_BAYCFG_RGRG  0x1
+#define ISC_WB_CFG_BAYCFG_GBGB  0x2
+#define ISC_WB_CFG_BAYCFG_BGBG  0x3
+#define ISC_WB_CFG_BAYCFG_MASK  GENMASK(1, 0)
+
+/* ISC Color Filter Array Control Register */
+#define ISC_CFA_CTRL    0x00000070
+
+#define ISC_CFA_CTRL_EN         BIT(0)
+#define ISC_CFA_CTRL_DIS        0x0
+#define ISC_CFA_CTRL_MASK       BIT(0)
+
+/* ISC Color Filter Array Configuration Register */
+#define ISC_CFA_CFG     0x00000074
+
+#define ISC_CFA_CFG_BAY_GRGR    0x0
+#define ISC_CFA_CFG_BAY_RGRG    0x1
+#define ISC_CFA_CFG_BAY_GBGB    0x2
+#define ISC_CFA_CFG_BAY_BGBG    0x3
+#define ISC_CFA_CFG_BAY_MASK    GENMASK(1, 0)
+
+/* ISC Color Correction Control Register */
+#define ISC_CC_CTRL     0x00000078
+
+#define ISC_CC_CTRL_EN          BIT(0)
+#define ISC_CC_CTRL_DIS         0x0
+#define ISC_CC_CTRL_MASK        BIT(0)
+
+/* ISC Gamma Correction Control Register */
+#define ISC_GAM_CTRL    0x00000094
+
+#define ISC_GAM_CTRL_EN         BIT(0)
+#define ISC_GAM_CTRL_DIS        0x0
+#define ISC_GAM_CTRL_MASK       BIT(0)
+
+#define ISC_GAM_CTRL_B_EN       BIT(1)
+#define ISC_GAM_CTRL_B_DIS      0x0
+#define ISC_GAM_CTRL_B_MASK     BIT(1)
+
+#define ISC_GAM_CTRL_G_EN       BIT(2)
+#define ISC_GAM_CTRL_G_DIS      0x0
+#define ISC_GAM_CTRL_G_MASK     BIT(2)
+
+#define ISC_GAM_CTRL_R_EN       BIT(3)
+#define ISC_GAM_CTRL_R_DIS      0x0
+#define ISC_GAM_CTRL_R_MASK     BIT(3)
+
+#define ISC_GAM_CTRL_ALL_CHAN_MASK (ISC_GAM_CTRL_B_MASK | \
+				    ISC_GAM_CTRL_G_MASK | \
+				    ISC_GAM_CTRL_R_MASK)
+
+/* Color Space Conversion Control Register */
+#define ISC_CSC_CTRL    0x00000398
+
+#define ISC_CSC_CTRL_EN         BIT(0)
+#define ISC_CSC_CTRL_DIS        0x0
+#define ISC_CSC_CTRL_MASK       BIT(0)
+
+/* Contrast And Brightness Control Register */
+#define ISC_CBC_CTRL    0x000003b4
+
+#define ISC_CBC_CTRL_EN         BIT(0)
+#define ISC_CBC_CTRL_DIS        0x0
+#define ISC_CBC_CTRL_MASK       BIT(0)
+
+/* Subsampling 4:4:4 to 4:2:2 Control Register */
+#define ISC_SUB422_CTRL 0x000003c4
+
+#define ISC_SUB422_CTRL_EN      BIT(0)
+#define ISC_SUB422_CTRL_DIS     0x0
+#define ISC_SUB422_CTRL_MASK    BIT(0)
+
+/* Subsampling 4:2:2 to 4:2:0 Control Register */
+#define ISC_SUB420_CTRL 0x000003cc
+
+#define ISC_SUB420_CTRL_EN      BIT(0)
+#define ISC_SUB420_CTRL_DIS     0x0
+#define ISC_SUB420_CTRL_MASK    BIT(0)
+
+#define ISC_SUB420_CTRL_FILTER_PROG     0x0
+#define ISC_SUB420_CTRL_FILTER_INTER    BIT(4)
+#define ISC_SUB420_CTRL_FILTER_MASK     BIT(4)
+
+/* Rounding, Limiting and Packing Configuration Register */
+#define ISC_RLP_CFG     0x000003d0
+
+#define ISC_RLP_CFG_MODE_DAT8           0x0
+#define ISC_RLP_CFG_MODE_DAT9           0x1
+#define ISC_RLP_CFG_MODE_DAT10          0x2
+#define ISC_RLP_CFG_MODE_DAT11          0x3
+#define ISC_RLP_CFG_MODE_DAT12          0x4
+#define ISC_RLP_CFG_MODE_DATY8          0x5
+#define ISC_RLP_CFG_MODE_DATY10         0x6
+#define ISC_RLP_CFG_MODE_ARGB444        0x7
+#define ISC_RLP_CFG_MODE_ARGB555        0x8
+#define ISC_RLP_CFG_MODE_RGB565         0x9
+#define ISC_RLP_CFG_MODE_ARGB32         0xa
+#define ISC_RLP_CFG_MODE_YYCC           0xb
+#define ISC_RLP_CFG_MODE_YYCC_LIMITED   0xc
+#define ISC_RLP_CFG_MODE_MASK           GENMASK(3, 0)
+
+/* DMA Configuration Register */
+#define ISC_DCFG        0x000003e0
+#define ISC_DCFG_IMODE_PACKED8          0x0
+#define ISC_DCFG_IMODE_PACKED16         0x1
+#define ISC_DCFG_IMODE_PACKED32         0x2
+#define ISC_DCFG_IMODE_YC422SP          0x3
+#define ISC_DCFG_IMODE_YC422P           0x4
+#define ISC_DCFG_IMODE_YC420SP          0x5
+#define ISC_DCFG_IMODE_YC420P           0x6
+#define ISC_DCFG_IMODE_MASK             GENMASK(2, 0)
+
+#define ISC_DCFG_YMBSIZE_SINGLE         0x0
+#define ISC_DCFG_YMBSIZE_BEATS4         (0x1 << 4)
+#define ISC_DCFG_YMBSIZE_BEATS8         (0x2 << 4)
+#define ISC_DCFG_YMBSIZE_BEATS16        (0x3 << 4)
+#define ISC_DCFG_YMBSIZE_MASK           GENMASK(5, 4)
+
+#define ISC_DCFG_CMBSIZE_SINGLE         0x0
+#define ISC_DCFG_CMBSIZE_BEATS4         (0x1 << 8)
+#define ISC_DCFG_CMBSIZE_BEATS8         (0x2 << 8)
+#define ISC_DCFG_CMBSIZE_BEATS16        (0x3 << 8)
+#define ISC_DCFG_CMBSIZE_MASK           GENMASK(9, 8)
+
+/* DMA Control Register */
+#define ISC_DCTRL       0x000003e4
+
+#define ISC_DCTRL_DE_EN         BIT(0)
+#define ISC_DCTRL_DE_DIS        0x0
+#define ISC_DCTRL_DE_MASK       BIT(0)
+
+#define ISC_DCTRL_DVIEW_PACKED          0x0
+#define ISC_DCTRL_DVIEW_SEMIPLANAR      (0x1 << 1)
+#define ISC_DCTRL_DVIEW_PLANAR          (0x2 << 1)
+#define ISC_DCTRL_DVIEW_MASK            GENMASK(2, 1)
+
+#define ISC_DCTRL_IE_IS         0x0
+#define ISC_DCTRL_IE_NOT        BIT(4)
+#define ISC_DCTRL_IE_MASK       BIT(4)
+
+#define ISC_DCTRL_WB_EN         BIT(5)
+#define ISC_DCTRL_WB_DIS        0x0
+#define ISC_DCTRL_WB_MASK       BIT(5)
+
+#define ISC_DCTRL_DESC_IS_DONE  BIT(7)
+#define ISC_DCTRL_DESC_NOT_DONE 0x0
+#define ISC_DCTRL_DESC_MASK     BIT(7)
+
+/* DMA Descriptor Address Register */
+#define ISC_DNDA        0x000003e8
+
+/* DMA Address 0 Register */
+#define ISC_DAD0        0x000003ec
+
+/* DMA Stride 0 Register */
+#define ISC_DST0        0x000003f0
+
+#endif
diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c
new file mode 100644
index 0000000..178f647
--- /dev/null
+++ b/drivers/media/platform/atmel/atmel-isc.c
@@ -0,0 +1,1583 @@
+/*
+ * Atmel Image Sensor Controller (ISC) driver
+ *
+ * Copyright (C) 2016 Atmel
+ *
+ * Author: Songjun Wu <songjun.wu at atmel.com>
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * Sensor-->PFE-->WB-->CFA-->CC-->GAM-->CSC-->CBC-->SUB-->RLP-->DMA
+ *
+ * ISC video pipeline integrates the following submodules:
+ * PFE: Parallel Front End to sample the camera sensor input stream
+ *  WB: Programmable white balance in the Bayer domain
+ * CFA: Color filter array interpolation module
+ *  CC: Programmable color correction
+ * GAM: Gamma correction
+ * CSC: Programmable color space conversion
+ * CBC: Contrast and Brightness control
+ * SUB: This module performs YCbCr444 to YCbCr420 chrominance subsampling
+ * RLP: This module performs rounding, range limiting
+ *      and packing of the incoming data
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-image-sizes.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-of.h>
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "atmel-isc-regs.h"
+
+#define ATMEL_ISC_NAME		"atmel_isc"
+
+#define ISC_MAX_SUPPORT_WIDTH   2592
+#define ISC_MAX_SUPPORT_HEIGHT  1944
+
+#define ISC_ISPCK_SOURCE_MAX    2
+#define ISC_MCK_SOURCE_MAX      3
+#define ISC_CLK_MAX_DIV		255
+
+enum isc_clk_id {
+	ISC_ISPCK = 0,
+	ISC_MCK = 1,
+};
+
+struct isc_clk {
+	struct clk_hw   hw;
+	struct clk      *clk;
+	struct regmap   *regmap;
+	spinlock_t      *lock;
+	enum isc_clk_id id;
+	u32		div;
+	u8		parent_id;
+
+	struct isc_device *isc;
+};
+
+#define to_isc_clk(hw) container_of(hw, struct isc_clk, hw)
+
+struct isc_buffer {
+	struct vb2_v4l2_buffer  vb;
+	struct list_head	list;
+};
+
+struct isc_subdev_entity {
+	struct v4l2_subdev		*sd;
+	struct v4l2_async_subdev	*asd;
+	struct v4l2_async_notifier      notifier;
+	struct v4l2_subdev_pad_config	*config;
+
+	u32 pfe_cfg0;
+
+	struct list_head list;
+};
+
+/*
+ * struct isc_format - ISC media bus format information
+ * @fourcc:		Fourcc code for this format
+ * @isc_mbus_code:      V4L2 media bus format code if ISC is preferred
+ * @sd_mbus_code:       V4L2 media bus format code if subdev is preferred
+ * @bpp:		Bytes per pixel (when stored in memory)
+ * @reg_sd_bps:		reg value for bits per sample if subdev is preferred
+ *			(when transferred over a bus)
+ * @reg_isc_bps:	reg value for bits per sample if ISC is preferred
+ *			(when transferred over a bus)
+ * @pipeline:		pipeline switch if ISC is preferred
+ * @isc_support:	ISC can convert raw format to this format
+ * @sd_support:		Subdev supports this format
+ */
+struct isc_format {
+	u32	fourcc;
+	u32	isc_mbus_code;
+	u32	sd_mbus_code;
+
+	u8	bpp;
+
+	u32	reg_sd_bps;
+	u32	reg_isc_bps;
+
+	u32	reg_wb_cfg;
+	u32	reg_cfa_cfg;
+	u32	reg_rlp_mode;
+	u32	reg_dcfg_imode;
+	u32	reg_dctrl_dview;
+
+	u32	pipeline;
+
+	bool	isc_support;
+	bool	sd_support;
+};
+
+struct isc_device {
+	struct regmap		*regmap;
+	struct clk		*hclock;
+	struct clk		*ispck;
+	struct isc_clk		isc_clks[2];
+	spinlock_t		clk_lock;
+
+	struct device		*dev;
+	struct v4l2_device	v4l2_dev;
+	struct video_device	video_dev;
+
+	struct vb2_queue	vb2_vidq;
+	struct vb2_alloc_ctx	*alloc_ctx;
+
+	spinlock_t		dma_queue_lock;
+	struct list_head	dma_queue;
+	struct isc_buffer	*cur_frm;
+	unsigned int		sequence;
+	bool			stop;
+	struct completion	comp;
+
+	struct v4l2_format	fmt;
+
+	struct isc_format	**user_formats;
+	unsigned int		num_user_formats;
+	const struct isc_format	*current_fmt;
+	u32			sensor_preferred;
+
+	struct mutex		lock;
+
+	struct isc_subdev_entity	*current_subdev;
+	struct list_head		subdev_entities;
+};
+
+struct reg_mask {
+	u32 reg;
+	u32 mask;
+};
+
+/* WB-->CFA-->CC-->GAM-->CSC-->CBC-->SUB422-->SUB420 */
+const struct reg_mask pipeline_regs[] = {
+	{ ISC_WB_CTRL,  ISC_WB_CTRL_MASK },
+	{ ISC_CFA_CTRL, ISC_CFA_CTRL_MASK },
+	{ ISC_CC_CTRL,  ISC_CC_CTRL_MASK },
+	{ ISC_GAM_CTRL, ISC_GAM_CTRL_MASK | ISC_GAM_CTRL_ALL_CHAN_MASK },
+	{ ISC_CSC_CTRL, ISC_CSC_CTRL_MASK },
+	{ ISC_CBC_CTRL, ISC_CBC_CTRL_MASK },
+	{ ISC_SUB422_CTRL, ISC_SUB422_CTRL_MASK },
+	{ ISC_SUB420_CTRL, ISC_SUB420_CTRL_MASK }
+};
+
+#define RAW_FMT_INDEX_START	0
+#define RAW_FMT_INDEX_END	11
+#define ISC_FMT_INDEX_START	12
+#define ISC_FMT_INDEX_END	12
+
+/*
+ * index(0~11):  raw formats.
+ * index(12~12): the formats which can be converted from raw format by ISC.
+ * index():      the formats which can only be provided by subdev.
+ */
+static struct isc_format isc_formats[] = {
+{V4L2_PIX_FMT_SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8,
+1, ISC_PFE_CFG0_BPS_EIGHT, ISC_PFE_CFG0_BPS_EIGHT, ISC_WB_CFG_BAYCFG_BGBG,
+ISC_CFA_CFG_BAY_BGBG, ISC_RLP_CFG_MODE_DAT8, ISC_DCFG_IMODE_PACKED8,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8,
+1, ISC_PFE_CFG0_BPS_EIGHT, ISC_PFE_CFG0_BPS_EIGHT, ISC_WB_CFG_BAYCFG_GBGB,
+ISC_CFA_CFG_BAY_GBGB, ISC_RLP_CFG_MODE_DAT8, ISC_DCFG_IMODE_PACKED8,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8,
+1, ISC_PFE_CFG0_BPS_EIGHT, ISC_PFE_CFG0_BPS_EIGHT, ISC_WB_CFG_BAYCFG_GRGR,
+ISC_CFA_CFG_BAY_GRGR, ISC_RLP_CFG_MODE_DAT8, ISC_DCFG_IMODE_PACKED8,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8,
+1, ISC_PFE_CFG0_BPS_EIGHT, ISC_PFE_CFG0_BPS_EIGHT, ISC_WB_CFG_BAYCFG_RGRG,
+ISC_CFA_CFG_BAY_RGRG, ISC_RLP_CFG_MODE_DAT8, ISC_DCFG_IMODE_PACKED8,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+
+{V4L2_PIX_FMT_SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10,
+2, ISC_PFG_CFG0_BPS_TEN, ISC_PFG_CFG0_BPS_TEN, ISC_WB_CFG_BAYCFG_BGBG,
+ISC_CFA_CFG_BAY_BGBG, ISC_RLP_CFG_MODE_DAT10, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10,
+2, ISC_PFG_CFG0_BPS_TEN, ISC_PFG_CFG0_BPS_TEN, ISC_WB_CFG_BAYCFG_GBGB,
+ISC_CFA_CFG_BAY_GBGB, ISC_RLP_CFG_MODE_DAT10, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SGRBG10, MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10,
+2, ISC_PFG_CFG0_BPS_TEN, ISC_PFG_CFG0_BPS_TEN, ISC_WB_CFG_BAYCFG_GRGR,
+ISC_CFA_CFG_BAY_GRGR, ISC_RLP_CFG_MODE_DAT10, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SRGGB10, MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10,
+2, ISC_PFG_CFG0_BPS_TEN, ISC_PFG_CFG0_BPS_TEN, ISC_WB_CFG_BAYCFG_RGRG,
+ISC_CFA_CFG_BAY_RGRG, ISC_RLP_CFG_MODE_DAT10, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+
+{V4L2_PIX_FMT_SBGGR12, MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR12_1X12,
+2, ISC_PFG_CFG0_BPS_TWELVE, ISC_PFG_CFG0_BPS_TWELVE, ISC_WB_CFG_BAYCFG_BGBG,
+ISC_CFA_CFG_BAY_BGBG, ISC_RLP_CFG_MODE_DAT12, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SGBRG12, MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG12_1X12,
+2, ISC_PFG_CFG0_BPS_TWELVE, ISC_PFG_CFG0_BPS_TWELVE, ISC_WB_CFG_BAYCFG_GBGB,
+ISC_CFA_CFG_BAY_GBGB, ISC_RLP_CFG_MODE_DAT12, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SGRBG12, MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG12_1X12,
+2, ISC_PFG_CFG0_BPS_TWELVE, ISC_PFG_CFG0_BPS_TWELVE, ISC_WB_CFG_BAYCFG_GRGR,
+ISC_CFA_CFG_BAY_GRGR, ISC_RLP_CFG_MODE_DAT12, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SRGGB12, MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB12_1X12,
+2, ISC_PFG_CFG0_BPS_TWELVE, ISC_PFG_CFG0_BPS_TWELVE, ISC_WB_CFG_BAYCFG_RGRG,
+ISC_CFA_CFG_BAY_RGRG, ISC_RLP_CFG_MODE_DAT12, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+
+{V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_YUYV8_2X8,
+2, ISC_PFE_CFG0_BPS_EIGHT, ISC_PFE_CFG0_BPS_EIGHT, ISC_WB_CFG_BAYCFG_BGBG,
+ISC_CFA_CFG_BAY_BGBG, ISC_RLP_CFG_MODE_DAT8, ISC_DCFG_IMODE_PACKED8,
+ISC_DCTRL_DVIEW_PACKED, 0x7f, false, false},
+};
+
+static int isc_clk_enable(struct clk_hw *hw)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+	u32 id = isc_clk->id;
+	struct regmap *regmap = isc_clk->regmap;
+	unsigned long flags;
+
+	dev_dbg(isc_clk->isc->dev, "ISC CLK: %s, div = %d, parent id = %d\n",
+		__func__, isc_clk->div, isc_clk->parent_id);
+
+	spin_lock_irqsave(isc_clk->lock, flags);
+
+	regmap_update_bits(regmap, ISC_CLKCFG,
+			   ISC_CLKCFG_DIV_MASK(id) | ISC_CLKCFG_SEL_MASK(id),
+			   (isc_clk->div << ISC_CLKCFG_DIV_SHIFT(id)) |
+			   (isc_clk->parent_id << ISC_CLKCFG_SEL_SHIFT(id)));
+
+	regmap_update_bits(regmap, ISC_CLKEN,
+			   ISC_CLKEN_EN_MASK(id),
+			   ISC_CLKEN_EN << ISC_CLKEN_EN_SHIFT(id));
+
+	spin_unlock_irqrestore(isc_clk->lock, flags);
+
+	return 0;
+}
+
+static void isc_clk_disable(struct clk_hw *hw)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+	u32 id = isc_clk->id;
+	unsigned long flags;
+
+	spin_lock_irqsave(isc_clk->lock, flags);
+
+	regmap_update_bits(isc_clk->regmap, ISC_CLKDIS,
+			   ISC_CLKDIS_DIS_MASK(id),
+			   ISC_CLKDIS_DIS << ISC_CLKDIS_DIS_SHIFT(id));
+
+	spin_unlock_irqrestore(isc_clk->lock, flags);
+}
+
+static int isc_clk_is_enabled(struct clk_hw *hw)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+	unsigned long flags;
+	u32 status;
+
+	spin_lock_irqsave(isc_clk->lock, flags);
+	regmap_read(isc_clk->regmap, ISC_CLKSR, &status);
+	spin_unlock_irqrestore(isc_clk->lock, flags);
+
+	return status & ISC_CLKSR_CLK_MASK(isc_clk->id) ? 1 : 0;
+}
+
+static unsigned long
+isc_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+
+	return DIV_ROUND_CLOSEST(parent_rate, isc_clk->div + 1);
+}
+
+static int isc_clk_determine_rate(struct clk_hw *hw,
+				  struct clk_rate_request *req)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+	long best_rate = -EINVAL;
+	int best_diff = -1;
+	unsigned int i, div;
+
+	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+		struct clk_hw *parent;
+		unsigned long parent_rate;
+
+		parent = clk_hw_get_parent_by_index(hw, i);
+		if (!parent)
+			continue;
+
+		parent_rate = clk_hw_get_rate(parent);
+		if (!parent_rate)
+			continue;
+
+		for (div = 1; div < ISC_CLK_MAX_DIV + 2; div++) {
+			unsigned long rate;
+			int diff;
+
+			rate = DIV_ROUND_CLOSEST(parent_rate, div);
+			diff = abs(req->rate - rate);
+
+			if (best_diff < 0 || best_diff > diff) {
+				best_rate = rate;
+				best_diff = diff;
+				req->best_parent_rate = parent_rate;
+				req->best_parent_hw = parent;
+			}
+
+			if (!best_diff || rate < req->rate)
+				break;
+		}
+
+		if (!best_diff)
+			break;
+	}
+
+	dev_dbg(isc_clk->isc->dev,
+		"ISC CLK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
+		__func__, best_rate,
+		__clk_get_name((req->best_parent_hw)->clk),
+		req->best_parent_rate);
+
+	if (best_rate < 0)
+		return best_rate;
+
+	req->rate = best_rate;
+
+	return 0;
+}
+
+static int isc_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+
+	if (index >= clk_hw_get_num_parents(hw))
+		return -EINVAL;
+
+	isc_clk->parent_id = index;
+
+	return 0;
+}
+
+static u8 isc_clk_get_parent(struct clk_hw *hw)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+
+	return isc_clk->parent_id;
+}
+
+static int isc_clk_set_rate(struct clk_hw *hw,
+			    unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+	u32 div;
+
+	if (!rate)
+		return -EINVAL;
+
+	div = DIV_ROUND_CLOSEST(parent_rate, rate);
+	if ((div > (ISC_CLK_MAX_DIV + 1)) || !div)
+		return -EINVAL;
+
+	isc_clk->div = div - 1;
+
+	return 0;
+}
+
+static const struct clk_ops isc_clk_ops = {
+	.enable		= isc_clk_enable,
+	.disable	= isc_clk_disable,
+	.is_enabled	= isc_clk_is_enabled,
+	.recalc_rate	= isc_clk_recalc_rate,
+	.determine_rate	= isc_clk_determine_rate,
+	.set_parent	= isc_clk_set_parent,
+	.get_parent	= isc_clk_get_parent,
+	.set_rate	= isc_clk_set_rate,
+};
+
+static int isc_clk_register(struct isc_device *isc, struct device_node *np)
+{
+	struct regmap *regmap = isc->regmap;
+	struct isc_clk *isc_clk;
+	struct clk_init_data init;
+	const char *clk_name = np->name;
+	const char **parent_names;
+	u32 id;
+	int num_parents, source_max, ret = 0;
+
+	if (of_property_read_u32(np, "reg", &id))
+		return -EINVAL;
+
+	switch (id) {
+	case ISC_ISPCK:
+		source_max = ISC_ISPCK_SOURCE_MAX;
+		break;
+	case ISC_MCK:
+		source_max = ISC_MCK_SOURCE_MAX;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	num_parents = of_clk_get_parent_count(np);
+	if (num_parents < 1 || num_parents > source_max)
+		return -EINVAL;
+
+	parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
+	if (!parent_names)
+		return -ENOMEM;
+
+	of_clk_parent_fill(np, parent_names, num_parents);
+
+	init.parent_names	= parent_names;
+	init.num_parents	= num_parents;
+	init.name		= clk_name;
+	init.ops		= &isc_clk_ops;
+	init.flags		= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+
+	isc_clk = &isc->isc_clks[id];
+	isc_clk->hw.init	= &init;
+	isc_clk->regmap		= regmap;
+	isc_clk->lock		= &isc->clk_lock;
+	isc_clk->id		= id;
+	isc_clk->isc		= isc;
+
+	isc_clk->clk = clk_register(NULL, &isc_clk->hw);
+	if (!IS_ERR(isc_clk->clk))
+		of_clk_add_provider(np, of_clk_src_simple_get, isc_clk->clk);
+	else {
+		dev_err(isc->dev, "%s: clock register fail\n", clk_name);
+		ret = PTR_ERR(isc_clk->clk);
+		goto free_parent_names;
+	}
+
+free_parent_names:
+	kfree(parent_names);
+	return ret;
+}
+
+static int isc_clk_init(struct isc_device *isc)
+{
+	struct device_node *np = of_get_child_by_name(isc->dev->of_node,
+						      "clk-in-isc");
+	struct device_node *childnp;
+	unsigned int i;
+	int ret;
+
+	if (!np) {
+		dev_err(isc->dev, "No clock node\n");
+		return -ENOENT;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(isc->isc_clks); i++)
+		isc->isc_clks[i].clk = ERR_PTR(-EINVAL);
+
+	spin_lock_init(&isc->clk_lock);
+	for_each_child_of_node(np, childnp) {
+		ret = isc_clk_register(isc, childnp);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void isc_clk_cleanup(struct isc_device *isc)
+{
+	struct device_node *np = of_get_child_by_name(isc->dev->of_node,
+						      "clk_in_isc");
+	struct device_node *childnp;
+	unsigned int i;
+
+	if (!np)
+		return;
+
+	for_each_child_of_node(np, childnp)
+		of_clk_del_provider(childnp);
+
+	for (i = 0; i < ARRAY_SIZE(isc->isc_clks); i++) {
+		struct isc_clk *isc_clk = &isc->isc_clks[i];
+
+		if (!IS_ERR(isc_clk->clk))
+			clk_unregister(isc_clk->clk);
+	}
+}
+
+static int isc_queue_setup(struct vb2_queue *vq,
+			   unsigned int *nbuffers, unsigned int *nplanes,
+			   unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct isc_device *isc = vb2_get_drv_priv(vq);
+	unsigned int size = isc->fmt.fmt.pix.sizeimage;
+
+	alloc_ctxs[0] = isc->alloc_ctx;
+
+	if (*nplanes)
+		return sizes[0] < size ? -EINVAL : 0;
+
+	*nplanes = 1;
+	sizes[0] = size;
+
+	return 0;
+}
+
+static int isc_buffer_prepare(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct isc_device *isc = vb2_get_drv_priv(vb->vb2_queue);
+	unsigned long size = isc->fmt.fmt.pix.sizeimage;
+
+	if (vb2_plane_size(vb, 0) < size) {
+		v4l2_err(&isc->v4l2_dev, "buffer too small (%lu < %lu)\n",
+			 vb2_plane_size(vb, 0), size);
+		return -EINVAL;
+	}
+
+	vb2_set_plane_payload(vb, 0, size);
+
+	vbuf->field = isc->fmt.fmt.pix.field;
+
+	return 0;
+}
+
+static inline void isc_start_dma(struct regmap *regmap,
+				 struct isc_buffer *frm, u32 dview)
+{
+	dma_addr_t addr;
+
+	addr = vb2_dma_contig_plane_dma_addr(&frm->vb.vb2_buf, 0);
+
+	regmap_write(regmap, ISC_DCTRL, dview | ISC_DCTRL_IE_IS);
+	regmap_write(regmap, ISC_DAD0, addr);
+	regmap_update_bits(regmap, ISC_CTRLEN,
+			   ISC_CTRLEN_CAPTURE_MASK, ISC_CTRLEN_CAPTURE);
+}
+
+static inline bool sensor_is_preferred(const u32 sensor_preferred,
+				       const struct isc_format *isc_fmt)
+{
+	if ((sensor_preferred && isc_fmt->sd_support) ||
+	    !isc_fmt->isc_support)
+		return true;
+	else
+		return false;
+}
+
+static void isc_set_pipeline(struct regmap *regmap, u32 pipeline)
+{
+	const struct reg_mask *reg = &pipeline_regs[0];
+	u32 val;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(pipeline_regs); i++) {
+		if (pipeline & BIT(i))
+			val = reg->mask;
+		else
+			val = 0;
+
+		regmap_update_bits(regmap, reg->reg, reg->mask, val);
+
+		reg++;
+	}
+}
+
+static int isc_configure(struct isc_device *isc)
+{
+	struct regmap *regmap = isc->regmap;
+	const struct isc_format *current_fmt = isc->current_fmt;
+	struct isc_subdev_entity *subdev = isc->current_subdev;
+	u32 pipeline, val, mask;
+	int counter = 10;
+
+	if (sensor_is_preferred(isc->sensor_preferred, current_fmt)) {
+		val = current_fmt->reg_sd_bps;
+		pipeline = 0x0;
+	} else {
+		val = current_fmt->reg_isc_bps;
+		pipeline = current_fmt->pipeline;
+
+		regmap_update_bits(regmap, ISC_WB_CFG, ISC_WB_CFG_BAYCFG_MASK,
+				   current_fmt->reg_wb_cfg);
+		regmap_update_bits(regmap, ISC_CFA_CFG, ISC_CFA_CFG_BAY_MASK,
+				   current_fmt->reg_cfa_cfg);
+	}
+
+	val |= subdev->pfe_cfg0 | ISC_PFE_CFG0_MODE_PROGRESSIVE;
+	mask = ISC_PFE_CFG0_BPS_MASK | ISC_PFE_CFG0_HPOL_MASK |
+	       ISC_PFE_CFG0_VPOL_MASK | ISC_PFE_CFG0_PPOL_MASK |
+	       ISC_PFE_CFG0_MODE_MASK;
+
+	regmap_update_bits(regmap, ISC_PFE_CFG0, mask, val);
+
+	regmap_update_bits(regmap, ISC_RLP_CFG, ISC_RLP_CFG_MODE_MASK,
+			   current_fmt->reg_rlp_mode);
+
+	regmap_update_bits(regmap, ISC_DCFG, ISC_DCFG_IMODE_MASK,
+			   current_fmt->reg_dcfg_imode);
+
+	isc_set_pipeline(regmap, pipeline);
+
+	/* Update profile */
+	regmap_update_bits(regmap, ISC_CTRLEN,
+			   ISC_CTRLEN_UPPRO_MASK, ISC_CTRLEN_UPPRO);
+
+	regmap_read(regmap, ISC_CTRLSR, &val);
+	while ((val & ISC_CTRLSR_UPPRO) && counter--) {
+		usleep_range(1000, 2000);
+		regmap_read(regmap, ISC_CTRLSR, &val);
+	}
+
+	if (counter < 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int isc_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct isc_device *isc = vb2_get_drv_priv(vq);
+	struct regmap *regmap = isc->regmap;
+	struct isc_buffer *buf;
+	unsigned long flags;
+	int ret;
+	u32 val;
+
+	/* Enable stream on the sub device */
+	ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 1);
+	if (ret && ret != -ENOIOCTLCMD) {
+		v4l2_err(&isc->v4l2_dev, "stream on failed in subdev\n");
+		goto err;
+	}
+
+	ret = isc_configure(isc);
+	if (unlikely(ret))
+		goto err;
+
+	/* Clean the interrupt status register */
+	regmap_read(regmap, ISC_INTSR, &val);
+
+	/* Enable DMA interrupt */
+	regmap_update_bits(regmap, ISC_INTEN,
+			   ISC_INTEN_DDONE_MASK, ISC_INTEN_DDONE);
+
+	spin_lock_irqsave(&isc->dma_queue_lock, flags);
+
+	isc->sequence = 0;
+	isc->stop = false;
+	reinit_completion(&isc->comp);
+
+	isc->cur_frm = list_first_entry(&isc->dma_queue,
+					struct isc_buffer, list);
+	list_del(&isc->cur_frm->list);
+
+	isc_start_dma(regmap, isc->cur_frm, isc->current_fmt->reg_dctrl_dview);
+
+	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
+
+	return 0;
+
+err:
+	spin_lock_irqsave(&isc->dma_queue_lock, flags);
+	list_for_each_entry(buf, &isc->dma_queue, list)
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
+	INIT_LIST_HEAD(&isc->dma_queue);
+	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
+
+	return ret;
+}
+
+static void isc_stop_streaming(struct vb2_queue *vq)
+{
+	struct isc_device *isc = vb2_get_drv_priv(vq);
+	unsigned long flags;
+	struct isc_buffer *buf;
+	int ret;
+
+	isc->stop = true;
+
+	/* Wait until the end of the current frame */
+	if (isc->cur_frm && !wait_for_completion_timeout(&isc->comp, 5 * HZ))
+		v4l2_err(&isc->v4l2_dev,
+			 "Timeout waiting for end of the capture\n");
+
+	/* Disable DMA interrupt */
+	regmap_update_bits(isc->regmap, ISC_INTDIS,
+			   ISC_INTDIS_DDONE_MASK, ISC_INTDIS_DDONE);
+
+	/* Disable stream on the sub device */
+	ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 0);
+	if (ret && ret != -ENOIOCTLCMD)
+		v4l2_err(&isc->v4l2_dev, "stream off failed in subdev\n");
+
+	/* Release all active buffers */
+	spin_lock_irqsave(&isc->dma_queue_lock, flags);
+	if (unlikely(isc->cur_frm)) {
+		vb2_buffer_done(&isc->cur_frm->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
+		isc->cur_frm = NULL;
+	}
+	list_for_each_entry(buf, &isc->dma_queue, list)
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+	INIT_LIST_HEAD(&isc->dma_queue);
+	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
+}
+
+static void isc_buffer_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct isc_buffer *buf = container_of(vbuf, struct isc_buffer, vb);
+	struct isc_device *isc = vb2_get_drv_priv(vb->vb2_queue);
+	unsigned long flags;
+
+	spin_lock_irqsave(&isc->dma_queue_lock, flags);
+	list_add_tail(&buf->list, &isc->dma_queue);
+	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
+}
+
+static struct vb2_ops isc_vb2_ops = {
+	.queue_setup		= isc_queue_setup,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
+	.buf_prepare		= isc_buffer_prepare,
+	.start_streaming	= isc_start_streaming,
+	.stop_streaming		= isc_stop_streaming,
+	.buf_queue		= isc_buffer_queue,
+};
+
+static int isc_querycap(struct file *file, void *priv,
+			struct v4l2_capability *cap)
+{
+	struct isc_device *isc = video_drvdata(file);
+
+	strcpy(cap->driver, ATMEL_ISC_NAME);
+	strcpy(cap->card, "Atmel Image Sensor Controller");
+	snprintf(cap->bus_info, sizeof(cap->bus_info),
+		 "platform:%s", isc->v4l2_dev.name);
+
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+	return 0;
+}
+
+static int isc_enum_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_fmtdesc *f)
+{
+	struct isc_device *isc = video_drvdata(file);
+	u32 index = f->index;
+
+	if (index >= isc->num_user_formats)
+		return -EINVAL;
+
+	f->pixelformat = isc->user_formats[index]->fourcc;
+
+	return 0;
+}
+
+static int isc_g_fmt_vid_cap(struct file *file, void *priv,
+			     struct v4l2_format *fmt)
+{
+	struct isc_device *isc = video_drvdata(file);
+
+	*fmt = isc->fmt;
+
+	return 0;
+}
+
+static struct isc_format *find_format_by_fourcc(struct isc_device *isc,
+						unsigned int fourcc)
+{
+	unsigned int num_formats = isc->num_user_formats;
+	struct isc_format *fmt;
+	unsigned int i;
+
+	for (i = 0; i < num_formats; i++) {
+		fmt = isc->user_formats[i];
+		if (fmt->fourcc == fourcc)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f,
+		       struct isc_format **current_fmt, u32 *code)
+{
+	struct isc_format *isc_fmt;
+	struct v4l2_pix_format *pixfmt = &f->fmt.pix;
+	struct v4l2_subdev_format format = {
+		.which = V4L2_SUBDEV_FORMAT_TRY,
+	};
+	u32 mbus_code;
+	int ret;
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	isc_fmt = find_format_by_fourcc(isc, pixfmt->pixelformat);
+	if (!isc_fmt) {
+		v4l2_warn(&isc->v4l2_dev, "Format 0x%x not found\n",
+			  pixfmt->pixelformat);
+		return -EINVAL;
+	}
+
+	/* Limit to Atmel ISC hardware capabilities */
+	if (pixfmt->width > ISC_MAX_SUPPORT_WIDTH)
+		pixfmt->width = ISC_MAX_SUPPORT_WIDTH;
+	if (pixfmt->height > ISC_MAX_SUPPORT_HEIGHT)
+		pixfmt->height = ISC_MAX_SUPPORT_HEIGHT;
+
+	if (sensor_is_preferred(isc->sensor_preferred, isc_fmt))
+		mbus_code = isc_fmt->sd_mbus_code;
+	else
+		mbus_code = isc_fmt->isc_mbus_code;
+
+	v4l2_fill_mbus_format(&format.format, pixfmt, mbus_code);
+	ret = v4l2_subdev_call(isc->current_subdev->sd, pad, set_fmt,
+			       isc->current_subdev->config, &format);
+	if (ret < 0)
+		return ret;
+
+	v4l2_fill_pix_format(pixfmt, &format.format);
+
+	switch (pixfmt->field) {
+	case V4L2_FIELD_ANY:
+	case V4L2_FIELD_NONE:
+		break;
+	default:
+		v4l2_err(&isc->v4l2_dev, "Field type %d unsupported.\n",
+			 pixfmt->field);
+		return -EINVAL;
+	}
+
+	pixfmt->bytesperline = pixfmt->width * isc_fmt->bpp;
+	pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
+
+	if (current_fmt)
+		*current_fmt = isc_fmt;
+
+	if (code)
+		*code = mbus_code;
+
+	return 0;
+}
+
+static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f)
+{
+	struct v4l2_subdev_format format = {
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+	};
+	struct isc_format *current_fmt;
+	int ret;
+	u32 mbus_code;
+
+	ret = isc_try_fmt(isc, f, &current_fmt, &mbus_code);
+	if (ret)
+		return ret;
+
+	v4l2_fill_mbus_format(&format.format, &f->fmt.pix, mbus_code);
+	ret = v4l2_subdev_call(isc->current_subdev->sd, pad,
+			       set_fmt, NULL, &format);
+	if (ret < 0)
+		return ret;
+
+	isc->fmt = *f;
+	isc->current_fmt = current_fmt;
+
+	return 0;
+}
+
+static int isc_s_fmt_vid_cap(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct isc_device *isc = video_drvdata(file);
+
+	if (vb2_is_streaming(&isc->vb2_vidq))
+		return -EBUSY;
+
+	return isc_set_fmt(isc, f);
+}
+
+static int isc_try_fmt_vid_cap(struct file *file, void *priv,
+			       struct v4l2_format *f)
+{
+	struct isc_device *isc = video_drvdata(file);
+
+	return isc_try_fmt(isc, f, NULL, NULL);
+}
+
+static int isc_enum_input(struct file *file, void *priv,
+			  struct v4l2_input *inp)
+{
+	if (inp->index != 0)
+		return -EINVAL;
+
+	inp->type = V4L2_INPUT_TYPE_CAMERA;
+	inp->std = 0;
+	strcpy(inp->name, "Camera");
+
+	return 0;
+}
+
+static int isc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	*i = 0;
+
+	return 0;
+}
+
+static int isc_s_input(struct file *file, void *priv, unsigned int i)
+{
+	if (i > 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int isc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct isc_device *isc = video_drvdata(file);
+	int ret;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	ret = v4l2_subdev_call(isc->current_subdev->sd, video, g_parm, a);
+	if (ret == -ENOIOCTLCMD)
+		ret = 0;
+
+	return ret;
+}
+
+static int isc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct isc_device *isc = video_drvdata(file);
+	int ret;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_parm, a);
+	if (ret == -ENOIOCTLCMD)
+		ret = 0;
+
+	return ret;
+}
+
+static const struct v4l2_ioctl_ops isc_ioctl_ops = {
+	.vidioc_querycap		= isc_querycap,
+	.vidioc_enum_fmt_vid_cap	= isc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap		= isc_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap		= isc_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap		= isc_try_fmt_vid_cap,
+
+	.vidioc_enum_input		= isc_enum_input,
+	.vidioc_g_input			= isc_g_input,
+	.vidioc_s_input			= isc_s_input,
+
+	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
+	.vidioc_expbuf			= vb2_ioctl_expbuf,
+	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
+	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
+
+	.vidioc_g_parm			= isc_g_parm,
+	.vidioc_s_parm			= isc_s_parm,
+};
+
+static int isc_set_default_fmt(struct isc_device *isc)
+{
+	u32 index = isc->num_user_formats - 1;
+	struct v4l2_format f = {
+		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+		.fmt.pix = {
+			.width		= VGA_WIDTH,
+			.height		= VGA_HEIGHT,
+			.field		= V4L2_FIELD_ANY,
+			.pixelformat	= isc->user_formats[index]->fourcc,
+		},
+	};
+
+	return isc_set_fmt(isc, &f);
+}
+
+static int isc_open(struct file *file)
+{
+	struct isc_device *isc = video_drvdata(file);
+	struct v4l2_subdev *sd = isc->current_subdev->sd;
+	int ret;
+
+	if (mutex_lock_interruptible(&isc->lock))
+		return -ERESTARTSYS;
+
+	ret = v4l2_fh_open(file);
+	if (ret < 0)
+		goto unlock;
+
+	ret = v4l2_subdev_call(sd, core, s_power, 1);
+	if (ret < 0 && ret != -ENOIOCTLCMD)
+		goto unlock;
+
+	ret = clk_prepare_enable(isc->hclock);
+	if (ret)
+		goto unlock;
+
+	ret = clk_prepare_enable(isc->ispck);
+	if (ret)
+		goto unlock;
+
+	ret = isc_set_default_fmt(isc);
+	if (ret)
+		goto unlock;
+
+	/* Disable all the interrupts */
+	regmap_write(isc->regmap, ISC_INTDIS, (u32)~0UL);
+
+unlock:
+	mutex_unlock(&isc->lock);
+	return ret;
+}
+
+static int isc_release(struct file *file)
+{
+	struct isc_device *isc = video_drvdata(file);
+	struct v4l2_subdev *sd = isc->current_subdev->sd;
+	int ret;
+
+	mutex_lock(&isc->lock);
+
+	ret = _vb2_fop_release(file, NULL);
+
+	v4l2_subdev_call(sd, core, s_power, 0);
+
+	clk_disable_unprepare(isc->ispck);
+	clk_disable_unprepare(isc->hclock);
+
+	mutex_unlock(&isc->lock);
+
+	return ret;
+}
+
+static const struct v4l2_file_operations isc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= isc_open,
+	.release	= isc_release,
+	.unlocked_ioctl	= video_ioctl2,
+	.read		= vb2_fop_read,
+	.mmap		= vb2_fop_mmap,
+	.poll		= vb2_fop_poll,
+};
+
+static irqreturn_t isc_interrupt(int irq, void *dev_id)
+{
+	struct isc_device *isc = (struct isc_device *)dev_id;
+	struct regmap *regmap = isc->regmap;
+	u32 isc_intsr, isc_intmask, pending;
+	irqreturn_t ret = IRQ_NONE;
+
+	spin_lock(&isc->dma_queue_lock);
+
+	regmap_read(regmap, ISC_INTSR, &isc_intsr);
+	regmap_read(regmap, ISC_INTMASK, &isc_intmask);
+
+	pending = isc_intsr & isc_intmask;
+
+	if (likely(pending & ISC_INTSR_DDONE)) {
+		if (isc->cur_frm) {
+			struct vb2_v4l2_buffer *vbuf = &isc->cur_frm->vb;
+			struct vb2_buffer *vb = &vbuf->vb2_buf;
+
+			vb->timestamp = ktime_get_ns();
+			vbuf->sequence = isc->sequence++;
+			vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+			isc->cur_frm = NULL;
+		}
+
+		if (!list_empty(&isc->dma_queue) && !isc->stop) {
+			isc->cur_frm = list_first_entry(&isc->dma_queue,
+						     struct isc_buffer, list);
+			list_del(&isc->cur_frm->list);
+
+			isc_start_dma(regmap, isc->cur_frm,
+				      isc->current_fmt->reg_dctrl_dview);
+		}
+
+		if (isc->stop)
+			complete(&isc->comp);
+
+		ret = IRQ_HANDLED;
+	}
+
+	spin_unlock(&isc->dma_queue_lock);
+
+	return ret;
+}
+
+static int isc_async_bound(struct v4l2_async_notifier *notifier,
+			   struct v4l2_subdev *subdev,
+			   struct v4l2_async_subdev *asd)
+{
+	struct isc_device *isc = container_of(notifier->v4l2_dev,
+					      struct isc_device, v4l2_dev);
+	struct isc_subdev_entity *subdev_entity =
+		container_of(notifier, struct isc_subdev_entity, notifier);
+
+	if (video_is_registered(&isc->video_dev)) {
+		v4l2_err(&isc->v4l2_dev, "only supports one sub-device.\n");
+		return -EBUSY;
+	}
+
+	subdev_entity->sd = subdev;
+
+	return 0;
+}
+
+static void isc_async_unbind(struct v4l2_async_notifier *notifier,
+			     struct v4l2_subdev *subdev,
+			     struct v4l2_async_subdev *asd)
+{
+	struct isc_device *isc = container_of(notifier->v4l2_dev,
+					      struct isc_device, v4l2_dev);
+
+	video_unregister_device(&isc->video_dev);
+	vb2_dma_contig_cleanup_ctx(isc->alloc_ctx);
+	isc->alloc_ctx = NULL;
+	if (isc->current_subdev->config)
+		v4l2_subdev_free_pad_config(isc->current_subdev->config);
+}
+
+static struct isc_format *find_format_by_code(unsigned int code, int *index)
+{
+	struct isc_format *fmt = &isc_formats[0];
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(isc_formats); i++) {
+		if (fmt->sd_mbus_code == code) {
+			*index = i;
+			return fmt;
+		}
+
+		fmt++;
+	}
+
+	return NULL;
+}
+
+static int isc_formats_init(struct isc_device *isc)
+{
+	struct isc_format *fmt;
+	struct v4l2_subdev *subdev = isc->current_subdev->sd;
+	int num_fmts, i, j;
+	struct v4l2_subdev_mbus_code_enum mbus_code = {
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+	};
+
+	fmt = &isc_formats[0];
+	for (i = 0; i < ARRAY_SIZE(isc_formats); i++) {
+		fmt->isc_support = false;
+		fmt->sd_support = false;
+
+		fmt++;
+	}
+
+	while (!v4l2_subdev_call(subdev, pad, enum_mbus_code,
+	       NULL, &mbus_code)) {
+		mbus_code.index++;
+		fmt = find_format_by_code(mbus_code.code, &i);
+		if (!fmt)
+			continue;
+
+		fmt->sd_support = true;
+
+		if (i <= RAW_FMT_INDEX_END) {
+			for (j = ISC_FMT_INDEX_START;
+			     j <= ISC_FMT_INDEX_END; j++) {
+				isc_formats[j].isc_support = true;
+				isc_formats[j].isc_mbus_code = mbus_code.code;
+				isc_formats[j].reg_isc_bps = fmt->reg_sd_bps;
+				isc_formats[j].reg_wb_cfg = fmt->reg_wb_cfg;
+				isc_formats[j].reg_cfa_cfg = fmt->reg_cfa_cfg;
+			}
+		}
+	}
+
+	fmt = &isc_formats[0];
+	for (i = 0, num_fmts = 0; i < ARRAY_SIZE(isc_formats); i++) {
+		if (fmt->isc_support || fmt->sd_support)
+			num_fmts++;
+
+		fmt++;
+	}
+
+	if (!num_fmts)
+		return -ENXIO;
+
+	isc->num_user_formats = num_fmts;
+	isc->user_formats = devm_kcalloc(isc->dev,
+					 num_fmts, sizeof(struct isc_format *),
+					 GFP_KERNEL);
+	if (!isc->user_formats) {
+		v4l2_err(&isc->v4l2_dev, "could not allocate memory\n");
+		return -ENOMEM;
+	}
+
+	fmt = &isc_formats[0];
+	for (i = 0, j = 0; i < ARRAY_SIZE(isc_formats); i++) {
+		if (fmt->isc_support || fmt->sd_support)
+			isc->user_formats[j++] = fmt;
+
+		fmt++;
+	}
+
+	return 0;
+}
+
+static int isc_async_complete(struct v4l2_async_notifier *notifier)
+{
+	struct isc_device *isc = container_of(notifier->v4l2_dev,
+					      struct isc_device, v4l2_dev);
+	struct isc_subdev_entity *sd_entity;
+	struct video_device *vdev = &isc->video_dev;
+	struct vb2_queue *q = &isc->vb2_vidq;
+	int ret;
+
+	isc->current_subdev = container_of(notifier,
+					   struct isc_subdev_entity, notifier);
+	sd_entity = isc->current_subdev;
+
+	mutex_init(&isc->lock);
+	init_completion(&isc->comp);
+
+	/* Initialize videobuf2 queue */
+	isc->alloc_ctx = vb2_dma_contig_init_ctx(isc->dev);
+	if (IS_ERR(isc->alloc_ctx)) {
+		ret = PTR_ERR(isc->alloc_ctx);
+		v4l2_err(&isc->v4l2_dev,
+			 "Failed to get the context: %d\n", ret);
+		return ret;
+	}
+
+	q->type			= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes		= VB2_MMAP;
+	q->drv_priv		= isc;
+	q->buf_struct_size	= sizeof(struct isc_buffer);
+	q->ops			= &isc_vb2_ops;
+	q->mem_ops		= &vb2_dma_contig_memops;
+	q->timestamp_flags	= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock			= &isc->lock;
+	q->min_buffers_needed	= 1;
+
+	ret = vb2_queue_init(q);
+	if (ret < 0) {
+		v4l2_err(&isc->v4l2_dev,
+			 "vb2_queue_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	/* Init video dma queues */
+	INIT_LIST_HEAD(&isc->dma_queue);
+	spin_lock_init(&isc->dma_queue_lock);
+
+	/* Register video device */
+	strlcpy(vdev->name, ATMEL_ISC_NAME, sizeof(vdev->name));
+	vdev->release		= video_device_release_empty;
+	vdev->fops		= &isc_fops;
+	vdev->ioctl_ops		= &isc_ioctl_ops;
+	vdev->v4l2_dev		= &isc->v4l2_dev;
+	vdev->vfl_dir		= VFL_DIR_RX;
+	vdev->queue		= q;
+	vdev->lock		= &isc->lock;
+	vdev->ctrl_handler	= isc->current_subdev->sd->ctrl_handler;
+	video_set_drvdata(vdev, isc);
+
+	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	if (ret < 0) {
+		v4l2_err(&isc->v4l2_dev,
+			 "video_register_device failed: %d\n", ret);
+		return ret;
+	}
+
+	sd_entity->config = v4l2_subdev_alloc_pad_config(sd_entity->sd);
+	if (sd_entity->config == NULL)
+		return -ENOMEM;
+
+	ret = isc_formats_init(isc);
+	if (ret < 0) {
+		v4l2_err(&isc->v4l2_dev,
+			 "Init format failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void isc_subdev_cleanup(struct isc_device *isc)
+{
+	struct isc_subdev_entity *subdev_entity;
+
+	list_for_each_entry(subdev_entity, &isc->subdev_entities, list)
+		v4l2_async_notifier_unregister(&subdev_entity->notifier);
+
+	INIT_LIST_HEAD(&isc->subdev_entities);
+}
+
+static int isc_parse_dt(struct device *dev, struct isc_device *isc)
+{
+	struct device_node *np = dev->of_node;
+	struct device_node *epn = NULL, *rem;
+	struct v4l2_of_endpoint v4l2_epn;
+	struct isc_subdev_entity *subdev_entity;
+	unsigned int flags;
+	int ret;
+
+	ret = of_property_read_u32(np, "atmel,sensor-preferred",
+				   &isc->sensor_preferred);
+	if (ret)
+		isc->sensor_preferred = 1;
+
+	INIT_LIST_HEAD(&isc->subdev_entities);
+
+	for (; ;) {
+		epn = of_graph_get_next_endpoint(np, epn);
+		if (!epn)
+			break;
+
+		rem = of_graph_get_remote_port_parent(epn);
+		if (!rem) {
+			dev_notice(dev, "Remote device at %s not found\n",
+				   of_node_full_name(epn));
+			continue;
+		}
+
+		ret = v4l2_of_parse_endpoint(epn, &v4l2_epn);
+		if (ret) {
+			of_node_put(rem);
+			ret = -EINVAL;
+			dev_err(dev, "Could not parse the endpoint\n");
+			break;
+		}
+
+		subdev_entity = devm_kzalloc(dev,
+					  sizeof(*subdev_entity), GFP_KERNEL);
+		if (subdev_entity == NULL) {
+			of_node_put(rem);
+			ret = -ENOMEM;
+			break;
+		}
+
+		subdev_entity->asd = devm_kzalloc(dev,
+				     sizeof(*subdev_entity->asd), GFP_KERNEL);
+		if (subdev_entity->asd == NULL) {
+			of_node_put(rem);
+			ret = -ENOMEM;
+			break;
+		}
+
+		flags = v4l2_epn.bus.parallel.flags;
+
+		if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+			subdev_entity->pfe_cfg0 = ISC_PFE_CFG0_HPOL_LOW;
+		else
+			subdev_entity->pfe_cfg0 = ISC_PFE_CFG0_HPOL_HIGH;
+
+		if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_VPOL_LOW;
+		else
+			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_VPOL_HIGH;
+
+		if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW;
+		else
+			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_HIGH;
+
+		subdev_entity->asd->match_type = V4L2_ASYNC_MATCH_OF;
+		subdev_entity->asd->match.of.node = rem;
+		list_add_tail(&subdev_entity->list, &isc->subdev_entities);
+	}
+
+	of_node_put(epn);
+	return ret;
+}
+
+/* regmap configuration */
+#define ATMEL_ISC_REG_MAX    0xbfc
+static const struct regmap_config isc_regmap_config = {
+	.reg_bits       = 32,
+	.reg_stride     = 4,
+	.val_bits       = 32,
+	.max_register	= ATMEL_ISC_REG_MAX,
+};
+
+static int atmel_isc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct isc_device *isc;
+	struct resource *res;
+	void __iomem *io_base;
+	struct isc_subdev_entity *subdev_entity;
+	int irq;
+	int ret;
+
+	isc = devm_kzalloc(dev, sizeof(*isc), GFP_KERNEL);
+	if (!isc)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, isc);
+	isc->dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	io_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(io_base))
+		return PTR_ERR(io_base);
+
+	isc->regmap = devm_regmap_init_mmio(dev, io_base, &isc_regmap_config);
+	if (IS_ERR(isc->regmap)) {
+		ret = PTR_ERR(isc->regmap);
+		dev_err(dev, "failed to init register map: %d\n", ret);
+		return ret;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (IS_ERR_VALUE(irq)) {
+		ret = irq;
+		dev_err(dev, "failed to get irq: %d\n", ret);
+		return ret;
+	}
+
+	ret = devm_request_irq(dev, irq, isc_interrupt, 0,
+			       ATMEL_ISC_NAME, isc);
+	if (ret < 0) {
+		dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
+			irq, ret);
+		return ret;
+	}
+
+	isc->hclock = devm_clk_get(dev, "hclock");
+	if (IS_ERR(isc->hclock)) {
+		ret = PTR_ERR(isc->hclock);
+		dev_err(dev, "failed to get hclock: %d\n", ret);
+		return ret;
+	}
+
+	ret = isc_clk_init(isc);
+	if (ret) {
+		dev_err(dev, "failed to init isc clock: %d\n", ret);
+		goto clean_isc_clk;
+	}
+
+	isc->ispck = devm_clk_get(dev, "ispck");
+	if (IS_ERR(isc->ispck)) {
+		ret = PTR_ERR(isc->ispck);
+		dev_err(dev, "failed to get isc_ispck: %d\n", ret);
+		goto clean_isc_clk;
+	}
+
+	/* ispck should be greater or equal to hclock */
+	ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock));
+	if (ret) {
+		dev_err(dev, "failed to set ispck rate: %d\n", ret);
+		goto clean_isc_clk;
+	}
+
+	ret = v4l2_device_register(dev, &isc->v4l2_dev);
+	if (ret) {
+		dev_err(dev, "unable to register v4l2 device.\n");
+		goto clean_isc_clk;
+	}
+
+	ret = isc_parse_dt(dev, isc);
+	if (ret) {
+		dev_err(dev, "fail to parse device tree\n");
+		goto unregister_v4l2_device;
+	}
+
+	if (list_empty(&isc->subdev_entities)) {
+		dev_err(dev, "no subdev found\n");
+		goto unregister_v4l2_device;
+	}
+
+	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
+		subdev_entity->notifier.subdevs = &subdev_entity->asd;
+		subdev_entity->notifier.num_subdevs = 1;
+		subdev_entity->notifier.bound = isc_async_bound;
+		subdev_entity->notifier.unbind = isc_async_unbind;
+		subdev_entity->notifier.complete = isc_async_complete;
+
+		ret = v4l2_async_notifier_register(&isc->v4l2_dev,
+						   &subdev_entity->notifier);
+		if (ret) {
+			dev_err(dev, "fail to register async notifier\n");
+			goto cleanup_subdev;
+		}
+
+		if (video_is_registered(&isc->video_dev))
+			break;
+	}
+
+	return 0;
+
+cleanup_subdev:
+	isc_subdev_cleanup(isc);
+
+unregister_v4l2_device:
+	v4l2_device_unregister(&isc->v4l2_dev);
+
+clean_isc_clk:
+	isc_clk_cleanup(isc);
+
+	return ret;
+}
+
+static int atmel_isc_remove(struct platform_device *pdev)
+{
+	struct isc_device *isc = platform_get_drvdata(pdev);
+
+	isc_subdev_cleanup(isc);
+
+	v4l2_device_unregister(&isc->v4l2_dev);
+
+	isc_clk_cleanup(isc);
+
+	return 0;
+}
+
+static const struct of_device_id atmel_isc_of_match[] = {
+	{ .compatible = "atmel,sama5d2-isc" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, atmel_isc_of_match);
+
+static struct platform_driver atmel_isc_driver = {
+	.probe	= atmel_isc_probe,
+	.remove	= atmel_isc_remove,
+	.driver	= {
+		.name = ATMEL_ISC_NAME,
+		.of_match_table = of_match_ptr(atmel_isc_of_match),
+	},
+};
+
+module_platform_driver(atmel_isc_driver);
+
+MODULE_AUTHOR("Songjun Wu <songjun.wu at atmel.com>");
+MODULE_DESCRIPTION("The V4L2 driver for Atmel-ISC");
+MODULE_LICENSE("GPL v2");
+MODULE_SUPPORTED_DEVICE("video");
-- 
2.7.4



From songjun.wu at atmel.com  Wed May 18 00:46:29 2016
From: songjun.wu at atmel.com (Songjun Wu)
Date: Wed, 18 May 2016 15:46:29 +0800
Subject: [PATCH v2 2/2] [media] atmel-isc: DT binding for Image Sensor
 Controller driver
In-Reply-To: <1463557590-29318-1-git-send-email-songjun.wu@atmel.com>
References: <1463557590-29318-1-git-send-email-songjun.wu@atmel.com>
Message-ID: <1463557590-29318-3-git-send-email-songjun.wu@atmel.com>

DT binding documentation for ISC driver.

Signed-off-by: Songjun Wu <songjun.wu at atmel.com>
---

Changes in v2:
- Remove the unit address of the endpoint.
- Add the unit address to the clock node.
- Avoid using underscores in node names.
- Drop the "0x" in the unit address of the i2c node.
- Modify the description of "atmel,sensor-preferred".
- Add the description for the ISC internal clock.

 .../devicetree/bindings/media/atmel-isc.txt        | 100 +++++++++++++++++++++
 1 file changed, 100 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/atmel-isc.txt

diff --git a/Documentation/devicetree/bindings/media/atmel-isc.txt b/Documentation/devicetree/bindings/media/atmel-isc.txt
new file mode 100644
index 0000000..9e65395
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/atmel-isc.txt
@@ -0,0 +1,100 @@
+Atmel Image Sensor Controller (ISC)
+----------------------------------------------
+
+Required properties for ISC:
+- compatible
+	Must be "atmel,sama5d2-isc"
+- reg
+	Physical base address and length of the registers set for the device;
+- interrupts
+	Should contain IRQ line for the ISC;
+- clocks
+	List of clock specifiers, corresponding to entries in
+	the clock-names property;
+	Please refer to clock-bindings.txt.
+- clock-names
+	Required elements: "hclock", "ispck".
+- pinctrl-names, pinctrl-0
+	Please refer to pinctrl-bindings.txt.
+- clk-in-isc
+	ISC internal clock node, it includes two clock nodes,
+	isc-ispck and isc-mck.
+- atmel,sensor-preferred
+	ISC may convert the raw format to the specified format when the sensor
+	outputs the raw format, and the sensor may output the specified format
+	directly. If sensor is preferred to output the specified format
+	directly, the value should be 1 (1-preferred, 0-not).
+	The default value is 1.
+
+ISC supports a single port node with parallel bus. It should contain one
+'port' child node with child 'endpoint' node. Please refer to the bindings
+defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Required properties for the ISC internal clocks:
+- #address-cells
+	should be 1 (reg is used to encode clk id).
+- #size-cells
+	should be 0 (reg is used to encode clk id).
+- name
+	device tree node describing a ISC internal clock.
+	* #clock-cells: from common clock binding; should be set to 0.
+	* reg: clock id, there are two values,
+	       <0> is ISP clock, <1> is master clock.
+	* clocks: shall be the isc internal clock source phandles.
+		  e.g. clocks = <&isc_clk>, <&iscck>, <&isc_gclk>;
+
+Example:
+isc: isc at f0008000 {
+	compatible = "atmel,sama5d2-isc";
+	reg = <0xf0008000 0x4000>;
+	interrupts = <46 IRQ_TYPE_LEVEL_HIGH 5>;
+	clocks = <&isc_clk>, <&isc_ispck>;
+	clock-names = "hclock", "ispck";
+	atmel,sensor-preferred = <1>;
+
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		isc_0: endpoint {
+			remote-endpoint = <&ov7740_0>;
+			hsync-active = <1>;
+			vsync-active = <0>;
+			pclk-sample = <1>;
+		};
+	};
+
+	clk-in-isc {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		isc_ispck: isc-ispck at 0 {
+			#clock-cells = <0>;
+			reg = <0>;
+			clocks = <&isc_clk>, <&iscck>;
+		};
+
+		isc_mck: isc-mck at 1 {
+			#clock-cells = <0>;
+			reg = <1>;
+			clocks = <&isc_clk>, <&iscck>, <&isc_gclk>;
+		};
+	};
+};
+
+i2c1: i2c at fc028000 {
+	ov7740: camera at 21 {
+	compatible = "ovti,ov7740";
+	reg = <0x21>;
+
+	clocks = <&isc_mck>;
+	clock-names = "xvclk";
+	assigned-clocks = <&isc_mck>;
+	assigned-clock-rates = <24000000>;
+
+	port {
+		ov7740_0: endpoint {
+			remote-endpoint = <&isc_0>;
+		};
+	};
+};
-- 
2.7.4



From m.gardet at overkiz.com  Wed May 18 01:04:35 2016
From: m.gardet at overkiz.com (Mickael GARDET)
Date: Wed, 18 May 2016 10:04:35 +0200
Subject: at91 slow clock with an external crystal (on Atmel SAM9G25)
Message-ID: <9cf2f9be-7f76-ca65-f2cf-ca0d20de6d2f@overkiz.com>

Hi,

I have one question about usage of slow clock with an external crystal 
(on Atmel SAM9G25).

All work fine If I set CONFIG_SCLK=y in at91bootstrap but we wouldn't 
update at91bootstrap.

If I force usage of external crystal (like the enclosed patch) it work 
for me but what's the recommended way to do this ?

My kernel version is 4.1.13.

Best regards.
Mickael GARDET


-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0003-force_external_osc.patch
Type: text/x-patch
Size: 2077 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160518/2a4552b7/attachment.bin>

From hdegoede at redhat.com  Wed May 18 01:13:52 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Wed, 18 May 2016 10:13:52 +0200
Subject: [PATCH 0/6] ARM: dts: sun5i: q8-common: Enable various peripherals
In-Reply-To: <1463500571-28970-1-git-send-email-wens@csie.org>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
Message-ID: <abbb9686-bbc7-cfad-ec1d-e5f099ac124b@redhat.com>

Hi Chen-Yu,

On 17-05-16 17:56, Chen-Yu Tsai wrote:
> Hi everyone,
>
> This series enables more peripherals for Allwinner A13-based Q8 devices.
> The peripherals include the WiFi, the PMIC's micro-usb power supply
> (driver), audio codec (headphone and speaker), and full display support
> with the new DRM KMS driver. The series is based on parts of Maxime's
> "drm: Add Support for Passive RGB to VGA bridges" series, specifically
> the clk and drm fixes, and common DTS bits.
>
> Hans, since you have a collection of q8 tablets, I'm hoping you could
> test these bits and provide some feedback.

I've not run any tests, just looked at the patches, the stuff in
patch 3 is already present in arch/arm/boot/dts/sun5i-a13-q8-tablet.dts
I put it there because I saw some .fex files which don't use ldo3 for wifi
I'm fine with moving it to -common though, I believe that you're right
that it makes more sense there, having it in 2 places is not really
useful though.

The other patches look good.

Thanks & Regards,

Hans


>
>
> Patch 1 is a small fix for part of the init failure path.
>
> Patch 2 disables ldo5 on the axp209 by default. This regulator output is
> muxed with a gpio, and the regulator on/off settings override the gpio.
>
> Patch 3 enables the USB WiFi module found.
>
> Patch 4 enables the USB/VBUS power supply of the PMIC.
>
> Patch 5 enables the audio codec, with support for the speaker amp.
>
> Patch 6 enables the LCD panel with the display pipeline.
>
>
> Regards
> ChenYu
>
>
> Chen-Yu Tsai (6):
>   drm: sun4i: do cleanup if RGB output init fails
>   ARM: dts: axp209: Disable ldo5 by default
>   ARM: dts: sun5i: q8-common: Enable USB-based WiFi
>   ARM: dts: sun5i: q8-common: Enable USB power supply
>   ARM: dts: sun5i: q8-common: Enable audio codec
>   ARM: dts: sun5i: q8-common: Enable display pipeline and LCD display
>
>  arch/arm/boot/dts/axp209.dtsi          |  1 +
>  arch/arm/boot/dts/sun5i-q8-common.dtsi | 62 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/sun4i/sun4i_tcon.c     |  6 +++-
>  3 files changed, 68 insertions(+), 1 deletion(-)
>


From joel at jms.id.au  Wed May 18 01:20:58 2016
From: joel at jms.id.au (Joel Stanley)
Date: Wed, 18 May 2016 17:50:58 +0930
Subject: [PATCH v3 0/2]  watchdog: Add Aspeed watchdog driver
In-Reply-To: <1463062631-16432-1-git-send-email-joel@jms.id.au>
References: <1463062631-16432-1-git-send-email-joel@jms.id.au>
Message-ID: <1463559661-14170-1-git-send-email-joel@jms.id.au>

Hello,

These patches add support for the watchdog timer found in Aspeed ast2400 and
ast2500 BMC SoCs.

The u-boot that ships on the edk and with many systems leaves the watchdog
running when jumping to the kernel, making this driver required for operation.

It has been tested on the ast2400 in an OpenPower Palmetto, and the ast2500-edk
dev board.

Changes in v3:
 - remove rate from struct aspeed_wdt in favour of #define
 - don't start the timer when setting the timeout
 - wait after initiaitng the reboot so it catches
 - remove dev_info from startup

 - update bindings following review from Rob (this didn't make it to the
 mailing list in v2)

Changes in v2:

Addressed review from Guenter:
 - dropped the drv_dbgs
 - added defines for all of the constants
 - clarified the type of reset we want
 - leaves the watchdog running

Cheers,

Joel

Joel Stanley (2):
  doc/devicetree: Add Aspeed watchdog timer bindings
  watchdog: Add Aspeed watchdog driver

 .../devicetree/bindings/watchdog/aspeed-wdt.txt    |  16 ++
 drivers/watchdog/Kconfig                           |  13 ++
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/aspeed_wdt.c                      | 212 +++++++++++++++++++++
 4 files changed, 242 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
 create mode 100644 drivers/watchdog/aspeed_wdt.c

-- 
2.8.1



From joel at jms.id.au  Wed May 18 01:20:59 2016
From: joel at jms.id.au (Joel Stanley)
Date: Wed, 18 May 2016 17:50:59 +0930
Subject: [PATCH v3 1/2] doc/devicetree: Add Aspeed watchdog timer bindings
In-Reply-To: <1463559661-14170-1-git-send-email-joel@jms.id.au>
References: <1463062631-16432-1-git-send-email-joel@jms.id.au>
 <1463559661-14170-1-git-send-email-joel@jms.id.au>
Message-ID: <1463559661-14170-2-git-send-email-joel@jms.id.au>

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 .../devicetree/bindings/watchdog/aspeed-wdt.txt          | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
new file mode 100644
index 000000000000..c5e74d7b4406
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
@@ -0,0 +1,16 @@
+Aspeed Watchdog Timer
+
+Required properties:
+ - compatible: must be one of:
+	- "aspeed,ast2400-wdt"
+	- "aspeed,ast2500-wdt"
+
+ - reg: physical base address of the controller and length of memory mapped
+   region
+
+Example:
+
+	wdt1: watchdog at 1e785000 {
+		compatible = "aspeed,ast2400-wdt";
+		reg = <0x1e785000 0x1c>;
+	};
-- 
2.8.1



From joel at jms.id.au  Wed May 18 01:21:00 2016
From: joel at jms.id.au (Joel Stanley)
Date: Wed, 18 May 2016 17:51:00 +0930
Subject: [PATCH v3 2/2] watchdog: Add Aspeed watchdog driver
In-Reply-To: <1463559661-14170-1-git-send-email-joel@jms.id.au>
References: <1463062631-16432-1-git-send-email-joel@jms.id.au>
 <1463559661-14170-1-git-send-email-joel@jms.id.au>
Message-ID: <1463559661-14170-3-git-send-email-joel@jms.id.au>

Provides generic watchdog features as well as reboot support for the
Aspeed SoCs.

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/watchdog/Kconfig      |  13 +++
 drivers/watchdog/Makefile     |   1 +
 drivers/watchdog/aspeed_wdt.c | 212 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 226 insertions(+)
 create mode 100644 drivers/watchdog/aspeed_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fb947655badd..4f0e2ded4785 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -661,6 +661,19 @@ config ATLAS7_WATCHDOG
 	  To compile this driver as a module, choose M here: the
 	  module will be called atlas7_wdt.
 
+config ASPEED_WATCHDOG
+	tristate "Aspeed 2400 watchdog support"
+	depends on ARCH_ASPEED || COMPILE_TEST
+	select WATCHDOG_CORE
+	help
+	  Say Y here to include support for the watchdog timer
+	  in Apseed BMC SoCs.
+
+	  This driver is required to reboot the SoC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called aspeed_wdt.
+
 # AVR32 Architecture
 
 config AT32AP700X_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index feb6270fdbde..36855375e0ce 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
 obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
 obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
 obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o
+obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
new file mode 100644
index 000000000000..f5ad8023c2e6
--- /dev/null
+++ b/drivers/watchdog/aspeed_wdt.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2016 IBM Corporation
+ *
+ * Joel Stanley <joel at jms.id.au>
+ *
+ * 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+
+struct aspeed_wdt {
+	struct watchdog_device	wdd;
+	void __iomem		*base;
+	u32			ctrl;
+};
+
+static const struct of_device_id aspeed_wdt_of_table[] = {
+	{ .compatible = "aspeed,ast2400-wdt" },
+	{ .compatible = "aspeed,ast2500-wdt" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
+
+#define WDT_STATUS		0x00
+#define WDT_RELOAD_VALUE	0x04
+#define WDT_RESTART		0x08
+#define WDT_CTRL		0x0C
+#define   WDT_CTRL_RESET_MODE_SOC	(0x00 << 5)
+#define   WDT_CTRL_RESET_MODE_FULL_CHIP	(0x01 << 5)
+#define   WDT_CTRL_1MHZ_CLK		BIT(4)
+#define   WDT_CTRL_WDT_EXT		BIT(3)
+#define   WDT_CTRL_WDT_INTR		BIT(2)
+#define   WDT_CTRL_RESET_SYSTEM		BIT(1)
+#define   WDT_CTRL_ENABLE		BIT(0)
+
+#define WDT_RESTART_MAGIC	0x4755
+
+/* 32 bits at 1MHz, in milliseconds */
+#define WDT_MAX_TIMEOUT_MS	4294967
+#define WDT_DEFAULT_TIMEOUT	30
+#define WDT_RATE_1MHZ		1000000
+
+static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd)
+{
+	return container_of(wdd, struct aspeed_wdt, wdd);
+}
+
+static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
+{
+	wdt->ctrl |= WDT_CTRL_ENABLE;
+
+	writel(0, wdt->base + WDT_CTRL);
+	writel(count, wdt->base + WDT_RELOAD_VALUE);
+	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
+	writel(wdt->ctrl, wdt->base + WDT_CTRL);
+}
+
+static int aspeed_wdt_start(struct watchdog_device *wdd)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+
+	aspeed_wdt_enable(wdt, wdd->timeout * WDT_RATE_1MHZ);
+
+	return 0;
+}
+
+static int aspeed_wdt_stop(struct watchdog_device *wdd)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+
+	wdt->ctrl &= ~WDT_CTRL_ENABLE;
+	writel(wdt->ctrl, wdt->base + WDT_CTRL);
+
+	return 0;
+}
+
+static int aspeed_wdt_ping(struct watchdog_device *wdd)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+
+	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
+
+	return 0;
+}
+
+static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
+				  unsigned int timeout)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+	u32 actual;
+
+	wdd->timeout = timeout;
+
+	actual = min(timeout, wdd->max_hw_heartbeat_ms * 1000);
+
+	writel(actual * WDT_RATE_1MHZ, wdt->base + WDT_RELOAD_VALUE);
+	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
+
+	return 0;
+}
+
+static int aspeed_wdt_restart(struct watchdog_device *wdd,
+			      unsigned long action, void *data)
+{
+	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
+
+	aspeed_wdt_enable(wdt, 128 * WDT_RATE_1MHZ / 1000);
+
+	mdelay(1000);
+
+	return 0;
+}
+
+static const struct watchdog_ops aspeed_wdt_ops = {
+	.start		= aspeed_wdt_start,
+	.stop		= aspeed_wdt_stop,
+	.ping		= aspeed_wdt_ping,
+	.set_timeout	= aspeed_wdt_set_timeout,
+	.restart	= aspeed_wdt_restart,
+	.owner		= THIS_MODULE,
+};
+
+static const struct watchdog_info aspeed_wdt_info = {
+	.options	= WDIOF_KEEPALIVEPING
+			| WDIOF_MAGICCLOSE
+			| WDIOF_SETTIMEOUT,
+	.identity	= KBUILD_MODNAME,
+};
+
+static int aspeed_wdt_remove(struct platform_device *pdev)
+{
+	struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
+
+	watchdog_unregister_device(&wdt->wdd);
+
+	return 0;
+}
+
+static int aspeed_wdt_probe(struct platform_device *pdev)
+{
+	struct aspeed_wdt *wdt;
+	struct resource *res;
+	int ret;
+
+	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+	if (!wdt)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	wdt->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(wdt->base))
+		return PTR_ERR(wdt->base);
+
+	/*
+	 * The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only
+	 * runs at 1MHz. We chose to always run at 1MHz, as there's no
+	 * good reason to have a faster watchdog counter.
+	 */
+	wdt->wdd.info = &aspeed_wdt_info;
+	wdt->wdd.ops = &aspeed_wdt_ops;
+	wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS;
+	wdt->wdd.parent = &pdev->dev;
+
+	wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT;
+	watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
+
+	/*
+	 * Control reset on a per-device basis to ensure the
+	 * host is not affected by a BMC reboot, so only reset
+	 * the SOC and not the full chip
+	 */
+	wdt->ctrl = WDT_CTRL_RESET_MODE_SOC |
+		WDT_CTRL_1MHZ_CLK |
+		WDT_CTRL_RESET_SYSTEM;
+
+	if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_ENABLE)  {
+		aspeed_wdt_start(&wdt->wdd);
+		set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
+	}
+
+	ret = watchdog_register_device(&wdt->wdd);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, wdt);
+
+	return 0;
+}
+
+static struct platform_driver aspeed_watchdog_driver = {
+	.probe = aspeed_wdt_probe,
+	.remove = aspeed_wdt_remove,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.of_match_table = of_match_ptr(aspeed_wdt_of_table),
+	},
+};
+module_platform_driver(aspeed_watchdog_driver);
+
+MODULE_DESCRIPTION("Aspeed Watchdog Driver");
+MODULE_LICENSE("GPL");
-- 
2.8.1



From slash.tmp at free.fr  Wed May 18 01:30:17 2016
From: slash.tmp at free.fr (Mason)
Date: Wed, 18 May 2016 10:30:17 +0200
Subject: CONFIG_ZBOOT_ROM_TEXT and CONFIG_ZBOOT_ROM_BSS in defconfig
In-Reply-To: <573B3F3C.80800@free.fr>
References: <573B3F3C.80800@free.fr>
Message-ID: <573C2819.3090109@free.fr>

On 17/05/2016 17:56, Mason wrote:

> I can submit a patch changing the default from 0 to 0x0, i.e.
> no functional change. The two entries would then disappear
> from defconfigs.

Specifically, this is what I meant:

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 70764838dfcc..6831c46a3672 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1823,7 +1823,7 @@ config DEPRECATED_PARAM_STRUCT
 # TEXT and BSS so we preserve their values in the config files.
 config ZBOOT_ROM_TEXT
 	hex "Compressed ROM boot loader base address"
-	default "0"
+	default 0x0
 	help
 	  The physical address at which the ROM-able zImage is to be
 	  placed in the target.  Platforms which normally make use of
@@ -1834,7 +1834,7 @@ config ZBOOT_ROM_TEXT
 
 config ZBOOT_ROM_BSS
 	hex "Compressed ROM boot loader BSS address"
-	default "0"
+	default 0x0
 	help
 	  The base address of an area of read/write memory in the target
 	  for the ROM-able zImage which must be available while the



From pavel at ucw.cz  Wed May 18 01:30:48 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Wed, 18 May 2016 10:30:48 +0200
Subject: [PATCH] support for AD5820 camera auto-focus coil
In-Reply-To: <20160517183340.GA10358@gmail.com>
References: <20160517181927.GA28741@amd>
 <20160517183340.GA10358@gmail.com>
Message-ID: <20160518083048.GA30870@amd>

Hi!

...
> Use module_i2c_driver() instead.

Thanks for all the comments, I've fixed it up like this, will post new
version soon.

Best regards,
								Pavel

commit 97a793fb20be29e7ed217c007e8bf857f9854968
Author: Pavel <pavel at ucw.cz>
Date:   Wed May 18 10:22:06 2016 +0200

    Cleanups, as suggested by Marcus Folkesson

diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
index b71cc11..7725829 100644
--- a/drivers/media/i2c/ad5820.c
+++ b/drivers/media/i2c/ad5820.c
@@ -147,7 +147,6 @@ static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl)
 	struct ad5820_device *coil =
 		container_of(ctrl->handler, struct ad5820_device, ctrls);
 	u32 code;
-	int r = 0;
 
 	switch (ctrl->id) {
 	case V4L2_CID_FOCUS_ABSOLUTE:
@@ -165,7 +164,7 @@ static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl)
 		break;
 	}
 
-	return r;
+	return 0;
 }
 
 static const struct v4l2_ctrl_ops ad5820_ctrl_ops = {
@@ -245,8 +244,6 @@ static int ad5820_init_controls(struct ad5820_device *coil)
  */
 static int ad5820_registered(struct v4l2_subdev *subdev)
 {
-	static const int CHECK_VALUE = 0x3FF0;
-
 	struct ad5820_device *coil = to_ad5820_device(subdev);
 	struct i2c_client *client = v4l2_get_subdevdata(subdev);
 
@@ -364,16 +361,19 @@ static int ad5820_probe(struct i2c_client *client,
 	strcpy(coil->subdev.name, "ad5820 focus");
 
 	ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
-	if (ret < 0) {
-		kfree(coil);
-		return ret;
-	}
+	if (ret < 0)
+		goto free;
 
 	ret = v4l2_async_register_subdev(&coil->subdev);
 	if (ret < 0)
-		kfree(coil);
+		goto cleanup;
 
 	return ret;
+cleanup:
+	media_entity_cleanup(&coil->subdev.entity);
+free:
+	kfree(coil);
+	return ret;
 }
 
 static int __exit ad5820_remove(struct i2c_client *client)
@@ -409,26 +409,7 @@ static struct i2c_driver ad5820_i2c_driver = {
 	.id_table	= ad5820_id_table,
 };
 
-static int __init ad5820_init(void)
-{
-	int rval;
-
-	rval = i2c_add_driver(&ad5820_i2c_driver);
-	if (rval)
-		printk(KERN_INFO "%s: failed registering " AD5820_NAME "\n",
-		       __func__);
-
-	return rval;
-}
-
-static void __exit ad5820_exit(void)
-{
-	i2c_del_driver(&ad5820_i2c_driver);
-}
-
-
-module_init(ad5820_init);
-module_exit(ad5820_exit);
+module_i2c_driver(ad5820_i2c_driver);
 
 MODULE_AUTHOR("Tuukka Toivonen");
 MODULE_DESCRIPTION("AD5820 camera lens driver");

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From yt.shen at mediatek.com  Wed May 18 01:33:21 2016
From: yt.shen at mediatek.com (YT Shen)
Date: Wed, 18 May 2016 16:33:21 +0800
Subject: [RFC 2/3] drm/mediatek: add support for Mediatek SoC MT2701
In-Reply-To: <CACvgo52qc4E=MAGLoCaUH+GZuyvPexHchZnvuv-fF8P23e_1Uw@mail.gmail.com>
References: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
 <1463053795-55455-3-git-send-email-yt.shen@mediatek.com>
 <CACvgo52qc4E=MAGLoCaUH+GZuyvPexHchZnvuv-fF8P23e_1Uw@mail.gmail.com>
Message-ID: <1463560401.8576.15.camel@mtksdaap41>

Hi Emil,

On Tue, 2016-05-17 at 10:55 +0100, Emil Velikov wrote:
> Hi YT Shen,
> 
> On 12 May 2016 at 12:49,  <yt.shen at mediatek.com> wrote:
> > From: YT Shen <yt.shen at mediatek.com>
> >
> > This patch add support for the Mediatek MT2701 DISP subsystem.
> > There is only one OVL engine in MT2701, and we have shadow
> > register support here.
> >
> > Signed-off-by: YT Shen <yt.shen at mediatek.com>
> > ---
> >  drivers/gpu/drm/mediatek/mtk_disp_ovl.c     |   49 ++++++---
> >  drivers/gpu/drm/mediatek/mtk_disp_rdma.c    |   36 +++++--
> >  drivers/gpu/drm/mediatek/mtk_drm_crtc.c     |   78 +++++++++-----
> >  drivers/gpu/drm/mediatek/mtk_drm_ddp.c      |  151 ++++++++++++++++++++-------
> >  drivers/gpu/drm/mediatek/mtk_drm_ddp.h      |    2 +
> >  drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c |   63 +++++++++--
> >  drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |   15 +++
> >  drivers/gpu/drm/mediatek/mtk_drm_drv.c      |   72 +++++++++++--
> >  drivers/gpu/drm/mediatek/mtk_drm_drv.h      |    9 ++
> >  drivers/gpu/drm/mediatek/mtk_drm_gem.c      |    4 +
> >  10 files changed, 373 insertions(+), 106 deletions(-)
> >
> This patch does a bit too many things at once imho
>  - Renames existing macros
>  - Factors out helper functions - mtk_crtc_ddp_config and alike.
>  - Introduces *driver_data for existing hardware and uses it
>  - and adds support for the different hardware.
> 
> I'm no expert in the area, but it feels like you want to split things
> roughly as per above.
> A rather serious mali note and some "this should be const" follow
> suggestions inline.
Thanks for your suggestions.  I will split this patch into several small
patches.  They are easier to understand, and easier to review.
> 
> 
> >
> > +static struct mtk_ddp_comp_driver_data mt2701_ovl_driver_data = {
> > +       .ovl = {0x0040, 1 << 12, 0}
> > +};
> > +
> > +static struct mtk_ddp_comp_driver_data mt8173_ovl_driver_data = {
> > +       .ovl = {0x0f40, 0, 1 << 12}
> > +};
> > +
> These two should be const right ?
Yes, they should.
> 
> 
> >
> > +static struct mtk_ddp_comp_driver_data mt2701_rdma_driver_data = {
> > +       .rdma_fifo_pseudo_size = SZ_4K,
> > +};
> > +
> > +static struct mtk_ddp_comp_driver_data mt8173_rdma_driver_data = {
> > +       .rdma_fifo_pseudo_size = SZ_8K,
> > +};
> > +
> Same here.
OK.
> 
> 
> >
> > -#define MUTEX_MOD_DISP_OVL0            BIT(11)
> > -#define MUTEX_MOD_DISP_OVL1            BIT(12)
> > -#define MUTEX_MOD_DISP_RDMA0           BIT(13)
> > -#define MUTEX_MOD_DISP_RDMA1           BIT(14)
> > -#define MUTEX_MOD_DISP_RDMA2           BIT(15)
> > -#define MUTEX_MOD_DISP_WDMA0           BIT(16)
> > -#define MUTEX_MOD_DISP_WDMA1           BIT(17)
> > -#define MUTEX_MOD_DISP_COLOR0          BIT(18)
> > -#define MUTEX_MOD_DISP_COLOR1          BIT(19)
> > -#define MUTEX_MOD_DISP_AAL             BIT(20)
> > -#define MUTEX_MOD_DISP_GAMMA           BIT(21)
> > -#define MUTEX_MOD_DISP_UFOE            BIT(22)
> > -#define MUTEX_MOD_DISP_PWM0            BIT(23)
> > -#define MUTEX_MOD_DISP_PWM1            BIT(24)
> > -#define MUTEX_MOD_DISP_OD              BIT(25)
> > +#define MUTEX_MOD_MT8173_DISP_OVL0             BIT(11)
> > +#define MUTEX_MOD_MT8173_DISP_OVL1             BIT(12)
> > +#define MUTEX_MOD_MT8173_DISP_RDMA0            BIT(13)
> > +#define MUTEX_MOD_MT8173_DISP_RDMA1            BIT(14)
> > +#define MUTEX_MOD_MT8173_DISP_RDMA2            BIT(15)
> > +#define MUTEX_MOD_MT8173_DISP_WDMA0            BIT(16)
> > +#define MUTEX_MOD_MT8173_DISP_WDMA1            BIT(17)
> > +#define MUTEX_MOD_MT8173_DISP_COLOR0           BIT(18)
> > +#define MUTEX_MOD_MT8173_DISP_COLOR1           BIT(19)
> > +#define MUTEX_MOD_MT8173_DISP_AAL              BIT(20)
> > +#define MUTEX_MOD_MT8173_DISP_GAMMA            BIT(21)
> > +#define MUTEX_MOD_MT8173_DISP_UFOE             BIT(22)
> > +#define MUTEX_MOD_MT8173_DISP_PWM0             BIT(23)
> > +#define MUTEX_MOD_MT8173_DISP_PWM1             BIT(24)
> > +#define MUTEX_MOD_MT8173_DISP_OD               BIT(25)
> > +
> > +#define MUTEX_MOD_MT2701_DISP_OVL              BIT(3)
> > +#define MUTEX_MOD_MT2701_DISP_WDMA             BIT(6)
> > +#define MUTEX_MOD_MT2701_DISP_COLOR            BIT(7)
> > +#define MUTEX_MOD_MT2701_DISP_BLS              BIT(9)
> > +#define MUTEX_MOD_MT2701_DISP_RDMA0            BIT(10)
> > +#define MUTEX_MOD_MT2701_DISP_RDMA1            BIT(12)
> >
> Even though the driver not does use a unique prefix/namespace for
> these macros (which it should imho), it's better to keep the hardware
> name/part first. Ideally the rename will be a separate patch.
OK, I will rename the macros and put it in a separate patch.
> 
> 
> > @@ -131,6 +153,32 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
> >         [DDP_COMPONENT_WDMA1]   = { MTK_DISP_WDMA,      1, NULL },
> >  };
> >
> > +static struct mtk_ddp_comp_driver_data mt2701_color_driver_data = {
> > +       .color_offset = 0x0f00,
> > +};
> > +
> > +static struct mtk_ddp_comp_driver_data mt8173_color_driver_data = {
> > +       .color_offset = 0x0c00,
> > +};
> > +
> const again ? You can even tweak the *_get_driver_data helpers, to
> return const struct foo*, and resolve the odd warning that the
> compiler will give you.
OK, I will do it in the next version.
> 
> 
> >  struct mtk_ddp_comp {
> >         struct clk *clk;
> >         void __iomem *regs;
> > @@ -82,6 +96,7 @@ struct mtk_ddp_comp {
> >         struct device *larb_dev;
> >         enum mtk_ddp_comp_id id;
> >         const struct mtk_ddp_comp_funcs *funcs;
> > +       struct mtk_ddp_comp_driver_data *data;
> const
OK.
> 
> 
> > +static struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
> > +       .main_path = mtk_ddp_main_2701,
> > +       .main_len = ARRAY_SIZE(mtk_ddp_main_2701),
> > +       .ext_path = mtk_ddp_ext_2701,
> > +       .ext_len = ARRAY_SIZE(mtk_ddp_ext_2701),
> > +       .shadow_register = true,
> > +};
> > +
> > +static struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
> > +       .main_path = mtk_ddp_main_8173,
> > +       .main_len = ARRAY_SIZE(mtk_ddp_main_8173),
> > +       .ext_path = mtk_ddp_ext_8173,
> > +       .ext_len = ARRAY_SIZE(mtk_ddp_ext_8173),
> > +       .shadow_register = false,
> > +};
> > +
> const
OK.
> 
> 
> > @@ -40,6 +48,7 @@ struct mtk_drm_private {
> >         void __iomem *config_regs;
> >         struct device_node *comp_node[DDP_COMPONENT_ID_MAX];
> >         struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX];
> > +       struct mtk_mmsys_driver_data *data;
> const ?
Yes.
> 
> 
> > @@ -108,6 +108,10 @@ int mtk_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
> >         int ret;
> >
> >         args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
> > +       /*
> > +       * align to 8 bytes since Mali requires it.
> > +       */
> > +       args->pitch = ALIGN(args->pitch, 8);
> Are you sure we need this, based on the line just above ?
I think bpp stands for bits per pixel, so width * bpp / 8 simply transfer from bits to bytes, which
cannot guarantee align to 8.

I will remove this align part from the patch, this constraint is not from display controller.
Thanks.


> 
> Iirc we had a chat earlier that upstream kernel code should not be
> tailoured for the needs to closed source userspace... seems like the
> comment got removed but the code remained. Philipp Zabel I believe you
> were the person who did the original upstreaming - can we remove this
> hack/workaround and keep it downstream until we have an open-source
> user that requires it ?
> 
> Can we have a MAINTAINERS entry for this driver ?
> 
> Thanks
> Emil





From ard.biesheuvel at linaro.org  Wed May 18 01:36:33 2016
From: ard.biesheuvel at linaro.org (Ard Biesheuvel)
Date: Wed, 18 May 2016 10:36:33 +0200
Subject: [PATCH v2 1/2] efi: esrt: use memremap not ioremap to access ESRT
 table in memory
In-Reply-To: <20160304062524.GA19010@dhcp-128-65.nay.redhat.com>
References: <20160218104407.GC2651@codeblueprint.co.uk>
 <CAKv+Gu_AW7PKJJOd2mbEu3LKJe+gNaPHnH=sgO=YXM_KWFyKxw@mail.gmail.com>
 <20160218132824.GE2651@codeblueprint.co.uk>
 <CAKv+Gu-s1pzYBzuDG-Z7s3gyo8dPOfeidZQ+rim-uAWZCBcKQQ@mail.gmail.com>
 <20160218134324.GG2651@codeblueprint.co.uk>
 <CAKv+Gu875r9RkDC723kNsG4XC0eSE9RPPmSFZrD0sx0QxS+V4g@mail.gmail.com>
 <20160218141544.GH2651@codeblueprint.co.uk>
 <20160218191624.GA1515@redhat.com>
 <20160226144114.GA7475@codeblueprint.co.uk>
 <20160301233040.GA31476@codeblueprint.co.uk>
 <20160304062524.GA19010@dhcp-128-65.nay.redhat.com>
Message-ID: <CAKv+Gu_ekP+44FJjR7BY_MFqx2jQgc6Tk9W4SBL__ttdvQ55VQ@mail.gmail.com>

On 4 March 2016 at 07:25, Dave Young <dyoung at redhat.com> wrote:
>> I have a very rough draft of patches that implement this strategy on
>> the 'experiemntal/efi-memmap' branch in the EFI tree if anyone is
>> curious and wants to take a look. The series will be sent out soon.
>>
>> I wouldn't necessarily try running them or anything as there's a few
>> things that I know are broken; ia64 build, EFI mixed mode boot,
>> probably arm64 regressions.
>
> Matt, I tried :). I see a build warning about print phys_addr_t without
> %pa anotation and booting with ioremap error messages about slot not found
> , and ioremap region leak messages.
>
> Looking forward to your formal posts.
>

So what is the status here? I know Sai is working on x86 support for
the memory attributes table, so it would make sense settle this matter
as well.


From gabriel.fernandez at linaro.org  Wed May 18 01:41:21 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Wed, 18 May 2016 10:41:21 +0200
Subject: [PATCH 00/11] Clock improvement for video playback
Message-ID: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>

This serie allows to increase video resolutions and make audio
adjustment during a video playback.

Gabriel Fernandez (11):
  drivers: clk: st: Add fs660c32 synthesizer algorithm
  drivers: clk: st: Add clock propagation for audio clocks
  drivers: clk: st: Handle clkgenD2 clk synchronous mode
  ARM: DT: STiH407: Add compatibility string on clkgend0 for audio
    clocks
  ARM: DT: STiH410: Add compatibility string on clkgend0 for audio
    clocks
  ARM: DT: STiH418: Add compatibility string on clkgend0 for audio
    clocks
  ARM: DT: STiH407: Enable synchronous clock mode on clkgend2
  ARM: DT: STiH410: Enable synchronous clock mode on clkgend2
  ARM: DT: STiH418: Enable synchronous clock mode on clkgend2
  ARM: DT: STi: STiH407: clock configuration to address 720p and 1080p
  ARM: DT: STi: STiH410: clock configuration to address 720p and 1080p

 .../devicetree/bindings/clock/st/st,flexgen.txt    |   3 +
 arch/arm/boot/dts/stih407-clock.dtsi               |   4 +-
 arch/arm/boot/dts/stih407.dtsi                     |  16 ++-
 arch/arm/boot/dts/stih410-clock.dtsi               |   4 +-
 arch/arm/boot/dts/stih410.dtsi                     |  16 ++-
 arch/arm/boot/dts/stih418-clock.dtsi               |   4 +-
 drivers/clk/st/clk-flexgen.c                       |  61 +++++++-
 drivers/clk/st/clkgen-fsyn.c                       | 159 +++++++++++++++------
 8 files changed, 211 insertions(+), 56 deletions(-)

-- 
1.9.1



From gabriel.fernandez at linaro.org  Wed May 18 01:41:22 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Wed, 18 May 2016 10:41:22 +0200
Subject: [PATCH 01/11] drivers: clk: st: Add fs660c32 synthesizer algorithm
In-Reply-To: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <1463560892-7209-2-git-send-email-gabriel.fernandez@linaro.org>

Use an algorithm instead of a table to compute clocks for fs660c32
synthesizer.
During a video playback we need to adjust audio & video frequencies.
A table can't cover all HDMI resolutions and audio adjustment.

Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
---
 drivers/clk/st/clkgen-fsyn.c | 159 +++++++++++++++++++++++++++++++------------
 1 file changed, 117 insertions(+), 42 deletions(-)

diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
index dec4eaa..06e9537 100644
--- a/drivers/clk/st/clkgen-fsyn.c
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -81,40 +81,6 @@ static const struct stm_fs fs432c65_rtbl[] = {
 	{ .mdiv = 0x19, .pe = 0x121a,	.sdiv = 0x0,	.nsdiv = 1 },	/* 297     MHz */
 };
 
-static const struct stm_fs fs660c32_rtbl[] = {
-	{ .mdiv = 0x14, .pe = 0x376b,	.sdiv = 0x4,	.nsdiv = 1 },	/* 25.175  MHz */
-	{ .mdiv = 0x14, .pe = 0x30c3,	.sdiv = 0x4,	.nsdiv = 1 },	/* 25.200  MHz */
-	{ .mdiv = 0x10, .pe = 0x71c7,	.sdiv = 0x4,	.nsdiv = 1 },	/* 27.000  MHz */
-	{ .mdiv = 0x00, .pe = 0x47af,	.sdiv = 0x3,	.nsdiv = 0 },	/* 27.027  MHz */
-	{ .mdiv = 0x0e, .pe = 0x4e1a,	.sdiv = 0x4,	.nsdiv = 1 },	/* 28.320  MHz */
-	{ .mdiv = 0x0b, .pe = 0x534d,	.sdiv = 0x4,	.nsdiv = 1 },	/* 30.240  MHz */
-	{ .mdiv = 0x17, .pe = 0x6fbf,	.sdiv = 0x2,	.nsdiv = 0 },	/* 31.500  MHz */
-	{ .mdiv = 0x01, .pe = 0x0,	.sdiv = 0x4,	.nsdiv = 1 },	/* 40.000  MHz */
-	{ .mdiv = 0x15, .pe = 0x2aab,	.sdiv = 0x3,	.nsdiv = 1 },	/* 49.500  MHz */
-	{ .mdiv = 0x14, .pe = 0x6666,	.sdiv = 0x3,	.nsdiv = 1 },	/* 50.000  MHz */
-	{ .mdiv = 0x1d, .pe = 0x395f,	.sdiv = 0x1,	.nsdiv = 0 },	/* 57.284  MHz */
-	{ .mdiv = 0x08, .pe = 0x4ec5,	.sdiv = 0x3,	.nsdiv = 1 },	/* 65.000  MHz */
-	{ .mdiv = 0x05, .pe = 0x1770,	.sdiv = 0x3,	.nsdiv = 1 },	/* 71.000  MHz */
-	{ .mdiv = 0x03, .pe = 0x4ba7,	.sdiv = 0x3,	.nsdiv = 1 },	/* 74.176  MHz */
-	{ .mdiv = 0x0f, .pe = 0x3426,	.sdiv = 0x1,	.nsdiv = 0 },	/* 74.250  MHz */
-	{ .mdiv = 0x0e, .pe = 0x7777,	.sdiv = 0x1,	.nsdiv = 0 },	/* 75.000  MHz */
-	{ .mdiv = 0x01, .pe = 0x4053,	.sdiv = 0x3,	.nsdiv = 1 },	/* 78.800  MHz */
-	{ .mdiv = 0x09, .pe = 0x15b5,	.sdiv = 0x1,	.nsdiv = 0 },	/* 85.500  MHz */
-	{ .mdiv = 0x1b, .pe = 0x3f19,	.sdiv = 0x2,	.nsdiv = 1 },	/* 88.750  MHz */
-	{ .mdiv = 0x10, .pe = 0x71c7,	.sdiv = 0x2,	.nsdiv = 1 },	/* 108.000 MHz */
-	{ .mdiv = 0x00, .pe = 0x47af,	.sdiv = 0x1,	.nsdiv = 0 },	/* 108.108 MHz */
-	{ .mdiv = 0x0c, .pe = 0x3118,	.sdiv = 0x2,	.nsdiv = 1 },	/* 118.963 MHz */
-	{ .mdiv = 0x0c, .pe = 0x2f54,	.sdiv = 0x2,	.nsdiv = 1 },	/* 119.000 MHz */
-	{ .mdiv = 0x07, .pe = 0xe39,	.sdiv = 0x2,	.nsdiv = 1 },	/* 135.000 MHz */
-	{ .mdiv = 0x03, .pe = 0x4ba7,	.sdiv = 0x2,	.nsdiv = 1 },	/* 148.352 MHz */
-	{ .mdiv = 0x0f, .pe = 0x3426,	.sdiv = 0x0,	.nsdiv = 0 },	/* 148.500 MHz */
-	{ .mdiv = 0x03, .pe = 0x4ba7,	.sdiv = 0x1,	.nsdiv = 1 },	/* 296.704 MHz */
-	{ .mdiv = 0x03, .pe = 0x471c,	.sdiv = 0x1,	.nsdiv = 1 },	/* 297.000 MHz */
-	{ .mdiv = 0x00, .pe = 0x295f,	.sdiv = 0x1,	.nsdiv = 1 },	/* 326.700 MHz */
-	{ .mdiv = 0x1f, .pe = 0x3633,	.sdiv = 0x0,	.nsdiv = 1 },	/* 333.000 MHz */
-	{ .mdiv = 0x1c, .pe = 0x0,	.sdiv = 0x0,	.nsdiv = 1 },	/* 352.000 Mhz */
-};
-
 struct clkgen_quadfs_data {
 	bool reset_present;
 	bool bwfilter_present;
@@ -140,6 +106,7 @@ struct clkgen_quadfs_data {
 	const struct clk_ops *pll_ops;
 	const struct stm_fs *rtbl;
 	u8 rtbl_cnt;
+	int  (*get_params)(unsigned long, unsigned long, struct stm_fs *);
 	int  (*get_rate)(unsigned long , const struct stm_fs *,
 			unsigned long *);
 };
@@ -156,6 +123,9 @@ static int clk_fs432c65_get_rate(unsigned long, const struct stm_fs *,
 		unsigned long *);
 static int clk_fs660c32_dig_get_rate(unsigned long, const struct stm_fs *,
 		unsigned long *);
+static int clk_fs660c32_dig_get_params(unsigned long input,
+		unsigned long output, struct stm_fs *fs);
+
 /*
  * Values for all of the standalone instances of this clock
  * generator found in STiH415 and STiH416 SYSCFG register banks. Note
@@ -266,8 +236,7 @@ static const struct clkgen_quadfs_data st_fs660c32_E_416 = {
 	.lockstatus_present = true,
 	.lock_status = CLKGEN_FIELD(0xAC, 0x1, 0),
 	.pll_ops	= &st_quadfs_pll_c32_ops,
-	.rtbl		= fs660c32_rtbl,
-	.rtbl_cnt	= ARRAY_SIZE(fs660c32_rtbl),
+	.get_params	= clk_fs660c32_dig_get_params,
 	.get_rate	= clk_fs660c32_dig_get_rate,
 };
 
@@ -302,8 +271,7 @@ static const struct clkgen_quadfs_data st_fs660c32_F_416 = {
 	.lockstatus_present = true,
 	.lock_status = CLKGEN_FIELD(0xEC, 0x1, 0),
 	.pll_ops	= &st_quadfs_pll_c32_ops,
-	.rtbl		= fs660c32_rtbl,
-	.rtbl_cnt	= ARRAY_SIZE(fs660c32_rtbl),
+	.get_params	= clk_fs660c32_dig_get_params,
 	.get_rate	= clk_fs660c32_dig_get_rate,
 };
 
@@ -345,8 +313,7 @@ static const struct clkgen_quadfs_data st_fs660c32_C = {
 	.powerup_polarity = 1,
 	.standby_polarity = 1,
 	.pll_ops	= &st_quadfs_pll_c32_ops,
-	.rtbl		= fs660c32_rtbl,
-	.rtbl_cnt	= ARRAY_SIZE(fs660c32_rtbl),
+	.get_params	= clk_fs660c32_dig_get_params,
 	.get_rate	= clk_fs660c32_dig_get_rate,
 };
 
@@ -388,8 +355,7 @@ static const struct clkgen_quadfs_data st_fs660c32_D = {
 	.powerup_polarity = 1,
 	.standby_polarity = 1,
 	.pll_ops	= &st_quadfs_pll_c32_ops,
-	.rtbl		= fs660c32_rtbl,
-	.rtbl_cnt	= ARRAY_SIZE(fs660c32_rtbl),
+	.get_params	= clk_fs660c32_dig_get_params,
 	.get_rate	= clk_fs660c32_dig_get_rate,};
 
 /**
@@ -893,12 +859,113 @@ static int quadfs_fsynt_get_hw_value_for_recalc(struct st_clk_quadfs_fsynth *fs,
 	return 0;
 }
 
+static int clk_fs660c32_get_pe(int m, int si, unsigned long *deviation,
+		signed long input, unsigned long output, uint64_t *p,
+		struct stm_fs *fs)
+{
+	unsigned long new_freq, new_deviation;
+	struct stm_fs fs_tmp;
+	uint64_t val;
+
+	val = (uint64_t)output << si;
+
+	*p = (uint64_t)input * P20 - (32LL  + (uint64_t)m) * val * (P20 / 32LL);
+
+	*p = div64_u64(*p, val);
+
+	if (*p > 32767LL)
+		return 1;
+
+	fs_tmp.mdiv = (unsigned long) m;
+	fs_tmp.pe = (unsigned long)*p;
+	fs_tmp.sdiv = si;
+	fs_tmp.nsdiv = 1;
+
+	clk_fs660c32_dig_get_rate(input, &fs_tmp, &new_freq);
+
+	new_deviation = abs(output - new_freq);
+
+	if (new_deviation < *deviation) {
+		fs->mdiv = m;
+		fs->pe = (unsigned long)*p;
+		fs->sdiv = si;
+		fs->nsdiv = 1;
+		*deviation = new_deviation;
+	}
+	return 0;
+}
+
+static int clk_fs660c32_dig_get_params(unsigned long input,
+		unsigned long output, struct stm_fs *fs)
+{
+	int si;	/* sdiv_reg (8 downto 0) */
+	int m; /* md value */
+	unsigned long new_freq, new_deviation;
+	/* initial condition to say: "infinite deviation" */
+	unsigned long deviation = ~0;
+	uint64_t p, p1, p2;	/* pe value */
+	int r1, r2;
+
+	struct stm_fs fs_tmp;
+
+	for (si = 0; (si <= 8) && deviation; si++) {
+
+		/* Boundary test to avoid useless iteration */
+		r1 = clk_fs660c32_get_pe(0, si, &deviation,
+				input, output, &p1, fs);
+		r2 = clk_fs660c32_get_pe(31, si, &deviation,
+				input, output, &p2, fs);
+
+		/* No solution */
+		if (r1 && r2 && (p1 > p2))
+			continue;
+
+		/* Try to find best deviation */
+		for (m = 1; (m < 31) && deviation; m++)
+			clk_fs660c32_get_pe(m, si, &deviation,
+					input, output, &p, fs);
+
+	}
+
+	if (deviation == ~0) /* No solution found */
+		return -1;
+
+	/* pe fine tuning if deviation not 0: +/- 2 around computed pe value */
+	if (deviation) {
+		fs_tmp.mdiv = fs->mdiv;
+		fs_tmp.sdiv = fs->sdiv;
+		fs_tmp.nsdiv = fs->nsdiv;
+
+		if (fs->pe > 2)
+			p2 = fs->pe - 2;
+		else
+			p2 = 0;
+
+		for (; p2 < 32768ll && (p2 <= (fs->pe + 2)); p2++) {
+			fs_tmp.pe = (unsigned long)p2;
+
+			clk_fs660c32_dig_get_rate(input, &fs_tmp, &new_freq);
+
+			new_deviation = abs(output - new_freq);
+
+			/* Check if this is a better solution */
+			if (new_deviation < deviation) {
+				fs->pe = (unsigned long)p2;
+				deviation = new_deviation;
+
+			}
+		}
+	}
+	return 0;
+}
+
 static long quadfs_find_best_rate(struct clk_hw *hw, unsigned long drate,
 				unsigned long prate, struct stm_fs *params)
 {
 	struct st_clk_quadfs_fsynth *fs = to_quadfs_fsynth(hw);
 	int (*clk_fs_get_rate)(unsigned long ,
 				const struct stm_fs *, unsigned long *);
+	int (*clk_fs_get_params)(unsigned long, unsigned long, struct stm_fs *);
 	struct stm_fs prev_params;
 	unsigned long prev_rate, rate = 0;
 	unsigned long diff_rate, prev_diff_rate = ~0;
@@ -906,6 +973,14 @@ static long quadfs_find_best_rate(struct clk_hw *hw, unsigned long drate,
 
 	clk_fs_get_rate = fs->data->get_rate;
 
+	if (fs->data->get_params) {
+		clk_fs_get_params = fs->data->get_params;
+
+		if (!clk_fs_get_params(prate, drate, params))
+			clk_fs_get_rate(prate, params, &rate);
+		return rate;
+	}
+
 	for (index = 0; index < fs->data->rtbl_cnt; index++) {
 		prev_rate = rate;
 
-- 
1.9.1



From gabriel.fernandez at linaro.org  Wed May 18 01:41:23 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Wed, 18 May 2016 10:41:23 +0200
Subject: [PATCH 02/11] drivers: clk: st: Add clock propagation for audio clocks
In-Reply-To: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <1463560892-7209-3-git-send-email-gabriel.fernandez@linaro.org>

This patch allows fine tuning of the quads FS for audio clocks
accuracy.

Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
---
 .../devicetree/bindings/clock/st/st,flexgen.txt    |  1 +
 drivers/clk/st/clk-flexgen.c                       | 24 ++++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
index b7ee5c7..15b33c7 100644
--- a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
+++ b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
@@ -60,6 +60,7 @@ This binding uses the common clock binding[2].
 Required properties:
 - compatible : shall be:
   "st,flexgen"
+  "st,stih407-clkgend0", "st,flexgen" (enable clock propagation on parent)
 
 - #clock-cells : from common clock binding; shall be set to 1 (multiple clock
   outputs).
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index 627267c..3ff51ec 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -15,6 +15,10 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 
+struct clkgen_data {
+	unsigned long flags;
+};
+
 struct flexgen {
 	struct clk_hw hw;
 
@@ -259,6 +263,18 @@ static const char ** __init flexgen_get_parents(struct device_node *np,
 	return parents;
 }
 
+static const struct clkgen_data clkgen_d0 = {
+	.flags = CLK_SET_RATE_PARENT,
+};
+
+static const struct of_device_id flexgen_of_match[] = {
+	{
+		.compatible = "st,stih407-clkgend0",
+		.data = &clkgen_d0,
+	},
+	{}
+};
+
 static void __init st_of_flexgen_setup(struct device_node *np)
 {
 	struct device_node *pnode;
@@ -267,6 +283,8 @@ static void __init st_of_flexgen_setup(struct device_node *np)
 	const char **parents;
 	int num_parents, i;
 	spinlock_t *rlock = NULL;
+	const struct of_device_id *match;
+	struct clkgen_data *data = NULL;
 	unsigned long flex_flags = 0;
 	int ret;
 
@@ -282,6 +300,12 @@ static void __init st_of_flexgen_setup(struct device_node *np)
 	if (!parents)
 		return;
 
+	match = of_match_node(flexgen_of_match, np);
+	if (match) {
+		data = (struct clkgen_data *)match->data;
+		flex_flags = data->flags;
+	}
+
 	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
 	if (!clk_data)
 		goto err;
-- 
1.9.1



From gabriel.fernandez at linaro.org  Wed May 18 01:41:24 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Wed, 18 May 2016 10:41:24 +0200
Subject: [PATCH 03/11] drivers: clk: st: Handle clkgenD2 clk synchronous mode
In-Reply-To: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <1463560892-7209-4-git-send-email-gabriel.fernandez@linaro.org>

This patch configures the semi-synchronous mode of the video clocks
of clkgenD2.

Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
---
 .../devicetree/bindings/clock/st/st,flexgen.txt    |  2 ++
 drivers/clk/st/clk-flexgen.c                       | 37 ++++++++++++++++++++--
 2 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
index 15b33c7..8b73831 100644
--- a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
+++ b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
@@ -61,6 +61,8 @@ Required properties:
 - compatible : shall be:
   "st,flexgen"
   "st,stih407-clkgend0", "st,flexgen" (enable clock propagation on parent)
+  "st,stih407-clkgend2", "st,flexgen" (enable clock propagation on parent
+					and activate synchronous mode)
 
 - #clock-cells : from common clock binding; shall be set to 1 (multiple clock
   outputs).
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index 3ff51ec..aad6f4b 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -17,6 +17,7 @@
 
 struct clkgen_data {
 	unsigned long flags;
+	bool mode;
 };
 
 struct flexgen {
@@ -32,9 +33,14 @@ struct flexgen {
 	struct clk_gate fgate;
 	/* Final divisor */
 	struct clk_divider fdiv;
+	/* Asynchronous mode control */
+	struct clk_gate sync;
+	/* hw control flags */
+	bool control_mode;
 };
 
 #define to_flexgen(_hw) container_of(_hw, struct flexgen, hw)
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
 
 static int flexgen_enable(struct clk_hw *hw)
 {
@@ -143,12 +149,21 @@ static int flexgen_set_rate(struct clk_hw *hw, unsigned long rate,
 	struct flexgen *flexgen = to_flexgen(hw);
 	struct clk_hw *pdiv_hw = &flexgen->pdiv.hw;
 	struct clk_hw *fdiv_hw = &flexgen->fdiv.hw;
+	struct clk_hw *sync_hw = &flexgen->sync.hw;
+	struct clk_gate *config = to_clk_gate(sync_hw);
 	unsigned long div = 0;
 	int ret = 0;
+	u32 reg;
 
 	__clk_hw_set_clk(pdiv_hw, hw);
 	__clk_hw_set_clk(fdiv_hw, hw);
 
+	if (flexgen->control_mode) {
+		reg = readl(config->reg);
+		reg &= ~BIT(config->bit_idx);
+		writel(reg, config->reg);
+	}
+
 	div = clk_best_div(parent_rate, rate);
 
 	/*
@@ -182,7 +197,7 @@ static const struct clk_ops flexgen_ops = {
 static struct clk *clk_register_flexgen(const char *name,
 				const char **parent_names, u8 num_parents,
 				void __iomem *reg, spinlock_t *lock, u32 idx,
-				unsigned long flexgen_flags) {
+				unsigned long flexgen_flags, bool mode) {
 	struct flexgen *fgxbar;
 	struct clk *clk;
 	struct clk_init_data init;
@@ -231,6 +246,13 @@ static struct clk *clk_register_flexgen(const char *name,
 	fgxbar->fdiv.reg = fdiv_reg;
 	fgxbar->fdiv.width = 6;
 
+	/* Final divider sync config */
+	fgxbar->sync.lock = lock;
+	fgxbar->sync.reg = fdiv_reg;
+	fgxbar->sync.bit_idx = 7;
+
+	fgxbar->control_mode = mode;
+
 	fgxbar->hw.init = &init;
 
 	clk = clk_register(NULL, &fgxbar->hw);
@@ -267,11 +289,20 @@ static const struct clkgen_data clkgen_d0 = {
 	.flags = CLK_SET_RATE_PARENT,
 };
 
+static const struct clkgen_data clkgen_d2 = {
+	.flags = CLK_SET_RATE_PARENT,
+	.mode = 1,
+};
+
 static const struct of_device_id flexgen_of_match[] = {
 	{
 		.compatible = "st,stih407-clkgend0",
 		.data = &clkgen_d0,
 	},
+	{
+		.compatible = "st,stih407-clkgend2",
+		.data = &clkgen_d2,
+	},
 	{}
 };
 
@@ -287,6 +318,7 @@ static void __init st_of_flexgen_setup(struct device_node *np)
 	struct clkgen_data *data = NULL;
 	unsigned long flex_flags = 0;
 	int ret;
+	bool clk_mode = 0;
 
 	pnode = of_get_parent(np);
 	if (!pnode)
@@ -304,6 +336,7 @@ static void __init st_of_flexgen_setup(struct device_node *np)
 	if (match) {
 		data = (struct clkgen_data *)match->data;
 		flex_flags = data->flags;
+		clk_mode = data->mode;
 	}
 
 	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
@@ -345,7 +378,7 @@ static void __init st_of_flexgen_setup(struct device_node *np)
 			continue;
 
 		clk = clk_register_flexgen(clk_name, parents, num_parents,
-					   reg, rlock, i, flex_flags);
+					   reg, rlock, i, flex_flags, clk_mode);
 
 		if (IS_ERR(clk))
 			goto err;
-- 
1.9.1



From gabriel.fernandez at linaro.org  Wed May 18 01:41:25 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Wed, 18 May 2016 10:41:25 +0200
Subject: [PATCH 04/11] ARM: DT: STiH407: Add compatibility string on clkgend0
 for audio clocks
In-Reply-To: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <1463560892-7209-5-git-send-email-gabriel.fernandez@linaro.org>

This patch is used in the clock driver to apply a clock propagation
flag on the audio clocks of STiH407

Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
---
 arch/arm/boot/dts/stih407-clock.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/stih407-clock.dtsi b/arch/arm/boot/dts/stih407-clock.dtsi
index ad45f5e..76c6984 100644
--- a/arch/arm/boot/dts/stih407-clock.dtsi
+++ b/arch/arm/boot/dts/stih407-clock.dtsi
@@ -216,7 +216,7 @@
 
 			clk_s_d0_flexgen: clk-s-d0-flexgen {
 				#clock-cells = <1>;
-				compatible = "st,flexgen";
+				compatible = "st,stih407-clkgend0", "st,flexgen";
 
 				clocks = <&clk_s_d0_quadfs 0>,
 					 <&clk_s_d0_quadfs 1>,
-- 
1.9.1



From gabriel.fernandez at linaro.org  Wed May 18 01:41:26 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Wed, 18 May 2016 10:41:26 +0200
Subject: [PATCH 05/11] ARM: DT: STiH410: Add compatibility string on clkgend0
 for audio clocks
In-Reply-To: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <1463560892-7209-6-git-send-email-gabriel.fernandez@linaro.org>

This patch is used in the clock driver to apply a clock propagation
flag on the audio clocks of STiH410

Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
---
 arch/arm/boot/dts/stih410-clock.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/stih410-clock.dtsi b/arch/arm/boot/dts/stih410-clock.dtsi
index d1f2aca..c265e54 100644
--- a/arch/arm/boot/dts/stih410-clock.dtsi
+++ b/arch/arm/boot/dts/stih410-clock.dtsi
@@ -226,7 +226,7 @@
 
 			clk_s_d0_flexgen: clk-s-d0-flexgen {
 				#clock-cells = <1>;
-				compatible = "st,flexgen";
+				compatible = "st,stih407-clkgend0", "st,flexgen";
 
 				clocks = <&clk_s_d0_quadfs 0>,
 					 <&clk_s_d0_quadfs 1>,
-- 
1.9.1



From gabriel.fernandez at linaro.org  Wed May 18 01:41:27 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Wed, 18 May 2016 10:41:27 +0200
Subject: [PATCH 06/11] ARM: DT: STiH418: Add compatibility string on clkgend0
 for audio clocks
In-Reply-To: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <1463560892-7209-7-git-send-email-gabriel.fernandez@linaro.org>

This patch is used in the clock driver to apply a clock propagation
flag on the audio clocks of STiH418

Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
---
 arch/arm/boot/dts/stih418-clock.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/stih418-clock.dtsi b/arch/arm/boot/dts/stih418-clock.dtsi
index ae6d997..9740f41 100644
--- a/arch/arm/boot/dts/stih418-clock.dtsi
+++ b/arch/arm/boot/dts/stih418-clock.dtsi
@@ -229,7 +229,7 @@
 
 			clk_s_d0_flexgen: clk-s-d0-flexgen {
 				#clock-cells = <1>;
-				compatible = "st,flexgen";
+				compatible = "st,stih407-clkgend0", "st,flexgen";
 
 				clocks = <&clk_s_d0_quadfs 0>,
 					 <&clk_s_d0_quadfs 1>,
-- 
1.9.1



From gabriel.fernandez at linaro.org  Wed May 18 01:41:29 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Wed, 18 May 2016 10:41:29 +0200
Subject: [PATCH 08/11] ARM: DT: STiH410: Enable synchronous clock mode on
 clkgend2
In-Reply-To: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <1463560892-7209-9-git-send-email-gabriel.fernandez@linaro.org>

This patch adds a compatibility string on clkgend2 to allow the clock
driver to handle the synchronous/asynchronous modes of STiH410

Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
---
 arch/arm/boot/dts/stih410-clock.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/stih410-clock.dtsi b/arch/arm/boot/dts/stih410-clock.dtsi
index c265e54..479e92d 100644
--- a/arch/arm/boot/dts/stih410-clock.dtsi
+++ b/arch/arm/boot/dts/stih410-clock.dtsi
@@ -268,7 +268,7 @@
 
 			clk_s_d2_flexgen: clk-s-d2-flexgen {
 				#clock-cells = <1>;
-				compatible = "st,flexgen";
+				compatible = "st,stih407-clkgend2", "st,flexgen";
 
 				clocks = <&clk_s_d2_quadfs 0>,
 					 <&clk_s_d2_quadfs 1>,
-- 
1.9.1



From gabriel.fernandez at linaro.org  Wed May 18 01:41:28 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Wed, 18 May 2016 10:41:28 +0200
Subject: [PATCH 07/11] ARM: DT: STiH407: Enable synchronous clock mode on
 clkgend2
In-Reply-To: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <1463560892-7209-8-git-send-email-gabriel.fernandez@linaro.org>

This patch adds a compatibility string on clkgend2 to allow the clock
driver to handle the synchronous/asynchronous modes of STiH407

Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
---
 arch/arm/boot/dts/stih407-clock.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/stih407-clock.dtsi b/arch/arm/boot/dts/stih407-clock.dtsi
index 76c6984..bdf3998 100644
--- a/arch/arm/boot/dts/stih407-clock.dtsi
+++ b/arch/arm/boot/dts/stih407-clock.dtsi
@@ -256,7 +256,7 @@
 
 			clk_s_d2_flexgen: clk-s-d2-flexgen {
 				#clock-cells = <1>;
-				compatible = "st,flexgen";
+				compatible = "st,stih407-clkgend2", "st,flexgen";
 
 				clocks = <&clk_s_d2_quadfs 0>,
 					 <&clk_s_d2_quadfs 1>,
-- 
1.9.1



From gabriel.fernandez at linaro.org  Wed May 18 01:41:30 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Wed, 18 May 2016 10:41:30 +0200
Subject: [PATCH 09/11] ARM: DT: STiH418: Enable synchronous clock mode on
 clkgend2
In-Reply-To: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <1463560892-7209-10-git-send-email-gabriel.fernandez@linaro.org>

This patch adds a compatibility string on clkgend2 to allow the clock
driver to handle the synchronous/asynchronous modes of STiH418

Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
---
 arch/arm/boot/dts/stih418-clock.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/stih418-clock.dtsi b/arch/arm/boot/dts/stih418-clock.dtsi
index 9740f41..4ae70a7 100644
--- a/arch/arm/boot/dts/stih418-clock.dtsi
+++ b/arch/arm/boot/dts/stih418-clock.dtsi
@@ -271,7 +271,7 @@
 
 			clk_s_d2_flexgen: clk-s-d2-flexgen {
 				#clock-cells = <1>;
-				compatible = "st,flexgen";
+				compatible = "st,stih407-clkgend2", "st,flexgen";
 
 				clocks = <&clk_s_d2_quadfs 0>,
 					 <&clk_s_d2_quadfs 1>,
-- 
1.9.1



From gabriel.fernandez at linaro.org  Wed May 18 01:41:31 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Wed, 18 May 2016 10:41:31 +0200
Subject: [PATCH 10/11] ARM: DT: STi: STiH407: clock configuration to address
 720p and 1080p
In-Reply-To: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <1463560892-7209-11-git-send-email-gabriel.fernandez@linaro.org>

It is necessary to properly configure these clocks in order
to address 720p and 1080p HDMI resolution.

Signed-off-by: Vincent Abriou <vincent.abriou at st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
---
 arch/arm/boot/dts/stih407.dtsi | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/stih407.dtsi b/arch/arm/boot/dts/stih407.dtsi
index d60f0d8..291ffac 100644
--- a/arch/arm/boot/dts/stih407.dtsi
+++ b/arch/arm/boot/dts/stih407.dtsi
@@ -16,7 +16,10 @@
 			#size-cells = <1>;
 
 			assigned-clocks	= <&clk_s_d2_quadfs 0>,
-					  <&clk_s_d2_quadfs 0>,
+					  <&clk_s_d2_quadfs 1>,
+					  <&clk_s_c0_pll1 0>,
+					  <&clk_s_c0_flexgen CLK_COMPO_DVP>,
+					  <&clk_s_c0_flexgen CLK_MAIN_DISP>,
 					  <&clk_s_d2_flexgen CLK_PIX_MAIN_DISP>,
 					  <&clk_s_d2_flexgen CLK_PIX_AUX_DISP>,
 					  <&clk_s_d2_flexgen CLK_PIX_GDP1>,
@@ -26,14 +29,21 @@
 
 			assigned-clock-parents = <0>,
 						 <0>,
+						 <0>,
+						 <&clk_s_c0_pll1 0>,
+						 <&clk_s_c0_pll1 0>,
 						 <&clk_s_d2_quadfs 0>,
-						 <&clk_s_d2_quadfs 0>,
+						 <&clk_s_d2_quadfs 1>,
 						 <&clk_s_d2_quadfs 0>,
 						 <&clk_s_d2_quadfs 0>,
 						 <&clk_s_d2_quadfs 0>,
 						 <&clk_s_d2_quadfs 0>;
 
-			assigned-clock-rates = <297000000>, <297000000>;
+			assigned-clock-rates = <297000000>,
+					       <108000000>,
+					       <0>,
+					       <400000000>,
+					       <400000000>;
 
 			ranges;
 
-- 
1.9.1



From gabriel.fernandez at linaro.org  Wed May 18 01:41:32 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Wed, 18 May 2016 10:41:32 +0200
Subject: [PATCH 11/11] ARM: DT: STi: STiH410: clock configuration to address
 720p and 1080p
In-Reply-To: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <1463560892-7209-12-git-send-email-gabriel.fernandez@linaro.org>

It is necessary to properly configure these clocks in order
to address 720p and 1080p HDMI resolution.

Signed-off-by: Vincent Abriou <vincent.abriou at st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
---
 arch/arm/boot/dts/stih410.dtsi | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi
index 18ed1ad..7eec729 100644
--- a/arch/arm/boot/dts/stih410.dtsi
+++ b/arch/arm/boot/dts/stih410.dtsi
@@ -103,7 +103,10 @@
 			#size-cells = <1>;
 
 			assigned-clocks	= <&clk_s_d2_quadfs 0>,
-					  <&clk_s_d2_quadfs 0>,
+					  <&clk_s_d2_quadfs 1>,
+					  <&clk_s_c0_pll1 0>,
+					  <&clk_s_c0_flexgen CLK_COMPO_DVP>,
+					  <&clk_s_c0_flexgen CLK_MAIN_DISP>,
 					  <&clk_s_d2_flexgen CLK_PIX_MAIN_DISP>,
 					  <&clk_s_d2_flexgen CLK_PIX_AUX_DISP>,
 					  <&clk_s_d2_flexgen CLK_PIX_GDP1>,
@@ -113,14 +116,21 @@
 
 			assigned-clock-parents = <0>,
 						 <0>,
+						 <0>,
+						 <&clk_s_c0_pll1 0>,
+						 <&clk_s_c0_pll1 0>,
 						 <&clk_s_d2_quadfs 0>,
-						 <&clk_s_d2_quadfs 0>,
+						 <&clk_s_d2_quadfs 1>,
 						 <&clk_s_d2_quadfs 0>,
 						 <&clk_s_d2_quadfs 0>,
 						 <&clk_s_d2_quadfs 0>,
 						 <&clk_s_d2_quadfs 0>;
 
-			assigned-clock-rates = <297000000>, <297000000>;
+			assigned-clock-rates = <297000000>,
+					       <108000000>,
+					       <0>,
+					       <400000000>,
+					       <400000000>;
 
 			ranges;
 
-- 
1.9.1



From kishon at ti.com  Wed May 18 01:45:12 2016
From: kishon at ti.com (Kishon Vijay Abraham I)
Date: Wed, 18 May 2016 14:15:12 +0530
Subject: [RFC PATCH 0/3] dra7/omap4/omap5: Enable ADMA2
Message-ID: <1463561115-31798-1-git-send-email-kishon@ti.com>

Add ADMA2 support in omap hsmmc driver. It's not added as
a dma engine since ADMA2 is only implemented in HSMMC.

Though this doesn't improve the throughput with high speed
cards, around 25% improvement is seen with HS200 card.

HS200 support is not yet added in OMAP HSMMC since
it has dependency with IODelay driver which is not yet
upstreamed.

Tested MMC1 and MMC2 in DRA7 (dra72-evm, dra7-evm) and OMAP5
(omap5-uevm).
Also tested having rootfs in MMC1 in DRA7, OMAP5, OMAP4 and OMAP3.

Kishon Vijay Abraham I (3):
  mmc: host: omap_hsmmc: remove *use_dma* member
  mmc: host: omap_hsmmc: Enable ADMA2
  ARM: dts: dra7/omap4/omap5: Enable ADMA2

 .../devicetree/bindings/mmc/ti-omap-hsmmc.txt      |    1 +
 arch/arm/boot/dts/dra7.dtsi                        |    4 +
 arch/arm/boot/dts/omap4.dtsi                       |    2 +
 arch/arm/boot/dts/omap5.dtsi                       |    4 +
 drivers/mmc/host/omap_hsmmc.c                      |  332 +++++++++++++++-----
 include/linux/platform_data/hsmmc-omap.h           |    1 +
 6 files changed, 269 insertions(+), 75 deletions(-)

-- 
1.7.9.5



From kishon at ti.com  Wed May 18 01:45:13 2016
From: kishon at ti.com (Kishon Vijay Abraham I)
Date: Wed, 18 May 2016 14:15:13 +0530
Subject: [RFC PATCH 1/3] mmc: host: omap_hsmmc: remove *use_dma* member
In-Reply-To: <1463561115-31798-1-git-send-email-kishon@ti.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
Message-ID: <1463561115-31798-2-git-send-email-kishon@ti.com>

omap_hsmmc doesn't support polled I/O. So remove *use_dma*
which is always set to '1'.

Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
---
 drivers/mmc/host/omap_hsmmc.c |   36 +++++++++++++++---------------------
 1 file changed, 15 insertions(+), 21 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index f9ac3bb..cc916d5 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -198,7 +198,7 @@ struct omap_hsmmc_host {
 	u32			capa;
 	int			irq;
 	int			wake_irq;
-	int			use_dma, dma_ch;
+	int			dma_ch;
 	struct dma_chan		*tx_chan;
 	struct dma_chan		*rx_chan;
 	int			response_busy;
@@ -582,8 +582,8 @@ static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host,
 	u32 irq_mask = INT_EN_MASK;
 	unsigned long flags;
 
-	if (host->use_dma)
-		irq_mask &= ~(BRR_EN | BWR_EN);
+	/* BRR and BWR need not be enabled for DMA */
+	irq_mask &= ~(BRR_EN | BWR_EN);
 
 	/* Disable timeout for erases */
 	if (cmd->opcode == MMC_ERASE)
@@ -928,8 +928,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
 			cmdreg &= ~(DDIR);
 	}
 
-	if (host->use_dma)
-		cmdreg |= DMAE;
+	cmdreg |= DMAE;
 
 	host->req_in_progress = 1;
 
@@ -964,7 +963,7 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
 
 	omap_hsmmc_disable_irq(host);
 	/* Do not complete the request if DMA is still in progress */
-	if (mrq->data && host->use_dma && dma_ch != -1)
+	if (mrq->data && dma_ch != -1)
 		return;
 	host->mrq = NULL;
 	mmc_request_done(host->mmc, mrq);
@@ -1053,7 +1052,7 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
 	host->dma_ch = -1;
 	spin_unlock_irqrestore(&host->irq_lock, flags);
 
-	if (host->use_dma && dma_ch != -1) {
+	if (dma_ch != -1) {
 		struct dma_chan *chan = omap_hsmmc_get_dma_chan(host, host->data);
 
 		dmaengine_terminate_all(chan);
@@ -1548,12 +1547,10 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
 		return 0;
 	}
 
-	if (host->use_dma) {
-		ret = omap_hsmmc_setup_dma_transfer(host, req);
-		if (ret != 0) {
-			dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
-			return ret;
-		}
+	ret = omap_hsmmc_setup_dma_transfer(host, req);
+	if (ret != 0) {
+		dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
+		return ret;
 	}
 	return 0;
 }
@@ -1564,7 +1561,7 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
 	struct mmc_data *data = mrq->data;
 
-	if (host->use_dma && data->host_cookie) {
+	if (data->host_cookie) {
 		struct dma_chan *c = omap_hsmmc_get_dma_chan(host, data);
 
 		dma_unmap_sg(c->device->dev, data->sg, data->sg_len,
@@ -1583,13 +1580,11 @@ static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
 		return ;
 	}
 
-	if (host->use_dma) {
-		struct dma_chan *c = omap_hsmmc_get_dma_chan(host, mrq->data);
+	struct dma_chan *c = omap_hsmmc_get_dma_chan(host, mrq->data);
 
-		if (omap_hsmmc_pre_dma_transfer(host, mrq->data,
-						&host->next_data, c))
-			mrq->data->host_cookie = 0;
-	}
+	if (omap_hsmmc_pre_dma_transfer(host, mrq->data,
+					&host->next_data, c))
+		mrq->data->host_cookie = 0;
 }
 
 /*
@@ -2052,7 +2047,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	host->mmc	= mmc;
 	host->pdata	= pdata;
 	host->dev	= &pdev->dev;
-	host->use_dma	= 1;
 	host->dma_ch	= -1;
 	host->irq	= irq;
 	host->mapbase	= res->start + pdata->reg_offset;
-- 
1.7.9.5



From kishon at ti.com  Wed May 18 01:45:14 2016
From: kishon at ti.com (Kishon Vijay Abraham I)
Date: Wed, 18 May 2016 14:15:14 +0530
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <1463561115-31798-1-git-send-email-kishon@ti.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
Message-ID: <1463561115-31798-3-git-send-email-kishon@ti.com>

omap hsmmc host controller has ADMA2 feature. Enable it here
for better read and write throughput. Add a new dt binding
"ti,use_adma" to enable ADMA2.

Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
---
 .../devicetree/bindings/mmc/ti-omap-hsmmc.txt      |    1 +
 drivers/mmc/host/omap_hsmmc.c                      |  320 ++++++++++++++++----
 include/linux/platform_data/hsmmc-omap.h           |    1 +
 3 files changed, 256 insertions(+), 66 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
index 74166a0..eb5ceec2 100644
--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
@@ -28,6 +28,7 @@ specifier is required.
 dma-names: List of DMA request names. These strings correspond
 1:1 with the DMA specifiers listed in dmas. The string naming is
 to be "rx" and "tx" for RX and TX DMA requests, respectively.
+ti,use_adma: enable adma2 feature
 
 Examples:
 
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index cc916d5..b4a7d18 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -66,6 +66,8 @@
 #define OMAP_HSMMC_ISE		0x0138
 #define OMAP_HSMMC_AC12		0x013C
 #define OMAP_HSMMC_CAPA		0x0140
+#define OMAP_HSMMC_ADMAES	0x0154
+#define OMAP_HSMMC_ADMASAL	0x0158
 
 #define VS18			(1 << 26)
 #define VS30			(1 << 25)
@@ -76,6 +78,7 @@
 #define SDVS_MASK		0x00000E00
 #define SDVSCLR			0xFFFFF1FF
 #define SDVSDET			0x00000400
+#define DMA_SELECT		(2 << 3)
 #define AUTOIDLE		0x1
 #define SDBP			(1 << 8)
 #define DTO			0xe
@@ -97,6 +100,7 @@
 #define FOUR_BIT		(1 << 1)
 #define HSPE			(1 << 2)
 #define IWE			(1 << 24)
+#define DMA_MASTER		(1 << 20)
 #define DDR			(1 << 19)
 #define CLKEXTFREE		(1 << 16)
 #define CTPL			(1 << 11)
@@ -127,10 +131,11 @@
 #define DCRC_EN			(1 << 21)
 #define DEB_EN			(1 << 22)
 #define ACE_EN			(1 << 24)
+#define ADMAE_EN		(1 << 24)
 #define CERR_EN			(1 << 28)
 #define BADA_EN			(1 << 29)
 
-#define INT_EN_MASK (BADA_EN | CERR_EN | ACE_EN | DEB_EN | DCRC_EN |\
+#define INT_EN_MASK (BADA_EN | CERR_EN | ADMAE_EN | ACE_EN | DEB_EN | DCRC_EN |\
 		DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \
 		BRR_EN | BWR_EN | TC_EN | CC_EN)
 
@@ -168,6 +173,25 @@
 #define OMAP_HSMMC_WRITE(base, reg, val) \
 	__raw_writel((val), (base) + OMAP_HSMMC_##reg)
 
+struct omap_hsmmc_adma_desc {
+	u8 attr;
+	u8 reserved;
+	u16 len;
+	u32 addr;
+} __packed;
+
+#define ADMA_MAX_LEN			65532
+
+/* Decriptor table defines */
+#define ADMA_DESC_ATTR_VALID		BIT(0)
+#define ADMA_DESC_ATTR_END		BIT(1)
+#define ADMA_DESC_ATTR_INT		BIT(2)
+#define ADMA_DESC_ATTR_ACT1		BIT(4)
+#define ADMA_DESC_ATTR_ACT2		BIT(5)
+
+#define ADMA_DESC_TRANSFER_DATA		ADMA_DESC_ATTR_ACT2
+#define ADMA_DESC_LINK_DESC	(ADMA_DESC_ATTR_ACT1 | ADMA_DESC_ATTR_ACT2)
+
 struct omap_hsmmc_next {
 	unsigned int	dma_len;
 	s32		cookie;
@@ -213,6 +237,9 @@ struct omap_hsmmc_host {
 	struct omap_hsmmc_next	next_data;
 	struct	omap_hsmmc_platform_data	*pdata;
 
+	struct omap_hsmmc_adma_desc *adma_desc_table;
+	dma_addr_t              adma_desc_table_addr;
+
 	/* return MMC cover switch state, can be NULL if not supported.
 	 *
 	 * possible return values:
@@ -951,6 +978,19 @@ static struct dma_chan *omap_hsmmc_get_dma_chan(struct omap_hsmmc_host *host,
 	return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan;
 }
 
+static void omap_hsmmc_adma_cleanup(struct omap_hsmmc_host *host)
+{
+	u32 val;
+
+	val = OMAP_HSMMC_READ(host->base, HCTL);
+	val &= ~DMA_SELECT;
+	OMAP_HSMMC_WRITE(host->base, HCTL, val);
+
+	val = OMAP_HSMMC_READ(host->base, CON);
+	val &= ~DMA_MASTER;
+	OMAP_HSMMC_WRITE(host->base, CON, val);
+}
+
 static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_request *mrq)
 {
 	int dma_ch;
@@ -963,8 +1003,11 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
 
 	omap_hsmmc_disable_irq(host);
 	/* Do not complete the request if DMA is still in progress */
-	if (mrq->data && dma_ch != -1)
+	if (host->pdata->controller_flags == OMAP_HSMMC_USE_ADMA)
+		omap_hsmmc_adma_cleanup(host);
+	else if (mrq->data && dma_ch != -1)
 		return;
+
 	host->mrq = NULL;
 	mmc_request_done(host->mmc, mrq);
 	pm_runtime_mark_last_busy(host->dev);
@@ -1052,15 +1095,22 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
 	host->dma_ch = -1;
 	spin_unlock_irqrestore(&host->irq_lock, flags);
 
-	if (dma_ch != -1) {
-		struct dma_chan *chan = omap_hsmmc_get_dma_chan(host, host->data);
-
-		dmaengine_terminate_all(chan);
-		dma_unmap_sg(chan->device->dev,
-			host->data->sg, host->data->sg_len,
+	if (!(host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)) {
+		if (dma_ch != -1) {
+			struct dma_chan *chan = omap_hsmmc_get_dma_chan(host,
+								host->data);
+			dmaengine_terminate_all(chan);
+			dma_unmap_sg(chan->device->dev,
+				     host->data->sg, host->data->sg_len,
 			omap_hsmmc_get_dma_dir(host, host->data));
 
+			host->data->host_cookie = 0;
+		}
+	} else {
+		dma_unmap_sg(host->dev, host->data->sg, host->data->sg_len,
+			     omap_hsmmc_get_dma_dir(host, host->data));
 		host->data->host_cookie = 0;
+
 	}
 	host->data = NULL;
 }
@@ -1191,6 +1241,14 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
 			}
 			dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12);
 		}
+
+		if (status & ADMAE_EN) {
+			u32 val;
+
+			val = OMAP_HSMMC_READ(host->base, ADMAES);
+			dev_dbg(mmc_dev(host->mmc), "ADMA error status: 0x%x\n",
+				val);
+		}
 	}
 
 	OMAP_HSMMC_WRITE(host->base, STAT, status);
@@ -1378,6 +1436,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
 				       struct dma_chan *chan)
 {
 	int dma_len;
+	struct device *dev;
 
 	if (!next && data->host_cookie &&
 	    data->host_cookie != host->next_data.cookie) {
@@ -1387,9 +1446,14 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
 		data->host_cookie = 0;
 	}
 
+	if (chan)
+		dev = chan->device->dev;
+	else
+		dev = mmc_dev(host->mmc);
+
 	/* Check if next job is already prepared */
 	if (next || data->host_cookie != host->next_data.cookie) {
-		dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len,
+		dma_len = dma_map_sg(dev, data->sg, data->sg_len,
 				     omap_hsmmc_get_dma_dir(host, data));
 
 	} else {
@@ -1516,6 +1580,7 @@ static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host)
 {
 	struct mmc_request *req = host->mrq;
 	struct dma_chan *chan;
+	int val;
 
 	if (!req->data)
 		return;
@@ -1523,10 +1588,66 @@ static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host)
 				| (req->data->blocks << 16));
 	set_data_timeout(host, req->data->timeout_ns,
 				req->data->timeout_clks);
-	chan = omap_hsmmc_get_dma_chan(host, req->data);
-	dma_async_issue_pending(chan);
+
+	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA) {
+		val = OMAP_HSMMC_READ(host->base, HCTL);
+		val |= DMA_SELECT;
+		OMAP_HSMMC_WRITE(host->base, HCTL, val);
+
+		val = OMAP_HSMMC_READ(host->base, CON);
+		val |= DMA_MASTER;
+		OMAP_HSMMC_WRITE(host->base, CON, val);
+
+		OMAP_HSMMC_WRITE(host->base, ADMASAL,
+				 (u32)host->adma_desc_table_addr);
+	} else {
+		chan = omap_hsmmc_get_dma_chan(host, req->data);
+		dma_async_issue_pending(chan);
+	}
+}
+
+static int omap_hsmmc_write_adma_desc(struct omap_hsmmc_host *host, void *desc,
+				      dma_addr_t addr, u16 len, u8 attr)
+{
+	struct omap_hsmmc_adma_desc *dma_desc = desc;
+
+	dma_desc->len = len;
+	dma_desc->addr = (u32)addr;
+	dma_desc->reserved = 0;
+	dma_desc->attr = attr;
+
+	return 0;
 }
 
+static int omap_hsmmc_setup_adma_transfer(struct omap_hsmmc_host *host,
+					  struct mmc_request *req)
+{
+	struct mmc_data *data = req->data;
+	struct scatterlist *sg;
+	int i;
+	int len;
+	int ret;
+	dma_addr_t addr;
+	struct omap_hsmmc_adma_desc *dma_desc;
+
+	ret = omap_hsmmc_pre_dma_transfer(host, data, NULL, NULL);
+	if (ret)
+		return ret;
+
+	dma_desc = host->adma_desc_table;
+	for_each_sg(data->sg, sg, host->dma_len, i) {
+		addr = sg_dma_address(sg);
+		len = sg_dma_len(sg);
+		WARN_ON(len > ADMA_MAX_LEN);
+		omap_hsmmc_write_adma_desc(host, dma_desc, addr, len,
+					   ADMA_DESC_ATTR_VALID |
+					   ADMA_DESC_TRANSFER_DATA);
+		dma_desc++;
+	}
+	omap_hsmmc_write_adma_desc(host, dma_desc, 0, 0, ADMA_DESC_ATTR_END);
+
+	return 0;
+}
 /*
  * Configure block length for MMC/SD cards and initiate the transfer.
  */
@@ -1547,10 +1668,18 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
 		return 0;
 	}
 
-	ret = omap_hsmmc_setup_dma_transfer(host, req);
-	if (ret != 0) {
-		dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
-		return ret;
+	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA) {
+		ret = omap_hsmmc_setup_adma_transfer(host, req);
+		if (ret != 0) {
+			dev_err(mmc_dev(host->mmc), "MMC adma setup failed\n");
+			return ret;
+		}
+	} else {
+		ret = omap_hsmmc_setup_dma_transfer(host, req);
+		if (ret != 0) {
+			dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
+			return ret;
+		}
 	}
 	return 0;
 }
@@ -1560,11 +1689,18 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
 {
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
 	struct mmc_data *data = mrq->data;
+	struct device *dev;
+	struct dma_chan *c;
 
 	if (data->host_cookie) {
-		struct dma_chan *c = omap_hsmmc_get_dma_chan(host, data);
+		if (!(host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)) {
+			c = omap_hsmmc_get_dma_chan(host, mrq->data);
+			dev = c->device->dev;
+		} else {
+			dev = mmc_dev(mmc);
+		}
 
-		dma_unmap_sg(c->device->dev, data->sg, data->sg_len,
+		dma_unmap_sg(dev, data->sg, data->sg_len,
 			     omap_hsmmc_get_dma_dir(host, data));
 		data->host_cookie = 0;
 	}
@@ -1574,13 +1710,15 @@ static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
 			       bool is_first_req)
 {
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
+	struct dma_chan *c = NULL;
 
 	if (mrq->data->host_cookie) {
 		mrq->data->host_cookie = 0;
 		return ;
 	}
 
-	struct dma_chan *c = omap_hsmmc_get_dma_chan(host, mrq->data);
+	if (!(host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA))
+		c = omap_hsmmc_get_dma_chan(host, mrq->data);
 
 	if (omap_hsmmc_pre_dma_transfer(host, mrq->data,
 					&host->next_data, c))
@@ -1967,6 +2105,9 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
 	if (of_find_property(np, "ti,dual-volt", NULL))
 		pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT;
 
+	if (of_find_property(np, "ti,use_adma", NULL))
+		pdata->controller_flags |= OMAP_HSMMC_USE_ADMA;
+
 	pdata->gpio_cd = -EINVAL;
 	pdata->gpio_cod = -EINVAL;
 	pdata->gpio_wp = -EINVAL;
@@ -1992,6 +2133,84 @@ static inline struct omap_hsmmc_platform_data
 }
 #endif
 
+static int omap_hsmmc_adma_init(struct omap_hsmmc_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+
+	host->adma_desc_table = dma_alloc_coherent(host->dev, mmc->max_segs + 1,
+						   &host->adma_desc_table_addr,
+						   GFP_KERNEL);
+	if (!host->adma_desc_table) {
+		dev_err(host->dev, "failed to allocate adma desc table\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void omap_hsmmc_adma_exit(struct omap_hsmmc_host *host)
+{
+	struct mmc_host *mmc = host->mmc;
+
+	dma_free_coherent(host->dev, mmc->max_segs + 1,
+			  host->adma_desc_table, host->adma_desc_table_addr);
+}
+
+static int omap_hsmmc_dma_init(struct omap_hsmmc_host *host)
+{
+	dma_cap_mask_t mask;
+	unsigned int tx_req, rx_req;
+	struct resource *res;
+	struct platform_device *pdev = to_platform_device(host->dev);
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	if (!pdev->dev.of_node) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+		if (!res) {
+			dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
+			return -ENXIO;
+		}
+		tx_req = res->start;
+
+		res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+		if (!res) {
+			dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
+			return -ENXIO;
+		}
+		rx_req = res->start;
+	}
+
+	host->rx_chan =
+		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+						 &rx_req, &pdev->dev, "rx");
+
+	if (!host->rx_chan) {
+		dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
+		return -ENXIO;
+	}
+
+	host->tx_chan =
+		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+						 &tx_req, &pdev->dev, "tx");
+
+	if (!host->tx_chan) {
+		dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+static void omap_hsmmc_dma_exit(struct omap_hsmmc_host *host)
+{
+	if (host->tx_chan)
+		dma_release_channel(host->tx_chan);
+	if (host->rx_chan)
+		dma_release_channel(host->rx_chan);
+}
+
 static int omap_hsmmc_probe(struct platform_device *pdev)
 {
 	struct omap_hsmmc_platform_data *pdata = pdev->dev.platform_data;
@@ -2000,8 +2219,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	struct resource *res;
 	int ret, irq;
 	const struct of_device_id *match;
-	dma_cap_mask_t mask;
-	unsigned tx_req, rx_req;
 	const struct omap_mmc_of_data *data;
 	void __iomem *base;
 
@@ -2114,7 +2331,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	mmc->max_blk_size = 512;       /* Block Length at max can be 1024 */
 	mmc->max_blk_count = 0xFFFF;    /* No. of Blocks is 16 bits */
 	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-	mmc->max_seg_size = mmc->max_req_size;
+	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
+		mmc->max_seg_size = ADMA_MAX_LEN;
+	else
+		mmc->max_seg_size = mmc->max_req_size;
 
 	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
 		     MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
@@ -2130,46 +2350,12 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 
 	omap_hsmmc_conf_bus_power(host);
 
-	if (!pdev->dev.of_node) {
-		res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
-		if (!res) {
-			dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
-			ret = -ENXIO;
-			goto err_irq;
-		}
-		tx_req = res->start;
-
-		res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
-		if (!res) {
-			dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
-			ret = -ENXIO;
-			goto err_irq;
-		}
-		rx_req = res->start;
-	}
-
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-
-	host->rx_chan =
-		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
-						 &rx_req, &pdev->dev, "rx");
-
-	if (!host->rx_chan) {
-		dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
-		ret = -ENXIO;
-		goto err_irq;
-	}
-
-	host->tx_chan =
-		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
-						 &tx_req, &pdev->dev, "tx");
-
-	if (!host->tx_chan) {
-		dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
-		ret = -ENXIO;
+	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
+		ret = omap_hsmmc_adma_init(host);
+	else
+		ret = omap_hsmmc_dma_init(host);
+	if (ret)
 		goto err_irq;
-	}
 
 	/* Request IRQ for MMC operations */
 	ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0,
@@ -2225,11 +2411,11 @@ err_slot_name:
 	mmc_remove_host(mmc);
 err_irq:
 	device_init_wakeup(&pdev->dev, false);
-	if (host->tx_chan)
-		dma_release_channel(host->tx_chan);
-	if (host->rx_chan)
-		dma_release_channel(host->rx_chan);
 	pm_runtime_dont_use_autosuspend(host->dev);
+	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
+		omap_hsmmc_adma_exit(host);
+	else
+		omap_hsmmc_dma_exit(host);
 	pm_runtime_put_sync(host->dev);
 	pm_runtime_disable(host->dev);
 	if (host->dbclk)
@@ -2248,8 +2434,10 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
 	pm_runtime_get_sync(host->dev);
 	mmc_remove_host(host->mmc);
 
-	dma_release_channel(host->tx_chan);
-	dma_release_channel(host->rx_chan);
+	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
+		omap_hsmmc_adma_exit(host);
+	else
+		omap_hsmmc_dma_exit(host);
 
 	pm_runtime_dont_use_autosuspend(host->dev);
 	pm_runtime_put_sync(host->dev);
diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h
index 8e981be..e26013d 100644
--- a/include/linux/platform_data/hsmmc-omap.h
+++ b/include/linux/platform_data/hsmmc-omap.h
@@ -27,6 +27,7 @@
 #define OMAP_HSMMC_SUPPORTS_DUAL_VOLT		BIT(0)
 #define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ	BIT(1)
 #define OMAP_HSMMC_SWAKEUP_MISSING		BIT(2)
+#define OMAP_HSMMC_USE_ADMA			BIT(3)
 
 struct omap_hsmmc_dev_attr {
 	u8 flags;
-- 
1.7.9.5



From kishon at ti.com  Wed May 18 01:45:15 2016
From: kishon at ti.com (Kishon Vijay Abraham I)
Date: Wed, 18 May 2016 14:15:15 +0530
Subject: [RFC PATCH 3/3] ARM: dts: dra7/omap4/omap5: Enable ADMA2
In-Reply-To: <1463561115-31798-1-git-send-email-kishon@ti.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
Message-ID: <1463561115-31798-4-git-send-email-kishon@ti.com>

Now that ADMA2 support is added in omap hsmmc controller driver,
enable ADMA2 for all the mmc instances that has ADMA2 support in
DRA7, OMAP4 and OMAP5 SoCs.

Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
---
 arch/arm/boot/dts/dra7.dtsi  |    4 ++++
 arch/arm/boot/dts/omap4.dtsi |    2 ++
 arch/arm/boot/dts/omap5.dtsi |    4 ++++
 3 files changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 13ac882..a63df6b 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -883,6 +883,7 @@
 			ti,hwmods = "mmc1";
 			ti,dual-volt;
 			ti,needs-special-reset;
+			ti,use_adma;
 			dmas = <&sdma_xbar 61>, <&sdma_xbar 62>;
 			dma-names = "tx", "rx";
 			status = "disabled";
@@ -895,6 +896,7 @@
 			interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "mmc2";
 			ti,needs-special-reset;
+			ti,use_adma;
 			dmas = <&sdma_xbar 47>, <&sdma_xbar 48>;
 			dma-names = "tx", "rx";
 			status = "disabled";
@@ -906,6 +908,7 @@
 			interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "mmc3";
 			ti,needs-special-reset;
+			ti,use_adma;
 			dmas = <&sdma_xbar 77>, <&sdma_xbar 78>;
 			dma-names = "tx", "rx";
 			status = "disabled";
@@ -917,6 +920,7 @@
 			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "mmc4";
 			ti,needs-special-reset;
+			ti,use_adma;
 			dmas = <&sdma_xbar 57>, <&sdma_xbar 58>;
 			dma-names = "tx", "rx";
 			status = "disabled";
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 421fe9f..23c78b4 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -513,6 +513,7 @@
 			ti,hwmods = "mmc1";
 			ti,dual-volt;
 			ti,needs-special-reset;
+			ti,use_adma;
 			dmas = <&sdma 61>, <&sdma 62>;
 			dma-names = "tx", "rx";
 			pbias-supply = <&pbias_mmc_reg>;
@@ -524,6 +525,7 @@
 			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "mmc2";
 			ti,needs-special-reset;
+			ti,use_adma;
 			dmas = <&sdma 47>, <&sdma 48>;
 			dma-names = "tx", "rx";
 		};
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 120b6b8..3bf113b 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -566,6 +566,7 @@
 			ti,hwmods = "mmc1";
 			ti,dual-volt;
 			ti,needs-special-reset;
+			ti,use_adma;
 			dmas = <&sdma 61>, <&sdma 62>;
 			dma-names = "tx", "rx";
 			pbias-supply = <&pbias_mmc_reg>;
@@ -577,6 +578,7 @@
 			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "mmc2";
 			ti,needs-special-reset;
+			ti,use_adma;
 			dmas = <&sdma 47>, <&sdma 48>;
 			dma-names = "tx", "rx";
 		};
@@ -587,6 +589,7 @@
 			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "mmc3";
 			ti,needs-special-reset;
+			ti,use_adma;
 			dmas = <&sdma 77>, <&sdma 78>;
 			dma-names = "tx", "rx";
 		};
@@ -597,6 +600,7 @@
 			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "mmc4";
 			ti,needs-special-reset;
+			ti,use_adma;
 			dmas = <&sdma 57>, <&sdma 58>;
 			dma-names = "tx", "rx";
 		};
-- 
1.7.9.5



From matt at codeblueprint.co.uk  Wed May 18 01:53:48 2016
From: matt at codeblueprint.co.uk (Matt Fleming)
Date: Wed, 18 May 2016 09:53:48 +0100
Subject: [PATCH v2 1/2] efi: esrt: use memremap not ioremap to access
 ESRT table in memory
In-Reply-To: <CAKv+Gu_ekP+44FJjR7BY_MFqx2jQgc6Tk9W4SBL__ttdvQ55VQ@mail.gmail.com>
References: <20160218132824.GE2651@codeblueprint.co.uk>
 <CAKv+Gu-s1pzYBzuDG-Z7s3gyo8dPOfeidZQ+rim-uAWZCBcKQQ@mail.gmail.com>
 <20160218134324.GG2651@codeblueprint.co.uk>
 <CAKv+Gu875r9RkDC723kNsG4XC0eSE9RPPmSFZrD0sx0QxS+V4g@mail.gmail.com>
 <20160218141544.GH2651@codeblueprint.co.uk>
 <20160218191624.GA1515@redhat.com>
 <20160226144114.GA7475@codeblueprint.co.uk>
 <20160301233040.GA31476@codeblueprint.co.uk>
 <20160304062524.GA19010@dhcp-128-65.nay.redhat.com>
 <CAKv+Gu_ekP+44FJjR7BY_MFqx2jQgc6Tk9W4SBL__ttdvQ55VQ@mail.gmail.com>
Message-ID: <20160518085348.GG21993@codeblueprint.co.uk>

On Wed, 18 May, at 10:36:33AM, Ard Biesheuvel wrote:
> 
> So what is the status here? I know Sai is working on x86 support for
> the memory attributes table, so it would make sense settle this matter
> as well.

This got stuck behind some other work, sorry about that.

Some of this was just merged by Linus (getting rid of the global
memmap and switching everyone over to efi.memmap), a large chunk
remains however.

I should be able to get those patches mailed out once the merge window
closes.


From LW at KARO-electronics.de  Wed May 18 02:12:43 2016
From: LW at KARO-electronics.de (Lothar =?UTF-8?B?V2HDn21hbm4=?=)
Date: Wed, 18 May 2016 11:12:43 +0200
Subject: imx-drm: regression due to commit 503fe87bd0a8 ("gpu: ipu-v3:
 Fix imx-ipuv3-crtc module autoloading")
In-Reply-To: <1463137452.3544.5.camel@pengutronix.de>
References: <20160513123336.6996dd89@ipc1.ka-ro>
 <1463137452.3544.5.camel@pengutronix.de>
Message-ID: <20160518111243.111b8e9c@ipc1.ka-ro>

Hi,

On Fri, 13 May 2016 13:04:12 +0200 Philipp Zabel wrote:
> Hi Lothar,
> 
> Am Freitag, den 13.05.2016, 12:33 +0200 schrieb Lothar Wa?mann:
> > Hi,
> > 
> > the commit 503fe87bd0a8 ("gpu: ipu-v3: Fix imx-ipuv3-crtc module autoloading")
> > indeed fixes the autoloading issue, but completely breaks the driver in
> > non-modular mode (at least with the parallel-display driver I didn't
> > yet check with the imx-ldb driver.
> > Can anyone confirm that the imx-drm driver in current linux-next
> > (next-20160512) works for them with any i.MX6 or i.MX53 board?
> 
> I have sent a patch: https://patchwork.kernel.org/patch/9081661/
> that I'd appreciate your input on.
> 
This patch works for the parallel-display driver but not for imx-ldb
(I didn't test the TV or HDMI drivers). It works when the DRM driver is
built as modules, but when it is non-modular I get a framebuffer
device which is useable from userspace, but no output on the LVDS
interface.

When reverting 503fe87bd0a8346ba9d8b7f49115dcd0a4185226 instead of
applying the above patch, the builtin driver works normally.


Lothar Wa?mann


From shawn.lin at rock-chips.com  Wed May 18 02:14:43 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Wed, 18 May 2016 17:14:43 +0800
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <CAD=FV=VneQR3wurjezBkRhtQiH+q-FfhDN8=Ym=XqtZpVmsdUw@mail.gmail.com>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <5502CA4E.9060401@samsung.com>
 <CAD=FV=VX3ix-j4y95W1q8b-aVuVEN+4xsd8WLx2xcE7KPNJwRw@mail.gmail.com>
 <5506707D.40708@samsung.com> <55189F04.8000404@samsung.com>
 <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
 <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
 <573BCC8D.5090606@kernel-upstream.org>
 <CAD=FV=VneQR3wurjezBkRhtQiH+q-FfhDN8=Ym=XqtZpVmsdUw@mail.gmail.com>
Message-ID: <573C3283.1040606@rock-chips.com>

Hi

On 2016-5-18 12:12, Doug Anderson wrote:
> Hi,
>
> On Tue, May 17, 2016 at 6:59 PM, Shawn Lin
> <shawn.lin at kernel-upstream.org> wrote:
>> Could you try this patch to see if you can still find HLE?
>>
>> @@ -2356,12 +2356,22 @@ static void dw_mci_cmd_interrupt(struct dw_mci
>> *host, u32 status)
>>   static void dw_mci_handle_cd(struct dw_mci *host)
>>   {
>>          int i;
>> +       int present;
>>
>>          for (i = 0; i < host->num_slots; i++) {
>>                  struct dw_mci_slot *slot = host->slot[i];
>>
>>                  if (!slot)
>>                          continue;
>>
>> +               present = !(mci_readl(slot->host, CDETECT) & (1 <<
>> slot->id));
>> +               if (present)
>> +                       set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>> +               else
>> +                       clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>
> No, because we don't use the builtin card detect on veyron.  ;)
>
> We use GPIO card detect because we didn't like the way JTAG and SD
> interacted.  Also on rk3288 the builtin card detect line had the wrong
> voltage domain (you couldn't detect a card when the IO lines were
> powered off).  The builtin card detect line is always driven low on
> veyron.

Okay, I see.

>
>
> I'm nearly certain that the root cause of my HLE errors is actually
> related to the same problem addressed by the commit 7c5209c315ea
> ("mmc: core: Increase delay for voltage to stabilize from 3.3V to
> 1.8V").  I think that on minnie we're still on the hairy edge and
> sometimes the line doesn't transition fast enough.

Things are not so simple from your details.

I was not enabling SD3.0 support, then I also found HLE sometimes.
So it seems commit 7c5209c315ea does not contibute to this phenomenon.

The scenario looks like:
remove sd-card -> mmc_sd_detect -> send status(CMD13) ->power_off ->
set_ios -> setup_bus -> disabled clk , then HLE irq storm coming

 From the code of dw_mci_prepare_command:
SDMMC_CMD_PRV_DAT_WAIT will not be used for CMD13, so we don't
wait_busy here, then cmd code is loding into queue of dw_mmc but
still failing send out because it's in busy?

With my patch, things go well:
remove sd-card -> clear bit of DW_MMC_CARD_PRESENT  -> send
status(CMD13) return directly -> power_off -> set_ios -> setup_bus -> 
disable clk

So why should we allow inquiry of card status if we sure the card is
removed? I mean no any further cmds should be delivered.

And another question: should we wait busy for cmd13?

>
> It appears that increasing this to 30ms avoids the HLE errors.
>
> I _think_ I can actually fully fix this properly by temporarily
> engaging the internal pull-ups while the voltage switch is happening.
> This will bleed away the voltage just a little bit faster (since lines
> are driven low here).  I'll try to confirm that.
>
>
> In any case, it seems like we should take this patch since (without
> this patch) the failure case when you get HLE errors is that the
> interrupt controller fires over and over again (with no printouts) and
> your system stalls with no error messages.

Sure, at least we need to address this irq storm...

>
> -Doug
>
>
>



From arnd at arndb.de  Wed May 18 02:31:17 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 11:31:17 +0200
Subject: [RESEND PATCH v6 0/6] Add Ethernet support on STM32F429
In-Reply-To: <CALszF6AE7jkRX3sSNm=PCvEmkmZM-Sv5LxFSj7J3vMbvi8M5Cg@mail.gmail.com>
References: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
 <20160517.122527.1937360418899371800.davem@davemloft.net>
 <CALszF6AE7jkRX3sSNm=PCvEmkmZM-Sv5LxFSj7J3vMbvi8M5Cg@mail.gmail.com>
Message-ID: <2535270.dCFPoM2olB@wuerfel>

On Wednesday 18 May 2016 09:48:53 Maxime Coquelin wrote:
> 2016-05-17 18:25 GMT+02:00 David Miller <davem at davemloft.net>:
> > From: Maxime Coquelin <mcoquelin.stm32 at gmail.com>
> > Date: Tue, 17 May 2016 11:20:16 +0200
> >
> >> Hi David,
> >>
> >> 2016-05-09 21:06 GMT+02:00 David Miller <davem at davemloft.net>:
> >>> From: Alexandre TORGUE <alexandre.torgue at gmail.com>
> >>> Date: Mon,  9 May 2016 12:31:33 +0200
> >>>
> >>>> STM32F429 Chip embeds a Synopsys 3.50a MAC IP.
> >>>> This series:
> >>>>  -enhance current stmmac driver to control it (code already
> >>>> available) and adds basic glue for STM32F429 chip.
> >>>>  -Enable basic Net config in kernel.
> >>>
> >>> I assume this will go via the ARM tree, for the networking bits:
> >> I would expect patches 1, 2 & 3 to got via your tree, to avoid conflicts.
> >
> > I don't think putting them all via the ARM tree is going to create much
> > in the way of conflicts, and right now during the merge window offloading
> > that work from me would really help my backlog a lot.
> 
> Ok, I understand this is not the best time to pick it.
> 
> Arnd, Olof & Kevin, would you accept to pick the series in your tree?
> 

It's too late for v4.7 for us too, please pick up the arch/arm patches
in your normal stm32 tree and send them to us along with any other changes
you may have, and resend the driver by itself to netdev time after the
merge window.

The binding document can go either way, with the dts changes or with
the driver. I see no dependencies between the patches, so we just need
to land them all in v4.8.

	Arnd


From agraf at suse.de  Wed May 18 02:33:01 2016
From: agraf at suse.de (Alexander Graf)
Date: Wed, 18 May 2016 11:33:01 +0200
Subject: [PATCH] arm64: Allow for different DMA and CPU bus offsets
Message-ID: <1463563981-69722-1-git-send-email-agraf@suse.de>

On arm64, all SoCs we supported so far either have an IOMMU or have bus
addresses equal to CPU addresses.

However, with the Raspberry Pi 3 coming up, this is no longer true. To
allow DMA to work with an AArch64 kernel on those devices, let's allow
devices to have DMA offsets again.

Signed-off-by: Alexander Graf <agraf at suse.de>

---

This patch may conflict with another patch titled "swiotlb: prefix dma_to_phys
and phys_to_dma functions" which is in flight, but hasn't seen an update since
March.

Since this patch is very small and isolated to arm64, I'd prefer to keep them
separate rather than combine them. So if the other patch gets accepted first,
I'm happy to rebase this patch on top of a topic branch that would address the
rename.
---
 arch/arm64/include/asm/dma-mapping.h | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index ba437f0..67bf8e1 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -66,12 +66,16 @@ static inline bool is_device_dma_coherent(struct device *dev)
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
-	return (dma_addr_t)paddr;
+	dma_addr_t dev_addr = (dma_addr_t)paddr;
+
+	return dev_addr - (dma_addr_t)__pfn_to_phys(dev->dma_pfn_offset);
 }
 
 static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
 {
-	return (phys_addr_t)dev_addr;
+	phys_addr_t paddr = (phys_addr_t)dev_addr;
+
+	return paddr + __pfn_to_phys(dev->dma_pfn_offset);
 }
 
 static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
@@ -86,5 +90,14 @@ static inline void dma_mark_clean(void *addr, size_t size)
 {
 }
 
+/* Override for dma_max_pfn() */
+static inline unsigned long dma_max_pfn(struct device *dev)
+{
+	dma_addr_t dma_max = (dma_addr_t)*dev->dma_mask;
+
+	return (ulong)__phys_to_pfn(dma_to_phys(dev, dma_max));
+}
+#define dma_max_pfn(dev) dma_max_pfn(dev)
+
 #endif	/* __KERNEL__ */
 #endif	/* __ASM_DMA_MAPPING_H */
-- 
1.8.5.6



From mcoquelin.stm32 at gmail.com  Wed May 18 02:49:44 2016
From: mcoquelin.stm32 at gmail.com (Maxime Coquelin)
Date: Wed, 18 May 2016 11:49:44 +0200
Subject: [RESEND PATCH v6 0/6] Add Ethernet support on STM32F429
In-Reply-To: <2535270.dCFPoM2olB@wuerfel>
References: <1462789899-13153-1-git-send-email-alexandre.torgue@gmail.com>
 <20160517.122527.1937360418899371800.davem@davemloft.net>
 <CALszF6AE7jkRX3sSNm=PCvEmkmZM-Sv5LxFSj7J3vMbvi8M5Cg@mail.gmail.com>
 <2535270.dCFPoM2olB@wuerfel>
Message-ID: <CALszF6AP52EAN68qH8Pup9uxqTnhoT8wigiKaZzgHns3m+NCgQ@mail.gmail.com>

2016-05-18 11:31 GMT+02:00 Arnd Bergmann <arnd at arndb.de>:
> On Wednesday 18 May 2016 09:48:53 Maxime Coquelin wrote:
>> 2016-05-17 18:25 GMT+02:00 David Miller <davem at davemloft.net>:
>> > From: Maxime Coquelin <mcoquelin.stm32 at gmail.com>
>> > Date: Tue, 17 May 2016 11:20:16 +0200
>> >
>> >> Hi David,
>> >>
>> >> 2016-05-09 21:06 GMT+02:00 David Miller <davem at davemloft.net>:
>> >>> From: Alexandre TORGUE <alexandre.torgue at gmail.com>
>> >>> Date: Mon,  9 May 2016 12:31:33 +0200
>> >>>
>> >>>> STM32F429 Chip embeds a Synopsys 3.50a MAC IP.
>> >>>> This series:
>> >>>>  -enhance current stmmac driver to control it (code already
>> >>>> available) and adds basic glue for STM32F429 chip.
>> >>>>  -Enable basic Net config in kernel.
>> >>>
>> >>> I assume this will go via the ARM tree, for the networking bits:
>> >> I would expect patches 1, 2 & 3 to got via your tree, to avoid conflicts.
>> >
>> > I don't think putting them all via the ARM tree is going to create much
>> > in the way of conflicts, and right now during the merge window offloading
>> > that work from me would really help my backlog a lot.
>>
>> Ok, I understand this is not the best time to pick it.
>>
>> Arnd, Olof & Kevin, would you accept to pick the series in your tree?
>>
>
> It's too late for v4.7 for us too, please pick up the arch/arm patches
> in your normal stm32 tree and send them to us along with any other changes
> you may have, and resend the driver by itself to netdev time after the
> merge window.
>
> The binding document can go either way, with the dts changes or with
> the driver. I see no dependencies between the patches, so we just need
> to land them all in v4.8.

Ok, this is good for me.
No problem to wait for v4.8.
I will take the arch/arm patches, and David the drivers/net/ ones once
v4.7-rc1 is out.

Thanks for your time,
Maxime


From peter.ujfalusi at ti.com  Wed May 18 03:24:44 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 13:24:44 +0300
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <1463561115-31798-3-git-send-email-kishon@ti.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
Message-ID: <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com>

On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
> omap hsmmc host controller has ADMA2 feature. Enable it here
> for better read and write throughput. Add a new dt binding
> "ti,use_adma" to enable ADMA2.
> 
> Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
> ---
>  .../devicetree/bindings/mmc/ti-omap-hsmmc.txt      |    1 +
>  drivers/mmc/host/omap_hsmmc.c                      |  320 ++++++++++++++++----
>  include/linux/platform_data/hsmmc-omap.h           |    1 +
>  3 files changed, 256 insertions(+), 66 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> index 74166a0..eb5ceec2 100644
> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> @@ -28,6 +28,7 @@ specifier is required.
>  dma-names: List of DMA request names. These strings correspond
>  1:1 with the DMA specifiers listed in dmas. The string naming is
>  to be "rx" and "tx" for RX and TX DMA requests, respectively.
> +ti,use_adma: enable adma2 feature

Do we have use case when you want to fall back to generic DMA instead of aDMA2?
IMHO if the driver supports aDMA2, it is going to use it instead of the
generic s/eDMA.
What I mean is:
the driver implements the aDMA2 support.
if the IP has support for aDMA2, then it is going to use it, otherwise it will
use the generic DMA.

-- 
P?ter


From christoffer.dall at linaro.org  Wed May 18 03:27:17 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 12:27:17 +0200
Subject: [PATCH v4 11/56] KVM: arm/arm64: pmu: abstract access to number
 of SPIs
In-Reply-To: <1463392481-26583-12-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-12-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518102717.GB3827@cbox>

On Mon, May 16, 2016 at 10:52:59AM +0100, Andre Przywara wrote:
> Currently the PMU uses a member of the struct vgic_dist directly,
> which not only breaks abstraction, but will fail with the new VGIC.
> Abstract this access in the VGIC header file and refactor the validity
> check in the PMU code.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v3 .. v4:
> - fix logic to allow PPIs again
> - refactor IRQ validity check
> 
>  include/kvm/arm_vgic.h |  2 ++
>  virt/kvm/arm/pmu.c     | 25 ++++++++++++++-----------
>  2 files changed, 16 insertions(+), 11 deletions(-)
> 
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 67a6637..ade7005 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -348,6 +348,8 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
>  #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
>  #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
>  #define vgic_ready(k)		((k)->arch.vgic.ready)
> +#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
> +				 ((i) < (k)->arch.vgic.nr_irqs))
>  
>  int vgic_v2_probe(const struct gic_kvm_info *gic_kvm_info,
>  		  const struct vgic_ops **ops,
> diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
> index 575c7aa..a027569 100644
> --- a/virt/kvm/arm/pmu.c
> +++ b/virt/kvm/arm/pmu.c
> @@ -436,7 +436,14 @@ static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
>  	return 0;
>  }
>  
> -static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
> +#define irq_is_ppi(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS)
> +
> +/*
> + * For one VM the interrupt type must be same for each vcpu.
> + * As a PPI, the interrupt number is the same for all vcpus,
> + * while as an SPI it must be a separate number per vcpu.
> + */
> +static bool pmu_irq_is_valid(struct kvm *kvm, int irq)
>  {
>  	int i;
>  	struct kvm_vcpu *vcpu;
> @@ -445,7 +452,7 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
>  		if (!kvm_arm_pmu_irq_initialized(vcpu))
>  			continue;
>  
> -		if (is_ppi) {
> +		if (irq_is_ppi(irq)) {
>  			if (vcpu->arch.pmu.irq_num != irq)
>  				return false;
>  		} else {
> @@ -457,7 +464,6 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
>  	return true;
>  }
>  
> -
>  int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
>  {
>  	switch (attr->attr) {
> @@ -471,14 +477,11 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
>  		if (get_user(irq, uaddr))
>  			return -EFAULT;
>  
> -		/*
> -		 * The PMU overflow interrupt could be a PPI or SPI, but for one
> -		 * VM the interrupt type must be same for each vcpu. As a PPI,
> -		 * the interrupt number is the same for all vcpus, while as an
> -		 * SPI it must be a separate number per vcpu.
> -		 */
> -		if (irq < VGIC_NR_SGIS || irq >= vcpu->kvm->arch.vgic.nr_irqs ||
> -		    !irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
> +		/* The PMU overflow interrupt can be a PPI or a valid SPI. */
> +		if (!(irq_is_ppi(irq) || vgic_valid_spi(vcpu->kvm, irq)))
> +			return -EINVAL;
> +
> +		if (!pmu_irq_is_valid(vcpu->kvm, irq))
>  			return -EINVAL;
>  
>  		if (kvm_arm_pmu_irq_initialized(vcpu))
> -- 
> 2.8.2
> 

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From andre.przywara at arm.com  Wed May 18 03:43:41 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 18 May 2016 11:43:41 +0100
Subject: [PATCH v3 08/55] KVM: arm/arm64: Get rid of vgic_cpu->nr_lr
In-Reply-To: <1462531568-9799-9-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-9-git-send-email-andre.przywara@arm.com>
Message-ID: <573C475D.30005@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> The number of list registers is a property of the underlying system, not
> of emulated VGIC CPU interface.
> 
> As we are about to move this variable to global state in the new vgic
> for clarity, move it from the legacy implementation as well to make the
> merge of the new code easier.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Andre Przywara <andre.przywara at arm.com>

Thanks,
Andre.


From mingo at kernel.org  Wed May 18 03:46:38 2016
From: mingo at kernel.org (Ingo Molnar)
Date: Wed, 18 May 2016 12:46:38 +0200
Subject: [Xen-devel] [GIT PULL] EFI ARM Xen support
In-Reply-To: <alpine.DEB.2.10.1605171153070.2494@sstabellini-ThinkPad-X260>
References: <20160514190410.GA2283@codeblueprint.co.uk>
 <alpine.DEB.2.10.1605171109170.2494@sstabellini-ThinkPad-X260>
 <573AF50E.9090206@citrix.com>
 <alpine.DEB.2.10.1605171153070.2494@sstabellini-ThinkPad-X260>
Message-ID: <20160518104638.GA19191@gmail.com>


* Stefano Stabellini <sstabellini at kernel.org> wrote:

> On Tue, 17 May 2016, David Vrabel wrote:
> > On 17/05/16 11:12, Stefano Stabellini wrote:
> > > On Sat, 14 May 2016, Matt Fleming wrote:
> > >> Folks,
> > >>
> > >> Please pull the following branch which contains support for Xen on ARM
> > >> EFI platforms.
> > >>
> > >> This merge includes a merge of Stefano's xen/linux-next branch to pull
> > >> in the prerequisites required for Shannon's commit:
> > >>
> > >>   11ee5491e5ff ("Xen: EFI: Parse DT parameters for Xen specific UEFI")
> > >>
> > >> as it needs both the latest changes in the EFI 'next' branch (now
> > >> tip/efi/core) and xen/linux-next.
> > >>
> > >> I have intentionally not included the individual patches as I would
> > >> normally do in a pull request, so that commit history created by my
> > >> merging of Stefano's branch is preserved, and so that there's no way
> > >> to accidentally apply the patches individually.
> > >>
> > >> The following changes since commit 6c5450ef66816216e574885cf8d3ddb31ef77428:
> > >>
> > >>   efivarfs: Make efivarfs_file_ioctl() static (2016-05-07 07:06:13 +0200)
> > >>
> > >> are available in the git repository at:
> > >>
> > >>   git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git efi/arm-xen
> > >>
> > >> for you to fetch changes up to 11ee5491e5ff519e0d3a7018eb21351cb6955a98:
> > >>
> > >>   Xen: EFI: Parse DT parameters for Xen specific UEFI (2016-05-14 19:31:01 +0100)
> > > 
> > > Is this arrangement working for everybody, in particular the tip
> > > maintainers?
> > 
> > Yes.
> 
> I meant the x86 tip maintainers (Thomas, Peter and Ingo).

I have no particular objections, since this seems to be Xen-next merged to the EFI 
tree that is already upstream, plus this single commit on top of t:

  11ee5491e5ff Xen: EFI: Parse DT parameters for Xen specific UEFI

Which, if Matt is fine with it, you could send to Linus too as part of this 
cycle's Xen pull request.

Thanks,

	Ingo


From matt at codeblueprint.co.uk  Wed May 18 03:49:00 2016
From: matt at codeblueprint.co.uk (Matt Fleming)
Date: Wed, 18 May 2016 11:49:00 +0100
Subject: [Xen-devel] [GIT PULL] EFI ARM Xen support
In-Reply-To: <20160518104638.GA19191@gmail.com>
References: <20160514190410.GA2283@codeblueprint.co.uk>
 <alpine.DEB.2.10.1605171109170.2494@sstabellini-ThinkPad-X260>
 <573AF50E.9090206@citrix.com>
 <alpine.DEB.2.10.1605171153070.2494@sstabellini-ThinkPad-X260>
 <20160518104638.GA19191@gmail.com>
Message-ID: <20160518104900.GH21993@codeblueprint.co.uk>

On Wed, 18 May, at 12:46:38PM, Ingo Molnar wrote:
> 
> I have no particular objections, since this seems to be Xen-next merged to the EFI 
> tree that is already upstream, plus this single commit on top of t:
> 
>   11ee5491e5ff Xen: EFI: Parse DT parameters for Xen specific UEFI
> 
> Which, if Matt is fine with it, you could send to Linus too as part of this 
> cycle's Xen pull request.

Sure, I'm fine with that.


From arnd at arndb.de  Wed May 18 03:52:28 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 12:52:28 +0200
Subject: [PATCH] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <1463563981-69722-1-git-send-email-agraf@suse.de>
References: <1463563981-69722-1-git-send-email-agraf@suse.de>
Message-ID: <12218676.p29ELivsix@wuerfel>

On Wednesday 18 May 2016 11:33:01 Alexander Graf wrote:
> diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
> index ba437f0..67bf8e1 100644
> --- a/arch/arm64/include/asm/dma-mapping.h
> +++ b/arch/arm64/include/asm/dma-mapping.h
> @@ -66,12 +66,16 @@ static inline bool is_device_dma_coherent(struct device *dev)
>  
>  static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
>  {
> -       return (dma_addr_t)paddr;
> +       dma_addr_t dev_addr = (dma_addr_t)paddr;
> +
> +       return dev_addr - (dma_addr_t)__pfn_to_phys(dev->dma_pfn_offset);
>  }
>  
>  static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
>  {
> -       return (phys_addr_t)dev_addr;
> +       phys_addr_t paddr = (phys_addr_t)dev_addr;
> +
> +       return paddr + __pfn_to_phys(dev->dma_pfn_offset);
>  }
>  

The patch looks ok overall, but I think it's better to use an open-coded
shift instead of __pfn_to_phys/__pfn_to_phys here: those helpers convert
between actual page frame numbers and addresses, which may not always
be a 1:1 relationship, e.g. if someone wants to work around the crazy
"Principles of ARM Memory Maps White Paper" layout.

	Arnd


From andre.przywara at arm.com  Wed May 18 04:02:07 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 18 May 2016 12:02:07 +0100
Subject: [PATCH v3 09/55] KVM: arm/arm64: Fix MMIO emulation data handling
In-Reply-To: <1462531568-9799-10-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-10-git-send-email-andre.przywara@arm.com>
Message-ID: <573C4BAF.5030008@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> When the kernel was handling a guest MMIO read access internally, we
> need to copy the emulation result into the run->mmio structure in order
> for the kvm_handle_mmio_return() function to pick it up and inject the
> 	result back into the guest.
> 
> Currently the only user of kvm_io_bus for ARM is the VGIC, which did
> this copying itself, so this was not causing issues so far.
> 
> But with the upcoming new vgic implementation we need this done
> properly.
> 
> Update the kvm_handle_mmio_return description and cleanup the code to
> only perform a single copying when needed.
> 
> Code and commit message inspired by Andre Przywara.
> 
> Reported-by: Andre Przywara <andre.przywara at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Andre Przywara <andre.przywara at arm.com>

Thanks,
Andre.


From peter.ujfalusi at ti.com  Wed May 18 04:07:57 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 14:07:57 +0300
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <1463561115-31798-3-git-send-email-kishon@ti.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
Message-ID: <5a9e0163-1fbb-e0a6-95ff-0b720ba5c110@ti.com>

On 05/18/16 11:45, Kishon Vijay Abraham I wrote:

> +static int omap_hsmmc_dma_init(struct omap_hsmmc_host *host)
> +{
> +	dma_cap_mask_t mask;
> +	unsigned int tx_req, rx_req;
> +	struct resource *res;
> +	struct platform_device *pdev = to_platform_device(host->dev);
> +
> +	dma_cap_zero(mask);
> +	dma_cap_set(DMA_SLAVE, mask);
> +
> +	if (!pdev->dev.of_node) {
> +		res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
> +		if (!res) {
> +			dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
> +			return -ENXIO;
> +		}
> +		tx_req = res->start;
> +
> +		res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
> +		if (!res) {
> +			dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
> +			return -ENXIO;
> +		}
> +		rx_req = res->start;
> +	}
> +
> +	host->rx_chan =
> +		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> +						 &rx_req, &pdev->dev, "rx");
> +
> +	if (!host->rx_chan) {
> +		dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
> +		return -ENXIO;
> +	}
> +
> +	host->tx_chan =
> +		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> +						 &tx_req, &pdev->dev, "tx");
> +
> +	if (!host->tx_chan) {
> +		dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
> +		return -ENXIO;

upstream moved to use dma_request_chan() so this part needs to be changed.

> +	}
> +
> +	return 0;
> +}
> +
> +static void omap_hsmmc_dma_exit(struct omap_hsmmc_host *host)
> +{
> +	if (host->tx_chan)
> +		dma_release_channel(host->tx_chan);
> +	if (host->rx_chan)
> +		dma_release_channel(host->rx_chan);
> +}
> +
>  static int omap_hsmmc_probe(struct platform_device *pdev)
>  {
>  	struct omap_hsmmc_platform_data *pdata = pdev->dev.platform_data;
> @@ -2000,8 +2219,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>  	struct resource *res;
>  	int ret, irq;
>  	const struct of_device_id *match;
> -	dma_cap_mask_t mask;
> -	unsigned tx_req, rx_req;
>  	const struct omap_mmc_of_data *data;
>  	void __iomem *base;
>  
> @@ -2114,7 +2331,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>  	mmc->max_blk_size = 512;       /* Block Length at max can be 1024 */
>  	mmc->max_blk_count = 0xFFFF;    /* No. of Blocks is 16 bits */
>  	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
> -	mmc->max_seg_size = mmc->max_req_size;
> +	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> +		mmc->max_seg_size = ADMA_MAX_LEN;
> +	else
> +		mmc->max_seg_size = mmc->max_req_size;
>  
>  	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
>  		     MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
> @@ -2130,46 +2350,12 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>  
>  	omap_hsmmc_conf_bus_power(host);
>  
> -	if (!pdev->dev.of_node) {
> -		res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
> -		if (!res) {
> -			dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
> -			ret = -ENXIO;
> -			goto err_irq;
> -		}
> -		tx_req = res->start;
> -
> -		res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
> -		if (!res) {
> -			dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
> -			ret = -ENXIO;
> -			goto err_irq;
> -		}
> -		rx_req = res->start;
> -	}
> -
> -	dma_cap_zero(mask);
> -	dma_cap_set(DMA_SLAVE, mask);
> -
> -	host->rx_chan =
> -		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> -						 &rx_req, &pdev->dev, "rx");
> -
> -	if (!host->rx_chan) {
> -		dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
> -		ret = -ENXIO;
> -		goto err_irq;
> -	}
> -
> -	host->tx_chan =
> -		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> -						 &tx_req, &pdev->dev, "tx");
> -
> -	if (!host->tx_chan) {
> -		dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
> -		ret = -ENXIO;
> +	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> +		ret = omap_hsmmc_adma_init(host);
> +	else
> +		ret = omap_hsmmc_dma_init(host);
> +	if (ret)
>  		goto err_irq;
> -	}
>  
>  	/* Request IRQ for MMC operations */
>  	ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0,
> @@ -2225,11 +2411,11 @@ err_slot_name:
>  	mmc_remove_host(mmc);
>  err_irq:
>  	device_init_wakeup(&pdev->dev, false);
> -	if (host->tx_chan)
> -		dma_release_channel(host->tx_chan);
> -	if (host->rx_chan)
> -		dma_release_channel(host->rx_chan);
>  	pm_runtime_dont_use_autosuspend(host->dev);
> +	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> +		omap_hsmmc_adma_exit(host);
> +	else
> +		omap_hsmmc_dma_exit(host);
>  	pm_runtime_put_sync(host->dev);
>  	pm_runtime_disable(host->dev);
>  	if (host->dbclk)
> @@ -2248,8 +2434,10 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
>  	pm_runtime_get_sync(host->dev);
>  	mmc_remove_host(host->mmc);
>  
> -	dma_release_channel(host->tx_chan);
> -	dma_release_channel(host->rx_chan);
> +	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> +		omap_hsmmc_adma_exit(host);
> +	else
> +		omap_hsmmc_dma_exit(host);
>  
>  	pm_runtime_dont_use_autosuspend(host->dev);
>  	pm_runtime_put_sync(host->dev);
> diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h
> index 8e981be..e26013d 100644
> --- a/include/linux/platform_data/hsmmc-omap.h
> +++ b/include/linux/platform_data/hsmmc-omap.h
> @@ -27,6 +27,7 @@
>  #define OMAP_HSMMC_SUPPORTS_DUAL_VOLT		BIT(0)
>  #define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ	BIT(1)
>  #define OMAP_HSMMC_SWAKEUP_MISSING		BIT(2)
> +#define OMAP_HSMMC_USE_ADMA			BIT(3)
>  
>  struct omap_hsmmc_dev_attr {
>  	u8 flags;
> 


-- 
P?ter


From catalin.marinas at arm.com  Wed May 18 04:21:46 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 18 May 2016 12:21:46 +0100
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <20160517190526.GA3731@yury-N73SV>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1459894127-17698-21-git-send-email-ynorov@caviumnetworks.com>
 <20160514150352.GA30533@yury-N73SV>
 <20160516170605.GB19290@e104818-lin.cambridge.arm.com>
 <20160517190526.GA3731@yury-N73SV>
Message-ID: <20160518112145.GD22378@e104818-lin.cambridge.arm.com>

On Tue, May 17, 2016 at 10:05:26PM +0300, Yury Norov wrote:
> On Mon, May 16, 2016 at 06:06:05PM +0100, Catalin Marinas wrote:
> > On Sat, May 14, 2016 at 06:03:52PM +0300, Yury Norov wrote:
> > > +SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
> > > +       unsigned long, prot, unsigned long, flags, unsigned long, fd,
> > > +       unsigned long, pgoff)
> > 
> > To avoid the types confusion we could add __SC_WRAP to mmap2 in unistd.h
> > and use COMPAT_SYSCALL_DEFINE6 here (together with compat_ptr_t etc.).
> > 
> > > +{
> > > +       if (pgoff & (~PAGE_MASK >> 12))
> > > +               return -EINVAL;
> > > +
> > > +       return sys_mmap_pgoff((compat_uptr_t) addr, (compat_size_t) len,
> > > +		       (int) prot, (int) flags, (int) fd,
> > > +		       pgoff >> (PAGE_SHIFT-12));
> > 
> > Then we wouldn't need the explicit casting here.
> 
> See below
> 
> > > +}
> > > +
> > > +COMPAT_SYSCALL_DEFINE4(pread64, unsigned int, fd, compat_uptr_t __user *, ubuf,
> > > +		       compat_size_t, count, off_t, offset)
> > > +{
> > > +	return sys_pread64(fd, (char *) ubuf, count, offset);
> > > +}
> > > +
> > > +COMPAT_SYSCALL_DEFINE4(pwrite64, unsigned int, fd, compat_uptr_t __user *, ubuf,
> > > +		       compat_size_t, count, off_t, offset)
> > > +{
> > > +	return sys_pwrite64(fd, (char *) ubuf, count, offset);
> > 
> > Nitpick: no space between cast type and variable name: (char *)ubuf, ...
> 
> I think it's really a matter of taste. I prefer to have a space, and
> there's no solid rule in coding style.
> 
> And there are 13032 insertions of my version vs 35030 of yours:
> ~/work/linux$ git grep ' \*)[a-zA-Z]'|wc -l
> 35030
> ~/work/linux$ git grep ' \*) [a-zA-Z]'|wc -l
> 13032
> 
> Of course, I will change it if you insist.

Not really, I thought it's covered by CodingStyle but it doesn't seem
to.

> > We can also make these functions static as they are not used outside
> > this file.
> 
> If it's OK, we can use just compat_sys_xxx() instead of
> COMPAT_SYSCALL_DEFINEx(xxx),

I got lost in macros, what difference would COMPAT_SYSCALL_DEFINE vs
compat_sys_*() make? Is this the delouse stuff?

> and for mmap2 we'll not need to change _SYSCALL to _SC_WRAP in
> unistd.h that way.

Looking at the generic unistd.h, adding _SC_WRAP for sys_mmap2 is
indeed not easy:

#define __NR3264_mmap 222
__SC_3264(__NR3264_mmap, sys_mmap2, sys_mmap)

So defining a compat_sys_mmap2() would work but I think you'd also need:

#define sys_mmap2	compat_sys_mmap2()

-- 
Catalin


From christoffer.dall at linaro.org  Wed May 18 04:49:54 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 13:49:54 +0200
Subject: [PATCH v4 17/56] KVM: arm/arm64: vgic-new: Add IRQ sorting
In-Reply-To: <1463392481-26583-18-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-18-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518114954.GC3827@cbox>

On Mon, May 16, 2016 at 10:53:05AM +0100, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> Adds the sorting function to cover the case where you have more IRQs
> to consider than you have LRs. We now consider priorities.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Reviewed-by: Eric Auger <eric.auger at linaro.org>
> Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From sricharan at codeaurora.org  Wed May 18 05:07:40 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Wed, 18 May 2016 17:37:40 +0530
Subject: [PATCH V4 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <3070591.xyl7SB8DB7@wuerfel>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
 <1463381341-30498-7-git-send-email-sricharan@codeaurora.org>
 <3070591.xyl7SB8DB7@wuerfel>
Message-ID: <002c01d1b0fd$e4f3c350$aedb49f0$@codeaurora.org>

Hi Arnd,

>> diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
>> index f7b4c11..1240a5a 100644
>> --- a/drivers/iommu/msm_iommu.c
>> +++ b/drivers/iommu/msm_iommu.c
>> @@ -124,6 +124,7 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
>>                 SET_TLBLKCR(base, ctx, 0);
>>                 SET_CONTEXTIDR(base, ctx, 0);
>>         }
>> +       mb(); /* sync */
>>  }
>>
>>  static void __flush_iotlb(void *cookie)
>> @@ -143,6 +144,7 @@ static void __flush_iotlb(void *cookie)
>>
>>                 __disable_clocks(iommu);
>>         }
>> +       mb(); /* sync */
>>  fail:
>>         return;
>>  }
>
>These comments are completely useless. What is the specific race
>that you are protecting against, and why are the implicit barriers
>not sufficient here? Please find a better way to document what
>is going on.
>

The reason for doing this was, when the tlb maintenance ops are called
by  io-pgtable functions, it expects that the tlb_range ops is complete
only after the tlb_sync callback is called. Previously we were using
writel and the sync in that case was dummy. Also previously every register
configuration write was done using writel,  which was an overkill. So now
we do all the writes with writel_relaxed  and a barrier in the end. I will
change the documentation for this.

>> diff --git a/drivers/iommu/msm_iommu_hw-8xxx.h b/drivers/iommu/msm_iommu_hw-8xxx.h
>> index 84ba5739..161036c 100644
>> --- a/drivers/iommu/msm_iommu_hw-8xxx.h
>> +++ b/drivers/iommu/msm_iommu_hw-8xxx.h
>> @@ -24,10 +24,10 @@
>>  #define GET_CTX_REG(reg, base, ctx) \
>>                                 (readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
>>
>> -#define SET_GLOBAL_REG(reg, base, val) writel((val), ((base) + (reg)))
>> +#define SET_GLOBAL_REG(reg, base, val) writel_relaxed((val), ((base) + (reg)))
>>
>>  #define SET_CTX_REG(reg, base, ctx, val) \
>> -                       writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
>> +               writel_relaxed((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
>>
>>  /* Wrappers for numbered registers */
>>  #define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG(b, ((r) + (n << 2)), (v))
>> @@ -48,7 +48,8 @@
>>  #define SET_FIELD(addr, mask, shift, v) \
>>  do { \
>>         int t = readl(addr); \
>> -       writel((t & ~((mask) << (shift))) + (((v) & (mask)) << (shift)), addr);\
>> +       writel_relaxed((t & ~((mask) << (shift))) + \
>> +                      (((v) & (mask)) << (shift)), addr);\
>>  } while (0)
>
>No, please add a new macro for the relaxed accessors and then add comments
>in the places where those are used, to document why you can take shortcuts
>in those places.

Ok, will add a new accessor for this and comment them.

Regards,
 Sricharan



From sricharan at codeaurora.org  Wed May 18 05:08:25 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Wed, 18 May 2016 17:38:25 +0530
Subject: [PATCH V4 2/7] documentation: iommu: Add bindings for msm,
 iommu-v0 ip
In-Reply-To: <20160516164414.GA25899@rob-hp-laptop>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
 <1463381341-30498-3-git-send-email-sricharan@codeaurora.org>
 <20160516164414.GA25899@rob-hp-laptop>
Message-ID: <002e01d1b0fe$00488730$00d99590$@codeaurora.org>

Hi Rob,

>> The MSM IOMMU is an implementation compatible with the ARM VMSA short
>> descriptor page tables. It provides address translation for bus masters outside
>> of the CPU, each connected to the IOMMU through a port called micro-TLB.
>> Adding the DT bindings for the same.
>>
>> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
>> ---
>>  .../devicetree/bindings/iommu/msm,iommu-v0.txt     | 64 ++++++++++++++++++++++
>>  1 file changed, 64 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
>>
>> diff --git a/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
>b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
>> new file mode 100644
>> index 0000000..b22c607
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
>> @@ -0,0 +1,64 @@
>> +* QCOM IOMMU
>> +
>> +The MSM IOMMU is an implementation compatible with the ARM VMSA short
>> +descriptor page tables. It provides address translation for bus masters outside
>> +of the CPU, each connected to the IOMMU through a port called micro-TLB.
>> +
>> +Required Properties:
>> +
>> +  - compatible: Must contain "qcom,iommu-v0-apq8064".
>
>qcom,apq8064-iommu would be the preferred order and I think you can drop
>the v0.

Ok, will change this.

Regards,
 Sricharan



From arnd at arndb.de  Wed May 18 05:15:20 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 14:15:20 +0200
Subject: [PATCH V4 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <002c01d1b0fd$e4f3c350$aedb49f0$@codeaurora.org>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
 <3070591.xyl7SB8DB7@wuerfel> <002c01d1b0fd$e4f3c350$aedb49f0$@codeaurora.org>
Message-ID: <2638968.1a16UdaY62@wuerfel>

On Wednesday 18 May 2016 17:37:40 Sricharan wrote:
> >
> >These comments are completely useless. What is the specific race
> >that you are protecting against, and why are the implicit barriers
> >not sufficient here? Please find a better way to document what
> >is going on.
> >
> 
> The reason for doing this was, when the tlb maintenance ops are called
> by  io-pgtable functions, it expects that the tlb_range ops is complete
> only after the tlb_sync callback is called. Previously we were using
> writel and the sync in that case was dummy. Also previously every register
> configuration write was done using writel,  which was an overkill. So now
> we do all the writes with writel_relaxed  and a barrier in the end. I will
> change the documentation for this.

If you need the barrier after the write, it probably was already faulty
before, because writel only implies a barrier before the store, not
after. Of course all the barriers likely made the whole process so
slow that you never hit that race in the end.

	Arnd


From christoffer.dall at linaro.org  Wed May 18 05:25:21 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 14:25:21 +0200
Subject: [PATCH v4 22/56] KVM: arm/arm64: vgic-new: Add MMIO handling
 framework
In-Reply-To: <573B1DB0.7030901@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-23-git-send-email-andre.przywara@arm.com>
 <573B1DB0.7030901@arm.com>
Message-ID: <20160518122521.GD3827@cbox>

On Tue, May 17, 2016 at 02:33:36PM +0100, Marc Zyngier wrote:
> On 16/05/16 10:53, Andre Przywara wrote:
> > From: Marc Zyngier <marc.zyngier at arm.com>
> > 
> > Add an MMIO handling framework to the VGIC emulation:
> > Each register is described by its offset, size (or number of bits per
> > IRQ, if applicable) and the read/write handler functions. We provide
> > initialization macros to describe each GIC register later easily.
> > 
> > Separate dispatch functions for read and write accesses are connected
> > to the kvm_io_bus framework and binary-search for the responsible
> > register handler based on the offset address within the region.
> > We convert the incoming data (referenced by a pointer) to the host's
> > endianess and use pass-by-value to hand the data over to the actual
> > handler functions.
> > 
> > The register handler prototype and the endianess conversion are
> > courtesy of Christoffer Dall.
> > 
> > Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> > Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> > Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> > ---
> > Changelog RFC..v1:
> > - rework MMIO dispatching to use only one kvm_io_bus device
> > - document purpose of register region macros
> > - rename "this" parameter to "dev"
> > - change IGROUPR to be RAO (returning 1 => Group1 IRQs)
> > 
> > Changelog v1 .. v2:
> > * MASSIVE rework:
> > - store register_region pointer in kvm_io_bus linked struct
> > - replace write_mask_xxx functions with extract_bytes() implementation
> > - change handler functions' prototypes to take and return unsigned long
> > - use binary search to find matching register handler
> > - convert endianess of input data in dispatch_mmio_xxx functions
> > - improve readability of register initializer macros
> > - remove any GICv2/GICv3 specific functions from vgic-mmio.c
> > - rename file from vgic_mmio.c to vgic-mmio.c
> > 
> > Changelog v2 .. v3:
> > - replace inclusion of vgic/vgic.h with arm_vgic.h
> > 
> > Changelog v3 .. v4:
> > - add IRQ number accessor macro
> > - check access width in dispatcher
> > - treat non-covered MMIO addresses as RAZ/WI
> > - remove extract_bytes() (re-introduced as static later in the series)
> > 
> >  include/kvm/vgic/vgic.h       |  13 +++
> >  virt/kvm/arm/vgic/vgic-mmio.c | 184 ++++++++++++++++++++++++++++++++++++++++++
> >  virt/kvm/arm/vgic/vgic-mmio.h |  87 ++++++++++++++++++++
> >  3 files changed, 284 insertions(+)
> >  create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
> >  create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h
> > 
> > diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> > index f663288..ff3f9c2 100644
> > --- a/include/kvm/vgic/vgic.h
> > +++ b/include/kvm/vgic/vgic.h
> > @@ -106,6 +106,16 @@ struct vgic_irq {
> >  	enum vgic_irq_config config;	/* Level or edge */
> >  };
> >  
> > +struct vgic_register_region;
> > +
> > +struct vgic_io_device {
> > +	gpa_t base_addr;
> > +	struct kvm_vcpu *redist_vcpu;
> > +	const struct vgic_register_region *regions;
> > +	int nr_regions;
> > +	struct kvm_io_device dev;
> > +};
> > +
> >  struct vgic_dist {
> >  	bool			in_kernel;
> >  	bool			ready;
> > @@ -132,6 +142,9 @@ struct vgic_dist {
> >  	bool			enabled;
> >  
> >  	struct vgic_irq		*spis;
> > +
> > +	struct vgic_io_device	dist_iodev;
> > +	struct vgic_io_device	*redist_iodevs;
> >  };
> >  
> >  struct vgic_v2_cpu_if {
> > diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> > new file mode 100644
> > index 0000000..012b82b
> > --- /dev/null
> > +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> > @@ -0,0 +1,184 @@
> > +/*
> > + * VGIC MMIO handling functions
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#include <linux/bitops.h>
> > +#include <linux/bsearch.h>
> > +#include <linux/kvm.h>
> > +#include <linux/kvm_host.h>
> > +#include <kvm/iodev.h>
> > +#include <kvm/arm_vgic.h>
> > +
> > +#include "vgic.h"
> > +#include "vgic-mmio.h"
> > +
> > +unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
> > +				 gpa_t addr, unsigned int len)
> > +{
> > +	return 0;
> > +}
> > +
> > +unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
> > +				 gpa_t addr, unsigned int len)
> > +{
> > +	return -1UL;
> > +}
> > +
> > +void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> > +			unsigned int len, unsigned long val)
> > +{
> > +	/* Ignore */
> > +}
> > +
> > +static int match_region(const void *key, const void *elt)
> > +{
> > +	const unsigned int offset = (unsigned long)key;
> > +	const struct vgic_register_region *region = elt;
> > +
> > +	if (offset < region->reg_offset)
> > +		return -1;
> > +
> > +	if (offset >= region->reg_offset + region->len)
> > +		return 1;
> > +
> > +	return 0;
> > +}
> > +
> > +/* Find the proper register handler entry given a certain address offset. */
> > +static const struct vgic_register_region *
> > +vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
> > +		      unsigned int offset)
> > +{
> > +	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
> > +		       sizeof(region[0]), match_region);
> > +}
> > +
> > +/*
> > + * kvm_mmio_read_buf() returns a value in a format where it can be converted
> > + * to a byte array and be directly observed as the guest wanted it to appear
> > + * in memory if it had done the store itself, which is LE for the GIC, as the
> > + * guest knows the GIC is always LE.
> > + *
> > + * We convert this value to the CPUs native format to deal with it as a data
> > + * value.
> > + */
> > +unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len)
> > +{
> > +	unsigned long data = kvm_mmio_read_buf(val, len);
> > +
> > +	switch (len) {
> > +	case 1:
> > +		return data;
> > +	case 2:
> > +		return le16_to_cpu(data);
> > +	case 4:
> > +		return le32_to_cpu(data);
> > +	default:
> > +		return le64_to_cpu(data);
> > +	}
> > +}
> > +
> > +/*
> > + * kvm_mmio_write_buf() expects a value in a format such that if converted to
> > + * a byte array it is observed as the guest would see it if it could perform
> > + * the load directly.  Since the GIC is LE, and the guest knows this, the
> > + * guest expects a value in little endian format.
> > + *
> > + * We convert the data value from the CPUs native format to LE so that the
> > + * value is returned in the proper format.
> > + */
> > +void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
> > +				unsigned long data)
> > +{
> > +	switch (len) {
> > +	case 1:
> > +		break;
> > +	case 2:
> > +		data = cpu_to_le16(data);
> > +		break;
> > +	case 4:
> > +		data = cpu_to_le32(data);
> > +		break;
> > +	default:
> > +		data = cpu_to_le64(data);
> > +	}
> > +
> > +	kvm_mmio_write_buf(buf, len, data);
> > +}
> > +
> > +static
> > +struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
> > +{
> > +	return container_of(dev, struct vgic_io_device, dev);
> > +}
> > +
> > +static bool check_region(const struct vgic_register_region *region,
> > +			 gpa_t addr, int len)
> > +{
> > +	if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1)
> > +		return true;
> > +	if ((region->access_flags & VGIC_ACCESS_32bit) &&
> > +	    len == sizeof(u32) && !(addr & 3))
> > +		return true;
> > +	if ((region->access_flags & VGIC_ACCESS_64bit) &&
> > +	    len == sizeof(u64) && !(addr & 7))
> > +		return true;
> > +
> > +	return false;
> > +}
> > +
> > +static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
> > +			      gpa_t addr, int len, void *val)
> > +{
> > +	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
> > +	const struct vgic_register_region *region;
> > +	struct kvm_vcpu *r_vcpu;
> > +	unsigned long data;
> > +
> > +	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
> > +				       addr - iodev->base_addr);
> > +	if (!region || !check_region(region, addr, len)) {
> > +		memset(val, 0, len);
> > +		return 0;
> > +	}
> > +
> > +	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
> > +	data = region->read(r_vcpu, addr, len);
> > +	vgic_data_host_to_mmio_bus(val, len, data);
> > +	return 0;
> > +}
> > +
> > +static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
> > +			       gpa_t addr, int len, const void *val)
> > +{
> > +	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
> > +	const struct vgic_register_region *region;
> > +	struct kvm_vcpu *r_vcpu;
> > +	unsigned long data = vgic_data_mmio_bus_to_host(val, len);
> > +
> > +	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
> > +				       addr - iodev->base_addr);
> > +	if (!region)
> > +		return 0;
> > +
> > +	if (!check_region(region, addr, len))
> > +		return 0;
> > +
> > +	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
> > +	region->write(r_vcpu, addr, len, data);
> > +	return 0;
> > +}
> > +
> > +struct kvm_io_device_ops kvm_io_gic_ops = {
> > +	.read = dispatch_mmio_read,
> > +	.write = dispatch_mmio_write,
> > +};
> > diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> > new file mode 100644
> > index 0000000..855b1db
> > --- /dev/null
> > +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> > @@ -0,0 +1,87 @@
> > +/*
> > + * Copyright (C) 2015, 2016 ARM 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.
> > + *
> > + * 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.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> > + */
> > +#ifndef __KVM_ARM_VGIC_MMIO_H__
> > +#define __KVM_ARM_VGIC_MMIO_H__
> > +
> > +struct vgic_register_region {
> > +	unsigned int reg_offset;
> > +	unsigned int len;
> > +	unsigned int bits_per_irq;
> > +	unsigned int access_flags;
> > +	unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr,
> > +			      unsigned int len);
> > +	void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
> > +		      unsigned long val);
> > +};
> > +
> > +extern struct kvm_io_device_ops kvm_io_gic_ops;
> > +
> > +#define VGIC_ACCESS_8bit	1
> > +#define VGIC_ACCESS_32bit	2
> > +#define VGIC_ACCESS_64bit	4
> > +
> > +/* generate a mask that covers 1024 interrupts with <b> bits per IRQ */
> 
> Hmmm. I'd appreciate some additional comments, specially when it comes
> to the various restrictions. May I'd suggest something like:
> 
> /*
>  * Generate a mask that covers the number of bytes required to address
>  * up to 1024 interrupts, each represented by <b> bits. This assumes
>  * that <b> is a power of two.
>  *
>  * ilog2(b) + ilog2(1024) is the number of bits required to bit-address
>  * 1024 interrupts, each represented by b bits. Minus ilog2(8) converts
>  * this to a byte address.

So I'm guessting this is a rewrite of ilog2( (b * 1024) / 8), but I'm
stupid enough to not understand our use of logarithms here.  Can someone
remind me whatever I forgot at CS 101?

>  */
> 
> > +#define VGIC_ADDR_IRQ_MASK(b) GENMASK_ULL(ilog2(b) + ilog2(1024) - \
> > +					  ilog2(BITS_PER_BYTE) - 1, 0)
> 
> /*
>  * Convert a base address into a base interrupt (each interrupt
>  * represented by <bits> bits. This assumes that <bits> is a power
>  * of two, that <addr> both part of a memory region aligned on a

did you mean '<addr> *is* both part of' ?

>  * <b> bits boundary, and itself aligned on that same boundary
>  * (for regions that describe an interrupt with more than a single
>  * byte of data).
>  */
> 

In any case, thanks for the commentary, I was faily lost here.

-Christoffer

> > +#define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
> > +					64 / (bits) / 8)
> > +
> > +/*
> > + * Some VGIC registers store per-IRQ information, with a different number
> > + * of bits per IRQ. For those registers this macro is used.
> > + * The _WITH_LENGTH version instantiates registers with a fixed length
> > + * and is mutually exclusive with the _PER_IRQ version.
> > + */
> > +#define REGISTER_DESC_WITH_BITS_PER_IRQ(off, rd, wr, bpi, acc)		\
> > +	{								\
> > +		.reg_offset = off,					\
> > +		.bits_per_irq = bpi,					\
> > +		.len = bpi * 1024 / 8,					\
> > +		.access_flags = acc,					\
> > +		.read = rd,						\
> > +		.write = wr,						\
> > +	}
> > +
> > +#define REGISTER_DESC_WITH_LENGTH(off, rd, wr, length, acc)		\
> > +	{								\
> > +		.reg_offset = off,					\
> > +		.bits_per_irq = 0,					\
> > +		.len = length,						\
> > +		.access_flags = acc,					\
> > +		.read = rd,						\
> > +		.write = wr,						\
> > +	}
> > +
> > +int kvm_vgic_register_mmio_region(struct kvm *kvm, struct kvm_vcpu *vcpu,
> > +				  struct vgic_register_region *reg_desc,
> > +				  struct vgic_io_device *region,
> > +				  int nr_irqs, bool offset_private);
> > +
> > +unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len);
> > +
> > +void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
> > +				unsigned long data);
> > +
> > +unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
> > +				 gpa_t addr, unsigned int len);
> > +
> > +unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
> > +				 gpa_t addr, unsigned int len);
> > +
> > +void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> > +			unsigned int len, unsigned long val);
> > +
> > +#endif
> > 
> 
> Thanks,
> 
> 	M.
> -- 
> Jazz is not dead. It just smells funny...


From christoffer.dall at linaro.org  Wed May 18 05:31:15 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 14:31:15 +0200
Subject: [PATCH v4 22/56] KVM: arm/arm64: vgic-new: Add MMIO handling
 framework
In-Reply-To: <1463392481-26583-23-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-23-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518123115.GE3827@cbox>

On Mon, May 16, 2016 at 10:53:10AM +0100, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Add an MMIO handling framework to the VGIC emulation:
> Each register is described by its offset, size (or number of bits per
> IRQ, if applicable) and the read/write handler functions. We provide
> initialization macros to describe each GIC register later easily.
> 
> Separate dispatch functions for read and write accesses are connected
> to the kvm_io_bus framework and binary-search for the responsible
> register handler based on the offset address within the region.
> We convert the incoming data (referenced by a pointer) to the host's
> endianess and use pass-by-value to hand the data over to the actual
> handler functions.
> 
> The register handler prototype and the endianess conversion are
> courtesy of Christoffer Dall.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - rework MMIO dispatching to use only one kvm_io_bus device
> - document purpose of register region macros
> - rename "this" parameter to "dev"
> - change IGROUPR to be RAO (returning 1 => Group1 IRQs)
> 
> Changelog v1 .. v2:
> * MASSIVE rework:
> - store register_region pointer in kvm_io_bus linked struct
> - replace write_mask_xxx functions with extract_bytes() implementation
> - change handler functions' prototypes to take and return unsigned long
> - use binary search to find matching register handler
> - convert endianess of input data in dispatch_mmio_xxx functions
> - improve readability of register initializer macros
> - remove any GICv2/GICv3 specific functions from vgic-mmio.c
> - rename file from vgic_mmio.c to vgic-mmio.c
> 
> Changelog v2 .. v3:
> - replace inclusion of vgic/vgic.h with arm_vgic.h
> 
> Changelog v3 .. v4:
> - add IRQ number accessor macro
> - check access width in dispatcher
> - treat non-covered MMIO addresses as RAZ/WI
> - remove extract_bytes() (re-introduced as static later in the series)
> 
>  include/kvm/vgic/vgic.h       |  13 +++
>  virt/kvm/arm/vgic/vgic-mmio.c | 184 ++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h |  87 ++++++++++++++++++++
>  3 files changed, 284 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index f663288..ff3f9c2 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -106,6 +106,16 @@ struct vgic_irq {
>  	enum vgic_irq_config config;	/* Level or edge */
>  };
>  
> +struct vgic_register_region;
> +
> +struct vgic_io_device {
> +	gpa_t base_addr;
> +	struct kvm_vcpu *redist_vcpu;
> +	const struct vgic_register_region *regions;
> +	int nr_regions;
> +	struct kvm_io_device dev;
> +};
> +
>  struct vgic_dist {
>  	bool			in_kernel;
>  	bool			ready;
> @@ -132,6 +142,9 @@ struct vgic_dist {
>  	bool			enabled;
>  
>  	struct vgic_irq		*spis;
> +
> +	struct vgic_io_device	dist_iodev;
> +	struct vgic_io_device	*redist_iodevs;
>  };
>  
>  struct vgic_v2_cpu_if {
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> new file mode 100644
> index 0000000..012b82b
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -0,0 +1,184 @@
> +/*
> + * VGIC MMIO handling functions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/bsearch.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/iodev.h>
> +#include <kvm/arm_vgic.h>
> +
> +#include "vgic.h"
> +#include "vgic-mmio.h"
> +
> +unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
> +				 gpa_t addr, unsigned int len)
> +{
> +	return 0;
> +}
> +
> +unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
> +				 gpa_t addr, unsigned int len)
> +{
> +	return -1UL;
> +}
> +
> +void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> +			unsigned int len, unsigned long val)
> +{
> +	/* Ignore */
> +}
> +
> +static int match_region(const void *key, const void *elt)
> +{
> +	const unsigned int offset = (unsigned long)key;
> +	const struct vgic_register_region *region = elt;
> +
> +	if (offset < region->reg_offset)
> +		return -1;
> +
> +	if (offset >= region->reg_offset + region->len)
> +		return 1;
> +
> +	return 0;
> +}
> +
> +/* Find the proper register handler entry given a certain address offset. */
> +static const struct vgic_register_region *
> +vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
> +		      unsigned int offset)
> +{
> +	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
> +		       sizeof(region[0]), match_region);
> +}
> +
> +/*
> + * kvm_mmio_read_buf() returns a value in a format where it can be converted
> + * to a byte array and be directly observed as the guest wanted it to appear
> + * in memory if it had done the store itself, which is LE for the GIC, as the
> + * guest knows the GIC is always LE.
> + *
> + * We convert this value to the CPUs native format to deal with it as a data
> + * value.
> + */
> +unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len)
> +{
> +	unsigned long data = kvm_mmio_read_buf(val, len);
> +
> +	switch (len) {
> +	case 1:
> +		return data;
> +	case 2:
> +		return le16_to_cpu(data);
> +	case 4:
> +		return le32_to_cpu(data);
> +	default:
> +		return le64_to_cpu(data);
> +	}
> +}
> +
> +/*
> + * kvm_mmio_write_buf() expects a value in a format such that if converted to
> + * a byte array it is observed as the guest would see it if it could perform
> + * the load directly.  Since the GIC is LE, and the guest knows this, the
> + * guest expects a value in little endian format.
> + *
> + * We convert the data value from the CPUs native format to LE so that the
> + * value is returned in the proper format.
> + */
> +void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
> +				unsigned long data)
> +{
> +	switch (len) {
> +	case 1:
> +		break;
> +	case 2:
> +		data = cpu_to_le16(data);
> +		break;
> +	case 4:
> +		data = cpu_to_le32(data);
> +		break;
> +	default:
> +		data = cpu_to_le64(data);
> +	}
> +
> +	kvm_mmio_write_buf(buf, len, data);
> +}
> +
> +static
> +struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
> +{
> +	return container_of(dev, struct vgic_io_device, dev);
> +}
> +
> +static bool check_region(const struct vgic_register_region *region,
> +			 gpa_t addr, int len)
> +{
> +	if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1)
> +		return true;
> +	if ((region->access_flags & VGIC_ACCESS_32bit) &&
> +	    len == sizeof(u32) && !(addr & 3))
> +		return true;
> +	if ((region->access_flags & VGIC_ACCESS_64bit) &&
> +	    len == sizeof(u64) && !(addr & 7))
> +		return true;
> +
> +	return false;
> +}
> +
> +static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
> +			      gpa_t addr, int len, void *val)
> +{
> +	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
> +	const struct vgic_register_region *region;
> +	struct kvm_vcpu *r_vcpu;
> +	unsigned long data;
> +
> +	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
> +				       addr - iodev->base_addr);
> +	if (!region || !check_region(region, addr, len)) {
> +		memset(val, 0, len);
> +		return 0;
> +	}
> +
> +	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
> +	data = region->read(r_vcpu, addr, len);
> +	vgic_data_host_to_mmio_bus(val, len, data);
> +	return 0;
> +}
> +
> +static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
> +			       gpa_t addr, int len, const void *val)
> +{
> +	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
> +	const struct vgic_register_region *region;
> +	struct kvm_vcpu *r_vcpu;
> +	unsigned long data = vgic_data_mmio_bus_to_host(val, len);
> +
> +	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
> +				       addr - iodev->base_addr);
> +	if (!region)
> +		return 0;
> +
> +	if (!check_region(region, addr, len))
> +		return 0;
> +
> +	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
> +	region->write(r_vcpu, addr, len, data);
> +	return 0;
> +}
> +
> +struct kvm_io_device_ops kvm_io_gic_ops = {
> +	.read = dispatch_mmio_read,
> +	.write = dispatch_mmio_write,
> +};
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> new file mode 100644
> index 0000000..855b1db
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -0,0 +1,87 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef __KVM_ARM_VGIC_MMIO_H__
> +#define __KVM_ARM_VGIC_MMIO_H__
> +
> +struct vgic_register_region {
> +	unsigned int reg_offset;
> +	unsigned int len;
> +	unsigned int bits_per_irq;
> +	unsigned int access_flags;
> +	unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr,
> +			      unsigned int len);
> +	void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
> +		      unsigned long val);
> +};
> +
> +extern struct kvm_io_device_ops kvm_io_gic_ops;
> +
> +#define VGIC_ACCESS_8bit	1
> +#define VGIC_ACCESS_32bit	2
> +#define VGIC_ACCESS_64bit	4
> +
> +/* generate a mask that covers 1024 interrupts with <b> bits per IRQ */
> +#define VGIC_ADDR_IRQ_MASK(b) GENMASK_ULL(ilog2(b) + ilog2(1024) - \
> +					  ilog2(BITS_PER_BYTE) - 1, 0)
> +#define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
> +					64 / (bits) / 8)

In the comment we end up adding here, can we also describe why
(addr & <magic mask>) * <magic 64> / (bits) / <BITS_PER_BYTE OR BYTES_PER_ULL>

gives us what we need, because I don't get it.

Except for this magic formula, which I trust you and Marc have verified
and proved:

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>

> +
> +/*
> + * Some VGIC registers store per-IRQ information, with a different number
> + * of bits per IRQ. For those registers this macro is used.
> + * The _WITH_LENGTH version instantiates registers with a fixed length
> + * and is mutually exclusive with the _PER_IRQ version.
> + */
> +#define REGISTER_DESC_WITH_BITS_PER_IRQ(off, rd, wr, bpi, acc)		\
> +	{								\
> +		.reg_offset = off,					\
> +		.bits_per_irq = bpi,					\
> +		.len = bpi * 1024 / 8,					\
> +		.access_flags = acc,					\
> +		.read = rd,						\
> +		.write = wr,						\
> +	}
> +
> +#define REGISTER_DESC_WITH_LENGTH(off, rd, wr, length, acc)		\
> +	{								\
> +		.reg_offset = off,					\
> +		.bits_per_irq = 0,					\
> +		.len = length,						\
> +		.access_flags = acc,					\
> +		.read = rd,						\
> +		.write = wr,						\
> +	}
> +
> +int kvm_vgic_register_mmio_region(struct kvm *kvm, struct kvm_vcpu *vcpu,
> +				  struct vgic_register_region *reg_desc,
> +				  struct vgic_io_device *region,
> +				  int nr_irqs, bool offset_private);
> +
> +unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len);
> +
> +void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
> +				unsigned long data);
> +
> +unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
> +				 gpa_t addr, unsigned int len);
> +
> +unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
> +				 gpa_t addr, unsigned int len);
> +
> +void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> +			unsigned int len, unsigned long val);
> +
> +#endif
> -- 
> 2.8.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From christoffer.dall at linaro.org  Wed May 18 05:33:37 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 14:33:37 +0200
Subject: [PATCH v4 24/56] KVM: arm/arm64: vgic-new: Add CTLR, TYPER and
 IIDR handlers
In-Reply-To: <1463392481-26583-25-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-25-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518123337.GF3827@cbox>

On Mon, May 16, 2016 at 10:53:12AM +0100, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> Those three registers are v2 emulation specific, so their implementation
> lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
> as their implementation is pretty simple.
> When the guest enables the distributor, we kick all VCPUs to get
> potentially pending interrupts serviced.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From sricharan at codeaurora.org  Wed May 18 05:33:51 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Wed, 18 May 2016 18:03:51 +0530
Subject: [PATCH V4 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <2638968.1a16UdaY62@wuerfel>
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
 <3070591.xyl7SB8DB7@wuerfel> <002c01d1b0fd$e4f3c350$aedb49f0$@codeaurora.org>
 <2638968.1a16UdaY62@wuerfel>
Message-ID: <003101d1b101$8ce470c0$a6ad5240$@codeaurora.org>

Hi Arnd,
>> >
>> >These comments are completely useless. What is the specific race
>> >that you are protecting against, and why are the implicit barriers
>> >not sufficient here? Please find a better way to document what
>> >is going on.
>> >
>>
>> The reason for doing this was, when the tlb maintenance ops are called
>> by  io-pgtable functions, it expects that the tlb_range ops is complete
>> only after the tlb_sync callback is called. Previously we were using
>> writel and the sync in that case was dummy. Also previously every register
>> configuration write was done using writel,  which was an overkill. So now
>> we do all the writes with writel_relaxed  and a barrier in the end. I will
>> change the documentation for this.
>
>If you need the barrier after the write, it probably was already faulty
>before, because writel only implies a barrier before the store, not
>after. Of course all the barriers likely made the whole process so
>slow that you never hit that race in the end.

ya, it could have worked in this way and i never saw a race issue before this.
The only reason for changing this was to optimise out the additonal barriers
that were happening. I do not see any issue now as well, only that the writes would
be faster.

Regards,
 Sricharan



From raashidmuhammed at zilogic.com  Wed May 18 05:32:46 2016
From: raashidmuhammed at zilogic.com (Raashid Muhammed)
Date: Wed, 18 May 2016 18:02:46 +0530
Subject: [PATCH] ARM: at91: Add DT support for Olimex SAM9-L9260 board.
Message-ID: <1463574766-15568-1-git-send-email-raashidmuhammed@zilogic.com>

From: Raashid Muhammed <raashidmuhammed at zilogic.com>

sam9-l9260 is a low cost board designed by Olimex.

More infomation is available at:
https://www.olimex.com/Products/ARM/Atmel/SAM9-L9260/

Signed-off-by: Raashid Muhammed <raashidmuhammed at zilogic.com>
Reviewed-by: Vijay Kumar B. <vijaykumar at bravegnu.org>
---
 .../devicetree/bindings/arm/olimex-at91.txt        |   6 ++
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/sam9-l9260.dts                   | 108 +++++++++++++++++++++
 3 files changed, 115 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/olimex-at91.txt
 create mode 100644 arch/arm/boot/dts/sam9-l9260.dts

diff --git a/Documentation/devicetree/bindings/arm/olimex-at91.txt b/Documentation/devicetree/bindings/arm/olimex-at91.txt
new file mode 100644
index 0000000..0587d63
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/olimex-at91.txt
@@ -0,0 +1,6 @@
+Olimex AT91 Device Tree Bindings
+--------------------------------
+
+SAM9-L9260 Board
+Required root node properties:
+    - compatible = "olimex,sam9-l9260", "atmel,at91sam9260";
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 95c1923..ae3b50f 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -19,6 +19,7 @@ dtb-$(CONFIG_SOC_SAM_V4_V5) += \
	usb_a9260.dtb \
	at91sam9261ek.dtb \
	at91sam9263ek.dtb \
+	sam9-l9260.dtb \
	tny_a9263.dtb \
	usb_a9263.dtb \
	at91-foxg20.dtb \
diff --git a/arch/arm/boot/dts/sam9-l9260.dts b/arch/arm/boot/dts/sam9-l9260.dts
new file mode 100644
index 0000000..3ddf7af
--- /dev/null
+++ b/arch/arm/boot/dts/sam9-l9260.dts
@@ -0,0 +1,108 @@
+/*
+ * sam9-l9260.dts - Device Tree file for Olimex SAM9-L9260 board
+ *
+ *  Copyright (C) 2016 Raashid Muhammed <raashidmuhammed at zilogic.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+#include "at91sam9260.dtsi"
+
+/ {
+	model = "Olimex sam9-l9260";
+	compatible = "olimex,sam9-l9260", "atmel,at91sam9260", "atmel,at91sam9";
+
+	chosen {
+		bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
+	 };
+
+	 memory {
+		reg = <0x20000000 0x4000000>;
+	 };
+
+	 clocks {
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
+	 };
+
+	 ahb {
+		apb {
+			dbgu: serial at fffff200 {
+				status = "okay";
+			 };
+
+			macb0: ethernet at fffc4000 {
+				phy-mode = "mii";
+				status = "okay";
+			 };
+
+			spi0: spi at fffc8000 {
+				status = "okay";
+				cs-gpios = <&pioC 11 0>, <0>, <0>, <0>;
+				mtd_dataflash at 0 {
+					compatible = "atmel,at45", "atmel,dataflash";
+					spi-max-frequency = <15000000>;
+					reg = <0>;
+				};
+			};
+
+			mmc0: mmc at fffa8000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc0
+					&pinctrl_mmc0_clk
+					&pinctrl_mmc0_slot1_cmd_dat0
+					&pinctrl_mmc0_slot1_dat1_3>;
+				status = "okay";
+				slot at 1 {
+					reg = <1>;
+					bus-width = <4>;
+					cd-gpios = <&pioC 8 GPIO_ACTIVE_HIGH>;
+					wp-gpios = <&pioC 4 GPIO_ACTIVE_HIGH>;
+				};
+			};
+
+			pinctrl at fffff400 {
+				mmc0 {
+					pinctrl_board_mmc0: mmc0-board {
+						atmel,pins =
+							<AT91_PIOC 8 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH	/* PC08 gpio CD pin pull up and deglitch */
+							 AT91_PIOC 4 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP>;	/* PC04 gpio WP pin pull up */
+					};
+				};
+			};
+
+
+		 };
+
+		 usb0: ohci at 00500000 {
+		       status = "okay";
+		 };
+
+		 nand0: nand at 40000000 {
+		       nand-bus-width = <8>;
+		       nand-ecc-mode = "soft";
+		       nand-on-flash-bbt = <1>;
+		       status = "okay";
+		 };
+	 };
+
+	 i2c at 0 {
+		status = "okay";
+	 };
+
+	 leds {
+		compatible = "gpio-leds";
+
+		b0 {
+			label = "b0";
+			gpios = <&pioA 6 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+
+	};
+};
--
2.1.4


From p.zabel at pengutronix.de  Wed May 18 05:50:50 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Wed, 18 May 2016 14:50:50 +0200
Subject: imx-drm: regression due to commit 503fe87bd0a8 ("gpu: ipu-v3:
 Fix imx-ipuv3-crtc module autoloading")
In-Reply-To: <20160518111243.111b8e9c@ipc1.ka-ro>
References: <20160513123336.6996dd89@ipc1.ka-ro>
 <1463137452.3544.5.camel@pengutronix.de>
 <20160518111243.111b8e9c@ipc1.ka-ro>
Message-ID: <1463575850.3639.30.camel@pengutronix.de>

Am Mittwoch, den 18.05.2016, 11:12 +0200 schrieb Lothar Wa?mann:
> Hi,
> 
> On Fri, 13 May 2016 13:04:12 +0200 Philipp Zabel wrote:
> > Hi Lothar,
> > 
> > Am Freitag, den 13.05.2016, 12:33 +0200 schrieb Lothar Wa?mann:
> > > Hi,
> > > 
> > > the commit 503fe87bd0a8 ("gpu: ipu-v3: Fix imx-ipuv3-crtc module autoloading")
> > > indeed fixes the autoloading issue, but completely breaks the driver in
> > > non-modular mode (at least with the parallel-display driver I didn't
> > > yet check with the imx-ldb driver.
> > > Can anyone confirm that the imx-drm driver in current linux-next
> > > (next-20160512) works for them with any i.MX6 or i.MX53 board?
> > 
> > I have sent a patch: https://patchwork.kernel.org/patch/9081661/
> > that I'd appreciate your input on.
> > 
> This patch works for the parallel-display driver but not for imx-ldb
> (I didn't test the TV or HDMI drivers). It works when the DRM driver is
> built as modules, but when it is non-modular I get a framebuffer
> device which is useable from userspace, but no output on the LVDS
> interface.
> 
> When reverting 503fe87bd0a8346ba9d8b7f49115dcd0a4185226 instead of
> applying the above patch, the builtin driver works normally.

Thank you for testing, I'll send a new version.

regards
Philipp



From agraf at suse.de  Wed May 18 05:53:30 2016
From: agraf at suse.de (Alexander Graf)
Date: Wed, 18 May 2016 14:53:30 +0200
Subject: [PATCH v2] arm64: Allow for different DMA and CPU bus offsets
Message-ID: <1463576010-115428-1-git-send-email-agraf@suse.de>

On arm64, all SoCs we supported so far either have an IOMMU or have bus
addresses equal to CPU addresses.

However, with the Raspberry Pi 3 coming up, this is no longer true. To
allow DMA to work with an AArch64 kernel on those devices, let's allow
devices to have DMA offsets again.

Signed-off-by: Alexander Graf <agraf at suse.de>

---

This patch may conflict with another patch titled "swiotlb: prefix dma_to_phys
and phys_to_dma functions" which is in flight, but hasn't seen an update since
March.

Since this patch is very small and isolated to arm64, I'd prefer to keep them
separate rather than combine them. So if the other patch gets accepted first,
I'm happy to rebase this patch on top of a topic branch that would address the
rename.

v1 -> v2:

  - Use PAGE_SHIFT explicitly rather than __pfn_to_phys and __phys_to_pfn
---
 arch/arm64/include/asm/dma-mapping.h | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index ba437f0..c14e9cd 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -66,12 +66,16 @@ static inline bool is_device_dma_coherent(struct device *dev)
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
-	return (dma_addr_t)paddr;
+	dma_addr_t dev_addr = (dma_addr_t)paddr;
+
+	return dev_addr - ((dma_addr_t)dev->dma_pfn_offset << PAGE_SHIFT);
 }
 
 static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
 {
-	return (phys_addr_t)dev_addr;
+	phys_addr_t paddr = (phys_addr_t)dev_addr;
+
+	return paddr + ((phys_addr_t)dev->dma_pfn_offset << PAGE_SHIFT);
 }
 
 static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
@@ -86,5 +90,14 @@ static inline void dma_mark_clean(void *addr, size_t size)
 {
 }
 
+/* Override for dma_max_pfn() */
+static inline unsigned long dma_max_pfn(struct device *dev)
+{
+	dma_addr_t dma_max = (dma_addr_t)*dev->dma_mask;
+
+	return (ulong)dma_to_phys(dev, dma_max) >> PAGE_SHIFT;
+}
+#define dma_max_pfn(dev) dma_max_pfn(dev)
+
 #endif	/* __KERNEL__ */
 #endif	/* __ASM_DMA_MAPPING_H */
-- 
1.8.5.6



From christoffer.dall at linaro.org  Wed May 18 06:01:39 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 15:01:39 +0200
Subject: [PATCH v4 27/56] KVM: arm/arm64: vgic-new: Add ACTIVE registers
 handlers
In-Reply-To: <1463392481-26583-28-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-28-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518130139.GG3827@cbox>

On Mon, May 16, 2016 at 10:53:15AM +0100, Andre Przywara wrote:
> The active register handlers are shared between the v2 and v3
> emulation, so their implementation goes into vgic-mmio.c, to be
> easily referenced from the v3 emulation as well later.
> Since activation/deactivation of an interrupt may happen entirely
> in the guest without it ever exiting, we need some extra logic to
> properly track the active state.

-- cut --

> Putting it on an ap_list on activation is similar to the normal case
> handled by vgic_queue_irq_unlock(), but differs in some details that
> make a separate implementation worthwhile.

-- cut --

this bit is no longer correct.


> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - handling queueing in write handler
> - remove IRQ lock from read handler
> 
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
> Changelog v3 .. v4:
> - specify accessor width
> - use IRQ number accessor macro
> - drop elaborate write_sactive handler and use new vgic_queue_irq_unlock()
> - properly emulate clear active by halting the guest (Christoffer)
> - replace extract_bytes() with simple return
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +-
>  virt/kvm/arm/vgic/vgic-mmio.c    | 82 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h    | 10 +++++
>  3 files changed, 94 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index c13a708..12e101b 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -84,10 +84,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
>  		VGIC_ACCESS_32bit),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1,
>  		VGIC_ACCESS_32bit),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
>  		VGIC_ACCESS_32bit),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index d8dc8f6..74d140e 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -155,6 +155,88 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len)
> +{
> +	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
> +	u32 value = 0;
> +	int i;
> +
> +	/* Loop over all IRQs affected by this read */
> +	for (i = 0; i < len * 8; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		if (irq->active)
> +			value |= (1U << i);
> +	}
> +
> +	return value;
> +}
> +
> +void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val)
> +{
> +	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
> +	int i;
> +
> +	kvm_arm_halt_guest(vcpu->kvm);
> +	for_each_set_bit(i, &val, len * 8) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +		/*
> +		 * If this virtual IRQ was written into a list register, we
> +		 * have to make sure the CPU that runs the VCPU thread has
> +		 * synced back LR state to the struct vgic_irq.  We can only
> +		 * know this for sure, when either this irq is not assigned to
> +		 * anyone's AP list anymore, or the VCPU thread is not
> +		 * running on any CPUs.
> +		 *
> +		 * In the opposite case, we know the VCPU thread may be on its
> +		 * way back from the guest and still has to sync back this
> +		 * IRQ, so we release and re-acquire the spin_lock to let the
> +		 * other thread sync back the IRQ.
> +		 */
> +		while (irq->vcpu && /* IRQ may have state in an LR somewhere */
> +		       irq->vcpu->cpu != -1) /* VCPU thread is running */
> +			cond_resched_lock(&irq->irq_lock);
> +
> +		irq->active = false;
> +		spin_unlock(&irq->irq_lock);
> +	}
> +	kvm_arm_resume_guest(vcpu->kvm);
> +}
> +
> +void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
> +			     gpa_t addr, unsigned int len,
> +			     unsigned long val)
> +{
> +	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
> +	int i;
> +
> +	for_each_set_bit(i, &val, len * 8) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		/*
> +		 * If the IRQ was already active or it was on a VCPU before
> +		 * or there is no target VCPU assigned at the moment, then
> +		 * just proceed.
> +		 */
> +		if (irq->active || irq->vcpu || !irq->target_vcpu) {

why is it that we don't care if this IRQ is on a LR, for example being
just pending and not active, and we thereby loose this active state when
the vcpu syncs back the state?

We care for the case where we clear the active state, but not when we
set it.  Perhaps we discussed this in the past, but now I've forgotten,
so that should at least be documented somehow.

> +			irq->active = true;
> +
> +			spin_unlock(&irq->irq_lock);
> +			continue;
> +		}
> +
> +		irq->active = true;
> +		vgic_queue_irq_unlock(vcpu->kvm, irq);

this won't work just yet, but I think all that's needed to make it work
is this patchlet:

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index c22f7e2..27204f22 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -81,7 +81,7 @@ static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
 
 	/* If the interrupt is active, it must stay on the current vcpu */
 	if (irq->active)
-		return irq->vcpu;
+		return irq->vcpu ? : irq->target_vcpu;
 
 	/*
 	 * If the IRQ is not active but enabled and pending, we should direct


Thanks,
-Christoffer


From arnd at arndb.de  Wed May 18 06:05:11 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 15:05:11 +0200
Subject: [PATCH v2] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <1463576010-115428-1-git-send-email-agraf@suse.de>
References: <1463576010-115428-1-git-send-email-agraf@suse.de>
Message-ID: <3627660.euTtGW2SrX@wuerfel>

On Wednesday 18 May 2016 14:53:30 Alexander Graf wrote:
> On arm64, all SoCs we supported so far either have an IOMMU or have bus
> addresses equal to CPU addresses.
> 
> However, with the Raspberry Pi 3 coming up, this is no longer true. To
> allow DMA to work with an AArch64 kernel on those devices, let's allow
> devices to have DMA offsets again.
> 
> Signed-off-by: Alexander Graf <agraf at suse.de>
> 
> 

Acked-by: Arnd Bergmann <arnd at arndb.de>


From shankerd at codeaurora.org  Wed May 18 06:06:34 2016
From: shankerd at codeaurora.org (Shanker Donthineni)
Date: Wed, 18 May 2016 08:06:34 -0500
Subject: [PATCH v2 2/5] arm64: efi: apply strict permissons for UEFI
 Runtime Services regions
In-Reply-To: <CAKv+Gu-Tam+QiXc_f0e+x8hNc4rxP_-59NdaCHkF9h=4Rd+XeA@mail.gmail.com>
References: <1459355933-13529-1-git-send-email-ard.biesheuvel@linaro.org>
 <1459355933-13529-3-git-send-email-ard.biesheuvel@linaro.org>
 <573BB9FE.7050008@codeaurora.org>
 <CAKv+Gu-Tam+QiXc_f0e+x8hNc4rxP_-59NdaCHkF9h=4Rd+XeA@mail.gmail.com>
Message-ID: <573C68DA.8080009@codeaurora.org>

Hi Ard,

We are not using the permission attribute table and all the Runtime
Data/Code regions are marked with 'XP' bit. Do you think something
wrong in our UEFI implementation or Linux has to map RuntimeCode
regions with executable permission always irrespective of an attribute
flag EFI_MEMORY_XP?

[    0.000000] efi: Processing EFI memory map:
[    0.000000] efi:   0x000000100000-0x00000010ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x00003b830000-0x00003b83ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x00003c000000-0x00003fffffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x000000100000-0x00000010ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x00003b830000-0x00003b83ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x00003c000000-0x00003fffffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x004000820000-0x00400085ffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x004003080000-0x00400308ffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047f9960000-0x0047f997ffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047fa9c0000-0x0047fa9cffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047faa30000-0x0047faa3ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047fab90000-0x0047fab9ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047faba0000-0x0047fabaffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047fab90000-0x0047fab9ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047faba0000-0x0047fabaffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047fabb0000-0x0047fabbffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047fabc0000-0x0047fad9ffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047fada0000-0x0047fae2ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047faf50000-0x0047faf7ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047fafa0000-0x0047fafbffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047faf50000-0x0047faf7ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047fafa0000-0x0047fafbffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047fff90000-0x0047fff9ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0047fffb0000-0x0047fffdffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*


On 05/18/2016 01:18 AM, Ard Biesheuvel wrote:
> On 18 May 2016 at 02:40, Shanker Donthineni <shankerd at codeaurora.org> wrote:
>> Hi Ard,
>>
>> This patch causing the kernel boot fail using the UEFI firmware on
>> Qualcomm Technologies QDF2XXX server platforms.
>>
>> +       /* RW- */
>> +       if (attr & EFI_MEMORY_XP || type != EFI_RUNTIME_SERVICES_CODE)
>> +               return pgprot_val(PAGE_KERNEL);
>> +
>>
>> Changing above condition from 'or' to 'and' fixed the problem.Are we
>> missing something here or intentionally implemented this logic?
> The logic is sound, I think. If you need execute permissions on a
> non-code region with the XP bit set, there is something wrong in the
> firmware, unless you are hitting this case for an MMIO region perhaps?
> Could you share the kernel log with efi=debug enabled?
>
>> At least
>> we need some pr_warn here if UEFI firmware passes EFI_RUNTIME_SEVRICE_CODE
>> region that has an attribute EFI_MEMORY_XP.
>>
> No. DXE_RUNTIME_DRIVER modules are implemented as PE/COFF binaries,
> which are covered completely by EfiRuntimeServicesCode regions.
> However, a PE/COFF image consists of .text and .data sections, which
> require different permissions, so PE/COFF binaries are represented by
> several memory map entries in the memory attributes table, all of
> which have a code type, but differ in the permission bits.
>
>>
>> On 03/30/2016 11:38 AM, Ard Biesheuvel wrote:
>>> Recent UEFI versions expose permission attributes for runtime services
>>> memory regions, either in the UEFI memory map or in the separate memory
>>> attributes table. This allows the kernel to map these regions with
>>> stricter permissions, rather than the RWX permissions that are used by
>>> default. So wire this up in our mapping routine.
>>>
>>> Note that in the absence of permission attributes, we still only map
>>> regions of type EFI_RUNTIME_SERVICE_CODE with the executable bit set.
>>> Also, we base the mapping attributes of EFI_MEMORY_MAPPED_IO on the
>>> type directly rather than on the absence of the EFI_MEMORY_WB attribute.
>>> This is more correct, but is also required for compatibility with the
>>> upcoming support for the Memory Attributes Table, which only carries
>>> permission attributes, not memory type attributes.
>>>
>>> Cc: Mark Rutland <mark.rutland at arm.com>
>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
>>> ---
>>>  arch/arm64/kernel/efi.c | 54 +++++++++++++++-----
>>>  1 file changed, 40 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
>>> index b6abc852f2a1..33a6da160a50 100644
>>> --- a/arch/arm64/kernel/efi.c
>>> +++ b/arch/arm64/kernel/efi.c
>>> @@ -17,22 +17,48 @@
>>>
>>>  #include <asm/efi.h>
>>>
>>> -int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t
>>> *md)
>>> +/*
>>> + * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
>>> + * executable, everything else can be mapped with the XN bits
>>> + * set. Also take the new (optional) RO/XP bits into account.
>>> + */
>>> +static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
>>>  {
>>> -     pteval_t prot_val;
>>> +     u64 attr = md->attribute;
>>> +     u32 type = md->type;
>>>
>>> -     /*
>>> -      * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
>>> -      * executable, everything else can be mapped with the XN bits
>>> -      * set.
>>> -      */
>>> -     if ((md->attribute & EFI_MEMORY_WB) == 0)
>>> -             prot_val = PROT_DEVICE_nGnRE;
>>> -     else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
>>> -              !PAGE_ALIGNED(md->phys_addr))
>>> -             prot_val = pgprot_val(PAGE_KERNEL_EXEC);
>>> -     else
>>> -             prot_val = pgprot_val(PAGE_KERNEL);
>>> +     if (type == EFI_MEMORY_MAPPED_IO)
>>> +             return PROT_DEVICE_nGnRE;
>>> +
>>> +     if (WARN_ONCE(!PAGE_ALIGNED(md->phys_addr),
>>> +                   "UEFI Runtime regions are not aligned to 64 KB --
>>> buggy firmware?"))
>>> +             /*
>>> +              * If the region is not aligned to the page size of the
>>> OS, we
>>> +              * can not use strict permissions, since that would also
>>> affect
>>> +              * the mapping attributes of the adjacent regions.
>>> +              */
>>> +             return pgprot_val(PAGE_KERNEL_EXEC);
>>> +
>>> +     /* R-- */
>>> +     if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) ==
>>> +         (EFI_MEMORY_XP | EFI_MEMORY_RO))
>>> +             return pgprot_val(PAGE_KERNEL_RO);
>>> +
>>> +     /* R-X */
>>> +     if (attr & EFI_MEMORY_RO)
>>> +             return pgprot_val(PAGE_KERNEL_ROX);
>>> +
>>> +     /* RW- */
>>> +     if (attr & EFI_MEMORY_XP || type != EFI_RUNTIME_SERVICES_CODE)
>>> +             return pgprot_val(PAGE_KERNEL);
>>> +
>>> +     /* RWX */
>>> +     return pgprot_val(PAGE_KERNEL_EXEC);
>>> +}
>>> +
>>> +int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t
>>> *md)
>>> +{
>>> +     pteval_t prot_val = create_mapping_protection(md);
>>>
>>>       create_pgd_mapping(mm, md->phys_addr, md->virt_addr,
>>>                          md->num_pages << EFI_PAGE_SHIFT,
>> --
>> Shanker Donthineni
>> Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
>>

-- 
Shanker Donthineni
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project



From christoffer.dall at linaro.org  Wed May 18 06:08:18 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 15:08:18 +0200
Subject: [PATCH v4 29/56] KVM: arm/arm64: vgic-new: Add CONFIG registers
 handlers
In-Reply-To: <1463392481-26583-30-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-30-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518130818.GH3827@cbox>

On Mon, May 16, 2016 at 10:53:17AM +0100, Andre Przywara wrote:
> The config register handlers are shared between the v2 and v3
> emulation, so their implementation goes into vgic-mmio.c, to be
> easily referenced from the v3 emulation as well later.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
> Changelog v3 .. v4:
> - specify accessor width
> - use IRQ number accessor macro
> - replace extract_bytes() with simple return
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
>  virt/kvm/arm/vgic/vgic-mmio.c    | 46 ++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.h    |  7 ++++++
>  3 files changed, 54 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index d564a30..bb7389e 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -96,7 +96,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
>  		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 2,
> +		vgic_mmio_read_config, vgic_mmio_write_config, 2,
>  		VGIC_ACCESS_32bit),
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index 5c8af05..5fe6896 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -277,6 +277,52 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len)
> +{
> +	u32 intid = VGIC_ADDR_TO_INTID(addr, 2);
> +	u32 value = 0;
> +	int i;
> +
> +	for (i = 0; i < len * 4; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		if (irq->config == VGIC_CONFIG_EDGE)
> +			value |= (2U << (i * 2));
> +	}
> +
> +	return value;
> +}
> +
> +void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
> +			    gpa_t addr, unsigned int len,
> +			    unsigned long val)
> +{
> +	u32 intid = VGIC_ADDR_TO_INTID(addr, 2);
> +	int i;
> +
> +	for (i = 0; i < len * 4; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		if (intid + i < 16)
> +			continue;

from my last round of commenting:

s/16/VGIC_NR_SGIS/

It's implementation defined if software can program the configuration of
PPIs, and since our timer code relies on its virtual PPI always being
level triggered, I think we should change the above to
VGIC_NR_PRIVATE_IRQS and then if someone ever needs a configurable
virtual PPI, we can add that later.

> +
> +		/*
> +		 * The spec says that interrupts must be disabled before
> +		 * changing the configuration to avoid UNDEFINED behaviour.
> +		 */

I'm still not sure what the benefit of having this comment here is?

> +
> +		spin_lock(&irq->irq_lock);
> +		if (test_bit(i * 2 + 1, &val)) {
> +			irq->config = VGIC_CONFIG_EDGE;
> +		} else {
> +			irq->config = VGIC_CONFIG_LEVEL;
> +			irq->pending = irq->line_level | irq->soft_pending;
> +		}
> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
>  static int match_region(const void *key, const void *elt)
>  {
>  	const unsigned int offset = (unsigned long)key;
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index 6983922..0bd0ece 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -124,6 +124,13 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
>  			      gpa_t addr, unsigned int len,
>  			      unsigned long val);
>  
> +unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len);
> +
> +void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
> +			    gpa_t addr, unsigned int len,
> +			    unsigned long val);
> +
>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
>  
>  #endif
> -- 
> 2.8.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Thanks,
-Christoffer


From ard.biesheuvel at linaro.org  Wed May 18 06:08:32 2016
From: ard.biesheuvel at linaro.org (Ard Biesheuvel)
Date: Wed, 18 May 2016 15:08:32 +0200
Subject: [PATCH v2 2/5] arm64: efi: apply strict permissons for UEFI
 Runtime Services regions
In-Reply-To: <573C68DA.8080009@codeaurora.org>
References: <1459355933-13529-1-git-send-email-ard.biesheuvel@linaro.org>
 <1459355933-13529-3-git-send-email-ard.biesheuvel@linaro.org>
 <573BB9FE.7050008@codeaurora.org>
 <CAKv+Gu-Tam+QiXc_f0e+x8hNc4rxP_-59NdaCHkF9h=4Rd+XeA@mail.gmail.com>
 <573C68DA.8080009@codeaurora.org>
Message-ID: <CAKv+Gu9G60h66jaAOe754w7tKEdgF9NUDbkXgqNEEqKkG=LDzQ@mail.gmail.com>

On 18 May 2016 at 15:06, Shanker Donthineni <shankerd at codeaurora.org> wrote:
> Hi Ard,
>
> We are not using the permission attribute table and all the Runtime
> Data/Code regions are marked with 'XP' bit. Do you think something
> wrong in our UEFI implementation or Linux has to map RuntimeCode
> regions with executable permission always irrespective of an attribute
> flag EFI_MEMORY_XP?
>
> [    0.000000] efi: Processing EFI memory map:
> [    0.000000] efi:   0x000000100000-0x00000010ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x00003b830000-0x00003b83ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x00003c000000-0x00003fffffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x000000100000-0x00000010ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x00003b830000-0x00003b83ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x00003c000000-0x00003fffffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x004000820000-0x00400085ffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x004003080000-0x00400308ffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047f9960000-0x0047f997ffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047fa9c0000-0x0047fa9cffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047faa30000-0x0047faa3ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047fab90000-0x0047fab9ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047faba0000-0x0047fabaffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047fab90000-0x0047fab9ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047faba0000-0x0047fabaffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047fabb0000-0x0047fabbffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047fabc0000-0x0047fad9ffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047fada0000-0x0047fae2ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047faf50000-0x0047faf7ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047fafa0000-0x0047fafbffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047faf50000-0x0047faf7ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047fafa0000-0x0047fafbffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047fff90000-0x0047fff9ffff [Runtime Code       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0047fffb0000-0x0047fffdffff [Runtime Data       |RUN|  |  |XP|  |  |  |   |WB|WT|WC|UC]*
>

This memory map looks utterly broken. Assuming you are using
Tianocore, does it work when setting
gEfiMdeModulePkgTokenSpaceGuid.PcdPropertiesTableEnable to FALSE in
your platform?


From christoffer.dall at linaro.org  Wed May 18 06:14:49 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 15:14:49 +0200
Subject: [PATCH v4 32/56] KVM: arm/arm64: vgic-new: Add SGIPENDR register
 handlers
In-Reply-To: <1463392481-26583-33-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-33-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518131449.GI3827@cbox>

On Mon, May 16, 2016 at 10:53:20AM +0100, Andre Przywara wrote:
> As this register is v2 specific, its implementation lives entirely
> in vgic-mmio-v2.c.
> This register allows setting the source mask of an IPI.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
> ---
> Changelog RFC..v1:
> - remove IRQ lock from read handler
> - update pending bit on setting the first / clearing the last bit
> - queue virtual IRQ if necessary
> 
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
> Changelog v3 .. v4:
> - specify accessor width
> 
>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 60 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index c884e9b..3925d4c 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -146,6 +146,64 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
> +					    gpa_t addr, unsigned int len)
> +{
> +	u32 intid = addr & 0x0f;

is there a reason why we cannot use the magic macro here?

> +	int i;
> +	u64 val = 0;
> +
> +	for (i = 0; i < len; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		val |= (u64)irq->source << (i * 8);
> +	}
> +	return val;
> +}
> +
> +static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
> +				     gpa_t addr, unsigned int len,
> +				     unsigned long val)
> +{
> +	u32 intid = addr & 0x0f;
> +	int i;
> +
> +	for (i = 0; i < len; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		irq->source &= ~((val >> (i * 8)) & 0xff);
> +		if (!irq->source)
> +			irq->pending = false;
> +
> +		spin_unlock(&irq->irq_lock);
> +	}
> +}
> +
> +static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
> +				     gpa_t addr, unsigned int len,
> +				     unsigned long val)
> +{
> +	u32 intid = addr & 0x0f;
> +	int i;
> +
> +	for (i = 0; i < len; i++) {
> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> +
> +		spin_lock(&irq->irq_lock);
> +
> +		irq->source |= (val >> (i * 8)) & 0xff;
> +
> +		if (irq->source) {
> +			irq->pending = true;
> +			vgic_queue_irq_unlock(vcpu->kvm, irq);
> +		} else {
> +			spin_unlock(&irq->irq_lock);
> +		}
> +	}
> +}
> +
>  static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
>  		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
> @@ -184,10 +242,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>  		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4,
>  		VGIC_ACCESS_32bit),
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
> +		vgic_mmio_read_sgipend, vgic_mmio_write_sgipendc, 16,
>  		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
> +		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16,
>  		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
>  };
>  
> -- 
> 2.8.2
> 
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 06:21:31 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 15:21:31 +0200
Subject: [PATCH v4 33/56] KVM: arm/arm64: vgic-new: Add GICv3 MMIO
 handling framework
In-Reply-To: <1463392481-26583-34-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-34-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518132131.GJ3827@cbox>

On Mon, May 16, 2016 at 10:53:21AM +0100, Andre Przywara wrote:
> Create a new file called vgic-mmio-v3.c and describe the GICv3
> distributor and redistributor registers there.
> This adds a special macro to deal with the split of SGI/PPI in the
> redistributor and SPIs in the distributor, which allows us to reuse
> the existing GICv2 handlers for those registers which are compatible.
> Also we provide a function to deal with the registration of the two
> separate redistributor frames per VCPU.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Reviewed-by: Eric Auger <eric.auger at linaro.org>
> ---
> Changelog RFC..v1:
> - adapt to new MMIO registration approach:
>   register one device for the distributor and two for each VCPU
> - implement special handling for private interrupts
> - remove empty stub functions
> - make IGROUPR return RAO
> 
> Changelog v1 .. v2:
> - adapt to new framework, introduce vgic-mmio-v3.c
> - remove userland register access functions (for now)
> - precompute .len when describing a VGIC register
> - add missed pointer incrementation on registering redist regions
> - replace _nyi stub functions with raz/wi versions
> 
> Changelog v2 .. v3:
> - replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h
> - add prototype and stub code for vgic_register_redist_iodevs
> - rename register struct variables _rdbase_ and _sgibase_
> 
> Changelog v3 .. v4:
> - specify accessor width
> 
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 224 +++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
>  virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
>  virt/kvm/arm/vgic/vgic.h         |   7 ++
>  4 files changed, 238 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> new file mode 100644
> index 0000000..31f1a13
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -0,0 +1,224 @@
> +/*
> + * VGICv3 MMIO handling functions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/irqchip/arm-gic-v3.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/iodev.h>
> +#include <kvm/arm_vgic.h>
> +
> +#include <asm/kvm_emulate.h>
> +
> +#include "vgic.h"
> +#include "vgic-mmio.h"
> +
> +/*
> + * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
> + * redistributors, while SPIs are covered by registers in the distributor
> + * block. Trying to set private IRQs in this block gets ignored.
> + * We take some special care here to fix the calculation of the register
> + * offset.
> + */
> +#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, rd, wr, bpi, acc)	\
> +	{								\
> +		.reg_offset = off,					\
> +		.bits_per_irq = bpi,					\
> +		.len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8,		\
> +		.access_flags = acc,					\
> +		.read = vgic_mmio_read_raz,				\
> +		.write = vgic_mmio_write_wi,				\
> +	}, {								\
> +		.reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8,	\
> +		.bits_per_irq = bpi,					\
> +		.len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
> +		.access_flags = acc,					\
> +		.read = rd,						\
> +		.write = wr,						\
> +	}
> +
> +static const struct vgic_register_region vgic_v3_dist_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 1,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 1,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 1,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
> +		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
> +		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
> +		vgic_mmio_read_config, vgic_mmio_write_config, 2,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
> +		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
> +		VGIC_ACCESS_32bit),
> +};
> +
> +static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
> +		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
> +		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
> +		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
> +		VGIC_ACCESS_32bit),
> +};
> +
> +static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
> +	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
> +		vgic_mmio_read_rao, vgic_mmio_write_wi, 4,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
> +		vgic_mmio_read_enable, vgic_mmio_write_senable, 4,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
> +		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
> +		vgic_mmio_read_pending, vgic_mmio_write_spending, 4,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
> +		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
> +		vgic_mmio_read_active, vgic_mmio_write_sactive, 4,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
> +		vgic_mmio_read_active, vgic_mmio_write_cactive, 4,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
> +		vgic_mmio_read_priority, vgic_mmio_write_priority, 32,
> +		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
> +		vgic_mmio_read_config, vgic_mmio_write_config, 8,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
> +		VGIC_ACCESS_32bit),
> +	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
> +		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
> +		VGIC_ACCESS_32bit),
> +};
> +
> +unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
> +{
> +	dev->regions = vgic_v3_dist_registers;
> +	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
> +
> +	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
> +
> +	return SZ_64K;
> +}
> +
> +int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
> +{
> +	int nr_vcpus = atomic_read(&kvm->online_vcpus);
> +	struct kvm_vcpu *vcpu;
> +	struct vgic_io_device *devices;
> +	int c, ret = 0;
> +
> +	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
> +			  GFP_KERNEL);
> +	if (!devices)
> +		return -ENOMEM;
> +
> +	kvm_for_each_vcpu(c, vcpu, kvm) {
> +		gpa_t rd_base = redist_base_address + c * SZ_64K * 2;
> +		gpa_t sgi_base = rd_base + SZ_64K;
> +		struct vgic_io_device *rd_dev = &devices[c * 2];
> +		struct vgic_io_device *sgi_dev = &devices[c * 2 + 1];
> +
> +		kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops);
> +		rd_dev->base_addr = rd_base;
> +		rd_dev->regions = vgic_v3_rdbase_registers;
> +		rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
> +		rd_dev->redist_vcpu = vcpu;
> +
> +		mutex_lock(&kvm->slots_lock);
> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base,
> +					      SZ_64K, &rd_dev->dev);
> +		mutex_unlock(&kvm->slots_lock);
> +
> +		if (ret)
> +			break;
> +
> +		kvm_iodevice_init(&sgi_dev->dev, &kvm_io_gic_ops);
> +		sgi_dev->base_addr = sgi_base;
> +		sgi_dev->regions = vgic_v3_sgibase_registers;
> +		sgi_dev->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
> +		sgi_dev->redist_vcpu = vcpu;
> +
> +		mutex_lock(&kvm->slots_lock);
> +		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, sgi_base,
> +					      SZ_64K, &sgi_dev->dev);
> +		mutex_unlock(&kvm->slots_lock);
> +		if (ret) {
> +			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
> +						  &devices[c * 2].dev);

nit: you could replace this last bit by &rd_dev->dev

but it's up to you what you prefer.

Otherwise:

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From catalin.marinas at arm.com  Wed May 18 06:27:41 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 18 May 2016 14:27:41 +0100
Subject: [PATCH v2] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <1463576010-115428-1-git-send-email-agraf@suse.de>
References: <1463576010-115428-1-git-send-email-agraf@suse.de>
Message-ID: <20160518132741.GE22378@e104818-lin.cambridge.arm.com>

On Wed, May 18, 2016 at 02:53:30PM +0200, Alexander Graf wrote:
> On arm64, all SoCs we supported so far either have an IOMMU or have bus
> addresses equal to CPU addresses.
> 
> However, with the Raspberry Pi 3 coming up, this is no longer true. To
> allow DMA to work with an AArch64 kernel on those devices, let's allow
> devices to have DMA offsets again.
> 
> Signed-off-by: Alexander Graf <agraf at suse.de>

We were aware about this issue but we've been waiting for an actual use
case. I'll queue this for 4.8 (given that RPi3 is not supported by the
arm64 kernel, I don't see the rush to merge it earlier).

Thanks.

-- 
Catalin


From andre.przywara at arm.com  Wed May 18 06:31:18 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 18 May 2016 14:31:18 +0100
Subject: [PATCH v4 32/56] KVM: arm/arm64: vgic-new: Add SGIPENDR register
 handlers
In-Reply-To: <20160518131449.GI3827@cbox>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-33-git-send-email-andre.przywara@arm.com>
 <20160518131449.GI3827@cbox>
Message-ID: <573C6EA6.90803@arm.com>

Hi,

On 18/05/16 14:14, Christoffer Dall wrote:
> On Mon, May 16, 2016 at 10:53:20AM +0100, Andre Przywara wrote:
>> As this register is v2 specific, its implementation lives entirely
>> in vgic-mmio-v2.c.
>> This register allows setting the source mask of an IPI.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
>> ---
>> Changelog RFC..v1:
>> - remove IRQ lock from read handler
>> - update pending bit on setting the first / clearing the last bit
>> - queue virtual IRQ if necessary
>>
>> Changelog v1 .. v2:
>> - adapt to new MMIO framework
>>
>> Changelog v3 .. v4:
>> - specify accessor width
>>
>>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++--
>>  1 file changed, 60 insertions(+), 2 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> index c884e9b..3925d4c 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>> @@ -146,6 +146,64 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
>>  	}
>>  }
>>  
>> +static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
>> +					    gpa_t addr, unsigned int len)
>> +{
>> +	u32 intid = addr & 0x0f;
> 
> is there a reason why we cannot use the magic macro here?

I wasn't sure about this, because it's not covering all 1024 interrupts,
but just SGIs, so it's always fixed to 16 interrupts ? 8 bits. The
default mask would be too big in this case.
I guess it would work anyway because this region is limited to 16 bytes
in our description, so we could use this here anyway to make it more
aligned with the other handlers, maybe adding a comment about the
difference?

Cheers,
Andre.

> 
>> +	int i;
>> +	u64 val = 0;
>> +
>> +	for (i = 0; i < len; i++) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
>> +		val |= (u64)irq->source << (i * 8);
>> +	}
>> +	return val;
>> +}
>> +
>> +static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
>> +				     gpa_t addr, unsigned int len,
>> +				     unsigned long val)
>> +{
>> +	u32 intid = addr & 0x0f;
>> +	int i;
>> +
>> +	for (i = 0; i < len; i++) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
>> +		spin_lock(&irq->irq_lock);
>> +
>> +		irq->source &= ~((val >> (i * 8)) & 0xff);
>> +		if (!irq->source)
>> +			irq->pending = false;
>> +
>> +		spin_unlock(&irq->irq_lock);
>> +	}
>> +}
>> +
>> +static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
>> +				     gpa_t addr, unsigned int len,
>> +				     unsigned long val)
>> +{
>> +	u32 intid = addr & 0x0f;
>> +	int i;
>> +
>> +	for (i = 0; i < len; i++) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
>> +		spin_lock(&irq->irq_lock);
>> +
>> +		irq->source |= (val >> (i * 8)) & 0xff;
>> +
>> +		if (irq->source) {
>> +			irq->pending = true;
>> +			vgic_queue_irq_unlock(vcpu->kvm, irq);
>> +		} else {
>> +			spin_unlock(&irq->irq_lock);
>> +		}
>> +	}
>> +}
>> +
>>  static const struct vgic_register_region vgic_v2_dist_registers[] = {
>>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
>>  		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
>> @@ -184,10 +242,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
>>  		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4,
>>  		VGIC_ACCESS_32bit),
>>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
>> +		vgic_mmio_read_sgipend, vgic_mmio_write_sgipendc, 16,
>>  		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
>>  	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
>> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
>> +		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16,
>>  		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
>>  };
>>  
>> -- 
>> 2.8.2
>>
> Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
> 


From arnd at arndb.de  Wed May 18 06:45:01 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 15:45:01 +0200
Subject: [PATCH 0/5] drm: fixes for merge-window regressions
Message-ID: <1463579106-400827-1-git-send-email-arnd@arndb.de>

A couple of new warnings and build errors appeared through the DRM
tree in linux-next after the merge window opened. The first patch
here is for scripts/headers_check.pl, but as the bug is only
present in drm-next at the moment, it would be good to add all
five patches to that tree before they make it into mainline.

It's likely that some of these have already been fixed since
this morning's linux-next, so just ignore the ones are no
longer needed.

Arnd Bergmann (5):
  headers_check: don't warn about c++ guards
  drm: mediatek: add CONFIG_OF dependency
  drm: mediatek: fixup drm_gem_object_lookup API change
  drm: exynos: mark pm functions as __maybe_unused
  drm: remove unused dev variables

 drivers/gpu/drm/armada/armada_crtc.c   | 1 -
 drivers/gpu/drm/exynos/exynos_hdmi.c   | 6 ++----
 drivers/gpu/drm/mediatek/Kconfig       | 1 +
 drivers/gpu/drm/mediatek/mtk_drm_fb.c  | 2 +-
 drivers/gpu/drm/mediatek/mtk_drm_gem.c | 2 +-
 drivers/gpu/drm/nouveau/nouveau_gem.c  | 1 -
 drivers/gpu/drm/nouveau/nv50_display.c | 1 -
 drivers/gpu/drm/radeon/radeon_cs.c     | 1 -
 scripts/headers_check.pl               | 4 ++++
 9 files changed, 9 insertions(+), 10 deletions(-)


Cc: Russell King <rmk+kernel at armlinux.org.uk>
Cc: Inki Dae <inki.dae at samsung.com>
Cc: Joonyoung Shim <jy0922.shim at samsung.com>
Cc: Seung-Woo Kim <sw0312.kim at samsung.com>
Cc: Kyungmin Park <kyungmin.park at samsung.com>
Cc: Kukjin Kim <kgene at kernel.org>
Cc: Krzysztof Kozlowski <k.kozlowski at samsung.com>
Cc: Matthias Brugger <matthias.bgg at gmail.com>
Cc: Ben Skeggs <bskeggs at redhat.com>
Cc: Alex Deucher <alexander.deucher at amd.com>
Cc: "Christian K?nig" <christian.koenig at amd.com>
Cc: Arnd Bergmann <arnd at arndb.de>
Cc: dri-devel at lists.freedesktop.org
Cc: linux-kernel at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-samsung-soc at vger.kernel.org
Cc: linux-mediatek at lists.infradead.org
Cc: nouveau at lists.freedesktop.org

-- 
2.7.0



From catalin.marinas at arm.com  Wed May 18 06:45:55 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 18 May 2016 14:45:55 +0100
Subject: [PATCH] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <12218676.p29ELivsix@wuerfel>
References: <1463563981-69722-1-git-send-email-agraf@suse.de>
 <12218676.p29ELivsix@wuerfel>
Message-ID: <20160518134554.GF22378@e104818-lin.cambridge.arm.com>

On Wed, May 18, 2016 at 12:52:28PM +0200, Arnd Bergmann wrote:
> On Wednesday 18 May 2016 11:33:01 Alexander Graf wrote:
> > diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
> > index ba437f0..67bf8e1 100644
> > --- a/arch/arm64/include/asm/dma-mapping.h
> > +++ b/arch/arm64/include/asm/dma-mapping.h
> > @@ -66,12 +66,16 @@ static inline bool is_device_dma_coherent(struct device *dev)
> >  
> >  static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
> >  {
> > -       return (dma_addr_t)paddr;
> > +       dma_addr_t dev_addr = (dma_addr_t)paddr;
> > +
> > +       return dev_addr - (dma_addr_t)__pfn_to_phys(dev->dma_pfn_offset);
> >  }
> >  
> >  static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
> >  {
> > -       return (phys_addr_t)dev_addr;
> > +       phys_addr_t paddr = (phys_addr_t)dev_addr;
> > +
> > +       return paddr + __pfn_to_phys(dev->dma_pfn_offset);
> >  }
> >  
> 
> The patch looks ok overall, but I think it's better to use an open-coded
> shift instead of __pfn_to_phys/__pfn_to_phys here: those helpers convert
> between actual page frame numbers and addresses, which may not always
> be a 1:1 relationship, e.g. if someone wants to work around the crazy
> "Principles of ARM Memory Maps White Paper" layout.

Nitpick: Even better to use the PFN_PHYS() macro as it matches the
PFN_DOWN() in of_dma_configure(). I can fix it up when applying.

-- 
Catalin


From peter.ujfalusi at ti.com  Wed May 18 06:46:23 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:23 +0300
Subject: [PATCH 01/14] clk: twl6040: Correct clk_ops
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-2-git-send-email-peter.ujfalusi@ti.com>

Since the drover only supports prepare callbacks, the use of is_enabled is
not correct, it should be handling is_prepared.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 drivers/clk/clk-twl6040.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c
index 697c66757400..e167e0bbaff5 100644
--- a/drivers/clk/clk-twl6040.c
+++ b/drivers/clk/clk-twl6040.c
@@ -34,7 +34,7 @@ struct twl6040_clk {
 	int enabled;
 };
 
-static int twl6040_bitclk_is_enabled(struct clk_hw *hw)
+static int twl6040_bitclk_is_prepared(struct clk_hw *hw)
 {
 	struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
 						       mcpdm_fclk);
@@ -66,7 +66,7 @@ static void twl6040_bitclk_unprepare(struct clk_hw *hw)
 }
 
 static const struct clk_ops twl6040_mcpdm_ops = {
-	.is_enabled = twl6040_bitclk_is_enabled,
+	.is_prepared = twl6040_bitclk_is_prepared,
 	.prepare = twl6040_bitclk_prepare,
 	.unprepare = twl6040_bitclk_unprepare,
 };
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:22 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:22 +0300
Subject: [PATCH 00/14] clk/mfd/ASoC/ARM: OMAP4/5: McPDM/twl6040 pdmclk support
Message-ID: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>

Hi,

this is something I wanted to do for a long time...

First of all: sorry for the cross domain series. I did tested alone all the
domain patches and they are not causing any regression. When they come together
we will have ability to control the pdmclk needed by McPDM.

CLK patches:
The driver was w/o DT support and needed some cleanup so we can use the driver.
I have also renamed it to twl6040-pdmclk from twl6040-clk to be precise.

MFD patches:
The regmap_sync() was not working since the twl6040 does not support bulk access
and now we are going to create the needed child for the pdmclk.

ARM patches:
Updatding the board DTS files and add the needed lines for the pdmclk.

ASoC patches:
The machine driver needs to select the twl6040-clk driver as it will be used
by the omap-mcpdm.
I needed to do some cleanup and add also suspend/resume support before adding
the code for pdmclk handling since I don't want to keep the twl6040 powered on
when the board is suspended. At the moment it is not possible to do true
dynamic twl6040 power up/down due to pop noises, but I will be looking at that
later.
The driver in the future will fail if it is not able to get the pdmclk to avoid
kernel crash (McPDM registers are not accessible when pdmclk is not available).

I have tested the patches by domain and also in all (I hope) permutation they
could be. I have not experienced any regression.

Regards,
Peter
---
Peter Ujfalusi (14):
  clk: twl6040: Correct clk_ops
  clk: twl6040: Register the clock as of_clk_provider
  clk: twl6040: Rename the driver and use consistent names in the code
  mfd: twl6040: The chip does not support bulk access
  mfd: twl6040: Register child device for twl6040-pdmclk
  ARM: dts: omap5-board-common: Add pdmclk binding for audio
  ARM: dts: omap4-panda-common: Add pdmclk binding for audio
  ARM: dts: omap4-sdp: Add pdmclk binding for audio
  ARM: dts: omap4-var-som-om44: Add pdmclk binding for audio
  ARM: dts: omap4-duovero: Add pdmclk binding for audio
  ASoC: omap: Kconfig: SND_OMAP_SOC_OMAP_ABE_TWL6040 to select
    CLK_TWL6040
  ASoC: omap-mcpdm: Move the WD enable write inside
    omap_mcpdm_open_streams()
  ASoC: omap-mcpdm: Support for suspend resume
  ASoC: omap-mcpdm: Add support for pdmclk clock handling

 Documentation/devicetree/bindings/mfd/twl6040.txt  |  1 +
 .../devicetree/bindings/sound/omap-mcpdm.txt       | 10 +++
 arch/arm/boot/dts/omap4-duovero.dtsi               |  5 ++
 arch/arm/boot/dts/omap4-panda-common.dtsi          |  5 ++
 arch/arm/boot/dts/omap4-sdp.dts                    |  5 ++
 arch/arm/boot/dts/omap4-var-som-om44.dtsi          |  5 ++
 arch/arm/boot/dts/omap5-board-common.dtsi          |  5 ++
 drivers/clk/clk-twl6040.c                          | 80 +++++++++++++---------
 drivers/mfd/twl6040.c                              |  6 ++
 include/linux/mfd/twl6040.h                        |  2 +-
 sound/soc/omap/Kconfig                             |  1 +
 sound/soc/omap/omap-mcpdm.c                        | 74 ++++++++++++++++++--
 12 files changed, 160 insertions(+), 39 deletions(-)

-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:25 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:25 +0300
Subject: [PATCH 03/14] clk: twl6040: Rename the driver and use consistent
 names in the code
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-4-git-send-email-peter.ujfalusi@ti.com>

The driver is to provide the functional clock to OMAP4/5 McPDM. The clock
is named as pdmclk in the documentations so change the function names,
structure names and variables to align with this.
At the same time rename the driver from "twl6040-clk" to "twl6040-pdmclk".
This can be done w/o regression since the clock driver is not in use at
the moment, the MFD core driver is not even registering the device for it.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 drivers/clk/clk-twl6040.c | 77 +++++++++++++++++++++++++++--------------------
 1 file changed, 45 insertions(+), 32 deletions(-)

diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c
index 6a2dbe6a1627..c98b1ec76f54 100644
--- a/drivers/clk/clk-twl6040.c
+++ b/drivers/clk/clk-twl6040.c
@@ -26,60 +26,73 @@
 #include <linux/mfd/twl6040.h>
 #include <linux/clk-provider.h>
 
-struct twl6040_clk {
+struct twl6040_pdmclk {
 	struct twl6040 *twl6040;
 	struct device *dev;
-	struct clk_hw mcpdm_fclk;
+	struct clk_hw pdmclk_hw;
 	struct clk *clk;
 	int enabled;
 };
 
-static int twl6040_bitclk_is_prepared(struct clk_hw *hw)
+static int twl6040_pdmclk_is_prepared(struct clk_hw *hw)
 {
-	struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
-						       mcpdm_fclk);
-	return twl6040_clk->enabled;
+	struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk,
+						     pdmclk_hw);
+
+	return pdmclk->enabled;
 }
 
-static int twl6040_bitclk_prepare(struct clk_hw *hw)
+static int twl6040_pdmclk_prepare(struct clk_hw *hw)
 {
-	struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
-						       mcpdm_fclk);
+	struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk,
+						     pdmclk_hw);
 	int ret;
 
-	ret = twl6040_power(twl6040_clk->twl6040, 1);
+	ret = twl6040_power(pdmclk->twl6040, 1);
 	if (!ret)
-		twl6040_clk->enabled = 1;
+		pdmclk->enabled = 1;
 
 	return ret;
 }
 
-static void twl6040_bitclk_unprepare(struct clk_hw *hw)
+static void twl6040_pdmclk_unprepare(struct clk_hw *hw)
 {
-	struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
-						       mcpdm_fclk);
+	struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk,
+						     pdmclk_hw);
 	int ret;
 
-	ret = twl6040_power(twl6040_clk->twl6040, 0);
+	ret = twl6040_power(pdmclk->twl6040, 0);
 	if (!ret)
-		twl6040_clk->enabled = 0;
+		pdmclk->enabled = 0;
+
+}
+
+static unsigned long twl6040_pdmclk_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk,
+						     pdmclk_hw);
+
+	return twl6040_get_sysclk(pdmclk->twl6040);
 }
 
-static const struct clk_ops twl6040_mcpdm_ops = {
-	.is_prepared = twl6040_bitclk_is_prepared,
-	.prepare = twl6040_bitclk_prepare,
-	.unprepare = twl6040_bitclk_unprepare,
+static const struct clk_ops twl6040_pdmclk_ops = {
+	.is_prepared = twl6040_pdmclk_is_prepared,
+	.prepare = twl6040_pdmclk_prepare,
+	.unprepare = twl6040_pdmclk_unprepare,
+	.recalc_rate = twl6040_pdmclk_recalc_rate,
 };
 
-static struct clk_init_data wm831x_clkout_init = {
-	.name = "mcpdm_fclk",
-	.ops = &twl6040_mcpdm_ops,
+static struct clk_init_data twl6040_pdmclk_init = {
+	.name = "pdmclk",
+	.ops = &twl6040_pdmclk_ops,
+	.flags = CLK_GET_RATE_NOCACHE,
 };
 
-static int twl6040_clk_probe(struct platform_device *pdev)
+static int twl6040_pdmclk_probe(struct platform_device *pdev)
 {
 	struct twl6040 *twl6040 = dev_get_drvdata(pdev->dev.parent);
-	struct twl6040_clk *clkdata;
+	struct twl6040_pdmclk *clkdata;
 
 	clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);
 	if (!clkdata)
@@ -88,8 +101,8 @@ static int twl6040_clk_probe(struct platform_device *pdev)
 	clkdata->dev = &pdev->dev;
 	clkdata->twl6040 = twl6040;
 
-	clkdata->mcpdm_fclk.init = &wm831x_clkout_init;
-	clkdata->clk = devm_clk_register(&pdev->dev, &clkdata->mcpdm_fclk);
+	clkdata->pdmclk_hw.init = &twl6040_pdmclk_init;
+	clkdata->clk = devm_clk_register(&pdev->dev, &clkdata->pdmclk_hw);
 	if (IS_ERR(clkdata->clk))
 		return PTR_ERR(clkdata->clk);
 
@@ -99,16 +112,16 @@ static int twl6040_clk_probe(struct platform_device *pdev)
 				   of_clk_src_simple_get, clkdata->clk);
 }
 
-static struct platform_driver twl6040_clk_driver = {
+static struct platform_driver twl6040_pdmclk_driver = {
 	.driver = {
-		.name = "twl6040-clk",
+		.name = "twl6040-pdmclk",
 	},
-	.probe = twl6040_clk_probe,
+	.probe = twl6040_pdmclk_probe,
 };
 
-module_platform_driver(twl6040_clk_driver);
+module_platform_driver(twl6040_pdmclk_driver);
 
 MODULE_DESCRIPTION("TWL6040 clock driver for McPDM functional clock");
 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi at ti.com>");
-MODULE_ALIAS("platform:twl6040-clk");
+MODULE_ALIAS("platform:twl6040-pdmclk");
 MODULE_LICENSE("GPL");
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:27 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:27 +0300
Subject: [PATCH 05/14] mfd: twl6040: Register child device for twl6040-pdmclk
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-6-git-send-email-peter.ujfalusi@ti.com>

The McPDM in OMAP4/5 is using the pdmclk from twl6040 as functional clock.
The twl6040-pdmclk driver provides a clock which can be used to make sure
that the pdmclk is active when the McPDM is in use.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 Documentation/devicetree/bindings/mfd/twl6040.txt | 1 +
 drivers/mfd/twl6040.c                             | 5 +++++
 include/linux/mfd/twl6040.h                       | 2 +-
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mfd/twl6040.txt b/Documentation/devicetree/bindings/mfd/twl6040.txt
index e6afdfa3543d..9a98ee7c323d 100644
--- a/Documentation/devicetree/bindings/mfd/twl6040.txt
+++ b/Documentation/devicetree/bindings/mfd/twl6040.txt
@@ -12,6 +12,7 @@ Required properties:
 - interrupt-parent: The parent interrupt controller
 - gpio-controller:
 - #gpio-cells = <1>: twl6040 provides GPO lines.
+- #clock-cells = <0>; twl6040 is a provider of pdmclk which is used by McPDM
 - twl6040,audpwron-gpio: Power on GPIO line for the twl6040
 
 - vio-supply: Regulator for the twl6040 VIO supply
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index 2596546553aa..873628a1bd79 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -782,6 +782,11 @@ static int twl6040_probe(struct i2c_client *client,
 	cell->name = "twl6040-gpo";
 	children++;
 
+	/* PDM clock support  */
+	cell = &twl6040->cells[children];
+	cell->name = "twl6040-pdmclk";
+	children++;
+
 	/* The chip is powered down so mark regmap to cache only and dirty */
 	regcache_cache_only(twl6040->regmap, true);
 	regcache_mark_dirty(twl6040->regmap);
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h
index 8015db974157..ef0bb07c3f3d 100644
--- a/include/linux/mfd/twl6040.h
+++ b/include/linux/mfd/twl6040.h
@@ -168,7 +168,7 @@
 #define TWL6040_VIBROCDET		0x20
 #define TWL6040_TSHUTDET                0x40
 
-#define TWL6040_CELLS			3
+#define TWL6040_CELLS			4
 
 #define TWL6040_REV_ES1_0		0x00
 #define TWL6040_REV_ES1_1		0x01 /* Rev ES1.1 and ES1.2 */
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:26 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:26 +0300
Subject: [PATCH 04/14] mfd: twl6040: The chip does not support bulk access
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-5-git-send-email-peter.ujfalusi@ti.com>

Bulk access is not working with twl6040, we need to use single register
access. Bulk access would happen when we try to sync the regcache after
power on.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 drivers/mfd/twl6040.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index f3dcf3a85e84..2596546553aa 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -608,6 +608,7 @@ static const struct regmap_config twl6040_regmap_config = {
 	.writeable_reg = twl6040_writeable_reg,
 
 	.cache_type = REGCACHE_RBTREE,
+	.use_single_rw = true,
 };
 
 static const struct regmap_irq twl6040_irqs[] = {
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:24 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:24 +0300
Subject: [PATCH 02/14] clk: twl6040: Register the clock as of_clk_provider
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-3-git-send-email-peter.ujfalusi@ti.com>

In order ot be able to use the pdmclk clock via DT it need to be registered
as of_clk_provide.
Since the twl6040 clock driver does not have it's own DT node, use the
parent's node for registering.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 drivers/clk/clk-twl6040.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c
index e167e0bbaff5..6a2dbe6a1627 100644
--- a/drivers/clk/clk-twl6040.c
+++ b/drivers/clk/clk-twl6040.c
@@ -95,7 +95,8 @@ static int twl6040_clk_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, clkdata);
 
-	return 0;
+	return of_clk_add_provider(pdev->dev.parent->of_node,
+				   of_clk_src_simple_get, clkdata->clk);
 }
 
 static struct platform_driver twl6040_clk_driver = {
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:33 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:33 +0300
Subject: [PATCH 11/14] ASoC: omap: Kconfig: SND_OMAP_SOC_OMAP_ABE_TWL6040 to
 select CLK_TWL6040
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-12-git-send-email-peter.ujfalusi@ti.com>

The pdmclk is needed for McPDM. It is generated by twl6040.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 sound/soc/omap/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 5520273724ae..347705c04db1 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -119,6 +119,7 @@ config SND_OMAP_SOC_OMAP_ABE_TWL6040
 	select SND_SOC_TWL6040
 	select SND_SOC_DMIC
 	select COMMON_CLK_PALMAS if (SOC_OMAP5 && MFD_PALMAS)
+	select CLK_TWL6040
 	help
 	  Say Y if you want to add support for SoC audio on OMAP boards using
 	  ABE and twl6040 codec. This driver currently supports:
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:32 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:32 +0300
Subject: [PATCH 10/14] ARM: dts: omap4-duovero: Add pdmclk binding for audio
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-11-git-send-email-peter.ujfalusi@ti.com>

The twl6040 codec is generating the pdmclk, which is used by the McPDM as
functional clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap4-duovero.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap4-duovero.dtsi b/arch/arm/boot/dts/omap4-duovero.dtsi
index f2a94fa62552..a90b582e4c3f 100644
--- a/arch/arm/boot/dts/omap4-duovero.dtsi
+++ b/arch/arm/boot/dts/omap4-duovero.dtsi
@@ -177,6 +177,7 @@
 
 	twl6040: twl at 4b {
 		compatible = "ti,twl6040";
+		#clock-cells = <0>;
 		reg = <0x4b>;
 		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;		/* IRQ_SYS_2N cascaded to gic */
 		ti,audpwron-gpio = <&gpio6 0 GPIO_ACTIVE_HIGH>;		/* gpio_160 */
@@ -207,6 +208,10 @@
 &mcpdm {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcpdm_pins>;
+
+	clocks = <&twl6040>;
+	clock-names = "pdmclk";
+
 	status = "okay";
 };
 
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:28 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:28 +0300
Subject: [PATCH 06/14] ARM: dts: omap5-board-common: Add pdmclk binding for
 audio
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-7-git-send-email-peter.ujfalusi@ti.com>

The twl6040 codec is generating the pdmclk, which is used by the McPDM as
functional clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap5-board-common.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi
index 19efaa079797..63d0352d068d 100644
--- a/arch/arm/boot/dts/omap5-board-common.dtsi
+++ b/arch/arm/boot/dts/omap5-board-common.dtsi
@@ -637,6 +637,7 @@
 
 	twl6040: twl at 4b {
 		compatible = "ti,twl6040";
+		#clock-cells = <0>;
 		reg = <0x4b>;
 
 		pinctrl-names = "default";
@@ -658,6 +659,10 @@
 &mcpdm {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcpdm_pins>;
+
+	clocks = <&twl6040>;
+	clock-names = "pdmclk";
+
 	status = "okay";
 };
 
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:30 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:30 +0300
Subject: [PATCH 08/14] ARM: dts: omap4-sdp: Add pdmclk binding for audio
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-9-git-send-email-peter.ujfalusi@ti.com>

The twl6040 codec is generating the pdmclk, which is used by the McPDM as
functional clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap4-sdp.dts | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
index aae513265dc2..7e6cd2d8ed5d 100644
--- a/arch/arm/boot/dts/omap4-sdp.dts
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -367,6 +367,7 @@
 
 	twl6040: twl at 4b {
 		compatible = "ti,twl6040";
+		#clock-cells = <0>;
 		reg = <0x4b>;
 
 		pinctrl-names = "default";
@@ -620,6 +621,10 @@
 &mcpdm {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcpdm_pins>;
+
+	clocks = <&twl6040>;
+	clock-names = "pdmclk";
+
 	status = "okay";
 };
 
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:31 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:31 +0300
Subject: [PATCH 09/14] ARM: dts: omap4-var-som-om44: Add pdmclk binding for
 audio
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-10-git-send-email-peter.ujfalusi@ti.com>

The twl6040 codec is generating the pdmclk, which is used by the McPDM as
functional clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap4-var-som-om44.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap4-var-som-om44.dtsi b/arch/arm/boot/dts/omap4-var-som-om44.dtsi
index a17997f4e9aa..873cfc87260c 100644
--- a/arch/arm/boot/dts/omap4-var-som-om44.dtsi
+++ b/arch/arm/boot/dts/omap4-var-som-om44.dtsi
@@ -189,6 +189,7 @@
 
 	twl6040: twl at 4b {
 		compatible = "ti,twl6040";
+		#clock-cells = <0>;
 		reg = <0x4b>;
 
 		pinctrl-names = "default";
@@ -252,6 +253,10 @@
 &mcpdm {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcpdm_pins>;
+
+	clocks = <&twl6040>;
+	clock-names = "pdmclk";
+
 	status = "okay";
 };
 
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:34 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:34 +0300
Subject: [PATCH 12/14] ASoC: omap-mcpdm: Move the WD enable write inside
 omap_mcpdm_open_streams()
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-13-git-send-email-peter.ujfalusi@ti.com>

The DS4_WD_EN bit is only touched before calling omap_mcpdm_open_streams().
Move it inside of that function for simplicity.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 sound/soc/omap/omap-mcpdm.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index b837265ac3e9..11bd07cdce22 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -173,6 +173,10 @@ static inline int omap_mcpdm_active(struct omap_mcpdm *mcpdm)
  */
 static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm)
 {
+	u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl | MCPDM_WD_EN);
+
 	omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_SET,
 			MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL |
 			MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
@@ -258,12 +262,9 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
 
 	mutex_lock(&mcpdm->mutex);
 
-	if (!dai->active) {
-		u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
-
-		omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl | MCPDM_WD_EN);
+	if (!dai->active)
 		omap_mcpdm_open_streams(mcpdm);
-	}
+
 	mutex_unlock(&mcpdm->mutex);
 
 	return 0;
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:35 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:35 +0300
Subject: [PATCH 13/14] ASoC: omap-mcpdm: Support for suspend resume
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-14-git-send-email-peter.ujfalusi@ti.com>

Implement ASoC's suspend and resume callbacks.
Since McPDM does not use pcm_trigger for start and stop of the stream due
to strict sequencing needs with the twl6040, the callbacks will stop and
restart the McPDM in case the board suspended during audio activity.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 sound/soc/omap/omap-mcpdm.c | 46 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 11bd07cdce22..74d6e6fdcfd0 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -66,6 +66,9 @@ struct omap_mcpdm {
 	/* McPDM needs to be restarted due to runtime reconfiguration */
 	bool restart;
 
+	/* pm state for suspend/resume handling */
+	int pm_active_count;
+
 	struct snd_dmaengine_dai_dma_data dma_data[2];
 };
 
@@ -422,12 +425,55 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int omap_mcpdm_suspend(struct snd_soc_dai *dai)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+	if (dai->active) {
+		omap_mcpdm_stop(mcpdm);
+		omap_mcpdm_close_streams(mcpdm);
+	}
+
+	mcpdm->pm_active_count = 0;
+	while (pm_runtime_active(mcpdm->dev)) {
+		pm_runtime_put_sync(mcpdm->dev);
+		mcpdm->pm_active_count++;
+	}
+
+	return 0;
+}
+
+static int omap_mcpdm_resume(struct snd_soc_dai *dai)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+	if (mcpdm->pm_active_count) {
+		while (mcpdm->pm_active_count--)
+			pm_runtime_get_sync(mcpdm->dev);
+
+		if (dai->active) {
+			omap_mcpdm_open_streams(mcpdm);
+			omap_mcpdm_start(mcpdm);
+		}
+	}
+
+
+	return 0;
+}
+#else
+#define omap_mcpdm_suspend NULL
+#define omap_mcpdm_resume NULL
+#endif
+
 #define OMAP_MCPDM_RATES	(SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 #define OMAP_MCPDM_FORMATS	SNDRV_PCM_FMTBIT_S32_LE
 
 static struct snd_soc_dai_driver omap_mcpdm_dai = {
 	.probe = omap_mcpdm_probe,
 	.remove = omap_mcpdm_remove,
+	.suspend = omap_mcpdm_suspend,
+	.resume = omap_mcpdm_resume,
 	.probe_order = SND_SOC_COMP_ORDER_LATE,
 	.remove_order = SND_SOC_COMP_ORDER_EARLY,
 	.playback = {
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:29 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:29 +0300
Subject: [PATCH 07/14] ARM: dts: omap4-panda-common: Add pdmclk binding for
 audio
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-8-git-send-email-peter.ujfalusi@ti.com>

The twl6040 codec is generating the pdmclk, which is used by the McPDM as
functional clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap4-panda-common.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi
index df2e356ec089..e1d606f64cb7 100644
--- a/arch/arm/boot/dts/omap4-panda-common.dtsi
+++ b/arch/arm/boot/dts/omap4-panda-common.dtsi
@@ -376,6 +376,7 @@
 
 	twl6040: twl at 4b {
 		compatible = "ti,twl6040";
+		#clock-cells = <0>;
 		reg = <0x4b>;
 
 		pinctrl-names = "default";
@@ -479,6 +480,10 @@
 &mcpdm {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcpdm_pins>;
+
+	clocks = <&twl6040>;
+	clock-names = "pdmclk";
+
 	status = "okay";
 };
 
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 18 06:46:36 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 18 May 2016 16:46:36 +0300
Subject: [PATCH 14/14] ASoC: omap-mcpdm: Add support for pdmclk clock handling
In-Reply-To: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1463579196-5484-15-git-send-email-peter.ujfalusi@ti.com>

McPDM module receives it's functional clock from external source. This
clock is the pdmclk provided by the twl6040 audio IC. If the clock is not
available all register accesses to McPDM fails and the module is not
operational.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 Documentation/devicetree/bindings/sound/omap-mcpdm.txt | 10 ++++++++++
 sound/soc/omap/omap-mcpdm.c                            | 17 +++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/omap-mcpdm.txt b/Documentation/devicetree/bindings/sound/omap-mcpdm.txt
index 0741dff048dd..6f6c2f8e908d 100644
--- a/Documentation/devicetree/bindings/sound/omap-mcpdm.txt
+++ b/Documentation/devicetree/bindings/sound/omap-mcpdm.txt
@@ -8,6 +8,8 @@ Required properties:
 - interrupts: Interrupt number for McPDM
 - interrupt-parent: The parent interrupt controller
 - ti,hwmods: Name of the hwmod associated to the McPDM
+- clocks:  phandle for the pdmclk provider, likely <&twl6040>
+- clock-names: Must be "pdmclk"
 
 Example:
 
@@ -19,3 +21,11 @@ mcpdm: mcpdm at 40132000 {
 	interrupt-parent = <&gic>;
 	ti,hwmods = "mcpdm";
 };
+
+In board DTS file the pdmclk needs to be added:
+
+&mcpdm {
+	clocks = <&twl6040>;
+	clock-names = "pdmclk";
+	status = "okay";
+};
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 74d6e6fdcfd0..e7cdc51fd806 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -31,6 +31,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/of_device.h>
@@ -54,6 +55,7 @@ struct omap_mcpdm {
 	unsigned long phys_base;
 	void __iomem *io_base;
 	int irq;
+	struct clk *pdmclk;
 
 	struct mutex mutex;
 
@@ -388,6 +390,7 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
 	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 	int ret;
 
+	clk_prepare_enable(mcpdm->pdmclk);
 	pm_runtime_enable(mcpdm->dev);
 
 	/* Disable lines while request is ongoing */
@@ -422,6 +425,7 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
 
 	pm_runtime_disable(mcpdm->dev);
 
+	clk_disable_unprepare(mcpdm->pdmclk);
 	return 0;
 }
 
@@ -441,6 +445,8 @@ static int omap_mcpdm_suspend(struct snd_soc_dai *dai)
 		mcpdm->pm_active_count++;
 	}
 
+	clk_disable_unprepare(mcpdm->pdmclk);
+
 	return 0;
 }
 
@@ -448,6 +454,8 @@ static int omap_mcpdm_resume(struct snd_soc_dai *dai)
 {
 	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 
+	clk_prepare_enable(mcpdm->pdmclk);
+
 	if (mcpdm->pm_active_count) {
 		while (mcpdm->pm_active_count--)
 			pm_runtime_get_sync(mcpdm->dev);
@@ -541,6 +549,15 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
 
 	mcpdm->dev = &pdev->dev;
 
+	mcpdm->pdmclk = devm_clk_get(&pdev->dev, "pdmclk");
+	if (IS_ERR(mcpdm->pdmclk)) {
+		if (PTR_ERR(mcpdm->pdmclk) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		dev_warn(&pdev->dev, "Error getting pdmclk (%ld)!\n",
+			 PTR_ERR(mcpdm->pdmclk));
+		mcpdm->pdmclk = NULL;
+	}
+
 	ret =  devm_snd_soc_register_component(&pdev->dev,
 					       &omap_mcpdm_component,
 					       &omap_mcpdm_dai, 1);
-- 
2.8.2



From christoffer.dall at linaro.org  Wed May 18 06:49:23 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 15:49:23 +0200
Subject: [PATCH v4 37/56] KVM: arm/arm64: vgic-new: Add GICv3 IROUTER
 register handlers
In-Reply-To: <1463392481-26583-38-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-38-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518134923.GK3827@cbox>

On Mon, May 16, 2016 at 10:53:25AM +0100, Andre Przywara wrote:
> Since GICv3 supports much more than the 8 CPUs the GICv2 ITARGETSR
> register can handle, the new IROUTER register covers the whole range
> of possible target (V)CPUs by using the same MPIDR that the cores
> report themselves.
> In addition to translating this MPIDR into a vcpu pointer we store
> the originally written value as well. The architecture allows to
> write any values into the register, which must be read back as written.
> 
> Since we don't support affinity level 3, we don't need to take care
> about the upper word of this 64-bit register, which simplifies the
> handling a bit.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - fold in and simplify vgic_v3_irq_change_affinity
> 
> Changelog v1 .. v2:
> - adapt to new MMIO framework
> 
> Changelog v3 .. v4:
> - move accessor width check into dispatcher
> - use IRQ number accessor macro
> 
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 37 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 36 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index b893284..7b9340b 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -75,6 +75,41 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
> +					    gpa_t addr, unsigned int len)
> +{
> +	int intid = VGIC_ADDR_TO_INTID(addr, 64);
> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
> +
> +	if (!irq)
> +		return 0;
> +
> +	return extract_bytes(READ_ONCE(irq->mpidr), addr & 7, len);

So for this to work for accesses to the upper word, we rely on this only
ever running on AArch64 where an unsigned long is 64 bits and the call
to extract_bytes converts the u32 irq->mpidr to 64 bit unsigned long?

Feels a bit weird, but I suppose this always works:

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>

> +}
> +
> +static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
> +				    gpa_t addr, unsigned int len,
> +				    unsigned long val)
> +{
> +	int intid = VGIC_ADDR_TO_INTID(addr, 64);
> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
> +
> +	if (!irq)
> +		return;
> +
> +	/* The upper word is WI for us since we don't implement Aff3. */
> +	if (addr & 4)
> +		return;
> +
> +	spin_lock(&irq->irq_lock);
> +
> +	/* We only care about and preserve Aff0, Aff1 and Aff2. */
> +	irq->mpidr = val & GENMASK(23, 0);
> +	irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, irq->mpidr);
> +
> +	spin_unlock(&irq->irq_lock);
> +}
> +
>  static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
>  					      gpa_t addr, unsigned int len)
>  {
> @@ -170,7 +205,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
>  		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
>  		VGIC_ACCESS_32bit),
>  	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
> -		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
> +		vgic_mmio_read_irouter, vgic_mmio_write_irouter, 64,
>  		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
>  	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
>  		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
> -- 
> 2.8.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From agraf at suse.de  Wed May 18 06:49:17 2016
From: agraf at suse.de (Alexander Graf)
Date: Wed, 18 May 2016 15:49:17 +0200
Subject: [PATCH v2] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <20160518132741.GE22378@e104818-lin.cambridge.arm.com>
References: <1463576010-115428-1-git-send-email-agraf@suse.de>
 <20160518132741.GE22378@e104818-lin.cambridge.arm.com>
Message-ID: <573C72DD.6010400@suse.de>

On 05/18/2016 03:27 PM, Catalin Marinas wrote:
> On Wed, May 18, 2016 at 02:53:30PM +0200, Alexander Graf wrote:
>> On arm64, all SoCs we supported so far either have an IOMMU or have bus
>> addresses equal to CPU addresses.
>>
>> However, with the Raspberry Pi 3 coming up, this is no longer true. To
>> allow DMA to work with an AArch64 kernel on those devices, let's allow
>> devices to have DMA offsets again.
>>
>> Signed-off-by: Alexander Graf <agraf at suse.de>
> We were aware about this issue but we've been waiting for an actual use
> case. I'll queue this for 4.8 (given that RPi3 is not supported by the
> arm64 kernel, I don't see the rush to merge it earlier).

Sure, works for me. That way Eric can try to push the other few bits 
necessary to run an arm64 kernel on the RPi3 towards 4.8 as well :).


Alex



From christoffer.dall at linaro.org  Wed May 18 06:50:22 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 15:50:22 +0200
Subject: [PATCH v4 32/56] KVM: arm/arm64: vgic-new: Add SGIPENDR register
 handlers
In-Reply-To: <573C6EA6.90803@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-33-git-send-email-andre.przywara@arm.com>
 <20160518131449.GI3827@cbox> <573C6EA6.90803@arm.com>
Message-ID: <20160518135022.GL3827@cbox>

On Wed, May 18, 2016 at 02:31:18PM +0100, Andre Przywara wrote:
> Hi,
> 
> On 18/05/16 14:14, Christoffer Dall wrote:
> > On Mon, May 16, 2016 at 10:53:20AM +0100, Andre Przywara wrote:
> >> As this register is v2 specific, its implementation lives entirely
> >> in vgic-mmio-v2.c.
> >> This register allows setting the source mask of an IPI.
> >>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
> >> ---
> >> Changelog RFC..v1:
> >> - remove IRQ lock from read handler
> >> - update pending bit on setting the first / clearing the last bit
> >> - queue virtual IRQ if necessary
> >>
> >> Changelog v1 .. v2:
> >> - adapt to new MMIO framework
> >>
> >> Changelog v3 .. v4:
> >> - specify accessor width
> >>
> >>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++--
> >>  1 file changed, 60 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> index c884e9b..3925d4c 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> >> @@ -146,6 +146,64 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
> >>  	}
> >>  }
> >>  
> >> +static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
> >> +					    gpa_t addr, unsigned int len)
> >> +{
> >> +	u32 intid = addr & 0x0f;
> > 
> > is there a reason why we cannot use the magic macro here?
> 
> I wasn't sure about this, because it's not covering all 1024 interrupts,
> but just SGIs, so it's always fixed to 16 interrupts ? 8 bits. The
> default mask would be too big in this case.
> I guess it would work anyway because this region is limited to 16 bytes
> in our description, so we could use this here anyway to make it more
> aligned with the other handlers, maybe adding a comment about the
> difference?
> 
meh, either way works for me actually, whatever you prefer.

Thanks,
-Christoffer


From arnd at arndb.de  Wed May 18 06:50:02 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 15:50:02 +0200
Subject: [PATCH] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <20160518134554.GF22378@e104818-lin.cambridge.arm.com>
References: <1463563981-69722-1-git-send-email-agraf@suse.de>
 <12218676.p29ELivsix@wuerfel>
 <20160518134554.GF22378@e104818-lin.cambridge.arm.com>
Message-ID: <30915363.3kcXpGGcy5@wuerfel>

On Wednesday 18 May 2016 14:45:55 Catalin Marinas wrote:
> On Wed, May 18, 2016 at 12:52:28PM +0200, Arnd Bergmann wrote:
> > On Wednesday 18 May 2016 11:33:01 Alexander Graf wrote:
> > > diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
> > > index ba437f0..67bf8e1 100644
> > > --- a/arch/arm64/include/asm/dma-mapping.h
> > > +++ b/arch/arm64/include/asm/dma-mapping.h
> > > @@ -66,12 +66,16 @@ static inline bool is_device_dma_coherent(struct device *dev)
> > >  
> > >  static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
> > >  {
> > > -       return (dma_addr_t)paddr;
> > > +       dma_addr_t dev_addr = (dma_addr_t)paddr;
> > > +
> > > +       return dev_addr - (dma_addr_t)__pfn_to_phys(dev->dma_pfn_offset);
> > >  }
> > >  
> > >  static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
> > >  {
> > > -       return (phys_addr_t)dev_addr;
> > > +       phys_addr_t paddr = (phys_addr_t)dev_addr;
> > > +
> > > +       return paddr + __pfn_to_phys(dev->dma_pfn_offset);
> > >  }
> > >  
> > 
> > The patch looks ok overall, but I think it's better to use an open-coded
> > shift instead of __pfn_to_phys/__pfn_to_phys here: those helpers convert
> > between actual page frame numbers and addresses, which may not always
> > be a 1:1 relationship, e.g. if someone wants to work around the crazy
> > "Principles of ARM Memory Maps White Paper" layout.
> 
> Nitpick: Even better to use the PFN_PHYS() macro as it matches the
> PFN_DOWN() in of_dma_configure(). I can fix it up when applying.
> 
> 

I'd probably avoid that for the same reason as avoiding __pfn_to_phys.
In practice all three methods do the same thing for now, and if someone
wanted to change one, they'd also have to audit all the existing users.

	Arnd


From joel at jms.id.au  Wed May 18 06:50:31 2016
From: joel at jms.id.au (Joel Stanley)
Date: Wed, 18 May 2016 23:20:31 +0930
Subject: [PATCH v2 1/2] doc/devicetree: Add Aspeed VIC bindings
In-Reply-To: <CAL_JsqJDGmvDxm1kN1w6NQZs0JLeA-V=X_BWi=VOaMTwftLn-w@mail.gmail.com>
References: <462797239-14765-1-git-send-email-joel@jms.id.au>
 <1462802317-27086-1-git-send-email-joel@jms.id.au>
 <1462802317-27086-2-git-send-email-joel@jms.id.au>
 <20160511143313.GA7426@rob-hp-laptop>
 <1463014882.20290.203.camel@kernel.crashing.org>
 <CAL_JsqJDGmvDxm1kN1w6NQZs0JLeA-V=X_BWi=VOaMTwftLn-w@mail.gmail.com>
Message-ID: <CACPK8Xe6TDdV3dC=gizXLxLjUziDFhsupUbXSuYsn6bcrAxahQ@mail.gmail.com>

On Fri, May 13, 2016 at 2:50 AM, Rob Herring <robh at kernel.org> wrote:
> On Wed, May 11, 2016 at 8:01 PM, Benjamin Herrenschmidt
> <benh at kernel.crashing.org> wrote:
>> On Wed, 2016-05-11 at 09:33 -0500, Rob Herring wrote:
>>> > +- interrupt-controller : Identifies the node as an interrupt controller
>>> > +- #interrupt-cells : Specifies the number of cells needed to encode an
>>> > +  interrupt source. The value shall be 1.
>>>
>>> No need for level vs. edge flags?
>>
>> That's an open question. Most interrupts are fixed. A handful of GPIOs
>> can be configured either way. For now I am relying on uboot setting up
>> the right config for them and I read it back at boot time, but we could
>> make it part of the binding I suppose.
>
> It is almost standard to just use 2 cells here even if reserved for
> future use. Especially since the IP block seems to have registers to
> control that.

Yep, makes sense. I've added this to the bindings document.

I was trying to use the second cell in our driver:

  static struct irq_domain_ops avic_dom_ops = {
          .map = avic_map,
         .xlate = irq_domain_xlate_twocell,
  };

 So we have irq_domain_xlate_twocell to parse the device tree and
grabs the type property from the second cell.

In avic_map we set the irq handler:

         if (vic->edge_sources[sidx] & sbit) {
                 /* TODO: Check aginst type from dt and warn if not edge */
                 irq_set_chip_and_handler(irq, &avic_chip, handle_edge_irq);
         } else {
                 /* TODO: Check aginst type from dt and warn if not level */
                 irq_set_chip_and_handler(irq, &avic_chip, handle_level_irq);
         }

However, we don't have the type here, so we can't use it to check that
we're setting the correct edge/level callback (or use it to set the
register in the future if we want to use the device tree to override
the bootloader settings).

I had a look at some other drivers and they don't seem to use the dt
property when mapping the irq. What am I missing here?

Cheers,

Joel


From christoffer.dall at linaro.org  Wed May 18 06:53:45 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 15:53:45 +0200
Subject: [PATCH v4 38/56] KVM: arm/arm64: vgic-new: Add GICv3 SGI system
 register trap handler
In-Reply-To: <1463392481-26583-39-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-39-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518135345.GM3827@cbox>

On Mon, May 16, 2016 at 10:53:26AM +0100, Andre Przywara wrote:
> In contrast to GICv2 SGIs in a GICv3 implementation are not triggered
> by a MMIO write, but with a system register write. KVM knows about
> that register already, we just need to implement the handler and wire
> it up to the core KVM/ARM code.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - add comment about SGI_AFFINITY_LEVEL macro
> 
>  include/kvm/vgic/vgic.h          |   8 +++
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 106 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 114 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index ff3f9c2..00e3dca 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -209,6 +209,14 @@ bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
>  void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
>  void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
>  
> +#ifdef CONFIG_KVM_ARM_VGIC_V3
> +void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
> +#else
> +static inline void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
> +{
> +}
> +#endif
> +
>  /**
>   * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
>   *
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index 7b9340b..63b8550 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -343,3 +343,109 @@ int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
>  
>  	return ret;
>  }
> +
> +/*
> + * Compare a given affinity (level 1-3 and a level 0 mask, from the SGI
> + * generation register ICC_SGI1R_EL1) with a given VCPU.
> + * If the VCPU's MPIDR matches, return the level0 affinity, otherwise
> + * return -1.
> + */
> +static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct kvm_vcpu *vcpu)
> +{
> +	unsigned long affinity;
> +	int level0;
> +
> +	/*
> +	 * Split the current VCPU's MPIDR into affinity level 0 and the
> +	 * rest as this is what we have to compare against.
> +	 */
> +	affinity = kvm_vcpu_get_mpidr_aff(vcpu);
> +	level0 = MPIDR_AFFINITY_LEVEL(affinity, 0);
> +	affinity &= ~MPIDR_LEVEL_MASK;
> +
> +	/* bail out if the upper three levels don't match */
> +	if (sgi_aff != affinity)
> +		return -1;
> +
> +	/* Is this VCPU's bit set in the mask ? */
> +	if (!(sgi_cpu_mask & BIT(level0)))
> +		return -1;
> +
> +	return level0;
> +}
> +
> +/*
> + * The ICC_SGI* registers encode the affinity differently from the MPIDR,
> + * so provide a wrapper to use the existing defines to isolate a certain
> + * affinity level.
> + */
> +#define SGI_AFFINITY_LEVEL(reg, level) \
> +	((((reg) & ICC_SGI1R_AFFINITY_## level ##_MASK) \
> +	>> ICC_SGI1R_AFFINITY_## level ##_SHIFT) << MPIDR_LEVEL_SHIFT(level))
> +

Do we still prefer this over the following (untested) ?:

static inline u64 decode_sgi_affinity(u64 reg)
{
	u64 aff1, aff2, aff3;

	aff1 = (reg & ICC_SGI1R_AFFINITY_1_MASK) >> ICC_SGI1R_AFFINITY_1_SHIFT;
	aff2 = (reg & ICC_SGI1R_AFFINITY_2_MASK) >> ICC_SGI1R_AFFINITY_2_SHIFT;
	aff3 = (reg & ICC_SGI1R_AFFINITY_3_MASK) >> ICC_SGI1R_AFFINITY_3_SHIFT;

	return (aff1 << MPIDR_LEVEL_SHIFT(1)) |
		(aff2 << MPIDR_LEVEL_SHIFT(2)) |
		(aff3 << MPIDR_LEVEL_SHIFT(3));
}


> +/**
> + * vgic_v3_dispatch_sgi - handle SGI requests from VCPUs
> + * @vcpu: The VCPU requesting a SGI
> + * @reg: The value written into the ICC_SGI1R_EL1 register by that VCPU
> + *
> + * With GICv3 (and ARE=1) CPUs trigger SGIs by writing to a system register.
> + * This will trap in sys_regs.c and call this function.
> + * This ICC_SGI1R_EL1 register contains the upper three affinity levels of the
> + * target processors as well as a bitmask of 16 Aff0 CPUs.
> + * If the interrupt routing mode bit is not set, we iterate over all VCPUs to
> + * check for matching ones. If this bit is set, we signal all, but not the
> + * calling VCPU.
> + */
> +void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
> +{
> +	struct kvm *kvm = vcpu->kvm;
> +	struct kvm_vcpu *c_vcpu;
> +	u16 target_cpus;
> +	u64 mpidr;
> +	int sgi, c;
> +	int vcpu_id = vcpu->vcpu_id;
> +	bool broadcast;
> +
> +	sgi = (reg & ICC_SGI1R_SGI_ID_MASK) >> ICC_SGI1R_SGI_ID_SHIFT;
> +	broadcast = reg & BIT(ICC_SGI1R_IRQ_ROUTING_MODE_BIT);
> +	target_cpus = (reg & ICC_SGI1R_TARGET_LIST_MASK) >> ICC_SGI1R_TARGET_LIST_SHIFT;
> +	mpidr = SGI_AFFINITY_LEVEL(reg, 3);
> +	mpidr |= SGI_AFFINITY_LEVEL(reg, 2);
> +	mpidr |= SGI_AFFINITY_LEVEL(reg, 1);
> +
> +	/*
> +	 * We iterate over all VCPUs to find the MPIDRs matching the request.
> +	 * If we have handled one CPU, we clear its bit to detect early
> +	 * if we are already finished. This avoids iterating through all
> +	 * VCPUs when most of the times we just signal a single VCPU.
> +	 */
> +	kvm_for_each_vcpu(c, c_vcpu, kvm) {
> +		struct vgic_irq *irq;
> +
> +		/* Exit early if we have dealt with all requested CPUs */
> +		if (!broadcast && target_cpus == 0)
> +			break;
> +
> +		/* Don't signal the calling VCPU */
> +		if (broadcast && c == vcpu_id)
> +			continue;
> +
> +		if (!broadcast) {
> +			int level0;
> +
> +			level0 = match_mpidr(mpidr, target_cpus, c_vcpu);
> +			if (level0 == -1)
> +				continue;
> +
> +			/* remove this matching VCPU from the mask */
> +			target_cpus &= ~BIT(level0);
> +		}
> +
> +		irq = vgic_get_irq(vcpu->kvm, c_vcpu, sgi);
> +
> +		spin_lock(&irq->irq_lock);
> +		irq->pending = true;
> +
> +		vgic_queue_irq_unlock(vcpu->kvm, irq);
> +	}
> +}
> -- 
> 2.8.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From christoffer.dall at linaro.org  Wed May 18 06:55:43 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 15:55:43 +0200
Subject: [PATCH v4 44/56] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 access to VGIC registers
In-Reply-To: <1463392481-26583-45-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-45-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518135543.GN3827@cbox>

On Mon, May 16, 2016 at 10:53:32AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
> and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
> access VGIC registers.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v3 .. v4:
> - check for proper alignment on userland GIC accesses
> 
>  virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
>  virt/kvm/arm/vgic/vgic-mmio-v2.c    | 38 ++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h            |  1 +
>  3 files changed, 90 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index a709097..78621283 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -226,6 +226,21 @@ void kvm_register_vgic_device(unsigned long type)
>  	}
>  }
>  
> +/** vgic_attr_regs_access: allows user space to read/write VGIC registers
> + *
> + * @dev: kvm device handle
> + * @attr: kvm device attribute
> + * @reg: address the value is read or written
> + * @is_write: write flag
> + *
> + */
> +static int vgic_attr_regs_access(struct kvm_device *dev,
> +				 struct kvm_device_attr *attr,
> +				 u32 *reg, bool is_write)
> +{
> +	return -ENXIO;
> +}
> +
>  /* V2 ops */
>  
>  static int vgic_v2_set_attr(struct kvm_device *dev,
> @@ -234,8 +249,23 @@ static int vgic_v2_set_attr(struct kvm_device *dev,
>  	int ret;
>  
>  	ret = vgic_set_common_attr(dev, attr);
> -	return ret;
> +	if (ret != -ENXIO)
> +		return ret;
> +
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
> +		u32 reg;
> +
> +		if (get_user(reg, uaddr))
> +			return -EFAULT;
>  
> +		return vgic_attr_regs_access(dev, attr, &reg, true);
> +	}
> +	}
> +
> +	return -ENXIO;
>  }
>  
>  static int vgic_v2_get_attr(struct kvm_device *dev,
> @@ -244,7 +274,23 @@ static int vgic_v2_get_attr(struct kvm_device *dev,
>  	int ret;
>  
>  	ret = vgic_get_common_attr(dev, attr);
> -	return ret;
> +	if (ret != -ENXIO)
> +		return ret;
> +
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
> +		u32 reg = 0;
> +
> +		ret = vgic_attr_regs_access(dev, attr, &reg, false);
> +		if (ret)
> +			return ret;
> +		return put_user(reg, uaddr);
> +	}
> +	}
> +
> +	return -ENXIO;
>  }
>  
>  static int vgic_v2_has_attr(struct kvm_device *dev,
> @@ -258,6 +304,9 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
>  			return 0;
>  		}
>  		break;
> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> +		return vgic_v2_has_attr_regs(dev, attr);
>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
>  		return 0;
>  	case KVM_DEV_ARM_VGIC_GRP_CTRL:
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> index 3925d4c..7189690 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
> @@ -258,3 +258,41 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
>  
>  	return SZ_4K;
>  }
> +
> +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
> +{
> +	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
> +	const struct vgic_register_region *regions;
> +	gpa_t addr;
> +	int nr_regions, i, len;
> +
> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
> +
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> +		regions = vgic_v2_dist_registers;
> +		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
> +		break;
> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> +		return -ENXIO;		/* TODO: describe CPU i/f regs also */
> +	default:
> +		return -ENXIO;
> +	}
> +
> +	/* We only support aligned 32-bit accesses. */
> +	if (addr & 3)
> +		return -ENXIO;
> +
> +	for (i = 0; i < nr_regions; i++) {
> +		if (regions[i].bits_per_irq)
> +			len = (regions[i].bits_per_irq * nr_irqs) / 8;
> +		else
> +			len = regions[i].len;
> +
> +		if (regions[i].reg_offset <= addr &&
> +		    regions[i].reg_offset + len > addr)
> +			return 0;
> +	}
> +
> +	return -ENXIO;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 6abc9a3..a264c5f 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -37,6 +37,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
>  void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
>  void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
>  void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
> +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
>  int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>  			     enum vgic_type);
>  
> -- 
> 2.8.2
> 

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 06:57:24 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 15:57:24 +0200
Subject: [PATCH v4 46/56] KVM: arm/arm64: vgic-new: Add userland access
 to VGIC dist registers
In-Reply-To: <1463392481-26583-47-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-47-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518135724.GO3827@cbox>

On Mon, May 16, 2016 at 10:53:34AM +0100, Andre Przywara wrote:
> Userland may want to save and restore the state of the in-kernel VGIC,
> so we provide the code which takes a userland request and translate
> that into calls to our MMIO framework.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-kvm-device.c | 50 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 49 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index 78621283..c3ec453 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -238,7 +238,55 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
>  				 struct kvm_device_attr *attr,
>  				 u32 *reg, bool is_write)
>  {
> -	return -ENXIO;
> +	gpa_t addr;
> +	int cpuid, ret, c;
> +	struct kvm_vcpu *vcpu, *tmp_vcpu;
> +
> +	cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
> +		 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
> +	vcpu = kvm_get_vcpu(dev->kvm, cpuid);
> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
> +
> +	mutex_lock(&dev->kvm->lock);
> +
> +	ret = vgic_init(dev->kvm);
> +	if (ret)
> +		goto out;
> +
> +	if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	/*
> +	 * Ensure that no other VCPU is running by checking the vcpu->cpu
> +	 * field.  If no other VPCUs are running we can safely access the VGIC
> +	 * state, because even if another VPU is run after this point, that
> +	 * VCPU will not touch the vgic state, because it will block on
> +	 * getting the vgic->lock in kvm_vgic_sync_hwstate().
> +	 */

We still have a problem here.  Want me to write a patch?

-Christoffer

> +	kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm) {
> +		if (unlikely(tmp_vcpu->cpu != -1)) {
> +			ret = -EBUSY;
> +			goto out;
> +		}
> +	}
> +
> +	switch (attr->group) {
> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
> +		ret = -EINVAL;
> +		break;
> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> +		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +out:
> +	mutex_unlock(&dev->kvm->lock);
> +	return ret;
>  }
>  
>  /* V2 ops */
> -- 
> 2.8.2
> 


From christoffer.dall at linaro.org  Wed May 18 06:59:09 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 15:59:09 +0200
Subject: [PATCH v4 47/56] KVM: arm/arm64: vgic-new: Add GICH_VMCR accessors
In-Reply-To: <1463392481-26583-48-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-48-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518135909.GP3827@cbox>

On Mon, May 16, 2016 at 10:53:35AM +0100, Andre Przywara wrote:
> Since the GIC CPU interface is always virtualized by the hardware,
> we don't have CPU interface state information readily available in our
> emulation if userland wants to save or restore it.
> Fortunately the GIC hypervisor interface provides the VMCR register to
> access the required virtual CPU interface bits.
> Provide wrappers for GICv2 and GICv3 hosts to have access to this
> register.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v2 .. v3:
> - remove exported v2/v3 selector functions (as per Marc's patch)
> 
> Changelog v3 .. v4:
> - move struct vgic_vmcr into the VGIC's private header file
> 
>  virt/kvm/arm/vgic/vgic-v2.c | 29 +++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c | 22 ++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h    | 21 +++++++++++++++++++++
>  3 files changed, 72 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> index fb5e65c..d943059 100644
> --- a/virt/kvm/arm/vgic/vgic-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -174,3 +174,32 @@ void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
>  {
>  	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
>  }
> +
> +void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
> +{
> +	u32 vmcr;
> +
> +	vmcr  = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK;
> +	vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) &
> +		GICH_VMCR_ALIAS_BINPOINT_MASK;
> +	vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) &
> +		GICH_VMCR_BINPOINT_MASK;
> +	vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) &
> +		GICH_VMCR_PRIMASK_MASK;
> +
> +	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = vmcr;
> +}
> +
> +void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
> +{
> +	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr;
> +
> +	vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >>
> +			GICH_VMCR_CTRL_SHIFT;
> +	vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >>
> +			GICH_VMCR_ALIAS_BINPOINT_SHIFT;
> +	vmcrp->bpr  = (vmcr & GICH_VMCR_BINPOINT_MASK) >>
> +			GICH_VMCR_BINPOINT_SHIFT;
> +	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
> +			GICH_VMCR_PRIMASK_SHIFT;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index fb547da..8548297 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -160,3 +160,25 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
>  {
>  	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
>  }
> +
> +void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
> +{
> +	u32 vmcr;
> +
> +	vmcr  = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK;
> +	vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
> +	vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
> +	vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
> +
> +	vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
> +}
> +
> +void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
> +{
> +	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
> +
> +	vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT;
> +	vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
> +	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
> +	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index f826026..d2c1fd5 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -27,6 +27,13 @@
>  
>  #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
>  
> +struct vgic_vmcr {
> +	u32	ctlr;
> +	u32	abpr;
> +	u32	bpr;
> +	u32	pmr;
> +};
> +
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid);
>  bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
> @@ -40,6 +47,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
>  int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
>  int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  			 int offset, u32 *val);
> +void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>  			     enum vgic_type);
>  
> @@ -49,6 +58,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
>  void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
>  void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
> +void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
>  #else
>  static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> @@ -72,6 +83,16 @@ static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>  {
>  }
>  
> +static inline
> +void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> +{
> +}
> +
> +static inline
> +void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
> +{
> +}
> +
>  static inline int vgic_register_redist_iodevs(struct kvm *kvm,
>  					      gpa_t dist_base_address)
>  {
> -- 
> 2.8.2
> 

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 07:02:24 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:02:24 +0200
Subject: [PATCH v4 48/56] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <1463392481-26583-49-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-49-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518140224.GQ3827@cbox>

On Mon, May 16, 2016 at 10:53:36AM +0100, Andre Przywara wrote:
> Using the VMCR accessors we provide access to GIC CPU interface state
> to userland by wiring it up to the existing userland interface.
> [Marc: move and make VMCR accessors static, streamline MMIO handlers]
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From maxime.ripard at free-electrons.com  Wed May 18 07:02:00 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 18 May 2016 16:02:00 +0200
Subject: [PATCH 15/16] clk: sunxi-ng: Add H3 clocks
In-Reply-To: <20160513114559.786221e415ce5956e161dd5b@free.fr>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
 <20160513114559.786221e415ce5956e161dd5b@free.fr>
Message-ID: <20160518140200.GN27618@lukather>

Hi Jean-Francois,

On Fri, May 13, 2016 at 11:45:59AM +0200, Jean-Francois Moine wrote:
> On Sun,  8 May 2016 22:01:50 +0200
> Maxime Ripard <maxime.ripard at free-electrons.com> wrote:
> 
> > Add the list of clocks and resets found in the H3 CCU.
> 
> Hi Maxime,
> 
> Nice job. I like this new way for defining the sunxi clocks.
> But it does not yet fully work for the H3 (apart the other already
> signalled errors). See below.

I'm glad you like it, it should make everyone's life easier.

And I was kind of expecting you'd uncover a bunch of bugs testing that
with the HDMI audio patches you have.

> 
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/clk/sunxi-ng/Makefile        |   2 +
> >  drivers/clk/sunxi-ng/ccu-sun8i-h3.c  | 757 +++++++++++++++++++++++++++++++++++
> >  include/dt-bindings/clock/sun8i-h3.h | 162 ++++++++
> >  include/dt-bindings/reset/sun8i-h3.h | 103 +++++
> >  4 files changed, 1024 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> >  create mode 100644 include/dt-bindings/clock/sun8i-h3.h
> >  create mode 100644 include/dt-bindings/reset/sun8i-h3.h
> > 
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> > index c794f57b6fb1..67ff6a92f124 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -13,3 +13,5 @@ obj-y += ccu_nkmp.o
> >  obj-y += ccu_nm.o
> >  obj-y += ccu_p.o
> >  obj-y += ccu_phase.o
> > +
> > +obj-y += ccu-sun8i-h3.o
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> > new file mode 100644
> > index 000000000000..5ce699e95c32
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> > @@ -0,0 +1,757 @@
> 	[snip]
> > +static struct ccu_nkmp pll_cpux_clk = {
> > +	.enable		= BIT(31),
> > +	.lock		= BIT(28),
> > +
> > +	.m		= SUNXI_CLK_FACTOR(0, 2),
> > +	.k		= SUNXI_CLK_FACTOR(4, 2),
> > +	.n		= SUNXI_CLK_FACTOR(8, 5),
> > +	.p		= SUNXI_CLK_FACTOR(16, 2),
> > +
> > +	.common		= {
> > +		.reg		= 0x000,
> > +		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> 
> It seems to me that these flags are redondant with the .enable
> and .lock fields (always != 0 when used).

Yes, kind of, but not exactly. The features flags describe in a
generic manner what the clock can and cannot do, while the fields
themselves are per-structure.

This will allow the core if we ever need it to probe what each clock
implements. And since we are using it for other features that can be
shared by multiple clock classes (muxes, post-div, pre-div and so on),
I think it would be best to keep it consitent and use it here.

But I agree that it's not really a strong argument.

> 
> > +		.hw.init	= SUNXI_HW_INIT("pll-cpux",
> > +						"osc24M",
> > +						&ccu_nkmp_ops,
> > +						0),
> > +	},
> > +};
> 
> The 'p' factor must be used only for very low rates (< 288MHz).
> I think that it should be ignored.

Yeah, I noticed it as well during the development. I just re-used the
current behaviour of the A23 PLL1 that uses P as well. I was not
really willing to change any behaviour here at first, this patch set
is already quite intrusive.

But we can definitely change that later.

> > +
> > +static struct ccu_nm pll_audio_base_clk = {
> > +	.enable		= BIT(31),
> > +	.lock		= BIT(28),
> > +
> > +	.m		= SUNXI_CLK_FACTOR(0, 5),
> > +	.n		= SUNXI_CLK_FACTOR(8, 7),
> > +
> > +	.common		= {
> > +		.reg		= 0x008,
> > +		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> > +		.hw.init	= SUNXI_HW_INIT("pll-audio-base",
> > +						"osc24M",
> > +						&ccu_nm_ops,
> > +						0),
> > +	},
> > +};
> > +
> > +static SUNXI_CCU_M(pll_audio_clk, "pll-audio", "pll-audio-base",
> > +		   0x008, 16, 4, 0);
> > +
> > +static SUNXI_CCU_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
> > +			      "pll-audio-base", 2, 1, 0);
> > +static SUNXI_CCU_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
> > +			      "pll-audio-base", 1, 1, 0);
> > +static SUNXI_CCU_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
> > +			      "pll-audio-base", 1, 2, 0);
> 
> Forcing the post divider 'p' to 4 would simplify this PLL.

Yes and no. It would simplify the clock rate computation and
propagation across the tree, but it would also add more code in there,
and we would not be able to read the clock rate properly.

Chaining clocks like that should also be supported and working, so I'd
still be very much in favour of implementing it as it is supposed to
be, and fixing whatever bug there might be in there.

> > +static struct ccu_nm pll_video_clk = {
> > +	.enable		= BIT(31),
> > +	.lock		= BIT(28),
> > +
> > +	.m		= SUNXI_CLK_FACTOR(0, 4),
> > +	.n		= SUNXI_CLK_FACTOR(8, 7),
> > +
> > +	.common		= {
> > +		.reg		= 0x010,
> > +		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> > +		.hw.init	= SUNXI_HW_INIT("pll-video",
> > +						"osc24M",
> > +						&ccu_nm_ops,
> > +						0),
> > +	},
> > +};
> 
> The legacy u-boot I use (lichee) forces this PLL to 297MHz in
> fractional mode (FRAC_CLK_OUT = 1 and PLL_MODE_SEL = 0).
> As these bits are not managed, getting the rate is false and setting it
> is not possible.

Ah, interesting.

I'll add support for fractional clocks in the next version then.

Just out of curiosity, is there any particular reason for sticking
with Allwinner's U-Boot over using mainline U-Boot?

> > +static struct ccu_nk pll_periph0_clk = {
> > +	.enable		= BIT(31),
> > +	.lock		= BIT(28),
> > +
> > +	.k		= SUNXI_CLK_FACTOR(4, 2),
> > +	.n		= SUNXI_CLK_FACTOR(8, 5),
> > +	.fixed_post_div	= 2,
> > +
> > +	.common		= {
> > +		.reg		= 0x028,
> > +		.features	= (CCU_FEATURE_GATE |
> > +				   CCU_FEATURE_LOCK |
> > +				   CCU_FEATURE_FIXED_POSTDIV),
> > +		.hw.init	= SUNXI_HW_INIT("pll-periph0",
> > +						"osc24M",
> > +						&ccu_nk_ops,
> > +						0),
> > +	},
> > +};
> 
> As told previously, the H3 documentation says:
> 
>  Note: The PLL Output should be fixed to 600MHz, it is not recommended to
>  vary this value arbitrarily.
> 
> So, is it useful to offer the possibility to change the rate of this PLL
> (and same for pll-periph1)?
> (I force the rate in the DT with assigned-clock-rates to avoid any problem)

assigned-clock-rates will not change anything unfortunately. It sets a
default rate at boot time, but it doesn't prevent the rate from being
changed.

Fortunately, that rate will never be modified, since none of the child
clock have CLK_SET_RATE_PARENT.

If that was to change, and when that time comes, we can always use the
clk boundaries to deal with it nicely.

> > +
> > +static SUNXI_CCU_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
> > +			      "pll-periph0", 1, 2, 0);
> > +
> 	[snip]
> > +static const char * const nand_parents[] = { "osc24M", "pll-periph0",
> > +					     "pll-periph1" };
> > +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", nand_parents, 0x080,
> > +				  0, 4,		/* M */
> > +				  16, 2,	/* P */
> > +				  24, 2,	/* mux */
> > +				  BIT(31),	/* gate */
> > +				  0);
> 
> The mux width is 2, meaning there may be 4 parents. Then, there may be
> an access out of the parent array (and same for mmcx and spix).

The mux relies on the number of parents registered in the clock
framework, which is 3 in this case, so that won't happen.

Or am I missing what you're saying?

> > +
> > +static const char * const mmc0_parents[] = { "osc24M", "pll-periph0",
> > +					     "pll-periph1" };
> 
> The parent tables of nand, mmcx and spix are the same. One table should
> be enough.

Ack.

> > +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_parents, 0x088,
> > +				  0, 4,		/* M */
> > +				  16, 2,	/* P */
> > +				  24, 2,	/* mux */
> > +				  BIT(31),	/* gate */
> > +				  0);
> > +
> > +static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0",
> > +		       0x088, 20, 3, 0);
> > +static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0",
> > +		       0x088, 8, 3, 0);
> 	[snip]
> > +static const char * const i2s0_parents[] = { "pll-audio-8x", "pll-audio-4x",
> > +					     "pll-audio-2x" , "pll-audio" };
> > +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s0_parents,
> > +			       0x0b0, 16, 2, BIT(31), 0);
> > +
> > +static const char * const i2s1_parents[] = { "pll-audio-8x", "pll-audio-4x",
> > +					     "pll-audio-2x" , "pll-audio" };
> > +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s1_parents,
> > +			       0x0b4, 16, 2, BIT(31), 0);
> > +
> > +static const char * const i2s2_parents[] = { "pll-audio-8x", "pll-audio-4x",
> > +					     "pll-audio-2x" , "pll-audio" };
> > +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s2_parents,
> > +			       0x0b8, 16, 2, BIT(31), 0);
> 	[snip]
> 
> Same parent tables.
> This occurs for other clocks.

Ack.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160518/dec7f73c/attachment-0001.sig>

From alexander.stein at systec-electronic.com  Wed May 18 07:02:03 2016
From: alexander.stein at systec-electronic.com (Alexander Stein)
Date: Wed, 18 May 2016 16:02:03 +0200
Subject: [PATCH 1/1] arm: dts: ls1021a: Fix dspi chip select amount
Message-ID: <1463580123-16713-1-git-send-email-alexander.stein@systec-electronic.com>

The DSPI periphery has 6 chip selects.

Signed-off-by: Alexander Stein <alexander.stein at systec-electronic.com>
---
 arch/arm/boot/dts/ls1021a.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index 726372d..1406e98 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -245,7 +245,7 @@
 			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "dspi";
 			clocks = <&platform_clk 1>;
-			spi-num-chipselects = <5>;
+			spi-num-chipselects = <6>;
 			big-endian;
 			status = "disabled";
 		};
@@ -258,7 +258,7 @@
 			interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "dspi";
 			clocks = <&platform_clk 1>;
-			spi-num-chipselects = <5>;
+			spi-num-chipselects = <6>;
 			big-endian;
 			status = "disabled";
 		};
-- 
2.7.3



From andre.przywara at arm.com  Wed May 18 07:06:10 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 18 May 2016 15:06:10 +0100
Subject: [PATCH v4 46/56] KVM: arm/arm64: vgic-new: Add userland access to
 VGIC dist registers
In-Reply-To: <20160518135724.GO3827@cbox>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-47-git-send-email-andre.przywara@arm.com>
 <20160518135724.GO3827@cbox>
Message-ID: <573C76D2.3050906@arm.com>

Hi,

On 18/05/16 14:57, Christoffer Dall wrote:
> On Mon, May 16, 2016 at 10:53:34AM +0100, Andre Przywara wrote:
>> Userland may want to save and restore the state of the in-kernel VGIC,
>> so we provide the code which takes a userland request and translate
>> that into calls to our MMIO framework.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> ---
>>  virt/kvm/arm/vgic/vgic-kvm-device.c | 50 ++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 49 insertions(+), 1 deletion(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> index 78621283..c3ec453 100644
>> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
>> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
>> @@ -238,7 +238,55 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
>>  				 struct kvm_device_attr *attr,
>>  				 u32 *reg, bool is_write)
>>  {
>> -	return -ENXIO;
>> +	gpa_t addr;
>> +	int cpuid, ret, c;
>> +	struct kvm_vcpu *vcpu, *tmp_vcpu;
>> +
>> +	cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
>> +		 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
>> +	vcpu = kvm_get_vcpu(dev->kvm, cpuid);
>> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
>> +
>> +	mutex_lock(&dev->kvm->lock);
>> +
>> +	ret = vgic_init(dev->kvm);
>> +	if (ret)
>> +		goto out;
>> +
>> +	if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
>> +		ret = -EINVAL;
>> +		goto out;
>> +	}
>> +
>> +	/*
>> +	 * Ensure that no other VCPU is running by checking the vcpu->cpu
>> +	 * field.  If no other VPCUs are running we can safely access the VGIC
>> +	 * state, because even if another VPU is run after this point, that
>> +	 * VCPU will not touch the vgic state, because it will block on
>> +	 * getting the vgic->lock in kvm_vgic_sync_hwstate().
>> +	 */
> 
> We still have a problem here.  Want me to write a patch?

Aargh, this somehow got lost in my pile of "comments to address", sorry!
Short answer: yes, please.
Last thing I did was following your suggestion from last time about
refactoring the check from kvm_vgic_create(): I think this doesn't help,
because it's only a check and we return -EBUSY or so instead of actually
enforcing VCPUs to exit. So if you could try to use your fancy new
make-the-guest-exit feature here?

Cheers,
Andre.

> -Christoffer
> 
>> +	kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm) {
>> +		if (unlikely(tmp_vcpu->cpu != -1)) {
>> +			ret = -EBUSY;
>> +			goto out;
>> +		}
>> +	}
>> +
>> +	switch (attr->group) {
>> +	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
>> +		ret = -EINVAL;
>> +		break;
>> +	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
>> +		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
>> +		break;
>> +	default:
>> +		ret = -EINVAL;
>> +		break;
>> +	}
>> +
>> +out:
>> +	mutex_unlock(&dev->kvm->lock);
>> +	return ret;
>>  }
>>  
>>  /* V2 ops */
>> -- 
>> 2.8.2
>>
> 


From christoffer.dall at linaro.org  Wed May 18 07:08:39 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:08:39 +0200
Subject: [PATCH v4 49/56] KVM: arm/arm64: vgic-new: vgic_init: implement
 kvm_vgic_hyp_init
In-Reply-To: <1463392481-26583-50-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-50-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518140839.GR3827@cbox>

On Mon, May 16, 2016 at 10:53:37AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> Implements kvm_vgic_hyp_init and vgic_probe function.
> This uses the new firmware independent VGIC probing to support both ACPI
> and DT based systems (code from Marc Zyngier).
> 
> The vgic_global struct is enriched with new fields populated
> by those functions.
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v1 .. v2:
> - rename vgic_init.c to vgic-init.c
> 
> Changelog v2 .. v3:
> - include kvm/arm_vgic.h instead of kvm/vgic/vgic.h
> - move ich_vtr_el2 variable into probe function
> 
> Changelog v3 .. v4:
> - improve nr_lr determination in GICv2 probe
> - switching to firmware-independent probing
> 
>  include/kvm/vgic/vgic.h       |   1 +
>  virt/kvm/arm/vgic/vgic-init.c | 123 ++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v2.c   |  64 ++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c   |  49 +++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h      |   9 ++++
>  5 files changed, 246 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-init.c
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 3689b9b..393489f 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -195,6 +195,7 @@ struct vgic_cpu {
>  };
>  
>  int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
> +int kvm_vgic_hyp_init(void);
>  
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  			bool level);
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> new file mode 100644
> index 0000000..4523beb
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -0,0 +1,123 @@
> +/*
> + * Copyright (C) 2015, 2016 ARM 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.
> + *
> + * 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.
> + *
> + * 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/uaccess.h>
> +#include <linux/interrupt.h>
> +#include <linux/cpu.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/arm_vgic.h>
> +#include <asm/kvm_mmu.h>
> +#include "vgic.h"
> +
> +/* GENERIC PROBE */
> +
> +static void vgic_init_maintenance_interrupt(void *info)
> +{
> +	enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0);
> +}
> +
> +static int vgic_cpu_notify(struct notifier_block *self,
> +			   unsigned long action, void *cpu)
> +{
> +	switch (action) {
> +	case CPU_STARTING:
> +	case CPU_STARTING_FROZEN:
> +		vgic_init_maintenance_interrupt(NULL);
> +		break;
> +	case CPU_DYING:
> +	case CPU_DYING_FROZEN:
> +		disable_percpu_irq(kvm_vgic_global_state.maint_irq);
> +		break;
> +	}
> +
> +	return NOTIFY_OK;
> +}
> +
> +static struct notifier_block vgic_cpu_nb = {
> +	.notifier_call = vgic_cpu_notify,
> +};
> +
> +static irqreturn_t vgic_maintenance_handler(int irq, void *data)
> +{
> +	/*
> +	 * We cannot rely on the vgic maintenance interrupt to be
> +	 * delivered synchronously. This means we can only use it to
> +	 * exit the VM, and we perform the handling of EOIed
> +	 * interrupts on the exit path (see vgic_process_maintenance).
> +	 */
> +	return IRQ_HANDLED;
> +}
> +
> +/**
> + * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable
> + * according to the host GIC model. Accordingly calls either
> + * vgic_v2/v3_probe which registers the KVM_DEVICE that can be
> + * instantiated by a guest later on .
> + */
> +int kvm_vgic_hyp_init(void)
> +{
> +	const struct gic_kvm_info *gic_kvm_info;
> +	int ret;
> +
> +	gic_kvm_info = gic_get_kvm_info();
> +	if (!gic_kvm_info)
> +		return -ENODEV;
> +
> +	if (!gic_kvm_info->maint_irq) {
> +		kvm_err("No vgic maintenance irq\n");
> +		return -ENXIO;
> +	}
> +
> +	switch (gic_kvm_info->type) {
> +	case GIC_V2:
> +		ret = vgic_v2_probe(gic_kvm_info);
> +		break;
> +	case GIC_V3:
> +		ret = vgic_v3_probe(gic_kvm_info);
> +		break;
> +	default:
> +		ret = -ENODEV;
> +	};
> +
> +	if (ret)
> +		return ret;
> +
> +	kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
> +	ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
> +				 vgic_maintenance_handler,
> +				 "vgic", kvm_get_running_vcpus());
> +	if (ret) {
> +		kvm_err("Cannot register interrupt %d\n",
> +			kvm_vgic_global_state.maint_irq);
> +		return ret;
> +	}
> +
> +	ret = __register_cpu_notifier(&vgic_cpu_nb);
> +	if (ret) {
> +		kvm_err("Cannot register vgic CPU notifier\n");
> +		goto out_free_irq;
> +	}
> +
> +	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
> +
> +	kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq);
> +	return 0;
> +
> +out_free_irq:
> +	free_percpu_irq(kvm_vgic_global_state.maint_irq,
> +			kvm_get_running_vcpus());
> +	return ret;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> index d943059..09777c8 100644
> --- a/virt/kvm/arm/vgic/vgic-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -17,6 +17,8 @@
>  #include <linux/irqchip/arm-gic.h>
>  #include <linux/kvm.h>
>  #include <linux/kvm_host.h>
> +#include <kvm/arm_vgic.h>
> +#include <asm/kvm_mmu.h>
>  
>  #include "vgic.h"
>  
> @@ -203,3 +205,65 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>  	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
>  			GICH_VMCR_PRIMASK_SHIFT;
>  }
> +
> +/**
> + * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
> + * @node:	pointer to the DT node
> + *
> + * Returns 0 if a GICv2 has been found, returns an error code otherwise
> + */
> +int vgic_v2_probe(const struct gic_kvm_info *info)
> +{
> +	int ret;
> +	u32 vtr;
> +
> +	if (!info->vctrl.start) {
> +		kvm_err("GICH not present in the firmware table\n");
> +		return -ENXIO;
> +	}
> +
> +	if (!PAGE_ALIGNED(info->vcpu.start)) {
> +		kvm_err("GICV physical address 0x%llx not page aligned\n",
> +			(unsigned long long)info->vcpu.start);
> +		return -ENXIO;
> +	}
> +
> +	if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
> +		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
> +			(unsigned long long)resource_size(&info->vcpu),
> +			PAGE_SIZE);
> +		return -ENXIO;
> +	}
> +
> +	kvm_vgic_global_state.vctrl_base = ioremap(info->vctrl.start,
> +						   resource_size(&info->vctrl));
> +	if (!kvm_vgic_global_state.vctrl_base) {
> +		kvm_err("Cannot ioremap GICH\n");
> +		return -ENOMEM;
> +	}
> +
> +	vtr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
> +	kvm_vgic_global_state.nr_lr = (vtr & 0x3f) + 1;
> +
> +	ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
> +				     kvm_vgic_global_state.vctrl_base +
> +					 resource_size(&info->vctrl),
> +				     info->vctrl.start);
> +
> +	if (ret) {
> +		kvm_err("Cannot map VCTRL into hyp\n");
> +		iounmap(kvm_vgic_global_state.vctrl_base);
> +		return ret;
> +	}
> +
> +	kvm_vgic_global_state.can_emulate_gicv2 = true;
> +	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
> +
> +	kvm_vgic_global_state.vcpu_base = info->vcpu.start;
> +	kvm_vgic_global_state.type = VGIC_V2;
> +	kvm_vgic_global_state.max_gic_vcpus = VGIC_V2_MAX_CPUS;
> +
> +	kvm_info("vgic-v2@%llx\n", info->vctrl.start);
> +
> +	return 0;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 8548297..de0e8e0 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -15,6 +15,9 @@
>  #include <linux/irqchip/arm-gic-v3.h>
>  #include <linux/kvm.h>
>  #include <linux/kvm_host.h>
> +#include <kvm/arm_vgic.h>
> +#include <asm/kvm_mmu.h>
> +#include <asm/kvm_asm.h>
>  
>  #include "vgic.h"
>  
> @@ -182,3 +185,49 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
>  	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
>  	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
>  }
> +
> +/**
> + * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
> + * @node:	pointer to the DT node
> + *
> + * Returns 0 if a GICv3 has been found, returns an error code otherwise
> + */
> +int vgic_v3_probe(const struct gic_kvm_info *info)
> +{
> +	u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
> +
> +	/*
> +	 * The ListRegs field is 5 bits, but there is a architectural
> +	 * maximum of 16 list registers. Just ignore bit 4...
> +	 */
> +	kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
> +	kvm_vgic_global_state.can_emulate_gicv2 = false;
> +
> +	if (!info->vcpu.start) {
> +		kvm_info("GICv3: no GICV resource entry\n");
> +		kvm_vgic_global_state.vcpu_base = 0;
> +	} else if (!PAGE_ALIGNED(info->vcpu.start)) {
> +		pr_warn("GICV physical address 0x%llx not page aligned\n",
> +			(unsigned long long)info->vcpu.start);
> +		kvm_vgic_global_state.vcpu_base = 0;
> +	} else if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
> +		pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
> +			(unsigned long long)resource_size(&info->vcpu),
> +			PAGE_SIZE);
> +		kvm_vgic_global_state.vcpu_base = 0;
> +	} else {
> +		kvm_vgic_global_state.vcpu_base = info->vcpu.start;
> +		kvm_vgic_global_state.can_emulate_gicv2 = true;
> +		kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
> +		kvm_info("vgic-v2@%llx\n", info->vcpu.start);
> +	}
> +	if (kvm_vgic_global_state.vcpu_base == 0)
> +		kvm_info("disabling GICv2 emulation\n");
> +	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V3);
> +
> +	kvm_vgic_global_state.vctrl_base = NULL;
> +	kvm_vgic_global_state.type = VGIC_V3;
> +	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
> +
> +	return 0;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index de9dc71..f4244b6 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -16,6 +16,8 @@
>  #ifndef __KVM_ARM_VGIC_NEW_H__
>  #define __KVM_ARM_VGIC_NEW_H__
>  
> +#include <linux/irqchip/arm-gic-common.h>
> +
>  #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
>  #define IMPLEMENTER_ARM		0x43b
>  
> @@ -51,6 +53,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
>  			  int offset, u32 *val);
>  void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +int vgic_v2_probe(const struct gic_kvm_info *info);
>  int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
>  			     enum vgic_type);
>  
> @@ -62,6 +65,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
>  void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
>  void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> +int vgic_v3_probe(const struct gic_kvm_info *info);
>  int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
>  #else
>  static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> @@ -95,6 +99,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
>  {
>  }
>  
> +static inline int vgic_v3_probe(const struct gic_kvm_info *info)
> +{
> +	return -ENODEV;
> +}
> +
>  static inline int vgic_register_redist_iodevs(struct kvm *kvm,
>  					      gpa_t dist_base_address)
>  {
> -- 
> 2.8.2
> 

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 07:11:44 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:11:44 +0200
Subject: [PATCH v4 50/56] KVM: arm/arm64: vgic-new: vgic_init: implement
 vgic_create
In-Reply-To: <1463392481-26583-51-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-51-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518141144.GS3827@cbox>

On Mon, May 16, 2016 at 10:53:38AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
> 
> This patch implements the vgic_creation function which is
> called on CREATE_IRQCHIP VM IOCTL (v2 only) or KVM_CREATE_DEVICE
> 
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog v3 .. v4:
> - fix comment
> 
>  include/kvm/vgic/vgic.h       |  1 +
>  virt/kvm/arm/vgic/vgic-init.c | 84 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 85 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 393489f..0634d89 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -195,6 +195,7 @@ struct vgic_cpu {
>  };
>  
>  int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
> +int kvm_vgic_create(struct kvm *kvm, u32 type);
>  int kvm_vgic_hyp_init(void);
>  
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> index 4523beb..15d5428 100644
> --- a/virt/kvm/arm/vgic/vgic-init.c
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -22,6 +22,90 @@
>  #include <asm/kvm_mmu.h>
>  #include "vgic.h"
>  
> +/* CREATION */
> +
> +/**
> + * kvm_vgic_create: triggered by the instantiation of the VGIC device by
> + * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only)
> + * or through the generic KVM_CREATE_DEVICE API ioctl.
> + * irqchip_in_kernel() tells you if this function succeeded or not.
> + */
> +int kvm_vgic_create(struct kvm *kvm, u32 type)
> +{
> +	int i, vcpu_lock_idx = -1, ret;
> +	struct kvm_vcpu *vcpu;
> +
> +	mutex_lock(&kvm->lock);
> +
> +	if (irqchip_in_kernel(kvm)) {
> +		ret = -EEXIST;
> +		goto out;
> +	}
> +
> +	/*
> +	 * This function is also called by the KVM_CREATE_IRQCHIP handler,
> +	 * which had no chance yet to check the availability of the GICv2
> +	 * emulation. So check this here again. KVM_CREATE_DEVICE does
> +	 * the proper checks already.
> +	 */
> +	if (type == KVM_DEV_TYPE_ARM_VGIC_V2 &&
> +		!kvm_vgic_global_state.can_emulate_gicv2) {
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	/*
> +	 * Any time a vcpu is run, vcpu_load is called which tries to grab the
> +	 * vcpu->mutex.  By grabbing the vcpu->mutex of all VCPUs we ensure
> +	 * that no other VCPUs are run while we create the vgic.
> +	 */
> +	ret = -EBUSY;
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		if (!mutex_trylock(&vcpu->mutex))
> +			goto out_unlock;
> +		vcpu_lock_idx = i;
> +	}
> +
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		if (vcpu->arch.has_run_once)
> +			goto out_unlock;
> +	}
> +	ret = 0;
> +
> +	if (type == KVM_DEV_TYPE_ARM_VGIC_V2)
> +		kvm->arch.max_vcpus = VGIC_V2_MAX_CPUS;
> +	else
> +		kvm->arch.max_vcpus = VGIC_V3_MAX_CPUS;
> +
> +	if (atomic_read(&kvm->online_vcpus) > kvm->arch.max_vcpus) {
> +		ret = -E2BIG;
> +		goto out_unlock;
> +	}
> +
> +	kvm->arch.vgic.in_kernel = true;
> +	kvm->arch.vgic.vgic_model = type;
> +
> +	/*
> +	 * kvm_vgic_global_state.vctrl_base is set on vgic probe (kvm_arch_init)
> +	 * it is stored in distributor struct for asm save/restore purpose
> +	 */
> +	kvm->arch.vgic.vctrl_base = kvm_vgic_global_state.vctrl_base;

I had some bit about the S/R code not being assembly anymore, so we
should get rid of the 'asm' part of the comment, but if reworking this
to be global state is too messy at this point, I'm ok with leaving this
as a fix for later.

So, for the remaining part:

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>

> +
> +	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
> +	kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
> +	kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
> +
> +out_unlock:
> +	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
> +		vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
> +		mutex_unlock(&vcpu->mutex);
> +	}
> +
> +out:
> +	mutex_unlock(&kvm->lock);
> +	return ret;
> +}
> +
>  /* GENERIC PROBE */
>  
>  static void vgic_init_maintenance_interrupt(void *info)
> -- 
> 2.8.2
> 


From marc.zyngier at arm.com  Wed May 18 07:12:33 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 18 May 2016 15:12:33 +0100
Subject: [PATCH v4 22/56] KVM: arm/arm64: vgic-new: Add MMIO handling
 framework
In-Reply-To: <20160518122521.GD3827@cbox>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-23-git-send-email-andre.przywara@arm.com>
 <573B1DB0.7030901@arm.com> <20160518122521.GD3827@cbox>
Message-ID: <573C7851.4010401@arm.com>

On 18/05/16 13:25, Christoffer Dall wrote:
> On Tue, May 17, 2016 at 02:33:36PM +0100, Marc Zyngier wrote:
>> On 16/05/16 10:53, Andre Przywara wrote:
>>> From: Marc Zyngier <marc.zyngier at arm.com>
>>>
>>> Add an MMIO handling framework to the VGIC emulation:
>>> Each register is described by its offset, size (or number of bits per
>>> IRQ, if applicable) and the read/write handler functions. We provide
>>> initialization macros to describe each GIC register later easily.
>>>
>>> Separate dispatch functions for read and write accesses are connected
>>> to the kvm_io_bus framework and binary-search for the responsible
>>> register handler based on the offset address within the region.
>>> We convert the incoming data (referenced by a pointer) to the host's
>>> endianess and use pass-by-value to hand the data over to the actual
>>> handler functions.
>>>
>>> The register handler prototype and the endianess conversion are
>>> courtesy of Christoffer Dall.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> ---
>>> Changelog RFC..v1:
>>> - rework MMIO dispatching to use only one kvm_io_bus device
>>> - document purpose of register region macros
>>> - rename "this" parameter to "dev"
>>> - change IGROUPR to be RAO (returning 1 => Group1 IRQs)
>>>
>>> Changelog v1 .. v2:
>>> * MASSIVE rework:
>>> - store register_region pointer in kvm_io_bus linked struct
>>> - replace write_mask_xxx functions with extract_bytes() implementation
>>> - change handler functions' prototypes to take and return unsigned long
>>> - use binary search to find matching register handler
>>> - convert endianess of input data in dispatch_mmio_xxx functions
>>> - improve readability of register initializer macros
>>> - remove any GICv2/GICv3 specific functions from vgic-mmio.c
>>> - rename file from vgic_mmio.c to vgic-mmio.c
>>>
>>> Changelog v2 .. v3:
>>> - replace inclusion of vgic/vgic.h with arm_vgic.h
>>>
>>> Changelog v3 .. v4:
>>> - add IRQ number accessor macro
>>> - check access width in dispatcher
>>> - treat non-covered MMIO addresses as RAZ/WI
>>> - remove extract_bytes() (re-introduced as static later in the series)
>>>
>>>  include/kvm/vgic/vgic.h       |  13 +++
>>>  virt/kvm/arm/vgic/vgic-mmio.c | 184 ++++++++++++++++++++++++++++++++++++++++++
>>>  virt/kvm/arm/vgic/vgic-mmio.h |  87 ++++++++++++++++++++
>>>  3 files changed, 284 insertions(+)
>>>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
>>>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h
>>>
>>> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
>>> index f663288..ff3f9c2 100644
>>> --- a/include/kvm/vgic/vgic.h
>>> +++ b/include/kvm/vgic/vgic.h
>>> @@ -106,6 +106,16 @@ struct vgic_irq {
>>>  	enum vgic_irq_config config;	/* Level or edge */
>>>  };
>>>  
>>> +struct vgic_register_region;
>>> +
>>> +struct vgic_io_device {
>>> +	gpa_t base_addr;
>>> +	struct kvm_vcpu *redist_vcpu;
>>> +	const struct vgic_register_region *regions;
>>> +	int nr_regions;
>>> +	struct kvm_io_device dev;
>>> +};
>>> +
>>>  struct vgic_dist {
>>>  	bool			in_kernel;
>>>  	bool			ready;
>>> @@ -132,6 +142,9 @@ struct vgic_dist {
>>>  	bool			enabled;
>>>  
>>>  	struct vgic_irq		*spis;
>>> +
>>> +	struct vgic_io_device	dist_iodev;
>>> +	struct vgic_io_device	*redist_iodevs;
>>>  };
>>>  
>>>  struct vgic_v2_cpu_if {
>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
>>> new file mode 100644
>>> index 0000000..012b82b
>>> --- /dev/null
>>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>>> @@ -0,0 +1,184 @@
>>> +/*
>>> + * VGIC MMIO handling functions
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + */
>>> +
>>> +#include <linux/bitops.h>
>>> +#include <linux/bsearch.h>
>>> +#include <linux/kvm.h>
>>> +#include <linux/kvm_host.h>
>>> +#include <kvm/iodev.h>
>>> +#include <kvm/arm_vgic.h>
>>> +
>>> +#include "vgic.h"
>>> +#include "vgic-mmio.h"
>>> +
>>> +unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
>>> +				 gpa_t addr, unsigned int len)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>> +unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
>>> +				 gpa_t addr, unsigned int len)
>>> +{
>>> +	return -1UL;
>>> +}
>>> +
>>> +void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
>>> +			unsigned int len, unsigned long val)
>>> +{
>>> +	/* Ignore */
>>> +}
>>> +
>>> +static int match_region(const void *key, const void *elt)
>>> +{
>>> +	const unsigned int offset = (unsigned long)key;
>>> +	const struct vgic_register_region *region = elt;
>>> +
>>> +	if (offset < region->reg_offset)
>>> +		return -1;
>>> +
>>> +	if (offset >= region->reg_offset + region->len)
>>> +		return 1;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +/* Find the proper register handler entry given a certain address offset. */
>>> +static const struct vgic_register_region *
>>> +vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
>>> +		      unsigned int offset)
>>> +{
>>> +	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
>>> +		       sizeof(region[0]), match_region);
>>> +}
>>> +
>>> +/*
>>> + * kvm_mmio_read_buf() returns a value in a format where it can be converted
>>> + * to a byte array and be directly observed as the guest wanted it to appear
>>> + * in memory if it had done the store itself, which is LE for the GIC, as the
>>> + * guest knows the GIC is always LE.
>>> + *
>>> + * We convert this value to the CPUs native format to deal with it as a data
>>> + * value.
>>> + */
>>> +unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len)
>>> +{
>>> +	unsigned long data = kvm_mmio_read_buf(val, len);
>>> +
>>> +	switch (len) {
>>> +	case 1:
>>> +		return data;
>>> +	case 2:
>>> +		return le16_to_cpu(data);
>>> +	case 4:
>>> +		return le32_to_cpu(data);
>>> +	default:
>>> +		return le64_to_cpu(data);
>>> +	}
>>> +}
>>> +
>>> +/*
>>> + * kvm_mmio_write_buf() expects a value in a format such that if converted to
>>> + * a byte array it is observed as the guest would see it if it could perform
>>> + * the load directly.  Since the GIC is LE, and the guest knows this, the
>>> + * guest expects a value in little endian format.
>>> + *
>>> + * We convert the data value from the CPUs native format to LE so that the
>>> + * value is returned in the proper format.
>>> + */
>>> +void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
>>> +				unsigned long data)
>>> +{
>>> +	switch (len) {
>>> +	case 1:
>>> +		break;
>>> +	case 2:
>>> +		data = cpu_to_le16(data);
>>> +		break;
>>> +	case 4:
>>> +		data = cpu_to_le32(data);
>>> +		break;
>>> +	default:
>>> +		data = cpu_to_le64(data);
>>> +	}
>>> +
>>> +	kvm_mmio_write_buf(buf, len, data);
>>> +}
>>> +
>>> +static
>>> +struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
>>> +{
>>> +	return container_of(dev, struct vgic_io_device, dev);
>>> +}
>>> +
>>> +static bool check_region(const struct vgic_register_region *region,
>>> +			 gpa_t addr, int len)
>>> +{
>>> +	if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1)
>>> +		return true;
>>> +	if ((region->access_flags & VGIC_ACCESS_32bit) &&
>>> +	    len == sizeof(u32) && !(addr & 3))
>>> +		return true;
>>> +	if ((region->access_flags & VGIC_ACCESS_64bit) &&
>>> +	    len == sizeof(u64) && !(addr & 7))
>>> +		return true;
>>> +
>>> +	return false;
>>> +}
>>> +
>>> +static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
>>> +			      gpa_t addr, int len, void *val)
>>> +{
>>> +	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
>>> +	const struct vgic_register_region *region;
>>> +	struct kvm_vcpu *r_vcpu;
>>> +	unsigned long data;
>>> +
>>> +	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
>>> +				       addr - iodev->base_addr);
>>> +	if (!region || !check_region(region, addr, len)) {
>>> +		memset(val, 0, len);
>>> +		return 0;
>>> +	}
>>> +
>>> +	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
>>> +	data = region->read(r_vcpu, addr, len);
>>> +	vgic_data_host_to_mmio_bus(val, len, data);
>>> +	return 0;
>>> +}
>>> +
>>> +static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
>>> +			       gpa_t addr, int len, const void *val)
>>> +{
>>> +	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
>>> +	const struct vgic_register_region *region;
>>> +	struct kvm_vcpu *r_vcpu;
>>> +	unsigned long data = vgic_data_mmio_bus_to_host(val, len);
>>> +
>>> +	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
>>> +				       addr - iodev->base_addr);
>>> +	if (!region)
>>> +		return 0;
>>> +
>>> +	if (!check_region(region, addr, len))
>>> +		return 0;
>>> +
>>> +	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
>>> +	region->write(r_vcpu, addr, len, data);
>>> +	return 0;
>>> +}
>>> +
>>> +struct kvm_io_device_ops kvm_io_gic_ops = {
>>> +	.read = dispatch_mmio_read,
>>> +	.write = dispatch_mmio_write,
>>> +};
>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
>>> new file mode 100644
>>> index 0000000..855b1db
>>> --- /dev/null
>>> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
>>> @@ -0,0 +1,87 @@
>>> +/*
>>> + * Copyright (C) 2015, 2016 ARM 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.
>>> + *
>>> + * 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.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +#ifndef __KVM_ARM_VGIC_MMIO_H__
>>> +#define __KVM_ARM_VGIC_MMIO_H__
>>> +
>>> +struct vgic_register_region {
>>> +	unsigned int reg_offset;
>>> +	unsigned int len;
>>> +	unsigned int bits_per_irq;
>>> +	unsigned int access_flags;
>>> +	unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr,
>>> +			      unsigned int len);
>>> +	void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
>>> +		      unsigned long val);
>>> +};
>>> +
>>> +extern struct kvm_io_device_ops kvm_io_gic_ops;
>>> +
>>> +#define VGIC_ACCESS_8bit	1
>>> +#define VGIC_ACCESS_32bit	2
>>> +#define VGIC_ACCESS_64bit	4
>>> +
>>> +/* generate a mask that covers 1024 interrupts with <b> bits per IRQ */
>>
>> Hmmm. I'd appreciate some additional comments, specially when it comes
>> to the various restrictions. May I'd suggest something like:
>>
>> /*
>>  * Generate a mask that covers the number of bytes required to address
>>  * up to 1024 interrupts, each represented by <b> bits. This assumes
>>  * that <b> is a power of two.
>>  *
>>  * ilog2(b) + ilog2(1024) is the number of bits required to bit-address
>>  * 1024 interrupts, each represented by b bits. Minus ilog2(8) converts
>>  * this to a byte address.
> 
> So I'm guessting this is a rewrite of ilog2( (b * 1024) / 8), but I'm

Yes, same thing.

> stupid enough to not understand our use of logarithms here.  Can someone
> remind me whatever I forgot at CS 101?

I'm bad at explaining that kind of things, so let me just quote
Wikipedia (https://en.wikipedia.org/wiki/Binary_logarithm):

"The number of digits (bits) in the binary representation of a positive
integer n is the integral part of 1 + log2?n"

Is that what you were missing?

> 
>>  */
>>
>>> +#define VGIC_ADDR_IRQ_MASK(b) GENMASK_ULL(ilog2(b) + ilog2(1024) - \
>>> +					  ilog2(BITS_PER_BYTE) - 1, 0)
>>
>> /*
>>  * Convert a base address into a base interrupt (each interrupt
>>  * represented by <bits> bits. This assumes that <bits> is a power
>>  * of two, that <addr> both part of a memory region aligned on a
> 
> did you mean '<addr> *is* both part of' ?

Indeed.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From d-gerlach at ti.com  Wed May 18 07:12:20 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 09:12:20 -0500
Subject: [RFC PATCH 1/3] asm-generic: io: Add exec versions of ioremap
In-Reply-To: <20160512163759.GW5783@n2100.arm.linux.org.uk>
References: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
 <1462830111-28172-2-git-send-email-d-gerlach@ti.com>
 <20160512163759.GW5783@n2100.arm.linux.org.uk>
Message-ID: <573C7844.5030107@ti.com>

Hi,
On 05/12/2016 11:37 AM, Russell King - ARM Linux wrote:
> On Mon, May 09, 2016 at 04:41:49PM -0500, Dave Gerlach wrote:
>> diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
>> index 66a978d05958..c6eef3c98074 100644
>> --- a/arch/arm/mm/ioremap.c
>> +++ b/arch/arm/mm/ioremap.c
>> @@ -400,6 +400,20 @@ EXPORT_SYMBOL(ioremap_wc);
>>    * clocks that would affect normal memory for example. Please see
>>    * CONFIG_GENERIC_ALLOCATOR for allocating external memory.
>>    */
>> +void __iomem *ioremap_exec(resource_size_t res_cookie, size_t size)
>> +{
>> +	return arch_ioremap_caller(res_cookie, size, MT_MEMORY_RWX,
>> +				   __builtin_return_address(0));
>> +}
>> +EXPORT_SYMBOL(ioremap_exec);
>> +
>> +void __iomem *ioremap_exec_nocache(resource_size_t res_cookie, size_t size)
>> +{
>> +	return arch_ioremap_caller(res_cookie, size, MT_MEMORY_RWX_NONCACHED,
>> +				   __builtin_return_address(0));
>> +}
>> +EXPORT_SYMBOL(ioremap_exec_nocache);
>
> I think these should be called memremap_exec() and similar.  Please
> see the description of memremap() in kernel/memremap.c.  If you're
> going to be executing code, the region must not have I/O side effects
> and according to the new definition of memremap() vs ioremap(), the
> memremap() interfaces fit better.
>
> Please also get these reviewed by Dan Williams who provided the
> memremap() API.

Ok thank you for the pointer. I agree, the memremap API looks like a 
better fit for this. I think it likely makes the most sense to still add 
these ioremap_exec and ioremap_exec_nocache and then call them through 
the memremap API based on new flags. This will fit into the current use 
model for memremap as it currently uses all of the other ioremap calls 
internally, and doing it how I just described will let this code evolve 
along with memremap.

I will put v2 together this way and send it out.

Regards,
Dave

>
> Thanks.
>



From srinivas.kandagatla at linaro.org  Wed May 18 07:12:27 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Wed, 18 May 2016 15:12:27 +0100
Subject: [PATCH] usb: echi-hcd: Add register access check in shutdown
Message-ID: <1463580747-20868-1-git-send-email-srinivas.kandagatla@linaro.org>

This patch adds a check in ehci_shutdown(), to make sure
that the register access is available before accessing registers.

The use case is simple, for boards like DB410c where the usb host
or device functionality is decided based on the micro-usb cable
presence. If the board boots up with micro-usb connected and the
host driver is probed, but the ehci_setup() has not been done yet,
then a system shutdown would trigger below NULL pointer exception
without this patch.

Unable to handle kernel NULL pointer dereference at virtual address
00000008

pgd = ffffffc034581000
[00000008] *pgd=0000000000000000, *pud=0000000000000000
CPU: 2 PID: 1957 Comm: reboot Not tainted 4.6.0+ #99
task: ffffffc034bc0000 ti: ffffffc0345cc000 task.ti: ffffffc0345cc000
PC is at ehci_halt+0x54/0x108
LR is at ehci_halt+0x38/0x108
pc : [<ffffff800869837c>] lr : [<ffffff8008698360>] pstate: a00001c5
sp : ffffffc0345cfc60
x29: ffffffc0345cfc60 x28: ffffffc0345cc000
x27: ffffff8008a4d000 x26: 000000000000008e
x25: ffffff8008d86cb0 x24: ffffff800908b040
x23: ffffffc036068870 x22: ffffff8009d0a000
x21: ffffffc03512a410 x20: ffffffc03512a410
x19: ffffffc03512a338 x18: 00000000000065ba
x17: ffffff8009b16b80 x16: 0000000000000003
x15: 00000000000065b9 x14: 00000000000065b6
x13: 0000000000000000 x12: 0000000000000000
x11: 000000000000003d x10: ffffffc0345cf9e0
x9 : 0000000000000001 x8 : ffffffc0345cc000
x7 : ffffff8008698360 x6 : 0000000000000000
x5 : 0000000000000080 x4 : 0000000000000001
x3 : 0000000000000000 x2 : 0000000000000000
x1 : 0000000000000008 x0 : ffffffc034bc0000

Process reboot (pid: 1957, stack limit = 0xffffffc0345cc020)
Stack: (0xffffffc0345cfc60 to 0xffffffc0345d0000)
fc60: ffffffc0345cfc90 ffffff8008698448 ffffffc03512a338 ffffffc03512a338
fc80: ffffffc03512a410 ffffff8008a3bbfc ffffffc0345cfcc0 ffffff8008698548
fca0: ffffffc03512a338 ffffffc03512a000 ffffffc03512a410 ffffff8009d0a000
fcc0: ffffffc0345cfcf0 ffffff800865d2bc ffffffc036068828 ffffffc036068810
fce0: ffffffc036003810 ffffff800853f43c ffffffc0345cfd00 ffffff800854338c
fd00: ffffffc0345cfd10 ffffff800853f45c ffffffc0345cfd60 ffffff80080e0f48
fd20: 0000000000000000 0000000001234567 ffffff8008f8c000 ffffff8008f8c060
fd40: 0000000000000000 0000000000000015 0000000000000120 ffffff80080e0f30
fd60: ffffffc0345cfd70 ffffff80080e1020 ffffffc0345cfd90 ffffff80080e12fc
fd80: 0000000000000000 0000000001234567 0000000000000000 ffffff8008085e70
fda0: 0000000000000000 0000005592905000 ffffffffffffffff 0000007f79daf1cc
fdc0: 0000000000000000 0000000000000000 0000007ffcbb1198 000000000000000a
fde0: 00000055928d3f58 0000000000000001 ffffffc034900000 00000000fffffffe
fe00: ffffffc034900000 0000007f79da902c ffffffc0345cfe40 ffffff800820af38
fe20: 0000000000000000 0000007ffcbb1078 ffffffffffffffff ffffff80081e9b38
fe40: ffffffc0345cfe60 ffffff80081eb410 ffffffc0345cfe60 ffffff80081eb444
fe60: ffffffc0345cfec0 ffffff80081ec4f4 0000000000000000 0000007ffcbb1078
fe80: ffffffffffffffff 0000000000000015 ffffffc0345cfec0 0000007ffcbb1078
fea0: 0000000000000002 000000000000000a ffffffffffffffff 0000000000000000
fec0: 0000000000000000 ffffff8008085e70 fffffffffee1dead 0000000028121969
fee0: 0000000001234567 0000000000000000 ffffffffffffffff 8080800000800000
ff00: 0000800000808080 0000007ffcbb10f0 000000000000008e fefeff54918cb8c7
ff20: 7f7f7f7fffffffff 0101010101010101 0000000000000010 0000000000000000
ff40: 0000000000000000 0000007f79e33588 0000005592905eb8 0000007f79daf1b0
ff60: 0000007ffcbb1340 0000005592906000 0000005592905000 0000005592906000
ff80: 0000005592907000 0000000000000002 0000007ffcbb1d98 0000005592906000
ffa0: 00000055928d2000 0000000000000000 0000000000000000 0000007ffcbb1aa0
ffc0: 00000055928b819c 0000007ffcbb1aa0 0000007f79daf1cc 0000000000000000
ffe0: fffffffffee1dead 000000000000008e 05ef555057155555 d555544d55d775d3
Call trace:
Exception stack(0xffffffc0345cfaa0 to 0xffffffc0345cfbc0)
Set corner to 6
faa0: ffffffc03512a338 ffffffc03512a410 ffffffc0345cfc60 ffffff800869837c
fac0: ffffff8008114210 0000000100000001 ffffff8009ce1b20 ffffff8009ce5f20
fae0: ffffffc0345cfb80 ffffff80081145a8 ffffffc0345cfc10 ffffff800810b924
fb00: ffffffc0345cc000 00000000000001c0 ffffffc03512a410 ffffff8009d0a000
fb20: ffffffc036068870 ffffff800908b040 ffffff8008d86cb0 000000000000008e
fb40: ffffffc034bc0000 0000000000000008 0000000000000000 0000000000000000
fb60: 0000000000000001 0000000000000080 0000000000000000 ffffff8008698360
fb80: ffffffc0345cc000 0000000000000001 ffffffc0345cf9e0 000000000000003d
fba0: 0000000000000000 0000000000000000 00000000000065b6 00000000000065b9
[<ffffff800869837c>] ehci_halt+0x54/0x108
[<ffffff8008698448>] ehci_silence_controller+0x18/0xcc
[<ffffff8008698548>] ehci_shutdown+0x4c/0x64
[<ffffff800865d2bc>] usb_hcd_platform_shutdown+0x1c/0x24
[<ffffff800854338c>] platform_drv_shutdown+0x20/0x28
[<ffffff800853f45c>] device_shutdown+0xf4/0x1b0
[<ffffff80080e0f48>] kernel_restart_prepare+0x34/0x3c
[<ffffff80080e1020>] kernel_restart+0x14/0x74
[<ffffff80080e12fc>] SyS_reboot+0x110/0x21c
[<ffffff8008085e70>] el0_svc_naked+0x24/0x28
Code: 53001c42 350000a2 d5033e9f 91002021 (b9000022)

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
---
 drivers/usb/host/ehci-hcd.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index ae1b6e6..43e57ba 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -368,6 +368,9 @@ static void ehci_shutdown(struct usb_hcd *hcd)
 {
 	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
 
+	if (!HCD_HW_ACCESSIBLE(hcd))
+		return;
+
 	spin_lock_irq(&ehci->lock);
 	ehci->shutdown = true;
 	ehci->rh_state = EHCI_RH_STOPPING;
-- 
2.7.4



From christoffer.dall at linaro.org  Wed May 18 07:14:27 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:14:27 +0200
Subject: [PATCH v4 16/56] KVM: arm/arm64: vgic-new: Implement virtual IRQ
 injection
In-Reply-To: <1463392481-26583-17-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-17-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518141427.GA6666@cbox>

On Mon, May 16, 2016 at 10:53:04AM +0100, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> Provide a vgic_queue_irq_unlock() function which decides whether a
> given IRQ needs to be queued to a VCPU's ap_list.
> This should be called whenever an IRQ becomes pending or enabled,
> either as a result of userspace injection, from in-kernel emulated
> devices like the architected timer or from MMIO accesses to the
> distributor emulation.
> Also provides the necessary functions to allow userland to inject an
> IRQ to a guest.
> Since this is the first code that starts using our locking mechanism, we
> add some (hopefully) clear documentation of our locking strategy and
> requirements along with this patch.
> 
> [Andre: refactor out vgic_queue_irq_unlock()]
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> Changelog RFC..v1:
> - add spinlock checks protected by CONFIG_DEBUG_SPINLOCK
> - add more comments to vgic_target_oracle
> - remove BUG_ON() if IRQ is neither edge or level
> - rename vgic_queue_irq() to vgic_queue_irq_unlock()
> - simplify initial check in vgic_queue_irq_unlock()
> - extend retry loop to ask the oracle again
> - minor comment fixes
> 
> Changelog v1 .. v2:
> - move most IRQ injection code into vgic_update_irq_pending()
> 
> Changelog v3 .. v4:
> - simplify vgic_queue_irq_unlock() to allow reusage later
> 
>  include/kvm/vgic/vgic.h  |   3 +
>  virt/kvm/arm/vgic/vgic.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h |   1 +
>  3 files changed, 215 insertions(+)
> 
> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> index 6ca0781..7b6ca90 100644
> --- a/include/kvm/vgic/vgic.h
> +++ b/include/kvm/vgic/vgic.h
> @@ -181,6 +181,9 @@ struct vgic_cpu {
>  	u64 live_lrs;
>  };
>  
> +int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
> +			bool level);
> +
>  #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
>  #define vgic_initialized(k)	(false)
>  #define vgic_ready(k)		((k)->arch.vgic.ready)
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index fb45537..62fede6 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -19,8 +19,31 @@
>  
>  #include "vgic.h"
>  
> +#define CREATE_TRACE_POINTS
> +#include "../trace.h"
> +
> +#ifdef CONFIG_DEBUG_SPINLOCK
> +#define DEBUG_SPINLOCK_BUG_ON(p) BUG_ON(p)
> +#else
> +#define DEBUG_SPINLOCK_BUG_ON(p)
> +#endif
> +
>  struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
>  
> +/*
> + * Locking order is always:
> + *   vgic_cpu->ap_list_lock
> + *     vgic_irq->irq_lock
> + *
> + * (that is, always take the ap_list_lock before the struct vgic_irq lock).
> + *
> + * When taking more than one ap_list_lock at the same time, always take the
> + * lowest numbered VCPU's ap_list_lock first, so:
> + *   vcpuX->vcpu_id < vcpuY->vcpu_id:
> + *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
> + *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
> + */
> +
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid)
>  {
> @@ -39,3 +62,191 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  	WARN(1, "Looking up struct vgic_irq for reserved INTID");
>  	return NULL;
>  }
> +
> +/**
> + * kvm_vgic_target_oracle - compute the target vcpu for an irq
> + *
> + * @irq:	The irq to route. Must be already locked.
> + *
> + * Based on the current state of the interrupt (enabled, pending,
> + * active, vcpu and target_vcpu), compute the next vcpu this should be
> + * given to. Return NULL if this shouldn't be injected at all.
> + *
> + * Requires the IRQ lock to be held.
> + */
> +static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
> +{
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
> +
> +	/* If the interrupt is active, it must stay on the current vcpu */
> +	if (irq->active)
> +		return irq->vcpu;
> +
> +	/*
> +	 * If the IRQ is not active but enabled and pending, we should direct
> +	 * it to its configured target VCPU.
> +	 * If the distributor is disabled, pending interrupts shouldn't be
> +	 * forwarded.
> +	 */
> +	if (irq->enabled && irq->pending) {
> +		if (unlikely(irq->target_vcpu &&
> +			     !irq->target_vcpu->kvm->arch.vgic.enabled))
> +			return NULL;
> +
> +		return irq->target_vcpu;
> +	}
> +
> +	/* If neither active nor pending and enabled, then this IRQ should not
> +	 * be queued to any VCPU.
> +	 */
> +	return NULL;
> +}
> +
> +/*
> + * Only valid injection if changing level for level-triggered IRQs or for a
> + * rising edge.
> + */
> +static bool vgic_validate_injection(struct vgic_irq *irq, bool level)
> +{
> +	switch (irq->config) {
> +	case VGIC_CONFIG_LEVEL:
> +		return irq->line_level != level;
> +	case VGIC_CONFIG_EDGE:
> +		return level;
> +	}
> +
> +	return false;
> +}
> +
> +/*
> + * Check whether an IRQ needs to (and can) be queued to a VCPU's ap list.
> + * Do the queuing if necessary, taking the right locks in the right order.
> + * Returns true when the IRQ was queued, false otherwise.
> + *
> + * Needs to be entered with the IRQ lock already held, but will return
> + * with all locks dropped.
> + */
> +bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq)
> +{
> +	struct kvm_vcpu *vcpu;
> +
> +	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
> +
> +retry:
> +	vcpu = vgic_target_oracle(irq);
> +	if (irq->vcpu || !vcpu) {
> +		/*
> +		 * If this IRQ is already on a VCPU's ap_list, then it
> +		 * cannot be moved or modified and there is no more work for
> +		 * us to do.
> +		 *
> +		 * Otherwise, if the irq is not pending and enabled, it does
> +		 * not need to be inserted into an ap_list and there is also
> +		 * no more work for us to do.
> +		 */
> +		spin_unlock(&irq->irq_lock);
> +		return false;
> +	}
> +
> +	/*
> +	 * We must unlock the irq lock to take the ap_list_lock where
> +	 * we are going to insert this new pending interrupt.
> +	 */
> +	spin_unlock(&irq->irq_lock);
> +
> +	/* someone can do stuff here, which we re-check below */
> +
> +	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +	spin_lock(&irq->irq_lock);
> +
> +	/*
> +	 * Did something change behind our backs?
> +	 *
> +	 * There are two cases:
> +	 * 1) The irq lost its pending state or was disabled behind our
> +	 *    backs and/or it was queued to another VCPU's ap_list.
> +	 *    Then drop the locks and return.
> +	 * 2) Someone changed the affinity on this irq behind our
> +	 *    backs and we are now holding the wrong ap_list_lock.
> +	 *    Then drop the locks and try the new VCPU.

nit: get rid of the 'Then drop the locks and return' from clause (1) and
write, 'In both cases, drop the locks and retry' as a separate paragraph
in the end.

> +	 */
> +
> +	if (unlikely(irq->vcpu || vcpu != vgic_target_oracle(irq))) {
> +		spin_unlock(&irq->irq_lock);
> +		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +
> +		spin_lock(&irq->irq_lock);
> +		goto retry;
> +	}
> +
> +	list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
> +	irq->vcpu = vcpu;
> +
> +	spin_unlock(&irq->irq_lock);
> +	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
> +
> +	kvm_vcpu_kick(vcpu);
> +
> +	return true;
> +}
> +
> +static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
> +				   unsigned int intid, bool level,
> +				   bool mapped_irq)
> +{
> +	struct kvm_vcpu *vcpu;
> +	struct vgic_irq *irq;
> +	int ret;
> +
> +	trace_vgic_update_irq_pending(cpuid, intid, level);
> +
> +	vcpu = kvm_get_vcpu(kvm, cpuid);
> +	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
> +		return -EINVAL;
> +
> +	irq = vgic_get_irq(kvm, vcpu, intid);
> +	if (!irq)
> +		return -EINVAL;
> +
> +	if (irq->hw != mapped_irq)
> +		return -EINVAL;
> +
> +	spin_lock(&irq->irq_lock);
> +
> +	if (!vgic_validate_injection(irq, level)) {
> +		/* Nothing to see here, move along... */
> +		spin_unlock(&irq->irq_lock);
> +		return 0;
> +	}
> +
> +	if (irq->config == VGIC_CONFIG_LEVEL) {
> +		irq->line_level = level;
> +		irq->pending = level || irq->soft_pending;
> +	} else {
> +		irq->pending = true;
> +	}
> +
> +	vgic_queue_irq_unlock(kvm, irq);
> +
> +	return 0;
> +}
> +
> +/**
> + * kvm_vgic_inject_irq - Inject an IRQ from a device to the vgic
> + * @kvm:     The VM structure pointer
> + * @cpuid:   The CPU for PPIs
> + * @intid:   The INTID to inject a new state to.
> + * @level:   Edge-triggered:  true:  to trigger the interrupt
> + *			      false: to ignore the call
> + *	     Level-sensitive  true:  raise the input signal
> + *			      false: lower the input signal
> + *
> + * The VGIC is not concerned with devices being active-LOW or active-HIGH for
> + * level-sensitive interrupts.  You can think of the level parameter as 1
> + * being HIGH and 0 being LOW and all devices being active-HIGH.
> + */
> +int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
> +			bool level)
> +{
> +	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 61b8d22..c625767 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -18,5 +18,6 @@
>  
>  struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  			      u32 intid);
> +bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
>  
>  #endif
> -- 
> 2.8.2
> 

Besides the comment nit:

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 07:14:38 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:14:38 +0200
Subject: [PATCH v4 20/56] KVM: arm/arm64: vgic-new: Add GICv3 world
 switch backend
In-Reply-To: <1463392481-26583-21-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-21-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518141438.GB6666@cbox>

On Mon, May 16, 2016 at 10:53:08AM +0100, Andre Przywara wrote:
> From: Marc Zyngier <marc.zyngier at arm.com>
> 
> As the GICv3 virtual interface registers differ from their GICv2
> siblings, we need different handlers for processing maintenance
> interrupts and reading/writing to the LRs.
> Implement the respective handler functions and connect them to
> existing code to be called if the host is using a GICv3.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 07:14:44 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:14:44 +0200
Subject: [PATCH v4 25/56] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <1463392481-26583-26-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-26-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518141444.GC6666@cbox>

On Mon, May 16, 2016 at 10:53:13AM +0100, Andre Przywara wrote:
> As the enable register handlers are shared between the v2 and v3
> emulation, their implementation goes into vgic-mmio.c, to be easily
> referenced from the v3 emulation as well later.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 07:14:08 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:14:08 +0200
Subject: [PATCH v4 36/56] KVM: arm/arm64: vgic-new: Add GICv3 IDREGS
 register handler
In-Reply-To: <1463392481-26583-37-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-37-git-send-email-andre.przywara@arm.com>
Message-ID: <CAMJs5B8KZv=dGDYtrXo3FQ9sx2=G+rrTFgN10tLLfb4O+wBcGw@mail.gmail.com>

On Mon, May 16, 2016 at 10:53:24AM +0100, Andre Przywara wrote:
> We implement the only one ID register that is required by the
> architecture, also this is the one that Linux actually checks.
>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 07:15:42 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:15:42 +0200
Subject: [PATCH v4 26/56] KVM: arm/arm64: vgic-new: Add PENDING registers
 handlers
In-Reply-To: <1463392481-26583-27-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-27-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518141542.GD6666@cbox>

On Mon, May 16, 2016 at 10:53:14AM +0100, Andre Przywara wrote:
> The pending register handlers are shared between the v2 and v3
> emulation, so their implementation goes into vgic-mmio.c, to be easily
> referenced from the v3 emulation as well later.
> For level triggered interrupts the real line level is unaffected by
> this write, so we keep this state separate and combine it with the
> device's level to get the actual pending state.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 07:15:47 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:15:47 +0200
Subject: [PATCH v4 28/56] KVM: arm/arm64: vgic-new: Add PRIORITY
 registers handlers
In-Reply-To: <1463392481-26583-29-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-29-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518141547.GE6666@cbox>

On Mon, May 16, 2016 at 10:53:16AM +0100, Andre Przywara wrote:
> The priority register handlers are shared between the v2 and v3
> emulation, so their implementation goes into vgic-mmio.c, to be
> easily referenced from the v3 emulation as well later.
> There is a corner case when we change the priority of a pending
> interrupt which we don't handle at the moment.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 07:15:51 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:15:51 +0200
Subject: [PATCH v4 30/56] KVM: arm/arm64: vgic-new: Add TARGET registers
 handlers
In-Reply-To: <1463392481-26583-31-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-31-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518141551.GF6666@cbox>

On Mon, May 16, 2016 at 10:53:18AM +0100, Andre Przywara wrote:
> The target register handlers are v2 emulation specific, so their
> implementation lives entirely in vgic-mmio-v2.c.
> We copy the old VGIC behaviour of assigning an IRQ to the first VCPU
> set in the target mask instead of making it possibly pending on
> multiple VCPUs.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 07:15:55 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:15:55 +0200
Subject: [PATCH v4 34/56] KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR, 
 TYPER handlers
In-Reply-To: <1463392481-26583-35-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-35-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518141555.GG6666@cbox>

On Mon, May 16, 2016 at 10:53:22AM +0100, Andre Przywara wrote:
> As in the GICv2 emulation we handle those three registers in one
> function.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 07:16:03 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:16:03 +0200
Subject: [PATCH v4 36/56] KVM: arm/arm64: vgic-new: Add GICv3 IDREGS
 register handler
In-Reply-To: <1463392481-26583-37-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-37-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518141603.GI6666@cbox>

On Mon, May 16, 2016 at 10:53:24AM +0100, Andre Przywara wrote:
> We implement the only one ID register that is required by the
> architecture, also this is the one that Linux actually checks.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From christoffer.dall at linaro.org  Wed May 18 07:15:59 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:15:59 +0200
Subject: [PATCH v4 35/56] KVM: arm/arm64: vgic-new: Add GICv3
 redistributor IIDR and TYPER handler
In-Reply-To: <1463392481-26583-36-git-send-email-andre.przywara@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-36-git-send-email-andre.przywara@arm.com>
Message-ID: <20160518141559.GH6666@cbox>

On Mon, May 16, 2016 at 10:53:23AM +0100, Andre Przywara wrote:
> The redistributor TYPER tells the OS about the associated MPIDR,
> also the LAST bit is crucial to determine the number of redistributors.
> 
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From sre at kernel.org  Wed May 18 07:16:25 2016
From: sre at kernel.org (Sebastian Reichel)
Date: Wed, 18 May 2016 16:16:25 +0200
Subject: 4.5-rc0 regression: GPRS breaks after very short while
In-Reply-To: <20160518074924.GA20652@amd>
References: <20160518074924.GA20652@amd>
Message-ID: <20160518141624.GA8025@earth>

Hi Pavel,

On Wed, May 18, 2016 at 09:49:24AM +0200, Pavel Machek wrote:
> I was afraid another GSM chip desoldered itself in N900, but no, it
> seems to be software this time.
> 
> In 4.4, GPRS is rock solid, can survive overnight ping.
> 
> In 4.5-rc0 and v4.6, modem fails when I use gprs for like a
> minute. Phone is not usable.

I only send three modem related changes for v4.5:

https://git.kernel.org/cgit/linux/kernel/git/sre/linux-hsi.git/commit/?h=hsi-for-4.5&id=525e1abc6b5a7d8bd9006de1da6e99722305ea2b
HSI: omap_ssi: fix handling ida_simple_get result

https://git.kernel.org/cgit/linux/kernel/git/sre/linux-hsi.git/commit/?h=hsi-for-4.5&id=6bf6ded3008a407ccab5ad72eb59ab71b97cc290
HSI: omap_ssi_port: fix handling of_get_named_gpio result

https://git.kernel.org/cgit/linux/kernel/git/sre/linux-hsi.git/commit/?h=hsi-for-4.5&id=403c5c0650816375527a6feecfb255d9b494dda3
HSI: Remove struct hsi_client private fields from kernel-doc

The last one only changes a comment, so not relevant, the other
two fix error handling during initialization and are most likely
also not the problem. Can you try to bisect the problem?

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160518/bf6ba04e/attachment.sig>

From andre.przywara at arm.com  Wed May 18 07:18:13 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 18 May 2016 15:18:13 +0100
Subject: [PATCH v3 10/55] KVM: arm/arm64: Export mmio_read/write_bus
In-Reply-To: <1462531568-9799-11-git-send-email-andre.przywara@arm.com>
References: <1462531568-9799-1-git-send-email-andre.przywara@arm.com>
 <1462531568-9799-11-git-send-email-andre.przywara@arm.com>
Message-ID: <573C79A5.6080008@arm.com>

On 06/05/16 11:45, Andre Przywara wrote:
> From: Christoffer Dall <christoffer.dall at linaro.org>
> 
> Rename mmio_{read,write}_bus to kvm_mmio_{read,write}_bus and export
> them out of mmio.c.
> This will be needed later for the new VGIC implementation.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>

Reviewed-by: Andre Przywara <andre.przywara at arm.com>

Thanks,
Andre.

> ---
>  arch/arm/include/asm/kvm_mmio.h   |  3 +++
>  arch/arm/kvm/mmio.c               | 10 +++++-----
>  arch/arm64/include/asm/kvm_mmio.h |  3 +++
>  3 files changed, 11 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm/include/asm/kvm_mmio.h b/arch/arm/include/asm/kvm_mmio.h
> index d8e90c8..f3a7de7 100644
> --- a/arch/arm/include/asm/kvm_mmio.h
> +++ b/arch/arm/include/asm/kvm_mmio.h
> @@ -28,6 +28,9 @@ struct kvm_decode {
>  	bool sign_extend;
>  };
>  
> +void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
> +unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
> +
>  int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
>  int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
>  		 phys_addr_t fault_ipa);
> diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
> index 0158e9e..10f80a6 100644
> --- a/arch/arm/kvm/mmio.c
> +++ b/arch/arm/kvm/mmio.c
> @@ -23,7 +23,7 @@
>  
>  #include "trace.h"
>  
> -static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
> +void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data)
>  {
>  	void *datap = NULL;
>  	union {
> @@ -55,7 +55,7 @@ static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
>  	memcpy(buf, datap, len);
>  }
>  
> -static unsigned long mmio_read_buf(char *buf, unsigned int len)
> +unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len)
>  {
>  	unsigned long data = 0;
>  	union {
> @@ -66,7 +66,7 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len)
>  
>  	switch (len) {
>  	case 1:
> -		data = buf[0];
> +		data = *(u8 *)buf;
>  		break;
>  	case 2:
>  		memcpy(&tmp.hword, buf, len);
> @@ -103,7 +103,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
>  		if (len > sizeof(unsigned long))
>  			return -EINVAL;
>  
> -		data = mmio_read_buf(run->mmio.data, len);
> +		data = kvm_mmio_read_buf(run->mmio.data, len);
>  
>  		if (vcpu->arch.mmio_decode.sign_extend &&
>  		    len < sizeof(unsigned long)) {
> @@ -189,7 +189,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
>  					       len);
>  
>  		trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data);
> -		mmio_write_buf(data_buf, len, data);
> +		kvm_mmio_write_buf(data_buf, len, data);
>  
>  		ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
>  				       data_buf);
> diff --git a/arch/arm64/include/asm/kvm_mmio.h b/arch/arm64/include/asm/kvm_mmio.h
> index fe612a9..75ea420 100644
> --- a/arch/arm64/include/asm/kvm_mmio.h
> +++ b/arch/arm64/include/asm/kvm_mmio.h
> @@ -30,6 +30,9 @@ struct kvm_decode {
>  	bool sign_extend;
>  };
>  
> +void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
> +unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
> +
>  int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
>  int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
>  		 phys_addr_t fault_ipa);
> 


From arnd at arndb.de  Wed May 18 07:17:36 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 16:17:36 +0200
Subject: [PATCH] ARM: exynos: don't select keyboard driver
Message-ID: <1463581102-1007639-1-git-send-email-arnd@arndb.de>

The samsung-keypad driver is implicitly selected by ARCH_EXYNOS4 (why?),
but this fails if CONFIG_INPUT is a loadable module:

drivers/input/built-in.o: In function `samsung_keypad_remove':
drivers/input/keyboard/samsung-keypad.c:461: undefined reference to `input_unregister_device'
drivers/input/built-in.o: In function `samsung_keypad_irq':
drivers/input/keyboard/samsung-keypad.c:137: undefined reference to `input_event'
drivers/input/built-in.o: In function `samsung_keypad_irq':
include/linux/input.h:389: undefined reference to `input_event'
drivers/input/built-in.o: In function `samsung_keypad_probe':
drivers/input/keyboard/samsung-keypad.c:358: undefined reference to `devm_input_allocate_device'
drivers/input/built-in.o:(.debug_addr+0x34): undefined reference to `input_set_capability'

This removes the 'select' as suggested by Krzysztof Kozlowski and
instead enables the driver from the defconfig files.

The problem does not happen on mainline kernels, as we don't normally
build built-in input drivers when CONFIG_INPUT=m, but I am experimenting
with a patch to change this, and the samsung keypad driver showed up
as one example that was silently broken before.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Link: https://lkml.org/lkml/2016/2/14/55
---
 arch/arm/configs/exynos_defconfig   | 1 +
 arch/arm/configs/multi_v7_defconfig | 1 +
 arch/arm/mach-exynos/Kconfig        | 1 -
 3 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
index a8cf295724c5..1124a51e0d16 100644
--- a/arch/arm/configs/exynos_defconfig
+++ b/arch/arm/configs/exynos_defconfig
@@ -82,6 +82,7 @@ CONFIG_TOUCHSCREEN_MMS114=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MAX77693_HAPTIC=y
 CONFIG_INPUT_MAX8997_HAPTIC=y
+CONFIG_KEYBOARD_SAMSUNG=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_SAMSUNG=y
 CONFIG_SERIAL_SAMSUNG_CONSOLE=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index f7e0d49b515a..a9bb659cdbbb 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -264,6 +264,7 @@ CONFIG_KEYBOARD_TEGRA=y
 CONFIG_KEYBOARD_SPEAR=y
 CONFIG_KEYBOARD_ST_KEYSCAN=y
 CONFIG_KEYBOARD_CROS_EC=m
+CONFIG_KEYBOARD_SAMSUNG=m
 CONFIG_MOUSE_PS2_ELANTECH=y
 CONFIG_MOUSE_CYAPA=m
 CONFIG_MOUSE_ELAN_I2C=y
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index dc9b6fb103c6..8ce964ddb4e3 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -61,7 +61,6 @@ config ARCH_EXYNOS4
 	select CLKSRC_SAMSUNG_PWM if CPU_EXYNOS4210
 	select CPU_EXYNOS4210
 	select GIC_NON_BANKED
-	select KEYBOARD_SAMSUNG if INPUT_KEYBOARD
 	select MIGHT_HAVE_CACHE_L2X0
 	help
 	  Samsung EXYNOS4 (Cortex-A9) SoC based systems
-- 
2.7.0



From catalin.marinas at arm.com  Wed May 18 07:26:21 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 18 May 2016 14:26:21 +0000
Subject: [PATCH v2] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <573C72DD.6010400@suse.de>
References: <1463576010-115428-1-git-send-email-agraf@suse.de>
 <20160518132741.GE22378@e104818-lin.cambridge.arm.com>
 <573C72DD.6010400@suse.de>
Message-ID: <20160518142620.GA22354@localhost.localdomain>

On Wed, May 18, 2016 at 03:49:17PM +0200, Alexander Graf wrote:
> On 05/18/2016 03:27 PM, Catalin Marinas wrote:
> >On Wed, May 18, 2016 at 02:53:30PM +0200, Alexander Graf wrote:
> >>On arm64, all SoCs we supported so far either have an IOMMU or have bus
> >>addresses equal to CPU addresses.
> >>
> >>However, with the Raspberry Pi 3 coming up, this is no longer true. To
> >>allow DMA to work with an AArch64 kernel on those devices, let's allow
> >>devices to have DMA offsets again.
> >>
> >>Signed-off-by: Alexander Graf <agraf at suse.de>
> >We were aware about this issue but we've been waiting for an actual use
> >case. I'll queue this for 4.8 (given that RPi3 is not supported by the
> >arm64 kernel, I don't see the rush to merge it earlier).
> 
> Sure, works for me. That way Eric can try to push the other few bits
> necessary to run an arm64 kernel on the RPi3 towards 4.8 as well :).

As long as the firmware is PSCI capable ;)

-- 
Catalin


From christoffer.dall at linaro.org  Wed May 18 07:29:49 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 16:29:49 +0200
Subject: [PATCH v4 22/56] KVM: arm/arm64: vgic-new: Add MMIO handling
 framework
In-Reply-To: <573C7851.4010401@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-23-git-send-email-andre.przywara@arm.com>
 <573B1DB0.7030901@arm.com> <20160518122521.GD3827@cbox>
 <573C7851.4010401@arm.com>
Message-ID: <20160518142949.GJ6666@cbox>

On Wed, May 18, 2016 at 03:12:33PM +0100, Marc Zyngier wrote:
> On 18/05/16 13:25, Christoffer Dall wrote:
> > On Tue, May 17, 2016 at 02:33:36PM +0100, Marc Zyngier wrote:
> >> On 16/05/16 10:53, Andre Przywara wrote:
> >>> From: Marc Zyngier <marc.zyngier at arm.com>
> >>>
> >>> Add an MMIO handling framework to the VGIC emulation:
> >>> Each register is described by its offset, size (or number of bits per
> >>> IRQ, if applicable) and the read/write handler functions. We provide
> >>> initialization macros to describe each GIC register later easily.
> >>>
> >>> Separate dispatch functions for read and write accesses are connected
> >>> to the kvm_io_bus framework and binary-search for the responsible
> >>> register handler based on the offset address within the region.
> >>> We convert the incoming data (referenced by a pointer) to the host's
> >>> endianess and use pass-by-value to hand the data over to the actual
> >>> handler functions.
> >>>
> >>> The register handler prototype and the endianess conversion are
> >>> courtesy of Christoffer Dall.
> >>>
> >>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> >>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> >>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >>> ---
> >>> Changelog RFC..v1:
> >>> - rework MMIO dispatching to use only one kvm_io_bus device
> >>> - document purpose of register region macros
> >>> - rename "this" parameter to "dev"
> >>> - change IGROUPR to be RAO (returning 1 => Group1 IRQs)
> >>>
> >>> Changelog v1 .. v2:
> >>> * MASSIVE rework:
> >>> - store register_region pointer in kvm_io_bus linked struct
> >>> - replace write_mask_xxx functions with extract_bytes() implementation
> >>> - change handler functions' prototypes to take and return unsigned long
> >>> - use binary search to find matching register handler
> >>> - convert endianess of input data in dispatch_mmio_xxx functions
> >>> - improve readability of register initializer macros
> >>> - remove any GICv2/GICv3 specific functions from vgic-mmio.c
> >>> - rename file from vgic_mmio.c to vgic-mmio.c
> >>>
> >>> Changelog v2 .. v3:
> >>> - replace inclusion of vgic/vgic.h with arm_vgic.h
> >>>
> >>> Changelog v3 .. v4:
> >>> - add IRQ number accessor macro
> >>> - check access width in dispatcher
> >>> - treat non-covered MMIO addresses as RAZ/WI
> >>> - remove extract_bytes() (re-introduced as static later in the series)
> >>>
> >>>  include/kvm/vgic/vgic.h       |  13 +++
> >>>  virt/kvm/arm/vgic/vgic-mmio.c | 184 ++++++++++++++++++++++++++++++++++++++++++
> >>>  virt/kvm/arm/vgic/vgic-mmio.h |  87 ++++++++++++++++++++
> >>>  3 files changed, 284 insertions(+)
> >>>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
> >>>  create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h
> >>>
> >>> diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
> >>> index f663288..ff3f9c2 100644
> >>> --- a/include/kvm/vgic/vgic.h
> >>> +++ b/include/kvm/vgic/vgic.h
> >>> @@ -106,6 +106,16 @@ struct vgic_irq {
> >>>  	enum vgic_irq_config config;	/* Level or edge */
> >>>  };
> >>>  
> >>> +struct vgic_register_region;
> >>> +
> >>> +struct vgic_io_device {
> >>> +	gpa_t base_addr;
> >>> +	struct kvm_vcpu *redist_vcpu;
> >>> +	const struct vgic_register_region *regions;
> >>> +	int nr_regions;
> >>> +	struct kvm_io_device dev;
> >>> +};
> >>> +
> >>>  struct vgic_dist {
> >>>  	bool			in_kernel;
> >>>  	bool			ready;
> >>> @@ -132,6 +142,9 @@ struct vgic_dist {
> >>>  	bool			enabled;
> >>>  
> >>>  	struct vgic_irq		*spis;
> >>> +
> >>> +	struct vgic_io_device	dist_iodev;
> >>> +	struct vgic_io_device	*redist_iodevs;
> >>>  };
> >>>  
> >>>  struct vgic_v2_cpu_if {
> >>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> >>> new file mode 100644
> >>> index 0000000..012b82b
> >>> --- /dev/null
> >>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> >>> @@ -0,0 +1,184 @@
> >>> +/*
> >>> + * VGIC MMIO handling functions
> >>> + *
> >>> + * This program is free software; you can redistribute it and/or modify
> >>> + * it under the terms of the GNU General Public License version 2 as
> >>> + * published by the Free Software Foundation.
> >>> + *
> >>> + * This program is distributed in the hope that it will be useful,
> >>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >>> + * GNU General Public License for more details.
> >>> + */
> >>> +
> >>> +#include <linux/bitops.h>
> >>> +#include <linux/bsearch.h>
> >>> +#include <linux/kvm.h>
> >>> +#include <linux/kvm_host.h>
> >>> +#include <kvm/iodev.h>
> >>> +#include <kvm/arm_vgic.h>
> >>> +
> >>> +#include "vgic.h"
> >>> +#include "vgic-mmio.h"
> >>> +
> >>> +unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
> >>> +				 gpa_t addr, unsigned int len)
> >>> +{
> >>> +	return 0;
> >>> +}
> >>> +
> >>> +unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
> >>> +				 gpa_t addr, unsigned int len)
> >>> +{
> >>> +	return -1UL;
> >>> +}
> >>> +
> >>> +void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
> >>> +			unsigned int len, unsigned long val)
> >>> +{
> >>> +	/* Ignore */
> >>> +}
> >>> +
> >>> +static int match_region(const void *key, const void *elt)
> >>> +{
> >>> +	const unsigned int offset = (unsigned long)key;
> >>> +	const struct vgic_register_region *region = elt;
> >>> +
> >>> +	if (offset < region->reg_offset)
> >>> +		return -1;
> >>> +
> >>> +	if (offset >= region->reg_offset + region->len)
> >>> +		return 1;
> >>> +
> >>> +	return 0;
> >>> +}
> >>> +
> >>> +/* Find the proper register handler entry given a certain address offset. */
> >>> +static const struct vgic_register_region *
> >>> +vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
> >>> +		      unsigned int offset)
> >>> +{
> >>> +	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
> >>> +		       sizeof(region[0]), match_region);
> >>> +}
> >>> +
> >>> +/*
> >>> + * kvm_mmio_read_buf() returns a value in a format where it can be converted
> >>> + * to a byte array and be directly observed as the guest wanted it to appear
> >>> + * in memory if it had done the store itself, which is LE for the GIC, as the
> >>> + * guest knows the GIC is always LE.
> >>> + *
> >>> + * We convert this value to the CPUs native format to deal with it as a data
> >>> + * value.
> >>> + */
> >>> +unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len)
> >>> +{
> >>> +	unsigned long data = kvm_mmio_read_buf(val, len);
> >>> +
> >>> +	switch (len) {
> >>> +	case 1:
> >>> +		return data;
> >>> +	case 2:
> >>> +		return le16_to_cpu(data);
> >>> +	case 4:
> >>> +		return le32_to_cpu(data);
> >>> +	default:
> >>> +		return le64_to_cpu(data);
> >>> +	}
> >>> +}
> >>> +
> >>> +/*
> >>> + * kvm_mmio_write_buf() expects a value in a format such that if converted to
> >>> + * a byte array it is observed as the guest would see it if it could perform
> >>> + * the load directly.  Since the GIC is LE, and the guest knows this, the
> >>> + * guest expects a value in little endian format.
> >>> + *
> >>> + * We convert the data value from the CPUs native format to LE so that the
> >>> + * value is returned in the proper format.
> >>> + */
> >>> +void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
> >>> +				unsigned long data)
> >>> +{
> >>> +	switch (len) {
> >>> +	case 1:
> >>> +		break;
> >>> +	case 2:
> >>> +		data = cpu_to_le16(data);
> >>> +		break;
> >>> +	case 4:
> >>> +		data = cpu_to_le32(data);
> >>> +		break;
> >>> +	default:
> >>> +		data = cpu_to_le64(data);
> >>> +	}
> >>> +
> >>> +	kvm_mmio_write_buf(buf, len, data);
> >>> +}
> >>> +
> >>> +static
> >>> +struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
> >>> +{
> >>> +	return container_of(dev, struct vgic_io_device, dev);
> >>> +}
> >>> +
> >>> +static bool check_region(const struct vgic_register_region *region,
> >>> +			 gpa_t addr, int len)
> >>> +{
> >>> +	if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1)
> >>> +		return true;
> >>> +	if ((region->access_flags & VGIC_ACCESS_32bit) &&
> >>> +	    len == sizeof(u32) && !(addr & 3))
> >>> +		return true;
> >>> +	if ((region->access_flags & VGIC_ACCESS_64bit) &&
> >>> +	    len == sizeof(u64) && !(addr & 7))
> >>> +		return true;
> >>> +
> >>> +	return false;
> >>> +}
> >>> +
> >>> +static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
> >>> +			      gpa_t addr, int len, void *val)
> >>> +{
> >>> +	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
> >>> +	const struct vgic_register_region *region;
> >>> +	struct kvm_vcpu *r_vcpu;
> >>> +	unsigned long data;
> >>> +
> >>> +	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
> >>> +				       addr - iodev->base_addr);
> >>> +	if (!region || !check_region(region, addr, len)) {
> >>> +		memset(val, 0, len);
> >>> +		return 0;
> >>> +	}
> >>> +
> >>> +	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
> >>> +	data = region->read(r_vcpu, addr, len);
> >>> +	vgic_data_host_to_mmio_bus(val, len, data);
> >>> +	return 0;
> >>> +}
> >>> +
> >>> +static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
> >>> +			       gpa_t addr, int len, const void *val)
> >>> +{
> >>> +	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
> >>> +	const struct vgic_register_region *region;
> >>> +	struct kvm_vcpu *r_vcpu;
> >>> +	unsigned long data = vgic_data_mmio_bus_to_host(val, len);
> >>> +
> >>> +	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
> >>> +				       addr - iodev->base_addr);
> >>> +	if (!region)
> >>> +		return 0;
> >>> +
> >>> +	if (!check_region(region, addr, len))
> >>> +		return 0;
> >>> +
> >>> +	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
> >>> +	region->write(r_vcpu, addr, len, data);
> >>> +	return 0;
> >>> +}
> >>> +
> >>> +struct kvm_io_device_ops kvm_io_gic_ops = {
> >>> +	.read = dispatch_mmio_read,
> >>> +	.write = dispatch_mmio_write,
> >>> +};
> >>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> >>> new file mode 100644
> >>> index 0000000..855b1db
> >>> --- /dev/null
> >>> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> >>> @@ -0,0 +1,87 @@
> >>> +/*
> >>> + * Copyright (C) 2015, 2016 ARM 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.
> >>> + *
> >>> + * 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.
> >>> + *
> >>> + * You should have received a copy of the GNU General Public License
> >>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> >>> + */
> >>> +#ifndef __KVM_ARM_VGIC_MMIO_H__
> >>> +#define __KVM_ARM_VGIC_MMIO_H__
> >>> +
> >>> +struct vgic_register_region {
> >>> +	unsigned int reg_offset;
> >>> +	unsigned int len;
> >>> +	unsigned int bits_per_irq;
> >>> +	unsigned int access_flags;
> >>> +	unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr,
> >>> +			      unsigned int len);
> >>> +	void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
> >>> +		      unsigned long val);
> >>> +};
> >>> +
> >>> +extern struct kvm_io_device_ops kvm_io_gic_ops;
> >>> +
> >>> +#define VGIC_ACCESS_8bit	1
> >>> +#define VGIC_ACCESS_32bit	2
> >>> +#define VGIC_ACCESS_64bit	4
> >>> +
> >>> +/* generate a mask that covers 1024 interrupts with <b> bits per IRQ */
> >>
> >> Hmmm. I'd appreciate some additional comments, specially when it comes
> >> to the various restrictions. May I'd suggest something like:
> >>
> >> /*
> >>  * Generate a mask that covers the number of bytes required to address
> >>  * up to 1024 interrupts, each represented by <b> bits. This assumes
> >>  * that <b> is a power of two.
> >>  *
> >>  * ilog2(b) + ilog2(1024) is the number of bits required to bit-address
> >>  * 1024 interrupts, each represented by b bits. Minus ilog2(8) converts
> >>  * this to a byte address.
> > 
> > So I'm guessting this is a rewrite of ilog2( (b * 1024) / 8), but I'm
> 
> Yes, same thing.
> 
> > stupid enough to not understand our use of logarithms here.  Can someone
> > remind me whatever I forgot at CS 101?
> 
> I'm bad at explaining that kind of things, so let me just quote
> Wikipedia (https://en.wikipedia.org/wiki/Binary_logarithm):
> 
> "The number of digits (bits) in the binary representation of a positive
> integer n is the integral part of 1 + log2?n"
> 
> Is that what you were missing?
> 

yeah, duh, I feel stupid now.  Mind if we add this "note to
Christoffer's brain" to the comment:

"Since n bits can address a maximum of N=n^2 values, we get the number of
bits required to address a number of values by applying log2(N).  With
N being 1024 * b, we get  that ilog(b) + ilog2(1024) is the number..."


> > 
> >>  */
> >>
> >>> +#define VGIC_ADDR_IRQ_MASK(b) GENMASK_ULL(ilog2(b) + ilog2(1024) - \
> >>> +					  ilog2(BITS_PER_BYTE) - 1, 0)
> >>
> >> /*
> >>  * Convert a base address into a base interrupt (each interrupt
> >>  * represented by <bits> bits. This assumes that <bits> is a power
> >>  * of two, that <addr> both part of a memory region aligned on a
> > 
> > did you mean '<addr> *is* both part of' ?
> 
> Indeed.
> 

Thanks,
-Christoffer


From stefan.wahren at i2se.com  Wed May 18 07:30:01 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Wed, 18 May 2016 16:30:01 +0200
Subject: [PATCH v3 0/2] nvmem: remove regmap dependency
In-Reply-To: <1462214174-469-1-git-send-email-srinivas.kandagatla@linaro.org>
References: <1462214174-469-1-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <573C7C69.1050301@i2se.com>

Hi Srinivas,

Am 02.05.2016 um 20:36 schrieb Srinivas Kandagatla:
> Hi Greg, 
>
> This is v3 patchset for the leftover 2 patches for nvmem regmap
> removal series [1]. These patches are based on char-misc tree.
>
> nvmem uses regmap_raw_read/write apis to read/write data from providers,
> With recent patch 922a9f936e40 ("regmap: mmio: Convert to regmap_bus
> and fix accessor usage") nvmem providers based on regmap-mmio stopped
> working, as nvmem core was using raw accessors.
> This issue can be fixed temporarly by moving to other regmap apis,
> but we might hit same issue in future, and regmap looks like an
> overdo for nvmem. Moving to interfaces based on read/write callbacks
> from providers would be more robust.

i noticed that Documentation/nvmem/nvmem.txt also needs a fix after
removing regmap dependency.




From agraf at suse.de  Wed May 18 07:34:12 2016
From: agraf at suse.de (Alexander Graf)
Date: Wed, 18 May 2016 16:34:12 +0200
Subject: [PATCH v2] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <20160518142620.GA22354@localhost.localdomain>
References: <1463576010-115428-1-git-send-email-agraf@suse.de>
 <20160518132741.GE22378@e104818-lin.cambridge.arm.com>
 <573C72DD.6010400@suse.de> <20160518142620.GA22354@localhost.localdomain>
Message-ID: <573C7D64.5040206@suse.de>

On 05/18/2016 04:26 PM, Catalin Marinas wrote:
> On Wed, May 18, 2016 at 03:49:17PM +0200, Alexander Graf wrote:
>> On 05/18/2016 03:27 PM, Catalin Marinas wrote:
>>> On Wed, May 18, 2016 at 02:53:30PM +0200, Alexander Graf wrote:
>>>> On arm64, all SoCs we supported so far either have an IOMMU or have bus
>>>> addresses equal to CPU addresses.
>>>>
>>>> However, with the Raspberry Pi 3 coming up, this is no longer true. To
>>>> allow DMA to work with an AArch64 kernel on those devices, let's allow
>>>> devices to have DMA offsets again.
>>>>
>>>> Signed-off-by: Alexander Graf <agraf at suse.de>
>>> We were aware about this issue but we've been waiting for an actual use
>>> case. I'll queue this for 4.8 (given that RPi3 is not supported by the
>>> arm64 kernel, I don't see the rush to merge it earlier).
>> Sure, works for me. That way Eric can try to push the other few bits
>> necessary to run an arm64 kernel on the RPi3 towards 4.8 as well :).
> As long as the firmware is PSCI capable ;)

So spin tables won't work for you? IIRC we don't own EL3 on there.


Alex



From linus.walleij at linaro.org  Wed May 18 07:35:13 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 18 May 2016 16:35:13 +0200
Subject: [GIT PULL] move ARM LCD display driver to auxdisplay
In-Reply-To: <20160512122500.11411882@erd979>
References: <CACRpkdbyO0axd5ergYZcXO302f2fFAPKrSNevkvreP1kRjm-vw@mail.gmail.com>
 <20160425115758.GA4874@lukather>
 <CACRpkdb=s5onVa7qND9nFUtYPw5H-Hdr7Ja5o3=-9+wxghHekQ@mail.gmail.com>
 <20160428092608.GE17159@lukather> <5723755D.9060108@ti.com>
 <20160509090615.6272f8ca@erd979>
 <CACRpkdbZmL9Cqp-ubzyxd7fWUFOVsS1DCxsfG02kSpbWu_rbZQ@mail.gmail.com>
 <20160509161728.3aee1134@erd979>
 <CACRpkdZwPVMx-dXVkfVwFN0juzVuyvShV7yDWbUFSXOPE=uUrw@mail.gmail.com>
 <20160512122500.11411882@erd979>
Message-ID: <CACRpkdYwtwosdCE_F5SEH9uwZRdJkAi-seL+nUrMFZ+w_esuVQ@mail.gmail.com>

On Thu, May 12, 2016 at 12:25 PM, Robin van der Gracht
<robin at protonic.nl> wrote:

> First half is completed. I've added myself as maintainer for the
> driver I've posted recently (HT16K33 LED CONTROLLER DRIVER).

Good!

> According to MAINTAINERS, Miguel maintains:
>  - CFAG12864B LCD DRIVER
>  - CFAG12864BFB LCD FRAMEBUFFER DRIVER
>  - KS0108 LCD CONTROLLER DRIVER
>  - AUXILIARY DISPLAY DRIVERS
>
> AFAIK, I should not be judge in Miguels case.

If patches come in for these drivers and Miguel still seem to be fallen
off the face of the earth I think you should ACK/merge patches for
these too, but deal with it when it happens.

> @linus: I'll send my patches to Greg if you agree on this.

We are in agreement.

Yours,
Linus Walleij


From srinivas.kandagatla at linaro.org  Wed May 18 07:36:38 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Wed, 18 May 2016 15:36:38 +0100
Subject: [PATCH v3 0/2] nvmem: remove regmap dependency
In-Reply-To: <573C7C69.1050301@i2se.com>
References: <1462214174-469-1-git-send-email-srinivas.kandagatla@linaro.org>
 <573C7C69.1050301@i2se.com>
Message-ID: <573C7DF6.6020105@linaro.org>



On 18/05/16 15:30, Stefan Wahren wrote:
> Hi Srinivas,
>
> Am 02.05.2016 um 20:36 schrieb Srinivas Kandagatla:
>> Hi Greg,
>>
>> This is v3 patchset for the leftover 2 patches for nvmem regmap
>> removal series [1]. These patches are based on char-misc tree.
>>
>> nvmem uses regmap_raw_read/write apis to read/write data from providers,
>> With recent patch 922a9f936e40 ("regmap: mmio: Convert to regmap_bus
>> and fix accessor usage") nvmem providers based on regmap-mmio stopped
>> working, as nvmem core was using raw accessors.
>> This issue can be fixed temporarly by moving to other regmap apis,
>> but we might hit same issue in future, and regmap looks like an
>> overdo for nvmem. Moving to interfaces based on read/write callbacks
>> from providers would be more robust.
>
> i noticed that Documentation/nvmem/nvmem.txt also needs a fix after
> removing regmap dependency.

Thanks Stefan for reporting this, I will send a patch to fix that too.

--srini
>
>


From linux at roeck-us.net  Wed May 18 07:38:39 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Wed, 18 May 2016 07:38:39 -0700
Subject: [PATCH omap v2 0/6] Fix OMAP uses of RCU from idle loop
In-Reply-To: <20160516184844.GA20144@linux.vnet.ibm.com>
References: <20160516184844.GA20144@linux.vnet.ibm.com>
Message-ID: <573C7E6F.90001@roeck-us.net>

On 05/16/2016 11:48 AM, Paul E. McKenney wrote:
> Hello!
>
> The following series fixes a number of uses of RCU from the idle loop.
> These are all due to tracing, so the fix is simply to append _rcuidle
> to the event-tracing call.
>
> Changes since v1: Fix commit-log subjects and add maintainers on CC.
>

For the series, on top of mainline (which now experiences the problem fixed
by this series):

Tested-by: Guenter Roeck <linux at roeck-us.net>

Guenter



From wxt at rock-chips.com  Wed May 18 07:41:50 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 18 May 2016 22:41:50 +0800
Subject: [PATCH] arm64: dts: rockchip: fixes the gic400 2nd region size for
 rk3368
Message-ID: <1463582510-29156-1-git-send-email-wxt@rock-chips.com>

The 2nd additional region is the GIC virtual cpu interface register
base and size.

As the gic400 of rk3368 says, the cpu interface register map as below

:

-0x0000 GICC_CTRL
.
.
.
-0x00fc GICC_IIDR
-0x1000 GICC_IDR

Obviously, the region size should be greater than 0x1000.
So we should make sure to include the GICC_IDR since the kernel will access
it in some cases.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-rockchip at lists.infradead.org

---

 arch/arm64/boot/dts/rockchip/rk3368.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
index 8b4a7c9..080203e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
@@ -670,7 +670,7 @@
 		#address-cells = <0>;
 
 		reg = <0x0 0xffb71000 0x0 0x1000>,
-		      <0x0 0xffb72000 0x0 0x1000>,
+		      <0x0 0xffb72000 0x0 0x2000>,
 		      <0x0 0xffb74000 0x0 0x2000>,
 		      <0x0 0xffb76000 0x0 0x2000>;
 		interrupts = <GIC_PPI 9
-- 
2.7.4



From stern at rowland.harvard.edu  Wed May 18 07:56:39 2016
From: stern at rowland.harvard.edu (Alan Stern)
Date: Wed, 18 May 2016 10:56:39 -0400 (EDT)
Subject: [PATCH] usb: echi-hcd: Add register access check in shutdown
In-Reply-To: <1463580747-20868-1-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <Pine.LNX.4.44L0.1605181044460.1981-100000@iolanthe.rowland.org>

On Wed, 18 May 2016, Srinivas Kandagatla wrote:

> This patch adds a check in ehci_shutdown(), to make sure
> that the register access is available before accessing registers.
> 
> The use case is simple, for boards like DB410c where the usb host
> or device functionality is decided based on the micro-usb cable
> presence. If the board boots up with micro-usb connected and the
> host driver is probed, but the ehci_setup() has not been done yet,
> then a system shutdown would trigger below NULL pointer exception
> without this patch.

How can that happen?  While the host driver is probed, the probing
thread holds the device lock.  But the system shutdown routine acquires
the device lock before invoking the ->shutdown callback.  Therefore the 
two things cannot happen concurrently.

> Unable to handle kernel NULL pointer dereference at virtual address
> 00000008

...

> --- a/drivers/usb/host/ehci-hcd.c
> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -368,6 +368,9 @@ static void ehci_shutdown(struct usb_hcd *hcd)
>  {
>  	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
>  
> +	if (!HCD_HW_ACCESSIBLE(hcd))
> +		return;
> +
>  	spin_lock_irq(&ehci->lock);
>  	ehci->shutdown = true;
>  	ehci->rh_state = EHCI_RH_STOPPING;

This doesn't seem like the right place.  What you really should do is
skip calling ehci_silence_controller() if the hardware isn't
accessible.  That's where the hardware gets touched, not in
ehci_shutdown().

Alan Stern



From carlo at caione.org  Wed May 18 07:56:21 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 18 May 2016 16:56:21 +0200
Subject: [PATCH v2 3/4] ARM64: dts: amlogic: gxbb: Enable secure monitor
In-Reply-To: <1463583382-15614-1-git-send-email-carlo@caione.org>
References: <1463583382-15614-1-git-send-email-carlo@caione.org>
Message-ID: <1463583382-15614-4-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add the secure monitor node in the Amlogic Meson GXBB DTSI file to
enable it.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 76b3b6d..003e298 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -44,6 +44,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/gpio/meson-gxbb-gpio.h>
+#include <dt-bindings/soc/meson-gxbb-sm.h>
 
 / {
 	compatible = "amlogic,meson-gxbb";
@@ -98,6 +99,12 @@
 		method = "smc";
 	};
 
+	sm {
+		compatible = "amlogic,meson-sm";
+		amlogic,sm_cmd_input_base = <SM_GET_SHARE_MEM_INPUT_BASE>;
+		amlogic,sm_cmd_output_base = <SM_GET_SHARE_MEM_OUTPUT_BASE>;
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13
-- 
2.7.4



From carlo at caione.org  Wed May 18 07:56:18 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 18 May 2016 16:56:18 +0200
Subject: [PATCH v2 0/4] Add Amlogic secure monitor driver
Message-ID: <1463583382-15614-1-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

In the Amlogic SoCs the secure monitor calls are used for a lot of reasons:
interact with the NVMEM (efuses), check the reboot reason, set USB boot, ...

This driver defines a generic interface towards the secure monitor that can be
used by more specialized drivers to interact with the secure monitor itself
without worrying about bounce buffers managing.

Changelog:

v2:
  * All the SMC function identifiers are now in a SoC-specific header file to
    be included by the DTS files so the SMC commands are now defined in the DT
    instead to be hardcoded into the driver
  * Patchset is no longer an RFC
  * Better error management and boundary checking
  * s/unsigned int/u32/
  * SMC call not only on CPU 0
  * Fix memory leaking
  * s/amlogic/meson/ in the directory names

Carlo Caione (4):
  soc: Amlogic: Add secure monitor driver
  soc: dt-bindings: Add secure monitor header file for GXBB
  ARM64: dts: amlogic: gxbb: Enable secure monitor
  documentation: Add secure monitor binding documentation

 .../devicetree/bindings/soc/meson/meson_sm.txt     |  45 ++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   7 +
 drivers/soc/Kconfig                                |   1 +
 drivers/soc/Makefile                               |   1 +
 drivers/soc/meson/Kconfig                          |   8 ++
 drivers/soc/meson/Makefile                         |   1 +
 drivers/soc/meson/meson_sm.c                       | 155 +++++++++++++++++++++
 include/dt-bindings/soc/meson-gxbb-sm.h            |  44 ++++++
 include/linux/soc/meson/meson_sm.h                 |  22 +++
 9 files changed, 284 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/meson/meson_sm.txt
 create mode 100644 drivers/soc/meson/Kconfig
 create mode 100644 drivers/soc/meson/Makefile
 create mode 100644 drivers/soc/meson/meson_sm.c
 create mode 100644 include/dt-bindings/soc/meson-gxbb-sm.h
 create mode 100644 include/linux/soc/meson/meson_sm.h

-- 
2.7.4



From carlo at caione.org  Wed May 18 07:56:20 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 18 May 2016 16:56:20 +0200
Subject: [PATCH v2 2/4] soc: dt-bindings: Add secure monitor header file for
 GXBB
In-Reply-To: <1463583382-15614-1-git-send-email-carlo@caione.org>
References: <1463583382-15614-1-git-send-email-carlo@caione.org>
Message-ID: <1463583382-15614-3-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

This patch adds the header file describing all the SMC function
identifiers for the Amlogic Meson GXBB SoC.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 include/dt-bindings/soc/meson-gxbb-sm.h | 44 +++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)
 create mode 100644 include/dt-bindings/soc/meson-gxbb-sm.h

diff --git a/include/dt-bindings/soc/meson-gxbb-sm.h b/include/dt-bindings/soc/meson-gxbb-sm.h
new file mode 100644
index 0000000..b7d02df
--- /dev/null
+++ b/include/dt-bindings/soc/meson-gxbb-sm.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MESON_SM_GXBB_H_
+#define _MESON_SM_GXBB_H_
+
+#define SM_GET_SHARE_MEM_INPUT_BASE		0x82000020
+#define SM_GET_SHARE_MEM_OUTPUT_BASE		0x82000021
+#define SM_GET_REBOOT_REASON			0x82000022
+#define SM_GET_SHARE_STORAGE_IN_BASE		0x82000023
+#define SM_GET_SHARE_STORAGE_OUT_BASE		0x82000024
+#define SM_GET_SHARE_STORAGE_BLOCK_BASE		0x82000025
+#define SM_GET_SHARE_STORAGE_MESSAGE_BASE	0x82000026
+#define SM_GET_SHARE_STORAGE_BLOCK_SIZE		0x82000027
+#define SM_EFUSE_READ				0x82000030
+#define SM_EFUSE_WRITE				0x82000031
+#define SM_EFUSE_WRITE_PATTERN			0x82000032
+#define SM_EFUSE_USER_MAX			0x82000033
+#define SM_JTAG_ON				0x82000040
+#define SM_JTAG_OFF				0x82000041
+#define SM_SET_USB_BOOT_FUNC			0x82000043
+#define SM_SECURITY_KEY_QUERY			0x82000060
+#define SM_SECURITY_KEY_READ			0x82000061
+#define SM_SECURITY_KEY_WRITE			0x82000062
+#define SM_SECURITY_KEY_TELL			0x82000063
+#define SM_SECURITY_KEY_VERIFY			0x82000064
+#define SM_SECURITY_KEY_STATUS			0x82000065
+#define SM_SECURITY_KEY_NOTIFY			0x82000066
+#define SM_SECURITY_KEY_LIST			0x82000067
+#define SM_SECURITY_KEY_REMOVE			0x82000068
+#define SM_DEBUG_EFUSE_WRITE_PATTERN		0x820000F0
+#define SM_DEBUG_EFUSE_READ_PATTERN		0x820000F1
+#define SM_AML_DATA_PROCESS			0x820000FF
+
+#endif /* _MESON_SM_GXBB_H_ */
-- 
2.7.4



From carlo at caione.org  Wed May 18 07:56:19 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 18 May 2016 16:56:19 +0200
Subject: [PATCH v2 1/4] soc: Amlogic: Add secure monitor driver
In-Reply-To: <1463583382-15614-1-git-send-email-carlo@caione.org>
References: <1463583382-15614-1-git-send-email-carlo@caione.org>
Message-ID: <1463583382-15614-2-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Introduce a driver to provide calls into secure monitor mode.

In the Amlogic SoCs these calls are used for multiple reasons: access to
NVMEM, set USB boot, enable JTAG, etc...

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 drivers/soc/Kconfig                |   1 +
 drivers/soc/Makefile               |   1 +
 drivers/soc/meson/Kconfig          |   8 ++
 drivers/soc/meson/Makefile         |   1 +
 drivers/soc/meson/meson_sm.c       | 155 +++++++++++++++++++++++++++++++++++++
 include/linux/soc/meson/meson_sm.h |  22 ++++++
 6 files changed, 188 insertions(+)
 create mode 100644 drivers/soc/meson/Kconfig
 create mode 100644 drivers/soc/meson/Makefile
 create mode 100644 drivers/soc/meson/meson_sm.c
 create mode 100644 include/linux/soc/meson/meson_sm.h

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cb58ef0..7e70b52 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -4,6 +4,7 @@ source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/brcmstb/Kconfig"
 source "drivers/soc/fsl/qe/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
+source "drivers/soc/meson/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/rockchip/Kconfig"
 source "drivers/soc/samsung/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 5ade713..9024d2b 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_ARCH_DOVE)		+= dove/
 obj-$(CONFIG_MACH_DOVE)		+= dove/
 obj-y				+= fsl/
 obj-$(CONFIG_ARCH_MEDIATEK)	+= mediatek/
+obj-$(CONFIG_ARCH_MESON)	+= meson/
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
 obj-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip/
 obj-$(CONFIG_SOC_SAMSUNG)	+= samsung/
diff --git a/drivers/soc/meson/Kconfig b/drivers/soc/meson/Kconfig
new file mode 100644
index 0000000..fff11a3
--- /dev/null
+++ b/drivers/soc/meson/Kconfig
@@ -0,0 +1,8 @@
+#
+# Amlogic Secure Monitor driver
+#
+config MESON_SM
+	bool
+	default ARCH_MESON
+	help
+	  Say y here to enable the Amlogic secure monitor driver
diff --git a/drivers/soc/meson/Makefile b/drivers/soc/meson/Makefile
new file mode 100644
index 0000000..9ab3884
--- /dev/null
+++ b/drivers/soc/meson/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MESON_SM) +=	meson_sm.o
diff --git a/drivers/soc/meson/meson_sm.c b/drivers/soc/meson/meson_sm.c
new file mode 100644
index 0000000..16f7e32
--- /dev/null
+++ b/drivers/soc/meson/meson_sm.c
@@ -0,0 +1,155 @@
+/*
+ * Amlogic Secure Monitor driver
+ *
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <stdarg.h>
+#include <asm/cacheflush.h>
+#include <asm/compiler.h>
+#include <linux/arm-smccc.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/smp.h>
+
+#include <linux/soc/meson/meson_sm.h>
+
+#define SM_MEM_SIZE	0x1000
+
+/*
+ * To read from / write to the secure monitor we use two bounce buffers. The
+ * physical addresses of the two buffers are obtained by querying the secure
+ * monitor itself.
+ */
+
+static u32 sm_phy_in_base;
+static u32 sm_phy_out_base;
+
+static void __iomem *sm_sharemem_in_base;
+static void __iomem *sm_sharemem_out_base;
+
+struct meson_sm_data {
+	u32 cmd;
+	u32 arg0;
+	u32 arg1;
+	u32 arg2;
+	u32 arg3;
+	u32 arg4;
+	u32 ret;
+};
+
+static void __meson_sm_call(void *info)
+{
+	struct meson_sm_data *data = info;
+	struct arm_smccc_res res;
+
+	arm_smccc_smc(data->cmd,
+		      data->arg0, data->arg1, data->arg2,
+		      data->arg3, data->arg4, 0, 0, &res);
+	data->ret = res.a0;
+}
+
+u32 meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	struct meson_sm_data data;
+
+	data.cmd = cmd;
+	data.arg0 = arg0;
+	data.arg1 = arg1;
+	data.arg2 = arg2;
+	data.arg3 = arg3;
+	data.arg4 = arg4;
+	data.ret = 0;
+
+	__meson_sm_call(&data);
+
+	return data.ret;
+}
+
+u32 meson_sm_call_read(void *buffer, u32 cmd, u32 arg0, u32 arg1,
+		       u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 size;
+
+	size = meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
+
+	if (!size || size > SM_MEM_SIZE)
+		return -EINVAL;
+
+	memcpy(buffer, sm_sharemem_out_base, size);
+	return size;
+}
+
+u32 meson_sm_call_write(void *buffer, unsigned int b_size, u32 cmd, u32 arg0,
+			u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 size;
+
+	if (b_size > SM_MEM_SIZE)
+		return -EINVAL;
+
+	memcpy(sm_sharemem_in_base, buffer, b_size);
+
+	size = meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
+
+	if (!size)
+		return -EINVAL;
+
+	return size;
+}
+
+static int meson_sm_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int cmd_in, cmd_out;
+
+	if (of_property_read_u32(np, "amlogic,sm_cmd_input_base", &cmd_in))
+		return -EINVAL;
+
+	if (of_property_read_u32(np, "amlogic,sm_cmd_output_base", &cmd_out))
+		return -EINVAL;
+
+	sm_phy_in_base = meson_sm_call(cmd_in, 0, 0, 0, 0, 0);
+	sm_sharemem_in_base = ioremap_cache(sm_phy_in_base, SM_MEM_SIZE);
+	if (!sm_sharemem_in_base)
+		return -EINVAL;
+
+	sm_phy_out_base = meson_sm_call(cmd_out, 0, 0, 0, 0, 0);
+	sm_sharemem_out_base = ioremap_cache(sm_phy_out_base, SM_MEM_SIZE);
+	if (!sm_sharemem_out_base) {
+		iounmap(sm_sharemem_in_base);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id meson_sm_ids[] = {
+	{ .compatible = "amlogic,meson-sm" },
+	{ /* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, meson_sm_ids);
+
+static struct platform_driver meson_sm_platform_driver = {
+	.probe	= meson_sm_probe,
+	.driver	= {
+		.name		= "secmon",
+		.of_match_table	= meson_sm_ids,
+	},
+};
+module_platform_driver(meson_sm_platform_driver);
+
+MODULE_AUTHOR("Carlo Caione <carlo at endlessm.com>");
+MODULE_DESCRIPTION("Amlogic secure monitor driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/soc/meson/meson_sm.h b/include/linux/soc/meson/meson_sm.h
new file mode 100644
index 0000000..6ff8317
--- /dev/null
+++ b/include/linux/soc/meson/meson_sm.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MESON_SM_H_
+#define _MESON_SM_H_
+
+u32 meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
+u32 meson_sm_call_read(void *buffer, u32 cmd, u32 arg0, u32 arg1, u32 arg2,
+		       u32 arg3, u32 arg4);
+u32 meson_sm_call_write(void *buffer, unsigned int b_size, u32 cmd, u32 arg0,
+			u32 arg1, u32 arg2, u32 arg3, u32 arg4);
+
+#endif /* _MESON_SM_H_ */
-- 
2.7.4



From carlo at caione.org  Wed May 18 07:56:22 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 18 May 2016 16:56:22 +0200
Subject: [PATCH v2 4/4] documentation: Add secure monitor binding documentation
In-Reply-To: <1463583382-15614-1-git-send-email-carlo@caione.org>
References: <1463583382-15614-1-git-send-email-carlo@caione.org>
Message-ID: <1463583382-15614-5-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add the binding documentation for the Amlogic secure monitor driver.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 .../devicetree/bindings/soc/meson/meson_sm.txt     | 45 ++++++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/meson/meson_sm.txt

diff --git a/Documentation/devicetree/bindings/soc/meson/meson_sm.txt b/Documentation/devicetree/bindings/soc/meson/meson_sm.txt
new file mode 100644
index 0000000..f59c732
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/meson/meson_sm.txt
@@ -0,0 +1,45 @@
+* Amlogic Secure Monitor
+
+In the Amlogic SoCs the Secure Monitor code is used to provide access to the
+NVMEM, enable JTAG, set USB boot, etc...
+
+Required properties for the secure monitor node:
+- compatible: Should be "amlogic,meson-sm"
+- amlogic,sm_cmd_input_base: SMC32 function identifier to read the physical
+                             address of the input buffer
+- amlogic,sm_cmd_output_base: SMC32 function identifier to read the physical
+                              address of the output buffer
+
+Example:
+
+	#include <dt-bindings/soc/meson-gxbb-sm.h>
+
+	...
+
+	sm {
+		compatible = "amlogic,meson-sm";
+		amlogic,sm_cmd_input_base = <SM_GET_SHARE_MEM_INPUT_BASE>;
+		amlogic,sm_cmd_output_base = <SM_GET_SHARE_MEM_OUTPUT_BASE>;
+	};
+
+Node of a device using the secure monitor must have a custom property to
+specify the SMC32 function the driver is going to use. The values of all the
+SMC function identifiers are listed in a SoC-specific header file:
+
+"include/dt-bindings/soc/meson-gxbb-sm.h" - for the Meson GXBB secure monitor.
+
+Example of the node using the secure monitor:
+
+	#include <dt-bindings/soc/meson-gxbb-sm.h>
+
+	...
+
+	efuse: efuse {
+		compatible = "amlogic,meson-gxbb-efuse";
+		amlogic,sm_cmd_read_efuse = <SM_EFUSE_READ>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		...
+	};
+
-- 
2.7.4



From k.kozlowski at samsung.com  Wed May 18 08:01:22 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 18 May 2016 17:01:22 +0200
Subject: [PATCH] ARM: samsung: improve static dma_mask definition
In-Reply-To: <1463042333-281444-1-git-send-email-arnd@arndb.de>
References: <1463042333-281444-1-git-send-email-arnd@arndb.de>
Message-ID: <573C83C2.5090203@samsung.com>

On 05/12/2016 10:38 AM, Arnd Bergmann wrote:
> When no DMA master devices are part of the kernel configuration,
> we get a warning about the unused dma mask definition:
> 
> arch/arm/plat-samsung/devs.c:71:12: error: 'samsung_device_dma_mask' defined but not used [-Werror=unused-variable]
>  static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
> 
> We could simply mark this as __maybe_unused to shut up that warning,
> but a nicer solution seems to be to have a separate mask for each
> device. The advantage is that a driver that happens to call
> dma_set_mask() on one device doesn't implicitly change the mask
> for the other devices as well. This is more of a theoretical
> problem, as obviously nothing does it for the devices in this
> file (or they would have always been broken), but it feels
> cleaner that way.
> 
> The definition works by creating an array in place so we can take
> the address of it and let the compiler generate a hidden symbol
> for it at compile time.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> ---
>  arch/arm/plat-samsung/devs.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Thanks, although does not look as critical fix but less warnings makes
spotting right issues faster so applied for v4.7.

Best regards,
Krzysztof


From k.kozlowski at samsung.com  Wed May 18 08:01:50 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 18 May 2016 17:01:50 +0200
Subject: [PATCH] ARM: exynos: don't select keyboard driver
In-Reply-To: <1463581102-1007639-1-git-send-email-arnd@arndb.de>
References: <1463581102-1007639-1-git-send-email-arnd@arndb.de>
Message-ID: <573C83DE.60106@samsung.com>

On 05/18/2016 04:17 PM, Arnd Bergmann wrote:
> The samsung-keypad driver is implicitly selected by ARCH_EXYNOS4 (why?),
> but this fails if CONFIG_INPUT is a loadable module:
> 
> drivers/input/built-in.o: In function `samsung_keypad_remove':
> drivers/input/keyboard/samsung-keypad.c:461: undefined reference to `input_unregister_device'
> drivers/input/built-in.o: In function `samsung_keypad_irq':
> drivers/input/keyboard/samsung-keypad.c:137: undefined reference to `input_event'
> drivers/input/built-in.o: In function `samsung_keypad_irq':
> include/linux/input.h:389: undefined reference to `input_event'
> drivers/input/built-in.o: In function `samsung_keypad_probe':
> drivers/input/keyboard/samsung-keypad.c:358: undefined reference to `devm_input_allocate_device'
> drivers/input/built-in.o:(.debug_addr+0x34): undefined reference to `input_set_capability'
> 
> This removes the 'select' as suggested by Krzysztof Kozlowski and
> instead enables the driver from the defconfig files.
> 
> The problem does not happen on mainline kernels, as we don't normally
> build built-in input drivers when CONFIG_INPUT=m, but I am experimenting
> with a patch to change this, and the samsung keypad driver showed up
> as one example that was silently broken before.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Link: https://lkml.org/lkml/2016/2/14/55
> ---
>  arch/arm/configs/exynos_defconfig   | 1 +
>  arch/arm/configs/multi_v7_defconfig | 1 +
>  arch/arm/mach-exynos/Kconfig        | 1 -
>  3 files changed, 2 insertions(+), 1 deletion(-)

Thanks for update.

Applied for v4.7 (same reason as in plat-samsung/devs.c).

Best regards,
Krzysztof



From christoffer.dall at linaro.org  Wed May 18 08:12:23 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 17:12:23 +0200
Subject: [PATCH v4 46/56] KVM: arm/arm64: vgic-new: Add userland access
 to VGIC dist registers
In-Reply-To: <573C76D2.3050906@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-47-git-send-email-andre.przywara@arm.com>
 <20160518135724.GO3827@cbox> <573C76D2.3050906@arm.com>
Message-ID: <20160518151223.GK6666@cbox>

On Wed, May 18, 2016 at 03:06:10PM +0100, Andre Przywara wrote:
> Hi,
> 
> On 18/05/16 14:57, Christoffer Dall wrote:
> > On Mon, May 16, 2016 at 10:53:34AM +0100, Andre Przywara wrote:
> >> Userland may want to save and restore the state of the in-kernel VGIC,
> >> so we provide the code which takes a userland request and translate
> >> that into calls to our MMIO framework.
> >>
> >> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >> ---
> >>  virt/kvm/arm/vgic/vgic-kvm-device.c | 50 ++++++++++++++++++++++++++++++++++++-
> >>  1 file changed, 49 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> >> index 78621283..c3ec453 100644
> >> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> >> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> >> @@ -238,7 +238,55 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
> >>  				 struct kvm_device_attr *attr,
> >>  				 u32 *reg, bool is_write)
> >>  {
> >> -	return -ENXIO;
> >> +	gpa_t addr;
> >> +	int cpuid, ret, c;
> >> +	struct kvm_vcpu *vcpu, *tmp_vcpu;
> >> +
> >> +	cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
> >> +		 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
> >> +	vcpu = kvm_get_vcpu(dev->kvm, cpuid);
> >> +	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
> >> +
> >> +	mutex_lock(&dev->kvm->lock);
> >> +
> >> +	ret = vgic_init(dev->kvm);
> >> +	if (ret)
> >> +		goto out;
> >> +
> >> +	if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
> >> +		ret = -EINVAL;
> >> +		goto out;
> >> +	}
> >> +
> >> +	/*
> >> +	 * Ensure that no other VCPU is running by checking the vcpu->cpu
> >> +	 * field.  If no other VPCUs are running we can safely access the VGIC
> >> +	 * state, because even if another VPU is run after this point, that
> >> +	 * VCPU will not touch the vgic state, because it will block on
> >> +	 * getting the vgic->lock in kvm_vgic_sync_hwstate().
> >> +	 */
> > 
> > We still have a problem here.  Want me to write a patch?
> 
> Aargh, this somehow got lost in my pile of "comments to address", sorry!
> Short answer: yes, please.
> Last thing I did was following your suggestion from last time about
> refactoring the check from kvm_vgic_create(): I think this doesn't help,
> because it's only a check and we return -EBUSY or so instead of actually
> enforcing VCPUs to exit. So if you could try to use your fancy new
> make-the-guest-exit feature here?
> 
Am I missing something completely or why doesn't this work:

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 237d753..0130c4b 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -241,6 +241,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 	gpa_t addr;
 	int cpuid, ret, c;
 	struct kvm_vcpu *vcpu, *tmp_vcpu;
+	int vcpu_lock_idx = -1;
 
 	cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
 		 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
@@ -259,17 +260,16 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 	}
 
 	/*
-	 * Ensure that no other VCPU is running by checking the vcpu->cpu
-	 * field.  If no other VPCUs are running we can safely access the VGIC
-	 * state, because even if another VPU is run after this point, that
-	 * VCPU will not touch the vgic state, because it will block on
-	 * getting the vgic->lock in kvm_vgic_sync_hwstate().
+	 * Any time a vcpu is run, vcpu_load is called which tries to grab the
+	 * vcpu->mutex.  By grabbing the vcpu->mutex of all VCPUs we ensure
+	 * that no other VCPUs are run and fiddle with the vgic state while we
+	 * access it.
 	 */
+	ret = -EBUSY;
 	kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm) {
-		if (unlikely(tmp_vcpu->cpu != -1)) {
-			ret = -EBUSY;
+		if (!mutex_trylock(&tmp_vcpu->mutex))
 			goto out;
-		}
+		vcpu_lock_idx = c;
 	}
 
 	switch (attr->group) {
@@ -285,6 +285,11 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 	}
 
 out:
+	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
+		tmp_vcpu = kvm_get_vcpu(dev->kvm, vcpu_lock_idx);
+		mutex_unlock(&tmp_vcpu->mutex);
+	}
+
 	mutex_unlock(&dev->kvm->lock);
 	return ret;
 }


Thanks,
-Christoffer


From aleksey.makarov at linaro.org  Wed May 18 08:11:34 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Wed, 18 May 2016 18:11:34 +0300
Subject: [PATCH 3/3] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
In-Reply-To: <20160517124629.GE14955@leverpostej>
References: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
 <1463486765-31827-4-git-send-email-aleksey.makarov@linaro.org>
 <20160517124629.GE14955@leverpostej>
Message-ID: <b1a9ef97-618c-064c-7968-900c96fb7e27@linaro.org>



On 05/17/2016 03:46 PM, Mark Rutland wrote:
> On Tue, May 17, 2016 at 03:06:03PM +0300, Aleksey Makarov wrote:

[...]

>> diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
>> index feab2ee..1d5e24f 100644
>> --- a/arch/arm64/kernel/setup.c
>> +++ b/arch/arm64/kernel/setup.c
>> @@ -261,11 +261,13 @@ void __init setup_arch(char **cmdline_p)
>>  	efi_init();
>>  	arm64_memblock_init();
>>  
>> +	paging_init();
>> +
>> +	early_initrd_acpi_init();
> 
> Do we actually need full paging up here?
> 
> Why can we not use fixmap based copying as we do for the other cases
> prior to paging_init?

The implementation of the feature acpi_table_initrd_init()
(drivers/acpi/tables.c) works with initrd data represented as an array
in virtual memory.  It uses some library utility to find the redefined
tables in that array and iterates over it to copy the data to new
allocated memory.  So we need to rewrite it considerably to access the
initrd data via fixmap.

In x86 arch, linear kernel memory is already mapped by the time when
early_initrd_acpi_init() and acpi_boot_table_init() are called so I
think that we can just move this mapping one function earlier too.

Is it ok?

I will address your other comments in the next version of the patchset.

Thank you
Aleksey Makarov

>> +
>>  	/* Parse the ACPI tables for possible boot-time configuration */
>>  	acpi_boot_table_init();
>>  
>> -	paging_init();
>> -
>>  	if (acpi_disabled)
>>  		unflatten_device_tree();
>>  
>> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
>> index c204344..ec694c0 100644
>> --- a/drivers/acpi/Kconfig
>> +++ b/drivers/acpi/Kconfig
>> @@ -313,7 +313,7 @@ config ACPI_CUSTOM_DSDT
>>  
>>  config ACPI_TABLE_UPGRADE
>>  	bool "Allow upgrading ACPI tables via initrd"
>> -	depends on BLK_DEV_INITRD && X86
>> +	depends on BLK_DEV_INITRD && (X86 || ARM64)
>>  	default y
>>  	help
> 
> Perhaps ARCH_HAS_ACPI_TABLE_UPGRADE?
> 
>>  	  This option provides functionality to upgrade arbitrary ACPI tables
>> diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
>> index 82be84a..c35034d8 100644
>> --- a/drivers/acpi/tables.c
>> +++ b/drivers/acpi/tables.c
>> @@ -482,6 +482,14 @@ static DECLARE_BITMAP(acpi_initrd_installed, NR_ACPI_INITRD_TABLES);
>>  
>>  #define MAP_CHUNK_SIZE   (NR_FIX_BTMAPS << PAGE_SHIFT)
>>  
>> +#if defined(CONFIG_X86)
>> +#define MAX_PHYS_ACPI_TABLES (max_low_pfn_mapped << PAGE_SHIFT)
>> +#elif defined(CONFIG_ARM64)
>> +#define MAX_PHYS_ACPI_TABLES PFN_PHYS(max_pfn)
>> +#else
>> +#error "MAX_PHYS_ACPI_TABLES is not defiend for this architecture"
>> +#endif
> 
> s/defiend/defined/
> 
> This should be defined in an arch-specific header if it is actually
> arch-specific.
> 
> Thanks,
> Mark.
> 
>> +
>>  static void __init acpi_table_initrd_init(void *data, size_t size)
>>  {
>>  	int sig, no, table_nr = 0, total_offset = 0;
>> @@ -541,7 +549,7 @@ static void __init acpi_table_initrd_init(void *data, size_t size)
>>  		return;
>>  
>>  	acpi_tables_addr =
>> -		memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
>> +		memblock_find_in_range(0, MAX_PHYS_ACPI_TABLES,
>>  				       all_tables_size, PAGE_SIZE);
>>  	if (!acpi_tables_addr) {
>>  		WARN_ON(1);
>> -- 
>> 2.8.2
>>


From catalin.marinas at arm.com  Wed May 18 08:19:58 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 18 May 2016 16:19:58 +0100
Subject: [PATCH v2] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <573C7D64.5040206@suse.de>
References: <1463576010-115428-1-git-send-email-agraf@suse.de>
 <20160518132741.GE22378@e104818-lin.cambridge.arm.com>
 <573C72DD.6010400@suse.de>
 <20160518142620.GA22354@localhost.localdomain>
 <573C7D64.5040206@suse.de>
Message-ID: <20160518151958.GH22378@e104818-lin.cambridge.arm.com>

On Wed, May 18, 2016 at 04:34:12PM +0200, Alexander Graf wrote:
> On 05/18/2016 04:26 PM, Catalin Marinas wrote:
> >On Wed, May 18, 2016 at 03:49:17PM +0200, Alexander Graf wrote:
> >>On 05/18/2016 03:27 PM, Catalin Marinas wrote:
> >>>On Wed, May 18, 2016 at 02:53:30PM +0200, Alexander Graf wrote:
> >>>>On arm64, all SoCs we supported so far either have an IOMMU or have bus
> >>>>addresses equal to CPU addresses.
> >>>>
> >>>>However, with the Raspberry Pi 3 coming up, this is no longer true. To
> >>>>allow DMA to work with an AArch64 kernel on those devices, let's allow
> >>>>devices to have DMA offsets again.
> >>>>
> >>>>Signed-off-by: Alexander Graf <agraf at suse.de>
> >>>We were aware about this issue but we've been waiting for an actual use
> >>>case. I'll queue this for 4.8 (given that RPi3 is not supported by the
> >>>arm64 kernel, I don't see the rush to merge it earlier).
> >>Sure, works for me. That way Eric can try to push the other few bits
> >>necessary to run an arm64 kernel on the RPi3 towards 4.8 as well :).
> >As long as the firmware is PSCI capable ;)
> 
> So spin tables won't work for you?

They only work for booting, not cpuidle or hotplug.

> IIRC we don't own EL3 on there.

Then how do you switch to AArch64?

-- 
Catalin


From slash.tmp at free.fr  Wed May 18 08:24:51 2016
From: slash.tmp at free.fr (Mason)
Date: Wed, 18 May 2016 17:24:51 +0200
Subject: [PATCH v2 omap 3/6] arm: Add _rcuidle tracepoints to allow
 clk_core_disable() use from idle
In-Reply-To: <1463424608-20237-3-git-send-email-paulmck@linux.vnet.ibm.com>
References: <20160516184844.GA20144@linux.vnet.ibm.com>
 <1463424608-20237-3-git-send-email-paulmck@linux.vnet.ibm.com>
Message-ID: <573C8943.6090104@free.fr>

On 16/05/2016 20:50, Paul E. McKenney wrote:

>> stack backtrace:
>> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1114
>> Hardware name: Generic OMAP36xx (Flattened Device Tree)
>> [<c0110290>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
>> [<c010c3a8>] (show_stack) from [<c047fd68>] (dump_stack+0xb0/0xe4)
>> [<c047fd68>] (dump_stack) from [<c0631618>] (clk_core_disable+0x17c/0x348)
>> [<c0631618>] (clk_core_disable) from [<c0632774>] (clk_disable+0x24/0x30)
>> [<c0632774>] (clk_disable) from [<c0120590>] (_disable_clocks+0x18/0x7c)
>> [<c0120590>] (_disable_clocks) from [<c0121680>] (_idle+0x12c/0x230)
>> [<c0121680>] (_idle) from [<c0121b4c>] (omap_hwmod_idle+0x24/0x44)
>> [<c0121b4c>] (omap_hwmod_idle) from [<c0122c24>] (omap_device_idle+0x3c/0x90)
>> [<c0122c24>] (omap_device_idle) from [<c052cc00>] (__rpm_callback+0x2c/0x60)
>> [<c052cc00>] (__rpm_callback) from [<c052cc54>] (rpm_callback+0x20/0x80)
>> [<c052cc54>] (rpm_callback) from [<c052d150>] (rpm_suspend+0x100/0x768)
>> [<c052d150>] (rpm_suspend) from [<c052ec58>] (__pm_runtime_suspend+0x64/0x84)
>> [<c052ec58>] (__pm_runtime_suspend) from [<c04bf25c>] (omap2_gpio_prepare_for_idle+0x5
>> c/0x70)
>> [<c04bf25c>] (omap2_gpio_prepare_for_idle) from [<c0125568>] (omap_sram_idle+0x140/0x2
>> 44)

Wouldn't the stack trace look better without the word wrap?  :-)

Regards.


From srinivas.kandagatla at linaro.org  Wed May 18 08:33:20 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Wed, 18 May 2016 16:33:20 +0100
Subject: [PATCH] usb: echi-hcd: Add register access check in shutdown
In-Reply-To: <Pine.LNX.4.44L0.1605181044460.1981-100000@iolanthe.rowland.org>
References: <Pine.LNX.4.44L0.1605181044460.1981-100000@iolanthe.rowland.org>
Message-ID: <573C8B40.1040503@linaro.org>



On 18/05/16 15:56, Alan Stern wrote:
> On Wed, 18 May 2016, Srinivas Kandagatla wrote:
>
>> This patch adds a check in ehci_shutdown(), to make sure
>> that the register access is available before accessing registers.
>>
>> The use case is simple, for boards like DB410c where the usb host
>> or device functionality is decided based on the micro-usb cable
>> presence. If the board boots up with micro-usb connected and the
>> host driver is probed, but the ehci_setup() has not been done yet,
>> then a system shutdown would trigger below NULL pointer exception
>> without this patch.
>
> How can that happen?  While the host driver is probed, the probing
> thread holds the device lock.  But the system shutdown routine acquires
> the device lock before invoking the ->shutdown callback.  Therefore the
> two things cannot happen concurrently.

No, I did not mean them happening concurrently, I mean that the host 
driver is up, however ehci_setup() is not done yet.

Will change the comments if its misleading the reader.

>
>> Unable to handle kernel NULL pointer dereference at virtual address
>> 00000008
>
> ...
>
>> --- a/drivers/usb/host/ehci-hcd.c
>> +++ b/drivers/usb/host/ehci-hcd.c
>> @@ -368,6 +368,9 @@ static void ehci_shutdown(struct usb_hcd *hcd)
>>   {
>>   	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
>>
>> +	if (!HCD_HW_ACCESSIBLE(hcd))
>> +		return;
>> +
>>   	spin_lock_irq(&ehci->lock);
>>   	ehci->shutdown = true;
>>   	ehci->rh_state = EHCI_RH_STOPPING;
>
> This doesn't seem like the right place.  What you really should do is
> skip calling ehci_silence_controller() if the hardware isn't
> accessible.  That's where the hardware gets touched, not in
> ehci_shutdown().
Yep , that should work as well.

Will send a v2 patch.

thanks,
srini

>
> Alan Stern
>


From agraf at suse.de  Wed May 18 08:33:41 2016
From: agraf at suse.de (Alexander Graf)
Date: Wed, 18 May 2016 17:33:41 +0200
Subject: [PATCH v2] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <20160518151958.GH22378@e104818-lin.cambridge.arm.com>
References: <1463576010-115428-1-git-send-email-agraf@suse.de>
 <20160518132741.GE22378@e104818-lin.cambridge.arm.com>
 <573C72DD.6010400@suse.de> <20160518142620.GA22354@localhost.localdomain>
 <573C7D64.5040206@suse.de>
 <20160518151958.GH22378@e104818-lin.cambridge.arm.com>
Message-ID: <573C8B55.3030805@suse.de>

On 05/18/2016 05:19 PM, Catalin Marinas wrote:
> On Wed, May 18, 2016 at 04:34:12PM +0200, Alexander Graf wrote:
>> On 05/18/2016 04:26 PM, Catalin Marinas wrote:
>>> On Wed, May 18, 2016 at 03:49:17PM +0200, Alexander Graf wrote:
>>>> On 05/18/2016 03:27 PM, Catalin Marinas wrote:
>>>>> On Wed, May 18, 2016 at 02:53:30PM +0200, Alexander Graf wrote:
>>>>>> On arm64, all SoCs we supported so far either have an IOMMU or have bus
>>>>>> addresses equal to CPU addresses.
>>>>>>
>>>>>> However, with the Raspberry Pi 3 coming up, this is no longer true. To
>>>>>> allow DMA to work with an AArch64 kernel on those devices, let's allow
>>>>>> devices to have DMA offsets again.
>>>>>>
>>>>>> Signed-off-by: Alexander Graf <agraf at suse.de>
>>>>> We were aware about this issue but we've been waiting for an actual use
>>>>> case. I'll queue this for 4.8 (given that RPi3 is not supported by the
>>>>> arm64 kernel, I don't see the rush to merge it earlier).
>>>> Sure, works for me. That way Eric can try to push the other few bits
>>>> necessary to run an arm64 kernel on the RPi3 towards 4.8 as well :).
>>> As long as the firmware is PSCI capable ;)
>> So spin tables won't work for you?
> They only work for booting, not cpuidle or hotplug.

Well, booting is a good step forward I'd say :).

>
>> IIRC we don't own EL3 on there.
> Then how do you switch to AArch64?

You write into config.txt that you want to boot into AArch64 EL2 and the 
raspberry pi firmware takes care of the rest.


Alex



From kernel at martin.sperl.org  Wed May 18 08:40:24 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Wed, 18 May 2016 15:40:24 +0000
Subject: [PATCH-V2 0/6] ARM: memory: bcm: add sdram driver
Message-ID: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add a sdram driver for the bcm2835 SOC.

This is needed (especially) as there are 2 clocks that are needed
by the SDram related HW block, which - right now are not claimed.

Without this driver there is a possibility that one of these
clocks (sdram (for low-voltage modes) or pll_core) or one of their
parents does get disabled when the clocks or PLLs are actually
needed.

In the current form of this driver there is still no absolute
certainty that such a situation can not happen under all
cirumstances, but it reduces the likleyhood that this happens.

To avoid this situation a patch-set will be needed that moves
bcm2835-clk and bcm2835-sdram to earlier stages during the
boot process.

The driver also claims the 3 necessary register ranges
to fully control the sdram (SDRAM, APHY, DPHY).

But for some reasons these registers are not accessible and
read as 0.

It is still unclear if this is a general feature of the SOC
or if this is configured by the binary-blob firmware.

That is why this patchset includes an optional patch
(patch 6: memory: bcm2835: expose register ranges via debugfs)
that exposes these register sets via debugfs.

Martin Sperl (6):
  dt: bindings: add bcm2835-memory-controller documentation
  memory: bcm2835: add bcm2835-memory controller
  ARM: dts: bcm2835: add the bcm2835-sdram-controller to the dt
  ARM: bcm2835_defconfig: add bcm2835-sdram controller
  ARM: multi_v7_defconfig: bcm2835: add bcm2835-sdram driver
  memory: bcm2835: expose register ranges via debugfs

 .../memory-controllers/brcm,bcm2835-sdram.txt      |  30 ++
 arch/arm/boot/dts/bcm283x.dtsi                     |  11 +
 arch/arm/configs/bcm2835_defconfig                 |   1 +
 arch/arm/configs/multi_v7_defconfig                |   1 +
 drivers/memory/Kconfig                             |   7 +
 drivers/memory/Makefile                            |   1 +
 drivers/memory/bcm2835-sdram.c                     | 464 +++++++++++++++++++++
 7 files changed, 515 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/brcm,bcm2835-sdram.txt
 create mode 100644 drivers/memory/bcm2835-sdram.c

--
2.1.4


From kernel at martin.sperl.org  Wed May 18 08:40:25 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Wed, 18 May 2016 15:40:25 +0000
Subject: [PATCH-V2 1/6] dt: bindings: add bcm2835-memory-controller
 documentation
In-Reply-To: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
References: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463586030-2778-2-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add memory controller dt-binding documentation for the
bcm2835 soc.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>

Changelog:
  V2 -> V3: added additional clock
	      (for the Controller internal PLL)
	    added clock-names
	    added additional register ranges for the
	      SDRAM Adress and Data PHY
	    added reg-names
---
 .../memory-controllers/brcm,bcm2835-sdram.txt      | 30 ++++++++++++++++++++++
 1 file changed, 30 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/brcm,bcm2835-sdram.txt

diff --git a/Documentation/devicetree/bindings/memory-controllers/brcm,bcm2835-sdram.txt b/Documentation/devicetree/bindings/memory-controllers/brcm,bcm2835-sdram.txt
new file mode 100644
index 0000000..5c4182f
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/brcm,bcm2835-sdram.txt
@@ -0,0 +1,30 @@
+Binding for SDRAM driver for BCM2835 SoCs.
+
+Required parameters:
+-------------------
+
+compatible : 	should be: "brcm,bcm2835-sdram"
+reg :		Address range of the register-set:
+		  * SD
+		  * APHY_CSR
+		  * DPHY_CSR
+reg-names :	Names of the register ranges:
+		  "sdram", "aphy_csr", "dphy_csr"
+clocks : 	Phandle of the clocks used by the sdram
+		  * low voltage clock
+		  * pll parent clock
+clock-names:	Names of the clocks:
+		  "low-voltage", "pll-parent"
+
+Example:
+
+memory-conroller at 7ee00000 {
+	compatible = "brcm,bcm2835-sdram";
+	reg = <0x7ee00000 0x18c>,
+	      <0x7ee06000 0x94>,
+	      <0x7ee07000 0x808>;
+	reg-names = "sdram", "aphy_csr", "dphy_csr";
+	clocks = <&clocks BCM2835_CLOCK_SDRAM>,
+		 <&clocks BCM2835_PLLD_CORE>;
+	clock-names = "low-voltage", "pll-parent";
+};
-- 
2.1.4



From kernel at martin.sperl.org  Wed May 18 08:40:26 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Wed, 18 May 2016 15:40:26 +0000
Subject: [PATCH-V2 2/6] memory: bcm2835: add bcm2835-memory controller
In-Reply-To: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
References: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463586030-2778-3-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add a memory-controller driver for the bcm2835 SOC.

This is mostly needed to claim the SDRAM clocks
so that this (and the corresponding parent pll)
never gets disabled.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>

Changelog:
 V1->V2: moved to different register sets (that are also
     	  set up by the alternative boot loader to enable sdram)
	 added 2 distinct clocks (for low voltage and internal pll)
	 made the use of "names" for reg and clocks
---
 drivers/memory/Kconfig         |   7 +++
 drivers/memory/Makefile        |   1 +
 drivers/memory/bcm2835-sdram.c | 128 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 136 insertions(+)
 create mode 100644 drivers/memory/bcm2835-sdram.c

diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 51d5cd2..a55cad3 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -25,6 +25,13 @@ config ATMEL_SDRAMC
 	  Starting with the at91sam9g45, this controller supports SDR, DDR and
 	  LP-DDR memories.
 
+config BCM2835_SDRAM
+	bool "Broadcom BCM2835 SDRAM Controller"
+	default y
+	depends on ARCH_BCM2835 || COMPILE_TEST
+	help
+	  This driver is for Broadcom BCM2835 SDRAM Controller.
+
 config TI_AEMIF
 	tristate "Texas Instruments AEMIF driver"
 	depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 890bdf4..1287b90 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_OF)		+= of_memory.o
 endif
 obj-$(CONFIG_ARM_PL172_MPMC)	+= pl172.o
 obj-$(CONFIG_ATMEL_SDRAMC)	+= atmel-sdramc.o
+obj-$(CONFIG_BCM2835_SDRAM)	+= bcm2835-sdram.o
 obj-$(CONFIG_TI_AEMIF)		+= ti-aemif.o
 obj-$(CONFIG_TI_EMIF)		+= emif.o
 obj-$(CONFIG_OMAP_GPMC)		+= omap-gpmc.o
diff --git a/drivers/memory/bcm2835-sdram.c b/drivers/memory/bcm2835-sdram.c
new file mode 100644
index 0000000..ce985ee
--- /dev/null
+++ b/drivers/memory/bcm2835-sdram.c
@@ -0,0 +1,128 @@
+/*
+ * Driver for Broadcom BCM2835 soc sdram controller
+ *
+ * Copyright (C) 2016 Martin Sperl
+ *
+ * inspired by: atmel-sdramc
+ *
+ * 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.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+struct bcm2835_sdram_data {
+	void __iomem	*sdram_regs;
+	void __iomem	*aphy_csr_regs;
+	void __iomem	*dphy_csr_regs;
+
+	struct clk	*clk_lv;
+	struct clk	*clk_pll_parent;
+};
+
+static int bcm2835_sdram_probe_reg(struct platform_device *pdev,
+				   const char *name,
+				   void __iomem **ptr)
+{
+	struct resource *res;
+	int err = 0;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Could not find register range %s\n",
+			name);
+		return -EINVAL;
+	}
+
+	*ptr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(*ptr)) {
+		err = PTR_ERR(*ptr);
+		dev_err(&pdev->dev,
+			"Could not get register range %s: %d\n",
+			name, err);
+	}
+
+	return err;
+}
+
+static int bcm2835_sdram_probe(struct platform_device *pdev)
+{
+	struct bcm2835_sdram_data *data;
+	int ret;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, data);
+
+	/* get registers */
+	ret = bcm2835_sdram_probe_reg(pdev, "sdram",
+				      &data->sdram_regs);
+	if (ret)
+		return ret;
+	ret = bcm2835_sdram_probe_reg(pdev, "aphy_csr",
+				      &data->aphy_csr_regs);
+	if (ret)
+		return ret;
+	ret = bcm2835_sdram_probe_reg(pdev, "dphy_csr",
+				      &data->dphy_csr_regs);
+	if (ret)
+		return ret;
+
+	/* get clocks */
+	data->clk_lv = devm_clk_get(&pdev->dev, "low-voltage");
+	if (IS_ERR(data->clk_lv)) {
+		ret = PTR_ERR(data->clk_lv);
+		dev_err(&pdev->dev, "Could not get clock named %s - %d\n",
+			"low-voltage", ret);
+		return ret;
+	}
+	data->clk_pll_parent = devm_clk_get(&pdev->dev, "pll-parent");
+	if (IS_ERR(data->clk_pll_parent)) {
+		ret = PTR_ERR(data->clk_pll_parent);
+		dev_err(&pdev->dev, "Could not get clock named %s - %d\n",
+			"pll-parent", ret);
+		return ret;
+	}
+
+	/* finally prepare both */
+	clk_prepare_enable(data->clk_lv);
+	clk_prepare_enable(data->clk_pll_parent);
+
+	return 0;
+}
+
+static const struct of_device_id bcm2835_sdram_of_match_table[] = {
+	{ .compatible = "brcm,bcm2835-sdram", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_sdram_of_match_table);
+
+static struct platform_driver bcm2835_sdram_driver = {
+	.probe = bcm2835_sdram_probe,
+	.driver = {
+		.name = "bcm2835_sdram",
+		.of_match_table = bcm2835_sdram_of_match_table,
+	},
+};
+module_platform_driver(bcm2835_sdram_driver);
+
+MODULE_AUTHOR("Martin Sperl");
+MODULE_DESCRIPTION("sdram driver for bcm2835 chip");
+MODULE_LICENSE("GPL");
-- 
2.1.4



From kernel at martin.sperl.org  Wed May 18 08:40:27 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Wed, 18 May 2016 15:40:27 +0000
Subject: [PATCH-V2 3/6] ARM: dts: bcm2835: add the bcm2835-sdram-controller to
 the dt
In-Reply-To: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
References: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463586030-2778-4-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add the bcm2835 sdram controller to the device tree.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 arch/arm/boot/dts/bcm283x.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index 2b5cbc6..177045a 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
+++ b/arch/arm/boot/dts/bcm283x.dtsi
@@ -237,6 +237,17 @@
 			reg = <0x7e980000 0x10000>;
 			interrupts = <1 9>;
 		};
+
+		memory-conroller at 7ee00000 {
+			compatible = "brcm,bcm2835-sdram";
+			reg = <0x7ee00000 0x18c>,
+			      <0x7ee06000 0x94>,
+			      <0x7ee07000 0x808>;
+			reg-names = "sdram", "aphy_csr", "dphy_csr";
+			clocks = <&clocks BCM2835_CLOCK_SDRAM>,
+				 <&clocks BCM2835_PLLD_CORE>;
+			clock-names = "low-voltage", "pll-parent";
+		};
 	};
 
 	clocks {
-- 
2.1.4



From kernel at martin.sperl.org  Wed May 18 08:40:28 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Wed, 18 May 2016 15:40:28 +0000
Subject: [PATCH-V2 4/6] ARM: bcm2835_defconfig: add bcm2835-sdram controller
In-Reply-To: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
References: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463586030-2778-5-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Add the bcm2835-sdram controller driver to the default config.
(as the driver is enabled by default vi KConfig, we only need
to enable CONFIG_MEMORY)

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 arch/arm/configs/bcm2835_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index f254d6b..634e07e 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -109,6 +109,7 @@ CONFIG_MAILBOX=y
 CONFIG_BCM2835_MBOX=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_RASPBERRYPI_POWER=y
+CONFIG_MEMORY=y
 CONFIG_PWM=y
 CONFIG_PWM_BCM2835=y
 CONFIG_RASPBERRYPI_FIRMWARE=y
-- 
2.1.4



From kernel at martin.sperl.org  Wed May 18 08:40:29 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Wed, 18 May 2016 15:40:29 +0000
Subject: [PATCH-V2 5/6] ARM: multi_v7_defconfig: bcm2835: add bcm2835-sdram
 driver
In-Reply-To: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
References: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463586030-2778-6-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

ad the sdram driver of bcm2835 to the list of compiled
modules in multi_v7_defconfig

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 9108cc7..bd6d400 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -764,6 +764,7 @@ CONFIG_TEGRA_IOMMU_SMMU=y
 CONFIG_PM_DEVFREQ=y
 CONFIG_ARM_TEGRA_DEVFREQ=m
 CONFIG_MEMORY=y
+CONFIG_BCM2835_SDRAM=y
 CONFIG_EXTCON=y
 CONFIG_TI_AEMIF=y
 CONFIG_IIO=y
-- 
2.1.4



From kernel at martin.sperl.org  Wed May 18 08:40:30 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Wed, 18 May 2016 15:40:30 +0000
Subject: [PATCH-V2 6/6] memory: bcm2835: expose register ranges via debugfs
In-Reply-To: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
References: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463586030-2778-7-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Expose the assigned register ranges via debugfs.

For some reason these register ranges are reading as 0
when running with the binary firmware - this may be a limitation
introduced by the firmware or it may be something that
the SOC is blocking.

This is there just to allow/document those registers,
that are visible on the VC4/GPU side.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 drivers/memory/bcm2835-sdram.c | 336 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 336 insertions(+)

diff --git a/drivers/memory/bcm2835-sdram.c b/drivers/memory/bcm2835-sdram.c
index ce985ee..9d8cce2 100644
--- a/drivers/memory/bcm2835-sdram.c
+++ b/drivers/memory/bcm2835-sdram.c
@@ -17,6 +17,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/debugfs.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -26,6 +27,140 @@
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 
+/* the set of registers of the sdram controller */
+#define BCM2835_SD_CS		0x000
+#define BCM2835_SD_SA		0x004
+#define BCM2835_SD_SB		0x008
+#define BCM2835_SD_SC		0x00c
+#define BCM2835_SD_PT2		0x010
+#define BCM2835_SD_PT1		0x014
+#define BCM2835_SD_SECSRT0	0x03c
+#define BCM2835_SD_SECEND0	0x040
+#define BCM2835_SD_SECSRT1	0x044
+#define BCM2835_SD_SECEND1	0x048
+#define BCM2835_SD_SECSRT2	0x04c
+#define BCM2835_SD_SECEND2	0x050
+#define BCM2835_SD_SECSRT3	0x054
+#define BCM2835_SD_SECEND3	0x058
+#define BCM2835_SD_PHYC		0x060
+#define BCM2835_SD_MRT		0x064
+#define BCM2835_SD_TMC		0x07c
+#define BCM2835_SD_RWC		0x080
+#define BCM2835_SD_VIN		0x088
+#define BCM2835_SD_MR		0x090
+#define BCM2835_SD_SD		0x094
+#define BCM2835_SD_SE		0x098
+#define BCM2835_SD_STALL	0x0a0
+#define BCM2835_SD_SF		0x0b4
+#define BCM2835_SD_CARCRC	0x100
+#define BCM2835_SD_DMRCRC0	0x104
+#define BCM2835_SD_DMRCRC1	0x108
+#define BCM2835_SD_DQRCRC0	0x10c
+#define BCM2835_SD_DQRCRC1	0x110
+#define BCM2835_SD_DQRCRC2	0x114
+#define BCM2835_SD_DQRCRC3	0x118
+#define BCM2835_SD_DQRCRC4	0x11c
+#define BCM2835_SD_DQRCRC5	0x120
+#define BCM2835_SD_DQRCRC6	0x124
+#define BCM2835_SD_DQRCRC7	0x128
+#define BCM2835_SD_DQRCRC8	0x12c
+#define BCM2835_SD_DQRCRC9	0x130
+#define BCM2835_SD_DQRCRC10	0x134
+#define BCM2835_SD_DQRCRC11	0x138
+#define BCM2835_SD_DQRCRC12	0x13c
+#define BCM2835_SD_DQRCRC13	0x140
+#define BCM2835_SD_DQRCRC14	0x144
+#define BCM2835_SD_DQRCRC15	0x148
+#define BCM2835_SD_DQLCRC0	0x14c
+#define BCM2835_SD_DQLCRC1	0x150
+#define BCM2835_SD_DQLCRC2	0x154
+#define BCM2835_SD_DQLCRC3	0x158
+#define BCM2835_SD_DQLCRC4	0x15c
+#define BCM2835_SD_DQLCRC5	0x160
+#define BCM2835_SD_DQLCRC6	0x164
+#define BCM2835_SD_DQLCRC7	0x168
+#define BCM2835_SD_DQLCRC8	0x16c
+#define BCM2835_SD_DQLCRC9	0x170
+#define BCM2835_SD_DQLCRC10	0x174
+#define BCM2835_SD_DQLCRC11	0x178
+#define BCM2835_SD_DQLCRC12	0x17c
+#define BCM2835_SD_DQLCRC13	0x180
+#define BCM2835_SD_DQLCRC14	0x184
+#define BCM2835_SD_DQLCRC15	0x188
+
+/* the set of registers of the APHY_CSR, which also contains the pll */
+#define APHY_CSR_ADDR_REV_ID			0x000
+#define APHY_CSR_GLBL_ADDR_DLL_RESET		0x004
+#define APHY_CSR_GLBL_ADDR_DLL_RECAL		0x008
+#define APHY_CSR_GLBL_ADDR_DLL_CNTRL		0x00c
+#define APHY_CSR_GLBL_ADDR_DLL_PH_LD_VAL	0x010
+#define APHY_CSR_ADDR_MASTER_DLL_OUTPUT		0x014
+#define APHY_CSR_ADDR_SLAVE_DLL_OFFSET		0x018
+#define APHY_CSR_GLBL_ADR_MSTR_DLL_BYPEN	0x01c
+#define APHY_CSR_GLBL_ADR_DLL_LOCK_STAT		0x020
+#define APHY_CSR_DDR_PLL_GLOBAL_RESET		0x024
+#define APHY_CSR_DDR_PLL_POST_DIV_RESET		0x028
+#define APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL0	0x02c
+#define APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL1	0x030
+#define APHY_CSR_DDR_PLL_MDIV_VALUE		0x034
+#define APHY_CSR_DDR_PLL_CONFIG_CNTRL		0x038
+#define APHY_CSR_DDR_PLL_MISC_CNTRL		0x03c
+#define APHY_CSR_DDR_PLL_SPRDSPECT_CTRL0	0x040
+#define APHY_CSR_DDR_PLL_SPRDSPECT_CTRL1	0x044
+#define APHY_CSR_DDR_PLL_LOCK_STATUS		0x048
+#define APHY_CSR_DDR_PLL_HOLD_CH		0x04c
+#define APHY_CSR_DDR_PLL_ENABLE_CH		0x050
+#define APHY_CSR_DDR_PLL_BYPASS			0x054
+#define APHY_CSR_DDR_PLL_PWRDWN			0x058
+#define APHY_CSR_DDR_PLL_CH0_DESKEW_CTRL	0x05c
+#define APHY_CSR_DDR_PLL_CH1_DESKEW_CTRL	0x060
+#define APHY_CSR_DDR_PLL_DESKEW_STATUS		0x064
+#define APHY_CSR_ADDR_PAD_DRV_SLEW_CTRL		0x068
+#define APHY_CSR_ADDR_PAD_MISC_CTRL		0x06c
+#define APHY_CSR_ADDR_PVT_COMP_CTRL		0x070
+#define APHY_CSR_ADDR_PVT_COMP_OVRD_CTRL	0x074
+#define APHY_CSR_ADDR_PVT_COMP_STATUS		0x078
+#define APHY_CSR_ADDR_PVT_COMP_DEBUG		0x07c
+#define APHY_CSR_PHY_BIST_CNTRL_SPR		0x080
+#define APHY_CSR_PHY_BIST_CA_CRC_SPR		0x084
+#define APHY_CSR_ADDR_SPR0_RW			0x088
+#define APHY_CSR_ADDR_SPR1_RO			0x08c
+#define APHY_CSR_ADDR_SPR_RO			0x090
+
+/* the set of registers of the DPHY_CSR */
+#define DPHY_CSR_DQ_REV_ID			0x000
+#define DPHY_CSR_GLBL_DQ_DLL_RESET		0x004
+#define DPHY_CSR_GLBL_DQ_DLL_RECALIBRATE	0x008
+#define DPHY_CSR_GLBL_DQ_DLL_CNTRL		0x00c
+#define DPHY_CSR_GLBL_DQ_DLL_PHASE_LD_VL	0x010
+#define DPHY_CSR_GLBL_DQ_MSTR_DLL_BYP_EN	0x014
+#define DPHY_CSR_GLBL_MSTR_DLL_LOCK_STAT	0x018
+#define DPHY_CSR_BYTE0_SLAVE_DLL_OFFSET		0x01c
+#define DPHY_CSR_BYTE1_SLAVE_DLL_OFFSET		0x020
+#define DPHY_CSR_BYTE2_SLAVE_DLL_OFFSET		0x024
+#define DPHY_CSR_BYTE3_SLAVE_DLL_OFFSET		0x028
+#define DPHY_CSR_BYTE0_MASTER_DLL_OUTPUT	0x02c
+#define DPHY_CSR_BYTE1_MASTER_DLL_OUTPUT	0x030
+#define DPHY_CSR_BYTE2_MASTER_DLL_OUTPUT	0x034
+#define DPHY_CSR_BYTE3_MASTER_DLL_OUTPUT	0x038
+#define DPHY_CSR_NORM_READ_DQS_GATE_CTRL	0x03c
+#define DPHY_CSR_BOOT_READ_DQS_GATE_CTRL	0x040
+#define DPHY_CSR_PHY_FIFO_PNTRS			0x044
+#define DPHY_CSR_DQ_PHY_MISC_CTRL		0x048
+#define DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL		0x04c
+#define DPHY_CSR_DQ_PAD_MISC_CTRL		0x050
+#define DPHY_CSR_DQ_PVT_COMP_CTRL		0x054
+#define DPHY_CSR_DQ_PVT_COMP_OVERRD_CTRL	0x058
+#define DPHY_CSR_DQ_PVT_COMP_STATUS		0x05c
+#define DPHY_CSR_DQ_PVT_COMP_DEBUG		0x060
+#define DPHY_CSR_DQ_PHY_READ_CTRL		0x064
+#define DPHY_CSR_DQ_PHY_READ_STATUS		0x068
+#define DPHY_CSR_DQ_SPR_RW			0x06c
+#define DPHY_CSR_DQ_SPR1_RO			0x070
+#define DPHY_CSR_DQ_SPR_RO			0x074
+#define DPHY_CSR_CRC_CTRL			0x800
+#define DPHY_CSR_CRC_DATA			0x804
+
 struct bcm2835_sdram_data {
 	void __iomem	*sdram_regs;
 	void __iomem	*aphy_csr_regs;
@@ -33,8 +168,196 @@ struct bcm2835_sdram_data {
 
 	struct clk	*clk_lv;
 	struct clk	*clk_pll_parent;
+
+	struct dentry	*debugfsdir;
+};
+
+#define R(n, o) { .name = n, .offset = o }
+static const struct debugfs_reg32 bcm2835_sdram_regs[] = {
+	R("cs",		BCM2835_SD_CS),
+	R("sa",		BCM2835_SD_SA),
+	R("sb",		BCM2835_SD_SB),
+	R("sc",		BCM2835_SD_SC),
+	R("pt2",	BCM2835_SD_PT2),
+	R("pt1",	BCM2835_SD_PT1),
+	R("secsrt0",	BCM2835_SD_SECSRT0),
+	R("secend0",	BCM2835_SD_SECEND0),
+	R("secsrt1",	BCM2835_SD_SECSRT1),
+	R("secend1",	BCM2835_SD_SECEND1),
+	R("secsrt2",	BCM2835_SD_SECSRT2),
+	R("secend2",	BCM2835_SD_SECEND2),
+	R("secsrt3",	BCM2835_SD_SECSRT3),
+	R("secend3",	BCM2835_SD_SECEND3),
+	R("phyc",	BCM2835_SD_PHYC),
+	R("mrt",	BCM2835_SD_MRT),
+	R("tmc",	BCM2835_SD_TMC),
+	R("rwc",	BCM2835_SD_RWC),
+	R("vin",	BCM2835_SD_VIN),
+	/*
+	 * this is not exposed as this may result in races with
+	 * a parallel read - possibly by the firmware:
+	 * R("mr",		BCM2835_SD_MR),
+	 */
+	R("sd",		BCM2835_SD_SD),
+	R("se",		BCM2835_SD_SE),
+	R("stall",	BCM2835_SD_STALL),
+	R("sf",		BCM2835_SD_SF),
+	R("carcrc",	BCM2835_SD_CARCRC),
+	R("dmrcrc0",	BCM2835_SD_DMRCRC0),
+	R("dmrcrc1",	BCM2835_SD_DMRCRC1),
+	R("dqrcrc0",	BCM2835_SD_DQRCRC0),
+	R("dqrcrc1",	BCM2835_SD_DQRCRC1),
+	R("dqrcrc2",	BCM2835_SD_DQRCRC2),
+	R("dqrcrc3",	BCM2835_SD_DQRCRC3),
+	R("dqrcrc4",	BCM2835_SD_DQRCRC4),
+	R("dqrcrc5",	BCM2835_SD_DQRCRC5),
+	R("dqrcrc6",	BCM2835_SD_DQRCRC6),
+	R("dqrcrc7",	BCM2835_SD_DQRCRC7),
+	R("dqrcrc8",	BCM2835_SD_DQRCRC8),
+	R("dqrcrc9",	BCM2835_SD_DQRCRC9),
+	R("dqrcrc10",	BCM2835_SD_DQRCRC10),
+	R("dqrcrc11",	BCM2835_SD_DQRCRC11),
+	R("dqrcrc12",	BCM2835_SD_DQRCRC12),
+	R("dqrcrc13",	BCM2835_SD_DQRCRC13),
+	R("dqrcrc14",	BCM2835_SD_DQRCRC14),
+	R("dqrcrc15",	BCM2835_SD_DQRCRC15),
+	R("dqlcrc0",	BCM2835_SD_DQLCRC0),
+	R("dqlcrc1",	BCM2835_SD_DQLCRC1),
+	R("dqlcrc2",	BCM2835_SD_DQLCRC2),
+	R("dqlcrc3",	BCM2835_SD_DQLCRC3),
+	R("dqlcrc4",	BCM2835_SD_DQLCRC4),
+	R("dqlcrc5",	BCM2835_SD_DQLCRC5),
+	R("dqlcrc6",	BCM2835_SD_DQLCRC6),
+	R("dqlcrc7",	BCM2835_SD_DQLCRC7),
+	R("dqlcrc8",	BCM2835_SD_DQLCRC8),
+	R("dqlcrc9",	BCM2835_SD_DQLCRC9),
+	R("dqlcrc10",	BCM2835_SD_DQLCRC10),
+	R("dqlcrc11",	BCM2835_SD_DQLCRC11),
+	R("dqlcrc12",	BCM2835_SD_DQLCRC12),
+	R("dqlcrc13",	BCM2835_SD_DQLCRC13),
+	R("dqlcrc14",	BCM2835_SD_DQLCRC14),
+	R("dqlcrc15",	BCM2835_SD_DQLCRC15)
+};
+
+static const struct debugfs_reg32 bcm2835_aphy_csr_regs[] = {
+	R("addr_rev_id",		APHY_CSR_ADDR_REV_ID),
+	R("glbl_addr_dll_reset",	APHY_CSR_GLBL_ADDR_DLL_RESET),
+	R("glbl_addr_dll_recal",	APHY_CSR_GLBL_ADDR_DLL_RECAL),
+	R("glbl_addr_dll_cntrl",	APHY_CSR_GLBL_ADDR_DLL_CNTRL),
+	R("glbl_addr_dll_ph_ld_val",	APHY_CSR_GLBL_ADDR_DLL_PH_LD_VAL),
+	R("addr_master_dll_output",	APHY_CSR_ADDR_MASTER_DLL_OUTPUT),
+	R("addr_slave_dll_offset",	APHY_CSR_ADDR_SLAVE_DLL_OFFSET),
+	R("glbl_adr_mstr_dll_bypen",	APHY_CSR_GLBL_ADR_MSTR_DLL_BYPEN),
+	R("glbl_adr_dll_lock_stat",	APHY_CSR_GLBL_ADR_DLL_LOCK_STAT),
+	R("ddr_pll_global_reset",	APHY_CSR_DDR_PLL_GLOBAL_RESET),
+	R("ddr_pll_post_div_reset",	APHY_CSR_DDR_PLL_POST_DIV_RESET),
+	R("ddr_pll_vco_freq_cntrl0",	APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL0),
+	R("ddr_pll_vco_freq_cntrl1",	APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL1),
+	R("ddr_pll_mdiv_value",		APHY_CSR_DDR_PLL_MDIV_VALUE),
+	R("ddr_pll_config_cntrl",	APHY_CSR_DDR_PLL_CONFIG_CNTRL),
+	R("ddr_pll_misc_cntrl",		APHY_CSR_DDR_PLL_MISC_CNTRL),
+	R("ddr_pll_sprdspect_ctrl0",	APHY_CSR_DDR_PLL_SPRDSPECT_CTRL0),
+	R("ddr_pll_sprdspect_ctrl1",	APHY_CSR_DDR_PLL_SPRDSPECT_CTRL1),
+	R("ddr_pll_lock_status",	APHY_CSR_DDR_PLL_LOCK_STATUS),
+	R("ddr_pll_hold_ch",		APHY_CSR_DDR_PLL_HOLD_CH),
+	R("ddr_pll_enable_ch",		APHY_CSR_DDR_PLL_ENABLE_CH),
+	R("ddr_pll_bypass",		APHY_CSR_DDR_PLL_BYPASS),
+	R("ddr_pll_pwrdwn",		APHY_CSR_DDR_PLL_PWRDWN),
+	R("ddr_pll_ch0_deskew_ctrl",	APHY_CSR_DDR_PLL_CH0_DESKEW_CTRL),
+	R("ddr_pll_ch1_deskew_ctrl",	APHY_CSR_DDR_PLL_CH1_DESKEW_CTRL),
+	R("ddr_pll_deskew_status",	APHY_CSR_DDR_PLL_DESKEW_STATUS),
+	R("addr_pad_drv_slew_ctrl",	APHY_CSR_ADDR_PAD_DRV_SLEW_CTRL),
+	R("addr_pad_misc_ctrl",		APHY_CSR_ADDR_PAD_MISC_CTRL),
+	R("addr_pvt_comp_ctrl",		APHY_CSR_ADDR_PVT_COMP_CTRL),
+	R("addr_pvt_comp_ovrd_ctrl",	APHY_CSR_ADDR_PVT_COMP_OVRD_CTRL),
+	R("addr_pvt_comp_status",	APHY_CSR_ADDR_PVT_COMP_STATUS),
+	R("addr_pvt_comp_debug",	APHY_CSR_ADDR_PVT_COMP_DEBUG),
+	R("phy_bist_cntrl_spr",		APHY_CSR_PHY_BIST_CNTRL_SPR),
+	R("phy_bist_ca_crc_spr",	APHY_CSR_PHY_BIST_CA_CRC_SPR),
+	R("addr_spr0_rw",		APHY_CSR_ADDR_SPR0_RW),
+	R("addr_spr1_ro",		APHY_CSR_ADDR_SPR1_RO),
+	R("addr_spr_ro",		APHY_CSR_ADDR_SPR_RO)
+};
+
+static const struct debugfs_reg32 bcm2835_dphy_csr_regs[] = {
+	R("dq_rev_id",			DPHY_CSR_DQ_REV_ID),
+	R("glbl_dq_dll_reset",		DPHY_CSR_GLBL_DQ_DLL_RESET),
+	R("glbl_dq_dll_recalibrate",	DPHY_CSR_GLBL_DQ_DLL_RECALIBRATE),
+	R("glbl_dq_dll_cntrl",		DPHY_CSR_GLBL_DQ_DLL_CNTRL),
+	R("glbl_dq_dll_phase_ld_vl",	DPHY_CSR_GLBL_DQ_DLL_PHASE_LD_VL),
+	R("glbl_dq_mstr_dll_byp_en",	DPHY_CSR_GLBL_DQ_MSTR_DLL_BYP_EN),
+	R("glbl_mstr_dll_lock_stat",	DPHY_CSR_GLBL_MSTR_DLL_LOCK_STAT),
+	R("byte0_slave_dll_offset",	DPHY_CSR_BYTE0_SLAVE_DLL_OFFSET),
+	R("byte1_slave_dll_offset",	DPHY_CSR_BYTE1_SLAVE_DLL_OFFSET),
+	R("byte2_slave_dll_offset",	DPHY_CSR_BYTE2_SLAVE_DLL_OFFSET),
+	R("byte3_slave_dll_offset",	DPHY_CSR_BYTE3_SLAVE_DLL_OFFSET),
+	R("byte0_master_dll_output",	DPHY_CSR_BYTE0_MASTER_DLL_OUTPUT),
+	R("byte1_master_dll_output",	DPHY_CSR_BYTE1_MASTER_DLL_OUTPUT),
+	R("byte2_master_dll_output",	DPHY_CSR_BYTE2_MASTER_DLL_OUTPUT),
+	R("byte3_master_dll_output",	DPHY_CSR_BYTE3_MASTER_DLL_OUTPUT),
+	R("norm_read_dqs_gate_ctrl",	DPHY_CSR_NORM_READ_DQS_GATE_CTRL),
+	R("boot_read_dqs_gate_ctrl",	DPHY_CSR_BOOT_READ_DQS_GATE_CTRL),
+	R("phy_fifo_pntrs",		DPHY_CSR_PHY_FIFO_PNTRS),
+	R("dq_phy_misc_ctrl",		DPHY_CSR_DQ_PHY_MISC_CTRL),
+	R("dq_pad_drv_slew_ctrl",	DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL),
+	R("dq_pad_misc_ctrl",		DPHY_CSR_DQ_PAD_MISC_CTRL),
+	R("dq_pvt_comp_ctrl",		DPHY_CSR_DQ_PVT_COMP_CTRL),
+	R("dq_pvt_comp_overrd_ctrl",	DPHY_CSR_DQ_PVT_COMP_OVERRD_CTRL),
+	R("dq_pvt_comp_status",		DPHY_CSR_DQ_PVT_COMP_STATUS),
+	R("dq_pvt_comp_debug",		DPHY_CSR_DQ_PVT_COMP_DEBUG),
+	R("dq_phy_read_ctrl",		DPHY_CSR_DQ_PHY_READ_CTRL),
+	R("dq_phy_read_status",		DPHY_CSR_DQ_PHY_READ_STATUS),
+	R("dq_spr_rw",			DPHY_CSR_DQ_SPR_RW),
+	R("dq_spr1_ro",			DPHY_CSR_DQ_SPR1_RO),
+	R("dq_spr_ro",			DPHY_CSR_DQ_SPR_RO),
+	R("crc_ctrl",			DPHY_CSR_CRC_CTRL),
+	R("crc_data",			DPHY_CSR_CRC_DATA),
 };
 
+static void bcm2835_sdram_debugfs_regset(struct platform_device *pdev,
+					 const char *name,
+					 const struct debugfs_reg32 *reg32,
+					 size_t size,
+					 void *base)
+{
+	struct bcm2835_sdram_data *data = platform_get_drvdata(pdev);
+	struct debugfs_regset32 *regset;
+
+	regset = devm_kzalloc(&pdev->dev, sizeof(*regset),
+			      GFP_KERNEL);
+	if (!regset)
+		return;
+
+	regset->regs = reg32;
+	regset->nregs = size;
+	regset->base = base;
+
+	debugfs_create_regset32(name, S_IRUGO,
+				data->debugfsdir, regset);
+}
+
+static void bcm2835_sdram_debugfs(struct platform_device *pdev)
+{
+	struct bcm2835_sdram_data *data = platform_get_drvdata(pdev);
+
+	data->debugfsdir = debugfs_create_dir("bcm2835_sdram", NULL);
+	if (!data->debugfsdir)
+		return;
+
+	bcm2835_sdram_debugfs_regset(pdev, "sdram-regset",
+				     bcm2835_sdram_regs,
+				     ARRAY_SIZE(bcm2835_sdram_regs),
+				     data->sdram_regs);
+	bcm2835_sdram_debugfs_regset(pdev, "aphy_csr-regset",
+				     bcm2835_aphy_csr_regs,
+				     ARRAY_SIZE(bcm2835_aphy_csr_regs),
+				     data->aphy_csr_regs);
+	bcm2835_sdram_debugfs_regset(pdev, "dphy_csr-regset",
+				     bcm2835_dphy_csr_regs,
+				     ARRAY_SIZE(bcm2835_dphy_csr_regs),
+				     data->dphy_csr_regs);
+}
+
 static int bcm2835_sdram_probe_reg(struct platform_device *pdev,
 				   const char *name,
 				   void __iomem **ptr)
@@ -105,6 +428,18 @@ static int bcm2835_sdram_probe(struct platform_device *pdev)
 	clk_prepare_enable(data->clk_lv);
 	clk_prepare_enable(data->clk_pll_parent);
 
+	/* setup debugfs */
+	bcm2835_sdram_debugfs(pdev);
+
+	return 0;
+}
+
+static int bcm2835_sdram_remove(struct platform_device *pdev)
+{
+	struct bcm2835_sdram_data *data = platform_get_drvdata(pdev);
+
+	debugfs_remove_recursive(data->debugfsdir);
+
 	return 0;
 }
 
@@ -116,6 +451,7 @@ MODULE_DEVICE_TABLE(of, bcm2835_sdram_of_match_table);
 
 static struct platform_driver bcm2835_sdram_driver = {
 	.probe = bcm2835_sdram_probe,
+	.remove = bcm2835_sdram_remove,
 	.driver = {
 		.name = "bcm2835_sdram",
 		.of_match_table = bcm2835_sdram_of_match_table,
-- 
2.1.4



From andre.przywara at arm.com  Wed May 18 08:55:45 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 18 May 2016 16:55:45 +0100
Subject: [PATCH v4 22/56] KVM: arm/arm64: vgic-new: Add MMIO handling
 framework
In-Reply-To: <20160518123115.GE3827@cbox>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-23-git-send-email-andre.przywara@arm.com>
 <20160518123115.GE3827@cbox>
Message-ID: <573C9081.6080500@arm.com>

Hi,

....

>> +
>> +/* generate a mask that covers 1024 interrupts with <b> bits per IRQ */
>> +#define VGIC_ADDR_IRQ_MASK(b) GENMASK_ULL(ilog2(b) + ilog2(1024) - \
>> +					  ilog2(BITS_PER_BYTE) - 1, 0)
>> +#define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
>> +					64 / (bits) / 8)
> 
> In the comment we end up adding here, can we also describe why
> (addr & <magic mask>) * <magic 64> / (bits) / <BITS_PER_BYTE OR BYTES_PER_ULL>
> gives us what we need, because I don't get it.

The reason is: we deal with 8 bits per byte, but have
bits-per-interrupts values bigger than 8. Doing the maths in floating
point arithmetic would work fine:

(float)(addr & mask) * (8.0 / bits_per_IRQ)

So would this comment make sense?

/*
 * Since we can have more than 8 bits per interrupt, we can't use
 * "8 / bpi" as a multiplicand directly, so we use a
 * fixed-point-arithmetic version of it tailored to cover at most 64
 * bits per IRQ.
 */

Cheers,
Andre.


From daniel at ffwll.ch  Wed May 18 09:05:24 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Wed, 18 May 2016 18:05:24 +0200
Subject: [PATCH 0/5] drm: fixes for merge-window regressions
In-Reply-To: <1463579106-400827-1-git-send-email-arnd@arndb.de>
References: <1463579106-400827-1-git-send-email-arnd@arndb.de>
Message-ID: <20160518160524.GI27098@phenom.ffwll.local>

On Wed, May 18, 2016 at 03:45:01PM +0200, Arnd Bergmann wrote:
> A couple of new warnings and build errors appeared through the DRM
> tree in linux-next after the merge window opened. The first patch
> here is for scripts/headers_check.pl, but as the bug is only
> present in drm-next at the moment, it would be good to add all
> five patches to that tree before they make it into mainline.
> 
> It's likely that some of these have already been fixed since
> this morning's linux-next, so just ignore the ones are no
> longer needed.
> 
> Arnd Bergmann (5):
>   headers_check: don't warn about c++ guards
>   drm: mediatek: add CONFIG_OF dependency
>   drm: mediatek: fixup drm_gem_object_lookup API change
>   drm: exynos: mark pm functions as __maybe_unused
>   drm: remove unused dev variables

None of the actual patches seems to have made it onto dri-devel. Stuck
somewhere?
-Daniel

> 
>  drivers/gpu/drm/armada/armada_crtc.c   | 1 -
>  drivers/gpu/drm/exynos/exynos_hdmi.c   | 6 ++----
>  drivers/gpu/drm/mediatek/Kconfig       | 1 +
>  drivers/gpu/drm/mediatek/mtk_drm_fb.c  | 2 +-
>  drivers/gpu/drm/mediatek/mtk_drm_gem.c | 2 +-
>  drivers/gpu/drm/nouveau/nouveau_gem.c  | 1 -
>  drivers/gpu/drm/nouveau/nv50_display.c | 1 -
>  drivers/gpu/drm/radeon/radeon_cs.c     | 1 -
>  scripts/headers_check.pl               | 4 ++++
>  9 files changed, 9 insertions(+), 10 deletions(-)
> 
> 
> Cc: Russell King <rmk+kernel at armlinux.org.uk>
> Cc: Inki Dae <inki.dae at samsung.com>
> Cc: Joonyoung Shim <jy0922.shim at samsung.com>
> Cc: Seung-Woo Kim <sw0312.kim at samsung.com>
> Cc: Kyungmin Park <kyungmin.park at samsung.com>
> Cc: Kukjin Kim <kgene at kernel.org>
> Cc: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> Cc: Matthias Brugger <matthias.bgg at gmail.com>
> Cc: Ben Skeggs <bskeggs at redhat.com>
> Cc: Alex Deucher <alexander.deucher at amd.com>
> Cc: "Christian K?nig" <christian.koenig at amd.com>
> Cc: Arnd Bergmann <arnd at arndb.de>
> Cc: dri-devel at lists.freedesktop.org
> Cc: linux-kernel at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-samsung-soc at vger.kernel.org
> Cc: linux-mediatek at lists.infradead.org
> Cc: nouveau at lists.freedesktop.org
> 
> -- 
> 2.7.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From arnd at arndb.de  Wed May 18 09:07:33 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 18:07:33 +0200
Subject: [PATCH 5/5] drm: remove unused dev variables
In-Reply-To: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
References: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
Message-ID: <1463587653-3035181-6-git-send-email-arnd@arndb.de>

After drm_gem_object_lookup() was changed along with all its callers,
we have several drivers that have unused variables:

drm/armada/armada_crtc.c: In function 'armada_drm_crtc_cursor_set':
drm/armada/armada_crtc.c:900:21: error: unused variable 'dev' [-Werror=unused-variable]
drm/nouveau/nouveau_gem.c: In function 'validate_init':
drm/nouveau/nouveau_gem.c:371:21: error: unused variable 'dev' [-Werror=unused-variable]
drm/nouveau/nv50_display.c: In function 'nv50_crtc_cursor_set':
drm/nouveau/nv50_display.c:1308:21: error: unused variable 'dev' [-Werror=unused-variable]
drm/radeon/radeon_cs.c: In function 'radeon_cs_parser_relocs':
drm/radeon/radeon_cs.c:77:21: error: unused variable 'ddev' [-Werror=unused-variable]

This fixes all the instances I found with ARM randconfig builds so far.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: a8ad0bd84f98 ("drm: Remove unused drm_device from drm_gem_object_lookup()")
---
 drivers/gpu/drm/armada/armada_crtc.c   | 1 -
 drivers/gpu/drm/nouveau/nouveau_gem.c  | 1 -
 drivers/gpu/drm/nouveau/nv50_display.c | 1 -
 drivers/gpu/drm/radeon/radeon_cs.c     | 1 -
 4 files changed, 4 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index a9b7e0f36513..3130aa8bcdd0 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -897,7 +897,6 @@ static void cursor_update(void *data)
 static int armada_drm_crtc_cursor_set(struct drm_crtc *crtc,
 	struct drm_file *file, uint32_t handle, uint32_t w, uint32_t h)
 {
-	struct drm_device *dev = crtc->dev;
 	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
 	struct armada_gem_object *obj = NULL;
 	int ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 445a9e2fb91a..a030e218adf7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -368,7 +368,6 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
 	      int nr_buffers, struct validate_op *op)
 {
 	struct nouveau_cli *cli = nouveau_cli(file_priv);
-	struct drm_device *dev = chan->drm->dev;
 	int trycnt = 0;
 	int ret, i;
 	struct nouveau_bo *res_bo = NULL;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 47761a92926e..ec2e67eb8980 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -1305,7 +1305,6 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
 		     uint32_t handle, uint32_t width, uint32_t height)
 {
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-	struct drm_device *dev = crtc->dev;
 	struct drm_gem_object *gem = NULL;
 	struct nouveau_bo *nvbo = NULL;
 	int ret = 0;
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 271652963fa1..510ea371dacc 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -74,7 +74,6 @@ static void radeon_cs_buckets_get_list(struct radeon_cs_buckets *b,
 
 static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
 {
-	struct drm_device *ddev = p->rdev->ddev;
 	struct radeon_cs_chunk *chunk;
 	struct radeon_cs_buckets buckets;
 	unsigned i;
-- 
2.7.0



From arnd at arndb.de  Wed May 18 09:07:28 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 18:07:28 +0200
Subject: [PATCH 0/5] drm: fixes for merge-window regressions
Message-ID: <1463587653-3035181-1-git-send-email-arnd@arndb.de>

A couple of new warnings and build errors appeared through the DRM
tree in linux-next after the merge window opened. The first patch
here is for scripts/headers_check.pl, but as the bug is only
present in drm-next at the moment, it would be good to add all
five patches to that tree before they make it into mainline.

It's likely that some of these have already been fixed since
this morning's linux-next, so just ignore the ones are no
longer needed.

[resending because of missing Cc list for the actual patches,
 sorry about that]

Arnd Bergmann (5):
  headers_check: don't warn about c++ guards
  drm: mediatek: add CONFIG_OF dependency
  drm: mediatek: fixup drm_gem_object_lookup API change
  drm: exynos: mark pm functions as __maybe_unused
  drm: remove unused dev variables

 drivers/gpu/drm/armada/armada_crtc.c   | 1 -
 drivers/gpu/drm/exynos/exynos_hdmi.c   | 6 ++----
 drivers/gpu/drm/mediatek/Kconfig       | 1 +
 drivers/gpu/drm/mediatek/mtk_drm_fb.c  | 2 +-
 drivers/gpu/drm/mediatek/mtk_drm_gem.c | 2 +-
 drivers/gpu/drm/nouveau/nouveau_gem.c  | 1 -
 drivers/gpu/drm/nouveau/nv50_display.c | 1 -
 drivers/gpu/drm/radeon/radeon_cs.c     | 1 -
 scripts/headers_check.pl               | 4 ++++
 9 files changed, 9 insertions(+), 10 deletions(-)


Cc: Russell King <rmk+kernel at armlinux.org.uk>
Cc: Inki Dae <inki.dae at samsung.com>
Cc: Joonyoung Shim <jy0922.shim at samsung.com>
Cc: Seung-Woo Kim <sw0312.kim at samsung.com>
Cc: Kyungmin Park <kyungmin.park at samsung.com>
Cc: Kukjin Kim <kgene at kernel.org>
Cc: Krzysztof Kozlowski <k.kozlowski at samsung.com>
Cc: Matthias Brugger <matthias.bgg at gmail.com>
Cc: Ben Skeggs <bskeggs at redhat.com>
Cc: Alex Deucher <alexander.deucher at amd.com>
Cc: "Christian K?nig" <christian.koenig at amd.com>
Cc: Arnd Bergmann <arnd at arndb.de>
Cc: dri-devel at lists.freedesktop.org
Cc: linux-kernel at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-samsung-soc at vger.kernel.org
Cc: linux-mediatek at lists.infradead.org
Cc: nouveau at lists.freedesktop.org

-- 
2.7.0



From arnd at arndb.de  Wed May 18 09:07:30 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 18:07:30 +0200
Subject: [PATCH 2/5] drm: mediatek: add CONFIG_OF dependency
In-Reply-To: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
References: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
Message-ID: <1463587653-3035181-3-git-send-email-arnd@arndb.de>

The mediatek DRM driver can be configured for compile testing with
CONFIG_OF disabled, but then fails to link:

drivers/gpu/built-in.o: In function `mtk_drm_bind':
analogix_dp_reg.c:(.text+0x52888): undefined reference to `of_find_device_by_node'
analogix_dp_reg.c:(.text+0x52930): undefined reference to `of_find_device_by_node'

This adds an explicit Kconfig dependency.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 drivers/gpu/drm/mediatek/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
index 545973f6b743..67183e26971d 100644
--- a/drivers/gpu/drm/mediatek/Kconfig
+++ b/drivers/gpu/drm/mediatek/Kconfig
@@ -3,6 +3,7 @@ config DRM_MEDIATEK
 	depends on DRM
 	depends on ARCH_MEDIATEK || (ARM && COMPILE_TEST)
 	depends on COMMON_CLK
+	depends on OF
 	select DRM_GEM_CMA_HELPER
 	select DRM_KMS_HELPER
 	select DRM_MIPI_DSI
-- 
2.7.0



From arnd at arndb.de  Wed May 18 09:07:31 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 18:07:31 +0200
Subject: [PATCH 3/5] drm: mediatek: fixup drm_gem_object_lookup API change
In-Reply-To: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
References: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
Message-ID: <1463587653-3035181-4-git-send-email-arnd@arndb.de>

The drm_gem_object_lookup() function prototype changed while this
driver was added, so it fails to build now:

drivers/gpu/drm/mediatek/mtk_drm_gem.c: In function 'mtk_drm_gem_dumb_map_offset':
drivers/gpu/drm/mediatek/mtk_drm_gem.c:142:30: error: passing argument 1 of 'drm_gem_object_lookup' from incompatible pointer type [-Werror=incompatible-pointer-types]
  obj = drm_gem_object_lookup(dev, file_priv, handle);

This fixes the new caller as well.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: a8ad0bd84f98 ("drm: Remove unused drm_device from drm_gem_object_lookup()")
---
 drivers/gpu/drm/mediatek/mtk_drm_fb.c  | 2 +-
 drivers/gpu/drm/mediatek/mtk_drm_gem.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
index 33d30c19f35f..147df85399ab 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
@@ -138,7 +138,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
 	if (drm_format_num_planes(cmd->pixel_format) != 1)
 		return ERR_PTR(-EINVAL);
 
-	gem = drm_gem_object_lookup(dev, file, cmd->handles[0]);
+	gem = drm_gem_object_lookup(file, cmd->handles[0]);
 	if (!gem)
 		return ERR_PTR(-ENOENT);
 
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
index a773bfaea913..fa2ec0cd00e8 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
@@ -139,7 +139,7 @@ int mtk_drm_gem_dumb_map_offset(struct drm_file *file_priv,
 	struct drm_gem_object *obj;
 	int ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, handle);
+	obj = drm_gem_object_lookup(file_priv, handle);
 	if (!obj) {
 		DRM_ERROR("failed to lookup gem object.\n");
 		return -EINVAL;
-- 
2.7.0



From arnd at arndb.de  Wed May 18 09:07:32 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 18:07:32 +0200
Subject: [PATCH 4/5] drm: exynos: mark pm functions as __maybe_unused
In-Reply-To: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
References: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
Message-ID: <1463587653-3035181-5-git-send-email-arnd@arndb.de>

The rework of the exynos DRM clock handling introduced
warnings for configurations that have CONFIG_PM disabled:

drivers/gpu/drm/exynos/exynos_hdmi.c:736:13: error: 'hdmi_clk_disable_gates' defined but not used [-Werror=unused-function]
 static void hdmi_clk_disable_gates(struct hdmi_context *hdata)
             ^~~~~~~~~~~~~~~~~~~~~~
drivers/gpu/drm/exynos/exynos_hdmi.c:717:12: error: 'hdmi_clk_enable_gates' defined but not used [-Werror=unused-function]
 static int hdmi_clk_enable_gates(struct hdmi_context *hdata)

The problem is that the PM functions themselves are inside of
an #ifdef, but some functions they call are not.

This patch removes the #ifdef and instead marks the PM functions
as __maybe_unused, which is a more reliable way to get it right.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 9be7e9898444 ("drm/exynos/hdmi: clock code re-factoring")
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 58de5a430508..ea4b2b7d7ad7 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1934,8 +1934,7 @@ static int hdmi_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int exynos_hdmi_suspend(struct device *dev)
+static int __maybe_unused exynos_hdmi_suspend(struct device *dev)
 {
 	struct hdmi_context *hdata = dev_get_drvdata(dev);
 
@@ -1944,7 +1943,7 @@ static int exynos_hdmi_suspend(struct device *dev)
 	return 0;
 }
 
-static int exynos_hdmi_resume(struct device *dev)
+static int __maybe_unused exynos_hdmi_resume(struct device *dev)
 {
 	struct hdmi_context *hdata = dev_get_drvdata(dev);
 	int ret;
@@ -1955,7 +1954,6 @@ static int exynos_hdmi_resume(struct device *dev)
 
 	return 0;
 }
-#endif
 
 static const struct dev_pm_ops exynos_hdmi_pm_ops = {
 	SET_RUNTIME_PM_OPS(exynos_hdmi_suspend, exynos_hdmi_resume, NULL)
-- 
2.7.0



From arnd at arndb.de  Wed May 18 09:07:29 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 18:07:29 +0200
Subject: [PATCH 1/5] headers_check: don't warn about c++ guards
In-Reply-To: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
References: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
Message-ID: <1463587653-3035181-2-git-send-email-arnd@arndb.de>

A recent addition to the DRM tree for 4.7 added 'extern "C"' guards
for c++ to all the DRM headers, and that now causes warnings
in 'make headers_check':

usr/include/drm/amdgpu_drm.h:38: userspace cannot reference function or variable defined in the kernel
usr/include/drm/drm.h:63: userspace cannot reference function or variable defined in the kernel
usr/include/drm/drm.h:699: userspace cannot reference function or variable defined in the kernel
usr/include/drm/drm_fourcc.h:30: userspace cannot reference function or variable defined in the kernel
usr/include/drm/drm_mode.h:33: userspace cannot reference function or variable defined in the kernel
usr/include/drm/drm_sarea.h:38: userspace cannot reference function or variable defined in the kernel
usr/include/drm/exynos_drm.h:21: userspace cannot reference function or variable defined in the kernel
usr/include/drm/i810_drm.h:7: userspace cannot reference function or variable defined in the kernel

This changes the headers_check.pl script to not warn about this.
I'm listing the merge commit as introducing the problem, because
there are several patches in this branch that each do this for
one file.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 7c10ddf87472 ("Merge branch 'drm-uapi-extern-c-fixes' of https://github.com/evelikov/linux into drm-next")
---
 scripts/headers_check.pl | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/scripts/headers_check.pl b/scripts/headers_check.pl
index 62320f93e903..8b2da054cdc3 100755
--- a/scripts/headers_check.pl
+++ b/scripts/headers_check.pl
@@ -69,6 +69,10 @@ sub check_declarations
 	if ($line =~ m/^void seqbuf_dump\(void\);/) {
 		return;
 	}
+	# drm headers are being C++ friendly
+	if ($line =~ m/^extern "C"/) {
+		return;
+	}
 	if ($line =~ m/^(\s*extern|unsigned|char|short|int|long|void)\b/) {
 		printf STDERR "$filename:$lineno: " .
 			      "userspace cannot reference function or " .
-- 
2.7.0



From arnd at arndb.de  Wed May 18 09:08:36 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 18:08:36 +0200
Subject: [PATCH v2] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <573C8B55.3030805@suse.de>
References: <1463576010-115428-1-git-send-email-agraf@suse.de>
 <20160518151958.GH22378@e104818-lin.cambridge.arm.com>
 <573C8B55.3030805@suse.de>
Message-ID: <3270693.WrXnxabe9J@wuerfel>

On Wednesday 18 May 2016 17:33:41 Alexander Graf wrote:
> >
> >> IIRC we don't own EL3 on there.
> > Then how do you switch to AArch64?
> 
> You write into config.txt that you want to boot into AArch64 EL2 and the 
> raspberry pi firmware takes care of the rest.
> 
> 

Have you tried telling the firmware that you'd like to boot into AArch64 EL3? ;-)

	Arnd


From stern at rowland.harvard.edu  Wed May 18 09:15:44 2016
From: stern at rowland.harvard.edu (Alan Stern)
Date: Wed, 18 May 2016 12:15:44 -0400 (EDT)
Subject: [PATCH] usb: echi-hcd: Add register access check in shutdown
In-Reply-To: <573C8B40.1040503@linaro.org>
Message-ID: <Pine.LNX.4.44L0.1605181211120.1981-100000@iolanthe.rowland.org>

On Wed, 18 May 2016, Srinivas Kandagatla wrote:

> On 18/05/16 15:56, Alan Stern wrote:
> > On Wed, 18 May 2016, Srinivas Kandagatla wrote:
> >
> >> This patch adds a check in ehci_shutdown(), to make sure
> >> that the register access is available before accessing registers.
> >>
> >> The use case is simple, for boards like DB410c where the usb host
> >> or device functionality is decided based on the micro-usb cable
> >> presence. If the board boots up with micro-usb connected and the
> >> host driver is probed, but the ehci_setup() has not been done yet,
> >> then a system shutdown would trigger below NULL pointer exception
> >> without this patch.
> >
> > How can that happen?  While the host driver is probed, the probing
> > thread holds the device lock.  But the system shutdown routine acquires
> > the device lock before invoking the ->shutdown callback.  Therefore the
> > two things cannot happen concurrently.
> 
> No, I did not mean them happening concurrently, I mean that the host 
> driver is up, however ehci_setup() is not done yet.

I don't understand.  ehci_setup() is called as part of the probe 
procedure.  How can the host driver be up if ehci_setup() is not done 
yet?

Are you saying that when the system is plugged into the "B" end of an 
OTG cable, ehci_setup() doesn't get called at all?

And would the same thing happen if the system started out as the host
but then used HNP to change into the peripheral?

Alan Stern



From agraf at suse.de  Wed May 18 09:16:05 2016
From: agraf at suse.de (Alexander Graf)
Date: Wed, 18 May 2016 18:16:05 +0200
Subject: [PATCH v2] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <3270693.WrXnxabe9J@wuerfel>
References: <1463576010-115428-1-git-send-email-agraf@suse.de>
 <20160518151958.GH22378@e104818-lin.cambridge.arm.com>
 <573C8B55.3030805@suse.de> <3270693.WrXnxabe9J@wuerfel>
Message-ID: <573C9545.9050909@suse.de>

On 05/18/2016 06:08 PM, Arnd Bergmann wrote:
> On Wednesday 18 May 2016 17:33:41 Alexander Graf wrote:
>>>> IIRC we don't own EL3 on there.
>>> Then how do you switch to AArch64?
>> You write into config.txt that you want to boot into AArch64 EL2 and the
>> raspberry pi firmware takes care of the rest.
>>
>>
> Have you tried telling the firmware that you'd like to boot into AArch64 EL3? ;-)

Yes, but then you don't get any SMP initialization (so we'd have to redo 
that in U-Boot, or port ATF) and you lose the usual workflow on defining 
how the hat device tree overlays work.

Overall, I think it's an interesting goal and you're more than happy to 
be my guest, but I think that spin tables are good enough for the device 
for now :). At least we'd be able to move people away from 32bit code.


Alex



From moinejf at free.fr  Wed May 18 09:23:02 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Wed, 18 May 2016 18:23:02 +0200
Subject: [PATCH 15/16] clk: sunxi-ng: Add H3 clocks
In-Reply-To: <20160518140200.GN27618@lukather>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
 <20160513114559.786221e415ce5956e161dd5b@free.fr>
 <20160518140200.GN27618@lukather>
Message-ID: <20160518182302.e5b6b17062dade90af4829b9@free.fr>

On Wed, 18 May 2016 16:02:00 +0200
Maxime Ripard <maxime.ripard at free-electrons.com> wrote:

> On Fri, May 13, 2016 at 11:45:59AM +0200, Jean-Francois Moine wrote:
	[snip]
> > > +
> > > +static struct ccu_nm pll_audio_base_clk = {
> > > +	.enable		= BIT(31),
> > > +	.lock		= BIT(28),
> > > +
> > > +	.m		= SUNXI_CLK_FACTOR(0, 5),
> > > +	.n		= SUNXI_CLK_FACTOR(8, 7),
> > > +
> > > +	.common		= {
> > > +		.reg		= 0x008,
> > > +		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> > > +		.hw.init	= SUNXI_HW_INIT("pll-audio-base",
> > > +						"osc24M",
> > > +						&ccu_nm_ops,
> > > +						0),
> > > +	},
> > > +};
> > > +
> > > +static SUNXI_CCU_M(pll_audio_clk, "pll-audio", "pll-audio-base",
> > > +		   0x008, 16, 4, 0);
> > > +
> > > +static SUNXI_CCU_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
> > > +			      "pll-audio-base", 2, 1, 0);
> > > +static SUNXI_CCU_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
> > > +			      "pll-audio-base", 1, 1, 0);
> > > +static SUNXI_CCU_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
> > > +			      "pll-audio-base", 1, 2, 0);
> > 
> > Forcing the post divider 'p' to 4 would simplify this PLL.
> 
> Yes and no. It would simplify the clock rate computation and
> propagation across the tree, but it would also add more code in there,
> and we would not be able to read the clock rate properly.
> 
> Chaining clocks like that should also be supported and working, so I'd
> still be very much in favour of implementing it as it is supposed to
> be, and fixing whatever bug there might be in there.

See my next mail:

static SUNXI_CCU_FIXED_FACTOR(pll_audio, "pll-audio",
			      "pll-audio-base", 4, 1,
				CLK_SET_RATE_PARENT);

> > > +static struct ccu_nm pll_video_clk = {
> > > +	.enable		= BIT(31),
> > > +	.lock		= BIT(28),
> > > +
> > > +	.m		= SUNXI_CLK_FACTOR(0, 4),
> > > +	.n		= SUNXI_CLK_FACTOR(8, 7),
> > > +
> > > +	.common		= {
> > > +		.reg		= 0x010,
> > > +		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> > > +		.hw.init	= SUNXI_HW_INIT("pll-video",
> > > +						"osc24M",
> > > +						&ccu_nm_ops,
> > > +						0),
> > > +	},
> > > +};
> > 
> > The legacy u-boot I use (lichee) forces this PLL to 297MHz in
> > fractional mode (FRAC_CLK_OUT = 1 and PLL_MODE_SEL = 0).
> > As these bits are not managed, getting the rate is false and setting it
> > is not possible.
> 
> Ah, interesting.
> 
> I'll add support for fractional clocks in the next version then.
> 
> Just out of curiosity, is there any particular reason for sticking
> with Allwinner's U-Boot over using mainline U-Boot?

Allwinner's U_Boot works fine enough for me, and with it, I am sure that the hidden/unknown parts of the SoC (dram, prcm) are correctly initialized.

> > > +static struct ccu_nk pll_periph0_clk = {
> > > +	.enable		= BIT(31),
> > > +	.lock		= BIT(28),
> > > +
> > > +	.k		= SUNXI_CLK_FACTOR(4, 2),
> > > +	.n		= SUNXI_CLK_FACTOR(8, 5),
> > > +	.fixed_post_div	= 2,
> > > +
> > > +	.common		= {
> > > +		.reg		= 0x028,
> > > +		.features	= (CCU_FEATURE_GATE |
> > > +				   CCU_FEATURE_LOCK |
> > > +				   CCU_FEATURE_FIXED_POSTDIV),
> > > +		.hw.init	= SUNXI_HW_INIT("pll-periph0",
> > > +						"osc24M",
> > > +						&ccu_nk_ops,
> > > +						0),
> > > +	},
> > > +};
> > 
> > As told previously, the H3 documentation says:
> > 
> >  Note: The PLL Output should be fixed to 600MHz, it is not recommended to
> >  vary this value arbitrarily.
> > 
> > So, is it useful to offer the possibility to change the rate of this PLL
> > (and same for pll-periph1)?
> > (I force the rate in the DT with assigned-clock-rates to avoid any problem)
> 
> assigned-clock-rates will not change anything unfortunately. It sets a
> default rate at boot time, but it doesn't prevent the rate from being
> changed.
> 
> Fortunately, that rate will never be modified, since none of the child
> clock have CLK_SET_RATE_PARENT.
> 
> If that was to change, and when that time comes, we can always use the
> clk boundaries to deal with it nicely.
> 
> > > +
> > > +static SUNXI_CCU_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
> > > +			      "pll-periph0", 1, 2, 0);
> > > +
> > 	[snip]
> > > +static const char * const nand_parents[] = { "osc24M", "pll-periph0",
> > > +					     "pll-periph1" };
> > > +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", nand_parents, 0x080,
> > > +				  0, 4,		/* M */
> > > +				  16, 2,	/* P */
> > > +				  24, 2,	/* mux */
> > > +				  BIT(31),	/* gate */
> > > +				  0);
> > 
> > The mux width is 2, meaning there may be 4 parents. Then, there may be
> > an access out of the parent array (and same for mmcx and spix).
> 
> The mux relies on the number of parents registered in the clock
> framework, which is 3 in this case, so that won't happen.
> 
> Or am I missing what you're saying?
> 
> > > +
> > > +static const char * const mmc0_parents[] = { "osc24M", "pll-periph0",
> > > +					     "pll-periph1" };
> > 
> > The parent tables of nand, mmcx and spix are the same. One table should
> > be enough.
> 
> Ack.
> 
> > > +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_parents, 0x088,
> > > +				  0, 4,		/* M */
> > > +				  16, 2,	/* P */
> > > +				  24, 2,	/* mux */
> > > +				  BIT(31),	/* gate */
> > > +				  0);
> > > +
> > > +static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0",
> > > +		       0x088, 20, 3, 0);
> > > +static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0",
> > > +		       0x088, 8, 3, 0);
> > 	[snip]
> > > +static const char * const i2s0_parents[] = { "pll-audio-8x", "pll-audio-4x",
> > > +					     "pll-audio-2x" , "pll-audio" };
> > > +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s0_parents,
> > > +			       0x0b0, 16, 2, BIT(31), 0);
> > > +
> > > +static const char * const i2s1_parents[] = { "pll-audio-8x", "pll-audio-4x",
> > > +					     "pll-audio-2x" , "pll-audio" };
> > > +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s1_parents,
> > > +			       0x0b4, 16, 2, BIT(31), 0);
> > > +
> > > +static const char * const i2s2_parents[] = { "pll-audio-8x", "pll-audio-4x",
> > > +					     "pll-audio-2x" , "pll-audio" };
> > > +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s2_parents,
> > > +			       0x0b8, 16, 2, BIT(31), 0);
> > 	[snip]
> > 
> > Same parent tables.
> > This occurs for other clocks.
> 
> Ack.
> 
> Thanks!
> Maxime
> 
> -- 
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com


-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From moinejf at free.fr  Wed May 18 09:27:24 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Wed, 18 May 2016 18:27:24 +0200
Subject: [PATCH 15/16] clk: sunxi-ng: Add H3 clocks
In-Reply-To: <20160518140200.GN27618@lukather>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
 <20160513114559.786221e415ce5956e161dd5b@free.fr>
 <20160518140200.GN27618@lukather>
Message-ID: <20160518182724.bf9137a9c04ac670457fc083@free.fr>

Hi Maxime,

Sorry, my previous mail was sent while not finished!

On Wed, 18 May 2016 16:02:00 +0200
Maxime Ripard <maxime.ripard at free-electrons.com> wrote:

> On Fri, May 13, 2016 at 11:45:59AM +0200, Jean-Francois Moine wrote:
	[snip]
> > > +static const char * const nand_parents[] = { "osc24M", "pll-periph0",
> > > +					     "pll-periph1" };
> > > +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", nand_parents, 0x080,
> > > +				  0, 4,		/* M */
> > > +				  16, 2,	/* P */
> > > +				  24, 2,	/* mux */
> > > +				  BIT(31),	/* gate */
> > > +				  0);
> > 
> > The mux width is 2, meaning there may be 4 parents. Then, there may be
> > an access out of the parent array (and same for mmcx and spix).
> 
> The mux relies on the number of parents registered in the clock
> framework, which is 3 in this case, so that won't happen.
> 
> Or am I missing what you're saying?

Sorry, at this time, I did not look yet at the macros.
There is no problem here.

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From robh at kernel.org  Wed May 18 09:37:32 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 18 May 2016 11:37:32 -0500
Subject: [PATCH v2 4/6] ir-rx51: add DT support to driver
In-Reply-To: <1463427254-7728-5-git-send-email-ivo.g.dimitrov.75@gmail.com>
References: <1463427254-7728-1-git-send-email-ivo.g.dimitrov.75@gmail.com>
 <1463427254-7728-5-git-send-email-ivo.g.dimitrov.75@gmail.com>
Message-ID: <20160518163732.GA25142@rob-hp-laptop>

On Mon, May 16, 2016 at 10:34:12PM +0300, Ivaylo Dimitrov wrote:
> With the upcoming removal of legacy boot, lets add support to one of the
> last N900 drivers remaining without it. As the driver still uses omap
> dmtimer, add auxdata as well.
> 
> Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75 at gmail.com>
> ---
>  .../devicetree/bindings/media/nokia,n900-ir          | 20 ++++++++++++++++++++
>  arch/arm/mach-omap2/pdata-quirks.c                   |  6 +-----
>  drivers/media/rc/ir-rx51.c                           | 11 ++++++++++-
>  3 files changed, 31 insertions(+), 6 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/media/nokia,n900-ir

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


From robh at kernel.org  Wed May 18 09:42:59 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 18 May 2016 11:42:59 -0500
Subject: [PATCH] drivers: nvmem: atmel-secumod: New driver for Atmel
 Secumod nvram
In-Reply-To: <1463429830-20539-1-git-send-email-davidm@egauge.net>
References: <alpine.LNX.2.00.1605121505320.21379@nippy.intranet>
 <1463429830-20539-1-git-send-email-davidm@egauge.net>
Message-ID: <20160518164259.GA28954@rob-hp-laptop>

On Mon, May 16, 2016 at 02:17:10PM -0600, David Mosberger-Tang wrote:
> Signed-off-by: David Mosberger <davidm at egauge.net>
> ---
>  .../devicetree/bindings/nvmem/atmel-secumod.txt    |  46 ++++++++
>  drivers/nvmem/atmel-secumod.c                      | 125 +++++++++++++++++++++
>  2 files changed, 171 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
>  create mode 100644 drivers/nvmem/atmel-secumod.c
> 
> diff --git a/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
> new file mode 100644
> index 0000000..85db709
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
> @@ -0,0 +1,46 @@
> += Atmel Secumod device tree bindings =
> +
> +This binding is intended to represent Atmel's Secumod which is found
> +in SAMA5D2 and perhaps others.
> +
> +Required properties:
> +- compatible: should be "atmel,sama5d2-secumod"
> +- reg: Should contain registers location and length of the RAM, followed

registers or RAM location?

"Should contain RAM location and length, ..."

> +       by register location and length of the Secumod controller.
> +
> += Data cells =
> +Are child nodes of secumod, bindings of which as described in
> +bindings/nvmem/nvmem.txt
> +
> +Example:
> +
> +    secumod at fc040000 {
> +            compatible = "atmel,sama5d2-secumod";
> +            reg = <0xf8044000 0x1420
> +                   0xfc040000 0x4000>;

You are missing ranges property.

> +            status = "okay";
> +
> +            #address-cells = <1>;
> +            #size-cells = <1>;
> +
> +            secram_auto_erasable at 0000 {

Use '-' rather than '_' and drop leading 0s.

> +                    reg = <0x0000 0x1000>;
> +            };
> +            secram at 1000 {
> +                    reg = <0x1000 0x400>;
> +            };
> +            ram at 1400 {
> +                    reg = <0x1400 0x20>;
> +            };
> +    };
> +
> += Data consumers =
> +Are device nodes which consume nvmem data cells.
> +
> +For example:
> +
> +	ram {
> +		...
> +		nvmem-cells = <&ram>;
> +		nvmem-cell-names = "RAM";
> +	};


From andre.przywara at arm.com  Wed May 18 09:46:55 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 18 May 2016 17:46:55 +0100
Subject: [PATCH v4 22/56] KVM: arm/arm64: vgic-new: Add MMIO handling
 framework
In-Reply-To: <20160518122521.GD3827@cbox>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-23-git-send-email-andre.przywara@arm.com>
 <573B1DB0.7030901@arm.com> <20160518122521.GD3827@cbox>
Message-ID: <573C9C7F.9020209@arm.com>

Hi,

>>> +
>>> +/* generate a mask that covers 1024 interrupts with <b> bits per IRQ */
>>
>> Hmmm. I'd appreciate some additional comments, specially when it comes
>> to the various restrictions. May I'd suggest something like:
>>
>> /*
>>  * Generate a mask that covers the number of bytes required to address
>>  * up to 1024 interrupts, each represented by <b> bits. This assumes
>>  * that <b> is a power of two.
>>  *
>>  * ilog2(b) + ilog2(1024) is the number of bits required to bit-address
>>  * 1024 interrupts, each represented by b bits. Minus ilog2(8) converts
>>  * this to a byte address.
> 
> So I'm guessting this is a rewrite of ilog2( (b * 1024) / 8), but I'm
> stupid enough to not understand our use of logarithms here.  Can someone
> remind me whatever I forgot at CS 101?

I guess it was more me not seeing the wood for the trees here:
Indeed doing the multiplication first and then calling ilog2 seems to
make more sense. Also I was thinking: Isn't
"GENMASK_ULL(ilog2(n) - 1, 0)" the same as "n - 1"?

So can't we just write:

#define VGIC_ADDR_IRQ_MASK(bpi) (((bpi) * 1024 / 8) - 1)

Proven by enumeration - over the values we use ;-)

I'd keep the first paragraph of Marc's comment above then, but we can
avoid mentioning Advanced Maths textbooks about binary logarithmic ;-)

Cheers,
Andre.

>>  */
>>
>>> +#define VGIC_ADDR_IRQ_MASK(b) GENMASK_ULL(ilog2(b) + ilog2(1024) - \
>>> +					  ilog2(BITS_PER_BYTE) - 1, 0)
>>
>> /*
>>  * Convert a base address into a base interrupt (each interrupt
>>  * represented by <bits> bits. This assumes that <bits> is a power
>>  * of two, that <addr> both part of a memory region aligned on a
> 
> did you mean '<addr> *is* both part of' ?
> 
>>  * <b> bits boundary, and itself aligned on that same boundary
>>  * (for regions that describe an interrupt with more than a single
>>  * byte of data).
>>  */
>>
> 
> In any case, thanks for the commentary, I was faily lost here.
> 


From christoffer.dall at linaro.org  Wed May 18 10:03:49 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 19:03:49 +0200
Subject: [PATCH v3] KVM: arm/arm64: Add VGICv3 save/restore API
 documentation
In-Reply-To: <CAFEAcA8fcxo18HhfboE5j=SC8TyrPXqmpsPNymM8zw4PhMTRDw@mail.gmail.com>
References: <1463150637-6896-1-git-send-email-christoffer.dall@linaro.org>
 <CAFEAcA8fcxo18HhfboE5j=SC8TyrPXqmpsPNymM8zw4PhMTRDw@mail.gmail.com>
Message-ID: <20160518170349.GL6666@cbox>

On Fri, May 13, 2016 at 04:28:44PM +0100, Peter Maydell wrote:
> On 13 May 2016 at 15:43, Christoffer Dall <christoffer.dall at linaro.org> wrote:
> > Factor out the GICv3-specific documentation into a separate
> > documentation file.  Add description for how to access distributor,
> > redistributor, and CPU interface registers for GICv3 in this new file,
> > and add a group for accesing level triggered IRQ information for GICv3
> > as well.
> >
> > Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> > ---
> > Changes since v2:
> >  - Changed distributor access to be 32-bits in size
> >  - Clearly specified data type pointed to by addr field
> >  - Specified exception behavior for STATUSR registers
> >  - Added group for level-triggered IRQ status info
> >  - Removed acks from Marc/Peter as content has changed
> 
> Hi; I have one substantial point and a few typos to point out.
> 
> >  Documentation/virtual/kvm/devices/arm-vgic-v3.txt | 176 ++++++++++++++++++++++
> >  Documentation/virtual/kvm/devices/arm-vgic.txt    |  21 +--
> >  2 files changed, 180 insertions(+), 17 deletions(-)
> >  create mode 100644 Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> >
> > diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> > new file mode 100644
> > index 0000000..69201e8
> > --- /dev/null
> > +++ b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> > @@ -0,0 +1,176 @@
> > +ARM Virtual Generic Interrupt Controller v3 and later (VGICv3)
> > +==============================================================
> > +
> > +
> > +Device types supported:
> > +  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
> > +
> > +Only one VGIC instance may be instantiated through this API.  The created VGIC
> > +will act as the VM interrupt controller, requiring emulated user-space devices
> > +to inject interrupts to the VGIC instead of directly to CPUs.  It is not
> > +possible to create both a GICv3 and GICv2 on the same VM.
> > +
> > +Creating a guest GICv3 device requires a host GICv3 as well.
> > +
> > +Groups:
> > +  KVM_DEV_ARM_VGIC_GRP_ADDR
> > +  Attributes:
> > +    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
> > +      Base address in the guest physical address space of the GICv3 distributor
> > +      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> > +      This address needs to be 64K aligned and the region covers 64 KByte.
> > +
> > +    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
> > +      Base address in the guest physical address space of the GICv3
> > +      redistributor register mappings. There are two 64K pages for each
> > +      VCPU and all of the redistributor pages are contiguous.
> > +      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> > +      This address needs to be 64K aligned.
> > +
> > +
> > +  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
> > +  KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
> > +  Attributes:
> > +    The attr field of kvm_device_attr encodes two values:
> > +    bits:     | 63   ....  32  |  31   ....    0 |
> > +    values:   |      mpidr     |      offset     |
> > +
> > +    All distributor regs are (rw, 32-bit) and kvm_device_attr.addr points to a
> > +    __u32 value.  64-bit registers must be accessed by separately accessing the
> > +    lower and higher word.
> > +
> > +    Writes to read-only registers can be ignored by the kernel.
> 
> Presumably "are ignored".
> 
> > +
> > +    KVM_DEV_ARM_VGIC_GRP_DIST_REGS accesses the main distributor registers.
> > +    KVM_DEV_ARM_VGIC_GRP_REDIST_REGS accesses the redistributor of the CPU
> > +    specified by the mpidr.
> > +
> > +    The offset is relative to the "[Re]Distributor base address" as defined
> > +    in the GICv3/4 specs.  Getting or setting such a register has the same
> > +    effect as reading or writing the register on real hardware (except for
> > +    GICD_STATUS and GICR_STATUSR, see blow), and the mpidr field is used to
> 
> "GICD_STATUSR". "below".
> 
> > +    specify which redistributor is accessed.  The mpidr is ignored for the
> > +    distributor.
> > +
> > +    The mpidr encoding is based on the affinity information in the
> > +    architecture defined MPIDR, and the field is encoded as follows:
> > +      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
> > +      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
> > +
> > +    Note that distributor fields are not banked, but return the same value
> > +    regardless of the mpidr used to access the register.
> > +
> > +    The GICD_STATUSR and GICR_STATUSR registers are architecturally defined such
> > +    that a write of a clear bit has no effect, whereas a write with a set bit
> > +    clears that value.  To allow userspace to freely set the values of these two
> > +    registers, setting the attributes with the register offsets for these two
> > +    registers simply sets the non-reserved bits to the value written.
> > +  Limitations:
> > +    - Priorities are not implemented, and registers are RAZ/WI
> > +  Errors:
> > +    -ENXIO: Getting or setting this register is not yet supported
> > +    -EBUSY: One or more VCPUs are running
> > +
> > +
> > +  KVM_DEV_ARM_VGIC_CPU_SYSREGS
> > +  Attributes:
> > +    The attr field of kvm_device_attr encodes two values:
> > +    bits:     | 63      ....       32 | 31  ....  16 | 15  ....  0 |
> > +    values:   |         mpidr         |      RES     |    instr    |
> > +
> > +    The mpidr field encodes the CPU ID based on the affinity information in the
> > +    architecture defined MPIDR, and the field is encoded as follows:
> > +      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
> > +      |    Aff3    |    Aff2    |    Aff1    |    Aff0   |
> 
> ASCII art diagram missing a space after "Aff0" ?
> 
> > +
> > +  KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO
> > +  Attributes:
> > +    The attr field of kvm_device_attr encodes the following values:
> > +    bits:     | 63      ....       32 | 31   ....    10 | 9  ....  0 |
> > +    values:   |         mpidr         |      info       |   vINTID   |
> > +
> > +    The vINTID specifies which set of IRQs is reported on.
> > +
> > +    The info field specifies which information userspace wants to get or set
> > +    using this interface.  Currently we support two different pieces of
> > +    information:
> > +
> > +      VGIC_LEVEL_INFO_LINE_LEVEL:
> > +        Get/Set the intput level of the IRQ line for a given IRQ.
> 
> "input"
> 
> > +       vINTID must be a multiple of 32.
> > +
> > +        kvm_device_attr.addr points to a __u32 value which will contain a
> > +       bitmap where a set bit means the interrupt level is asserted.
> > +
> > +       Bit[n] indicates the status for interrupt vINTID + n.
> > +
> > +
> > +      VGIC_LEVEL_INFO_SOFT_PENDING
> > +        Get/Set the latch state of a GIVEN level-triggered IRQ as manipulated by
> 
> Why is "given" capitalised?

Just a mistake, some magic VIM keystroke must have happenede here.

> 
> I would like this to simply get/set the latch state regardless of whether
> the interrupt is edge triggered or level triggered. (Obviously if the
> interrupt is edge triggered this is equivalent to accessing the
> ISPENDR/ICPENDR registers, but I don't want in userspace to have to
> manually look at whether each interrupt is edge or level in order to
> identify whether to use ISPENDR or this API, when in fact the state
> in the kernel is exactly the same. I just want a straightforward
> get/set accessor to the underlying state.)
> 

I think my reservations against this come from the fact that we're
getting farther and farther away from anything that looks like
software's interface to the GIC hardware as specified by the
architecture, and it was kind of the motivation for our choice of API
here in the first place to try to stay close to that.

That being said, what we're designing an API for here is a different
case that for what the software view of the hardware via registers has
been designed for, so potentially it's ok to deviate from that.

How about we special-case the SPENDR region, and make CPENDR region
RAZ/WI, and the SPENDR region then reflects the latch state exclusively.
Or is this more confusing than just having a separate 'fake' region?

Do you have a suggestion in mind for wording/naming of the 'latch state'
that makes sense for software people who have access to the GIC manual,
but doesn't necessarily understand how the hardware would be built and
why 'latch state' logically has clear semantics... ?

Thanks,
-Christoffer


From christoffer.dall at linaro.org  Wed May 18 10:04:13 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 19:04:13 +0200
Subject: [PATCH v3] KVM: arm/arm64: Add VGICv3 save/restore API
 documentation
In-Reply-To: <5735ED2F.4030104@arm.com>
References: <1463150637-6896-1-git-send-email-christoffer.dall@linaro.org>
 <5735ED2F.4030104@arm.com>
Message-ID: <20160518170413.GM6666@cbox>

On Fri, May 13, 2016 at 04:05:19PM +0100, Marc Zyngier wrote:
> On 13/05/16 15:43, Christoffer Dall wrote:
> > Factor out the GICv3-specific documentation into a separate
> > documentation file.  Add description for how to access distributor,
> > redistributor, and CPU interface registers for GICv3 in this new file,
> > and add a group for accesing level triggered IRQ information for GICv3
> 
> accessing
> 
> > as well.
> > 
> > Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> > ---
> > Changes since v2:
> >  - Changed distributor access to be 32-bits in size
> >  - Clearly specified data type pointed to by addr field
> >  - Specified exception behavior for STATUSR registers
> >  - Added group for level-triggered IRQ status info
> >  - Removed acks from Marc/Peter as content has changed
> > 
> >  Documentation/virtual/kvm/devices/arm-vgic-v3.txt | 176 ++++++++++++++++++++++
> >  Documentation/virtual/kvm/devices/arm-vgic.txt    |  21 +--
> >  2 files changed, 180 insertions(+), 17 deletions(-)
> >  create mode 100644 Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> > 
> > diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> > new file mode 100644
> > index 0000000..69201e8
> > --- /dev/null
> > +++ b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> > @@ -0,0 +1,176 @@
> > +ARM Virtual Generic Interrupt Controller v3 and later (VGICv3)
> > +==============================================================
> > +
> > +
> > +Device types supported:
> > +  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
> > +
> > +Only one VGIC instance may be instantiated through this API.  The created VGIC
> > +will act as the VM interrupt controller, requiring emulated user-space devices
> > +to inject interrupts to the VGIC instead of directly to CPUs.  It is not
> > +possible to create both a GICv3 and GICv2 on the same VM.
> > +
> > +Creating a guest GICv3 device requires a host GICv3 as well.
> > +
> > +Groups:
> > +  KVM_DEV_ARM_VGIC_GRP_ADDR
> > +  Attributes:
> > +    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
> > +      Base address in the guest physical address space of the GICv3 distributor
> > +      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> > +      This address needs to be 64K aligned and the region covers 64 KByte.
> > +
> > +    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
> > +      Base address in the guest physical address space of the GICv3
> > +      redistributor register mappings. There are two 64K pages for each
> > +      VCPU and all of the redistributor pages are contiguous.
> > +      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> > +      This address needs to be 64K aligned.
> > +
> > +
> > +  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
> > +  KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
> > +  Attributes:
> > +    The attr field of kvm_device_attr encodes two values:
> > +    bits:     | 63   ....  32  |  31   ....    0 |
> > +    values:   |      mpidr     |      offset     |
> > +
> > +    All distributor regs are (rw, 32-bit) and kvm_device_attr.addr points to a
> > +    __u32 value.  64-bit registers must be accessed by separately accessing the
> > +    lower and higher word.
> > +
> > +    Writes to read-only registers can be ignored by the kernel.
> > +
> > +    KVM_DEV_ARM_VGIC_GRP_DIST_REGS accesses the main distributor registers.
> > +    KVM_DEV_ARM_VGIC_GRP_REDIST_REGS accesses the redistributor of the CPU
> > +    specified by the mpidr.
> > +
> > +    The offset is relative to the "[Re]Distributor base address" as defined
> > +    in the GICv3/4 specs.  Getting or setting such a register has the same
> > +    effect as reading or writing the register on real hardware (except for
> > +    GICD_STATUS and GICR_STATUSR, see blow), and the mpidr field is used to
> 
>                                          below
> 
> > +    specify which redistributor is accessed.  The mpidr is ignored for the
> > +    distributor.
> > +
> > +    The mpidr encoding is based on the affinity information in the
> > +    architecture defined MPIDR, and the field is encoded as follows:
> > +      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
> > +      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
> > +
> > +    Note that distributor fields are not banked, but return the same value
> > +    regardless of the mpidr used to access the register.
> > +
> > +    The GICD_STATUSR and GICR_STATUSR registers are architecturally defined such
> > +    that a write of a clear bit has no effect, whereas a write with a set bit
> > +    clears that value.  To allow userspace to freely set the values of these two
> > +    registers, setting the attributes with the register offsets for these two
> > +    registers simply sets the non-reserved bits to the value written.
> > +  Limitations:
> > +    - Priorities are not implemented, and registers are RAZ/WI
> > +  Errors:
> > +    -ENXIO: Getting or setting this register is not yet supported
> > +    -EBUSY: One or more VCPUs are running
> > +
> > +
> > +  KVM_DEV_ARM_VGIC_CPU_SYSREGS
> > +  Attributes:
> > +    The attr field of kvm_device_attr encodes two values:
> > +    bits:     | 63      ....       32 | 31  ....  16 | 15  ....  0 |
> > +    values:   |         mpidr         |      RES     |    instr    |
> > +
> > +    The mpidr field encodes the CPU ID based on the affinity information in the
> > +    architecture defined MPIDR, and the field is encoded as follows:
> > +      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
> > +      |    Aff3    |    Aff2    |    Aff1    |    Aff0   |
> > +
> > +    The instr field encodes the system register to access based on the fields
> > +    defined in the A64 instruction set encoding for system register access
> > +    (RES means the bits are reserved for future use and should be zero):
> 
> Should we call this field RES0 in order to match the various
> architecture documents?
> 
> > +
> > +      | 15 ... 14 | 13 ... 11 | 10 ... 7 | 6 ... 3 | 2 ... 0 |
> > +      |   Op 0    |    Op1    |    CRn   |   CRm   |   Op2   |
> > +
> > +    All system regs accessed through this API are (rw, 64-bit) and
> > +    kvm_device_attr.addr points to a __u64 value.
> > +
> > +    KVM_DEV_ARM_VGIC_CPU_SYSREGS accesses the CPU interface registers for the
> > +    CPU specified by the mpidr field.
> > +
> > +
> > +  Limitations:
> > +    - Priorities are not implemented, and registers are RAZ/WI
> 
> Is that still true? We should also document the lack of Group0 support.
> 
> > +  Errors:
> > +    -ENXIO: Getting or setting this register is not yet supported
> > +    -EBUSY: VCPU is running
> > +    -EINVAL: Invalid mpidr supplied
> > +
> > +
> > +  KVM_DEV_ARM_VGIC_GRP_NR_IRQS
> > +  Attributes:
> > +    A value describing the number of interrupts (SGI, PPI and SPI) for
> > +    this GIC instance, ranging from 64 to 1024, in increments of 32.
> > +
> > +    kvm_device_attr.addr points to a __u32 value.
> > +
> > +  Errors:
> > +    -EINVAL: Value set is out of the expected range
> > +    -EBUSY: Value has already be set.
> > +
> > +
> > +  KVM_DEV_ARM_VGIC_GRP_CTRL
> > +  Attributes:
> > +    KVM_DEV_ARM_VGIC_CTRL_INIT
> > +      request the initialization of the VGIC, no additional parameter in
> > +      kvm_device_attr.addr.
> > +  Errors:
> > +    -ENXIO: VGIC not properly configured as required prior to calling
> > +     this attribute
> > +    -ENODEV: no online VCPU
> > +    -ENOMEM: memory shortage when allocating vgic internal data
> > +
> > +
> > +  KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO
> > +  Attributes:
> > +    The attr field of kvm_device_attr encodes the following values:
> > +    bits:     | 63      ....       32 | 31   ....    10 | 9  ....  0 |
> > +    values:   |         mpidr         |      info       |   vINTID   |
> > +
> > +    The vINTID specifies which set of IRQs is reported on.
> > +
> > +    The info field specifies which information userspace wants to get or set
> > +    using this interface.  Currently we support two different pieces of
> > +    information:
> > +
> > +      VGIC_LEVEL_INFO_LINE_LEVEL:
> > +        Get/Set the intput level of the IRQ line for a given IRQ.
> > +	vINTID must be a multiple of 32.
> 
> Is it for a single interrupt, or a set of 32 interrupts? I believe this
> is the latter, so the "for a given IRQ" is a bit misleading ("for a set
> of 32 contiguous interrupts"?).
> 
> > +
> > +        kvm_device_attr.addr points to a __u32 value which will contain a
> > +	bitmap where a set bit means the interrupt level is asserted.
> > +
> > +	Bit[n] indicates the status for interrupt vINTID + n.
> > +
> > +
> > +      VGIC_LEVEL_INFO_SOFT_PENDING
> > +        Get/Set the latch state of a GIVEN level-triggered IRQ as manipulated by
> > +	guest writes to GICD_SPENDR.
> > +	vINTID must be a multiple of 32.
> 
> Same here. Also, can you clear the soft-pending bit through this
> interface? If so, this is not equivalent to a write to GICD_SPENDR.
> 
> > +
> > +        kvm_device_attr.addr points to a __u32 value which will contain a
> > +	bitmap where a set bit means the guest has set the interrupt by writing
> > +	to the SPENDR.
> > +
> > +	Bit[n] indicates the status for interrupt vINTID + n.
> > +
> > +
> > +    SGIs and any interrupt with a higher ID than the number of interrupts
> 
>                                             INTID
> 
> > +    supported, will be RAZ/WI.  LPIs are always edge-triggered and are
> > +    therefore not supported by this interface.
> > +
> > +    PPIs are reported per VCPU as specified in the mpidr field, and SPIs are
> > +    reported with the same value regardless of the mpidr specified.
> > +
> > +    The mpidr field encodes the CPU ID based on the affinity information in the
> > +    architecture defined MPIDR, and the field is encoded as follows:
> > +      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
> > +      |    Aff3    |    Aff2    |    Aff1    |    Aff0   |
> > diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
> > index 59541d4..257b854 100644
> > --- a/Documentation/virtual/kvm/devices/arm-vgic.txt
> > +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
> > @@ -3,16 +3,16 @@ ARM Virtual Generic Interrupt Controller (VGIC)
> >  
> >  Device types supported:
> >    KVM_DEV_TYPE_ARM_VGIC_V2     ARM Generic Interrupt Controller v2.0
> > -  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
> >  
> >  Only one VGIC instance may be instantiated through either this API or the
> >  legacy KVM_CREATE_IRQCHIP api.  The created VGIC will act as the VM interrupt
> >  controller, requiring emulated user-space devices to inject interrupts to the
> >  VGIC instead of directly to CPUs.
> >  
> > -Creating a guest GICv3 device requires a host GICv3 as well.
> > -GICv3 implementations with hardware compatibility support allow a guest GICv2
> > -as well.
> > +GICv3 implementations with hardware compatibility support allow creating a
> > +guest GICv2 through this interface.  For information on creating a guest GICv3
> > +device, see arm-vgic-v3.txt.  It is not possible to create both a GICv3 and
> > +GICv2 device on the same VM.
> >  
> >  Groups:
> >    KVM_DEV_ARM_VGIC_GRP_ADDR
> > @@ -27,19 +27,6 @@ Groups:
> >        interface register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2.
> >        This address needs to be 4K aligned and the region covers 4 KByte.
> >  
> > -    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
> > -      Base address in the guest physical address space of the GICv3 distributor
> > -      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> > -      This address needs to be 64K aligned and the region covers 64 KByte.
> > -
> > -    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
> > -      Base address in the guest physical address space of the GICv3
> > -      redistributor register mappings. There are two 64K pages for each
> > -      VCPU and all of the redistributor pages are contiguous.
> > -      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> > -      This address needs to be 64K aligned.
> > -
> > -
> >    KVM_DEV_ARM_VGIC_GRP_DIST_REGS
> >    Attributes:
> >      The attr field of kvm_device_attr encodes two values:
> > 
> 

Ack on all your points, will consider them on respin.

-Christoffer


From srinivas.kandagatla at linaro.org  Wed May 18 10:06:04 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Wed, 18 May 2016 18:06:04 +0100
Subject: [PATCH] usb: echi-hcd: Add register access check in shutdown
In-Reply-To: <Pine.LNX.4.44L0.1605181211120.1981-100000@iolanthe.rowland.org>
References: <Pine.LNX.4.44L0.1605181211120.1981-100000@iolanthe.rowland.org>
Message-ID: <573CA0FC.4010700@linaro.org>



On 18/05/16 17:15, Alan Stern wrote:
> On Wed, 18 May 2016, Srinivas Kandagatla wrote:
>
>> On 18/05/16 15:56, Alan Stern wrote:
>>> On Wed, 18 May 2016, Srinivas Kandagatla wrote:
>>>
>>>> This patch adds a check in ehci_shutdown(), to make sure
>>>> that the register access is available before accessing registers.
>>>>
>>>> The use case is simple, for boards like DB410c where the usb host
>>>> or device functionality is decided based on the micro-usb cable
>>>> presence. If the board boots up with micro-usb connected and the
>>>> host driver is probed, but the ehci_setup() has not been done yet,
>>>> then a system shutdown would trigger below NULL pointer exception
>>>> without this patch.
>>>
>>> How can that happen?  While the host driver is probed, the probing
>>> thread holds the device lock.  But the system shutdown routine acquires
>>> the device lock before invoking the ->shutdown callback.  Therefore the
>>> two things cannot happen concurrently.
>>
>> No, I did not mean them happening concurrently, I mean that the host
>> driver is up, however ehci_setup() is not done yet.
>
> I don't understand.  ehci_setup() is called as part of the probe
> procedure.  How can the host driver be up if ehci_setup() is not done
> yet?
>
Yes, this is true in ehci-msm driver, The driver does not add usb host 
by default in probe when phy is otg capable.

The usb host is added dynamically by the msm_otg driver depending on the 
the micro USB cable plug/un-plug events via extcon.

> Are you saying that when the system is plugged into the "B" end of an
> OTG cable, ehci_setup() doesn't get called at all?
>
Yes, for echi-msm driver, not sure about other host controller drivers.

> And would the same thing happen if the system started out as the host
> but then used HNP to change into the peripheral?
I don't think so, As the ehci->regs get populated once we enter the 
ehci_setup(), so ehci_halt() will never get chance to dereference null 
in this case.

Fault occurs only if the driver did not enter into host mode and system 
reboot/shutdown is requested.

--srini


>
> Alan Stern
>


From christoffer.dall at linaro.org  Wed May 18 10:08:49 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 19:08:49 +0200
Subject: [PATCH v4 22/56] KVM: arm/arm64: vgic-new: Add MMIO handling
 framework
In-Reply-To: <573C9C7F.9020209@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-23-git-send-email-andre.przywara@arm.com>
 <573B1DB0.7030901@arm.com> <20160518122521.GD3827@cbox>
 <573C9C7F.9020209@arm.com>
Message-ID: <20160518170849.GN6666@cbox>

On Wed, May 18, 2016 at 05:46:55PM +0100, Andre Przywara wrote:
> Hi,
> 
> >>> +
> >>> +/* generate a mask that covers 1024 interrupts with <b> bits per IRQ */
> >>
> >> Hmmm. I'd appreciate some additional comments, specially when it comes
> >> to the various restrictions. May I'd suggest something like:
> >>
> >> /*
> >>  * Generate a mask that covers the number of bytes required to address
> >>  * up to 1024 interrupts, each represented by <b> bits. This assumes
> >>  * that <b> is a power of two.
> >>  *
> >>  * ilog2(b) + ilog2(1024) is the number of bits required to bit-address
> >>  * 1024 interrupts, each represented by b bits. Minus ilog2(8) converts
> >>  * this to a byte address.
> > 
> > So I'm guessting this is a rewrite of ilog2( (b * 1024) / 8), but I'm
> > stupid enough to not understand our use of logarithms here.  Can someone
> > remind me whatever I forgot at CS 101?
> 
> I guess it was more me not seeing the wood for the trees here:
> Indeed doing the multiplication first and then calling ilog2 seems to
> make more sense. Also I was thinking: Isn't
> "GENMASK_ULL(ilog2(n) - 1, 0)" the same as "n - 1"?

if there's no integer rounding taking place with ilog2 (iow. n is a
power of 2) then yes, I believe it is.

> 
> So can't we just write:
> 
> #define VGIC_ADDR_IRQ_MASK(bpi) (((bpi) * 1024 / 8) - 1)

that certianly all of the sudden feels intuitive.

> 
> Proven by enumeration - over the values we use ;-)
> 
> I'd keep the first paragraph of Marc's comment above then, but we can
> avoid mentioning Advanced Maths textbooks about binary logarithmic ;-)
> 

Haha, you saved my day with that comment.  I feel slightly less idiotic
now, yes, let's call it advanced quantum math or something instead of CS
101 :)

-Christoffer

> 
> >>  */
> >>
> >>> +#define VGIC_ADDR_IRQ_MASK(b) GENMASK_ULL(ilog2(b) + ilog2(1024) - \
> >>> +					  ilog2(BITS_PER_BYTE) - 1, 0)
> >>
> >> /*
> >>  * Convert a base address into a base interrupt (each interrupt
> >>  * represented by <bits> bits. This assumes that <bits> is a power
> >>  * of two, that <addr> both part of a memory region aligned on a
> > 
> > did you mean '<addr> *is* both part of' ?
> > 
> >>  * <b> bits boundary, and itself aligned on that same boundary
> >>  * (for regions that describe an interrupt with more than a single
> >>  * byte of data).
> >>  */
> >>
> > 
> > In any case, thanks for the commentary, I was faily lost here.
> > 


From dinguyen at kernel.org  Wed May 18 10:08:57 2016
From: dinguyen at kernel.org (Dinh Nguyen)
Date: Wed, 18 May 2016 12:08:57 -0500
Subject: [GIT PULL] SoCFPGA DTS updates for v4.7, part3
In-Reply-To: <2600031.fLUcj7Vapa@wuerfel>
References: <1462891391-13876-1-git-send-email-dinguyen@kernel.org>
 <2600031.fLUcj7Vapa@wuerfel>
Message-ID: <573CA1A9.9020809@kernel.org>



On 05/17/2016 05:43 PM, Arnd Bergmann wrote:
> On Tuesday 10 May 2016 09:43:11 Dinh Nguyen wrote:
>> If not too late, please pull in this patch for v4.7.
>>
>> Thanks,
>> Dinh
>>
>> The following changes since commit 02da2d72174c61988eb4456b53f405e3ebdebce4:
>>
>>   Linux 4.6-rc5 (2016-04-24 16:17:05 -0700)
>>
>> are available in the git repository at:
>>
>>   git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git socfpga_for_next_v4.7_dts_part_3
>>
>> for you to fetch changes up to fca689561e8170ad954b982b9ce2160a06d9435e:
>>
>>   ARM: dts: socfpga: add ethernet alias on Arria10 (2016-05-03 09:25:21 -0500)
>>
>> ----------------------------------------------------------------
>> SoCFPGA DTS update for v4.7, part 3
>> - Add ethernet alias on Arria10
>>
> 
> I was going to put this into the next/late branch that already has some other
> changes, but in the end I decided to drop it because it is based on
> a later -rc release than the other branches, and doesn't seem obvious
> or important enough.
> 

That's fine. I can queue it for v4.8.

> Just a clarification about the contents of the patch, you write:
> 
>     Without having an ethernet alias, ethernet will have a random MAC address,
>     versus take an address that was provided from the bootloader.
> 
> Why is the alias needed to get the right MAC address? How does the
> bootloader pass it?
> 

For example, if U-Boot's ethaddr environment is set, the MAC address
gets populated in the mac-address property of the node with "ethernet"
alias.

Dinh



From daniel at ffwll.ch  Wed May 18 10:17:08 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Wed, 18 May 2016 19:17:08 +0200
Subject: [PATCH 5/5] drm: remove unused dev variables
In-Reply-To: <1463587653-3035181-6-git-send-email-arnd@arndb.de>
References: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
 <1463587653-3035181-6-git-send-email-arnd@arndb.de>
Message-ID: <20160518171708.GJ27098@phenom.ffwll.local>

On Wed, May 18, 2016 at 06:07:33PM +0200, Arnd Bergmann wrote:
> After drm_gem_object_lookup() was changed along with all its callers,
> we have several drivers that have unused variables:
> 
> drm/armada/armada_crtc.c: In function 'armada_drm_crtc_cursor_set':
> drm/armada/armada_crtc.c:900:21: error: unused variable 'dev' [-Werror=unused-variable]
> drm/nouveau/nouveau_gem.c: In function 'validate_init':
> drm/nouveau/nouveau_gem.c:371:21: error: unused variable 'dev' [-Werror=unused-variable]
> drm/nouveau/nv50_display.c: In function 'nv50_crtc_cursor_set':
> drm/nouveau/nv50_display.c:1308:21: error: unused variable 'dev' [-Werror=unused-variable]
> drm/radeon/radeon_cs.c: In function 'radeon_cs_parser_relocs':
> drm/radeon/radeon_cs.c:77:21: error: unused variable 'ddev' [-Werror=unused-variable]
> 
> This fixes all the instances I found with ARM randconfig builds so far.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Fixes: a8ad0bd84f98 ("drm: Remove unused drm_device from drm_gem_object_lookup()")

Merged both fixup patches for the drm_gem_object_lookup change to
drm-misc. Sorry for the mess :(
-Daniel

> ---
>  drivers/gpu/drm/armada/armada_crtc.c   | 1 -
>  drivers/gpu/drm/nouveau/nouveau_gem.c  | 1 -
>  drivers/gpu/drm/nouveau/nv50_display.c | 1 -
>  drivers/gpu/drm/radeon/radeon_cs.c     | 1 -
>  4 files changed, 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
> index a9b7e0f36513..3130aa8bcdd0 100644
> --- a/drivers/gpu/drm/armada/armada_crtc.c
> +++ b/drivers/gpu/drm/armada/armada_crtc.c
> @@ -897,7 +897,6 @@ static void cursor_update(void *data)
>  static int armada_drm_crtc_cursor_set(struct drm_crtc *crtc,
>  	struct drm_file *file, uint32_t handle, uint32_t w, uint32_t h)
>  {
> -	struct drm_device *dev = crtc->dev;
>  	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
>  	struct armada_gem_object *obj = NULL;
>  	int ret;
> diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
> index 445a9e2fb91a..a030e218adf7 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_gem.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
> @@ -368,7 +368,6 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
>  	      int nr_buffers, struct validate_op *op)
>  {
>  	struct nouveau_cli *cli = nouveau_cli(file_priv);
> -	struct drm_device *dev = chan->drm->dev;
>  	int trycnt = 0;
>  	int ret, i;
>  	struct nouveau_bo *res_bo = NULL;
> diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
> index 47761a92926e..ec2e67eb8980 100644
> --- a/drivers/gpu/drm/nouveau/nv50_display.c
> +++ b/drivers/gpu/drm/nouveau/nv50_display.c
> @@ -1305,7 +1305,6 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
>  		     uint32_t handle, uint32_t width, uint32_t height)
>  {
>  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
> -	struct drm_device *dev = crtc->dev;
>  	struct drm_gem_object *gem = NULL;
>  	struct nouveau_bo *nvbo = NULL;
>  	int ret = 0;
> diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
> index 271652963fa1..510ea371dacc 100644
> --- a/drivers/gpu/drm/radeon/radeon_cs.c
> +++ b/drivers/gpu/drm/radeon/radeon_cs.c
> @@ -74,7 +74,6 @@ static void radeon_cs_buckets_get_list(struct radeon_cs_buckets *b,
>  
>  static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
>  {
> -	struct drm_device *ddev = p->rdev->ddev;
>  	struct radeon_cs_chunk *chunk;
>  	struct radeon_cs_buckets buckets;
>  	unsigned i;
> -- 
> 2.7.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From eric at anholt.net  Wed May 18 10:18:17 2016
From: eric at anholt.net (Eric Anholt)
Date: Wed, 18 May 2016 10:18:17 -0700
Subject: [PATCH v2] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <20160518132741.GE22378@e104818-lin.cambridge.arm.com>
References: <1463576010-115428-1-git-send-email-agraf@suse.de>
 <20160518132741.GE22378@e104818-lin.cambridge.arm.com>
Message-ID: <874m9vp9nq.fsf@eliezer.anholt.net>

Catalin Marinas <catalin.marinas at arm.com> writes:

> On Wed, May 18, 2016 at 02:53:30PM +0200, Alexander Graf wrote:
>> On arm64, all SoCs we supported so far either have an IOMMU or have bus
>> addresses equal to CPU addresses.
>> 
>> However, with the Raspberry Pi 3 coming up, this is no longer true. To
>> allow DMA to work with an AArch64 kernel on those devices, let's allow
>> devices to have DMA offsets again.
>> 
>> Signed-off-by: Alexander Graf <agraf at suse.de>
>
> We were aware about this issue but we've been waiting for an actual use
> case. I'll queue this for 4.8 (given that RPi3 is not supported by the
> arm64 kernel, I don't see the rush to merge it earlier).

Sounds good to me.  I'm looking forward to getting the other pieces in
place for 4.8.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160518/d6a194aa/attachment.sig>

From paulmck at linux.vnet.ibm.com  Wed May 18 10:31:38 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Wed, 18 May 2016 10:31:38 -0700
Subject: [PATCH v2 omap 3/6] arm: Add _rcuidle tracepoints to allow
 clk_core_disable() use from idle
In-Reply-To: <573C8943.6090104@free.fr>
References: <20160516184844.GA20144@linux.vnet.ibm.com>
 <1463424608-20237-3-git-send-email-paulmck@linux.vnet.ibm.com>
 <573C8943.6090104@free.fr>
Message-ID: <20160518173138.GW3528@linux.vnet.ibm.com>

On Wed, May 18, 2016 at 05:24:51PM +0200, Mason wrote:
> On 16/05/2016 20:50, Paul E. McKenney wrote:
> 
> >> stack backtrace:
> >> CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.6.0-rc5-next-20160426+ #1114
> >> Hardware name: Generic OMAP36xx (Flattened Device Tree)
> >> [<c0110290>] (unwind_backtrace) from [<c010c3a8>] (show_stack+0x10/0x14)
> >> [<c010c3a8>] (show_stack) from [<c047fd68>] (dump_stack+0xb0/0xe4)
> >> [<c047fd68>] (dump_stack) from [<c0631618>] (clk_core_disable+0x17c/0x348)
> >> [<c0631618>] (clk_core_disable) from [<c0632774>] (clk_disable+0x24/0x30)
> >> [<c0632774>] (clk_disable) from [<c0120590>] (_disable_clocks+0x18/0x7c)
> >> [<c0120590>] (_disable_clocks) from [<c0121680>] (_idle+0x12c/0x230)
> >> [<c0121680>] (_idle) from [<c0121b4c>] (omap_hwmod_idle+0x24/0x44)
> >> [<c0121b4c>] (omap_hwmod_idle) from [<c0122c24>] (omap_device_idle+0x3c/0x90)
> >> [<c0122c24>] (omap_device_idle) from [<c052cc00>] (__rpm_callback+0x2c/0x60)
> >> [<c052cc00>] (__rpm_callback) from [<c052cc54>] (rpm_callback+0x20/0x80)
> >> [<c052cc54>] (rpm_callback) from [<c052d150>] (rpm_suspend+0x100/0x768)
> >> [<c052d150>] (rpm_suspend) from [<c052ec58>] (__pm_runtime_suspend+0x64/0x84)
> >> [<c052ec58>] (__pm_runtime_suspend) from [<c04bf25c>] (omap2_gpio_prepare_for_idle+0x5
> >> c/0x70)
> >> [<c04bf25c>] (omap2_gpio_prepare_for_idle) from [<c0125568>] (omap_sram_idle+0x140/0x2
> >> 44)
> 
> Wouldn't the stack trace look better without the word wrap?  :-)

Truth in advertising!!!  ;-)

							Thanx, Paul



From dianders at chromium.org  Wed May 18 10:37:52 2016
From: dianders at chromium.org (Doug Anderson)
Date: Wed, 18 May 2016 10:37:52 -0700
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <573C3283.1040606@rock-chips.com>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <5502CA4E.9060401@samsung.com>
 <CAD=FV=VX3ix-j4y95W1q8b-aVuVEN+4xsd8WLx2xcE7KPNJwRw@mail.gmail.com>
 <5506707D.40708@samsung.com> <55189F04.8000404@samsung.com>
 <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
 <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
 <573BCC8D.5090606@kernel-upstream.org>
 <CAD=FV=VneQR3wurjezBkRhtQiH+q-FfhDN8=Ym=XqtZpVmsdUw@mail.gmail.com>
 <573C3283.1040606@rock-chips.com>
Message-ID: <CAD=FV=UoT2GRYWJWXEn_ccvKGgC+PzQM_BCtLHAa7jxzbaQ9SA@mail.gmail.com>

Hi,

On Wed, May 18, 2016 at 2:14 AM, Shawn Lin <shawn.lin at rock-chips.com> wrote:
> Hi
>
>
> On 2016-5-18 12:12, Doug Anderson wrote:
>>
>> Hi,
>>
>> On Tue, May 17, 2016 at 6:59 PM, Shawn Lin
>> <shawn.lin at kernel-upstream.org> wrote:
>>>
>>> Could you try this patch to see if you can still find HLE?
>>>
>>> @@ -2356,12 +2356,22 @@ static void dw_mci_cmd_interrupt(struct dw_mci
>>> *host, u32 status)
>>>   static void dw_mci_handle_cd(struct dw_mci *host)
>>>   {
>>>          int i;
>>> +       int present;
>>>
>>>          for (i = 0; i < host->num_slots; i++) {
>>>                  struct dw_mci_slot *slot = host->slot[i];
>>>
>>>                  if (!slot)
>>>                          continue;
>>>
>>> +               present = !(mci_readl(slot->host, CDETECT) & (1 <<
>>> slot->id));
>>> +               if (present)
>>> +                       set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>>> +               else
>>> +                       clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>>
>>
>> No, because we don't use the builtin card detect on veyron.  ;)
>>
>> We use GPIO card detect because we didn't like the way JTAG and SD
>> interacted.  Also on rk3288 the builtin card detect line had the wrong
>> voltage domain (you couldn't detect a card when the IO lines were
>> powered off).  The builtin card detect line is always driven low on
>> veyron.
>
>
> Okay, I see.
>
>>
>>
>> I'm nearly certain that the root cause of my HLE errors is actually
>> related to the same problem addressed by the commit 7c5209c315ea
>> ("mmc: core: Increase delay for voltage to stabilize from 3.3V to
>> 1.8V").  I think that on minnie we're still on the hairy edge and
>> sometimes the line doesn't transition fast enough.
>
>
> Things are not so simple from your details.
>
> I was not enabling SD3.0 support, then I also found HLE sometimes.
> So it seems commit 7c5209c315ea does not contibute to this phenomenon.

Just to clarify, in my case commit 7c5209c315ea didn't make the
problem worse, but made it better.  Just not better enough.  ;)


> The scenario looks like:
> remove sd-card -> mmc_sd_detect -> send status(CMD13) ->power_off ->
> set_ios -> setup_bus -> disabled clk , then HLE irq storm coming
>
> From the code of dw_mci_prepare_command:
> SDMMC_CMD_PRV_DAT_WAIT will not be used for CMD13, so we don't
> wait_busy here, then cmd code is loding into queue of dw_mmc but
> still failing send out because it's in busy?
>
> With my patch, things go well:
> remove sd-card -> clear bit of DW_MMC_CARD_PRESENT  -> send
> status(CMD13) return directly -> power_off -> set_ios -> setup_bus ->
> disable clk
>
> So why should we allow inquiry of card status if we sure the card is
> removed? I mean no any further cmds should be delivered.

Quite honestly just dealing with the HLE error (my patch or
equivalent) might be a sane solution for the problem you describe.

dw_mmc needs to be able to work with an external card detect GPIO.
It's been part of the dw_mmc driver for a long time and is (in fact)
in use upstream at least by rk3288-veyron.  Any solution that only
works for internal card detect is not enough.  Just handling the HLE
error to deal with the interrupt storm and then letting Linux remove
the card (because of the card detect interrupt) seems totally OK to
me.

Note: I'd be very curious if your problems get better if you disable
the "grf_force_jtag" bit in the GRF.  If you're using the builtin card
detect and you use the boot default of "grf_force_jtag" then your pins
will be unmuxed behind your back when the card is ejected.  This could
be causing the dw_mmc controller to get confused.


> And another question: should we wait busy for cmd13?

I don't think so.  As I understand it CMD13 uses only the CMD line for
communication and it should be appropriate to send this when the bus
is "busy" (which means that the DATA lines are low).

Also: it seems odd that the HLE IRQ storm didn't come right after the
CMD 13 in your description above.  Are you sure it was the CMD 13 that
caused the HLEs, or could it has been something else?


-Doug


From stillcompiling at gmail.com  Wed May 18 10:38:20 2016
From: stillcompiling at gmail.com (Joshua Clayton)
Date: Wed, 18 May 2016 10:38:20 -0700
Subject: CONFIG_ZBOOT_ROM_TEXT and CONFIG_ZBOOT_ROM_BSS in defconfig
In-Reply-To: <573C2819.3090109@free.fr>
References: <573B3F3C.80800@free.fr>
	<573C2819.3090109@free.fr>
Message-ID: <20160518103820.0f244706@jclayton-pc>

On Wed, 18 May 2016 10:30:17 +0200
Mason <slash.tmp at free.fr> wrote:

> On 17/05/2016 17:56, Mason wrote:
> 
> > I can submit a patch changing the default from 0 to 0x0, i.e.
> > no functional change. The two entries would then disappear
> > from defconfigs.  
> 
> Specifically, this is what I meant:
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 70764838dfcc..6831c46a3672 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1823,7 +1823,7 @@ config DEPRECATED_PARAM_STRUCT
>  # TEXT and BSS so we preserve their values in the config files.
>  config ZBOOT_ROM_TEXT
>  	hex "Compressed ROM boot loader base address"
> -	default "0"
> +	default 0x0
>  	help
>  	  The physical address at which the ROM-able zImage is to be
>  	  placed in the target.  Platforms which normally make use of
> @@ -1834,7 +1834,7 @@ config ZBOOT_ROM_TEXT
>  
>  config ZBOOT_ROM_BSS
>  	hex "Compressed ROM boot loader BSS address"
> -	default "0"
> +	default 0x0
>  	help
>  	  The base address of an area of read/write memory in the
> target for the ROM-able zImage which must be available while the
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

If the goal is to get rid of the 0x0's in the defconfigs, would it not
be just as effective to drop those so they land at "0"?


From linux at armlinux.org.uk  Wed May 18 10:51:02 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Wed, 18 May 2016 18:51:02 +0100
Subject: [RFC PATCH 1/3] asm-generic: io: Add exec versions of ioremap
In-Reply-To: <573C7844.5030107@ti.com>
References: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
 <1462830111-28172-2-git-send-email-d-gerlach@ti.com>
 <20160512163759.GW5783@n2100.arm.linux.org.uk>
 <573C7844.5030107@ti.com>
Message-ID: <20160518175102.GX5783@n2100.arm.linux.org.uk>

On Wed, May 18, 2016 at 09:12:20AM -0500, Dave Gerlach wrote:
> Ok thank you for the pointer. I agree, the memremap API looks like a better
> fit for this. I think it likely makes the most sense to still add these
> ioremap_exec and ioremap_exec_nocache and then call them through the
> memremap API based on new flags. This will fit into the current use model
> for memremap as it currently uses all of the other ioremap calls internally,
> and doing it how I just described will let this code evolve along with
> memremap.

I would _really_ prefer not to do that.  Why?  Because IO memory does
not have the required properties to be executable.  IO memory is normally
memory which has side effects - and by side effects, I mean reading it
can provoke hardware to perform some action.  You don't want to be
executing from such memory.

So, in my mind, ioremap_exec makes absolutely no sense, and having it
gives people a new interface to abuse - and abuse they will.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From srinivas.kandagatla at linaro.org  Wed May 18 10:57:46 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Wed, 18 May 2016 18:57:46 +0100
Subject: [PATCH] usb: echi-hcd: Add register access check in shutdown
In-Reply-To: <Pine.LNX.4.44L0.1605181044460.1981-100000@iolanthe.rowland.org>
References: <Pine.LNX.4.44L0.1605181044460.1981-100000@iolanthe.rowland.org>
Message-ID: <573CAD1A.4090805@linaro.org>



On 18/05/16 15:56, Alan Stern wrote:
> This doesn't seem like the right place.  What you really should do is
> skip calling ehci_silence_controller() if the hardware isn't
> accessible.  That's where the hardware gets touched, not in
> ehci_shutdown().

Just tried this suggestion, this would not work as well, Its not just 
the hardware registers, which are of concern here, but also the rest of 
the things like ehci->hrtimer pointer which are allocated or initialized 
as part of ehci_setup().

Either the msm controller driver is not correct or we should have a way 
to stop calling ehci_shutdown() if there was no ehci_setup() done yet.

Any suggestions?


--srini


From ynorov at caviumnetworks.com  Wed May 18 10:58:59 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Wed, 18 May 2016 20:58:59 +0300
Subject: [PATCH 20/25] arm64:ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <20160518112145.GD22378@e104818-lin.cambridge.arm.com>
References: <1459894127-17698-1-git-send-email-ynorov@caviumnetworks.com>
 <1459894127-17698-21-git-send-email-ynorov@caviumnetworks.com>
 <20160514150352.GA30533@yury-N73SV>
 <20160516170605.GB19290@e104818-lin.cambridge.arm.com>
 <20160517190526.GA3731@yury-N73SV>
 <20160518112145.GD22378@e104818-lin.cambridge.arm.com>
Message-ID: <20160518175859.GA2560@yury-N73SV>

On Wed, May 18, 2016 at 12:21:46PM +0100, Catalin Marinas wrote:
> On Tue, May 17, 2016 at 10:05:26PM +0300, Yury Norov wrote:
> > On Mon, May 16, 2016 at 06:06:05PM +0100, Catalin Marinas wrote:
> > > On Sat, May 14, 2016 at 06:03:52PM +0300, Yury Norov wrote:
> > > > +SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
> > > > +       unsigned long, prot, unsigned long, flags, unsigned long, fd,
> > > > +       unsigned long, pgoff)
> > > 
> > > To avoid the types confusion we could add __SC_WRAP to mmap2 in unistd.h
> > > and use COMPAT_SYSCALL_DEFINE6 here (together with compat_ptr_t etc.).
> > > 
> > > > +{
> > > > +       if (pgoff & (~PAGE_MASK >> 12))
> > > > +               return -EINVAL;
> > > > +
> > > > +       return sys_mmap_pgoff((compat_uptr_t) addr, (compat_size_t) len,
> > > > +		       (int) prot, (int) flags, (int) fd,
> > > > +		       pgoff >> (PAGE_SHIFT-12));
> > > 
> > > Then we wouldn't need the explicit casting here.
> > 
> > See below
> > 
> > > > +}
> > > > +
> > > > +COMPAT_SYSCALL_DEFINE4(pread64, unsigned int, fd, compat_uptr_t __user *, ubuf,
> > > > +		       compat_size_t, count, off_t, offset)
> > > > +{
> > > > +	return sys_pread64(fd, (char *) ubuf, count, offset);
> > > > +}
> > > > +
> > > > +COMPAT_SYSCALL_DEFINE4(pwrite64, unsigned int, fd, compat_uptr_t __user *, ubuf,
> > > > +		       compat_size_t, count, off_t, offset)
> > > > +{
> > > > +	return sys_pwrite64(fd, (char *) ubuf, count, offset);
> > > 
> > > Nitpick: no space between cast type and variable name: (char *)ubuf, ...
> > 
> > I think it's really a matter of taste. I prefer to have a space, and
> > there's no solid rule in coding style.
> > 
> > And there are 13032 insertions of my version vs 35030 of yours:
> > ~/work/linux$ git grep ' \*)[a-zA-Z]'|wc -l
> > 35030
> > ~/work/linux$ git grep ' \*) [a-zA-Z]'|wc -l
> > 13032
> > 
> > Of course, I will change it if you insist.
> 
> Not really, I thought it's covered by CodingStyle but it doesn't seem
> to.
> 
> > > We can also make these functions static as they are not used outside
> > > this file.
> > 
> > If it's OK, we can use just compat_sys_xxx() instead of
> > COMPAT_SYSCALL_DEFINEx(xxx),
> 
> I got lost in macros, what difference would COMPAT_SYSCALL_DEFINE vs
> compat_sys_*() make? Is this the delouse stuff?
> 

Hmm... I looked again. It seems that COMPAT delouses all arguments,
including off_t, and that's what we try to avoid. So we *should* use
naked functions. 

include/linux/compat.h:
53 #define COMPAT_SYSCALL_DEFINEx(x, name, ...) \
54         asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))\
55              __attribute__((alias(__stringify(compat_SyS##name))));  \
56         static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
57         asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));\
58         asmlinkage long compat_SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))\
59         { \
60                 return C_SYSC##name(__MAP(x,__SC_DELOUSE,__VA_ARGS__)); \
61         } \
62         static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))


> > and for mmap2 we'll not need to change _SYSCALL to _SC_WRAP in
> > unistd.h that way.
> 
> Looking at the generic unistd.h, adding _SC_WRAP for sys_mmap2 is
> indeed not easy:
> 
> #define __NR3264_mmap 222
> __SC_3264(__NR3264_mmap, sys_mmap2, sys_mmap)
> 
> So defining a compat_sys_mmap2() would work but I think you'd also need:
> 

> #define sys_mmap2	compat_sys_mmap2()

OK.

> 
> -- 
> Catalin


From heiko at sntech.de  Wed May 18 11:01:44 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 18 May 2016 20:01:44 +0200
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <CAD=FV=UoT2GRYWJWXEn_ccvKGgC+PzQM_BCtLHAa7jxzbaQ9SA@mail.gmail.com>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <573C3283.1040606@rock-chips.com>
 <CAD=FV=UoT2GRYWJWXEn_ccvKGgC+PzQM_BCtLHAa7jxzbaQ9SA@mail.gmail.com>
Message-ID: <9061286.nTNVjb4bva@phil>

Am Mittwoch, 18. Mai 2016, 10:37:52 schrieb Doug Anderson:
> Note: I'd be very curious if your problems get better if you disable
> the "grf_force_jtag" bit in the GRF.  If you're using the builtin card
> detect and you use the boot default of "grf_force_jtag" then your pins
> will be unmuxed behind your back when the card is ejected.  This could
> be causing the dw_mmc controller to get confused.

On the rk3288, we saw issues with the jtag/sdmmc function and thus disabled 
that altogether in [0]. Not sure if that is a similar problem for you.

Heiko

[0] 
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c9b75d51c940c25587a2ad72ec7ec60490abfb6c



From christoffer.dall at linaro.org  Wed May 18 11:06:37 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 20:06:37 +0200
Subject: [PATCH v4 22/56] KVM: arm/arm64: vgic-new: Add MMIO handling
 framework
In-Reply-To: <573C9081.6080500@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-23-git-send-email-andre.przywara@arm.com>
 <20160518123115.GE3827@cbox> <573C9081.6080500@arm.com>
Message-ID: <20160518180637.GO6666@cbox>

On Wed, May 18, 2016 at 04:55:45PM +0100, Andre Przywara wrote:
> Hi,
> 
> ....
> 
> >> +
> >> +/* generate a mask that covers 1024 interrupts with <b> bits per IRQ */
> >> +#define VGIC_ADDR_IRQ_MASK(b) GENMASK_ULL(ilog2(b) + ilog2(1024) - \
> >> +					  ilog2(BITS_PER_BYTE) - 1, 0)
> >> +#define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
> >> +					64 / (bits) / 8)
> > 
> > In the comment we end up adding here, can we also describe why
> > (addr & <magic mask>) * <magic 64> / (bits) / <BITS_PER_BYTE OR BYTES_PER_ULL>
> > gives us what we need, because I don't get it.
> 
> The reason is: we deal with 8 bits per byte, but have
> bits-per-interrupts values bigger than 8. Doing the maths in floating
> point arithmetic would work fine:
> 
> (float)(addr & mask) * (8.0 / bits_per_IRQ)
> 
> So would this comment make sense?
> 
> /*
>  * Since we can have more than 8 bits per interrupt, we can't use
>  * "8 / bpi" as a multiplicand directly, so we use a
>  * fixed-point-arithmetic version of it tailored to cover at most 64
>  * bits per IRQ.
>  */
> 

Something like this certainly helps, here's another version which is
easier for me to understand, but you can take your pick:

 /*
  * (addr & mask) gives us the byte offset for the INT ID, so we want to
  * divide this with 'bytes per irq' to get the INT ID, which is given
  * by '(bits) / 8'.  But we do this with fixed-point-arithmetic and
  * take advantage of the fact that division by a fraction equals
  * multiplication with the inverted fraction, and scale up both the
  * numerator and denominator with 8 to support at most 64 bits per IRQ:
  */

At least I think we all agree that the approach works by now.

-Christoffer


From stern at rowland.harvard.edu  Wed May 18 11:54:25 2016
From: stern at rowland.harvard.edu (Alan Stern)
Date: Wed, 18 May 2016 14:54:25 -0400 (EDT)
Subject: [PATCH] usb: echi-hcd: Add register access check in shutdown
In-Reply-To: <573CAD1A.4090805@linaro.org>
Message-ID: <Pine.LNX.4.44L0.1605181449390.1981-100000@iolanthe.rowland.org>

On Wed, 18 May 2016, Srinivas Kandagatla wrote:

> On 18/05/16 15:56, Alan Stern wrote:
> > This doesn't seem like the right place.  What you really should do is
> > skip calling ehci_silence_controller() if the hardware isn't
> > accessible.  That's where the hardware gets touched, not in
> > ehci_shutdown().
> 
> Just tried this suggestion, this would not work as well, Its not just 
> the hardware registers, which are of concern here, but also the rest of 
> the things like ehci->hrtimer pointer which are allocated or initialized 
> as part of ehci_setup().
> 
> Either the msm controller driver is not correct or we should have a way 
> to stop calling ehci_shutdown() if there was no ehci_setup() done yet.
> 
> Any suggestions?

Yes, you're right.

Since you're concerned about more than just accessing the hardware 
registers, HW_ACCESSIBLE isn't the right thing to test.  You need 
something that gets set in ehci_setup() and nowhere else.

One possibility is ehci->sbrn.  If that is equal to 0 then ehci_setup() 
hasn't run, so ehci->shutdown() can simply return.  Be sure to put a 
comment in the code explaining the reason for doing this.

Alan Stern



From paulmck at linux.vnet.ibm.com  Wed May 18 11:56:38 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Wed, 18 May 2016 11:56:38 -0700
Subject: [PATCH omap v2 0/6] Fix OMAP uses of RCU from idle loop
In-Reply-To: <573C7E6F.90001@roeck-us.net>
References: <20160516184844.GA20144@linux.vnet.ibm.com>
 <573C7E6F.90001@roeck-us.net>
Message-ID: <20160518185638.GD3528@linux.vnet.ibm.com>

On Wed, May 18, 2016 at 07:38:39AM -0700, Guenter Roeck wrote:
> On 05/16/2016 11:48 AM, Paul E. McKenney wrote:
> >Hello!
> >
> >The following series fixes a number of uses of RCU from the idle loop.
> >These are all due to tracing, so the fix is simply to append _rcuidle
> >to the event-tracing call.
> >
> >Changes since v1: Fix commit-log subjects and add maintainers on CC.
> >
> 
> For the series, on top of mainline (which now experiences the problem fixed
> by this series):
> 
> Tested-by: Guenter Roeck <linux at roeck-us.net>

Applied, thank you!  And fixed the line-wrapping while I was at it.  ;-)

							Thanx, Paul



From okaya at codeaurora.org  Wed May 18 11:59:25 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Wed, 18 May 2016 14:59:25 -0400
Subject: [PATCH v2] arm64: Allow for different DMA and CPU bus offsets
In-Reply-To: <1463576010-115428-1-git-send-email-agraf@suse.de>
References: <1463576010-115428-1-git-send-email-agraf@suse.de>
Message-ID: <573CBB8D.4020409@codeaurora.org>

On 5/18/2016 8:53 AM, Alexander Graf wrote:
> ---
> 
> This patch may conflict with another patch titled "swiotlb: prefix dma_to_phys
> and phys_to_dma functions" which is in flight, but hasn't seen an update since
> March.

Thanks for the heads up. Due to missing API in DMA API, I couldn't make progress
with the series.

I need dma_map_resource API to get merged. After that one of the drivers
that actually uses dma_to_phys need to be changed to use dma_map_resource. 

Then the rest of the series can come.

-- 
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


From tony at atomide.com  Wed May 18 12:30:28 2016
From: tony at atomide.com (Tony Lindgren)
Date: Wed, 18 May 2016 12:30:28 -0700
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
 <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com>
Message-ID: <20160518193028.GT5995@atomide.com>

* Peter Ujfalusi <peter.ujfalusi at ti.com> [160518 03:26]:
> On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
> > omap hsmmc host controller has ADMA2 feature. Enable it here
> > for better read and write throughput. Add a new dt binding
> > "ti,use_adma" to enable ADMA2.
> > 
> > Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
> > ---
> >  .../devicetree/bindings/mmc/ti-omap-hsmmc.txt      |    1 +
> >  drivers/mmc/host/omap_hsmmc.c                      |  320 ++++++++++++++++----
> >  include/linux/platform_data/hsmmc-omap.h           |    1 +
> >  3 files changed, 256 insertions(+), 66 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> > index 74166a0..eb5ceec2 100644
> > --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> > +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> > @@ -28,6 +28,7 @@ specifier is required.
> >  dma-names: List of DMA request names. These strings correspond
> >  1:1 with the DMA specifiers listed in dmas. The string naming is
> >  to be "rx" and "tx" for RX and TX DMA requests, respectively.
> > +ti,use_adma: enable adma2 feature
> 
> Do we have use case when you want to fall back to generic DMA instead of aDMA2?

Yes my guess is that PM runtime breaks with these currently..

> IMHO if the driver supports aDMA2, it is going to use it instead of the
> generic s/eDMA.
> What I mean is:
> the driver implements the aDMA2 support.
> if the IP has support for aDMA2, then it is going to use it, otherwise it will
> use the generic DMA.

Ideally the adma support would be a separate loadable module,
similar how the cppi41dma is a child of the OTG controller.

That way the systems wanting to use adma can just specify it
in the binding, and adma PM runtime support can be added later
on.

Of course this won't work if the adma registers are sprinkled
within the MMC controller registers..

Regards,

Tony


From mikecyr at linux.vnet.ibm.com  Wed May 18 12:35:23 2016
From: mikecyr at linux.vnet.ibm.com (Michael Cyr)
Date: Wed, 18 May 2016 14:35:23 -0500
Subject: [PATCH] Fix for hang of Ordered task in TCM
In-Reply-To: <1463550825.22249.17.camel@haakon3.risingtidesystems.com>
References: <1463177741-4385-1-git-send-email-mikecyr@linux.vnet.ibm.com>
 <1463550825.22249.17.camel@haakon3.risingtidesystems.com>
Message-ID: <82ddb84d-1a3c-f7ad-3f91-0a9506317bdf@linux.vnet.ibm.com>


On 5/18/16 12:53 AM, Nicholas A. Bellinger wrote:
> Hi Michael,
>
> On Fri, 2016-05-13 at 17:15 -0500, Michael Cyr wrote:
>> If a command with a Simple task attribute is failed due to a Unit
>> Attention, then a subsequent command with an Ordered task attribute will
>> hang forever.  The reason for this is that the Unit Attention status is
>> checked for in target_setup_cmd_from_cdb, before the call to
>> target_execute_cmd, which calls target_handle_task_attr, which in turn
>> increments dev->simple_cmds.  However, transport_generic_request_failure
>> still calls transport_complete_task_attr, which will decrement
>> dev->simple_cmds.  In this case, simple_cmds is now -1.  So when a
>> command with the Ordered task attribute is sent, target_handle_task_attr
>> sees that dev->simple_cmds is not 0, so it decides it can't execute the
>> command until all the (nonexistent) Simple commands have completed.
>>
> Thanks for reporting this bug.  Comments below.
>
>> The solution I've implemented is to move target_scsi3_ua_check, as well as
>> target_alua_state_check and target_check_reservation, into
>> target_execute_cmd, after the call to target_handle_task_attr.  I believe
>> this is actually the correct way this should be handled.  According to
>> SAM-4 r14, under section 5.14:
>>
>> "h) if a command other than INQUIRY, REPORT LUNS, REQUEST SENSE, or NOTIFY
>> DATA TRANSFER DEVICE enters the enabled command state while a unit
>> attention condition exists for the SCSI initiator port associated with
>> the I_T nexus on which the command was received, the device server shall
>> terminate the command with a CHECK CONDITION status. The device server
>> shall provide sense data that reports a unit attention condition for the
>> SCSI initiator port that sent the command on the I_T nexus."
>>
>> But according to section 8.5 and 8.6, a command which is not yet executed
>> because of the presence of other tasks in the task set (i.e., one for
>> which target_handle_task_attr returns true) would not enter the enabled
>> command state; it would be in the dormant command state.
>> target_execute_cmd would get called when a command entered the enabled
>> command state, and thus that is the appropriate place to check for Unit
>> Attenion.  Similarly, though not quite as explicit, section 5.3.3 tells
>> us that a Reservation Conflict status has a lower precedence than a Unit
>> Attention, and so this would also seem to be the appropriate place to
>> call target_check_reservation.  I'm less sure about
>> target_alua_state_check, since I'm not very familiar with ALUA.
>>
>> Signed-off-by: Michael Cyr <mikecyr at linux.vnet.ibm.com>
>> ---
>>   drivers/target/target_core_transport.c | 41 ++++++++++++++++++++--------------
>>   1 file changed, 24 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
>> index 6c089af..2ee5502 100644
>> --- a/drivers/target/target_core_transport.c
>> +++ b/drivers/target/target_core_transport.c
>> @@ -1303,23 +1303,6 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
>>   
>>   	trace_target_sequencer_start(cmd);
>>   
>> -	/*
>> -	 * Check for an existing UNIT ATTENTION condition
>> -	 */
>> -	ret = target_scsi3_ua_check(cmd);
>> -	if (ret)
>> -		return ret;
>> -
>> -	ret = target_alua_state_check(cmd);
>> -	if (ret)
>> -		return ret;
>> -
>> -	ret = target_check_reservation(cmd);
>> -	if (ret) {
>> -		cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
>> -		return ret;
>> -	}
>> -
>>   	ret = dev->transport->parse_cdb(cmd);
>>   	if (ret == TCM_UNSUPPORTED_SCSI_OPCODE)
>>   		pr_warn_ratelimited("%s/%s: Unsupported SCSI Opcode 0x%02x, sending CHECK_CONDITION.\n",
>> @@ -1865,6 +1848,8 @@ static int __transport_check_aborted_status(struct se_cmd *, int);
>>   
>>   void target_execute_cmd(struct se_cmd *cmd)
>>   {
>> +	sense_reason_t ret;
>> +
>>   	/*
>>   	 * Determine if frontend context caller is requesting the stopping of
>>   	 * this command for frontend exceptions.
>> @@ -1899,6 +1884,28 @@ void target_execute_cmd(struct se_cmd *cmd)
>>   		return;
>>   	}
>>   
>> +	/*
>> +	 * Check for an existing UNIT ATTENTION condition
>> +	 */
>> +	ret = target_scsi3_ua_check(cmd);
>> +	if (ret) {
>> +		transport_generic_request_failure(cmd, ret);
>> +		return;
>> +	}
>> +
>> +	ret = target_alua_state_check(cmd);
>> +	if (ret) {
>> +		transport_generic_request_failure(cmd, ret);
>> +		return;
>> +	}
>> +
>> +	ret = target_check_reservation(cmd);
>> +	if (ret) {
>> +		cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
>> +		transport_generic_request_failure(cmd, ret);
>> +		return;
>> +	}
>> +
>>   	__target_execute_cmd(cmd);
>>   }
>>   EXPORT_SYMBOL(target_execute_cmd);
> So AFAICT for delayed commands, the above patch ends up skipping these
> three checks subsequently when doing __target_execute_cmd() directly
> from target_restart_delayed_cmds(), no..?
>
> After pondering this some more, what about moving these checks into
> __target_execute_cmd() to handle both target_core_transport.c cases
> instead..?
You're right, __target_execute_cmd is clearly the right place for the 
checks.
> We'll also need a parameter for internal COMPARE_AND_WRITE usage
> within compare_and_write_callback(), to bypass checks upon secondary
> ->execute_cmd() WRITE payload submission after READ + COMPARE has
> completed successfully.
I'm still learning about the target code, and I was unaware of 
COMPARE_AND_WRITE.  Thanks for pointing this out to me.  You're right 
here too, we need to make sure we only make the tests when the Compare 
and Write is first executed (to do the read), and not later when the 
write is done.
>
> WDYT..?
You've covered all the places that call __target_execute_cmd, so I think 
it's good.
>
> diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
> index fc91e85..e2c970a 100644
> --- a/drivers/target/target_core_internal.h
> +++ b/drivers/target/target_core_internal.h
> @@ -146,6 +146,7 @@ sense_reason_t	target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
>   void	target_qf_do_work(struct work_struct *work);
>   bool	target_check_wce(struct se_device *dev);
>   bool	target_check_fua(struct se_device *dev);
> +void	__target_execute_cmd(struct se_cmd *, bool);
>
>   /* target_core_stat.c */
>   void	target_stat_setup_dev_default_groups(struct se_device *);
> diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
> index a9057aa..04f616b 100644
> --- a/drivers/target/target_core_sbc.c
> +++ b/drivers/target/target_core_sbc.c
> @@ -602,7 +602,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes
>   	cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
>   	spin_unlock_irq(&cmd->t_state_lock);
>
> -	__target_execute_cmd(cmd);
> +	__target_execute_cmd(cmd, false);
>
>   	kfree(buf);
>   	return ret;
> diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
> index 6c089af..f3e93dd 100644
> --- a/drivers/target/target_core_transport.c
> +++ b/drivers/target/target_core_transport.c
> @@ -1761,20 +1761,45 @@ queue_full:
>   }
>   EXPORT_SYMBOL(transport_generic_request_failure);
>
> -void __target_execute_cmd(struct se_cmd *cmd)
> +void __target_execute_cmd(struct se_cmd *cmd, bool do_checks)
>   {
>   	sense_reason_t ret;
>
> -	if (cmd->execute_cmd) {
> -		ret = cmd->execute_cmd(cmd);
> -		if (ret) {
> -			spin_lock_irq(&cmd->t_state_lock);
> -			cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
> -			spin_unlock_irq(&cmd->t_state_lock);
> +	if (!cmd->execute_cmd) {
> +		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> +		goto err;
> +	}
> +	if (do_checks) {
> +		/*
> +		 * Check for an existing UNIT ATTENTION condition after
> +		 * target_handle_task_attr() has done SAM task attr
> +		 * checking, and possibly have already defered execution
> +		 * out to target_restart_delayed_cmds() context.
> +		 */
> +		ret = target_scsi3_ua_check(cmd);
> +		if (ret)
> +			goto err;
>
> -			transport_generic_request_failure(cmd, ret);
> +		ret = target_alua_state_check(cmd);
> +		if (ret)
> +			goto err;
> +
> +		ret = target_check_reservation(cmd);
> +		if (ret) {
> +			cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
> +			goto err;
>   		}
>   	}
> +
> +	ret = cmd->execute_cmd(cmd);
> +	if (!ret)
> +		return;
> +err:
> +	spin_lock_irq(&cmd->t_state_lock);
> +	cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
> +	spin_unlock_irq(&cmd->t_state_lock);
> +
> +	transport_generic_request_failure(cmd, ret);
>   }
>
>   static int target_write_prot_action(struct se_cmd *cmd)
> @@ -1899,7 +1924,7 @@ void target_execute_cmd(struct se_cmd *cmd)
>   		return;
>   	}
>
> -	__target_execute_cmd(cmd);
> +	__target_execute_cmd(cmd, true);
>   }
>   EXPORT_SYMBOL(target_execute_cmd);
>
> @@ -1923,7 +1948,7 @@ static void target_restart_delayed_cmds(struct se_device *dev)
>   		list_del(&cmd->se_delayed_node);
>   		spin_unlock(&dev->delayed_cmd_lock);
>
> -		__target_execute_cmd(cmd);
> +		__target_execute_cmd(cmd, true);
>
>   		if (cmd->sam_task_attr == TCM_ORDERED_TAG)
>   			break;
> diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
> index ec79da3..334f107 100644
> --- a/include/target/target_core_fabric.h
> +++ b/include/target/target_core_fabric.h
> @@ -163,7 +163,6 @@ int	core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t);
>   void	core_tmr_release_req(struct se_tmr_req *);
>   int	transport_generic_handle_tmr(struct se_cmd *);
>   void	transport_generic_request_failure(struct se_cmd *, sense_reason_t);
> -void	__target_execute_cmd(struct se_cmd *);
>   int	transport_lookup_tmr_lun(struct se_cmd *, u64);
>   void	core_allocate_nexus_loss_ua(struct se_node_acl *acl);
>



From christoffer.dall at linaro.org  Wed May 18 12:53:47 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Wed, 18 May 2016 21:53:47 +0200
Subject: [PATCH] kvm: arm64: Fix EC field in inject_abt64
In-Reply-To: <5739C320.6010602@arm.com>
References: <5739C320.6010602@arm.com>
Message-ID: <20160518195347.GA26840@cbox>

On Mon, May 16, 2016 at 01:54:56PM +0100, Matt Evans wrote:
> The EC field of the constructed ESR is conditionally modified by ORing in
> ESR_ELx_EC_DABT_LOW for a data abort.  However, ESR_ELx_EC_SHIFT is missing
> from this condition.
> 
> Signed-off-by: Matt Evans <matt.evans at arm.com>
> Acked-by: Marc Zyngier <marc.zyngier at arm.com>
> Cc: <stable at vger.kernel.org>
> ---
>  arch/arm64/kvm/inject_fault.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
> index 4d1ac81..e9e0e6d 100644
> --- a/arch/arm64/kvm/inject_fault.c
> +++ b/arch/arm64/kvm/inject_fault.c
> @@ -162,7 +162,7 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
>  		esr |= (ESR_ELx_EC_IABT_CUR << ESR_ELx_EC_SHIFT);
>  
>  	if (!is_iabt)
> -		esr |= ESR_ELx_EC_DABT_LOW;
> +		esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
>  
>  	vcpu_sys_reg(vcpu, ESR_EL1) = esr | ESR_ELx_FSC_EXTABT;
>  }
> -- 
> 1.9.1
> 

Applied to queue.

Thanks!
-Christoffer


From maxime.ripard at free-electrons.com  Wed May 18 12:59:29 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 18 May 2016 21:59:29 +0200
Subject: [PATCH 02/16] clk: sunxi-ng: Add common infrastructure
In-Reply-To: <20160517085427.f2f3aa0c66686f8f5f6318ff@free.fr>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-3-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v67XWt6tjG_xXWgGatTaiN5uYQb2_Q6bgixMDUkHfVHLHg@mail.gmail.com>
 <20160515183122.GA27618@lukather>
 <20160516100239.a93a238b0d458b38a3689a95@free.fr>
 <20160516201509.GL27618@lukather>
 <20160517085427.f2f3aa0c66686f8f5f6318ff@free.fr>
Message-ID: <20160518195929.GS27618@lukather>

On Tue, May 17, 2016 at 08:54:27AM +0200, Jean-Francois Moine wrote:
> On Mon, 16 May 2016 22:15:09 +0200
> Maxime Ripard <maxime.ripard at free-electrons.com> wrote:
> 
> > > > Yes, I intended it to be a simple busy waiting loop since I don't
> > > > expect it to be very long. Do yu have any more data on how much time
> > > > it usually takes?
> > > 
> > > I have a Soc in which the rate of the audio clock is stable after a
> > > good second.
> > 
> > You mean before the clock is actually stable, or before the lock bit
> > is cleared?
> > 
> > Which SoC is it? As far as I've seen, only the H3 allows to configure
> > the stable time, and while by default it will take 16us, you can
> > configure as high as 66ms (which is still way higher than the current
> > limit).
> 
> Hi Maxime,
> 
> Well, it is not a SoC, but an external chip, the SI5351 (in the Dove
> Cubox). There is no lock bit, but as it is used for audio, and as I did
> not set any delay at streaming start time, I can hear when the clock is
> stable.

Ok. So I guess we set it high enough to cover the maximum we know for
know (65ms), and we can always rise that up later if needed.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160518/a06a27a8/attachment.sig>

From pavel at ucw.cz  Wed May 18 13:12:51 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Wed, 18 May 2016 22:12:51 +0200
Subject: 4.5-rc0 regression: GPRS breaks after very short while
In-Reply-To: <20160518141624.GA8025@earth>
References: <20160518074924.GA20652@amd>
 <20160518141624.GA8025@earth>
Message-ID: <20160518201251.GA22015@amd>

Hi!

> On Wed, May 18, 2016 at 09:49:24AM +0200, Pavel Machek wrote:
> > I was afraid another GSM chip desoldered itself in N900, but no, it
> > seems to be software this time.
> > 
> > In 4.4, GPRS is rock solid, can survive overnight ping.
> > 
> > In 4.5-rc0 and v4.6, modem fails when I use gprs for like a
> > minute. Phone is not usable.
> 
> I only send three modem related changes for v4.5:
> 
> https://git.kernel.org/cgit/linux/kernel/git/sre/linux-hsi.git/commit/?h=hsi-for-4.5&id=525e1abc6b5a7d8bd9006de1da6e99722305ea2b
> HSI: omap_ssi: fix handling ida_simple_get result
> 
> https://git.kernel.org/cgit/linux/kernel/git/sre/linux-hsi.git/commit/?h=hsi-for-4.5&id=6bf6ded3008a407ccab5ad72eb59ab71b97cc290
> HSI: omap_ssi_port: fix handling of_get_named_gpio result
> 
> https://git.kernel.org/cgit/linux/kernel/git/sre/linux-hsi.git/commit/?h=hsi-for-4.5&id=403c5c0650816375527a6feecfb255d9b494dda3
> HSI: Remove struct hsi_client private fields from kernel-doc
> 
> The last one only changes a comment, so not relevant, the other
> two fix error handling during initialization and are most likely
> also not the problem. Can you try to bisect the problem?

It will not be fun, but I guess it is doable. But before I start it
would be good to know -- does it work for you?

Thanks and best regards,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From emil.l.velikov at gmail.com  Wed May 18 13:20:29 2016
From: emil.l.velikov at gmail.com (Emil Velikov)
Date: Wed, 18 May 2016 21:20:29 +0100
Subject: [PATCH 1/5] headers_check: don't warn about c++ guards
In-Reply-To: <1463587653-3035181-2-git-send-email-arnd@arndb.de>
References: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
 <1463587653-3035181-2-git-send-email-arnd@arndb.de>
Message-ID: <CACvgo51FkfzzhFjYKyyHfxb-DyZeheQP2oZG-tWf1-EiBakp2w@mail.gmail.com>

On 18 May 2016 at 17:07, Arnd Bergmann <arnd at arndb.de> wrote:
> A recent addition to the DRM tree for 4.7 added 'extern "C"' guards
> for c++ to all the DRM headers, and that now causes warnings
> in 'make headers_check':
>
> usr/include/drm/amdgpu_drm.h:38: userspace cannot reference function or variable defined in the kernel
> usr/include/drm/drm.h:63: userspace cannot reference function or variable defined in the kernel
> usr/include/drm/drm.h:699: userspace cannot reference function or variable defined in the kernel
> usr/include/drm/drm_fourcc.h:30: userspace cannot reference function or variable defined in the kernel
> usr/include/drm/drm_mode.h:33: userspace cannot reference function or variable defined in the kernel
> usr/include/drm/drm_sarea.h:38: userspace cannot reference function or variable defined in the kernel
> usr/include/drm/exynos_drm.h:21: userspace cannot reference function or variable defined in the kernel
> usr/include/drm/i810_drm.h:7: userspace cannot reference function or variable defined in the kernel
>
> This changes the headers_check.pl script to not warn about this.
> I'm listing the merge commit as introducing the problem, because
> there are several patches in this branch that each do this for
> one file.
>
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Fixes: 7c10ddf87472 ("Merge branch 'drm-uapi-extern-c-fixes' of https://github.com/evelikov/linux into drm-next")
Reviewed-by: Emil Velikov <emil.l.velikov at gmail.com>

Thanks Arnd !

As Dave mentioned - the best solution would be to have the hunks
generated on the fly. Sadly Perl and me don't go hand in hand so if
you're interested I'll be really grateful.

-Emil


From arnd at arndb.de  Wed May 18 13:25:03 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 18 May 2016 22:25:03 +0200
Subject: [RFC PATCH 1/3] asm-generic: io: Add exec versions of ioremap
In-Reply-To: <20160518175102.GX5783@n2100.arm.linux.org.uk>
References: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
 <573C7844.5030107@ti.com> <20160518175102.GX5783@n2100.arm.linux.org.uk>
Message-ID: <3861017.ZJOlWYvEFT@wuerfel>

On Wednesday 18 May 2016 18:51:02 Russell King - ARM Linux wrote:
> On Wed, May 18, 2016 at 09:12:20AM -0500, Dave Gerlach wrote:
> > Ok thank you for the pointer. I agree, the memremap API looks like a better
> > fit for this. I think it likely makes the most sense to still add these
> > ioremap_exec and ioremap_exec_nocache and then call them through the
> > memremap API based on new flags. This will fit into the current use model
> > for memremap as it currently uses all of the other ioremap calls internally,
> > and doing it how I just described will let this code evolve along with
> > memremap.
> 
> I would _really_ prefer not to do that.  Why?  Because IO memory does
> not have the required properties to be executable.  IO memory is normally
> memory which has side effects - and by side effects, I mean reading it
> can provoke hardware to perform some action.  You don't want to be
> executing from such memory.
> 
> So, in my mind, ioremap_exec makes absolutely no sense, and having it
> gives people a new interface to abuse - and abuse they will.

Agreed, calling it ioremap when it is really memremap makes no sense.

I also see another problem in the asm-generic portion:

+#ifndef ARCH_HAS_IOREMAP_EXEC
+#define ioremap_exec ioremap
+#define ioremap_exec_nocache ioremap_nocache
+#endif

The ARM version of ioremap_exec() that gets added in this patch is cached
(like memremap()), but then the asm-generic version is not? This is
even more confusing, it should at least do roughly the same thing across
architectures.

There should also be some documentation about what the expected behavior is, e.g.:

- is memremap_exec() by default cached or not? (I assume it would
  be like memremap())
- If we have an interface that does explicit uncached executable mapping,
  what about architectures on which this is not possible? Should they
  fall back to cached or non-executable, or cause a link error?  

	Arnd


From emil.l.velikov at gmail.com  Wed May 18 13:26:04 2016
From: emil.l.velikov at gmail.com (Emil Velikov)
Date: Wed, 18 May 2016 21:26:04 +0100
Subject: [RFC 2/3] drm/mediatek: add support for Mediatek SoC MT2701
In-Reply-To: <1463560401.8576.15.camel@mtksdaap41>
References: <1463053795-55455-1-git-send-email-yt.shen@mediatek.com>
 <1463053795-55455-3-git-send-email-yt.shen@mediatek.com>
 <CACvgo52qc4E=MAGLoCaUH+GZuyvPexHchZnvuv-fF8P23e_1Uw@mail.gmail.com>
 <1463560401.8576.15.camel@mtksdaap41>
Message-ID: <CACvgo50-wnRYiYueRTqUT=PsUWu4NRm6bwZO8izaAZuf6-kMWQ@mail.gmail.com>

On 18 May 2016 at 09:33, YT Shen <yt.shen at mediatek.com> wrote:

>> > @@ -108,6 +108,10 @@ int mtk_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
>> >         int ret;
>> >
>> >         args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
>> > +       /*
>> > +       * align to 8 bytes since Mali requires it.
>> > +       */
>> > +       args->pitch = ALIGN(args->pitch, 8);
>> Are you sure we need this, based on the line just above ?
> I think bpp stands for bits per pixel, so width * bpp / 8 simply transfer from bits to bytes, which
> cannot guarantee align to 8.
>
You're absolutely correct. Reading the comment made me loose my mind
and completely misinterpret the division macro.

> I will remove this align part from the patch, this constraint is not from display controller.
Thank you !

Regards
Emil


From davidm at egauge.net  Wed May 18 13:46:32 2016
From: davidm at egauge.net (David Mosberger)
Date: Wed, 18 May 2016 14:46:32 -0600
Subject: [PATCH] drivers: nvmem: atmel-secumod: New driver for Atmel
 Secumod nvram
In-Reply-To: <20160518164259.GA28954@rob-hp-laptop>
References: <alpine.LNX.2.00.1605121505320.21379@nippy.intranet>
 <1463429830-20539-1-git-send-email-davidm@egauge.net>
 <20160518164259.GA28954@rob-hp-laptop>
Message-ID: <CALnQHM0YxahSX040i78X2182QWqvdyEtuvRY98KaETQf4eKvDg@mail.gmail.com>

Thanks for the feedback. Rob!  I'll make the changes and resend the
patch (which has now also been updated to work with linux-next).


From linux at armlinux.org.uk  Wed May 18 13:57:59 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Wed, 18 May 2016 21:57:59 +0100
Subject: [RFC PATCH 1/3] asm-generic: io: Add exec versions of ioremap
In-Reply-To: <3861017.ZJOlWYvEFT@wuerfel>
References: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
 <573C7844.5030107@ti.com>
 <20160518175102.GX5783@n2100.arm.linux.org.uk>
 <3861017.ZJOlWYvEFT@wuerfel>
Message-ID: <20160518205758.GY5783@n2100.arm.linux.org.uk>

On Wed, May 18, 2016 at 10:25:03PM +0200, Arnd Bergmann wrote:
> The ARM version of ioremap_exec() that gets added in this patch is cached
> (like memremap()), but then the asm-generic version is not? This is
> even more confusing, it should at least do roughly the same thing across
> architectures.
> 
> There should also be some documentation about what the expected behavior is, e.g.:
> 
> - is memremap_exec() by default cached or not? (I assume it would
>   be like memremap())
> - If we have an interface that does explicit uncached executable mapping,
>   what about architectures on which this is not possible? Should they
>   fall back to cached or non-executable, or cause a link error?  

Another important point is whether atomic instructions / kernel locks
can be located within the mapped memory.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From xypron.glpk at gmx.de  Wed May 18 13:59:50 2016
From: xypron.glpk at gmx.de (Heinrich Schuchardt)
Date: Wed, 18 May 2016 22:59:50 +0200
Subject: [PATCH 1/1] drm/mediatek: do not dereference NULL
Message-ID: <1463605190-5323-1-git-send-email-xypron.glpk@gmx.de>

After having verified that dpi is NULL we should not
dereference it.

Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
 drivers/gpu/drm/mediatek/mtk_dpi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index d05ca79..3dbd00d 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -433,7 +433,7 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
 	unsigned int factor;
 
 	if (!dpi) {
-		dev_err(dpi->dev, "invalid argument\n");
+		dev_err(NULL, "invalid argument\n");
 		return -EINVAL;
 	}
 
-- 
2.1.4



From davidm at egauge.net  Wed May 18 14:06:04 2016
From: davidm at egauge.net (David Mosberger-Tang)
Date: Wed, 18 May 2016 15:06:04 -0600
Subject: [PATCH] drivers: nvmem: atmel-secumod: New driver for Atmel Secumod
 nvram
In-Reply-To: <20160518164259.GA28954@rob-hp-laptop>
References: <20160518164259.GA28954@rob-hp-laptop>
Message-ID: <1463605564-14397-1-git-send-email-davidm@egauge.net>

Signed-off-by: David Mosberger <davidm at egauge.net>
---
 .../devicetree/bindings/nvmem/atmel-secumod.txt    |  47 +++++++
 drivers/nvmem/Kconfig                              |   7 +
 drivers/nvmem/Makefile                             |   2 +
 drivers/nvmem/atmel-secumod.c                      | 143 +++++++++++++++++++++
 4 files changed, 199 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
 create mode 100644 drivers/nvmem/atmel-secumod.c

diff --git a/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
new file mode 100644
index 0000000..d65cad5
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
@@ -0,0 +1,47 @@
+= Atmel Secumod device tree bindings =
+
+This binding is intended to represent Atmel's Secumod which is found
+in SAMA5D2 and perhaps others.
+
+Required properties:
+- compatible: should be "atmel,sama5d2-secumod"
+- reg: Should contain RAM location and length, followed
+       by register location and length of the Secumod controller.
+
+= Data cells =
+Are child nodes of secumod, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example:
+
+    secumod at fc040000 {
+            compatible = "atmel,sama5d2-secumod";
+            reg = <0xf8044000 0x1420>, <0xfc040000 0x4000>;
+            reg-names = "SECURAM", "SECUMOD";
+            status = "okay";
+
+            #address-cells = <1>;
+            #size-cells = <1>;
+            ranges;
+
+            secram-auto-erasable at 0 {
+                    reg = <0x0000 0x1000>;
+            };
+            secram at 1000 {
+                    reg = <0x1000 0x400>;
+            };
+            ram at 1400 {
+                    reg = <0x1400 0x20>;
+            };
+    };
+
+= Data consumers =
+Are device nodes which consume nvmem data cells.
+
+For example:
+
+	ram {
+		...
+		nvmem-cells = <&ram>;
+		nvmem-cell-names = "RAM";
+	};
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 3041d48..88b21e3 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -101,4 +101,11 @@ config NVMEM_VF610_OCOTP
 	  This driver can also be build as a module. If so, the module will
 	  be called nvmem-vf610-ocotp.
 
+config NVMEM_ATMEL_SECUMOD
+       tristate "Atmel Secure Module driver"
+       depends on ARCH_AT91
+       help
+         Select this to get support for the secure module (SECUMOD) built
+	 into the SAMA5D2 chips.
+
 endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 45ab1ae..9cbd950 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -22,3 +22,5 @@ obj-$(CONFIG_NVMEM_SUNXI_SID)	+= nvmem_sunxi_sid.o
 nvmem_sunxi_sid-y		:= sunxi_sid.o
 obj-$(CONFIG_NVMEM_VF610_OCOTP)	+= nvmem-vf610-ocotp.o
 nvmem-vf610-ocotp-y		:= vf610-ocotp.o
+obj-$(CONFIG_NVMEM_ATMEL_SECUMOD)	+= nvmem-atmel-secumod.o
+nvmem-atmel-secumod-y		:= atmel-secumod.o
diff --git a/drivers/nvmem/atmel-secumod.c b/drivers/nvmem/atmel-secumod.c
new file mode 100644
index 0000000..fc5a96b
--- /dev/null
+++ b/drivers/nvmem/atmel-secumod.c
@@ -0,0 +1,143 @@
+/*
+ * Driver for SAMA5D2 secure module (SECUMOD).
+ *
+ * Copyright (C) 2016 eGauge Systems LLC
+ *
+ * David Mosberger <davidm at egauge.net>
+ *
+ * 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/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+static int
+secumod_reg_read(void *context, unsigned int reg, void *_val, size_t bytes)
+{
+	void __iomem *base = context;
+	u32 *val = _val;
+	int i = 0, words = bytes / 4;
+
+	while (words--)
+		*val++ = readl(base + reg + (i++ * 4));
+
+	return 0;
+}
+
+static int
+secumod_reg_write(void *context, unsigned int reg, void *_val, size_t bytes)
+{
+	void __iomem *base = context;
+	u32 *val = _val;
+	int i = 0, words = bytes / 4;
+
+	while (words--)
+		writel(*val++, base + reg + (i++ * 4));
+
+	return 0;
+}
+
+static struct nvmem_config econfig = {
+	.name = "secumod",
+	.owner = THIS_MODULE,
+	.stride = 4,
+	.word_size = 1,
+	.reg_read = secumod_reg_read,
+	.reg_write = secumod_reg_write,
+};
+
+/*
+ * Security-module register definitions:
+ */
+#define SECUMOD_RAMRDY	0x0014
+
+/*
+ * Since the secure module may need to automatically erase some of the
+ * RAM, it may take a while for it to be ready.  As far as I know,
+ * it's not documented how long this might take in the worst-case.
+ */
+static void
+secumod_wait_ready (void *regs)
+{
+	unsigned long start, stop;
+
+	start = jiffies;
+	while (!(readl(regs + SECUMOD_RAMRDY) & 1))
+		msleep_interruptible(1);
+	stop = jiffies;
+	if (stop != start)
+		pr_info("nvmem-atmel-secumod: it took %u msec for SECUMOD "
+			"to become ready...\n", jiffies_to_msecs(stop - start));
+	else
+		pr_info("nvmem-atmel-secumod: ready\n");
+}
+
+static int secumod_remove(struct platform_device *pdev)
+{
+	struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+	return nvmem_unregister(nvmem);
+}
+
+static int secumod_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct nvmem_device *nvmem;
+	void __iomem *base;
+
+	/*
+	 * Map controller address temporarily so we can ensure that
+	 * the hardware is ready:
+	 */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	secumod_wait_ready(base);
+	devm_iounmap(dev, base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	econfig.size = resource_size(res);
+	econfig.dev = dev;
+	econfig.priv = base;
+
+	nvmem = nvmem_register(&econfig);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
+
+	platform_set_drvdata(pdev, nvmem);
+
+	return 0;
+}
+
+static const struct of_device_id secumod_of_match[] = {
+	{ .compatible = "atmel,sama5d2-secumod",},
+	{/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, secumod_of_match);
+
+static struct platform_driver secumod_driver = {
+	.probe = secumod_probe,
+	.remove = secumod_remove,
+	.driver = {
+		.name = "atmel,sama5d2-secumod",
+		.of_match_table = secumod_of_match,
+	},
+};
+module_platform_driver(secumod_driver);
+MODULE_AUTHOR("David Mosberger <davidm at egauge.net>");
+MODULE_DESCRIPTION("Atmel Secumod driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1



From maxime.ripard at free-electrons.com  Wed May 18 14:20:18 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 18 May 2016 23:20:18 +0200
Subject: [PATCH 15/16] clk: sunxi-ng: Add H3 clocks
In-Reply-To: <20160516154739.d87e0a9891a7fb5fed051a89@free.fr>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
 <20160516154739.d87e0a9891a7fb5fed051a89@free.fr>
Message-ID: <20160518212018.GT27618@lukather>

Hi,

On Mon, May 16, 2016 at 03:47:39PM +0200, Jean-Francois Moine wrote:
> On Sun,  8 May 2016 22:01:50 +0200
> Maxime Ripard <maxime.ripard at free-electrons.com> wrote:
> 
> > Add the list of clocks and resets found in the H3 CCU.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/clk/sunxi-ng/Makefile        |   2 +
> >  drivers/clk/sunxi-ng/ccu-sun8i-h3.c  | 757 +++++++++++++++++++++++++++++++++++
> >  include/dt-bindings/clock/sun8i-h3.h | 162 ++++++++
> >  include/dt-bindings/reset/sun8i-h3.h | 103 +++++
> >  4 files changed, 1024 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> >  create mode 100644 include/dt-bindings/clock/sun8i-h3.h
> >  create mode 100644 include/dt-bindings/reset/sun8i-h3.h
> > 
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> > index c794f57b6fb1..67ff6a92f124 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -13,3 +13,5 @@ obj-y += ccu_nkmp.o
> >  obj-y += ccu_nm.o
> >  obj-y += ccu_p.o
> >  obj-y += ccu_phase.o
> > +
> > +obj-y += ccu-sun8i-h3.o
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> > new file mode 100644
> > index 000000000000..5ce699e95c32
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> > @@ -0,0 +1,757 @@
> 	[snip]
> > +static struct ccu_nm pll_audio_base_clk = {
> > +	.enable		= BIT(31),
> > +	.lock		= BIT(28),
> > +
> > +	.m		= SUNXI_CLK_FACTOR(0, 5),
> > +	.n		= SUNXI_CLK_FACTOR(8, 7),
> > +
> > +	.common		= {
> > +		.reg		= 0x008,
> > +		.features	= CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> > +		.hw.init	= SUNXI_HW_INIT("pll-audio-base",
> > +						"osc24M",
> > +						&ccu_nm_ops,
> > +						0),
> > +	},
> > +};
> > +
> > +static SUNXI_CCU_M(pll_audio_clk, "pll-audio", "pll-audio-base",
> > +		   0x008, 16, 4, 0);
> > +
> > +static SUNXI_CCU_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
> > +			      "pll-audio-base", 2, 1, 0);
> > +static SUNXI_CCU_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
> > +			      "pll-audio-base", 1, 1, 0);
> > +static SUNXI_CCU_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
> > +			      "pll-audio-base", 1, 2, 0);
> > +
> 	[snip]
> 
> The pll-audio-{2,4,8}x clocks lack the CLK_SET_RATE_PARENT.
> 
> Also, in my implementation of the sound on HDMI, I set pll-audio as the
> parent of the i2s2 clock. Then, as the pll-audio clock is defined here,
> setting its rate is always wrong (only 'M' is changed, and with a bad
> value - BTW, DIV_ROUND_UP would be welcome in ccu_m_find_best()).
> 
> As the pre-divider 'M' is set to 4 by default, there is no need to
> change it. Then, audio works fine for me with:
> 
> static SUNXI_CCU_FIXED_FACTOR(pll_audio, "pll-audio",
> 			      "pll-audio-base", 4, 1,
> 				CLK_SET_RATE_PARENT);

OK. I just changed it, we can always change it later if needs be.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160518/197395b9/attachment.sig>

From robh at kernel.org  Wed May 18 15:15:47 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 18 May 2016 17:15:47 -0500
Subject: [PATCH INTERNAL v2 1/3] Documentation: dt: Add Broadcom iproc
 pwm controller binding
In-Reply-To: <1463554441-47982-2-git-send-email-yendapally.reddy@broadcom.com>
References: <1463554441-47982-1-git-send-email-yendapally.reddy@broadcom.com>
 <1463554441-47982-2-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <20160518221546.GA32596@rob-hp-laptop>

Am I supposed to ignore since this is "internal"?

On Wed, May 18, 2016 at 02:53:59AM -0400, Yendapally Reddy Dhananjaya Reddy wrote:
> Add a binding for Broadcom iproc pwm controller
> 
> Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
> ---
>  .../devicetree/bindings/pwm/brcm,iproc-pwm.txt      | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt

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


From scott.branden at broadcom.com  Wed May 18 16:04:32 2016
From: scott.branden at broadcom.com (Scott Branden)
Date: Wed, 18 May 2016 16:04:32 -0700
Subject: [PATCH INTERNAL v2 1/3] Documentation: dt: Add Broadcom iproc pwm
 controller binding
In-Reply-To: <20160518221546.GA32596@rob-hp-laptop>
References: <1463554441-47982-1-git-send-email-yendapally.reddy@broadcom.com>
 <1463554441-47982-2-git-send-email-yendapally.reddy@broadcom.com>
 <20160518221546.GA32596@rob-hp-laptop>
Message-ID: <573CF500.5070708@broadcom.com>

Hi Rob,

On 16-05-18 03:15 PM, Rob Herring wrote:
> Am I supposed to ignore since this is "internal"?
The "INTERNAL" was supposed to be removed after internal review before 
sending out to the public mailing list.

Also, Yendapally's git email config was not setup properly so some are 
tagging the patchset as spam.

Other than that, everything is fine with the PATCH sent out to the open 
source community :)

I'm sure Yendapally will send out an updated version with those items 
corrected (and can add your Acked-by now).

Thanks,
  Scott

>
> On Wed, May 18, 2016 at 02:53:59AM -0400, Yendapally Reddy Dhananjaya Reddy wrote:
>> Add a binding for Broadcom iproc pwm controller
>>
>> Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
>> ---
>>   .../devicetree/bindings/pwm/brcm,iproc-pwm.txt      | 21 +++++++++++++++++++++
>>   1 file changed, 21 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
>
> Acked-by: Rob Herring <robh at kernel.org>
>


From robh at kernel.org  Wed May 18 16:05:22 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 18 May 2016 18:05:22 -0500
Subject: [PATCH v2 2/2] [media] atmel-isc: DT binding for Image Sensor
 Controller driver
In-Reply-To: <1463557590-29318-3-git-send-email-songjun.wu@atmel.com>
References: <1463557590-29318-1-git-send-email-songjun.wu@atmel.com>
 <1463557590-29318-3-git-send-email-songjun.wu@atmel.com>
Message-ID: <20160518230522.GA3198@rob-hp-laptop>

On Wed, May 18, 2016 at 03:46:29PM +0800, Songjun Wu wrote:
> DT binding documentation for ISC driver.
> 
> Signed-off-by: Songjun Wu <songjun.wu at atmel.com>
> ---
> 
> Changes in v2:
> - Remove the unit address of the endpoint.
> - Add the unit address to the clock node.
> - Avoid using underscores in node names.
> - Drop the "0x" in the unit address of the i2c node.
> - Modify the description of "atmel,sensor-preferred".
> - Add the description for the ISC internal clock.
> 
>  .../devicetree/bindings/media/atmel-isc.txt        | 100 +++++++++++++++++++++
>  1 file changed, 100 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/media/atmel-isc.txt
> 
> diff --git a/Documentation/devicetree/bindings/media/atmel-isc.txt b/Documentation/devicetree/bindings/media/atmel-isc.txt
> new file mode 100644
> index 0000000..9e65395
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/atmel-isc.txt
> @@ -0,0 +1,100 @@
> +Atmel Image Sensor Controller (ISC)
> +----------------------------------------------
> +
> +Required properties for ISC:
> +- compatible
> +	Must be "atmel,sama5d2-isc"
> +- reg
> +	Physical base address and length of the registers set for the device;
> +- interrupts
> +	Should contain IRQ line for the ISC;
> +- clocks
> +	List of clock specifiers, corresponding to entries in
> +	the clock-names property;
> +	Please refer to clock-bindings.txt.
> +- clock-names
> +	Required elements: "hclock", "ispck".
> +- pinctrl-names, pinctrl-0
> +	Please refer to pinctrl-bindings.txt.
> +- clk-in-isc
> +	ISC internal clock node, it includes two clock nodes,
> +	isc-ispck and isc-mck.

And you need to describe each of these nodes and the properties they 
have. But more on this below...

> +- atmel,sensor-preferred
> +	ISC may convert the raw format to the specified format when the sensor
> +	outputs the raw format, and the sensor may output the specified format
> +	directly. If sensor is preferred to output the specified format
> +	directly, the value should be 1 (1-preferred, 0-not).
> +	The default value is 1.

I don't think this belongs in DT. It sounds more like a configuration 
and userspace decision. It is still not clear what you mean by 
"specified format".

> +
> +ISC supports a single port node with parallel bus. It should contain one
> +'port' child node with child 'endpoint' node. Please refer to the bindings
> +defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
> +
> +Required properties for the ISC internal clocks:
> +- #address-cells
> +	should be 1 (reg is used to encode clk id).
> +- #size-cells
> +	should be 0 (reg is used to encode clk id).
> +- name
> +	device tree node describing a ISC internal clock.
> +	* #clock-cells: from common clock binding; should be set to 0.
> +	* reg: clock id, there are two values,
> +	       <0> is ISP clock, <1> is master clock.
> +	* clocks: shall be the isc internal clock source phandles.
> +		  e.g. clocks = <&isc_clk>, <&iscck>, <&isc_gclk>;
> +
> +Example:
> +isc: isc at f0008000 {
> +	compatible = "atmel,sama5d2-isc";
> +	reg = <0xf0008000 0x4000>;
> +	interrupts = <46 IRQ_TYPE_LEVEL_HIGH 5>;
> +	clocks = <&isc_clk>, <&isc_ispck>;
> +	clock-names = "hclock", "ispck";
> +	atmel,sensor-preferred = <1>;
> +
> +	port {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		isc_0: endpoint {
> +			remote-endpoint = <&ov7740_0>;
> +			hsync-active = <1>;
> +			vsync-active = <0>;
> +			pclk-sample = <1>;
> +		};
> +	};
> +
> +	clk-in-isc {

Is this really separate from the rest of the isc block. It would be 
much more simple to define all the input clocks at the parent and then 
reference these 2 clocks with <&isc 0> and <&isc 1>.

> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		isc_ispck: isc-ispck at 0 {

These would need a compatible string otherwise.

> +			#clock-cells = <0>;
> +			reg = <0>;

Are 0 and 1 meaningful in terms of the hardware description?

> +			clocks = <&isc_clk>, <&iscck>;
> +		};
> +
> +		isc_mck: isc-mck at 1 {
> +			#clock-cells = <0>;
> +			reg = <1>;
> +			clocks = <&isc_clk>, <&iscck>, <&isc_gclk>;
> +		};
> +	};
> +};


From robh at kernel.org  Wed May 18 16:29:25 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 18 May 2016 18:29:25 -0500
Subject: [PATCH] ARM: at91: Add DT support for Olimex SAM9-L9260 board.
In-Reply-To: <1463574766-15568-1-git-send-email-raashidmuhammed@zilogic.com>
References: <1463574766-15568-1-git-send-email-raashidmuhammed@zilogic.com>
Message-ID: <20160518232925.GA6545@rob-hp-laptop>

On Wed, May 18, 2016 at 06:02:46PM +0530, Raashid Muhammed wrote:
> From: Raashid Muhammed <raashidmuhammed at zilogic.com>
> 
> sam9-l9260 is a low cost board designed by Olimex.
> 
> More infomation is available at:
> https://www.olimex.com/Products/ARM/Atmel/SAM9-L9260/
> 
> Signed-off-by: Raashid Muhammed <raashidmuhammed at zilogic.com>
> Reviewed-by: Vijay Kumar B. <vijaykumar at bravegnu.org>
> ---
>  .../devicetree/bindings/arm/olimex-at91.txt        |   6 ++
>  arch/arm/boot/dts/Makefile                         |   1 +
>  arch/arm/boot/dts/sam9-l9260.dts                   | 108 +++++++++++++++++++++
>  3 files changed, 115 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/olimex-at91.txt
>  create mode 100644 arch/arm/boot/dts/sam9-l9260.dts
> 
> diff --git a/Documentation/devicetree/bindings/arm/olimex-at91.txt b/Documentation/devicetree/bindings/arm/olimex-at91.txt
> new file mode 100644
> index 0000000..0587d63
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/olimex-at91.txt
> @@ -0,0 +1,6 @@
> +Olimex AT91 Device Tree Bindings
> +--------------------------------

There's not an existing at91 or olimex file this would fit into? We 
don't need 1 file per board.

> +
> +SAM9-L9260 Board
> +Required root node properties:
> +    - compatible = "olimex,sam9-l9260", "atmel,at91sam9260";
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index 95c1923..ae3b50f 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -19,6 +19,7 @@ dtb-$(CONFIG_SOC_SAM_V4_V5) += \
> 	usb_a9260.dtb \
> 	at91sam9261ek.dtb \
> 	at91sam9263ek.dtb \
> +	sam9-l9260.dtb \
> 	tny_a9263.dtb \
> 	usb_a9263.dtb \
> 	at91-foxg20.dtb \
> diff --git a/arch/arm/boot/dts/sam9-l9260.dts b/arch/arm/boot/dts/sam9-l9260.dts
> new file mode 100644
> index 0000000..3ddf7af
> --- /dev/null
> +++ b/arch/arm/boot/dts/sam9-l9260.dts
> @@ -0,0 +1,108 @@
> +/*
> + * sam9-l9260.dts - Device Tree file for Olimex SAM9-L9260 board
> + *
> + *  Copyright (C) 2016 Raashid Muhammed <raashidmuhammed at zilogic.com>
> + *
> + * Licensed under GPLv2 or later.
> + */
> +/dts-v1/;
> +#include "at91sam9260.dtsi"
> +
> +/ {
> +	model = "Olimex sam9-l9260";
> +	compatible = "olimex,sam9-l9260", "atmel,at91sam9260", "atmel,at91sam9";
> +
> +	chosen {
> +		bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";

use stdout-path instead of console on the command line. Actually, you 
should then drop the rest of the bootargs. They are all user specific.

> +	 };
> +
> +	 memory {
> +		reg = <0x20000000 0x4000000>;
> +	 };
> +
> +	 clocks {
> +		slow_xtal {
> +			clock-frequency = <32768>;
> +		};
> +
> +		main_xtal {
> +			clock-frequency = <18432000>;
> +		};
> +	 };
> +
> +	 ahb {
> +		apb {
> +			dbgu: serial at fffff200 {
> +				status = "okay";
> +			 };
> +
> +			macb0: ethernet at fffc4000 {
> +				phy-mode = "mii";
> +				status = "okay";
> +			 };
> +
> +			spi0: spi at fffc8000 {
> +				status = "okay";
> +				cs-gpios = <&pioC 11 0>, <0>, <0>, <0>;
> +				mtd_dataflash at 0 {
> +					compatible = "atmel,at45", "atmel,dataflash";
> +					spi-max-frequency = <15000000>;
> +					reg = <0>;
> +				};
> +			};
> +
> +			mmc0: mmc at fffa8000 {
> +				pinctrl-0 = <
> +					&pinctrl_board_mmc0
> +					&pinctrl_mmc0_clk
> +					&pinctrl_mmc0_slot1_cmd_dat0
> +					&pinctrl_mmc0_slot1_dat1_3>;
> +				status = "okay";
> +				slot at 1 {
> +					reg = <1>;
> +					bus-width = <4>;
> +					cd-gpios = <&pioC 8 GPIO_ACTIVE_HIGH>;
> +					wp-gpios = <&pioC 4 GPIO_ACTIVE_HIGH>;
> +				};
> +			};
> +
> +			pinctrl at fffff400 {
> +				mmc0 {
> +					pinctrl_board_mmc0: mmc0-board {
> +						atmel,pins =
> +							<AT91_PIOC 8 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH	/* PC08 gpio CD pin pull up and deglitch */
> +							 AT91_PIOC 4 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP>;	/* PC04 gpio WP pin pull up */
> +					};
> +				};
> +			};
> +
> +
> +		 };
> +
> +		 usb0: ohci at 00500000 {

Drop the leading 0. You'll need to fixup the base dts.

> +		       status = "okay";
> +		 };
> +
> +		 nand0: nand at 40000000 {
> +		       nand-bus-width = <8>;
> +		       nand-ecc-mode = "soft";
> +		       nand-on-flash-bbt = <1>;
> +		       status = "okay";
> +		 };
> +	 };
> +
> +	 i2c at 0 {
> +		status = "okay";
> +	 };
> +
> +	 leds {
> +		compatible = "gpio-leds";
> +
> +		b0 {
> +			label = "b0";
> +			gpios = <&pioA 6 GPIO_ACTIVE_HIGH>;
> +			linux,default-trigger = "heartbeat";
> +		};
> +
> +	};
> +};
> --
> 2.1.4
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From robh at kernel.org  Wed May 18 16:30:30 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 18 May 2016 18:30:30 -0500
Subject: [PATCH 05/14] mfd: twl6040: Register child device for
 twl6040-pdmclk
In-Reply-To: <1463579196-5484-6-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
 <1463579196-5484-6-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <20160518233030.GA9813@rob-hp-laptop>

On Wed, May 18, 2016 at 04:46:27PM +0300, Peter Ujfalusi wrote:
> The McPDM in OMAP4/5 is using the pdmclk from twl6040 as functional clock.
> The twl6040-pdmclk driver provides a clock which can be used to make sure
> that the pdmclk is active when the McPDM is in use.
> 
> Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
> ---
>  Documentation/devicetree/bindings/mfd/twl6040.txt | 1 +
>  drivers/mfd/twl6040.c                             | 5 +++++
>  include/linux/mfd/twl6040.h                       | 2 +-
>  3 files changed, 7 insertions(+), 1 deletion(-)

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


From d-gerlach at ti.com  Wed May 18 16:30:25 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 18:30:25 -0500
Subject: [PATCH 1/2] Documentation: dt: add bindings for ti-cpufreq
In-Reply-To: <cover.1463609497.git.d-gerlach@ti.com>
References: <cover.1463609497.git.d-gerlach@ti.com>
Message-ID: <f17fbc8acb1e903b9f175f49fe29563b83132faf.1463609497.git.d-gerlach@ti.com>

Add the device tree bindings document for the TI CPUFreq/OPP driver
on AM33xx and AM43xx SoCs. The operating-points-v2 binding allows us
to provide an opp-supported-hw property for each OPP to define when
it is available. This driver is responsible for reading and parsing
registers to determine which OPPs can be selectively enabled based
on the specific SoC in use by matching against the opp-supported-hw
data.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 .../devicetree/bindings/cpufreq/ti-cpufreq.txt     | 89 ++++++++++++++++++++++
 1 file changed, 89 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt

diff --git a/Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt
new file mode 100644
index 000000000000..f719b2df2a1f
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt
@@ -0,0 +1,89 @@
+Bindings for TI's CPUFreq driver
+================================
+
+The ti-cpufreq driver works with the operating-points-v2 binding described
+at [../opp/opp.txt] to make sure the proper OPPs for a platform get enabled
+and then creates a "cpufreq-dt" platform device to leverage the cpufreq-dt
+driver described in [cpufreq-dt.txt].
+
+Certain TI SoCs, like those in the am335x, am437x, am57xx, and dra7xx
+families support different OPPs depending on the silicon variant in use.
+The ti-cpufreq driver uses the revision and an efuse value from the SoC to
+provide the OPP framework with supported hardware information. This is used
+to determine which OPPs from the operating-points-v2 table get enabled. In
+order to maintain backwards compatilibity if this information is not present
+the "cpufreq-dt" platform device is still created to attempt to find an
+operating-points (v1) table, otherwise no OPPs will be available because
+safe OPPs cannot be determined.
+
+Required properties:
+--------------------
+In 'cpus' nodes:
+- operating-points-v2: Phandle to the operating-points-v2 table to use
+- ti,syscon-efuse: Syscon phandle, offset to efuse register, efuse register
+		   mask, and efuse register shift to get the relevant bits
+		   that describe OPP availability
+- ti,syscon-rev: Syscon and offset used to look up revision value on SoC
+
+In 'operating-points-v2' table:
+- opp-supported-hw: Two bitfields indicating:
+	1. Which revision of the SoC the OPP is supported by
+	2. Which eFuse bits indicate this OPP is available
+
+	A bitwise and is performed against these values and if any bit
+	matches, the OPP gets enabled.
+
+NOTE: Without the above, platform-device for "cpufreq-dt" is still created
+      but no determination of which OPPs should be available is done, but this
+      allows for use of a v1 operating-points table.
+
+Example:
+--------
+
+/* From arch/arm/boot/dts/am4372.dtsi */
+cpus {
+	cpu: cpu at 0 {
+		...
+
+		operating-points-v2 = <&cpu0_opp_table>;
+
+		ti,syscon-efuse = <&scm_conf 0x610 0x3f 0>;
+		ti,syscon-rev = <&scm_conf 0x600>;
+
+		...
+	};
+};
+
+cpu0_opp_table: opp_table0 {
+	compatible = "operating-points-v2";
+	opp50 at 300000000 {
+		opp-hz = /bits/ 64 <300000000>;
+		opp-microvolt = <950000>;
+		opp-supported-hw = <0xFF 0x01>;
+		opp-suspend;
+	};
+
+	opp100 at 600000000 {
+		opp-hz = /bits/ 64 <600000000>;
+		opp-microvolt = <1100000>;
+		opp-supported-hw = <0xFF 0x04>;
+	};
+
+	opp120 at 720000000 {
+		opp-hz = /bits/ 64 <720000000>;
+		opp-microvolt = <1200000>;
+		opp-supported-hw = <0xFF 0x08>;
+	};
+
+	oppturbo at 800000000 {
+		opp-hz = /bits/ 64 <800000000>;
+		opp-microvolt = <1260000>;
+		opp-supported-hw = <0xFF 0x10>;
+	};
+
+	oppnitro at 1000000000 {
+		opp-hz = /bits/ 64 <1000000000>;
+		opp-microvolt = <1325000>;
+		opp-supported-hw = <0xFF 0x20>;
+	};
+};
-- 
2.7.3



From d-gerlach at ti.com  Wed May 18 16:30:24 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 18:30:24 -0500
Subject: [PATCH 0/2] cpufreq: Introduce TI CPUFreq/OPP Driver
Message-ID: <cover.1463609497.git.d-gerlach@ti.com>

Hi,
This series introduces the ti-cpufreq driver which parses SoC data and
provides opp-supported-hw data to the OPP core in order to enable the
proper OPPs for the silicon in use. It still relies on the cpufreq-dt
driver to actually provide cpufreq and creates the "cpufreq-dt" platform
driver after it probes as the sti-cpufreq driver does.

This series will add support for am335x, am437x, dra7xx, and am57xx
platforms, otherwise other TI devices will rely on the recently introduced
cpufreq-dt-platdev code [1] to create the cpufreq-dt device. This means
that the aforementioned platforms do *not* need to be added to
cpufreq-dt-platdev. DTS patches for the above platforms are being sent in
a separate series right after this one. Even without merging the DTS series,
this series will not break backwards compatibility for those platforms above
that already have operating-points v1 tables as the ti-cpufreq driver
fails through and creates the cpufreq-dt platform device if no
operating-points-v2 table is found.

This series is based on linux-next next-20160517 tag, it depends on [2] which
drops the default creation of the cpufreq-dt device from omap platform code,
otherwise we'd end up with a duplicate because this driver creates it also.

Regards,
Dave

[1] http://permalink.gmane.org/gmane.linux.power-management.general/73887
[2] http://permalink.gmane.org/gmane.linux.power-management.general/75215

Dave Gerlach (2):
  Documentation: dt: add bindings for ti-cpufreq
  cpufreq: ti: Add cpufreq driver to determine available OPPs at runtime

 .../devicetree/bindings/cpufreq/ti-cpufreq.txt     |  89 ++++++++
 drivers/cpufreq/Kconfig.arm                        |  11 +
 drivers/cpufreq/Makefile                           |   1 +
 drivers/cpufreq/ti-cpufreq.c                       | 254 +++++++++++++++++++++
 4 files changed, 355 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt
 create mode 100644 drivers/cpufreq/ti-cpufreq.c

-- 
2.7.3



From d-gerlach at ti.com  Wed May 18 16:30:26 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 18:30:26 -0500
Subject: [PATCH 2/2] cpufreq: ti: Add cpufreq driver to determine available
 OPPs at runtime
In-Reply-To: <cover.1463609497.git.d-gerlach@ti.com>
References: <cover.1463609497.git.d-gerlach@ti.com>
Message-ID: <9b8c1ba22e07cbfa25f93b33422fcfd1a8d10655.1463609497.git.d-gerlach@ti.com>

Some TI SoCs, like those in the AM335x, AM437x, DRA7x, and AM57x families,
have different OPPs available for the MPU depending on which specific
variant of the SoC is in use. This can be determined through use of the
revision and an eFuse register present in the silicon. Introduce a
ti-cpufreq driver that can read the aformentioned values and provide
them as version matching data to the opp framework. Through this the
opp-supported-hw dt binding that is part of the operating-points-v2
table can be used to indicate availability of OPPs for each device.

This driver also creates the "cpufreq-dt" platform_device after passing
the version matching data to the OPP framework so that the cpufreq-dt
handles the actual cpufreq implementation. Even without the necessary
data to pass the version matching data the driver will still create this
device to maintain backwards compatibility with operating-points v1
tables.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 drivers/cpufreq/Kconfig.arm  |  11 ++
 drivers/cpufreq/Makefile     |   1 +
 drivers/cpufreq/ti-cpufreq.c | 254 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 266 insertions(+)
 create mode 100644 drivers/cpufreq/ti-cpufreq.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index d89b8afe23b6..0dea6849ac3e 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -234,6 +234,17 @@ config ARM_TEGRA124_CPUFREQ
 	help
 	  This adds the CPUFreq driver support for Tegra124 SOCs.
 
+config ARM_TI_CPUFREQ
+	tristate "Texas Instruments CPUFreq support"
+	depends on ARCH_OMAP2PLUS
+	help
+	  This driver enables valid OPPs on the running platform based on
+	  values contained within the SoC in use. Enable this in order to
+	  use the cpufreq-dt driver on all Texas Instruments platforms that
+	  provide dt based operating-points-v2 tables with opp-supported-hw
+	  data provided. Required for cpufreq support on AM335x, AM437x,
+	  DRA7x, and AM57x platforms.
+
 config ARM_PXA2xx_CPUFREQ
 	tristate "Intel PXA2xx CPUfreq driver"
 	depends on PXA27x || PXA25x
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 0a9b6a093646..5b1b6ec0a9f0 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_ARM_SPEAR_CPUFREQ)		+= spear-cpufreq.o
 obj-$(CONFIG_ARM_STI_CPUFREQ)		+= sti-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)	+= tegra20-cpufreq.o
 obj-$(CONFIG_ARM_TEGRA124_CPUFREQ)	+= tegra124-cpufreq.o
+obj-$(CONFIG_ARM_TI_CPUFREQ)		+= ti-cpufreq.o
 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ)	+= vexpress-spc-cpufreq.o
 obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
 obj-$(CONFIG_MACH_MVEBU_V7)		+= mvebu-cpufreq.o
diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
new file mode 100644
index 000000000000..e47b452aadd0
--- /dev/null
+++ b/drivers/cpufreq/ti-cpufreq.c
@@ -0,0 +1,254 @@
+/*
+ * TI CPUFreq/OPP hw-supported driver
+ *
+ * Copyright (C) 2016 Texas Instruments, Inc.
+ *	 Dave Gerlach <d-gerlach at ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/cpu.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pm_opp.h>
+#include <linux/regmap.h>
+
+#define REVISION_MASK				(0xF << 28)
+#define REVISION_SHIFT				28
+
+#define DRA7_EFUSE_HAS_OD_MPU_OPP		11
+#define DRA7_EFUSE_HAS_HIGH_MPU_OPP		15
+#define DRA7_EFUSE_HAS_ALL_MPU_OPP		23
+
+#define DRA7_EFUSE_NOM_MPU_OPP			BIT(0)
+#define DRA7_EFUSE_OD_MPU_OPP			BIT(1)
+#define DRA7_EFUSE_HIGH_MPU_OPP			BIT(2)
+
+#define VERSION_COUNT				2
+
+static struct ti_cpufreq_data {
+	struct device *cpu;
+	struct regmap *opp_efuse;
+	struct regmap *revision;
+} opp_data;
+
+static struct ti_cpufreq_soc_data {
+	unsigned long (*efuse_xlate)(unsigned long efuse);
+} *soc_data;
+
+static unsigned long amx3_efuse_xlate(unsigned long efuse)
+{
+	/* AM335x and AM437x use "OPP disable" bits, so invert */
+	return ~efuse;
+}
+
+static unsigned long dra7_efuse_xlate(unsigned long efuse)
+{
+	unsigned long calculated_efuse = DRA7_EFUSE_NOM_MPU_OPP;
+
+	/*
+	 * The efuse on dra7 and am57 parts contains a specific
+	 * value indicating the highest available OPP.
+	 */
+
+	switch (efuse) {
+	case DRA7_EFUSE_HAS_ALL_MPU_OPP:
+	case DRA7_EFUSE_HAS_HIGH_MPU_OPP:
+		calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP;
+	case DRA7_EFUSE_HAS_OD_MPU_OPP:
+		calculated_efuse |= DRA7_EFUSE_OD_MPU_OPP;
+	}
+
+	return calculated_efuse;
+}
+
+static struct ti_cpufreq_soc_data amx3_soc_data = {
+	.efuse_xlate = amx3_efuse_xlate,
+};
+
+static struct ti_cpufreq_soc_data dra7_soc_data = {
+	.efuse_xlate = dra7_efuse_xlate,
+};
+
+/**
+ * ti_cpufreq_get_efuse() - Parse and return efuse value present on SoC
+ * @efuse_value: Set to the value parsed from efuse
+ *
+ * Returns error code if efuse not read properly.
+ */
+static int ti_cpufreq_get_efuse(u32 *efuse_value)
+{
+	struct device *dev = opp_data.cpu;
+	struct device_node *np = dev->of_node;
+	unsigned int efuse_offset;
+	u32 efuse, efuse_mask, efuse_shift;
+	int ret;
+
+	ret = of_property_read_u32_index(np, "ti,syscon-efuse",
+					 1, &efuse_offset);
+	if (ret) {
+		dev_err(dev,
+			"No efuse offset provided %s: %d\n",
+			np->full_name, ret);
+		return ret;
+	}
+
+	ret = of_property_read_u32_index(np, "ti,syscon-efuse", 2,
+					 &efuse_mask);
+	if (ret)
+		efuse_mask = 0xffffffff;
+
+	ret = of_property_read_u32_index(np, "ti,syscon-efuse", 3,
+					 &efuse_shift);
+	if (ret)
+		efuse_shift = 0;
+
+	ret = regmap_read(opp_data.opp_efuse, efuse_offset, &efuse);
+	if (ret) {
+		dev_err(dev,
+			"Failed to read the efuse value from syscon: %d\n",
+			ret);
+		return ret;
+	}
+
+	efuse = (efuse & efuse_mask) >> efuse_shift;
+
+	*efuse_value = soc_data->efuse_xlate(efuse);
+
+	return 0;
+}
+
+/**
+ * ti_cpufreq_get_rev() - Parse and return rev value present on SoC
+ * @revision_value: Set to the value parsed from revision register
+ *
+ * Returns error code if revision not read properly.
+ */
+static int ti_cpufreq_get_rev(u32 *revision_value)
+{
+	struct device *dev = opp_data.cpu;
+	struct device_node *np = dev->of_node;
+	unsigned int revision_offset;
+	u32 revision;
+	int ret;
+
+	ret = of_property_read_u32_index(np, "ti,syscon-rev",
+					 1, &revision_offset);
+	if (ret) {
+		dev_err(dev,
+			"No revision offset provided %s [%d]\n",
+			np->full_name, ret);
+		return ret;
+	}
+
+	ret = regmap_read(opp_data.revision, revision_offset, &revision);
+	if (ret) {
+		dev_err(dev,
+			"Failed to read the revision number from syscon: %d\n",
+			ret);
+		return ret;
+	}
+
+	*revision_value = BIT((revision & REVISION_MASK) >> REVISION_SHIFT);
+
+	return 0;
+}
+
+static int ti_cpufreq_setup_syscon_registers(void)
+{
+	struct device *dev = opp_data.cpu;
+	struct device_node *np = dev->of_node;
+
+	opp_data.opp_efuse = syscon_regmap_lookup_by_phandle(np,
+							"ti,syscon-efuse");
+	if (IS_ERR(opp_data.opp_efuse)) {
+		dev_dbg(dev,  "\"ti,syscon-efuse\" is missing, cannot use OPPv2 table.\n");
+		return PTR_ERR(opp_data.opp_efuse);
+	}
+
+	opp_data.revision = syscon_regmap_lookup_by_phandle(np,
+							"ti,syscon-rev");
+	if (IS_ERR(opp_data.revision)) {
+		dev_dbg(dev,  "\"ti,syscon-rev\" is missing, cannot use OPPv2 table.\n");
+		return PTR_ERR(opp_data.revision);
+	}
+
+	return 0;
+}
+
+static struct ti_cpufreq_soc_data *ti_cpufreq_get_soc_data(void)
+{
+	if (of_machine_is_compatible("ti,am33xx") ||
+	    of_machine_is_compatible("ti,am4372"))
+		return &amx3_soc_data;
+	else if (of_machine_is_compatible("ti,dra7"))
+		return &dra7_soc_data;
+	else
+		return NULL;
+}
+
+static int ti_cpufreq_init(void)
+{
+	int ret;
+	u32 version[VERSION_COUNT];
+
+	soc_data = ti_cpufreq_get_soc_data();
+	if (!soc_data)
+		return -ENODEV;
+
+	opp_data.cpu = get_cpu_device(0);
+	if (!opp_data.cpu) {
+		pr_err("%s: Failed to get device for CPU0\n", __func__);
+		return -ENODEV;
+	}
+
+	if (!of_get_property(opp_data.cpu->of_node, "operating-points-v2",
+			     NULL)) {
+		dev_info(opp_data.cpu, "OPP-v2 not supported, cpufreq-dt will attempt to use legacy tables.\n");
+		goto register_cpufreq_dt;
+	}
+
+	ret = ti_cpufreq_setup_syscon_registers();
+	if (ret)
+		goto register_cpufreq_dt;
+
+	/*
+	 * OPPs determine whether or not they are supported based on
+	 * two metrics:
+	 *	0 - SoC Revision
+	 *	1 - eFuse value
+	 */
+	ret = ti_cpufreq_get_rev(&version[0]);
+	if (ret)
+		return ret;
+
+	ret = ti_cpufreq_get_efuse(&version[1]);
+	if (ret)
+		return ret;
+
+	ret = dev_pm_opp_set_supported_hw(opp_data.cpu, version, VERSION_COUNT);
+	if (ret) {
+		dev_err(opp_data.cpu, "Failed to set supported hardware\n");
+		return ret;
+	}
+
+register_cpufreq_dt:
+	platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+
+	return 0;
+}
+module_init(ti_cpufreq_init);
+
+MODULE_DESCRIPTION("TI CPUFreq/OPP hw-supported driver");
+MODULE_AUTHOR("Dave Gerlach <d-gerlach at ti.com>");
+MODULE_LICENSE("GPL v2");
-- 
2.7.3



From robh at kernel.org  Wed May 18 16:31:41 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 18 May 2016 18:31:41 -0500
Subject: [PATCH 14/14] ASoC: omap-mcpdm: Add support for pdmclk clock
 handling
In-Reply-To: <1463579196-5484-15-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
 <1463579196-5484-15-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <20160518233141.GA10395@rob-hp-laptop>

On Wed, May 18, 2016 at 04:46:36PM +0300, Peter Ujfalusi wrote:
> McPDM module receives it's functional clock from external source. This
> clock is the pdmclk provided by the twl6040 audio IC. If the clock is not
> available all register accesses to McPDM fails and the module is not
> operational.
> 
> Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
> ---
>  Documentation/devicetree/bindings/sound/omap-mcpdm.txt | 10 ++++++++++
>  sound/soc/omap/omap-mcpdm.c                            | 17 +++++++++++++++++
>  2 files changed, 27 insertions(+)

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


From robh at kernel.org  Wed May 18 16:35:18 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 18 May 2016 18:35:18 -0500
Subject: [PATCH v2 4/4] documentation: Add secure monitor binding
 documentation
In-Reply-To: <1463583382-15614-5-git-send-email-carlo@caione.org>
References: <1463583382-15614-1-git-send-email-carlo@caione.org>
 <1463583382-15614-5-git-send-email-carlo@caione.org>
Message-ID: <20160518233518.GA11027@rob-hp-laptop>

On Wed, May 18, 2016 at 04:56:22PM +0200, Carlo Caione wrote:
> From: Carlo Caione <carlo at endlessm.com>
> 
> Add the binding documentation for the Amlogic secure monitor driver.
> 
> Signed-off-by: Carlo Caione <carlo at endlessm.com>
> ---
>  .../devicetree/bindings/soc/meson/meson_sm.txt     | 45 ++++++++++++++++++++++
>  1 file changed, 45 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/soc/meson/meson_sm.txt
> 
> diff --git a/Documentation/devicetree/bindings/soc/meson/meson_sm.txt b/Documentation/devicetree/bindings/soc/meson/meson_sm.txt
> new file mode 100644
> index 0000000..f59c732
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/meson/meson_sm.txt

bindings/firmware/

> @@ -0,0 +1,45 @@
> +* Amlogic Secure Monitor
> +
> +In the Amlogic SoCs the Secure Monitor code is used to provide access to the
> +NVMEM, enable JTAG, set USB boot, etc...
> +
> +Required properties for the secure monitor node:
> +- compatible: Should be "amlogic,meson-sm"
> +- amlogic,sm_cmd_input_base: SMC32 function identifier to read the physical
> +                             address of the input buffer
> +- amlogic,sm_cmd_output_base: SMC32 function identifier to read the physical
> +                              address of the output buffer

Use '-' rather than '_'.

> +
> +Example:
> +
> +	#include <dt-bindings/soc/meson-gxbb-sm.h>
> +
> +	...
> +
> +	sm {

Put this under a /firmware node.

> +		compatible = "amlogic,meson-sm";
> +		amlogic,sm_cmd_input_base = <SM_GET_SHARE_MEM_INPUT_BASE>;
> +		amlogic,sm_cmd_output_base = <SM_GET_SHARE_MEM_OUTPUT_BASE>;
> +	};
> +
> +Node of a device using the secure monitor must have a custom property to
> +specify the SMC32 function the driver is going to use. The values of all the
> +SMC function identifiers are listed in a SoC-specific header file:
> +
> +"include/dt-bindings/soc/meson-gxbb-sm.h" - for the Meson GXBB secure monitor.
> +
> +Example of the node using the secure monitor:
> +
> +	#include <dt-bindings/soc/meson-gxbb-sm.h>
> +
> +	...
> +
> +	efuse: efuse {
> +		compatible = "amlogic,meson-gxbb-efuse";
> +		amlogic,sm_cmd_read_efuse = <SM_EFUSE_READ>;
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +
> +		...
> +	};
> +
> -- 
> 2.7.4
> 


From d-gerlach at ti.com  Wed May 18 16:36:31 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 18:36:31 -0500
Subject: [PATCH 6/8] ARM: dts: dra7: Add dt node for the syscon control module
 wkup
In-Reply-To: <cover.1463606963.git.d-gerlach@ti.com>
References: <cover.1463606963.git.d-gerlach@ti.com>
Message-ID: <fb1b7f4b3f645decec4d3da1a71b204d4b8345fc.1463606963.git.d-gerlach@ti.com>

Create a system control module node for the control module portion that
resides under l4_wkup.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/boot/dts/dra7.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 3a8f3976f6f9..406f6ff21d7f 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -233,6 +233,11 @@
 				prm_clockdomains: clockdomains {
 				};
 			};
+
+			scm_wkup: scm_conf at c000 {
+				compatible = "syscon";
+				reg = <0xc000 0x1000>;
+			};
 		};
 
 		axi at 0 {
-- 
2.7.3



From d-gerlach at ti.com  Wed May 18 16:36:26 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 18:36:26 -0500
Subject: [PATCH 1/8] ARM: dts: am335x: Update MPU regulator range for TI boards
In-Reply-To: <cover.1463606963.git.d-gerlach@ti.com>
References: <cover.1463606963.git.d-gerlach@ti.com>
Message-ID: <8df50393ed0b2caf3f29408ad378ea16d94464db.1463606963.git.d-gerlach@ti.com>

Now that we are moving to OPPv2 bindings and able to add 1GHz OPP for
MPU, let's update the max MPU voltage range to align with the maximum
possible value allowed in the operating-points table, which is max
target voltage of 132500 uV + 2%.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/boot/dts/am335x-bone-common.dtsi | 2 +-
 arch/arm/boot/dts/am335x-evm.dts          | 2 +-
 arch/arm/boot/dts/am335x-evmsk.dts        | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
index 0cc150b87b86..13133f3587b8 100644
--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
@@ -318,7 +318,7 @@
 			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
 			regulator-name = "vdd_mpu";
 			regulator-min-microvolt = <925000>;
-			regulator-max-microvolt = <1325000>;
+			regulator-max-microvolt = <1351500>;
 			regulator-boot-on;
 			regulator-always-on;
 		};
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index 516673bb023d..5d28712ad253 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -640,7 +640,7 @@
 			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
 			regulator-name = "vdd_mpu";
 			regulator-min-microvolt = <912500>;
-			regulator-max-microvolt = <1312500>;
+			regulator-max-microvolt = <1351500>;
 			regulator-boot-on;
 			regulator-always-on;
 		};
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
index 282fe1b37095..09308d66645b 100644
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -560,7 +560,7 @@
 			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
 			regulator-name = "vdd_mpu";
 			regulator-min-microvolt = <912500>;
-			regulator-max-microvolt = <1312500>;
+			regulator-max-microvolt = <1351500>;
 			regulator-boot-on;
 			regulator-always-on;
 		};
-- 
2.7.3



From d-gerlach at ti.com  Wed May 18 16:36:32 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 18:36:32 -0500
Subject: [PATCH 7/8] ARM: dts: dra7: Move cpus node to parent dts for dra74x
 and dra72x
In-Reply-To: <cover.1463606963.git.d-gerlach@ti.com>
References: <cover.1463606963.git.d-gerlach@ti.com>
Message-ID: <282afe5e02c165dfd6d5de7d7480a8854cfe16a8.1463606963.git.d-gerlach@ti.com>

Nearly all of the information in the cpus node, especially for cpu0, is
the same between dra74x and dra72x so move the common information to
the parent dra7.dtsi to avoid duplication of data.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/boot/dts/dra7.dtsi   | 27 +++++++++++++++++++++++++++
 arch/arm/boot/dts/dra72x.dtsi | 16 ----------------
 arch/arm/boot/dts/dra74x.dtsi | 24 ------------------------
 3 files changed, 27 insertions(+), 40 deletions(-)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 406f6ff21d7f..104b62657163 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -73,6 +73,33 @@
 		interrupt-parent = <&gic>;
 	};
 
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+
+			operating-points = <
+				/* kHz    uV */
+				1000000	1060000
+				1176000	1160000
+				>;
+
+			clocks = <&dpll_mpu_ck>;
+			clock-names = "cpu";
+
+			clock-latency = <300000>; /* From omap-cpufreq driver */
+
+			/* cooling options */
+			cooling-min-level = <0>;
+			cooling-max-level = <2>;
+			#cooling-cells = <2>; /* min followed by max */
+		};
+	};
+
 	/*
 	 * The soc node represents the soc top level view. It is used for IPs
 	 * that are not memory mapped in the MPU view or for the MPU itself.
diff --git a/arch/arm/boot/dts/dra72x.dtsi b/arch/arm/boot/dts/dra72x.dtsi
index 70a217050a4c..67107605fb4c 100644
--- a/arch/arm/boot/dts/dra72x.dtsi
+++ b/arch/arm/boot/dts/dra72x.dtsi
@@ -12,22 +12,6 @@
 / {
 	compatible = "ti,dra722", "ti,dra72", "ti,dra7";
 
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		cpu0: cpu at 0 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a15";
-			reg = <0>;
-
-			/* cooling options */
-			cooling-min-level = <0>;
-			cooling-max-level = <2>;
-			#cooling-cells = <2>; /* min followed by max */
-		};
-	};
-
 	pmu {
 		compatible = "arm,cortex-a15-pmu";
 		interrupt-parent = <&wakeupgen>;
diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/dra74x.dtsi
index 4220eeffc65a..0c31db3a8919 100644
--- a/arch/arm/boot/dts/dra74x.dtsi
+++ b/arch/arm/boot/dts/dra74x.dtsi
@@ -13,30 +13,6 @@
 	compatible = "ti,dra742", "ti,dra74", "ti,dra7";
 
 	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		cpu0: cpu at 0 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a15";
-			reg = <0>;
-
-			operating-points = <
-				/* kHz    uV */
-				1000000	1060000
-				1176000	1160000
-				>;
-
-			clocks = <&dpll_mpu_ck>;
-			clock-names = "cpu";
-
-			clock-latency = <300000>; /* From omap-cpufreq driver */
-
-			/* cooling options */
-			cooling-min-level = <0>;
-			cooling-max-level = <2>;
-			#cooling-cells = <2>; /* min followed by max */
-		};
 		cpu at 1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
-- 
2.7.3



From d-gerlach at ti.com  Wed May 18 16:36:30 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 18:36:30 -0500
Subject: [PATCH 5/8] ARM: dts: am437x-gp-evm: Hook dcdc2 as the cpu0-supply
In-Reply-To: <cover.1463606963.git.d-gerlach@ti.com>
References: <cover.1463606963.git.d-gerlach@ti.com>
Message-ID: <da3d9998f2e71a213e50364fd20b3c94d3403ccd.1463606963.git.d-gerlach@ti.com>

Hook dcdc2 as the cpu0-supply.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/boot/dts/am437x-gp-evm.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts
index 5bcd3aa025bc..84832bf26b39 100644
--- a/arch/arm/boot/dts/am437x-gp-evm.dts
+++ b/arch/arm/boot/dts/am437x-gp-evm.dts
@@ -975,3 +975,7 @@
 	clock-names = "ext-clk", "int-clk";
 	status = "okay";
 };
+
+&cpu {
+	cpu0-supply = <&dcdc2>;
+};
-- 
2.7.3



From d-gerlach at ti.com  Wed May 18 16:36:25 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 18:36:25 -0500
Subject: [PATCH 0/8] ARM: dts: Add operating-points-v2 tables for TI platforms
Message-ID: <cover.1463606963.git.d-gerlach@ti.com>

Hi,
This series adds operating-points-v2 tables for am335x, am437x, dra7xx,
and am57xx based platforms along with some support patches so that we
can enable more OPPs for the CPU on these platforms.

These patches rely on the ti-cpufreq series sent here [1] and provide
opp-supported-hw data for each OPP so that only the appropriate OPPs
for a specific piece of silicon get enabled.

Regards,
Dave

[1] https://www.mail-archive.com/linux-kernel at vger.kernel.org/msg1147940.html

Dave Gerlach (8):
  ARM: dts: am335x: Update MPU regulator range for TI boards
  ARM: dts: am33xx: Move to operating-points-v2 table and ti-cpufreq
    driver
  ARM: dts: am335x-boneblack: Enable 1GHz OPP for cpu
  ARM: dts: am4372: Add operating-points-v2 table
  ARM: dts: am437x-gp-evm: Hook dcdc2 as the cpu0-supply
  ARM: dts: dra7: Add dt node for the syscon control module wkup
  ARM: dts: dra7: Move cpus node to parent dts for dra74x and dra72x
  ARM: dts: dra7: Move to operating-points-v2 table

 arch/arm/boot/dts/am335x-bone-common.dtsi |  2 +-
 arch/arm/boot/dts/am335x-boneblack.dts    | 11 ++++
 arch/arm/boot/dts/am335x-evm.dts          |  2 +-
 arch/arm/boot/dts/am335x-evmsk.dts        |  2 +-
 arch/arm/boot/dts/am33xx.dtsi             | 88 ++++++++++++++++++++++++++-----
 arch/arm/boot/dts/am4372.dtsi             | 39 ++++++++++++++
 arch/arm/boot/dts/am437x-gp-evm.dts       |  4 ++
 arch/arm/boot/dts/dra7.dtsi               | 48 +++++++++++++++++
 arch/arm/boot/dts/dra72x.dtsi             | 16 ------
 arch/arm/boot/dts/dra74x.dtsi             | 25 +--------
 10 files changed, 181 insertions(+), 56 deletions(-)

-- 
2.7.3



From d-gerlach at ti.com  Wed May 18 16:36:27 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 18:36:27 -0500
Subject: [PATCH 2/8] ARM: dts: am33xx: Move to operating-points-v2 table and
 ti-cpufreq driver
In-Reply-To: <cover.1463606963.git.d-gerlach@ti.com>
References: <cover.1463606963.git.d-gerlach@ti.com>
Message-ID: <f30e0313514cdbb9c3b0a83bbb96f05f2e179775.1463606963.git.d-gerlach@ti.com>

Drop the operating-points table present in am33xx.dtsi and add an
operating-points-v2 table with all OPPs available for all silicon
revisions along with necessary data for use by ti-cpufreq to selectively
enable the appropriate OPPs at runtime. Also, drop the voltage-tolerance
value and provide voltages for each OPP using the <target min max>
format instead.

Information from AM335x Data Manual, SPRS717i, Revised December 2015,
Table 5-7.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/boot/dts/am33xx.dtsi | 88 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 75 insertions(+), 13 deletions(-)

diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 52be48bbd2dd..df1106f89ff2 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -45,19 +45,9 @@
 			device_type = "cpu";
 			reg = <0>;
 
-			/*
-			 * To consider voltage drop between PMIC and SoC,
-			 * tolerance value is reduced to 2% from 4% and
-			 * voltage value is increased as a precaution.
-			 */
-			operating-points = <
-				/* kHz    uV */
-				720000  1285000
-				600000  1225000
-				500000  1125000
-				275000  1125000
-			>;
-			voltage-tolerance = <2>; /* 2 percentage */
+			operating-points-v2 = <&cpu0_opp_table>;
+			ti,syscon-efuse = <&scm_conf 0x7fc 0x1fff 0>;
+			ti,syscon-rev = <&scm_conf 0x600>;
 
 			clocks = <&dpll_mpu_ck>;
 			clock-names = "cpu";
@@ -66,6 +56,78 @@
 		};
 	};
 
+	cpu0_opp_table: opp_table0 {
+		compatible = "operating-points-v2";
+
+		/*
+		 * The three following nodes are marked with opp-suspend
+		 * because the can not be enabled simultaneously on a
+		 * single SoC.
+		 */
+		opp50 at 300000000 {
+			opp-hz = /bits/ 64 <300000000>;
+			opp-microvolt = <950000 931000 969000>;
+			opp-supported-hw = <0x06 0x0010>;
+			opp-suspend;
+		};
+
+		opp100 at 275000000 {
+			opp-hz = /bits/ 64 <275000000>;
+			opp-microvolt = <1100000 1078000 1122000>;
+			opp-supported-hw = <0x01 0x00FF>;
+			opp-suspend;
+		};
+
+		opp100 at 300000000 {
+			opp-hz = /bits/ 64 <300000000>;
+			opp-microvolt = <1100000 1078000 1122000>;
+			opp-supported-hw = <0x06 0x0020>;
+			opp-suspend;
+		};
+
+		opp100 at 500000000 {
+			opp-hz = /bits/ 64 <500000000>;
+			opp-microvolt = <1100000 1078000 1122000>;
+			opp-supported-hw = <0x01 0xFFFF>;
+		};
+
+		opp100 at 600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <1100000 1078000 1122000>;
+			opp-supported-hw = <0x06 0x0040>;
+		};
+
+		opp120 at 600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <1200000 1176000 1224000>;
+			opp-supported-hw = <0x01 0xFFFF>;
+		};
+
+		opp120 at 720000000 {
+			opp-hz = /bits/ 64 <720000000>;
+			opp-microvolt = <1200000 1176000 1224000>;
+			opp-supported-hw = <0x06 0x0080>;
+		};
+
+		oppturbo at 720000000 {
+			opp-hz = /bits/ 64 <720000000>;
+			opp-microvolt = <1260000 1234800 1285200>;
+			opp-supported-hw = <0x01 0xFFFF>;
+		};
+
+		oppturbo at 800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-microvolt = <1260000 1234800 1285200>;
+			opp-supported-hw = <0x06 0x0100>;
+		};
+
+		oppnitro at 1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-microvolt = <1325000 1298500 1351500>;
+			opp-supported-hw = <0x04 0x0200>;
+		};
+	};
+
 	pmu {
 		compatible = "arm,cortex-a8-pmu";
 		interrupts = <3>;
-- 
2.7.3



From d-gerlach at ti.com  Wed May 18 16:36:29 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 18:36:29 -0500
Subject: [PATCH 4/8] ARM: dts: am4372: Add operating-points-v2 table
In-Reply-To: <cover.1463606963.git.d-gerlach@ti.com>
References: <cover.1463606963.git.d-gerlach@ti.com>
Message-ID: <ac373ad0594ce79516614d52fef59b76fbea4563.1463606963.git.d-gerlach@ti.com>

Add an operating-points-v2 table with all OPPs available for all silicon
revisions along with necessary data for use by ti-cpufreq to selectively
enable the appropriate OPPs at runtime.

Information from AM437x Data Manual, SPRS851B, Revised April 2015,
Table 5-2.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/boot/dts/am4372.dtsi | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index 12fcde4d4d2e..8bf2db276128 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -44,10 +44,49 @@
 			clocks = <&dpll_mpu_ck>;
 			clock-names = "cpu";
 
+			operating-points-v2 = <&cpu0_opp_table>;
+			ti,syscon-efuse = <&scm_conf 0x610 0x3f 0>;
+			ti,syscon-rev = <&scm_conf 0x600>;
+
 			clock-latency = <300000>; /* From omap-cpufreq driver */
 		};
 	};
 
+	cpu0_opp_table: opp_table0 {
+		compatible = "operating-points-v2";
+
+		opp50 at 300000000 {
+			opp-hz = /bits/ 64 <300000000>;
+			opp-microvolt = <950000 931000 969000>;
+			opp-supported-hw = <0xFF 0x01>;
+			opp-suspend;
+		};
+
+		opp100 at 600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <1100000 1078000 1122000>;
+			opp-supported-hw = <0xFF 0x04>;
+		};
+
+		opp120 at 720000000 {
+			opp-hz = /bits/ 64 <720000000>;
+			opp-microvolt = <1200000 1176000 1224000>;
+			opp-supported-hw = <0xFF 0x08>;
+		};
+
+		oppturbo at 800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-microvolt = <1260000 1234800 1285200>;
+			opp-supported-hw = <0xFF 0x10>;
+		};
+
+		oppnitro at 1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-microvolt = <1325000 1298500 1351500>;
+			opp-supported-hw = <0xFF 0x20>;
+		};
+	};
+
 	gic: interrupt-controller at 48241000 {
 		compatible = "arm,cortex-a9-gic";
 		interrupt-controller;
-- 
2.7.3



From d-gerlach at ti.com  Wed May 18 16:36:28 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 18:36:28 -0500
Subject: [PATCH 3/8] ARM: dts: am335x-boneblack: Enable 1GHz OPP for cpu
In-Reply-To: <cover.1463606963.git.d-gerlach@ti.com>
References: <cover.1463606963.git.d-gerlach@ti.com>
Message-ID: <f093008d2e4c0754c1790a606b3568b892d054ee.1463606963.git.d-gerlach@ti.com>

Although all PG2.0 silicon may not support 1GHz OPP for the MPU, older
Beaglebone Blacks may have PG2.0 silicon populated and these particular
parts are guaranteed to support the OPP, so enable it for PG2.0 on
am335x-boneblack only.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/boot/dts/am335x-boneblack.dts | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
index 55c0e954b146..ca721670bd91 100644
--- a/arch/arm/boot/dts/am335x-boneblack.dts
+++ b/arch/arm/boot/dts/am335x-boneblack.dts
@@ -33,6 +33,17 @@
 	status = "okay";
 };
 
+&cpu0_opp_table {
+	/*
+	 * All PG 2.0 silicon may not support 1GHz but some of the early
+	 * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+	 * to support 1GHz OPP so enable it for PG 2.0 on this board.
+	 */
+	oppnitro at 1000000000 {
+		opp-supported-hw = <0x06 0x0100>;
+	};
+};
+
 &am33xx_pinmux {
 	nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
 		pinctrl-single,pins = <
-- 
2.7.3



From d-gerlach at ti.com  Wed May 18 16:36:33 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 18 May 2016 18:36:33 -0500
Subject: [PATCH 8/8] ARM: dts: dra7: Move to operating-points-v2 table
In-Reply-To: <cover.1463606963.git.d-gerlach@ti.com>
References: <cover.1463606963.git.d-gerlach@ti.com>
Message-ID: <20af92f75bf0f707458dd021719cce3a70d768d5.1463606963.git.d-gerlach@ti.com>

Add an operating-points-v2 table with all OPPs available for all silicon
revisions along with necessary data for use by ti-opp driver to selectively
enable the appropriate OPPs at runtime and handle voltage transitions

As we now need to define voltage ranges for each OPP, we define the
minimum and maximum voltage to match the ranges possible for AVS class0
voltage as defined by the DRA7/AM57 Data Manual, with the exception of
using a range for OPP_OD based on historical data to ensure that SoCs
from older lots still continue to boot, even though more optimal voltages
are now the standard. Once an AVS Class0 driver is in place it will be
possible for these OPP voltages to be adjusted to any voltage within the
provided range.

Information from SPRS953, Revised December 2015.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
 arch/arm/boot/dts/dra7.dtsi   | 26 +++++++++++++++++++++-----
 arch/arm/boot/dts/dra74x.dtsi |  1 +
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 104b62657163..0d74f8a15937 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -82,11 +82,9 @@
 			compatible = "arm,cortex-a15";
 			reg = <0>;
 
-			operating-points = <
-				/* kHz    uV */
-				1000000	1060000
-				1176000	1160000
-				>;
+			operating-points-v2 = <&cpu0_opp_table>;
+			ti,syscon-efuse = <&scm_wkup 0x20c 0xf80000 19>;
+			ti,syscon-rev = <&scm_wkup 0x204>;
 
 			clocks = <&dpll_mpu_ck>;
 			clock-names = "cpu";
@@ -100,6 +98,24 @@
 		};
 	};
 
+	cpu0_opp_table: opp_table0 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp_nom at 1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-microvolt = <1060000 850000 1150000>;
+			opp-supported-hw = <0xFF 0x01>;
+			opp-suspend;
+		};
+
+		opp_od at 1176000000 {
+			opp-hz = /bits/ 64 <1176000000>;
+			opp-microvolt = <1160000 885000 1160000>;
+			opp-supported-hw = <0xFF 0x02>;
+		};
+	};
+
 	/*
 	 * The soc node represents the soc top level view. It is used for IPs
 	 * that are not memory mapped in the MPU view or for the MPU itself.
diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/dra74x.dtsi
index 0c31db3a8919..0a8a5eee5dd0 100644
--- a/arch/arm/boot/dts/dra74x.dtsi
+++ b/arch/arm/boot/dts/dra74x.dtsi
@@ -17,6 +17,7 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <1>;
+			operating-points-v2 = <&cpu0_opp_table>;
 		};
 	};
 
-- 
2.7.3



From chanho.min at lge.com  Wed May 18 17:08:08 2016
From: chanho.min at lge.com (Chanho Min)
Date: Thu, 19 May 2016 09:08:08 +0900
Subject: [RESEND PATCH] arm64: defconfig: Enable Cadence MACB/GEM support
Message-ID: <1463616488-5168-1-git-send-email-chanho.min@lge.com>

This patch enables the cadence MACB/GEM support that is needed
by lg1312 SoC.

Signed-off-by: Chanho Min <chanho.min at lge.com>
---
 arch/arm64/configs/defconfig |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 14dbe27..ed11cb6 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -105,6 +105,7 @@ CONFIG_TUN=y
 CONFIG_VIRTIO_NET=y
 CONFIG_AMD_XGBE=y
 CONFIG_NET_XGENE=y
+CONFIG_MACB=y
 CONFIG_E1000E=y
 CONFIG_IGB=y
 CONFIG_IGBVF=y
-- 
1.7.9.5



From wangkefeng.wang at huawei.com  Wed May 18 18:45:33 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 19 May 2016 09:45:33 +0800
Subject: [PATCH] serial: 8250_early: Add earlycon support for Synopsys
 DesignWare ABP UART
In-Reply-To: <1462946761-11982-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1462946761-11982-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <573D1ABD.5020908@huawei.com>

+Cc Jon and arm-kernel mailist

Any comments, thanks.

Kefeng

On 2016/5/11 14:06, Kefeng Wang wrote:
> Some board like Hisilicon D02 uses Synopsys DesignWare ABP UART, declare an
> OF early console for it, so early console device can be enabled with comand
> line "earlycon"(without option) via the "stdout-path" property in device-tree.
> 
> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> ---
>  drivers/tty/serial/8250/8250_early.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
> index 8d08ff5..85a12f0 100644
> --- a/drivers/tty/serial/8250/8250_early.c
> +++ b/drivers/tty/serial/8250/8250_early.c
> @@ -150,6 +150,7 @@ EARLYCON_DECLARE(uart, early_serial8250_setup);
>  OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup);
>  OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup);
>  OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup);
> +OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup);
>  
>  #ifdef CONFIG_SERIAL_8250_OMAP
>  
> 



From shijie.huang at arm.com  Wed May 18 18:52:24 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Thu, 19 May 2016 09:52:24 +0800
Subject: [PATCH v12 07/10] arm64: kprobes instruction simulation support
In-Reply-To: <1461783185-9056-8-git-send-email-dave.long@linaro.org>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-8-git-send-email-dave.long@linaro.org>
Message-ID: <20160519015222.GA25870@sha-win-210.asiapac.arm.com>

On Wed, Apr 27, 2016 at 02:53:02PM -0400, David Long wrote:
> From: Sandeepa Prabhu <sandeepa.s.prabhu at gmail.com>
> 
> Kprobes needs simulation of instructions that cannot be stepped
> from a different memory location, e.g.: those instructions
> that uses PC-relative addressing. In simulation, the behaviour
> of the instruction is implemented using a copy of pt_regs.
> 
> The following instruction categories are simulated:
>  - All branching instructions(conditional, register, and immediate)
>  - Literal access instructions(load-literal, adr/adrp)
> 
> Conditional execution is limited to branching instructions in
> ARM v8. If conditions at PSTATE do not match the condition fields
> of opcode, the instruction is effectively NOP.
> 
> Thanks to Will Cohen for assorted suggested changes.
> 
> Signed-off-by: Sandeepa Prabhu <sandeepa.s.prabhu at gmail.com>
> Signed-off-by: William Cohen <wcohen at redhat.com>
> Signed-off-by: David A. Long <dave.long at linaro.org>
> ---
>  arch/arm64/include/asm/insn.h            |   1 +
>  arch/arm64/include/asm/probes.h          |   5 +-
>  arch/arm64/kernel/Makefile               |   3 +-
>  arch/arm64/kernel/insn.c                 |   1 +
>  arch/arm64/kernel/kprobes-arm64.c        |  29 ++++
>  arch/arm64/kernel/kprobes.c              |  32 ++++-
>  arch/arm64/kernel/probes-simulate-insn.c | 218 +++++++++++++++++++++++++++++++
>  arch/arm64/kernel/probes-simulate-insn.h |  28 ++++
>  8 files changed, 311 insertions(+), 6 deletions(-)
>  create mode 100644 arch/arm64/kernel/probes-simulate-insn.c
>  create mode 100644 arch/arm64/kernel/probes-simulate-insn.h
> 
> diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
> index b9567a1..26cee10 100644
> --- a/arch/arm64/include/asm/insn.h
> +++ b/arch/arm64/include/asm/insn.h
> @@ -410,6 +410,7 @@ u32 aarch32_insn_mcr_extract_crm(u32 insn);
>  
>  typedef bool (pstate_check_t)(unsigned long);
>  extern pstate_check_t * const opcode_condition_checks[16];
> +
>  #endif /* __ASSEMBLY__ */
>  
>  #endif	/* __ASM_INSN_H */
> diff --git a/arch/arm64/include/asm/probes.h b/arch/arm64/include/asm/probes.h
> index c5fcbe6..d524f7d 100644
> --- a/arch/arm64/include/asm/probes.h
> +++ b/arch/arm64/include/asm/probes.h
> @@ -15,11 +15,12 @@
>  #ifndef _ARM_PROBES_H
>  #define _ARM_PROBES_H
>  
> +#include <asm/opcodes.h>
> +
>  struct kprobe;
>  struct arch_specific_insn;
>  
>  typedef u32 kprobe_opcode_t;
> -typedef unsigned long (kprobes_pstate_check_t)(unsigned long);
>  typedef void (kprobes_handler_t) (u32 opcode, long addr, struct pt_regs *);
>  
>  enum pc_restore_type {
> @@ -35,7 +36,7 @@ struct kprobe_pc_restore {
>  /* architecture specific copy of original instruction */
>  struct arch_specific_insn {
>  	kprobe_opcode_t *insn;
> -	kprobes_pstate_check_t *pstate_cc;
> +	pstate_check_t *pstate_cc;
>  	kprobes_handler_t *handler;
>  	/* restore address after step xol */
>  	struct kprobe_pc_restore restore;
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 8816de2..43bf6cc 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -37,7 +37,8 @@ arm64-obj-$(CONFIG_CPU_PM)		+= sleep.o suspend.o
>  arm64-obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
>  arm64-obj-$(CONFIG_JUMP_LABEL)		+= jump_label.o
>  arm64-obj-$(CONFIG_KGDB)		+= kgdb.o
> -arm64-obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-arm64.o
> +arm64-obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-arm64.o		\
> +					   probes-simulate-insn.o
>  arm64-obj-$(CONFIG_EFI)			+= efi.o efi-entry.stub.o
>  arm64-obj-$(CONFIG_PCI)			+= pci.o
>  arm64-obj-$(CONFIG_ARMV8_DEPRECATED)	+= armv8_deprecated.o
> diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
> index f79e72e..bb2738c 100644
> --- a/arch/arm64/kernel/insn.c
> +++ b/arch/arm64/kernel/insn.c
> @@ -30,6 +30,7 @@
>  #include <asm/cacheflush.h>
>  #include <asm/debug-monitors.h>
>  #include <asm/fixmap.h>
> +#include <asm/opcodes.h>
>  #include <asm/insn.h>
>  
>  #define AARCH64_INSN_SF_BIT	BIT(31)
> diff --git a/arch/arm64/kernel/kprobes-arm64.c b/arch/arm64/kernel/kprobes-arm64.c
> index e07727a..487238a 100644
> --- a/arch/arm64/kernel/kprobes-arm64.c
> +++ b/arch/arm64/kernel/kprobes-arm64.c
> @@ -21,6 +21,7 @@
>  #include <asm/sections.h>
>  
>  #include "kprobes-arm64.h"
> +#include "probes-simulate-insn.h"
>  
>  static bool __kprobes aarch64_insn_is_steppable(u32 insn)
>  {
> @@ -62,8 +63,36 @@ arm_probe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
>  	 */
>  	if (aarch64_insn_is_steppable(insn))
>  		return INSN_GOOD;
> +
> +	if (aarch64_insn_is_bcond(insn)) {
> +		asi->handler = simulate_b_cond;
> +	} else if (aarch64_insn_is_cbz(insn) ||
> +	    aarch64_insn_is_cbnz(insn)) {
> +		asi->handler = simulate_cbz_cbnz;
> +	} else if (aarch64_insn_is_tbz(insn) ||
> +	    aarch64_insn_is_tbnz(insn)) {
> +		asi->handler = simulate_tbz_tbnz;
> +	} else if (aarch64_insn_is_adr_adrp(insn))
> +		asi->handler = simulate_adr_adrp;
> +	else if (aarch64_insn_is_b(insn) ||
> +	    aarch64_insn_is_bl(insn))
> +		asi->handler = simulate_b_bl;

For the same codingstyle, we'd better add more "{}" here and below.

thanks
Huang Shijie

> +	else if (aarch64_insn_is_br(insn) ||
> +	    aarch64_insn_is_blr(insn) ||
> +	    aarch64_insn_is_ret(insn))
> +		asi->handler = simulate_br_blr_ret;
> +	else if (aarch64_insn_is_ldr_lit(insn))
> +		asi->handler = simulate_ldr_literal;
> +	else if (aarch64_insn_is_ldrsw_lit(insn))
> +		asi->handler = simulate_ldrsw_literal;
>  	else
> +		/*
> +		 * Instruction cannot be stepped out-of-line and we don't
> +		 * (yet) simulate it.
> +		 */
>  		return INSN_REJECTED;
> +
> +	return INSN_GOOD_NO_SLOT;
>  }



From saberlily.xia at hisilicon.com  Wed May 18 19:44:33 2016
From: saberlily.xia at hisilicon.com (x00195127)
Date: Thu, 19 May 2016 10:44:33 +0800
Subject: [PATCH] arm64: cpuinfo: add AArch64 & elf platform for app
 compatibility
Message-ID: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>

we find that some apps will read cpuinfo when start up,
they need the string  as follows:
"Processor       : AArch64 Processor rev 0 (aarch64)"

Then thay could load the corresponding libs. But now
arm64 platform's cpuinfo don't has this now, so
we need add this.

Signed-off-by: Qing Xia <saberlily.xia at hisilicon.com>
---
 arch/arm64/kernel/cpuinfo.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 3808470..c3527ad 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -114,6 +114,9 @@ static int c_show(struct seq_file *m, void *v)
 		 * online processors, looking for lines beginning with
 		 * "processor".  Give glibc what it expects.
 		 */
+		seq_printf(m, "Processor\t: AArch64 Processor rev %d (%s)\n",
+				read_cpuid_id() & 15, ELF_PLATFORM);
+
 		seq_printf(m, "processor\t: %d\n", i);
 
 		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
-- 
1.8.3.2



From viresh.kumar at linaro.org  Wed May 18 20:15:59 2016
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Thu, 19 May 2016 08:45:59 +0530
Subject: [PATCH 1/2] Documentation: dt: add bindings for ti-cpufreq
In-Reply-To: <f17fbc8acb1e903b9f175f49fe29563b83132faf.1463609497.git.d-gerlach@ti.com>
References: <cover.1463609497.git.d-gerlach@ti.com>
 <f17fbc8acb1e903b9f175f49fe29563b83132faf.1463609497.git.d-gerlach@ti.com>
Message-ID: <20160519031559.GK24777@vireshk-i7>

On 18-05-16, 18:30, Dave Gerlach wrote:
> Add the device tree bindings document for the TI CPUFreq/OPP driver
> on AM33xx and AM43xx SoCs. The operating-points-v2 binding allows us
> to provide an opp-supported-hw property for each OPP to define when
> it is available. This driver is responsible for reading and parsing
> registers to determine which OPPs can be selectively enabled based
> on the specific SoC in use by matching against the opp-supported-hw
> data.

Here and ...

> Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
> ---
>  .../devicetree/bindings/cpufreq/ti-cpufreq.txt     | 89 ++++++++++++++++++++++
>  1 file changed, 89 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt
> 
> diff --git a/Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt
> new file mode 100644
> index 000000000000..f719b2df2a1f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt
> @@ -0,0 +1,89 @@
> +Bindings for TI's CPUFreq driver
> +================================
> +
> +The ti-cpufreq driver works with the operating-points-v2 binding described
> +at [../opp/opp.txt] to make sure the proper OPPs for a platform get enabled
> +and then creates a "cpufreq-dt" platform device to leverage the cpufreq-dt
> +driver described in [cpufreq-dt.txt].
> +
> +Certain TI SoCs, like those in the am335x, am437x, am57xx, and dra7xx
> +families support different OPPs depending on the silicon variant in use.
> +The ti-cpufreq driver uses the revision and an efuse value from the SoC to
> +provide the OPP framework with supported hardware information. This is used
> +to determine which OPPs from the operating-points-v2 table get enabled. In
> +order to maintain backwards compatilibity if this information is not present
> +the "cpufreq-dt" platform device is still created to attempt to find an
> +operating-points (v1) table, otherwise no OPPs will be available because
> +safe OPPs cannot be determined.

... here..

We shouldn't be talking about the drivers are going to use it, etc.
This is a binding document, which should be independent of Linux
kernel. It can be used by other Operating systems as well and so the
implementation details should be just dropped.

> +
> +Required properties:
> +--------------------
> +In 'cpus' nodes:
> +- operating-points-v2: Phandle to the operating-points-v2 table to use
> +- ti,syscon-efuse: Syscon phandle, offset to efuse register, efuse register
> +		   mask, and efuse register shift to get the relevant bits
> +		   that describe OPP availability
> +- ti,syscon-rev: Syscon and offset used to look up revision value on SoC

These are proper sentences and so maybe a full-stop (.) at the end of
each line ?

> +
> +In 'operating-points-v2' table:
> +- opp-supported-hw: Two bitfields indicating:
> +	1. Which revision of the SoC the OPP is supported by
> +	2. Which eFuse bits indicate this OPP is available
> +
> +	A bitwise and is performed against these values and if any bit

                  AND or &

> +	matches, the OPP gets enabled.
> +
> +NOTE: Without the above, platform-device for "cpufreq-dt" is still created
> +      but no determination of which OPPs should be available is done, but this
> +      allows for use of a v1 operating-points table.

Again, these are implementation details.. should be dropped.

> +
> +Example:
> +--------
> +
> +/* From arch/arm/boot/dts/am4372.dtsi */
> +cpus {
> +	cpu: cpu at 0 {
> +		...
> +
> +		operating-points-v2 = <&cpu0_opp_table>;
> +
> +		ti,syscon-efuse = <&scm_conf 0x610 0x3f 0>;
> +		ti,syscon-rev = <&scm_conf 0x600>;

@Rob: Can we add properties to the CPU node just like that ?

> +
> +		...
> +	};
> +};
> +
> +cpu0_opp_table: opp_table0 {
> +	compatible = "operating-points-v2";

Otherwise, you could have added above properties right here and added
your own compatible string..

> +	opp50 at 300000000 {
> +		opp-hz = /bits/ 64 <300000000>;
> +		opp-microvolt = <950000>;
> +		opp-supported-hw = <0xFF 0x01>;
> +		opp-suspend;
> +	};
> +
> +	opp100 at 600000000 {
> +		opp-hz = /bits/ 64 <600000000>;
> +		opp-microvolt = <1100000>;
> +		opp-supported-hw = <0xFF 0x04>;
> +	};
> +
> +	opp120 at 720000000 {
> +		opp-hz = /bits/ 64 <720000000>;
> +		opp-microvolt = <1200000>;
> +		opp-supported-hw = <0xFF 0x08>;
> +	};
> +
> +	oppturbo at 800000000 {
> +		opp-hz = /bits/ 64 <800000000>;
> +		opp-microvolt = <1260000>;
> +		opp-supported-hw = <0xFF 0x10>;
> +	};
> +
> +	oppnitro at 1000000000 {
> +		opp-hz = /bits/ 64 <1000000000>;
> +		opp-microvolt = <1325000>;
> +		opp-supported-hw = <0xFF 0x20>;

so the first one is always FF ? Why have it then ?

> +	};
> +};

-- 
viresh


From horms+renesas at verge.net.au  Wed May 18 20:50:42 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Thu, 19 May 2016 12:50:42 +0900
Subject: [PATCH/RFC 0/3] arm64: Add Renesas R8A7796 SoC support
Message-ID: <1463629845-7115-1-git-send-email-horms+renesas@verge.net.au>

Hi,

this short series aims to add basic support for the
Gen 3 R-Car M3-W (r8a7796) SoC.

It has few bells and whistles but is sufficient to bring up
an r8a7795/salvator-x. I have provided a boot-log at the bottom
of this email in case it is of interest.


Dependency:

"[PATCH 0/4] clk: renesas: cpg-mssr: Add support for R-Car M3-W"


Availability:

In order to aid review this series, its dependency (above)
and the related patch "serial: sh-sci: Document SoC specific bindings for
r8a7796", which has been posted separately, are available at:

git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git topic/r8a7796

To be entirely clear, I have _not_ queued up this series for mainline.
I anticipate some revisions will be made following review before that
happens.


Simon Horman (1):
  arm64: dts: r8a7796: Add Renesas R8A7796 SoC support

Takeshi Kihara (2):
  arm64: dts: salvator-x: add Salvator-X board on R8A7796 SoC
  arm64: defconfig: enable Renesas R8A7796 SoC

 Documentation/devicetree/bindings/arm/shmobile.txt |   4 +
 arch/arm64/Kconfig.platforms                       |   6 ++
 arch/arm64/boot/dts/renesas/Makefile               |   1 +
 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts |  45 ++++++++
 arch/arm64/boot/dts/renesas/r8a7796.dtsi           | 120 +++++++++++++++++++++
 arch/arm64/configs/defconfig                       |   1 +
 6 files changed, 177 insertions(+)
 create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
 create mode 100644 arch/arm64/boot/dts/renesas/r8a7796.dtsi

-- 
2.1.4


Boot Log:

The following boot log was generated by booting this patch set,
in its form in the topic/r8a7796 branch. It was compiled using
the ARM64 defconfig with initrd enabled to provide a working userspace.

=> setenv bootargs ignore_loglevel rw root=/dev/nfs ip=dhcp nfsroot=10.3.3.135:/srv/nfs/salvator-x-arm64
=> setenv ethaddr 2e:09:0a:00:83:2b
=> setenv ipaddr 10.3.3.172
=> setenv serverip 10.3.3.135
=> tftpboot 0x48080000 salvator-x/Image;tftpboot 0x48f00000 salvator-x/r8a7796-salvator-x.dtb; booti 0x48080000 - 0x48f00000
ravb Waiting for PHY auto negotiation to complete.. done
ravb: 100Base/Full
Using ravb device
TFTP from server 10.3.3.135; our IP address is 10.3.3.172
Filename 'salvator-x/Image'.
Load address: 0x48080000
Loading: T #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ################################
         58.6 KiB/s
done
Bytes transferred = 12860928 (c43e00 hex)
ravb:0 is connected to ravb.  Reconnecting to ravb
ravb Waiting for PHY auto negotiation to complete.. done
ravb: 100Base/Full
Using ravb device
TFTP from server 10.3.3.135; our IP address is 10.3.3.172
Filename 'salvator-x/r8a7796-salvator-x.dtb'.
Load address: 0x48f00000
Loading: T #
         0 Bytes/s
done
Bytes transferred = 2325 (915 hex)
## Flattened Device Tree blob at 48f00000
   Booting using the fdt blob at 0x48f00000
   Using Device Tree in place at 0000000048f00000, end 0000000048f03914

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.6.0-rc1+ (horms at ayumi.isobedori.kobe.vergenet.net) (gcc version 4.8.5 (Linaro GCC 4.8-2015.06) ) #570 SMP PREEMPT Thu May 19 11:24:58 JST 2016
[    0.000000] Boot CPU: AArch64 Processor [411fd073]
[    0.000000] debug: ignoring loglevel setting.
[    0.000000] efi: Getting EFI parameters from FDT:
[    0.000000] efi: UEFI not found.
[    0.000000] cma: Reserved 16 MiB at 0x00000000bf000000
[    0.000000] On node 0 totalpages: 1015808
[    0.000000]   DMA zone: 7680 pages used for memmap
[    0.000000]   DMA zone: 0 pages reserved
[    0.000000]   DMA zone: 491520 pages, LIFO batch:31
[    0.000000]   Normal zone: 8192 pages used for memmap
[    0.000000]   Normal zone: 524288 pages, LIFO batch:31
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv1.0 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: Trusted OS migration not required
[    0.000000] percpu: Embedded 20 pages/cpu @ffffffc63ffad000 s43008 r8192 d30720 u81920
[    0.000000] pcpu-alloc: s43008 r8192 d30720 u81920 alloc=20*4096
[    0.000000] pcpu-alloc: [0] 0 
[    0.000000] Detected PIPT I-cache on CPU0
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 999936
[    0.000000] Kernel command line: ignore_loglevel rw root=/dev/nfs ip=dhcp nfsroot=10.3.3.135:/srv/nfs/salvator-x-arm64
[    0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes)
[    0.000000] Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes)
[    0.000000] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes)
[    0.000000] software IO TLB [mem 0xbafff000-0xbefff000] (64MB) mapped at [ffffffc07afff000-ffffffc07effefff]
[    0.000000] Memory: 3896020K/4063232K available (6796K kernel code, 619K rwdata, 2880K rodata, 2256K init, 241K bss, 150828K reserved, 16384K cma-reserved)
[    0.000000] Virtual kernel memory layout:
[    0.000000]     modules : 0xffffff8000000000 - 0xffffff8008000000   (   128 MB)
[    0.000000]     vmalloc : 0xffffff8008000000 - 0xffffffbdbfff0000   (   246 GB)
[    0.000000]       .text : 0xffffff8008080000 - 0xffffff8008721000   (  6788 KB)
[    0.000000]     .rodata : 0xffffff8008721000 - 0xffffff80089f5000   (  2896 KB)
[    0.000000]       .init : 0xffffff80089f5000 - 0xffffff8008c29000   (  2256 KB)
[    0.000000]       .data : 0xffffff8008c29000 - 0xffffff8008cc3e00   (   620 KB)
[    0.000000]     vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000   (     8 GB maximum)
[    0.000000]               0xffffffbdc0200000 - 0xffffffbdd9000000   (   398 MB actual)
[    0.000000]     fixed   : 0xffffffbffe7fd000 - 0xffffffbffec00000   (  4108 KB)
[    0.000000]     PCI I/O : 0xffffffbffee00000 - 0xffffffbfffe00000   (    16 MB)
[    0.000000]     memory  : 0xffffffc008000000 - 0xffffffc640000000   ( 25472 MB)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] Preemptible hierarchical RCU implementation.
[    0.000000]  Build-time adjustment of leaf fanout to 64.
[    0.000000]  RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=1.
[    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=64, nr_cpu_ids=1
[    0.000000] NR_IRQS:64 nr_irqs:64 0
[    0.000000] Architected cp15 timer(s) running at 8.33MHz (virt).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1ec02923e, max_idle_ns: 440795202125 ns
[    0.000003] sched_clock: 56 bits at 8MHz, resolution 120ns, wraps every 2199023255496ns
[    0.000075] Console: colour dummy device 80x25
[    0.000378] console [tty0] enabled
[    0.000399] Calibrating delay loop (skipped), value calculated using timer frequency.. 16.66 BogoMIPS (lpj=33333)
[    0.000416] pid_max: default: 32768 minimum: 301
[    0.000459] Security Framework initialized
[    0.000492] Mount-cache hash table entries: 8192 (order: 4, 65536 bytes)
[    0.000503] Mountpoint-cache hash table entries: 8192 (order: 4, 65536 bytes)
[    0.001208] ASID allocator initialised with 65536 entries
[    0.001732] EFI services will not be available.
[    0.001840] Brought up 1 CPUs
[    0.001849] SMP: Total of 1 processors activated.
[    0.001864] CPU: All CPU(s) started at EL1
[    0.002629] devtmpfs: initialized
[    0.003203] DMI not present or invalid.
[    0.003402] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.003780] pinctrl core: initialized pinctrl subsystem
[    0.004565] NET: Registered protocol family 16
[    0.016068] cpuidle: using governor menu
[    0.016220] vdso: 2 pages (1 code @ ffffff8008727000, 1 data @ ffffff8008c30000)
[    0.016257] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[    0.016745] DMA: preallocated 256 KiB pool for atomic allocations
[    0.016903] Serial: AMBA PL011 UART driver
[    0.037020] HugeTLB registered 2 MB page size, pre-allocated 0 pages
[    0.048846] vgaarb: loaded
[    0.049044] SCSI subsystem initialized
[    0.052301] libata version 3.00 loaded.
[    0.052495] usbcore: registered new interface driver usbfs
[    0.052529] usbcore: registered new interface driver hub
[    0.052560] usbcore: registered new device driver usb
[    0.052646] pps_core: LinuxPPS API ver. 1 registered
[    0.052655] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti at linux.it>
[    0.052678] PTP clock support registered
[    0.052755] dmi: Firmware registration failed.
[    0.053044] Advanced Linux Sound Architecture Driver Initialized.
[    0.053994] clocksource: Switched to clocksource arch_sys_counter
[    0.054137] VFS: Disk quotas dquot_6.6.0
[    0.054180] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[    0.064158] NET: Registered protocol family 2
[    0.064557] TCP established hash table entries: 32768 (order: 6, 262144 bytes)
[    0.064673] TCP bind hash table entries: 32768 (order: 7, 524288 bytes)
[    0.065128] TCP: Hash tables configured (established 32768 bind 32768)
[    0.065244] UDP hash table entries: 2048 (order: 4, 65536 bytes)
[    0.065276] UDP-Lite hash table entries: 2048 (order: 4, 65536 bytes)
[    0.065448] NET: Registered protocol family 1
[    0.066169] RPC: Registered named UNIX socket transport module.
[    0.066187] RPC: Registered udp transport module.
[    0.066194] RPC: Registered tcp transport module.
[    0.066201] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.066227] PCI: CLS 0 bytes, default 128
[    0.112786] kvm [1]: HYP mode not available
[    0.114560] futex hash table entries: 256 (order: 3, 32768 bytes)
[    0.114641] audit: initializing netlink subsys (disabled)
[    0.114686] audit: type=2000 audit(0.111:1): initialized
[    0.119404] workingset: timestamp_bits=44 max_order=20 bucket_order=0
[    0.129317] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.130529] NFS: Registering the id_resolver key type
[    0.130574] Key type id_resolver registered
[    0.130583] Key type id_legacy registered
[    0.130788] fuse init (API version 7.24)
[    0.131214] 9p: Installing v9fs 9p2000 file system support
[    0.132914] io scheduler noop registered
[    0.133088] io scheduler cfq registered (default)
[    0.135948] xenfs: not registering filesystem on non-xen platform
[    0.141277] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    0.143126] SuperH (H)SCI(F) driver initialized
[    0.143318] e6e88000.serial: ttySC0 at MMIO 0xe6e88000 (irq = 6, base_baud = 0) is a scif
[    0.812755] console [ttySC0] enabled
[    0.816711] msm_serial: driver initialized
[    0.849025] loop: module loaded
[    0.853721] tun: Universal TUN/TAP device driver, 1.6
[    0.859420] tun: (C) 1999-2004 Max Krasnyansky <maxk at qualcomm.com>
[    0.866040] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[    0.872138] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    0.878152] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.3.0-k
[    0.885185] igb: Copyright (c) 2007-2014 Intel Corporation.
[    0.890826] igbvf: Intel(R) Gigabit Virtual Function Network Driver - version 2.0.2-k
[    0.898690] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
[    0.904680] sky2: driver version 1.30
[    0.908738] VFIO - User Level meta-driver version: 0.3
[    0.916288] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    0.923057] ehci-pci: EHCI PCI platform driver
[    0.927617] ehci-platform: EHCI generic platform driver
[    0.933050] ehci-msm: Qualcomm On-Chip EHCI Host Controller
[    0.938714] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    0.944963] ohci-pci: OHCI PCI platform driver
[    0.949471] ohci-platform: OHCI generic platform driver
[    0.954940] usbcore: registered new interface driver usb-storage
[    0.961749] mousedev: PS/2 mouse device common for all mice
[    0.968060] i2c /dev entries driver
[    0.972511] sdhci: Secure Digital Host Controller Interface driver
[    0.979103] sdhci: Copyright(c) Pierre Ossman
[    0.983598] Synopsys Designware Multimedia Card Interface Driver
[    0.989873] sdhci-pltfm: SDHCI platform and OF driver helper
[    0.995797] ledtrig-cpu: registered to indicate activity on CPUs
[    1.002502] usbcore: registered new interface driver usbhid
[    1.008386] usbhid: USB HID core driver
[    1.013395] NET: Registered protocol family 17
[    1.018342] 9pnet: Installing 9P2000 support
[    1.022755] Key type dns_resolver registered
[    1.027708] registered taskstats version 1
[    1.032247] hctosys: unable to open rtc device (rtc0)
[   13.085552] ALSA device list:
[   13.088531]   No soundcards found.
[   13.093427] Freeing unused kernel memory: 2256K (ffffff80089f5000 - ffffff8008c29000)


boot (Linux 4.6.0-rc1+, BusyBox v1.16.0.git, kexec-tools 2.0.1-git)
/ # cat /proc/interrupts 
           CPU0       
  3:        247     GIC-0  27 Edge      arch_timer
  6:        101     GIC-0 196 Level     e6e88000.serial:mux
IPI0:         0       Rescheduling interrupts
IPI1:         0       Function call interrupts
IPI2:         0       CPU stop interrupts
IPI3:         0       Timer broadcast interrupts
IPI4:         0       IRQ work interrupts
IPI5:         0       CPU wake-up interrupts
Err:          0
/ # 



From horms+renesas at verge.net.au  Wed May 18 20:50:44 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Thu, 19 May 2016 12:50:44 +0900
Subject: [PATCH/RFC 2/3] arm64: dts: salvator-x: add Salvator-X board on
 R8A7796 SoC
In-Reply-To: <1463629845-7115-1-git-send-email-horms+renesas@verge.net.au>
References: <1463629845-7115-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1463629845-7115-3-git-send-email-horms+renesas@verge.net.au>

From: Takeshi Kihara <takeshi.kihara.df at renesas.com>

This patch adds initial board support for R8A7796 Salvator-X.

Signed-off-by: Takeshi Kihara <takeshi.kihara.df at renesas.com>
Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
--
v1 [Simon Horman]
* Drop use of pfc, that can be added once pfc support is present in mainline
* Set size of memory (bank 0) to 2GiB instead of 1GiB
* Omit scif0
* Add scif_clk, from patch by Hiromitsu Yamasaki

v0 [Takeshi Kihara]
---
 arch/arm64/boot/dts/renesas/Makefile               |  1 +
 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts | 45 ++++++++++++++++++++++
 2 files changed, 46 insertions(+)
 create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts

diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
index 9ce1890a650e..17139f7003a6 100644
--- a/arch/arm64/boot/dts/renesas/Makefile
+++ b/arch/arm64/boot/dts/renesas/Makefile
@@ -1,4 +1,5 @@
 dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x.dtb
+dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb
 
 always		:= $(dtb-y)
 clean-files	:= *.dtb
diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
new file mode 100644
index 000000000000..9c52613fb88c
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
@@ -0,0 +1,45 @@
+/*
+ * Device Tree Source for the Salvator-X board
+ *
+ * Copyright (C) 2016 Renesas Electronics Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+#include "r8a7796.dtsi"
+
+/ {
+	model = "Renesas Salvator-X board based on r8a7796";
+	compatible = "renesas,salvator-x", "renesas,r8a7796";
+
+	aliases {
+		serial0 = &scif2;
+	};
+
+	chosen {
+		bootargs = "ignore_loglevel";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory at 48000000 {
+		device_type = "memory";
+		/* first 128MB is reserved for secure area. */
+		reg = <0x0 0x48000000 0x0 0x78000000>;
+	};
+};
+
+&extal_clk {
+	clock-frequency = <16666666>;
+};
+
+&scif2 {
+	status = "okay";
+};
+
+&scif_clk {
+	clock-frequency = <14745600>;
+	status = "okay";
+};
-- 
2.1.4



From horms+renesas at verge.net.au  Wed May 18 20:50:43 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Thu, 19 May 2016 12:50:43 +0900
Subject: [PATCH/RFC 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC support
In-Reply-To: <1463629845-7115-1-git-send-email-horms+renesas@verge.net.au>
References: <1463629845-7115-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1463629845-7115-2-git-send-email-horms+renesas@verge.net.au>

Basic support for the Gen 3 R-Car M3-W SoC.

Based on work for the r8a7795 and r8a7796 SoCs by
Takeshi Kihara, Dirk Behme and Geert Uytterhoeven.

Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
---
 Documentation/devicetree/bindings/arm/shmobile.txt |   4 +
 arch/arm64/Kconfig.platforms                       |   6 ++
 arch/arm64/boot/dts/renesas/r8a7796.dtsi           | 120 +++++++++++++++++++++
 3 files changed, 130 insertions(+)
 create mode 100644 arch/arm64/boot/dts/renesas/r8a7796.dtsi

diff --git a/Documentation/devicetree/bindings/arm/shmobile.txt b/Documentation/devicetree/bindings/arm/shmobile.txt
index 9cf67e48f222..d5ed554830d7 100644
--- a/Documentation/devicetree/bindings/arm/shmobile.txt
+++ b/Documentation/devicetree/bindings/arm/shmobile.txt
@@ -29,6 +29,8 @@ SoCs:
     compatible = "renesas,r8a7794"
   - R-Car H3 (R8A77950)
     compatible = "renesas,r8a7795"
+  - R-Car M3-W (R8A77960)
+    compatible = "renesas,r8a7796"
 
 
 Boards:
@@ -61,5 +63,7 @@ Boards:
     compatible = "renesas,porter", "renesas,r8a7791"
   - Salvator-X (RTP0RC7795SIPB0010S)
     compatible = "renesas,salvator-x", "renesas,r8a7795";
+  - Salvator-X
+    compatible = "renesas,salvator-x", "renesas,r8a7796";
   - SILK (RTP0RC7794LCB00011S)
     compatible = "renesas,silk", "renesas,r8a7794"
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index efa77c146415..16d8d26839ea 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -114,6 +114,12 @@ config ARCH_R8A7795
 	help
 	  This enables support for the Renesas R-Car H3 SoC.
 
+config ARCH_R8A7796
+	bool "Renesas R-Car M3-W SoC Platform"
+	depends on ARCH_RENESAS
+	help
+	  This enables support for the Renesas R-Car M3-W SoC.
+
 config ARCH_STRATIX10
 	bool "Altera's Stratix 10 SoCFPGA Family"
 	help
diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
new file mode 100644
index 000000000000..db4a128adf57
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
@@ -0,0 +1,120 @@
+/*
+ * Device Tree Source for the r8a7796 SoC
+ *
+ * Copyright (C) 2016 Renesas Electronics Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/clock/r8a7796-cpg-mssr.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "renesas,r8a7796";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* 1 core only at this point */
+		a57_0: cpu at 0 {
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x0>;
+			device_type = "cpu";
+			next-level-cache = <&L2_CA57>;
+			enable-method = "psci";
+		};
+	};
+
+	L2_CA57: cache-controller at 0 {
+		compatible = "cache";
+		cache-unified;
+		cache-level = <2>;
+	};
+
+	extal_clk: extal {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	extalr_clk: extalr {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	/* External SCIF clock - to be overridden by boards that provide it */
+	scif_clk: scif {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+		status = "disabled";
+	};
+
+	soc {
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gic: interrupt-controller at 0xf1010000 {
+			compatible = "arm,gic-400";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0x0 0xf1010000 0 0x1000>,
+			      <0x0 0xf1020000 0 0x20000>,
+			      <0x0 0xf1040000 0 0x20000>,
+			      <0x0 0xf1060000 0 0x20000>;
+			interrupts = <GIC_PPI 9
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+		};
+
+		timer {
+			compatible = "arm,armv8-timer";
+			interrupts = <GIC_PPI 13
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 14
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 11
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 10
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
+		};
+
+		cpg: clock-controller at e6150000 {
+			compatible = "renesas,r8a7796-cpg-mssr";
+			reg = <0 0xe6150000 0 0x1000>;
+			clocks = <&extal_clk>, <&extalr_clk>;
+			clock-names = "extal", "extalr";
+			#clock-cells = <2>;
+			#power-domain-cells = <0>;
+		};
+
+		scif2: serial at e6e88000 {
+			compatible = "renesas,scif-r8a7796",
+				     "renesas,rcar-gen3-scif", "renesas,scif";
+			reg = <0 0xe6e88000 0 64>;
+			interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 310>,
+				 <&cpg CPG_CORE R8A7796_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			power-domains = <&cpg>;
+			status = "disabled";
+		};
+	};
+};
-- 
2.1.4



From horms+renesas at verge.net.au  Wed May 18 20:50:45 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Thu, 19 May 2016 12:50:45 +0900
Subject: [PATCH/RFC 3/3] arm64: defconfig: enable Renesas R8A7796 SoC
In-Reply-To: <1463629845-7115-1-git-send-email-horms+renesas@verge.net.au>
References: <1463629845-7115-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1463629845-7115-4-git-send-email-horms+renesas@verge.net.au>

From: Takeshi Kihara <takeshi.kihara.df at renesas.com>

This patch enables the Renesas R8A7796 SoC in the arm64 defconfig.

Signed-off-by: Takeshi Kihara <takeshi.kihara.df at renesas.com>
Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index f70505186820..0d37fa5a59aa 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -44,6 +44,7 @@ CONFIG_ARCH_ROCKCHIP=y
 CONFIG_ARCH_SEATTLE=y
 CONFIG_ARCH_RENESAS=y
 CONFIG_ARCH_R8A7795=y
+CONFIG_ARCH_R8A7796=y
 CONFIG_ARCH_STRATIX10=y
 CONFIG_ARCH_TEGRA=y
 CONFIG_ARCH_SPRD=y
-- 
2.1.4



From viresh.kumar at linaro.org  Wed May 18 21:39:20 2016
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Thu, 19 May 2016 10:09:20 +0530
Subject: [PATCH 2/2] cpufreq: ti: Add cpufreq driver to determine
 available OPPs at runtime
In-Reply-To: <9b8c1ba22e07cbfa25f93b33422fcfd1a8d10655.1463609497.git.d-gerlach@ti.com>
References: <cover.1463609497.git.d-gerlach@ti.com>
 <9b8c1ba22e07cbfa25f93b33422fcfd1a8d10655.1463609497.git.d-gerlach@ti.com>
Message-ID: <20160519043920.GC32001@vireshk-i7>

On 18-05-16, 18:30, Dave Gerlach wrote:
> Some TI SoCs, like those in the AM335x, AM437x, DRA7x, and AM57x families,
> have different OPPs available for the MPU depending on which specific
> variant of the SoC is in use. This can be determined through use of the
> revision and an eFuse register present in the silicon. Introduce a
> ti-cpufreq driver that can read the aformentioned values and provide
> them as version matching data to the opp framework. Through this the
> opp-supported-hw dt binding that is part of the operating-points-v2
> table can be used to indicate availability of OPPs for each device.
> 
> This driver also creates the "cpufreq-dt" platform_device after passing
> the version matching data to the OPP framework so that the cpufreq-dt
> handles the actual cpufreq implementation. Even without the necessary
> data to pass the version matching data the driver will still create this
> device to maintain backwards compatibility with operating-points v1
> tables.
> 
> Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
> ---
>  drivers/cpufreq/Kconfig.arm  |  11 ++
>  drivers/cpufreq/Makefile     |   1 +
>  drivers/cpufreq/ti-cpufreq.c | 254 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 266 insertions(+)
>  create mode 100644 drivers/cpufreq/ti-cpufreq.c
> 
> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
> index d89b8afe23b6..0dea6849ac3e 100644
> --- a/drivers/cpufreq/Kconfig.arm
> +++ b/drivers/cpufreq/Kconfig.arm
> @@ -234,6 +234,17 @@ config ARM_TEGRA124_CPUFREQ
>  	help
>  	  This adds the CPUFreq driver support for Tegra124 SOCs.
>  
> +config ARM_TI_CPUFREQ
> +	tristate "Texas Instruments CPUFreq support"

You sure you want to get it compiled as a module? And don't provide
module_exit() at all?

> +	depends on ARCH_OMAP2PLUS
> +	help
> +	  This driver enables valid OPPs on the running platform based on
> +	  values contained within the SoC in use. Enable this in order to
> +	  use the cpufreq-dt driver on all Texas Instruments platforms that
> +	  provide dt based operating-points-v2 tables with opp-supported-hw
> +	  data provided. Required for cpufreq support on AM335x, AM437x,
> +	  DRA7x, and AM57x platforms.
> +
>  config ARM_PXA2xx_CPUFREQ
>  	tristate "Intel PXA2xx CPUfreq driver"
>  	depends on PXA27x || PXA25x
> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
> index 0a9b6a093646..5b1b6ec0a9f0 100644
> --- a/drivers/cpufreq/Makefile
> +++ b/drivers/cpufreq/Makefile
> @@ -77,6 +77,7 @@ obj-$(CONFIG_ARM_SPEAR_CPUFREQ)		+= spear-cpufreq.o
>  obj-$(CONFIG_ARM_STI_CPUFREQ)		+= sti-cpufreq.o
>  obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)	+= tegra20-cpufreq.o
>  obj-$(CONFIG_ARM_TEGRA124_CPUFREQ)	+= tegra124-cpufreq.o
> +obj-$(CONFIG_ARM_TI_CPUFREQ)		+= ti-cpufreq.o
>  obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ)	+= vexpress-spc-cpufreq.o
>  obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
>  obj-$(CONFIG_MACH_MVEBU_V7)		+= mvebu-cpufreq.o
> diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
> new file mode 100644
> index 000000000000..e47b452aadd0
> --- /dev/null
> +++ b/drivers/cpufreq/ti-cpufreq.c
> @@ -0,0 +1,254 @@
> +/*
> + * TI CPUFreq/OPP hw-supported driver
> + *
> + * Copyright (C) 2016 Texas Instruments, Inc.
> + *	 Dave Gerlach <d-gerlach at ti.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/cpu.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/pm_opp.h>
> +#include <linux/regmap.h>
> +
> +#define REVISION_MASK				(0xF << 28)

Use below shift-mask here ?

> +#define REVISION_SHIFT				28
> +
> +#define DRA7_EFUSE_HAS_OD_MPU_OPP		11
> +#define DRA7_EFUSE_HAS_HIGH_MPU_OPP		15
> +#define DRA7_EFUSE_HAS_ALL_MPU_OPP		23
> +
> +#define DRA7_EFUSE_NOM_MPU_OPP			BIT(0)
> +#define DRA7_EFUSE_OD_MPU_OPP			BIT(1)
> +#define DRA7_EFUSE_HIGH_MPU_OPP			BIT(2)
> +
> +#define VERSION_COUNT				2
> +
> +static struct ti_cpufreq_data {
> +	struct device *cpu;
> +	struct regmap *opp_efuse;
> +	struct regmap *revision;
> +} opp_data;
> +
> +static struct ti_cpufreq_soc_data {
> +	unsigned long (*efuse_xlate)(unsigned long efuse);
> +} *soc_data;
> +
> +static unsigned long amx3_efuse_xlate(unsigned long efuse)
> +{
> +	/* AM335x and AM437x use "OPP disable" bits, so invert */
> +	return ~efuse;
> +}
> +
> +static unsigned long dra7_efuse_xlate(unsigned long efuse)
> +{
> +	unsigned long calculated_efuse = DRA7_EFUSE_NOM_MPU_OPP;
> +
> +	/*
> +	 * The efuse on dra7 and am57 parts contains a specific
> +	 * value indicating the highest available OPP.
> +	 */
> +
> +	switch (efuse) {
> +	case DRA7_EFUSE_HAS_ALL_MPU_OPP:
> +	case DRA7_EFUSE_HAS_HIGH_MPU_OPP:
> +		calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP;
> +	case DRA7_EFUSE_HAS_OD_MPU_OPP:
> +		calculated_efuse |= DRA7_EFUSE_OD_MPU_OPP;
> +	}
> +
> +	return calculated_efuse;
> +}
> +
> +static struct ti_cpufreq_soc_data amx3_soc_data = {
> +	.efuse_xlate = amx3_efuse_xlate,
> +};
> +
> +static struct ti_cpufreq_soc_data dra7_soc_data = {
> +	.efuse_xlate = dra7_efuse_xlate,
> +};
> +
> +/**
> + * ti_cpufreq_get_efuse() - Parse and return efuse value present on SoC
> + * @efuse_value: Set to the value parsed from efuse
> + *
> + * Returns error code if efuse not read properly.
> + */
> +static int ti_cpufreq_get_efuse(u32 *efuse_value)
> +{
> +	struct device *dev = opp_data.cpu;
> +	struct device_node *np = dev->of_node;
> +	unsigned int efuse_offset;
> +	u32 efuse, efuse_mask, efuse_shift;
> +	int ret;
> +
> +	ret = of_property_read_u32_index(np, "ti,syscon-efuse",
> +					 1, &efuse_offset);
> +	if (ret) {
> +		dev_err(dev,

Line break here isn't required.

> +			"No efuse offset provided %s: %d\n",
> +			np->full_name, ret);
> +		return ret;
> +	}
> +
> +	ret = of_property_read_u32_index(np, "ti,syscon-efuse", 2,
> +					 &efuse_mask);
> +	if (ret)
> +		efuse_mask = 0xffffffff;
> +
> +	ret = of_property_read_u32_index(np, "ti,syscon-efuse", 3,
> +					 &efuse_shift);
> +	if (ret)
> +		efuse_shift = 0;

Why don't you read an array of 3 integers in one go?

> +
> +	ret = regmap_read(opp_data.opp_efuse, efuse_offset, &efuse);
> +	if (ret) {
> +		dev_err(dev,
> +			"Failed to read the efuse value from syscon: %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	efuse = (efuse & efuse_mask) >> efuse_shift;
> +
> +	*efuse_value = soc_data->efuse_xlate(efuse);
> +
> +	return 0;
> +}
> +
> +/**
> + * ti_cpufreq_get_rev() - Parse and return rev value present on SoC
> + * @revision_value: Set to the value parsed from revision register
> + *
> + * Returns error code if revision not read properly.
> + */
> +static int ti_cpufreq_get_rev(u32 *revision_value)
> +{
> +	struct device *dev = opp_data.cpu;
> +	struct device_node *np = dev->of_node;
> +	unsigned int revision_offset;
> +	u32 revision;
> +	int ret;
> +
> +	ret = of_property_read_u32_index(np, "ti,syscon-rev",
> +					 1, &revision_offset);
> +	if (ret) {
> +		dev_err(dev,
> +			"No revision offset provided %s [%d]\n",
> +			np->full_name, ret);
> +		return ret;
> +	}
> +
> +	ret = regmap_read(opp_data.revision, revision_offset, &revision);
> +	if (ret) {
> +		dev_err(dev,
> +			"Failed to read the revision number from syscon: %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	*revision_value = BIT((revision & REVISION_MASK) >> REVISION_SHIFT);

That's an crazy operation.

So you first shifted 0xF << 27, and then right shifted everything by 27 bits :)

You should rather do:

#define REVISION_MASK   0xF
(revision >> REVISION_SHIFT) & REVISION_MASK

> +
> +	return 0;
> +}
> +
> +static int ti_cpufreq_setup_syscon_registers(void)
> +{
> +	struct device *dev = opp_data.cpu;
> +	struct device_node *np = dev->of_node;
> +
> +	opp_data.opp_efuse = syscon_regmap_lookup_by_phandle(np,
> +							"ti,syscon-efuse");
> +	if (IS_ERR(opp_data.opp_efuse)) {
> +		dev_dbg(dev,  "\"ti,syscon-efuse\" is missing, cannot use OPPv2 table.\n");
> +		return PTR_ERR(opp_data.opp_efuse);
> +	}
> +
> +	opp_data.revision = syscon_regmap_lookup_by_phandle(np,
> +							"ti,syscon-rev");
> +	if (IS_ERR(opp_data.revision)) {
> +		dev_dbg(dev,  "\"ti,syscon-rev\" is missing, cannot use OPPv2 table.\n");

These messages are wrong as your code is going to use opp-v2 anyway.

> +		return PTR_ERR(opp_data.revision);
> +	}
> +
> +	return 0;
> +}
> +
> +static struct ti_cpufreq_soc_data *ti_cpufreq_get_soc_data(void)
> +{
> +	if (of_machine_is_compatible("ti,am33xx") ||
> +	    of_machine_is_compatible("ti,am4372"))
> +		return &amx3_soc_data;
> +	else if (of_machine_is_compatible("ti,dra7"))
> +		return &dra7_soc_data;
> +	else
> +		return NULL;
> +}
> +
> +static int ti_cpufreq_init(void)

__init ?

> +{
> +	int ret;
> +	u32 version[VERSION_COUNT];
> +
> +	soc_data = ti_cpufreq_get_soc_data();
> +	if (!soc_data)
> +		return -ENODEV;

Why not use of_match_node() and an array of type struct of_device_id instead of
above function?

> +
> +	opp_data.cpu = get_cpu_device(0);
> +	if (!opp_data.cpu) {
> +		pr_err("%s: Failed to get device for CPU0\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	if (!of_get_property(opp_data.cpu->of_node, "operating-points-v2",
> +			     NULL)) {
> +		dev_info(opp_data.cpu, "OPP-v2 not supported, cpufreq-dt will attempt to use legacy tables.\n");
> +		goto register_cpufreq_dt;
> +	}
> +
> +	ret = ti_cpufreq_setup_syscon_registers();
> +	if (ret)
> +		goto register_cpufreq_dt;
> +
> +	/*
> +	 * OPPs determine whether or not they are supported based on
> +	 * two metrics:
> +	 *	0 - SoC Revision
> +	 *	1 - eFuse value
> +	 */
> +	ret = ti_cpufreq_get_rev(&version[0]);
> +	if (ret)
> +		return ret;
> +
> +	ret = ti_cpufreq_get_efuse(&version[1]);
> +	if (ret)
> +		return ret;
> +
> +	ret = dev_pm_opp_set_supported_hw(opp_data.cpu, version, VERSION_COUNT);
> +	if (ret) {
> +		dev_err(opp_data.cpu, "Failed to set supported hardware\n");
> +		return ret;
> +	}
> +
> +register_cpufreq_dt:
> +	platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
> +
> +	return 0;
> +}
> +module_init(ti_cpufreq_init);
> +
> +MODULE_DESCRIPTION("TI CPUFreq/OPP hw-supported driver");
> +MODULE_AUTHOR("Dave Gerlach <d-gerlach at ti.com>");
> +MODULE_LICENSE("GPL v2");
> -- 
> 2.7.3

-- 
viresh


From viresh.kumar at linaro.org  Wed May 18 21:41:21 2016
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Thu, 19 May 2016 10:11:21 +0530
Subject: [PATCH 2/8] ARM: dts: am33xx: Move to operating-points-v2 table
 and ti-cpufreq driver
In-Reply-To: <f30e0313514cdbb9c3b0a83bbb96f05f2e179775.1463606963.git.d-gerlach@ti.com>
References: <cover.1463606963.git.d-gerlach@ti.com>
 <f30e0313514cdbb9c3b0a83bbb96f05f2e179775.1463606963.git.d-gerlach@ti.com>
Message-ID: <20160519044121.GD32001@vireshk-i7>

On 18-05-16, 18:36, Dave Gerlach wrote:
> +	cpu0_opp_table: opp_table0 {
> +		compatible = "operating-points-v2";
> +
> +		/*
> +		 * The three following nodes are marked with opp-suspend
> +		 * because the can not be enabled simultaneously on a
> +		 * single SoC.
> +		 */
> +		opp50 at 300000000 {
> +			opp-hz = /bits/ 64 <300000000>;
> +			opp-microvolt = <950000 931000 969000>;
> +			opp-supported-hw = <0x06 0x0010>;

Is there any place in either of the patchsets you have sent, that details the
usage of the above two values? I mean which defines, what is 0x6 and what is
0x1 ?

-- 
viresh


From viresh.kumar at linaro.org  Wed May 18 21:47:44 2016
From: viresh.kumar at linaro.org (Viresh Kumar)
Date: Thu, 19 May 2016 10:17:44 +0530
Subject: [PATCH 0/8] ARM: dts: Add operating-points-v2 tables for TI
 platforms
In-Reply-To: <cover.1463606963.git.d-gerlach@ti.com>
References: <cover.1463606963.git.d-gerlach@ti.com>
Message-ID: <20160519044744.GE32001@vireshk-i7>

On 18-05-16, 18:36, Dave Gerlach wrote:
> Hi,
> This series adds operating-points-v2 tables for am335x, am437x, dra7xx,
> and am57xx based platforms along with some support patches so that we
> can enable more OPPs for the CPU on these platforms.
> 
> These patches rely on the ti-cpufreq series sent here [1] and provide
> opp-supported-hw data for each OPP so that only the appropriate OPPs
> for a specific piece of silicon get enabled.

Acked-by: Viresh Kumar <viresh.kumar at linaro.org>

-- 
viresh


From andy.gross at linaro.org  Wed May 18 22:00:15 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 19 May 2016 00:00:15 -0500
Subject: [PATCH 0/5] Qualcomm Suspend to Idle Support
Message-ID: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>

This set of patches adds suspend to idle support for the Qualcomm APQ8084
and MSM8916 platforms.  The patches add a minimal set of suspend ops and
init functions to properly configure the enter_freeze function.

This patch set is based on the work done in the following:
[RFC v3 00/12] PM: SoC idle support using PM domains
http://comments.gmane.org/gmane.linux.ports.arm.msm/17966

The relevant prerequisites are the PSCI enablement DT patches.  PSCI based
firmware is also required for the MSM8916 to work properly.

Andy Gross (5):
  soc: qcom: Add suspend to idle support
  arm: defconfig: Add Qualcomm Suspend options
  arm64: dts: msm8916: Add spc compat tag
  ARM: dts: qcom: Remove size elements from pmic reg
  ARM: dts: qcom: pma8084: Add pwrkey entry

 arch/arm/boot/dts/qcom-pma8084.dtsi   | 20 ++++++---
 arch/arm64/boot/dts/qcom/msm8916.dtsi |  2 +-
 arch/arm64/configs/defconfig          |  2 +
 drivers/soc/qcom/Makefile             |  1 +
 drivers/soc/qcom/suspend.c            | 77 +++++++++++++++++++++++++++++++++++
 5 files changed, 95 insertions(+), 7 deletions(-)
 create mode 100644 drivers/soc/qcom/suspend.c

-- 
1.9.1



From andy.gross at linaro.org  Wed May 18 22:00:16 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 19 May 2016 00:00:16 -0500
Subject: [PATCH 1/5] soc: qcom: Add suspend to idle support
In-Reply-To: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
References: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463634020-17252-2-git-send-email-andy.gross@linaro.org>

This patch adds suspend to idle support for Qualcomm processors.  While
suspend to memory will be a valid state, there won't be any special
handling or power savings over the suspend to idle.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 drivers/soc/qcom/Makefile  |  1 +
 drivers/soc/qcom/suspend.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+)
 create mode 100644 drivers/soc/qcom/suspend.c

diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index fdd664e..7c479d3 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
 obj-$(CONFIG_QCOM_SMP2P)	+= smp2p.o
 obj-$(CONFIG_QCOM_SMSM)	+= smsm.o
 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_SUSPEND)	+=	suspend.o
diff --git a/drivers/soc/qcom/suspend.c b/drivers/soc/qcom/suspend.c
new file mode 100644
index 0000000..7d3f2dd
--- /dev/null
+++ b/drivers/soc/qcom/suspend.c
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2016 Linaro Ltd.
+ *
+ * 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; version 2
+ * of the License.
+ */
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/cpuidle.h>
+#include <linux/suspend.h>
+
+
+static void qcom_pm_enter_freeze(struct cpuidle_device *dev,
+	struct cpuidle_driver *drv,
+	int index)
+{
+	drv->states[index].enter(dev, drv, index);
+}
+
+static const struct of_device_id qcom_idle_state_match[] = {
+	{ .compatible = "qcom,idle-state-spc", },
+	{ },
+};
+
+static const struct platform_suspend_ops qcom_suspend_ops = {
+	.valid          = suspend_valid_only_mem,
+};
+
+static int __init qcom_pm_init(void)
+{
+	struct cpuidle_device *cpu_dev;
+	struct cpuidle_driver *cpu_drv;
+	int state_count;
+	struct device_node *state_np, *cpu_np;
+	const struct of_device_id *match;
+	int i;
+
+	/* configure CPU enter_freeze if applicable */
+	for_each_present_cpu(i) {
+		cpu_np = of_get_cpu_node(i, NULL);
+		cpu_dev = per_cpu_ptr(cpuidle_devices, i);
+		cpu_drv = cpuidle_get_cpu_driver(cpu_dev);
+
+		if (!cpu_dev || !cpu_drv) {
+			of_node_put(cpu_np);
+			return -EPROBE_DEFER;
+		}
+
+		state_count = 0;
+		state_np = of_parse_phandle(cpu_np, "cpu-idle-states",
+						  state_count);
+
+		while (state_np) {
+			match = of_match_node(qcom_idle_state_match,
+					      state_np);
+
+			state_count++;
+			if (match)
+				cpu_drv->states[state_count].enter_freeze =
+						&qcom_pm_enter_freeze;
+			of_node_put(state_np);
+
+			state_np = of_parse_phandle(cpu_np, "cpu-idle-states",
+						    state_count);
+		}
+
+		of_node_put(cpu_np);
+	}
+
+	suspend_set_ops(&qcom_suspend_ops);
+
+	return 0;
+}
+
+late_initcall(qcom_pm_init);
-- 
1.9.1



From andy.gross at linaro.org  Wed May 18 22:00:17 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 19 May 2016 00:00:17 -0500
Subject: [PATCH 2/5] arm: defconfig: Enable PM8941 pwr key
In-Reply-To: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
References: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463634020-17252-3-git-send-email-andy.gross@linaro.org>

This patch enables the PM8941 pwr key driver.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 arch/arm64/configs/defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 8917150..d4c539f 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -142,6 +142,8 @@ CONFIG_WL18XX=m
 CONFIG_WLCORE_SDIO=m
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PM8941_PWRKEY=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_AMBAKMI=y
 CONFIG_LEGACY_PTY_COUNT=16
-- 
1.9.1



From andy.gross at linaro.org  Wed May 18 22:00:18 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 19 May 2016 00:00:18 -0500
Subject: [PATCH 3/5] arm64: dts: msm8916: Add spc compat tag
In-Reply-To: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
References: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463634020-17252-4-git-send-email-andy.gross@linaro.org>

This patch adds the qcom,idle-state-spc compatible to the SPC idle
state.  This compatible indicates that the state is one which supports
freeze.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 208af00..032e411 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -104,7 +104,7 @@
 
 		idle-states {
 			CPU_SPC: spc {
-				compatible = "arm,idle-state";
+				compatible = "qcom,idle-state-spc", "arm,idle-state";
 				arm,psci-suspend-param = <0x40000002>;
 				entry-latency-us = <130>;
 				exit-latency-us = <150>;
-- 
1.9.1



From andy.gross at linaro.org  Wed May 18 22:00:19 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 19 May 2016 00:00:19 -0500
Subject: [PATCH 4/5] ARM: dts: qcom: Remove size elements from pmic reg
In-Reply-To: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
References: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463634020-17252-5-git-send-email-andy.gross@linaro.org>

The #size-cells for the pmics are 0, but we specify a size in the
reg property so that MPP and GPIO modules can figure out how many
pins there are. Now that we've done that by counting irqs, we can
remove the size elements in the reg properties and be DT
compliant.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 arch/arm/boot/dts/qcom-pma8084.dtsi | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/qcom-pma8084.dtsi b/arch/arm/boot/dts/qcom-pma8084.dtsi
index 4e9bd3f..ea7fce3 100644
--- a/arch/arm/boot/dts/qcom-pma8084.dtsi
+++ b/arch/arm/boot/dts/qcom-pma8084.dtsi
@@ -12,15 +12,15 @@
 
 		rtc at 6000 {
 			compatible = "qcom,pm8941-rtc";
-			reg = <0x6000 0x100>,
-			      <0x6100 0x100>;
+			reg = <0x6000>,
+			      <0x6100>;
 			reg-names = "rtc", "alarm";
 			interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>;
 		};
 
 		pma8084_gpios: gpios at c000 {
 			compatible = "qcom,pma8084-gpio", "qcom,spmi-gpio";
-			reg = <0xc000 0x1600>;
+			reg = <0xc000>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupts = <0 0xc0 0 IRQ_TYPE_NONE>,
@@ -49,7 +49,7 @@
 
 		pma8084_mpps: mpps at a000 {
 			compatible = "qcom,pma8084-mpp", "qcom,spmi-mpp";
-			reg = <0xa000 0x800>;
+			reg = <0xa000>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupts = <0 0xa0 0 IRQ_TYPE_NONE>,
@@ -64,7 +64,7 @@
 
 		pma8084_temp: temp-alarm at 2400 {
 			compatible = "qcom,spmi-temp-alarm";
-			reg = <0x2400 0x100>;
+			reg = <0x2400>;
 			interrupts = <0 0x24 0 IRQ_TYPE_EDGE_RISING>;
 			#thermal-sensor-cells = <0>;
 			io-channels = <&pma8084_vadc VADC_DIE_TEMP>;
@@ -73,7 +73,7 @@
 
 		pma8084_vadc: vadc at 3100 {
 			compatible = "qcom,spmi-vadc";
-			reg = <0x3100 0x100>;
+			reg = <0x3100>;
 			interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-- 
1.9.1



From andy.gross at linaro.org  Wed May 18 22:00:20 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 19 May 2016 00:00:20 -0500
Subject: [PATCH 5/5] ARM: dts: qcom: pma8084: Add pwrkey entry
In-Reply-To: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
References: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
Message-ID: <1463634020-17252-6-git-send-email-andy.gross@linaro.org>

This patch adds the power key device tree node.

Signed-off-by: Andy Gross <andy.gross at linaro.org>
---
 arch/arm/boot/dts/qcom-pma8084.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-pma8084.dtsi b/arch/arm/boot/dts/qcom-pma8084.dtsi
index ea7fce3..82d2580 100644
--- a/arch/arm/boot/dts/qcom-pma8084.dtsi
+++ b/arch/arm/boot/dts/qcom-pma8084.dtsi
@@ -18,6 +18,14 @@
 			interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>;
 		};
 
+		pwrkey at 800 {
+			compatible = "qcom,pm8941-pwrkey";
+			reg = <0x800>;
+			interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
+			debounce = <15625>;
+			bias-pull-up;
+		};
+
 		pma8084_gpios: gpios at c000 {
 			compatible = "qcom,pma8084-gpio", "qcom,spmi-gpio";
 			reg = <0xc000>;
-- 
1.9.1



From fixed-term.Oleksij.Rempel at de.bosch.com  Wed May 18 22:34:43 2016
From: fixed-term.Oleksij.Rempel at de.bosch.com (fixed-term.Oleksij.Rempel)
Date: Thu, 19 May 2016 07:34:43 +0200
Subject: arm64: unhandled level 3 permission fault on ltp mmap16 test
Message-ID: <573D5073.1050508@de.bosch.com>

Hallo all,

if i run latest ltp tests on any of latest kernel version i get
fallowing warning:

root at rcar1:/opt/ltp# dmesg
root at rcar1:/opt/ltp# ./testcases/bin/mmap16
mmap16      0  TINFO  :  Found free device '/dev/loop0'
mmap16      0  TINFO  :  Formatting /dev/loop0 with ext4 opts='-b 1024'
extra opts='10240'
mke2fs 1.43-WIP (15-Mar-2016)
[  889.736679] EXT4-fs (loop0): mounted filesystem with ordered data
mode. Opts: nodelalloc
[  889.843995] mmap16[2164]: unhandled level 3 permission fault (7) at
0x7f8397d400, esr 0x9200004f
[  889.852807] pgd = ffffffc00b342000
[  889.856239] [7f8397d400] *pgd=0000000052977003,
*pud=0000000052977003, *pmd=0000000053a8d003, *pte3
[  889.866719]
[  889.868223] CPU: 0 PID: 2164 Comm: mmap16 Not tainted
4.4.0-10183-g20698ed #9
[  889.875361] Hardware name: Renesas Salvator-X board based on r8a7795 (DT)
[  889.882152] task: ffffffc5ba52d400 ti: ffffffc00a998000 task.ti:
ffffffc00a998000
[  889.889642] PC is at 0x402ed8
[  889.892612] LR is at 0x402eb4
[  889.895582] pc : [<0000000000402ed8>] lr : [<0000000000402eb4>]
pstate: 20000000
[  889.902978] sp : 0000007fe744fc80
[  889.906293] x29: 0000007fe744fcb0 x28: 0000000000000000
[  889.911626] x27: 0000000000000000 x26: 000000000040adc0
[  889.916952] x25: 0000007f8397d000 x24: 000000000041f648
[  889.922279] x23: 0000007f8397d000 x22: 0000000000000061
[  889.927611] x21: 0000000000000003 x20: 000000000040a000
[  889.932937] x19: 000000000040ad78 x18: 0000000000000001
[  889.938263] x17: 0000007f838a6760 x16: 000000000041f570
[  889.943593] x15: 0000007f837e41c0 x14: 0000007f83984000
[  889.948919] x13: 0000007fe744fc50 x12: 0000007f8396a63c
[  889.954246] x11: 0000007fe744fc40 x10: 000000000000000a
[  889.959575] x9 : 00000000000f4240 x8 : 0000000000000062
[  889.964903] x7 : 0000000000000000 x6 : 0000000000000000
[  889.970228] x5 : 0000000000000000 x4 : 0000000000001000
[  889.975559] x3 : 0000007fe744fc30 x2 : 0000000000000061
[  889.980885] x1 : 0000007f8397d400 x0 : 0000007f8397e000
[  889.986210]
[  890.944664] mmap16[2165]: unhandled level 3 permission fault (7) at
0x7f8397d400, esr 0x9200004f
[  890.953483] pgd = ffffffc00b314000
[  890.956916] [7f8397d400] *pgd=000000005382b003,
*pud=000000005382b003, *pmd=000000005281f003, *pte3
[  890.967403]
[  890.968898] CPU: 2 PID: 2165 Comm: mmap16 Not tainted
4.4.0-10183-g20698ed #9
[  890.976039] Hardware name: Renesas Salvator-X board based on r8a7795 (DT)
[  890.982833] task: ffffffc00a913c00 ti: ffffffc00a800000 task.ti:
ffffffc00a800000
[  890.990325] PC is at 0x402ed8
[  890.993294] LR is at 0x402eb4
[  890.996267] pc : [<0000000000402ed8>] lr : [<0000000000402eb4>]
pstate: 20000000
[  891.003663] sp : 0000007fe744fc80
[  891.006972] x29: 0000007fe744fcb0 x28: 0000000000000000
[  891.012305] x27: 0000000000000000 x26: 000000000040adc0
[  891.017635] x25: 0000007f8397d000 x24: 000000000041f648
[  891.022964] x23: 0000007f8397d000 x22: 0000000000000061
[  891.028297] x21: 0000000000000003 x20: 000000000040a000
[  891.033625] x19: 000000000040ad78 x18: 0000000000000001
[  891.038954] x17: 0000007f838a6760 x16: 000000000041f570
[  891.044305] x15: 0000007f837e3ff4 x14: 0000007f83984cc0
[  891.049644] x13: 0000007fe744fc50 x12: 0000000000000000
[  891.054976] x11: 0000000000000000 x10: 000000000000000a
[  891.060306] x9 : 00000000000f4240 x8 : 0000000000000062
[  891.065634] x7 : 0000000000000000 x6 : 0000000000000000
[  891.070962] x5 : 0000000000000000 x4 : 0000000000001000
[  891.076296] x3 : 0000007fe744fc30 x2 : 0000000000000061
[  891.081625] x1 : 0000007f8397d400 x0 : 0000007f8397e000
[  891.086954]
                    [188/1931]
[  892.576092] mmap16[2166]: unhandled level 3 permission fault (7) at
0x7f8397d400, esr 0x9200004f
[  892.584918] pgd = ffffffc5bbc25000
[  892.588352] [7f8397d400] *pgd=0000000603d6d003,
*pud=0000000603d6d003, *pmd=0000000603661003, *pte3
[  892.598831]
[  892.600333] CPU: 2 PID: 2166 Comm: mmap16 Not tainted
4.4.0-10183-g20698ed #9
[  892.607474] Hardware name: Renesas Salvator-X board based on r8a7795 (DT)
[  892.614265] task: ffffffc00a913000 ti: ffffffc4f53e0000 task.ti:
ffffffc4f53e0000
[  892.621752] PC is at 0x402ed8
[  892.624720] LR is at 0x402eb4
[  892.627689] pc : [<0000000000402ed8>] lr : [<0000000000402eb4>]
pstate: 20000000
[  892.635083] sp : 0000007fe744fc80
[  892.638397] x29: 0000007fe744fcb0 x28: 0000000000000000
[  892.643728] x27: 0000000000000000 x26: 000000000040adc0
[  892.649053] x25: 0000007f8397d000 x24: 000000000041f648
[  892.654379] x23: 0000007f8397d000 x22: 0000000000000061
[  892.659709] x21: 0000000000000003 x20: 000000000040a000
[  892.665034] x19: 000000000040ad78 x18: 0000000000000001
[  892.670361] x17: 0000007f838a6760 x16: 000000000041f570
[  892.675689] x15: 0000007f837e3ff4 x14: 0000007f83984cc0
[  892.681013] x13: 4010040140100401 x12: 0010000000000000
[  892.686338] x11: 4000000000000000 x10: 000000000000000a
[  892.691668] x9 : 00000000000f4240 x8 : 0000000000000062
[  892.696993] x7 : 0000000000000000 x6 : 0000000000000000
[  892.702318] x5 : 0000000000000000 x4 : 0000000000001000
[  892.707647] x3 : 0000007fe744fc30 x2 : 0000000000000061
[  892.712971] x1 : 0000007f8397d400 x0 : 0000007f8397e000
[  892.718296]
[  893.699683] mmap16[2167]: unhandled level 3 permission fault (7) at
0x7f8397d400, esr 0x9200004f
[  893.708500] pgd = ffffffc00b3f8000
[  893.711927] [7f8397d400] *pgd=0000000053108003,
*pud=0000000053108003, *pmd=0000000053120003, *pte3
[  893.722412]
[  893.723914] CPU: 0 PID: 2167 Comm: mmap16 Not tainted
4.4.0-10183-g20698ed #9
[  893.731058] Hardware name: Renesas Salvator-X board based on r8a7795 (DT)
[  893.737850] task: ffffffc5ba52e000 ti: ffffffc00b168000 task.ti:
ffffffc00b168000
[  893.745341] PC is at 0x402ed8
[  893.748313] LR is at 0x402eb4
[  893.751284] pc : [<0000000000402ed8>] lr : [<0000000000402eb4>]
pstate: 20000000
[  893.758680] sp : 0000007fe744fc80
[  893.761996] x29: 0000007fe744fcb0 x28: 0000000000000000
[  893.767329] x27: 0000000000000000 x26: 000000000040adc0
[  893.772657] x25: 0000007f8397d000 x24: 000000000041f648
[  893.777982] x23: 0000007f8397d000 x22: 0000000000000061
[  893.783312] x21: 0000000000000003 x20: 000000000040a000
[  893.788639] x19: 000000000040ad78 x18: 0000000000000001
[  893.793965] x17: 0000007f838a6760 x16: 000000000041f570
[  893.799303] x15: 0000007f837e3ff4 x14: 0000007f83984cc0
[  893.804630] x13: 4010040140100401 x12: 0010000000000000
[  893.809956] x11: 4000000000000000 x10: 000000000000000a
[  893.815286] x9 : 00000000000f4240 x8 : 0000000000000062
[  893.820641] x7 : 0000000000000000 x6 : 0000000000000000
[  893.825971] x5 : 0000000000000000 x4 : 0000000000001000
[  893.831301] x3 : 0000007fe744fc30 x2 : 0000000000000061
[  893.836628] x1 : 0000007f8397d400 x0 : 0000007f8397e000
[  893.841953]
[  894.640420] mmap16[2168]: unhandled level 3 permission fault (7) at
0x7f8397d400, esr 0x9[133/1931]
[  894.649251] pgd = ffffffc5bba23000
[  894.652686] [7f8397d400] *pgd=0000000603530003,
*pud=0000000603530003, *pmd=0000000603a83003, *pte3
[  894.663163]
[  894.664671] CPU: 1 PID: 2168 Comm: mmap16 Not tainted
4.4.0-10183-g20698ed #9
[  894.671813] Hardware name: Renesas Salvator-X board based on r8a7795 (DT)
[  894.678603] task: ffffffc5ba529800 ti: ffffffc4f53e0000 task.ti:
ffffffc4f53e0000
[  894.686093] PC is at 0x402ed8
[  894.689062] LR is at 0x402eb4
[  894.692032] pc : [<0000000000402ed8>] lr : [<0000000000402eb4>]
pstate: 20000000
[  894.699430] sp : 0000007fe744fc80
[  894.702738] x29: 0000007fe744fcb0 x28: 0000000000000000
[  894.708072] x27: 0000000000000000 x26: 000000000040adc0
[  894.713399] x25: 0000007f8397d000 x24: 000000000041f648
[  894.718727] x23: 0000007f8397d000 x22: 0000000000000061
[  894.724059] x21: 0000000000000003 x20: 000000000040a000
[  894.729386] x19: 000000000040ad78 x18: 0000000000000001
[  894.734712] x17: 0000007f838a6760 x16: 000000000041f570
[  894.740043] x15: 0000007f837e3ff4 x14: 0000007f83984cc0
[  894.745370] x13: 4010040140100401 x12: 0010000000000000
[  894.750697] x11: 4000000000000000 x10: 000000000000000a
[  894.756028] x9 : 00000000000f4240 x8 : 0000000000000062
[  894.761353] x7 : 0000000000000000 x6 : 0000000000000000
[  894.766681] x5 : 0000000000000000 x4 : 0000000000001000
[  894.772017] x3 : 0000007fe744fc30 x2 : 0000000000000061
[  894.777343] x1 : 0000007f8397d400 x0 : 0000007f8397e000
[  894.782675]
[  895.880198] mmap16[2169]: unhandled level 3 permission fault (7) at
0x7f8397d400, esr 0x9200004f
[  895.889018] pgd = ffffffc5ba6be000
[  895.892447] [7f8397d400] *pgd=00000006026bd003,
*pud=00000006026bd003, *pmd=00000006024b3003, *pte3
[  895.902929]
[  895.904430] CPU: 2 PID: 2169 Comm: mmap16 Not tainted
4.4.0-10183-g20698ed #9
[  895.911571] Hardware name: Renesas Salvator-X board based on r8a7795
(DT)                [101/1931]
[  895.918361] task: ffffffc5ba67d400 ti: ffffffc5bbd8c000 task.ti:
ffffffc5bbd8c000
[  895.925853] PC is at 0x402ed8
[  895.928822] LR is at 0x402eb4
[  895.931792] pc : [<0000000000402ed8>] lr : [<0000000000402eb4>]
pstate: 20000000
[  895.939186] sp : 0000007fe744fc80
[  895.942502] x29: 0000007fe744fcb0 x28: 0000000000000000
[  895.947835] x27: 0000000000000000 x26: 000000000040adc0
[  895.953161] x25: 0000007f8397d000 x24: 000000000041f648
[  895.958488] x23: 0000007f8397d000 x22: 0000000000000061
[  895.963817] x21: 0000000000000003 x20: 000000000040a000
[  895.969142] x19: 000000000040ad78 x18: 0000000000000001
[  895.974469] x17: 0000007f838a6760 x16: 000000000041f570
[  895.979799] x15: 0000007f837e3ff4 x14: 0000007f83984cc0
[  895.985124] x13: 4010040140100401 x12: 0010000000000000
[  895.990451] x11: 4000000000000000 x10: 000000000000000a
[  895.995781] x9 : 00000000000f4240 x8 : 0000000000000062
[  896.001107] x7 : 0000000000000000 x6 : 0000000000000000
[  896.006433] x5 : 0000000000000000 x4 : 0000000000001000
[  896.011763] x3 : 0000007fe744fc30 x2 : 0000000000000061
[  896.017089] x1 : 0000007f8397d400 x0 : 0000007f8397e000
[  896.022416]
[  896.962641] mmap16[2170]: unhandled level 3 permission fault (7) at
0x7f8397d400, esr 0x9200004f
[  896.971470] pgd = ffffffc00b117000
[  896.974872] [7f8397d400] *pgd=000000005311d003,
*pud=000000005311d003, *pmd=0000000053137003, *pte3
[  896.985375]
[  896.986869] CPU: 1 PID: 2170 Comm: mmap16 Not tainted
4.4.0-10183-g20698ed #9
[  896.994011] Hardware name: Renesas Salvator-X board based on r8a7795 (DT)
[  897.000804] task: ffffffc5ba678c00 ti: ffffffc00a800000 task.ti:
ffffffc00a800000
[  897.008295] PC is at 0x402ed8
[  897.011265] LR is at 0x402eb4
[  897.014228] pc : [<0000000000402ed8>] lr : [<0000000000402eb4>]
pstate: 20000000
[  897.011265] LR is at 0x402eb4
                     [71/1931]
[  897.014228] pc : [<0000000000402ed8>] lr : [<0000000000402eb4>]
pstate: 20000000
[  897.021625] sp : 0000007fe744fc80
[  897.024942] x29: 0000007fe744fcb0 x28: 0000000000000000
[  897.030270] x27: 0000000000000000 x26: 000000000040adc0
[  897.035601] x25: 0000007f8397d000 x24: 000000000041f648
[  897.040927] x23: 0000007f8397d000 x22: 0000000000000061
[  897.046255] x21: 0000000000000003 x20: 000000000040a000
[  897.051587] x19: 000000000040ad78 x18: 0000000000000001
[  897.056914] x17: 0000007f838a6760 x16: 000000000041f570
[  897.062241] x15: 0000007f837e3ff4 x14: 0000007f83984cc0
[  897.067572] x13: 4010040140100401 x12: 0010000000000000
[  897.072898] x11: 4000000000000000 x10: 000000000000000a
[  897.078225] x9 : 00000000000f4240 x8 : 0000000000000062
[  897.083556] x7 : 0000000000000000 x6 : 0000000000000000
[  897.088882] x5 : 0000000000000000 x4 : 0000000000001000
[  897.094209] x3 : 0000007fe744fc30 x2 : 0000000000000061
[  897.099540] x1 : 0000007f8397d400 x0 : 0000007f8397e000
[  897.104874]
[  897.937392] mmap16[2171]: unhandled level 3 permission fault (7) at
0x7f8397d400, esr 0x9200004f
[  897.946215] pgd = ffffffc5bbf8a000
[  897.949639] [7f8397d400] *pgd=000000060379a003,
*pud=000000060379a003, *pmd=0000000603a80003, *pte3
[  897.960121]
[  897.961615] CPU: 2 PID: 2171 Comm: mmap16 Not tainted
4.4.0-10183-g20698ed #9
[  897.968752] Hardware name: Renesas Salvator-X board based on r8a7795 (DT)
[  897.975546] task: ffffffc5ba67d400 ti: ffffffc5bbd8c000 task.ti:
ffffffc5bbd8c000
[  897.983036] PC is at 0x402ed8
[  897.986004] LR is at 0x402eb4
[  897.988974] pc : [<0000000000402ed8>] lr : [<0000000000402eb4>]
pstate: 20000000
[  897.996370] sp : 0000007fe744fc80
[  897.999686] x29: 0000007fe744fcb0 x28: 0000000000000000
[  898.005014] x27: 0000000000000000 x26: 000000000040adc0
.............snip................
[  900.078262] x5 : 0000000000000000 x4 : 0000000000001000
[  900.083609] x3 : 0000007fe744fc30 x2 : 0000000000000061
[  900.088943] x1 : 0000007f8397d400 x0 : 0000007f8397e000
[  900.094275]
mmap16      1  TPASS  :  Bug is not reproduced!



Can some one please help me to understand this? If i see it correctly,
some thing wrong happened by level 3 address translation. But i have no
idea how to solve it (if it should be solved)

-- 
Best regards,
Oleksij Rempel
CM-AI/ECO3
Tel.: +49(5121)49-2962


From kishon at ti.com  Wed May 18 23:06:18 2016
From: kishon at ti.com (Kishon Vijay Abraham I)
Date: Thu, 19 May 2016 11:36:18 +0530
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
 <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com>
Message-ID: <573D57DA.20900@ti.com>

Hi Peter,

On Wednesday 18 May 2016 03:54 PM, Peter Ujfalusi wrote:
> On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
>> omap hsmmc host controller has ADMA2 feature. Enable it here
>> for better read and write throughput. Add a new dt binding
>> "ti,use_adma" to enable ADMA2.
>>
>> Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
>> ---
>>  .../devicetree/bindings/mmc/ti-omap-hsmmc.txt      |    1 +
>>  drivers/mmc/host/omap_hsmmc.c                      |  320 ++++++++++++++++----
>>  include/linux/platform_data/hsmmc-omap.h           |    1 +
>>  3 files changed, 256 insertions(+), 66 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>> index 74166a0..eb5ceec2 100644
>> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>> @@ -28,6 +28,7 @@ specifier is required.
>>  dma-names: List of DMA request names. These strings correspond
>>  1:1 with the DMA specifiers listed in dmas. The string naming is
>>  to be "rx" and "tx" for RX and TX DMA requests, respectively.
>> +ti,use_adma: enable adma2 feature
> 
> Do we have use case when you want to fall back to generic DMA instead of aDMA2?
> IMHO if the driver supports aDMA2, it is going to use it instead of the
> generic s/eDMA.
> What I mean is:
> the driver implements the aDMA2 support.
> if the IP has support for aDMA2, then it is going to use it, otherwise it will
> use the generic DMA.

hmm.. how will the driver know if the IP has support for aDMA2. Using dt
binding is one way. Using MMCHS_HL_HWINFO is another way but then the register
offsets in omap_hsmmc driver has to be modified for omap4+.

Thanks
Kishon


From kishon at ti.com  Wed May 18 23:14:16 2016
From: kishon at ti.com (Kishon Vijay Abraham I)
Date: Thu, 19 May 2016 11:44:16 +0530
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <20160518193028.GT5995@atomide.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
 <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com>
 <20160518193028.GT5995@atomide.com>
Message-ID: <573D59B8.7050701@ti.com>

Hi Tony,

On Thursday 19 May 2016 01:00 AM, Tony Lindgren wrote:
> * Peter Ujfalusi <peter.ujfalusi at ti.com> [160518 03:26]:
>> On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
>>> omap hsmmc host controller has ADMA2 feature. Enable it here
>>> for better read and write throughput. Add a new dt binding
>>> "ti,use_adma" to enable ADMA2.
>>>
>>> Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
>>> ---
>>>  .../devicetree/bindings/mmc/ti-omap-hsmmc.txt      |    1 +
>>>  drivers/mmc/host/omap_hsmmc.c                      |  320 ++++++++++++++++----
>>>  include/linux/platform_data/hsmmc-omap.h           |    1 +
>>>  3 files changed, 256 insertions(+), 66 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> index 74166a0..eb5ceec2 100644
>>> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> @@ -28,6 +28,7 @@ specifier is required.
>>>  dma-names: List of DMA request names. These strings correspond
>>>  1:1 with the DMA specifiers listed in dmas. The string naming is
>>>  to be "rx" and "tx" for RX and TX DMA requests, respectively.
>>> +ti,use_adma: enable adma2 feature
>>
>> Do we have use case when you want to fall back to generic DMA instead of aDMA2?
> 
> Yes my guess is that PM runtime breaks with these currently..

pm_runtime_get is invoked during omap_hsmmc_request and pm_runtime_put is
invoked during omap_hsmmc_request_done. Both these calls are outside DMA API's.
So it shouldn't break anything w.r.t PM runtime no?
> 
>> IMHO if the driver supports aDMA2, it is going to use it instead of the
>> generic s/eDMA.
>> What I mean is:
>> the driver implements the aDMA2 support.
>> if the IP has support for aDMA2, then it is going to use it, otherwise it will
>> use the generic DMA.
> 
> Ideally the adma support would be a separate loadable module,
> similar how the cppi41dma is a child of the OTG controller.
> 
> That way the systems wanting to use adma can just specify it
> in the binding, and adma PM runtime support can be added later
> on.
> 
> Of course this won't work if the adma registers are sprinkled
> within the MMC controller registers..

right, adma registers are within the MMC controller register space.

Thanks
Kishon


From vigneshr at ti.com  Wed May 18 23:47:28 2016
From: vigneshr at ti.com (Vignesh R)
Date: Thu, 19 May 2016 12:17:28 +0530
Subject: [PATCH 0/2] AM335x ICE: Add support for PCA9536 GPIO expander
Message-ID: <1463640450-16762-1-git-send-email-vigneshr@ti.com>



This patch series adds support for TI PCA9536 GPIO expander present on
AM335x ICE board.

Vignesh R (2):
  gpio: pca953x: Add support for TI PCA9536
  ARM: dts: am335x-icev2: Add DT node for TI PCA9536

 Documentation/devicetree/bindings/gpio/gpio-pca953x.txt | 1 +
 arch/arm/boot/dts/am335x-icev2.dts                      | 7 +++++++
 drivers/gpio/gpio-pca953x.c                             | 1 +
 3 files changed, 9 insertions(+)

-- 
2.8.2



From vigneshr at ti.com  Wed May 18 23:47:29 2016
From: vigneshr at ti.com (Vignesh R)
Date: Thu, 19 May 2016 12:17:29 +0530
Subject: [PATCH 1/2] gpio: pca953x: Add support for TI PCA9536
In-Reply-To: <1463640450-16762-1-git-send-email-vigneshr@ti.com>
References: <1463640450-16762-1-git-send-email-vigneshr@ti.com>
Message-ID: <1463640450-16762-2-git-send-email-vigneshr@ti.com>

TI PCA9536 is 4-Bit I2C GPIO expander without interrupt support[1].
Add support for the same.

[1] TRM: http://www.ti.com/lit/ds/symlink/pca9536.pdf

Signed-off-by: Vignesh R <vigneshr at ti.com>
---
 Documentation/devicetree/bindings/gpio/gpio-pca953x.txt | 1 +
 drivers/gpio/gpio-pca953x.c                             | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt
index 6b4a98f74be3..08dd15f89ba9 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt
@@ -21,6 +21,7 @@ Required properties:
 	maxim,max7313
 	maxim,max7315
 	ti,pca6107
+	ti,pca9536
 	ti,tca6408
 	ti,tca6416
 	ti,tca6424
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 5e3be32ebb8d..763028562d22 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -861,6 +861,7 @@ static const struct of_device_id pca953x_dt_ids[] = {
 	{ .compatible = "maxim,max7315", .data = OF_953X( 8, PCA_INT), },
 
 	{ .compatible = "ti,pca6107", .data = OF_953X( 8, PCA_INT), },
+	{ .compatible = "ti,pca9536", .data = OF_953X( 4, 0), },
 	{ .compatible = "ti,tca6408", .data = OF_953X( 8, PCA_INT), },
 	{ .compatible = "ti,tca6416", .data = OF_953X(16, PCA_INT), },
 	{ .compatible = "ti,tca6424", .data = OF_953X(24, PCA_INT), },
-- 
2.8.2



From vigneshr at ti.com  Wed May 18 23:47:30 2016
From: vigneshr at ti.com (Vignesh R)
Date: Thu, 19 May 2016 12:17:30 +0530
Subject: [PATCH 2/2] ARM: dts: am335x-icev2: Add DT node for TI PCA9536
In-Reply-To: <1463640450-16762-1-git-send-email-vigneshr@ti.com>
References: <1463640450-16762-1-git-send-email-vigneshr@ti.com>
Message-ID: <1463640450-16762-3-git-send-email-vigneshr@ti.com>

AM335x ICE board has a TI PCA9536 chip connected to I2C0 at address
0x41. Add DT entry for the same.

Signed-off-by: Vignesh R <vigneshr at ti.com>
---
 arch/arm/boot/dts/am335x-icev2.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/am335x-icev2.dts b/arch/arm/boot/dts/am335x-icev2.dts
index e271013e78a6..7d8b8fefdf08 100644
--- a/arch/arm/boot/dts/am335x-icev2.dts
+++ b/arch/arm/boot/dts/am335x-icev2.dts
@@ -206,6 +206,13 @@
 		gpio-controller;
 		#gpio-cells = <2>;
 	};
+
+	pca9536: gpio at 41 {
+		compatible = "ti,pca9536";
+		reg = <0x41>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
 };
 
 #include "tps65910.dtsi"
-- 
2.8.2



From sr at denx.de  Thu May 19 00:07:05 2016
From: sr at denx.de (Stefan Roese)
Date: Thu, 19 May 2016 09:07:05 +0200
Subject: [PATCH v9] spi: orion.c: Add direct access mode
Message-ID: <1463641625-15601-1-git-send-email-sr@denx.de>

This patch adds support for the direct access mode to the Orion SPI
driver which is used on the Marvell Armada based SoCs. In this direct
mode, all data written to (or read from) a specifically mapped MBus
window (linked to one SPI chip-select on one of the SPI controllers)
will be transferred directly to the SPI bus. Without the need to control
the SPI registers in between. This can improve the SPI transfer rate in
such cases.

Both, direct-read and -write mode are supported. But only the write
mode has been tested. This mode especially benefits from the SPI direct
mode, as the data bytes are written head-to-head to the SPI bus,
without any additional addresses.

One use-case for this direct write mode is, programming a FPGA bitstream
image into the FPGA connected to the SPI bus at maximum speed.

This mode is described in chapter "22.5.2 Direct Write to SPI" in the
Marvell Armada XP Functional Spec Datasheet.

Signed-off-by: Stefan Roese <sr at denx.de>
Cc: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
Cc: Gregory CLEMENT <gregory.clement at free-electrons.com>
Cc: Andrew Lunn <andrew at lunn.ch>
Acked-by: Arnd Bergmann <arnd at arndb.de>
Cc: Mark Brown <broonie at kernel.org>
---
v9:
- Use iowrite32_rep / iowrite8_rep instead of writesl / writesb
  to fix the compile introduced by this patch on
  linux-next build (x86_64 allmodconfig)

v8:
- Use "/ 4" instead of ">> 2" as suggested by Mark

v7:
- Changed tx function to only write the really intended number of
  bytes (drop DIV_ROUND_UP) as suggested by Arnd
- Added Arnd's Acked-by

v6:
- Switched from memcpy() to writesl() for the TX transfer.
- Only one page is mapped via ioremap as this is sufficient for
  the currently implemented simple TX transfer.
- Removed max_transfer_size() as its not needed with the current
  one page mapping that supports an unlimited amount of SPI data.
- Added a comment to the 'reg' description in the DT bindings
  documentation as suggested by Arnd.
- Changed 'reg' and 'ranges' to use '<' and '>' in this file.
- Changed size to 0xffffffff in this file.
- Added a small paragraph to the commit text, describing the
  possibility to support SPI-NOR & SPI-NAND devices via this
  direct access mode.

v5:
- Added some documentation for the direct mode to the orion-spi DT
  bindings document, including an example and a reference to the
  mbus DT bindings documentation.

v4:
- Add max_transfer_size()
- Fall back from direct-write mode to PIO mode when
  - transfer size is exceedeed
  - non-8bit transfers
- Restrict to direct-write mode for now. SPI direct read mode can
  be added later, when someone has a platform supporting this
  mode.

v3:
- Used static MBus windows again, as suggested by Arnd
- No new DT bindings needed for this. The MBus windows need to be
  configured in the 'reg' property of the SPI controller. This is
  done in a separate patch for the Armada platforms.
- The direct mapping is configured and enable by adding the
  specific MBus entry to the 'ranges' property of the 'soc' node
  in the board dts file.

v2:
- Use one MBus window for each SPI controller instead of one for
  for each SPI device. This MBus window is re-assigned, once the
  CS changes.
- Assert the CS over the entire message
- Don't restrict the direct access mode to only direct write mode
- Add check for max size before using memcpy()
- Remove spidev from DT bindings documentation

 .../devicetree/bindings/spi/spi-orion.txt          | 49 +++++++++++-
 drivers/spi/spi-orion.c                            | 88 ++++++++++++++++++++++
 2 files changed, 136 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-orion.txt b/Documentation/devicetree/bindings/spi/spi-orion.txt
index 98bc698..4f629cc 100644
--- a/Documentation/devicetree/bindings/spi/spi-orion.txt
+++ b/Documentation/devicetree/bindings/spi/spi-orion.txt
@@ -8,7 +8,15 @@ Required properties:
     - "marvell,armada-380-spi", for the Armada 38x SoCs
     - "marvell,armada-390-spi", for the Armada 39x SoCs
     - "marvell,armada-xp-spi", for the Armada XP SoCs
-- reg : offset and length of the register set for the device
+- reg : offset and length of the register set for the device.
+	This property can optionally have additional entries to configure
+	the SPI direct access mode that some of the Marvell SoCs support
+	additionally to the normal indirect access (PIO) mode. The values
+	for the MBus "target" and "attribute" are defined in the Marvell
+	SoC "Functional Specifications" Manual in the chapter "Marvell
+	Core Processor Address Decoding".
+	The eight register sets following the control registers refer to
+	chip-select lines 0 through 7 respectively.
 - cell-index : Which of multiple SPI controllers is this.
 Optional properties:
 - interrupts : Is currently not used.
@@ -23,3 +31,42 @@ Example:
 	       interrupts = <23>;
 	       status = "disabled";
        };
+
+Example with SPI direct mode support (optionally):
+	spi0: spi at 10600 {
+		compatible = "marvell,orion-spi";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cell-index = <0>;
+		reg = <MBUS_ID(0xf0, 0x01) 0x10600 0x28>, /* control */
+		      <MBUS_ID(0x01, 0x1e) 0 0xffffffff>, /* CS0 */
+		      <MBUS_ID(0x01, 0x5e) 0 0xffffffff>, /* CS1 */
+		      <MBUS_ID(0x01, 0x9e) 0 0xffffffff>, /* CS2 */
+		      <MBUS_ID(0x01, 0xde) 0 0xffffffff>, /* CS3 */
+		      <MBUS_ID(0x01, 0x1f) 0 0xffffffff>, /* CS4 */
+		      <MBUS_ID(0x01, 0x5f) 0 0xffffffff>, /* CS5 */
+		      <MBUS_ID(0x01, 0x9f) 0 0xffffffff>, /* CS6 */
+		      <MBUS_ID(0x01, 0xdf) 0 0xffffffff>; /* CS7 */
+		interrupts = <23>;
+		status = "disabled";
+	};
+
+To enable the direct mode, the board specific 'ranges' property in the
+'soc' node needs to add the entries for the desired SPI controllers
+and its chip-selects that are used in the direct mode instead of PIO
+mode. Here an example for this (SPI controller 0, device 1 and SPI
+controller 1, device 2 are used in direct mode. All other SPI device
+are used in the default indirect (PIO) mode):
+	soc {
+		/*
+		 * Enable the SPI direct access by configuring an entry
+		 * here in the board-specific ranges property
+		 */
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000>,	/* internal regs */
+			 <MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>,	/* BootROM       */
+			 <MBUS_ID(0x01, 0x5e) 0 0 0xf1100000 0x10000>,	/* SPI0-DEV1 */
+			 <MBUS_ID(0x01, 0x9a) 0 0 0xf1110000 0x10000>;	/* SPI1-DEV2 */
+
+For further information on the MBus bindings, please see the MBus
+DT documentation:
+Documentation/devicetree/bindings/bus/mvebu-mbus.txt
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index a87cfd4..d0d9c86 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/clk.h>
 #include <linux/sizes.h>
@@ -43,6 +44,9 @@
 #define ORION_SPI_INT_CAUSE_REG		0x10
 #define ORION_SPI_TIMING_PARAMS_REG	0x18
 
+/* Register for the "Direct Mode" */
+#define SPI_DIRECT_WRITE_CONFIG_REG	0x20
+
 #define ORION_SPI_TMISO_SAMPLE_MASK	(0x3 << 6)
 #define ORION_SPI_TMISO_SAMPLE_1	(1 << 6)
 #define ORION_SPI_TMISO_SAMPLE_2	(2 << 6)
@@ -78,11 +82,18 @@ struct orion_spi_dev {
 	bool			is_errata_50mhz_ac;
 };
 
+struct orion_direct_acc {
+	void __iomem		*vaddr;
+	u32			size;
+};
+
 struct orion_spi {
 	struct spi_master	*master;
 	void __iomem		*base;
 	struct clk              *clk;
 	const struct orion_spi_dev *devdata;
+
+	struct orion_direct_acc	direct_access[ORION_NUM_CHIPSELECTS];
 };
 
 static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
@@ -372,10 +383,39 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
 {
 	unsigned int count;
 	int word_len;
+	struct orion_spi *orion_spi;
+	int cs = spi->chip_select;
 
 	word_len = spi->bits_per_word;
 	count = xfer->len;
 
+	orion_spi = spi_master_get_devdata(spi->master);
+
+	/*
+	 * Use SPI direct write mode if base address is available. Otherwise
+	 * fall back to PIO mode for this transfer.
+	 */
+	if ((orion_spi->direct_access[cs].vaddr) && (xfer->tx_buf) &&
+	    (word_len == 8)) {
+		unsigned int cnt = count / 4;
+		unsigned int rem = count % 4;
+
+		/*
+		 * Send the TX-data to the SPI device via the direct
+		 * mapped address window
+		 */
+		iowrite32_rep(orion_spi->direct_access[cs].vaddr,
+			      xfer->tx_buf, cnt);
+		if (rem) {
+			u32 *buf = (u32 *)xfer->tx_buf;
+
+			iowrite8_rep(orion_spi->direct_access[cs].vaddr,
+				     &buf[cnt], rem);
+		}
+
+		return count;
+	}
+
 	if (word_len == 8) {
 		const u8 *tx = xfer->tx_buf;
 		u8 *rx = xfer->rx_buf;
@@ -425,6 +465,10 @@ static int orion_spi_reset(struct orion_spi *orion_spi)
 {
 	/* Verify that the CS is deasserted */
 	orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+
+	/* Don't deassert CS between the direct mapped SPI transfers */
+	writel(0, spi_reg(orion_spi, SPI_DIRECT_WRITE_CONFIG_REG));
+
 	return 0;
 }
 
@@ -504,6 +548,7 @@ static int orion_spi_probe(struct platform_device *pdev)
 	struct resource *r;
 	unsigned long tclk_hz;
 	int status = 0;
+	struct device_node *np;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(*spi));
 	if (master == NULL) {
@@ -576,6 +621,49 @@ static int orion_spi_probe(struct platform_device *pdev)
 		goto out_rel_clk;
 	}
 
+	/* Scan all SPI devices of this controller for direct mapped devices */
+	for_each_available_child_of_node(pdev->dev.of_node, np) {
+		u32 cs;
+
+		/* Get chip-select number from the "reg" property */
+		status = of_property_read_u32(np, "reg", &cs);
+		if (status) {
+			dev_err(&pdev->dev,
+				"%s has no valid 'reg' property (%d)\n",
+				np->full_name, status);
+			status = 0;
+			continue;
+		}
+
+		/*
+		 * Check if an address is configured for this SPI device. If
+		 * not, the MBus mapping via the 'ranges' property in the 'soc'
+		 * node is not configured and this device should not use the
+		 * direct mode. In this case, just continue with the next
+		 * device.
+		 */
+		status = of_address_to_resource(pdev->dev.of_node, cs + 1, r);
+		if (status)
+			continue;
+
+		/*
+		 * Only map one page for direct access. This is enough for the
+		 * simple TX transfer which only writes to the first word.
+		 * This needs to get extended for the direct SPI-NOR / SPI-NAND
+		 * support, once this gets implemented.
+		 */
+		spi->direct_access[cs].vaddr = devm_ioremap(&pdev->dev,
+							    r->start,
+							    PAGE_SIZE);
+		if (IS_ERR(spi->direct_access[cs].vaddr)) {
+			status = PTR_ERR(spi->direct_access[cs].vaddr);
+			goto out_rel_clk;
+		}
+		spi->direct_access[cs].size = PAGE_SIZE;
+
+		dev_info(&pdev->dev, "CS%d configured for direct access\n", cs);
+	}
+
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
-- 
2.8.2



From peter.ujfalusi at ti.com  Thu May 19 01:02:43 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Thu, 19 May 2016 11:02:43 +0300
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <573D57DA.20900@ti.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
 <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com> <573D57DA.20900@ti.com>
Message-ID: <2d328902-d59e-4497-38fa-5bc3ec98180f@ti.com>

On 05/19/2016 09:06 AM, Kishon Vijay Abraham I wrote:
> Hi Peter,
> 
> On Wednesday 18 May 2016 03:54 PM, Peter Ujfalusi wrote:
>> On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
>>> omap hsmmc host controller has ADMA2 feature. Enable it here
>>> for better read and write throughput. Add a new dt binding
>>> "ti,use_adma" to enable ADMA2.
>>>
>>> Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
>>> ---
>>>  .../devicetree/bindings/mmc/ti-omap-hsmmc.txt      |    1 +
>>>  drivers/mmc/host/omap_hsmmc.c                      |  320 ++++++++++++++++----
>>>  include/linux/platform_data/hsmmc-omap.h           |    1 +
>>>  3 files changed, 256 insertions(+), 66 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> index 74166a0..eb5ceec2 100644
>>> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> @@ -28,6 +28,7 @@ specifier is required.
>>>  dma-names: List of DMA request names. These strings correspond
>>>  1:1 with the DMA specifiers listed in dmas. The string naming is
>>>  to be "rx" and "tx" for RX and TX DMA requests, respectively.
>>> +ti,use_adma: enable adma2 feature
>>
>> Do we have use case when you want to fall back to generic DMA instead of aDMA2?
>> IMHO if the driver supports aDMA2, it is going to use it instead of the
>> generic s/eDMA.
>> What I mean is:
>> the driver implements the aDMA2 support.
>> if the IP has support for aDMA2, then it is going to use it, otherwise it will
>> use the generic DMA.
> 
> hmm.. how will the driver know if the IP has support for aDMA2. Using dt
> binding is one way. Using MMCHS_HL_HWINFO is another way but then the register
> offsets in omap_hsmmc driver has to be modified for omap4+.

I remember Felipe saying that MMCHS_HL_HWINFO is not reliable for some reason?
But in any case it would be better IMHO if we query the HW for Master DMA
support and if it is available we will use it.

If it is really the case that MMCHS_HL_HWINFO is not reliable, then probably
have a flag for the MMC/SD phandle saying that ti,master_dma_supported to
indicate that it is capable has ADMA support also.

-- 
P?ter


From david.wu at rock-chips.com  Thu May 19 01:09:13 2016
From: david.wu at rock-chips.com (David.Wu)
Date: Thu, 19 May 2016 16:09:13 +0800
Subject: [PATCH] arm64: dts: rockchip: add i2c nodes for rk3399
In-Reply-To: <1463429371-10950-1-git-send-email-dianders@chromium.org>
References: <1463429371-10950-1-git-send-email-dianders@chromium.org>
Message-ID: <466d93c8-e405-51d7-401d-3d7cbd8560cf@rock-chips.com>

Hi Doug,

? 2016/5/17 4:09, Douglas Anderson ??:
> From: David Wu <david.wu at rock-chips.com>
>
> We've got 9 (count em!) i2c controllers on rk3399, some of which are in
> the PMU power domain and some of which are normal peripherals.  Add them
> all to the main rk3399 dtsi file so future patches can turn them on in
> the board dts files.
>
> Note: by default we try to set the i2c clock rate to 200 MHz so that we
> can achieve good i2c functional clock rates.  200 MHz gives us the
> ability to make very close to 100 kHz / 400 kHz / 1 MHz rates.  If
> boards want to tune clock rates further they can always override.
> Possibly boards could want to tune this if:
> - they wanted to save an infinitesimal amount of power and they knew
>   their i2c bus was slow anyway.  Since we gate the functional clock
>   when the i2c bus is not active, power savings would only be while i2c
>   transfers were happening and probably won't be very big anyway.
> - they wanted to eek out a bit more speed by carefully tuning the source
>   clock to make divisions work out perfectly, accounting for the rise /
>   fall time measured on an actual board.
>
> Note also that we still request 200 MHz for the PMU i2c busses even
> though we expect that we won't make that exactly (currently PPLL is 676
> MHz which gives us 169 MHz).

Yeah, this looks like you got all the right bits in the right places and 
didn't mess it up.
This patch is looking really good to me, thanks for doing it.

>
> Signed-off-by: David Wu <david.wu at rock-chips.com>
> Signed-off-by: Jianqun Xu <jay.xu at rock-chips.com>
> [dianders: wrote desc; put in assigned-clocks; reordered nodes]
> Signed-off-by: Douglas Anderson <dianders at chromium.org>
> ---
> Note: this patch is based upon David Wu's patch series to add rk3399
> support to i2c-rk3x.c and shouldn't land until at least device tree
> bindings land.
>
>  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 144 +++++++++++++++++++++++++++++++
>  1 file changed, 144 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> index 46f325a143b0..753a91728b4c 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -54,6 +54,15 @@
>  	#size-cells = <2>;
>
>  	aliases {
> +		i2c0 = &i2c0;
> +		i2c1 = &i2c1;
> +		i2c2 = &i2c2;
> +		i2c3 = &i2c3;
> +		i2c4 = &i2c4;
> +		i2c5 = &i2c5;
> +		i2c6 = &i2c6;
> +		i2c7 = &i2c7;
> +		i2c8 = &i2c8;
>  		serial0 = &uart0;
>  		serial1 = &uart1;
>  		serial2 = &uart2;
> @@ -272,6 +281,96 @@
>  		};
>  	};
>
> +	i2c1: i2c at ff110000 {
> +		compatible = "rockchip,rk3399-i2c";
> +		reg = <0x0 0xff110000 0x0 0x1000>;
> +		assigned-clocks = <&cru SCLK_I2C1>;
> +		assigned-clock-rates = <200000000>;
> +		clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>;
> +		clock-names = "i2c", "pclk";
> +		interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&i2c1_xfer>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		status = "disabled";
> +	};
> +
> +	i2c2: i2c at ff120000 {
> +		compatible = "rockchip,rk3399-i2c";
> +		reg = <0x0 0xff120000 0x0 0x1000>;
> +		assigned-clocks = <&cru SCLK_I2C2>;
> +		assigned-clock-rates = <200000000>;
> +		clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>;
> +		clock-names = "i2c", "pclk";
> +		interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&i2c2_xfer>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		status = "disabled";
> +	};
> +
> +	i2c3: i2c at ff130000 {
> +		compatible = "rockchip,rk3399-i2c";
> +		reg = <0x0 0xff130000 0x0 0x1000>;
> +		assigned-clocks = <&cru SCLK_I2C3>;
> +		assigned-clock-rates = <200000000>;
> +		clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>;
> +		clock-names = "i2c", "pclk";
> +		interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&i2c3_xfer>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		status = "disabled";
> +	};
> +
> +	i2c5: i2c at ff140000 {
> +		compatible = "rockchip,rk3399-i2c";
> +		reg = <0x0 0xff140000 0x0 0x1000>;
> +		assigned-clocks = <&cru SCLK_I2C5>;
> +		assigned-clock-rates = <200000000>;
> +		clocks = <&cru SCLK_I2C5>, <&cru PCLK_I2C5>;
> +		clock-names = "i2c", "pclk";
> +		interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&i2c5_xfer>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		status = "disabled";
> +	};
> +
> +	i2c6: i2c at ff150000 {
> +		compatible = "rockchip,rk3399-i2c";
> +		reg = <0x0 0xff150000 0x0 0x1000>;
> +		assigned-clocks = <&cru SCLK_I2C6>;
> +		assigned-clock-rates = <200000000>;
> +		clocks = <&cru SCLK_I2C6>, <&cru PCLK_I2C6>;
> +		clock-names = "i2c", "pclk";
> +		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&i2c6_xfer>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		status = "disabled";
> +	};
> +
> +	i2c7: i2c at ff160000 {
> +		compatible = "rockchip,rk3399-i2c";
> +		reg = <0x0 0xff160000 0x0 0x1000>;
> +		assigned-clocks = <&cru SCLK_I2C7>;
> +		assigned-clock-rates = <200000000>;
> +		clocks = <&cru SCLK_I2C7>, <&cru PCLK_I2C7>;
> +		clock-names = "i2c", "pclk";
> +		interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&i2c7_xfer>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		status = "disabled";
> +	};
> +
>  	uart0: serial at ff180000 {
>  		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
>  		reg = <0x0 0xff180000 0x0 0x100>;
> @@ -420,6 +519,51 @@
>  		status = "disabled";
>  	};
>
> +	i2c0: i2c at ff3c0000 {
> +		compatible = "rockchip,rk3399-i2c";
> +		reg = <0x0 0xff3c0000 0x0 0x1000>;
> +		assigned-clocks = <&pmucru SCLK_I2C0_PMU>;
> +		assigned-clock-rates = <200000000>;
> +		clocks = <&pmucru SCLK_I2C0_PMU>, <&pmucru PCLK_I2C0_PMU>;
> +		clock-names = "i2c", "pclk";
> +		interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&i2c0_xfer>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		status = "disabled";
> +	};
> +
> +	i2c4: i2c at ff3d0000 {
> +		compatible = "rockchip,rk3399-i2c";
> +		reg = <0x0 0xff3d0000 0x0 0x1000>;
> +		assigned-clocks = <&pmucru SCLK_I2C4_PMU>;
> +		assigned-clock-rates = <200000000>;
> +		clocks = <&pmucru SCLK_I2C4_PMU>, <&pmucru PCLK_I2C4_PMU>;
> +		clock-names = "i2c", "pclk";
> +		interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&i2c4_xfer>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		status = "disabled";
> +	};
> +
> +	i2c8: i2c at ff3e0000 {
> +		compatible = "rockchip,rk3399-i2c";
> +		reg = <0x0 0xff3e0000 0x0 0x1000>;
> +		assigned-clocks = <&pmucru SCLK_I2C8_PMU>;
> +		assigned-clock-rates = <200000000>;
> +		clocks = <&pmucru SCLK_I2C8_PMU>, <&pmucru PCLK_I2C8_PMU>;
> +		clock-names = "i2c", "pclk";
> +		interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&i2c8_xfer>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		status = "disabled";
> +	};
> +
>  	pwm0: pwm at ff420000 {
>  		compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
>  		reg = <0x0 0xff420000 0x0 0x10>;
>



From peter.ujfalusi at ti.com  Thu May 19 01:07:28 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Thu, 19 May 2016 11:07:28 +0300
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <20160518193028.GT5995@atomide.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
 <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com>
 <20160518193028.GT5995@atomide.com>
Message-ID: <0d463add-9fa5-a768-2ba6-34c4126c7817@ti.com>

On 05/18/2016 10:30 PM, Tony Lindgren wrote:
> * Peter Ujfalusi <peter.ujfalusi at ti.com> [160518 03:26]:
>> On 05/18/16 11:45, Kishon Vijay Abraham I wrote:
>>> omap hsmmc host controller has ADMA2 feature. Enable it here
>>> for better read and write throughput. Add a new dt binding
>>> "ti,use_adma" to enable ADMA2.
>>>
>>> Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
>>> ---
>>>  .../devicetree/bindings/mmc/ti-omap-hsmmc.txt      |    1 +
>>>  drivers/mmc/host/omap_hsmmc.c                      |  320 ++++++++++++++++----
>>>  include/linux/platform_data/hsmmc-omap.h           |    1 +
>>>  3 files changed, 256 insertions(+), 66 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> index 74166a0..eb5ceec2 100644
>>> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
>>> @@ -28,6 +28,7 @@ specifier is required.
>>>  dma-names: List of DMA request names. These strings correspond
>>>  1:1 with the DMA specifiers listed in dmas. The string naming is
>>>  to be "rx" and "tx" for RX and TX DMA requests, respectively.
>>> +ti,use_adma: enable adma2 feature
>>
>> Do we have use case when you want to fall back to generic DMA instead of aDMA2?
> 
> Yes my guess is that PM runtime breaks with these currently..
> 
>> IMHO if the driver supports aDMA2, it is going to use it instead of the
>> generic s/eDMA.
>> What I mean is:
>> the driver implements the aDMA2 support.
>> if the IP has support for aDMA2, then it is going to use it, otherwise it will
>> use the generic DMA.
> 
> Ideally the adma support would be a separate loadable module,
> similar how the cppi41dma is a child of the OTG controller.

The Master DMA is part of the hsmmc IP block. If the same ADMA module is
present on other IPs it might be beneficial to have a helper library to handle
it (allocating the descriptor pool, wrinting, updating descriptors, etc).

> That way the systems wanting to use adma can just specify it
> in the binding, and adma PM runtime support can be added later
> on.
> 
> Of course this won't work if the adma registers are sprinkled
> within the MMC controller registers..
> 
> Regards,
> 
> Tony
> 


-- 
P?ter


From peter.ujfalusi at ti.com  Thu May 19 01:25:06 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Thu, 19 May 2016 11:25:06 +0300
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <1463561115-31798-3-git-send-email-kishon@ti.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
Message-ID: <7e9c3486-88c5-a61d-0629-936b428ad959@ti.com>

On 05/18/2016 11:45 AM, Kishon Vijay Abraham I wrote:
> omap hsmmc host controller has ADMA2 feature. Enable it here
> for better read and write throughput. Add a new dt binding
> "ti,use_adma" to enable ADMA2.
> 
> Signed-off-by: Kishon Vijay Abraham I <kishon at ti.com>
> ---
>  .../devicetree/bindings/mmc/ti-omap-hsmmc.txt      |    1 +
>  drivers/mmc/host/omap_hsmmc.c                      |  320 ++++++++++++++++----
>  include/linux/platform_data/hsmmc-omap.h           |    1 +
>  3 files changed, 256 insertions(+), 66 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> index 74166a0..eb5ceec2 100644
> --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
> @@ -28,6 +28,7 @@ specifier is required.
>  dma-names: List of DMA request names. These strings correspond
>  1:1 with the DMA specifiers listed in dmas. The string naming is
>  to be "rx" and "tx" for RX and TX DMA requests, respectively.
> +ti,use_adma: enable adma2 feature
>  
>  Examples:
>  
> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> index cc916d5..b4a7d18 100644
> --- a/drivers/mmc/host/omap_hsmmc.c
> +++ b/drivers/mmc/host/omap_hsmmc.c
> @@ -66,6 +66,8 @@
>  #define OMAP_HSMMC_ISE		0x0138
>  #define OMAP_HSMMC_AC12		0x013C
>  #define OMAP_HSMMC_CAPA		0x0140
> +#define OMAP_HSMMC_ADMAES	0x0154
> +#define OMAP_HSMMC_ADMASAL	0x0158
>  
>  #define VS18			(1 << 26)
>  #define VS30			(1 << 25)
> @@ -76,6 +78,7 @@
>  #define SDVS_MASK		0x00000E00
>  #define SDVSCLR			0xFFFFF1FF
>  #define SDVSDET			0x00000400
> +#define DMA_SELECT		(2 << 3)
>  #define AUTOIDLE		0x1
>  #define SDBP			(1 << 8)
>  #define DTO			0xe
> @@ -97,6 +100,7 @@
>  #define FOUR_BIT		(1 << 1)
>  #define HSPE			(1 << 2)
>  #define IWE			(1 << 24)
> +#define DMA_MASTER		(1 << 20)
>  #define DDR			(1 << 19)
>  #define CLKEXTFREE		(1 << 16)
>  #define CTPL			(1 << 11)
> @@ -127,10 +131,11 @@
>  #define DCRC_EN			(1 << 21)
>  #define DEB_EN			(1 << 22)
>  #define ACE_EN			(1 << 24)
> +#define ADMAE_EN		(1 << 24)
>  #define CERR_EN			(1 << 28)
>  #define BADA_EN			(1 << 29)
>  
> -#define INT_EN_MASK (BADA_EN | CERR_EN | ACE_EN | DEB_EN | DCRC_EN |\
> +#define INT_EN_MASK (BADA_EN | CERR_EN | ADMAE_EN | ACE_EN | DEB_EN | DCRC_EN |\
>  		DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \
>  		BRR_EN | BWR_EN | TC_EN | CC_EN)
>  
> @@ -168,6 +173,25 @@
>  #define OMAP_HSMMC_WRITE(base, reg, val) \
>  	__raw_writel((val), (base) + OMAP_HSMMC_##reg)
>  
> +struct omap_hsmmc_adma_desc {
> +	u8 attr;
> +	u8 reserved;
> +	u16 len;
> +	u32 addr;
> +} __packed;
> +
> +#define ADMA_MAX_LEN			65532
> +
> +/* Decriptor table defines */
> +#define ADMA_DESC_ATTR_VALID		BIT(0)
> +#define ADMA_DESC_ATTR_END		BIT(1)
> +#define ADMA_DESC_ATTR_INT		BIT(2)
> +#define ADMA_DESC_ATTR_ACT1		BIT(4)
> +#define ADMA_DESC_ATTR_ACT2		BIT(5)
> +
> +#define ADMA_DESC_TRANSFER_DATA		ADMA_DESC_ATTR_ACT2
> +#define ADMA_DESC_LINK_DESC	(ADMA_DESC_ATTR_ACT1 | ADMA_DESC_ATTR_ACT2)
> +
>  struct omap_hsmmc_next {
>  	unsigned int	dma_len;
>  	s32		cookie;
> @@ -213,6 +237,9 @@ struct omap_hsmmc_host {
>  	struct omap_hsmmc_next	next_data;
>  	struct	omap_hsmmc_platform_data	*pdata;
>  
> +	struct omap_hsmmc_adma_desc *adma_desc_table;
> +	dma_addr_t              adma_desc_table_addr;
> +
>  	/* return MMC cover switch state, can be NULL if not supported.
>  	 *
>  	 * possible return values:
> @@ -951,6 +978,19 @@ static struct dma_chan *omap_hsmmc_get_dma_chan(struct omap_hsmmc_host *host,
>  	return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan;
>  }
>  
> +static void omap_hsmmc_adma_cleanup(struct omap_hsmmc_host *host)
> +{
> +	u32 val;
> +
> +	val = OMAP_HSMMC_READ(host->base, HCTL);
> +	val &= ~DMA_SELECT;
> +	OMAP_HSMMC_WRITE(host->base, HCTL, val);
> +
> +	val = OMAP_HSMMC_READ(host->base, CON);
> +	val &= ~DMA_MASTER;
> +	OMAP_HSMMC_WRITE(host->base, CON, val);
> +}
> +
>  static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_request *mrq)
>  {
>  	int dma_ch;
> @@ -963,8 +1003,11 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
>  
>  	omap_hsmmc_disable_irq(host);
>  	/* Do not complete the request if DMA is still in progress */
> -	if (mrq->data && dma_ch != -1)
> +	if (host->pdata->controller_flags == OMAP_HSMMC_USE_ADMA)

host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA

and I would probably name the flag to OMAP_HSMMC_MASTER_DMA_SUPPORTED

> +		omap_hsmmc_adma_cleanup(host);
> +	else if (mrq->data && dma_ch != -1)
>  		return;
> +
>  	host->mrq = NULL;
>  	mmc_request_done(host->mmc, mrq);
>  	pm_runtime_mark_last_busy(host->dev);
> @@ -1052,15 +1095,22 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
>  	host->dma_ch = -1;
>  	spin_unlock_irqrestore(&host->irq_lock, flags);
>  
> -	if (dma_ch != -1) {
> -		struct dma_chan *chan = omap_hsmmc_get_dma_chan(host, host->data);
> -
> -		dmaengine_terminate_all(chan);
> -		dma_unmap_sg(chan->device->dev,
> -			host->data->sg, host->data->sg_len,
> +	if (!(host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)) {

it might be better to use the same order in the driver for Master and Slave
DMA cases:

if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA) {
	/* Master DMA case */
} else {
	/* Slave DMA case */
}

It will make the driver easier to read.

> +		if (dma_ch != -1) {
> +			struct dma_chan *chan = omap_hsmmc_get_dma_chan(host,
> +								host->data);
> +			dmaengine_terminate_all(chan);
> +			dma_unmap_sg(chan->device->dev,
> +				     host->data->sg, host->data->sg_len,
>  			omap_hsmmc_get_dma_dir(host, host->data));
>  
> +			host->data->host_cookie = 0;
> +		}
> +	} else {
> +		dma_unmap_sg(host->dev, host->data->sg, host->data->sg_len,
> +			     omap_hsmmc_get_dma_dir(host, host->data));
>  		host->data->host_cookie = 0;
> +
>  	}
>  	host->data = NULL;
>  }
> @@ -1191,6 +1241,14 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
>  			}
>  			dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12);
>  		}
> +
> +		if (status & ADMAE_EN) {
> +			u32 val;
> +
> +			val = OMAP_HSMMC_READ(host->base, ADMAES);
> +			dev_dbg(mmc_dev(host->mmc), "ADMA error status: 0x%x\n",
> +				val);
> +		}
>  	}
>  
>  	OMAP_HSMMC_WRITE(host->base, STAT, status);
> @@ -1378,6 +1436,7 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
>  				       struct dma_chan *chan)
>  {
>  	int dma_len;
> +	struct device *dev;
>  
>  	if (!next && data->host_cookie &&
>  	    data->host_cookie != host->next_data.cookie) {
> @@ -1387,9 +1446,14 @@ static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
>  		data->host_cookie = 0;
>  	}
>  
> +	if (chan)
> +		dev = chan->device->dev;
> +	else
> +		dev = mmc_dev(host->mmc);
> +
>  	/* Check if next job is already prepared */
>  	if (next || data->host_cookie != host->next_data.cookie) {
> -		dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len,
> +		dma_len = dma_map_sg(dev, data->sg, data->sg_len,
>  				     omap_hsmmc_get_dma_dir(host, data));
>  
>  	} else {
> @@ -1516,6 +1580,7 @@ static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host)
>  {
>  	struct mmc_request *req = host->mrq;
>  	struct dma_chan *chan;
> +	int val;
>  
>  	if (!req->data)
>  		return;
> @@ -1523,10 +1588,66 @@ static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host)
>  				| (req->data->blocks << 16));
>  	set_data_timeout(host, req->data->timeout_ns,
>  				req->data->timeout_clks);
> -	chan = omap_hsmmc_get_dma_chan(host, req->data);
> -	dma_async_issue_pending(chan);
> +
> +	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA) {
> +		val = OMAP_HSMMC_READ(host->base, HCTL);
> +		val |= DMA_SELECT;
> +		OMAP_HSMMC_WRITE(host->base, HCTL, val);
> +
> +		val = OMAP_HSMMC_READ(host->base, CON);
> +		val |= DMA_MASTER;
> +		OMAP_HSMMC_WRITE(host->base, CON, val);
> +
> +		OMAP_HSMMC_WRITE(host->base, ADMASAL,
> +				 (u32)host->adma_desc_table_addr);
> +	} else {
> +		chan = omap_hsmmc_get_dma_chan(host, req->data);
> +		dma_async_issue_pending(chan);
> +	}
> +}
> +
> +static int omap_hsmmc_write_adma_desc(struct omap_hsmmc_host *host, void *desc,
> +				      dma_addr_t addr, u16 len, u8 attr)
> +{
> +	struct omap_hsmmc_adma_desc *dma_desc = desc;
> +
> +	dma_desc->len = len;
> +	dma_desc->addr = (u32)addr;
> +	dma_desc->reserved = 0;
> +	dma_desc->attr = attr;
> +
> +	return 0;
>  }
>  
> +static int omap_hsmmc_setup_adma_transfer(struct omap_hsmmc_host *host,
> +					  struct mmc_request *req)
> +{
> +	struct mmc_data *data = req->data;
> +	struct scatterlist *sg;
> +	int i;
> +	int len;
> +	int ret;
> +	dma_addr_t addr;
> +	struct omap_hsmmc_adma_desc *dma_desc;
> +
> +	ret = omap_hsmmc_pre_dma_transfer(host, data, NULL, NULL);
> +	if (ret)
> +		return ret;
> +
> +	dma_desc = host->adma_desc_table;
> +	for_each_sg(data->sg, sg, host->dma_len, i) {
> +		addr = sg_dma_address(sg);
> +		len = sg_dma_len(sg);
> +		WARN_ON(len > ADMA_MAX_LEN);
> +		omap_hsmmc_write_adma_desc(host, dma_desc, addr, len,
> +					   ADMA_DESC_ATTR_VALID |
> +					   ADMA_DESC_TRANSFER_DATA);
> +		dma_desc++;
> +	}
> +	omap_hsmmc_write_adma_desc(host, dma_desc, 0, 0, ADMA_DESC_ATTR_END);
> +
> +	return 0;
> +}

Would be nice to group the ADMA functions in one section, not scattering it
around the driver.

>  /*
>   * Configure block length for MMC/SD cards and initiate the transfer.
>   */
> @@ -1547,10 +1668,18 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
>  		return 0;
>  	}
>  
> -	ret = omap_hsmmc_setup_dma_transfer(host, req);
> -	if (ret != 0) {
> -		dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
> -		return ret;
> +	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA) {
> +		ret = omap_hsmmc_setup_adma_transfer(host, req);
> +		if (ret != 0) {
> +			dev_err(mmc_dev(host->mmc), "MMC adma setup failed\n");
> +			return ret;
> +		}
> +	} else {
> +		ret = omap_hsmmc_setup_dma_transfer(host, req);
> +		if (ret != 0) {
> +			dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
> +			return ret;

the error checking can go outside

> +		}
>  	}
>  	return 0;

	if (ret != 0)
		dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
	return ret;

if compiler complains about ret not beeing initialized
int rer = 0;

>  }
> @@ -1560,11 +1689,18 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
>  {
>  	struct omap_hsmmc_host *host = mmc_priv(mmc);
>  	struct mmc_data *data = mrq->data;
> +	struct device *dev;
> +	struct dma_chan *c;
>  
>  	if (data->host_cookie) {
> -		struct dma_chan *c = omap_hsmmc_get_dma_chan(host, data);
> +		if (!(host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)) {
> +			c = omap_hsmmc_get_dma_chan(host, mrq->data);
> +			dev = c->device->dev;
> +		} else {
> +			dev = mmc_dev(mmc);
> +		}
>  
> -		dma_unmap_sg(c->device->dev, data->sg, data->sg_len,
> +		dma_unmap_sg(dev, data->sg, data->sg_len,
>  			     omap_hsmmc_get_dma_dir(host, data));
>  		data->host_cookie = 0;
>  	}
> @@ -1574,13 +1710,15 @@ static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
>  			       bool is_first_req)
>  {
>  	struct omap_hsmmc_host *host = mmc_priv(mmc);
> +	struct dma_chan *c = NULL;
>  
>  	if (mrq->data->host_cookie) {
>  		mrq->data->host_cookie = 0;
>  		return ;
>  	}
>  
> -	struct dma_chan *c = omap_hsmmc_get_dma_chan(host, mrq->data);
> +	if (!(host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA))
> +		c = omap_hsmmc_get_dma_chan(host, mrq->data);
>  
>  	if (omap_hsmmc_pre_dma_transfer(host, mrq->data,
>  					&host->next_data, c))
> @@ -1967,6 +2105,9 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
>  	if (of_find_property(np, "ti,dual-volt", NULL))
>  		pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT;
>  
> +	if (of_find_property(np, "ti,use_adma", NULL))
> +		pdata->controller_flags |= OMAP_HSMMC_USE_ADMA;
> +
>  	pdata->gpio_cd = -EINVAL;
>  	pdata->gpio_cod = -EINVAL;
>  	pdata->gpio_wp = -EINVAL;
> @@ -1992,6 +2133,84 @@ static inline struct omap_hsmmc_platform_data
>  }
>  #endif
>  
> +static int omap_hsmmc_adma_init(struct omap_hsmmc_host *host)
> +{
> +	struct mmc_host *mmc = host->mmc;
> +
> +	host->adma_desc_table = dma_alloc_coherent(host->dev, mmc->max_segs + 1,
> +						   &host->adma_desc_table_addr,
> +						   GFP_KERNEL);
> +	if (!host->adma_desc_table) {
> +		dev_err(host->dev, "failed to allocate adma desc table\n");
> +		return -ENOMEM;

Fall back to Slave DMA?

> +	}
> +
> +	return 0;
> +}
> +
> +static void omap_hsmmc_adma_exit(struct omap_hsmmc_host *host)
> +{
> +	struct mmc_host *mmc = host->mmc;
> +
> +	dma_free_coherent(host->dev, mmc->max_segs + 1,
> +			  host->adma_desc_table, host->adma_desc_table_addr);
> +}
> +
> +static int omap_hsmmc_dma_init(struct omap_hsmmc_host *host)
> +{
> +	dma_cap_mask_t mask;
> +	unsigned int tx_req, rx_req;
> +	struct resource *res;
> +	struct platform_device *pdev = to_platform_device(host->dev);
> +
> +	dma_cap_zero(mask);
> +	dma_cap_set(DMA_SLAVE, mask);
> +
> +	if (!pdev->dev.of_node) {
> +		res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
> +		if (!res) {
> +			dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
> +			return -ENXIO;
> +		}
> +		tx_req = res->start;
> +
> +		res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
> +		if (!res) {
> +			dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
> +			return -ENXIO;
> +		}
> +		rx_req = res->start;
> +	}
> +
> +	host->rx_chan =
> +		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> +						 &rx_req, &pdev->dev, "rx");
> +
> +	if (!host->rx_chan) {
> +		dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
> +		return -ENXIO;
> +	}
> +
> +	host->tx_chan =
> +		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> +						 &tx_req, &pdev->dev, "tx");
> +
> +	if (!host->tx_chan) {
> +		dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
> +		return -ENXIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static void omap_hsmmc_dma_exit(struct omap_hsmmc_host *host)
> +{
> +	if (host->tx_chan)
> +		dma_release_channel(host->tx_chan);
> +	if (host->rx_chan)
> +		dma_release_channel(host->rx_chan);
> +}
> +
>  static int omap_hsmmc_probe(struct platform_device *pdev)
>  {
>  	struct omap_hsmmc_platform_data *pdata = pdev->dev.platform_data;
> @@ -2000,8 +2219,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>  	struct resource *res;
>  	int ret, irq;
>  	const struct of_device_id *match;
> -	dma_cap_mask_t mask;
> -	unsigned tx_req, rx_req;
>  	const struct omap_mmc_of_data *data;
>  	void __iomem *base;
>  
> @@ -2114,7 +2331,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>  	mmc->max_blk_size = 512;       /* Block Length at max can be 1024 */
>  	mmc->max_blk_count = 0xFFFF;    /* No. of Blocks is 16 bits */
>  	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
> -	mmc->max_seg_size = mmc->max_req_size;
> +	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> +		mmc->max_seg_size = ADMA_MAX_LEN;
> +	else
> +		mmc->max_seg_size = mmc->max_req_size;
>  
>  	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
>  		     MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
> @@ -2130,46 +2350,12 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
>  
>  	omap_hsmmc_conf_bus_power(host);
>  
> -	if (!pdev->dev.of_node) {
> -		res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
> -		if (!res) {
> -			dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
> -			ret = -ENXIO;
> -			goto err_irq;
> -		}
> -		tx_req = res->start;
> -
> -		res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
> -		if (!res) {
> -			dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
> -			ret = -ENXIO;
> -			goto err_irq;
> -		}
> -		rx_req = res->start;
> -	}
> -
> -	dma_cap_zero(mask);
> -	dma_cap_set(DMA_SLAVE, mask);
> -
> -	host->rx_chan =
> -		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> -						 &rx_req, &pdev->dev, "rx");
> -
> -	if (!host->rx_chan) {
> -		dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel\n");
> -		ret = -ENXIO;
> -		goto err_irq;
> -	}
> -
> -	host->tx_chan =
> -		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
> -						 &tx_req, &pdev->dev, "tx");
> -
> -	if (!host->tx_chan) {
> -		dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel\n");
> -		ret = -ENXIO;
> +	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> +		ret = omap_hsmmc_adma_init(host);
> +	else
> +		ret = omap_hsmmc_dma_init(host);
> +	if (ret)
>  		goto err_irq;
> -	}
>  
>  	/* Request IRQ for MMC operations */
>  	ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0,
> @@ -2225,11 +2411,11 @@ err_slot_name:
>  	mmc_remove_host(mmc);
>  err_irq:
>  	device_init_wakeup(&pdev->dev, false);
> -	if (host->tx_chan)
> -		dma_release_channel(host->tx_chan);
> -	if (host->rx_chan)
> -		dma_release_channel(host->rx_chan);
>  	pm_runtime_dont_use_autosuspend(host->dev);
> +	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> +		omap_hsmmc_adma_exit(host);
> +	else
> +		omap_hsmmc_dma_exit(host);
>  	pm_runtime_put_sync(host->dev);
>  	pm_runtime_disable(host->dev);
>  	if (host->dbclk)
> @@ -2248,8 +2434,10 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
>  	pm_runtime_get_sync(host->dev);
>  	mmc_remove_host(host->mmc);
>  
> -	dma_release_channel(host->tx_chan);
> -	dma_release_channel(host->rx_chan);
> +	if (host->pdata->controller_flags & OMAP_HSMMC_USE_ADMA)
> +		omap_hsmmc_adma_exit(host);
> +	else
> +		omap_hsmmc_dma_exit(host);
>  
>  	pm_runtime_dont_use_autosuspend(host->dev);
>  	pm_runtime_put_sync(host->dev);
> diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h
> index 8e981be..e26013d 100644
> --- a/include/linux/platform_data/hsmmc-omap.h
> +++ b/include/linux/platform_data/hsmmc-omap.h
> @@ -27,6 +27,7 @@
>  #define OMAP_HSMMC_SUPPORTS_DUAL_VOLT		BIT(0)
>  #define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ	BIT(1)
>  #define OMAP_HSMMC_SWAKEUP_MISSING		BIT(2)
> +#define OMAP_HSMMC_USE_ADMA			BIT(3)
>  
>  struct omap_hsmmc_dev_attr {
>  	u8 flags;
> 


-- 
P?ter


From arnd at arndb.de  Thu May 19 01:35:36 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 19 May 2016 10:35:36 +0200
Subject: [PATCH] ARM: lpc32xx: fix NR_IRQS confict
Message-ID: <1463646968-1047336-1-git-send-email-arnd@arndb.de>

With the change to sparse IRQs, the lpc32xx platform gets a warning about
conflicting macros:

In file included from arch/arm/mach-lpc32xx/irq.c:31:0:
arch/arm/mach-lpc32xx/include/mach/irqs.h:115:0: warning: "NR_IRQS" redefined
 #define NR_IRQS    96
arch/arm/include/asm/irq.h:9:0: note: this is the location of the previous definition
 #define NR_IRQS NR_IRQS_LEGACY

In the irq controller driver, we surely need the local number instead of
the generic NR_IRQS definition, so I'm renaming that one to LPC32XX_NR_IRQS.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
Fixes: 8cb17b5ed017 ("irqchip: Add LPC32xx interrupt controller driver")
---
 arch/arm/mach-lpc32xx/include/mach/irqs.h | 2 +-
 arch/arm/mach-lpc32xx/irq.c               | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-lpc32xx/include/mach/irqs.h b/arch/arm/mach-lpc32xx/include/mach/irqs.h
index 9e3b90df32e1..00190535df90 100644
--- a/arch/arm/mach-lpc32xx/include/mach/irqs.h
+++ b/arch/arm/mach-lpc32xx/include/mach/irqs.h
@@ -112,6 +112,6 @@
 #define IRQ_LPC32XX_GPI_06		LPC32XX_SIC2_IRQ(28)
 #define IRQ_LPC32XX_SYSCLK		LPC32XX_SIC2_IRQ(31)
 
-#define NR_IRQS				96
+#define LPC32XX_NR_IRQS			96
 
 #endif
diff --git a/arch/arm/mach-lpc32xx/irq.c b/arch/arm/mach-lpc32xx/irq.c
index 2ae431e8bc1b..e30f5e6b8573 100644
--- a/arch/arm/mach-lpc32xx/irq.c
+++ b/arch/arm/mach-lpc32xx/irq.c
@@ -81,7 +81,7 @@ struct lpc32xx_event_info {
 /*
  * Maps an IRQ number to and event mask and register
  */
-static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
+static const struct lpc32xx_event_info lpc32xx_events[LPC32XX_NR_IRQS] = {
 	[IRQ_LPC32XX_GPI_08] = {
 		.event_group = &lpc32xx_event_pin_regs,
 		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_08_BIT,
@@ -431,7 +431,7 @@ void __init lpc32xx_init_irq(void)
 				LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC2_BASE));
 
 	/* Configure supported IRQ's */
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 0; i < LPC32XX_NR_IRQS; i++) {
 		irq_set_chip_and_handler(i, &lpc32xx_irq_chip,
 					 handle_level_irq);
 		irq_clear_status_flags(i, IRQ_NOREQUEST);
@@ -465,7 +465,7 @@ void __init lpc32xx_init_irq(void)
 
 	of_irq_init(mic_of_match);
 
-	lpc32xx_mic_domain = irq_domain_add_legacy(lpc32xx_mic_np, NR_IRQS,
+	lpc32xx_mic_domain = irq_domain_add_legacy(lpc32xx_mic_np, LPC32XX_NR_IRQS,
 						   0, 0, &irq_domain_simple_ops,
 						   NULL);
 	if (!lpc32xx_mic_domain)
-- 
2.7.0



From chaotian.jing at mediatek.com  Thu May 19 01:47:39 2016
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Thu, 19 May 2016 16:47:39 +0800
Subject: [PATCH v2] mmc: mmc: do not use CMD13 to get status after speed mode
Message-ID: <1463647662-27426-1-git-send-email-chaotian.jing@mediatek.com>

base on Adrian's comment to split it to 2 patches
fix switch timeout issue caused by jiffies



From chaotian.jing at mediatek.com  Thu May 19 01:47:42 2016
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Thu, 19 May 2016 16:47:42 +0800
Subject: [PATCH 3/3] mmc: mmc: fix switch timeout issue caused by jiffies
 precision
In-Reply-To: <1463647662-27426-1-git-send-email-chaotian.jing@mediatek.com>
References: <1463647662-27426-1-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <1463647662-27426-4-git-send-email-chaotian.jing@mediatek.com>

with CONFIG_HZ=100, the precision of jiffies is 10ms, and the
generic_cmd6_time of some card is also 10ms. then, may be current
time is only 5ms, but already timed out caused by jiffies precision.

Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
---
 drivers/mmc/core/mmc_ops.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 32de144..ad6e979 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -534,7 +534,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 		timeout_ms = MMC_OPS_TIMEOUT_MS;
 
 	/* Must check status to be sure of no errors. */
-	timeout = jiffies + msecs_to_jiffies(timeout_ms);
+	timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1;
 	do {
 		/*
 		 * Due to the possibility of being preempted after
-- 
1.8.1.1.dirty



From chaotian.jing at mediatek.com  Thu May 19 01:47:41 2016
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Thu, 19 May 2016 16:47:41 +0800
Subject: [PATCH 2/3] mmc: mmc: do not use CMD13 to get status after speed mode
 switch
In-Reply-To: <1463647662-27426-1-git-send-email-chaotian.jing@mediatek.com>
References: <1463647662-27426-1-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <1463647662-27426-3-git-send-email-chaotian.jing@mediatek.com>

Per JEDEC spec, it is not recommended to use CMD13 to get card status
after speed mode switch. below are two reason about this:
1. CMD13 cannot be guaranteed due to the asynchronous operation.
Therefore it is not recommended to use CMD13 to check busy completion
of the timing change indication.
2. After switch to HS200, CMD13 will get response of 0x800, and even the
busy signal gets de-asserted, the response of CMD13 is aslo 0x800.

Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
---
 drivers/mmc/core/mmc.c | 112 ++++++++++++++++++++-----------------------------
 1 file changed, 45 insertions(+), 67 deletions(-)

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 4dbe3df..97403a6 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -952,6 +952,19 @@ static int mmc_select_bus_width(struct mmc_card *card)
 	return err;
 }
 
+/* Caller must hold re-tuning */
+static int mmc_switch_status(struct mmc_card *card)
+{
+	u32 status;
+	int err;
+
+	err = mmc_send_status(card, &status);
+	if (err)
+		return err;
+
+	return mmc_switch_status_error(card->host, status);
+}
+
 /*
  * Switch to the high-speed mode
  */
@@ -962,9 +975,11 @@ static int mmc_select_hs(struct mmc_card *card)
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
 			   card->ext_csd.generic_cmd6_time,
-			   true, true, true);
-	if (!err)
+			   true, false, true);
+	if (!err) {
 		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+		err = mmc_switch_status(card);
+	}
 
 	return err;
 }
@@ -1040,23 +1055,9 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
 	return err;
 }
 
-/* Caller must hold re-tuning */
-static int mmc_switch_status(struct mmc_card *card)
-{
-	u32 status;
-	int err;
-
-	err = mmc_send_status(card, &status);
-	if (err)
-		return err;
-
-	return mmc_switch_status_error(card->host, status);
-}
-
 static int mmc_select_hs400(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	bool send_status = true;
 	unsigned int max_dtr;
 	int err = 0;
 	u8 val;
@@ -1068,9 +1069,6 @@ static int mmc_select_hs400(struct mmc_card *card)
 	      host->ios.bus_width == MMC_BUS_WIDTH_8))
 		return 0;
 
-	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-		send_status = false;
-
 	/* Reduce frequency to HS frequency */
 	max_dtr = card->ext_csd.hs_max_dtr;
 	mmc_set_clock(host, max_dtr);
@@ -1080,7 +1078,7 @@ static int mmc_select_hs400(struct mmc_card *card)
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, val,
 			   card->ext_csd.generic_cmd6_time,
-			   true, send_status, true);
+			   true, false, true);
 	if (err) {
 		pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
 			mmc_hostname(host), err);
@@ -1090,11 +1088,9 @@ static int mmc_select_hs400(struct mmc_card *card)
 	/* Set host controller to HS timing */
 	mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	/* Switch card to DDR */
 	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1113,7 +1109,7 @@ static int mmc_select_hs400(struct mmc_card *card)
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, val,
 			   card->ext_csd.generic_cmd6_time,
-			   true, send_status, true);
+			   true, false, true);
 	if (err) {
 		pr_err("%s: switch to hs400 failed, err:%d\n",
 			 mmc_hostname(host), err);
@@ -1124,11 +1120,9 @@ static int mmc_select_hs400(struct mmc_card *card)
 	mmc_set_timing(host, MMC_TIMING_MMC_HS400);
 	mmc_set_bus_speed(card);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	return 0;
 
@@ -1146,14 +1140,10 @@ int mmc_hs200_to_hs400(struct mmc_card *card)
 int mmc_hs400_to_hs200(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	bool send_status = true;
 	unsigned int max_dtr;
 	int err;
 	u8 val;
 
-	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-		send_status = false;
-
 	/* Reduce frequency to HS */
 	max_dtr = card->ext_csd.hs_max_dtr;
 	mmc_set_clock(host, max_dtr);
@@ -1162,49 +1152,43 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
 	val = EXT_CSD_TIMING_HS;
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
 			   val, card->ext_csd.generic_cmd6_time,
-			   true, send_status, true);
+			   true, false, true);
 	if (err)
 		goto out_err;
 
 	mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	/* Switch HS DDR to HS */
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
 			   EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time,
-			   true, send_status, true);
+			   true, false, true);
 	if (err)
 		goto out_err;
 
 	mmc_set_timing(host, MMC_TIMING_MMC_HS);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	/* Switch HS to HS200 */
 	val = EXT_CSD_TIMING_HS200 |
 	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
 			   val, card->ext_csd.generic_cmd6_time, true,
-			   send_status, true);
+			   false, true);
 	if (err)
 		goto out_err;
 
 	mmc_set_timing(host, MMC_TIMING_MMC_HS200);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	mmc_set_bus_speed(card);
 
@@ -1243,7 +1227,6 @@ static void mmc_select_driver_type(struct mmc_card *card)
 static int mmc_select_hs200(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	bool send_status = true;
 	unsigned int old_timing;
 	int err = -EINVAL;
 	u8 val;
@@ -1260,9 +1243,6 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	mmc_select_driver_type(card);
 
-	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-		send_status = false;
-
 	/*
 	 * Set the bus width(4 or 8) with host's support and
 	 * switch to HS200 mode if bus width is set successfully.
@@ -1274,20 +1254,18 @@ static int mmc_select_hs200(struct mmc_card *card)
 		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 				   EXT_CSD_HS_TIMING, val,
 				   card->ext_csd.generic_cmd6_time,
-				   true, send_status, true);
+				   true, false, true);
 		if (err)
 			goto err;
 		old_timing = host->ios.timing;
 		mmc_set_timing(host, MMC_TIMING_MMC_HS200);
-		if (!send_status) {
-			err = mmc_switch_status(card);
-			/*
-			 * mmc_select_timing() assumes timing has not changed if
-			 * it is a switch error.
-			 */
-			if (err == -EBADMSG)
-				mmc_set_timing(host, old_timing);
-		}
+		err = mmc_switch_status(card);
+		/*
+		 * mmc_select_timing() assumes timing has not changed if
+		 * it is a switch error.
+		 */
+		if (err == -EBADMSG)
+			mmc_set_timing(host, old_timing);
 	}
 err:
 	if (err)
-- 
1.8.1.1.dirty



From chaotian.jing at mediatek.com  Thu May 19 01:47:40 2016
From: chaotian.jing at mediatek.com (Chaotian Jing)
Date: Thu, 19 May 2016 16:47:40 +0800
Subject: [PATCH 1/3] mmc: mmc: use ops->card_busy() to check card status in
 __mmc_switch()
In-Reply-To: <1463647662-27426-1-git-send-email-chaotian.jing@mediatek.com>
References: <1463647662-27426-1-git-send-email-chaotian.jing@mediatek.com>
Message-ID: <1463647662-27426-2-git-send-email-chaotian.jing@mediatek.com>

some MMC host do not support MMC_CAP_WAIT_WHILE_BUSY but provides
ops->card_busy(), So, add this method to check card status after
switch command.

Signed-off-by: Chaotian Jing <chaotian.jing at mediatek.com>
---
 drivers/mmc/core/mmc_ops.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 62355bd..32de144 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -480,6 +480,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 	u32 status = 0;
 	bool use_r1b_resp = use_busy_signal;
 	bool expired = false;
+	bool busy = false;
 
 	mmc_retune_hold(host);
 
@@ -535,19 +536,24 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 	/* Must check status to be sure of no errors. */
 	timeout = jiffies + msecs_to_jiffies(timeout_ms);
 	do {
+		/*
+		 * Due to the possibility of being preempted after
+		 * sending the status command, check the expiration
+		 * time first.
+		 */
+		expired = time_after(jiffies, timeout);
 		if (send_status) {
-			/*
-			 * Due to the possibility of being preempted after
-			 * sending the status command, check the expiration
-			 * time first.
-			 */
-			expired = time_after(jiffies, timeout);
 			err = __mmc_send_status(card, &status, ignore_crc);
 			if (err)
 				goto out;
 		}
 		if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
 			break;
+		if (host->ops->card_busy) {
+			if (!host->ops->card_busy(host))
+				break;
+			busy = true;
+		}
 		if (mmc_host_is_spi(host))
 			break;
 
@@ -556,19 +562,20 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 		 * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
 		 * rely on waiting for the stated timeout to be sufficient.
 		 */
-		if (!send_status) {
+		if (!send_status && !host->ops->card_busy) {
 			mmc_delay(timeout_ms);
 			goto out;
 		}
 
 		/* Timeout if the device never leaves the program state. */
-		if (expired && R1_CURRENT_STATE(status) == R1_STATE_PRG) {
+		if (expired &&
+		    (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy)) {
 			pr_err("%s: Card stuck in programming state! %s\n",
 				mmc_hostname(host), __func__);
 			err = -ETIMEDOUT;
 			goto out;
 		}
-	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
+	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy);
 
 	err = mmc_switch_status_error(host, status);
 out:
-- 
1.8.1.1.dirty



From vigneshr at ti.com  Thu May 19 02:03:59 2016
From: vigneshr at ti.com (Vignesh R)
Date: Thu, 19 May 2016 14:33:59 +0530
Subject: [RFC PATCH 0/2] AM335x-ICE: Add support for rotary-encoder
Message-ID: <1463648641-6931-1-git-send-email-vigneshr@ti.com>


This series adds support for rotary-encoder on AM335x-ICE that is
connected to TI PCA9536 I2C GPIO expander.

The rotary encoder is different from the incremental encoders in the
sense that GPIO line status directly reflect the position(number)
pointed by the dial of the encoder. So, there is no need to count steps
or know the direction of rotation. Patch 1/2 adds DT property
"rotary-encoder,absolute-encoder" to support this encoder. Since, such
encoders do not actually require IRQ lines (as the encoder state can
always be known by reading GPIO lines at that moment), support for
polling based input is added.
The second patch adds DT entry for the rotary-encoder present on
AM335x ICE board.

Tested on AM335x ICE board that has above described rotary-encoder
without IRQs (polling mode).
I don't have hardware with incremental encoder or encoder with IRQ,
please give it a spin on incremental encoders for sanity.

Vignesh R (2):
  Input: rotary-encoder- Add support for absolute encoder
  ARM: dts: am335x-icev2: Add rotary-encoder node

 .../devicetree/bindings/input/rotary-encoder.txt   |   4 +
 Documentation/input/rotary-encoder.txt             |   9 ++
 arch/arm/boot/dts/am335x-icev2.dts                 |  11 ++
 drivers/input/misc/Kconfig                         |  11 ++
 drivers/input/misc/rotary_encoder.c                | 165 ++++++++++++++++-----
 5 files changed, 166 insertions(+), 34 deletions(-)

-- 
2.8.2



From vigneshr at ti.com  Thu May 19 02:04:00 2016
From: vigneshr at ti.com (Vignesh R)
Date: Thu, 19 May 2016 14:34:00 +0530
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
Message-ID: <1463648641-6931-2-git-send-email-vigneshr@ti.com>

There are rotary-encoders where GPIO lines reflect the actual position
of the rotary encoder dial. For example, if dial points to 9, then four
GPIO lines connected to the rotary encoder will read HLLH(1001b = 9).
Add support for such rotary-encoder.
The driver relies on rotary-encoder,absolute-encoder DT property to
detect such encoders.
Since, GPIO IRQs are not necessary to work with
such encoders, optional polling mode support is added using
input_poll_dev skeleton. This is can be used by enabling
CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT.

Signed-off-by: Vignesh R <vigneshr at ti.com>
---
 .../devicetree/bindings/input/rotary-encoder.txt   |   4 +
 Documentation/input/rotary-encoder.txt             |   9 ++
 drivers/input/misc/Kconfig                         |  11 ++
 drivers/input/misc/rotary_encoder.c                | 165 ++++++++++++++++-----
 4 files changed, 155 insertions(+), 34 deletions(-)

diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
index 6c9f0c8a846c..9c928dbd1500 100644
--- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
+++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
@@ -12,6 +12,10 @@ Optional properties:
 - rotary-encoder,relative-axis: register a relative axis rather than an
   absolute one. Relative axis will only generate +1/-1 events on the input
   device, hence no steps need to be passed.
+- rotary-encoder,absolute-encoder: support encoders where GPIO lines
+  reflect the actual position of the rotary encoder dial. For example,
+  if dial points to 9, then four GPIO lines read HLLH(1001b = 9).
+  In this case, rotary-encoder,steps-per-period needed not be defined.
 - rotary-encoder,rollover: Automatic rollove when the rotary value becomes
   greater than the specified steps or smaller than 0. For absolute axis only.
 - rotary-encoder,steps-per-period: Number of steps (stable states) per period.
diff --git a/Documentation/input/rotary-encoder.txt b/Documentation/input/rotary-encoder.txt
index 46a74f0c551a..dc76092f5618 100644
--- a/Documentation/input/rotary-encoder.txt
+++ b/Documentation/input/rotary-encoder.txt
@@ -36,6 +36,15 @@ The phase diagram of these two outputs look like this:
                 |<>|
 	          one step (quarter-period mode)
 
+
+In some encoders, the value pointed by rotary encoders switch is directly
+reflected by status of the GPIOs connecting rotary encoder to CPU. For
+example, if rotary encoder dial points to 9, then the four GPIOs
+conncting rotary encoder will read HLLH(1001b = 9). Such encoders are
+supported by defining devictree binding "rotary-encoder,absolute-encoder".
+These encoders are also supported without need for event(IRQ) generation
+using Input subsytem's polling mode support.
+
 For more information, please see
 	https://en.wikipedia.org/wiki/Rotary_encoder
 
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 1f2337abcf2f..81805f9a534c 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -566,6 +566,17 @@ config INPUT_GPIO_ROTARY_ENCODER
 	  To compile this driver as a module, choose M here: the
 	  module will be called rotary_encoder.
 
+config INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT
+	bool "Polling mode support for rotary encoder"
+	depends on INPUT_GPIO_ROTARY_ENCODER
+	select INPUT_POLLDEV
+	help
+	  Say Y here to enable polling mode support for rotary encoders
+	  connected to GPIO lines that do have interrupt capability and
+	  report rotary encoder position as absolute value over GPIO
+	  lines. Check file: Documentation/input/rotary-encoder.txt for
+	  more information.
+
 config INPUT_RB532_BUTTON
 	tristate "Mikrotik Routerboard 532 button interface"
 	depends on MIKROTIK_RB532
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index c7fc8d4fb080..8f60289fb6cd 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -25,24 +25,29 @@
 #include <linux/of.h>
 #include <linux/pm.h>
 #include <linux/property.h>
+#include <linux/input-polldev.h>
 
 #define DRV_NAME "rotary-encoder"
 
 struct rotary_encoder {
 	struct input_dev *input;
-
+#ifdef CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT
+	struct input_polled_dev *poll_dev;
+#endif
 	struct mutex access_mutex;
 
 	u32 steps;
 	u32 axis;
 	bool relative_axis;
 	bool rollover;
+	bool absolute_encoder;
 
 	unsigned int pos;
 
 	struct gpio_descs *gpios;
+	struct device *dev;
 
-	unsigned int *irq;
+	int *irq;
 
 	bool armed;
 	signed char dir;	/* 1 - clockwise, -1 - CCW */
@@ -67,6 +72,21 @@ static unsigned int rotary_encoder_get_state(struct rotary_encoder *encoder)
 	return ret & 3;
 }
 
+static unsigned int rotary_encoder_get_gpios_state(struct rotary_encoder
+						   *encoder)
+{
+	int i;
+	unsigned int ret = 0;
+
+	for (i = 0; i < encoder->gpios->ndescs; ++i) {
+		int val = gpiod_get_value_cansleep(encoder->gpios->desc[i]);
+
+		ret = ret << 1 | val;
+	}
+
+	return ret;
+}
+
 static void rotary_encoder_report_event(struct rotary_encoder *encoder)
 {
 	if (encoder->relative_axis) {
@@ -178,6 +198,72 @@ out:
 	return IRQ_HANDLED;
 }
 
+static void rotary_encoder_setup_input_params(struct rotary_encoder  *encoder)
+{
+	struct input_dev *input = encoder->input;
+	struct platform_device *pdev = to_platform_device(encoder->dev);
+
+	input->name = pdev->name;
+	input->id.bustype = BUS_HOST;
+	input->dev.parent = encoder->dev;
+
+	if (encoder->relative_axis)
+		input_set_capability(input, EV_REL, encoder->axis);
+	else
+		input_set_abs_params(input,
+				     encoder->axis, 0, encoder->steps, 0, 1);
+}
+
+static irqreturn_t rotary_absolute_encoder_irq(int irq, void *dev_id)
+{
+	struct rotary_encoder *encoder = dev_id;
+	unsigned int state;
+
+	mutex_lock(&encoder->access_mutex);
+
+	state = rotary_encoder_get_gpios_state(encoder);
+	if (state != encoder->last_stable) {
+		input_report_abs(encoder->input, encoder->axis, state);
+		input_sync(encoder->input);
+		encoder->last_stable = state;
+	}
+
+	mutex_lock(&encoder->access_mutex);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT
+static void rotary_encoder_poll_gpios(struct input_polled_dev *poll_dev)
+{
+	struct rotary_encoder *encoder = poll_dev->private;
+	unsigned int state = rotary_encoder_get_gpios_state(encoder);
+
+	if (state != encoder->last_stable) {
+		input_report_abs(encoder->input, encoder->axis, state);
+		input_sync(encoder->input);
+		encoder->last_stable = state;
+	}
+}
+
+static int rotary_encoder_register_poll_device(struct rotary_encoder
+		*encoder)
+{
+	struct input_polled_dev *poll_dev =
+		devm_input_allocate_polled_device(encoder->dev);
+
+	if (!poll_dev)
+		return -ENOMEM;
+	poll_dev->private = encoder;
+	poll_dev->poll = rotary_encoder_poll_gpios;
+	encoder->input = poll_dev->input;
+	rotary_encoder_setup_input_params(encoder);
+	encoder->poll_dev = poll_dev;
+
+	return input_register_polled_device(poll_dev);
+}
+#endif
+
 static int rotary_encoder_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -227,38 +313,32 @@ static int rotary_encoder_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	input = devm_input_allocate_device(dev);
-	if (!input)
-		return -ENOMEM;
-
-	encoder->input = input;
-
-	input->name = pdev->name;
-	input->id.bustype = BUS_HOST;
-	input->dev.parent = dev;
-
-	if (encoder->relative_axis)
-		input_set_capability(input, EV_REL, encoder->axis);
-	else
-		input_set_abs_params(input,
-				     encoder->axis, 0, encoder->steps, 0, 1);
-
-	switch (steps_per_period >> (encoder->gpios->ndescs - 2)) {
-	case 4:
-		handler = &rotary_encoder_quarter_period_irq;
-		encoder->last_stable = rotary_encoder_get_state(encoder);
-		break;
-	case 2:
-		handler = &rotary_encoder_half_period_irq;
-		encoder->last_stable = rotary_encoder_get_state(encoder);
-		break;
-	case 1:
-		handler = &rotary_encoder_irq;
-		break;
-	default:
-		dev_err(dev, "'%d' is not a valid steps-per-period value\n",
-			steps_per_period);
-		return -EINVAL;
+	encoder->dev = dev;
+	encoder->absolute_encoder =
+		device_property_read_bool(dev,
+					  "rotary-encoder,absolute-encoder");
+	if (encoder->absolute_encoder) {
+		handler = rotary_absolute_encoder_irq;
+	} else {
+		switch (steps_per_period >> (encoder->gpios->ndescs - 2)) {
+		case 4:
+			handler = &rotary_encoder_quarter_period_irq;
+			encoder->last_stable =
+				rotary_encoder_get_state(encoder);
+			break;
+		case 2:
+			handler = &rotary_encoder_half_period_irq;
+			encoder->last_stable =
+				rotary_encoder_get_state(encoder);
+			break;
+		case 1:
+			handler = &rotary_encoder_irq;
+			break;
+		default:
+			dev_err(dev, "'%d' is not a valid steps-per-period value\n",
+				steps_per_period);
+			return -EINVAL;
+		}
 	}
 
 	encoder->irq =
@@ -271,6 +351,18 @@ static int rotary_encoder_probe(struct platform_device *pdev)
 	for (i = 0; i < encoder->gpios->ndescs; ++i) {
 		encoder->irq[i] = gpiod_to_irq(encoder->gpios->desc[i]);
 
+#ifdef CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT
+		if (encoder->irq[i] < 0 && encoder->absolute_encoder) {
+			dev_info(dev, "Using poll mode\n");
+			err = rotary_encoder_register_poll_device(encoder);
+			if (err) {
+				dev_err(dev, "failed to register poll dev\n");
+				return err;
+			}
+			platform_set_drvdata(pdev, encoder);
+			return 0;
+		}
+#endif
 		err = devm_request_threaded_irq(dev, encoder->irq[i],
 				NULL, handler,
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
@@ -283,6 +375,11 @@ static int rotary_encoder_probe(struct platform_device *pdev)
 		}
 	}
 
+	input = devm_input_allocate_device(dev);
+	if (!input)
+		return -ENOMEM;
+	encoder->input = input;
+	rotary_encoder_setup_input_params(encoder);
 	err = input_register_device(input);
 	if (err) {
 		dev_err(dev, "failed to register input device\n");
-- 
2.8.2



From vigneshr at ti.com  Thu May 19 02:04:01 2016
From: vigneshr at ti.com (Vignesh R)
Date: Thu, 19 May 2016 14:34:01 +0530
Subject: [RFC PATCH 2/2] ARM: dts: am335x-icev2: Add rotary-encoder node
In-Reply-To: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
Message-ID: <1463648641-6931-3-git-send-email-vigneshr@ti.com>

AM335x ICE board has a rotary-encoder connected to PCA9536 I2C GPIO
expander. Add DT entry for the same.

Signed-off-by: Vignesh R <vigneshr at ti.com>
---

depends on patches to Add TI PCA9536 node posted to linux-gpio:
http://www.spinics.net/lists/arm-kernel/msg505194.html

 arch/arm/boot/dts/am335x-icev2.dts | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/am335x-icev2.dts b/arch/arm/boot/dts/am335x-icev2.dts
index 7d8b8fefdf08..672dccbf203d 100644
--- a/arch/arm/boot/dts/am335x-icev2.dts
+++ b/arch/arm/boot/dts/am335x-icev2.dts
@@ -139,6 +139,17 @@
 			default-state = "off";
 		};
 	};
+
+	rotary-in0 {
+		compatible = "rotary-encoder";
+		gpios = <&pca9536 3 GPIO_ACTIVE_HIGH>,
+			<&pca9536 2 GPIO_ACTIVE_HIGH>,
+			<&pca9536 1 GPIO_ACTIVE_HIGH>,
+			<&pca9536 0 GPIO_ACTIVE_HIGH>;
+		linux,axis = <0>; /* ABS_X */
+		rotary-encoder,steps = <10>;
+		rotary-encoder,absolute-encoder;
+	};
 };
 
 &am33xx_pinmux {
-- 
2.8.2



From Suzuki.Poulose at arm.com  Thu May 19 02:14:17 2016
From: Suzuki.Poulose at arm.com (Suzuki K Poulose)
Date: Thu, 19 May 2016 10:14:17 +0100
Subject: arm64: unhandled level 3 permission fault on ltp mmap16 test
In-Reply-To: <573D5073.1050508@de.bosch.com>
References: <573D5073.1050508@de.bosch.com>
Message-ID: <573D83E9.90706@arm.com>

On 19/05/16 06:34, fixed-term.Oleksij.Rempel wrote:
> Hallo all,
>
> if i run latest ltp tests on any of latest kernel version i get
> fallowing warning:
>
> root at rcar1:/opt/ltp# dmesg
> root at rcar1:/opt/ltp# ./testcases/bin/mmap16
> mmap16      0  TINFO  :  Found free device '/dev/loop0'
> mmap16      0  TINFO  :  Formatting /dev/loop0 with ext4 opts='-b 1024'
> extra opts='10240'
> mke2fs 1.43-WIP (15-Mar-2016)
> [  889.736679] EXT4-fs (loop0): mounted filesystem with ordered data
> mode. Opts: nodelalloc
> [  889.843995] mmap16[2164]: unhandled level 3 permission fault (7) at
> 0x7f8397d400, esr 0x9200004f

IIRC, this is expected. The test performs the access on purpose. It spawns
a child which does this access and expects SIGBUS to be delivered to it. The
parent makes sure that the SIGBUS is delivered to by wait()-ing for it.

See :
                 /*
                  * If child process was killed by SIGBUS, bug is not reproduced.
                  */
                 if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGBUS) {
                         tst_brkm(TBROK | TERRNO, cleanup,
                                  "child process terminate unexpectedly");
                 }

>
> Can some one please help me to understand this? If i see it correctly,
> some thing wrong happened by level 3 address translation. But i have no
> idea how to solve it (if it should be solved)

On arm64 we print unhandled faults to give enough information to debug the
problem, which is why you see those messages in dmesg.

So, you can ignore those messages as long as the faults are generated by
mmap16 and thetest reports success.

Suzuki
  



From fixed-term.Oleksij.Rempel at de.bosch.com  Thu May 19 02:22:43 2016
From: fixed-term.Oleksij.Rempel at de.bosch.com (fixed-term.Oleksij.Rempel)
Date: Thu, 19 May 2016 11:22:43 +0200
Subject: arm64: unhandled level 3 permission fault on ltp mmap16 test
In-Reply-To: <573D83E9.90706@arm.com>
References: <573D5073.1050508@de.bosch.com> <573D83E9.90706@arm.com>
Message-ID: <573D85E3.3090408@de.bosch.com>



On 19.05.2016 11:14, Suzuki K Poulose wrote:
> On 19/05/16 06:34, fixed-term.Oleksij.Rempel wrote:
>> Hallo all,
>>
>> if i run latest ltp tests on any of latest kernel version i get
>> fallowing warning:
>>
>> root at rcar1:/opt/ltp# dmesg
>> root at rcar1:/opt/ltp# ./testcases/bin/mmap16
>> mmap16      0  TINFO  :  Found free device '/dev/loop0'
>> mmap16      0  TINFO  :  Formatting /dev/loop0 with ext4 opts='-b 1024'
>> extra opts='10240'
>> mke2fs 1.43-WIP (15-Mar-2016)
>> [  889.736679] EXT4-fs (loop0): mounted filesystem with ordered data
>> mode. Opts: nodelalloc
>> [  889.843995] mmap16[2164]: unhandled level 3 permission fault (7) at
>> 0x7f8397d400, esr 0x9200004f
> 
> IIRC, this is expected. The test performs the access on purpose. It spawns
> a child which does this access and expects SIGBUS to be delivered to it.
> The
> parent makes sure that the SIGBUS is delivered to by wait()-ing for it.
> 
> See :
>                 /*
>                  * If child process was killed by SIGBUS, bug is not
> reproduced.
>                  */
>                 if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGBUS) {
>                         tst_brkm(TBROK | TERRNO, cleanup,
>                                  "child process terminate unexpectedly");
>                 }
> 
>>
>> Can some one please help me to understand this? If i see it correctly,
>> some thing wrong happened by level 3 address translation. But i have no
>> idea how to solve it (if it should be solved)
> 
> On arm64 we print unhandled faults to give enough information to debug the
> problem, which is why you see those messages in dmesg.
> 
> So, you can ignore those messages as long as the faults are generated by
> mmap16 and thetest reports success.

OK, thank you!


From hongbo.zhang at nxp.com  Thu May 19 02:26:15 2016
From: hongbo.zhang at nxp.com (Hongbo Zhang)
Date: Thu, 19 May 2016 09:26:15 +0000
Subject: [PSCI DISCUSS] How to implement standby and suspend-to-ram by PSCI
In-Reply-To: <5734562E.40303@arm.com>
References: <DB3PR04MB0812DAA98F71C30E8A8832E3847D0@DB3PR04MB0812.eurprd04.prod.outlook.com>
 <572C9BF2.9010004@arm.com>
 <DB3PR04MB08125A628F5034749F8109D884730@DB3PR04MB0812.eurprd04.prod.outlook.com>
 <5734562E.40303@arm.com>
Message-ID: <AM3PR04MB0805EC05291F31CC38919722844A0@AM3PR04MB0805.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: Sudeep Holla [mailto:sudeep.holla at arm.com]
> Sent: Thursday, May 12, 2016 6:09 PM
> To: Hongbo Zhang <hongbo.zhang at nxp.com>; linux-pm at vger.kernel.org
> Cc: Sudeep Holla <sudeep.holla at arm.com>; Mark Rutland
> <mark.rutland at arm.com>; jszhang at marvell.com; Lorenzo Pieralisi
> <lorenzo.pieralisi at arm.com>; Frank Li <Frank.Li at freescale.com>; Marc Zyngier
> <marc.zyngier at arm.com>; Jan Kiszka <jan.kiszka at siemens.com>; Daniel
> Lezcano <daniel.lezcano at linaro.org>; Peng Fan <Peng.Fan at freescale.com>;
> Hans de Goede <hdegoede at redhat.com>; Chen-Yu Tsai <wens at csie.org>;
> Tom Warren <twarren at nvidia.com>; Vincent Guittot
> <vincent.guittot at linaro.org>; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PSCI DISCUSS] How to implement standby and suspend-to-ram by
> PSCI
> 
> 
> 
> On 12/05/16 10:42, Hongbo Zhang wrote:
> > Hi Sudeep,
> >
> 
> [...]
> 
> >
> > Sleep state:
> > All cores are in WFI state,
> > Core cluster is in standby state, e.g. L2 cache is flushed then stops
> > snooping,
> > Only those modules which are required to wake up the device still have a
> > running clock, other device modules in chip are clock gated.
> >
> > Deep sleep state:
> > ARM cores and DDR controller are switched off,
> > DDR is in self-refresh mode,
> > VDD power to off domain IPs are removed, Only the blocks needed to
> > detect wake up and sequence the chip out of deep sleep are on.
> >
> > For the two states, except for the wake-up devices, all the other device
> > dirver's suspend callback needs to be called because those devices will
> > be clock or power gated off. So, the kernel suspend process (freeze
> > tasks, suspend devices etc) are needed for our sleep and deep sleep states.
> > In fact we've already implemented these two stated by legacy way, e.g.
> > mapping sleep state to STANDBY and deep sleep to MEM, both states are
> > implemented in one traditional .enter callback and can be indexed by a
> > 'state' parameter.
> >
> 
> Yes I understand that.
> 
> > While transferring to PSCI, we met the problem I mentioned.
> >
> > As to the freeze(suspend-to-idle), it is described as "a generic, pure
> > software, light-weight, system sleep state" in the Document, and the
> > fact is only acpi is using it,
> 
> No, it independent of ACPI. It can be used on any platform with CPUIdle
> support.
> 
> > what's more, I don't think it satisfy us
> > well, because the freeze_enter() is executed before
> > disable_nonboot_cpus() and syscore_suspend(), while the later two are
> > necessary for us.
> >
> 
> Care to explain ? With suspend-to-idle, wakeup latency is much lesser as
> the CPUs are not hotplugged out. I don't think it makes huge different
> with power on ARM platforms. So its is much better than standby which
> does CPU hotplugging IMO.
> 

Sorry for response late, I was investigating the possibility of implementing suspend-to-idle on our platform.
Our user manual says the core1 should enter wfi first and the core0 is the last core which is responsible for some cleanup such as triggering the clock gating off for non-wakeup devices.
If we use suspend-to-idle (no disable none boot cpu in this routine), which core enters idle last cannot be guaranteed, I don't know if core1 can do the cleanup instead, this cannot be confirmed from any document, so have to do a test later, this needs some time.

> > So it seems another 'state' parameter for SYSTEM_SUSPEND can settle this
> > problem, but it is lack in the spec.
> >
> 
> If you still think you can't make use of suspend-to-idle with added
> advantage of reduced wakeup latency, please send email with all the
> details to errata at arm.com as suggested in the PSCI specification.

Will consider this after my test I mention above, thanks for the info.

> 
> > There are diverse kinds of ARM SOC, and divers kind of peripheral
> > devices in each SOC, so even for the SYSTEM_SUSPEND, there may be
> > different states too(deeper or shallower states of each device, more or
> > less of devices are put to idle), the more the PSCI spec supports, the
> > better.
> >
> 
> With runtime PM, you can work out on the peripheral device PM directly,
> so I can't imagine how the diversity there adds to SYSTEM_SUSPEND
> complexity.

Our SoC isn't designed for mobile device, so the peripheral PM is quite rough, except for the wakeup devices, all the other devices can only be power or clock gated off by one operation at one time, they cannot be treated separately, so the runtime PM doesn't fit well.

> 
> --
> Regards,
> Sudeep


From kristofer.s.martinez at gmail.com  Thu May 19 02:58:36 2016
From: kristofer.s.martinez at gmail.com (Martinez Kristofer)
Date: Thu, 19 May 2016 17:58:36 +0800
Subject: [PATCH 2/2] ARM: dts: am335x-icev2: Add DT node for TI PCA9536
In-Reply-To: <1463640450-16762-3-git-send-email-vigneshr@ti.com>
References: <1463640450-16762-1-git-send-email-vigneshr@ti.com>
 <1463640450-16762-3-git-send-email-vigneshr@ti.com>
Message-ID: <CABtop_EjYF+8i4=GTLWyKGO3CMm9o3Qgv104ZrOJYyExAwDuoA@mail.gmail.com>

On Thu, May 19, 2016 at 2:47 PM, Vignesh R <vigneshr at ti.com> wrote:
> AM335x ICE board has a TI PCA9536 chip connected to I2C0 at address
> 0x41. Add DT entry for the same.
>
> Signed-off-by: Vignesh R <vigneshr at ti.com>
> ---
>  arch/arm/boot/dts/am335x-icev2.dts | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/arch/arm/boot/dts/am335x-icev2.dts b/arch/arm/boot/dts/am335x-icev2.dts
> index e271013e78a6..7d8b8fefdf08 100644
> --- a/arch/arm/boot/dts/am335x-icev2.dts
> +++ b/arch/arm/boot/dts/am335x-icev2.dts
> @@ -206,6 +206,13 @@
>                 gpio-controller;
>                 #gpio-cells = <2>;
>         };
> +
> +       pca9536: gpio at 41 {
> +               compatible = "ti,pca9536";
> +               reg = <0x41>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +       };
>  };
>
>  #include "tps65910.dtsi"

Acked-by: Kristofer Martinez <Kristofer.S.Martinez at gmail.com>

M.K.

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


From vz at mleia.com  Thu May 19 03:04:02 2016
From: vz at mleia.com (Vladimir Zapolskiy)
Date: Thu, 19 May 2016 13:04:02 +0300
Subject: [PATCH] ARM: lpc32xx: fix NR_IRQS confict
In-Reply-To: <1463646968-1047336-1-git-send-email-arnd@arndb.de>
References: <1463646968-1047336-1-git-send-email-arnd@arndb.de>
Message-ID: <573D8F92.3010902@mleia.com>

Hi Arnd,

On 19.05.2016 11:35, Arnd Bergmann wrote:
> With the change to sparse IRQs, the lpc32xx platform gets a warning about
> conflicting macros:
> 
> In file included from arch/arm/mach-lpc32xx/irq.c:31:0:
> arch/arm/mach-lpc32xx/include/mach/irqs.h:115:0: warning: "NR_IRQS" redefined
>  #define NR_IRQS    96
> arch/arm/include/asm/irq.h:9:0: note: this is the location of the previous definition
>  #define NR_IRQS NR_IRQS_LEGACY
> 
> In the irq controller driver, we surely need the local number instead of
> the generic NR_IRQS definition, so I'm renaming that one to LPC32XX_NR_IRQS.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Fixes: 8cb17b5ed017 ("irqchip: Add LPC32xx interrupt controller driver")

I think that the entire removal of arch/arm/mach-lpc32xx/irq.c is the proper fix,
since it is a dead code now - http://www.spinics.net/lists/arm-kernel/msg499976.html

I believe you can apply that change and add Fixes: tag.

--
With best wishes,
Vladimir


From andre.przywara at arm.com  Thu May 19 03:12:55 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 11:12:55 +0100
Subject: [PATCH v4 27/56] KVM: arm/arm64: vgic-new: Add ACTIVE registers
 handlers
In-Reply-To: <20160518130139.GG3827@cbox>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-28-git-send-email-andre.przywara@arm.com>
 <20160518130139.GG3827@cbox>
Message-ID: <92adb318-35e3-81f0-5d5c-73d1728a4e82@arm.com>

Hi Marc,

can you have a quick look below?

On 18/05/16 14:01, Christoffer Dall wrote:
>> +
>> +void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
>> +			     gpa_t addr, unsigned int len,
>> +			     unsigned long val)
>> +{
>> +	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
>> +	int i;
>> +
>> +	kvm_arm_halt_guest(vcpu->kvm);
>> +	for_each_set_bit(i, &val, len * 8) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
>> +		spin_lock(&irq->irq_lock);
>> +		/*
>> +		 * If this virtual IRQ was written into a list register, we
>> +		 * have to make sure the CPU that runs the VCPU thread has
>> +		 * synced back LR state to the struct vgic_irq.  We can only
>> +		 * know this for sure, when either this irq is not assigned to
>> +		 * anyone's AP list anymore, or the VCPU thread is not
>> +		 * running on any CPUs.
>> +		 *
>> +		 * In the opposite case, we know the VCPU thread may be on its
>> +		 * way back from the guest and still has to sync back this
>> +		 * IRQ, so we release and re-acquire the spin_lock to let the
>> +		 * other thread sync back the IRQ.
>> +		 */
>> +		while (irq->vcpu && /* IRQ may have state in an LR somewhere */
>> +		       irq->vcpu->cpu != -1) /* VCPU thread is running */
>> +			cond_resched_lock(&irq->irq_lock);
>> +
>> +		irq->active = false;
>> +		spin_unlock(&irq->irq_lock);
>> +	}
>> +	kvm_arm_resume_guest(vcpu->kvm);
>> +}
>> +
>> +void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
>> +			     gpa_t addr, unsigned int len,
>> +			     unsigned long val)
>> +{
>> +	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
>> +	int i;
>> +
>> +	for_each_set_bit(i, &val, len * 8) {
>> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
>> +
>> +		spin_lock(&irq->irq_lock);
>> +
>> +		/*
>> +		 * If the IRQ was already active or it was on a VCPU before
>> +		 * or there is no target VCPU assigned at the moment, then
>> +		 * just proceed.
>> +		 */
>> +		if (irq->active || irq->vcpu || !irq->target_vcpu) {
> 
> why is it that we don't care if this IRQ is on a LR, for example being
> just pending and not active, and we thereby loose this active state when
> the vcpu syncs back the state?

Mmmh, good question. I don't remember anymore why this irq->vcpu check
was added.
Marc, can you confirm that this is OK to be removed?
I think it's an optimization anyway.

Thanks,
Andre,

> 
> We care for the case where we clear the active state, but not when we
> set it.  Perhaps we discussed this in the past, but now I've forgotten,
> so that should at least be documented somehow.
> 
>> +			irq->active = true;
>> +
>> +			spin_unlock(&irq->irq_lock);
>> +			continue;
>> +		}
>> +
>> +		irq->active = true;
>> +		vgic_queue_irq_unlock(vcpu->kvm, irq);
> 
> this won't work just yet, but I think all that's needed to make it work
> is this patchlet:
> 
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index c22f7e2..27204f22 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -81,7 +81,7 @@ static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
>  
>  	/* If the interrupt is active, it must stay on the current vcpu */
>  	if (irq->active)
> -		return irq->vcpu;
> +		return irq->vcpu ? : irq->target_vcpu;
>  
>  	/*
>  	 * If the IRQ is not active but enabled and pending, we should direct
> 
> 
> Thanks,
> -Christoffer
> 


From srinivas.kandagatla at linaro.org  Thu May 19 03:12:56 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Thu, 19 May 2016 11:12:56 +0100
Subject: [PATCH] usb: echi-hcd: Add ehci_setup check before echi_shutdown
Message-ID: <1463652776-30456-1-git-send-email-srinivas.kandagatla@linaro.org>

This patch protects system from crashing at shutdown in
cases where usb host is not added yet from OTG controller driver.
As ehci_setup() not done yet, so stop accessing registers or
variables initialized as part of ehci_setup().

The use case is simple, for boards like DB410c where the usb host
or device functionality is decided based on the micro-usb cable
presence. If the board boots up with micro-usb connected, the
OTG driver like echi-msm would not add the usb host by default.
However a system shutdown would go and access registers and
uninitialized variables, resulting in below crash.

Unable to handle kernel NULL pointer dereference at virtual address
 00000008
pgd = ffffffc034581000
[00000008] *pgd=0000000000000000, *pud=0000000000000000
CPU: 2 PID: 1957 Comm: reboot Not tainted 4.6.0+ #99
task: ffffffc034bc0000 ti: ffffffc0345cc000 task.ti: ffffffc0345cc000
PC is at ehci_halt+0x54/0x108
LR is at ehci_halt+0x38/0x108
pc : [<ffffff800869837c>] lr : [<ffffff8008698360>] pstate: a00001c5
sp : ffffffc0345cfc60
x29: ffffffc0345cfc60 x28: ffffffc0345cc000
x27: ffffff8008a4d000 x26: 000000000000008e
x25: ffffff8008d86cb0 x24: ffffff800908b040
x23: ffffffc036068870 x22: ffffff8009d0a000
x21: ffffffc03512a410 x20: ffffffc03512a410
x19: ffffffc03512a338 x18: 00000000000065ba
x17: ffffff8009b16b80 x16: 0000000000000003
x15: 00000000000065b9 x14: 00000000000065b6
x13: 0000000000000000 x12: 0000000000000000
x11: 000000000000003d x10: ffffffc0345cf9e0
x9 : 0000000000000001 x8 : ffffffc0345cc000
x7 : ffffff8008698360 x6 : 0000000000000000
x5 : 0000000000000080 x4 : 0000000000000001
x3 : 0000000000000000 x2 : 0000000000000000
x1 : 0000000000000008 x0 : ffffffc034bc0000

Process reboot (pid: 1957, stack limit = 0xffffffc0345cc020)
Stack: (0xffffffc0345cfc60 to 0xffffffc0345d0000)
fc60: ffffffc0345cfc90 ffffff8008698448 ffffffc03512a338 ffffffc03512a338
fc80: ffffffc03512a410 ffffff8008a3bbfc ffffffc0345cfcc0 ffffff8008698548
fca0: ffffffc03512a338 ffffffc03512a000 ffffffc03512a410 ffffff8009d0a000
fcc0: ffffffc0345cfcf0 ffffff800865d2bc ffffffc036068828 ffffffc036068810
fce0: ffffffc036003810 ffffff800853f43c ffffffc0345cfd00 ffffff800854338c
fd00: ffffffc0345cfd10 ffffff800853f45c ffffffc0345cfd60 ffffff80080e0f48
fd20: 0000000000000000 0000000001234567 ffffff8008f8c000 ffffff8008f8c060
fd40: 0000000000000000 0000000000000015 0000000000000120 ffffff80080e0f30
fd60: ffffffc0345cfd70 ffffff80080e1020 ffffffc0345cfd90 ffffff80080e12fc
fd80: 0000000000000000 0000000001234567 0000000000000000 ffffff8008085e70
fda0: 0000000000000000 0000005592905000 ffffffffffffffff 0000007f79daf1cc
fdc0: 0000000000000000 0000000000000000 0000007ffcbb1198 000000000000000a
fde0: 00000055928d3f58 0000000000000001 ffffffc034900000 00000000fffffffe
fe00: ffffffc034900000 0000007f79da902c ffffffc0345cfe40 ffffff800820af38
fe20: 0000000000000000 0000007ffcbb1078 ffffffffffffffff ffffff80081e9b38
fe40: ffffffc0345cfe60 ffffff80081eb410 ffffffc0345cfe60 ffffff80081eb444
fe60: ffffffc0345cfec0 ffffff80081ec4f4 0000000000000000 0000007ffcbb1078
fe80: ffffffffffffffff 0000000000000015 ffffffc0345cfec0 0000007ffcbb1078
fea0: 0000000000000002 000000000000000a ffffffffffffffff 0000000000000000
fec0: 0000000000000000 ffffff8008085e70 fffffffffee1dead 0000000028121969
fee0: 0000000001234567 0000000000000000 ffffffffffffffff 8080800000800000
ff00: 0000800000808080 0000007ffcbb10f0 000000000000008e fefeff54918cb8c7
ff20: 7f7f7f7fffffffff 0101010101010101 0000000000000010 0000000000000000
ff40: 0000000000000000 0000007f79e33588 0000005592905eb8 0000007f79daf1b0
ff60: 0000007ffcbb1340 0000005592906000 0000005592905000 0000005592906000
ff80: 0000005592907000 0000000000000002 0000007ffcbb1d98 0000005592906000
ffa0: 00000055928d2000 0000000000000000 0000000000000000 0000007ffcbb1aa0
ffc0: 00000055928b819c 0000007ffcbb1aa0 0000007f79daf1cc 0000000000000000
ffe0: fffffffffee1dead 000000000000008e 05ef555057155555 d555544d55d775d3
Call trace:
Exception stack(0xffffffc0345cfaa0 to 0xffffffc0345cfbc0)
Set corner to 6
faa0: ffffffc03512a338 ffffffc03512a410 ffffffc0345cfc60 ffffff800869837c
fac0: ffffff8008114210 0000000100000001 ffffff8009ce1b20 ffffff8009ce5f20
fae0: ffffffc0345cfb80 ffffff80081145a8 ffffffc0345cfc10 ffffff800810b924
fb00: ffffffc0345cc000 00000000000001c0 ffffffc03512a410 ffffff8009d0a000
fb20: ffffffc036068870 ffffff800908b040 ffffff8008d86cb0 000000000000008e
fb40: ffffffc034bc0000 0000000000000008 0000000000000000 0000000000000000
fb60: 0000000000000001 0000000000000080 0000000000000000 ffffff8008698360
fb80: ffffffc0345cc000 0000000000000001 ffffffc0345cf9e0 000000000000003d
fba0: 0000000000000000 0000000000000000 00000000000065b6 00000000000065b9
[<ffffff800869837c>] ehci_halt+0x54/0x108
[<ffffff8008698448>] ehci_silence_controller+0x18/0xcc
[<ffffff8008698548>] ehci_shutdown+0x4c/0x64
[<ffffff800865d2bc>] usb_hcd_platform_shutdown+0x1c/0x24
[<ffffff800854338c>] platform_drv_shutdown+0x20/0x28
[<ffffff800853f45c>] device_shutdown+0xf4/0x1b0
[<ffffff80080e0f48>] kernel_restart_prepare+0x34/0x3c
[<ffffff80080e1020>] kernel_restart+0x14/0x74
[<ffffff80080e12fc>] SyS_reboot+0x110/0x21c
[<ffffff8008085e70>] el0_svc_naked+0x24/0x28
Code: 53001c42 350000a2 d5033e9f 91002021 (b9000022)

Fixes 4bb3cad7125b ("usb: host: ehci-msm: Register usb shutdown function")
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
---
 drivers/usb/host/ehci-hcd.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index ae1b6e6..a962b89 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -368,6 +368,15 @@ static void ehci_shutdown(struct usb_hcd *hcd)
 {
 	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
 
+	/**
+	 * Protect the system from crashing at system shutdown in cases where
+	 * usb host is not added yet from OTG controller driver.
+	 * As ehci_setup() not done yet, so stop accessing registers or
+	 * variables initialized in ehci_setup()
+	 */
+	if (!ehci->sbrn)
+		return;
+
 	spin_lock_irq(&ehci->lock);
 	ehci->shutdown = true;
 	ehci->rh_state = EHCI_RH_STOPPING;
-- 
2.8.1



From kristofer.s.martinez at gmail.com  Thu May 19 03:14:54 2016
From: kristofer.s.martinez at gmail.com (Martinez Kristofer)
Date: Thu, 19 May 2016 18:14:54 +0800
Subject: [PATCH] arm64: cpuinfo: add AArch64 & elf platform for app
 compatibility
In-Reply-To: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>
References: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>
Message-ID: <CABtop_ED5ASg-0O-6QE5LXeN_t8rwYWWgExM_1GCnstP7RZ-7g@mail.gmail.com>

On Thu, May 19, 2016 at 10:44 AM, x00195127 <saberlily.xia at hisilicon.com> wrote:
> we find that some apps will read cpuinfo when start up,
> they need the string  as follows:
> "Processor       : AArch64 Processor rev 0 (aarch64)"
>
> Then thay could load the corresponding libs. But now
> arm64 platform's cpuinfo don't has this now, so
> we need add this.
>
> Signed-off-by: Qing Xia <saberlily.xia at hisilicon.com>
> ---
>  arch/arm64/kernel/cpuinfo.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> index 3808470..c3527ad 100644
> --- a/arch/arm64/kernel/cpuinfo.c
> +++ b/arch/arm64/kernel/cpuinfo.c
> @@ -114,6 +114,9 @@ static int c_show(struct seq_file *m, void *v)
>                  * online processors, looking for lines beginning with
>                  * "processor".  Give glibc what it expects.
>                  */
> +               seq_printf(m, "Processor\t: AArch64 Processor rev %d (%s)\n",
> +                               read_cpuid_id() & 15, ELF_PLATFORM);

Nit: read_cpuid_id() & 0xf, ELF_PLATFORM);
What're those apps will need this string to startup?

M.K.

> +
>                 seq_printf(m, "processor\t: %d\n", i);
>
>                 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
> --
> 1.8.3.2
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From hongbo.zhang at nxp.com  Thu May 19 03:27:41 2016
From: hongbo.zhang at nxp.com (Hongbo Zhang)
Date: Thu, 19 May 2016 10:27:41 +0000
Subject: [PSCI DISCUSS] How to implement standby and suspend-to-ram by PSCI
In-Reply-To: <1463486036.19237.9.camel@suse.com>
References: <DB3PR04MB0812DAA98F71C30E8A8832E3847D0@DB3PR04MB0812.eurprd04.prod.outlook.com>
 <572C9BF2.9010004@arm.com>
 <DB3PR04MB08125A628F5034749F8109D884730@DB3PR04MB0812.eurprd04.prod.outlook.com>
 <1463486036.19237.9.camel@suse.com>
Message-ID: <AM3PR04MB0805D7F5375413C154DFB981844A0@AM3PR04MB0805.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: Oliver Neukum [mailto:oneukum at suse.com]
> Sent: Tuesday, May 17, 2016 7:54 PM
> To: Hongbo Zhang <hongbo.zhang at nxp.com>
> Cc: Sudeep Holla <sudeep.holla at arm.com>; linux-pm at vger.kernel.org;
> Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>; Marc Zyngier
> <marc.zyngier at arm.com>; Jan Kiszka <jan.kiszka at siemens.com>; Mark
> Rutland <mark.rutland at arm.com>; Daniel Lezcano
> <daniel.lezcano at linaro.org>; Chen-Yu Tsai <wens at csie.org>; Hans de Goede
> <hdegoede at redhat.com>; Frank Li <Frank.Li at freescale.com>; Peng Fan
> <Peng.Fan at freescale.com>; Tom Warren <twarren at nvidia.com>; Vincent
> Guittot <vincent.guittot at linaro.org>; jszhang at marvell.com; linux-arm-
> kernel at lists.infradead.org
> Subject: Re: [PSCI DISCUSS] How to implement standby and suspend-to-ram by
> PSCI
> 
> On Thu, 2016-05-12 at 09:42 +0000, Hongbo Zhang wrote:
> > On our platform we have some shallow states which maps to cpuidle
> > well,
> > and we have two more deeper states:
> >
> > Sleep state:
> > All cores are in WFI state,
> > Core cluster is in standby state, e.g. L2 cache is flushed then stops
> > snooping,
> > Only those modules which are required to wake up the device still have
> > a
> > running clock, other device modules in chip are clock gated.
> >
> > Deep sleep state:
> > ARM cores and DDR controller are switched off,
> > DDR is in self-refresh mode,
> > VDD power to off domain IPs are removed, Only the blocks needed to
> > detect wake up and sequence the chip out of deep sleep are on.
> 
> For the pm module of the core kernel a low power state is a sleep
> state if even one of three conditions is met:
> 
> a) a device that can be used for input is not a source of wake ups
> b) tasks need to be frozen to enter it
> c) the display goes off, while it should be on
> 
> Generally runtime PM is better if you can get the same results.
> Going to a system sleep state is a necessary evil.
> 
> 	Regards
> 		Oliver
> 
As I just explained in previous reply, many devices in our Soc cannot be physically clock or power gated, all the non-wakeup devices can only be gated off at same time by a PM module, so runtime PM doesn't fit for us well.

Thanks for your advice. 

From peter.maydell at linaro.org  Thu May 19 03:44:23 2016
From: peter.maydell at linaro.org (Peter Maydell)
Date: Thu, 19 May 2016 11:44:23 +0100
Subject: [PATCH v3] KVM: arm/arm64: Add VGICv3 save/restore API
 documentation
In-Reply-To: <20160518170349.GL6666@cbox>
References: <1463150637-6896-1-git-send-email-christoffer.dall@linaro.org>
 <CAFEAcA8fcxo18HhfboE5j=SC8TyrPXqmpsPNymM8zw4PhMTRDw@mail.gmail.com>
 <20160518170349.GL6666@cbox>
Message-ID: <CAFEAcA_RATH6-6PuqevNWw=X=C+_hphhspu6_u=hcpeeRfLtpg@mail.gmail.com>

On 18 May 2016 at 18:03, Christoffer Dall <christoffer.dall at linaro.org> wrote:
> On Fri, May 13, 2016 at 04:28:44PM +0100, Peter Maydell wrote:
>> I would like this to simply get/set the latch state regardless of whether
>> the interrupt is edge triggered or level triggered. (Obviously if the
>> interrupt is edge triggered this is equivalent to accessing the
>> ISPENDR/ICPENDR registers, but I don't want in userspace to have to
>> manually look at whether each interrupt is edge or level in order to
>> identify whether to use ISPENDR or this API, when in fact the state
>> in the kernel is exactly the same. I just want a straightforward
>> get/set accessor to the underlying state.)

> I think my reservations against this come from the fact that we're
> getting farther and farther away from anything that looks like
> software's interface to the GIC hardware as specified by the
> architecture, and it was kind of the motivation for our choice of API
> here in the first place to try to stay close to that.
>
> That being said, what we're designing an API for here is a different
> case that for what the software view of the hardware via registers has
> been designed for, so potentially it's ok to deviate from that.

Yes; our two deviations are just the two awkward points where the
register view of the hardware doesn't provide complete access to
the internal state.

> How about we special-case the SPENDR region, and make CPENDR region
> RAZ/WI, and the SPENDR region then reflects the latch state exclusively.
> Or is this more confusing than just having a separate 'fake' region?

I don't have a preference either way here.

> Do you have a suggestion in mind for wording/naming of the 'latch state'
> that makes sense for software people who have access to the GIC manual,
> but doesn't necessarily understand how the hardware would be built and
> why 'latch state' logically has clear semantics... ?

This is a bit tricky because the spec leaves you to deduce how things
work and doesn't provide much terminology to work with either. Here's
an attempt at an explanation, which is a bit long-winded but I can't
see any way to be more concise:

This returns the value of the latched pending state for the interrupts.
This is identical to the value read from ISPENDR for an edge triggered
interrupt, but may differ for level triggered interrupts. For edge
triggered interrupts, once an interrupt becomes pending (whether because
of an edge detected on the input line or because of a guest write to
ISPENDR) this state is "latched", and only cleared when either the
interrupt is activated or when the guest writes to ICPENDR. A
level triggered interrupt may be pending either because the level input
is held high by a device, or because of a guest write to the ISPENDR
register. Only ISPENDR writes are latched: if the device lowers the line
level then the interrupt is no longer pending unless the guest also
wrote to ISPENDR, and conversely writes to ICPENDR or activations of the
interrupt do not clear the pending status if the line level is still
being held high. (These rules are documented in the GICv3 specification
descriptions of the ICPENDR and ISPENDR registers.)
For a level triggered interrupt the value returned here is that of the
latch which is set by ISPENDR and cleared by ICPENDR or interrupt
activation, whereas the value read from ISPENDR is the logical OR of
the latch value and the input line level. Raw access to the latch state
is provided to userspace so that it can save and restore the entire GIC
internal state (which is defined by the combination of the current input
line level and the latch state, and cannot be deduced from purely the
line level and the value of the ISPENDR registers).

thanks
-- PMM


From harninder.rai at nxp.com  Thu May 19 03:48:41 2016
From: harninder.rai at nxp.com (Harninder Rai)
Date: Thu, 19 May 2016 10:48:41 +0000
Subject: Help needed with kexec on arm64
References: <DB5PR04MB168845795D86B4CE5BA5656FE68B0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <1458230896.3391.18.camel@infradead.org>
 <CAB5YjtBEO=efjhcFdVOaZqG13qK3uzCbS5SFym5hhw-n+_QLhw@mail.gmail.com>
 <DB5PR04MB1688A6D4385B76DAFF71D364E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org> 
Message-ID: <DB5PR04MB16885BC6F5EA7A328A5C36A4E64A0@DB5PR04MB1688.eurprd04.prod.outlook.com>

Hello Takahiro Akashi,

Do you have any further suggestions?

Regards
Harry++

> -----Original Message-----
> From: Harninder Rai
> Sent: Tuesday, May 10, 2016 6:02 PM
> To: 'AKASHI Takahiro'
> Cc: Geoff Levand; linux-arm-kernel at lists.infradead.org
> Subject: RE: Help needed with kexec on arm64
> 
> >
> > This means that there is no enough space left at this point.
> > I guess that you are using too big initramfs against 64MB of total memory.
> > Just increase the memory size for crash dump kernel.
> >
> > -Takahiro AKASHI
> 
> Hello Takahiro Akashi,
> 
> I used a smaller initramfs (as you suggested) and my crash kernel has moved
> further but it again dumped with the following log messages. Any further
> pointers?
> Does this mean that there isn't enough memory to save the core file or
> something? Because the error mostly are related to OOM killer process
> 
> [    8.833434] Freeing unused kernel memory: 748K (ffff800000a3a000 -
> ffff800000af5000)
> [    8.848924] init: Console is alive
> [    8.856866] mmc0: new high speed SDHC card at address b368
> [    8.868239] mmcblk0: mmc0:b368 SDC   3.75 GiB
> [    8.873913]  mmcblk0: p1
> [    9.855930] init: - preinit -
> Press the [f] key and hit [enter] to enter failsafe mode Press the [1], [2],
> [3] or [4] key and hit [enter] to select the debug level
> [   12.896779] procd: - early -
> [   12.977417] kworker/u16:0 invoked oom-killer: gfp_mask=0x27000c0,
> order=2, oom_score_adj=0
> [   12.994568] CPU: 0 PID: 6 Comm: kworker/u16:0 Not tainted 4.5.0-rc6-
> 00038-gae2804a-dirty #5
> [   13.002950] Hardware name: Freescale Layerscape 2085a RDB Board (DT)
> [   13.009333] Workqueue: events_unbound call_usermodehelper_exec_work
> [   13.015623] Call trace:
> [   13.018076] [<ffff800000089760>] dump_backtrace+0x0/0x1ac
> [   13.023492] [<ffff800000089920>] show_stack+0x14/0x1c
> [   13.028560] [<ffff80000032c1d4>] dump_stack+0x8c/0xb0
> [   13.033627] [<ffff8000001aebdc>] dump_header.isra.7+0x4c/0x18c
> [   13.039480] [<ffff800000152130>] oom_kill_process+0x26c/0x45c
> [   13.045243] [<ffff800000152688>] out_of_memory+0x2e0/0x32c
> [   13.050745] [<ffff800000156c68>] __alloc_pages_nodemask+0x83c/0x848
> [   13.057031] [<ffff800000156f78>] alloc_kmem_pages_node+0x30/0xa8
> [   13.063058] [<ffff8000000b776c>]
> copy_process.isra.42.part.43+0x128/0x1488
> [   13.069955] [<ffff8000000b8c4c>] _do_fork+0xcc/0x338
> [   13.074934] [<ffff8000000b8f04>] kernel_thread+0x34/0x3c
> [   13.080261] [<ffff8000000cb8e0>] call_usermodehelper_exec_work+0x2c/0xd8
> [   13.086984] [<ffff8000000ce4b0>] process_one_work+0x134/0x2f4
> [   13.092747] [<ffff8000000ce6c8>] worker_thread+0x58/0x43c
> [   13.098162] [<ffff8000000d3f88>] kthread+0xd8/0xec
> [   13.102967] [<ffff800000085cd0>] ret_from_fork+0x10/0x40
> [   13.261745] Mem-Info:
> 
> Thanks and Regards
> Harry++


From catalin.marinas at arm.com  Thu May 19 03:49:26 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 19 May 2016 11:49:26 +0100
Subject: [PATCH] arm64: cpuinfo: add AArch64 & elf platform for app
 compatibility
In-Reply-To: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>
References: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>
Message-ID: <20160519104925.GL22378@e104818-lin.cambridge.arm.com>

On Thu, May 19, 2016 at 10:44:33AM +0800, x00195127 wrote:
> we find that some apps will read cpuinfo when start up,
> they need the string  as follows:
> "Processor       : AArch64 Processor rev 0 (aarch64)"
> 
> Then thay could load the corresponding libs. But now
> arm64 platform's cpuinfo don't has this now, so
> we need add this.

I have the same question as Martinez: what are those apps? If they are
64-bit apps, they can always assume AArch64 processor.

-- 
Catalin


From catalin.marinas at arm.com  Thu May 19 03:55:24 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 19 May 2016 11:55:24 +0100
Subject: arm64: unhandled level 3 permission fault on ltp mmap16 test
In-Reply-To: <573D83E9.90706@arm.com>
References: <573D5073.1050508@de.bosch.com>
 <573D83E9.90706@arm.com>
Message-ID: <20160519105523.GM22378@e104818-lin.cambridge.arm.com>

On Thu, May 19, 2016 at 10:14:17AM +0100, Suzuki K. Poulose wrote:
> On 19/05/16 06:34, fixed-term.Oleksij.Rempel wrote:
> >if i run latest ltp tests on any of latest kernel version i get
> >fallowing warning:
> >
> >root at rcar1:/opt/ltp# dmesg
> >root at rcar1:/opt/ltp# ./testcases/bin/mmap16
> >mmap16      0  TINFO  :  Found free device '/dev/loop0'
> >mmap16      0  TINFO  :  Formatting /dev/loop0 with ext4 opts='-b 1024'
> >extra opts='10240'
> >mke2fs 1.43-WIP (15-Mar-2016)
> >[  889.736679] EXT4-fs (loop0): mounted filesystem with ordered data
> >mode. Opts: nodelalloc
> >[  889.843995] mmap16[2164]: unhandled level 3 permission fault (7) at
> >0x7f8397d400, esr 0x9200004f
> 
> IIRC, this is expected. The test performs the access on purpose. It spawns
> a child which does this access and expects SIGBUS to be delivered to it. The
> parent makes sure that the SIGBUS is delivered to by wait()-ing for it.
> 
> See :
>                 /*
>                  * If child process was killed by SIGBUS, bug is not reproduced.
>                  */
>                 if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGBUS) {
>                         tst_brkm(TBROK | TERRNO, cleanup,
>                                  "child process terminate unexpectedly");
>                 }
> 
> >Can some one please help me to understand this? If i see it correctly,
> >some thing wrong happened by level 3 address translation. But i have no
> >idea how to solve it (if it should be solved)
> 
> On arm64 we print unhandled faults to give enough information to debug the
> problem, which is why you see those messages in dmesg.
> 
> So, you can ignore those messages as long as the faults are generated by
> mmap16 and thetest reports success.

You can disable it with:

sysctl debug.exception-trace=0

(or via the sysctl files like /etc/sysctl.d/99-sysctl.conf)

-- 
Catalin


From takahiro.akashi at linaro.org  Thu May 19 04:03:09 2016
From: takahiro.akashi at linaro.org (AKASHI Takahiro)
Date: Thu, 19 May 2016 20:03:09 +0900
Subject: Help needed with kexec on arm64
In-Reply-To: <DB5PR04MB1688C3F122091109E6BD9B68E6740@DB5PR04MB1688.eurprd04.prod.outlook.com>
References: <CAB5YjtBEO=efjhcFdVOaZqG13qK3uzCbS5SFym5hhw-n+_QLhw@mail.gmail.com>
 <DB5PR04MB1688A6D4385B76DAFF71D364E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org>
 <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160511005334.GA8417@linaro.org>
 <DB5PR04MB1688C3F122091109E6BD9B68E6740@DB5PR04MB1688.eurprd04.prod.outlook.com>
Message-ID: <20160519110307.GA4941@linaro.org>

On Fri, May 13, 2016 at 12:45:04PM +0000, Harninder Rai wrote:
> Hello Takahiro Akashi,
> 
> > 
> > Apparently lack of memory is a cause of OOM killer, but the core file has
> > nothing to do with this issue.
> > I think that you don't have enough memory for the system yet.
> > 
> > -Takahiro AKASHI
> 
> 
> I moved to SD card based rootfs for booting the crash kernel but when I try to load the dump kernel, I get the following message
> Is there limitation with kexec that the crash kernel cannot be booted from anything apart from RAM?

I don't know what you did here exactly, but I don't think that
there is such a limitation.

> kexec -p ./vmlinux --initrd=./ramdisk_ls1012_openwrt.cpio.gz --append='console=ttyS1,115200 root=/dev/mmcblk0p1 earlycon=uart8250,mmio,0x21c0600ramdisk_size=0x2000000 default_hugepagesz=2m hugepagesz=2m hugepages=256 crashkernel=64M at 2240M memblock=debug'
> Memory for crashkernel is not reserved

This message is a hint. You have got the same one before, right?
Please check /proc/iomem and a dmesg log from the first kernel
with memblock=debug.

-Takahiro AKASHI

> Please reserve memory by passing"crashkernel=X at Y" parameter to kernel
> Then try to loading kdump kernel
> 
> Regards
> Harry++

-- 
Thanks,
-Takahiro AKASHI


From robin.murphy at arm.com  Thu May 19 04:04:45 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 19 May 2016 12:04:45 +0100
Subject: [PATCH] arm64: cpuinfo: add AArch64 & elf platform for app
 compatibility
In-Reply-To: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>
References: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>
Message-ID: <573D9DCD.8020308@arm.com>

On 19/05/16 03:44, x00195127 wrote:
> we find that some apps will read cpuinfo when start up,
> they need the string  as follows:
> "Processor       : AArch64 Processor rev 0 (aarch64)"
>
> Then thay could load the corresponding libs. But now
> arm64 platform's cpuinfo don't has this now, so
> we need add this.
>
> Signed-off-by: Qing Xia <saberlily.xia at hisilicon.com>
> ---
>   arch/arm64/kernel/cpuinfo.c | 3 +++
>   1 file changed, 3 insertions(+)
>
> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> index 3808470..c3527ad 100644
> --- a/arch/arm64/kernel/cpuinfo.c
> +++ b/arch/arm64/kernel/cpuinfo.c
> @@ -114,6 +114,9 @@ static int c_show(struct seq_file *m, void *v)
>   		 * online processors, looking for lines beginning with
>   		 * "processor".  Give glibc what it expects.
>   		 */
> +		seq_printf(m, "Processor\t: AArch64 Processor rev %d (%s)\n",
> +				read_cpuid_id() & 15, ELF_PLATFORM);

The pre-3.19 behaviour printed this once - now you're printing it for 
every CPU in the system, but all with the same revision of whichever 
core this happens to be running on, which is unjustifiably incorrect.

Furthermore, this string provides virtually no useful information anyway 
- the majority of code running on AArch64 already knows that by virtue 
of the fact that *it's running at all*, and for scripts/interpreted 
code/etc. there are already appropriate mechanisms for discovering the 
platform (e.g. uname).

Robin.

> +
>   		seq_printf(m, "processor\t: %d\n", i);
>
>   		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
>



From saberlily.xia at hisilicon.com  Thu May 19 04:06:40 2016
From: saberlily.xia at hisilicon.com (Xiaqing (A))
Date: Thu, 19 May 2016 19:06:40 +0800
Subject: [PATCH] arm64: cpuinfo: add AArch64 & elf platform for app
 compatibility
In-Reply-To: <20160519104925.GL22378@e104818-lin.cambridge.arm.com>
References: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>
 <20160519104925.GL22378@e104818-lin.cambridge.arm.com>
Message-ID: <573D9E40.4000705@hisilicon.com>



? 2016/5/19 18:49, Catalin Marinas ??:
> On Thu, May 19, 2016 at 10:44:33AM +0800, x00195127 wrote:
>> we find that some apps will read cpuinfo when start up,
>> they need the string  as follows:
>> "Processor       : AArch64 Processor rev 0 (aarch64)"
>>
>> Then thay could load the corresponding libs. But now
>> arm64 platform's cpuinfo don't has this now, so
>> we need add this.
>
> I have the same question as Martinez: what are those apps? If they are
> 64-bit apps, they can always assume AArch64 processor.
>

Those are 32-bit apps, and those apps are very popular in our country.



From niklas.soderlund at ragnatech.se  Thu May 19 04:21:22 2016
From: niklas.soderlund at ragnatech.se (Niklas =?iso-8859-1?Q?S=F6derlund?=)
Date: Thu, 19 May 2016 13:21:22 +0200
Subject: [PATCHv6 2/8] dma-debug: add support for resource mappings
In-Reply-To: <20160517145002.GD4074@char.us.oracle.com>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <1462812247-3414-3-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <20160517145002.GD4074@char.us.oracle.com>
Message-ID: <20160519112122.GN29375@bigcity.dyn.berto.se>

Hi Konrad,

Thanks for your feedback.

On 2016-05-17 10:50:02 -0400, Konrad Rzeszutek Wilk wrote:
> > +void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size,
> > +			    int direction, dma_addr_t dma_addr)
> > +{
> > +	struct dma_debug_entry *entry;
> > +
> > +	if (unlikely(dma_debug_disabled()))
> > +		return;
> > +
> > +	entry = dma_entry_alloc();
> > +	if (!entry)
> > +		return;
> > +
> > +	entry->type		= dma_debug_resource;
> > +	entry->dev		= dev;
> > +	entry->pfn		= __phys_to_pfn(addr);
> > +	entry->offset		= addr - PHYS_PFN(entry->pfn);
> 
> Is that right? 

You are correct that should be:

   entry->offset = addr - PFN_PHYS(entry->pfn);

Or even better:

   entry->offset = addr - __pfn_to_phys(entry->pfn);

I will address this and resend late next week, still hoping for some 
more feedback.

> 
> __phys_to_pfn(addr) is PHYS_PFN(addr), so what you get here is
> 
> addr - PHYS_PFN(PHYS_PFN(addr)) ?
> 
> 
> > +	entry->size		= size;
> > +	entry->dev_addr		= dma_addr;
> > +	entry->direction	= direction;
> > +	entry->map_err_type	= MAP_ERR_NOT_CHECKED;
> > +
> > +	add_dma_entry(entry);
> > +}
> > +EXPORT_SYMBOL(debug_dma_map_resource);
> > +

-- 
Regards,
Niklas S?derlund


From k.kozlowski at samsung.com  Thu May 19 04:25:14 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Thu, 19 May 2016 13:25:14 +0200
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <1463648641-6931-2-git-send-email-vigneshr@ti.com>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
 <1463648641-6931-2-git-send-email-vigneshr@ti.com>
Message-ID: <573DA29A.1080609@samsung.com>

On 05/19/2016 11:04 AM, Vignesh R wrote:
> There are rotary-encoders where GPIO lines reflect the actual position
> of the rotary encoder dial. For example, if dial points to 9, then four
> GPIO lines connected to the rotary encoder will read HLLH(1001b = 9).
> Add support for such rotary-encoder.
> The driver relies on rotary-encoder,absolute-encoder DT property to
> detect such encoders.
> Since, GPIO IRQs are not necessary to work with
> such encoders, optional polling mode support is added using
> input_poll_dev skeleton. This is can be used by enabling
> CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT.
> 
> Signed-off-by: Vignesh R <vigneshr at ti.com>
> ---
>  .../devicetree/bindings/input/rotary-encoder.txt   |   4 +
>  Documentation/input/rotary-encoder.txt             |   9 ++
>  drivers/input/misc/Kconfig                         |  11 ++
>  drivers/input/misc/rotary_encoder.c                | 165 ++++++++++++++++-----
>  4 files changed, 155 insertions(+), 34 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> index 6c9f0c8a846c..9c928dbd1500 100644
> --- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
> +++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> @@ -12,6 +12,10 @@ Optional properties:
>  - rotary-encoder,relative-axis: register a relative axis rather than an
>    absolute one. Relative axis will only generate +1/-1 events on the input
>    device, hence no steps need to be passed.
> +- rotary-encoder,absolute-encoder: support encoders where GPIO lines
> +  reflect the actual position of the rotary encoder dial. For example,
> +  if dial points to 9, then four GPIO lines read HLLH(1001b = 9).
> +  In this case, rotary-encoder,steps-per-period needed not be defined.
>  - rotary-encoder,rollover: Automatic rollove when the rotary value becomes
>    greater than the specified steps or smaller than 0. For absolute axis only.
>  - rotary-encoder,steps-per-period: Number of steps (stable states) per period.
> diff --git a/Documentation/input/rotary-encoder.txt b/Documentation/input/rotary-encoder.txt
> index 46a74f0c551a..dc76092f5618 100644
> --- a/Documentation/input/rotary-encoder.txt
> +++ b/Documentation/input/rotary-encoder.txt
> @@ -36,6 +36,15 @@ The phase diagram of these two outputs look like this:
>                  |<>|
>  	          one step (quarter-period mode)
>  
> +
> +In some encoders, the value pointed by rotary encoders switch is directly
> +reflected by status of the GPIOs connecting rotary encoder to CPU. For
> +example, if rotary encoder dial points to 9, then the four GPIOs
> +conncting rotary encoder will read HLLH(1001b = 9). Such encoders are
> +supported by defining devictree binding "rotary-encoder,absolute-encoder".
> +These encoders are also supported without need for event(IRQ) generation
> +using Input subsytem's polling mode support.
> +
>  For more information, please see
>  	https://en.wikipedia.org/wiki/Rotary_encoder
>  
> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> index 1f2337abcf2f..81805f9a534c 100644
> --- a/drivers/input/misc/Kconfig
> +++ b/drivers/input/misc/Kconfig
> @@ -566,6 +566,17 @@ config INPUT_GPIO_ROTARY_ENCODER
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called rotary_encoder.
>  
> +config INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT
> +	bool "Polling mode support for rotary encoder"
> +	depends on INPUT_GPIO_ROTARY_ENCODER
> +	select INPUT_POLLDEV
> +	help
> +	  Say Y here to enable polling mode support for rotary encoders
> +	  connected to GPIO lines that do have interrupt capability and
> +	  report rotary encoder position as absolute value over GPIO
> +	  lines. Check file: Documentation/input/rotary-encoder.txt for
> +	  more information.
> +
>  config INPUT_RB532_BUTTON
>  	tristate "Mikrotik Routerboard 532 button interface"
>  	depends on MIKROTIK_RB532
> diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
> index c7fc8d4fb080..8f60289fb6cd 100644
> --- a/drivers/input/misc/rotary_encoder.c
> +++ b/drivers/input/misc/rotary_encoder.c
> @@ -25,24 +25,29 @@
>  #include <linux/of.h>
>  #include <linux/pm.h>
>  #include <linux/property.h>
> +#include <linux/input-polldev.h>
>  
>  #define DRV_NAME "rotary-encoder"
>  
>  struct rotary_encoder {
>  	struct input_dev *input;
> -
> +#ifdef CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT

Ifdefs look dirty.

> +	struct input_polled_dev *poll_dev;
> +#endif
>  	struct mutex access_mutex;
>  
>  	u32 steps;
>  	u32 axis;
>  	bool relative_axis;
>  	bool rollover;
> +	bool absolute_encoder;
>  
>  	unsigned int pos;
>  
>  	struct gpio_descs *gpios;
> +	struct device *dev;
>  
> -	unsigned int *irq;
> +	int *irq;
>  
>  	bool armed;
>  	signed char dir;	/* 1 - clockwise, -1 - CCW */
> @@ -67,6 +72,21 @@ static unsigned int rotary_encoder_get_state(struct rotary_encoder *encoder)
>  	return ret & 3;
>  }
>  
> +static unsigned int rotary_encoder_get_gpios_state(struct rotary_encoder
> +						   *encoder)
> +{
> +	int i;
> +	unsigned int ret = 0;
> +
> +	for (i = 0; i < encoder->gpios->ndescs; ++i) {
> +		int val = gpiod_get_value_cansleep(encoder->gpios->desc[i]);
> +
> +		ret = ret << 1 | val;
> +	}
> +
> +	return ret;
> +}
> +
>  static void rotary_encoder_report_event(struct rotary_encoder *encoder)
>  {
>  	if (encoder->relative_axis) {
> @@ -178,6 +198,72 @@ out:
>  	return IRQ_HANDLED;
>  }
>  
> +static void rotary_encoder_setup_input_params(struct rotary_encoder  *encoder)
> +{
> +	struct input_dev *input = encoder->input;
> +	struct platform_device *pdev = to_platform_device(encoder->dev);
> +
> +	input->name = pdev->name;
> +	input->id.bustype = BUS_HOST;
> +	input->dev.parent = encoder->dev;
> +
> +	if (encoder->relative_axis)
> +		input_set_capability(input, EV_REL, encoder->axis);
> +	else
> +		input_set_abs_params(input,
> +				     encoder->axis, 0, encoder->steps, 0, 1);
> +}
> +
> +static irqreturn_t rotary_absolute_encoder_irq(int irq, void *dev_id)
> +{
> +	struct rotary_encoder *encoder = dev_id;
> +	unsigned int state;
> +
> +	mutex_lock(&encoder->access_mutex);
> +
> +	state = rotary_encoder_get_gpios_state(encoder);
> +	if (state != encoder->last_stable) {
> +		input_report_abs(encoder->input, encoder->axis, state);
> +		input_sync(encoder->input);
> +		encoder->last_stable = state;
> +	}
> +
> +	mutex_lock(&encoder->access_mutex);

1. Double mutex_lock()? Oh, that is weird. Please document it at least
in form of lockdep annotations.

2. Maybe that should be unlock? Did you test this code?

> +
> +	return IRQ_HANDLED;
> +}
> +
> +#ifdef CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT

Same here and later in the code, ifdefs look dirty.

Best regards,
Krzysztof


From niklas.soderlund at ragnatech.se  Thu May 19 04:29:26 2016
From: niklas.soderlund at ragnatech.se (Niklas =?iso-8859-1?Q?S=F6derlund?=)
Date: Thu, 19 May 2016 13:29:26 +0200
Subject: [PATCHv6 3/8] dma-mapping: add dma_{map,unmap}_resource
In-Reply-To: <20160517145445.GE4074@char.us.oracle.com>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <1462812247-3414-4-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <20160517145445.GE4074@char.us.oracle.com>
Message-ID: <20160519112926.GO29375@bigcity.dyn.berto.se>

Hi Konrad,

Thanks for your feedback.

On 2016-05-17 10:54:45 -0400, Konrad Rzeszutek Wilk wrote:
> >  
> > -In some circumstances dma_map_single() and dma_map_page() will fail to create
> > -a mapping. A driver can check for these errors by testing the returned
> > -DMA address with dma_mapping_error(). A non-zero return value means the mapping
> > -could not be created and the driver should take appropriate action (e.g.
> > -reduce current DMA mapping usage or delay and try again later).
> > +In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
> > +will fail to create a mapping. A driver can check for these errors by testing
> > +the returned DMA address with dma_mapping_error(). A non-zero return value
> > +means the mapping could not be created and the driver should take appropriate
> > +action (e.g. reduce current DMA mapping usage or delay and try again later).
> 
> This looks like it belongs to another patch?

No it is correct (at least intended to be in this patch). All it really 
do is inject dma_map_resource() (which is added in this patch) as one of 
the calls which return dma_addr_t should be checked for error using 
dma_mapping_error().  But yes the change effect all lines in the 
paragraph due to line wrapping.

Hum or maybe I'm misunderstanding your question.

-- 
Regards,
Niklas S?derlund


From shawn.lin at rock-chips.com  Thu May 19 04:31:53 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Thu, 19 May 2016 19:31:53 +0800
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <CAD=FV=UoT2GRYWJWXEn_ccvKGgC+PzQM_BCtLHAa7jxzbaQ9SA@mail.gmail.com>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <5502CA4E.9060401@samsung.com>
 <CAD=FV=VX3ix-j4y95W1q8b-aVuVEN+4xsd8WLx2xcE7KPNJwRw@mail.gmail.com>
 <5506707D.40708@samsung.com> <55189F04.8000404@samsung.com>
 <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
 <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
 <573BCC8D.5090606@kernel-upstream.org>
 <CAD=FV=VneQR3wurjezBkRhtQiH+q-FfhDN8=Ym=XqtZpVmsdUw@mail.gmail.com>
 <573C3283.1040606@rock-chips.com>
 <CAD=FV=UoT2GRYWJWXEn_ccvKGgC+PzQM_BCtLHAa7jxzbaQ9SA@mail.gmail.com>
Message-ID: <10b3dc0e-aebf-664b-b36b-c54692cd9983@rock-chips.com>

Hi,

On 2016/5/19 1:37, Doug Anderson wrote:
> Hi,
>
> On Wed, May 18, 2016 at 2:14 AM, Shawn Lin <shawn.lin at rock-chips.com> wrote:
>> Hi
>>
>>
>> On 2016-5-18 12:12, Doug Anderson wrote:
>>>
>>> Hi,
>>>
>>> On Tue, May 17, 2016 at 6:59 PM, Shawn Lin
>>> <shawn.lin at kernel-upstream.org> wrote:
>>>>
>>>> Could you try this patch to see if you can still find HLE?
>>>>
>>>> @@ -2356,12 +2356,22 @@ static void dw_mci_cmd_interrupt(struct dw_mci
>>>> *host, u32 status)
>>>>   static void dw_mci_handle_cd(struct dw_mci *host)
>>>>   {
>>>>          int i;
>>>> +       int present;
>>>>
>>>>          for (i = 0; i < host->num_slots; i++) {
>>>>                  struct dw_mci_slot *slot = host->slot[i];
>>>>
>>>>                  if (!slot)
>>>>                          continue;
>>>>
>>>> +               present = !(mci_readl(slot->host, CDETECT) & (1 <<
>>>> slot->id));
>>>> +               if (present)
>>>> +                       set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>>>> +               else
>>>> +                       clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>>>
>>>
>>> No, because we don't use the builtin card detect on veyron.  ;)
>>>
>>> We use GPIO card detect because we didn't like the way JTAG and SD
>>> interacted.  Also on rk3288 the builtin card detect line had the wrong
>>> voltage domain (you couldn't detect a card when the IO lines were
>>> powered off).  The builtin card detect line is always driven low on
>>> veyron.
>>
>>
>> Okay, I see.
>>
>>>
>>>
>>> I'm nearly certain that the root cause of my HLE errors is actually
>>> related to the same problem addressed by the commit 7c5209c315ea
>>> ("mmc: core: Increase delay for voltage to stabilize from 3.3V to
>>> 1.8V").  I think that on minnie we're still on the hairy edge and
>>> sometimes the line doesn't transition fast enough.
>>
>>
>> Things are not so simple from your details.
>>
>> I was not enabling SD3.0 support, then I also found HLE sometimes.
>> So it seems commit 7c5209c315ea does not contibute to this phenomenon.
>
> Just to clarify, in my case commit 7c5209c315ea didn't make the
> problem worse, but made it better.  Just not better enough.  ;)
>
>
>> The scenario looks like:
>> remove sd-card -> mmc_sd_detect -> send status(CMD13) ->power_off ->
>> set_ios -> setup_bus -> disabled clk , then HLE irq storm coming
>>
>> From the code of dw_mci_prepare_command:
>> SDMMC_CMD_PRV_DAT_WAIT will not be used for CMD13, so we don't
>> wait_busy here, then cmd code is loding into queue of dw_mmc but
>> still failing send out because it's in busy?
>>
>> With my patch, things go well:
>> remove sd-card -> clear bit of DW_MMC_CARD_PRESENT  -> send
>> status(CMD13) return directly -> power_off -> set_ios -> setup_bus ->
>> disable clk
>>
>> So why should we allow inquiry of card status if we sure the card is
>> removed? I mean no any further cmds should be delivered.
>
> Quite honestly just dealing with the HLE error (my patch or
> equivalent) might be a sane solution for the problem you describe.

Yes, your patch looks good to me, so it should be merged firstly. :)
Then let's push it a bit further more that when HLEs are coming,
somethings must be wrong(currently I don't see a obvious clue from
the code itself although, I'm prone to think it belongs to the
software issue).


>
> dw_mmc needs to be able to work with an external card detect GPIO.
> It's been part of the dw_mmc driver for a long time and is (in fact)
> in use upstream at least by rk3288-veyron.  Any solution that only
> works for internal card detect is not enough.  Just handling the HLE
> error to deal with the interrupt storm and then letting Linux remove
> the card (because of the card detect interrupt) seems totally OK to
> me.
>

Sure, some of rockchip Socs use gpio for CD because they don't
have a internal CD, such as RK3036, right?

> Note: I'd be very curious if your problems get better if you disable

Not at all.

> the "grf_force_jtag" bit in the GRF.  If you're using the builtin card
> detect and you use the boot default of "grf_force_jtag" then your pins
> will be unmuxed behind your back when the card is ejected.  This could
> be causing the dw_mmc controller to get confused.

Right, grf_force_jtag is also not a friend of mine. :)
So I had disabled this function before I was debugging it.

>
>
>> And another question: should we wait busy for cmd13?
>
> I don't think so.  As I understand it CMD13 uses only the CMD line for
> communication and it should be appropriate to send this when the bus
> is "busy" (which means that the DATA lines are low).

Ahh... take back my question.. I was just considering a wired situation
that pins are unmuxed on the background(cmd line as well) when cmd13 is
delivering....


>
> Also: it seems odd that the HLE IRQ storm didn't come right after the
> CMD 13 in your description above.  Are you sure it was the CMD 13 that
> caused the HLEs, or could it has been something else?

Actually no. Any cmds be issued can trigger HLEs, I think, after sd card 
is removed When I hacked mmc_sd_detecd to send other cmds intead
of cmd13.

 From dw_mmc databook v270a(7.2.3 Clock Programming) we can see:
The DWC_mobile_storage loads each of these registers only when the
start_cmd bit and the Update_clk_regs_only bit in the CMD register are
set. When a command is successfully loaded, the DWC_mobile_storage
clears this bit, unless the DWC_mobile_storage already has another
command in the queue, at which point it gives an HLE (Hardware Locked
Error); for details on HLEs, refer to ?Error Handling? on page 233.
Software should look for the start_cmd and the Update_clk_regs_only
bits, and should also set the wait_prvdata_complete bit to ensure that
clock parameters do not change during data transfer.

Maybe the cmd is trying to load(or somethings wrong with the
controller?) when we disable the clk? That may explain my observation
that HLEs came after disabling clk.


>
>
> -Doug
>
>
>


-- 
Best Regards
Shawn Lin



From robin.murphy at arm.com  Thu May 19 04:42:04 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Thu, 19 May 2016 12:42:04 +0100
Subject: [PATCHv6 2/8] dma-debug: add support for resource mappings
In-Reply-To: <20160519112122.GN29375@bigcity.dyn.berto.se>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <1462812247-3414-3-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <20160517145002.GD4074@char.us.oracle.com>
 <20160519112122.GN29375@bigcity.dyn.berto.se>
Message-ID: <573DA68C.3060304@arm.com>

On 19/05/16 12:21, Niklas S?derlund wrote:
> Hi Konrad,
>
> Thanks for your feedback.
>
> On 2016-05-17 10:50:02 -0400, Konrad Rzeszutek Wilk wrote:
>>> +void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size,
>>> +			    int direction, dma_addr_t dma_addr)
>>> +{
>>> +	struct dma_debug_entry *entry;
>>> +
>>> +	if (unlikely(dma_debug_disabled()))
>>> +		return;
>>> +
>>> +	entry = dma_entry_alloc();
>>> +	if (!entry)
>>> +		return;
>>> +
>>> +	entry->type		= dma_debug_resource;
>>> +	entry->dev		= dev;
>>> +	entry->pfn		= __phys_to_pfn(addr);
>>> +	entry->offset		= addr - PHYS_PFN(entry->pfn);
>>
>> Is that right?
>
> You are correct that should be:
>
>     entry->offset = addr - PFN_PHYS(entry->pfn);
>
> Or even better:
>
>     entry->offset = addr - __pfn_to_phys(entry->pfn);

Better still, simply offset_in_page(addr) (as per dma_map_single()).

Robin.

> I will address this and resend late next week, still hoping for some
> more feedback.
>
>>
>> __phys_to_pfn(addr) is PHYS_PFN(addr), so what you get here is
>>
>> addr - PHYS_PFN(PHYS_PFN(addr)) ?
>>
>>
>>> +	entry->size		= size;
>>> +	entry->dev_addr		= dma_addr;
>>> +	entry->direction	= direction;
>>> +	entry->map_err_type	= MAP_ERR_NOT_CHECKED;
>>> +
>>> +	add_dma_entry(entry);
>>> +}
>>> +EXPORT_SYMBOL(debug_dma_map_resource);
>>> +
>



From saberlily.xia at hisilicon.com  Thu May 19 04:42:03 2016
From: saberlily.xia at hisilicon.com (Xiaqing (A))
Date: Thu, 19 May 2016 19:42:03 +0800
Subject: [PATCH] arm64: cpuinfo: add AArch64 & elf platform for app
 compatibility
In-Reply-To: <573D9DCD.8020308@arm.com>
References: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>
 <573D9DCD.8020308@arm.com>
Message-ID: <573DA68B.6030006@hisilicon.com>



? 2016/5/19 19:04, Robin Murphy ??:
> On 19/05/16 03:44, x00195127 wrote:
>> we find that some apps will read cpuinfo when start up,
>> they need the string  as follows:
>> "Processor       : AArch64 Processor rev 0 (aarch64)"
>>
>> Then thay could load the corresponding libs. But now
>> arm64 platform's cpuinfo don't has this now, so
>> we need add this.
>>
>> Signed-off-by: Qing Xia <saberlily.xia at hisilicon.com>
>> ---
>>   arch/arm64/kernel/cpuinfo.c | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
>> index 3808470..c3527ad 100644
>> --- a/arch/arm64/kernel/cpuinfo.c
>> +++ b/arch/arm64/kernel/cpuinfo.c
>> @@ -114,6 +114,9 @@ static int c_show(struct seq_file *m, void *v)
>>            * online processors, looking for lines beginning with
>>            * "processor".  Give glibc what it expects.
>>            */
>> +        seq_printf(m, "Processor\t: AArch64 Processor rev %d (%s)\n",
>> +                read_cpuid_id() & 15, ELF_PLATFORM);
>
> The pre-3.19 behaviour printed this once - now you're printing it for
> every CPU in the system, but all with the same revision of whichever
> core this happens to be running on, which is unjustifiably incorrect.
>
> Furthermore, this string provides virtually no useful information anyway
> - the majority of code running on AArch64 already knows that by virtue
> of the fact that *it's running at all*, and for scripts/interpreted
> code/etc. there are already appropriate mechanisms for discovering the
> platform (e.g. uname).
>
> Robin.
>

Those are 32-bit andriod apps, and according to my tests they really 
need this information, although this information is already useless in 
my opinion. A lot of android apps update very slowly.

>> +
>>           seq_printf(m, "processor\t: %d\n", i);
>>
>>           seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
>>
>
>
> .
>



From vigneshr at ti.com  Thu May 19 04:44:15 2016
From: vigneshr at ti.com (Vignesh R)
Date: Thu, 19 May 2016 17:14:15 +0530
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <573DA29A.1080609@samsung.com>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
 <1463648641-6931-2-git-send-email-vigneshr@ti.com>
 <573DA29A.1080609@samsung.com>
Message-ID: <573DA70F.70206@ti.com>

Hi,

On 05/19/2016 04:55 PM, Krzysztof Kozlowski wrote:
[...]
> On 05/19/2016 11:04 AM, Vignesh R wrote:
>> diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
>> index c7fc8d4fb080..8f60289fb6cd 100644
>> --- a/drivers/input/misc/rotary_encoder.c
>> +++ b/drivers/input/misc/rotary_encoder.c
>> @@ -25,24 +25,29 @@
>>  #include <linux/of.h>
>>  #include <linux/pm.h>
>>  #include <linux/property.h>
>> +#include <linux/input-polldev.h>
>>  
>>  #define DRV_NAME "rotary-encoder"
>>  
>>  struct rotary_encoder {
>>  	struct input_dev *input;
>> -
>> +#ifdef CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT
> 
> Ifdefs look dirty.

I will drop this.

> 
>> +	struct input_polled_dev *poll_dev;
>> +#endif
>>  	struct mutex access_mutex;
>>  
>>  	u32 steps;
>>  	u32 axis;
>>  	bool relative_axis;
>>  	bool rollover;
>> +	bool absolute_encoder;
>>  
>>  	unsigned int pos;
>>  
>>  	struct gpio_descs *gpios;
>> +	struct device *dev;
>>  
>> -	unsigned int *irq;
>> +	int *irq;
>>  
>>  	bool armed;
>>  	signed char dir;	/* 1 - clockwise, -1 - CCW */
>> @@ -67,6 +72,21 @@ static unsigned int rotary_encoder_get_state(struct rotary_encoder *encoder)
>>  	return ret & 3;
>>  }
>>  
>> +static unsigned int rotary_encoder_get_gpios_state(struct rotary_encoder
>> +						   *encoder)
>> +{
>> +	int i;
>> +	unsigned int ret = 0;
>> +
>> +	for (i = 0; i < encoder->gpios->ndescs; ++i) {
>> +		int val = gpiod_get_value_cansleep(encoder->gpios->desc[i]);
>> +
>> +		ret = ret << 1 | val;
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>>  static void rotary_encoder_report_event(struct rotary_encoder *encoder)
>>  {
>>  	if (encoder->relative_axis) {
>> @@ -178,6 +198,72 @@ out:
>>  	return IRQ_HANDLED;
>>  }
>>  
>> +static void rotary_encoder_setup_input_params(struct rotary_encoder  *encoder)
>> +{
>> +	struct input_dev *input = encoder->input;
>> +	struct platform_device *pdev = to_platform_device(encoder->dev);
>> +
>> +	input->name = pdev->name;
>> +	input->id.bustype = BUS_HOST;
>> +	input->dev.parent = encoder->dev;
>> +
>> +	if (encoder->relative_axis)
>> +		input_set_capability(input, EV_REL, encoder->axis);
>> +	else
>> +		input_set_abs_params(input,
>> +				     encoder->axis, 0, encoder->steps, 0, 1);
>> +}
>> +
>> +static irqreturn_t rotary_absolute_encoder_irq(int irq, void *dev_id)
>> +{
>> +	struct rotary_encoder *encoder = dev_id;
>> +	unsigned int state;
>> +
>> +	mutex_lock(&encoder->access_mutex);
>> +
>> +	state = rotary_encoder_get_gpios_state(encoder);
>> +	if (state != encoder->last_stable) {
>> +		input_report_abs(encoder->input, encoder->axis, state);
>> +		input_sync(encoder->input);
>> +		encoder->last_stable = state;
>> +	}
>> +
>> +	mutex_lock(&encoder->access_mutex);
> 
> 1. Double mutex_lock()? Oh, that is weird. Please document it at least
> in form of lockdep annotations.
> 
> 2. Maybe that should be unlock? Did you test this code?
> 

Sorry... this should have been unlock.
I dont have a h/w with rotary-encoder hooked to IRQ line. It would be
much appreciated if someone with rotary-encoder hooked up to h/w IRQ
line test this patch.

>> +
>> +	return IRQ_HANDLED;
>> +}
>> +
>> +#ifdef CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT
> 
> Same here and later in the code, ifdefs look dirty.

Ok, I will remove #ifdefs and directly select INPUT_POLLDEV when
INPUT_GPIO_ROTARY_ENCODER is selected.

-- 
Regards
Vignesh


From honghui.zhang at mediatek.com  Thu May 19 04:49:13 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Thu, 19 May 2016 19:49:13 +0800
Subject: [PATCH v2 0/5] MT2701 iommu support
Message-ID: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

  Mediatek's m4u(Multimedia Memory Management Unit) and SMI(Smart
Multimedia Interface)have two generations HW. They basically sharing the
same hardware block diagram, but have some difference as below:

  Generation one m4u only supports one layer, flat pagetable addressing,
and only supports 4K size page mapping. While generation two m4u supports 2
levels of pagetable which uses the ARM short-descriptor translation table
format for address translation.
They have slight different register base and register offset.
They have very different HW ports defines.

  Generaion one SMI has additional "async" clock which transform the smi
clock into emi clock domain, this clock should be prepared and enabled for
SMI generation one HW.
The register which control the iommu need to translation the address or not
for a particular port is located at smi ao base(smi always on register
base) for generation one SMI HW, but located at each larb's register base
for generation two HW.

This patch set add mt2701 iommu support, it's based on 4.6-rc1 and James
Liao's "Add clock support for Mediatek MT2701 v8[1]" and "Mediatek MT2701
SCPSYS power domain support v7[2]" patch.

v2:
-Fix syntax errors in dt-bindings.
-Use dma_alloc/free_coherent to allocate pagetable memory and reduce the
 streaming DMA stuff.
-Make the mtk_iommu_ops.pgsize_bitmap as ~0UL << MT2701_IOMMU_PAGE_SHIFT.
-Use macro instead of variable to indicate the pagetable size.
-Change some macro name from MTK_XXX to MT2701_XXX.

v1: http://lists.infradead.org/pipermail/linux-mediatek/2016-May/005301.html
-initial version

[1] http://lists.infradead.org/pipermail/linux-mediatek/2016-May/005439.html
[2] http://lists.infradead.org/pipermail/linux-mediatek/2016-May/005429.html

Honghui Zhang (5):
  dt-bindings: mediatek: add descriptions for mediatek mt2701 iommu and
    smi
  iommu/mediatek: move the common struct into header file
  memory/mediatek: add support for mt2701
  iommu/mediatek: add support for mtk iommu generation one HW
  ARM: dts: mt2701: add iommu/smi dtsi node for mt2701

 .../devicetree/bindings/iommu/mediatek,iommu.txt   |  13 +-
 .../memory-controllers/mediatek,smi-common.txt     |  21 +-
 .../memory-controllers/mediatek,smi-larb.txt       |   4 +-
 arch/arm/boot/dts/mt2701.dtsi                      |  51 ++
 drivers/iommu/Kconfig                              |  19 +
 drivers/iommu/Makefile                             |   1 +
 drivers/iommu/mtk_iommu.c                          |  62 +-
 drivers/iommu/mtk_iommu.h                          |  93 +++
 drivers/iommu/mtk_iommu_v1.c                       | 742 +++++++++++++++++++++
 drivers/memory/mtk-smi.c                           | 168 ++++-
 include/dt-bindings/memory/mt2701-larb-port.h      |  85 +++
 11 files changed, 1171 insertions(+), 88 deletions(-)
 create mode 100644 drivers/iommu/mtk_iommu.h
 create mode 100644 drivers/iommu/mtk_iommu_v1.c
 create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h

-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Thu May 19 04:49:18 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Thu, 19 May 2016 19:49:18 +0800
Subject: [PATCH 5/5] ARM: dts: mt2701: add iommu/smi dtsi node for mt2701
In-Reply-To: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
References: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1463658558-567-6-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

Add the dtsi node of iommu and smi for mt2701.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 arch/arm/boot/dts/mt2701.dtsi | 51 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 42d5a37..363de0d 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -16,6 +16,7 @@
 #include <dt-bindings/power/mt2701-power.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/memory/mt2701-larb-port.h>
 #include "skeleton64.dtsi"
 #include "mt2701-pinfunc.h"
 
@@ -160,6 +161,16 @@
 		clock-names = "system-clk", "rtc-clk";
 	};
 
+	smi_common: smi at 1000c000 {
+		compatible = "mediatek,mt2701-smi-common";
+		reg = <0 0x1000c000 0 0x1000>;
+		clocks = <&infracfg CLK_INFRA_SMI>,
+			 <&mmsys CLK_MM_SMI_COMMON>,
+			 <&infracfg CLK_INFRA_SMI>;
+		clock-names = "apb", "smi", "async";
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
+	};
+
 	sysirq: interrupt-controller at 10200100 {
 		compatible = "mediatek,mt2701-sysirq",
 			     "mediatek,mt6577-sysirq";
@@ -169,6 +180,16 @@
 		reg = <0 0x10200100 0 0x1c>;
 	};
 
+	iommu: mmsys_iommu at 10205000 {
+		compatible = "mediatek,mt2701-m4u";
+		reg = <0 0x10205000 0 0x1000>;
+		interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&infracfg CLK_INFRA_M4U>;
+		clock-names = "bclk";
+		mediatek,larbs = <&larb0 &larb1 &larb2>;
+		#iommu-cells = <1>;
+	};
+
 	apmixedsys: syscon at 10209000 {
 		compatible = "mediatek,mt2701-apmixedsys", "syscon";
 		reg = <0 0x10209000 0 0x1000>;
@@ -234,6 +255,16 @@
 		status = "disabled";
 	};
 
+	larb0: larb at 14010000 {
+		compatible = "mediatek,mt2701-smi-larb";
+		reg = <0 0x14010000 0 0x1000>;
+		mediatek,smi = <&smi_common>;
+		clocks = <&mmsys CLK_MM_SMI_LARB0>,
+			 <&mmsys CLK_MM_SMI_LARB0>;
+		clock-names = "apb", "smi";
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
+	};
+
 	imgsys: syscon at 15000000 {
 		compatible = "mediatek,mt2701-imgsys", "syscon";
 		reg = <0 0x15000000 0 0x1000>;
@@ -241,6 +272,16 @@
 		status = "disabled";
 	};
 
+	larb2: larb at 15001000 {
+		compatible = "mediatek,mt2701-smi-larb";
+		reg = <0 0x15001000 0 0x1000>;
+		mediatek,smi = <&smi_common>;
+		clocks = <&imgsys CLK_IMG_SMI_COMM>,
+			 <&imgsys CLK_IMG_SMI_COMM>;
+		clock-names = "apb", "smi";
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_ISP>;
+	};
+
 	vdecsys: syscon at 16000000 {
 		compatible = "mediatek,mt2701-vdecsys", "syscon";
 		reg = <0 0x16000000 0 0x1000>;
@@ -248,6 +289,16 @@
 		status = "disabled";
 	};
 
+	larb1: larb at 16010000 {
+		compatible = "mediatek,mt2701-smi-larb";
+		reg = <0 0x16010000 0 0x1000>;
+		mediatek,smi = <&smi_common>;
+		clocks = <&vdecsys CLK_VDEC_CKGEN>,
+			 <&vdecsys CLK_VDEC_LARB>;
+		clock-names = "apb", "smi";
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_VDEC>;
+	};
+
 	hifsys: syscon at 1a000000 {
 		compatible = "mediatek,mt2701-hifsys", "syscon";
 		reg = <0 0x1a000000 0 0x1000>;
-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Thu May 19 04:49:14 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Thu, 19 May 2016 19:49:14 +0800
Subject: [PATCH v2 1/5] dt-bindings: mediatek: add descriptions for mediatek
 mt2701 iommu and smi
In-Reply-To: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
References: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1463658558-567-2-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

This patch defines the local arbitor port IDs for mediatek SoC MT2701 and
add descriptions of binding for mediatek generation one iommu and smi.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 .../devicetree/bindings/iommu/mediatek,iommu.txt   | 13 +++-
 .../memory-controllers/mediatek,smi-common.txt     | 21 +++++-
 .../memory-controllers/mediatek,smi-larb.txt       |  4 +-
 include/dt-bindings/memory/mt2701-larb-port.h      | 85 ++++++++++++++++++++++
 4 files changed, 115 insertions(+), 8 deletions(-)
 create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h

diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
index cd1b1cd..53c20ca 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
@@ -1,7 +1,9 @@
 * Mediatek IOMMU Architecture Implementation
 
-  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U) which
-uses the ARM Short-Descriptor translation table format for address translation.
+  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U), and
+this M4U have two generations of HW architecture. Generation one uses flat
+pagetable, and only supports 4K size page mapping. Generation two uses the
+ARM Short-Descriptor translation table format for address translation.
 
   About the M4U Hardware Block Diagram, please check below:
 
@@ -36,7 +38,9 @@ in each larb. Take a example, There are many ports like MC, PP, VLD in the
 video decode local arbiter, all these ports are according to the video HW.
 
 Required properties:
-- compatible : must be "mediatek,mt8173-m4u".
+- compatible : must be one of the following string:
+	"mediatek,mt2701-m4u" for mt2701 which uses generation one m4u HW.
+	"mediatek,mt8173-m4u" for mt8173 which uses generation two m4u HW.
 - reg : m4u register base and size.
 - interrupts : the interrupt of m4u.
 - clocks : must contain one entry for each clock-names.
@@ -46,7 +50,8 @@ Required properties:
 	according to the local arbiter index, like larb0, larb1, larb2...
 - iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
 	Specifies the mtk_m4u_id as defined in
-	dt-binding/memory/mt8173-larb-port.h.
+	dt-binding/memory/mt2701-larb-port.h for mt2701 and
+	dt-binding/memory/mt8173-larb-port.h for mt8173
 
 Example:
 	iommu: iommu at 10205000 {
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
index 06a83ce..aa614b2 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
@@ -2,16 +2,31 @@ SMI (Smart Multimedia Interface) Common
 
 The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
 
+Mediatek SMI have two generations of HW architecture, mt8173 uses the second
+generation of SMI HW while mt2701 uses the first generation HW of SMI.
+
+There's slight differences between the two SMI, for generation 2, the
+register which control the iommu port is at each larb's register base. But
+for generation 1, the register is at smi ao base(smi always on register
+base). Besides that, the smi async clock should be prepared and enabled for
+SMI generation 1 to transform the smi clock into emi clock domain, but that is
+not needed for SMI generation 2.
+
 Required properties:
-- compatible : must be "mediatek,mt8173-smi-common"
+- compatible : must be one of :
+	"mediatek,mt2701-smi-common"
+	"mediatek,mt8173-smi-common"
 - reg : the register and size of the SMI block.
 - power-domains : a phandle to the power domain of this local arbiter.
 - clocks : Must contain an entry for each entry in clock-names.
-- clock-names : must contain 2 entries, as follows:
+- clock-names : must contain 3 entries for generation 1 smi HW and 2 entries
+  for generation 2 smi HW as follows:
   - "apb" : Advanced Peripheral Bus clock, It's the clock for setting
 	    the register.
   - "smi" : It's the clock for transfer data and command.
-  They may be the same if both source clocks are the same.
+	    They may be the same if both source clocks are the same.
+  - "async" : asynchronous clock, it help transform the smi clock into the emi
+	      clock domain, this clock is only needed by generation 1 smi HW.
 
 Example:
 	smi_common: smi at 14022000 {
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
index 55ff3b7..21277a5 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
@@ -3,7 +3,9 @@ SMI (Smart Multimedia Interface) Local Arbiter
 The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
 
 Required properties:
-- compatible : must be "mediatek,mt8173-smi-larb"
+- compatible : must be one of :
+		"mediatek,mt8173-smi-larb"
+		"mediatek,mt2701-smi-larb"
 - reg : the register and size of this local arbiter.
 - mediatek,smi : a phandle to the smi_common node.
 - power-domains : a phandle to the power domain of this local arbiter.
diff --git a/include/dt-bindings/memory/mt2701-larb-port.h b/include/dt-bindings/memory/mt2701-larb-port.h
new file mode 100644
index 0000000..78f6678
--- /dev/null
+++ b/include/dt-bindings/memory/mt2701-larb-port.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Honghui Zhang <honghui.zhang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MT2701_LARB_PORT_H_
+#define _MT2701_LARB_PORT_H_
+
+/*
+ * Mediatek m4u generation 1 such as mt2701 has flat m4u port numbers,
+ * the first port's id for larb[N] would be the last port's id of larb[N - 1]
+ * plus one while larb[0]'s first port number is 0. The definition of
+ * MT2701_M4U_ID_LARBx is following HW register spec.
+ * But m4u generation 2 like mt8173 have different port number, it use fixed
+ * offset for each larb, the first port's id for larb[N] would be (N * 32).
+ */
+#define LARB0_PORT_OFFSET		0
+#define LARB1_PORT_OFFSET		11
+#define LARB2_PORT_OFFSET		21
+#define LARB3_PORT_OFFSET		43
+
+#define MT2701_M4U_ID_LARB0(port)	((port) + LARB0_PORT_OFFSET)
+#define MT2701_M4U_ID_LARB1(port)	((port) + LARB1_PORT_OFFSET)
+#define MT2701_M4U_ID_LARB2(port)	((port) + LARB2_PORT_OFFSET)
+
+/* Port define for larb0 */
+#define MT2701_M4U_PORT_DISP_OVL_0		MT2701_M4U_ID_LARB0(0)
+#define MT2701_M4U_PORT_DISP_RDMA1		MT2701_M4U_ID_LARB0(1)
+#define MT2701_M4U_PORT_DISP_RDMA		MT2701_M4U_ID_LARB0(2)
+#define MT2701_M4U_PORT_DISP_WDMA		MT2701_M4U_ID_LARB0(3)
+#define MT2701_M4U_PORT_MM_CMDQ			MT2701_M4U_ID_LARB0(4)
+#define MT2701_M4U_PORT_MDP_RDMA		MT2701_M4U_ID_LARB0(5)
+#define MT2701_M4U_PORT_MDP_WDMA		MT2701_M4U_ID_LARB0(6)
+#define MT2701_M4U_PORT_MDP_ROTO		MT2701_M4U_ID_LARB0(7)
+#define MT2701_M4U_PORT_MDP_ROTCO		MT2701_M4U_ID_LARB0(8)
+#define MT2701_M4U_PORT_MDP_ROTVO		MT2701_M4U_ID_LARB0(9)
+#define MT2701_M4U_PORT_MDP_RDMA1		MT2701_M4U_ID_LARB0(10)
+
+/* Port define for larb1 */
+#define MT2701_M4U_PORT_VDEC_MC_EXT		MT2701_M4U_ID_LARB1(0)
+#define MT2701_M4U_PORT_VDEC_PP_EXT		MT2701_M4U_ID_LARB1(1)
+#define MT2701_M4U_PORT_VDEC_PPWRAP_EXT		MT2701_M4U_ID_LARB1(2)
+#define MT2701_M4U_PORT_VDEC_AVC_MV_EXT		MT2701_M4U_ID_LARB1(3)
+#define MT2701_M4U_PORT_VDEC_PRED_RD_EXT	MT2701_M4U_ID_LARB1(4)
+#define MT2701_M4U_PORT_VDEC_PRED_WR_EXT	MT2701_M4U_ID_LARB1(5)
+#define MT2701_M4U_PORT_VDEC_VLD_EXT		MT2701_M4U_ID_LARB1(6)
+#define MT2701_M4U_PORT_VDEC_VLD2_EXT		MT2701_M4U_ID_LARB1(7)
+#define MT2701_M4U_PORT_VDEC_TILE_EXT		MT2701_M4U_ID_LARB1(8)
+#define MT2701_M4U_PORT_VDEC_IMG_RESZ_EXT	MT2701_M4U_ID_LARB1(9)
+
+/* Port define for larb2 */
+#define MT2701_M4U_PORT_VENC_RCPU		MT2701_M4U_ID_LARB2(0)
+#define MT2701_M4U_PORT_VENC_REC_FRM		MT2701_M4U_ID_LARB2(1)
+#define MT2701_M4U_PORT_VENC_BSDMA		MT2701_M4U_ID_LARB2(2)
+#define MT2701_M4U_PORT_JPGENC_RDMA		MT2701_M4U_ID_LARB2(3)
+#define MT2701_M4U_PORT_VENC_LT_RCPU		MT2701_M4U_ID_LARB2(4)
+#define MT2701_M4U_PORT_VENC_LT_REC_FRM		MT2701_M4U_ID_LARB2(5)
+#define MT2701_M4U_PORT_VENC_LT_BSDMA		MT2701_M4U_ID_LARB2(6)
+#define MT2701_M4U_PORT_JPGDEC_BSDMA		MT2701_M4U_ID_LARB2(7)
+#define MT2701_M4U_PORT_VENC_SV_COMV		MT2701_M4U_ID_LARB2(8)
+#define MT2701_M4U_PORT_VENC_RD_COMV		MT2701_M4U_ID_LARB2(9)
+#define MT2701_M4U_PORT_JPGENC_BSDMA		MT2701_M4U_ID_LARB2(10)
+#define MT2701_M4U_PORT_VENC_CUR_LUMA		MT2701_M4U_ID_LARB2(11)
+#define MT2701_M4U_PORT_VENC_CUR_CHROMA		MT2701_M4U_ID_LARB2(12)
+#define MT2701_M4U_PORT_VENC_REF_LUMA		MT2701_M4U_ID_LARB2(13)
+#define MT2701_M4U_PORT_VENC_REF_CHROMA		MT2701_M4U_ID_LARB2(14)
+#define MT2701_M4U_PORT_IMG_RESZ		MT2701_M4U_ID_LARB2(15)
+#define MT2701_M4U_PORT_VENC_LT_SV_COMV		MT2701_M4U_ID_LARB2(16)
+#define MT2701_M4U_PORT_VENC_LT_RD_COMV		MT2701_M4U_ID_LARB2(17)
+#define MT2701_M4U_PORT_VENC_LT_CUR_LUMA	MT2701_M4U_ID_LARB2(18)
+#define MT2701_M4U_PORT_VENC_LT_CUR_CHROMA	MT2701_M4U_ID_LARB2(19)
+#define MT2701_M4U_PORT_VENC_LT_REF_LUMA	MT2701_M4U_ID_LARB2(20)
+#define MT2701_M4U_PORT_VENC_LT_REF_CHROMA	MT2701_M4U_ID_LARB2(21)
+#define MT2701_M4U_PORT_JPGDEC_WDMA		MT2701_M4U_ID_LARB2(22)
+
+#endif
-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Thu May 19 04:49:16 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Thu, 19 May 2016 19:49:16 +0800
Subject: [PATCH v2 3/5] memory/mediatek: add support for mt2701
In-Reply-To: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
References: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1463658558-567-4-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

Mediatek SMI has two generations of HW architecture, mt8173 uses the
second generation of SMI HW while mt2701 uses the first generation
HW of SMI.

There's slight differences between the two generations, for generation 2,
the register which control the iommu port access PA or IOVA is at each
larb's register base. But for generation 1, the register is at smi ao
base(smi always on register base).
Besides that, the smi async clock should be prepared and enabled for SMI
generation 1 HW to transform the smi clock into emi clock domain, but is
not needed for SMI generation 2.

This patch add SMI driver for mt2701 which use generation 1 SMI HW.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 drivers/memory/mtk-smi.c | 168 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 149 insertions(+), 19 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 089091f..0a47382 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -21,19 +21,50 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <soc/mediatek/smi.h>
+#include <dt-bindings/memory/mt2701-larb-port.h>
 
 #define SMI_LARB_MMU_EN		0xf00
+#define REG_SMI_SECUR_CON_BASE		0x5c0
+
+/* every register control 8 port, register offset 0x4 */
+#define REG_SMI_SECUR_CON_OFFSET(id)	(((id) >> 3) << 2)
+#define REG_SMI_SECUR_CON_ADDR(id)	\
+	(REG_SMI_SECUR_CON_BASE + REG_SMI_SECUR_CON_OFFSET(id))
+
+/*
+ * every port have 4 bit to control, bit[port + 3] control virtual or physical,
+ * bit[port + 2 : port + 1] control the domain, bit[port] control the security
+ * or non-security.
+ */
+#define SMI_SECUR_CON_VAL_MSK(id)	(~(0xf << (((id) & 0x7) << 2)))
+#define SMI_SECUR_CON_VAL_VIRT(id)	BIT((((id) & 0x7) << 2) + 3)
+/* mt2701 domain should be set to 3 */
+#define SMI_SECUR_CON_VAL_DOMAIN(id)	(0x3 << ((((id) & 0x7) << 2) + 1))
+
+struct mtk_smi_larb_gen {
+	int port_in_larb[MTK_LARB_NR_MAX + 1];
+	void (*config_port)(struct device *);
+};
 
 struct mtk_smi {
-	struct device	*dev;
-	struct clk	*clk_apb, *clk_smi;
+	struct device			*dev;
+	struct clk			*clk_apb, *clk_smi;
+	struct clk			*clk_async; /*only needed by mt2701*/
+	void __iomem			*smi_ao_base;
 };
 
 struct mtk_smi_larb { /* larb: local arbiter */
-	struct mtk_smi  smi;
-	void __iomem	*base;
-	struct device	*smi_common_dev;
-	u32		*mmu;
+	struct mtk_smi			smi;
+	void __iomem			*base;
+	struct device			*smi_common_dev;
+	const struct mtk_smi_larb_gen	*larb_gen;
+	int				larbid;
+	u32				*mmu;
+};
+
+enum mtk_smi_gen {
+	MTK_SMI_GEN1,
+	MTK_SMI_GEN2
 };
 
 static int mtk_smi_enable(const struct mtk_smi *smi)
@@ -71,6 +102,7 @@ static void mtk_smi_disable(const struct mtk_smi *smi)
 int mtk_smi_larb_get(struct device *larbdev)
 {
 	struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
+	const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
 	struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
 	int ret;
 
@@ -87,8 +119,7 @@ int mtk_smi_larb_get(struct device *larbdev)
 	}
 
 	/* Configure the iommu info for this larb */
-	writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
-
+	larb_gen->config_port(larbdev);
 	return 0;
 }
 
@@ -124,6 +155,45 @@ mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
 	return -ENODEV;
 }
 
+static void mtk_smi_larb_config_port(struct device *dev)
+{
+	struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+
+	writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
+}
+
+
+static void mtk_smi_larb_config_port_gen1(struct device *dev)
+{
+	struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+	const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
+	struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
+	int i, m4u_port_id, larb_port_num;
+	u32 sec_con_val, reg_val;
+
+	m4u_port_id = larb_gen->port_in_larb[larb->larbid];
+	larb_port_num = larb_gen->port_in_larb[larb->larbid + 1]
+			- larb_gen->port_in_larb[larb->larbid];
+
+	for (i = 0; i < larb_port_num; i++, m4u_port_id++) {
+		if (*larb->mmu & BIT(i)) {
+			/* bit[port + 3] controls the virtual or physical */
+			sec_con_val = SMI_SECUR_CON_VAL_VIRT(m4u_port_id);
+		} else {
+			/* do not need to enable m4u for this port */
+			continue;
+		}
+		reg_val = readl(common->smi_ao_base
+			+ REG_SMI_SECUR_CON_ADDR(m4u_port_id));
+		reg_val &= SMI_SECUR_CON_VAL_MSK(m4u_port_id);
+		reg_val |= sec_con_val;
+		reg_val |= SMI_SECUR_CON_VAL_DOMAIN(m4u_port_id);
+		writel(reg_val,
+			common->smi_ao_base
+			+ REG_SMI_SECUR_CON_ADDR(m4u_port_id));
+	}
+}
+
 static void
 mtk_smi_larb_unbind(struct device *dev, struct device *master, void *data)
 {
@@ -135,6 +205,31 @@ static const struct component_ops mtk_smi_larb_component_ops = {
 	.unbind = mtk_smi_larb_unbind,
 };
 
+static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = {
+	/* mt8173 do not need the port in larb */
+	.config_port = mtk_smi_larb_config_port,
+};
+
+static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
+	.port_in_larb = {
+		LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
+		LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
+	},
+	.config_port = mtk_smi_larb_config_port_gen1,
+};
+
+static const struct of_device_id mtk_smi_larb_of_ids[] = {
+	{
+		.compatible = "mediatek,mt8173-smi-larb",
+		.data = &mtk_smi_larb_mt8173
+	},
+	{
+		.compatible = "mediatek,mt2701-smi-larb",
+		.data = &mtk_smi_larb_mt2701
+	},
+	{}
+};
+
 static int mtk_smi_larb_probe(struct platform_device *pdev)
 {
 	struct mtk_smi_larb *larb;
@@ -142,14 +237,20 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct device_node *smi_node;
 	struct platform_device *smi_pdev;
+	const struct of_device_id *of_id;
 
 	if (!dev->pm_domain)
 		return -EPROBE_DEFER;
 
+	of_id = of_match_node(mtk_smi_larb_of_ids, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
 	larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
 	if (!larb)
 		return -ENOMEM;
 
+	larb->larb_gen = of_id->data;
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	larb->base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(larb->base))
@@ -189,24 +290,34 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id mtk_smi_larb_of_ids[] = {
-	{ .compatible = "mediatek,mt8173-smi-larb",},
-	{}
-};
-
 static struct platform_driver mtk_smi_larb_driver = {
 	.probe	= mtk_smi_larb_probe,
-	.remove = mtk_smi_larb_remove,
+	.remove	= mtk_smi_larb_remove,
 	.driver	= {
 		.name = "mtk-smi-larb",
 		.of_match_table = mtk_smi_larb_of_ids,
 	}
 };
 
+static const struct of_device_id mtk_smi_common_of_ids[] = {
+	{
+		.compatible = "mediatek,mt8173-smi-common",
+		.data = (void *)MTK_SMI_GEN2
+	},
+	{
+		.compatible = "mediatek,mt2701-smi-common",
+		.data = (void *)MTK_SMI_GEN1
+	},
+	{}
+};
+
 static int mtk_smi_common_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct mtk_smi *common;
+	struct resource *res;
+	const struct of_device_id *of_id;
+	enum mtk_smi_gen smi_gen;
 
 	if (!dev->pm_domain)
 		return -EPROBE_DEFER;
@@ -224,6 +335,29 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
 	if (IS_ERR(common->clk_smi))
 		return PTR_ERR(common->clk_smi);
 
+	of_id = of_match_node(mtk_smi_common_of_ids, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
+	/*
+	 * for mtk smi gen 1, we need to get the ao(always on) base to config
+	 * m4u port, and we need to enable the aync clock for transform the smi
+	 * clock into emi clock domain, but for mtk smi gen2, there's no smi ao
+	 * base.
+	 */
+	smi_gen = (enum mtk_smi_gen)of_id->data;
+	if (smi_gen == MTK_SMI_GEN1) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		common->smi_ao_base = devm_ioremap_resource(dev, res);
+		if (IS_ERR(common->smi_ao_base))
+			return PTR_ERR(common->smi_ao_base);
+
+		common->clk_async = devm_clk_get(dev, "async");
+		if (IS_ERR(common->clk_async))
+			return PTR_ERR(common->clk_async);
+
+		clk_prepare_enable(common->clk_async);
+	}
 	pm_runtime_enable(dev);
 	platform_set_drvdata(pdev, common);
 	return 0;
@@ -235,11 +369,6 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id mtk_smi_common_of_ids[] = {
-	{ .compatible = "mediatek,mt8173-smi-common", },
-	{}
-};
-
 static struct platform_driver mtk_smi_common_driver = {
 	.probe	= mtk_smi_common_probe,
 	.remove = mtk_smi_common_remove,
@@ -270,4 +399,5 @@ err_unreg_smi:
 	platform_driver_unregister(&mtk_smi_common_driver);
 	return ret;
 }
+
 subsys_initcall(mtk_smi_init);
-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Thu May 19 04:49:15 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Thu, 19 May 2016 19:49:15 +0800
Subject: [PATCH v2 2/5] iommu/mediatek: move the common struct into header file
In-Reply-To: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
References: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1463658558-567-3-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

Move the struct defines of mtk iommu into a new header files for
common use.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 drivers/iommu/mtk_iommu.c | 62 +-------------------------------
 drivers/iommu/mtk_iommu.h | 90 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+), 61 deletions(-)
 create mode 100644 drivers/iommu/mtk_iommu.h

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index db74553..a6b7846 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -34,7 +34,7 @@
 #include <dt-bindings/memory/mt8173-larb-port.h>
 #include <soc/mediatek/smi.h>
 
-#include "io-pgtable.h"
+#include "mtk_iommu.h"
 
 #define REG_MMU_PT_BASE_ADDR			0x000
 
@@ -93,49 +93,8 @@
 
 #define MTK_PROTECT_PA_ALIGN			128
 
-struct mtk_iommu_suspend_reg {
-	u32				standard_axi_mode;
-	u32				dcm_dis;
-	u32				ctrl_reg;
-	u32				int_control0;
-	u32				int_main_control;
-};
-
-struct mtk_iommu_client_priv {
-	struct list_head		client;
-	unsigned int			mtk_m4u_id;
-	struct device			*m4udev;
-};
-
-struct mtk_iommu_domain {
-	spinlock_t			pgtlock; /* lock for page table */
-
-	struct io_pgtable_cfg		cfg;
-	struct io_pgtable_ops		*iop;
-
-	struct iommu_domain		domain;
-};
-
-struct mtk_iommu_data {
-	void __iomem			*base;
-	int				irq;
-	struct device			*dev;
-	struct clk			*bclk;
-	phys_addr_t			protect_base; /* protect memory base */
-	struct mtk_iommu_suspend_reg	reg;
-	struct mtk_iommu_domain		*m4u_dom;
-	struct iommu_group		*m4u_group;
-	struct mtk_smi_iommu		smi_imu;      /* SMI larb iommu info */
-	bool                            enable_4GB;
-};
-
 static struct iommu_ops mtk_iommu_ops;
 
-static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
-{
-	return container_of(dom, struct mtk_iommu_domain, domain);
-}
-
 static void mtk_iommu_tlb_flush_all(void *cookie)
 {
 	struct mtk_iommu_data *data = cookie;
@@ -552,25 +511,6 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
 	return 0;
 }
 
-static int compare_of(struct device *dev, void *data)
-{
-	return dev->of_node == data;
-}
-
-static int mtk_iommu_bind(struct device *dev)
-{
-	struct mtk_iommu_data *data = dev_get_drvdata(dev);
-
-	return component_bind_all(dev, &data->smi_imu);
-}
-
-static void mtk_iommu_unbind(struct device *dev)
-{
-	struct mtk_iommu_data *data = dev_get_drvdata(dev);
-
-	component_unbind_all(dev, &data->smi_imu);
-}
-
 static const struct component_master_ops mtk_iommu_com_ops = {
 	.bind		= mtk_iommu_bind,
 	.unbind		= mtk_iommu_unbind,
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
new file mode 100644
index 0000000..5656355
--- /dev/null
+++ b/drivers/iommu/mtk_iommu.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Yong Wu <yong.wu at mediatek.com>
+ *       : Honghui Zhang <honghui.zhang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MTK_IOMMU_H_
+#define _MTK_IOMMU_H_
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/iommu.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <soc/mediatek/smi.h>
+
+#include "io-pgtable.h"
+
+struct mtk_iommu_suspend_reg {
+	u32				standard_axi_mode;
+	u32				dcm_dis;
+	u32				ctrl_reg;
+	u32				int_control0;
+	u32				int_main_control;
+};
+
+struct mtk_iommu_client_priv {
+	struct list_head		client;
+	unsigned int			mtk_m4u_id;
+	struct device			*m4udev;
+};
+
+struct mtk_iommu_domain {
+	spinlock_t			pgtlock; /* lock for page table */
+
+	struct io_pgtable_cfg		cfg;
+	struct io_pgtable_ops		*iop;
+
+	struct iommu_domain		domain;
+};
+
+struct mtk_iommu_data {
+	void __iomem			*base;
+	int				irq;
+	struct device			*dev;
+	struct clk			*bclk;
+	phys_addr_t			protect_base; /* protect memory base */
+	struct mtk_iommu_suspend_reg	reg;
+	struct mtk_iommu_domain		*m4u_dom;
+	struct iommu_group		*m4u_group;
+	struct mtk_smi_iommu		smi_imu;      /* SMI larb iommu info */
+	bool                            enable_4GB;
+};
+
+static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
+{
+	return container_of(dom, struct mtk_iommu_domain, domain);
+}
+
+static int compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static int mtk_iommu_bind(struct device *dev)
+{
+	struct mtk_iommu_data *data = dev_get_drvdata(dev);
+
+	return component_bind_all(dev, &data->smi_imu);
+}
+
+static void mtk_iommu_unbind(struct device *dev)
+{
+	struct mtk_iommu_data *data = dev_get_drvdata(dev);
+
+	component_unbind_all(dev, &data->smi_imu);
+}
+
+#endif
-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Thu May 19 04:49:17 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Thu, 19 May 2016 19:49:17 +0800
Subject: [PATCH v2 4/5] iommu/mediatek: add support for mtk iommu generation
 one HW
In-Reply-To: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
References: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1463658558-567-5-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

Mediatek SoC's M4U has two generations of HW architcture. Generation one
uses flat, one layer pagetable, and was shipped with ARM architecture, it
only supports 4K size page mapping. MT2701 SoC uses this generation one
m4u HW. Generation two uses the ARM short-descriptor translation table
format for address translation, and was shipped with ARM64 architecture,
MT8173 uses this generation two m4u HW. All the two generation iommu HW
only have one iommu domain, and all its iommu clients share the same
iova address.

These two generation m4u HW have slit different register groups and
register offset, but most register names are the same. This patch add iommu
support for mediatek SoC mt2701.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 drivers/iommu/Kconfig        |  19 ++
 drivers/iommu/Makefile       |   1 +
 drivers/iommu/mtk_iommu.h    |   3 +
 drivers/iommu/mtk_iommu_v1.c | 742 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 765 insertions(+)
 create mode 100644 drivers/iommu/mtk_iommu_v1.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index dd1dc39..2e17d70 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -354,4 +354,23 @@ config MTK_IOMMU
 
 	  If unsure, say N here.
 
+config MTK_IOMMU_V1
+	bool "MTK IOMMU Version 1 (M4U gen1) Support"
+	depends on ARM || ARM64
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	select ARM_DMA_USE_IOMMU
+	select IOMMU_API
+	select IOMMU_DMA
+	select MEMORY
+	select MTK_SMI
+	select COMMON_CLK_MT2701_MMSYS
+	select COMMON_CLK_MT2701_IMGSYS
+	select COMMON_CLK_MT2701_VDECSYS
+	help
+	  Support for the M4U on certain Mediatek SoCs. M4U generation 1 HW is
+	  Multimedia Memory Managememt Unit. This option enables remapping of
+	  DMA memory accesses for the multimedia subsystem.
+
+	  if unsure, say N here.
+
 endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index c6edb31..778baf5 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
 obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
 obj-$(CONFIG_MTK_IOMMU) += mtk_iommu.o
+obj-$(CONFIG_MTK_IOMMU_V1) += mtk_iommu_v1.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
 obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 5656355..8d60f21 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -48,6 +48,9 @@ struct mtk_iommu_domain {
 	struct io_pgtable_ops		*iop;
 
 	struct iommu_domain		domain;
+	void				*pgt_va;
+	dma_addr_t			pgt_pa;
+	void				*cookie;
 };
 
 struct mtk_iommu_data {
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
new file mode 100644
index 0000000..55023e1
--- /dev/null
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -0,0 +1,742 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Yong Wu <yong.wu at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/bootmem.h>
+#include <linux/bug.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/dma-iommu.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iommu.h>
+#include <linux/iopoll.h>
+#include <linux/kmemleak.h>
+#include <linux/list.h>
+#include <linux/of_address.h>
+#include <linux/of_iommu.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/barrier.h>
+#include <asm/dma-iommu.h>
+#include <linux/module.h>
+#include <dt-bindings/memory/mt2701-larb-port.h>
+#include <soc/mediatek/smi.h>
+#include "mtk_iommu.h"
+
+#define REG_MMU_PT_BASE_ADDR			0x000
+
+#define F_ALL_INVLD				0x2
+#define F_MMU_INV_RANGE				0x1
+#define F_INVLD_EN0				BIT(0)
+#define F_INVLD_EN1				BIT(1)
+
+#define F_MMU_FAULT_VA_MSK			0xfffff000
+#define MTK_PROTECT_PA_ALIGN			128
+
+#define REG_MMU_CTRL_REG			0x210
+#define F_MMU_CTRL_COHERENT_EN			BIT(8)
+#define REG_MMU_IVRP_PADDR			0x214
+#define REG_MMU_INT_CONTROL			0x220
+#define F_INT_TRANSLATION_FAULT			BIT(0)
+#define F_INT_MAIN_MULTI_HIT_FAULT		BIT(1)
+#define F_INT_INVALID_PA_FAULT			BIT(2)
+#define F_INT_ENTRY_REPLACEMENT_FAULT		BIT(3)
+#define F_INT_TABLE_WALK_FAULT			BIT(4)
+#define F_INT_TLB_MISS_FAULT			BIT(5)
+#define F_INT_PFH_DMA_FIFO_OVERFLOW		BIT(6)
+#define F_INT_MISS_DMA_FIFO_OVERFLOW		BIT(7)
+
+#define F_MMU_TF_PROTECT_SEL(prot)		(((prot) & 0x3) << 5)
+#define F_INT_CLR_BIT				BIT(12)
+
+#define REG_MMU_FAULT_ST			0x224
+#define REG_MMU_FAULT_VA			0x228
+#define REG_MMU_INVLD_PA			0x22C
+#define REG_MMU_INT_ID				0x388
+#define REG_MMU_INVALIDATE			0x5c0
+#define REG_MMU_INVLD_START_A			0x5c4
+#define REG_MMU_INVLD_END_A			0x5c8
+
+#define REG_MMU_INV_SEL				0x5d8
+#define REG_MMU_STANDARD_AXI_MODE		0x5e8
+
+#define REG_MMU_DCM				0x5f0
+#define F_MMU_DCM_ON				BIT(1)
+#define REG_MMU_CPE_DONE			0x60c
+#define F_DESC_VALID				0x2
+#define F_DESC_NONSEC				BIT(3)
+#define MT2701_M4U_TF_LARB(TF)			(6 - (((TF) >> 13) & 0x7))
+#define MT2701_M4U_TF_PORT(TF)			(((TF) >> 8) & 0xF)
+/* MTK generation one iommu HW only support 4K size mapping */
+#define MT2701_IOMMU_PAGE_SHIFT			12
+#define MT2701_IOMMU_PAGE_SIZE			(1UL << MT2701_IOMMU_PAGE_SHIFT)
+
+/*
+ * MTK m4u support 4GB iova address space, and oly support 4K page
+ * mapping. So the pagetable size should be exactly as 4M.
+ */
+#define M2701_IOMMU_PGT_SIZE			SZ_4M
+
+static const int mt2701_m4u_in_larb[] = {
+	LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
+	LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
+};
+
+static inline int mt2701_m4u_to_larb(int id)
+{
+	int i;
+
+	for (i = ARRAY_SIZE(mt2701_m4u_in_larb); i >= 0; i--)
+		if ((id) >= mt2701_m4u_in_larb[i])
+			return i;
+
+	return 0;
+}
+
+static inline int mt2701_m4u_to_port(int id)
+{
+	int larb = mt2701_m4u_to_larb(id);
+
+	return id - mt2701_m4u_in_larb[larb];
+}
+
+static void mtk_iommu_tlb_flush_all(void *cookie)
+{
+	struct mtk_iommu_data *data = cookie;
+
+	writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
+			data->base + REG_MMU_INV_SEL);
+	writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
+	wmb(); /* Make sure the tlb flush all done */
+}
+
+static void mtk_iommu_tlb_flush_range(void *cookie,
+				unsigned long iova, size_t size)
+{
+	struct mtk_iommu_data *data = cookie;
+	int ret;
+	u32 tmp;
+
+	writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
+		data->base + REG_MMU_INV_SEL);
+	writel_relaxed(iova & F_MMU_FAULT_VA_MSK,
+		data->base + REG_MMU_INVLD_START_A);
+	writel_relaxed((iova + size - 1) & F_MMU_FAULT_VA_MSK,
+		data->base + REG_MMU_INVLD_END_A);
+	writel_relaxed(F_MMU_INV_RANGE, data->base + REG_MMU_INVALIDATE);
+
+	ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE,
+				tmp, tmp != 0, 10, 100000);
+	if (ret) {
+		dev_warn(data->dev,
+			 "Partial TLB flush timed out, falling back to full flush\n");
+		mtk_iommu_tlb_flush_all(cookie);
+	}
+	/* Clear the CPE status */
+	writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
+}
+
+static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
+{
+	struct mtk_iommu_data *data = dev_id;
+	struct mtk_iommu_domain *dom = data->m4u_dom;
+	u32 int_state, regval, fault_iova, fault_pa;
+	unsigned int fault_larb, fault_port;
+
+	/* Read error information from registers */
+	int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST);
+	fault_iova = readl_relaxed(data->base + REG_MMU_FAULT_VA);
+
+	fault_iova &= F_MMU_FAULT_VA_MSK;
+	fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
+	regval = readl_relaxed(data->base + REG_MMU_INT_ID);
+	fault_larb = MT2701_M4U_TF_LARB(regval);
+	fault_port = MT2701_M4U_TF_PORT(regval);
+
+	/*
+	 * MTK v1 iommu HW could not determin whether the fault is read or
+	 * write fault, report as read fault.
+	 */
+	if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
+			IOMMU_FAULT_READ))
+		dev_err_ratelimited(data->dev,
+			"fault type=0x%x iova=0x%x pa=0x%x larb=%d port=%d\n",
+			int_state, fault_iova, fault_pa,
+			fault_larb, fault_port);
+
+	/* Interrupt clear */
+	regval = readl_relaxed(data->base + REG_MMU_INT_CONTROL);
+	regval |= F_INT_CLR_BIT;
+	writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL);
+
+	mtk_iommu_tlb_flush_all(data);
+
+	return IRQ_HANDLED;
+}
+
+static void mtk_iommu_config(struct mtk_iommu_data *data,
+			     struct device *dev, bool enable)
+{
+	struct mtk_iommu_client_priv *head, *cur, *next;
+	struct mtk_smi_larb_iommu    *larb_mmu;
+	unsigned int                 larbid, portid;
+
+	head = dev->archdata.iommu;
+	list_for_each_entry_safe(cur, next, &head->client, client) {
+		larbid = mt2701_m4u_to_larb(cur->mtk_m4u_id);
+		portid = mt2701_m4u_to_port(cur->mtk_m4u_id);
+		larb_mmu = &data->smi_imu.larb_imu[larbid];
+
+		dev_dbg(dev, "%s iommu port: %d\n",
+			enable ? "enable" : "disable", portid);
+
+		if (enable)
+			larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
+		else
+			larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
+	}
+}
+
+static void *mtk_iommu_alloc_pgt(struct device *dev,
+				dma_addr_t *dma, gfp_t gfp)
+{
+	void *pages = dma_alloc_coherent(dev,
+				M2701_IOMMU_PGT_SIZE, dma, gfp | __GFP_ZERO);
+
+	if (!pages)
+		return NULL;
+
+	kmemleak_ignore(pages);
+	return pages;
+}
+
+static void mtk_iommu_free_pgt(struct device *dev,
+				void *pages, dma_addr_t dma)
+{
+	dma_free_coherent(dev, M2701_IOMMU_PGT_SIZE, pages, dma);
+}
+
+static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data)
+{
+	struct mtk_iommu_domain *dom = data->m4u_dom;
+
+	spin_lock_init(&dom->pgtlock);
+
+	dom->pgt_va = mtk_iommu_alloc_pgt(data->dev,
+				&dom->pgt_pa, GFP_KERNEL);
+	if (!dom->pgt_va)
+		return -ENOMEM;
+
+	writel(dom->pgt_pa, data->base + REG_MMU_PT_BASE_ADDR);
+
+	dom->cookie = (void *)data;
+
+	return 0;
+}
+
+static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type)
+{
+	struct mtk_iommu_domain *dom;
+
+	if (type != IOMMU_DOMAIN_UNMANAGED)
+		return NULL;
+
+	dom = kzalloc(sizeof(*dom), GFP_KERNEL);
+	if (!dom)
+		return NULL;
+
+	return &dom->domain;
+}
+
+static void mtk_iommu_domain_free(struct iommu_domain *domain)
+{
+	kfree(to_mtk_domain(domain));
+}
+
+static int mtk_iommu_attach_device(struct iommu_domain *domain,
+				   struct device *dev)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
+	struct mtk_iommu_data *data;
+	int ret;
+
+	if (!priv)
+		return -ENODEV;
+
+	data = dev_get_drvdata(priv->m4udev);
+	if (!data->m4u_dom) {
+		data->m4u_dom = dom;
+		ret = mtk_iommu_domain_finalise(data);
+		if (ret) {
+			data->m4u_dom = NULL;
+			return ret;
+		}
+	} else if (data->m4u_dom != dom) {
+		/* All the client devices should be in the same m4u domain */
+		dev_err(dev, "try to attach into the error iommu domain\n");
+		return -EPERM;
+	}
+
+	mtk_iommu_config(data, dev, true);
+	return 0;
+}
+
+static void mtk_iommu_detach_device(struct iommu_domain *domain,
+				    struct device *dev)
+{
+	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
+	struct mtk_iommu_data *data;
+
+	if (!priv)
+		return;
+
+	data = dev_get_drvdata(priv->m4udev);
+	mtk_iommu_config(data, dev, false);
+}
+
+static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
+			 phys_addr_t paddr, size_t size, int prot)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct mtk_iommu_data *data = dom->cookie;
+	unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT;
+	unsigned long flags;
+	unsigned int i;
+	u32 *pgt_base_iova = dom->pgt_va;
+	u32 pabase = (u32)paddr;
+	int map_size = 0;
+
+	spin_lock_irqsave(&dom->pgtlock, flags);
+	pgt_base_iova += iova  >> MT2701_IOMMU_PAGE_SHIFT;
+	for (i = 0; i < page_num; i++) {
+		if (pgt_base_iova[i])
+			break;
+		pgt_base_iova[i] = pabase | F_DESC_VALID | F_DESC_NONSEC;
+		pabase += MT2701_IOMMU_PAGE_SIZE;
+		map_size += MT2701_IOMMU_PAGE_SIZE;
+	}
+
+	spin_unlock_irqrestore(&dom->pgtlock, flags);
+
+	mtk_iommu_tlb_flush_range(data, iova, size);
+
+	return map_size == size ? 0 : -EEXIST;
+}
+
+static size_t mtk_iommu_unmap(struct iommu_domain *domain,
+			      unsigned long iova, size_t size)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct mtk_iommu_data *data = dom->cookie;
+	unsigned long flags;
+	u32 *pgt_base_iova = dom->pgt_va;
+	unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT;
+
+	spin_lock_irqsave(&dom->pgtlock, flags);
+	pgt_base_iova += iova  >> MT2701_IOMMU_PAGE_SHIFT;
+	memset(pgt_base_iova, 0, page_num * sizeof(u32));
+
+	spin_unlock_irqrestore(&dom->pgtlock, flags);
+
+	mtk_iommu_tlb_flush_range(data, iova, size);
+
+	return size;
+}
+
+static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
+					  dma_addr_t iova)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	unsigned long flags;
+	phys_addr_t pa;
+
+	spin_lock_irqsave(&dom->pgtlock, flags);
+	pa = *((u32 *)((u32 *)dom->pgt_va + (iova >> MT2701_IOMMU_PAGE_SHIFT)));
+	pa = pa & (~(MT2701_IOMMU_PAGE_SIZE - 1));
+	spin_unlock_irqrestore(&dom->pgtlock, flags);
+
+	return pa;
+}
+
+/*
+ * MTK generaion one iommu HW only support one iommu domain, and all the client
+ * sharing the same iova address space.
+ */
+static int mtk_iommu_create_mapping(struct device *dev,
+				    struct of_phandle_args *args)
+{
+	struct mtk_iommu_client_priv *head, *priv, *next;
+	struct platform_device *m4updev;
+	struct dma_iommu_mapping *mtk_mapping;
+	struct device *m4udev;
+	int ret;
+
+	if (args->args_count != 1) {
+		dev_err(dev, "invalid #iommu-cells(%d) property for IOMMU\n",
+			args->args_count);
+		return -EINVAL;
+	}
+
+	if (!dev->archdata.iommu) {
+		/* Get the m4u device */
+		m4updev = of_find_device_by_node(args->np);
+		of_node_put(args->np);
+		if (WARN_ON(!m4updev))
+			return -EINVAL;
+
+		head = kzalloc(sizeof(*head), GFP_KERNEL);
+		if (!head)
+			return -ENOMEM;
+
+		dev->archdata.iommu = head;
+		INIT_LIST_HEAD(&head->client);
+		head->m4udev = &m4updev->dev;
+	} else {
+		head = dev->archdata.iommu;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto err_free_mem;
+	}
+	priv->mtk_m4u_id = args->args[0];
+	list_add_tail(&priv->client, &head->client);
+
+	m4udev = head->m4udev;
+	mtk_mapping = m4udev->archdata.iommu;
+	if (!mtk_mapping) {
+		/* MTK iommu support 4GB iova address space. */
+		mtk_mapping = arm_iommu_create_mapping(&platform_bus_type,
+						0, 1ULL << 32);
+		if (IS_ERR(mtk_mapping)) {
+			ret = PTR_ERR(mtk_mapping);
+			goto err_free_mem;
+		}
+		m4udev->archdata.iommu = mtk_mapping;
+	}
+
+	ret = arm_iommu_attach_device(dev, mtk_mapping);
+	if (ret)
+		goto err_release_mapping;
+
+	return 0;
+
+err_release_mapping:
+	arm_iommu_release_mapping(mtk_mapping);
+	m4udev->archdata.iommu = NULL;
+err_free_mem:
+	list_for_each_entry_safe(priv, next, &head->client, client)
+		kfree(priv);
+	kfree(head);
+	dev->archdata.iommu = NULL;
+	return ret;
+}
+
+static int mtk_iommu_add_device(struct device *dev)
+{
+	struct iommu_group *group;
+	struct device_node *np;
+	struct of_phandle_args iommu_spec;
+	int idx = 0;
+
+	while (!of_parse_phandle_with_args(dev->of_node, "iommus",
+				   "#iommu-cells", idx,
+				   &iommu_spec)) {
+		np = iommu_spec.np;
+		mtk_iommu_create_mapping(dev, &iommu_spec);
+
+		of_node_put(np);
+		idx++;
+	}
+
+	if (!dev->archdata.iommu) /* Not a iommu client device */
+		return -ENODEV;
+
+	group = iommu_group_get_for_dev(dev);
+	if (IS_ERR(group))
+		return PTR_ERR(group);
+
+	iommu_group_put(group);
+	return 0;
+}
+
+static void mtk_iommu_remove_device(struct device *dev)
+{
+	struct mtk_iommu_client_priv *head, *cur, *next;
+
+	head = dev->archdata.iommu;
+	if (!head)
+		return;
+
+	list_for_each_entry_safe(cur, next, &head->client, client) {
+		list_del(&cur->client);
+		kfree(cur);
+	}
+	kfree(head);
+	dev->archdata.iommu = NULL;
+
+	iommu_group_remove_device(dev);
+}
+
+static struct iommu_group *mtk_iommu_device_group(struct device *dev)
+{
+	struct mtk_iommu_data *data;
+	struct mtk_iommu_client_priv *priv;
+
+	priv = dev->archdata.iommu;
+	if (!priv)
+		return ERR_PTR(-ENODEV);
+
+	/* All the client devices are in the same m4u iommu-group */
+	data = dev_get_drvdata(priv->m4udev);
+	if (!data->m4u_group) {
+		data->m4u_group = iommu_group_alloc();
+		if (IS_ERR(data->m4u_group))
+			dev_err(dev, "Failed to allocate M4U IOMMU group\n");
+	}
+	return data->m4u_group;
+}
+
+static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
+{
+	u32 regval;
+	int ret;
+
+	ret = clk_prepare_enable(data->bclk);
+	if (ret) {
+		dev_err(data->dev, "Failed to enable iommu bclk(%d)\n", ret);
+		return ret;
+	}
+
+	regval = F_MMU_CTRL_COHERENT_EN | F_MMU_TF_PROTECT_SEL(2);
+	writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
+
+	regval = F_INT_TRANSLATION_FAULT |
+		F_INT_MAIN_MULTI_HIT_FAULT |
+		F_INT_INVALID_PA_FAULT |
+		F_INT_ENTRY_REPLACEMENT_FAULT |
+		F_INT_TABLE_WALK_FAULT |
+		F_INT_TLB_MISS_FAULT |
+		F_INT_PFH_DMA_FIFO_OVERFLOW |
+		F_INT_MISS_DMA_FIFO_OVERFLOW;
+	writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL);
+
+	/* protect memory,hw will write here while translation fault */
+	writel_relaxed(data->protect_base,
+			data->base + REG_MMU_IVRP_PADDR);
+
+	writel_relaxed(F_MMU_DCM_ON, data->base + REG_MMU_DCM);
+
+	if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
+			     dev_name(data->dev), (void *)data)) {
+		writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR);
+		clk_disable_unprepare(data->bclk);
+		dev_err(data->dev, "Failed @ IRQ-%d Request\n", data->irq);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static struct iommu_ops mtk_iommu_ops = {
+	.domain_alloc	= mtk_iommu_domain_alloc,
+	.domain_free	= mtk_iommu_domain_free,
+	.attach_dev	= mtk_iommu_attach_device,
+	.detach_dev	= mtk_iommu_detach_device,
+	.map		= mtk_iommu_map,
+	.unmap		= mtk_iommu_unmap,
+	.map_sg		= default_iommu_map_sg,
+	.iova_to_phys	= mtk_iommu_iova_to_phys,
+	.add_device	= mtk_iommu_add_device,
+	.remove_device	= mtk_iommu_remove_device,
+	.device_group	= mtk_iommu_device_group,
+	.pgsize_bitmap	= ~0UL << MT2701_IOMMU_PAGE_SHIFT,
+};
+
+static const struct of_device_id mtk_iommu_of_ids[] = {
+	{ .compatible = "mediatek,mt2701-m4u", },
+	{}
+};
+
+static const struct component_master_ops mtk_iommu_com_ops = {
+	.bind		= mtk_iommu_bind,
+	.unbind		= mtk_iommu_unbind,
+};
+
+static int mtk_iommu_probe(struct platform_device *pdev)
+{
+	struct mtk_iommu_data		*data;
+	struct device			*dev = &pdev->dev;
+	struct resource			*res;
+	struct component_match		*match = NULL;
+	void				*protect;
+	int				i, larb_nr, ret;
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->dev = dev;
+
+	/* Protect memory. HW will access here while translation fault.*/
+	protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL);
+	if (!protect)
+		return -ENOMEM;
+	data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(data->base))
+		return PTR_ERR(data->base);
+
+	data->irq = platform_get_irq(pdev, 0);
+	if (data->irq < 0)
+		return data->irq;
+
+	data->bclk = devm_clk_get(dev, "bclk");
+	if (IS_ERR(data->bclk))
+		return PTR_ERR(data->bclk);
+
+	larb_nr = of_count_phandle_with_args(dev->of_node,
+					"mediatek,larbs", NULL);
+	if (larb_nr < 0)
+		return larb_nr;
+	data->smi_imu.larb_nr = larb_nr;
+
+	for (i = 0; i < larb_nr; i++) {
+		struct device_node *larbnode;
+		struct platform_device *plarbdev;
+
+		larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
+		if (!larbnode)
+			return -EINVAL;
+
+		if (!of_device_is_available(larbnode))
+			continue;
+
+		plarbdev = of_find_device_by_node(larbnode);
+		of_node_put(larbnode);
+		if (!plarbdev) {
+			plarbdev = of_platform_device_create(
+						larbnode, NULL,
+						platform_bus_type.dev_root);
+			if (!plarbdev)
+				return -EPROBE_DEFER;
+		}
+		data->smi_imu.larb_imu[i].dev = &plarbdev->dev;
+
+		component_match_add(dev, &match, compare_of, larbnode);
+	}
+
+	platform_set_drvdata(pdev, data);
+
+	ret = mtk_iommu_hw_init(data);
+	if (ret)
+		return ret;
+
+	if (!iommu_present(&platform_bus_type))
+		bus_set_iommu(&platform_bus_type,  &mtk_iommu_ops);
+
+	return component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
+}
+
+static int mtk_iommu_remove(struct platform_device *pdev)
+{
+	struct mtk_iommu_data *data = platform_get_drvdata(pdev);
+	struct mtk_iommu_domain *dom = data->m4u_dom;
+	struct device *dev = &pdev->dev;
+
+	mtk_iommu_free_pgt(dev, dom->pgt_va, dom->pgt_pa);
+
+	if (iommu_present(&platform_bus_type))
+		bus_set_iommu(&platform_bus_type, NULL);
+
+	clk_disable_unprepare(data->bclk);
+	devm_free_irq(&pdev->dev, data->irq, data);
+	component_master_del(&pdev->dev, &mtk_iommu_com_ops);
+	return 0;
+}
+
+static int __maybe_unused mtk_iommu_suspend(struct device *dev)
+{
+	struct mtk_iommu_data *data = dev_get_drvdata(dev);
+	struct mtk_iommu_suspend_reg *reg = &data->reg;
+	void __iomem *base = data->base;
+
+	reg->standard_axi_mode = readl_relaxed(base +
+					       REG_MMU_STANDARD_AXI_MODE);
+	reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM);
+	reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG);
+	reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL);
+	return 0;
+}
+
+static int __maybe_unused mtk_iommu_resume(struct device *dev)
+{
+	struct mtk_iommu_data *data = dev_get_drvdata(dev);
+	struct mtk_iommu_suspend_reg *reg = &data->reg;
+	void __iomem *base = data->base;
+
+	writel_relaxed(data->m4u_dom->pgt_pa, base + REG_MMU_PT_BASE_ADDR);
+	writel_relaxed(reg->standard_axi_mode,
+		       base + REG_MMU_STANDARD_AXI_MODE);
+	writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM);
+	writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG);
+	writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL);
+	writel_relaxed(data->protect_base, base + REG_MMU_IVRP_PADDR);
+	return 0;
+}
+
+const struct dev_pm_ops mtk_iommu_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume)
+};
+
+static struct platform_driver mtk_iommu_driver = {
+	.probe	= mtk_iommu_probe,
+	.remove	= mtk_iommu_remove,
+	.driver	= {
+		.name = "mtk-iommu",
+		.of_match_table = mtk_iommu_of_ids,
+		.pm = &mtk_iommu_pm_ops,
+	}
+};
+
+static int __init m4u_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&mtk_iommu_driver);
+	if (ret)
+		bus_set_iommu(&platform_bus_type, NULL);
+
+	return ret;
+}
+
+static void __exit m4u_exit(void)
+{
+	return platform_driver_unregister(&mtk_iommu_driver);
+}
+
+subsys_initcall(m4u_init);
+module_exit(m4u_exit);
+
+MODULE_DESCRIPTION("IOMMU API for MTK architected m4u v1 implementations");
+MODULE_AUTHOR("Honghui Zhang <honghui.zhang at mediatek.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.8.1.1.dirty



From oneukum at suse.com  Thu May 19 05:01:01 2016
From: oneukum at suse.com (Oliver Neukum)
Date: Thu, 19 May 2016 14:01:01 +0200
Subject: [PSCI DISCUSS] How to implement standby and suspend-to-ram by PSCI
In-Reply-To: <AM3PR04MB0805D7F5375413C154DFB981844A0@AM3PR04MB0805.eurprd04.prod.outlook.com>
References: <DB3PR04MB0812DAA98F71C30E8A8832E3847D0@DB3PR04MB0812.eurprd04.prod.outlook.com>
 <572C9BF2.9010004@arm.com>
 <DB3PR04MB08125A628F5034749F8109D884730@DB3PR04MB0812.eurprd04.prod.outlook.com>
 <1463486036.19237.9.camel@suse.com>
 <AM3PR04MB0805D7F5375413C154DFB981844A0@AM3PR04MB0805.eurprd04.prod.outlook.com>
Message-ID: <1463659261.14323.3.camel@suse.com>

On Thu, 2016-05-19 at 10:27 +0000, Hongbo Zhang wrote:
> > For the pm module of the core kernel a low power state is a sleep
> > state if even one of three conditions is met:
> > 
> > a) a device that can be used for input is not a source of wake ups
> > b) tasks need to be frozen to enter it
> > c) the display goes off, while it should be on
> > 
> > Generally runtime PM is better if you can get the same results.
> > Going to a system sleep state is a necessary evil.


> As I just explained in previous reply, many devices in our Soc cannot
> be physically clock or power gated, all the non-wakeup devices can
> only be gated off at same time by a PM module, so runtime PM doesn't
> fit for us well.

You are looking for a contradiction where none is to be found. We have
PM domains which allow you to model common clocks and gates. You simply
use the driver core and it will use the common gate when every device is
idle. Obviously this is also true when the system is suspended. But not
necessarily only when the system is suspended.

	Regards
		Oliver




From slemieux.tyco at gmail.com  Thu May 19 05:09:29 2016
From: slemieux.tyco at gmail.com (Sylvain Lemieux)
Date: Thu, 19 May 2016 08:09:29 -0400
Subject: [PATCH] ARM: lpc32xx: fix NR_IRQS confict
In-Reply-To: <573D8F92.3010902@mleia.com>
References: <1463646968-1047336-1-git-send-email-arnd@arndb.de>
 <573D8F92.3010902@mleia.com>
Message-ID: <1463659769.14963.4.camel@localhost>

Hi Arnd,

On Thu, 2016-05-19 at 13:04 +0300, Vladimir Zapolskiy wrote:
> Hi Arnd,
> 
> On 19.05.2016 11:35, Arnd Bergmann wrote:
> > With the change to sparse IRQs, the lpc32xx platform gets a warning about
> > conflicting macros:
> > 
> > In file included from arch/arm/mach-lpc32xx/irq.c:31:0:
> > arch/arm/mach-lpc32xx/include/mach/irqs.h:115:0: warning: "NR_IRQS" redefined
> >  #define NR_IRQS    96
> > arch/arm/include/asm/irq.h:9:0: note: this is the location of the previous definition
> >  #define NR_IRQS NR_IRQS_LEGACY
> > 
> > In the irq controller driver, we surely need the local number instead of
> > the generic NR_IRQS definition, so I'm renaming that one to LPC32XX_NR_IRQS.
> > 
> > Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> > Fixes: 8cb17b5ed017 ("irqchip: Add LPC32xx interrupt controller driver")
> 
> I think that the entire removal of arch/arm/mach-lpc32xx/irq.c is the proper fix,
> since it is a dead code now - http://www.spinics.net/lists/arm-kernel/msg499976.html
> 
> I believe you can apply that change and add Fixes: tag.
> 

I also submitted a patch that remove this warning at the source
(GPIO driver broken to_irq support), until the GPIO driver update is
done.

Please refer to this link:
http://thread.gmane.org/gmane.linux.kernel.gpio/16837


Sylvain

> --
> With best wishes,
> Vladimir




From thomas.petazzoni at free-electrons.com  Thu May 19 05:11:34 2016
From: thomas.petazzoni at free-electrons.com (Thomas Petazzoni)
Date: Thu, 19 May 2016 14:11:34 +0200
Subject: [PATCH] arm64: configs: enable PCIe driver for Armada 7K/8K
Message-ID: <1463659894-20585-1-git-send-email-thomas.petazzoni@free-electrons.com>

This patch enables the driver for the PCIe host controller found on
the Marvell Armada 7K/8K ARM64 SoCs.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 0bd559a..23821c2 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -63,6 +63,7 @@ CONFIG_PCI_XGENE=y
 CONFIG_PCI_LAYERSCAPE=y
 CONFIG_PCI_HISI=y
 CONFIG_PCIE_QCOM=y
+CONFIG_PCIE_ARMADA_8K=y
 CONFIG_ARM64_VA_BITS_48=y
 CONFIG_SCHED_MC=y
 CONFIG_PREEMPT=y
-- 
2.7.4



From nicolas.ferre at atmel.com  Thu May 19 05:28:48 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Thu, 19 May 2016 14:28:48 +0200
Subject: [PATCH] ARM: at91: Add DT support for Olimex SAM9-L9260 board.
In-Reply-To: <20160518232925.GA6545@rob-hp-laptop>
References: <1463574766-15568-1-git-send-email-raashidmuhammed@zilogic.com>
 <20160518232925.GA6545@rob-hp-laptop>
Message-ID: <573DB180.9030200@atmel.com>

Le 19/05/2016 01:29, Rob Herring a ?crit :
> On Wed, May 18, 2016 at 06:02:46PM +0530, Raashid Muhammed wrote:
>> From: Raashid Muhammed <raashidmuhammed at zilogic.com>
>>
>> sam9-l9260 is a low cost board designed by Olimex.
>>
>> More infomation is available at:
>> https://www.olimex.com/Products/ARM/Atmel/SAM9-L9260/
>>
>> Signed-off-by: Raashid Muhammed <raashidmuhammed at zilogic.com>
>> Reviewed-by: Vijay Kumar B. <vijaykumar at bravegnu.org>
>> ---
>>  .../devicetree/bindings/arm/olimex-at91.txt        |   6 ++
>>  arch/arm/boot/dts/Makefile                         |   1 +
>>  arch/arm/boot/dts/sam9-l9260.dts                   | 108 +++++++++++++++++++++

For AT91-based boards, please use this prefix: "at91-" as stated in the
Atmel README file:
http://lxr.free-electrons.com/source/Documentation/arm/Atmel/README#L127

So I would recommend this name instead:
at91-sam9-l9260.dts


>>  3 files changed, 115 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/arm/olimex-at91.txt
>>  create mode 100644 arch/arm/boot/dts/sam9-l9260.dts
>>
>> diff --git a/Documentation/devicetree/bindings/arm/olimex-at91.txt b/Documentation/devicetree/bindings/arm/olimex-at91.txt
>> new file mode 100644
>> index 0000000..0587d63
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/olimex-at91.txt
>> @@ -0,0 +1,6 @@
>> +Olimex AT91 Device Tree Bindings
>> +--------------------------------
> 
> There's not an existing at91 or olimex file this would fit into? We 
> don't need 1 file per board.
> 
>> +
>> +SAM9-L9260 Board
>> +Required root node properties:
>> +    - compatible = "olimex,sam9-l9260", "atmel,at91sam9260";

I don't think this file is needed at all actually. We have a lot of
board files and none of them have a dedicated or particular entry for them.


>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>> index 95c1923..ae3b50f 100644
>> --- a/arch/arm/boot/dts/Makefile
>> +++ b/arch/arm/boot/dts/Makefile
>> @@ -19,6 +19,7 @@ dtb-$(CONFIG_SOC_SAM_V4_V5) += \
>> 	usb_a9260.dtb \
>> 	at91sam9261ek.dtb \
>> 	at91sam9263ek.dtb \
>> +	sam9-l9260.dtb \

Ditto about the file name.

>> 	tny_a9263.dtb \
>> 	usb_a9263.dtb \
>> 	at91-foxg20.dtb \
>> diff --git a/arch/arm/boot/dts/sam9-l9260.dts b/arch/arm/boot/dts/sam9-l9260.dts
>> new file mode 100644
>> index 0000000..3ddf7af
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/sam9-l9260.dts
>> @@ -0,0 +1,108 @@
>> +/*
>> + * sam9-l9260.dts - Device Tree file for Olimex SAM9-L9260 board
>> + *
>> + *  Copyright (C) 2016 Raashid Muhammed <raashidmuhammed at zilogic.com>
>> + *
>> + * Licensed under GPLv2 or later.
>> + */
>> +/dts-v1/;
>> +#include "at91sam9260.dtsi"
>> +
>> +/ {
>> +	model = "Olimex sam9-l9260";
>> +	compatible = "olimex,sam9-l9260", "atmel,at91sam9260", "atmel,at91sam9";
>> +
>> +	chosen {
>> +		bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
> 
> use stdout-path instead of console on the command line. Actually, you 
> should then drop the rest of the bootargs. They are all user specific.

example of stdout-path:
http://lxr.free-electrons.com/source/arch/arm/boot/dts/at91-sama5d2_xplained.dts#L55

>> +	 };
>> +
>> +	 memory {
>> +		reg = <0x20000000 0x4000000>;
>> +	 };
>> +
>> +	 clocks {
>> +		slow_xtal {
>> +			clock-frequency = <32768>;
>> +		};
>> +
>> +		main_xtal {
>> +			clock-frequency = <18432000>;
>> +		};
>> +	 };
>> +
>> +	 ahb {
>> +		apb {
>> +			dbgu: serial at fffff200 {

We like to sort node by their address: can you rearrange them like this?

>> +				status = "okay";
>> +			 };
>> +
>> +			macb0: ethernet at fffc4000 {
>> +				phy-mode = "mii";
>> +				status = "okay";

I advice you to add the phy address for any Ethernet interface like:

  phy0: ethernet-phy at 1 {
        reg = <1>;
  };

for a phy address configured as 0x1.


>> +			 };
>> +
>> +			spi0: spi at fffc8000 {
>> +				status = "okay";

Nitpicking: "status" property is usually the last one of the node
(before the child nodes if they exist)

>> +				cs-gpios = <&pioC 11 0>, <0>, <0>, <0>;
>> +				mtd_dataflash at 0 {
>> +					compatible = "atmel,at45", "atmel,dataflash";
>> +					spi-max-frequency = <15000000>;
>> +					reg = <0>;
>> +				};
>> +			};
>> +
>> +			mmc0: mmc at fffa8000 {
>> +				pinctrl-0 = <
>> +					&pinctrl_board_mmc0
>> +					&pinctrl_mmc0_clk
>> +					&pinctrl_mmc0_slot1_cmd_dat0
>> +					&pinctrl_mmc0_slot1_dat1_3>;
>> +				status = "okay";
>> +				slot at 1 {
>> +					reg = <1>;
>> +					bus-width = <4>;
>> +					cd-gpios = <&pioC 8 GPIO_ACTIVE_HIGH>;
>> +					wp-gpios = <&pioC 4 GPIO_ACTIVE_HIGH>;
>> +				};
>> +			};
>> +
>> +			pinctrl at fffff400 {
>> +				mmc0 {
>> +					pinctrl_board_mmc0: mmc0-board {
>> +						atmel,pins =
>> +							<AT91_PIOC 8 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH	/* PC08 gpio CD pin pull up and deglitch */

Here, you can remove the duplicate information in the comments: just
keep useful "CD" or "WP" information.

>> +							 AT91_PIOC 4 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP>;	/* PC04 gpio WP pin pull up */
>> +					};
>> +				};
>> +			};
>> +
>> +
>> +		 };
>> +
>> +		 usb0: ohci at 00500000 {
> 
> Drop the leading 0. You'll need to fixup the base dts.
> 
>> +		       status = "okay";
>> +		 };
>> +
>> +		 nand0: nand at 40000000 {
>> +		       nand-bus-width = <8>;
>> +		       nand-ecc-mode = "soft";
>> +		       nand-on-flash-bbt = <1>;
>> +		       status = "okay";
>> +		 };
>> +	 };
>> +
>> +	 i2c at 0 {
>> +		status = "okay";
>> +	 };
>> +
>> +	 leds {
>> +		compatible = "gpio-leds";
>> +
>> +		b0 {
>> +			label = "b0";
>> +			gpios = <&pioA 6 GPIO_ACTIVE_HIGH>;
>> +			linux,default-trigger = "heartbeat";
>> +		};
>> +
>> +	};
>> +};
>> --
>> 2.1.4

Thanks a lot for this board .dts file. I'll be happy to add the support
for this Olimex board!

Bye,
-- 
Nicolas Ferre


From robh at kernel.org  Thu May 19 05:50:20 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 19 May 2016 07:50:20 -0500
Subject: [PATCH] ARM: at91: Add DT support for Olimex SAM9-L9260 board.
In-Reply-To: <573DB180.9030200@atmel.com>
References: <1463574766-15568-1-git-send-email-raashidmuhammed@zilogic.com>
 <20160518232925.GA6545@rob-hp-laptop> <573DB180.9030200@atmel.com>
Message-ID: <CAL_JsqLXaq7KKPKnSTcRBswnvdZiUS=1wb35oo+JrjY3_tPRJQ@mail.gmail.com>

On Thu, May 19, 2016 at 7:28 AM, Nicolas Ferre <nicolas.ferre at atmel.com> wrote:
> Le 19/05/2016 01:29, Rob Herring a ?crit :
>> On Wed, May 18, 2016 at 06:02:46PM +0530, Raashid Muhammed wrote:
>>> From: Raashid Muhammed <raashidmuhammed at zilogic.com>
>>>
>>> sam9-l9260 is a low cost board designed by Olimex.
>>>
>>> More infomation is available at:
>>> https://www.olimex.com/Products/ARM/Atmel/SAM9-L9260/
>>>
>>> Signed-off-by: Raashid Muhammed <raashidmuhammed at zilogic.com>
>>> Reviewed-by: Vijay Kumar B. <vijaykumar at bravegnu.org>
>>> ---
>>>  .../devicetree/bindings/arm/olimex-at91.txt        |   6 ++
>>>  arch/arm/boot/dts/Makefile                         |   1 +
>>>  arch/arm/boot/dts/sam9-l9260.dts                   | 108 +++++++++++++++++++++
>
> For AT91-based boards, please use this prefix: "at91-" as stated in the
> Atmel README file:
> http://lxr.free-electrons.com/source/Documentation/arm/Atmel/README#L127
>
> So I would recommend this name instead:
> at91-sam9-l9260.dts
>
>
>>>  3 files changed, 115 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/arm/olimex-at91.txt
>>>  create mode 100644 arch/arm/boot/dts/sam9-l9260.dts
>>>
>>> diff --git a/Documentation/devicetree/bindings/arm/olimex-at91.txt b/Documentation/devicetree/bindings/arm/olimex-at91.txt
>>> new file mode 100644
>>> index 0000000..0587d63
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/arm/olimex-at91.txt
>>> @@ -0,0 +1,6 @@
>>> +Olimex AT91 Device Tree Bindings
>>> +--------------------------------
>>
>> There's not an existing at91 or olimex file this would fit into? We
>> don't need 1 file per board.
>>
>>> +
>>> +SAM9-L9260 Board
>>> +Required root node properties:
>>> +    - compatible = "olimex,sam9-l9260", "atmel,at91sam9260";
>
> I don't think this file is needed at all actually. We have a lot of
> board files and none of them have a dedicated or particular entry for them.

Well, they should have one.

Rob


From catalin.marinas at arm.com  Thu May 19 05:50:40 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 19 May 2016 13:50:40 +0100
Subject: [PATCH] arm64: cpuinfo: add AArch64 & elf platform for app
 compatibility
In-Reply-To: <573D9E40.4000705@hisilicon.com>
References: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>
 <20160519104925.GL22378@e104818-lin.cambridge.arm.com>
 <573D9E40.4000705@hisilicon.com>
Message-ID: <20160519125039.GN22378@e104818-lin.cambridge.arm.com>

On Thu, May 19, 2016 at 07:06:40PM +0800, Xiaqing (A) wrote:
> 
> 
> ? 2016/5/19 18:49, Catalin Marinas ??:
> >On Thu, May 19, 2016 at 10:44:33AM +0800, x00195127 wrote:
> >>we find that some apps will read cpuinfo when start up,
> >>they need the string  as follows:
> >>"Processor       : AArch64 Processor rev 0 (aarch64)"
> >>
> >>Then thay could load the corresponding libs. But now
> >>arm64 platform's cpuinfo don't has this now, so
> >>we need add this.
> >
> >I have the same question as Martinez: what are those apps? If they are
> >64-bit apps, they can always assume AArch64 processor.
> 
> Those are 32-bit apps, and those apps are very popular in our country.

32-bit apps checking for "AArch64" is a really silly idea. What do they
do with this information?

I'm rather inclined to merge this patch:

diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 3808470486f3..623d7d291dd6 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -127,7 +127,8 @@ static int c_show(struct seq_file *m, void *v)
 		 * software which does already (at least for 32-bit).
 		 */
 		seq_puts(m, "Features\t:");
-		if (personality(current->personality) == PER_LINUX32) {
+		if (is_compat_task() ||
+		    personality(current->personality) == PER_LINUX32) {
 #ifdef CONFIG_COMPAT
 			for (j = 0; compat_hwcap_str[j]; j++)
 				if (compat_elf_hwcap & (1 << j))

As discussed here:

http://article.gmane.org/gmane.linux.kernel/2209217

-- 
Catalin


From nicolas.ferre at atmel.com  Thu May 19 05:54:22 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Thu, 19 May 2016 14:54:22 +0200
Subject: [PATCH] ARM: dts: at91: add at91sam9260ek board DT
Message-ID: <1463662462-921-1-git-send-email-nicolas.ferre@atmel.com>

Add Device Tree source file for at91sam9260ek board. This official Atmel
Evaluation Kit is designed around a SoC based on a ARM 926 core the
at91sam9260.

The board is also added to the dts Makefile.

Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
---
Hi,

This DTS file was sitting in my kernel tree for a long time... So, revived and
updated, here it is as I'm sure it can be useful. Even if the board itself is
pretty old.

Bye,

 arch/arm/boot/dts/Makefile          |   1 +
 arch/arm/boot/dts/at91sam9260ek.dts | 211 ++++++++++++++++++++++++++++++++++++
 2 files changed, 212 insertions(+)
 create mode 100644 arch/arm/boot/dts/at91sam9260ek.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 8f9f1c2ac96b..6893415a53a3 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -17,6 +17,7 @@ dtb-$(CONFIG_SOC_SAM_V4_V5) += \
 	evk-pro3.dtb \
 	tny_a9260.dtb \
 	usb_a9260.dtb \
+	at91sam9260ek.dtb \
 	at91sam9261ek.dtb \
 	at91sam9263ek.dtb \
 	tny_a9263.dtb \
diff --git a/arch/arm/boot/dts/at91sam9260ek.dts b/arch/arm/boot/dts/at91sam9260ek.dts
new file mode 100644
index 000000000000..43875d18808f
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9260ek.dts
@@ -0,0 +1,211 @@
+/*
+ * Device Tree file for Atmel at91sam9260 Evaluation Kit
+ *
+ *  Copyright (C) 2016 Atmel,
+ *		  2016 Nicolas Ferre <nicolas.ferre at atmel.com>
+ *
+ * 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 "at91sam9260.dtsi"
+
+/ {
+	model = "Atmel at91sam9260ek";
+	compatible = "atmel,at91sam9260ek", "atmel,at91sam9260", "atmel,at91sam9";
+
+	chosen {
+		stdout-path = &dbgu;
+	};
+
+	memory {
+		reg = <0x20000000 0x4000000>;
+	};
+
+	clocks {
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
+	};
+
+	ahb {
+		apb {
+			usb1: gadget at fffa4000 {
+				atmel,vbus-gpio = <&pioC 5 GPIO_ACTIVE_HIGH>;
+				status = "okay";
+			};
+
+			mmc0: mmc at fffa8000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc0_slot1
+					&pinctrl_mmc0_clk
+					&pinctrl_mmc0_slot1_cmd_dat0
+					&pinctrl_mmc0_slot1_dat1_3>;
+				status = "okay";
+				slot at 1 {
+					reg = <1>;
+					bus-width = <4>;
+					cd-gpios = <&pioC 9 GPIO_ACTIVE_HIGH>;
+				};
+			};
+
+			usart0: serial at fffb0000 {
+				pinctrl-0 =
+					<&pinctrl_usart0
+					 &pinctrl_usart0_rts
+					 &pinctrl_usart0_cts
+					 &pinctrl_usart0_dtr_dsr
+					 &pinctrl_usart0_dcd
+					 &pinctrl_usart0_ri>;
+				status = "okay";
+			};
+
+			usart1: serial at fffb4000 {
+				status = "okay";
+			};
+
+			ssc0: ssc at fffbc000 {
+				status = "okay";
+				pinctrl-0 = <&pinctrl_ssc0_tx>;
+			};
+
+			macb0: ethernet at fffc4000 {
+				phy-mode = "rmii";
+				status = "okay";
+			};
+
+			spi0: spi at fffc8000 {
+				cs-gpios = <0>, <&pioC 11 0>, <0>, <0>;
+				mtd_dataflash at 0 {
+					compatible = "atmel,at45", "atmel,dataflash";
+					spi-max-frequency = <50000000>;
+					reg = <1>;
+				};
+			};
+
+			dbgu: serial at fffff200 {
+				status = "okay";
+			};
+
+			pinctrl at fffff400 {
+				board {
+					pinctrl_board_mmc0_slot1: mmc0_slot1-board {
+						atmel,pins =
+							<AT91_PIOC 9 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
+					};
+				};
+			};
+
+			shdwc at fffffd10 {
+				atmel,wakeup-counter = <10>;
+				atmel,wakeup-rtt-timer;
+			};
+
+			rtc at fffffd20 {
+				atmel,rtt-rtc-time-reg = <&gpbr 0x0>;
+				status = "okay";
+			};
+
+			watchdog at fffffd40 {
+				status = "okay";
+			};
+
+			gpbr: syscon at fffffd50 {
+				status = "okay";
+			};
+		};
+
+		usb0: ohci at 00500000 {
+			num-ports = <2>;
+			status = "okay";
+		};
+
+		nand0: nand at 40000000 {
+			nand-bus-width = <8>;
+			nand-ecc-mode = "soft";
+			nand-on-flash-bbt;
+			status = "okay";
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+
+		btn3 {
+			label = "Button 3";
+			gpios = <&pioA 30 GPIO_ACTIVE_LOW>;
+			linux,code = <0x103>;
+			gpio-key,wakeup;
+		};
+
+		btn4 {
+			label = "Button 4";
+			gpios = <&pioA 31 GPIO_ACTIVE_LOW>;
+			linux,code = <0x104>;
+			gpio-key,wakeup;
+		};
+	};
+
+	i2c at 0 {
+		status = "okay";
+
+		24c512 at 50 {
+			compatible = "24c512";
+			reg = <0x50>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		ds1 {
+			label = "ds1";
+			gpios = <&pioA 9 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		ds5 {
+			label = "ds5";
+			gpios = <&pioA 6 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
-- 
2.1.3



From jh80.chung at samsung.com  Thu May 19 06:07:49 2016
From: jh80.chung at samsung.com (Jaehoon Chung)
Date: Thu, 19 May 2016 22:07:49 +0900
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <10b3dc0e-aebf-664b-b36b-c54692cd9983@rock-chips.com>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <5502CA4E.9060401@samsung.com>
 <CAD=FV=VX3ix-j4y95W1q8b-aVuVEN+4xsd8WLx2xcE7KPNJwRw@mail.gmail.com>
 <5506707D.40708@samsung.com> <55189F04.8000404@samsung.com>
 <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
 <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
 <573BCC8D.5090606@kernel-upstream.org>
 <CAD=FV=VneQR3wurjezBkRhtQiH+q-FfhDN8=Ym=XqtZpVmsdUw@mail.gmail.com>
 <573C3283.1040606@rock-chips.com>
 <CAD=FV=UoT2GRYWJWXEn_ccvKGgC+PzQM_BCtLHAa7jxzbaQ9SA@mail.gmail.com>
 <10b3dc0e-aebf-664b-b36b-c54692cd9983@rock-chips.com>
Message-ID: <573DBAA5.2070706@samsung.com>

On 05/19/2016 08:31 PM, Shawn Lin wrote:
> Hi,
> 
> On 2016/5/19 1:37, Doug Anderson wrote:
>> Hi,
>>
>> On Wed, May 18, 2016 at 2:14 AM, Shawn Lin <shawn.lin at rock-chips.com> wrote:
>>> Hi
>>>
>>>
>>> On 2016-5-18 12:12, Doug Anderson wrote:
>>>>
>>>> Hi,
>>>>
>>>> On Tue, May 17, 2016 at 6:59 PM, Shawn Lin
>>>> <shawn.lin at kernel-upstream.org> wrote:
>>>>>
>>>>> Could you try this patch to see if you can still find HLE?
>>>>>
>>>>> @@ -2356,12 +2356,22 @@ static void dw_mci_cmd_interrupt(struct dw_mci
>>>>> *host, u32 status)
>>>>>   static void dw_mci_handle_cd(struct dw_mci *host)
>>>>>   {
>>>>>          int i;
>>>>> +       int present;
>>>>>
>>>>>          for (i = 0; i < host->num_slots; i++) {
>>>>>                  struct dw_mci_slot *slot = host->slot[i];
>>>>>
>>>>>                  if (!slot)
>>>>>                          continue;
>>>>>
>>>>> +               present = !(mci_readl(slot->host, CDETECT) & (1 <<
>>>>> slot->id));
>>>>> +               if (present)
>>>>> +                       set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>>>>> +               else
>>>>> +                       clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>>>>
>>>>
>>>> No, because we don't use the builtin card detect on veyron.  ;)
>>>>
>>>> We use GPIO card detect because we didn't like the way JTAG and SD
>>>> interacted.  Also on rk3288 the builtin card detect line had the wrong
>>>> voltage domain (you couldn't detect a card when the IO lines were
>>>> powered off).  The builtin card detect line is always driven low on
>>>> veyron.
>>>
>>>
>>> Okay, I see.
>>>
>>>>
>>>>
>>>> I'm nearly certain that the root cause of my HLE errors is actually
>>>> related to the same problem addressed by the commit 7c5209c315ea
>>>> ("mmc: core: Increase delay for voltage to stabilize from 3.3V to
>>>> 1.8V").  I think that on minnie we're still on the hairy edge and
>>>> sometimes the line doesn't transition fast enough.
>>>
>>>
>>> Things are not so simple from your details.
>>>
>>> I was not enabling SD3.0 support, then I also found HLE sometimes.
>>> So it seems commit 7c5209c315ea does not contibute to this phenomenon.
>>
>> Just to clarify, in my case commit 7c5209c315ea didn't make the
>> problem worse, but made it better.  Just not better enough.  ;)
>>
>>
>>> The scenario looks like:
>>> remove sd-card -> mmc_sd_detect -> send status(CMD13) ->power_off ->
>>> set_ios -> setup_bus -> disabled clk , then HLE irq storm coming
>>>
>>> From the code of dw_mci_prepare_command:
>>> SDMMC_CMD_PRV_DAT_WAIT will not be used for CMD13, so we don't
>>> wait_busy here, then cmd code is loding into queue of dw_mmc but
>>> still failing send out because it's in busy?
>>>
>>> With my patch, things go well:
>>> remove sd-card -> clear bit of DW_MMC_CARD_PRESENT  -> send
>>> status(CMD13) return directly -> power_off -> set_ios -> setup_bus ->
>>> disable clk
>>>
>>> So why should we allow inquiry of card status if we sure the card is
>>> removed? I mean no any further cmds should be delivered.
>>
>> Quite honestly just dealing with the HLE error (my patch or
>> equivalent) might be a sane solution for the problem you describe.
> 
> Yes, your patch looks good to me, so it should be merged firstly. :)
> Then let's push it a bit further more that when HLEs are coming,
> somethings must be wrong(currently I don't see a obvious clue from
> the code itself although, I'm prone to think it belongs to the
> software issue).

We don't know what's main cause for HLE..But i also think it's relevant to SW issue.
But we need to consider all possibilities..

> 
> 
>>
>> dw_mmc needs to be able to work with an external card detect GPIO.
>> It's been part of the dw_mmc driver for a long time and is (in fact)
>> in use upstream at least by rk3288-veyron.  Any solution that only
>> works for internal card detect is not enough.  Just handling the HLE
>> error to deal with the interrupt storm and then letting Linux remove
>> the card (because of the card detect interrupt) seems totally OK to
>> me.
>>
> 
> Sure, some of rockchip Socs use gpio for CD because they don't
> have a internal CD, such as RK3036, right?
> 
>> Note: I'd be very curious if your problems get better if you disable
> 
> Not at all.
> 
>> the "grf_force_jtag" bit in the GRF.  If you're using the builtin card
>> detect and you use the boot default of "grf_force_jtag" then your pins
>> will be unmuxed behind your back when the card is ejected.  This could
>> be causing the dw_mmc controller to get confused.
> 
> Right, grf_force_jtag is also not a friend of mine. :)
> So I had disabled this function before I was debugging it.
> 
>>
>>
>>> And another question: should we wait busy for cmd13?
>>
>> I don't think so.  As I understand it CMD13 uses only the CMD line for
>> communication and it should be appropriate to send this when the bus
>> is "busy" (which means that the DATA lines are low).
> 
> Ahh... take back my question.. I was just considering a wired situation
> that pins are unmuxed on the background(cmd line as well) when cmd13 is
> delivering....
> 
> 
>>
>> Also: it seems odd that the HLE IRQ storm didn't come right after the
>> CMD 13 in your description above.  Are you sure it was the CMD 13 that
>> caused the HLEs, or could it has been something else?
> 
> Actually no. Any cmds be issued can trigger HLEs, I think, after sd card is removed When I hacked mmc_sd_detecd to send other cmds intead
> of cmd13.
> 
> From dw_mmc databook v270a(7.2.3 Clock Programming) we can see:
> The DWC_mobile_storage loads each of these registers only when the
> start_cmd bit and the Update_clk_regs_only bit in the CMD register are
> set. When a command is successfully loaded, the DWC_mobile_storage
> clears this bit, unless the DWC_mobile_storage already has another
> command in the queue, at which point it gives an HLE (Hardware Locked
> Error); for details on HLEs, refer to ?Error Handling? on page 233.
> Software should look for the start_cmd and the Update_clk_regs_only
> bits, and should also set the wait_prvdata_complete bit to ensure that
> clock parameters do not change during data transfer.
> 
> Maybe the cmd is trying to load(or somethings wrong with the
> controller?) when we disable the clk? That may explain my observation
> that HLEs came after disabling clk.

I agreed.

To Disable clock, it sends cmd with update_clk_regs_only and wait_prvdata_complete bit.
I think it's problem..(waiting for prvdata..)

If there are ongoing some data(read/write), then before disabling clock, waiting for completing previous data.
(But card was already removed, and it couldn't do anything.)
It's difficult to analyze the HLE..So After applying first, then we can solve this problem, step by step.

Best Regards,
Jaehoon Chung

> 
> 
>>
>>
>> -Doug
>>
>>
>>
> 
> 



From nicolas.ferre at atmel.com  Thu May 19 06:11:03 2016
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Thu, 19 May 2016 15:11:03 +0200
Subject: [PATCH] ARM: at91: Documentation: update the sama5d2 entry
Message-ID: <1463663463-1581-1-git-send-email-nicolas.ferre@atmel.com>

Update the Atmel SoC entry for SAMA5D2 with all the product variants. Add the
datasheet web link, now that it's available, for instant access to full product
documentation.

Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
---
 Documentation/arm/Atmel/README | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/Documentation/arm/Atmel/README b/Documentation/arm/Atmel/README
index 0931cf7e2e56..6ca78f818dbf 100644
--- a/Documentation/arm/Atmel/README
+++ b/Documentation/arm/Atmel/README
@@ -91,9 +91,15 @@ the Atmel website: http://www.atmel.com.
           http://www.atmel.com/Images/Atmel-11238-32-bit-Cortex-A5-Microcontroller-SAMA5D4_Datasheet.pdf
 
       - sama5d2 family
-        - sama5d27
+        - sama5d21
+        - sama5d22
+        - sama5d23
+        - sama5d24
+        - sama5d26
+        - sama5d27 (device superset)
+        - sama5d28 (device superset + environmental monitors)
         + Datasheet
-          Coming soon
+          http://www.atmel.com/Images/Atmel-11267-32-bit-Cortex-A5-Microcontroller-SAMA5D2_Datasheet.pdf
 
 
 Linux kernel information
-- 
2.1.3



From marcel.ziswiler at toradex.com  Thu May 19 06:15:24 2016
From: marcel.ziswiler at toradex.com (Marcel Ziswiler)
Date: Thu, 19 May 2016 13:15:24 +0000
Subject: [PATCH] arm: tegra: initial support for apalis tk1
In-Reply-To: <20160516155542.GA25949@rob-hp-laptop>
References: <1463056032-25888-1-git-send-email-marcel.ziswiler@toradex.com>
 <20160516155542.GA25949@rob-hp-laptop>
Message-ID: <1463663721.4958.18.camel@toradex.com>

On Mon, 2016-05-16 at 10:55 -0500, Rob Herring wrote:
> On Thu, May 12, 2016 at 02:27:12PM +0200, Marcel Ziswiler wrote:
> > 
> > This patch adds the device tree to support Toradex Apalis TK1 a
> > computer on module which can be used on different carrier boards.
> > 
> > The module consists of a Tegra TK1 SoC, a PMIC solution, 2 GB of
> > DDR3L
> > RAM, a bunch of level shifters, an eMMC, a TMP451 temperature
> > sensor
> > chip and an I210 gigabit Ethernet controller. Furthermore, there is
> > an
> > SGTL5000 audio codec plus a Kinetis MK20DN512 companion micro
> > controller for analogue, CAN and resistive touch functionality
> > which
> > are not yet supported. Anything that is not self contained on the
> > module is disabled by default.
> > 
> > The device tree for the Evaluation Board includes the module's
> > device
> > tree and enables the supported peripherals of the carrier board
> > (the
> > Evaluation Board supports almost all of them).
> > 
> > While at it also add the device tree binding documentation for
> > Apalis
> > TK1 as well as for Colibri T30 which was missing so far.
> "While at it" and "also" are keywords for put in a separate patch.

While I do agree in general in this case it is about missing device
tree documentation which has absolutely zero potential to break
bisectability or anything the like. Anyway, I will split it for a v2.

> > Signed-off-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>
> > 
> > ---
> > 
> > ?Documentation/devicetree/bindings/arm/tegra.txt |????4 +
> > ?arch/arm/boot/dts/Makefile??????????????????????|????1 +
> > ?arch/arm/boot/dts/tegra124-apalis-emc.dtsi??????| 2462
> > +++++++++++++++++++++++
> > ?arch/arm/boot/dts/tegra124-apalis-eval.dts??????|??283 +++
> > ?arch/arm/boot/dts/tegra124-apalis.dtsi??????????| 2058
> > +++++++++++++++++++
> > ?5 files changed, 4808 insertions(+)
> > ?create mode 100644 arch/arm/boot/dts/tegra124-apalis-emc.dtsi
> > ?create mode 100644 arch/arm/boot/dts/tegra124-apalis-eval.dts
> > ?create mode 100644 arch/arm/boot/dts/tegra124-apalis.dtsi
> > 
> > diff --git a/Documentation/devicetree/bindings/arm/tegra.txt
> > b/Documentation/devicetree/bindings/arm/tegra.txt
> > index 73278c6..7709f3d 100644
> > --- a/Documentation/devicetree/bindings/arm/tegra.txt
> > +++ b/Documentation/devicetree/bindings/arm/tegra.txt
> > @@ -31,8 +31,12 @@ board-specific compatible values:
> > ???nvidia,ventana
> > ???nvidia,whistler
> > ???toradex,apalis_t30
> > +??toradex,apalis_tk1
> > ???toradex,apalis_t30-eval
> > +??toradex,apalis_tk1-eval
> > ???toradex,colibri_t20-512
> > +??toradex,colibri_t30
> > +??toradex,colibri_t30-eval-v3
> > ???toradex,iris
> Please use '-' rather than '_' for new strings even if that's what?
> previous strings have. For ones that already in use in upstream dts?
> files, then keep the underscore.

OK, semantically so far we used '_' aka underscores as having a weaker
separation meaning (e.g. like a space) than '-' aka dashes which
separated the module from the carrier board part. We even once
discussed that the dash between eval and v3 for colibri_t30 should
actually rather be an underscore. I guess something like this is now no
more feasible or do you have any suggestions for us?

> > ?Trusted Foundations
> > diff --git a/arch/arm/boot/dts/Makefile
> > b/arch/arm/boot/dts/Makefile
> > index 06b6c2d..3a13d4f 100644
> > --- a/arch/arm/boot/dts/Makefile
> > +++ b/arch/arm/boot/dts/Makefile
> > @@ -793,6 +793,7 @@ dtb-$(CONFIG_ARCH_TEGRA_114_SOC) += \
> > ?	tegra114-roth.dtb \
> > ?	tegra114-tn7.dtb
> > ?dtb-$(CONFIG_ARCH_TEGRA_124_SOC) += \
> > +	tegra124-apalis-eval.dtb \
> > ?	tegra124-jetson-tk1.dtb \
> > ?	tegra124-nyan-big.dtb \
> > ?	tegra124-nyan-blaze.dtb \
> > diff --git a/arch/arm/boot/dts/tegra124-apalis-emc.dtsi
> > b/arch/arm/boot/dts/tegra124-apalis-emc.dtsi
> > new file mode 100644
> > index 0000000..31b31ea
> > --- /dev/null
> > +++ b/arch/arm/boot/dts/tegra124-apalis-emc.dtsi
> > @@ -0,0 +1,2462 @@
> > +/*
> > + * Copyright 2016 Toradex AG
> > + *
> > + * 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
> > + *?????version 2 as published by the Free Software Foundation.
> > + *
> > + *?????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 , 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.
> > + */
> > +
> > +/ {
> > +	clock at 0,60006000 {
> All these commas should be dropped. These have been fixed in -next
> and?
> will go into 4.7.

I guess you mean the zero followed by the comma, right? That only works
if tegra124.dtsi and with it all the other boards get migrated to this
as well. I can certainly send a patch for that as well if this is the
direction we want to go.

> > +		emc-timings-1 {
> > +			nvidia,ram-code = <1>;
> > +
> > +			timing-12750000 {
> > +				clock-frequency = <12750000>;
> > +				nvidia,parent-clock-frequency =
> > <408000000>;
> > +				clocks = <&tegra_car
> > TEGRA124_CLK_PLL_P>;
> > +				clock-names = "emc-parent";
> > +			};
> > +			timing-20400000 {
> > +				clock-frequency = <20400000>;
> > +				nvidia,parent-clock-frequency =
> > <408000000>;
> > +				clocks = <&tegra_car
> > TEGRA124_CLK_PLL_P>;
> > +				clock-names = "emc-parent";
> > +			};
> > +			timing-40800000 {
> > +				clock-frequency = <40800000>;
> > +				nvidia,parent-clock-frequency =
> > <408000000>;
> > +				clocks = <&tegra_car
> > TEGRA124_CLK_PLL_P>;
> > +				clock-names = "emc-parent";
> > +			};
> > +			timing-68000000 {
> > +				clock-frequency = <68000000>;
> > +				nvidia,parent-clock-frequency =
> > <408000000>;
> > +				clocks = <&tegra_car
> > TEGRA124_CLK_PLL_P>;
> > +				clock-names = "emc-parent";
> > +			};
> > +			timing-102000000 {
> > +				clock-frequency = <102000000>;
> > +				nvidia,parent-clock-frequency =
> > <408000000>;
> > +				clocks = <&tegra_car
> > TEGRA124_CLK_PLL_P>;
> > +				clock-names = "emc-parent";
> > +			};
> > +			timing-204000000 {
> > +				clock-frequency = <204000000>;
> > +				nvidia,parent-clock-frequency =
> > <408000000>;
> > +				clocks = <&tegra_car
> > TEGRA124_CLK_PLL_P>;
> > +				clock-names = "emc-parent";
> > +			};
> > +			timing-300000000 {
> > +				clock-frequency = <300000000>;
> > +				nvidia,parent-clock-frequency =
> > <600000000>;
> > +				clocks = <&tegra_car
> > TEGRA124_CLK_PLL_C>;
> > +				clock-names = "emc-parent";
> > +			};
> > +			timing-396000000 {
> > +				clock-frequency = <396000000>;
> > +				nvidia,parent-clock-frequency =
> > <792000000>;
> > +				clocks = <&tegra_car
> > TEGRA124_CLK_PLL_M>;
> > +				clock-names = "emc-parent";
> > +			};
> > +			timing-528000000 {
> > +				clock-frequency = <528000000>;
> > +				nvidia,parent-clock-frequency =
> > <528000000>;
> > +				clocks = <&tegra_car
> > TEGRA124_CLK_PLL_M_UD>;
> > +				clock-names = "emc-parent";
> > +			};
> > +			timing-600000000 {
> > +				clock-frequency = <600000000>;
> > +				nvidia,parent-clock-frequency =
> > <600000000>;
> > +				clocks = <&tegra_car
> > TEGRA124_CLK_PLL_C_UD>;
> > +				clock-names = "emc-parent";
> > +			};
> > +			timing-792000000 {
> > +				clock-frequency = <792000000>;
> > +				nvidia,parent-clock-frequency =
> > <792000000>;
> > +				clocks = <&tegra_car
> > TEGRA124_CLK_PLL_M_UD>;
> > +				clock-names = "emc-parent";
> > +			};
> > +			timing-924000000 {
> > +				clock-frequency = <924000000>;
> > +				nvidia,parent-clock-frequency =
> > <924000000>;
> > +				clocks = <&tegra_car
> > TEGRA124_CLK_PLL_M_UD>;
> > +				clock-names = "emc-parent";
> > +			};
> > +		};
> > +	};
> > +
> > +	emc at 0,7001b000 {
> > +		emc-timings-1 {
> > +			nvidia,ram-code = <1>;
> > +
> > +			timing-12750000 {
> > +				clock-frequency = <12750000>;
> > +
> > +				nvidia,emc-auto-cal-config =
> > <0xa1430000>;
> > +				nvidia,emc-auto-cal-config2 =
> > <0x00000000>;
> > +				nvidia,emc-auto-cal-config3 =
> > <0x00000000>;
> > +				nvidia,emc-auto-cal-interval =
> > <0x001fffff>;
> > +				nvidia,emc-bgbias-ctl0 =
> > <0x00000008>;
> > +				nvidia,emc-cfg = <0x73240000>;
> > +				nvidia,emc-cfg-2 = <0x000008c5>;
> > +				nvidia,emc-ctt-term-ctrl =
> > <0x00000802>;
> > +				nvidia,emc-mode-1 = <0x80100003>;
> > +				nvidia,emc-mode-2 = <0x80200008>;
> > +				nvidia,emc-mode-4 = <0x00000000>;
> > +				nvidia,emc-mode-reset =
> > <0x80001221>;
> > +				nvidia,emc-mrs-wait-cnt =
> > <0x000e000e>;
> > +				nvidia,emc-sel-dpd-ctrl =
> > <0x00040128>;
> > +				nvidia,emc-xm2dqspadctrl2 =
> > <0x0130b118>;
> > +				nvidia,emc-zcal-cnt-long =
> > <0x00000042>;
> > +				nvidia,emc-zcal-interval =
> > <0x00000000>;
> > +
> > +				nvidia,emc-configuration = <
> > +					0x00000000
> > +					0x00000003
> This is a bit long. Do multiple values per line.

OK. If keeping the 80 character limit one could get 3 values per line
which otherwise seems rather inconvenient. Should I just do two then or
allow for longer lines and putting 4 or even 8?

> > +					0x00000000
> > +					0x00000000
> > +					0x00000000
> > +					0x00000004
> > +					0x0000000a
> > +					0x00000005

Thanks, Rob.

From catalin.marinas at arm.com  Thu May 19 06:18:32 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 19 May 2016 14:18:32 +0100
Subject: [PATCH] arm64: cpuinfo: add AArch64 & elf platform for app
 compatibility
In-Reply-To: <20160519125039.GN22378@e104818-lin.cambridge.arm.com>
References: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>
 <20160519104925.GL22378@e104818-lin.cambridge.arm.com>
 <573D9E40.4000705@hisilicon.com>
 <20160519125039.GN22378@e104818-lin.cambridge.arm.com>
Message-ID: <20160519131832.GO22378@e104818-lin.cambridge.arm.com>

On Thu, May 19, 2016 at 01:50:40PM +0100, Catalin Marinas wrote:
> On Thu, May 19, 2016 at 07:06:40PM +0800, Xiaqing (A) wrote:
> > 
> > 
> > ? 2016/5/19 18:49, Catalin Marinas ??:
> > >On Thu, May 19, 2016 at 10:44:33AM +0800, x00195127 wrote:
> > >>we find that some apps will read cpuinfo when start up,
> > >>they need the string  as follows:
> > >>"Processor       : AArch64 Processor rev 0 (aarch64)"
> > >>
> > >>Then thay could load the corresponding libs. But now
> > >>arm64 platform's cpuinfo don't has this now, so
> > >>we need add this.
> > >
> > >I have the same question as Martinez: what are those apps? If they are
> > >64-bit apps, they can always assume AArch64 processor.
> > 
> > Those are 32-bit apps, and those apps are very popular in our country.
> 
> 32-bit apps checking for "AArch64" is a really silly idea. What do they
> do with this information?
> 
> I'm rather inclined to merge this patch:
> 
> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> index 3808470486f3..623d7d291dd6 100644
> --- a/arch/arm64/kernel/cpuinfo.c
> +++ b/arch/arm64/kernel/cpuinfo.c
> @@ -127,7 +127,8 @@ static int c_show(struct seq_file *m, void *v)
>  		 * software which does already (at least for 32-bit).
>  		 */
>  		seq_puts(m, "Features\t:");
> -		if (personality(current->personality) == PER_LINUX32) {
> +		if (is_compat_task() ||
> +		    personality(current->personality) == PER_LINUX32) {
>  #ifdef CONFIG_COMPAT
>  			for (j = 0; compat_hwcap_str[j]; j++)
>  				if (compat_elf_hwcap & (1 << j))

To make it even more in line with the AArch32 kernel, let's add the
"model name":

------------------8<---------------------
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 3808470486f3..6bda9d30a769 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -22,6 +22,7 @@
 
 #include <linux/bitops.h>
 #include <linux/bug.h>
+#include <linux/elf.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/personality.h>
@@ -104,6 +105,8 @@ static const char *const compat_hwcap2_str[] = {
 static int c_show(struct seq_file *m, void *v)
 {
 	int i, j;
+	bool compat = is_compat_task() ||
+		personality(current->personality) == PER_LINUX32;
 
 	for_each_online_cpu(i) {
 		struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
@@ -115,6 +118,9 @@ static int c_show(struct seq_file *m, void *v)
 		 * "processor".  Give glibc what it expects.
 		 */
 		seq_printf(m, "processor\t: %d\n", i);
+		if (compat)
+			seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
+				   MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
 
 		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
 			   loops_per_jiffy / (500000UL/HZ),
@@ -127,7 +133,7 @@ static int c_show(struct seq_file *m, void *v)
 		 * software which does already (at least for 32-bit).
 		 */
 		seq_puts(m, "Features\t:");
-		if (personality(current->personality) == PER_LINUX32) {
+		if (compat) {
 #ifdef CONFIG_COMPAT
 			for (j = 0; compat_hwcap_str[j]; j++)
 				if (compat_elf_hwcap & (1 << j))
------------------8<---------------------

With the above, a compat task or a native one with PER_LINUX32
personality would get:

processor       : 0
model name      : ARMv8 Processor rev 0 (v8l)
BogoMIPS        : 100.00
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt lpae evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 0

-- 
Catalin


From andre.przywara at arm.com  Thu May 19 06:25:22 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 14:25:22 +0100
Subject: [PATCH v4 32/56] KVM: arm/arm64: vgic-new: Add SGIPENDR register
 handlers
In-Reply-To: <20160518135022.GL3827@cbox>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-33-git-send-email-andre.przywara@arm.com>
 <20160518131449.GI3827@cbox> <573C6EA6.90803@arm.com>
 <20160518135022.GL3827@cbox>
Message-ID: <d2a62bb3-791a-b6d2-a41b-faa671f5e3f6@arm.com>

Hi,

On 18/05/16 14:50, Christoffer Dall wrote:
> On Wed, May 18, 2016 at 02:31:18PM +0100, Andre Przywara wrote:
>> Hi,
>>
>> On 18/05/16 14:14, Christoffer Dall wrote:
>>> On Mon, May 16, 2016 at 10:53:20AM +0100, Andre Przywara wrote:
>>>> As this register is v2 specific, its implementation lives entirely
>>>> in vgic-mmio-v2.c.
>>>> This register allows setting the source mask of an IPI.
>>>>
>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>> Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
>>>> ---
>>>> Changelog RFC..v1:
>>>> - remove IRQ lock from read handler
>>>> - update pending bit on setting the first / clearing the last bit
>>>> - queue virtual IRQ if necessary
>>>>
>>>> Changelog v1 .. v2:
>>>> - adapt to new MMIO framework
>>>>
>>>> Changelog v3 .. v4:
>>>> - specify accessor width
>>>>
>>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++--
>>>>  1 file changed, 60 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> index c884e9b..3925d4c 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>> @@ -146,6 +146,64 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
>>>>  	}
>>>>  }
>>>>  
>>>> +static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
>>>> +					    gpa_t addr, unsigned int len)
>>>> +{
>>>> +	u32 intid = addr & 0x0f;
>>>
>>> is there a reason why we cannot use the magic macro here?
>>
>> I wasn't sure about this, because it's not covering all 1024 interrupts,
>> but just SGIs, so it's always fixed to 16 interrupts ? 8 bits. The
>> default mask would be too big in this case.
>> I guess it would work anyway because this region is limited to 16 bytes
>> in our description, so we could use this here anyway to make it more
>> aligned with the other handlers, maybe adding a comment about the
>> difference?
>>
> meh, either way works for me actually, whatever you prefer.

So for the records: we can't use the macro here, since it relies on
masking and thus a certain alignment, which the SGIPENDR registers do
not have (being mapped to 0xF10 and 0xF20, respectively). So the
calculated intid would be much higher than the number of actually
allocated interrupts - with all the consequences ;-)

Cheers,
Andre.


From arnd at arndb.de  Thu May 19 06:29:14 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 19 May 2016 15:29:14 +0200
Subject: [PATCH] ARM: lpc32xx: fix NR_IRQS confict
In-Reply-To: <1463659769.14963.4.camel@localhost>
References: <1463646968-1047336-1-git-send-email-arnd@arndb.de>
 <573D8F92.3010902@mleia.com> <1463659769.14963.4.camel@localhost>
Message-ID: <3344142.lW8euGrkl5@wuerfel>

On Thursday 19 May 2016 08:09:29 Sylvain Lemieux wrote:
> Hi Arnd,
> 
> On Thu, 2016-05-19 at 13:04 +0300, Vladimir Zapolskiy wrote:
> > Hi Arnd,
> > 
> > On 19.05.2016 11:35, Arnd Bergmann wrote:
> > > With the change to sparse IRQs, the lpc32xx platform gets a warning about
> > > conflicting macros:
> > > 
> > > In file included from arch/arm/mach-lpc32xx/irq.c:31:0:
> > > arch/arm/mach-lpc32xx/include/mach/irqs.h:115:0: warning: "NR_IRQS" redefined
> > >  #define NR_IRQS    96
> > > arch/arm/include/asm/irq.h:9:0: note: this is the location of the previous definition
> > >  #define NR_IRQS NR_IRQS_LEGACY
> > > 
> > > In the irq controller driver, we surely need the local number instead of
> > > the generic NR_IRQS definition, so I'm renaming that one to LPC32XX_NR_IRQS.
> > > 
> > > Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> > > Fixes: 8cb17b5ed017 ("irqchip: Add LPC32xx interrupt controller driver")
> > 
> > I think that the entire removal of arch/arm/mach-lpc32xx/irq.c is the proper fix,
> > since it is a dead code now - http://www.spinics.net/lists/arm-kernel/msg499976.html
> > 
> > I believe you can apply that change and add Fixes: tag.

Ok, I've applied that on the next/late branch for arm-soc now, and one patch
on top that removes the NR_IRQS definition from mach/irqs.h

> I also submitted a patch that remove this warning at the source
> (GPIO driver broken to_irq support), until the GPIO driver update is
> done.
> 
> Please refer to this link:
> http://thread.gmane.org/gmane.linux.kernel.gpio/16837

This is in another subsystem, so I'm not applying this to arm-soc, but
the warning should be gone with my one-line change to remove NR_IRQS
anyway.

Linus, if you want to put it in the gpio tree for v4.7, feel free to
add my Acked-by: Arnd Bergmann <arnd at arndb.de>, otherwise I guess it's
enough to have this in v4.8.

	Arnd


From pankaj.dubey at samsung.com  Thu May 19 06:32:38 2016
From: pankaj.dubey at samsung.com (Pankaj Dubey)
Date: Thu, 19 May 2016 19:02:38 +0530
Subject: [PATCH v5 0/2] Introducing Exynos ChipId driver
In-Reply-To: <CAJKOXPdteY4DH_QpCztbnuY6Njhxb4nvKt14gOundwGdHyb+cQ@mail.gmail.com>
References: <1418285264-21763-1-git-send-email-pankaj.dubey@samsung.com>
 <CAJKOXPdteY4DH_QpCztbnuY6Njhxb4nvKt14gOundwGdHyb+cQ@mail.gmail.com>
Message-ID: <CAGcde9HN7AWge=b10OJ5Xn71GJUOJoxs8DJpoxWG=Jqp7yCg3g@mail.gmail.com>

Hi Krzysztof,

On 16 May 2016 at 18:52, Krzysztof Kozlowski <k.kozlowski at samsung.com> wrote:
>
> On Thu, Dec 11, 2014 at 9:07 AM, Pankaj Dubey <pankaj.dubey at samsung.com> wrote:
> > This patch series introduces Exynos Chipid platform driver.
> > Each Exynos SoC has ChipID block which can give information about SoC's
> > product Id and revision number.
> > At the same time it reduces dependency of mach-exynos files from plat-samsung,
> > by removing samsung_rev API, similar API is introduced in chipid driver itself
> > to get revision number and product id.
> >
> > This patch series is based on Kukjin Kim's for-next having SHA_ID:
> > 9db7d78aca2c7fbc19a26ce2ef01c805dc010c72
> >
> > It can also be cleanly applied on latest (next-20141209) linux-next.
> >
> > This has been tested against both tree on Exynos3250 and Exynos5250 (SMDK) board.
> >
> > Revision 4 and it's discussion can be found here
> >  - https://lkml.org/lkml/2014/12/3/115
> >
> > Changes since v4:
> >  - Removed custom sysfs entries as they were not providing any new information
> >    as pointed out by Arnd.
> >  - Removed functions exporting product_id and revision, instead we will export
> >    exynos_chipid_info structure. It will be helpfull when we need to provide more
> >    fields of chipid outside of chipid, as commented by Yadwinder
> >  - Converted all funcions as __init.
> >
> > Change since v3:
> >  - This patch set contains 5/6 and 6/6 patch from v3 series.
> >  - Made EXYNOS_CHIPID config option non-user selectable,
> >    as suggested by Tomasz Figa.
> >  - Made uniform macro for EXYNOS4/5_SOC_MASK as EXYNOS_SOC_MASK as
> >    suggested by Tomasz Figa.
> >  - Made local variables static in chipid driver.
> >  - Added existing SoC's product id's.
> >  - Added platform driver support.
> >
> > Changes since v2:
> >  - Reorganized patches as suggested by Tomasz Figa.
> >  - Addressed review comments of Tomasz Figa in i2c-s3c2410.c file.
> >
> > Changes since v1:
> >  - Added patch to move i2c interrupt re-configuration code from exynos.c
> >    to i2c driver, as suggested by Arnd.
> >  - After above patch only user of SYS_I2C_CFG register is pm.c so moving
> >    save/restore of this register also into i2c driver.
> >  - Spiltted up exynos4 and exynos5 machine descriptors to get rid from
> >    soc_is_exynos4/exynos5 kind of macros, as suggested by Arnd.
> >  - Changed location of chipid driver to "drivers/soc".
> >  - Added drivers/base/soc.c provided infrastructure to make SoC specific
> >    information avaible to user space via sysfs entry, as suggested by Arnd.
> >
> >
> > Pankaj Dubey (2):
> >   soc: samsung: add exynos chipid driver support
> >   ARM: EXYNOS: refactoring of mach-exynos to enable chipid driver
>
> Hi,
>
> This is quite old patchset and apparently was not merged. I quickly
> looked at previous discussions (for previous versions) and it seems
> all review feedback was addressed.
>
> Any other obstacles?
>
> Pankaj, maybe you could respin this (after merge window)?

Thanks for looking into this.
Infact I also wanted to respin this patchset. Will do it soon.

Thanks,
Pankaj Dubey
>
> Best regards,
> Krzysztof
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From harninder.rai at nxp.com  Thu May 19 06:53:56 2016
From: harninder.rai at nxp.com (Harninder Rai)
Date: Thu, 19 May 2016 13:53:56 +0000
Subject: Help needed with kexec on arm64
In-Reply-To: <20160519110307.GA4941@linaro.org>
References: <CAB5YjtBEO=efjhcFdVOaZqG13qK3uzCbS5SFym5hhw-n+_QLhw@mail.gmail.com>
 <DB5PR04MB1688A6D4385B76DAFF71D364E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org>
 <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160511005334.GA8417@linaro.org>
 <DB5PR04MB1688C3F122091109E6BD9B68E6740@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160519110307.GA4941@linaro.org>
Message-ID: <DB5PR04MB168870DA264FEA88763A84ADE64A0@DB5PR04MB1688.eurprd04.prod.outlook.com>

> 
> I don't know what you did here exactly, but I don't think that there is such
> a limitation.
Ok. Thanks for the confirmation
> 
> > kexec -p ./vmlinux --initrd=./ramdisk_ls1012_openwrt.cpio.gz --
> append='console=ttyS1,115200 root=/dev/mmcblk0p1
> earlycon=uart8250,mmio,0x21c0600ramdisk_size=0x2000000 default_hugepagesz=2m
> hugepagesz=2m hugepages=256 crashkernel=64M at 2240M memblock=debug'
> > Memory for crashkernel is not reserved
> 
> This message is a hint. You have got the same one before, right?
> Please check /proc/iomem and a dmesg log from the first kernel with
> memblock=debug.
I did check /proc/iomem and everything looks there. This is very strange since if I keep everything same and just move the rootfs from RAM based to SD based, I start getting this issue. 

Regards
Harry++


From stern at rowland.harvard.edu  Thu May 19 07:06:53 2016
From: stern at rowland.harvard.edu (Alan Stern)
Date: Thu, 19 May 2016 10:06:53 -0400 (EDT)
Subject: [PATCH] usb: echi-hcd: Add ehci_setup check before echi_shutdown
In-Reply-To: <1463652776-30456-1-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <Pine.LNX.4.44L0.1605191005590.1565-100000@iolanthe.rowland.org>

On Thu, 19 May 2016, Srinivas Kandagatla wrote:

> This patch protects system from crashing at shutdown in
> cases where usb host is not added yet from OTG controller driver.
> As ehci_setup() not done yet, so stop accessing registers or
> variables initialized as part of ehci_setup().
> 
> The use case is simple, for boards like DB410c where the usb host
> or device functionality is decided based on the micro-usb cable
> presence. If the board boots up with micro-usb connected, the
> OTG driver like echi-msm would not add the usb host by default.
> However a system shutdown would go and access registers and
> uninitialized variables, resulting in below crash.

...

> Fixes 4bb3cad7125b ("usb: host: ehci-msm: Register usb shutdown function")
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
> ---
>  drivers/usb/host/ehci-hcd.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
> index ae1b6e6..a962b89 100644
> --- a/drivers/usb/host/ehci-hcd.c
> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -368,6 +368,15 @@ static void ehci_shutdown(struct usb_hcd *hcd)
>  {
>  	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
>  
> +	/**
> +	 * Protect the system from crashing at system shutdown in cases where
> +	 * usb host is not added yet from OTG controller driver.
> +	 * As ehci_setup() not done yet, so stop accessing registers or
> +	 * variables initialized in ehci_setup()
> +	 */
> +	if (!ehci->sbrn)
> +		return;
> +
>  	spin_lock_irq(&ehci->lock);
>  	ehci->shutdown = true;
>  	ehci->rh_state = EHCI_RH_STOPPING;

Acked-by: Alan Stern <stern at rowland.harvard.edu>



From christoffer.dall at linaro.org  Thu May 19 07:09:54 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Thu, 19 May 2016 16:09:54 +0200
Subject: [PATCH v4 32/56] KVM: arm/arm64: vgic-new: Add SGIPENDR register
 handlers
In-Reply-To: <d2a62bb3-791a-b6d2-a41b-faa671f5e3f6@arm.com>
References: <1463392481-26583-1-git-send-email-andre.przywara@arm.com>
 <1463392481-26583-33-git-send-email-andre.przywara@arm.com>
 <20160518131449.GI3827@cbox> <573C6EA6.90803@arm.com>
 <20160518135022.GL3827@cbox>
 <d2a62bb3-791a-b6d2-a41b-faa671f5e3f6@arm.com>
Message-ID: <CAMJs5B-BbbKBH0Kkd-eu8=fdCQfxmYEhkPh+UcXZ0hemeCksLg@mail.gmail.com>

On Thu, May 19, 2016 at 3:25 PM, Andre Przywara <andre.przywara at arm.com> wrote:
> Hi,
>
> On 18/05/16 14:50, Christoffer Dall wrote:
>> On Wed, May 18, 2016 at 02:31:18PM +0100, Andre Przywara wrote:
>>> Hi,
>>>
>>> On 18/05/16 14:14, Christoffer Dall wrote:
>>>> On Mon, May 16, 2016 at 10:53:20AM +0100, Andre Przywara wrote:
>>>>> As this register is v2 specific, its implementation lives entirely
>>>>> in vgic-mmio-v2.c.
>>>>> This register allows setting the source mask of an IPI.
>>>>>
>>>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>>>> Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
>>>>> ---
>>>>> Changelog RFC..v1:
>>>>> - remove IRQ lock from read handler
>>>>> - update pending bit on setting the first / clearing the last bit
>>>>> - queue virtual IRQ if necessary
>>>>>
>>>>> Changelog v1 .. v2:
>>>>> - adapt to new MMIO framework
>>>>>
>>>>> Changelog v3 .. v4:
>>>>> - specify accessor width
>>>>>
>>>>>  virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++--
>>>>>  1 file changed, 60 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>>> index c884e9b..3925d4c 100644
>>>>> --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>>> +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
>>>>> @@ -146,6 +146,64 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
>>>>>    }
>>>>>  }
>>>>>
>>>>> +static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
>>>>> +                                      gpa_t addr, unsigned int len)
>>>>> +{
>>>>> +  u32 intid = addr & 0x0f;
>>>>
>>>> is there a reason why we cannot use the magic macro here?
>>>
>>> I wasn't sure about this, because it's not covering all 1024 interrupts,
>>> but just SGIs, so it's always fixed to 16 interrupts ? 8 bits. The
>>> default mask would be too big in this case.
>>> I guess it would work anyway because this region is limited to 16 bytes
>>> in our description, so we could use this here anyway to make it more
>>> aligned with the other handlers, maybe adding a comment about the
>>> difference?
>>>
>> meh, either way works for me actually, whatever you prefer.
>
> So for the records: we can't use the macro here, since it relies on
> masking and thus a certain alignment, which the SGIPENDR registers do
> not have (being mapped to 0xF10 and 0xF20, respectively). So the
> calculated intid would be much higher than the number of actually
> allocated interrupts - with all the consequences ;-)
>
Ah, yeah, didn't see that one coming.  Sorry for making you spend half
a day to give me an answer to a seemingly innocent question.

-Christoffer


From konrad.wilk at oracle.com  Thu May 19 07:22:48 2016
From: konrad.wilk at oracle.com (Konrad Rzeszutek Wilk)
Date: Thu, 19 May 2016 10:22:48 -0400
Subject: [PATCHv6 3/8] dma-mapping: add dma_{map,unmap}_resource
In-Reply-To: <20160519112926.GO29375@bigcity.dyn.berto.se>
References: <1462812247-3414-1-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <1462812247-3414-4-git-send-email-niklas.soderlund+renesas@ragnatech.se>
 <20160517145445.GE4074@char.us.oracle.com>
 <20160519112926.GO29375@bigcity.dyn.berto.se>
Message-ID: <20160519142248.GB21691@localhost.localdomain>

On Thu, May 19, 2016 at 01:29:26PM +0200, Niklas S?derlund wrote:
> Hi Konrad,
> 
> Thanks for your feedback.
> 
> On 2016-05-17 10:54:45 -0400, Konrad Rzeszutek Wilk wrote:
> > >  
> > > -In some circumstances dma_map_single() and dma_map_page() will fail to create
> > > -a mapping. A driver can check for these errors by testing the returned
> > > -DMA address with dma_mapping_error(). A non-zero return value means the mapping
> > > -could not be created and the driver should take appropriate action (e.g.
> > > -reduce current DMA mapping usage or delay and try again later).
> > > +In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
> > > +will fail to create a mapping. A driver can check for these errors by testing
> > > +the returned DMA address with dma_mapping_error(). A non-zero return value
> > > +means the mapping could not be created and the driver should take appropriate
> > > +action (e.g. reduce current DMA mapping usage or delay and try again later).
> > 
> > This looks like it belongs to another patch?
> 
> No it is correct (at least intended to be in this patch). All it really 
> do is inject dma_map_resource() (which is added in this patch) as one of 
> the calls which return dma_addr_t should be checked for error using 
> dma_mapping_error().  But yes the change effect all lines in the 
> paragraph due to line wrapping.
> 
> Hum or maybe I'm misunderstanding your question.

I totally missed the 'dma_map_resource' in there and just read
'dma_mapping_error'!

<sigh> Thanks.
> 
> -- 
> Regards,
> Niklas S?derlund


From jonathanh at nvidia.com  Thu May 19 07:29:07 2016
From: jonathanh at nvidia.com (Jon Hunter)
Date: Thu, 19 May 2016 15:29:07 +0100
Subject: [PATCH] ARM: tegra: beaver: allow SD card voltage to be changed
In-Reply-To: <20160513172704.GA498@ulmo.ba.sec>
References: <1456779678-20173-1-git-send-email-dev@lynxeye.de>
 <1463124331.2459.0.camel@lynxeye.de> <20160513172704.GA498@ulmo.ba.sec>
Message-ID: <573DCDB3.80202@nvidia.com>


On 13/05/16 18:27, Thierry Reding wrote:
> * PGP Signed by an unknown key
> 
> On Fri, May 13, 2016 at 09:25:31AM +0200, Lucas Stach wrote:
>> Am Montag, den 29.02.2016, 22:01 +0100 schrieb Lucas Stach:
>>> This allows to switch the card signal voltage level to 1.8V,
>>> which is needed for any ultra high speed modes to work.
>>>
>>> Signed-off-by: Lucas Stach <dev at lynxeye.de>
>>> ---
>>> This needs the SDMMC memcomp pad calibration patches I just
>>> sent out to be applied, otherwise the card voltage change will
>>> fail with a message in the kernel log and a fall back to
>>> high speed operation.
>>
>> The patches this one depends on have been applied for some time now.
>> Please pick up this patch.
> 
> My understanding is that UHS modes currently cause problems on Beaver.
> What I don't understand about that is how it will even try those modes
> if the voltage regulator can't be set to 1.8 V? Shouldn't that actively
> prevent those modes from even being attempted?

Looking at the sdhci code, if the regulator is missing then we still
attempt to place the controller is 1.8V mode ...

 static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
                                              struct mmc_ios *ios)
 {

 ...

         case MMC_SIGNAL_VOLTAGE_180:
                 if (!IS_ERR(mmc->supply.vqmmc)) {
                         ret = regulator_set_voltage(mmc->supply.vqmmc,
                                         1700000, 1950000);
                         if (ret) {
                                 pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
                                         mmc_hostname(mmc));
                                 return -EIO;
                         }
                 }

                 /*
                  * Enable 1.8V Signal Enable in the Host Control2
                  * register
                  */
                 ctrl |= SDHCI_CTRL_VDD_180;
                 sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
                 /* Some controller need to do more when switching */
                 if (host->ops->voltage_switch)
                         host->ops->voltage_switch(host);
 
                 /* 1.8V regulator output should be stable within 5 ms */
                 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
                 if (ctrl & SDHCI_CTRL_VDD_180)
                         return 0;
 
                 pr_warn("%s: 1.8V regulator output did not became stable\n",
                         mmc_hostname(mmc));
 
                 return -EAGAIN;

Ideally, the above *should* fail if the regulator is missing. However, what
I have found, is that in my case, even though the regulator is missing, the
above succeeds and the host thinks we are operating at 1.8V even though we
are still at 3.3V! It seems that this does not happen with all SD cards that
support UHS. 

This patch resolves the problems I am seeing on beaver with SD card
initialisation failing. I am surprised this is not causing problems for
others?

That said, looking at the schematics for the board, this patch looks
correct to me and we should apply this and mark for stable as this
appears to be broken for sometime. Note that even before Lucas' changes
in the SD card init we will try to switch to 1.8V if the cards supports
it and the controller is greater or equal to sdhci v3.

Cheers
Jon

-- 
nvpublic


From jonathanh at nvidia.com  Thu May 19 07:31:31 2016
From: jonathanh at nvidia.com (Jon Hunter)
Date: Thu, 19 May 2016 15:31:31 +0100
Subject: [PATCH] ARM: tegra: beaver: allow SD card voltage to be changed
In-Reply-To: <1456779678-20173-1-git-send-email-dev@lynxeye.de>
References: <1456779678-20173-1-git-send-email-dev@lynxeye.de>
Message-ID: <573DCE43.70906@nvidia.com>


On 29/02/16 21:01, Lucas Stach wrote:
> This allows to switch the card signal voltage level to 1.8V,
> which is needed for any ultra high speed modes to work.
> 
> Signed-off-by: Lucas Stach <dev at lynxeye.de>
> ---
> This needs the SDMMC memcomp pad calibration patches I just
> sent out to be applied, otherwise the card voltage change will
> fail with a message in the kernel log and a fall back to
> high speed operation.
> ---
>  arch/arm/boot/dts/tegra30-beaver.dts | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/tegra30-beaver.dts b/arch/arm/boot/dts/tegra30-beaver.dts
> index 1daed40..6b237f2 100644
> --- a/arch/arm/boot/dts/tegra30-beaver.dts
> +++ b/arch/arm/boot/dts/tegra30-beaver.dts
> @@ -1848,7 +1848,7 @@
>  
>  				ldo5_reg: ldo5 {
>  					regulator-name = "vddio_sdmmc,avdd_vdac";

Stephen, looking at the schematics, I don't see that this is connected
to the avdd_vdac (which appears to be unconnected) and so I am wondering
if this name should be just "vddio_sdmmc"?

> -					regulator-min-microvolt = <3300000>;
> +					regulator-min-microvolt = <1800000>;
>  					regulator-max-microvolt = <3300000>;
>  					regulator-always-on;
>  				};
> @@ -1919,6 +1919,7 @@
>  
>  	sdhci at 78000000 {
>  		status = "okay";
> +		vqmmc-supply = <&ldo5_reg>;
>  		cd-gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
>  		wp-gpios = <&gpio TEGRA_GPIO(T, 3) GPIO_ACTIVE_HIGH>;
>  		power-gpios = <&gpio TEGRA_GPIO(D, 7) GPIO_ACTIVE_HIGH>;
> 

Otherwise ...

Acked-by: Jon Hunter <jonathanh at nvidia.com>

Cheers
Jon

-- 
nvpublic


From matthias.bgg at gmail.com  Thu May 19 07:55:53 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Thu, 19 May 2016 16:55:53 +0200
Subject: [PATCH 2/5] drm: mediatek: add CONFIG_OF dependency
In-Reply-To: <1463587653-3035181-3-git-send-email-arnd@arndb.de>
References: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
 <1463587653-3035181-3-git-send-email-arnd@arndb.de>
Message-ID: <573DD3F9.5010702@gmail.com>



On 18/05/16 18:07, Arnd Bergmann wrote:
> The mediatek DRM driver can be configured for compile testing with
> CONFIG_OF disabled, but then fails to link:
>
> drivers/gpu/built-in.o: In function `mtk_drm_bind':
> analogix_dp_reg.c:(.text+0x52888): undefined reference to `of_find_device_by_node'
> analogix_dp_reg.c:(.text+0x52930): undefined reference to `of_find_device_by_node'
>
> This adds an explicit Kconfig dependency.
>
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> ---
>   drivers/gpu/drm/mediatek/Kconfig | 1 +
>   1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
> index 545973f6b743..67183e26971d 100644
> --- a/drivers/gpu/drm/mediatek/Kconfig
> +++ b/drivers/gpu/drm/mediatek/Kconfig
> @@ -3,6 +3,7 @@ config DRM_MEDIATEK
>   	depends on DRM
>   	depends on ARCH_MEDIATEK || (ARM && COMPILE_TEST)
>   	depends on COMMON_CLK
> +	depends on OF
>   	select DRM_GEM_CMA_HELPER
>   	select DRM_KMS_HELPER
>   	select DRM_MIPI_DSI
>

Reviewed-by: Matthias Brugger <matthias.bgg at gmail.com>


From matthias.bgg at gmail.com  Thu May 19 07:56:30 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Thu, 19 May 2016 16:56:30 +0200
Subject: [PATCH 3/5] drm: mediatek: fixup drm_gem_object_lookup API change
In-Reply-To: <1463587653-3035181-4-git-send-email-arnd@arndb.de>
References: <1463587653-3035181-1-git-send-email-arnd@arndb.de>
 <1463587653-3035181-4-git-send-email-arnd@arndb.de>
Message-ID: <573DD41E.3050506@gmail.com>



On 18/05/16 18:07, Arnd Bergmann wrote:
> The drm_gem_object_lookup() function prototype changed while this
> driver was added, so it fails to build now:
>
> drivers/gpu/drm/mediatek/mtk_drm_gem.c: In function 'mtk_drm_gem_dumb_map_offset':
> drivers/gpu/drm/mediatek/mtk_drm_gem.c:142:30: error: passing argument 1 of 'drm_gem_object_lookup' from incompatible pointer type [-Werror=incompatible-pointer-types]
>    obj = drm_gem_object_lookup(dev, file_priv, handle);
>
> This fixes the new caller as well.
>
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Fixes: a8ad0bd84f98 ("drm: Remove unused drm_device from drm_gem_object_lookup()")
> ---
>   drivers/gpu/drm/mediatek/mtk_drm_fb.c  | 2 +-
>   drivers/gpu/drm/mediatek/mtk_drm_gem.c | 2 +-
>   2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
> index 33d30c19f35f..147df85399ab 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
> @@ -138,7 +138,7 @@ struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
>   	if (drm_format_num_planes(cmd->pixel_format) != 1)
>   		return ERR_PTR(-EINVAL);
>
> -	gem = drm_gem_object_lookup(dev, file, cmd->handles[0]);
> +	gem = drm_gem_object_lookup(file, cmd->handles[0]);
>   	if (!gem)
>   		return ERR_PTR(-ENOENT);
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
> index a773bfaea913..fa2ec0cd00e8 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
> @@ -139,7 +139,7 @@ int mtk_drm_gem_dumb_map_offset(struct drm_file *file_priv,
>   	struct drm_gem_object *obj;
>   	int ret;
>
> -	obj = drm_gem_object_lookup(dev, file_priv, handle);
> +	obj = drm_gem_object_lookup(file_priv, handle);
>   	if (!obj) {
>   		DRM_ERROR("failed to lookup gem object.\n");
>   		return -EINVAL;
>

Reviewed-by: Matthias Brugger <matthias.bgg at gmail.com>


From tony at atomide.com  Thu May 19 07:57:46 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 19 May 2016 07:57:46 -0700
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <0d463add-9fa5-a768-2ba6-34c4126c7817@ti.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
 <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com>
 <20160518193028.GT5995@atomide.com>
 <0d463add-9fa5-a768-2ba6-34c4126c7817@ti.com>
Message-ID: <20160519145745.GU5995@atomide.com>

* Peter Ujfalusi <peter.ujfalusi at ti.com> [160519 01:10]:
> On 05/18/2016 10:30 PM, Tony Lindgren wrote:
> > Ideally the adma support would be a separate loadable module,
> > similar how the cppi41dma is a child of the OTG controller.
> 
> The Master DMA is part of the hsmmc IP block. If the same ADMA module is
> present on other IPs it might be beneficial to have a helper library to handle
> it (allocating the descriptor pool, wrinting, updating descriptors, etc).

OK. Yeah if it's part of the MMC controller it makes no sense to
separate it. So then the conecrns are using alternate DMA
implementations and keeping PM runtime working :)

BTW, Felipe mentioned that the best thing to do in the long run would
be to set up sdhci-omap.c operating in ADMA mode.

Felipe, care to summarize what you had in mind?

Regards,

Tony



From horia.geanta at nxp.com  Thu May 19 08:11:04 2016
From: horia.geanta at nxp.com (=?UTF-8?q?Horia=20Geant=C4=83?=)
Date: Thu, 19 May 2016 18:11:04 +0300
Subject: [PATCH v3 3/8] arm64: add io{read,write}64be accessors
In-Reply-To: <1463670405-1059-1-git-send-email-horia.geanta@nxp.com>
References: <1463670405-1059-1-git-send-email-horia.geanta@nxp.com>
Message-ID: <1463670664-2856-1-git-send-email-horia.geanta@nxp.com>

This will allow device drivers to consistently use io{read,write}XXbe
also for 64-bit accesses.

Acked-by: Catalin Marinas <catalin.marinas at arm.com>
Signed-off-by: Alex Porosanu <alexandru.porosanu at nxp.com>
Signed-off-by: Horia Geant? <horia.geanta at nxp.com>
---
 arch/arm64/include/asm/io.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 44be1e03ed65..9b6e408cfa51 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -174,13 +174,15 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
 #define iounmap				__iounmap
 
 /*
- * io{read,write}{16,32}be() macros
+ * io{read,write}{16,32,64}be() macros
  */
 #define ioread16be(p)		({ __u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
 #define ioread32be(p)		({ __u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })
+#define ioread64be(p)		({ __u64 __v = be64_to_cpu((__force __be64)__raw_readq(p)); __iormb(); __v; })
 
 #define iowrite16be(v,p)	({ __iowmb(); __raw_writew((__force __u16)cpu_to_be16(v), p); })
 #define iowrite32be(v,p)	({ __iowmb(); __raw_writel((__force __u32)cpu_to_be32(v), p); })
+#define iowrite64be(v,p)	({ __iowmb(); __raw_writeq((__force __u64)cpu_to_be64(v), p); })
 
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
-- 
2.4.4



From wxt at rock-chips.com  Thu May 19 08:47:02 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Thu, 19 May 2016 23:47:02 +0800
Subject: [PATCH 1/3] spi/rockchip: add rk3036/rk3228/rk3368 socs for spi
 document
Message-ID: <1463672824-15367-1-git-send-email-wxt@rock-chips.com>

We had supported the rk3036/rk3066/rk3188/rk3228/rk3288/rk3368/rk3399
family SoCs in linux kernel.

Let's add the other SoCs, in order to a better understanding from the
rockchip spi document.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Mark Brown <broonie at kernel.org>
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: linux-rockchip at lists.infradead.org
---

 Documentation/devicetree/bindings/spi/spi-rockchip.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/spi/spi-rockchip.txt b/Documentation/devicetree/bindings/spi/spi-rockchip.txt
index 1b14d69..305b542 100644
--- a/Documentation/devicetree/bindings/spi/spi-rockchip.txt
+++ b/Documentation/devicetree/bindings/spi/spi-rockchip.txt
@@ -6,9 +6,12 @@ and display controllers using the SPI communication interface.
 Required Properties:
 
 - compatible: should be one of the following.
+    "rockchip,rk3036-spi" for rk3036.
     "rockchip,rk3066-spi" for rk3066.
     "rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188.
+    "rockchip,rk3228-spi", "rockchip,rk3066-spi" for rk3228.
     "rockchip,rk3288-spi", "rockchip,rk3066-spi" for rk3288.
+    "rockchip,rk3368-spi", "rockchip,rk3066-spi" for rk3368.
     "rockchip,rk3399-spi", "rockchip,rk3066-spi" for rk3399.
 - reg: physical base address of the controller and length of memory mapped
        region.
-- 
2.7.4



From wxt at rock-chips.com  Thu May 19 08:47:03 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Thu, 19 May 2016 23:47:03 +0800
Subject: [PATCH 2/3] spi/rockchip: add the rk3036/rk3228/rk3368 to match for
 driver
In-Reply-To: <1463672824-15367-1-git-send-email-wxt@rock-chips.com>
References: <1463672824-15367-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1463672824-15367-2-git-send-email-wxt@rock-chips.com>

In gerenal, the "rockchip,rockchip-spi" string will match the dts
that's great in spi driver. After all the most of rockchip SoCs ar
same spi controller.

Then, we should keep the old style to match the dts various.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Mark Brown <broonie at kernel.org>
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: linux-rockchip at lists.infradead.org
---

 drivers/spi/spi-rockchip.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 6c6c001..dd08b68 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -893,9 +893,12 @@ static const struct dev_pm_ops rockchip_spi_pm = {
 };
 
 static const struct of_device_id rockchip_spi_dt_match[] = {
+	{ .compatible = "rockchip,rk3036-spi", },
 	{ .compatible = "rockchip,rk3066-spi", },
 	{ .compatible = "rockchip,rk3188-spi", },
+	{ .compatible = "rockchip,rk3228-spi", },
 	{ .compatible = "rockchip,rk3288-spi", },
+	{ .compatible = "rockchip,rk3368-spi", },
 	{ .compatible = "rockchip,rk3399-spi", },
 	{ },
 };
-- 
2.7.4



From wxt at rock-chips.com  Thu May 19 08:47:04 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Thu, 19 May 2016 23:47:04 +0800
Subject: [PATCH 3/3] ARM: dts: rockchip: fixes the spi compatible for rk3036
In-Reply-To: <1463672824-15367-1-git-send-email-wxt@rock-chips.com>
References: <1463672824-15367-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1463672824-15367-3-git-send-email-wxt@rock-chips.com>

That's seem the incorrect string to match the spi driver.

Fixes commit f629fcfab2cd
("ARM: dts: rockchip: support the spi for rk3036")

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: linux-rockchip at lists.infradead.org

---

 arch/arm/boot/dts/rk3036.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
index d0f4bb7..a30700a 100644
--- a/arch/arm/boot/dts/rk3036.dtsi
+++ b/arch/arm/boot/dts/rk3036.dtsi
@@ -431,7 +431,7 @@
 	};
 
 	spi: spi at 20074000 {
-		compatible = "rockchip,rockchip-spi";
+		compatible = "rockchip,rk3036-spi";
 		reg = <0x20074000 0x1000>;
 		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
 		clocks =<&cru PCLK_SPI>, <&cru SCLK_SPI>;
-- 
2.7.4



From heiko at sntech.de  Thu May 19 08:51:54 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 19 May 2016 17:51:54 +0200
Subject: [PATCH 1/3] spi/rockchip: add rk3036/rk3228/rk3368 socs for spi
 document
In-Reply-To: <1463672824-15367-1-git-send-email-wxt@rock-chips.com>
References: <1463672824-15367-1-git-send-email-wxt@rock-chips.com>
Message-ID: <3685935.dKdIbE8hXb@phil>

Am Donnerstag, 19. Mai 2016, 23:47:02 schrieb Caesar Wang:
> We had supported the rk3036/rk3066/rk3188/rk3228/rk3288/rk3368/rk3399
> family SoCs in linux kernel.
> 
> Let's add the other SoCs, in order to a better understanding from the
> rockchip spi document.
> 
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> Cc: Rob Herring <robh+dt at kernel.org>
> Cc: Mark Brown <broonie at kernel.org>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Cc: linux-rockchip at lists.infradead.org
> ---
> 
>  Documentation/devicetree/bindings/spi/spi-rockchip.txt | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/spi/spi-rockchip.txt
> b/Documentation/devicetree/bindings/spi/spi-rockchip.txt index
> 1b14d69..305b542 100644
> --- a/Documentation/devicetree/bindings/spi/spi-rockchip.txt
> +++ b/Documentation/devicetree/bindings/spi/spi-rockchip.txt
> @@ -6,9 +6,12 @@ and display controllers using the SPI communication
> interface. Required Properties:
> 
>  - compatible: should be one of the following.
> +    "rockchip,rk3036-spi" for rk3036.

shouldn't the rk3036 also get the rk3066 fallback. Looking at the driver 
part (patch2) the rk3036 still is the same IP as for every other soc in 
here.

>      "rockchip,rk3066-spi" for rk3066.
>      "rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188.
> +    "rockchip,rk3228-spi", "rockchip,rk3066-spi" for rk3228.
>      "rockchip,rk3288-spi", "rockchip,rk3066-spi" for rk3288.
> +    "rockchip,rk3368-spi", "rockchip,rk3066-spi" for rk3368.
>      "rockchip,rk3399-spi", "rockchip,rk3066-spi" for rk3399.
>  - reg: physical base address of the controller and length of memory
> mapped region.



From robh at kernel.org  Thu May 19 09:02:56 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 19 May 2016 11:02:56 -0500
Subject: [GIT PULL 0/7] ARM: SoC changes for 4.7
In-Reply-To: <8749147.ztcb6kVhye@wuerfel>
References: <8749147.ztcb6kVhye@wuerfel>
Message-ID: <CAL_JsqKcVN-KcJnBhqoMpoBjJk4KiPgbWXzA1FR+vh5_bL6oYg@mail.gmail.com>

On Tue, May 17, 2016 at 5:07 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> Hi Linus,
>
> These are the first seven pull requests for arm-soc this time, there is
> one small follow-up coming once the dependencies for that have landed
> in your tree.
>
> Things remain relatively calm for us. We merged 122 pull requests with
> 822 patches, plus 35 individual patches, which is less than what we used
> to have. We are shifting even more towards changing only dts files,
> for the most part adding new functionality on existing boards, and adding
> new machines, as shown clearly by the dirstat:

[...]

>  730 files changed, 47909 insertions(+), 7916 deletions(-)
>
> My feeling is that the number of dts changes remain constant, but
> everything else gets less every time, and that's good.

I happen have a script... (I run it every time people complain about DT).

Here's the diffstat of mach-* and plat-* since merging DT support:

v3.0: 833 files changed, 10945 insertions(+), 37476 deletions(-)
v3.1: 955 files changed, 17796 insertions(+), 20300 deletions(-)
v3.2: 1507 files changed, 32960 insertions(+), 33392 deletions(-)
v3.3: 1301 files changed, 27725 insertions(+), 18941 deletions(-)
v3.4: 1324 files changed, 27079 insertions(+), 21500 deletions(-)
v3.5: 975 files changed, 32340 insertions(+), 46663 deletions(-)
v3.6: 648 files changed, 16121 insertions(+), 13161 deletions(-)
v3.7: 1389 files changed, 23739 insertions(+), 61097 deletions(-)
v3.8: 1066 files changed, 32812 insertions(+), 40821 deletions(-)
v3.9: 1031 files changed, 10051 insertions(+), 33399 deletions(-)
v3.10: 831 files changed, 15049 insertions(+), 27333 deletions(-)
v3.11: 675 files changed, 18519 insertions(+), 30012 deletions(-)
v3.12: 474 files changed, 12575 insertions(+), 25120 deletions(-)
v3.13: 491 files changed, 11088 insertions(+), 13375 deletions(-)
v3.14: 408 files changed, 5586 insertions(+), 12691 deletions(-)
v3.15: 538 files changed, 7809 insertions(+), 9337 deletions(-)
v3.16: 499 files changed, 6528 insertions(+), 10252 deletions(-)
v3.17: 596 files changed, 6274 insertions(+), 36824 deletions(-)
v3.18: 333 files changed, 3111 insertions(+), 6905 deletions(-)
v3.19: 435 files changed, 6180 insertions(+), 32402 deletions(-)
v4.0: 265 files changed, 4081 insertions(+), 14119 deletions(-)
v4.1: 362 files changed, 4286 insertions(+), 24876 deletions(-)
v4.2: 292 files changed, 3115 insertions(+), 11567 deletions(-)
v4.3: 306 files changed, 3223 insertions(+), 14510 deletions(-)
v4.4: 160 files changed, 2014 insertions(+), 4893 deletions(-)
v4.5: 531 files changed, 3839 insertions(+), 4398 deletions(-)
v4.6: 211 files changed, 1417 insertions(+), 4320 deletions(-)

Once this goes to 0, we can move the dts files out of the kernel and
make you maintainer. ;)

The dts files' numbers do look pretty constant.

Rob


From wxt at rock-chips.com  Thu May 19 09:04:07 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri, 20 May 2016 00:04:07 +0800
Subject: [PATCH 1/3] spi/rockchip: add rk3036/rk3228/rk3368 socs for spi
 document
In-Reply-To: <3685935.dKdIbE8hXb@phil>
References: <1463672824-15367-1-git-send-email-wxt@rock-chips.com>
 <3685935.dKdIbE8hXb@phil>
Message-ID: <573DE3F7.6070300@rock-chips.com>



? 2016?05?19? 23:51, Heiko Stuebner ??:
> Am Donnerstag, 19. Mai 2016, 23:47:02 schrieb Caesar Wang:
>> We had supported the rk3036/rk3066/rk3188/rk3228/rk3288/rk3368/rk3399
>> family SoCs in linux kernel.
>>
>> Let's add the other SoCs, in order to a better understanding from the
>> rockchip spi document.
>>
>> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>> Cc: Rob Herring <robh+dt at kernel.org>
>> Cc: Mark Brown <broonie at kernel.org>
>> Cc: Heiko Stuebner <heiko at sntech.de>
>> Cc: linux-rockchip at lists.infradead.org
>> ---
>>
>>   Documentation/devicetree/bindings/spi/spi-rockchip.txt | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/spi/spi-rockchip.txt
>> b/Documentation/devicetree/bindings/spi/spi-rockchip.txt index
>> 1b14d69..305b542 100644
>> --- a/Documentation/devicetree/bindings/spi/spi-rockchip.txt
>> +++ b/Documentation/devicetree/bindings/spi/spi-rockchip.txt
>> @@ -6,9 +6,12 @@ and display controllers using the SPI communication
>> interface. Required Properties:
>>
>>   - compatible: should be one of the following.
>> +    "rockchip,rk3036-spi" for rk3036.
> shouldn't the rk3036 also get the rk3066 fallback. Looking at the driver
> part (patch2) the rk3036 still is the same IP as for every other soc in
> here.

Yep, the same IP.

Do you think we should keep the below style?

1)
"rockchip,rk3036-spi", "rockchip,rk3066-spi" for rk3036.
  "rockchip,rk3066-spi" for rk3066.
  "rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188.
...

or
2)
  "rockchip,rk3066-spi" for rk3066.
"rockchip,rk3036-spi", "rockchip,rk3066-spi" for rk3036.
  "rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188
..

or
3)
"rockchip, rockchip-spi" for rk3036 rk3066.......

Think about the 1) will be googd select.

-Caesar

>>       "rockchip,rk3066-spi" for rk3066.
>>       "rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188.
>> +    "rockchip,rk3228-spi", "rockchip,rk3066-spi" for rk3228.
>>       "rockchip,rk3288-spi", "rockchip,rk3066-spi" for rk3288.
>> +    "rockchip,rk3368-spi", "rockchip,rk3066-spi" for rk3368.
>>       "rockchip,rk3399-spi", "rockchip,rk3066-spi" for rk3399.
>>   - reg: physical base address of the controller and length of memory
>> mapped region.
>
>
>




From swarren at wwwdotorg.org  Thu May 19 09:12:35 2016
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Thu, 19 May 2016 10:12:35 -0600
Subject: [PATCH] ARM: tegra: beaver: allow SD card voltage to be changed
In-Reply-To: <573DCE43.70906@nvidia.com>
References: <1456779678-20173-1-git-send-email-dev@lynxeye.de>
 <573DCE43.70906@nvidia.com>
Message-ID: <573DE5F3.2060406@wwwdotorg.org>

On 05/19/2016 08:31 AM, Jon Hunter wrote:
>
> On 29/02/16 21:01, Lucas Stach wrote:
>> This allows to switch the card signal voltage level to 1.8V,
>> which is needed for any ultra high speed modes to work.
>>
>> Signed-off-by: Lucas Stach <dev at lynxeye.de>
>> ---
>> This needs the SDMMC memcomp pad calibration patches I just
>> sent out to be applied, otherwise the card voltage change will
>> fail with a message in the kernel log and a fall back to
>> high speed operation.
>> ---
>>   arch/arm/boot/dts/tegra30-beaver.dts | 3 ++-
>>   1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/boot/dts/tegra30-beaver.dts b/arch/arm/boot/dts/tegra30-beaver.dts
>> index 1daed40..6b237f2 100644
>> --- a/arch/arm/boot/dts/tegra30-beaver.dts
>> +++ b/arch/arm/boot/dts/tegra30-beaver.dts
>> @@ -1848,7 +1848,7 @@
>>
>>   				ldo5_reg: ldo5 {
>>   					regulator-name = "vddio_sdmmc,avdd_vdac";
>
> Stephen, looking at the schematics, I don't see that this is connected
> to the avdd_vdac (which appears to be unconnected) and so I am wondering
> if this name should be just "vddio_sdmmc"?

Yes, I don't know where avdd_vdac came from; it doesn't appear connected 
on any Beaver (or even Cardhu, from which it was probably derived) 
schematic that I have.

CC += Bryan in case he has any recollection since he wrote this DT.


From aleksey.makarov at linaro.org  Thu May 19 09:15:11 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Thu, 19 May 2016 19:15:11 +0300
Subject: [PATCH v2 0/5] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
Message-ID: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>

This patchset adds support for ACPI_TABLE_UPGRADE for ARM64

These patches help with:

1). During development of a platform, it is much easier to debug
problems with tables if you can test replacement ones without having to
respin the firmware. In the server world, you usually don't have the
firmware source code, so to get it respun could be days-weeks even if
you are working with the authors closely. We have practically used this
feature on a number of platforms already and it will continue.

2). They empower (advanced) users and developers to work around problems
that they find on platforms. Sure, we want firmware to always be fixed
and working well, but it is better if folks have the tools.

It's also required for parity with x86 functionality on servers as Redhat
use that method in their tooling.

The patchset refactors the code introduced by the patches by Lv Zheng [1],
fixes access to the destination of new ACPI tables as suggested
by Mark Rutland [2] and enables the feature for ARM64

It was first sent by Jon Masters [3] to linaro-acpi in December 2015

Tested on QEMU (arm64 and x86) and ThunderX
Should be applied to next-20160519

v2:
- add Acked-by: Lv Zheng <lv.zheng at intel.com>
- replace the original patch "ACPI: table upgrade: move early_initrd_acpi_init()
  to header file" with the patch "ACPI: table upgrade: refactor function
  definitions".  This new patch is just the original one rewritten following the
  suggestion by Lv Zheng to use initrd_start, inird_end directly in
  acpi_table_initrd_init().  It simplifies things noticeably.
- add Jon's explanations to the cover of the patchset and my explanations
  to "ACPI: ARM64: support for ACPI_TABLE_UPGRADE"
- introduce ARCH_HAS_ACPI_TABLE_UPGRADE in a separate patch (Mark Rutland)
- move arch-specific definition to an arch-specific header in a separate patch
  (Mark Rutland)

v1:
https://lkml.kernel.org/g/1463486765-31827-1-git-send-email-aleksey.makarov at linaro.org

[1] https://lkml.kernel.org/g/cover.1460340514.git.lv.zheng at intel.com
[2] https://lists.linaro.org/pipermail/linaro-acpi/2015-December/006101.html
[3] https://lists.linaro.org/pipermail/linaro-acpi/2015-December/006099.html

Aleksey Makarov (4):
  ACPI: table upgrade: use cacheable map for tables
  ACPI: table upgrade: refactor function definitions
  ACPI: table upgrade: move arch-specific symbol to asm/acpi.h
  ACPI: table upgrade: introduce ARCH_HAS_ACPI_TABLE_UPGRADE

Jon Masters (1):
  ACPI: ARM64: support for ACPI_TABLE_UPGRADE

 arch/arm64/Kconfig            |  1 +
 arch/arm64/include/asm/acpi.h |  2 ++
 arch/arm64/kernel/setup.c     |  6 ++++--
 arch/x86/Kconfig              |  1 +
 arch/x86/include/asm/acpi.h   |  2 ++
 arch/x86/kernel/setup.c       |  9 +--------
 drivers/acpi/Kconfig          |  5 ++++-
 drivers/acpi/tables.c         | 23 +++++++++--------------
 include/linux/acpi.h          |  8 ++++++--
 9 files changed, 30 insertions(+), 27 deletions(-)

-- 
2.8.2



From aleksey.makarov at linaro.org  Thu May 19 09:15:12 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Thu, 19 May 2016 19:15:12 +0300
Subject: [PATCH v2 1/5] ACPI: table upgrade: use cacheable map for tables
In-Reply-To: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1463674518-22477-2-git-send-email-aleksey.makarov@linaro.org>

The new memory allocated in acpi_table_initrd_init() is used to
copy the upgraded tables to it.  So it should be mapped with
early_memunmap() instead of early_ioremap().

This is critical for ARM.

Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
Acked-by: Lv Zheng <lv.zheng at intel.com>
---
 drivers/acpi/tables.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index a372f9e..f829e6a 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -578,10 +578,10 @@ static void __init acpi_table_initrd_init(void *data, size_t size)
 			clen = size;
 			if (clen > MAP_CHUNK_SIZE - slop)
 				clen = MAP_CHUNK_SIZE - slop;
-			dest_p = early_ioremap(dest_addr & PAGE_MASK,
-						 clen + slop);
+			dest_p = early_memremap(dest_addr & PAGE_MASK,
+						clen + slop);
 			memcpy(dest_p + slop, src_p, clen);
-			early_iounmap(dest_p, clen + slop);
+			early_memunmap(dest_p, clen + slop);
 			src_p += clen;
 			dest_addr += clen;
 			size -= clen;
-- 
2.8.2



From aleksey.makarov at linaro.org  Thu May 19 09:15:13 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Thu, 19 May 2016 19:15:13 +0300
Subject: [PATCH v2 2/5] ACPI: table upgrade: refactor function definitions
In-Reply-To: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1463674518-22477-3-git-send-email-aleksey.makarov@linaro.org>

Refer initrd_start, initrd_end directly from drivers/acpi/tables.c.
This allows to use the table upgrade feature in architectures
other than x86.  Also this simplifies header files.

The patch renames acpi_table_initrd_init() to acpi_table_upgrade()
(what reflects the purpose of the function) and removes the unneeded
wraps early_acpi_table_init() and early_initrd_acpi_init().

Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
---
 arch/x86/kernel/setup.c |  9 +--------
 drivers/acpi/tables.c   | 14 ++++----------
 include/linux/acpi.h    |  8 ++++++--
 3 files changed, 11 insertions(+), 20 deletions(-)

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index c4e7b39..aac91be 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -399,10 +399,6 @@ static void __init reserve_initrd(void)
 	memblock_free(ramdisk_image, ramdisk_end - ramdisk_image);
 }
 
-static void __init early_initrd_acpi_init(void)
-{
-	early_acpi_table_init((void *)initrd_start, initrd_end - initrd_start);
-}
 #else
 static void __init early_reserve_initrd(void)
 {
@@ -410,9 +406,6 @@ static void __init early_reserve_initrd(void)
 static void __init reserve_initrd(void)
 {
 }
-static void __init early_initrd_acpi_init(void)
-{
-}
 #endif /* CONFIG_BLK_DEV_INITRD */
 
 static void __init parse_setup_data(void)
@@ -1146,7 +1139,7 @@ void __init setup_arch(char **cmdline_p)
 
 	reserve_initrd();
 
-	early_initrd_acpi_init();
+	acpi_table_upgrade();
 
 	vsmp_init();
 
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index f829e6a..b05df13 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -34,6 +34,7 @@
 #include <linux/bootmem.h>
 #include <linux/earlycpio.h>
 #include <linux/memblock.h>
+#include <linux/initrd.h>
 #include "internal.h"
 
 #ifdef CONFIG_ACPI_CUSTOM_DSDT
@@ -481,8 +482,10 @@ static DECLARE_BITMAP(acpi_initrd_installed, NR_ACPI_INITRD_TABLES);
 
 #define MAP_CHUNK_SIZE   (NR_FIX_BTMAPS << PAGE_SHIFT)
 
-static void __init acpi_table_initrd_init(void *data, size_t size)
+void __init acpi_table_upgrade(void)
 {
+	void *data = (void *)initrd_start;
+	size_t size = initrd_end - initrd_start;
 	int sig, no, table_nr = 0, total_offset = 0;
 	long offset = 0;
 	struct acpi_table_header *table;
@@ -696,10 +699,6 @@ next_table:
 	}
 }
 #else
-static void __init acpi_table_initrd_init(void *data, size_t size)
-{
-}
-
 static acpi_status
 acpi_table_initrd_override(struct acpi_table_header *existing_table,
 			   acpi_physical_address *address,
@@ -742,11 +741,6 @@ acpi_os_table_override(struct acpi_table_header *existing_table,
 	return AE_OK;
 }
 
-void __init early_acpi_table_init(void *data, size_t size)
-{
-	acpi_table_initrd_init(data, size);
-}
-
 /*
  * acpi_table_init()
  *
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 288fac5..ef2ad26 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -208,7 +208,6 @@ void acpi_boot_table_init (void);
 int acpi_mps_check (void);
 int acpi_numa_init (void);
 
-void early_acpi_table_init(void *data, size_t size);
 int acpi_table_init (void);
 int acpi_table_parse(char *id, acpi_tbl_table_handler handler);
 int __init acpi_parse_entries(char *id, unsigned long table_size,
@@ -588,7 +587,6 @@ static inline const char *acpi_dev_name(struct acpi_device *adev)
 	return NULL;
 }
 
-static inline void early_acpi_table_init(void *data, size_t size) { }
 static inline void acpi_early_init(void) { }
 static inline void acpi_subsystem_init(void) { }
 
@@ -997,4 +995,10 @@ static inline struct fwnode_handle *acpi_get_next_subnode(struct device *dev,
 #define acpi_probe_device_table(t)	({ int __r = 0; __r;})
 #endif
 
+#ifdef CONFIG_ACPI_TABLE_UPGRADE
+void acpi_table_upgrade(void);
+#else
+static inline void acpi_table_upgrade(void) { }
+#endif
+
 #endif	/*_LINUX_ACPI_H*/
-- 
2.8.2



From aleksey.makarov at linaro.org  Thu May 19 09:15:14 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Thu, 19 May 2016 19:15:14 +0300
Subject: [PATCH v2 3/5] ACPI: table upgrade: move arch-specific symbol to
 asm/acpi.h
In-Reply-To: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1463674518-22477-4-git-send-email-aleksey.makarov@linaro.org>

The constant that defines max phys address where the new upgraded
ACPI table should be allocated is arch-specific.  Move it to
<asm/acpi.h>

Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
---
 arch/x86/include/asm/acpi.h | 2 ++
 drivers/acpi/tables.c       | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 94c18eb..c24c070 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -170,4 +170,6 @@ static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
 }
 #endif
 
+#define ACPI_TABLE_UPGRADE_MAX_PHYS (max_low_pfn_mapped << PAGE_SHIFT)
+
 #endif /* _ASM_X86_ACPI_H */
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index b05df13..9f0ad6e 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -35,6 +35,7 @@
 #include <linux/earlycpio.h>
 #include <linux/memblock.h>
 #include <linux/initrd.h>
+#include <linux/acpi.h>
 #include "internal.h"
 
 #ifdef CONFIG_ACPI_CUSTOM_DSDT
@@ -543,7 +544,7 @@ void __init acpi_table_upgrade(void)
 		return;
 
 	acpi_tables_addr =
-		memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
+		memblock_find_in_range(0, ACPI_TABLE_UPGRADE_MAX_PHYS,
 				       all_tables_size, PAGE_SIZE);
 	if (!acpi_tables_addr) {
 		WARN_ON(1);
-- 
2.8.2



From aleksey.makarov at linaro.org  Thu May 19 09:15:16 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Thu, 19 May 2016 19:15:16 +0300
Subject: [PATCH v2 5/5] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
In-Reply-To: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1463674518-22477-6-git-send-email-aleksey.makarov@linaro.org>

From: Jon Masters <jcm at redhat.com>

This patch adds support for ACPI_TABLE_UPGRADE for ARM64

To access initrd image we need to move initialization
of linear mapping a bit earlier.

The implementation of the feature acpi_table_upgrade()
(drivers/acpi/tables.c) works with initrd data represented as an array
in virtual memory.  It uses some library utility to find the redefined
tables in that array and iterates over it to copy the data to new
allocated memory.  So to access the initrd data via fixmap
we need to rewrite it considerably.

In x86 arch, kernel memory is already mapped by the time when
acpi_table_upgrade() and acpi_boot_table_init() are called so I
think that we can just move this mapping one function earlier too.

Signed-off-by: Jon Masters <jcm at redhat.com>
Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
---
 arch/arm64/Kconfig            | 1 +
 arch/arm64/include/asm/acpi.h | 2 ++
 arch/arm64/kernel/setup.c     | 6 ++++--
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 5d30abf..f4f9f56 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -5,6 +5,7 @@ config ARM64
 	select ACPI_PCI_HOST_GENERIC if ACPI
 	select ACPI_REDUCED_HARDWARE_ONLY if ACPI
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
+	select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select ARCH_HAS_ELF_RANDOMIZE
 	select ARCH_HAS_GCOV_PROFILE_ALL
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index aee323b..d75f6c7 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -113,4 +113,6 @@ static inline const char *acpi_get_enable_method(int cpu)
 pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr);
 #endif
 
+#define ACPI_TABLE_UPGRADE_MAX_PHYS PFN_PHYS(max_pfn)
+
 #endif /*_ASM_ACPI_H*/
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index feab2ee..4bce811 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -261,11 +261,13 @@ void __init setup_arch(char **cmdline_p)
 	efi_init();
 	arm64_memblock_init();
 
+	paging_init();
+
+	acpi_table_upgrade();
+
 	/* Parse the ACPI tables for possible boot-time configuration */
 	acpi_boot_table_init();
 
-	paging_init();
-
 	if (acpi_disabled)
 		unflatten_device_tree();
 
-- 
2.8.2



From aleksey.makarov at linaro.org  Thu May 19 09:15:15 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Thu, 19 May 2016 19:15:15 +0300
Subject: [PATCH v2 4/5] ACPI: table upgrade: introduce
 ARCH_HAS_ACPI_TABLE_UPGRADE
In-Reply-To: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1463674518-22477-5-git-send-email-aleksey.makarov@linaro.org>

We want to use the table upgrade feature in ARM64.
Introduce a new configuration option that allows that.

Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
---
 arch/x86/Kconfig     | 1 +
 drivers/acpi/Kconfig | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 48ac290..f60fd27 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -22,6 +22,7 @@ config X86
 	select ANON_INODES
 	select ARCH_CLOCKSOURCE_DATA
 	select ARCH_DISCARD_MEMBLOCK
+	select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index c204344..083da18 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -311,9 +311,12 @@ config ACPI_CUSTOM_DSDT
 	bool
 	default ACPI_CUSTOM_DSDT_FILE != ""
 
+config ARCH_HAS_ACPI_TABLE_UPGRADE
+	def_bool n
+
 config ACPI_TABLE_UPGRADE
 	bool "Allow upgrading ACPI tables via initrd"
-	depends on BLK_DEV_INITRD && X86
+	depends on BLK_DEV_INITRD && ARCH_HAS_ACPI_TABLE_UPGRADE
 	default y
 	help
 	  This option provides functionality to upgrade arbitrary ACPI tables
-- 
2.8.2



From heiko at sntech.de  Thu May 19 09:20:58 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 19 May 2016 18:20:58 +0200
Subject: [PATCH 1/3] spi/rockchip: add rk3036/rk3228/rk3368 socs for spi
 document
In-Reply-To: <573DE3F7.6070300@rock-chips.com>
References: <1463672824-15367-1-git-send-email-wxt@rock-chips.com>
 <3685935.dKdIbE8hXb@phil> <573DE3F7.6070300@rock-chips.com>
Message-ID: <3828505.WBLtTjjB7h@phil>

Am Freitag, 20. Mai 2016, 00:04:07 schrieb Caesar Wang:
> ? 2016?05?19? 23:51, Heiko Stuebner ??:
> > Am Donnerstag, 19. Mai 2016, 23:47:02 schrieb Caesar Wang:
> >> We had supported the rk3036/rk3066/rk3188/rk3228/rk3288/rk3368/rk3399
> >> family SoCs in linux kernel.
> >> 
> >> Let's add the other SoCs, in order to a better understanding from the
> >> rockchip spi document.
> >> 
> >> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> >> Cc: Rob Herring <robh+dt at kernel.org>
> >> Cc: Mark Brown <broonie at kernel.org>
> >> Cc: Heiko Stuebner <heiko at sntech.de>
> >> Cc: linux-rockchip at lists.infradead.org
> >> ---
> >> 
> >>   Documentation/devicetree/bindings/spi/spi-rockchip.txt | 3 +++
> >>   1 file changed, 3 insertions(+)
> >> 
> >> diff --git a/Documentation/devicetree/bindings/spi/spi-rockchip.txt
> >> b/Documentation/devicetree/bindings/spi/spi-rockchip.txt index
> >> 1b14d69..305b542 100644
> >> --- a/Documentation/devicetree/bindings/spi/spi-rockchip.txt
> >> +++ b/Documentation/devicetree/bindings/spi/spi-rockchip.txt
> >> @@ -6,9 +6,12 @@ and display controllers using the SPI communication
> >> 
> >> interface. Required Properties:
> >>   - compatible: should be one of the following.
> >> 
> >> +    "rockchip,rk3036-spi" for rk3036.
> > 
> > shouldn't the rk3036 also get the rk3066 fallback. Looking at the driver
> > part (patch2) the rk3036 still is the same IP as for every other soc in
> > here.
> 
> Yep, the same IP.
> 
> Do you think we should keep the below style?
> 
> 1)
> "rockchip,rk3036-spi", "rockchip,rk3066-spi" for rk3036.
>   "rockchip,rk3066-spi" for rk3066.
>   "rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188.
> ...
> 
> or
> 2)
>   "rockchip,rk3066-spi" for rk3066.
> "rockchip,rk3036-spi", "rockchip,rk3066-spi" for rk3036.
>   "rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188
> ..
> 
> or
> 3)
> "rockchip, rockchip-spi" for rk3036 rk3066.......
> 
> Think about the 1) will be googd select.

or
(4) drop the fallbacks. We match against each compatible all the time 
anyway, so you could also simply do

  "rockchip,rk3036-spi" for rk3036
  "rockchip,rk3066-spi" for rk3066
  "rockchip,rk3188-spi" for rk3188

Maybe leave the fallbacks for existing socs, and just add the new ones 
without the fallbacks.

rockchip,rockchip-spi is not future proof ... i.e. in some future soc 
somebody might want to exchange the IP block against a different one, so 
being specific saves us from hassle then :-)


Heiko

> >>       "rockchip,rk3066-spi" for rk3066.
> >>       "rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188.
> >> 
> >> +    "rockchip,rk3228-spi", "rockchip,rk3066-spi" for rk3228.
> >> 
> >>       "rockchip,rk3288-spi", "rockchip,rk3066-spi" for rk3288.
> >> 
> >> +    "rockchip,rk3368-spi", "rockchip,rk3066-spi" for rk3368.
> >> 
> >>       "rockchip,rk3399-spi", "rockchip,rk3066-spi" for rk3399.
> >>   
> >>   - reg: physical base address of the controller and length of memory
> >> 
> >> mapped region.



From geert at linux-m68k.org  Thu May 19 09:25:02 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Thu, 19 May 2016 18:25:02 +0200
Subject: [PATCH v3 2/6] ARM: dts: r8a7794: add MSTP5 clocks
In-Reply-To: <1576909.nm8MtQ2Ln5@wasted.cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
 <1576909.nm8MtQ2Ln5@wasted.cogentembedded.com>
Message-ID: <CAMuHMdXaUNwOTQ7827+iTTfuRne_Z1F=-qgxu2cs07==AeqzCA@mail.gmail.com>

Hi Sergei,

On Thu, May 12, 2016 at 10:45 PM, Sergei Shtylyov
<sergei.shtylyov at cogentembedded.com> wrote:
> Add some MSTP5 clocks to the R8A7794 device tree.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>
>
> ---
> Changes in version 3:
> - refreshed the patch.
>
> Changes in version 2:
> - added "the" article to the change log.
>
>  arch/arm/boot/dts/r8a7794.dtsi            |    9 +++++++++
>  include/dt-bindings/clock/r8a7794-clock.h |    1 +
>  2 files changed, 10 insertions(+)
>
> Index: renesas/arch/arm/boot/dts/r8a7794.dtsi
> ===================================================================
> --- renesas.orig/arch/arm/boot/dts/r8a7794.dtsi
> +++ renesas/arch/arm/boot/dts/r8a7794.dtsi
> @@ -1172,6 +1172,15 @@
>                         clock-indices = <R8A7794_CLK_IRQC>;
>                         clock-output-names = "irqc";
>                 };
> +               mstp5_clks: mstp5_clks at e6150144 {
> +                       compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
> +                       reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>;
> +                       clocks = <&hp_clk>, <&extal_clk>, <&p_clk>;
> +                       #clock-cells = <1>;
> +                       clock-indices = <R8A7794_CLK_AUDIO_DMAC0
> +                                        R8A7794_CLK_THERMAL R8A7794_CLK_PWM>;
> +                       clock-output-names = "audmac0", "thermal", "pwm";

R-Car E2 does not have the thermal module.

> +               };
>                 mstp7_clks: mstp7_clks at e615014c {
>                         compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
>                         reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>;
> Index: renesas/include/dt-bindings/clock/r8a7794-clock.h
> ===================================================================
> --- renesas.orig/include/dt-bindings/clock/r8a7794-clock.h
> +++ renesas/include/dt-bindings/clock/r8a7794-clock.h
> @@ -67,6 +67,7 @@
>  #define R8A7794_CLK_IRQC               7
>
>  /* MSTP5 */
> +#define R8A7794_CLK_AUDIO_DMAC0                2
>  #define R8A7794_CLK_THERMAL            22

Hence R8A7794_CLK_THERMAL should be removed.

>  #define R8A7794_CLK_PWM                        23

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 geert at linux-m68k.org  Thu May 19 09:44:19 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Thu, 19 May 2016 18:44:19 +0200
Subject: [PATCH v3 3/6] ARM: dts: r8a7794: add MSTP10 clocks
In-Reply-To: <3321354.LNTkVAhXvF@wasted.cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
 <3321354.LNTkVAhXvF@wasted.cogentembedded.com>
Message-ID: <CAMuHMdVjrVFpEZPukWiLQK473R+7CTqVHc1jj8fktAD9RpH_sw@mail.gmail.com>

On Thu, May 12, 2016 at 10:46 PM, Sergei Shtylyov
<sergei.shtylyov at cogentembedded.com> wrote:
> Add MSTP10 clocks to the R8A7794 device tree.
>
> This patch is based on the commit ee9141522dcf ("ARM: shmobile: r8a7791:
> add MSTP10 support on DTSI").
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>
>
> ---
> Changes in version 3:
> - refreshed the patch.
>
> Changes in version 2:
> - fixed the SoC model in the change log;
> - added "the" article to the change log.
>
>  arch/arm/boot/dts/r8a7794.dtsi            |   53 ++++++++++++++++++++++++++++++
>  include/dt-bindings/clock/r8a7794-clock.h |   28 +++++++++++++++
>  2 files changed, 81 insertions(+)
>
> Index: renesas/arch/arm/boot/dts/r8a7794.dtsi
> ===================================================================
> --- renesas.orig/arch/arm/boot/dts/r8a7794.dtsi
> +++ renesas/arch/arm/boot/dts/r8a7794.dtsi
> @@ -1235,6 +1235,59 @@
>                                 "gpio1", "gpio0", "rcan1", "rcan0", "qspi_mod",
>                                 "i2c5", "i2c4", "i2c3", "i2c2", "i2c1", "i2c0";
>                 };
> +               mstp10_clks: mstp10_clks at e6150998 {
> +                       compatible = "renesas,r8a7794-mstp-clocks",
> +                                    "renesas,cpg-mstp-clocks";
> +                       reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
> +                       clocks = <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
> +                                <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
> +                                <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>,
> +                                <&mstp10_clks R8A7794_CLK_SCU_ALL>;
> +                       #clock-cells = <1>;
> +                       clock-indices = <R8A7794_CLK_SSI_ALL
> +                                        R8A7794_CLK_SSI9 R8A7794_CLK_SSI8
> +                                        R8A7794_CLK_SSI7 R8A7794_CLK_SSI6
> +                                        R8A7794_CLK_SSI5 R8A7794_CLK_SSI4
> +                                        R8A7794_CLK_SSI3 R8A7794_CLK_SSI2
> +                                        R8A7794_CLK_SSI1 R8A7794_CLK_SSI0
> +                                        R8A7794_CLK_SCU_ALL
> +                                        R8A7794_CLK_SCU_DVC1
> +                                        R8A7794_CLK_SCU_DVC0
> +                                        R8A7794_CLK_SCU_CTU1_MIX1
> +                                        R8A7794_CLK_SCU_CTU0_MIX0
> +                                        R8A7794_CLK_SCU_SRC9
> +                                        R8A7794_CLK_SCU_SRC8
> +                                        R8A7794_CLK_SCU_SRC7
> +                                        R8A7794_CLK_SCU_SRC6
> +                                        R8A7794_CLK_SCU_SRC5
> +                                        R8A7794_CLK_SCU_SRC4
> +                                        R8A7794_CLK_SCU_SRC3
> +                                        R8A7794_CLK_SCU_SRC2
> +                                        R8A7794_CLK_SCU_SRC1
> +                                        R8A7794_CLK_SCU_SRC0>;
> +                       clock-output-names = "ssi-all", "ssi9", "ssi8", "ssi7",
> +                                            "ssi6", "ssi5", "ssi4", "ssi3",
> +                                            "ssi2", "ssi1", "ssi0",
> +                                            "scu-all", "scu-dvc1", "scu-dvc0",
> +                                            "scu-ctu1-mix1", "scu-ctu0-mix0",
> +                                            "scu-src9", "scu-src8", "scu-src7",
> +                                            "scu-src6", "scu-src5", "scu-src4",
> +                                            "scu-src3", "scu-src2", "scu-src1",
> +                                            "scu-src0";
> +               };
>                 mstp11_clks: mstp11_clks at e615099c {
>                         compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
>                         reg = <0 0xe615099c 0 4>, <0 0xe61509ac 0 4>;
> Index: renesas/include/dt-bindings/clock/r8a7794-clock.h
> ===================================================================
> --- renesas.orig/include/dt-bindings/clock/r8a7794-clock.h
> +++ renesas/include/dt-bindings/clock/r8a7794-clock.h
> @@ -109,6 +109,34 @@
>  #define R8A7794_CLK_I2C1               30
>  #define R8A7794_CLK_I2C0               31
>
> +/* MSTP10 */
> +#define R8A7794_CLK_SSI_ALL            5
> +#define R8A7794_CLK_SSI9               6
> +#define R8A7794_CLK_SSI8               7
> +#define R8A7794_CLK_SSI7               8
> +#define R8A7794_CLK_SSI6               9
> +#define R8A7794_CLK_SSI5               10
> +#define R8A7794_CLK_SSI4               11
> +#define R8A7794_CLK_SSI3               12
> +#define R8A7794_CLK_SSI2               13
> +#define R8A7794_CLK_SSI1               14
> +#define R8A7794_CLK_SSI0               15
> +#define R8A7794_CLK_SCU_ALL            17
> +#define R8A7794_CLK_SCU_DVC1           18
> +#define R8A7794_CLK_SCU_DVC0           19
> +#define R8A7794_CLK_SCU_CTU1_MIX1      20
> +#define R8A7794_CLK_SCU_CTU0_MIX0      21
> +#define R8A7794_CLK_SCU_SRC9           22
> +#define R8A7794_CLK_SCU_SRC8           23
> +#define R8A7794_CLK_SCU_SRC7           24

R-Car E2 does not have SRC7, SRC8, SRC9, ...

> +#define R8A7794_CLK_SCU_SRC6           25
> +#define R8A7794_CLK_SCU_SRC5           26
> +#define R8A7794_CLK_SCU_SRC4           27
> +#define R8A7794_CLK_SCU_SRC3           28
> +#define R8A7794_CLK_SCU_SRC2           29
> +#define R8A7794_CLK_SCU_SRC1           30
> +#define R8A7794_CLK_SCU_SRC0           31

... and SRC0.

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 eballetbo at gmail.com  Thu May 19 09:53:09 2016
From: eballetbo at gmail.com (Enric Balletbo Serra)
Date: Thu, 19 May 2016 18:53:09 +0200
Subject: [PATCH v3] mmc: dw_mmc: rockchip: Set the drive phase properly
In-Reply-To: <2865073.LogD6IIKLp@phil>
References: <1463077910-25914-1-git-send-email-dianders@chromium.org>
 <2865073.LogD6IIKLp@phil>
Message-ID: <CAFqH_52KqPXM_AjC8qKrVvH2hSvqtiBjmN28SZgJgoWVCe0pmg@mail.gmail.com>

2016-05-13 0:52 GMT+02:00 Heiko Stuebner <heiko at sntech.de>:
> Am Donnerstag, 12. Mai 2016, 11:31:50 schrieb Douglas Anderson:
>
> [...]
>
>> In commit 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card
>> initialization") we actually started setting this explicitly in the
>> kernel, but that commit wasn't quite right and also wasn't quite
>> enough.  See <https://patchwork.kernel.org/patch/9085311/> for some
>> details.
>>
>> Let's explicitly set this phase in dw_mmc.
>
> [...]
>
>> Fixes: 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card
>> initialization") Signed-off-by: Douglas Anderson <dianders at chromium.org>
>> Reviewed-by: Shawn Lin <shawn.lin at rock-chips.com>
>
> I've tested this patch together with the two clock patches linked above on a
> rk3288-firefly and a rk3288-veyron-jerry. On the firefly tuning still does not
> work (probably really some regulator issue) and on veyron tuning still works
> as expected, so
>
> Tested-by: Heiko Stuebner <heiko at sntech.de>
>
> Doug's explanations both in the commit message and the code look sane to me,
> but I don't feel confident enough in my understanding of the matter to
> transform that into a Reviewed-by tag.
>
>

I've tested this patch on rock2 square inserting some uSD cards and
seeing that they still enumerate properly, also I booted from a uSD
card.
Note that in current state UHS is not supported so the tuning is not
executed. Enable UHS on rock2 requires some work, I'll try to look at
it but meanwhile I can say that doesn't break current state, so

Tested-by: Enric Balletbo i Serra <enric.balletbo at collabora.com>

> Heiko
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From geert at linux-m68k.org  Thu May 19 09:54:40 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Thu, 19 May 2016 18:54:40 +0200
Subject: [PATCH/RFC 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <1463629845-7115-2-git-send-email-horms+renesas@verge.net.au>
References: <1463629845-7115-1-git-send-email-horms+renesas@verge.net.au>
 <1463629845-7115-2-git-send-email-horms+renesas@verge.net.au>
Message-ID: <CAMuHMdV0tvAPvCQ3NjXVar6fykOwWzGs9fzks-0eEqk8-ZsTKQ@mail.gmail.com>

Hi Simon,

On Thu, May 19, 2016 at 5:50 AM, Simon Horman
<horms+renesas at verge.net.au> wrote:
> Basic support for the Gen 3 R-Car M3-W SoC.
>
> Based on work for the r8a7795 and r8a7796 SoCs by
> Takeshi Kihara, Dirk Behme and Geert Uytterhoeven.
>
> Signed-off-by: Simon Horman <horms+renesas at verge.net.au>

Thanks for your patch!

> --- /dev/null
> +++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> @@ -0,0 +1,120 @@
> +/*
> + * Device Tree Source for the r8a7796 SoC
> + *
> + * Copyright (C) 2016 Renesas Electronics Corp.
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2.  This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#include <dt-bindings/clock/r8a7796-cpg-mssr.h>
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +/ {
> +       compatible = "renesas,r8a7796";
> +       #address-cells = <2>;
> +       #size-cells = <2>;
> +
> +       psci {
> +               compatible = "arm,psci-1.0";
> +               method = "smc";
> +       };
> +
> +       cpus {
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +               /* 1 core only at this point */
> +               a57_0: cpu at 0 {
> +                       compatible = "arm,cortex-a57", "arm,armv8";
> +                       reg = <0x0>;
> +                       device_type = "cpu";
> +                       next-level-cache = <&L2_CA57>;
> +                       enable-method = "psci";
> +               };
> +       };
> +
> +       L2_CA57: cache-controller at 0 {
> +               compatible = "cache";

With W=1:

Warning (unit_address_vs_reg): Node /cache-controller at 0 has a unit
name, but no reg property

> +               cache-unified;
> +               cache-level = <2>;
> +       };

Please add the missing "reg = <0>;>, and move this node under the cpus node
so he reg property matches #address-cells/#size-cells.

> +       /* External SCIF clock - to be overridden by boards that provide it */
> +       scif_clk: scif {
> +               compatible = "fixed-clock";
> +               #clock-cells = <0>;
> +               clock-frequency = <0>;
> +               status = "disabled";

Please drop the disabled status.

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 mbrugger at suse.com  Thu May 19 09:56:25 2016
From: mbrugger at suse.com (Matthias Brugger)
Date: Thu, 19 May 2016 18:56:25 +0200
Subject: [PATCH V7 08/11] pci, acpi: Support for ACPI based generic PCI
 host controller
In-Reply-To: <1462893601-8937-9-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-9-git-send-email-tn@semihalf.com>
Message-ID: <573DF039.5040405@suse.com>



On 10/05/16 17:19, Tomasz Nowicki wrote:
> This patch is going to implement generic PCI host controller for
> ACPI world, similar to what pci-host-generic.c driver does for DT world.
>
> All such drivers, which we have seen so far, were implemented within
> arch/ directory since they had some arch assumptions (x86 and ia64).
> However, they all are doing similar thing, so it makes sense to find
> some common code and abstract it into the generic driver.
>
> In order to handle PCI config space regions properly, we define new
> MCFG interface which does sanity checks on MCFG table and keeps its
> root pointer. User is able to lookup MCFG regions based on that root
> pointer and specified domain:bus_start:bus_end touple. We are using
> pci_mmcfg_late_init old prototype to avoid another function name.
>
> The implementation of pci_acpi_scan_root() looks up the MCFG entries
> and sets up a new mapping (regions are not mapped until host controller ask
> for it). Generic PCI functions are used for accessing config space.
> Driver selects PCI_ECAM and uses functions from drivers/pci/ecam.h
> to create and access ECAM mappings.
>
> As mentioned in Kconfig help section, ACPI_PCI_HOST_GENERIC choice
> should be made on a per-architecture basis.
>
> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
> ---
>   drivers/acpi/Kconfig            |   8 +++
>   drivers/acpi/Makefile           |   1 +
>   drivers/acpi/pci_mcfg.c         |  97 ++++++++++++++++++++++++++
>   drivers/acpi/pci_root_generic.c | 149 ++++++++++++++++++++++++++++++++++++++++
>   drivers/pci/ecam.h              |   5 ++
>   include/linux/pci-acpi.h        |   5 ++
>   include/linux/pci.h             |   5 +-
>   7 files changed, 269 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/acpi/pci_mcfg.c
>   create mode 100644 drivers/acpi/pci_root_generic.c
>
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index 183ffa3..44afc76 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -346,6 +346,14 @@ config ACPI_PCI_SLOT
>   	  i.e., segment/bus/device/function tuples, with physical slots in
>   	  the system.  If you are unsure, say N.
>
> +config ACPI_PCI_HOST_GENERIC
> +	bool
> +	select PCI_ECAM
> +	help
> +	  Select this config option from the architecture Kconfig,
> +	  if it is preferred to enable ACPI PCI host controller driver which
> +	  has no arch-specific assumptions.
> +
>   config X86_PM_TIMER
>   	bool "Power Management Timer Support" if EXPERT
>   	depends on X86
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 81e5cbc..627a2b7 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -40,6 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
>   acpi-y				+= ec.o
>   acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
>   acpi-y				+= pci_root.o pci_link.o pci_irq.o
> +obj-$(CONFIG_ACPI_PCI_HOST_GENERIC)	+= pci_root_generic.o pci_mcfg.o
>   acpi-y				+= acpi_lpss.o acpi_apd.o
>   acpi-y				+= acpi_platform.o
>   acpi-y				+= acpi_pnp.o
> diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
> new file mode 100644
> index 0000000..373d079
> --- /dev/null
> +++ b/drivers/acpi/pci_mcfg.c
> @@ -0,0 +1,97 @@
> +/*
> + * Copyright (C) 2016 Broadcom
> + *	Author: Jayachandran C <jchandra at broadcom.com>
> + * Copyright (C) 2016 Semihalf
> + * 	Author: Tomasz Nowicki <tn at semihalf.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, version 2, as
> + * published by the Free Software Foundation (the "GPL").
> + *
> + * 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 version 2 (GPLv2) for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * version 2 (GPLv2) along with this source code.
> + */
> +#include <linux/kernel.h>
> +#include <linux/pci.h>
> +#include <linux/pci-acpi.h>
> +
> +#define PREFIX	"ACPI: "
> +
> +/* Root pointer to the mapped MCFG table */
> +static struct acpi_table_mcfg *mcfg_table;
> +
> +#define MCFG_ENTRIES(mcfg_ptr)	(((mcfg_ptr)->header.length -		\
> +				sizeof(struct acpi_table_mcfg)) /	\
> +				sizeof(struct acpi_mcfg_allocation))
> +
> +static phys_addr_t pci_mcfg_lookup_static(u16 seg, u8 bus_start, u8 bus_end)
> +{
> +	struct acpi_mcfg_allocation *mptr;
> +	int i;
> +
> +	if (!mcfg_table) {
> +		pr_err(PREFIX "MCFG table not available, lookup failed\n");
> +		return -ENXIO;
> +	}
> +
> +	mptr = (struct acpi_mcfg_allocation *) &mcfg_table[1];
> +
> +	/*
> +	 * We expect exact match, unless MCFG entry end bus covers more than
> +	 * specified by caller.
> +	 */
> +	for (i = 0; i < MCFG_ENTRIES(mcfg_table); i++, mptr++) {
> +		if (mptr->pci_segment == seg &&
> +		    mptr->start_bus_number == bus_start &&
> +		    mptr->end_bus_number >= bus_end) {
> +			return mptr->address;
> +		}
> +	}
> +
> +	return -ENXIO;
> +}
> +
> +phys_addr_t pci_mcfg_lookup(struct acpi_device *device, u16 seg,
> +			    struct resource *bus_res)
> +{
> +	phys_addr_t addr;
> +
> +	addr = acpi_pci_root_get_mcfg_addr(device->handle);
> +	if (addr)
> +		return addr;
> +
> +	return pci_mcfg_lookup_static(seg, bus_res->start, bus_res->end);
> +}
> +
> +static __init int pci_mcfg_parse(struct acpi_table_header *header)
> +{
> +	struct acpi_table_mcfg *mcfg;
> +	int n;
> +
> +	if (!header)
> +		return -EINVAL;

Maybe that's bike shedding, but acpi_table_parse already checks that the 
table passed to the handler exists, so this is redundant.

Regards,
Matthias


From tony at atomide.com  Thu May 19 09:57:19 2016
From: tony at atomide.com (Tony Lindgren)
Date: Thu, 19 May 2016 09:57:19 -0700
Subject: Regression: next-20160518: Clk? on BeagleBoard-X15
In-Reply-To: <573DDFE6.8010209@ti.com>
References: <573DDFE6.8010209@ti.com>
Message-ID: <20160519165719.GW5995@atomide.com>

* Nishanth Menon <nm at ti.com> [160519 08:48]:
> I have'nt bisected yet, but the platform seems to have booted on
> next-20160517
> https://github.com/nmenon/kernel-test-logs/blob/next-20160517/omap2plus_defconfig/am57xx-evm.txt
> 
> https://github.com/nmenon/kernel-test-logs/blob/next-20160518/omap2plus_defconfig/am57xx-evm.txt

Seems to be commit ac78f9bdcf38 ("drivers/of: Fix depth when
unflattening devicetree").

Rob, you need to start playing golf or something between -rc6 and
the end of the merge window or something :)

Regards,

Tony


From geert at linux-m68k.org  Thu May 19 09:58:11 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Thu, 19 May 2016 18:58:11 +0200
Subject: [PATCH/RFC 2/3] arm64: dts: salvator-x: add Salvator-X board on
 R8A7796 SoC
In-Reply-To: <1463629845-7115-3-git-send-email-horms+renesas@verge.net.au>
References: <1463629845-7115-1-git-send-email-horms+renesas@verge.net.au>
 <1463629845-7115-3-git-send-email-horms+renesas@verge.net.au>
Message-ID: <CAMuHMdVTMvDsmO1g=FNwpkvx_56guHk_V6Katj8e3qOdyQsjeQ@mail.gmail.com>

On Thu, May 19, 2016 at 5:50 AM, Simon Horman
<horms+renesas at verge.net.au> wrote:
> --- /dev/null
> +++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
> @@ -0,0 +1,45 @@

> +       chosen {
> +               bootargs = "ignore_loglevel";

Perhaps you want this to be consistent with the other Renesas boards?

git grep bootargs -- $(git grep -l renesas, -- arch/arm*/*dts)

> +               stdout-path = "serial0:115200n8";
> +       };

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 geert at linux-m68k.org  Thu May 19 10:07:00 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Thu, 19 May 2016 19:07:00 +0200
Subject: [PATCH/RFC 3/3] arm64: defconfig: enable Renesas R8A7796 SoC
In-Reply-To: <1463629845-7115-4-git-send-email-horms+renesas@verge.net.au>
References: <1463629845-7115-1-git-send-email-horms+renesas@verge.net.au>
 <1463629845-7115-4-git-send-email-horms+renesas@verge.net.au>
Message-ID: <CAMuHMdWQ8LPZsOYUH5E6WkjOHoUHkqpTUMz4xd5k=ovi1XH0ow@mail.gmail.com>

On Thu, May 19, 2016 at 5:50 AM, Simon Horman
<horms+renesas at verge.net.au> wrote:
> From: Takeshi Kihara <takeshi.kihara.df at renesas.com>
>
> This patch enables the Renesas R8A7796 SoC in the arm64 defconfig.
>
> Signed-off-by: Takeshi Kihara <takeshi.kihara.df at renesas.com>
> Signed-off-by: Simon Horman <horms+renesas at verge.net.au>

Acked-by: Geert Uytterhoeven <geert+renesas at glider.be>

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 sergei.shtylyov at cogentembedded.com  Thu May 19 10:30:12 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 19 May 2016 20:30:12 +0300
Subject: [PATCH v3 2/6] ARM: dts: r8a7794: add MSTP5 clocks
In-Reply-To: <CAMuHMdXaUNwOTQ7827+iTTfuRne_Z1F=-qgxu2cs07==AeqzCA@mail.gmail.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
 <1576909.nm8MtQ2Ln5@wasted.cogentembedded.com>
 <CAMuHMdXaUNwOTQ7827+iTTfuRne_Z1F=-qgxu2cs07==AeqzCA@mail.gmail.com>
Message-ID: <23a35d91-7ba3-be23-c8ee-5a056e6a627b@cogentembedded.com>

On 05/19/2016 07:25 PM, Geert Uytterhoeven wrote:

>> Add some MSTP5 clocks to the R8A7794 device tree.
>>
>> Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>
>>
>> ---
>> Changes in version 3:
>> - refreshed the patch.
>>
>> Changes in version 2:
>> - added "the" article to the change log.
>>
>>  arch/arm/boot/dts/r8a7794.dtsi            |    9 +++++++++
>>  include/dt-bindings/clock/r8a7794-clock.h |    1 +
>>  2 files changed, 10 insertions(+)
>>
>> Index: renesas/arch/arm/boot/dts/r8a7794.dtsi
>> ===================================================================
>> --- renesas.orig/arch/arm/boot/dts/r8a7794.dtsi
>> +++ renesas/arch/arm/boot/dts/r8a7794.dtsi
>> @@ -1172,6 +1172,15 @@
>>                         clock-indices = <R8A7794_CLK_IRQC>;
>>                         clock-output-names = "irqc";
>>                 };
>> +               mstp5_clks: mstp5_clks at e6150144 {
>> +                       compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
>> +                       reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>;
>> +                       clocks = <&hp_clk>, <&extal_clk>, <&p_clk>;
>> +                       #clock-cells = <1>;
>> +                       clock-indices = <R8A7794_CLK_AUDIO_DMAC0
>> +                                        R8A7794_CLK_THERMAL R8A7794_CLK_PWM>;
>> +                       clock-output-names = "audmac0", "thermal", "pwm";
>
> R-Car E2 does not have the thermal module.

    My "R-Car Series, 2nd Generation User?s Manual: Hardware, Rev.1.02 Oct 
2014" says it does. What's your source?

>> +               };
>>                 mstp7_clks: mstp7_clks at e615014c {
>>                         compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
>>                         reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>;
>> Index: renesas/include/dt-bindings/clock/r8a7794-clock.h
>> ===================================================================
>> --- renesas.orig/include/dt-bindings/clock/r8a7794-clock.h
>> +++ renesas/include/dt-bindings/clock/r8a7794-clock.h
>> @@ -67,6 +67,7 @@
>>  #define R8A7794_CLK_IRQC               7
>>
>>  /* MSTP5 */
>> +#define R8A7794_CLK_AUDIO_DMAC0                2
>>  #define R8A7794_CLK_THERMAL            22
>
> Hence R8A7794_CLK_THERMAL should be removed.

    Well, remove it then. ;-)

>>  #define R8A7794_CLK_PWM                        23
>
> Gr{oetje,eeting}s,

MBR, Sergei



From tomi.valkeinen at ti.com  Thu May 19 10:35:29 2016
From: tomi.valkeinen at ti.com (Tomi Valkeinen)
Date: Thu, 19 May 2016 20:35:29 +0300
Subject: Regression: next-20160518: Clk? on BeagleBoard-X15
In-Reply-To: <20160519165719.GW5995@atomide.com>
References: <573DDFE6.8010209@ti.com> <20160519165719.GW5995@atomide.com>
Message-ID: <573DF961.4070705@ti.com>

On 19/05/16 19:57, Tony Lindgren wrote:
> * Nishanth Menon <nm at ti.com> [160519 08:48]:
>> I have'nt bisected yet, but the platform seems to have booted on
>> next-20160517
>> https://github.com/nmenon/kernel-test-logs/blob/next-20160517/omap2plus_defconfig/am57xx-evm.txt
>>
>> https://github.com/nmenon/kernel-test-logs/blob/next-20160518/omap2plus_defconfig/am57xx-evm.txt
> 
> Seems to be commit ac78f9bdcf38 ("drivers/of: Fix depth when
> unflattening devicetree").
> 
> Rob, you need to start playing golf or something between -rc6 and
> the end of the merge window or something :)

I'm not sure if it's related, but I'm seeing this on omap4 panda, next-20160519:

[    0.000000] Unable to handle kernel paging request at virtual address af6ec820
...
[    0.000000] [<c071ced4>] (unflatten_dt_nodes) from [<c071d5a4>] (__unflatten_device_tree+0xe8/0x254)
[    0.000000]  r10:c0de3140 r9:ef6b44a4 r8:c15b77c0 r7:00000000 r6:cffee000 r5:00038358
[    0.000000]  r4:c0de00c0
[    0.000000] [<c071d4bc>] (__unflatten_device_tree) from [<c0c4a050>] (unflatten_device_tree+0x28/0x40)
[    0.000000]  r9:0000000c r8:c0d07ca8 r7:c159f4f4 r6:c0d520f8 r5:c0c5984c r4:c0c491a0
[    0.000000] [<c0c4a028>] (unflatten_device_tree) from [<c0c04754>] (setup_arch+0x770/0xbb4)
[    0.000000]  r5:c0c5984c r4:c0d02908
[    0.000000] [<c0c03fe4>] (setup_arch) from [<c0c009c8>] (start_kernel+0x50/0x3c4)
[    0.000000]  r10:00000000 r9:412fc09a r8:8000406a r7:c0d02900 r6:c0c5ba44 r5:c0d029ac
[    0.000000]  r4:c0de3214
[    0.000000] [<c0c00978>] (start_kernel) from [<8000807c>] (0x8000807c)
[    0.000000]  r10:00000000 r9:412fc09a r8:8000406a r7:c0d07de8 r6:c0c5ba44 r5:c0d029ac
[    0.000000]  r4:c0de3214

 Tomi

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160519/b70f5f89/attachment.sig>

From robh at kernel.org  Thu May 19 10:35:29 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 19 May 2016 12:35:29 -0500
Subject: Regression: next-20160518: Clk? on BeagleBoard-X15
In-Reply-To: <20160519165719.GW5995@atomide.com>
References: <573DDFE6.8010209@ti.com> <20160519165719.GW5995@atomide.com>
Message-ID: <CAL_Jsq+ORQ5PP80_HbH16+SaHFLdrefcVGFzsvgLYiiwtq9PuQ@mail.gmail.com>

On Thu, May 19, 2016 at 11:57 AM, Tony Lindgren <tony at atomide.com> wrote:
> * Nishanth Menon <nm at ti.com> [160519 08:48]:
>> I have'nt bisected yet, but the platform seems to have booted on
>> next-20160517
>> https://github.com/nmenon/kernel-test-logs/blob/next-20160517/omap2plus_defconfig/am57xx-evm.txt
>>
>> https://github.com/nmenon/kernel-test-logs/blob/next-20160518/omap2plus_defconfig/am57xx-evm.txt
>
> Seems to be commit ac78f9bdcf38 ("drivers/of: Fix depth when
> unflattening devicetree").
>
> Rob, you need to start playing golf or something between -rc6 and
> the end of the merge window or something :)

It seems the fix for one board broke more... It is fixed in my tree now.

Rob


From sergei.shtylyov at cogentembedded.com  Thu May 19 10:37:39 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 19 May 2016 20:37:39 +0300
Subject: [PATCH v3 3/6] ARM: dts: r8a7794: add MSTP10 clocks
In-Reply-To: <CAMuHMdVjrVFpEZPukWiLQK473R+7CTqVHc1jj8fktAD9RpH_sw@mail.gmail.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
 <3321354.LNTkVAhXvF@wasted.cogentembedded.com>
 <CAMuHMdVjrVFpEZPukWiLQK473R+7CTqVHc1jj8fktAD9RpH_sw@mail.gmail.com>
Message-ID: <f0700315-af43-b208-cd91-8ca510bf5da9@cogentembedded.com>

Hello.

On 05/19/2016 07:44 PM, Geert Uytterhoeven wrote:

>> Add MSTP10 clocks to the R8A7794 device tree.
>>
>> This patch is based on the commit ee9141522dcf ("ARM: shmobile: r8a7791:
>> add MSTP10 support on DTSI").
>>
>> Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>
>>
[...]
>> Index: renesas/include/dt-bindings/clock/r8a7794-clock.h
>> ===================================================================
>> --- renesas.orig/include/dt-bindings/clock/r8a7794-clock.h
>> +++ renesas/include/dt-bindings/clock/r8a7794-clock.h
>> @@ -109,6 +109,34 @@
>>  #define R8A7794_CLK_I2C1               30
>>  #define R8A7794_CLK_I2C0               31
>>
>> +/* MSTP10 */
>> +#define R8A7794_CLK_SSI_ALL            5
>> +#define R8A7794_CLK_SSI9               6
>> +#define R8A7794_CLK_SSI8               7
>> +#define R8A7794_CLK_SSI7               8
>> +#define R8A7794_CLK_SSI6               9
>> +#define R8A7794_CLK_SSI5               10
>> +#define R8A7794_CLK_SSI4               11
>> +#define R8A7794_CLK_SSI3               12
>> +#define R8A7794_CLK_SSI2               13
>> +#define R8A7794_CLK_SSI1               14
>> +#define R8A7794_CLK_SSI0               15
>> +#define R8A7794_CLK_SCU_ALL            17
>> +#define R8A7794_CLK_SCU_DVC1           18
>> +#define R8A7794_CLK_SCU_DVC0           19
>> +#define R8A7794_CLK_SCU_CTU1_MIX1      20
>> +#define R8A7794_CLK_SCU_CTU0_MIX0      21
>> +#define R8A7794_CLK_SCU_SRC9           22
>> +#define R8A7794_CLK_SCU_SRC8           23
>> +#define R8A7794_CLK_SCU_SRC7           24
>
> R-Car E2 does not have SRC7, SRC8, SRC9, ...
>
>> +#define R8A7794_CLK_SCU_SRC6           25
>> +#define R8A7794_CLK_SCU_SRC5           26
>> +#define R8A7794_CLK_SCU_SRC4           27
>> +#define R8A7794_CLK_SCU_SRC3           28
>> +#define R8A7794_CLK_SCU_SRC2           29
>> +#define R8A7794_CLK_SCU_SRC1           30
>> +#define R8A7794_CLK_SCU_SRC0           31
>
> ... and SRC0.

    Yet table 7A.12 in the rev1.02 manual lists them all. Your manual doesn't?

MBR, Sergei



From geert at linux-m68k.org  Thu May 19 10:41:29 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Thu, 19 May 2016 19:41:29 +0200
Subject: [PATCH v3 3/6] ARM: dts: r8a7794: add MSTP10 clocks
In-Reply-To: <f0700315-af43-b208-cd91-8ca510bf5da9@cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
 <3321354.LNTkVAhXvF@wasted.cogentembedded.com>
 <CAMuHMdVjrVFpEZPukWiLQK473R+7CTqVHc1jj8fktAD9RpH_sw@mail.gmail.com>
 <f0700315-af43-b208-cd91-8ca510bf5da9@cogentembedded.com>
Message-ID: <CAMuHMdWSfx_Q9xopidpLCbwHhuPKwfokiUXYPpHxf3B2tC+-dw@mail.gmail.com>

On Thu, May 19, 2016 at 7:37 PM, Sergei Shtylyov
<sergei.shtylyov at cogentembedded.com> wrote:
>>> --- renesas.orig/include/dt-bindings/clock/r8a7794-clock.h
>>> +++ renesas/include/dt-bindings/clock/r8a7794-clock.h
>>> @@ -109,6 +109,34 @@
>>>  #define R8A7794_CLK_I2C1               30
>>>  #define R8A7794_CLK_I2C0               31
>>>
>>> +/* MSTP10 */
>>> +#define R8A7794_CLK_SSI_ALL            5
>>> +#define R8A7794_CLK_SSI9               6
>>> +#define R8A7794_CLK_SSI8               7
>>> +#define R8A7794_CLK_SSI7               8
>>> +#define R8A7794_CLK_SSI6               9
>>> +#define R8A7794_CLK_SSI5               10
>>> +#define R8A7794_CLK_SSI4               11
>>> +#define R8A7794_CLK_SSI3               12
>>> +#define R8A7794_CLK_SSI2               13
>>> +#define R8A7794_CLK_SSI1               14
>>> +#define R8A7794_CLK_SSI0               15
>>> +#define R8A7794_CLK_SCU_ALL            17
>>> +#define R8A7794_CLK_SCU_DVC1           18
>>> +#define R8A7794_CLK_SCU_DVC0           19
>>> +#define R8A7794_CLK_SCU_CTU1_MIX1      20
>>> +#define R8A7794_CLK_SCU_CTU0_MIX0      21
>>> +#define R8A7794_CLK_SCU_SRC9           22
>>> +#define R8A7794_CLK_SCU_SRC8           23
>>> +#define R8A7794_CLK_SCU_SRC7           24
>>
>>
>> R-Car E2 does not have SRC7, SRC8, SRC9, ...
>>
>>> +#define R8A7794_CLK_SCU_SRC6           25
>>> +#define R8A7794_CLK_SCU_SRC5           26
>>> +#define R8A7794_CLK_SCU_SRC4           27
>>> +#define R8A7794_CLK_SCU_SRC3           28
>>> +#define R8A7794_CLK_SCU_SRC2           29
>>> +#define R8A7794_CLK_SCU_SRC1           30
>>> +#define R8A7794_CLK_SCU_SRC0           31
>>
>>
>> ... and SRC0.
>
>
>    Yet table 7A.12 in the rev1.02 manual lists them all. Your manual
> doesn't?

I thought you were aware of this, cfr. your "[PATCH] rcar: src: skip
disabled-SRC nodes"?

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 matija.glavinic-pecotic.ext at nokia.com  Thu May 19 10:41:28 2016
From: matija.glavinic-pecotic.ext at nokia.com (Matija Glavinic Pecotic)
Date: Thu, 19 May 2016 19:41:28 +0200
Subject: [PATCH v2] ARM Fix A15 798181 errata initialization
Message-ID: <573DFAC8.2070805@nokia.com>

Current errata initialization doesn't take properly revision and REVIDR
into account. Depending on the core revision, revidr bits should not be
taken into account. Errata misleadingly declares r3p3 to be error-free,
but this is not the case. Include rp3p3 in errata initialization.

Here are possible fixes defined in revidr register for r2 and r3 [1,2]:

r0p0-r2p1: No fixes applied

r2p2,r2p3:

REVIDR[4]: 798181 Moving a virtual page that is being accessed by
	   an active process can lead to unexpected behavior
REVIDR[9]: Not defined

r2p4,r3p0,r3p1,r3p2:

REVIDR[4]: 798181 Moving a virtual page that is being accessed by
	   an active process can lead to unexpected behavior
REVIDR[9]: 798181 Moving a virtual page that is being accessed by
	   an active process can lead to unexpected behavior
	   - This is an update to a previously released ECO.

r3p3:

REVIDR[4]: Reserved
REVIDR[9]: 798181 Moving a virtual page that is being accessed by
	   an active process can lead to unexpected behavior
	   - This is an update to a previously released ECO.

And here is proposed handling from the same document:

* In r3p2 and earlier versions with REVIDR[4]= 0,the full workaround is
  required.
* In r3p2 and earlier versions with REVIDR[4]=1, REVIDR[9]=0, only the
  portion of the workaround up to the end of step 6 is required.
* In r3p2 and earlier versions with REVIDR[4]=1, REVIDR[9]=1, no
  workaround is required.
* In r3p3, if REVIDR[9]=0, only the portion of the workaround up
  to the end of step 6 is required.
* In r3p3, if REVIDR[9]=1, no workaround is required.

These imply following:

REVIDR[9] set -> No WA
REVIDR[4] set, REVIDR[9] cleared -> Partial WA
Both cleared -> Full WA

Where certain bits should and should not be taken into account
depending on whether they are defined for the revision.

Although not explicitly mentioned in the errata note, REVIDR[9] set,
with REVIDR[4] cleared is valid combination which requires no WA. This
is confirmed by ARM support and errata will be updated.

[1] ARM CortexTM-A15 MPCore - NEON
    Product revision r3
    Software Developers Errata Notice
    ARM-EPM-028093 v20.0 Released

[2] ARM CortexTM-A15 MPCore - NEON
    Product Revision r2
    Software Developers Errata Notice
    ARM-EPM-028090 v19.3 Released

Signed-off-by: Matija Glavinic Pecotic <matija.glavinic-pecotic.ext at nokia.com>
Reviewed-by: Alexander Sverdlin <alexander.sverdlin at nokia.com>
Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>
---
Changes in v2: Explicitly comment versions, fixes and handling

 arch/arm/kernel/smp_tlb.c | 44 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 40 insertions(+), 4 deletions(-)

diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
index 2e72be4..22313cb 100644
--- a/arch/arm/kernel/smp_tlb.c
+++ b/arch/arm/kernel/smp_tlb.c
@@ -93,17 +93,53 @@ void erratum_a15_798181_init(void)
 	unsigned int revidr = read_cpuid(CPUID_REVIDR);
 
 	/* Brahma-B15 r0p0..r0p2 affected
-	 * Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
-	if ((midr & 0xff0ffff0) == 0x420f00f0 && midr <= 0x420f00f2)
+	 * Cortex-A15 r0p0..r3p3 w/o ECO fix affected
+	 * Fixes applied to A15 with respect to the revision and revidr are:
+	 *
+	 * r0p0-r2p1: No fixes applied
+	 * r2p2,r2p3:
+	 *	REVIDR[4]: 798181 Moving a virtual page that is being accessed
+	 *		   by an active process can lead to unexpected behavior
+	 *	REVIDR[9]: Not defined
+	 * r2p4,r3p0,r3p1,r3p2:
+	 *	REVIDR[4]: 798181 Moving a virtual page that is being accessed
+	 *		   by an active process can lead to unexpected behavior
+	 *	REVIDR[9]: 798181 Moving a virtual page that is being accessed
+	 *		   by an active process can lead to unexpected behavior
+	 *		   - This is an update to a previously released ECO.
+	 * r3p3:
+	 *	REVIDR[4]: Reserved
+	 *	REVIDR[9]: 798181 Moving a virtual page that is being accessed
+	 *		   by an active process can lead to unexpected behavior
+	 *		   - This is an update to a previously released ECO.
+	 *
+	 * Handling:
+	 *	REVIDR[9] set -> No WA
+	 *	REVIDR[4] set, REVIDR[9] cleared -> Partial WA
+	 *	Both cleared -> Full WA
+	 */
+	if ((midr & 0xff0ffff0) == 0x420f00f0 && midr <= 0x420f00f2) {
 		erratum_a15_798181_handler = erratum_a15_798181_broadcast;
-	else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr <= 0x413fc0f2 &&
-		 (revidr & 0x210) != 0x210) {
+	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x412fc0f2) {
+		erratum_a15_798181_handler = erratum_a15_798181_broadcast;
+	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x412fc0f4) {
 		if (revidr & 0x10)
 			erratum_a15_798181_handler =
 				erratum_a15_798181_partial;
 		else
 			erratum_a15_798181_handler =
 				erratum_a15_798181_broadcast;
+	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x413fc0f3) {
+		if ((revidr & 0x210) == 0)
+			erratum_a15_798181_handler =
+				erratum_a15_798181_broadcast;
+		else if (revidr & 0x10)
+			erratum_a15_798181_handler =
+				erratum_a15_798181_partial;
+	} else if ((midr & 0xff0ffff0) == 0x410fc0f0 && midr < 0x414fc0f0) {
+		if ((revidr & 0x200) == 0)
+			erratum_a15_798181_handler =
+				erratum_a15_798181_partial;
 	}
 }
 #endif
-- 
2.1.4


From andre.przywara at arm.com  Thu May 19 11:07:40 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:40 +0100
Subject: [PATCH v5 01/57] KVM: arm/arm64: vgic: streamline
 vgic_update_irq_pending() interface
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-2-git-send-email-andre.przywara@arm.com>

We actually don't use the irq_phys_map parameter in
vgic_update_irq_pending(), so let's just remove it.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 virt/kvm/arm/vgic.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 60668a7..f6c6172 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1521,7 +1521,6 @@ static int vgic_validate_injection(struct kvm_vcpu *vcpu, int irq, int level)
 }
 
 static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
-				   struct irq_phys_map *map,
 				   unsigned int irq_num, bool level)
 {
 	struct vgic_dist *dist = &kvm->arch.vgic;
@@ -1660,7 +1659,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 	if (map)
 		return -EINVAL;
 
-	return vgic_update_irq_pending(kvm, cpuid, NULL, irq_num, level);
+	return vgic_update_irq_pending(kvm, cpuid, irq_num, level);
 }
 
 /**
@@ -1686,7 +1685,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 	if (ret)
 		return ret;
 
-	return vgic_update_irq_pending(kvm, cpuid, map, map->virt_irq, level);
+	return vgic_update_irq_pending(kvm, cpuid, map->virt_irq, level);
 }
 
 static irqreturn_t vgic_maintenance_handler(int irq, void *data)
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:42 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:42 +0100
Subject: [PATCH v5 03/57] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_map_is_active()
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-4-git-send-email-andre.przywara@arm.com>

For getting the active state of a mapped IRQ, we actually only need
the virtual IRQ number, not the pointer to the mapping entry.
Pass the virtual IRQ number from the arch timer to the VGIC directly.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- rewrap phys_active determination to fit in 80 characters

 include/kvm/arm_vgic.h    | 2 +-
 virt/kvm/arm/arch_timer.c | 6 ++----
 virt/kvm/arm/vgic.c       | 6 +++---
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index e22f015..9830232 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -348,7 +348,7 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 					   int virt_irq, int irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index a9c6c1c..37f82c1 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -274,10 +274,8 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* to ensure that hardware interrupts from the timer triggers a guest
 	* exit.
 	*/
-	if (timer->irq.level || kvm_vgic_map_is_active(vcpu, timer->map))
-		phys_active = true;
-	else
-		phys_active = false;
+	phys_active = timer->irq.level ||
+			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
 
 	/*
 	 * We want to avoid hitting the (re)distributor as much as
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 81c557c..2fd43a6 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1102,18 +1102,18 @@ static bool dist_active_irq(struct kvm_vcpu *vcpu)
 	return test_bit(vcpu->vcpu_id, dist->irq_active_on_cpu);
 }
 
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map)
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	int i;
 
 	for (i = 0; i < vcpu->arch.vgic_cpu.nr_lr; i++) {
 		struct vgic_lr vlr = vgic_get_lr(vcpu, i);
 
-		if (vlr.irq == map->virt_irq && vlr.state & LR_STATE_ACTIVE)
+		if (vlr.irq == virt_irq && vlr.state & LR_STATE_ACTIVE)
 			return true;
 	}
 
-	return vgic_irq_is_active(vcpu, map->virt_irq);
+	return vgic_irq_is_active(vcpu, virt_irq);
 }
 
 /*
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:39 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:39 +0100
Subject: [PATCH v5 00/57] KVM: arm/arm64: Rework virtual GIC emulation
Message-ID: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>

Hi,

hopefully the final version of the new VGIC series.
Again mostly smaller fixes: A new patch (8/57) to establish the
arch timer <-> VGIC connection later in the init process, to avoid
calls to VGIC code before the VGIC is actually initialized.
Also we now make sure that no VCPU is running while userland accesses
the VGIC registers. The set-active-bit code has been slightly adjusted
to cover a corner case as well. Last, but not least we now properly
annotate our lock nesting so the kernel is happy now even with
CONFIG_SPINLOCK_DEBUG enabled.
More detailed changelog in the patches.

As this new VGIC emulation will probably become the default very shortly,
please test it full steam on whatever setup you have access to.
Any reports are warmly welcome.

As v4, this series is based on kvmarm/next, which will be merged
shortly into Linus' kernel.
A git tree containing this series can be found on linux-arm.org:

git://linux-arm.org/linux-ap.git	branch: vgic-new/v5
http://www.linux-arm.org/git?p=linux-ap.git;a=log;h=refs/heads/vgic-new/v5

Cheers,
Andre.

===========================
This series is a joint effort to re-implement KVM's GIC emulation.
Many patches as in here have been effectively authored by multiple
people and authorship isn't clear in every case, especially since
many of the patches have been stashed together or split apart in
the process. So take the Author: tag with a grain of salt.

While the current VGIC implementation is centered around providing
efficient MMIO emulation, the hot path for most guests is actually
the guest entry and exit, which currently is rather costly.
Also the existing emulation has a global distributor lock, which
quickly becomes a bottleneck once the number of VCPUs increases.
Additionally the emulation was originally designed for GICv2, adding
GICv3 ITS emulation support to this proved to be rather painful.
Last, but not least the existing code became less and less
maintainable, with many special cases handled explicitly.

The new implementation is build around a struct vgic_irq data
structure, which holds all information about a virtual interrupt.
Interruts which should be injected are held in a per-VCPU list, this
make the entry/exit path much more efficient. Also the new structure
allows to have more fine grained locking - per IRQ and per VCPU -
getting rid of the global distributor lock.
As a result of the new design ITS emulation fits in more nicely, the
respective code will be provided as a follow-up series.

This series implements the same feature set as the existing emulation,
as a goodie we now implement priorities correctly.
To allow an easy transition with good test coverage, but still maintain
stability, both implementations live side by side, selectable via a
Kconfig option. The default is the new implementation.
If this code proves to be reliable, we will later remove the current
implementation with an extra patch set.

Please have a look at the series, review it and give the code some
serious testing (and possibly debugging). All feedback is appreciated.

Cheers,
Andre.

Andre Przywara (29):
  KVM: arm/arm64: vgic: streamline vgic_update_irq_pending() interface
  KVM: arm/arm64: vgic: avoid map in kvm_vgic_inject_mapped_irq()
  KVM: arm/arm64: vgic: avoid map in kvm_vgic_map_is_active()
  KVM: arm/arm64: vgic: avoid map in kvm_vgic_unmap_phys_irq()
  KVM: arm/arm64: arch_timer: Remove irq_phys_map
  KVM: arm/arm64: vgic: Remove irq_phys_map from interface
  KVM: arm/arm64: pmu: abstract access to number of SPIs
  KVM: arm/arm64: move GICv2 emulation defines into arm-gic-v3.h
  KVM: arm/arm64: vgic-new: Add GICv2 MMIO handling framework
  KVM: arm/arm64: vgic-new: Add ENABLE registers handlers
  KVM: arm/arm64: vgic-new: Add PENDING registers handlers
  KVM: arm/arm64: vgic-new: Add ACTIVE registers handlers
  KVM: arm/arm64: vgic-new: Add PRIORITY registers handlers
  KVM: arm/arm64: vgic-new: Add CONFIG registers handlers
  KVM: arm/arm64: vgic-new: Add TARGET registers handlers
  KVM: arm/arm64: vgic-new: Add SGIR register handler
  KVM: arm/arm64: vgic-new: Add SGIPENDR register handlers
  KVM: arm/arm64: vgic-new: Add GICv3 MMIO handling framework
  KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR, TYPER handlers
  KVM: arm/arm64: vgic-new: Add GICv3 redistributor IIDR and TYPER handler
  KVM: arm/arm64: vgic-new: Add GICv3 IDREGS register handler
  KVM: arm/arm64: vgic-new: Add GICv3 IROUTER register handlers
  KVM: arm/arm64: vgic-new: Add GICv3 SGI system register trap handler
  KVM: arm/arm64: vgic-new: Add userland access to VGIC dist registers
  KVM: arm/arm64: vgic-new: Add GICH_VMCR accessors
  KVM: arm/arm64: vgic-new: Add userland GIC CPU interface access
  KVM: arm/arm64: vgic-new: Wire up irqfd injection
  KVM: arm/arm64: vgic-new: implement mapped IRQ handling
  KVM: arm/arm64: vgic-new: enable build

Christoffer Dall (11):
  KVM: arm/arm64: Remove the IRQ field from struct irq_phys_map
  KVM: arm/arm64: Move timer IRQ map to latest possible time
  KVM: arm/arm64: Get rid of vgic_cpu->nr_lr
  KVM: arm/arm64: Fix MMIO emulation data handling
  KVM: arm/arm64: Export mmio_read/write_bus
  KVM: arm/arm64: Provide functionality to pause and resume a guest
  KVM: arm/arm64: vgic-new: Add data structure definitions
  KVM: arm/arm64: vgic-new: Add acccessor to new struct vgic_irq instance
  KVM: arm/arm64: vgic-new: Implement virtual IRQ injection
  KVM: arm/arm64: vgic-new: Add IRQ sorting
  KVM: arm/arm64: vgic-new: Export register access interface

Eric Auger (12):
  KVM: arm/arm64: vgic-new: Implement kvm_vgic_vcpu_pending_irq
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM device ops registration
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_NR_IRQS
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_CTRL
  KVM: arm/arm64: vgic-new: vgic_kvm_device: implement kvm_vgic_addr
  KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_ADDR
  KVM: arm/arm64: vgic-new: vgic_kvm_device: access to VGIC registers
  KVM: arm/arm64: vgic-new: vgic_init: implement kvm_vgic_hyp_init
  KVM: arm/arm64: vgic-new: vgic_init: implement vgic_create
  KVM: arm/arm64: vgic-new: vgic_init: implement vgic_init
  KVM: arm/arm64: vgic-new: vgic_init: implement map_resources
  KVM: arm/arm64: vgic-new: Add vgic_v2/v3_enable

Marc Zyngier (5):
  KVM: arm/arm64: vgic-new: Add IRQ sync/flush framework
  KVM: arm/arm64: vgic-new: Add GICv2 world switch backend
  KVM: arm/arm64: vgic-new: Add GICv3 world switch backend
  KVM: arm/arm64: vgic-new: Add MMIO handling framework
  KVM: arm/arm64: vgic-new: Add CTLR, TYPER and IIDR handlers

 arch/arm/include/asm/kvm_host.h     |   4 +
 arch/arm/include/asm/kvm_mmio.h     |   3 +
 arch/arm/kvm/Kconfig                |   7 +
 arch/arm/kvm/Makefile               |  11 +
 arch/arm/kvm/arm.c                  |  31 +-
 arch/arm/kvm/mmio.c                 |  24 +-
 arch/arm64/include/asm/kvm_host.h   |   4 +
 arch/arm64/include/asm/kvm_mmio.h   |   3 +
 arch/arm64/kvm/Kconfig              |   7 +
 arch/arm64/kvm/Makefile             |  12 +
 include/kvm/arm_arch_timer.h        |  11 +-
 include/kvm/arm_vgic.h              |  20 +-
 include/kvm/vgic/vgic.h             | 246 ++++++++++++++
 include/linux/irqchip/arm-gic-v3.h  |   6 +
 include/linux/irqchip/arm-gic.h     |   2 +
 virt/kvm/arm/arch_timer.c           |  68 ++--
 virt/kvm/arm/hyp/timer-sr.c         |   5 +-
 virt/kvm/arm/hyp/vgic-v2-sr.c       |  17 +-
 virt/kvm/arm/pmu.c                  |  25 +-
 virt/kvm/arm/vgic-v2.c              |   4 +-
 virt/kvm/arm/vgic-v3.c              |   8 +-
 virt/kvm/arm/vgic.c                 |  86 ++---
 virt/kvm/arm/vgic/vgic-init.c       | 452 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-irqfd.c      |  52 +++
 virt/kvm/arm/vgic/vgic-kvm-device.c | 431 +++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 446 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio-v3.c    | 455 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c       | 499 +++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h       | 150 +++++++++
 virt/kvm/arm/vgic/vgic-v2.c         | 352 ++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c         | 330 +++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c            | 619 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            | 131 ++++++++
 33 files changed, 4366 insertions(+), 155 deletions(-)
 create mode 100644 include/kvm/vgic/vgic.h
 create mode 100644 virt/kvm/arm/vgic/vgic-init.c
 create mode 100644 virt/kvm/arm/vgic/vgic-irqfd.c
 create mode 100644 virt/kvm/arm/vgic/vgic-kvm-device.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v2.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h
 create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
 create mode 100644 virt/kvm/arm/vgic/vgic-v3.c
 create mode 100644 virt/kvm/arm/vgic/vgic.c
 create mode 100644 virt/kvm/arm/vgic/vgic.h

-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:41 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:41 +0100
Subject: [PATCH v5 02/57] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_inject_mapped_irq()
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-3-git-send-email-andre.przywara@arm.com>

When we want to inject a hardware mapped IRQ into a guest, we actually
only need the virtual IRQ number from the irq_phys_map.
So let's pass this number directly from the arch timer to the VGIC
to avoid using the map as a parameter.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 include/kvm/arm_vgic.h    | 2 +-
 virt/kvm/arm/arch_timer.c | 2 +-
 virt/kvm/arm/vgic.c       | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index be6037a..e22f015 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -342,7 +342,7 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 			bool level);
 int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
-			       struct irq_phys_map *map, bool level);
+			       unsigned int virt_irq, bool level);
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 409db33..a9c6c1c 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -177,7 +177,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
 				   timer->irq.level);
 	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->map,
+					 timer->map->virt_irq,
 					 timer->irq.level);
 	WARN_ON(ret);
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index f6c6172..81c557c 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1666,7 +1666,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
  * kvm_vgic_inject_mapped_irq - Inject a physically mapped IRQ to the vgic
  * @kvm:     The VM structure pointer
  * @cpuid:   The CPU for PPIs
- * @map:     Pointer to a irq_phys_map structure describing the mapping
+ * @virt_irq: The virtual IRQ to be injected
  * @level:   Edge-triggered:  true:  to trigger the interrupt
  *			      false: to ignore the call
  *	     Level-sensitive  true:  raise the input signal
@@ -1677,7 +1677,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
  * being HIGH and 0 being LOW and all devices being active-HIGH.
  */
 int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
-			       struct irq_phys_map *map, bool level)
+			       unsigned int virt_irq, bool level)
 {
 	int ret;
 
@@ -1685,7 +1685,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 	if (ret)
 		return ret;
 
-	return vgic_update_irq_pending(kvm, cpuid, map->virt_irq, level);
+	return vgic_update_irq_pending(kvm, cpuid, virt_irq, level);
 }
 
 static irqreturn_t vgic_maintenance_handler(int irq, void *data)
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:51 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:51 +0100
Subject: [PATCH v5 12/57] KVM: arm/arm64: pmu: abstract access to number of
 SPIs
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-13-git-send-email-andre.przywara@arm.com>

Currently the PMU uses a member of the struct vgic_dist directly,
which not only breaks abstraction, but will fail with the new VGIC.
Abstract this access in the VGIC header file and refactor the validity
check in the PMU code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v3 .. v4:
- fix logic to allow PPIs again
- refactor IRQ validity check

 include/kvm/arm_vgic.h |  2 ++
 virt/kvm/arm/pmu.c     | 25 ++++++++++++++-----------
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 67a6637..ade7005 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -348,6 +348,8 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
 #define vgic_ready(k)		((k)->arch.vgic.ready)
+#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
+				 ((i) < (k)->arch.vgic.nr_irqs))
 
 int vgic_v2_probe(const struct gic_kvm_info *gic_kvm_info,
 		  const struct vgic_ops **ops,
diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
index 575c7aa..a027569 100644
--- a/virt/kvm/arm/pmu.c
+++ b/virt/kvm/arm/pmu.c
@@ -436,7 +436,14 @@ static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
-static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
+#define irq_is_ppi(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS)
+
+/*
+ * For one VM the interrupt type must be same for each vcpu.
+ * As a PPI, the interrupt number is the same for all vcpus,
+ * while as an SPI it must be a separate number per vcpu.
+ */
+static bool pmu_irq_is_valid(struct kvm *kvm, int irq)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
@@ -445,7 +452,7 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
 		if (!kvm_arm_pmu_irq_initialized(vcpu))
 			continue;
 
-		if (is_ppi) {
+		if (irq_is_ppi(irq)) {
 			if (vcpu->arch.pmu.irq_num != irq)
 				return false;
 		} else {
@@ -457,7 +464,6 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
 	return true;
 }
 
-
 int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 {
 	switch (attr->attr) {
@@ -471,14 +477,11 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 		if (get_user(irq, uaddr))
 			return -EFAULT;
 
-		/*
-		 * The PMU overflow interrupt could be a PPI or SPI, but for one
-		 * VM the interrupt type must be same for each vcpu. As a PPI,
-		 * the interrupt number is the same for all vcpus, while as an
-		 * SPI it must be a separate number per vcpu.
-		 */
-		if (irq < VGIC_NR_SGIS || irq >= vcpu->kvm->arch.vgic.nr_irqs ||
-		    !irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
+		/* The PMU overflow interrupt can be a PPI or a valid SPI. */
+		if (!(irq_is_ppi(irq) || vgic_valid_spi(vcpu->kvm, irq)))
+			return -EINVAL;
+
+		if (!pmu_irq_is_valid(vcpu->kvm, irq))
 			return -EINVAL;
 
 		if (kvm_arm_pmu_irq_initialized(vcpu))
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:49 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:49 +0100
Subject: [PATCH v5 10/57] KVM: arm/arm64: Fix MMIO emulation data handling
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-11-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

When the kernel was handling a guest MMIO read access internally, we
need to copy the emulation result into the run->mmio structure in order
for the kvm_handle_mmio_return() function to pick it up and inject the
	result back into the guest.

Currently the only user of kvm_io_bus for ARM is the VGIC, which did
this copying itself, so this was not causing issues so far.

But with the upcoming new vgic implementation we need this done
properly.

Update the kvm_handle_mmio_return description and cleanup the code to
only perform a single copying when needed.

Code and commit message inspired by Andre Przywara.

Reported-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/kvm/mmio.c | 14 +++++++-------
 virt/kvm/arm/vgic.c |  7 -------
 2 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 0f6600f..0158e9e 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -87,11 +87,10 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len)
 
 /**
  * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation
+ *			     or in-kernel IO emulation
+ *
  * @vcpu: The VCPU pointer
  * @run:  The VCPU run struct containing the mmio data
- *
- * This should only be called after returning from userspace for MMIO load
- * emulation.
  */
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
@@ -206,18 +205,19 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 	run->mmio.is_write	= is_write;
 	run->mmio.phys_addr	= fault_ipa;
 	run->mmio.len		= len;
-	if (is_write)
-		memcpy(run->mmio.data, data_buf, len);
 
 	if (!ret) {
 		/* We handled the access successfully in the kernel. */
+		if (!is_write)
+			memcpy(run->mmio.data, data_buf, len);
 		vcpu->stat.mmio_exit_kernel++;
 		kvm_handle_mmio_return(vcpu, run);
 		return 1;
-	} else {
-		vcpu->stat.mmio_exit_user++;
 	}
 
+	if (is_write)
+		memcpy(run->mmio.data, data_buf, len);
+	vcpu->stat.mmio_exit_user++;
 	run->exit_reason	= KVM_EXIT_MMIO;
 	return 0;
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index f76bb64..c3bfbb9 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -819,7 +819,6 @@ static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct vgic_io_device *iodev = container_of(this,
 						    struct vgic_io_device, dev);
-	struct kvm_run *run = vcpu->run;
 	const struct vgic_io_range *range;
 	struct kvm_exit_mmio mmio;
 	bool updated_state;
@@ -848,12 +847,6 @@ static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
 		updated_state = false;
 	}
 	spin_unlock(&dist->lock);
-	run->mmio.is_write	= is_write;
-	run->mmio.len		= len;
-	run->mmio.phys_addr	= addr;
-	memcpy(run->mmio.data, val, len);
-
-	kvm_handle_mmio_return(vcpu, run);
 
 	if (updated_state)
 		vgic_kick_vcpus(vcpu->kvm);
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:45 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:45 +0100
Subject: [PATCH v5 06/57] KVM: arm/arm64: arch_timer: Remove irq_phys_map
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-7-git-send-email-andre.przywara@arm.com>

Now that the interface between the arch timer and the VGIC does not
require passing the irq_phys_map entry pointer anymore, let's remove
it from the virtual arch timer and use the virtual IRQ number instead
directly.
The remaining pointer returned by kvm_vgic_map_phys_irq() will be
removed in the following patch.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- remove extra virt_irq member from struct, instead use irq.irq directly

Changelog v2 .. v3:
- remove bogus validity check from kvm_vgic_unmap_phys_irq()

 include/kvm/arm_arch_timer.h |  3 ---
 virt/kvm/arm/arch_timer.c    | 10 ++++------
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index b651aed..a47b7de 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -53,9 +53,6 @@ struct arch_timer_cpu {
 	/* Timer IRQ */
 	struct kvm_irq_level		irq;
 
-	/* VGIC mapping */
-	struct irq_phys_map		*map;
-
 	/* Active IRQ state caching */
 	bool				active_cleared_last;
 };
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index e45895a..458d4d8 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -175,10 +175,10 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 
 	timer->active_cleared_last = false;
 	timer->irq.level = new_level;
-	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
+	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
 				   timer->irq.level);
 	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->map->virt_irq,
+					 timer->irq.irq,
 					 timer->irq.level);
 	WARN_ON(ret);
 }
@@ -276,7 +276,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* exit.
 	*/
 	phys_active = timer->irq.level ||
-			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
+			kvm_vgic_map_is_active(vcpu, timer->irq.irq);
 
 	/*
 	 * We want to avoid hitting the (re)distributor as much as
@@ -378,7 +378,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	if (WARN_ON(IS_ERR(map)))
 		return PTR_ERR(map);
 
-	timer->map = map;
 	return 0;
 }
 
@@ -504,8 +503,7 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 
 	timer_disarm(timer);
-	if (timer->map)
-		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
+	kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq);
 }
 
 void kvm_timer_enable(struct kvm *kvm)
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:46 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:46 +0100
Subject: [PATCH v5 07/57] KVM: arm/arm64: vgic: Remove irq_phys_map from
 interface
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-8-git-send-email-andre.przywara@arm.com>

Now that the virtual arch timer does not care about the irq_phys_map
anymore, let's rework kvm_vgic_map_phys_irq() to return an error
value instead. Any reference to that mapping can later be done by
passing the correct combination of VCPU and virtual IRQ number.
This makes the irq_phys_map handling completely private to the
VGIC code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- adaptations to changes in previous patches (removal of virt_irq)

Changelog v2 .. v3:
- simplify return in kvm_timer_vcpu_reset()

 include/kvm/arm_vgic.h    |  3 +--
 virt/kvm/arm/arch_timer.c |  7 +------
 virt/kvm/arm/vgic.c       | 15 +++++++--------
 3 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 9ad7625..3e17fb4 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -344,8 +344,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 			       unsigned int virt_irq, bool level);
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
-struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int phys_irq);
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, int virt_irq, int phys_irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 458d4d8..3232105 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -333,7 +333,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 			 const struct kvm_irq_level *irq)
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-	struct irq_phys_map *map;
 	struct irq_desc *desc;
 	struct irq_data *data;
 	int phys_irq;
@@ -374,11 +373,7 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	 * Tell the VGIC that the virtual interrupt is tied to a
 	 * physical interrupt. We do that once per VCPU.
 	 */
-	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
-	if (WARN_ON(IS_ERR(map)))
-		return PTR_ERR(map);
-
-	return 0;
+	return kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
 }
 
 void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index a7e496a..91d42a8 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1719,21 +1719,20 @@ static struct list_head *vgic_get_irq_phys_map_list(struct kvm_vcpu *vcpu,
  * the physical interrupt represented by @phys_irq. This mapping can be
  * established multiple times as long as the parameters are the same.
  *
- * Returns a valid pointer on success, and an error pointer otherwise
+ * Returns 0 on success or an error value otherwise.
  */
-struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int phys_irq)
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, int virt_irq, int phys_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct list_head *root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 	struct irq_phys_map *map;
 	struct irq_phys_map_entry *entry;
-
+	int ret = 0;
 
 	/* Create a new mapping */
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	spin_lock(&dist->irq_phys_map_lock);
 
@@ -1742,7 +1741,7 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	if (map) {
 		/* Make sure this mapping matches */
 		if (map->phys_irq != phys_irq)
-			map = ERR_PTR(-EINVAL);
+			ret = -EINVAL;
 
 		/* Found an existing, valid mapping */
 		goto out;
@@ -1758,9 +1757,9 @@ out:
 	spin_unlock(&dist->irq_phys_map_lock);
 	/* If we've found a hit in the existing list, free the useless
 	 * entry */
-	if (IS_ERR(map) || map != &entry->map)
+	if (ret || map != &entry->map)
 		kfree(entry);
-	return map;
+	return ret;
 }
 
 static struct irq_phys_map *vgic_irq_map_search(struct kvm_vcpu *vcpu,
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:48 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:48 +0100
Subject: [PATCH v5 09/57] KVM: arm/arm64: Get rid of vgic_cpu->nr_lr
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-10-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

The number of list registers is a property of the underlying system, not
of emulated VGIC CPU interface.

As we are about to move this variable to global state in the new vgic
for clarity, move it from the legacy implementation as well to make the
merge of the new code easier.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Andre Przywara <andre.przywara at arm.com>
---
 include/kvm/arm_vgic.h        |  3 ---
 virt/kvm/arm/hyp/vgic-v2-sr.c | 12 +++++++-----
 virt/kvm/arm/vgic-v2.c        |  4 +++-
 virt/kvm/arm/vgic.c           | 12 ++----------
 4 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 3e17fb4..67a6637 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -304,9 +304,6 @@ struct vgic_cpu {
 	unsigned long   *active_shared;
 	unsigned long   *pend_act_shared;
 
-	/* Number of list registers on this CPU */
-	int		nr_lr;
-
 	/* CPU vif control registers for world switch */
 	union {
 		struct vgic_v2_cpu_if	vgic_v2;
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index 674bdf8..caac41f 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -21,11 +21,13 @@
 
 #include <asm/kvm_hyp.h>
 
+extern struct vgic_params vgic_v2_params;
+
 static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 					    void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	u32 eisr0, eisr1;
 	int i;
 	bool expect_mi;
@@ -67,7 +69,7 @@ static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	u32 elrsr0, elrsr1;
 
 	elrsr0 = readl_relaxed(base + GICH_ELRSR0);
@@ -86,7 +88,7 @@ static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
 static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	int i;
 
 	for (i = 0; i < nr_lr; i++) {
@@ -141,13 +143,13 @@ void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
 	struct vgic_dist *vgic = &kvm->arch.vgic;
 	void __iomem *base = kern_hyp_va(vgic->vctrl_base);
-	int i, nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
+	int i;
 	u64 live_lrs = 0;
 
 	if (!base)
 		return;
 
-	nr_lr = vcpu->arch.vgic_cpu.nr_lr;
 
 	for (i = 0; i < nr_lr; i++)
 		if (cpu_if->vgic_lr[i] & GICH_LR_STATE)
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
index 7e826c9..334cd7a 100644
--- a/virt/kvm/arm/vgic-v2.c
+++ b/virt/kvm/arm/vgic-v2.c
@@ -171,7 +171,7 @@ static const struct vgic_ops vgic_v2_ops = {
 	.enable			= vgic_v2_enable,
 };
 
-static struct vgic_params vgic_v2_params;
+struct vgic_params __section(.hyp.text) vgic_v2_params;
 
 static void vgic_cpu_init_lrs(void *params)
 {
@@ -201,6 +201,8 @@ int vgic_v2_probe(const struct gic_kvm_info *gic_kvm_info,
 	const struct resource *vctrl_res = &gic_kvm_info->vctrl;
 	const struct resource *vcpu_res = &gic_kvm_info->vcpu;
 
+	memset(vgic, 0, sizeof(*vgic));
+
 	if (!gic_kvm_info->maint_irq) {
 		kvm_err("error getting vgic maintenance irq\n");
 		ret = -ENXIO;
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 91d42a8..f76bb64 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -690,12 +690,11 @@ bool vgic_handle_cfg_reg(u32 *reg, struct kvm_exit_mmio *mmio,
  */
 void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
 {
-	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
 	u64 elrsr = vgic_get_elrsr(vcpu);
 	unsigned long *elrsr_ptr = u64_to_bitmask(&elrsr);
 	int i;
 
-	for_each_clear_bit(i, elrsr_ptr, vgic_cpu->nr_lr) {
+	for_each_clear_bit(i, elrsr_ptr, vgic->nr_lr) {
 		struct vgic_lr lr = vgic_get_lr(vcpu, i);
 
 		/*
@@ -1106,7 +1105,7 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	int i;
 
-	for (i = 0; i < vcpu->arch.vgic_cpu.nr_lr; i++) {
+	for (i = 0; i < vgic->nr_lr; i++) {
 		struct vgic_lr vlr = vgic_get_lr(vcpu, i);
 
 		if (vlr.irq == virt_irq && vlr.state & LR_STATE_ACTIVE)
@@ -1866,13 +1865,6 @@ static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
 		return -ENOMEM;
 	}
 
-	/*
-	 * Store the number of LRs per vcpu, so we don't have to go
-	 * all the way to the distributor structure to find out. Only
-	 * assembly code should use this one.
-	 */
-	vgic_cpu->nr_lr = vgic->nr_lr;
-
 	return 0;
 }
 
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:43 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:43 +0100
Subject: [PATCH v5 04/57] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_unmap_phys_irq()
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-5-git-send-email-andre.przywara@arm.com>

kvm_vgic_unmap_phys_irq() only needs the virtual IRQ number, so let's
just pass that between the arch timer and the VGIC to get rid of
the irq_phys_map pointer.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 include/kvm/arm_vgic.h    |  2 +-
 virt/kvm/arm/arch_timer.c |  2 +-
 virt/kvm/arm/vgic.c       | 11 ++++-------
 3 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 9830232..c7bb184 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -347,7 +347,7 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 					   int virt_irq, int irq);
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 37f82c1..962b442 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -486,7 +486,7 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 
 	timer_disarm(timer);
 	if (timer->map)
-		kvm_vgic_unmap_phys_irq(vcpu, timer->map);
+		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
 }
 
 void kvm_timer_enable(struct kvm *kvm)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 2fd43a6..06abd59 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1812,25 +1812,22 @@ static void vgic_free_phys_irq_map_rcu(struct rcu_head *rcu)
 /**
  * kvm_vgic_unmap_phys_irq - Remove a virtual to physical IRQ mapping
  * @vcpu: The VCPU pointer
- * @map: The pointer to a mapping obtained through kvm_vgic_map_phys_irq
+ * @virt_irq: The virtual IRQ number to be unmapped
  *
  * Remove an existing mapping between virtual and physical interrupts.
  */
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map)
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct irq_phys_map_entry *entry;
 	struct list_head *root;
 
-	if (!map)
-		return -EINVAL;
-
-	root = vgic_get_irq_phys_map_list(vcpu, map->virt_irq);
+	root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 
 	spin_lock(&dist->irq_phys_map_lock);
 
 	list_for_each_entry(entry, root, entry) {
-		if (&entry->map == map) {
+		if (entry->map.virt_irq == virt_irq) {
 			list_del_rcu(&entry->entry);
 			call_rcu(&entry->rcu, vgic_free_phys_irq_map_rcu);
 			break;
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:50 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:50 +0100
Subject: [PATCH v5 11/57] KVM: arm/arm64: Export mmio_read/write_bus
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-12-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Rename mmio_{read,write}_bus to kvm_mmio_{read,write}_bus and export
them out of mmio.c.
This will be needed later for the new VGIC implementation.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/include/asm/kvm_mmio.h   |  3 +++
 arch/arm/kvm/mmio.c               | 10 +++++-----
 arch/arm64/include/asm/kvm_mmio.h |  3 +++
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmio.h b/arch/arm/include/asm/kvm_mmio.h
index d8e90c8..f3a7de7 100644
--- a/arch/arm/include/asm/kvm_mmio.h
+++ b/arch/arm/include/asm/kvm_mmio.h
@@ -28,6 +28,9 @@ struct kvm_decode {
 	bool sign_extend;
 };
 
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
+
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		 phys_addr_t fault_ipa);
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 0158e9e..10f80a6 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -23,7 +23,7 @@
 
 #include "trace.h"
 
-static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data)
 {
 	void *datap = NULL;
 	union {
@@ -55,7 +55,7 @@ static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
 	memcpy(buf, datap, len);
 }
 
-static unsigned long mmio_read_buf(char *buf, unsigned int len)
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len)
 {
 	unsigned long data = 0;
 	union {
@@ -66,7 +66,7 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len)
 
 	switch (len) {
 	case 1:
-		data = buf[0];
+		data = *(u8 *)buf;
 		break;
 	case 2:
 		memcpy(&tmp.hword, buf, len);
@@ -103,7 +103,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		if (len > sizeof(unsigned long))
 			return -EINVAL;
 
-		data = mmio_read_buf(run->mmio.data, len);
+		data = kvm_mmio_read_buf(run->mmio.data, len);
 
 		if (vcpu->arch.mmio_decode.sign_extend &&
 		    len < sizeof(unsigned long)) {
@@ -189,7 +189,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 					       len);
 
 		trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data);
-		mmio_write_buf(data_buf, len, data);
+		kvm_mmio_write_buf(data_buf, len, data);
 
 		ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
 				       data_buf);
diff --git a/arch/arm64/include/asm/kvm_mmio.h b/arch/arm64/include/asm/kvm_mmio.h
index fe612a9..75ea420 100644
--- a/arch/arm64/include/asm/kvm_mmio.h
+++ b/arch/arm64/include/asm/kvm_mmio.h
@@ -30,6 +30,9 @@ struct kvm_decode {
 	bool sign_extend;
 };
 
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
+
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		 phys_addr_t fault_ipa);
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:44 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:44 +0100
Subject: [PATCH v5 05/57] KVM: arm/arm64: Remove the IRQ field from struct
 irq_phys_map
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-6-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

The communication of a Linux IRQ number from outside the VGIC to the
vgic was a leftover from the day when the vgic code cared about how a
particular device injects virtual interrupts mapped to a physical
interrupt.

We can safely remove this notion, leaving all physical IRQ handling to
be done in the device driver (the arch timer in this case), which makes
room for a saner API for the new VGIC.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog v1 .. v2:
- update kerneldoc comments on kvm_vgic_map_phys_irq()

Changelog v2 .. v3:
- include <linux/irq.h>

 include/kvm/arm_vgic.h    |  3 +--
 virt/kvm/arm/arch_timer.c | 23 +++++++++++++++++++++--
 virt/kvm/arm/vgic.c       | 28 ++++++----------------------
 3 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index c7bb184..9ad7625 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -158,7 +158,6 @@ struct vgic_io_device {
 struct irq_phys_map {
 	u32			virt_irq;
 	u32			phys_irq;
-	u32			irq;
 };
 
 struct irq_phys_map_entry {
@@ -346,7 +345,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int irq);
+					   int virt_irq, int phys_irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 962b442..e45895a 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -20,6 +20,7 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <clocksource/arm_arch_timer.h>
 #include <asm/arch_timer.h>
@@ -300,7 +301,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	if (timer->active_cleared_last && !phys_active)
 		return;
 
-	ret = irq_set_irqchip_state(timer->map->irq,
+	ret = irq_set_irqchip_state(host_vtimer_irq,
 				    IRQCHIP_STATE_ACTIVE,
 				    phys_active);
 	WARN_ON(ret);
@@ -333,6 +334,9 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 	struct irq_phys_map *map;
+	struct irq_desc *desc;
+	struct irq_data *data;
+	int phys_irq;
 
 	/*
 	 * The vcpu timer irq number cannot be determined in
@@ -352,10 +356,25 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	kvm_timer_update_state(vcpu);
 
 	/*
+	 * Find the physical IRQ number corresponding to the host_vtimer_irq
+	 */
+	desc = irq_to_desc(host_vtimer_irq);
+	if (!desc) {
+		kvm_err("%s: no interrupt descriptor\n", __func__);
+		return -EINVAL;
+	}
+
+	data = irq_desc_get_irq_data(desc);
+	while (data->parent_data)
+		data = data->parent_data;
+
+	phys_irq = data->hwirq;
+
+	/*
 	 * Tell the VGIC that the virtual interrupt is tied to a
 	 * physical interrupt. We do that once per VCPU.
 	 */
-	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, host_vtimer_irq);
+	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
 	if (WARN_ON(IS_ERR(map)))
 		return PTR_ERR(map);
 
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 06abd59..a7e496a 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1711,38 +1711,24 @@ static struct list_head *vgic_get_irq_phys_map_list(struct kvm_vcpu *vcpu,
 /**
  * kvm_vgic_map_phys_irq - map a virtual IRQ to a physical IRQ
  * @vcpu: The VCPU pointer
- * @virt_irq: The virtual irq number
- * @irq: The Linux IRQ number
+ * @virt_irq: The virtual IRQ number for the guest
+ * @phys_irq: The hardware IRQ number of the host
  *
  * Establish a mapping between a guest visible irq (@virt_irq) and a
- * Linux irq (@irq). On injection, @virt_irq will be associated with
- * the physical interrupt represented by @irq. This mapping can be
+ * hardware irq (@phys_irq). On injection, @virt_irq will be associated with
+ * the physical interrupt represented by @phys_irq. This mapping can be
  * established multiple times as long as the parameters are the same.
  *
  * Returns a valid pointer on success, and an error pointer otherwise
  */
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int irq)
+					   int virt_irq, int phys_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct list_head *root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 	struct irq_phys_map *map;
 	struct irq_phys_map_entry *entry;
-	struct irq_desc *desc;
-	struct irq_data *data;
-	int phys_irq;
 
-	desc = irq_to_desc(irq);
-	if (!desc) {
-		kvm_err("%s: no interrupt descriptor\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
-
-	data = irq_desc_get_irq_data(desc);
-	while (data->parent_data)
-		data = data->parent_data;
-
-	phys_irq = data->hwirq;
 
 	/* Create a new mapping */
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
@@ -1755,8 +1741,7 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	map = vgic_irq_map_search(vcpu, virt_irq);
 	if (map) {
 		/* Make sure this mapping matches */
-		if (map->phys_irq != phys_irq	||
-		    map->irq      != irq)
+		if (map->phys_irq != phys_irq)
 			map = ERR_PTR(-EINVAL);
 
 		/* Found an existing, valid mapping */
@@ -1766,7 +1751,6 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	map           = &entry->map;
 	map->virt_irq = virt_irq;
 	map->phys_irq = phys_irq;
-	map->irq      = irq;
 
 	list_add_tail_rcu(&entry->entry, root);
 
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:47 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:47 +0100
Subject: [PATCH v5 08/57] KVM: arm/arm64: Move timer IRQ map to latest
 possible time
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-9-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

We are about to modify the VGIC to allocate all data structures
dynamically and store mapped IRQ information on a per-IRQ struct, which
is indeed allocated dynamically at init time.

Therefore, we cannot record the mapped IRQ info from the timer at timer
reset time like it's done now, because VCPU reset happens before timer
init.

A possible later time to do this is on the first run of a per VCPU, it
just requires us to move the enable state to be a per-VCPU state and do
the lookup of the physical IRQ number when we are about to run the VCPU.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/kvm/arm.c           |  6 ++--
 include/kvm/arm_arch_timer.h |  8 +++---
 virt/kvm/arm/arch_timer.c    | 66 +++++++++++++++++++++++++-------------------
 virt/kvm/arm/hyp/timer-sr.c  |  5 ++--
 4 files changed, 47 insertions(+), 38 deletions(-)

diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index be4b639..ceb9345 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -459,7 +459,7 @@ static void update_vttbr(struct kvm *kvm)
 static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
-	int ret;
+	int ret = 0;
 
 	if (likely(vcpu->arch.has_run_once))
 		return 0;
@@ -482,9 +482,9 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 	 * interrupts from the virtual timer with a userspace gic.
 	 */
 	if (irqchip_in_kernel(kvm) && vgic_initialized(kvm))
-		kvm_timer_enable(kvm);
+		ret = kvm_timer_enable(vcpu);
 
-	return 0;
+	return ret;
 }
 
 bool kvm_arch_intc_initialized(struct kvm *kvm)
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index a47b7de..dda39d8 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -24,9 +24,6 @@
 #include <linux/workqueue.h>
 
 struct arch_timer_kvm {
-	/* Is the timer enabled */
-	bool			enabled;
-
 	/* Virtual offset */
 	cycle_t			cntvoff;
 };
@@ -55,10 +52,13 @@ struct arch_timer_cpu {
 
 	/* Active IRQ state caching */
 	bool				active_cleared_last;
+
+	/* Is the timer enabled */
+	bool			enabled;
 };
 
 int kvm_timer_hyp_init(void);
-void kvm_timer_enable(struct kvm *kvm);
+int kvm_timer_enable(struct kvm_vcpu *vcpu);
 void kvm_timer_init(struct kvm *kvm);
 int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 			 const struct kvm_irq_level *irq);
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 3232105..e2d5b6f 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -197,7 +197,7 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
 	 * because the guest would never see the interrupt.  Instead wait
 	 * until we call this function from kvm_timer_flush_hwstate.
 	 */
-	if (!vgic_initialized(vcpu->kvm))
+	if (!vgic_initialized(vcpu->kvm) || !timer->enabled)
 		return -ENODEV;
 
 	if (kvm_timer_should_fire(vcpu) != timer->irq.level)
@@ -333,9 +333,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 			 const struct kvm_irq_level *irq)
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-	struct irq_desc *desc;
-	struct irq_data *data;
-	int phys_irq;
 
 	/*
 	 * The vcpu timer irq number cannot be determined in
@@ -354,26 +351,7 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	timer->cntv_ctl = 0;
 	kvm_timer_update_state(vcpu);
 
-	/*
-	 * Find the physical IRQ number corresponding to the host_vtimer_irq
-	 */
-	desc = irq_to_desc(host_vtimer_irq);
-	if (!desc) {
-		kvm_err("%s: no interrupt descriptor\n", __func__);
-		return -EINVAL;
-	}
-
-	data = irq_desc_get_irq_data(desc);
-	while (data->parent_data)
-		data = data->parent_data;
-
-	phys_irq = data->hwirq;
-
-	/*
-	 * Tell the VGIC that the virtual interrupt is tied to a
-	 * physical interrupt. We do that once per VCPU.
-	 */
-	return kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
+	return 0;
 }
 
 void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
@@ -501,10 +479,40 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 	kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq);
 }
 
-void kvm_timer_enable(struct kvm *kvm)
+int kvm_timer_enable(struct kvm_vcpu *vcpu)
 {
-	if (kvm->arch.timer.enabled)
-		return;
+	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+	struct irq_desc *desc;
+	struct irq_data *data;
+	int phys_irq;
+	int ret;
+
+	if (timer->enabled)
+		return 0;
+
+	/*
+	 * Find the physical IRQ number corresponding to the host_vtimer_irq
+	 */
+	desc = irq_to_desc(host_vtimer_irq);
+	if (!desc) {
+		kvm_err("%s: no interrupt descriptor\n", __func__);
+		return -EINVAL;
+	}
+
+	data = irq_desc_get_irq_data(desc);
+	while (data->parent_data)
+		data = data->parent_data;
+
+	phys_irq = data->hwirq;
+
+	/*
+	 * Tell the VGIC that the virtual interrupt is tied to a
+	 * physical interrupt. We do that once per VCPU.
+	 */
+	ret = kvm_vgic_map_phys_irq(vcpu, timer->irq.irq, phys_irq);
+	if (ret)
+		return ret;
+
 
 	/*
 	 * There is a potential race here between VCPUs starting for the first
@@ -515,7 +523,9 @@ void kvm_timer_enable(struct kvm *kvm)
 	 * the arch timers are enabled.
 	 */
 	if (timecounter && wqueue)
-		kvm->arch.timer.enabled = 1;
+		timer->enabled = 1;
+
+	return 0;
 }
 
 void kvm_timer_init(struct kvm *kvm)
diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c
index ea00d69..798866a 100644
--- a/virt/kvm/arm/hyp/timer-sr.c
+++ b/virt/kvm/arm/hyp/timer-sr.c
@@ -24,11 +24,10 @@
 /* vcpu is already in the HYP VA space */
 void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu)
 {
-	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 	u64 val;
 
-	if (kvm->arch.timer.enabled) {
+	if (timer->enabled) {
 		timer->cntv_ctl = read_sysreg_el0(cntv_ctl);
 		timer->cntv_cval = read_sysreg_el0(cntv_cval);
 	}
@@ -60,7 +59,7 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
 	val |= CNTHCTL_EL1PCTEN;
 	write_sysreg(val, cnthctl_el2);
 
-	if (kvm->arch.timer.enabled) {
+	if (timer->enabled) {
 		write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2);
 		write_sysreg_el0(timer->cntv_cval, cntv_cval);
 		isb();
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:56 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:56 +0100
Subject: [PATCH v5 17/57] KVM: arm/arm64: vgic-new: Implement virtual IRQ
 injection
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-18-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Provide a vgic_queue_irq_unlock() function which decides whether a
given IRQ needs to be queued to a VCPU's ap_list.
This should be called whenever an IRQ becomes pending or enabled,
either as a result of userspace injection, from in-kernel emulated
devices like the architected timer or from MMIO accesses to the
distributor emulation.
Also provides the necessary functions to allow userland to inject an
IRQ to a guest.
Since this is the first code that starts using our locking mechanism, we
add some (hopefully) clear documentation of our locking strategy and
requirements along with this patch.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- add spinlock checks protected by CONFIG_DEBUG_SPINLOCK
- add more comments to vgic_target_oracle
- remove BUG_ON() if IRQ is neither edge or level
- rename vgic_queue_irq() to vgic_queue_irq_unlock()
- simplify initial check in vgic_queue_irq_unlock()
- extend retry loop to ask the oracle again
- minor comment fixes

Changelog v1 .. v2:
- move most IRQ injection code into vgic_update_irq_pending()

Changelog v3 .. v4:
- simplify vgic_queue_irq_unlock() to allow reusage later

Changelog v4 .. v5:
- return target_vcpu if active, but not on a VCPU
- fix comments about retrying after mismatch

 include/kvm/vgic/vgic.h  |   3 +
 virt/kvm/arm/vgic/vgic.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h |   1 +
 3 files changed, 215 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 6ca0781..7b6ca90 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -181,6 +181,9 @@ struct vgic_cpu {
 	u64 live_lrs;
 };
 
+int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			bool level);
+
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(false)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index fb45537..ada1d02 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -19,8 +19,31 @@
 
 #include "vgic.h"
 
+#define CREATE_TRACE_POINTS
+#include "../trace.h"
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+#define DEBUG_SPINLOCK_BUG_ON(p) BUG_ON(p)
+#else
+#define DEBUG_SPINLOCK_BUG_ON(p)
+#endif
+
 struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
 
+/*
+ * Locking order is always:
+ *   vgic_cpu->ap_list_lock
+ *     vgic_irq->irq_lock
+ *
+ * (that is, always take the ap_list_lock before the struct vgic_irq lock).
+ *
+ * When taking more than one ap_list_lock at the same time, always take the
+ * lowest numbered VCPU's ap_list_lock first, so:
+ *   vcpuX->vcpu_id < vcpuY->vcpu_id:
+ *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
+ *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
+ */
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid)
 {
@@ -39,3 +62,191 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 	WARN(1, "Looking up struct vgic_irq for reserved INTID");
 	return NULL;
 }
+
+/**
+ * kvm_vgic_target_oracle - compute the target vcpu for an irq
+ *
+ * @irq:	The irq to route. Must be already locked.
+ *
+ * Based on the current state of the interrupt (enabled, pending,
+ * active, vcpu and target_vcpu), compute the next vcpu this should be
+ * given to. Return NULL if this shouldn't be injected at all.
+ *
+ * Requires the IRQ lock to be held.
+ */
+static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
+{
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+	/* If the interrupt is active, it must stay on the current vcpu */
+	if (irq->active)
+		return irq->vcpu ? : irq->target_vcpu;
+
+	/*
+	 * If the IRQ is not active but enabled and pending, we should direct
+	 * it to its configured target VCPU.
+	 * If the distributor is disabled, pending interrupts shouldn't be
+	 * forwarded.
+	 */
+	if (irq->enabled && irq->pending) {
+		if (unlikely(irq->target_vcpu &&
+			     !irq->target_vcpu->kvm->arch.vgic.enabled))
+			return NULL;
+
+		return irq->target_vcpu;
+	}
+
+	/* If neither active nor pending and enabled, then this IRQ should not
+	 * be queued to any VCPU.
+	 */
+	return NULL;
+}
+
+/*
+ * Only valid injection if changing level for level-triggered IRQs or for a
+ * rising edge.
+ */
+static bool vgic_validate_injection(struct vgic_irq *irq, bool level)
+{
+	switch (irq->config) {
+	case VGIC_CONFIG_LEVEL:
+		return irq->line_level != level;
+	case VGIC_CONFIG_EDGE:
+		return level;
+	}
+
+	return false;
+}
+
+/*
+ * Check whether an IRQ needs to (and can) be queued to a VCPU's ap list.
+ * Do the queuing if necessary, taking the right locks in the right order.
+ * Returns true when the IRQ was queued, false otherwise.
+ *
+ * Needs to be entered with the IRQ lock already held, but will return
+ * with all locks dropped.
+ */
+bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq)
+{
+	struct kvm_vcpu *vcpu;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+retry:
+	vcpu = vgic_target_oracle(irq);
+	if (irq->vcpu || !vcpu) {
+		/*
+		 * If this IRQ is already on a VCPU's ap_list, then it
+		 * cannot be moved or modified and there is no more work for
+		 * us to do.
+		 *
+		 * Otherwise, if the irq is not pending and enabled, it does
+		 * not need to be inserted into an ap_list and there is also
+		 * no more work for us to do.
+		 */
+		spin_unlock(&irq->irq_lock);
+		return false;
+	}
+
+	/*
+	 * We must unlock the irq lock to take the ap_list_lock where
+	 * we are going to insert this new pending interrupt.
+	 */
+	spin_unlock(&irq->irq_lock);
+
+	/* someone can do stuff here, which we re-check below */
+
+	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+	spin_lock(&irq->irq_lock);
+
+	/*
+	 * Did something change behind our backs?
+	 *
+	 * There are two cases:
+	 * 1) The irq lost its pending state or was disabled behind our
+	 *    backs and/or it was queued to another VCPU's ap_list.
+	 * 2) Someone changed the affinity on this irq behind our
+	 *    backs and we are now holding the wrong ap_list_lock.
+	 *
+	 * In both cases, drop the locks and retry.
+	 */
+
+	if (unlikely(irq->vcpu || vcpu != vgic_target_oracle(irq))) {
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+		spin_lock(&irq->irq_lock);
+		goto retry;
+	}
+
+	list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
+	irq->vcpu = vcpu;
+
+	spin_unlock(&irq->irq_lock);
+	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+	kvm_vcpu_kick(vcpu);
+
+	return true;
+}
+
+static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
+				   unsigned int intid, bool level,
+				   bool mapped_irq)
+{
+	struct kvm_vcpu *vcpu;
+	struct vgic_irq *irq;
+	int ret;
+
+	trace_vgic_update_irq_pending(cpuid, intid, level);
+
+	vcpu = kvm_get_vcpu(kvm, cpuid);
+	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
+		return -EINVAL;
+
+	irq = vgic_get_irq(kvm, vcpu, intid);
+	if (!irq)
+		return -EINVAL;
+
+	if (irq->hw != mapped_irq)
+		return -EINVAL;
+
+	spin_lock(&irq->irq_lock);
+
+	if (!vgic_validate_injection(irq, level)) {
+		/* Nothing to see here, move along... */
+		spin_unlock(&irq->irq_lock);
+		return 0;
+	}
+
+	if (irq->config == VGIC_CONFIG_LEVEL) {
+		irq->line_level = level;
+		irq->pending = level || irq->soft_pending;
+	} else {
+		irq->pending = true;
+	}
+
+	vgic_queue_irq_unlock(kvm, irq);
+
+	return 0;
+}
+
+/**
+ * kvm_vgic_inject_irq - Inject an IRQ from a device to the vgic
+ * @kvm:     The VM structure pointer
+ * @cpuid:   The CPU for PPIs
+ * @intid:   The INTID to inject a new state to.
+ * @level:   Edge-triggered:  true:  to trigger the interrupt
+ *			      false: to ignore the call
+ *	     Level-sensitive  true:  raise the input signal
+ *			      false: lower the input signal
+ *
+ * The VGIC is not concerned with devices being active-LOW or active-HIGH for
+ * level-sensitive interrupts.  You can think of the level parameter as 1
+ * being HIGH and 0 being LOW and all devices being active-HIGH.
+ */
+int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			bool level)
+{
+	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 61b8d22..c625767 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -18,5 +18,6 @@
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
+bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:54 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:54 +0100
Subject: [PATCH v5 15/57] KVM: arm/arm64: vgic-new: Add data structure
 definitions
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-16-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Add a new header file for the new and improved GIC implementation.
The big change is that we now have a struct vgic_irq per IRQ instead
of spreading all the information over various bitmaps.

We include this new header conditionally from within the old header
file for the time being to avoid touching all the users.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog RFC .. v1:
- adapt to 4.6-rc (adding live_lrs member)
- elaborate on ap_list usage

Changelog v1 .. v2:
- change data type of dist->enabled to bool

Changelog v3 .. v4:
- fix comment typos

 include/kvm/arm_vgic.h  |   5 ++
 include/kvm/vgic/vgic.h | 201 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 206 insertions(+)
 create mode 100644 include/kvm/vgic/vgic.h

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index ade7005..da0a5248 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -19,6 +19,10 @@
 #ifndef __ASM_ARM_KVM_VGIC_H
 #define __ASM_ARM_KVM_VGIC_H
 
+#ifdef CONFIG_KVM_NEW_VGIC
+#include <kvm/vgic/vgic.h>
+#else
+
 #include <linux/kernel.h>
 #include <linux/kvm.h>
 #include <linux/irqreturn.h>
@@ -367,4 +371,5 @@ static inline int vgic_v3_probe(const struct gic_kvm_info *gic_kvm_info,
 }
 #endif
 
+#endif	/* old VGIC include */
 #endif
diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
new file mode 100644
index 0000000..6ca0781
--- /dev/null
+++ b/include/kvm/vgic/vgic.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_ARM_KVM_VGIC_VGIC_H
+#define __ASM_ARM_KVM_VGIC_VGIC_H
+
+#include <linux/kernel.h>
+#include <linux/kvm.h>
+#include <linux/irqreturn.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <kvm/iodev.h>
+
+#define VGIC_V3_MAX_CPUS	255
+#define VGIC_V2_MAX_CPUS	8
+#define VGIC_NR_IRQS_LEGACY     256
+#define VGIC_NR_SGIS		16
+#define VGIC_NR_PPIS		16
+#define VGIC_NR_PRIVATE_IRQS	(VGIC_NR_SGIS + VGIC_NR_PPIS)
+#define VGIC_MAX_PRIVATE	(VGIC_NR_PRIVATE_IRQS - 1)
+#define VGIC_MAX_SPI		1019
+#define VGIC_MAX_RESERVED	1023
+#define VGIC_MIN_LPI		8192
+
+enum vgic_type {
+	VGIC_V2,		/* Good ol' GICv2 */
+	VGIC_V3,		/* New fancy GICv3 */
+};
+
+/* same for all guests, as depending only on the _host's_ GIC model */
+struct vgic_global {
+	/* type of the host GIC */
+	enum vgic_type		type;
+
+	/* Physical address of vgic virtual cpu interface */
+	phys_addr_t		vcpu_base;
+
+	/* virtual control interface mapping */
+	void __iomem		*vctrl_base;
+
+	/* Number of implemented list registers */
+	int			nr_lr;
+
+	/* Maintenance IRQ number */
+	unsigned int		maint_irq;
+
+	/* maximum number of VCPUs allowed (GICv2 limits us to 8) */
+	int			max_gic_vcpus;
+
+	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
+	bool			can_emulate_gicv2;
+};
+
+extern struct vgic_global kvm_vgic_global_state;
+
+#define VGIC_V2_MAX_LRS		(1 << 6)
+#define VGIC_V3_MAX_LRS		16
+#define VGIC_V3_LR_INDEX(lr)	(VGIC_V3_MAX_LRS - 1 - lr)
+
+enum vgic_irq_config {
+	VGIC_CONFIG_EDGE = 0,
+	VGIC_CONFIG_LEVEL
+};
+
+struct vgic_irq {
+	spinlock_t irq_lock;		/* Protects the content of the struct */
+	struct list_head ap_list;
+
+	struct kvm_vcpu *vcpu;		/* SGIs and PPIs: The VCPU
+					 * SPIs and LPIs: The VCPU whose ap_list
+					 * this is queued on.
+					 */
+
+	struct kvm_vcpu *target_vcpu;	/* The VCPU that this interrupt should
+					 * be sent to, as a result of the
+					 * targets reg (v2) or the
+					 * affinity reg (v3).
+					 */
+
+	u32 intid;			/* Guest visible INTID */
+	bool pending;
+	bool line_level;		/* Level only */
+	bool soft_pending;		/* Level only */
+	bool active;			/* not used for LPIs */
+	bool enabled;
+	bool hw;			/* Tied to HW IRQ */
+	u32 hwintid;			/* HW INTID number */
+	union {
+		u8 targets;			/* GICv2 target VCPUs mask */
+		u32 mpidr;			/* GICv3 target VCPU */
+	};
+	u8 source;			/* GICv2 SGIs only */
+	u8 priority;
+	enum vgic_irq_config config;	/* Level or edge */
+};
+
+struct vgic_dist {
+	bool			in_kernel;
+	bool			ready;
+
+	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
+	u32			vgic_model;
+
+	int			nr_spis;
+
+	/* TODO: Consider moving to global state */
+	/* Virtual control interface mapping */
+	void __iomem		*vctrl_base;
+
+	/* base addresses in guest physical address space: */
+	gpa_t			vgic_dist_base;		/* distributor */
+	union {
+		/* either a GICv2 CPU interface */
+		gpa_t			vgic_cpu_base;
+		/* or a number of GICv3 redistributor regions */
+		gpa_t			vgic_redist_base;
+	};
+
+	/* distributor enabled */
+	bool			enabled;
+
+	struct vgic_irq		*spis;
+};
+
+struct vgic_v2_cpu_if {
+	u32		vgic_hcr;
+	u32		vgic_vmcr;
+	u32		vgic_misr;	/* Saved only */
+	u64		vgic_eisr;	/* Saved only */
+	u64		vgic_elrsr;	/* Saved only */
+	u32		vgic_apr;
+	u32		vgic_lr[VGIC_V2_MAX_LRS];
+};
+
+struct vgic_v3_cpu_if {
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	u32		vgic_hcr;
+	u32		vgic_vmcr;
+	u32		vgic_sre;	/* Restored only, change ignored */
+	u32		vgic_misr;	/* Saved only */
+	u32		vgic_eisr;	/* Saved only */
+	u32		vgic_elrsr;	/* Saved only */
+	u32		vgic_ap0r[4];
+	u32		vgic_ap1r[4];
+	u64		vgic_lr[VGIC_V3_MAX_LRS];
+#endif
+};
+
+struct vgic_cpu {
+	/* CPU vif control registers for world switch */
+	union {
+		struct vgic_v2_cpu_if	vgic_v2;
+		struct vgic_v3_cpu_if	vgic_v3;
+	};
+
+	unsigned int used_lrs;
+	struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
+
+	spinlock_t ap_list_lock;	/* Protects the ap_list */
+
+	/*
+	 * List of IRQs that this VCPU should consider because they are either
+	 * Active or Pending (hence the name; AP list), or because they recently
+	 * were one of the two and need to be migrated off this list to another
+	 * VCPU.
+	 */
+	struct list_head ap_list_head;
+
+	u64 live_lrs;
+};
+
+#define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
+#define vgic_initialized(k)	(false)
+#define vgic_ready(k)		((k)->arch.vgic.ready)
+#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
+			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
+
+/**
+ * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
+ *
+ * The host's GIC naturally limits the maximum amount of VCPUs a guest
+ * can use.
+ */
+static inline int kvm_vgic_get_max_vcpus(void)
+{
+	return kvm_vgic_global_state.max_gic_vcpus;
+}
+
+#endif /* __ASM_ARM_KVM_VGIC_VGIC_H */
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:00 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:00 +0100
Subject: [PATCH v5 21/57] KVM: arm/arm64: vgic-new: Add GICv3 world switch
 backend
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-22-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

As the GICv3 virtual interface registers differ from their GICv2
siblings, we need different handlers for processing maintenance
interrupts and reading/writing to the LRs.
Implement the respective handler functions and connect them to
existing code to be called if the host is using a GICv3.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- remove outdated comment about the dist_lock
- add WARN_ON about LR_STATE not being 0 in maintenance interrupts

Changelog v1 .. v2:
- inject the IRQ priority into the list register

Changelog v2 .. v3:
- remove no longer needed irqchip/arm-gic.h inclusion

Changelog v3 .. v4:
- remove ELRSR bit set during process_maintenance()
- refine comment about Group1 interrupts
- remove wrong comment about ap_list_lock in vgic_v3_fold_lr_state()

 include/linux/irqchip/arm-gic-v3.h |   1 +
 virt/kvm/arm/vgic/vgic-v3.c        | 162 +++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c           |  25 ++++--
 virt/kvm/arm/vgic/vgic.h           |  29 +++++++
 4 files changed, 212 insertions(+), 5 deletions(-)
 create mode 100644 virt/kvm/arm/vgic/vgic-v3.c

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index ec938d1..35e93cf 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -275,6 +275,7 @@
 #define ICH_LR_ACTIVE_BIT		(1ULL << 63)
 #define ICH_LR_PHYS_ID_SHIFT		32
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
+#define ICH_LR_PRIORITY_SHIFT		48
 
 /* These are for GICv2 emulation only */
 #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
new file mode 100644
index 0000000..fb547da
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -0,0 +1,162 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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/irqchip/arm-gic-v3.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+
+	if (cpuif->vgic_misr & ICH_MISR_EOI) {
+		unsigned long eisr_bmap = cpuif->vgic_eisr;
+		int lr;
+
+		for_each_set_bit(lr, &eisr_bmap, kvm_vgic_global_state.nr_lr) {
+			u32 intid;
+			u64 val = cpuif->vgic_lr[lr];
+
+			if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+				intid = val & ICH_LR_VIRTUAL_ID_MASK;
+			else
+				intid = val & GICH_LR_VIRTUALID;
+
+			WARN_ON(cpuif->vgic_lr[lr] & ICH_LR_STATE);
+
+			kvm_notify_acked_irq(vcpu->kvm, 0,
+					     intid - VGIC_NR_PRIVATE_IRQS);
+		}
+
+		/*
+		 * In the next iterations of the vcpu loop, if we sync
+		 * the vgic state after flushing it, but before
+		 * entering the guest (this happens for pending
+		 * signals and vmid rollovers), then make sure we
+		 * don't pick up any old maintenance interrupts here.
+		 */
+		cpuif->vgic_eisr = 0;
+	}
+
+	cpuif->vgic_hcr &= ~ICH_HCR_UIE;
+}
+
+void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+
+	cpuif->vgic_hcr |= ICH_HCR_UIE;
+}
+
+void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+	int lr;
+
+	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
+		u64 val = cpuif->vgic_lr[lr];
+		u32 intid;
+		struct vgic_irq *irq;
+
+		if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+			intid = val & ICH_LR_VIRTUAL_ID_MASK;
+		else
+			intid = val & GICH_LR_VIRTUALID;
+		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+
+		/* Always preserve the active bit */
+		irq->active = !!(val & ICH_LR_ACTIVE_BIT);
+
+		/* Edge is the only case where we preserve the pending bit */
+		if (irq->config == VGIC_CONFIG_EDGE &&
+		    (val & ICH_LR_PENDING_BIT)) {
+			irq->pending = true;
+
+			if (vgic_irq_is_sgi(intid) &&
+			    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
+
+				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+				irq->source |= (1 << cpuid);
+			}
+		}
+
+		/* Clear soft pending state when level irqs have been acked */
+		if (irq->config == VGIC_CONFIG_LEVEL &&
+		    !(val & ICH_LR_PENDING_BIT)) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+/* Requires the irq to be locked already */
+void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
+{
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+	u64 val = irq->intid;
+
+	if (irq->pending) {
+		val |= ICH_LR_PENDING_BIT;
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			irq->pending = false;
+
+		if (vgic_irq_is_sgi(irq->intid) &&
+		    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+			u32 src = ffs(irq->source);
+
+			BUG_ON(!src);
+			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
+			irq->source &= ~(1 << (src - 1));
+			if (irq->source)
+				irq->pending = true;
+		}
+	}
+
+	if (irq->active)
+		val |= ICH_LR_ACTIVE_BIT;
+
+	if (irq->hw) {
+		val |= ICH_LR_HW;
+		val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
+	} else {
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			val |= ICH_LR_EOI;
+	}
+
+	/*
+	 * We currently only support Group1 interrupts, which is a
+	 * known defect. This needs to be addressed at some point.
+	 */
+	if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+		val |= ICH_LR_GROUP;
+
+	val |= (u64)irq->priority << ICH_LR_PRIORITY_SHIFT;
+
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = val;
+}
+
+void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 7a9e25d..719cef0 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -400,12 +400,18 @@ retry:
 
 static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_process_maintenance(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_process_maintenance(vcpu);
+	else
+		vgic_v3_process_maintenance(vcpu);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_fold_lr_state(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_fold_lr_state(vcpu);
+	else
+		vgic_v3_fold_lr_state(vcpu);
 }
 
 /* Requires the irq_lock to be held. */
@@ -414,17 +420,26 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
 {
 	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
 
-	vgic_v2_populate_lr(vcpu, irq, lr);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_populate_lr(vcpu, irq, lr);
+	else
+		vgic_v3_populate_lr(vcpu, irq, lr);
 }
 
 static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
-	vgic_v2_clear_lr(vcpu, lr);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_clear_lr(vcpu, lr);
+	else
+		vgic_v3_clear_lr(vcpu, lr);
 }
 
 static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_set_underflow(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_set_underflow(vcpu);
+	else
+		vgic_v3_set_underflow(vcpu);
 }
 
 /* Requires the ap_list_lock to be held. */
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 0db490e..81b1a20 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -28,4 +28,33 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
+void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
+void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
+void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
+void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+#else
+static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_v3_populate_lr(struct kvm_vcpu *vcpu,
+				       struct vgic_irq *irq, int lr)
+{
+}
+
+static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+}
+
+static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
+{
+}
+#endif
+
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:58 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:58 +0100
Subject: [PATCH v5 19/57] KVM: arm/arm64: vgic-new: Add IRQ sync/flush
 framework
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-20-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Implement the framework for syncing IRQs between our emulation and
the list registers, which represent the guest's view of IRQs.
This is done in kvm_vgic_flush_hwstate and kvm_vgic_sync_hwstate,
which gets called on guest entry and exit.
The code talking to the actual GICv2/v3 hardware is added in the
following patches.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- split out vgic_clear_lr() from vgic_populate_lr()
- rename vgic_populate_lrs() to vgic_flush_lr_state()
- clean all LRs when the distributor is disabled
- use list_del() instead of list_del_init()
- add comments to explain the direction of sync/flush_hwstate
- remove unneeded BUG_ON(in_interrupt()

Changelog v2 .. v3:
- remove bogus v2 specific rebase leftovers

Changelog v3 .. v4:
- amend locks requirements

Changelog v4 .. v5:
- add nested spinlock annotation
- refine comment about multiple-source SGIs

 include/kvm/vgic/vgic.h  |   4 +
 virt/kvm/arm/vgic/vgic.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h |   2 +
 3 files changed, 198 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 7b6ca90..9506267 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -190,6 +190,10 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
 			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
 
+bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
+void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
+void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
+
 /**
  * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
  *
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index bce17de..2e048a4 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -307,3 +307,195 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 {
 	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
 }
+
+/**
+ * vgic_prune_ap_list - Remove non-relevant interrupts from the list
+ *
+ * @vcpu: The VCPU pointer
+ *
+ * Go over the list of "interesting" interrupts, and prune those that we
+ * won't have to consider in the near future.
+ */
+static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq, *tmp;
+
+retry:
+	spin_lock(&vgic_cpu->ap_list_lock);
+
+	list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
+		struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
+
+		spin_lock(&irq->irq_lock);
+
+		BUG_ON(vcpu != irq->vcpu);
+
+		target_vcpu = vgic_target_oracle(irq);
+
+		if (!target_vcpu) {
+			/*
+			 * We don't need to process this interrupt any
+			 * further, move it off the list.
+			 */
+			list_del(&irq->ap_list);
+			irq->vcpu = NULL;
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		if (target_vcpu == vcpu) {
+			/* We're on the right CPU */
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		/* This interrupt looks like it has to be migrated. */
+
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vgic_cpu->ap_list_lock);
+
+		/*
+		 * Ensure locking order by always locking the smallest
+		 * ID first.
+		 */
+		if (vcpu->vcpu_id < target_vcpu->vcpu_id) {
+			vcpuA = vcpu;
+			vcpuB = target_vcpu;
+		} else {
+			vcpuA = target_vcpu;
+			vcpuB = vcpu;
+		}
+
+		spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+		spin_lock_nested(&vcpuB->arch.vgic_cpu.ap_list_lock,
+				 SINGLE_DEPTH_NESTING);
+		spin_lock(&irq->irq_lock);
+
+		/*
+		 * If the affinity has been preserved, move the
+		 * interrupt around. Otherwise, it means things have
+		 * changed while the interrupt was unlocked, and we
+		 * need to replay this.
+		 *
+		 * In all cases, we cannot trust the list not to have
+		 * changed, so we restart from the beginning.
+		 */
+		if (target_vcpu == vgic_target_oracle(irq)) {
+			struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;
+
+			list_del(&irq->ap_list);
+			irq->vcpu = target_vcpu;
+			list_add_tail(&irq->ap_list, &new_cpu->ap_list_head);
+		}
+
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
+		spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+		goto retry;
+	}
+
+	spin_unlock(&vgic_cpu->ap_list_lock);
+}
+
+static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+}
+
+/* Requires the irq_lock to be held. */
+static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
+				    struct vgic_irq *irq, int lr)
+{
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+}
+
+static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+}
+
+static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
+{
+}
+
+/* Requires the ap_list_lock to be held. */
+static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	int count = 0;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+		/* GICv2 SGIs can count for more than one... */
+		if (vgic_irq_is_sgi(irq->intid) && irq->source)
+			count += hweight8(irq->source);
+		else
+			count++;
+		spin_unlock(&irq->irq_lock);
+	}
+	return count;
+}
+
+/* Requires the VCPU's ap_list_lock to be held. */
+static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	int count = 0;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	if (compute_ap_list_depth(vcpu) > kvm_vgic_global_state.nr_lr) {
+		vgic_set_underflow(vcpu);
+		vgic_sort_ap_list(vcpu);
+	}
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+
+		if (unlikely(vgic_target_oracle(irq) != vcpu))
+			goto next;
+
+		/*
+		 * On a VGICv2 we can have SGIs with multiple sources, so
+		 * we loop here to hopefully get all of them in at once.
+		 */
+		do {
+			vgic_populate_lr(vcpu, irq, count++);
+		} while (irq->source && count < kvm_vgic_global_state.nr_lr);
+
+next:
+		spin_unlock(&irq->irq_lock);
+
+		if (count == kvm_vgic_global_state.nr_lr)
+			break;
+	}
+
+	vcpu->arch.vgic_cpu.used_lrs = count;
+
+	/* Nuke remaining LRs */
+	for ( ; count < kvm_vgic_global_state.nr_lr; count++)
+		vgic_clear_lr(vcpu, count);
+}
+
+/* Sync back the hardware VGIC state into our emulation after a guest's run. */
+void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
+{
+	vgic_process_maintenance_interrupt(vcpu);
+	vgic_fold_lr_state(vcpu);
+	vgic_prune_ap_list(vcpu);
+}
+
+/* Flush our emulation state into the GIC hardware before entering the guest. */
+void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
+{
+	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+	vgic_flush_lr_state(vcpu);
+	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index c625767..29b96b9 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,6 +16,8 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:03 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:03 +0100
Subject: [PATCH v5 24/57] KVM: arm/arm64: vgic-new: Add GICv2 MMIO handling
 framework
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-25-git-send-email-andre.przywara@arm.com>

Create vgic-mmio-v2.c to describe GICv2 emulation specific handlers
using the initializer macros provided by the VGIC MMIO framework.
Provide a function to register the GICv2 distributor registers to
the kvm_io_bus framework.
The actual handler functions are still stubs in this patch.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v1 .. v2:
- new patch, split out from the generic MMIO framework patch
- use a separate file to hold GICv2 emulation specific handlers
- replace _nyi stub functions with raz/wi versions

Changelog v2 .. v3:
- replace kvm/vgic/vgic.h with kvm/arm_vgic.h
- add vgic_register_dist_iodev() prototype

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 76 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c    | 26 ++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  2 ++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 4 files changed, 106 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v2.c

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
new file mode 100644
index 0000000..a3e31a9
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -0,0 +1,76 @@
+/*
+ * VGICv2 MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irqchip/arm-gic.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+static const struct vgic_register_region vgic_v2_dist_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 12,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 2,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+};
+
+unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
+{
+	dev->regions = vgic_v2_dist_registers;
+	dev->nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
+
+	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
+
+	return SZ_4K;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 012b82b..1a97765 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -182,3 +182,29 @@ struct kvm_io_device_ops kvm_io_gic_ops = {
 	.read = dispatch_mmio_read,
 	.write = dispatch_mmio_write,
 };
+
+int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
+			     enum vgic_type type)
+{
+	struct vgic_io_device *io_device = &kvm->arch.vgic.dist_iodev;
+	int ret = 0;
+	unsigned int len;
+
+	switch (type) {
+	case VGIC_V2:
+		len = vgic_v2_init_dist_iodev(io_device);
+		break;
+	default:
+		BUG_ON(1);
+	}
+
+	io_device->base_addr = dist_base_address;
+	io_device->redist_vcpu = NULL;
+
+	mutex_lock(&kvm->slots_lock);
+	ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address,
+				      len, &io_device->dev);
+	mutex_unlock(&kvm->slots_lock);
+
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 58a1878..b38ff6c 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -96,4 +96,6 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
 void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 			unsigned int len, unsigned long val);
 
+unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
+
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 81b1a20..fd9acaa 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -27,6 +27,8 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
+			     enum vgic_type);
 
 #ifdef CONFIG_KVM_ARM_VGIC_V3
 void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:05 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:05 +0100
Subject: [PATCH v5 26/57] KVM: arm/arm64: vgic-new: Add ENABLE registers
 handlers
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-27-git-send-email-andre.przywara@arm.com>

As the enable register handlers are shared between the v2 and v3
emulation, their implementation goes into vgic-mmio.c, to be easily
referenced from the v3 emulation as well later.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- use lower bits of address to determine IRQ number
- remove TODO, confirmed to be fine

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro
- replace extract_bytes() with simple return

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
 virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
 3 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index d812c93..d5355b5 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -72,10 +72,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 1a97765..32ed8db 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -39,6 +39,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 	/* Ignore */
 }
 
+/*
+ * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
+ * of the enabled bit, so there is only one function for both here.
+ */
+unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->enabled)
+			value |= (1U << i);
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		irq->enabled = true;
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
+void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->enabled = false;
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index b38ff6c..5a86e30 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -96,6 +96,17 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
 void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 			unsigned int len, unsigned long val);
 
+unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
+void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:06 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:06 +0100
Subject: [PATCH v5 27/57] KVM: arm/arm64: vgic-new: Add PENDING registers
 handlers
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-28-git-send-email-andre.przywara@arm.com>

The pending register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be easily
referenced from the v3 emulation as well later.
For level triggered interrupts the real line level is unaffected by
this write, so we keep this state separate and combine it with the
device's level to get the actual pending state.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- remove IRQ lock from read handler
- remove TODO from clear pending handler

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro
- replace extract_bytes() with simple return

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
 virt/kvm/arm/vgic/vgic-mmio.c    | 60 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 12 ++++++++
 3 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index d5355b5..c13a708 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -78,10 +78,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 32ed8db..d8dc8f6 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -95,6 +95,66 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->pending)
+			value |= (1U << i);
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			irq->soft_pending = true;
+
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
+void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		if (irq->config == VGIC_CONFIG_LEVEL) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		} else {
+			irq->pending = false;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 5a86e30..b18120d 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -107,6 +107,18 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val);
 
+unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
+void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:12 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:12 +0100
Subject: [PATCH v5 33/57] KVM: arm/arm64: vgic-new: Add SGIPENDR register
 handlers
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-34-git-send-email-andre.przywara@arm.com>

As this register is v2 specific, its implementation lives entirely
in vgic-mmio-v2.c.
This register allows setting the source mask of an IPI.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- remove IRQ lock from read handler
- update pending bit on setting the first / clearing the last bit
- queue virtual IRQ if necessary

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 60 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index c884e9b..3925d4c 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -146,6 +146,64 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->source << (i * 8);
+	}
+	return val;
+}
+
+static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len,
+				     unsigned long val)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->source &= ~((val >> (i * 8)) & 0xff);
+		if (!irq->source)
+			irq->pending = false;
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len,
+				     unsigned long val)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->source |= (val >> (i * 8)) & 0xff;
+
+		if (irq->source) {
+			irq->pending = true;
+			vgic_queue_irq_unlock(vcpu->kvm, irq);
+		} else {
+			spin_unlock(&irq->irq_lock);
+		}
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
@@ -184,10 +242,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		vgic_mmio_read_sgipend, vgic_mmio_write_sgipendc, 16,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 };
 
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:13 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:13 +0100
Subject: [PATCH v5 34/57] KVM: arm/arm64: vgic-new: Add GICv3 MMIO handling
 framework
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-35-git-send-email-andre.przywara@arm.com>

Create a new file called vgic-mmio-v3.c and describe the GICv3
distributor and redistributor registers there.
This adds a special macro to deal with the split of SGI/PPI in the
redistributor and SPIs in the distributor, which allows us to reuse
the existing GICv2 handlers for those registers which are compatible.
Also we provide a function to deal with the registration of the two
separate redistributor frames per VCPU.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- adapt to new MMIO registration approach:
  register one device for the distributor and two for each VCPU
- implement special handling for private interrupts
- remove empty stub functions
- make IGROUPR return RAO

Changelog v1 .. v2:
- adapt to new framework, introduce vgic-mmio-v3.c
- remove userland register access functions (for now)
- precompute .len when describing a VGIC register
- add missed pointer incrementation on registering redist regions
- replace _nyi stub functions with raz/wi versions

Changelog v2 .. v3:
- replace inclusion of kvm/vgic/vgic.h with kvm/arm_vgic.h
- add prototype and stub code for vgic_register_redist_iodevs
- rename register struct variables _rdbase_ and _sgibase_

Changelog v3 .. v4:
- specify accessor width

Changelog v4 .. v5:
- enclose macro arguments in parentheses

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 224 +++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
 virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
 virt/kvm/arm/vgic/vgic.h         |   7 ++
 4 files changed, 238 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
new file mode 100644
index 0000000..02ddaf7
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -0,0 +1,224 @@
+/*
+ * VGICv3 MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irqchip/arm-gic-v3.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include <asm/kvm_emulate.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+/*
+ * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
+ * redistributors, while SPIs are covered by registers in the distributor
+ * block. Trying to set private IRQs in this block gets ignored.
+ * We take some special care here to fix the calculation of the register
+ * offset.
+ */
+#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, rd, wr, bpi, acc)	\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = bpi,					\
+		.len = ((bpi) * VGIC_NR_PRIVATE_IRQS) / 8,		\
+		.access_flags = acc,					\
+		.read = vgic_mmio_read_raz,				\
+		.write = vgic_mmio_write_wi,				\
+	}, {								\
+		.reg_offset = (off) + ((bpi) * VGIC_NR_PRIVATE_IRQS) / 8, \
+		.bits_per_irq = bpi,					\
+		.len = ((bpi) * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
+		.access_flags = acc,					\
+		.read = rd,						\
+		.write = wr,						\
+	}
+
+static const struct vgic_register_region vgic_v3_dist_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
+		vgic_mmio_read_config, vgic_mmio_write_config, 2,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		VGIC_ACCESS_32bit),
+};
+
+static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		VGIC_ACCESS_32bit),
+};
+
+static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 32,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
+		vgic_mmio_read_config, vgic_mmio_write_config, 8,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+};
+
+unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
+{
+	dev->regions = vgic_v3_dist_registers;
+	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
+
+	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
+
+	return SZ_64K;
+}
+
+int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
+{
+	int nr_vcpus = atomic_read(&kvm->online_vcpus);
+	struct kvm_vcpu *vcpu;
+	struct vgic_io_device *devices;
+	int c, ret = 0;
+
+	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
+			  GFP_KERNEL);
+	if (!devices)
+		return -ENOMEM;
+
+	kvm_for_each_vcpu(c, vcpu, kvm) {
+		gpa_t rd_base = redist_base_address + c * SZ_64K * 2;
+		gpa_t sgi_base = rd_base + SZ_64K;
+		struct vgic_io_device *rd_dev = &devices[c * 2];
+		struct vgic_io_device *sgi_dev = &devices[c * 2 + 1];
+
+		kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops);
+		rd_dev->base_addr = rd_base;
+		rd_dev->regions = vgic_v3_rdbase_registers;
+		rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
+		rd_dev->redist_vcpu = vcpu;
+
+		mutex_lock(&kvm->slots_lock);
+		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base,
+					      SZ_64K, &rd_dev->dev);
+		mutex_unlock(&kvm->slots_lock);
+
+		if (ret)
+			break;
+
+		kvm_iodevice_init(&sgi_dev->dev, &kvm_io_gic_ops);
+		sgi_dev->base_addr = sgi_base;
+		sgi_dev->regions = vgic_v3_sgibase_registers;
+		sgi_dev->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
+		sgi_dev->redist_vcpu = vcpu;
+
+		mutex_lock(&kvm->slots_lock);
+		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, sgi_base,
+					      SZ_64K, &sgi_dev->dev);
+		mutex_unlock(&kvm->slots_lock);
+		if (ret) {
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &rd_dev->dev);
+			break;
+		}
+	}
+
+	if (ret) {
+		/* The current c failed, so we start with the previous one. */
+		for (c--; c >= 0; c--) {
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2].dev);
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2 + 1].dev);
+		}
+		kfree(devices);
+	} else {
+		kvm->arch.vgic.redist_iodevs = devices;
+	}
+
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 9de80be..4ef35719 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -478,6 +478,11 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 	case VGIC_V2:
 		len = vgic_v2_init_dist_iodev(io_device);
 		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case VGIC_V3:
+		len = vgic_v3_init_dist_iodev(io_device);
+		break;
+#endif
 	default:
 		BUG_ON(1);
 	}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 5e4a3e4..43cf429 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -145,4 +145,6 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
 
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
+unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
+
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index e57f8d5..6742b11 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -42,6 +42,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
 {
@@ -63,6 +64,12 @@ static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 }
+
+static inline int vgic_register_redist_iodevs(struct kvm *kvm,
+					      gpa_t dist_base_address)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:14 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:14 +0100
Subject: [PATCH v5 35/57] KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR,
 TYPER handlers
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-36-git-send-email-andre.przywara@arm.com>

As in the GICv2 emulation we handle those three registers in one
function.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- kick VCPUs if distributor gets enabled

Changelog v1 .. v2:
- rewrite write handler to use switch statement

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 48 +++++++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.h         |  1 +
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 02ddaf7..34afa75 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -22,6 +22,52 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 value = 0;
+
+	switch (addr & 0x0c) {
+	case GICD_CTLR:
+		if (vcpu->kvm->arch.vgic.enabled)
+			value |= GICD_CTLR_ENABLE_SS_G1;
+		value |= GICD_CTLR_ARE_NS | GICD_CTLR_DS;
+		break;
+	case GICD_TYPER:
+		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+		value = (value >> 5) - 1;
+		value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19;
+		break;
+	case GICD_IIDR:
+		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+		break;
+	default:
+		return 0;
+	}
+
+	return value;
+}
+
+static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+	bool was_enabled = dist->enabled;
+
+	switch (addr & 0x0c) {
+	case GICD_CTLR:
+		dist->enabled = val & GICD_CTLR_ENABLE_SS_G1;
+
+		if (!was_enabled && dist->enabled)
+			vgic_kick_vcpus(vcpu->kvm);
+		break;
+	case GICD_TYPER:
+	case GICD_IIDR:
+		return;
+	}
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -48,7 +94,7 @@
 
 static const struct vgic_register_region vgic_v3_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc, 16,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 6742b11..44c6a1b 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,7 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define INTERRUPT_ID_BITS_SPIS	10
 #define VGIC_PRI_BITS		5
 
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:15 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:15 +0100
Subject: [PATCH v5 36/57] KVM: arm/arm64: vgic-new: Add GICv3 redistributor
 IIDR and TYPER handler
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-37-git-send-email-andre.przywara@arm.com>

The redistributor TYPER tells the OS about the associated MPIDR,
also the LAST bit is crucial to determine the number of redistributors.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- add extract_bytes() as static (moved from an earlier patch)
- replace one extract_bytes() access with a simple return

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 34afa75..16942e8 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -22,6 +22,13 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+/* extract @num bytes at @offset bytes offset in data */
+static unsigned long extract_bytes(unsigned long data, unsigned int offset,
+				   unsigned int num)
+{
+	return (data >> (offset * 8)) & GENMASK_ULL(num * 8 - 1, 0);
+}
+
 static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
 					    gpa_t addr, unsigned int len)
 {
@@ -68,6 +75,27 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
+					      gpa_t addr, unsigned int len)
+{
+	unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
+	int target_vcpu_id = vcpu->vcpu_id;
+	u64 value;
+
+	value = (mpidr & GENMASK(23, 0)) << 32;
+	value |= ((target_vcpu_id & 0xffff) << 8);
+	if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
+		value |= GICR_TYPER_LAST;
+
+	return extract_bytes(value, addr & 7, len);
+}
+
+static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
+					     gpa_t addr, unsigned int len)
+{
+	return (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -142,10 +170,10 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		vgic_mmio_read_v3r_iidr, vgic_mmio_write_wi, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, 8,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:17 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:17 +0100
Subject: [PATCH v5 38/57] KVM: arm/arm64: vgic-new: Add GICv3 IROUTER register
 handlers
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-39-git-send-email-andre.przywara@arm.com>

Since GICv3 supports much more than the 8 CPUs the GICv2 ITARGETSR
register can handle, the new IROUTER register covers the whole range
of possible target (V)CPUs by using the same MPIDR that the cores
report themselves.
In addition to translating this MPIDR into a vcpu pointer we store
the originally written value as well. The architecture allows to
write any values into the register, which must be read back as written.

Since we don't support affinity level 3, we don't need to take care
about the upper word of this 64-bit register, which simplifies the
handling a bit.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- fold in and simplify vgic_v3_irq_change_affinity

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- move accessor width check into dispatcher
- use IRQ number accessor macro

Changelog v4 .. v5:
- make upper word of IROUTER read-as-zero

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 41 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index abf0d8d..78764d9 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -75,6 +75,45 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	int intid = VGIC_ADDR_TO_INTID(addr, 64);
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+
+	if (!irq)
+		return 0;
+
+	/* The upper word is RAZ for us. */
+	if (addr & 4)
+		return 0;
+
+	return extract_bytes(READ_ONCE(irq->mpidr), addr & 7, len);
+}
+
+static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	int intid = VGIC_ADDR_TO_INTID(addr, 64);
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+
+	if (!irq)
+		return;
+
+	/* The upper word is WI for us since we don't implement Aff3. */
+	if (addr & 4)
+		return;
+
+	spin_lock(&irq->irq_lock);
+
+	/* We only care about and preserve Aff0, Aff1 and Aff2. */
+	irq->mpidr = val & GENMASK(23, 0);
+	irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, irq->mpidr);
+
+	spin_unlock(&irq->irq_lock);
+}
+
 static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
 					      gpa_t addr, unsigned int len)
 {
@@ -170,7 +209,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
+		vgic_mmio_read_irouter, vgic_mmio_write_irouter, 64,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
 		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:18 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:18 +0100
Subject: [PATCH v5 39/57] KVM: arm/arm64: vgic-new: Add GICv3 SGI system
 register trap handler
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-40-git-send-email-andre.przywara@arm.com>

In contrast to GICv2 SGIs in a GICv3 implementation are not triggered
by a MMIO write, but with a system register write. KVM knows about
that register already, we just need to implement the handler and wire
it up to the core KVM/ARM code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- add comment about SGI_AFFINITY_LEVEL macro

 include/kvm/vgic/vgic.h          |   8 +++
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 106 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index ff3f9c2..00e3dca 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -209,6 +209,14 @@ bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
 
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
+#else
+static inline void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
+{
+}
+#endif
+
 /**
  * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
  *
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 78764d9..d524d85 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -347,3 +347,109 @@ int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
 
 	return ret;
 }
+
+/*
+ * Compare a given affinity (level 1-3 and a level 0 mask, from the SGI
+ * generation register ICC_SGI1R_EL1) with a given VCPU.
+ * If the VCPU's MPIDR matches, return the level0 affinity, otherwise
+ * return -1.
+ */
+static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct kvm_vcpu *vcpu)
+{
+	unsigned long affinity;
+	int level0;
+
+	/*
+	 * Split the current VCPU's MPIDR into affinity level 0 and the
+	 * rest as this is what we have to compare against.
+	 */
+	affinity = kvm_vcpu_get_mpidr_aff(vcpu);
+	level0 = MPIDR_AFFINITY_LEVEL(affinity, 0);
+	affinity &= ~MPIDR_LEVEL_MASK;
+
+	/* bail out if the upper three levels don't match */
+	if (sgi_aff != affinity)
+		return -1;
+
+	/* Is this VCPU's bit set in the mask ? */
+	if (!(sgi_cpu_mask & BIT(level0)))
+		return -1;
+
+	return level0;
+}
+
+/*
+ * The ICC_SGI* registers encode the affinity differently from the MPIDR,
+ * so provide a wrapper to use the existing defines to isolate a certain
+ * affinity level.
+ */
+#define SGI_AFFINITY_LEVEL(reg, level) \
+	((((reg) & ICC_SGI1R_AFFINITY_## level ##_MASK) \
+	>> ICC_SGI1R_AFFINITY_## level ##_SHIFT) << MPIDR_LEVEL_SHIFT(level))
+
+/**
+ * vgic_v3_dispatch_sgi - handle SGI requests from VCPUs
+ * @vcpu: The VCPU requesting a SGI
+ * @reg: The value written into the ICC_SGI1R_EL1 register by that VCPU
+ *
+ * With GICv3 (and ARE=1) CPUs trigger SGIs by writing to a system register.
+ * This will trap in sys_regs.c and call this function.
+ * This ICC_SGI1R_EL1 register contains the upper three affinity levels of the
+ * target processors as well as a bitmask of 16 Aff0 CPUs.
+ * If the interrupt routing mode bit is not set, we iterate over all VCPUs to
+ * check for matching ones. If this bit is set, we signal all, but not the
+ * calling VCPU.
+ */
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
+{
+	struct kvm *kvm = vcpu->kvm;
+	struct kvm_vcpu *c_vcpu;
+	u16 target_cpus;
+	u64 mpidr;
+	int sgi, c;
+	int vcpu_id = vcpu->vcpu_id;
+	bool broadcast;
+
+	sgi = (reg & ICC_SGI1R_SGI_ID_MASK) >> ICC_SGI1R_SGI_ID_SHIFT;
+	broadcast = reg & BIT(ICC_SGI1R_IRQ_ROUTING_MODE_BIT);
+	target_cpus = (reg & ICC_SGI1R_TARGET_LIST_MASK) >> ICC_SGI1R_TARGET_LIST_SHIFT;
+	mpidr = SGI_AFFINITY_LEVEL(reg, 3);
+	mpidr |= SGI_AFFINITY_LEVEL(reg, 2);
+	mpidr |= SGI_AFFINITY_LEVEL(reg, 1);
+
+	/*
+	 * We iterate over all VCPUs to find the MPIDRs matching the request.
+	 * If we have handled one CPU, we clear its bit to detect early
+	 * if we are already finished. This avoids iterating through all
+	 * VCPUs when most of the times we just signal a single VCPU.
+	 */
+	kvm_for_each_vcpu(c, c_vcpu, kvm) {
+		struct vgic_irq *irq;
+
+		/* Exit early if we have dealt with all requested CPUs */
+		if (!broadcast && target_cpus == 0)
+			break;
+
+		/* Don't signal the calling VCPU */
+		if (broadcast && c == vcpu_id)
+			continue;
+
+		if (!broadcast) {
+			int level0;
+
+			level0 = match_mpidr(mpidr, target_cpus, c_vcpu);
+			if (level0 == -1)
+				continue;
+
+			/* remove this matching VCPU from the mask */
+			target_cpus &= ~BIT(level0);
+		}
+
+		irq = vgic_get_irq(vcpu->kvm, c_vcpu, sgi);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:19 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:19 +0100
Subject: [PATCH v5 40/57] KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM
 device ops registration
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-41-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch introduces the skeleton for the KVM device operations
associated to KVM_DEV_TYPE_ARM_VGIC_V2 and KVM_DEV_TYPE_ARM_VGIC_V3.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v1 .. v2:
- rename vgic_kvm_device.c to vgic-kvm-device.c

Changelog v2 .. v3:
- replace inclusion of vgic/vgic.h with arm_vgic.h
- add kvm_register_vgic_device() prototype to this patch

 virt/kvm/arm/vgic/vgic-kvm-device.c | 108 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |   2 +
 2 files changed, 110 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-kvm-device.c

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
new file mode 100644
index 0000000..ff332f3
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -0,0 +1,108 @@
+/*
+ * VGIC: KVM DEVICE API
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ * Author: Marc Zyngier <marc.zyngier at arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+
+/* common helpers */
+
+static int vgic_create(struct kvm_device *dev, u32 type)
+{
+	return kvm_vgic_create(dev->kvm, type);
+}
+
+static void vgic_destroy(struct kvm_device *dev)
+{
+	kfree(dev);
+}
+
+void kvm_register_vgic_device(unsigned long type)
+{
+	switch (type) {
+	case KVM_DEV_TYPE_ARM_VGIC_V2:
+		kvm_register_device_ops(&kvm_arm_vgic_v2_ops,
+					KVM_DEV_TYPE_ARM_VGIC_V2);
+		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case KVM_DEV_TYPE_ARM_VGIC_V3:
+		kvm_register_device_ops(&kvm_arm_vgic_v3_ops,
+					KVM_DEV_TYPE_ARM_VGIC_V3);
+		break;
+#endif
+	}
+}
+
+/* V2 ops */
+
+static int vgic_v2_set_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v2_get_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v2_has_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+struct kvm_device_ops kvm_arm_vgic_v2_ops = {
+	.name = "kvm-arm-vgic-v2",
+	.create = vgic_create,
+	.destroy = vgic_destroy,
+	.set_attr = vgic_v2_set_attr,
+	.get_attr = vgic_v2_get_attr,
+	.has_attr = vgic_v2_has_attr,
+};
+
+/* V3 ops */
+
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+
+static int vgic_v3_set_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v3_get_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v3_has_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+struct kvm_device_ops kvm_arm_vgic_v3_ops = {
+	.name = "kvm-arm-vgic-v3",
+	.create = vgic_create,
+	.destroy = vgic_destroy,
+	.set_attr = vgic_v3_set_attr,
+	.get_attr = vgic_v3_get_attr,
+	.has_attr = vgic_v3_has_attr,
+};
+
+#endif /* CONFIG_KVM_ARM_VGIC_V3 */
+
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 44c6a1b..77b0ab3 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -73,4 +73,6 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 }
 #endif
 
+void kvm_register_vgic_device(unsigned long type);
+
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:57 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:57 +0100
Subject: [PATCH v5 18/57] KVM: arm/arm64: vgic-new: Add IRQ sorting
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-19-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Adds the sorting function to cover the case where you have more IRQs
to consider than you have LRs. We now consider priorities.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog v4 .. v5:
- add nested spin lock annotation

 virt/kvm/arm/vgic/vgic.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index ada1d02..bce17de 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -16,6 +16,7 @@
 
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <linux/list_sort.h>
 
 #include "vgic.h"
 
@@ -103,6 +104,62 @@ static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
 }
 
 /*
+ * The order of items in the ap_lists defines how we'll pack things in LRs as
+ * well, the first items in the list being the first things populated in the
+ * LRs.
+ *
+ * A hard rule is that active interrupts can never be pushed out of the LRs
+ * (and therefore take priority) since we cannot reliably trap on deactivation
+ * of IRQs and therefore they have to be present in the LRs.
+ *
+ * Otherwise things should be sorted by the priority field and the GIC
+ * hardware support will take care of preemption of priority groups etc.
+ *
+ * Return negative if "a" sorts before "b", 0 to preserve order, and positive
+ * to sort "b" before "a".
+ */
+static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+	struct vgic_irq *irqa = container_of(a, struct vgic_irq, ap_list);
+	struct vgic_irq *irqb = container_of(b, struct vgic_irq, ap_list);
+	bool penda, pendb;
+	int ret;
+
+	spin_lock(&irqa->irq_lock);
+	spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING);
+
+	if (irqa->active || irqb->active) {
+		ret = (int)irqb->active - (int)irqa->active;
+		goto out;
+	}
+
+	penda = irqa->enabled && irqa->pending;
+	pendb = irqb->enabled && irqb->pending;
+
+	if (!penda || !pendb) {
+		ret = (int)pendb - (int)penda;
+		goto out;
+	}
+
+	/* Both pending and enabled, sort by priority */
+	ret = irqa->priority - irqb->priority;
+out:
+	spin_unlock(&irqb->irq_lock);
+	spin_unlock(&irqa->irq_lock);
+	return ret;
+}
+
+/* Must be called with the ap_list_lock held */
+static void vgic_sort_ap_list(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	list_sort(NULL, &vgic_cpu->ap_list_head, vgic_irq_cmp);
+}
+
+/*
  * Only valid injection if changing level for level-triggered IRQs or for a
  * rising edge.
  */
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:01 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:01 +0100
Subject: [PATCH v5 22/57] KVM: arm/arm64: vgic-new: Implement
 kvm_vgic_vcpu_pending_irq
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-23-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

Tell KVM whether a particular VCPU has an IRQ that needs handling
in the guest. This is used to decide whether a VCPU is runnable.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
Changelog RFC..v1:
- return false if distributor is disabled
- add vgic_kick_vcpus() implementations

Changelog v2 .. v3:
- remove vgic_kick_vcpus() implementation from this patch

 include/kvm/vgic/vgic.h  |  2 ++
 virt/kvm/arm/vgic/vgic.c | 25 +++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 9506267..f663288 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -184,6 +184,8 @@ struct vgic_cpu {
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
 
+int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
+
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(false)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 719cef0..48fdaf3 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -520,3 +520,28 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 	vgic_flush_lr_state(vcpu);
 	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
 }
+
+int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	bool pending = false;
+
+	if (!vcpu->kvm->arch.vgic.enabled)
+		return false;
+
+	spin_lock(&vgic_cpu->ap_list_lock);
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+		pending = irq->pending && irq->enabled;
+		spin_unlock(&irq->irq_lock);
+
+		if (pending)
+			break;
+	}
+
+	spin_unlock(&vgic_cpu->ap_list_lock);
+
+	return pending;
+}
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:20 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:20 +0100
Subject: [PATCH v5 41/57] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_NR_IRQS
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-42-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_NR_IRQS group. This
modality is supported by both VGIC V2 and V3 KVM device as will be
other groups, hence the introduction of common helpers.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 83 +++++++++++++++++++++++++++++++++++--
 1 file changed, 79 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index ff332f3..05ff925 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -15,9 +15,69 @@
  */
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
+#include <linux/uaccess.h>
+#include "vgic.h"
 
 /* common helpers */
 
+static int vgic_set_common_attr(struct kvm_device *dev,
+				struct kvm_device_attr *attr)
+{
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 val;
+		int ret = 0;
+
+		if (get_user(val, uaddr))
+			return -EFAULT;
+
+		/*
+		 * We require:
+		 * - at least 32 SPIs on top of the 16 SGIs and 16 PPIs
+		 * - at most 1024 interrupts
+		 * - a multiple of 32 interrupts
+		 */
+		if (val < (VGIC_NR_PRIVATE_IRQS + 32) ||
+		    val > VGIC_MAX_RESERVED ||
+		    (val & 31))
+			return -EINVAL;
+
+		mutex_lock(&dev->kvm->lock);
+
+		if (vgic_ready(dev->kvm) || dev->kvm->arch.vgic.nr_spis)
+			ret = -EBUSY;
+		else
+			dev->kvm->arch.vgic.nr_spis =
+				val - VGIC_NR_PRIVATE_IRQS;
+
+		mutex_unlock(&dev->kvm->lock);
+
+		return ret;
+	}
+	}
+
+	return -ENXIO;
+}
+
+static int vgic_get_common_attr(struct kvm_device *dev,
+				struct kvm_device_attr *attr)
+{
+	int r = -ENXIO;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+
+		r = put_user(dev->kvm->arch.vgic.nr_spis +
+			     VGIC_NR_PRIVATE_IRQS, uaddr);
+		break;
+	}
+	}
+
+	return r;
+}
+
 static int vgic_create(struct kvm_device *dev, u32 type)
 {
 	return kvm_vgic_create(dev->kvm, type);
@@ -49,18 +109,29 @@ void kvm_register_vgic_device(unsigned long type)
 static int vgic_v2_set_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	int ret;
+
+	ret = vgic_set_common_attr(dev, attr);
+	return ret;
+
 }
 
 static int vgic_v2_get_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	int ret;
+
+	ret = vgic_get_common_attr(dev, attr);
+	return ret;
 }
 
 static int vgic_v2_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
+		return 0;
+	}
 	return -ENXIO;
 }
 
@@ -80,18 +151,22 @@ struct kvm_device_ops kvm_arm_vgic_v2_ops = {
 static int vgic_v3_set_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	return vgic_set_common_attr(dev, attr);
 }
 
 static int vgic_v3_get_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	return vgic_get_common_attr(dev, attr);
 }
 
 static int vgic_v3_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
+		return 0;
+	}
 	return -ENXIO;
 }
 
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:55 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:55 +0100
Subject: [PATCH v5 16/57] KVM: arm/arm64: vgic-new: Add acccessor to new
 struct vgic_irq instance
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-17-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

The new VGIC implementation centers around a struct vgic_irq instance
per virtual IRQ.
Provide a function to retrieve the right instance for a given IRQ
number and (in case of private interrupts) the right VCPU.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/vgic/vgic.c | 41 +++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h | 22 ++++++++++++++++++++++
 2 files changed, 63 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic.c
 create mode 100644 virt/kvm/arm/vgic/vgic.h

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
new file mode 100644
index 0000000..fb45537
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
+
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
+			      u32 intid)
+{
+	/* SGIs and PPIs */
+	if (intid <= VGIC_MAX_PRIVATE)
+		return &vcpu->arch.vgic_cpu.private_irqs[intid];
+
+	/* SPIs */
+	if (intid <= VGIC_MAX_SPI)
+		return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS];
+
+	/* LPIs are not yet covered */
+	if (intid >= VGIC_MIN_LPI)
+		return NULL;
+
+	WARN(1, "Looking up struct vgic_irq for reserved INTID");
+	return NULL;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
new file mode 100644
index 0000000..61b8d22
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __KVM_ARM_VGIC_NEW_H__
+#define __KVM_ARM_VGIC_NEW_H__
+
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
+			      u32 intid);
+
+#endif
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:59 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:59 +0100
Subject: [PATCH v5 20/57] KVM: arm/arm64: vgic-new: Add GICv2 world switch
 backend
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-21-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Processing maintenance interrupts and accessing the list registers
are dependent on the host's GIC version.
Introduce vgic-v2.c to contain GICv2 specific functions.
Implement the GICv2 specific code for syncing the emulation state
into the VGIC registers.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
Changelog RFC..v1:
- remove explicit LR_STATE clearing on maintenance interrupt handling
- improve documentation for vgic_v2_populate_lr()
- remove WARN_ON on non-edge IRQs in maintenance interrupts
- simplify multi-CPU source SGI handling

Changelog v1 .. v2:
- inject the IRQ priority into the list register

Changelog v2 .. v3:
- cleanup diff containing rebase artifacts

Changelog v3 .. v4:
- remove ELRSR bit set during process_maintenance()

 include/linux/irqchip/arm-gic.h |   1 +
 virt/kvm/arm/vgic/vgic-v2.c     | 176 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c        |   6 ++
 virt/kvm/arm/vgic/vgic.h        |   6 ++
 4 files changed, 189 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-v2.c

diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 9c94026..be0d26f 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -76,6 +76,7 @@
 #define GICH_LR_VIRTUALID		(0x3ff << 0)
 #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
 #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
+#define GICH_LR_PRIORITY_SHIFT		23
 #define GICH_LR_STATE			(3 << 28)
 #define GICH_LR_PENDING_BIT		(1 << 28)
 #define GICH_LR_ACTIVE_BIT		(1 << 29)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
new file mode 100644
index 0000000..fb5e65c
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/irqchip/arm-gic.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+/*
+ * Call this function to convert a u64 value to an unsigned long * bitmask
+ * in a way that works on both 32-bit and 64-bit LE and BE platforms.
+ *
+ * Warning: Calling this function may modify *val.
+ */
+static unsigned long *u64_to_bitmask(u64 *val)
+{
+#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
+	*val = (*val >> 32) | (*val << 32);
+#endif
+	return (unsigned long *)val;
+}
+
+void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+
+	if (cpuif->vgic_misr & GICH_MISR_EOI) {
+		u64 eisr = cpuif->vgic_eisr;
+		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
+		int lr;
+
+		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
+			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
+
+			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
+
+			kvm_notify_acked_irq(vcpu->kvm, 0,
+					     intid - VGIC_NR_PRIVATE_IRQS);
+		}
+	}
+
+	/* check and disable underflow maintenance IRQ */
+	cpuif->vgic_hcr &= ~GICH_HCR_UIE;
+
+	/*
+	 * In the next iterations of the vcpu loop, if we sync the
+	 * vgic state after flushing it, but before entering the guest
+	 * (this happens for pending signals and vmid rollovers), then
+	 * make sure we don't pick up any old maintenance interrupts
+	 * here.
+	 */
+	cpuif->vgic_eisr = 0;
+}
+
+void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+
+	cpuif->vgic_hcr |= GICH_HCR_UIE;
+}
+
+/*
+ * transfer the content of the LRs back into the corresponding ap_list:
+ * - active bit is transferred as is
+ * - pending bit is
+ *   - transferred as is in case of edge sensitive IRQs
+ *   - set to the line-level (resample time) for level sensitive IRQs
+ */
+void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+	int lr;
+
+	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
+		u32 val = cpuif->vgic_lr[lr];
+		u32 intid = val & GICH_LR_VIRTUALID;
+		struct vgic_irq *irq;
+
+		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+
+		/* Always preserve the active bit */
+		irq->active = !!(val & GICH_LR_ACTIVE_BIT);
+
+		/* Edge is the only case where we preserve the pending bit */
+		if (irq->config == VGIC_CONFIG_EDGE &&
+		    (val & GICH_LR_PENDING_BIT)) {
+			irq->pending = true;
+
+			if (vgic_irq_is_sgi(intid)) {
+				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
+
+				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+				irq->source |= (1 << cpuid);
+			}
+		}
+
+		/* Clear soft pending state when level IRQs have been acked */
+		if (irq->config == VGIC_CONFIG_LEVEL &&
+		    !(val & GICH_LR_PENDING_BIT)) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+/*
+ * Populates the particular LR with the state of a given IRQ:
+ * - for an edge sensitive IRQ the pending state is cleared in struct vgic_irq
+ * - for a level sensitive IRQ the pending state value is unchanged;
+ *   it is dictated directly by the input level
+ *
+ * If @irq describes an SGI with multiple sources, we choose the
+ * lowest-numbered source VCPU and clear that bit in the source bitmap.
+ *
+ * The irq_lock must be held by the caller.
+ */
+void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
+{
+	u32 val = irq->intid;
+
+	if (irq->pending) {
+		val |= GICH_LR_PENDING_BIT;
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			irq->pending = false;
+
+		if (vgic_irq_is_sgi(irq->intid)) {
+			u32 src = ffs(irq->source);
+
+			BUG_ON(!src);
+			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
+			irq->source &= ~(1 << (src - 1));
+			if (irq->source)
+				irq->pending = true;
+		}
+	}
+
+	if (irq->active)
+		val |= GICH_LR_ACTIVE_BIT;
+
+	if (irq->hw) {
+		val |= GICH_LR_HW;
+		val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
+	} else {
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			val |= GICH_LR_EOI;
+	}
+
+	/* The GICv2 LR only holds five bits of priority. */
+	val |= (irq->priority >> 3) << GICH_LR_PRIORITY_SHIFT;
+
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = val;
+}
+
+void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 2e048a4..7a9e25d 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -400,10 +400,12 @@ retry:
 
 static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_process_maintenance(vcpu);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_fold_lr_state(vcpu);
 }
 
 /* Requires the irq_lock to be held. */
@@ -411,14 +413,18 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
 				    struct vgic_irq *irq, int lr)
 {
 	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+	vgic_v2_populate_lr(vcpu, irq, lr);
 }
 
 static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
+	vgic_v2_clear_lr(vcpu, lr);
 }
 
 static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_set_underflow(vcpu);
 }
 
 /* Requires the ap_list_lock to be held. */
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 29b96b9..0db490e 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -22,4 +22,10 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
 
+void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
+void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
+void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
+void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
+void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:04 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:04 +0100
Subject: [PATCH v5 25/57] KVM: arm/arm64: vgic-new: Add CTLR,
 TYPER and IIDR handlers
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-26-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Those three registers are v2 emulation specific, so their implementation
lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
as their implementation is pretty simple.
When the guest enables the distributor, we kick all VCPUs to get
potentially pending interrupts serviced.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- kick VCPUs is the distributor gets enabled
- improve comment

Changelog v1 .. v2:
- adapt to new MMIO framework
- use switch() statements to improve readability

Changelog v2 .. v3:
- add vgic_kick_vcpus() implementation

Changelog v3 .. v4;
- specify accessor width
- simplify CTLR write access
- replace extract_bytes() with simple return

 include/linux/irqchip/arm-gic.h  |  1 +
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 46 +++++++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
 virt/kvm/arm/vgic/vgic.h         |  4 ++++
 4 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index be0d26f..fd05185 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -33,6 +33,7 @@
 
 #define GIC_DIST_CTRL			0x000
 #define GIC_DIST_CTR			0x004
+#define GIC_DIST_IIDR			0x008
 #define GIC_DIST_IGROUP			0x080
 #define GIC_DIST_ENABLE_SET		0x100
 #define GIC_DIST_ENABLE_CLEAR		0x180
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index a3e31a9..d812c93 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -20,9 +20,53 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 value;
+
+	switch (addr & 0x0c) {
+	case GIC_DIST_CTRL:
+		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
+		break;
+	case GIC_DIST_CTR:
+		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+		value = (value >> 5) - 1;
+		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
+		break;
+	case GIC_DIST_IIDR:
+		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+		break;
+	default:
+		return 0;
+	}
+
+	return value;
+}
+
+static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+	bool was_enabled = dist->enabled;
+
+	switch (addr & 0x0c) {
+	case GIC_DIST_CTRL:
+		dist->enabled = val & GICD_ENABLE;
+		if (!was_enabled && dist->enabled)
+			vgic_kick_vcpus(vcpu->kvm);
+		break;
+	case GIC_DIST_CTR:
+	case GIC_DIST_IIDR:
+		/* Nothing to do */
+		return;
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 12,
+		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 48fdaf3..067c56e 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -545,3 +545,18 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 
 	return pending;
 }
+
+void vgic_kick_vcpus(struct kvm *kvm)
+{
+	struct kvm_vcpu *vcpu;
+	int c;
+
+	/*
+	 * We've injected an interrupt, time to find out who deserves
+	 * a good kick...
+	 */
+	kvm_for_each_vcpu(c, vcpu, kvm) {
+		if (kvm_vgic_vcpu_pending_irq(vcpu))
+			kvm_vcpu_kick(vcpu);
+	}
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index fd9acaa..cf62015 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,11 +16,15 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
+#define IMPLEMENTER_ARM		0x43b
+
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
+void vgic_kick_vcpus(struct kvm *kvm);
 
 void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
 void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:21 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:21 +0100
Subject: [PATCH v5 42/57] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_CTRL
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-43-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_CTRL group API
featuring KVM_DEV_ARM_VGIC_CTRL_INIT attribute. The vgic_init
function is not yet implemented though.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 05ff925..e153f12 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -23,6 +23,8 @@
 static int vgic_set_common_attr(struct kvm_device *dev,
 				struct kvm_device_attr *attr)
 {
+	int r;
+
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
@@ -55,6 +57,16 @@ static int vgic_set_common_attr(struct kvm_device *dev,
 
 		return ret;
 	}
+	case KVM_DEV_ARM_VGIC_GRP_CTRL: {
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			mutex_lock(&dev->kvm->lock);
+			r = vgic_init(dev->kvm);
+			mutex_unlock(&dev->kvm->lock);
+			return r;
+		}
+		break;
+	}
 	}
 
 	return -ENXIO;
@@ -131,6 +143,11 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
+	case KVM_DEV_ARM_VGIC_GRP_CTRL:
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			return 0;
+		}
 	}
 	return -ENXIO;
 }
@@ -166,6 +183,11 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
+	case KVM_DEV_ARM_VGIC_GRP_CTRL:
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			return 0;
+		}
 	}
 	return -ENXIO;
 }
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:23 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:23 +0100
Subject: [PATCH v5 44/57] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_ADDR
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-45-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_ADDR group which
enables to set the base address of GIC regions as seen by the guest.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 38 +++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 082829a..a709097 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -112,6 +112,17 @@ static int vgic_set_common_attr(struct kvm_device *dev,
 	int r;
 
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 addr;
+		unsigned long type = (unsigned long)attr->attr;
+
+		if (copy_from_user(&addr, uaddr, sizeof(addr)))
+			return -EFAULT;
+
+		r = kvm_vgic_addr(dev->kvm, type, &addr, true);
+		return (r == -ENODEV) ? -ENXIO : r;
+	}
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
 		u32 val;
@@ -164,6 +175,19 @@ static int vgic_get_common_attr(struct kvm_device *dev,
 	int r = -ENXIO;
 
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 addr;
+		unsigned long type = (unsigned long)attr->attr;
+
+		r = kvm_vgic_addr(dev->kvm, type, &addr, false);
+		if (r)
+			return (r == -ENODEV) ? -ENXIO : r;
+
+		if (copy_to_user(uaddr, &addr, sizeof(addr)))
+			return -EFAULT;
+		break;
+	}
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
 
@@ -227,6 +251,13 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR:
+		switch (attr->attr) {
+		case KVM_VGIC_V2_ADDR_TYPE_DIST:
+		case KVM_VGIC_V2_ADDR_TYPE_CPU:
+			return 0;
+		}
+		break;
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
@@ -267,6 +298,13 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR:
+		switch (attr->attr) {
+		case KVM_VGIC_V3_ADDR_TYPE_DIST:
+		case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+			return 0;
+		}
+		break;
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:53 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:53 +0100
Subject: [PATCH v5 14/57] KVM: arm/arm64: move GICv2 emulation defines into
 arm-gic-v3.h
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-15-git-send-email-andre.przywara@arm.com>

As (some) GICv3 hosts can emulate a GICv2, some GICv2 specific masks
for the list register definition also apply to GICv3 LRs.
At the moment we have those definitions in the KVM VGICv3
implementation, so let's move them into the GICv3 header file to
have them automatically defined.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
---
 include/linux/irqchip/arm-gic-v3.h | 5 +++++
 virt/kvm/arm/vgic-v3.c             | 8 +-------
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index d5d798b..ec938d1 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -276,6 +276,11 @@
 #define ICH_LR_PHYS_ID_SHIFT		32
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
 
+/* These are for GICv2 emulation only */
+#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
+#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
+#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
+
 #define ICH_MISR_EOI			(1 << 0)
 #define ICH_MISR_U			(1 << 1)
 
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index c02a1b1..75b02fa 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -29,12 +29,6 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmu.h>
 
-/* These are for GICv2 emulation only */
-#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
-#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
-#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
-#define ICH_LR_VIRTUALID_MASK		(BIT_ULL(32) - 1)
-
 static u32 ich_vtr_el2;
 
 static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
@@ -43,7 +37,7 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
 	u64 val = vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr];
 
 	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
-		lr_desc.irq = val & ICH_LR_VIRTUALID_MASK;
+		lr_desc.irq = val & ICH_LR_VIRTUAL_ID_MASK;
 	else
 		lr_desc.irq = val & GICH_LR_VIRTUALID;
 
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:08 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:08 +0100
Subject: [PATCH v5 29/57] KVM: arm/arm64: vgic-new: Add PRIORITY registers
 handlers
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-30-git-send-email-andre.przywara@arm.com>

The priority register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.
There is a corner case when we change the priority of a pending
interrupt which we don't handle at the moment.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 40 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  7 +++++++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 4 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 12e101b..d564a30 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -90,7 +90,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 79a4622..6f4e05b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -236,6 +236,46 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
+				      gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->priority << (i * 8);
+	}
+
+	return val;
+}
+
+/*
+ * We currently don't handle changing the priority of an interrupt that
+ * is already pending on a VCPU. If there is a need for this, we would
+ * need to make this VCPU exit and re-evaluate the priorities, potentially
+ * leading to this interrupt getting presented now to the guest (if it has
+ * been masked by the priority mask before).
+ */
+void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		/* Narrow the priority range to what we actually support */
+		irq->priority = (val >> (i * 8)) & GENMASK(7, 8 - VGIC_PRI_BITS);
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 90146c7..62ecec0 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -129,6 +129,13 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val);
 
+unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
+				      gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index cf62015..e57f8d5 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,8 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define VGIC_PRI_BITS		5
+
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:07:52 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:07:52 +0100
Subject: [PATCH v5 13/57] KVM: arm/arm64: Provide functionality to pause and
 resume a guest
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-14-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

For some rare corner cases in our VGIC emulation later we have to stop
the guest to make sure the VGIC state is consistent.
Provide the necessary framework to pause and resume a guest.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/include/asm/kvm_host.h   |  4 ++++
 arch/arm/kvm/arm.c                | 25 +++++++++++++------------
 arch/arm64/include/asm/kvm_host.h |  4 ++++
 3 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 3850701..832be03 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -41,6 +41,8 @@
 
 #define KVM_MAX_VCPUS VGIC_V2_MAX_CPUS
 
+#define KVM_REQ_VCPU_EXIT	8
+
 u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode);
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
@@ -225,6 +227,8 @@ static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
 
 struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
+void kvm_arm_halt_guest(struct kvm *kvm);
+void kvm_arm_resume_guest(struct kvm *kvm);
 
 int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
 unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index ceb9345..e89329d 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -492,30 +492,31 @@ bool kvm_arch_intc_initialized(struct kvm *kvm)
 	return vgic_initialized(kvm);
 }
 
-static void kvm_arm_halt_guest(struct kvm *kvm) __maybe_unused;
-static void kvm_arm_resume_guest(struct kvm *kvm) __maybe_unused;
-
-static void kvm_arm_halt_guest(struct kvm *kvm)
+void kvm_arm_halt_guest(struct kvm *kvm)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
 
 	kvm_for_each_vcpu(i, vcpu, kvm)
 		vcpu->arch.pause = true;
-	force_vm_exit(cpu_all_mask);
+	kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT);
+}
+
+static void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
+{
+	struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
+
+	vcpu->arch.pause = false;
+	swake_up(wq);
 }
 
-static void kvm_arm_resume_guest(struct kvm *kvm)
+void kvm_arm_resume_guest(struct kvm *kvm)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
 
-	kvm_for_each_vcpu(i, vcpu, kvm) {
-		struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
-
-		vcpu->arch.pause = false;
-		swake_up(wq);
-	}
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_arm_resume_vcpu(vcpu);
 }
 
 static void vcpu_sleep(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 4cd4196..fa94f91 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -44,6 +44,8 @@
 
 #define KVM_VCPU_MAX_FEATURES 4
 
+#define KVM_REQ_VCPU_EXIT	8
+
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
 int kvm_arch_dev_ioctl_check_extension(long ext);
@@ -325,6 +327,8 @@ static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
 
 struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
+void kvm_arm_halt_guest(struct kvm *kvm);
+void kvm_arm_resume_guest(struct kvm *kvm);
 
 u64 __kvm_call_hyp(void *hypfn, ...);
 #define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__)
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:16 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:16 +0100
Subject: [PATCH v5 37/57] KVM: arm/arm64: vgic-new: Add GICv3 IDREGS register
 handler
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-38-git-send-email-andre.przywara@arm.com>

We implement the only one ID register that is required by the
architecture, also this is the one that Linux actually checks.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v3.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 16942e8..abf0d8d 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -96,6 +96,18 @@ static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
 	return (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
 }
 
+static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu,
+					      gpa_t addr, unsigned int len)
+{
+	switch (addr & 0xffff) {
+	case GICD_PIDR2:
+		/* report a GICv3 compliant implementation */
+		return 0x3b;
+	}
+
+	return 0;
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -161,7 +173,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
 		VGIC_ACCESS_32bit),
 };
 
@@ -182,7 +194,7 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
 		VGIC_ACCESS_32bit),
 };
 
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:11 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:11 +0100
Subject: [PATCH v5 32/57] KVM: arm/arm64: vgic-new: Add SGIR register handler
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-33-git-send-email-andre.przywara@arm.com>

Triggering an IPI via this register is v2 specific, so the
implementation lives entirely in vgic-mmio-v2.c.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- silently return on illegal TargetListFilter value (=3)

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 52389ff..c884e9b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -64,6 +64,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
+				 gpa_t addr, unsigned int len,
+				 unsigned long val)
+{
+	int nr_vcpus = atomic_read(&source_vcpu->kvm->online_vcpus);
+	int intid = val & 0xf;
+	int targets = (val >> 16) & 0xff;
+	int mode = (val >> 24) & 0x03;
+	int c;
+	struct kvm_vcpu *vcpu;
+
+	switch (mode) {
+	case 0x0:		/* as specified by targets */
+		break;
+	case 0x1:
+		targets = (1U << nr_vcpus) - 1;			/* all, ... */
+		targets &= ~(1U << source_vcpu->vcpu_id);	/* but self */
+		break;
+	case 0x2:		/* this very vCPU only */
+		targets = (1U << source_vcpu->vcpu_id);
+		break;
+	case 0x3:		/* reserved */
+		return;
+	}
+
+	kvm_for_each_vcpu(c, vcpu, source_vcpu->kvm) {
+		struct vgic_irq *irq;
+
+		if (!(targets & (1U << c)))
+			continue;
+
+		irq = vgic_get_irq(source_vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+		irq->source |= 1U << source_vcpu->vcpu_id;
+
+		vgic_queue_irq_unlock(source_vcpu->kvm, irq);
+	}
+}
+
 static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
 					   gpa_t addr, unsigned int len)
 {
@@ -140,7 +181,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_config, vgic_mmio_write_config, 2,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:09 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:09 +0100
Subject: [PATCH v5 30/57] KVM: arm/arm64: vgic-new: Add CONFIG registers
 handlers
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-31-git-send-email-andre.przywara@arm.com>

The config register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro
- replace extract_bytes() with simple return

Changelog v4 .. v5:
- make PPIs CONFIG register access read-only

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 47 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  7 ++++++
 3 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index d564a30..bb7389e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -96,7 +96,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 2,
+		vgic_mmio_read_config, vgic_mmio_write_config, 2,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 6f4e05b..9de80be 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -276,6 +276,53 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 2);
+	u32 value = 0;
+	int i;
+
+	for (i = 0; i < len * 4; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			value |= (2U << (i * 2));
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
+			    gpa_t addr, unsigned int len,
+			    unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 2);
+	int i;
+
+	for (i = 0; i < len * 4; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		/*
+		 * The configuration cannot be changed for SGIs in general,
+		 * for PPIs this is IMPLEMENTATION DEFINED. The arch timer
+		 * code relies on PPIs being level triggered, so we also
+		 * make them read-only here.
+		 */
+		if (intid + i < VGIC_NR_PRIVATE_IRQS)
+			continue;
+
+		spin_lock(&irq->irq_lock);
+		if (test_bit(i * 2 + 1, &val)) {
+			irq->config = VGIC_CONFIG_EDGE;
+		} else {
+			irq->config = VGIC_CONFIG_LEVEL;
+			irq->pending = irq->line_level | irq->soft_pending;
+		}
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 62ecec0..5e4a3e4 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -136,6 +136,13 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
 			      gpa_t addr, unsigned int len,
 			      unsigned long val);
 
+unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
+			    gpa_t addr, unsigned int len,
+			    unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:27 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:27 +0100
Subject: [PATCH v5 48/57] KVM: arm/arm64: vgic-new: Add GICH_VMCR accessors
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-49-git-send-email-andre.przywara@arm.com>

Since the GIC CPU interface is always virtualized by the hardware,
we don't have CPU interface state information readily available in our
emulation if userland wants to save or restore it.
Fortunately the GIC hypervisor interface provides the VMCR register to
access the required virtual CPU interface bits.
Provide wrappers for GICv2 and GICv3 hosts to have access to this
register.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v2 .. v3:
- remove exported v2/v3 selector functions (as per Marc's patch)

Changelog v3 .. v4:
- move struct vgic_vmcr into the VGIC's private header file

 virt/kvm/arm/vgic/vgic-v2.c | 29 +++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c | 22 ++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h    | 21 +++++++++++++++++++++
 3 files changed, 72 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index fb5e65c..d943059 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -174,3 +174,32 @@ void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
 	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
 }
+
+void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr;
+
+	vmcr  = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK;
+	vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) &
+		GICH_VMCR_ALIAS_BINPOINT_MASK;
+	vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) &
+		GICH_VMCR_BINPOINT_MASK;
+	vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) &
+		GICH_VMCR_PRIMASK_MASK;
+
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = vmcr;
+}
+
+void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr;
+
+	vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >>
+			GICH_VMCR_CTRL_SHIFT;
+	vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >>
+			GICH_VMCR_ALIAS_BINPOINT_SHIFT;
+	vmcrp->bpr  = (vmcr & GICH_VMCR_BINPOINT_MASK) >>
+			GICH_VMCR_BINPOINT_SHIFT;
+	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
+			GICH_VMCR_PRIMASK_SHIFT;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index fb547da..8548297 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -160,3 +160,25 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
 	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
 }
+
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr;
+
+	vmcr  = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK;
+	vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
+	vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
+	vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
+
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
+}
+
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
+
+	vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT;
+	vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
+	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
+	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index f826026..d2c1fd5 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -27,6 +27,13 @@
 
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
+struct vgic_vmcr {
+	u32	ctlr;
+	u32	abpr;
+	u32	bpr;
+	u32	pmr;
+};
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
@@ -40,6 +47,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val);
+void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -49,6 +58,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -72,6 +83,16 @@ static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 }
 
+static inline
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+}
+
+static inline
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:28 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:28 +0100
Subject: [PATCH v5 49/57] KVM: arm/arm64: vgic-new: Add userland GIC CPU
 interface access
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-50-git-send-email-andre.przywara@arm.com>

To allow userland access to the GIC CPU interface state, we use handler
functions similar to what we use for the distributor and connect those
to the VMCR accessors on one side and our userland access framework on
the other side.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v2 .. v3:
- total rework, moving into vgic-mmio-v2.c
- move vmcr accessor wrapper functions into this file
- use the register description table for CPU i/f registers as well
- add RAZ/WI handling for the active priority registers
- streamline MMIO handler functions

Changelog v3 .. v4:
- advertise CPU interface registers to userland
- specify accessor width
- replace call to extract_bytes() with a simple return

 virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 114 +++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.h            |   2 +
 3 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 9ee27cb..0130c4b 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -274,7 +274,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		ret = -EINVAL;
+		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
 		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index a255122..a213936 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -204,6 +204,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_set_vmcr(vcpu, vmcr);
+	else
+		vgic_v3_set_vmcr(vcpu, vmcr);
+}
+
+static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_get_vmcr(vcpu, vmcr);
+	else
+		vgic_v3_get_vmcr(vcpu, vmcr);
+}
+
+#define GICC_ARCH_VERSION_V2	0x2
+
+/* These are for userland accesses only, there is no guest-facing emulation. */
+static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
+					   gpa_t addr, unsigned int len)
+{
+	struct vgic_vmcr vmcr;
+	u32 val;
+
+	vgic_get_vmcr(vcpu, &vmcr);
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		val = vmcr.ctlr;
+		break;
+	case GIC_CPU_PRIMASK:
+		val = vmcr.pmr;
+		break;
+	case GIC_CPU_BINPOINT:
+		val = vmcr.bpr;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		val = vmcr.abpr;
+		break;
+	case GIC_CPU_IDENT:
+		val = ((PRODUCT_ID_KVM << 20) |
+		       (GICC_ARCH_VERSION_V2 << 16) |
+		       IMPLEMENTER_ARM);
+		break;
+	default:
+		return 0;
+	}
+
+	return val;
+}
+
+static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
+				   gpa_t addr, unsigned int len,
+				   unsigned long val)
+{
+	struct vgic_vmcr vmcr;
+
+	vgic_get_vmcr(vcpu, &vmcr);
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		vmcr.ctlr = val;
+		break;
+	case GIC_CPU_PRIMASK:
+		vmcr.pmr = val;
+		break;
+	case GIC_CPU_BINPOINT:
+		vmcr.bpr = val;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		vmcr.abpr = val;
+		break;
+	}
+
+	vgic_set_vmcr(vcpu, &vmcr);
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
@@ -249,6 +327,27 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 };
 
+static const struct vgic_register_region vgic_v2_cpu_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_CTRL,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_PRIMASK,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ALIAS_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ACTIVEPRIO,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_IDENT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+};
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
 {
 	dev->regions = vgic_v2_dist_registers;
@@ -274,7 +373,9 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		return -ENXIO;		/* TODO: describe CPU i/f regs also */
+		regions = vgic_v2_cpu_registers;
+		nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers);
+		break;
 	default:
 		return -ENXIO;
 	}
@@ -322,6 +423,17 @@ static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
 	return ret;
 }
 
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_cpu_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
+
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val)
 {
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index d2c1fd5..de9dc71 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -47,6 +47,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val);
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:29 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:29 +0100
Subject: [PATCH v5 50/57] KVM: arm/arm64: vgic-new: vgic_init: implement
 kvm_vgic_hyp_init
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-51-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

Implements kvm_vgic_hyp_init and vgic_probe function.
This uses the new firmware independent VGIC probing to support both ACPI
and DT based systems (code from Marc Zyngier).

The vgic_global struct is enriched with new fields populated
by those functions.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v1 .. v2:
- rename vgic_init.c to vgic-init.c

Changelog v2 .. v3:
- include kvm/arm_vgic.h instead of kvm/vgic/vgic.h
- move ich_vtr_el2 variable into probe function

Changelog v3 .. v4:
- improve nr_lr determination in GICv2 probe
- switching to firmware-independent probing

 include/kvm/vgic/vgic.h       |   1 +
 virt/kvm/arm/vgic/vgic-init.c | 123 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   |  64 ++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c   |  49 +++++++++++++++++
 virt/kvm/arm/vgic/vgic.h      |   9 ++++
 5 files changed, 246 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-init.c

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 3689b9b..393489f 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -195,6 +195,7 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
new file mode 100644
index 0000000..4523beb
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/cpu.h>
+#include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
+#include "vgic.h"
+
+/* GENERIC PROBE */
+
+static void vgic_init_maintenance_interrupt(void *info)
+{
+	enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0);
+}
+
+static int vgic_cpu_notify(struct notifier_block *self,
+			   unsigned long action, void *cpu)
+{
+	switch (action) {
+	case CPU_STARTING:
+	case CPU_STARTING_FROZEN:
+		vgic_init_maintenance_interrupt(NULL);
+		break;
+	case CPU_DYING:
+	case CPU_DYING_FROZEN:
+		disable_percpu_irq(kvm_vgic_global_state.maint_irq);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block vgic_cpu_nb = {
+	.notifier_call = vgic_cpu_notify,
+};
+
+static irqreturn_t vgic_maintenance_handler(int irq, void *data)
+{
+	/*
+	 * We cannot rely on the vgic maintenance interrupt to be
+	 * delivered synchronously. This means we can only use it to
+	 * exit the VM, and we perform the handling of EOIed
+	 * interrupts on the exit path (see vgic_process_maintenance).
+	 */
+	return IRQ_HANDLED;
+}
+
+/**
+ * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable
+ * according to the host GIC model. Accordingly calls either
+ * vgic_v2/v3_probe which registers the KVM_DEVICE that can be
+ * instantiated by a guest later on .
+ */
+int kvm_vgic_hyp_init(void)
+{
+	const struct gic_kvm_info *gic_kvm_info;
+	int ret;
+
+	gic_kvm_info = gic_get_kvm_info();
+	if (!gic_kvm_info)
+		return -ENODEV;
+
+	if (!gic_kvm_info->maint_irq) {
+		kvm_err("No vgic maintenance irq\n");
+		return -ENXIO;
+	}
+
+	switch (gic_kvm_info->type) {
+	case GIC_V2:
+		ret = vgic_v2_probe(gic_kvm_info);
+		break;
+	case GIC_V3:
+		ret = vgic_v3_probe(gic_kvm_info);
+		break;
+	default:
+		ret = -ENODEV;
+	};
+
+	if (ret)
+		return ret;
+
+	kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
+	ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
+				 vgic_maintenance_handler,
+				 "vgic", kvm_get_running_vcpus());
+	if (ret) {
+		kvm_err("Cannot register interrupt %d\n",
+			kvm_vgic_global_state.maint_irq);
+		return ret;
+	}
+
+	ret = __register_cpu_notifier(&vgic_cpu_nb);
+	if (ret) {
+		kvm_err("Cannot register vgic CPU notifier\n");
+		goto out_free_irq;
+	}
+
+	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
+
+	kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq);
+	return 0;
+
+out_free_irq:
+	free_percpu_irq(kvm_vgic_global_state.maint_irq,
+			kvm_get_running_vcpus());
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index d943059..09777c8 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -17,6 +17,8 @@
 #include <linux/irqchip/arm-gic.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
 
 #include "vgic.h"
 
@@ -203,3 +205,65 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
 			GICH_VMCR_PRIMASK_SHIFT;
 }
+
+/**
+ * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
+ * @node:	pointer to the DT node
+ *
+ * Returns 0 if a GICv2 has been found, returns an error code otherwise
+ */
+int vgic_v2_probe(const struct gic_kvm_info *info)
+{
+	int ret;
+	u32 vtr;
+
+	if (!info->vctrl.start) {
+		kvm_err("GICH not present in the firmware table\n");
+		return -ENXIO;
+	}
+
+	if (!PAGE_ALIGNED(info->vcpu.start)) {
+		kvm_err("GICV physical address 0x%llx not page aligned\n",
+			(unsigned long long)info->vcpu.start);
+		return -ENXIO;
+	}
+
+	if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
+		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+			(unsigned long long)resource_size(&info->vcpu),
+			PAGE_SIZE);
+		return -ENXIO;
+	}
+
+	kvm_vgic_global_state.vctrl_base = ioremap(info->vctrl.start,
+						   resource_size(&info->vctrl));
+	if (!kvm_vgic_global_state.vctrl_base) {
+		kvm_err("Cannot ioremap GICH\n");
+		return -ENOMEM;
+	}
+
+	vtr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
+	kvm_vgic_global_state.nr_lr = (vtr & 0x3f) + 1;
+
+	ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
+				     kvm_vgic_global_state.vctrl_base +
+					 resource_size(&info->vctrl),
+				     info->vctrl.start);
+
+	if (ret) {
+		kvm_err("Cannot map VCTRL into hyp\n");
+		iounmap(kvm_vgic_global_state.vctrl_base);
+		return ret;
+	}
+
+	kvm_vgic_global_state.can_emulate_gicv2 = true;
+	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+
+	kvm_vgic_global_state.vcpu_base = info->vcpu.start;
+	kvm_vgic_global_state.type = VGIC_V2;
+	kvm_vgic_global_state.max_gic_vcpus = VGIC_V2_MAX_CPUS;
+
+	kvm_info("vgic-v2@%llx\n", info->vctrl.start);
+
+	return 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 8548297..de0e8e0 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -15,6 +15,9 @@
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
+#include <asm/kvm_asm.h>
 
 #include "vgic.h"
 
@@ -182,3 +185,49 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
+
+/**
+ * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
+ * @node:	pointer to the DT node
+ *
+ * Returns 0 if a GICv3 has been found, returns an error code otherwise
+ */
+int vgic_v3_probe(const struct gic_kvm_info *info)
+{
+	u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
+
+	/*
+	 * The ListRegs field is 5 bits, but there is a architectural
+	 * maximum of 16 list registers. Just ignore bit 4...
+	 */
+	kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
+	kvm_vgic_global_state.can_emulate_gicv2 = false;
+
+	if (!info->vcpu.start) {
+		kvm_info("GICv3: no GICV resource entry\n");
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else if (!PAGE_ALIGNED(info->vcpu.start)) {
+		pr_warn("GICV physical address 0x%llx not page aligned\n",
+			(unsigned long long)info->vcpu.start);
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
+		pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+			(unsigned long long)resource_size(&info->vcpu),
+			PAGE_SIZE);
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else {
+		kvm_vgic_global_state.vcpu_base = info->vcpu.start;
+		kvm_vgic_global_state.can_emulate_gicv2 = true;
+		kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+		kvm_info("vgic-v2@%llx\n", info->vcpu.start);
+	}
+	if (kvm_vgic_global_state.vcpu_base == 0)
+		kvm_info("disabling GICv2 emulation\n");
+	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V3);
+
+	kvm_vgic_global_state.vctrl_base = NULL;
+	kvm_vgic_global_state.type = VGIC_V3;
+	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
+
+	return 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index de9dc71..f4244b6 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,6 +16,8 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#include <linux/irqchip/arm-gic-common.h>
+
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
@@ -51,6 +53,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+int vgic_v2_probe(const struct gic_kvm_info *info);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -62,6 +65,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+int vgic_v3_probe(const struct gic_kvm_info *info);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -95,6 +99,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
 {
 }
 
+static inline int vgic_v3_probe(const struct gic_kvm_info *info)
+{
+	return -ENODEV;
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:31 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:31 +0100
Subject: [PATCH v5 52/57] KVM: arm/arm64: vgic-new: vgic_init: implement
 vgic_init
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-53-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch allocates and initializes the data structures used
to model the vgic distributor and virtual cpu interfaces. At that
stage the number of IRQs and number of virtual CPUs is frozen.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- initialize v2/v3 default CPU affinities explicitly

Changelog v1 .. v2:
- move lazy_init() into vgic_update_irq_pending()

Changelog v3 .. v4:
- fix comments
- make local functions static
- adapt to new firmware independent probing

 include/kvm/vgic/vgic.h       |   7 +-
 virt/kvm/arm/vgic/vgic-init.c | 217 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   |   5 +
 virt/kvm/arm/vgic/vgic-v3.c   |   5 +
 virt/kvm/arm/vgic/vgic.c      |   4 +
 virt/kvm/arm/vgic/vgic.h      |   8 ++
 6 files changed, 245 insertions(+), 1 deletion(-)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 0634d89..e7ae36b 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -119,6 +119,7 @@ struct vgic_io_device {
 struct vgic_dist {
 	bool			in_kernel;
 	bool			ready;
+	bool			initialized;
 
 	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
 	u32			vgic_model;
@@ -195,7 +196,11 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+void kvm_vgic_early_init(struct kvm *kvm);
 int kvm_vgic_create(struct kvm *kvm, u32 type);
+void kvm_vgic_destroy(struct kvm *kvm);
+void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
+void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
@@ -204,7 +209,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
-#define vgic_initialized(k)	(false)
+#define vgic_initialized(k)	((k)->arch.vgic.initialized)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
 #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
 			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 15d5428..bed3240 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -22,6 +22,42 @@
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
+/*
+ * Initialization rules: there are multiple stages to the vgic
+ * initialization, both for the distributor and the CPU interfaces.
+ *
+ * Distributor:
+ *
+ * - kvm_vgic_early_init(): initialization of static data that doesn't
+ *   depend on any sizing information or emulation type. No allocation
+ *   is allowed there.
+ *
+ * - vgic_init(): allocation and initialization of the generic data
+ *   structures that depend on sizing information (number of CPUs,
+ *   number of interrupts). Also initializes the vcpu specific data
+ *   structures. Can be executed lazily for GICv2.
+ *
+ * CPU Interface:
+ *
+ * - kvm_vgic_cpu_early_init(): initialization of static data that
+ *   doesn't depend on any sizing information or emulation type. No
+ *   allocation is allowed there.
+ */
+
+/* EARLY INIT */
+
+/*
+ * Those 2 functions should not be needed anymore but they
+ * still are called from arm.c
+ */
+void kvm_vgic_early_init(struct kvm *kvm)
+{
+}
+
+void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu)
+{
+}
+
 /* CREATION */
 
 /**
@@ -29,6 +65,8 @@
  * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only)
  * or through the generic KVM_CREATE_DEVICE API ioctl.
  * irqchip_in_kernel() tells you if this function succeeded or not.
+ * @kvm: kvm struct pointer
+ * @type: KVM_DEV_TYPE_ARM_VGIC_V[23]
  */
 int kvm_vgic_create(struct kvm *kvm, u32 type)
 {
@@ -106,6 +144,185 @@ out:
 	return ret;
 }
 
+/* INIT/DESTROY */
+
+/**
+ * kvm_vgic_dist_init: initialize the dist data structures
+ * @kvm: kvm struct pointer
+ * @nr_spis: number of spis, frozen by caller
+ */
+static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct kvm_vcpu *vcpu0 = kvm_get_vcpu(kvm, 0);
+	int i;
+
+	dist->spis = kcalloc(nr_spis, sizeof(struct vgic_irq), GFP_KERNEL);
+	if (!dist->spis)
+		return  -ENOMEM;
+
+	/*
+	 * In the following code we do not take the irq struct lock since
+	 * no other action on irq structs can happen while the VGIC is
+	 * not initialized yet:
+	 * If someone wants to inject an interrupt or does a MMIO access, we
+	 * require prior initialization in case of a virtual GICv3 or trigger
+	 * initialization when using a virtual GICv2.
+	 */
+	for (i = 0; i < nr_spis; i++) {
+		struct vgic_irq *irq = &dist->spis[i];
+
+		irq->intid = i + VGIC_NR_PRIVATE_IRQS;
+		INIT_LIST_HEAD(&irq->ap_list);
+		spin_lock_init(&irq->irq_lock);
+		irq->vcpu = NULL;
+		irq->target_vcpu = vcpu0;
+		if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+			irq->targets = 0;
+		else
+			irq->mpidr = 0;
+	}
+	return 0;
+}
+
+/**
+ * kvm_vgic_vcpu_init: initialize the vcpu data structures and
+ * enable the VCPU interface
+ * @vcpu: the VCPU which's VGIC should be initialized
+ */
+static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	int i;
+
+	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
+	spin_lock_init(&vgic_cpu->ap_list_lock);
+
+	/*
+	 * Enable and configure all SGIs to be edge-triggered and
+	 * configure all PPIs as level-triggered.
+	 */
+	for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
+		struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
+
+		INIT_LIST_HEAD(&irq->ap_list);
+		spin_lock_init(&irq->irq_lock);
+		irq->intid = i;
+		irq->vcpu = NULL;
+		irq->target_vcpu = vcpu;
+		irq->targets = 1U << vcpu->vcpu_id;
+		if (vgic_irq_is_sgi(i)) {
+			/* SGIs */
+			irq->enabled = 1;
+			irq->config = VGIC_CONFIG_EDGE;
+		} else {
+			/* PPIs */
+			irq->config = VGIC_CONFIG_LEVEL;
+		}
+	}
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_enable(vcpu);
+	else
+		vgic_v3_enable(vcpu);
+}
+
+/*
+ * vgic_init: allocates and initializes dist and vcpu data structures
+ * depending on two dimensioning parameters:
+ * - the number of spis
+ * - the number of vcpus
+ * The function is generally called when nr_spis has been explicitly set
+ * by the guest through the KVM DEVICE API. If not nr_spis is set to 256.
+ * vgic_initialized() returns true when this function has succeeded.
+ * Must be called with kvm->lock held!
+ */
+int vgic_init(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct kvm_vcpu *vcpu;
+	int ret = 0, i;
+
+	if (vgic_initialized(kvm))
+		return 0;
+
+	/* freeze the number of spis */
+	if (!dist->nr_spis)
+		dist->nr_spis = VGIC_NR_IRQS_LEGACY - VGIC_NR_PRIVATE_IRQS;
+
+	ret = kvm_vgic_dist_init(kvm, dist->nr_spis);
+	if (ret)
+		goto out;
+
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_vgic_vcpu_init(vcpu);
+
+	dist->initialized = true;
+out:
+	return ret;
+}
+
+static void kvm_vgic_dist_destroy(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+
+	mutex_lock(&kvm->lock);
+
+	dist->ready = false;
+	dist->initialized = false;
+
+	kfree(dist->spis);
+	kfree(dist->redist_iodevs);
+	dist->nr_spis = 0;
+
+	mutex_unlock(&kvm->lock);
+}
+
+void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
+}
+
+void kvm_vgic_destroy(struct kvm *kvm)
+{
+	struct kvm_vcpu *vcpu;
+	int i;
+
+	kvm_vgic_dist_destroy(kvm);
+
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_vgic_vcpu_destroy(vcpu);
+}
+
+/**
+ * vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest
+ * is a GICv2. A GICv3 must be explicitly initialized by the guest using the
+ * KVM_DEV_ARM_VGIC_GRP_CTRL KVM_DEVICE group.
+ * @kvm: kvm struct pointer
+ */
+int vgic_lazy_init(struct kvm *kvm)
+{
+	int ret = 0;
+
+	if (unlikely(!vgic_initialized(kvm))) {
+		/*
+		 * We only provide the automatic initialization of the VGIC
+		 * for the legacy case of a GICv2. Any other type must
+		 * be explicitly initialized once setup with the respective
+		 * KVM device call.
+		 */
+		if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2)
+			return -EBUSY;
+
+		mutex_lock(&kvm->lock);
+		ret = vgic_init(kvm);
+		mutex_unlock(&kvm->lock);
+	}
+
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 09777c8..fcbfa38 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -206,6 +206,11 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 			GICH_VMCR_PRIMASK_SHIFT;
 }
 
+/* not yet implemented */
+void vgic_v2_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index de0e8e0..d1c0285 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -186,6 +186,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
 
+/* not yet implemented */
+void vgic_v3_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 067c56e..6b892a4 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -257,6 +257,10 @@ static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
 
 	trace_vgic_update_irq_pending(cpuid, intid, level);
 
+	ret = vgic_lazy_init(kvm);
+	if (ret)
+		return ret;
+
 	vcpu = kvm_get_vcpu(kvm, cpuid);
 	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
 		return -EINVAL;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index f4244b6..5951551 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -53,6 +53,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v2_enable(struct kvm_vcpu *vcpu);
 int vgic_v2_probe(const struct gic_kvm_info *info);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
@@ -65,6 +66,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v3_enable(struct kvm_vcpu *vcpu);
 int vgic_v3_probe(const struct gic_kvm_info *info);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
@@ -99,6 +101,10 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
 {
 }
 
+static inline void vgic_v3_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 static inline int vgic_v3_probe(const struct gic_kvm_info *info)
 {
 	return -ENODEV;
@@ -112,5 +118,7 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 #endif
 
 void kvm_register_vgic_device(unsigned long type);
+int vgic_lazy_init(struct kvm *kvm);
+int vgic_init(struct kvm *kvm);
 
 #endif
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:33 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:33 +0100
Subject: [PATCH v5 54/57] KVM: arm/arm64: vgic-new: Add vgic_v2/v3_enable
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-55-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

Enable the VGIC operation by properly initialising the registers
in the hypervisor GIC interface.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-v2.c | 11 ++++++++++-
 virt/kvm/arm/vgic/vgic-v3.c | 23 ++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 1fe031b..8ad42c2 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -206,9 +206,18 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 			GICH_VMCR_PRIMASK_SHIFT;
 }
 
-/* not yet implemented */
 void vgic_v2_enable(struct kvm_vcpu *vcpu)
 {
+	/*
+	 * By forcing VMCR to zero, the GIC will restore the binary
+	 * points to their reset values. Anything else resets to zero
+	 * anyway.
+	 */
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = 0;
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr = ~0;
+
+	/* Get the show on the road... */
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr = GICH_HCR_EN;
 }
 
 /* check for overlapping regions and for regions crossing the end of memory */
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 637ff2b..336a461 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -186,9 +186,30 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
 
-/* not yet implemented */
 void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
+	struct vgic_v3_cpu_if *vgic_v3 = &vcpu->arch.vgic_cpu.vgic_v3;
+
+	/*
+	 * By forcing VMCR to zero, the GIC will restore the binary
+	 * points to their reset values. Anything else resets to zero
+	 * anyway.
+	 */
+	vgic_v3->vgic_vmcr = 0;
+	vgic_v3->vgic_elrsr = ~0;
+
+	/*
+	 * If we are emulating a GICv3, we do it in an non-GICv2-compatible
+	 * way, so we force SRE to 1 to demonstrate this to the guest.
+	 * This goes with the spec allowing the value to be RAO/WI.
+	 */
+	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+		vgic_v3->vgic_sre = ICC_SRE_EL1_SRE;
+	else
+		vgic_v3->vgic_sre = 0;
+
+	/* Get the show on the road... */
+	vgic_v3->vgic_hcr = ICH_HCR_EN;
 }
 
 /* check for overlapping regions and for regions crossing the end of memory */
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:22 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:22 +0100
Subject: [PATCH v5 43/57] KVM: arm/arm64: vgic-new: vgic_kvm_device: implement
 kvm_vgic_addr
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-44-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

kvm_vgic_addr is used by the userspace to set the base address of
the following register regions, as seen by the guest:
- distributor(v2 and v3),
- re-distributors (v3),
- CPU interface (v2).

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v3 .. v4:
- move overlap check to init time (cannot work with GICv3 here)
- refactor remaining address sanity checks

 include/kvm/vgic/vgic.h             |  2 +
 virt/kvm/arm/vgic/vgic-kvm-device.c | 86 +++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |  3 ++
 3 files changed, 91 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 00e3dca..3689b9b 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -194,6 +194,8 @@ struct vgic_cpu {
 	u64 live_lrs;
 };
 
+int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
 
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index e153f12..082829a 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -16,10 +16,96 @@
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
 #include <linux/uaccess.h>
+#include <asm/kvm_mmu.h>
 #include "vgic.h"
 
 /* common helpers */
 
+static int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
+			     phys_addr_t addr, phys_addr_t alignment)
+{
+	if (addr & ~KVM_PHYS_MASK)
+		return -E2BIG;
+
+	if (!IS_ALIGNED(addr, alignment))
+		return -EINVAL;
+
+	if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
+		return -EEXIST;
+
+	return 0;
+}
+
+/**
+ * kvm_vgic_addr - set or get vgic VM base addresses
+ * @kvm:   pointer to the vm struct
+ * @type:  the VGIC addr type, one of KVM_VGIC_V[23]_ADDR_TYPE_XXX
+ * @addr:  pointer to address value
+ * @write: if true set the address in the VM address space, if false read the
+ *          address
+ *
+ * Set or get the vgic base addresses for the distributor and the virtual CPU
+ * interface in the VM physical address space.  These addresses are properties
+ * of the emulated core/SoC and therefore user space initially knows this
+ * information.
+ * Check them for sanity (alignment, double assignment). We can't check for
+ * overlapping regions in case of a virtual GICv3 here, since we don't know
+ * the number of VCPUs yet, so we defer this check to map_resources().
+ */
+int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
+{
+	int r = 0;
+	struct vgic_dist *vgic = &kvm->arch.vgic;
+	int type_needed;
+	phys_addr_t *addr_ptr, alignment;
+
+	mutex_lock(&kvm->lock);
+	switch (type) {
+	case KVM_VGIC_V2_ADDR_TYPE_DIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+		addr_ptr = &vgic->vgic_dist_base;
+		alignment = SZ_4K;
+		break;
+	case KVM_VGIC_V2_ADDR_TYPE_CPU:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+		addr_ptr = &vgic->vgic_cpu_base;
+		alignment = SZ_4K;
+		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case KVM_VGIC_V3_ADDR_TYPE_DIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+		addr_ptr = &vgic->vgic_dist_base;
+		alignment = SZ_64K;
+		break;
+	case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+		addr_ptr = &vgic->vgic_redist_base;
+		alignment = SZ_64K;
+		break;
+#endif
+	default:
+		r = -ENODEV;
+		goto out;
+	}
+
+	if (vgic->vgic_model != type_needed) {
+		r = -ENODEV;
+		goto out;
+	}
+
+	if (write) {
+		r = vgic_check_ioaddr(kvm, addr_ptr, *addr, alignment);
+		if (!r)
+			*addr_ptr = *addr;
+	} else {
+		*addr = *addr_ptr;
+	}
+
+out:
+	mutex_unlock(&kvm->lock);
+	return r;
+}
+
 static int vgic_set_common_attr(struct kvm_device *dev,
 				struct kvm_device_attr *attr)
 {
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 77b0ab3..6abc9a3 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,9 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define VGIC_ADDR_UNDEF		(-1)
+#define IS_VGIC_ADDR_UNDEF(_x)  ((_x) == VGIC_ADDR_UNDEF)
+
 #define INTERRUPT_ID_BITS_SPIS	10
 #define VGIC_PRI_BITS		5
 
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:35 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:35 +0100
Subject: [PATCH v5 56/57] KVM: arm/arm64: vgic-new: implement mapped IRQ
 handling
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-57-git-send-email-andre.przywara@arm.com>

As we now store the mapped hardware IRQ number in our vgic_irq struct,
we no longer need the irq_phys_map for the new VGIC.
Implement the hardware IRQ mapping on top of the reworked arch timer
interface.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- adapt to new arch_timer mapped IRQ interface
- implement inject_mapped_irq() as a macro (since it is identical to
  the "un-mapped" IRQ implementation)

Changelog v1 .. v2:
- replace inject_mapped_irq() macro with a separate implementation,
  which only allows mapped IRQs to be injected via this interface

Changelog v4 .. v5:
- avoid accessing uninitialized spinlock on kvm_vgic_unmap_phys_irq

 include/kvm/vgic/vgic.h  |  5 +++++
 virt/kvm/arm/vgic/vgic.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 17b2a73..3fbd175 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -206,6 +206,11 @@ int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
+int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			       bool level);
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq);
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 6b892a4..fc74367 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -312,6 +312,47 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
 }
 
+int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			       bool level)
+{
+	return vgic_update_irq_pending(kvm, cpuid, intid, level, true);
+}
+
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+
+	BUG_ON(!irq);
+
+	spin_lock(&irq->irq_lock);
+
+	irq->hw = true;
+	irq->hwintid = phys_irq;
+
+	spin_unlock(&irq->irq_lock);
+
+	return 0;
+}
+
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+
+	BUG_ON(!irq);
+
+	if (!vgic_initialized(vcpu->kvm))
+		return -EAGAIN;
+
+	spin_lock(&irq->irq_lock);
+
+	irq->hw = false;
+	irq->hwintid = 0;
+
+	spin_unlock(&irq->irq_lock);
+
+	return 0;
+}
+
 /**
  * vgic_prune_ap_list - Remove non-relevant interrupts from the list
  *
@@ -564,3 +605,15 @@ void vgic_kick_vcpus(struct kvm *kvm)
 			kvm_vcpu_kick(vcpu);
 	}
 }
+
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+	bool map_is_active;
+
+	spin_lock(&irq->irq_lock);
+	map_is_active = irq->hw && irq->active;
+	spin_unlock(&irq->irq_lock);
+
+	return map_is_active;
+}
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:36 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:36 +0100
Subject: [PATCH v5 57/57] KVM: arm/arm64: vgic-new: enable build
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-58-git-send-email-andre.przywara@arm.com>

Now that the new VGIC implementation has reached feature parity with
the old one, add the new files to the build system and add a Kconfig
option to switch between the two versions.
We set the default to the new version to get maximum test coverage,
in case people experience problems they can switch back to the old
behaviour if needed.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adjust the changed filenames in the Makefiles
- add vgic-mmio-v2.c and vgic-mmio-v3.c to the Makefiles

 arch/arm/kvm/Kconfig          |  7 +++++++
 arch/arm/kvm/Makefile         | 11 +++++++++++
 arch/arm64/kvm/Kconfig        |  7 +++++++
 arch/arm64/kvm/Makefile       | 12 ++++++++++++
 virt/kvm/arm/hyp/vgic-v2-sr.c |  5 +++++
 5 files changed, 42 insertions(+)

diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 95a0005..02abfff 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -46,6 +46,13 @@ config KVM_ARM_HOST
 	---help---
 	  Provides host support for ARM processors.
 
+config KVM_NEW_VGIC
+	bool "New VGIC implementation"
+	depends on KVM
+	default y
+	---help---
+	  uses the new VGIC implementation
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index eb1bf43..a596b58 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -21,7 +21,18 @@ obj-$(CONFIG_KVM_ARM_HOST) += hyp/
 obj-y += kvm-arm.o init.o interrupts.o
 obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
+
+ifeq ($(CONFIG_KVM_NEW_VGIC),y)
+obj-y += $(KVM)/arm/vgic/vgic.o
+obj-y += $(KVM)/arm/vgic/vgic-init.o
+obj-y += $(KVM)/arm/vgic/vgic-irqfd.o
+obj-y += $(KVM)/arm/vgic/vgic-v2.o
+obj-y += $(KVM)/arm/vgic/vgic-mmio.o
+obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
+obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
+else
 obj-y += $(KVM)/arm/vgic.o
 obj-y += $(KVM)/arm/vgic-v2.o
 obj-y += $(KVM)/arm/vgic-v2-emul.o
+endif
 obj-y += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index aa2e34e..c4f26ef 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -54,6 +54,13 @@ config KVM_ARM_PMU
 	  Adds support for a virtual Performance Monitoring Unit (PMU) in
 	  virtual machines.
 
+config KVM_NEW_VGIC
+	bool "New VGIC implementation"
+	depends on KVM
+	default y
+        ---help---
+          uses the new VGIC implementation
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 122cff4..a7a958c 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -20,10 +20,22 @@ kvm-$(CONFIG_KVM_ARM_HOST) += emulate.o inject_fault.o regmap.o
 kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
 kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
 
+ifeq ($(CONFIG_KVM_NEW_VGIC),y)
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-irqfd.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
+else
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2-emul.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3-emul.o
+endif
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
 kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index caac41f..a3f12b3 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -21,7 +21,12 @@
 
 #include <asm/kvm_hyp.h>
 
+#ifdef CONFIG_KVM_NEW_VGIC
+extern struct vgic_global kvm_vgic_global_state;
+#define vgic_v2_params kvm_vgic_global_state
+#else
 extern struct vgic_params vgic_v2_params;
+#endif
 
 static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 					    void __iomem *base)
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:30 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:30 +0100
Subject: [PATCH v5 51/57] KVM: arm/arm64: vgic-new: vgic_init: implement
 vgic_create
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-52-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements kvm_vgic_create, which is called on the
KVM_CREATE_IRQCHIP VM ioctl (GICv2 only) or via KVM_CREATE_DEVICE.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v3 .. v4:
- fix comment

 include/kvm/vgic/vgic.h       |  1 +
 virt/kvm/arm/vgic/vgic-init.c | 84 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 393489f..0634d89 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -195,6 +195,7 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+int kvm_vgic_create(struct kvm *kvm, u32 type);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 4523beb..15d5428 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -22,6 +22,90 @@
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
+/* CREATION */
+
+/**
+ * kvm_vgic_create: triggered by the instantiation of the VGIC device by
+ * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only)
+ * or through the generic KVM_CREATE_DEVICE API ioctl.
+ * irqchip_in_kernel() tells you if this function succeeded or not.
+ */
+int kvm_vgic_create(struct kvm *kvm, u32 type)
+{
+	int i, vcpu_lock_idx = -1, ret;
+	struct kvm_vcpu *vcpu;
+
+	mutex_lock(&kvm->lock);
+
+	if (irqchip_in_kernel(kvm)) {
+		ret = -EEXIST;
+		goto out;
+	}
+
+	/*
+	 * This function is also called by the KVM_CREATE_IRQCHIP handler,
+	 * which had no chance yet to check the availability of the GICv2
+	 * emulation. So check this here again. KVM_CREATE_DEVICE does
+	 * the proper checks already.
+	 */
+	if (type == KVM_DEV_TYPE_ARM_VGIC_V2 &&
+		!kvm_vgic_global_state.can_emulate_gicv2) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/*
+	 * Any time a vcpu is run, vcpu_load is called which tries to grab the
+	 * vcpu->mutex.  By grabbing the vcpu->mutex of all VCPUs we ensure
+	 * that no other VCPUs are run while we create the vgic.
+	 */
+	ret = -EBUSY;
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		if (!mutex_trylock(&vcpu->mutex))
+			goto out_unlock;
+		vcpu_lock_idx = i;
+	}
+
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		if (vcpu->arch.has_run_once)
+			goto out_unlock;
+	}
+	ret = 0;
+
+	if (type == KVM_DEV_TYPE_ARM_VGIC_V2)
+		kvm->arch.max_vcpus = VGIC_V2_MAX_CPUS;
+	else
+		kvm->arch.max_vcpus = VGIC_V3_MAX_CPUS;
+
+	if (atomic_read(&kvm->online_vcpus) > kvm->arch.max_vcpus) {
+		ret = -E2BIG;
+		goto out_unlock;
+	}
+
+	kvm->arch.vgic.in_kernel = true;
+	kvm->arch.vgic.vgic_model = type;
+
+	/*
+	 * kvm_vgic_global_state.vctrl_base is set on vgic probe (kvm_arch_init)
+	 * it is stored in distributor struct for asm save/restore purpose
+	 */
+	kvm->arch.vgic.vctrl_base = kvm_vgic_global_state.vctrl_base;
+
+	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
+	kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
+	kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
+
+out_unlock:
+	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
+		vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
+		mutex_unlock(&vcpu->mutex);
+	}
+
+out:
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:32 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:32 +0100
Subject: [PATCH v5 53/57] KVM: arm/arm64: vgic-new: vgic_init: implement
 map_resources
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-54-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

map_resources is the last initialization step. It is executed on
first VCPU run. At that stage the code checks that userspace has provided
the base addresses for the relevant VGIC regions, which depend on the
type of VGIC that is exposed to the guest.  Also we check if the two
regions overlap.
If the checks succeeded, we register the respective register frames with
the kvm_io_bus framework.

If we emulate a GICv2, the function also forces vgic_init execution if
it has not been executed yet. Also we map the virtual GIC CPU interface
onto the guest's CPU interface.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v3 .. v4:
- add overlap check (moved from kvm_vgic_addr())
- reword commit message
- improve comment

 include/kvm/vgic/vgic.h       |  1 +
 virt/kvm/arm/vgic/vgic-init.c | 28 +++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   | 69 +++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c   | 71 +++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h      |  7 +++++
 5 files changed, 176 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index e7ae36b..17b2a73 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -201,6 +201,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type);
 void kvm_vgic_destroy(struct kvm *kvm);
 void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
+int kvm_vgic_map_resources(struct kvm *kvm);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index bed3240..a1442f7 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -323,6 +323,34 @@ int vgic_lazy_init(struct kvm *kvm)
 	return ret;
 }
 
+/* RESOURCE MAPPING */
+
+/**
+ * Map the MMIO regions depending on the VGIC model exposed to the guest
+ * called on the first VCPU run.
+ * Also map the virtual CPU interface into the VM.
+ * v2/v3 derivatives call vgic_init if not already done.
+ * vgic_ready() returns true if this function has succeeded.
+ * @kvm: kvm struct pointer
+ */
+int kvm_vgic_map_resources(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	int ret = 0;
+
+	mutex_lock(&kvm->lock);
+	if (!irqchip_in_kernel(kvm))
+		goto out;
+
+	if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+		ret = vgic_v2_map_resources(kvm);
+	else
+		ret = vgic_v3_map_resources(kvm);
+out:
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index fcbfa38..1fe031b 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -211,6 +211,75 @@ void vgic_v2_enable(struct kvm_vcpu *vcpu)
 {
 }
 
+/* check for overlapping regions and for regions crossing the end of memory */
+static bool vgic_v2_check_base(gpa_t dist_base, gpa_t cpu_base)
+{
+	if (dist_base + KVM_VGIC_V2_DIST_SIZE < dist_base)
+		return false;
+	if (cpu_base + KVM_VGIC_V2_CPU_SIZE < cpu_base)
+		return false;
+
+	if (dist_base + KVM_VGIC_V2_DIST_SIZE <= cpu_base)
+		return true;
+	if (cpu_base + KVM_VGIC_V2_CPU_SIZE <= dist_base)
+		return true;
+
+	return false;
+}
+
+int vgic_v2_map_resources(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	int ret = 0;
+
+	if (vgic_ready(kvm))
+		goto out;
+
+	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
+	    IS_VGIC_ADDR_UNDEF(dist->vgic_cpu_base)) {
+		kvm_err("Need to set vgic cpu and dist addresses first\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	if (!vgic_v2_check_base(dist->vgic_dist_base, dist->vgic_cpu_base)) {
+		kvm_err("VGIC CPU and dist frames overlap\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Initialize the vgic if this hasn't already been done on demand by
+	 * accessing the vgic state from userspace.
+	 */
+	ret = vgic_init(kvm);
+	if (ret) {
+		kvm_err("Unable to initialize VGIC dynamic data structures\n");
+		goto out;
+	}
+
+	ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V2);
+	if (ret) {
+		kvm_err("Unable to register VGIC MMIO regions\n");
+		goto out;
+	}
+
+	ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base,
+				    kvm_vgic_global_state.vcpu_base,
+				    KVM_VGIC_V2_CPU_SIZE, true);
+	if (ret) {
+		kvm_err("Unable to remap VGIC CPU to VCPU\n");
+		goto out;
+	}
+
+	dist->ready = true;
+
+out:
+	if (ret)
+		kvm_vgic_destroy(kvm);
+	return ret;
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index d1c0285..637ff2b 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -191,6 +191,77 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
 }
 
+/* check for overlapping regions and for regions crossing the end of memory */
+static bool vgic_v3_check_base(struct kvm *kvm)
+{
+	struct vgic_dist *d = &kvm->arch.vgic;
+	gpa_t redist_size = KVM_VGIC_V3_REDIST_SIZE;
+
+	redist_size *= atomic_read(&kvm->online_vcpus);
+
+	if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base)
+		return false;
+	if (d->vgic_redist_base + redist_size < d->vgic_redist_base)
+		return false;
+
+	if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE <= d->vgic_redist_base)
+		return true;
+	if (d->vgic_redist_base + redist_size <= d->vgic_dist_base)
+		return true;
+
+	return false;
+}
+
+int vgic_v3_map_resources(struct kvm *kvm)
+{
+	int ret = 0;
+	struct vgic_dist *dist = &kvm->arch.vgic;
+
+	if (vgic_ready(kvm))
+		goto out;
+
+	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
+	    IS_VGIC_ADDR_UNDEF(dist->vgic_redist_base)) {
+		kvm_err("Need to set vgic distributor addresses first\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	if (!vgic_v3_check_base(kvm)) {
+		kvm_err("VGIC redist and dist frames overlap\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * For a VGICv3 we require the userland to explicitly initialize
+	 * the VGIC before we need to use it.
+	 */
+	if (!vgic_initialized(kvm)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V3);
+	if (ret) {
+		kvm_err("Unable to register VGICv3 dist MMIO regions\n");
+		goto out;
+	}
+
+	ret = vgic_register_redist_iodevs(kvm, dist->vgic_redist_base);
+	if (ret) {
+		kvm_err("Unable to register VGICv3 redist MMIO regions\n");
+		goto out;
+	}
+
+	dist->ready = true;
+
+out:
+	if (ret)
+		kvm_vgic_destroy(kvm);
+	return ret;
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 5951551..7b300ca 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -55,6 +55,7 @@ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_enable(struct kvm_vcpu *vcpu);
 int vgic_v2_probe(const struct gic_kvm_info *info);
+int vgic_v2_map_resources(struct kvm *kvm);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -68,6 +69,7 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_enable(struct kvm_vcpu *vcpu);
 int vgic_v3_probe(const struct gic_kvm_info *info);
+int vgic_v3_map_resources(struct kvm *kvm);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -110,6 +112,11 @@ static inline int vgic_v3_probe(const struct gic_kvm_info *info)
 	return -ENODEV;
 }
 
+static inline int vgic_v3_map_resources(struct kvm *kvm)
+{
+	return -ENODEV;
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:34 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:34 +0100
Subject: [PATCH v5 55/57] KVM: arm/arm64: vgic-new: Wire up irqfd injection
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-56-git-send-email-andre.przywara@arm.com>

Connect the new VGIC implementation to the irqfd framework, so that we
can inject IRQs.
GSI routing and MSI routing are not yet implemented.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-irqfd.c | 52 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-irqfd.c

diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
new file mode 100644
index 0000000..c675513
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/kvm.h>
+#include <linux/kvm_host.h>
+#include <trace/events/kvm.h>
+
+int kvm_irq_map_gsi(struct kvm *kvm,
+		    struct kvm_kernel_irq_routing_entry *entries,
+		    int gsi)
+{
+	return 0;
+}
+
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned int irqchip,
+			 unsigned int pin)
+{
+	return pin;
+}
+
+int kvm_set_irq(struct kvm *kvm, int irq_source_id,
+		u32 irq, int level, bool line_status)
+{
+	unsigned int spi = irq + VGIC_NR_PRIVATE_IRQS;
+
+	trace_kvm_set_irq(irq, level, irq_source_id);
+
+	BUG_ON(!vgic_initialized(kvm));
+
+	return kvm_vgic_inject_irq(kvm, 0, spi, level);
+}
+
+/* MSI not implemented yet */
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
+		struct kvm *kvm, int irq_source_id,
+		int level, bool line_status)
+{
+	return 0;
+}
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:10 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:10 +0100
Subject: [PATCH v5 31/57] KVM: arm/arm64: vgic-new: Add TARGET registers
 handlers
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-32-git-send-email-andre.przywara@arm.com>

The target register handlers are v2 emulation specific, so their
implementation lives entirely in vgic-mmio-v2.c.
We copy the old VGIC behaviour of assigning an IRQ to the first VCPU
set in the target mask instead of making it possibly pending on
multiple VCPUs.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- remove runtime VCPU determination from this v2-only register
- fold in implementation of vgic_v2_irq_change_affinity()
- replace ffs() with __ffs()

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index bb7389e..52389ff 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -64,6 +64,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
+					   gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->targets << (i * 8);
+	}
+
+	return val;
+}
+
+static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
+				   gpa_t addr, unsigned int len,
+				   unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+
+	/* GICD_ITARGETSR[0-7] are read-only */
+	if (intid < VGIC_NR_PRIVATE_IRQS)
+		return;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
+		int target;
+
+		spin_lock(&irq->irq_lock);
+
+		irq->targets = (val >> (i * 8)) & 0xff;
+		target = irq->targets ? __ffs(irq->targets) : 0;
+		irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target);
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
@@ -93,7 +134,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		vgic_mmio_read_target, vgic_mmio_write_target, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
 		vgic_mmio_read_config, vgic_mmio_write_config, 2,
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:02 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:02 +0100
Subject: [PATCH v5 23/57] KVM: arm/arm64: vgic-new: Add MMIO handling framework
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-24-git-send-email-andre.przywara@arm.com>

From: Marc Zyngier <marc.zyngier at arm.com>

Add an MMIO handling framework to the VGIC emulation:
Each register is described by its offset, size (or number of bits per
IRQ, if applicable) and the read/write handler functions. We provide
initialization macros to describe each GIC register later easily.

Separate dispatch functions for read and write accesses are connected
to the kvm_io_bus framework and binary-search for the responsible
register handler based on the offset address within the region.
We convert the incoming data (referenced by a pointer) to the host's
endianness and use pass-by-value to hand the data over to the actual
handler functions.

The register handler prototype and the endianness conversion are
courtesy of Christoffer Dall.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog RFC..v1:
- rework MMIO dispatching to use only one kvm_io_bus device
- document purpose of register region macros
- rename "this" parameter to "dev"
- change IGROUPR to be RAO (returning 1 => Group1 IRQs)

Changelog v1 .. v2:
* MASSIVE rework:
- store register_region pointer in kvm_io_bus linked struct
- replace write_mask_xxx functions with extract_bytes() implementation
- change handler functions' prototypes to take and return unsigned long
- use binary search to find matching register handler
- convert endianness of input data in dispatch_mmio_xxx functions
- improve readability of register initializer macros
- remove any GICv2/GICv3 specific functions from vgic-mmio.c
- rename file from vgic_mmio.c to vgic-mmio.c

Changelog v2 .. v3:
- replace inclusion of vgic/vgic.h with arm_vgic.h

Changelog v3 .. v4:
- add IRQ number accessor macro
- check access width in dispatcher
- treat non-covered MMIO addresses as RAZ/WI
- remove extract_bytes() (re-introduced as static later in the series)

Changelog v4 .. v5:
- simplify and document VGIC_ADDR_TO_INTID macros

 include/kvm/vgic/vgic.h       |  13 +++
 virt/kvm/arm/vgic/vgic-mmio.c | 184 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h |  99 +++++++++++++++++++++++
 3 files changed, 296 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index f663288..ff3f9c2 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -106,6 +106,16 @@ struct vgic_irq {
 	enum vgic_irq_config config;	/* Level or edge */
 };
 
+struct vgic_register_region;
+
+struct vgic_io_device {
+	gpa_t base_addr;
+	struct kvm_vcpu *redist_vcpu;
+	const struct vgic_register_region *regions;
+	int nr_regions;
+	struct kvm_io_device dev;
+};
+
 struct vgic_dist {
 	bool			in_kernel;
 	bool			ready;
@@ -132,6 +142,9 @@ struct vgic_dist {
 	bool			enabled;
 
 	struct vgic_irq		*spis;
+
+	struct vgic_io_device	dist_iodev;
+	struct vgic_io_device	*redist_iodevs;
 };
 
 struct vgic_v2_cpu_if {
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
new file mode 100644
index 0000000..012b82b
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -0,0 +1,184 @@
+/*
+ * VGIC MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/bsearch.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len)
+{
+	return 0;
+}
+
+unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len)
+{
+	return -1UL;
+}
+
+void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
+			unsigned int len, unsigned long val)
+{
+	/* Ignore */
+}
+
+static int match_region(const void *key, const void *elt)
+{
+	const unsigned int offset = (unsigned long)key;
+	const struct vgic_register_region *region = elt;
+
+	if (offset < region->reg_offset)
+		return -1;
+
+	if (offset >= region->reg_offset + region->len)
+		return 1;
+
+	return 0;
+}
+
+/* Find the proper register handler entry given a certain address offset. */
+static const struct vgic_register_region *
+vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
+		      unsigned int offset)
+{
+	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
+		       sizeof(region[0]), match_region);
+}
+
+/*
+ * kvm_mmio_read_buf() returns a value in a format where it can be converted
+ * to a byte array and be directly observed as the guest wanted it to appear
+ * in memory if it had done the store itself, which is LE for the GIC, as the
+ * guest knows the GIC is always LE.
+ *
+ * We convert this value to the CPUs native format to deal with it as a data
+ * value.
+ */
+unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len)
+{
+	unsigned long data = kvm_mmio_read_buf(val, len);
+
+	switch (len) {
+	case 1:
+		return data;
+	case 2:
+		return le16_to_cpu(data);
+	case 4:
+		return le32_to_cpu(data);
+	default:
+		return le64_to_cpu(data);
+	}
+}
+
+/*
+ * kvm_mmio_write_buf() expects a value in a format such that if converted to
+ * a byte array it is observed as the guest would see it if it could perform
+ * the load directly.  Since the GIC is LE, and the guest knows this, the
+ * guest expects a value in little endian format.
+ *
+ * We convert the data value from the CPUs native format to LE so that the
+ * value is returned in the proper format.
+ */
+void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
+				unsigned long data)
+{
+	switch (len) {
+	case 1:
+		break;
+	case 2:
+		data = cpu_to_le16(data);
+		break;
+	case 4:
+		data = cpu_to_le32(data);
+		break;
+	default:
+		data = cpu_to_le64(data);
+	}
+
+	kvm_mmio_write_buf(buf, len, data);
+}
+
+static
+struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
+{
+	return container_of(dev, struct vgic_io_device, dev);
+}
+
+static bool check_region(const struct vgic_register_region *region,
+			 gpa_t addr, int len)
+{
+	if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1)
+		return true;
+	if ((region->access_flags & VGIC_ACCESS_32bit) &&
+	    len == sizeof(u32) && !(addr & 3))
+		return true;
+	if ((region->access_flags & VGIC_ACCESS_64bit) &&
+	    len == sizeof(u64) && !(addr & 7))
+		return true;
+
+	return false;
+}
+
+static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
+			      gpa_t addr, int len, void *val)
+{
+	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
+	const struct vgic_register_region *region;
+	struct kvm_vcpu *r_vcpu;
+	unsigned long data;
+
+	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
+				       addr - iodev->base_addr);
+	if (!region || !check_region(region, addr, len)) {
+		memset(val, 0, len);
+		return 0;
+	}
+
+	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
+	data = region->read(r_vcpu, addr, len);
+	vgic_data_host_to_mmio_bus(val, len, data);
+	return 0;
+}
+
+static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
+			       gpa_t addr, int len, const void *val)
+{
+	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
+	const struct vgic_register_region *region;
+	struct kvm_vcpu *r_vcpu;
+	unsigned long data = vgic_data_mmio_bus_to_host(val, len);
+
+	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
+				       addr - iodev->base_addr);
+	if (!region)
+		return 0;
+
+	if (!check_region(region, addr, len))
+		return 0;
+
+	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
+	region->write(r_vcpu, addr, len, data);
+	return 0;
+}
+
+struct kvm_io_device_ops kvm_io_gic_ops = {
+	.read = dispatch_mmio_read,
+	.write = dispatch_mmio_write,
+};
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
new file mode 100644
index 0000000..58a1878
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __KVM_ARM_VGIC_MMIO_H__
+#define __KVM_ARM_VGIC_MMIO_H__
+
+struct vgic_register_region {
+	unsigned int reg_offset;
+	unsigned int len;
+	unsigned int bits_per_irq;
+	unsigned int access_flags;
+	unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr,
+			      unsigned int len);
+	void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
+		      unsigned long val);
+};
+
+extern struct kvm_io_device_ops kvm_io_gic_ops;
+
+#define VGIC_ACCESS_8bit	1
+#define VGIC_ACCESS_32bit	2
+#define VGIC_ACCESS_64bit	4
+
+/*
+ * Generate a mask that covers the number of bytes required to address
+ * up to 1024 interrupts, each represented by <bits> bits. This assumes
+ * that <bits> is a power of two.
+ */
+#define VGIC_ADDR_IRQ_MASK(bits) (((bits) * 1024 / 8) - 1)
+
+/*
+ * (addr & mask) gives us the byte offset for the INT ID, so we want to
+ * divide this with 'bytes per irq' to get the INT ID, which is given
+ * by '(bits) / 8'.  But we do this with fixed-point-arithmetic and
+ * take advantage of the fact that division by a fraction equals
+ * multiplication with the inverted fraction, and scale up both the
+ * numerator and denominator with 8 to support at most 64 bits per IRQ:
+ */
+#define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
+					64 / (bits) / 8)
+
+/*
+ * Some VGIC registers store per-IRQ information, with a different number
+ * of bits per IRQ. For those registers this macro is used.
+ * The _WITH_LENGTH version instantiates registers with a fixed length
+ * and is mutually exclusive with the _PER_IRQ version.
+ */
+#define REGISTER_DESC_WITH_BITS_PER_IRQ(off, rd, wr, bpi, acc)		\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = bpi,					\
+		.len = (bpi) * 1024 / 8,				\
+		.access_flags = acc,					\
+		.read = rd,						\
+		.write = wr,						\
+	}
+
+#define REGISTER_DESC_WITH_LENGTH(off, rd, wr, length, acc)		\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = 0,					\
+		.len = length,						\
+		.access_flags = acc,					\
+		.read = rd,						\
+		.write = wr,						\
+	}
+
+int kvm_vgic_register_mmio_region(struct kvm *kvm, struct kvm_vcpu *vcpu,
+				  struct vgic_register_region *reg_desc,
+				  struct vgic_io_device *region,
+				  int nr_irqs, bool offset_private);
+
+unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len);
+
+void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
+				unsigned long data);
+
+unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len);
+
+unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
+			unsigned int len, unsigned long val);
+
+#endif
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:07 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:07 +0100
Subject: [PATCH v5 28/57] KVM: arm/arm64: vgic-new: Add ACTIVE registers
 handlers
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-29-git-send-email-andre.przywara@arm.com>

The active register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.
Since activation/deactivation of an interrupt may happen entirely
in the guest without it ever exiting, we need some extra logic to
properly track the active state.
For clearing the active state, we basically have to halt the guest to
make sure this is properly propagated into the respective VCPUs.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog RFC..v1:
- handling queueing in write handler
- remove IRQ lock from read handler

Changelog v1 .. v2:
- adapt to new MMIO framework

Changelog v3 .. v4:
- specify accessor width
- use IRQ number accessor macro
- drop elaborate write_sactive handler and use new vgic_queue_irq_unlock()
- properly emulate clear active by halting the guest (Christoffer)
- replace extract_bytes() with simple return

Changelog v4 .. v5:
- remove irq->vcpu condition from set-active early bail-out check
- fix commit message

 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 81 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 10 +++++
 3 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index c13a708..12e101b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -84,10 +84,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index d8dc8f6..79a4622 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -155,6 +155,87 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->active)
+			value |= (1U << i);
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	kvm_arm_halt_guest(vcpu->kvm);
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		/*
+		 * If this virtual IRQ was written into a list register, we
+		 * have to make sure the CPU that runs the VCPU thread has
+		 * synced back LR state to the struct vgic_irq.  We can only
+		 * know this for sure, when either this irq is not assigned to
+		 * anyone's AP list anymore, or the VCPU thread is not
+		 * running on any CPUs.
+		 *
+		 * In the opposite case, we know the VCPU thread may be on its
+		 * way back from the guest and still has to sync back this
+		 * IRQ, so we release and re-acquire the spin_lock to let the
+		 * other thread sync back the IRQ.
+		 */
+		while (irq->vcpu && /* IRQ may have state in an LR somewhere */
+		       irq->vcpu->cpu != -1) /* VCPU thread is running */
+			cond_resched_lock(&irq->irq_lock);
+
+		irq->active = false;
+		spin_unlock(&irq->irq_lock);
+	}
+	kvm_arm_resume_guest(vcpu->kvm);
+}
+
+void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		/*
+		 * If the IRQ was already active or there is no target VCPU
+		 * assigned at the moment, then just proceed.
+		 */
+		if (irq->active || !irq->target_vcpu) {
+			irq->active = true;
+
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		irq->active = true;
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index b18120d..90146c7 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -118,6 +118,16 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
 			      gpa_t addr, unsigned int len,
 			      unsigned long val);
 
+unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
+void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
 
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:24 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:24 +0100
Subject: [PATCH v5 45/57] KVM: arm/arm64: vgic-new: vgic_kvm_device: access to
 VGIC registers
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-46-git-send-email-andre.przywara@arm.com>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
access VGIC registers.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v3 .. v4:
- check for proper alignment on userland GIC accesses

 virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 38 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |  1 +
 3 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index a709097..78621283 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -226,6 +226,21 @@ void kvm_register_vgic_device(unsigned long type)
 	}
 }
 
+/** vgic_attr_regs_access: allows user space to read/write VGIC registers
+ *
+ * @dev: kvm device handle
+ * @attr: kvm device attribute
+ * @reg: address the value is read or written
+ * @is_write: write flag
+ *
+ */
+static int vgic_attr_regs_access(struct kvm_device *dev,
+				 struct kvm_device_attr *attr,
+				 u32 *reg, bool is_write)
+{
+	return -ENXIO;
+}
+
 /* V2 ops */
 
 static int vgic_v2_set_attr(struct kvm_device *dev,
@@ -234,8 +249,23 @@ static int vgic_v2_set_attr(struct kvm_device *dev,
 	int ret;
 
 	ret = vgic_set_common_attr(dev, attr);
-	return ret;
+	if (ret != -ENXIO)
+		return ret;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 reg;
+
+		if (get_user(reg, uaddr))
+			return -EFAULT;
 
+		return vgic_attr_regs_access(dev, attr, &reg, true);
+	}
+	}
+
+	return -ENXIO;
 }
 
 static int vgic_v2_get_attr(struct kvm_device *dev,
@@ -244,7 +274,23 @@ static int vgic_v2_get_attr(struct kvm_device *dev,
 	int ret;
 
 	ret = vgic_get_common_attr(dev, attr);
-	return ret;
+	if (ret != -ENXIO)
+		return ret;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 reg = 0;
+
+		ret = vgic_attr_regs_access(dev, attr, &reg, false);
+		if (ret)
+			return ret;
+		return put_user(reg, uaddr);
+	}
+	}
+
+	return -ENXIO;
 }
 
 static int vgic_v2_has_attr(struct kvm_device *dev,
@@ -258,6 +304,9 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 			return 0;
 		}
 		break;
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		return vgic_v2_has_attr_regs(dev, attr);
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 3925d4c..7189690 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -258,3 +258,41 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
 
 	return SZ_4K;
 }
+
+int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+	const struct vgic_register_region *regions;
+	gpa_t addr;
+	int nr_regions, i, len;
+
+	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+		regions = vgic_v2_dist_registers;
+		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
+		break;
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		return -ENXIO;		/* TODO: describe CPU i/f regs also */
+	default:
+		return -ENXIO;
+	}
+
+	/* We only support aligned 32-bit accesses. */
+	if (addr & 3)
+		return -ENXIO;
+
+	for (i = 0; i < nr_regions; i++) {
+		if (regions[i].bits_per_irq)
+			len = (regions[i].bits_per_irq * nr_irqs) / 8;
+		else
+			len = regions[i].len;
+
+		if (regions[i].reg_offset <= addr &&
+		    regions[i].reg_offset + len > addr)
+			return 0;
+	}
+
+	return -ENXIO;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 6abc9a3..a264c5f 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -37,6 +37,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:25 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:25 +0100
Subject: [PATCH v5 46/57] KVM: arm/arm64: vgic-new: Export register access
 interface
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-47-git-send-email-andre.przywara@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

Userland can access the emulated GIC to save and restore its state
for initialization or migration purposes.
The kvm_io_bus API requires an absolute gpa, which does not fit the
KVM_DEV_ARM_VGIC_GRP_DIST_REGS user API, that only provides relative
offsets. So we provide a wrapper to plug into our MMIO framework and
find the respective register handler.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Andre Przywara <andre.przywara at arm.com>
---
Changelog v1 .. v2:
- adapt to new MMIO framework
- handle endianess explicitly

Changelog v2 .. v3:
- wrap accessor function for easier reusage later
- moved from earlier in the series

 virt/kvm/arm/vgic/vgic-mmio-v2.c | 36 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 2 files changed, 38 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 7189690..a255122 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -296,3 +296,39 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 
 	return -ENXIO;
 }
+
+/*
+ * When userland tries to access the VGIC register handlers, we need to
+ * create a usable struct vgic_io_device to be passed to the handlers and we
+ * have to set up a buffer similar to what would have happened if a guest MMIO
+ * access occurred, including doing endian conversions on BE systems.
+ */
+static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
+			bool is_write, int offset, u32 *val)
+{
+	unsigned int len = 4;
+	u8 buf[4];
+	int ret;
+
+	if (is_write) {
+		vgic_data_host_to_mmio_bus(buf, len, *val);
+		ret = kvm_io_gic_ops.write(vcpu, &dev->dev, offset, len, buf);
+	} else {
+		ret = kvm_io_gic_ops.read(vcpu, &dev->dev, offset, len, buf);
+		if (!ret)
+			*val = vgic_data_mmio_bus_to_host(buf, len);
+	}
+
+	return ret;
+}
+
+int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			 int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_dist_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_dist_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index a264c5f..f826026 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -38,6 +38,8 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
+int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			 int offset, u32 *val);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
-- 
2.8.2



From andre.przywara at arm.com  Thu May 19 11:08:26 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Thu, 19 May 2016 19:08:26 +0100
Subject: [PATCH v5 47/57] KVM: arm/arm64: vgic-new: Add userland access to
 VGIC dist registers
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <1463681316-23039-48-git-send-email-andre.przywara@arm.com>

Userland may want to save and restore the state of the in-kernel VGIC,
so we provide the code which takes a userland request and translate
that into calls to our MMIO framework.

>From Christoffer:
When accessing the VGIC state from userspace we really don't want a VCPU
to be messing with the state at the same time, and the API specifies
that we should return -EBUSY if any VCPUs are running.
Check and prevent VCPUs from running by grabbing their mutexes, one by
one, and error out if we fail.
(Note: This could potentially be simplified to just do a simple check
and see if any VCPUs are running, and return -EBUSY then, without
enforcing the locking throughout the duration of the uaccess, if we
think that taking/releasing all these mutexes for every single GIC
register access is too heavyweight.)

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changelog v4 .. v5:
- add check to avoid running VCPUs on userland access

 virt/kvm/arm/vgic/vgic-kvm-device.c | 55 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 78621283..9ee27cb 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -238,7 +238,60 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 				 struct kvm_device_attr *attr,
 				 u32 *reg, bool is_write)
 {
-	return -ENXIO;
+	gpa_t addr;
+	int cpuid, ret, c;
+	struct kvm_vcpu *vcpu, *tmp_vcpu;
+	int vcpu_lock_idx = -1;
+
+	cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
+		 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
+	vcpu = kvm_get_vcpu(dev->kvm, cpuid);
+	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+	mutex_lock(&dev->kvm->lock);
+
+	ret = vgic_init(dev->kvm);
+	if (ret)
+		goto out;
+
+	if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Any time a vcpu is run, vcpu_load is called which tries to grab the
+	 * vcpu->mutex.  By grabbing the vcpu->mutex of all VCPUs we ensure
+	 * that no other VCPUs are run and fiddle with the vgic state while we
+	 * access it.
+	 */
+	ret = -EBUSY;
+	kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm) {
+		if (!mutex_trylock(&tmp_vcpu->mutex))
+			goto out;
+		vcpu_lock_idx = c;
+	}
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		ret = -EINVAL;
+		break;
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+out:
+	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
+		tmp_vcpu = kvm_get_vcpu(dev->kvm, vcpu_lock_idx);
+		mutex_unlock(&tmp_vcpu->mutex);
+	}
+
+	mutex_unlock(&dev->kvm->lock);
+	return ret;
 }
 
 /* V2 ops */
-- 
2.8.2



From jeremy.linton at arm.com  Thu May 19 11:18:48 2016
From: jeremy.linton at arm.com (Jeremy Linton)
Date: Thu, 19 May 2016 13:18:48 -0500
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <573E0388.7030203@arm.com>

On 05/10/2016 10:19 AM, Tomasz Nowicki wrote:
>  From the functionality point of view this series may be split into the
> following logic parts:
> 1. New ECAM API and update for users of the pci-host-common API
> 2. Necessary fixes as the preparation for using driver on ARM64.
> 3. Use new MCFG interface and implement generic ACPI based PCI host controller driver.
> 4. Enable above driver on ARM64

Thomasz,

Unless i'm doing something wrong, this patch causes a build break if 
NUMA is enabled in a 4.6+ kernel.

Thanks,



drivers/built-in.o: In function `pci_device_add':
/home/jlinton/linux-main/drivers/pci/probe.c:1744: undefined reference 
to `pcibus_to_node'
drivers/built-in.o: In function `pci_create_root_bus':
/home/jlinton/linux-main/drivers/pci/probe.c:2163: undefined reference 
to `pcibus_to_node'
drivers/built-in.o: In function `cpulistaffinity_show':
/home/jlinton/linux-main/drivers/pci/pci-sysfs.c:123: undefined 
reference to `pcibus_to_node'
/home/jlinton/linux-main/drivers/pci/pci-sysfs.c:123: undefined 
reference to `pcibus_to_node'
drivers/built-in.o: In function `cpuaffinity_show':
/home/jlinton/linux-main/drivers/pci/pci-sysfs.c:114: undefined 
reference to `pcibus_to_node'
drivers/built-in.o:/home/jlinton/linux-main/drivers/pci/pci-sysfs.c:114: 
more undefined references to `pcibus_to_node' follow
Makefile:937: recipe for target 'vmlinux' failed



From davem at davemloft.net  Thu May 19 11:25:50 2016
From: davem at davemloft.net (David Miller)
Date: Thu, 19 May 2016 11:25:50 -0700 (PDT)
Subject: [PATCH 1/1] net: thunderx: avoid null pointer dereference
In-Reply-To: <1463514038-9008-1-git-send-email-xypron.glpk@gmx.de>
References: <1463514038-9008-1-git-send-email-xypron.glpk@gmx.de>
Message-ID: <20160519.112550.1461536215214747775.davem@davemloft.net>

From: Heinrich Schuchardt <xypron.glpk at gmx.de>
Date: Tue, 17 May 2016 21:40:38 +0200

> In function bgx_lmac_handler only use a member of
> lmac after checking it is not null.
> 
> Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>

Applied.


From d-gerlach at ti.com  Thu May 19 11:33:40 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Thu, 19 May 2016 13:33:40 -0500
Subject: [PATCH 2/2] cpufreq: ti: Add cpufreq driver to determine
 available OPPs at runtime
In-Reply-To: <20160519043920.GC32001@vireshk-i7>
References: <cover.1463609497.git.d-gerlach@ti.com>
 <9b8c1ba22e07cbfa25f93b33422fcfd1a8d10655.1463609497.git.d-gerlach@ti.com>
 <20160519043920.GC32001@vireshk-i7>
Message-ID: <573E0704.7010104@ti.com>

On 05/18/2016 11:39 PM, Viresh Kumar wrote:
> On 18-05-16, 18:30, Dave Gerlach wrote:
>> Some TI SoCs, like those in the AM335x, AM437x, DRA7x, and AM57x families,
>> have different OPPs available for the MPU depending on which specific
>> variant of the SoC is in use. This can be determined through use of the
>> revision and an eFuse register present in the silicon. Introduce a
>> ti-cpufreq driver that can read the aformentioned values and provide
>> them as version matching data to the opp framework. Through this the
>> opp-supported-hw dt binding that is part of the operating-points-v2
>> table can be used to indicate availability of OPPs for each device.
>>
>> This driver also creates the "cpufreq-dt" platform_device after passing
>> the version matching data to the OPP framework so that the cpufreq-dt
>> handles the actual cpufreq implementation. Even without the necessary
>> data to pass the version matching data the driver will still create this
>> device to maintain backwards compatibility with operating-points v1
>> tables.
>>
>> Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
>> ---
>>   drivers/cpufreq/Kconfig.arm  |  11 ++
>>   drivers/cpufreq/Makefile     |   1 +
>>   drivers/cpufreq/ti-cpufreq.c | 254 +++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 266 insertions(+)
>>   create mode 100644 drivers/cpufreq/ti-cpufreq.c
>>
>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
>> index d89b8afe23b6..0dea6849ac3e 100644
>> --- a/drivers/cpufreq/Kconfig.arm
>> +++ b/drivers/cpufreq/Kconfig.arm
>> @@ -234,6 +234,17 @@ config ARM_TEGRA124_CPUFREQ
>>   	help
>>   	  This adds the CPUFreq driver support for Tegra124 SOCs.
>>
>> +config ARM_TI_CPUFREQ
>> +	tristate "Texas Instruments CPUFreq support"
>
> You sure you want to get it compiled as a module? And don't provide
> module_exit() at all?

I thought about this for a while, and I was going to make it bool but 
decided to model it after what has already been accepted (sti-cpufreq). 
Wasn't sure what preferred path is, but I will go ahead and switch this 
to bool for this driver as I think that makes the most sense.

>
>> +	depends on ARCH_OMAP2PLUS
>> +	help
>> +	  This driver enables valid OPPs on the running platform based on
>> +	  values contained within the SoC in use. Enable this in order to
>> +	  use the cpufreq-dt driver on all Texas Instruments platforms that
>> +	  provide dt based operating-points-v2 tables with opp-supported-hw
>> +	  data provided. Required for cpufreq support on AM335x, AM437x,
>> +	  DRA7x, and AM57x platforms.
>> +
>>   config ARM_PXA2xx_CPUFREQ
>>   	tristate "Intel PXA2xx CPUfreq driver"
>>   	depends on PXA27x || PXA25x
>> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
>> index 0a9b6a093646..5b1b6ec0a9f0 100644
>> --- a/drivers/cpufreq/Makefile
>> +++ b/drivers/cpufreq/Makefile
>> @@ -77,6 +77,7 @@ obj-$(CONFIG_ARM_SPEAR_CPUFREQ)		+= spear-cpufreq.o
>>   obj-$(CONFIG_ARM_STI_CPUFREQ)		+= sti-cpufreq.o
>>   obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)	+= tegra20-cpufreq.o
>>   obj-$(CONFIG_ARM_TEGRA124_CPUFREQ)	+= tegra124-cpufreq.o
>> +obj-$(CONFIG_ARM_TI_CPUFREQ)		+= ti-cpufreq.o
>>   obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ)	+= vexpress-spc-cpufreq.o
>>   obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
>>   obj-$(CONFIG_MACH_MVEBU_V7)		+= mvebu-cpufreq.o
>> diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
>> new file mode 100644
>> index 000000000000..e47b452aadd0
>> --- /dev/null
>> +++ b/drivers/cpufreq/ti-cpufreq.c
>> @@ -0,0 +1,254 @@
>> +/*
>> + * TI CPUFreq/OPP hw-supported driver
>> + *
>> + * Copyright (C) 2016 Texas Instruments, Inc.
>> + *	 Dave Gerlach <d-gerlach at ti.com>
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * version 2 as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <linux/cpu.h>
>> +#include <linux/io.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/pm_opp.h>
>> +#include <linux/regmap.h>
>> +
>> +#define REVISION_MASK				(0xF << 28)
>
> Use below shift-mask here ?

Yes, but this will change due to later change where this will actually 
be used.

>
>> +#define REVISION_SHIFT				28
>> +
>> +#define DRA7_EFUSE_HAS_OD_MPU_OPP		11
>> +#define DRA7_EFUSE_HAS_HIGH_MPU_OPP		15
>> +#define DRA7_EFUSE_HAS_ALL_MPU_OPP		23
>> +
>> +#define DRA7_EFUSE_NOM_MPU_OPP			BIT(0)
>> +#define DRA7_EFUSE_OD_MPU_OPP			BIT(1)
>> +#define DRA7_EFUSE_HIGH_MPU_OPP			BIT(2)
>> +
>> +#define VERSION_COUNT				2
>> +
>> +static struct ti_cpufreq_data {
>> +	struct device *cpu;
>> +	struct regmap *opp_efuse;
>> +	struct regmap *revision;
>> +} opp_data;
>> +
>> +static struct ti_cpufreq_soc_data {
>> +	unsigned long (*efuse_xlate)(unsigned long efuse);
>> +} *soc_data;
>> +
>> +static unsigned long amx3_efuse_xlate(unsigned long efuse)
>> +{
>> +	/* AM335x and AM437x use "OPP disable" bits, so invert */
>> +	return ~efuse;
>> +}
>> +
>> +static unsigned long dra7_efuse_xlate(unsigned long efuse)
>> +{
>> +	unsigned long calculated_efuse = DRA7_EFUSE_NOM_MPU_OPP;
>> +
>> +	/*
>> +	 * The efuse on dra7 and am57 parts contains a specific
>> +	 * value indicating the highest available OPP.
>> +	 */
>> +
>> +	switch (efuse) {
>> +	case DRA7_EFUSE_HAS_ALL_MPU_OPP:
>> +	case DRA7_EFUSE_HAS_HIGH_MPU_OPP:
>> +		calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP;
>> +	case DRA7_EFUSE_HAS_OD_MPU_OPP:
>> +		calculated_efuse |= DRA7_EFUSE_OD_MPU_OPP;
>> +	}
>> +
>> +	return calculated_efuse;
>> +}
>> +
>> +static struct ti_cpufreq_soc_data amx3_soc_data = {
>> +	.efuse_xlate = amx3_efuse_xlate,
>> +};
>> +
>> +static struct ti_cpufreq_soc_data dra7_soc_data = {
>> +	.efuse_xlate = dra7_efuse_xlate,
>> +};
>> +
>> +/**
>> + * ti_cpufreq_get_efuse() - Parse and return efuse value present on SoC
>> + * @efuse_value: Set to the value parsed from efuse
>> + *
>> + * Returns error code if efuse not read properly.
>> + */
>> +static int ti_cpufreq_get_efuse(u32 *efuse_value)
>> +{
>> +	struct device *dev = opp_data.cpu;
>> +	struct device_node *np = dev->of_node;
>> +	unsigned int efuse_offset;
>> +	u32 efuse, efuse_mask, efuse_shift;
>> +	int ret;
>> +
>> +	ret = of_property_read_u32_index(np, "ti,syscon-efuse",
>> +					 1, &efuse_offset);
>> +	if (ret) {
>> +		dev_err(dev,
>
> Line break here isn't required.

Ok thanks for catching this.

>
>> +			"No efuse offset provided %s: %d\n",
>> +			np->full_name, ret);
>> +		return ret;
>> +	}
>> +
>> +	ret = of_property_read_u32_index(np, "ti,syscon-efuse", 2,
>> +					 &efuse_mask);
>> +	if (ret)
>> +		efuse_mask = 0xffffffff;
>> +
>> +	ret = of_property_read_u32_index(np, "ti,syscon-efuse", 3,
>> +					 &efuse_shift);
>> +	if (ret)
>> +		efuse_shift = 0;
>
> Why don't you read an array of 3 integers in one go?

To be honest, didn't know I could, will update to use 
of_property_read_u32_array.

>
>> +
>> +	ret = regmap_read(opp_data.opp_efuse, efuse_offset, &efuse);
>> +	if (ret) {
>> +		dev_err(dev,
>> +			"Failed to read the efuse value from syscon: %d\n",
>> +			ret);
>> +		return ret;
>> +	}
>> +
>> +	efuse = (efuse & efuse_mask) >> efuse_shift;
>> +
>> +	*efuse_value = soc_data->efuse_xlate(efuse);
>> +
>> +	return 0;
>> +}
>> +
>> +/**
>> + * ti_cpufreq_get_rev() - Parse and return rev value present on SoC
>> + * @revision_value: Set to the value parsed from revision register
>> + *
>> + * Returns error code if revision not read properly.
>> + */
>> +static int ti_cpufreq_get_rev(u32 *revision_value)
>> +{
>> +	struct device *dev = opp_data.cpu;
>> +	struct device_node *np = dev->of_node;
>> +	unsigned int revision_offset;
>> +	u32 revision;
>> +	int ret;
>> +
>> +	ret = of_property_read_u32_index(np, "ti,syscon-rev",
>> +					 1, &revision_offset);
>> +	if (ret) {
>> +		dev_err(dev,
>> +			"No revision offset provided %s [%d]\n",
>> +			np->full_name, ret);
>> +		return ret;
>> +	}
>> +
>> +	ret = regmap_read(opp_data.revision, revision_offset, &revision);
>> +	if (ret) {
>> +		dev_err(dev,
>> +			"Failed to read the revision number from syscon: %d\n",
>> +			ret);
>> +		return ret;
>> +	}
>> +
>> +	*revision_value = BIT((revision & REVISION_MASK) >> REVISION_SHIFT);
>
> That's an crazy operation.
>
> So you first shifted 0xF << 27, and then right shifted everything by 27 bits :)
>
> You should rather do:
>
> #define REVISION_MASK   0xF
> (revision >> REVISION_SHIFT) & REVISION_MASK

Yeah that's much cleaner I can update.

>
>> +
>> +	return 0;
>> +}
>> +
>> +static int ti_cpufreq_setup_syscon_registers(void)
>> +{
>> +	struct device *dev = opp_data.cpu;
>> +	struct device_node *np = dev->of_node;
>> +
>> +	opp_data.opp_efuse = syscon_regmap_lookup_by_phandle(np,
>> +							"ti,syscon-efuse");
>> +	if (IS_ERR(opp_data.opp_efuse)) {
>> +		dev_dbg(dev,  "\"ti,syscon-efuse\" is missing, cannot use OPPv2 table.\n");
>> +		return PTR_ERR(opp_data.opp_efuse);
>> +	}
>> +
>> +	opp_data.revision = syscon_regmap_lookup_by_phandle(np,
>> +							"ti,syscon-rev");
>> +	if (IS_ERR(opp_data.revision)) {
>> +		dev_dbg(dev,  "\"ti,syscon-rev\" is missing, cannot use OPPv2 table.\n");
>
> These messages are wrong as your code is going to use opp-v2 anyway.

Yes you are right for the case when these properties aren't provided 
isn't provided but opp-v2 table is, I was thinking more of when no 
properties are provided but opp-v1 table has been provided, like on 
legacy DT files. I will need to consider both for this message.

>
>> +		return PTR_ERR(opp_data.revision);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static struct ti_cpufreq_soc_data *ti_cpufreq_get_soc_data(void)
>> +{
>> +	if (of_machine_is_compatible("ti,am33xx") ||
>> +	    of_machine_is_compatible("ti,am4372"))
>> +		return &amx3_soc_data;
>> +	else if (of_machine_is_compatible("ti,dra7"))
>> +		return &dra7_soc_data;
>> +	else
>> +		return NULL;
>> +}
>> +
>> +static int ti_cpufreq_init(void)
>
> __init ?

Whoops, left that out.

>
>> +{
>> +	int ret;
>> +	u32 version[VERSION_COUNT];
>> +
>> +	soc_data = ti_cpufreq_get_soc_data();
>> +	if (!soc_data)
>> +		return -ENODEV;
>
> Why not use of_match_node() and an array of type struct of_device_id instead of
> above function?

Interesting idea, I like it and will do that.

Thanks for your comments.

Regards,
Dave

>
>> +
>> +	opp_data.cpu = get_cpu_device(0);
>> +	if (!opp_data.cpu) {
>> +		pr_err("%s: Failed to get device for CPU0\n", __func__);
>> +		return -ENODEV;
>> +	}
>> +
>> +	if (!of_get_property(opp_data.cpu->of_node, "operating-points-v2",
>> +			     NULL)) {
>> +		dev_info(opp_data.cpu, "OPP-v2 not supported, cpufreq-dt will attempt to use legacy tables.\n");
>> +		goto register_cpufreq_dt;
>> +	}
>> +
>> +	ret = ti_cpufreq_setup_syscon_registers();
>> +	if (ret)
>> +		goto register_cpufreq_dt;
>> +
>> +	/*
>> +	 * OPPs determine whether or not they are supported based on
>> +	 * two metrics:
>> +	 *	0 - SoC Revision
>> +	 *	1 - eFuse value
>> +	 */
>> +	ret = ti_cpufreq_get_rev(&version[0]);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = ti_cpufreq_get_efuse(&version[1]);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = dev_pm_opp_set_supported_hw(opp_data.cpu, version, VERSION_COUNT);
>> +	if (ret) {
>> +		dev_err(opp_data.cpu, "Failed to set supported hardware\n");
>> +		return ret;
>> +	}
>> +
>> +register_cpufreq_dt:
>> +	platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
>> +
>> +	return 0;
>> +}
>> +module_init(ti_cpufreq_init);
>> +
>> +MODULE_DESCRIPTION("TI CPUFreq/OPP hw-supported driver");
>> +MODULE_AUTHOR("Dave Gerlach <d-gerlach at ti.com>");
>> +MODULE_LICENSE("GPL v2");
>> --
>> 2.7.3
>



From d-gerlach at ti.com  Thu May 19 11:35:04 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Thu, 19 May 2016 13:35:04 -0500
Subject: [PATCH 1/2] Documentation: dt: add bindings for ti-cpufreq
In-Reply-To: <20160519031559.GK24777@vireshk-i7>
References: <cover.1463609497.git.d-gerlach@ti.com>
 <f17fbc8acb1e903b9f175f49fe29563b83132faf.1463609497.git.d-gerlach@ti.com>
 <20160519031559.GK24777@vireshk-i7>
Message-ID: <573E0758.3080109@ti.com>

On 05/18/2016 10:15 PM, Viresh Kumar wrote:
> On 18-05-16, 18:30, Dave Gerlach wrote:
>> Add the device tree bindings document for the TI CPUFreq/OPP driver
>> on AM33xx and AM43xx SoCs. The operating-points-v2 binding allows us
>> to provide an opp-supported-hw property for each OPP to define when
>> it is available. This driver is responsible for reading and parsing
>> registers to determine which OPPs can be selectively enabled based
>> on the specific SoC in use by matching against the opp-supported-hw
>> data.
>
> Here and ...
>
>> Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
>> ---
>>   .../devicetree/bindings/cpufreq/ti-cpufreq.txt     | 89 ++++++++++++++++++++++
>>   1 file changed, 89 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt
>>
>> diff --git a/Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt
>> new file mode 100644
>> index 000000000000..f719b2df2a1f
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/cpufreq/ti-cpufreq.txt
>> @@ -0,0 +1,89 @@
>> +Bindings for TI's CPUFreq driver
>> +================================
>> +
>> +The ti-cpufreq driver works with the operating-points-v2 binding described
>> +at [../opp/opp.txt] to make sure the proper OPPs for a platform get enabled
>> +and then creates a "cpufreq-dt" platform device to leverage the cpufreq-dt
>> +driver described in [cpufreq-dt.txt].
>> +
>> +Certain TI SoCs, like those in the am335x, am437x, am57xx, and dra7xx
>> +families support different OPPs depending on the silicon variant in use.
>> +The ti-cpufreq driver uses the revision and an efuse value from the SoC to
>> +provide the OPP framework with supported hardware information. This is used
>> +to determine which OPPs from the operating-points-v2 table get enabled. In
>> +order to maintain backwards compatilibity if this information is not present
>> +the "cpufreq-dt" platform device is still created to attempt to find an
>> +operating-points (v1) table, otherwise no OPPs will be available because
>> +safe OPPs cannot be determined.
>
> ... here..
>
> We shouldn't be talking about the drivers are going to use it, etc.
> This is a binding document, which should be independent of Linux
> kernel. It can be used by other Operating systems as well and so the
> implementation details should be just dropped.

Ah ok, will fix this up.

>
>> +
>> +Required properties:
>> +--------------------
>> +In 'cpus' nodes:
>> +- operating-points-v2: Phandle to the operating-points-v2 table to use
>> +- ti,syscon-efuse: Syscon phandle, offset to efuse register, efuse register
>> +		   mask, and efuse register shift to get the relevant bits
>> +		   that describe OPP availability
>> +- ti,syscon-rev: Syscon and offset used to look up revision value on SoC
>
> These are proper sentences and so maybe a full-stop (.) at the end of
> each line ?

Sure, can do this.

>
>> +
>> +In 'operating-points-v2' table:
>> +- opp-supported-hw: Two bitfields indicating:
>> +	1. Which revision of the SoC the OPP is supported by
>> +	2. Which eFuse bits indicate this OPP is available
>> +
>> +	A bitwise and is performed against these values and if any bit
>
>                    AND or &

Ok will change.

>
>> +	matches, the OPP gets enabled.
>> +
>> +NOTE: Without the above, platform-device for "cpufreq-dt" is still created
>> +      but no determination of which OPPs should be available is done, but this
>> +      allows for use of a v1 operating-points table.
>
> Again, these are implementation details.. should be dropped.

Yes, will do.

>
>> +
>> +Example:
>> +--------
>> +
>> +/* From arch/arm/boot/dts/am4372.dtsi */
>> +cpus {
>> +	cpu: cpu at 0 {
>> +		...
>> +
>> +		operating-points-v2 = <&cpu0_opp_table>;
>> +
>> +		ti,syscon-efuse = <&scm_conf 0x610 0x3f 0>;
>> +		ti,syscon-rev = <&scm_conf 0x600>;
>
> @Rob: Can we add properties to the CPU node just like that ?
>
>> +
>> +		...
>> +	};
>> +};
>> +
>> +cpu0_opp_table: opp_table0 {
>> +	compatible = "operating-points-v2";
>
> Otherwise, you could have added above properties right here and added
> your own compatible string..

I felt they went well with the cpu node but thinking about it more they 
fit just as well here, I'd be fine moving them.

>
>> +	opp50 at 300000000 {
>> +		opp-hz = /bits/ 64 <300000000>;
>> +		opp-microvolt = <950000>;
>> +		opp-supported-hw = <0xFF 0x01>;
>> +		opp-suspend;
>> +	};
>> +
>> +	opp100 at 600000000 {
>> +		opp-hz = /bits/ 64 <600000000>;
>> +		opp-microvolt = <1100000>;
>> +		opp-supported-hw = <0xFF 0x04>;
>> +	};
>> +
>> +	opp120 at 720000000 {
>> +		opp-hz = /bits/ 64 <720000000>;
>> +		opp-microvolt = <1200000>;
>> +		opp-supported-hw = <0xFF 0x08>;
>> +	};
>> +
>> +	oppturbo at 800000000 {
>> +		opp-hz = /bits/ 64 <800000000>;
>> +		opp-microvolt = <1260000>;
>> +		opp-supported-hw = <0xFF 0x10>;
>> +	};
>> +
>> +	oppnitro at 1000000000 {
>> +		opp-hz = /bits/ 64 <1000000000>;
>> +		opp-microvolt = <1325000>;
>> +		opp-supported-hw = <0xFF 0x20>;
>
> so the first one is always FF ? Why have it then ?

Hmmm, this particular platform was a bad choice for the example, I will 
use a different platform that makes use of the first field better. This 
platform supports all OPPs on all revisions, but am335x does not so I 
will use that instead in v2.

Regards,
Dave

>
>> +	};
>> +};
>



From sergei.shtylyov at cogentembedded.com  Thu May 19 11:36:27 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Thu, 19 May 2016 21:36:27 +0300
Subject: [PATCH v3 3/6] ARM: dts: r8a7794: add MSTP10 clocks
In-Reply-To: <CAMuHMdWSfx_Q9xopidpLCbwHhuPKwfokiUXYPpHxf3B2tC+-dw@mail.gmail.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
 <3321354.LNTkVAhXvF@wasted.cogentembedded.com>
 <CAMuHMdVjrVFpEZPukWiLQK473R+7CTqVHc1jj8fktAD9RpH_sw@mail.gmail.com>
 <f0700315-af43-b208-cd91-8ca510bf5da9@cogentembedded.com>
 <CAMuHMdWSfx_Q9xopidpLCbwHhuPKwfokiUXYPpHxf3B2tC+-dw@mail.gmail.com>
Message-ID: <ba23906d-afca-ed5c-511f-bd7531a277a8@cogentembedded.com>

Hello.

On 05/19/2016 08:41 PM, Geert Uytterhoeven wrote:

>>>> --- renesas.orig/include/dt-bindings/clock/r8a7794-clock.h
>>>> +++ renesas/include/dt-bindings/clock/r8a7794-clock.h
>>>> @@ -109,6 +109,34 @@
>>>>  #define R8A7794_CLK_I2C1               30
>>>>  #define R8A7794_CLK_I2C0               31
>>>>
>>>> +/* MSTP10 */
>>>> +#define R8A7794_CLK_SSI_ALL            5
>>>> +#define R8A7794_CLK_SSI9               6
>>>> +#define R8A7794_CLK_SSI8               7
>>>> +#define R8A7794_CLK_SSI7               8
>>>> +#define R8A7794_CLK_SSI6               9
>>>> +#define R8A7794_CLK_SSI5               10
>>>> +#define R8A7794_CLK_SSI4               11
>>>> +#define R8A7794_CLK_SSI3               12
>>>> +#define R8A7794_CLK_SSI2               13
>>>> +#define R8A7794_CLK_SSI1               14
>>>> +#define R8A7794_CLK_SSI0               15
>>>> +#define R8A7794_CLK_SCU_ALL            17
>>>> +#define R8A7794_CLK_SCU_DVC1           18
>>>> +#define R8A7794_CLK_SCU_DVC0           19
>>>> +#define R8A7794_CLK_SCU_CTU1_MIX1      20
>>>> +#define R8A7794_CLK_SCU_CTU0_MIX0      21
>>>> +#define R8A7794_CLK_SCU_SRC9           22
>>>> +#define R8A7794_CLK_SCU_SRC8           23
>>>> +#define R8A7794_CLK_SCU_SRC7           24
>>>
>>>
>>> R-Car E2 does not have SRC7, SRC8, SRC9, ...
>>>
>>>> +#define R8A7794_CLK_SCU_SRC6           25
>>>> +#define R8A7794_CLK_SCU_SRC5           26
>>>> +#define R8A7794_CLK_SCU_SRC4           27
>>>> +#define R8A7794_CLK_SCU_SRC3           28
>>>> +#define R8A7794_CLK_SCU_SRC2           29
>>>> +#define R8A7794_CLK_SCU_SRC1           30
>>>> +#define R8A7794_CLK_SCU_SRC0           31
>>>
>>>
>>> ... and SRC0.
>>
>>
>>    Yet table 7A.12 in the rev1.02 manual lists them all. Your manual
>> doesn't?
>
> I thought you were aware of this, cfr. your "[PATCH] rcar: src: skip
> disabled-SRC nodes"?

    I am, I was just pointing out that this patch was backed by the manual I 
had...

> Gr{oetje,eeting}s,
>
>                         Geert

MBR, Sergei



From balbi at kernel.org  Thu May 19 11:36:57 2016
From: balbi at kernel.org (Felipe Balbi)
Date: Thu, 19 May 2016 21:36:57 +0300
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <20160519145745.GU5995@atomide.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
 <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com>
 <20160518193028.GT5995@atomide.com>
 <0d463add-9fa5-a768-2ba6-34c4126c7817@ti.com>
 <20160519145745.GU5995@atomide.com>
Message-ID: <87shxdlws6.fsf@linux.intel.com>


Hi,

Tony Lindgren <tony at atomide.com> writes:
> * Peter Ujfalusi <peter.ujfalusi at ti.com> [160519 01:10]:
>> On 05/18/2016 10:30 PM, Tony Lindgren wrote:
>> > Ideally the adma support would be a separate loadable module,
>> > similar how the cppi41dma is a child of the OTG controller.
>> 
>> The Master DMA is part of the hsmmc IP block. If the same ADMA module is
>> present on other IPs it might be beneficial to have a helper library to handle
>> it (allocating the descriptor pool, wrinting, updating descriptors, etc).
>
> OK. Yeah if it's part of the MMC controller it makes no sense to
> separate it. So then the conecrns are using alternate DMA
> implementations and keeping PM runtime working :)
>
> BTW, Felipe mentioned that the best thing to do in the long run would
> be to set up sdhci-omap.c operating in ADMA mode.
>
> Felipe, care to summarize what you had in mind?

yeah, just write a new sdhci-omap.c to start moving away from
omap-hsmmc.c, just like it was done for 8250-omap.

At the beginning, it could be just the bare minimum to get it working
and slowly move over stuff like pm runtime, dmaengine, PIO. Move more
platforms over to that driver and, eventually, get rid of omap-hsmmc.c
altogether.

That way, development can be focussed on generic layers (SDHCI) to which
OMAP MMC controller is compliant (apart from the VERSION register
quirk).

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160519/67d87938/attachment.sig>

From stanimir.varbanov at linaro.org  Thu May 19 12:52:34 2016
From: stanimir.varbanov at linaro.org (Stanimir Varbanov)
Date: Thu, 19 May 2016 22:52:34 +0300
Subject: [PATCH 3/5] arm64: dts: msm8916: Add spc compat tag
In-Reply-To: <1463634020-17252-4-git-send-email-andy.gross@linaro.org>
References: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
 <1463634020-17252-4-git-send-email-andy.gross@linaro.org>
Message-ID: <573E1982.7090402@linaro.org>

Hi Andy,

On 05/19/2016 08:00 AM, Andy Gross wrote:
> This patch adds the qcom,idle-state-spc compatible to the SPC idle
> state.  This compatible indicates that the state is one which supports
> freeze.
> 
> Signed-off-by: Andy Gross <andy.gross at linaro.org>
> ---
>  arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> index 208af00..032e411 100644
> --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> @@ -104,7 +104,7 @@
>  
>  		idle-states {

Is this change depends on some another patchset, I cannot find
idle-states dt node on mainline nor linux-next ?

>  			CPU_SPC: spc {
> -				compatible = "arm,idle-state";
> +				compatible = "qcom,idle-state-spc", "arm,idle-state";
>  				arm,psci-suspend-param = <0x40000002>;
>  				entry-latency-us = <130>;
>  				exit-latency-us = <150>;
> 


From robert.jarzmik at free.fr  Thu May 19 12:54:59 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Thu, 19 May 2016 21:54:59 +0200
Subject: [GIT PULL 0/7] ARM: SoC changes for 4.7
In-Reply-To: <8749147.ztcb6kVhye@wuerfel> (Arnd Bergmann's message of "Wed, 18
 May 2016 00:07:24 +0200")
References: <8749147.ztcb6kVhye@wuerfel>
Message-ID: <87eg8xj018.fsf@belgarion.home>

Arnd Bergmann <arnd at arndb.de> writes:

.. zip ... removed Linux and lkml as this is pxa specific.

> Hi Linus,
>
> These are the first seven pull requests for arm-soc this time, there is
> one small follow-up coming once the dependencies for that have landed
> in your tree.
I was wondering if my pull requests will be part of this follow-up ?
I'm speaking of :
 - https://patchwork.ozlabs.org/patch/617118/
 - https://patchwork.ozlabs.org/patch/617119/ 

Even if from my persespective passing this cycle doesn't matter much, I don't
know if this matters to Stephen as CLK_IS_ROOT will remain one more cycle.

Cheers.

--
Robert


From alexandre.belloni at free-electrons.com  Thu May 19 13:00:13 2016
From: alexandre.belloni at free-electrons.com (Alexandre Belloni)
Date: Thu, 19 May 2016 22:00:13 +0200
Subject: [PATCH] ARM: dts: at91: add at91sam9260ek board DT
In-Reply-To: <1463662462-921-1-git-send-email-nicolas.ferre@atmel.com>
References: <1463662462-921-1-git-send-email-nicolas.ferre@atmel.com>
Message-ID: <20160519200013.GM2890@piout.net>

On 19/05/2016 at 14:54:22 +0200, Nicolas Ferre wrote :
> Add Device Tree source file for at91sam9260ek board. This official Atmel
> Evaluation Kit is designed around a SoC based on a ARM 926 core the
> at91sam9260.
> 
> The board is also added to the dts Makefile.
> 
> Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
Acked-by: Alexandre Belloni <alexandre.belloni at free-electrons.com>

> ---
> Hi,
> 
> This DTS file was sitting in my kernel tree for a long time... So, revived and
> updated, here it is as I'm sure it can be useful. Even if the board itself is
> pretty old.
> 
> Bye,
> 
>  arch/arm/boot/dts/Makefile          |   1 +
>  arch/arm/boot/dts/at91sam9260ek.dts | 211 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 212 insertions(+)
>  create mode 100644 arch/arm/boot/dts/at91sam9260ek.dts
> 
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index 8f9f1c2ac96b..6893415a53a3 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -17,6 +17,7 @@ dtb-$(CONFIG_SOC_SAM_V4_V5) += \
>  	evk-pro3.dtb \
>  	tny_a9260.dtb \
>  	usb_a9260.dtb \
> +	at91sam9260ek.dtb \
>  	at91sam9261ek.dtb \
>  	at91sam9263ek.dtb \
>  	tny_a9263.dtb \
> diff --git a/arch/arm/boot/dts/at91sam9260ek.dts b/arch/arm/boot/dts/at91sam9260ek.dts
> new file mode 100644
> index 000000000000..43875d18808f
> --- /dev/null
> +++ b/arch/arm/boot/dts/at91sam9260ek.dts
> @@ -0,0 +1,211 @@
> +/*
> + * Device Tree file for Atmel at91sam9260 Evaluation Kit
> + *
> + *  Copyright (C) 2016 Atmel,
> + *		  2016 Nicolas Ferre <nicolas.ferre at atmel.com>
> + *
> + * 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 "at91sam9260.dtsi"
> +
> +/ {
> +	model = "Atmel at91sam9260ek";
> +	compatible = "atmel,at91sam9260ek", "atmel,at91sam9260", "atmel,at91sam9";
> +
> +	chosen {
> +		stdout-path = &dbgu;
> +	};
> +
> +	memory {
> +		reg = <0x20000000 0x4000000>;
> +	};
> +
> +	clocks {
> +		slow_xtal {
> +			clock-frequency = <32768>;
> +		};
> +
> +		main_xtal {
> +			clock-frequency = <18432000>;
> +		};
> +	};
> +
> +	ahb {
> +		apb {
> +			usb1: gadget at fffa4000 {
> +				atmel,vbus-gpio = <&pioC 5 GPIO_ACTIVE_HIGH>;
> +				status = "okay";
> +			};
> +
> +			mmc0: mmc at fffa8000 {
> +				pinctrl-0 = <
> +					&pinctrl_board_mmc0_slot1
> +					&pinctrl_mmc0_clk
> +					&pinctrl_mmc0_slot1_cmd_dat0
> +					&pinctrl_mmc0_slot1_dat1_3>;
> +				status = "okay";
> +				slot at 1 {
> +					reg = <1>;
> +					bus-width = <4>;
> +					cd-gpios = <&pioC 9 GPIO_ACTIVE_HIGH>;
> +				};
> +			};
> +
> +			usart0: serial at fffb0000 {
> +				pinctrl-0 =
> +					<&pinctrl_usart0
> +					 &pinctrl_usart0_rts
> +					 &pinctrl_usart0_cts
> +					 &pinctrl_usart0_dtr_dsr
> +					 &pinctrl_usart0_dcd
> +					 &pinctrl_usart0_ri>;
> +				status = "okay";
> +			};
> +
> +			usart1: serial at fffb4000 {
> +				status = "okay";
> +			};
> +
> +			ssc0: ssc at fffbc000 {
> +				status = "okay";
> +				pinctrl-0 = <&pinctrl_ssc0_tx>;
> +			};
> +
> +			macb0: ethernet at fffc4000 {
> +				phy-mode = "rmii";
> +				status = "okay";
> +			};
> +
> +			spi0: spi at fffc8000 {
> +				cs-gpios = <0>, <&pioC 11 0>, <0>, <0>;
> +				mtd_dataflash at 0 {
> +					compatible = "atmel,at45", "atmel,dataflash";
> +					spi-max-frequency = <50000000>;
> +					reg = <1>;
> +				};
> +			};
> +
> +			dbgu: serial at fffff200 {
> +				status = "okay";
> +			};
> +
> +			pinctrl at fffff400 {
> +				board {
> +					pinctrl_board_mmc0_slot1: mmc0_slot1-board {
> +						atmel,pins =
> +							<AT91_PIOC 9 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
> +					};
> +				};
> +			};
> +
> +			shdwc at fffffd10 {
> +				atmel,wakeup-counter = <10>;
> +				atmel,wakeup-rtt-timer;
> +			};
> +
> +			rtc at fffffd20 {
> +				atmel,rtt-rtc-time-reg = <&gpbr 0x0>;
> +				status = "okay";
> +			};
> +
> +			watchdog at fffffd40 {
> +				status = "okay";
> +			};
> +
> +			gpbr: syscon at fffffd50 {
> +				status = "okay";
> +			};
> +		};
> +
> +		usb0: ohci at 00500000 {
> +			num-ports = <2>;
> +			status = "okay";
> +		};
> +
> +		nand0: nand at 40000000 {
> +			nand-bus-width = <8>;
> +			nand-ecc-mode = "soft";
> +			nand-on-flash-bbt;
> +			status = "okay";
> +		};
> +	};
> +
> +	gpio_keys {
> +		compatible = "gpio-keys";
> +
> +		btn3 {
> +			label = "Button 3";
> +			gpios = <&pioA 30 GPIO_ACTIVE_LOW>;
> +			linux,code = <0x103>;
> +			gpio-key,wakeup;
> +		};
> +
> +		btn4 {
> +			label = "Button 4";
> +			gpios = <&pioA 31 GPIO_ACTIVE_LOW>;
> +			linux,code = <0x104>;
> +			gpio-key,wakeup;
> +		};
> +	};
> +
> +	i2c at 0 {
> +		status = "okay";
> +
> +		24c512 at 50 {
> +			compatible = "24c512";
> +			reg = <0x50>;
> +		};
> +	};
> +
> +	leds {
> +		compatible = "gpio-leds";
> +
> +		ds1 {
> +			label = "ds1";
> +			gpios = <&pioA 9 GPIO_ACTIVE_HIGH>;
> +			linux,default-trigger = "heartbeat";
> +		};
> +
> +		ds5 {
> +			label = "ds5";
> +			gpios = <&pioA 6 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +};
> -- 
> 2.1.3
> 

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com


From alexandre.belloni at free-electrons.com  Thu May 19 13:00:25 2016
From: alexandre.belloni at free-electrons.com (Alexandre Belloni)
Date: Thu, 19 May 2016 22:00:25 +0200
Subject: [PATCH] ARM: at91: Documentation: update the sama5d2 entry
In-Reply-To: <1463663463-1581-1-git-send-email-nicolas.ferre@atmel.com>
References: <1463663463-1581-1-git-send-email-nicolas.ferre@atmel.com>
Message-ID: <20160519200025.GN2890@piout.net>

On 19/05/2016 at 15:11:03 +0200, Nicolas Ferre wrote :
> Update the Atmel SoC entry for SAMA5D2 with all the product variants. Add the
> datasheet web link, now that it's available, for instant access to full product
> documentation.
> 
> Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
Acked-by: Alexandre Belloni <alexandre.belloni at free-electrons.com>

> ---
>  Documentation/arm/Atmel/README | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/arm/Atmel/README b/Documentation/arm/Atmel/README
> index 0931cf7e2e56..6ca78f818dbf 100644
> --- a/Documentation/arm/Atmel/README
> +++ b/Documentation/arm/Atmel/README
> @@ -91,9 +91,15 @@ the Atmel website: http://www.atmel.com.
>            http://www.atmel.com/Images/Atmel-11238-32-bit-Cortex-A5-Microcontroller-SAMA5D4_Datasheet.pdf
>  
>        - sama5d2 family
> -        - sama5d27
> +        - sama5d21
> +        - sama5d22
> +        - sama5d23
> +        - sama5d24
> +        - sama5d26
> +        - sama5d27 (device superset)
> +        - sama5d28 (device superset + environmental monitors)
>          + Datasheet
> -          Coming soon
> +          http://www.atmel.com/Images/Atmel-11267-32-bit-Cortex-A5-Microcontroller-SAMA5D2_Datasheet.pdf
>  
>  
>  Linux kernel information
> -- 
> 2.1.3
> 

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com


From nkaje at codeaurora.org  Thu May 19 13:14:02 2016
From: nkaje at codeaurora.org (Naveen Kaje)
Date: Thu, 19 May 2016 14:14:02 -0600
Subject: [PATCH v2 2/2] i2c: qup: support SMBus block read
In-Reply-To: <000d01d1b0d3$d70e1f30$852a5d90$@codeaurora.org>
References: <1463006736-24652-1-git-send-email-nkaje@codeaurora.org>
 <1463006736-24652-2-git-send-email-nkaje@codeaurora.org>
 <000d01d1b0d3$d70e1f30$852a5d90$@codeaurora.org>
Message-ID: <757c18e2-562a-9f43-0fb6-ab3e7ac3af88@codeaurora.org>

Hi Sricharan,


On 5/18/2016 1:06 AM, Sricharan wrote:
> Hi,
>
> <snip..>
>
>> +static bool qup_i2c_check_msg_len(struct i2c_msg *msg) {
>> +	return ((msg->flags & I2C_M_RD) && (msg->flags &
>> I2C_M_RECV_LEN)); }
>> +
>> +static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev
>> *qup,
>> +			struct i2c_msg *msg)
>> +{
>> +	int len = 0;
>> +	int data_len = qup_i2c_get_data_len(qup);
>> +
>> +	if (msg->len > 1) {
>> +		tags[len++] = QUP_TAG_V2_DATARD_STOP;
>> +		tags[len++] = data_len - 1;
>> +	} else {
>      So we hit this else part for msg->len = 1 and this case blk.pos = 0
>      will always be true right ?
Yes, will fix that in V3.
>
>> +		if (qup->blk.pos == 0) {
>> +			tags[len++] = QUP_TAG_V2_START;
>> +			tags[len++] = addr & 0xff;
>> +
>> +			if (msg->flags & I2C_M_TEN)
>> +				tags[len++] = addr >> 8;
>> +		}
>> +
>> +		tags[len++] = QUP_TAG_V2_DATARD;
>> +		/* 0 implies 256 bytes */
>> +		if (data_len == QUP_READ_LIMIT)
>> +			tags[len++] = 0;
>> +		else
>> +			tags[len++] = data_len;
>> +	}
>         Even data_len will always be '1' right ?
Yes, but here preferably we use a variable than a number without a context.
>> +	return len;
>> +}
>> +
>>   static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
>>   			    struct i2c_msg *msg,  int is_dma)  { @@ -526,6
>> +559,10 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
>>
>>   	int last = (qup->blk.pos == (qup->blk.count - 1)) && (qup->is_last);
>>
>> +	/* Handle tags for SMBus block read */
>> +	if (qup_i2c_check_msg_len(msg))
>> +		return qup_i2c_set_tags_smb(addr, tags, qup, msg);
>> +
>>   	if (qup->blk.pos == 0) {
>>   		tags[len++] = QUP_TAG_V2_START;
>>   		tags[len++] = addr & 0xff;
>> @@ -1065,9 +1102,17 @@ static int qup_i2c_read_fifo_v2(struct
>> qup_i2c_dev *qup,
>>   				struct i2c_msg *msg)
>>   {
>>   	u32 val;
>> -	int idx, pos = 0, ret = 0, total;
>> +	int idx, pos = 0, ret = 0, total, msg_offset = 0;
>>
>> +	/*
>> +	 * If the message length is already read in
>> +	 * the first byte of the buffer, account for
>> +	 * that by setting the offset
>> +	 */
>> +	if (qup_i2c_check_msg_len(msg) && (msg->len > 1))
>> +		msg_offset = 1;
>>   	total = qup_i2c_get_data_len(qup);
>> +	total -= msg_offset;
>>
>>   	/* 2 extra bytes for read tags */
>>   	while (pos < (total + 2)) {
>> @@ -1087,8 +1132,8 @@ static int qup_i2c_read_fifo_v2(struct
>> qup_i2c_dev *qup,
>>
>>   			if (pos >= (total + 2))
>>   				goto out;
>> -
>> -			msg->buf[qup->pos++] = val & 0xff;
>> +			msg->buf[qup->pos+msg_offset] = val & 0xff;
> 	A space around '+' ?
Thanks, will fix that.
>
>> +			qup->pos++;
>>   		}
>>   	}
>>
>> @@ -1128,6 +1173,22 @@ static int qup_i2c_read_one_v2(struct
>> qup_i2c_dev *qup, struct i2c_msg *msg)
>>   			goto err;
>>
>>   		qup->blk.pos++;
>> +
>> +		/* Handle SMBus block read length */
>> +		if (qup_i2c_check_msg_len(msg) && (msg->len == 1)) {
>> +			if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
>> +				ret = -EPROTO;
>> +				goto err;
>> +			}
>> +			msg->len += msg->buf[0];
>> +			qup->pos = 0;
>> +			qup_i2c_set_read_mode_v2(qup, msg->len);
>> +			qup_i2c_issue_xfer_v2(qup, msg);
>> +			ret = qup_i2c_wait_for_complete(qup, msg);
>> +			if (ret)
>> +				goto err;
> 		Is the issue_xfer_v2 needed inside this here ?
No, qup_i2c_issue_xfer_v2 is needed so that we read rest of the data 
that is indicated by the length we read earlier.
>
>> +			qup_i2c_set_blk_data(qup, msg);
>> +		}
>>   	} while (qup->blk.pos < qup->blk.count);
>     Regards,
>       Sricharan

Thanks,
Naveen
>



From andy.gross at linaro.org  Thu May 19 13:16:47 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 19 May 2016 15:16:47 -0500
Subject: [PATCH 3/5] arm64: dts: msm8916: Add spc compat tag
In-Reply-To: <573E1982.7090402@linaro.org>
References: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
 <1463634020-17252-4-git-send-email-andy.gross@linaro.org>
 <573E1982.7090402@linaro.org>
Message-ID: <CAPBZ5QcF4tKYLxAw1bsNv2Ma=JutRRvta9kiYMHM0XKoXni5SA@mail.gmail.com>

On 19 May 2016 at 14:52, Stanimir Varbanov <stanimir.varbanov at linaro.org> wrote:
> Hi Andy,
>
> On 05/19/2016 08:00 AM, Andy Gross wrote:
>> This patch adds the qcom,idle-state-spc compatible to the SPC idle
>> state.  This compatible indicates that the state is one which supports
>> freeze.
>>
>> Signed-off-by: Andy Gross <andy.gross at linaro.org>
>> ---
>>  arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
>> index 208af00..032e411 100644
>> --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
>> +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
>> @@ -104,7 +104,7 @@
>>
>>               idle-states {
>
> Is this change depends on some another patchset, I cannot find
> idle-states dt node on mainline nor linux-next ?

The cover letter gives a link to the patchset that contains the basis
for the changes.  You can also check out my posted branch which merges
in a part of those changes.

The link to the specific patch is:
http://www.spinics.net/lists/linux-arm-msm/msg19675.html

or you can look at this:
https://git.linaro.org/people/andy.gross/linux-pm.git/shortlog/refs/heads/for-pramod


From timur at codeaurora.org  Thu May 19 13:21:48 2016
From: timur at codeaurora.org (Timur Tabi)
Date: Thu, 19 May 2016 15:21:48 -0500
Subject: [PATCH v2 2/2] i2c: qup: support SMBus block read
In-Reply-To: <757c18e2-562a-9f43-0fb6-ab3e7ac3af88@codeaurora.org>
References: <1463006736-24652-1-git-send-email-nkaje@codeaurora.org>
 <1463006736-24652-2-git-send-email-nkaje@codeaurora.org>
 <000d01d1b0d3$d70e1f30$852a5d90$@codeaurora.org>
 <757c18e2-562a-9f43-0fb6-ab3e7ac3af88@codeaurora.org>
Message-ID: <573E205C.9080701@codeaurora.org>

Naveen Kaje wrote:
>>>
>>> +        tags[len++] = QUP_TAG_V2_DATARD;
>>> +        /* 0 implies 256 bytes */
>>> +        if (data_len == QUP_READ_LIMIT)
>>> +            tags[len++] = 0;
>>> +        else
>>> +            tags[len++] = data_len;
>>> +    }
>>         Even data_len will always be '1' right ?
> Yes, but here preferably we use a variable than a number without a context.

Actually, I would say the opposite.  I would rather see a constant with 
a comment explaining it, than a variable that we know will always 
contain only one number.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum, a Linux Foundation collaborative project.


From scott.branden at broadcom.com  Thu May 19 13:35:46 2016
From: scott.branden at broadcom.com (Scott Branden)
Date: Thu, 19 May 2016 13:35:46 -0700
Subject: [PATCH v7 0/3] ASoC: cygnus: Add audio support for Broadcom
 Cygnus SoC
In-Reply-To: <1463514382-20930-1-git-send-email-simran.rai@broadcom.com>
References: <1463514382-20930-1-git-send-email-simran.rai@broadcom.com>
Message-ID: <573E23A2.4020907@broadcom.com>

Looks good Simran.

Mark, anything else for us to do before this driver can be accepted 
upstream?

On 16-05-17 12:46 PM, Simran Rai wrote:
> From: Simran <ssimran at lbrmn-ssimran-lnxub64.ric.broadcom.com>
>
> Hi,
>
> This patchset contains audio support for Broadcom's Cygnus SoC.
> It contains DT bindings and core audio driver. The audio driver supports
> both capture and playback of Audio PCM samples over I2S/TDM interface and
> provides playback support over SPDIF interface.
>
> This patchset is derived from a previously submitted patchset:
> http://lkml.iu.edu/hypermail/linux/kernel/1503.3/05434.html
>
> This patchset has been tested on Cygnus wireless audio bcm958305K board.
> It is based on v4.6-rc1 and is available from github:
>
> repo: https://github.com/Broadcom/cygnus-linux/tree/cygnus-sound-v7
>
> Changes from v6:
> - DT bindings acknowledged by Rob Herring
> Changes from v5:
> - Fix code style, e.g. change "if" statements to "switch" statements
> - Fix SPDIF output enable register field
> - Set BUFFER_PAIR_ENABLE for both mono, stereo and TDM modes
> - Reflect PCM bit formats for SPDIF, SSP and TDM as supported by
> hardware
> Changes from v4:
> - Fix power suspend function and add power resume function
> - Move clock initialization code from audio driver to clock framework
> Changes from v3:
> - Fix the subject lines to match the style for the subsystem
> Changes from v2:
> - Split patchset 2/2 from v2 into patchsets 2/3 and 3/3.
> - Remove SND_SOC_CYGNUS_DIAG. Diagnostics can be performed using
> standard kernel trace infrastructure.
> - Fix interrupt handler. Acknowledge only those interrupts that are
> handledby ISR.
> - Modify configure_vco() and the pll_macro_entry() struct to make it
> better readable. The functionality did not change.
> - Remove casts on macros
> - Remove surround sound channel grouping from the driver.
> Changes from v1:
> - Address code review comments. Fix print format of type size_t and
> pointer.
>
> Simran Rai (3):
>    ASoC: cygnus: Add DT bindings for Broadcom Cygnus audio
>    ASoC: cygnus: Add Cygnus audio DAI driver
>    ASoC: cygnus: Add Cygnus audio DMA driver
>
>   .../bindings/sound/brcm,cygnus-audio.txt           |   67 +
>   sound/soc/bcm/Kconfig                              |    9 +
>   sound/soc/bcm/Makefile                             |    5 +
>   sound/soc/bcm/cygnus-pcm.c                         |  861 +++++++++++
>   sound/soc/bcm/cygnus-ssp.c                         | 1529 ++++++++++++++++++++
>   sound/soc/bcm/cygnus-ssp.h                         |  139 ++
>   6 files changed, 2610 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/sound/brcm,cygnus-audio.txt
>   create mode 100644 sound/soc/bcm/cygnus-pcm.c
>   create mode 100644 sound/soc/bcm/cygnus-ssp.c
>   create mode 100644 sound/soc/bcm/cygnus-ssp.h
>


From andy.gross at linaro.org  Thu May 19 13:49:36 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 19 May 2016 15:49:36 -0500
Subject: [PATCH] usb: echi-hcd: Add ehci_setup check before echi_shutdown
In-Reply-To: <1463652776-30456-1-git-send-email-srinivas.kandagatla@linaro.org>
References: <1463652776-30456-1-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <CAPBZ5QeK62Bs4Kh4UfQS=cmiGceb6gZcTSgOzncXL3f=ypZ3Gg@mail.gmail.com>

On 19 May 2016 at 05:12, Srinivas Kandagatla
<srinivas.kandagatla at linaro.org> wrote:
> This patch protects system from crashing at shutdown in
> cases where usb host is not added yet from OTG controller driver.
> As ehci_setup() not done yet, so stop accessing registers or
> variables initialized as part of ehci_setup().
>
> The use case is simple, for boards like DB410c where the usb host
> or device functionality is decided based on the micro-usb cable
> presence. If the board boots up with micro-usb connected, the
> OTG driver like echi-msm would not add the usb host by default.
> However a system shutdown would go and access registers and
> uninitialized variables, resulting in below crash.

Works great.

Tested-by: Andy Gross <andy.gross at linaro.org>


From nkaje at codeaurora.org  Thu May 19 14:16:49 2016
From: nkaje at codeaurora.org (Naveen Kaje)
Date: Thu, 19 May 2016 15:16:49 -0600
Subject: [PATCH v2 2/2] i2c: qup: support SMBus block read
In-Reply-To: <573E205C.9080701@codeaurora.org>
References: <1463006736-24652-1-git-send-email-nkaje@codeaurora.org>
 <1463006736-24652-2-git-send-email-nkaje@codeaurora.org>
 <000d01d1b0d3$d70e1f30$852a5d90$@codeaurora.org>
 <757c18e2-562a-9f43-0fb6-ab3e7ac3af88@codeaurora.org>
 <573E205C.9080701@codeaurora.org>
Message-ID: <1d96dfb6-9f0e-14ee-7f75-4c20fd98b183@codeaurora.org>

Hi Timur, Sricharan,

On 5/19/2016 2:21 PM, Timur Tabi wrote:
> Naveen Kaje wrote:
>>>>
>>>> +        tags[len++] = QUP_TAG_V2_DATARD;
>>>> +        /* 0 implies 256 bytes */
>>>> +        if (data_len == QUP_READ_LIMIT)
>>>> +            tags[len++] = 0;
>>>> +        else
>>>> +            tags[len++] = data_len;
>>>> +    }
>>>         Even data_len will always be '1' right ?
>> Yes, but here preferably we use a variable than a number without a 
>> context.
>
> Actually, I would say the opposite.  I would rather see a constant 
> with a comment explaining it, than a variable that we know will always 
> contain only one number.
>
Ok, got it. Will be fixed in V3.
Thanks,
Naveen


From andy.gross at linaro.org  Thu May 19 14:20:50 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Thu, 19 May 2016 16:20:50 -0500
Subject: [PATCH] usb: echi-hcd: Add ehci_setup check before echi_shutdown
In-Reply-To: <1463652776-30456-1-git-send-email-srinivas.kandagatla@linaro.org>
References: <1463652776-30456-1-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <CAPBZ5QcMiMEv1n=WU6aW2PGNsSPZJR42iZge_VUX4aWZ-KKzbw@mail.gmail.com>

On 19 May 2016 at 05:12, Srinivas Kandagatla
<srinivas.kandagatla at linaro.org> wrote:

<snip>

> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -368,6 +368,15 @@ static void ehci_shutdown(struct usb_hcd *hcd)
>  {
>         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
>
> +       /**
> +        * Protect the system from crashing at system shutdown in cases where
> +        * usb host is not added yet from OTG controller driver.
> +        * As ehci_setup() not done yet, so stop accessing registers or
> +        * variables initialized in ehci_setup()
> +        */
> +       if (!ehci->sbrn)
> +               return;
> +
>         spin_lock_irq(&ehci->lock);
>         ehci->shutdown = true;
>         ehci->rh_state = EHCI_RH_STOPPING;


Should we also not check this in ehci_suspend and ehci_resume?  If I
do suspend/resume, it crashes in a similar manner.  I know this goes
beyond the problem scope of the patch.  Perhaps I should send in an
additional patch with the code?

Are there any other places in the ehci-hcd where this needs to be checked?

Regards,

Andy


From rafael at kernel.org  Thu May 19 14:22:07 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Thu, 19 May 2016 23:22:07 +0200
Subject: [PATCH v2 0/5] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
In-Reply-To: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <CAJZ5v0is7c833aQkRm-D+TwLM+eUYeKEAdLOOdrEdT-hrC_M1A@mail.gmail.com>

On Thu, May 19, 2016 at 6:15 PM, Aleksey Makarov
<aleksey.makarov at linaro.org> wrote:
> This patchset adds support for ACPI_TABLE_UPGRADE for ARM64
>
> These patches help with:
>
> 1). During development of a platform, it is much easier to debug
> problems with tables if you can test replacement ones without having to
> respin the firmware. In the server world, you usually don't have the
> firmware source code, so to get it respun could be days-weeks even if
> you are working with the authors closely. We have practically used this
> feature on a number of platforms already and it will continue.
>
> 2). They empower (advanced) users and developers to work around problems
> that they find on platforms. Sure, we want firmware to always be fixed
> and working well, but it is better if folks have the tools.
>
> It's also required for parity with x86 functionality on servers as Redhat
> use that method in their tooling.
>
> The patchset refactors the code introduced by the patches by Lv Zheng [1],
> fixes access to the destination of new ACPI tables as suggested
> by Mark Rutland [2] and enables the feature for ARM64
>
> It was first sent by Jon Masters [3] to linaro-acpi in December 2015
>
> Tested on QEMU (arm64 and x86) and ThunderX
> Should be applied to next-20160519
>
> v2:
> - add Acked-by: Lv Zheng <lv.zheng at intel.com>
> - replace the original patch "ACPI: table upgrade: move early_initrd_acpi_init()
>   to header file" with the patch "ACPI: table upgrade: refactor function
>   definitions".  This new patch is just the original one rewritten following the
>   suggestion by Lv Zheng to use initrd_start, inird_end directly in
>   acpi_table_initrd_init().  It simplifies things noticeably.
> - add Jon's explanations to the cover of the patchset and my explanations
>   to "ACPI: ARM64: support for ACPI_TABLE_UPGRADE"
> - introduce ARCH_HAS_ACPI_TABLE_UPGRADE in a separate patch (Mark Rutland)
> - move arch-specific definition to an arch-specific header in a separate patch
>   (Mark Rutland)
>
> v1:
> https://lkml.kernel.org/g/1463486765-31827-1-git-send-email-aleksey.makarov at linaro.org
>
> [1] https://lkml.kernel.org/g/cover.1460340514.git.lv.zheng at intel.com
> [2] https://lists.linaro.org/pipermail/linaro-acpi/2015-December/006101.html
> [3] https://lists.linaro.org/pipermail/linaro-acpi/2015-December/006099.html
>
> Aleksey Makarov (4):
>   ACPI: table upgrade: use cacheable map for tables
>   ACPI: table upgrade: refactor function definitions
>   ACPI: table upgrade: move arch-specific symbol to asm/acpi.h
>   ACPI: table upgrade: introduce ARCH_HAS_ACPI_TABLE_UPGRADE
>
> Jon Masters (1):
>   ACPI: ARM64: support for ACPI_TABLE_UPGRADE
>
>  arch/arm64/Kconfig            |  1 +
>  arch/arm64/include/asm/acpi.h |  2 ++
>  arch/arm64/kernel/setup.c     |  6 ++++--
>  arch/x86/Kconfig              |  1 +
>  arch/x86/include/asm/acpi.h   |  2 ++
>  arch/x86/kernel/setup.c       |  9 +--------
>  drivers/acpi/Kconfig          |  5 ++++-
>  drivers/acpi/tables.c         | 23 +++++++++--------------
>  include/linux/acpi.h          |  8 ++++++--
>  9 files changed, 30 insertions(+), 27 deletions(-)

I'm fine with the series.

I can queue up patches [1-4/5] for 4.8, but I'll need an ACK from the
ARM64 maintainers for the [5/5].

Thanks,
Rafael


From jon.mason at broadcom.com  Thu May 19 14:35:17 2016
From: jon.mason at broadcom.com (Jon Mason)
Date: Thu, 19 May 2016 17:35:17 -0400
Subject: [PATCH] serial: 8250_early: Add earlycon support for Synopsys
 DesignWare ABP UART
In-Reply-To: <573D1ABD.5020908@huawei.com>
References: <1462946761-11982-1-git-send-email-wangkefeng.wang@huawei.com>
 <573D1ABD.5020908@huawei.com>
Message-ID: <20160519213516.GA12456@broadcom.com>

On Thu, May 19, 2016 at 09:45:33AM +0800, Kefeng Wang wrote:
> +Cc Jon and arm-kernel mailist
> 
> Any comments, thanks.

It works for me.  Please feel free to add

Tested-by: Jon Mason <jon.mason at broadcom.com>

Thanks,
Jon

> 
> Kefeng
> 
> On 2016/5/11 14:06, Kefeng Wang wrote:
> > Some board like Hisilicon D02 uses Synopsys DesignWare ABP UART, declare an
> > OF early console for it, so early console device can be enabled with comand
> > line "earlycon"(without option) via the "stdout-path" property in device-tree.
> > 
> > Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> > ---
> >  drivers/tty/serial/8250/8250_early.c | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
> > index 8d08ff5..85a12f0 100644
> > --- a/drivers/tty/serial/8250/8250_early.c
> > +++ b/drivers/tty/serial/8250/8250_early.c
> > @@ -150,6 +150,7 @@ EARLYCON_DECLARE(uart, early_serial8250_setup);
> >  OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup);
> >  OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup);
> >  OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup);
> > +OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup);
> >  
> >  #ifdef CONFIG_SERIAL_8250_OMAP
> >  
> > 
> 


From austinwc at codeaurora.org  Thu May 19 14:44:27 2016
From: austinwc at codeaurora.org (Austin Christ)
Date: Thu, 19 May 2016 15:44:27 -0600
Subject: [PATCH v3 1/2] i2c: qup: add ACPI support
Message-ID: <1463694268-9473-1-git-send-email-austinwc@codeaurora.org>

From: Naveen Kaje <nkaje at codeaurora.org>

Add support to get the device parameters from ACPI. Assume
that the clocks are managed by firmware.

Signed-off-by: Naveen Kaje <nkaje at codeaurora.org>
Signed-off-by: Austin Christ <austinwc at codeaurora.org>
---
 drivers/i2c/busses/i2c-qup.c | 60 ++++++++++++++++++++++++++++++++------------
 1 file changed, 44 insertions(+), 16 deletions(-)

Changes:
- v3:
 - clean up unused variable
- v2:
 - clean up redundant checks and variables

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index dddd4da..ea6ca5f 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -29,6 +29,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/scatterlist.h>
+#include <linux/acpi.h>
 
 /* QUP Registers */
 #define QUP_CONFIG		0x000
@@ -132,6 +133,10 @@
 /* Max timeout in ms for 32k bytes */
 #define TOUT_MAX			300
 
+/* Default values. Use these if FW query fails */
+#define DEFAULT_CLK_FREQ 100000
+#define DEFAULT_SRC_CLK 20000000
+
 struct qup_i2c_block {
 	int	count;
 	int	pos;
@@ -1354,14 +1359,13 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
 static int qup_i2c_probe(struct platform_device *pdev)
 {
 	static const int blk_sizes[] = {4, 16, 32};
-	struct device_node *node = pdev->dev.of_node;
 	struct qup_i2c_dev *qup;
 	unsigned long one_bit_t;
 	struct resource *res;
 	u32 io_mode, hw_ver, size;
 	int ret, fs_div, hs_div;
-	int src_clk_freq;
-	u32 clk_freq = 100000;
+	u32 src_clk_freq = 0;
+	u32 clk_freq = 0;
 	int blocks;
 
 	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
@@ -1372,7 +1376,12 @@ static int qup_i2c_probe(struct platform_device *pdev)
 	init_completion(&qup->xfer);
 	platform_set_drvdata(pdev, qup);
 
-	of_property_read_u32(node, "clock-frequency", &clk_freq);
+	ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
+	if (ret) {
+		dev_warn(qup->dev, "using default clock-frequency %d",
+			DEFAULT_CLK_FREQ);
+		clk_freq = DEFAULT_CLK_FREQ;
+	}
 
 	if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
 		qup->adap.algo = &qup_i2c_algo;
@@ -1454,20 +1463,31 @@ nodma:
 		return qup->irq;
 	}
 
-	qup->clk = devm_clk_get(qup->dev, "core");
-	if (IS_ERR(qup->clk)) {
-		dev_err(qup->dev, "Could not get core clock\n");
-		return PTR_ERR(qup->clk);
-	}
+	if (ACPI_HANDLE(qup->dev)) {
+		ret = device_property_read_u32(qup->dev,
+				"src-clock-hz", &src_clk_freq);
+		if (ret) {
+			dev_warn(qup->dev, "using default src-clock-hz %d",
+				DEFAULT_SRC_CLK);
+			src_clk_freq = DEFAULT_SRC_CLK;
+		}
+		ACPI_COMPANION_SET(&qup->adap.dev, ACPI_COMPANION(qup->dev));
+	} else {
+		qup->clk = devm_clk_get(qup->dev, "core");
+		if (IS_ERR(qup->clk)) {
+			dev_err(qup->dev, "Could not get core clock\n");
+			return PTR_ERR(qup->clk);
+		}
 
-	qup->pclk = devm_clk_get(qup->dev, "iface");
-	if (IS_ERR(qup->pclk)) {
-		dev_err(qup->dev, "Could not get iface clock\n");
-		return PTR_ERR(qup->pclk);
+		qup->pclk = devm_clk_get(qup->dev, "iface");
+		if (IS_ERR(qup->pclk)) {
+			dev_err(qup->dev, "Could not get iface clock\n");
+			return PTR_ERR(qup->pclk);
+		}
+		qup_i2c_enable_clocks(qup);
+		src_clk_freq = clk_get_rate(qup->clk);
 	}
 
-	qup_i2c_enable_clocks(qup);
-
 	/*
 	 * Bootloaders might leave a pending interrupt on certain QUP's,
 	 * so we reset the core before registering for interrupts.
@@ -1514,7 +1534,6 @@ nodma:
 	size = QUP_INPUT_FIFO_SIZE(io_mode);
 	qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
 
-	src_clk_freq = clk_get_rate(qup->clk);
 	fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
 	hs_div = 3;
 	qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
@@ -1639,6 +1658,14 @@ static const struct of_device_id qup_i2c_dt_match[] = {
 };
 MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
 
+#if IS_ENABLED(CONFIG_ACPI)
+static const struct acpi_device_id qup_i2c_acpi_match[] = {
+	{ "QCOM8010"},
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_ids);
+#endif
+
 static struct platform_driver qup_i2c_driver = {
 	.probe  = qup_i2c_probe,
 	.remove = qup_i2c_remove,
@@ -1646,6 +1673,7 @@ static struct platform_driver qup_i2c_driver = {
 		.name = "i2c_qup",
 		.pm = &qup_i2c_qup_pm_ops,
 		.of_match_table = qup_i2c_dt_match,
+		.acpi_match_table = ACPI_PTR(qup_i2c_acpi_match),
 	},
 };
 
-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.



From austinwc at codeaurora.org  Thu May 19 14:44:28 2016
From: austinwc at codeaurora.org (Austin Christ)
Date: Thu, 19 May 2016 15:44:28 -0600
Subject: [PATCH v3 2/2] i2c: qup: support SMBus block read
In-Reply-To: <1463694268-9473-1-git-send-email-austinwc@codeaurora.org>
References: <1463694268-9473-1-git-send-email-austinwc@codeaurora.org>
Message-ID: <1463694268-9473-2-git-send-email-austinwc@codeaurora.org>

From: Naveen Kaje <nkaje at codeaurora.org>

I2C QUP driver relies on SMBus emulation support from the framework.
To handle SMBus block reads, the driver should check I2C_M_RECV_LEN
flag and should read the first byte received as the message length.

The driver configures the QUP hardware to read one byte. Once the
message length is known from this byte, the QUP hardware is configured
to read the rest.

Signed-off-by: Naveen Kaje <nkaje at codeaurora.org>
Signed-off-by: Austin Christ <austinwc at codeaurora.org>
---
 drivers/i2c/busses/i2c-qup.c | 68 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 65 insertions(+), 3 deletions(-)

Changes:
- v3:
 - clean up redundant checks
 - use constant instead of variable for smbus length field
- v2:
 - rework the smbus block read and break into separate function

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index ea6ca5f..9fbed83 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -517,6 +517,33 @@ static int qup_i2c_get_data_len(struct qup_i2c_dev *qup)
 	return data_len;
 }
 
+static bool qup_i2c_check_msg_len(struct i2c_msg *msg)
+{
+	return ((msg->flags & I2C_M_RD) && (msg->flags & I2C_M_RECV_LEN));
+}
+
+static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev *qup,
+			struct i2c_msg *msg)
+{
+	int len = 0;
+
+	if (msg->len > 1) {
+		tags[len++] = QUP_TAG_V2_DATARD_STOP;
+		tags[len++] = qup_i2c_get_data_len(qup) - 1;
+	} else {
+		tags[len++] = QUP_TAG_V2_START;
+		tags[len++] = addr & 0xff;
+
+		if (msg->flags & I2C_M_TEN)
+			tags[len++] = addr >> 8;
+
+		tags[len++] = QUP_TAG_V2_DATARD;
+		/* Read 1 byte indicating the length of the SMBus message */
+		tags[len++] = 1;
+	}
+	return len;
+}
+
 static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
 			    struct i2c_msg *msg,  int is_dma)
 {
@@ -526,6 +553,10 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
 
 	int last = (qup->blk.pos == (qup->blk.count - 1)) && (qup->is_last);
 
+	/* Handle tags for SMBus block read */
+	if (qup_i2c_check_msg_len(msg))
+		return qup_i2c_set_tags_smb(addr, tags, qup, msg);
+
 	if (qup->blk.pos == 0) {
 		tags[len++] = QUP_TAG_V2_START;
 		tags[len++] = addr & 0xff;
@@ -1065,9 +1096,17 @@ static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
 				struct i2c_msg *msg)
 {
 	u32 val;
-	int idx, pos = 0, ret = 0, total;
+	int idx, pos = 0, ret = 0, total, msg_offset = 0;
 
+	/*
+	 * If the message length is already read in
+	 * the first byte of the buffer, account for
+	 * that by setting the offset
+	 */
+	if (qup_i2c_check_msg_len(msg) && (msg->len > 1))
+		msg_offset = 1;
 	total = qup_i2c_get_data_len(qup);
+	total -= msg_offset;
 
 	/* 2 extra bytes for read tags */
 	while (pos < (total + 2)) {
@@ -1087,8 +1126,8 @@ static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
 
 			if (pos >= (total + 2))
 				goto out;
-
-			msg->buf[qup->pos++] = val & 0xff;
+			msg->buf[qup->pos + msg_offset] = val & 0xff;
+			qup->pos++;
 		}
 	}
 
@@ -1128,6 +1167,24 @@ static int qup_i2c_read_one_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 			goto err;
 
 		qup->blk.pos++;
+
+		/* Handle SMBus block read length */
+		if (qup_i2c_check_msg_len(msg) && (msg->len == 1)) {
+			if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
+				ret = -EPROTO;
+				goto err;
+			}
+			msg->len += msg->buf[0];
+			qup->pos = 0;
+			qup_i2c_set_read_mode_v2(qup, msg->len);
+			ret = qup_i2c_issue_xfer_v2(qup, msg);
+			if (ret)
+				goto err;
+			ret = qup_i2c_wait_for_complete(qup, msg);
+			if (ret)
+				goto err;
+			qup_i2c_set_blk_data(qup, msg);
+		}
 	} while (qup->blk.pos < qup->blk.count);
 
 err:
@@ -1210,6 +1267,11 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 			goto out;
 		}
 
+		if (qup_i2c_check_msg_len(&msgs[idx])) {
+			ret = -EOPNOTSUPP;
+			goto out;
+		}
+
 		if (msgs[idx].flags & I2C_M_RD)
 			ret = qup_i2c_read_one(qup, &msgs[idx]);
 		else
-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.



From javier at osg.samsung.com  Thu May 19 14:52:33 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 19 May 2016 17:52:33 -0400
Subject: [PATCH] ARM: dts: exynos: Remove unneded always-on for regulators on
 Peach boards
Message-ID: <1463694753-7259-1-git-send-email-javier@osg.samsung.com>

The regulator always-on property should only be used for regulators
that either can't be disabled or the drivers for the client devices
are not enabling the regulator and so being disabled due to unused.

There are some max77802 regulators in the Peach Pit and Pi boards
that are always-on but shouldn't since they are enabled by drivers:

BUCK5 is max77802 inl1 supply
BUCK7 is max77802 inl{2,10} supply
BUCK9 is max77802 inl{3,4,5,7} supply
BUCK10 is mmc1 vqmmc supply
LDO9 is adc vdd supply

This patch removes the always-on property for these regulators.

Some regulators should remain always-on even when they are used as
input supplies, because these regulators are also used by other
components that are not described in the DT, for example:

LDO10 is hdmi vdd_osc supply but it's also used as input supply for
the Exynos5420 temperature sensor.

LDO8 is hdmi vdd and vdd_pll supply but it's also used as supply for
the Exynos5420 Display port.

BUCK2 and BUCK6 are the vdd supplies for the EAGLE and KFC clusters.

Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
---

 arch/arm/boot/dts/exynos5420-peach-pit.dts | 5 -----
 arch/arm/boot/dts/exynos5800-peach-pi.dts  | 5 -----
 2 files changed, 10 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
index f9d2e4f1a0e0..c1247402cb17 100644
--- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
@@ -278,7 +278,6 @@
 				regulator-name = "vdd_1v2";
 				regulator-min-microvolt = <1200000>;
 				regulator-max-microvolt = <1200000>;
-				regulator-always-on;
 				regulator-boot-on;
 				regulator-state-mem {
 					regulator-off-in-suspend;
@@ -301,7 +300,6 @@
 				regulator-name = "vdd_1v35";
 				regulator-min-microvolt = <1350000>;
 				regulator-max-microvolt = <1350000>;
-				regulator-always-on;
 				regulator-boot-on;
 				regulator-state-mem {
 					regulator-on-in-suspend;
@@ -323,7 +321,6 @@
 				regulator-name = "vdd_2v";
 				regulator-min-microvolt = <2000000>;
 				regulator-max-microvolt = <2000000>;
-				regulator-always-on;
 				regulator-boot-on;
 				regulator-state-mem {
 					regulator-on-in-suspend;
@@ -334,7 +331,6 @@
 				regulator-name = "vdd_1v8";
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <1800000>;
-				regulator-always-on;
 				regulator-boot-on;
 				regulator-state-mem {
 					regulator-on-in-suspend;
@@ -419,7 +415,6 @@
 				regulator-name = "vdd_ldo9";
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <1800000>;
-				regulator-always-on;
 				regulator-state-mem {
 					regulator-on-in-suspend;
 					regulator-mode = <MAX77802_OPMODE_LP>;
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index 62ceb89e073f..af1c9b9a63f9 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -278,7 +278,6 @@
 				regulator-name = "vdd_1v2";
 				regulator-min-microvolt = <1200000>;
 				regulator-max-microvolt = <1200000>;
-				regulator-always-on;
 				regulator-boot-on;
 				regulator-state-mem {
 					regulator-off-in-suspend;
@@ -301,7 +300,6 @@
 				regulator-name = "vdd_1v35";
 				regulator-min-microvolt = <1350000>;
 				regulator-max-microvolt = <1350000>;
-				regulator-always-on;
 				regulator-boot-on;
 				regulator-state-mem {
 					regulator-on-in-suspend;
@@ -323,7 +321,6 @@
 				regulator-name = "vdd_2v";
 				regulator-min-microvolt = <2000000>;
 				regulator-max-microvolt = <2000000>;
-				regulator-always-on;
 				regulator-boot-on;
 				regulator-state-mem {
 					regulator-on-in-suspend;
@@ -334,7 +331,6 @@
 				regulator-name = "vdd_1v8";
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <1800000>;
-				regulator-always-on;
 				regulator-boot-on;
 				regulator-state-mem {
 					regulator-on-in-suspend;
@@ -419,7 +415,6 @@
 				regulator-name = "vdd_ldo9";
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <1800000>;
-				regulator-always-on;
 				regulator-state-mem {
 					regulator-on-in-suspend;
 					regulator-mode = <MAX77802_OPMODE_LP>;
-- 
2.5.5



From nm at ti.com  Thu May 19 16:20:17 2016
From: nm at ti.com (Nishanth Menon)
Date: Thu, 19 May 2016 18:20:17 -0500
Subject: [PATCH] ARM: OMAP2: Enable Errata 430973 for OMAP3
Message-ID: <1463700017-18527-1-git-send-email-nm@ti.com>

Enable Erratum 430973 similar to commit 5c86c5339c56 ("ARM:
omap2plus_defconfig: Enable ARM erratum 430973 for omap3") - Since
multiple defconfigs can exist from various points of view (multi_v7,
omap2plus etc.. it is always better to enable the erratum from the
Kconfig selection point of view so that downstream kernels dont have
to rediscover this all over again.

Reported-by: Grygorii Strashko <grygorii.strashko at ti.com>
Signed-off-by: Nishanth Menon <nm at ti.com>
---

Note: If this approach is fine, we should probably search and fixup
errata enablement we have done directly in omap2plus_defconfig.

 arch/arm/mach-omap2/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 415a0bd0cda6..e0c796060fa2 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -17,6 +17,7 @@ config ARCH_OMAP3
 	select PM_OPP if PM
 	select PM if CPU_IDLE
 	select SOC_HAS_OMAP2_SDRC
+	select ARM_ERRATA_430973
 
 config ARCH_OMAP4
 	bool "TI OMAP4"
-- 
2.8.0



From wxt at rock-chips.com  Thu May 19 16:56:20 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri, 20 May 2016 07:56:20 +0800
Subject: [PATCH v2 1/3] spi/rockchip: add rk3036/rk3228/rk3368 SoCs for spi
 document
Message-ID: <1463702182-5188-1-git-send-email-wxt@rock-chips.com>

We had supported the rk3036/rk3066/rk3188/rk3228/rk3288/rk3368/rk3399
family SoCs in linux kernel.

Let's add the other SoCs, in order to a better understanding from the
rockchip spi document.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Mark Brown <broonie at kernel.org>
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: linux-rockchip at lists.infradead.org

---

Changes in v2:
- Drop the fallbacks, As Heiko comments on https://patchwork.kernel.org/patch/9127881/
- update commit

 Documentation/devicetree/bindings/spi/spi-rockchip.txt | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-rockchip.txt b/Documentation/devicetree/bindings/spi/spi-rockchip.txt
index 1b14d69..d2ca153 100644
--- a/Documentation/devicetree/bindings/spi/spi-rockchip.txt
+++ b/Documentation/devicetree/bindings/spi/spi-rockchip.txt
@@ -6,10 +6,13 @@ and display controllers using the SPI communication interface.
 Required Properties:
 
 - compatible: should be one of the following.
-    "rockchip,rk3066-spi" for rk3066.
-    "rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188.
-    "rockchip,rk3288-spi", "rockchip,rk3066-spi" for rk3288.
-    "rockchip,rk3399-spi", "rockchip,rk3066-spi" for rk3399.
+    "rockchip,rk3036-spi" for rk3036 SoCS.
+    "rockchip,rk3066-spi" for rk3066 SoCs.
+    "rockchip,rk3188-spi" for rk3188 SoCs.
+    "rockchip,rk3228-spi" for rk3228 SoCS.
+    "rockchip,rk3288-spi" for rk3288 SoCs.
+    "rockchip,rk3368-spi" for rk3368 SoCs.
+    "rockchip,rk3399-spi" for rk3399 SoCs.
 - reg: physical base address of the controller and length of memory mapped
        region.
 - interrupts: The interrupt number to the cpu. The interrupt specifier format
-- 
2.7.4



From wxt at rock-chips.com  Thu May 19 16:56:21 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri, 20 May 2016 07:56:21 +0800
Subject: [PATCH v2 2/3] spi/rockchip: add the rk3036/rk3228/rk3368 to match
 for driver
In-Reply-To: <1463702182-5188-1-git-send-email-wxt@rock-chips.com>
References: <1463702182-5188-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1463702182-5188-2-git-send-email-wxt@rock-chips.com>

In gerenal, the "rockchip,rockchip-spi" string will match the dts
that's great in spi driver. After all the most of rockchip SoCs ar
same spi controller.

Then, we should keep the old style to match the dts various.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Mark Brown <broonie at kernel.org>
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: linux-rockchip at lists.infradead.org
---

Changes in v2: None

 drivers/spi/spi-rockchip.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 6c6c001..dd08b68 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -893,9 +893,12 @@ static const struct dev_pm_ops rockchip_spi_pm = {
 };
 
 static const struct of_device_id rockchip_spi_dt_match[] = {
+	{ .compatible = "rockchip,rk3036-spi", },
 	{ .compatible = "rockchip,rk3066-spi", },
 	{ .compatible = "rockchip,rk3188-spi", },
+	{ .compatible = "rockchip,rk3228-spi", },
 	{ .compatible = "rockchip,rk3288-spi", },
+	{ .compatible = "rockchip,rk3368-spi", },
 	{ .compatible = "rockchip,rk3399-spi", },
 	{ },
 };
-- 
2.7.4



From wxt at rock-chips.com  Thu May 19 16:56:22 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri, 20 May 2016 07:56:22 +0800
Subject: [PATCH v2 3/3] ARM: dts: rockchip: fixes the spi compatible for rk3036
In-Reply-To: <1463702182-5188-1-git-send-email-wxt@rock-chips.com>
References: <1463702182-5188-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1463702182-5188-3-git-send-email-wxt@rock-chips.com>

That's seem the incorrect string to match the spi driver.

Fixes commit f629fcfab2cd
("ARM: dts: rockchip: support the spi for rk3036")

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: linux-rockchip at lists.infradead.org

---

Changes in v2: None

 arch/arm/boot/dts/rk3036.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
index d0f4bb7..a30700a 100644
--- a/arch/arm/boot/dts/rk3036.dtsi
+++ b/arch/arm/boot/dts/rk3036.dtsi
@@ -431,7 +431,7 @@
 	};
 
 	spi: spi at 20074000 {
-		compatible = "rockchip,rockchip-spi";
+		compatible = "rockchip,rk3036-spi";
 		reg = <0x20074000 0x1000>;
 		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
 		clocks =<&cru PCLK_SPI>, <&cru SCLK_SPI>;
-- 
2.7.4



From lv.zheng at intel.com  Thu May 19 17:52:14 2016
From: lv.zheng at intel.com (Zheng, Lv)
Date: Fri, 20 May 2016 00:52:14 +0000
Subject: [PATCH v2 2/5] ACPI: table upgrade: refactor function definitions
In-Reply-To: <1463674518-22477-3-git-send-email-aleksey.makarov@linaro.org>
References: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
 <1463674518-22477-3-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1AE640813FDE7649BE1B193DEA596E883BBA461D@SHSMSX101.ccr.corp.intel.com>

Hi,

Looks real good now. :)
If there is a next version, feel free to add:
Acked-by: Lv Zheng <lv.zheng at intel.com>

Thanks and best regards
-Lv

> From: Aleksey Makarov [mailto:aleksey.makarov at linaro.org]
> Subject: [PATCH v2 2/5] ACPI: table upgrade: refactor function definitions
> 
> Refer initrd_start, initrd_end directly from drivers/acpi/tables.c.
> This allows to use the table upgrade feature in architectures
> other than x86.  Also this simplifies header files.
> 
> The patch renames acpi_table_initrd_init() to acpi_table_upgrade()
> (what reflects the purpose of the function) and removes the unneeded
> wraps early_acpi_table_init() and early_initrd_acpi_init().
> 
> Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
> ---
>  arch/x86/kernel/setup.c |  9 +--------
>  drivers/acpi/tables.c   | 14 ++++----------
>  include/linux/acpi.h    |  8 ++++++--
>  3 files changed, 11 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> index c4e7b39..aac91be 100644
> --- a/arch/x86/kernel/setup.c
> +++ b/arch/x86/kernel/setup.c
> @@ -399,10 +399,6 @@ static void __init reserve_initrd(void)
>  	memblock_free(ramdisk_image, ramdisk_end - ramdisk_image);
>  }
> 
> -static void __init early_initrd_acpi_init(void)
> -{
> -	early_acpi_table_init((void *)initrd_start, initrd_end - initrd_start);
> -}
>  #else
>  static void __init early_reserve_initrd(void)
>  {
> @@ -410,9 +406,6 @@ static void __init early_reserve_initrd(void)
>  static void __init reserve_initrd(void)
>  {
>  }
> -static void __init early_initrd_acpi_init(void)
> -{
> -}
>  #endif /* CONFIG_BLK_DEV_INITRD */
> 
>  static void __init parse_setup_data(void)
> @@ -1146,7 +1139,7 @@ void __init setup_arch(char **cmdline_p)
> 
>  	reserve_initrd();
> 
> -	early_initrd_acpi_init();
> +	acpi_table_upgrade();
> 
>  	vsmp_init();
> 
> diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
> index f829e6a..b05df13 100644
> --- a/drivers/acpi/tables.c
> +++ b/drivers/acpi/tables.c
> @@ -34,6 +34,7 @@
>  #include <linux/bootmem.h>
>  #include <linux/earlycpio.h>
>  #include <linux/memblock.h>
> +#include <linux/initrd.h>
>  #include "internal.h"
> 
>  #ifdef CONFIG_ACPI_CUSTOM_DSDT
> @@ -481,8 +482,10 @@ static DECLARE_BITMAP(acpi_initrd_installed,
> NR_ACPI_INITRD_TABLES);
> 
>  #define MAP_CHUNK_SIZE   (NR_FIX_BTMAPS << PAGE_SHIFT)
> 
> -static void __init acpi_table_initrd_init(void *data, size_t size)
> +void __init acpi_table_upgrade(void)
>  {
> +	void *data = (void *)initrd_start;
> +	size_t size = initrd_end - initrd_start;
>  	int sig, no, table_nr = 0, total_offset = 0;
>  	long offset = 0;
>  	struct acpi_table_header *table;
> @@ -696,10 +699,6 @@ next_table:
>  	}
>  }
>  #else
> -static void __init acpi_table_initrd_init(void *data, size_t size)
> -{
> -}
> -
>  static acpi_status
>  acpi_table_initrd_override(struct acpi_table_header *existing_table,
>  			   acpi_physical_address *address,
> @@ -742,11 +741,6 @@ acpi_os_table_override(struct acpi_table_header
> *existing_table,
>  	return AE_OK;
>  }
> 
> -void __init early_acpi_table_init(void *data, size_t size)
> -{
> -	acpi_table_initrd_init(data, size);
> -}
> -
>  /*
>   * acpi_table_init()
>   *
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 288fac5..ef2ad26 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -208,7 +208,6 @@ void acpi_boot_table_init (void);
>  int acpi_mps_check (void);
>  int acpi_numa_init (void);
> 
> -void early_acpi_table_init(void *data, size_t size);
>  int acpi_table_init (void);
>  int acpi_table_parse(char *id, acpi_tbl_table_handler handler);
>  int __init acpi_parse_entries(char *id, unsigned long table_size,
> @@ -588,7 +587,6 @@ static inline const char *acpi_dev_name(struct
> acpi_device *adev)
>  	return NULL;
>  }
> 
> -static inline void early_acpi_table_init(void *data, size_t size) { }
>  static inline void acpi_early_init(void) { }
>  static inline void acpi_subsystem_init(void) { }
> 
> @@ -997,4 +995,10 @@ static inline struct fwnode_handle
> *acpi_get_next_subnode(struct device *dev,
>  #define acpi_probe_device_table(t)	({ int __r = 0; __r;})
>  #endif
> 
> +#ifdef CONFIG_ACPI_TABLE_UPGRADE
> +void acpi_table_upgrade(void);
> +#else
> +static inline void acpi_table_upgrade(void) { }
> +#endif
> +
>  #endif	/*_LINUX_ACPI_H*/
> --
> 2.8.2



From festevam at gmail.com  Thu May 19 19:07:45 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Thu, 19 May 2016 23:07:45 -0300
Subject: [PATCH] Revert "ARM: imx: add cpufreq device for imx6ul" 
Message-ID: <1463710065-2483-1-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam at nxp.com>

The imx6q-cpufreq does not support mx6ul currently. After running 'reboot'
the following crash is seen:
...
[ 3857.667167] [<c01b2448>] (irq_work_sync) from [<c064ad44>]
(cpufreq_governor_dbs+0x170/0x580)
[ 3857.675713]  r4:00000004 r3:00000001
[ 3857.679384] [<c064abd4>] (cpufreq_governor_dbs) from [<c06480e4>]
(cpufreq_governor+0x64/0x120)
[ 3857.688103]  r10:00000000 r9:dde7a000 r8:c0108044 r7:c1556f80
r6:00000002 r5:ddcea000
[ 3857.696088]  r4:c0d4c5dc
[ 3857.698684] [<c0648080>] (cpufreq_governor) from [<c06493c4>]
(cpufreq_suspend+0x70/0x128)
[ 3857.706967]  r6:c0d4c328 r5:ddcea0dc r4:ddcea000 r3:ddd9c800
[ 3857.712777] [<c0649354>] (cpufreq_suspend) from [<c04da71c>]
(syscore_shutdown+0x4c/0x80)
...

Not registering the cpufreq driver fixes the issue.

This reverts commit 7f7308198f98700be82d123569ea59229a75d3c3.

Cc: <stable at vger.kernel.org> # 4.4.x
Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
---
 arch/arm/mach-imx/mach-imx6ul.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c
index a38b16b..57f174a 100644
--- a/arch/arm/mach-imx/mach-imx6ul.c
+++ b/arch/arm/mach-imx/mach-imx6ul.c
@@ -78,12 +78,6 @@ static void __init imx6ul_init_irq(void)
 	imx6_pm_ccm_init("fsl,imx6ul-ccm");
 }
 
-static void __init imx6ul_init_late(void)
-{
-	if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
-		platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
-}
-
 static const char * const imx6ul_dt_compat[] __initconst = {
 	"fsl,imx6ul",
 	NULL,
@@ -92,6 +86,5 @@ static const char * const imx6ul_dt_compat[] __initconst = {
 DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)")
 	.init_irq	= imx6ul_init_irq,
 	.init_machine	= imx6ul_init_machine,
-	.init_late	= imx6ul_init_late,
 	.dt_compat	= imx6ul_dt_compat,
 MACHINE_END
-- 
1.9.1



From festevam at gmail.com  Thu May 19 19:10:54 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Thu, 19 May 2016 23:10:54 -0300
Subject: mx6ul cannot reboot
In-Reply-To: <CAOMZO5DLz7vBARB+uweDG+tw0UM3EMDb9+_XcLaaBv0GN+im7g@mail.gmail.com>
References: <CAOMZO5DLz7vBARB+uweDG+tw0UM3EMDb9+_XcLaaBv0GN+im7g@mail.gmail.com>
Message-ID: <CAOMZO5CF7g=GOXL_BMRQTZ6UPk+15z3hkxoM3j+KW033Dtp7wA@mail.gmail.com>

On Wed, May 11, 2016 at 6:12 PM, Fabio Estevam <festevam at gmail.com> wrote:
> Hi,
>
> After issuing a 'reboot' command on mx6ul-evk running 4.6-rc I get the
> following problem:

....

> I have only seen this on mx6ul.

The cpufreq-imx6q driver does not support mx6ul yet, so in order to
fix this issue I had to revert 7f7308198f98700be ("ARM: imx: add
cpufreq device for imx6ul"). Just sent a patch with the revert.


From ping.bai at nxp.com  Thu May 19 19:25:18 2016
From: ping.bai at nxp.com (Ping Bai)
Date: Fri, 20 May 2016 02:25:18 +0000
Subject: mx6ul cannot reboot
In-Reply-To: <CAOMZO5CF7g=GOXL_BMRQTZ6UPk+15z3hkxoM3j+KW033Dtp7wA@mail.gmail.com>
References: <CAOMZO5DLz7vBARB+uweDG+tw0UM3EMDb9+_XcLaaBv0GN+im7g@mail.gmail.com>
 <CAOMZO5CF7g=GOXL_BMRQTZ6UPk+15z3hkxoM3j+KW033Dtp7wA@mail.gmail.com>
Message-ID: <DB4PR04MB538C503553C02CE7DDA5385874B0@DB4PR04MB538.eurprd04.prod.outlook.com>

Hi Fabio,

I have already add cpufreq driver support in imx6q-cpufreq.c before adding the cpufreq device.
Commit: a35fc5a33b62a6c658b8ffe7544c966c1776d128.

BR
Jacky Bai

> -----Original Message-----
> From: Fabio Estevam [mailto:festevam at gmail.com]
> Sent: 2016?5?20? 10:11
> To: Shawn Guo <shawnguo at kernel.org>
> Cc: Sascha Hauer <kernel at pengutronix.de>; Yongcai Huang
> <anson.huang at nxp.com>; Frank Li <frank.li at nxp.com>; linux-arm-
> kernel at lists.infradead.org; Ping Bai <ping.bai at nxp.com>
> Subject: Re: mx6ul cannot reboot
> 
> On Wed, May 11, 2016 at 6:12 PM, Fabio Estevam <festevam at gmail.com>
> wrote:
> > Hi,
> >
> > After issuing a 'reboot' command on mx6ul-evk running 4.6-rc I get the
> > following problem:
> 
> ....
> 
> > I have only seen this on mx6ul.
> 
> The cpufreq-imx6q driver does not support mx6ul yet, so in order to fix this
> issue I had to revert 7f7308198f98700be ("ARM: imx: add cpufreq device for
> imx6ul"). Just sent a patch with the revert.

From festevam at gmail.com  Thu May 19 19:39:48 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Thu, 19 May 2016 23:39:48 -0300
Subject: mx6ul cannot reboot
In-Reply-To: <DB4PR04MB538C503553C02CE7DDA5385874B0@DB4PR04MB538.eurprd04.prod.outlook.com>
References: <CAOMZO5DLz7vBARB+uweDG+tw0UM3EMDb9+_XcLaaBv0GN+im7g@mail.gmail.com>
 <CAOMZO5CF7g=GOXL_BMRQTZ6UPk+15z3hkxoM3j+KW033Dtp7wA@mail.gmail.com>
 <DB4PR04MB538C503553C02CE7DDA5385874B0@DB4PR04MB538.eurprd04.prod.outlook.com>
Message-ID: <CAOMZO5A-y86T1HUVDMUnOC6BOKUw87EOCL5oinGu9XNLE-HucQ@mail.gmail.com>

Hi Jacky,

On Thu, May 19, 2016 at 11:25 PM, Ping Bai <ping.bai at nxp.com> wrote:
> Hi Fabio,
>
> I have already add cpufreq driver support in imx6q-cpufreq.c before adding the cpufreq device.
> Commit: a35fc5a33b62a6c658b8ffe7544c966c1776d128.

Ok, I see. Can you try to run kernel 4.6 on a mx6ul board and run a
'reboot' command? You will see a crash related to cpufreq.

cpufreq is broken for mx6ul. Could you please take a look?

Thanks


From festevam at gmail.com  Thu May 19 19:47:55 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Thu, 19 May 2016 23:47:55 -0300
Subject: mx6ul cannot reboot
In-Reply-To: <CAOMZO5A-y86T1HUVDMUnOC6BOKUw87EOCL5oinGu9XNLE-HucQ@mail.gmail.com>
References: <CAOMZO5DLz7vBARB+uweDG+tw0UM3EMDb9+_XcLaaBv0GN+im7g@mail.gmail.com>
 <CAOMZO5CF7g=GOXL_BMRQTZ6UPk+15z3hkxoM3j+KW033Dtp7wA@mail.gmail.com>
 <DB4PR04MB538C503553C02CE7DDA5385874B0@DB4PR04MB538.eurprd04.prod.outlook.com>
 <CAOMZO5A-y86T1HUVDMUnOC6BOKUw87EOCL5oinGu9XNLE-HucQ@mail.gmail.com>
Message-ID: <CAOMZO5CcykTOBqP=ukABnXzA=_1zYLMo_AN3buZn2zWvayvG8g@mail.gmail.com>

On Thu, May 19, 2016 at 11:39 PM, Fabio Estevam <festevam at gmail.com> wrote:
> Hi Jacky,
>
> On Thu, May 19, 2016 at 11:25 PM, Ping Bai <ping.bai at nxp.com> wrote:
>> Hi Fabio,
>>
>> I have already add cpufreq driver support in imx6q-cpufreq.c before adding the cpufreq device.
>> Commit: a35fc5a33b62a6c658b8ffe7544c966c1776d128.
>
> Ok, I see. Can you try to run kernel 4.6 on a mx6ul board and run a
> 'reboot' command? You will see a crash related to cpufreq.
>
> cpufreq is broken for mx6ul. Could you please take a look?

Ok, here is the fix:

--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -212,7 +212,7 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)

        if (of_machine_is_compatible("fsl,imx6ul")) {
                pll2_bus_clk = clk_get(cpu_dev, "pll2_bus");
-               secondary_sel_clk = clk_get(cpu_dev, "secondary_sel");
+               secondary_sel_clk = clk_get(cpu_dev, "secondary_sel_clk");
                if (IS_ERR(pll2_bus_clk) || IS_ERR(secondary_sel_clk)) {
                        dev_err(cpu_dev, "failed to get clocks specific to imx6u
                        ret = -ENOENT;


Will send a proper patch.

Thanks


From saberlily.xia at hisilicon.com  Thu May 19 20:22:40 2016
From: saberlily.xia at hisilicon.com (Xiaqing (A))
Date: Fri, 20 May 2016 11:22:40 +0800
Subject: [PATCH] arm64: cpuinfo: add AArch64 & elf platform for app
 compatibility
In-Reply-To: <20160519131832.GO22378@e104818-lin.cambridge.arm.com>
References: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>
 <20160519104925.GL22378@e104818-lin.cambridge.arm.com>
 <573D9E40.4000705@hisilicon.com>
 <20160519125039.GN22378@e104818-lin.cambridge.arm.com>
 <20160519131832.GO22378@e104818-lin.cambridge.arm.com>
Message-ID: <573E8300.7060106@hisilicon.com>



? 2016/5/19 21:18, Catalin Marinas ??:
> On Thu, May 19, 2016 at 01:50:40PM +0100, Catalin Marinas wrote:
>> On Thu, May 19, 2016 at 07:06:40PM +0800, Xiaqing (A) wrote:
>>>
>>>
>>> ? 2016/5/19 18:49, Catalin Marinas ??:
>>>> On Thu, May 19, 2016 at 10:44:33AM +0800, x00195127 wrote:
>>>>> we find that some apps will read cpuinfo when start up,
>>>>> they need the string  as follows:
>>>>> "Processor       : AArch64 Processor rev 0 (aarch64)"
>>>>>
>>>>> Then thay could load the corresponding libs. But now
>>>>> arm64 platform's cpuinfo don't has this now, so
>>>>> we need add this.
>>>>
>>>> I have the same question as Martinez: what are those apps? If they are
>>>> 64-bit apps, they can always assume AArch64 processor.
>>>
>>> Those are 32-bit apps, and those apps are very popular in our country.
>>
>> 32-bit apps checking for "AArch64" is a really silly idea. What do they
>> do with this information?
>>
>> I'm rather inclined to merge this patch:
>>
>> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
>> index 3808470486f3..623d7d291dd6 100644
>> --- a/arch/arm64/kernel/cpuinfo.c
>> +++ b/arch/arm64/kernel/cpuinfo.c
>> @@ -127,7 +127,8 @@ static int c_show(struct seq_file *m, void *v)
>>   		 * software which does already (at least for 32-bit).
>>   		 */
>>   		seq_puts(m, "Features\t:");
>> -		if (personality(current->personality) == PER_LINUX32) {
>> +		if (is_compat_task() ||
>> +		    personality(current->personality) == PER_LINUX32) {
>>   #ifdef CONFIG_COMPAT
>>   			for (j = 0; compat_hwcap_str[j]; j++)
>>   				if (compat_elf_hwcap & (1 << j))
>
> To make it even more in line with the AArch32 kernel, let's add the
> "model name":
>
> ------------------8<---------------------
> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> index 3808470486f3..6bda9d30a769 100644
> --- a/arch/arm64/kernel/cpuinfo.c
> +++ b/arch/arm64/kernel/cpuinfo.c
> @@ -22,6 +22,7 @@
>
>   #include <linux/bitops.h>
>   #include <linux/bug.h>
> +#include <linux/elf.h>
>   #include <linux/init.h>
>   #include <linux/kernel.h>
>   #include <linux/personality.h>
> @@ -104,6 +105,8 @@ static const char *const compat_hwcap2_str[] = {
>   static int c_show(struct seq_file *m, void *v)
>   {
>   	int i, j;
> +	bool compat = is_compat_task() ||
> +		personality(current->personality) == PER_LINUX32;
>
>   	for_each_online_cpu(i) {
>   		struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
> @@ -115,6 +118,9 @@ static int c_show(struct seq_file *m, void *v)
>   		 * "processor".  Give glibc what it expects.
>   		 */
>   		seq_printf(m, "processor\t: %d\n", i);
> +		if (compat)
> +			seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
> +				   MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
>
>   		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
>   			   loops_per_jiffy / (500000UL/HZ),
> @@ -127,7 +133,7 @@ static int c_show(struct seq_file *m, void *v)
>   		 * software which does already (at least for 32-bit).
>   		 */
>   		seq_puts(m, "Features\t:");
> -		if (personality(current->personality) == PER_LINUX32) {
> +		if (compat) {
>   #ifdef CONFIG_COMPAT
>   			for (j = 0; compat_hwcap_str[j]; j++)
>   				if (compat_elf_hwcap & (1 << j))
> ------------------8<---------------------
>
> With the above, a compat task or a native one with PER_LINUX32
> personality would get:
>
> processor       : 0
> model name      : ARMv8 Processor rev 0 (v8l)
> BogoMIPS        : 100.00
> Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt lpae evtstrm aes pmull sha1 sha2 crc32
> CPU implementer : 0x41
> CPU architecture: 8
> CPU variant     : 0x0
> CPU part        : 0xd03
> CPU revision    : 0
>

I have tested with your patch, the app still can not start up at all.

I'm sorry I didn't explan this exactly before, those apps are 32-bit 
android apps(com.tencent.pao etc.). They want to get the information as
   "*D m3e : GetCPUType:AArch64 Processor rev 0 (aarch64)*"
and I'm sure the process is forked by zygote not zygote64 in android M.

Finally, I find that apps need the information "Processor :", so when I 
change your patch as below, the apps can start up.
----------------------------------------------------------------------
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 3808470..f14ea4a 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -104,6 +104,8 @@ static const char *const compat_hwcap2_str[] = {
  static int c_show(struct seq_file *m, void *v)
  {
         int i, j;
+       bool compat = is_compat_task() ||
+               personality(current->personality) == PER_LINUX32;

         for_each_online_cpu(i) {
                 struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
@@ -116,6 +118,10 @@ static int c_show(struct seq_file *m, void *v)
                  */
                 seq_printf(m, "processor\t: %d\n", i);

+               if (compat)
+                       seq_printf(m, "Processor\t: ARMv8 Processor rev 
%d (%s)\n",
+                                       MIDR_REVISION(midr), 
COMPAT_ELF_PLATFORM);
+
                 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
                            loops_per_jiffy / (500000UL/HZ),
                            loops_per_jiffy / (5000UL/HZ) % 100);
@@ -127,7 +133,7 @@ static int c_show(struct seq_file *m, void *v)
                  * software which does already (at least for 32-bit).
                  */
                 seq_puts(m, "Features\t:");
-               if (personality(current->personality) == PER_LINUX32) {
+               if (compat) {
  #ifdef CONFIG_COMPAT
                         for (j = 0; compat_hwcap_str[j]; j++)
                                 if (compat_elf_hwcap & (1 << j))



From songjun.wu at atmel.com  Thu May 19 20:30:17 2016
From: songjun.wu at atmel.com (Wu, Songjun)
Date: Fri, 20 May 2016 11:30:17 +0800
Subject: [PATCH v2 2/2] [media] atmel-isc: DT binding for Image Sensor
 Controller driver
In-Reply-To: <20160518230522.GA3198@rob-hp-laptop>
References: <1463557590-29318-1-git-send-email-songjun.wu@atmel.com>
 <1463557590-29318-3-git-send-email-songjun.wu@atmel.com>
 <20160518230522.GA3198@rob-hp-laptop>
Message-ID: <c3ffa795-a59a-6453-f371-7bced5944cf6@atmel.com>

Hi Rob,

Thank you for your comments.

On 5/19/2016 07:05, Rob Herring wrote:
> On Wed, May 18, 2016 at 03:46:29PM +0800, Songjun Wu wrote:
>> DT binding documentation for ISC driver.
>>
>> Signed-off-by: Songjun Wu <songjun.wu at atmel.com>
>> ---
>>
>> Changes in v2:
>> - Remove the unit address of the endpoint.
>> - Add the unit address to the clock node.
>> - Avoid using underscores in node names.
>> - Drop the "0x" in the unit address of the i2c node.
>> - Modify the description of "atmel,sensor-preferred".
>> - Add the description for the ISC internal clock.
>>
>>  .../devicetree/bindings/media/atmel-isc.txt        | 100 +++++++++++++++++++++
>>  1 file changed, 100 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/media/atmel-isc.txt
>>
>> diff --git a/Documentation/devicetree/bindings/media/atmel-isc.txt b/Documentation/devicetree/bindings/media/atmel-isc.txt
>> new file mode 100644
>> index 0000000..9e65395
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/media/atmel-isc.txt
>> @@ -0,0 +1,100 @@
>> +Atmel Image Sensor Controller (ISC)
>> +----------------------------------------------
>> +
>> +Required properties for ISC:
>> +- compatible
>> +	Must be "atmel,sama5d2-isc"
>> +- reg
>> +	Physical base address and length of the registers set for the device;
>> +- interrupts
>> +	Should contain IRQ line for the ISC;
>> +- clocks
>> +	List of clock specifiers, corresponding to entries in
>> +	the clock-names property;
>> +	Please refer to clock-bindings.txt.
>> +- clock-names
>> +	Required elements: "hclock", "ispck".
>> +- pinctrl-names, pinctrl-0
>> +	Please refer to pinctrl-bindings.txt.
>> +- clk-in-isc
>> +	ISC internal clock node, it includes two clock nodes,
>> +	isc-ispck and isc-mck.
>
> And you need to describe each of these nodes and the properties they
> have. But more on this below...
>
Should I move the description of clock node below to here?

>> +- atmel,sensor-preferred
>> +	ISC may convert the raw format to the specified format when the sensor
>> +	outputs the raw format, and the sensor may output the specified format
>> +	directly. If sensor is preferred to output the specified format
>> +	directly, the value should be 1 (1-preferred, 0-not).
>> +	The default value is 1.
>
> I don't think this belongs in DT. It sounds more like a configuration
> and userspace decision. It is still not clear what you mean by
> "specified format".
>
Accept, I will remove this.

>> +
>> +ISC supports a single port node with parallel bus. It should contain one
>> +'port' child node with child 'endpoint' node. Please refer to the bindings
>> +defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
>> +
>> +Required properties for the ISC internal clocks:
>> +- #address-cells
>> +	should be 1 (reg is used to encode clk id).
>> +- #size-cells
>> +	should be 0 (reg is used to encode clk id).
>> +- name
>> +	device tree node describing a ISC internal clock.
>> +	* #clock-cells: from common clock binding; should be set to 0.
>> +	* reg: clock id, there are two values,
>> +	       <0> is ISP clock, <1> is master clock.
>> +	* clocks: shall be the isc internal clock source phandles.
>> +		  e.g. clocks = <&isc_clk>, <&iscck>, <&isc_gclk>;
>> +
>> +Example:
>> +isc: isc at f0008000 {
>> +	compatible = "atmel,sama5d2-isc";
>> +	reg = <0xf0008000 0x4000>;
>> +	interrupts = <46 IRQ_TYPE_LEVEL_HIGH 5>;
>> +	clocks = <&isc_clk>, <&isc_ispck>;
>> +	clock-names = "hclock", "ispck";
>> +	atmel,sensor-preferred = <1>;
>> +
>> +	port {
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +
>> +		isc_0: endpoint {
>> +			remote-endpoint = <&ov7740_0>;
>> +			hsync-active = <1>;
>> +			vsync-active = <0>;
>> +			pclk-sample = <1>;
>> +		};
>> +	};
>> +
>> +	clk-in-isc {
>
> Is this really separate from the rest of the isc block. It would be
> much more simple to define all the input clocks at the parent and then
> reference these 2 clocks with <&isc 0> and <&isc 1>.
>
Yes, it's separate from the rest of isc block.
It will register two clocks, one is used in ISC internal processor, the 
other will provide the clock to the sensor outside.
I think it's better that the parent clock is included in node 
'clk-in-isc' node. I will try to optimize this node.

>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +
>> +		isc_ispck: isc-ispck at 0 {
>
> These would need a compatible string otherwise.
>
>> +			#clock-cells = <0>;
>> +			reg = <0>;
>
> Are 0 and 1 meaningful in terms of the hardware description?
>
Yes, It's meaningful.
The register field is different, 0 and 1 can distinguish the different 
clock.

>> +			clocks = <&isc_clk>, <&iscck>;
>> +		};
>> +
>> +		isc_mck: isc-mck at 1 {
>> +			#clock-cells = <0>;
>> +			reg = <1>;
>> +			clocks = <&isc_clk>, <&iscck>, <&isc_gclk>;
>> +		};
>> +	};
>> +};


From sre at kernel.org  Thu May 19 21:12:59 2016
From: sre at kernel.org (Sebastian Reichel)
Date: Fri, 20 May 2016 06:12:59 +0200
Subject: 4.5-rc0 regression: GPRS breaks after very short while
In-Reply-To: <20160518201251.GA22015@amd>
References: <20160518074924.GA20652@amd> <20160518141624.GA8025@earth>
 <20160518201251.GA22015@amd>
Message-ID: <20160520041258.GB22076@earth>

Hi,

On Wed, May 18, 2016 at 10:12:51PM +0200, Pavel Machek wrote:
> > The last one only changes a comment, so not relevant, the other
> > two fix error handling during initialization and are most likely
> > also not the problem. Can you try to bisect the problem?
> 
> It will not be fun, but I guess it is doable. But before I start it
> would be good to know -- does it work for you?

I currently don't have a second SIM card with network access for my
dev phone, so I usually only test without gprs connection. As a
result I don't really know if longer data connection would work.

Also I'm quite busy until next weekend with other stuff. If you did
not find anything until then, I will do some testing/debugging.

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160520/e1685193/attachment.sig>

From horms at verge.net.au  Thu May 19 21:14:46 2016
From: horms at verge.net.au (Simon Horman)
Date: Fri, 20 May 2016 13:14:46 +0900
Subject: [PATCH/RFC 2/3] arm64: dts: salvator-x: add Salvator-X board on
 R8A7796 SoC
In-Reply-To: <CAMuHMdVTMvDsmO1g=FNwpkvx_56guHk_V6Katj8e3qOdyQsjeQ@mail.gmail.com>
References: <1463629845-7115-1-git-send-email-horms+renesas@verge.net.au>
 <1463629845-7115-3-git-send-email-horms+renesas@verge.net.au>
 <CAMuHMdVTMvDsmO1g=FNwpkvx_56guHk_V6Katj8e3qOdyQsjeQ@mail.gmail.com>
Message-ID: <20160520041445.GC25184@verge.net.au>

On Thu, May 19, 2016 at 06:58:11PM +0200, Geert Uytterhoeven wrote:
> On Thu, May 19, 2016 at 5:50 AM, Simon Horman
> <horms+renesas at verge.net.au> wrote:
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
> > @@ -0,0 +1,45 @@
> 
> > +       chosen {
> > +               bootargs = "ignore_loglevel";
> 
> Perhaps you want this to be consistent with the other Renesas boards?
> 
> git grep bootargs -- $(git grep -l renesas, -- arch/arm*/*dts)

I omitted "rw root=/dev/nfs ip=dhcp" which I believe should be added
when the board gets network and thus NFS-root support.

> 
> > +               stdout-path = "serial0:115200n8";
> > +       };
> 
> 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 dave.long at linaro.org  Thu May 19 21:18:03 2016
From: dave.long at linaro.org (David Long)
Date: Fri, 20 May 2016 00:18:03 -0400
Subject: [PATCH v12 01/10] arm64: Add HAVE_REGS_AND_STACK_ACCESS_API
 feature
In-Reply-To: <20160517091446.GB5082@sha-win-210.asiapac.arm.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-2-git-send-email-dave.long@linaro.org>
 <20160517091446.GB5082@sha-win-210.asiapac.arm.com>
Message-ID: <573E8FFB.3000107@linaro.org>

On 05/17/2016 05:14 AM, Huang Shijie wrote:
> On Wed, Apr 27, 2016 at 02:52:56PM -0400, David Long wrote:
>> From: "David A. Long" <dave.long at linaro.org>
>> +/**
>> + * regs_within_kernel_stack() - check the address in the stack
>> + * @regs:      pt_regs which contains kernel stack pointer.
>> + * @addr:      address which is checked.
>> + *
>> + * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
>> + * If @addr is within the kernel stack, it returns true. If not, returns false.
>> + */
>> +bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
>> +{
>> +	return ((addr & ~(THREAD_SIZE - 1))  ==
>> +		(kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))) ||
>> +		on_irq_stack(addr, raw_smp_processor_id());
>> +}
>> +
>> +/**
>> + * regs_get_kernel_stack_nth() - get Nth entry of the stack
>> + * @regs:	pt_regs which contains kernel stack pointer.
>> + * @n:		stack entry number.
>> + *
>> + * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
>> + * is specified by @regs. If the @n th entry is NOT in the kernel stack,
>> + * this returns 0.
>> + */_
>> +unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
>> +{
>> +	unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
>> +
>> +	addr += n;
>> +	if (regs_within_kernel_stack(regs, (unsigned long)addr))
> If the @addr fall in the interrupt stack, the regs_within_kernel_stack()
> will return true. But Is it what we want?
>

Yes, I think it is.  The function is used in regs_get_kernel_stack_nth() 
to make sure the data being asked for (based on the pt_regs saved stack 
pointer) is actually on the stack, whether it's "kernel" stack or "irq" 
stack.

Thanks,
-dl



From horms at verge.net.au  Thu May 19 21:20:27 2016
From: horms at verge.net.au (Simon Horman)
Date: Fri, 20 May 2016 13:20:27 +0900
Subject: [PATCH v3 2/6] ARM: dts: r8a7794: add MSTP5 clocks
In-Reply-To: <23a35d91-7ba3-be23-c8ee-5a056e6a627b@cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
 <1576909.nm8MtQ2Ln5@wasted.cogentembedded.com>
 <CAMuHMdXaUNwOTQ7827+iTTfuRne_Z1F=-qgxu2cs07==AeqzCA@mail.gmail.com>
 <23a35d91-7ba3-be23-c8ee-5a056e6a627b@cogentembedded.com>
Message-ID: <20160520042027.GD25184@verge.net.au>

On Thu, May 19, 2016 at 08:30:12PM +0300, Sergei Shtylyov wrote:
> On 05/19/2016 07:25 PM, Geert Uytterhoeven wrote:
> 
> >>Add some MSTP5 clocks to the R8A7794 device tree.
> >>
> >>Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>
> >>
> >>---
> >>Changes in version 3:
> >>- refreshed the patch.
> >>
> >>Changes in version 2:
> >>- added "the" article to the change log.
> >>
> >> arch/arm/boot/dts/r8a7794.dtsi            |    9 +++++++++
> >> include/dt-bindings/clock/r8a7794-clock.h |    1 +
> >> 2 files changed, 10 insertions(+)
> >>
> >>Index: renesas/arch/arm/boot/dts/r8a7794.dtsi
> >>===================================================================
> >>--- renesas.orig/arch/arm/boot/dts/r8a7794.dtsi
> >>+++ renesas/arch/arm/boot/dts/r8a7794.dtsi
> >>@@ -1172,6 +1172,15 @@
> >>                        clock-indices = <R8A7794_CLK_IRQC>;
> >>                        clock-output-names = "irqc";
> >>                };
> >>+               mstp5_clks: mstp5_clks at e6150144 {
> >>+                       compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
> >>+                       reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>;
> >>+                       clocks = <&hp_clk>, <&extal_clk>, <&p_clk>;
> >>+                       #clock-cells = <1>;
> >>+                       clock-indices = <R8A7794_CLK_AUDIO_DMAC0
> >>+                                        R8A7794_CLK_THERMAL R8A7794_CLK_PWM>;
> >>+                       clock-output-names = "audmac0", "thermal", "pwm";
> >
> >R-Car E2 does not have the thermal module.
> 
>    My "R-Car Series, 2nd Generation User?s Manual: Hardware, Rev.1.02 Oct
> 2014" says it does. What's your source?

Please see chapter 80 of v2.00.
I have also confirmed with the hw team that the thermal sensor is not present.

FWIW until recently I was also going off the older documentation in this
regards and the absence of the thermal block was a bit of a revelation to
me.

> >>+               };
> >>                mstp7_clks: mstp7_clks at e615014c {
> >>                        compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
> >>                        reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>;
> >>Index: renesas/include/dt-bindings/clock/r8a7794-clock.h
> >>===================================================================
> >>--- renesas.orig/include/dt-bindings/clock/r8a7794-clock.h
> >>+++ renesas/include/dt-bindings/clock/r8a7794-clock.h
> >>@@ -67,6 +67,7 @@
> >> #define R8A7794_CLK_IRQC               7
> >>
> >> /* MSTP5 */
> >>+#define R8A7794_CLK_AUDIO_DMAC0                2
> >> #define R8A7794_CLK_THERMAL            22
> >
> >Hence R8A7794_CLK_THERMAL should be removed.
> 
>    Well, remove it then. ;-)
> 
> >> #define R8A7794_CLK_PWM                        23
> >
> >Gr{oetje,eeting}s,
> 
> MBR, Sergei
> 


From horms at verge.net.au  Thu May 19 21:22:35 2016
From: horms at verge.net.au (Simon Horman)
Date: Fri, 20 May 2016 13:22:35 +0900
Subject: [PATCH v3 3/6] ARM: dts: r8a7794: add MSTP10 clocks
In-Reply-To: <ba23906d-afca-ed5c-511f-bd7531a277a8@cogentembedded.com>
References: <2378837.cigT3tNQPe@wasted.cogentembedded.com>
 <3321354.LNTkVAhXvF@wasted.cogentembedded.com>
 <CAMuHMdVjrVFpEZPukWiLQK473R+7CTqVHc1jj8fktAD9RpH_sw@mail.gmail.com>
 <f0700315-af43-b208-cd91-8ca510bf5da9@cogentembedded.com>
 <CAMuHMdWSfx_Q9xopidpLCbwHhuPKwfokiUXYPpHxf3B2tC+-dw@mail.gmail.com>
 <ba23906d-afca-ed5c-511f-bd7531a277a8@cogentembedded.com>
Message-ID: <20160520042235.GE25184@verge.net.au>

On Thu, May 19, 2016 at 09:36:27PM +0300, Sergei Shtylyov wrote:
> Hello.
> 
> On 05/19/2016 08:41 PM, Geert Uytterhoeven wrote:
> 
> >>>>--- renesas.orig/include/dt-bindings/clock/r8a7794-clock.h
> >>>>+++ renesas/include/dt-bindings/clock/r8a7794-clock.h
> >>>>@@ -109,6 +109,34 @@
> >>>> #define R8A7794_CLK_I2C1               30
> >>>> #define R8A7794_CLK_I2C0               31
> >>>>
> >>>>+/* MSTP10 */
> >>>>+#define R8A7794_CLK_SSI_ALL            5
> >>>>+#define R8A7794_CLK_SSI9               6
> >>>>+#define R8A7794_CLK_SSI8               7
> >>>>+#define R8A7794_CLK_SSI7               8
> >>>>+#define R8A7794_CLK_SSI6               9
> >>>>+#define R8A7794_CLK_SSI5               10
> >>>>+#define R8A7794_CLK_SSI4               11
> >>>>+#define R8A7794_CLK_SSI3               12
> >>>>+#define R8A7794_CLK_SSI2               13
> >>>>+#define R8A7794_CLK_SSI1               14
> >>>>+#define R8A7794_CLK_SSI0               15
> >>>>+#define R8A7794_CLK_SCU_ALL            17
> >>>>+#define R8A7794_CLK_SCU_DVC1           18
> >>>>+#define R8A7794_CLK_SCU_DVC0           19
> >>>>+#define R8A7794_CLK_SCU_CTU1_MIX1      20
> >>>>+#define R8A7794_CLK_SCU_CTU0_MIX0      21
> >>>>+#define R8A7794_CLK_SCU_SRC9           22
> >>>>+#define R8A7794_CLK_SCU_SRC8           23
> >>>>+#define R8A7794_CLK_SCU_SRC7           24
> >>>
> >>>
> >>>R-Car E2 does not have SRC7, SRC8, SRC9, ...
> >>>
> >>>>+#define R8A7794_CLK_SCU_SRC6           25
> >>>>+#define R8A7794_CLK_SCU_SRC5           26
> >>>>+#define R8A7794_CLK_SCU_SRC4           27
> >>>>+#define R8A7794_CLK_SCU_SRC3           28
> >>>>+#define R8A7794_CLK_SCU_SRC2           29
> >>>>+#define R8A7794_CLK_SCU_SRC1           30
> >>>>+#define R8A7794_CLK_SCU_SRC0           31
> >>>
> >>>
> >>>... and SRC0.
> >>
> >>
> >>   Yet table 7A.12 in the rev1.02 manual lists them all. Your manual
> >>doesn't?
> >
> >I thought you were aware of this, cfr. your "[PATCH] rcar: src: skip
> >disabled-SRC nodes"?
> 
>    I am, I was just pointing out that this patch was backed by the manual I
> had...

It looks like the manual is incorrect in this regard.
Please update the patch as Geert suggests.

> >Gr{oetje,eeting}s,
> >
> >                        Geert
> 
> MBR, Sergei
> 


From horms at verge.net.au  Thu May 19 21:30:25 2016
From: horms at verge.net.au (Simon Horman)
Date: Fri, 20 May 2016 13:30:25 +0900
Subject: [PATCH 00/23] ARM/arm64: dts: renesas: Fix W=1 dtc warnings
In-Reply-To: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
References: <1463126163-29423-1-git-send-email-geert+renesas@glider.be>
Message-ID: <20160520043025.GI25184@verge.net.au>

Hi Geert,

On Fri, May 13, 2016 at 09:55:40AM +0200, Geert Uytterhoeven wrote:
> 	Hi Simon, Magnus, Morimoto-san, Rob,
> 
> This patch series fixes the new warnings related to Renesas arm32/arm64
> DTSes that can be seen in -next using "make W=1 dtbs", courtesy of
> commit b993734718c01064 ("scripts/dtc: Update to upstream version
> 53bf130b1cdd") in Rob herring's for-next branch. They're all of the
> form:

I am fine with these changes. Would you care to repost after addressing
the minor feedback they have received (mostly from yourself).


From yamada.masahiro at socionext.com  Thu May 19 21:30:10 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Fri, 20 May 2016 13:30:10 +0900
Subject: [PATCH v3] gpio: UniPhier: add driver for UniPhier GPIO controller
In-Reply-To: <CAK7LNAQH+Ge61+MJo2rLmjCBJRnYviT3LyCo0nrOPRQL+RtK2g@mail.gmail.com>
References: <1436841787-7734-1-git-send-email-yamada.masahiro@socionext.com>
 <CACRpkdYaAMw5U3pctf96j0QpY2Qf+e=LX740F0okCmVU6pXkhA@mail.gmail.com>
 <CAK7LNAQ+_ynWT944fPZsHCzMBLtfNu5AnppzaOxNgPSBTvj_tw@mail.gmail.com>
 <CACRpkdZK41P-1JQsL6RiywqFEUj6=g5xJMKy86wDdp6BxLJNzQ@mail.gmail.com>
 <CAK7LNASd9z99RBmUgLVEM1WuLNSzGFM8qzrHwDf58tgGDy2SAw@mail.gmail.com>
 <CACRpkdbBfidn_otxzSV-8HMv2AuD-htUbcRHZ8n9CHAUO=TB9w@mail.gmail.com>
 <CAK7LNAQH+Ge61+MJo2rLmjCBJRnYviT3LyCo0nrOPRQL+RtK2g@mail.gmail.com>
Message-ID: <CAK7LNAQcfrvuG6fD+gN2Ojq4wzCSNa=qpr5kh2QSFJZMCA2UaQ@mail.gmail.com>

Hi Linus,


2015-07-16 16:48 GMT+09:00 Masahiro Yamada <yamada.masahiro at socionext.com>:
> Hi Linus,

>
> OK, I will do it in v4.


I has been away from my GPIO driver upstreaming
for a long time for some reason.

I sent v3 ten months ago.
http://patchwork.ozlabs.org/patch/494860/


In the meantime, there have been various updates
in the GPIO frame-work.

So, I'd like to know the recommended driver coding style
based on 4.7-rc1.


Diving into the git-log so far, I came up the following list:

[1] The "dev" member of gpiochip was renamed to "parent"

[2] The most recommended register function is now
    devm_gpiochip_add_data()

[3] Pass the driver private data to the
    3rd argument of devm_gpiochip_add_data().

[4] Do not use container_of() to covert
    from gpiochip to driver private data.
    Instead, gpiochip_get_data() should be used.

    (I used of_mm_gpio_chip in v3,
     but I needed to use container_of() to
     convert from gpiochip to of_mm_gpio_chip.
     I am wondering if you are happy with it or not.)

[5] gpiochip.owner is being deprecated.
    So, platform drivers need not set
     "gpiochip.owner =  THIS_MODULE".


Correct?
Is there anything else missing?

Any advice is appreciated.


-- 
Best Regards
Masahiro Yamada


From jcm at redhat.com  Thu May 19 21:41:28 2016
From: jcm at redhat.com (Jon Masters)
Date: Fri, 20 May 2016 00:41:28 -0400
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <57331290.7070104@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
Message-ID: <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>

Hi Tomasz, all,

On 05/11/2016 07:08 AM, Tomasz Nowicki wrote:

> On 11.05.2016 12:41, Gabriele Paoloni wrote:

>>> v6 -> v7
>>> - drop quirks handling
>>
>> Maybe I missed something in the v6 discussion thread; when was it
>> decided to drop quirk handling?
> 
> I had such requests in previous series.

A quick note on quirk handling. This, I believe, applies post-merge of
the base infrastructure, which I realize will likely not have quirks.

We've some "gen1" ARMv8 server platforms where we end up doing quirks
(for things like forcing 32-bit config space accessors and the like) due
to people repurposing existing embedded PCIe IP blocks or using them for
the first time (especially in servers), and those being involved in the
design not necessarily seeing this problem ahead of time, or not
realizing that it would be an issue for servers. In the early days of
ARM server designs 3-4 years ago, many of us had never really played
with ECAM or realized how modern topologies are built.

Anyway. We missed this one in our SBSA requirements. They say (words to
the effect of) "thou shalt do PCIe the way it is done on servers" but
they aren't prescriptive, and they don't tell people how that actually
is in reality. That is being fixed. A lot of things are happening behind
the scenes - especially with third party IP block providers (all of whom
myself and others are speaking with directly about this) - to ensure
that the next wave of designs won't repeat these mistakes. We don't have
a time machine, but we can contain this from becoming an ongoing mess
for upstream, and we will do so. It won't be a zoo.

Various proposals have arisen for how to handle quirks in the longer
term, including elaborate frameworks and tables to describe them
generically. I would like to caution against such approaches, especially
in the case that they deviate from practice on x86, or prior to being
standardized fully with other Operating System vendors. I don't expect
there to be too many more than the existing initial set of quirks we
have seen posted. A number of "future" server SoCs have already been
fixed prior to silicon, and new design starts are being warned not to
make this a problem for us to have to clean up later.

So, I would like to suggest that the eventual framework mirror the
existing approach on x86 systems (matching DMI, etc.) and not be made
into some kind of generic, utopia. This is a case where we want there to
be pain involved (and upstream patches required) when people screw up,
so that they have a level of pain in response to ever making this
mistake in the future. If we try to create too grand a generic scheme
and make it too easy to handle this kind of situation beyond the small
number of existing offenders, we undermine efforts to force vendors to
ensure that their IP blocks are compliant going forward.

Side note: if you're a third party IP vendor and we didn't already speak
about this one, drop me a line, and let's collaborate also on your test
frameworks to make sure you're covered as well.

Jon.

-- 
Computer Architect | Sent from my Fedora powered laptop



From dave.long at linaro.org  Thu May 19 22:16:33 2016
From: dave.long at linaro.org (David Long)
Date: Fri, 20 May 2016 01:16:33 -0400
Subject: [PATCH v12 05/10] arm64: Kprobes with single stepping support
In-Reply-To: <57349AE2.3060507@arm.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-6-git-send-email-dave.long@linaro.org>
 <57349AE2.3060507@arm.com>
Message-ID: <573E9DB1.4070109@linaro.org>

On 05/12/2016 11:01 AM, James Morse wrote:
> Hi David, Sandeepa,
>
> On 27/04/16 19:53, David Long wrote:
>> From: Sandeepa Prabhu <sandeepa.s.prabhu at gmail.com>
>
>> diff --git a/arch/arm64/kernel/kprobes.c b/arch/arm64/kernel/kprobes.c
>> new file mode 100644
>> index 0000000..dfa1b1f
>> --- /dev/null
>> +++ b/arch/arm64/kernel/kprobes.c
>> @@ -0,0 +1,520 @@
>> +/*
>> + * arch/arm64/kernel/kprobes.c
>> + *
>> + * Kprobes support for ARM64
>> + *
>> + * Copyright (C) 2013 Linaro Limited.
>> + * Author: Sandeepa Prabhu <sandeepa.prabhu at linaro.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * General Public License for more details.
>> + *
>> + */
>> +#include <linux/kernel.h>
>> +#include <linux/kprobes.h>
>> +#include <linux/module.h>
>> +#include <linux/slab.h>
>> +#include <linux/stop_machine.h>
>> +#include <linux/stringify.h>
>> +#include <asm/traps.h>
>> +#include <asm/ptrace.h>
>> +#include <asm/cacheflush.h>
>> +#include <asm/debug-monitors.h>
>> +#include <asm/system_misc.h>
>> +#include <asm/insn.h>
>> +#include <asm/uaccess.h>
>> +
>> +#include "kprobes-arm64.h"
>> +
>> +#define MIN_STACK_SIZE(addr)	min((unsigned long)MAX_STACK_SIZE,	\
>> +	(unsigned long)current_thread_info() + THREAD_START_SP - (addr))
>
> What if we probe something called on the irq stack?
> This needs the on_irq_stack() checks too, the start/end can be found from the
> per-cpu irq_stack value.
>
> [ ... ]
>

OK.

>> +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
>> +{
>> +	struct jprobe *jp = container_of(p, struct jprobe, kp);
>> +	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
>> +	long stack_ptr = kernel_stack_pointer(regs);
>> +
>> +	kcb->jprobe_saved_regs = *regs;
>> +	memcpy(kcb->jprobes_stack, (void *)stack_ptr,
>> +	       MIN_STACK_SIZE(stack_ptr));
>
> I wonder if we need this stack save/restore?
>
> The comment next to the equivalent code for x86 says:
>> gcc assumes that the callee owns the argument space and could overwrite it,
>> e.g. tailcall optimization. So, to be absolutely safe we also save and
>> restore enough stack bytes to cover the argument area.
>
> On arm64 the first eight arguments are passed in registers, so we might not need
> this stack copy. (sparc and powerpc work like this too, their versions of this
> function don't copy chunks of the stack).
>
> ... then I went looking for functions with >8 arguments...
>
> Looking at the arm64 defconfig dwarf debug data, there are 71 of these that
> don't get inlined, picking at random:
>> rockchip_clk_register_pll() has 13
>> fib_dump_info() has 11
>> vma_merge() has 10
>> vring_create_virtqueue() has 10
> etc...
>
> So we do need this stack copying, so that we can probe these function without
> risking the arguments being modified.
>
> It may be worth including a comment to the effect that this stack save/restore
> is needed for functions that pass >8 arguments where the pre-handler may change
> these values on the stack.
>
>

I can add a comment.

>> +	preempt_enable_no_resched();
>> +	return 1;
>> +}
>> +
>
>
> Thanks,
>
> James
>

Thanks,
-dl



From dave.long at linaro.org  Thu May 19 22:28:19 2016
From: dave.long at linaro.org (David Long)
Date: Fri, 20 May 2016 01:28:19 -0400
Subject: [PATCH v12 06/10] arm64: Treat all entry code as non-kprobe-able
In-Reply-To: <573497FA.5030309@arm.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-7-git-send-email-dave.long@linaro.org>
 <573497FA.5030309@arm.com>
Message-ID: <573EA073.5090409@linaro.org>

On 05/12/2016 10:49 AM, James Morse wrote:
> Hi David, Pratyush
>
> On 27/04/16 19:53, David Long wrote:
>> From: Pratyush Anand <panand at redhat.com>
>>
>> Entry symbols are not kprobe safe. So blacklist them for kprobing.
>>
>> Signed-off-by: Pratyush Anand <panand at redhat.com>
>
>> diff --git a/arch/arm64/kernel/kprobes.c b/arch/arm64/kernel/kprobes.c
>> index dfa1b1f..6a1292b 100644
>> --- a/arch/arm64/kernel/kprobes.c
>> +++ b/arch/arm64/kernel/kprobes.c
>> @@ -29,6 +29,7 @@
>>   #include <asm/system_misc.h>
>>   #include <asm/insn.h>
>>   #include <asm/uaccess.h>
>> +#include <asm-generic/sections.h>
>>
>>   #include "kprobes-arm64.h"
>>
>> @@ -514,6 +515,15 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
>>   	return 1;
>>   }
>>
>> +bool arch_within_kprobe_blacklist(unsigned long addr)
>> +{
>> +	return  (addr >= (unsigned long)__kprobes_text_start &&
>> +		 addr < (unsigned long)__kprobes_text_end) ||
>> +		(addr >= (unsigned long)__entry_text_start &&
>> +		 addr < (unsigned long)__entry_text_end) ||
>> +		 !!search_exception_tables(addr);
>> +}
>> +
>
> Looking at __kvm_hyp_vector, we don't have support for handling breakpoints at
> EL2, so we should forbid kprobing these address ranges too:
> __hyp_text_start -> __hyp_text_end
> __hyp_idmap_text_start -> __hyp_idmap_text_end
>
> These can probably be guarded with is_kernel_in_hyp_mode(), if this is true then
> we are running with VHE where this code runs at the same exception level as the
> rest of the kernel, so we can probe them. (In this case you may want to add
> 'eret' to aarch64_insn_is_branch() in patch 2)
>

OK.

>
> Probing things in the kernel idmap sounds dangerous! Lets blacklist that too:
> __idmap_text_start -> __idmap_text_end
>

OK.

>
>
> Thanks,
>
> James
>



From a.heider at gmail.com  Thu May 19 22:44:06 2016
From: a.heider at gmail.com (Andre Heider)
Date: Fri, 20 May 2016 07:44:06 +0200
Subject: 4.5.0 on sun7i-a20-olinuxino-lime2: libphy: PHY stmmac-0:ffffffff
 not found (regression from rc7)
In-Reply-To: <20160317075202.16b14ed6@arm.com>
References: <56E9413D.9010902@a20.net> <56E945FF.6080005@arm.com>
 <56E94CF4.2060607@arm.com> <56E95B57.1090100@suse.de>
 <56E9776F.3070102@a20.net> <56E99B0C.2070609@arm.com>
 <56E9F2B8.1030605@a20.net> <20160317075202.16b14ed6@arm.com>
Message-ID: <CAHsu+b-t_r93XKLJTUcin6xjhOrFVn3_60vwHkbRt3iHK28CbA@mail.gmail.com>

Giuseppe, Alexandre, et al.,

On Thu, Mar 17, 2016 at 8:52 AM, Marc Zyngier <marc.zyngier at arm.com> wrote:
> On Thu, 17 Mar 2016 00:56:40 +0100
> Bert Lindner <bert at a20.net> wrote:
>> On 2016-03-16 18:42, Marc Zyngier wrote:
>> > On 16/03/16 15:10, Bert Lindner wrote:
>> >> On 2016-03-16 14:10, Andreas F?rber wrote:
>> >>> Am 16.03.2016 um 13:09 schrieb Robin Murphy:
>> >>>> On 16/03/16 11:39, Marc Zyngier wrote:
>> >>>>> On 16/03/16 11:19, Bert Lindner wrote:
...
>> >>>>>> For the board sun7i-a20-olinuxino-lime2, there seems to be a problem
>> >>>>>> with the eth0 PHY in mainline kernel 4.5.0 that developed since
>> >>>>>> 4.5.0-rc7. Ethernet does not work, although eth0 is reported:
...
>> >>>>>> [    9.767125] NET: Registered protocol family 10
>> >>>>>> [   10.357405] libphy: PHY stmmac-0:ffffffff not found
>> >>>>>> [   10.362382] eth0: Could not attach to PHY
>> >>>>>> [   10.366557] stmmac_open: Cannot attach to PHY (error: -19)
...
>> >>> v4 fixes for 4.5 are here:
>> >>>
>> >>> https://patchwork.ozlabs.org/patch/598195/ (revert)
>> >>> https://patchwork.ozlabs.org/patch/598196/
...
>> > Good to know, thanks. Could you also give the potential fix a go (as
>> > mentioned by Andreas)? Just to make sure that whatever gets merged next
>> > will actually fix the issue.
>>
>> Yes sure, it took a while because I had to travel. Confirmed, the
>> v4-for-4.5 fix works well for me, on sun7i-a20-olinuxino-lime2:
>>
>> root at lime2-079f:~# cat /proc/version
>> Linux version 4.5.0-598195-598196-v4 (root at lime2-079f) (gcc version
>> 4.9.1 (Ubuntu/Linaro 4.9.1-16ubuntu6) ) #1 SMP Wed Mar 16 16:44:22 UTC 2016
>>
>> dmesg:
>> [    8.245273] NET: Registered protocol family 10
>> [    9.297406]  RX IPC Checksum Offload disabled
>> [    9.297460]  No MAC Management Counters available
>> [    9.297951] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
>> [   16.285658] sun7i-dwmac 1c50000.ethernet eth0: Link is Up -
>> 1Gbps/Full - flow control rx/tx
>> [   16.285798] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
>>
>> The board is connected to my laptop rather than to a switch, so that
>> might be where the flow control message comes from (not sure). Anyway
>> ethernet works.
>
> Cool, many thanks for taking the time to test and report.
>
> Hopefully Giuseppe will get this merged quickly enough in mainline, and
> it should then trickle into a 4.5-stable release (cc-ing stable on
> these patches would probably be a good idea, BTW).

stmmac is broken on at least Lime2, BananaPi and Cubieboard2 since
v4.5 [0], including all five stable releases :(
The v4.5 patches quoted above are already +4 weeks old, could we
please get them into stable?

Thanks!
Andre

[0] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=823493


From yangbo.lu at nxp.com  Thu May 19 23:05:45 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Fri, 20 May 2016 06:05:45 +0000
Subject: [v10, 7/7] mmc: sdhci-of-esdhc: fix host version for
 T4240-R1.0-R2.0
In-Reply-To: <1462937186.16584.77.camel@buserror.net>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <4448030.Zs8fVnr3nm@wuerfel>
 <HE1PR04MB0889B52134A43C0E7A452B7BF87C0@HE1PR04MB0889.eurprd04.prod.outlook.com>
 <5159406.HOFrj7pRfW@wuerfel> <1462937186.16584.77.camel@buserror.net>
Message-ID: <HE1PR04MB08891B37898C97E1800D701EF84B0@HE1PR04MB0889.eurprd04.prod.outlook.com>

Hi Arnd,

Any comments? 
Please reply when you see the email since we want this eSDHC issue to be fixed soon.

All the patches are Freescale-specific and is to fix the eSDHC driver.
Could we let them merged first if you were talking about a new way of abstracting getting SoC version.


Thanks :)


Best regards,
Yangbo Lu

> -----Original Message-----
> From: Scott Wood [mailto:oss at buserror.net]
> Sent: Wednesday, May 11, 2016 11:26 AM
> To: Arnd Bergmann; linux-arm-kernel at lists.infradead.org
> Cc: Yangbo Lu; linuxppc-dev at lists.ozlabs.org; Mark Rutland;
> devicetree at vger.kernel.org; ulf.hansson at linaro.org; Russell King; Bhupesh
> Sharma; netdev at vger.kernel.org; Joerg Roedel; Kumar Gala; linux-
> mmc at vger.kernel.org; linux-kernel at vger.kernel.org; Yang-Leo Li;
> iommu at lists.linux-foundation.org; Rob Herring; linux-i2c at vger.kernel.org;
> Claudiu Manoil; Santosh Shilimkar; Xiaobo Xie; linux-clk at vger.kernel.org;
> Qiang Zhao
> Subject: Re: [v10, 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-
> R1.0-R2.0
> 
> On Thu, 2016-05-05 at 13:10 +0200, Arnd Bergmann wrote:
> > On Thursday 05 May 2016 09:41:32 Yangbo Lu wrote:
> > > > -----Original Message-----
> > > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > > Sent: Thursday, May 05, 2016 4:32 PM
> > > > To: linuxppc-dev at lists.ozlabs.org
> > > > Cc: Yangbo Lu; linux-mmc at vger.kernel.org;
> > > > devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org;
> > > > linux-kernel at vger.kernel.org; linux-clk at vger.kernel.org;
> > > > linux-i2c at vger.kernel.org; iommu at lists.linux- foundation.org;
> > > > netdev at vger.kernel.org; Mark Rutland; ulf.hansson at linaro.org;
> > > > Russell King; Bhupesh Sharma; Joerg Roedel; Santosh Shilimkar;
> > > > Yang-Leo Li; Scott Wood; Rob Herring; Claudiu Manoil; Kumar Gala;
> > > > Xiaobo Xie; Qiang Zhao
> > > > Subject: Re: [v10, 7/7] mmc: sdhci-of-esdhc: fix host version for
> > > > T4240-
> > > > R1.0-R2.0
> > > >
> > > > On Thursday 05 May 2016 11:12:30 Yangbo Lu wrote:
> > > > > IIRC, it is the same IP block as i.MX and Arnd's point is this
> > > > > won't even compile on !PPC. It is things like this that prevent
> > > > > sharing the driver.
> > >
> > > The whole point of using the MMIO SVR instead of the PPC SPR is so
> > > that it will work on ARM...  The guts driver should build on any
> > > platform as long as OF is enabled, and if it doesn't find a node to
> > > bind to it will return 0 for SVR, and the eSDHC driver will continue
> > > (after printing an error that should be removed) without the ability
> > > to test for errata based on SVR.
> >
> > It feels like a bad design to have to come up with a different method
> > for each SoC type here when they all do the same thing and want to
> > identify some variant of the chip to do device specific quirks.
> >
> > As far as I'm concerned, every driver in drivers/soc that needs to
> > export a symbol to be used by a device driver is an indication that we
> > don't have the right set of abstractions yet. There are cases that are
> > not worth abstracting because the functionality is rather obscure and
> > only a couple of drivers for one particular chip ever need it.
> >
> > Finding out the version of the SoC does not look like this case.
> 
> I'm open to new ways of abstracting this, but can that please be
> discussed after these patches are merged?  This patchset is fixing a
> problem, the existing abstraction is unappealing and not widely adopted,
> a new abstraction is not ready, and we're only touching code for our
> hardware.
> 
> Oh, and the existing abstraction isn't even "existing".  I don't see any
> examples where soc_device is being used like this -- or even any way for
> a driver (the one consuming the information, not the soc "driver") to get
> a reference to the soc_device that's been registered short of searching
> for the device object by name -- and you're asking for new functionality
> in drivers/base/soc.c.
> 
> > > > I think the first four patches take care of building for ARM, but
> > > > the problem remains if you want to enable COMPILE_TEST as we need
> > > > for certain automated checking.
> > >
> > > What specific problem is there with COMPILE_TEST?
> >
> > COMPILE_TEST is solvable here and the way it is implemented in this
> > case (selecting FSL_GUTS from the driver) indeed looks like it works
> > correctly, but it's still awkward that this means building the SoC
> > specific ID stuff into the vmlinux binary for any driver that uses
> > something like that for a particular SoC.
> 
> Please keep in mind that this is a Freescale-specific driver... it's not
> as if we're attaching this dependency to common SDHCI code.
> 
> >
> > > > > Dealing with Si revs is a common problem. We should have a
> > > > > common solution. There is soc_device for this purpose.
> > > >
> > > > Exactly. The last time this came up, I think we agreed to
> > > > implement a helper using glob_match() on the soc_device strings.
> > > > Unfortunately this hasn't happened then, but I'd still prefer that
> > > > over yet another vendor-specific way of dealing with the generic
> issue.
> > >
> > > soc_device would require encoding the SVR as a string and then
> > > decoding the string, which is more complicated and error prone than
> > > having platform-specific code test a platform-specific number.
> >
> > You already need to encode it as a string to register the soc_device,
> 
> No we don't, because we don't already register a soc_device on arm64 or
> ppc (and it looks like whatever does get registered on at least some
> relevant
> arm32 chips is not particularly useful).
> 
> > and the driver just needs to pass a glob string, so the only part that
> > is missing is the generic function that takes the string from the
> > driver and passes that to glob_match for the soc_device.
> 
> "just"
> 
> And what would the glob look like?
> 
> I'd rather not write kernel code as if it were a shell/Perl script.
> 
> > > And when would it get registered on arm64, which doesn't have
> > > platform code?
> >
> > Whenever the soc driver is loaded, as is the case now. The match
> > function can return -EPROBE_DEFER if no SoC device is registered yet.
> 
> That's too late for some places where we need access to SVR, e.g. clock
> drivers (which use CLK_OF_DECLARE and are initialized very early, not as
> part of the driver model and thus can't defer).  Currently we have an
> #ifdef CONFIG_PPC for this in drivers/clk/clk-qoriq.c... Maybe we should
> have done that here as well, and saved some grief. :-)  At least until an
> erratum pops up on an ARM-based chip.
> 
> And what happens if we're running on arm32, and thus the arch code
> already registered an soc_device with a different (and less useful)
> encoding?
> 
> -Scott


From pramod.gurav at linaro.org  Thu May 19 23:09:33 2016
From: pramod.gurav at linaro.org (Pramod Gurav)
Date: Fri, 20 May 2016 11:39:33 +0530
Subject: [PATCH 0/5] Qualcomm Suspend to Idle Support
In-Reply-To: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
References: <1463634020-17252-1-git-send-email-andy.gross@linaro.org>
Message-ID: <CANYu_0u7Q-iTDB17mmfByPULXgzqjnSQ1w_7qUg-ms9OBkdmGw@mail.gmail.com>

On 19 May 2016 at 10:30, Andy Gross <andy.gross at linaro.org> wrote:
> This set of patches adds suspend to idle support for the Qualcomm APQ8084
> and MSM8916 platforms.  The patches add a minimal set of suspend ops and
> init functions to properly configure the enter_freeze function.
>
> This patch set is based on the work done in the following:
> [RFC v3 00/12] PM: SoC idle support using PM domains
> http://comments.gmane.org/gmane.linux.ports.arm.msm/17966
>
> The relevant prerequisites are the PSCI enablement DT patches.  PSCI based
> firmware is also required for the MSM8916 to work properly.
>
> Andy Gross (5):
>   soc: qcom: Add suspend to idle support
>   arm: defconfig: Add Qualcomm Suspend options
>   arm64: dts: msm8916: Add spc compat tag

Tested this series on DB410C. So for these three patches:

Tested-by: Pramod Gurav <pramod.gurav at linaro.org>

>   ARM: dts: qcom: Remove size elements from pmic reg
>   ARM: dts: qcom: pma8084: Add pwrkey entry
>
>  arch/arm/boot/dts/qcom-pma8084.dtsi   | 20 ++++++---
>  arch/arm64/boot/dts/qcom/msm8916.dtsi |  2 +-
>  arch/arm64/configs/defconfig          |  2 +
>  drivers/soc/qcom/Makefile             |  1 +
>  drivers/soc/qcom/suspend.c            | 77 +++++++++++++++++++++++++++++++++++
>  5 files changed, 95 insertions(+), 7 deletions(-)
>  create mode 100644 drivers/soc/qcom/suspend.c
>
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From geert at linux-m68k.org  Thu May 19 23:49:35 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Fri, 20 May 2016 08:49:35 +0200
Subject: [PATCH/RFC 2/3] arm64: dts: salvator-x: add Salvator-X board on
 R8A7796 SoC
In-Reply-To: <20160520041445.GC25184@verge.net.au>
References: <1463629845-7115-1-git-send-email-horms+renesas@verge.net.au>
 <1463629845-7115-3-git-send-email-horms+renesas@verge.net.au>
 <CAMuHMdVTMvDsmO1g=FNwpkvx_56guHk_V6Katj8e3qOdyQsjeQ@mail.gmail.com>
 <20160520041445.GC25184@verge.net.au>
Message-ID: <CAMuHMdXTrLiu5e1Ki6UXmJ1WJ1fWLFYOrmjGNfmRM9Goeha-vA@mail.gmail.com>

Hi Simon,

On Fri, May 20, 2016 at 6:14 AM, Simon Horman <horms at verge.net.au> wrote:
> On Thu, May 19, 2016 at 06:58:11PM +0200, Geert Uytterhoeven wrote:
>> On Thu, May 19, 2016 at 5:50 AM, Simon Horman
>> <horms+renesas at verge.net.au> wrote:
>> > --- /dev/null
>> > +++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
>> > @@ -0,0 +1,45 @@
>>
>> > +       chosen {
>> > +               bootargs = "ignore_loglevel";
>>
>> Perhaps you want this to be consistent with the other Renesas boards?
>>
>> git grep bootargs -- $(git grep -l renesas, -- arch/arm*/*dts)
>
> I omitted "rw root=/dev/nfs ip=dhcp" which I believe should be added
> when the board gets network and thus NFS-root support.

Fair enough.

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

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 geert+renesas at glider.be  Fri May 20 00:10:00 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 20 May 2016 09:10:00 +0200
Subject: [PATCH v2 09/23] ARM: dts: sh73a0: Fix W=1 dtc warnings
In-Reply-To: <1463728214-13838-1-git-send-email-geert+renesas@glider.be>
References: <1463728214-13838-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463728214-13838-10-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /cache-controller has a reg or ranges property, but no unit name

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
v2:
  - No changes.
---
 arch/arm/boot/dts/sh73a0.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
index c4f434cdec60f075..032fe2f14b16998f 100644
--- a/arch/arm/boot/dts/sh73a0.dtsi
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -55,7 +55,7 @@
 		      <0xf0000100 0x100>;
 	};
 
-	L2: cache-controller {
+	L2: cache-controller at f0100000 {
 		compatible = "arm,pl310-cache";
 		reg = <0xf0100000 0x1000>;
 		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
-- 
1.9.1



From geert+renesas at glider.be  Fri May 20 00:10:14 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Fri, 20 May 2016 09:10:14 +0200
Subject: [PATCH v2 23/23] arm64: dts: salvator-x: Fix W=1 dtc warnings
In-Reply-To: <1463728214-13838-1-git-send-email-geert+renesas@glider.be>
References: <1463728214-13838-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1463728214-13838-24-git-send-email-geert+renesas@glider.be>

Warning (unit_address_vs_reg): Node /regulator at 1 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 2 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 3 has a unit name, but no reg property
Warning (unit_address_vs_reg): Node /regulator at 4 has a unit name, but no reg property

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
v2:
  - No changes.
---
 arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
index 84082922edb219ab..98f02631a0f0c66c 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
+++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
@@ -62,7 +62,7 @@
 		clock-frequency = <24576000>;
 	};
 
-	vcc_sdhi0: regulator at 1 {
+	vcc_sdhi0: regulator-vcc-sdhi0 {
 		compatible = "regulator-fixed";
 
 		regulator-name = "SDHI0 Vcc";
@@ -73,7 +73,7 @@
 		enable-active-high;
 	};
 
-	vccq_sdhi0: regulator at 2 {
+	vccq_sdhi0: regulator-vccq-sdhi0 {
 		compatible = "regulator-gpio";
 
 		regulator-name = "SDHI0 VccQ";
@@ -86,7 +86,7 @@
 			  1800000 0>;
 	};
 
-	vcc_sdhi3: regulator at 3 {
+	vcc_sdhi3: regulator-vcc-sdhi3 {
 		compatible = "regulator-fixed";
 
 		regulator-name = "SDHI3 Vcc";
@@ -97,7 +97,7 @@
 		enable-active-high;
 	};
 
-	vccq_sdhi3: regulator at 4 {
+	vccq_sdhi3: regulator-vccq-sdhi3 {
 		compatible = "regulator-gpio";
 
 		regulator-name = "SDHI3 VccQ";
-- 
1.9.1



From kernel at martin.sperl.org  Fri May 20 00:23:15 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Fri, 20 May 2016 07:23:15 +0000
Subject: [PATCH 0/2] ARM: bcm2835: probe clock and sdram driver early
Message-ID: <1463728997-8241-1-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Probe the clock and sdram driver early during the boot process.
This is done to minimize the risk that the PLLD_CORE0 or PLLD
clocks get disabled by another driver.

Such a situation results in the SDRAM stopping to work, which
we can trigger easily with current kernels when there are only a
few clocks enabled.

Right now both drivers are registered with core_initcall.
I am unsure if there is any link-ordering that could
impact us - if such is the case we will need to move the
priorities of one of the drivers slightly. Recommendations?

Note that this patchset requires the sdram memory driver patch
to be applied first.

Martin Sperl (2):
  clk: bcm2835: register clocks early
  memory: bcm2835: enable driver early in the boot process

 drivers/clk/bcm/clk-bcm2835.c  | 18 +++++++++++++++---
 drivers/memory/bcm2835-sdram.c | 10 +++++++++-
 2 files changed, 24 insertions(+), 4 deletions(-)

--
2.1.4


From kernel at martin.sperl.org  Fri May 20 00:23:16 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Fri, 20 May 2016 07:23:16 +0000
Subject: [PATCH 1/2] clk: bcm2835: register clocks early
In-Reply-To: <1463728997-8241-1-git-send-email-kernel@martin.sperl.org>
References: <1463728997-8241-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463728997-8241-2-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Register the clocks early during the boot process,
so that special/critical clocks can get enabled early on
in the boot process avoiding the risk of disabling a clock,
pll_divider or pll when a claiming driver fails to install
propperly - maybe it needs to defer.

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 drivers/clk/bcm/clk-bcm2835.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 085e521..6aaeab4 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1825,6 +1825,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
 	const struct bcm2835_clk_desc *desc;
 	const size_t asize = ARRAY_SIZE(clk_desc_array);
 	size_t i;
+	int err;
 
 	cprman = devm_kzalloc(dev,
 			      sizeof(*cprman) + asize * sizeof(*clks),
@@ -1855,8 +1856,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
 			clks[i] = desc->clk_register(cprman, desc->data);
 	}
 
-	return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
-				   &cprman->onecell);
+	err = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
+				  &cprman->onecell);
+	if (err)
+		return err;
+
+	/* note that we have registered all the clocks */
+	dev_dbg(dev, "registered %d clocks\n", asize);
+
+	return 0;
 }
 
 static const struct of_device_id bcm2835_clk_of_match[] = {
@@ -1873,7 +1881,11 @@ static struct platform_driver bcm2835_clk_driver = {
 	.probe          = bcm2835_clk_probe,
 };
 
-builtin_platform_driver(bcm2835_clk_driver);
+static int __init __bcm2835_clk_driver_init(void)
+{
+	return platform_driver_register(&bcm2835_clk_driver);
+}
+core_initcall(__bcm2835_clk_driver_init);
 
 MODULE_AUTHOR("Eric Anholt <eric at anholt.net>");
 MODULE_DESCRIPTION("BCM2835 clock driver");
-- 
2.1.4



From kernel at martin.sperl.org  Fri May 20 00:23:17 2016
From: kernel at martin.sperl.org (kernel at martin.sperl.org)
Date: Fri, 20 May 2016 07:23:17 +0000
Subject: [PATCH 2/2] memory: bcm2835: enable driver early in the boot process
In-Reply-To: <1463728997-8241-1-git-send-email-kernel@martin.sperl.org>
References: <1463728997-8241-1-git-send-email-kernel@martin.sperl.org>
Message-ID: <1463728997-8241-3-git-send-email-kernel@martin.sperl.org>

From: Martin Sperl <kernel at martin.sperl.org>

Enable the critical sdram-clocks early during the boot process,
so that these clocks (and their PLLs) can not get disabled
when a different driver disables its clocks again because
it failed to probe propperly (maybe deferred).

Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
---
 drivers/memory/bcm2835-sdram.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/memory/bcm2835-sdram.c b/drivers/memory/bcm2835-sdram.c
index 9d8cce2..7b6406d 100644
--- a/drivers/memory/bcm2835-sdram.c
+++ b/drivers/memory/bcm2835-sdram.c
@@ -431,6 +431,9 @@ static int bcm2835_sdram_probe(struct platform_device *pdev)
 	/* setup debugfs */
 	bcm2835_sdram_debugfs(pdev);
 
+	/* note that we have registered sdram */
+	dev_dbg(&pdev->dev, "registered sdram\n");
+
 	return 0;
 }
 
@@ -457,7 +460,12 @@ static struct platform_driver bcm2835_sdram_driver = {
 		.of_match_table = bcm2835_sdram_of_match_table,
 	},
 };
-module_platform_driver(bcm2835_sdram_driver);
+
+static int __init __bcm2835_sdram_driver_init(void)
+{
+	return platform_driver_register(&bcm2835_sdram_driver);
+}
+core_initcall_sync(__bcm2835_sdram_driver_init);
 
 MODULE_AUTHOR("Martin Sperl");
 MODULE_DESCRIPTION("sdram driver for bcm2835 chip");
-- 
2.1.4



From ard.biesheuvel at linaro.org  Fri May 20 00:37:59 2016
From: ard.biesheuvel at linaro.org (Ard Biesheuvel)
Date: Fri, 20 May 2016 09:37:59 +0200
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
Message-ID: <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>

On 20 May 2016 at 06:41, Jon Masters <jcm at redhat.com> wrote:
> Hi Tomasz, all,
>
> On 05/11/2016 07:08 AM, Tomasz Nowicki wrote:
>
>> On 11.05.2016 12:41, Gabriele Paoloni wrote:
>
>>>> v6 -> v7
>>>> - drop quirks handling
>>>
>>> Maybe I missed something in the v6 discussion thread; when was it
>>> decided to drop quirk handling?
>>
>> I had such requests in previous series.
>
> A quick note on quirk handling. This, I believe, applies post-merge of
> the base infrastructure, which I realize will likely not have quirks.
>
> We've some "gen1" ARMv8 server platforms where we end up doing quirks
> (for things like forcing 32-bit config space accessors and the like) due
> to people repurposing existing embedded PCIe IP blocks or using them for
> the first time (especially in servers), and those being involved in the
> design not necessarily seeing this problem ahead of time, or not
> realizing that it would be an issue for servers. In the early days of
> ARM server designs 3-4 years ago, many of us had never really played
> with ECAM or realized how modern topologies are built.
>
> Anyway. We missed this one in our SBSA requirements. They say (words to
> the effect of) "thou shalt do PCIe the way it is done on servers" but
> they aren't prescriptive, and they don't tell people how that actually
> is in reality. That is being fixed. A lot of things are happening behind
> the scenes - especially with third party IP block providers (all of whom
> myself and others are speaking with directly about this) - to ensure
> that the next wave of designs won't repeat these mistakes. We don't have
> a time machine, but we can contain this from becoming an ongoing mess
> for upstream, and we will do so. It won't be a zoo.
>
> Various proposals have arisen for how to handle quirks in the longer
> term, including elaborate frameworks and tables to describe them
> generically. I would like to caution against such approaches, especially
> in the case that they deviate from practice on x86, or prior to being
> standardized fully with other Operating System vendors. I don't expect
> there to be too many more than the existing initial set of quirks we
> have seen posted. A number of "future" server SoCs have already been
> fixed prior to silicon, and new design starts are being warned not to
> make this a problem for us to have to clean up later.
>
> So, I would like to suggest that the eventual framework mirror the
> existing approach on x86 systems (matching DMI, etc.) and not be made
> into some kind of generic, utopia. This is a case where we want there to
> be pain involved (and upstream patches required) when people screw up,
> so that they have a level of pain in response to ever making this
> mistake in the future. If we try to create too grand a generic scheme
> and make it too easy to handle this kind of situation beyond the small
> number of existing offenders, we undermine efforts to force vendors to
> ensure that their IP blocks are compliant going forward.
>

I understand that there is a desire from the RedHat side to mimic x86
as closely as possible, but I never saw any technical justification
for that. DMI contains strings that are visible to userland, and you
effectively lock those down to certain values just so that the kernel
can distinguish a broken PCIe root complex from a working one. Linux
on x86 had no choice, since the overwhelming majority of existing
hardware misrepresented itself as generic, and DMI was the only thing
available to actually distinguish these broken implementations from
one another. This does not mean we should allow and/or encourage this
first gen hardware to misrepresent non-compliant hardware as compliant
as well.

Since you are talking to all the people involved, how about you
convince them to put something in the ACPI tables that allows the
kernel to distinguish those non-standard PCIe implementations from
hardware that is really generic? This way, we can sidestep the quirks
debate entirely, since it will simply be a different device as far as
the kernel is concerned. This is no worse than a quirk from a
practical point of view, since an older OS will be equally unable to
run on newer hardware, but it is arguably more true to the standards
compliance you tend to preach about, especially since this small pool
of third party IP could potentially be identified directly rather than
based on some divination of the SoC we may or may not be running on. I
am also convinced that adding support for an additional HID() to the
ACPI ECAM driver with some special config space handling wired in is
an easier sell upstream than making the same ugly mess x86 has had to
make because they did not have any choice to begin with.

If we do need a quirks handling mechanism, I still don't see how the
x86 situation extrapolates to ARM. ACPI offers plenty of ways for a
SoC vendor to identify the make and particular revision, and quirks
could be keyed off of that.

-- 
Ard.


From jcm at jonmasters.org  Fri May 20 00:46:21 2016
From: jcm at jonmasters.org (Jon Masters)
Date: Fri, 20 May 2016 03:46:21 -0400
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <e6525c52-9cdc-aa0b-dea3-d29ab14cc39b@jonmasters.org>

On 05/10/2016 11:19 AM, Tomasz Nowicki wrote:

> This has been tested on Cavium ThunderX server. Any help in reviewing and
> testing is very appreciated.

Boot log from Intel Itanium 2 system attached.

Jon.

-------------- next part --------------
[    0.000000] Linux version 4.6.0-rc7.jcm_tomasz_pciv7_test+ (jcm at hamartia) (gcc version 4.4.5 (Debian 4.4.5-8) ) #2 SMP Fri May 20 03:24:58 EDT 2016
[    0.000000] EFI v1.10 by HP:
[    0.000000] efi:  SALsystab=0x3fefa000  ACPI 2.0=0x3fd5e000  SMBIOS=0x3fefc000  HCDP=0x3fd5c000 
[    0.000000] booting generic kernel on platform hpzx1
[    0.000000] PCDP: v0 at 0x3fd5c000
[    0.000000] earlycon: uart8250 at MMIO 0x00000000ff5e0000 (options '9600n8')
[    0.000000] bootconsole [uart8250] enabled
[    0.000000] ACPI: Early table checksum verification disabled
[    0.000000] ACPI: RSDP 0x000000003FD5E000 000028 (v02 HP    )
[    0.000000] ACPI: XSDT 0x000000003FD5E02C 00008C (v01 HP     rx2620   00000000 HP   00000000)
[    0.000000] ACPI: FACP 0x000000003FD672A0 0000F4 (v03 HP     rx2620   00000000 HP   00000000)
[    0.000000] ACPI BIOS Warning (bug): 32/64X length mismatch in FADT/Gpe0Block: 32/16 (20160108/tbfadt-623)
[    0.000000] ACPI BIOS Warning (bug): 32/64X length mismatch in FADT/Gpe1Block: 32/16 (20160108/tbfadt-623)
[    0.000000] ACPI: DSDT 0x000000003FD5E100 005F3C (v01 HP     rx2620   00000007 INTL 02012044)
[    0.000000] ACPI: FACS 0x000000003FD67398 000040
[    0.000000] ACPI: SPCR 0x000000003FD673D8 000050 (v01 HP     rx2620   00000000 HP   00000000)
[    0.000000] ACPI: DBGP 0x000000003FD67428 000034 (v01 HP     rx2620   00000000 HP   00000000)
[    0.000000] ACPI: APIC 0x000000003FD67520 0000A4 (v01 HP     rx2620   00000000 HP   00000000)
[    0.000000] ACPI: SPMI 0x000000003FD67460 000050 (v04 HP     rx2620   00000000 HP   00000000)
[    0.000000] ACPI: CPEP 0x000000003FD674B0 000034 (v01 HP     rx2620   00000000 HP   00000000)
[    0.000000] ACPI: SSDT 0x000000003FD64040 0001D6 (v01 HP     rx2620   00000006 INTL 02012044)
[    0.000000] ACPI: SSDT 0x000000003FD64220 000702 (v01 HP     rx2620   00000006 INTL 02012044)
[    0.000000] ACPI: SSDT 0x000000003FD64930 000A16 (v01 HP     rx2620   00000006 INTL 02012044)
[    0.000000] ACPI: SSDT 0x000000003FD65350 000A16 (v01 HP     rx2620   00000006 INTL 02012044)
[    0.000000] ACPI: SSDT 0x000000003FD65D70 000A16 (v01 HP     rx2620   00000006 INTL 02012044)
[    0.000000] ACPI: SSDT 0x000000003FD66790 000A16 (v01 HP     rx2620   00000006 INTL 02012044)
[    0.000000] ACPI: SSDT 0x000000003FD671B0 0000EB (v01 HP     rx2620   00000006 INTL 02012044)
[    0.000000] ACPI: Local APIC address c0000000fee00000
[    0.000000] 1 CPUs available, 1 CPUs total
[    0.000000] SMP: Allowing 1 CPUs, 0 hotplug CPUs
[    0.000000] warning: skipping physical page 0
[    0.000000] warning: skipping physical page 0
[    0.000000] warning: skipping physical page 0
[    0.000000] warning: skipping physical page 0
[    0.000000] Initial ramdisk at: 0xe00000003d4ac000 (17110715 bytes)
[    0.000000] SAL 3.1: HP version 3.15
[    0.000000] SAL Platform features: None
[    0.000000] SAL: AP wakeup using external interrupt vector 0xff
[    0.000000] MCA related initialization done
[    0.000000] warning: skipping physical page 0
[    0.000000] Virtual mem_map starts at 0xa0007fffffc80000
[    0.000000] Zone ranges:
[    0.000000]   DMA      [mem 0x0000000000004000-0x00000000ffffffff]
[    0.000000]   Normal   empty
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000000004000-0x000000003f4b3fff]
[    0.000000]   node   0: [mem 0x000000003fc00000-0x000000003fc7bfff]
[    0.000000] Initmem setup node 0 [mem 0x0000000000004000-0x000000003fc7bfff]
[    0.000000] Built 1 zonelists in Node order, mobility grouping off.  Total pages: 64619
[    0.000000] Policy zone: DMA
[    0.000000] Kernel command line: BOOT_IMAGE=scsi0:/EFI/debian/vmtest root=/dev/sda2  ro
[    0.000000] PID hash table entries: 4096 (order: 1, 32768 bytes)
[    0.000000] Sorting __ex_table...
[    0.000000] Memory: 989904K/1037488K available (12139K kernel code, 1118K rwdata, 1432K rodata, 880K init, 807K bss, 47584K reserved, 0K cma-reserved)
[    0.000000] SLUB: HWalign=128, Order=0-3, MinObjects=0, CPUs=1, Nodes=256
[    0.000000] Hierarchical RCU implementation.
[    0.000000] 	Build-time adjustment of leaf fanout to 64.
[    0.000000] 	RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=1.
[    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=64, nr_cpu_ids=1
[    0.000000] NR_IRQS:1024
[    0.000000] ACPI: Local APIC address c0000000fee00000
[    0.000000] GSI 36 (level, low) -> CPU 0 (0x0000) vector 49
[    0.000000] clocksource: itc: mask: 0xffffffffffffffff max_cycles: 0x17101df767f, max_idle_ns: 440795286379 ns
[    0.000000] Console: colour dummy device 80x25
[    0.192000] Calibrating delay loop... 2390.01 BogoMIPS (lpj=4780032)
[    0.288000] pid_max: default: 32768 minimum: 301
[    0.348000] ACPI: Core revision 20160108
[    0.404000] ACPI: 8 ACPI AML tables successfully acquired and loaded
[    0.488000] 
[    0.504000] Security Framework initialized
[    0.560000] SELinux:  Disabled at boot.
[    0.608000] Dentry cache hash table entries: 131072 (order: 6, 1048576 bytes)
[    0.704000] Inode-cache hash table entries: 65536 (order: 5, 524288 bytes)
[    0.796000] Mount-cache hash table entries: 2048 (order: 0, 16384 bytes)
[    0.884000] Mountpoint-cache hash table entries: 2048 (order: 0, 16384 bytes)
[    0.980000] Boot processor id 0x0/0x0
[    1.028000] Brought up 1 CPUs
[    1.068000] Total of 1 processors activated (2390.01 BogoMIPS).
[    1.144000] devtmpfs: initialized
[    1.188000] SMBIOS 2.3 present.
[    1.232000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    1.360000] NET: Registered protocol family 16
[    1.420000] ACPI: bus type PCI registered
[    1.472000] HugeTLB registered 256 MB page size, pre-allocated 0 pages
[    1.560000] ACPI: Added _OSI(Module Device)
[    1.616000] ACPI: Added _OSI(Processor Device)
[    1.672000] ACPI: Added _OSI(3.0 _SCP Extensions)
[    1.736000] ACPI: Added _OSI(Processor Aggregator Device)
[    1.828000] ACPI: Interpreter enabled
[    1.876000] ACPI: (supports S0 S5)
[    1.920000] ACPI: Using IOSAPIC for interrupt routing
[    2.128000] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-1f])
[    2.212000] acpi HWP0002:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI]
[    2.320000] acpi HWP0002:00: _OSC failed (AE_NOT_FOUND); disabling ASPM
[    2.416000] PCI host bridge to bus 0000:00
[    2.472000] pci_bus 0000:00: root bus resource [io  0x0000-0x1fff window]
[    2.560000] pci_bus 0000:00: root bus resource [mem 0x80000000-0x8fffffff window]
[    2.660000] pci_bus 0000:00: root bus resource [mem 0x80004000000-0x80103fffffe window]
[    2.764000] pci_bus 0000:00: root bus resource [bus 00-1f]
[    2.876000] ACPI: PCI Root Bridge [PCI1] (domain 0000 [bus 20-3f])
[    2.960000] acpi HWP0002:01: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI]
[    3.068000] acpi HWP0002:01: _OSC failed (AE_NOT_FOUND); disabling ASPM
[    3.168000] PCI host bridge to bus 0000:20
[    3.224000] pci_bus 0000:20: root bus resource [io  0x2000-0x2fff window]
[    3.312000] pci_bus 0000:20: root bus resource [mem 0x90000000-0x97ffffff window]
[    3.412000] pci_bus 0000:20: root bus resource [mem 0x90004000000-0x90103fffffe window]
[    3.516000] pci_bus 0000:20: root bus resource [bus 20-3f]
[    3.632000] ACPI: PCI Root Bridge [PCI2] (domain 0000 [bus 40-5f])
[    3.712000] acpi HWP0002:02: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI]
[    3.820000] acpi HWP0002:02: _OSC failed (AE_NOT_FOUND); disabling ASPM
[    3.920000] PCI host bridge to bus 0000:40
[    3.972000] pci_bus 0000:40: root bus resource [io  0x3000-0x5fff window]
[    4.064001] pci_bus 0000:40: root bus resource [mem 0x98000000-0xafffffff window]
[    4.160001] pci_bus 0000:40: root bus resource [mem 0xa0004000000-0xa0103fffffe window]
[    4.268001] pci_bus 0000:40: root bus resource [bus 40-5f]
[    4.364001] ACPI: PCI Root Bridge [PCI3] (domain 0000 [bus 60-7f])
[    4.444001] acpi HWP0002:03: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI]
[    4.552001] acpi HWP0002:03: _OSC failed (AE_NOT_FOUND); disabling ASPM
[    4.652001] PCI host bridge to bus 0000:60
[    4.704001] pci_bus 0000:60: root bus resource [io  0x6000-0x7fff window]
[    4.796001] pci_bus 0000:60: root bus resource [mem 0xb0000000-0xc7ffffff window]
[    4.892001] pci_bus 0000:60: root bus resource [mem 0xb0004000000-0xb0103fffffe window]
[    5.000001] pci_bus 0000:60: root bus resource [bus 60-7f]
[    5.096001] ACPI: PCI Root Bridge [PCI4] (domain 0000 [bus 80-bf])
[    5.176001] acpi HWP0002:04: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI]
[    5.284001] acpi HWP0002:04: _OSC failed (AE_NOT_FOUND); disabling ASPM
[    5.384001] PCI host bridge to bus 0000:80
[    5.436001] pci_bus 0000:80: root bus resource [io  0x8000-0xbfff window]
[    5.524001] pci_bus 0000:80: root bus resource [mem 0xc8000000-0xdfffffff window]
[    5.624001] pci_bus 0000:80: root bus resource [mem 0xc0004000000-0xc0103fffffe window]
[    5.728001] pci_bus 0000:80: root bus resource [bus 80-bf]
[    5.828001] ACPI: PCI Root Bridge [PCI6] (domain 0000 [bus c0-df])
[    5.908001] acpi HWP0002:05: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI]
[    6.016001] acpi HWP0002:05: _OSC failed (AE_NOT_FOUND); disabling ASPM
[    6.112001] PCI host bridge to bus 0000:c0
[    6.168001] pci_bus 0000:c0: root bus resource [io  0xc000-0xdfff window]
[    6.256001] pci_bus 0000:c0: root bus resource [mem 0xe0000000-0xefffffff window]
[    6.356001] pci_bus 0000:c0: root bus resource [mem 0xe0004000000-0xe0103fffffe window]
[    6.460001] pci_bus 0000:c0: root bus resource [bus c0-df]
[    6.548001] ACPI: Enabled 1 GPEs in block 10 to 1F
[    6.608001] vgaarb: loaded
[    6.644001] SCSI subsystem initialized
[    6.696001] ACPI: bus type USB registered
[    6.748001] usbcore: registered new interface driver usbfs
[    6.820001] usbcore: registered new interface driver hub
[    6.888001] usbcore: registered new device driver usb
[    6.960001] IOC: zx1 2.3 HPA 0xfed01000 IOVA space 1024Mb at 0x40000000
[    7.096001] clocksource: Switched to clocksource itc
[    7.165391] VFS: Disk quotas dquot_6.6.0
[    7.217160] VFS: Dquot-cache hash table entries: 2048 (order 0, 16384 bytes)
[    7.310088] pnp: PnP ACPI init
[    7.350492] GSI 34 (level, low) -> CPU 0 (0x0000) vector 50
[    7.427065] GSI 35 (level, low) -> CPU 0 (0x0000) vector 51
[    7.542336] pnp: PnP ACPI: found 2 devices
[    7.599353] NET: Registered protocol family 2
[    7.659252] TCP established hash table entries: 8192 (order: 2, 65536 bytes)
[    7.752389] TCP bind hash table entries: 8192 (order: 3, 131072 bytes)
[    7.838429] TCP: Hash tables configured (established 8192 bind 8192)
[    7.922282] UDP hash table entries: 512 (order: 0, 16384 bytes)
[    8.000304] UDP-Lite hash table entries: 512 (order: 0, 16384 bytes)
[    8.084056] NET: Registered protocol family 1
[    8.141446] GSI 16 (level, low) -> CPU 0 (0x0000) vector 52
[    8.216452] GSI 16 (level, low) -> CPU 0 (0x0000) vector 52 unregistered
[    8.306355] GSI 17 (level, low) -> CPU 0 (0x0000) vector 52
[    8.381350] GSI 17 (level, low) -> CPU 0 (0x0000) vector 52 unregistered
[    8.471253] GSI 18 (level, low) -> CPU 0 (0x0000) vector 52
[    8.546247] GSI 18 (level, low) -> CPU 0 (0x0000) vector 52 unregistered
[    8.636151] Unpacking initramfs...
[    9.390337] Freeing initrd memory: 16704kB freed
[    9.452092] perfmon: version 2.0 IRQ 238
[    9.504173] perfmon: Itanium 2 PMU detected, 16 PMCs, 18 PMDs, 4 counters (47 bits)
[    9.605023] perfmon: added sampling format default_format
[    9.676576] perfmon_default_smpl: default_format v2.0 registered
[    9.755645] futex hash table entries: 256 (order: 1, 32768 bytes)
[    9.836164] audit: initializing netlink subsys (disabled)
[    9.907310] audit: type=2000 audit(1463729949.900:1): initialized
[    9.987625] workingset: timestamp_bits=52 max_order=16 bucket_order=0
[   10.072633] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 252)
[   10.174301] io scheduler noop registered
[   10.225953] io scheduler deadline registered
[   10.282101] io scheduler cfq registered (default)
[   10.344189] input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0
[   10.441907] ACPI: Power Button [PWRF]
[   10.490124] input: Sleep Button as /devices/LNXSYSTM:00/LNXSLPBN:00/input/input1
[   10.587641] ACPI: Sleep Button [SLPF]
[   10.635751] thermal LNXTHERM:00: registered as thermal_zone0
[   10.710659] ACPI: Thermal Zone [THM0] (27 C)
[   10.766799] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[   10.869739] 00:00: ttyS0 at MMIO 0xff5e0000 (irq = 50, base_baud = 115200) is a 16550A
[   10.974038] console [ttyS0] enabled
[   10.974038] console [ttyS0] enabled
[   11.061742] bootconsole [uart8250] disabled
[   11.061742] bootconsole [uart8250] disabled
[   11.187308] 00:01: ttyS1 at MMIO 0xff5e2000 (irq = 51, base_baud = 115200) is a 16550A
[   11.282265] Linux agpgart interface v0.103
[   11.350337] loop: module loaded
[   11.388606] Uniform Multi-Platform E-IDE driver
[   11.442986] ide-cd driver 5.00
[   11.479646] GSI 21 (level, low) -> CPU 0 (0x0000) vector 52
[   11.548304] pata_cmd64x 0000:00:02.0: Secondary port is disabled
[   11.620496] scsi host0: pata_cmd64x
[   11.662883] scsi host1: pata_cmd64x
[   11.704862] ata1: PATA max UDMA/100 cmd 0xd18 ctl 0xd24 bmdma 0xd00 irq 55
[   11.787375] ata2: DUMMY
[   11.816629] e1000: Intel(R) PRO/1000 Network Driver - version 7.3.21-k8-NAPI
[   11.901233] e1000: Copyright (c) 1999-2006 Intel Corporation.
[   11.970186] GSI 29 (level, low) -> CPU 0 (0x0000) vector 53
[   12.138336] ata1.00: ATAPI: DV-28E-N, E.6A, max UDMA/33
[   12.278336] ata1.00: configured for UDMA/33
[   12.386336] scsi 0:0:0:0: CD-ROM            TEAC     DV-28E-N         E.6A PQ: 0 ANSI: 5
[   12.542338] sr 0:0:0:0: [sr0] scsi3-mmc drive: 24x/24x cd/rw xa/form2 cdda tray
[   12.633847] cdrom: Uniform CD-ROM driver Revision: 3.20
[   12.706336] e1000 0000:20:02.0 eth0: (PCI-X:66MHz:64-bit) 00:17:08:7c:18:20
[   12.789892] e1000 0000:20:02.0 eth0: Intel(R) PRO/1000 Network Connection
[   12.871351] sr 0:0:0:0: Attached scsi generic sg0 type 5
[   12.935306] GSI 30 (level, low) -> CPU 0 (0x0000) vector 54
[   13.314340] e1000 0000:20:02.1 eth1: (PCI-X:66MHz:64-bit) 00:17:08:7c:18:21
[   13.399691] e1000 0000:20:02.1 eth1: Intel(R) PRO/1000 Network Connection
[   13.481044] Fusion MPT base driver 3.04.20
[   13.530204] Copyright (c) 1999-2008 LSI Corporation
[   13.588646] Fusion MPT SPI Host driver 3.04.20
[   13.641872] GSI 27 (level, low) -> CPU 0 (0x0000) vector 55
[   13.710213] mptbase: ioc0: Initiating bringup
[   14.242338] ioc0: LSI53C1030 C0: Capabilities={Initiator,Target}
[   14.986338] scsi host2: ioc0: LSI53C1030 C0, FwRev=01032341h, Ports=1, MaxQ=255, IRQ=58
[   15.718338] GSI 28 (level, low) -> CPU 0 (0x0000) vector 56
[   15.787849] mptbase: ioc1: Initiating bringup
[   16.318338] ioc1: LSI53C1030 C0: Capabilities={Initiator,Target}
[   17.062338] scsi host3: ioc1: LSI53C1030 C0, FwRev=01032341h, Ports=1, MaxQ=255, IRQ=59
[   17.160901] scsi 2:0:0:0: Direct-Access     HP 73.4G ST373454LC       HPC2 PQ: 0 ANSI: 3
[   17.259548] scsi target2:0:0: Beginning Domain Validation
[   17.942338] Fusion MPT FC Host driver 3.04.20
[   17.995796] Fusion MPT SAS Host driver 3.04.20
[   18.049128] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[   18.127474] ehci-pci: EHCI PCI platform driver
[   18.180798] GSI 18 (level, low) -> CPU 0 (0x0000) vector 57
[   18.249240] ehci-pci 0000:00:01.2: EHCI Host Controller
[   18.312052] ehci-pci 0000:00:01.2: new USB bus registered, assigned bus number 1
[   18.400810] ehci-pci 0000:00:01.2: irq 54, io mem 0x80000000
[   18.474340] scsi target2:0:0: Ending Domain Validation
[   18.537887] ehci-pci 0000:00:01.2: USB 2.0 started, EHCI 0.95
[   18.606851] scsi target2:0:0: FAST-160 WIDE SCSI 320.0 MB/s DT IU QAS RTI WRFLOW PCOMP (6.25 ns, offset 63)
[   18.723742] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
[   18.805192] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[   18.891860] usb usb1: Product: EHCI Host Controller
[   18.950394] usb usb1: Manufacturer: Linux 4.6.0-rc7.jcm_tomasz_pciv7_test+ ehci_hcd
[   19.042175] usb usb1: SerialNumber: 0000:00:01.2
[   19.097584] hub 1-0:1.0: USB hub found
[   19.142790] hub 1-0:1.0: 5 ports detected
[   19.190915] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[   19.265300] mousedev: PS/2 mouse device common for all mice
[   19.334336] rtc-efi rtc-efi: rtc core: registered rtc-efi as rtc0
[   19.407799] EFI Variables Facility v0.08 2004-May-17
[   19.467590] NET: Registered protocol family 10
[   19.521650] NET: Registered protocol family 17
[   19.575405] registered taskstats version 1
[   19.624776] rtc-efi rtc-efi: setting system clock to 2016-05-20 07:39:20 UTC (1463729960)
[   22.826338] sd 2:0:0:0: Attached scsi generic sg1 type 0
[   22.892021] sd 2:0:0:0: [sda] 143374738 512-byte logical blocks: (73.4 GB/68.4 GiB)
[   22.984321] sd 2:0:0:0: [sda] Write Protect is off
[   23.043271] sd 2:0:0:0: [sda] Write cache: disabled, read cache: enabled, supports DPO and FUA
[   23.174340]  sda: sda1 sda2 sda3
[   23.218340] sd 2:0:0:0: [sda] Attached SCSI disk
[   23.273689] Freeing unused kernel memory: 880K (e000000004e64000 - e000000004f40000)
[   23.366620] This architecture does not have kernel memory protection.
Loading, please wait...
[   23.462341] udev[112]: starting version 164
FATAL: Could not[   23.806340] EXT4-fs (sda2): mounting ext3 file system using the ext4 subsystem
 load /lib/modules/4.6.0-rc7.jcm[   23.914337] EXT4-fs (sda2): mounted filesystem with ordered data mode. Opts: (null)
_tomasz_pciv7_test+/modules.dep: No such file or directory
Begin: Loading essential drivers ... FATAL: Could not load /lib/modules/4.6.0-rc7.jcm_tomasz_pciv7_test+/modules.dep: No such file or directory
done.
Begin: Running /scripts/init-premount ... done.
Begin: Mounting root file system ... Begin: Running /scripts/local-top ... done.
Begin: Running /scripts/local-premount ... done.
FATAL: Could not load /lib/modules/4.6.0-rc7.jcm_tomasz_pciv7_test+/modules.dep: No such file or directory
Begin: Running /scripts/local-bottom ... done.
done.
Begin: Running /scripts/init-bottom ... done.
modprobe: FATAL: Could not load /lib/modules/4.6.0-rc7.jcm_tomasz_pciv7_test+/modules.dep: No such file or directory



INIT: version 2.88 booting

Using makefile-s[   24.982338] random: nonblocking pool is initialized
tyle concurrent boot in runlevel S.
Starting the hotplug events dispatcher: udevd[   25.330336] udev[267]: starting version 164
.
Synthesizing the initial hotplug events...done.
Waiting for /dev to be fully populated...done.
Activating swap...[   25.998339] Adding 2000784k swap on /dev/sda3.  Priority:-1 extents:1 across:2000784k 
done.
[   26.098340] EXT4-fs (sda2): re-mounted. Opts: (null)
Checking root file system...fsck from util-linux-ng 2.17.2
/dev/sda2: clean[   26.262343] EXT4-fs (sda2): re-mounted. Opts: errors=remount-ro
, 93785/4349952 files, 1074005/17397216 blocks
done.
Loading kernel modules...done.
Cleaning up ifupdown....
Setting up networking....
Activating lvm and md swap...done.
Checking file systems...fsck from util-linux-ng 2.17.2
done.
Mounting local filesystems...done.
Activating swapfile swap...done.
Cleaning up temporary files....
Configuring network interfaces...done.
Starting portmap daemon....
Starting NFS common utilities: statd.
Cleaning up temporary files....
[   27.090342] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
[   27.162611] e1000: eth0 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: RX
[   27.249590] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
Setting console screen modes and fonts.
cannot (un)set powersave mode
[9;30][14;30]Setting kernel variables ...done.

INIT: Entering runlevel: 2

Using makefile-style concurrent boot in runlevel 2.
Starting portmap daemon...Already running..
Starting NFS common utilities: statd.
Starting enhanced syslogd: rsyslogd.
Starting ACPI services....
Starting deferred execution scheduler: atd.
Starting mpt-status monitor: mpt-statusd.
Starting periodic command scheduler: cron.
Starting MTA: exim4.
Starting O[   28.750341] sshd (1082): /proc/1082/oom_adj is deprecated, please use /proc/1082/oom_score_adj instead.
penBSD Secure Shell server: sshd.

Debian GNU/Linux 6.0 hamartia ttyS0

hamartia login: root
Password: 
Last login: Fri May 20 03:35:54 EDT 2016 on ttyS0
Linux hamartia 4.6.0-rc7.jcm_tomasz_pciv7_test+ #2 SMP Fri May 20 03:24:58 EDT 2016 ia64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root at hamartia:~# uname -a
Linux hamartia 4.6.0-rc7.jcm_tomasz_pciv7_test+ #2 SMP Fri May 20 03:24:58 EDT 2016 ia64 GNU/Linux
root at hamartia:~# 

From marc.zyngier at arm.com  Fri May 20 00:56:45 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Fri, 20 May 2016 08:56:45 +0100
Subject: 4.5.0 on sun7i-a20-olinuxino-lime2: libphy: PHY stmmac-0:ffffffff
 not found (regression from rc7)
In-Reply-To: <CAHsu+b-t_r93XKLJTUcin6xjhOrFVn3_60vwHkbRt3iHK28CbA@mail.gmail.com>
References: <56E9413D.9010902@a20.net> <56E945FF.6080005@arm.com>
 <56E94CF4.2060607@arm.com> <56E95B57.1090100@suse.de>
 <56E9776F.3070102@a20.net> <56E99B0C.2070609@arm.com>
 <56E9F2B8.1030605@a20.net> <20160317075202.16b14ed6@arm.com>
 <CAHsu+b-t_r93XKLJTUcin6xjhOrFVn3_60vwHkbRt3iHK28CbA@mail.gmail.com>
Message-ID: <573EC33D.2010209@arm.com>

On 20/05/16 06:44, Andre Heider wrote:
> Giuseppe, Alexandre, et al.,
> 
> On Thu, Mar 17, 2016 at 8:52 AM, Marc Zyngier <marc.zyngier at arm.com> wrote:
>> On Thu, 17 Mar 2016 00:56:40 +0100
>> Bert Lindner <bert at a20.net> wrote:
>>> On 2016-03-16 18:42, Marc Zyngier wrote:
>>>> On 16/03/16 15:10, Bert Lindner wrote:
>>>>> On 2016-03-16 14:10, Andreas F?rber wrote:
>>>>>> Am 16.03.2016 um 13:09 schrieb Robin Murphy:
>>>>>>> On 16/03/16 11:39, Marc Zyngier wrote:
>>>>>>>> On 16/03/16 11:19, Bert Lindner wrote:
> ...
>>>>>>>>> For the board sun7i-a20-olinuxino-lime2, there seems to be a problem
>>>>>>>>> with the eth0 PHY in mainline kernel 4.5.0 that developed since
>>>>>>>>> 4.5.0-rc7. Ethernet does not work, although eth0 is reported:
> ...
>>>>>>>>> [    9.767125] NET: Registered protocol family 10
>>>>>>>>> [   10.357405] libphy: PHY stmmac-0:ffffffff not found
>>>>>>>>> [   10.362382] eth0: Could not attach to PHY
>>>>>>>>> [   10.366557] stmmac_open: Cannot attach to PHY (error: -19)
> ...
>>>>>> v4 fixes for 4.5 are here:
>>>>>>
>>>>>> https://patchwork.ozlabs.org/patch/598195/ (revert)
>>>>>> https://patchwork.ozlabs.org/patch/598196/
> ...
>>>> Good to know, thanks. Could you also give the potential fix a go (as
>>>> mentioned by Andreas)? Just to make sure that whatever gets merged next
>>>> will actually fix the issue.
>>>
>>> Yes sure, it took a while because I had to travel. Confirmed, the
>>> v4-for-4.5 fix works well for me, on sun7i-a20-olinuxino-lime2:
>>>
>>> root at lime2-079f:~# cat /proc/version
>>> Linux version 4.5.0-598195-598196-v4 (root at lime2-079f) (gcc version
>>> 4.9.1 (Ubuntu/Linaro 4.9.1-16ubuntu6) ) #1 SMP Wed Mar 16 16:44:22 UTC 2016
>>>
>>> dmesg:
>>> [    8.245273] NET: Registered protocol family 10
>>> [    9.297406]  RX IPC Checksum Offload disabled
>>> [    9.297460]  No MAC Management Counters available
>>> [    9.297951] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
>>> [   16.285658] sun7i-dwmac 1c50000.ethernet eth0: Link is Up -
>>> 1Gbps/Full - flow control rx/tx
>>> [   16.285798] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
>>>
>>> The board is connected to my laptop rather than to a switch, so that
>>> might be where the flow control message comes from (not sure). Anyway
>>> ethernet works.
>>
>> Cool, many thanks for taking the time to test and report.
>>
>> Hopefully Giuseppe will get this merged quickly enough in mainline, and
>> it should then trickle into a 4.5-stable release (cc-ing stable on
>> these patches would probably be a good idea, BTW).
> 
> stmmac is broken on at least Lime2, BananaPi and Cubieboard2 since
> v4.5 [0], including all five stable releases :(

All the A20 platforms are dead, actually.

> The v4.5 patches quoted above are already +4 weeks old, could we
> please get them into stable?

For that, the maintainer would have needed to CC stable, which he
didn't. I'd expect someone who cares to send these patches to stable.
It'd be better if the maintainer would do it himself though.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From jcm at redhat.com  Fri May 20 01:01:00 2016
From: jcm at redhat.com (Jon Masters)
Date: Fri, 20 May 2016 04:01:00 -0400
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
Message-ID: <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>

Hi Ard,

On 05/20/2016 03:37 AM, Ard Biesheuvel wrote:
> On 20 May 2016 at 06:41, Jon Masters <jcm at redhat.com> wrote:
>> Hi Tomasz, all,
>>
>> On 05/11/2016 07:08 AM, Tomasz Nowicki wrote:
>>
>>> On 11.05.2016 12:41, Gabriele Paoloni wrote:
>>
>>>>> v6 -> v7
>>>>> - drop quirks handling
>>>>
>>>> Maybe I missed something in the v6 discussion thread; when was it
>>>> decided to drop quirk handling?
>>>
>>> I had such requests in previous series.
>>
>> A quick note on quirk handling. This, I believe, applies post-merge of
>> the base infrastructure, which I realize will likely not have quirks.
>>
>> We've some "gen1" ARMv8 server platforms where we end up doing quirks
>> (for things like forcing 32-bit config space accessors and the like) due
>> to people repurposing existing embedded PCIe IP blocks or using them for
>> the first time (especially in servers), and those being involved in the
>> design not necessarily seeing this problem ahead of time, or not
>> realizing that it would be an issue for servers. In the early days of
>> ARM server designs 3-4 years ago, many of us had never really played
>> with ECAM or realized how modern topologies are built.
>>
>> Anyway. We missed this one in our SBSA requirements. They say (words to
>> the effect of) "thou shalt do PCIe the way it is done on servers" but
>> they aren't prescriptive, and they don't tell people how that actually
>> is in reality. That is being fixed. A lot of things are happening behind
>> the scenes - especially with third party IP block providers (all of whom
>> myself and others are speaking with directly about this) - to ensure
>> that the next wave of designs won't repeat these mistakes. We don't have
>> a time machine, but we can contain this from becoming an ongoing mess
>> for upstream, and we will do so. It won't be a zoo.
>>
>> Various proposals have arisen for how to handle quirks in the longer
>> term, including elaborate frameworks and tables to describe them
>> generically. I would like to caution against such approaches, especially
>> in the case that they deviate from practice on x86, or prior to being
>> standardized fully with other Operating System vendors. I don't expect
>> there to be too many more than the existing initial set of quirks we
>> have seen posted. A number of "future" server SoCs have already been
>> fixed prior to silicon, and new design starts are being warned not to
>> make this a problem for us to have to clean up later.
>>
>> So, I would like to suggest that the eventual framework mirror the
>> existing approach on x86 systems (matching DMI, etc.) and not be made
>> into some kind of generic, utopia. This is a case where we want there to
>> be pain involved (and upstream patches required) when people screw up,
>> so that they have a level of pain in response to ever making this
>> mistake in the future. If we try to create too grand a generic scheme
>> and make it too easy to handle this kind of situation beyond the small
>> number of existing offenders, we undermine efforts to force vendors to
>> ensure that their IP blocks are compliant going forward.

> I understand that there is a desire from the RedHat side to mimic x86
> as closely as possible, but I never saw any technical justification
> for that.

Understood. My own motivation is always to make the experience as
familiar as possible, both for end users, as well as for ODMs and the
entire ecosystem. There are very many ODMs currently working on v8
server designs and they're already expecting this to be "just like x88".
Intentionally. But as to the specifics of using DMI...

> DMI contains strings that are visible to userland, and you
> effectively lock those down to certain values just so that the kernel
> can distinguish a broken PCIe root complex from a working one. Linux
> on x86 had no choice, since the overwhelming majority of existing
> hardware misrepresented itself as generic, and DMI was the only thing
> available to actually distinguish these broken implementations from
> one another. This does not mean we should allow and/or encourage this
> first gen hardware to misrepresent non-compliant hardware as compliant
> as well.

That's a very reasonable argument. I don't disagree that it would be
nice to have nicer ways to distinguish the non-compliant IP than
treating the whole platform with an ASCII matching sledgehammer.

> Since you are talking to all the people involved, how about you
> convince them to put something in the ACPI tables that allows the
> kernel to distinguish those non-standard PCIe implementations from
> hardware that is really generic?

I'm open to this *BUT* it has to be something that will be adopted
beyond Linux. I have reached out to some non-Linux folks about this. If
there's buy-in, and if there's agreement to go standardize it through
the ASWG, then we should do so. What we should not do is treat ARM as
special in a way that the others aren't involved with. I'll admit DMI
ended up part of the SBBR in part because I wrote that piece in with the
assumption that exactly the same matches as on x86 would happen.

> This way, we can sidestep the quirks
> debate entirely, since it will simply be a different device as far as
> the kernel is concerned. This is no worse than a quirk from a
> practical point of view, since an older OS will be equally unable to
> run on newer hardware, but it is arguably more true to the standards
> compliance you tend to preach about, especially since this small pool
> of third party IP could potentially be identified directly rather than
> based on some divination of the SoC we may or may not be running on. I
> am also convinced that adding support for an additional HID() to the
> ACPI ECAM driver with some special config space handling wired in is
> an easier sell upstream than making the same ugly mess x86 has had to
> make because they did not have any choice to begin with.

Again, open to it. I just don't want to do something that's Linux
specific. So it'll take time. It would be awesome if an interim quirk
solution existed that got platforms that are shipping in production
(e.g. HP Moonshot) actually booting upstream kernels this year. We
/really/ want F25 to be able to run on these without needing to carry an
out-of-tree quirk patch or just not support them. That's much worse.

> If we do need a quirks handling mechanism, I still don't see how the
> x86 situation extrapolates to ARM. ACPI offers plenty of ways for a
> SoC vendor to identify the make and particular revision, and quirks
> could be keyed off of that.

Fair enough. Is there any traction for an interim solution for these
initial platforms do you think? If we wait to add a new table it's
probably going to be the end of the year before we get this done.

Jon.

-- 
Computer Architect | Sent from my Fedora powered laptop



From gabriele.paoloni at huawei.com  Fri May 20 01:11:27 2016
From: gabriele.paoloni at huawei.com (Gabriele Paoloni)
Date: Fri, 20 May 2016 08:11:27 +0000
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
Message-ID: <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF540@lhreml503-mbs>

Hi Ard, Jon

> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel at linaro.org]
> Sent: 20 May 2016 08:38
> To: Jon Masters
> Cc: Tomasz Nowicki; Gabriele Paoloni; helgaas at kernel.org; arnd at arndb.de;
> will.deacon at arm.com; catalin.marinas at arm.com; rafael at kernel.org;
> hanjun.guo at linaro.org; Lorenzo.Pieralisi at arm.com; okaya at codeaurora.org;
> jchandra at broadcom.com; linaro-acpi at lists.linaro.org; linux-
> pci at vger.kernel.org; dhdang at apm.com; Liviu.Dudau at arm.com;
> ddaney at caviumnetworks.com; jeremy.linton at arm.com; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org;
> robert.richter at caviumnetworks.com; Suravee.Suthikulpanit at amd.com;
> msalter at redhat.com; Wangyijing; mw at semihalf.com;
> andrea.gallo at linaro.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI host
> controller
> 
> On 20 May 2016 at 06:41, Jon Masters <jcm at redhat.com> wrote:
> > Hi Tomasz, all,
> >
> > On 05/11/2016 07:08 AM, Tomasz Nowicki wrote:
> >
> >> On 11.05.2016 12:41, Gabriele Paoloni wrote:
> >
> >>>> v6 -> v7
> >>>> - drop quirks handling
> >>>
> >>> Maybe I missed something in the v6 discussion thread; when was it
> >>> decided to drop quirk handling?
> >>
> >> I had such requests in previous series.
> >
> > A quick note on quirk handling. This, I believe, applies post-merge
> of
> > the base infrastructure, which I realize will likely not have quirks.
> >
> > We've some "gen1" ARMv8 server platforms where we end up doing quirks
> > (for things like forcing 32-bit config space accessors and the like)
> due
> > to people repurposing existing embedded PCIe IP blocks or using them
> for
> > the first time (especially in servers), and those being involved in
> the
> > design not necessarily seeing this problem ahead of time, or not
> > realizing that it would be an issue for servers. In the early days of
> > ARM server designs 3-4 years ago, many of us had never really played
> > with ECAM or realized how modern topologies are built.
> >
> > Anyway. We missed this one in our SBSA requirements. They say (words
> to
> > the effect of) "thou shalt do PCIe the way it is done on servers" but
> > they aren't prescriptive, and they don't tell people how that
> actually
> > is in reality. That is being fixed. A lot of things are happening
> behind
> > the scenes - especially with third party IP block providers (all of
> whom
> > myself and others are speaking with directly about this) - to ensure
> > that the next wave of designs won't repeat these mistakes. We don't
> have
> > a time machine, but we can contain this from becoming an ongoing mess
> > for upstream, and we will do so. It won't be a zoo.
> >
> > Various proposals have arisen for how to handle quirks in the longer
> > term, including elaborate frameworks and tables to describe them
> > generically. I would like to caution against such approaches,
> especially
> > in the case that they deviate from practice on x86, or prior to being
> > standardized fully with other Operating System vendors. I don't
> expect
> > there to be too many more than the existing initial set of quirks we
> > have seen posted. A number of "future" server SoCs have already been
> > fixed prior to silicon, and new design starts are being warned not to
> > make this a problem for us to have to clean up later.
> >
> > So, I would like to suggest that the eventual framework mirror the
> > existing approach on x86 systems (matching DMI, etc.) and not be made
> > into some kind of generic, utopia. This is a case where we want there
> to
> > be pain involved (and upstream patches required) when people screw up,
> > so that they have a level of pain in response to ever making this
> > mistake in the future. If we try to create too grand a generic scheme
> > and make it too easy to handle this kind of situation beyond the
> small
> > number of existing offenders, we undermine efforts to force vendors
> to
> > ensure that their IP blocks are compliant going forward.
> >
> 
> I understand that there is a desire from the RedHat side to mimic x86
> as closely as possible, but I never saw any technical justification
> for that. DMI contains strings that are visible to userland, and you
> effectively lock those down to certain values just so that the kernel
> can distinguish a broken PCIe root complex from a working one. Linux
> on x86 had no choice, since the overwhelming majority of existing
> hardware misrepresented itself as generic, and DMI was the only thing
> available to actually distinguish these broken implementations from
> one another. This does not mean we should allow and/or encourage this
> first gen hardware to misrepresent non-compliant hardware as compliant
> as well.
> 
> Since you are talking to all the people involved, how about you
> convince them to put something in the ACPI tables that allows the
> kernel to distinguish those non-standard PCIe implementations from
> hardware that is really generic? This way, we can sidestep the quirks
> debate entirely, since it will simply be a different device as far as
> the kernel is concerned. This is no worse than a quirk from a
> practical point of view, since an older OS will be equally unable to
> run on newer hardware, but it is arguably more true to the standards
> compliance you tend to preach about, especially since this small pool
> of third party IP could potentially be identified directly rather than
> based on some divination of the SoC we may or may not be running on. I
> am also convinced that adding support for an additional HID() to the
> ACPI ECAM driver with some special config space handling wired in is
> an easier sell upstream than making the same ugly mess x86 has had to
> make because they did not have any choice to begin with.

In our case (HiSilicon Hip05/Hip06) we are using the Designware IP
that unfortunately is non-ECAM for the RC config space.

A possible ACPI table solution was discussed already in this thread

https://lkml.org/lkml/2016/3/14/722

where <<Name (_CID, "PNP0C02")  // Motherboard reserved resource>>
is used to specify an Host Controller specific resource.
It looks to me that this can be an approach that can accommodate
different vendors/scenarios and Bjorn seemed to be quite ok with
it.

It comes without saying that for future HW releases we all should
make an effort to deliver fully ECAM compliant controllers.

What's your view about this approach?

Thanks

Gab

> 
> If we do need a quirks handling mechanism, I still don't see how the
> x86 situation extrapolates to ARM. ACPI offers plenty of ways for a
> SoC vendor to identify the make and particular revision, and quirks
> could be keyed off of that.
> 
> --
> Ard.

From peppe.cavallaro at st.com  Fri May 20 01:14:50 2016
From: peppe.cavallaro at st.com (Giuseppe CAVALLARO)
Date: Fri, 20 May 2016 10:14:50 +0200
Subject: 4.5.0 on sun7i-a20-olinuxino-lime2: libphy: PHY stmmac-0:ffffffff
 not found (regression from rc7)
In-Reply-To: <573EC33D.2010209@arm.com>
References: <56E9413D.9010902@a20.net> <56E945FF.6080005@arm.com>
 <56E94CF4.2060607@arm.com> <56E95B57.1090100@suse.de>
 <56E9776F.3070102@a20.net> <56E99B0C.2070609@arm.com>
 <56E9F2B8.1030605@a20.net> <20160317075202.16b14ed6@arm.com>
 <CAHsu+b-t_r93XKLJTUcin6xjhOrFVn3_60vwHkbRt3iHK28CbA@mail.gmail.com>
 <573EC33D.2010209@arm.com>
Message-ID: <573EC77A.2000800@st.com>

Hello

On 5/20/2016 9:56 AM, Marc Zyngier wrote:
> On 20/05/16 06:44, Andre Heider wrote:
>> Giuseppe, Alexandre, et al.,
>>
>> On Thu, Mar 17, 2016 at 8:52 AM, Marc Zyngier <marc.zyngier at arm.com> wrote:
>>> On Thu, 17 Mar 2016 00:56:40 +0100
>>> Bert Lindner <bert at a20.net> wrote:
>>>> On 2016-03-16 18:42, Marc Zyngier wrote:
>>>>> On 16/03/16 15:10, Bert Lindner wrote:
>>>>>> On 2016-03-16 14:10, Andreas F?rber wrote:
>>>>>>> Am 16.03.2016 um 13:09 schrieb Robin Murphy:
>>>>>>>> On 16/03/16 11:39, Marc Zyngier wrote:
>>>>>>>>> On 16/03/16 11:19, Bert Lindner wrote:
>> ...
>>>>>>>>>> For the board sun7i-a20-olinuxino-lime2, there seems to be a problem
>>>>>>>>>> with the eth0 PHY in mainline kernel 4.5.0 that developed since
>>>>>>>>>> 4.5.0-rc7. Ethernet does not work, although eth0 is reported:
>> ...
>>>>>>>>>> [    9.767125] NET: Registered protocol family 10
>>>>>>>>>> [   10.357405] libphy: PHY stmmac-0:ffffffff not found
>>>>>>>>>> [   10.362382] eth0: Could not attach to PHY
>>>>>>>>>> [   10.366557] stmmac_open: Cannot attach to PHY (error: -19)
>> ...
>>>>>>> v4 fixes for 4.5 are here:
>>>>>>>
>>>>>>> https://patchwork.ozlabs.org/patch/598195/ (revert)
>>>>>>> https://patchwork.ozlabs.org/patch/598196/
>> ...
>>>>> Good to know, thanks. Could you also give the potential fix a go (as
>>>>> mentioned by Andreas)? Just to make sure that whatever gets merged next
>>>>> will actually fix the issue.
>>>>
>>>> Yes sure, it took a while because I had to travel. Confirmed, the
>>>> v4-for-4.5 fix works well for me, on sun7i-a20-olinuxino-lime2:
>>>>
>>>> root at lime2-079f:~# cat /proc/version
>>>> Linux version 4.5.0-598195-598196-v4 (root at lime2-079f) (gcc version
>>>> 4.9.1 (Ubuntu/Linaro 4.9.1-16ubuntu6) ) #1 SMP Wed Mar 16 16:44:22 UTC 2016
>>>>
>>>> dmesg:
>>>> [    8.245273] NET: Registered protocol family 10
>>>> [    9.297406]  RX IPC Checksum Offload disabled
>>>> [    9.297460]  No MAC Management Counters available
>>>> [    9.297951] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
>>>> [   16.285658] sun7i-dwmac 1c50000.ethernet eth0: Link is Up -
>>>> 1Gbps/Full - flow control rx/tx
>>>> [   16.285798] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
>>>>
>>>> The board is connected to my laptop rather than to a switch, so that
>>>> might be where the flow control message comes from (not sure). Anyway
>>>> ethernet works.
>>>
>>> Cool, many thanks for taking the time to test and report.
>>>
>>> Hopefully Giuseppe will get this merged quickly enough in mainline, and
>>> it should then trickle into a 4.5-stable release (cc-ing stable on
>>> these patches would probably be a good idea, BTW).
>>
>> stmmac is broken on at least Lime2, BananaPi and Cubieboard2 since
>> v4.5 [0], including all five stable releases :(
>
> All the A20 platforms are dead, actually.
>
>> The v4.5 patches quoted above are already +4 weeks old, could we
>> please get them into stable?
>
> For that, the maintainer would have needed to CC stable, which he
> didn't. I'd expect someone who cares to send these patches to stable.
> It'd be better if the maintainer would do it himself though.

sure, I can send the patches to stable (sorry if I missed to add
stable ML on CC).

Andre, I have not clear if the train of patches actually fix the
issue or if you need my support to fix something else. In that case
I need some input for debugging (e.g. kernel log).

let me know, is it enough to re-send the patches only?

Regards
Peppe

>
> Thanks,
>
> 	M.
>



From hongbo.zhang at nxp.com  Fri May 20 01:23:36 2016
From: hongbo.zhang at nxp.com (Hongbo Zhang)
Date: Fri, 20 May 2016 08:23:36 +0000
Subject: [PSCI DISCUSS] How to implement standby and suspend-to-ram by PSCI
In-Reply-To: <1463659261.14323.3.camel@suse.com>
References: <DB3PR04MB0812DAA98F71C30E8A8832E3847D0@DB3PR04MB0812.eurprd04.prod.outlook.com>
 <572C9BF2.9010004@arm.com>
 <DB3PR04MB08125A628F5034749F8109D884730@DB3PR04MB0812.eurprd04.prod.outlook.com>
 <1463486036.19237.9.camel@suse.com>
 <AM3PR04MB0805D7F5375413C154DFB981844A0@AM3PR04MB0805.eurprd04.prod.outlook.com>
 <1463659261.14323.3.camel@suse.com>
Message-ID: <DB3PR04MB0812AAD69AEE789DB577C2D2844B0@DB3PR04MB0812.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: Oliver Neukum [mailto:oneukum at suse.com]
> Sent: Thursday, May 19, 2016 8:01 PM
> To: Hongbo Zhang <hongbo.zhang at nxp.com>
> Cc: Sudeep Holla <sudeep.holla at arm.com>; linux-pm at vger.kernel.org;
> Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>; Marc Zyngier
> <marc.zyngier at arm.com>; Jan Kiszka <jan.kiszka at siemens.com>; Mark
> Rutland <mark.rutland at arm.com>; Daniel Lezcano
> <daniel.lezcano at linaro.org>; Chen-Yu Tsai <wens at csie.org>; Hans de Goede
> <hdegoede at redhat.com>; Frank Li <Frank.Li at freescale.com>; Peng Fan
> <Peng.Fan at freescale.com>; Tom Warren <twarren at nvidia.com>; Vincent
> Guittot <vincent.guittot at linaro.org>; jszhang at marvell.com; linux-arm-
> kernel at lists.infradead.org
> Subject: Re: [PSCI DISCUSS] How to implement standby and suspend-to-ram by
> PSCI
> 
> On Thu, 2016-05-19 at 10:27 +0000, Hongbo Zhang wrote:
> > > For the pm module of the core kernel a low power state is a sleep
> > > state if even one of three conditions is met:
> > >
> > > a) a device that can be used for input is not a source of wake ups
> > > b) tasks need to be frozen to enter it
> > > c) the display goes off, while it should be on
> > >
> > > Generally runtime PM is better if you can get the same results.
> > > Going to a system sleep state is a necessary evil.
> 
> 
> > As I just explained in previous reply, many devices in our Soc cannot
> > be physically clock or power gated, all the non-wakeup devices can
> > only be gated off at same time by a PM module, so runtime PM doesn't
> > fit for us well.
> 
> You are looking for a contradiction where none is to be found. We have
> PM domains which allow you to model common clocks and gates. You simply
> use the driver core and it will use the common gate when every device is
> idle. Obviously this is also true when the system is suspended. But not
> necessarily only when the system is suspended.
> 
> 	Regards
> 		Oliver
> 

Understand.
Well, currently our situation is that we've already implemented our sleep/deep sleep mode (mapping to kernel terms standby/suspend to ram), and now while transferring to PSCI we meet such a problem.
If runtime PM is used, many device driver's developers have to be involved to offer their runtime callbacks, a lot of efforts needed in whole system level. But yes, runtime PM has its own advantages, will consider to apply it in the coming SOCs.
Thanks for advice.

Hongbo Zhang @ NXP

From jcm at redhat.com  Fri May 20 01:24:18 2016
From: jcm at redhat.com (Jon Masters)
Date: Fri, 20 May 2016 04:24:18 -0400
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF540@lhreml503-mbs>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF540@lhreml503-mbs>
Message-ID: <9a9d2e00-efb4-2607-a410-43af1d3c97c3@redhat.com>

On 05/20/2016 04:11 AM, Gabriele Paoloni wrote:
> Hi Ard, Jon

Hi Gabriele :)

> In our case (HiSilicon Hip05/Hip06) we are using the Designware IP
> that unfortunately is non-ECAM for the RC config space.

Yea, I know, and I've pinged them already.

> A possible ACPI table solution was discussed already in this thread
> 
> https://lkml.org/lkml/2016/3/14/722
> 
> where <<Name (_CID, "PNP0C02")  // Motherboard reserved resource>>
> is used to specify an Host Controller specific resource.
> It looks to me that this can be an approach that can accommodate
> different vendors/scenarios and Bjorn seemed to be quite ok with
> it.

Yeah, pondering that. We'll chat with a few others about it.

> It comes without saying that for future HW releases we all should
> make an effort to deliver fully ECAM compliant controllers.

Right. Like I said, a number of designs have been fixed already.

> What's your view about this approach?

Will followup over the weekend.

Jon.

-- 
Computer Architect | Sent from my Fedora powered laptop


From narmstrong at baylibre.com  Fri May 20 01:27:52 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 10:27:52 +0200
Subject: [PATCH 0/3] Amlogic: GXBB: Add reset controller
Message-ID: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>

Patchset to add and enable the reset controller driver on GXBB platforms.

This reset controller has up to 256 reset lines with reset pulse generation only,
so the assert and deassert calls are not available.

Changes since the RFC at http://lkml.kernel.org/r/1463148012-25988-1-git-send-email-narmstrong at baylibre.com :
- Fix register mapping and bit defines in bindings header
- Remove assert and unassert calls
- Fix missing __iomem

Neil Armstrong (3):
  reset: Add support for the Amlogic Meson GXBB Reset Controller
  dt-bindings: reset: Add bindings for the Meson GXBB Reset Controller
  ARM64: dts: amlogic: Enable Reset Controller on GXBB-based platforms

 .../bindings/reset/amlogic,meson-gxbb-reset.txt    |  18 ++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   6 +
 drivers/reset/Kconfig                              |   6 +
 drivers/reset/Makefile                             |   1 +
 drivers/reset/reset-meson-gxbb.c                   | 129 +++++++++++++
 .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 199 +++++++++++++++++++++
 6 files changed, 359 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/amlogic,meson-gxbb-reset.txt
 create mode 100644 drivers/reset/reset-meson-gxbb.c
 create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h

-- 
2.7.0



From narmstrong at baylibre.com  Fri May 20 01:27:53 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 10:27:53 +0200
Subject: [PATCH 1/3] reset: Add support for the Amlogic Meson GXBB Reset
 Controller
In-Reply-To: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1463732875-23141-2-git-send-email-narmstrong@baylibre.com>

This patch adds the platform driver for the Amlogic Meson GXBB Reset
Controller.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/reset/Kconfig            |   6 ++
 drivers/reset/Makefile           |   1 +
 drivers/reset/reset-meson-gxbb.c | 129 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 136 insertions(+)
 create mode 100644 drivers/reset/reset-meson-gxbb.c

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index df37212..4ac5c4d 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -12,5 +12,11 @@ menuconfig RESET_CONTROLLER
 
 	  If unsure, say no.
 
+config MESON_GXBB_RESET
+	tristate "Amlogic Meson GXBB Reset Driver"
+	depends on (ARCH_MESON && RESET_CONTROLLER)
+	help
+	  Build the Amlogic Meson GxBB reset driver.
+
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index a1fc8ed..5ff83a1 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
 obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
 obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
 obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o
+obj-$(CONFIG_MESON_GXBB_RESET) += reset-meson-gxbb.o
 obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_HISI) += hisilicon/
diff --git a/drivers/reset/reset-meson-gxbb.c b/drivers/reset/reset-meson-gxbb.c
new file mode 100644
index 0000000..e96691b
--- /dev/null
+++ b/drivers/reset/reset-meson-gxbb.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * 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 <linux/err.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define REG_COUNT	8
+#define BITS_PER_REG	32
+
+struct meson_gxbb_reset {
+	void __iomem *reg_base;
+	struct reset_controller_dev rcdev;
+};
+
+static int meson_gxbb_reset_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct meson_gxbb_reset *data =
+		container_of(rcdev, struct meson_gxbb_reset, rcdev);
+	unsigned int bank = id / BITS_PER_REG;
+	unsigned int offset = id % BITS_PER_REG;
+	void __iomem *reg_addr = data->reg_base + (bank << 2);
+
+	if (bank >= REG_COUNT)
+		return -EINVAL;
+
+	writel(BIT(offset), reg_addr);
+
+	return 0;
+}
+
+static const struct reset_control_ops meson_gxbb_reset_ops = {
+	.reset		= meson_gxbb_reset_reset,
+};
+
+static const struct of_device_id meson_gxbb_reset_dt_ids[] = {
+	 { .compatible = "amlogic,meson-gxbb-reset", },
+	 { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, meson_gxbb_reset_dt_ids);
+
+static int meson_gxbb_reset_probe(struct platform_device *pdev)
+{
+	struct meson_gxbb_reset *data;
+	struct resource *res;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(data->reg_base))
+		return PTR_ERR(data->reg_base);
+
+	platform_set_drvdata(pdev, data);
+
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = REG_COUNT * BITS_PER_REG;
+	data->rcdev.ops = &meson_gxbb_reset_ops;
+	data->rcdev.of_node = pdev->dev.of_node;
+
+	return reset_controller_register(&data->rcdev);
+}
+
+static int meson_gxbb_reset_remove(struct platform_device *pdev)
+{
+	struct meson_gxbb_reset *data = platform_get_drvdata(pdev);
+
+	reset_controller_unregister(&data->rcdev);
+
+	return 0;
+}
+
+static struct platform_driver meson_gxbb_reset_driver = {
+	.probe	= meson_gxbb_reset_probe,
+	.remove	= meson_gxbb_reset_remove,
+	.driver = {
+		.name		= "meson_gxbb_reset",
+		.of_match_table	= meson_gxbb_reset_dt_ids,
+	},
+};
+
+module_platform_driver(meson_gxbb_reset_driver);
-- 
2.7.0



From narmstrong at baylibre.com  Fri May 20 01:27:54 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 10:27:54 +0200
Subject: [PATCH 2/3] dt-bindings: reset: Add bindings for the Meson GXBB Reset
 Controller
In-Reply-To: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1463732875-23141-3-git-send-email-narmstrong@baylibre.com>

Add DT bindings for the Meson GXBB SoC Reset Controller documentation and the
associated include file.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 .../bindings/reset/amlogic,meson-gxbb-reset.txt    |  18 ++
 .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 199 +++++++++++++++++++++
 2 files changed, 217 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/amlogic,meson-gxbb-reset.txt
 create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h

diff --git a/Documentation/devicetree/bindings/reset/amlogic,meson-gxbb-reset.txt b/Documentation/devicetree/bindings/reset/amlogic,meson-gxbb-reset.txt
new file mode 100644
index 0000000..0758259
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/amlogic,meson-gxbb-reset.txt
@@ -0,0 +1,18 @@
+Amlogic Meson GXBB SoC Reset Controller
+=======================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "amlogic,meson-gxbb-reset"
+- reg: should contain the register address base
+- #reset-cells: 1, see below
+
+example:
+
+reset: reset-controller {
+	compatible = "amlogic,meson-gxbb-reset";
+	reg = <0x0 0x04404 0x0 0x20>;
+	#reset-cells = <1>;
+};
diff --git a/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
new file mode 100644
index 0000000..ff4e804
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * 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.
+ */
+
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
+
+/*	RESET0				*/
+#define RESET_HIU		0
+/*				1	*/
+#define RESET_DOS_RESET		2
+#define RESET_DDR_TOP		3
+#define RESET_DCU_RESET		4
+#define RESET_VIU		5
+#define RESET_AIU		6
+#define RESET_VID_PLL_DIV	7
+/*				8	*/
+#define RESET_PMUX		9
+#define RESET_VENC		10
+#define RESET_ASSIST		11
+#define RESET_AFIFO2		12
+#define RESET_VCBUS		13
+/*				14	*/
+/*				15	*/
+#define RESET_GIC		16
+#define RESET_CAPB3_DECODE	17
+#define RESET_NAND_CAPB3	18
+#define RESET_HDMITX_CAPB3	19
+#define RESET_MALI_CAPB3	20
+#define RESET_DOS_CAPB3		21
+#define RESET_SYS_CPU_CAPB3	22
+#define RESET_CBUS_CAPB3	23
+#define RESET_AHB_CNTL		24
+#define RESET_AHB_DATA		25
+#define RESET_VCBUS_CLK81	26
+#define RESET_MMC		27
+#define RESET_MIPI_0		28
+#define RESET_MIPI_1		29
+#define RESET_MIPI_2		30
+#define RESET_MIPI_3		31
+/*	RESET1				*/
+#define RESET_CPPM		32
+#define RESET_DEMUX		33
+#define RESET_USB_OTG		34
+#define RESET_DDR		35
+#define RESET_AO_RESET		36
+#define RESET_BT656		37
+#define RESET_AHB_SRAM		38
+/*				39	*/
+#define RESET_PARSER		40
+#define RESET_BLKMV		41
+#define RESET_ISA		42
+#define RESET_ETHERNET		43
+#define RESET_SD_EMMC_A		44
+#define RESET_SD_EMMC_B		45
+#define RESET_SD_EMMC_C		46
+#define RESET_ROM_BOOT		47
+#define RESET_SYS_CPU_0		48
+#define RESET_SYS_CPU_1		49
+#define RESET_SYS_CPU_2		50
+#define RESET_SYS_CPU_3		51
+#define RESET_SYS_CPU_CORE_0	52
+#define RESET_SYS_CPU_CORE_1	53
+#define RESET_SYS_CPU_CORE_2	54
+#define RESET_SYS_CPU_CORE_3	55
+#define RESET_SYS_PLL_DIV	56
+#define RESET_SYS_CPU_AXI	57
+#define RESET_SYS_CPU_L2	58
+#define RESET_SYS_CPU_P		59
+#define RESET_SYS_CPU_MBIST	60
+/*				61	*/
+/*				62	*/
+/*				63	*/
+/*	RESET2				*/
+#define RESET_VD_RMEM		64
+#define RESET_AUDIN		65
+#define RESET_HDMI_TX		66
+/*				67	*/
+/*				68	*/
+/*				69	*/
+#define RESET_GE2D		70
+#define RESET_PARSER_REG	71
+#define RESET_PARSER_FETCH	72
+#define RESET_PARSER_CTL	73
+#define RESET_PARSER_TOP	74
+/*				75	*/
+/*				76	*/
+#define RESET_AO_CPU_RESET	77
+#define RESET_MALI		78
+#define RESET_HDMI_SYSTEM_RESET	79
+/*				80-95	*/
+/*	RESET3				*/
+#define RESET_RING_OSCILLATOR	96
+#define RESET_SYS_CPU		97
+#define RESET_EFUSE		98
+#define RESET_SYS_CPU_BVCI	99
+#define RESET_AIFIFO		100
+#define RESET_TVFE		101
+#define RESET_AHB_BRIDGE_CNTL	102
+/*				103	*/
+#define RESET_AUDIO_DAC		104
+#define RESET_DEMUX_TOP		105
+#define RESET_DEMUX_DES		106
+#define RESET_DEMUX_S2P_0	107
+#define RESET_DEMUX_S2P_1	108
+#define RESET_DEMUX_RESET_0	109
+#define RESET_DEMUX_RESET_1	110
+#define RESET_DEMUX_RESET_2	111
+/*				112-127	*/
+/*	RESET4				*/
+/*				128	*/
+/*				129	*/
+/*				130	*/
+/*				131	*/
+#define RESET_DVIN_RESET	132
+#define RESET_RDMA		133
+#define RESET_VENCI		134
+#define RESET_VENCP		135
+/*				136	*/
+#define RESET_VDAC		137
+#define RESET_RTC		138
+/*				139	*/
+#define RESET_VDI6		140
+#define RESET_VENCL		141
+#define RESET_I2C_MASTER_2	142
+#define RESET_I2C_MASTER_1	143
+/*				144-159	*/
+/*	RESET5				*/
+/*				160-191	*/
+/*	RESET6				*/
+#define RESET_PERIPHS_GENERAL	192
+#define RESET_PERIPHS_SPICC	193
+#define RESET_PERIPHS_SMART_CARD	194
+#define RESET_PERIPHS_SAR_ADC	195
+#define RESET_PERIPHS_I2C_MASTER_0	196
+#define RESET_SANA		197
+/*				198	*/
+#define RESET_PERIPHS_STREAM_INTERFACE	199
+#define RESET_PERIPHS_SDIO	200
+#define RESET_PERIPHS_UART_0	201
+#define RESET_PERIPHS_UART_1_2	202
+#define RESET_PERIPHS_ASYNC_0	203
+#define RESET_PERIPHS_ASYNC_1	204
+#define RESET_PERIPHS_SPI_0	205
+#define RESET_PERIPHS_SDHC	206
+#define RESET_UART_SLIP		207
+/*				208-223	*/
+/*	RESET7				*/
+#define RESET_USB_DDR_0		224
+#define RESET_USB_DDR_1		225
+#define RESET_USB_DDR_2		226
+#define RESET_USB_DDR_3		227
+/*				228	*/
+#define RESET_DEVICE_MMC_ARB	229
+/*				230	*/
+#define RESET_VID_LOCK		231
+#define RESET_A9_DMC_PIPEL	232
+/*				233-255	*/
+
+#endif
-- 
2.7.0



From narmstrong at baylibre.com  Fri May 20 01:27:55 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 10:27:55 +0200
Subject: [PATCH 3/3] ARM64: dts: amlogic: Enable Reset Controller on
 GXBB-based platforms
In-Reply-To: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1463732875-23141-4-git-send-email-narmstrong@baylibre.com>

Update DTSI file to add the reset controller node.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 832815d..2463e04 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -129,6 +129,12 @@
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
 
+			reset: reset-controller at 4404 {
+				compatible = "amlogic,meson-gxbb-reset";
+				reg = <0x0 0x04404 0x0 0x20>;
+				#reset-cells = <1>;
+			};
+
 			uart_A: serial at 84c0 {
 				compatible = "amlogic,meson-uart";
 				reg = <0x0 0x084c0 0x0 0x14>;
-- 
2.7.0



From ard.biesheuvel at linaro.org  Fri May 20 01:28:59 2016
From: ard.biesheuvel at linaro.org (Ard Biesheuvel)
Date: Fri, 20 May 2016 10:28:59 +0200
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
Message-ID: <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>

On 20 May 2016 at 10:01, Jon Masters <jcm at redhat.com> wrote:
> Hi Ard,
>
> On 05/20/2016 03:37 AM, Ard Biesheuvel wrote:
>> On 20 May 2016 at 06:41, Jon Masters <jcm at redhat.com> wrote:
>>> Hi Tomasz, all,
>>>
>>> On 05/11/2016 07:08 AM, Tomasz Nowicki wrote:
>>>
>>>> On 11.05.2016 12:41, Gabriele Paoloni wrote:
>>>
>>>>>> v6 -> v7
>>>>>> - drop quirks handling
>>>>>
>>>>> Maybe I missed something in the v6 discussion thread; when was it
>>>>> decided to drop quirk handling?
>>>>
>>>> I had such requests in previous series.
>>>
>>> A quick note on quirk handling. This, I believe, applies post-merge of
>>> the base infrastructure, which I realize will likely not have quirks.
>>>
>>> We've some "gen1" ARMv8 server platforms where we end up doing quirks
>>> (for things like forcing 32-bit config space accessors and the like) due
>>> to people repurposing existing embedded PCIe IP blocks or using them for
>>> the first time (especially in servers), and those being involved in the
>>> design not necessarily seeing this problem ahead of time, or not
>>> realizing that it would be an issue for servers. In the early days of
>>> ARM server designs 3-4 years ago, many of us had never really played
>>> with ECAM or realized how modern topologies are built.
>>>
>>> Anyway. We missed this one in our SBSA requirements. They say (words to
>>> the effect of) "thou shalt do PCIe the way it is done on servers" but
>>> they aren't prescriptive, and they don't tell people how that actually
>>> is in reality. That is being fixed. A lot of things are happening behind
>>> the scenes - especially with third party IP block providers (all of whom
>>> myself and others are speaking with directly about this) - to ensure
>>> that the next wave of designs won't repeat these mistakes. We don't have
>>> a time machine, but we can contain this from becoming an ongoing mess
>>> for upstream, and we will do so. It won't be a zoo.
>>>
>>> Various proposals have arisen for how to handle quirks in the longer
>>> term, including elaborate frameworks and tables to describe them
>>> generically. I would like to caution against such approaches, especially
>>> in the case that they deviate from practice on x86, or prior to being
>>> standardized fully with other Operating System vendors. I don't expect
>>> there to be too many more than the existing initial set of quirks we
>>> have seen posted. A number of "future" server SoCs have already been
>>> fixed prior to silicon, and new design starts are being warned not to
>>> make this a problem for us to have to clean up later.
>>>
>>> So, I would like to suggest that the eventual framework mirror the
>>> existing approach on x86 systems (matching DMI, etc.) and not be made
>>> into some kind of generic, utopia. This is a case where we want there to
>>> be pain involved (and upstream patches required) when people screw up,
>>> so that they have a level of pain in response to ever making this
>>> mistake in the future. If we try to create too grand a generic scheme
>>> and make it too easy to handle this kind of situation beyond the small
>>> number of existing offenders, we undermine efforts to force vendors to
>>> ensure that their IP blocks are compliant going forward.
>
>> I understand that there is a desire from the RedHat side to mimic x86
>> as closely as possible, but I never saw any technical justification
>> for that.
>
> Understood. My own motivation is always to make the experience as
> familiar as possible, both for end users, as well as for ODMs and the
> entire ecosystem. There are very many ODMs currently working on v8
> server designs and they're already expecting this to be "just like x88".
> Intentionally. But as to the specifics of using DMI...
>
>> DMI contains strings that are visible to userland, and you
>> effectively lock those down to certain values just so that the kernel
>> can distinguish a broken PCIe root complex from a working one. Linux
>> on x86 had no choice, since the overwhelming majority of existing
>> hardware misrepresented itself as generic, and DMI was the only thing
>> available to actually distinguish these broken implementations from
>> one another. This does not mean we should allow and/or encourage this
>> first gen hardware to misrepresent non-compliant hardware as compliant
>> as well.
>
> That's a very reasonable argument. I don't disagree that it would be
> nice to have nicer ways to distinguish the non-compliant IP than
> treating the whole platform with an ASCII matching sledgehammer.
>
>> Since you are talking to all the people involved, how about you
>> convince them to put something in the ACPI tables that allows the
>> kernel to distinguish those non-standard PCIe implementations from
>> hardware that is really generic?
>
> I'm open to this *BUT* it has to be something that will be adopted
> beyond Linux. I have reached out to some non-Linux folks about this. If
> there's buy-in, and if there's agreement to go standardize it through
> the ASWG, then we should do so. What we should not do is treat ARM as
> special in a way that the others aren't involved with. I'll admit DMI
> ended up part of the SBBR in part because I wrote that piece in with the
> assumption that exactly the same matches as on x86 would happen.
>

Is the PCIe root complex so special that you cannot simply describe an
implementation that is not PNP0408 compatible as something else, under
its own unique HID? If everybody is onboard with using ACPI, how is
this any different from describing other parts of the platform
topology? Even if the SBSA mandates generic PCI, they already deviated
from that when they built the hardware, so pretending that it is a
PNP0408 with quirks really does not buy us anything.

>> This way, we can sidestep the quirks
>> debate entirely, since it will simply be a different device as far as
>> the kernel is concerned. This is no worse than a quirk from a
>> practical point of view, since an older OS will be equally unable to
>> run on newer hardware, but it is arguably more true to the standards
>> compliance you tend to preach about, especially since this small pool
>> of third party IP could potentially be identified directly rather than
>> based on some divination of the SoC we may or may not be running on. I
>> am also convinced that adding support for an additional HID() to the
>> ACPI ECAM driver with some special config space handling wired in is
>> an easier sell upstream than making the same ugly mess x86 has had to
>> make because they did not have any choice to begin with.
>
> Again, open to it. I just don't want to do something that's Linux
> specific. So it'll take time. It would be awesome if an interim quirk
> solution existed that got platforms that are shipping in production
> (e.g. HP Moonshot) actually booting upstream kernels this year. We
> /really/ want F25 to be able to run on these without needing to carry an
> out-of-tree quirk patch or just not support them. That's much worse.
>

My whole point is that we don't need quirks in the first place if
non-compliant devices are not being misrepresented as compliant ones.
This is fine for other platform devices, i.e., SATA, network, so
again, why is PCIe so special that we *must* use a generic ID + quirks
rather than a specific ID?

>> If we do need a quirks handling mechanism, I still don't see how the
>> x86 situation extrapolates to ARM. ACPI offers plenty of ways for a
>> SoC vendor to identify the make and particular revision, and quirks
>> could be keyed off of that.
>
> Fair enough. Is there any traction for an interim solution for these
> initial platforms do you think? If we wait to add a new table it's
> probably going to be the end of the year before we get this done.
>

The 'interim solution' is to come to terms with the fact that these
initial platforms are not SBSA compliant, contain a PCIe root complex
that is not PNP0408 but can be identified by its own HID, and we make
the software work with that. This means our message from the beginning
is that, yes, you can have non-compliant hardware and the burden is on
you to get it supported upstream, and no, you don't get to hang out
with the cool SBSA kids if you decide to go that route


From sricharan at codeaurora.org  Fri May 20 01:31:17 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Fri, 20 May 2016 14:01:17 +0530
Subject: [PATCH v2 2/2] i2c: qup: support SMBus block read
In-Reply-To: <757c18e2-562a-9f43-0fb6-ab3e7ac3af88@codeaurora.org>
References: <1463006736-24652-1-git-send-email-nkaje@codeaurora.org>
 <1463006736-24652-2-git-send-email-nkaje@codeaurora.org>
 <000d01d1b0d3$d70e1f30$852a5d90$@codeaurora.org>
 <757c18e2-562a-9f43-0fb6-ab3e7ac3af88@codeaurora.org>
Message-ID: <000501d1b271$fef3bc90$fcdb35b0$@codeaurora.org>

Hi,

<snip..>
>>> @@ -1128,6 +1173,22 @@ static int qup_i2c_read_one_v2(struct
>>> qup_i2c_dev *qup, struct i2c_msg *msg)
>>>   			goto err;
>>>
>>>   		qup->blk.pos++;
>>> +
>>> +		/* Handle SMBus block read length */
>>> +		if (qup_i2c_check_msg_len(msg) && (msg->len == 1)) {
>>> +			if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
>>> +				ret = -EPROTO;
>>> +				goto err;
>>> +			}
>>> +			msg->len += msg->buf[0];
>>> +			qup->pos = 0;
>>> +			qup_i2c_set_read_mode_v2(qup, msg->len);
>>> +			qup_i2c_issue_xfer_v2(qup, msg);
>>> +			ret = qup_i2c_wait_for_complete(qup, msg);
>>> +			if (ret)
>>> +				goto err;
>> 		Is the issue_xfer_v2 needed inside this here ?
>No, qup_i2c_issue_xfer_v2 is needed so that we read rest of the data
>that is indicated by the length we read earlier.

So qup_i2c_issue_xfer_v2 writes the tags and there is one already in the loop above this
 check. So if you just do qup_i2c_set_read_mode_v2 and qup_i2c_set_blk_data inside this
 check, will not be enough ?

Regards,
 Sricharan



From gabriele.paoloni at huawei.com  Fri May 20 01:40:34 2016
From: gabriele.paoloni at huawei.com (Gabriele Paoloni)
Date: Fri, 20 May 2016 08:40:34 +0000
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
Message-ID: <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>

Hi Ard

> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel at linaro.org]
> Sent: 20 May 2016 09:29
> To: Jon Masters
> Cc: Tomasz Nowicki; Gabriele Paoloni; helgaas at kernel.org;
> arnd at arndb.de; will.deacon at arm.com; catalin.marinas at arm.com;
> rafael at kernel.org; hanjun.guo at linaro.org; Lorenzo.Pieralisi at arm.com;
> okaya at codeaurora.org; jchandra at broadcom.com; linaro-
> acpi at lists.linaro.org; linux-pci at vger.kernel.org; dhdang at apm.com;
> Liviu.Dudau at arm.com; ddaney at caviumnetworks.com; jeremy.linton at arm.com;
> linux-kernel at vger.kernel.org; linux-acpi at vger.kernel.org;
> robert.richter at caviumnetworks.com; Suravee.Suthikulpanit at amd.com;
> msalter at redhat.com; Wangyijing; mw at semihalf.com;
> andrea.gallo at linaro.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI host
> controller
> 
> On 20 May 2016 at 10:01, Jon Masters <jcm at redhat.com> wrote:
> > Hi Ard,
> >
> > On 05/20/2016 03:37 AM, Ard Biesheuvel wrote:
> >> On 20 May 2016 at 06:41, Jon Masters <jcm at redhat.com> wrote:
> >>> Hi Tomasz, all,
> >>>
> >>> On 05/11/2016 07:08 AM, Tomasz Nowicki wrote:
> >>>
> >>>> On 11.05.2016 12:41, Gabriele Paoloni wrote:
> >>>
> >>>>>> v6 -> v7
> >>>>>> - drop quirks handling
> >>>>>
> >>>>> Maybe I missed something in the v6 discussion thread; when was it
> >>>>> decided to drop quirk handling?
> >>>>
> >>>> I had such requests in previous series.
> >>>
> >>> A quick note on quirk handling. This, I believe, applies post-merge
> of
> >>> the base infrastructure, which I realize will likely not have
> quirks.
> >>>
> >>> We've some "gen1" ARMv8 server platforms where we end up doing
> quirks
> >>> (for things like forcing 32-bit config space accessors and the
> like) due
> >>> to people repurposing existing embedded PCIe IP blocks or using
> them for
> >>> the first time (especially in servers), and those being involved in
> the
> >>> design not necessarily seeing this problem ahead of time, or not
> >>> realizing that it would be an issue for servers. In the early days
> of
> >>> ARM server designs 3-4 years ago, many of us had never really
> played
> >>> with ECAM or realized how modern topologies are built.
> >>>
> >>> Anyway. We missed this one in our SBSA requirements. They say
> (words to
> >>> the effect of) "thou shalt do PCIe the way it is done on servers"
> but
> >>> they aren't prescriptive, and they don't tell people how that
> actually
> >>> is in reality. That is being fixed. A lot of things are happening
> behind
> >>> the scenes - especially with third party IP block providers (all of
> whom
> >>> myself and others are speaking with directly about this) - to
> ensure
> >>> that the next wave of designs won't repeat these mistakes. We don't
> have
> >>> a time machine, but we can contain this from becoming an ongoing
> mess
> >>> for upstream, and we will do so. It won't be a zoo.
> >>>
> >>> Various proposals have arisen for how to handle quirks in the
> longer
> >>> term, including elaborate frameworks and tables to describe them
> >>> generically. I would like to caution against such approaches,
> especially
> >>> in the case that they deviate from practice on x86, or prior to
> being
> >>> standardized fully with other Operating System vendors. I don't
> expect
> >>> there to be too many more than the existing initial set of quirks
> we
> >>> have seen posted. A number of "future" server SoCs have already
> been
> >>> fixed prior to silicon, and new design starts are being warned not
> to
> >>> make this a problem for us to have to clean up later.
> >>>
> >>> So, I would like to suggest that the eventual framework mirror the
> >>> existing approach on x86 systems (matching DMI, etc.) and not be
> made
> >>> into some kind of generic, utopia. This is a case where we want
> there to
> >>> be pain involved (and upstream patches required) when people screw
> up,
> >>> so that they have a level of pain in response to ever making this
> >>> mistake in the future. If we try to create too grand a generic
> scheme
> >>> and make it too easy to handle this kind of situation beyond the
> small
> >>> number of existing offenders, we undermine efforts to force vendors
> to
> >>> ensure that their IP blocks are compliant going forward.
> >
> >> I understand that there is a desire from the RedHat side to mimic
> x86
> >> as closely as possible, but I never saw any technical justification
> >> for that.
> >
> > Understood. My own motivation is always to make the experience as
> > familiar as possible, both for end users, as well as for ODMs and the
> > entire ecosystem. There are very many ODMs currently working on v8
> > server designs and they're already expecting this to be "just like
> x88".
> > Intentionally. But as to the specifics of using DMI...
> >
> >> DMI contains strings that are visible to userland, and you
> >> effectively lock those down to certain values just so that the
> kernel
> >> can distinguish a broken PCIe root complex from a working one. Linux
> >> on x86 had no choice, since the overwhelming majority of existing
> >> hardware misrepresented itself as generic, and DMI was the only
> thing
> >> available to actually distinguish these broken implementations from
> >> one another. This does not mean we should allow and/or encourage
> this
> >> first gen hardware to misrepresent non-compliant hardware as
> compliant
> >> as well.
> >
> > That's a very reasonable argument. I don't disagree that it would be
> > nice to have nicer ways to distinguish the non-compliant IP than
> > treating the whole platform with an ASCII matching sledgehammer.
> >
> >> Since you are talking to all the people involved, how about you
> >> convince them to put something in the ACPI tables that allows the
> >> kernel to distinguish those non-standard PCIe implementations from
> >> hardware that is really generic?
> >
> > I'm open to this *BUT* it has to be something that will be adopted
> > beyond Linux. I have reached out to some non-Linux folks about this.
> If
> > there's buy-in, and if there's agreement to go standardize it through
> > the ASWG, then we should do so. What we should not do is treat ARM as
> > special in a way that the others aren't involved with. I'll admit DMI
> > ended up part of the SBBR in part because I wrote that piece in with
> the
> > assumption that exactly the same matches as on x86 would happen.
> >
> 
> Is the PCIe root complex so special that you cannot simply describe an
> implementation that is not PNP0408 compatible as something else, under
> its own unique HID? If everybody is onboard with using ACPI, how is
> this any different from describing other parts of the platform
> topology? Even if the SBSA mandates generic PCI, they already deviated
> from that when they built the hardware, so pretending that it is a
> PNP0408 with quirks really does not buy us anything.

From my understanding we want to avoid this as this would allow each
vendor to come up with his own code and it would be much more effort
for the PCI maintainer to rework the PCI framework to accommodate X86
and "all" ARM64 Host Controllers...

I guess this approach is too risky and we want to avoid this. Through
standardization we can more easily maintain the code and scale it to
multiple SoCs...

So this is my understanding; maybe Jon, Tomasz or Lorenzo can give
a bit more explanation...

Thanks

Gab


> 
> >> This way, we can sidestep the quirks
> >> debate entirely, since it will simply be a different device as far
> as
> >> the kernel is concerned. This is no worse than a quirk from a
> >> practical point of view, since an older OS will be equally unable to
> >> run on newer hardware, but it is arguably more true to the standards
> >> compliance you tend to preach about, especially since this small
> pool
> >> of third party IP could potentially be identified directly rather
> than
> >> based on some divination of the SoC we may or may not be running on.
> I
> >> am also convinced that adding support for an additional HID() to the
> >> ACPI ECAM driver with some special config space handling wired in is
> >> an easier sell upstream than making the same ugly mess x86 has had
> to
> >> make because they did not have any choice to begin with.
> >
> > Again, open to it. I just don't want to do something that's Linux
> > specific. So it'll take time. It would be awesome if an interim quirk
> > solution existed that got platforms that are shipping in production
> > (e.g. HP Moonshot) actually booting upstream kernels this year. We
> > /really/ want F25 to be able to run on these without needing to carry
> an
> > out-of-tree quirk patch or just not support them. That's much worse.
> >
> 
> My whole point is that we don't need quirks in the first place if
> non-compliant devices are not being misrepresented as compliant ones.
> This is fine for other platform devices, i.e., SATA, network, so
> again, why is PCIe so special that we *must* use a generic ID + quirks
> rather than a specific ID?
> 
> >> If we do need a quirks handling mechanism, I still don't see how the
> >> x86 situation extrapolates to ARM. ACPI offers plenty of ways for a
> >> SoC vendor to identify the make and particular revision, and quirks
> >> could be keyed off of that.
> >
> > Fair enough. Is there any traction for an interim solution for these
> > initial platforms do you think? If we wait to add a new table it's
> > probably going to be the end of the year before we get this done.
> >
> 
> The 'interim solution' is to come to terms with the fact that these
> initial platforms are not SBSA compliant, contain a PCIe root complex
> that is not PNP0408 but can be identified by its own HID, and we make
> the software work with that. This means our message from the beginning
> is that, yes, you can have non-compliant hardware and the burden is on
> you to get it supported upstream, and no, you don't get to hang out
> with the cool SBSA kids if you decide to go that route

From carlo at caione.org  Fri May 20 01:46:46 2016
From: carlo at caione.org (Carlo Caione)
Date: Fri, 20 May 2016 10:46:46 +0200
Subject: [PATCH 2/3] dt-bindings: reset: Add bindings for the Meson GXBB
 Reset Controller
In-Reply-To: <1463732875-23141-3-git-send-email-narmstrong@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-3-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160520084646.GB16732@mephisto>

On 20/05/16 10:27, Neil Armstrong wrote:
> Add DT bindings for the Meson GXBB SoC Reset Controller documentation and the
> associated include file.

[...]

> +#define RESET_I2C_MASTER_2	142
> +#define RESET_I2C_MASTER_1	143
> +/*				144-159	*/
> +/*	RESET5				*/
> +/*				160-191	*/
> +/*	RESET6				*/
> +#define RESET_PERIPHS_GENERAL	192
> +#define RESET_PERIPHS_SPICC	193
> +#define RESET_PERIPHS_SMART_CARD	194
> +#define RESET_PERIPHS_SAR_ADC	195
> +#define RESET_PERIPHS_I2C_MASTER_0	196
> +#define RESET_SANA		197
> +/*				198	*/
> +#define RESET_PERIPHS_STREAM_INTERFACE	199
> +#define RESET_PERIPHS_SDIO	200
> +#define RESET_PERIPHS_UART_0	201
> +#define RESET_PERIPHS_UART_1_2	202
> +#define RESET_PERIPHS_ASYNC_0	203
> +#define RESET_PERIPHS_ASYNC_1	204
> +#define RESET_PERIPHS_SPI_0	205
> +#define RESET_PERIPHS_SDHC	206
> +#define RESET_UART_SLIP		207
> +/*				208-223	*/
> +/*	RESET7				*/
> +#define RESET_USB_DDR_0		224
> +#define RESET_USB_DDR_1		225
> +#define RESET_USB_DDR_2		226
> +#define RESET_USB_DDR_3		227
> +/*				228	*/
> +#define RESET_DEVICE_MMC_ARB	229
> +/*				230	*/
> +#define RESET_VID_LOCK		231
> +#define RESET_A9_DMC_PIPEL	232
> +/*				233-255	*/
> +
> +#endif

Indentation looks really messy. Can you just shift the numbers to the
right so that they are on the same column?

-- 
Carlo Caione


From carlo at caione.org  Fri May 20 01:47:48 2016
From: carlo at caione.org (Carlo Caione)
Date: Fri, 20 May 2016 10:47:48 +0200
Subject: [PATCH 3/3] ARM64: dts: amlogic: Enable Reset Controller on
 GXBB-based platforms
In-Reply-To: <1463732875-23141-4-git-send-email-narmstrong@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-4-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160520084748.GC16732@mephisto>

On 20/05/16 10:27, Neil Armstrong wrote:
> Update DTSI file to add the reset controller node.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> index 832815d..2463e04 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> @@ -129,6 +129,12 @@
>  			#size-cells = <2>;
>  			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
>  
> +			reset: reset-controller at 4404 {
> +				compatible = "amlogic,meson-gxbb-reset";
> +				reg = <0x0 0x04404 0x0 0x20>;
> +				#reset-cells = <1>;
> +			};
> +
>  			uart_A: serial at 84c0 {
>  				compatible = "amlogic,meson-uart";
>  				reg = <0x0 0x084c0 0x0 0x14>;

Missing #include <dt-bindings/reset/amlogic,meson-gxbb-reset.h> ?

Thanks,

-- 
Carlo Caione


From narmstrong at baylibre.com  Fri May 20 01:51:40 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 10:51:40 +0200
Subject: [PATCH 2/3] dt-bindings: reset: Add bindings for the Meson GXBB
 Reset Controller
In-Reply-To: <20160520084646.GB16732@mephisto>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-3-git-send-email-narmstrong@baylibre.com>
 <20160520084646.GB16732@mephisto>
Message-ID: <573ED01C.2070800@baylibre.com>

On 05/20/2016 10:46 AM, Carlo Caione wrote:
> On 20/05/16 10:27, Neil Armstrong wrote:
>> Add DT bindings for the Meson GXBB SoC Reset Controller documentation and the
>> associated include file.
> 
> [...]
> 
>> +#define RESET_I2C_MASTER_2	142
>> +#define RESET_I2C_MASTER_1	143
>> +/*				144-159	*/
>> +/*	RESET5				*/
>> +/*				160-191	*/
>> +/*	RESET6				*/
>> +#define RESET_PERIPHS_GENERAL	192
>> +#define RESET_PERIPHS_SPICC	193
>> +#define RESET_PERIPHS_SMART_CARD	194
>> +#define RESET_PERIPHS_SAR_ADC	195
>> +#define RESET_PERIPHS_I2C_MASTER_0	196
>> +#define RESET_SANA		197
>> +/*				198	*/
>> +#define RESET_PERIPHS_STREAM_INTERFACE	199
>> +#define RESET_PERIPHS_SDIO	200
>> +#define RESET_PERIPHS_UART_0	201
>> +#define RESET_PERIPHS_UART_1_2	202
>> +#define RESET_PERIPHS_ASYNC_0	203
>> +#define RESET_PERIPHS_ASYNC_1	204
>> +#define RESET_PERIPHS_SPI_0	205
>> +#define RESET_PERIPHS_SDHC	206
>> +#define RESET_UART_SLIP		207
>> +/*				208-223	*/
>> +/*	RESET7				*/
>> +#define RESET_USB_DDR_0		224
>> +#define RESET_USB_DDR_1		225
>> +#define RESET_USB_DDR_2		226
>> +#define RESET_USB_DDR_3		227
>> +/*				228	*/
>> +#define RESET_DEVICE_MMC_ARB	229
>> +/*				230	*/
>> +#define RESET_VID_LOCK		231
>> +#define RESET_A9_DMC_PIPEL	232
>> +/*				233-255	*/
>> +
>> +#endif
> 
> Indentation looks really messy. Can you just shift the numbers to the
> right so that they are on the same column?
> 
Hi Carlo,

The patch format makes it very messy, not as in the original format :
https://github.com/superna9999/linux/blob/6163f8742454bb7ff962956b4e286d110ec0fb79/include/dt-bindings/reset/amlogic%2Cmeson-gxbb-reset.h

Neil


From narmstrong at baylibre.com  Fri May 20 01:53:03 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 10:53:03 +0200
Subject: [PATCH 3/3] ARM64: dts: amlogic: Enable Reset Controller on
 GXBB-based platforms
In-Reply-To: <20160520084748.GC16732@mephisto>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-4-git-send-email-narmstrong@baylibre.com>
 <20160520084748.GC16732@mephisto>
Message-ID: <573ED06F.9070909@baylibre.com>

On 05/20/2016 10:47 AM, Carlo Caione wrote:
> On 20/05/16 10:27, Neil Armstrong wrote:
>> Update DTSI file to add the reset controller node.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> ---
>>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 6 ++++++
>>  1 file changed, 6 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>> index 832815d..2463e04 100644
>> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>> @@ -129,6 +129,12 @@
>>  			#size-cells = <2>;
>>  			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
>>  
>> +			reset: reset-controller at 4404 {
>> +				compatible = "amlogic,meson-gxbb-reset";
>> +				reg = <0x0 0x04404 0x0 0x20>;
>> +				#reset-cells = <1>;
>> +			};
>> +
>>  			uart_A: serial at 84c0 {
>>  				compatible = "amlogic,meson-uart";
>>  				reg = <0x0 0x084c0 0x0 0x14>;
> 
> Missing #include <dt-bindings/reset/amlogic,meson-gxbb-reset.h> ?
> 
> Thanks,
> 

Shouldn't we wait until the reset bindings are actually used in the dtsi ?
I'm quite sure kevin will post it with the Ethernet nodes.

Neil


From carlo at caione.org  Fri May 20 02:04:48 2016
From: carlo at caione.org (Carlo Caione)
Date: Fri, 20 May 2016 11:04:48 +0200
Subject: [PATCH 1/3] reset: Add support for the Amlogic Meson GXBB Reset
 Controller
In-Reply-To: <1463732875-23141-2-git-send-email-narmstrong@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160520090448.GA19888@mephisto>

On 20/05/16 10:27, Neil Armstrong wrote:
> This patch adds the platform driver for the Amlogic Meson GXBB Reset
> Controller.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/reset/Kconfig            |   6 ++
>  drivers/reset/Makefile           |   1 +
>  drivers/reset/reset-meson-gxbb.c | 129 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 136 insertions(+)
>  create mode 100644 drivers/reset/reset-meson-gxbb.c

Do we really need to be that specific (-gxbb)? This driver looks generic
and simple enough to be used for several Amlogic families. You are
already differentiating between them with the include file defining the
reset indexes for the SoC.

> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index df37212..4ac5c4d 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -12,5 +12,11 @@ menuconfig RESET_CONTROLLER
>  
>  	  If unsure, say no.
>  
> +config MESON_GXBB_RESET
> +	tristate "Amlogic Meson GXBB Reset Driver"
> +	depends on (ARCH_MESON && RESET_CONTROLLER)
> +	help
> +	  Build the Amlogic Meson GxBB reset driver.
> +
>  source "drivers/reset/sti/Kconfig"
>  source "drivers/reset/hisilicon/Kconfig"
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index a1fc8ed..5ff83a1 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -3,6 +3,7 @@ obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
>  obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
>  obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
>  obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o
> +obj-$(CONFIG_MESON_GXBB_RESET) += reset-meson-gxbb.o

obj-$(CONFIG_ARCH_MESON) ?

[...]
> +static const struct reset_control_ops meson_gxbb_reset_ops = {
> +	.reset		= meson_gxbb_reset_reset,
> +};

nit: unfortunate name :)

Any reason to not have also .assert / .deassert?

[...]
> +static struct platform_driver meson_gxbb_reset_driver = {
> +	.probe	= meson_gxbb_reset_probe,
> +	.remove	= meson_gxbb_reset_remove,
> +	.driver = {
> +		.name		= "meson_gxbb_reset",
> +		.of_match_table	= meson_gxbb_reset_dt_ids,
> +	},
> +};
> +
> +module_platform_driver(meson_gxbb_reset_driver);

No MODULE_AUTHOR, MODULE_LICENSE, etc... ?

-- 
Carlo Caione


From carlo at caione.org  Fri May 20 02:08:59 2016
From: carlo at caione.org (Carlo Caione)
Date: Fri, 20 May 2016 11:08:59 +0200
Subject: [PATCH 2/3] dt-bindings: reset: Add bindings for the Meson GXBB
 Reset Controller
In-Reply-To: <573ED01C.2070800@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-3-git-send-email-narmstrong@baylibre.com>
 <20160520084646.GB16732@mephisto> <573ED01C.2070800@baylibre.com>
Message-ID: <20160520090859.GB19888@mephisto>

On 20/05/16 10:51, Neil Armstrong wrote:
> On 05/20/2016 10:46 AM, Carlo Caione wrote:
> > On 20/05/16 10:27, Neil Armstrong wrote:
> >> Add DT bindings for the Meson GXBB SoC Reset Controller documentation and the
> >> associated include file.
> > 
> > [...]
> > 
> >> +#define RESET_I2C_MASTER_2	142
> >> +#define RESET_I2C_MASTER_1	143
> >> +/*				144-159	*/
> >> +/*	RESET5				*/
> >> +/*				160-191	*/
> >> +/*	RESET6				*/
> >> +#define RESET_PERIPHS_GENERAL	192
> >> +#define RESET_PERIPHS_SPICC	193
> >> +#define RESET_PERIPHS_SMART_CARD	194
> >> +#define RESET_PERIPHS_SAR_ADC	195
> >> +#define RESET_PERIPHS_I2C_MASTER_0	196
> >> +#define RESET_SANA		197
> >> +/*				198	*/
> >> +#define RESET_PERIPHS_STREAM_INTERFACE	199
> >> +#define RESET_PERIPHS_SDIO	200
> >> +#define RESET_PERIPHS_UART_0	201
> >> +#define RESET_PERIPHS_UART_1_2	202
> >> +#define RESET_PERIPHS_ASYNC_0	203
> >> +#define RESET_PERIPHS_ASYNC_1	204
> >> +#define RESET_PERIPHS_SPI_0	205
> >> +#define RESET_PERIPHS_SDHC	206
> >> +#define RESET_UART_SLIP		207
> >> +/*				208-223	*/
> >> +/*	RESET7				*/
> >> +#define RESET_USB_DDR_0		224
> >> +#define RESET_USB_DDR_1		225
> >> +#define RESET_USB_DDR_2		226
> >> +#define RESET_USB_DDR_3		227
> >> +/*				228	*/
> >> +#define RESET_DEVICE_MMC_ARB	229
> >> +/*				230	*/
> >> +#define RESET_VID_LOCK		231
> >> +#define RESET_A9_DMC_PIPEL	232
> >> +/*				233-255	*/
> >> +
> >> +#endif
> > 
> > Indentation looks really messy. Can you just shift the numbers to the
> > right so that they are on the same column?
> > 
> Hi Carlo,
> 
> The patch format makes it very messy, not as in the original format :
> https://github.com/superna9999/linux/blob/6163f8742454bb7ff962956b4e286d110ec0fb79/include/dt-bindings/reset/amlogic%2Cmeson-gxbb-reset.h

https://raw.githubusercontent.com/superna9999/linux/6163f8742454bb7ff962956b4e286d110ec0fb79/include/dt-bindings/reset/amlogic%2Cmeson-gxbb-reset.h

yes, but 192 -> 200 are not nicely indented to me :)

-- 
Carlo Caione


From narmstrong at baylibre.com  Fri May 20 02:10:27 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 11:10:27 +0200
Subject: [PATCH 1/3] reset: Add support for the Amlogic Meson GXBB Reset
 Controller
In-Reply-To: <20160520090448.GA19888@mephisto>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-2-git-send-email-narmstrong@baylibre.com>
 <20160520090448.GA19888@mephisto>
Message-ID: <573ED483.10101@baylibre.com>

On 05/20/2016 11:04 AM, Carlo Caione wrote:
> On 20/05/16 10:27, Neil Armstrong wrote:
>> This patch adds the platform driver for the Amlogic Meson GXBB Reset
>> Controller.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> ---
>>  drivers/reset/Kconfig            |   6 ++
>>  drivers/reset/Makefile           |   1 +
>>  drivers/reset/reset-meson-gxbb.c | 129 +++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 136 insertions(+)
>>  create mode 100644 drivers/reset/reset-meson-gxbb.c
> 
> Do we really need to be that specific (-gxbb)? This driver looks generic
> and simple enough to be used for several Amlogic families. You are
> already differentiating between them with the include file defining the
> reset indexes for the SoC.

This is a good question, do the S805 have similar registers ? Same count and width ?
I no, it should need a rework to add a data structure per-SoC.

> 
>> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
>> index df37212..4ac5c4d 100644
>> --- a/drivers/reset/Kconfig
>> +++ b/drivers/reset/Kconfig
>> @@ -12,5 +12,11 @@ menuconfig RESET_CONTROLLER
>>  
>>  	  If unsure, say no.
>>  
>> +config MESON_GXBB_RESET
>> +	tristate "Amlogic Meson GXBB Reset Driver"
>> +	depends on (ARCH_MESON && RESET_CONTROLLER)
>> +	help
>> +	  Build the Amlogic Meson GxBB reset driver.
>> +
>>  source "drivers/reset/sti/Kconfig"
>>  source "drivers/reset/hisilicon/Kconfig"
>> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
>> index a1fc8ed..5ff83a1 100644
>> --- a/drivers/reset/Makefile
>> +++ b/drivers/reset/Makefile
>> @@ -3,6 +3,7 @@ obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
>>  obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
>>  obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
>>  obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o
>> +obj-$(CONFIG_MESON_GXBB_RESET) += reset-meson-gxbb.o
> 
> obj-$(CONFIG_ARCH_MESON) ?
> 
> [...]
>> +static const struct reset_control_ops meson_gxbb_reset_ops = {
>> +	.reset		= meson_gxbb_reset_reset,
>> +};
> 
> nit: unfortunate name :)
> 
> Any reason to not have also .assert / .deassert?

The registers seems write-only and does no retain the bit written, assert and deassert makes no sense in this case.

> 
> [...]
>> +static struct platform_driver meson_gxbb_reset_driver = {
>> +	.probe	= meson_gxbb_reset_probe,
>> +	.remove	= meson_gxbb_reset_remove,
>> +	.driver = {
>> +		.name		= "meson_gxbb_reset",
>> +		.of_match_table	= meson_gxbb_reset_dt_ids,
>> +	},
>> +};
>> +
>> +module_platform_driver(meson_gxbb_reset_driver);
> 
> No MODULE_AUTHOR, MODULE_LICENSE, etc... ?

What is the MODULE_LICENCE format for dual licensing ?

Thanks,
Neil



From carlo at caione.org  Fri May 20 02:10:50 2016
From: carlo at caione.org (Carlo Caione)
Date: Fri, 20 May 2016 11:10:50 +0200
Subject: [PATCH 3/3] ARM64: dts: amlogic: Enable Reset Controller on
 GXBB-based platforms
In-Reply-To: <573ED06F.9070909@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-4-git-send-email-narmstrong@baylibre.com>
 <20160520084748.GC16732@mephisto> <573ED06F.9070909@baylibre.com>
Message-ID: <20160520091050.GC19888@mephisto>

On 20/05/16 10:53, Neil Armstrong wrote:
> On 05/20/2016 10:47 AM, Carlo Caione wrote:
> > On 20/05/16 10:27, Neil Armstrong wrote:
> >> Update DTSI file to add the reset controller node.
> >>
> >> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> >> ---
> >>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 6 ++++++
> >>  1 file changed, 6 insertions(+)
> >>
> >> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> >> index 832815d..2463e04 100644
> >> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> >> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> >> @@ -129,6 +129,12 @@
> >>  			#size-cells = <2>;
> >>  			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
> >>  
> >> +			reset: reset-controller at 4404 {
> >> +				compatible = "amlogic,meson-gxbb-reset";
> >> +				reg = <0x0 0x04404 0x0 0x20>;
> >> +				#reset-cells = <1>;
> >> +			};
> >> +
> >>  			uart_A: serial at 84c0 {
> >>  				compatible = "amlogic,meson-uart";
> >>  				reg = <0x0 0x084c0 0x0 0x14>;
> > 
> > Missing #include <dt-bindings/reset/amlogic,meson-gxbb-reset.h> ?
> > 
> > Thanks,
> > 
> 
> Shouldn't we wait until the reset bindings are actually used in the dtsi ?
> I'm quite sure kevin will post it with the Ethernet nodes.

Why? The header file is related to the reset controller. Better add it
now with this patchset.

Cheers,

-- 
Carlo Caione


From ard.biesheuvel at linaro.org  Fri May 20 02:14:03 2016
From: ard.biesheuvel at linaro.org (Ard Biesheuvel)
Date: Fri, 20 May 2016 11:14:03 +0200
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
Message-ID: <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>

On 20 May 2016 at 10:40, Gabriele Paoloni <gabriele.paoloni at huawei.com> wrote:
> Hi Ard
>
>> -----Original Message-----
>> From: Ard Biesheuvel [mailto:ard.biesheuvel at linaro.org]
[...]
>>
>> Is the PCIe root complex so special that you cannot simply describe an
>> implementation that is not PNP0408 compatible as something else, under
>> its own unique HID? If everybody is onboard with using ACPI, how is
>> this any different from describing other parts of the platform
>> topology? Even if the SBSA mandates generic PCI, they already deviated
>> from that when they built the hardware, so pretending that it is a
>> PNP0408 with quirks really does not buy us anything.
>
> From my understanding we want to avoid this as this would allow each
> vendor to come up with his own code and it would be much more effort
> for the PCI maintainer to rework the PCI framework to accommodate X86
> and "all" ARM64 Host Controllers...
>
> I guess this approach is too risky and we want to avoid this. Through
> standardization we can more easily maintain the code and scale it to
> multiple SoCs...
>
> So this is my understanding; maybe Jon, Tomasz or Lorenzo can give
> a bit more explanation...
>

OK, so that boils down to recommending to vendors to represent known
non-compliant hardware as compliant, just so that we don't have to
change the code to support additional flavors of ECAM ? It's fine to
be pragmatic, but that sucks.

We keep confusing the x86 case with the ARM case here: for x86, they
needed to deal with broken hardware *after* the fact, and all they
could do is find /some/ distinguishing feature in order to guess which
exact hardware they might be running on. For arm64, it is the opposite
case. We are currently in a position where we can demand vendors to
comply with the standards they endorsed themselves, and (ab)using ACPI
+ DMI as a de facto platform description rather than plain ACPI makes
me think the DT crowd were actually right from the beginning. It
*directly* violates the standardization principle, since it requires a
priori knowledge inside the OS that a certain 'generic' device must be
driven in a special way.

So can anyone comment on the feasibility of adding support for devices
with vendor specific HIDs (and no generic CIDs) to the current ACPI
ECAM driver in Linux?


From p.zabel at pengutronix.de  Fri May 20 02:27:58 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Fri, 20 May 2016 11:27:58 +0200
Subject: [PATCH 1/3] reset: Add support for the Amlogic Meson GXBB Reset
 Controller
In-Reply-To: <1463732875-23141-2-git-send-email-narmstrong@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <1463736478.4322.31.camel@pengutronix.de>

Hi Neil,

Am Freitag, den 20.05.2016, 10:27 +0200 schrieb Neil Armstrong:
> This patch adds the platform driver for the Amlogic Meson GXBB Reset
> Controller.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/reset/Kconfig            |   6 ++
>  drivers/reset/Makefile           |   1 +
>  drivers/reset/reset-meson-gxbb.c | 129 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 136 insertions(+)
>  create mode 100644 drivers/reset/reset-meson-gxbb.c
> 
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index df37212..4ac5c4d 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -12,5 +12,11 @@ menuconfig RESET_CONTROLLER
>  
>  	  If unsure, say no.
>  
> +config MESON_GXBB_RESET
> +	tristate "Amlogic Meson GXBB Reset Driver"
> +	depends on (ARCH_MESON && RESET_CONTROLLER)

With the "reset: fix Kconfig menu to include reset drivers in sub-menu"
patch [1] applied this is wrapped in "if RESET_CONTROLLER ... endif", so
no need to depend on RESET_CONTROLLER.
Is there a reason to have this configurable at all, though?

[1] https://patchwork.kernel.org/patch/9000591/

> +	help
> +	  Build the Amlogic Meson GxBB reset driver.
> +
>  source "drivers/reset/sti/Kconfig"
>  source "drivers/reset/hisilicon/Kconfig"
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index a1fc8ed..5ff83a1 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -3,6 +3,7 @@ obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
>  obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
>  obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
>  obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o
> +obj-$(CONFIG_MESON_GXBB_RESET) += reset-meson-gxbb.o

Or drop CONFIG_MESON_GXBB_RESET and use CONFIG_ARCH_MESON directly.

[...]
> +static int meson_gxbb_reset_probe(struct platform_device *pdev)
> +{
> +	struct meson_gxbb_reset *data;
> +	struct resource *res;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	data->reg_base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(data->reg_base))
> +		return PTR_ERR(data->reg_base);
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	data->rcdev.owner = THIS_MODULE;
> +	data->rcdev.nr_resets = REG_COUNT * BITS_PER_REG;
> +	data->rcdev.ops = &meson_gxbb_reset_ops;
> +	data->rcdev.of_node = pdev->dev.of_node;
> +
> +	return reset_controller_register(&data->rcdev);

With the "reset: add devm_reset_controller_register API" patch [2]
applied you can use devm_reset_controller_register() here and remove the
meson_gxbb_reset_remove() function below.

[2] https://patchwork.kernel.org/patch/8988471/

> +}
> +
> +static int meson_gxbb_reset_remove(struct platform_device *pdev)
> +{
> +	struct meson_gxbb_reset *data = platform_get_drvdata(pdev);
> +
> +	reset_controller_unregister(&data->rcdev);
> +
> +	return 0;
> +}

Could be removed, then.

regards
Philipp



From p.zabel at pengutronix.de  Fri May 20 02:28:02 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Fri, 20 May 2016 11:28:02 +0200
Subject: [PATCH 1/3] reset: Add support for the Amlogic Meson GXBB Reset
 Controller
In-Reply-To: <573ED483.10101@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-2-git-send-email-narmstrong@baylibre.com>
 <20160520090448.GA19888@mephisto> <573ED483.10101@baylibre.com>
Message-ID: <1463736482.4322.32.camel@pengutronix.de>

Am Freitag, den 20.05.2016, 11:10 +0200 schrieb Neil Armstrong:
[...]
> >> +module_platform_driver(meson_gxbb_reset_driver);
> > 
> > No MODULE_AUTHOR, MODULE_LICENSE, etc... ?
> 
> What is the MODULE_LICENCE format for dual licensing ?

"Dual BSD/GPL"

regards
Philipp



From boris.brezillon at free-electrons.com  Fri May 20 02:38:46 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Fri, 20 May 2016 11:38:46 +0200
Subject: at91 slow clock with an external crystal (on Atmel SAM9G25)
In-Reply-To: <9cf2f9be-7f76-ca65-f2cf-ca0d20de6d2f@overkiz.com>
References: <9cf2f9be-7f76-ca65-f2cf-ca0d20de6d2f@overkiz.com>
Message-ID: <20160520113846.5df0be05@bbrezillon>

+ Atmel and clk maintainers.

Hi Mickael,

Please use get_maintainer.pl (or the MAINTAINERS file) to find people
you should send your questions too

On Wed, 18 May 2016 10:04:35 +0200
Mickael GARDET <m.gardet at overkiz.com> wrote:

> Hi,
> 
> I have one question about usage of slow clock with an external crystal 
> (on Atmel SAM9G25).
> 
> All work fine If I set CONFIG_SCLK=y in at91bootstrap but we wouldn't 
> update at91bootstrap.

Yes, the 'external crystal'/'internal RC osc' selection is currently
done in at91bootstrap, and Linux just use what has been configured by
the bootstrap.

> 
> If I force usage of external crystal (like this [1]) it work 
> for me but what's the recommended way to do this ?

I'd rather see something more generic for mainline, but you can keep it
in your own tree ;).

IMHO, the proper solution would be to add a min_accuracy field in
struct clk_rate_request (and a clk_set_min_accuracy() helper), implement
->determine_rate() in clk-slow.c to find the parent matching this
constraint, and patch all users of the slow clk to set this constraint
to something appropriate (100ppm ?).

At least, slow clock users should check if the accuracy provided by the
slow clock match what they expect and complain if it's not the case
(it's already doable thanks to the clk_get_accuracy() function).

Best Regards,

Boris

> [1]http://code.bulix.org/kpzu92-98883


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


From k.kozlowski at samsung.com  Fri May 20 02:54:58 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 20 May 2016 11:54:58 +0200
Subject: [PATCH] ARM: dts: exynos: Remove unneded always-on for regulators
 on Peach boards
In-Reply-To: <1463694753-7259-1-git-send-email-javier@osg.samsung.com>
References: <1463694753-7259-1-git-send-email-javier@osg.samsung.com>
Message-ID: <573EDEF2.8020903@samsung.com>

On 05/19/2016 11:52 PM, Javier Martinez Canillas wrote:
> The regulator always-on property should only be used for regulators
> that either can't be disabled or the drivers for the client devices
> are not enabling the regulator and so being disabled due to unused.
> 
> There are some max77802 regulators in the Peach Pit and Pi boards
> that are always-on but shouldn't since they are enabled by drivers:
> 
> BUCK5 is max77802 inl1 supply
> BUCK7 is max77802 inl{2,10} supply
> BUCK9 is max77802 inl{3,4,5,7} supply
> BUCK10 is mmc1 vqmmc supply
> LDO9 is adc vdd supply
> 
> This patch removes the always-on property for these regulators.
> 
> Some regulators should remain always-on even when they are used as
> input supplies, because these regulators are also used by other
> components that are not described in the DT, for example:
> 
> LDO10 is hdmi vdd_osc supply but it's also used as input supply for
> the Exynos5420 temperature sensor.

I don't have the schematics, so just guessing: by temperature sensor do
you mean the tmu_cpu* node (supplying power to VDD_TS01/23/4)?

If yes then you can also change it, like on Odroid XU boards.

> 
> LDO8 is hdmi vdd and vdd_pll supply but it's also used as supply for
> the Exynos5420 Display port.
> 
> BUCK2 and BUCK6 are the vdd supplies for the EAGLE and KFC clusters.
> 
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
> ---
> 
>  arch/arm/boot/dts/exynos5420-peach-pit.dts | 5 -----
>  arch/arm/boot/dts/exynos5800-peach-pi.dts  | 5 -----
>  2 files changed, 10 deletions(-)

Anyway,

Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

Best regards,
Krzysztof


From catalin.marinas at arm.com  Fri May 20 02:55:15 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 20 May 2016 10:55:15 +0100
Subject: [PATCH] arm64: cpuinfo: add AArch64 & elf platform for app
 compatibility
In-Reply-To: <573E8300.7060106@hisilicon.com>
References: <1463625873-60016-1-git-send-email-saberlily.xia@hisilicon.com>
 <20160519104925.GL22378@e104818-lin.cambridge.arm.com>
 <573D9E40.4000705@hisilicon.com>
 <20160519125039.GN22378@e104818-lin.cambridge.arm.com>
 <20160519131832.GO22378@e104818-lin.cambridge.arm.com>
 <573E8300.7060106@hisilicon.com>
Message-ID: <20160520095515.GC11974@e104818-lin.cambridge.arm.com>

On Fri, May 20, 2016 at 11:22:40AM +0800, Xiaqing (A) wrote:
> ? 2016/5/19 21:18, Catalin Marinas ??:
> >diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> >index 3808470486f3..6bda9d30a769 100644
> >--- a/arch/arm64/kernel/cpuinfo.c
> >+++ b/arch/arm64/kernel/cpuinfo.c
> >@@ -22,6 +22,7 @@
> >
> >  #include <linux/bitops.h>
> >  #include <linux/bug.h>
> >+#include <linux/elf.h>
> >  #include <linux/init.h>
> >  #include <linux/kernel.h>
> >  #include <linux/personality.h>
> >@@ -104,6 +105,8 @@ static const char *const compat_hwcap2_str[] = {
> >  static int c_show(struct seq_file *m, void *v)
> >  {
> >  	int i, j;
> >+	bool compat = is_compat_task() ||
> >+		personality(current->personality) == PER_LINUX32;
> >
> >  	for_each_online_cpu(i) {
> >  		struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
> >@@ -115,6 +118,9 @@ static int c_show(struct seq_file *m, void *v)
> >  		 * "processor".  Give glibc what it expects.
> >  		 */
> >  		seq_printf(m, "processor\t: %d\n", i);
> >+		if (compat)
> >+			seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
> >+				   MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
> >
> >  		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
> >  			   loops_per_jiffy / (500000UL/HZ),
> >@@ -127,7 +133,7 @@ static int c_show(struct seq_file *m, void *v)
> >  		 * software which does already (at least for 32-bit).
> >  		 */
> >  		seq_puts(m, "Features\t:");
> >-		if (personality(current->personality) == PER_LINUX32) {
> >+		if (compat) {
> >  #ifdef CONFIG_COMPAT
> >  			for (j = 0; compat_hwcap_str[j]; j++)
> >  				if (compat_elf_hwcap & (1 << j))
> >------------------8<---------------------
> >
> >With the above, a compat task or a native one with PER_LINUX32
> >personality would get:
> >
> >processor       : 0
> >model name      : ARMv8 Processor rev 0 (v8l)
> >BogoMIPS        : 100.00
> >Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt lpae evtstrm aes pmull sha1 sha2 crc32
> >CPU implementer : 0x41
> >CPU architecture: 8
> >CPU variant     : 0x0
> >CPU part        : 0xd03
> >CPU revision    : 0
> 
> I have tested with your patch, the app still can not start up at all.
> 
> I'm sorry I didn't explan this exactly before, those apps are 32-bit android
> apps(com.tencent.pao etc.). They want to get the information as
>   "*D m3e : GetCPUType:AArch64 Processor rev 0 (aarch64)*"
> and I'm sure the process is forked by zygote not zygote64 in android M.

So, these 32-bit applications would never run on an arm32 kernel
(because with my patch, compat /proc/cpuinfo is the same as the native
arm32 kernel)? How did they get into this situation?

I recall from some past discussions with Google on this aspect that
there are indeed applications parsing /proc/cpuinfo but the 32-bit
zygote would set PER_LINUX32 so that child processes would inherit it
and always get the compat /proc/cpuinfo. I don't follow the Android
developments, so I can't tell whether this personality setting is in
place.

While we did change the /proc/cpuinfo 64-bit format slightly in 3.19, I
find it insane that there are 32-bit applications relying on always
running under a 64-bit kernel.

-- 
Catalin


From carlo at caione.org  Fri May 20 03:04:37 2016
From: carlo at caione.org (Carlo Caione)
Date: Fri, 20 May 2016 12:04:37 +0200
Subject: [PATCH 1/3] reset: Add support for the Amlogic Meson GXBB Reset
 Controller
In-Reply-To: <573ED483.10101@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-2-git-send-email-narmstrong@baylibre.com>
 <20160520090448.GA19888@mephisto> <573ED483.10101@baylibre.com>
Message-ID: <20160520100437.GA21213@mephisto>

On 20/05/16 11:10, Neil Armstrong wrote:
> On 05/20/2016 11:04 AM, Carlo Caione wrote:
> > On 20/05/16 10:27, Neil Armstrong wrote:
> >> This patch adds the platform driver for the Amlogic Meson GXBB Reset
> >> Controller.
> >>
> >> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> >> ---
> >>  drivers/reset/Kconfig            |   6 ++
> >>  drivers/reset/Makefile           |   1 +
> >>  drivers/reset/reset-meson-gxbb.c | 129 +++++++++++++++++++++++++++++++++++++++
> >>  3 files changed, 136 insertions(+)
> >>  create mode 100644 drivers/reset/reset-meson-gxbb.c
> > 
> > Do we really need to be that specific (-gxbb)? This driver looks generic
> > and simple enough to be used for several Amlogic families. You are
> > already differentiating between them with the include file defining the
> > reset indexes for the SoC.
> 
> This is a good question, do the S805 have similar registers ? Same count and width ?
> I no, it should need a rework to add a data structure per-SoC.

According to the datasheet on S805 we have 7 registers with 16 reset
bits per register.

[...]
> > 
> > [...]
> >> +static struct platform_driver meson_gxbb_reset_driver = {
> >> +	.probe	= meson_gxbb_reset_probe,
> >> +	.remove	= meson_gxbb_reset_remove,
> >> +	.driver = {
> >> +		.name		= "meson_gxbb_reset",
> >> +		.of_match_table	= meson_gxbb_reset_dt_ids,
> >> +	},
> >> +};
> >> +
> >> +module_platform_driver(meson_gxbb_reset_driver);
> > 
> > No MODULE_AUTHOR, MODULE_LICENSE, etc... ?
> 
> What is the MODULE_LICENCE format for dual licensing ?

Dual BSD/GPL ?

Cheers,

-- 
Carlo Caione


From maitysanchayan at gmail.com  Fri May 20 03:02:01 2016
From: maitysanchayan at gmail.com (Sanchayan Maity)
Date: Fri, 20 May 2016 15:32:01 +0530
Subject: [PATCH v3 0/4] Implement SoC driver for Vybrid
Message-ID: <cover.1463737502.git.maitysanchayan@gmail.com>

Hello,

This third patch series is rebased on top of shawn's for-next branch
and tested on Colibri Vybrid VF50 and VF61 modules.

This patchset implements SoC bus support for Freescale Vybrid platform,
implementing the following
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-soc

This a reworked version of an older patchset series posted in June 2015
which was at v5 then [1]. Since the NVMEM framework was then getting
introduced, we decided that first a NVMEM driver for OCOTP peripheral
being in place would be better.

Compared to the older revisions, this driver now relies on NVMEM
consumer API using the NVMEM based vf610_ocotp driver which has
already been in mainline for a while now.

One point on which we were not sure here is whether we really should
introduce a new Kconfig symbol as being introduced here. While we
could just enable it when SOC_VF610 is selected, this however would
introduce circular dependencies.

Feedback is most welcome.

@Rob Herring
Does this patchset address the concerns you had?

Changes since v2:
1. Remove syscon_regmap_read_from_offset function and use the
available syscon functions
2. Remove fsl,vf610-soc-bus and related bindings at SoC node
level and introduce a fsl,vf610-soc node which is used by the
driver to bind and has all the required phandles plus the NVMEM
consumer handles.
3. Fix memory leak. of_node_put was not called for returned node
of of_parse_phandle and memory allocated by nvmem_cell_read was
not freed explicitly in return error paths.

Changes since v1:
Add device tree binding documentation.

2016: v2 patchset
https://lkml.org/lkml/2016/5/2/69

2016: v1 patchset
https://lkml.org/lkml/2016/3/11/132

[1] Older v5:
http://lkml.iu.edu/hypermail/linux/kernel/1506.0/03787.html
Even earlier versions:
Version 4 of the patchset can be found here
https://lkml.org/lkml/2015/5/26/199
Version 3 of the patchset can be found here
http://www.spinics.net/lists/arm-kernel/msg420847.html
Version 2 of the patchset can be found here
http://www.spinics.net/lists/devicetree/msg80654.html
Version 1 of the patchset can be found here
http://www.spinics.net/lists/devicetree/msg80257.html
The RFC version can be found here
https://lkml.org/lkml/2015/5/11/13

Regards,
Sanchayan.

Sanchayan Maity (4):
  ARM: dts: vfxxx: Add device tree node for OCOTP
  ARM: dts: vfxxx: Add On-Chip ROM node for Vybrid
  ARM: dts: vfxxx: Add device tree node required by Vybrid SoC driver
  soc: Add SoC driver for Freescale Vybrid platform

 .../bindings/arm/freescale/fsl,vf610-soc.txt       |  20 +++
 arch/arm/boot/dts/vfxxx.dtsi                       |  29 +++
 drivers/soc/Kconfig                                |   1 +
 drivers/soc/fsl/Kconfig                            |  10 ++
 drivers/soc/fsl/Makefile                           |   1 +
 drivers/soc/fsl/soc-vf610.c                        | 198 +++++++++++++++++++++
 6 files changed, 259 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
 create mode 100644 drivers/soc/fsl/Kconfig
 create mode 100644 drivers/soc/fsl/soc-vf610.c

-- 
2.8.2



From maitysanchayan at gmail.com  Fri May 20 03:02:03 2016
From: maitysanchayan at gmail.com (Sanchayan Maity)
Date: Fri, 20 May 2016 15:32:03 +0530
Subject: [PATCH v3 2/4] ARM: dts: vfxxx: Add On-Chip ROM node for Vybrid
In-Reply-To: <cover.1463737502.git.maitysanchayan@gmail.com>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
Message-ID: <f81f11d720b0f3f871a7203bde5af4d4b6f2f4fa.1463737502.git.maitysanchayan@gmail.com>

Add a device tree node for the On-Chip ROM on Vybrid.

Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
---
 arch/arm/boot/dts/vfxxx.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
index 0e34d44..6c5222e 100644
--- a/arch/arm/boot/dts/vfxxx.dtsi
+++ b/arch/arm/boot/dts/vfxxx.dtsi
@@ -91,6 +91,11 @@
 		interrupt-parent = <&mscm_ir>;
 		ranges;
 
+		ocrom: ocrom at 00000000 {
+			compatible = "fsl,vf610-ocrom", "syscon";
+			reg = <0x00000000 0x18000>;
+		};
+
 		aips0: aips-bus at 40000000 {
 			compatible = "fsl,aips-bus", "simple-bus";
 			#address-cells = <1>;
-- 
2.8.2



From maitysanchayan at gmail.com  Fri May 20 03:02:02 2016
From: maitysanchayan at gmail.com (Sanchayan Maity)
Date: Fri, 20 May 2016 15:32:02 +0530
Subject: [PATCH v3 1/4] ARM: dts: vfxxx: Add device tree node for OCOTP
In-Reply-To: <cover.1463737502.git.maitysanchayan@gmail.com>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
Message-ID: <b8b03694c72f27cebf607da003ebf459d9c08f8b.1463737502.git.maitysanchayan@gmail.com>

Add device tree node for the OCOTP peripheral on Vybrid.

Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
---
 arch/arm/boot/dts/vfxxx.dtsi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
index 2c13ec6..0e34d44 100644
--- a/arch/arm/boot/dts/vfxxx.dtsi
+++ b/arch/arm/boot/dts/vfxxx.dtsi
@@ -520,6 +520,22 @@
 				status = "disabled";
 			};
 
+			ocotp at 400a5000 {
+				compatible = "fsl,vf610-ocotp";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0x400a5000 0xCF0>;
+				clocks = <&clks VF610_CLK_OCOTP>;
+
+				ocotp_cfg0: cfg0 at 410 {
+					reg = <0x410 0x4>;
+				};
+
+				ocotp_cfg1: cfg1 at 420 {
+					reg = <0x420 0x4>;
+				};
+			};
+
 			snvs0: snvs at 400a7000 {
 			    compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
 				reg = <0x400a7000 0x2000>;
-- 
2.8.2



From maitysanchayan at gmail.com  Fri May 20 03:02:04 2016
From: maitysanchayan at gmail.com (Sanchayan Maity)
Date: Fri, 20 May 2016 15:32:04 +0530
Subject: [PATCH v3 3/4] ARM: dts: vfxxx: Add device tree node required by
 Vybrid SoC driver
In-Reply-To: <cover.1463737502.git.maitysanchayan@gmail.com>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
Message-ID: <94eb84f49274732dce3390a217e4f37a81e50373.1463737502.git.maitysanchayan@gmail.com>

Add a device tree node which will be used to bind the Vybrid
SoC driver and provide information adhering to the following:
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-soc

Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
---
 arch/arm/boot/dts/vfxxx.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
index 6c5222e..24979d6 100644
--- a/arch/arm/boot/dts/vfxxx.dtsi
+++ b/arch/arm/boot/dts/vfxxx.dtsi
@@ -770,5 +770,13 @@
 			compatible = "iio-hwmon";
 			io-channels = <&adc0 16>, <&adc1 16>;
 		};
+
+		vf610-soc {
+			compatible = "fsl,vf610-soc";
+			rom-revision = <&ocrom>;
+			mscm = <&mscm_cpucfg>;
+			nvmem-cells = <&ocotp_cfg0>, <&ocotp_cfg1>;
+			nvmem-cell-names = "cfg0", "cfg1";
+		};
 	};
 };
-- 
2.8.2



From maitysanchayan at gmail.com  Fri May 20 03:02:05 2016
From: maitysanchayan at gmail.com (Sanchayan Maity)
Date: Fri, 20 May 2016 15:32:05 +0530
Subject: [PATCH v3 4/4] soc: Add SoC driver for Freescale Vybrid platform
In-Reply-To: <cover.1463737502.git.maitysanchayan@gmail.com>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
Message-ID: <ffef165d05f71a1b19437171d8fdb4bc78f6b1e3.1463737502.git.maitysanchayan@gmail.com>

This adds a SoC driver to be used by Freescale Vybrid SoC's.
Driver utilises syscon and nvmem consumer API's to get the
various register values needed and expose the SoC specific
properties via sysfs.

A sample output from Colibri Vybrid VF61 is below:

root at colibri-vf:~# cd /sys/bus/soc/devices/soc0
root at colibri-vf:/sys/bus/soc/devices/soc0# ls
family     machine    power      revision   soc_id     subsystem  uevent
root at colibri-vf:/sys/bus/soc/devices/soc0# cat family
Freescale Vybrid VF610
root at colibri-vf:/sys/bus/soc/devices/soc0# cat machine
Freescale Vybrid
root at colibri-vf:/sys/bus/soc/devices/soc0# cat revision
00000013
root at colibri-vf:/sys/bus/soc/devices/soc0# cat soc_id
df6472a6130f29d4

Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
---
 .../bindings/arm/freescale/fsl,vf610-soc.txt       |  20 +++
 drivers/soc/Kconfig                                |   1 +
 drivers/soc/fsl/Kconfig                            |  10 ++
 drivers/soc/fsl/Makefile                           |   1 +
 drivers/soc/fsl/soc-vf610.c                        | 198 +++++++++++++++++++++
 5 files changed, 230 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
 create mode 100644 drivers/soc/fsl/Kconfig
 create mode 100644 drivers/soc/fsl/soc-vf610.c

diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
new file mode 100644
index 0000000..338905d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
@@ -0,0 +1,20 @@
+Vybrid System-on-Chip
+---------------------
+
+Required properties:
+
+- compatible: "fsl,vf610-soc"
+- rom-revision: phandle to the on-chip ROM node
+- mscm: phandle to the MSCM CPU configuration node
+- nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
+- nvmem-cell-names: should contain string names "cfg0" and "cfg1"
+
+Example:
+
+	vf610-soc {
+		compatible = "fsl,vf610-soc";
+		rom-revision = <&ocrom>;
+		mscm = <&mscm_cpucfg>;
+		nvmem-cells = <&ocotp_cfg0>, <&ocotp_cfg1>;
+		nvmem-cell-names = "cfg0", "cfg1";
+	};
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cb58ef0..4410eb7 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -2,6 +2,7 @@ menu "SOC (System On Chip) specific Drivers"
 
 source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/brcmstb/Kconfig"
+source "drivers/soc/fsl/Kconfig"
 source "drivers/soc/fsl/qe/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
new file mode 100644
index 0000000..029ea17
--- /dev/null
+++ b/drivers/soc/fsl/Kconfig
@@ -0,0 +1,10 @@
+#
+# Freescale SoC drivers
+
+config SOC_BUS_VF610
+	bool "SoC bus device for the Freescale Vybrid platform"
+	depends on NVMEM && NVMEM_VF610_OCOTP
+	select SOC_BUS
+	help
+	 Include support for the SoC bus on the Freescale Vybrid platform
+	 providing sysfs information about the module variant.
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index 203307f..afaf092 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -2,5 +2,6 @@
 # Makefile for the Linux Kernel SOC fsl specific device drivers
 #
 
+obj-$(CONFIG_SOC_VF610)			+= soc-vf610.o
 obj-$(CONFIG_QUICC_ENGINE)		+= qe/
 obj-$(CONFIG_CPM)			+= qe/
diff --git a/drivers/soc/fsl/soc-vf610.c b/drivers/soc/fsl/soc-vf610.c
new file mode 100644
index 0000000..571ba69
--- /dev/null
+++ b/drivers/soc/fsl/soc-vf610.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2016 Toradex AG.
+ *
+ * Author: Sanchayan Maity <sanchayan.maity at toradex.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+
+#define MSCM_CPxCOUNT_OFFSET	0x2C
+#define MSCM_CPxCFG1_OFFSET	0x14
+#define ROM_REVISION_OFFSET	0x80
+
+struct vf610_soc {
+	struct device *dev;
+	struct soc_device_attribute *soc_dev_attr;
+	struct soc_device *soc_dev;
+	struct nvmem_cell *ocotp_cfg0;
+	struct nvmem_cell *ocotp_cfg1;
+};
+
+static int vf610_soc_probe(struct platform_device *pdev)
+{
+	struct vf610_soc *info;
+	struct device *dev = &pdev->dev;
+	struct device_node *rom_node, *mscm_node;
+	struct regmap *rom_regmap, *mscm_regmap;
+	char soc_type[] = "xx0";
+	size_t id1_len, id2_len;
+	u32 cpucount, l2size, rom_rev;
+	u8 *socid1, *socid2;
+	int ret;
+
+	info = devm_kzalloc(dev, sizeof(struct vf610_soc), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+	info->dev = dev;
+
+	info->ocotp_cfg0 = devm_nvmem_cell_get(dev, "cfg0");
+	if (IS_ERR(info->ocotp_cfg0))
+		return -EPROBE_DEFER;
+
+	info->ocotp_cfg1 = devm_nvmem_cell_get(dev, "cfg1");
+	if (IS_ERR(info->ocotp_cfg1))
+		return -EPROBE_DEFER;
+
+	socid1 = nvmem_cell_read(info->ocotp_cfg0, &id1_len);
+	if (IS_ERR(socid1)) {
+		dev_err(dev, "Could not read nvmem cell %ld\n",
+			PTR_ERR(socid1));
+		return PTR_ERR(socid1);
+	}
+
+	socid2 = nvmem_cell_read(info->ocotp_cfg1, &id2_len);
+	if (IS_ERR(socid2)) {
+		dev_err(dev, "Could not read nvmem cell %ld\n",
+			PTR_ERR(socid2));
+		ret = PTR_ERR(socid2);
+		goto out_socid2;
+	}
+	add_device_randomness(socid1, id1_len);
+	add_device_randomness(socid2, id2_len);
+
+	rom_node = of_parse_phandle(pdev->dev.of_node, "rom-revision", 0);
+	if (!rom_node) {
+		dev_err(dev, "Lookup failed for rom-revision node\n");
+		ret = -ENODEV;
+		goto out_rom_node;
+	}
+
+	mscm_node = of_parse_phandle(pdev->dev.of_node, "mscm", 0);
+	if (!mscm_node) {
+		dev_err(dev, "lookup failed for mscm node\n");
+		ret = -ENODEV;
+		goto out_mscm_node;
+	}
+
+	rom_regmap = syscon_node_to_regmap(rom_node);
+	if (IS_ERR(rom_regmap)) {
+		dev_err(dev, "regmap lookup for ocrom failed %ld\n",
+			PTR_ERR(rom_regmap));
+		ret = PTR_ERR(rom_regmap);
+		goto out;
+	}
+
+	mscm_regmap = syscon_node_to_regmap(mscm_node);
+	if (IS_ERR(mscm_regmap)) {
+		dev_err(dev, "regmap lookup for mscm failed %ld\n",
+			PTR_ERR(mscm_regmap));
+		ret = PTR_ERR(mscm_regmap);
+		goto out;
+	}
+
+	ret = regmap_read(rom_regmap, ROM_REVISION_OFFSET, &rom_rev);
+	if (ret) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ret = regmap_read(mscm_regmap, MSCM_CPxCOUNT_OFFSET, &cpucount);
+	if (ret) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ret = regmap_read(mscm_regmap, MSCM_CPxCFG1_OFFSET, &l2size);
+	if (ret) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	soc_type[0] = cpucount ? '6' : '5'; /* Dual Core => VF6x0 */
+	soc_type[1] = l2size ? '1' : '0'; /* L2 Cache => VFx10 */
+
+	info->soc_dev_attr = devm_kzalloc(dev,
+				sizeof(info->soc_dev_attr), GFP_KERNEL);
+	if (!info->soc_dev_attr) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	info->soc_dev_attr->machine = devm_kasprintf(dev,
+					GFP_KERNEL, "Freescale Vybrid");
+	info->soc_dev_attr->soc_id = devm_kasprintf(dev,
+					GFP_KERNEL,
+					"%02x%02x%02x%02x%02x%02x%02x%02x",
+					socid1[3], socid1[2], socid1[1],
+					socid1[0], socid2[3], socid2[2],
+					socid2[1], socid2[0]);
+	info->soc_dev_attr->family = devm_kasprintf(&pdev->dev,
+					GFP_KERNEL, "Freescale Vybrid VF%s",
+					soc_type);
+	info->soc_dev_attr->revision = devm_kasprintf(dev,
+					GFP_KERNEL, "%08x", rom_rev);
+
+	platform_set_drvdata(pdev, info);
+
+	info->soc_dev = soc_device_register(info->soc_dev_attr);
+	if (IS_ERR(info->soc_dev)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	of_node_put(mscm_node);
+out_mscm_node:
+	of_node_put(rom_node);
+out_rom_node:
+	kfree(socid2);
+out_socid2:
+	kfree(socid1);
+
+	return ret;
+}
+
+static int vf610_soc_remove(struct platform_device *pdev)
+{
+	struct vf610_soc *info = platform_get_drvdata(pdev);
+
+	if (info->soc_dev)
+		soc_device_unregister(info->soc_dev);
+
+	return 0;
+}
+
+static const struct of_device_id vf610_soc_match[] = {
+	{ .compatible = "fsl,vf610-soc", },
+	{ /* */ }
+};
+
+static struct platform_driver vf610_soc_driver = {
+	.probe		= vf610_soc_probe,
+	.remove		= vf610_soc_remove,
+	.driver		= {
+		.name = "vf610-soc",
+		.of_match_table = vf610_soc_match,
+	},
+};
+builtin_platform_driver(vf610_soc_driver);
-- 
2.8.2



From tomi.valkeinen at ti.com  Fri May 20 03:13:33 2016
From: tomi.valkeinen at ti.com (Tomi Valkeinen)
Date: Fri, 20 May 2016 13:13:33 +0300
Subject: [PATCH] ARM: dts: DRA74x: fix DSS PLL2 addresses
Message-ID: <1463739213-31540-1-git-send-email-tomi.valkeinen@ti.com>

DSS's 'pll2_clkctrl' and 'pll2' have wrong addresses in the dra74x.dtsi
file. Video PLL2 has not been used so wrong addresses went unnoticed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen at ti.com>
---
 arch/arm/boot/dts/dra74x.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/dra74x.dtsi
index 4220eeffc65a..5e06020f450b 100644
--- a/arch/arm/boot/dts/dra74x.dtsi
+++ b/arch/arm/boot/dts/dra74x.dtsi
@@ -107,8 +107,8 @@
 	reg = <0x58000000 0x80>,
 	      <0x58004054 0x4>,
 	      <0x58004300 0x20>,
-	      <0x58005054 0x4>,
-	      <0x58005300 0x20>;
+	      <0x58009054 0x4>,
+	      <0x58009300 0x20>;
 	reg-names = "dss", "pll1_clkctrl", "pll1",
 		    "pll2_clkctrl", "pll2";
 
-- 
2.5.0



From lkp at intel.com  Fri May 20 03:27:33 2016
From: lkp at intel.com (kbuild test robot)
Date: Fri, 20 May 2016 18:27:33 +0800
Subject: [patch V3] lib: GCD: add binary GCD algorithm
In-Reply-To: <1461843824-19853-1-git-send-email-zengzhaoxiu@163.com>
Message-ID: <201605201833.ecqQBWwU%fengguang.wu@intel.com>

Hi,

[auto build test ERROR on v4.6-rc5]
[cannot apply to next-20160519]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/zengzhaoxiu-163-com/lib-GCD-add-binary-GCD-algorithm/20160428-195527
config: mips-jz4740 (attached as .config)
compiler: mips-linux-gnu-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=mips 

Note: the linux-review/zengzhaoxiu-163-com/lib-GCD-add-binary-GCD-algorithm/20160428-195527 HEAD 35e1a24e8fc3a5308b053ed3c744f02ec2a76820 builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   In file included from arch/mips/include/asm/bitops.h:21:0,
                    from include/linux/bitops.h:36,
                    from include/linux/kernel.h:10,
                    from include/asm-generic/bug.h:13,
                    from arch/mips/include/asm/bug.h:41,
                    from include/linux/bug.h:4,
                    from include/linux/page-flags.h:9,
                    from kernel/bounds.c:9:
   arch/mips/include/asm/cpu-features.h:205:28: warning: "cpu_data" is not defined [-Wundef]
    # define cpu_has_mips32r6 (cpu_data[0].isa_level & MIPS_CPU_ISA_M32R6)
                               ^
   arch/mips/include/asm/cpu-features.h:241:5: note: in expansion of macro 'cpu_has_mips32r6'
        cpu_has_mips32r6 | cpu_has_mips64r1 | \
        ^
   arch/mips/include/asm/cpu-features.h:289:25: note: in expansion of macro 'cpu_has_mips_r'
    #define cpu_has_clo_clz cpu_has_mips_r
                            ^
   arch/mips/include/asm/cpu-features.h:291:6: note: in expansion of macro 'cpu_has_clo_clz'
    #if !cpu_has_clo_clz
         ^
>> arch/mips/include/asm/cpu-features.h:205:36: error: token "[" is not valid in preprocessor expressions
    # define cpu_has_mips32r6 (cpu_data[0].isa_level & MIPS_CPU_ISA_M32R6)
                                       ^
   arch/mips/include/asm/cpu-features.h:241:5: note: in expansion of macro 'cpu_has_mips32r6'
        cpu_has_mips32r6 | cpu_has_mips64r1 | \
        ^
   arch/mips/include/asm/cpu-features.h:289:25: note: in expansion of macro 'cpu_has_mips_r'
    #define cpu_has_clo_clz cpu_has_mips_r
                            ^
   arch/mips/include/asm/cpu-features.h:291:6: note: in expansion of macro 'cpu_has_clo_clz'
    #if !cpu_has_clo_clz
         ^
   make[2]: *** [kernel/bounds.s] Error 1
   make[2]: Target '__build' not remade because of errors.
   make[1]: *** [prepare0] Error 2
   make[1]: Target 'prepare' not remade because of errors.
   make: *** [sub-make] Error 2

vim +205 arch/mips/include/asm/cpu-features.h

0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  199  # define cpu_has_mips32r1	(cpu_data[0].isa_level & MIPS_CPU_ISA_M32R1)
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  200  #endif
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  201  #ifndef cpu_has_mips32r2
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  202  # define cpu_has_mips32r2	(cpu_data[0].isa_level & MIPS_CPU_ISA_M32R2)
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  203  #endif
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13  204  #ifndef cpu_has_mips32r6
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13 @205  # define cpu_has_mips32r6	(cpu_data[0].isa_level & MIPS_CPU_ISA_M32R6)
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13  206  #endif
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  207  #ifndef cpu_has_mips64r1
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  208  # define cpu_has_mips64r1	(cpu_data[0].isa_level & MIPS_CPU_ISA_M64R1)
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  209  #endif
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  210  #ifndef cpu_has_mips64r2
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  211  # define cpu_has_mips64r2	(cpu_data[0].isa_level & MIPS_CPU_ISA_M64R2)
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  212  #endif
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13  213  #ifndef cpu_has_mips64r6
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13  214  # define cpu_has_mips64r6	(cpu_data[0].isa_level & MIPS_CPU_ISA_M64R6)
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13  215  #endif
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  216  
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  217  /*
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  218   * Shortcuts ...
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  219   */
08a07904 arch/mips/include/asm/cpu-features.h Ralf Baechle      2014-04-19  220  #define cpu_has_mips_2_3_4_5	(cpu_has_mips_2 | cpu_has_mips_3_4_5)
08a07904 arch/mips/include/asm/cpu-features.h Ralf Baechle      2014-04-19  221  #define cpu_has_mips_3_4_5	(cpu_has_mips_3 | cpu_has_mips_4_5)
08a07904 arch/mips/include/asm/cpu-features.h Ralf Baechle      2014-04-19  222  #define cpu_has_mips_4_5	(cpu_has_mips_4 | cpu_has_mips_5)
08a07904 arch/mips/include/asm/cpu-features.h Ralf Baechle      2014-04-19  223  
08a07904 arch/mips/include/asm/cpu-features.h Ralf Baechle      2014-04-19  224  #define cpu_has_mips_2_3_4_5_r	(cpu_has_mips_2 | cpu_has_mips_3_4_5_r)
08a07904 arch/mips/include/asm/cpu-features.h Ralf Baechle      2014-04-19  225  #define cpu_has_mips_3_4_5_r	(cpu_has_mips_3 | cpu_has_mips_4_5_r)
08a07904 arch/mips/include/asm/cpu-features.h Ralf Baechle      2014-04-19  226  #define cpu_has_mips_4_5_r	(cpu_has_mips_4 | cpu_has_mips_5_r)
08a07904 arch/mips/include/asm/cpu-features.h Ralf Baechle      2014-04-19  227  #define cpu_has_mips_5_r	(cpu_has_mips_5 | cpu_has_mips_r)
08a07904 arch/mips/include/asm/cpu-features.h Ralf Baechle      2014-04-19  228  
2d83fea7 arch/mips/include/asm/cpu-features.h Maciej W. Rozycki 2015-04-03  229  #define cpu_has_mips_3_4_5_64_r2_r6					\
2d83fea7 arch/mips/include/asm/cpu-features.h Maciej W. Rozycki 2015-04-03  230  				(cpu_has_mips_3 | cpu_has_mips_4_5_64_r2_r6)
2d83fea7 arch/mips/include/asm/cpu-features.h Maciej W. Rozycki 2015-04-03  231  #define cpu_has_mips_4_5_64_r2_r6					\
2d83fea7 arch/mips/include/asm/cpu-features.h Maciej W. Rozycki 2015-04-03  232  				(cpu_has_mips_4_5 | cpu_has_mips64r1 |	\
2d83fea7 arch/mips/include/asm/cpu-features.h Maciej W. Rozycki 2015-04-03  233  				 cpu_has_mips_r2 | cpu_has_mips_r6)
08a07904 arch/mips/include/asm/cpu-features.h Ralf Baechle      2014-04-19  234  
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13  235  #define cpu_has_mips32	(cpu_has_mips32r1 | cpu_has_mips32r2 | cpu_has_mips32r6)
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13  236  #define cpu_has_mips64	(cpu_has_mips64r1 | cpu_has_mips64r2 | cpu_has_mips64r6)
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  237  #define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1)
0401572a include/asm-mips/cpu-features.h      Ralf Baechle      2005-12-09  238  #define cpu_has_mips_r2 (cpu_has_mips32r2 | cpu_has_mips64r2)
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13  239  #define cpu_has_mips_r6	(cpu_has_mips32r6 | cpu_has_mips64r6)
c46b302b arch/mips/include/asm/cpu-features.h Ralf Baechle      2008-10-28  240  #define cpu_has_mips_r	(cpu_has_mips32r1 | cpu_has_mips32r2 | \
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13 @241  			 cpu_has_mips32r6 | cpu_has_mips64r1 | \
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13  242  			 cpu_has_mips64r2 | cpu_has_mips64r6)
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13  243  
34c56fc1 arch/mips/include/asm/cpu-features.h Leonid Yegoshin   2014-11-13  244  /* MIPSR2 and MIPSR6 have a lot of similarities */

:::::: The code at line 205 was first introduced by commit
:::::: 34c56fc1c167facc375d927687df0a3891d164ac MIPS: asm: cpu: Add MIPSR6 ISA definitions

:::::: TO: Leonid Yegoshin <Leonid.Yegoshin at imgtec.com>
:::::: CC: Markos Chandras <markos.chandras at imgtec.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 18282 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160520/95fd2492/attachment-0001.obj>

From a.heider at gmail.com  Fri May 20 03:30:30 2016
From: a.heider at gmail.com (Andre Heider)
Date: Fri, 20 May 2016 12:30:30 +0200
Subject: 4.5.0 on sun7i-a20-olinuxino-lime2: libphy: PHY stmmac-0:ffffffff
 not found (regression from rc7)
In-Reply-To: <573EC77A.2000800@st.com>
References: <56E9413D.9010902@a20.net> <56E945FF.6080005@arm.com>
 <56E94CF4.2060607@arm.com> <56E95B57.1090100@suse.de>
 <56E9776F.3070102@a20.net> <56E99B0C.2070609@arm.com>
 <56E9F2B8.1030605@a20.net> <20160317075202.16b14ed6@arm.com>
 <CAHsu+b-t_r93XKLJTUcin6xjhOrFVn3_60vwHkbRt3iHK28CbA@mail.gmail.com>
 <573EC33D.2010209@arm.com> <573EC77A.2000800@st.com>
Message-ID: <CAHsu+b9BrqBLdCpsPpetc_4_EaFVGBdDHtoeeCqqzsCG3Wpsig@mail.gmail.com>

Hi,

On Fri, May 20, 2016 at 10:14 AM, Giuseppe CAVALLARO
<peppe.cavallaro at st.com> wrote:
> On 5/20/2016 9:56 AM, Marc Zyngier wrote:
>>
>> On 20/05/16 06:44, Andre Heider wrote:
>>>
>>> Giuseppe, Alexandre, et al.,
>>>
>>> On Thu, Mar 17, 2016 at 8:52 AM, Marc Zyngier <marc.zyngier at arm.com>
>>> wrote:
>>>>
>>>> On Thu, 17 Mar 2016 00:56:40 +0100
>>>> Bert Lindner <bert at a20.net> wrote:
>>>>>
>>>>> On 2016-03-16 18:42, Marc Zyngier wrote:
>>>>>>
>>>>>> On 16/03/16 15:10, Bert Lindner wrote:
>>>>>>>
>>>>>>> On 2016-03-16 14:10, Andreas F?rber wrote:
>>>>>>>>
>>>>>>>> Am 16.03.2016 um 13:09 schrieb Robin Murphy:
>>>>>>>>>
>>>>>>>>> On 16/03/16 11:39, Marc Zyngier wrote:
>>>>>>>>>>
>>>>>>>>>> On 16/03/16 11:19, Bert Lindner wrote:
>>>
>>> ...
>>>>>>>>>>>
>>>>>>>>>>> For the board sun7i-a20-olinuxino-lime2, there seems to be a
>>>>>>>>>>> problem
>>>>>>>>>>> with the eth0 PHY in mainline kernel 4.5.0 that developed since
>>>>>>>>>>> 4.5.0-rc7. Ethernet does not work, although eth0 is reported:
>>>
>>> ...
>>>>>>>>>>>
>>>>>>>>>>> [    9.767125] NET: Registered protocol family 10
>>>>>>>>>>> [   10.357405] libphy: PHY stmmac-0:ffffffff not found
>>>>>>>>>>> [   10.362382] eth0: Could not attach to PHY
>>>>>>>>>>> [   10.366557] stmmac_open: Cannot attach to PHY (error: -19)
>>>
>>> ...
>>>>>>>>
>>>>>>>> v4 fixes for 4.5 are here:
>>>>>>>>
>>>>>>>> https://patchwork.ozlabs.org/patch/598195/ (revert)
>>>>>>>> https://patchwork.ozlabs.org/patch/598196/
>>>
>>> ...
>>>>>>
>>>>>> Good to know, thanks. Could you also give the potential fix a go (as
>>>>>> mentioned by Andreas)? Just to make sure that whatever gets merged
>>>>>> next
>>>>>> will actually fix the issue.
>>>>>
>>>>>
>>>>> Yes sure, it took a while because I had to travel. Confirmed, the
>>>>> v4-for-4.5 fix works well for me, on sun7i-a20-olinuxino-lime2:
>>>>>
>>>>> root at lime2-079f:~# cat /proc/version
>>>>> Linux version 4.5.0-598195-598196-v4 (root at lime2-079f) (gcc version
>>>>> 4.9.1 (Ubuntu/Linaro 4.9.1-16ubuntu6) ) #1 SMP Wed Mar 16 16:44:22 UTC
>>>>> 2016
>>>>>
>>>>> dmesg:
>>>>> [    8.245273] NET: Registered protocol family 10
>>>>> [    9.297406]  RX IPC Checksum Offload disabled
>>>>> [    9.297460]  No MAC Management Counters available
>>>>> [    9.297951] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
>>>>> [   16.285658] sun7i-dwmac 1c50000.ethernet eth0: Link is Up -
>>>>> 1Gbps/Full - flow control rx/tx
>>>>> [   16.285798] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
>>>>>
>>>>> The board is connected to my laptop rather than to a switch, so that
>>>>> might be where the flow control message comes from (not sure). Anyway
>>>>> ethernet works.
>>>>
>>>>
>>>> Cool, many thanks for taking the time to test and report.
>>>>
>>>> Hopefully Giuseppe will get this merged quickly enough in mainline, and
>>>> it should then trickle into a 4.5-stable release (cc-ing stable on
>>>> these patches would probably be a good idea, BTW).
>>>
>>>
>>> stmmac is broken on at least Lime2, BananaPi and Cubieboard2 since
>>> v4.5 [0], including all five stable releases :(
>>
>>
>> All the A20 platforms are dead, actually.
>>
>>> The v4.5 patches quoted above are already +4 weeks old, could we
>>> please get them into stable?
>>
>>
>> For that, the maintainer would have needed to CC stable, which he
>> didn't. I'd expect someone who cares to send these patches to stable.
>> It'd be better if the maintainer would do it himself though.
>
>
> sure, I can send the patches to stable (sorry if I missed to add
> stable ML on CC).
>
> Andre, I have not clear if the train of patches actually fix the
> issue or if you need my support to fix something else. In that case
> I need some input for debugging (e.g. kernel log).

Bert already confirmed that those two patches fixes stmmac on his
Lime2, so I assume that it fixes the issue for all A20 platforms.

> let me know, is it enough to re-send the patches only?

Just a resend with cc:stable :)

Thanks!
Andre


From marc.zyngier at arm.com  Fri May 20 03:36:36 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Fri, 20 May 2016 11:36:36 +0100
Subject: 4.5.0 on sun7i-a20-olinuxino-lime2: libphy: PHY stmmac-0:ffffffff
 not found (regression from rc7)
In-Reply-To: <CAHsu+b9BrqBLdCpsPpetc_4_EaFVGBdDHtoeeCqqzsCG3Wpsig@mail.gmail.com>
References: <56E9413D.9010902@a20.net> <56E945FF.6080005@arm.com>
 <56E94CF4.2060607@arm.com> <56E95B57.1090100@suse.de>
 <56E9776F.3070102@a20.net> <56E99B0C.2070609@arm.com>
 <56E9F2B8.1030605@a20.net> <20160317075202.16b14ed6@arm.com>
 <CAHsu+b-t_r93XKLJTUcin6xjhOrFVn3_60vwHkbRt3iHK28CbA@mail.gmail.com>
 <573EC33D.2010209@arm.com> <573EC77A.2000800@st.com>
 <CAHsu+b9BrqBLdCpsPpetc_4_EaFVGBdDHtoeeCqqzsCG3Wpsig@mail.gmail.com>
Message-ID: <573EE8B4.1050701@arm.com>

On 20/05/16 11:30, Andre Heider wrote:
> Hi,
> 
> On Fri, May 20, 2016 at 10:14 AM, Giuseppe CAVALLARO
> <peppe.cavallaro at st.com> wrote:
>> On 5/20/2016 9:56 AM, Marc Zyngier wrote:
>>>
>>> On 20/05/16 06:44, Andre Heider wrote:
>>>>
>>>> Giuseppe, Alexandre, et al.,
>>>>
>>>> On Thu, Mar 17, 2016 at 8:52 AM, Marc Zyngier <marc.zyngier at arm.com>
>>>> wrote:
>>>>>
>>>>> On Thu, 17 Mar 2016 00:56:40 +0100
>>>>> Bert Lindner <bert at a20.net> wrote:
>>>>>>
>>>>>> On 2016-03-16 18:42, Marc Zyngier wrote:
>>>>>>>
>>>>>>> On 16/03/16 15:10, Bert Lindner wrote:
>>>>>>>>
>>>>>>>> On 2016-03-16 14:10, Andreas F?rber wrote:
>>>>>>>>>
>>>>>>>>> Am 16.03.2016 um 13:09 schrieb Robin Murphy:
>>>>>>>>>>
>>>>>>>>>> On 16/03/16 11:39, Marc Zyngier wrote:
>>>>>>>>>>>
>>>>>>>>>>> On 16/03/16 11:19, Bert Lindner wrote:
>>>>
>>>> ...
>>>>>>>>>>>>
>>>>>>>>>>>> For the board sun7i-a20-olinuxino-lime2, there seems to be a
>>>>>>>>>>>> problem
>>>>>>>>>>>> with the eth0 PHY in mainline kernel 4.5.0 that developed since
>>>>>>>>>>>> 4.5.0-rc7. Ethernet does not work, although eth0 is reported:
>>>>
>>>> ...
>>>>>>>>>>>>
>>>>>>>>>>>> [    9.767125] NET: Registered protocol family 10
>>>>>>>>>>>> [   10.357405] libphy: PHY stmmac-0:ffffffff not found
>>>>>>>>>>>> [   10.362382] eth0: Could not attach to PHY
>>>>>>>>>>>> [   10.366557] stmmac_open: Cannot attach to PHY (error: -19)
>>>>
>>>> ...
>>>>>>>>>
>>>>>>>>> v4 fixes for 4.5 are here:
>>>>>>>>>
>>>>>>>>> https://patchwork.ozlabs.org/patch/598195/ (revert)
>>>>>>>>> https://patchwork.ozlabs.org/patch/598196/
>>>>
>>>> ...
>>>>>>>
>>>>>>> Good to know, thanks. Could you also give the potential fix a go (as
>>>>>>> mentioned by Andreas)? Just to make sure that whatever gets merged
>>>>>>> next
>>>>>>> will actually fix the issue.
>>>>>>
>>>>>>
>>>>>> Yes sure, it took a while because I had to travel. Confirmed, the
>>>>>> v4-for-4.5 fix works well for me, on sun7i-a20-olinuxino-lime2:
>>>>>>
>>>>>> root at lime2-079f:~# cat /proc/version
>>>>>> Linux version 4.5.0-598195-598196-v4 (root at lime2-079f) (gcc version
>>>>>> 4.9.1 (Ubuntu/Linaro 4.9.1-16ubuntu6) ) #1 SMP Wed Mar 16 16:44:22 UTC
>>>>>> 2016
>>>>>>
>>>>>> dmesg:
>>>>>> [    8.245273] NET: Registered protocol family 10
>>>>>> [    9.297406]  RX IPC Checksum Offload disabled
>>>>>> [    9.297460]  No MAC Management Counters available
>>>>>> [    9.297951] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
>>>>>> [   16.285658] sun7i-dwmac 1c50000.ethernet eth0: Link is Up -
>>>>>> 1Gbps/Full - flow control rx/tx
>>>>>> [   16.285798] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
>>>>>>
>>>>>> The board is connected to my laptop rather than to a switch, so that
>>>>>> might be where the flow control message comes from (not sure). Anyway
>>>>>> ethernet works.
>>>>>
>>>>>
>>>>> Cool, many thanks for taking the time to test and report.
>>>>>
>>>>> Hopefully Giuseppe will get this merged quickly enough in mainline, and
>>>>> it should then trickle into a 4.5-stable release (cc-ing stable on
>>>>> these patches would probably be a good idea, BTW).
>>>>
>>>>
>>>> stmmac is broken on at least Lime2, BananaPi and Cubieboard2 since
>>>> v4.5 [0], including all five stable releases :(
>>>
>>>
>>> All the A20 platforms are dead, actually.
>>>
>>>> The v4.5 patches quoted above are already +4 weeks old, could we
>>>> please get them into stable?
>>>
>>>
>>> For that, the maintainer would have needed to CC stable, which he
>>> didn't. I'd expect someone who cares to send these patches to stable.
>>> It'd be better if the maintainer would do it himself though.
>>
>>
>> sure, I can send the patches to stable (sorry if I missed to add
>> stable ML on CC).
>>
>> Andre, I have not clear if the train of patches actually fix the
>> issue or if you need my support to fix something else. In that case
>> I need some input for debugging (e.g. kernel log).
> 
> Bert already confirmed that those two patches fixes stmmac on his
> Lime2, so I assume that it fixes the issue for all A20 platforms.
> 
>> let me know, is it enough to re-send the patches only?
> 
> Just a resend with cc:stable :)

Not quite. Please read Documentation/stable_kernel_rules.txt, and the
section that concerns networking patches (and then consult
Documentation/networking/netdev-FAQ.txt which has all the details).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From broonie at kernel.org  Fri May 20 03:41:54 2016
From: broonie at kernel.org (Mark Brown)
Date: Fri, 20 May 2016 11:41:54 +0100
Subject: [PATCH v7 0/3] ASoC: cygnus: Add audio support for Broadcom
 Cygnus SoC
In-Reply-To: <573E23A2.4020907@broadcom.com>
References: <1463514382-20930-1-git-send-email-simran.rai@broadcom.com>
 <573E23A2.4020907@broadcom.com>
Message-ID: <20160520104154.GI8206@sirena.org.uk>

On Thu, May 19, 2016 at 01:35:46PM -0700, Scott Branden wrote:
> Looks good Simran.
> 
> Mark, anything else for us to do before this driver can be accepted
> upstream?

It's a new driver submitted in the first week of the merge window, I've
not looked at it yet.

Please don't top post, reply in line with needed context.  This allows
readers to readily follow the flow of conversation and understand what
you are talking about and also helps ensure that everything in the
discussion is being addressed.

Please don't send content free pings and please allow a reasonable time
for review.  People get busy, go on holiday, attend conferences and so 
on so unless there is some reason for urgency (like critical bug fixes)
please allow at least a couple of weeks for review.  If there have been
review comments then people may be waiting for those to be addressed.
Sending content free pings just adds to the mail volume (if they are
seen at all) and if something has gone wrong you'll have to resend the
patches anyway.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160520/ef60e100/attachment.sig>

From a.heider at gmail.com  Fri May 20 03:43:32 2016
From: a.heider at gmail.com (Andre Heider)
Date: Fri, 20 May 2016 12:43:32 +0200
Subject: 4.5.0 on sun7i-a20-olinuxino-lime2: libphy: PHY stmmac-0:ffffffff
 not found (regression from rc7)
In-Reply-To: <573EE8B4.1050701@arm.com>
References: <56E9413D.9010902@a20.net> <56E945FF.6080005@arm.com>
 <56E94CF4.2060607@arm.com> <56E95B57.1090100@suse.de>
 <56E9776F.3070102@a20.net> <56E99B0C.2070609@arm.com>
 <56E9F2B8.1030605@a20.net> <20160317075202.16b14ed6@arm.com>
 <CAHsu+b-t_r93XKLJTUcin6xjhOrFVn3_60vwHkbRt3iHK28CbA@mail.gmail.com>
 <573EC33D.2010209@arm.com> <573EC77A.2000800@st.com>
 <CAHsu+b9BrqBLdCpsPpetc_4_EaFVGBdDHtoeeCqqzsCG3Wpsig@mail.gmail.com>
 <573EE8B4.1050701@arm.com>
Message-ID: <CAHsu+b8THiFygO+cwz_wDfL7j1yPjmLCqze5ZnT_w5dasP2UqQ@mail.gmail.com>

Hi,

On Fri, May 20, 2016 at 12:36 PM, Marc Zyngier <marc.zyngier at arm.com> wrote:
> On 20/05/16 11:30, Andre Heider wrote:
>> Hi,
>>
>> On Fri, May 20, 2016 at 10:14 AM, Giuseppe CAVALLARO
>> <peppe.cavallaro at st.com> wrote:
>>> On 5/20/2016 9:56 AM, Marc Zyngier wrote:
>>>>
>>>> On 20/05/16 06:44, Andre Heider wrote:
>>>>>
>>>>> Giuseppe, Alexandre, et al.,
>>>>>
>>>>> On Thu, Mar 17, 2016 at 8:52 AM, Marc Zyngier <marc.zyngier at arm.com>
>>>>> wrote:
>>>>>>
>>>>>> On Thu, 17 Mar 2016 00:56:40 +0100
>>>>>> Bert Lindner <bert at a20.net> wrote:
>>>>>>>
>>>>>>> On 2016-03-16 18:42, Marc Zyngier wrote:
>>>>>>>>
>>>>>>>> On 16/03/16 15:10, Bert Lindner wrote:
>>>>>>>>>
>>>>>>>>> On 2016-03-16 14:10, Andreas F?rber wrote:
>>>>>>>>>>
>>>>>>>>>> Am 16.03.2016 um 13:09 schrieb Robin Murphy:
>>>>>>>>>>>
>>>>>>>>>>> On 16/03/16 11:39, Marc Zyngier wrote:
>>>>>>>>>>>>
>>>>>>>>>>>> On 16/03/16 11:19, Bert Lindner wrote:
>>>>>
>>>>> ...
>>>>>>>>>>>>>
>>>>>>>>>>>>> For the board sun7i-a20-olinuxino-lime2, there seems to be a
>>>>>>>>>>>>> problem
>>>>>>>>>>>>> with the eth0 PHY in mainline kernel 4.5.0 that developed since
>>>>>>>>>>>>> 4.5.0-rc7. Ethernet does not work, although eth0 is reported:
>>>>>
>>>>> ...
>>>>>>>>>>>>>
>>>>>>>>>>>>> [    9.767125] NET: Registered protocol family 10
>>>>>>>>>>>>> [   10.357405] libphy: PHY stmmac-0:ffffffff not found
>>>>>>>>>>>>> [   10.362382] eth0: Could not attach to PHY
>>>>>>>>>>>>> [   10.366557] stmmac_open: Cannot attach to PHY (error: -19)
>>>>>
>>>>> ...
>>>>>>>>>>
>>>>>>>>>> v4 fixes for 4.5 are here:
>>>>>>>>>>
>>>>>>>>>> https://patchwork.ozlabs.org/patch/598195/ (revert)
>>>>>>>>>> https://patchwork.ozlabs.org/patch/598196/
>>>>>
>>>>> ...
>>>>>>>>
>>>>>>>> Good to know, thanks. Could you also give the potential fix a go (as
>>>>>>>> mentioned by Andreas)? Just to make sure that whatever gets merged
>>>>>>>> next
>>>>>>>> will actually fix the issue.
>>>>>>>
>>>>>>>
>>>>>>> Yes sure, it took a while because I had to travel. Confirmed, the
>>>>>>> v4-for-4.5 fix works well for me, on sun7i-a20-olinuxino-lime2:
>>>>>>>
>>>>>>> root at lime2-079f:~# cat /proc/version
>>>>>>> Linux version 4.5.0-598195-598196-v4 (root at lime2-079f) (gcc version
>>>>>>> 4.9.1 (Ubuntu/Linaro 4.9.1-16ubuntu6) ) #1 SMP Wed Mar 16 16:44:22 UTC
>>>>>>> 2016
>>>>>>>
>>>>>>> dmesg:
>>>>>>> [    8.245273] NET: Registered protocol family 10
>>>>>>> [    9.297406]  RX IPC Checksum Offload disabled
>>>>>>> [    9.297460]  No MAC Management Counters available
>>>>>>> [    9.297951] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
>>>>>>> [   16.285658] sun7i-dwmac 1c50000.ethernet eth0: Link is Up -
>>>>>>> 1Gbps/Full - flow control rx/tx
>>>>>>> [   16.285798] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
>>>>>>>
>>>>>>> The board is connected to my laptop rather than to a switch, so that
>>>>>>> might be where the flow control message comes from (not sure). Anyway
>>>>>>> ethernet works.
>>>>>>
>>>>>>
>>>>>> Cool, many thanks for taking the time to test and report.
>>>>>>
>>>>>> Hopefully Giuseppe will get this merged quickly enough in mainline, and
>>>>>> it should then trickle into a 4.5-stable release (cc-ing stable on
>>>>>> these patches would probably be a good idea, BTW).
>>>>>
>>>>>
>>>>> stmmac is broken on at least Lime2, BananaPi and Cubieboard2 since
>>>>> v4.5 [0], including all five stable releases :(
>>>>
>>>>
>>>> All the A20 platforms are dead, actually.
>>>>
>>>>> The v4.5 patches quoted above are already +4 weeks old, could we
>>>>> please get them into stable?
>>>>
>>>>
>>>> For that, the maintainer would have needed to CC stable, which he
>>>> didn't. I'd expect someone who cares to send these patches to stable.
>>>> It'd be better if the maintainer would do it himself though.
>>>
>>>
>>> sure, I can send the patches to stable (sorry if I missed to add
>>> stable ML on CC).
>>>
>>> Andre, I have not clear if the train of patches actually fix the
>>> issue or if you need my support to fix something else. In that case
>>> I need some input for debugging (e.g. kernel log).
>>
>> Bert already confirmed that those two patches fixes stmmac on his
>> Lime2, so I assume that it fixes the issue for all A20 platforms.
>>
>>> let me know, is it enough to re-send the patches only?
>>
>> Just a resend with cc:stable :)
>
> Not quite. Please read Documentation/stable_kernel_rules.txt, and the
> section that concerns networking patches (and then consult
> Documentation/networking/netdev-FAQ.txt which has all the details).

Right, it's just been a while since I sent a patch.
What I really meant was "do what's neccessary for -stable inclusion" :)

Regards,
Andre


From sricharan at codeaurora.org  Fri May 20 03:54:47 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Fri, 20 May 2016 16:24:47 +0530
Subject: [PATCH V5 0/7] iommu/msm: Add DT adaptation and generic bindings
 support
Message-ID: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>

The msm_iommu.c driver currently works based on platform data.
A single master device can be connected to more than one iommu and multiple
contexts in each of the iommu. This association between master and iommus was
represented from platform data using parent/child devices. The master drivers
were responsible for attaching all of the iommus/context to a domain. Now the
platform data support is removed and DT support is added. The master/iommus are
added through generic iommu bindings.

This is essentially rework of the patch posted earlier by
Rob Clark <robdclark at gmail.com>. This series folds the changes in to the
existing driver with the addition of generic bindings.

        http://www.spinics.net/lists/linux-arm-msm/msg10077.html

Tested this series on ifc6410 board.

[V5] Changed the compatible binding name as per comments, added comments
     for usage of barriers in patch 6.

[V4] Addressed comments for making the iommu compatible binding more soc
     specific and updated the documentation for the iommu clocks.

[V3] Addressed comments to correct the usage
     of the #iommu-cells binding, improve the flush_iotlb_range function,
     added a new patch to use writel_relaxed for register access and split
     up the documentation patch.

[V2] Adapted the driver to use generic ARMV7S short descriptor pagetable ops
     and addressed comments.

[V1]
   https://lists.linuxfoundation.org/pipermail/iommu/2015-August/014074.html

Sricharan R (7):
  iommu/msm: Add DT adaptation
  documentation: iommu: Add bindings for msm,iommu-v0 ip
  iommu/msm: Move the contents from msm_iommu_dev.c to msm_iommu.c
  iommu/msm: Add support for generic master bindings
  iommu/msm: use generic ARMV7S short descriptor pagetable ops
  iommu/msm: Use writel_relaxed and add a barrier
  iommu/msm: Remove driver BROKEN

 .../devicetree/bindings/iommu/msm,iommu-v0.txt     |  64 ++
 drivers/iommu/Kconfig                              |   2 +-
 drivers/iommu/Makefile                             |   2 +-
 drivers/iommu/msm_iommu.c                          | 885 +++++++++++----------
 drivers/iommu/msm_iommu.h                          |  73 +-
 drivers/iommu/msm_iommu_dev.c                      | 381 ---------
 drivers/iommu/msm_iommu_hw-8xxx.h                  | 109 +--
 7 files changed, 636 insertions(+), 880 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
 delete mode 100644 drivers/iommu/msm_iommu_dev.c

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Fri May 20 03:54:48 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Fri, 20 May 2016 16:24:48 +0530
Subject: [PATCH V5 1/7] iommu/msm: Add DT adaptation
In-Reply-To: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463741694-1735-2-git-send-email-sricharan@codeaurora.org>

The driver currently works based on platform data. Remove this
and add support for DT. A single master can have multiple ports
connected to more than one iommu.

                      master
                        |
                        |
                        |
           ------------------------
           |                      |
         IOMMU0                 IOMMU1
           |                      |
      ctx0   ctx1            ctx0   ctx1

This association of master and iommus/contexts were previously
represented by platform data parent/child device details. The client
drivers were responsible for programming all of the iommus/contexts
for the device. Now while adapting to generic DT bindings we maintain the
list of iommus, contexts that each master domain is connected to and
program all of them on attach/detach.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/msm_iommu.c     | 252 ++++++++++++++++++---------------
 drivers/iommu/msm_iommu.h     |  73 ++++------
 drivers/iommu/msm_iommu_dev.c | 315 ++++++++++--------------------------------
 3 files changed, 237 insertions(+), 403 deletions(-)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index e321fa5..bc1a4e3 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -48,6 +48,7 @@ __asm__ __volatile__ (							\
 static int msm_iommu_tex_class[4];
 
 DEFINE_SPINLOCK(msm_iommu_lock);
+static LIST_HEAD(qcom_iommu_devices);
 
 struct msm_priv {
 	unsigned long *pgtable;
@@ -60,35 +61,37 @@ static struct msm_priv *to_msm_priv(struct iommu_domain *dom)
 	return container_of(dom, struct msm_priv, domain);
 }
 
-static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
+static int __enable_clocks(struct msm_iommu_dev *iommu)
 {
 	int ret;
 
-	ret = clk_enable(drvdata->pclk);
+	ret = clk_enable(iommu->pclk);
 	if (ret)
 		goto fail;
 
-	if (drvdata->clk) {
-		ret = clk_enable(drvdata->clk);
+	if (iommu->clk) {
+		ret = clk_enable(iommu->clk);
 		if (ret)
-			clk_disable(drvdata->pclk);
+			clk_disable(iommu->pclk);
 	}
 fail:
 	return ret;
 }
 
-static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
+static void __disable_clocks(struct msm_iommu_dev *iommu)
 {
-	clk_disable(drvdata->clk);
-	clk_disable(drvdata->pclk);
+	if (iommu->clk)
+		clk_disable(iommu->clk);
+	clk_disable(iommu->pclk);
 }
 
 static int __flush_iotlb(struct iommu_domain *domain)
 {
 	struct msm_priv *priv = to_msm_priv(domain);
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	struct msm_iommu_dev *iommu = NULL;
+	struct msm_iommu_ctx_dev *master;
 	int ret = 0;
+
 #ifndef CONFIG_IOMMU_PGTABLES_L2
 	unsigned long *fl_table = priv->pgtable;
 	int i;
@@ -105,24 +108,67 @@ static int __flush_iotlb(struct iommu_domain *domain)
 	}
 #endif
 
-	list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
-
-		BUG_ON(!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent);
-
-		iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
-		BUG_ON(!iommu_drvdata);
-
-		ret = __enable_clocks(iommu_drvdata);
+	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
+		ret = __enable_clocks(iommu);
 		if (ret)
 			goto fail;
 
-		SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
-		__disable_clocks(iommu_drvdata);
+		list_for_each_entry(master, &iommu->ctx_list, list)
+			SET_CTX_TLBIALL(iommu->base, master->num, 0);
+
+		__disable_clocks(iommu);
 	}
 fail:
 	return ret;
 }
 
+static int msm_iommu_alloc_ctx(unsigned long *map, int start, int end)
+{
+	int idx;
+
+	do {
+		idx = find_next_zero_bit(map, end, start);
+		if (idx == end)
+			return -ENOSPC;
+	} while (test_and_set_bit(idx, map));
+
+	return idx;
+}
+
+static void msm_iommu_free_ctx(unsigned long *map, int idx)
+{
+	clear_bit(idx, map);
+}
+
+static void config_mids(struct msm_iommu_dev *iommu,
+			struct msm_iommu_ctx_dev *master)
+{
+	int mid, ctx, i;
+
+	for (i = 0; i < master->num_mids; i++) {
+		mid = master->mids[i];
+		ctx = master->num;
+
+		SET_M2VCBR_N(iommu->base, mid, 0);
+		SET_CBACR_N(iommu->base, ctx, 0);
+
+		/* Set VMID = 0 */
+		SET_VMID(iommu->base, mid, 0);
+
+		/* Set the context number for that MID to this context */
+		SET_CBNDX(iommu->base, mid, ctx);
+
+		/* Set MID associated with this context bank to 0*/
+		SET_CBVMID(iommu->base, ctx, 0);
+
+		/* Set the ASID for TLB tagging for this context */
+		SET_CONTEXTIDR_ASID(iommu->base, ctx, ctx);
+
+		/* Set security bit override to be Non-secure */
+		SET_NSCFG(iommu->base, mid, 3);
+	}
+}
+
 static void __reset_context(void __iomem *base, int ctx)
 {
 	SET_BPRCOSH(base, ctx, 0);
@@ -272,94 +318,76 @@ static void msm_iommu_domain_free(struct iommu_domain *domain)
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
-	struct msm_priv *priv;
-	struct msm_iommu_ctx_dev *ctx_dev;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-	struct msm_iommu_ctx_drvdata *tmp_drvdata;
 	int ret = 0;
 	unsigned long flags;
+	struct msm_iommu_dev *iommu;
+	struct msm_priv *priv = to_msm_priv(domain);
+	struct msm_iommu_ctx_dev *master;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	priv = to_msm_priv(domain);
-
-	if (!dev) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	iommu_drvdata = dev_get_drvdata(dev->parent);
-	ctx_drvdata = dev_get_drvdata(dev);
-	ctx_dev = dev->platform_data;
-
-	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (!list_empty(&ctx_drvdata->attached_elm)) {
-		ret = -EBUSY;
-		goto fail;
-	}
-
-	list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
-		if (tmp_drvdata == ctx_drvdata) {
-			ret = -EBUSY;
-			goto fail;
+	list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) {
+		master = list_first_entry(&iommu->ctx_list,
+					  struct msm_iommu_ctx_dev,
+					  list);
+		if (master->of_node == dev->of_node) {
+			ret = __enable_clocks(iommu);
+			if (ret)
+				goto fail;
+
+			list_for_each_entry(master, &iommu->ctx_list, list) {
+				if (master->num) {
+					dev_err(dev, "domain already attached");
+					ret = -EEXIST;
+					goto fail;
+				}
+				master->num =
+					msm_iommu_alloc_ctx(iommu->context_map,
+							    0, iommu->ncb);
+					if (IS_ERR_VALUE(master->num)) {
+						ret = -ENODEV;
+						goto fail;
+					}
+				config_mids(iommu, master);
+				__program_context(iommu->base, master->num,
+						  __pa(priv->pgtable));
+			}
+			__disable_clocks(iommu);
+			list_add(&iommu->dom_node, &priv->list_attached);
 		}
+	}
 
-	ret = __enable_clocks(iommu_drvdata);
-	if (ret)
-		goto fail;
-
-	__program_context(iommu_drvdata->base, ctx_dev->num,
-			  __pa(priv->pgtable));
-
-	__disable_clocks(iommu_drvdata);
-	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
 	ret = __flush_iotlb(domain);
-
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+
 	return ret;
 }
 
 static void msm_iommu_detach_dev(struct iommu_domain *domain,
 				 struct device *dev)
 {
-	struct msm_priv *priv;
-	struct msm_iommu_ctx_dev *ctx_dev;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	struct msm_priv *priv = to_msm_priv(domain);
 	unsigned long flags;
+	struct msm_iommu_dev *iommu;
+	struct msm_iommu_ctx_dev *master;
 	int ret;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
-	priv = to_msm_priv(domain);
-
-	if (!dev)
-		goto fail;
-
-	iommu_drvdata = dev_get_drvdata(dev->parent);
-	ctx_drvdata = dev_get_drvdata(dev);
-	ctx_dev = dev->platform_data;
-
-	if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
-		goto fail;
-
 	ret = __flush_iotlb(domain);
 	if (ret)
 		goto fail;
 
-	ret = __enable_clocks(iommu_drvdata);
-	if (ret)
-		goto fail;
-
-	__reset_context(iommu_drvdata->base, ctx_dev->num);
-	__disable_clocks(iommu_drvdata);
-	list_del_init(&ctx_drvdata->attached_elm);
+	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
+		ret = __enable_clocks(iommu);
+		if (ret)
+			goto fail;
 
+		list_for_each_entry(master, &iommu->ctx_list, list) {
+			msm_iommu_free_ctx(iommu->context_map, master->num);
+			__reset_context(iommu->base, master->num);
+		}
+		__disable_clocks(iommu);
+	}
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 }
@@ -555,47 +583,46 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
 					  dma_addr_t va)
 {
 	struct msm_priv *priv;
-	struct msm_iommu_drvdata *iommu_drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
+	struct msm_iommu_dev *iommu;
+	struct msm_iommu_ctx_dev *master;
 	unsigned int par;
 	unsigned long flags;
-	void __iomem *base;
 	phys_addr_t ret = 0;
-	int ctx;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
 
 	priv = to_msm_priv(domain);
-	if (list_empty(&priv->list_attached))
-		goto fail;
+	iommu = list_first_entry(&priv->list_attached,
+				 struct msm_iommu_dev, dom_node);
 
-	ctx_drvdata = list_entry(priv->list_attached.next,
-				 struct msm_iommu_ctx_drvdata, attached_elm);
-	iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+	if (list_empty(&iommu->ctx_list))
+		goto fail;
 
-	base = iommu_drvdata->base;
-	ctx = ctx_drvdata->num;
+	master = list_first_entry(&iommu->ctx_list,
+				  struct msm_iommu_ctx_dev, list);
+	if (!master)
+		goto fail;
 
-	ret = __enable_clocks(iommu_drvdata);
+	ret = __enable_clocks(iommu);
 	if (ret)
 		goto fail;
 
 	/* Invalidate context TLB */
-	SET_CTX_TLBIALL(base, ctx, 0);
-	SET_V2PPR(base, ctx, va & V2Pxx_VA);
+	SET_CTX_TLBIALL(iommu->base, master->num, 0);
+	SET_V2PPR(iommu->base, master->num, va & V2Pxx_VA);
 
-	par = GET_PAR(base, ctx);
+	par = GET_PAR(iommu->base, master->num);
 
 	/* We are dealing with a supersection */
-	if (GET_NOFAULT_SS(base, ctx))
+	if (GET_NOFAULT_SS(iommu->base, master->num))
 		ret = (par & 0xFF000000) | (va & 0x00FFFFFF);
 	else	/* Upper 20 bits from PAR, lower 12 from VA */
 		ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
 
-	if (GET_FAULT(base, ctx))
+	if (GET_FAULT(iommu->base, master->num))
 		ret = 0;
 
-	__disable_clocks(iommu_drvdata);
+	__disable_clocks(iommu);
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
@@ -635,37 +662,34 @@ static void print_ctx_regs(void __iomem *base, int ctx)
 
 irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 {
-	struct msm_iommu_drvdata *drvdata = dev_id;
-	void __iomem *base;
+	struct msm_iommu_dev *iommu = dev_id;
 	unsigned int fsr;
 	int i, ret;
 
 	spin_lock(&msm_iommu_lock);
 
-	if (!drvdata) {
+	if (!iommu) {
 		pr_err("Invalid device ID in context interrupt handler\n");
 		goto fail;
 	}
 
-	base = drvdata->base;
-
 	pr_err("Unexpected IOMMU page fault!\n");
-	pr_err("base = %08x\n", (unsigned int) base);
+	pr_err("base = %08x\n", (unsigned int)iommu->base);
 
-	ret = __enable_clocks(drvdata);
+	ret = __enable_clocks(iommu);
 	if (ret)
 		goto fail;
 
-	for (i = 0; i < drvdata->ncb; i++) {
-		fsr = GET_FSR(base, i);
+	for (i = 0; i < iommu->ncb; i++) {
+		fsr = GET_FSR(iommu->base, i);
 		if (fsr) {
 			pr_err("Fault occurred in context %d.\n", i);
 			pr_err("Interesting registers:\n");
-			print_ctx_regs(base, i);
-			SET_FSR(base, i, 0x4000000F);
+			print_ctx_regs(iommu->base, i);
+			SET_FSR(iommu->base, i, 0x4000000F);
 		}
 	}
-	__disable_clocks(drvdata);
+	__disable_clocks(iommu);
 fail:
 	spin_unlock(&msm_iommu_lock);
 	return 0;
diff --git a/drivers/iommu/msm_iommu.h b/drivers/iommu/msm_iommu.h
index 5c7c955..4ca25d5 100644
--- a/drivers/iommu/msm_iommu.h
+++ b/drivers/iommu/msm_iommu.h
@@ -42,74 +42,53 @@
  */
 #define MAX_NUM_MIDS	32
 
+/* Maximum number of context banks that can be present in IOMMU */
+#define IOMMU_MAX_CBS	128
+
 /**
  * struct msm_iommu_dev - a single IOMMU hardware instance
- * name		Human-readable name given to this IOMMU HW instance
  * ncb		Number of context banks present on this IOMMU HW instance
+ * dev:		IOMMU device
+ * irq:		Interrupt number
+ * clk:		The bus clock for this IOMMU hardware instance
+ * pclk:	The clock for the IOMMU bus interconnect
+ * dev_node:	list head in qcom_iommu_device_list
+ * dom_node:	list head for domain
+ * ctx_list:	list of 'struct msm_iommu_ctx_dev'
+ * context_map: Bitmap to track allocated context banks
  */
 struct msm_iommu_dev {
-	const char *name;
+	void __iomem *base;
 	int ncb;
+	struct device *dev;
+	int irq;
+	struct clk *clk;
+	struct clk *pclk;
+	struct list_head dev_node;
+	struct list_head dom_node;
+	struct list_head ctx_list;
+	DECLARE_BITMAP(context_map, IOMMU_MAX_CBS);
 };
 
 /**
  * struct msm_iommu_ctx_dev - an IOMMU context bank instance
- * name		Human-readable name given to this context bank
+ * of_node	node ptr of client device
  * num		Index of this context bank within the hardware
  * mids		List of Machine IDs that are to be mapped into this context
  *		bank, terminated by -1. The MID is a set of signals on the
  *		AXI bus that identifies the function associated with a specific
  *		memory request. (See ARM spec).
+ * num_mids	Total number of mids
+ * node		list head in ctx_list
  */
 struct msm_iommu_ctx_dev {
-	const char *name;
+	struct device_node *of_node;
 	int num;
 	int mids[MAX_NUM_MIDS];
+	int num_mids;
+	struct list_head list;
 };
 
-
-/**
- * struct msm_iommu_drvdata - A single IOMMU hardware instance
- * @base:	IOMMU config port base address (VA)
- * @ncb		The number of contexts on this IOMMU
- * @irq:	Interrupt number
- * @clk:	The bus clock for this IOMMU hardware instance
- * @pclk:	The clock for the IOMMU bus interconnect
- *
- * A msm_iommu_drvdata holds the global driver data about a single piece
- * of an IOMMU hardware instance.
- */
-struct msm_iommu_drvdata {
-	void __iomem *base;
-	int irq;
-	int ncb;
-	struct clk *clk;
-	struct clk *pclk;
-};
-
-/**
- * struct msm_iommu_ctx_drvdata - an IOMMU context bank instance
- * @num:		Hardware context number of this context
- * @pdev:		Platform device associated wit this HW instance
- * @attached_elm:	List element for domains to track which devices are
- *			attached to them
- *
- * A msm_iommu_ctx_drvdata holds the driver data for a single context bank
- * within each IOMMU hardware instance
- */
-struct msm_iommu_ctx_drvdata {
-	int num;
-	struct platform_device *pdev;
-	struct list_head attached_elm;
-};
-
-/*
- * Look up an IOMMU context device by its context name. NULL if none found.
- * Useful for testing and drivers that do not yet fully have IOMMU stuff in
- * their platform devices.
- */
-struct device *msm_iommu_get_ctx(const char *ctx_name);
-
 /*
  * Interrupt handler for the IOMMU context fault interrupt. Hooking the
  * interrupt is not supported in the API yet, but this will print an error
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
index 4b09e81..be01cc4 100644
--- a/drivers/iommu/msm_iommu_dev.c
+++ b/drivers/iommu/msm_iommu_dev.c
@@ -30,60 +30,6 @@
 #include "msm_iommu_hw-8xxx.h"
 #include "msm_iommu.h"
 
-struct iommu_ctx_iter_data {
-	/* input */
-	const char *name;
-
-	/* output */
-	struct device *dev;
-};
-
-static struct platform_device *msm_iommu_root_dev;
-
-static int each_iommu_ctx(struct device *dev, void *data)
-{
-	struct iommu_ctx_iter_data *res = data;
-	struct msm_iommu_ctx_dev *c = dev->platform_data;
-
-	if (!res || !c || !c->name || !res->name)
-		return -EINVAL;
-
-	if (!strcmp(res->name, c->name)) {
-		res->dev = dev;
-		return 1;
-	}
-	return 0;
-}
-
-static int each_iommu(struct device *dev, void *data)
-{
-	return device_for_each_child(dev, data, each_iommu_ctx);
-}
-
-struct device *msm_iommu_get_ctx(const char *ctx_name)
-{
-	struct iommu_ctx_iter_data r;
-	int found;
-
-	if (!msm_iommu_root_dev) {
-		pr_err("No root IOMMU device.\n");
-		goto fail;
-	}
-
-	r.name = ctx_name;
-	found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
-
-	if (!found) {
-		pr_err("Could not find context <%s>\n", ctx_name);
-		goto fail;
-	}
-
-	return r.dev;
-fail:
-	return NULL;
-}
-EXPORT_SYMBOL(msm_iommu_get_ctx);
-
 static void msm_iommu_reset(void __iomem *base, int ncb)
 {
 	int ctx;
@@ -128,237 +74,122 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
 static int msm_iommu_probe(struct platform_device *pdev)
 {
 	struct resource *r;
-	struct clk *iommu_clk;
-	struct clk *iommu_pclk;
-	struct msm_iommu_drvdata *drvdata;
-	struct msm_iommu_dev *iommu_dev = dev_get_platdata(&pdev->dev);
-	void __iomem *regs_base;
-	int ret, irq, par;
+	struct msm_iommu_dev *iommu;
+	int ret, par, val;
 
-	if (pdev->id == -1) {
-		msm_iommu_root_dev = pdev;
-		return 0;
-	}
+	iommu = devm_kzalloc(&pdev->dev, sizeof(*iommu), GFP_KERNEL);
+	if (!iommu)
+		return -ENODEV;
 
-	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+	iommu->dev = &pdev->dev;
+	INIT_LIST_HEAD(&iommu->ctx_list);
 
-	if (!drvdata) {
-		ret = -ENOMEM;
-		goto fail;
+	iommu->pclk = devm_clk_get(iommu->dev, "smmu_pclk");
+	if (IS_ERR(iommu->pclk)) {
+		dev_err(iommu->dev, "could not get smmu_pclk\n");
+		return PTR_ERR(iommu->pclk);
 	}
 
-	if (!iommu_dev) {
-		ret = -ENODEV;
-		goto fail;
+	ret = clk_prepare(iommu->pclk);
+	if (ret) {
+		dev_err(iommu->dev, "could not prepare smmu_pclk\n");
+		return ret;
 	}
 
-	iommu_pclk = clk_get(NULL, "smmu_pclk");
-	if (IS_ERR(iommu_pclk)) {
-		ret = -ENODEV;
-		goto fail;
+	iommu->clk = devm_clk_get(iommu->dev, "iommu_clk");
+	if (IS_ERR(iommu->clk)) {
+		dev_err(iommu->dev, "could not get iommu_clk\n");
+		clk_unprepare(iommu->pclk);
+		return PTR_ERR(iommu->clk);
 	}
 
-	ret = clk_prepare_enable(iommu_pclk);
-	if (ret)
-		goto fail_enable;
-
-	iommu_clk = clk_get(&pdev->dev, "iommu_clk");
-
-	if (!IS_ERR(iommu_clk))	{
-		if (clk_get_rate(iommu_clk) == 0)
-			clk_set_rate(iommu_clk, 1);
-
-		ret = clk_prepare_enable(iommu_clk);
-		if (ret) {
-			clk_put(iommu_clk);
-			goto fail_pclk;
-		}
-	} else
-		iommu_clk = NULL;
+	ret = clk_prepare(iommu->clk);
+	if (ret) {
+		dev_err(iommu->dev, "could not prepare iommu_clk\n");
+		clk_unprepare(iommu->pclk);
+		return ret;
+	}
 
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");
-	regs_base = devm_ioremap_resource(&pdev->dev, r);
-	if (IS_ERR(regs_base)) {
-		ret = PTR_ERR(regs_base);
-		goto fail_clk;
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	iommu->base = devm_ioremap_resource(iommu->dev, r);
+	if (IS_ERR(iommu->base)) {
+		dev_err(iommu->dev, "could not get iommu base\n");
+		ret = PTR_ERR(iommu->base);
+		goto fail;
 	}
 
-	irq = platform_get_irq_byname(pdev, "secure_irq");
-	if (irq < 0) {
+	iommu->irq = platform_get_irq(pdev, 0);
+	if (iommu->irq < 0) {
+		dev_err(iommu->dev, "could not get iommu irq\n");
 		ret = -ENODEV;
-		goto fail_clk;
+		goto fail;
 	}
 
-	msm_iommu_reset(regs_base, iommu_dev->ncb);
+	ret = of_property_read_u32(iommu->dev->of_node, "ncb", &val);
+	if (ret) {
+		dev_err(iommu->dev, "could not get ncb\n");
+		goto fail;
+	}
+	iommu->ncb = val;
 
-	SET_M(regs_base, 0, 1);
-	SET_PAR(regs_base, 0, 0);
-	SET_V2PCFG(regs_base, 0, 1);
-	SET_V2PPR(regs_base, 0, 0);
-	par = GET_PAR(regs_base, 0);
-	SET_V2PCFG(regs_base, 0, 0);
-	SET_M(regs_base, 0, 0);
+	msm_iommu_reset(iommu->base, iommu->ncb);
+	SET_M(iommu->base, 0, 1);
+	SET_PAR(iommu->base, 0, 0);
+	SET_V2PCFG(iommu->base, 0, 1);
+	SET_V2PPR(iommu->base, 0, 0);
+	par = GET_PAR(iommu->base, 0);
+	SET_V2PCFG(iommu->base, 0, 0);
+	SET_M(iommu->base, 0, 0);
 
 	if (!par) {
-		pr_err("%s: Invalid PAR value detected\n", iommu_dev->name);
+		pr_err("Invalid PAR value detected\n");
 		ret = -ENODEV;
-		goto fail_clk;
+		goto fail;
 	}
 
-	ret = request_irq(irq, msm_iommu_fault_handler, 0,
-			"msm_iommu_secure_irpt_handler", drvdata);
+	ret = devm_request_threaded_irq(iommu->dev, iommu->irq, NULL,
+					msm_iommu_fault_handler,
+					IRQF_ONESHOT | IRQF_SHARED,
+					"msm_iommu_secure_irpt_handler",
+					iommu);
 	if (ret) {
-		pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
-		goto fail_clk;
+		pr_err("Request IRQ %d failed with ret=%d\n", iommu->irq, ret);
+		goto fail;
 	}
 
+	list_add(&iommu->dev_node, &qcom_iommu_devices);
 
-	drvdata->pclk = iommu_pclk;
-	drvdata->clk = iommu_clk;
-	drvdata->base = regs_base;
-	drvdata->irq = irq;
-	drvdata->ncb = iommu_dev->ncb;
-
-	pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
-		iommu_dev->name, regs_base, irq, iommu_dev->ncb);
-
-	platform_set_drvdata(pdev, drvdata);
-
-	clk_disable(iommu_clk);
-
-	clk_disable(iommu_pclk);
-
-	return 0;
-fail_clk:
-	if (iommu_clk) {
-		clk_disable(iommu_clk);
-		clk_put(iommu_clk);
-	}
-fail_pclk:
-	clk_disable_unprepare(iommu_pclk);
-fail_enable:
-	clk_put(iommu_pclk);
+	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
+		iommu->base, iommu->irq, iommu->ncb);
 fail:
-	kfree(drvdata);
+	clk_unprepare(iommu->clk);
+	clk_unprepare(iommu->pclk);
 	return ret;
 }
 
+static const struct of_device_id msm_iommu_dt_match[] = {
+	{ .compatible = "qcom,apq8064-iommu" },
+	{}
+};
+
 static int msm_iommu_remove(struct platform_device *pdev)
 {
-	struct msm_iommu_drvdata *drv = NULL;
+	struct msm_iommu_dev *iommu = platform_get_drvdata(pdev);
 
-	drv = platform_get_drvdata(pdev);
-	if (drv) {
-		if (drv->clk) {
-			clk_unprepare(drv->clk);
-			clk_put(drv->clk);
-		}
-		clk_unprepare(drv->pclk);
-		clk_put(drv->pclk);
-		memset(drv, 0, sizeof(*drv));
-		kfree(drv);
-	}
-	return 0;
-}
-
-static int msm_iommu_ctx_probe(struct platform_device *pdev)
-{
-	struct msm_iommu_ctx_dev *c = dev_get_platdata(&pdev->dev);
-	struct msm_iommu_drvdata *drvdata;
-	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-	int i, ret;
-
-	if (!c || !pdev->dev.parent)
-		return -EINVAL;
-
-	drvdata = dev_get_drvdata(pdev->dev.parent);
-	if (!drvdata)
-		return -ENODEV;
-
-	ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL);
-	if (!ctx_drvdata)
-		return -ENOMEM;
-
-	ctx_drvdata->num = c->num;
-	ctx_drvdata->pdev = pdev;
-
-	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
-	platform_set_drvdata(pdev, ctx_drvdata);
-
-	ret = clk_prepare_enable(drvdata->pclk);
-	if (ret)
-		goto fail;
-
-	if (drvdata->clk) {
-		ret = clk_prepare_enable(drvdata->clk);
-		if (ret) {
-			clk_disable_unprepare(drvdata->pclk);
-			goto fail;
-		}
-	}
-
-	/* Program the M2V tables for this context */
-	for (i = 0; i < MAX_NUM_MIDS; i++) {
-		int mid = c->mids[i];
-		if (mid == -1)
-			break;
-
-		SET_M2VCBR_N(drvdata->base, mid, 0);
-		SET_CBACR_N(drvdata->base, c->num, 0);
-
-		/* Set VMID = 0 */
-		SET_VMID(drvdata->base, mid, 0);
-
-		/* Set the context number for that MID to this context */
-		SET_CBNDX(drvdata->base, mid, c->num);
-
-		/* Set MID associated with this context bank to 0*/
-		SET_CBVMID(drvdata->base, c->num, 0);
-
-		/* Set the ASID for TLB tagging for this context */
-		SET_CONTEXTIDR_ASID(drvdata->base, c->num, c->num);
-
-		/* Set security bit override to be Non-secure */
-		SET_NSCFG(drvdata->base, mid, 3);
-	}
-
-	clk_disable(drvdata->clk);
-	clk_disable(drvdata->pclk);
-
-	dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
-	return 0;
-fail:
-	kfree(ctx_drvdata);
-	return ret;
-}
-
-static int msm_iommu_ctx_remove(struct platform_device *pdev)
-{
-	struct msm_iommu_ctx_drvdata *drv = NULL;
-	drv = platform_get_drvdata(pdev);
-	if (drv) {
-		memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
-		kfree(drv);
-	}
+	clk_unprepare(iommu->clk);
+	clk_unprepare(iommu->pclk);
 	return 0;
 }
 
 static struct platform_driver msm_iommu_driver = {
 	.driver = {
 		.name	= "msm_iommu",
+		.of_match_table = msm_iommu_dt_match,
 	},
 	.probe		= msm_iommu_probe,
 	.remove		= msm_iommu_remove,
 };
 
-static struct platform_driver msm_iommu_ctx_driver = {
-	.driver = {
-		.name	= "msm_iommu_ctx",
-	},
-	.probe		= msm_iommu_ctx_probe,
-	.remove		= msm_iommu_ctx_remove,
-};
-
 static struct platform_driver * const drivers[] = {
 	&msm_iommu_driver,
 	&msm_iommu_ctx_driver,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Fri May 20 03:54:49 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Fri, 20 May 2016 16:24:49 +0530
Subject: [PATCH V5 2/7] documentation: iommu: Add bindings for msm, iommu-v0 ip
In-Reply-To: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463741694-1735-3-git-send-email-sricharan@codeaurora.org>

The MSM IOMMU is an implementation compatible with the ARM VMSA short
descriptor page tables. It provides address translation for bus masters outside
of the CPU, each connected to the IOMMU through a port called micro-TLB.
Adding the DT bindings for the same.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 .../devicetree/bindings/iommu/msm,iommu-v0.txt     | 64 ++++++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt

diff --git a/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
new file mode 100644
index 0000000..2023638
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
@@ -0,0 +1,64 @@
+* QCOM IOMMU
+
+The MSM IOMMU is an implementation compatible with the ARM VMSA short
+descriptor page tables. It provides address translation for bus masters outside
+of the CPU, each connected to the IOMMU through a port called micro-TLB.
+
+Required Properties:
+
+  - compatible: Must contain "qcom,apq8064-iommu".
+  - reg: Base address and size of the IOMMU registers.
+  - interrupts: Specifiers for the MMU fault interrupts. For instances that
+    support secure mode two interrupts must be specified, for non-secure and
+    secure mode, in that order. For instances that don't support secure mode a
+    single interrupt must be specified.
+  - #iommu-cells: The number of cells needed to specify the stream id. This
+		  is always 1.
+  - qcom,ncb:	  The total number of context banks in the IOMMU.
+  - clocks	: List of clocks to be used during SMMU register access. See
+		  Documentation/devicetree/bindings/clock/clock-bindings.txt
+		  for information about the format. For each clock specified
+		  here, there must be a corresponding entry in clock-names
+		  (see below).
+
+  - clock-names	: List of clock names corresponding to the clocks specified in
+		  the "clocks" property (above).
+		  Should be "smmu_pclk" for specifying the interface clock
+		  required for iommu's register accesses.
+		  Should be "smmu_clk" for specifying the functional clock
+		  required by iommu for bus accesses.
+
+Each bus master connected to an IOMMU must reference the IOMMU in its device
+node with the following property:
+
+  - iommus: A reference to the IOMMU in multiple cells. The first cell is a
+	    phandle to the IOMMU and the second cell is the stream id.
+	    A single master device can be connected to more than one iommu
+	    and multiple contexts in each of the iommu. So multiple entries
+	    are required to list all the iommus and the stream ids that the
+	    master is connected to.
+
+Example: mdp iommu and its bus master
+
+                mdp_port0: iommu at 7500000 {
+			compatible = "qcom,apq8064-iommu";
+			#iommu-cells = <1>;
+			clock-names =
+			    "smmu_pclk",
+			    "smmu_clk";
+			clocks =
+			    <&mmcc SMMU_AHB_CLK>,
+			    <&mmcc MDP_AXI_CLK>;
+			reg = <0x07500000 0x100000>;
+			interrupts =
+			    <GIC_SPI 63 0>,
+			    <GIC_SPI 64 0>;
+			qcom,ncb = <2>;
+		};
+
+		mdp: qcom,mdp at 5100000 {
+			compatible = "qcom,mdp";
+			...
+			iommus = <&mdp_port0 0
+				  &mdp_port0 2>;
+		};
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Fri May 20 03:54:50 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Fri, 20 May 2016 16:24:50 +0530
Subject: [PATCH V5 3/7] iommu/msm: Move the contents from msm_iommu_dev.c to
 msm_iommu.c
In-Reply-To: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463741694-1735-4-git-send-email-sricharan@codeaurora.org>

There are only two functions left in msm_iommu_dev.c. Move it to
msm_iommu.c and delete the file.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/Makefile        |   2 +-
 drivers/iommu/msm_iommu.c     | 182 ++++++++++++++++++++++++++++++++++++
 drivers/iommu/msm_iommu_dev.c | 212 ------------------------------------------
 3 files changed, 183 insertions(+), 213 deletions(-)
 delete mode 100644 drivers/iommu/msm_iommu_dev.c

diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index f7134f7..8695ead 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU)	+= of_iommu.o
-obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
+obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
 obj-$(CONFIG_QCOM_IOMMU_V1) += qcom/
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index bc1a4e3..792b352 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/iommu.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
@@ -85,6 +86,47 @@ static void __disable_clocks(struct msm_iommu_dev *iommu)
 	clk_disable(iommu->pclk);
 }
 
+static void msm_iommu_reset(void __iomem *base, int ncb)
+{
+	int ctx;
+
+	SET_RPUE(base, 0);
+	SET_RPUEIE(base, 0);
+	SET_ESRRESTORE(base, 0);
+	SET_TBE(base, 0);
+	SET_CR(base, 0);
+	SET_SPDMBE(base, 0);
+	SET_TESTBUSCR(base, 0);
+	SET_TLBRSW(base, 0);
+	SET_GLOBAL_TLBIALL(base, 0);
+	SET_RPU_ACR(base, 0);
+	SET_TLBLKCRWE(base, 1);
+
+	for (ctx = 0; ctx < ncb; ctx++) {
+		SET_BPRCOSH(base, ctx, 0);
+		SET_BPRCISH(base, ctx, 0);
+		SET_BPRCNSH(base, ctx, 0);
+		SET_BPSHCFG(base, ctx, 0);
+		SET_BPMTCFG(base, ctx, 0);
+		SET_ACTLR(base, ctx, 0);
+		SET_SCTLR(base, ctx, 0);
+		SET_FSRRESTORE(base, ctx, 0);
+		SET_TTBR0(base, ctx, 0);
+		SET_TTBR1(base, ctx, 0);
+		SET_TTBCR(base, ctx, 0);
+		SET_BFBCR(base, ctx, 0);
+		SET_PAR(base, ctx, 0);
+		SET_FAR(base, ctx, 0);
+		SET_CTX_TLBIALL(base, ctx, 0);
+		SET_TLBFLPTER(base, ctx, 0);
+		SET_TLBSLPTER(base, ctx, 0);
+		SET_TLBLKCR(base, ctx, 0);
+		SET_PRRR(base, ctx, 0);
+		SET_NMRR(base, ctx, 0);
+		SET_CONTEXTIDR(base, ctx, 0);
+	}
+}
+
 static int __flush_iotlb(struct iommu_domain *domain)
 {
 	struct msm_priv *priv = to_msm_priv(domain);
@@ -708,6 +750,146 @@ static const struct iommu_ops msm_iommu_ops = {
 	.pgsize_bitmap = MSM_IOMMU_PGSIZES,
 };
 
+static int msm_iommu_probe(struct platform_device *pdev)
+{
+	struct resource *r;
+	struct msm_iommu_dev *iommu;
+	int ret, par, val;
+
+	iommu = devm_kzalloc(&pdev->dev, sizeof(*iommu), GFP_KERNEL);
+	if (!iommu)
+		return -ENODEV;
+
+	iommu->dev = &pdev->dev;
+	INIT_LIST_HEAD(&iommu->ctx_list);
+
+	iommu->pclk = devm_clk_get(iommu->dev, "smmu_pclk");
+	if (IS_ERR(iommu->pclk)) {
+		dev_err(iommu->dev, "could not get smmu_pclk\n");
+		return PTR_ERR(iommu->pclk);
+	}
+
+	ret = clk_prepare(iommu->pclk);
+	if (ret) {
+		dev_err(iommu->dev, "could not prepare smmu_pclk\n");
+		return ret;
+	}
+
+	iommu->clk = devm_clk_get(iommu->dev, "iommu_clk");
+	if (IS_ERR(iommu->clk)) {
+		dev_err(iommu->dev, "could not get iommu_clk\n");
+		clk_unprepare(iommu->pclk);
+		return PTR_ERR(iommu->clk);
+	}
+
+	ret = clk_prepare(iommu->clk);
+	if (ret) {
+		dev_err(iommu->dev, "could not prepare iommu_clk\n");
+		clk_unprepare(iommu->pclk);
+		return ret;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	iommu->base = devm_ioremap_resource(iommu->dev, r);
+	if (IS_ERR(iommu->base)) {
+		dev_err(iommu->dev, "could not get iommu base\n");
+		ret = PTR_ERR(iommu->base);
+		goto fail;
+	}
+
+	iommu->irq = platform_get_irq(pdev, 0);
+	if (iommu->irq < 0) {
+		dev_err(iommu->dev, "could not get iommu irq\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	ret = of_property_read_u32(iommu->dev->of_node, "qcom,ncb", &val);
+	if (ret) {
+		dev_err(iommu->dev, "could not get ncb\n");
+		goto fail;
+	}
+	iommu->ncb = val;
+
+	msm_iommu_reset(iommu->base, iommu->ncb);
+	SET_M(iommu->base, 0, 1);
+	SET_PAR(iommu->base, 0, 0);
+	SET_V2PCFG(iommu->base, 0, 1);
+	SET_V2PPR(iommu->base, 0, 0);
+	par = GET_PAR(iommu->base, 0);
+	SET_V2PCFG(iommu->base, 0, 0);
+	SET_M(iommu->base, 0, 0);
+
+	if (!par) {
+		pr_err("Invalid PAR value detected\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	ret = devm_request_threaded_irq(iommu->dev, iommu->irq, NULL,
+					msm_iommu_fault_handler,
+					IRQF_ONESHOT | IRQF_SHARED,
+					"msm_iommu_secure_irpt_handler",
+					iommu);
+	if (ret) {
+		pr_err("Request IRQ %d failed with ret=%d\n", iommu->irq, ret);
+		goto fail;
+	}
+
+	list_add(&iommu->dev_node, &qcom_iommu_devices);
+
+	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
+		iommu->base, iommu->irq, iommu->ncb);
+
+	return ret;
+fail:
+	clk_unprepare(iommu->clk);
+	clk_unprepare(iommu->pclk);
+	return ret;
+}
+
+static const struct of_device_id msm_iommu_dt_match[] = {
+	{ .compatible = "qcom,apq8064-iommu" },
+	{}
+};
+
+static int msm_iommu_remove(struct platform_device *pdev)
+{
+	struct msm_iommu_dev *iommu = platform_get_drvdata(pdev);
+
+	clk_unprepare(iommu->clk);
+	clk_unprepare(iommu->pclk);
+	return 0;
+}
+
+static struct platform_driver msm_iommu_driver = {
+	.driver = {
+		.name	= "msm_iommu",
+		.of_match_table = msm_iommu_dt_match,
+	},
+	.probe		= msm_iommu_probe,
+	.remove		= msm_iommu_remove,
+};
+
+static int __init msm_iommu_driver_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&msm_iommu_driver);
+	if (ret != 0)
+		pr_err("Failed to register IOMMU driver\n");
+
+	return ret;
+}
+
+static void __exit msm_iommu_driver_exit(void)
+{
+	platform_driver_unregister(&msm_iommu_driver);
+}
+
+subsys_initcall(msm_iommu_driver_init);
+module_exit(msm_iommu_driver_exit);
+
 static int __init get_tex_class(int icp, int ocp, int mt, int nos)
 {
 	int i = 0;
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
deleted file mode 100644
index be01cc4..0000000
--- a/drivers/iommu/msm_iommu_dev.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/iommu.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-#include "msm_iommu_hw-8xxx.h"
-#include "msm_iommu.h"
-
-static void msm_iommu_reset(void __iomem *base, int ncb)
-{
-	int ctx;
-
-	SET_RPUE(base, 0);
-	SET_RPUEIE(base, 0);
-	SET_ESRRESTORE(base, 0);
-	SET_TBE(base, 0);
-	SET_CR(base, 0);
-	SET_SPDMBE(base, 0);
-	SET_TESTBUSCR(base, 0);
-	SET_TLBRSW(base, 0);
-	SET_GLOBAL_TLBIALL(base, 0);
-	SET_RPU_ACR(base, 0);
-	SET_TLBLKCRWE(base, 1);
-
-	for (ctx = 0; ctx < ncb; ctx++) {
-		SET_BPRCOSH(base, ctx, 0);
-		SET_BPRCISH(base, ctx, 0);
-		SET_BPRCNSH(base, ctx, 0);
-		SET_BPSHCFG(base, ctx, 0);
-		SET_BPMTCFG(base, ctx, 0);
-		SET_ACTLR(base, ctx, 0);
-		SET_SCTLR(base, ctx, 0);
-		SET_FSRRESTORE(base, ctx, 0);
-		SET_TTBR0(base, ctx, 0);
-		SET_TTBR1(base, ctx, 0);
-		SET_TTBCR(base, ctx, 0);
-		SET_BFBCR(base, ctx, 0);
-		SET_PAR(base, ctx, 0);
-		SET_FAR(base, ctx, 0);
-		SET_CTX_TLBIALL(base, ctx, 0);
-		SET_TLBFLPTER(base, ctx, 0);
-		SET_TLBSLPTER(base, ctx, 0);
-		SET_TLBLKCR(base, ctx, 0);
-		SET_PRRR(base, ctx, 0);
-		SET_NMRR(base, ctx, 0);
-		SET_CONTEXTIDR(base, ctx, 0);
-	}
-}
-
-static int msm_iommu_probe(struct platform_device *pdev)
-{
-	struct resource *r;
-	struct msm_iommu_dev *iommu;
-	int ret, par, val;
-
-	iommu = devm_kzalloc(&pdev->dev, sizeof(*iommu), GFP_KERNEL);
-	if (!iommu)
-		return -ENODEV;
-
-	iommu->dev = &pdev->dev;
-	INIT_LIST_HEAD(&iommu->ctx_list);
-
-	iommu->pclk = devm_clk_get(iommu->dev, "smmu_pclk");
-	if (IS_ERR(iommu->pclk)) {
-		dev_err(iommu->dev, "could not get smmu_pclk\n");
-		return PTR_ERR(iommu->pclk);
-	}
-
-	ret = clk_prepare(iommu->pclk);
-	if (ret) {
-		dev_err(iommu->dev, "could not prepare smmu_pclk\n");
-		return ret;
-	}
-
-	iommu->clk = devm_clk_get(iommu->dev, "iommu_clk");
-	if (IS_ERR(iommu->clk)) {
-		dev_err(iommu->dev, "could not get iommu_clk\n");
-		clk_unprepare(iommu->pclk);
-		return PTR_ERR(iommu->clk);
-	}
-
-	ret = clk_prepare(iommu->clk);
-	if (ret) {
-		dev_err(iommu->dev, "could not prepare iommu_clk\n");
-		clk_unprepare(iommu->pclk);
-		return ret;
-	}
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	iommu->base = devm_ioremap_resource(iommu->dev, r);
-	if (IS_ERR(iommu->base)) {
-		dev_err(iommu->dev, "could not get iommu base\n");
-		ret = PTR_ERR(iommu->base);
-		goto fail;
-	}
-
-	iommu->irq = platform_get_irq(pdev, 0);
-	if (iommu->irq < 0) {
-		dev_err(iommu->dev, "could not get iommu irq\n");
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	ret = of_property_read_u32(iommu->dev->of_node, "ncb", &val);
-	if (ret) {
-		dev_err(iommu->dev, "could not get ncb\n");
-		goto fail;
-	}
-	iommu->ncb = val;
-
-	msm_iommu_reset(iommu->base, iommu->ncb);
-	SET_M(iommu->base, 0, 1);
-	SET_PAR(iommu->base, 0, 0);
-	SET_V2PCFG(iommu->base, 0, 1);
-	SET_V2PPR(iommu->base, 0, 0);
-	par = GET_PAR(iommu->base, 0);
-	SET_V2PCFG(iommu->base, 0, 0);
-	SET_M(iommu->base, 0, 0);
-
-	if (!par) {
-		pr_err("Invalid PAR value detected\n");
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	ret = devm_request_threaded_irq(iommu->dev, iommu->irq, NULL,
-					msm_iommu_fault_handler,
-					IRQF_ONESHOT | IRQF_SHARED,
-					"msm_iommu_secure_irpt_handler",
-					iommu);
-	if (ret) {
-		pr_err("Request IRQ %d failed with ret=%d\n", iommu->irq, ret);
-		goto fail;
-	}
-
-	list_add(&iommu->dev_node, &qcom_iommu_devices);
-
-	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
-		iommu->base, iommu->irq, iommu->ncb);
-fail:
-	clk_unprepare(iommu->clk);
-	clk_unprepare(iommu->pclk);
-	return ret;
-}
-
-static const struct of_device_id msm_iommu_dt_match[] = {
-	{ .compatible = "qcom,apq8064-iommu" },
-	{}
-};
-
-static int msm_iommu_remove(struct platform_device *pdev)
-{
-	struct msm_iommu_dev *iommu = platform_get_drvdata(pdev);
-
-	clk_unprepare(iommu->clk);
-	clk_unprepare(iommu->pclk);
-	return 0;
-}
-
-static struct platform_driver msm_iommu_driver = {
-	.driver = {
-		.name	= "msm_iommu",
-		.of_match_table = msm_iommu_dt_match,
-	},
-	.probe		= msm_iommu_probe,
-	.remove		= msm_iommu_remove,
-};
-
-static struct platform_driver * const drivers[] = {
-	&msm_iommu_driver,
-	&msm_iommu_ctx_driver,
-};
-
-static int __init msm_iommu_driver_init(void)
-{
-	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
-}
-
-static void __exit msm_iommu_driver_exit(void)
-{
-	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
-}
-
-subsys_initcall(msm_iommu_driver_init);
-module_exit(msm_iommu_driver_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Stepan Moskovchenko <stepanm at codeaurora.org>");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Fri May 20 03:54:51 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Fri, 20 May 2016 16:24:51 +0530
Subject: [PATCH V5 4/7] iommu/msm: Add support for generic master bindings
In-Reply-To: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463741694-1735-5-git-send-email-sricharan@codeaurora.org>

This adds the xlate callback which gets invoked during
device registration from DT. The master devices gets added
through this.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/msm_iommu.c | 61 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 59 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 792b352..8ab0643 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -28,6 +28,7 @@
 #include <linux/iommu.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/of_iommu.h>
 
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
@@ -702,6 +703,54 @@ static void print_ctx_regs(void __iomem *base, int ctx)
 	       GET_PRRR(base, ctx), GET_NMRR(base, ctx));
 }
 
+static void insert_iommu_master(struct device *dev,
+				struct msm_iommu_dev **iommu,
+				struct of_phandle_args *spec)
+{
+	struct msm_iommu_ctx_dev *master = dev->archdata.iommu;
+	int sid;
+
+	if (list_empty(&(*iommu)->ctx_list)) {
+		master = kzalloc(sizeof(*master), GFP_ATOMIC);
+		master->of_node = dev->of_node;
+		list_add(&master->list, &(*iommu)->ctx_list);
+		dev->archdata.iommu = master;
+	}
+
+	for (sid = 0; sid < master->num_mids; sid++)
+		if (master->mids[sid] == spec->args[0]) {
+			dev_warn(dev, "Stream ID 0x%hx repeated; ignoring\n",
+				 sid);
+			return;
+		}
+
+	master->mids[master->num_mids++] = spec->args[0];
+}
+
+static int qcom_iommu_of_xlate(struct device *dev,
+			       struct of_phandle_args *spec)
+{
+	struct msm_iommu_dev *iommu;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&msm_iommu_lock, flags);
+	list_for_each_entry(iommu, &qcom_iommu_devices, dev_node)
+		if (iommu->dev->of_node == spec->np)
+			break;
+
+	if (!iommu || iommu->dev->of_node != spec->np) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	insert_iommu_master(dev, &iommu, spec);
+fail:
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+
+	return ret;
+}
+
 irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 {
 	struct msm_iommu_dev *iommu = dev_id;
@@ -737,7 +786,7 @@ fail:
 	return 0;
 }
 
-static const struct iommu_ops msm_iommu_ops = {
+static struct iommu_ops msm_iommu_ops = {
 	.capable = msm_iommu_capable,
 	.domain_alloc = msm_iommu_domain_alloc,
 	.domain_free = msm_iommu_domain_free,
@@ -748,6 +797,7 @@ static const struct iommu_ops msm_iommu_ops = {
 	.map_sg = default_iommu_map_sg,
 	.iova_to_phys = msm_iommu_iova_to_phys,
 	.pgsize_bitmap = MSM_IOMMU_PGSIZES,
+	.of_xlate = qcom_iommu_of_xlate,
 };
 
 static int msm_iommu_probe(struct platform_device *pdev)
@@ -837,6 +887,7 @@ static int msm_iommu_probe(struct platform_device *pdev)
 	}
 
 	list_add(&iommu->dev_node, &qcom_iommu_devices);
+	of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops);
 
 	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
 		iommu->base, iommu->irq, iommu->ncb);
@@ -935,7 +986,13 @@ static int __init msm_iommu_init(void)
 	return 0;
 }
 
-subsys_initcall(msm_iommu_init);
+static int __init msm_iommu_of_setup(struct device_node *np)
+{
+	msm_iommu_init();
+	return 0;
+}
+
+IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", msm_iommu_of_setup);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Stepan Moskovchenko <stepanm at codeaurora.org>");
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Fri May 20 03:54:52 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Fri, 20 May 2016 16:24:52 +0530
Subject: [PATCH V5 5/7] iommu/msm: use generic ARMV7S short descriptor
 pagetable ops
In-Reply-To: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463741694-1735-6-git-send-email-sricharan@codeaurora.org>

This iommu uses the armv7 short descriptor format. So use the
generic ARMV7S pagetable ops instead of rewriting the same stuff
in the driver.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/Kconfig     |   1 +
 drivers/iommu/msm_iommu.c | 400 ++++++++++++----------------------------------
 2 files changed, 104 insertions(+), 297 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 232a54a..761be35 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -92,6 +92,7 @@ config MSM_IOMMU
 	depends on ARCH_MSM8X60 || ARCH_MSM8960 || COMPILE_TEST
 	depends on BROKEN
 	select IOMMU_API
+	select IOMMU_IO_PGTABLE_ARMV7S
 	help
 	  Support for the IOMMUs found on certain Qualcomm SOCs.
 	  These IOMMUs allow virtualization of the address space used by most
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 8ab0643..0299a37 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -35,27 +35,27 @@
 
 #include "msm_iommu_hw-8xxx.h"
 #include "msm_iommu.h"
+#include "io-pgtable.h"
 
 #define MRC(reg, processor, op1, crn, crm, op2)				\
 __asm__ __volatile__ (							\
 "   mrc   "   #processor "," #op1 ", %0,"  #crn "," #crm "," #op2 "\n"  \
 : "=r" (reg))
 
-#define RCP15_PRRR(reg)		MRC(reg, p15, 0, c10, c2, 0)
-#define RCP15_NMRR(reg)		MRC(reg, p15, 0, c10, c2, 1)
-
 /* bitmap of the page sizes currently supported */
 #define MSM_IOMMU_PGSIZES	(SZ_4K | SZ_64K | SZ_1M | SZ_16M)
 
-static int msm_iommu_tex_class[4];
-
 DEFINE_SPINLOCK(msm_iommu_lock);
 static LIST_HEAD(qcom_iommu_devices);
+static struct iommu_ops msm_iommu_ops;
 
 struct msm_priv {
-	unsigned long *pgtable;
 	struct list_head list_attached;
 	struct iommu_domain domain;
+	struct io_pgtable_cfg	cfg;
+	struct io_pgtable_ops	*iop;
+	struct device		*dev;
+	spinlock_t		pgtlock; /* pagetable lock */
 };
 
 static struct msm_priv *to_msm_priv(struct iommu_domain *dom)
@@ -122,49 +122,74 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
 		SET_TLBFLPTER(base, ctx, 0);
 		SET_TLBSLPTER(base, ctx, 0);
 		SET_TLBLKCR(base, ctx, 0);
-		SET_PRRR(base, ctx, 0);
-		SET_NMRR(base, ctx, 0);
 		SET_CONTEXTIDR(base, ctx, 0);
 	}
 }
 
-static int __flush_iotlb(struct iommu_domain *domain)
+static void __flush_iotlb(void *cookie)
 {
-	struct msm_priv *priv = to_msm_priv(domain);
+	struct msm_priv *priv = cookie;
 	struct msm_iommu_dev *iommu = NULL;
 	struct msm_iommu_ctx_dev *master;
 	int ret = 0;
 
-#ifndef CONFIG_IOMMU_PGTABLES_L2
-	unsigned long *fl_table = priv->pgtable;
-	int i;
+	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
+		ret = __enable_clocks(iommu);
+		if (ret)
+			goto fail;
 
-	if (!list_empty(&priv->list_attached)) {
-		dmac_flush_range(fl_table, fl_table + SZ_16K);
+		list_for_each_entry(master, &iommu->ctx_list, list)
+			SET_CTX_TLBIALL(iommu->base, master->num, 0);
 
-		for (i = 0; i < NUM_FL_PTE; i++)
-			if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) {
-				void *sl_table = __va(fl_table[i] &
-								FL_BASE_MASK);
-				dmac_flush_range(sl_table, sl_table + SZ_4K);
-			}
+		__disable_clocks(iommu);
 	}
-#endif
+fail:
+	return;
+}
+
+static void __flush_iotlb_range(unsigned long iova, size_t size,
+				size_t granule, bool leaf, void *cookie)
+{
+	struct msm_priv *priv = cookie;
+	struct msm_iommu_dev *iommu = NULL;
+	struct msm_iommu_ctx_dev *master;
+	int ret = 0;
+	int temp_size;
 
 	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
 		ret = __enable_clocks(iommu);
 		if (ret)
 			goto fail;
 
-		list_for_each_entry(master, &iommu->ctx_list, list)
-			SET_CTX_TLBIALL(iommu->base, master->num, 0);
+		list_for_each_entry(master, &iommu->ctx_list, list) {
+			temp_size = size;
+			do {
+				iova &= TLBIVA_VA;
+				iova |= GET_CONTEXTIDR_ASID(iommu->base,
+							    master->num);
+				SET_TLBIVA(iommu->base, master->num, iova);
+				iova += granule;
+			} while (temp_size -= granule);
+		}
 
 		__disable_clocks(iommu);
 	}
+
 fail:
-	return ret;
+	return;
+}
+
+static void __flush_iotlb_sync(void *cookie)
+{
+	/* To avoid a null function pointer */
 }
 
+static const struct iommu_gather_ops msm_iommu_gather_ops = {
+	.tlb_flush_all = __flush_iotlb,
+	.tlb_add_flush = __flush_iotlb_range,
+	.tlb_sync = __flush_iotlb_sync,
+};
+
 static int msm_iommu_alloc_ctx(unsigned long *map, int start, int end)
 {
 	int idx;
@@ -232,15 +257,17 @@ static void __reset_context(void __iomem *base, int ctx)
 	SET_TLBFLPTER(base, ctx, 0);
 	SET_TLBSLPTER(base, ctx, 0);
 	SET_TLBLKCR(base, ctx, 0);
-	SET_PRRR(base, ctx, 0);
-	SET_NMRR(base, ctx, 0);
 }
 
-static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
+static void __program_context(void __iomem *base, int ctx,
+			      struct msm_priv *priv)
 {
-	unsigned int prrr, nmrr;
 	__reset_context(base, ctx);
 
+	/* Turn on TEX Remap */
+	SET_TRE(base, ctx, 1);
+	SET_AFE(base, ctx, 1);
+
 	/* Set up HTW mode */
 	/* TLB miss configuration: perform HTW on miss */
 	SET_TLBMCFG(base, ctx, 0x3);
@@ -248,8 +275,13 @@ static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
 	/* V2P configuration: HTW for access */
 	SET_V2PCFG(base, ctx, 0x3);
 
-	SET_TTBCR(base, ctx, 0);
-	SET_TTBR0_PA(base, ctx, (pgtable >> 14));
+	SET_TTBCR(base, ctx, priv->cfg.arm_v7s_cfg.tcr);
+	SET_TTBR0(base, ctx, priv->cfg.arm_v7s_cfg.ttbr[0]);
+	SET_TTBR1(base, ctx, priv->cfg.arm_v7s_cfg.ttbr[1]);
+
+	/* Set prrr and nmrr */
+	SET_PRRR(base, ctx, priv->cfg.arm_v7s_cfg.prrr);
+	SET_NMRR(base, ctx, priv->cfg.arm_v7s_cfg.nmrr);
 
 	/* Invalidate the TLB for this context */
 	SET_CTX_TLBIALL(base, ctx, 0);
@@ -268,38 +300,9 @@ static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
 	SET_RCOSH(base, ctx, 1);
 	SET_RCNSH(base, ctx, 1);
 
-	/* Turn on TEX Remap */
-	SET_TRE(base, ctx, 1);
-
-	/* Set TEX remap attributes */
-	RCP15_PRRR(prrr);
-	RCP15_NMRR(nmrr);
-	SET_PRRR(base, ctx, prrr);
-	SET_NMRR(base, ctx, nmrr);
-
 	/* Turn on BFB prefetch */
 	SET_BFBDFE(base, ctx, 1);
 
-#ifdef CONFIG_IOMMU_PGTABLES_L2
-	/* Configure page tables as inner-cacheable and shareable to reduce
-	 * the TLB miss penalty.
-	 */
-	SET_TTBR0_SH(base, ctx, 1);
-	SET_TTBR1_SH(base, ctx, 1);
-
-	SET_TTBR0_NOS(base, ctx, 1);
-	SET_TTBR1_NOS(base, ctx, 1);
-
-	SET_TTBR0_IRGNH(base, ctx, 0); /* WB, WA */
-	SET_TTBR0_IRGNL(base, ctx, 1);
-
-	SET_TTBR1_IRGNH(base, ctx, 0); /* WB, WA */
-	SET_TTBR1_IRGNL(base, ctx, 1);
-
-	SET_TTBR0_ORGN(base, ctx, 1); /* WB, WA */
-	SET_TTBR1_ORGN(base, ctx, 1); /* WB, WA */
-#endif
-
 	/* Enable the MMU */
 	SET_M(base, ctx, 1);
 }
@@ -316,13 +319,6 @@ static struct iommu_domain *msm_iommu_domain_alloc(unsigned type)
 		goto fail_nomem;
 
 	INIT_LIST_HEAD(&priv->list_attached);
-	priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL,
-							  get_order(SZ_16K));
-
-	if (!priv->pgtable)
-		goto fail_nomem;
-
-	memset(priv->pgtable, 0, SZ_16K);
 
 	priv->domain.geometry.aperture_start = 0;
 	priv->domain.geometry.aperture_end   = (1ULL << 32) - 1;
@@ -339,24 +335,35 @@ static void msm_iommu_domain_free(struct iommu_domain *domain)
 {
 	struct msm_priv *priv;
 	unsigned long flags;
-	unsigned long *fl_table;
-	int i;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
 	priv = to_msm_priv(domain);
+	kfree(priv);
+	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+}
 
-	fl_table = priv->pgtable;
+static int msm_iommu_domain_config(struct msm_priv *priv)
+{
+	spin_lock_init(&priv->pgtlock);
 
-	for (i = 0; i < NUM_FL_PTE; i++)
-		if ((fl_table[i] & 0x03) == FL_TYPE_TABLE)
-			free_page((unsigned long) __va(((fl_table[i]) &
-							FL_BASE_MASK)));
+	priv->cfg = (struct io_pgtable_cfg) {
+		.quirks = IO_PGTABLE_QUIRK_TLBI_ON_MAP,
+		.pgsize_bitmap = msm_iommu_ops.pgsize_bitmap,
+		.ias = 32,
+		.oas = 32,
+		.tlb = &msm_iommu_gather_ops,
+		.iommu_dev = priv->dev,
+	};
 
-	free_pages((unsigned long)priv->pgtable, get_order(SZ_16K));
-	priv->pgtable = NULL;
+	priv->iop = alloc_io_pgtable_ops(ARM_V7S, &priv->cfg, priv);
+	if (!priv->iop) {
+		dev_err(priv->dev, "Failed to allocate pgtable\n");
+		return -EINVAL;
+	}
 
-	kfree(priv);
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
+	msm_iommu_ops.pgsize_bitmap = priv->cfg.pgsize_bitmap;
+
+	return 0;
 }
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -367,6 +374,9 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 	struct msm_priv *priv = to_msm_priv(domain);
 	struct msm_iommu_ctx_dev *master;
 
+	priv->dev = dev;
+	msm_iommu_domain_config(priv);
+
 	spin_lock_irqsave(&msm_iommu_lock, flags);
 	list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) {
 		master = list_first_entry(&iommu->ctx_list,
@@ -392,14 +402,13 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 					}
 				config_mids(iommu, master);
 				__program_context(iommu->base, master->num,
-						  __pa(priv->pgtable));
+						  priv);
 			}
 			__disable_clocks(iommu);
 			list_add(&iommu->dom_node, &priv->list_attached);
 		}
 	}
 
-	ret = __flush_iotlb(domain);
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 
@@ -415,11 +424,9 @@ static void msm_iommu_detach_dev(struct iommu_domain *domain,
 	struct msm_iommu_ctx_dev *master;
 	int ret;
 
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-	ret = __flush_iotlb(domain);
-	if (ret)
-		goto fail;
+	free_io_pgtable_ops(priv->iop);
 
+	spin_lock_irqsave(&msm_iommu_lock, flags);
 	list_for_each_entry(iommu, &priv->list_attached, dom_node) {
 		ret = __enable_clocks(iommu);
 		if (ret)
@@ -435,190 +442,30 @@ fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 }
 
-static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
+static int msm_iommu_map(struct iommu_domain *domain, unsigned long iova,
 			 phys_addr_t pa, size_t len, int prot)
 {
-	struct msm_priv *priv;
+	struct msm_priv *priv = to_msm_priv(domain);
 	unsigned long flags;
-	unsigned long *fl_table;
-	unsigned long *fl_pte;
-	unsigned long fl_offset;
-	unsigned long *sl_table;
-	unsigned long *sl_pte;
-	unsigned long sl_offset;
-	unsigned int pgprot;
-	int ret = 0, tex, sh;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	sh = (prot & MSM_IOMMU_ATTR_SH) ? 1 : 0;
-	tex = msm_iommu_tex_class[prot & MSM_IOMMU_CP_MASK];
-
-	if (tex < 0 || tex > NUM_TEX_CLASS - 1) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	priv = to_msm_priv(domain);
-
-	fl_table = priv->pgtable;
-
-	if (len != SZ_16M && len != SZ_1M &&
-	    len != SZ_64K && len != SZ_4K) {
-		pr_debug("Bad size: %d\n", len);
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (!fl_table) {
-		pr_debug("Null page table\n");
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	if (len == SZ_16M || len == SZ_1M) {
-		pgprot = sh ? FL_SHARED : 0;
-		pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0;
-		pgprot |= tex & 0x02 ? FL_CACHEABLE : 0;
-		pgprot |= tex & 0x04 ? FL_TEX0 : 0;
-	} else	{
-		pgprot = sh ? SL_SHARED : 0;
-		pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0;
-		pgprot |= tex & 0x02 ? SL_CACHEABLE : 0;
-		pgprot |= tex & 0x04 ? SL_TEX0 : 0;
-	}
-
-	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
-	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
-
-	if (len == SZ_16M) {
-		int i = 0;
-		for (i = 0; i < 16; i++)
-			*(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
-				  FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
-				  FL_SHARED | FL_NG | pgprot;
-	}
-
-	if (len == SZ_1M)
-		*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE | FL_NG |
-					    FL_TYPE_SECT | FL_SHARED | pgprot;
-
-	/* Need a 2nd level table */
-	if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) {
-		unsigned long *sl;
-		sl = (unsigned long *) __get_free_pages(GFP_ATOMIC,
-							get_order(SZ_4K));
-
-		if (!sl) {
-			pr_debug("Could not allocate second level table\n");
-			ret = -ENOMEM;
-			goto fail;
-		}
-
-		memset(sl, 0, SZ_4K);
-		*fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | FL_TYPE_TABLE);
-	}
-
-	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
-	sl_offset = SL_OFFSET(va);
-	sl_pte = sl_table + sl_offset;
-
-
-	if (len == SZ_4K)
-		*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | SL_NG |
-					  SL_SHARED | SL_TYPE_SMALL | pgprot;
-
-	if (len == SZ_64K) {
-		int i;
+	int ret;
 
-		for (i = 0; i < 16; i++)
-			*(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
-			    SL_NG | SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
-	}
+	spin_lock_irqsave(&priv->pgtlock, flags);
+	ret = priv->iop->map(priv->iop, iova, pa, len, prot);
+	spin_unlock_irqrestore(&priv->pgtlock, flags);
 
-	ret = __flush_iotlb(domain);
-fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
 }
 
-static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
-			    size_t len)
+static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
+			      size_t len)
 {
-	struct msm_priv *priv;
+	struct msm_priv *priv = to_msm_priv(domain);
 	unsigned long flags;
-	unsigned long *fl_table;
-	unsigned long *fl_pte;
-	unsigned long fl_offset;
-	unsigned long *sl_table;
-	unsigned long *sl_pte;
-	unsigned long sl_offset;
-	int i, ret = 0;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-
-	priv = to_msm_priv(domain);
 
-	fl_table = priv->pgtable;
+	spin_lock_irqsave(&priv->pgtlock, flags);
+	len = priv->iop->unmap(priv->iop, iova, len);
+	spin_unlock_irqrestore(&priv->pgtlock, flags);
 
-	if (len != SZ_16M && len != SZ_1M &&
-	    len != SZ_64K && len != SZ_4K) {
-		pr_debug("Bad length: %d\n", len);
-		goto fail;
-	}
-
-	if (!fl_table) {
-		pr_debug("Null page table\n");
-		goto fail;
-	}
-
-	fl_offset = FL_OFFSET(va);	/* Upper 12 bits */
-	fl_pte = fl_table + fl_offset;	/* int pointers, 4 bytes */
-
-	if (*fl_pte == 0) {
-		pr_debug("First level PTE is 0\n");
-		goto fail;
-	}
-
-	/* Unmap supersection */
-	if (len == SZ_16M)
-		for (i = 0; i < 16; i++)
-			*(fl_pte+i) = 0;
-
-	if (len == SZ_1M)
-		*fl_pte = 0;
-
-	sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
-	sl_offset = SL_OFFSET(va);
-	sl_pte = sl_table + sl_offset;
-
-	if (len == SZ_64K) {
-		for (i = 0; i < 16; i++)
-			*(sl_pte+i) = 0;
-	}
-
-	if (len == SZ_4K)
-		*sl_pte = 0;
-
-	if (len == SZ_4K || len == SZ_64K) {
-		int used = 0;
-
-		for (i = 0; i < NUM_SL_PTE; i++)
-			if (sl_table[i])
-				used = 1;
-		if (!used) {
-			free_page((unsigned long)sl_table);
-			*fl_pte = 0;
-		}
-	}
-
-	ret = __flush_iotlb(domain);
-
-fail:
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
-
-	/* the IOMMU API requires us to return how many bytes were unmapped */
-	len = ret ? 0 : len;
 	return len;
 }
 
@@ -699,8 +546,6 @@ static void print_ctx_regs(void __iomem *base, int ctx)
 	       GET_TTBR0(base, ctx), GET_TTBR1(base, ctx));
 	pr_err("SCTLR  = %08x    ACTLR  = %08x\n",
 	       GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
-	pr_err("PRRR   = %08x    NMRR   = %08x\n",
-	       GET_PRRR(base, ctx), GET_NMRR(base, ctx));
 }
 
 static void insert_iommu_master(struct device *dev,
@@ -941,47 +786,8 @@ static void __exit msm_iommu_driver_exit(void)
 subsys_initcall(msm_iommu_driver_init);
 module_exit(msm_iommu_driver_exit);
 
-static int __init get_tex_class(int icp, int ocp, int mt, int nos)
-{
-	int i = 0;
-	unsigned int prrr = 0;
-	unsigned int nmrr = 0;
-	int c_icp, c_ocp, c_mt, c_nos;
-
-	RCP15_PRRR(prrr);
-	RCP15_NMRR(nmrr);
-
-	for (i = 0; i < NUM_TEX_CLASS; i++) {
-		c_nos = PRRR_NOS(prrr, i);
-		c_mt = PRRR_MT(prrr, i);
-		c_icp = NMRR_ICP(nmrr, i);
-		c_ocp = NMRR_OCP(nmrr, i);
-
-		if (icp == c_icp && ocp == c_ocp && c_mt == mt && c_nos == nos)
-			return i;
-	}
-
-	return -ENODEV;
-}
-
-static void __init setup_iommu_tex_classes(void)
-{
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_NONCACHED] =
-			get_tex_class(CP_NONCACHED, CP_NONCACHED, MT_NORMAL, 1);
-
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_WA] =
-			get_tex_class(CP_WB_WA, CP_WB_WA, MT_NORMAL, 1);
-
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WB_NWA] =
-			get_tex_class(CP_WB_NWA, CP_WB_NWA, MT_NORMAL, 1);
-
-	msm_iommu_tex_class[MSM_IOMMU_ATTR_CACHED_WT] =
-			get_tex_class(CP_WT, CP_WT, MT_NORMAL, 1);
-}
-
 static int __init msm_iommu_init(void)
 {
-	setup_iommu_tex_classes();
 	bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
 	return 0;
 }
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Fri May 20 03:54:53 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Fri, 20 May 2016 16:24:53 +0530
Subject: [PATCH V5 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463741694-1735-7-git-send-email-sricharan@codeaurora.org>

While using the generic pagetable ops the tlb maintenance
operation gets completed in the sync callback. So use writel_relaxed
for all register access and add a mb() at appropriate places.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/msm_iommu.c         |  24 +++++++--
 drivers/iommu/msm_iommu_hw-8xxx.h | 109 ++++++++++++++++++++------------------
 2 files changed, 79 insertions(+), 54 deletions(-)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 0299a37..dfcaeef 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -124,6 +124,9 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
 		SET_TLBLKCR(base, ctx, 0);
 		SET_CONTEXTIDR(base, ctx, 0);
 	}
+
+	/* Ensure completion of relaxed writes from the above SET macros */
+	mb();
 }
 
 static void __flush_iotlb(void *cookie)
@@ -141,6 +144,9 @@ static void __flush_iotlb(void *cookie)
 		list_for_each_entry(master, &iommu->ctx_list, list)
 			SET_CTX_TLBIALL(iommu->base, master->num, 0);
 
+		/* To ensure completion of TLBIALL above */
+		mb();
+
 		__disable_clocks(iommu);
 	}
 fail:
@@ -181,7 +187,8 @@ fail:
 
 static void __flush_iotlb_sync(void *cookie)
 {
-	/* To avoid a null function pointer */
+	/* To ensure completion of the TLBIVA in __flush_iotlb_range */
+	mb();
 }
 
 static const struct iommu_gather_ops msm_iommu_gather_ops = {
@@ -235,6 +242,9 @@ static void config_mids(struct msm_iommu_dev *iommu,
 		/* Set security bit override to be Non-secure */
 		SET_NSCFG(iommu->base, mid, 3);
 	}
+
+	/* Ensure completion of relaxed writes from the above SET macros */
+	mb();
 }
 
 static void __reset_context(void __iomem *base, int ctx)
@@ -257,6 +267,9 @@ static void __reset_context(void __iomem *base, int ctx)
 	SET_TLBFLPTER(base, ctx, 0);
 	SET_TLBSLPTER(base, ctx, 0);
 	SET_TLBLKCR(base, ctx, 0);
+
+	/* Ensure completion of relaxed writes from the above SET macros */
+	mb();
 }
 
 static void __program_context(void __iomem *base, int ctx,
@@ -305,6 +318,9 @@ static void __program_context(void __iomem *base, int ctx,
 
 	/* Enable the MMU */
 	SET_M(base, ctx, 1);
+
+	/* Ensure completion of relaxed writes from the above SET macros */
+	mb();
 }
 
 static struct iommu_domain *msm_iommu_domain_alloc(unsigned type)
@@ -500,7 +516,8 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
 	/* Invalidate context TLB */
 	SET_CTX_TLBIALL(iommu->base, master->num, 0);
 	SET_V2PPR(iommu->base, master->num, va & V2Pxx_VA);
-
+	/* Ensure completion of relaxed writes from the above SET macros */
+	mb();
 	par = GET_PAR(iommu->base, master->num);
 
 	/* We are dealing with a supersection */
@@ -714,7 +731,8 @@ static int msm_iommu_probe(struct platform_device *pdev)
 	par = GET_PAR(iommu->base, 0);
 	SET_V2PCFG(iommu->base, 0, 0);
 	SET_M(iommu->base, 0, 0);
-
+	/* Ensure completion of relaxed writes from the above SET macros */
+	mb();
 	if (!par) {
 		pr_err("Invalid PAR value detected\n");
 		ret = -ENODEV;
diff --git a/drivers/iommu/msm_iommu_hw-8xxx.h b/drivers/iommu/msm_iommu_hw-8xxx.h
index fc16010..fe2c5ca 100644
--- a/drivers/iommu/msm_iommu_hw-8xxx.h
+++ b/drivers/iommu/msm_iommu_hw-8xxx.h
@@ -24,13 +24,19 @@
 #define GET_CTX_REG(reg, base, ctx) \
 				(readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
 
-#define SET_GLOBAL_REG(reg, base, val)	writel((val), ((base) + (reg)))
+/*
+ * The writes to the global/context registers needs to be synced only after
+ * all the configuration writes are done. So use relaxed accessors and
+ * a barrier at the end.
+ */
+#define SET_GLOBAL_REG_RELAXED(reg, base, val) \
+			       writel_relaxed((val), ((base) + (reg)))
 
-#define SET_CTX_REG(reg, base, ctx, val) \
-			writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
+#define SET_CTX_REG_RELAXED(reg, base, ctx, val) \
+		writel_relaxed((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
 
-/* Wrappers for numbered registers */
-#define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG(b, ((r) + (n << 2)), (v))
+ /* Wrappers for numbered registers */
+#define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG_RELAXED(b, ((r) + (n << 2)), (v))
 #define GET_GLOBAL_REG_N(b, n, r)    GET_GLOBAL_REG(b, ((r) + (n << 2)))
 
 /* Field wrappers */
@@ -39,16 +45,17 @@
 	GET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT)
 
 #define SET_GLOBAL_FIELD(b, r, F, v) \
-	SET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT, (v))
+	SET_FIELD_RELAXED(((b) + (r)), F##_MASK, F##_SHIFT, (v))
 #define SET_CONTEXT_FIELD(b, c, r, F, v)	\
-	SET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT, (v))
+	SET_FIELD_RELAXED(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT, (v))
 
 #define GET_FIELD(addr, mask, shift)  ((readl(addr) >> (shift)) & (mask))
 
-#define SET_FIELD(addr, mask, shift, v) \
+#define SET_FIELD_RELAXED(addr, mask, shift, v) \
 do { \
 	int t = readl(addr); \
-	writel((t & ~((mask) << (shift))) + (((v) & (mask)) << (shift)), addr);\
+	writel_relaxed((t & ~((mask) << (shift))) + \
+		       (((v) & (mask)) << (shift)), addr);\
 } while (0)
 
 
@@ -96,20 +103,20 @@ do { \
 /* Global register setters / getters */
 #define SET_M2VCBR_N(b, N, v)	 SET_GLOBAL_REG_N(M2VCBR_N, N, (b), (v))
 #define SET_CBACR_N(b, N, v)	 SET_GLOBAL_REG_N(CBACR_N, N, (b), (v))
-#define SET_TLBRSW(b, v)	 SET_GLOBAL_REG(TLBRSW, (b), (v))
-#define SET_TLBTR0(b, v)	 SET_GLOBAL_REG(TLBTR0, (b), (v))
-#define SET_TLBTR1(b, v)	 SET_GLOBAL_REG(TLBTR1, (b), (v))
-#define SET_TLBTR2(b, v)	 SET_GLOBAL_REG(TLBTR2, (b), (v))
-#define SET_TESTBUSCR(b, v)	 SET_GLOBAL_REG(TESTBUSCR, (b), (v))
-#define SET_GLOBAL_TLBIALL(b, v) SET_GLOBAL_REG(GLOBAL_TLBIALL, (b), (v))
-#define SET_TLBIVMID(b, v)	 SET_GLOBAL_REG(TLBIVMID, (b), (v))
-#define SET_CR(b, v)		 SET_GLOBAL_REG(CR, (b), (v))
-#define SET_EAR(b, v)		 SET_GLOBAL_REG(EAR, (b), (v))
-#define SET_ESR(b, v)		 SET_GLOBAL_REG(ESR, (b), (v))
-#define SET_ESRRESTORE(b, v)	 SET_GLOBAL_REG(ESRRESTORE, (b), (v))
-#define SET_ESYNR0(b, v)	 SET_GLOBAL_REG(ESYNR0, (b), (v))
-#define SET_ESYNR1(b, v)	 SET_GLOBAL_REG(ESYNR1, (b), (v))
-#define SET_RPU_ACR(b, v)	 SET_GLOBAL_REG(RPU_ACR, (b), (v))
+#define SET_TLBRSW(b, v)	 SET_GLOBAL_REG_RELAXED(TLBRSW, (b), (v))
+#define SET_TLBTR0(b, v)	 SET_GLOBAL_REG_RELAXED(TLBTR0, (b), (v))
+#define SET_TLBTR1(b, v)	 SET_GLOBAL_REG_RELAXED(TLBTR1, (b), (v))
+#define SET_TLBTR2(b, v)	 SET_GLOBAL_REG_RELAXED(TLBTR2, (b), (v))
+#define SET_TESTBUSCR(b, v)	 SET_GLOBAL_REG_RELAXED(TESTBUSCR, (b), (v))
+#define SET_GLOBAL_TLBIALL(b, v) SET_GLOBAL_REG_RELAXED(GLOBAL_TLBIALL, (b), (v))
+#define SET_TLBIVMID(b, v)	 SET_GLOBAL_REG_RELAXED(TLBIVMID, (b), (v))
+#define SET_CR(b, v)		 SET_GLOBAL_REG_RELAXED(CR, (b), (v))
+#define SET_EAR(b, v)		 SET_GLOBAL_REG_RELAXED(EAR, (b), (v))
+#define SET_ESR(b, v)		 SET_GLOBAL_REG_RELAXED(ESR, (b), (v))
+#define SET_ESRRESTORE(b, v)	 SET_GLOBAL_REG_RELAXED(ESRRESTORE, (b), (v))
+#define SET_ESYNR0(b, v)	 SET_GLOBAL_REG_RELAXED(ESYNR0, (b), (v))
+#define SET_ESYNR1(b, v)	 SET_GLOBAL_REG_RELAXED(ESYNR1, (b), (v))
+#define SET_RPU_ACR(b, v)	 SET_GLOBAL_REG_RELAXED(RPU_ACR, (b), (v))
 
 #define GET_M2VCBR_N(b, N)	 GET_GLOBAL_REG_N(M2VCBR_N, N, (b))
 #define GET_CBACR_N(b, N)	 GET_GLOBAL_REG_N(CBACR_N, N, (b))
@@ -131,34 +138,34 @@ do { \
 
 
 /* Context register setters/getters */
-#define SET_SCTLR(b, c, v)	 SET_CTX_REG(SCTLR, (b), (c), (v))
-#define SET_ACTLR(b, c, v)	 SET_CTX_REG(ACTLR, (b), (c), (v))
-#define SET_CONTEXTIDR(b, c, v)	 SET_CTX_REG(CONTEXTIDR, (b), (c), (v))
-#define SET_TTBR0(b, c, v)	 SET_CTX_REG(TTBR0, (b), (c), (v))
-#define SET_TTBR1(b, c, v)	 SET_CTX_REG(TTBR1, (b), (c), (v))
-#define SET_TTBCR(b, c, v)	 SET_CTX_REG(TTBCR, (b), (c), (v))
-#define SET_PAR(b, c, v)	 SET_CTX_REG(PAR, (b), (c), (v))
-#define SET_FSR(b, c, v)	 SET_CTX_REG(FSR, (b), (c), (v))
-#define SET_FSRRESTORE(b, c, v)	 SET_CTX_REG(FSRRESTORE, (b), (c), (v))
-#define SET_FAR(b, c, v)	 SET_CTX_REG(FAR, (b), (c), (v))
-#define SET_FSYNR0(b, c, v)	 SET_CTX_REG(FSYNR0, (b), (c), (v))
-#define SET_FSYNR1(b, c, v)	 SET_CTX_REG(FSYNR1, (b), (c), (v))
-#define SET_PRRR(b, c, v)	 SET_CTX_REG(PRRR, (b), (c), (v))
-#define SET_NMRR(b, c, v)	 SET_CTX_REG(NMRR, (b), (c), (v))
-#define SET_TLBLKCR(b, c, v)	 SET_CTX_REG(TLBLCKR, (b), (c), (v))
-#define SET_V2PSR(b, c, v)	 SET_CTX_REG(V2PSR, (b), (c), (v))
-#define SET_TLBFLPTER(b, c, v)	 SET_CTX_REG(TLBFLPTER, (b), (c), (v))
-#define SET_TLBSLPTER(b, c, v)	 SET_CTX_REG(TLBSLPTER, (b), (c), (v))
-#define SET_BFBCR(b, c, v)	 SET_CTX_REG(BFBCR, (b), (c), (v))
-#define SET_CTX_TLBIALL(b, c, v) SET_CTX_REG(CTX_TLBIALL, (b), (c), (v))
-#define SET_TLBIASID(b, c, v)	 SET_CTX_REG(TLBIASID, (b), (c), (v))
-#define SET_TLBIVA(b, c, v)	 SET_CTX_REG(TLBIVA, (b), (c), (v))
-#define SET_TLBIVAA(b, c, v)	 SET_CTX_REG(TLBIVAA, (b), (c), (v))
-#define SET_V2PPR(b, c, v)	 SET_CTX_REG(V2PPR, (b), (c), (v))
-#define SET_V2PPW(b, c, v)	 SET_CTX_REG(V2PPW, (b), (c), (v))
-#define SET_V2PUR(b, c, v)	 SET_CTX_REG(V2PUR, (b), (c), (v))
-#define SET_V2PUW(b, c, v)	 SET_CTX_REG(V2PUW, (b), (c), (v))
-#define SET_RESUME(b, c, v)	 SET_CTX_REG(RESUME, (b), (c), (v))
+#define SET_SCTLR(b, c, v)	 SET_CTX_REG_RELAXED(SCTLR, (b), (c), (v))
+#define SET_ACTLR(b, c, v)	 SET_CTX_REG_RELAXED(ACTLR, (b), (c), (v))
+#define SET_CONTEXTIDR(b, c, v)	 SET_CTX_REG_RELAXED(CONTEXTIDR, (b), (c), (v))
+#define SET_TTBR0(b, c, v)	 SET_CTX_REG_RELAXED(TTBR0, (b), (c), (v))
+#define SET_TTBR1(b, c, v)	 SET_CTX_REG_RELAXED(TTBR1, (b), (c), (v))
+#define SET_TTBCR(b, c, v)	 SET_CTX_REG_RELAXED(TTBCR, (b), (c), (v))
+#define SET_PAR(b, c, v)	 SET_CTX_REG_RELAXED(PAR, (b), (c), (v))
+#define SET_FSR(b, c, v)	 SET_CTX_REG_RELAXED(FSR, (b), (c), (v))
+#define SET_FSRRESTORE(b, c, v)	 SET_CTX_REG_RELAXED(FSRRESTORE, (b), (c), (v))
+#define SET_FAR(b, c, v)	 SET_CTX_REG_RELAXED(FAR, (b), (c), (v))
+#define SET_FSYNR0(b, c, v)	 SET_CTX_REG_RELAXED(FSYNR0, (b), (c), (v))
+#define SET_FSYNR1(b, c, v)	 SET_CTX_REG_RELAXED(FSYNR1, (b), (c), (v))
+#define SET_PRRR(b, c, v)	 SET_CTX_REG_RELAXED(PRRR, (b), (c), (v))
+#define SET_NMRR(b, c, v)	 SET_CTX_REG_RELAXED(NMRR, (b), (c), (v))
+#define SET_TLBLKCR(b, c, v)	 SET_CTX_REG_RELAXED(TLBLCKR, (b), (c), (v))
+#define SET_V2PSR(b, c, v)	 SET_CTX_REG_RELAXED(V2PSR, (b), (c), (v))
+#define SET_TLBFLPTER(b, c, v)	 SET_CTX_REG_RELAXED(TLBFLPTER, (b), (c), (v))
+#define SET_TLBSLPTER(b, c, v)	 SET_CTX_REG_RELAXED(TLBSLPTER, (b), (c), (v))
+#define SET_BFBCR(b, c, v)	 SET_CTX_REG_RELAXED(BFBCR, (b), (c), (v))
+#define SET_CTX_TLBIALL(b, c, v) SET_CTX_REG_RELAXED(CTX_TLBIALL, (b), (c), (v))
+#define SET_TLBIASID(b, c, v)	 SET_CTX_REG_RELAXED(TLBIASID, (b), (c), (v))
+#define SET_TLBIVA(b, c, v)	 SET_CTX_REG_RELAXED(TLBIVA, (b), (c), (v))
+#define SET_TLBIVAA(b, c, v)	 SET_CTX_REG_RELAXED(TLBIVAA, (b), (c), (v))
+#define SET_V2PPR(b, c, v)	 SET_CTX_REG_RELAXED(V2PPR, (b), (c), (v))
+#define SET_V2PPW(b, c, v)	 SET_CTX_REG_RELAXED(V2PPW, (b), (c), (v))
+#define SET_V2PUR(b, c, v)	 SET_CTX_REG_RELAXED(V2PUR, (b), (c), (v))
+#define SET_V2PUW(b, c, v)	 SET_CTX_REG_RELAXED(V2PUW, (b), (c), (v))
+#define SET_RESUME(b, c, v)	 SET_CTX_REG_RELAXED(RESUME, (b), (c), (v))
 
 #define GET_SCTLR(b, c)		 GET_CTX_REG(SCTLR, (b), (c))
 #define GET_ACTLR(b, c)		 GET_CTX_REG(ACTLR, (b), (c))
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Fri May 20 03:54:54 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Fri, 20 May 2016 16:24:54 +0530
Subject: [PATCH V5 7/7] iommu/msm: Remove driver BROKEN
In-Reply-To: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1463741694-1735-8-git-send-email-sricharan@codeaurora.org>

Now that the driver is DT adapted, bus_set_iommu gets called only
when on compatible matching. So the driver should not break multiplatform
builds now. So remove the BROKEN config.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
 drivers/iommu/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 761be35..f3d9fd0 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -90,7 +90,6 @@ config MSM_IOMMU
 	bool "MSM IOMMU Support"
 	depends on ARM
 	depends on ARCH_MSM8X60 || ARCH_MSM8960 || COMPILE_TEST
-	depends on BROKEN
 	select IOMMU_API
 	select IOMMU_IO_PGTABLE_ARMV7S
 	help
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Fri May 20 04:18:26 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Fri, 20 May 2016 16:48:26 +0530
Subject: [PATCH V4 6/7] iommu/msm: Use writel_relaxed and add a barrier
References: <1463381341-30498-1-git-send-email-sricharan@codeaurora.org>
 <3070591.xyl7SB8DB7@wuerfel> <002c01d1b0fd$e4f3c350$aedb49f0$@codeaurora.org>
 <2638968.1a16UdaY62@wuerfel> 
Message-ID: <001301d1b289$58e56f70$0ab04e50$@codeaurora.org>

Hi Arnd,

>>
>>If you need the barrier after the write, it probably was already faulty
>>before, because writel only implies a barrier before the store, not
>>after. Of course all the barriers likely made the whole process so
>>slow that you never hit that race in the end.
>
>ya, it could have worked in this way and i never saw a race issue before this.
>The only reason for changing this was to optimise out the additonal barriers
>that were happening. I do not see any issue now as well, only that the writes would
>be faster.
>
 I reposted a patch here [1] with comments, i had to delete the
old accessors though as it became unused now.

http://www.spinics.net/lists/arm-kernel/msg505448.html

Regards,
 Sricharan



From sricharan at codeaurora.org  Fri May 20 04:34:35 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Fri, 20 May 2016 17:04:35 +0530
Subject: [RFC 0/9] IOMMU probe deferral support
References: <1461599894-1969-1-git-send-email-sricharan@codeaurora.org>
 <f192d4a0-9e13-4ae2-d3da-058e2e092634@samsung.com> 
Message-ID: <001701d1b28b$9941ce40$cbc56ac0$@codeaurora.org>

Hi Robin/Laurent,

>> -----Original Message-----
>> From: linux-arm-kernel [mailto:linux-arm-kernel-
>> bounces at lists.infradead.org] On Behalf Of Marek Szyprowski
>> Sent: Thursday, May 12, 2016 6:23 PM
>> To: Sricharan R <sricharan at codeaurora.org>; will.deacon at arm.com;
>> robin.murphy at arm.com; joro at 8bytes.org; iommu at lists.linux-
>> foundation.org; linux-arm-kernel at lists.infradead.org;
>> laurent.pinchart at ideasonboard.com
>> Subject: Re: [RFC 0/9] IOMMU probe deferral support
>>
>> Hello,
>>
>>
>> On 2016-04-25 17:58, Sricharan R wrote:
>> > This is mostly a repost of the probe deferral series from Laurent
>> > Pinchart [1]. Added a check to fix boot with ACPI.
>> > Adapted arm-smmu driver to work with deferred probing and added a new
>> > api for the below reason. This is based on the generic iommu binding
>> > series from Robin Murphy <robin.murphy at arm.com>.
>>
>> Thanks for this patchset. I'm working on some serious rework in exynos
>> power domains and clocks support code and it turned out that I need this
>> feature to resolve probing order. It works fine on my internal tree, where
>> some iommu controllers cannot get their clocks early enough.
>>
>> Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
>>
>   Thanks for testing. So the issue that I was facing also was the same where the iommu
>   controllers cannot get clocks early. So waiting for some suggestions if this is right/
>   or there is another way for doing this probe deferral?

So wanted to ask what will be approach to have the probe deferral working.
I remember that you mentioned last time that you were going to visit this. Hence thought
of asking how to proceed on this ?

Regards,
 Sricharan



From arnd at arndb.de  Fri May 20 04:44:10 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 20 May 2016 13:44:10 +0200
Subject: [PATCH V5 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <1463741694-1735-7-git-send-email-sricharan@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
 <1463741694-1735-7-git-send-email-sricharan@codeaurora.org>
Message-ID: <3164695.VzCnHHyi7r@wuerfel>

On Friday 20 May 2016 16:24:53 Sricharan R wrote:
> While using the generic pagetable ops the tlb maintenance
> operation gets completed in the sync callback. So use writel_relaxed
> for all register access and add a mb() at appropriate places.
> 
> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> ---
>  drivers/iommu/msm_iommu.c         |  24 +++++++--
>  drivers/iommu/msm_iommu_hw-8xxx.h | 109 ++++++++++++++++++++------------------
>  2 files changed, 79 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
> index 0299a37..dfcaeef 100644
> --- a/drivers/iommu/msm_iommu.c
> +++ b/drivers/iommu/msm_iommu.c
> @@ -124,6 +124,9 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
>  		SET_TLBLKCR(base, ctx, 0);
>  		SET_CONTEXTIDR(base, ctx, 0);
>  	}
> +
> +	/* Ensure completion of relaxed writes from the above SET macros */
> +	mb();
>  }

Why do the above use the relaxed writes? Do you have any performance
numbers showing that skipping the sync for the reset makes a measurable
difference?

How did you prove that skipping the sync before the write is safe?

How about resetting the iommu less often instead?

>  static void __flush_iotlb(void *cookie)
> @@ -141,6 +144,9 @@ static void __flush_iotlb(void *cookie)
>  		list_for_each_entry(master, &iommu->ctx_list, list)
>  			SET_CTX_TLBIALL(iommu->base, master->num, 0);
>  
> +		/* To ensure completion of TLBIALL above */
> +		mb();
> +
>  		__disable_clocks(iommu);
>  	}
>  fail:

__disable_clocks() takes spinlocks and accesses the hardware, which
in turn will also involve multiple syncs, so this seems like
a premature optimization. 

Have you tried just leaving the clocks enabled? I'd suspect you could
gain more performance that way.

> @@ -181,7 +187,8 @@ fail:
>  
>  static void __flush_iotlb_sync(void *cookie)
>  {
> -	/* To avoid a null function pointer */
> +	/* To ensure completion of the TLBIVA in __flush_iotlb_range */
> +	mb();
>  }

I don't understand the specific race from the comment.

What operation comes after this that relies on __flush_iotlb_range
having completed, and how does an mb() guarantee this?

This seems to be a bug fix that is unrelated to the change to
use writel_relaxed(), so better split it out into a separate
patch, with a longer changeset description. Did you spot this
race by running into incorrect data, or by inspection?

>  static const struct iommu_gather_ops msm_iommu_gather_ops = {
> @@ -235,6 +242,9 @@ static void config_mids(struct msm_iommu_dev *iommu,
>  		/* Set security bit override to be Non-secure */
>  		SET_NSCFG(iommu->base, mid, 3);
>  	}
> +
> +	/* Ensure completion of relaxed writes from the above SET macros */
> +	mb();
>  }
>  

This looks similar to the msm_iommu_reset() case. Maybe put those
two into one patch, or find a way to run config_mids() less often so
it doesn't show up in the profiles any more.

If you hit this often enough that it causes performance problems,
it's more likely that there is a bug in your code than that changing
to relaxed accessors is a good idea.

>  static void __reset_context(void __iomem *base, int ctx)
> @@ -257,6 +267,9 @@ static void __reset_context(void __iomem *base, int ctx)
>  	SET_TLBFLPTER(base, ctx, 0);
>  	SET_TLBSLPTER(base, ctx, 0);
>  	SET_TLBLKCR(base, ctx, 0);
> +
> +	/* Ensure completion of relaxed writes from the above SET macros */
> +	mb();
>  }
>
>  static void __program_context(void __iomem *base, int ctx,
> @@ -305,6 +318,9 @@ static void __program_context(void __iomem *base, int ctx,
>  
>  	/* Enable the MMU */
>  	SET_M(base, ctx, 1);
> +
> +	/* Ensure completion of relaxed writes from the above SET macros */
> +	mb();
>  }
>  
>  static struct iommu_domain *msm_iommu_domain_alloc(unsigned type)

Maybe one more patch for these? I can see that
__reset_context/__program_context would be run often enough to make
a difference, though maybe not as much as the flushes.

Also, split this in two patches: one that adds a comment describing
how you proved that you don't need barriers before the writes, and
another one adding the barrier afterwards, with a description of
the failure scenario.

> @@ -500,7 +516,8 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
>  	/* Invalidate context TLB */
>  	SET_CTX_TLBIALL(iommu->base, master->num, 0);
>  	SET_V2PPR(iommu->base, master->num, va & V2Pxx_VA);
> -
> +	/* Ensure completion of relaxed writes from the above SET macros */
> +	mb();
>  	par = GET_PAR(iommu->base, master->num);
>  
>  	/* We are dealing with a supersection */

In this case, I'd say it's better to rewrite the function to avoid the
read: iova_to_phys() should be fast, and not require hardware access.
Getting rid of the hardware access by using an in-memory cache for
this should gain more than just removing the barriers, as an MMIO read
is always slow.

> @@ -714,7 +731,8 @@ static int msm_iommu_probe(struct platform_device *pdev)
>  	par = GET_PAR(iommu->base, 0);
>  	SET_V2PCFG(iommu->base, 0, 0);
>  	SET_M(iommu->base, 0, 0);
> -
> +	/* Ensure completion of relaxed writes from the above SET macros */
> +	mb();
>  	if (!par) {

Probe() clearly isn't performance sensitive, so please back this out
and use the non-relaxed accessors.

> diff --git a/drivers/iommu/msm_iommu_hw-8xxx.h b/drivers/iommu/msm_iommu_hw-8xxx.h
> index fc16010..fe2c5ca 100644
> --- a/drivers/iommu/msm_iommu_hw-8xxx.h
> +++ b/drivers/iommu/msm_iommu_hw-8xxx.h
> @@ -24,13 +24,19 @@
>  #define GET_CTX_REG(reg, base, ctx) \
>  				(readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
>  
> -#define SET_GLOBAL_REG(reg, base, val)	writel((val), ((base) + (reg)))
> +/*
> + * The writes to the global/context registers needs to be synced only after
> + * all the configuration writes are done. So use relaxed accessors and
> + * a barrier at the end.
> + */
> +#define SET_GLOBAL_REG_RELAXED(reg, base, val) \
> +			       writel_relaxed((val), ((base) + (reg)))
>  
> -#define SET_CTX_REG(reg, base, ctx, val) \
> -			writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
> +#define SET_CTX_REG_RELAXED(reg, base, ctx, val) \
> +		writel_relaxed((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))

Please add the relaxed accessors first in a separate patch, and then
change over one user at a time before you remove the non-relaxed ones.

It's hard to believe that all users are actually performance critical,
so start with the ones that gain the most performance. As commented above,
some of the conversions seem particularly fishy and it's likely that
a slow reset() function should not be fixed by making reset() faster
but by calling it less often.

>  /* Context register setters/getters */
> -#define SET_SCTLR(b, c, v)	 SET_CTX_REG(SCTLR, (b), (c), (v))
> -#define SET_ACTLR(b, c, v)	 SET_CTX_REG(ACTLR, (b), (c), (v))
> -#define SET_CONTEXTIDR(b, c, v)	 SET_CTX_REG(CONTEXTIDR, (b), (c), (v))
> -#define SET_TTBR0(b, c, v)	 SET_CTX_REG(TTBR0, (b), (c), (v))
> -#define SET_TTBR1(b, c, v)	 SET_CTX_REG(TTBR1, (b), (c), (v))
> +#define SET_SCTLR(b, c, v)	 SET_CTX_REG_RELAXED(SCTLR, (b), (c), (v))
> +#define SET_ACTLR(b, c, v)	 SET_CTX_REG_RELAXED(ACTLR, (b), (c), (v))
> +#define SET_CONTEXTIDR(b, c, v)	 SET_CTX_REG_RELAXED(CONTEXTIDR, (b), (c), (v))
> +#define SET_TTBR0(b, c, v)	 SET_CTX_REG_RELAXED(TTBR0, (b), (c), (v))
> +#define SET_TTBR1(b, c, v)	 SET_CTX_REG_RELAXED(TTBR1, (b), (c), (v))
> +#define SET_TTBCR(b, c, v)	 SET_CTX_REG_RELAXED(TTBCR, (b), (c), (v))
> +#define SET_PAR(b, c, v)	 SET_CTX_REG_RELAXED(PAR, (b), (c), (v))

Can you just remove those macros, and open-code the function calls?

This is an unnecessary obfuscation that now also hides the fact that you
are using relaxed accessors.

	Arnd


From arnd at arndb.de  Fri May 20 05:04:01 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 20 May 2016 14:04:01 +0200
Subject: [GIT PULL 0/7] ARM: SoC changes for 4.7
In-Reply-To: <CAL_JsqKcVN-KcJnBhqoMpoBjJk4KiPgbWXzA1FR+vh5_bL6oYg@mail.gmail.com>
References: <8749147.ztcb6kVhye@wuerfel>
 <CAL_JsqKcVN-KcJnBhqoMpoBjJk4KiPgbWXzA1FR+vh5_bL6oYg@mail.gmail.com>
Message-ID: <39566023.glxaClBiC0@wuerfel>

On Thursday 19 May 2016 11:02:56 Rob Herring wrote:
> I happen have a script... (I run it every time people complain about DT).
> 
> Here's the diffstat of mach-* and plat-* since merging DT support:
> 
> v3.0: 833 files changed, 10945 insertions(+), 37476 deletions(-)
> v3.1: 955 files changed, 17796 insertions(+), 20300 deletions(-)
> v3.2: 1507 files changed, 32960 insertions(+), 33392 deletions(-)
> v3.3: 1301 files changed, 27725 insertions(+), 18941 deletions(-)
> v3.4: 1324 files changed, 27079 insertions(+), 21500 deletions(-)
> v3.5: 975 files changed, 32340 insertions(+), 46663 deletions(-)
> v3.6: 648 files changed, 16121 insertions(+), 13161 deletions(-)
> v3.7: 1389 files changed, 23739 insertions(+), 61097 deletions(-)
> v3.8: 1066 files changed, 32812 insertions(+), 40821 deletions(-)
> v3.9: 1031 files changed, 10051 insertions(+), 33399 deletions(-)
> v3.10: 831 files changed, 15049 insertions(+), 27333 deletions(-)
> v3.11: 675 files changed, 18519 insertions(+), 30012 deletions(-)
> v3.12: 474 files changed, 12575 insertions(+), 25120 deletions(-)
> v3.13: 491 files changed, 11088 insertions(+), 13375 deletions(-)
> v3.14: 408 files changed, 5586 insertions(+), 12691 deletions(-)
> v3.15: 538 files changed, 7809 insertions(+), 9337 deletions(-)
> v3.16: 499 files changed, 6528 insertions(+), 10252 deletions(-)
> v3.17: 596 files changed, 6274 insertions(+), 36824 deletions(-)
> v3.18: 333 files changed, 3111 insertions(+), 6905 deletions(-)
> v3.19: 435 files changed, 6180 insertions(+), 32402 deletions(-)
> v4.0: 265 files changed, 4081 insertions(+), 14119 deletions(-)
> v4.1: 362 files changed, 4286 insertions(+), 24876 deletions(-)
> v4.2: 292 files changed, 3115 insertions(+), 11567 deletions(-)
> v4.3: 306 files changed, 3223 insertions(+), 14510 deletions(-)
> v4.4: 160 files changed, 2014 insertions(+), 4893 deletions(-)
> v4.5: 531 files changed, 3839 insertions(+), 4398 deletions(-)
> v4.6: 211 files changed, 1417 insertions(+), 4320 deletions(-)
> 
> Once this goes to 0, we can move the dts files out of the kernel and
> make you maintainer. 
> 
> The dts files' numbers do look pretty constant.

Ah nice. I've done the statistics before (last time for ELC 2015 when
I did a presentation on this), but the last few lines look particularly
nice.

It's also worth comparing this to the earlier times, as by 2.6.39 we
had already started some large-scale cleanups:

This is v2.6.32..v2.6.39:
 3215 files changed, 345665 insertions(+), 100550 deletions(-)

	Arnd


From narmstrong at baylibre.com  Fri May 20 05:18:03 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 14:18:03 +0200
Subject: [PATCH 1/3] reset: Add support for the Amlogic Meson GXBB Reset
 Controller
In-Reply-To: <1463736478.4322.31.camel@pengutronix.de>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-2-git-send-email-narmstrong@baylibre.com>
 <1463736478.4322.31.camel@pengutronix.de>
Message-ID: <573F007B.6030502@baylibre.com>

Hi Philipp,

On 05/20/2016 11:27 AM, Philipp Zabel wrote:
> Hi Neil,
> 
> Am Freitag, den 20.05.2016, 10:27 +0200 schrieb Neil Armstrong:
>> +config MESON_GXBB_RESET
>> +	tristate "Amlogic Meson GXBB Reset Driver"
>> +	depends on (ARCH_MESON && RESET_CONTROLLER)
> 
> With the "reset: fix Kconfig menu to include reset drivers in sub-menu"
> patch [1] applied this is wrapped in "if RESET_CONTROLLER ... endif", so
> no need to depend on RESET_CONTROLLER.
> Is there a reason to have this configurable at all, though?
> 
> [1] https://patchwork.kernel.org/patch/9000591/
> 
> Or drop CONFIG_MESON_GXBB_RESET and use CONFIG_ARCH_MESON directly.

No strong reason, I will switch to CONFIG_ARCH_MESON.

> [...]
> 
> With the "reset: add devm_reset_controller_register API" patch [2]
> applied you can use devm_reset_controller_register() here and remove the
> meson_gxbb_reset_remove() function below.
> 
> [2] https://patchwork.kernel.org/patch/8988471/
> 
>> +}
>> +
>> +static int meson_gxbb_reset_remove(struct platform_device *pdev)
>> +{
>> +	struct meson_gxbb_reset *data = platform_get_drvdata(pdev);
>> +
>> +	reset_controller_unregister(&data->rcdev);
>> +
>> +	return 0;
>> +}
> 
> Could be removed, then.
> 
> regards
> Philipp

It will be for sure !

Neil



From narmstrong at baylibre.com  Fri May 20 05:18:52 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 14:18:52 +0200
Subject: [PATCH 2/3] dt-bindings: reset: Add bindings for the Meson GXBB
 Reset Controller
In-Reply-To: <20160520090859.GB19888@mephisto>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-3-git-send-email-narmstrong@baylibre.com>
 <20160520084646.GB16732@mephisto> <573ED01C.2070800@baylibre.com>
 <20160520090859.GB19888@mephisto>
Message-ID: <573F00AC.6040304@baylibre.com>

On 05/20/2016 11:08 AM, Carlo Caione wrote:
> On 20/05/16 10:51, Neil Armstrong wrote:
>> On 05/20/2016 10:46 AM, Carlo Caione wrote:
>>> On 20/05/16 10:27, Neil Armstrong wrote:
>>>> Add DT bindings for the Meson GXBB SoC Reset Controller documentation and the
>>>> associated include file.
>>>
>>> [...]
>>>
>>>> +#define RESET_I2C_MASTER_2	142
>>>> +#define RESET_I2C_MASTER_1	143
>>>> +/*				144-159	*/
>>>> +/*	RESET5				*/
>>>> +/*				160-191	*/
>>>> +/*	RESET6				*/
>>>> +#define RESET_PERIPHS_GENERAL	192
>>>> +#define RESET_PERIPHS_SPICC	193
>>>> +#define RESET_PERIPHS_SMART_CARD	194
>>>> +#define RESET_PERIPHS_SAR_ADC	195
>>>> +#define RESET_PERIPHS_I2C_MASTER_0	196
>>>> +#define RESET_SANA		197
>>>> +/*				198	*/
>>>> +#define RESET_PERIPHS_STREAM_INTERFACE	199
>>>> +#define RESET_PERIPHS_SDIO	200
>>>> +#define RESET_PERIPHS_UART_0	201
>>>> +#define RESET_PERIPHS_UART_1_2	202
>>>> +#define RESET_PERIPHS_ASYNC_0	203
>>>> +#define RESET_PERIPHS_ASYNC_1	204
>>>> +#define RESET_PERIPHS_SPI_0	205
>>>> +#define RESET_PERIPHS_SDHC	206
>>>> +#define RESET_UART_SLIP		207
>>>> +/*				208-223	*/
>>>> +/*	RESET7				*/
>>>> +#define RESET_USB_DDR_0		224
>>>> +#define RESET_USB_DDR_1		225
>>>> +#define RESET_USB_DDR_2		226
>>>> +#define RESET_USB_DDR_3		227
>>>> +/*				228	*/
>>>> +#define RESET_DEVICE_MMC_ARB	229
>>>> +/*				230	*/
>>>> +#define RESET_VID_LOCK		231
>>>> +#define RESET_A9_DMC_PIPEL	232
>>>> +/*				233-255	*/
>>>> +
>>>> +#endif
>>>
>>> Indentation looks really messy. Can you just shift the numbers to the
>>> right so that they are on the same column?
>>>
>> Hi Carlo,
>>
>> The patch format makes it very messy, not as in the original format :
>> https://github.com/superna9999/linux/blob/6163f8742454bb7ff962956b4e286d110ec0fb79/include/dt-bindings/reset/amlogic%2Cmeson-gxbb-reset.h
> 
> https://raw.githubusercontent.com/superna9999/linux/6163f8742454bb7ff962956b4e286d110ec0fb79/include/dt-bindings/reset/amlogic%2Cmeson-gxbb-reset.h
> 
> yes, but 192 -> 200 are not nicely indented to me :)
> 

Aw, you got me !

I will add a shift and add a separate meson8b version of this file.

Neil


From narmstrong at baylibre.com  Fri May 20 05:19:25 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 14:19:25 +0200
Subject: [PATCH 3/3] ARM64: dts: amlogic: Enable Reset Controller on
 GXBB-based platforms
In-Reply-To: <20160520091050.GC19888@mephisto>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-4-git-send-email-narmstrong@baylibre.com>
 <20160520084748.GC16732@mephisto> <573ED06F.9070909@baylibre.com>
 <20160520091050.GC19888@mephisto>
Message-ID: <573F00CD.8070504@baylibre.com>

On 05/20/2016 11:10 AM, Carlo Caione wrote:
> On 20/05/16 10:53, Neil Armstrong wrote:
>> On 05/20/2016 10:47 AM, Carlo Caione wrote:
>>> On 20/05/16 10:27, Neil Armstrong wrote:
>>>> Update DTSI file to add the reset controller node.
>>>>
>>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>>> ---
>>>>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 6 ++++++
>>>>  1 file changed, 6 insertions(+)
>>>>
>>>> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>>>> index 832815d..2463e04 100644
>>>> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>>>> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>>>> @@ -129,6 +129,12 @@
>>>>  			#size-cells = <2>;
>>>>  			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
>>>>  
>>>> +			reset: reset-controller at 4404 {
>>>> +				compatible = "amlogic,meson-gxbb-reset";
>>>> +				reg = <0x0 0x04404 0x0 0x20>;
>>>> +				#reset-cells = <1>;
>>>> +			};
>>>> +
>>>>  			uart_A: serial at 84c0 {
>>>>  				compatible = "amlogic,meson-uart";
>>>>  				reg = <0x0 0x084c0 0x0 0x14>;
>>>
>>> Missing #include <dt-bindings/reset/amlogic,meson-gxbb-reset.h> ?
>>>
>>> Thanks,
>>>
>>
>> Shouldn't we wait until the reset bindings are actually used in the dtsi ?
>> I'm quite sure kevin will post it with the Ethernet nodes.
> 
> Why? The header file is related to the reset controller. Better add it
> now with this patchset.
> 
> Cheers,
> 

OK, I will add it in gxbb and meson8b dtsi files.

Neil


From narmstrong at baylibre.com  Fri May 20 05:20:25 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 14:20:25 +0200
Subject: [PATCH 1/3] reset: Add support for the Amlogic Meson GXBB Reset
 Controller
In-Reply-To: <20160520100437.GA21213@mephisto>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-2-git-send-email-narmstrong@baylibre.com>
 <20160520090448.GA19888@mephisto> <573ED483.10101@baylibre.com>
 <20160520100437.GA21213@mephisto>
Message-ID: <573F0109.9080302@baylibre.com>

On 05/20/2016 12:04 PM, Carlo Caione wrote:
> On 20/05/16 11:10, Neil Armstrong wrote:
>> On 05/20/2016 11:04 AM, Carlo Caione wrote:
>>> On 20/05/16 10:27, Neil Armstrong wrote:
>>>> This patch adds the platform driver for the Amlogic Meson GXBB Reset
>>>> Controller.
>>>>
>>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>>>> ---
>>>>  drivers/reset/Kconfig            |   6 ++
>>>>  drivers/reset/Makefile           |   1 +
>>>>  drivers/reset/reset-meson-gxbb.c | 129 +++++++++++++++++++++++++++++++++++++++
>>>>  3 files changed, 136 insertions(+)
>>>>  create mode 100644 drivers/reset/reset-meson-gxbb.c
>>>
>>> Do we really need to be that specific (-gxbb)? This driver looks generic
>>> and simple enough to be used for several Amlogic families. You are
>>> already differentiating between them with the include file defining the
>>> reset indexes for the SoC.
>>
>> This is a good question, do the S805 have similar registers ? Same count and width ?
>> I no, it should need a rework to add a data structure per-SoC.
> 
> According to the datasheet on S805 we have 7 registers with 16 reset
> bits per register.

It will fit, I made the change to be generic. Do you know if the meson8 and previous meson6 has these registers ?

Neil



From arnd at arndb.de  Fri May 20 05:20:52 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 20 May 2016 14:20:52 +0200
Subject: [PATCH V5 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <3164695.VzCnHHyi7r@wuerfel>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
 <1463741694-1735-7-git-send-email-sricharan@codeaurora.org>
 <3164695.VzCnHHyi7r@wuerfel>
Message-ID: <2864715.kytdDZX8IX@wuerfel>

On Friday 20 May 2016 13:44:10 Arnd Bergmann wrote:
> >  #define GET_CTX_REG(reg, base, ctx) \
> >                               (readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
> >  
> > -#define SET_GLOBAL_REG(reg, base, val)       writel((val), ((base) + (reg)))
> > +/*
> > + * The writes to the global/context registers needs to be synced only after
> > + * all the configuration writes are done. So use relaxed accessors and
> > + * a barrier at the end.
> > + */
> > +#define SET_GLOBAL_REG_RELAXED(reg, base, val) \
> > +                            writel_relaxed((val), ((base) + (reg)))
> >  
> > -#define SET_CTX_REG(reg, base, ctx, val) \
> > -                     writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
> > +#define SET_CTX_REG_RELAXED(reg, base, ctx, val) \
> > +             writel_relaxed((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
> 
> Please add the relaxed accessors first in a separate patch, and then
> change over one user at a time before you remove the non-relaxed ones.
> 
> It's hard to believe that all users are actually performance critical,
> so start with the ones that gain the most performance. As commented above,
> some of the conversions seem particularly fishy and it's likely that
> a slow reset() function should not be fixed by making reset() faster
> but by calling it less often.

One more thing, please also convert them into inline functions when you modify
them, and use normal names such as

static inline void msm_iommu_write(struct msm_iommu_dev *iommu, unsigned int reg, u32 val)
{
	writel(val, iommu->base + reg);
}

static inline void msm_iommu_context_write(struct msm_iommu_ctx_dev *ctx, unsigned int reg, u32 val)
{
	writel(val, ctx->iommu->base + ctx << CTX_SHIFT + reg, val);
}

	Arnd


From narmstrong at baylibre.com  Fri May 20 05:21:37 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 14:21:37 +0200
Subject: [PATCH] reset: oxnas: Use devm register API and get rid of platform
 remove
Message-ID: <1463746897-24813-1-git-send-email-narmstrong@baylibre.com>

Use the brand new devm_reset_controller_register() API to get rid of
the platform driver remove callback.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/reset/reset-oxnas.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

Hi Philip,

This patch is based on your reset/next tree after the new
devm_reset_controller_register() was merged.

I hope it could be merged for 4.7.

Thanks,
Neil

diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c
index c60fb2d..9449805 100644
--- a/drivers/reset/reset-oxnas.c
+++ b/drivers/reset/reset-oxnas.c
@@ -112,21 +112,11 @@ static int oxnas_reset_probe(struct platform_device *pdev)
 	data->rcdev.ops = &oxnas_reset_ops;
 	data->rcdev.of_node = pdev->dev.of_node;
 
-	return reset_controller_register(&data->rcdev);
-}
-
-static int oxnas_reset_remove(struct platform_device *pdev)
-{
-	struct oxnas_reset *data = platform_get_drvdata(pdev);
-
-	reset_controller_unregister(&data->rcdev);
-
-	return 0;
+	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
 }
 
 static struct platform_driver oxnas_reset_driver = {
 	.probe	= oxnas_reset_probe,
-	.remove	= oxnas_reset_remove,
 	.driver = {
 		.name		= "oxnas-reset",
 		.of_match_table	= oxnas_reset_dt_ids,
-- 
1.9.1



From carlo at caione.org  Fri May 20 05:22:45 2016
From: carlo at caione.org (Carlo Caione)
Date: Fri, 20 May 2016 14:22:45 +0200
Subject: [PATCH 3/3] ARM64: dts: amlogic: Enable Reset Controller on
 GXBB-based platforms
In-Reply-To: <573F00CD.8070504@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-4-git-send-email-narmstrong@baylibre.com>
 <20160520084748.GC16732@mephisto> <573ED06F.9070909@baylibre.com>
 <20160520091050.GC19888@mephisto> <573F00CD.8070504@baylibre.com>
Message-ID: <20160520122245.GA22047@mephisto>

On 20/05/16 14:19, Neil Armstrong wrote:

[...]
> >>> Missing #include <dt-bindings/reset/amlogic,meson-gxbb-reset.h> ?
> >>>
> >>> Thanks,
> >>>
> >>
> >> Shouldn't we wait until the reset bindings are actually used in the dtsi ?
> >> I'm quite sure kevin will post it with the Ethernet nodes.
> > 
> > Why? The header file is related to the reset controller. Better add it
> > now with this patchset.
> > 
> > Cheers,
> > 
> 
> OK, I will add it in gxbb and meson8b dtsi files.

Why also meson8b DTSI?

-- 
Carlo Caione


From narmstrong at baylibre.com  Fri May 20 05:23:46 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 14:23:46 +0200
Subject: [PATCH 3/3] ARM64: dts: amlogic: Enable Reset Controller on
 GXBB-based platforms
In-Reply-To: <20160520122245.GA22047@mephisto>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-4-git-send-email-narmstrong@baylibre.com>
 <20160520084748.GC16732@mephisto> <573ED06F.9070909@baylibre.com>
 <20160520091050.GC19888@mephisto> <573F00CD.8070504@baylibre.com>
 <20160520122245.GA22047@mephisto>
Message-ID: <573F01D2.1090602@baylibre.com>

On 05/20/2016 02:22 PM, Carlo Caione wrote:
> On 20/05/16 14:19, Neil Armstrong wrote:
> 
> [...]
>>>>> Missing #include <dt-bindings/reset/amlogic,meson-gxbb-reset.h> ?
>>>>>
>>>>> Thanks,
>>>>>
>>>>
>>>> Shouldn't we wait until the reset bindings are actually used in the dtsi ?
>>>> I'm quite sure kevin will post it with the Ethernet nodes.
>>>
>>> Why? The header file is related to the reset controller. Better add it
>>> now with this patchset.
>>>
>>> Cheers,
>>>
>>
>> OK, I will add it in gxbb and meson8b dtsi files.
> 
> Why also meson8b DTSI?
> 

Sorry, I'll add the meson8b specific header of course.

Neil


From carlo at caione.org  Fri May 20 05:25:23 2016
From: carlo at caione.org (Carlo Caione)
Date: Fri, 20 May 2016 14:25:23 +0200
Subject: [PATCH 1/3] reset: Add support for the Amlogic Meson GXBB Reset
 Controller
In-Reply-To: <573F0109.9080302@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-2-git-send-email-narmstrong@baylibre.com>
 <20160520090448.GA19888@mephisto> <573ED483.10101@baylibre.com>
 <20160520100437.GA21213@mephisto> <573F0109.9080302@baylibre.com>
Message-ID: <20160520122523.GA9913@mephisto>

On 20/05/16 14:20, Neil Armstrong wrote:
> On 05/20/2016 12:04 PM, Carlo Caione wrote:
> > On 20/05/16 11:10, Neil Armstrong wrote:
> >> On 05/20/2016 11:04 AM, Carlo Caione wrote:
> >>> On 20/05/16 10:27, Neil Armstrong wrote:
> >>>> This patch adds the platform driver for the Amlogic Meson GXBB Reset
> >>>> Controller.
> >>>>
> >>>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> >>>> ---
> >>>>  drivers/reset/Kconfig            |   6 ++
> >>>>  drivers/reset/Makefile           |   1 +
> >>>>  drivers/reset/reset-meson-gxbb.c | 129 +++++++++++++++++++++++++++++++++++++++
> >>>>  3 files changed, 136 insertions(+)
> >>>>  create mode 100644 drivers/reset/reset-meson-gxbb.c
> >>>
> >>> Do we really need to be that specific (-gxbb)? This driver looks generic
> >>> and simple enough to be used for several Amlogic families. You are
> >>> already differentiating between them with the include file defining the
> >>> reset indexes for the SoC.
> >>
> >> This is a good question, do the S805 have similar registers ? Same count and width ?
> >> I no, it should need a rework to add a data structure per-SoC.
> > 
> > According to the datasheet on S805 we have 7 registers with 16 reset
> > bits per register.
> 
> It will fit, I made the change to be generic. Do you know if the meson8 and previous meson6 has these registers ?

No idea. No datasheet for those.

Cheers,

-- 
Carlo Caione


From arnd at arndb.de  Fri May 20 05:26:43 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 20 May 2016 14:26:43 +0200
Subject: [PATCH] reset: oxnas: Use devm register API and get rid of
 platform remove
In-Reply-To: <1463746897-24813-1-git-send-email-narmstrong@baylibre.com>
References: <1463746897-24813-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <16785613.U51XVX7YG6@wuerfel>

On Friday 20 May 2016 14:21:37 Neil Armstrong wrote:
> Use the brand new devm_reset_controller_register() API to get rid of
> the platform driver remove callback.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/reset/reset-oxnas.c | 12 +-----------
>  1 file changed, 1 insertion(+), 11 deletions(-)
> 
> Hi Philip,
> 
> This patch is based on your reset/next tree after the new
> devm_reset_controller_register() was merged.
> 
> I hope it could be merged for 4.7.
> 
> 

It's too late for that now, as it looks like a cleanup patch that
can wait until 4.8. If the patch fixes a bug that prevents it from
working correctly, please clarify that in the changelog text.

	Arnd


From shawn.lin at kernel-upstream.org  Fri May 20 05:35:53 2016
From: shawn.lin at kernel-upstream.org (Shawn Lin)
Date: Fri, 20 May 2016 20:35:53 +0800
Subject: [PATCH v2 3/3] ARM: dts: rockchip: fixes the spi compatible for
 rk3036
In-Reply-To: <1463702182-5188-3-git-send-email-wxt@rock-chips.com>
References: <1463702182-5188-1-git-send-email-wxt@rock-chips.com>
 <1463702182-5188-3-git-send-email-wxt@rock-chips.com>
Message-ID: <8f662b3b-e359-efdf-72e5-c4f862dd1cf6@kernel-upstream.org>

? 2016/5/20 7:56, Caesar Wang ??:
> That's seem the incorrect string to match the spi driver.
>

Will it break the backward compatibility for some dtb if not
falling back to "rockchip,rockchip-spi" ?

> Fixes commit f629fcfab2cd
> ("ARM: dts: rockchip: support the spi for rk3036")
>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Cc: linux-rockchip at lists.infradead.org
>
> ---
>
> Changes in v2: None
>
>  arch/arm/boot/dts/rk3036.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
> index d0f4bb7..a30700a 100644
> --- a/arch/arm/boot/dts/rk3036.dtsi
> +++ b/arch/arm/boot/dts/rk3036.dtsi
> @@ -431,7 +431,7 @@
>  	};
>
>  	spi: spi at 20074000 {
> -		compatible = "rockchip,rockchip-spi";
> +		compatible = "rockchip,rk3036-spi";
>  		reg = <0x20074000 0x1000>;
>  		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
>  		clocks =<&cru PCLK_SPI>, <&cru SCLK_SPI>;
>



From fengguang.wu at intel.com  Fri May 20 05:40:46 2016
From: fengguang.wu at intel.com (kbuild test robot)
Date: Fri, 20 May 2016 20:40:46 +0800
Subject: [stericsson:earlydebug 1/1] init/main.c:490: undefined reference to
 `printascii'
Message-ID: <201605202044.auhsCGs8%fengguang.wu@intel.com>

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git earlydebug
head:   7a0e86123c84ec8853d7c6ae248e911a04a81bb4
commit: 7a0e86123c84ec8853d7c6ae248e911a04a81bb4 [1/1] uglyhack printascii
config: alpha-defconfig (attached as .config)
compiler: alpha-linux-gnu-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        git checkout 7a0e86123c84ec8853d7c6ae248e911a04a81bb4
        # save the attached .config to linux build tree
        make.cross ARCH=alpha 

Note: the stericsson/earlydebug HEAD 7a0e86123c84ec8853d7c6ae248e911a04a81bb4 builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   init/built-in.o: In function `start_kernel':
>> init/main.c:490: undefined reference to `printascii'
>> init/main.c:490: undefined reference to `printascii'

vim +490 init/main.c

   484		set_task_stack_end_magic(&init_task);
   485		smp_setup_processor_id();
   486		debug_objects_early_init();
   487	
   488		{
   489		  extern void printascii(char *);
 > 490		  printascii("start_kernel\n");
   491		}
   492		/*
   493		 * Set up the the initial canary ASAP:

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 11941 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160520/e4f54856/attachment.obj>

From shawn.lin at rock-chips.com  Fri May 20 05:55:56 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Fri, 20 May 2016 20:55:56 +0800
Subject: [PATCH] arm64: dts: rockchip: fixes the gic400 2nd region size
 for rk3368
In-Reply-To: <1463582510-29156-1-git-send-email-wxt@rock-chips.com>
References: <1463582510-29156-1-git-send-email-wxt@rock-chips.com>
Message-ID: <61133267-f903-b580-7737-b77610392cde@rock-chips.com>

? 2016/5/18 22:41, Caesar Wang ??:
> The 2nd additional region is the GIC virtual cpu interface register
> base and size.
>
> As the gic400 of rk3368 says, the cpu interface register map as below
>
> :
>
> -0x0000 GICC_CTRL
> .
> .
> .
> -0x00fc GICC_IIDR
> -0x1000 GICC_IDR
>
> Obviously, the region size should be greater than 0x1000.
> So we should make sure to include the GICC_IDR since the kernel will access
> it in some cases.
>

yes, address range for GICC_* should be from 0x2000 to 0x3fff according
to gic400 memory map Table 3-1.

Reviewed-by: Shawn Lin <shawn.lin at rock-chips.com>

> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-rockchip at lists.infradead.org
>
> ---
>
>  arch/arm64/boot/dts/rockchip/rk3368.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
> index 8b4a7c9..080203e 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
> @@ -670,7 +670,7 @@
>  		#address-cells = <0>;
>
>  		reg = <0x0 0xffb71000 0x0 0x1000>,
> -		      <0x0 0xffb72000 0x0 0x1000>,
> +		      <0x0 0xffb72000 0x0 0x2000>,
>  		      <0x0 0xffb74000 0x0 0x2000>,
>  		      <0x0 0xffb76000 0x0 0x2000>;
>  		interrupts = <GIC_PPI 9
>


-- 
Best Regards
Shawn Lin



From wxt at rock-chips.com  Fri May 20 05:57:03 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri, 20 May 2016 20:57:03 +0800
Subject: [PATCH v2 3/3] ARM: dts: rockchip: fixes the spi compatible for
 rk3036
In-Reply-To: <8f662b3b-e359-efdf-72e5-c4f862dd1cf6@kernel-upstream.org>
References: <1463702182-5188-1-git-send-email-wxt@rock-chips.com>
 <1463702182-5188-3-git-send-email-wxt@rock-chips.com>
 <8f662b3b-e359-efdf-72e5-c4f862dd1cf6@kernel-upstream.org>
Message-ID: <573F099F.1020603@rock-chips.com>


? 2016?05?20? 20:35, Shawn Lin ??:
> ? 2016/5/20 7:56, Caesar Wang ??:
>> That's seem the incorrect string to match the spi driver.
>>
>
> Will it break the backward compatibility for some dtb if not
> falling back to "rockchip,rockchip-spi" ?

The rk3036 shouldn't work if you read the driver/spi/spi-rockchip.c.
since the "rockchip,rockchip-spi" is *not* exist in linux kernel.

..
  static const struct of_device_id rockchip_spi_dt_match[] = {
     { .compatible = "rockchip,rk3066-spi", },
     { .compatible = "rockchip,rk3188-spi", },
     { .compatible = "rockchip,rk3288-spi", },
     { .compatible = "rockchip,rk3399-spi", },
     { },
}
..


-Caesar

>
>> Fixes commit f629fcfab2cd
>> ("ARM: dts: rockchip: support the spi for rk3036")
>>
>> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>> Cc: Heiko Stuebner <heiko at sntech.de>
>> Cc: linux-rockchip at lists.infradead.org
>>
>> ---
>>
>> Changes in v2: None
>>
>>  arch/arm/boot/dts/rk3036.dtsi | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/boot/dts/rk3036.dtsi 
>> b/arch/arm/boot/dts/rk3036.dtsi
>> index d0f4bb7..a30700a 100644
>> --- a/arch/arm/boot/dts/rk3036.dtsi
>> +++ b/arch/arm/boot/dts/rk3036.dtsi
>> @@ -431,7 +431,7 @@
>>      };
>>
>>      spi: spi at 20074000 {
>> -        compatible = "rockchip,rockchip-spi";
>> +        compatible = "rockchip,rk3036-spi";
>>          reg = <0x20074000 0x1000>;
>>          interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
>>          clocks =<&cru PCLK_SPI>, <&cru SCLK_SPI>;
>>
>
>
>
>

-- 
caesar wang | software engineer | wxt at rock-chip.com




From heiko at sntech.de  Fri May 20 05:58:27 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Fri, 20 May 2016 14:58:27 +0200
Subject: [PATCH v2 3/3] ARM: dts: rockchip: fixes the spi compatible for
 rk3036
In-Reply-To: <8f662b3b-e359-efdf-72e5-c4f862dd1cf6@kernel-upstream.org>
References: <1463702182-5188-1-git-send-email-wxt@rock-chips.com>
 <1463702182-5188-3-git-send-email-wxt@rock-chips.com>
 <8f662b3b-e359-efdf-72e5-c4f862dd1cf6@kernel-upstream.org>
Message-ID: <28155403.nCsUkeXQB1@phil>

Am Freitag, 20. Mai 2016, 20:35:53 schrieb Shawn Lin:
> ? 2016/5/20 7:56, Caesar Wang ??:
> > That's seem the incorrect string to match the spi driver.
> 
> Will it break the backward compatibility for some dtb if not
> falling back to "rockchip,rockchip-spi" ?

in what dtb did you see "rockchip,rockchip-spi"?
I.e. it isn't part of any current _mainline_ devicetree files.


Heiko

> 
> > Fixes commit f629fcfab2cd
> > ("ARM: dts: rockchip: support the spi for rk3036")
> > 
> > Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> > Cc: Heiko Stuebner <heiko at sntech.de>
> > Cc: linux-rockchip at lists.infradead.org
> > 
> > ---
> > 
> > Changes in v2: None
> > 
> >  arch/arm/boot/dts/rk3036.dtsi | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm/boot/dts/rk3036.dtsi
> > b/arch/arm/boot/dts/rk3036.dtsi index d0f4bb7..a30700a 100644
> > --- a/arch/arm/boot/dts/rk3036.dtsi
> > +++ b/arch/arm/boot/dts/rk3036.dtsi
> > @@ -431,7 +431,7 @@
> > 
> >  	};
> >  	
> >  	spi: spi at 20074000 {
> > 
> > -		compatible = "rockchip,rockchip-spi";
> > +		compatible = "rockchip,rk3036-spi";
> > 
> >  		reg = <0x20074000 0x1000>;
> >  		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
> >  		clocks =<&cru PCLK_SPI>, <&cru SCLK_SPI>;



From p.zabel at pengutronix.de  Fri May 20 06:02:23 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Fri, 20 May 2016 15:02:23 +0200
Subject: [PATCH] reset: oxnas: Use devm register API and get rid of
 platform remove
In-Reply-To: <1463746897-24813-1-git-send-email-narmstrong@baylibre.com>
References: <1463746897-24813-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1463749343.4322.38.camel@pengutronix.de>

Hi Neil,

Am Freitag, den 20.05.2016, 14:21 +0200 schrieb Neil Armstrong:
> Use the brand new devm_reset_controller_register() API to get rid of
> the platform driver remove callback.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/reset/reset-oxnas.c | 12 +-----------
>  1 file changed, 1 insertion(+), 11 deletions(-)
> 
> Hi Philip,
> 
> This patch is based on your reset/next tree after the new
> devm_reset_controller_register() was merged.

Applied, thank you.

> I hope it could be merged for 4.7.

I'll submit the branch for 4.8 after 4.7-rc1 is released.

regards
Philipp



From narmstrong at baylibre.com  Fri May 20 06:03:10 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 20 May 2016 15:03:10 +0200
Subject: [PATCH] reset: oxnas: Use devm register API and get rid of
 platform remove
In-Reply-To: <1463749343.4322.38.camel@pengutronix.de>
References: <1463746897-24813-1-git-send-email-narmstrong@baylibre.com>
 <1463749343.4322.38.camel@pengutronix.de>
Message-ID: <573F0B0E.4090102@baylibre.com>

On 05/20/2016 03:02 PM, Philipp Zabel wrote:
> Hi Neil,
> 
> Am Freitag, den 20.05.2016, 14:21 +0200 schrieb Neil Armstrong:
>> Use the brand new devm_reset_controller_register() API to get rid of
>> the platform driver remove callback.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> ---
>>  drivers/reset/reset-oxnas.c | 12 +-----------
>>  1 file changed, 1 insertion(+), 11 deletions(-)
>>
>> Hi Philip,
>>
>> This patch is based on your reset/next tree after the new
>> devm_reset_controller_register() was merged.
> 
> Applied, thank you.
> 
>> I hope it could be merged for 4.7.
> 
> I'll submit the branch for 4.8 after 4.7-rc1 is released.
> 
> regards
> Philipp
> 

Thanks Philipp,

Sorry I missed the 4.6 release...

Neil


From shawn.lin at rock-chips.com  Fri May 20 06:04:57 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Fri, 20 May 2016 21:04:57 +0800
Subject: [PATCH v2 3/3] ARM: dts: rockchip: fixes the spi compatible for
 rk3036
In-Reply-To: <573F099F.1020603@rock-chips.com>
References: <1463702182-5188-1-git-send-email-wxt@rock-chips.com>
 <1463702182-5188-3-git-send-email-wxt@rock-chips.com>
 <8f662b3b-e359-efdf-72e5-c4f862dd1cf6@kernel-upstream.org>
 <573F099F.1020603@rock-chips.com>
Message-ID: <e538d784-2860-04e9-1e8c-45c8769561f9@rock-chips.com>

? 2016/5/20 20:57, Caesar Wang ??:
>
> ? 2016?05?20? 20:35, Shawn Lin ??:
>> ? 2016/5/20 7:56, Caesar Wang ??:
>>> That's seem the incorrect string to match the spi driver.
>>>
>>
>> Will it break the backward compatibility for some dtb if not
>> falling back to "rockchip,rockchip-spi" ?
>
> The rk3036 shouldn't work if you read the driver/spi/spi-rockchip.c.
> since the "rockchip,rockchip-spi" is *not* exist in linux kernel.
>

okay, so that means we take "rockchip,rockchip-spi" from local branch
by mistake?

> ..
>  static const struct of_device_id rockchip_spi_dt_match[] = {
>     { .compatible = "rockchip,rk3066-spi", },
>     { .compatible = "rockchip,rk3188-spi", },
>     { .compatible = "rockchip,rk3288-spi", },
>     { .compatible = "rockchip,rk3399-spi", },
>     { },
> }
> ..
>
>
> -Caesar
>
>>
>>> Fixes commit f629fcfab2cd
>>> ("ARM: dts: rockchip: support the spi for rk3036")
>>>
>>> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>>> Cc: Heiko Stuebner <heiko at sntech.de>
>>> Cc: linux-rockchip at lists.infradead.org
>>>
>>> ---
>>>
>>> Changes in v2: None
>>>
>>>  arch/arm/boot/dts/rk3036.dtsi | 2 +-
>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/arch/arm/boot/dts/rk3036.dtsi
>>> b/arch/arm/boot/dts/rk3036.dtsi
>>> index d0f4bb7..a30700a 100644
>>> --- a/arch/arm/boot/dts/rk3036.dtsi
>>> +++ b/arch/arm/boot/dts/rk3036.dtsi
>>> @@ -431,7 +431,7 @@
>>>      };
>>>
>>>      spi: spi at 20074000 {
>>> -        compatible = "rockchip,rockchip-spi";
>>> +        compatible = "rockchip,rk3036-spi";
>>>          reg = <0x20074000 0x1000>;
>>>          interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
>>>          clocks =<&cru PCLK_SPI>, <&cru SCLK_SPI>;
>>>
>>
>>
>>
>>
>


-- 
Best Regards
Shawn Lin



From aleksey.makarov at linaro.org  Fri May 20 06:03:20 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Fri, 20 May 2016 16:03:20 +0300
Subject: [PATCH v8 1/4] of/serial: move earlycon early_param handling to serial
In-Reply-To: <1463749405-11640-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463749405-11640-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1463749405-11640-2-git-send-email-aleksey.makarov@linaro.org>

From: Leif Lindholm <leif.lindholm at linaro.org>

We have multiple "earlycon" early_param handlers - merge the DT one into
the main earlycon one.  It's a cleanup that also will be useful
to defer setting up DT console until ACPI/DT decision is made.

Rename the exported function to avoid clashing with the function from
arch/microblaze/kernel/prom.c

Signed-off-by: Leif Lindholm <leif.lindholm at linaro.org>
Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
Acked-by: Rob Herring <robh at kernel.org>
Acked-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
Reviewed-by: Peter Hurley <peter at hurleysoftware.com>
Tested-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/of/fdt.c              | 11 +----------
 drivers/tty/serial/earlycon.c |  2 +-
 include/linux/of_fdt.h        |  2 ++
 3 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index e7a8caa..56da2a9 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -906,7 +906,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node)
 
 #ifdef CONFIG_SERIAL_EARLYCON
 
-static int __init early_init_dt_scan_chosen_serial(void)
+int __init early_init_dt_scan_chosen_stdout(void)
 {
 	int offset;
 	const char *p, *q, *options = NULL;
@@ -950,15 +950,6 @@ static int __init early_init_dt_scan_chosen_serial(void)
 	}
 	return -ENODEV;
 }
-
-static int __init setup_of_earlycon(char *buf)
-{
-	if (buf)
-		return 0;
-
-	return early_init_dt_scan_chosen_serial();
-}
-early_param("earlycon", setup_of_earlycon);
 #endif
 
 /**
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 067783f..7aae655 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -209,7 +209,7 @@ static int __init param_setup_earlycon(char *buf)
 	 * don't generate a warning from parse_early_params() in that case
 	 */
 	if (!buf || !buf[0])
-		return 0;
+		return early_init_dt_scan_chosen_stdout();
 
 	err = setup_earlycon(buf);
 	if (err == -ENOENT || err == -EALREADY)
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index 26c3302..2f69d4c 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -66,6 +66,7 @@ extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
 				     int depth, void *data);
 extern int early_init_dt_scan_memory(unsigned long node, const char *uname,
 				     int depth, void *data);
+extern int early_init_dt_scan_chosen_stdout(void);
 extern void early_init_fdt_scan_reserved_mem(void);
 extern void early_init_fdt_reserve_self(void);
 extern void early_init_dt_add_memory_arch(u64 base, u64 size);
@@ -94,6 +95,7 @@ extern void early_get_first_memblock_info(void *, phys_addr_t *);
 extern u64 of_flat_dt_translate_address(unsigned long node);
 extern void of_fdt_limit_memory(int limit);
 #else /* CONFIG_OF_FLATTREE */
+static inline int early_init_dt_scan_chosen_stdout(void) { return -ENODEV; }
 static inline void early_init_fdt_scan_reserved_mem(void) {}
 static inline void early_init_fdt_reserve_self(void) {}
 static inline const char *of_flat_dt_get_machine_name(void) { return NULL; }
-- 
2.8.2



From aleksey.makarov at linaro.org  Fri May 20 06:03:21 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Fri, 20 May 2016 16:03:21 +0300
Subject: [PATCH v8 2/4] ACPI: parse SPCR and enable matching console
In-Reply-To: <1463749405-11640-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463749405-11640-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1463749405-11640-3-git-send-email-aleksey.makarov@linaro.org>

'ARM Server Base Boot Requiremets' [1] mentions SPCR (Serial Port
Console Redirection Table) [2] as a mandatory ACPI table that
specifies the configuration of serial console.

Defer initialization of DT earlycon until ACPI/DT decision is made.

Parse the ACPI SPCR table, setup earlycon if required,
enable specified console.

Thanks to Peter Hurley for explaining how this should work.

[1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0044a/index.html
[2] https://msdn.microsoft.com/en-us/library/windows/hardware/dn639132(v=vs.85).aspx

Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
Reviewed-by: Peter Hurley <peter at hurleysoftware.com>
Tested-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/acpi/Kconfig          |   3 ++
 drivers/acpi/Makefile         |   1 +
 drivers/acpi/spcr.c           | 111 ++++++++++++++++++++++++++++++++++++++++++
 drivers/tty/serial/earlycon.c |  19 +++++++-
 include/linux/acpi.h          |   6 +++
 include/linux/serial_core.h   |   6 +++
 6 files changed, 144 insertions(+), 2 deletions(-)
 create mode 100644 drivers/acpi/spcr.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index c204344..c8c02f1 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -77,6 +77,9 @@ config ACPI_DEBUGGER_USER
 
 endif
 
+config ACPI_SPCR_TABLE
+	bool
+
 config ACPI_SLEEP
 	bool
 	depends on SUSPEND || HIBERNATION
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 8b08e20..d0dc940 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS)	+= ec_sys.o
 obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
 obj-$(CONFIG_ACPI_BGRT)		+= bgrt.o
 obj-$(CONFIG_ACPI_CPPC_LIB)	+= cppc_acpi.o
+obj-$(CONFIG_ACPI_SPCR_TABLE)	+= spcr.o
 obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o
 
 # processor has its own "processor." module_param namespace
diff --git a/drivers/acpi/spcr.c b/drivers/acpi/spcr.c
new file mode 100644
index 0000000..f4cfc5c
--- /dev/null
+++ b/drivers/acpi/spcr.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2012, Intel Corporation
+ * Copyright (c) 2015, Red Hat, Inc.
+ * Copyright (c) 2015, 2016 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define pr_fmt(fmt) "ACPI: SPCR: " fmt
+
+#include <linux/acpi.h>
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/serial_core.h>
+
+/**
+ * parse_spcr() - parse ACPI SPCR table and add preferred console
+ *
+ * @earlycon: set up earlycon for the console specified by the table
+ *
+ * For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be
+ * defined to parse ACPI SPCR table.  As a result of the parsing preferred
+ * console is registered and if @earlycon is true, earlycon is set up.
+ *
+ * When CONFIG_ACPI_SPCR_TABLE is defined, this function should be called
+ * from arch inintialization code as soon as the DT/ACPI decision is made.
+ *
+ */
+int __init parse_spcr(bool earlycon)
+{
+	static char opts[64];
+	struct acpi_table_spcr *table;
+	acpi_size table_size;
+	acpi_status status;
+	char *uart;
+	char *iotype;
+	int baud_rate;
+	int err;
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	status = acpi_get_table_with_size(ACPI_SIG_SPCR, 0,
+					  (struct acpi_table_header **)&table,
+					  &table_size);
+
+	if (ACPI_FAILURE(status))
+		return -ENOENT;
+
+	if (table->header.revision < 2) {
+		err = -ENOENT;
+		pr_err("wrong table version\n");
+		goto done;
+	}
+
+	iotype = table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY ?
+			"mmio" : "io";
+
+	switch (table->interface_type) {
+	case ACPI_DBG2_ARM_SBSA_32BIT:
+		iotype = "mmio32";
+		/* fall through */
+	case ACPI_DBG2_ARM_PL011:
+	case ACPI_DBG2_ARM_SBSA_GENERIC:
+	case ACPI_DBG2_BCM2835:
+		uart = "pl011";
+		break;
+	case ACPI_DBG2_16550_COMPATIBLE:
+	case ACPI_DBG2_16550_SUBSET:
+		uart = "uart";
+		break;
+	default:
+		err = -ENOENT;
+		goto done;
+	}
+
+	switch (table->baud_rate) {
+	case 3:
+		baud_rate = 9600;
+		break;
+	case 4:
+		baud_rate = 19200;
+		break;
+	case 6:
+		baud_rate = 57600;
+		break;
+	case 7:
+		baud_rate = 115200;
+		break;
+	default:
+		err = -ENOENT;
+		goto done;
+	}
+
+	snprintf(opts, sizeof(opts), "%s,%s,0x%llx,%d", uart, iotype,
+		 table->serial_port.address, baud_rate);
+
+	pr_info("console: %s", opts);
+
+	if (earlycon)
+		setup_earlycon(opts);
+
+	err = add_preferred_console(uart, 0, opts + strlen(uart) + 1);
+
+done:
+	early_acpi_os_unmap_memory((void __iomem *)table, table_size);
+	return err;
+}
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index 7aae655..ea00b9f 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -21,6 +21,7 @@
 #include <linux/sizes.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
+#include <linux/acpi.h>
 
 #ifdef CONFIG_FIX_EARLYCON_MEM
 #include <asm/fixmap.h>
@@ -199,6 +200,14 @@ int __init setup_earlycon(char *buf)
 	return -ENOENT;
 }
 
+/*
+ * When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in
+ * command line does not start DT earlycon immediately, instead it defers
+ * starting it until DT/ACPI decision is made.  At that time if ACPI is enabled
+ * call parse_spcr(), else call early_init_dt_scan_chosen_stdout()
+ */
+bool earlycon_init_is_deferred __initdata;
+
 /* early_param wrapper for setup_earlycon() */
 static int __init param_setup_earlycon(char *buf)
 {
@@ -208,8 +217,14 @@ static int __init param_setup_earlycon(char *buf)
 	 * Just 'earlycon' is a valid param for devicetree earlycons;
 	 * don't generate a warning from parse_early_params() in that case
 	 */
-	if (!buf || !buf[0])
-		return early_init_dt_scan_chosen_stdout();
+	if (!buf || !buf[0]) {
+		if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) {
+			earlycon_init_is_deferred = true;
+			return 0;
+		} else {
+			return early_init_dt_scan_chosen_stdout();
+		}
+	}
 
 	err = setup_earlycon(buf);
 	if (err == -ENOENT || err == -EALREADY)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 288fac5..1de43be 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -997,4 +997,10 @@ static inline struct fwnode_handle *acpi_get_next_subnode(struct device *dev,
 #define acpi_probe_device_table(t)	({ int __r = 0; __r;})
 #endif
 
+#ifdef CONFIG_ACPI_SPCR_TABLE
+int parse_spcr(bool earlycon);
+#else
+static inline int parse_spcr(bool earlycon) { return 0; }
+#endif
+
 #endif	/*_LINUX_ACPI_H*/
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index a3d7c0d..60b6143 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -366,6 +366,12 @@ extern int of_setup_earlycon(const struct earlycon_id *match,
 			     unsigned long node,
 			     const char *options);
 
+#ifdef CONFIG_SERIAL_EARLYCON
+extern bool earlycon_init_is_deferred __initdata;
+#else
+static const bool earlycon_init_is_deferred;
+#endif
+
 struct uart_port *uart_get_console(struct uart_port *ports, int nr,
 				   struct console *c);
 int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
-- 
2.8.2



From aleksey.makarov at linaro.org  Fri May 20 06:03:19 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Fri, 20 May 2016 16:03:19 +0300
Subject: [PATCH v8 0/4] ACPI: parse the SPCR table
Message-ID: <1463749405-11640-1-git-send-email-aleksey.makarov@linaro.org>

'ARM Server Base Boot Requirements' [1] mentions SPCR (Serial Port Console
Redirection Table) [2] as a mandatory ACPI table that specifies the
configuration of serial console.

Move "earlycon" early_param handling to earlycon.c to parse this option once

Parse SPCR table, setup earlycon and register specified console.

Enable parsing this table on ARM64.  Earlycon should be set up as early as
possible.  ACPI boot tables are mapped in
arch/arm64/kernel/acpi.c:acpi_boot_table_init() called from setup_arch() and
that's where we parse spcr.  So it has to be opted-in per-arch. When
ACPI_SPCR_TABLE is defined initialization of DT earlycon is deferred until the
DT/ACPI decision is done.

Implement console_match() for pl011.

Based on the work by Leif Lindholm [3]
Thanks to Peter Hurley for explaining how this should work.

Should be applied to next-20160520
Tested on QEMU and ThunderX.
SPCR support is included in QEMU's ARM64 mach-virt since 2.4 release.

v8:
- rebase to next-20160520
- remove the patch "ACPICA: Headers: Add new constants for the DBG2 ACPI table"
  as it have got to linux-next
- add Acked-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>, Reviewed-by:
  Peter Hurley <peter at hurleysoftware.com> (but see below)
- fix the patch "serial: pl011: add console matching function".  The patch by
  Christopher Covington [4] specifies that SBSA uart does 32-bit access to
  registers and this breaks the match function.  In this series the function
  was changed to match when SPCR specifies both mmio32 and mmio access.
  I removed Acked-by: Greg from this patch because of these changes.

v7:
https://lkml.kernel.org/g/1459431629-27934-1-git-send-email-aleksey.makarov at linaro.org
- add Acked-by: Rob Herring for "of/serial: move earlycon early_param handling
  to serial"
- call DT earlycon initialization from the arch ACPI code, not from parse_spcr()
  (Rafael J. Wysocki)
- fix a few minor issues (Rafael J. Wysocki)

v6:
https://lkml.kernel.org/g/1458823925-19560-1-git-send-email-aleksey.makarov at linaro.org
- add documentation for parse_spcr() functioin (Yury Norov)
- don't initialize err variable (Yury Norov)
- add __initdata for the earlycon_init_is_deferred flag variable
- rename the function exported in "of/serial: move earlycon early_param handling
  to serial" to avoid clash with the function from arch/microblaze/kernel/prom.c
- defer initialization of DT earlycon until DT/ACPI decision is made
  (Rob Herring, Peter Hurley)
- use snprintf instead of sprintf (Andy Shevchenko)
- drop patch that adds EARLYCON_DECLARE for pl011 as EARLYCON_DECLARE is
  equivalent to OF_EARLYCON_DECLARE for 4.6+ (Peter Hurley).  This means that
  SPCR earlycon will not work on the kernels before 4.6

v5:
https://lkml.kernel.org/g/1458643595-14719-1-git-send-email-aleksey.makarov at linaro.org
- drop patch "serial: pl011: use ACPI SPCR to setup 32-bit access" because
  it is ugly. Also because Christopher Covington came with a better solution [4]
- remove error message when the table is not provided by ACPI (Andy Shevchenko)
- rewrite spcr.c following the suggestions by Peter Hurley
- add console_match() for pl011 in a separate patch
- add EARLYCON_DECLARE for pl011 in a separate patch
- add patch "of/serial: move earlycon early_param handling to serial" from
  the GDB2 series

v4:
https://lkml.kernel.org/g/1456747355-15692-1-git-send-email-aleksey.makarov at linaro.org
- drop patch "ACPI: change __init to __ref for early_acpi_os_unmap_memory()"
  ACPI developers work on a new API and asked not to do that.
  Instead, use acpi_get_table_with_size()/early_acpi_os_unmap_memory() once
  and cache the result. (Lv Zheng)
- fix some style issues (Yury Norov)

v3:
https://lkml.kernel.org/g/1455559532-8305-1-git-send-email-aleksey.makarov at linaro.org

Greg Kroah-Hartman did not like v2 so I have rewritten this patchset:

- drop acpi_match() member of struct console
- drop implementations of this member for pl011 and 8250
- drop the patch that renames some vars in printk.c as it is not needed anymore
- drop patch that introduces system wide acpi_table_parse2().
  Instead introduce a custom acpi_table_parse_spcr() in spcr.c

Instead of introducing a new match_acpi() member of struct console,
this patchset introduces a new function acpi_console_check().
This function is called when a new uart is registered at serial_core.c
the same way OF code checks for console.  If the registered uart is the
console specified by SPCR table, this function calls add_preferred_console()

The restrictions of this approach are:

- only serial consoles can be set up
- only consoles specified by the memory/io address can be set up
  (SPCR can specify devices by PCI id/PCI address)

v2:
https://lkml.kernel.org/g/1455299022-11641-1-git-send-email-aleksey.makarov at linaro.org
- don't use SPCR if user specified console in command line
- fix initialization order of newcon->index = 0
- rename some variables at printk.c (Joe Perches, Peter Hurley)
- enable ACPI_SPCR_TABLE in a separate patch (Andy Shevchenko)
- remove the retry loop for console registering (Peter Hurley).
  Instead, obtain SPCR with acpi_get_table().  That works after
  call to acpi_early_init() i. e. in any *_initcall()
- describe design decision behind introducing acpi_match() (Peter Hurley)
- fix compilation for x86 + ACPI (Graeme Gregory)
- introduce DBG2 constants in a separate patch (Andy Shevchenko)
- fix a typo in DBG2 constants (Andy Shevchenko)
- add ACPI_DBG2_ARM_SBSA_32BIT constant (Christopher Covington)
- add support for ACPI_DBG2_ARM_SBSA_* consoles (Christopher Covington)
- add documentation for functions
- add a patch that uses SPCR to find if SBSA serial driver should use 32-bit
  accessor functions (Christopher Covington)
- change __init to __ref for early_acpi_os_unmap_memory() in a separate patch
- introduce acpi_table_parse2() in a separate patch
- fix fetching the SPCR table early (Mark Salter)
- add a patch from Mark Salter that introduces support for matching 8250-based
  consoles

v1:
https://lkml.kernel.org/g/1453722324-22407-1-git-send-email-aleksey.makarov at linaro.org

[1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0044a/index.html
[2] https://msdn.microsoft.com/en-us/library/windows/hardware/dn639132(v=vs.85).aspx
[3] https://lkml.kernel.org/g/1441716217-23786-1-git-send-email-leif.lindholm at linaro.org
[4] https://lkml.kernel.org/g/1457415800-8799-1-git-send-email-cov at codeaurora.org

Aleksey Makarov (3):
  ACPI: parse SPCR and enable matching console
  ARM64: ACPI: enable ACPI_SPCR_TABLE
  serial: pl011: add console matching function

Leif Lindholm (1):
  of/serial: move earlycon early_param handling to serial

 arch/arm64/Kconfig              |   1 +
 arch/arm64/kernel/acpi.c        |  11 +++-
 drivers/acpi/Kconfig            |   3 ++
 drivers/acpi/Makefile           |   1 +
 drivers/acpi/spcr.c             | 111 ++++++++++++++++++++++++++++++++++++++++
 drivers/of/fdt.c                |  11 +---
 drivers/tty/serial/amba-pl011.c |  56 ++++++++++++++++++++
 drivers/tty/serial/earlycon.c   |  19 ++++++-
 include/linux/acpi.h            |   6 +++
 include/linux/of_fdt.h          |   2 +
 include/linux/serial_core.h     |   6 +++
 11 files changed, 214 insertions(+), 13 deletions(-)
 create mode 100644 drivers/acpi/spcr.c

-- 
2.8.2



From aleksey.makarov at linaro.org  Fri May 20 06:03:22 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Fri, 20 May 2016 16:03:22 +0300
Subject: [PATCH v8 3/4] ARM64: ACPI: enable ACPI_SPCR_TABLE
In-Reply-To: <1463749405-11640-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463749405-11640-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1463749405-11640-4-git-send-email-aleksey.makarov@linaro.org>

SBBR mentions SPCR as a mandatory ACPI table.  So enable it for ARM64

Earlycon should be set up as early as possible.  ACPI boot tables are
mapped in arch/arm64/kernel/acpi.c:acpi_boot_table_init() that
is called from setup_arch() and that's where we parse SPCR.
So it has to be opted-in per-arch.

When ACPI_SPCR_TABLE is defined initialization of DT earlycon is
deferred until the DT/ACPI decision is done.  Initialize DT earlycon
if ACPI is disabled.

Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
Tested-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/arm64/Kconfig       |  1 +
 arch/arm64/kernel/acpi.c | 11 ++++++++++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 5d30abf..80c0816 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -4,6 +4,7 @@ config ARM64
 	select ACPI_GENERIC_GSI if ACPI
 	select ACPI_PCI_HOST_GENERIC if ACPI
 	select ACPI_REDUCED_HARDWARE_ONLY if ACPI
+	select ACPI_SPCR_TABLE if ACPI
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select ARCH_HAS_ELF_RANDOMIZE
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 3e4f1a4..252a6d9 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -24,6 +24,7 @@
 #include <linux/memblock.h>
 #include <linux/of_fdt.h>
 #include <linux/smp.h>
+#include <linux/serial_core.h>
 
 #include <asm/cputype.h>
 #include <asm/cpu_ops.h>
@@ -206,7 +207,7 @@ void __init acpi_boot_table_init(void)
 	if (param_acpi_off ||
 	    (!param_acpi_on && !param_acpi_force &&
 	     of_scan_flat_dt(dt_scan_depth1_nodes, NULL)))
-		return;
+		goto done;
 
 	/*
 	 * ACPI is disabled at this point. Enable it in order to parse
@@ -226,6 +227,14 @@ void __init acpi_boot_table_init(void)
 		if (!param_acpi_force)
 			disable_acpi();
 	}
+
+done:
+	if (acpi_disabled) {
+		if (earlycon_init_is_deferred)
+			early_init_dt_scan_chosen_stdout();
+	} else {
+		parse_spcr(earlycon_init_is_deferred);
+	}
 }
 
 #ifdef CONFIG_ACPI_APEI
-- 
2.8.2



From aleksey.makarov at linaro.org  Fri May 20 06:03:23 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Fri, 20 May 2016 16:03:23 +0300
Subject: [PATCH v8 4/4] serial: pl011: add console matching function
In-Reply-To: <1463749405-11640-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463749405-11640-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <1463749405-11640-5-git-send-email-aleksey.makarov@linaro.org>

This patch adds function pl011_console_match() that implements
method match of struct console.  It allows to match consoles against
data specified in a string, for example taken from command line or
compiled by ACPI SPCR table handler.

Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
Reviewed-by: Peter Hurley <peter at hurleysoftware.com>
---
 drivers/tty/serial/amba-pl011.c | 56 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index a2aa655..388edc8 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2288,12 +2288,68 @@ static int __init pl011_console_setup(struct console *co, char *options)
 	return uart_set_options(&uap->port, co, baud, parity, bits, flow);
 }
 
+/**
+ *	pl011_console_match - non-standard console matching
+ *	@co:	  registering console
+ *	@name:	  name from console command line
+ *	@idx:	  index from console command line
+ *	@options: ptr to option string from console command line
+ *
+ *	Only attempts to match console command lines of the form:
+ *	    console=pl011,mmio|mmio32,<addr>[,<options>]
+ *	    console=pl011,0x<addr>[,<options>]
+ *	This form is used to register an initial earlycon boot console and
+ *	replace it with the amba_console at pl011 driver init.
+ *
+ *	Performs console setup for a match (as required by interface)
+ *	If no <options> are specified, then assume the h/w is already setup.
+ *
+ *	Returns 0 if console matches; otherwise non-zero to use default matching
+ */
+static int __init pl011_console_match(struct console *co, char *name, int idx,
+				      char *options)
+{
+	char match[] = "pl011";	/* pl011-specific earlycon name */
+	unsigned char iotype;
+	unsigned long addr;
+	int i;
+
+	if (strncmp(name, match, 5) != 0)
+		return -ENODEV;
+
+	if (uart_parse_earlycon(options, &iotype, &addr, &options))
+		return -ENODEV;
+
+	/* try to match the port specified on the command line */
+	for (i = 0; i < ARRAY_SIZE(amba_ports); i++) {
+		struct uart_port *port;
+
+		if (!amba_ports[i])
+			continue;
+
+		port = &amba_ports[i]->port;
+
+		if (iotype != UPIO_MEM && iotype != UPIO_MEM32)
+			continue;
+
+		if (port->mapbase != addr)
+			continue;
+
+		co->index = i;
+		port->cons = co;
+		return pl011_console_setup(co, options);
+	}
+
+	return -ENODEV;
+}
+
 static struct uart_driver amba_reg;
 static struct console amba_console = {
 	.name		= "ttyAMA",
 	.write		= pl011_console_write,
 	.device		= uart_console_device,
 	.setup		= pl011_console_setup,
+	.match		= pl011_console_match,
 	.flags		= CON_PRINTBUFFER,
 	.index		= -1,
 	.data		= &amba_reg,
-- 
2.8.2



From shawn.lin at rock-chips.com  Fri May 20 06:09:55 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Fri, 20 May 2016 21:09:55 +0800
Subject: [PATCH v2 3/3] ARM: dts: rockchip: fixes the spi compatible for
 rk3036
In-Reply-To: <28155403.nCsUkeXQB1@phil>
References: <1463702182-5188-1-git-send-email-wxt@rock-chips.com>
 <1463702182-5188-3-git-send-email-wxt@rock-chips.com>
 <8f662b3b-e359-efdf-72e5-c4f862dd1cf6@kernel-upstream.org>
 <28155403.nCsUkeXQB1@phil>
Message-ID: <3c1e174e-035b-78ae-b045-fe89990826da@rock-chips.com>

On 2016/5/20 20:58, Heiko Stuebner wrote:
> Am Freitag, 20. Mai 2016, 20:35:53 schrieb Shawn Lin:
>> ? 2016/5/20 7:56, Caesar Wang ??:
>>> That's seem the incorrect string to match the spi driver.
>>
>> Will it break the backward compatibility for some dtb if not
>> falling back to "rockchip,rockchip-spi" ?
>
> in what dtb did you see "rockchip,rockchip-spi"?

I'm not 100% sure, but I remember we toke this name on local
branch for rk3036 when we were developing this Soc.

> I.e. it isn't part of any current _mainline_ devicetree files.
>

Caesar, Could you check our develop-3.10 branch to see if it does
exist?

Anyway, "rockchip,rockchip-spi" isn't a part of mainline dt property.


>
> Heiko
>
>>
>>> Fixes commit f629fcfab2cd
>>> ("ARM: dts: rockchip: support the spi for rk3036")
>>>
>>> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>>> Cc: Heiko Stuebner <heiko at sntech.de>
>>> Cc: linux-rockchip at lists.infradead.org
>>>
>>> ---
>>>
>>> Changes in v2: None
>>>
>>>  arch/arm/boot/dts/rk3036.dtsi | 2 +-
>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/arch/arm/boot/dts/rk3036.dtsi
>>> b/arch/arm/boot/dts/rk3036.dtsi index d0f4bb7..a30700a 100644
>>> --- a/arch/arm/boot/dts/rk3036.dtsi
>>> +++ b/arch/arm/boot/dts/rk3036.dtsi
>>> @@ -431,7 +431,7 @@
>>>
>>>  	};
>>>  	
>>>  	spi: spi at 20074000 {
>>>
>>> -		compatible = "rockchip,rockchip-spi";
>>> +		compatible = "rockchip,rk3036-spi";
>>>
>>>  		reg = <0x20074000 0x1000>;
>>>  		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
>>>  		clocks =<&cru PCLK_SPI>, <&cru SCLK_SPI>;
>
>


-- 
Best Regards
Shawn Lin



From christoffer.dall at linaro.org  Fri May 20 06:30:27 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 20 May 2016 15:30:27 +0200
Subject: [PATCH] KVM: arm/arm64: vgic-new: Synchronize changes to active state
Message-ID: <1463751027-17517-1-git-send-email-christoffer.dall@linaro.org>

When modifying the active state of an interrupt via the MMIO interface,
we should ensure that the write has the intended effect.

If a guest sets an interrupt to active, but that interrupt is already
flushed into a list register on a running VCPU, then that VCPU will
write the active state back into the struct vgic_irq upon returning from
the guest and syncing its state.  This is a non-benign race, because the
guest can observe that an interrupt is not active, and it can have a
reasonable expectations that other VCPUs will not ack any IRQs, and then
set the state to active, and expect it to stay that way.  Currently we
are not honoring this case.

Thefore, change both the SACTIVE and CACTIVE mmio handlers to stop the
world, change the irq state, potentially queue the irq if we're setting
it to active, and then continue.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio.c | 69 ++++++++++++++++++++-----------------------
 1 file changed, 32 insertions(+), 37 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 4ef3571..90b0dc4 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -173,6 +173,34 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
 	return value;
 }
 
+static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
+				    bool new_active_state)
+{
+	spin_lock(&irq->irq_lock);
+	/*
+	 * If this virtual IRQ was written into a list register, we
+	 * have to make sure the CPU that runs the VCPU thread has
+	 * synced back LR state to the struct vgic_irq.  We can only
+	 * know this for sure, when either this irq is not assigned to
+	 * anyone's AP list anymore, or the VCPU thread is not
+	 * running on any CPUs.
+	 *
+	 * In the opposite case, we know the VCPU thread may be on its
+	 * way back from the guest and still has to sync back this
+	 * IRQ, so we release and re-acquire the spin_lock to let the
+	 * other thread sync back the IRQ.
+	 */
+	while (irq->vcpu && /* IRQ may have state in an LR somewhere */
+	       irq->vcpu->cpu != -1) /* VCPU thread is running */
+		cond_resched_lock(&irq->irq_lock);
+
+	irq->active = new_active_state;
+	if (new_active_state)
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	else
+		spin_unlock(&irq->irq_lock);
+}
+
 void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val)
@@ -183,27 +211,7 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
 	kvm_arm_halt_guest(vcpu->kvm);
 	for_each_set_bit(i, &val, len * 8) {
 		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-
-		spin_lock(&irq->irq_lock);
-		/*
-		 * If this virtual IRQ was written into a list register, we
-		 * have to make sure the CPU that runs the VCPU thread has
-		 * synced back LR state to the struct vgic_irq.  We can only
-		 * know this for sure, when either this irq is not assigned to
-		 * anyone's AP list anymore, or the VCPU thread is not
-		 * running on any CPUs.
-		 *
-		 * In the opposite case, we know the VCPU thread may be on its
-		 * way back from the guest and still has to sync back this
-		 * IRQ, so we release and re-acquire the spin_lock to let the
-		 * other thread sync back the IRQ.
-		 */
-		while (irq->vcpu && /* IRQ may have state in an LR somewhere */
-		       irq->vcpu->cpu != -1) /* VCPU thread is running */
-			cond_resched_lock(&irq->irq_lock);
-
-		irq->active = false;
-		spin_unlock(&irq->irq_lock);
+		vgic_mmio_change_active(vcpu, irq, false);
 	}
 	kvm_arm_resume_guest(vcpu->kvm);
 }
@@ -215,25 +223,12 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
 	int i;
 
+	kvm_arm_halt_guest(vcpu->kvm);
 	for_each_set_bit(i, &val, len * 8) {
 		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-
-		spin_lock(&irq->irq_lock);
-
-		/*
-		 * If the IRQ was already active or there is no target VCPU
-		 * assigned at the moment, then just proceed.
-		 */
-		if (irq->active || !irq->target_vcpu) {
-			irq->active = true;
-
-			spin_unlock(&irq->irq_lock);
-			continue;
-		}
-
-		irq->active = true;
-		vgic_queue_irq_unlock(vcpu->kvm, irq);
+		vgic_mmio_change_active(vcpu, irq, true);
 	}
+	kvm_arm_resume_guest(vcpu->kvm);
 }
 
 unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
-- 
2.1.2.330.g565301e.dirty



From m.szyprowski at samsung.com  Fri May 20 06:48:21 2016
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Fri, 20 May 2016 15:48:21 +0200
Subject: [PATCH] iommu/exynos: Suppress unbinding to prevent system failure
Message-ID: <1463752114-23653-1-git-send-email-m.szyprowski@samsung.com>

Removal of IOMMU driver cannot be done reliably, so Exynos IOMMU driver
doesn't support this operation. It is essential for system operation, so
it makes sense to prevent unbinding by disabling bind/unbind sysfs
feature for SYSMMU controller driver to avoid kernel ops or trashing
memory caused by such operation.

Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
CC: stable at vger.kernel.org  # v4.2+
---
 drivers/iommu/exynos-iommu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 558a40d3a6a0..d365c40a7b84 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -681,6 +681,7 @@ static struct platform_driver exynos_sysmmu_driver __refdata = {
 		.name		= "exynos-sysmmu",
 		.of_match_table	= sysmmu_of_match,
 		.pm		= &sysmmu_pm_ops,
+		.suppress_bind_attrs = true,
 	}
 };
 
-- 
1.9.2



From christoffer.dall at linaro.org  Fri May 20 06:53:30 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 20 May 2016 15:53:30 +0200
Subject: [PATCH v2] KVM: arm/arm64: vgic-new: Synchronize changes to active
 state
In-Reply-To: <1463751027-17517-1-git-send-email-christoffer.dall@linaro.org>
References: <1463751027-17517-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1463752410-3800-1-git-send-email-christoffer.dall@linaro.org>

When modifying the active state of an interrupt via the MMIO interface,
we should ensure that the write has the intended effect.

If a guest sets an interrupt to active, but that interrupt is already
flushed into a list register on a running VCPU, then that VCPU will
write the active state back into the struct vgic_irq upon returning from
the guest and syncing its state.  This is a non-benign race, because the
guest can observe that an interrupt is not active, and it can have a
reasonable expectations that other VCPUs will not ack any IRQs, and then
set the state to active, and expect it to stay that way.  Currently we
are not honoring this case.

Thefore, change both the SACTIVE and CACTIVE mmio handlers to stop the
world, change the irq state, potentially queue the irq if we're setting
it to active, and then continue.

We take this chance to slightly optimize these functions by not stopping
the world when touching private interrupts where there is inherently no
possible race.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changes since v1:
 - Dont' stop the world for private IRQs

 virt/kvm/arm/vgic/vgic-mmio.c | 87 ++++++++++++++++++++++++-------------------
 1 file changed, 48 insertions(+), 39 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 4ef3571..b014c8c 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -173,6 +173,36 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
 	return value;
 }
 
+static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
+				    bool new_active_state)
+{
+	spin_lock(&irq->irq_lock);
+	/*
+	 * If this virtual IRQ was written into a list register, we
+	 * have to make sure the CPU that runs the VCPU thread has
+	 * synced back LR state to the struct vgic_irq.  We can only
+	 * know this for sure, when either this irq is not assigned to
+	 * anyone's AP list anymore, or the VCPU thread is not
+	 * running on any CPUs.
+	 *
+	 * In the opposite case, we know the VCPU thread may be on its
+	 * way back from the guest and still has to sync back this
+	 * IRQ, so we release and re-acquire the spin_lock to let the
+	 * other thread sync back the IRQ.
+	 */
+	while (irq->vcpu && /* IRQ may have state in an LR somewhere */
+	       irq->vcpu->cpu != -1) { /* VCPU thread is running */
+		BUG_ON(irq->intid < VGIC_NR_PRIVATE_IRQS);
+		cond_resched_lock(&irq->irq_lock);
+	}
+
+	irq->active = new_active_state;
+	if (new_active_state)
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	else
+		spin_unlock(&irq->irq_lock);
+}
+
 void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val)
@@ -180,32 +210,18 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
 	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
 	int i;
 
-	kvm_arm_halt_guest(vcpu->kvm);
+	/* Only the VCPU itself can access its active state regs */
+	if (intid >= VGIC_NR_PRIVATE_IRQS)
+		kvm_arm_halt_guest(vcpu->kvm);
+
 	for_each_set_bit(i, &val, len * 8) {
 		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-
-		spin_lock(&irq->irq_lock);
-		/*
-		 * If this virtual IRQ was written into a list register, we
-		 * have to make sure the CPU that runs the VCPU thread has
-		 * synced back LR state to the struct vgic_irq.  We can only
-		 * know this for sure, when either this irq is not assigned to
-		 * anyone's AP list anymore, or the VCPU thread is not
-		 * running on any CPUs.
-		 *
-		 * In the opposite case, we know the VCPU thread may be on its
-		 * way back from the guest and still has to sync back this
-		 * IRQ, so we release and re-acquire the spin_lock to let the
-		 * other thread sync back the IRQ.
-		 */
-		while (irq->vcpu && /* IRQ may have state in an LR somewhere */
-		       irq->vcpu->cpu != -1) /* VCPU thread is running */
-			cond_resched_lock(&irq->irq_lock);
-
-		irq->active = false;
-		spin_unlock(&irq->irq_lock);
+		vgic_mmio_change_active(vcpu, irq, false);
 	}
-	kvm_arm_resume_guest(vcpu->kvm);
+
+	/* Only the VCPU itself can access its active state regs */
+	if (intid >= VGIC_NR_PRIVATE_IRQS)
+		kvm_arm_resume_guest(vcpu->kvm);
 }
 
 void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
@@ -215,25 +231,18 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
 	int i;
 
+	/* Only the VCPU itself can access its active state regs */
+	if (intid >= VGIC_NR_PRIVATE_IRQS)
+		kvm_arm_halt_guest(vcpu->kvm);
+
 	for_each_set_bit(i, &val, len * 8) {
 		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-
-		spin_lock(&irq->irq_lock);
-
-		/*
-		 * If the IRQ was already active or there is no target VCPU
-		 * assigned at the moment, then just proceed.
-		 */
-		if (irq->active || !irq->target_vcpu) {
-			irq->active = true;
-
-			spin_unlock(&irq->irq_lock);
-			continue;
-		}
-
-		irq->active = true;
-		vgic_queue_irq_unlock(vcpu->kvm, irq);
+		vgic_mmio_change_active(vcpu, irq, true);
 	}
+
+	/* Only the VCPU itself can access its active state regs */
+	if (intid >= VGIC_NR_PRIVATE_IRQS)
+		kvm_arm_resume_guest(vcpu->kvm);
 }
 
 unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
-- 
2.1.2.330.g565301e.dirty



From k.kozlowski at samsung.com  Fri May 20 07:02:36 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 20 May 2016 16:02:36 +0200
Subject: [PATCH] iommu/exynos: Suppress unbinding to prevent system failure
In-Reply-To: <1463752114-23653-1-git-send-email-m.szyprowski@samsung.com>
References: <1463752114-23653-1-git-send-email-m.szyprowski@samsung.com>
Message-ID: <573F18FC.9000506@samsung.com>

On 05/20/2016 03:48 PM, Marek Szyprowski wrote:
> Removal of IOMMU driver cannot be done reliably, so Exynos IOMMU driver
> doesn't support this operation. It is essential for system operation, so
> it makes sense to prevent unbinding by disabling bind/unbind sysfs
> feature for SYSMMU controller driver to avoid kernel ops or trashing
> memory caused by such operation.
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
> CC: stable at vger.kernel.org  # v4.2+
> ---
>  drivers/iommu/exynos-iommu.c | 1 +
>  1 file changed, 1 insertion(+)

Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

Best regards,
Krzysztof




From marc.zyngier at arm.com  Fri May 20 07:07:57 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Fri, 20 May 2016 15:07:57 +0100
Subject: [PATCH v2] KVM: arm/arm64: vgic-new: Synchronize changes to
 active state
In-Reply-To: <1463752410-3800-1-git-send-email-christoffer.dall@linaro.org>
References: <1463751027-17517-1-git-send-email-christoffer.dall@linaro.org>
 <1463752410-3800-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <573F1A3D.7050808@arm.com>

On 20/05/16 14:53, Christoffer Dall wrote:
> When modifying the active state of an interrupt via the MMIO interface,
> we should ensure that the write has the intended effect.
> 
> If a guest sets an interrupt to active, but that interrupt is already
> flushed into a list register on a running VCPU, then that VCPU will
> write the active state back into the struct vgic_irq upon returning from
> the guest and syncing its state.  This is a non-benign race, because the
> guest can observe that an interrupt is not active, and it can have a
> reasonable expectations that other VCPUs will not ack any IRQs, and then
> set the state to active, and expect it to stay that way.  Currently we
> are not honoring this case.
> 
> Thefore, change both the SACTIVE and CACTIVE mmio handlers to stop the
> world, change the irq state, potentially queue the irq if we're setting
> it to active, and then continue.
> 
> We take this chance to slightly optimize these functions by not stopping
> the world when touching private interrupts where there is inherently no
> possible race.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> ---
> Changes since v1:
>  - Dont' stop the world for private IRQs
> 
>  virt/kvm/arm/vgic/vgic-mmio.c | 87 ++++++++++++++++++++++++-------------------
>  1 file changed, 48 insertions(+), 39 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index 4ef3571..b014c8c 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -173,6 +173,36 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
>  	return value;
>  }
>  
> +static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
> +				    bool new_active_state)
> +{
> +	spin_lock(&irq->irq_lock);
> +	/*
> +	 * If this virtual IRQ was written into a list register, we
> +	 * have to make sure the CPU that runs the VCPU thread has
> +	 * synced back LR state to the struct vgic_irq.  We can only
> +	 * know this for sure, when either this irq is not assigned to
> +	 * anyone's AP list anymore, or the VCPU thread is not
> +	 * running on any CPUs.
> +	 *
> +	 * In the opposite case, we know the VCPU thread may be on its
> +	 * way back from the guest and still has to sync back this
> +	 * IRQ, so we release and re-acquire the spin_lock to let the
> +	 * other thread sync back the IRQ.
> +	 */
> +	while (irq->vcpu && /* IRQ may have state in an LR somewhere */
> +	       irq->vcpu->cpu != -1) { /* VCPU thread is running */
> +		BUG_ON(irq->intid < VGIC_NR_PRIVATE_IRQS);
> +		cond_resched_lock(&irq->irq_lock);
> +	}
> +
> +	irq->active = new_active_state;
> +	if (new_active_state)
> +		vgic_queue_irq_unlock(vcpu->kvm, irq);
> +	else
> +		spin_unlock(&irq->irq_lock);
> +}
> +
>  void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
>  			     gpa_t addr, unsigned int len,
>  			     unsigned long val)
> @@ -180,32 +210,18 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
>  	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
>  	int i;
>  
> -	kvm_arm_halt_guest(vcpu->kvm);
> +	/* Only the VCPU itself can access its active state regs */

I'm afraid this is not true for GICv3 (the private interrupts are
handled by the redistributors, which are not banked).

> +	if (intid >= VGIC_NR_PRIVATE_IRQS)
> +		kvm_arm_halt_guest(vcpu->kvm);
	else {
		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
		irq->target_vcpu.arch.pause = true;
		kvm_make_request(irq->target_vcpu, KVM_REQ_VCPU_EXIT);
		/* and then it is a bit complicated... */
	}
> +
>  	for_each_set_bit(i, &val, len * 8) {
>  		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> -
> -		spin_lock(&irq->irq_lock);
> -		/*
> -		 * If this virtual IRQ was written into a list register, we
> -		 * have to make sure the CPU that runs the VCPU thread has
> -		 * synced back LR state to the struct vgic_irq.  We can only
> -		 * know this for sure, when either this irq is not assigned to
> -		 * anyone's AP list anymore, or the VCPU thread is not
> -		 * running on any CPUs.
> -		 *
> -		 * In the opposite case, we know the VCPU thread may be on its
> -		 * way back from the guest and still has to sync back this
> -		 * IRQ, so we release and re-acquire the spin_lock to let the
> -		 * other thread sync back the IRQ.
> -		 */
> -		while (irq->vcpu && /* IRQ may have state in an LR somewhere */
> -		       irq->vcpu->cpu != -1) /* VCPU thread is running */
> -			cond_resched_lock(&irq->irq_lock);
> -
> -		irq->active = false;
> -		spin_unlock(&irq->irq_lock);
> +		vgic_mmio_change_active(vcpu, irq, false);
>  	}
> -	kvm_arm_resume_guest(vcpu->kvm);
> +
> +	/* Only the VCPU itself can access its active state regs */
> +	if (intid >= VGIC_NR_PRIVATE_IRQS)
> +		kvm_arm_resume_guest(vcpu->kvm);
>  }

I though we had a way to stop a single vcpu without too much hassle,
but I'm not seeing any standard way to do that. Grmbl...

	M.
-- 
Jazz is not dead. It just smells funny...


From christoffer.dall at linaro.org  Fri May 20 07:11:06 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 20 May 2016 16:11:06 +0200
Subject: [PATCH v3] KVM: arm/arm64: Add VGICv3 save/restore API
 documentation
In-Reply-To: <5735ED2F.4030104@arm.com>
References: <1463150637-6896-1-git-send-email-christoffer.dall@linaro.org>
 <5735ED2F.4030104@arm.com>
Message-ID: <20160520141106.GA10370@cbox>

Hi Marc,

[turns out I did have a few questions]

On Fri, May 13, 2016 at 04:05:19PM +0100, Marc Zyngier wrote:
> On 13/05/16 15:43, Christoffer Dall wrote:

[...]

> > +
> > +  KVM_DEV_ARM_VGIC_CPU_SYSREGS
> > +  Attributes:
> > +    The attr field of kvm_device_attr encodes two values:
> > +    bits:     | 63      ....       32 | 31  ....  16 | 15  ....  0 |
> > +    values:   |         mpidr         |      RES     |    instr    |
> > +
> > +    The mpidr field encodes the CPU ID based on the affinity information in the
> > +    architecture defined MPIDR, and the field is encoded as follows:
> > +      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
> > +      |    Aff3    |    Aff2    |    Aff1    |    Aff0   |
> > +
> > +    The instr field encodes the system register to access based on the fields
> > +    defined in the A64 instruction set encoding for system register access
> > +    (RES means the bits are reserved for future use and should be zero):
> 
> Should we call this field RES0 in order to match the various
> architecture documents?
> 

I define this below, so I don't think this is hugely important.  If you
think it clarifies things, I can fix it.

> > +
> > +      | 15 ... 14 | 13 ... 11 | 10 ... 7 | 6 ... 3 | 2 ... 0 |
> > +      |   Op 0    |    Op1    |    CRn   |   CRm   |   Op2   |
> > +
> > +    All system regs accessed through this API are (rw, 64-bit) and
> > +    kvm_device_attr.addr points to a __u64 value.
> > +
> > +    KVM_DEV_ARM_VGIC_CPU_SYSREGS accesses the CPU interface registers for the
> > +    CPU specified by the mpidr field.
> > +
> > +
> > +  Limitations:
> > +    - Priorities are not implemented, and registers are RAZ/WI
> 
> Is that still true? We should also document the lack of Group0 support.
> 

The priorities limiation must go out.  Not sure why we need to document
the lack of Group0 support on the user api?  Isn't that a strictly
internal limitation, but unlrelated to getting/setting the userspace
state?


Thanks,
-Christoffer


From christoffer.dall at linaro.org  Fri May 20 07:14:59 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 20 May 2016 16:14:59 +0200
Subject: [PATCH v2] KVM: arm/arm64: vgic-new: Synchronize changes to
 active state
In-Reply-To: <573F1A3D.7050808@arm.com>
References: <1463751027-17517-1-git-send-email-christoffer.dall@linaro.org>
 <1463752410-3800-1-git-send-email-christoffer.dall@linaro.org>
 <573F1A3D.7050808@arm.com>
Message-ID: <20160520141459.GB10370@cbox>

On Fri, May 20, 2016 at 03:07:57PM +0100, Marc Zyngier wrote:
> On 20/05/16 14:53, Christoffer Dall wrote:
> > When modifying the active state of an interrupt via the MMIO interface,
> > we should ensure that the write has the intended effect.
> > 
> > If a guest sets an interrupt to active, but that interrupt is already
> > flushed into a list register on a running VCPU, then that VCPU will
> > write the active state back into the struct vgic_irq upon returning from
> > the guest and syncing its state.  This is a non-benign race, because the
> > guest can observe that an interrupt is not active, and it can have a
> > reasonable expectations that other VCPUs will not ack any IRQs, and then
> > set the state to active, and expect it to stay that way.  Currently we
> > are not honoring this case.
> > 
> > Thefore, change both the SACTIVE and CACTIVE mmio handlers to stop the
> > world, change the irq state, potentially queue the irq if we're setting
> > it to active, and then continue.
> > 
> > We take this chance to slightly optimize these functions by not stopping
> > the world when touching private interrupts where there is inherently no
> > possible race.
> > 
> > Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> > ---
> > Changes since v1:
> >  - Dont' stop the world for private IRQs
> > 
> >  virt/kvm/arm/vgic/vgic-mmio.c | 87 ++++++++++++++++++++++++-------------------
> >  1 file changed, 48 insertions(+), 39 deletions(-)
> > 
> > diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> > index 4ef3571..b014c8c 100644
> > --- a/virt/kvm/arm/vgic/vgic-mmio.c
> > +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> > @@ -173,6 +173,36 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
> >  	return value;
> >  }
> >  
> > +static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
> > +				    bool new_active_state)
> > +{
> > +	spin_lock(&irq->irq_lock);
> > +	/*
> > +	 * If this virtual IRQ was written into a list register, we
> > +	 * have to make sure the CPU that runs the VCPU thread has
> > +	 * synced back LR state to the struct vgic_irq.  We can only
> > +	 * know this for sure, when either this irq is not assigned to
> > +	 * anyone's AP list anymore, or the VCPU thread is not
> > +	 * running on any CPUs.
> > +	 *
> > +	 * In the opposite case, we know the VCPU thread may be on its
> > +	 * way back from the guest and still has to sync back this
> > +	 * IRQ, so we release and re-acquire the spin_lock to let the
> > +	 * other thread sync back the IRQ.
> > +	 */
> > +	while (irq->vcpu && /* IRQ may have state in an LR somewhere */
> > +	       irq->vcpu->cpu != -1) { /* VCPU thread is running */
> > +		BUG_ON(irq->intid < VGIC_NR_PRIVATE_IRQS);
> > +		cond_resched_lock(&irq->irq_lock);
> > +	}
> > +
> > +	irq->active = new_active_state;
> > +	if (new_active_state)
> > +		vgic_queue_irq_unlock(vcpu->kvm, irq);
> > +	else
> > +		spin_unlock(&irq->irq_lock);
> > +}
> > +
> >  void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
> >  			     gpa_t addr, unsigned int len,
> >  			     unsigned long val)
> > @@ -180,32 +210,18 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
> >  	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
> >  	int i;
> >  
> > -	kvm_arm_halt_guest(vcpu->kvm);
> > +	/* Only the VCPU itself can access its active state regs */
> 
> I'm afraid this is not true for GICv3 (the private interrupts are
> handled by the redistributors, which are not banked).
> 
> > +	if (intid >= VGIC_NR_PRIVATE_IRQS)
> > +		kvm_arm_halt_guest(vcpu->kvm);
> 	else {
> 		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
> 		irq->target_vcpu.arch.pause = true;
> 		kvm_make_request(irq->target_vcpu, KVM_REQ_VCPU_EXIT);
> 		/* and then it is a bit complicated... */
> 	}
> > +
> >  	for_each_set_bit(i, &val, len * 8) {
> >  		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
> > -
> > -		spin_lock(&irq->irq_lock);
> > -		/*
> > -		 * If this virtual IRQ was written into a list register, we
> > -		 * have to make sure the CPU that runs the VCPU thread has
> > -		 * synced back LR state to the struct vgic_irq.  We can only
> > -		 * know this for sure, when either this irq is not assigned to
> > -		 * anyone's AP list anymore, or the VCPU thread is not
> > -		 * running on any CPUs.
> > -		 *
> > -		 * In the opposite case, we know the VCPU thread may be on its
> > -		 * way back from the guest and still has to sync back this
> > -		 * IRQ, so we release and re-acquire the spin_lock to let the
> > -		 * other thread sync back the IRQ.
> > -		 */
> > -		while (irq->vcpu && /* IRQ may have state in an LR somewhere */
> > -		       irq->vcpu->cpu != -1) /* VCPU thread is running */
> > -			cond_resched_lock(&irq->irq_lock);
> > -
> > -		irq->active = false;
> > -		spin_unlock(&irq->irq_lock);
> > +		vgic_mmio_change_active(vcpu, irq, false);
> >  	}
> > -	kvm_arm_resume_guest(vcpu->kvm);
> > +
> > +	/* Only the VCPU itself can access its active state regs */
> > +	if (intid >= VGIC_NR_PRIVATE_IRQS)
> > +		kvm_arm_resume_guest(vcpu->kvm);
> >  }
> 
> I though we had a way to stop a single vcpu without too much hassle,
> but I'm not seeing any standard way to do that. Grmbl...
> 
You can pause it and kick it, I think that should work... Let me have a
look.  Otherwise we'll fall back to v1 and optimize this later.

-Christoffer


From sf84 at laposte.net  Fri May 20 07:28:23 2016
From: sf84 at laposte.net (Sebastian Frias)
Date: Fri, 20 May 2016 16:28:23 +0200
Subject: Sharing code between Linux and bootloader (U-boot) ?
Message-ID: <573F1F07.6040202@laposte.net>

Hi,

Some bootloaders (like U-boot) support several HW devices: serial, network, NAND, USB, etc. most of which are also supported by Linux.

So the question is: is code shared? I mean, I understand that the drivers need to talk to the appropriate API, and such API could be different between Linux and U-boot.
But putting that aside, would it be naive to imagine that some "core" functionality could be shared? Or would that part be so small it is not worth the effort?

Since many companies use both, U-boot and Linux, I would figure they try their best to optimize engineering resources and share code, right?
In that case, I also wonder how do they share DT descriptions that right now are being stored in the Linux kernel tree.

We'd like to share code/DT for obvious reasons, what would you guys suggest?

Best regards,

Sebastian


From christoffer.dall at linaro.org  Fri May 20 07:31:00 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 20 May 2016 16:31:00 +0200
Subject: [PATCH v3] KVM: arm/arm64: vgic-new: Synchronize changes to active
 state
In-Reply-To: <1463752410-3800-1-git-send-email-christoffer.dall@linaro.org>
References: <1463752410-3800-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1463754660-25805-1-git-send-email-christoffer.dall@linaro.org>

When modifying the active state of an interrupt via the MMIO interface,
we should ensure that the write has the intended effect.

If a guest sets an interrupt to active, but that interrupt is already
flushed into a list register on a running VCPU, then that VCPU will
write the active state back into the struct vgic_irq upon returning from
the guest and syncing its state.  This is a non-benign race, because the
guest can observe that an interrupt is not active, and it can have a
reasonable expectations that other VCPUs will not ack any IRQs, and then
set the state to active, and expect it to stay that way.  Currently we
are not honoring this case.

Thefore, change both the SACTIVE and CACTIVE mmio handlers to stop the
world, change the irq state, potentially queue the irq if we're setting
it to active, and then continue.

We take this chance to slightly optimize these functions by not stopping
the world when touching private interrupts where there is inherently no
possible race.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changes since v1:
 - Dont' stop the world for private IRQs
Changes since v2:
 - Explicitly stop the VCPU that private IRQs target because GICv3
   redistributors allow any VCPU to tamper with the active state of
   interrupts private to another VCPU.

 arch/arm/include/asm/kvm_host.h   |   2 +
 arch/arm/kvm/arm.c                |   8 ++-
 arch/arm64/include/asm/kvm_host.h |   2 +
 virt/kvm/arm/vgic/vgic-mmio.c     | 105 ++++++++++++++++++++++++--------------
 4 files changed, 77 insertions(+), 40 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 832be03..987da9f 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -229,6 +229,8 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
 void kvm_arm_halt_guest(struct kvm *kvm);
 void kvm_arm_resume_guest(struct kvm *kvm);
+void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu);
+void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu);
 
 int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
 unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index e89329d..5a599c2 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -502,7 +502,13 @@ void kvm_arm_halt_guest(struct kvm *kvm)
 	kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT);
 }
 
-static void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
+void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu)
+{
+	vcpu->arch.pause = true;
+	kvm_vcpu_kick(vcpu);
+}
+
+void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
 {
 	struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
 
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index fa94f91..38746d2 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -329,6 +329,8 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
 void kvm_arm_halt_guest(struct kvm *kvm);
 void kvm_arm_resume_guest(struct kvm *kvm);
+void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu);
+void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu);
 
 u64 __kvm_call_hyp(void *hypfn, ...);
 #define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__)
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 4ef3571..059595e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -173,6 +173,66 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
 	return value;
 }
 
+static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
+				    bool new_active_state)
+{
+	spin_lock(&irq->irq_lock);
+	/*
+	 * If this virtual IRQ was written into a list register, we
+	 * have to make sure the CPU that runs the VCPU thread has
+	 * synced back LR state to the struct vgic_irq.  We can only
+	 * know this for sure, when either this irq is not assigned to
+	 * anyone's AP list anymore, or the VCPU thread is not
+	 * running on any CPUs.
+	 *
+	 * In the opposite case, we know the VCPU thread may be on its
+	 * way back from the guest and still has to sync back this
+	 * IRQ, so we release and re-acquire the spin_lock to let the
+	 * other thread sync back the IRQ.
+	 */
+	while (irq->vcpu && /* IRQ may have state in an LR somewhere */
+	       irq->vcpu->cpu != -1) { /* VCPU thread is running */
+		BUG_ON(irq->intid < VGIC_NR_PRIVATE_IRQS);
+		cond_resched_lock(&irq->irq_lock);
+	}
+
+	irq->active = new_active_state;
+	if (new_active_state)
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	else
+		spin_unlock(&irq->irq_lock);
+}
+
+/*
+ * If we are fiddling with an IRQ's active state, we have to make sure the IRQ
+ * is not queued on some running VCPU's LRs, because then the change to the
+ * active state can be overwritten when the VCPU's state is synced coming back
+ * from the guest.
+ *
+ * For shared interrupts, we have to stop all the VCPUs because interrupts can
+ * be migrated while we don't hold the IRQ locks and we don't want to be
+ * chasing moving targets.
+ *
+ * For private interrupts, we only have to make sure the single and only VCPU
+ * that can potentially queue the IRQ is stopped.
+ */
+static void vgic_change_active_prepare(struct kvm_vcpu *vcpu, u32 intid)
+{
+	if (intid < VGIC_NR_PRIVATE_IRQS)
+		kvm_arm_halt_vcpu(vcpu);
+	else
+		kvm_arm_halt_guest(vcpu->kvm);
+}
+
+/* See vgic_change_active_prepare */
+static void vgic_change_active_finish(struct kvm_vcpu *vcpu, u32 intid)
+{
+	if (intid < VGIC_NR_PRIVATE_IRQS)
+		kvm_arm_resume_vcpu(vcpu);
+	else
+		kvm_arm_resume_guest(vcpu->kvm);
+}
+
 void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val)
@@ -180,32 +240,12 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
 	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
 	int i;
 
-	kvm_arm_halt_guest(vcpu->kvm);
+	vgic_change_active_prepare(vcpu, intid);
 	for_each_set_bit(i, &val, len * 8) {
 		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-
-		spin_lock(&irq->irq_lock);
-		/*
-		 * If this virtual IRQ was written into a list register, we
-		 * have to make sure the CPU that runs the VCPU thread has
-		 * synced back LR state to the struct vgic_irq.  We can only
-		 * know this for sure, when either this irq is not assigned to
-		 * anyone's AP list anymore, or the VCPU thread is not
-		 * running on any CPUs.
-		 *
-		 * In the opposite case, we know the VCPU thread may be on its
-		 * way back from the guest and still has to sync back this
-		 * IRQ, so we release and re-acquire the spin_lock to let the
-		 * other thread sync back the IRQ.
-		 */
-		while (irq->vcpu && /* IRQ may have state in an LR somewhere */
-		       irq->vcpu->cpu != -1) /* VCPU thread is running */
-			cond_resched_lock(&irq->irq_lock);
-
-		irq->active = false;
-		spin_unlock(&irq->irq_lock);
+		vgic_mmio_change_active(vcpu, irq, false);
 	}
-	kvm_arm_resume_guest(vcpu->kvm);
+	vgic_change_active_finish(vcpu, intid);
 }
 
 void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
@@ -215,25 +255,12 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
 	int i;
 
+	vgic_change_active_prepare(vcpu, intid);
 	for_each_set_bit(i, &val, len * 8) {
 		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-
-		spin_lock(&irq->irq_lock);
-
-		/*
-		 * If the IRQ was already active or there is no target VCPU
-		 * assigned at the moment, then just proceed.
-		 */
-		if (irq->active || !irq->target_vcpu) {
-			irq->active = true;
-
-			spin_unlock(&irq->irq_lock);
-			continue;
-		}
-
-		irq->active = true;
-		vgic_queue_irq_unlock(vcpu->kvm, irq);
+		vgic_mmio_change_active(vcpu, irq, true);
 	}
+	vgic_change_active_finish(vcpu, intid);
 }
 
 unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
-- 
2.1.2.330.g565301e.dirty



From stern at rowland.harvard.edu  Fri May 20 07:31:56 2016
From: stern at rowland.harvard.edu (Alan Stern)
Date: Fri, 20 May 2016 10:31:56 -0400 (EDT)
Subject: [PATCH] usb: echi-hcd: Add ehci_setup check before echi_shutdown
In-Reply-To: <CAPBZ5QcMiMEv1n=WU6aW2PGNsSPZJR42iZge_VUX4aWZ-KKzbw@mail.gmail.com>
Message-ID: <Pine.LNX.4.44L0.1605201026060.1938-100000@iolanthe.rowland.org>

On Thu, 19 May 2016, Andy Gross wrote:

> On 19 May 2016 at 05:12, Srinivas Kandagatla
> <srinivas.kandagatla at linaro.org> wrote:
> 
> <snip>
> 
> > +++ b/drivers/usb/host/ehci-hcd.c
> > @@ -368,6 +368,15 @@ static void ehci_shutdown(struct usb_hcd *hcd)
> >  {
> >         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
> >
> > +       /**
> > +        * Protect the system from crashing at system shutdown in cases where
> > +        * usb host is not added yet from OTG controller driver.
> > +        * As ehci_setup() not done yet, so stop accessing registers or
> > +        * variables initialized in ehci_setup()
> > +        */
> > +       if (!ehci->sbrn)
> > +               return;
> > +
> >         spin_lock_irq(&ehci->lock);
> >         ehci->shutdown = true;
> >         ehci->rh_state = EHCI_RH_STOPPING;
> 
> 
> Should we also not check this in ehci_suspend and ehci_resume?  If I
> do suspend/resume, it crashes in a similar manner.  I know this goes
> beyond the problem scope of the patch.  Perhaps I should send in an
> additional patch with the code?
> 
> Are there any other places in the ehci-hcd where this needs to be checked?

Really, this is an indication that the problem lies not in ehci-hcd but 
rather in the platform glue code.  The platform code allows itself to 
be registered as the driver of the controller device but does not 
initialize the ehci-hcd parts.

Neither ehci_suspend nor ehci_resume is called directly by the driver
core; the calls all have to pass through the glue code.  So maybe the
glue layer needs to be careful about invoking these routines in
ehci-hcd before ehci-hcd has been initialized.

Alan Stern



From marc.zyngier at arm.com  Fri May 20 07:43:15 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Fri, 20 May 2016 15:43:15 +0100
Subject: [PATCH v3] KVM: arm/arm64: vgic-new: Synchronize changes to
 active state
In-Reply-To: <1463754660-25805-1-git-send-email-christoffer.dall@linaro.org>
References: <1463752410-3800-1-git-send-email-christoffer.dall@linaro.org>
 <1463754660-25805-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <573F2283.2030909@arm.com>

On 20/05/16 15:31, Christoffer Dall wrote:
> When modifying the active state of an interrupt via the MMIO interface,
> we should ensure that the write has the intended effect.
> 
> If a guest sets an interrupt to active, but that interrupt is already
> flushed into a list register on a running VCPU, then that VCPU will
> write the active state back into the struct vgic_irq upon returning from
> the guest and syncing its state.  This is a non-benign race, because the
> guest can observe that an interrupt is not active, and it can have a
> reasonable expectations that other VCPUs will not ack any IRQs, and then
> set the state to active, and expect it to stay that way.  Currently we
> are not honoring this case.
> 
> Thefore, change both the SACTIVE and CACTIVE mmio handlers to stop the
> world, change the irq state, potentially queue the irq if we're setting
> it to active, and then continue.
> 
> We take this chance to slightly optimize these functions by not stopping
> the world when touching private interrupts where there is inherently no
> possible race.
> 
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> ---
> Changes since v1:
>  - Dont' stop the world for private IRQs
> Changes since v2:
>  - Explicitly stop the VCPU that private IRQs target because GICv3
>    redistributors allow any VCPU to tamper with the active state of
>    interrupts private to another VCPU.
> 
>  arch/arm/include/asm/kvm_host.h   |   2 +
>  arch/arm/kvm/arm.c                |   8 ++-
>  arch/arm64/include/asm/kvm_host.h |   2 +
>  virt/kvm/arm/vgic/vgic-mmio.c     | 105 ++++++++++++++++++++++++--------------
>  4 files changed, 77 insertions(+), 40 deletions(-)
> 
> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index 832be03..987da9f 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -229,6 +229,8 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
>  struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
>  void kvm_arm_halt_guest(struct kvm *kvm);
>  void kvm_arm_resume_guest(struct kvm *kvm);
> +void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu);
> +void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu);
>  
>  int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
>  unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index e89329d..5a599c2 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -502,7 +502,13 @@ void kvm_arm_halt_guest(struct kvm *kvm)
>  	kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT);
>  }
>  
> -static void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
> +void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu)
> +{
> +	vcpu->arch.pause = true;
> +	kvm_vcpu_kick(vcpu);
> +}
> +
> +void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
>  {
>  	struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
>  
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index fa94f91..38746d2 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -329,6 +329,8 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
>  struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
>  void kvm_arm_halt_guest(struct kvm *kvm);
>  void kvm_arm_resume_guest(struct kvm *kvm);
> +void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu);
> +void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu);
>  
>  u64 __kvm_call_hyp(void *hypfn, ...);
>  #define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__)
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> index 4ef3571..059595e 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> @@ -173,6 +173,66 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
>  	return value;
>  }
>  
> +static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
> +				    bool new_active_state)
> +{
> +	spin_lock(&irq->irq_lock);
> +	/*
> +	 * If this virtual IRQ was written into a list register, we
> +	 * have to make sure the CPU that runs the VCPU thread has
> +	 * synced back LR state to the struct vgic_irq.  We can only
> +	 * know this for sure, when either this irq is not assigned to
> +	 * anyone's AP list anymore, or the VCPU thread is not
> +	 * running on any CPUs.
> +	 *
> +	 * In the opposite case, we know the VCPU thread may be on its
> +	 * way back from the guest and still has to sync back this
> +	 * IRQ, so we release and re-acquire the spin_lock to let the
> +	 * other thread sync back the IRQ.
> +	 */
> +	while (irq->vcpu && /* IRQ may have state in an LR somewhere */
> +	       irq->vcpu->cpu != -1) { /* VCPU thread is running */
> +		BUG_ON(irq->intid < VGIC_NR_PRIVATE_IRQS);
> +		cond_resched_lock(&irq->irq_lock);
> +	}
> +
> +	irq->active = new_active_state;
> +	if (new_active_state)
> +		vgic_queue_irq_unlock(vcpu->kvm, irq);
> +	else
> +		spin_unlock(&irq->irq_lock);
> +}
> +
> +/*
> + * If we are fiddling with an IRQ's active state, we have to make sure the IRQ
> + * is not queued on some running VCPU's LRs, because then the change to the
> + * active state can be overwritten when the VCPU's state is synced coming back
> + * from the guest.
> + *
> + * For shared interrupts, we have to stop all the VCPUs because interrupts can
> + * be migrated while we don't hold the IRQ locks and we don't want to be
> + * chasing moving targets.
> + *
> + * For private interrupts, we only have to make sure the single and only VCPU
> + * that can potentially queue the IRQ is stopped.
> + */
> +static void vgic_change_active_prepare(struct kvm_vcpu *vcpu, u32 intid)
> +{
> +	if (intid < VGIC_NR_PRIVATE_IRQS)
> +		kvm_arm_halt_vcpu(vcpu);
> +	else
> +		kvm_arm_halt_guest(vcpu->kvm);
> +}
> +
> +/* See vgic_change_active_prepare */
> +static void vgic_change_active_finish(struct kvm_vcpu *vcpu, u32 intid)
> +{
> +	if (intid < VGIC_NR_PRIVATE_IRQS)
> +		kvm_arm_resume_vcpu(vcpu);
> +	else
> +		kvm_arm_resume_guest(vcpu->kvm);
> +}
> +
>  void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
>  			     gpa_t addr, unsigned int len,
>  			     unsigned long val)
> @@ -180,32 +240,12 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
>  	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
>  	int i;
>  
> -	kvm_arm_halt_guest(vcpu->kvm);
> +	vgic_change_active_prepare(vcpu, intid);

You're still only halting the current vcpu, not the one targeted by the
interrupt.

Let's not bother with that for the time being. I'm happy to merge v1,
and optimize this when this starts bugging us (and this is going to take
a while).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From marc.zyngier at arm.com  Fri May 20 07:47:01 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Fri, 20 May 2016 15:47:01 +0100
Subject: [PATCH v3] KVM: arm/arm64: vgic-new: Synchronize changes to
 active state
In-Reply-To: <573F2283.2030909@arm.com>
References: <1463752410-3800-1-git-send-email-christoffer.dall@linaro.org>
 <1463754660-25805-1-git-send-email-christoffer.dall@linaro.org>
 <573F2283.2030909@arm.com>
Message-ID: <573F2365.5020605@arm.com>

On 20/05/16 15:43, Marc Zyngier wrote:
> On 20/05/16 15:31, Christoffer Dall wrote:
>> When modifying the active state of an interrupt via the MMIO interface,
>> we should ensure that the write has the intended effect.
>>
>> If a guest sets an interrupt to active, but that interrupt is already
>> flushed into a list register on a running VCPU, then that VCPU will
>> write the active state back into the struct vgic_irq upon returning from
>> the guest and syncing its state.  This is a non-benign race, because the
>> guest can observe that an interrupt is not active, and it can have a
>> reasonable expectations that other VCPUs will not ack any IRQs, and then
>> set the state to active, and expect it to stay that way.  Currently we
>> are not honoring this case.
>>
>> Thefore, change both the SACTIVE and CACTIVE mmio handlers to stop the
>> world, change the irq state, potentially queue the irq if we're setting
>> it to active, and then continue.
>>
>> We take this chance to slightly optimize these functions by not stopping
>> the world when touching private interrupts where there is inherently no
>> possible race.
>>
>> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
>> ---
>> Changes since v1:
>>  - Dont' stop the world for private IRQs
>> Changes since v2:
>>  - Explicitly stop the VCPU that private IRQs target because GICv3
>>    redistributors allow any VCPU to tamper with the active state of
>>    interrupts private to another VCPU.
>>
>>  arch/arm/include/asm/kvm_host.h   |   2 +
>>  arch/arm/kvm/arm.c                |   8 ++-
>>  arch/arm64/include/asm/kvm_host.h |   2 +
>>  virt/kvm/arm/vgic/vgic-mmio.c     | 105 ++++++++++++++++++++++++--------------
>>  4 files changed, 77 insertions(+), 40 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
>> index 832be03..987da9f 100644
>> --- a/arch/arm/include/asm/kvm_host.h
>> +++ b/arch/arm/include/asm/kvm_host.h
>> @@ -229,6 +229,8 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
>>  struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
>>  void kvm_arm_halt_guest(struct kvm *kvm);
>>  void kvm_arm_resume_guest(struct kvm *kvm);
>> +void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu);
>> +void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu);
>>  
>>  int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
>>  unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
>> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
>> index e89329d..5a599c2 100644
>> --- a/arch/arm/kvm/arm.c
>> +++ b/arch/arm/kvm/arm.c
>> @@ -502,7 +502,13 @@ void kvm_arm_halt_guest(struct kvm *kvm)
>>  	kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT);
>>  }
>>  
>> -static void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
>> +void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu)
>> +{
>> +	vcpu->arch.pause = true;
>> +	kvm_vcpu_kick(vcpu);
>> +}
>> +
>> +void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
>>  {
>>  	struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
>>  
>> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
>> index fa94f91..38746d2 100644
>> --- a/arch/arm64/include/asm/kvm_host.h
>> +++ b/arch/arm64/include/asm/kvm_host.h
>> @@ -329,6 +329,8 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
>>  struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
>>  void kvm_arm_halt_guest(struct kvm *kvm);
>>  void kvm_arm_resume_guest(struct kvm *kvm);
>> +void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu);
>> +void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu);
>>  
>>  u64 __kvm_call_hyp(void *hypfn, ...);
>>  #define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__)
>> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
>> index 4ef3571..059595e 100644
>> --- a/virt/kvm/arm/vgic/vgic-mmio.c
>> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
>> @@ -173,6 +173,66 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
>>  	return value;
>>  }
>>  
>> +static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
>> +				    bool new_active_state)
>> +{
>> +	spin_lock(&irq->irq_lock);
>> +	/*
>> +	 * If this virtual IRQ was written into a list register, we
>> +	 * have to make sure the CPU that runs the VCPU thread has
>> +	 * synced back LR state to the struct vgic_irq.  We can only
>> +	 * know this for sure, when either this irq is not assigned to
>> +	 * anyone's AP list anymore, or the VCPU thread is not
>> +	 * running on any CPUs.
>> +	 *
>> +	 * In the opposite case, we know the VCPU thread may be on its
>> +	 * way back from the guest and still has to sync back this
>> +	 * IRQ, so we release and re-acquire the spin_lock to let the
>> +	 * other thread sync back the IRQ.
>> +	 */
>> +	while (irq->vcpu && /* IRQ may have state in an LR somewhere */
>> +	       irq->vcpu->cpu != -1) { /* VCPU thread is running */
>> +		BUG_ON(irq->intid < VGIC_NR_PRIVATE_IRQS);
>> +		cond_resched_lock(&irq->irq_lock);
>> +	}
>> +
>> +	irq->active = new_active_state;
>> +	if (new_active_state)
>> +		vgic_queue_irq_unlock(vcpu->kvm, irq);
>> +	else
>> +		spin_unlock(&irq->irq_lock);
>> +}
>> +
>> +/*
>> + * If we are fiddling with an IRQ's active state, we have to make sure the IRQ
>> + * is not queued on some running VCPU's LRs, because then the change to the
>> + * active state can be overwritten when the VCPU's state is synced coming back
>> + * from the guest.
>> + *
>> + * For shared interrupts, we have to stop all the VCPUs because interrupts can
>> + * be migrated while we don't hold the IRQ locks and we don't want to be
>> + * chasing moving targets.
>> + *
>> + * For private interrupts, we only have to make sure the single and only VCPU
>> + * that can potentially queue the IRQ is stopped.
>> + */
>> +static void vgic_change_active_prepare(struct kvm_vcpu *vcpu, u32 intid)
>> +{
>> +	if (intid < VGIC_NR_PRIVATE_IRQS)
>> +		kvm_arm_halt_vcpu(vcpu);
>> +	else
>> +		kvm_arm_halt_guest(vcpu->kvm);
>> +}
>> +
>> +/* See vgic_change_active_prepare */
>> +static void vgic_change_active_finish(struct kvm_vcpu *vcpu, u32 intid)
>> +{
>> +	if (intid < VGIC_NR_PRIVATE_IRQS)
>> +		kvm_arm_resume_vcpu(vcpu);
>> +	else
>> +		kvm_arm_resume_guest(vcpu->kvm);
>> +}
>> +
>>  void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
>>  			     gpa_t addr, unsigned int len,
>>  			     unsigned long val)
>> @@ -180,32 +240,12 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
>>  	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
>>  	int i;
>>  
>> -	kvm_arm_halt_guest(vcpu->kvm);
>> +	vgic_change_active_prepare(vcpu, intid);
> 
> You're still only halting the current vcpu, not the one targeted by the
> interrupt.
> 
> Let's not bother with that for the time being. I'm happy to merge v1,
> and optimize this when this starts bugging us (and this is going to take
> a while).

Actually, I now realize that you are right. The MMIO handler is passing
us the target vcpu, not the the one causing the exit. I'm an idiot.

So this looks fine to me.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From christoffer.dall at linaro.org  Fri May 20 07:49:08 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 20 May 2016 16:49:08 +0200
Subject: [PATCH v3] KVM: arm/arm64: vgic-new: Synchronize changes to
 active state
In-Reply-To: <573F2365.5020605@arm.com>
References: <1463752410-3800-1-git-send-email-christoffer.dall@linaro.org>
 <1463754660-25805-1-git-send-email-christoffer.dall@linaro.org>
 <573F2283.2030909@arm.com> <573F2365.5020605@arm.com>
Message-ID: <20160520144908.GA26381@cbox>

On Fri, May 20, 2016 at 03:47:01PM +0100, Marc Zyngier wrote:
> On 20/05/16 15:43, Marc Zyngier wrote:
> > On 20/05/16 15:31, Christoffer Dall wrote:
> >> When modifying the active state of an interrupt via the MMIO interface,
> >> we should ensure that the write has the intended effect.
> >>
> >> If a guest sets an interrupt to active, but that interrupt is already
> >> flushed into a list register on a running VCPU, then that VCPU will
> >> write the active state back into the struct vgic_irq upon returning from
> >> the guest and syncing its state.  This is a non-benign race, because the
> >> guest can observe that an interrupt is not active, and it can have a
> >> reasonable expectations that other VCPUs will not ack any IRQs, and then
> >> set the state to active, and expect it to stay that way.  Currently we
> >> are not honoring this case.
> >>
> >> Thefore, change both the SACTIVE and CACTIVE mmio handlers to stop the
> >> world, change the irq state, potentially queue the irq if we're setting
> >> it to active, and then continue.
> >>
> >> We take this chance to slightly optimize these functions by not stopping
> >> the world when touching private interrupts where there is inherently no
> >> possible race.
> >>
> >> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
> >> ---
> >> Changes since v1:
> >>  - Dont' stop the world for private IRQs
> >> Changes since v2:
> >>  - Explicitly stop the VCPU that private IRQs target because GICv3
> >>    redistributors allow any VCPU to tamper with the active state of
> >>    interrupts private to another VCPU.
> >>
> >>  arch/arm/include/asm/kvm_host.h   |   2 +
> >>  arch/arm/kvm/arm.c                |   8 ++-
> >>  arch/arm64/include/asm/kvm_host.h |   2 +
> >>  virt/kvm/arm/vgic/vgic-mmio.c     | 105 ++++++++++++++++++++++++--------------
> >>  4 files changed, 77 insertions(+), 40 deletions(-)
> >>
> >> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> >> index 832be03..987da9f 100644
> >> --- a/arch/arm/include/asm/kvm_host.h
> >> +++ b/arch/arm/include/asm/kvm_host.h
> >> @@ -229,6 +229,8 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
> >>  struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
> >>  void kvm_arm_halt_guest(struct kvm *kvm);
> >>  void kvm_arm_resume_guest(struct kvm *kvm);
> >> +void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu);
> >> +void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu);
> >>  
> >>  int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
> >>  unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
> >> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> >> index e89329d..5a599c2 100644
> >> --- a/arch/arm/kvm/arm.c
> >> +++ b/arch/arm/kvm/arm.c
> >> @@ -502,7 +502,13 @@ void kvm_arm_halt_guest(struct kvm *kvm)
> >>  	kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT);
> >>  }
> >>  
> >> -static void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
> >> +void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu)
> >> +{
> >> +	vcpu->arch.pause = true;
> >> +	kvm_vcpu_kick(vcpu);
> >> +}
> >> +
> >> +void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
> >>  {
> >>  	struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
> >>  
> >> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> >> index fa94f91..38746d2 100644
> >> --- a/arch/arm64/include/asm/kvm_host.h
> >> +++ b/arch/arm64/include/asm/kvm_host.h
> >> @@ -329,6 +329,8 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
> >>  struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
> >>  void kvm_arm_halt_guest(struct kvm *kvm);
> >>  void kvm_arm_resume_guest(struct kvm *kvm);
> >> +void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu);
> >> +void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu);
> >>  
> >>  u64 __kvm_call_hyp(void *hypfn, ...);
> >>  #define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__)
> >> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
> >> index 4ef3571..059595e 100644
> >> --- a/virt/kvm/arm/vgic/vgic-mmio.c
> >> +++ b/virt/kvm/arm/vgic/vgic-mmio.c
> >> @@ -173,6 +173,66 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
> >>  	return value;
> >>  }
> >>  
> >> +static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
> >> +				    bool new_active_state)
> >> +{
> >> +	spin_lock(&irq->irq_lock);
> >> +	/*
> >> +	 * If this virtual IRQ was written into a list register, we
> >> +	 * have to make sure the CPU that runs the VCPU thread has
> >> +	 * synced back LR state to the struct vgic_irq.  We can only
> >> +	 * know this for sure, when either this irq is not assigned to
> >> +	 * anyone's AP list anymore, or the VCPU thread is not
> >> +	 * running on any CPUs.
> >> +	 *
> >> +	 * In the opposite case, we know the VCPU thread may be on its
> >> +	 * way back from the guest and still has to sync back this
> >> +	 * IRQ, so we release and re-acquire the spin_lock to let the
> >> +	 * other thread sync back the IRQ.
> >> +	 */
> >> +	while (irq->vcpu && /* IRQ may have state in an LR somewhere */
> >> +	       irq->vcpu->cpu != -1) { /* VCPU thread is running */
> >> +		BUG_ON(irq->intid < VGIC_NR_PRIVATE_IRQS);
> >> +		cond_resched_lock(&irq->irq_lock);
> >> +	}
> >> +
> >> +	irq->active = new_active_state;
> >> +	if (new_active_state)
> >> +		vgic_queue_irq_unlock(vcpu->kvm, irq);
> >> +	else
> >> +		spin_unlock(&irq->irq_lock);
> >> +}
> >> +
> >> +/*
> >> + * If we are fiddling with an IRQ's active state, we have to make sure the IRQ
> >> + * is not queued on some running VCPU's LRs, because then the change to the
> >> + * active state can be overwritten when the VCPU's state is synced coming back
> >> + * from the guest.
> >> + *
> >> + * For shared interrupts, we have to stop all the VCPUs because interrupts can
> >> + * be migrated while we don't hold the IRQ locks and we don't want to be
> >> + * chasing moving targets.
> >> + *
> >> + * For private interrupts, we only have to make sure the single and only VCPU
> >> + * that can potentially queue the IRQ is stopped.
> >> + */
> >> +static void vgic_change_active_prepare(struct kvm_vcpu *vcpu, u32 intid)
> >> +{
> >> +	if (intid < VGIC_NR_PRIVATE_IRQS)
> >> +		kvm_arm_halt_vcpu(vcpu);
> >> +	else
> >> +		kvm_arm_halt_guest(vcpu->kvm);
> >> +}
> >> +
> >> +/* See vgic_change_active_prepare */
> >> +static void vgic_change_active_finish(struct kvm_vcpu *vcpu, u32 intid)
> >> +{
> >> +	if (intid < VGIC_NR_PRIVATE_IRQS)
> >> +		kvm_arm_resume_vcpu(vcpu);
> >> +	else
> >> +		kvm_arm_resume_guest(vcpu->kvm);
> >> +}
> >> +
> >>  void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
> >>  			     gpa_t addr, unsigned int len,
> >>  			     unsigned long val)
> >> @@ -180,32 +240,12 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
> >>  	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
> >>  	int i;
> >>  
> >> -	kvm_arm_halt_guest(vcpu->kvm);
> >> +	vgic_change_active_prepare(vcpu, intid);
> > 
> > You're still only halting the current vcpu, not the one targeted by the
> > interrupt.
> > 
> > Let's not bother with that for the time being. I'm happy to merge v1,
> > and optimize this when this starts bugging us (and this is going to take
> > a while).
> 
> Actually, I now realize that you are right. The MMIO handler is passing
> us the target vcpu, not the the one causing the exit. I'm an idiot.

You are most certainly not.

> 
> So this looks fine to me.
> 

Cool, thanks.

-Christoffer


From christoffer.dall at linaro.org  Fri May 20 08:00:45 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 20 May 2016 17:00:45 +0200
Subject: [PATCH v4] KVM: arm/arm64: Add VGICv3 save/restore API documentation
Message-ID: <1463756445-26974-1-git-send-email-christoffer.dall@linaro.org>

Factor out the GICv3-specific documentation into a separate
documentation file.  Add description for how to access distributor,
redistributor, and CPU interface registers for GICv3 in this new file,
and add a group for accessing level triggered IRQ information for GICv3
as well.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
Changes since v2:
 - Changed distributor access to be 32-bits in size
 - Clearly specified data type pointed to by addr field
 - Specified exception behavior for STATUSR registers
 - Added group for level-triggered IRQ status info
 - Removed acks from Marc/Peter as content has changed

Changes since v3:
 - Fix typos
 - Clarified level register containing 32 IRQs
 - Removed limitations about priority support which are no longer true
 - Special-case the SPENDR register accesses to access the latch state
   and the CPENDR register accesses to be RAZ/WI.

 Documentation/virtual/kvm/devices/arm-vgic-v3.txt | 198 ++++++++++++++++++++++
 Documentation/virtual/kvm/devices/arm-vgic.txt    |  21 +--
 2 files changed, 202 insertions(+), 17 deletions(-)
 create mode 100644 Documentation/virtual/kvm/devices/arm-vgic-v3.txt

diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
new file mode 100644
index 0000000..3eed940
--- /dev/null
+++ b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
@@ -0,0 +1,198 @@
+ARM Virtual Generic Interrupt Controller v3 and later (VGICv3)
+==============================================================
+
+
+Device types supported:
+  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
+
+Only one VGIC instance may be instantiated through this API.  The created VGIC
+will act as the VM interrupt controller, requiring emulated user-space devices
+to inject interrupts to the VGIC instead of directly to CPUs.  It is not
+possible to create both a GICv3 and GICv2 on the same VM.
+
+Creating a guest GICv3 device requires a host GICv3 as well.
+
+Groups:
+  KVM_DEV_ARM_VGIC_GRP_ADDR
+  Attributes:
+    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
+      Base address in the guest physical address space of the GICv3 distributor
+      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
+      This address needs to be 64K aligned and the region covers 64 KByte.
+
+    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
+      Base address in the guest physical address space of the GICv3
+      redistributor register mappings. There are two 64K pages for each
+      VCPU and all of the redistributor pages are contiguous.
+      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
+      This address needs to be 64K aligned.
+
+
+  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
+  KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
+  Attributes:
+    The attr field of kvm_device_attr encodes two values:
+    bits:     | 63   ....  32  |  31   ....    0 |
+    values:   |      mpidr     |      offset     |
+
+    All distributor regs are (rw, 32-bit) and kvm_device_attr.addr points to a
+    __u32 value.  64-bit registers must be accessed by separately accessing the
+    lower and higher word.
+
+    Writes to read-only registers are ignored by the kernel.
+
+    KVM_DEV_ARM_VGIC_GRP_DIST_REGS accesses the main distributor registers.
+    KVM_DEV_ARM_VGIC_GRP_REDIST_REGS accesses the redistributor of the CPU
+    specified by the mpidr.
+
+    The offset is relative to the "[Re]Distributor base address" as defined
+    in the GICv3/4 specs.  Getting or setting such a register has the same
+    effect as reading or writing the register on real hardware, except for the
+    following registers: GICD_STATUSR, GICR_STATUSR, GICD_ISPENDR,
+    GICR_ISPENDR0, GICD_ICPENDR, and GICR_ICPENDR0.  These registers behave
+    differently when accessed via this interface compared to their
+    architecturally defined behavior to allow software a full view of the
+    VGIC's internal state.
+
+    The mpidr field is used to specify which
+    redistributor is accessed.  The mpidr is ignored for the distributor.
+
+    The mpidr encoding is based on the affinity information in the
+    architecture defined MPIDR, and the field is encoded as follows:
+      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
+      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
+
+    Note that distributor fields are not banked, but return the same value
+    regardless of the mpidr used to access the register.
+
+    The GICD_STATUSR and GICR_STATUSR registers are architecturally defined such
+    that a write of a clear bit has no effect, whereas a write with a set bit
+    clears that value.  To allow userspace to freely set the values of these two
+    registers, setting the attributes with the register offsets for these two
+    registers simply sets the non-reserved bits to the value written.
+
+
+    Accesses (reads and writes) to the GICD_ISPENDR register region and
+    GICR_ISPENDR0 registers get/set the value of the latched pending state for
+    the interrupts.
+
+    This is identical to the value read from ISPENDR for an edge triggered
+    interrupt, but may differ for level triggered interrupts. For edge triggered
+    interrupts, once an interrupt becomes pending (whether because of an edge
+    detected on the input line or because of a guest write to ISPENDR) this
+    state is "latched", and only cleared when either the interrupt is activated
+    or when the guest writes to ICPENDR. A level triggered interrupt may be
+    pending either because the level input is held high by a device, or because
+    of a guest write to the ISPENDR register. Only ISPENDR writes are latched;
+    if the device lowers the line level then the interrupt is no longer pending
+    unless the guest also wrote to ISPENDR, and conversely writes to ICPENDR or
+    activations of the interrupt do not clear the pending status if the line
+    level is still being held high.  (These rules are documented in the GICv3
+    specification descriptions of the ICPENDR and ISPENDR registers.)
+    For a level triggered interrupt the value accessed here
+    is that of the latch which is set by ISPENDR and cleared by ICPENDR or
+    interrupt activation, whereas the value read from ISPENDR is the logical OR
+    of the latch value and the input line level.
+
+    Raw access to the latch state is provided to userspace so that it can save
+    and restore the entire GIC internal state (which is defined by the
+    combination of the current input line level and the latch state, and cannot
+    be deduced from purely the line level and the value of the ISPENDR
+    registers).
+
+    Accesses to GICD_ICPENDR register region and GICR_ICPENDR0 registers have
+    RAZ/WI semantics, meaning that reads always return 0 and writes are always
+    ignored.
+
+  Errors:
+    -ENXIO: Getting or setting this register is not yet supported
+    -EBUSY: One or more VCPUs are running
+
+
+  KVM_DEV_ARM_VGIC_CPU_SYSREGS
+  Attributes:
+    The attr field of kvm_device_attr encodes two values:
+    bits:     | 63      ....       32 | 31  ....  16 | 15  ....  0 |
+    values:   |         mpidr         |      RES     |    instr    |
+
+    The mpidr field encodes the CPU ID based on the affinity information in the
+    architecture defined MPIDR, and the field is encoded as follows:
+      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
+      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
+
+    The instr field encodes the system register to access based on the fields
+    defined in the A64 instruction set encoding for system register access
+    (RES means the bits are reserved for future use and should be zero):
+
+      | 15 ... 14 | 13 ... 11 | 10 ... 7 | 6 ... 3 | 2 ... 0 |
+      |   Op 0    |    Op1    |    CRn   |   CRm   |   Op2   |
+
+    All system regs accessed through this API are (rw, 64-bit) and
+    kvm_device_attr.addr points to a __u64 value.
+
+    KVM_DEV_ARM_VGIC_CPU_SYSREGS accesses the CPU interface registers for the
+    CPU specified by the mpidr field.
+
+  Errors:
+    -ENXIO: Getting or setting this register is not yet supported
+    -EBUSY: VCPU is running
+    -EINVAL: Invalid mpidr supplied
+
+
+  KVM_DEV_ARM_VGIC_GRP_NR_IRQS
+  Attributes:
+    A value describing the number of interrupts (SGI, PPI and SPI) for
+    this GIC instance, ranging from 64 to 1024, in increments of 32.
+
+    kvm_device_attr.addr points to a __u32 value.
+
+  Errors:
+    -EINVAL: Value set is out of the expected range
+    -EBUSY: Value has already be set.
+
+
+  KVM_DEV_ARM_VGIC_GRP_CTRL
+  Attributes:
+    KVM_DEV_ARM_VGIC_CTRL_INIT
+      request the initialization of the VGIC, no additional parameter in
+      kvm_device_attr.addr.
+  Errors:
+    -ENXIO: VGIC not properly configured as required prior to calling
+     this attribute
+    -ENODEV: no online VCPU
+    -ENOMEM: memory shortage when allocating vgic internal data
+
+
+  KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO
+  Attributes:
+    The attr field of kvm_device_attr encodes the following values:
+    bits:     | 63      ....       32 | 31   ....    10 | 9  ....  0 |
+    values:   |         mpidr         |      info       |   vINTID   |
+
+    The vINTID specifies which set of IRQs is reported on.
+
+    The info field specifies which information userspace wants to get or set
+    using this interface.  Currently we support two different pieces of
+    information:
+
+      VGIC_LEVEL_INFO_LINE_LEVEL:
+	Get/Set the input level of the IRQ line for a set of 32 contiguously
+	numbered interrupts.
+	vINTID must be a multiple of 32.
+
+        kvm_device_attr.addr points to a __u32 value which will contain a
+	bitmap where a set bit means the interrupt level is asserted.
+
+	Bit[n] indicates the status for interrupt vINTID + n.
+
+    SGIs and any interrupt with a higher ID than the number of interrupts
+    supported, will be RAZ/WI.  LPIs are always edge-triggered and are
+    therefore not supported by this interface.
+
+    PPIs are reported per VCPU as specified in the mpidr field, and SPIs are
+    reported with the same value regardless of the mpidr specified.
+
+    The mpidr field encodes the CPU ID based on the affinity information in the
+    architecture defined MPIDR, and the field is encoded as follows:
+      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
+      |    Aff3    |    Aff2    |    Aff1    |    Aff0   |
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
index 59541d4..257b854 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic.txt
+++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
@@ -3,16 +3,16 @@ ARM Virtual Generic Interrupt Controller (VGIC)
 
 Device types supported:
   KVM_DEV_TYPE_ARM_VGIC_V2     ARM Generic Interrupt Controller v2.0
-  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
 
 Only one VGIC instance may be instantiated through either this API or the
 legacy KVM_CREATE_IRQCHIP api.  The created VGIC will act as the VM interrupt
 controller, requiring emulated user-space devices to inject interrupts to the
 VGIC instead of directly to CPUs.
 
-Creating a guest GICv3 device requires a host GICv3 as well.
-GICv3 implementations with hardware compatibility support allow a guest GICv2
-as well.
+GICv3 implementations with hardware compatibility support allow creating a
+guest GICv2 through this interface.  For information on creating a guest GICv3
+device, see arm-vgic-v3.txt.  It is not possible to create both a GICv3 and
+GICv2 device on the same VM.
 
 Groups:
   KVM_DEV_ARM_VGIC_GRP_ADDR
@@ -27,19 +27,6 @@ Groups:
       interface register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2.
       This address needs to be 4K aligned and the region covers 4 KByte.
 
-    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
-      Base address in the guest physical address space of the GICv3 distributor
-      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
-      This address needs to be 64K aligned and the region covers 64 KByte.
-
-    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
-      Base address in the guest physical address space of the GICv3
-      redistributor register mappings. There are two 64K pages for each
-      VCPU and all of the redistributor pages are contiguous.
-      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
-      This address needs to be 64K aligned.
-
-
   KVM_DEV_ARM_VGIC_GRP_DIST_REGS
   Attributes:
     The attr field of kvm_device_attr encodes two values:
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Fri May 20 08:04:25 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Fri, 20 May 2016 17:04:25 +0200
Subject: [PATCH v5 00/57] KVM: arm/arm64: Rework virtual GIC emulation
In-Reply-To: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
References: <1463681316-23039-1-git-send-email-andre.przywara@arm.com>
Message-ID: <20160520150425.GC10370@cbox>

On Thu, May 19, 2016 at 07:07:39PM +0100, Andre Przywara wrote:
> Hi,
> 
> hopefully the final version of the new VGIC series.
> Again mostly smaller fixes: A new patch (8/57) to establish the
> arch timer <-> VGIC connection later in the init process, to avoid
> calls to VGIC code before the VGIC is actually initialized.
> Also we now make sure that no VCPU is running while userland accesses
> the VGIC registers. The set-active-bit code has been slightly adjusted
> to cover a corner case as well. Last, but not least we now properly
> annotate our lock nesting so the kernel is happy now even with
> CONFIG_SPINLOCK_DEBUG enabled.
> More detailed changelog in the patches.
> 
> As this new VGIC emulation will probably become the default very shortly,
> please test it full steam on whatever setup you have access to.
> Any reports are warmly welcome.
> 
> As v4, this series is based on kvmarm/next, which will be merged
> shortly into Linus' kernel.
> A git tree containing this series can be found on linux-arm.org:
> 
> git://linux-arm.org/linux-ap.git	branch: vgic-new/v5
> http://www.linux-arm.org/git?p=linux-ap.git;a=log;h=refs/heads/vgic-new/v5
> 

Applied, huge thanks for all this work to all participants!

-Christoffer


From yt.shen at mediatek.com  Fri May 20 08:05:31 2016
From: yt.shen at mediatek.com (yt.shen at mediatek.com)
Date: Fri, 20 May 2016 23:05:31 +0800
Subject: [RFC v2 0/5] MT2701 DRM support
Message-ID: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>

From: YT Shen <yt.shen at mediatek.com>

This is MT2701 DRM support RFC, based on MT8173 DRM patch v16.
Most codes are the same, except some register changed.

For example:
 - DISP_OVL address offset changed, color format definition changed.
 - DISP_RDMA fifo size changed.
 - DISP_COLOR offset changed.

We add a new component DISP_BLS, and the connection settings are updated.
And we have shadow register support in MT2701.

Changes since v1:
- Removed BLS bindings and codes, which belong to pwm driver
- Moved mtk_disp_mutex_acquire() just before mtk_crtc_ddp_config()
- Split patch into smaller parts
- Added const keyword to constant structure
- Removed codes for special memory align

The RFC depends on MT2701 iommu/smi driver.
https://patchwork.kernel.org/patch/9043411/ ("dt-bindings: mediatek: add descriptions for mediatek mt2701 iommu and smi"),
https://patchwork.kernel.org/patch/9043391/ ("iommu/mediatek: move the common struct into header file"),
https://patchwork.kernel.org/patch/9043421/ ("memory/mediatek: add support for mt2701"),
https://patchwork.kernel.org/patch/9043451/ ("iommu/mediatek: add support for mtk iommu generation one HW"),
https://patchwork.kernel.org/patch/9043471/ ("ARM: dts: mt2701: add iommu/smi dtsi node for mt2701"),

Thanks,
yt.shen

YT Shen (5):
  drm/mediatek: rename macros, add chip suffix
  drm/mediatke: add support for Mediatek SoC MT2701
  drm/mediatek: add *driver_data for different hardware settings
  drm/mediatek: add shadow register support
  arm: dts: mt2701: Add display subsystem related nodes for MT2701

 arch/arm/boot/dts/mt2701.dtsi               |  117 +++++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c     |   49 ++++++---
 drivers/gpu/drm/mediatek/mtk_disp_rdma.c    |   36 +++++--
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c     |   75 ++++++++-----
 drivers/gpu/drm/mediatek/mtk_drm_ddp.c      |  151 ++++++++++++++++++++-------
 drivers/gpu/drm/mediatek/mtk_drm_ddp.h      |    2 +
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c |   42 ++++++--
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |   15 +++
 drivers/gpu/drm/mediatek/mtk_drm_drv.c      |   72 +++++++++++--
 drivers/gpu/drm/mediatek/mtk_drm_drv.h      |    9 ++
 10 files changed, 462 insertions(+), 106 deletions(-)

-- 
1.7.9.5



From yt.shen at mediatek.com  Fri May 20 08:05:32 2016
From: yt.shen at mediatek.com (yt.shen at mediatek.com)
Date: Fri, 20 May 2016 23:05:32 +0800
Subject: [RFC v2 1/5] drm/mediatek: rename macros, add chip suffix
In-Reply-To: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
Message-ID: <1463756736-46573-2-git-send-email-yt.shen@mediatek.com>

From: YT Shen <yt.shen at mediatek.com>

Add MT8173 suffix for hardware related macros.

Signed-off-by: YT Shen <yt.shen at mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_drm_ddp.c |   62 ++++++++++++++++----------------
 1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index 17ba935..d6aafd4 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -36,21 +36,21 @@
 #define DISP_REG_MUTEX_MOD(n)	(0x2c + 0x20 * (n))
 #define DISP_REG_MUTEX_SOF(n)	(0x30 + 0x20 * (n))
 
-#define MUTEX_MOD_DISP_OVL0		BIT(11)
-#define MUTEX_MOD_DISP_OVL1		BIT(12)
-#define MUTEX_MOD_DISP_RDMA0		BIT(13)
-#define MUTEX_MOD_DISP_RDMA1		BIT(14)
-#define MUTEX_MOD_DISP_RDMA2		BIT(15)
-#define MUTEX_MOD_DISP_WDMA0		BIT(16)
-#define MUTEX_MOD_DISP_WDMA1		BIT(17)
-#define MUTEX_MOD_DISP_COLOR0		BIT(18)
-#define MUTEX_MOD_DISP_COLOR1		BIT(19)
-#define MUTEX_MOD_DISP_AAL		BIT(20)
-#define MUTEX_MOD_DISP_GAMMA		BIT(21)
-#define MUTEX_MOD_DISP_UFOE		BIT(22)
-#define MUTEX_MOD_DISP_PWM0		BIT(23)
-#define MUTEX_MOD_DISP_PWM1		BIT(24)
-#define MUTEX_MOD_DISP_OD		BIT(25)
+#define MUTEX_MOD_DISP_OVL0_MT8173		BIT(11)
+#define MUTEX_MOD_DISP_OVL1_MT8173		BIT(12)
+#define MUTEX_MOD_DISP_RDMA0_MT8173		BIT(13)
+#define MUTEX_MOD_DISP_RDMA1_MT8173		BIT(14)
+#define MUTEX_MOD_DISP_RDMA2_MT8173		BIT(15)
+#define MUTEX_MOD_DISP_WDMA0_MT8173		BIT(16)
+#define MUTEX_MOD_DISP_WDMA1_MT8173		BIT(17)
+#define MUTEX_MOD_DISP_COLOR0_MT8173		BIT(18)
+#define MUTEX_MOD_DISP_COLOR1_MT8173		BIT(19)
+#define MUTEX_MOD_DISP_AAL_MT8173		BIT(20)
+#define MUTEX_MOD_DISP_GAMMA_MT8173		BIT(21)
+#define MUTEX_MOD_DISP_UFOE_MT8173		BIT(22)
+#define MUTEX_MOD_DISP_PWM0_MT8173		BIT(23)
+#define MUTEX_MOD_DISP_PWM1_MT8173		BIT(24)
+#define MUTEX_MOD_DISP_OD_MT8173		BIT(25)
 
 #define MUTEX_SOF_SINGLE_MODE		0
 #define MUTEX_SOF_DSI0			1
@@ -79,22 +79,22 @@ struct mtk_ddp {
 	struct mtk_disp_mutex		mutex[10];
 };
 
-static const unsigned int mutex_mod[DDP_COMPONENT_ID_MAX] = {
-	[DDP_COMPONENT_AAL] = MUTEX_MOD_DISP_AAL,
-	[DDP_COMPONENT_COLOR0] = MUTEX_MOD_DISP_COLOR0,
-	[DDP_COMPONENT_COLOR1] = MUTEX_MOD_DISP_COLOR1,
-	[DDP_COMPONENT_GAMMA] = MUTEX_MOD_DISP_GAMMA,
-	[DDP_COMPONENT_OD] = MUTEX_MOD_DISP_OD,
-	[DDP_COMPONENT_OVL0] = MUTEX_MOD_DISP_OVL0,
-	[DDP_COMPONENT_OVL1] = MUTEX_MOD_DISP_OVL1,
-	[DDP_COMPONENT_PWM0] = MUTEX_MOD_DISP_PWM0,
-	[DDP_COMPONENT_PWM1] = MUTEX_MOD_DISP_PWM1,
-	[DDP_COMPONENT_RDMA0] = MUTEX_MOD_DISP_RDMA0,
-	[DDP_COMPONENT_RDMA1] = MUTEX_MOD_DISP_RDMA1,
-	[DDP_COMPONENT_RDMA2] = MUTEX_MOD_DISP_RDMA2,
-	[DDP_COMPONENT_UFOE] = MUTEX_MOD_DISP_UFOE,
-	[DDP_COMPONENT_WDMA0] = MUTEX_MOD_DISP_WDMA0,
-	[DDP_COMPONENT_WDMA1] = MUTEX_MOD_DISP_WDMA1,
+static const unsigned int mutex_mod_mt8173[DDP_COMPONENT_ID_MAX] = {
+	[DDP_COMPONENT_AAL] = MUTEX_MOD_DISP_AAL_MT8173,
+	[DDP_COMPONENT_COLOR0] = MUTEX_MOD_DISP_COLOR0_MT8173,
+	[DDP_COMPONENT_COLOR1] = MUTEX_MOD_DISP_COLOR1_MT8173,
+	[DDP_COMPONENT_GAMMA] = MUTEX_MOD_DISP_GAMMA_MT8173,
+	[DDP_COMPONENT_OD] = MUTEX_MOD_DISP_OD_MT8173,
+	[DDP_COMPONENT_OVL0] = MUTEX_MOD_DISP_OVL0_MT8173,
+	[DDP_COMPONENT_OVL1] = MUTEX_MOD_DISP_OVL1_MT8173,
+	[DDP_COMPONENT_PWM0] = MUTEX_MOD_DISP_PWM0_MT8173,
+	[DDP_COMPONENT_PWM1] = MUTEX_MOD_DISP_PWM1_MT8173,
+	[DDP_COMPONENT_RDMA0] = MUTEX_MOD_DISP_RDMA0_MT8173,
+	[DDP_COMPONENT_RDMA1] = MUTEX_MOD_DISP_RDMA1_MT8173,
+	[DDP_COMPONENT_RDMA2] = MUTEX_MOD_DISP_RDMA2_MT8173,
+	[DDP_COMPONENT_UFOE] = MUTEX_MOD_DISP_UFOE_MT8173,
+	[DDP_COMPONENT_WDMA0] = MUTEX_MOD_DISP_WDMA0_MT8173,
+	[DDP_COMPONENT_WDMA1] = MUTEX_MOD_DISP_WDMA1_MT8173,
 };
 
 static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
-- 
1.7.9.5



From yt.shen at mediatek.com  Fri May 20 08:05:33 2016
From: yt.shen at mediatek.com (yt.shen at mediatek.com)
Date: Fri, 20 May 2016 23:05:33 +0800
Subject: [RFC v2 2/5] drm/mediatke: add support for Mediatek SoC MT2701
In-Reply-To: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
Message-ID: <1463756736-46573-3-git-send-email-yt.shen@mediatek.com>

From: YT Shen <yt.shen at mediatek.com>

This patch add support for the Mediatek MT2701 DISP subsystem.
There is only one OVL engine in MT2701.

Signed-off-by: YT Shen <yt.shen at mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_drm_ddp.c      |   63 +++++++++++++++++++++---
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c |    2 +
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |    2 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.c      |   70 ++++++++++++++++++++++-----
 drivers/gpu/drm/mediatek/mtk_drm_drv.h      |    8 +++
 5 files changed, 126 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index d6aafd4..529569d 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -31,6 +31,10 @@
 #define DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN	0x0c8
 #define DISP_REG_CONFIG_MMSYS_CG_CON0		0x100
 
+#define DISP_REG_CONFIG_DISP_OVL_MOUT_EN	0x030
+#define DISP_REG_CONFIG_OUT_SEL			0x04c
+#define DISP_REG_CONFIG_DSI_SEL			0x050
+
 #define DISP_REG_MUTEX_EN(n)	(0x20 + 0x20 * (n))
 #define DISP_REG_MUTEX_RST(n)	(0x28 + 0x20 * (n))
 #define DISP_REG_MUTEX_MOD(n)	(0x2c + 0x20 * (n))
@@ -52,6 +56,13 @@
 #define MUTEX_MOD_DISP_PWM1_MT8173		BIT(24)
 #define MUTEX_MOD_DISP_OD_MT8173		BIT(25)
 
+#define MUTEX_MOD_DISP_OVL_MT2701		BIT(3)
+#define MUTEX_MOD_DISP_WDMA_MT2701		BIT(6)
+#define MUTEX_MOD_DISP_COLOR_MT2701		BIT(7)
+#define MUTEX_MOD_DISP_BLS_MT2701		BIT(9)
+#define MUTEX_MOD_DISP_RDMA0_MT2701		BIT(10)
+#define MUTEX_MOD_DISP_RDMA1_MT2701		BIT(12)
+
 #define MUTEX_SOF_SINGLE_MODE		0
 #define MUTEX_SOF_DSI0			1
 #define MUTEX_SOF_DSI1			2
@@ -67,6 +78,10 @@
 #define DPI0_SEL_IN_RDMA1		0x1
 #define COLOR1_SEL_IN_OVL1		0x1
 
+#define OVL_MOUT_EN_RDMA		0x1
+#define BLS_TO_DSI_RDMA1_TO_DPI1	0x8
+#define DSI_SEL_IN_BLS			0x0
+
 struct mtk_disp_mutex {
 	int id;
 	bool claimed;
@@ -77,6 +92,16 @@ struct mtk_ddp {
 	struct clk			*clk;
 	void __iomem			*regs;
 	struct mtk_disp_mutex		mutex[10];
+	const unsigned int		*mutex_mod;
+};
+
+static const unsigned int mutex_mod_mt2701[DDP_COMPONENT_ID_MAX] = {
+	[DDP_COMPONENT_BLS] = MUTEX_MOD_DISP_BLS_MT2701,
+	[DDP_COMPONENT_COLOR0] = MUTEX_MOD_DISP_COLOR_MT2701,
+	[DDP_COMPONENT_OVL0] = MUTEX_MOD_DISP_OVL_MT2701,
+	[DDP_COMPONENT_RDMA0] = MUTEX_MOD_DISP_RDMA0_MT2701,
+	[DDP_COMPONENT_RDMA1] = MUTEX_MOD_DISP_RDMA1_MT2701,
+	[DDP_COMPONENT_WDMA0] = MUTEX_MOD_DISP_WDMA_MT2701,
 };
 
 static const unsigned int mutex_mod_mt8173[DDP_COMPONENT_ID_MAX] = {
@@ -106,6 +131,9 @@ static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
 	if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
 		*addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN;
 		value = OVL0_MOUT_EN_COLOR0;
+	} else if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_RDMA0) {
+		*addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN;
+		value = OVL_MOUT_EN_RDMA;
 	} else if (cur == DDP_COMPONENT_OD && next == DDP_COMPONENT_RDMA0) {
 		*addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
 		value = OD_MOUT_EN_RDMA0;
@@ -143,6 +171,9 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,
 	} else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
 		*addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN;
 		value = COLOR1_SEL_IN_OVL1;
+	} else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
+		*addr = DISP_REG_CONFIG_DSI_SEL;
+		value = DSI_SEL_IN_BLS;
 	} else {
 		value = 0;
 	}
@@ -150,6 +181,15 @@ static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,
 	return value;
 }
 
+static void mtk_ddp_mux_sel(void __iomem *config_regs,
+			    enum mtk_ddp_comp_id cur, enum mtk_ddp_comp_id next)
+{
+	if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
+		writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1,
+			       config_regs + DISP_REG_CONFIG_OUT_SEL);
+	}
+}
+
 void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
 			      enum mtk_ddp_comp_id cur,
 			      enum mtk_ddp_comp_id next)
@@ -162,6 +202,8 @@ void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
 		writel_relaxed(reg, config_regs + addr);
 	}
 
+	mtk_ddp_mux_sel(config_regs, cur, next);
+
 	value = mtk_ddp_sel_in(cur, next, &addr);
 	if (value) {
 		reg = readl_relaxed(config_regs + addr) | value;
@@ -247,7 +289,7 @@ void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
 		break;
 	default:
 		reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
-		reg |= mutex_mod[id];
+		reg |= ddp->mutex_mod[id];
 		writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
 		return;
 	}
@@ -273,7 +315,7 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
 		break;
 	default:
 		reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
-		reg &= ~mutex_mod[id];
+		reg &= ~(ddp->mutex_mod[id]);
 		writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
 		break;
 	}
@@ -299,8 +341,16 @@ void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex)
 	writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
 }
 
+static const struct of_device_id ddp_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt2701-disp-mutex", .data = mutex_mod_mt2701},
+	{ .compatible = "mediatek,mt8173-disp-mutex", .data = mutex_mod_mt8173},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
+
 static int mtk_ddp_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *of_id;
 	struct device *dev = &pdev->dev;
 	struct mtk_ddp *ddp;
 	struct resource *regs;
@@ -326,6 +376,9 @@ static int mtk_ddp_probe(struct platform_device *pdev)
 		return PTR_ERR(ddp->regs);
 	}
 
+	of_id = of_match_device(ddp_driver_dt_match, &pdev->dev);
+	ddp->mutex_mod = of_id->data;
+
 	platform_set_drvdata(pdev, ddp);
 
 	return 0;
@@ -336,12 +389,6 @@ static int mtk_ddp_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id ddp_driver_dt_match[] = {
-	{ .compatible = "mediatek,mt8173-disp-mutex" },
-	{},
-};
-MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
-
 struct platform_driver mtk_ddp_driver = {
 	.probe		= mtk_ddp_probe,
 	.remove		= mtk_ddp_remove,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 3970fcf..0360fd6 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -103,6 +103,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
 	[MTK_DISP_PWM] = "pwm",
 	[MTK_DISP_MUTEX] = "mutex",
 	[MTK_DISP_OD] = "od",
+	[MTK_DISP_BLS] = "bls",
 };
 
 struct mtk_ddp_comp_match {
@@ -113,6 +114,7 @@ struct mtk_ddp_comp_match {
 
 static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
 	[DDP_COMPONENT_AAL]	= { MTK_DISP_AAL,	0, NULL },
+	[DDP_COMPONENT_BLS]	= { MTK_DISP_BLS,	0, NULL },
 	[DDP_COMPONENT_COLOR0]	= { MTK_DISP_COLOR,	0, &ddp_color },
 	[DDP_COMPONENT_COLOR1]	= { MTK_DISP_COLOR,	1, &ddp_color },
 	[DDP_COMPONENT_DPI0]	= { MTK_DPI,		0, NULL },
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index 6b13ba9..1c344e4 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -35,6 +35,7 @@ enum mtk_ddp_comp_type {
 	MTK_DISP_PWM,
 	MTK_DISP_MUTEX,
 	MTK_DISP_OD,
+	MTK_DISP_BLS,
 	MTK_DDP_COMP_TYPE_MAX,
 };
 
@@ -57,6 +58,7 @@ enum mtk_ddp_comp_id {
 	DDP_COMPONENT_UFOE,
 	DDP_COMPONENT_WDMA0,
 	DDP_COMPONENT_WDMA1,
+	DDP_COMPONENT_BLS,
 	DDP_COMPONENT_ID_MAX,
 };
 
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 2774cbd..8b562ab 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -109,7 +109,20 @@ static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = {
 	.atomic_commit = mtk_atomic_commit,
 };
 
-static const enum mtk_ddp_comp_id mtk_ddp_main[] = {
+static const enum mtk_ddp_comp_id mtk_ddp_main_2701[] = {
+	DDP_COMPONENT_OVL0,
+	DDP_COMPONENT_RDMA0,
+	DDP_COMPONENT_COLOR0,
+	DDP_COMPONENT_BLS,
+	DDP_COMPONENT_DSI0,
+};
+
+static const enum mtk_ddp_comp_id mtk_ddp_ext_2701[] = {
+	DDP_COMPONENT_OVL0,
+	DDP_COMPONENT_DSI0,
+};
+
+static const enum mtk_ddp_comp_id mtk_ddp_main_8173[] = {
 	DDP_COMPONENT_OVL0,
 	DDP_COMPONENT_COLOR0,
 	DDP_COMPONENT_AAL,
@@ -120,7 +133,7 @@ static const enum mtk_ddp_comp_id mtk_ddp_main[] = {
 	DDP_COMPONENT_PWM0,
 };
 
-static const enum mtk_ddp_comp_id mtk_ddp_ext[] = {
+static const enum mtk_ddp_comp_id mtk_ddp_ext_8173[] = {
 	DDP_COMPONENT_OVL1,
 	DDP_COMPONENT_COLOR1,
 	DDP_COMPONENT_GAMMA,
@@ -128,6 +141,20 @@ static const enum mtk_ddp_comp_id mtk_ddp_ext[] = {
 	DDP_COMPONENT_DPI0,
 };
 
+static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
+	.main_path = mtk_ddp_main_2701,
+	.main_len = ARRAY_SIZE(mtk_ddp_main_2701),
+	.ext_path = mtk_ddp_ext_2701,
+	.ext_len = ARRAY_SIZE(mtk_ddp_ext_2701),
+};
+
+static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
+	.main_path = mtk_ddp_main_8173,
+	.main_len = ARRAY_SIZE(mtk_ddp_main_8173),
+	.ext_path = mtk_ddp_ext_8173,
+	.ext_len = ARRAY_SIZE(mtk_ddp_ext_8173),
+};
+
 static int mtk_drm_kms_init(struct drm_device *drm)
 {
 	struct mtk_drm_private *private = drm->dev_private;
@@ -170,17 +197,19 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 	 * and each statically assigned to a crtc:
 	 * OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ...
 	 */
-	ret = mtk_drm_crtc_create(drm, mtk_ddp_main, ARRAY_SIZE(mtk_ddp_main));
+	ret = mtk_drm_crtc_create(drm, private->data->main_path,
+				  private->data->main_len);
 	if (ret < 0)
 		goto err_component_unbind;
 	/* ... and OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0. */
-	ret = mtk_drm_crtc_create(drm, mtk_ddp_ext, ARRAY_SIZE(mtk_ddp_ext));
+	ret = mtk_drm_crtc_create(drm, private->data->ext_path,
+				  private->data->ext_len);
 	if (ret < 0)
 		goto err_component_unbind;
 
 	/* Use OVL device for all DMA memory allocations */
-	np = private->comp_node[mtk_ddp_main[0]] ?:
-	     private->comp_node[mtk_ddp_ext[0]];
+	np = private->comp_node[private->data->main_path[0]] ?:
+	     private->comp_node[private->data->ext_path[0]];
 	pdev = of_find_device_by_node(np);
 	if (!pdev) {
 		ret = -ENODEV;
@@ -316,21 +345,44 @@ static const struct component_master_ops mtk_drm_ops = {
 };
 
 static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
+	{ .compatible = "mediatek,mt2701-disp-ovl",   .data = (void *)MTK_DISP_OVL },
 	{ .compatible = "mediatek,mt8173-disp-ovl",   .data = (void *)MTK_DISP_OVL },
+	{ .compatible = "mediatek,mt2701-disp-rdma",  .data = (void *)MTK_DISP_RDMA },
 	{ .compatible = "mediatek,mt8173-disp-rdma",  .data = (void *)MTK_DISP_RDMA },
+	{ .compatible = "mediatek,mt2701-disp-wdma",  .data = (void *)MTK_DISP_WDMA },
 	{ .compatible = "mediatek,mt8173-disp-wdma",  .data = (void *)MTK_DISP_WDMA },
+	{ .compatible = "mediatek,mt2701-disp-color", .data = (void *)MTK_DISP_COLOR },
 	{ .compatible = "mediatek,mt8173-disp-color", .data = (void *)MTK_DISP_COLOR },
 	{ .compatible = "mediatek,mt8173-disp-aal",   .data = (void *)MTK_DISP_AAL},
 	{ .compatible = "mediatek,mt8173-disp-gamma", .data = (void *)MTK_DISP_GAMMA, },
 	{ .compatible = "mediatek,mt8173-disp-ufoe",  .data = (void *)MTK_DISP_UFOE },
+	{ .compatible = "mediatek,mt2701-dsi",	      .data = (void *)MTK_DSI },
 	{ .compatible = "mediatek,mt8173-dsi",        .data = (void *)MTK_DSI },
+	{ .compatible = "mediatek,mt2701-dpi",	      .data = (void *)MTK_DPI },
 	{ .compatible = "mediatek,mt8173-dpi",        .data = (void *)MTK_DPI },
+	{ .compatible = "mediatek,mt2701-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
 	{ .compatible = "mediatek,mt8173-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
 	{ .compatible = "mediatek,mt8173-disp-pwm",   .data = (void *)MTK_DISP_PWM },
 	{ .compatible = "mediatek,mt8173-disp-od",    .data = (void *)MTK_DISP_OD },
+	{ .compatible = "mediatek,mt2701-disp-bls",   .data = (void *)MTK_DISP_BLS },
 	{ }
 };
 
+static const struct of_device_id mtk_drm_of_ids[] = {
+	{ .compatible = "mediatek,mt2701-mmsys", .data = &mt2701_mmsys_driver_data},
+	{ .compatible = "mediatek,mt8173-mmsys", .data = &mt8173_mmsys_driver_data},
+	{ }
+};
+
+static inline struct mtk_mmsys_driver_data *mtk_drm_get_driver_data(
+	struct platform_device *pdev)
+{
+	const struct of_device_id *of_id =
+		of_match_device(mtk_drm_of_ids, &pdev->dev);
+
+	return (struct mtk_mmsys_driver_data *)of_id->data;
+}
+
 static int mtk_drm_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -347,6 +399,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
 
 	mutex_init(&private->commit.lock);
 	INIT_WORK(&private->commit.work, mtk_atomic_work);
+	private->data = mtk_drm_get_driver_data(pdev);
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	private->config_regs = devm_ioremap_resource(dev, mem);
@@ -497,11 +550,6 @@ static int mtk_drm_sys_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops, mtk_drm_sys_suspend,
 			 mtk_drm_sys_resume);
 
-static const struct of_device_id mtk_drm_of_ids[] = {
-	{ .compatible = "mediatek,mt8173-mmsys", },
-	{ }
-};
-
 static struct platform_driver mtk_drm_platform_driver = {
 	.probe	= mtk_drm_probe,
 	.remove	= mtk_drm_remove,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index aa93894..fa0b106 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -28,6 +28,13 @@ struct drm_fb_helper;
 struct drm_property;
 struct regmap;
 
+struct mtk_mmsys_driver_data {
+	const enum mtk_ddp_comp_id *main_path;
+	unsigned int main_len;
+	const enum mtk_ddp_comp_id *ext_path;
+	unsigned int ext_len;
+};
+
 struct mtk_drm_private {
 	struct drm_device *drm;
 	struct device *dma_dev;
@@ -40,6 +47,7 @@ struct mtk_drm_private {
 	void __iomem *config_regs;
 	struct device_node *comp_node[DDP_COMPONENT_ID_MAX];
 	struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX];
+	const struct mtk_mmsys_driver_data *data;
 
 	struct {
 		struct drm_atomic_state *state;
-- 
1.7.9.5



From yt.shen at mediatek.com  Fri May 20 08:05:34 2016
From: yt.shen at mediatek.com (yt.shen at mediatek.com)
Date: Fri, 20 May 2016 23:05:34 +0800
Subject: [RFC v2 3/5] drm/mediatek: add *driver_data for different hardware
 settings
In-Reply-To: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
Message-ID: <1463756736-46573-4-git-send-email-yt.shen@mediatek.com>

From: YT Shen <yt.shen at mediatek.com>

There are some hardware settings changed, between MT8173 & MT2701:
DISP_OVL address offset changed, color format definition changed.
DISP_RDMA fifo size changed.
DISP_COLOR offset changed.

Signed-off-by: YT Shen <yt.shen at mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_disp_ovl.c     |   49 +++++++++++++++++++--------
 drivers/gpu/drm/mediatek/mtk_disp_rdma.c    |   36 ++++++++++++++++----
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c |   40 ++++++++++++++++++----
 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |   13 +++++++
 4 files changed, 111 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 8f62671f..8d2811d 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -40,8 +40,6 @@
 #define	OVL_RDMA_MEM_GMC	0x40402020
 
 #define OVL_CON_BYTE_SWAP	BIT(24)
-#define OVL_CON_CLRFMT_RGB565	(0 << 12)
-#define OVL_CON_CLRFMT_RGB888	(1 << 12)
 #define OVL_CON_CLRFMT_RGBA8888	(2 << 12)
 #define OVL_CON_CLRFMT_ARGB8888	(3 << 12)
 #define	OVL_CON_AEN		BIT(8)
@@ -136,18 +134,18 @@ static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx)
 	writel(0x0, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx));
 }
 
-static unsigned int ovl_fmt_convert(unsigned int fmt)
+static unsigned int ovl_fmt_convert(struct mtk_ddp_comp *comp, unsigned int fmt)
 {
 	switch (fmt) {
 	default:
 	case DRM_FORMAT_RGB565:
-		return OVL_CON_CLRFMT_RGB565;
+		return comp->data->ovl.fmt_rgb565;
 	case DRM_FORMAT_BGR565:
-		return OVL_CON_CLRFMT_RGB565 | OVL_CON_BYTE_SWAP;
+		return comp->data->ovl.fmt_rgb565 | OVL_CON_BYTE_SWAP;
 	case DRM_FORMAT_RGB888:
-		return OVL_CON_CLRFMT_RGB888;
+		return comp->data->ovl.fmt_rgb888;
 	case DRM_FORMAT_BGR888:
-		return OVL_CON_CLRFMT_RGB888 | OVL_CON_BYTE_SWAP;
+		return comp->data->ovl.fmt_rgb888 | OVL_CON_BYTE_SWAP;
 	case DRM_FORMAT_RGBX8888:
 	case DRM_FORMAT_RGBA8888:
 		return OVL_CON_CLRFMT_ARGB8888;
@@ -177,7 +175,7 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
 	if (!pending->enable)
 		mtk_ovl_layer_off(comp, idx);
 
-	con = ovl_fmt_convert(fmt);
+	con = ovl_fmt_convert(comp, fmt);
 	if (idx != 0)
 		con |= OVL_CON_AEN | OVL_CON_ALPHA;
 
@@ -185,7 +183,7 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
 	writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx));
 	writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx));
 	writel_relaxed(offset, comp->regs + DISP_REG_OVL_OFFSET(idx));
-	writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(idx));
+	writel_relaxed(addr, comp->regs + (comp->data->ovl.addr_offset + idx * 0x20));
 
 	if (pending->enable)
 		mtk_ovl_layer_on(comp, idx);
@@ -233,6 +231,32 @@ static const struct component_ops mtk_disp_ovl_component_ops = {
 	.unbind = mtk_disp_ovl_unbind,
 };
 
+static const struct mtk_ddp_comp_driver_data mt2701_ovl_driver_data = {
+	.ovl = {0x0040, 1 << 12, 0}
+};
+
+static const struct mtk_ddp_comp_driver_data mt8173_ovl_driver_data = {
+	.ovl = {0x0f40, 0, 1 << 12}
+};
+
+static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt2701-disp-ovl",
+	  .data = &mt2701_ovl_driver_data},
+	{ .compatible = "mediatek,mt8173-disp-ovl",
+	  .data = &mt8173_ovl_driver_data},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
+
+static inline struct mtk_ddp_comp_driver_data *mtk_ovl_get_driver_data(
+	struct platform_device *pdev)
+{
+	const struct of_device_id *of_id =
+		of_match_device(mtk_disp_ovl_driver_dt_match, &pdev->dev);
+
+	return (struct mtk_ddp_comp_driver_data *)of_id->data;
+}
+
 static int mtk_disp_ovl_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -269,6 +293,8 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	priv->ddp_comp.data = mtk_ovl_get_driver_data(pdev);
+
 	platform_set_drvdata(pdev, priv);
 
 	ret = component_add(dev, &mtk_disp_ovl_component_ops);
@@ -285,11 +311,6 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
-	{ .compatible = "mediatek,mt8173-disp-ovl", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
 
 struct platform_driver mtk_disp_ovl_driver = {
 	.probe		= mtk_disp_ovl_probe,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index 5fb80cb..a20a6cd 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -122,7 +122,7 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width,
 	 */
 	threshold = width * height * vrefresh * 4 * 7 / 1000000;
 	reg = RDMA_FIFO_UNDERFLOW_EN |
-	      RDMA_FIFO_PSEUDO_SIZE(SZ_8K) |
+	      RDMA_FIFO_PSEUDO_SIZE(comp->data->rdma_fifo_pseudo_size) |
 	      RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold);
 	writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON);
 }
@@ -167,6 +167,32 @@ static const struct component_ops mtk_disp_rdma_component_ops = {
 	.unbind = mtk_disp_rdma_unbind,
 };
 
+static const struct mtk_ddp_comp_driver_data mt2701_rdma_driver_data = {
+	.rdma_fifo_pseudo_size = SZ_4K,
+};
+
+static const struct mtk_ddp_comp_driver_data mt8173_rdma_driver_data = {
+	.rdma_fifo_pseudo_size = SZ_8K,
+};
+
+static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt2701-disp-rdma",
+	  .data = &mt2701_rdma_driver_data},
+	{ .compatible = "mediatek,mt8173-disp-rdma",
+	  .data = &mt8173_rdma_driver_data},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
+
+static inline struct mtk_ddp_comp_driver_data *mtk_rdma_get_driver_data(
+	struct platform_device *pdev)
+{
+	const struct of_device_id *of_id =
+		of_match_device(mtk_disp_rdma_driver_dt_match, &pdev->dev);
+
+	return (struct mtk_ddp_comp_driver_data *)of_id->data;
+}
+
 static int mtk_disp_rdma_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -196,6 +222,8 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	priv->ddp_comp.data = mtk_rdma_get_driver_data(pdev);
+
 	/* Disable and clear pending interrupts */
 	writel(0x0, priv->ddp_comp.regs + DISP_REG_RDMA_INT_ENABLE);
 	writel(0x0, priv->ddp_comp.regs + DISP_REG_RDMA_INT_STATUS);
@@ -223,12 +251,6 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
-	{ .compatible = "mediatek,mt8173-disp-rdma", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
-
 struct platform_driver mtk_disp_rdma_driver = {
 	.probe		= mtk_disp_rdma_probe,
 	.remove		= mtk_disp_rdma_remove,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index 0360fd6..53f936f 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -34,9 +34,8 @@
 #define DISP_REG_UFO_START			0x0000
 
 #define DISP_COLOR_CFG_MAIN			0x0400
-#define DISP_COLOR_START			0x0c00
-#define DISP_COLOR_WIDTH			0x0c50
-#define DISP_COLOR_HEIGHT			0x0c54
+#define DISP_COLOR_WIDTH			0x50
+#define DISP_COLOR_HEIGHT			0x54
 
 #define	OD_RELAY_MODE		BIT(0)
 
@@ -48,15 +47,15 @@
 static void mtk_color_config(struct mtk_ddp_comp *comp, unsigned int w,
 			     unsigned int h, unsigned int vrefresh)
 {
-	writel(w, comp->regs + DISP_COLOR_WIDTH);
-	writel(h, comp->regs + DISP_COLOR_HEIGHT);
+	writel(w, comp->regs + comp->data->color_offset + DISP_COLOR_WIDTH);
+	writel(h, comp->regs + comp->data->color_offset + DISP_COLOR_HEIGHT);
 }
 
 static void mtk_color_start(struct mtk_ddp_comp *comp)
 {
 	writel(COLOR_BYPASS_ALL | COLOR_SEQ_SEL,
 	       comp->regs + DISP_COLOR_CFG_MAIN);
-	writel(0x1, comp->regs + DISP_COLOR_START);
+	writel(0x1, comp->regs + comp->data->color_offset);
 }
 
 static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w,
@@ -133,6 +132,32 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
 	[DDP_COMPONENT_WDMA1]	= { MTK_DISP_WDMA,	1, NULL },
 };
 
+static const struct mtk_ddp_comp_driver_data mt2701_color_driver_data = {
+	.color_offset = 0x0f00,
+};
+
+static const struct mtk_ddp_comp_driver_data mt8173_color_driver_data = {
+	.color_offset = 0x0c00,
+};
+
+static const struct of_device_id mtk_disp_color_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt2701-disp-color",
+	  .data = &mt2701_color_driver_data},
+	{ .compatible = "mediatek,mt8173-disp-color",
+	  .data = &mt8173_color_driver_data},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_color_driver_dt_match);
+
+static inline struct mtk_ddp_comp_driver_data *mtk_color_get_driver_data(
+	struct device_node *node)
+{
+	const struct of_device_id *of_id =
+		of_match_node(mtk_disp_color_driver_dt_match, node);
+
+	return (struct mtk_ddp_comp_driver_data *)of_id->data;
+}
+
 int mtk_ddp_comp_get_id(struct device_node *node,
 			enum mtk_ddp_comp_type comp_type)
 {
@@ -179,6 +204,9 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
 
 	type = mtk_ddp_matches[comp_id].type;
 
+	if (type == MTK_DISP_COLOR)
+		comp->data = mtk_color_get_driver_data(node);
+
 	/* Only DMA capable components need the LARB property */
 	comp->larb_dev = NULL;
 	if (type != MTK_DISP_OVL &&
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index 1c344e4..6e2d918 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -77,6 +77,18 @@ struct mtk_ddp_comp_funcs {
 			     struct mtk_plane_state *state);
 };
 
+struct mtk_ddp_comp_driver_data {
+	union {
+		struct ovl {
+			unsigned int addr_offset;
+			unsigned int fmt_rgb565;
+			unsigned int fmt_rgb888;
+		} ovl;
+		unsigned int rdma_fifo_pseudo_size;
+		unsigned int color_offset;
+	};
+};
+
 struct mtk_ddp_comp {
 	struct clk *clk;
 	void __iomem *regs;
@@ -84,6 +96,7 @@ struct mtk_ddp_comp {
 	struct device *larb_dev;
 	enum mtk_ddp_comp_id id;
 	const struct mtk_ddp_comp_funcs *funcs;
+	const struct mtk_ddp_comp_driver_data *data;
 };
 
 static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp,
-- 
1.7.9.5



From yt.shen at mediatek.com  Fri May 20 08:05:35 2016
From: yt.shen at mediatek.com (yt.shen at mediatek.com)
Date: Fri, 20 May 2016 23:05:35 +0800
Subject: [RFC v2 4/5] drm/mediatek: add shadow register support
In-Reply-To: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
Message-ID: <1463756736-46573-5-git-send-email-yt.shen@mediatek.com>

From: YT Shen <yt.shen at mediatek.com>

We need to acquire mutex before using the resources,
and need to release it after finished.
So we don't need to write registers in the blanking period.

Signed-off-by: YT Shen <yt.shen at mediatek.com>
---
 drivers/gpu/drm/mediatek/mtk_drm_crtc.c |   75 +++++++++++++++++++------------
 drivers/gpu/drm/mediatek/mtk_drm_ddp.c  |   26 +++++++++++
 drivers/gpu/drm/mediatek/mtk_drm_ddp.h  |    2 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.c  |    2 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.h  |    1 +
 5 files changed, 77 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 3095fc1..5f1eea1 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -315,6 +315,42 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
 	pm_runtime_put(drm->dev);
 }
 
+static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
+{
+	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+	struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
+	struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
+	unsigned int i;
+
+	/*
+	 * TODO: instead of updating the registers here, we should prepare
+	 * working registers in atomic_commit and let the hardware command
+	 * queue update module registers on vblank.
+	 */
+	if (state->pending_config) {
+		mtk_ddp_comp_config(ovl, state->pending_width,
+				    state->pending_height,
+				    state->pending_vrefresh);
+
+		state->pending_config = false;
+	}
+
+	if (mtk_crtc->pending_planes) {
+		for (i = 0; i < OVL_LAYER_NR; i++) {
+			struct drm_plane *plane = &mtk_crtc->planes[i].base;
+			struct mtk_plane_state *plane_state;
+
+			plane_state = to_mtk_plane_state(plane->state);
+
+			if (plane_state->pending.config) {
+				mtk_ddp_comp_layer_config(ovl, i, plane_state);
+				plane_state->pending.config = false;
+			}
+		}
+		mtk_crtc->pending_planes = false;
+	}
+}
+
 static void mtk_drm_crtc_enable(struct drm_crtc *crtc)
 {
 	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
@@ -391,6 +427,7 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
 				      struct drm_crtc_state *old_crtc_state)
 {
 	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+	struct mtk_drm_private *priv = crtc->dev->dev_private;
 	unsigned int pending_planes = 0;
 	int i;
 
@@ -409,6 +446,12 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
 	}
 	if (pending_planes)
 		mtk_crtc->pending_planes = true;
+
+	if (priv->data->shadow_register) {
+		mtk_disp_mutex_acquire(mtk_crtc->mutex);
+		mtk_crtc_ddp_config(crtc);
+		mtk_disp_mutex_release(mtk_crtc->mutex);
+	}
 }
 
 static const struct drm_crtc_funcs mtk_crtc_funcs = {
@@ -453,36 +496,10 @@ err_cleanup_crtc:
 void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl)
 {
 	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
-	struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
-	unsigned int i;
+	struct mtk_drm_private *priv = crtc->dev->dev_private;
 
-	/*
-	 * TODO: instead of updating the registers here, we should prepare
-	 * working registers in atomic_commit and let the hardware command
-	 * queue update module registers on vblank.
-	 */
-	if (state->pending_config) {
-		mtk_ddp_comp_config(ovl, state->pending_width,
-				    state->pending_height,
-				    state->pending_vrefresh);
-
-		state->pending_config = false;
-	}
-
-	if (mtk_crtc->pending_planes) {
-		for (i = 0; i < OVL_LAYER_NR; i++) {
-			struct drm_plane *plane = &mtk_crtc->planes[i].base;
-			struct mtk_plane_state *plane_state;
-
-			plane_state = to_mtk_plane_state(plane->state);
-
-			if (plane_state->pending.config) {
-				mtk_ddp_comp_layer_config(ovl, i, plane_state);
-				plane_state->pending.config = false;
-			}
-		}
-		mtk_crtc->pending_planes = false;
-	}
+	if (!priv->data->shadow_register)
+		mtk_crtc_ddp_config(crtc);
 
 	mtk_drm_finish_page_flip(mtk_crtc);
 }
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index 529569d..f09a414 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
@@ -36,6 +37,7 @@
 #define DISP_REG_CONFIG_DSI_SEL			0x050
 
 #define DISP_REG_MUTEX_EN(n)	(0x20 + 0x20 * (n))
+#define DISP_REG_MUTEX(n)	(0x24 + 0x20 * (n))
 #define DISP_REG_MUTEX_RST(n)	(0x28 + 0x20 * (n))
 #define DISP_REG_MUTEX_MOD(n)	(0x2c + 0x20 * (n))
 #define DISP_REG_MUTEX_SOF(n)	(0x30 + 0x20 * (n))
@@ -341,6 +343,30 @@ void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex)
 	writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
 }
 
+void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex)
+{
+	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+					   mutex[mutex->id]);
+
+	unsigned int cnt = 0;
+
+	writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
+	writel(1, ddp->regs + DISP_REG_MUTEX(mutex->id));
+	while (!(readl(ddp->regs + DISP_REG_MUTEX(mutex->id)) & 0x2)) {
+		if (cnt++ > 10000)
+			break;
+		udelay(1);
+	}
+}
+
+void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex)
+{
+	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+					   mutex[mutex->id]);
+
+	writel(0, ddp->regs + DISP_REG_MUTEX(mutex->id));
+}
+
 static const struct of_device_id ddp_driver_dt_match[] = {
 	{ .compatible = "mediatek,mt2701-disp-mutex", .data = mutex_mod_mt2701},
 	{ .compatible = "mediatek,mt8173-disp-mutex", .data = mutex_mod_mt8173},
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp.h
index 92c1175..f9a7991 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.h
@@ -37,5 +37,7 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
 				enum mtk_ddp_comp_id id);
 void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex);
 void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex);
+void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex);
+void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex);
 
 #endif /* MTK_DRM_DDP_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 8b562ab..8f9fb7e 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -146,6 +146,7 @@ static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
 	.main_len = ARRAY_SIZE(mtk_ddp_main_2701),
 	.ext_path = mtk_ddp_ext_2701,
 	.ext_len = ARRAY_SIZE(mtk_ddp_ext_2701),
+	.shadow_register = true,
 };
 
 static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
@@ -153,6 +154,7 @@ static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
 	.main_len = ARRAY_SIZE(mtk_ddp_main_8173),
 	.ext_path = mtk_ddp_ext_8173,
 	.ext_len = ARRAY_SIZE(mtk_ddp_ext_8173),
+	.shadow_register = false,
 };
 
 static int mtk_drm_kms_init(struct drm_device *drm)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index fa0b106..94f8b66 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -33,6 +33,7 @@ struct mtk_mmsys_driver_data {
 	unsigned int main_len;
 	const enum mtk_ddp_comp_id *ext_path;
 	unsigned int ext_len;
+	bool shadow_register;
 };
 
 struct mtk_drm_private {
-- 
1.7.9.5



From yt.shen at mediatek.com  Fri May 20 08:05:36 2016
From: yt.shen at mediatek.com (yt.shen at mediatek.com)
Date: Fri, 20 May 2016 23:05:36 +0800
Subject: [RFC v2 5/5] arm: dts: mt2701: Add display subsystem related nodes
 for MT2701
In-Reply-To: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
Message-ID: <1463756736-46573-6-git-send-email-yt.shen@mediatek.com>

From: YT Shen <yt.shen at mediatek.com>

This patch adds the device nodes for the DISP function blocks for MT2701

Signed-off-by: YT Shen <yt.shen at mediatek.com>
---
 arch/arm/boot/dts/mt2701.dtsi |  117 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 117 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 363de0d..0beef2a 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -24,6 +24,13 @@
 	compatible = "mediatek,mt2701";
 	interrupt-parent = <&sysirq>;
 
+	aliases {
+		rdma0 = &rdma0;
+		rdma1 = &rdma1;
+		dpi0 = &dpi0;
+		dpi1 = &dpi1;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -171,6 +178,14 @@
 		power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
 	};
 
+	mipi_tx0: mipi-dphy at 10010000 {
+		compatible = "mediatek,mt2701-mipi-tx";
+		reg = <0 0x10010000 0 0x90>;
+		clocks = <&clk26m>;
+		clock-output-names = "mipi_tx0_pll";
+		status = "disabled";
+	};
+
 	sysirq: interrupt-controller at 10200100 {
 		compatible = "mediatek,mt2701-sysirq",
 			     "mediatek,mt6577-sysirq";
@@ -255,6 +270,79 @@
 		status = "disabled";
 	};
 
+	ovl at 14007000 {
+		compatible = "mediatek,mt2701-disp-ovl";
+		reg = <0 0x14007000 0 0x1000>;
+		interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DISP_OVL>;
+		iommus = <&iommu MT2701_M4U_PORT_DISP_OVL_0>;
+		mediatek,larb = <&larb0>;
+	};
+
+	rdma0: rdma at 14008000 {
+		compatible = "mediatek,mt2701-disp-rdma";
+		reg = <0 0x14008000 0 0x1000>;
+		interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DISP_RDMA>;
+		iommus = <&iommu MT2701_M4U_PORT_DISP_RDMA>;
+		mediatek,larb = <&larb0>;
+	};
+
+	wdma at 14009000 {
+		compatible = "mediatek,mt2701-disp-wdma";
+		reg = <0 0x14009000 0 0x1000>;
+		interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DISP_WDMA>;
+		iommus = <&iommu MT2701_M4U_PORT_DISP_WDMA>;
+		mediatek,larb = <&larb0>;
+	};
+
+	bls at 1400a000 {
+		compatible = "mediatek,mt2701-disp-bls";
+		reg = <0 0x1400a000 0 0x1000>;
+		interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DISP_BLS>;
+	};
+
+	color at 1400b000 {
+		compatible = "mediatek,mt2701-disp-color";
+		reg = <0 0x1400b000 0 0x1000>;
+		interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DISP_COLOR>;
+	};
+
+	dsi0: dsi at 1400c000 {
+		compatible = "mediatek,mt2701-dsi";
+		reg = <0 0x1400c000 0 0x1000>;
+		interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DSI_ENGINE>, <&mmsys CLK_MM_DSI_DIG>,
+			 <&mipi_tx0>;
+		clock-names = "engine", "digital", "hs";
+		phys = <&mipi_tx0>;
+		phy-names = "dphy";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	dpi0: dpi at 1400d000 {
+		compatible = "mediatek,mt2701-dpi";
+		reg = <0 0x1400d000 0 0x1000>;
+		interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DPI_DIGL>,
+			 <&mmsys CLK_MM_DPI_ENGINE>;
+		clock-names = "clk_dpi_digl",
+			      "clk_dpi_engine";
+		status = "disabled";
+	};
+
+	mutex: mutex at 1400e000 {
+		compatible = "mediatek,mt2701-disp-mutex";
+		reg = <0 0x1400e000 0 0x1000>;
+		interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_MUTEX_32K>;
+	};
+
 	larb0: larb at 14010000 {
 		compatible = "mediatek,mt2701-smi-larb";
 		reg = <0 0x14010000 0 0x1000>;
@@ -265,6 +353,35 @@
 		power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
 	};
 
+	rdma1: rdma at 14012000 {
+		compatible = "mediatek,mt2701-disp-rdma";
+		reg = <0 0x14012000 0 0x1000>;
+		interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DISP_RDMA1>;
+		iommus = <&iommu MT2701_M4U_PORT_DISP_RDMA1>;
+		mediatek,larb = <&larb0>;
+	};
+
+	ufoe at 14013000 {
+		compatible = "mediatek,mt2701-disp-ufoe";
+		reg = <0 0x14013000 0 0x1000>;
+		clocks = <&mmsys CLK_MM_DISP_UFOE>;
+	};
+
+	dpi1: dpi at 14014000 {
+		compatible = "mediatek,mt2701-dpi";
+		reg = <0 0x14014000 0 0x1000>;
+		interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&mmsys CLK_MM_DPI1_DIGL>,
+			 <&mmsys CLK_MM_DPI1_ENGINE>,
+			 <&topckgen CLK_TOP_DPI1_SEL>,
+			 <&topckgen CLK_TOP_TVDPLL>,
+			 <&topckgen CLK_TOP_TVDPLL_D2>,
+			 <&topckgen CLK_TOP_TVDPLL_D4>;
+		clock-names = "pixel", "engine", "sel","div1","div2","div4";
+		status = "disabled";
+	};
+
 	imgsys: syscon at 15000000 {
 		compatible = "mediatek,mt2701-imgsys", "syscon";
 		reg = <0 0x15000000 0 0x1000>;
-- 
1.7.9.5



From javier at osg.samsung.com  Fri May 20 08:13:41 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Fri, 20 May 2016 11:13:41 -0400
Subject: [PATCH] ARM: dts: exynos: Remove unneded always-on for regulators
 on Peach boards
In-Reply-To: <573EDEF2.8020903@samsung.com>
References: <1463694753-7259-1-git-send-email-javier@osg.samsung.com>
 <573EDEF2.8020903@samsung.com>
Message-ID: <66cd7fed-c281-0645-0a60-5e1300419642@osg.samsung.com>

Hello Krzysztof,

Thanks a lot for the feedback.

On 05/20/2016 05:54 AM, Krzysztof Kozlowski wrote:
> On 05/19/2016 11:52 PM, Javier Martinez Canillas wrote:
>> The regulator always-on property should only be used for regulators
>> that either can't be disabled or the drivers for the client devices
>> are not enabling the regulator and so being disabled due to unused.
>>
>> There are some max77802 regulators in the Peach Pit and Pi boards
>> that are always-on but shouldn't since they are enabled by drivers:
>>
>> BUCK5 is max77802 inl1 supply
>> BUCK7 is max77802 inl{2,10} supply
>> BUCK9 is max77802 inl{3,4,5,7} supply
>> BUCK10 is mmc1 vqmmc supply
>> LDO9 is adc vdd supply
>>
>> This patch removes the always-on property for these regulators.
>>
>> Some regulators should remain always-on even when they are used as
>> input supplies, because these regulators are also used by other
>> components that are not described in the DT, for example:
>>
>> LDO10 is hdmi vdd_osc supply but it's also used as input supply for
>> the Exynos5420 temperature sensor.
> 
> I don't have the schematics, so just guessing: by temperature sensor do
> you mean the tmu_cpu* node (supplying power to VDD_TS01/23/4)?
>

Yes, I meant that the LDO10 regulator supplies 1v8 to VDD18_TS{01,23,4}.
 
> If yes then you can also change it, like on Odroid XU boards.
>

Indeed, I think that should be a separate patch though. I'll do it
next week since I don't have access to the machine today to test.
 
>>
>> LDO8 is hdmi vdd and vdd_pll supply but it's also used as supply for
>> the Exynos5420 Display port.
>>
>> BUCK2 and BUCK6 are the vdd supplies for the EAGLE and KFC clusters.
>>
>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>> ---
>>
>>  arch/arm/boot/dts/exynos5420-peach-pit.dts | 5 -----
>>  arch/arm/boot/dts/exynos5800-peach-pi.dts  | 5 -----
>>  2 files changed, 10 deletions(-)
> 
> Anyway,
> 
> Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>

Thanks!
 
> Best regards,
> Krzysztof
> --

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From andy.gross at linaro.org  Fri May 20 08:33:56 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Fri, 20 May 2016 10:33:56 -0500
Subject: [PATCH] usb: echi-hcd: Add ehci_setup check before echi_shutdown
In-Reply-To: <Pine.LNX.4.44L0.1605201026060.1938-100000@iolanthe.rowland.org>
References: <CAPBZ5QcMiMEv1n=WU6aW2PGNsSPZJR42iZge_VUX4aWZ-KKzbw@mail.gmail.com>
 <Pine.LNX.4.44L0.1605201026060.1938-100000@iolanthe.rowland.org>
Message-ID: <CAPBZ5Qf6VtfGrfx1LaR5d9gL3zcBCZ_MeUpxX+E6dpi1HP+QpQ@mail.gmail.com>

On 20 May 2016 at 09:31, Alan Stern <stern at rowland.harvard.edu> wrote:
> On Thu, 19 May 2016, Andy Gross wrote:
>
>> On 19 May 2016 at 05:12, Srinivas Kandagatla
>> <srinivas.kandagatla at linaro.org> wrote:
>>
>> <snip>
>>
>> > +++ b/drivers/usb/host/ehci-hcd.c
>> > @@ -368,6 +368,15 @@ static void ehci_shutdown(struct usb_hcd *hcd)
>> >  {
>> >         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
>> >
>> > +       /**
>> > +        * Protect the system from crashing at system shutdown in cases where
>> > +        * usb host is not added yet from OTG controller driver.
>> > +        * As ehci_setup() not done yet, so stop accessing registers or
>> > +        * variables initialized in ehci_setup()
>> > +        */
>> > +       if (!ehci->sbrn)
>> > +               return;
>> > +
>> >         spin_lock_irq(&ehci->lock);
>> >         ehci->shutdown = true;
>> >         ehci->rh_state = EHCI_RH_STOPPING;
>>
>>
>> Should we also not check this in ehci_suspend and ehci_resume?  If I
>> do suspend/resume, it crashes in a similar manner.  I know this goes
>> beyond the problem scope of the patch.  Perhaps I should send in an
>> additional patch with the code?
>>
>> Are there any other places in the ehci-hcd where this needs to be checked?
>
> Really, this is an indication that the problem lies not in ehci-hcd but
> rather in the platform glue code.  The platform code allows itself to
> be registered as the driver of the controller device but does not
> initialize the ehci-hcd parts.
>
> Neither ehci_suspend nor ehci_resume is called directly by the driver
> core; the calls all have to pass through the glue code.  So maybe the
> glue layer needs to be careful about invoking these routines in
> ehci-hcd before ehci-hcd has been initialized.

That's a good point.  Perhaps all of this should be in the glue,
including the shutdown case.

Regards,

Andy


From sergei.shtylyov at cogentembedded.com  Fri May 20 08:38:49 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Fri, 20 May 2016 18:38:49 +0300
Subject: [PATCH v2 11/23] ARM: dts: armadillo800eva: Fix W=1 dtc warnings
In-Reply-To: <1463728214-13838-12-git-send-email-geert+renesas@glider.be>
References: <1463728214-13838-1-git-send-email-geert+renesas@glider.be>
 <1463728214-13838-12-git-send-email-geert+renesas@glider.be>
Message-ID: <e0a1fbc1-ac95-2c79-65ed-d0328679bb8a@cogentembedded.com>

Hello.

On 05/20/2016 10:10 AM, Geert Uytterhoeven wrote:

> Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
> Warning (unit_address_vs_reg): Node /regulator at 0 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /regulator at 1 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /regulator at 2 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /regulator at 3 has a unit name, but no reg property
> Warning (unit_address_vs_reg): Node /i2c at 2 has a unit name, but no reg property
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
> ---
> v2:
>   - No changes.
> ---
>  arch/arm/boot/dts/r8a7740-armadillo800eva.dts | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
> index 2c82dab2b6f45f9c..b3f0ac4b99bd5a3d 100644
> --- a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
> +++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
[...]
> @@ -127,7 +127,7 @@
>  		};
>  	};
>
> -	i2c2: i2c at 2 {
> +	i2c2: i2c2 {

    Not "i2c-2" as in the other patches?

>  		#address-cells = <1>;
>  		#size-cells = <0>;
>  		compatible = "i2c-gpio";

MBR, Sergei



From tglx at linutronix.de  Fri May 20 08:42:17 2016
From: tglx at linutronix.de (Thomas Gleixner)
Date: Fri, 20 May 2016 17:42:17 +0200 (CEST)
Subject: [PATCH] arm: Enable interrupts before calling schedule()
Message-ID: <alpine.DEB.2.11.1605201740320.3639@nanos>

do_work_pending() calls schedule() with interrupts disabled, which is just
wrong. Fix it.

Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
---
 arch/arm/kernel/signal.c |    1 +
 1 file changed, 1 insertion(+)

--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -573,6 +573,7 @@ do_work_pending(struct pt_regs *regs, un
 	trace_hardirqs_off();
 	do {
 		if (likely(thread_flags & _TIF_NEED_RESCHED)) {
+			local_irq_enable();
 			schedule();
 		} else {
 			if (unlikely(!user_mode(regs)))


From stern at rowland.harvard.edu  Fri May 20 08:57:49 2016
From: stern at rowland.harvard.edu (Alan Stern)
Date: Fri, 20 May 2016 11:57:49 -0400 (EDT)
Subject: [PATCH] usb: echi-hcd: Add ehci_setup check before echi_shutdown
In-Reply-To: <CAPBZ5Qf6VtfGrfx1LaR5d9gL3zcBCZ_MeUpxX+E6dpi1HP+QpQ@mail.gmail.com>
Message-ID: <Pine.LNX.4.44L0.1605201156220.1938-100000@iolanthe.rowland.org>

On Fri, 20 May 2016, Andy Gross wrote:

> On 20 May 2016 at 09:31, Alan Stern <stern at rowland.harvard.edu> wrote:
> > On Thu, 19 May 2016, Andy Gross wrote:
> >
> >> On 19 May 2016 at 05:12, Srinivas Kandagatla
> >> <srinivas.kandagatla at linaro.org> wrote:
> >>
> >> <snip>
> >>
> >> > +++ b/drivers/usb/host/ehci-hcd.c
> >> > @@ -368,6 +368,15 @@ static void ehci_shutdown(struct usb_hcd *hcd)
> >> >  {
> >> >         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
> >> >
> >> > +       /**
> >> > +        * Protect the system from crashing at system shutdown in cases where
> >> > +        * usb host is not added yet from OTG controller driver.
> >> > +        * As ehci_setup() not done yet, so stop accessing registers or
> >> > +        * variables initialized in ehci_setup()
> >> > +        */
> >> > +       if (!ehci->sbrn)
> >> > +               return;
> >> > +
> >> >         spin_lock_irq(&ehci->lock);
> >> >         ehci->shutdown = true;
> >> >         ehci->rh_state = EHCI_RH_STOPPING;
> >>
> >>
> >> Should we also not check this in ehci_suspend and ehci_resume?  If I
> >> do suspend/resume, it crashes in a similar manner.  I know this goes
> >> beyond the problem scope of the patch.  Perhaps I should send in an
> >> additional patch with the code?
> >>
> >> Are there any other places in the ehci-hcd where this needs to be checked?
> >
> > Really, this is an indication that the problem lies not in ehci-hcd but
> > rather in the platform glue code.  The platform code allows itself to
> > be registered as the driver of the controller device but does not
> > initialize the ehci-hcd parts.
> >
> > Neither ehci_suspend nor ehci_resume is called directly by the driver
> > core; the calls all have to pass through the glue code.  So maybe the
> > glue layer needs to be careful about invoking these routines in
> > ehci-hcd before ehci-hcd has been initialized.
> 
> That's a good point.  Perhaps all of this should be in the glue,
> including the shutdown case.

Many of the platform glue files set usb_hcd_platform_shutdown() as 
their shutdown callback, which makes it impossible for them to include 
a controller-specific test.

Alan Stern



From eric.auger at linaro.org  Fri May 20 09:01:14 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Fri, 20 May 2016 18:01:14 +0200
Subject: [PATCH v9 0/7] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part
 3/3: vfio changes
In-Reply-To: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
References: <1462362858-2925-1-git-send-email-eric.auger@linaro.org>
Message-ID: <573F34CA.5080308@linaro.org>

Alex, Robin,

While my 3 part series primarily addresses the problematic of mapping
MSI doorbells into arm-smmu, it fails in :

1) determining whether the MSI controller is downstream or upstream to
the IOMMU,
	=> indicates whether the MSI doorbell must be mapped
	=> participates in the decision about 2)

2) determining whether it is safe to assign a PCIe device.

I think we share this understanding with Robin. All above of course
stands for ARM.

I get stuck with those 2 issues and I have few questions about iommu
group setup, PCIe, iommu dt/ACPI description. I would be grateful to you
if you could answer part of those questions and advise about the
strategy to fix those.

Best Regards

Eric

QUESTIONS:

1) Robin, you pointed some host controllers which also are MSI
controllers
(http://thread.gmane.org/gmane.linux.kernel.pci/47174/focus=47268). In
that case MSIs never reach the IOMMU. I failed in finding anything about
MSIs in PCIe ACS spec. What should be the iommu groups in that
situation. Isn't the upstreamed code able to see some DMA transfers are
not properly isolated and alias devices in the same group? According to
your security warning, Alex, I would think the code does not recognize
it, can you confirm please?

2) can other PCIe components be MSI controllers?

3) Am I obliged to consider arbitrary topologies where an MSI controller
stands between the PCIe host and the iommu? in the PCIe space or
platform space? If this only relates to PCIe couldn' I check if an MSI
controller exists in the PCIe tree?

4) Robin suggested in a private thread to enumerate through a list of
"registered" doorbells and if any belongs to an unsafe MSI controller,
consider the assignment is unsafe. This would be a first step before
doing something more complex. Alex, would that be acceptable to you for
issue #2?

5) About issue #1: don't we miss tools in dt/ACPI to describe the
location of the iommu on ARM? This is not needed on x86 because
irq_remapping and IOMMU are at the same place but my understanding is
that it is on ARM where
- there is no connection between the MSI controller - which implements
irq remapping - and the iommu
- MSI are conveyed on the same address space as standard memory
transactions.

6)  can't we live with iommu/MSI controller respective location uncertainty?

- in my current series, with the above Xilinx MSI controller, I would
see there is an arm-smmu requiring mapping behind the PCI host, would
query the characteristics of the MSI doorbell (not implemented by that
controller), so no mapping would be done. So it would work I think.
- However in case we have this topology: PCIe host -> MSI controller
generally used behind an IOMMU (so registering a doorbell) -> IOMMU,
this wouldn't work since the doorbell would be mapped.




On 05/04/2016 01:54 PM, Eric Auger wrote:
> This series allows the user-space to register a reserved IOVA domain.
> This completes the kernel integration of the whole functionality on top
> of part 1 (v9) & 2 (v8).
> 
> It also depends on [PATCH 1/3] iommu: Add MMIO mapping type series,
> http://comments.gmane.org/gmane.linux.kernel.iommu/12869
> 
> We reuse the VFIO DMA MAP ioctl with a new flag to bridge to the
> msi-iommu API. The need for provisioning such MSI IOVA range is reported
> through capability chain, using VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY.
> 
> vfio_iommu_type1 checks if the MSI mapping is safe when attaching the
> vfio group to the container (allow_unsafe_interrupts modality).
> 
> On ARM/ARM64, the IOMMU does not astract IRQ remapping. the modality is
> abstracted on MSI controller side. The GICv3 ITS is the first controller
> advertising the modality.
> 
> More details & context can be found at:
> http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/
> 
> Best Regards
> 
> Eric
> 
> Testing:
> - functional on ARM64 AMD Overdrive HW (single GICv2m frame) with
>   Intel X540-T2 (SR-IOV capable)
> - also tested on Armada-7040 using an intel IXGBE (82599ES) by
>   Yehuda Yitschak (v8)
> - Not tested: ARM GICv3 ITS
> 
> References:
> [1] [RFC 0/2] VFIO: Add virtual MSI doorbell support
>     (https://lkml.org/lkml/2015/7/24/135)
> [2] [RFC PATCH 0/6] vfio: Add interface to map MSI pages
>     (https://lists.cs.columbia.edu/pipermail/kvmarm/2015-September/016607.html)
> [3] [PATCH v2 0/3] Introduce MSI hardware mapping for VFIO
>     (http://permalink.gmane.org/gmane.comp.emulators.kvm.arm.devel/3858)
> 
> Git: complete series available at
> https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc6-pcie-passthrough-v9
> 
> previous version at
> https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc5-pcie-passthrough-v8
> 
> History:
> v8 -> v9:
> - report MSI geometry through capability chain (last patch only);
>   with the current limitation that an arbitrary number of 16 page
>   requirement is reported. To be improved later on.
> 
> 
> v7 -> v8:
> - use renamed msi-iommu API
> - VFIO only responsible for setting the IOVA aperture
> - use new DOMAIN_ATTR_MSI_GEOMETRY iommu domain attribute
> 
> v6 -> v7:
> - vfio_find_dma now accepts a dma_type argument.
> - should have recovered the capability to unmap the whole user IOVA range
> - remove computation of nb IOVA pages -> will post a separate RFC for that
>   while respinning the QEMU part
> 
> RFC v5 -> patch v6:
> - split to ease the review process
> 
> RFC v4 -> RFC v5:
> - take into account Thomas' comments on MSI related patches
>   - split "msi: IOMMU map the doorbell address when needed"
>   - increase readability and add comments
>   - fix style issues
>  - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
>  - platform ITS now advertises IOMMU_CAP_INTR_REMAP
>  - fix compilation issue with CONFIG_IOMMU API unset
>  - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING
> 
> RFC v3 -> v4:
> - Move doorbell mapping/unmapping in msi.c
> - fix ref count issue on set_affinity: in case of a change in the address
>   the previous address is decremented
> - doorbell map/unmap now is done on msi composition. Should allow the use
>   case for platform MSI controllers
> - create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
>   to reserved IOVA management (looking like dma-iommu glue)
> - series reordering to ease the review:
>   - first part is related to IOMMU
>   - second related to MSI sub-system
>   - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
> - expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
>   [this partially addresses Marc's comments on iommu_get/put_single_reserved
>    size/alignment problematic - which I did not ignore - but I don't know
>    how much I can do at the moment]
> 
> RFC v2 -> RFC v3:
> - should fix wrong handling of some CONFIG combinations:
>   CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
> - fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)
> 
> PATCH v1 -> RFC v2:
> - reverted to RFC since it looks more reasonable ;-) the code is split
>   between VFIO, IOMMU, MSI controller and I am not sure I did the right
>   choices. Also API need to be further discussed.
> - iova API usage in arm-smmu.c.
> - MSI controller natively programs the MSI addr with either the PA or IOVA.
>   This is not done anymore in vfio-pci driver as suggested by Alex.
> - check irq remapping capability of the group
> 
> RFC v1 [2] -> PATCH v1:
> - use the existing dma map/unmap ioctl interface with a flag to register a
>   reserved IOVA range. Use the legacy Rb to store this special vfio_dma.
> - a single reserved IOVA contiguous region now is allowed
> - use of an RB tree indexed by PA to store allocated reserved slots
> - use of a vfio_domain iova_domain to manage iova allocation within the
>   window provided by the userspace
> - vfio alloc_map/unmap_free take a vfio_group handle
> - vfio_group handle is cached in vfio_pci_device
> - add ref counting to bindings
> - user modality enabled at the end of the series
> 
> 
> Eric Auger (7):
>   vfio: introduce a vfio_dma type field
>   vfio/type1: vfio_find_dma accepting a type argument
>   vfio/type1: bypass unmap/unpin and replay for VFIO_IOVA_RESERVED slots
>   vfio: allow reserved msi iova registration
>   vfio/type1: also check IRQ remapping capability at msi domain
>   iommu/arm-smmu: do not advertise IOMMU_CAP_INTR_REMAP
>   vfio/type1: return MSI geometry through VFIO_IOMMU_GET_INFO capability
>     chains
> 
>  drivers/iommu/arm-smmu-v3.c     |   3 +-
>  drivers/iommu/arm-smmu.c        |   3 +-
>  drivers/vfio/vfio_iommu_type1.c | 270 +++++++++++++++++++++++++++++++++++++---
>  include/uapi/linux/vfio.h       |  40 +++++-
>  4 files changed, 298 insertions(+), 18 deletions(-)
> 



From andy.gross at linaro.org  Fri May 20 09:09:00 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Fri, 20 May 2016 11:09:00 -0500
Subject: [PATCH] usb: echi-hcd: Add ehci_setup check before echi_shutdown
In-Reply-To: <Pine.LNX.4.44L0.1605201156220.1938-100000@iolanthe.rowland.org>
References: <CAPBZ5Qf6VtfGrfx1LaR5d9gL3zcBCZ_MeUpxX+E6dpi1HP+QpQ@mail.gmail.com>
 <Pine.LNX.4.44L0.1605201156220.1938-100000@iolanthe.rowland.org>
Message-ID: <CAPBZ5Qe3EbTKSihugJ-b8HwvPyQtPXFXVyaeBjY0takuzn+d4A@mail.gmail.com>

On 20 May 2016 at 10:57, Alan Stern <stern at rowland.harvard.edu> wrote:
> On Fri, 20 May 2016, Andy Gross wrote:
>
>> On 20 May 2016 at 09:31, Alan Stern <stern at rowland.harvard.edu> wrote:
>> > On Thu, 19 May 2016, Andy Gross wrote:
>> >
>> >> On 19 May 2016 at 05:12, Srinivas Kandagatla
>> >> <srinivas.kandagatla at linaro.org> wrote:
>> >>
>> >> <snip>
>> >>
>> >> > +++ b/drivers/usb/host/ehci-hcd.c
>> >> > @@ -368,6 +368,15 @@ static void ehci_shutdown(struct usb_hcd *hcd)
>> >> >  {
>> >> >         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
>> >> >
>> >> > +       /**
>> >> > +        * Protect the system from crashing at system shutdown in cases where
>> >> > +        * usb host is not added yet from OTG controller driver.
>> >> > +        * As ehci_setup() not done yet, so stop accessing registers or
>> >> > +        * variables initialized in ehci_setup()
>> >> > +        */
>> >> > +       if (!ehci->sbrn)
>> >> > +               return;
>> >> > +
>> >> >         spin_lock_irq(&ehci->lock);
>> >> >         ehci->shutdown = true;
>> >> >         ehci->rh_state = EHCI_RH_STOPPING;
>> >>
>> >>
>> >> Should we also not check this in ehci_suspend and ehci_resume?  If I
>> >> do suspend/resume, it crashes in a similar manner.  I know this goes
>> >> beyond the problem scope of the patch.  Perhaps I should send in an
>> >> additional patch with the code?
>> >>
>> >> Are there any other places in the ehci-hcd where this needs to be checked?
>> >
>> > Really, this is an indication that the problem lies not in ehci-hcd but
>> > rather in the platform glue code.  The platform code allows itself to
>> > be registered as the driver of the controller device but does not
>> > initialize the ehci-hcd parts.
>> >
>> > Neither ehci_suspend nor ehci_resume is called directly by the driver
>> > core; the calls all have to pass through the glue code.  So maybe the
>> > glue layer needs to be careful about invoking these routines in
>> > ehci-hcd before ehci-hcd has been initialized.
>>
>> That's a good point.  Perhaps all of this should be in the glue,
>> including the shutdown case.
>
> Many of the platform glue files set usb_hcd_platform_shutdown() as
> their shutdown callback, which makes it impossible for them to include
> a controller-specific test.

Yes, I just found this out for myself.  So in that specific case, it
makes sense to have the check within the ehci-hcd.  Whereas in the
glue driver, the suspend/resume use direct calls to
ehci_suspend/resume.

I'll send along a ehci-msm patch to address the issues i see with
suspend/resume.

Thanks!

Andy


From dmitry.torokhov at gmail.com  Fri May 20 09:34:04 2016
From: dmitry.torokhov at gmail.com (Dmitry Torokhov)
Date: Fri, 20 May 2016 09:34:04 -0700
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <1463648641-6931-2-git-send-email-vigneshr@ti.com>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
 <1463648641-6931-2-git-send-email-vigneshr@ti.com>
Message-ID: <20160520163404.GC14951@dtor-ws>

On Thu, May 19, 2016 at 02:34:00PM +0530, Vignesh R wrote:
> There are rotary-encoders where GPIO lines reflect the actual position
> of the rotary encoder dial. For example, if dial points to 9, then four
> GPIO lines connected to the rotary encoder will read HLLH(1001b = 9).
> Add support for such rotary-encoder.
> The driver relies on rotary-encoder,absolute-encoder DT property to
> detect such encoders.
> Since, GPIO IRQs are not necessary to work with
> such encoders, optional polling mode support is added using
> input_poll_dev skeleton. This is can be used by enabling
> CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT.

Does this really belong to a rotary encoder and not a new driver that
simply translates gpio-encoded value into ABS* event?

> 
> Signed-off-by: Vignesh R <vigneshr at ti.com>
> ---
>  .../devicetree/bindings/input/rotary-encoder.txt   |   4 +
>  Documentation/input/rotary-encoder.txt             |   9 ++
>  drivers/input/misc/Kconfig                         |  11 ++
>  drivers/input/misc/rotary_encoder.c                | 165 ++++++++++++++++-----
>  4 files changed, 155 insertions(+), 34 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> index 6c9f0c8a846c..9c928dbd1500 100644
> --- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
> +++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> @@ -12,6 +12,10 @@ Optional properties:
>  - rotary-encoder,relative-axis: register a relative axis rather than an
>    absolute one. Relative axis will only generate +1/-1 events on the input
>    device, hence no steps need to be passed.
> +- rotary-encoder,absolute-encoder: support encoders where GPIO lines
> +  reflect the actual position of the rotary encoder dial. For example,
> +  if dial points to 9, then four GPIO lines read HLLH(1001b = 9).
> +  In this case, rotary-encoder,steps-per-period needed not be defined.
>  - rotary-encoder,rollover: Automatic rollove when the rotary value becomes
>    greater than the specified steps or smaller than 0. For absolute axis only.
>  - rotary-encoder,steps-per-period: Number of steps (stable states) per period.
> diff --git a/Documentation/input/rotary-encoder.txt b/Documentation/input/rotary-encoder.txt
> index 46a74f0c551a..dc76092f5618 100644
> --- a/Documentation/input/rotary-encoder.txt
> +++ b/Documentation/input/rotary-encoder.txt
> @@ -36,6 +36,15 @@ The phase diagram of these two outputs look like this:
>                  |<>|
>  	          one step (quarter-period mode)
>  
> +
> +In some encoders, the value pointed by rotary encoders switch is directly
> +reflected by status of the GPIOs connecting rotary encoder to CPU. For
> +example, if rotary encoder dial points to 9, then the four GPIOs
> +conncting rotary encoder will read HLLH(1001b = 9). Such encoders are
> +supported by defining devictree binding "rotary-encoder,absolute-encoder".
> +These encoders are also supported without need for event(IRQ) generation
> +using Input subsytem's polling mode support.
> +
>  For more information, please see
>  	https://en.wikipedia.org/wiki/Rotary_encoder
>  
> diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
> index 1f2337abcf2f..81805f9a534c 100644
> --- a/drivers/input/misc/Kconfig
> +++ b/drivers/input/misc/Kconfig
> @@ -566,6 +566,17 @@ config INPUT_GPIO_ROTARY_ENCODER
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called rotary_encoder.
>  
> +config INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT
> +	bool "Polling mode support for rotary encoder"
> +	depends on INPUT_GPIO_ROTARY_ENCODER
> +	select INPUT_POLLDEV
> +	help
> +	  Say Y here to enable polling mode support for rotary encoders
> +	  connected to GPIO lines that do have interrupt capability and
> +	  report rotary encoder position as absolute value over GPIO
> +	  lines. Check file: Documentation/input/rotary-encoder.txt for
> +	  more information.
> +
>  config INPUT_RB532_BUTTON
>  	tristate "Mikrotik Routerboard 532 button interface"
>  	depends on MIKROTIK_RB532
> diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
> index c7fc8d4fb080..8f60289fb6cd 100644
> --- a/drivers/input/misc/rotary_encoder.c
> +++ b/drivers/input/misc/rotary_encoder.c
> @@ -25,24 +25,29 @@
>  #include <linux/of.h>
>  #include <linux/pm.h>
>  #include <linux/property.h>
> +#include <linux/input-polldev.h>
>  
>  #define DRV_NAME "rotary-encoder"
>  
>  struct rotary_encoder {
>  	struct input_dev *input;
> -
> +#ifdef CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT
> +	struct input_polled_dev *poll_dev;
> +#endif
>  	struct mutex access_mutex;
>  
>  	u32 steps;
>  	u32 axis;
>  	bool relative_axis;
>  	bool rollover;
> +	bool absolute_encoder;
>  
>  	unsigned int pos;
>  
>  	struct gpio_descs *gpios;
> +	struct device *dev;
>  
> -	unsigned int *irq;
> +	int *irq;
>  
>  	bool armed;
>  	signed char dir;	/* 1 - clockwise, -1 - CCW */
> @@ -67,6 +72,21 @@ static unsigned int rotary_encoder_get_state(struct rotary_encoder *encoder)
>  	return ret & 3;
>  }
>  
> +static unsigned int rotary_encoder_get_gpios_state(struct rotary_encoder
> +						   *encoder)
> +{
> +	int i;
> +	unsigned int ret = 0;
> +
> +	for (i = 0; i < encoder->gpios->ndescs; ++i) {
> +		int val = gpiod_get_value_cansleep(encoder->gpios->desc[i]);
> +
> +		ret = ret << 1 | val;
> +	}
> +
> +	return ret;
> +}
> +
>  static void rotary_encoder_report_event(struct rotary_encoder *encoder)
>  {
>  	if (encoder->relative_axis) {
> @@ -178,6 +198,72 @@ out:
>  	return IRQ_HANDLED;
>  }
>  
> +static void rotary_encoder_setup_input_params(struct rotary_encoder  *encoder)
> +{
> +	struct input_dev *input = encoder->input;
> +	struct platform_device *pdev = to_platform_device(encoder->dev);
> +
> +	input->name = pdev->name;
> +	input->id.bustype = BUS_HOST;
> +	input->dev.parent = encoder->dev;
> +
> +	if (encoder->relative_axis)
> +		input_set_capability(input, EV_REL, encoder->axis);
> +	else
> +		input_set_abs_params(input,
> +				     encoder->axis, 0, encoder->steps, 0, 1);
> +}
> +
> +static irqreturn_t rotary_absolute_encoder_irq(int irq, void *dev_id)
> +{
> +	struct rotary_encoder *encoder = dev_id;
> +	unsigned int state;
> +
> +	mutex_lock(&encoder->access_mutex);
> +
> +	state = rotary_encoder_get_gpios_state(encoder);
> +	if (state != encoder->last_stable) {
> +		input_report_abs(encoder->input, encoder->axis, state);
> +		input_sync(encoder->input);
> +		encoder->last_stable = state;
> +	}
> +
> +	mutex_lock(&encoder->access_mutex);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +#ifdef CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT
> +static void rotary_encoder_poll_gpios(struct input_polled_dev *poll_dev)
> +{
> +	struct rotary_encoder *encoder = poll_dev->private;
> +	unsigned int state = rotary_encoder_get_gpios_state(encoder);
> +
> +	if (state != encoder->last_stable) {
> +		input_report_abs(encoder->input, encoder->axis, state);
> +		input_sync(encoder->input);
> +		encoder->last_stable = state;
> +	}
> +}
> +
> +static int rotary_encoder_register_poll_device(struct rotary_encoder
> +		*encoder)
> +{
> +	struct input_polled_dev *poll_dev =
> +		devm_input_allocate_polled_device(encoder->dev);
> +
> +	if (!poll_dev)
> +		return -ENOMEM;
> +	poll_dev->private = encoder;
> +	poll_dev->poll = rotary_encoder_poll_gpios;
> +	encoder->input = poll_dev->input;
> +	rotary_encoder_setup_input_params(encoder);
> +	encoder->poll_dev = poll_dev;
> +
> +	return input_register_polled_device(poll_dev);
> +}
> +#endif
> +
>  static int rotary_encoder_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -227,38 +313,32 @@ static int rotary_encoder_probe(struct platform_device *pdev)
>  		return -EINVAL;
>  	}
>  
> -	input = devm_input_allocate_device(dev);
> -	if (!input)
> -		return -ENOMEM;
> -
> -	encoder->input = input;
> -
> -	input->name = pdev->name;
> -	input->id.bustype = BUS_HOST;
> -	input->dev.parent = dev;
> -
> -	if (encoder->relative_axis)
> -		input_set_capability(input, EV_REL, encoder->axis);
> -	else
> -		input_set_abs_params(input,
> -				     encoder->axis, 0, encoder->steps, 0, 1);
> -
> -	switch (steps_per_period >> (encoder->gpios->ndescs - 2)) {
> -	case 4:
> -		handler = &rotary_encoder_quarter_period_irq;
> -		encoder->last_stable = rotary_encoder_get_state(encoder);
> -		break;
> -	case 2:
> -		handler = &rotary_encoder_half_period_irq;
> -		encoder->last_stable = rotary_encoder_get_state(encoder);
> -		break;
> -	case 1:
> -		handler = &rotary_encoder_irq;
> -		break;
> -	default:
> -		dev_err(dev, "'%d' is not a valid steps-per-period value\n",
> -			steps_per_period);
> -		return -EINVAL;
> +	encoder->dev = dev;
> +	encoder->absolute_encoder =
> +		device_property_read_bool(dev,
> +					  "rotary-encoder,absolute-encoder");
> +	if (encoder->absolute_encoder) {
> +		handler = rotary_absolute_encoder_irq;
> +	} else {
> +		switch (steps_per_period >> (encoder->gpios->ndescs - 2)) {
> +		case 4:
> +			handler = &rotary_encoder_quarter_period_irq;
> +			encoder->last_stable =
> +				rotary_encoder_get_state(encoder);
> +			break;
> +		case 2:
> +			handler = &rotary_encoder_half_period_irq;
> +			encoder->last_stable =
> +				rotary_encoder_get_state(encoder);
> +			break;
> +		case 1:
> +			handler = &rotary_encoder_irq;
> +			break;
> +		default:
> +			dev_err(dev, "'%d' is not a valid steps-per-period value\n",
> +				steps_per_period);
> +			return -EINVAL;
> +		}
>  	}
>  
>  	encoder->irq =
> @@ -271,6 +351,18 @@ static int rotary_encoder_probe(struct platform_device *pdev)
>  	for (i = 0; i < encoder->gpios->ndescs; ++i) {
>  		encoder->irq[i] = gpiod_to_irq(encoder->gpios->desc[i]);
>  
> +#ifdef CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT
> +		if (encoder->irq[i] < 0 && encoder->absolute_encoder) {
> +			dev_info(dev, "Using poll mode\n");
> +			err = rotary_encoder_register_poll_device(encoder);
> +			if (err) {
> +				dev_err(dev, "failed to register poll dev\n");
> +				return err;
> +			}
> +			platform_set_drvdata(pdev, encoder);
> +			return 0;
> +		}
> +#endif
>  		err = devm_request_threaded_irq(dev, encoder->irq[i],
>  				NULL, handler,
>  				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
> @@ -283,6 +375,11 @@ static int rotary_encoder_probe(struct platform_device *pdev)
>  		}
>  	}
>  
> +	input = devm_input_allocate_device(dev);
> +	if (!input)
> +		return -ENOMEM;
> +	encoder->input = input;
> +	rotary_encoder_setup_input_params(encoder);
>  	err = input_register_device(input);
>  	if (err) {
>  		dev_err(dev, "failed to register input device\n");
> -- 
> 2.8.2
> 

-- 
Dmitry


From festevam at gmail.com  Fri May 20 11:05:55 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Fri, 20 May 2016 15:05:55 -0300
Subject: Crash after 'reboot' due to 9be4fd2c7723a
Message-ID: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>

Rafael,

Running the 'reboot' command works fine on a 4.5 kernel running on a
mx6ul platform (ARM single core SoC), but it crashes on 4.6.

Running bisect I got 9be4fd2c7723a3057b0b39676 ("cpufreq: governor:
Replace timers with utilization update callbacks") as the first bad
commit.

Below is the output crash log.

Not sure if this issue is related to the problem reported by Guenter here:
http://lkml.iu.edu/hypermail/linux/kernel/1602.1/06075.html

Any ideas?

Thanks,

Fabio Estevam


[ 3857.373588] INFO: rcu_sched detected stalls on CPUs/tasks:
[ 3857.379155]  (detected by 0, t=2602 jiffies, g=1880, c=1879, q=29)
[ 3857.385406] All QSes seen, last rcu_sched kthread activity 2602
(355736-353134), jiffies_till_next_fqs=1, root ->qsmask 0x0
[ 3857.396562] init            R running      0   864      1 0x00000002
[ 3857.402999] Backtrace:
[ 3857.405532] [<c010b6e8>] (dump_backtrace) from [<c010b884>]
(show_stack+0x18/0x1c)
[ 3857.413125]  r6:c0d6c6d6 r5:00000001 r4:ddd9c800 r3:00000000
[ 3857.418941] [<c010b86c>] (show_stack) from [<c014fc3c>]
(sched_show_task+0x124/0x234)
[ 3857.426820] [<c014fb18>] (sched_show_task) from [<c0185e24>]
(rcu_check_callbacks+0x844/0x894)
[ 3857.435452]  r6:c0c76b40 r5:c0d14b80 r4:debd0b40
[ 3857.440189] [<c01855e0>] (rcu_check_callbacks) from [<c018884c>]
(update_process_times+0x38/0x64)
[ 3857.449081]  r10:c0d21e1c r9:debcdd10 r8:c019a230 r7:dde7bd50
r6:debce048 r5:00000000
[ 3857.457067]  r4:ddd9c800
[ 3857.459665] [<c0188814>] (update_process_times) from [<c019a174>]
(tick_sched_handle+0x50/0x54)
[ 3857.468386]  r5:00000382 r4:1c92d15d
[ 3857.472048] [<c019a124>] (tick_sched_handle) from [<c019a290>]
(tick_sched_timer+0x60/0xa8)
[ 3857.480443] [<c019a230>] (tick_sched_timer) from [<c018915c>]
(__hrtimer_run_queues+0xc0/0x1c8)
[ 3857.489162]  r7:debcdd80 r6:debcdd00 r5:debcdd8c r4:debce048
[ 3857.494969] [<c018909c>] (__hrtimer_run_queues) from [<c018998c>]
(hrtimer_interrupt+0xc8/0x22c)
[ 3857.503774]  r10:debcddd8 r9:debcddb8 r8:debcddf8 r7:debcdd00
r6:debcdd40 r5:00000003
[ 3857.511758]  r4:ffffffff
[ 3857.514354] [<c01898c4>] (hrtimer_interrupt) from [<c067d994>]
(mxc_timer_interrupt+0x3c/0x44)
[ 3857.522985]  r10:c0d6c710 r9:e0805000 r8:de41d000 r7:00000010
r6:00000000 r5:00000000
[ 3857.530969]  r4:de402440
[ 3857.533568] [<c067d958>] (mxc_timer_interrupt) from [<c0177acc>]
(handle_irq_event_percpu+0x64/0x168)
[ 3857.542809]  r4:de402500 r3:c067d958
[ 3857.546482] [<c0177a68>] (handle_irq_event_percpu) from
[<c0177c10>] (handle_irq_event+0x40/0x64)
[ 3857.555374]  r10:de406000 r9:e0805000 r8:00000001 r7:00000000
r6:c0d10330 r5:de41d060
[ 3857.563358]  r4:de41d000
[ 3857.565956] [<c0177bd0>] (handle_irq_event) from [<c017b120>]
(handle_fasteoi_irq+0xd4/0x1ac)
[ 3857.574502]  r6:c0d10330 r5:de41d060 r4:de41d000 r3:00000000
[ 3857.580305] [<c017b04c>] (handle_fasteoi_irq) from [<c017726c>]
(generic_handle_irq+0x20/0x30)
[ 3857.588937]  r7:00000000 r6:c0c746ec r5:c0d02b10 r4:00000010
[ 3857.594743] [<c017724c>] (generic_handle_irq) from [<c01773b0>]
(__handle_domain_irq+0x6c/0xe4)
[ 3857.603485] [<c0177344>] (__handle_domain_irq) from [<c01015d8>]
(gic_handle_irq+0x4c/0x9c)
[ 3857.611857]  r10:000003eb r8:c0d22000 r7:c0d02c58 r6:dde7bd50
r5:e080400c r4:e0804000
[ 3857.619858] [<c010158c>] (gic_handle_irq) from [<c010c4b8>]
(__irq_svc+0x58/0x78)
[ 3857.627367] Exception stack(0xdde7bd50 to 0xdde7bd98)
[ 3857.632450] bd40:                                     ddce911c
00000001 00000000 00000003
[ 3857.640664] bd60: ddce911c c0d02a48 ddcea000 ddce90c0 c0108044
dde7a000 00000000 dde7bdb4
[ 3857.648875] bd80: dde7bdb8 dde7bda0 c064ad44 c01b247c 20000013 ffffffff
[ 3857.655509]  r10:00000000 r9:dde7a000 r8:c0108044 r7:dde7bd84
r6:ffffffff r5:20000013
[ 3857.663494]  r4:c01b247c r3:ddd9c800
[ 3857.667167] [<c01b2448>] (irq_work_sync) from [<c064ad44>]
(cpufreq_governor_dbs+0x170/0x580)
[ 3857.675713]  r4:00000004 r3:00000001
[ 3857.679384] [<c064abd4>] (cpufreq_governor_dbs) from [<c06480e4>]
(cpufreq_governor+0x64/0x120)
[ 3857.688103]  r10:00000000 r9:dde7a000 r8:c0108044 r7:c1556f80
r6:00000002 r5:ddcea000
[ 3857.696088]  r4:c0d4c5dc
[ 3857.698684] [<c0648080>] (cpufreq_governor) from [<c06493c4>]
(cpufreq_suspend+0x70/0x128)
[ 3857.706967]  r6:c0d4c328 r5:ddcea0dc r4:ddcea000 r3:ddd9c800
[ 3857.712777] [<c0649354>] (cpufreq_suspend) from [<c04da71c>]
(syscore_shutdown+0x4c/0x80)
[ 3857.720976]  r8:c0108044 r7:00000000 r6:c0d6e020 r5:c0d315a8
r4:c0d4c2fc r3:00000000
[ 3857.728895] [<c04da6d0>] (syscore_shutdown) from [<c0147aa8>]
(kernel_restart+0x1c/0x58)
[ 3857.737007]  r6:c0d13074 r5:4321fedc r4:00000000 r3:de434900
[ 3857.742805] [<c0147a8c>] (kernel_restart) from [<c0147cc4>]
(SyS_reboot+0x18c/0x1e4)
[ 3857.750569]  r4:01234567 r3:01234567
[ 3857.754234] [<c0147b38>] (SyS_reboot) from [<c0107ea0>]
(ret_fast_syscall+0x0/0x1c)
[ 3857.761910]  r7:00000058 r6:00000000 r5:00000000 r4:00000000
[ 3857.767707] rcu_sched kthread starved for 2602 jiffies! g1880 c1879
f0x2 RCU_GP_WAIT_FQS(3) ->state=0x0
[ 3857.777123] rcu_sched       R running      0     7      2 0x00000000
[ 3857.783558] Backtrace:
[ 3857.786076] [<c08f488c>] (__schedule) from [<c08f50d8>] (schedule+0x3c/0xa0)
[ 3857.793148]  r10:00000001 r9:00000003 r8:c0d02100 r7:0005636f
r6:debcd4c0 r5:debcd4c0
[ 3857.801133]  r4:de487e9c
[ 3857.803728] [<c08f509c>] (schedule) from [<c08f941c>]
(schedule_timeout+0x138/0x1cc)
[ 3857.811509] [<c08f92e4>] (schedule_timeout) from [<c0184bf0>]
(rcu_gp_kthread+0x3b0/0x894)
[ 3857.819794]  r8:00000000 r7:000002b8 r6:00000001 r5:c0d14e10 r4:c0d14b80
[ 3857.826667] [<c0184840>] (rcu_gp_kthread) from [<c0144e7c>]
(kthread+0xd8/0xf4)
[ 3857.833997]  r7:c0184840
[ 3857.836593] [<c0144da4>] (kthread) from [<c0107f30>]
(ret_from_fork+0x14/0x24)
[ 3857.843836]  r7:00000000 r6:00000000 r5:c0144da4 r4:de435040


From yendapally.reddy at broadcom.com  Fri May 20 11:05:49 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Fri, 20 May 2016 14:05:49 -0400
Subject: [PATCH v2 0/3] pwm support for Broadcom iProc SoC's
Message-ID: <1463767552-30670-1-git-send-email-yendapally.reddy@broadcom.com>

This patchset contains the pwm support for the Broadcom's iProc SoC's.

The first patch provides the documentation details and the
second patch contains the controller support details. The third patch
contains the enable method for Northstar Plus SoC.

This patch series has been tested on NSP bcm958625HR board.
The pwm is not enabled for this board as the pins are open and not used.

This patch series is based on v4.6.0-rc1 and is available from github
repo: https://github.com/Broadcom/cygnus-linux.git
branch: iproc-pwm-v2

Changes since v1

Addressed the review comments from Thierry
 1. Use separate driver for iProc SoC's.
 2. Added Robs ack to the Documentation patch

Yendapally Reddy Dhananjaya Reddy (3):
  Documentation: dt: Add Broadcom iproc pwm controller binding
  pwm: iproc: Add support for Broadcom iproc pwm controller
  ARM: dts: NSP: Add PWM Support to DT

 .../devicetree/bindings/pwm/brcm,iproc-pwm.txt     |  21 ++
 arch/arm/boot/dts/bcm-nsp.dtsi                     |   8 +
 drivers/pwm/Kconfig                                |  10 +
 drivers/pwm/Makefile                               |   1 +
 drivers/pwm/pwm-bcm-iproc.c                        | 320 +++++++++++++++++++++
 5 files changed, 360 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
 create mode 100644 drivers/pwm/pwm-bcm-iproc.c

-- 
2.1.0



From yendapally.reddy at broadcom.com  Fri May 20 11:05:50 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Fri, 20 May 2016 14:05:50 -0400
Subject: [PATCH v2 1/3] Documentation: dt: Add Broadcom iproc pwm controller
 binding
In-Reply-To: <1463767552-30670-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1463767552-30670-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1463767552-30670-2-git-send-email-yendapally.reddy@broadcom.com>

Add a binding for Broadcom iproc pwm controller

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/pwm/brcm,iproc-pwm.txt      | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt

diff --git a/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt b/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
new file mode 100644
index 0000000..21f75bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
@@ -0,0 +1,21 @@
+Broadcom iProc PWM controller device tree bindings
+
+This controller has 4 channels.
+
+Required Properties :
+- compatible: must be "brcm,iproc-pwm"
+- reg: physical base address and length of the controller's registers
+- clocks: phandle + clock specifier pair for the external clock
+- #pwm-cells: Should be 3. See pwm.txt in this directory for a
+  description of the cells format.
+
+Refer to clocks/clock-bindings.txt for generic clock consumer properties.
+
+Example:
+
+pwm: pwm at 18031000 {
+	compatible = "brcm,iproc-pwm";
+	reg = <0x18031000 0x28>;
+	clocks = <&osc>;
+	#pwm-cells = <3>;
+};
-- 
2.1.0



From yendapally.reddy at broadcom.com  Fri May 20 11:05:51 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Fri, 20 May 2016 14:05:51 -0400
Subject: [PATCH v2 2/3] pwm: iproc: Add support for Broadcom iproc pwm
 controller
In-Reply-To: <1463767552-30670-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1463767552-30670-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1463767552-30670-3-git-send-email-yendapally.reddy@broadcom.com>

Add support for the PWM controller present in Broadcom's iProc
family of SoCs. This driver is derived from the pwm-bcm-kona
driver, with changes to the register offsets and bit positions.
It has been tested on the  Northstar+ bcm958625HR board.

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
---
 drivers/pwm/Kconfig         |  10 ++
 drivers/pwm/Makefile        |   1 +
 drivers/pwm/pwm-bcm-iproc.c | 320 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 331 insertions(+)
 create mode 100644 drivers/pwm/pwm-bcm-iproc.c

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index c182efc..d298ebd 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -74,6 +74,16 @@ config PWM_ATMEL_TCB
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-atmel-tcb.
 
+config PWM_BCM_IPROC
+	tristate "iProc PWM support"
+	depends on ARCH_BCM_IPROC
+	help
+	  Generic PWM framework driver for Broadcom iProc PWM block. This
+	  block is used in Broadcom iProc SoC's.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-bcm-iproc.
+
 config PWM_BCM_KONA
 	tristate "Kona PWM support"
 	depends on ARCH_BCM_MOBILE
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index dd35bc1..a196d79 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_PWM_AB8500)	+= pwm-ab8500.o
 obj-$(CONFIG_PWM_ATMEL)		+= pwm-atmel.o
 obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM)	+= pwm-atmel-hlcdc.o
 obj-$(CONFIG_PWM_ATMEL_TCB)	+= pwm-atmel-tcb.o
+obj-$(CONFIG_PWM_BCM_IPROC)	+= pwm-bcm-iproc.o
 obj-$(CONFIG_PWM_BCM_KONA)	+= pwm-bcm-kona.o
 obj-$(CONFIG_PWM_BCM2835)	+= pwm-bcm2835.o
 obj-$(CONFIG_PWM_BERLIN)	+= pwm-berlin.o
diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c
new file mode 100644
index 0000000..3ba3ca5
--- /dev/null
+++ b/drivers/pwm/pwm-bcm-iproc.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+
+#define IPROC_PWM_CTRL_OFFSET			(0x00)
+#define IPROC_PWM_CTRL_TYPE_SHIFT(chan)		(15 + (chan))
+#define IPROC_PWM_CTRL_POLARITY_SHIFT(chan)	(8 + (chan))
+#define IPROC_PWM_CTRL_EN_SHIFT(chan)		(chan)
+
+#define IPROC_PWM_PERIOD_OFFSET(chan)		(0x04 + ((chan) << 3))
+#define IPROC_PWM_PERIOD_MIN			(0x02)
+#define IPROC_PWM_PERIOD_MAX			(0xffff)
+
+#define IPROC_PWM_DUTY_CYCLE_OFFSET(chan)	(0x08 + ((chan) << 3))
+#define IPROC_PWM_DUTY_CYCLE_MIN		(0x00)
+#define IPROC_PWM_DUTY_CYCLE_MAX		(0xffff)
+
+#define IPROC_PWM_PRESCALE_OFFSET		(0x24)
+#define IPROC_PWM_PRESCALE_BITS			(0x06)
+#define IPROC_PWM_PRESCALE_SHIFT(chan)		((3 - (chan)) *	\
+						IPROC_PWM_PRESCALE_BITS)
+#define IPROC_PWM_PRESCALE_MASK(chan)		(IPROC_PWM_PRESCALE_MAX << \
+						IPROC_PWM_PRESCALE_SHIFT(chan))
+#define IPROC_PWM_PRESCALE_MIN			(0x00)
+#define IPROC_PWM_PRESCALE_MAX			(0x3f)
+
+#define IPROC_PWM_CHANNEL_COUNT			(0x04)
+
+struct iproc_pwmc {
+	struct pwm_chip chip;
+	void __iomem *base;
+	struct clk *clk;
+};
+
+static inline struct iproc_pwmc *to_iproc_pwmc(struct pwm_chip *_chip)
+{
+	return container_of(_chip, struct iproc_pwmc, chip);
+}
+
+static void iproc_pwmc_unset_enable_bit(struct iproc_pwmc *ip, u32 chan)
+{
+	unsigned int value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+
+	value &= ~(1 << IPROC_PWM_CTRL_EN_SHIFT(chan));
+	writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+	/*
+	 * There must be a min 400ns delay between clearing trigger and setting
+	 * it. Failing to do this may result in no PWM signal.
+	 */
+	ndelay(400);
+}
+
+static void iproc_pwmc_set_enable_bit(struct iproc_pwmc *ip, unsigned int chan)
+{
+	unsigned int value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+
+	/* Set trigger bit to apply new settings */
+	value |= 1 << IPROC_PWM_CTRL_EN_SHIFT(chan);
+	writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+	/* Trigger bit must be held high for at least 400 ns. */
+	ndelay(400);
+}
+
+static int iproc_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm,
+			     int duty_ns, int period_ns)
+{
+	unsigned long prescale = IPROC_PWM_PRESCALE_MIN;
+	struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+	unsigned int value, chan = pwm->hwpwm;
+	unsigned long period_cnt, duty_cnt;
+	u64 val, div, rate;
+
+	rate = clk_get_rate(ip->clk);
+	if (!rate) {
+		dev_err(pwm->chip->dev, "pwm clock has no frequency\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Find period count, duty count and prescale to suit duty_ns and
+	 * period_ns. This is done according to formulas described below:
+	 *
+	 * period_ns = 10^9 * (PRESCALE + 1) * PC / PWM_CLK_RATE
+	 * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
+	 *
+	 * PC = (PWM_CLK_RATE * period_ns) / (10^9 * (PRESCALE + 1))
+	 * DC = (PWM_CLK_RATE * duty_ns) / (10^9 * (PRESCALE + 1))
+	 */
+	while (1) {
+		div = 1000000000;
+		div *= 1 + prescale;
+		val = rate * period_ns;
+		period_cnt = div64_u64(val, div);
+		val = rate * duty_ns;
+		duty_cnt = div64_u64(val, div);
+
+		if (period_cnt < IPROC_PWM_PERIOD_MIN ||
+				duty_cnt < IPROC_PWM_DUTY_CYCLE_MIN)
+			return -EINVAL;
+
+		if (period_cnt <= IPROC_PWM_PERIOD_MAX &&
+				 duty_cnt <= IPROC_PWM_DUTY_CYCLE_MAX)
+			break;
+
+		/* Otherwise, increase prescale and recalculate counts */
+		if (++prescale > IPROC_PWM_PRESCALE_MAX)
+			return -EINVAL;
+	}
+
+	/*
+	 * Don't apply settings if disabled. The period and duty cycle are
+	 * always calculated above to ensure the new values are
+	 * validated immediately instead of on enable.
+	 */
+	if (pwm_is_enabled(pwm)) {
+		iproc_pwmc_unset_enable_bit(ip, chan);
+
+		value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
+		value &= ~IPROC_PWM_PRESCALE_MASK(chan);
+		value |= prescale << IPROC_PWM_PRESCALE_SHIFT(chan);
+
+		writel(value, ip->base + IPROC_PWM_PRESCALE_OFFSET);
+		writel(period_cnt, ip->base + IPROC_PWM_PERIOD_OFFSET(chan));
+		writel(duty_cnt, ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(chan));
+
+		iproc_pwmc_set_enable_bit(ip, chan);
+	}
+
+	return 0;
+}
+
+static int iproc_pwmc_set_polarity(struct pwm_chip *chip,
+				   struct pwm_device *pwm,
+				   enum pwm_polarity polarity)
+{
+	struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+	unsigned int chan = pwm->hwpwm;
+	unsigned int value;
+	int ret;
+
+	ret = clk_prepare_enable(ip->clk);
+	if (ret < 0) {
+		dev_err(chip->dev, "failed to enable clock: %d\n", ret);
+		return ret;
+	}
+
+	iproc_pwmc_unset_enable_bit(ip, chan);
+
+	value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+	if (polarity == PWM_POLARITY_NORMAL)
+		value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(chan);
+	else
+		value &= ~(1 << IPROC_PWM_CTRL_POLARITY_SHIFT(chan));
+	writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+	iproc_pwmc_set_enable_bit(ip, chan);
+
+	clk_disable_unprepare(ip->clk);
+
+	return 0;
+}
+
+static int iproc_pwmc_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+	int ret;
+
+	ret = clk_prepare_enable(ip->clk);
+	if (ret < 0) {
+		dev_err(chip->dev, "failed to enable clock: %d\n", ret);
+		return ret;
+	}
+
+	ret = iproc_pwmc_config(chip, pwm, pwm_get_duty_cycle(pwm),
+						pwm_get_period(pwm));
+	if (ret < 0) {
+		clk_disable_unprepare(ip->clk);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void iproc_pwmc_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+	unsigned int chan = pwm->hwpwm;
+	unsigned int value;
+
+	iproc_pwmc_unset_enable_bit(ip, chan);
+
+	writel(0, ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(chan));
+	writel(0, ip->base + IPROC_PWM_PERIOD_OFFSET(chan));
+
+	/* Set prescale to 0 for this channel */
+	value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
+	value &= ~IPROC_PWM_PRESCALE_MASK(chan);
+	writel(value, ip->base + IPROC_PWM_PRESCALE_OFFSET);
+
+	iproc_pwmc_set_enable_bit(ip, chan);
+
+	clk_disable_unprepare(ip->clk);
+}
+
+static const struct pwm_ops iproc_pwm_ops = {
+	.config = iproc_pwmc_config,
+	.set_polarity = iproc_pwmc_set_polarity,
+	.enable = iproc_pwmc_enable,
+	.disable = iproc_pwmc_disable,
+	.owner = THIS_MODULE,
+};
+
+static int iproc_pwmc_probe(struct platform_device *pdev)
+{
+	struct iproc_pwmc *ip;
+	struct resource *res;
+	unsigned int value;
+	unsigned int chan;
+	int ret;
+
+	ip = devm_kzalloc(&pdev->dev, sizeof(*ip), GFP_KERNEL);
+	if (ip == NULL)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ip);
+
+	ip->chip.dev = &pdev->dev;
+	ip->chip.ops = &iproc_pwm_ops;
+	ip->chip.base = -1;
+	ip->chip.npwm = IPROC_PWM_CHANNEL_COUNT;
+	ip->chip.of_xlate = of_pwm_xlate_with_flags;
+	ip->chip.of_pwm_n_cells = 3;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ip->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ip->base))
+		return PTR_ERR(ip->base);
+
+	ip->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(ip->clk)) {
+		dev_err(&pdev->dev, "failed to get clock: %ld\n",
+			PTR_ERR(ip->clk));
+		return PTR_ERR(ip->clk);
+	}
+
+	ret = clk_prepare_enable(ip->clk);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to enable clock: %d\n", ret);
+		return ret;
+	}
+
+	/* Set full drive and normal polarity for all channels */
+	value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+	for (chan = 0; chan < ip->chip.npwm; chan++) {
+		value &= ~(1 << IPROC_PWM_CTRL_TYPE_SHIFT(chan));
+		value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(chan);
+	}
+	writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+	clk_disable_unprepare(ip->clk);
+
+	ret = pwmchip_add(&ip->chip);
+	if (ret < 0)
+		dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
+
+	return ret;
+}
+
+static int iproc_pwmc_remove(struct platform_device *pdev)
+{
+	struct iproc_pwmc *ip = platform_get_drvdata(pdev);
+	unsigned int chan;
+
+	for (chan = 0; chan < ip->chip.npwm; chan++)
+		if (pwm_is_enabled(&ip->chip.pwms[chan]))
+			clk_disable_unprepare(ip->clk);
+
+	return pwmchip_remove(&ip->chip);
+}
+
+static const struct of_device_id bcm_iproc_pwmc_dt[] = {
+	{ .compatible = "brcm,iproc-pwm" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, bcm_iproc_pwmc_dt);
+
+static struct platform_driver iproc_pwmc_driver = {
+	.driver = {
+		.name = "bcm-iproc-pwm",
+		.of_match_table = bcm_iproc_pwmc_dt,
+	},
+	.probe = iproc_pwmc_probe,
+	.remove = iproc_pwmc_remove,
+};
+module_platform_driver(iproc_pwmc_driver);
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom iProc PWM driver");
+MODULE_LICENSE("GPL v2");
-- 
2.1.0



From yendapally.reddy at broadcom.com  Fri May 20 11:05:52 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Fri, 20 May 2016 14:05:52 -0400
Subject: [PATCH v2 3/3] ARM: dts: NSP: Add PWM Support to DT
In-Reply-To: <1463767552-30670-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1463767552-30670-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1463767552-30670-4-git-send-email-yendapally.reddy@broadcom.com>

Add PWM support to the device tree for the Broadcom Northstar Plus SoC.

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
---
 arch/arm/boot/dts/bcm-nsp.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi
index def9e78..f9c8341 100644
--- a/arch/arm/boot/dts/bcm-nsp.dtsi
+++ b/arch/arm/boot/dts/bcm-nsp.dtsi
@@ -206,6 +206,14 @@
 			brcm,nand-has-wp;
 		};
 
+		pwm: pwm at 31000 {
+			compatible = "brcm,iproc-pwm";
+			reg = <0x31000 0x28>;
+			clocks = <&osc>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
 		ccbtimer0: timer at 34000 {
 			compatible = "arm,sp804";
 			reg = <0x34000 0x1000>;
-- 
2.1.0



From f.fainelli at gmail.com  Fri May 20 11:11:20 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 20 May 2016 11:11:20 -0700
Subject: [PATCH] arm64: vulcan: enable GPIOLIB in Kconfig
In-Reply-To: <1461819767-17539-1-git-send-email-kamlakant.patel@broadcom.com>
References: <1461819767-17539-1-git-send-email-kamlakant.patel@broadcom.com>
Message-ID: <573F5348.6040907@gmail.com>

On 04/27/2016 10:02 PM, kamlakant.patel at broadcom.com wrote:
> From: Kamlakant Patel <kamlakant.patel at broadcom.com>
> 
> Add select GPIOLIB in Kconfig for Broadcom Vulcan ARM64 GPIO driver.
> 
> Signed-off-by: Kamlakant Patel <kamlakant.patel at broadcom.com>

Applied to soc-arm64/next, thanks!
-- 
Florian


From festevam at gmail.com  Fri May 20 11:32:43 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Fri, 20 May 2016 15:32:43 -0300
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
Message-ID: <CAOMZO5D_-3St-jqzMLzFHRn3dXXoSZGn4APSK4F63qCP3X=FfA@mail.gmail.com>

On Fri, May 20, 2016 at 3:05 PM, Fabio Estevam <festevam at gmail.com> wrote:
> Rafael,
>
> Running the 'reboot' command works fine on a 4.5 kernel running on a
> mx6ul platform (ARM single core SoC), but it crashes on 4.6.
>
> Running bisect I got 9be4fd2c7723a3057b0b39676 ("cpufreq: governor:
> Replace timers with utilization update callbacks") as the first bad
> commit.
>
> Below is the output crash log.
>
> Not sure if this issue is related to the problem reported by Guenter here:
> http://lkml.iu.edu/hypermail/linux/kernel/1602.1/06075.html
>
> Any ideas?

If I rebuilt a kernel with SMP=n then the reboot command works as expected.

>
> Thanks,
>
> Fabio Estevam
>
>
> [ 3857.373588] INFO: rcu_sched detected stalls on CPUs/tasks:
> [ 3857.379155]  (detected by 0, t=2602 jiffies, g=1880, c=1879, q=29)
> [ 3857.385406] All QSes seen, last rcu_sched kthread activity 2602
> (355736-353134), jiffies_till_next_fqs=1, root ->qsmask 0x0
> [ 3857.396562] init            R running      0   864      1 0x00000002
> [ 3857.402999] Backtrace:
> [ 3857.405532] [<c010b6e8>] (dump_backtrace) from [<c010b884>]
> (show_stack+0x18/0x1c)
> [ 3857.413125]  r6:c0d6c6d6 r5:00000001 r4:ddd9c800 r3:00000000
> [ 3857.418941] [<c010b86c>] (show_stack) from [<c014fc3c>]
> (sched_show_task+0x124/0x234)
> [ 3857.426820] [<c014fb18>] (sched_show_task) from [<c0185e24>]
> (rcu_check_callbacks+0x844/0x894)
> [ 3857.435452]  r6:c0c76b40 r5:c0d14b80 r4:debd0b40
> [ 3857.440189] [<c01855e0>] (rcu_check_callbacks) from [<c018884c>]
> (update_process_times+0x38/0x64)
> [ 3857.449081]  r10:c0d21e1c r9:debcdd10 r8:c019a230 r7:dde7bd50
> r6:debce048 r5:00000000
> [ 3857.457067]  r4:ddd9c800
> [ 3857.459665] [<c0188814>] (update_process_times) from [<c019a174>]
> (tick_sched_handle+0x50/0x54)
> [ 3857.468386]  r5:00000382 r4:1c92d15d
> [ 3857.472048] [<c019a124>] (tick_sched_handle) from [<c019a290>]
> (tick_sched_timer+0x60/0xa8)
> [ 3857.480443] [<c019a230>] (tick_sched_timer) from [<c018915c>]
> (__hrtimer_run_queues+0xc0/0x1c8)
> [ 3857.489162]  r7:debcdd80 r6:debcdd00 r5:debcdd8c r4:debce048
> [ 3857.494969] [<c018909c>] (__hrtimer_run_queues) from [<c018998c>]
> (hrtimer_interrupt+0xc8/0x22c)
> [ 3857.503774]  r10:debcddd8 r9:debcddb8 r8:debcddf8 r7:debcdd00
> r6:debcdd40 r5:00000003
> [ 3857.511758]  r4:ffffffff
> [ 3857.514354] [<c01898c4>] (hrtimer_interrupt) from [<c067d994>]
> (mxc_timer_interrupt+0x3c/0x44)
> [ 3857.522985]  r10:c0d6c710 r9:e0805000 r8:de41d000 r7:00000010
> r6:00000000 r5:00000000
> [ 3857.530969]  r4:de402440
> [ 3857.533568] [<c067d958>] (mxc_timer_interrupt) from [<c0177acc>]
> (handle_irq_event_percpu+0x64/0x168)
> [ 3857.542809]  r4:de402500 r3:c067d958
> [ 3857.546482] [<c0177a68>] (handle_irq_event_percpu) from
> [<c0177c10>] (handle_irq_event+0x40/0x64)
> [ 3857.555374]  r10:de406000 r9:e0805000 r8:00000001 r7:00000000
> r6:c0d10330 r5:de41d060
> [ 3857.563358]  r4:de41d000
> [ 3857.565956] [<c0177bd0>] (handle_irq_event) from [<c017b120>]
> (handle_fasteoi_irq+0xd4/0x1ac)
> [ 3857.574502]  r6:c0d10330 r5:de41d060 r4:de41d000 r3:00000000
> [ 3857.580305] [<c017b04c>] (handle_fasteoi_irq) from [<c017726c>]
> (generic_handle_irq+0x20/0x30)
> [ 3857.588937]  r7:00000000 r6:c0c746ec r5:c0d02b10 r4:00000010
> [ 3857.594743] [<c017724c>] (generic_handle_irq) from [<c01773b0>]
> (__handle_domain_irq+0x6c/0xe4)
> [ 3857.603485] [<c0177344>] (__handle_domain_irq) from [<c01015d8>]
> (gic_handle_irq+0x4c/0x9c)
> [ 3857.611857]  r10:000003eb r8:c0d22000 r7:c0d02c58 r6:dde7bd50
> r5:e080400c r4:e0804000
> [ 3857.619858] [<c010158c>] (gic_handle_irq) from [<c010c4b8>]
> (__irq_svc+0x58/0x78)
> [ 3857.627367] Exception stack(0xdde7bd50 to 0xdde7bd98)
> [ 3857.632450] bd40:                                     ddce911c
> 00000001 00000000 00000003
> [ 3857.640664] bd60: ddce911c c0d02a48 ddcea000 ddce90c0 c0108044
> dde7a000 00000000 dde7bdb4
> [ 3857.648875] bd80: dde7bdb8 dde7bda0 c064ad44 c01b247c 20000013 ffffffff
> [ 3857.655509]  r10:00000000 r9:dde7a000 r8:c0108044 r7:dde7bd84
> r6:ffffffff r5:20000013
> [ 3857.663494]  r4:c01b247c r3:ddd9c800
> [ 3857.667167] [<c01b2448>] (irq_work_sync) from [<c064ad44>]
> (cpufreq_governor_dbs+0x170/0x580)
> [ 3857.675713]  r4:00000004 r3:00000001
> [ 3857.679384] [<c064abd4>] (cpufreq_governor_dbs) from [<c06480e4>]
> (cpufreq_governor+0x64/0x120)
> [ 3857.688103]  r10:00000000 r9:dde7a000 r8:c0108044 r7:c1556f80
> r6:00000002 r5:ddcea000
> [ 3857.696088]  r4:c0d4c5dc
> [ 3857.698684] [<c0648080>] (cpufreq_governor) from [<c06493c4>]
> (cpufreq_suspend+0x70/0x128)
> [ 3857.706967]  r6:c0d4c328 r5:ddcea0dc r4:ddcea000 r3:ddd9c800
> [ 3857.712777] [<c0649354>] (cpufreq_suspend) from [<c04da71c>]
> (syscore_shutdown+0x4c/0x80)
> [ 3857.720976]  r8:c0108044 r7:00000000 r6:c0d6e020 r5:c0d315a8
> r4:c0d4c2fc r3:00000000
> [ 3857.728895] [<c04da6d0>] (syscore_shutdown) from [<c0147aa8>]
> (kernel_restart+0x1c/0x58)
> [ 3857.737007]  r6:c0d13074 r5:4321fedc r4:00000000 r3:de434900
> [ 3857.742805] [<c0147a8c>] (kernel_restart) from [<c0147cc4>]
> (SyS_reboot+0x18c/0x1e4)
> [ 3857.750569]  r4:01234567 r3:01234567
> [ 3857.754234] [<c0147b38>] (SyS_reboot) from [<c0107ea0>]
> (ret_fast_syscall+0x0/0x1c)
> [ 3857.761910]  r7:00000058 r6:00000000 r5:00000000 r4:00000000
> [ 3857.767707] rcu_sched kthread starved for 2602 jiffies! g1880 c1879
> f0x2 RCU_GP_WAIT_FQS(3) ->state=0x0
> [ 3857.777123] rcu_sched       R running      0     7      2 0x00000000
> [ 3857.783558] Backtrace:
> [ 3857.786076] [<c08f488c>] (__schedule) from [<c08f50d8>] (schedule+0x3c/0xa0)
> [ 3857.793148]  r10:00000001 r9:00000003 r8:c0d02100 r7:0005636f
> r6:debcd4c0 r5:debcd4c0
> [ 3857.801133]  r4:de487e9c
> [ 3857.803728] [<c08f509c>] (schedule) from [<c08f941c>]
> (schedule_timeout+0x138/0x1cc)
> [ 3857.811509] [<c08f92e4>] (schedule_timeout) from [<c0184bf0>]
> (rcu_gp_kthread+0x3b0/0x894)
> [ 3857.819794]  r8:00000000 r7:000002b8 r6:00000001 r5:c0d14e10 r4:c0d14b80
> [ 3857.826667] [<c0184840>] (rcu_gp_kthread) from [<c0144e7c>]
> (kthread+0xd8/0xf4)
> [ 3857.833997]  r7:c0184840
> [ 3857.836593] [<c0144da4>] (kthread) from [<c0107f30>]
> (ret_from_fork+0x14/0x24)
> [ 3857.843836]  r7:00000000 r6:00000000 r5:c0144da4 r4:de435040


From f.fainelli at gmail.com  Fri May 20 11:38:15 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 20 May 2016 11:38:15 -0700
Subject: [PATCH] soc: Move brcmstb to bcm/brcmstb
Message-ID: <1463769495-10072-1-git-send-email-f.fainelli@gmail.com>

Unify the different Broadcom SoCs directory and have everybody live
under drivers/soc/bcm/*.

Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
 drivers/soc/Kconfig                     |  1 -
 drivers/soc/Makefile                    |  1 -
 drivers/soc/bcm/Kconfig                 | 15 +++++++++++++++
 drivers/soc/bcm/Makefile                |  1 +
 drivers/soc/{ => bcm}/brcmstb/Makefile  |  0
 drivers/soc/{ => bcm}/brcmstb/biuctrl.c |  0
 drivers/soc/{ => bcm}/brcmstb/common.c  |  0
 drivers/soc/brcmstb/Kconfig             | 10 ----------
 8 files changed, 16 insertions(+), 12 deletions(-)
 rename drivers/soc/{ => bcm}/brcmstb/Makefile (100%)
 rename drivers/soc/{ => bcm}/brcmstb/biuctrl.c (100%)
 rename drivers/soc/{ => bcm}/brcmstb/common.c (100%)
 delete mode 100644 drivers/soc/brcmstb/Kconfig

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cb58ef0d9b2c..91d5c05d395f 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -1,7 +1,6 @@
 menu "SOC (System On Chip) specific Drivers"
 
 source "drivers/soc/bcm/Kconfig"
-source "drivers/soc/brcmstb/Kconfig"
 source "drivers/soc/fsl/qe/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 380230f03874..b75e3bd0a01e 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -3,7 +3,6 @@
 #
 
 obj-y				+= bcm/
-obj-$(CONFIG_SOC_BRCMSTB)	+= brcmstb/
 obj-$(CONFIG_ARCH_DOVE)		+= dove/
 obj-$(CONFIG_MACH_DOVE)		+= dove/
 obj-y				+= fsl/
diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig
index 3066edea184d..97156aeed286 100644
--- a/drivers/soc/bcm/Kconfig
+++ b/drivers/soc/bcm/Kconfig
@@ -1,3 +1,5 @@
+menu "Broadcom SoC drivers"
+
 config RASPBERRYPI_POWER
 	bool "Raspberry Pi power domain driver"
 	depends on ARCH_BCM2835 || COMPILE_TEST
@@ -7,3 +9,16 @@ config RASPBERRYPI_POWER
 	help
 	  This enables support for the RPi power domains which can be enabled
 	  or disabled via the RPi firmware.
+
+config SOC_BRCMSTB
+	bool "Broadcom STB SoC drivers"
+	depends on ARM
+	select SOC_BUS
+	help
+	  Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
+	  This option alone enables only some support code, while the drivers
+	  can be enabled individually within this menu.
+
+	  If unsure, say N.
+
+endmenu
diff --git a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile
index 63aa3eb23087..dc4fced72d21 100644
--- a/drivers/soc/bcm/Makefile
+++ b/drivers/soc/bcm/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_RASPBERRYPI_POWER)	+= raspberrypi-power.o
+obj-$(CONFIG_SOC_BRCMSTB)	+= brcmstb/
diff --git a/drivers/soc/brcmstb/Makefile b/drivers/soc/bcm/brcmstb/Makefile
similarity index 100%
rename from drivers/soc/brcmstb/Makefile
rename to drivers/soc/bcm/brcmstb/Makefile
diff --git a/drivers/soc/brcmstb/biuctrl.c b/drivers/soc/bcm/brcmstb/biuctrl.c
similarity index 100%
rename from drivers/soc/brcmstb/biuctrl.c
rename to drivers/soc/bcm/brcmstb/biuctrl.c
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c
similarity index 100%
rename from drivers/soc/brcmstb/common.c
rename to drivers/soc/bcm/brcmstb/common.c
diff --git a/drivers/soc/brcmstb/Kconfig b/drivers/soc/brcmstb/Kconfig
deleted file mode 100644
index 7fec3b4c80a1..000000000000
--- a/drivers/soc/brcmstb/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-menuconfig SOC_BRCMSTB
-	bool "Broadcom STB SoC drivers"
-	depends on ARM
-	select SOC_BUS
-	help
-	  Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
-	  This option alone enables only some support code, while the drivers
-	  can be enabled individually within this menu.
-
-	  If unsure, say N.
-- 
2.7.4



From f.fainelli at gmail.com  Fri May 20 11:45:39 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 20 May 2016 11:45:39 -0700
Subject: [PATCH 2/2] arm64: dts: NS2: Add CCI-400 PMU support
In-Reply-To: <1463007369-13071-2-git-send-email-jonmason@broadcom.com>
References: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
 <1463007369-13071-2-git-send-email-jonmason@broadcom.com>
Message-ID: <573F5B53.2090304@gmail.com>

On 05/11/2016 03:56 PM, Jon Mason wrote:
> Add support to the Northstar 2 Device tree file for the ARM CCI-400 PMU.
> 
> Signed-off-by: Jon Mason <jonmason at broadcom.com>

Also applied to devicetree-arm64/next, thanks Jon!
-- 
Florian


From f.fainelli at gmail.com  Fri May 20 11:45:48 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 20 May 2016 11:45:48 -0700
Subject: [PATCH 1/2] arm64: dts: NS2: Add all of the UARTs
In-Reply-To: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
References: <1463007369-13071-1-git-send-email-jonmason@broadcom.com>
Message-ID: <573F5B5C.7080407@gmail.com>

On 05/11/2016 03:56 PM, Jon Mason wrote:
> Add all of the UARTs present on NS2 and enable them in the SVK device
> tree file.  Also, do some magic to make sure that uart3 is discovered as
> ttyS0 (as that is the console UART).
> 
> Signed-off-by: Jon Mason <jonmason at broadcom.com>

Applied to devicetree-arm64/next, thanks Jon!
-- 
Florian


From arnd at arndb.de  Fri May 20 12:01:24 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 20 May 2016 21:01:24 +0200
Subject: [GIT PULL 0/7] ARM: SoC changes for 4.7
In-Reply-To: <87eg8xj018.fsf@belgarion.home>
References: <8749147.ztcb6kVhye@wuerfel> <87eg8xj018.fsf@belgarion.home>
Message-ID: <201605202101.24832.arnd@arndb.de>

On Thursday 19 May 2016, Robert Jarzmik wrote:
> Arnd Bergmann <arnd at arndb.de> writes:
> 
> .. zip ... removed Linux and lkml as this is pxa specific.
> 
> > Hi Linus,
> >
> > These are the first seven pull requests for arm-soc this time, there is
> > one small follow-up coming once the dependencies for that have landed
> > in your tree.
> I was wondering if my pull requests will be part of this follow-up ?
> I'm speaking of :
>  - https://patchwork.ozlabs.org/patch/617118/
>  - https://patchwork.ozlabs.org/patch/617119/ 
>
Hmm, no they were not part of this.

> Even if from my persespective passing this cycle doesn't matter much, I don't
> know if this matters to Stephen as CLK_IS_ROOT will remain one more cycle.

I'm very sorry I completely missed the pull requests. I've the first one in the
fixes branch now, so it should be in v4.7rc1 after all.

I also considered pulling the second branch into late/next, as it looks small
and harmless and you did send it in time, but as you say here it's not really
urgent either.	Just let me know if you want me to pick up "
ARM: dts: pxa: fix the ohci clock for pxa3xx" in the fixes branch as well,
I can cherry-pick the commit directly.

	Arnd


From f.fainelli at gmail.com  Fri May 20 12:07:25 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 20 May 2016 12:07:25 -0700
Subject: [PATCH 0/7] ARM: multi_v7_defconfig: Add more Broadcom SoCs
Message-ID: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>

This patch series enables more fundamental drivers which are useful for
Broadcom BCM63xx and BCM7xxx SoCs.

The last patch remove bcm_defconfig which is causing a whole lot of confusiong
at best and is completely out of sync now.

Florian Fainelli (7):
  ARM: multi_v7_defconfig: Enable BCM63xx
  ARM: multi_v7_defconfig: Enable BRCMSTB networking
  ARM: multi_v7_defconfig: Enable BRCMSTB AHCI
  ARM: multi_v7_defconfig: Enable BCM7038 Watchdog
  ARM: multi_v7_defconfig: Enable Broadcom STB PWM
  ARM: multi_v7_defconfig: Enable Broadcom Kona watchdog
  ARM: Remove bcm_defconfig

 arch/arm/configs/bcm_defconfig      | 142 ------------------------------------
 arch/arm/configs/multi_v7_defconfig |  13 ++++
 2 files changed, 13 insertions(+), 142 deletions(-)
 delete mode 100644 arch/arm/configs/bcm_defconfig

-- 
2.7.4



From f.fainelli at gmail.com  Fri May 20 12:07:30 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 20 May 2016 12:07:30 -0700
Subject: [PATCH 5/7] ARM: multi_v7_defconfig: Enable Broadcom STB PWM
In-Reply-To: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
References: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1463771252-12805-6-git-send-email-f.fainelli@gmail.com>

Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 13e5af6334ac..b59081bda51b 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -816,6 +816,7 @@ CONFIG_PWM_VT8500=y
 CONFIG_PHY_HIX5HD2_SATA=y
 CONFIG_PWM_STI=y
 CONFIG_PWM_BCM2835=y
+CONFIG_PWM_BRCMSTB=m
 CONFIG_OMAP_USB2=y
 CONFIG_TI_PIPE3=y
 CONFIG_PHY_BERLIN_USB=y
-- 
2.7.4



From f.fainelli at gmail.com  Fri May 20 12:07:27 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 20 May 2016 12:07:27 -0700
Subject: [PATCH 2/7] ARM: multi_v7_defconfig: Enable BRCMSTB networking
In-Reply-To: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
References: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1463771252-12805-3-git-send-email-f.fainelli@gmail.com>

Enable the required drivers and subsystems to bring-up networking on
Broadcom's Set-top Box SoCs: BCMGENET and SF2. These two drivers both
have proper dependencies on their internal PHY and MDIO drivers.

Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
 arch/arm/configs/multi_v7_defconfig | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 968a7ec08633..31ed7318f406 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -158,6 +158,8 @@ CONFIG_INET6_IPCOMP=m
 CONFIG_IPV6_MIP6=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NET_DSA=m
+CONFIG_NET_SWITCHDEV=y
 CONFIG_CAN=y
 CONFIG_CAN_RAW=y
 CONFIG_CAN_BCM=y
@@ -166,6 +168,7 @@ CONFIG_CAN_AT91=m
 CONFIG_CAN_RCAR=m
 CONFIG_CAN_XILINXCAN=y
 CONFIG_CAN_MCP251X=y
+CONFIG_NET_DSA_BCM_SF2=m
 CONFIG_CAN_SUN4I=y
 CONFIG_BT=m
 CONFIG_BT_MRVL=m
@@ -225,6 +228,8 @@ CONFIG_VIRTIO_NET=y
 CONFIG_HIX5HD2_GMAC=y
 CONFIG_SUN4I_EMAC=y
 CONFIG_MACB=y
+CONFIG_BCMGENET=m
+CONFIG_SYSTEMPORT=m
 CONFIG_NET_CALXEDA_XGMAC=y
 CONFIG_GIANFAR=y
 CONFIG_IGB=y
-- 
2.7.4



From f.fainelli at gmail.com  Fri May 20 12:07:26 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 20 May 2016 12:07:26 -0700
Subject: [PATCH 1/7] ARM: multi_v7_defconfig: Enable BCM63xx
In-Reply-To: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
References: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1463771252-12805-2-git-send-email-f.fainelli@gmail.com>

Enable ARCH_BCM_63XX to build ARM-specific boot and SMP code, as well as
the serial console driver for this platform.

Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
 arch/arm/configs/multi_v7_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 8f857564657f..968a7ec08633 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -36,6 +36,7 @@ CONFIG_ARCH_BCM_21664=y
 CONFIG_ARCH_BCM_281XX=y
 CONFIG_ARCH_BCM_5301X=y
 CONFIG_ARCH_BCM2835=y
+CONFIG_ARCH_BCM_63XX=y
 CONFIG_ARCH_BRCMSTB=y
 CONFIG_ARCH_BERLIN=y
 CONFIG_MACH_BERLIN_BG2=y
@@ -291,6 +292,8 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_SERIAL_ATMEL=y
 CONFIG_SERIAL_ATMEL_CONSOLE=y
 CONFIG_SERIAL_ATMEL_TTYAT=y
+CONFIG_SERIAL_BCM63XX=y
+CONFIG_SERIAL_BCM63XX_CONSOLE=y
 CONFIG_SERIAL_MESON=y
 CONFIG_SERIAL_MESON_CONSOLE=y
 CONFIG_SERIAL_SAMSUNG=y
-- 
2.7.4



From f.fainelli at gmail.com  Fri May 20 12:07:31 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 20 May 2016 12:07:31 -0700
Subject: [PATCH 6/7] ARM: multi_v7_defconfig: Enable Broadcom Kona watchdog
In-Reply-To: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
References: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1463771252-12805-7-git-send-email-f.fainelli@gmail.com>

In order to get rid of bcm_defconfig, enable this driver which is needed
by some Broadcom SoCs based on the Kona architecture to reboot.

Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index b59081bda51b..d180b6694374 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -458,6 +458,7 @@ CONFIG_DW_WATCHDOG=y
 CONFIG_DIGICOLOR_WATCHDOG=y
 CONFIG_BCM2835_WDT=y
 CONFIG_BCM7038_WDT=m
+CONFIG_BCM_KONA_WDT=y
 CONFIG_MFD_AS3711=y
 CONFIG_MFD_AS3722=y
 CONFIG_MFD_ATMEL_FLEXCOM=y
-- 
2.7.4



From f.fainelli at gmail.com  Fri May 20 12:07:28 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 20 May 2016 12:07:28 -0700
Subject: [PATCH 3/7] ARM: multi_v7_defconfig: Enable BRCMSTB AHCI
In-Reply-To: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
References: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1463771252-12805-4-git-send-email-f.fainelli@gmail.com>

Enable the Broadcom STB AHCI driver and its companion PHY driver to get
functional SATA3 support.

Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
 arch/arm/configs/multi_v7_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 31ed7318f406..07ad8f9a033b 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -217,6 +217,7 @@ CONFIG_SCSI_MULTI_LUN=y
 CONFIG_ATA=y
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_BRCMSTB=y
 CONFIG_AHCI_ST=y
 CONFIG_AHCI_SUNXI=y
 CONFIG_AHCI_TEGRA=y
@@ -830,6 +831,7 @@ CONFIG_PHY_SUN4I_USB=y
 CONFIG_PHY_SUN9I_USB=y
 CONFIG_PHY_SAMSUNG_USB2=m
 CONFIG_PHY_TEGRA_XUSB=y
+CONFIG_PHY_BRCMSTB_SATA=y
 CONFIG_NVMEM=y
 CONFIG_NVMEM_SUNXI_SID=y
 CONFIG_BCM2835_MBOX=y
-- 
2.7.4



From f.fainelli at gmail.com  Fri May 20 12:07:29 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 20 May 2016 12:07:29 -0700
Subject: [PATCH 4/7] ARM: multi_v7_defconfig: Enable BCM7038 Watchdog
In-Reply-To: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
References: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1463771252-12805-5-git-send-email-f.fainelli@gmail.com>

The BCM7038 watchdog is used by all Broadcom STB SoCs but is not needed
for system reboot, we just turn it on as a module.

Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 07ad8f9a033b..13e5af6334ac 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -457,6 +457,7 @@ CONFIG_MESON_WATCHDOG=y
 CONFIG_DW_WATCHDOG=y
 CONFIG_DIGICOLOR_WATCHDOG=y
 CONFIG_BCM2835_WDT=y
+CONFIG_BCM7038_WDT=m
 CONFIG_MFD_AS3711=y
 CONFIG_MFD_AS3722=y
 CONFIG_MFD_ATMEL_FLEXCOM=y
-- 
2.7.4



From f.fainelli at gmail.com  Fri May 20 12:07:32 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 20 May 2016 12:07:32 -0700
Subject: [PATCH 7/7] ARM: Remove bcm_defconfig
In-Reply-To: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
References: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1463771252-12805-8-git-send-email-f.fainelli@gmail.com>

We have everything we need in multi_v7_defconfig that exists in
bcm_defconfig, so get rid of that file to reduce the maintenance burden.

Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
 arch/arm/configs/bcm_defconfig | 142 -----------------------------------------
 1 file changed, 142 deletions(-)
 delete mode 100644 arch/arm/configs/bcm_defconfig

diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
deleted file mode 100644
index 7117662bab2e..000000000000
--- a/arch/arm/configs/bcm_defconfig
+++ /dev/null
@@ -1,142 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=19
-CONFIG_CGROUPS=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_DEVICE=y
-CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
-CONFIG_CGROUP_SCHED=y
-CONFIG_BLK_CGROUP=y
-CONFIG_NAMESPACES=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_EMBEDDED=y
-# CONFIG_COMPAT_BRK is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_ARCH_BCM=y
-CONFIG_ARCH_BCM_21664=y
-CONFIG_ARCH_BCM_281XX=y
-CONFIG_ARM_THUMBEE=y
-CONFIG_SMP=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-# CONFIG_COMPACTION is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200n8 mem=128M"
-CONFIG_CPU_IDLE=y
-CONFIG_VFP=y
-CONFIG_NEON=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_PACKET_DIAG=y
-CONFIG_UNIX=y
-CONFIG_UNIX_DIAG=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_SYN_COOKIES=y
-CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6=y
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_BLK_DEV is not set
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_INPUT_FF_MEMLESS=y
-CONFIG_INPUT_JOYDEV=y
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-# CONFIG_SERIO is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-CONFIG_SERIAL_8250_DW=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-# CONFIG_HWMON is not set
-CONFIG_MFD_BCM590XX=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_FIXED_VOLTAGE=y
-CONFIG_REGULATOR_USERSPACE_CONSUMER=y
-CONFIG_REGULATOR_BCM590XX=y
-
-CONFIG_VIDEO_OUTPUT_CONTROL=y
-CONFIG_FB=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_PWM=y
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_BLOCK_MINORS=32
-CONFIG_MMC_TEST=y
-CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_PLTFM=y
-CONFIG_MMC_SDHCI_BCM_KONA=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_PWM=y
-CONFIG_PWM_BCM_KONA=y
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_EXT4_FS_SECURITY=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_FUSE_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_CONFIGFS_FS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_FS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DETECT_HUNG_TASK=y
-CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=110
-CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
-# CONFIG_FTRACE is not set
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRC_CCITT=y
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC_ITU_T=y
-CONFIG_CRC7=y
-CONFIG_XZ_DEC=y
-CONFIG_AVERAGE=y
-CONFIG_PINCTRL_BCM281XX=y
-CONFIG_WATCHDOG=y
-CONFIG_BCM_KONA_WDT=y
-CONFIG_BCM_KONA_WDT_DEBUG=y
-- 
2.7.4



From nleeder at codeaurora.org  Fri May 20 12:13:07 2016
From: nleeder at codeaurora.org (Neil Leeder)
Date: Fri, 20 May 2016 15:13:07 -0400
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
Message-ID: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>

L2 registers are accessed using a select register and data
register pair. To prevent multiple concurrent writes to the
select register by independent drivers, the write to the
select register and the associated access of the data register
are protected with a lock. All drivers accessing the L2
registers use the set and get functions provided by
l2-accessors to ensure correct reads and writes to L2 registers.

Signed-off-by: Neil Leeder <nleeder at codeaurora.org>
---
 drivers/soc/qcom/Kconfig              |  9 +++++
 drivers/soc/qcom/Makefile             |  1 +
 drivers/soc/qcom/l2-accessors.c       | 66 +++++++++++++++++++++++++++++++++++
 include/linux/soc/qcom/l2-accessors.h | 27 ++++++++++++++
 4 files changed, 103 insertions(+)
 create mode 100644 drivers/soc/qcom/l2-accessors.c
 create mode 100644 include/linux/soc/qcom/l2-accessors.h

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 461b387..c8498cd 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -10,6 +10,15 @@ config QCOM_GSBI
           functions for connecting the underlying serial UART, SPI, and I2C
           devices to the output pins.
 
+config QCOM_L2_ACCESSORS
+	bool "Qualcomm Technologies L2-cache accessors"
+	depends on ARCH_QCOM
+	help
+	  Say y here to enable support for the Qualcomm Technologies
+	  L2 accessors.
+	  Provides support for accessing registers in the L2 cache
+	  for Qualcomm Technologies chips.
+
 config QCOM_PM
 	bool "Qualcomm Power Management"
 	depends on ARCH_QCOM && !ARM64
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index fdd664e..6ef29b9 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
+obj-$(CONFIG_QCOM_L2_ACCESSORS) += l2-accessors.o
 obj-$(CONFIG_QCOM_PM)	+=	spm.o
 obj-$(CONFIG_QCOM_SMD) +=	smd.o
 obj-$(CONFIG_QCOM_SMD_RPM)	+= smd-rpm.o
diff --git a/drivers/soc/qcom/l2-accessors.c b/drivers/soc/qcom/l2-accessors.c
new file mode 100644
index 0000000..fbb69bd
--- /dev/null
+++ b/drivers/soc/qcom/l2-accessors.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/soc/qcom/l2-accessors.h>
+#include <asm/cputype.h>
+#include <asm/sysreg.h>
+
+#define	L2CPUSRSELR_EL1	S3_3_c15_c0_6
+#define	L2CPUSRDR_EL1	S3_3_c15_c0_7
+
+static DEFINE_RAW_SPINLOCK(l2_access_lock);
+
+/**
+ * set_l2_indirect_reg: write value to an L2 register
+ * @reg: Address of L2 register.
+ * @value: Value to be written to register.
+ *
+ * Use architecturally required barriers for ordering between system register
+ * accesses
+ */
+void set_l2_indirect_reg(u64 reg, u64 val)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&l2_access_lock, flags);
+	write_sysreg(reg, L2CPUSRSELR_EL1);
+	isb();
+	write_sysreg(val, L2CPUSRDR_EL1);
+	isb();
+	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
+}
+EXPORT_SYMBOL(set_l2_indirect_reg);
+
+/**
+ * get_l2_indirect_reg: read an L2 register value
+ * @reg: Address of L2 register.
+ *
+ * Use architecturally required barriers for ordering between system register
+ * accesses
+ */
+u64 get_l2_indirect_reg(u64 reg)
+{
+	u64 val;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&l2_access_lock, flags);
+	write_sysreg(reg, L2CPUSRSELR_EL1);
+	isb();
+	val = read_sysreg(L2CPUSRDR_EL1);
+	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
+
+	return val;
+}
+EXPORT_SYMBOL(get_l2_indirect_reg);
diff --git a/include/linux/soc/qcom/l2-accessors.h b/include/linux/soc/qcom/l2-accessors.h
new file mode 100644
index 0000000..563c114
--- /dev/null
+++ b/include/linux/soc/qcom/l2-accessors.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __QCOM_L2_ACCESSORS_H
+#define __QCOM_L2_ACCESSORS_H
+
+#ifdef CONFIG_QCOM_L2_ACCESSORS
+void set_l2_indirect_reg(u64 reg_addr, u64 val);
+u64 get_l2_indirect_reg(u64 reg_addr);
+#else
+static inline void set_l2_indirect_reg(u64 reg_addr, u64 val) {}
+static inline u64 get_l2_indirect_reg(u64 reg_addr)
+{
+	return 0;
+}
+#endif
+#endif
-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.



From robh at kernel.org  Fri May 20 12:16:45 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 20 May 2016 14:16:45 -0500
Subject: [PATCH-V2 1/6] dt: bindings: add bcm2835-memory-controller
 documentation
In-Reply-To: <1463586030-2778-2-git-send-email-kernel@martin.sperl.org>
References: <1463586030-2778-1-git-send-email-kernel@martin.sperl.org>
 <1463586030-2778-2-git-send-email-kernel@martin.sperl.org>
Message-ID: <20160520191645.GA14779@rob-hp-laptop>

On Wed, May 18, 2016 at 03:40:25PM +0000, kernel at martin.sperl.org wrote:
> From: Martin Sperl <kernel at martin.sperl.org>
> 
> Add memory controller dt-binding documentation for the
> bcm2835 soc.
> 
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
> 
> Changelog:
>   V2 -> V3: added additional clock
> 	      (for the Controller internal PLL)
> 	    added clock-names
> 	    added additional register ranges for the
> 	      SDRAM Adress and Data PHY
> 	    added reg-names
> ---
>  .../memory-controllers/brcm,bcm2835-sdram.txt      | 30 ++++++++++++++++++++++
>  1 file changed, 30 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/memory-controllers/brcm,bcm2835-sdram.txt

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


From robh at kernel.org  Fri May 20 12:21:01 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 20 May 2016 14:21:01 -0500
Subject: [PATCH] drivers: nvmem: atmel-secumod: New driver for Atmel
 Secumod nvram
In-Reply-To: <1463605564-14397-1-git-send-email-davidm@egauge.net>
References: <20160518164259.GA28954@rob-hp-laptop>
 <1463605564-14397-1-git-send-email-davidm@egauge.net>
Message-ID: <20160520192101.GA15615@rob-hp-laptop>

On Wed, May 18, 2016 at 03:06:04PM -0600, David Mosberger-Tang wrote:
> Signed-off-by: David Mosberger <davidm at egauge.net>
> ---
>  .../devicetree/bindings/nvmem/atmel-secumod.txt    |  47 +++++++
>  drivers/nvmem/Kconfig                              |   7 +
>  drivers/nvmem/Makefile                             |   2 +
>  drivers/nvmem/atmel-secumod.c                      | 143 +++++++++++++++++++++
>  4 files changed, 199 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
>  create mode 100644 drivers/nvmem/atmel-secumod.c
> 
> diff --git a/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
> new file mode 100644
> index 0000000..d65cad5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
> @@ -0,0 +1,47 @@
> += Atmel Secumod device tree bindings =
> +
> +This binding is intended to represent Atmel's Secumod which is found
> +in SAMA5D2 and perhaps others.
> +
> +Required properties:
> +- compatible: should be "atmel,sama5d2-secumod"
> +- reg: Should contain RAM location and length, followed
> +       by register location and length of the Secumod controller.
> +
> += Data cells =
> +Are child nodes of secumod, bindings of which as described in
> +bindings/nvmem/nvmem.txt
> +
> +Example:
> +
> +    secumod at fc040000 {

This unit-address should match the first reg address.

> +            compatible = "atmel,sama5d2-secumod";
> +            reg = <0xf8044000 0x1420>, <0xfc040000 0x4000>;
> +            reg-names = "SECURAM", "SECUMOD";
> +            status = "okay";
> +
> +            #address-cells = <1>;
> +            #size-cells = <1>;
> +            ranges;

Sorry, to be clear, you need values here too.

> +
> +            secram-auto-erasable at 0 {
> +                    reg = <0x0000 0x1000>;

The 0 here is address 0xf8044000, right? So ranges is what is used to 
translate from child address of 0 to the parent address.

> +            };
> +            secram at 1000 {
> +                    reg = <0x1000 0x400>;
> +            };
> +            ram at 1400 {
> +                    reg = <0x1400 0x20>;
> +            };
> +    };
> +
> += Data consumers =
> +Are device nodes which consume nvmem data cells.
> +
> +For example:
> +
> +	ram {
> +		...
> +		nvmem-cells = <&ram>;
> +		nvmem-cell-names = "RAM";
> +	};


From nm at ti.com  Fri May 20 12:43:05 2016
From: nm at ti.com (Nishanth Menon)
Date: Fri, 20 May 2016 14:43:05 -0500
Subject: Regression: next-20160518: Clk? on BeagleBoard-X15
In-Reply-To: <CAL_Jsq+ORQ5PP80_HbH16+SaHFLdrefcVGFzsvgLYiiwtq9PuQ@mail.gmail.com>
References: <573DDFE6.8010209@ti.com> <20160519165719.GW5995@atomide.com>
 <CAL_Jsq+ORQ5PP80_HbH16+SaHFLdrefcVGFzsvgLYiiwtq9PuQ@mail.gmail.com>
Message-ID: <573F68C9.2060404@ti.com>

On 05/19/2016 12:35 PM, Rob Herring wrote:
> On Thu, May 19, 2016 at 11:57 AM, Tony Lindgren <tony at atomide.com> wrote:
>> * Nishanth Menon <nm at ti.com> [160519 08:48]:
>>> I have'nt bisected yet, but the platform seems to have booted on
>>> next-20160517
>>> https://github.com/nmenon/kernel-test-logs/blob/next-20160517/omap2plus_defconfig/am57xx-evm.txt
>>>
>>> https://github.com/nmenon/kernel-test-logs/blob/next-20160518/omap2plus_defconfig/am57xx-evm.txt
>>
>> Seems to be commit ac78f9bdcf38 ("drivers/of: Fix depth when
>> unflattening devicetree").
>>
>> Rob, you need to start playing golf or something between -rc6 and
>> the end of the merge window or something :)
> 
> It seems the fix for one board broke more... It is fixed in my tree now.

Thanks. Looks good today on my test lists:
https://github.com/nmenon/kernel-test-logs/tree/next-20160520



-- 
Regards,
Nishanth Menon


From robh at kernel.org  Fri May 20 13:13:31 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 20 May 2016 15:13:31 -0500
Subject: [PATCH v2 1/2] doc/devicetree: Add Aspeed VIC bindings
In-Reply-To: <CACPK8Xe6TDdV3dC=gizXLxLjUziDFhsupUbXSuYsn6bcrAxahQ@mail.gmail.com>
References: <462797239-14765-1-git-send-email-joel@jms.id.au>
 <1462802317-27086-1-git-send-email-joel@jms.id.au>
 <1462802317-27086-2-git-send-email-joel@jms.id.au>
 <20160511143313.GA7426@rob-hp-laptop>
 <1463014882.20290.203.camel@kernel.crashing.org>
 <CAL_JsqJDGmvDxm1kN1w6NQZs0JLeA-V=X_BWi=VOaMTwftLn-w@mail.gmail.com>
 <CACPK8Xe6TDdV3dC=gizXLxLjUziDFhsupUbXSuYsn6bcrAxahQ@mail.gmail.com>
Message-ID: <CAL_Jsq+EL-syhXoG2fBztaYSD4MXt488JVPh7kyxBT9iA4ipiA@mail.gmail.com>

On Wed, May 18, 2016 at 8:50 AM, Joel Stanley <joel at jms.id.au> wrote:
> On Fri, May 13, 2016 at 2:50 AM, Rob Herring <robh at kernel.org> wrote:
>> On Wed, May 11, 2016 at 8:01 PM, Benjamin Herrenschmidt
>> <benh at kernel.crashing.org> wrote:
>>> On Wed, 2016-05-11 at 09:33 -0500, Rob Herring wrote:
>>>> > +- interrupt-controller : Identifies the node as an interrupt controller
>>>> > +- #interrupt-cells : Specifies the number of cells needed to encode an
>>>> > +  interrupt source. The value shall be 1.
>>>>
>>>> No need for level vs. edge flags?
>>>
>>> That's an open question. Most interrupts are fixed. A handful of GPIOs
>>> can be configured either way. For now I am relying on uboot setting up
>>> the right config for them and I read it back at boot time, but we could
>>> make it part of the binding I suppose.
>>
>> It is almost standard to just use 2 cells here even if reserved for
>> future use. Especially since the IP block seems to have registers to
>> control that.
>
> Yep, makes sense. I've added this to the bindings document.
>
> I was trying to use the second cell in our driver:
>
>   static struct irq_domain_ops avic_dom_ops = {
>           .map = avic_map,
>          .xlate = irq_domain_xlate_twocell,
>   };
>
>  So we have irq_domain_xlate_twocell to parse the device tree and
> grabs the type property from the second cell.
>
> In avic_map we set the irq handler:
>
>          if (vic->edge_sources[sidx] & sbit) {
>                  /* TODO: Check aginst type from dt and warn if not edge */
>                  irq_set_chip_and_handler(irq, &avic_chip, handle_edge_irq);
>          } else {
>                  /* TODO: Check aginst type from dt and warn if not level */
>                  irq_set_chip_and_handler(irq, &avic_chip, handle_level_irq);
>          }
>
> However, we don't have the type here, so we can't use it to check that
> we're setting the correct edge/level callback (or use it to set the
> register in the future if we want to use the device tree to override
> the bootloader settings).
>
> I had a look at some other drivers and they don't seem to use the dt
> property when mapping the irq. What am I missing here?

The type will be set by the irqdomain core when the mapping is created
and this should result in irq_set_type() being called on your irqchip.
The map function doesn't need to deal with type.

Rob


From rafael at kernel.org  Fri May 20 13:29:12 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Fri, 20 May 2016 22:29:12 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
Message-ID: <CAJZ5v0jv5GafkXvqAqYoyit_dAVQXZL+Qb=sh-aWiJjppu_hLw@mail.gmail.com>

On Fri, May 20, 2016 at 8:05 PM, Fabio Estevam <festevam at gmail.com> wrote:
> Rafael,
>
> Running the 'reboot' command works fine on a 4.5 kernel running on a
> mx6ul platform (ARM single core SoC), but it crashes on 4.6.
>
> Running bisect I got 9be4fd2c7723a3057b0b39676 ("cpufreq: governor:
> Replace timers with utilization update callbacks") as the first bad
> commit.
>
> Below is the output crash log.

This is not a crash, this is a stall, meaning that something waits too long.

> Not sure if this issue is related to the problem reported by Guenter here:
> http://lkml.iu.edu/hypermail/linux/kernel/1602.1/06075.html

I don't think so and that one has been fixed in 4.6.

> Any ideas?
>
>
> [ 3857.373588] INFO: rcu_sched detected stalls on CPUs/tasks:
> [ 3857.379155]  (detected by 0, t=2602 jiffies, g=1880, c=1879, q=29)
> [ 3857.385406] All QSes seen, last rcu_sched kthread activity 2602
> (355736-353134), jiffies_till_next_fqs=1, root ->qsmask 0x0
> [ 3857.396562] init            R running      0   864      1 0x00000002
> [ 3857.402999] Backtrace:
> [ 3857.405532] [<c010b6e8>] (dump_backtrace) from [<c010b884>]
> (show_stack+0x18/0x1c)
> [ 3857.413125]  r6:c0d6c6d6 r5:00000001 r4:ddd9c800 r3:00000000
> [ 3857.418941] [<c010b86c>] (show_stack) from [<c014fc3c>]
> (sched_show_task+0x124/0x234)
> [ 3857.426820] [<c014fb18>] (sched_show_task) from [<c0185e24>]
> (rcu_check_callbacks+0x844/0x894)
> [ 3857.435452]  r6:c0c76b40 r5:c0d14b80 r4:debd0b40
> [ 3857.440189] [<c01855e0>] (rcu_check_callbacks) from [<c018884c>]
> (update_process_times+0x38/0x64)
> [ 3857.449081]  r10:c0d21e1c r9:debcdd10 r8:c019a230 r7:dde7bd50
> r6:debce048 r5:00000000
> [ 3857.457067]  r4:ddd9c800
> [ 3857.459665] [<c0188814>] (update_process_times) from [<c019a174>]
> (tick_sched_handle+0x50/0x54)
> [ 3857.468386]  r5:00000382 r4:1c92d15d
> [ 3857.472048] [<c019a124>] (tick_sched_handle) from [<c019a290>]
> (tick_sched_timer+0x60/0xa8)
> [ 3857.480443] [<c019a230>] (tick_sched_timer) from [<c018915c>]
> (__hrtimer_run_queues+0xc0/0x1c8)
> [ 3857.489162]  r7:debcdd80 r6:debcdd00 r5:debcdd8c r4:debce048
> [ 3857.494969] [<c018909c>] (__hrtimer_run_queues) from [<c018998c>]
> (hrtimer_interrupt+0xc8/0x22c)
> [ 3857.503774]  r10:debcddd8 r9:debcddb8 r8:debcddf8 r7:debcdd00
> r6:debcdd40 r5:00000003
> [ 3857.511758]  r4:ffffffff
> [ 3857.514354] [<c01898c4>] (hrtimer_interrupt) from [<c067d994>]
> (mxc_timer_interrupt+0x3c/0x44)
> [ 3857.522985]  r10:c0d6c710 r9:e0805000 r8:de41d000 r7:00000010
> r6:00000000 r5:00000000
> [ 3857.530969]  r4:de402440
> [ 3857.533568] [<c067d958>] (mxc_timer_interrupt) from [<c0177acc>]
> (handle_irq_event_percpu+0x64/0x168)
> [ 3857.542809]  r4:de402500 r3:c067d958
> [ 3857.546482] [<c0177a68>] (handle_irq_event_percpu) from
> [<c0177c10>] (handle_irq_event+0x40/0x64)
> [ 3857.555374]  r10:de406000 r9:e0805000 r8:00000001 r7:00000000
> r6:c0d10330 r5:de41d060
> [ 3857.563358]  r4:de41d000
> [ 3857.565956] [<c0177bd0>] (handle_irq_event) from [<c017b120>]
> (handle_fasteoi_irq+0xd4/0x1ac)
> [ 3857.574502]  r6:c0d10330 r5:de41d060 r4:de41d000 r3:00000000
> [ 3857.580305] [<c017b04c>] (handle_fasteoi_irq) from [<c017726c>]
> (generic_handle_irq+0x20/0x30)
> [ 3857.588937]  r7:00000000 r6:c0c746ec r5:c0d02b10 r4:00000010
> [ 3857.594743] [<c017724c>] (generic_handle_irq) from [<c01773b0>]
> (__handle_domain_irq+0x6c/0xe4)
> [ 3857.603485] [<c0177344>] (__handle_domain_irq) from [<c01015d8>]
> (gic_handle_irq+0x4c/0x9c)
> [ 3857.611857]  r10:000003eb r8:c0d22000 r7:c0d02c58 r6:dde7bd50
> r5:e080400c r4:e0804000
> [ 3857.619858] [<c010158c>] (gic_handle_irq) from [<c010c4b8>]
> (__irq_svc+0x58/0x78)
> [ 3857.627367] Exception stack(0xdde7bd50 to 0xdde7bd98)
> [ 3857.632450] bd40:                                     ddce911c
> 00000001 00000000 00000003
> [ 3857.640664] bd60: ddce911c c0d02a48 ddcea000 ddce90c0 c0108044
> dde7a000 00000000 dde7bdb4
> [ 3857.648875] bd80: dde7bdb8 dde7bda0 c064ad44 c01b247c 20000013 ffffffff
> [ 3857.655509]  r10:00000000 r9:dde7a000 r8:c0108044 r7:dde7bd84
> r6:ffffffff r5:20000013
> [ 3857.663494]  r4:c01b247c r3:ddd9c800
> [ 3857.667167] [<c01b2448>] (irq_work_sync) from [<c064ad44>]
> (cpufreq_governor_dbs+0x170/0x580)

>From here it looks like irq_work_sync() called from gov_cancel_work()
waits for something to happen, but that doesn't happen.  Maybe the
interrupt controller has been shut down?

> [ 3857.675713]  r4:00000004 r3:00000001
> [ 3857.679384] [<c064abd4>] (cpufreq_governor_dbs) from [<c06480e4>]
> (cpufreq_governor+0x64/0x120)
> [ 3857.688103]  r10:00000000 r9:dde7a000 r8:c0108044 r7:c1556f80
> r6:00000002 r5:ddcea000
> [ 3857.696088]  r4:c0d4c5dc
> [ 3857.698684] [<c0648080>] (cpufreq_governor) from [<c06493c4>]
> (cpufreq_suspend+0x70/0x128)
> [ 3857.706967]  r6:c0d4c328 r5:ddcea0dc r4:ddcea000 r3:ddd9c800
> [ 3857.712777] [<c0649354>] (cpufreq_suspend) from [<c04da71c>]
> (syscore_shutdown+0x4c/0x80)

And that's in the syscore_shutdown() code path where cpufreq_suspend()
is invoked.

There's something weird going on here and it sort of looks like that
may be an ordering problem to me.

> [ 3857.720976]  r8:c0108044 r7:00000000 r6:c0d6e020 r5:c0d315a8
> r4:c0d4c2fc r3:00000000
> [ 3857.728895] [<c04da6d0>] (syscore_shutdown) from [<c0147aa8>]
> (kernel_restart+0x1c/0x58)
> [ 3857.737007]  r6:c0d13074 r5:4321fedc r4:00000000 r3:de434900
> [ 3857.742805] [<c0147a8c>] (kernel_restart) from [<c0147cc4>]
> (SyS_reboot+0x18c/0x1e4)
> [ 3857.750569]  r4:01234567 r3:01234567
> [ 3857.754234] [<c0147b38>] (SyS_reboot) from [<c0107ea0>]
> (ret_fast_syscall+0x0/0x1c)
> [ 3857.761910]  r7:00000058 r6:00000000 r5:00000000 r4:00000000
> [ 3857.767707] rcu_sched kthread starved for 2602 jiffies! g1880 c1879
> f0x2 RCU_GP_WAIT_FQS(3) ->state=0x0
> [ 3857.777123] rcu_sched       R running      0     7      2 0x00000000
> [ 3857.783558] Backtrace:
> [ 3857.786076] [<c08f488c>] (__schedule) from [<c08f50d8>] (schedule+0x3c/0xa0)
> [ 3857.793148]  r10:00000001 r9:00000003 r8:c0d02100 r7:0005636f
> r6:debcd4c0 r5:debcd4c0
> [ 3857.801133]  r4:de487e9c
> [ 3857.803728] [<c08f509c>] (schedule) from [<c08f941c>]
> (schedule_timeout+0x138/0x1cc)
> [ 3857.811509] [<c08f92e4>] (schedule_timeout) from [<c0184bf0>]
> (rcu_gp_kthread+0x3b0/0x894)
> [ 3857.819794]  r8:00000000 r7:000002b8 r6:00000001 r5:c0d14e10 r4:c0d14b80
> [ 3857.826667] [<c0184840>] (rcu_gp_kthread) from [<c0144e7c>]
> (kthread+0xd8/0xf4)
> [ 3857.833997]  r7:c0184840
> [ 3857.836593] [<c0144da4>] (kthread) from [<c0107f30>]
> (ret_from_fork+0x14/0x24)
> [ 3857.843836]  r7:00000000 r6:00000000 r5:c0144da4 r4:de435040


From scott.branden at broadcom.com  Fri May 20 13:36:45 2016
From: scott.branden at broadcom.com (Scott Branden)
Date: Fri, 20 May 2016 13:36:45 -0700
Subject: [PATCH 0/7] ARM: multi_v7_defconfig: Add more Broadcom SoCs
In-Reply-To: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
References: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <573F755D.3070203@broadcom.com>

Hi Florian,

On 16-05-20 12:07 PM, Florian Fainelli wrote:
> This patch series enables more fundamental drivers which are useful for
> Broadcom BCM63xx and BCM7xxx SoCs.
>
> The last patch remove bcm_defconfig which is causing a whole lot of confusiong
> at best and is completely out of sync now.
>
> Florian Fainelli (7):
>    ARM: multi_v7_defconfig: Enable BCM63xx
>    ARM: multi_v7_defconfig: Enable BRCMSTB networking
>    ARM: multi_v7_defconfig: Enable BRCMSTB AHCI
>    ARM: multi_v7_defconfig: Enable BCM7038 Watchdog
>    ARM: multi_v7_defconfig: Enable Broadcom STB PWM
>    ARM: multi_v7_defconfig: Enable Broadcom Kona watchdog
>    ARM: Remove bcm_defconfig

Patch series looks good.  Given we can't upstream a defconfig per SoC 
family, bcm_defconfig is quite useless and can be removed.

Acked-by: Scott Branden <scott.branden at broadcom.com>
>
>   arch/arm/configs/bcm_defconfig      | 142 ------------------------------------
>   arch/arm/configs/multi_v7_defconfig |  13 ++++
>   2 files changed, 13 insertions(+), 142 deletions(-)
>   delete mode 100644 arch/arm/configs/bcm_defconfig
>


From scott.branden at broadcom.com  Fri May 20 13:37:52 2016
From: scott.branden at broadcom.com (Scott Branden)
Date: Fri, 20 May 2016 13:37:52 -0700
Subject: [PATCH] soc: Move brcmstb to bcm/brcmstb
In-Reply-To: <1463769495-10072-1-git-send-email-f.fainelli@gmail.com>
References: <1463769495-10072-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <573F75A0.5090206@broadcom.com>

Hi Florian,

Looks good.

On 16-05-20 11:38 AM, Florian Fainelli wrote:
> Unify the different Broadcom SoCs directory and have everybody live
> under drivers/soc/bcm/*.
>
> Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
Acked-by: Scott Branden <scott.branden at broadcom.com>
> ---
>   drivers/soc/Kconfig                     |  1 -
>   drivers/soc/Makefile                    |  1 -
>   drivers/soc/bcm/Kconfig                 | 15 +++++++++++++++
>   drivers/soc/bcm/Makefile                |  1 +
>   drivers/soc/{ => bcm}/brcmstb/Makefile  |  0
>   drivers/soc/{ => bcm}/brcmstb/biuctrl.c |  0
>   drivers/soc/{ => bcm}/brcmstb/common.c  |  0
>   drivers/soc/brcmstb/Kconfig             | 10 ----------
>   8 files changed, 16 insertions(+), 12 deletions(-)
>   rename drivers/soc/{ => bcm}/brcmstb/Makefile (100%)
>   rename drivers/soc/{ => bcm}/brcmstb/biuctrl.c (100%)
>   rename drivers/soc/{ => bcm}/brcmstb/common.c (100%)
>   delete mode 100644 drivers/soc/brcmstb/Kconfig
>
> diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> index cb58ef0d9b2c..91d5c05d395f 100644
> --- a/drivers/soc/Kconfig
> +++ b/drivers/soc/Kconfig
> @@ -1,7 +1,6 @@
>   menu "SOC (System On Chip) specific Drivers"
>
>   source "drivers/soc/bcm/Kconfig"
> -source "drivers/soc/brcmstb/Kconfig"
>   source "drivers/soc/fsl/qe/Kconfig"
>   source "drivers/soc/mediatek/Kconfig"
>   source "drivers/soc/qcom/Kconfig"
> diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
> index 380230f03874..b75e3bd0a01e 100644
> --- a/drivers/soc/Makefile
> +++ b/drivers/soc/Makefile
> @@ -3,7 +3,6 @@
>   #
>
>   obj-y				+= bcm/
> -obj-$(CONFIG_SOC_BRCMSTB)	+= brcmstb/
>   obj-$(CONFIG_ARCH_DOVE)		+= dove/
>   obj-$(CONFIG_MACH_DOVE)		+= dove/
>   obj-y				+= fsl/
> diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig
> index 3066edea184d..97156aeed286 100644
> --- a/drivers/soc/bcm/Kconfig
> +++ b/drivers/soc/bcm/Kconfig
> @@ -1,3 +1,5 @@
> +menu "Broadcom SoC drivers"
> +
>   config RASPBERRYPI_POWER
>   	bool "Raspberry Pi power domain driver"
>   	depends on ARCH_BCM2835 || COMPILE_TEST
> @@ -7,3 +9,16 @@ config RASPBERRYPI_POWER
>   	help
>   	  This enables support for the RPi power domains which can be enabled
>   	  or disabled via the RPi firmware.
> +
> +config SOC_BRCMSTB
> +	bool "Broadcom STB SoC drivers"
> +	depends on ARM
> +	select SOC_BUS
> +	help
> +	  Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
> +	  This option alone enables only some support code, while the drivers
> +	  can be enabled individually within this menu.
> +
> +	  If unsure, say N.
> +
> +endmenu
> diff --git a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile
> index 63aa3eb23087..dc4fced72d21 100644
> --- a/drivers/soc/bcm/Makefile
> +++ b/drivers/soc/bcm/Makefile
> @@ -1 +1,2 @@
>   obj-$(CONFIG_RASPBERRYPI_POWER)	+= raspberrypi-power.o
> +obj-$(CONFIG_SOC_BRCMSTB)	+= brcmstb/
> diff --git a/drivers/soc/brcmstb/Makefile b/drivers/soc/bcm/brcmstb/Makefile
> similarity index 100%
> rename from drivers/soc/brcmstb/Makefile
> rename to drivers/soc/bcm/brcmstb/Makefile
> diff --git a/drivers/soc/brcmstb/biuctrl.c b/drivers/soc/bcm/brcmstb/biuctrl.c
> similarity index 100%
> rename from drivers/soc/brcmstb/biuctrl.c
> rename to drivers/soc/bcm/brcmstb/biuctrl.c
> diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c
> similarity index 100%
> rename from drivers/soc/brcmstb/common.c
> rename to drivers/soc/bcm/brcmstb/common.c
> diff --git a/drivers/soc/brcmstb/Kconfig b/drivers/soc/brcmstb/Kconfig
> deleted file mode 100644
> index 7fec3b4c80a1..000000000000
> --- a/drivers/soc/brcmstb/Kconfig
> +++ /dev/null
> @@ -1,10 +0,0 @@
> -menuconfig SOC_BRCMSTB
> -	bool "Broadcom STB SoC drivers"
> -	depends on ARM
> -	select SOC_BUS
> -	help
> -	  Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
> -	  This option alone enables only some support code, while the drivers
> -	  can be enabled individually within this menu.
> -
> -	  If unsure, say N.
>


From rafael at kernel.org  Fri May 20 13:42:55 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Fri, 20 May 2016 22:42:55 +0200
Subject: [PATCH v8 2/4] ACPI: parse SPCR and enable matching console
In-Reply-To: <1463749405-11640-3-git-send-email-aleksey.makarov@linaro.org>
References: <1463749405-11640-1-git-send-email-aleksey.makarov@linaro.org>
 <1463749405-11640-3-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <CAJZ5v0hdoLTfjrD8+WxSoxM48dqbZK2KwY_h+63kHKHKgO=JFA@mail.gmail.com>

On Fri, May 20, 2016 at 3:03 PM, Aleksey Makarov
<aleksey.makarov at linaro.org> wrote:
> 'ARM Server Base Boot Requiremets' [1] mentions SPCR (Serial Port
> Console Redirection Table) [2] as a mandatory ACPI table that
> specifies the configuration of serial console.
>
> Defer initialization of DT earlycon until ACPI/DT decision is made.
>
> Parse the ACPI SPCR table, setup earlycon if required,
> enable specified console.
>
> Thanks to Peter Hurley for explaining how this should work.
>
> [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0044a/index.html
> [2] https://msdn.microsoft.com/en-us/library/windows/hardware/dn639132(v=vs.85).aspx
>
> Signed-off-by: Aleksey Makarov <aleksey.makarov at linaro.org>
> Reviewed-by: Peter Hurley <peter at hurleysoftware.com>
> Tested-by: Kefeng Wang <wangkefeng.wang at huawei.com>

Acked-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>

for the ACPI part.

> ---
>  drivers/acpi/Kconfig          |   3 ++
>  drivers/acpi/Makefile         |   1 +
>  drivers/acpi/spcr.c           | 111 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/tty/serial/earlycon.c |  19 +++++++-
>  include/linux/acpi.h          |   6 +++
>  include/linux/serial_core.h   |   6 +++
>  6 files changed, 144 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/acpi/spcr.c
>
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index c204344..c8c02f1 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -77,6 +77,9 @@ config ACPI_DEBUGGER_USER
>
>  endif
>
> +config ACPI_SPCR_TABLE
> +       bool
> +
>  config ACPI_SLEEP
>         bool
>         depends on SUSPEND || HIBERNATION
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 8b08e20..d0dc940 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -82,6 +82,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
>  obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
>  obj-$(CONFIG_ACPI_BGRT)                += bgrt.o
>  obj-$(CONFIG_ACPI_CPPC_LIB)    += cppc_acpi.o
> +obj-$(CONFIG_ACPI_SPCR_TABLE)  += spcr.o
>  obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o
>
>  # processor has its own "processor." module_param namespace
> diff --git a/drivers/acpi/spcr.c b/drivers/acpi/spcr.c
> new file mode 100644
> index 0000000..f4cfc5c
> --- /dev/null
> +++ b/drivers/acpi/spcr.c
> @@ -0,0 +1,111 @@
> +/*
> + * Copyright (c) 2012, Intel Corporation
> + * Copyright (c) 2015, Red Hat, Inc.
> + * Copyright (c) 2015, 2016 Linaro Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#define pr_fmt(fmt) "ACPI: SPCR: " fmt
> +
> +#include <linux/acpi.h>
> +#include <linux/console.h>
> +#include <linux/kernel.h>
> +#include <linux/serial_core.h>
> +
> +/**
> + * parse_spcr() - parse ACPI SPCR table and add preferred console
> + *
> + * @earlycon: set up earlycon for the console specified by the table
> + *
> + * For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be
> + * defined to parse ACPI SPCR table.  As a result of the parsing preferred
> + * console is registered and if @earlycon is true, earlycon is set up.
> + *
> + * When CONFIG_ACPI_SPCR_TABLE is defined, this function should be called
> + * from arch inintialization code as soon as the DT/ACPI decision is made.
> + *
> + */
> +int __init parse_spcr(bool earlycon)
> +{
> +       static char opts[64];
> +       struct acpi_table_spcr *table;
> +       acpi_size table_size;
> +       acpi_status status;
> +       char *uart;
> +       char *iotype;
> +       int baud_rate;
> +       int err;
> +
> +       if (acpi_disabled)
> +               return -ENODEV;
> +
> +       status = acpi_get_table_with_size(ACPI_SIG_SPCR, 0,
> +                                         (struct acpi_table_header **)&table,
> +                                         &table_size);
> +
> +       if (ACPI_FAILURE(status))
> +               return -ENOENT;
> +
> +       if (table->header.revision < 2) {
> +               err = -ENOENT;
> +               pr_err("wrong table version\n");
> +               goto done;
> +       }
> +
> +       iotype = table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY ?
> +                       "mmio" : "io";
> +
> +       switch (table->interface_type) {
> +       case ACPI_DBG2_ARM_SBSA_32BIT:
> +               iotype = "mmio32";
> +               /* fall through */
> +       case ACPI_DBG2_ARM_PL011:
> +       case ACPI_DBG2_ARM_SBSA_GENERIC:
> +       case ACPI_DBG2_BCM2835:
> +               uart = "pl011";
> +               break;
> +       case ACPI_DBG2_16550_COMPATIBLE:
> +       case ACPI_DBG2_16550_SUBSET:
> +               uart = "uart";
> +               break;
> +       default:
> +               err = -ENOENT;
> +               goto done;
> +       }
> +
> +       switch (table->baud_rate) {
> +       case 3:
> +               baud_rate = 9600;
> +               break;
> +       case 4:
> +               baud_rate = 19200;
> +               break;
> +       case 6:
> +               baud_rate = 57600;
> +               break;
> +       case 7:
> +               baud_rate = 115200;
> +               break;
> +       default:
> +               err = -ENOENT;
> +               goto done;
> +       }
> +
> +       snprintf(opts, sizeof(opts), "%s,%s,0x%llx,%d", uart, iotype,
> +                table->serial_port.address, baud_rate);
> +
> +       pr_info("console: %s", opts);
> +
> +       if (earlycon)
> +               setup_earlycon(opts);
> +
> +       err = add_preferred_console(uart, 0, opts + strlen(uart) + 1);
> +
> +done:
> +       early_acpi_os_unmap_memory((void __iomem *)table, table_size);
> +       return err;
> +}
> diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
> index 7aae655..ea00b9f 100644
> --- a/drivers/tty/serial/earlycon.c
> +++ b/drivers/tty/serial/earlycon.c
> @@ -21,6 +21,7 @@
>  #include <linux/sizes.h>
>  #include <linux/of.h>
>  #include <linux/of_fdt.h>
> +#include <linux/acpi.h>
>
>  #ifdef CONFIG_FIX_EARLYCON_MEM
>  #include <asm/fixmap.h>
> @@ -199,6 +200,14 @@ int __init setup_earlycon(char *buf)
>         return -ENOENT;
>  }
>
> +/*
> + * When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in
> + * command line does not start DT earlycon immediately, instead it defers
> + * starting it until DT/ACPI decision is made.  At that time if ACPI is enabled
> + * call parse_spcr(), else call early_init_dt_scan_chosen_stdout()
> + */
> +bool earlycon_init_is_deferred __initdata;
> +
>  /* early_param wrapper for setup_earlycon() */
>  static int __init param_setup_earlycon(char *buf)
>  {
> @@ -208,8 +217,14 @@ static int __init param_setup_earlycon(char *buf)
>          * Just 'earlycon' is a valid param for devicetree earlycons;
>          * don't generate a warning from parse_early_params() in that case
>          */
> -       if (!buf || !buf[0])
> -               return early_init_dt_scan_chosen_stdout();
> +       if (!buf || !buf[0]) {
> +               if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) {
> +                       earlycon_init_is_deferred = true;
> +                       return 0;
> +               } else {
> +                       return early_init_dt_scan_chosen_stdout();
> +               }
> +       }
>
>         err = setup_earlycon(buf);
>         if (err == -ENOENT || err == -EALREADY)
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 288fac5..1de43be 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -997,4 +997,10 @@ static inline struct fwnode_handle *acpi_get_next_subnode(struct device *dev,
>  #define acpi_probe_device_table(t)     ({ int __r = 0; __r;})
>  #endif
>
> +#ifdef CONFIG_ACPI_SPCR_TABLE
> +int parse_spcr(bool earlycon);
> +#else
> +static inline int parse_spcr(bool earlycon) { return 0; }
> +#endif
> +
>  #endif /*_LINUX_ACPI_H*/
> diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> index a3d7c0d..60b6143 100644
> --- a/include/linux/serial_core.h
> +++ b/include/linux/serial_core.h
> @@ -366,6 +366,12 @@ extern int of_setup_earlycon(const struct earlycon_id *match,
>                              unsigned long node,
>                              const char *options);
>
> +#ifdef CONFIG_SERIAL_EARLYCON
> +extern bool earlycon_init_is_deferred __initdata;
> +#else
> +static const bool earlycon_init_is_deferred;
> +#endif
> +
>  struct uart_port *uart_get_console(struct uart_port *ports, int nr,
>                                    struct console *c);
>  int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
> --


From b-liu at ti.com  Fri May 20 13:55:29 2016
From: b-liu at ti.com (Bin Liu)
Date: Fri, 20 May 2016 15:55:29 -0500
Subject: [PATCH v2 1/2] musb: sunxi: Add set_mode platform function
In-Reply-To: <20160516201059.GA9927@uda0271908>
References: <1463229905-26387-2-git-send-email-hdegoede@redhat.com>
 <1463229905-26387-1-git-send-email-hdegoede@redhat.com>
 <20160516201059.GA9927@uda0271908>
Message-ID: <20160520205529.GB7475@uda0271908>

Hi,

On Mon, May 16, 2016 at 03:11:34PM -0500, Bin Liu wrote:
> On Sat, May 14, 2016 at 02:45:04PM +0200, Hans de Goede wrote:
> > Move the mode handling to the platform_set_mode callback.
> > 
> > Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> 
> Signed-off-by: Bin Liu <b-liu at ti.com>

I revised the subject prefix to "usb: musb: sunxi: ..." for both
patches.

Regards,
-Bin.

> 
> Regards,
> -Bin.


From rjw at rjwysocki.net  Fri May 20 14:20:59 2016
From: rjw at rjwysocki.net (Rafael J. Wysocki)
Date: Fri, 20 May 2016 23:20:59 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAOMZO5D_-3St-jqzMLzFHRn3dXXoSZGn4APSK4F63qCP3X=FfA@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAOMZO5D_-3St-jqzMLzFHRn3dXXoSZGn4APSK4F63qCP3X=FfA@mail.gmail.com>
Message-ID: <4080948.V5DMHR9bsk@vostro.rjw.lan>

On Friday, May 20, 2016 03:32:43 PM Fabio Estevam wrote:
> On Fri, May 20, 2016 at 3:05 PM, Fabio Estevam <festevam at gmail.com> wrote:
> > Rafael,
> >
> > Running the 'reboot' command works fine on a 4.5 kernel running on a
> > mx6ul platform (ARM single core SoC), but it crashes on 4.6.
> >
> > Running bisect I got 9be4fd2c7723a3057b0b39676 ("cpufreq: governor:
> > Replace timers with utilization update callbacks") as the first bad
> > commit.
> >
> > Below is the output crash log.
> >
> > Not sure if this issue is related to the problem reported by Guenter here:
> > http://lkml.iu.edu/hypermail/linux/kernel/1602.1/06075.html
> >
> > Any ideas?
> 
> If I rebuilt a kernel with SMP=n then the reboot command works as expected.

Does it work if you boot with maxcpus=1 or nosmp in the kernel command line?

Also, please try if the appended patch makes any difference.

---
 drivers/base/core.c       |    3 +++
 drivers/cpufreq/cpufreq.c |   11 -----------
 2 files changed, 3 insertions(+), 11 deletions(-)

Index: linux-pm/drivers/cpufreq/cpufreq.c
===================================================================
--- linux-pm.orig/drivers/cpufreq/cpufreq.c
+++ linux-pm/drivers/cpufreq/cpufreq.c
@@ -27,7 +27,6 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
-#include <linux/syscore_ops.h>
 #include <linux/tick.h>
 #include <trace/events/power.h>
 
@@ -2556,14 +2555,6 @@ int cpufreq_unregister_driver(struct cpu
 }
 EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
 
-/*
- * Stop cpufreq at shutdown to make sure it isn't holding any locks
- * or mutexes when secondary CPUs are halted.
- */
-static struct syscore_ops cpufreq_syscore_ops = {
-	.shutdown = cpufreq_suspend,
-};
-
 struct kobject *cpufreq_global_kobject;
 EXPORT_SYMBOL(cpufreq_global_kobject);
 
@@ -2575,8 +2566,6 @@ static int __init cpufreq_core_init(void
 	cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
 	BUG_ON(!cpufreq_global_kobject);
 
-	register_syscore_ops(&cpufreq_syscore_ops);
-
 	return 0;
 }
 core_initcall(cpufreq_core_init);
Index: linux-pm/drivers/base/core.c
===================================================================
--- linux-pm.orig/drivers/base/core.c
+++ linux-pm/drivers/base/core.c
@@ -10,6 +10,7 @@
  *
  */
 
+#include <linux/cpufreq.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/fwnode.h>
@@ -2042,6 +2043,8 @@ void device_shutdown(void)
 {
 	struct device *dev, *parent;
 
+	cpufreq_suspend();
+
 	spin_lock(&devices_kset->list_lock);
 	/*
 	 * Walk the devices list backward, shutting down each in turn.



From sboyd at codeaurora.org  Fri May 20 14:19:24 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Fri, 20 May 2016 14:19:24 -0700
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
In-Reply-To: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
References: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
Message-ID: <573F7F5C.1050100@codeaurora.org>

On 05/20/2016 12:13 PM, Neil Leeder wrote:
> diff --git a/drivers/soc/qcom/l2-accessors.c b/drivers/soc/qcom/l2-accessors.c
> new file mode 100644
> index 0000000..fbb69bd
> --- /dev/null
> +++ b/drivers/soc/qcom/l2-accessors.c
> @@ -0,0 +1,66 @@
> +/*
> + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/spinlock.h>
> +#include <linux/module.h>

export.h instead?

> +#include <linux/soc/qcom/l2-accessors.h>
> +#include <asm/cputype.h>
> +#include <asm/sysreg.h>

Is there a patch to add sysreg.h to arch/arm? It would be nice to use
one l2 accessor API on arm64 and arm.

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



From heiko at sntech.de  Fri May 20 14:19:52 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Fri, 20 May 2016 23:19:52 +0200
Subject: [PATCH] arm64: dts: rockchip: fixes the gic400 2nd region size
 for rk3368
In-Reply-To: <1463582510-29156-1-git-send-email-wxt@rock-chips.com>
References: <1463582510-29156-1-git-send-email-wxt@rock-chips.com>
Message-ID: <2773450.t8WTDyMWXy@phil>

Hi Caesar,

Am Mittwoch, 18. Mai 2016, 22:41:50 schrieb Caesar Wang:
> The 2nd additional region is the GIC virtual cpu interface register
> base and size.
> 
> As the gic400 of rk3368 says, the cpu interface register map as below
> 
> 
> 
> -0x0000 GICC_CTRL
> .
> .
> .
> -0x00fc GICC_IIDR
> -0x1000 GICC_IDR
> 
> Obviously, the region size should be greater than 0x1000.
> So we should make sure to include the GICC_IDR since the kernel will
> access it in some cases.
> 
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-rockchip at lists.infradead.org

applied to a fixes branch for 4.7 with Shawn's review-tag.


Thanks for catching this
Heiko


From festevam at gmail.com  Fri May 20 14:37:38 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Fri, 20 May 2016 18:37:38 -0300
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <4080948.V5DMHR9bsk@vostro.rjw.lan>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAOMZO5D_-3St-jqzMLzFHRn3dXXoSZGn4APSK4F63qCP3X=FfA@mail.gmail.com>
 <4080948.V5DMHR9bsk@vostro.rjw.lan>
Message-ID: <CAOMZO5Di3s36=B_52g=S+sWjpdNQ2GozDjeT=3n0B5jNM9z8tA@mail.gmail.com>

Hi Rafael,

On Fri, May 20, 2016 at 6:20 PM, Rafael J. Wysocki <rjw at rjwysocki.net> wrote:

>> If I rebuilt a kernel with SMP=n then the reboot command works as expected.
>
> Does it work if you boot with maxcpus=1 or nosmp in the kernel command line?

No, it does not help.

> Also, please try if the appended patch makes any difference.

I tried it, and the console shows "Requesting system reboot" and stays
there forever. No more messages after that and the system does not
reboot.


From robh at kernel.org  Fri May 20 14:44:07 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 20 May 2016 16:44:07 -0500
Subject: [PATCH 1/2] gpio: pca953x: Add support for TI PCA9536
In-Reply-To: <1463640450-16762-2-git-send-email-vigneshr@ti.com>
References: <1463640450-16762-1-git-send-email-vigneshr@ti.com>
 <1463640450-16762-2-git-send-email-vigneshr@ti.com>
Message-ID: <20160520214407.GA18432@rob-hp-laptop>

On Thu, May 19, 2016 at 12:17:29PM +0530, Vignesh R wrote:
> TI PCA9536 is 4-Bit I2C GPIO expander without interrupt support[1].
> Add support for the same.
> 
> [1] TRM: http://www.ti.com/lit/ds/symlink/pca9536.pdf
> 
> Signed-off-by: Vignesh R <vigneshr at ti.com>
> ---
>  Documentation/devicetree/bindings/gpio/gpio-pca953x.txt | 1 +
>  drivers/gpio/gpio-pca953x.c                             | 1 +
>  2 files changed, 2 insertions(+)

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


From rafael at kernel.org  Fri May 20 14:48:36 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Fri, 20 May 2016 23:48:36 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAOMZO5Di3s36=B_52g=S+sWjpdNQ2GozDjeT=3n0B5jNM9z8tA@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAOMZO5D_-3St-jqzMLzFHRn3dXXoSZGn4APSK4F63qCP3X=FfA@mail.gmail.com>
 <4080948.V5DMHR9bsk@vostro.rjw.lan>
 <CAOMZO5Di3s36=B_52g=S+sWjpdNQ2GozDjeT=3n0B5jNM9z8tA@mail.gmail.com>
Message-ID: <CAJZ5v0h6qU8_BBmugSw8YGiWsmgYfZXtqOmGWkcNOM_O1mfD4g@mail.gmail.com>

On Fri, May 20, 2016 at 11:37 PM, Fabio Estevam <festevam at gmail.com> wrote:
> Hi Rafael,
>
> On Fri, May 20, 2016 at 6:20 PM, Rafael J. Wysocki <rjw at rjwysocki.net> wrote:
>
>>> If I rebuilt a kernel with SMP=n then the reboot command works as expected.
>>
>> Does it work if you boot with maxcpus=1 or nosmp in the kernel command line?
>
> No, it does not help.
>
>> Also, please try if the appended patch makes any difference.
>
> I tried it, and the console shows "Requesting system reboot" and stays
> there forever. No more messages after that and the system does not
> reboot.

So what about if you comment out the cpufreq_suspend() line in
device_shutdown() (after applying the patch)?


From robh at kernel.org  Fri May 20 14:49:06 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 20 May 2016 16:49:06 -0500
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <1463648641-6931-2-git-send-email-vigneshr@ti.com>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
 <1463648641-6931-2-git-send-email-vigneshr@ti.com>
Message-ID: <20160520214906.GA20973@rob-hp-laptop>

On Thu, May 19, 2016 at 02:34:00PM +0530, Vignesh R wrote:
> There are rotary-encoders where GPIO lines reflect the actual position
> of the rotary encoder dial. For example, if dial points to 9, then four
> GPIO lines connected to the rotary encoder will read HLLH(1001b = 9).
> Add support for such rotary-encoder.
> The driver relies on rotary-encoder,absolute-encoder DT property to
> detect such encoders.
> Since, GPIO IRQs are not necessary to work with
> such encoders, optional polling mode support is added using
> input_poll_dev skeleton. This is can be used by enabling
> CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT.
> 
> Signed-off-by: Vignesh R <vigneshr at ti.com>
> ---
>  .../devicetree/bindings/input/rotary-encoder.txt   |   4 +
>  Documentation/input/rotary-encoder.txt             |   9 ++
>  drivers/input/misc/Kconfig                         |  11 ++
>  drivers/input/misc/rotary_encoder.c                | 165 ++++++++++++++++-----
>  4 files changed, 155 insertions(+), 34 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> index 6c9f0c8a846c..9c928dbd1500 100644
> --- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
> +++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> @@ -12,6 +12,10 @@ Optional properties:
>  - rotary-encoder,relative-axis: register a relative axis rather than an
>    absolute one. Relative axis will only generate +1/-1 events on the input
>    device, hence no steps need to be passed.
> +- rotary-encoder,absolute-encoder: support encoders where GPIO lines
> +  reflect the actual position of the rotary encoder dial. For example,
> +  if dial points to 9, then four GPIO lines read HLLH(1001b = 9).
> +  In this case, rotary-encoder,steps-per-period needed not be defined.

I think this should be done as a new compatible string rather than a 
property. It seems like fundamentally different h/w.

Rob


From festevam at gmail.com  Fri May 20 14:55:24 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Fri, 20 May 2016 18:55:24 -0300
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAJZ5v0h6qU8_BBmugSw8YGiWsmgYfZXtqOmGWkcNOM_O1mfD4g@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAOMZO5D_-3St-jqzMLzFHRn3dXXoSZGn4APSK4F63qCP3X=FfA@mail.gmail.com>
 <4080948.V5DMHR9bsk@vostro.rjw.lan>
 <CAOMZO5Di3s36=B_52g=S+sWjpdNQ2GozDjeT=3n0B5jNM9z8tA@mail.gmail.com>
 <CAJZ5v0h6qU8_BBmugSw8YGiWsmgYfZXtqOmGWkcNOM_O1mfD4g@mail.gmail.com>
Message-ID: <CAOMZO5ABUpb4yx19j09hvOL7_QpO+_33Q+LCYQ-44LoqFrAxEg@mail.gmail.com>

On Fri, May 20, 2016 at 6:48 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:

> So what about if you comment out the cpufreq_suspend() line in
> device_shutdown() (after applying the patch)?

Then it reboots fine :-) Thanks


From rafael at kernel.org  Fri May 20 14:59:06 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Fri, 20 May 2016 23:59:06 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAOMZO5ABUpb4yx19j09hvOL7_QpO+_33Q+LCYQ-44LoqFrAxEg@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAOMZO5D_-3St-jqzMLzFHRn3dXXoSZGn4APSK4F63qCP3X=FfA@mail.gmail.com>
 <4080948.V5DMHR9bsk@vostro.rjw.lan>
 <CAOMZO5Di3s36=B_52g=S+sWjpdNQ2GozDjeT=3n0B5jNM9z8tA@mail.gmail.com>
 <CAJZ5v0h6qU8_BBmugSw8YGiWsmgYfZXtqOmGWkcNOM_O1mfD4g@mail.gmail.com>
 <CAOMZO5ABUpb4yx19j09hvOL7_QpO+_33Q+LCYQ-44LoqFrAxEg@mail.gmail.com>
Message-ID: <CAJZ5v0icSd72P1MpMhOsZtC7mgLLGy_5-FM4t0d13zLe2cG8-Q@mail.gmail.com>

On Fri, May 20, 2016 at 11:55 PM, Fabio Estevam <festevam at gmail.com> wrote:
> On Fri, May 20, 2016 at 6:48 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:
>
>> So what about if you comment out the cpufreq_suspend() line in
>> device_shutdown() (after applying the patch)?
>
> Then it reboots fine :-) Thanks

But that probably means that irq_work_sync() doesn't work on your system.

Can you please try to boot and change the cpufreq governor to
performance and back and see if that works?

Is this an SMP board, actually?


From rjw at rjwysocki.net  Fri May 20 15:27:54 2016
From: rjw at rjwysocki.net (Rafael J. Wysocki)
Date: Sat, 21 May 2016 00:27:54 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAJZ5v0icSd72P1MpMhOsZtC7mgLLGy_5-FM4t0d13zLe2cG8-Q@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAOMZO5ABUpb4yx19j09hvOL7_QpO+_33Q+LCYQ-44LoqFrAxEg@mail.gmail.com>
 <CAJZ5v0icSd72P1MpMhOsZtC7mgLLGy_5-FM4t0d13zLe2cG8-Q@mail.gmail.com>
Message-ID: <1979704.U8oId5AOcb@vostro.rjw.lan>

On Friday, May 20, 2016 11:59:06 PM Rafael J. Wysocki wrote:
> On Fri, May 20, 2016 at 11:55 PM, Fabio Estevam <festevam at gmail.com> wrote:
> > On Fri, May 20, 2016 at 6:48 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:
> >
> >> So what about if you comment out the cpufreq_suspend() line in
> >> device_shutdown() (after applying the patch)?
> >
> > Then it reboots fine :-) Thanks
> 
> But that probably means that irq_work_sync() doesn't work on your system.
> 
> Can you please try to boot and change the cpufreq governor to
> performance and back and see if that works?
> 
> Is this an SMP board, actually?

No, it isn't (checked the report again).

Silly question maybe: Is CONFIG_IRQ_WORK set in your .config?



From rjw at rjwysocki.net  Fri May 20 15:31:24 2016
From: rjw at rjwysocki.net (Rafael J. Wysocki)
Date: Sat, 21 May 2016 00:31:24 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <1979704.U8oId5AOcb@vostro.rjw.lan>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0icSd72P1MpMhOsZtC7mgLLGy_5-FM4t0d13zLe2cG8-Q@mail.gmail.com>
 <1979704.U8oId5AOcb@vostro.rjw.lan>
Message-ID: <2720594.bAVGPyzWeg@vostro.rjw.lan>

On Saturday, May 21, 2016 12:27:54 AM Rafael J. Wysocki wrote:
> On Friday, May 20, 2016 11:59:06 PM Rafael J. Wysocki wrote:
> > On Fri, May 20, 2016 at 11:55 PM, Fabio Estevam <festevam at gmail.com> wrote:
> > > On Fri, May 20, 2016 at 6:48 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:
> > >
> > >> So what about if you comment out the cpufreq_suspend() line in
> > >> device_shutdown() (after applying the patch)?
> > >
> > > Then it reboots fine :-) Thanks
> > 
> > But that probably means that irq_work_sync() doesn't work on your system.
> > 
> > Can you please try to boot and change the cpufreq governor to
> > performance and back and see if that works?
> > 
> > Is this an SMP board, actually?
> 
> No, it isn't (checked the report again).
> 
> Silly question maybe: Is CONFIG_IRQ_WORK set in your .config?

Well, the kernel wouldn't have built for you without it, so it must be set.



From festevam at gmail.com  Fri May 20 17:12:09 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Fri, 20 May 2016 21:12:09 -0300
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAJZ5v0icSd72P1MpMhOsZtC7mgLLGy_5-FM4t0d13zLe2cG8-Q@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAOMZO5D_-3St-jqzMLzFHRn3dXXoSZGn4APSK4F63qCP3X=FfA@mail.gmail.com>
 <4080948.V5DMHR9bsk@vostro.rjw.lan>
 <CAOMZO5Di3s36=B_52g=S+sWjpdNQ2GozDjeT=3n0B5jNM9z8tA@mail.gmail.com>
 <CAJZ5v0h6qU8_BBmugSw8YGiWsmgYfZXtqOmGWkcNOM_O1mfD4g@mail.gmail.com>
 <CAOMZO5ABUpb4yx19j09hvOL7_QpO+_33Q+LCYQ-44LoqFrAxEg@mail.gmail.com>
 <CAJZ5v0icSd72P1MpMhOsZtC7mgLLGy_5-FM4t0d13zLe2cG8-Q@mail.gmail.com>
Message-ID: <CAOMZO5C=v8AzSX7CNkJOkwtRM5dekZ8rpdAfZyggecbdcQK5gg@mail.gmail.com>

On Fri, May 20, 2016 at 6:59 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:

> Can you please try to boot and change the cpufreq governor to
> performance and back and see if that works?

I cannot change to governor with 9be4fd2c7723a305.

After running 'cat performance >
/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor'
the system hangs silently.

Reverting 9be4fd2c7723a305 allows me to change to performace.

> Is this an SMP board, actually?

Yes, this is a single core CortexA7.


From rafael at kernel.org  Fri May 20 17:30:27 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Sat, 21 May 2016 02:30:27 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAOMZO5C=v8AzSX7CNkJOkwtRM5dekZ8rpdAfZyggecbdcQK5gg@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAOMZO5D_-3St-jqzMLzFHRn3dXXoSZGn4APSK4F63qCP3X=FfA@mail.gmail.com>
 <4080948.V5DMHR9bsk@vostro.rjw.lan>
 <CAOMZO5Di3s36=B_52g=S+sWjpdNQ2GozDjeT=3n0B5jNM9z8tA@mail.gmail.com>
 <CAJZ5v0h6qU8_BBmugSw8YGiWsmgYfZXtqOmGWkcNOM_O1mfD4g@mail.gmail.com>
 <CAOMZO5ABUpb4yx19j09hvOL7_QpO+_33Q+LCYQ-44LoqFrAxEg@mail.gmail.com>
 <CAJZ5v0icSd72P1MpMhOsZtC7mgLLGy_5-FM4t0d13zLe2cG8-Q@mail.gmail.com>
 <CAOMZO5C=v8AzSX7CNkJOkwtRM5dekZ8rpdAfZyggecbdcQK5gg@mail.gmail.com>
Message-ID: <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>

On Sat, May 21, 2016 at 2:12 AM, Fabio Estevam <festevam at gmail.com> wrote:
> On Fri, May 20, 2016 at 6:59 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:
>
>> Can you please try to boot and change the cpufreq governor to
>> performance and back and see if that works?
>
> I cannot change to governor with 9be4fd2c7723a305.
>
> After running 'cat performance >
> /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor'
> the system hangs silently.

So this means that irq_work doesn't really work on your system at all.
It looks like queuing up an irq_work sort of works (because the
IRQ_WORK_BUSY), but then the queue is never processed.

> Reverting 9be4fd2c7723a305 allows me to change to performace.

What exactly do you mean by reverting here?  It surely cannot be
reverted by itself and there are many things that depend on it.

>> Is this an SMP board, actually?
>
> Yes, this is a single core CortexA7.

Hmm.  Single core means non-SMP rather?


From rafael at kernel.org  Fri May 20 17:31:36 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Sat, 21 May 2016 02:31:36 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAOMZO5D_-3St-jqzMLzFHRn3dXXoSZGn4APSK4F63qCP3X=FfA@mail.gmail.com>
 <4080948.V5DMHR9bsk@vostro.rjw.lan>
 <CAOMZO5Di3s36=B_52g=S+sWjpdNQ2GozDjeT=3n0B5jNM9z8tA@mail.gmail.com>
 <CAJZ5v0h6qU8_BBmugSw8YGiWsmgYfZXtqOmGWkcNOM_O1mfD4g@mail.gmail.com>
 <CAOMZO5ABUpb4yx19j09hvOL7_QpO+_33Q+LCYQ-44LoqFrAxEg@mail.gmail.com>
 <CAJZ5v0icSd72P1MpMhOsZtC7mgLLGy_5-FM4t0d13zLe2cG8-Q@mail.gmail.com>
 <CAOMZO5C=v8AzSX7CNkJOkwtRM5dekZ8rpdAfZyggecbdcQK5gg@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
Message-ID: <CAJZ5v0ganmS5RoS3KuxtCKzBFHzR1bLpz8ttivj33FopsmnSmA@mail.gmail.com>

On Sat, May 21, 2016 at 2:30 AM, Rafael J. Wysocki <rafael at kernel.org> wrote:
> On Sat, May 21, 2016 at 2:12 AM, Fabio Estevam <festevam at gmail.com> wrote:
>> On Fri, May 20, 2016 at 6:59 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:
>>
>>> Can you please try to boot and change the cpufreq governor to
>>> performance and back and see if that works?
>>
>> I cannot change to governor with 9be4fd2c7723a305.
>>
>> After running 'cat performance >
>> /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor'
>> the system hangs silently.
>
> So this means that irq_work doesn't really work on your system at all.
> It looks like queuing up an irq_work sort of works (because the
> IRQ_WORK_BUSY), but then the queue is never processed.

I wanted to say "because the IRQ_WORK_BUSY flag is set", sorry.


From festevam at gmail.com  Fri May 20 17:36:52 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Fri, 20 May 2016 21:36:52 -0300
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAOMZO5D_-3St-jqzMLzFHRn3dXXoSZGn4APSK4F63qCP3X=FfA@mail.gmail.com>
 <4080948.V5DMHR9bsk@vostro.rjw.lan>
 <CAOMZO5Di3s36=B_52g=S+sWjpdNQ2GozDjeT=3n0B5jNM9z8tA@mail.gmail.com>
 <CAJZ5v0h6qU8_BBmugSw8YGiWsmgYfZXtqOmGWkcNOM_O1mfD4g@mail.gmail.com>
 <CAOMZO5ABUpb4yx19j09hvOL7_QpO+_33Q+LCYQ-44LoqFrAxEg@mail.gmail.com>
 <CAJZ5v0icSd72P1MpMhOsZtC7mgLLGy_5-FM4t0d13zLe2cG8-Q@mail.gmail.com>
 <CAOMZO5C=v8AzSX7CNkJOkwtRM5dekZ8rpdAfZyggecbdcQK5gg@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
Message-ID: <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>

On Fri, May 20, 2016 at 9:30 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:

> What exactly do you mean by reverting here?  It surely cannot be
> reverted by itself and there are many things that depend on it.

Yes, it cannot be reverted cleanly on 4.6.

If I do 'git checkout 9be4fd2c7723a30' and then 'git revert
9be4fd2c7723a30' then the reboot command works.

>>> Is this an SMP board, actually?
>>
>> Yes, this is a single core CortexA7.
>
> Hmm.  Single core means non-SMP rather?

CONFIG_SMP can be set or not in the kernel config. With CONFIG_SMP=n
the issue does not happen.


From rjw at rjwysocki.net  Fri May 20 17:56:20 2016
From: rjw at rjwysocki.net (Rafael J. Wysocki)
Date: Sat, 21 May 2016 02:56:20 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
Message-ID: <2148724.oQlEHos3jS@vostro.rjw.lan>

On Friday, May 20, 2016 09:36:52 PM Fabio Estevam wrote:
> On Fri, May 20, 2016 at 9:30 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:
> 
> > What exactly do you mean by reverting here?  It surely cannot be
> > reverted by itself and there are many things that depend on it.
> 
> Yes, it cannot be reverted cleanly on 4.6.
> 
> If I do 'git checkout 9be4fd2c7723a30' and then 'git revert
> 9be4fd2c7723a30' then the reboot command works.

OK, so in fact you need to go all the way to the parent of 9be4fd2c7723a30.

> >>> Is this an SMP board, actually?
> >>
> >> Yes, this is a single core CortexA7.
> >
> > Hmm.  Single core means non-SMP rather?
> 
> CONFIG_SMP can be set or not in the kernel config. With CONFIG_SMP=n
> the issue does not happen.

Yes, you can run an SMP kernel on a non-SMP board too, which is what leads to
the problem you're seeing.

If I'm not mistaken, the patch below should allow irq_work to make forward
progress for you, so please check if it makes any difference.

The root of the problem seems to be arch_irq_work_raise() and specifically
the __smp_cross_call function that appears to have problems.

I bet that is_smp() should return false on your platform, but it returns
true for some reason.

---
 drivers/cpufreq/cpufreq_governor.c |    1 +
 1 file changed, 1 insertion(+)

Index: linux-pm/drivers/cpufreq/cpufreq_governor.c
===================================================================
--- linux-pm.orig/drivers/cpufreq/cpufreq_governor.c
+++ linux-pm/drivers/cpufreq/cpufreq_governor.c
@@ -362,6 +362,7 @@ static struct policy_dbs_info *alloc_pol
 	mutex_init(&policy_dbs->timer_mutex);
 	atomic_set(&policy_dbs->work_count, 0);
 	init_irq_work(&policy_dbs->irq_work, dbs_irq_work);
+	policy_dbs->irq_work.flags = IRQ_WORK_LAZY;
 	INIT_WORK(&policy_dbs->work, dbs_work_handler);
 
 	/* Set policy_dbs for all CPUs, online+offline */



From festevam at gmail.com  Fri May 20 18:19:09 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Fri, 20 May 2016 22:19:09 -0300
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <2148724.oQlEHos3jS@vostro.rjw.lan>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
Message-ID: <CAOMZO5BBXmXAJayo8YpX4eV-_rTtAoDvjf91CUhWnLV8A0mx0g@mail.gmail.com>

Hi Rafael,

On Fri, May 20, 2016 at 9:56 PM, Rafael J. Wysocki <rjw at rjwysocki.net> wrote:

> If I'm not mistaken, the patch below should allow irq_work to make forward
> progress for you, so please check if it makes any difference.
....

> Index: linux-pm/drivers/cpufreq/cpufreq_governor.c
> ===================================================================
> --- linux-pm.orig/drivers/cpufreq/cpufreq_governor.c
> +++ linux-pm/drivers/cpufreq/cpufreq_governor.c
> @@ -362,6 +362,7 @@ static struct policy_dbs_info *alloc_pol
>         mutex_init(&policy_dbs->timer_mutex);
>         atomic_set(&policy_dbs->work_count, 0);
>         init_irq_work(&policy_dbs->irq_work, dbs_irq_work);
> +       policy_dbs->irq_work.flags = IRQ_WORK_LAZY;
>         INIT_WORK(&policy_dbs->work, dbs_work_handler);
>
>         /* Set policy_dbs for all CPUs, online+offline */

Running a 4.6 kernel with this patch applied allows me to reboot the
system, thanks.

'echo performance >
/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor' works fine now.


From festevam at gmail.com  Fri May 20 18:22:19 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Fri, 20 May 2016 22:22:19 -0300
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAOMZO5BBXmXAJayo8YpX4eV-_rTtAoDvjf91CUhWnLV8A0mx0g@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
 <CAOMZO5BBXmXAJayo8YpX4eV-_rTtAoDvjf91CUhWnLV8A0mx0g@mail.gmail.com>
Message-ID: <CAOMZO5DjgXuYiuOrUdbap3x2PVyUXbp2V1VGnU=2THRSM8Hfow@mail.gmail.com>

On Fri, May 20, 2016 at 10:19 PM, Fabio Estevam <festevam at gmail.com> wrote:

> Running a 4.6 kernel with this patch applied allows me to reboot the
> system, thanks.
>
> 'echo performance >
> /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor' works fine now.

and as a bonus point suspend/resume works fine now too :-)


From rafael at kernel.org  Fri May 20 18:31:59 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Sat, 21 May 2016 03:31:59 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAOMZO5DjgXuYiuOrUdbap3x2PVyUXbp2V1VGnU=2THRSM8Hfow@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
 <CAOMZO5BBXmXAJayo8YpX4eV-_rTtAoDvjf91CUhWnLV8A0mx0g@mail.gmail.com>
 <CAOMZO5DjgXuYiuOrUdbap3x2PVyUXbp2V1VGnU=2THRSM8Hfow@mail.gmail.com>
Message-ID: <CAJZ5v0i3h9Jepcxq5xZd1juCWxgOhT1-NBhV9zUXGz4A_j=XeA@mail.gmail.com>

On Sat, May 21, 2016 at 3:22 AM, Fabio Estevam <festevam at gmail.com> wrote:
> On Fri, May 20, 2016 at 10:19 PM, Fabio Estevam <festevam at gmail.com> wrote:
>
>> Running a 4.6 kernel with this patch applied allows me to reboot the
>> system, thanks.
>>
>> 'echo performance >
>> /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor' works fine now.
>
> and as a bonus point suspend/resume works fine now too :-)

OK, thanks for the confirmation!

The patch is just a workaround for a problem in the arch code showing
up on your platform, though.


From trini at konsulko.com  Fri May 20 18:41:59 2016
From: trini at konsulko.com (Tom Rini)
Date: Fri, 20 May 2016 21:41:59 -0400
Subject: [U-Boot] Sharing code between Linux and bootloader (U-boot) ?
In-Reply-To: <573F1F07.6040202@laposte.net>
References: <573F1F07.6040202@laposte.net>
Message-ID: <20160521014159.GK7650@bill-the-cat>

On Fri, May 20, 2016 at 04:28:23PM +0200, Sebastian Frias wrote:

> Hi,
> 
> Some bootloaders (like U-boot) support several HW devices: serial,
> network, NAND, USB, etc. most of which are also supported by Linux.
> 
> So the question is: is code shared? I mean, I understand that the
> drivers need to talk to the appropriate API, and such API could be
> different between Linux and U-boot.
> But putting that aside, would it be naive to imagine that some "core"
> functionality could be shared? Or would that part be so small it is
> not worth the effort?
> 
> Since many companies use both, U-boot and Linux, I would figure they
> try their best to optimize engineering resources and share code,
> right?
> In that case, I also wonder how do they share DT descriptions that
> right now are being stored in the Linux kernel tree.
> 
> We'd like to share code/DT for obvious reasons, what would you guys
> suggest?

So, in all cases, Linux is always the primary.  In some cases in U-Boot
we port drivers over (NAND is a good example here).  In other cases,
things are similar enough that it's having done it in one place it's
easy enough to do it again in the other.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160520/085f7137/attachment.sig>

From javier at osg.samsung.com  Fri May 20 19:11:37 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Fri, 20 May 2016 22:11:37 -0400
Subject: [PATCH] ARM: exynos: don't select keyboard driver
In-Reply-To: <1463581102-1007639-1-git-send-email-arnd@arndb.de>
References: <1463581102-1007639-1-git-send-email-arnd@arndb.de>
Message-ID: <b20eb044-f575-9504-2446-ca74df9d1724@osg.samsung.com>

Hello Arnd,

On 05/18/2016 10:17 AM, Arnd Bergmann wrote:
> The samsung-keypad driver is implicitly selected by ARCH_EXYNOS4 (why?),
> but this fails if CONFIG_INPUT is a loadable module:
> 
> drivers/input/built-in.o: In function `samsung_keypad_remove':
> drivers/input/keyboard/samsung-keypad.c:461: undefined reference to `input_unregister_device'
> drivers/input/built-in.o: In function `samsung_keypad_irq':
> drivers/input/keyboard/samsung-keypad.c:137: undefined reference to `input_event'
> drivers/input/built-in.o: In function `samsung_keypad_irq':
> include/linux/input.h:389: undefined reference to `input_event'
> drivers/input/built-in.o: In function `samsung_keypad_probe':
> drivers/input/keyboard/samsung-keypad.c:358: undefined reference to `devm_input_allocate_device'
> drivers/input/built-in.o:(.debug_addr+0x34): undefined reference to `input_set_capability'
> 
> This removes the 'select' as suggested by Krzysztof Kozlowski and
> instead enables the driver from the defconfig files.
> 
> The problem does not happen on mainline kernels, as we don't normally
> build built-in input drivers when CONFIG_INPUT=m, but I am experimenting
> with a patch to change this, and the samsung keypad driver showed up
> as one example that was silently broken before.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Link: https://lkml.org/lkml/2016/2/14/55
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Fri May 20 19:29:50 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Fri, 20 May 2016 22:29:50 -0400
Subject: [PATCH] pinctrl: samsung: Suppress unbinding to prevent
 theoretical attacks
In-Reply-To: <1463464926-17482-1-git-send-email-k.kozlowski@samsung.com>
References: <1463464926-17482-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <7d725a0a-216e-40d9-8a65-62eeb2faaf34@osg.samsung.com>

Hello Krzysztof,

On 05/17/2016 02:02 AM, Krzysztof Kozlowski wrote:
> Although unbinding a pinctrl driver requires root privileges but it
> still might be used theoretically in certain attacks (by triggering NULL
> pointer exception or memory corruption).
> 
> Samsung pincontrol drivers are essential for system operation so their
> removal is not expected. They do not implement remove() driver callback
> and they are not buildable as modules.
> 
> Suppression of the unbinding will prevent triggering NULL pointer
> exception like this (Odroid XU3):
> 
>   $ echo 13400000.pinctrl > /sys/bus/platform/drivers/samsung-pinctrl/unbind
>   $ cat /sys/kernel/debug/gpio
> 
>   Unable to handle kernel NULL pointer dereference at virtual address 00000c44
>   pgd = ec41c000
>   [00000c44] *pgd=6d448835, *pte=00000000, *ppte=00000000
>   Internal error: Oops: 17 [#1] PREEMPT SMP ARM
>     (samsung_gpio_get) from [<c034f9a0>] (gpiolib_seq_show+0x1b0/0x26c)
>     (gpiolib_seq_show) from [<c01fb8c0>] (seq_read+0x304/0x4b8)
>     (seq_read) from [<c02dbc78>] (full_proxy_read+0x4c/0x64)
>     (full_proxy_read) from [<c01d9fb0>] (__vfs_read+0x2c/0x110)
>     (__vfs_read) from [<c01db400>] (vfs_read+0x8c/0x110)
>     (vfs_read) from [<c01db4c4>] (SyS_read+0x40/0x8c)
>     (SyS_read) from [<c01078c0>] (ret_fast_syscall+0x0/0x3c)
> 
> Suggested-by: Marek Szyprowski <m.szyprowski at samsung.com>
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Fri May 20 19:30:30 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Fri, 20 May 2016 22:30:30 -0400
Subject: [PATCH] clk: samsung: Suppress unbinding to prevent theoretical
 attacks
In-Reply-To: <1463469974-13340-1-git-send-email-k.kozlowski@samsung.com>
References: <1463469974-13340-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <b71ecdbc-8650-a246-5e53-94eb620737ba@osg.samsung.com>

Hello Krzysztof,

On 05/17/2016 03:26 AM, Krzysztof Kozlowski wrote:
> Although unbinding a driver requires root privileges but it still might
> be used theoretically in certain attacks (by triggering NULL pointer
> exception or memory corruption if driver does not provide proper remove
> callbacks or core does not handle it).
> 
> Samsung clock drivers are essential for system operation so their
> removal is not expected. More over, the Exynos3250 ISP clock driver does
> not implement remove() driver callback and it is not buildable as
> modules.
> 
> Suppress the unbind interface for Exynos3250 ISP and S3C2410 DCLK clock
> drivers.
> 
> Suggested-by: Marek Szyprowski <m.szyprowski at samsung.com>
> Cc: Marek Szyprowski <m.szyprowski at samsung.com>
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From pavel at ucw.cz  Fri May 20 22:43:36 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Sat, 21 May 2016 07:43:36 +0200
Subject: [PATCHv2] support for AD5820 camera auto-focus coil
In-Reply-To: <20160517181927.GA28741@amd>
References: <20160517181927.GA28741@amd>
Message-ID: <20160521054336.GA27123@amd>

This adds support for AD5820 autofocus coil, found for example in
Nokia N900 smartphone.

Signed-off-by: Pavel Machek <pavel at ucw.cz>

---
v2: simple cleanups, fix error paths, simplify probe

I think it is ready. Please apply :-).

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 993dc50..77313a1 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -279,6 +279,13 @@ config VIDEO_ML86V7667
 	  To compile this driver as a module, choose M here: the
 	  module will be called ml86v7667.
 
+config VIDEO_AD5820
+	tristate "AD5820 lens voice coil support"
+	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+	---help---
+	  This is a driver for the AD5820 camera lens voice coil.
+	  It is used for example in Nokia N900 (RX-51).
+
 config VIDEO_SAA7110
 	tristate "Philips SAA7110 video decoder"
 	depends on VIDEO_V4L2 && I2C
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 94f2c99..34434ae 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -19,6 +20,7 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
 obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
 obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
+obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o
 obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
 obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
 obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
new file mode 100644
index 0000000..7725829
--- /dev/null
+++ b/drivers/media/i2c/ad5820.c
@@ -0,0 +1,416 @@
+/*
+ * drivers/media/i2c/ad5820.c
+ *
+ * AD5820 DAC driver for camera voice coil focus.
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2007 Texas Instruments
+ * Copyright (C) 2016 Pavel Machek <pavel at ucw.cz>
+ *
+ * Contact: Tuukka Toivonen
+ *          Sakari Ailus
+ *
+ * Based on af_d88.c by Texas Instruments.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/regulator/consumer.h>
+
+#include <media/ad5820.h>
+#include <media/v4l2-device.h>
+
+#define CODE_TO_RAMP_US(s)	((s) == 0 ? 0 : (1 << ((s) - 1)) * 50)
+#define RAMP_US_TO_CODE(c)	fls(((c) + ((c)>>1)) / 50)
+
+/**
+ * @brief I2C write using i2c_transfer().
+ * @param coil - the driver data structure
+ * @param data - register value to be written
+ * @returns nonnegative on success, negative if failed
+ */
+static int ad5820_write(struct ad5820_device *coil, u16 data)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&coil->subdev);
+	struct i2c_msg msg;
+	int r;
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	data = cpu_to_be16(data);
+	msg.addr  = client->addr;
+	msg.flags = 0;
+	msg.len   = 2;
+	msg.buf   = (u8 *)&data;
+
+	r = i2c_transfer(client->adapter, &msg, 1);
+	if (r < 0) {
+		dev_err(&client->dev, "write failed, error %d\n", r);
+		return r;
+	}
+
+	return 0;
+}
+
+/*
+ * Calculate status word and write it to the device based on current
+ * values of V4L2 controls. It is assumed that the stored V4L2 control
+ * values are properly limited and rounded.
+ */
+static int ad5820_update_hw(struct ad5820_device *coil)
+{
+	u16 status;
+
+	status = RAMP_US_TO_CODE(coil->focus_ramp_time);
+	status |= coil->focus_ramp_mode
+		? AD5820_RAMP_MODE_64_16 : AD5820_RAMP_MODE_LINEAR;
+	status |= coil->focus_absolute << AD5820_DAC_SHIFT;
+
+	if (coil->standby)
+		status |= AD5820_POWER_DOWN;
+
+	return ad5820_write(coil, status);
+}
+
+/*
+ * Power handling
+ */
+static int ad5820_power_off(struct ad5820_device *coil, int standby)
+{
+	int ret = 0;
+
+	/*
+	 * Go to standby first as real power off my be denied by the hardware
+	 * (single power line control for both coil and sensor).
+	 */
+	if (standby) {
+		coil->standby = 1;
+		ret = ad5820_update_hw(coil);
+	}
+
+	ret |= regulator_disable(coil->vana);
+
+	return ret;
+}
+
+static int ad5820_power_on(struct ad5820_device *coil, int restore)
+{
+	int ret;
+
+	printk("ad5820_power_on: 1\n");
+	ret = regulator_enable(coil->vana);
+	if (ret < 0)
+		return ret;
+
+	if (restore) {
+		/* Restore the hardware settings. */
+		coil->standby = 0;
+		ret = ad5820_update_hw(coil);
+		if (ret)
+			goto fail;
+	}
+	return 0;
+
+fail:
+	coil->standby = 1;
+	regulator_disable(coil->vana);
+
+	return ret;
+}
+
+/*
+ * V4L2 controls
+ */
+static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ad5820_device *coil =
+		container_of(ctrl->handler, struct ad5820_device, ctrls);
+	u32 code;
+
+	switch (ctrl->id) {
+	case V4L2_CID_FOCUS_ABSOLUTE:
+		coil->focus_absolute = ctrl->val;
+		return ad5820_update_hw(coil);
+
+	case V4L2_CID_FOCUS_AD5820_RAMP_TIME:
+		code = RAMP_US_TO_CODE(ctrl->val);
+		ctrl->val = CODE_TO_RAMP_US(code);
+		coil->focus_ramp_time = ctrl->val;
+		break;
+
+	case V4L2_CID_FOCUS_AD5820_RAMP_MODE:
+		coil->focus_ramp_mode = ctrl->val;
+		break;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops ad5820_ctrl_ops = {
+	.s_ctrl = ad5820_set_ctrl,
+};
+
+static const char *ad5820_focus_menu[] = {
+	"Linear ramp",
+	"64/16 ramp",
+};
+
+static const struct v4l2_ctrl_config ad5820_ctrls[] = {
+	{
+		.ops		= &ad5820_ctrl_ops,
+		.id		= V4L2_CID_FOCUS_AD5820_RAMP_TIME,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Focus ramping time [us]",
+		.min		= 0,
+		.max		= 3200,
+		.step		= 50,
+		.def		= 0,
+		.flags		= 0,
+	},
+	{
+		.ops		= &ad5820_ctrl_ops,
+		.id		= V4L2_CID_FOCUS_AD5820_RAMP_MODE,
+		.type		= V4L2_CTRL_TYPE_MENU,
+		.name		= "Focus ramping mode",
+		.min		= 0,
+		.max		= ARRAY_SIZE(ad5820_focus_menu),
+		.step		= 0,
+		.def		= 0,
+		.flags		= 0,
+		.qmenu		= ad5820_focus_menu,
+	},
+};
+
+
+static int ad5820_init_controls(struct ad5820_device *coil)
+{
+	unsigned int i;
+
+	v4l2_ctrl_handler_init(&coil->ctrls, ARRAY_SIZE(ad5820_ctrls) + 1);
+
+	/*
+	 * V4L2_CID_FOCUS_ABSOLUTE
+	 *
+	 * Minimum current is 0 mA, maximum is 100 mA. Thus, 1 code is
+	 * equivalent to 100/1023 = 0.0978 mA. Nevertheless, we do not use [mA]
+	 * for focus position, because it is meaningless for user. Meaningful
+	 * would be to use focus distance or even its inverse, but since the
+	 * driver doesn't have sufficiently knowledge to do the conversion, we
+	 * will just use abstract codes here. In any case, smaller value = focus
+	 * position farther from camera. The default zero value means focus at
+	 * infinity, and also least current consumption.
+	 */
+	v4l2_ctrl_new_std(&coil->ctrls, &ad5820_ctrl_ops,
+			  V4L2_CID_FOCUS_ABSOLUTE, 0, 1023, 1, 0);
+
+	/* V4L2_CID_TEST_PATTERN and V4L2_CID_MODE_* */
+	for (i = 0; i < ARRAY_SIZE(ad5820_ctrls); ++i)
+		v4l2_ctrl_new_custom(&coil->ctrls, &ad5820_ctrls[i], NULL);
+
+	if (coil->ctrls.error)
+		return coil->ctrls.error;
+
+	coil->focus_absolute = 0;
+	coil->focus_ramp_time = 0;
+	coil->focus_ramp_mode = 0;
+
+	coil->subdev.ctrl_handler = &coil->ctrls;
+	return 0;
+}
+
+/*
+ * V4L2 subdev operations
+ */
+static int ad5820_registered(struct v4l2_subdev *subdev)
+{
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+
+	coil->vana = regulator_get(&client->dev, "VANA");
+	if (IS_ERR(coil->vana)) {
+		dev_err(&client->dev, "could not get regulator for vana\n");
+		return -ENODEV;
+	}
+
+	return ad5820_init_controls(coil);
+}
+
+static int
+ad5820_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+	int ret = 0;
+
+	mutex_lock(&coil->power_lock);
+
+	/*
+	 * If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (coil->power_count == !on) {
+		ret = on ? ad5820_power_on(coil, 1) : ad5820_power_off(coil, 1);
+		if (ret < 0)
+			goto done;
+	}
+
+	/* Update the power count. */
+	coil->power_count += on ? 1 : -1;
+	WARN_ON(coil->power_count < 0);
+
+done:
+	mutex_unlock(&coil->power_lock);
+	return ret;
+}
+
+static int ad5820_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return ad5820_set_power(sd, 1);
+}
+
+static int ad5820_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return ad5820_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_core_ops ad5820_core_ops = {
+	.s_power = ad5820_set_power,
+};
+
+static const struct v4l2_subdev_ops ad5820_ops = {
+	.core = &ad5820_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops ad5820_internal_ops = {
+	.registered = ad5820_registered,
+	.open = ad5820_open,
+	.close = ad5820_close,
+};
+
+/*
+ * I2C driver
+ */
+#ifdef CONFIG_PM
+
+static int ad5820_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	if (!coil->power_count)
+		return 0;
+
+	return ad5820_power_off(coil, 0);
+}
+
+static int ad5820_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	if (!coil->power_count)
+		return 0;
+
+	return ad5820_power_on(coil, 1);
+}
+
+#else
+
+#define ad5820_suspend	NULL
+#define ad5820_resume	NULL
+
+#endif /* CONFIG_PM */
+
+static int ad5820_probe(struct i2c_client *client,
+			const struct i2c_device_id *devid)
+{
+	struct ad5820_device *coil;
+	int ret = 0;
+
+	coil = kzalloc(sizeof(*coil), GFP_KERNEL);
+	if (coil == NULL)
+		return -ENOMEM;
+
+	mutex_init(&coil->power_lock);
+
+	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
+	coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	coil->subdev.internal_ops = &ad5820_internal_ops;
+	strcpy(coil->subdev.name, "ad5820 focus");
+
+	ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
+	if (ret < 0)
+		goto free;
+
+	ret = v4l2_async_register_subdev(&coil->subdev);
+	if (ret < 0)
+		goto cleanup;
+
+	return ret;
+cleanup:
+	media_entity_cleanup(&coil->subdev.entity);
+free:
+	kfree(coil);
+	return ret;
+}
+
+static int __exit ad5820_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	v4l2_device_unregister_subdev(&coil->subdev);
+	v4l2_ctrl_handler_free(&coil->ctrls);
+	media_entity_cleanup(&coil->subdev.entity);
+	if (coil->vana)
+		regulator_put(coil->vana);
+
+	kfree(coil);
+	return 0;
+}
+
+static const struct i2c_device_id ad5820_id_table[] = {
+	{ AD5820_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ad5820_id_table);
+
+static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume);
+
+static struct i2c_driver ad5820_i2c_driver = {
+	.driver		= {
+		.name	= AD5820_NAME,
+		.pm	= &ad5820_pm,
+	},
+	.probe		= ad5820_probe,
+	.remove		= __exit_p(ad5820_remove),
+	.id_table	= ad5820_id_table,
+};
+
+module_i2c_driver(ad5820_i2c_driver);
+
+MODULE_AUTHOR("Tuukka Toivonen");
+MODULE_DESCRIPTION("AD5820 camera lens driver");
+MODULE_LICENSE("GPL");

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From ivo.g.dimitrov.75 at gmail.com  Fri May 20 23:25:21 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Sat, 21 May 2016 09:25:21 +0300
Subject: [PATCHv2] support for AD5820 camera auto-focus coil
In-Reply-To: <20160521054336.GA27123@amd>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
Message-ID: <573FFF51.1000004@gmail.com>

Hi,

On 21.05.2016 08:43, Pavel Machek wrote:
> This adds support for AD5820 autofocus coil, found for example in
> Nokia N900 smartphone.
>
> Signed-off-by: Pavel Machek <pavel at ucw.cz>
>
> ---
> v2: simple cleanups, fix error paths, simplify probe
>
> I think it is ready. Please apply :-).
>
> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> index 993dc50..77313a1 100644
> --- a/drivers/media/i2c/Kconfig
> +++ b/drivers/media/i2c/Kconfig
> @@ -279,6 +279,13 @@ config VIDEO_ML86V7667
>   	  To compile this driver as a module, choose M here: the
>   	  module will be called ml86v7667.
>
> +config VIDEO_AD5820
> +	tristate "AD5820 lens voice coil support"
> +	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
> +	---help---
> +	  This is a driver for the AD5820 camera lens voice coil.
> +	  It is used for example in Nokia N900 (RX-51).
> +
>   config VIDEO_SAA7110
>   	tristate "Philips SAA7110 video decoder"
>   	depends on VIDEO_V4L2 && I2C
> diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
> index 94f2c99..34434ae 100644
> --- a/drivers/media/i2c/Makefile
> +++ b/drivers/media/i2c/Makefile
> @@ -19,6 +20,7 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
>   obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
>   obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
>   obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
> +obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o
>   obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
>   obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
>   obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
> diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
> new file mode 100644
> index 0000000..7725829
> --- /dev/null
> +++ b/drivers/media/i2c/ad5820.c
> @@ -0,0 +1,416 @@
> +/*
> + * drivers/media/i2c/ad5820.c
> + *
> + * AD5820 DAC driver for camera voice coil focus.
> + *
> + * Copyright (C) 2008 Nokia Corporation
> + * Copyright (C) 2007 Texas Instruments
> + * Copyright (C) 2016 Pavel Machek <pavel at ucw.cz>
> + *
> + * Contact: Tuukka Toivonen
> + *          Sakari Ailus
> + *
> + * Based on af_d88.c by Texas Instruments.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> + * 02110-1301 USA
> + */
> +

Remove FSF address from the above.

> +#include <linux/module.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/slab.h>
> +#include <linux/sched.h>
> +#include <linux/delay.h>
> +#include <linux/bitops.h>
> +#include <linux/kernel.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include <media/ad5820.h>

drivers/media/i2c/ad5820.c:40:26: fatal error: media/ad5820.h: No such 
file or directory

> +#include <media/v4l2-device.h>
> +
> +#define CODE_TO_RAMP_US(s)	((s) == 0 ? 0 : (1 << ((s) - 1)) * 50)
> +#define RAMP_US_TO_CODE(c)	fls(((c) + ((c)>>1)) / 50)
> +
> +/**
> + * @brief I2C write using i2c_transfer().
> + * @param coil - the driver data structure
> + * @param data - register value to be written
> + * @returns nonnegative on success, negative if failed
> + */
> +static int ad5820_write(struct ad5820_device *coil, u16 data)
> +{
> +	struct i2c_client *client = v4l2_get_subdevdata(&coil->subdev);
> +	struct i2c_msg msg;
> +	int r;
> +
> +	if (!client->adapter)
> +		return -ENODEV;
> +
> +	data = cpu_to_be16(data);
> +	msg.addr  = client->addr;
> +	msg.flags = 0;
> +	msg.len   = 2;
> +	msg.buf   = (u8 *)&data;
> +
> +	r = i2c_transfer(client->adapter, &msg, 1);
> +	if (r < 0) {
> +		dev_err(&client->dev, "write failed, error %d\n", r);
> +		return r;
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * Calculate status word and write it to the device based on current
> + * values of V4L2 controls. It is assumed that the stored V4L2 control
> + * values are properly limited and rounded.
> + */
> +static int ad5820_update_hw(struct ad5820_device *coil)
> +{
> +	u16 status;
> +
> +	status = RAMP_US_TO_CODE(coil->focus_ramp_time);
> +	status |= coil->focus_ramp_mode
> +		? AD5820_RAMP_MODE_64_16 : AD5820_RAMP_MODE_LINEAR;
> +	status |= coil->focus_absolute << AD5820_DAC_SHIFT;
> +
> +	if (coil->standby)
> +		status |= AD5820_POWER_DOWN;
> +
> +	return ad5820_write(coil, status);
> +}
> +
> +/*
> + * Power handling
> + */
> +static int ad5820_power_off(struct ad5820_device *coil, int standby)
> +{
> +	int ret = 0;
> +
> +	/*
> +	 * Go to standby first as real power off my be denied by the hardware
> +	 * (single power line control for both coil and sensor).
> +	 */
> +	if (standby) {
> +		coil->standby = 1;
> +		ret = ad5820_update_hw(coil);
> +	}
> +
> +	ret |= regulator_disable(coil->vana);
> +
> +	return ret;
> +}
> +
> +static int ad5820_power_on(struct ad5820_device *coil, int restore)
> +{
> +	int ret;
> +
> +	printk("ad5820_power_on: 1\n");

Some remnants from testing?

> +	ret = regulator_enable(coil->vana);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (restore) {
> +		/* Restore the hardware settings. */
> +		coil->standby = 0;
> +		ret = ad5820_update_hw(coil);
> +		if (ret)
> +			goto fail;
> +	}
> +	return 0;
> +
> +fail:
> +	coil->standby = 1;
> +	regulator_disable(coil->vana);
> +
> +	return ret;
> +}
> +
> +/*
> + * V4L2 controls
> + */
> +static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +	struct ad5820_device *coil =
> +		container_of(ctrl->handler, struct ad5820_device, ctrls);
> +	u32 code;
> +
> +	switch (ctrl->id) {
> +	case V4L2_CID_FOCUS_ABSOLUTE:
> +		coil->focus_absolute = ctrl->val;
> +		return ad5820_update_hw(coil);
> +
> +	case V4L2_CID_FOCUS_AD5820_RAMP_TIME:
> +		code = RAMP_US_TO_CODE(ctrl->val);
> +		ctrl->val = CODE_TO_RAMP_US(code);
> +		coil->focus_ramp_time = ctrl->val;
> +		break;
> +
> +	case V4L2_CID_FOCUS_AD5820_RAMP_MODE:
> +		coil->focus_ramp_mode = ctrl->val;
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_ctrl_ops ad5820_ctrl_ops = {
> +	.s_ctrl = ad5820_set_ctrl,
> +};
> +
> +static const char *ad5820_focus_menu[] = {

static const char * const ?

> +	"Linear ramp",
> +	"64/16 ramp",
> +};
> +
> +static const struct v4l2_ctrl_config ad5820_ctrls[] = {
> +	{
> +		.ops		= &ad5820_ctrl_ops,
> +		.id		= V4L2_CID_FOCUS_AD5820_RAMP_TIME,
> +		.type		= V4L2_CTRL_TYPE_INTEGER,
> +		.name		= "Focus ramping time [us]",
> +		.min		= 0,
> +		.max		= 3200,
> +		.step		= 50,
> +		.def		= 0,
> +		.flags		= 0,
> +	},
> +	{
> +		.ops		= &ad5820_ctrl_ops,
> +		.id		= V4L2_CID_FOCUS_AD5820_RAMP_MODE,
> +		.type		= V4L2_CTRL_TYPE_MENU,
> +		.name		= "Focus ramping mode",
> +		.min		= 0,
> +		.max		= ARRAY_SIZE(ad5820_focus_menu),
> +		.step		= 0,
> +		.def		= 0,
> +		.flags		= 0,
> +		.qmenu		= ad5820_focus_menu,
> +	},
> +};
> +
> +
> +static int ad5820_init_controls(struct ad5820_device *coil)
> +{
> +	unsigned int i;
> +
> +	v4l2_ctrl_handler_init(&coil->ctrls, ARRAY_SIZE(ad5820_ctrls) + 1);
> +
> +	/*
> +	 * V4L2_CID_FOCUS_ABSOLUTE
> +	 *
> +	 * Minimum current is 0 mA, maximum is 100 mA. Thus, 1 code is
> +	 * equivalent to 100/1023 = 0.0978 mA. Nevertheless, we do not use [mA]
> +	 * for focus position, because it is meaningless for user. Meaningful
> +	 * would be to use focus distance or even its inverse, but since the
> +	 * driver doesn't have sufficiently knowledge to do the conversion, we
> +	 * will just use abstract codes here. In any case, smaller value = focus
> +	 * position farther from camera. The default zero value means focus at
> +	 * infinity, and also least current consumption.
> +	 */
> +	v4l2_ctrl_new_std(&coil->ctrls, &ad5820_ctrl_ops,
> +			  V4L2_CID_FOCUS_ABSOLUTE, 0, 1023, 1, 0);
> +
> +	/* V4L2_CID_TEST_PATTERN and V4L2_CID_MODE_* */
> +	for (i = 0; i < ARRAY_SIZE(ad5820_ctrls); ++i)
> +		v4l2_ctrl_new_custom(&coil->ctrls, &ad5820_ctrls[i], NULL);
> +
> +	if (coil->ctrls.error)
> +		return coil->ctrls.error;
> +
> +	coil->focus_absolute = 0;
> +	coil->focus_ramp_time = 0;
> +	coil->focus_ramp_mode = 0;
> +
> +	coil->subdev.ctrl_handler = &coil->ctrls;
> +	return 0;
> +}

please add a new line before return.

> +
> +/*
> + * V4L2 subdev operations
> + */
> +static int ad5820_registered(struct v4l2_subdev *subdev)
> +{
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +	struct i2c_client *client = v4l2_get_subdevdata(subdev);
> +
> +	coil->vana = regulator_get(&client->dev, "VANA");
> +	if (IS_ERR(coil->vana)) {
> +		dev_err(&client->dev, "could not get regulator for vana\n");
> +		return -ENODEV;
> +	}
> +
> +	return ad5820_init_controls(coil);
> +}
> +
> +static int
> +ad5820_set_power(struct v4l2_subdev *subdev, int on)
> +{
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +	int ret = 0;
> +
> +	mutex_lock(&coil->power_lock);
> +
> +	/*
> +	 * If the power count is modified from 0 to != 0 or from != 0 to 0,
> +	 * update the power state.
> +	 */
> +	if (coil->power_count == !on) {
> +		ret = on ? ad5820_power_on(coil, 1) : ad5820_power_off(coil, 1);
> +		if (ret < 0)
> +			goto done;
> +	}
> +
> +	/* Update the power count. */
> +	coil->power_count += on ? 1 : -1;
> +	WARN_ON(coil->power_count < 0);
> +
> +done:
> +	mutex_unlock(&coil->power_lock);
> +	return ret;
> +}
> +
> +static int ad5820_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> +{
> +	return ad5820_set_power(sd, 1);
> +}
> +
> +static int ad5820_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> +{
> +	return ad5820_set_power(sd, 0);
> +}
> +
> +static const struct v4l2_subdev_core_ops ad5820_core_ops = {
> +	.s_power = ad5820_set_power,
> +};
> +
> +static const struct v4l2_subdev_ops ad5820_ops = {
> +	.core = &ad5820_core_ops,
> +};
> +
> +static const struct v4l2_subdev_internal_ops ad5820_internal_ops = {
> +	.registered = ad5820_registered,
> +	.open = ad5820_open,
> +	.close = ad5820_close,
> +};
> +
> +/*
> + * I2C driver
> + */
> +#ifdef CONFIG_PM
> +
> +static int ad5820_suspend(struct device *dev)
> +{
> +	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
> +	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +
> +	if (!coil->power_count)
> +		return 0;
> +
> +	return ad5820_power_off(coil, 0);
> +}
> +
> +static int ad5820_resume(struct device *dev)
> +{
> +	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
> +	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +
> +	if (!coil->power_count)
> +		return 0;
> +
> +	return ad5820_power_on(coil, 1);
> +}
> +
> +#else
> +
> +#define ad5820_suspend	NULL
> +#define ad5820_resume	NULL
> +
> +#endif /* CONFIG_PM */
> +
> +static int ad5820_probe(struct i2c_client *client,
> +			const struct i2c_device_id *devid)
> +{
> +	struct ad5820_device *coil;
> +	int ret = 0;
> +
> +	coil = kzalloc(sizeof(*coil), GFP_KERNEL);
> +	if (coil == NULL)

if (!coil) ?

> +		return -ENOMEM;
> +
> +	mutex_init(&coil->power_lock);
> +
> +	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
> +	coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> +	coil->subdev.internal_ops = &ad5820_internal_ops;
> +	strcpy(coil->subdev.name, "ad5820 focus");
> +
> +	ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
> +	if (ret < 0)
> +		goto free;
> +
> +	ret = v4l2_async_register_subdev(&coil->subdev);
> +	if (ret < 0)
> +		goto cleanup;
> +
> +	return ret;
> +cleanup:
> +	media_entity_cleanup(&coil->subdev.entity);
> +free:
> +	kfree(coil);
> +	return ret;
> +}

new line before return, also I would put new lines before labels :)

> +
> +static int __exit ad5820_remove(struct i2c_client *client)
> +{
> +	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +
> +	v4l2_device_unregister_subdev(&coil->subdev);
> +	v4l2_ctrl_handler_free(&coil->ctrls);
> +	media_entity_cleanup(&coil->subdev.entity);
> +	if (coil->vana)
> +		regulator_put(coil->vana);
> +
> +	kfree(coil);

new line here

> +	return 0;
> +}
> +
> +static const struct i2c_device_id ad5820_id_table[] = {
> +	{ AD5820_NAME, 0 },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, ad5820_id_table);
> +
> +static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume);
> +
> +static struct i2c_driver ad5820_i2c_driver = {
> +	.driver		= {
> +		.name	= AD5820_NAME,
> +		.pm	= &ad5820_pm,
> +	},
> +	.probe		= ad5820_probe,
> +	.remove		= __exit_p(ad5820_remove),
> +	.id_table	= ad5820_id_table,
> +};
> +
> +module_i2c_driver(ad5820_i2c_driver);
> +
> +MODULE_AUTHOR("Tuukka Toivonen");
> +MODULE_DESCRIPTION("AD5820 camera lens driver");
> +MODULE_LICENSE("GPL");
>

Thanks,
Ivo


From hongkun.cao at mediatek.com  Sat May 21 00:23:39 2016
From: hongkun.cao at mediatek.com (hongkun.cao at mediatek.com)
Date: Sat, 21 May 2016 15:23:39 +0800
Subject: [PATCH] pinctrl: mediatek: fix dual-edge code defect
Message-ID: <1463815419-11719-1-git-send-email-hongkun.cao@mediatek.com>

From: "hongkun.cao" <hongkun.cao at mediatek.com>

When a dual-edge irq is triggered, an incorrect irq will be reported on
condition that the external signal is not stable and this incorrect irq
has been registered.
Correct the register offset.

Signed-off-by: hongkun.cao <hongkun.cao at mediatek.com>
---
 drivers/pinctrl/mediatek/pinctrl-mtk-common.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 2bbe6f7..92ae49f 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -1255,9 +1255,10 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
 	const struct mtk_desc_pin *pin;
 
 	chained_irq_enter(chip, desc);
-	for (eint_num = 0; eint_num < pctl->devdata->ap_num; eint_num += 32) {
+	for (eint_num = 0;
+	     eint_num < pctl->devdata->ap_num;
+	     eint_num += 32, reg += 4) {
 		status = readl(reg);
-		reg += 4;
 		while (status) {
 			offset = __ffs(status);
 			index = eint_num + offset;
-- 
1.7.9.5



From jassisinghbrar at gmail.com  Sat May 21 01:11:08 2016
From: jassisinghbrar at gmail.com (Jassi Brar)
Date: Sat, 21 May 2016 13:41:08 +0530
Subject: [GIT PULL] Mailbox changes for v4.7
Message-ID: <CABb+yY00f9NU-kmqVSe2h9XDuG-QvVf=wegYFetrF+CGEa+HbA@mail.gmail.com>

Hi Linus,

The following changes since commit c3b46c73264b03000d1e18b22f5caf63332547c9:

  Linux 4.6-rc4 (2016-04-17 19:13:32 -0700)

are available in the git repository at:

  git://git.linaro.org/landing-teams/working/fujitsu/integration.git
mailbox-for-next

for you to fetch changes up to c430cf376fee0b03d9c9293615f9737649de1b12:

  mailbox: Fix devm_ioremap_resource error detection code (2016-05-08
22:44:46 +0530)

----------------------------------------------------------------
- OMAP
       Remove non-DT support from mailbox driver
       Move PM from client calls to native driver suspend/resume
       Trivial cleanups to make checkpatch happy
- STI
        Check return from devm_ioremap_resource as ERR_PTR, not NULL

----------------------------------------------------------------
Amitoj Kaur Chawla (1):
      mailbox: Fix devm_ioremap_resource error detection code

Suman Anna (8):
      mailbox/omap: drop legacy platform device support
      mailbox/omap: use variable name for sizeof() operator
      mailbox/omap: remove FSF mailing address paragraph
      mailbox/omap: add blank lines after declarations
      mailbox/omap: store mailbox interrupt type in omap_mbox_device
      mailbox/omap: add support for suspend/resume
      mailbox/omap: check for any unread messages during suspend
      mailbox/omap: kill omap_mbox_{save/restore}_ctx() functions

 drivers/mailbox/mailbox-sti.c              |   4 +-
 drivers/mailbox/omap-mailbox.c             | 220 +++++++++++++----------------
 include/linux/omap-mailbox.h               |   2 -
 include/linux/platform_data/mailbox-omap.h |  58 --------
 4 files changed, 104 insertions(+), 180 deletions(-)
 delete mode 100644 include/linux/platform_data/mailbox-omap.h


From robert.jarzmik at free.fr  Sat May 21 01:33:29 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Sat, 21 May 2016 10:33:29 +0200
Subject: [GIT PULL 0/7] ARM: SoC changes for 4.7
In-Reply-To: <201605202101.24832.arnd@arndb.de> (Arnd Bergmann's message of
 "Fri, 20 May 2016 21:01:24 +0200")
References: <8749147.ztcb6kVhye@wuerfel> <87eg8xj018.fsf@belgarion.home>
 <201605202101.24832.arnd@arndb.de>
Message-ID: <87a8jjizdy.fsf@belgarion.home>

Arnd Bergmann <arnd at arndb.de> writes:

> On Thursday 19 May 2016, Robert Jarzmik wrote:
> I'm very sorry I completely missed the pull requests. I've the first one in the
> fixes branch now, so it should be in v4.7rc1 after all.
Don't worry, it's really all right, there is no urgency at all. And it's great
you'll pull the pxa/for-next for v4.7-rc1 !

> I also considered pulling the second branch into late/next, as it looks small
> and harmless and you did send it in time, but as you say here it's not really
> urgent either.	Just let me know if you want me to pick up "
> ARM: dts: pxa: fix the ohci clock for pxa3xx" in the fixes branch as well,
> I can cherry-pick the commit directly.
Oh no, let it be, it will live happily until v4.8 pull request. After all, no
time to market is driving me, let us enjoy this freedom :)

Cheers.

-- 
Robert


From robert.jarzmik at free.fr  Sat May 21 01:37:14 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Sat, 21 May 2016 10:37:14 +0200
Subject: [PATCH 1/1] ASoC: pxa: Fix module autoload for platform drivers
In-Reply-To: <1462548454-28597-1-git-send-email-andrea.adami@gmail.com>
 (Andrea Adami's message of "Fri, 6 May 2016 17:27:34 +0200")
References: <1462548454-28597-1-git-send-email-andrea.adami@gmail.com>
Message-ID: <8760u7iz7p.fsf@belgarion.home>

Andrea Adami <andrea.adami at gmail.com> writes:

> These platform drivers are lacking MODULE_ALIAS so module autoloading
> doesn't work. Tested on corgi and poodle with kernel 4.4.
>
> Signed-off-by: Andrea Adami <andrea.adami at gmail.com>
Yes, why not.

Acked-by: Robert Jarzmik <robert.jarzmik at free.fr>

Cheers.

--
Robert


From pavel at ucw.cz  Sat May 21 03:56:08 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Sat, 21 May 2016 12:56:08 +0200
Subject: [PATCHv3] support for AD5820 camera auto-focus coil
In-Reply-To: <573FFF51.1000004@gmail.com>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com>
Message-ID: <20160521105607.GA20071@amd>

This adds support for AD5820 autofocus coil, found for example in
Nokia N900 smartphone.

Signed-off-by: Pavel Machek <pavel at ucw.cz>

---
v2: simple cleanups, fix error paths, simplify probe

v3: more cleanups, remove printk, add include

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 993dc50..77313a1 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -279,6 +279,13 @@ config VIDEO_ML86V7667
 	  To compile this driver as a module, choose M here: the
 	  module will be called ml86v7667.
 
+config VIDEO_AD5820
+	tristate "AD5820 lens voice coil support"
+	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+	---help---
+	  This is a driver for the AD5820 camera lens voice coil.
+	  It is used for example in Nokia N900 (RX-51).
+
 config VIDEO_SAA7110
 	tristate "Philips SAA7110 video decoder"
 	depends on VIDEO_V4L2 && I2C
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 94f2c99..34434ae 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -19,6 +20,7 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
 obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
 obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
+obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o
 obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
 obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
 obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
new file mode 100644
index 0000000..7725829
--- /dev/null
+++ b/drivers/media/i2c/ad5820.c
@@ -0,0 +1,416 @@
+/*
+ * drivers/media/i2c/ad5820.c
+ *
+ * AD5820 DAC driver for camera voice coil focus.
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2007 Texas Instruments
+ * Copyright (C) 2016 Pavel Machek <pavel at ucw.cz>
+ *
+ * Contact: Tuukka Toivonen
+ *          Sakari Ailus
+ *
+ * Based on af_d88.c by Texas Instruments.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/regulator/consumer.h>
+
+#include <media/ad5820.h>
+#include <media/v4l2-device.h>
+
+#define CODE_TO_RAMP_US(s)	((s) == 0 ? 0 : (1 << ((s) - 1)) * 50)
+#define RAMP_US_TO_CODE(c)	fls(((c) + ((c)>>1)) / 50)
+
+/**
+ * @brief I2C write using i2c_transfer().
+ * @param coil - the driver data structure
+ * @param data - register value to be written
+ * @returns nonnegative on success, negative if failed
+ */
+static int ad5820_write(struct ad5820_device *coil, u16 data)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&coil->subdev);
+	struct i2c_msg msg;
+	int r;
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	data = cpu_to_be16(data);
+	msg.addr  = client->addr;
+	msg.flags = 0;
+	msg.len   = 2;
+	msg.buf   = (u8 *)&data;
+
+	r = i2c_transfer(client->adapter, &msg, 1);
+	if (r < 0) {
+		dev_err(&client->dev, "write failed, error %d\n", r);
+		return r;
+	}
+
+	return 0;
+}
+
+/*
+ * Calculate status word and write it to the device based on current
+ * values of V4L2 controls. It is assumed that the stored V4L2 control
+ * values are properly limited and rounded.
+ */
+static int ad5820_update_hw(struct ad5820_device *coil)
+{
+	u16 status;
+
+	status = RAMP_US_TO_CODE(coil->focus_ramp_time);
+	status |= coil->focus_ramp_mode
+		? AD5820_RAMP_MODE_64_16 : AD5820_RAMP_MODE_LINEAR;
+	status |= coil->focus_absolute << AD5820_DAC_SHIFT;
+
+	if (coil->standby)
+		status |= AD5820_POWER_DOWN;
+
+	return ad5820_write(coil, status);
+}
+
+/*
+ * Power handling
+ */
+static int ad5820_power_off(struct ad5820_device *coil, int standby)
+{
+	int ret = 0;
+
+	/*
+	 * Go to standby first as real power off my be denied by the hardware
+	 * (single power line control for both coil and sensor).
+	 */
+	if (standby) {
+		coil->standby = 1;
+		ret = ad5820_update_hw(coil);
+	}
+
+	ret |= regulator_disable(coil->vana);
+
+	return ret;
+}
+
+static int ad5820_power_on(struct ad5820_device *coil, int restore)
+{
+	int ret;
+
+	printk("ad5820_power_on: 1\n");
+	ret = regulator_enable(coil->vana);
+	if (ret < 0)
+		return ret;
+
+	if (restore) {
+		/* Restore the hardware settings. */
+		coil->standby = 0;
+		ret = ad5820_update_hw(coil);
+		if (ret)
+			goto fail;
+	}
+	return 0;
+
+fail:
+	coil->standby = 1;
+	regulator_disable(coil->vana);
+
+	return ret;
+}
+
+/*
+ * V4L2 controls
+ */
+static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ad5820_device *coil =
+		container_of(ctrl->handler, struct ad5820_device, ctrls);
+	u32 code;
+
+	switch (ctrl->id) {
+	case V4L2_CID_FOCUS_ABSOLUTE:
+		coil->focus_absolute = ctrl->val;
+		return ad5820_update_hw(coil);
+
+	case V4L2_CID_FOCUS_AD5820_RAMP_TIME:
+		code = RAMP_US_TO_CODE(ctrl->val);
+		ctrl->val = CODE_TO_RAMP_US(code);
+		coil->focus_ramp_time = ctrl->val;
+		break;
+
+	case V4L2_CID_FOCUS_AD5820_RAMP_MODE:
+		coil->focus_ramp_mode = ctrl->val;
+		break;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops ad5820_ctrl_ops = {
+	.s_ctrl = ad5820_set_ctrl,
+};
+
+static const char *ad5820_focus_menu[] = {
+	"Linear ramp",
+	"64/16 ramp",
+};
+
+static const struct v4l2_ctrl_config ad5820_ctrls[] = {
+	{
+		.ops		= &ad5820_ctrl_ops,
+		.id		= V4L2_CID_FOCUS_AD5820_RAMP_TIME,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Focus ramping time [us]",
+		.min		= 0,
+		.max		= 3200,
+		.step		= 50,
+		.def		= 0,
+		.flags		= 0,
+	},
+	{
+		.ops		= &ad5820_ctrl_ops,
+		.id		= V4L2_CID_FOCUS_AD5820_RAMP_MODE,
+		.type		= V4L2_CTRL_TYPE_MENU,
+		.name		= "Focus ramping mode",
+		.min		= 0,
+		.max		= ARRAY_SIZE(ad5820_focus_menu),
+		.step		= 0,
+		.def		= 0,
+		.flags		= 0,
+		.qmenu		= ad5820_focus_menu,
+	},
+};
+
+
+static int ad5820_init_controls(struct ad5820_device *coil)
+{
+	unsigned int i;
+
+	v4l2_ctrl_handler_init(&coil->ctrls, ARRAY_SIZE(ad5820_ctrls) + 1);
+
+	/*
+	 * V4L2_CID_FOCUS_ABSOLUTE
+	 *
+	 * Minimum current is 0 mA, maximum is 100 mA. Thus, 1 code is
+	 * equivalent to 100/1023 = 0.0978 mA. Nevertheless, we do not use [mA]
+	 * for focus position, because it is meaningless for user. Meaningful
+	 * would be to use focus distance or even its inverse, but since the
+	 * driver doesn't have sufficiently knowledge to do the conversion, we
+	 * will just use abstract codes here. In any case, smaller value = focus
+	 * position farther from camera. The default zero value means focus at
+	 * infinity, and also least current consumption.
+	 */
+	v4l2_ctrl_new_std(&coil->ctrls, &ad5820_ctrl_ops,
+			  V4L2_CID_FOCUS_ABSOLUTE, 0, 1023, 1, 0);
+
+	/* V4L2_CID_TEST_PATTERN and V4L2_CID_MODE_* */
+	for (i = 0; i < ARRAY_SIZE(ad5820_ctrls); ++i)
+		v4l2_ctrl_new_custom(&coil->ctrls, &ad5820_ctrls[i], NULL);
+
+	if (coil->ctrls.error)
+		return coil->ctrls.error;
+
+	coil->focus_absolute = 0;
+	coil->focus_ramp_time = 0;
+	coil->focus_ramp_mode = 0;
+
+	coil->subdev.ctrl_handler = &coil->ctrls;
+	return 0;
+}
+
+/*
+ * V4L2 subdev operations
+ */
+static int ad5820_registered(struct v4l2_subdev *subdev)
+{
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+
+	coil->vana = regulator_get(&client->dev, "VANA");
+	if (IS_ERR(coil->vana)) {
+		dev_err(&client->dev, "could not get regulator for vana\n");
+		return -ENODEV;
+	}
+
+	return ad5820_init_controls(coil);
+}
+
+static int
+ad5820_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+	int ret = 0;
+
+	mutex_lock(&coil->power_lock);
+
+	/*
+	 * If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (coil->power_count == !on) {
+		ret = on ? ad5820_power_on(coil, 1) : ad5820_power_off(coil, 1);
+		if (ret < 0)
+			goto done;
+	}
+
+	/* Update the power count. */
+	coil->power_count += on ? 1 : -1;
+	WARN_ON(coil->power_count < 0);
+
+done:
+	mutex_unlock(&coil->power_lock);
+	return ret;
+}
+
+static int ad5820_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return ad5820_set_power(sd, 1);
+}
+
+static int ad5820_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return ad5820_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_core_ops ad5820_core_ops = {
+	.s_power = ad5820_set_power,
+};
+
+static const struct v4l2_subdev_ops ad5820_ops = {
+	.core = &ad5820_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops ad5820_internal_ops = {
+	.registered = ad5820_registered,
+	.open = ad5820_open,
+	.close = ad5820_close,
+};
+
+/*
+ * I2C driver
+ */
+#ifdef CONFIG_PM
+
+static int ad5820_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	if (!coil->power_count)
+		return 0;
+
+	return ad5820_power_off(coil, 0);
+}
+
+static int ad5820_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	if (!coil->power_count)
+		return 0;
+
+	return ad5820_power_on(coil, 1);
+}
+
+#else
+
+#define ad5820_suspend	NULL
+#define ad5820_resume	NULL
+
+#endif /* CONFIG_PM */
+
+static int ad5820_probe(struct i2c_client *client,
+			const struct i2c_device_id *devid)
+{
+	struct ad5820_device *coil;
+	int ret = 0;
+
+	coil = kzalloc(sizeof(*coil), GFP_KERNEL);
+	if (coil == NULL)
+		return -ENOMEM;
+
+	mutex_init(&coil->power_lock);
+
+	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
+	coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	coil->subdev.internal_ops = &ad5820_internal_ops;
+	strcpy(coil->subdev.name, "ad5820 focus");
+
+	ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
+	if (ret < 0)
+		goto free;
+
+	ret = v4l2_async_register_subdev(&coil->subdev);
+	if (ret < 0)
+		goto cleanup;
+
+	return ret;
+cleanup:
+	media_entity_cleanup(&coil->subdev.entity);
+free:
+	kfree(coil);
+	return ret;
+}
+
+static int __exit ad5820_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	v4l2_device_unregister_subdev(&coil->subdev);
+	v4l2_ctrl_handler_free(&coil->ctrls);
+	media_entity_cleanup(&coil->subdev.entity);
+	if (coil->vana)
+		regulator_put(coil->vana);
+
+	kfree(coil);
+	return 0;
+}
+
+static const struct i2c_device_id ad5820_id_table[] = {
+	{ AD5820_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ad5820_id_table);
+
+static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume);
+
+static struct i2c_driver ad5820_i2c_driver = {
+	.driver		= {
+		.name	= AD5820_NAME,
+		.pm	= &ad5820_pm,
+	},
+	.probe		= ad5820_probe,
+	.remove		= __exit_p(ad5820_remove),
+	.id_table	= ad5820_id_table,
+};
+
+module_i2c_driver(ad5820_i2c_driver);
+
+MODULE_AUTHOR("Tuukka Toivonen");
+MODULE_DESCRIPTION("AD5820 camera lens driver");
+MODULE_LICENSE("GPL");
diff --git a/include/media/ad5820.h b/include/media/ad5820.h
new file mode 100644
index 0000000..f5a1565
--- /dev/null
+++ b/include/media/ad5820.h
@@ -0,0 +1,70 @@
+/*
+ * include/media/ad5820.h
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2007 Texas Instruments
+ *
+ * Contact: Tuukka Toivonen <tuukka.o.toivonen at nokia.com>
+ *          Sakari Ailus <sakari.ailus at nokia.com>
+ *
+ * Based on af_d88.c by Texas Instruments.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef AD5820_H
+#define AD5820_H
+
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+struct regulator;
+
+#define AD5820_NAME		"ad5820"
+#define AD5820_I2C_ADDR		(0x18 >> 1)
+
+/* Register definitions */
+#define AD5820_POWER_DOWN		(1 << 15)
+#define AD5820_DAC_SHIFT		4
+#define AD5820_RAMP_MODE_LINEAR		(0 << 3)
+#define AD5820_RAMP_MODE_64_16		(1 << 3)
+
+struct ad5820_platform_data {
+	int (*set_xshutdown)(struct v4l2_subdev *subdev, int set);
+};
+
+#define to_ad5820_device(sd)	container_of(sd, struct ad5820_device, subdev)
+
+struct ad5820_device {
+	struct v4l2_subdev subdev;
+	struct ad5820_platform_data *platform_data;
+	struct regulator *vana;
+
+	struct v4l2_ctrl_handler ctrls;
+	u32 focus_absolute;
+	u32 focus_ramp_time;
+	u32 focus_ramp_mode;
+
+	struct mutex power_lock;
+	int power_count;
+
+	int standby : 1;
+};
+
+#endif /* AD5820_H */



-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From andrea.gelmini at gelma.net  Sat May 21 04:36:48 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:36:48 +0200
Subject: [PATCH 0011/1529] Fix typo
Message-ID: <20160521113648.31841-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 Documentation/devicetree/bindings/arm/coresight.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
index 93147c0c..a846d4b 100644
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -6,7 +6,7 @@ SoCs tracing needs. These trace components can generally be classified as
 sinks, links and sources. Trace data produced by one or more sources flows
 through the intermediate links connecting the source to the currently selected
 sink. Each CoreSight component device should use these properties to describe
-its hardware characteristcs.
+its hardware characteristics.
 
 * Required properties for all components *except* non-configurable replicators:
 
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:37:22 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:37:22 +0200
Subject: [PATCH 0015/1529] Fix typo
Message-ID: <20160521113722.32053-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt b/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt
index 3e36c1d..616428a 100644
--- a/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt
+++ b/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt
@@ -8,7 +8,7 @@ use to analyze system performance, to make behaviors visible and to count
 usages of each IP (DMC, CPU, RIGHTBUS, LEFTBUS, CAM interface, LCD, G3D, MFC).
 The Exynos PPMU driver uses the devfreq-event class to provide event data
 to various devfreq devices. The devfreq devices would use the event data when
-derterming the current state of each IP.
+determing the current state of each IP.
 
 Required properties:
 - compatible: Should be "samsung,exynos-ppmu" or "samsung,exynos-ppmu-v2.
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:37:32 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:37:32 +0200
Subject: [PATCH 0016/1529] Fix typo
Message-ID: <20160521113732.32110-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 Documentation/devicetree/bindings/display/cirrus,clps711x-fb.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/cirrus,clps711x-fb.txt b/Documentation/devicetree/bindings/display/cirrus,clps711x-fb.txt
index d685be8..66a261c 100644
--- a/Documentation/devicetree/bindings/display/cirrus,clps711x-fb.txt
+++ b/Documentation/devicetree/bindings/display/cirrus,clps711x-fb.txt
@@ -1,4 +1,4 @@
-* Currus Logic CLPS711X Framebuffer
+* Cirrus Logic CLPS711X Framebuffer
 
 Required properties:
 - compatible: Shall contain "cirrus,clps711x-fb".
-- 
2.8.2.534.g1f66975



From ivo.g.dimitrov.75 at gmail.com  Sat May 21 04:43:43 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Sat, 21 May 2016 14:43:43 +0300
Subject: [PATCHv3] support for AD5820 camera auto-focus coil
In-Reply-To: <20160521105607.GA20071@amd>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com> <20160521105607.GA20071@amd>
Message-ID: <574049EF.2090208@gmail.com>

Hi,

On 21.05.2016 13:56, Pavel Machek wrote:
> This adds support for AD5820 autofocus coil, found for example in
> Nokia N900 smartphone.
>
> Signed-off-by: Pavel Machek <pavel at ucw.cz>
>
> ---
> v2: simple cleanups, fix error paths, simplify probe
>
> v3: more cleanups, remove printk, add include
>
> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> index 993dc50..77313a1 100644
> --- a/drivers/media/i2c/Kconfig
> +++ b/drivers/media/i2c/Kconfig
> @@ -279,6 +279,13 @@ config VIDEO_ML86V7667
>   	  To compile this driver as a module, choose M here: the
>   	  module will be called ml86v7667.
>
> +config VIDEO_AD5820
> +	tristate "AD5820 lens voice coil support"
> +	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
> +	---help---
> +	  This is a driver for the AD5820 camera lens voice coil.
> +	  It is used for example in Nokia N900 (RX-51).
> +
>   config VIDEO_SAA7110
>   	tristate "Philips SAA7110 video decoder"
>   	depends on VIDEO_V4L2 && I2C
> diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
> index 94f2c99..34434ae 100644
> --- a/drivers/media/i2c/Makefile
> +++ b/drivers/media/i2c/Makefile
> @@ -19,6 +20,7 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
>   obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
>   obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
>   obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
> +obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o
>   obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
>   obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
>   obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
> diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
> new file mode 100644
> index 0000000..7725829
> --- /dev/null
> +++ b/drivers/media/i2c/ad5820.c
> @@ -0,0 +1,416 @@
> +/*
> + * drivers/media/i2c/ad5820.c
> + *
> + * AD5820 DAC driver for camera voice coil focus.
> + *
> + * Copyright (C) 2008 Nokia Corporation
> + * Copyright (C) 2007 Texas Instruments
> + * Copyright (C) 2016 Pavel Machek <pavel at ucw.cz>
> + *
> + * Contact: Tuukka Toivonen
> + *          Sakari Ailus
> + *
> + * Based on af_d88.c by Texas Instruments.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> + * 02110-1301 USA
> + */
> +

At least on my machine checkpatch.pl complains about FSF address.

> +#include <linux/module.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/slab.h>
> +#include <linux/sched.h>
> +#include <linux/delay.h>

Doesn't seem to get used.

> +#include <linux/bitops.h>
> +#include <linux/kernel.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include <media/ad5820.h>
> +#include <media/v4l2-device.h>
> +
> +#define CODE_TO_RAMP_US(s)	((s) == 0 ? 0 : (1 << ((s) - 1)) * 50)
> +#define RAMP_US_TO_CODE(c)	fls(((c) + ((c)>>1)) / 50)
> +
> +/**
> + * @brief I2C write using i2c_transfer().
> + * @param coil - the driver data structure
> + * @param data - register value to be written
> + * @returns nonnegative on success, negative if failed
> + */
> +static int ad5820_write(struct ad5820_device *coil, u16 data)
> +{
> +	struct i2c_client *client = v4l2_get_subdevdata(&coil->subdev);
> +	struct i2c_msg msg;
> +	int r;
> +
> +	if (!client->adapter)
> +		return -ENODEV;
> +
> +	data = cpu_to_be16(data);
> +	msg.addr  = client->addr;
> +	msg.flags = 0;
> +	msg.len   = 2;
> +	msg.buf   = (u8 *)&data;
> +
> +	r = i2c_transfer(client->adapter, &msg, 1);
> +	if (r < 0) {
> +		dev_err(&client->dev, "write failed, error %d\n", r);
> +		return r;
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * Calculate status word and write it to the device based on current
> + * values of V4L2 controls. It is assumed that the stored V4L2 control
> + * values are properly limited and rounded.
> + */
> +static int ad5820_update_hw(struct ad5820_device *coil)
> +{
> +	u16 status;
> +
> +	status = RAMP_US_TO_CODE(coil->focus_ramp_time);
> +	status |= coil->focus_ramp_mode
> +		? AD5820_RAMP_MODE_64_16 : AD5820_RAMP_MODE_LINEAR;
> +	status |= coil->focus_absolute << AD5820_DAC_SHIFT;
> +
> +	if (coil->standby)
> +		status |= AD5820_POWER_DOWN;
> +
> +	return ad5820_write(coil, status);
> +}
> +
> +/*
> + * Power handling
> + */
> +static int ad5820_power_off(struct ad5820_device *coil, int standby)
> +{
> +	int ret = 0;
> +
> +	/*
> +	 * Go to standby first as real power off my be denied by the hardware
> +	 * (single power line control for both coil and sensor).
> +	 */
> +	if (standby) {
> +		coil->standby = 1;
> +		ret = ad5820_update_hw(coil);
> +	}
> +
> +	ret |= regulator_disable(coil->vana);
> +
> +	return ret;
> +}
> +
> +static int ad5820_power_on(struct ad5820_device *coil, int restore)
> +{
> +	int ret;
> +
> +	printk("ad5820_power_on: 1\n");
> +	ret = regulator_enable(coil->vana);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (restore) {
> +		/* Restore the hardware settings. */
> +		coil->standby = 0;
> +		ret = ad5820_update_hw(coil);
> +		if (ret)
> +			goto fail;
> +	}
> +	return 0;
> +
> +fail:
> +	coil->standby = 1;
> +	regulator_disable(coil->vana);
> +
> +	return ret;
> +}
> +
> +/*
> + * V4L2 controls
> + */
> +static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +	struct ad5820_device *coil =
> +		container_of(ctrl->handler, struct ad5820_device, ctrls);
> +	u32 code;
> +
> +	switch (ctrl->id) {
> +	case V4L2_CID_FOCUS_ABSOLUTE:
> +		coil->focus_absolute = ctrl->val;
> +		return ad5820_update_hw(coil);
> +
> +	case V4L2_CID_FOCUS_AD5820_RAMP_TIME:
> +		code = RAMP_US_TO_CODE(ctrl->val);
> +		ctrl->val = CODE_TO_RAMP_US(code);
> +		coil->focus_ramp_time = ctrl->val;
> +		break;
> +
> +	case V4L2_CID_FOCUS_AD5820_RAMP_MODE:
> +		coil->focus_ramp_mode = ctrl->val;
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_ctrl_ops ad5820_ctrl_ops = {
> +	.s_ctrl = ad5820_set_ctrl,
> +};
> +
> +static const char *ad5820_focus_menu[] = {
> +	"Linear ramp",
> +	"64/16 ramp",
> +};
> +
> +static const struct v4l2_ctrl_config ad5820_ctrls[] = {
> +	{
> +		.ops		= &ad5820_ctrl_ops,
> +		.id		= V4L2_CID_FOCUS_AD5820_RAMP_TIME,
> +		.type		= V4L2_CTRL_TYPE_INTEGER,
> +		.name		= "Focus ramping time [us]",
> +		.min		= 0,
> +		.max		= 3200,
> +		.step		= 50,
> +		.def		= 0,
> +		.flags		= 0,
> +	},
> +	{
> +		.ops		= &ad5820_ctrl_ops,
> +		.id		= V4L2_CID_FOCUS_AD5820_RAMP_MODE,
> +		.type		= V4L2_CTRL_TYPE_MENU,
> +		.name		= "Focus ramping mode",
> +		.min		= 0,
> +		.max		= ARRAY_SIZE(ad5820_focus_menu),
> +		.step		= 0,
> +		.def		= 0,
> +		.flags		= 0,
> +		.qmenu		= ad5820_focus_menu,
> +	},
> +};
> +
> +
> +static int ad5820_init_controls(struct ad5820_device *coil)
> +{
> +	unsigned int i;
> +
> +	v4l2_ctrl_handler_init(&coil->ctrls, ARRAY_SIZE(ad5820_ctrls) + 1);
> +
> +	/*
> +	 * V4L2_CID_FOCUS_ABSOLUTE
> +	 *
> +	 * Minimum current is 0 mA, maximum is 100 mA. Thus, 1 code is
> +	 * equivalent to 100/1023 = 0.0978 mA. Nevertheless, we do not use [mA]
> +	 * for focus position, because it is meaningless for user. Meaningful
> +	 * would be to use focus distance or even its inverse, but since the
> +	 * driver doesn't have sufficiently knowledge to do the conversion, we
> +	 * will just use abstract codes here. In any case, smaller value = focus
> +	 * position farther from camera. The default zero value means focus at
> +	 * infinity, and also least current consumption.
> +	 */
> +	v4l2_ctrl_new_std(&coil->ctrls, &ad5820_ctrl_ops,
> +			  V4L2_CID_FOCUS_ABSOLUTE, 0, 1023, 1, 0);
> +
> +	/* V4L2_CID_TEST_PATTERN and V4L2_CID_MODE_* */
> +	for (i = 0; i < ARRAY_SIZE(ad5820_ctrls); ++i)
> +		v4l2_ctrl_new_custom(&coil->ctrls, &ad5820_ctrls[i], NULL);
> +
> +	if (coil->ctrls.error)
> +		return coil->ctrls.error;
> +
> +	coil->focus_absolute = 0;
> +	coil->focus_ramp_time = 0;
> +	coil->focus_ramp_mode = 0;
> +
> +	coil->subdev.ctrl_handler = &coil->ctrls;
> +	return 0;
> +}
> +
> +/*
> + * V4L2 subdev operations
> + */
> +static int ad5820_registered(struct v4l2_subdev *subdev)
> +{
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +	struct i2c_client *client = v4l2_get_subdevdata(subdev);
> +
> +	coil->vana = regulator_get(&client->dev, "VANA");

devm_regulator_get()?

> +	if (IS_ERR(coil->vana)) {
> +		dev_err(&client->dev, "could not get regulator for vana\n");
> +		return -ENODEV;
> +	}
> +
> +	return ad5820_init_controls(coil);
> +}
> +
> +static int
> +ad5820_set_power(struct v4l2_subdev *subdev, int on)
> +{
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +	int ret = 0;
> +
> +	mutex_lock(&coil->power_lock);
> +
> +	/*
> +	 * If the power count is modified from 0 to != 0 or from != 0 to 0,
> +	 * update the power state.
> +	 */
> +	if (coil->power_count == !on) {
> +		ret = on ? ad5820_power_on(coil, 1) : ad5820_power_off(coil, 1);
> +		if (ret < 0)
> +			goto done;
> +	}
> +
> +	/* Update the power count. */
> +	coil->power_count += on ? 1 : -1;
> +	WARN_ON(coil->power_count < 0);
> +
> +done:
> +	mutex_unlock(&coil->power_lock);
> +	return ret;
> +}
> +
> +static int ad5820_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> +{
> +	return ad5820_set_power(sd, 1);
> +}
> +
> +static int ad5820_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> +{
> +	return ad5820_set_power(sd, 0);
> +}
> +
> +static const struct v4l2_subdev_core_ops ad5820_core_ops = {
> +	.s_power = ad5820_set_power,
> +};
> +
> +static const struct v4l2_subdev_ops ad5820_ops = {
> +	.core = &ad5820_core_ops,
> +};
> +
> +static const struct v4l2_subdev_internal_ops ad5820_internal_ops = {
> +	.registered = ad5820_registered,
> +	.open = ad5820_open,
> +	.close = ad5820_close,
> +};
> +
> +/*
> + * I2C driver
> + */
> +#ifdef CONFIG_PM
> +
> +static int ad5820_suspend(struct device *dev)
> +{
> +	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
> +	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +
> +	if (!coil->power_count)
> +		return 0;
> +
> +	return ad5820_power_off(coil, 0);
> +}
> +
> +static int ad5820_resume(struct device *dev)
> +{
> +	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
> +	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +
> +	if (!coil->power_count)
> +		return 0;
> +
> +	return ad5820_power_on(coil, 1);
> +}
> +
> +#else
> +
> +#define ad5820_suspend	NULL
> +#define ad5820_resume	NULL
> +
> +#endif /* CONFIG_PM */
> +
> +static int ad5820_probe(struct i2c_client *client,
> +			const struct i2c_device_id *devid)
> +{
> +	struct ad5820_device *coil;
> +	int ret = 0;
> +
> +	coil = kzalloc(sizeof(*coil), GFP_KERNEL);

devm_kzalloc() ?

> +	if (coil == NULL)
> +		return -ENOMEM;
> +
> +	mutex_init(&coil->power_lock);
> +
> +	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
> +	coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> +	coil->subdev.internal_ops = &ad5820_internal_ops;
> +	strcpy(coil->subdev.name, "ad5820 focus");
> +
> +	ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
> +	if (ret < 0)
> +		goto free;
> +
> +	ret = v4l2_async_register_subdev(&coil->subdev);
> +	if (ret < 0)
> +		goto cleanup;
> +
> +	return ret;
> +cleanup:
> +	media_entity_cleanup(&coil->subdev.entity);
> +free:
> +	kfree(coil);
> +	return ret;
> +}
> +
> +static int __exit ad5820_remove(struct i2c_client *client)
> +{
> +	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +
> +	v4l2_device_unregister_subdev(&coil->subdev);
> +	v4l2_ctrl_handler_free(&coil->ctrls);
> +	media_entity_cleanup(&coil->subdev.entity);
> +	if (coil->vana)
> +		regulator_put(coil->vana);
> +
> +	kfree(coil);
> +	return 0;
> +}
> +
> +static const struct i2c_device_id ad5820_id_table[] = {
> +	{ AD5820_NAME, 0 },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, ad5820_id_table);
> +
> +static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume);
> +
> +static struct i2c_driver ad5820_i2c_driver = {
> +	.driver		= {
> +		.name	= AD5820_NAME,
> +		.pm	= &ad5820_pm,
> +	},
> +	.probe		= ad5820_probe,
> +	.remove		= __exit_p(ad5820_remove),
> +	.id_table	= ad5820_id_table,
> +};
> +
> +module_i2c_driver(ad5820_i2c_driver);
> +
> +MODULE_AUTHOR("Tuukka Toivonen");
> +MODULE_DESCRIPTION("AD5820 camera lens driver");
> +MODULE_LICENSE("GPL");
> diff --git a/include/media/ad5820.h b/include/media/ad5820.h
> new file mode 100644
> index 0000000..f5a1565
> --- /dev/null
> +++ b/include/media/ad5820.h
> @@ -0,0 +1,70 @@
> +/*
> + * include/media/ad5820.h
> + *
> + * Copyright (C) 2008 Nokia Corporation
> + * Copyright (C) 2007 Texas Instruments
> + *
> + * Contact: Tuukka Toivonen <tuukka.o.toivonen at nokia.com>
> + *          Sakari Ailus <sakari.ailus at nokia.com>
> + *
> + * Based on af_d88.c by Texas Instruments.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> + * 02110-1301 USA
> + */
> +
> +#ifndef AD5820_H
> +#define AD5820_H
> +
> +#include <linux/i2c.h>
> +#include <linux/mutex.h>
> +#include <linux/videodev2.h>
> +
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-subdev.h>
> +
> +struct regulator;
> +
> +#define AD5820_NAME		"ad5820"
> +#define AD5820_I2C_ADDR		(0x18 >> 1)
> +
> +/* Register definitions */
> +#define AD5820_POWER_DOWN		(1 << 15)
> +#define AD5820_DAC_SHIFT		4

Do those defines really belong here? Isn't it better if they are moved 
to ad5820.c?

> +#define AD5820_RAMP_MODE_LINEAR		(0 << 3)
> +#define AD5820_RAMP_MODE_64_16		(1 << 3)
> +
> +struct ad5820_platform_data {
> +	int (*set_xshutdown)(struct v4l2_subdev *subdev, int set);
> +};
> +
> +#define to_ad5820_device(sd)	container_of(sd, struct ad5820_device, subdev)
> +
> +struct ad5820_device {
> +	struct v4l2_subdev subdev;
> +	struct ad5820_platform_data *platform_data;
> +	struct regulator *vana;
> +
> +	struct v4l2_ctrl_handler ctrls;
> +	u32 focus_absolute;
> +	u32 focus_ramp_time;
> +	u32 focus_ramp_mode;
> +
> +	struct mutex power_lock;
> +	int power_count;
> +
> +	int standby : 1;
> +};
> +

The same for struct ad5820_device, is it really part of the public API?

> +#endif /* AD5820_H */
>
>
>


From andrea.gelmini at gelma.net  Sat May 21 04:47:27 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:47:27 +0200
Subject: [PATCH 0081/1529] Fix typo
Message-ID: <20160521114727.3496-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/common/scoop.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 9ba45ad..5e24e06 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -27,7 +27,7 @@
    is used which is setup by the platform code.
 
    This file is never modular so this symbol is always
-   accessile to the board support files.
+   accessible to the board support files.
 */
 struct scoop_pcmcia_config *platform_scoop_config;
 EXPORT_SYMBOL(platform_scoop_config);
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:47:36 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:47:36 +0200
Subject: [PATCH 0082/1529] Fix typo
Message-ID: <20160521114736.3553-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/include/asm/fncpy.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/fncpy.h b/arch/arm/include/asm/fncpy.h
index de53547..88f9c36 100644
--- a/arch/arm/include/asm/fncpy.h
+++ b/arch/arm/include/asm/fncpy.h
@@ -49,7 +49,7 @@
  * copied_f(args);
  *
  * The size of the function to be copied can't be determined from C:
- * this must be determined by other means, such as adding assmbler directives
+ * this must be determined by other means, such as adding assembler directives
  * in the file where f is defined.
  */
 
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:47:44 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:47:44 +0200
Subject: [PATCH 0083/1529] Fix typo
Message-ID: <20160521114744.3635-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/include/asm/spinlock.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h
index 0fa4184..c8122df 100644
--- a/arch/arm/include/asm/spinlock.h
+++ b/arch/arm/include/asm/spinlock.h
@@ -19,7 +19,7 @@
  * assembler to insert a extra (16-bit) IT instruction, depending on the
  * presence or absence of neighbouring conditional instructions.
  *
- * To avoid this unpredictableness, an approprite IT is inserted explicitly:
+ * To avoid this unpredictableness, an appropriate IT is inserted explicitly:
  * the assembler won't change IT instructions which are explicitly present
  * in the input.
  */
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:47:52 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:47:52 +0200
Subject: [PATCH 0084/1529] Fix typo
Message-ID: <20160521114752.3706-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/include/asm/tlbflush.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index def9e57..2dee30f 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -281,7 +281,7 @@ extern struct cpu_tlb_fns cpu_tlb;
  *  - if we're going to need __cpu_tlb_flags, access it once and only once
  *
  * This allows us to build optimal assembly for the single-CPU type case,
- * and as close to optimal given the compiler constrants for multi-CPU
+ * and as close to optimal given the compiler constraints for multi-CPU
  * case.  We could do better for the multi-CPU case if the compiler
  * implemented the "%?" method, but this has been discontinued due to too
  * many people getting it wrong.
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:47:59 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:47:59 +0200
Subject: [PATCH 0085/1529] Fix typo
Message-ID: <20160521114759.3760-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/include/asm/ucontext.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h
index 14749ae..b4d2d0f 100644
--- a/arch/arm/include/asm/ucontext.h
+++ b/arch/arm/include/asm/ucontext.h
@@ -8,7 +8,7 @@
  * ucontext now has room for all registers which need to be saved and
  * restored.  Coprocessor registers are stored in uc_regspace.  Each
  * coprocessor's saved state should start with a documented 32-bit magic
- * number, followed by a 32-bit word giving the coproccesor's saved size.
+ * number, followed by a 32-bit word giving the coprocessor saved size.
  * uc_regspace may be expanded if necessary, although this takes some
  * coordination with glibc.
  */
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:48:07 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:48:07 +0200
Subject: [PATCH 0086/1529] Fix typo
Message-ID: <20160521114807.3817-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/include/debug/samsung.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/include/debug/samsung.S b/arch/arm/include/debug/samsung.S
index 8d8d922..92f1bc8 100644
--- a/arch/arm/include/debug/samsung.S
+++ b/arch/arm/include/debug/samsung.S
@@ -11,7 +11,7 @@
 
 #include <linux/serial_s3c.h>
 
-/* The S5PV210/S5PC110 implementations are as belows. */
+/* The S5PV210/S5PC110 implementations are as below. */
 
 	.macro fifo_level_s5pv210 rd, rx
 		ldr	\rd, [\rx, # S3C2410_UFSTAT]
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:48:14 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:48:14 +0200
Subject: [PATCH 0087/1529] Fix typo
Message-ID: <20160521114814.3868-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/kernel/sys_oabi-compat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index 087acb5..e3e0c00 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -58,7 +58,7 @@
  * sys_semtimedop:
  *
  *   struct sembuf loses its padding with EABI.  Since arrays of them are
- *   used they have to be copyed to remove the padding. Compatibility wrappers
+ *   used they have to be copied to remove the padding. Compatibility wrappers
  *   provided below.
  *
  * sys_bind:
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:48:21 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:48:21 +0200
Subject: [PATCH 0088/1529] Fix typo
Message-ID: <20160521114821.3925-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/kernel/time.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 97b22fa..a6fb752 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -98,7 +98,7 @@ void read_boot_clock64(struct timespec64 *ts)
 int __init register_persistent_clock(clock_access_fn read_boot,
 				     clock_access_fn read_persistent)
 {
-	/* Only allow the clockaccess functions to be registered once */
+	/* Only allow the clock access functions to be registered once */
 	if (__read_persistent_clock == dummy_clock_access &&
 	    __read_boot_clock == dummy_clock_access) {
 		if (read_boot)
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:48:29 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:48:29 +0200
Subject: [PATCH 0089/1529] Fix typo
Message-ID: <20160521114829.3977-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/kernel/topology.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index ec279d1..ebbf60c 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -154,7 +154,7 @@ static void __init parse_dt_topology(void)
 }
 
 /*
- * Look for a customed capacity of a CPU in the cpu_capacity table during the
+ * Look for a custom capacity of a CPU in the cpu_capacity table during the
  * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the
  * function returns directly for SMP system.
  */
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:48:35 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:48:35 +0200
Subject: [PATCH 0090/1529] Fix typo
Message-ID: <20160521114835.4026-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/kvm/arm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 237d5d8..16e38f4 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -376,7 +376,7 @@ void force_vm_exit(const cpumask_t *mask)
 
 /**
  * need_new_vmid_gen - check that the VMID is still valid
- * @kvm: The VM's VMID to checkt
+ * @kvm: The VM's VMID to check
  *
  * return true if there is a new generation of VMIDs being used
  *
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:48:41 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:48:41 +0200
Subject: [PATCH 0091/1529] Fix typo
Message-ID: <20160521114841.4077-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/kvm/emulate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index a494def..af93e3f 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -210,7 +210,7 @@ bool kvm_condition_valid(struct kvm_vcpu *vcpu)
  * @vcpu:	The VCPU pointer
  *
  * When exceptions occur while instructions are executed in Thumb IF-THEN
- * blocks, the ITSTATE field of the CPSR is not advanved (updated), so we have
+ * blocks, the ITSTATE field of the CPSR is not advanced (updated), so we have
  * to do this little bit of work manually. The fields map like this:
  *
  * IT[7:0] -> CPSR[26:25],CPSR[15:10]
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:48:46 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:48:46 +0200
Subject: [PATCH 0092/1529] Fix typo
Message-ID: <20160521114846.4126-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/kvm/guest.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index 9093ed0..9aca920 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -182,7 +182,7 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 /**
  * kvm_arm_copy_reg_indices - get indices of all registers.
  *
- * We do core registers right here, then we apppend coproc regs.
+ * We do core registers right here, then we append coproc regs.
  */
 int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
 {
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:49:32 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:49:32 +0200
Subject: [PATCH 0099/1529] Fix typo
Message-ID: <20160521114932.4505-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-integrator/pci_v3.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index 2565f0e..7ce4495 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -324,7 +324,7 @@ static u64 pre_mem_pci_sz;
  * configuration address space, you present the V3 with the following pattern
  * (which is very nearly a type 1 (except that the lower two bits are 00 and
  * not 01).   In order for this mapping to work you need to set up one of
- * the local to PCI aperatures to 16Mbytes in length translating to
+ * the local to PCI apertures to 16Mbytes in length translating to
  * PCI configuration space starting at 0x0000.0000.
  *
  * PCI configuration cycles look like this:
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:49:36 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:49:36 +0200
Subject: [PATCH 0100/1529] Fix typo
Message-ID: <20160521114936.4554-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-mmp/gplugd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
index c224119..4d30529 100644
--- a/arch/arm/mach-mmp/gplugd.c
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -157,7 +157,7 @@ static int gplugd_eth_init(void)
 struct pxa168_eth_platform_data gplugd_eth_platform_data = {
 	.port_number = 0,
 	.phy_addr    = 0,
-	.speed       = 0, /* Autonagotiation */
+	.speed       = 0, /* Autonegotiation */
 	.intf        = PHY_INTERFACE_MODE_RMII,
 	.init        = gplugd_eth_init,
 };
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:49:42 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:49:42 +0200
Subject: [PATCH 0101/1529] Fix typo
Message-ID: <20160521114942.4603-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-mmp/pxa168.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index 0f5f16f..e37dfd7 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -133,7 +133,7 @@ struct platform_device pxa168_device_gpio = {
 };
 
 struct resource pxa168_usb_host_resources[] = {
-	/* USB Host conroller register base */
+	/* USB Host controller register base */
 	[0] = {
 		.start	= PXA168_U2H_REGBASE + U2x_CAPREGS_OFFSET,
 		.end	= PXA168_U2H_REGBASE + USB_REG_RANGE,
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:49:48 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:49:48 +0200
Subject: [PATCH 0102/1529] Fix typo
Message-ID: <20160521114948.4664-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-omap1/ams-delta-fiq.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c b/arch/arm/mach-omap1/ams-delta-fiq.c
index d1f1209..acd6bf0 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -136,7 +136,7 @@ void __init ams_delta_init_fiq(void)
 		fiq_buffer[i] = 0;
 
 	/*
-	 * FIQ mode r9 always points to the fiq_buffer, becauses the FIQ isr
+	 * FIQ mode r9 always points to the fiq_buffer, because the FIQ isr
 	 * will run in an unpredictable context. The fiq_buffer is the FIQ isr's
 	 * only means of communication with the IRQ level and other kernel
 	 * context code.
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:49:24 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:49:24 +0200
Subject: [PATCH 0098/1529] Fix typo
Message-ID: <20160521114924.4453-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-imx/pm-imx5.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c
index 868781f..0d75e5f 100644
--- a/arch/arm/mach-imx/pm-imx5.c
+++ b/arch/arm/mach-imx/pm-imx5.c
@@ -51,7 +51,7 @@
  * This is also the lowest power state possible without affecting
  * non-cpu parts of the system.  For these reasons, imx5 should default
  * to always using this state for cpu idling.  The PM_SUSPEND_STANDBY also
- * uses this state and needs to take no action when registers remain confgiured
+ * uses this state and needs to take no action when registers remain configured
  * for this state.
  */
 #define IMX5_DEFAULT_CPU_IDLE_STATE WAIT_UNCLOCKED_POWER_OFF
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:50:13 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:50:13 +0200
Subject: [PATCH 0105/1529] Fix typo
Message-ID: <20160521115013.4816-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-omap2/mux34xx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/mux34xx.c b/arch/arm/mach-omap2/mux34xx.c
index be271f1..393e687 100644
--- a/arch/arm/mach-omap2/mux34xx.c
+++ b/arch/arm/mach-omap2/mux34xx.c
@@ -1266,7 +1266,7 @@ static struct omap_ball __initdata omap3_cus_ball[] = {
 #endif
 
 /*
- * Signals different on CBB package comapared to superset
+ * Signals different on CBB package compared to superset
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBB)
 static struct omap_mux __initdata omap3_cbb_subset[] = {
@@ -1597,7 +1597,7 @@ static struct omap_ball __initdata omap3_cbb_ball[] = {
 #endif
 
 /*
- * Signals different on 36XX CBP package comapared to 34XX CBC package
+ * Signals different on 36XX CBP package compared to 34XX CBC package
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBP)
 static struct omap_mux __initdata omap36xx_cbp_subset[] = {
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:50:19 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:50:19 +0200
Subject: [PATCH 0106/1529] Fix typo
Message-ID: <20160521115019.4865-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-omap2/omap4-common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 949696b..fb6fe26 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -61,7 +61,7 @@ static phys_addr_t dram_sync_paddr;
 static u32 dram_sync_size;
 
 /*
- * The OMAP4 bus structure contains asynchrnous bridges which can buffer
+ * The OMAP4 bus structure contains asynchronous bridges which can buffer
  * data writes from the MPU. These asynchronous bridges can be found on
  * paths between the MPU to EMIF, and the MPU to L3 interconnects.
  *
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:50:49 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:50:49 +0200
Subject: [PATCH 0111/1529] Fix typo
Message-ID: <20160521115049.5125-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-pxa/pcm027.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/pcm027.h b/arch/arm/mach-pxa/pcm027.h
index 047cdf2..7c884db 100644
--- a/arch/arm/mach-pxa/pcm027.h
+++ b/arch/arm/mach-pxa/pcm027.h
@@ -79,8 +79,8 @@
 /*
  * This CPU module needs a baseboard to work. After basic initializing
  * its own devices, it calls baseboard's init function.
- * TODO: Add your own basebaord init function and call it from
- * inside pcm027_init(). This example here is for the developmen board.
+ * TODO: Add your own baseboard init function and call it from
+ * inside pcm027_init(). This example here is for the development board.
  * Refer pcm990-baseboard.c
  */
 extern void pcm990_baseboard_init(void);
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:50:55 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:50:55 +0200
Subject: [PATCH 0112/1529] Fix typo
Message-ID: <20160521115055.5174-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-pxa/regs-u2d.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-pxa/regs-u2d.h b/arch/arm/mach-pxa/regs-u2d.h
index c15c0c5..d8febd6 100644
--- a/arch/arm/mach-pxa/regs-u2d.h
+++ b/arch/arm/mach-pxa/regs-u2d.h
@@ -159,7 +159,7 @@
 #define U2DMACSR_EORIRQEN	(1 << 28)	/* End of Receive Interrupt Enable (R/W) */
 #define U2DMACSR_EORJMPEN	(1 << 27)	/* Jump to next descriptor on EOR */
 #define U2DMACSR_EORSTOPEN	(1 << 26)	/* STOP on an EOR */
-#define U2DMACSR_RASIRQEN	(1 << 23)	/* Request After Cnannel Stopped Interrupt Enable */
+#define U2DMACSR_RASIRQEN	(1 << 23)	/* Request After Channel Stopped Interrupt Enable */
 #define U2DMACSR_MASKRUN	(1 << 22)	/* Mask Run */
 #define U2DMACSR_SCEMC		(3 << 18)	/* System Bus Split Completion Error Message Class */
 #define U2DMACSR_SCEMI		(0x1f << 13)	/* System Bus Split Completion Error Message Index */
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:51:02 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:51:02 +0200
Subject: [PATCH 0113/1529] Fix typo
Message-ID: <20160521115102.5231-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-pxa/trizeps4.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index ea78bc5..ce913fe 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -55,7 +55,7 @@
 
 /*	comment out the following line if you want to use the
  *	Standard UART from PXA for serial / irda transmission
- *	and acivate it if you have status leds connected */
+ *	and activate it if you have status leds connected */
 #define STATUS_LEDS_ON_STUART_PINS 1
 
 /*****************************************************************************
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:51:09 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:51:09 +0200
Subject: [PATCH 0114/1529] Fix typo
Message-ID: <20160521115109.5318-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-rockchip/pm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c
index bee8c80..309d672 100644
--- a/arch/arm/mach-rockchip/pm.c
+++ b/arch/arm/mach-rockchip/pm.c
@@ -280,7 +280,7 @@ static int rk3288_suspend_init(struct device_node *np)
 
 	rk3288_config_bootdata();
 
-	/* copy resume code and data to bootsram */
+	/* copy resume code and data to bootram */
 	memcpy(rk3288_bootram_base, rockchip_slp_cpu_resume,
 	       rk3288_bootram_sz);
 
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:48:59 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:48:59 +0200
Subject: [PATCH 0094/1529] Fix typo
Message-ID: <20160521114859.4225-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-dove/mpp.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-dove/mpp.h b/arch/arm/mach-dove/mpp.h
index fbec7c5..b219cf9 100644
--- a/arch/arm/mach-dove/mpp.h
+++ b/arch/arm/mach-dove/mpp.h
@@ -178,7 +178,7 @@ enum dove_mpp_grp_idx {
 /*
  * The MPP[52:57] functionality is encoded by 4 bits in different
  * registers. The _num field in this case encodes those bits in
- * correspodence with Table 135 of 88AP510 Functional specification
+ * correspondence with Table 135 of 88AP510 Functional specification
  */
 #define MPP_GRP_AU1_52_57_AU1		0x0
 #define MPP_GRP_AU1_52_57_AU1_GPIO57	0x2
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:48:52 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:48:52 +0200
Subject: [PATCH 0093/1529] Fix typo
Message-ID: <20160521114852.4176-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/kvm/reset.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c
index 0048b5a..4b5e802 100644
--- a/arch/arm/kvm/reset.c
+++ b/arch/arm/kvm/reset.c
@@ -52,7 +52,7 @@ static const struct kvm_irq_level cortexa_vtimer_irq = {
  * @vcpu: The VCPU pointer
  *
  * This function finds the right table above and sets the registers on the
- * virtual CPU struct to their architectually defined reset values.
+ * virtual CPU struct to their architecturally defined reset values.
  */
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 {
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:49:05 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:49:05 +0200
Subject: [PATCH 0095/1529] Fix typo
Message-ID: <20160521114905.4276-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-gemini/idle.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-gemini/idle.c b/arch/arm/mach-gemini/idle.c
index ddf8ec9..cb34fe4e 100644
--- a/arch/arm/mach-gemini/idle.c
+++ b/arch/arm/mach-gemini/idle.c
@@ -10,7 +10,7 @@ static void gemini_idle(void)
 {
 	/*
 	 * Because of broken hardware we have to enable interrupts or the CPU
-	 * will never wakeup... Acctualy it is not very good to enable
+	 * will never wakeup... Actually it is not very good to enable
 	 * interrupts first since scheduler can miss a tick, but there is
 	 * no other way around this. Platforms that needs it for power saving
 	 * should enable it in init code, since by default it is
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:49:12 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:49:12 +0200
Subject: [PATCH 0096/1529] Fix typo
Message-ID: <20160521114912.4331-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-imx/hardware.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h
index d737f95..026441c 100644
--- a/arch/arm/mach-imx/hardware.h
+++ b/arch/arm/mach-imx/hardware.h
@@ -121,7 +121,7 @@
 	.type = _type,							\
 }
 
-/* There's a off-by-one betweem the gpio bank number and the gpiochip */
+/* There's a off-by-one between the gpio bank number and the gpiochip */
 /* range e.g. GPIO_1_5 is gpio 5 under linux */
 #define IMX_GPIO_NR(bank, nr)		(((bank) - 1) * 32 + (nr))
 
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:49:18 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:49:18 +0200
Subject: [PATCH 0097/1529] Fix typo
Message-ID: <20160521114918.4399-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-imx/iomux-mx3.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/iomux-mx3.h b/arch/arm/mach-imx/iomux-mx3.h
index 2e4a0dd..9a11b71 100644
--- a/arch/arm/mach-imx/iomux-mx3.h
+++ b/arch/arm/mach-imx/iomux-mx3.h
@@ -129,7 +129,7 @@ int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
 void mxc_iomux_release_pin(unsigned int pin);
 /*
  * releases multiple pins
- * convenvient way to call the above function with tables
+ * convenient way to call the above function with tables
  */
 void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count);
 
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:49:56 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:49:56 +0200
Subject: [PATCH 0103/1529] Fix typo
Message-ID: <20160521114956.4714-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-omap1/include/mach/mtd-xip.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap1/include/mach/mtd-xip.h b/arch/arm/mach-omap1/include/mach/mtd-xip.h
index f82a8dc..d09b2bc 100644
--- a/arch/arm/mach-omap1/include/mach/mtd-xip.h
+++ b/arch/arm/mach-omap1/include/mach/mtd-xip.h
@@ -39,7 +39,7 @@ static inline unsigned long xip_omap_mpu_timer_read(int nr)
 #define xip_currtime()		(~xip_omap_mpu_timer_read(0))
 
 /*
- * It's permitted to do approxmation for xip_elapsed_since macro
+ * It's permitted to do approximation for xip_elapsed_since macro
  * (see linux/mtd/xip.h)
  */
 
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:50:25 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:50:25 +0200
Subject: [PATCH 0107/1529] Fix typo
Message-ID: <20160521115025.4915-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-omap2/omap_device.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index f7ff3b9..a7be05d 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -268,7 +268,7 @@ static int _omap_device_idle_hwmods(struct omap_device *od)
  * function returns a value different than the value the caller got
  * the last time it called this function.
  *
- * If any hwmods exist for the omap_device assoiated with @pdev,
+ * If any hwmods exist for the omap_device associated with @pdev,
  * return the context loss counter for that hwmod, otherwise return
  * zero.
  */
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:50:07 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:50:07 +0200
Subject: [PATCH 0104/1529] Fix typo
Message-ID: <20160521115007.4767-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-omap2/cm3xxx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c
index 187fa43..d91ae82 100644
--- a/arch/arm/mach-omap2/cm3xxx.c
+++ b/arch/arm/mach-omap2/cm3xxx.c
@@ -649,7 +649,7 @@ void omap3_cm_save_scratchpad_contents(u32 *ptr)
 	/*
 	 * As per erratum i671, ROM code does not respect the PER DPLL
 	 * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
-	 * Then,  in anycase, clear these bits to avoid extra latencies.
+	 * Then,  in any case, clear these bits to avoid extra latencies.
 	 */
 	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
 		~OMAP3430_AUTO_PERIPH_DPLL_MASK;
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:51:36 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:51:36 +0200
Subject: [PATCH 0118/1529] Fix typo
Message-ID: <20160521115136.5547-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-s3c24xx/mach-n30.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-s3c24xx/mach-n30.c b/arch/arm/mach-s3c24xx/mach-n30.c
index 171c1f1..070a0d0 100644
--- a/arch/arm/mach-s3c24xx/mach-n30.c
+++ b/arch/arm/mach-s3c24xx/mach-n30.c
@@ -522,7 +522,7 @@ static void __init n30_hwinit(void)
 	 *
 	 * The pull ups for H6/H7 are enabled on N30 but not on the
 	 * N35/PiN.  I suppose is useful for a budget model of the N30
-	 * with no bluetooh.  It doesn't hurt to have the pull ups
+	 * with no bluetooth.  It doesn't hurt to have the pull ups
 	 * enabled on the N35, so leave them enabled for all models.
 	 */
 	__raw_writel(0x0028aaaa, S3C2410_GPHCON);
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:51:43 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:51:43 +0200
Subject: [PATCH 0119/1529] Fix typo
Message-ID: <20160521115143.5598-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-s3c24xx/mach-osiris-dvs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-s3c24xx/mach-osiris-dvs.c b/arch/arm/mach-s3c24xx/mach-osiris-dvs.c
index ce2db23..262ab07 100644
--- a/arch/arm/mach-s3c24xx/mach-osiris-dvs.c
+++ b/arch/arm/mach-s3c24xx/mach-osiris-dvs.c
@@ -143,7 +143,7 @@ static int osiris_dvs_remove(struct platform_device *pdev)
 	return 0;
 }
 
-/* the CONFIG_PM block is so small, it isn't worth actaully compiling it
+/* the CONFIG_PM block is so small, it isn't worth actually compiling it
  * out if the configuration isn't set. */
 
 static int osiris_dvs_suspend(struct device *dev)
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:51:51 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:51:51 +0200
Subject: [PATCH 0120/1529] Fix typo
Message-ID: <20160521115151.5653-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-s3c64xx/include/mach/map.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-s3c64xx/include/mach/map.h
index f55ccb1..d51873e 100644
--- a/arch/arm/mach-s3c64xx/include/mach/map.h
+++ b/arch/arm/mach-s3c64xx/include/mach/map.h
@@ -99,7 +99,7 @@
 
 #define S3C64XX_PA_USB_HSPHY	(0x7C100000)
 
-/* compatibiltiy defines. */
+/* compatibility defines. */
 #define S3C_PA_TIMER		S3C64XX_PA_TIMER
 #define S3C_PA_HSMMC0		S3C64XX_PA_HSMMC0
 #define S3C_PA_HSMMC1		S3C64XX_PA_HSMMC1
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:52:01 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:52:01 +0200
Subject: [PATCH 0121/1529] Fix typo
Message-ID: <20160521115201.5707-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-tegra/platsmp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 75620ae..d9cd9d5 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -86,7 +86,7 @@ static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 * For warm boot CPU that was resumed from CPU hotplug, the
 	 * power will be resumed automatically after un-halting the
 	 * flow controller of the warm boot CPU. We need to wait for
-	 * the confirmaiton that the CPU is powered then removing
+	 * the confirmation that the CPU is powered then removing
 	 * the IO clamps.
 	 * For cold boot CPU, do not wait. After the cold boot CPU be
 	 * booted, it will run to tegra_secondary_init() and set
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:52:11 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:52:11 +0200
Subject: [PATCH 0122/1529] Fix typo
Message-ID: <20160521115211.5758-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-w90x900/include/mach/regs-ldm.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-w90x900/include/mach/regs-ldm.h b/arch/arm/mach-w90x900/include/mach/regs-ldm.h
index e9d480a..cb0bd95 100644
--- a/arch/arm/mach-w90x900/include/mach/regs-ldm.h
+++ b/arch/arm/mach-w90x900/include/mach/regs-ldm.h
@@ -229,7 +229,7 @@ enum LCM_DEV_CTRL_DE_POL {
 /* Hardware cursor control Register */
 #define REG_LCM_HC_CTRL			(0x6C)
 
-/* Hardware cursot tip point potison on va picture */
+/* Hardware cursor tip point potison on va picture */
 #define REG_LCM_HC_POS			(0x70)
 
 /* Hardware Cursor Window Buffer Control Register */
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:50:37 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:50:37 +0200
Subject: [PATCH 0109/1529] Fix typo
Message-ID: <20160521115037.5020-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-pxa/cm-x2xx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
index 7202022..c293d1b 100644
--- a/arch/arm/mach-pxa/cm-x2xx.c
+++ b/arch/arm/mach-pxa/cm-x2xx.c
@@ -385,7 +385,7 @@ static int __init cmx2xx_set_display(char *str)
    frame buffer.
    Indeed, pxafb parameters can be used istead, but CM-X2XX bootloader
    has limitied line length for kernel command line, and also it will
-   break compatibitlty with proprietary releases already in field.
+   break compatibility with proprietary releases already in field.
 */
 __setup("monitor=", cmx2xx_set_display);
 
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:50:32 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:50:32 +0200
Subject: [PATCH 0108/1529] Fix typo
Message-ID: <20160521115032.4966-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-omap2/sdrc.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/sdrc.h b/arch/arm/mach-omap2/sdrc.h
index 645a2a4..f115006 100644
--- a/arch/arm/mach-omap2/sdrc.h
+++ b/arch/arm/mach-omap2/sdrc.h
@@ -175,8 +175,8 @@ u32 omap2xxx_sdrc_reprogram(u32 level, u32 force);
  * don't adjust it down as your clock period increases the refresh interval
  * will not be met. Setting all parameters for complete worst case may work,
  * but may cut memory performance by 2x. Due to errata the DLLs need to be
- * unlocked and their value needs run time calibration.	A dynamic call is
- * need for that as no single right value exists acorss production samples.
+ * unlocked and their value needs run time calibration. A dynamic call is
+ * need for that as no single right value exists across production samples.
  *
  * Only the FULL speed values are given. Current code is such that rate
  * changes must be made at DPLLoutx2. The actual value adjustment for low
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:50:43 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:50:43 +0200
Subject: [PATCH 0110/1529] Fix typo
Message-ID: <20160521115043.5071-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-pxa/mioa701.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 38a96a1..08c6909 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -423,12 +423,12 @@ static struct platform_device docg3 = {
 /*
  * Suspend/Resume bootstrap management
  *
- * MIO A701 reboot sequence is highly ROM dependent. From the one dissassembled,
+ * MIO A701 reboot sequence is highly ROM dependent. From the one disassembled,
  * this sequence is as follows :
  *   - disables interrupts
  *   - initialize SDRAM (self refresh RAM into active RAM)
  *   - initialize GPIOs (depends on value at 0xa020b020)
- *   - initialize coprossessors
+ *   - initialize coprocessors
  *   - if edge detect on PWR_SCL(GPIO3), then proceed to cold start
  *   - or if value at 0xa020b000 not equal to 0x0f0f0f0f, proceed to cold start
  *   - else do a resume, ie. jump to addr 0xa0100000
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:51:16 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:51:16 +0200
Subject: [PATCH 0115/1529] Fix typo
Message-ID: <20160521115116.5387-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-rpc/include/mach/acornfb.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-rpc/include/mach/acornfb.h b/arch/arm/mach-rpc/include/mach/acornfb.h
index 395d762..f447d27 100644
--- a/arch/arm/mach-rpc/include/mach/acornfb.h
+++ b/arch/arm/mach-rpc/include/mach/acornfb.h
@@ -21,7 +21,7 @@ acornfb_valid_pixrate(struct fb_var_screeninfo *var)
 		return 0;
 
 	/*
-	 * Limits below are taken from RISC OS bandwidthlimit file
+	 * Limits below are taken from RISC OS bandwidth limit file
 	 */
 	if (current_par.using_vram) {
 		if (current_par.vram_half_sam == 2048)
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:51:23 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:51:23 +0200
Subject: [PATCH 0116/1529] Fix typo
Message-ID: <20160521115123.5447-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-s3c24xx/include/mach/regs-gpio.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h b/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h
index c6583cf..0d622f3 100644
--- a/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s3c24xx/include/mach/regs-gpio.h
@@ -520,7 +520,7 @@
 #define S3C24XX_EXTINT1	   S3C24XX_GPIOREG2(0x8C)
 #define S3C24XX_EXTINT2	   S3C24XX_GPIOREG2(0x90)
 
-/* interrupt filtering conrrol for EINT16..EINT23 */
+/* interrupt filtering control for EINT16..EINT23 */
 #define S3C2410_EINFLT0	   S3C2410_GPIOREG(0x94)
 #define S3C2410_EINFLT1	   S3C2410_GPIOREG(0x98)
 #define S3C2410_EINFLT2	   S3C2410_GPIOREG(0x9C)
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:51:29 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:51:29 +0200
Subject: [PATCH 0117/1529] Fix typo
Message-ID: <20160521115129.5498-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/mach-s3c24xx/iotiming-s3c2410.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-s3c24xx/iotiming-s3c2410.c b/arch/arm/mach-s3c24xx/iotiming-s3c2410.c
index 4cd13ab..65e5f9c 100644
--- a/arch/arm/mach-s3c24xx/iotiming-s3c2410.c
+++ b/arch/arm/mach-s3c24xx/iotiming-s3c2410.c
@@ -423,7 +423,7 @@ void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg,
  * @timings: The IO timing information to fill out.
  *
  * Calculate the @timings timing information from the current frequency
- * information in @cfg, and the new frequency configur
+ * information in @cfg, and the new frequency configuration
  * through all the IO banks, reading the state and then updating @iot
  * as necessary.
  *
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:52:20 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:52:20 +0200
Subject: [PATCH 0123/1529] Fix typo
Message-ID: <20160521115220.5810-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/plat-samsung/include/plat/cpu-freq-core.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/plat-samsung/include/plat/cpu-freq-core.h b/arch/arm/plat-samsung/include/plat/cpu-freq-core.h
index 317c523..37cf20e 100644
--- a/arch/arm/plat-samsung/include/plat/cpu-freq-core.h
+++ b/arch/arm/plat-samsung/include/plat/cpu-freq-core.h
@@ -39,7 +39,7 @@ struct s3c2410_iobank_timing {
 	unsigned int	tacs;
 	unsigned int	tcos;
 	unsigned int	tacc;
-	unsigned int	tcoh;		/* nCS hold afrer nOE/nWE */
+	unsigned int	tcoh;		/* nCS hold after nOE/nWE */
 	unsigned int	tcah;		/* Address hold after nCS */
 	unsigned char	nwait_en;	/* nWait enabled for bank. */
 };
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:52:29 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:52:29 +0200
Subject: [PATCH 0124/1529] Fix typo
Message-ID: <20160521115229.5862-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/plat-samsung/include/plat/fb-s3c2410.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/plat-samsung/include/plat/fb-s3c2410.h b/arch/arm/plat-samsung/include/plat/fb-s3c2410.h
index 4e5d958..1f2972a 100644
--- a/arch/arm/plat-samsung/include/plat/fb-s3c2410.h
+++ b/arch/arm/plat-samsung/include/plat/fb-s3c2410.h
@@ -48,7 +48,7 @@ struct s3c2410fb_display {
 
 struct s3c2410fb_mach_info {
 
-	struct s3c2410fb_display *displays;	/* attached diplays info */
+	struct s3c2410fb_display *displays;	/* attached displays info */
 	unsigned num_displays;			/* number of defined displays */
 	unsigned default_display;
 
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:52:39 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:52:39 +0200
Subject: [PATCH 0125/1529] Fix typo
Message-ID: <20160521115239.5917-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/plat-samsung/include/plat/gpio-cfg.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
index b5294ef..21391fa 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
@@ -35,7 +35,7 @@ struct samsung_gpio_chip;
  * struct samsung_gpio_cfg GPIO configuration
  * @cfg_eint: Configuration setting when used for external interrupt source
  * @get_pull: Read the current pull configuration for the GPIO
- * @set_pull: Set the current pull configuraiton for the GPIO
+ * @set_pull: Set the current pull configuration for the GPIO
  * @set_config: Set the current configuration for the GPIO
  * @get_config: Read the current configuration for the GPIO
  *
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:52:45 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:52:45 +0200
Subject: [PATCH 0126/1529] Fix typo
Message-ID: <20160521115245.5966-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/plat-samsung/pm-check.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/plat-samsung/pm-check.c b/arch/arm/plat-samsung/pm-check.c
index 70f2f69..d635163 100644
--- a/arch/arm/plat-samsung/pm-check.c
+++ b/arch/arm/plat-samsung/pm-check.c
@@ -5,7 +5,7 @@
  *	http://armlinux.simtec.co.uk
  *	Ben Dooks <ben at simtec.co.uk>
  *
- * S3C Power Mangament - suspend/resume memory corruptiuon check.
+ * S3C Power Mangament - suspend/resume memory corruption check.
  *
  * 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
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:52:52 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:52:52 +0200
Subject: [PATCH 0127/1529] Fix typo
Message-ID: <20160521115252.6023-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/plat-samsung/watchdog-reset.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/plat-samsung/watchdog-reset.c b/arch/arm/plat-samsung/watchdog-reset.c
index 2ecb50be..307d8ad 100644
--- a/arch/arm/plat-samsung/watchdog-reset.c
+++ b/arch/arm/plat-samsung/watchdog-reset.c
@@ -3,7 +3,7 @@
  * Copyright (c) 2008 Simtec Electronics
  *	Ben Dooks <ben at simtec.co.uk>
  *
- * Coyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.com>
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.com>
  *
  * Watchdog reset support for Samsung SoCs.
  *
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:53:14 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:53:14 +0200
Subject: [PATCH 0130/1529] Fix typo
Message-ID: <20160521115314.6184-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm64/include/asm/kvm_arm.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 2cdb6b5..4b5c977 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -178,7 +178,7 @@
 /* Hyp System Trap Register */
 #define HSTR_EL2_T(x)	(1 << x)
 
-/* Hyp Coproccessor Trap Register Shifts */
+/* Hyp Coprocessor Trap Register Shifts */
 #define CPTR_EL2_TFP_SHIFT 10
 
 /* Hyp Coprocessor Trap Register */
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:53:22 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:53:22 +0200
Subject: [PATCH 0131/1529] Fix typo
Message-ID: <20160521115322.6241-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm64/kvm/guest.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 32fad75..3f9e157 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -211,7 +211,7 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 /**
  * kvm_arm_copy_reg_indices - get indices of all registers.
  *
- * We do core registers right here, then we apppend system regs.
+ * We do core registers right here, then we append system regs.
  */
 int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
 {
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:53:30 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:53:30 +0200
Subject: [PATCH 0132/1529] Fix typo
Message-ID: <20160521115330.6299-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm64/kvm/reset.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index b1ad730..7be24f2 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -98,7 +98,7 @@ int kvm_arch_dev_ioctl_check_extension(long ext)
  * @vcpu: The VCPU pointer
  *
  * This function finds the right table above and sets the registers on
- * the virtual CPU struct to their architectually defined reset
+ * the virtual CPU struct to their architecturally defined reset
  * values.
  */
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
-- 
2.8.2.534.g1f66975



From linux at armlinux.org.uk  Sat May 21 04:55:56 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Sat, 21 May 2016 12:55:56 +0100
Subject: [PATCH 0085/1529] Fix typo
In-Reply-To: <20160521114759.3760-1-andrea.gelmini@gelma.net>
References: <20160521114759.3760-1-andrea.gelmini@gelma.net>
Message-ID: <20160521115556.GV19428@n2100.arm.linux.org.uk>

On Sat, May 21, 2016 at 01:47:59PM +0200, Andrea Gelmini wrote:
> Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
> ---
>  arch/arm/include/asm/ucontext.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h
> index 14749ae..b4d2d0f 100644
> --- a/arch/arm/include/asm/ucontext.h
> +++ b/arch/arm/include/asm/ucontext.h
> @@ -8,7 +8,7 @@
>   * ucontext now has room for all registers which need to be saved and
>   * restored.  Coprocessor registers are stored in uc_regspace.  Each
>   * coprocessor's saved state should start with a documented 32-bit magic
> - * number, followed by a 32-bit word giving the coproccesor's saved size.
> + * number, followed by a 32-bit word giving the coprocessor saved size.

The original is fine, and I'd say is more correct.

"coprocessor's saved size" "saved size of the coprocessor".  The
apostrophe here is the possessive apostrophe.

http://www.grammarbook.com/punctuation/apostro.asp

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From ivo.g.dimitrov.75 at gmail.com  Sat May 21 05:00:38 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Sat, 21 May 2016 15:00:38 +0300
Subject: [PATCH 0108/1529] Fix typo
In-Reply-To: <20160521115032.4966-1-andrea.gelmini@gelma.net>
References: <20160521115032.4966-1-andrea.gelmini@gelma.net>
Message-ID: <57404DE6.7040506@gmail.com>



On 21.05.2016 14:50, Andrea Gelmini wrote:
> Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
> ---
>   arch/arm/mach-omap2/sdrc.h | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/sdrc.h b/arch/arm/mach-omap2/sdrc.h
> index 645a2a4..f115006 100644
> --- a/arch/arm/mach-omap2/sdrc.h
> +++ b/arch/arm/mach-omap2/sdrc.h
> @@ -175,8 +175,8 @@ u32 omap2xxx_sdrc_reprogram(u32 level, u32 force);
>    * don't adjust it down as your clock period increases the refresh interval
>    * will not be met. Setting all parameters for complete worst case may work,
>    * but may cut memory performance by 2x. Due to errata the DLLs need to be
> - * unlocked and their value needs run time calibration.	A dynamic call is
> - * need for that as no single right value exists acorss production samples.
> + * unlocked and their value needs run time calibration. A dynamic call is
> + * need for that as no single right value exists across production samples.

needed?

>    *
>    * Only the FULL speed values are given. Current code is such that rate
>    * changes must be made at DPLLoutx2. The actual value adjustment for low
>


From andrea.gelmini at gelma.net  Sat May 21 04:53:00 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:53:00 +0200
Subject: [PATCH 0128/1529] Fix typo
Message-ID: <20160521115300.6081-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/probes/kprobes/opt-arm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c
index bcdecc2..b165881 100644
--- a/arch/arm/probes/kprobes/opt-arm.c
+++ b/arch/arm/probes/kprobes/opt-arm.c
@@ -320,7 +320,7 @@ void __kprobes arch_optimize_kprobes(struct list_head *oplist)
 
 		/*
 		 * Make it a conditional branch if replaced insn
-		 * is consitional
+		 * is conditional
 		 */
 		insn = (__mem_to_opcode_arm(
 			  op->optinsn.copied_insn[0]) & 0xf0000000) |
-- 
2.8.2.534.g1f66975



From andrea.gelmini at gelma.net  Sat May 21 04:53:07 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 13:53:07 +0200
Subject: [PATCH 0129/1529] Fix typo
Message-ID: <20160521115307.6132-1-andrea.gelmini@gelma.net>

Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
---
 arch/arm/xen/mm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
index c5f9a9e..483da5e 100644
--- a/arch/arm/xen/mm.c
+++ b/arch/arm/xen/mm.c
@@ -150,7 +150,7 @@ bool xen_arch_need_swiotlb(struct device *dev,
 	 *	- The Linux page refers to foreign memory
 	 *	- The device doesn't support coherent DMA request
 	 *
-	 * The Linux page may be spanned acrros multiple Xen page, although
+	 * The Linux page may be spanned across multiple Xen page, although
 	 * it's not possible to have a mix of local and foreign Xen page.
 	 * Furthermore, range_straddles_page_boundary is already checking
 	 * if buffer is physically contiguous in the host RAM.
-- 
2.8.2.534.g1f66975



From heiko at sntech.de  Sat May 21 05:14:27 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 21 May 2016 14:14:27 +0200
Subject: [PATCH 0114/1529] Fix typo
In-Reply-To: <20160521115109.5318-1-andrea.gelmini@gelma.net>
References: <20160521115109.5318-1-andrea.gelmini@gelma.net>
Message-ID: <1785036.RoNATgRSre@phil>

Hi Andrea,

Am Samstag, 21. Mai 2016, 13:51:09 schrieb Andrea Gelmini:
> Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>

A series of 1529 patches? That's a bit extreme.

Also in future please use a sane subject line and additionally see comment 
below making the patch not valid.

> ---
>  arch/arm/mach-rockchip/pm.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c
> index bee8c80..309d672 100644
> --- a/arch/arm/mach-rockchip/pm.c
> +++ b/arch/arm/mach-rockchip/pm.c
> @@ -280,7 +280,7 @@ static int rk3288_suspend_init(struct device_node *np)
> 
>  	rk3288_config_bootdata();
> 
> -	/* copy resume code and data to bootsram */
> +	/* copy resume code and data to bootram */

this is _not_ a typo, it is sram not regular ram

>  	memcpy(rk3288_bootram_base, rockchip_slp_cpu_resume,
>  	       rk3288_bootram_sz);



From andrea.gelmini at gelma.net  Sat May 21 05:21:57 2016
From: andrea.gelmini at gelma.net (Andrea Gelmini)
Date: Sat, 21 May 2016 12:21:57 +0000
Subject: [PATCH 0085/1529] Fix typo
In-Reply-To: <20160521115556.GV19428@n2100.arm.linux.org.uk>
References: <20160521114759.3760-1-andrea.gelmini@gelma.net>
 <20160521115556.GV19428@n2100.arm.linux.org.uk>
Message-ID: <20160521122157.GA6289@li61-168.members.linode.com>

On Sat, May 21, 2016 at 12:55:56PM +0100, Russell King - ARM Linux wrote:
> On Sat, May 21, 2016 at 01:47:59PM +0200, Andrea Gelmini wrote:
> > Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
> > ---
> >  arch/arm/include/asm/ucontext.h | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h
> > index 14749ae..b4d2d0f 100644
> > --- a/arch/arm/include/asm/ucontext.h
> > +++ b/arch/arm/include/asm/ucontext.h
> > @@ -8,7 +8,7 @@
> >   * ucontext now has room for all registers which need to be saved and
> >   * restored.  Coprocessor registers are stored in uc_regspace.  Each
> >   * coprocessor's saved state should start with a documented 32-bit magic
> > - * number, followed by a 32-bit word giving the coproccesor's saved size.
> > + * number, followed by a 32-bit word giving the coprocessor saved size.
> 
> The original is fine, and I'd say is more correct.

My point was about the spelling: coproccesor (double C, single S).

I don't resend a new version of the patch.
My interest is notify it, don't care to have commit in kernel for such
little thing.
I guess is easier if you fix it with next batch of your patches.

Bye,
Andrea


From linux at armlinux.org.uk  Sat May 21 05:49:45 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Sat, 21 May 2016 13:49:45 +0100
Subject: [PATCH 0085/1529] Fix typo
In-Reply-To: <20160521122157.GA6289@li61-168.members.linode.com>
References: <20160521114759.3760-1-andrea.gelmini@gelma.net>
 <20160521115556.GV19428@n2100.arm.linux.org.uk>
 <20160521122157.GA6289@li61-168.members.linode.com>
Message-ID: <20160521124945.GW19428@n2100.arm.linux.org.uk>

On Sat, May 21, 2016 at 12:21:57PM +0000, Andrea Gelmini wrote:
> On Sat, May 21, 2016 at 12:55:56PM +0100, Russell King - ARM Linux wrote:
> > On Sat, May 21, 2016 at 01:47:59PM +0200, Andrea Gelmini wrote:
> > > Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
> > > ---
> > >  arch/arm/include/asm/ucontext.h | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h
> > > index 14749ae..b4d2d0f 100644
> > > --- a/arch/arm/include/asm/ucontext.h
> > > +++ b/arch/arm/include/asm/ucontext.h
> > > @@ -8,7 +8,7 @@
> > >   * ucontext now has room for all registers which need to be saved and
> > >   * restored.  Coprocessor registers are stored in uc_regspace.  Each
> > >   * coprocessor's saved state should start with a documented 32-bit magic
> > > - * number, followed by a 32-bit word giving the coproccesor's saved size.
> > > + * number, followed by a 32-bit word giving the coprocessor saved size.
> > 
> > The original is fine, and I'd say is more correct.
> 
> My point was about the spelling: coproccesor (double C, single S).

I didn't spot that, sorry.

> I don't resend a new version of the patch.
> My interest is notify it, don't care to have commit in kernel for such
> little thing.
> I guess is easier if you fix it with next batch of your patches.

Well, I also don't care enough to fix the spelling either.  I also
don't see the point of applying a patch which results in it still
being wrong.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From sstabellini at kernel.org  Sat May 21 06:19:07 2016
From: sstabellini at kernel.org (Stefano Stabellini)
Date: Sat, 21 May 2016 14:19:07 +0100 (BST)
Subject: [PATCH 0129/1529] Fix typo
In-Reply-To: <20160521115307.6132-1-andrea.gelmini@gelma.net>
References: <20160521115307.6132-1-andrea.gelmini@gelma.net>
Message-ID: <alpine.DEB.2.10.1605211418190.2958@sstabellini-ThinkPad-X260>

On Sat, 21 May 2016, Andrea Gelmini wrote:
> Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
> ---
>  arch/arm/xen/mm.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
> index c5f9a9e..483da5e 100644
> --- a/arch/arm/xen/mm.c
> +++ b/arch/arm/xen/mm.c
> @@ -150,7 +150,7 @@ bool xen_arch_need_swiotlb(struct device *dev,
>  	 *	- The Linux page refers to foreign memory
>  	 *	- The device doesn't support coherent DMA request
>  	 *
> -	 * The Linux page may be spanned acrros multiple Xen page, although
> +	 * The Linux page may be spanned across multiple Xen page, although

Since you are at it, please also fix the lacking plural. It should be:

The Linux page may be spanned across multiple Xen pages, although


From heiko at sntech.de  Sat May 21 06:40:52 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 21 May 2016 15:40:52 +0200
Subject: [PATCH v2 3/5] ARM: dts: rockchip: move rk3288 io-domain nodes to
 the grf
In-Reply-To: <1459432126-6395-4-git-send-email-heiko@sntech.de>
References: <1459432126-6395-1-git-send-email-heiko@sntech.de>
 <1459432126-6395-4-git-send-email-heiko@sntech.de>
Message-ID: <3043390.x2mOUff8Ni@phil>

Am Donnerstag, 31. M?rz 2016, 15:48:44 schrieb Heiko Stuebner:
> io-voltage control is actually part of the grf, so move the node under the
> newly available grf simple-mfd.
> 
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>

applied for 4.8, but adapted slightly to have the core io-domain nodes centrally in the rk3288.dtsi:

----- 8< -----
From: Heiko Stuebner <heiko at sntech.de>
Date: Sat, 21 May 2016 01:36:17 +0200
Subject: [PATCH v2.1 3/5] ARM: dts: rockchip: move rk3288 io-domain nodes to the grf

io-voltage control is actually part of the grf, so move the node under the
newly available grf simple-mfd.

To minimize duplicate code, the core node and compatible property
gets placed in the core rk3288.dtsi while the individual boards
now only need to enable it and add the necessary supply properties.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 arch/arm/boot/dts/rk3288-firefly.dtsi   | 31 +++++++++++++++----------------
 arch/arm/boot/dts/rk3288-miqi.dts       | 26 +++++++++++++-------------
 arch/arm/boot/dts/rk3288-popmetal.dts   | 31 +++++++++++++++----------------
 arch/arm/boot/dts/rk3288-rock2-som.dtsi | 31 +++++++++++++++----------------
 arch/arm/boot/dts/rk3288-veyron.dtsi    | 25 ++++++++++++-------------
 arch/arm/boot/dts/rk3288.dtsi           |  5 +++++
 6 files changed, 75 insertions(+), 74 deletions(-)

diff --git a/arch/arm/boot/dts/rk3288-firefly.dtsi b/arch/arm/boot/dts/rk3288-firefly.dtsi
index d6cf9ad..114c90fb 100644
--- a/arch/arm/boot/dts/rk3288-firefly.dtsi
+++ b/arch/arm/boot/dts/rk3288-firefly.dtsi
@@ -64,22 +64,6 @@
 		clock-output-names = "ext_gmac";
 	};
 
-	io_domains: io-domains {
-		compatible = "rockchip,rk3288-io-voltage-domain";
-		rockchip,grf = <&grf>;
-
-		audio-supply = <&vcca_33>;
-		bb-supply = <&vcc_io>;
-		dvp-supply = <&dovdd_1v8>;
-		flash0-supply = <&vcc_flash>;
-		flash1-supply = <&vcc_lan>;
-		gpio30-supply = <&vcc_io>;
-		gpio1830-supply = <&vcc_io>;
-		lcdc-supply = <&vcc_io>;
-		sdcard-supply = <&vccio_sd>;
-		wifi-supply = <&vccio_wl>;
-	};
-
 	ir: ir-receiver {
 		compatible = "gpio-ir-receiver";
 		pinctrl-names = "default";
@@ -397,6 +381,21 @@
 	status = "okay";
 };
 
+&io_domains {
+	status = "okay";
+
+	audio-supply = <&vcca_33>;
+	bb-supply = <&vcc_io>;
+	dvp-supply = <&dovdd_1v8>;
+	flash0-supply = <&vcc_flash>;
+	flash1-supply = <&vcc_lan>;
+	gpio30-supply = <&vcc_io>;
+	gpio1830-supply = <&vcc_io>;
+	lcdc-supply = <&vcc_io>;
+	sdcard-supply = <&vccio_sd>;
+	wifi-supply = <&vccio_wl>;
+};
+
 &pinctrl {
 	pcfg_output_high: pcfg-output-high {
 		output-high;
diff --git a/arch/arm/boot/dts/rk3288-miqi.dts b/arch/arm/boot/dts/rk3288-miqi.dts
index 8643103..2448842 100644
--- a/arch/arm/boot/dts/rk3288-miqi.dts
+++ b/arch/arm/boot/dts/rk3288-miqi.dts
@@ -64,19 +64,6 @@
 		clock-output-names = "ext_gmac";
 	};
 
-	io_domains: io-domains {
-		compatible = "rockchip,rk3288-io-voltage-domain";
-
-		audio-supply = <&vcca_33>;
-		flash0-supply = <&vcc_flash>;
-		flash1-supply = <&vcc_lan>;
-		gpio30-supply = <&vcc_io>;
-		gpio1830-supply = <&vcc_io>;
-		lcdc-supply = <&vcc_io>;
-		sdcard-supply = <&vccio_sd>;
-		wifi-supply = <&vcc_18>;
-	};
-
 	leds {
 		compatible = "gpio-leds";
 
@@ -321,6 +308,19 @@
 	status = "okay";
 };
 
+&io_domains {
+	status = "okay";
+
+	audio-supply = <&vcca_33>;
+	flash0-supply = <&vcc_flash>;
+	flash1-supply = <&vcc_lan>;
+	gpio30-supply = <&vcc_io>;
+	gpio1830-supply = <&vcc_io>;
+	lcdc-supply = <&vcc_io>;
+	sdcard-supply = <&vccio_sd>;
+	wifi-supply = <&vcc_18>;
+};
+
 &pinctrl {
 	pcfg_output_high: pcfg-output-high {
 		output-high;
diff --git a/arch/arm/boot/dts/rk3288-popmetal.dts b/arch/arm/boot/dts/rk3288-popmetal.dts
index 720717b..dda8d25 100644
--- a/arch/arm/boot/dts/rk3288-popmetal.dts
+++ b/arch/arm/boot/dts/rk3288-popmetal.dts
@@ -77,22 +77,6 @@
 		};
 	};
 
-	io_domains: io-domains {
-		compatible = "rockchip,rk3288-io-voltage-domain";
-		rockchip,grf = <&grf>;
-
-		audio-supply = <&vcca_33>;
-		bb-supply = <&vcc_io>;
-		dvp-supply = <&vcc18_dvp>;
-		flash0-supply = <&vcc_flash>;
-		flash1-supply = <&vcc_lan>;
-		gpio30-supply = <&vcc_io>;
-		gpio1830-supply = <&vcc_io>;
-		lcdc-supply = <&vcc_io>;
-		sdcard-supply = <&vccio_sd>;
-		wifi-supply = <&vccio_wl>;
-	};
-
 	ir: ir-receiver {
 		compatible = "gpio-ir-receiver";
 		gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
@@ -437,6 +421,21 @@
 	status = "okay";
 };
 
+&io_domains {
+	status = "okay";
+
+	audio-supply = <&vcca_33>;
+	bb-supply = <&vcc_io>;
+	dvp-supply = <&vcc18_dvp>;
+	flash0-supply = <&vcc_flash>;
+	flash1-supply = <&vcc_lan>;
+	gpio30-supply = <&vcc_io>;
+	gpio1830-supply = <&vcc_io>;
+	lcdc-supply = <&vcc_io>;
+	sdcard-supply = <&vccio_sd>;
+	wifi-supply = <&vccio_wl>;
+};
+
 &pinctrl {
 	ak8963 {
 		comp_int: comp-int {
diff --git a/arch/arm/boot/dts/rk3288-rock2-som.dtsi b/arch/arm/boot/dts/rk3288-rock2-som.dtsi
index e1ee9f9..bb1f01e 100644
--- a/arch/arm/boot/dts/rk3288-rock2-som.dtsi
+++ b/arch/arm/boot/dts/rk3288-rock2-som.dtsi
@@ -61,22 +61,6 @@
 		clock-output-names = "ext_gmac";
 	};
 
-	io_domains: io-domains {
-		compatible = "rockchip,rk3288-io-voltage-domain";
-		rockchip,grf = <&grf>;
-
-		audio-supply = <&vcc_io>;
-		bb-supply = <&vcc_io>;
-		dvp-supply = <&vcc_18>;
-		flash0-supply = <&vcc_flash>;
-		flash1-supply = <&vccio_pmu>;
-		gpio30-supply = <&vccio_pmu>;
-		gpio1830 = <&vcc_io>;
-		lcdc-supply = <&vcc_io>;
-		sdcard-supply = <&vccio_sd>;
-		wifi-supply = <&vcc_18>;
-	};
-
 	vcc_flash: flash-regulator {
 		compatible = "regulator-fixed";
 		regulator-name = "vcc_sys";
@@ -259,6 +243,21 @@
 	};
 };
 
+&io_domains {
+	status = "okay";
+
+	audio-supply = <&vcc_io>;
+	bb-supply = <&vcc_io>;
+	dvp-supply = <&vcc_18>;
+	flash0-supply = <&vcc_flash>;
+	flash1-supply = <&vccio_pmu>;
+	gpio30-supply = <&vccio_pmu>;
+	gpio1830 = <&vcc_io>;
+	lcdc-supply = <&vcc_io>;
+	sdcard-supply = <&vccio_sd>;
+	wifi-supply = <&vcc_18>;
+};
+
 &pinctrl {
 	pcfg_output_high: pcfg-output-high {
 		output-high;
diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
index 5e4c690..3dd2cca 100644
--- a/arch/arm/boot/dts/rk3288-veyron.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
@@ -83,19 +83,6 @@
 		reset-gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>;
 	};
 
-	io_domains: io-domains {
-		compatible = "rockchip,rk3288-io-voltage-domain";
-		rockchip,grf = <&grf>;
-
-		bb-supply = <&vcc33_io>;
-		dvp-supply = <&vcc_18>;
-		flash0-supply = <&vcc18_flashio>;
-		gpio1830-supply = <&vcc33_io>;
-		gpio30-supply = <&vcc33_io>;
-		lcdc-supply = <&vcc33_lcd>;
-		wifi-supply = <&vcc18_wl>;
-	};
-
 	sdio_pwrseq: sdio-pwrseq {
 		compatible = "mmc-pwrseq-simple";
 		clocks = <&rk808 RK808_CLKOUT1>;
@@ -355,6 +342,18 @@
 	i2c-scl-rising-time-ns = <1000>;
 };
 
+&io_domains {
+	status = "okay";
+
+	bb-supply = <&vcc33_io>;
+	dvp-supply = <&vcc_18>;
+	flash0-supply = <&vcc18_flashio>;
+	gpio1830-supply = <&vcc33_io>;
+	gpio30-supply = <&vcc33_io>;
+	lcdc-supply = <&vcc33_lcd>;
+	wifi-supply = <&vcc18_wl>;
+};
+
 &pwm1 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 3b44ef3..7fa932f 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -826,6 +826,11 @@
 			#phy-cells = <0>;
 			status = "disabled";
 		};
+
+		io_domains: io-domains {
+			compatible = "rockchip,rk3288-io-voltage-domain";
+			status = "disabled";
+		};
 	};
 
 	wdt: watchdog at ff800000 {
-- 
2.6.4

----- 8< -----



From heiko at sntech.de  Sat May 21 06:55:06 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 21 May 2016 15:55:06 +0200
Subject: [PATCH v2 4/5] arm64: dts: rockchip: make rk3368 grf syscons
 simple-mfds as well
In-Reply-To: <1459432126-6395-5-git-send-email-heiko@sntech.de>
References: <1459432126-6395-1-git-send-email-heiko@sntech.de>
 <1459432126-6395-5-git-send-email-heiko@sntech.de>
Message-ID: <2597247.kfueRAYi3v@phil>

Am Donnerstag, 31. M?rz 2016, 15:48:45 schrieb Heiko Stuebner:
> The general register files do contain a lot of separate functions and
> while some really are only registers with a lot of different 1-bit
> settings, there are also a lot of them containing some bigger function
> blocks. To be able to define these as sub-devices, make them simple-mfds.
> 
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> Tested-by: David Wu <david.wu at rock-chips.com>

applied for 4.8


From sstabellini at kernel.org  Sat May 21 07:09:12 2016
From: sstabellini at kernel.org (Stefano Stabellini)
Date: Sat, 21 May 2016 15:09:12 +0100 (BST)
Subject: [PATCH 0129/1529] Fix typo
In-Reply-To: <alpine.DEB.2.10.1605211418190.2958@sstabellini-ThinkPad-X260>
References: <20160521115307.6132-1-andrea.gelmini@gelma.net>
 <alpine.DEB.2.10.1605211418190.2958@sstabellini-ThinkPad-X260>
Message-ID: <alpine.DEB.2.10.1605211508460.2958@sstabellini-ThinkPad-X260>

On Sat, 21 May 2016, Stefano Stabellini wrote:
> On Sat, 21 May 2016, Andrea Gelmini wrote:
> > Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
> > ---
> >  arch/arm/xen/mm.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
> > index c5f9a9e..483da5e 100644
> > --- a/arch/arm/xen/mm.c
> > +++ b/arch/arm/xen/mm.c
> > @@ -150,7 +150,7 @@ bool xen_arch_need_swiotlb(struct device *dev,
> >  	 *	- The Linux page refers to foreign memory
> >  	 *	- The device doesn't support coherent DMA request
> >  	 *
> > -	 * The Linux page may be spanned acrros multiple Xen page, although
> > +	 * The Linux page may be spanned across multiple Xen page, although
> 
> Since you are at it, please also fix the lacking plural. It should be:
> 
> The Linux page may be spanned across multiple Xen pages, although

But given that this is patch 129 of 1529:

Acked-by: Stefano Stabellini <sstabellini at kernel.org>


From fengguang.wu at intel.com  Sat May 21 07:46:38 2016
From: fengguang.wu at intel.com (kbuild test robot)
Date: Sat, 21 May 2016 22:46:38 +0800
Subject: [arm-platforms:kvm-arm64/vgic-fixes-4.7 5/6]
 arch/arm64/kvm/sys_regs.c:144:3: error: 'struct sys_reg_params' has no
 member named 'retval'
Message-ID: <201605212236.l8y8YZJr%fengguang.wu@intel.com>

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git kvm-arm64/vgic-fixes-4.7
head:   1ff896af0190c4244ceab0658407da5095b40076
commit: 3320e0e2679738f8f46310412410786f379ad095 [5/6] arm64: KVM: Make ICC_SRE_EL1 access return the configured SRE value
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        git checkout 3320e0e2679738f8f46310412410786f379ad095
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

Note: the arm-platforms/kvm-arm64/vgic-fixes-4.7 HEAD 1ff896af0190c4244ceab0658407da5095b40076 builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   arch/arm64/kvm/sys_regs.c: In function 'access_gic_sre':
>> arch/arm64/kvm/sys_regs.c:144:3: error: 'struct sys_reg_params' has no member named 'retval'
     p->retval = vcpu->arch.vgic_cpu.vgic_v3.vgic_sre;
      ^

vim +144 arch/arm64/kvm/sys_regs.c

   138				   struct sys_reg_params *p,
   139				   const struct sys_reg_desc *r)
   140	{
   141		if (p->is_write)
   142			return ignore_write(vcpu, p);
   143	
 > 144		p->retval = vcpu->arch.vgic_cpu.vgic_v3.vgic_sre;
   145		return true;
   146	}
   147	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 22498 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160521/cb12f761/attachment-0001.obj>

From bert at a20.net  Sat May 21 08:47:05 2016
From: bert at a20.net (Bert Lindner)
Date: Sat, 21 May 2016 17:47:05 +0200
Subject: 4.5.0 on sun7i-a20-olinuxino-lime2: libphy: PHY stmmac-0:ffffffff
 not found (regression from rc7)
In-Reply-To: <573EE8B4.1050701@arm.com>
References: <56E9413D.9010902@a20.net> <56E945FF.6080005@arm.com>
 <56E94CF4.2060607@arm.com> <56E95B57.1090100@suse.de>
 <56E9776F.3070102@a20.net> <56E99B0C.2070609@arm.com>
 <56E9F2B8.1030605@a20.net> <20160317075202.16b14ed6@arm.com>
 <CAHsu+b-t_r93XKLJTUcin6xjhOrFVn3_60vwHkbRt3iHK28CbA@mail.gmail.com>
 <573EC33D.2010209@arm.com> <573EC77A.2000800@st.com>
 <CAHsu+b9BrqBLdCpsPpetc_4_EaFVGBdDHtoeeCqqzsCG3Wpsig@mail.gmail.com>
 <573EE8B4.1050701@arm.com>
Message-ID: <574082F9.7010702@a20.net>

Hi,

On 2016-05-20 12:36, Marc Zyngier wrote:
> On 20/05/16 11:30, Andre Heider wrote:
>> Hi,
>>
>> On Fri, May 20, 2016 at 10:14 AM, Giuseppe CAVALLARO
>> <peppe.cavallaro at st.com> wrote:
>>> On 5/20/2016 9:56 AM, Marc Zyngier wrote:
>>>>
>>>> On 20/05/16 06:44, Andre Heider wrote:
>>>>>
>>>>> Giuseppe, Alexandre, et al.,
>>>>>
>>>>> On Thu, Mar 17, 2016 at 8:52 AM, Marc Zyngier <marc.zyngier at arm.com>
>>>>> wrote:
>>>>>>
>>>>>> On Thu, 17 Mar 2016 00:56:40 +0100
>>>>>> Bert Lindner <bert at a20.net> wrote:
>>>>>>>
>>>>>>> On 2016-03-16 18:42, Marc Zyngier wrote:
>>>>>>>>
>>>>>>>> On 16/03/16 15:10, Bert Lindner wrote:
>>>>>>>>>
>>>>>>>>> On 2016-03-16 14:10, Andreas F?rber wrote:
>>>>>>>>>>
>>>>>>>>>> Am 16.03.2016 um 13:09 schrieb Robin Murphy:
>>>>>>>>>>>
>>>>>>>>>>> On 16/03/16 11:39, Marc Zyngier wrote:
>>>>>>>>>>>>
>>>>>>>>>>>> On 16/03/16 11:19, Bert Lindner wrote:
>>>>>
>>>>> ...
>>>>>>>>>>>>>
>>>>>>>>>>>>> For the board sun7i-a20-olinuxino-lime2, there seems to be a
>>>>>>>>>>>>> problem
>>>>>>>>>>>>> with the eth0 PHY in mainline kernel 4.5.0 that developed since
>>>>>>>>>>>>> 4.5.0-rc7. Ethernet does not work, although eth0 is reported:
>>>>>
>>>>> ...
>>>>>>>>>>>>>
>>>>>>>>>>>>> [    9.767125] NET: Registered protocol family 10
>>>>>>>>>>>>> [   10.357405] libphy: PHY stmmac-0:ffffffff not found
>>>>>>>>>>>>> [   10.362382] eth0: Could not attach to PHY
>>>>>>>>>>>>> [   10.366557] stmmac_open: Cannot attach to PHY (error: -19)
>>>>>
>>>>> ...
>>>>>>>>>>
>>>>>>>>>> v4 fixes for 4.5 are here:
>>>>>>>>>>
>>>>>>>>>> https://patchwork.ozlabs.org/patch/598195/ (revert)
>>>>>>>>>> https://patchwork.ozlabs.org/patch/598196/
>>>>>
>>>>> ...
>>>>>>>>
>>>>>>>> Good to know, thanks. Could you also give the potential fix a go (as
>>>>>>>> mentioned by Andreas)? Just to make sure that whatever gets merged
>>>>>>>> next
>>>>>>>> will actually fix the issue.
>>>>>>>
>>>>>>>
>>>>>>> Yes sure, it took a while because I had to travel. Confirmed, the
>>>>>>> v4-for-4.5 fix works well for me, on sun7i-a20-olinuxino-lime2:
>>>>>>>
>>>>>>> root at lime2-079f:~# cat /proc/version
>>>>>>> Linux version 4.5.0-598195-598196-v4 (root at lime2-079f) (gcc version
>>>>>>> 4.9.1 (Ubuntu/Linaro 4.9.1-16ubuntu6) ) #1 SMP Wed Mar 16 16:44:22 UTC
>>>>>>> 2016
>>>>>>>
>>>>>>> dmesg:
>>>>>>> [    8.245273] NET: Registered protocol family 10
>>>>>>> [    9.297406]  RX IPC Checksum Offload disabled
>>>>>>> [    9.297460]  No MAC Management Counters available
>>>>>>> [    9.297951] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
>>>>>>> [   16.285658] sun7i-dwmac 1c50000.ethernet eth0: Link is Up -
>>>>>>> 1Gbps/Full - flow control rx/tx
>>>>>>> [   16.285798] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
>>>>>>>
>>>>>>> The board is connected to my laptop rather than to a switch, so that
>>>>>>> might be where the flow control message comes from (not sure). Anyway
>>>>>>> ethernet works.
>>>>>>
>>>>>>
>>>>>> Cool, many thanks for taking the time to test and report.
>>>>>>
>>>>>> Hopefully Giuseppe will get this merged quickly enough in mainline, and
>>>>>> it should then trickle into a 4.5-stable release (cc-ing stable on
>>>>>> these patches would probably be a good idea, BTW).
>>>>>
>>>>>
>>>>> stmmac is broken on at least Lime2, BananaPi and Cubieboard2 since
>>>>> v4.5 [0], including all five stable releases :(
>>>>
>>>>
>>>> All the A20 platforms are dead, actually.
>>>>
>>>>> The v4.5 patches quoted above are already +4 weeks old, could we
>>>>> please get them into stable?
>>>>
>>>>
>>>> For that, the maintainer would have needed to CC stable, which he
>>>> didn't. I'd expect someone who cares to send these patches to stable.
>>>> It'd be better if the maintainer would do it himself though.
>>>
>>>
>>> sure, I can send the patches to stable (sorry if I missed to add
>>> stable ML on CC).
>>>
>>> Andre, I have not clear if the train of patches actually fix the
>>> issue or if you need my support to fix something else. In that case
>>> I need some input for debugging (e.g. kernel log).
>>
>> Bert already confirmed that those two patches fixes stmmac on his
>> Lime2, so I assume that it fixes the issue for all A20 platforms.
>>
>>> let me know, is it enough to re-send the patches only?
>>
>> Just a resend with cc:stable :)
>
> Not quite. Please read Documentation/stable_kernel_rules.txt, and the
> section that concerns networking patches (and then consult
> Documentation/networking/netdev-FAQ.txt which has all the details).

FWIW, recent 4.6-rc series and 4.6.0 have worked fine for me and the 
lime2. Had not tried 4.5.x again.

Best,

	-bert




From heiko at sntech.de  Sat May 21 09:52:07 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 21 May 2016 18:52:07 +0200
Subject: [PATCH v2 5/5] arm64: dts: rockchip: add rk3368-r88 iodomains
In-Reply-To: <1459432126-6395-6-git-send-email-heiko@sntech.de>
References: <1459432126-6395-1-git-send-email-heiko@sntech.de>
 <1459432126-6395-6-git-send-email-heiko@sntech.de>
Message-ID: <1656719.1xsq0kaqYf@phil>

Am Donnerstag, 31. M?rz 2016, 15:48:46 schrieb Heiko Stuebner:
> Add the supply-links according to the R88 schematics.
> 
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>

going to rework this one a bit and make it part of a new series.


From wens at csie.org  Sat May 21 09:43:48 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Sun, 22 May 2016 00:43:48 +0800
Subject: [PATCH 07/16] clk: sunxi-ng: Add phase clock support
In-Reply-To: <1462737711-10017-8-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-8-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v661dvdPKj9DWL7LWGgiDCEk7G-a_7jv5gb+KBMoWbR8Lg@mail.gmail.com>

Hi,

On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Add support for the clocks in the CCU that introduce a phase shift from
> their parent clock.
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile    |   1 +
>  drivers/clk/sunxi-ng/ccu_phase.c | 126 +++++++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_phase.h |  50 ++++++++++++++++
>  3 files changed, 177 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_phase.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_phase.h
>
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index f20c6c8f217c..a47a3bbdf285 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -5,3 +5,4 @@ obj-y += ccu_div_table.o
>  obj-y += ccu_fixed_factor.o
>  obj-y += ccu_gate.o
>  obj-y += ccu_mux.o
> +obj-y += ccu_phase.o
> diff --git a/drivers/clk/sunxi-ng/ccu_phase.c b/drivers/clk/sunxi-ng/ccu_phase.c
> new file mode 100644
> index 000000000000..cf0f0b20115c
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_phase.c
> @@ -0,0 +1,126 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/spinlock.h>
> +
> +#include "ccu_phase.h"
> +
> +static int ccu_phase_get_phase(struct clk_hw *hw)
> +{
> +       struct ccu_phase *phase = hw_to_ccu_phase(hw);
> +       struct clk_hw *parent, *pparent;
> +       unsigned int parent_rate, pparent_rate;
> +       u16 step, parent_div;
> +       u32 reg;
> +       u8 delay;
> +
> +       reg = readl(phase->common.base + phase->common.reg);
> +       delay = (reg >> phase->shift);
> +       delay &= (1 << phase->width) - 1;
> +
> +       if (!delay)
> +               return 180;

I don't understand why a "no delay" would be 180 phase. More on this below.

> +
> +       /* Get our parent clock, it's the one that can adjust its rate */
> +       parent = clk_hw_get_parent(hw);
> +       if (!parent)
> +               return -EINVAL;
> +
> +       /* And its rate */
> +       parent_rate = clk_hw_get_rate(parent);
> +       if (!parent_rate)
> +               return -EINVAL;
> +
> +       /* Now, get our parent's parent (most likely some PLL) */
> +       pparent = clk_hw_get_parent(parent);
> +       if (!pparent)
> +               return -EINVAL;
> +
> +       /* And its rate */
> +       pparent_rate = clk_hw_get_rate(pparent);
> +       if (!pparent_rate)
> +               return -EINVAL;
> +
> +       /* Get our parent clock divider */
> +       parent_div = pparent_rate / parent_rate;
> +
> +       step = DIV_ROUND_CLOSEST(360, parent_div);
> +       return delay * step;
> +}
> +
> +static int ccu_phase_set_phase(struct clk_hw *hw, int degrees)
> +{
> +       struct ccu_phase *phase = hw_to_ccu_phase(hw);
> +       struct clk_hw *parent, *pparent;
> +       unsigned int parent_rate, pparent_rate;

grandparent(_rate) would be easier to understand.

> +       unsigned long flags;
> +       u32 reg;
> +       u8 delay;
> +
> +       /* Get our parent clock, it's the one that can adjust its rate */
> +       parent = clk_hw_get_parent(hw);
> +       if (!parent)
> +               return -EINVAL;
> +
> +       /* And its rate */
> +       parent_rate = clk_hw_get_rate(parent);
> +       if (!parent_rate)
> +               return -EINVAL;
> +
> +       /* Now, get our parent's parent (most likely some PLL) */
> +       pparent = clk_hw_get_parent(parent);
> +       if (!pparent)
> +               return -EINVAL;
> +
> +       /* And its rate */
> +       pparent_rate = clk_hw_get_rate(pparent);
> +       if (!pparent_rate)
> +               return -EINVAL;
> +
> +       if (degrees != 180) {
> +               u16 step, parent_div;
> +
> +               /* Get our parent divider */
> +               parent_div = pparent_rate / parent_rate;
> +
> +               /*
> +                * We can only outphase the clocks by multiple of the
> +                * PLL's period.
> +                *
> +                * Since our parent clock is only a divider, and the
> +                * formula to get the outphasing in degrees is deg =
> +                * 360 * delta / period
> +                *
> +                * If we simplify this formula, we can see that the
> +                * only thing that we're concerned about is the number
> +                * of period we want to outphase our clock from, and
> +                * the divider set by our parent clock.
> +                */
> +               step = DIV_ROUND_CLOSEST(360, parent_div);
> +               delay = DIV_ROUND_CLOSEST(degrees, step);

Doesn't this mean some delay values are impossible to set?

For instance, for PLL = 600 MHz and this clock = 50 MHz, div would be 12,
and a step would be 30 degrees. This means we can't ask for a delay of 6,
which is 180 degrees.

For PLL = 600 MHz, clock = 100 MHz, div would be 6, and a step is 60
degrees. Therefor we can't ask for a delay of 3.

Does this make sense?

> +       } else {
> +               delay = 0;
> +       }
> +
> +       spin_lock_irqsave(phase->common.lock, flags);
> +       reg = readl(phase->common.base + phase->common.reg);
> +       reg &= ~GENMASK(phase->width + phase->shift, phase->shift);
> +       writel(reg | (delay << phase->shift),
> +              phase->common.base + phase->common.reg);
> +       spin_unlock_irqrestore(phase->common.lock, flags);
> +
> +       return 0;
> +}
> +
> +const struct clk_ops ccu_phase_ops = {
> +       .get_phase      = ccu_phase_get_phase,
> +       .set_phase      = ccu_phase_set_phase,
> +};
> diff --git a/drivers/clk/sunxi-ng/ccu_phase.h b/drivers/clk/sunxi-ng/ccu_phase.h
> new file mode 100644
> index 000000000000..e28b4e58a819
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_phase.h
> @@ -0,0 +1,50 @@
> +/*
> + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _CCU_PHASE_H_
> +#define _CCU_PHASE_H_
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_common.h"
> +
> +struct ccu_phase {
> +       u8                      shift;
> +       u8                      width;

Not sure why you used struct ccu_factor in the divider table clock,
but separate fields directly in ccu_phase here.

Regards
ChenYu

> +
> +       struct ccu_common       common;
> +};
> +
> +#define SUNXI_CCU_PHASE(_struct, _name, _parent, _reg, _shift, _width, _flags) \
> +       struct ccu_phase _struct = {                                    \
> +               .shift  = _shift,                                       \
> +               .width  = _width,                                       \
> +               .common = {                                             \
> +                       .reg            = _reg,                         \
> +                       .hw.init        = SUNXI_HW_INIT(_name,          \
> +                                                       _parent,        \
> +                                                       &ccu_phase_ops, \
> +                                                       _flags),        \
> +               }                                                       \
> +       }
> +
> +static inline struct ccu_phase *hw_to_ccu_phase(struct clk_hw *hw)
> +{
> +       struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +       return container_of(common, struct ccu_phase, common);
> +}
> +
> +extern const struct clk_ops ccu_phase_ops;
> +
> +#endif /* _CCU_PHASE_H_ */
> --
> 2.8.2
>


From wens at csie.org  Sat May 21 09:18:26 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Sun, 22 May 2016 00:18:26 +0800
Subject: [PATCH 05/16] clk: sunxi-ng: Add mux clock support
In-Reply-To: <1462737711-10017-6-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-6-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v66FShuDB_YH37x+VymjrpD+Q9OA2D=b3=MyaLkfFySvmQ@mail.gmail.com>

Hi,

On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Some clocks in the Allwinner SoCs clocks unit are just muxes.
>
> However, those muxes might also be found in some other complicated clocks
> that would benefit from the code in there to deal with "advanced" features,
> like pre-dividers.
>
> Introduce a set of helpers to reduce the code duplication in such cases.
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile  |   1 +
>  drivers/clk/sunxi-ng/ccu_mux.c | 187 +++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_mux.h |  80 +++++++++++++++++-
>  3 files changed, 264 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_mux.c
>
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index fc01127b3b45..aa5c411ff8ea 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -3,3 +3,4 @@ obj-y += ccu_reset.o
>
>  obj-y += ccu_fixed_factor.o
>  obj-y += ccu_gate.o
> +obj-y += ccu_mux.o
> diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
> new file mode 100644
> index 000000000000..cb54a8931de3
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_mux.c
> @@ -0,0 +1,187 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_gate.h"
> +#include "ccu_mux.h"
> +
> +void ccu_mux_helper_adjust_parent_for_prediv(struct ccu_common *common,
> +                                            struct ccu_mux_internal *cm,
> +                                            int parent_index,
> +                                            unsigned long *parent_rate)
> +{
> +       u8 prediv = 1;
> +       u32 reg;
> +
> +       if (!((common->features & CCU_FEATURE_FIXED_PREDIV) ||
> +             (common->features & CCU_FEATURE_VARIABLE_PREDIV)))
> +               return;
> +
> +       reg = readl(common->base + common->reg);
> +       if (parent_index < 0) {
> +               parent_index = reg >> cm->shift;
> +               parent_index &= (1 << cm->width) - 1;
> +       }
> +
> +       if (common->features & CCU_FEATURE_FIXED_PREDIV)
> +               if (parent_index == cm->fixed_prediv.index)
> +                       prediv = cm->fixed_prediv.div;
> +
> +       if (common->features & CCU_FEATURE_VARIABLE_PREDIV)
> +               if (parent_index == cm->variable_prediv.index) {
> +                       u8 div;
> +
> +                       div = reg >> cm->variable_prediv.shift;
> +                       div &= (1 << cm->variable_prediv.width) - 1;
> +                       prediv = div + 1;
> +               }
> +
> +       *parent_rate = *parent_rate / prediv;
> +}
> +
> +int ccu_mux_helper_determine_rate(struct ccu_common *common,
> +                                 struct ccu_mux_internal *cm,
> +                                 struct clk_rate_request *req,
> +                                 unsigned long (*round)(struct ccu_mux_internal *,
> +                                                        unsigned long,
> +                                                        unsigned long,
> +                                                        void *),
> +                                 void *data)
> +{
> +       unsigned long best_parent_rate = 0, best_rate = 0;
> +       struct clk_hw *best_parent, *hw = &common->hw;
> +       unsigned int i;
> +
> +       for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
> +               unsigned long tmp_rate, parent_rate;
> +               struct clk_hw *parent;
> +
> +               parent = clk_hw_get_parent_by_index(hw, i);
> +               if (!parent)
> +                       continue;
> +
> +               parent_rate = clk_hw_get_rate(parent);

Using clk-mux.c as a reference, you should honor CLK_SET_RATE_PARENT here.

> +               ccu_mux_helper_adjust_parent_for_prediv(common, cm, i,
> +                                                       &parent_rate);

ccu_mux_helper_adjust_parent_for_prediv can modify parent_rate. You
should probably save a copy...

> +
> +               tmp_rate = round(cm, clk_hw_get_rate(parent), req->rate, data);
> +               if (tmp_rate == req->rate) {
> +                       best_parent = parent;
> +                       best_parent_rate = parent_rate;

... to assign to best_parent_rate. The returned best_parent_rate is used
to change the parent clock rate. This happens if CLK_SET_RATE_PARENT is set.
The CCF doesn't know about our predivs, so you should pass back the original
rate, not the one after the prediv.

I suppose you didn't run into problems as CLK_SET_RATE_PARENT was not used
anywhere?

Regards
ChenYu

> +                       best_rate = tmp_rate;
> +                       goto out;
> +               }
> +
> +               if ((req->rate - tmp_rate) < (req->rate - best_rate)) {
> +                       best_rate = tmp_rate;
> +                       best_parent_rate = parent_rate;
> +                       best_parent = parent;
> +               }
> +       }
> +
> +       if (best_rate == 0)
> +               return -EINVAL;
> +
> +out:
> +       req->best_parent_hw = best_parent;
> +       req->best_parent_rate = best_parent_rate;
> +       req->rate = best_rate;
> +       return 0;
> +}
> +
> +u8 ccu_mux_helper_get_parent(struct ccu_common *common,
> +                            struct ccu_mux_internal *cm)
> +{
> +       u32 reg;
> +       u8 parent;
> +
> +       reg = readl(common->base + common->reg);
> +       parent = reg >> cm->shift;
> +       parent &= (1 << cm->width) - 1;
> +
> +       return parent;
> +}
> +
> +int ccu_mux_helper_set_parent(struct ccu_common *common,
> +                             struct ccu_mux_internal *cm,
> +                             u8 index)
> +{
> +       unsigned long flags;
> +       u32 reg;
> +
> +       spin_lock_irqsave(common->lock, flags);
> +
> +       reg = readl(common->base + common->reg);
> +       reg &= ~GENMASK(cm->width + cm->shift, cm->shift);
> +       writel(reg | (index << cm->shift), common->base + common->reg);
> +
> +       spin_unlock_irqrestore(common->lock, flags);
> +
> +       return 0;
> +}
> +
> +static void ccu_mux_disable(struct clk_hw *hw)
> +{
> +       struct ccu_mux *cm = hw_to_ccu_mux(hw);
> +
> +       return ccu_gate_helper_disable(&cm->common, cm->enable);
> +}
> +
> +static int ccu_mux_enable(struct clk_hw *hw)
> +{
> +       struct ccu_mux *cm = hw_to_ccu_mux(hw);
> +
> +       return ccu_gate_helper_enable(&cm->common, cm->enable);
> +}
> +
> +static int ccu_mux_is_enabled(struct clk_hw *hw)
> +{
> +       struct ccu_mux *cm = hw_to_ccu_mux(hw);
> +
> +       return ccu_gate_helper_is_enabled(&cm->common, cm->enable);
> +}
> +
> +static u8 ccu_mux_get_parent(struct clk_hw *hw)
> +{
> +       struct ccu_mux *cm = hw_to_ccu_mux(hw);
> +
> +       return ccu_mux_helper_get_parent(&cm->common, &cm->mux);
> +}
> +
> +static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       struct ccu_mux *cm = hw_to_ccu_mux(hw);
> +
> +       return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index);
> +}
> +
> +static unsigned long ccu_mux_recalc_rate(struct clk_hw *hw,
> +                                        unsigned long parent_rate)
> +{
> +       struct ccu_mux *cm = hw_to_ccu_mux(hw);
> +
> +       ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1,
> +                                               &parent_rate);
> +
> +       return parent_rate;
> +}
> +
> +const struct clk_ops ccu_mux_ops = {
> +       .disable        = ccu_mux_disable,
> +       .enable         = ccu_mux_enable,
> +       .is_enabled     = ccu_mux_is_enabled,
> +
> +       .get_parent     = ccu_mux_get_parent,
> +       .set_parent     = ccu_mux_set_parent,
> +
> +       .determine_rate = __clk_mux_determine_rate,
> +       .recalc_rate    = ccu_mux_recalc_rate,
> +};
> diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
> index 17cedad4e433..c85707f80f68 100644
> --- a/drivers/clk/sunxi-ng/ccu_mux.h
> +++ b/drivers/clk/sunxi-ng/ccu_mux.h
> @@ -1,20 +1,92 @@
>  #ifndef _CCU_MUX_H_
>  #define _CCU_MUX_H_
>
> -#include "common.h"
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_common.h"
>
>  struct ccu_mux_internal {
>         u8      shift;
>         u8      width;
>
> -       u8      *map;
> +       struct {
> +               u8      index;
> +               u8      div;
> +       } fixed_prediv;
> +
> +       struct {
> +               u8      index;
> +               u8      shift;
> +               u8      width;
> +       } variable_prediv;
>  };
>
> -#define SUNXI_CLK_MUX(_shift, _width, _map)    \
> +#define SUNXI_CLK_MUX(_shift, _width)  \
>         {                                       \
> -               .map    = _map,                 \
>                 .shift  = _shift,               \
>                 .width  = _width,               \
>         }
>
> +struct ccu_mux {
> +       u16                     reg;
> +       u32                     enable;
> +
> +       struct ccu_mux_internal mux;
> +       struct ccu_common       common;
> +};
> +
> +#define SUNXI_CCU_MUX(_struct, _name, _parents, _reg, _shift, _width, _flags) \
> +       struct ccu_mux _struct = {                                      \
> +               .mux    = SUNXI_CLK_MUX(_shift, _width),                \
> +               .common = {                                             \
> +                       .reg            = _reg,                         \
> +                       .hw.init        = SUNXI_HW_INIT_PARENTS(_name,  \
> +                                                               _parents, \
> +                                                               &ccu_mux_ops, \
> +                                                               _flags), \
> +               }                                                       \
> +       }
> +
> +#define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg,                \
> +                               _shift, _width, _gate, _flags)          \
> +       struct ccu_mux _struct = {                                      \
> +               .enable = _gate,                                        \
> +               .mux    = SUNXI_CLK_MUX(_shift, _width),                \
> +               .common = {                                             \
> +                       .reg            = _reg,                         \
> +                       .features       = CCU_FEATURE_GATE,             \
> +                       .hw.init        = SUNXI_HW_INIT_PARENTS(_name,  \
> +                                                               _parents, \
> +                                                               &ccu_mux_ops, \
> +                                                               _flags), \
> +               }                                                       \
> +       }
> +
> +static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
> +{
> +       struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +       return container_of(common, struct ccu_mux, common);
> +}
> +
> +extern const struct clk_ops ccu_mux_ops;
> +
> +void ccu_mux_helper_adjust_parent_for_prediv(struct ccu_common *common,
> +                                            struct ccu_mux_internal *cm,
> +                                            int parent_index,
> +                                            unsigned long *parent_rate);
> +int ccu_mux_helper_determine_rate(struct ccu_common *common,
> +                                 struct ccu_mux_internal *cm,
> +                                 struct clk_rate_request *req,
> +                                 unsigned long (*round)(struct ccu_mux_internal *,
> +                                                        unsigned long,
> +                                                        unsigned long,
> +                                                        void *),
> +                                 void *data);
> +u8 ccu_mux_helper_get_parent(struct ccu_common *common,
> +                            struct ccu_mux_internal *cm);
> +int ccu_mux_helper_set_parent(struct ccu_common *common,
> +                             struct ccu_mux_internal *cm,
> +                             u8 index);
> +
>  #endif /* _CCU_MUX_H_ */
> --
> 2.8.2
>


From wens at csie.org  Sat May 21 09:30:19 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Sun, 22 May 2016 00:30:19 +0800
Subject: [PATCH 06/16] clk: sunxi-ng: Add divider table clock
In-Reply-To: <1462737711-10017-7-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-7-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v66eMndSwAGs-Nmx6f1ct+JdQMh7JLdVa4geP2YYb4tsog@mail.gmail.com>

Hi,

On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Add support for clocks based on a divider tables.
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile        |   1 +
>  drivers/clk/sunxi-ng/ccu_div_table.c | 117 +++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_div_table.h |  75 ++++++++++++++++++++++
>  3 files changed, 193 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_div_table.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_div_table.h
>
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index aa5c411ff8ea..f20c6c8f217c 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -1,6 +1,7 @@
>  obj-y += ccu_common.o
>  obj-y += ccu_reset.o
>
> +obj-y += ccu_div_table.o
>  obj-y += ccu_fixed_factor.o
>  obj-y += ccu_gate.o
>  obj-y += ccu_mux.o
> diff --git a/drivers/clk/sunxi-ng/ccu_div_table.c b/drivers/clk/sunxi-ng/ccu_div_table.c
> new file mode 100644
> index 000000000000..cbfff0bd47e3
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_div_table.c
> @@ -0,0 +1,117 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_div_table.h"
> +#include "ccu_gate.h"
> +
> +static void ccu_div_table_find_best(unsigned long parent, unsigned long rate,
> +                                   struct ccu_div_table *ct,
> +                                   unsigned int *index)
> +{
> +       unsigned long best_rate = 0;
> +       unsigned int best_index = 0;
> +       unsigned int _index;
> +
> +       for (_index = 0; _index <= ct->num_divs; _index++) {
> +               unsigned long tmp_rate = parent / ct->table[_index];
> +
> +               if (tmp_rate > rate)
> +                       continue;
> +
> +               if ((rate - tmp_rate) < (rate - best_rate)) {
> +                       best_rate = tmp_rate;
> +                       best_index = _index;
> +               }
> +       }
> +
> +       *index = best_index;
> +}

You can drop this function and use the CCF helpers (mentioned below)
instead.

> +
> +static void ccu_div_table_disable(struct clk_hw *hw)
> +{
> +       struct ccu_div_table *ct = hw_to_ccu_div_table(hw);
> +
> +       return ccu_gate_helper_disable(&ct->common, ct->enable);
> +}
> +
> +static int ccu_div_table_enable(struct clk_hw *hw)
> +{
> +       struct ccu_div_table *ct = hw_to_ccu_div_table(hw);
> +
> +       return ccu_gate_helper_enable(&ct->common, ct->enable);
> +}
> +
> +static int ccu_div_table_is_enabled(struct clk_hw *hw)
> +{
> +       struct ccu_div_table *ct = hw_to_ccu_div_table(hw);
> +
> +       return ccu_gate_helper_is_enabled(&ct->common, ct->enable);
> +}
> +
> +static unsigned long ccu_div_table_recalc_rate(struct clk_hw *hw,
> +                                              unsigned long parent_rate)
> +{
> +       struct ccu_div_table *ct = hw_to_ccu_div_table(hw);
> +       unsigned long div;
> +       u32 reg;
> +
> +       reg = readl(ct->common.base + ct->common.reg);
> +
> +       div = reg >> ct->div.shift;
> +       div &= (1 << ct->div.width) - 1;
> +
> +       return parent_rate / ct->table[div];

CCF provides divider_recalc_rate().

> +}
> +
> +static long ccu_div_table_round_rate(struct clk_hw *hw, unsigned long rate,
> +                                    unsigned long *parent_rate)
> +{
> +       struct ccu_div_table *ct = hw_to_ccu_div_table(hw);
> +       unsigned int index;
> +
> +       ccu_div_table_find_best(*parent_rate, rate,
> +                               ct, &index);
> +
> +       return *parent_rate / ct->table[index];

CCF provides divider_round_rate().

> +}
> +
> +static int ccu_div_table_set_rate(struct clk_hw *hw, unsigned long rate,
> +                                 unsigned long parent_rate)
> +{
> +       struct ccu_div_table *ct = hw_to_ccu_div_table(hw);
> +       unsigned long flags;
> +       unsigned int index;
> +       u32 reg;
> +
> +       ccu_div_table_find_best(parent_rate, rate, ct, &index);

CCF provides divider_get_val().

> +
> +       spin_lock_irqsave(ct->common.lock, flags);
> +
> +       reg = readl(ct->common.base + ct->common.reg);
> +       reg &= ~GENMASK(ct->div.width + ct->div.shift, ct->div.shift);
> +       writel(reg | ((ct->table[index]) << ct->div.shift),
> +              ct->common.base + ct->common.reg);
> +
> +       spin_unlock_irqrestore(ct->common.lock, flags);
> +
> +       return 0;
> +}
> +
> +const struct clk_ops ccu_div_table_ops = {
> +       .disable        = ccu_div_table_disable,
> +       .enable         = ccu_div_table_enable,
> +       .is_enabled     = ccu_div_table_is_enabled,
> +
> +       .recalc_rate    = ccu_div_table_recalc_rate,
> +       .round_rate     = ccu_div_table_round_rate,
> +       .set_rate       = ccu_div_table_set_rate,
> +};
> diff --git a/drivers/clk/sunxi-ng/ccu_div_table.h b/drivers/clk/sunxi-ng/ccu_div_table.h
> new file mode 100644
> index 000000000000..bd7da49087ed
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_div_table.h
> @@ -0,0 +1,75 @@
> +/*
> + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _CCU_DIV_TABLE_H_
> +#define _CCU_DIV_TABLE_H_
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_factor.h"
> +
> +struct ccu_div_table {
> +       u32                     enable;
> +
> +       u8                      *table;

I suggest using struct clk_div_table instead, to be able to use the
CCF helpers.

> +       int                     num_divs;

This field won't be needed then, but you should add a divider flags
field.

Regards
ChenYu

> +
> +       struct ccu_factor       div;
> +       struct ccu_common       common;
> +};
> +
> +#define SUNXI_CCU_DIV_TABLE(_struct, _name, _parent, _reg,             \
> +                           _shift, _width,                             \
> +                           _table, _flags)                             \
> +       struct ccu_div_table _struct = {                                \
> +               .table          = _table,                               \
> +               .num_divs       = ARRAY_SIZE(_table),                   \
> +               .div            = SUNXI_CLK_FACTOR(_shift, _width),     \
> +               .common = {                                             \
> +                       .reg            = _reg,                         \
> +                       .hw.init        = SUNXI_HW_INIT(_name,          \
> +                                                       _parent,        \
> +                                                       &ccu_div_table_ops, \
> +                                                       _flags),        \
> +               }                                                       \
> +       }
> +
> +#define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg,   \
> +                                     _shift, _width,                   \
> +                                     _table, _gate, _flags)            \
> +       struct ccu_div_table _struct = {                                \
> +               .enable         = _gate,                                \
> +               .table          = _table,                               \
> +               .num_divs       = ARRAY_SIZE(_table),                   \
> +               .div            = SUNXI_CLK_FACTOR(_shift, _width),     \
> +               .common = {                                             \
> +                       .reg            = _reg,                         \
> +                       .features       = CCU_FEATURE_GATE,             \
> +                       .hw.init        = SUNXI_HW_INIT(_name,          \
> +                                                       _parent,        \
> +                                                       &ccu_div_table_ops, \
> +                                                       _flags),        \
> +               }                                                       \
> +       }
> +
> +static inline struct ccu_div_table *hw_to_ccu_div_table(struct clk_hw *hw)
> +{
> +       struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +       return container_of(common, struct ccu_div_table, common);
> +}
> +
> +extern const struct clk_ops ccu_div_table_ops;
> +
> +#endif /* _CCU_DIV_H_ */
> --
> 2.8.2
>


From f.fainelli at gmail.com  Sat May 21 10:09:07 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Sat, 21 May 2016 10:09:07 -0700
Subject: [PATCH v2 1/6] power: Introduce Broadcom kona reset driver
In-Reply-To: <1463002582-6875-2-git-send-email-chris.brand@broadcom.com>
References: <1463002582-6875-1-git-send-email-chris.brand@broadcom.com>
 <1463002582-6875-2-git-send-email-chris.brand@broadcom.com>
Message-ID: <57409633.8060605@gmail.com>

Le 11/05/2016 14:36, Chris Brand a ?crit :
> This driver supports reset on both BCM21664 and BCM23550.
> Code is being moved from arch/arm/mach-bcm/board_bcm21664.c
> 
> Signed-off-by: Chris Brand <chris.brand at broadcom.com>

Sebastian, Dmitry, I know we are in the merge window, let me know if you
would want me to take this patch and the 5 others in the next arm-soc
pull request, or if you prefer to take this one in your own tree.

Thanks!
-- 
Florian


From wens at csie.org  Sat May 21 10:09:09 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Sun, 22 May 2016 01:09:09 +0800
Subject: [PATCH 08/16] clk: sunxi-ng: Add M-factor clock support
In-Reply-To: <1462737711-10017-9-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-9-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v67wqsLR9QoMihSS6dkqqtyed=HqyBMJEp4adNm_xF-26Q@mail.gmail.com>

Hi,

On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Introduce support for clocks that divide by a linear factor.

I think we can have just one implementation for single divide factor
(either P or M)
clocks, using the CCF divider helpers. Even the divider table clock
could be merged
in.

>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile |   1 +
>  drivers/clk/sunxi-ng/ccu_m.c  | 135 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_m.h  | 101 +++++++++++++++++++++++++++++++
>  3 files changed, 237 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_m.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_m.h
>
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index a47a3bbdf285..f41de901c607 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -4,5 +4,6 @@ obj-y += ccu_reset.o
>  obj-y += ccu_div_table.o
>  obj-y += ccu_fixed_factor.o
>  obj-y += ccu_gate.o
> +obj-y += ccu_m.o
>  obj-y += ccu_mux.o
>  obj-y += ccu_phase.o
> diff --git a/drivers/clk/sunxi-ng/ccu_m.c b/drivers/clk/sunxi-ng/ccu_m.c
> new file mode 100644
> index 000000000000..424eb6da0d5b
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_m.c
> @@ -0,0 +1,135 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_gate.h"
> +#include "ccu_m.h"
> +#include "ccu_mux.h"
> +
> +static void ccu_m_find_best(unsigned long parent, unsigned long rate,
> +                           unsigned int max_m, unsigned int *m)
> +{
> +       unsigned int _m = parent / rate;
> +
> +       if (_m > max_m)
> +               _m = max_m;
> +
> +       *m = _m;
> +}

This can go.

> +
> +static unsigned long ccu_m_round_rate(struct ccu_mux_internal *mux,
> +                                      unsigned long parent_rate,
> +                                      unsigned long rate,
> +                                      void *data)
> +{
> +       struct ccu_m *cm = data;
> +       unsigned int m;
> +
> +       ccu_m_find_best(parent_rate, rate, 1 << cm->m.width, &m);
> +
> +       return parent_rate / m;

Use divider_round_rate() helper instead.

> +}
> +
> +
> +static void ccu_m_disable(struct clk_hw *hw)
> +{
> +       struct ccu_m *cm = hw_to_ccu_m(hw);
> +
> +       return ccu_gate_helper_disable(&cm->common, cm->enable);
> +}
> +
> +static int ccu_m_enable(struct clk_hw *hw)
> +{
> +       struct ccu_m *cm = hw_to_ccu_m(hw);
> +
> +       return ccu_gate_helper_enable(&cm->common, cm->enable);
> +}
> +
> +static int ccu_m_is_enabled(struct clk_hw *hw)
> +{
> +       struct ccu_m *cm = hw_to_ccu_m(hw);
> +
> +       return ccu_gate_helper_is_enabled(&cm->common, cm->enable);
> +}
> +
> +static unsigned long ccu_m_recalc_rate(struct clk_hw *hw,
> +                                      unsigned long parent_rate)
> +{
> +       struct ccu_m *cm = hw_to_ccu_m(hw);
> +       unsigned long m;
> +       u32 reg;
> +
> +       reg = readl(cm->common.base + cm->common.reg);
> +
> +       m = reg >> cm->m.shift;
> +       m &= (1 << cm->m.width) - 1;
> +
> +       return parent_rate / (m + 1);

Use divider_recalc_rate() helper.

> +}
> +
> +static int ccu_m_determine_rate(struct clk_hw *hw,
> +                               struct clk_rate_request *req)
> +{
> +       struct ccu_m *cm = hw_to_ccu_m(hw);
> +
> +       return ccu_mux_helper_determine_rate(&cm->common, &cm->mux,
> +                                            req, ccu_m_round_rate, cm);
> +}
> +
> +static int ccu_m_set_rate(struct clk_hw *hw, unsigned long rate,
> +                         unsigned long parent_rate)
> +{
> +       struct ccu_m *cm = hw_to_ccu_m(hw);
> +       unsigned long flags;
> +       unsigned int m;
> +       u32 reg;
> +
> +       ccu_m_find_best(parent_rate, rate, 1 << cm->m.width, &m);

Use divider_get_val() helper.

> +
> +       spin_lock_irqsave(cm->common.lock, flags);
> +
> +       reg = readl(cm->common.base + cm->common.reg);
> +       reg &= ((1 << cm->m.width) - 1) << cm->m.shift;
> +
> +       writel(reg | ((m - 1) << cm->m.shift),
> +              cm->common.base + cm->common.reg);
> +
> +       spin_unlock_irqrestore(cm->common.lock, flags);
> +
> +       return 0;
> +}
> +
> +static u8 ccu_m_get_parent(struct clk_hw *hw)
> +{
> +       struct ccu_m *cm = hw_to_ccu_m(hw);
> +
> +       return ccu_mux_helper_get_parent(&cm->common, &cm->mux);
> +}
> +
> +static int ccu_m_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       struct ccu_m *cm = hw_to_ccu_m(hw);
> +
> +       return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index);
> +}
> +
> +const struct clk_ops ccu_m_ops = {
> +       .disable        = ccu_m_disable,
> +       .enable         = ccu_m_enable,
> +       .is_enabled     = ccu_m_is_enabled,
> +
> +       .get_parent     = ccu_m_get_parent,
> +       .set_parent     = ccu_m_set_parent,
> +
> +       .determine_rate = ccu_m_determine_rate,
> +       .recalc_rate    = ccu_m_recalc_rate,
> +       .set_rate       = ccu_m_set_rate,
> +};
> diff --git a/drivers/clk/sunxi-ng/ccu_m.h b/drivers/clk/sunxi-ng/ccu_m.h
> new file mode 100644
> index 000000000000..625c0a7cef43
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_m.h
> @@ -0,0 +1,101 @@
> +/*
> + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _CCU_M_H_
> +#define _CCU_M_H_
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_factor.h"
> +#include "ccu_mux.h"
> +
> +struct ccu_m {
> +       u32                     enable;

Add a field for divider flags, such as CLK_DIVIDER_ONE_BASED and
CLK_DIVIDER_POWER_OF_TWO. With these we can merge P & M factor clocks,
and also be able to handle M factors starting from both 1 and 0.

Also add a field for divider tables to merge the divider table clock.

> +
> +       struct ccu_factor       m;
> +       struct ccu_mux_internal mux;
> +       struct ccu_common       common;
> +};
> +
> +#define SUNXI_CCU_M(_struct, _name, _parent, _reg, _mshift, _mwidth,   \
> +                   _flags)                                             \
> +       struct ccu_m _struct = {                                        \
> +               .m      = SUNXI_CLK_FACTOR(_mshift, _mwidth),           \
> +               .common = {                                             \
> +                       .reg            = _reg,                         \
> +                       .hw.init        = SUNXI_HW_INIT(_name,          \
> +                                                       _parent,        \
> +                                                       &ccu_m_ops,     \
> +                                                       _flags),        \
> +               },                                                      \
> +       }
> +
> +#define SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,           \
> +                             _mshift, _mwidth, _gate,                  \
> +                             _flags)                                   \
> +       struct ccu_m _struct = {                                        \
> +               .enable = _gate,                                        \
> +               .m      = SUNXI_CLK_FACTOR(_mshift, _mwidth),           \
> +               .common = {                                             \
> +                       .reg            = _reg,                         \
> +                       .features       = CCU_FEATURE_GATE,             \
> +                       .hw.init        = SUNXI_HW_INIT(_name,          \
> +                                                       _parent,        \
> +                                                       &ccu_m_ops,     \
> +                                                       _flags),        \
> +               },                                                      \
> +       }
> +
> +#define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg,           \
> +                            _mshift, _mwidth, _muxshift, _muxwidth,    \
> +                            _flags)                                    \
> +       struct ccu_m _struct = {                                        \
> +               .m      = SUNXI_CLK_FACTOR(_mshift, _mwidth),           \
> +               .mux    = SUNXI_CLK_MUX(_muxshift, _muxwidth),          \
> +               .common = {                                             \
> +                       .reg            = _reg,                         \
> +                       .hw.init        = SUNXI_HW_INIT_PARENTS(_name,  \
> +                                                               _parents, \
> +                                                               &ccu_m_ops, \
> +                                                               _flags), \
> +               },                                                      \
> +       }

Maybe you could use the full macro below to simplify the above 3, with
the unused fields set to 0?


Regards
ChenYu

> +
> +#define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg,      \
> +                                 _mshift, _mwidth, _muxshift, _muxwidth, \
> +                                 _gate, _flags)                        \
> +       struct ccu_m _struct = {                                        \
> +               .enable = _gate,                                        \
> +               .m      = SUNXI_CLK_FACTOR(_mshift, _mwidth),           \
> +               .mux    = SUNXI_CLK_MUX(_muxshift, _muxwidth),          \
> +               .common = {                                             \
> +                       .reg            = _reg,                         \
> +                       .features       = CCU_FEATURE_GATE,             \
> +                       .hw.init        = SUNXI_HW_INIT_PARENTS(_name,  \
> +                                                               _parents, \
> +                                                               &ccu_m_ops, \
> +                                                               _flags), \
> +               },                                                      \
> +       }
> +
> +static inline struct ccu_m *hw_to_ccu_m(struct clk_hw *hw)
> +{
> +       struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +       return container_of(common, struct ccu_m, common);
> +}
> +
> +extern const struct clk_ops ccu_m_ops;
> +
> +#endif /* _CCU_M_H_ */
> --
> 2.8.2
>


From heiko at sntech.de  Sat May 21 14:23:47 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 21 May 2016 23:23:47 +0200
Subject: [PATCH 2/3] arm64: dts: rockchip: add rk3368-r88 iodomains
In-Reply-To: <1463865828-14583-1-git-send-email-heiko@sntech.de>
References: <1463865828-14583-1-git-send-email-heiko@sntech.de>
Message-ID: <1463865828-14583-3-git-send-email-heiko@sntech.de>

Add the supply-links according to the R88 schematics.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 arch/arm64/boot/dts/rockchip/rk3368-r88.dts | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts
index b56b720..82a32e5 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts
@@ -236,6 +236,15 @@
 	};
 };
 
+&io_domains {
+	status = "ok";
+
+	audio-supply = <&vcc_io>;
+	gpio30-supply = <&vcc_io>;
+	gpio1830-supply = <&vcc_io>;
+	wifi-supply = <&vccio_wl>;
+};
+
 &sdio0 {
 	assigned-clocks = <&cru SCLK_SDIO0>;
 	assigned-clock-parents = <&cru PLL_CPLL>;
@@ -329,6 +338,13 @@
 	};
 };
 
+&pmu_io_domains {
+	status = "okay";
+
+	pmu-supply = <&vcc_io>;
+	vop-supply = <&vcc_io>;
+};
+
 &saradc {
 	vref-supply = <&vcc_18>;
 	status = "okay";
-- 
2.6.4



From heiko at sntech.de  Sat May 21 14:23:48 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 21 May 2016 23:23:48 +0200
Subject: [PATCH 3/3] arm64: dts: rockchip: add rk3399 io-domain core nodes
In-Reply-To: <1463865828-14583-1-git-send-email-heiko@sntech.de>
References: <1463865828-14583-1-git-send-email-heiko@sntech.de>
Message-ID: <1463865828-14583-4-git-send-email-heiko@sntech.de>

Add the core io-domain nodes to grf and pmugrf which individual
boards than just have to enable and add the necessary supplies to.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index a6a60fa..12acae6 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -407,6 +407,11 @@
 		reg = <0x0 0xff320000 0x0 0x1000>;
 		#address-cells = <1>;
 		#size-cells = <1>;
+
+		pmu_io_domains: io-domains {
+			compatible = "rockchip,rk3399-pmu-io-voltage-domain";
+			status = "disabled";
+		};
 	};
 
 	spi3: spi at ff350000 {
@@ -517,6 +522,11 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 
+		io_domains: io-domains {
+			compatible = "rockchip,rk3399-io-voltage-domain";
+			status = "disabled";
+		};
+
 		emmc_phy: phy at f780 {
 			compatible = "rockchip,rk3399-emmc-phy";
 			reg = <0xf780 0x24>;
-- 
2.6.4



From heiko at sntech.de  Sat May 21 14:23:46 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 21 May 2016 23:23:46 +0200
Subject: [PATCH 1/3] arm64: dts: rockchip: add rk3368 io-domain core nodes
In-Reply-To: <1463865828-14583-1-git-send-email-heiko@sntech.de>
References: <1463865828-14583-1-git-send-email-heiko@sntech.de>
Message-ID: <1463865828-14583-2-git-send-email-heiko@sntech.de>

Add the core io-domain nodes to grf and pmugrf which individual
boards than just have to enable and add the necessary supplies to.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 arch/arm64/boot/dts/rockchip/rk3368.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
index 4fb8484..58c2585 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
@@ -634,6 +634,11 @@
 	pmugrf: syscon at ff738000 {
 		compatible = "rockchip,rk3368-pmugrf", "syscon", "simple-mfd";
 		reg = <0x0 0xff738000 0x0 0x1000>;
+
+		pmu_io_domains: io-domains {
+			compatible = "rockchip,rk3368-pmu-io-voltage-domain";
+			status = "disabled";
+		};
 	};
 
 	cru: clock-controller at ff760000 {
@@ -647,6 +652,11 @@
 	grf: syscon at ff770000 {
 		compatible = "rockchip,rk3368-grf", "syscon", "simple-mfd";
 		reg = <0x0 0xff770000 0x0 0x1000>;
+
+		io_domains: io-domains {
+			compatible = "rockchip,rk3368-io-voltage-domain";
+			status = "disabled";
+		};
 	};
 
 	wdt: watchdog at ff800000 {
-- 
2.6.4



From heiko at sntech.de  Sat May 21 14:23:45 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 21 May 2016 23:23:45 +0200
Subject: [PATCH 0/3] arm64: dts: rockchip: add io-domain support for rk3368
 and rk3399
Message-ID: <1463865828-14583-1-git-send-email-heiko@sntech.de>

This adds the core io-domain nodes for both the rk3368 and rk3399
as well as the actual supplies on the rk3368-r88 board.

This of course needs
    PM / AVS: rockchip-io: make io-domains a child of the GRF
that went into mainline during the 4.7 merge window.

Heiko Stuebner (3):
  arm64: dts: rockchip: add rk3368 io-domain core nodes
  arm64: dts: rockchip: add rk3368-r88 iodomains
  arm64: dts: rockchip: add rk3399 io-domain core nodes

 arch/arm64/boot/dts/rockchip/rk3368-r88.dts | 16 ++++++++++++++++
 arch/arm64/boot/dts/rockchip/rk3368.dtsi    | 10 ++++++++++
 arch/arm64/boot/dts/rockchip/rk3399.dtsi    | 10 ++++++++++
 3 files changed, 36 insertions(+)

-- 
2.6.4



From heiko at sntech.de  Sun May 22 02:27:34 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Sun, 22 May 2016 11:27:34 +0200
Subject: [PATCH 05/54] MAINTAINERS: Add file patterns for rockchip device
 tree bindings
In-Reply-To: <1463907991-7916-6-git-send-email-geert@linux-m68k.org>
References: <1463907991-7916-1-git-send-email-geert@linux-m68k.org>
 <1463907991-7916-6-git-send-email-geert@linux-m68k.org>
Message-ID: <1575416.jfSztnP7S8@phil>

Hi Geert,

Am Sonntag, 22. Mai 2016, 11:05:42 schrieb Geert Uytterhoeven:
> Submitters of device tree binding documentation may forget to CC
> the subsystem maintainer if this is missing.

The "N:	rockchip" line at the bottom of the block catches this nicely 
already (also just verified with a get_maintainer.pl -f call), so I don't 
think this new more explicit line is really necessary?


Thanks
Heiko


> Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-rockchip at lists.infradead.org
> ---
> Please apply this patch directly if you want to be involved in device
> tree binding documentation for your subsystem.
> ---
>  MAINTAINERS | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ea4e25a2f188aca1..e6b84eba4d574d13 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1577,6 +1577,7 @@ L:	linux-arm-kernel at lists.infradead.org (moderated
> for non-subscribers) L:	linux-rockchip at lists.infradead.org
>  T:	git
> git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git
> S:	Maintained
> +F:	Documentation/devicetree/bindings/soc/rockchip/
>  F:	arch/arm/boot/dts/rk3*
>  F:	arch/arm/mach-rockchip/
>  F:	drivers/clk/rockchip/



From marc.zyngier at arm.com  Sun May 22 02:30:56 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Sun, 22 May 2016 10:30:56 +0100
Subject: 4.5.0 on sun7i-a20-olinuxino-lime2: libphy: PHY
 stmmac-0:ffffffff not found (regression from rc7)
In-Reply-To: <574082F9.7010702@a20.net>
References: <56E9413D.9010902@a20.net> <56E945FF.6080005@arm.com>
 <56E94CF4.2060607@arm.com> <56E95B57.1090100@suse.de>
 <56E9776F.3070102@a20.net> <56E99B0C.2070609@arm.com>
 <56E9F2B8.1030605@a20.net> <20160317075202.16b14ed6@arm.com>
 <CAHsu+b-t_r93XKLJTUcin6xjhOrFVn3_60vwHkbRt3iHK28CbA@mail.gmail.com>
 <573EC33D.2010209@arm.com> <573EC77A.2000800@st.com>
 <CAHsu+b9BrqBLdCpsPpetc_4_EaFVGBdDHtoeeCqqzsCG3Wpsig@mail.gmail.com>
 <573EE8B4.1050701@arm.com> <574082F9.7010702@a20.net>
Message-ID: <20160522103056.2fa86293@arm.com>

On Sat, 21 May 2016 17:47:05 +0200
Bert Lindner <bert at a20.net> wrote:

> Hi,
> 
> On 2016-05-20 12:36, Marc Zyngier wrote:
> > On 20/05/16 11:30, Andre Heider wrote:
> >> Hi,
> >>
> >> On Fri, May 20, 2016 at 10:14 AM, Giuseppe CAVALLARO
> >> <peppe.cavallaro at st.com> wrote:
> >>> On 5/20/2016 9:56 AM, Marc Zyngier wrote:
> >>>>
> >>>> On 20/05/16 06:44, Andre Heider wrote:
> >>>>>
> >>>>> Giuseppe, Alexandre, et al.,
> >>>>>
> >>>>> On Thu, Mar 17, 2016 at 8:52 AM, Marc Zyngier <marc.zyngier at arm.com>
> >>>>> wrote:
> >>>>>>
> >>>>>> On Thu, 17 Mar 2016 00:56:40 +0100
> >>>>>> Bert Lindner <bert at a20.net> wrote:
> >>>>>>>
> >>>>>>> On 2016-03-16 18:42, Marc Zyngier wrote:
> >>>>>>>>
> >>>>>>>> On 16/03/16 15:10, Bert Lindner wrote:
> >>>>>>>>>
> >>>>>>>>> On 2016-03-16 14:10, Andreas F?rber wrote:
> >>>>>>>>>>
> >>>>>>>>>> Am 16.03.2016 um 13:09 schrieb Robin Murphy:
> >>>>>>>>>>>
> >>>>>>>>>>> On 16/03/16 11:39, Marc Zyngier wrote:
> >>>>>>>>>>>>
> >>>>>>>>>>>> On 16/03/16 11:19, Bert Lindner wrote:
> >>>>>
> >>>>> ...
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> For the board sun7i-a20-olinuxino-lime2, there seems to be a
> >>>>>>>>>>>>> problem
> >>>>>>>>>>>>> with the eth0 PHY in mainline kernel 4.5.0 that developed since
> >>>>>>>>>>>>> 4.5.0-rc7. Ethernet does not work, although eth0 is reported:
> >>>>>
> >>>>> ...
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> [    9.767125] NET: Registered protocol family 10
> >>>>>>>>>>>>> [   10.357405] libphy: PHY stmmac-0:ffffffff not found
> >>>>>>>>>>>>> [   10.362382] eth0: Could not attach to PHY
> >>>>>>>>>>>>> [   10.366557] stmmac_open: Cannot attach to PHY (error: -19)
> >>>>>
> >>>>> ...
> >>>>>>>>>>
> >>>>>>>>>> v4 fixes for 4.5 are here:
> >>>>>>>>>>
> >>>>>>>>>> https://patchwork.ozlabs.org/patch/598195/ (revert)
> >>>>>>>>>> https://patchwork.ozlabs.org/patch/598196/
> >>>>>
> >>>>> ...
> >>>>>>>>
> >>>>>>>> Good to know, thanks. Could you also give the potential fix a go (as
> >>>>>>>> mentioned by Andreas)? Just to make sure that whatever gets merged
> >>>>>>>> next
> >>>>>>>> will actually fix the issue.
> >>>>>>>
> >>>>>>>
> >>>>>>> Yes sure, it took a while because I had to travel. Confirmed, the
> >>>>>>> v4-for-4.5 fix works well for me, on sun7i-a20-olinuxino-lime2:
> >>>>>>>
> >>>>>>> root at lime2-079f:~# cat /proc/version
> >>>>>>> Linux version 4.5.0-598195-598196-v4 (root at lime2-079f) (gcc version
> >>>>>>> 4.9.1 (Ubuntu/Linaro 4.9.1-16ubuntu6) ) #1 SMP Wed Mar 16 16:44:22 UTC
> >>>>>>> 2016
> >>>>>>>
> >>>>>>> dmesg:
> >>>>>>> [    8.245273] NET: Registered protocol family 10
> >>>>>>> [    9.297406]  RX IPC Checksum Offload disabled
> >>>>>>> [    9.297460]  No MAC Management Counters available
> >>>>>>> [    9.297951] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
> >>>>>>> [   16.285658] sun7i-dwmac 1c50000.ethernet eth0: Link is Up -
> >>>>>>> 1Gbps/Full - flow control rx/tx
> >>>>>>> [   16.285798] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
> >>>>>>>
> >>>>>>> The board is connected to my laptop rather than to a switch, so that
> >>>>>>> might be where the flow control message comes from (not sure). Anyway
> >>>>>>> ethernet works.
> >>>>>>
> >>>>>>
> >>>>>> Cool, many thanks for taking the time to test and report.
> >>>>>>
> >>>>>> Hopefully Giuseppe will get this merged quickly enough in mainline, and
> >>>>>> it should then trickle into a 4.5-stable release (cc-ing stable on
> >>>>>> these patches would probably be a good idea, BTW).
> >>>>>
> >>>>>
> >>>>> stmmac is broken on at least Lime2, BananaPi and Cubieboard2 since
> >>>>> v4.5 [0], including all five stable releases :(
> >>>>
> >>>>
> >>>> All the A20 platforms are dead, actually.
> >>>>
> >>>>> The v4.5 patches quoted above are already +4 weeks old, could we
> >>>>> please get them into stable?
> >>>>
> >>>>
> >>>> For that, the maintainer would have needed to CC stable, which he
> >>>> didn't. I'd expect someone who cares to send these patches to stable.
> >>>> It'd be better if the maintainer would do it himself though.
> >>>
> >>>
> >>> sure, I can send the patches to stable (sorry if I missed to add
> >>> stable ML on CC).
> >>>
> >>> Andre, I have not clear if the train of patches actually fix the
> >>> issue or if you need my support to fix something else. In that case
> >>> I need some input for debugging (e.g. kernel log).
> >>
> >> Bert already confirmed that those two patches fixes stmmac on his
> >> Lime2, so I assume that it fixes the issue for all A20 platforms.
> >>
> >>> let me know, is it enough to re-send the patches only?
> >>
> >> Just a resend with cc:stable :)
> >
> > Not quite. Please read Documentation/stable_kernel_rules.txt, and the
> > section that concerns networking patches (and then consult
> > Documentation/networking/netdev-FAQ.txt which has all the details).
> 
> FWIW, recent 4.6-rc series and 4.6.0 have worked fine for me and the 
> lime2. Had not tried 4.5.x again.

We've already established this. This is a 4.5-specific regression (both
4.4 and 4.6 are fine). One major issue is that Debian Stretch is
currently shipping with 4.5, and upgrading to it results in a system
without networking. Should this patch make it into stable, the fix would
quickly percolate into distro kernels, and we could forget about it.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.


From u.kleine-koenig at pengutronix.de  Sun May 22 03:26:06 2016
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Sun, 22 May 2016 12:26:06 +0200
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <1463648641-6931-2-git-send-email-vigneshr@ti.com>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
 <1463648641-6931-2-git-send-email-vigneshr@ti.com>
Message-ID: <20160522102606.GB23704@pengutronix.de>

Hello,

On Thu, May 19, 2016 at 02:34:00PM +0530, Vignesh R wrote:
> There are rotary-encoders where GPIO lines reflect the actual position
> of the rotary encoder dial. For example, if dial points to 9, then four
> GPIO lines connected to the rotary encoder will read HLLH(1001b = 9).
> Add support for such rotary-encoder.
> The driver relies on rotary-encoder,absolute-encoder DT property to
> detect such encoders.
> Since, GPIO IRQs are not necessary to work with
> such encoders, optional polling mode support is added using

I don't understand this. It's necessary in the same way as with the
already supported devices. I.e. you want to trigger an irq when the
encoder is moved and then check for it's position in the handler.

> diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> index 6c9f0c8a846c..9c928dbd1500 100644
> --- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
> +++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> @@ -12,6 +12,10 @@ Optional properties:
>  - rotary-encoder,relative-axis: register a relative axis rather than an
>    absolute one. Relative axis will only generate +1/-1 events on the input
>    device, hence no steps need to be passed.
> +- rotary-encoder,absolute-encoder: support encoders where GPIO lines
> +  reflect the actual position of the rotary encoder dial. For example,
> +  if dial points to 9, then four GPIO lines read HLLH(1001b = 9).
> +  In this case, rotary-encoder,steps-per-period needed not be defined.

IMHO this is wrong, I'd formalize this device as:

	{
		compatible = "rotary-encoder";
		gpios = <&gpio 19 1>, <&gpio 20 0>, <...>, <...>;
		rotary-encoder,encoding = "binary";
		rotary-encoder,steps = <16>;
		rotary-encoder,steps-per-period = <16>;
		rotary-encoder,rollover;
	}

and support this with a v4 of

	http://thread.gmane.org/gmane.linux.kernel.input/48892

.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From hramrach at gmail.com  Sun May 22 07:18:20 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: Sun, 22 May 2016 16:18:20 +0200
Subject: sunxi spi clock problem
Message-ID: <CAOMqctQKNWz3mYPMModLTZ-hj38GxHqa3mBmDhbfTZz0zJ-CUw@mail.gmail.com>

Hello,

I tried running a spidev test program on linux 4.6 and I uncovered a
problem with the sunxi clk framework.

Basically the system would lock up after running the test program.

Digging deeper I found that it locks up with commit
[47284e3e0f3c427c93f8583549b6c938e8a18015] spi: sun4i: allow transfers
to set transmission speed

This exposes a problem with the test program. I try to set the SPI
sped to 1MHz but at other place the speed is multiplied by 1000 to
save typing zeros so the actual requested speed is 1GHz. This commit
probably allows that request to propagate leading to the observed
system lockup.

Given the parents OSC24M, pll6 and pll5 one of pll6 and pll5 is
probably set up at 2GHz (or both in turn because due to some rounding
neither goes fully up to 2GHz resulting in 864000000 SPI clock). Then
the system locks up.

I can limit the speed in the SPI driver which is rated at 100MHz in
SoC manual (giving 200MHz pll) but the clk driver should probably
limit the clock setting to sane speeds itself.

I am not familiar with the sunxi-clk code and it has unfortunately no
debug prints which would show what is programmed to what speed.

Thanks

Michal

root at a10s:~/spidisp# ./spitest -r 50 -d -s 1000000 /dev/spidev2.0
Debug mode.
spidev spi2.0: setup mode 0, 8 bits/w, 40000000 Hz max --> 0
spidev spi2.0: spi mode 0
spidev spi2.0: setup mode 0, 8 bits/w, 40000000 Hz max --> 0
spidev spi2.0: msb first
spidev spi2.0: setup mode 0, 8 bits/w, 40000000 Hz max --> 0
spidev spi2.0: 0 bits per word
spidev spi2.0: setup mode 0, 8 bits/w, 1000000000 Hz max --> 0
/dev/spidev2.0: spi mode 0x0, 8 bits per word, 1000000000 Hz maxspidev
spi2.0: mclk spi2 (24000000)

Sending 00
spidev spi2.0: mclk spi2 setting rate 2000000000Hz
spidev spi2.0: mclk spi2 (864000000)
spidev spi2.0: clkdiv 0 CDR2 0 regval 4096
spi_master spi2: spi2.0: timeout transferring 1 bytes at 1000000000Hz for
100(100)ms
spidev spi2.0: SPI transfer failed: -110
spi_master spi2: failed to transfer one message from queue
xfer: Connection timed out
buffer size: 1, result -110
buffer size: 1, result -110, Connection timed out
Sending
maximum buffer size: 0
Using gpio 50.
Writing gpio export 50 to /sys/class/gpio/export.
Reading gpio direction from /sys/class/gpio/gpio50/direction: in

Reading gpio inversion from /sys/class/gpio/gpio50/active_low: 0

Writing gpio direction in to /sys/class/gpio/gpio50/direction.
Reading gpio value from /sys/class/gpio/gpio50/value: 1

Writing gpio direction out to /sys/class/gpio/gpio50/direction.
Writing gpio value 0 to /sys/class/gpio/gpio50/value.
Writing gpio value 1 to /sys/class/gpio/gpio50/value.
Writing gpio value 0 to /sys/class/gpio/gpio50/value.
Writing gpio value 1 to /sys/class/gpio/gpio50/value.
Sending 9f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
spidev spi2.0: mclk spi2 (864000000)
spidev spi2.0: mclk spi2 setting rate 2000000000Hz
spidev spi2.0: mclk spi2 (864000000)
spidev spi2.0: clkdiv 0 CDR2 0 regval 4096


From wens at csie.org  Sun May 22 07:58:09 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Sun, 22 May 2016 22:58:09 +0800
Subject: sunxi spi clock problem
In-Reply-To: <CAOMqctQKNWz3mYPMModLTZ-hj38GxHqa3mBmDhbfTZz0zJ-CUw@mail.gmail.com>
References: <CAOMqctQKNWz3mYPMModLTZ-hj38GxHqa3mBmDhbfTZz0zJ-CUw@mail.gmail.com>
Message-ID: <CAGb2v64gYov-tKENkeu0Mf+-qev49JnmR-Q94YvOMHwHti3djQ@mail.gmail.com>

Hi,

On Sun, May 22, 2016 at 10:18 PM, Michal Suchanek <hramrach at gmail.com> wrote:
> Hello,
>
> I tried running a spidev test program on linux 4.6 and I uncovered a
> problem with the sunxi clk framework.
>
> Basically the system would lock up after running the test program.
>
> Digging deeper I found that it locks up with commit
> [47284e3e0f3c427c93f8583549b6c938e8a18015] spi: sun4i: allow transfers
> to set transmission speed
>
> This exposes a problem with the test program. I try to set the SPI
> sped to 1MHz but at other place the speed is multiplied by 1000 to
> save typing zeros so the actual requested speed is 1GHz. This commit
> probably allows that request to propagate leading to the observed
> system lockup.
>
> Given the parents OSC24M, pll6 and pll5 one of pll6 and pll5 is
> probably set up at 2GHz (or both in turn because due to some rounding
> neither goes fully up to 2GHz resulting in 864000000 SPI clock). Then
> the system locks up.

IIRC the mod clock does not propagate rate changes up the tree.
But some output from the debugfs would be helpful. See below.

>
> I can limit the speed in the SPI driver which is rated at 100MHz in
> SoC manual (giving 200MHz pll) but the clk driver should probably
> limit the clock setting to sane speeds itself.
>
> I am not familiar with the sunxi-clk code and it has unfortunately no
> debug prints which would show what is programmed to what speed.

You can use /sys/kernel/debug/clk/clk_summary, provided you have
debugfs built in and mounted.

Regards
ChenYu

>
> Thanks
>
> Michal
>
> root at a10s:~/spidisp# ./spitest -r 50 -d -s 1000000 /dev/spidev2.0
> Debug mode.
> spidev spi2.0: setup mode 0, 8 bits/w, 40000000 Hz max --> 0
> spidev spi2.0: spi mode 0
> spidev spi2.0: setup mode 0, 8 bits/w, 40000000 Hz max --> 0
> spidev spi2.0: msb first
> spidev spi2.0: setup mode 0, 8 bits/w, 40000000 Hz max --> 0
> spidev spi2.0: 0 bits per word
> spidev spi2.0: setup mode 0, 8 bits/w, 1000000000 Hz max --> 0
> /dev/spidev2.0: spi mode 0x0, 8 bits per word, 1000000000 Hz maxspidev
> spi2.0: mclk spi2 (24000000)
>
> Sending 00
> spidev spi2.0: mclk spi2 setting rate 2000000000Hz
> spidev spi2.0: mclk spi2 (864000000)
> spidev spi2.0: clkdiv 0 CDR2 0 regval 4096
> spi_master spi2: spi2.0: timeout transferring 1 bytes at 1000000000Hz for
> 100(100)ms
> spidev spi2.0: SPI transfer failed: -110
> spi_master spi2: failed to transfer one message from queue
> xfer: Connection timed out
> buffer size: 1, result -110
> buffer size: 1, result -110, Connection timed out
> Sending
> maximum buffer size: 0
> Using gpio 50.
> Writing gpio export 50 to /sys/class/gpio/export.
> Reading gpio direction from /sys/class/gpio/gpio50/direction: in
>
> Reading gpio inversion from /sys/class/gpio/gpio50/active_low: 0
>
> Writing gpio direction in to /sys/class/gpio/gpio50/direction.
> Reading gpio value from /sys/class/gpio/gpio50/value: 1
>
> Writing gpio direction out to /sys/class/gpio/gpio50/direction.
> Writing gpio value 0 to /sys/class/gpio/gpio50/value.
> Writing gpio value 1 to /sys/class/gpio/gpio50/value.
> Writing gpio value 0 to /sys/class/gpio/gpio50/value.
> Writing gpio value 1 to /sys/class/gpio/gpio50/value.
> Sending 9f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> spidev spi2.0: mclk spi2 (864000000)
> spidev spi2.0: mclk spi2 setting rate 2000000000Hz
> spidev spi2.0: mclk spi2 (864000000)
> spidev spi2.0: clkdiv 0 CDR2 0 regval 4096


From hramrach at gmail.com  Sun May 22 09:41:18 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: Sun, 22 May 2016 18:41:18 +0200
Subject: sunxi spi clock problem
In-Reply-To: <CAGb2v64gYov-tKENkeu0Mf+-qev49JnmR-Q94YvOMHwHti3djQ@mail.gmail.com>
References: <CAOMqctQKNWz3mYPMModLTZ-hj38GxHqa3mBmDhbfTZz0zJ-CUw@mail.gmail.com>
 <CAGb2v64gYov-tKENkeu0Mf+-qev49JnmR-Q94YvOMHwHti3djQ@mail.gmail.com>
Message-ID: <CAOMqctRS6sEcQ9sy7dqX_TH4gsRiywCN1nUJiQtXAa7NtoboOw@mail.gmail.com>

Hello,

The debugfs output shows that spi2 is reparented under pll5 and the
pll5 frequency remains unchanged.

The request to get a 2GHz clock for spi is fulfilled on best-effort
basis by giving the 864MHz pll5 clock which should theoretically
result in 432MHz SPI clock.

On 22 May 2016 at 16:58, Chen-Yu Tsai <wens at csie.org> wrote:
> Hi,
>
> On Sun, May 22, 2016 at 10:18 PM, Michal Suchanek <hramrach at gmail.com> wrote:
>> Hello,
>>
>> I tried running a spidev test program on linux 4.6 and I uncovered a
>> problem with the sunxi clk framework.
>>
>> Basically the system would lock up after running the test program.
>>
>> Digging deeper I found that it locks up with commit
>> [47284e3e0f3c427c93f8583549b6c938e8a18015] spi: sun4i: allow transfers
>> to set transmission speed
>>
>> This exposes a problem with the test program. I try to set the SPI
>> sped to 1MHz but at other place the speed is multiplied by 1000 to
>> save typing zeros so the actual requested speed is 1GHz. This commit
>> probably allows that request to propagate leading to the observed
>> system lockup.
>>
>> Given the parents OSC24M, pll6 and pll5 one of pll6 and pll5 is
>> probably set up at 2GHz (or both in turn because due to some rounding
>> neither goes fully up to 2GHz resulting in 864000000 SPI clock). Then
>> the system locks up.
>
> IIRC the mod clock does not propagate rate changes up the tree.
> But some output from the debugfs would be helpful. See below.
>
>>
>> I can limit the speed in the SPI driver which is rated at 100MHz in
>> SoC manual (giving 200MHz pll) but the clk driver should probably
>> limit the clock setting to sane speeds itself.
>>
>> I am not familiar with the sunxi-clk code and it has unfortunately no
>> debug prints which would show what is programmed to what speed.
>
> You can use /sys/kernel/debug/clk/clk_summary, provided you have
> debugfs built in and mounted.

root at a10s:~/spidisp# ./spitest -d -s 1000000 /dev/spidev2.0
Debug mode.
/dev/spidev2.0: spi mode 0x0, 8 bits per word, 1000000000 Hz max
Sending 00
   clock                         enable_cnt  prepare_cnt        rate
accuracy   phase
----------------------------------------------------------------------------------------
 osc32k                                   0            0       32768
       0 0
 osc24M                                   6            6    24000000
       0 0
    ir0                                   0            0    24000000
       0 0
    spi2                                  0            0    24000000
       0 0
    spi1                                  0            0    24000000
       0 0
    spi0                                  0            0    24000000
       0 0
...
spi_master spi2: spi2.0: timeout transferring 1 bytes at 1000000000Hz for
100(100)ms
spidev spi2.0: SPI transfer failed: -110
spi_master spi2: failed to transfer one message from queue
...
    pll5                                  1            1   864000000
       0 0
       pll5_other                         0            0   864000000
       0 0
       pll5_ddr                           1            1   432000000
       0 0
...
xfer: Connection timed out
buffer size: 1, result -110
buffer size: 1, result -110, Connection timed out
Sending
   clock                         enable_cnt  prepare_cnt        rate
accuracy   phase
----------------------------------------------------------------------------------------
 osc32k                                   0            0       32768
       0 0
 osc24M                                   6            6    24000000
       0 0
    ir0                                   0            0    24000000
       0 0
    spi1                                  0            0    24000000
       0 0
    spi0                                  0            0    24000000
       0 0
    ss                                    0            0    24000000
       0 0
...
    pll5                                  1            1   864000000
       0 0
       pll5_other                         0            0   864000000
       0 0
          spi2                            0            0   864000000
       0 0
       pll5_ddr                           1            1   432000000
       0 0
...
maximum buffer size: 0
Sending 9f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...
    pll5                                  1            1   864000000
       0 0
       pll5_other                         0            0   864000000
       0 0
          spi2                            0            0   864000000
       0 0
       pll5_ddr                           1            1   432000000
       0 0
    pll4                                  0            0   384000000
       0 0
    pll2-prediv                           0

The system locks up here before finishing the output from debugfs and
actually starting the transfer printed above.

Thanks

Michal

---

The diff between the two full outputs shows only spi2 changed:

--- clk1.txt    2016-05-22 18:38:24.890906037 +0200
+++ clk2.txt    2016-05-22 18:38:15.891003130 +0200
@@ -3,7 +3,6 @@
  osc32k                                   0            0       32768
        0 0
  osc24M                                   6            6    24000000
        0 0
     ir0                                   0            0    24000000
        0 0
-    spi2                                  0            0    24000000
        0 0
     spi1                                  0            0    24000000
        0 0
     spi0                                  0            0    24000000
        0 0
     ss                                    0            0    24000000
        0 0
@@ -69,6 +68,7 @@
        pll6_sata                          0            0   100000000
        0 0
     pll5                                  1            1   864000000
        0 0
        pll5_other                         0            0   864000000
        0 0
+          spi2                            0            0   864000000
        0 0
        pll5_ddr                           1            1   432000000
        0 0
     pll4                                  0            0   384000000
        0 0
     pll2-prediv                           0            0     1500000
        0 0


From santosh.shilimkar at oracle.com  Sun May 22 09:52:22 2016
From: santosh.shilimkar at oracle.com (Santosh Shilimkar)
Date: Sun, 22 May 2016 09:52:22 -0700
Subject: [PATCH 46/54] MAINTAINERS: Add file patterns for ti device tree
 bindings
In-Reply-To: <1463907991-7916-47-git-send-email-geert@linux-m68k.org>
References: <1463907991-7916-1-git-send-email-geert@linux-m68k.org>
 <1463907991-7916-47-git-send-email-geert@linux-m68k.org>
Message-ID: <e8cc8949-aa20-4bba-fa69-64e54ab45853@oracle.com>

On 5/22/2016 2:06 AM, Geert Uytterhoeven wrote:
> Submitters of device tree binding documentation may forget to CC
> the subsystem maintainer if this is missing.
>
> Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
> Cc: Santosh Shilimkar <ssantosh at kernel.org>
> Cc: linux-kernel at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org
> ---
> Please apply this patch directly if you want to be involved in device
> tree binding documentation for your subsystem.
> ---
Acked-by: Santosh Shilimkar <ssantosh at kernel.org>


From hramrach at gmail.com  Sun May 22 09:59:26 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: Sun, 22 May 2016 18:59:26 +0200
Subject: sunxi spi clock problem
In-Reply-To: <CAOMqctRS6sEcQ9sy7dqX_TH4gsRiywCN1nUJiQtXAa7NtoboOw@mail.gmail.com>
References: <CAOMqctQKNWz3mYPMModLTZ-hj38GxHqa3mBmDhbfTZz0zJ-CUw@mail.gmail.com>
 <CAGb2v64gYov-tKENkeu0Mf+-qev49JnmR-Q94YvOMHwHti3djQ@mail.gmail.com>
 <CAOMqctRS6sEcQ9sy7dqX_TH4gsRiywCN1nUJiQtXAa7NtoboOw@mail.gmail.com>
Message-ID: <CAOMqctSt613dRA5=Ss=rA8-8L+vHJ9YK_m4SMdqV7DxTymXxNQ@mail.gmail.com>

On 22 May 2016 at 18:41, Michal Suchanek <hramrach at gmail.com> wrote:
> Hello,
>
> The debugfs output shows that spi2 is reparented under pll5 and the
> pll5 frequency remains unchanged.
>
> The request to get a 2GHz clock for spi is fulfilled on best-effort
> basis by giving the 864MHz pll5 clock which should theoretically
> result in 432MHz SPI clock.
>
> On 22 May 2016 at 16:58, Chen-Yu Tsai <wens at csie.org> wrote:
>> Hi,
>>
>> On Sun, May 22, 2016 at 10:18 PM, Michal Suchanek <hramrach at gmail.com> wrote:
>>> Hello,
>>>
>>> I tried running a spidev test program on linux 4.6 and I uncovered a
>>> problem with the sunxi clk framework.
>>>
>>> Basically the system would lock up after running the test program.
>>>
>>> Digging deeper I found that it locks up with commit
>>> [47284e3e0f3c427c93f8583549b6c938e8a18015] spi: sun4i: allow transfers
>>> to set transmission speed
>>>
>>> This exposes a problem with the test program. I try to set the SPI
>>> sped to 1MHz but at other place the speed is multiplied by 1000 to
>>> save typing zeros so the actual requested speed is 1GHz. This commit
>>> probably allows that request to propagate leading to the observed
>>> system lockup.
>>>
>>> Given the parents OSC24M, pll6 and pll5 one of pll6 and pll5 is
>>> probably set up at 2GHz (or both in turn because due to some rounding
>>> neither goes fully up to 2GHz resulting in 864000000 SPI clock). Then
>>> the system locks up.
>>
>> IIRC the mod clock does not propagate rate changes up the tree.
>> But some output from the debugfs would be helpful. See below.
>>
>>>
>>> I can limit the speed in the SPI driver which is rated at 100MHz in
>>> SoC manual (giving 200MHz pll) but the clk driver should probably
>>> limit the clock setting to sane speeds itself.
>>>
>>> I am not familiar with the sunxi-clk code and it has unfortunately no
>>> debug prints which would show what is programmed to what speed.
>>
>> You can use /sys/kernel/debug/clk/clk_summary, provided you have
>> debugfs built in and mounted.
>
> root at a10s:~/spidisp# ./spitest -d -s 1000000 /dev/spidev2.0
> Debug mode.
> /dev/spidev2.0: spi mode 0x0, 8 bits per word, 1000000000 Hz max
> Sending 00
>    clock                         enable_cnt  prepare_cnt        rate
> accuracy   phase
> ----------------------------------------------------------------------------------------
>  osc32k                                   0            0       32768
>        0 0
>  osc24M                                   6            6    24000000
>        0 0
>     ir0                                   0            0    24000000
>        0 0
>     spi2                                  0            0    24000000
>        0 0
>     spi1                                  0            0    24000000
>        0 0
>     spi0                                  0            0    24000000
>        0 0
> ...
> spi_master spi2: spi2.0: timeout transferring 1 bytes at 1000000000Hz for
> 100(100)ms
> spidev spi2.0: SPI transfer failed: -110
> spi_master spi2: failed to transfer one message from queue
> ...
>     pll5                                  1            1   864000000
>        0 0
>        pll5_other                         0            0   864000000
>        0 0
>        pll5_ddr                           1            1   432000000
>        0 0
> ...
> xfer: Connection timed out
> buffer size: 1, result -110
> buffer size: 1, result -110, Connection timed out
> Sending
>    clock                         enable_cnt  prepare_cnt        rate
> accuracy   phase
> ----------------------------------------------------------------------------------------
>  osc32k                                   0            0       32768
>        0 0
>  osc24M                                   6            6    24000000
>        0 0
>     ir0                                   0            0    24000000
>        0 0
>     spi1                                  0            0    24000000
>        0 0
>     spi0                                  0            0    24000000
>        0 0
>     ss                                    0            0    24000000
>        0 0
> ...
>     pll5                                  1            1   864000000
>        0 0
>        pll5_other                         0            0   864000000
>        0 0
>           spi2                            0            0   864000000
>        0 0
>        pll5_ddr                           1            1   432000000
>        0 0
> ...
> maximum buffer size: 0
> Sending 9f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> ...
>     pll5                                  1            1   864000000
>        0 0
>        pll5_other                         0            0   864000000
>        0 0
>           spi2                            0            0   864000000
>        0 0
>        pll5_ddr                           1            1   432000000
>        0 0
>     pll4                                  0            0   384000000
>        0 0
>     pll2-prediv                           0
>
> The system locks up here before finishing the output from debugfs and
> actually starting the transfer printed above.
>

Actually the serial console speed is limited so the system might be
doing something else already while transferring this debug output.

Thanks

Michal


From maxime.ripard at free-electrons.com  Sun May 22 12:20:58 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun, 22 May 2016 21:20:58 +0200
Subject: [PATCH 05/16] clk: sunxi-ng: Add mux clock support
In-Reply-To: <CAGb2v66FShuDB_YH37x+VymjrpD+Q9OA2D=b3=MyaLkfFySvmQ@mail.gmail.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-6-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v66FShuDB_YH37x+VymjrpD+Q9OA2D=b3=MyaLkfFySvmQ@mail.gmail.com>
Message-ID: <20160522192058.GY27618@lukather>

Hi,

On Sun, May 22, 2016 at 12:18:26AM +0800, Chen-Yu Tsai wrote:
> Hi,
> 
> On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
> <maxime.ripard at free-electrons.com> wrote:
> > Some clocks in the Allwinner SoCs clocks unit are just muxes.
> >
> > However, those muxes might also be found in some other complicated clocks
> > that would benefit from the code in there to deal with "advanced" features,
> > like pre-dividers.
> >
> > Introduce a set of helpers to reduce the code duplication in such cases.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/clk/sunxi-ng/Makefile  |   1 +
> >  drivers/clk/sunxi-ng/ccu_mux.c | 187 +++++++++++++++++++++++++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu_mux.h |  80 +++++++++++++++++-
> >  3 files changed, 264 insertions(+), 4 deletions(-)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_mux.c
> >
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> > index fc01127b3b45..aa5c411ff8ea 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -3,3 +3,4 @@ obj-y += ccu_reset.o
> >
> >  obj-y += ccu_fixed_factor.o
> >  obj-y += ccu_gate.o
> > +obj-y += ccu_mux.o
> > diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
> > new file mode 100644
> > index 000000000000..cb54a8931de3
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_mux.c
> > @@ -0,0 +1,187 @@
> > +/*
> > + * Copyright (C) 2016 Maxime Ripard
> > + * Maxime Ripard <maxime.ripard at free-electrons.com>
> > + *
> > + * 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.
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +
> > +#include "ccu_gate.h"
> > +#include "ccu_mux.h"
> > +
> > +void ccu_mux_helper_adjust_parent_for_prediv(struct ccu_common *common,
> > +                                            struct ccu_mux_internal *cm,
> > +                                            int parent_index,
> > +                                            unsigned long *parent_rate)
> > +{
> > +       u8 prediv = 1;
> > +       u32 reg;
> > +
> > +       if (!((common->features & CCU_FEATURE_FIXED_PREDIV) ||
> > +             (common->features & CCU_FEATURE_VARIABLE_PREDIV)))
> > +               return;
> > +
> > +       reg = readl(common->base + common->reg);
> > +       if (parent_index < 0) {
> > +               parent_index = reg >> cm->shift;
> > +               parent_index &= (1 << cm->width) - 1;
> > +       }
> > +
> > +       if (common->features & CCU_FEATURE_FIXED_PREDIV)
> > +               if (parent_index == cm->fixed_prediv.index)
> > +                       prediv = cm->fixed_prediv.div;
> > +
> > +       if (common->features & CCU_FEATURE_VARIABLE_PREDIV)
> > +               if (parent_index == cm->variable_prediv.index) {
> > +                       u8 div;
> > +
> > +                       div = reg >> cm->variable_prediv.shift;
> > +                       div &= (1 << cm->variable_prediv.width) - 1;
> > +                       prediv = div + 1;
> > +               }
> > +
> > +       *parent_rate = *parent_rate / prediv;
> > +}
> > +
> > +int ccu_mux_helper_determine_rate(struct ccu_common *common,
> > +                                 struct ccu_mux_internal *cm,
> > +                                 struct clk_rate_request *req,
> > +                                 unsigned long (*round)(struct ccu_mux_internal *,
> > +                                                        unsigned long,
> > +                                                        unsigned long,
> > +                                                        void *),
> > +                                 void *data)
> > +{
> > +       unsigned long best_parent_rate = 0, best_rate = 0;
> > +       struct clk_hw *best_parent, *hw = &common->hw;
> > +       unsigned int i;
> > +
> > +       for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
> > +               unsigned long tmp_rate, parent_rate;
> > +               struct clk_hw *parent;
> > +
> > +               parent = clk_hw_get_parent_by_index(hw, i);
> > +               if (!parent)
> > +                       continue;
> > +
> > +               parent_rate = clk_hw_get_rate(parent);
> 
> Using clk-mux.c as a reference, you should honor CLK_SET_RATE_PARENT here.
> 
> > +               ccu_mux_helper_adjust_parent_for_prediv(common, cm, i,
> > +                                                       &parent_rate);
> 
> ccu_mux_helper_adjust_parent_for_prediv can modify parent_rate. You
> should probably save a copy...
> 
> > +
> > +               tmp_rate = round(cm, clk_hw_get_rate(parent), req->rate, data);
> > +               if (tmp_rate == req->rate) {
> > +                       best_parent = parent;
> > +                       best_parent_rate = parent_rate;
> 
> ... to assign to best_parent_rate. The returned best_parent_rate is used
> to change the parent clock rate. This happens if CLK_SET_RATE_PARENT is set.
> The CCF doesn't know about our predivs, so you should pass back the original
> rate, not the one after the prediv.
>
> I suppose you didn't run into problems as CLK_SET_RATE_PARENT was not used
> anywhere?

Probably, yes. You do have a good point, but I'm a bit unconfident
merging some code that hasn't been tested, and will probably end up
broken anyway. This is always something that we can add later.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160522/43ff552c/attachment.sig>

From maxime.ripard at free-electrons.com  Sun May 22 12:22:19 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Sun, 22 May 2016 21:22:19 +0200
Subject: [PATCH 08/16] clk: sunxi-ng: Add M-factor clock support
In-Reply-To: <CAGb2v67wqsLR9QoMihSS6dkqqtyed=HqyBMJEp4adNm_xF-26Q@mail.gmail.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-9-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v67wqsLR9QoMihSS6dkqqtyed=HqyBMJEp4adNm_xF-26Q@mail.gmail.com>
Message-ID: <20160522192219.GZ27618@lukather>

On Sun, May 22, 2016 at 01:09:09AM +0800, Chen-Yu Tsai wrote:
> Hi,
> 
> On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
> <maxime.ripard at free-electrons.com> wrote:
> > Introduce support for clocks that divide by a linear factor.
> 
> I think we can have just one implementation for single divide factor
> (either P or M)
> clocks, using the CCF divider helpers. Even the divider table clock
> could be merged
> in.

This is a good point, I'll merge the drivers.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160522/0aa79e59/attachment.sig>

From u.kleine-koenig at pengutronix.de  Sun May 22 13:16:15 2016
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Sun, 22 May 2016 22:16:15 +0200
Subject: [PATCH 0096/1529] Fix typo
In-Reply-To: <20160521114912.4331-1-andrea.gelmini@gelma.net>
References: <20160521114912.4331-1-andrea.gelmini@gelma.net>
Message-ID: <20160522201615.GD23704@pengutronix.de>

Hello Andrea,

On Sat, May 21, 2016 at 01:49:12PM +0200, Andrea Gelmini wrote:
> Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
> ---
>  arch/arm/mach-imx/hardware.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h
> index d737f95..026441c 100644
> --- a/arch/arm/mach-imx/hardware.h
> +++ b/arch/arm/mach-imx/hardware.h
> @@ -121,7 +121,7 @@
>  	.type = _type,							\
>  }
>  
> -/* There's a off-by-one betweem the gpio bank number and the gpiochip */
> +/* There's a off-by-one between the gpio bank number and the gpiochip */

maybe fix s/a/an/ in the same go? And I'd suggest to squash your patches
by directory (here: arch/arm/mach-imx or even arch/arm/mach-*) and add a
commit log that could for example mention the tool you used to find and
fix these typos.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From christopher.spinrath at rwth-aachen.de  Sun May 22 15:47:37 2016
From: christopher.spinrath at rwth-aachen.de (christopher.spinrath at rwth-aachen.de)
Date: Mon, 23 May 2016 00:47:37 +0200
Subject: [PATCH 1/2] ARM: dts: imx6q: extend support for the cm-fx6
Message-ID: <709d6b3d522f4fcb8112830e0426dbb3@rwthex-s1-b.rwth-ad.de>

From: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>

The cm-fx6 module has an on-board spi-flash chip for its firmware, an
eeprom (containing e.g. the mac address of the on-board Ethernet),
a sata port, a pcie controller, an USB hub, and an USB otg port.
Enable support for them. In addition, enable syscon poweroff support.

Signed-off-by: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>
---
 arch/arm/boot/dts/imx6q-cm-fx6.dts | 136 +++++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git a/arch/arm/boot/dts/imx6q-cm-fx6.dts b/arch/arm/boot/dts/imx6q-cm-fx6.dts
index 99b46f8..f4fc22e 100644
--- a/arch/arm/boot/dts/imx6q-cm-fx6.dts
+++ b/arch/arm/boot/dts/imx6q-cm-fx6.dts
@@ -31,6 +31,61 @@
 			linux,default-trigger = "heartbeat";
 		};
 	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_usb_otg_vbus: usb_otg_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
+
+		reg_usb_h1_vbus: usb_h1_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb_h1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio7 8 0>;
+			enable-active-high;
+		};
+	};
+};
+
+&ecspi1 {
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	status = "okay";
+
+	flash: m25p80 at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,m25p", "jedec,spi-nor";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+
+		partition at 0 {
+			label = "uboot";
+			reg = <0x0 0xc0000>;
+		};
+
+		partition at c0000 {
+			label = "uboot environment";
+			reg = <0xc0000 0x40000>;
+		};
+
+		partition at 100000 {
+			label = "reserved";
+			reg = <0x100000 0x100000>;
+		};
+	};
 };
 
 &fec {
@@ -46,8 +101,31 @@
 	status = "okay";
 };
 
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+	clock-frequency = <100000>;
+
+	eeprom at 50 {
+		compatible = "at24,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+};
+
 &iomuxc {
 	imx6q-cm-fx6 {
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		 0x100b1
+				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		 0x100b1
+				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		 0x100b1
+				MX6QDL_PAD_EIM_EB2__GPIO2_IO30		0x100b1
+				MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x100b1
+			>;
+		};
+
 		pinctrl_enet: enetgrp {
 			fsl,pins = <
 				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
@@ -91,17 +169,75 @@
 			>;
 		};
 
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+			>;
+		};
+
+		pinctrl_pcie: pciegrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000
+				MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x80000000
+			>;
+		};
+
 		pinctrl_uart4: uart4grp {
 			fsl,pins = <
 				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
 				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
 			>;
 		};
+
+		pinctrl_usbh1: usbh1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x80000000
+			>;
+		};
+
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
+			>;
+		};
 	};
 };
 
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 26 0>;
+	power-on-gpio = <&gpio2 24 0>;
+	status = "okay";
+};
+
+&sata {
+	status = "okay";
+};
+
+&snvs_poweroff {
+	status = "okay";
+};
+
 &uart4 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart4>;
 	status = "okay";
 };
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh1>;
+	status = "okay";
+};
-- 
2.8.2



From christopher.spinrath at rwth-aachen.de  Sun May 22 15:47:38 2016
From: christopher.spinrath at rwth-aachen.de (christopher.spinrath at rwth-aachen.de)
Date: Mon, 23 May 2016 00:47:38 +0200
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
Message-ID: <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>

From: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>

The CompuLab Utilite Pro is a miniature fanless desktop pc based on
the i.MX6 Quad powered cm-fx6 module. It features two serial ports,
USB OTG, 4x USB, analog audio and S/PDIF, 2x Gb Ethernet, HDMI and
DVI ports, an on-board 32GB SSD, a mmc slot, and on-board wifi/bt.

Add initial support for it including USB, Ethernet (both ports), sata
and HDMI support.

Signed-off-by: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>
---
 arch/arm/boot/dts/Makefile              |   1 +
 arch/arm/boot/dts/imx6q-utilite-pro.dts | 128 ++++++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx6q-utilite-pro.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 515a428..287044c 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -369,6 +369,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6q-tx6q-1110.dtb \
 	imx6q-tx6q-11x0-mb7.dtb \
 	imx6q-udoo.dtb \
+	imx6q-utilite-pro.dtb \
 	imx6q-wandboard.dtb \
 	imx6q-wandboard-revb1.dtb \
 	imx6qp-nitrogen6_max.dtb \
diff --git a/arch/arm/boot/dts/imx6q-utilite-pro.dts b/arch/arm/boot/dts/imx6q-utilite-pro.dts
new file mode 100644
index 0000000..bcd8e0d
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-utilite-pro.dts
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2016 Christopher Spinrath
+ * Copyright 2013 CompuLab Ltd.
+ *
+ * Based on the GPLv2 licensed devicetree distributed with the vendor
+ * kernel for the Utilite Pro:
+ *	Copyright 2013 CompuLab Ltd.
+ *	Author: Valentin Raevsky <valentin at compulab.co.il>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx6q-cm-fx6.dts"
+
+/ {
+	model = "CompuLab Utilite Pro";
+	compatible = "compulab,utilite-pro", "compulab,cm-fx6", "fsl,imx6q";
+
+	aliases {
+		ethernet1 = &eth1;
+		rtc0 = &em3027;
+		rtc1 = &snvs_rtc;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		power {
+			label = "Power Button";
+			gpios = <&gpio1 29 1>;
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+	};
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c2>;
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	eeprom at 50 {
+		compatible = "at24,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	em3027: rtc at 56 {
+		compatible = "emmicro,em3027";
+		reg = <0x56>;
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				/* power button */
+				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
+			>;
+		};
+	};
+
+	imx6q-utilite-pro {
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+			>;
+		};
+
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+			>;
+		};
+
+		pinctrl_uart2: uart2grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_7__UART2_TX_DATA 0x1b0b1
+				MX6QDL_PAD_GPIO_8__UART2_RX_DATA 0x1b0b1
+				MX6QDL_PAD_SD4_DAT5__UART2_RTS_B 0x1b0b1
+				MX6QDL_PAD_SD4_DAT6__UART2_CTS_B 0x1b0b1
+			>;
+		};
+	};
+};
+
+&pcie {
+	pcie at 0,0 {
+		reg = <0x000000 0 0 0 0>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+
+		/* non-removable i211 ethernet card */
+		eth1: intel,i211 at pcie0,0 {
+			reg = <0x010000 0 0 0 0>;
+		};
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	fsl,uart-has-rtscts;
+	dma-names = "rx", "tx";
+	dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
+	status = "okay";
+};
-- 
2.8.2



From horms+renesas at verge.net.au  Sun May 22 18:28:24 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Mon, 23 May 2016 10:28:24 +0900
Subject: [PATCH v2 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC support
In-Reply-To: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>
References: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1463966906-15129-2-git-send-email-horms+renesas@verge.net.au>

Basic support for the Gen 3 R-Car M3-W SoC.

Based on work for the r8a7795 and r8a7796 SoCs by
Takeshi Kihara, Dirk Behme and Geert Uytterhoeven.

Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
---
v2
* As suggested by Geert Uytterhoeven
  - Move L2_CA57 node under cpus node and include reg property
  - Omit status = "disabled" from scif_clk node
---
 Documentation/devicetree/bindings/arm/shmobile.txt |   4 +
 arch/arm64/Kconfig.platforms                       |   6 ++
 arch/arm64/boot/dts/renesas/r8a7796.dtsi           | 120 +++++++++++++++++++++
 3 files changed, 130 insertions(+)
 create mode 100644 arch/arm64/boot/dts/renesas/r8a7796.dtsi

diff --git a/Documentation/devicetree/bindings/arm/shmobile.txt b/Documentation/devicetree/bindings/arm/shmobile.txt
index 9cf67e48f222..d5ed554830d7 100644
--- a/Documentation/devicetree/bindings/arm/shmobile.txt
+++ b/Documentation/devicetree/bindings/arm/shmobile.txt
@@ -29,6 +29,8 @@ SoCs:
     compatible = "renesas,r8a7794"
   - R-Car H3 (R8A77950)
     compatible = "renesas,r8a7795"
+  - R-Car M3-W (R8A77960)
+    compatible = "renesas,r8a7796"
 
 
 Boards:
@@ -61,5 +63,7 @@ Boards:
     compatible = "renesas,porter", "renesas,r8a7791"
   - Salvator-X (RTP0RC7795SIPB0010S)
     compatible = "renesas,salvator-x", "renesas,r8a7795";
+  - Salvator-X
+    compatible = "renesas,salvator-x", "renesas,r8a7796";
   - SILK (RTP0RC7794LCB00011S)
     compatible = "renesas,silk", "renesas,r8a7794"
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index efa77c146415..16d8d26839ea 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -114,6 +114,12 @@ config ARCH_R8A7795
 	help
 	  This enables support for the Renesas R-Car H3 SoC.
 
+config ARCH_R8A7796
+	bool "Renesas R-Car M3-W SoC Platform"
+	depends on ARCH_RENESAS
+	help
+	  This enables support for the Renesas R-Car M3-W SoC.
+
 config ARCH_STRATIX10
 	bool "Altera's Stratix 10 SoCFPGA Family"
 	help
diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
new file mode 100644
index 000000000000..43d42a55119c
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
@@ -0,0 +1,120 @@
+/*
+ * Device Tree Source for the r8a7796 SoC
+ *
+ * Copyright (C) 2016 Renesas Electronics Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/clock/r8a7796-cpg-mssr.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "renesas,r8a7796";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* 1 core only at this point */
+		a57_0: cpu at 0 {
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x0>;
+			device_type = "cpu";
+			next-level-cache = <&L2_CA57>;
+			enable-method = "psci";
+		};
+
+		L2_CA57: cache-controller at 0 {
+			compatible = "cache";
+			reg = <0>;
+			cache-unified;
+			cache-level = <2>;
+		};
+	};
+
+	extal_clk: extal {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	extalr_clk: extalr {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	/* External SCIF clock - to be overridden by boards that provide it */
+	scif_clk: scif {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gic: interrupt-controller at 0xf1010000 {
+			compatible = "arm,gic-400";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0x0 0xf1010000 0 0x1000>,
+			      <0x0 0xf1020000 0 0x20000>,
+			      <0x0 0xf1040000 0 0x20000>,
+			      <0x0 0xf1060000 0 0x20000>;
+			interrupts = <GIC_PPI 9
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+		};
+
+		timer {
+			compatible = "arm,armv8-timer";
+			interrupts = <GIC_PPI 13
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 14
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 11
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 10
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
+		};
+
+		cpg: clock-controller at e6150000 {
+			compatible = "renesas,r8a7796-cpg-mssr";
+			reg = <0 0xe6150000 0 0x1000>;
+			clocks = <&extal_clk>, <&extalr_clk>;
+			clock-names = "extal", "extalr";
+			#clock-cells = <2>;
+			#power-domain-cells = <0>;
+		};
+
+		scif2: serial at e6e88000 {
+			compatible = "renesas,scif-r8a7796",
+				     "renesas,rcar-gen3-scif", "renesas,scif";
+			reg = <0 0xe6e88000 0 64>;
+			interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 310>,
+				 <&cpg CPG_CORE R8A7796_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			power-domains = <&cpg>;
+			status = "disabled";
+		};
+	};
+};
-- 
2.1.4



From horms+renesas at verge.net.au  Sun May 22 18:28:23 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Mon, 23 May 2016 10:28:23 +0900
Subject: [PATCH v2 0/3] arm64: Add Renesas R8A7796 SoC support
Message-ID: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>

Hi,

this short series aims to add basic support for the
Gen 3 R-Car M3-W (r8a7796) SoC.

It has few bells and whistles but is sufficient to bring up
an r8a7795/salvator-x. I have provided a boot-log at the bottom
of this email in case it is of interest.


Dependency:

"[PATCH 0/4] clk: renesas: cpg-mssr: Add support for R-Car M3-W"


Availability:

In order to aid review this series, its dependency (above)
and the related patch "serial: sh-sci: Document SoC specific bindings for
r8a7796", which has been posted separately, are available at:

git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git topic/r8a7796-v2

To be entirely clear, at the time of writing I have _not_ queued up this
series for mainline.


Changes since v1:
* Move L2_CA57 node under cpus node and include reg property
* Omit status = "disabled" from scif_clk node
* Accumulate Ack and Reviewed-by tags


Simon Horman (1):
  arm64: dts: r8a7796: Add Renesas R8A7796 SoC support

Takeshi Kihara (2):
  arm64: dts: salvator-x: add Salvator-X board on R8A7796 SoC
  arm64: defconfig: enable Renesas R8A7796 SoC

 Documentation/devicetree/bindings/arm/shmobile.txt |   4 +
 arch/arm64/Kconfig.platforms                       |   6 ++
 arch/arm64/boot/dts/renesas/Makefile               |   1 +
 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts |  45 ++++++++
 arch/arm64/boot/dts/renesas/r8a7796.dtsi           | 120 +++++++++++++++++++++
 arch/arm64/configs/defconfig                       |   1 +
 6 files changed, 177 insertions(+)
 create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
 create mode 100644 arch/arm64/boot/dts/renesas/r8a7796.dtsi


Boot Log:

The following boot log was generated by booting this patch set,
in its form in the topic/r8a7796 branch. It was compiled using
the ARM64 defconfig with initrd enabled to provide a working userspace.


[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.6.0-rc1+ (horms at ayumi.isobedori.kobe.vergenet.net) (gcc version 4.8.5 (Linaro GCC 4.8-2015.06) ) #147 SMP PREEMPT Mon May 23 10:16:34 JST 2016
[    0.000000] Boot CPU: AArch64 Processor [411fd073]
[    0.000000] debug: ignoring loglevel setting.
[    0.000000] efi: Getting EFI parameters from FDT:
[    0.000000] efi: UEFI not found.
[    0.000000] cma: Reserved 16 MiB at 0x00000000bf000000
[    0.000000] On node 0 totalpages: 1015808
[    0.000000]   DMA zone: 7680 pages used for memmap
[    0.000000]   DMA zone: 0 pages reserved
[    0.000000]   DMA zone: 491520 pages, LIFO batch:31
[    0.000000]   Normal zone: 8192 pages used for memmap
[    0.000000]   Normal zone: 524288 pages, LIFO batch:31
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv1.0 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: Trusted OS migration not required
[    0.000000] percpu: Embedded 20 pages/cpu @ffffffc63ffad000 s43008 r8192 d30720 u81920
[    0.000000] pcpu-alloc: s43008 r8192 d30720 u81920 alloc=20*4096
[    0.000000] pcpu-alloc: [0] 0 
[    0.000000] Detected PIPT I-cache on CPU0
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 999936
[    0.000000] Kernel command line: ignore_loglevel rw root=/dev/nfs ip=dhcp nfsroot=10.3.3.135:/srv/nfs/salvator-x-arm64
[    0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes)
[    0.000000] Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes)
[    0.000000] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes)
[    0.000000] software IO TLB [mem 0xbafff000-0xbefff000] (64MB) mapped at [ffffffc07afff000-ffffffc07effefff]
[    0.000000] Memory: 3896020K/4063232K available (6796K kernel code, 619K rwdata, 2880K rodata, 2256K init, 241K bss, 150828K reserved, 16384K cma-reserved)
[    0.000000] Virtual kernel memory layout:
[    0.000000]     modules : 0xffffff8000000000 - 0xffffff8008000000   (   128 MB)
[    0.000000]     vmalloc : 0xffffff8008000000 - 0xffffffbdbfff0000   (   246 GB)
[    0.000000]       .text : 0xffffff8008080000 - 0xffffff8008721000   (  6788 KB)
[    0.000000]     .rodata : 0xffffff8008721000 - 0xffffff80089f5000   (  2896 KB)
[    0.000000]       .init : 0xffffff80089f5000 - 0xffffff8008c29000   (  2256 KB)
[    0.000000]       .data : 0xffffff8008c29000 - 0xffffff8008cc3e00   (   620 KB)
[    0.000000]     vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000   (     8 GB maximum)
[    0.000000]               0xffffffbdc0200000 - 0xffffffbdd9000000   (   398 MB actual)
[    0.000000]     fixed   : 0xffffffbffe7fd000 - 0xffffffbffec00000   (  4108 KB)
[    0.000000]     PCI I/O : 0xffffffbffee00000 - 0xffffffbfffe00000   (    16 MB)
[    0.000000]     memory  : 0xffffffc008000000 - 0xffffffc640000000   ( 25472 MB)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] Preemptible hierarchical RCU implementation.
[    0.000000]  Build-time adjustment of leaf fanout to 64.
[    0.000000]  RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=1.
[    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=64, nr_cpu_ids=1
[    0.000000] NR_IRQS:64 nr_irqs:64 0
[    0.000000] Architected cp15 timer(s) running at 8.33MHz (virt).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1ec02923e, max_idle_ns: 440795202125 ns
[    0.000003] sched_clock: 56 bits at 8MHz, resolution 120ns, wraps every 2199023255496ns
[    0.000076] Console: colour dummy device 80x25
[    0.000378] console [tty0] enabled
[    0.000400] Calibrating delay loop (skipped), value calculated using timer frequency.. 16.66 BogoMIPS (lpj=33333)
[    0.000418] pid_max: default: 32768 minimum: 301
[    0.000460] Security Framework initialized
[    0.000495] Mount-cache hash table entries: 8192 (order: 4, 65536 bytes)
[    0.000506] Mountpoint-cache hash table entries: 8192 (order: 4, 65536 bytes)
[    0.001210] ASID allocator initialised with 65536 entries
[    0.001734] EFI services will not be available.
[    0.001842] Brought up 1 CPUs
[    0.001852] SMP: Total of 1 processors activated.
[    0.001866] CPU: All CPU(s) started at EL1
[    0.002633] devtmpfs: initialized
[    0.003209] DMI not present or invalid.
[    0.003405] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.003784] pinctrl core: initialized pinctrl subsystem
[    0.004583] NET: Registered protocol family 16
[    0.016073] cpuidle: using governor menu
[    0.016219] vdso: 2 pages (1 code @ ffffff8008727000, 1 data @ ffffff8008c30000)
[    0.016260] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[    0.016757] DMA: preallocated 256 KiB pool for atomic allocations
[    0.016913] Serial: AMBA PL011 UART driver
[    0.037039] HugeTLB registered 2 MB page size, pre-allocated 0 pages
[    0.048850] vgaarb: loaded
[    0.049050] SCSI subsystem initialized
[    0.052301] libata version 3.00 loaded.
[    0.052495] usbcore: registered new interface driver usbfs
[    0.052532] usbcore: registered new interface driver hub
[    0.052568] usbcore: registered new device driver usb
[    0.052650] pps_core: LinuxPPS API ver. 1 registered
[    0.052659] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti at linux.it>
[    0.052683] PTP clock support registered
[    0.052760] dmi: Firmware registration failed.
[    0.053053] Advanced Linux Sound Architecture Driver Initialized.
[    0.054018] clocksource: Switched to clocksource arch_sys_counter
[    0.054161] VFS: Disk quotas dquot_6.6.0
[    0.054205] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[    0.064167] NET: Registered protocol family 2
[    0.064575] TCP established hash table entries: 32768 (order: 6, 262144 bytes)
[    0.064691] TCP bind hash table entries: 32768 (order: 7, 524288 bytes)
[    0.065136] TCP: Hash tables configured (established 32768 bind 32768)
[    0.065242] UDP hash table entries: 2048 (order: 4, 65536 bytes)
[    0.065275] UDP-Lite hash table entries: 2048 (order: 4, 65536 bytes)
[    0.065440] NET: Registered protocol family 1
[    0.065886] RPC: Registered named UNIX socket transport module.
[    0.065904] RPC: Registered udp transport module.
[    0.065911] RPC: Registered tcp transport module.
[    0.065918] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.065946] PCI: CLS 0 bytes, default 128
[    0.112788] kvm [1]: HYP mode not available
[    0.114548] futex hash table entries: 256 (order: 3, 32768 bytes)
[    0.114628] audit: initializing netlink subsys (disabled)
[    0.114674] audit: type=2000 audit(0.111:1): initialized
[    0.119392] workingset: timestamp_bits=44 max_order=20 bucket_order=0
[    0.128860] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.130513] NFS: Registering the id_resolver key type
[    0.130559] Key type id_resolver registered
[    0.130567] Key type id_legacy registered
[    0.130774] fuse init (API version 7.24)
[    0.131222] 9p: Installing v9fs 9p2000 file system support
[    0.132858] io scheduler noop registered
[    0.133031] io scheduler cfq registered (default)
[    0.135826] xenfs: not registering filesystem on non-xen platform
[    0.141149] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    0.143084] SuperH (H)SCI(F) driver initialized
[    0.143265] e6e88000.serial: ttySC0 at MMIO 0xe6e88000 (irq = 6, base_baud = 0) is a scif
[    0.812694] console [ttySC0] enabled
[    0.816631] msm_serial: driver initialized
[    0.848929] loop: module loaded
[    0.853563] tun: Universal TUN/TAP device driver, 1.6
[    0.859288] tun: (C) 1999-2004 Max Krasnyansky <maxk at qualcomm.com>
[    0.865887] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[    0.871853] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    0.878013] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.3.0-k
[    0.885054] igb: Copyright (c) 2007-2014 Intel Corporation.
[    0.890695] igbvf: Intel(R) Gigabit Virtual Function Network Driver - version 2.0.2-k
[    0.898560] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
[    0.904542] sky2: driver version 1.30
[    0.908582] VFIO - User Level meta-driver version: 0.3
[    0.916099] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    0.922849] ehci-pci: EHCI PCI platform driver
[    0.927400] ehci-platform: EHCI generic platform driver
[    0.932833] ehci-msm: Qualcomm On-Chip EHCI Host Controller
[    0.938493] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    0.944738] ohci-pci: OHCI PCI platform driver
[    0.949248] ohci-platform: OHCI generic platform driver
[    0.954723] usbcore: registered new interface driver usb-storage
[    0.961487] mousedev: PS/2 mouse device common for all mice
[    0.967788] i2c /dev entries driver
[    0.972228] sdhci: Secure Digital Host Controller Interface driver
[    0.978839] sdhci: Copyright(c) Pierre Ossman
[    0.983343] Synopsys Designware Multimedia Card Interface Driver
[    0.989639] sdhci-pltfm: SDHCI platform and OF driver helper
[    0.995574] ledtrig-cpu: registered to indicate activity on CPUs
[    1.002270] usbcore: registered new interface driver usbhid
[    1.008128] usbhid: USB HID core driver
[    1.013169] NET: Registered protocol family 17
[    1.018115] 9pnet: Installing 9P2000 support
[    1.022521] Key type dns_resolver registered
[    1.027443] registered taskstats version 1
[    1.031986] hctosys: unable to open rtc device (rtc0)
[   13.085570] ALSA device list:
[   13.088549]   No soundcards found.
[   13.093446] Freeing unused kernel memory: 2256K (ffffff80089f5000 - ffffff8008c29000)


boot (Linux 4.6.0-rc1+, BusyBox v1.16.0.git, kexec-tools 2.0.1-git)
/ # cat /proc/interrupts 
           CPU0       
  3:        252     GIC-0  27 Edge      arch_timer
  6:         75     GIC-0 196 Level     e6e88000.serial:mux
IPI0:         0       Rescheduling interrupts
IPI1:         0       Function call interrupts
IPI2:         0       CPU stop interrupts
IPI3:         0       Timer broadcast interrupts
IPI4:         0       IRQ work interrupts
IPI5:         0       CPU wake-up interrupts
Err:          0


From horms+renesas at verge.net.au  Sun May 22 18:28:25 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Mon, 23 May 2016 10:28:25 +0900
Subject: [PATCH v2 2/3] arm64: dts: salvator-x: add Salvator-X board on
 R8A7796 SoC
In-Reply-To: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>
References: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1463966906-15129-3-git-send-email-horms+renesas@verge.net.au>

From: Takeshi Kihara <takeshi.kihara.df at renesas.com>

This patch adds initial board support for R8A7796 Salvator-X.

Signed-off-by: Takeshi Kihara <takeshi.kihara.df at renesas.com>
Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
--
v2 [Simon Horman]
* Added Reviewed-by tag from Geert Uytterhoeven

v1 [Simon Horman]
* Drop use of pfc, that can be added once pfc support is present in mainline
* Set size of memory (bank 0) to 2GiB instead of 1GiB
* Omit scif0
* Add scif_clk, from patch by Hiromitsu Yamasaki

v0 [Takeshi Kihara]
---
 arch/arm64/boot/dts/renesas/Makefile               |  1 +
 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts | 45 ++++++++++++++++++++++
 2 files changed, 46 insertions(+)
 create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts

diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
index 9ce1890a650e..17139f7003a6 100644
--- a/arch/arm64/boot/dts/renesas/Makefile
+++ b/arch/arm64/boot/dts/renesas/Makefile
@@ -1,4 +1,5 @@
 dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x.dtb
+dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb
 
 always		:= $(dtb-y)
 clean-files	:= *.dtb
diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
new file mode 100644
index 000000000000..9c52613fb88c
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
@@ -0,0 +1,45 @@
+/*
+ * Device Tree Source for the Salvator-X board
+ *
+ * Copyright (C) 2016 Renesas Electronics Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+#include "r8a7796.dtsi"
+
+/ {
+	model = "Renesas Salvator-X board based on r8a7796";
+	compatible = "renesas,salvator-x", "renesas,r8a7796";
+
+	aliases {
+		serial0 = &scif2;
+	};
+
+	chosen {
+		bootargs = "ignore_loglevel";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory at 48000000 {
+		device_type = "memory";
+		/* first 128MB is reserved for secure area. */
+		reg = <0x0 0x48000000 0x0 0x78000000>;
+	};
+};
+
+&extal_clk {
+	clock-frequency = <16666666>;
+};
+
+&scif2 {
+	status = "okay";
+};
+
+&scif_clk {
+	clock-frequency = <14745600>;
+	status = "okay";
+};
-- 
2.1.4



From horms+renesas at verge.net.au  Sun May 22 18:28:26 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Mon, 23 May 2016 10:28:26 +0900
Subject: [PATCH v2 3/3] arm64: defconfig: enable Renesas R8A7796 SoC
In-Reply-To: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>
References: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1463966906-15129-4-git-send-email-horms+renesas@verge.net.au>

From: Takeshi Kihara <takeshi.kihara.df at renesas.com>

This patch enables the Renesas R8A7796 SoC in the arm64 defconfig.

Signed-off-by: Takeshi Kihara <takeshi.kihara.df at renesas.com>
Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
Acked-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
v2 [Simon Horman]
* Added Acked-by tag from Geert Uytterhoeven
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index f70505186820..0d37fa5a59aa 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -44,6 +44,7 @@ CONFIG_ARCH_ROCKCHIP=y
 CONFIG_ARCH_SEATTLE=y
 CONFIG_ARCH_RENESAS=y
 CONFIG_ARCH_R8A7795=y
+CONFIG_ARCH_R8A7796=y
 CONFIG_ARCH_STRATIX10=y
 CONFIG_ARCH_TEGRA=y
 CONFIG_ARCH_SPRD=y
-- 
2.1.4



From architt at codeaurora.org  Sun May 22 19:53:53 2016
From: architt at codeaurora.org (Archit Taneja)
Date: Mon, 23 May 2016 08:23:53 +0530
Subject: [PATCH V5 0/7] iommu/msm: Add DT adaptation and generic bindings
 support
In-Reply-To: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <574270C1.9030308@codeaurora.org>



On 05/20/2016 04:24 PM, Sricharan R wrote:
> The msm_iommu.c driver currently works based on platform data.
> A single master device can be connected to more than one iommu and multiple
> contexts in each of the iommu. This association between master and iommus was
> represented from platform data using parent/child devices. The master drivers
> were responsible for attaching all of the iommus/context to a domain. Now the
> platform data support is removed and DT support is added. The master/iommus are
> added through generic iommu bindings.
>
> This is essentially rework of the patch posted earlier by
> Rob Clark <robdclark at gmail.com>. This series folds the changes in to the
> existing driver with the addition of generic bindings.
>
>          http://www.spinics.net/lists/linux-arm-msm/msg10077.html
>
> Tested this series on ifc6410 board.
>
> [V5] Changed the compatible binding name as per comments, added comments
>       for usage of barriers in patch 6.
>
> [V4] Addressed comments for making the iommu compatible binding more soc
>       specific and updated the documentation for the iommu clocks.
>
> [V3] Addressed comments to correct the usage
>       of the #iommu-cells binding, improve the flush_iotlb_range function,
>       added a new patch to use writel_relaxed for register access and split
>       up the documentation patch.
>
> [V2] Adapted the driver to use generic ARMV7S short descriptor pagetable ops
>       and addressed comments.
>
> [V1]
>     https://lists.linuxfoundation.org/pipermail/iommu/2015-August/014074.html

Tested with the drm/msm driver as an iommu client on IFC6410 board
(APQ8064).

Tested-by: Archit Taneja <architt at codeaurora.org>

>
> Sricharan R (7):
>    iommu/msm: Add DT adaptation
>    documentation: iommu: Add bindings for msm,iommu-v0 ip
>    iommu/msm: Move the contents from msm_iommu_dev.c to msm_iommu.c
>    iommu/msm: Add support for generic master bindings
>    iommu/msm: use generic ARMV7S short descriptor pagetable ops
>    iommu/msm: Use writel_relaxed and add a barrier
>    iommu/msm: Remove driver BROKEN
>
>   .../devicetree/bindings/iommu/msm,iommu-v0.txt     |  64 ++
>   drivers/iommu/Kconfig                              |   2 +-
>   drivers/iommu/Makefile                             |   2 +-
>   drivers/iommu/msm_iommu.c                          | 885 +++++++++++----------
>   drivers/iommu/msm_iommu.h                          |  73 +-
>   drivers/iommu/msm_iommu_dev.c                      | 381 ---------
>   drivers/iommu/msm_iommu_hw-8xxx.h                  | 109 +--
>   7 files changed, 636 insertions(+), 880 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
>   delete mode 100644 drivers/iommu/msm_iommu_dev.c
>

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum, hosted by The Linux Foundation


From zhengxing at rock-chips.com  Sun May 22 20:11:48 2016
From: zhengxing at rock-chips.com (Xing Zheng)
Date: Mon, 23 May 2016 11:11:48 +0800
Subject: [PATCH] ASoC: rockchip: Add machine driver for MAX98357A/RT5514/DA7219
Message-ID: <1463973108-8699-1-git-send-email-zhengxing@rock-chips.com>

There are multi codec devices on the RK3399 platform, we can use
this patch support and control these codecs.

Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
---

 .../sound/rockchip-max98357a-rt5514-da7219.txt     |   15 +
 sound/soc/rockchip/Kconfig                         |   11 +
 sound/soc/rockchip/Makefile                        |    2 +
 .../rockchip/rockchip_max98357a_rt5514_da7219.c    |  339 ++++++++++++++++++++
 4 files changed, 367 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
 create mode 100644 sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c

diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt b/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
new file mode 100644
index 0000000..5928384
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
@@ -0,0 +1,15 @@
+ROCKCHIP with MAX98357A/RT5514/DA7219 codecs
+
+Required properties:
+- compatible: "rockchip,rockchip-sound"
+- rockchip,cpu: The phandle of the Rockchip I2S controller that's
+  connected to the codecs
+- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs
+
+Example:
+
+sound {
+	compatible = "rockchip,rockchip-sound";
+	rockchip,cpu = <&i2s0 &i2s0 &i2s1>;
+	rockchip,codec = <&max98357a &headsetcodec &codec>;
+};
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index f1e0c70..d02aa94 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -41,3 +41,14 @@ config SND_SOC_ROCKCHIP_RT5645
 	help
 	  Say Y or M here if you want to add support for SoC audio on Rockchip
 	  boards using the RT5645/RT5650 codec, such as Veyron.
+
+config SND_SOC_ROCKCHIP_MAX98357A_RT5514_DA7219
+	tristate "ASoC support for Rockchip boards using the MAX98357A/RT5514/DA7219"
+	depends on SND_SOC_ROCKCHIP && GPIOLIB
+	select SND_SOC_ROCKCHIP_I2S
+	select SND_SOC_MAX98357A
+	select SND_SOC_RT5514
+	select SND_SOC_DA7219
+	help
+	  Say Y or M here if you want to add support for SoC audio on Rockchip
+	  boards using the MAX98357A/RT5514/DA7219.
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
index c0bf560..ca97489 100644
--- a/sound/soc/rockchip/Makefile
+++ b/sound/soc/rockchip/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o
 
 snd-soc-rockchip-max98090-objs := rockchip_max98090.o
 snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o
+snd-soc-rockchip-max98357a-rt5514-da7219-objs := rockchip_max98357a_rt5514_da7219.o
 
 obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o
+obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98357A_RT5514_DA7219) += snd-soc-rockchip-max98357a-rt5514-da7219.o
diff --git a/sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c b/sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c
new file mode 100644
index 0000000..50c0d35
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c
@@ -0,0 +1,339 @@
+/*
+ * Rockchip machine ASoC driver for boards using MAX98357A/RT5514/DA7219
+ *
+ * Copyright (c) 2016, ROCKCHIP CORPORATION.  All rights reserved.
+ *
+ * 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 <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include "rockchip_i2s.h"
+#include "../codecs/da7219.h"
+#include "../codecs/da7219-aad.h"
+#include "../codecs/rt5514.h"
+
+#define DRV_NAME "rockchip-sound"
+
+static struct snd_soc_jack rockchip_sound_jack;
+
+static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphones", NULL),
+	SND_SOC_DAPM_SPK("Speakers", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Int Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route rockchip_dapm_routes[] = {
+	/* Input Lines */
+	{"MIC", NULL, "Headset Mic"},
+	{"DMIC1L", NULL, "Int Mic"},
+	{"DMIC1R", NULL, "Int Mic"},
+
+	/* Output Lines */
+	{"Headphones", NULL, "HPL"},
+	{"Headphones", NULL, "HPR"},
+	{"Speakers", NULL, "Speakers"},
+};
+
+static const struct snd_kcontrol_new rockchip_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphones"),
+	SOC_DAPM_PIN_SWITCH("Speakers"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Int Mic"),
+};
+
+static int rockchip_sound_max98357a_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_dapm_context *dapm = &rtd->card->dapm;
+	unsigned int mclk;
+	int ret;
+
+	switch (params_rate(params)) {
+	case 8000:
+	case 16000:
+	case 48000:
+	case 96000:
+		mclk = 12288000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0);
+	if (ret) {
+		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
+				__func__, mclk, ret);
+		return ret;
+	}
+
+	snd_soc_dapm_disable_pin(dapm, "Headphones");
+	snd_soc_dapm_enable_pin(dapm, "Speakers");
+	snd_soc_dapm_sync(dapm);
+
+	return 0;
+}
+
+static int rockchip_sound_rt5514_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;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	unsigned int mclk;
+	int ret;
+
+	switch (params_rate(params)) {
+	case 8000:
+	case 16000:
+	case 32000:
+	case 48000:
+	case 96000:
+		mclk = 12288000;
+		break;
+	case 11025:
+	case 22050:
+	case 44100:
+		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(rtd->card->dev, "Can't set cpu clock out %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK,
+				     mclk, SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
+				__func__, params_rate(params) * 512, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rockchip_sound_da7219_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;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dapm_context *dapm = &rtd->card->dapm;
+	int mclk, ret;
+
+	switch (params_rate(params)) {
+	case 8000:
+	case 16000:
+	case 32000:
+	case 48000:
+	case 96000:
+		mclk = 12288000;
+		break;
+	case 11025:
+	case 22050:
+	case 44100:
+		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(codec_dai->dev, "Can't set cpu clock out %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
+				     SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		dev_err(codec_dai->dev, "Can't set codec clock in %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
+	if (ret < 0) {
+		dev_err(codec_dai->dev, "Can't set pll sysclk mclk %d\n", ret);
+		return ret;
+	}
+
+	snd_soc_dapm_disable_pin(dapm, "Speakers");
+	snd_soc_dapm_enable_pin(dapm, "Headphones");
+	snd_soc_dapm_sync(dapm);
+
+	return 0;
+}
+
+static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec_dais[0]->codec;
+	int ret;
+
+	/* Enable Headset and 4 Buttons Jack detection */
+	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
+				    SND_JACK_HEADSET |
+				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
+				    &rockchip_sound_jack, NULL, 0);
+
+	if (ret) {
+		dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
+		return ret;
+	}
+
+	da7219_aad_jack_det(codec, &rockchip_sound_jack);
+
+	return 0;
+}
+
+static struct snd_soc_ops rockchip_sound_max98357a_ops = {
+	.hw_params = rockchip_sound_max98357a_hw_params,
+};
+
+static struct snd_soc_ops rockchip_sound_rt5514_ops = {
+	.hw_params = rockchip_sound_rt5514_hw_params,
+};
+
+static struct snd_soc_ops rockchip_sound_da7219_ops = {
+	.hw_params = rockchip_sound_da7219_hw_params,
+};
+
+enum {
+	DAILINK_MAX98357A,
+	DAILINK_RT5514,
+	DAILINK_DA7219,
+};
+
+static struct snd_soc_dai_link rockchip_dailinks[] = {
+	[DAILINK_MAX98357A] = {
+		.name = "MAX98357A",
+		.stream_name = "MAX98357A PCM",
+		.codec_dai_name = "HiFi",
+		.ops = &rockchip_sound_max98357a_ops,
+		/* set max98357a as slave */
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+	[DAILINK_RT5514] = {
+		.name = "RT5514",
+		.stream_name = "RT5514 PCM",
+		.codec_dai_name = "rt5514-aif1",
+		.ops = &rockchip_sound_rt5514_ops,
+		/* set rt5514 as slave */
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+	[DAILINK_DA7219] = {
+		.name = "DA7219",
+		.stream_name = "DA7219 PCM",
+		.codec_dai_name = "da7219-hifi",
+		.init = rockchip_sound_da7219_init,
+		.ops = &rockchip_sound_da7219_ops,
+		/* set da7219 as slave */
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+};
+
+static struct snd_soc_card rockchip_sound_card = {
+	.name = "rockchip-sound",
+	.owner = THIS_MODULE,
+	.dai_link = rockchip_dailinks,
+	.num_links =  ARRAY_SIZE(rockchip_dailinks),
+	.dapm_widgets = rockchip_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
+	.dapm_routes = rockchip_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes),
+	.controls = rockchip_controls,
+	.num_controls = ARRAY_SIZE(rockchip_controls),
+};
+
+static int rockchip_sound_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &rockchip_sound_card;
+	struct device_node *cpu_node;
+	int i, ret;
+
+	for (i = 0; i < card->num_links; i++) {
+		cpu_node = of_parse_phandle(pdev->dev.of_node,
+					 "rockchip,cpu", i);
+		if (!cpu_node) {
+			dev_err(&pdev->dev, "Property[%d] 'rockchip,cpu' missing or invalid\n", i);
+			return -EINVAL;
+		}
+
+		rockchip_dailinks[i].platform_of_node = cpu_node;
+		rockchip_dailinks[i].cpu_of_node = cpu_node;
+
+		rockchip_dailinks[i].codec_of_node =
+			of_parse_phandle(pdev->dev.of_node, "rockchip,codec", i);
+		if (!rockchip_dailinks[i].codec_of_node) {
+			dev_err(&pdev->dev,
+				"Property[%d] 'rockchip,codec' missing or invalid\n", i);
+			return -EINVAL;
+		}
+	}
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret)
+		dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
+			__func__, ret);
+
+	return ret;
+}
+
+static const struct of_device_id rockchip_sound_of_match[] = {
+	{ .compatible = "rockchip,rockchip-sound", },
+	{},
+};
+
+static struct platform_driver rockchip_sound_driver = {
+	.probe = rockchip_sound_probe,
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = rockchip_sound_of_match,
+#ifdef CONFIG_PM
+		.pm = &snd_soc_pm_ops,
+#endif
+	},
+};
+
+module_platform_driver(rockchip_sound_driver);
+
+MODULE_AUTHOR("Xing Zheng <zhengxing at rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);
-- 
1.7.9.5




From raashidmuhammed at zilogic.com  Sun May 22 22:17:36 2016
From: raashidmuhammed at zilogic.com (raashidmuhammed)
Date: Mon, 23 May 2016 10:47:36 +0530
Subject: [PATCH] ARM: at91: Add DT support for Olimex SAM9-L9260 board.
In-Reply-To: <CAL_JsqLXaq7KKPKnSTcRBswnvdZiUS=1wb35oo+JrjY3_tPRJQ@mail.gmail.com>
References: <1463574766-15568-1-git-send-email-raashidmuhammed@zilogic.com>
 <20160518232925.GA6545@rob-hp-laptop> <573DB180.9030200@atmel.com>
 <CAL_JsqLXaq7KKPKnSTcRBswnvdZiUS=1wb35oo+JrjY3_tPRJQ@mail.gmail.com>
Message-ID: <57429270.8060401@zilogic.com>



On 05/19/2016 06:20 PM, Rob Herring wrote:
> On Thu, May 19, 2016 at 7:28 AM, Nicolas Ferre <nicolas.ferre at atmel.com> wrote:
>> Le 19/05/2016 01:29, Rob Herring a ?crit :
>>> On Wed, May 18, 2016 at 06:02:46PM +0530, Raashid Muhammed wrote:
>>>> From: Raashid Muhammed <raashidmuhammed at zilogic.com>
>>>>
>>>> sam9-l9260 is a low cost board designed by Olimex.
>>>>
>>>> More infomation is available at:
>>>> https://www.olimex.com/Products/ARM/Atmel/SAM9-L9260/
>>>>
>>>> Signed-off-by: Raashid Muhammed <raashidmuhammed at zilogic.com>
>>>> Reviewed-by: Vijay Kumar B. <vijaykumar at bravegnu.org>
>>>> ---
>>>>   .../devicetree/bindings/arm/olimex-at91.txt        |   6 ++
>>>>   arch/arm/boot/dts/Makefile                         |   1 +
>>>>   arch/arm/boot/dts/sam9-l9260.dts                   | 108 +++++++++++++++++++++
>> For AT91-based boards, please use this prefix: "at91-" as stated in the
>> Atmel README file:
>> http://lxr.free-electrons.com/source/Documentation/arm/Atmel/README#L127
>>
>> So I would recommend this name instead:
>> at91-sam9-l9260.dts
>>
>>
>>>>   3 files changed, 115 insertions(+)
>>>>   create mode 100644 Documentation/devicetree/bindings/arm/olimex-at91.txt
>>>>   create mode 100644 arch/arm/boot/dts/sam9-l9260.dts
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/arm/olimex-at91.txt b/Documentation/devicetree/bindings/arm/olimex-at91.txt
>>>> new file mode 100644
>>>> index 0000000..0587d63
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/arm/olimex-at91.txt
>>>> @@ -0,0 +1,6 @@
>>>> +Olimex AT91 Device Tree Bindings
>>>> +--------------------------------
>>> There's not an existing at91 or olimex file this would fit into? We
>>> don't need 1 file per board.
>>>
>>>> +
>>>> +SAM9-L9260 Board
>>>> +Required root node properties:
>>>> +    - compatible = "olimex,sam9-l9260", "atmel,at91sam9260";
>> I don't think this file is needed at all actually. We have a lot of
>> board files and none of them have a dedicated or particular entry for them.
> Well, they should have one.
>
> Rob

Thanks everyone for your valuable comments. I'll incorporate the changes 
and resend the patch.

Regards,
Raashid


From sricharan at codeaurora.org  Sun May 22 23:05:04 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Mon, 23 May 2016 11:35:04 +0530
Subject: [PATCH V5 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <3164695.VzCnHHyi7r@wuerfel>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
 <1463741694-1735-7-git-send-email-sricharan@codeaurora.org>
 <3164695.VzCnHHyi7r@wuerfel>
Message-ID: <000601d1b4b9$119c2410$34d46c30$@codeaurora.org>

Hi Arnd,

>> @@ -124,6 +124,9 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
>>  		SET_TLBLKCR(base, ctx, 0);
>>  		SET_CONTEXTIDR(base, ctx, 0);
>>  	}
>> +
>> +	/* Ensure completion of relaxed writes from the above SET macros */
>> +	mb();
>>  }
>
>Why do the above use the relaxed writes? Do you have any performance
>numbers showing that skipping the sync for the reset makes a measurable
>difference?
>
>How did you prove that skipping the sync before the write is safe?
>
>How about resetting the iommu less often instead?
>

I had measured the numbers only for the full usecase path, not for the
reset path alone. I saw improvement of about 5% on full numbers.
As you said, the reset path would be called only less often
and might not bring a measurable change. I did not see a difference in behavior
when changing the sync to happen after the writes. But my understanding was that
the sync after the writes was required to ensure write completion. 

I should have made smaller patches to do this change.
The only patch relevant for this series is the one that changes the write in _iotlb_range
function. Rest of the changes, should be added one by one in a separate series.

>>  static void __flush_iotlb(void *cookie)
>> @@ -141,6 +144,9 @@ static void __flush_iotlb(void *cookie)
>>  		list_for_each_entry(master, &iommu->ctx_list, list)
>>  			SET_CTX_TLBIALL(iommu->base, master->num, 0);
>>
>> +		/* To ensure completion of TLBIALL above */
>> +		mb();
>> +
>>  		__disable_clocks(iommu);
>>  	}
>>  fail:
>
>__disable_clocks() takes spinlocks and accesses the hardware, which
>in turn will also involve multiple syncs, so this seems like
>a premature optimization.
>
>Have you tried just leaving the clocks enabled? I'd suspect you could
>gain more performance that way.

I have not tried by keep clocks enabled always. But intention here was
to have more granular clock control. But agree that the barrier might not
be needed in this case as it is indirectly taken care. I will remove this here
and explain it.

>
>> @@ -181,7 +187,8 @@ fail:
>>
>>  static void __flush_iotlb_sync(void *cookie)
>>  {
>> -	/* To avoid a null function pointer */
>> +	/* To ensure completion of the TLBIVA in __flush_iotlb_range */
>> +	mb();
>>  }
>
>I don't understand the specific race from the comment.
>
>What operation comes after this that relies on __flush_iotlb_range
>having completed, and how does an mb() guarantee this?
>

The flush_iotlb_range operation invalidates the tlb for writes to
pagetable and the finally calls the sync operation to ensure completion
of the flush and this is required before returning back to the client
of the iommu. In the case of this iommu, only a barrier is required to
ensure completion of the invalidate operation. 

>This seems to be a bug fix that is unrelated to the change to
>use writel_relaxed(), so better split it out into a separate
>patch, with a longer changeset description. Did you spot this
>race by running into incorrect data, or by inspection?
>

No i did not see a data corruption issue without the mb(),
but that it would have been hidden in someother way as well.
Another difference was the sync  was done before the write
previously and now its moved after the write. As i understand
sync after the write is correct. So i will change this patch with more
description and move rest of that changes out.

>>  static const struct iommu_gather_ops msm_iommu_gather_ops = {
>> @@ -235,6 +242,9 @@ static void config_mids(struct msm_iommu_dev *iommu,
>>  		/* Set security bit override to be Non-secure */
>>  		SET_NSCFG(iommu->base, mid, 3);
>>  	}
>> +
>> +	/* Ensure completion of relaxed writes from the above SET macros */
>> +	mb();
>>  }
>>
>
>This looks similar to the msm_iommu_reset() case. Maybe put those
>two into one patch, or find a way to run config_mids() less often so
>it doesn't show up in the profiles any more.
>
>If you hit this often enough that it causes performance problems,
>it's more likely that there is a bug in your code than that changing
>to relaxed accessors is a good idea.
>

  Ok, similar to reset this is called less often compared to flushes and
  may not show difference in performance. I will move this out.

>>  static void __reset_context(void __iomem *base, int ctx)
>> @@ -257,6 +267,9 @@ static void __reset_context(void __iomem *base, int ctx)
>>  	SET_TLBFLPTER(base, ctx, 0);
>>  	SET_TLBSLPTER(base, ctx, 0);
>>  	SET_TLBLKCR(base, ctx, 0);
>> +
>> +	/* Ensure completion of relaxed writes from the above SET macros */
>> +	mb();
>>  }
>>
>>  static void __program_context(void __iomem *base, int ctx,
>> @@ -305,6 +318,9 @@ static void __program_context(void __iomem *base, int ctx,
>>
>>  	/* Enable the MMU */
>>  	SET_M(base, ctx, 1);
>> +
>> +	/* Ensure completion of relaxed writes from the above SET macros */
>> +	mb();
>>  }
>>
>>  static struct iommu_domain *msm_iommu_domain_alloc(unsigned type)
>
>Maybe one more patch for these? I can see that
>__reset_context/__program_context would be run often enough to make
>a difference, though maybe not as much as the flushes.
>
>Also, split this in two patches: one that adds a comment describing
>how you proved that you don't need barriers before the writes, and
>another one adding the barrier afterwards, with a description of
>the failure scenario.

ok, i will split it. I did not see a failure though explicitly. It is based on
the understanding that the sync after the write is more appropriate
 than before it.
>
>> @@ -500,7 +516,8 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
>>  	/* Invalidate context TLB */
>>  	SET_CTX_TLBIALL(iommu->base, master->num, 0);
>>  	SET_V2PPR(iommu->base, master->num, va & V2Pxx_VA);
>> -
>> +	/* Ensure completion of relaxed writes from the above SET macros */
>> +	mb();
>>  	par = GET_PAR(iommu->base, master->num);
>>
>>  	/* We are dealing with a supersection */
>
>In this case, I'd say it's better to rewrite the function to avoid the
>read: iova_to_phys() should be fast, and not require hardware access.
>Getting rid of the hardware access by using an in-memory cache for
>this should gain more than just removing the barriers, as an MMIO read
>is always slow

Ok, you mean using the software walk through ? I will check on this to measure
 the latency difference. If thats true, then the iopgtable ops itself provides a
function for iova_to_phys conversion, so that can be used.

>
>> @@ -714,7 +731,8 @@ static int msm_iommu_probe(struct platform_device *pdev)
>>  	par = GET_PAR(iommu->base, 0);
>>  	SET_V2PCFG(iommu->base, 0, 0);
>>  	SET_M(iommu->base, 0, 0);
>> -
>> +	/* Ensure completion of relaxed writes from the above SET macros */
>> +	mb();
>>  	if (!par) {
>
>Probe() clearly isn't performance sensitive, so please back this out
>and use the non-relaxed accessors.
>

ok, will change this back.

>> diff --git a/drivers/iommu/msm_iommu_hw-8xxx.h b/drivers/iommu/msm_iommu_hw-8xxx.h
>> index fc16010..fe2c5ca 100644
>> --- a/drivers/iommu/msm_iommu_hw-8xxx.h
>> +++ b/drivers/iommu/msm_iommu_hw-8xxx.h
>> @@ -24,13 +24,19 @@
>>  #define GET_CTX_REG(reg, base, ctx) \
>>  				(readl((base) + (reg) + ((ctx) << CTX_SHIFT)))
>>
>> -#define SET_GLOBAL_REG(reg, base, val)	writel((val), ((base) + (reg)))
>> +/*
>> + * The writes to the global/context registers needs to be synced only after
>> + * all the configuration writes are done. So use relaxed accessors and
>> + * a barrier at the end.
>> + */
>> +#define SET_GLOBAL_REG_RELAXED(reg, base, val) \
>> +			       writel_relaxed((val), ((base) + (reg)))
>>
>> -#define SET_CTX_REG(reg, base, ctx, val) \
>> -			writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
>> +#define SET_CTX_REG_RELAXED(reg, base, ctx, val) \
>> +		writel_relaxed((val), ((base) + (reg) + ((ctx) << CTX_SHIFT)))
>
>Please add the relaxed accessors first in a separate patch, and then
>change over one user at a time before you remove the non-relaxed ones.
>

ok

>It's hard to believe that all users are actually performance critical,
>so start with the ones that gain the most performance. As commented above,
>some of the conversions seem particularly fishy and it's likely that
>a slow reset() function should not be fixed by making reset() faster
>but by calling it less often.

Ok. Will change this. So i will split this in to separate series, one patch to modify
relevant the flush_iotlb_range function in this series and rest of all changes
as  a driver improvement in one more.

>Can you just remove those macros, and open-code the function calls?
>
>This is an unnecessary obfuscation that now also hides the fact that you
>are using relaxed accessors.

Ok, will make this in to inline functions to make it obvious.

Regards,
 Sricharan



From mark.yao at rock-chips.com  Sun May 22 23:10:16 2016
From: mark.yao at rock-chips.com (Mark yao)
Date: Mon, 23 May 2016 14:10:16 +0800
Subject: [PATCH 0/3] drm/rockchip: fix some sparse warnings
In-Reply-To: <20160510160356.1167-1-john@metanate.com>
References: <20160510160356.1167-1-john@metanate.com>
Message-ID: <57429EC8.4080207@rock-chips.com>

On 2016?05?11? 00:03, John Keeping wrote:
> The first patch wasn't found by sparse, but is something I noticed while
> in the area.  The following two fix all of the sparse warnings inside
> drm/rockchip.
>
> John Keeping (3):
>    drm/rockchip: dw_hdmi: remove unused #include
>    drm/rockchip: fb: add missing header
>    drm/rockchip: fix "should it be static?" warnings
>
>   drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 -
>   drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 4 ++--
>   drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 7 ++++---
>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 ++--
>   drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 2 +-
>   5 files changed, 9 insertions(+), 9 deletions(-)
>

Hi John

Sorry for reply late, this series of patches looks good for me, Applied 
to my branch.

Thanks.

-- 
?ark Yao




From kishon at ti.com  Sun May 22 23:22:01 2016
From: kishon at ti.com (Kishon Vijay Abraham I)
Date: Mon, 23 May 2016 11:52:01 +0530
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <87shxdlws6.fsf@linux.intel.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
 <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com>
 <20160518193028.GT5995@atomide.com>
 <0d463add-9fa5-a768-2ba6-34c4126c7817@ti.com>
 <20160519145745.GU5995@atomide.com> <87shxdlws6.fsf@linux.intel.com>
Message-ID: <5742A189.4060803@ti.com>

Hi Felipe,

On Friday 20 May 2016 12:06 AM, Felipe Balbi wrote:
> 
> Hi,
> 
> Tony Lindgren <tony at atomide.com> writes:
>> * Peter Ujfalusi <peter.ujfalusi at ti.com> [160519 01:10]:
>>> On 05/18/2016 10:30 PM, Tony Lindgren wrote:
>>>> Ideally the adma support would be a separate loadable module,
>>>> similar how the cppi41dma is a child of the OTG controller.
>>>
>>> The Master DMA is part of the hsmmc IP block. If the same ADMA module is
>>> present on other IPs it might be beneficial to have a helper library to handle
>>> it (allocating the descriptor pool, wrinting, updating descriptors, etc).
>>
>> OK. Yeah if it's part of the MMC controller it makes no sense to
>> separate it. So then the conecrns are using alternate DMA
>> implementations and keeping PM runtime working :)
>>
>> BTW, Felipe mentioned that the best thing to do in the long run would
>> be to set up sdhci-omap.c operating in ADMA mode.
>>
>> Felipe, care to summarize what you had in mind?
> 
> yeah, just write a new sdhci-omap.c to start moving away from
> omap-hsmmc.c, just like it was done for 8250-omap.
> 
> At the beginning, it could be just the bare minimum to get it working
> and slowly move over stuff like pm runtime, dmaengine, PIO. Move more
> platforms over to that driver and, eventually, get rid of omap-hsmmc.c
> altogether.
> 
> That way, development can be focussed on generic layers (SDHCI) to which
> OMAP MMC controller is compliant (apart from the VERSION register
> quirk).

About an year back, when I tried using SDHCI for OMAP I ran into issues and was
not able to get it working. IIRC SDHCI_PRESENT_STATE (or OMAP_HSMMC_PSTATE) was
not showing the correct state for card present and is unable to raise an
interrupt when a card is inserted. I didn't debug this further.

It also kept me wondering why gpio interrupt was always used for card detect
instead of using mmci_sdcd line of the controller.

Thanks
Kishon


From mark.yao at rock-chips.com  Sun May 22 23:32:59 2016
From: mark.yao at rock-chips.com (Mark yao)
Date: Mon, 23 May 2016 14:32:59 +0800
Subject: [PATCH 1/2] drm/rockchip: vop: Do check if an update is pending
 during disable
In-Reply-To: <CAAObsKBXxb8ZS3CqLy4qsDRWLvT=w2ACANCcDLE5B47nRKtvBw@mail.gmail.com>
References: <1459937686-9142-1-git-send-email-tomeu.vizoso@collabora.com>
 <5707043D.6060706@rock-chips.com>
 <CAAObsKAeAjUP1retiZqo5geOK2OkVjKvSB6g6nvGTh_rdNiFJQ@mail.gmail.com>
 <570AFAC2.8080907@rock-chips.com>
 <CAAObsKCmPZBaSudVJy8BPThhoZw8VVqxicqsmc8diApajD57nA@mail.gmail.com>
 <CAAObsKBXxb8ZS3CqLy4qsDRWLvT=w2ACANCcDLE5B47nRKtvBw@mail.gmail.com>
Message-ID: <5742A41B.8030308@rock-chips.com>

On 2016?05?05? 17:34, Tomeu Vizoso wrote:
> On 20 April 2016 at 16:23, Tomeu Vizoso <tomeu.vizoso at collabora.com> wrote:
>> On 11 April 2016 at 03:15, Mark yao <mark.yao at rock-chips.com> wrote:
>>> On 2016?04?08? 18:54, Tomeu Vizoso wrote:
>>>> On 8 April 2016 at 03:07, Mark yao <mark.yao at rock-chips.com> wrote:
>>>>> On 2016?04?06? 18:14, Tomeu Vizoso wrote:
>>>>>
>>>>> When a plane is being disabled but it's still enabled, do check if the
>>>>> previous update has been completed by reading yrgb_mst back.
>>>>>
>>>>> Otherwise, pending pageflips would remain pending after a CRTC is
>>>>> disabled.
>>>>>
>>>>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>
>>>>> ---
>>>>>    drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +++--
>>>>>    1 file changed, 3 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>>> index a9b1e8b5ac85..f46b1fd1887b 100644
>>>>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>>> @@ -1064,8 +1064,9 @@ static bool vop_win_pending_is_complete(struct
>>>>> vop_win
>>>>> *vop_win)
>>>>>     struct vop_plane_state *state = to_vop_plane_state(plane->state);
>>>>>     dma_addr_t yrgb_mst;
>>>>>
>>>>> - if (!state->enable)
>>>>> - return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;
>>>>> + if (!state->enable &&
>>>>> +    VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0)
>>>>> + return true;
>>>>>
>>>>>
>>>>> It is wrong, the patch would cause a bug.
>>>>>
>>>>> when state->enable is 0, check yrgb_mst == state->yrgb_mst always be
>>>>> true,
>>>>> because state->yrgb_mst not update on plane disabled funtion, that would
>>>>> cause iommu crash.
>>>> Sorry, but I don't understand where's the bug and what could cause
>>>> that crash. What the existing code was doing is saying that a pageflip
>>>> event is still pending if we have told the plane to disable but for
>>>> some reason it hasn't yet.
>>>>
>>>> With this modification, if we read back that it's already disabled, we
>>>> return true as before. But if we read back that it isn't disabled yet,
>>>> then we still check the fb pointers and compare them.
>>>>
>>>> The iommu mapping is removed when the _CRTC_ is disabled, and what
>>>> this series does is to wait for the pending pageflip to finish before
>>>> conitnuing with CRTC disablement.
>>>
>>> the iommu mapping will unmap after plane disabled, we need sure that the
>>> plane really disabled before unmap, if not, the unmap may call before plane
>>> really disable, vop may access unmap address, then would get iommu page
>>> fault.
>> Sorry, but I still don't see the error condition that you are
>> describing. AFAICS, the unmap will happen after the last pageflip has
>> completed.
>>
>>>>> About pending pageflips would remain pending, can you  describe more info
>>>>> about it? I think those pending pageflips should be ignore when CRTC is
>>>>> disabled.
>>>> Well, right now in rockchip-drm pending pageflips won't be ignored
>>>> when a CRTC is disabled, but will be delivered when it's re-enabled.
>>>>
>>>> If they would be to be ignored (understanding that as dropped), that
>>>> would require modifications to clients so they keep track of which fbs
>>>> were used in a particular crtc and destroy them when the crtc is
>>>> disabled, but that would be incorrect when using the i915 DRM driver
>>>> (I also assume others do the same). Given that the pageflip ioctl
>>>> isn't driver-specific, I think there cannot be such a difference in
>>>> behavior between drivers.
>>>>
>>>> With the current behavior (pending pageflip events being delayed until
>>>> the CRTC is enabled again), compositors and other clients will be
>>>> holding on to the fb in the pending pageflip until an arbitrary point
>>>> in the future that may not ever come. To me that sounds like a serious
>>>> modification of the assumptions on fb lifecycle that might not be
>>>> warranted.
>>>>
>>>> So in summary, even if I haven't found any explicit documentation on
>>>> this, I think the ABI is that any pending pageflips are to be
>>>> delivered when that CRTC is being disabled and not later.
>>>
>>> on drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>>>
>>> drm_atomic_helper_commit_planes(dev, state, true);
>>> rockchip_atomic_wait_for_complete(dev, state);
>>>
>>> We set active_only = true, I think planes can only update when crtc is
>>> active. and rockchip_atomic_wait_for_complete only wait when crtc is active.
>> That's fine, but if a pageflip is pending when the client requests the
>> CRTC to be disabled, we need to wait for the event to be emitted
>> before we actually disable the HW.
> Hi Mark,
>
> could you tell me if you agree that there's a bug that needs to be
> solved, and if so, what do you think we should do about it?
Hi Tomeu

Sorry for reply late.
I don't agree the changes:

- if (!state->enable)
- return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;
+ if (!state->enable &&
+    VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0)
+ return true;

This changes actually would lead a bug.
when we disable a plane, the vop_win_pending_is_complete would always 
return true, That is not allowed, would cause fb free too early.

Does this patch is needed for "[PATCH 2/2] drm/rockchip: vop: Wait for 
pending events when disabling a CRTC"

Thanks.

> Thanks,
>
> Tomeu
>
>> Regards,
>>
>> Tomeu
>>
>>> Thanks.
>>>
>>>> Thanks,
>>>>
>>>> Tomeu
>>>>
>>>>> Thanks.
>>>>>
>>>>>
>>>>>     yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> ?ark Yao
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> dri-devel mailing list
>>>>> dri-devel at lists.freedesktop.org
>>>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>>>>>
>>>>
>>>
>>> --
>>> ?ark Yao
>>>
>>>
>>> _______________________________________________
>>> dri-devel mailing list
>>> dri-devel at lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
>


-- 
?ark Yao




From LW at KARO-electronics.de  Mon May 23 00:03:01 2016
From: LW at KARO-electronics.de (Lothar =?UTF-8?B?V2HDn21hbm4=?=)
Date: Mon, 23 May 2016 09:03:01 +0200
Subject: [PATCH 0015/1529] Fix typo
In-Reply-To: <20160521113722.32053-1-andrea.gelmini@gelma.net>
References: <20160521113722.32053-1-andrea.gelmini@gelma.net>
Message-ID: <20160523090301.3cdbd523@ipc1.ka-ro>

Hi,

On Sat, 21 May 2016 13:37:22 +0200 Andrea Gelmini wrote:
> Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
> ---
>  Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt b/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt
> index 3e36c1d..616428a 100644
> --- a/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt
> +++ b/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt
> @@ -8,7 +8,7 @@ use to analyze system performance, to make behaviors visible and to count
>  usages of each IP (DMC, CPU, RIGHTBUS, LEFTBUS, CAM interface, LCD, G3D, MFC).
>  The Exynos PPMU driver uses the devfreq-event class to provide event data
>  to various devfreq devices. The devfreq devices would use the event data when
> -derterming the current state of each IP.
> +determing the current state of each IP.
>  
s/determing/determine/


Lothar Wa?mann


From geert at linux-m68k.org  Mon May 23 00:07:20 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 23 May 2016 09:07:20 +0200
Subject: [PATCH v2 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <1463966906-15129-2-git-send-email-horms+renesas@verge.net.au>
References: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>
 <1463966906-15129-2-git-send-email-horms+renesas@verge.net.au>
Message-ID: <CAMuHMdXsu=O13rLysob1Xp+5vWcp7gq6byCffR-6hGc+W-837A@mail.gmail.com>

On Mon, May 23, 2016 at 3:28 AM, Simon Horman
<horms+renesas at verge.net.au> wrote:
> Basic support for the Gen 3 R-Car M3-W SoC.
>
> Based on work for the r8a7795 and r8a7796 SoCs by
> Takeshi Kihara, Dirk Behme and Geert Uytterhoeven.
>
> Signed-off-by: Simon Horman <horms+renesas at verge.net.au>

> --- /dev/null
> +++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> @@ -0,0 +1,120 @@
> +       psci {
> +               compatible = "arm,psci-1.0";

Do we want to use 1.0 on r8a7795, too?

> +               method = "smc";
> +       };

> +       soc {
> +               compatible = "simple-bus";
> +               interrupt-parent = <&gic>;
> +               #address-cells = <2>;
> +               #size-cells = <2>;
> +               ranges;
> +
> +               gic: interrupt-controller at 0xf1010000 {

If you drop the "0x" (which is BTW also present in r8a7795.dtsi), you can add
my
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

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 henryc.chen at mediatek.com  Mon May 23 00:13:29 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Mon, 23 May 2016 15:13:29 +0800
Subject: [PATCH v2 1/3] regulator: DT: Add DT property for operation mode
 configuration
In-Reply-To: <1463987611-32139-1-git-send-email-henryc.chen@mediatek.com>
References: <1463987611-32139-1-git-send-email-henryc.chen@mediatek.com>
Message-ID: <1463987611-32139-2-git-send-email-henryc.chen@mediatek.com>

Some regulators support their operating mode to be changed by consumers for
module specific purpose. Add a DT property to support this.

Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
---
 Documentation/devicetree/bindings/regulator/regulator.txt |  5 +++++
 include/dt-bindings/regulator/regulator.h                 | 14 ++++++++++++++
 2 files changed, 19 insertions(+)
 create mode 100644 include/dt-bindings/regulator/regulator.h

diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt
index ecfc593..e505d0b 100644
--- a/Documentation/devicetree/bindings/regulator/regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/regulator.txt
@@ -49,6 +49,11 @@ Optional properties:
 	0: Disable active discharge.
 	1: Enable active discharge.
 	Absence of this property will leave configuration to default.
+- regulator-supported-modes: Regulators can run in a variety of different
+  operating modes depending on output load. This allows further system power
+  savings by selecting the best (and most efficient) regulator mode for a
+  desired load. The definition for each of these operation is defined at
+  include/dt-bindings/regulator/regulator.h
 
 Deprecated properties:
 - regulator-compatible: If a regulator chip contains multiple
diff --git a/include/dt-bindings/regulator/regulator.h b/include/dt-bindings/regulator/regulator.h
new file mode 100644
index 0000000..2ed1dfd
--- /dev/null
+++ b/include/dt-bindings/regulator/regulator.h
@@ -0,0 +1,14 @@
+/*
+ * This header provides constants for binding regulator.
+ */
+
+#ifndef _DT_BINDINGS_REGULATOR_REGULATOR_H
+#define _DT_BINDINGS_REGULATOR_REGULATOR_H
+
+/* Regulator operating modes */
+#define REGULATOR_OPERATION_MODE_FAST			0x0
+#define REGULATOR_OPERATION_MODE_NORMAL			0x1
+#define REGULATOR_OPERATION_MODE_IDLE			0x2
+#define REGULATOR_OPERATION_MODE_STANDBY		0x3
+
+#endif
-- 
1.8.1.1.dirty



From henryc.chen at mediatek.com  Mon May 23 00:13:28 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Mon, 23 May 2016 15:13:28 +0800
Subject: Add support for regulator operation mode of mt6397
Message-ID: <1463987611-32139-1-git-send-email-henryc.chen@mediatek.com>

Some regulators support different operating modes, but there is no suitable
property that can pass the opeation mode constraints on runtime at present.

This series making the change to specify supported modes as a devicetree list.
Consumers can change or get the regulator operation mode by regulator_set_mode
/regulator_get_mode and define the support operating mode on devicetree.

There is a requirement from SVS driver. SVS calibartion requires that the
regulator be in its low-noise (pwm mode) state at boot, but at all other times
it can be normal mode for power saving.
http://www.spinics.net/lists/devicetree/msg111204.html

Changes in v2:
- Separate patch for binding document changes.
- Create a header to define operation mode on dt-bindings.
- Remove the property "regulator-supported-modes".

Henry Chen (3):
  regulator: DT: Add DT property for operation mode configuration
  regulator: of: Add support for parsing operation mode
  regulator: mt6397: Add buck change mode regulator interface for mt6397

 .../devicetree/bindings/regulator/regulator.txt    |  5 ++
 drivers/regulator/mt6397-regulator.c               | 89 +++++++++++++++++++---
 drivers/regulator/of_regulator.c                   | 15 +++-
 include/dt-bindings/regulator/regulator.h          | 14 ++++
 4 files changed, 113 insertions(+), 10 deletions(-)
 create mode 100644 include/dt-bindings/regulator/regulator.h

-- 
1.8.1.1.dirty



From henryc.chen at mediatek.com  Mon May 23 00:13:30 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Mon, 23 May 2016 15:13:30 +0800
Subject: [PATCH v2 2/3] regulator: of: Add support for parsing operation mode
In-Reply-To: <1463987611-32139-1-git-send-email-henryc.chen@mediatek.com>
References: <1463987611-32139-1-git-send-email-henryc.chen@mediatek.com>
Message-ID: <1463987611-32139-3-git-send-email-henryc.chen@mediatek.com>

Some regulators support their operating mode to be changed by consumers for
module specific purpose.

This patch adds support to parse those properties and fill the regulator
constraints so the regulator core can call the regualtor_set_mode to change
the modes.

Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
---
 drivers/regulator/of_regulator.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 6b0aa80..7f8d82e 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -31,7 +31,7 @@ static void of_get_regulation_constraints(struct device_node *np,
 	struct regulation_constraints *constraints = &(*init_data)->constraints;
 	struct regulator_state *suspend_state;
 	struct device_node *suspend_np;
-	int ret, i;
+	int ret, i, cnt;
 	u32 pval;
 
 	constraints->name = of_get_property(np, "regulator-name", NULL);
@@ -167,6 +167,19 @@ static void of_get_regulation_constraints(struct device_node *np,
 		suspend_state = NULL;
 		suspend_np = NULL;
 	}
+	cnt = of_property_count_elems_of_size(np,
+					      "regulator-supported-modes",
+					      sizeof(u32));
+	if (cnt > 0)
+		constraints->valid_ops_mask |= REGULATOR_CHANGE_MODE;
+
+	for (i = 0; i < cnt; i++) {
+		u32 mode;
+
+		of_property_read_u32_index(np, "regulator-supported-modes",
+					   i, &mode);
+		constraints->valid_modes_mask |= (1 << mode);
+	}
 }
 
 /**
-- 
1.8.1.1.dirty



From henryc.chen at mediatek.com  Mon May 23 00:13:31 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Mon, 23 May 2016 15:13:31 +0800
Subject: [PATCH v2 3/3] regulator: mt6397: Add buck change mode regulator
 interface for mt6397
In-Reply-To: <1463987611-32139-1-git-send-email-henryc.chen@mediatek.com>
References: <1463987611-32139-1-git-send-email-henryc.chen@mediatek.com>
Message-ID: <1463987611-32139-4-git-send-email-henryc.chen@mediatek.com>

BUCKs of mt6397 have auto mode and pwm mode.
User can use regulator interfaces to control modes

Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
---
 drivers/regulator/mt6397-regulator.c | 89 ++++++++++++++++++++++++++++++++----
 1 file changed, 80 insertions(+), 9 deletions(-)

diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c
index 1c45abb..c6c6aa85 100644
--- a/drivers/regulator/mt6397-regulator.c
+++ b/drivers/regulator/mt6397-regulator.c
@@ -23,6 +23,9 @@
 #include <linux/regulator/mt6397-regulator.h>
 #include <linux/regulator/of_regulator.h>
 
+#define MT6397_BUCK_MODE_AUTO	0
+#define MT6397_BUCK_MODE_FORCE_PWM	1
+
 /*
  * MT6397 regulators' information
  *
@@ -38,10 +41,14 @@ struct mt6397_regulator_info {
 	u32 vselon_reg;
 	u32 vselctrl_reg;
 	u32 vselctrl_mask;
+	u32 modeset_reg;
+	u32 modeset_mask;
+	u32 modeset_shift;
 };
 
 #define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg,	\
-		vosel, vosel_mask, voselon, vosel_ctrl)			\
+		vosel, vosel_mask, voselon, vosel_ctrl, _modeset_reg,	\
+		_modeset_shift)					\
 [MT6397_ID_##vreg] = {							\
 	.desc = {							\
 		.name = #vreg,						\
@@ -62,6 +69,9 @@ struct mt6397_regulator_info {
 	.vselon_reg = voselon,						\
 	.vselctrl_reg = vosel_ctrl,					\
 	.vselctrl_mask = BIT(1),					\
+	.modeset_reg = _modeset_reg,					\
+	.modeset_mask = BIT(_modeset_shift),				\
+	.modeset_shift = _modeset_shift					\
 }
 
 #define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel,	\
@@ -145,6 +155,63 @@ static const u32 ldo_volt_table7[] = {
 	1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,
 };
 
+static int mt6397_regulator_set_mode(struct regulator_dev *rdev,
+				     unsigned int mode)
+{
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret, val;
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		val = MT6397_BUCK_MODE_FORCE_PWM;
+		break;
+	case REGULATOR_MODE_NORMAL:
+		val = MT6397_BUCK_MODE_AUTO;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err_mode;
+	}
+
+	dev_dbg(&rdev->dev, "mt6397 buck set_mode %#x, %#x, %#x, %#x\n",
+		info->modeset_reg, info->modeset_mask,
+		info->modeset_shift, val);
+
+	val <<= info->modeset_shift;
+	ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
+				 info->modeset_mask, val);
+err_mode:
+	if (ret != 0) {
+		dev_err(&rdev->dev,
+			"Failed to set mt6397 buck mode: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static unsigned int mt6397_regulator_get_mode(struct regulator_dev *rdev)
+{
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret, regval;
+
+	ret = regmap_read(rdev->regmap, info->modeset_reg, &regval);
+	if (ret != 0) {
+		dev_err(&rdev->dev,
+			"Failed to get mt6397 buck mode: %d\n", ret);
+		return ret;
+	}
+
+	switch ((regval & info->modeset_mask) >> info->modeset_shift) {
+	case MT6397_BUCK_MODE_AUTO:
+		return REGULATOR_MODE_NORMAL;
+	case MT6397_BUCK_MODE_FORCE_PWM:
+		return REGULATOR_MODE_FAST;
+	default:
+		return -EINVAL;
+	}
+}
+
 static int mt6397_get_status(struct regulator_dev *rdev)
 {
 	int ret;
@@ -170,6 +237,8 @@ static const struct regulator_ops mt6397_volt_range_ops = {
 	.disable = regulator_disable_regmap,
 	.is_enabled = regulator_is_enabled_regmap,
 	.get_status = mt6397_get_status,
+	.set_mode = mt6397_regulator_set_mode,
+	.get_mode = mt6397_regulator_get_mode,
 };
 
 static const struct regulator_ops mt6397_volt_table_ops = {
@@ -196,28 +265,30 @@ static const struct regulator_ops mt6397_volt_fixed_ops = {
 static struct mt6397_regulator_info mt6397_regulators[] = {
 	MT6397_BUCK("buck_vpca15", VPCA15, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VCA15_CON7, MT6397_VCA15_CON9, 0x7f,
-		MT6397_VCA15_CON10, MT6397_VCA15_CON5),
+		MT6397_VCA15_CON10, MT6397_VCA15_CON5, MT6397_VCA15_CON2, 11),
 	MT6397_BUCK("buck_vpca7", VPCA7, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VPCA7_CON7, MT6397_VPCA7_CON9, 0x7f,
-		MT6397_VPCA7_CON10, MT6397_VPCA7_CON5),
+		MT6397_VPCA7_CON10, MT6397_VPCA7_CON5, MT6397_VPCA7_CON2, 8),
 	MT6397_BUCK("buck_vsramca15", VSRAMCA15, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VSRMCA15_CON7, MT6397_VSRMCA15_CON9,
-		0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5),
+		0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5,
+		MT6397_VSRMCA15_CON2, 8),
 	MT6397_BUCK("buck_vsramca7", VSRAMCA7, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VSRMCA7_CON7, MT6397_VSRMCA7_CON9,
-		0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5),
+		0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5,
+		MT6397_VSRMCA7_CON2, 8),
 	MT6397_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VCORE_CON7, MT6397_VCORE_CON9, 0x7f,
-		MT6397_VCORE_CON10, MT6397_VCORE_CON5),
+		MT6397_VCORE_CON10, MT6397_VCORE_CON5, MT6397_VCORE_CON2, 8),
 	MT6397_BUCK("buck_vgpu", VGPU, 700000, 1493750, 6250, buck_volt_range1,
 		MT6397_VGPU_CON7, MT6397_VGPU_CON9, 0x7f,
-		MT6397_VGPU_CON10, MT6397_VGPU_CON5),
+		MT6397_VGPU_CON10, MT6397_VGPU_CON5, MT6397_VGPU_CON2, 8),
 	MT6397_BUCK("buck_vdrm", VDRM, 800000, 1593750, 6250, buck_volt_range2,
 		MT6397_VDRM_CON7, MT6397_VDRM_CON9, 0x7f,
-		MT6397_VDRM_CON10, MT6397_VDRM_CON5),
+		MT6397_VDRM_CON10, MT6397_VDRM_CON5, MT6397_VDRM_CON2, 8),
 	MT6397_BUCK("buck_vio18", VIO18, 1500000, 2120000, 20000,
 		buck_volt_range3, MT6397_VIO18_CON7, MT6397_VIO18_CON9, 0x1f,
-		MT6397_VIO18_CON10, MT6397_VIO18_CON5),
+		MT6397_VIO18_CON10, MT6397_VIO18_CON5, MT6397_VIO18_CON2, 8),
 	MT6397_REG_FIXED("ldo_vtcxo", VTCXO, MT6397_ANALDO_CON0, 10, 2800000),
 	MT6397_REG_FIXED("ldo_va28", VA28, MT6397_ANALDO_CON1, 14, 2800000),
 	MT6397_LDO("ldo_vcama", VCAMA, ldo_volt_table1,
-- 
1.8.1.1.dirty



From balbi at kernel.org  Mon May 23 00:18:54 2016
From: balbi at kernel.org (Felipe Balbi)
Date: Mon, 23 May 2016 10:18:54 +0300
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <5742A189.4060803@ti.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
 <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com>
 <20160518193028.GT5995@atomide.com>
 <0d463add-9fa5-a768-2ba6-34c4126c7817@ti.com>
 <20160519145745.GU5995@atomide.com> <87shxdlws6.fsf@linux.intel.com>
 <5742A189.4060803@ti.com>
Message-ID: <874m9pgs2p.fsf@linux.intel.com>


Hi Kishon,

Kishon Vijay Abraham I <kishon at ti.com> writes:
> Hi Felipe,
>
> On Friday 20 May 2016 12:06 AM, Felipe Balbi wrote:
>> 
>> Hi,
>> 
>> Tony Lindgren <tony at atomide.com> writes:
>>> * Peter Ujfalusi <peter.ujfalusi at ti.com> [160519 01:10]:
>>>> On 05/18/2016 10:30 PM, Tony Lindgren wrote:
>>>>> Ideally the adma support would be a separate loadable module,
>>>>> similar how the cppi41dma is a child of the OTG controller.
>>>>
>>>> The Master DMA is part of the hsmmc IP block. If the same ADMA module is
>>>> present on other IPs it might be beneficial to have a helper library to handle
>>>> it (allocating the descriptor pool, wrinting, updating descriptors, etc).
>>>
>>> OK. Yeah if it's part of the MMC controller it makes no sense to
>>> separate it. So then the conecrns are using alternate DMA
>>> implementations and keeping PM runtime working :)
>>>
>>> BTW, Felipe mentioned that the best thing to do in the long run would
>>> be to set up sdhci-omap.c operating in ADMA mode.
>>>
>>> Felipe, care to summarize what you had in mind?
>> 
>> yeah, just write a new sdhci-omap.c to start moving away from
>> omap-hsmmc.c, just like it was done for 8250-omap.
>> 
>> At the beginning, it could be just the bare minimum to get it working
>> and slowly move over stuff like pm runtime, dmaengine, PIO. Move more
>> platforms over to that driver and, eventually, get rid of omap-hsmmc.c
>> altogether.
>> 
>> That way, development can be focussed on generic layers (SDHCI) to which
>> OMAP MMC controller is compliant (apart from the VERSION register
>> quirk).
>
> About an year back, when I tried using SDHCI for OMAP I ran into
> issues and was not able to get it working. IIRC SDHCI_PRESENT_STATE
> (or OMAP_HSMMC_PSTATE) was not showing the correct state for card
> present and is unable to raise an interrupt when a card is inserted. I
> didn't debug this further.

I'd say this is a bug in hsmmc. I remember seeing some bits in some
TI-specific register (before SDHCI address space starts) which can be
used to keep parts of SDHCI powered on exactly so normal WP and CD pins
work as expected.

In any case, adding support for GPIO-based card detect to generic SDHCI
shouldn't be too difficult :-)

> It also kept me wondering why gpio interrupt was always used for card
> detect instead of using mmci_sdcd line of the controller.

Probably a really, really old bug which nobody ever debugged properly ;-)

ps: you don't need that ADMA2 DT property, btw. There's a bit in another
register which you can check if $this controller was configured with
ADMA2 support or not. IIRC, OMAP5's TRM describes them.

-- 
balbi


From henryc.chen at mediatek.com  Mon May 23 00:30:16 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Mon, 23 May 2016 15:30:16 +0800
Subject: [PATCH] regulator: mt6397: Constify struct regulator_ops
Message-ID: <1463988616-18803-1-git-send-email-henryc.chen@mediatek.com>

Consitify the structure of regulator operations.

Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
---
 drivers/regulator/mt6397-regulator.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c
index 17a5b6c..1c45abb 100644
--- a/drivers/regulator/mt6397-regulator.c
+++ b/drivers/regulator/mt6397-regulator.c
@@ -160,7 +160,7 @@ static int mt6397_get_status(struct regulator_dev *rdev)
 	return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
 }
 
-static struct regulator_ops mt6397_volt_range_ops = {
+static const struct regulator_ops mt6397_volt_range_ops = {
 	.list_voltage = regulator_list_voltage_linear_range,
 	.map_voltage = regulator_map_voltage_linear_range,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -172,7 +172,7 @@ static struct regulator_ops mt6397_volt_range_ops = {
 	.get_status = mt6397_get_status,
 };
 
-static struct regulator_ops mt6397_volt_table_ops = {
+static const struct regulator_ops mt6397_volt_table_ops = {
 	.list_voltage = regulator_list_voltage_table,
 	.map_voltage = regulator_map_voltage_iterate,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -184,7 +184,7 @@ static struct regulator_ops mt6397_volt_table_ops = {
 	.get_status = mt6397_get_status,
 };
 
-static struct regulator_ops mt6397_volt_fixed_ops = {
+static const struct regulator_ops mt6397_volt_fixed_ops = {
 	.list_voltage = regulator_list_voltage_linear,
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
-- 
1.8.1.1.dirty



From caesar.upstream at gmail.com  Mon May 23 00:32:39 2016
From: caesar.upstream at gmail.com (Caesar Wang)
Date: Mon, 23 May 2016 15:32:39 +0800
Subject: [PATCH v2 0/5] Thermal: Support for hardware-tracked trip points
In-Reply-To: <1462268013-14992-1-git-send-email-wxt@rock-chips.com>
References: <1462268013-14992-1-git-send-email-wxt@rock-chips.com>
Message-ID: <5742B217.4080405@gmail.com>

Hello Eduardo & 'Zhang Rui'

Do we have the chance to merge this series patches for next kernel?
I had picked them up in my github, and tested for a period of time with 
rockchip inside kernel.

Let me know if someone have some suggestions or against opinios.
Thanks,

-Caesar
On 2016?05?03? 17:33, Caesar Wang wrote:
> The history patches come from Mikko and Sascha.
> http://thread.gmane.org/gmane.linux.power-management.general/59451
>
> Now, I pick them up to continue upstream.
> Nevermind!
>
> This series history patches:
> v1: https://lkml.org/lkml/2016/4/24/227
>
> This series adds support for hardware trip points. It picks up earlier
> work from Mikko Perttunen. Mikko implemented hardware trip points as part
> of the device tree support. It was suggested back then to move the
> functionality to the thermal core instead of putting more code into the
> device tree support. This series does exactly that.
>
> This series patches rebase the conflicts.
> Note that the hardware-tracked trip points are very well tested currently.
>
> Verified and tested on https://github.com/Caesar-github/rockchip/tree/wip/fixes-thermal-0503
> That's based on linux-kernel 20160502.
> .Linux version 4.6.0-rc6-next-20160502-08922-g860ed34 (wxt at nb)
>
>
> Changes in v2:
> - update the sysfs-api.txt for set_trips
> - add the commit in patch[v2 2/5].
> - Update the commit for patch[v2 4/5].
>
> Caesar Wang (1):
>    thermal: rockchip: add the set_trips function
>
> Sascha Hauer (4):
>    thermal: Add support for hardware-tracked trip points
>    thermal: of: implement .set_trips for device tree thermal zones
>    thermal: streamline get_trend callbacks
>    thermal: bang-bang governor: act on lower trip boundary
>
>   Documentation/thermal/sysfs-api.txt                |  7 +++
>   drivers/thermal/gov_bang_bang.c                    |  2 +-
>   drivers/thermal/of-thermal.c                       | 23 +++++-----
>   drivers/thermal/rockchip_thermal.c                 | 39 ++++++++++++++++
>   drivers/thermal/thermal_core.c                     | 52 ++++++++++++++++++++++
>   drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 25 ++++-------
>   include/linux/thermal.h                            |  9 +++-
>   7 files changed, 128 insertions(+), 29 deletions(-)
>



From pali.rohar at gmail.com  Mon May 23 00:41:32 2016
From: pali.rohar at gmail.com (Pali =?utf-8?B?Um9ow6Fy?=)
Date: Mon, 23 May 2016 09:41:32 +0200
Subject: [PATCHv3] support for AD5820 camera auto-focus coil
In-Reply-To: <574049EF.2090208@gmail.com>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com> <20160521105607.GA20071@amd>
 <574049EF.2090208@gmail.com>
Message-ID: <20160523074132.GD29844@pali>

On Saturday 21 May 2016 14:43:43 Ivaylo Dimitrov wrote:
> >diff --git a/include/media/ad5820.h b/include/media/ad5820.h
> >new file mode 100644
> >index 0000000..f5a1565
> >--- /dev/null
> >+++ b/include/media/ad5820.h
> >@@ -0,0 +1,70 @@
> >+/*
> >+ * include/media/ad5820.h
> >+ *
> >+ * Copyright (C) 2008 Nokia Corporation
> >+ * Copyright (C) 2007 Texas Instruments
> >+ *
> >+ * Contact: Tuukka Toivonen <tuukka.o.toivonen at nokia.com>
> >+ *          Sakari Ailus <sakari.ailus at nokia.com>
> >+ *
> >+ * Based on af_d88.c by Texas Instruments.
> >+ *
> >+ * This program is free software; you can redistribute it and/or
> >+ * modify it under the terms of the GNU General Public License
> >+ * version 2 as published by the Free Software Foundation.
> >+ *
> >+ * This program is distributed in the hope that it will be useful, but
> >+ * WITHOUT ANY WARRANTY; without even the implied warranty of
> >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> >+ * General Public License for more details.
> >+ *
> >+ * You should have received a copy of the GNU General Public License
> >+ * along with this program; if not, write to the Free Software
> >+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
> >+ * 02110-1301 USA
> >+ */
> >+
> >+#ifndef AD5820_H
> >+#define AD5820_H
> >+
> >+#include <linux/i2c.h>
> >+#include <linux/mutex.h>
> >+#include <linux/videodev2.h>
> >+
> >+#include <media/v4l2-ctrls.h>
> >+#include <media/v4l2-subdev.h>
> >+
> >+struct regulator;
> >+
> >+#define AD5820_NAME		"ad5820"
> >+#define AD5820_I2C_ADDR		(0x18 >> 1)

Maybe write I2C address is more readable form? What is reason such
bit shift format?

> >+/* Register definitions */
> >+#define AD5820_POWER_DOWN		(1 << 15)
> >+#define AD5820_DAC_SHIFT		4
> 
> Do those defines really belong here? Isn't it better if they are moved to
> ad5820.c?

For me it looks like this is private for ad5820.c.

> >+#define AD5820_RAMP_MODE_LINEAR		(0 << 3)
> >+#define AD5820_RAMP_MODE_64_16		(1 << 3)
> >+
> >+struct ad5820_platform_data {
> >+	int (*set_xshutdown)(struct v4l2_subdev *subdev, int set);
> >+};

This is for legacy board code support right? We need DT support for N900
as legacy board code is going to be deleted.

> >+#define to_ad5820_device(sd)	container_of(sd, struct ad5820_device, subdev)
> >+
> >+struct ad5820_device {
> >+	struct v4l2_subdev subdev;
> >+	struct ad5820_platform_data *platform_data;
> >+	struct regulator *vana;
> >+
> >+	struct v4l2_ctrl_handler ctrls;
> >+	u32 focus_absolute;
> >+	u32 focus_ramp_time;
> >+	u32 focus_ramp_mode;
> >+
> >+	struct mutex power_lock;
> >+	int power_count;
> >+
> >+	int standby : 1;
> >+};
> >+
> 
> The same for struct ad5820_device, is it really part of the public API?

Yes, this is also private for ad5820.c

> >+#endif /* AD5820_H */
> >
> >
> >

-- 
Pali Roh?r
pali.rohar at gmail.com


From josephl at nvidia.com  Mon May 23 00:42:21 2016
From: josephl at nvidia.com (Joseph Lo)
Date: Mon, 23 May 2016 15:42:21 +0800
Subject: [PATCH] arm64: tegra: Fix CPU compatible string for Tegra132
Message-ID: <20160523074221.7135-1-josephl@nvidia.com>

As per commit f634da375fc96 ("Documentation: DT bindings: add nvidia,
tegra132-denver compatible string"), fixing the CPU compatible string for
Tegra132 to match the binding document currently.

Signed-off-by: Joseph Lo <josephl at nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra132.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
index 2013f8916084..7b1cdc029de3 100644
--- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
@@ -964,13 +964,13 @@
 
 		cpu at 0 {
 			device_type = "cpu";
-			compatible = "nvidia,denver", "arm,armv8";
+			compatible = "nvidia,tegra132-denver", "arm,armv8";
 			reg = <0>;
 		};
 
 		cpu at 1 {
 			device_type = "cpu";
-			compatible = "nvidia,denver", "arm,armv8";
+			compatible = "nvidia,tegra132-denver", "arm,armv8";
 			reg = <1>;
 		};
 	};
-- 
2.8.3



From boris.brezillon at free-electrons.com  Mon May 23 00:44:55 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Mon, 23 May 2016 09:44:55 +0200
Subject: [PATCH v9 2/2] memory: atmel-ebi: add DT bindings documentation
In-Reply-To: <1463989495-13787-1-git-send-email-boris.brezillon@free-electrons.com>
References: <1463989495-13787-1-git-send-email-boris.brezillon@free-electrons.com>
Message-ID: <1463989495-13787-3-git-send-email-boris.brezillon@free-electrons.com>

The EBI (External Bus Interface) is used to access external peripherals
(NOR, SRAM, NAND, and other specific devices like ethernet controllers).
Each device is assigned a CS line and an address range and can have its
own configuration (timings, access mode, bus width, ...).
This driver provides a generic DT binding to configure a device according
to its requirements.
For specific device controllers (like the NAND one) the SMC timings
should be configured by the controller driver through the matrix and smc
syscon regmaps.

Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../bindings/memory-controllers/atmel,ebi.txt      | 136 +++++++++++++++++++++
 1 file changed, 136 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt

diff --git a/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
new file mode 100644
index 0000000..9bb5f57
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
@@ -0,0 +1,136 @@
+* Device tree bindings for Atmel EBI
+
+The External Bus Interface (EBI) controller is a bus where you can connect
+asynchronous (NAND, NOR, SRAM, ....) and synchronous memories (SDR/DDR SDRAMs).
+The EBI provides a glue-less interface to asynchronous memories through the SMC
+(Static Memory Controller).
+
+Required properties:
+
+- compatible:		"atmel,at91sam9260-ebi"
+			"atmel,at91sam9261-ebi"
+			"atmel,at91sam9263-ebi0"
+			"atmel,at91sam9263-ebi1"
+			"atmel,at91sam9rl-ebi"
+			"atmel,at91sam9g45-ebi"
+			"atmel,at91sam9x5-ebi"
+			"atmel,sama5d3-ebi"
+
+- reg:			Contains offset/length value for EBI memory mapping.
+			This property might contain several entries if the EBI
+			memory range is not contiguous
+
+- #address-cells:	Must be 2.
+			The first cell encodes the CS.
+			The second cell encode the offset into the CS memory
+			range.
+
+- #size-cells:		Must be set to 1.
+
+- ranges:		Encodes CS to memory region association.
+
+- clocks:		Clock feeding the EBI controller.
+			See clock-bindings.txt
+
+Children device nodes are representing device connected to the EBI bus.
+
+Required device node properties:
+
+- reg:			Contains the chip-select id, the offset and the length
+			of the memory region requested by the device.
+
+EBI bus configuration will be defined directly in the device subnode.
+
+Optional EBI/SMC properties:
+
+- atmel,smc-bus-width:		width of the asynchronous device's data bus
+				8, 16 or 32.
+				Default to 8 when undefined.
+
+- atmel,smc-byte-access-type	"write" or "select" (see Atmel datasheet).
+				Default to "select" when undefined.
+
+- atmel,smc-read-mode		"nrd" or "ncs".
+				Default to "ncs" when undefined.
+
+- atmel,smc-write-mode		"nwe" or "ncs".
+				Default to "ncs" when undefined.
+
+- atmel,smc-exnw-mode		"disabled", "frozen" or "ready".
+				Default to "disabled" when undefined.
+
+- atmel,smc-page-mode		enable page mode if present. The provided value
+				defines the page size (supported values: 4, 8,
+				16 and 32).
+
+- atmel,smc-tdf-mode:		"normal" or "optimized". When set to
+				"optimized" the data float time is optimized
+				depending on the next device being accessed
+				(next device setup time is subtracted to the
+				current device data float time).
+				Default to "normal" when undefined.
+
+If at least one atmel,smc- property is defined the following SMC timing
+properties become mandatory. In the other hand, if none of the atmel,smc-
+properties are specified, we assume that the EBI bus configuration will be
+handled by the sub-device driver, and none of those properties should be
+defined.
+
+All the timings are expressed in nanoseconds (see Atmel datasheet for a full
+description).
+
+- atmel,smc-ncs-rd-setup-ns
+- atmel,smc-nrd-setup-ns
+- atmel,smc-ncs-wr-setup-ns
+- atmel,smc-nwe-setup-ns
+- atmel,smc-ncs-rd-pulse-ns
+- atmel,smc-nrd-pulse-ns
+- atmel,smc-ncs-wr-pulse-ns
+- atmel,smc-nwe-pulse-ns
+- atmel,smc-nwe-cycle-ns
+- atmel,smc-nrd-cycle-ns
+- atmel,smc-tdf-ns
+
+Example:
+
+	ebi: ebi at 10000000 {
+		compatible = "atmel,sama5d3-ebi";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		atmel,smc = <&hsmc>;
+		atmel,matrix = <&matrix>;
+		reg = <0x10000000 0x10000000
+		       0x40000000 0x30000000>;
+		ranges = <0x0 0x0 0x10000000 0x10000000
+			  0x1 0x0 0x40000000 0x10000000
+			  0x2 0x0 0x50000000 0x10000000
+			  0x3 0x0 0x60000000 0x10000000>;
+		clocks = <&mck>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_ebi_addr>;
+
+		nor: flash at 0,0 {
+			compatible = "cfi-flash";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x0 0x0 0x1000000>;
+			bank-width = <2>;
+
+			atmel,smc-read-mode = "nrd";
+			atmel,smc-write-mode = "nwe";
+			atmel,smc-bus-width = <16>;
+			atmel,smc-ncs-rd-setup-ns = <0>;
+			atmel,smc-ncs-wr-setup-ns = <0>;
+			atmel,smc-nwe-setup-ns = <8>;
+			atmel,smc-nrd-setup-ns = <16>;
+			atmel,smc-ncs-rd-pulse-ns = <84>;
+			atmel,smc-ncs-wr-pulse-ns = <84>;
+			atmel,smc-nrd-pulse-ns = <76>;
+			atmel,smc-nwe-pulse-ns = <76>;
+			atmel,smc-nrd-cycle-ns = <107>;
+			atmel,smc-nwe-cycle-ns = <84>;
+			atmel,smc-tdf-ns = <16>;
+		};
+	};
+
-- 
2.7.4



From boris.brezillon at free-electrons.com  Mon May 23 00:44:53 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Mon, 23 May 2016 09:44:53 +0200
Subject: [PATCH v9 0/2] memory: add Atmel EBI (External Bus Interface) driver
Message-ID: <1463989495-13787-1-git-send-email-boris.brezillon@free-electrons.com>

Hello,

This patch series provides support for the EBI bus.

The EBI (External Bus Interface) is used to access external peripherals
(NOR, SRAM, NAND, and other specific devices like ethernet controllers).
Each device is assigned a CS line and an address range and can have its
own configuration (timings, access mode, bus width, ...).
This driver provides a generic DT binding to configure a device according
to its requirements.
For specific device controllers (like the NAND one) the SMC timings
should be configured by the controller driver through the matrix and
smc syscon regmaps.

Best Regards,

Boris

Changes since v8:
- fixed typo in DT bindings doc

Changes since v7:
- move EBI bus config properties directly in the sub-device node
- prefix all EBI/SMC properties with atmel,smc-
- rework the driver to take the new binding into account
- disable the subdevice when EBI implementation fails to configure
  the bus as requested

Changes since v6:
- rework the binding to put per-device config information into a
  separate subnode and have devices connected to the EBI bus
  defined as direct children of the EBI node
- make all EBI timings mandatory
- keep adding sub-devices when a failure occurs on one of them

Changes since v5:
- remove the "atmel,specialized-logic" property: now all devices are
  are attached to the SMC logic by default, and specialized drivers
  (like the NAND controller one), should change this configuration
  manually.
- provide hardware readout to allow partial config description.
  This is mainly here to keep existing platforms (where everything
  is configured by the bootloader/bootstrap) in working state.
- rename "atmel,tdf-optimized" into "atmel,tdf-mode" and switch from
  a boolean to string property to properly support partial config

Changes since v4:
- fix inconsistencies in SMC and MATRIX registers definition
- add missing compatible strings for at91sam9rl SoC
- fix DT bindings documentation
- replace "atmel,generic-dev" property by "atmel,specialized-logic"

Changes since v3:
- added AT91_MATRIX_USBPUCR_PUON definition
- removed useless macros (those directly returning SoC specific register
  offsets)
- use syscon_regmap_lookup_by_phandle instead of of_parse_phandle +
  syscon_node_to_regmap
- drop AT91_EBICSA_REGFIELD and AT91_MULTI_EBICSA_REGFIELD macros

Changes since v2:
- minor fixes int DT bindings doc
- fix SMC macros
- make use of SMC macros defined in include/linux/mfd/syscon/atmel-smc.h

Changes since v1:
- almost everything :-)

Boris Brezillon (2):
  memory: add Atmel EBI (External Bus Interface) driver
  memory: atmel-ebi: add DT bindings documentation

 .../bindings/memory-controllers/atmel,ebi.txt      | 136 ++++
 drivers/memory/Kconfig                             |  11 +
 drivers/memory/Makefile                            |   1 +
 drivers/memory/atmel-ebi.c                         | 771 +++++++++++++++++++++
 4 files changed, 919 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt
 create mode 100644 drivers/memory/atmel-ebi.c

-- 
2.7.4



From boris.brezillon at free-electrons.com  Mon May 23 00:44:54 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Mon, 23 May 2016 09:44:54 +0200
Subject: [PATCH v9 1/2] memory: add Atmel EBI (External Bus Interface) driver
In-Reply-To: <1463989495-13787-1-git-send-email-boris.brezillon@free-electrons.com>
References: <1463989495-13787-1-git-send-email-boris.brezillon@free-electrons.com>
Message-ID: <1463989495-13787-2-git-send-email-boris.brezillon@free-electrons.com>

The EBI (External Bus Interface) is used to access external peripherals
(NOR, SRAM, NAND, and other specific devices like ethernet controllers).
Each device is assigned a CS line and an address range and can have its
own configuration (timings, access mode, bus width, ...).
This driver provides a generic DT binding to configure a device according
to its requirements.
For specific device controllers (like the NAND one) the SMC timings
should be configured by the controller driver through the matrix and
smc syscon regmaps.

Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
---
 drivers/memory/Kconfig     |  11 +
 drivers/memory/Makefile    |   1 +
 drivers/memory/atmel-ebi.c | 771 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 783 insertions(+)
 create mode 100644 drivers/memory/atmel-ebi.c

diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index c61a284..d13ce16 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -25,6 +25,17 @@ config ATMEL_SDRAMC
 	  Starting with the at91sam9g45, this controller supports SDR, DDR and
 	  LP-DDR memories.
 
+config ATMEL_EBI
+	bool "Atmel EBI driver"
+	default y
+	depends on ARCH_AT91 && OF
+	select MFD_SYSCON
+	help
+	  Driver for Atmel EBI controller.
+	  Used to configure the EBI (external bus interface) when the device-
+	  tree is used. This bus supports NANDs, external ethernet controller,
+	  SRAMs, ATA devices, etc.
+
 config TI_AEMIF
 	tristate "Texas Instruments AEMIF driver"
 	depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index cb0b7a1..b20ae38 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_OF)		+= of_memory.o
 endif
 obj-$(CONFIG_ARM_PL172_MPMC)	+= pl172.o
 obj-$(CONFIG_ATMEL_SDRAMC)	+= atmel-sdramc.o
+obj-$(CONFIG_ATMEL_EBI)		+= atmel-ebi.o
 obj-$(CONFIG_TI_AEMIF)		+= ti-aemif.o
 obj-$(CONFIG_TI_EMIF)		+= emif.o
 obj-$(CONFIG_OMAP_GPMC)		+= omap-gpmc.o
diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c
new file mode 100644
index 0000000..712c767
--- /dev/null
+++ b/drivers/memory/atmel-ebi.c
@@ -0,0 +1,771 @@
+/*
+ * EBI driver for Atmel chips
+ * inspired by the fsl weim bus driver
+ *
+ * Copyright (C) 2013 JJ Hiblot.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/atmel-matrix.h>
+#include <linux/mfd/syscon/atmel-smc.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+struct at91sam9_smc_timings {
+	u32 ncs_rd_setup_ns;
+	u32 nrd_setup_ns;
+	u32 ncs_wr_setup_ns;
+	u32 nwe_setup_ns;
+	u32 ncs_rd_pulse_ns;
+	u32 nrd_pulse_ns;
+	u32 ncs_wr_pulse_ns;
+	u32 nwe_pulse_ns;
+	u32 nrd_cycle_ns;
+	u32 nwe_cycle_ns;
+	u32 tdf_ns;
+};
+
+struct at91sam9_smc_generic_fields {
+	struct regmap_field *setup;
+	struct regmap_field *pulse;
+	struct regmap_field *cycle;
+	struct regmap_field *mode;
+};
+
+struct at91sam9_ebi_dev_config {
+	struct at91sam9_smc_timings timings;
+	u32 mode;
+};
+
+struct at91_ebi_dev_config {
+	int cs;
+	union {
+		struct at91sam9_ebi_dev_config sam9;
+	};
+};
+
+struct at91_ebi;
+
+struct at91_ebi_dev {
+	struct list_head node;
+	struct at91_ebi *ebi;
+	u32 mode;
+	int numcs;
+	struct at91_ebi_dev_config configs[];
+};
+
+struct at91_ebi_caps {
+	unsigned int available_cs;
+	const struct reg_field *ebi_csa;
+	void (*get_config)(struct at91_ebi_dev *ebid,
+			   struct at91_ebi_dev_config *conf);
+	int (*xlate_config)(struct at91_ebi_dev *ebid,
+			    struct device_node *configs_np,
+			    struct at91_ebi_dev_config *conf);
+	int (*apply_config)(struct at91_ebi_dev *ebid,
+			    struct at91_ebi_dev_config *conf);
+	int (*init)(struct at91_ebi *ebi);
+};
+
+struct at91_ebi {
+	struct clk *clk;
+	struct regmap *smc;
+	struct regmap *matrix;
+
+	struct regmap_field *ebi_csa;
+
+	struct device *dev;
+	const struct at91_ebi_caps *caps;
+	struct list_head devs;
+	union {
+		struct at91sam9_smc_generic_fields sam9;
+	};
+};
+
+static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid,
+				    struct at91_ebi_dev_config *conf)
+{
+	struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9;
+	unsigned int clk_rate = clk_get_rate(ebid->ebi->clk);
+	struct at91sam9_ebi_dev_config *config = &conf->sam9;
+	struct at91sam9_smc_timings *timings = &config->timings;
+	unsigned int val;
+
+	regmap_fields_read(fields->mode, conf->cs, &val);
+	config->mode = val & ~AT91_SMC_TDF;
+
+	val = (val & AT91_SMC_TDF) >> 16;
+	timings->tdf_ns = clk_rate * val;
+
+	regmap_fields_read(fields->setup, conf->cs, &val);
+	timings->ncs_rd_setup_ns = (val >> 24) & 0x1f;
+	timings->ncs_rd_setup_ns += ((val >> 29) & 0x1) * 128;
+	timings->ncs_rd_setup_ns *= clk_rate;
+	timings->nrd_setup_ns = (val >> 16) & 0x1f;
+	timings->nrd_setup_ns += ((val >> 21) & 0x1) * 128;
+	timings->nrd_setup_ns *= clk_rate;
+	timings->ncs_wr_setup_ns = (val >> 8) & 0x1f;
+	timings->ncs_wr_setup_ns += ((val >> 13) & 0x1) * 128;
+	timings->ncs_wr_setup_ns *= clk_rate;
+	timings->nwe_setup_ns = val & 0x1f;
+	timings->nwe_setup_ns += ((val >> 5) & 0x1) * 128;
+	timings->nwe_setup_ns *= clk_rate;
+
+	regmap_fields_read(fields->pulse, conf->cs, &val);
+	timings->ncs_rd_pulse_ns = (val >> 24) & 0x3f;
+	timings->ncs_rd_pulse_ns += ((val >> 30) & 0x1) * 256;
+	timings->ncs_rd_pulse_ns *= clk_rate;
+	timings->nrd_pulse_ns = (val >> 16) & 0x3f;
+	timings->nrd_pulse_ns += ((val >> 22) & 0x1) * 256;
+	timings->nrd_pulse_ns *= clk_rate;
+	timings->ncs_wr_pulse_ns = (val >> 8) & 0x3f;
+	timings->ncs_wr_pulse_ns += ((val >> 14) & 0x1) * 256;
+	timings->ncs_wr_pulse_ns *= clk_rate;
+	timings->nwe_pulse_ns = val & 0x3f;
+	timings->nwe_pulse_ns += ((val >> 6) & 0x1) * 256;
+	timings->nwe_pulse_ns *= clk_rate;
+
+	regmap_fields_read(fields->cycle, conf->cs, &val);
+	timings->nrd_cycle_ns = (val >> 16) & 0x7f;
+	timings->nrd_cycle_ns += ((val >> 23) & 0x3) * 256;
+	timings->nrd_cycle_ns *= clk_rate;
+	timings->nwe_cycle_ns = val & 0x7f;
+	timings->nwe_cycle_ns += ((val >> 7) & 0x3) * 256;
+	timings->nwe_cycle_ns *= clk_rate;
+}
+
+static int at91_xlate_timing(struct device_node *np, const char *prop,
+			     u32 *val, bool *required)
+{
+	if (!of_property_read_u32(np, prop, val)) {
+		*required = true;
+		return 0;
+	}
+
+	if (*required)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int at91sam9_smc_xslate_timings(struct at91_ebi_dev *ebid,
+				       struct device_node *np,
+				       struct at91sam9_smc_timings *timings,
+				       bool *required)
+{
+	int ret;
+
+	ret = at91_xlate_timing(np, "atmel,smc-ncs-rd-setup-ns",
+				&timings->ncs_rd_setup_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-nrd-setup-ns",
+				&timings->nrd_setup_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-ncs-wr-setup-ns",
+				&timings->ncs_wr_setup_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-nwe-setup-ns",
+				&timings->nwe_setup_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-ncs-rd-pulse-ns",
+				&timings->ncs_rd_pulse_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-nrd-pulse-ns",
+				&timings->nrd_pulse_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-ncs-wr-pulse-ns",
+				&timings->ncs_wr_pulse_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-nwe-pulse-ns",
+				&timings->nwe_pulse_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-nwe-cycle-ns",
+				&timings->nwe_cycle_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-nrd-cycle-ns",
+				&timings->nrd_cycle_ns, required);
+	if (ret)
+		goto out;
+
+	ret = at91_xlate_timing(np, "atmel,smc-tdf-ns",
+				&timings->tdf_ns, required);
+
+out:
+	if (ret)
+		dev_err(ebid->ebi->dev,
+			"missing or invalid timings definition in %s",
+			np->full_name);
+
+	return ret;
+}
+
+static int at91sam9_ebi_xslate_config(struct at91_ebi_dev *ebid,
+				      struct device_node *np,
+				      struct at91_ebi_dev_config *conf)
+{
+	struct at91sam9_ebi_dev_config *config = &conf->sam9;
+	bool required = false;
+	const char *tmp_str;
+	u32 tmp;
+	int ret;
+
+	ret = of_property_read_u32(np, "atmel,smc-bus-width", &tmp);
+	if (!ret) {
+		switch (tmp) {
+		case 8:
+			config->mode |= AT91_SMC_DBW_8;
+			break;
+
+		case 16:
+			config->mode |= AT91_SMC_DBW_16;
+			break;
+
+		case 32:
+			config->mode |= AT91_SMC_DBW_32;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		required = true;
+	}
+
+	if (of_property_read_bool(np, "atmel,smc-tdf-optimized")) {
+		config->mode |= AT91_SMC_TDFMODE_OPTIMIZED;
+		required = true;
+	}
+
+	tmp_str = NULL;
+	of_property_read_string(np, "atmel,smc-byte-access-type", &tmp_str);
+	if (tmp_str && !strcmp(tmp_str, "write")) {
+		config->mode |= AT91_SMC_BAT_WRITE;
+		required = true;
+	}
+
+	tmp_str = NULL;
+	of_property_read_string(np, "atmel,smc-read-mode", &tmp_str);
+	if (tmp_str && !strcmp(tmp_str, "nrd")) {
+		config->mode |= AT91_SMC_READMODE_NRD;
+		required = true;
+	}
+
+	tmp_str = NULL;
+	of_property_read_string(np, "atmel,smc-write-mode", &tmp_str);
+	if (tmp_str && !strcmp(tmp_str, "nwe")) {
+		config->mode |= AT91_SMC_WRITEMODE_NWE;
+		required = true;
+	}
+
+	tmp_str = NULL;
+	of_property_read_string(np, "atmel,smc-exnw-mode", &tmp_str);
+	if (tmp_str) {
+		if (!strcmp(tmp_str, "frozen"))
+			config->mode |= AT91_SMC_EXNWMODE_FROZEN;
+		else if (!strcmp(tmp_str, "ready"))
+			config->mode |= AT91_SMC_EXNWMODE_READY;
+		else if (strcmp(tmp_str, "disabled"))
+			return -EINVAL;
+
+		required = true;
+	}
+
+	ret = of_property_read_u32(np, "atmel,smc-page-mode", &tmp);
+	if (!ret) {
+		switch (tmp) {
+		case 4:
+			config->mode |= AT91_SMC_PS_4;
+			break;
+
+		case 8:
+			config->mode |= AT91_SMC_PS_8;
+			break;
+
+		case 16:
+			config->mode |= AT91_SMC_PS_16;
+			break;
+
+		case 32:
+			config->mode |= AT91_SMC_PS_32;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		config->mode |= AT91_SMC_PMEN;
+		required = true;
+	}
+
+	ret = at91sam9_smc_xslate_timings(ebid, np, &config->timings,
+					  &required);
+	if (ret)
+		return ret;
+
+	return required;
+}
+
+static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid,
+				     struct at91_ebi_dev_config *conf)
+{
+	unsigned int clk_rate = clk_get_rate(ebid->ebi->clk);
+	struct at91sam9_ebi_dev_config *config = &conf->sam9;
+	struct at91sam9_smc_timings *timings = &config->timings;
+	struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9;
+	u32 coded_val;
+	u32 val;
+
+	coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
+						    timings->ncs_rd_setup_ns);
+	val = AT91SAM9_SMC_NCS_NRDSETUP(coded_val);
+	coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
+						    timings->nrd_setup_ns);
+	val |= AT91SAM9_SMC_NRDSETUP(coded_val);
+	coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
+						    timings->ncs_wr_setup_ns);
+	val |= AT91SAM9_SMC_NCS_WRSETUP(coded_val);
+	coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
+						    timings->nwe_setup_ns);
+	val |= AT91SAM9_SMC_NWESETUP(coded_val);
+	regmap_fields_write(fields->setup, conf->cs, val);
+
+	coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
+						    timings->ncs_rd_pulse_ns);
+	val = AT91SAM9_SMC_NCS_NRDPULSE(coded_val);
+	coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
+						    timings->nrd_pulse_ns);
+	val |= AT91SAM9_SMC_NRDPULSE(coded_val);
+	coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
+						    timings->ncs_wr_pulse_ns);
+	val |= AT91SAM9_SMC_NCS_WRPULSE(coded_val);
+	coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
+						    timings->nwe_pulse_ns);
+	val |= AT91SAM9_SMC_NWEPULSE(coded_val);
+	regmap_fields_write(fields->pulse, conf->cs, val);
+
+	coded_val = at91sam9_smc_cycle_ns_to_cycles(clk_rate,
+						    timings->nrd_cycle_ns);
+	val = AT91SAM9_SMC_NRDCYCLE(coded_val);
+	coded_val = at91sam9_smc_cycle_ns_to_cycles(clk_rate,
+						    timings->nwe_cycle_ns);
+	val |= AT91SAM9_SMC_NWECYCLE(coded_val);
+	regmap_fields_write(fields->cycle, conf->cs, val);
+
+	val = DIV_ROUND_UP(timings->tdf_ns, clk_rate);
+	if (val > AT91_SMC_TDF_MAX)
+		val = AT91_SMC_TDF_MAX;
+	regmap_fields_write(fields->mode, conf->cs,
+			    config->mode | AT91_SMC_TDF_(val));
+
+	return 0;
+}
+
+static int at91sam9_ebi_init(struct at91_ebi *ebi)
+{
+	struct at91sam9_smc_generic_fields *fields = &ebi->sam9;
+	struct reg_field field = REG_FIELD(0, 0, 31);
+
+	field.id_size = fls(ebi->caps->available_cs);
+	field.id_offset = AT91SAM9_SMC_GENERIC_BLK_SZ;
+
+	field.reg = AT91SAM9_SMC_SETUP(AT91SAM9_SMC_GENERIC);
+	fields->setup = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->setup))
+		return PTR_ERR(fields->setup);
+
+	field.reg = AT91SAM9_SMC_PULSE(AT91SAM9_SMC_GENERIC);
+	fields->pulse = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->pulse))
+		return PTR_ERR(fields->pulse);
+
+	field.reg = AT91SAM9_SMC_CYCLE(AT91SAM9_SMC_GENERIC);
+	fields->cycle = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->cycle))
+		return PTR_ERR(fields->cycle);
+
+	field.reg = AT91SAM9_SMC_MODE(AT91SAM9_SMC_GENERIC);
+	fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->mode))
+		return PTR_ERR(fields->mode);
+
+	return 0;
+}
+
+static int sama5d3_ebi_init(struct at91_ebi *ebi)
+{
+	struct at91sam9_smc_generic_fields *fields = &ebi->sam9;
+	struct reg_field field = REG_FIELD(0, 0, 31);
+
+	field.id_size = fls(ebi->caps->available_cs);
+	field.id_offset = SAMA5_SMC_GENERIC_BLK_SZ;
+
+	field.reg = AT91SAM9_SMC_SETUP(SAMA5_SMC_GENERIC);
+	fields->setup = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->setup))
+		return PTR_ERR(fields->setup);
+
+	field.reg = AT91SAM9_SMC_PULSE(SAMA5_SMC_GENERIC);
+	fields->pulse = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->pulse))
+		return PTR_ERR(fields->pulse);
+
+	field.reg = AT91SAM9_SMC_CYCLE(SAMA5_SMC_GENERIC);
+	fields->cycle = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->cycle))
+		return PTR_ERR(fields->cycle);
+
+	field.reg = SAMA5_SMC_MODE(SAMA5_SMC_GENERIC);
+	fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
+	if (IS_ERR(fields->mode))
+		return PTR_ERR(fields->mode);
+
+	return 0;
+}
+
+static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np,
+			      int reg_cells)
+{
+	const struct at91_ebi_caps *caps = ebi->caps;
+	struct at91_ebi_dev_config conf = { };
+	struct device *dev = ebi->dev;
+	struct at91_ebi_dev *ebid;
+	int ret, numcs = 0, i;
+	bool apply = false;
+
+	numcs = of_property_count_elems_of_size(np, "reg",
+						reg_cells * sizeof(u32));
+	if (numcs <= 0) {
+		dev_err(dev, "invalid reg property in %s\n", np->full_name);
+		return -EINVAL;
+	}
+
+	ebid = devm_kzalloc(ebi->dev,
+			    sizeof(*ebid) + (numcs * sizeof(*ebid->configs)),
+			    GFP_KERNEL);
+	if (!ebid)
+		return -ENOMEM;
+
+	ebid->ebi = ebi;
+
+	ret = caps->xlate_config(ebid, np, &conf);
+	if (ret < 0)
+		return ret;
+	else if (ret)
+		apply = true;
+
+	for (i = 0; i < numcs; i++) {
+		u32 cs;
+
+		ret = of_property_read_u32_index(np, "reg", i * reg_cells,
+						 &cs);
+		if (ret)
+			return ret;
+
+		if (cs > AT91_MATRIX_EBI_NUM_CS ||
+		    !(ebi->caps->available_cs & BIT(cs))) {
+			dev_err(dev, "invalid reg property in %s\n",
+				np->full_name);
+			return -EINVAL;
+		}
+
+		ebid->configs[i].cs = cs;
+
+		if (apply) {
+			conf.cs = cs;
+			ret = caps->apply_config(ebid, &conf);
+			if (ret)
+				return ret;
+		}
+
+		caps->get_config(ebid, &ebid->configs[i]);
+
+		/*
+		 * Attach the EBI device to the generic SMC logic if at least
+		 * one "atmel,smc-" property is present.
+		 */
+		if (ebi->ebi_csa && ret)
+			regmap_field_update_bits(ebi->ebi_csa,
+						 BIT(cs), 0);
+	}
+
+	list_add_tail(&ebid->node, &ebi->devs);
+
+	return 0;
+}
+
+static const struct reg_field at91sam9260_ebi_csa =
+				REG_FIELD(AT91SAM9260_MATRIX_EBICSA, 0,
+					  AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9260_ebi_caps = {
+	.available_cs = 0xff,
+	.ebi_csa = &at91sam9260_ebi_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9261_ebi_csa =
+				REG_FIELD(AT91SAM9261_MATRIX_EBICSA, 0,
+					  AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9261_ebi_caps = {
+	.available_cs = 0xff,
+	.ebi_csa = &at91sam9261_ebi_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9263_ebi0_csa =
+				REG_FIELD(AT91SAM9263_MATRIX_EBI0CSA, 0,
+					  AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9263_ebi0_caps = {
+	.available_cs = 0x3f,
+	.ebi_csa = &at91sam9263_ebi0_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9263_ebi1_csa =
+				REG_FIELD(AT91SAM9263_MATRIX_EBI1CSA, 0,
+					  AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9263_ebi1_caps = {
+	.available_cs = 0x7,
+	.ebi_csa = &at91sam9263_ebi1_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9rl_ebi_csa =
+				REG_FIELD(AT91SAM9RL_MATRIX_EBICSA, 0,
+					  AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9rl_ebi_caps = {
+	.available_cs = 0x3f,
+	.ebi_csa = &at91sam9rl_ebi_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct reg_field at91sam9g45_ebi_csa =
+				REG_FIELD(AT91SAM9G45_MATRIX_EBICSA, 0,
+					  AT91_MATRIX_EBI_NUM_CS - 1);
+
+static const struct at91_ebi_caps at91sam9g45_ebi_caps = {
+	.available_cs = 0x3f,
+	.ebi_csa = &at91sam9g45_ebi_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct at91_ebi_caps at91sam9x5_ebi_caps = {
+	.available_cs = 0x3f,
+	.ebi_csa = &at91sam9263_ebi0_csa,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = at91sam9_ebi_init,
+};
+
+static const struct at91_ebi_caps sama5d3_ebi_caps = {
+	.available_cs = 0xf,
+	.get_config = at91sam9_ebi_get_config,
+	.xlate_config = at91sam9_ebi_xslate_config,
+	.apply_config = at91sam9_ebi_apply_config,
+	.init = sama5d3_ebi_init,
+};
+
+static const struct of_device_id at91_ebi_id_table[] = {
+	{
+		.compatible = "atmel,at91sam9260-ebi",
+		.data = &at91sam9260_ebi_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9261-ebi",
+		.data = &at91sam9261_ebi_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9263-ebi0",
+		.data = &at91sam9263_ebi0_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9263-ebi1",
+		.data = &at91sam9263_ebi1_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9rl-ebi",
+		.data = &at91sam9rl_ebi_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9g45-ebi",
+		.data = &at91sam9g45_ebi_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9x5-ebi",
+		.data = &at91sam9x5_ebi_caps,
+	},
+	{
+		.compatible = "atmel,sama5d3-ebi",
+		.data = &sama5d3_ebi_caps,
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, at91_ebi_id_table);
+
+static int at91_ebi_dev_disable(struct at91_ebi *ebi, struct device_node *np)
+{
+	struct device *dev = ebi->dev;
+	struct property *newprop;
+
+	newprop = devm_kzalloc(dev, sizeof(*newprop), GFP_KERNEL);
+	if (!newprop)
+		return -ENOMEM;
+
+	newprop->name = devm_kstrdup(dev, "status", GFP_KERNEL);
+	if (!newprop->name)
+		return -ENOMEM;
+
+	newprop->value = devm_kstrdup(dev, "disabled", GFP_KERNEL);
+	if (!newprop->name)
+		return -ENOMEM;
+
+	newprop->length = sizeof("disabled");
+
+	return of_update_property(np, newprop);
+}
+
+static int at91_ebi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *child, *np = dev->of_node;
+	const struct of_device_id *match;
+	struct at91_ebi *ebi;
+	int ret, reg_cells;
+	struct clk *clk;
+	u32 val;
+
+	match = of_match_device(at91_ebi_id_table, dev);
+	if (!match || !match->data)
+		return -EINVAL;
+
+	ebi = devm_kzalloc(dev, sizeof(*ebi), GFP_KERNEL);
+	if (!ebi)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&ebi->devs);
+	ebi->caps = match->data;
+	ebi->dev = dev;
+
+	clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	ebi->clk = clk;
+
+	ebi->smc = syscon_regmap_lookup_by_phandle(np, "atmel,smc");
+	if (IS_ERR(ebi->smc))
+		return PTR_ERR(ebi->smc);
+
+	/*
+	 * The sama5d3 does not provide an EBICSA register and thus does need
+	 * to access the matrix registers.
+	 */
+	if (ebi->caps->ebi_csa) {
+		ebi->matrix =
+			syscon_regmap_lookup_by_phandle(np, "atmel,matrix");
+		if (IS_ERR(ebi->matrix))
+			return PTR_ERR(ebi->matrix);
+
+		ebi->ebi_csa = regmap_field_alloc(ebi->matrix,
+						  *ebi->caps->ebi_csa);
+		if (IS_ERR(ebi->ebi_csa))
+			return PTR_ERR(ebi->ebi_csa);
+	}
+
+	ret = ebi->caps->init(ebi);
+	if (ret)
+		return ret;
+
+	ret = of_property_read_u32(np, "#address-cells", &val);
+	if (ret) {
+		dev_err(dev, "missing #address-cells property\n");
+		return ret;
+	}
+
+	reg_cells = val;
+
+	ret = of_property_read_u32(np, "#size-cells", &val);
+	if (ret) {
+		dev_err(dev, "missing #address-cells property\n");
+		return ret;
+	}
+
+	reg_cells += val;
+
+	for_each_available_child_of_node(np, child) {
+		if (!of_find_property(child, "reg", NULL))
+			continue;
+
+		ret = at91_ebi_dev_setup(ebi, child, reg_cells);
+		if (ret) {
+			dev_err(dev, "failed to configure EBI bus for %s, disabling the device",
+				child->full_name);
+
+			ret = at91_ebi_dev_disable(ebi, child);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return of_platform_populate(np, NULL, NULL, dev);
+}
+
+static struct platform_driver at91_ebi_driver = {
+	.driver = {
+		.name = "atmel-ebi",
+		.of_match_table	= at91_ebi_id_table,
+	},
+};
+module_platform_driver_probe(at91_ebi_driver, at91_ebi_probe);
+
+MODULE_AUTHOR("JJ Hiblot");
+MODULE_DESCRIPTION("Atmel EBI driver");
+MODULE_LICENSE("GPL");
-- 
2.7.4



From khiem.nguyen.xt at rvc.renesas.com  Mon May 23 00:51:08 2016
From: khiem.nguyen.xt at rvc.renesas.com (Khiem Nguyen)
Date: Mon, 23 May 2016 14:51:08 +0700
Subject: [PATCH v2 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <CAMuHMdXsu=O13rLysob1Xp+5vWcp7gq6byCffR-6hGc+W-837A@mail.gmail.com>
References: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>
 <1463966906-15129-2-git-send-email-horms+renesas@verge.net.au>
 <CAMuHMdXsu=O13rLysob1Xp+5vWcp7gq6byCffR-6hGc+W-837A@mail.gmail.com>
Message-ID: <5742B66C.7080102@rvc.renesas.com>

Hi Simon, Geert,

On 5/23/2016 2:07 PM, Geert Uytterhoeven wrote:
> On Mon, May 23, 2016 at 3:28 AM, Simon Horman
> <horms+renesas at verge.net.au> wrote:
>> Basic support for the Gen 3 R-Car M3-W SoC.
>>
>> Based on work for the r8a7795 and r8a7796 SoCs by
>> Takeshi Kihara, Dirk Behme and Geert Uytterhoeven.
>>
>> Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
>
>> --- /dev/null
>> +++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
>> @@ -0,0 +1,120 @@
>> +       psci {
>> +               compatible = "arm,psci-1.0";
>
> Do we want to use 1.0 on r8a7795, too?

I think we should apply same setting as r8a7795.
i.e compatible = "arm,psci-0.2";

Using 1.0 will open Suspend-to-RAM support if secure firmware supports 
that feature.
However, we might need additional work in drivers to support 
suspend/resume handlers.
So, I suggest that we keep using 0.2 until Suspend-to-RAM feature is 
confirmed in r8a7795/r8a7796.

Best regards,
KHIEM Nguyen


From boris.brezillon at free-electrons.com  Mon May 23 00:55:57 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Mon, 23 May 2016 09:55:57 +0200
Subject: [PATCH 1/2] Revert "mtd: atmel_nand: Support variable RB_EDGE
 interrupts"
In-Reply-To: <1462776680-5284-2-git-send-email-wenyou.yang@atmel.com>
References: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
 <1462776680-5284-2-git-send-email-wenyou.yang@atmel.com>
Message-ID: <20160523095557.1efea63d@bbrezillon>

On Mon, 9 May 2016 14:51:18 +0800
Wenyou Yang <wenyou.yang at atmel.com> wrote:

> This reverts commit 5ddc7bd43ccc ("mtd: atmel_nand: Support variable
> RB_EDGE interrupts")
> 
> Because for current SoCs, the RB_EDGE3(i.e. bit 27) of HSMC_SR
> register does not exist, the RB_EDGE0 (i.e. bit 24) is the ready/busy
> line edge status bit. It is a datasheet bug.
> 
> Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>

Wenyou, I know you sent it before v4.6 was released, but now we should
probably add

Cc: <stable at vger.kernel.org>

Brian, can you apply this patch directly in your tree (as previously
discussed, I'm not sure creating a nand/fixes branch is really useful)?

Thanks,

Boris

> ---
> 
>  .../devicetree/bindings/mtd/atmel-nand.txt         |  2 +-
>  drivers/mtd/nand/atmel_nand.c                      | 35 +++++-----------------
>  drivers/mtd/nand/atmel_nand_nfc.h                  |  3 +-
>  3 files changed, 10 insertions(+), 30 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> index d53aba9..3e7ee99 100644
> --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> @@ -39,7 +39,7 @@ Optional properties:
>  
>  Nand Flash Controller(NFC) is an optional sub-node
>  Required properties:
> -- compatible : "atmel,sama5d3-nfc" or "atmel,sama5d4-nfc".
> +- compatible : "atmel,sama5d3-nfc".
>  - reg : should specify the address and size used for NFC command registers,
>          NFC registers and NFC SRAM. NFC SRAM address and size can be absent
>          if don't want to use it.
> diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
> index efc8ea2..68b9160 100644
> --- a/drivers/mtd/nand/atmel_nand.c
> +++ b/drivers/mtd/nand/atmel_nand.c
> @@ -67,10 +67,6 @@ struct atmel_nand_caps {
>  	uint8_t pmecc_max_correction;
>  };
>  
> -struct atmel_nand_nfc_caps {
> -	uint32_t rb_mask;
> -};
> -
>  /*
>   * oob layout for large page size
>   * bad block info is on bytes 0 and 1
> @@ -129,7 +125,6 @@ struct atmel_nfc {
>  	/* Point to the sram bank which include readed data via NFC */
>  	void			*data_in_sram;
>  	bool			will_write_sram;
> -	const struct atmel_nand_nfc_caps *caps;
>  };
>  static struct atmel_nfc	nand_nfc;
>  
> @@ -1715,9 +1710,9 @@ static irqreturn_t hsmc_interrupt(int irq, void *dev_id)
>  		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE);
>  		ret = IRQ_HANDLED;
>  	}
> -	if (pending & host->nfc->caps->rb_mask) {
> +	if (pending & NFC_SR_RB_EDGE) {
>  		complete(&host->nfc->comp_ready);
> -		nfc_writel(host->nfc->hsmc_regs, IDR, host->nfc->caps->rb_mask);
> +		nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE);
>  		ret = IRQ_HANDLED;
>  	}
>  	if (pending & NFC_SR_CMD_DONE) {
> @@ -1735,7 +1730,7 @@ static void nfc_prepare_interrupt(struct atmel_nand_host *host, u32 flag)
>  	if (flag & NFC_SR_XFR_DONE)
>  		init_completion(&host->nfc->comp_xfer_done);
>  
> -	if (flag & host->nfc->caps->rb_mask)
> +	if (flag & NFC_SR_RB_EDGE)
>  		init_completion(&host->nfc->comp_ready);
>  
>  	if (flag & NFC_SR_CMD_DONE)
> @@ -1753,7 +1748,7 @@ static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag)
>  	if (flag & NFC_SR_XFR_DONE)
>  		comp[index++] = &host->nfc->comp_xfer_done;
>  
> -	if (flag & host->nfc->caps->rb_mask)
> +	if (flag & NFC_SR_RB_EDGE)
>  		comp[index++] = &host->nfc->comp_ready;
>  
>  	if (flag & NFC_SR_CMD_DONE)
> @@ -1821,7 +1816,7 @@ static int nfc_device_ready(struct mtd_info *mtd)
>  		dev_err(host->dev, "Lost the interrupt flags: 0x%08x\n",
>  				mask & status);
>  
> -	return status & host->nfc->caps->rb_mask;
> +	return status & NFC_SR_RB_EDGE;
>  }
>  
>  static void nfc_select_chip(struct mtd_info *mtd, int chip)
> @@ -1994,8 +1989,8 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
>  		}
>  		/* fall through */
>  	default:
> -		nfc_prepare_interrupt(host, host->nfc->caps->rb_mask);
> -		nfc_wait_interrupt(host, host->nfc->caps->rb_mask);
> +		nfc_prepare_interrupt(host, NFC_SR_RB_EDGE);
> +		nfc_wait_interrupt(host, NFC_SR_RB_EDGE);
>  	}
>  }
>  
> @@ -2426,11 +2421,6 @@ static int atmel_nand_nfc_probe(struct platform_device *pdev)
>  		}
>  	}
>  
> -	nfc->caps = (const struct atmel_nand_nfc_caps *)
> -		of_device_get_match_data(&pdev->dev);
> -	if (!nfc->caps)
> -		return -ENODEV;
> -
>  	nfc_writel(nfc->hsmc_regs, IDR, 0xffffffff);
>  	nfc_readl(nfc->hsmc_regs, SR);	/* clear the NFC_SR */
>  
> @@ -2459,17 +2449,8 @@ static int atmel_nand_nfc_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> -static const struct atmel_nand_nfc_caps sama5d3_nfc_caps = {
> -	.rb_mask = NFC_SR_RB_EDGE0,
> -};
> -
> -static const struct atmel_nand_nfc_caps sama5d4_nfc_caps = {
> -	.rb_mask = NFC_SR_RB_EDGE3,
> -};
> -
>  static const struct of_device_id atmel_nand_nfc_match[] = {
> -	{ .compatible = "atmel,sama5d3-nfc", .data = &sama5d3_nfc_caps },
> -	{ .compatible = "atmel,sama5d4-nfc", .data = &sama5d4_nfc_caps },
> +	{ .compatible = "atmel,sama5d3-nfc" },
>  	{ /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match);
> diff --git a/drivers/mtd/nand/atmel_nand_nfc.h b/drivers/mtd/nand/atmel_nand_nfc.h
> index 0bbc1fa..4d5d262 100644
> --- a/drivers/mtd/nand/atmel_nand_nfc.h
> +++ b/drivers/mtd/nand/atmel_nand_nfc.h
> @@ -42,8 +42,7 @@
>  #define		NFC_SR_UNDEF		(1 << 21)
>  #define		NFC_SR_AWB		(1 << 22)
>  #define		NFC_SR_ASE		(1 << 23)
> -#define		NFC_SR_RB_EDGE0		(1 << 24)
> -#define		NFC_SR_RB_EDGE3		(1 << 27)
> +#define		NFC_SR_RB_EDGE		(1 << 24)
>  
>  #define ATMEL_HSMC_NFC_IER	0x0c
>  #define ATMEL_HSMC_NFC_IDR	0x10



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


From kishon at ti.com  Mon May 23 01:00:18 2016
From: kishon at ti.com (Kishon Vijay Abraham I)
Date: Mon, 23 May 2016 13:30:18 +0530
Subject: [RFC PATCH 2/3] mmc: host: omap_hsmmc: Enable ADMA2
In-Reply-To: <874m9pgs2p.fsf@linux.intel.com>
References: <1463561115-31798-1-git-send-email-kishon@ti.com>
 <1463561115-31798-3-git-send-email-kishon@ti.com>
 <b66f678a-be74-d5f7-f2ef-93b5c9f29b92@ti.com>
 <20160518193028.GT5995@atomide.com>
 <0d463add-9fa5-a768-2ba6-34c4126c7817@ti.com>
 <20160519145745.GU5995@atomide.com> <87shxdlws6.fsf@linux.intel.com>
 <5742A189.4060803@ti.com> <874m9pgs2p.fsf@linux.intel.com>
Message-ID: <5742B892.2070904@ti.com>

Hi Felipe,

On Monday 23 May 2016 12:48 PM, Felipe Balbi wrote:
> 
> Hi Kishon,
> 
> Kishon Vijay Abraham I <kishon at ti.com> writes:
>> Hi Felipe,
>>
>> On Friday 20 May 2016 12:06 AM, Felipe Balbi wrote:
>>>
>>> Hi,
>>>
>>> Tony Lindgren <tony at atomide.com> writes:
>>>> * Peter Ujfalusi <peter.ujfalusi at ti.com> [160519 01:10]:
>>>>> On 05/18/2016 10:30 PM, Tony Lindgren wrote:
>>>>>> Ideally the adma support would be a separate loadable module,
>>>>>> similar how the cppi41dma is a child of the OTG controller.
>>>>>
>>>>> The Master DMA is part of the hsmmc IP block. If the same ADMA module is
>>>>> present on other IPs it might be beneficial to have a helper library to handle
>>>>> it (allocating the descriptor pool, wrinting, updating descriptors, etc).
>>>>
>>>> OK. Yeah if it's part of the MMC controller it makes no sense to
>>>> separate it. So then the conecrns are using alternate DMA
>>>> implementations and keeping PM runtime working :)
>>>>
>>>> BTW, Felipe mentioned that the best thing to do in the long run would
>>>> be to set up sdhci-omap.c operating in ADMA mode.
>>>>
>>>> Felipe, care to summarize what you had in mind?
>>>
>>> yeah, just write a new sdhci-omap.c to start moving away from
>>> omap-hsmmc.c, just like it was done for 8250-omap.
>>>
>>> At the beginning, it could be just the bare minimum to get it working
>>> and slowly move over stuff like pm runtime, dmaengine, PIO. Move more
>>> platforms over to that driver and, eventually, get rid of omap-hsmmc.c
>>> altogether.
>>>
>>> That way, development can be focussed on generic layers (SDHCI) to which
>>> OMAP MMC controller is compliant (apart from the VERSION register
>>> quirk).
>>
>> About an year back, when I tried using SDHCI for OMAP I ran into
>> issues and was not able to get it working. IIRC SDHCI_PRESENT_STATE
>> (or OMAP_HSMMC_PSTATE) was not showing the correct state for card
>> present and is unable to raise an interrupt when a card is inserted. I
>> didn't debug this further.
> 
> I'd say this is a bug in hsmmc. I remember seeing some bits in some
> TI-specific register (before SDHCI address space starts) which can be
> used to keep parts of SDHCI powered on exactly so normal WP and CD pins
> work as expected.
> 
> In any case, adding support for GPIO-based card detect to generic SDHCI
> shouldn't be too difficult :-)
> 
>> It also kept me wondering why gpio interrupt was always used for card
>> detect instead of using mmci_sdcd line of the controller.
> 
> Probably a really, really old bug which nobody ever debugged properly ;-)
> 
> ps: you don't need that ADMA2 DT property, btw. There's a bit in another
> register which you can check if $this controller was configured with
> ADMA2 support or not. IIRC, OMAP5's TRM describes them.

hmm yeah.. Should be the MADMA_EN in MMCHS_HL_HWINFO.

Thanks
Kishon


From srinivas.kandagatla at linaro.org  Mon May 23 01:10:40 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon, 23 May 2016 09:10:40 +0100
Subject: [PATCH V5 0/7] iommu/msm: Add DT adaptation and generic bindings
 support
In-Reply-To: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <5742BB00.3040504@linaro.org>

Hi Sricharan,

Thanks for the patchset,

On 20/05/16 11:54, Sricharan R wrote:
> The msm_iommu.c driver currently works based on platform data.
> A single master device can be connected to more than one iommu and multiple
> contexts in each of the iommu. This association between master and iommus was
> represented from platform data using parent/child devices. The master drivers
> were responsible for attaching all of the iommus/context to a domain. Now the
> platform data support is removed and DT support is added. The master/iommus are
> added through generic iommu bindings.
...
> [V1]
>     https://lists.linuxfoundation.org/pipermail/iommu/2015-August/014074.html
>
> Sricharan R (7):
>    iommu/msm: Add DT adaptation
>    documentation: iommu: Add bindings for msm,iommu-v0 ip
>    iommu/msm: Move the contents from msm_iommu_dev.c to msm_iommu.c
>    iommu/msm: Add support for generic master bindings
>    iommu/msm: use generic ARMV7S short descriptor pagetable ops
>    iommu/msm: Use writel_relaxed and add a barrier
>    iommu/msm: Remove driver BROKEN
>
>   .../devicetree/bindings/iommu/msm,iommu-v0.txt     |  64 ++
>   drivers/iommu/Kconfig                              |   2 +-
>   drivers/iommu/Makefile                             |   2 +-
>   drivers/iommu/msm_iommu.c                          | 885 +++++++++++----------
>   drivers/iommu/msm_iommu.h                          |  73 +-
>   drivers/iommu/msm_iommu_dev.c                      | 381 ---------
>   drivers/iommu/msm_iommu_hw-8xxx.h                  | 109 +--
>   7 files changed, 636 insertions(+), 880 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt
>   delete mode 100644 drivers/iommu/msm_iommu_dev.c


Tested It on IFC6410 and DB600c.

Tested-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>


--srini


From jchandra at broadcom.com  Mon May 23 01:28:36 2016
From: jchandra at broadcom.com (Jayachandran C)
Date: Mon, 23 May 2016 13:58:36 +0530
Subject: [PATCH V7 04/11] pci: Add new function to unmap IO resources.
In-Reply-To: <1462893601-8937-5-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-5-git-send-email-tn@semihalf.com>
Message-ID: <CAKc_7PVYyGNY3fv_w0c+epBP+WyJB8DtnA6f_E-P6Cz2jqbpgA@mail.gmail.com>

On Tue, May 10, 2016 at 8:49 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
> It is very useful to release I/O resources so that the same I/O resources
> can be allocated again (pci_remap_iospace), like in PCI hotplug removal
> scenario. Therefore this patch implements new pci_unmap_iospace call which
> unmaps I/O space as the symmetry to pci_remap_iospace.
>
> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
> ---
>  drivers/pci/pci.c   | 24 ++++++++++++++++++++++++
>  include/linux/pci.h |  1 +
>  2 files changed, 25 insertions(+)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index bc0c914..ff97a0b 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -25,6 +25,7 @@
>  #include <linux/device.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/pci_hotplug.h>
> +#include <linux/vmalloc.h>
>  #include <asm/setup.h>
>  #include <linux/aer.h>
>  #include "pci.h"
> @@ -3167,6 +3168,29 @@ int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
>  #endif
>  }
>
> +/**
> + *     pci_unmap_iospace - Unmap the memory mapped I/O space
> + *     @res: resource to be unmapped
> + *
> + *     Unmap the CPU virtual address @res from virtual address space.
> + *     Only architectures that have memory mapped IO functions defined
> + *     (and the PCI_IOBASE value defined) should call this function.
> + */
> +void  pci_unmap_iospace(struct resource *res)
> +{
> +#if defined(PCI_IOBASE) && defined(CONFIG_MMU)
> +       unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start;
> +
> +       unmap_kernel_range(vaddr, resource_size(res));
> +#else
> +       /*
> +        * This architecture does not have memory mapped I/O space,
> +        * so this function should never be called.
> +        */
> +       WARN_ONCE(1, "This architecture does not support memory mapped I/O\n");
> +#endif
> +}

WARN is not needed here, since we would have already done it in
pci_remap_iospace.

Ideally, we should undo the pci_register_io_range as well, but
re-registering the same range seems to be fine.

JC.


From m.szyprowski at samsung.com  Mon May 23 01:37:55 2016
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Mon, 23 May 2016 10:37:55 +0200
Subject: [RFC 8/9] drivers: of: call iommu_bus_add_dev after
 iommu_configure_ops
In-Reply-To: <1461599894-1969-9-git-send-email-sricharan@codeaurora.org>
References: <1461599894-1969-1-git-send-email-sricharan@codeaurora.org>
 <1461599894-1969-9-git-send-email-sricharan@codeaurora.org>
Message-ID: <898fef51-39a0-09af-4eb9-9a6581ffbe77@samsung.com>

Hello,


On 2016-04-25 17:58, Sricharan R wrote:
> Now that the device's iommu ops are configured at probe time,
> the device has to be added to the iommu late.
>
> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> ---
>   drivers/of/device.c | 4 ++++
>   1 file changed, 4 insertions(+)
>
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index 57a5f2d..722115c 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -6,6 +6,7 @@
>   #include <linux/of_iommu.h>
>   #include <linux/dma-mapping.h>
>   #include <linux/init.h>
> +#include <linux/iommu.h>
>   #include <linux/module.h>
>   #include <linux/mod_devicetable.h>
>   #include <linux/slab.h>
> @@ -154,6 +155,9 @@ int of_dma_configure_ops(struct device *dev, struct device_node *np)
>   	dev_dbg(dev, "device is%sbehind an iommu\n",
>   		iommu ? " " : " not ");
>   
> +	if (iommu)
> +		iommu_bus_add_dev(dev);
> +

This causes build break when IOMMU subsystem is not enabled:

drivers/of/device.c: In function 'of_dma_configure_ops':
drivers/of/device.c:159:3: error: implicit declaration of function 
'iommu_bus_add_dev' [-Werror=implicit-function-declaration]
    iommu_bus_add_dev(dev);
    ^

>   	arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
>   
>   	return 0;

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



From sricharan at codeaurora.org  Mon May 23 01:47:01 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Mon, 23 May 2016 14:17:01 +0530
Subject: [RFC 8/9] drivers: of: call iommu_bus_add_dev after
 iommu_configure_ops
In-Reply-To: <898fef51-39a0-09af-4eb9-9a6581ffbe77@samsung.com>
References: <1461599894-1969-1-git-send-email-sricharan@codeaurora.org>
 <1461599894-1969-9-git-send-email-sricharan@codeaurora.org>
 <898fef51-39a0-09af-4eb9-9a6581ffbe77@samsung.com>
Message-ID: <000801d1b4cf$af951cb0$0ebf5610$@codeaurora.org>

Hi Marek,

>On 2016-04-25 17:58, Sricharan R wrote:
>> Now that the device's iommu ops are configured at probe time,
>> the device has to be added to the iommu late.
>>
>> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
>> ---
>>   drivers/of/device.c | 4 ++++
>>   1 file changed, 4 insertions(+)
>>
>> diff --git a/drivers/of/device.c b/drivers/of/device.c
>> index 57a5f2d..722115c 100644
>> --- a/drivers/of/device.c
>> +++ b/drivers/of/device.c
>> @@ -6,6 +6,7 @@
>>   #include <linux/of_iommu.h>
>>   #include <linux/dma-mapping.h>
>>   #include <linux/init.h>
>> +#include <linux/iommu.h>
>>   #include <linux/module.h>
>>   #include <linux/mod_devicetable.h>
>>   #include <linux/slab.h>
>> @@ -154,6 +155,9 @@ int of_dma_configure_ops(struct device *dev, struct device_node *np)
>>   	dev_dbg(dev, "device is%sbehind an iommu\n",
>>   		iommu ? " " : " not ");
>>
>> +	if (iommu)
>> +		iommu_bus_add_dev(dev);
>> +
>
>This causes build break when IOMMU subsystem is not enabled:
>
>drivers/of/device.c: In function 'of_dma_configure_ops':
>drivers/of/device.c:159:3: error: implicit declaration of function
>'iommu_bus_add_dev' [-Werror=implicit-function-declaration]
>    iommu_bus_add_dev(dev);
>    ^

Ah ok. Thanks for pointing this out. I will repost, with this fixed.
I also realised that PATCH 9, might cause a issue in NON-DT
builds and needs a correction. But otherwise, i am waiting for
suggestions/feedback on how to proceed with this series.

Regards,
 Sricharan



From srinivas.kandagatla at linaro.org  Mon May 23 01:50:56 2016
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Mon, 23 May 2016 09:50:56 +0100
Subject: [PATCH] drivers: nvmem: atmel-secumod: New driver for Atmel
 Secumod nvram
In-Reply-To: <1463605564-14397-1-git-send-email-davidm@egauge.net>
References: <20160518164259.GA28954@rob-hp-laptop>
 <1463605564-14397-1-git-send-email-davidm@egauge.net>
Message-ID: <5742C470.9080708@linaro.org>

Thanks for the patch,
Few minors comments below.

On 18/05/16 22:06, David Mosberger-Tang wrote:
> Signed-off-by: David Mosberger <davidm at egauge.net>
> ---
>   .../devicetree/bindings/nvmem/atmel-secumod.txt    |  47 +++++++
>   drivers/nvmem/Kconfig                              |   7 +
>   drivers/nvmem/Makefile                             |   2 +
>   drivers/nvmem/atmel-secumod.c                      | 143 +++++++++++++++++++++
>   4 files changed, 199 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
>   create mode 100644 drivers/nvmem/atmel-secumod.c
>
> diff --git a/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
> new file mode 100644
> index 0000000..d65cad5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/nvmem/atmel-secumod.txt
> @@ -0,0 +1,47 @@
> += Atmel Secumod device tree bindings =
> +

Can you split the dt-bindings into separate patch.

> +This binding is intended to represent Atmel's Secumod which is found
> +in SAMA5D2 and perhaps others.
> +
> +Required properties:
> +- compatible: should be "atmel,sama5d2-secumod"
> +- reg: Should contain RAM location and length, followed
> +       by register location and length of the Secumod controller.
> +
> += Data cells =
> +Are child nodes of secumod, bindings of which as described in
> +bindings/nvmem/nvmem.txt
> +
> +Example:
> +
> +    secumod at fc040000 {
> +            compatible = "atmel,sama5d2-secumod";
> +            reg = <0xf8044000 0x1420>, <0xfc040000 0x4000>;
> +            reg-names = "SECURAM", "SECUMOD";
> +            status = "okay";
> +
> +            #address-cells = <1>;
> +            #size-cells = <1>;
> +            ranges;
> +
> +            secram-auto-erasable at 0 {
> +                    reg = <0x0000 0x1000>;
> +            };
> +            secram at 1000 {
> +                    reg = <0x1000 0x400>;
> +            };
> +            ram at 1400 {
> +                    reg = <0x1400 0x20>;
> +            };
> +    };
> +
> += Data consumers =
> +Are device nodes which consume nvmem data cells.
> +
> +For example:
> +
> +	ram {
> +		...
> +		nvmem-cells = <&ram>;
> +		nvmem-cell-names = "RAM";
> +	};
> diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
> index 3041d48..88b21e3 100644
> --- a/drivers/nvmem/Kconfig
> +++ b/drivers/nvmem/Kconfig
> @@ -101,4 +101,11 @@ config NVMEM_VF610_OCOTP
>   	  This driver can also be build as a module. If so, the module will
>   	  be called nvmem-vf610-ocotp.
>
> +config NVMEM_ATMEL_SECUMOD
> +       tristate "Atmel Secure Module driver"
> +       depends on ARCH_AT91

COMPILE_TEST ?
Also please add
depends on HAS_IOMEM

> +       help
> +         Select this to get support for the secure module (SECUMOD) built
> +	 into the SAMA5D2 chips.
> +
>   endif
...

> index 0000000..fc5a96b
> --- /dev/null
> +++ b/drivers/nvmem/atmel-secumod.c

...
> +
> +/*
> + * Security-module register definitions:
> + */
> +#define SECUMOD_RAMRDY	0x0014
> +
> +/*
> + * Since the secure module may need to automatically erase some of the
> + * RAM, it may take a while for it to be ready.  As far as I know,
> + * it's not documented how long this might take in the worst-case.
> + */
> +static void
> +secumod_wait_ready (void *regs)
> +{
> +	unsigned long start, stop;
> +
> +	start = jiffies;
> +	while (!(readl(regs + SECUMOD_RAMRDY) & 1))
> +		msleep_interruptible(1);

Worst case would be the system loop here forever, Can we add worst case 
timeout for this, and get out of this loop.

> +	stop = jiffies;
> +	if (stop != start)
> +		pr_info("nvmem-atmel-secumod: it took %u msec for SECUMOD "
> +			"to become ready...\n", jiffies_to_msecs(stop - start));
> +	else
> +		pr_info("nvmem-atmel-secumod: ready\n");
I dont see any use of this prints, We should probably remove these and 
add just a one dev_dbg.

> +}
> +
...
thanks,
srini


From l.stach at pengutronix.de  Mon May 23 02:03:11 2016
From: l.stach at pengutronix.de (Lucas Stach)
Date: Mon, 23 May 2016 11:03:11 +0200
Subject: [PATCH 1/2] ARM: dts: imx6q: extend support for the cm-fx6
In-Reply-To: <709d6b3d522f4fcb8112830e0426dbb3@rwthex-s1-b.rwth-ad.de>
References: <709d6b3d522f4fcb8112830e0426dbb3@rwthex-s1-b.rwth-ad.de>
Message-ID: <1463994191.2370.3.camel@pengutronix.de>

Am Montag, den 23.05.2016, 00:47 +0200 schrieb
christopher.spinrath at rwth-aachen.de:
> From: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>
> 
> The cm-fx6 module has an on-board spi-flash chip for its firmware, an
> eeprom (containing e.g. the mac address of the on-board Ethernet),
> a sata port, a pcie controller, an USB hub, and an USB otg port.
> Enable support for them. In addition, enable syscon poweroff support.
> 
> Signed-off-by: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>
> ---
>  arch/arm/boot/dts/imx6q-cm-fx6.dts | 136 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 136 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx6q-cm-fx6.dts b/arch/arm/boot/dts/imx6q-cm-fx6.dts
> index 99b46f8..f4fc22e 100644
> --- a/arch/arm/boot/dts/imx6q-cm-fx6.dts
> +++ b/arch/arm/boot/dts/imx6q-cm-fx6.dts
> @@ -31,6 +31,61 @@
>  			linux,default-trigger = "heartbeat";
>  		};
>  	};
> +
> +	regulators {
> +		compatible = "simple-bus";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +

Please remove this regulator pseudo-bus. It doesn't exist in hardware.
The regulators are direct children of the module.

> +		reg_usb_otg_vbus: usb_otg_vbus {
> +			compatible = "regulator-fixed";
> +			regulator-name = "usb_otg_vbus";
> +			regulator-min-microvolt = <5000000>;
> +			regulator-max-microvolt = <5000000>;
> +			gpio = <&gpio3 22 0>;
> +			enable-active-high;
> +		};
> +
> +		reg_usb_h1_vbus: usb_h1_vbus {
> +			compatible = "regulator-fixed";
> +			regulator-name = "usb_h1_vbus";
> +			regulator-min-microvolt = <5000000>;
> +			regulator-max-microvolt = <5000000>;
> +			gpio = <&gpio7 8 0>;
> +			enable-active-high;
> +		};
> +	};
> +};
> +
> +&ecspi1 {
> +	fsl,spi-num-chipselects = <2>;
> +	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_ecspi1>;
> +	status = "okay";
> +
> +	flash: m25p80 at 0 {
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		compatible = "st,m25p", "jedec,spi-nor";
> +		spi-max-frequency = <20000000>;
> +		reg = <0>;
> +
> +		partition at 0 {
> +			label = "uboot";
> +			reg = <0x0 0xc0000>;
> +		};
> +
> +		partition at c0000 {
> +			label = "uboot environment";
> +			reg = <0xc0000 0x40000>;
> +		};
> +
> +		partition at 100000 {
> +			label = "reserved";
> +			reg = <0x100000 0x100000>;
> +		};

Partition layouts don't belong in the upstream DT, as it a device
configuration thing. Please kep them in the bootloader/firmware and make
this one pass the partition layout to the kernel.

> +	};
>  };
>  
>  &fec {
> @@ -46,8 +101,31 @@
>  	status = "okay";
>  };
>  
> +&i2c3 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_i2c3>;
> +	status = "okay";
> +	clock-frequency = <100000>;
> +
> +	eeprom at 50 {
> +		compatible = "at24,24c02";
> +		reg = <0x50>;
> +		pagesize = <16>;
> +	};
> +};
> +
>  &iomuxc {
>  	imx6q-cm-fx6 {
> +		pinctrl_ecspi1: ecspi1grp {
> +			fsl,pins = <
> +				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		 0x100b1
> +				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		 0x100b1
> +				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		 0x100b1
> +				MX6QDL_PAD_EIM_EB2__GPIO2_IO30		0x100b1
> +				MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x100b1
> +			>;
> +		};
> +
>  		pinctrl_enet: enetgrp {
>  			fsl,pins = <
>  				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
> @@ -91,17 +169,75 @@
>  			>;
>  		};
>  
> +		pinctrl_i2c3: i2c3grp {
> +			fsl,pins = <
> +				MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
> +				MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
> +			>;
> +		};
> +
> +		pinctrl_pcie: pciegrp {
> +			fsl,pins = <
> +				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000
> +				MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x80000000
> +			>;
> +		};
> +
>  		pinctrl_uart4: uart4grp {
>  			fsl,pins = <
>  				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
>  				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
>  			>;
>  		};
> +
> +		pinctrl_usbh1: usbh1grp {
> +			fsl,pins = <
> +				MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x80000000
> +			>;
> +		};
> +
> +		pinctrl_usbotg: usbotggrp {
> +			fsl,pins = <
> +				MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
> +				MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
> +			>;
> +		};
>  	};
>  };
>  
> +&pcie {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_pcie>;
> +	reset-gpio = <&gpio1 26 0>;
> +	power-on-gpio = <&gpio2 24 0>;

There is no power-on-gpio in the upstream binding.

> +	status = "okay";
> +};
> +
> +&sata {
> +	status = "okay";
> +};
> +
> +&snvs_poweroff {
> +	status = "okay";
> +};
> +
>  &uart4 {
>  	pinctrl-names = "default";
>  	pinctrl-0 = <&pinctrl_uart4>;
>  	status = "okay";
>  };
> +
> +&usbotg {
> +	vbus-supply = <&reg_usb_otg_vbus>;
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_usbotg>;
> +	dr_mode = "otg";
> +	status = "okay";
> +};
> +
> +&usbh1 {
> +	vbus-supply = <&reg_usb_h1_vbus>;
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_usbh1>;
> +	status = "okay";
> +};




From ck.hu at mediatek.com  Mon May 23 02:09:50 2016
From: ck.hu at mediatek.com (CK Hu)
Date: Mon, 23 May 2016 17:09:50 +0800
Subject: [RFC v2 2/5] drm/mediatke: add support for Mediatek SoC MT2701
In-Reply-To: <1463756736-46573-3-git-send-email-yt.shen@mediatek.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
 <1463756736-46573-3-git-send-email-yt.shen@mediatek.com>
Message-ID: <1463994590.31921.14.camel@mtksdaap41>

Hi, YT:

Some comments below.

On Fri, 2016-05-20 at 23:05 +0800, yt.shen at mediatek.com wrote:
> From: YT Shen <yt.shen at mediatek.com>
> 
> This patch add support for the Mediatek MT2701 DISP subsystem.
> There is only one OVL engine in MT2701.
> 
> Signed-off-by: YT Shen <yt.shen at mediatek.com>
>  
> +static void mtk_ddp_mux_sel(void __iomem *config_regs,
> +			    enum mtk_ddp_comp_id cur, enum mtk_ddp_comp_id next)
> +{
> +	if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
> +		writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1,
> +			       config_regs + DISP_REG_CONFIG_OUT_SEL);
> +	}
> +}
> +

The function name 'mux' looks strange. The register written here
controls the single output selection. I prefer to rename it as
mtk_ddp_sout_sel().

>  
> -static const enum mtk_ddp_comp_id mtk_ddp_main[] = {
> +static const enum mtk_ddp_comp_id mtk_ddp_main_2701[] = {
> +	DDP_COMPONENT_OVL0,
> +	DDP_COMPONENT_RDMA0,
> +	DDP_COMPONENT_COLOR0,
> +	DDP_COMPONENT_BLS,
> +	DDP_COMPONENT_DSI0,
> +};
> +
> +static const enum mtk_ddp_comp_id mtk_ddp_ext_2701[] = {
> +	DDP_COMPONENT_OVL0,
> +	DDP_COMPONENT_DSI0,
> +};
> +

These two pipelines has the same component such as OVL0 and DSI0. I
think user program could not enable both crtc at the same time. Maybe
MT2701 has only one crtc, so you should modify initial flow to create
only one crtc for main display. Or it's typo for external display pipe,
please correct it.


Regards,
CK



From henryc.chen at mediatek.com  Mon May 23 02:15:24 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Mon, 23 May 2016 17:15:24 +0800
Subject: [PATCH] soc: mtk-pmic-wrap: avoid integer overflow warning
In-Reply-To: <1463086904-2493288-1-git-send-email-arnd@arndb.de>
References: <1463086904-2493288-1-git-send-email-arnd@arndb.de>
Message-ID: <1463994924.18442.1.camel@mtksdaap41>

Hi,

Thanks to the patch.

On Thu, 2016-05-12 at 23:01 +0200, Arnd Bergmann wrote:
> On ARM64, the mtk-pmic-wrap driver causes a harmless warning:
> 
> mtk-pmic-wrap.c:1062:16: warning: large integer implicitly truncated to unsigned type [-Woverflow]
> mtk-pmic-wrap.c:1074:16: warning: large integer implicitly truncated to unsigned type [-Woverflow]
> mtk-pmic-wrap.c:1086:16: warning: large integer implicitly truncated to unsigned type [-Woverflow]
>   .int_en_all = ~(BIT(31) | BIT(1)),
> 
> The problem is that the result of the BIT() macro is an 'unsigned long',
> so taking the bitwise NOT operation of that results in an integer
> with the upper 32 bits all set and that cannot be assigned to a
> 'u32' variable without loss of information.
> 
> This is harmless because we were never interested in the upper bits
> here anyway, so we can shut up the warning by adding a simple cast
> to 'u32'.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>

Acked-by: Henry Chen <henryc.chen at mediatek.com>

> ---
>  drivers/soc/mediatek/mtk-pmic-wrap.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
> index 3c3e56df526e..a003ba26ca6e 100644
> --- a/drivers/soc/mediatek/mtk-pmic-wrap.c
> +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
> @@ -1059,7 +1059,7 @@ static const struct pmic_wrapper_type pwrap_mt2701 = {
>  	.regs = mt2701_regs,
>  	.type = PWRAP_MT2701,
>  	.arb_en_all = 0x3f,
> -	.int_en_all = ~(BIT(31) | BIT(2)),
> +	.int_en_all = ~(u32)(BIT(31) | BIT(2)),
>  	.spi_w = PWRAP_MAN_CMD_SPI_WRITE_NEW,
>  	.wdt_src = PWRAP_WDT_SRC_MASK_ALL,
>  	.has_bridge = 0,
> @@ -1071,7 +1071,7 @@ static struct pmic_wrapper_type pwrap_mt8135 = {
>  	.regs = mt8135_regs,
>  	.type = PWRAP_MT8135,
>  	.arb_en_all = 0x1ff,
> -	.int_en_all = ~(BIT(31) | BIT(1)),
> +	.int_en_all = ~(u32)(BIT(31) | BIT(1)),
>  	.spi_w = PWRAP_MAN_CMD_SPI_WRITE,
>  	.wdt_src = PWRAP_WDT_SRC_MASK_ALL,
>  	.has_bridge = 1,
> @@ -1083,7 +1083,7 @@ static struct pmic_wrapper_type pwrap_mt8173 = {
>  	.regs = mt8173_regs,
>  	.type = PWRAP_MT8173,
>  	.arb_en_all = 0x3f,
> -	.int_en_all = ~(BIT(31) | BIT(1)),
> +	.int_en_all = ~(u32)(BIT(31) | BIT(1)),
>  	.spi_w = PWRAP_MAN_CMD_SPI_WRITE,
>  	.wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD,
>  	.has_bridge = 0,




From vigneshr at ti.com  Mon May 23 02:18:59 2016
From: vigneshr at ti.com (R, Vignesh)
Date: Mon, 23 May 2016 14:48:59 +0530
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <20160520163404.GC14951@dtor-ws>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
 <1463648641-6931-2-git-send-email-vigneshr@ti.com>
 <20160520163404.GC14951@dtor-ws>
Message-ID: <5742CB03.8010805@ti.com>



On 5/20/2016 10:04 PM, Dmitry Torokhov wrote:
> On Thu, May 19, 2016 at 02:34:00PM +0530, Vignesh R wrote:
>> There are rotary-encoders where GPIO lines reflect the actual position
>> of the rotary encoder dial. For example, if dial points to 9, then four
>> GPIO lines connected to the rotary encoder will read HLLH(1001b = 9).
>> Add support for such rotary-encoder.
>> The driver relies on rotary-encoder,absolute-encoder DT property to
>> detect such encoders.
>> Since, GPIO IRQs are not necessary to work with
>> such encoders, optional polling mode support is added using
>> input_poll_dev skeleton. This is can be used by enabling
>> CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT.
> 
> Does this really belong to a rotary encoder and not a new driver that
> simply translates gpio-encoded value into ABS* event?
> 

Currently rotary encoder driver only supports incremental/step counting
rotary devices. However, the device that is there on am335x-ice is an
absolute encoder but, IMO, nevertheless a kind of rotary encoder. The
only difference is that there is no need to count steps and the absolute
position value is always available as binary encoded state of connected
GPIOs.
The hardware on am335x-ice is a mechanical rotary encoder switch
connected over 4 GPIOs. It is same as binary encoder described at [1]
(except there are 4 GPIO lines), so this lead me to add support in
rotary-encoder.

[1]https://en.wikipedia.org/wiki/Rotary_encoder#Standard_binary_encoding


From m.szyprowski at samsung.com  Mon May 23 02:30:06 2016
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Mon, 23 May 2016 11:30:06 +0200
Subject: [PATCH 0/3] Exynos IOMMU: improve clock management
Message-ID: <1463995809-26862-1-git-send-email-m.szyprowski@samsung.com>

Hello,

This patch series improves clock management in Exynos IOMMU driver, so
the driver will be ready for potential deferred probe caused by
not-yet-available clocks. Such case doesn't happen with current kernel,
but it may happen with the planned rework on clocks and power domain
code.

Best regards
Marek Szyprowski
Samsung R&D Institute Poland


Marek Szyprowski (3):
  iommu/exynos: Return proper errors from getting clocks
  iommu/exynos: Fix master clock management for inactive SYSMMU
  iommu/exynos: Prepare clocks when needed, not in driver probe

 drivers/iommu/exynos-iommu.c | 95 ++++++++++++++++++++------------------------
 1 file changed, 42 insertions(+), 53 deletions(-)

-- 
1.9.2



From m.szyprowski at samsung.com  Mon May 23 02:30:09 2016
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Mon, 23 May 2016 11:30:09 +0200
Subject: [PATCH 3/3] iommu/exynos: Prepare clocks when needed,
 not in driver probe
In-Reply-To: <1463995809-26862-1-git-send-email-m.szyprowski@samsung.com>
References: <1463995809-26862-1-git-send-email-m.szyprowski@samsung.com>
Message-ID: <1463995809-26862-4-git-send-email-m.szyprowski@samsung.com>

Make clock preparation together with clk_enable(). This way inactive
SYSMMU controllers will not keep clocks prepared all the time.
This change allows more fine graded power management in the future.
All the code assumes that clock management doesn't fail, so guard
clock_prepare_enable() it with BUG_ON().

Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
---
 drivers/iommu/exynos-iommu.c | 54 +++++++++++++++++++++-----------------------
 1 file changed, 26 insertions(+), 28 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 018bcd5d5edc..e0b834375f17 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -322,14 +322,27 @@ static void __sysmmu_set_ptbase(struct sysmmu_drvdata *data, phys_addr_t pgd)
 	__sysmmu_tlb_invalidate(data);
 }
 
+static void __sysmmu_enable_clocks(struct sysmmu_drvdata *data)
+{
+	BUG_ON(clk_prepare_enable(data->clk_master));
+	BUG_ON(clk_prepare_enable(data->clk));
+	BUG_ON(clk_prepare_enable(data->pclk));
+	BUG_ON(clk_prepare_enable(data->aclk));
+}
+
+static void __sysmmu_disable_clocks(struct sysmmu_drvdata *data)
+{
+	clk_disable_unprepare(data->aclk);
+	clk_disable_unprepare(data->pclk);
+	clk_disable_unprepare(data->clk);
+	clk_disable_unprepare(data->clk_master);
+}
+
 static void __sysmmu_get_version(struct sysmmu_drvdata *data)
 {
 	u32 ver;
 
-	clk_enable(data->clk_master);
-	clk_enable(data->clk);
-	clk_enable(data->pclk);
-	clk_enable(data->aclk);
+	__sysmmu_enable_clocks(data);
 
 	ver = readl(data->sfrbase + REG_MMU_VERSION);
 
@@ -342,10 +355,7 @@ static void __sysmmu_get_version(struct sysmmu_drvdata *data)
 	dev_dbg(data->sysmmu, "hardware version: %d.%d\n",
 		MMU_MAJ_VER(data->version), MMU_MIN_VER(data->version));
 
-	clk_disable(data->aclk);
-	clk_disable(data->pclk);
-	clk_disable(data->clk);
-	clk_disable(data->clk_master);
+	__sysmmu_disable_clocks(data);
 }
 
 static void show_fault_information(struct sysmmu_drvdata *data,
@@ -427,10 +437,7 @@ static void __sysmmu_disable_nocount(struct sysmmu_drvdata *data)
 	writel(CTRL_DISABLE, data->sfrbase + REG_MMU_CTRL);
 	writel(0, data->sfrbase + REG_MMU_CFG);
 
-	clk_disable(data->aclk);
-	clk_disable(data->pclk);
-	clk_disable(data->clk);
-	clk_disable(data->clk_master);
+	__sysmmu_disable_clocks(data);
 }
 
 static bool __sysmmu_disable(struct sysmmu_drvdata *data)
@@ -475,10 +482,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata *data)
 
 static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
 {
-	clk_enable(data->clk_master);
-	clk_enable(data->clk);
-	clk_enable(data->pclk);
-	clk_enable(data->aclk);
+	__sysmmu_enable_clocks(data);
 
 	writel(CTRL_BLOCK, data->sfrbase + REG_MMU_CTRL);
 
@@ -488,6 +492,12 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
 
 	writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL);
 
+	/*
+	 * SYSMMU driver keeps master's clock enabled only for the short
+	 * time, while accessing the registers. For performing address
+	 * translation during DMA transaction it relies on the client
+	 * driver to enable it.
+	 */
 	clk_disable(data->clk_master);
 }
 
@@ -605,27 +615,18 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 		data->clk = NULL;
 	else if (IS_ERR(data->clk))
 		return PTR_ERR(data->clk);
-	ret = clk_prepare(data->clk);
-	if (ret)
-		return ret;
 
 	data->aclk = devm_clk_get(dev, "aclk");
 	if (PTR_ERR(data->aclk) == -ENOENT)
 		data->aclk = NULL;
 	else if (IS_ERR(data->aclk))
 		return PTR_ERR(data->aclk);
-	ret = clk_prepare(data->aclk);
-	if (ret)
-		return ret;
 
 	data->pclk = devm_clk_get(dev, "pclk");
 	if (PTR_ERR(data->pclk) == -ENOENT)
 		data->pclk = NULL;
 	else if (IS_ERR(data->pclk))
 		return PTR_ERR(data->pclk);
-	ret = clk_prepare(data->pclk);
-	if (ret)
-		return ret;
 
 	if (!data->clk && (!data->aclk || !data->pclk)) {
 		dev_err(dev, "Failed to get device clock(s)!\n");
@@ -637,9 +638,6 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 		data->clk_master = NULL;
 	else if (IS_ERR(data->clk_master))
 		return PTR_ERR(data->clk_master);
-	ret = clk_prepare(data->clk_master);
-	if (ret)
-		return ret;
 
 	data->sysmmu = dev;
 	spin_lock_init(&data->lock);
-- 
1.9.2



From m.szyprowski at samsung.com  Mon May 23 02:30:08 2016
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Mon, 23 May 2016 11:30:08 +0200
Subject: [PATCH 2/3] iommu/exynos: Fix master clock management for inactive
 SYSMMU
In-Reply-To: <1463995809-26862-1-git-send-email-m.szyprowski@samsung.com>
References: <1463995809-26862-1-git-send-email-m.szyprowski@samsung.com>
Message-ID: <1463995809-26862-3-git-send-email-m.szyprowski@samsung.com>

If SYSMMU controller is not active, there is no point in enabling master's
clock just for doing the the of internal state. This patch moves enabling
that clock to the block which actually does the register access.

Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
---
 drivers/iommu/exynos-iommu.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 989365682d14..018bcd5d5edc 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -524,16 +524,15 @@ static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
 {
 	unsigned long flags;
 
-	clk_enable(data->clk_master);
 
 	spin_lock_irqsave(&data->lock, flags);
-	if (is_sysmmu_active(data)) {
-		if (data->version >= MAKE_MMU_VER(3, 3))
-			__sysmmu_tlb_invalidate_entry(data, iova, 1);
+	if (is_sysmmu_active(data) && data->version >= MAKE_MMU_VER(3, 3)) {
+		clk_enable(data->clk_master);
+		__sysmmu_tlb_invalidate_entry(data, iova, 1);
+		clk_disable(data->clk_master);
 	}
 	spin_unlock_irqrestore(&data->lock, flags);
 
-	clk_disable(data->clk_master);
 }
 
 static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
-- 
1.9.2



From m.szyprowski at samsung.com  Mon May 23 02:30:07 2016
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Mon, 23 May 2016 11:30:07 +0200
Subject: [PATCH 1/3] iommu/exynos: Return proper errors from getting clocks
In-Reply-To: <1463995809-26862-1-git-send-email-m.szyprowski@samsung.com>
References: <1463995809-26862-1-git-send-email-m.szyprowski@samsung.com>
Message-ID: <1463995809-26862-2-git-send-email-m.szyprowski@samsung.com>

This patch reworks driver probe code to propagate error codes from
clk_get() operation. This will allow to properly handle deferred probe
in the future.

Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
---
 drivers/iommu/exynos-iommu.c | 56 +++++++++++++++++++-------------------------
 1 file changed, 24 insertions(+), 32 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index e27e3b7df4e7..989365682d14 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -602,37 +602,31 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 	}
 
 	data->clk = devm_clk_get(dev, "sysmmu");
-	if (!IS_ERR(data->clk)) {
-		ret = clk_prepare(data->clk);
-		if (ret) {
-			dev_err(dev, "Failed to prepare clk\n");
-			return ret;
-		}
-	} else {
+	if (PTR_ERR(data->clk) == -ENOENT)
 		data->clk = NULL;
-	}
+	else if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+	ret = clk_prepare(data->clk);
+	if (ret)
+		return ret;
 
 	data->aclk = devm_clk_get(dev, "aclk");
-	if (!IS_ERR(data->aclk)) {
-		ret = clk_prepare(data->aclk);
-		if (ret) {
-			dev_err(dev, "Failed to prepare aclk\n");
-			return ret;
-		}
-	} else {
+	if (PTR_ERR(data->aclk) == -ENOENT)
 		data->aclk = NULL;
-	}
+	else if (IS_ERR(data->aclk))
+		return PTR_ERR(data->aclk);
+	ret = clk_prepare(data->aclk);
+	if (ret)
+		return ret;
 
 	data->pclk = devm_clk_get(dev, "pclk");
-	if (!IS_ERR(data->pclk)) {
-		ret = clk_prepare(data->pclk);
-		if (ret) {
-			dev_err(dev, "Failed to prepare pclk\n");
-			return ret;
-		}
-	} else {
+	if (PTR_ERR(data->pclk) == -ENOENT)
 		data->pclk = NULL;
-	}
+	else if (IS_ERR(data->pclk))
+		return PTR_ERR(data->pclk);
+	ret = clk_prepare(data->pclk);
+	if (ret)
+		return ret;
 
 	if (!data->clk && (!data->aclk || !data->pclk)) {
 		dev_err(dev, "Failed to get device clock(s)!\n");
@@ -640,15 +634,13 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 	}
 
 	data->clk_master = devm_clk_get(dev, "master");
-	if (!IS_ERR(data->clk_master)) {
-		ret = clk_prepare(data->clk_master);
-		if (ret) {
-			dev_err(dev, "Failed to prepare master's clk\n");
-			return ret;
-		}
-	} else {
+	if (PTR_ERR(data->clk_master) == -ENOENT)
 		data->clk_master = NULL;
-	}
+	else if (IS_ERR(data->clk_master))
+		return PTR_ERR(data->clk_master);
+	ret = clk_prepare(data->clk_master);
+	if (ret)
+		return ret;
 
 	data->sysmmu = dev;
 	spin_lock_init(&data->lock);
-- 
1.9.2



From ck.hu at mediatek.com  Mon May 23 02:43:02 2016
From: ck.hu at mediatek.com (CK Hu)
Date: Mon, 23 May 2016 17:43:02 +0800
Subject: [RFC v2 3/5] drm/mediatek: add *driver_data for different
 hardware settings
In-Reply-To: <1463756736-46573-4-git-send-email-yt.shen@mediatek.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
 <1463756736-46573-4-git-send-email-yt.shen@mediatek.com>
Message-ID: <1463996582.30093.5.camel@mtksdaap41>

Hi, YT:

One comment below.

On Fri, 2016-05-20 at 23:05 +0800, yt.shen at mediatek.com wrote:
> From: YT Shen <yt.shen at mediatek.com>
> 
> There are some hardware settings changed, between MT8173 & MT2701:
> DISP_OVL address offset changed, color format definition changed.
> DISP_RDMA fifo size changed.
> DISP_COLOR offset changed.
> 
> Signed-off-by: YT Shen <yt.shen at mediatek.com>
> ---
> +
> +static inline struct mtk_ddp_comp_driver_data *mtk_ovl_get_driver_data(
> +	struct platform_device *pdev)
> +{
> +	const struct of_device_id *of_id =
> +		of_match_device(mtk_disp_ovl_driver_dt_match, &pdev->dev);
> +
> +	return (struct mtk_ddp_comp_driver_data *)of_id->data;
> +}
> +
> +static inline struct mtk_ddp_comp_driver_data *mtk_rdma_get_driver_data(
> +	struct platform_device *pdev)
> +{
> +	const struct of_device_id *of_id =
> +		of_match_device(mtk_disp_rdma_driver_dt_match, &pdev->dev);
> +
> +	return (struct mtk_ddp_comp_driver_data *)of_id->data;
> +}
> +
> +static inline struct mtk_ddp_comp_driver_data *mtk_color_get_driver_data(
> +	struct device_node *node)
> +{
> +	const struct of_device_id *of_id =
> +		of_match_node(mtk_disp_color_driver_dt_match, node);
> +
> +	return (struct mtk_ddp_comp_driver_data *)of_id->data;
> +}
> + 

These three functions looks the same with different parameter:
mtk_disp_ovl_driver_dt_match, mtk_disp_rdma_driver_dt_match, and
mtk_disp_color_driver_dt_match. So merge them to prevent duplicated
code.

Regards,
CK




From eric.engestrom at imgtec.com  Mon May 23 03:35:19 2016
From: eric.engestrom at imgtec.com (Eric Engestrom)
Date: Mon, 23 May 2016 11:35:19 +0100
Subject: [PATCH 1/1] drm/mediatek: do not dereference NULL
In-Reply-To: <1463605190-5323-1-git-send-email-xypron.glpk@gmx.de>
References: <1463605190-5323-1-git-send-email-xypron.glpk@gmx.de>
Message-ID: <20160523103519.GB13596@imgtec.com>

On Wed, May 18, 2016 at 10:59:50PM +0200, Heinrich Schuchardt wrote:
> After having verified that dpi is NULL we should not
> dereference it.
> 
> Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
> ---
>  drivers/gpu/drm/mediatek/mtk_dpi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index d05ca79..3dbd00d 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -433,7 +433,7 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
>  	unsigned int factor;
>  
>  	if (!dpi) {
> -		dev_err(dpi->dev, "invalid argument\n");
> +		dev_err(NULL, "invalid argument\n");
>  		return -EINVAL;
>  	}
>  
> -- 
> 2.1.4

Seems obvious ^^
Reviewed-by: Eric Engestrom <eric.engestrom at imgtec.com>


From matthias.bgg at gmail.com  Mon May 23 03:39:33 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 23 May 2016 12:39:33 +0200
Subject: [PATCH] pinctrl: mediatek: fix dual-edge code defect
In-Reply-To: <1463815419-11719-1-git-send-email-hongkun.cao@mediatek.com>
References: <1463815419-11719-1-git-send-email-hongkun.cao@mediatek.com>
Message-ID: <5742DDE5.7050701@gmail.com>



On 21/05/16 09:23, hongkun.cao at mediatek.com wrote:
> From: "hongkun.cao" <hongkun.cao at mediatek.com>
>
> When a dual-edge irq is triggered, an incorrect irq will be reported on
> condition that the external signal is not stable and this incorrect irq
> has been registered.
> Correct the register offset.
>

I'm not sure what you want to say. From what I can see the without this 
fix, the the wrong IRQ will be cleared and raised. Is this what you are 
addressing?

If so:
Reviewed-by: Matthias Brugger <matthias.bgg at gmail.com>

> Signed-off-by: hongkun.cao <hongkun.cao at mediatek.com>
> ---
>   drivers/pinctrl/mediatek/pinctrl-mtk-common.c |    5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
> index 2bbe6f7..92ae49f 100644
> --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
> +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
> @@ -1255,9 +1255,10 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
>   	const struct mtk_desc_pin *pin;
>
>   	chained_irq_enter(chip, desc);
> -	for (eint_num = 0; eint_num < pctl->devdata->ap_num; eint_num += 32) {
> +	for (eint_num = 0;
> +	     eint_num < pctl->devdata->ap_num;
> +	     eint_num += 32, reg += 4) {
>   		status = readl(reg);
> -		reg += 4;
>   		while (status) {
>   			offset = __ffs(status);
>   			index = eint_num + offset;
>


From mark.rutland at arm.com  Mon May 23 03:47:04 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 23 May 2016 11:47:04 +0100
Subject: [PATCH v2 1/3] regulator: DT: Add DT property for operation mode
 configuration
In-Reply-To: <1463987611-32139-2-git-send-email-henryc.chen@mediatek.com>
References: <1463987611-32139-1-git-send-email-henryc.chen@mediatek.com>
 <1463987611-32139-2-git-send-email-henryc.chen@mediatek.com>
Message-ID: <20160523104703.GB26992@leverpostej>

On Mon, May 23, 2016 at 03:13:29PM +0800, Henry Chen wrote:
> Some regulators support their operating mode to be changed by consumers for
> module specific purpose. Add a DT property to support this.
> 
> Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
> ---
>  Documentation/devicetree/bindings/regulator/regulator.txt |  5 +++++
>  include/dt-bindings/regulator/regulator.h                 | 14 ++++++++++++++
>  2 files changed, 19 insertions(+)
>  create mode 100644 include/dt-bindings/regulator/regulator.h
> 
> diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt
> index ecfc593..e505d0b 100644
> --- a/Documentation/devicetree/bindings/regulator/regulator.txt
> +++ b/Documentation/devicetree/bindings/regulator/regulator.txt
> @@ -49,6 +49,11 @@ Optional properties:
>  	0: Disable active discharge.
>  	1: Enable active discharge.
>  	Absence of this property will leave configuration to default.
> +- regulator-supported-modes: Regulators can run in a variety of different
> +  operating modes depending on output load. This allows further system power
> +  savings by selecting the best (and most efficient) regulator mode for a
> +  desired load. The definition for each of these operation is defined at
> +  include/dt-bindings/regulator/regulator.h

This doesen't tell me for the property is formatted.

Is it a list? A mask?

>  
>  Deprecated properties:
>  - regulator-compatible: If a regulator chip contains multiple
> diff --git a/include/dt-bindings/regulator/regulator.h b/include/dt-bindings/regulator/regulator.h
> new file mode 100644
> index 0000000..2ed1dfd
> --- /dev/null
> +++ b/include/dt-bindings/regulator/regulator.h
> @@ -0,0 +1,14 @@
> +/*
> + * This header provides constants for binding regulator.
> + */
> +
> +#ifndef _DT_BINDINGS_REGULATOR_REGULATOR_H
> +#define _DT_BINDINGS_REGULATOR_REGULATOR_H
> +
> +/* Regulator operating modes */
> +#define REGULATOR_OPERATION_MODE_FAST			0x0
> +#define REGULATOR_OPERATION_MODE_NORMAL			0x1
> +#define REGULATOR_OPERATION_MODE_IDLE			0x2
> +#define REGULATOR_OPERATION_MODE_STANDBY		0x3

These sound like they're tied to linux internal details (e.g. the
implementation of idle and/or suspend).

What do each of these actually mean?

Mark.

> +
> +#endif
> -- 
> 1.8.1.1.dirty
> 


From catalin.marinas at arm.com  Mon May 23 03:54:20 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Mon, 23 May 2016 11:54:20 +0100
Subject: [PATCH] arm: Enable interrupts before calling schedule()
In-Reply-To: <alpine.DEB.2.11.1605201740320.3639@nanos>
References: <alpine.DEB.2.11.1605201740320.3639@nanos>
Message-ID: <20160523105420.GE4892@e104818-lin.cambridge.arm.com>

Hi Thomas,

On Fri, May 20, 2016 at 05:42:17PM +0200, Thomas Gleixner wrote:
> do_work_pending() calls schedule() with interrupts disabled, which is just
> wrong. Fix it.
> 
> Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
> ---
>  arch/arm/kernel/signal.c |    1 +
>  1 file changed, 1 insertion(+)
> 
> --- a/arch/arm/kernel/signal.c
> +++ b/arch/arm/kernel/signal.c
> @@ -573,6 +573,7 @@ do_work_pending(struct pt_regs *regs, un
>  	trace_hardirqs_off();
>  	do {
>  		if (likely(thread_flags & _TIF_NEED_RESCHED)) {
> +			local_irq_enable();
>  			schedule();
>  		} else {
>  			if (unlikely(!user_mode(regs)))

We may have the same bug on arm64 (arch/arm64/kernel/entry.S). Is there
a more fundamental problem with calling schedule() with IRQs off? The
__schedule() function disables the IRQs shortly after it is entered.

To silence IRQ trace warnings on arm64, we merged commit db3899a6477a
("arm64: Add trace_hardirqs_off annotation in ret_to_user"). But we were
also debating whether enabling the IRQs before calling schedule() in
arch/arm64/kernel/entry.S would make more sense. It looks like we need
to revisit this patch:

https://git.kernel.org/cgit/linux/kernel/git/mark/linux.git/commit/?h=arm64/entry-deasm&id=d244472af6e88c55603dc1ba342fae4e85cde31c

Thanks.

-- 
Catalin


From lorenzo.pieralisi at arm.com  Mon May 23 03:56:55 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Mon, 23 May 2016 11:56:55 +0100
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
Message-ID: <20160523105655.GA22902@red-moon>

On Fri, May 20, 2016 at 11:14:03AM +0200, Ard Biesheuvel wrote:
> On 20 May 2016 at 10:40, Gabriele Paoloni <gabriele.paoloni at huawei.com> wrote:
> > Hi Ard
> >
> >> -----Original Message-----
> >> From: Ard Biesheuvel [mailto:ard.biesheuvel at linaro.org]
> [...]
> >>
> >> Is the PCIe root complex so special that you cannot simply describe an
> >> implementation that is not PNP0408 compatible as something else, under
> >> its own unique HID? If everybody is onboard with using ACPI, how is
> >> this any different from describing other parts of the platform
> >> topology? Even if the SBSA mandates generic PCI, they already deviated
> >> from that when they built the hardware, so pretending that it is a
> >> PNP0408 with quirks really does not buy us anything.
> >
> > From my understanding we want to avoid this as this would allow each
> > vendor to come up with his own code and it would be much more effort
> > for the PCI maintainer to rework the PCI framework to accommodate X86
> > and "all" ARM64 Host Controllers...
> >
> > I guess this approach is too risky and we want to avoid this. Through
> > standardization we can more easily maintain the code and scale it to
> > multiple SoCs...
> >
> > So this is my understanding; maybe Jon, Tomasz or Lorenzo can give
> > a bit more explanation...
> >
> 
> OK, so that boils down to recommending to vendors to represent known
> non-compliant hardware as compliant, just so that we don't have to
> change the code to support additional flavors of ECAM ? It's fine to
> be pragmatic, but that sucks.
> 
> We keep confusing the x86 case with the ARM case here: for x86, they
> needed to deal with broken hardware *after* the fact, and all they
> could do is find /some/ distinguishing feature in order to guess which
> exact hardware they might be running on. For arm64, it is the opposite
> case. We are currently in a position where we can demand vendors to
> comply with the standards they endorsed themselves, and (ab)using ACPI
> + DMI as a de facto platform description rather than plain ACPI makes
> me think the DT crowd were actually right from the beginning. It
> *directly* violates the standardization principle, since it requires a
> priori knowledge inside the OS that a certain 'generic' device must be
> driven in a special way.
> 
> So can anyone comment on the feasibility of adding support for devices
> with vendor specific HIDs (and no generic CIDs) to the current ACPI
> ECAM driver in Linux?

Host bridges in ACPI are handled through PNP0A08/PNP0A03 ids, and
most of the arch specific code is handled in the respective arch
directories (X86 and IA64, even though IA64 does not rely on ECAM/MCFG for
PCI ops), it is not a driver per-se, PNP0A08/PNP0A03 are detected through
ACPI scan handlers and the respective arch code (ie pci_acpi_scan_root)
sets-up resources AND config space on an arch specific basis.

X86 deals with that with code in arch/x86 that sets-up the pci_raw_ops
on a platform specific basis (and it is not nice, but it works because
as you all know the number of platforms in X86 world is contained).

Will this happen for ARM64 in arch/arm64 based on vendor specific
HIDs ?

No.

So given the current state of play (we were requested to move the
arch/arm64 specific ACPI PCI bits to arch/arm64), we would end up
with arch/arm64 code requiring code in /drivers to set-up pci_ops
in a platform specific way, it is horrible, if feasible at all.

The only way this can be implemented is by pretending that the
ACPI/PCI arch/arm64 implementation is generic code (that's what this
series does), move it to /drivers (where it is in this series), and
implement _DSD vendor specific bindings (per HID) to set-up the pci
operations; whether this solution should go upstream, given that it
is just a short-term solution for early platforms bugs, it is another
story and my personal answer is no.

Lorenzo


From m.szyprowski at samsung.com  Mon May 23 04:01:27 2016
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Mon, 23 May 2016 13:01:27 +0200
Subject: [PATCH 4/3] iommu/exynos: Prepare for deferred probe support
In-Reply-To: <1463995809-26862-1-git-send-email-m.szyprowski@samsung.com>
References: <1463995809-26862-1-git-send-email-m.szyprowski@samsung.com>
Message-ID: <1464001287-12748-1-git-send-email-m.szyprowski@samsung.com>

Register iommu_ops at the end of successful probe instead of doing that
unconditionally. This makes Exynos IOMMU driver ready for deferred probe
caused by not-yet-available clocks.

Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
---
I'm sorry for the confussing patch number. This patch got lost while
rebasing, but it should belong to the "Exynos IOMMU: improve clock
management" patchset.

Best regards
Marek Szyprowski
Samsung R&D Institute Poland
---
 drivers/iommu/exynos-iommu.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index e0b834375f17..633e6d023c0d 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -581,6 +581,8 @@ static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
 	spin_unlock_irqrestore(&data->lock, flags);
 }
 
+static struct iommu_ops exynos_iommu_ops;
+
 static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 {
 	int irq, ret;
@@ -654,6 +656,8 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 
 	pm_runtime_enable(dev);
 
+	of_iommu_set_ops(dev->of_node, &exynos_iommu_ops);
+
 	return 0;
 }
 
@@ -1347,7 +1351,6 @@ static int __init exynos_iommu_of_setup(struct device_node *np)
 	if (!dma_dev)
 		dma_dev = &pdev->dev;
 
-	of_iommu_set_ops(np, &exynos_iommu_ops);
 	return 0;
 }
 
-- 
1.9.2



From linux at armlinux.org.uk  Mon May 23 04:09:40 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Mon, 23 May 2016 12:09:40 +0100
Subject: [PATCH] arm: Enable interrupts before calling schedule()
In-Reply-To: <20160523105420.GE4892@e104818-lin.cambridge.arm.com>
References: <alpine.DEB.2.11.1605201740320.3639@nanos>
 <20160523105420.GE4892@e104818-lin.cambridge.arm.com>
Message-ID: <20160523110940.GX19428@n2100.arm.linux.org.uk>

On Mon, May 23, 2016 at 11:54:20AM +0100, Catalin Marinas wrote:
> We may have the same bug on arm64 (arch/arm64/kernel/entry.S). Is there
> a more fundamental problem with calling schedule() with IRQs off? The
> __schedule() function disables the IRQs shortly after it is entered.

schedule() does other stuff before entering __schedule() though, such
as calling into the block layer.  This code may have the expectation
that interrupts are enabled.

However, having interrupts enabled in this path (which I'd argue is
special in respect of the "thou shalt not enter schedule() with IRQs
off" rule) opens up the possibility to call into schedule() with the
need_resched flag cleared:

- need_resched was set when returning to userspace, we enter
  do_work_pending().
- do_work_pending() enables IRQs, and an IRQ was pending.
- IRQ is processed, and during that kernel preemption happens, clearing
  this thread's need_resched flag.
- we return to this thread, and now we will enter schedule() with
  need_resched clear.

Whether that matters or not is a different question - and I guess
is a question for scheduler people.

The likelyhood of this happening depends on the IRQ load, but the
requirements are quite simple: need_resched set while returning to
userspace with a pending IRQ.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From matthias.bgg at gmail.com  Mon May 23 04:09:51 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 23 May 2016 13:09:51 +0200
Subject: [RFC PATCH] soc: Amlogic: Add secure monitor driver
In-Reply-To: <CAOQ7t2aCccyqtzQGQ0q+Q4+toAwrVVVLG5=idgZ1eGOLyJMY2g@mail.gmail.com>
References: <1463335845-23534-1-git-send-email-carlo@caione.org>
 <20160516113333.GG656@leverpostej>
 <CAOQ7t2aCccyqtzQGQ0q+Q4+toAwrVVVLG5=idgZ1eGOLyJMY2g@mail.gmail.com>
Message-ID: <5742E4FF.7030504@gmail.com>



On 16/05/16 22:30, Carlo Caione wrote:
> On Mon, May 16, 2016 at 1:33 PM, Mark Rutland <mark.rutland at arm.com> wrote:
>> On Sun, May 15, 2016 at 08:10:45PM +0200, Carlo Caione wrote:
>>> From: Carlo Caione <carlo at endlessm.com>
>>>
>>> Introduce a driver to provide calls into secure monitor mode.
>>>
>>> In the Amlogic SoCs these calls are used for multiple reasons: access to
>>> NVMEM, reboot, set USB boot, enable JTAG, etc...
>>>
>>> Signed-off-by: Carlo Caione <carlo at endlessm.com>
>>> ---
>>>   arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi |   4 +
>>>   drivers/soc/Kconfig                         |   1 +
>>>   drivers/soc/Makefile                        |   1 +
>>>   drivers/soc/amlogic/Kconfig                 |   8 ++
>>>   drivers/soc/amlogic/Makefile                |   1 +
>>>   drivers/soc/amlogic/meson_sm.c              | 141 ++++++++++++++++++++++++++++
>>>   include/linux/soc/amlogic/meson_sm.h        |  57 +++++++++++
>>>   7 files changed, 213 insertions(+)
>>
>> The binding is missing documentation.
>
> Yes, not much to document for this RFC.
>
>> Is there any documentation of the actual interface?
>
> There isn't or at least I do not have it. This driver has been written
> by reverse engineering the Amlogic driver shipped in their SDK [1]
>
>> Are there any restrictions on how it's used? It looks like calls are
>> only expected to happen from the boot CPU, per the code below.
>
> Yes, that's what I could infer from the Amlogic code here [2] but then
> I checked this better and it seems that's not the case (see below).
>
>> There are no users in this patch. Are there any example uses (i.e.
>> specific code rather than the high-level examples above)?
>
> I use it already to read the NVMEM. It works fine.
> I'll submit the NVMEM driver as soon as I have this merged (if ever)
>
>>>   create mode 100644 drivers/soc/amlogic/Kconfig
>>>   create mode 100644 drivers/soc/amlogic/Makefile
>>>   create mode 100644 drivers/soc/amlogic/meson_sm.c
>>>   create mode 100644 include/linux/soc/amlogic/meson_sm.h
>>>
>>> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>>> index 76b3b6d..e4017c3 100644
>>> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>>> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
>>> @@ -98,6 +98,10 @@
>>>                method = "smc";
>>>        };
>>>
>>> +     sm {
>>> +             compatible = "amlogic,meson-sm";
>>> +     };
>>
>> We should have more specific strings, at least in addition to this.
>
> Agree, not sure what I can add though.

I would say someting linke "amlogic,gxbb-sm" to specify the SoC.

>
> [...]
>>> +struct meson_sm_data {
>>> +     unsigned int cmd;
>>> +     unsigned int arg0;
>>> +     unsigned int arg1;
>>> +     unsigned int arg2;
>>> +     unsigned int arg3;
>>> +     unsigned int arg4;
>>> +     unsigned int ret;
>>> +};
>>
>> Please be explicit and use u32 rather than unsigned int.
>
> Ok
>
>> It looks like all the calls you care about are SMC32 SiP calls, per the
>> IDs in the header.
>
> Yes, all the SMC function identifiers I gathered from the Amlogic
> sources are SMC32 SiP calls
>
>>> +
>>> +static void __meson_sm_call(void *info)
>>> +{
>>> +     struct meson_sm_data *data = info;
>>> +     struct arm_smccc_res res;
>>> +
>>> +     arm_smccc_smc(data->cmd,
>>> +                   data->arg0, data->arg1, data->arg2,
>>> +                   data->arg3, data->arg4, 0, 0, &res);
>>> +     data->ret = res.a0;
>>> +}
>>> +
>>> +unsigned int meson_sm_call(unsigned int cmd, unsigned int arg0,
>>> +                        unsigned int arg1, unsigned int arg2,
>>> +                        unsigned int arg3, unsigned int arg4)
>>> +{
>>> +     struct meson_sm_data data;
>>> +
>>> +     data.cmd = cmd;
>>> +     data.arg0 = arg0;
>>> +     data.arg1 = arg1;
>>> +     data.arg2 = arg2;
>>> +     data.arg3 = arg3;
>>> +     data.arg4 = arg4;
>>> +     data.ret = 0;
>>> +
>>> +     smp_call_function_single(0, __meson_sm_call, &data, 1);
>>
>> Why must this occur on a particular CPU?
>>
>> With kexec and so on logical CPU 0 is not necessarily the CPU that the
>> FW brought out of reset.
>
> You are right. I tried to move this to a different CPU and it keeps
> working fine. Still I wonder why Amlogic has something like [2]
>
>> Can the core with the secure OS be powered down, or is that prevented
>> with the usual PSCI machinery (e.g. MIGRATE, MIGRATE_INFO_TYPE,
>> MIGRATE_INFO_UP_CPU)
>>
>> I would recommend that any CPU restriction were described explicitly in
>> the DT, or detected dynamically based on the MIGRATE_INFO_UP_CPU value.
>
> MIGRATE_INFO_TYPE returns PSCI_0_2_TOS_MP. Does this confirm that the
> SMC calls can happen not only from the CPU 0?
>
>>> +
>>> +     return data.ret;
>>> +}
>>> +
>>> +unsigned int meson_sm_call_read(void *buffer, unsigned int cmd,
>>> +                             unsigned int arg0, unsigned int arg1,
>>> +                             unsigned int arg2, unsigned int arg3,
>>> +                             unsigned int arg4)
>>> +{
>>> +     unsigned int size;
>>> +
>>> +     size = meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
>>> +
>>> +     if (size != 0)
>>
>> Is the size guaranteed to never be > SM_MEM_SIZE? Can we sanity-check
>> that?
>
> Fix in v2
>
>> The call can't return an error code?
>
> 0 in R0 is considered error that we return back.
>
>>> +             memcpy(buffer, sm_sharemem_out_base, size);
>>
>> Is the buffer completely opaque to this layer?
>>
>> Are there any endianness concerns, for example?
>
> The best answer I can give you here is: not that I know of.
> The driver works fine when reading from the NVMEM, so I assume there
> isn't any endiness issue.
>
>>> +
>>> +     return size;
>>> +}
>>> +
>>> +unsigned int meson_sm_call_write(void *buffer, unsigned int size,
>>> +                              unsigned int cmd, unsigned int arg0,
>>> +                              unsigned int arg1, unsigned int arg2,
>>> +                              unsigned int arg3, unsigned int arg4)
>>> +{
>>> +     memcpy(sm_sharemem_in_base, buffer, size);
>>> +
>>> +     return meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
>>> +}
>>> +
>>> +static int meson_sm_probe(struct platform_device *pdev)
>>> +{
>>> +     sm_phy_in_base = meson_sm_call(SM_GET_SHARE_MEM_INPUT_BASE, 0, 0, 0, 0, 0);
>>> +
>>> +     sm_sharemem_in_base = ioremap_cache(sm_phy_in_base, SM_MEM_SIZE);
>>> +     if (!sm_sharemem_in_base)
>>> +             return -EINVAL;
>>
>> Are the attributes used for ioremap_cache guaranteed to match and not
>> cause a mismatched alias against the firmware's mapping?
>>
>> Which precise memory attributes does the secure firmware use for the
>> shared memory?
>
> Again I wish I had more information. Is there any way I can check this?
> The only reasonable answer I can give you right now is that this is
> how it is done in the original Amlogic driver in [1]
>
> [...]
>>> +#define SM_GET_SHARE_MEM_INPUT_BASE          0x82000020
>>> +#define SM_GET_SHARE_MEM_OUTPUT_BASE         0x82000021
>>> +#define SM_GET_REBOOT_REASON                 0x82000022
>>> +#define SM_GET_SHARE_STORAGE_IN_BASE         0x82000023
>>> +#define SM_GET_SHARE_STORAGE_OUT_BASE                0x82000024
>>> +#define SM_GET_SHARE_STORAGE_BLOCK_BASE              0x82000025
>>> +#define SM_GET_SHARE_STORAGE_MESSAGE_BASE    0x82000026
>>> +#define SM_GET_SHARE_STORAGE_BLOCK_SIZE              0x82000027
>>> +#define SM_EFUSE_READ                                0x82000030
>>> +#define SM_EFUSE_WRITE                               0x82000031
>>> +#define SM_EFUSE_WRITE_PATTERN                       0x82000032
>>> +#define SM_EFUSE_USER_MAX                    0x82000033
>>> +#define SM_JTAG_ON                           0x82000040
>>> +#define SM_JTAG_OFF                          0x82000041
>>> +#define SM_SET_USB_BOOT_FUNC                 0x82000043
>>> +#define SM_SECURITY_KEY_QUERY                        0x82000060
>>> +#define SM_SECURITY_KEY_READ                 0x82000061
>>> +#define SM_SECURITY_KEY_WRITE                        0x82000062
>>> +#define SM_SECURITY_KEY_TELL                 0x82000063
>>> +#define SM_SECURITY_KEY_VERIFY                       0x82000064
>>> +#define SM_SECURITY_KEY_STATUS                       0x82000065
>>> +#define SM_SECURITY_KEY_NOTIFY                       0x82000066
>>> +#define SM_SECURITY_KEY_LIST                 0x82000067
>>> +#define SM_SECURITY_KEY_REMOVE                       0x82000068
>>> +#define SM_DEBUG_EFUSE_WRITE_PATTERN         0x820000F0
>>> +#define SM_DEBUG_EFUSE_READ_PATTERN          0x820000F1
>>> +#define SM_AML_DATA_PROCESS                  0x820000FF
>>
>> Is there any documentation for these functions?
>
> Unfortunately there isn't.
> I could restrict the list to those functions I know how to use
> (*_EFUSE) maybe adding the remaining ones when we actually use them.
>
>>> +#define SM_PSCI_SYS_REBOOT                   0x84000009
>>
>> The existing PCSI code should be the only caller of this. This should
>> not be used here.
>
> Ups, that slipped through when pasting the list.
>
> Thank you for reviewing this RFC, I'll submit a v2 soon.
>
> Cheers,
>
> [1] https://github.com/hardkernel/linux/blob/odroidc2-3.14.y/drivers/amlogic/secmon/secmon.c
> [2] https://github.com/hardkernel/linux/blob/odroidc2-3.14.y/drivers/amlogic/efuse/efuse_hw64.c#L94
>


From carlo at caione.org  Mon May 23 04:16:19 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 23 May 2016 13:16:19 +0200
Subject: [RFC PATCH] soc: Amlogic: Add secure monitor driver
In-Reply-To: <5742E4FF.7030504@gmail.com>
References: <1463335845-23534-1-git-send-email-carlo@caione.org>
 <20160516113333.GG656@leverpostej>
 <CAOQ7t2aCccyqtzQGQ0q+Q4+toAwrVVVLG5=idgZ1eGOLyJMY2g@mail.gmail.com>
 <5742E4FF.7030504@gmail.com>
Message-ID: <20160523111619.GB17269@mephisto>

On 23/05/16 13:09, Matthias Brugger wrote:
 
[...]
> >>>diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> >>>index 76b3b6d..e4017c3 100644
> >>>--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> >>>+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
> >>>@@ -98,6 +98,10 @@
> >>>               method = "smc";
> >>>       };
> >>>
> >>>+     sm {
> >>>+             compatible = "amlogic,meson-sm";
> >>>+     };
> >>
> >>We should have more specific strings, at least in addition to this.
> >
> >Agree, not sure what I can add though.
> 
> I would say someting linke "amlogic,gxbb-sm" to specify the SoC.

If you look at v2 of this patchset [1] I separated the SoC specific
SMC32 function definitions in a separate header file so I think the main
driver is generic enough to be called meson-sm.

Cheers,

[1] http://www.spinics.net/lists/arm-kernel/msg505087.html

-- 
Carlo Caione


From vigneshr at ti.com  Mon May 23 04:18:40 2016
From: vigneshr at ti.com (R, Vignesh)
Date: Mon, 23 May 2016 16:48:40 +0530
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <20160522102606.GB23704@pengutronix.de>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
 <1463648641-6931-2-git-send-email-vigneshr@ti.com>
 <20160522102606.GB23704@pengutronix.de>
Message-ID: <5742E710.9@ti.com>



On 5/22/2016 3:56 PM, Uwe Kleine-K?nig wrote:
> Hello,
> 
> On Thu, May 19, 2016 at 02:34:00PM +0530, Vignesh R wrote:
>> There are rotary-encoders where GPIO lines reflect the actual position
>> of the rotary encoder dial. For example, if dial points to 9, then four
>> GPIO lines connected to the rotary encoder will read HLLH(1001b = 9).
>> Add support for such rotary-encoder.
>> The driver relies on rotary-encoder,absolute-encoder DT property to
>> detect such encoders.
>> Since, GPIO IRQs are not necessary to work with
>> such encoders, optional polling mode support is added using
> 
> I don't understand this. It's necessary in the same way as with the
> already supported devices. I.e. you want to trigger an irq when the
> encoder is moved and then check for it's position in the handler.
> 

Unlike already supported device, there is no need to count steps or
determine the direction of rotation. Hence, IRQ is not a requirement,
periodically polling the gpio lines is more than sufficient. With
absolute encoder, you are able to determine the current position at any
time just by looking at the gpio inputs.
Suppose we poll device at t=0ms and see gpio values are LLLH(1), if we
again poll device at t=500ms(which is what input_poll_dev helps to do)
and see that gpio values is LLHH(3), then we know that rotary encoder
has changed to 3. This can be done w/o IRQ for absolute encoders.

>> diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
>> index 6c9f0c8a846c..9c928dbd1500 100644
>> --- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
>> +++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
>> @@ -12,6 +12,10 @@ Optional properties:
>>  - rotary-encoder,relative-axis: register a relative axis rather than an
>>    absolute one. Relative axis will only generate +1/-1 events on the input
>>    device, hence no steps need to be passed.
>> +- rotary-encoder,absolute-encoder: support encoders where GPIO lines
>> +  reflect the actual position of the rotary encoder dial. For example,
>> +  if dial points to 9, then four GPIO lines read HLLH(1001b = 9).
>> +  In this case, rotary-encoder,steps-per-period needed not be defined.
> 
> IMHO this is wrong, I'd formalize this device as:
> 
> 	{
> 		compatible = "rotary-encoder";
> 		gpios = <&gpio 19 1>, <&gpio 20 0>, <...>, <...>;
> 		rotary-encoder,encoding = "binary";
> 		rotary-encoder,steps = <16>;
> 		rotary-encoder,steps-per-period = <16>;

The above bindings essential means quarter_period device. I would not
like to bother with all the logic in rotary_encoder_quarter_period_irq()
when we can know encoder->pos by directly reading state of gpio lines.

> 		rotary-encoder,rollover;
> 	}
> 
> and support this with a v4 of
> 
> 	http://thread.gmane.org/gmane.linux.kernel.input/48892
> 
>

IMHO, there needs to be separate IRQ handler for absolute encoders so
that the driver logic is greatly simplified.



From broonie at kernel.org  Mon May 23 04:28:56 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 23 May 2016 12:28:56 +0100
Subject: [PATCH v2 1/3] regulator: DT: Add DT property for operation mode
 configuration
In-Reply-To: <20160523104703.GB26992@leverpostej>
References: <1463987611-32139-1-git-send-email-henryc.chen@mediatek.com>
 <1463987611-32139-2-git-send-email-henryc.chen@mediatek.com>
 <20160523104703.GB26992@leverpostej>
Message-ID: <20160523112856.GR8206@sirena.org.uk>

On Mon, May 23, 2016 at 11:47:04AM +0100, Mark Rutland wrote:

> > +/* Regulator operating modes */
> > +#define REGULATOR_OPERATION_MODE_FAST			0x0
> > +#define REGULATOR_OPERATION_MODE_NORMAL			0x1
> > +#define REGULATOR_OPERATION_MODE_IDLE			0x2
> > +#define REGULATOR_OPERATION_MODE_STANDBY		0x3

> These sound like they're tied to linux internal details (e.g. the
> implementation of idle and/or suspend).

> What do each of these actually mean?

They are not really at all general and I'm fairly sure I've provided the
same feedback repeatedly on earlier versions of the patch set.  They are
not entirely based on Linux internal details (or at least the Linux
internal details tend to flow from the hardware) - broadly fast is
forced PWM, normal is default, idle is LDO mode and standby is a lower
quality LDO mode - but how this translates into anything that a consumer
could actually use is unclear since the supported output loads and
quality of regulation can vary wildy.  It's also somewhat implementation
dependent what a given regulator does (and it's always possible that
some regulators may have more modes to control or differing definitions
in the hardware).

Henry, *please* look at how the existing mode support in the bindings is
done and consider how a consumer would use this given that it doesn't
know anything about the regulator...
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160523/45c856a7/attachment.sig>

From broonie at kernel.org  Mon May 23 04:29:53 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 23 May 2016 12:29:53 +0100
Subject: [PATCH v2 3/3] regulator: mt6397: Add buck change mode regulator
 interface for mt6397
In-Reply-To: <1463987611-32139-4-git-send-email-henryc.chen@mediatek.com>
References: <1463987611-32139-1-git-send-email-henryc.chen@mediatek.com>
 <1463987611-32139-4-git-send-email-henryc.chen@mediatek.com>
Message-ID: <20160523112953.GS8206@sirena.org.uk>

On Mon, May 23, 2016 at 03:13:31PM +0800, Henry Chen wrote:
> BUCKs of mt6397 have auto mode and pwm mode.
> User can use regulator interfaces to control modes

This doesn't apply against current code, please check and resend.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160523/2d7f72d9/attachment.sig>

From broonie at kernel.org  Mon May 23 04:32:22 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 23 May 2016 12:32:22 +0100
Subject: [PATCH] regulator: mt6397: Constify struct regulator_ops
In-Reply-To: <1463988616-18803-1-git-send-email-henryc.chen@mediatek.com>
References: <1463988616-18803-1-git-send-email-henryc.chen@mediatek.com>
Message-ID: <20160523113222.GT8206@sirena.org.uk>

On Mon, May 23, 2016 at 03:30:16PM +0800, Henry Chen wrote:
> Consitify the structure of regulator operations.

Oh, actually the mode setting patch does apply but it depends on this
one (which was sent after...).  It would have been better to send a
patch series for the driver and separately a patch series for the core,
the driver changes are orthogonal to the core ones here.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160523/1a6c87dd/attachment.sig>

From tn at semihalf.com  Mon May 23 04:34:08 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 23 May 2016 13:34:08 +0200
Subject: [PATCH V7 08/11] pci, acpi: Support for ACPI based generic PCI
 host controller
In-Reply-To: <CAKc_7PVz8rgCTqMVuR7g944nonSHExAhx5rNsjiP3J=9LfA99g@mail.gmail.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <1462893601-8937-9-git-send-email-tn@semihalf.com>
 <CAKc_7PVz8rgCTqMVuR7g944nonSHExAhx5rNsjiP3J=9LfA99g@mail.gmail.com>
Message-ID: <5742EAB0.1080006@semihalf.com>

On 14.05.2016 11:07, Jayachandran C wrote:
> On Tue, May 10, 2016 at 8:49 PM, Tomasz Nowicki <tn at semihalf.com> wrote:
>> This patch is going to implement generic PCI host controller for
>> ACPI world, similar to what pci-host-generic.c driver does for DT world.
>>
>> All such drivers, which we have seen so far, were implemented within
>> arch/ directory since they had some arch assumptions (x86 and ia64).
>> However, they all are doing similar thing, so it makes sense to find
>> some common code and abstract it into the generic driver.
>>
>> In order to handle PCI config space regions properly, we define new
>> MCFG interface which does sanity checks on MCFG table and keeps its
>> root pointer. User is able to lookup MCFG regions based on that root
>> pointer and specified domain:bus_start:bus_end touple. We are using
>> pci_mmcfg_late_init old prototype to avoid another function name.
>>
>> The implementation of pci_acpi_scan_root() looks up the MCFG entries
>> and sets up a new mapping (regions are not mapped until host controller ask
>> for it). Generic PCI functions are used for accessing config space.
>> Driver selects PCI_ECAM and uses functions from drivers/pci/ecam.h
>> to create and access ECAM mappings.
>>
>> As mentioned in Kconfig help section, ACPI_PCI_HOST_GENERIC choice
>> should be made on a per-architecture basis.
>
> Looking thru the new code, I see a few issues, please see below
>
>> Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
>> Signed-off-by: Jayachandran C <jchandra at broadcom.com>
>> ---
>>   drivers/acpi/Kconfig            |   8 +++
>>   drivers/acpi/Makefile           |   1 +
>>   drivers/acpi/pci_mcfg.c         |  97 ++++++++++++++++++++++++++
>>   drivers/acpi/pci_root_generic.c | 149 ++++++++++++++++++++++++++++++++++++++++
>>   drivers/pci/ecam.h              |   5 ++
>>   include/linux/pci-acpi.h        |   5 ++
>>   include/linux/pci.h             |   5 +-
>>   7 files changed, 269 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/acpi/pci_mcfg.c
>>   create mode 100644 drivers/acpi/pci_root_generic.c
>>
>> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
>> index 183ffa3..44afc76 100644
>> --- a/drivers/acpi/Kconfig
>> +++ b/drivers/acpi/Kconfig
>> @@ -346,6 +346,14 @@ config ACPI_PCI_SLOT
>>            i.e., segment/bus/device/function tuples, with physical slots in
>>            the system.  If you are unsure, say N.
>>
>> +config ACPI_PCI_HOST_GENERIC
>> +       bool
>> +       select PCI_ECAM
>> +       help
>> +         Select this config option from the architecture Kconfig,
>> +         if it is preferred to enable ACPI PCI host controller driver which
>> +         has no arch-specific assumptions.
>> +
>>   config X86_PM_TIMER
>>          bool "Power Management Timer Support" if EXPERT
>>          depends on X86
>> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
>> index 81e5cbc..627a2b7 100644
>> --- a/drivers/acpi/Makefile
>> +++ b/drivers/acpi/Makefile
>> @@ -40,6 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
>>   acpi-y                         += ec.o
>>   acpi-$(CONFIG_ACPI_DOCK)       += dock.o
>>   acpi-y                         += pci_root.o pci_link.o pci_irq.o
>> +obj-$(CONFIG_ACPI_PCI_HOST_GENERIC)    += pci_root_generic.o pci_mcfg.o
>>   acpi-y                         += acpi_lpss.o acpi_apd.o
>>   acpi-y                         += acpi_platform.o
>>   acpi-y                         += acpi_pnp.o
>> diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
>> new file mode 100644
>> index 0000000..373d079
>> --- /dev/null
>> +++ b/drivers/acpi/pci_mcfg.c
>> @@ -0,0 +1,97 @@
>> +/*
>> + * Copyright (C) 2016 Broadcom
>> + *     Author: Jayachandran C <jchandra at broadcom.com>
>> + * Copyright (C) 2016 Semihalf
>> + *     Author: Tomasz Nowicki <tn at semihalf.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License, version 2, as
>> + * published by the Free Software Foundation (the "GPL").
>> + *
>> + * 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 version 2 (GPLv2) for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * version 2 (GPLv2) along with this source code.
>> + */
>> +#include <linux/kernel.h>
>> +#include <linux/pci.h>
>> +#include <linux/pci-acpi.h>
>> +
>> +#define PREFIX "ACPI: "
>> +
>> +/* Root pointer to the mapped MCFG table */
>> +static struct acpi_table_mcfg *mcfg_table;
>> +
>> +#define MCFG_ENTRIES(mcfg_ptr) (((mcfg_ptr)->header.length -           \
>> +                               sizeof(struct acpi_table_mcfg)) /       \
>> +                               sizeof(struct acpi_mcfg_allocation))
>
> It would be better if you used static inline function here.

OK

>
>> +static phys_addr_t pci_mcfg_lookup_static(u16 seg, u8 bus_start, u8 bus_end)
>> +{
>> +       struct acpi_mcfg_allocation *mptr;
>> +       int i;
>> +
>> +       if (!mcfg_table) {
>> +               pr_err(PREFIX "MCFG table not available, lookup failed\n");
>> +               return -ENXIO;
>> +       }
>> +
>> +       mptr = (struct acpi_mcfg_allocation *) &mcfg_table[1];
>> +
>> +       /*
>> +        * We expect exact match, unless MCFG entry end bus covers more than
>> +        * specified by caller.
>> +        */
>> +       for (i = 0; i < MCFG_ENTRIES(mcfg_table); i++, mptr++) {
>> +               if (mptr->pci_segment == seg &&
>> +                   mptr->start_bus_number == bus_start &&
>> +                   mptr->end_bus_number >= bus_end) {
>> +                       return mptr->address;
>> +               }
>> +       }
>
> There is an issue here, the bus range is obtained if different
> ways. If the _CRS has it, this should be fine. But if it is _BBN-0xff
> or the default 0-0xff, then I would think taking the MCFG entry end
> would be better. This would require updating the bus resource end.

Yeah we can implement algorithm like that but IMO it would try to guess 
what FW designer meant putting various combination of BUS resources into 
the tables. We should rather be strict about this so I agree with Bjorn:
https://lkml.org/lkml/2016/4/28/807
Either we get exact match or MCFG covers more than the host bridge range.

Host bridge bus range definition -> MCFG
_BBN-0xff -> we expect exact _BBN-0xff match
0-0xff -> ditto
_CRS (the only way to trim host bridge bus rage) -> exact match or MCFG 
covers more

>
> Also (trivial), the braces are not needed.

OK

>
>> +       return -ENXIO;
>> +}
>> +
>> +phys_addr_t pci_mcfg_lookup(struct acpi_device *device, u16 seg,
>> +                           struct resource *bus_res)
>> +{
>> +       phys_addr_t addr;
>> +
>> +       addr = acpi_pci_root_get_mcfg_addr(device->handle);
>> +       if (addr)
>> +               return addr;
>
> When you have address from _CBA, you are assuming that the
> bus range is also set correctly (from _CRS or as _BBN-0xff). Is
> this assumption correct?

I think so, see above. Maybe Bjorn may advise here.

>
> (this was discussed earlier)  you are doing the _CBA call again,
> I think cleaning up the _CBA, _BBN, _CRS and MCFG based
> ECAM area resources and defaults should be a different patch,
> which would need changes to pci_root.c. We should use
> root->mcfg_addr in this patchset.

OK

>
>> +
>> +       return pci_mcfg_lookup_static(seg, bus_res->start, bus_res->end);
>
> There is no need to have a separate function for this, based on by
> above comment, you might need to change bus_res, so having it here
> would be better.
>
>> +}
>> +
>> +static __init int pci_mcfg_parse(struct acpi_table_header *header)
>> +{
>> +       struct acpi_table_mcfg *mcfg;
>> +       int n;
>> +
>> +       if (!header)
>> +               return -EINVAL;
>
> This is not needed, the handler is not called if header is NULL

OK

>
>> +
>> +       mcfg = (struct acpi_table_mcfg *)header;
>> +       n = MCFG_ENTRIES(mcfg);
>> +       if (n <= 0 || n > 255) {
>> +               pr_err(PREFIX "MCFG has incorrect entries (%d).\n", n);
>> +               return -EINVAL;
>> +       }
>>
>> +       mcfg_table = mcfg;
>
> Saving a reference of ACPI mapping seems dangerous, acpi_parse_table
> calles early_acpi_os_unmap_memory() after calling handler, which does
> not do anything since acpi_gbl_permanent_mmap is set.
>
> I would suggest copying the entries.

You got the point about early_acpi_os_unmap_memory but that would be the 
case if we call pci_mmcfg_late_init before acpi_early_init. But 
pci_mmcfg_late_init is called much later. Also the code is much simpler 
as is now.

Thanks,
Tomasz


From matthias.bgg at gmail.com  Mon May 23 04:38:44 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 23 May 2016 13:38:44 +0200
Subject: [PATCH v2 1/4] soc: Amlogic: Add secure monitor driver
In-Reply-To: <1463583382-15614-2-git-send-email-carlo@caione.org>
References: <1463583382-15614-1-git-send-email-carlo@caione.org>
 <1463583382-15614-2-git-send-email-carlo@caione.org>
Message-ID: <5742EBC4.3050704@gmail.com>



On 18/05/16 16:56, Carlo Caione wrote:
> From: Carlo Caione <carlo at endlessm.com>
>
> Introduce a driver to provide calls into secure monitor mode.
>
> In the Amlogic SoCs these calls are used for multiple reasons: access to
> NVMEM, set USB boot, enable JTAG, etc...
>
> Signed-off-by: Carlo Caione <carlo at endlessm.com>
> ---
>   drivers/soc/Kconfig                |   1 +
>   drivers/soc/Makefile               |   1 +
>   drivers/soc/meson/Kconfig          |   8 ++
>   drivers/soc/meson/Makefile         |   1 +
>   drivers/soc/meson/meson_sm.c       | 155 +++++++++++++++++++++++++++++++++++++
>   include/linux/soc/meson/meson_sm.h |  22 ++++++
>   6 files changed, 188 insertions(+)
>   create mode 100644 drivers/soc/meson/Kconfig
>   create mode 100644 drivers/soc/meson/Makefile
>   create mode 100644 drivers/soc/meson/meson_sm.c
>   create mode 100644 include/linux/soc/meson/meson_sm.h
>
> diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> index cb58ef0..7e70b52 100644
> --- a/drivers/soc/Kconfig
> +++ b/drivers/soc/Kconfig
> @@ -4,6 +4,7 @@ source "drivers/soc/bcm/Kconfig"
>   source "drivers/soc/brcmstb/Kconfig"
>   source "drivers/soc/fsl/qe/Kconfig"
>   source "drivers/soc/mediatek/Kconfig"
> +source "drivers/soc/meson/Kconfig"
>   source "drivers/soc/qcom/Kconfig"
>   source "drivers/soc/rockchip/Kconfig"
>   source "drivers/soc/samsung/Kconfig"
> diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
> index 5ade713..9024d2b 100644
> --- a/drivers/soc/Makefile
> +++ b/drivers/soc/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_ARCH_DOVE)		+= dove/
>   obj-$(CONFIG_MACH_DOVE)		+= dove/
>   obj-y				+= fsl/
>   obj-$(CONFIG_ARCH_MEDIATEK)	+= mediatek/
> +obj-$(CONFIG_ARCH_MESON)	+= meson/
>   obj-$(CONFIG_ARCH_QCOM)		+= qcom/
>   obj-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip/
>   obj-$(CONFIG_SOC_SAMSUNG)	+= samsung/
> diff --git a/drivers/soc/meson/Kconfig b/drivers/soc/meson/Kconfig
> new file mode 100644
> index 0000000..fff11a3
> --- /dev/null
> +++ b/drivers/soc/meson/Kconfig
> @@ -0,0 +1,8 @@
> +#
> +# Amlogic Secure Monitor driver
> +#
> +config MESON_SM
> +	bool
> +	default ARCH_MESON
> +	help
> +	  Say y here to enable the Amlogic secure monitor driver
> diff --git a/drivers/soc/meson/Makefile b/drivers/soc/meson/Makefile
> new file mode 100644
> index 0000000..9ab3884
> --- /dev/null
> +++ b/drivers/soc/meson/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_MESON_SM) +=	meson_sm.o
> diff --git a/drivers/soc/meson/meson_sm.c b/drivers/soc/meson/meson_sm.c
> new file mode 100644
> index 0000000..16f7e32
> --- /dev/null
> +++ b/drivers/soc/meson/meson_sm.c
> @@ -0,0 +1,155 @@
> +/*
> + * Amlogic Secure Monitor driver
> + *
> + * Copyright (C) 2016 Endless Mobile, Inc.
> + * Author: Carlo Caione <carlo at endlessm.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * 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 <stdarg.h>
> +#include <asm/cacheflush.h>
> +#include <asm/compiler.h>
> +#include <linux/arm-smccc.h>
> +#include <linux/io.h>
> +#include <linux/ioport.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/smp.h>
> +
> +#include <linux/soc/meson/meson_sm.h>
> +
> +#define SM_MEM_SIZE	0x1000
> +
> +/*
> + * To read from / write to the secure monitor we use two bounce buffers. The
> + * physical addresses of the two buffers are obtained by querying the secure
> + * monitor itself.
> + */
> +
> +static u32 sm_phy_in_base;
> +static u32 sm_phy_out_base;

You can put this two variable in meson_sm_probe, right?

> +
> +static void __iomem *sm_sharemem_in_base;
> +static void __iomem *sm_sharemem_out_base;
> +
> +struct meson_sm_data {
> +	u32 cmd;
> +	u32 arg0;
> +	u32 arg1;
> +	u32 arg2;
> +	u32 arg3;
> +	u32 arg4;
> +	u32 ret;
> +};
> +
> +static void __meson_sm_call(void *info)
> +{
> +	struct meson_sm_data *data = info;
> +	struct arm_smccc_res res;
> +
> +	arm_smccc_smc(data->cmd,
> +		      data->arg0, data->arg1, data->arg2,
> +		      data->arg3, data->arg4, 0, 0, &res);
> +	data->ret = res.a0;
> +}
> +
> +u32 meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)

Can the function be static or will it be called from another driver?

> +{
> +	struct meson_sm_data data;
> +
> +	data.cmd = cmd;
> +	data.arg0 = arg0;
> +	data.arg1 = arg1;
> +	data.arg2 = arg2;
> +	data.arg3 = arg3;
> +	data.arg4 = arg4;
> +	data.ret = 0;
> +
> +	__meson_sm_call(&data);
> +
> +	return data.ret;
> +}
> +
> +u32 meson_sm_call_read(void *buffer, u32 cmd, u32 arg0, u32 arg1,
> +		       u32 arg2, u32 arg3, u32 arg4)
> +{
> +	u32 size;
> +
> +	size = meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
> +
> +	if (!size || size > SM_MEM_SIZE)
> +		return -EINVAL;
> +
> +	memcpy(buffer, sm_sharemem_out_base, size);
> +	return size;
> +}

This function will be needed to be exported to be callable from modules.

> +
> +u32 meson_sm_call_write(void *buffer, unsigned int b_size, u32 cmd, u32 arg0,
> +			u32 arg1, u32 arg2, u32 arg3, u32 arg4)
> +{
> +	u32 size;
> +
> +	if (b_size > SM_MEM_SIZE)
> +		return -EINVAL;
> +
> +	memcpy(sm_sharemem_in_base, buffer, b_size);
> +
> +	size = meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
> +
> +	if (!size)
> +		return -EINVAL;
> +
> +	return size;
> +}
> +

Same here.

Regards,
Matthias

> +static int meson_sm_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	int cmd_in, cmd_out;
> +
> +	if (of_property_read_u32(np, "amlogic,sm_cmd_input_base", &cmd_in))
> +		return -EINVAL;
> +
> +	if (of_property_read_u32(np, "amlogic,sm_cmd_output_base", &cmd_out))
> +		return -EINVAL;
> +
> +	sm_phy_in_base = meson_sm_call(cmd_in, 0, 0, 0, 0, 0);
> +	sm_sharemem_in_base = ioremap_cache(sm_phy_in_base, SM_MEM_SIZE);
> +	if (!sm_sharemem_in_base)
> +		return -EINVAL;
> +
> +	sm_phy_out_base = meson_sm_call(cmd_out, 0, 0, 0, 0, 0);
> +	sm_sharemem_out_base = ioremap_cache(sm_phy_out_base, SM_MEM_SIZE);
> +	if (!sm_sharemem_out_base) {
> +		iounmap(sm_sharemem_in_base);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id meson_sm_ids[] = {
> +	{ .compatible = "amlogic,meson-sm" },
> +	{ /* sentinel */},
> +};
> +MODULE_DEVICE_TABLE(of, meson_sm_ids);
> +
> +static struct platform_driver meson_sm_platform_driver = {
> +	.probe	= meson_sm_probe,
> +	.driver	= {
> +		.name		= "secmon",
> +		.of_match_table	= meson_sm_ids,
> +	},
> +};
> +module_platform_driver(meson_sm_platform_driver);
> +
> +MODULE_AUTHOR("Carlo Caione <carlo at endlessm.com>");
> +MODULE_DESCRIPTION("Amlogic secure monitor driver");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/soc/meson/meson_sm.h b/include/linux/soc/meson/meson_sm.h
> new file mode 100644
> index 0000000..6ff8317
> --- /dev/null
> +++ b/include/linux/soc/meson/meson_sm.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright (C) 2016 Endless Mobile, Inc.
> + * Author: Carlo Caione <carlo at endlessm.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef _MESON_SM_H_
> +#define _MESON_SM_H_
> +
> +u32 meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
> +u32 meson_sm_call_read(void *buffer, u32 cmd, u32 arg0, u32 arg1, u32 arg2,
> +		       u32 arg3, u32 arg4);
> +u32 meson_sm_call_write(void *buffer, unsigned int b_size, u32 cmd, u32 arg0,
> +			u32 arg1, u32 arg2, u32 arg3, u32 arg4);
> +
> +#endif /* _MESON_SM_H_ */
>


From liudongdong3 at huawei.com  Mon May 23 04:25:07 2016
From: liudongdong3 at huawei.com (Dongdong Liu)
Date: Mon, 23 May 2016 19:25:07 +0800
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <5742E893.1060004@huawei.com>



? 2016/5/10 23:19, Tomasz Nowicki ??:
>>From the functionality point of view this series may be split into the
> following logic parts:
> 1. New ECAM API and update for users of the pci-host-common API
> 2. Necessary fixes as the preparation for using driver on ARM64.
> 3. Use new MCFG interface and implement generic ACPI based PCI host controller driver.
> 4. Enable above driver on ARM64
>
> Patches has been built on top of 4.6-rc7 and can be found here:
> git at github.com:semihalf-nowicki-tomasz/linux.git (pci-acpi-v7)
>
> This has been tested on Cavium ThunderX server. Any help in reviewing and
> testing is very appreciated.
>

Based on the patchset (with ECAM fix-up quirk added) and added the patch(Add ACPI support for HiSilicon PCIe Host Controllers).
Tested on the HiSilicon ARM64 D02 board.
It can work ok with Intel 82599 networking card.
This is the bootup log which contains PCIe host and Intel 82599 networking card part.

Tested-by: Dongdong Liu <liudongdong3 at huawei.com>

EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration table
EFI stub: Exiting boot services and installing virtual address map...
GMAC ExitBootServicesEvent
SMMU ExitBootServicesEvent
[    0.000000] Booting Linux on physical CPU 0x20000
[    0.000000] Linux version 4.6.0-rc1+ (l00290354 at linux-ioko) (gcc version 4.9.3 20150211 (prerelease) (20150316) ) #43 SMP PREEMPT Thu May 19 17:15:30 CST 2016
[    0.000000] Boot CPU: AArch64 Processor [411fd071]
[    0.000000] earlycon: uart8250 at MMIO32 0x0000000080300000 (options '')
[    0.000000] bootconsole [uart8250] enabled
[    0.000000] efi: Getting EFI parameters from FDT:
[    0.000000] EFI v2.50 by EDK II
[    0.000000] efi:  SMBIOS=0x7a650000  SMBIOS 3.0=0x7a630000  ACPI=0x7aba0000  ACPI 2.0=0x7aba0014
[    0.000000] cma: Reserved 16 MiB at 0x000000007e800000
[    0.000000] ACPI: Early table checksum verification disabled
[    0.000000] ACPI: RSDP 0x000000007ABA0014 000024 (v02 HISI  )
[    0.000000] ACPI: XSDT 0x000000007A7000E8 000064 (v01 HISI   HISI-D02 20140727      01000013)
[    0.000000] ACPI: FACP 0x000000007A5F0000 00010C (v05 HISI   HISI-D02 20140727 HISI 00000099)
[    0.000000] ACPI: DSDT 0x000000007A5A0000 001656 (v01 HISI   HISI-D02 20140727 INTL 20150619)
[    0.000000] ACPI: DBG2 0x000000007A610000 00005A (v00 HISI   HISI-D02 20140727 HISI 00000099)
[    0.000000] ACPI: GTDT 0x000000007A5E0000 000060 (v02 HISI   HISI-D02 20140727 HISI 00000099)
[    0.000000] ACPI: APIC 0x000000007A5D0000 000554 (v01 HISI   HISI-D02 20140727 HISI 00000099)
[    0.000000] ACPI: MCFG 0x000000007A5C0000 00004C (v01 HISI   HISI-D02 20140727 HISI 00000099)
[    0.000000] ACPI: SPCR 0x000000007A5B0000 000050 (v02 HISI   HISI-D02 20140727 HISI 00000099)
[    0.000000] ACPI: IORT 0x000000007A590000 0001FC (v00 INTEL  TEMPLATE 00000000 INTL 20150619)
[    0.000000] ACPI: SSDT 0x000000007A580000 00046E (v01 HISI   SAS0     20140727 INTL 20150619)
[    0.000000] ACPI: SPCR: console: uart,mmio,0x80300000,115200
[    0.000000] psci: probing for conduit method from ACPI.
NOTICE:  [psci_smc_handler]:[347L] PSCI_VERSION CALL
NOTICE:  [psci_version]:[99L] PSCI_MAJOR_VER: 10000: PSCI_MINOR_VER: 0

0808?844
[    0.000000] psci: PSCIv1.0 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs

0808?844
[    0.000000] psci: MIGRATE_INFO_TYPE not supported.

0808?844

0808?844
[    0.000000] percpu: Embedded 20 pages/cpu @ffffffd1ffe7e000 s43008 r8192 d30720 u81920
[    0.000000] Detected PIPT I-cache on CPU0
[    0.000000] CPU features: enabling workaround for ARM erratum 832075
[    0.000000] CPU features: enabling workaround for ARM erratum 834220
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 2063376
[    0.000000] Kernel command line: console=ttyS0,115200 earlycon=uart8250,mmio32,0x80300000 initrd=filesystem.cpio.gz acpi=force pcie_aspm=off
[    0.000000] PCIe ASPM is disabled
[    0.000000] log_buf_len individual max cpu contribution: 4096 bytes
[    0.000000] log_buf_len total cpu_extra contributions: 61440 bytes
[    0.000000] log_buf_len min size: 16384 bytes
[    0.000000] log_buf_len: 131072 bytes
[    0.000000] early log buf free: 12988(79%)
[    0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes)
[    0.000000] Dentry cache hash table entries: 1048576 (order: 11, 8388608 bytes)
[    0.000000] Inode-cache hash table entries: 524288 (order: 10, 4194304 bytes)
[    0.000000] software IO TLB [mem 0x764e0000-0x7a4e0000] (64MB) mapped at [ffffffc0764e0000-ffffffc07a4dffff]
[    0.000000] Memory: 8110296K/8384512K available (7240K kernel code, 632K rwdata, 3028K rodata, 840K init, 247K bss, 257832K reserved, 16384K cma-reserved)
[    0.000000] Virtual kernel memory layout:
[    0.000000]     modules : 0xffffff8000000000 - 0xffffff8008000000   (   128 MB)
[    0.000000]     vmalloc : 0xffffff8008000000 - 0xffffffbdbfff0000   (   246 GB)
[    0.000000]       .text : 0xffffff8008080000 - 0xffffff8008790000   (  7232 KB)
[    0.000000]     .rodata : 0xffffff8008790000 - 0xffffff8008a89000   (  3044 KB)
[    0.000000]       .init : 0xffffff8008a89000 - 0xffffff8008b5b000   (   840 KB)
[    0.000000]       .data : 0xffffff8008b5b000 - 0xffffff8008bf9200   (   633 KB)
[    0.000000]     vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000   (     8 GB maximum)
[    0.000000]               0xffffffbdc0000000 - 0xffffffbe08000000   (  1152 MB actual)
[    0.000000]     fixed   : 0xffffffbffe7fd000 - 0xffffffbffec00000   (  4108 KB)
[    0.000000]     PCI I/O : 0xffffffbffee00000 - 0xffffffbfffe00000   (    16 MB)
[    0.000000]     memory  : 0xffffffc000000000 - 0xffffffd200000000   ( 73728 MB)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=16, Nodes=1
[    0.000000] Preemptible hierarchical RCU implementation.
[    0.000000] 	Build-time adjustment of leaf fanout to 64.
[    0.000000] 	RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=16.
[    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=64, nr_cpu_ids=16
[    0.000000] NR_IRQS:64 nr_irqs:64 0
[    0.000000] GIC: Using split EOI/Deactivate mode
[    0.000000] ITS at 0x8c000000
[    0.000000] ITS: allocated 65536 Devices @11f6c80000 (psz 4K, shr 1)
[    0.000000] ITS: allocated 512 Virtual CPUs @11f6c0f000 (psz 4K, shr 1)
[    0.000000] ITS: allocated 512 Interrupt Collections @11f6c20000 (psz 4K, shr 1)
[    0.000000] ITS at 0xc6000000
[    0.000000] ITS: allocated 65536 Devices @11f6d00000 (psz 4K, shr 1)
[    0.000000] ITS: allocated 512 Virtual CPUs @11f6c21000 (psz 4K, shr 1)
[    0.000000] ITS: allocated 512 Interrupt Collections @11f6c22000 (psz 4K, shr 1)
[    0.000000] ITS at 0xa3000000
[    0.000000] ITS: allocated 65536 Devices @11f6d80000 (psz 4K, shr 1)
[    0.000000] ITS: allocated 512 Virtual CPUs @11f6c24000 (psz 4K, shr 1)
[    0.000000] ITS: allocated 512 Interrupt Collections @11f6c25000 (psz 4K, shr 1)
[    0.000000] ITS at 0xb7000000
[    0.000000] ITS: allocated 65536 Devices @11f6e00000 (psz 4K, shr 1)
[    0.000000] ITS: allocated 512 Virtual CPUs @11f6c26000 (psz 4K, shr 1)
[    0.000000] ITS: allocated 512 Interrupt Collections @11f6c27000 (psz 4K, shr 1)
[    0.000000] GIC: using LPI property table @0x00000011f6c60000
[    0.000000] ITS: Allocated 1792 chunks for LPIs
[    0.000000] CPU0: found redistributor 20000 region 0:0x000000008d100000
[    0.000000] CPU0: using LPI pending table @0x00000011f6c70000
[    0.000000] Unable to get hardware information used for virtualization
[    0.000000] GTDT: No Platform Timer structures.
[    0.000000] arch_timer: Can't find GT Block.
[    0.000000] Architected cp15 and mmio timer(s) running at 50.00MHz (phys/phys).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0xb8812736b, max_idle_ns: 440795202655 ns
[    0.000001] sched_clock: 56 bits at 50MHz, resolution 20ns, wraps every 4398046511100ns
[    0.008025] Console: colour dummy device 80x25
[    0.012459] Calibrating delay loop (skipped), value calculated using timer frequency.. 100.00 BogoMIPS (lpj=200000)
[    0.022850] pid_max: default: 32768 minimum: 301
[    0.027450] ACPI: Core revision 20160108
[    0.032284] ACPI: 2 ACPI AML tables successfully acquired and loaded
[    0.038617]
[    0.040126] Security Framework initialized
[    0.044213] Mount-cache hash table entries: 16384 (order: 5, 131072 bytes)
[    0.051053] Mountpoint-cache hash table entries: 16384 (order: 5, 131072 bytes)
[    0.058747] ASID allocator initialised with 65536 entries
[    0.064393] PCI/MSI: ITS at 0x8c000000 domain created
[    0.069162] PCI/MSI: ITS at 0xc6000000 domain created
[    0.073927] PCI/MSI: ITS at 0xa3000000 domain created
[    0.078693] PCI/MSI: ITS at 0xb7000000 domain created
[    0.083463] Platform MSI: irqchip at 000000008c000000 domain created
[    0.089525] Platform MSI: irqchip at 00000000c6000000 domain created
[    0.095586] Platform MSI: irqchip at 00000000a3000000 domain created
[    0.101648] Platform MSI: irqchip at 00000000b7000000 domain created
[    0.107753] Remapping and enabling EFI services.
[    0.112370]   EFI remap 0x000000007a4e0000 => 0000000020000000
[    0.118185]   EFI remap 0x000000007a530000 => 0000000020050000
[    0.124008]   EFI remap 0x000000007a620000 => 00000000200a0000
[    0.129822]   EFI remap 0x000000007a6b0000 => 0000000020130000
[    0.135636]   EFI remap 0x000000007a710000 => 0000000020180000
[    0.141454]   EFI remap 0x000000007a760000 => 00000000201d0000
[    0.147269]   EFI remap 0x000000007a7b0000 => 0000000020220000
[    0.153083]   EFI remap 0x000000007a800000 => 0000000020270000
[    0.158897]   EFI remap 0x000000007a850000 => 00000000202c0000
[    0.164711]   EFI remap 0x000000007a8a0000 => 0000000020310000
[    0.170525]   EFI remap 0x000000007a8f0000 => 0000000020360000
[    0.176339]   EFI remap 0x000000007a940000 => 00000000203b0000
[    0.182160]   EFI remap 0x000000007a990000 => 0000000020400000
[    0.187974]   EFI remap 0x000000007aa00000 => 0000000020470000
[    0.193788]   EFI remap 0x000000007aa50000 => 00000000204c0000
[    0.199602]   EFI remap 0x000000007aaa0000 => 0000000020510000
[    0.205417]   EFI remap 0x000000007aaf0000 => 0000000020560000
[    0.211230]   EFI remap 0x000000007ab40000 => 00000000205b0000
[    0.217043]   EFI remap 0x000000007fbb0000 => 0000000020600000
[    0.222849]   EFI remap 0x0000000080300000 => 0000000020630000
[    0.228654]   EFI remap 0x00000000a00f0000 => 0000000020640000
[    0.234457]   EFI remap 0x00000000a4000000 => 0000000020800000
[    0.240266]   EFI remap 0x00000000a6000000 => 0000000021800000
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20001 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0x1

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0x1


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c080
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3d190
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20002 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0x1

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0x1


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c100
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3d3a0
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20003 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0x1

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0x1


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c180
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3d5b0
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20100 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0x1

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0x3


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c200
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3d7c0
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20101 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0x3

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0x3


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c280
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3d9d0
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20102 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0x3

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0x3


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c300
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3dbe0
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20103 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0x3

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0x3


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c380
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3ddf0
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20200 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0x3

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0x7


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c400
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3e000
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20201 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0x7

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0x7


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c480
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3e210
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20202 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0x7

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0x7


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c500
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3e420
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20203 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0x7

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0x7


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c580
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3e630
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20300 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0x7

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0xf


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c600
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3e840
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20301 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0xf

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0xf


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c680
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3ea50
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20302 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0xf

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0xf


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c700
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3ec60
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
NOTICE:  [psci_smc_handler]:[408L] PSCI_CPU_ON_AARCH64 CALL
NOTICE:  [psci_smc_handler]:[409L] x1=0x20303 x2=0x82870 x3=0x0
NOTICE:  [scpi_set_css_power_state]:[85L] domain_cluster=0xf

NOTICE:  [scpi_set_css_power_state]:[93L] domain_cluster=0xf


0808?8AB44
NOTICE:  [psci_afflvl_power_on_finish]:[504L]
NOTICE:  [cm_prepare_el3_exit]:[262L] read_tpidr_el3 = 7fc3c780
NOTICE:  [cm_prepare_el3_exit]:[319L] ctx add = 7fc3ee70
NOTICE:  [psci_afflvl_power_on_finish]:[562L]

00082870
[    0.288031] Detected PIPT I-cache on CPU1
[    0.288043] CPU1: found redistributor 20001 region 1:0x000000008d130000
[    0.288064] CPU1: using LPI pending table @0x00000011f6410000
[    0.288122] CPU1: Booted secondary processor [411fd071]
[    0.331143] Detected PIPT I-cache on CPU2
[    0.331150] CPU2: found redistributor 20002 region 2:0x000000008d160000
[    0.331170] CPU2: using LPI pending table @0x00000011f6440000
[    0.331218] CPU2: Booted secondary processor [411fd071]
[    0.374257] Detected PIPT I-cache on CPU3
[    0.374263] CPU3: found redistributor 20003 region 3:0x000000008d190000
[    0.374283] CPU3: using LPI pending table @0x00000011f6480000
[    0.374328] CPU3: Booted secondary processor [411fd071]
[    0.417372] Detected PIPT I-cache on CPU4
[    0.417380] CPU4: found redistributor 20100 region 4:0x000000008d1c0000
[    0.417400] CPU4: using LPI pending table @0x00000011f64c0000
[    0.417447] CPU4: Booted secondary processor [411fd071]
[    0.460484] Detected PIPT I-cache on CPU5
[    0.460491] CPU5: found redistributor 20101 region 5:0x000000008d1f0000
[    0.460511] CPU5: using LPI pending table @0x00000011f64f0000
[    0.460558] CPU5: Booted secondary processor [411fd071]
[    0.503598] Detected PIPT I-cache on CPU6
[    0.503605] CPU6: found redistributor 20102 region 6:0x000000008d220000
[    0.503625] CPU6: using LPI pending table @0x00000011f6530000
[    0.503669] CPU6: Booted secondary processor [411fd071]
[    0.546711] Detected PIPT I-cache on CPU7
[    0.546718] CPU7: found redistributor 20103 region 7:0x000000008d250000
[    0.546738] CPU7: using LPI pending table @0x00000011f6560000
[    0.546783] CPU7: Booted secondary processor [411fd071]
[    0.589826] Detected PIPT I-cache on CPU8
[    0.589835] CPU8: found redistributor 20200 region 8:0x000000008d280000
[    0.589857] CPU8: using LPI pending table @0x00000011f65a0000
[    0.589910] CPU8: Booted secondary processor [411fd071]
[    0.632939] Detected PIPT I-cache on CPU9
[    0.632946] CPU9: found redistributor 20201 region 9:0x000000008d2b0000
[    0.632967] CPU9: using LPI pending table @0x00000011f65e0000
[    0.633014] CPU9: Booted secondary processor [411fd071]
[    0.676052] Detected PIPT I-cache on CPU10
[    0.676060] CPU10: found redistributor 20202 region 10:0x000000008d2e0000
[    0.676081] CPU10: using LPI pending table @0x00000011f6610000
[    0.676126] CPU10: Booted secondary processor [411fd071]
[    0.719166] Detected PIPT I-cache on CPU11
[    0.719173] CPU11: found redistributor 20203 region 11:0x000000008d310000
[    0.719195] CPU11: using LPI pending table @0x00000011f6650000
[    0.719240] CPU11: Booted secondary processor [411fd071]
[    0.762280] Detected PIPT I-cache on CPU12
[    0.762289] CPU12: found redistributor 20300 region 12:0x000000008d340000
[    0.762311] CPU12: using LPI pending table @0x00000011f6680000
[    0.762360] CPU12: Booted secondary processor [411fd071]
[    0.805392] Detected PIPT I-cache on CPU13
[    0.805400] CPU13: found redistributor 20301 region 13:0x000000008d370000
[    0.805421] CPU13: using LPI pending table @0x00000011f66c0000
[    0.805466] CPU13: Booted secondary processor [411fd071]
[    0.848506] Detected PIPT I-cache on CPU14
[    0.848513] CPU14: found redistributor 20302 region 14:0x000000008d3a0000
[    0.848534] CPU14: using LPI pending table @0x00000011f6700000
[    0.848579] CPU14: Booted secondary processor [411fd071]
[    0.891620] Detected PIPT I-cache on CPU15
[    0.891628] CPU15: found redistributor 20303 region 15:0x000000008d3d0000
[    0.891648] CPU15: using LPI pending table @0x00000011f6750000
[    0.891693] CPU15: Booted secondary processor [411fd071]
[    0.891723] Brought up 16 CPUs
[    1.220754] SMP: Total of 16 processors activated.
[    1.225520] CPU features: detected feature: GIC system register CPU interface
[    1.232620] CPU: All CPU(s) started at EL2
[    1.236718] alternatives: patching kernel code
[    1.243905] devtmpfs: initialized
[    1.247446] SMBIOS 3.0.0 present.
[    1.250851] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    1.260790] pinctrl core: initialized pinctrl subsystem
[    1.266365] NET: Registered protocol family 16
[    1.282800] cpuidle: using governor menu
[    1.286747] vdso: 2 pages (1 code @ ffffff8008796000, 1 data @ ffffff8008b60000)
[    1.294122] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[    1.301211] DMA: preallocated 256 KiB pool for atomic allocations
[    1.307340] ACPI: bus type PCI registered
[    1.311388] Serial: AMBA PL011 UART driver
[    1.331638] HugeTLB registered 2 MB page size, pre-allocated 0 pages
[    1.338373] ACPI: Added _OSI(Module Device)
[    1.342562] ACPI: Added _OSI(Processor Device)
[    1.346984] ACPI: Added _OSI(3.0 _SCP Extensions)
[    1.351664] ACPI: Added _OSI(Processor Aggregator Device)
[    1.358469] ACPI: Interpreter enabled
[    1.362116] ACPI: Using GIC for interrupt routing
[    1.366815] ACPI: MCFG table loaded, 2 entries detected
[    1.375180] Hisilicon MBIGEN-V1 HISI0151:00: Allocated 256 MSIs
[    1.381158] Hisilicon MBIGEN-V1 HISI0151:01: Allocated 640 MSIs
[    1.387123] Hisilicon MBIGEN-V1 HISI0151:02: Allocated 256 MSIs
[    1.393091] Hisilicon MBIGEN-V1 HISI0151:03: Allocated 640 MSIs
[    1.399213] ACPI: IORT: can't find node related to (null) device
[    1.405292] ACPI: IORT: can't find node related to (null) device
[    1.411324] ACPI: IORT: can't find node related to (null) device
[    1.417348] ACPI: IORT: can't find node related to (null) device
[    1.423370] ACPI: IORT: can't find node related to (null) device
[    1.429391] ACPI: IORT: can't find node related to (null) device
[    1.436634] ACPI: IORT: can't find node related to (null) device
[    1.442681] ACPI: IORT: can't find node related to (null) device
[    1.448698] ACPI: IORT: can't find node related to (null) device
[    1.454712] ACPI: IORT: can't find node related to (null) device
[    1.460724] ACPI: IORT: can't find node related to (null) device
[    1.466764] ACPI: PCI Root Bridge [PCI1] (domain 0001 [bus 40-7f])
[    1.472918] acpi HISI0080:00: _OSC: OS supports [ExtendedConfig Segments MSI]
[    1.480025] acpi HISI0080:00: _OSC failed (AE_NOT_FOUND); disabling ASPM
[    1.486771] acpi HISI0080:00: ECAM at [mem 0x22004000000-0x22007ffffff] for [bus 40-7f]
[    1.494762] Remapped I/O 0x000002200fff0000 to [io  0x0000-0xffff window]
[    1.501592] PCI host bridge to bus 0001:40
[    1.505671] pci_bus 0001:40: root bus resource [mem 0x22008000000-0x2200ffeffff window] (bus address [0xb0000000-0xb7feffff])
[    1.516919] pci_bus 0001:40: root bus resource [io  0x0000-0xffff window]
[    1.523675] pci_bus 0001:40: root bus resource [bus 40-7f]
[    1.534090] pci 0001:41:00.0: VF(n) BAR0 space: [mem 0x22008e08000-0x22008f07fff 64bit pref] (contains BAR0 for 64 VFs)
[    1.545323] pci 0001:41:00.0: VF(n) BAR3 space: [mem 0x22008f08000-0x22009007fff 64bit pref] (contains BAR3 for 64 VFs)
[    1.568223] pci 0001:41:00.1: VF(n) BAR0 space: [mem 0x22008c04000-0x22008d03fff 64bit pref] (contains BAR0 for 64 VFs)
[    1.579460] pci 0001:41:00.1: VF(n) BAR3 space: [mem 0x22008d04000-0x22008e03fff 64bit pref] (contains BAR3 for 64 VFs)
[    1.597823] pci 0001:40:00.0: BAR 15: assigned [mem 0x22008000000-0x220095fffff pref]
[    1.605616] pci 0001:40:00.0: BAR 13: assigned [io  0x1000-0x1fff]
[    1.611771] pci 0001:41:00.0: BAR 0: assigned [mem 0x22008000000-0x220083fffff 64bit pref]
[    1.620245] pci 0001:41:00.0: BAR 6: assigned [mem 0x22008400000-0x220087fffff pref]
[    1.627952] pci 0001:41:00.1: BAR 0: assigned [mem 0x22008800000-0x22008bfffff 64bit pref]
[    1.636430] pci 0001:41:00.1: BAR 6: assigned [mem 0x22008c00000-0x22008ffffff pref]
[    1.644138] pci 0001:41:00.0: BAR 4: assigned [mem 0x22009000000-0x22009003fff 64bit pref]
[    1.652610] pci 0001:41:00.0: BAR 7: assigned [mem 0x22009004000-0x22009103fff 64bit pref]
[    1.661083] pci 0001:41:00.0: BAR 10: assigned [mem 0x22009104000-0x22009203fff 64bit pref]
[    1.669640] pci 0001:41:00.1: BAR 4: assigned [mem 0x22009204000-0x22009207fff 64bit pref]
[    1.678115] pci 0001:41:00.1: BAR 7: assigned [mem 0x22009208000-0x22009307fff 64bit pref]
[    1.686591] pci 0001:41:00.1: BAR 10: assigned [mem 0x22009308000-0x22009407fff 64bit pref]
[    1.695148] pci 0001:41:00.0: BAR 2: assigned [io  0x1000-0x101f]
[    1.701285] pci 0001:41:00.1: BAR 2: assigned [io  0x1020-0x103f]
[    1.707421] pci 0001:40:00.0: PCI bridge to [bus 41-42]
[    1.712621] pci 0001:40:00.0:   bridge window [io  0x1000-0x1fff]
[    1.718685] pci 0001:40:00.0:   bridge window [mem 0x22008000000-0x220095fffff pref]
[    1.726434] ACPI: PCI Root Bridge [PCI2] (domain 0002 [bus 80-bf])
[    1.732594] acpi HISI0080:01: _OSC: OS supports [ExtendedConfig Segments MSI]
[    1.739696] acpi HISI0080:01: _OSC failed (AE_NOT_FOUND); disabling ASPM
[    1.746425] acpi HISI0080:01: link status is down
[    1.751106] acpi HISI0080:01: ECAM at [mem 0x24008000000-0x2400bffffff] for [bus 80-bf]
[    1.759090] Remapped I/O 0x000002400fff0000 to [io  0x10000-0x1ffff window]
[    1.766086] PCI host bridge to bus 0002:80
[    1.770172] pci_bus 0002:80: root bus resource [mem 0x2400c000000-0x2400ffeffff window] (bus address [0xc0000000-0xc3feffff])
[    1.781422] pci_bus 0002:80: root bus resource [io  0x10000-0x1ffff window] (bus address [0x0000-0xffff])
[    1.790940] pci_bus 0002:80: root bus resource [bus 80-bf]
[    1.796414] pci 0002:80:00.0: ignoring class 0x000000 (doesn't match header type 01)
[    1.804311] pci 0002:80:00.0: not setting up bridge for bus 0002:81
[    1.810956] ACPI: IORT: can't find node related to (null) device
[    1.817228] ACPI: IORT: can't find node related to (null) device
[    1.823453] vgaarb: loaded
[    1.826246] SCSI subsystem initialized
[    1.830103] ACPI: bus type USB registered
[    1.834130] usbcore: registered new interface driver usbfs
[    1.839606] usbcore: registered new interface driver hub
[    1.844933] usbcore: registered new device driver usb
[    1.850014] pps_core: LinuxPPS API ver. 1 registered
[    1.854953] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti at linux.it>
[    1.864048] PTP clock support registered
[    1.868069] Advanced Linux Sound Architecture Driver Initialized.
[    1.874376] clocksource: Switched to clocksource arch_sys_counter
[    1.880489] VFS: Disk quotas dquot_6.6.0
[    1.884414] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[    1.891385] pnp: PnP ACPI init
[    1.894570] system 00:00: [mem 0xb0080000-0xb008ffff] has been reserved
[    1.901209] system 00:01: [mem 0xb0090000-0xb009ffff] has been reserved
[    1.907813] pnp: PnP ACPI: found 2 devices
[    1.914467] NET: Registered protocol family 2
[    1.919030] TCP established hash table entries: 65536 (order: 7, 524288 bytes)
[    1.926352] TCP bind hash table entries: 65536 (order: 8, 1048576 bytes)
[    1.933333] TCP: Hash tables configured (established 65536 bind 65536)
[    1.939876] UDP hash table entries: 4096 (order: 5, 131072 bytes)
[    1.945968] UDP-Lite hash table entries: 4096 (order: 5, 131072 bytes)
[    1.952576] NET: Registered protocol family 1
[    1.957013] RPC: Registered named UNIX socket transport module.
[    1.962905] RPC: Registered udp transport module.
[    1.967586] RPC: Registered tcp transport module.
[    1.972266] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    1.978872] Unpacking initramfs...
[    2.340835] Freeing initrd memory: 27492K (ffffffc01e520000 - ffffffc01fff9000)
[    2.348645] kvm [1]: 8-bit VMID
[    2.351776] kvm [1]: Hyp mode initialized successfully
[    2.356892] kvm [1]: error: KVM vGIC probing failed
[    2.361790] kvm [1]: virtual timer IRQ3
[    2.366650] ACPI: IORT: can't find node related to (null) device
[    2.373057] futex hash table entries: 4096 (order: 7, 524288 bytes)
[    2.379403] audit: initializing netlink subsys (disabled)
[    2.384813] audit: type=2000 audit(1.864:1): initialized
[    2.390302] workingset: timestamp_bits=44 max_order=21 bucket_order=0
[    2.400222] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    2.406342] NFS: Registering the id_resolver key type
[    2.411393] Key type id_resolver registered
[    2.415557] Key type id_legacy registered
[    2.419609] fuse init (API version 7.24)
[    2.423687] 9p: Installing v9fs 9p2000 file system support
[    2.429982] io scheduler noop registered
[    2.433946] io scheduler cfq registered (default)
[    2.439027] pcieport 0001:40:00.0: can't derive routing for PCI INT A
[    2.445438] pcieport 0001:40:00.0: PCI INT A: no GSI
[    2.451126] xenfs: not registering filesystem on non-xen platform
[    2.458262] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    2.465049] console [ttyS0] disabled
[    2.468627] APMC0D08:00: ttyS0 at MMIO 0x80300000 (irq = 5, base_baud = 12500000) is a 16550A
[    2.477133] console [ttyS0] enabled
[    2.477133] console [ttyS0] enabled
[    2.484137] bootconsole [uart8250] disabled
[    2.484137] bootconsole [uart8250] disabled
[    2.492728] SuperH (H)SCI(F) driver initialized
[    2.497322] msm_serial: driver initialized
[    2.501649] Failed to find cpu0 device node
[    2.505852] Unable to detect cache hierarchy from DT for CPU 0
[    2.514093] loop: module loaded
[    2.517694] tun: Universal TUN/TAP device driver, 1.6
[    2.522771] tun: (C) 1999-2004 Max Krasnyansky <maxk at qualcomm.com>
[    2.529079] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[    2.534939] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    2.540908] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.3.0-k
[    2.547900] igb: Copyright (c) 2007-2014 Intel Corporation.
[    2.553518] igbvf: Intel(R) Gigabit Virtual Function Network Driver - version 2.0.2-k
[    2.561382] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
[    2.567350] ixgbe: Intel(R) 10 Gigabit PCI Express Network Driver - version 4.2.1-k
[    2.575039] ixgbe: Copyright (c) 1999-2015 Intel Corporation.
[    2.580854] pcieport 0001:40:00.0: can't derive routing for PCI INT A
[    2.587326] ixgbe 0001:41:00.0: PCI INT A: no GSI
[    2.592178] ixgbe 0001:41:00.0: enabling device (0000 -> 0002)
[    2.753716] ixgbe 0001:41:00.0: Multiqueue Enabled: Rx Queue count = 16, Tx Queue count = 16
[    2.762393] ixgbe 0001:41:00.0: PCI Express bandwidth of 32GT/s available
[    2.769213] ixgbe 0001:41:00.0: (Speed:5.0GT/s, Width: x8, Encoding Loss:20%)
[    2.776457] ixgbe 0001:41:00.0: MAC: 2, PHY: 17, SFP+: 5, PBA No: FFFFFF-0FF
[    2.783537] ixgbe 0001:41:00.0: 68:a8:28:2e:c9:10
[    2.792732] ixgbe 0001:41:00.0: Intel(R) 10 Gigabit Network Connection
[    2.799312] pcieport 0001:40:00.0: can't derive routing for PCI INT B
[    2.805783] ixgbe 0001:41:00.1: PCI INT B: no GSI
[    2.810598] ixgbe 0001:41:00.1: enabling device (0000 -> 0002)
[    3.949697] ixgbe 0001:41:00.1: Multiqueue Enabled: Rx Queue count = 16, Tx Queue count = 16
[    3.958365] ixgbe 0001:41:00.1: PCI Express bandwidth of 32GT/s available
[    3.965185] ixgbe 0001:41:00.1: (Speed:5.0GT/s, Width: x8, Encoding Loss:20%)
[    3.972427] ixgbe 0001:41:00.1: MAC: 2, PHY: 1, PBA No: FFFFFF-0FF
[    3.978634] ixgbe 0001:41:00.1: 68:a8:28:2e:c9:11
[    3.987790] ixgbe 0001:41:00.1: Intel(R) 10 Gigabit Network Connection
[    3.994388] sky2: driver version 1.30
[    3.998201] VFIO - User Level meta-driver version: 0.3
[    4.003889] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    4.010459] ehci-pci: EHCI PCI platform driver
[    4.014944] ehci-platform: EHCI generic platform driver
[    4.020226] ehci-platform PNP0D20:00: EHCI Host Controller
[    4.025745] ehci-platform PNP0D20:00: new USB bus registered, assigned bus number 1
[    4.033572] ehci-platform PNP0D20:00: irq 6, io mem 0xa1000000
[    4.050387] ehci-platform PNP0D20:00: USB 2.0 started, EHCI 1.00
[    4.056652] hub 1-0:1.0: USB hub found
[    4.060428] hub 1-0:1.0: 1 port detected
[    4.064517] ehci-msm: Qualcomm On-Chip EHCI Host Controller
[    4.070137] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    4.076351] ohci-pci: OHCI PCI platform driver
[    4.080834] ohci-platform: OHCI generic platform driver
[    4.086166] usbcore: registered new interface driver usb-storage
[    4.092427] mousedev: PS/2 mouse device common for all mice
[    4.161533] rtc-efi rtc-efi: rtc core: registered rtc-efi as rtc0
[    4.168513] i2c /dev entries driver
[    4.172251] sdhci: Secure Digital Host Controller Interface driver
[    4.178458] sdhci: Copyright(c) Pierre Ossman
[    4.182850] Synopsys Designware Multimedia Card Interface Driver
[    4.188933] sdhci-pltfm: SDHCI platform and OF driver helper
[    4.194701] ledtrig-cpu: registered to indicate activity on CPUs
[    4.200950] usbcore: registered new interface driver usbhid
[    4.206549] usbhid: USB HID core driver
[    4.210569] ACPI: IORT: can't find node related to (null) device
[    4.216837] NET: Registered protocol family 17
[    4.221334] 9pnet: Installing 9P2000 support
[    4.225652] Key type dns_resolver registered
[    4.230166] registered taskstats version 1
[    4.297850] rtc-efi rtc-efi: hctosys: unable to read the hardware clock
[    4.304576] ALSA device list:
[    4.307561]   No soundcards found.
[    4.311063] ttyS0 - failed to request DMA
[    4.315348] Freeing unused kernel memory: 840K (ffffff8008a89000 - ffffff8008b5b000)
root@(none)$ ifconfig eth0 192.168.20.188
[   15.679957] ixgbe 0001:41:00.0: registered PHC device on eth0
root@(none)$ [   15.851142] ixgbe 0001:41:00.0 eth0: detected SFP+: 5
[   15.990419] ixgbe 0001:41:00.0 eth0: NIC Link is Up 10 Gbps, Flow Control: RX/TX

root@(none)$ ping 192.168.20.188
PING 192.168.20.4 (192.168.20.4): 56 data bytes
64 bytes from 192.168.20.4: seq=14 ttl=128 time=1.465 ms
64 bytes from 192.168.20.4: seq=15 ttl=128 time=0.616 ms
64 bytes from 192.168.20.4: seq=16 ttl=128 time=0.391 ms
64 bytes from 192.168.20.4: seq=17 ttl=128 time=0.698 ms
64 bytes from 192.168.20.4: seq=18 ttl=128 time=0.676 ms
64 bytes from 192.168.20.4: seq=19 ttl=128 time=0.524 ms
64 bytes from 192.168.20.4: seq=20 ttl=128 time=0.301 ms
64 bytes from 192.168.20.4: seq=21 ttl=128 time=0.248 ms
64 bytes from 192.168.20.4: seq=22 ttl=128 time=0.403 ms



From carlo at caione.org  Mon May 23 04:43:58 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 23 May 2016 13:43:58 +0200
Subject: [PATCH v2 1/4] soc: Amlogic: Add secure monitor driver
In-Reply-To: <5742EBC4.3050704@gmail.com>
References: <1463583382-15614-1-git-send-email-carlo@caione.org>
 <1463583382-15614-2-git-send-email-carlo@caione.org>
 <5742EBC4.3050704@gmail.com>
Message-ID: <20160523114358.GC17269@mephisto>

On 23/05/16 13:38, Matthias Brugger wrote:
> 

[...]
> >+#include <stdarg.h>
> >+#include <asm/cacheflush.h>
> >+#include <asm/compiler.h>
> >+#include <linux/arm-smccc.h>
> >+#include <linux/io.h>
> >+#include <linux/ioport.h>
> >+#include <linux/module.h>
> >+#include <linux/platform_device.h>
> >+#include <linux/of.h>
> >+#include <linux/smp.h>
> >+
> >+#include <linux/soc/meson/meson_sm.h>
> >+
> >+#define SM_MEM_SIZE	0x1000
> >+
> >+/*
> >+ * To read from / write to the secure monitor we use two bounce buffers. The
> >+ * physical addresses of the two buffers are obtained by querying the secure
> >+ * monitor itself.
> >+ */
> >+
> >+static u32 sm_phy_in_base;
> >+static u32 sm_phy_out_base;
> 
> You can put this two variable in meson_sm_probe, right?

Yeah, actually no need to be there.

> >+
> >+static void __iomem *sm_sharemem_in_base;
> >+static void __iomem *sm_sharemem_out_base;
> >+
> >+struct meson_sm_data {
> >+	u32 cmd;
> >+	u32 arg0;
> >+	u32 arg1;
> >+	u32 arg2;
> >+	u32 arg3;
> >+	u32 arg4;
> >+	u32 ret;
> >+};
> >+
> >+static void __meson_sm_call(void *info)
> >+{
> >+	struct meson_sm_data *data = info;
> >+	struct arm_smccc_res res;
> >+
> >+	arm_smccc_smc(data->cmd,
> >+		      data->arg0, data->arg1, data->arg2,
> >+		      data->arg3, data->arg4, 0, 0, &res);
> >+	data->ret = res.a0;
> >+}
> >+
> >+u32 meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
> 
> Can the function be static or will it be called from another driver?

It _can_ be called from another driver. It depends on the SMC used, so
better making it available.

> 
> >+{
> >+	struct meson_sm_data data;
> >+
> >+	data.cmd = cmd;
> >+	data.arg0 = arg0;
> >+	data.arg1 = arg1;
> >+	data.arg2 = arg2;
> >+	data.arg3 = arg3;
> >+	data.arg4 = arg4;
> >+	data.ret = 0;
> >+
> >+	__meson_sm_call(&data);
> >+
> >+	return data.ret;
> >+}
> >+
> >+u32 meson_sm_call_read(void *buffer, u32 cmd, u32 arg0, u32 arg1,
> >+		       u32 arg2, u32 arg3, u32 arg4)
> >+{
> >+	u32 size;
> >+
> >+	size = meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
> >+
> >+	if (!size || size > SM_MEM_SIZE)
> >+		return -EINVAL;
> >+
> >+	memcpy(buffer, sm_sharemem_out_base, size);
> >+	return size;
> >+}
> 
> This function will be needed to be exported to be callable from modules.

Fix in v3.

> >+
> >+u32 meson_sm_call_write(void *buffer, unsigned int b_size, u32 cmd, u32 arg0,
> >+			u32 arg1, u32 arg2, u32 arg3, u32 arg4)
> >+{
> >+	u32 size;
> >+
> >+	if (b_size > SM_MEM_SIZE)
> >+		return -EINVAL;
> >+
> >+	memcpy(sm_sharemem_in_base, buffer, b_size);
> >+
> >+	size = meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
> >+
> >+	if (!size)
> >+		return -EINVAL;
> >+
> >+	return size;
> >+}
> >+
> 
> Same here.

Thanks.

Cheers,

-- 
Carlo Caione


From boris.brezillon at free-electrons.com  Mon May 23 05:04:24 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Mon, 23 May 2016 14:04:24 +0200
Subject: [PATCH] misc: atmel-secumod: Driver for Atmel "security module".
In-Reply-To: <20160131113409.GI20165@piout.net>
References: <1453348655-31182-1-git-send-email-davidm@egauge.net>
 <20160125110921.GA4027@piout.net>
 <CALnQHM13cGnoma_3erb0oCnRD0sYGGNF1E1cgzCJHrEXbvJpRQ@mail.gmail.com>
 <alpine.LNX.2.00.1601291055520.23683@nippy.intranet>
 <20160131113409.GI20165@piout.net>
Message-ID: <20160523140424.7ded3893@bbrezillon>

Hi David,

Sorry for the late review (I know you've posted new versions but I want
to comment on this one).

On Sun, 31 Jan 2016 12:34:09 +0100
Alexandre Belloni <alexandre.belloni at free-electrons.com> wrote:

> On 29/01/2016 at 11:13:05 +1100, Finn Thain wrote :
> > 
> > On Mon, 25 Jan 2016, David Mosberger wrote:
> >   
> > > On Mon, Jan 25, 2016 at 4:09 AM, Alexandre Belloni 
> > > <alexandre.belloni at free-electrons.com> wrote:
> > >   
> > > > I know this does more than that but I think those thre sections should 
> > > > be registered using the nvmem framework. The sysfs file creation and 
> > > > accesses then comes for free.  
> > > 
> > > I think Finn's patches would have to go in for that first, since the 
> > > existing nvram code is a mess. Even with Finn's patches in, I think it 
> > > could go either way.  
> > 
> > I think Alexandre is speaking of the nvmem subsystem (not nvram).
> > Documentation/devicetree/bindings/nvmem
> > Documentation/nvmem
> > drivers/nvmem
> >   
> 
> absolutely.
> 
> > > I'm not exactly sure how some of the features of the security module 
> > > would be used: key management, auto erasing, there is a strange "backup 
> > > mode" vs "normal mode" which is not well documented, etc.  So I think it 
> > > may well end up being sufficiently different to warrant a separate 
> > > driver.  
> > 
> > nvmem is not a subsystem I am familiar with, so it's not immediately clear 
> > to me what your driver would look like if re-written that way.
> > 
> > Maybe it would become simpler. But if you did end up needing a separate 
> > misc driver as well, maybe use of the nvmem framework would actually 
> > increase complexity.
> > 
> > It would depend on your requirements. But I would focus on the actual 
> > requirement rather than uncertain future possibilities.
> >   
> > >   
> > > > Another idea is also to expose it using a genpool so it can be 
> > > > accessed as sram from inside the kernel.  
> > > 
> > > That may be a fine idea, but as far as our application is concerned, we 
> > > need user-level access to the battery-backed RAM.  
> > 
> > Right. I don't see how adding a memory allocator would help either.
> >   
> 
> While the immediate need is to use that sram from userspace, I think
> this is valuable to already think that at some point we will need to be
> able to partition and access that sram from the kernel.
> 
> 
> 

Well, I think we're reaching this point right now: I have to implement
"freeze" mode (entering a deep sleep mode by cutting all power domains
except VDDBU), and in order to do that I need to access BUREGs which
are part of the secu-sram you're trying to expose here.

Two comments on the nvmem approach:
1/ first of all it's not really a non-volative memory: if you loose
VDDBU you also loose the whole SRAM content.
2/ I need to be able to reserve the BUREG region (at least part of it)
for in kernel usage (need to store the SDRAM address I should jump to
when exiting freeze mode).

For those reason I think using the SRAM driver (drivers/misc/sram.c) is
a better approach. This driver both provides a sysfs interface (just
add the "export" property on the SRAM region you want to export to
user-space through sysfs), and a genpool provider (which I need to
reserve part of the SRAM for my "freeze" mode implementation).

Best Regards,

Boris

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


From hs.liao at mediatek.com  Mon May 23 05:23:06 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Mon, 23 May 2016 20:23:06 +0800
Subject: [PATCH v7 0/4] Mediatek MT8173 CMDQ support
Message-ID: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>


Hi,

This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used
to help read/write registers with critical time limitation, such as
updating display configuration during the vblank. It controls Global
Command Engine (GCE) hardware to achieve this requirement.

These patches have a build dependency on top of v4.6-rc1.

Changes since v6:
 - remove task waiting list
 - remove cmdq_command
 - use kzalloc/kfree instead of kmem_cache
 - use u64* instead of u32* if suitable
 - shrink some code

Best regards,
HS Liao

HS Liao (4):
  dt-bindings: soc: Add documentation for the MediaTek GCE unit
  CMDQ: Mediatek CMDQ driver
  arm64: dts: mt8173: Add GCE node
  CMDQ: suspend/resume protection

 .../devicetree/bindings/soc/mediatek/gce.txt       |   34 +
 arch/arm64/boot/dts/mediatek/mt8173.dtsi           |    8 +
 drivers/soc/mediatek/Kconfig                       |   10 +
 drivers/soc/mediatek/Makefile                      |    1 +
 drivers/soc/mediatek/mtk-cmdq.c                    | 1062 ++++++++++++++++++++
 include/soc/mediatek/cmdq.h                        |  197 ++++
 6 files changed, 1312 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/gce.txt
 create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
 create mode 100644 include/soc/mediatek/cmdq.h

-- 
1.9.1



From hs.liao at mediatek.com  Mon May 23 05:23:07 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Mon, 23 May 2016 20:23:07 +0800
Subject: [PATCH v7 1/4] dt-bindings: soc: Add documentation for the MediaTek
 GCE unit
In-Reply-To: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
References: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1464006190-344-2-git-send-email-hs.liao@mediatek.com>

This adds documentation for the MediaTek Global Command Engine (GCE) unit
found in MT8173 SoCs.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/soc/mediatek/gce.txt       | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/gce.txt

diff --git a/Documentation/devicetree/bindings/soc/mediatek/gce.txt b/Documentation/devicetree/bindings/soc/mediatek/gce.txt
new file mode 100644
index 0000000..eff07e2
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/gce.txt
@@ -0,0 +1,34 @@
+MediaTek GCE
+===============
+
+The Global Command Engine (GCE) is used to help read/write registers with
+critical time limitation, such as updating display configuration during the
+vblank. The GCE can be used to implement the Command Queue (CMDQ) driver.
+
+Required properties:
+- compatible: Must be "mediatek,mt8173-gce"
+- reg: Address range of the GCE unit
+- interrupts: The interrupt signal from the GCE block
+- clock: Clocks according to the common clock binding
+- clock-names: Must be "gce" to stand for GCE clock
+
+Required properties for a client device:
+- mediatek,gce: Should point to the respective GCE block
+
+Example:
+
+	gce: gce at 10212000 {
+		compatible = "mediatek,mt8173-gce";
+		reg = <0 0x10212000 0 0x1000>;
+		interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&infracfg CLK_INFRA_GCE>;
+		clock-names = "gce";
+	};
+
+Example for a client device:
+
+	mmsys: clock-controller at 14000000 {
+		compatible = "mediatek,mt8173-mmsys";
+		mediatek,gce = <&gce>;
+		...
+	};
-- 
1.9.1



From hs.liao at mediatek.com  Mon May 23 05:23:08 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Mon, 23 May 2016 20:23:08 +0800
Subject: [PATCH v7 2/4] CMDQ: Mediatek CMDQ driver
In-Reply-To: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
References: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1464006190-344-3-git-send-email-hs.liao@mediatek.com>

This patch is first version of Mediatek Command Queue(CMDQ) driver. The
CMDQ is used to help read/write registers with critical time limitation,
such as updating display configuration during the vblank. It controls
Global Command Engine (GCE) hardware to achieve this requirement.
Currently, CMDQ only supports display related hardwares, but we expect
it can be extended to other hardwares for future requirements.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
Signed-off-by: CK Hu <ck.hu at mediatek.com>
---
 drivers/soc/mediatek/Kconfig    |  10 +
 drivers/soc/mediatek/Makefile   |   1 +
 drivers/soc/mediatek/mtk-cmdq.c | 904 ++++++++++++++++++++++++++++++++++++++++
 include/soc/mediatek/cmdq.h     | 197 +++++++++
 4 files changed, 1112 insertions(+)
 create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
 create mode 100644 include/soc/mediatek/cmdq.h

diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 0a4ea80..c4ad75c 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -1,6 +1,16 @@
 #
 # MediaTek SoC drivers
 #
+config MTK_CMDQ
+	bool "MediaTek CMDQ Support"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	select MTK_INFRACFG
+	help
+	  Say yes here to add support for the MediaTek Command Queue (CMDQ)
+	  driver. The CMDQ is used to help read/write registers with critical
+	  time limitation, such as updating display configuration during the
+	  vblank.
+
 config MTK_INFRACFG
 	bool "MediaTek INFRACFG Support"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index 12998b0..f7397ef 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq.o
 obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
 obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
 obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
new file mode 100644
index 0000000..f8c5d02
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-cmdq.c
@@ -0,0 +1,904 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/suspend.h>
+#include <linux/workqueue.h>
+#include <soc/mediatek/cmdq.h>
+
+#define CMDQ_INITIAL_CMD_BLOCK_SIZE	PAGE_SIZE
+#define CMDQ_INST_SIZE			8 /* instruction is 64-bit */
+
+#define CMDQ_DEFAULT_TIMEOUT_MS		1000
+
+#define CMDQ_DRIVER_DEVICE_NAME		"mtk_cmdq"
+#define CMDQ_CLK_NAME			"gce"
+
+#define CMDQ_CURR_IRQ_STATUS		0x010
+#define CMDQ_THR_SLOT_CYCLES		0x030
+
+#define CMDQ_THR_BASE			0x100
+#define CMDQ_THR_SHIFT			0x080
+#define CMDQ_THR_WARM_RESET		0x00
+#define CMDQ_THR_ENABLE_TASK		0x04
+#define CMDQ_THR_SUSPEND_TASK		0x08
+#define CMDQ_THR_CURR_STATUS		0x0c
+#define CMDQ_THR_IRQ_STATUS		0x10
+#define CMDQ_THR_IRQ_ENABLE		0x14
+#define CMDQ_THR_CURR_ADDR		0x20
+#define CMDQ_THR_END_ADDR		0x24
+#define CMDQ_THR_CFG			0x40
+
+#define CMDQ_IRQ_MASK			0xffff
+
+#define CMDQ_THR_ENABLED		0x1
+#define CMDQ_THR_DISABLED		0x0
+#define CMDQ_THR_SUSPEND		0x1
+#define CMDQ_THR_RESUME			0x0
+#define CMDQ_THR_STATUS_SUSPENDED	BIT(1)
+#define CMDQ_THR_DO_WARM_RESET		BIT(0)
+#define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
+#define CMDQ_THR_PRIORITY		3
+#define CMDQ_THR_IRQ_DONE		0x1
+#define CMDQ_THR_IRQ_ERROR		0x12
+#define CMDQ_THR_IRQ_EN			0x13 /* done + error */
+#define CMDQ_THR_IRQ_MASK		0x13
+#define CMDQ_THR_EXECUTING		BIT(31)
+
+#define CMDQ_ARG_A_WRITE_MASK		0xffff
+#define CMDQ_SUBSYS_MASK		0x1f
+
+#define CMDQ_OP_CODE_SHIFT		24
+#define CMDQ_SUBSYS_SHIFT		16
+
+#define CMDQ_JUMP_BY_OFFSET		0x10000000
+#define CMDQ_JUMP_BY_PA			0x10000001
+#define CMDQ_JUMP_PASS			CMDQ_INST_SIZE
+
+#define CMDQ_WFE_UPDATE			BIT(31)
+#define CMDQ_WFE_WAIT			BIT(15)
+#define CMDQ_WFE_WAIT_VALUE		0x1
+
+#define CMDQ_EOC_IRQ_EN			BIT(0)
+
+#define CMDQ_ENABLE_MASK		BIT(0)
+
+#define CMDQ_OP_CODE_MASK		0xff000000
+
+enum cmdq_thread_index {
+	CMDQ_THR_DISP_MAIN_IDX,	/* main */
+	CMDQ_THR_DISP_SUB_IDX,	/* sub */
+	CMDQ_THR_DISP_MISC_IDX,	/* misc */
+	CMDQ_THR_MAX_COUNT,	/* max */
+};
+
+/*
+ * CMDQ_CODE_MOVE:
+ *   move value into internal register as mask
+ *   format: op mask
+ * CMDQ_CODE_WRITE:
+ *   write value into target register
+ *   format: op subsys address value
+ * CMDQ_CODE_JUMP:
+ *   jump by offset
+ *   format: op offset
+ * CMDQ_CODE_WFE:
+ *   wait for event and clear
+ *   it is just clear if no wait
+ *   format: [wait]  op event update:1 to_wait:1 wait:1
+ *           [clear] op event update:1 to_wait:0 wait:0
+ * CMDQ_CODE_EOC:
+ *   end of command
+ *   format: op irq_flag
+ */
+enum cmdq_code {
+	CMDQ_CODE_MOVE = 0x02,
+	CMDQ_CODE_WRITE = 0x04,
+	CMDQ_CODE_JUMP = 0x10,
+	CMDQ_CODE_WFE = 0x20,
+	CMDQ_CODE_EOC = 0x40,
+};
+
+enum cmdq_task_state {
+	TASK_STATE_BUSY,	/* task running on a thread */
+	TASK_STATE_ERROR,	/* task execution error */
+	TASK_STATE_DONE,	/* task finished */
+};
+
+struct cmdq_task_cb {
+	cmdq_async_flush_cb	cb;
+	void			*data;
+};
+
+struct cmdq_thread {
+	void __iomem		*base;
+	struct list_head	task_busy_list;
+	wait_queue_head_t	wait_queue; /* wait task done */
+};
+
+
+struct cmdq_task {
+	struct cmdq		*cmdq;
+	struct list_head	list_entry;
+	enum cmdq_task_state	task_state;
+	void			*va_base; /* va */
+	dma_addr_t		mva_base; /* pa */
+	u64			engine_flag;
+	size_t			command_size;
+	u32			num_cmd;
+	struct cmdq_thread	*thread;
+	struct cmdq_task_cb	cb;
+	struct work_struct	release_work;
+};
+
+struct cmdq {
+	struct device		*dev;
+	void __iomem		*base;
+	u32			irq;
+	struct workqueue_struct	*task_release_wq;
+	struct cmdq_thread	thread[CMDQ_THR_MAX_COUNT];
+	spinlock_t		exec_lock;	/* for exec task */
+	struct clk		*clock;
+};
+
+struct cmdq_subsys {
+	u32	base_addr;
+	int	id;
+};
+
+static const struct cmdq_subsys g_subsys[] = {
+	{0x1400, 1},
+	{0x1401, 2},
+	{0x1402, 3},
+};
+
+static int cmdq_subsys_base_addr_to_id(u32 base_addr)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(g_subsys); i++)
+		if (g_subsys[i].base_addr == base_addr)
+			return g_subsys[i].id;
+	return -EFAULT;
+}
+
+static int cmdq_eng_get_thread(u64 flag)
+{
+	if (flag & BIT_ULL(CMDQ_ENG_DISP_DSI0))
+		return CMDQ_THR_DISP_MAIN_IDX;
+	else if (flag & BIT_ULL(CMDQ_ENG_DISP_DPI0))
+		return CMDQ_THR_DISP_SUB_IDX;
+	else
+		return CMDQ_THR_DISP_MISC_IDX;
+}
+
+static void cmdq_task_release(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+
+	dma_free_coherent(cmdq->dev, task->command_size, task->va_base,
+			  task->mva_base);
+	kfree(task);
+}
+
+static struct cmdq_task *cmdq_task_acquire(struct cmdq_rec *rec,
+					   struct cmdq_task_cb cb)
+{
+	struct cmdq *cmdq = rec->cmdq;
+	struct device *dev = cmdq->dev;
+	struct cmdq_task *task;
+
+	task = kzalloc(sizeof(*task), GFP_KERNEL);
+	INIT_LIST_HEAD(&task->list_entry);
+	task->va_base = dma_alloc_coherent(dev, rec->command_size,
+					   &task->mva_base, GFP_KERNEL);
+	if (!task->va_base) {
+		dev_err(dev, "allocate command buffer failed\n");
+		kfree(task);
+		return NULL;
+	}
+
+	task->cmdq = cmdq;
+	task->command_size = rec->command_size;
+	task->engine_flag = rec->engine_flag;
+	task->task_state = TASK_STATE_BUSY;
+	task->cb = cb;
+	memcpy(task->va_base, rec->buf, rec->command_size);
+	task->num_cmd = task->command_size / sizeof(u64);
+	return task;
+}
+
+static void cmdq_thread_writel(struct cmdq_thread *thread, u32 value,
+			       u32 offset)
+{
+	writel(value, thread->base + offset);
+}
+
+static u32 cmdq_thread_readl(struct cmdq_thread *thread, u32 offset)
+{
+	return readl(thread->base + offset);
+}
+
+static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	u32 enabled;
+	u32 status;
+
+	cmdq_thread_writel(thread, CMDQ_THR_SUSPEND, CMDQ_THR_SUSPEND_TASK);
+
+	/* If already disabled, treat as suspended successful. */
+	enabled = cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK);
+	if (!(enabled & CMDQ_THR_ENABLED))
+		return 0;
+
+	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_CURR_STATUS,
+				      status,
+				      status & CMDQ_THR_STATUS_SUSPENDED,
+				      0, 10)) {
+		dev_err(cmdq->dev, "Suspend HW thread 0x%x failed\n",
+			(u32)(thread->base - cmdq->base));
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static void cmdq_thread_resume(struct cmdq_thread *thread)
+{
+	cmdq_thread_writel(thread, CMDQ_THR_RESUME, CMDQ_THR_SUSPEND_TASK);
+}
+
+static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	void __iomem *gce_base = cmdq->base;
+	u32 warm_reset;
+
+	cmdq_thread_writel(thread, CMDQ_THR_DO_WARM_RESET, CMDQ_THR_WARM_RESET);
+	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET,
+				      warm_reset,
+				      !(warm_reset & CMDQ_THR_DO_WARM_RESET),
+				      0, 10)) {
+		dev_err(cmdq->dev, "Reset HW thread 0x%x failed\n",
+			(u32)(thread->base - cmdq->base));
+		return -EFAULT;
+	}
+	writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, gce_base + CMDQ_THR_SLOT_CYCLES);
+	return 0;
+}
+
+static void cmdq_thread_disable(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	cmdq_thread_reset(cmdq, thread);
+	cmdq_thread_writel(thread, CMDQ_THR_DISABLED, CMDQ_THR_ENABLE_TASK);
+}
+
+/* notify GCE to re-fetch commands by setting HW thread PC */
+static void cmdq_thread_invalidate_fetched_data(struct cmdq_thread *thread)
+{
+	cmdq_thread_writel(thread,
+			   cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR),
+			   CMDQ_THR_CURR_ADDR);
+}
+
+static void cmdq_task_insert_into_thread(struct cmdq_task *task)
+{
+	struct cmdq_thread *thread = task->thread;
+	struct cmdq_task *prev_task = list_last_entry(
+			&thread->task_busy_list, typeof(*task), list_entry);
+	u64 *prev_task_base = prev_task->va_base;
+
+	/* let previous task jump to this task */
+	prev_task_base[prev_task->num_cmd - 1] = (u64)CMDQ_JUMP_BY_PA << 32 |
+						 task->mva_base;
+
+	cmdq_thread_invalidate_fetched_data(thread);
+}
+
+/* we assume tasks in the same display thread are waiting the same event. */
+static void cmdq_task_remove_wfe(struct cmdq_task *task)
+{
+	u32 wfe_option = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
+	u32 wfe_op = CMDQ_CODE_WFE << CMDQ_OP_CODE_SHIFT;
+	u32 *base = task->va_base;
+	u32 num_cmd = task->num_cmd << 1;
+	int i;
+
+	for (i = 0; i < num_cmd; i += 2)
+		if (base[i] == wfe_option &&
+		    (base[i + 1] & CMDQ_OP_CODE_MASK) == wfe_op) {
+			base[i] = CMDQ_JUMP_PASS;
+			base[i + 1] = CMDQ_JUMP_BY_OFFSET;
+		}
+}
+
+static void cmdq_task_exec(struct cmdq_task *task, struct cmdq_thread *thread)
+{
+	struct cmdq *cmdq = task->cmdq;
+	unsigned long flags;
+	unsigned long curr_pa, end_pa;
+
+	WARN_ON(clk_prepare_enable(cmdq->clock) < 0);
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+	task->thread = thread;
+	task->task_state = TASK_STATE_BUSY;
+	if (list_empty(&thread->task_busy_list)) {
+		WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
+
+		cmdq_thread_writel(thread, task->mva_base, CMDQ_THR_CURR_ADDR);
+		cmdq_thread_writel(thread, task->mva_base + task->command_size,
+				   CMDQ_THR_END_ADDR);
+		cmdq_thread_writel(thread, CMDQ_THR_PRIORITY, CMDQ_THR_CFG);
+		cmdq_thread_writel(thread, CMDQ_THR_IRQ_EN,
+				   CMDQ_THR_IRQ_ENABLE);
+
+		list_move_tail(&task->list_entry,
+			       &thread->task_busy_list);
+
+		cmdq_thread_writel(thread, CMDQ_THR_ENABLED,
+				   CMDQ_THR_ENABLE_TASK);
+	} else {
+		WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
+
+		/*
+		 * check boundary condition
+		 * PC = END - 8, EOC is executed
+		 * PC = END, all CMDs are executed
+		 */
+		curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
+		end_pa = cmdq_thread_readl(thread, CMDQ_THR_END_ADDR);
+		if (curr_pa == end_pa - 8 || curr_pa == end_pa) {
+			/* set to this task directly */
+			cmdq_thread_writel(thread, task->mva_base,
+					   CMDQ_THR_CURR_ADDR);
+		} else {
+			cmdq_task_insert_into_thread(task);
+
+			if (thread == &cmdq->thread[CMDQ_THR_DISP_MAIN_IDX] ||
+			    thread == &cmdq->thread[CMDQ_THR_DISP_SUB_IDX])
+				cmdq_task_remove_wfe(task);
+
+			smp_mb(); /* modify jump before enable thread */
+		}
+
+		cmdq_thread_writel(thread, task->mva_base + task->command_size,
+				   CMDQ_THR_END_ADDR);
+		list_move_tail(&task->list_entry, &thread->task_busy_list);
+		cmdq_thread_resume(thread);
+	}
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+}
+
+static void cmdq_handle_error_done(struct cmdq *cmdq,
+				   struct cmdq_thread *thread, bool err)
+{
+	struct cmdq_task *task, *tmp, *curr_task = NULL;
+	u32 curr_pa;
+	struct cmdq_cb_data cmdq_cb_data;
+
+	curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
+
+	list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
+				 list_entry) {
+		if (curr_pa >= task->mva_base &&
+		    curr_pa < (task->mva_base + task->command_size))
+			curr_task = task;
+		if (task->cb.cb) {
+			cmdq_cb_data.err = curr_task ? err : false;
+			cmdq_cb_data.data = task->cb.data;
+			task->cb.cb(cmdq_cb_data);
+		}
+		task->task_state = (curr_task && err) ? TASK_STATE_ERROR :
+				TASK_STATE_DONE;
+		list_del(&task->list_entry);
+		if (curr_task)
+			break;
+	}
+
+	wake_up(&thread->wait_queue);
+}
+
+static void cmdq_thread_irq_handler(struct cmdq *cmdq, int tid)
+{
+	struct cmdq_thread *thread = &cmdq->thread[tid];
+	unsigned long flags = 0L;
+	int value;
+
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+
+	/*
+	 * it is possible for another CPU core
+	 * to run "release task" right before we acquire the spin lock
+	 * and thus reset / disable this HW thread
+	 * so we check both the IRQ flag and the enable bit of this thread
+	 */
+	value = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
+	if (!(value & CMDQ_THR_IRQ_MASK)) {
+		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+		return;
+	}
+
+	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
+	      CMDQ_THR_ENABLED)) {
+		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+		return;
+	}
+
+	cmdq_thread_writel(thread, ~value, CMDQ_THR_IRQ_STATUS);
+
+	if (value & CMDQ_THR_IRQ_ERROR)
+		cmdq_handle_error_done(cmdq, thread, true);
+	else if (value & CMDQ_THR_IRQ_DONE)
+		cmdq_handle_error_done(cmdq, thread, false);
+
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+}
+
+static irqreturn_t cmdq_irq_handler(int irq, void *dev)
+{
+	struct cmdq *cmdq = dev;
+	u32 irq_status;
+	int i;
+
+	irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS);
+	irq_status &= CMDQ_IRQ_MASK;
+	irq_status ^= CMDQ_IRQ_MASK;
+
+	if (!irq_status)
+		return IRQ_NONE;
+
+	while (irq_status) {
+		i = ffs(irq_status) - 1;
+		irq_status &= ~BIT(i);
+		cmdq_thread_irq_handler(cmdq, i);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int cmdq_task_handle_error_result(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+	struct device *dev = cmdq->dev;
+	struct cmdq_thread *thread = task->thread;
+	struct cmdq_task *next_task, *prev_task;
+	u32 irq_flag;
+
+	/* suspend HW thread to ensure consistency */
+	WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
+
+	/*
+	 * Save next_task and prev_task in advance
+	 * since cmdq_handle_error_done will remove list_entry.
+	 */
+	next_task = prev_task = NULL;
+	if (task->list_entry.next != &thread->task_busy_list)
+		next_task = list_next_entry(task, list_entry);
+	if (task->list_entry.prev != &thread->task_busy_list)
+		prev_task = list_prev_entry(task, list_entry);
+
+	/*
+	 * Although IRQ is disabled, GCE continues to execute.
+	 * It may have pending IRQ before HW thread is suspended,
+	 * so check this condition again.
+	 */
+	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
+	if (irq_flag & CMDQ_THR_IRQ_ERROR)
+		cmdq_handle_error_done(cmdq, thread, true);
+	else if (irq_flag & CMDQ_THR_IRQ_DONE)
+		cmdq_handle_error_done(cmdq, thread, false);
+	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
+
+	if (task->task_state == TASK_STATE_DONE) {
+		cmdq_thread_resume(thread);
+		return 0;
+	}
+
+	if (task->task_state == TASK_STATE_ERROR) {
+		dev_err(dev, "task 0x%p error\n", task);
+		if (next_task) /* move to next task */
+			cmdq_thread_writel(thread, next_task->mva_base,
+					   CMDQ_THR_CURR_ADDR);
+		cmdq_thread_resume(thread);
+		return -ECANCELED;
+	}
+
+	/* If task is running, force to remove it. */
+	dev_err(dev, "task 0x%p timeout or killed\n", task);
+
+	if (task->task_state == TASK_STATE_BUSY)
+		task->task_state = TASK_STATE_ERROR;
+
+	if (prev_task) {
+		u64 *prev_va = prev_task->va_base;
+		u64 *curr_va = task->va_base;
+
+		/* copy JUMP instruction */
+		prev_va[prev_task->num_cmd - 1] = curr_va[task->num_cmd - 1];
+
+		cmdq_thread_invalidate_fetched_data(thread);
+	} else if (next_task) { /* move to next task */
+		cmdq_thread_writel(thread, next_task->mva_base,
+				   CMDQ_THR_CURR_ADDR);
+	}
+
+	list_del(&task->list_entry);
+	cmdq_thread_resume(thread);
+
+	/* call cb here to prevent lock */
+	if (task->cb.cb) {
+		struct cmdq_cb_data cmdq_cb_data;
+
+		cmdq_cb_data.err = true;
+		cmdq_cb_data.data = task->cb.data;
+		task->cb.cb(cmdq_cb_data);
+	}
+
+	return -ECANCELED;
+}
+
+static int cmdq_task_wait_and_release(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+	struct device *dev = cmdq->dev;
+	struct cmdq_thread *thread = task->thread;
+	int wait_q;
+	int err = 0;
+	unsigned long flags;
+
+	wait_q = wait_event_timeout(thread->wait_queue,
+				    task->task_state != TASK_STATE_BUSY,
+				    msecs_to_jiffies(CMDQ_DEFAULT_TIMEOUT_MS));
+	if (!wait_q)
+		dev_dbg(dev, "timeout!\n");
+
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+	if (task->task_state != TASK_STATE_DONE)
+		err = cmdq_task_handle_error_result(task);
+	if (list_empty(&thread->task_busy_list))
+		cmdq_thread_disable(cmdq, thread);
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+
+	/* release regardless of success or not */
+	clk_disable_unprepare(cmdq->clock);
+	cmdq_task_release(task);
+
+	return err;
+}
+
+static void cmdq_task_wait_release_work(struct work_struct *work_item)
+{
+	struct cmdq_task *task = container_of(work_item, struct cmdq_task,
+					      release_work);
+
+	cmdq_task_wait_and_release(task);
+}
+
+static void cmdq_task_wait_release_schedule(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+
+	INIT_WORK(&task->release_work, cmdq_task_wait_release_work);
+	queue_work(cmdq->task_release_wq, &task->release_work);
+}
+
+static int cmdq_rec_realloc_cmd_buffer(struct cmdq_rec *rec, size_t size)
+{
+	void *new_buf;
+
+	new_buf = krealloc(rec->buf, size, GFP_KERNEL | __GFP_ZERO);
+	if (!new_buf)
+		return -ENOMEM;
+	rec->buf = new_buf;
+	rec->buf_size = size;
+	return 0;
+}
+
+struct cmdq_base *cmdq_register_device(struct device *dev)
+{
+	struct cmdq_base *cmdq_base;
+	struct resource res;
+	int subsys;
+	u32 base;
+
+	if (of_address_to_resource(dev->of_node, 0, &res))
+		return NULL;
+	base = (u32)res.start;
+
+	subsys = cmdq_subsys_base_addr_to_id(base >> 16);
+	if (subsys < 0)
+		return NULL;
+
+	cmdq_base = devm_kmalloc(dev, sizeof(*cmdq_base), GFP_KERNEL);
+	if (!cmdq_base)
+		return NULL;
+	cmdq_base->subsys = subsys;
+	cmdq_base->base = base;
+
+	return cmdq_base;
+}
+EXPORT_SYMBOL(cmdq_register_device);
+
+int cmdq_rec_create(struct device *dev, u64 engine_flag,
+		    struct cmdq_rec **rec_ptr)
+{
+	struct cmdq_rec *rec;
+	int err;
+
+	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
+	if (!rec)
+		return -ENOMEM;
+	rec->cmdq = dev_get_drvdata(dev);
+	rec->engine_flag = engine_flag;
+	err = cmdq_rec_realloc_cmd_buffer(rec, CMDQ_INITIAL_CMD_BLOCK_SIZE);
+	if (err < 0) {
+		kfree(rec);
+		return err;
+	}
+	*rec_ptr = rec;
+	return 0;
+}
+EXPORT_SYMBOL(cmdq_rec_create);
+
+static int cmdq_rec_append_command(struct cmdq_rec *rec, enum cmdq_code code,
+				   u32 arg_a, u32 arg_b)
+{
+	u64 *cmd_ptr;
+	int err;
+
+	if (WARN_ON(rec->finalized))
+		return -EBUSY;
+	if (code < CMDQ_CODE_MOVE || code > CMDQ_CODE_EOC)
+		return -EINVAL;
+	if (unlikely(rec->command_size + CMDQ_INST_SIZE > rec->buf_size)) {
+		err = cmdq_rec_realloc_cmd_buffer(rec, rec->buf_size * 2);
+		if (err < 0)
+			return err;
+	}
+	cmd_ptr = rec->buf + rec->command_size;
+	(*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b;
+	rec->command_size += CMDQ_INST_SIZE;
+	return 0;
+}
+
+int cmdq_rec_write(struct cmdq_rec *rec, u32 value, struct cmdq_base *base,
+		   u32 offset)
+{
+	u32 arg_a = ((base->base + offset) & CMDQ_ARG_A_WRITE_MASK) |
+		    ((base->subsys & CMDQ_SUBSYS_MASK) << CMDQ_SUBSYS_SHIFT);
+	return cmdq_rec_append_command(rec, CMDQ_CODE_WRITE, arg_a, value);
+}
+EXPORT_SYMBOL(cmdq_rec_write);
+
+int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
+			struct cmdq_base *base, u32 offset, u32 mask)
+{
+	u32 offset_mask = offset;
+	int err;
+
+	if (mask != 0xffffffff) {
+		err = cmdq_rec_append_command(rec, CMDQ_CODE_MOVE, 0, ~mask);
+		if (err < 0)
+			return err;
+		offset_mask |= CMDQ_ENABLE_MASK;
+	}
+	return cmdq_rec_write(rec, value, base, offset_mask);
+}
+EXPORT_SYMBOL(cmdq_rec_write_mask);
+
+int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event)
+{
+	u32 arg_b;
+
+	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
+		return -EINVAL;
+
+	/*
+	 * bit 0-11: wait value
+	 * bit 15: 1 - wait, 0 - no wait
+	 * bit 16-27: update value
+	 * bit 31: 1 - update, 0 - no update
+	 */
+	arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
+	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event, arg_b);
+}
+EXPORT_SYMBOL(cmdq_rec_wfe);
+
+int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event)
+{
+	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
+		return -EINVAL;
+
+	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event,
+				       CMDQ_WFE_UPDATE);
+}
+EXPORT_SYMBOL(cmdq_rec_clear_event);
+
+static int cmdq_rec_finalize(struct cmdq_rec *rec)
+{
+	int err;
+
+	if (rec->finalized)
+		return 0;
+
+	/* insert EOC and generate IRQ for each command iteration */
+	err = cmdq_rec_append_command(rec, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN);
+	if (err < 0)
+		return err;
+
+	/* JUMP to end */
+	err = cmdq_rec_append_command(rec, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS);
+	if (err < 0)
+		return err;
+
+	rec->finalized = true;
+	return 0;
+}
+
+static int _cmdq_rec_flush(struct cmdq_rec *rec, struct cmdq_task **task_out,
+			   cmdq_async_flush_cb cb, void *data)
+{
+	struct cmdq *cmdq = rec->cmdq;
+	struct cmdq_task_cb task_cb;
+	struct cmdq_thread *thread;
+	int err;
+
+	err = cmdq_rec_finalize(rec);
+	if (err < 0)
+		return err;
+
+	task_cb.cb = cb;
+	task_cb.data = data;
+	*task_out = cmdq_task_acquire(rec, task_cb);
+	if (!(*task_out))
+		return -EFAULT;
+
+	thread = &cmdq->thread[cmdq_eng_get_thread((*task_out)->engine_flag)];
+	cmdq_task_exec(*task_out, thread);
+	return 0;
+}
+
+int cmdq_rec_flush(struct cmdq_rec *rec)
+{
+	struct cmdq_task *task;
+	int err;
+
+	err = _cmdq_rec_flush(rec, &task, NULL, NULL);
+	if (err < 0)
+		return err;
+	return cmdq_task_wait_and_release(task);
+}
+EXPORT_SYMBOL(cmdq_rec_flush);
+
+int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
+			 void *data)
+{
+	struct cmdq_task *task;
+	int err;
+
+	err = _cmdq_rec_flush(rec, &task, cb, data);
+	if (err < 0)
+		return err;
+	cmdq_task_wait_release_schedule(task);
+	return 0;
+}
+EXPORT_SYMBOL(cmdq_rec_flush_async);
+
+void cmdq_rec_destroy(struct cmdq_rec *rec)
+{
+	kfree(rec->buf);
+	kfree(rec);
+}
+EXPORT_SYMBOL(cmdq_rec_destroy);
+
+static int cmdq_remove(struct platform_device *pdev)
+{
+	struct cmdq *cmdq = platform_get_drvdata(pdev);
+
+	destroy_workqueue(cmdq->task_release_wq);
+	cmdq->task_release_wq = NULL;
+	return 0;
+}
+
+static int cmdq_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct resource *res;
+	struct cmdq *cmdq;
+	int err, i;
+
+	cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
+	if (!cmdq)
+		return -ENOMEM;
+	cmdq->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	cmdq->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(cmdq->base)) {
+		dev_err(dev, "failed to ioremap gce\n");
+		return PTR_ERR(cmdq->base);
+	}
+
+	cmdq->irq = irq_of_parse_and_map(node, 0);
+	if (!cmdq->irq) {
+		dev_err(dev, "failed to get irq\n");
+		return -EINVAL;
+	}
+
+	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
+		dev, cmdq->base, cmdq->irq);
+
+	spin_lock_init(&cmdq->exec_lock);
+	cmdq->task_release_wq = alloc_ordered_workqueue(
+			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI,
+			"cmdq_task_wait_release");
+
+	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
+		cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
+				CMDQ_THR_SHIFT * i;
+		init_waitqueue_head(&cmdq->thread[i].wait_queue);
+		INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list);
+	}
+
+	platform_set_drvdata(pdev, cmdq);
+
+	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
+			       CMDQ_DRIVER_DEVICE_NAME, cmdq);
+	if (err < 0) {
+		dev_err(dev, "failed to register ISR (%d)\n", err);
+		goto fail;
+	}
+
+	cmdq->clock = devm_clk_get(dev, CMDQ_CLK_NAME);
+	if (IS_ERR(cmdq->clock)) {
+		dev_err(dev, "failed to get clk:%s\n", CMDQ_CLK_NAME);
+		err = PTR_ERR(cmdq->clock);
+		goto fail;
+	}
+	return 0;
+
+fail:
+	cmdq_remove(pdev);
+	return err;
+}
+
+static const struct of_device_id cmdq_of_ids[] = {
+	{.compatible = "mediatek,mt8173-gce",},
+	{}
+};
+
+static struct platform_driver cmdq_drv = {
+	.probe = cmdq_probe,
+	.remove = cmdq_remove,
+	.driver = {
+		.name = CMDQ_DRIVER_DEVICE_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = cmdq_of_ids,
+	}
+};
+
+builtin_platform_driver(cmdq_drv);
diff --git a/include/soc/mediatek/cmdq.h b/include/soc/mediatek/cmdq.h
new file mode 100644
index 0000000..60eef3d
--- /dev/null
+++ b/include/soc/mediatek/cmdq.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_CMDQ_H__
+#define __MTK_CMDQ_H__
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+enum cmdq_eng {
+	CMDQ_ENG_DISP_AAL,
+	CMDQ_ENG_DISP_COLOR0,
+	CMDQ_ENG_DISP_COLOR1,
+	CMDQ_ENG_DISP_DPI0,
+	CMDQ_ENG_DISP_DSI0,
+	CMDQ_ENG_DISP_DSI1,
+	CMDQ_ENG_DISP_GAMMA,
+	CMDQ_ENG_DISP_OD,
+	CMDQ_ENG_DISP_OVL0,
+	CMDQ_ENG_DISP_OVL1,
+	CMDQ_ENG_DISP_PWM0,
+	CMDQ_ENG_DISP_PWM1,
+	CMDQ_ENG_DISP_RDMA0,
+	CMDQ_ENG_DISP_RDMA1,
+	CMDQ_ENG_DISP_RDMA2,
+	CMDQ_ENG_DISP_UFOE,
+	CMDQ_ENG_DISP_WDMA0,
+	CMDQ_ENG_DISP_WDMA1,
+	CMDQ_ENG_MAX,
+};
+
+/* events for CMDQ and display */
+enum cmdq_event {
+	/* Display start of frame(SOF) events */
+	CMDQ_EVENT_DISP_OVL0_SOF = 11,
+	CMDQ_EVENT_DISP_OVL1_SOF = 12,
+	CMDQ_EVENT_DISP_RDMA0_SOF = 13,
+	CMDQ_EVENT_DISP_RDMA1_SOF = 14,
+	CMDQ_EVENT_DISP_RDMA2_SOF = 15,
+	CMDQ_EVENT_DISP_WDMA0_SOF = 16,
+	CMDQ_EVENT_DISP_WDMA1_SOF = 17,
+	/* Display end of frame(EOF) events */
+	CMDQ_EVENT_DISP_OVL0_EOF = 39,
+	CMDQ_EVENT_DISP_OVL1_EOF = 40,
+	CMDQ_EVENT_DISP_RDMA0_EOF = 41,
+	CMDQ_EVENT_DISP_RDMA1_EOF = 42,
+	CMDQ_EVENT_DISP_RDMA2_EOF = 43,
+	CMDQ_EVENT_DISP_WDMA0_EOF = 44,
+	CMDQ_EVENT_DISP_WDMA1_EOF = 45,
+	/* Mutex end of frame(EOF) events */
+	CMDQ_EVENT_MUTEX0_STREAM_EOF = 53,
+	CMDQ_EVENT_MUTEX1_STREAM_EOF = 54,
+	CMDQ_EVENT_MUTEX2_STREAM_EOF = 55,
+	CMDQ_EVENT_MUTEX3_STREAM_EOF = 56,
+	CMDQ_EVENT_MUTEX4_STREAM_EOF = 57,
+	/* Display underrun events */
+	CMDQ_EVENT_DISP_RDMA0_UNDERRUN = 63,
+	CMDQ_EVENT_DISP_RDMA1_UNDERRUN = 64,
+	CMDQ_EVENT_DISP_RDMA2_UNDERRUN = 65,
+	/* Keep this at the end of HW events */
+	CMDQ_MAX_HW_EVENT_COUNT = 260,
+};
+
+struct cmdq_cb_data {
+	bool	err;
+	void	*data;
+};
+
+typedef int (*cmdq_async_flush_cb)(struct cmdq_cb_data data);
+
+struct cmdq_task;
+struct cmdq;
+
+struct cmdq_rec {
+	struct cmdq		*cmdq;
+	u64			engine_flag;
+	size_t			command_size;
+	void			*buf;
+	size_t			buf_size;
+	bool			finalized;
+};
+
+struct cmdq_base {
+	int	subsys;
+	u32	base;
+};
+
+/**
+ * cmdq_register_device() - register device which needs CMDQ
+ * @dev:		device
+ *
+ * Return: cmdq_base pointer or NULL for failed
+ */
+struct cmdq_base *cmdq_register_device(struct device *dev);
+
+/**
+ * cmdq_rec_create() - create command queue record
+ * @dev:		device
+ * @engine_flag:	command queue engine flag
+ * @rec_ptr:		command queue record pointer to retrieve cmdq_rec
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_create(struct device *dev, u64 engine_flag,
+		    struct cmdq_rec **rec_ptr);
+
+/**
+ * cmdq_rec_write() - append write command to the command queue record
+ * @rec:	the command queue record
+ * @value:	the specified target register value
+ * @base:	the command queue base
+ * @offset:	register offset from module base
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_write(struct cmdq_rec *rec, u32 value,
+		   struct cmdq_base *base, u32 offset);
+
+/**
+ * cmdq_rec_write_mask() - append write command with mask to the command
+ *			   queue record
+ * @rec:	the command queue record
+ * @value:	the specified target register value
+ * @base:	the command queue base
+ * @offset:	register offset from module base
+ * @mask:	the specified target register mask
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
+			struct cmdq_base *base, u32 offset, u32 mask);
+
+/**
+ * cmdq_rec_wfe() - append wait for event command to the command queue record
+ * @rec:	the command queue record
+ * @event:	the desired event type to "wait and CLEAR"
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event);
+
+/**
+ * cmdq_rec_clear_event() - append clear event command to the command queue
+ *			    record
+ * @rec:	the command queue record
+ * @event:	the desired event to be cleared
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event);
+
+/**
+ * cmdq_rec_flush() - trigger CMDQ to execute the recorded commands
+ * @rec:	the command queue record
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ * Trigger CMDQ to execute the recorded commands. Note that this is a
+ * synchronous flush function. When the function returned, the recorded
+ * commands have been done.
+ */
+int cmdq_rec_flush(struct cmdq_rec *rec);
+
+/**
+ * cmdq_rec_flush_async() - trigger CMDQ to asynchronously execute the recorded
+ *			    commands and call back after ISR is finished
+ * @rec:	the command queue record
+ * @cb:		called in the end of CMDQ ISR
+ * @data:	this data will pass back to cb
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ * Trigger CMDQ to asynchronously execute the recorded commands and call back
+ * after ISR is finished. Note that this is an ASYNC function. When the function
+ * returned, it may or may not be finished. The ISR callback function is called
+ * in the end of ISR.
+ */
+int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
+			 void *data);
+
+/**
+ * cmdq_rec_destroy() - destroy command queue record
+ * @rec:	the command queue record
+ */
+void cmdq_rec_destroy(struct cmdq_rec *rec);
+
+#endif	/* __MTK_CMDQ_H__ */
-- 
1.9.1



From hs.liao at mediatek.com  Mon May 23 05:23:09 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Mon, 23 May 2016 20:23:09 +0800
Subject: [PATCH v7 3/4] arm64: dts: mt8173: Add GCE node
In-Reply-To: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
References: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1464006190-344-4-git-send-email-hs.liao@mediatek.com>

This patch adds the device node of the GCE hardware for CMDQ module.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index eab7efc..63d1718 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -300,6 +300,14 @@
 			#clock-cells = <1>;
 		};
 
+		gce: gce at 10212000 {
+			compatible = "mediatek,mt8173-gce";
+			reg = <0 0x10212000 0 0x1000>;
+			interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>;
+			clocks = <&infracfg CLK_INFRA_GCE>;
+			clock-names = "gce";
+		};
+
 		gic: interrupt-controller at 10220000 {
 			compatible = "arm,gic-400";
 			#interrupt-cells = <3>;
-- 
1.9.1



From hs.liao at mediatek.com  Mon May 23 05:23:10 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Mon, 23 May 2016 20:23:10 +0800
Subject: [PATCH v7 4/4] CMDQ: suspend/resume protection
In-Reply-To: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
References: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1464006190-344-5-git-send-email-hs.liao@mediatek.com>

Add suspend/resume protection mechanism to prevent active task(s) in
suspend.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
---
 drivers/soc/mediatek/mtk-cmdq.c | 174 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 166 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
index f8c5d02..1a51cfb 100644
--- a/drivers/soc/mediatek/mtk-cmdq.c
+++ b/drivers/soc/mediatek/mtk-cmdq.c
@@ -39,6 +39,7 @@
 #define CMDQ_CLK_NAME			"gce"
 
 #define CMDQ_CURR_IRQ_STATUS		0x010
+#define CMDQ_CURR_LOADED_THR		0x018
 #define CMDQ_THR_SLOT_CYCLES		0x030
 
 #define CMDQ_THR_BASE			0x100
@@ -125,6 +126,7 @@ enum cmdq_code {
 
 enum cmdq_task_state {
 	TASK_STATE_BUSY,	/* task running on a thread */
+	TASK_STATE_KILLED,	/* task process being killed */
 	TASK_STATE_ERROR,	/* task execution error */
 	TASK_STATE_DONE,	/* task finished */
 };
@@ -161,8 +163,12 @@ struct cmdq {
 	u32			irq;
 	struct workqueue_struct	*task_release_wq;
 	struct cmdq_thread	thread[CMDQ_THR_MAX_COUNT];
-	spinlock_t		exec_lock;	/* for exec task */
+	atomic_t		thread_usage;
+	struct mutex		task_mutex;	/* for task */
+	spinlock_t		exec_lock;	/* for exec */
 	struct clk		*clock;
+	bool			suspending;
+	bool			suspended;
 };
 
 struct cmdq_subsys {
@@ -196,15 +202,27 @@ static int cmdq_eng_get_thread(u64 flag)
 		return CMDQ_THR_DISP_MISC_IDX;
 }
 
-static void cmdq_task_release(struct cmdq_task *task)
+static void cmdq_task_release_unlocked(struct cmdq_task *task)
 {
 	struct cmdq *cmdq = task->cmdq;
 
+	/* This func should be inside cmdq->task_mutex mutex */
+	lockdep_assert_held(&cmdq->task_mutex);
+
 	dma_free_coherent(cmdq->dev, task->command_size, task->va_base,
 			  task->mva_base);
 	kfree(task);
 }
 
+static void cmdq_task_release(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+
+	mutex_lock(&cmdq->task_mutex);
+	cmdq_task_release_unlocked(task);
+	mutex_unlock(&cmdq->task_mutex);
+}
+
 static struct cmdq_task *cmdq_task_acquire(struct cmdq_rec *rec,
 					   struct cmdq_task_cb cb)
 {
@@ -576,6 +594,12 @@ static int cmdq_task_wait_and_release(struct cmdq_task *task)
 		dev_dbg(dev, "timeout!\n");
 
 	spin_lock_irqsave(&cmdq->exec_lock, flags);
+
+	if (cmdq->suspending && task->task_state == TASK_STATE_KILLED) {
+		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+		return 0;
+	}
+
 	if (task->task_state != TASK_STATE_DONE)
 		err = cmdq_task_handle_error_result(task);
 	if (list_empty(&thread->task_busy_list))
@@ -584,7 +608,9 @@ static int cmdq_task_wait_and_release(struct cmdq_task *task)
 
 	/* release regardless of success or not */
 	clk_disable_unprepare(cmdq->clock);
-	cmdq_task_release(task);
+	atomic_dec(&cmdq->thread_usage);
+	if (!(task->cmdq->suspending && task->task_state == TASK_STATE_KILLED))
+		cmdq_task_release(task);
 
 	return err;
 }
@@ -597,12 +623,28 @@ static void cmdq_task_wait_release_work(struct work_struct *work_item)
 	cmdq_task_wait_and_release(task);
 }
 
-static void cmdq_task_wait_release_schedule(struct cmdq_task *task)
+static void cmdq_task_wait_release_schedule(struct cmdq *cmdq,
+					    struct cmdq_task *task)
 {
-	struct cmdq *cmdq = task->cmdq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+
+	if (cmdq->suspending || cmdq->suspended) {
+		/*
+		 * This means system is suspened between
+		 * cmdq_task_submit_async() and
+		 * cmdq_task_wait_release_schedule(), so return immediately.
+		 * This task should be forced to remove by suspend flow.
+		 */
+		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+		return;
+	}
 
 	INIT_WORK(&task->release_work, cmdq_task_wait_release_work);
 	queue_work(cmdq->task_release_wq, &task->release_work);
+
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
 }
 
 static int cmdq_rec_realloc_cmd_buffer(struct cmdq_rec *rec, size_t size)
@@ -766,18 +808,31 @@ static int _cmdq_rec_flush(struct cmdq_rec *rec, struct cmdq_task **task_out,
 	struct cmdq_thread *thread;
 	int err;
 
+	mutex_lock(&cmdq->task_mutex);
+	if (rec->cmdq->suspending || rec->cmdq->suspended) {
+		dev_err(rec->cmdq->dev,
+			"%s is called after suspending\n", __func__);
+		mutex_unlock(&cmdq->task_mutex);
+		return -EPERM;
+	}
+
 	err = cmdq_rec_finalize(rec);
-	if (err < 0)
+	if (err < 0) {
+		mutex_unlock(&cmdq->task_mutex);
 		return err;
+	}
 
 	task_cb.cb = cb;
 	task_cb.data = data;
 	*task_out = cmdq_task_acquire(rec, task_cb);
-	if (!(*task_out))
+	if (!(*task_out)) {
+		mutex_unlock(&cmdq->task_mutex);
 		return -EFAULT;
+	}
 
 	thread = &cmdq->thread[cmdq_eng_get_thread((*task_out)->engine_flag)];
 	cmdq_task_exec(*task_out, thread);
+	mutex_unlock(&cmdq->task_mutex);
 	return 0;
 }
 
@@ -802,7 +857,13 @@ int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
 	err = _cmdq_rec_flush(rec, &task, cb, data);
 	if (err < 0)
 		return err;
-	cmdq_task_wait_release_schedule(task);
+
+	/*
+	 * Task could be released in suspend flow,
+	 * so we have to pass cmdq as parameter.
+	 */
+	cmdq_task_wait_release_schedule(rec->cmdq, task);
+
 	return 0;
 }
 EXPORT_SYMBOL(cmdq_rec_flush_async);
@@ -814,6 +875,95 @@ void cmdq_rec_destroy(struct cmdq_rec *rec)
 }
 EXPORT_SYMBOL(cmdq_rec_destroy);
 
+static int cmdq_suspend(struct device *dev)
+{
+	struct cmdq *cmdq = dev_get_drvdata(dev);
+	u32 exec_threads;
+	int ref_count;
+	unsigned long flags;
+	struct cmdq_thread *thread;
+	struct cmdq_task *task, *tmp;
+	int i;
+
+	/* lock to prevent new tasks */
+	mutex_lock(&cmdq->task_mutex);
+	cmdq->suspending = true;
+
+	exec_threads = readl(cmdq->base + CMDQ_CURR_LOADED_THR);
+	ref_count = atomic_read(&cmdq->thread_usage);
+	if (ref_count <= 0 && !(exec_threads & CMDQ_THR_EXECUTING))
+		goto exit;
+
+	dev_err(dev, "suspend: kill running, tasks.\n");
+	dev_err(dev, "threads: 0x%08x, ref:%d\n", exec_threads, ref_count);
+
+	/*
+	 * We need to ensure the system is ready to suspend,
+	 * so kill all running CMDQ tasks and release HW engines.
+	 */
+
+	/* remove all active tasks from thread and disable thread */
+	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
+		thread = &cmdq->thread[i];
+
+		if (list_empty(&thread->task_busy_list))
+			continue;
+
+		/* prevent clk disable in release flow */
+		clk_prepare_enable(cmdq->clock);
+		cmdq_thread_suspend(cmdq, thread);
+
+		list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
+					 list_entry) {
+			bool already_done = false;
+
+			spin_lock_irqsave(&cmdq->exec_lock, flags);
+			if (task->task_state == TASK_STATE_BUSY) {
+				/* still wait_event */
+				list_del(&task->list_entry);
+				task->task_state = TASK_STATE_KILLED;
+			} else {
+				/* almost finish its work */
+				already_done = true;
+			}
+			spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+
+			/*
+			 * TASK_STATE_KILLED will unlock
+			 * wait_event_timeout in cmdq_task_wait_and_release(),
+			 * so flush_work to wait auto release flow.
+			 *
+			 * We don't know processes running order,
+			 * so call cmdq_task_release_unlocked() here to
+			 * prevent releasing task before flush_work, and
+			 * also to prevent deadlock of task_mutex.
+			 */
+			if (!already_done) {
+				flush_work(&task->release_work);
+				cmdq_task_release_unlocked(task);
+			}
+		}
+
+		cmdq_thread_resume(thread);
+		cmdq_thread_disable(cmdq, &cmdq->thread[i]);
+		clk_disable_unprepare(cmdq->clock);
+	}
+
+exit:
+	cmdq->suspended = true;
+	cmdq->suspending = false;
+	mutex_unlock(&cmdq->task_mutex);
+	return 0; /* ALWAYS allow suspend */
+}
+
+static int cmdq_resume(struct device *dev)
+{
+	struct cmdq *cmdq = dev_get_drvdata(dev);
+
+	cmdq->suspended = false;
+	return 0;
+}
+
 static int cmdq_remove(struct platform_device *pdev)
 {
 	struct cmdq *cmdq = platform_get_drvdata(pdev);
@@ -852,6 +1002,7 @@ static int cmdq_probe(struct platform_device *pdev)
 	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
 		dev, cmdq->base, cmdq->irq);
 
+	mutex_init(&cmdq->task_mutex);
 	spin_lock_init(&cmdq->exec_lock);
 	cmdq->task_release_wq = alloc_ordered_workqueue(
 			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI,
@@ -879,6 +1030,7 @@ static int cmdq_probe(struct platform_device *pdev)
 		err = PTR_ERR(cmdq->clock);
 		goto fail;
 	}
+
 	return 0;
 
 fail:
@@ -886,6 +1038,11 @@ fail:
 	return err;
 }
 
+static const struct dev_pm_ops cmdq_pm_ops = {
+	.suspend = cmdq_suspend,
+	.resume = cmdq_resume,
+};
+
 static const struct of_device_id cmdq_of_ids[] = {
 	{.compatible = "mediatek,mt8173-gce",},
 	{}
@@ -897,6 +1054,7 @@ static struct platform_driver cmdq_drv = {
 	.driver = {
 		.name = CMDQ_DRIVER_DEVICE_NAME,
 		.owner = THIS_MODULE,
+		.pm = &cmdq_pm_ops,
 		.of_match_table = cmdq_of_ids,
 	}
 };
-- 
1.9.1



From j-keerthy at ti.com  Mon May 23 05:29:04 2016
From: j-keerthy at ti.com (Keerthy)
Date: Mon, 23 May 2016 17:59:04 +0530
Subject: [PATCH 0/3] ARM: keystone-k2l: Enable pinctrl support
Message-ID: <1464006547-19569-1-git-send-email-j-keerthy@ti.com>

The series enables pinctrl support for k2l devices.
Tested on keystone-k2l-evm board.

Keerthy (3):
  ARM: dts: keystone-k2l: Add pinctrl node
  arm: mach-keystone: Enable PINCTRL config
  ARM: configs: keystone: Enable PINCTRL_SINGLE Config

 arch/arm/boot/dts/keystone-k2l.dtsi | 149 ++++++++++++++++++++++++++++++++++++
 arch/arm/configs/keystone_defconfig |   1 +
 arch/arm/mach-keystone/Kconfig      |   1 +
 3 files changed, 151 insertions(+)

-- 
1.9.1



From j-keerthy at ti.com  Mon May 23 05:29:06 2016
From: j-keerthy at ti.com (Keerthy)
Date: Mon, 23 May 2016 17:59:06 +0530
Subject: [PATCH 2/3] arm: mach-keystone: Enable PINCTRL config
In-Reply-To: <1464006547-19569-1-git-send-email-j-keerthy@ti.com>
References: <1464006547-19569-1-git-send-email-j-keerthy@ti.com>
Message-ID: <1464006547-19569-3-git-send-email-j-keerthy@ti.com>

keystone-k2l uses pinmux and is compliant with PINCTRL_SINGLE
which depends on PINCTRL. Hence enable PINCTRL.

Signed-off-by: Keerthy <j-keerthy at ti.com>
---
 arch/arm/mach-keystone/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-keystone/Kconfig b/arch/arm/mach-keystone/Kconfig
index ea955f6db..7a432ee 100644
--- a/arch/arm/mach-keystone/Kconfig
+++ b/arch/arm/mach-keystone/Kconfig
@@ -11,6 +11,7 @@ config ARCH_KEYSTONE
 	select ZONE_DMA if ARM_LPAE
 	select MIGHT_HAVE_PCI
 	select PCI_DOMAINS if PCI
+	select PINCTRL
 	help
 	  Support for boards based on the Texas Instruments Keystone family of
 	  SoCs.
-- 
1.9.1



From j-keerthy at ti.com  Mon May 23 05:29:05 2016
From: j-keerthy at ti.com (Keerthy)
Date: Mon, 23 May 2016 17:59:05 +0530
Subject: [PATCH 1/3] ARM: dts: keystone-k2l: Add pinctrl node
In-Reply-To: <1464006547-19569-1-git-send-email-j-keerthy@ti.com>
References: <1464006547-19569-1-git-send-email-j-keerthy@ti.com>
Message-ID: <1464006547-19569-2-git-send-email-j-keerthy@ti.com>

Add pinctrl node and populate the pinctrl registers with the default
values.

Signed-off-by: Keerthy <j-keerthy at ti.com>
---
 arch/arm/boot/dts/keystone-k2l.dtsi | 149 ++++++++++++++++++++++++++++++++++++
 1 file changed, 149 insertions(+)

diff --git a/arch/arm/boot/dts/keystone-k2l.dtsi b/arch/arm/boot/dts/keystone-k2l.dtsi
index ff22ffc..2ee3d0a 100644
--- a/arch/arm/boot/dts/keystone-k2l.dtsi
+++ b/arch/arm/boot/dts/keystone-k2l.dtsi
@@ -54,6 +54,155 @@
 			interrupts = <GIC_SPI 435 IRQ_TYPE_EDGE_RISING>;
 		};
 
+		k2l_pmx: pinmux at 02620690 {
+			compatible = "pinctrl-single";
+			reg = <0x02620690 0xc>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-single,bit-per-mux;
+			pinctrl-single,register-width = <32>;
+			pinctrl-single,function-mask = <0x1>;
+			status = "disabled";
+
+			uart3_emifa_pins: pinmux_uart3_emifa_pins {
+				pinctrl-single,bits = <
+					/* UART3_EMIFA_SEL */
+					0x0 0x0  0xc0
+				>;
+			};
+
+			uart2_emifa_pins: pinmux_uart2_emifa_pins {
+			pinctrl-single,bits = <
+					/* UART2_EMIFA_SEL */
+					0x0 0x0  0x30
+				>;
+			};
+
+			uart01_spi2_pins: pinmux_uart01_spi2_pins {
+				pinctrl-single,bits = <
+					/* UART01_SPI2_SEL */
+					0x0 0x0 0x4
+				>;
+			};
+
+			dfesync_rp1_pins: pinmux_dfesync_rp1_pins{
+				pinctrl-single,bits = <
+					/* DFESYNC_RP1_SEL */
+					0x0 0x0 0x2
+				>;
+			};
+
+			avsif_pins: pinmux_avsif_pins {
+				pinctrl-single,bits = <
+					/* AVSIF_SEL */
+					0x0 0x0 0x1
+				>;
+			};
+
+			gpio_emu_pins: pinmux_gpio_emu_pins {
+				pinctrl-single,bits = <
+				/*
+				 * GPIO_EMU_SEL[31]: 0-GPIO31, 1-EMU33
+				 * GPIO_EMU_SEL[30]: 0-GPIO30, 1-EMU32
+				 * GPIO_EMU_SEL[29]: 0-GPIO29, 1-EMU31
+				 * GPIO_EMU_SEL[28]: 0-GPIO28, 1-EMU30
+				 * GPIO_EMU_SEL[27]: 0-GPIO27, 1-EMU29
+				 * GPIO_EMU_SEL[26]: 0-GPIO26, 1-EMU28
+				 * GPIO_EMU_SEL[25]: 0-GPIO25, 1-EMU27
+				 * GPIO_EMU_SEL[24]: 0-GPIO24, 1-EMU26
+				 * GPIO_EMU_SEL[23]: 0-GPIO23, 1-EMU25
+				 * GPIO_EMU_SEL[22]: 0-GPIO22, 1-EMU24
+				 * GPIO_EMU_SEL[21]: 0-GPIO21, 1-EMU23
+				 * GPIO_EMU_SEL[20]: 0-GPIO20, 1-EMU22
+				 * GPIO_EMU_SEL[19]: 0-GPIO19, 1-EMU21
+				 * GPIO_EMU_SEL[18]: 0-GPIO18, 1-EMU20
+				 * GPIO_EMU_SEL[17]: 0-GPIO17, 1-EMU19
+				 */
+					0x4 0x0000 0xFFFE0000
+				>;
+			};
+
+			gpio_timio_pins: pinmux_gpio_timio_pins {
+				pinctrl-single,bits = <
+				/*
+				 * GPIO_TIMIO_SEL[15]: 0-GPIO15, 1-TIMO7
+				 * GPIO_TIMIO_SEL[14]: 0-GPIO14, 1-TIMO6
+				 * GPIO_TIMIO_SEL[13]: 0-GPIO13, 1-TIMO5
+				 * GPIO_TIMIO_SEL[12]: 0-GPIO12, 1-TIMO4
+				 * GPIO_TIMIO_SEL[11]: 0-GPIO11, 1-TIMO3
+				 * GPIO_TIMIO_SEL[10]: 0-GPIO10, 1-TIMO2
+				 * GPIO_TIMIO_SEL[9]: 0-GPIO9, 1-TIMI7
+				 * GPIO_TIMIO_SEL[8]: 0-GPIO8, 1-TIMI6
+				 * GPIO_TIMIO_SEL[7]: 0-GPIO7, 1-TIMI5
+				 * GPIO_TIMIO_SEL[6]: 0-GPIO6, 1-TIMI4
+				 * GPIO_TIMIO_SEL[5]: 0-GPIO5, 1-TIMI3
+				 * GPIO_TIMIO_SEL[4]: 0-GPIO4, 1-TIMI2
+				 */
+					0x4 0x0 0xFFF0
+				>;
+			};
+
+			gpio_spi2cs_pins: pinmux_gpio_spi2cs_pins {
+				pinctrl-single,bits = <
+				/*
+				 * GPIO_SPI2CS_SEL[3]: 0-GPIO3, 1-SPI2CS4
+				 * GPIO_SPI2CS_SEL[2]: 0-GPIO2, 1-SPI2CS3
+				 * GPIO_SPI2CS_SEL[1]: 0-GPIO1, 1-SPI2CS2
+				 * GPIO_SPI2CS_SEL[0]: 0-GPIO0, 1-SPI2CS1
+				 */
+					0x4 0x0 0xF
+				>;
+			};
+
+			gpio_dfeio_pins: pinmux_gpio_dfeio_pins {
+				pinctrl-single,bits = <
+				/*
+				 * GPIO_DFEIO_SEL[31]: 0-DFEIO17, 1-GPIO63
+				 * GPIO_DFEIO_SEL[30]: 0-DFEIO16, 1-GPIO62
+				 * GPIO_DFEIO_SEL[29]: 0-DFEIO15, 1-GPIO61
+				 * GPIO_DFEIO_SEL[28]: 0-DFEIO14, 1-GPIO60
+				 * GPIO_DFEIO_SEL[27]: 0-DFEIO13, 1-GPIO59
+				 * GPIO_DFEIO_SEL[26]: 0-DFEIO12, 1-GPIO58
+				 * GPIO_DFEIO_SEL[25]: 0-DFEIO11, 1-GPIO57
+				 * GPIO_DFEIO_SEL[24]: 0-DFEIO10, 1-GPIO56
+				 * GPIO_DFEIO_SEL[23]: 0-DFEIO9, 1-GPIO55
+				 * GPIO_DFEIO_SEL[22]: 0-DFEIO8, 1-GPIO54
+				 * GPIO_DFEIO_SEL[21]: 0-DFEIO7, 1-GPIO53
+				 * GPIO_DFEIO_SEL[20]: 0-DFEIO6, 1-GPIO52
+				 * GPIO_DFEIO_SEL[19]: 0-DFEIO5, 1-GPIO51
+				 * GPIO_DFEIO_SEL[18]: 0-DFEIO4, 1-GPIO50
+				 * GPIO_DFEIO_SEL[17]: 0-DFEIO3, 1-GPIO49
+				 * GPIO_DFEIO_SEL[16]: 0-DFEIO2, 1-GPIO48
+				 */
+					0x8 0x0 0xFFFF0000
+				>;
+			};
+
+			gpio_emifa_pins: pinmux_gpio_emifa_pins {
+				pinctrl-single,bits = <
+				/*
+				 * GPIO_EMIFA_SEL[15]: 0-EMIFA17, 1-GPIO47
+				 * GPIO_EMIFA_SEL[14]: 0-EMIFA16, 1-GPIO46
+				 * GPIO_EMIFA_SEL[13]: 0-EMIFA15, 1-GPIO45
+				 * GPIO_EMIFA_SEL[12]: 0-EMIFA14, 1-GPIO44
+				 * GPIO_EMIFA_SEL[11]: 0-EMIFA13, 1-GPIO43
+				 * GPIO_EMIFA_SEL[10]: 0-EMIFA10, 1-GPIO42
+				 * GPIO_EMIFA_SEL[9]: 0-EMIFA9, 1-GPIO41
+				 * GPIO_EMIFA_SEL[8]: 0-EMIFA8, 1-GPIO40
+				 * GPIO_EMIFA_SEL[7]: 0-EMIFA7, 1-GPIO39
+				 * GPIO_EMIFA_SEL[6]: 0-EMIFA6, 1-GPIO38
+				 * GPIO_EMIFA_SEL[5]: 0-EMIFA5, 1-GPIO37
+				 * GPIO_EMIFA_SEL[4]: 0-EMIFA4, 1-GPIO36
+				 * GPIO_EMIFA_SEL[3]: 0-EMIFA3, 1-GPIO35
+				 * GPIO_EMIFA_SEL[2]: 0-EMIFA2, 1-GPIO34
+				 * GPIO_EMIFA_SEL[1]: 0-EMIFA1, 1-GPIO33
+				 * GPIO_EMIFA_SEL[0]: 0-EMIFA0, 1-GPIO32
+				 */
+					0x8 0x0 0xFFFF
+				>;
+			};
+		};
+
 		dspgpio0: keystone_dsp_gpio at 02620240 {
 			compatible = "ti,keystone-dsp-gpio";
 			gpio-controller;
-- 
1.9.1



From j-keerthy at ti.com  Mon May 23 05:29:07 2016
From: j-keerthy at ti.com (Keerthy)
Date: Mon, 23 May 2016 17:59:07 +0530
Subject: [PATCH 3/3] ARM: configs: keystone: Enable PINCTRL_SINGLE Config
In-Reply-To: <1464006547-19569-1-git-send-email-j-keerthy@ti.com>
References: <1464006547-19569-1-git-send-email-j-keerthy@ti.com>
Message-ID: <1464006547-19569-4-git-send-email-j-keerthy@ti.com>

keystone-k2l devices use pinmux and are compliant with PINCTRL_SINGLE.
Hence enable the config option.

Signed-off-by: Keerthy <j-keerthy at ti.com>
---
 arch/arm/configs/keystone_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig
index faba04d..71b42e6 100644
--- a/arch/arm/configs/keystone_defconfig
+++ b/arch/arm/configs/keystone_defconfig
@@ -144,6 +144,7 @@ CONFIG_I2C_DAVINCI=y
 CONFIG_SPI=y
 CONFIG_SPI_DAVINCI=y
 CONFIG_SPI_SPIDEV=y
+CONFIG_PINCTRL_SINGLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_DAVINCI=y
-- 
1.9.1



From marc.zyngier at arm.com  Mon May 23 05:36:58 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 23 May 2016 13:36:58 +0100
Subject: [PATCH 2/7] KVM: arm/arm64: vgic-v3: Clear all dirty LRs
In-Reply-To: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464007023-11736-3-git-send-email-marc.zyngier@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

When saving the state of the list registers, it is critical to
reset them zero, as we could otherwise leave unexpected EOI
interrupts pending for virtual level interrupts.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm64/kvm/hyp/vgic-v3-sr.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c
index fff7cd4..3129df9 100644
--- a/arch/arm64/kvm/hyp/vgic-v3-sr.c
+++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c
@@ -190,12 +190,11 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 			if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
 				continue;
 
-			if (cpu_if->vgic_elrsr & (1 << i)) {
+			if (cpu_if->vgic_elrsr & (1 << i))
 				cpu_if->vgic_lr[i] &= ~ICH_LR_STATE;
-				continue;
-			}
+			else
+				cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
 
-			cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
 			__gic_v3_set_lr(0, i);
 		}
 
-- 
2.1.4



From marc.zyngier at arm.com  Mon May 23 05:36:59 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 23 May 2016 13:36:59 +0100
Subject: [PATCH 3/7] KVM: arm/arm64: vgic-v2: Always resample level interrupts
In-Reply-To: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464007023-11736-4-git-send-email-marc.zyngier@arm.com>

When reading back from the list registers, we need to perform
two actions for level interrupts:
1) clear the soft-pending bit if the interrupt is not pending
   anymore *in the list register*
2) resample the line level and propagate it to the pending state

But these two actions linked, and we should *always* resample
the line level, no matter what state is in the list register.
Otherwise, we may end-up injecting spurious interrupts that
have been already retired.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/vgic/vgic-v2.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 8ad42c2..f659af0 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -112,10 +112,13 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
 			}
 		}
 
-		/* Clear soft pending state when level IRQs have been acked */
-		if (irq->config == VGIC_CONFIG_LEVEL &&
-		    !(val & GICH_LR_PENDING_BIT)) {
-			irq->soft_pending = false;
+		/*
+		 * Clear soft pending state when level irqs have been acked.
+		 * Always resample the line level.
+		 */
+		if (irq->config == VGIC_CONFIG_LEVEL) {
+			if (!(val & GICH_LR_PENDING_BIT))
+				irq->soft_pending = false;
 			irq->pending = irq->line_level;
 		}
 
-- 
2.1.4



From marc.zyngier at arm.com  Mon May 23 05:36:56 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 23 May 2016 13:36:56 +0100
Subject: [PATCH 0/7] vgic fixes for 4.7-rc1
Message-ID: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>

The dust has not yet settled on the new vgic, but here's the first
batch of fixes anyway!

The first two patches are courtesy of Christoffer, who noticed that we
fail to clear LRs that generate a maintenance interrupt, leading to
potential screaming interrupts. This bug already exists in the current
mainline.

The next two address a bug where we fail to properly resample the line
level on exit, which could result in spurious interrupts being
injected. This is specific to the new vgic.

The following two patches tighten our GICv3 emulation by preventing
the guest from changing the SRE setting. This bug already exists in
mainline.

The last patch is actually a performance optimization: if the guest is
using GICv3, we can drop a number of barriers (since we don't need to
change SRE, and there is no memory-mapped view to synchronize
with). This results in a world switch that is 2.5% faster on my LS2085
box when running GICv3 guests.

These patches have been tested on top of the kvmarm/next branch.

Thanks,

	M.

Christoffer Dall (2):
  KVM: arm/arm64: vgic-v2: Clear all dirty LRs
  KVM: arm/arm64: vgic-v3: Clear all dirty LRs

Marc Zyngier (5):
  KVM: arm/arm64: vgic-v2: Always resample level interrupts
  KVM: arm/arm64: vgic-v3: Always resample level interrupts
  arm64: KVM: Make ICC_SRE_EL1 access return the configured SRE value
  arm64: KVM: vgic-v3: Prevent the guest from messing with ICC_SRE_EL1
  arm64: KVM: vgic-v3: Relax synchronization when SRE==1

 arch/arm64/kvm/hyp/vgic-v3-sr.c | 36 +++++++++++++++++++++---------------
 arch/arm64/kvm/sys_regs.c       | 13 ++++++++++++-
 virt/kvm/arm/hyp/vgic-v2-sr.c   |  7 +++----
 virt/kvm/arm/vgic/vgic-v2.c     | 11 +++++++----
 virt/kvm/arm/vgic/vgic-v3.c     | 11 +++++++----
 5 files changed, 50 insertions(+), 28 deletions(-)

-- 
2.1.4



From marc.zyngier at arm.com  Mon May 23 05:36:57 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 23 May 2016 13:36:57 +0100
Subject: [PATCH 1/7] KVM: arm/arm64: vgic-v2: Clear all dirty LRs
In-Reply-To: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464007023-11736-2-git-send-email-marc.zyngier@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

When saving the state of the list registers, it is critical to
reset them zero, as we could otherwise leave unexpected EOI
interrupts pending for virtual level interrupts.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/hyp/vgic-v2-sr.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index a3f12b3..3a3a699 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -100,12 +100,11 @@ static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
 		if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
 			continue;
 
-		if (cpu_if->vgic_elrsr & (1UL << i)) {
+		if (cpu_if->vgic_elrsr & (1UL << i))
 			cpu_if->vgic_lr[i] &= ~GICH_LR_STATE;
-			continue;
-		}
+		else
+			cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
 
-		cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
 		writel_relaxed(0, base + GICH_LR0 + (i * 4));
 	}
 }
-- 
2.1.4



From marc.zyngier at arm.com  Mon May 23 05:37:00 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 23 May 2016 13:37:00 +0100
Subject: [PATCH 4/7] KVM: arm/arm64: vgic-v3: Always resample level interrupts
In-Reply-To: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464007023-11736-5-git-send-email-marc.zyngier@arm.com>

When reading back from the list registers, we need to perform
two actions for level interrupts:
1) clear the soft-pending bit if the interrupt is not pending
   anymore *in the list register*
2) resample the line level and propagate it to the pending state

But these two actions linked, and we should *always* resample
the line level, no matter what state is in the list register.
Otherwise, we may end-up injecting spurious interrupts that
have been already retired.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/vgic/vgic-v3.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 336a461..63b8bae 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -101,10 +101,13 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
 			}
 		}
 
-		/* Clear soft pending state when level irqs have been acked */
-		if (irq->config == VGIC_CONFIG_LEVEL &&
-		    !(val & ICH_LR_PENDING_BIT)) {
-			irq->soft_pending = false;
+		/*
+		 * Clear soft pending state when level irqs have been acked.
+		 * Always resample the line level.
+		 */
+		if (irq->config == VGIC_CONFIG_LEVEL) {
+			if (!(val & ICH_LR_PENDING_BIT))
+				irq->soft_pending = false;
 			irq->pending = irq->line_level;
 		}
 
-- 
2.1.4



From marc.zyngier at arm.com  Mon May 23 05:37:03 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 23 May 2016 13:37:03 +0100
Subject: [PATCH 7/7] arm64: KVM: vgic-v3: Relax synchronization when SRE==1
In-Reply-To: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464007023-11736-8-git-send-email-marc.zyngier@arm.com>

The GICv3 backend of the vgic is quite barrier heavy, in order
to ensure synchronization of the system registers and the
memory mapped view for a potential GICv2 guest.

But when the guest is using a GICv3 model, there is absolutely
no need to execute all these heavy barriers, and it is actually
beneficial to avoid them altogether.

This patch makes the synchonization conditional, and ensures
that we do not change the EL1 SRE settings if we do not need to.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm64/kvm/hyp/vgic-v3-sr.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c
index 40c3b4c..5f8f80b 100644
--- a/arch/arm64/kvm/hyp/vgic-v3-sr.c
+++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c
@@ -169,7 +169,8 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 	 * Make sure stores to the GIC via the memory mapped interface
 	 * are now visible to the system register interface.
 	 */
-	dsb(st);
+	if (!cpu_if->vgic_sre)
+		dsb(st);
 
 	cpu_if->vgic_vmcr  = read_gicreg(ICH_VMCR_EL2);
 
@@ -235,8 +236,12 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 
 	val = read_gicreg(ICC_SRE_EL2);
 	write_gicreg(val | ICC_SRE_EL2_ENABLE, ICC_SRE_EL2);
-	isb(); /* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
-	write_gicreg(1, ICC_SRE_EL1);
+
+	if (!cpu_if->vgic_sre) {
+		/* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
+		isb();
+		write_gicreg(1, ICC_SRE_EL1);
+	}
 }
 
 void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
@@ -255,8 +260,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 	 * been actually programmed with the value we want before
 	 * starting to mess with the rest of the GIC.
 	 */
-	write_gicreg(cpu_if->vgic_sre, ICC_SRE_EL1);
-	isb();
+	if (!cpu_if->vgic_sre) {
+		write_gicreg(0, ICC_SRE_EL1);
+		isb();
+	}
 
 	val = read_gicreg(ICH_VTR_EL2);
 	max_lr_idx = vtr_to_max_lr_idx(val);
@@ -305,8 +312,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 	 * (re)distributors. This ensure the guest will read the
 	 * correct values from the memory-mapped interface.
 	 */
-	isb();
-	dsb(sy);
+	if (!cpu_if->vgic_sre) {
+		isb();
+		dsb(sy);
+	}
 	vcpu->arch.vgic_cpu.live_lrs = live_lrs;
 
 	/*
-- 
2.1.4



From marc.zyngier at arm.com  Mon May 23 05:37:02 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 23 May 2016 13:37:02 +0100
Subject: [PATCH 6/7] arm64: KVM: vgic-v3: Prevent the guest from messing with
 ICC_SRE_EL1
In-Reply-To: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464007023-11736-7-git-send-email-marc.zyngier@arm.com>

Both our GIC emulations are "strict", in the sense that we either
emulate a GICv2 or a GICv3, and not a GICv3 with GICv2 legacy
support.

But when running on a GICv3 host, we still allow the guest to
tinker with the ICC_SRE_EL1 register during its time slice:
it can switch SRE off, observe that it is off, and yet on the
next world switch, find the SRE bit to be set again. Not very
nice.

An obvious solution is to always trap accesses to ICC_SRE_EL1
(by clearing ICC_SRE_EL2.Enable), and to let the handler return
the programmed value on a read, or ignore the write.

That way, the guest can always observe that our GICv3 is SRE==1
only.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm64/kvm/hyp/vgic-v3-sr.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c
index 3129df9..40c3b4c 100644
--- a/arch/arm64/kvm/hyp/vgic-v3-sr.c
+++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c
@@ -313,10 +313,8 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 	 * Prevent the guest from touching the GIC system registers if
 	 * SRE isn't enabled for GICv3 emulation.
 	 */
-	if (!cpu_if->vgic_sre) {
-		write_gicreg(read_gicreg(ICC_SRE_EL2) & ~ICC_SRE_EL2_ENABLE,
-			     ICC_SRE_EL2);
-	}
+	write_gicreg(read_gicreg(ICC_SRE_EL2) & ~ICC_SRE_EL2_ENABLE,
+		     ICC_SRE_EL2);
 }
 
 void __hyp_text __vgic_v3_init_lrs(void)
-- 
2.1.4



From marc.zyngier at arm.com  Mon May 23 05:37:01 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 23 May 2016 13:37:01 +0100
Subject: [PATCH 5/7] arm64: KVM: Make ICC_SRE_EL1 access return the configured
 SRE value
In-Reply-To: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464007023-11736-6-git-send-email-marc.zyngier@arm.com>

When we trap ICC_SRE_EL1, we handle it as RAZ/WI. It would be
more correct to actual make it RO, and return the configured
value when read.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm64/kvm/sys_regs.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 7bbe3ff..a57d650 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -134,6 +134,17 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
 	return true;
 }
 
+static bool access_gic_sre(struct kvm_vcpu *vcpu,
+			   struct sys_reg_params *p,
+			   const struct sys_reg_desc *r)
+{
+	if (p->is_write)
+		return ignore_write(vcpu, p);
+
+	p->regval = vcpu->arch.vgic_cpu.vgic_v3.vgic_sre;
+	return true;
+}
+
 static bool trap_raz_wi(struct kvm_vcpu *vcpu,
 			struct sys_reg_params *p,
 			const struct sys_reg_desc *r)
@@ -958,7 +969,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	  access_gic_sgi },
 	/* ICC_SRE_EL1 */
 	{ Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b101),
-	  trap_raz_wi },
+	  access_gic_sre },
 
 	/* CONTEXTIDR_EL1 */
 	{ Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b001),
-- 
2.1.4



From peterz at infradead.org  Mon May 23 05:44:02 2016
From: peterz at infradead.org (Peter Zijlstra)
Date: Mon, 23 May 2016 14:44:02 +0200
Subject: [PATCH] arm: Enable interrupts before calling schedule()
In-Reply-To: <alpine.DEB.2.11.1605201740320.3639@nanos>
References: <alpine.DEB.2.11.1605201740320.3639@nanos>
Message-ID: <20160523124402.GJ15728@worktop.ger.corp.intel.com>

On Fri, May 20, 2016 at 05:42:17PM +0200, Thomas Gleixner wrote:
> do_work_pending() calls schedule() with interrupts disabled, which is just
> wrong. Fix it.

Thomas; lockdep cannot currently catch this. It doesn't do IRQ state
validation other than ensuring the state matches with the hardware.

So things like:

	local_irq_disable();
	local_irq_disable();
	local_irq_save();
	local_irq_enable();

(and 'obviously' suspect sequence of IRQ events)

Are _fine_ by it. The only time it will yell is if flipping IRQ state
ends up marking an actual held lock with ENABLED_HARDIRQ while it
already had USED_IN_HARDIRQ.




From geert at linux-m68k.org  Mon May 23 05:52:20 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 23 May 2016 14:52:20 +0200
Subject: [PATCH v2 11/23] ARM: dts: armadillo800eva: Fix W=1 dtc warnings
In-Reply-To: <e0a1fbc1-ac95-2c79-65ed-d0328679bb8a@cogentembedded.com>
References: <1463728214-13838-1-git-send-email-geert+renesas@glider.be>
 <1463728214-13838-12-git-send-email-geert+renesas@glider.be>
 <e0a1fbc1-ac95-2c79-65ed-d0328679bb8a@cogentembedded.com>
Message-ID: <CAMuHMdXPhMToHhZggdKo=i65nS_mQT1o44YBd_Lz-B2Td3Jm9Q@mail.gmail.com>

On Fri, May 20, 2016 at 5:38 PM, Sergei Shtylyov
<sergei.shtylyov at cogentembedded.com> wrote:
> On 05/20/2016 10:10 AM, Geert Uytterhoeven wrote:
>> Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
>> Warning (unit_address_vs_reg): Node /regulator at 0 has a unit name, but no reg property
>> Warning (unit_address_vs_reg): Node /regulator at 1 has a unit name, but no reg property
>> Warning (unit_address_vs_reg): Node /regulator at 2 has a unit name, but no reg property
>> Warning (unit_address_vs_reg): Node /regulator at 3 has a unit name, but no reg property
>> Warning (unit_address_vs_reg): Node /i2c at 2 has a unit name, but no reg property
>>
>> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
>> ---
>> v2:
>>   - No changes.
>> ---
>>  arch/arm/boot/dts/r8a7740-armadillo800eva.dts | 12 ++++++------
>>  1 file changed, 6 insertions(+), 6 deletions(-)
>>
>> diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
>> b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
>> index 2c82dab2b6f45f9c..b3f0ac4b99bd5a3d 100644
>> --- a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
>> +++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
>
> [...]
>>
>> @@ -127,7 +127,7 @@
>>                 };
>>         };
>>
>> -       i2c2: i2c at 2 {
>> +       i2c2: i2c2 {
>
>    Not "i2c-2" as in the other patches?

Oops... Thanks for noticing!

Simon: Do you want me to repost the whole series once again, or
can you fix this up while applying?

Thanks!

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 boris.brezillon at free-electrons.com  Mon May 23 05:53:15 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Mon, 23 May 2016 14:53:15 +0200
Subject: [PATCH] misc: atmel-secumod: Driver for Atmel "security module".
In-Reply-To: <20160523140424.7ded3893@bbrezillon>
References: <1453348655-31182-1-git-send-email-davidm@egauge.net>
 <20160125110921.GA4027@piout.net>
 <CALnQHM13cGnoma_3erb0oCnRD0sYGGNF1E1cgzCJHrEXbvJpRQ@mail.gmail.com>
 <alpine.LNX.2.00.1601291055520.23683@nippy.intranet>
 <20160131113409.GI20165@piout.net>
 <20160523140424.7ded3893@bbrezillon>
Message-ID: <20160523145315.38eacf07@bbrezillon>

On Mon, 23 May 2016 14:04:24 +0200
Boris Brezillon <boris.brezillon at free-electrons.com> wrote:

> Hi David,
> 
> Sorry for the late review (I know you've posted new versions but I want
> to comment on this one).
> 
> On Sun, 31 Jan 2016 12:34:09 +0100
> Alexandre Belloni <alexandre.belloni at free-electrons.com> wrote:
> 
> > On 29/01/2016 at 11:13:05 +1100, Finn Thain wrote :  
> > > 
> > > On Mon, 25 Jan 2016, David Mosberger wrote:
> > >     
> > > > On Mon, Jan 25, 2016 at 4:09 AM, Alexandre Belloni 
> > > > <alexandre.belloni at free-electrons.com> wrote:
> > > >     
> > > > > I know this does more than that but I think those thre sections should 
> > > > > be registered using the nvmem framework. The sysfs file creation and 
> > > > > accesses then comes for free.    
> > > > 
> > > > I think Finn's patches would have to go in for that first, since the 
> > > > existing nvram code is a mess. Even with Finn's patches in, I think it 
> > > > could go either way.    
> > > 
> > > I think Alexandre is speaking of the nvmem subsystem (not nvram).
> > > Documentation/devicetree/bindings/nvmem
> > > Documentation/nvmem
> > > drivers/nvmem
> > >     
> > 
> > absolutely.
> >   
> > > > I'm not exactly sure how some of the features of the security module 
> > > > would be used: key management, auto erasing, there is a strange "backup 
> > > > mode" vs "normal mode" which is not well documented, etc.  So I think it 
> > > > may well end up being sufficiently different to warrant a separate 
> > > > driver.    
> > > 
> > > nvmem is not a subsystem I am familiar with, so it's not immediately clear 
> > > to me what your driver would look like if re-written that way.
> > > 
> > > Maybe it would become simpler. But if you did end up needing a separate 
> > > misc driver as well, maybe use of the nvmem framework would actually 
> > > increase complexity.
> > > 
> > > It would depend on your requirements. But I would focus on the actual 
> > > requirement rather than uncertain future possibilities.
> > >     
> > > >     
> > > > > Another idea is also to expose it using a genpool so it can be 
> > > > > accessed as sram from inside the kernel.    
> > > > 
> > > > That may be a fine idea, but as far as our application is concerned, we 
> > > > need user-level access to the battery-backed RAM.    
> > > 
> > > Right. I don't see how adding a memory allocator would help either.
> > >     
> > 
> > While the immediate need is to use that sram from userspace, I think
> > this is valuable to already think that at some point we will need to be
> > able to partition and access that sram from the kernel.
> > 
> > 
> >   
> 
> Well, I think we're reaching this point right now: I have to implement
> "freeze" mode (entering a deep sleep mode by cutting all power domains
> except VDDBU), and in order to do that I need to access BUREGs which
> are part of the secu-sram you're trying to expose here.
> 
> Two comments on the nvmem approach:
> 1/ first of all it's not really a non-volative memory: if you loose
> VDDBU you also loose the whole SRAM content.
> 2/ I need to be able to reserve the BUREG region (at least part of it)
> for in kernel usage (need to store the SDRAM address I should jump to
> when exiting freeze mode).

Forget this aspect. As Alexandre pointed out, the nvmem framework
provides an in-kernel API, so reserving space for the "freeze" mode
implementation is doable. But need to use the securam for advanced
stuff (like executing code from there) then the SRAM driver approach is
more future-proof IMO.


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


From eric.auger at linaro.org  Mon May 23 05:52:05 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 23 May 2016 14:52:05 +0200
Subject: [PATCH V5 1/6] vfio: platform: rename reset function
In-Reply-To: <1463364819-477-2-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
 <1463364819-477-2-git-send-email-okaya@codeaurora.org>
Message-ID: <5742FCF5.5060007@linaro.org>

Hi Sinan
On 05/16/2016 04:13 AM, Sinan Kaya wrote:
> Renaming the reset function to of_reset as it is only used
> by the device tree based platforms.
> 
> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
> ---
>  drivers/vfio/platform/vfio_platform_common.c  | 30 +++++++++++++--------------
>  drivers/vfio/platform/vfio_platform_private.h |  6 +++---
>  2 files changed, 18 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
> index e65b142..08fd7c2 100644
> --- a/drivers/vfio/platform/vfio_platform_common.c
> +++ b/drivers/vfio/platform/vfio_platform_common.c
> @@ -41,7 +41,7 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
>  		if (!strcmp(iter->compat, compat) &&
>  			try_module_get(iter->owner)) {
>  			*module = iter->owner;
> -			reset_fn = iter->reset;
> +			reset_fn = iter->of_reset;
>  			break;
>  		}
>  	}
> @@ -51,18 +51,18 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
>  
>  static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>  {
> -	vdev->reset = vfio_platform_lookup_reset(vdev->compat,
> -						&vdev->reset_module);
> -	if (!vdev->reset) {
> +	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
> +						    &vdev->reset_module);
> +	if (!vdev->of_reset) {
>  		request_module("vfio-reset:%s", vdev->compat);
> -		vdev->reset = vfio_platform_lookup_reset(vdev->compat,
> -							 &vdev->reset_module);
> +		vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
> +							&vdev->reset_module);
>  	}
>  }
>  
>  static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
>  {
> -	if (vdev->reset)
> +	if (vdev->of_reset)
>  		module_put(vdev->reset_module);
>  }
>  
> @@ -141,9 +141,9 @@ static void vfio_platform_release(void *device_data)
>  	mutex_lock(&driver_lock);
>  
>  	if (!(--vdev->refcnt)) {
> -		if (vdev->reset) {
> +		if (vdev->of_reset) {
>  			dev_info(vdev->device, "reset\n");
> -			vdev->reset(vdev);
> +			vdev->of_reset(vdev);
>  		} else {
>  			dev_warn(vdev->device, "no reset function found!\n");
>  		}
> @@ -175,9 +175,9 @@ static int vfio_platform_open(void *device_data)
>  		if (ret)
>  			goto err_irq;
>  
> -		if (vdev->reset) {
> +		if (vdev->of_reset) {
>  			dev_info(vdev->device, "reset\n");
> -			vdev->reset(vdev);
> +			vdev->of_reset(vdev);
>  		} else {
>  			dev_warn(vdev->device, "no reset function found!\n");
>  		}
> @@ -213,7 +213,7 @@ static long vfio_platform_ioctl(void *device_data,
>  		if (info.argsz < minsz)
>  			return -EINVAL;
>  
> -		if (vdev->reset)
> +		if (vdev->of_reset)
>  			vdev->flags |= VFIO_DEVICE_FLAGS_RESET;
>  		info.flags = vdev->flags;
>  		info.num_regions = vdev->num_regions;
> @@ -312,8 +312,8 @@ static long vfio_platform_ioctl(void *device_data,
>  		return ret;
>  
>  	} else if (cmd == VFIO_DEVICE_RESET) {
> -		if (vdev->reset)
> -			return vdev->reset(vdev);
> +		if (vdev->of_reset)
> +			return vdev->of_reset(vdev);
>  		else
>  			return -EINVAL;
>  	}
> @@ -611,7 +611,7 @@ void vfio_platform_unregister_reset(const char *compat,
>  
>  	mutex_lock(&driver_lock);
>  	list_for_each_entry_safe(iter, temp, &reset_list, link) {
> -		if (!strcmp(iter->compat, compat) && (iter->reset == fn)) {
> +		if (!strcmp(iter->compat, compat) && (iter->of_reset == fn)) {
>  			list_del(&iter->link);
>  			break;
>  		}
> diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
> index 42816dd..71ed7d1 100644
> --- a/drivers/vfio/platform/vfio_platform_private.h
> +++ b/drivers/vfio/platform/vfio_platform_private.h
> @@ -71,7 +71,7 @@ struct vfio_platform_device {
>  	struct resource*
>  		(*get_resource)(struct vfio_platform_device *vdev, int i);
>  	int	(*get_irq)(struct vfio_platform_device *vdev, int i);
> -	int	(*reset)(struct vfio_platform_device *vdev);
> +	int	(*of_reset)(struct vfio_platform_device *vdev);
>  };
>  
>  typedef int (*vfio_platform_reset_fn_t)(struct vfio_platform_device *vdev);
> @@ -80,7 +80,7 @@ struct vfio_platform_reset_node {
>  	struct list_head link;
>  	char *compat;
>  	struct module *owner;
> -	vfio_platform_reset_fn_t reset;
> +	vfio_platform_reset_fn_t of_reset;
>  };
>  
>  extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
> @@ -103,7 +103,7 @@ extern void vfio_platform_unregister_reset(const char *compat,
>  static struct vfio_platform_reset_node __reset ## _node = {	\
>  	.owner = THIS_MODULE,					\
>  	.compat = __compat,					\
> -	.reset = __reset,					\
> +	.of_reset = __reset,					\
>  };								\
>  __vfio_platform_register_reset(&__reset ## _node)
>  
> 

Reviewed-by: Eric Auger <eric.auger at linaro.org>

Best Regards

Eric



From eric.auger at linaro.org  Mon May 23 06:02:17 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 23 May 2016 15:02:17 +0200
Subject: [PATCH V5 2/6] vfio: platform: move reset call to a common
 function
In-Reply-To: <1463364819-477-3-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
 <1463364819-477-3-git-send-email-okaya@codeaurora.org>
Message-ID: <5742FF59.6090108@linaro.org>

Hi Sinan,
On 05/16/2016 04:13 AM, Sinan Kaya wrote:
> The reset call sequence seems to replicate itself multiple times
> across the file. Grouping them together for maintenance reasons.
> 
> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
> ---
>  drivers/vfio/platform/vfio_platform_common.c | 31 ++++++++++++++--------------
>  1 file changed, 15 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
> index 08fd7c2..cb91dd3 100644
> --- a/drivers/vfio/platform/vfio_platform_common.c
> +++ b/drivers/vfio/platform/vfio_platform_common.c
> @@ -134,6 +134,18 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
>  	kfree(vdev->regions);
>  }
>  
> +static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
> +{
> +	if (vdev->of_reset) {
> +		dev_info(vdev->device, "reset\n");
> +		vdev->of_reset(vdev);
> +		return 0;
you should return vdev->of_reset(vdev) to keep the existing
VFIO_DEVICE_RESET ioctl behavior

Once fixed, Reviewed-by: Eric Auger <eric.auger at linaro.org>

Besides, but this goes beyond the scope of your series, maybe we should
reconsider in the future what happens in case the reset fails on
open/release.

Best Regards

Eric
> +	}
> +
> +	dev_warn(vdev->device, "no reset function found!\n");
> +	return -EINVAL;
> +}
> +
>  static void vfio_platform_release(void *device_data)
>  {
>  	struct vfio_platform_device *vdev = device_data;
> @@ -141,12 +153,7 @@ static void vfio_platform_release(void *device_data)
>  	mutex_lock(&driver_lock);
>  
>  	if (!(--vdev->refcnt)) {
> -		if (vdev->of_reset) {
> -			dev_info(vdev->device, "reset\n");
> -			vdev->of_reset(vdev);
> -		} else {
> -			dev_warn(vdev->device, "no reset function found!\n");
> -		}
> +		vfio_platform_call_reset(vdev);
>  		vfio_platform_regions_cleanup(vdev);
>  		vfio_platform_irq_cleanup(vdev);
>  	}
> @@ -175,12 +182,7 @@ static int vfio_platform_open(void *device_data)
>  		if (ret)
>  			goto err_irq;
>  
> -		if (vdev->of_reset) {
> -			dev_info(vdev->device, "reset\n");
> -			vdev->of_reset(vdev);
> -		} else {
> -			dev_warn(vdev->device, "no reset function found!\n");
> -		}
> +		vfio_platform_call_reset(vdev);
>  	}
>  
>  	vdev->refcnt++;
> @@ -312,10 +314,7 @@ static long vfio_platform_ioctl(void *device_data,
>  		return ret;
>  
>  	} else if (cmd == VFIO_DEVICE_RESET) {
> -		if (vdev->of_reset)
> -			return vdev->of_reset(vdev);
> -		else
> -			return -EINVAL;
> +		return vfio_platform_call_reset(vdev);
>  	}
>  
>  	return -ENOTTY;
> 



From ykk at rock-chips.com  Mon May 23 06:10:56 2016
From: ykk at rock-chips.com (Yakir Yang)
Date: Mon, 23 May 2016 21:10:56 +0800
Subject: [PATCH 0/3] Add the eDP/VOP device node for rk3399
Message-ID: <1464009056-32158-1-git-send-email-ykk@rock-chips.com>

This thread is rely on Mark's VOP thread[1] and Yakir's eDP thread[2].

[1]: https://lkml.org/lkml/2016/4/20/36
[2]: https://patchwork.freedesktop.org/patch/83406/


Mark Yao (1):
  arm64: dts: rockchip: add VOP and VOP iommu node for rk3399

Yakir Yang (2):
  arm64: dts: rockchip: add eDP device node for rk3399
  arm64: dts: rockchip: add backlight support for rk3399 evb board

 arch/arm64/boot/dts/rockchip/rk3399-evb.dts |  40 ++++++++++
 arch/arm64/boot/dts/rockchip/rk3399.dtsi    | 110 ++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+)

-- 
1.9.1




From ykk at rock-chips.com  Mon May 23 06:11:10 2016
From: ykk at rock-chips.com (Yakir Yang)
Date: Mon, 23 May 2016 21:11:10 +0800
Subject: [PATCH 1/3] arm64: dts: rockchip: add VOP and VOP iommu node for
 rk3399
In-Reply-To: <1464009056-32158-1-git-send-email-ykk@rock-chips.com>
References: <1464009056-32158-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1464009070-32215-1-git-send-email-ykk@rock-chips.com>

From: Mark Yao <mark.yao at rock-chips.com>

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
Signed-off-by: Yakir Yang <ykk at rock-chips.com>

Signed-off-by: Yakir Yang <ykk at rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 58 ++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 46f325a..54e5c25 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -543,6 +543,64 @@
 		status = "disabled";
 	};
 
+	vopl: vop at ff8f0000 {
+		compatible = "rockchip,rk3399-vop-lit";
+		reg = <0x0 0xff8f0000 0x0 0x3efc>;
+		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>;
+		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
+		resets = <&cru SRST_A_VOP1>, <&cru SRST_H_VOP1>, <&cru SRST_D_VOP1>;
+		reset-names = "axi", "ahb", "dclk";
+		iommus = <&vopl_mmu>;
+		status = "disabled";
+
+		vopl_out: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	vopl_mmu: iommu at ff8f3f00 {
+		compatible = "rockchip,iommu";
+		reg = <0x0 0xff8f3f00 0x0 0x100>;
+		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vopl_mmu";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
+	vopb: vop at ff900000 {
+		compatible = "rockchip,rk3399-vop-big";
+		reg = <0x0 0xff900000 0x0 0x3efc>;
+		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>;
+		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
+		resets = <&cru SRST_A_VOP0>, <&cru SRST_H_VOP0>, <&cru SRST_D_VOP0>;
+		reset-names = "axi", "ahb", "dclk";
+		iommus = <&vopb_mmu>;
+		status = "disabled";
+
+		vopb_out: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	vopb_mmu: iommu at ff903f00 {
+		compatible = "rockchip,iommu";
+		reg = <0x0 0xff903f00 0x0 0x100>;
+		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vopb_mmu";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
+	display_subsystem: display-subsystem {
+		compatible = "rockchip,display-subsystem";
+		ports = <&vopl_out>, <&vopb_out>;
+		status = "disabled";
+	};
+
 	pinctrl: pinctrl {
 		compatible = "rockchip,rk3399-pinctrl";
 		rockchip,grf = <&grf>;
-- 
1.9.1




From ykk at rock-chips.com  Mon May 23 06:11:21 2016
From: ykk at rock-chips.com (Yakir Yang)
Date: Mon, 23 May 2016 21:11:21 +0800
Subject: [PATCH 2/3] arm64: dts: rockchip: add eDP device node for rk3399
In-Reply-To: <1464009056-32158-1-git-send-email-ykk@rock-chips.com>
References: <1464009056-32158-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1464009081-32268-1-git-send-email-ykk@rock-chips.com>

Signed-off-by: Yakir Yang <ykk at rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 52 ++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 54e5c25..be322db 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -557,6 +557,11 @@
 		vopl_out: port {
 			#address-cells = <1>;
 			#size-cells = <0>;
+
+			vopl_out_edp: endpoint at 0 {
+				reg = <0>;
+				remote-endpoint = <&edp_in_vopl>;
+			};
 		};
 	};
 
@@ -583,6 +588,11 @@
 		vopb_out: port {
 			#address-cells = <1>;
 			#size-cells = <0>;
+
+			vopb_out_edp: endpoint at 0 {
+				reg = <0>;
+				remote-endpoint = <&edp_in_vopb>;
+			};
 		};
 	};
 
@@ -595,6 +605,41 @@
 		status = "disabled";
 	};
 
+	edp: edp at ff970000 {
+		compatible = "rockchip,rk3399-edp";
+		reg = <0x0 0xff970000 0x0 0x8000>;
+		interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru PCLK_EDP>, <&cru PCLK_EDP_CTRL>;
+		clock-names = "dp", "pclk";
+		resets = <&cru SRST_P_EDP_CTRL>;
+		reset-names = "dp";
+		rockchip,grf = <&grf>;
+		status = "disabled";
+		pinctrl-names = "default";
+		pinctrl-0 = <&edp_hpd>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			edp_in: port at 0 {
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				edp_in_vopb: endpoint at 0 {
+					reg = <0>;
+					remote-endpoint = <&vopb_out_edp>;
+				};
+
+				edp_in_vopl: endpoint at 1 {
+					reg = <1>;
+					remote-endpoint = <&vopl_out_edp>;
+				};
+			};
+		};
+	};
+
 	display_subsystem: display-subsystem {
 		compatible = "rockchip,display-subsystem";
 		ports = <&vopl_out>, <&vopb_out>;
@@ -1067,5 +1112,12 @@
 					<1 14 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
+
+		edp {
+			edp_hpd: edp-hpd {
+				rockchip,pins =
+					<4 23 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
 	};
 };
-- 
1.9.1




From ykk at rock-chips.com  Mon May 23 06:11:30 2016
From: ykk at rock-chips.com (Yakir Yang)
Date: Mon, 23 May 2016 21:11:30 +0800
Subject: [PATCH 3/3] arm64: dts: rockchip: add backlight support for rk3399
 evb board
In-Reply-To: <1464009056-32158-1-git-send-email-ykk@rock-chips.com>
References: <1464009056-32158-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1464009090-32322-1-git-send-email-ykk@rock-chips.com>

Signed-off-by: Yakir Yang <ykk at rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 40 +++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
index 1a3eb14..31d9e27 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
@@ -75,6 +75,46 @@
 		regulator-always-on;
 		regulator-boot-on;
 	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm0 0 25000 0>;
+		brightness-levels = <
+			  0   1   2   3   4   5   6   7
+			  8   9  10  11  12  13  14  15
+			 16  17  18  19  20  21  22  23
+			 24  25  26  27  28  29  30  31
+			 32  33  34  35  36  37  38  39
+			 40  41  42  43  44  45  46  47
+			 48  49  50  51  52  53  54  55
+			 56  57  58  59  60  61  62  63
+			 64  65  66  67  68  69  70  71
+			 72  73  74  75  76  77  78  79
+			 80  81  82  83  84  85  86  87
+			 88  89  90  91  92  93  94  95
+			 96  97  98  99 100 101 102 103
+			104 105 106 107 108 109 110 111
+			112 113 114 115 116 117 118 119
+			120 121 122 123 124 125 126 127
+			128 129 130 131 132 133 134 135
+			136 137 138 139 140 141 142 143
+			144 145 146 147 148 149 150 151
+			152 153 154 155 156 157 158 159
+			160 161 162 163 164 165 166 167
+			168 169 170 171 172 173 174 175
+			176 177 178 179 180 181 182 183
+			184 185 186 187 188 189 190 191
+			192 193 194 195 196 197 198 199
+			200 201 202 203 204 205 206 207
+			208 209 210 211 212 213 214 215
+			216 217 218 219 220 221 222 223
+			224 225 226 227 228 229 230 231
+			232 233 234 235 236 237 238 239
+			240 241 242 243 244 245 246 247
+			248 249 250 251 252 253 254 255>;
+		default-brightness-level = <200>;
+		enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+	};
 };
 
 &pwm0 {
-- 
1.9.1




From eric.auger at linaro.org  Mon May 23 06:16:39 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 23 May 2016 15:16:39 +0200
Subject: [PATCH V5 3/6] vfio: platform: determine reset capability
In-Reply-To: <1463364819-477-4-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
 <1463364819-477-4-git-send-email-okaya@codeaurora.org>
Message-ID: <574302B7.7010605@linaro.org>

On 05/16/2016 04:13 AM, Sinan Kaya wrote:
> Creating a new function to determine if this driver supports reset
> function or not. This is an attempt to abstract device tree calls
> from the rest of the code.
> 
> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
> ---
>  drivers/vfio/platform/vfio_platform_common.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
> index cb91dd3..25378bd 100644
> --- a/drivers/vfio/platform/vfio_platform_common.c
> +++ b/drivers/vfio/platform/vfio_platform_common.c
> @@ -49,6 +49,11 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
>  	return reset_fn;
>  }
>  
> +static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
> +{
> +	return vdev->of_reset ? true : false;
> +}
> +
>  static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>  {
>  	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
> @@ -215,7 +220,7 @@ static long vfio_platform_ioctl(void *device_data,
>  		if (info.argsz < minsz)
>  			return -EINVAL;
>  
> -		if (vdev->of_reset)
> +		if (vfio_platform_has_reset(vdev))
>  			vdev->flags |= VFIO_DEVICE_FLAGS_RESET;
>  		info.flags = vdev->flags;
>  		info.num_regions = vdev->num_regions;
> 
Reviewed-by: Eric Auger <eric.auger at linaro.org>

Eric



From u.kleine-koenig at pengutronix.de  Mon May 23 06:18:08 2016
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Mon, 23 May 2016 15:18:08 +0200
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <5742E710.9@ti.com>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
 <1463648641-6931-2-git-send-email-vigneshr@ti.com>
 <20160522102606.GB23704@pengutronix.de> <5742E710.9@ti.com>
Message-ID: <20160523131808.GN23704@pengutronix.de>

Hello,

On Mon, May 23, 2016 at 04:48:40PM +0530, R, Vignesh wrote:
> On 5/22/2016 3:56 PM, Uwe Kleine-K?nig wrote:
> > Hello,
> > 
> > On Thu, May 19, 2016 at 02:34:00PM +0530, Vignesh R wrote:
> >> There are rotary-encoders where GPIO lines reflect the actual position
> >> of the rotary encoder dial. For example, if dial points to 9, then four
> >> GPIO lines connected to the rotary encoder will read HLLH(1001b = 9).
> >> Add support for such rotary-encoder.
> >> The driver relies on rotary-encoder,absolute-encoder DT property to
> >> detect such encoders.
> >> Since, GPIO IRQs are not necessary to work with
> >> such encoders, optional polling mode support is added using
> > 
> > I don't understand this. It's necessary in the same way as with the
> > already supported devices. I.e. you want to trigger an irq when the
> > encoder is moved and then check for it's position in the handler.
> > 
> 
> Unlike already supported device, there is no need to count steps or
> determine the direction of rotation. Hence, IRQ is not a requirement,
> periodically polling the gpio lines is more than sufficient. With
> absolute encoder, you are able to determine the current position at any
> time just by looking at the gpio inputs.

The timing might not be that critical, but there is no reason to operate
this device without irqs, is there?

> Suppose we poll device at t=0ms and see gpio values are LLLH(1), if we
> again poll device at t=500ms(which is what input_poll_dev helps to do)
> and see that gpio values is LLHH(3), then we know that rotary encoder
> has changed to 3. This can be done w/o IRQ for absolute encoders.
> 
> >> diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> >> index 6c9f0c8a846c..9c928dbd1500 100644
> >> --- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
> >> +++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
> >> @@ -12,6 +12,10 @@ Optional properties:
> >>  - rotary-encoder,relative-axis: register a relative axis rather than an
> >>    absolute one. Relative axis will only generate +1/-1 events on the input
> >>    device, hence no steps need to be passed.
> >> +- rotary-encoder,absolute-encoder: support encoders where GPIO lines
> >> +  reflect the actual position of the rotary encoder dial. For example,
> >> +  if dial points to 9, then four GPIO lines read HLLH(1001b = 9).
> >> +  In this case, rotary-encoder,steps-per-period needed not be defined.
> > 
> > IMHO this is wrong, I'd formalize this device as:
> > 
> > 	{
> > 		compatible = "rotary-encoder";
> > 		gpios = <&gpio 19 1>, <&gpio 20 0>, <...>, <...>;
> > 		rotary-encoder,encoding = "binary";
> > 		rotary-encoder,steps = <16>;
> > 		rotary-encoder,steps-per-period = <16>;
> 
> The above bindings essential means quarter_period device. I would not
> like to bother with all the logic in rotary_encoder_quarter_period_irq()
> when we can know encoder->pos by directly reading state of gpio lines.

OK, we have code that is more complex than it needs to be for your
device. But your device is a special case of the supported devices, so
I'd say don't bother that there is more logic in the driver than you
need and be lucky.

> > 		rotary-encoder,rollover;
> > 	}
> > 
> > and support this with a v4 of
> > 
> > 	http://thread.gmane.org/gmane.linux.kernel.input/48892
> > 
> >
> 
> IMHO, there needs to be separate IRQ handler for absolute encoders so
> that the driver logic is greatly simplified.

As above, the added complexity can handle your case just fine. So just
use it.

One thing I see to improve is to make use of the additional GPIOs, but
this is orthogonal to the different encoding and the question if polling
is enough here.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From heiko at sntech.de  Mon May 23 06:18:53 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Mon, 23 May 2016 15:18:53 +0200
Subject: [PATCH 1/3] arm64: dts: rockchip: add VOP and VOP iommu node for
 rk3399
In-Reply-To: <1464009070-32215-1-git-send-email-ykk@rock-chips.com>
References: <1464009056-32158-1-git-send-email-ykk@rock-chips.com>
 <1464009070-32215-1-git-send-email-ykk@rock-chips.com>
Message-ID: <2088899.KxOSoPueyv@phil>

Am Montag, 23. Mai 2016, 21:11:10 schrieb Yakir Yang:
> From: Mark Yao <mark.yao at rock-chips.com>

Please always at least provide some minimal patch description. Something 
like

--- 8< ---
Add the core display-subsystem node and the two display controllers
available on the rk3399
--- 8< ---

applies to the other two patches as well.

> Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
> Signed-off-by: Yakir Yang <ykk at rock-chips.com>
> 
> Signed-off-by: Yakir Yang <ykk at rock-chips.com>

one Signed-off-by from Yakir to much ;-)

Otherwise all 3 look good, but we need to of course wait for the code-parts 
to be in place.


Heiko

> ---
>  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 58
> ++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index 46f325a..54e5c25 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -543,6 +543,64 @@
>  		status = "disabled";
>  	};
> 
> +	vopl: vop at ff8f0000 {
> +		compatible = "rockchip,rk3399-vop-lit";
> +		reg = <0x0 0xff8f0000 0x0 0x3efc>;
> +		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>;
> +		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
> +		resets = <&cru SRST_A_VOP1>, <&cru SRST_H_VOP1>, <&cru SRST_D_VOP1>;
> +		reset-names = "axi", "ahb", "dclk";
> +		iommus = <&vopl_mmu>;
> +		status = "disabled";
> +
> +		vopl_out: port {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +	};
> +
> +	vopl_mmu: iommu at ff8f3f00 {
> +		compatible = "rockchip,iommu";
> +		reg = <0x0 0xff8f3f00 0x0 0x100>;
> +		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
> +		interrupt-names = "vopl_mmu";
> +		#iommu-cells = <0>;
> +		status = "disabled";
> +	};
> +
> +	vopb: vop at ff900000 {
> +		compatible = "rockchip,rk3399-vop-big";
> +		reg = <0x0 0xff900000 0x0 0x3efc>;
> +		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>;
> +		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
> +		resets = <&cru SRST_A_VOP0>, <&cru SRST_H_VOP0>, <&cru SRST_D_VOP0>;
> +		reset-names = "axi", "ahb", "dclk";
> +		iommus = <&vopb_mmu>;
> +		status = "disabled";
> +
> +		vopb_out: port {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +	};
> +
> +	vopb_mmu: iommu at ff903f00 {
> +		compatible = "rockchip,iommu";
> +		reg = <0x0 0xff903f00 0x0 0x100>;
> +		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
> +		interrupt-names = "vopb_mmu";
> +		#iommu-cells = <0>;
> +		status = "disabled";
> +	};
> +
> +	display_subsystem: display-subsystem {
> +		compatible = "rockchip,display-subsystem";
> +		ports = <&vopl_out>, <&vopb_out>;
> +		status = "disabled";
> +	};
> +
>  	pinctrl: pinctrl {
>  		compatible = "rockchip,rk3399-pinctrl";
>  		rockchip,grf = <&grf>;



From eric.auger at linaro.org  Mon May 23 06:18:19 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 23 May 2016 15:18:19 +0200
Subject: [PATCH V5 4/6] vfio: platform: add support for ACPI probe
In-Reply-To: <1463364819-477-5-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
 <1463364819-477-5-git-send-email-okaya@codeaurora.org>
Message-ID: <5743031B.5000208@linaro.org>

On 05/16/2016 04:13 AM, Sinan Kaya wrote:
> The code is using the compatible DT string to associate a reset driver
> with the actual device itself. The compatible string does not exist on
> ACPI based systems. HID is the unique identifier for a device driver
> instead.
> 
> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
> ---
>  drivers/vfio/platform/vfio_platform_common.c  | 58 ++++++++++++++++++++++++---
>  drivers/vfio/platform/vfio_platform_private.h |  1 +
>  2 files changed, 54 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
> index 25378bd..d859d3b 100644
> --- a/drivers/vfio/platform/vfio_platform_common.c
> +++ b/drivers/vfio/platform/vfio_platform_common.c
> @@ -13,6 +13,7 @@
>   */
>  
>  #include <linux/device.h>
> +#include <linux/acpi.h>
>  #include <linux/iommu.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
> @@ -49,6 +50,37 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
>  	return reset_fn;
>  }
>  
> +#ifdef CONFIG_ACPI
> +int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
> +			     struct device *dev)
should be static
> +{
> +	struct acpi_device *adev = ACPI_COMPANION(dev);
> +
> +	if (acpi_disabled)
> +		return -ENODEV;
> +
> +	if (!adev) {
> +		pr_err("VFIO: ACPI companion device not found for %s\n",
> +			vdev->name);
> +		return -ENODEV;
> +	}
> +
> +	vdev->acpihid = acpi_device_hid(adev);
> +	if (!vdev->acpihid) {
> +		pr_err("VFIO: cannot find ACPI HID for %s\n",
> +		       vdev->name);
> +		return -ENODEV;
> +	}
> +	return 0;
> +}
> +#else
> +int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
> +			     struct device *dev)
static inline?
> +{
> +	return -EINVAL;
nit: -ENOENT ?
> +}
> +#endif
> +
>  static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
>  {
>  	return vdev->of_reset ? true : false;
> @@ -548,6 +580,21 @@ static const struct vfio_device_ops vfio_platform_ops = {
>  	.mmap		= vfio_platform_mmap,
>  };
>  
> +int vfio_platform_of_probe(struct vfio_platform_device *vdev,
> +			   struct device *dev)
> +{
> +	int ret;
> +
> +	ret = device_property_read_string(dev, "compatible",
> +					  &vdev->compat);
> +	if (ret) {
> +		pr_err("VFIO: cannot retrieve compat for %s\n",
> +			vdev->name);
> +		return ret;
> +	}
> +	return 0;
nit: can be simplified by returning ret in any case.

Best Regards

Eric

> +}
> +
>  int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>  			       struct device *dev)
>  {
> @@ -557,11 +604,12 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>  	if (!vdev)
>  		return -EINVAL;
>  
> -	ret = device_property_read_string(dev, "compatible", &vdev->compat);
> -	if (ret) {
> -		pr_err("VFIO: cannot retrieve compat for %s\n", vdev->name);
> -		return -EINVAL;
> -	}
> +	ret = vfio_platform_acpi_probe(vdev, dev);
> +	if (ret)
> +		ret = vfio_platform_of_probe(vdev, dev);
> +
> +	if (ret)
> +		return ret;
>  
>  	vdev->device = dev;
>  
> diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
> index 71ed7d1..ba9e4f8 100644
> --- a/drivers/vfio/platform/vfio_platform_private.h
> +++ b/drivers/vfio/platform/vfio_platform_private.h
> @@ -58,6 +58,7 @@ struct vfio_platform_device {
>  	struct mutex			igate;
>  	struct module			*parent_module;
>  	const char			*compat;
> +	const char			*acpihid;
>  	struct module			*reset_module;
>  	struct device			*device;
>  
> 



From sf84 at laposte.net  Mon May 23 06:22:27 2016
From: sf84 at laposte.net (Sebastian Frias)
Date: Mon, 23 May 2016 15:22:27 +0200
Subject: [U-Boot] Sharing code between Linux and bootloader (U-boot) ?
In-Reply-To: <20160521014159.GK7650@bill-the-cat>
References: <573F1F07.6040202@laposte.net> <20160521014159.GK7650@bill-the-cat>
Message-ID: <57430413.2020704@laposte.net>

Hi Tom,

On 05/21/2016 03:41 AM, Tom Rini wrote:
> On Fri, May 20, 2016 at 04:28:23PM +0200, Sebastian Frias wrote:
> 
>> Hi,
>>
>> Some bootloaders (like U-boot) support several HW devices: serial,
>> network, NAND, USB, etc. most of which are also supported by Linux.
>>
>> So the question is: is code shared? I mean, I understand that the
>> drivers need to talk to the appropriate API, and such API could be
>> different between Linux and U-boot.
>> But putting that aside, would it be naive to imagine that some "core"
>> functionality could be shared? Or would that part be so small it is
>> not worth the effort?
>>
>> Since many companies use both, U-boot and Linux, I would figure they
>> try their best to optimize engineering resources and share code,
>> right?
>> In that case, I also wonder how do they share DT descriptions that
>> right now are being stored in the Linux kernel tree.
>>
>> We'd like to share code/DT for obvious reasons, what would you guys
>> suggest?
> 
> So, in all cases, Linux is always the primary.  

For drivers and DT?

>In some cases in U-Boot
> we port drivers over (NAND is a good example here). 

>From your message, I get that first you write the driver for Linux and then port to U-boot, is that right?
I would have thought that the opposite way could be easier, since the U-boot driver could be simpler (maybe no DMA) w.r.t the one in Linux.

> In other cases,
> things are similar enough that it's having done it in one place it's
> easy enough to do it again in the other.
> 

So, basically people just do it again, duplicating code?

Best regards,

Sebastian


From peppe.cavallaro at st.com  Mon May 23 06:17:41 2016
From: peppe.cavallaro at st.com (Giuseppe Cavallaro)
Date: Mon, 23 May 2016 15:17:41 +0200
Subject: [PATCH 0/2 (linux-stable-4.5.y)] net: stmmac: MDIO fixes
Message-ID: <1464009463-23654-1-git-send-email-peppe.cavallaro@st.com>

These patches port some recent fixes for linux-4.5.y stable branch.
They fix the MDIO settings trying to cover the all possible scenario
when the stmmac is connected to a real transceiver or a switch.

These patches are needed for Kernel 4.5 where Lime2, BananaPi and Cubieboard2
show problems when use the stmmac:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=823493

Additional Note:

 o The 4.4.y branch has a previous version of the stmmac;
   that is not including the development that introduced
   the regressions for MDIO bus.

 o The 4.5.y kernel has "March_2013" stmmac version plus the
   patch that introduce some MDIO configuration problems
   so the regressions.

 o The 4.6.y has all the fixes on top of the "Oct_2015"
   stmmac version.

Giuseppe CAVALLARO (1):
  Revert "stmmac: Fix 'eth0: No PHY found' regression"

Giuseppe Cavallaro (1):
  stmmac: fix MDIO settings

 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  | 11 +--
 drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c  | 10 +--
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  | 91 ++++++++++++++++------
 3 files changed, 70 insertions(+), 42 deletions(-)

-- 
2.7.4



From peppe.cavallaro at st.com  Mon May 23 06:17:42 2016
From: peppe.cavallaro at st.com (Giuseppe Cavallaro)
Date: Mon, 23 May 2016 15:17:42 +0200
Subject: [PATCH 1/2 (linux-stable-4.5.y)] Revert "stmmac: Fix 'eth0: No PHY
 found' regression"
In-Reply-To: <1464009463-23654-1-git-send-email-peppe.cavallaro@st.com>
References: <1464009463-23654-1-git-send-email-peppe.cavallaro@st.com>
Message-ID: <1464009463-23654-2-git-send-email-peppe.cavallaro@st.com>

From: Giuseppe CAVALLARO <peppe.cavallaro at st.com>

This reverts commit 88f8b1bb41c6208f81b6a480244533ded7b59493.
due to problems on GeekBox and Banana Pi M1 board when
connected to a real transceiver instead of a switch via
fixed-link.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro at st.com>
Cc: Gabriel Fernandez <gabriel.fernandez at linaro.org>
Cc: Andreas F?rber <afaerber at suse.de>
Cc: Frank Sch?fer <fschaefer.oss at googlemail.com>
Cc: Dinh Nguyen <dinh.linux at gmail.com>
Cc: David S. Miller <davem at davemloft.net>
Signed-off-by: David S. Miller <davem at davemloft.net>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c     | 11 ++++++++++-
 drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c |  9 +--------
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index efb54f3..0faf163 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -199,12 +199,21 @@ int stmmac_mdio_register(struct net_device *ndev)
 	struct stmmac_priv *priv = netdev_priv(ndev);
 	struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
 	int addr, found;
-	struct device_node *mdio_node = priv->plat->mdio_node;
+	struct device_node *mdio_node = NULL;
+	struct device_node *child_node = NULL;
 
 	if (!mdio_bus_data)
 		return 0;
 
 	if (IS_ENABLED(CONFIG_OF)) {
+		for_each_child_of_node(priv->device->of_node, child_node) {
+			if (of_device_is_compatible(child_node,
+						    "snps,dwmac-mdio")) {
+				mdio_node = child_node;
+				break;
+			}
+		}
+
 		if (mdio_node) {
 			netdev_dbg(ndev, "FOUND MDIO subnode\n");
 		} else {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 4514ba7..6a52fa1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -110,7 +110,6 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
 	struct device_node *np = pdev->dev.of_node;
 	struct plat_stmmacenet_data *plat;
 	struct stmmac_dma_cfg *dma_cfg;
-	struct device_node *child_node = NULL;
 
 	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
 	if (!plat)
@@ -141,19 +140,13 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
 		plat->phy_node = of_node_get(np);
 	}
 
-	for_each_child_of_node(np, child_node)
-		if (of_device_is_compatible(child_node,	"snps,dwmac-mdio")) {
-			plat->mdio_node = child_node;
-			break;
-		}
-
 	/* "snps,phy-addr" is not a standard property. Mark it as deprecated
 	 * and warn of its use. Remove this when phy node support is added.
 	 */
 	if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
 		dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
 
-	if ((plat->phy_node && !of_phy_is_fixed_link(np)) || !plat->mdio_node)
+	if ((plat->phy_node && !of_phy_is_fixed_link(np)) || plat->phy_bus_name)
 		plat->mdio_bus_data = NULL;
 	else
 		plat->mdio_bus_data =
-- 
2.7.4



From peppe.cavallaro at st.com  Mon May 23 06:17:43 2016
From: peppe.cavallaro at st.com (Giuseppe Cavallaro)
Date: Mon, 23 May 2016 15:17:43 +0200
Subject: [PATCH 2/2 (linux-stable-4.5.y)] stmmac: fix MDIO settings
In-Reply-To: <1464009463-23654-1-git-send-email-peppe.cavallaro@st.com>
References: <1464009463-23654-1-git-send-email-peppe.cavallaro@st.com>
Message-ID: <1464009463-23654-3-git-send-email-peppe.cavallaro@st.com>

Initially the phy_bus_name was added to manipulate the
driver name but it was recently just used to manage the
fixed-link and then to take some decision at run-time.
So the patch uses the is_pseudo_fixed_link and removes
the phy_bus_name variable not necessary anymore.

The driver can manage the mdio registration by using phy-handle,
dwmac-mdio and own parameter e.g. snps,phy-addr.
This patch takes care about all these possible configurations
and fixes the mdio registration in case of there is a real
transceiver or a switch (that needs to be managed by using
fixed-link).

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro at st.com>
Reviewed-by: Andreas F?rber <afaerber at suse.de>
Tested-by: Frank Sch?fer <fschaefer.oss at googlemail.com>
Cc: Gabriel Fernandez <gabriel.fernandez at linaro.org>
Cc: Dinh Nguyen <dinh.linux at gmail.com>
Cc: David S. Miller <davem at davemloft.net>
Cc: Phil Reid <preid at electromag.com.au>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  | 11 +--
 drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c  | 19 +----
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  | 84 +++++++++++++++++-----
 3 files changed, 70 insertions(+), 44 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c21015b..389d7d0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -271,7 +271,6 @@ static void stmmac_eee_ctrl_timer(unsigned long arg)
  */
 bool stmmac_eee_init(struct stmmac_priv *priv)
 {
-	char *phy_bus_name = priv->plat->phy_bus_name;
 	unsigned long flags;
 	bool ret = false;
 
@@ -283,7 +282,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
 		goto out;
 
 	/* Never init EEE in case of a switch is attached */
-	if (phy_bus_name && (!strcmp(phy_bus_name, "fixed")))
+	if (priv->phydev->is_pseudo_fixed_link)
 		goto out;
 
 	/* MAC core supports the EEE feature. */
@@ -820,12 +819,8 @@ static int stmmac_init_phy(struct net_device *dev)
 		phydev = of_phy_connect(dev, priv->plat->phy_node,
 					&stmmac_adjust_link, 0, interface);
 	} else {
-		if (priv->plat->phy_bus_name)
-			snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
-				 priv->plat->phy_bus_name, priv->plat->bus_id);
-		else
-			snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
-				 priv->plat->bus_id);
+		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
+			 priv->plat->bus_id);
 
 		snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
 			 priv->plat->phy_addr);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 0faf163..3f5512f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -198,29 +198,12 @@ int stmmac_mdio_register(struct net_device *ndev)
 	struct mii_bus *new_bus;
 	struct stmmac_priv *priv = netdev_priv(ndev);
 	struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
+	struct device_node *mdio_node = priv->plat->mdio_node;
 	int addr, found;
-	struct device_node *mdio_node = NULL;
-	struct device_node *child_node = NULL;
 
 	if (!mdio_bus_data)
 		return 0;
 
-	if (IS_ENABLED(CONFIG_OF)) {
-		for_each_child_of_node(priv->device->of_node, child_node) {
-			if (of_device_is_compatible(child_node,
-						    "snps,dwmac-mdio")) {
-				mdio_node = child_node;
-				break;
-			}
-		}
-
-		if (mdio_node) {
-			netdev_dbg(ndev, "FOUND MDIO subnode\n");
-		} else {
-			netdev_warn(ndev, "No MDIO subnode found\n");
-		}
-	}
-
 	new_bus = mdiobus_alloc();
 	if (new_bus == NULL)
 		return -ENOMEM;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 6a52fa1..190fb6d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -96,6 +96,69 @@ static int dwmac1000_validate_ucast_entries(int ucast_entries)
 }
 
 /**
+ * stmmac_dt_phy - parse device-tree driver parameters to allocate PHY resources
+ * @plat: driver data platform structure
+ * @np: device tree node
+ * @dev: device pointer
+ * Description:
+ * The mdio bus will be allocated in case of a phy transceiver is on board;
+ * it will be NULL if the fixed-link is configured.
+ * If there is the "snps,dwmac-mdio" sub-node the mdio will be allocated
+ * in any case (for DSA, mdio must be registered even if fixed-link).
+ * The table below sums the supported configurations:
+ *	-------------------------------
+ *	snps,phy-addr	|     Y
+ *	-------------------------------
+ *	phy-handle	|     Y
+ *	-------------------------------
+ *	fixed-link	|     N
+ *	-------------------------------
+ *	snps,dwmac-mdio	|
+ *	  even if	|     Y
+ *	fixed-link	|
+ *	-------------------------------
+ *
+ * It returns 0 in case of success otherwise -ENODEV.
+ */
+static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
+			 struct device_node *np, struct device *dev)
+{
+	bool mdio = true;
+
+	/* If phy-handle property is passed from DT, use it as the PHY */
+	plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
+	if (plat->phy_node)
+		dev_dbg(dev, "Found phy-handle subnode\n");
+
+	/* If phy-handle is not specified, check if we have a fixed-phy */
+	if (!plat->phy_node && of_phy_is_fixed_link(np)) {
+		if ((of_phy_register_fixed_link(np) < 0))
+			return -ENODEV;
+
+		dev_dbg(dev, "Found fixed-link subnode\n");
+		plat->phy_node = of_node_get(np);
+		mdio = false;
+	}
+
+	/* If snps,dwmac-mdio is passed from DT, always register the MDIO */
+	for_each_child_of_node(np, plat->mdio_node) {
+		if (of_device_is_compatible(plat->mdio_node, "snps,dwmac-mdio"))
+			break;
+	}
+
+	if (plat->mdio_node) {
+		dev_dbg(dev, "Found MDIO subnode\n");
+		mdio = true;
+	}
+
+	if (mdio)
+		plat->mdio_bus_data =
+			devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data),
+				     GFP_KERNEL);
+	return 0;
+}
+
+/**
  * stmmac_probe_config_dt - parse device-tree driver parameters
  * @pdev: platform_device structure
  * @plat: driver data platform structure
@@ -129,30 +192,15 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
 	/* Default to phy auto-detection */
 	plat->phy_addr = -1;
 
-	/* If we find a phy-handle property, use it as the PHY */
-	plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
-
-	/* If phy-handle is not specified, check if we have a fixed-phy */
-	if (!plat->phy_node && of_phy_is_fixed_link(np)) {
-		if ((of_phy_register_fixed_link(np) < 0))
-			return ERR_PTR(-ENODEV);
-
-		plat->phy_node = of_node_get(np);
-	}
-
 	/* "snps,phy-addr" is not a standard property. Mark it as deprecated
 	 * and warn of its use. Remove this when phy node support is added.
 	 */
 	if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
 		dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
 
-	if ((plat->phy_node && !of_phy_is_fixed_link(np)) || plat->phy_bus_name)
-		plat->mdio_bus_data = NULL;
-	else
-		plat->mdio_bus_data =
-			devm_kzalloc(&pdev->dev,
-				     sizeof(struct stmmac_mdio_bus_data),
-				     GFP_KERNEL);
+	/* To Configure PHY by using all device-tree supported properties */
+	if (stmmac_dt_phy(plat, np, &pdev->dev))
+		return ERR_PTR(-ENODEV);
 
 	of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
 
-- 
2.7.4



From ykk at rock-chips.com  Mon May 23 06:26:48 2016
From: ykk at rock-chips.com (Yakir Yang)
Date: Mon, 23 May 2016 21:26:48 +0800
Subject: [PATCH 1/3] arm64: dts: rockchip: add VOP and VOP iommu node for
 rk3399
In-Reply-To: <2088899.KxOSoPueyv@phil>
References: <1464009056-32158-1-git-send-email-ykk@rock-chips.com>
 <1464009070-32215-1-git-send-email-ykk@rock-chips.com>
 <2088899.KxOSoPueyv@phil>
Message-ID: <57430518.6090708@rock-chips.com>


On 05/23/2016 09:18 PM, Heiko Stuebner wrote:
> Am Montag, 23. Mai 2016, 21:11:10 schrieb Yakir Yang:
>> From: Mark Yao <mark.yao at rock-chips.com>
> Please always at least provide some minimal patch description. Something
> like
>
> --- 8< ---
> Add the core display-subsystem node and the two display controllers
> available on the rk3399
> --- 8< ---
>
> applies to the other two patches as well.
Okay  ;)
>> Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
>> Signed-off-by: Yakir Yang <ykk at rock-chips.com>
>>
>> Signed-off-by: Yakir Yang <ykk at rock-chips.com>
> one Signed-off-by from Yakir to much ;-)
Done
> Otherwise all 3 look good, but we need to of course wait for the code-parts
> to be in place.
Thanks,

- Yakir
>
> Heiko
>
>> ---
>>   arch/arm64/boot/dts/rockchip/rk3399.dtsi | 58
>> ++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
>> b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index 46f325a..54e5c25 100644
>> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
>> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
>> @@ -543,6 +543,64 @@
>>   		status = "disabled";
>>   	};
>>
>> +	vopl: vop at ff8f0000 {
>> +		compatible = "rockchip,rk3399-vop-lit";
>> +		reg = <0x0 0xff8f0000 0x0 0x3efc>;
>> +		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
>> +		clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>;
>> +		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
>> +		resets = <&cru SRST_A_VOP1>, <&cru SRST_H_VOP1>, <&cru SRST_D_VOP1>;
>> +		reset-names = "axi", "ahb", "dclk";
>> +		iommus = <&vopl_mmu>;
>> +		status = "disabled";
>> +
>> +		vopl_out: port {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +		};
>> +	};
>> +
>> +	vopl_mmu: iommu at ff8f3f00 {
>> +		compatible = "rockchip,iommu";
>> +		reg = <0x0 0xff8f3f00 0x0 0x100>;
>> +		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
>> +		interrupt-names = "vopl_mmu";
>> +		#iommu-cells = <0>;
>> +		status = "disabled";
>> +	};
>> +
>> +	vopb: vop at ff900000 {
>> +		compatible = "rockchip,rk3399-vop-big";
>> +		reg = <0x0 0xff900000 0x0 0x3efc>;
>> +		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
>> +		clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>;
>> +		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
>> +		resets = <&cru SRST_A_VOP0>, <&cru SRST_H_VOP0>, <&cru SRST_D_VOP0>;
>> +		reset-names = "axi", "ahb", "dclk";
>> +		iommus = <&vopb_mmu>;
>> +		status = "disabled";
>> +
>> +		vopb_out: port {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +		};
>> +	};
>> +
>> +	vopb_mmu: iommu at ff903f00 {
>> +		compatible = "rockchip,iommu";
>> +		reg = <0x0 0xff903f00 0x0 0x100>;
>> +		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
>> +		interrupt-names = "vopb_mmu";
>> +		#iommu-cells = <0>;
>> +		status = "disabled";
>> +	};
>> +
>> +	display_subsystem: display-subsystem {
>> +		compatible = "rockchip,display-subsystem";
>> +		ports = <&vopl_out>, <&vopb_out>;
>> +		status = "disabled";
>> +	};
>> +
>>   	pinctrl: pinctrl {
>>   		compatible = "rockchip,rk3399-pinctrl";
>>   		rockchip,grf = <&grf>;
>
>
>




From peppe.cavallaro at st.com  Mon May 23 06:28:04 2016
From: peppe.cavallaro at st.com (Giuseppe CAVALLARO)
Date: Mon, 23 May 2016 15:28:04 +0200
Subject: 4.5.0 on sun7i-a20-olinuxino-lime2: libphy: PHY stmmac-0:ffffffff
 not found (regression from rc7)
In-Reply-To: <20160522103056.2fa86293@arm.com>
References: <56E9413D.9010902@a20.net>	<56E945FF.6080005@arm.com>	<56E94CF4.2060607@arm.com>	<56E95B57.1090100@suse.de>	<56E9776F.3070102@a20.net>	<56E99B0C.2070609@arm.com>	<56E9F2B8.1030605@a20.net>	<20160317075202.16b14ed6@arm.com>	<CAHsu+b-t_r93XKLJTUcin6xjhOrFVn3_60vwHkbRt3iHK28CbA@mail.gmail.com>	<573EC33D.2010209@arm.com>	<573EC77A.2000800@st.com>	<CAHsu+b9BrqBLdCpsPpetc_4_EaFVGBdDHtoeeCqqzsCG3Wpsig@mail.gmail.com>	<573EE8B4.1050701@arm.com>	<574082F9.7010702@a20.net>
 <20160522103056.2fa86293@arm.com>
Message-ID: <57430564.9050305@st.com>

Hello

On 5/22/2016 11:30 AM, Marc Zyngier wrote:
> On Sat, 21 May 2016 17:47:05 +0200
> Bert Lindner <bert at a20.net> wrote:
>
>> Hi,
>>
>> On 2016-05-20 12:36, Marc Zyngier wrote:
>>> On 20/05/16 11:30, Andre Heider wrote:
>>>> Hi,
>>>>
>>>> On Fri, May 20, 2016 at 10:14 AM, Giuseppe CAVALLARO
>>>> <peppe.cavallaro at st.com> wrote:
>>>>> On 5/20/2016 9:56 AM, Marc Zyngier wrote:
>>>>>>
>>>>>> On 20/05/16 06:44, Andre Heider wrote:
>>>>>>>
>>>>>>> Giuseppe, Alexandre, et al.,
>>>>>>>
>>>>>>> On Thu, Mar 17, 2016 at 8:52 AM, Marc Zyngier <marc.zyngier at arm.com>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> On Thu, 17 Mar 2016 00:56:40 +0100
>>>>>>>> Bert Lindner <bert at a20.net> wrote:
>>>>>>>>>
>>>>>>>>> On 2016-03-16 18:42, Marc Zyngier wrote:
>>>>>>>>>>
>>>>>>>>>> On 16/03/16 15:10, Bert Lindner wrote:
>>>>>>>>>>>
>>>>>>>>>>> On 2016-03-16 14:10, Andreas F?rber wrote:
>>>>>>>>>>>>
>>>>>>>>>>>> Am 16.03.2016 um 13:09 schrieb Robin Murphy:
>>>>>>>>>>>>>
>>>>>>>>>>>>> On 16/03/16 11:39, Marc Zyngier wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> On 16/03/16 11:19, Bert Lindner wrote:
>>>>>>>
>>>>>>> ...
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> For the board sun7i-a20-olinuxino-lime2, there seems to be a
>>>>>>>>>>>>>>> problem
>>>>>>>>>>>>>>> with the eth0 PHY in mainline kernel 4.5.0 that developed since
>>>>>>>>>>>>>>> 4.5.0-rc7. Ethernet does not work, although eth0 is reported:
>>>>>>>
>>>>>>> ...
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> [    9.767125] NET: Registered protocol family 10
>>>>>>>>>>>>>>> [   10.357405] libphy: PHY stmmac-0:ffffffff not found
>>>>>>>>>>>>>>> [   10.362382] eth0: Could not attach to PHY
>>>>>>>>>>>>>>> [   10.366557] stmmac_open: Cannot attach to PHY (error: -19)
>>>>>>>
>>>>>>> ...
>>>>>>>>>>>>
>>>>>>>>>>>> v4 fixes for 4.5 are here:
>>>>>>>>>>>>
>>>>>>>>>>>> https://patchwork.ozlabs.org/patch/598195/ (revert)
>>>>>>>>>>>> https://patchwork.ozlabs.org/patch/598196/
>>>>>>>
>>>>>>> ...
>>>>>>>>>>
>>>>>>>>>> Good to know, thanks. Could you also give the potential fix a go (as
>>>>>>>>>> mentioned by Andreas)? Just to make sure that whatever gets merged
>>>>>>>>>> next
>>>>>>>>>> will actually fix the issue.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Yes sure, it took a while because I had to travel. Confirmed, the
>>>>>>>>> v4-for-4.5 fix works well for me, on sun7i-a20-olinuxino-lime2:
>>>>>>>>>
>>>>>>>>> root at lime2-079f:~# cat /proc/version
>>>>>>>>> Linux version 4.5.0-598195-598196-v4 (root at lime2-079f) (gcc version
>>>>>>>>> 4.9.1 (Ubuntu/Linaro 4.9.1-16ubuntu6) ) #1 SMP Wed Mar 16 16:44:22 UTC
>>>>>>>>> 2016
>>>>>>>>>
>>>>>>>>> dmesg:
>>>>>>>>> [    8.245273] NET: Registered protocol family 10
>>>>>>>>> [    9.297406]  RX IPC Checksum Offload disabled
>>>>>>>>> [    9.297460]  No MAC Management Counters available
>>>>>>>>> [    9.297951] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
>>>>>>>>> [   16.285658] sun7i-dwmac 1c50000.ethernet eth0: Link is Up -
>>>>>>>>> 1Gbps/Full - flow control rx/tx
>>>>>>>>> [   16.285798] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
>>>>>>>>>
>>>>>>>>> The board is connected to my laptop rather than to a switch, so that
>>>>>>>>> might be where the flow control message comes from (not sure). Anyway
>>>>>>>>> ethernet works.
>>>>>>>>
>>>>>>>>
>>>>>>>> Cool, many thanks for taking the time to test and report.
>>>>>>>>
>>>>>>>> Hopefully Giuseppe will get this merged quickly enough in mainline, and
>>>>>>>> it should then trickle into a 4.5-stable release (cc-ing stable on
>>>>>>>> these patches would probably be a good idea, BTW).
>>>>>>>
>>>>>>>
>>>>>>> stmmac is broken on at least Lime2, BananaPi and Cubieboard2 since
>>>>>>> v4.5 [0], including all five stable releases :(
>>>>>>
>>>>>>
>>>>>> All the A20 platforms are dead, actually.
>>>>>>
>>>>>>> The v4.5 patches quoted above are already +4 weeks old, could we
>>>>>>> please get them into stable?
>>>>>>
>>>>>>
>>>>>> For that, the maintainer would have needed to CC stable, which he
>>>>>> didn't. I'd expect someone who cares to send these patches to stable.
>>>>>> It'd be better if the maintainer would do it himself though.
>>>>>
>>>>>
>>>>> sure, I can send the patches to stable (sorry if I missed to add
>>>>> stable ML on CC).
>>>>>
>>>>> Andre, I have not clear if the train of patches actually fix the
>>>>> issue or if you need my support to fix something else. In that case
>>>>> I need some input for debugging (e.g. kernel log).
>>>>
>>>> Bert already confirmed that those two patches fixes stmmac on his
>>>> Lime2, so I assume that it fixes the issue for all A20 platforms.
>>>>
>>>>> let me know, is it enough to re-send the patches only?
>>>>
>>>> Just a resend with cc:stable :)
>>>
>>> Not quite. Please read Documentation/stable_kernel_rules.txt, and the
>>> section that concerns networking patches (and then consult
>>> Documentation/networking/netdev-FAQ.txt which has all the details).
>>
>> FWIW, recent 4.6-rc series and 4.6.0 have worked fine for me and the
>> lime2. Had not tried 4.5.x again.
>
> We've already established this. This is a 4.5-specific regression (both
> 4.4 and 4.6 are fine). One major issue is that Debian Stretch is
> currently shipping with 4.5, and upgrading to it results in a system
> without networking. Should this patch make it into stable, the fix would
> quickly percolate into distro kernels, and we could forget about it.

I have just ported and sent the patches to stable list.

   [PATCH 0/2 (linux-stable-4.5.y)] net: stmmac: MDIO fixes

Please, let me know if it is ok for you.

Peppe



> Thanks,
>
> 	M.
>



From ykk at rock-chips.com  Mon May 23 06:33:20 2016
From: ykk at rock-chips.com (Yakir Yang)
Date: Mon, 23 May 2016 21:33:20 +0800
Subject: [PATCH 0/3] Add the eDP/VOP device node for rk3399
Message-ID: <1464010400-10903-1-git-send-email-ykk@rock-chips.com>

This thread is rely on Mark's VOP thread[1] and Yakir's eDP thread[2].

[1]: https://lkml.org/lkml/2016/4/20/36
[2]: https://patchwork.freedesktop.org/patch/83406/


Mark Yao (1):
  arm64: dts: rockchip: add VOP and VOP iommu node for rk3399

Yakir Yang (2):
  arm64: dts: rockchip: add eDP device node for rk3399
  arm64: dts: rockchip: add backlight support for rk3399 evb board

 arch/arm64/boot/dts/rockchip/rk3399-evb.dts |  40 ++++++++++
 arch/arm64/boot/dts/rockchip/rk3399.dtsi    | 110 ++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+)

-- 
1.9.1




From ykk at rock-chips.com  Mon May 23 06:33:32 2016
From: ykk at rock-chips.com (Yakir Yang)
Date: Mon, 23 May 2016 21:33:32 +0800
Subject: [PATCH 1/3] arm64: dts: rockchip: add VOP and VOP iommu node for
 rk3399
In-Reply-To: <1464010400-10903-1-git-send-email-ykk@rock-chips.com>
References: <1464010400-10903-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1464010412-10961-1-git-send-email-ykk@rock-chips.com>

From: Mark Yao <mark.yao at rock-chips.com>

Add the core display-subsystem node and the two display controllers
available on the rk3399.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
Signed-off-by: Yakir Yang <ykk at rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 58 ++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 46f325a..54e5c25 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -543,6 +543,64 @@
 		status = "disabled";
 	};
 
+	vopl: vop at ff8f0000 {
+		compatible = "rockchip,rk3399-vop-lit";
+		reg = <0x0 0xff8f0000 0x0 0x3efc>;
+		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>;
+		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
+		resets = <&cru SRST_A_VOP1>, <&cru SRST_H_VOP1>, <&cru SRST_D_VOP1>;
+		reset-names = "axi", "ahb", "dclk";
+		iommus = <&vopl_mmu>;
+		status = "disabled";
+
+		vopl_out: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	vopl_mmu: iommu at ff8f3f00 {
+		compatible = "rockchip,iommu";
+		reg = <0x0 0xff8f3f00 0x0 0x100>;
+		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vopl_mmu";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
+	vopb: vop at ff900000 {
+		compatible = "rockchip,rk3399-vop-big";
+		reg = <0x0 0xff900000 0x0 0x3efc>;
+		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>;
+		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
+		resets = <&cru SRST_A_VOP0>, <&cru SRST_H_VOP0>, <&cru SRST_D_VOP0>;
+		reset-names = "axi", "ahb", "dclk";
+		iommus = <&vopb_mmu>;
+		status = "disabled";
+
+		vopb_out: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	vopb_mmu: iommu at ff903f00 {
+		compatible = "rockchip,iommu";
+		reg = <0x0 0xff903f00 0x0 0x100>;
+		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vopb_mmu";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
+	display_subsystem: display-subsystem {
+		compatible = "rockchip,display-subsystem";
+		ports = <&vopl_out>, <&vopb_out>;
+		status = "disabled";
+	};
+
 	pinctrl: pinctrl {
 		compatible = "rockchip,rk3399-pinctrl";
 		rockchip,grf = <&grf>;
-- 
1.9.1




From ykk at rock-chips.com  Mon May 23 06:33:38 2016
From: ykk at rock-chips.com (Yakir Yang)
Date: Mon, 23 May 2016 21:33:38 +0800
Subject: [PATCH 2/3] arm64: dts: rockchip: add eDP device node for rk3399
In-Reply-To: <1464010400-10903-1-git-send-email-ykk@rock-chips.com>
References: <1464010400-10903-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1464010418-11014-1-git-send-email-ykk@rock-chips.com>

Add rk3399 eDP device node, and connect to VOP device node with
remote endpoint.

Signed-off-by: Yakir Yang <ykk at rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 52 ++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 54e5c25..be322db 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -557,6 +557,11 @@
 		vopl_out: port {
 			#address-cells = <1>;
 			#size-cells = <0>;
+
+			vopl_out_edp: endpoint at 0 {
+				reg = <0>;
+				remote-endpoint = <&edp_in_vopl>;
+			};
 		};
 	};
 
@@ -583,6 +588,11 @@
 		vopb_out: port {
 			#address-cells = <1>;
 			#size-cells = <0>;
+
+			vopb_out_edp: endpoint at 0 {
+				reg = <0>;
+				remote-endpoint = <&edp_in_vopb>;
+			};
 		};
 	};
 
@@ -595,6 +605,41 @@
 		status = "disabled";
 	};
 
+	edp: edp at ff970000 {
+		compatible = "rockchip,rk3399-edp";
+		reg = <0x0 0xff970000 0x0 0x8000>;
+		interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru PCLK_EDP>, <&cru PCLK_EDP_CTRL>;
+		clock-names = "dp", "pclk";
+		resets = <&cru SRST_P_EDP_CTRL>;
+		reset-names = "dp";
+		rockchip,grf = <&grf>;
+		status = "disabled";
+		pinctrl-names = "default";
+		pinctrl-0 = <&edp_hpd>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			edp_in: port at 0 {
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				edp_in_vopb: endpoint at 0 {
+					reg = <0>;
+					remote-endpoint = <&vopb_out_edp>;
+				};
+
+				edp_in_vopl: endpoint at 1 {
+					reg = <1>;
+					remote-endpoint = <&vopl_out_edp>;
+				};
+			};
+		};
+	};
+
 	display_subsystem: display-subsystem {
 		compatible = "rockchip,display-subsystem";
 		ports = <&vopl_out>, <&vopb_out>;
@@ -1067,5 +1112,12 @@
 					<1 14 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
+
+		edp {
+			edp_hpd: edp-hpd {
+				rockchip,pins =
+					<4 23 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
 	};
 };
-- 
1.9.1




From ykk at rock-chips.com  Mon May 23 06:33:42 2016
From: ykk at rock-chips.com (Yakir Yang)
Date: Mon, 23 May 2016 21:33:42 +0800
Subject: [PATCH 3/3] arm64: dts: rockchip: add backlight support for rk3399
 evb board
In-Reply-To: <1464010400-10903-1-git-send-email-ykk@rock-chips.com>
References: <1464010400-10903-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1464010422-11067-1-git-send-email-ykk@rock-chips.com>

Add backlight node for evb board, perpare for panel device node.

Signed-off-by: Yakir Yang <ykk at rock-chips.com>
---
 arch/arm64/boot/dts/rockchip/rk3399-evb.dts | 40 +++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
index 1a3eb14..31d9e27 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
@@ -75,6 +75,46 @@
 		regulator-always-on;
 		regulator-boot-on;
 	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm0 0 25000 0>;
+		brightness-levels = <
+			  0   1   2   3   4   5   6   7
+			  8   9  10  11  12  13  14  15
+			 16  17  18  19  20  21  22  23
+			 24  25  26  27  28  29  30  31
+			 32  33  34  35  36  37  38  39
+			 40  41  42  43  44  45  46  47
+			 48  49  50  51  52  53  54  55
+			 56  57  58  59  60  61  62  63
+			 64  65  66  67  68  69  70  71
+			 72  73  74  75  76  77  78  79
+			 80  81  82  83  84  85  86  87
+			 88  89  90  91  92  93  94  95
+			 96  97  98  99 100 101 102 103
+			104 105 106 107 108 109 110 111
+			112 113 114 115 116 117 118 119
+			120 121 122 123 124 125 126 127
+			128 129 130 131 132 133 134 135
+			136 137 138 139 140 141 142 143
+			144 145 146 147 148 149 150 151
+			152 153 154 155 156 157 158 159
+			160 161 162 163 164 165 166 167
+			168 169 170 171 172 173 174 175
+			176 177 178 179 180 181 182 183
+			184 185 186 187 188 189 190 191
+			192 193 194 195 196 197 198 199
+			200 201 202 203 204 205 206 207
+			208 209 210 211 212 213 214 215
+			216 217 218 219 220 221 222 223
+			224 225 226 227 228 229 230 231
+			232 233 234 235 236 237 238 239
+			240 241 242 243 244 245 246 247
+			248 249 250 251 252 253 254 255>;
+		default-brightness-level = <200>;
+		enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+	};
 };
 
 &pwm0 {
-- 
1.9.1




From wens at csie.org  Mon May 23 06:45:16 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 23 May 2016 21:45:16 +0800
Subject: [PATCH 10/16] clk: sunxi-ng: Add M-P factor clock support
In-Reply-To: <1462737711-10017-11-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-11-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v67F3UvSCYDTxeLkCJL3FzmcpkogM4RAQgDseXMJDv7bUw@mail.gmail.com>

Hi,

On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Introduce support for the clocks that combine a linear divider and a
> power-of-two based one.

A description or formula in the source code (for those of us that forget)
would be nice. :)

>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile |   1 +
>  drivers/clk/sunxi-ng/ccu_mp.c | 158 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_mp.h |  79 +++++++++++++++++++++
>  3 files changed, 238 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_mp.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_mp.h
>
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 063c50f35ad4..09fce7467784 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -5,6 +5,7 @@ obj-y += ccu_div_table.o
>  obj-y += ccu_fixed_factor.o
>  obj-y += ccu_gate.o
>  obj-y += ccu_m.o
> +obj-y += ccu_mp.o
>  obj-y += ccu_mux.o
>  obj-y += ccu_p.o
>  obj-y += ccu_phase.o
> diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
> new file mode 100644
> index 000000000000..7181188deba7
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_mp.c
> @@ -0,0 +1,158 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_gate.h"
> +#include "ccu_mp.h"
> +
> +static void ccu_mp_find_best(unsigned long parent, unsigned long rate,
> +                            unsigned int max_m, unsigned int max_p,
> +                            unsigned int *m, unsigned int *p)
> +{
> +       unsigned long best_rate = 0;
> +       unsigned int best_m = 0, best_p = 0;
> +       unsigned int _m, _p;
> +
> +       for (_p = 0; _p <= max_p; _p++) {
> +               for (_m = 1; _m <= max_m; _m++) {
> +                       unsigned long tmp_rate = (parent >> _p) / _m;
> +
> +                       if (tmp_rate > rate)
> +                               continue;
> +
> +                       if ((rate - tmp_rate) < (rate - best_rate)) {
> +                               best_rate = tmp_rate;
> +                               best_m = _m;
> +                               best_p = _p;
> +                       }
> +               }
> +       }
> +
> +       *m = best_m;
> +       *p = best_p;
> +}
> +
> +static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
> +                                      unsigned long parent_rate,
> +                                      unsigned long rate,
> +                                      void *data)
> +{
> +       struct ccu_mp *cmp = data;
> +       unsigned int m, p;
> +
> +       ccu_mp_find_best(parent_rate, rate,
> +                        1 << cmp->m.width, (1 << cmp->p.width) - 1,
> +                        &m, &p);
> +
> +       return (parent_rate >> p) / m;
> +}
> +
> +static void ccu_mp_disable(struct clk_hw *hw)
> +{
> +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> +
> +       return ccu_gate_helper_disable(&cmp->common, cmp->enable);
> +}
> +
> +static int ccu_mp_enable(struct clk_hw *hw)
> +{
> +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> +
> +       return ccu_gate_helper_enable(&cmp->common, cmp->enable);
> +}
> +
> +static int ccu_mp_is_enabled(struct clk_hw *hw)
> +{
> +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> +
> +       return ccu_gate_helper_is_enabled(&cmp->common, cmp->enable);
> +}
> +
> +static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
> +                                       unsigned long parent_rate)
> +{
> +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> +       unsigned int m, p;
> +       u32 reg;
> +
> +       reg = readl(cmp->common.base + cmp->common.reg);
> +
> +       m = reg >> cmp->m.shift;
> +       m &= (1 << cmp->m.width) - 1;
> +
> +       p = reg >> cmp->p.shift;
> +       p &= (1 << cmp->p.width) - 1;
> +
> +       return (parent_rate >> p) / (m + 1);
> +}
> +
> +static int ccu_mp_determine_rate(struct clk_hw *hw,
> +                                struct clk_rate_request *req)
> +{
> +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> +
> +       return ccu_mux_helper_determine_rate(&cmp->common, &cmp->mux,
> +                                            req, ccu_mp_round_rate, cmp);
> +}
> +
> +static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
> +                          unsigned long parent_rate)
> +{
> +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> +       unsigned long flags;
> +       unsigned int m, p;
> +       u32 reg;
> +
> +       ccu_mp_find_best(parent_rate, rate,
> +                        1 << cmp->m.width, (1 << cmp->p.width) - 1,
> +                        &m, &p);
> +
> +
> +       spin_lock_irqsave(cmp->common.lock, flags);
> +
> +       reg = readl(cmp->common.base + cmp->common.reg);
> +       reg &= ~GENMASK(cmp->m.width + cmp->m.shift, cmp->m.shift);
> +       reg &= ~GENMASK(cmp->p.width + cmp->p.shift, cmp->p.shift);

width + shift - 1 ? IIRC GENMASK is inclusive at both ends.

> +
> +       writel(reg | (p << cmp->p.shift) | ((m - 1) << cmp->m.shift),
> +              cmp->common.base + cmp->common.reg);
> +
> +       spin_unlock_irqrestore(cmp->common.lock, flags);
> +
> +       return 0;
> +}
> +
> +static u8 ccu_mp_get_parent(struct clk_hw *hw)
> +{
> +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> +
> +       return ccu_mux_helper_get_parent(&cmp->common, &cmp->mux);
> +}
> +
> +static int ccu_mp_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> +
> +       return ccu_mux_helper_set_parent(&cmp->common, &cmp->mux, index);
> +}
> +
> +const struct clk_ops ccu_mp_ops = {
> +       .disable        = ccu_mp_disable,
> +       .enable         = ccu_mp_enable,
> +       .is_enabled     = ccu_mp_is_enabled,
> +
> +       .get_parent     = ccu_mp_get_parent,
> +       .set_parent     = ccu_mp_set_parent,
> +
> +       .determine_rate = ccu_mp_determine_rate,
> +       .recalc_rate    = ccu_mp_recalc_rate,
> +       .set_rate       = ccu_mp_set_rate,
> +};
> diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
> new file mode 100644
> index 000000000000..95da9c46cd4f
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_mp.h
> @@ -0,0 +1,79 @@
> +/*
> + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _CCU_MP_H_
> +#define _CCU_MP_H_
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_factor.h"
> +#include "ccu_mux.h"
> +
> +struct ccu_mp {
> +       u32                     enable;
> +
> +       struct ccu_factor       m;
> +       struct ccu_factor       p;
> +       struct ccu_mux_internal mux;
> +       struct ccu_common       common;
> +};
> +
> +#define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg,          \
> +                             _mshift, _mwidth,                         \
> +                             _pshift, _pwidth,                         \
> +                             _muxshift, _muxwidth,                     \
> +                             _flags)                                   \
> +       struct ccu_mp _struct = {                                       \
> +               .m      = SUNXI_CLK_FACTOR(_mshift, _mwidth),           \
> +               .p      = SUNXI_CLK_FACTOR(_pshift, _pwidth),           \
> +               .mux    = SUNXI_CLK_MUX(_muxshift, _muxwidth),          \
> +               .common = {                                             \
> +                       .reg            = _reg,                         \
> +                       .hw.init        = SUNXI_HW_INIT_PARENTS(_name,  \
> +                                                               _parents, \
> +                                                               &ccu_mp_ops, \
> +                                                               _flags), \
> +               }                                                       \
> +       }

Use the latter to simplify this one?

> +
> +#define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,     \

We could merge _struct with _name ...

> +                                  _mshift, _mwidth,                    \
> +                                  _pshift, _pwidth,                    \
> +                                  _muxshift, _muxwidth,                \
> +                                  _gate, _flags)                       \
> +       struct ccu_mp _struct = {                                       \

and have struct ccu_mp _name##_clk = {

> +               .enable = _gate,                                        \
> +               .m      = SUNXI_CLK_FACTOR(_mshift, _mwidth),           \
> +               .p      = SUNXI_CLK_FACTOR(_pshift, _pwidth),           \
> +               .mux    = SUNXI_CLK_MUX(_muxshift, _muxwidth),          \
> +               .common = {                                             \
> +                       .reg            = _reg,                         \
> +                       .features       = CCU_FEATURE_GATE,             \
> +                       .hw.init        = SUNXI_HW_INIT_PARENTS(_name,  \

and                                                               #_name, \

to try to squeeze the users each on a single line. It's a just minor
thing though.


Regards
ChenYu

> +                                                               _parents, \
> +                                                               &ccu_mp_ops, \
> +                                                               _flags), \
> +               }                                                       \
> +       }
> +
> +static inline struct ccu_mp *hw_to_ccu_mp(struct clk_hw *hw)
> +{
> +       struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +       return container_of(common, struct ccu_mp, common);
> +}
> +
> +extern const struct clk_ops ccu_mp_ops;
> +
> +#endif /* _CCU_MP_H_ */
> --
> 2.8.2
>


From linus.walleij at linaro.org  Mon May 23 06:49:16 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 23 May 2016 15:49:16 +0200
Subject: [PATCH v2 3/4] ARM64: Kconfig: Select the Amlogic Meson pin
 controller driver
In-Reply-To: <CAOQ7t2aLORBKiuZEp1BZ1+O-Yr5xvM9bjkFnfA9Yn9oZZefSnw@mail.gmail.com>
References: <1462176138-29433-1-git-send-email-carlo@caione.org>
 <1462176138-29433-4-git-send-email-carlo@caione.org>
 <CACRpkdbTr7YUrzSQQci929ugBhTkJKWvpjdf5Wo3HkfVKFhGLw@mail.gmail.com>
 <3200982.vJgYKNLqaA@wuerfel>
 <CAOQ7t2aLORBKiuZEp1BZ1+O-Yr5xvM9bjkFnfA9Yn9oZZefSnw@mail.gmail.com>
Message-ID: <CACRpkdY9jLeUzixZQ4_RoOJqpT7iHOHZi55K6htUeKQFjO2FgA@mail.gmail.com>

On Wed, May 11, 2016 at 8:41 PM, Carlo Caione <carlo at caione.org> wrote:
> On Wed, May 11, 2016 at 12:56 PM, Arnd Bergmann <arnd at arndb.de> wrote:
>> On Wednesday 11 May 2016 10:53:35 Linus Walleij wrote:
>>> On Mon, May 2, 2016 at 10:02 AM, Carlo Caione <carlo at caione.org> wrote:
>>>
>>> > From: Carlo Caione <carlo at endlessm.com>
>>> >
>>> > Select the Meson pin controller driver also for the AArch64 Meson
>>> > platform.
>>> >
>>> > Signed-off-by: Carlo Caione <carlo at endlessm.com>
>>>
>>> Acked-by: Linus Walleij <linus.walleij at linaro.org>
>>>
>>> I guess this should get merged through the ARM SoC tree.
>>>
>>
>> I'd keep it together with the other changes for clarity and
>> merge it through your tree.
>
> Linus,
> did you take it? otherwise I can merge it through my repo.

Nope didn't pick this one. I prefer to not take such patches
since they tend to generate collissions. Please take this
through ARM SoC.

Yours,
Linus Walleij


From wens at csie.org  Mon May 23 06:58:04 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 23 May 2016 21:58:04 +0800
Subject: [PATCH 11/16] clk: sunxi-ng: Add N-K-factor clock support
In-Reply-To: <1462737711-10017-12-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-12-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v65x8nxHzKG2MF8YLm6G1HHtTibxoqsNz_nzhqbzD8S-Gw@mail.gmail.com>

Hi,

On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Introduce support for clocks that use a combination of two linear
> multipliers.

Mostly the same comments as the previous patch.

> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile |   1 +
>  drivers/clk/sunxi-ng/ccu_nk.c | 147 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_nk.h |  44 +++++++++++++
>  3 files changed, 192 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_nk.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_nk.h
>
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 09fce7467784..e29ddae99653 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -7,5 +7,6 @@ obj-y += ccu_gate.o
>  obj-y += ccu_m.o
>  obj-y += ccu_mp.o
>  obj-y += ccu_mux.o
> +obj-y += ccu_nk.o
>  obj-y += ccu_p.o
>  obj-y += ccu_phase.o
> diff --git a/drivers/clk/sunxi-ng/ccu_nk.c b/drivers/clk/sunxi-ng/ccu_nk.c
> new file mode 100644
> index 000000000000..46eede3e986e
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_nk.c
> @@ -0,0 +1,147 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/rational.h>
> +
> +#include "ccu_gate.h"
> +#include "ccu_nk.h"

A formula to check against would be nice.

> +void ccu_nk_find_best(unsigned long parent, unsigned long rate,
> +                     unsigned int max_n, unsigned int max_k,
> +                     unsigned int *n, unsigned int *k)
> +{
> +       unsigned long best_rate = 0;
> +       unsigned int best_k = 0, best_n =0;
> +       unsigned int _k, _n;
> +
> +       for (_k = 0; _k <= max_k; _k++) {
> +               for (_n = 0; _n <= max_n; _n++) {

I don't think 0 is a valid multiplier, regardless whether the N value in
the register starts from 0 or 1.

> +                       unsigned long tmp_rate = parent * _n * _k;
> +
> +                       if (tmp_rate > rate)
> +                               continue;
> +
> +                       if ((rate - tmp_rate) < (rate - best_rate)) {
> +                               best_rate = tmp_rate;
> +                               best_k = _k;
> +                               best_n = _n;
> +                       }
> +               }
> +       }
> +
> +       *k = best_k;
> +       *n = best_n;
> +}
> +
> +static void ccu_nk_disable(struct clk_hw *hw)
> +{
> +       struct ccu_nk *nk = hw_to_ccu_nk(hw);
> +
> +       return ccu_gate_helper_disable(&nk->common, nk->enable);
> +}
> +
> +static int ccu_nk_enable(struct clk_hw *hw)
> +{
> +       struct ccu_nk *nk = hw_to_ccu_nk(hw);
> +
> +       return ccu_gate_helper_enable(&nk->common, nk->enable);
> +}
> +
> +static int ccu_nk_is_enabled(struct clk_hw *hw)
> +{
> +       struct ccu_nk *nk = hw_to_ccu_nk(hw);
> +
> +       return ccu_gate_helper_is_enabled(&nk->common, nk->enable);
> +}
> +
> +static unsigned long ccu_nk_recalc_rate(struct clk_hw *hw,
> +                                       unsigned long parent_rate)
> +{
> +       struct ccu_nk *nk = hw_to_ccu_nk(hw);
> +       unsigned long rate, n, k;
> +       u32 reg;
> +
> +       reg = readl(nk->common.base + nk->common.reg);
> +
> +       n = reg >> nk->n.shift;
> +       n &= (1 << nk->n.width) - 1;
> +
> +       k = reg >> nk->k.shift;
> +       k &= (1 << nk->k.width) - 1;
> +
> +       rate = parent_rate * (n + 1) * (k + 1);
> +
> +       if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
> +               rate = rate / nk->fixed_post_div;

I would go with "rate /= nk->fixed_post_div", but it's purely aesthetics.

> +
> +       return rate;
> +}
> +
> +static long ccu_nk_round_rate(struct clk_hw *hw, unsigned long rate,
> +                             unsigned long *parent_rate)
> +{
> +       struct ccu_nk *nk = hw_to_ccu_nk(hw);
> +       unsigned int n, k;
> +
> +       if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
> +               rate = rate * nk->fixed_post_div;
> +
> +       ccu_nk_find_best(*parent_rate, rate,
> +                        1 << nk->n.width, 1 << nk->k.width,
> +                        &n, &k);
> +
> +       rate = *parent_rate * n * k;
> +       if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
> +               rate = rate / nk->fixed_post_div;
> +
> +       return rate;
> +}
> +
> +static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate,
> +                          unsigned long parent_rate)
> +{
> +       struct ccu_nk *nk = hw_to_ccu_nk(hw);
> +       unsigned long flags;
> +       unsigned int n, k;
> +       u32 reg;
> +
> +       if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
> +               rate = rate * nk->fixed_post_div;
> +
> +       ccu_nk_find_best(parent_rate, rate,
> +                        1 << nk->n.width, 1 << nk->k.width,
> +                        &n, &k);
> +
> +       spin_lock_irqsave(nk->common.lock, flags);
> +
> +       reg = readl(nk->common.base + nk->common.reg);
> +       reg &= ~GENMASK(nk->n.width + nk->n.shift, nk->n.shift);
> +       reg &= ~GENMASK(nk->k.width + nk->k.shift, nk->k.shift);

width + shift - 1

> +
> +       writel(reg | ((k - 1) << nk->k.shift) | ((n - 1) << nk->n.shift),
> +              nk->common.base + nk->common.reg);
> +
> +       spin_unlock_irqrestore(nk->common.lock, flags);
> +
> +       ccu_helper_wait_for_lock(&nk->common, nk->lock);
> +
> +       return 0;
> +}
> +
> +const struct clk_ops ccu_nk_ops = {
> +       .disable        = ccu_nk_disable,
> +       .enable         = ccu_nk_enable,
> +       .is_enabled     = ccu_nk_is_enabled,
> +
> +       .recalc_rate    = ccu_nk_recalc_rate,
> +       .round_rate     = ccu_nk_round_rate,
> +       .set_rate       = ccu_nk_set_rate,
> +};
> diff --git a/drivers/clk/sunxi-ng/ccu_nk.h b/drivers/clk/sunxi-ng/ccu_nk.h
> new file mode 100644
> index 000000000000..cdbbd45815c6
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_nk.h
> @@ -0,0 +1,44 @@
> +/*
> + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _CCU_NK_H_
> +#define _CCU_NK_H_
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_factor.h"
> +
> +struct ccu_nk {
> +       u16                     reg;
> +       u32                     enable;
> +       u32                     lock;
> +
> +       struct ccu_factor       n;
> +       struct ccu_factor       k;
> +
> +       unsigned int            fixed_post_div;
> +
> +       struct ccu_common       common;
> +};
> +
> +static inline struct ccu_nk *hw_to_ccu_nk(struct clk_hw *hw)
> +{
> +       struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +       return container_of(common, struct ccu_nk, common);
> +}
> +
> +extern const struct clk_ops ccu_nk_ops;

No macros for this one?


Regards
ChenYu

> +
> +#endif /* _CCU_NK_H_ */
> --
> 2.8.2
>


From alexandre.belloni at free-electrons.com  Mon May 23 06:59:12 2016
From: alexandre.belloni at free-electrons.com (Alexandre Belloni)
Date: Mon, 23 May 2016 15:59:12 +0200
Subject: [PATCH] misc: atmel-secumod: Driver for Atmel "security module".
In-Reply-To: <20160523145315.38eacf07@bbrezillon>
References: <1453348655-31182-1-git-send-email-davidm@egauge.net>
 <20160125110921.GA4027@piout.net>
 <CALnQHM13cGnoma_3erb0oCnRD0sYGGNF1E1cgzCJHrEXbvJpRQ@mail.gmail.com>
 <alpine.LNX.2.00.1601291055520.23683@nippy.intranet>
 <20160131113409.GI20165@piout.net>
 <20160523140424.7ded3893@bbrezillon>
 <20160523145315.38eacf07@bbrezillon>
Message-ID: <20160523135912.GA2580@piout.net>

On 23/05/2016 at 14:53:15 +0200, Boris Brezillon wrote :
> > Well, I think we're reaching this point right now: I have to implement
> > "freeze" mode (entering a deep sleep mode by cutting all power domains
> > except VDDBU), and in order to do that I need to access BUREGs which
> > are part of the secu-sram you're trying to expose here.
> > 
> > Two comments on the nvmem approach:
> > 1/ first of all it's not really a non-volative memory: if you loose
> > VDDBU you also loose the whole SRAM content.
> > 2/ I need to be able to reserve the BUREG region (at least part of it)
> > for in kernel usage (need to store the SDRAM address I should jump to
> > when exiting freeze mode).
> 
> Forget this aspect. As Alexandre pointed out, the nvmem framework
> provides an in-kernel API, so reserving space for the "freeze" mode
> implementation is doable. But need to use the securam for advanced
> stuff (like executing code from there) then the SRAM driver approach is
> more future-proof IMO.
> 

Yeah, in case we want to use the SRAM to actually run some code, we will
need the sram driver.

-- 
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com


From damien.thebault at vitec.com  Mon May 23 07:07:49 2016
From: damien.thebault at vitec.com (=?utf-8?B?RGFtaWVuIFRow6liYXVsdA==?=)
Date: Mon, 23 May 2016 14:07:49 +0000
Subject: armada thermal issues with negative temperatures
Message-ID: <1464012466.1329.361.camel@vitec.com>

Hello,

I've been using an armada 370 SoC, and the thermal driver is reporting
erroneous values at negative temperatures.

After looking at what happened, in the armada_get_temp() function,
after applying shift and mask, we get the following values around 0?C:
- 315 (just above 0)
- 316 (just below 0)

If the code after /* Get formula coeficients */ is executed with those
two values, the first one gives the proper value of 216, but the second
one gives 310160 instead of the proper value of -506.

To have the proper final value, a signed division must be performed,
which will only be done if both operands are signed according to the C
standard, otherwise an unsigned division is done, which will provide
wrong results.

As the current coefficients are just fitting in unsigned long values,
the best fix I could find was to just cast each operand to (signed)
long.

With this fix, the temperature is the proper one, even for negative
values.

Best Regards
---
?drivers/thermal/armada_thermal.c | 4 ++--
?1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/thermal/armada_thermal.c
b/drivers/thermal/armada_thermal.c
index ae75328..ad8b88c 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -177,9 +177,9 @@ static int armada_get_temp(struct
thermal_zone_device *thermal,
?	div = priv->data->coef_div;
?
?	if (priv->data->inverted)
-		*temp = ((m * reg) - b) / div;
+		*temp = (long)((m * reg) - b) / (long)div;
?	else
-		*temp = (b - (m * reg)) / div;
+		*temp = (long)(b - (m * reg)) / (long)div;
?	return 0;
?}
?
--?
2.8.2

-- 
Damien Th?bault

From wens at csie.org  Mon May 23 07:10:16 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 23 May 2016 22:10:16 +0800
Subject: [PATCH 13/16] clk: sunxi-ng: Add N-K-M Factor clock
In-Reply-To: <1462737711-10017-14-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-14-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v679v3AW5OC129ShjxU9fUK7xQEZvUzLf2qQHFGiU2AhMQ@mail.gmail.com>

Hi,

On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Introduce support for clocks that multiply and divide using two linear
> multipliers and one linear divider.
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile  |   1 +
>  drivers/clk/sunxi-ng/ccu_nkm.c | 144 +++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_nkm.h |  42 ++++++++++++
>  3 files changed, 187 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_nkm.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_nkm.h
>
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index fba64c7f4fcd..2bb8bc22e907 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -8,6 +8,7 @@ obj-y += ccu_m.o
>  obj-y += ccu_mp.o
>  obj-y += ccu_mux.o
>  obj-y += ccu_nk.o
> +obj-y += ccu_nkm.o
>  obj-y += ccu_nm.o
>  obj-y += ccu_p.o
>  obj-y += ccu_phase.o
> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
> new file mode 100644
> index 000000000000..9019c7f6988c
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_nkm.c
> @@ -0,0 +1,144 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/rational.h>
> +
> +#include "ccu_gate.h"
> +#include "ccu_nkm.h"
> +
> +void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
> +                      unsigned long max_n, unsigned long max_k, unsigned long max_m,
> +                      unsigned long *n, unsigned long *k, unsigned long *m)

Would it be easier to just pass struct ccu_nkm* here?

> +{
> +       unsigned long best_rate = 0;
> +       unsigned long best_n = 0, best_k = 0, best_m = 0;
> +       unsigned long _n, _k, _m;
> +
> +       for (_k = 1; _k <= max_k; _k++) {
> +               unsigned long tmp_rate;
> +
> +               rational_best_approximation(rate / _k, parent,
> +                                           max_n, max_m, &_n, &_m);
> +
> +               tmp_rate = parent * _n * _k / _m;
> +
> +               if (tmp_rate > rate)
> +                       continue;
> +
> +               if ((rate - tmp_rate) < (rate - best_rate)) {
> +                       best_rate = tmp_rate;
> +                       best_n = _n;
> +                       best_k = _k;
> +                       best_m = _m;
> +               }
> +       }
> +
> +       *n = best_n;
> +       *k = best_k;
> +       *m = best_m;
> +}
> +
> +static void ccu_nkm_disable(struct clk_hw *hw)
> +{
> +       struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
> +
> +       return ccu_gate_helper_disable(&nkm->common, nkm->enable);
> +}
> +
> +static int ccu_nkm_enable(struct clk_hw *hw)
> +{
> +       struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
> +
> +       return ccu_gate_helper_enable(&nkm->common, nkm->enable);
> +}
> +
> +static int ccu_nkm_is_enabled(struct clk_hw *hw)
> +{
> +       struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
> +
> +       return ccu_gate_helper_is_enabled(&nkm->common, nkm->enable);
> +}
> +
> +static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw,
> +                                       unsigned long parent_rate)
> +{
> +       struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
> +       unsigned long n, m, k;
> +       u32 reg;
> +
> +       reg = readl(nkm->common.base + nkm->common.reg);
> +
> +       n = reg >> nkm->n.shift;
> +       n &= (1 << nkm->n.width) - 1;
> +
> +       k = reg >> nkm->k.shift;
> +       k &= (1 << nkm->k.width) - 1;
> +
> +       m = reg >> nkm->m.shift;
> +       m &= (1 << nkm->m.width) - 1;
> +
> +       return parent_rate * (n + 1) * (k + 1) / (m + 1);
> +}
> +
> +static long ccu_nkm_round_rate(struct clk_hw *hw, unsigned long rate,
> +                             unsigned long *parent_rate)
> +{
> +       struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
> +       unsigned long n, k, m;
> +
> +       ccu_nkm_find_best(*parent_rate, rate, 1 << nkm->n.width,
> +                         1 << nkm->k.width, 1 << nkm->m.width,
> +                         &n, &k, &m);
> +
> +       return *parent_rate * n * k / m;
> +}
> +
> +static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
> +                          unsigned long parent_rate)
> +{
> +       struct ccu_nkm *nkm = hw_to_ccu_nkm(hw);
> +       unsigned long n, k, m;
> +       unsigned long flags;
> +       u32 reg;
> +
> +       ccu_nkm_find_best(parent_rate, rate, 1 << nkm->n.width,
> +                         1 << nkm->k.width, 1 << nkm->m.width,
> +                         &n, &k, &m);
> +
> +       spin_lock_irqsave(nkm->common.lock, flags);
> +
> +       reg = readl(nkm->common.base + nkm->common.reg);
> +       reg &= ~GENMASK(nkm->n.width + nkm->n.shift, nkm->n.shift);
> +       reg &= ~GENMASK(nkm->k.width + nkm->k.shift, nkm->k.shift);
> +       reg &= ~GENMASK(nkm->m.width + nkm->m.shift, nkm->m.shift);

GENMASK(width + shift - 1, shift)

> +
> +       reg |= (n - 1) << nkm->m.shift;
> +       reg |= (k - 1) << nkm->m.shift;
> +       reg |= (m - 1) << nkm->m.shift;
> +
> +       writel(reg, nkm->common.base + nkm->common.reg);
> +
> +       spin_unlock_irqrestore(nkm->common.lock, flags);
> +
> +       ccu_helper_wait_for_lock(&nkm->common, nkm->lock);
> +
> +       return 0;
> +}
> +
> +const struct clk_ops ccu_nkm_ops = {
> +       .disable        = ccu_nkm_disable,
> +       .enable         = ccu_nkm_enable,
> +       .is_enabled     = ccu_nkm_is_enabled,
> +
> +       .recalc_rate    = ccu_nkm_recalc_rate,
> +       .round_rate     = ccu_nkm_round_rate,
> +       .set_rate       = ccu_nkm_set_rate,
> +};
> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
> new file mode 100644
> index 000000000000..1301e9f08305
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_nkm.h
> @@ -0,0 +1,42 @@
> +/*
> + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _CCU_NKM_H_
> +#define _CCU_NKM_H_
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_factor.h"
> +#include "ccu_common.h"
> +
> +struct ccu_nkm {
> +       u32                     enable;
> +       u32                     lock;
> +
> +       struct ccu_factor       n;
> +       struct ccu_factor       k;
> +       struct ccu_factor       m;
> +
> +       struct ccu_common       common;
> +};
> +
> +static inline struct ccu_nkm *hw_to_ccu_nkm(struct clk_hw *hw)
> +{
> +       struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +       return container_of(common, struct ccu_nkm, common);
> +}
> +
> +extern const struct clk_ops ccu_nkm_ops;

No macro? I like the macros as they give the actual driver a more table-like
look.

Regards
ChenYu

> +
> +#endif /* _CCU_NKM_H_ */
> --
> 2.8.2
>


From christoffer.dall at linaro.org  Mon May 23 07:19:37 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Mon, 23 May 2016 16:19:37 +0200
Subject: [PATCH 3/7] KVM: arm/arm64: vgic-v2: Always resample level
 interrupts
In-Reply-To: <1464007023-11736-4-git-send-email-marc.zyngier@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
 <1464007023-11736-4-git-send-email-marc.zyngier@arm.com>
Message-ID: <20160523141937.GA9625@lvm>

On Mon, May 23, 2016 at 01:36:59PM +0100, Marc Zyngier wrote:
> When reading back from the list registers, we need to perform
> two actions for level interrupts:
> 1) clear the soft-pending bit if the interrupt is not pending
>    anymore *in the list register*
> 2) resample the line level and propagate it to the pending state
> 
> But these two actions linked, and we should *always* resample

were linked?

> the line level, no matter what state is in the list register.
> Otherwise, we may end-up injecting spurious interrupts that
> have been already retired.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-v2.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
> index 8ad42c2..f659af0 100644
> --- a/virt/kvm/arm/vgic/vgic-v2.c
> +++ b/virt/kvm/arm/vgic/vgic-v2.c
> @@ -112,10 +112,13 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
>  			}
>  		}
>  
> -		/* Clear soft pending state when level IRQs have been acked */
> -		if (irq->config == VGIC_CONFIG_LEVEL &&
> -		    !(val & GICH_LR_PENDING_BIT)) {
> -			irq->soft_pending = false;
> +		/*
> +		 * Clear soft pending state when level irqs have been acked.
> +		 * Always resample the line level.
> +		 */
> +		if (irq->config == VGIC_CONFIG_LEVEL) {
> +			if (!(val & GICH_LR_PENDING_BIT))
> +				irq->soft_pending = false;
>  			irq->pending = irq->line_level;

shouldn't this context line then be:
	irq->pending = irq->line_level || irq->soft_pending;  ??

Thanks,
-Christoffer


From christoffer.dall at linaro.org  Mon May 23 07:19:56 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Mon, 23 May 2016 16:19:56 +0200
Subject: [PATCH 4/7] KVM: arm/arm64: vgic-v3: Always resample level
 interrupts
In-Reply-To: <1464007023-11736-5-git-send-email-marc.zyngier@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
 <1464007023-11736-5-git-send-email-marc.zyngier@arm.com>
Message-ID: <20160523141956.GB9625@lvm>

On Mon, May 23, 2016 at 01:37:00PM +0100, Marc Zyngier wrote:
> When reading back from the list registers, we need to perform
> two actions for level interrupts:
> 1) clear the soft-pending bit if the interrupt is not pending
>    anymore *in the list register*
> 2) resample the line level and propagate it to the pending state
> 
> But these two actions linked, and we should *always* resample
> the line level, no matter what state is in the list register.
> Otherwise, we may end-up injecting spurious interrupts that
> have been already retired.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-v3.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 336a461..63b8bae 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -101,10 +101,13 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
>  			}
>  		}
>  
> -		/* Clear soft pending state when level irqs have been acked */
> -		if (irq->config == VGIC_CONFIG_LEVEL &&
> -		    !(val & ICH_LR_PENDING_BIT)) {
> -			irq->soft_pending = false;
> +		/*
> +		 * Clear soft pending state when level irqs have been acked.
> +		 * Always resample the line level.
> +		 */
> +		if (irq->config == VGIC_CONFIG_LEVEL) {
> +			if (!(val & ICH_LR_PENDING_BIT))
> +				irq->soft_pending = false;
>  			irq->pending = irq->line_level;

same question as previous patch


From marc.zyngier at arm.com  Mon May 23 07:41:42 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Mon, 23 May 2016 15:41:42 +0100
Subject: [PATCH 3/7] KVM: arm/arm64: vgic-v2: Always resample level
 interrupts
In-Reply-To: <20160523141937.GA9625@lvm>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
 <1464007023-11736-4-git-send-email-marc.zyngier@arm.com>
 <20160523141937.GA9625@lvm>
Message-ID: <574316A6.8030305@arm.com>

On 23/05/16 15:19, Christoffer Dall wrote:
> On Mon, May 23, 2016 at 01:36:59PM +0100, Marc Zyngier wrote:
>> When reading back from the list registers, we need to perform
>> two actions for level interrupts:
>> 1) clear the soft-pending bit if the interrupt is not pending
>>    anymore *in the list register*
>> 2) resample the line level and propagate it to the pending state
>>
>> But these two actions linked, and we should *always* resample
> 
> were linked?

Indeed.

> 
>> the line level, no matter what state is in the list register.
>> Otherwise, we may end-up injecting spurious interrupts that
>> have been already retired.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> ---
>>  virt/kvm/arm/vgic/vgic-v2.c | 11 +++++++----
>>  1 file changed, 7 insertions(+), 4 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
>> index 8ad42c2..f659af0 100644
>> --- a/virt/kvm/arm/vgic/vgic-v2.c
>> +++ b/virt/kvm/arm/vgic/vgic-v2.c
>> @@ -112,10 +112,13 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
>>  			}
>>  		}
>>  
>> -		/* Clear soft pending state when level IRQs have been acked */
>> -		if (irq->config == VGIC_CONFIG_LEVEL &&
>> -		    !(val & GICH_LR_PENDING_BIT)) {
>> -			irq->soft_pending = false;
>> +		/*
>> +		 * Clear soft pending state when level irqs have been acked.
>> +		 * Always resample the line level.
>> +		 */
>> +		if (irq->config == VGIC_CONFIG_LEVEL) {
>> +			if (!(val & GICH_LR_PENDING_BIT))
>> +				irq->soft_pending = false;
>>  			irq->pending = irq->line_level;
> 
> shouldn't this context line then be:
> 	irq->pending = irq->line_level || irq->soft_pending;  ??

Yes, you're right. The only case we discard the soft-pending bit is when
we know for sure that the interrupt has transitioned from pending to active.

I'll update the two patches and repost once the rest of the series has
been reviewed.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From eric.auger at linaro.org  Mon May 23 07:41:52 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 23 May 2016 16:41:52 +0200
Subject: [PATCH V5 5/6] vfio: platform: call _RST method when using ACPI
In-Reply-To: <1463364819-477-6-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
 <1463364819-477-6-git-send-email-okaya@codeaurora.org>
Message-ID: <574316B0.5080306@linaro.org>

On 05/16/2016 04:13 AM, Sinan Kaya wrote:
> The device tree code checks for the presence of a reset driver and calls
> the of_reset function pointer by looking up the reset driver as a module.
> 
> ACPI defines _RST method to perform device level reset. After the _RST
> method is executed, the OS can resume using the device.
> 
> This patch checks the presence of _RST method and calls the _RST
> method when reset is requested.
> 
> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
> ---
>  drivers/vfio/platform/vfio_platform_common.c | 44 ++++++++++++++++++++++++++++
>  1 file changed, 44 insertions(+)
> 
> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
> index d859d3b..095d5b7 100644
> --- a/drivers/vfio/platform/vfio_platform_common.c
> +++ b/drivers/vfio/platform/vfio_platform_common.c
> @@ -73,21 +73,59 @@ int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
>  	}
>  	return 0;
>  }
> +
> +static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
> +{
> +	struct device *dev = vdev->device;
> +	acpi_handle handle = ACPI_HANDLE(dev);
> +	acpi_status acpi_ret;
> +	unsigned long long val;
> +
> +	acpi_ret = acpi_evaluate_integer(handle, "_RST", NULL, &val);
> +	if (ACPI_FAILURE(acpi_ret))
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
> +{
> +	struct device *dev = vdev->device;
> +	acpi_handle handle = ACPI_HANDLE(dev);
> +
> +	return acpi_has_method(handle, "_RST");
> +}
>  #else
>  int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
>  			     struct device *dev)
>  {
>  	return -EINVAL;
>  }
> +
> +static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
> +{
nit: inline
> +	return -EINVAL;
> +}
> +
> +static bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
nit: inline

Besides Reviewed-by: Eric Auger <eric.auger at linaro.org>

It is not explictly written in the ACPI spec that _RST is expected to
stop DMA transfers and IRQs although this may be implicit in the notion
of "function level reset ". May be worth adding this info in the commit msg?

Best Regards

Eric
> +{
> +	return false;
> +}
>  #endif
>  
>  static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
>  {
> +	if (vdev->acpihid)
> +		return vfio_platform_acpi_has_reset(vdev);
> +
>  	return vdev->of_reset ? true : false;
>  }
>  
>  static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>  {
> +	if (vdev->acpihid)
> +		return;
> +
>  	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
>  						    &vdev->reset_module);
>  	if (!vdev->of_reset) {
> @@ -99,6 +137,9 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>  
>  static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
>  {
> +	if (vdev->acpihid)
> +		return;
> +
>  	if (vdev->of_reset)
>  		module_put(vdev->reset_module);
>  }
> @@ -177,6 +218,9 @@ static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
>  		dev_info(vdev->device, "reset\n");
>  		vdev->of_reset(vdev);
>  		return 0;
> +	} else if (vdev->acpihid) {
> +		dev_info(vdev->device, "reset\n");
> +		return vfio_platform_acpi_call_reset(vdev);
>  	}
>  
>  	dev_warn(vdev->device, "no reset function found!\n");
> 



From zhengxing at rock-chips.com  Mon May 23 07:43:32 2016
From: zhengxing at rock-chips.com (Xing Zheng)
Date: Mon, 23 May 2016 22:43:32 +0800
Subject: [PATCH v2] ASoC: rockchip: Add machine driver for
 MAX98357A/RT5514/DA7219
Message-ID: <1464014612-14396-1-git-send-email-zhengxing@rock-chips.com>

There are multi codec devices on the RK3399 platform, we can use
this patch support and control these codecs.

---

Changes in v2:
Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>

 .../sound/rockchip-max98357a-rt5514-da7219.txt     |   15 +
 sound/soc/rockchip/Kconfig                         |   11 +
 sound/soc/rockchip/Makefile                        |    2 +
 .../rockchip/rockchip_max98357a_rt5514_da7219.c    |  333 ++++++++++++++++++++
 4 files changed, 361 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
 create mode 100644 sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c

diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt b/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
new file mode 100644
index 0000000..5928384
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
@@ -0,0 +1,15 @@
+ROCKCHIP with MAX98357A/RT5514/DA7219 codecs
+
+Required properties:
+- compatible: "rockchip,rockchip-sound"
+- rockchip,cpu: The phandle of the Rockchip I2S controller that's
+  connected to the codecs
+- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs
+
+Example:
+
+sound {
+	compatible = "rockchip,rockchip-sound";
+	rockchip,cpu = <&i2s0 &i2s0 &i2s1>;
+	rockchip,codec = <&max98357a &headsetcodec &codec>;
+};
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index f1e0c70..d02aa94 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -41,3 +41,14 @@ config SND_SOC_ROCKCHIP_RT5645
 	help
 	  Say Y or M here if you want to add support for SoC audio on Rockchip
 	  boards using the RT5645/RT5650 codec, such as Veyron.
+
+config SND_SOC_ROCKCHIP_MAX98357A_RT5514_DA7219
+	tristate "ASoC support for Rockchip boards using the MAX98357A/RT5514/DA7219"
+	depends on SND_SOC_ROCKCHIP && GPIOLIB
+	select SND_SOC_ROCKCHIP_I2S
+	select SND_SOC_MAX98357A
+	select SND_SOC_RT5514
+	select SND_SOC_DA7219
+	help
+	  Say Y or M here if you want to add support for SoC audio on Rockchip
+	  boards using the MAX98357A/RT5514/DA7219.
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
index c0bf560..ca97489 100644
--- a/sound/soc/rockchip/Makefile
+++ b/sound/soc/rockchip/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o
 
 snd-soc-rockchip-max98090-objs := rockchip_max98090.o
 snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o
+snd-soc-rockchip-max98357a-rt5514-da7219-objs := rockchip_max98357a_rt5514_da7219.o
 
 obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o
+obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98357A_RT5514_DA7219) += snd-soc-rockchip-max98357a-rt5514-da7219.o
diff --git a/sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c b/sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c
new file mode 100644
index 0000000..818c47e
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c
@@ -0,0 +1,333 @@
+/*
+ * Rockchip machine ASoC driver for boards using MAX98357A/RT5514/DA7219
+ *
+ * Copyright (c) 2016, ROCKCHIP CORPORATION.  All rights reserved.
+ *
+ * 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 <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include "rockchip_i2s.h"
+#include "../codecs/da7219.h"
+#include "../codecs/da7219-aad.h"
+#include "../codecs/rt5514.h"
+
+#define DRV_NAME "rockchip-sound"
+
+#define SOUND_FS	256
+
+static struct snd_soc_jack rockchip_sound_jack;
+
+static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphones", NULL),
+	SND_SOC_DAPM_SPK("Speakers", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Int Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route rockchip_dapm_routes[] = {
+	/* Input Lines */
+	{"MIC", NULL, "Headset Mic"},
+	{"DMIC1L", NULL, "Int Mic"},
+	{"DMIC1R", NULL, "Int Mic"},
+
+	/* Output Lines */
+	{"Headphones", NULL, "HPL"},
+	{"Headphones", NULL, "HPR"},
+	{"Speakers", NULL, "Speakers"},
+};
+
+static const struct snd_kcontrol_new rockchip_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphones"),
+	SOC_DAPM_PIN_SWITCH("Speakers"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Int Mic"),
+};
+
+static int rockchip_sound_max98357a_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_dapm_context *dapm = &rtd->card->dapm;
+	unsigned int mclk;
+	int ret;
+
+	/* max98357a supports these sample rates */
+	switch (params_rate(params)) {
+	case 8000:
+	case 16000:
+	case 48000:
+	case 96000:
+		mclk = params_rate(params) * SOUND_FS;
+		break;
+	default:
+		dev_err(rtd->card->dev, "%s() doesn't support this sample rate: %d\n",
+				__func__, params_rate(params));
+		return -EINVAL;
+	}
+
+	ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0);
+	if (ret) {
+		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
+				__func__, mclk, ret);
+		return ret;
+	}
+
+	snd_soc_dapm_disable_pin(dapm, "Headphones");
+	snd_soc_dapm_enable_pin(dapm, "Speakers");
+	snd_soc_dapm_sync(dapm);
+
+	return 0;
+}
+
+static int rockchip_sound_rt5514_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;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	unsigned int mclk;
+	int ret;
+
+	mclk = params_rate(params) * SOUND_FS;
+
+	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
+				     SND_SOC_CLOCK_OUT);
+	if (ret < 0) {
+		dev_err(rtd->card->dev, "Can't set cpu clock out %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK,
+				     mclk, SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
+				__func__, params_rate(params) * 512, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rockchip_sound_da7219_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;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dapm_context *dapm = &rtd->card->dapm;
+	int mclk, ret;
+
+	/* in bypass mode, the mclk has to be one of the frequencies below */
+	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(codec_dai->dev, "Can't set cpu clock out %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
+				     SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		dev_err(codec_dai->dev, "Can't set codec clock in %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
+	if (ret < 0) {
+		dev_err(codec_dai->dev, "Can't set pll sysclk mclk %d\n", ret);
+		return ret;
+	}
+
+	snd_soc_dapm_disable_pin(dapm, "Speakers");
+	snd_soc_dapm_enable_pin(dapm, "Headphones");
+	snd_soc_dapm_sync(dapm);
+
+	return 0;
+}
+
+static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec_dais[0]->codec;
+	int ret;
+
+	/* Enable Headset and 4 Buttons Jack detection */
+	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
+				    SND_JACK_HEADSET |
+				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
+				    &rockchip_sound_jack, NULL, 0);
+
+	if (ret) {
+		dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
+		return ret;
+	}
+
+	da7219_aad_jack_det(codec, &rockchip_sound_jack);
+
+	return 0;
+}
+
+static struct snd_soc_ops rockchip_sound_max98357a_ops = {
+	.hw_params = rockchip_sound_max98357a_hw_params,
+};
+
+static struct snd_soc_ops rockchip_sound_rt5514_ops = {
+	.hw_params = rockchip_sound_rt5514_hw_params,
+};
+
+static struct snd_soc_ops rockchip_sound_da7219_ops = {
+	.hw_params = rockchip_sound_da7219_hw_params,
+};
+
+enum {
+	DAILINK_MAX98357A,
+	DAILINK_RT5514,
+	DAILINK_DA7219,
+};
+
+static struct snd_soc_dai_link rockchip_dailinks[] = {
+	[DAILINK_MAX98357A] = {
+		.name = "MAX98357A",
+		.stream_name = "MAX98357A PCM",
+		.codec_dai_name = "HiFi",
+		.ops = &rockchip_sound_max98357a_ops,
+		/* set max98357a as slave */
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+	[DAILINK_RT5514] = {
+		.name = "RT5514",
+		.stream_name = "RT5514 PCM",
+		.codec_dai_name = "rt5514-aif1",
+		.ops = &rockchip_sound_rt5514_ops,
+		/* set rt5514 as slave */
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+	[DAILINK_DA7219] = {
+		.name = "DA7219",
+		.stream_name = "DA7219 PCM",
+		.codec_dai_name = "da7219-hifi",
+		.init = rockchip_sound_da7219_init,
+		.ops = &rockchip_sound_da7219_ops,
+		/* set da7219 as slave */
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+};
+
+static struct snd_soc_card rockchip_sound_card = {
+	.name = "rockchip-sound",
+	.owner = THIS_MODULE,
+	.dai_link = rockchip_dailinks,
+	.num_links =  ARRAY_SIZE(rockchip_dailinks),
+	.dapm_widgets = rockchip_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
+	.dapm_routes = rockchip_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes),
+	.controls = rockchip_controls,
+	.num_controls = ARRAY_SIZE(rockchip_controls),
+};
+
+static int rockchip_sound_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &rockchip_sound_card;
+	struct device_node *cpu_node;
+	int i, ret;
+
+	for (i = 0; i < card->num_links; i++) {
+		cpu_node = of_parse_phandle(pdev->dev.of_node,
+					 "rockchip,cpu", i);
+		if (!cpu_node) {
+			dev_err(&pdev->dev, "Property[%d] 'rockchip,cpu' missing or invalid\n", i);
+			return -EINVAL;
+		}
+
+		rockchip_dailinks[i].platform_of_node = cpu_node;
+		rockchip_dailinks[i].cpu_of_node = cpu_node;
+
+		rockchip_dailinks[i].codec_of_node =
+			of_parse_phandle(pdev->dev.of_node, "rockchip,codec", i);
+		if (!rockchip_dailinks[i].codec_of_node) {
+			dev_err(&pdev->dev,
+				"Property[%d] 'rockchip,codec' missing or invalid\n", i);
+			return -EINVAL;
+		}
+	}
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret)
+		dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
+			__func__, ret);
+
+	return ret;
+}
+
+static const struct of_device_id rockchip_sound_of_match[] = {
+	{ .compatible = "rockchip,rockchip-sound", },
+	{},
+};
+
+static struct platform_driver rockchip_sound_driver = {
+	.probe = rockchip_sound_probe,
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = rockchip_sound_of_match,
+#ifdef CONFIG_PM
+		.pm = &snd_soc_pm_ops,
+#endif
+	},
+};
+
+module_platform_driver(rockchip_sound_driver);
+
+MODULE_AUTHOR("Xing Zheng <zhengxing at rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);
-- 
1.7.9.5




From rdunlap at infradead.org  Mon May 23 07:50:13 2016
From: rdunlap at infradead.org (Randy Dunlap)
Date: Mon, 23 May 2016 07:50:13 -0700
Subject: [PATCH 0015/1529] Fix typo
In-Reply-To: <20160523090301.3cdbd523@ipc1.ka-ro>
References: <20160521113722.32053-1-andrea.gelmini@gelma.net>
 <20160523090301.3cdbd523@ipc1.ka-ro>
Message-ID: <574318A5.5000108@infradead.org>

On 05/23/16 00:03, Lothar Wa?mann wrote:
> Hi,
> 
> On Sat, 21 May 2016 13:37:22 +0200 Andrea Gelmini wrote:
>> Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
>> ---
>>  Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt b/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt
>> index 3e36c1d..616428a 100644
>> --- a/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt
>> +++ b/Documentation/devicetree/bindings/devfreq/event/exynos-ppmu.txt
>> @@ -8,7 +8,7 @@ use to analyze system performance, to make behaviors visible and to count
>>  usages of each IP (DMC, CPU, RIGHTBUS, LEFTBUS, CAM interface, LCD, G3D, MFC).
>>  The Exynos PPMU driver uses the devfreq-event class to provide event data
>>  to various devfreq devices. The devfreq devices would use the event data when
>> -derterming the current state of each IP.
>> +determing the current state of each IP.
>>  
> s/determing/determine/

determining


-- 
~Randy


From heiko at sntech.de  Mon May 23 07:51:08 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Mon, 23 May 2016 16:51:08 +0200
Subject: [PATCH v2] ASoC: rockchip: Add machine driver for
 MAX98357A/RT5514/DA7219
In-Reply-To: <1464014612-14396-1-git-send-email-zhengxing@rock-chips.com>
References: <1464014612-14396-1-git-send-email-zhengxing@rock-chips.com>
Message-ID: <6209835.s95gRr0Nsp@phil>

Hi Xing,

Am Montag, 23. Mai 2016, 22:43:32 schrieb Xing Zheng:
> There are multi codec devices on the RK3399 platform, we can use
> this patch support and control these codecs.
> 
> ---
> 
> Changes in v2:
> Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>

something seems to have gone wrong here.

The Signed-off needs to be above the "---" and the changelog itself seems 
empty while at least the number of lines in your 
rockchip_max98357a_rt5514_da7219.c seems to have changed.

> 
>  .../sound/rockchip-max98357a-rt5514-da7219.txt     |   15 +
>  sound/soc/rockchip/Kconfig                         |   11 +
>  sound/soc/rockchip/Makefile                        |    2 +
>  .../rockchip/rockchip_max98357a_rt5514_da7219.c    |  333
> ++++++++++++++++++++ 4 files changed, 361 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.
> txt create mode 100644
> sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c
> 
> diff --git
> a/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da721
> 9.txt
> b/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da721
> 9.txt new file mode 100644
> index 0000000..5928384
> --- /dev/null
> +++
> b/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da721
> 9.txt @@ -0,0 +1,15 @@
> +ROCKCHIP with MAX98357A/RT5514/DA7219 codecs
> +
> +Required properties:
> +- compatible: "rockchip,rockchip-sound"
> +- rockchip,cpu: The phandle of the Rockchip I2S controller that's
> +  connected to the codecs
> +- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs
> +
> +Example:
> +
> +sound {
> +	compatible = "rockchip,rockchip-sound";
> +	rockchip,cpu = <&i2s0 &i2s0 &i2s1>;
> +	rockchip,codec = <&max98357a &headsetcodec &codec>;
> +};
> diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
> index f1e0c70..d02aa94 100644
> --- a/sound/soc/rockchip/Kconfig
> +++ b/sound/soc/rockchip/Kconfig
> @@ -41,3 +41,14 @@ config SND_SOC_ROCKCHIP_RT5645
>  	help
>  	  Say Y or M here if you want to add support for SoC audio on Rockchip
>  	  boards using the RT5645/RT5650 codec, such as Veyron.
> +
> +config SND_SOC_ROCKCHIP_MAX98357A_RT5514_DA7219
> +	tristate "ASoC support for Rockchip boards using the
> MAX98357A/RT5514/DA7219" +	depends on SND_SOC_ROCKCHIP && GPIOLIB
> +	select SND_SOC_ROCKCHIP_I2S
> +	select SND_SOC_MAX98357A
> +	select SND_SOC_RT5514
> +	select SND_SOC_DA7219
> +	help
> +	  Say Y or M here if you want to add support for SoC audio on Rockchip
> +	  boards using the MAX98357A/RT5514/DA7219.
> diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
> index c0bf560..ca97489 100644
> --- a/sound/soc/rockchip/Makefile
> +++ b/sound/soc/rockchip/Makefile
> @@ -7,6 +7,8 @@ obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) +=
> snd-soc-rockchip-spdif.o
> 
>  snd-soc-rockchip-max98090-objs := rockchip_max98090.o
>  snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o
> +snd-soc-rockchip-max98357a-rt5514-da7219-objs :=
> rockchip_max98357a_rt5514_da7219.o
> 
>  obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o
>  obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o
> +obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98357A_RT5514_DA7219) +=
> snd-soc-rockchip-max98357a-rt5514-da7219.o diff --git
> a/sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c
> b/sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c new file mode
> 100644
> index 0000000..818c47e
> --- /dev/null
> +++ b/sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c
> @@ -0,0 +1,333 @@
> +/*
> + * Rockchip machine ASoC driver for boards using MAX98357A/RT5514/DA7219
> + *
> + * Copyright (c) 2016, ROCKCHIP CORPORATION.  All rights reserved.
> + *
> + * 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 <linux/slab.h>
> +#include <linux/gpio.h>
> +#include <linux/of_gpio.h>
> +#include <linux/delay.h>
> +#include <linux/spi/spi.h>
> +#include <sound/core.h>
> +#include <sound/jack.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc.h>
> +#include "rockchip_i2s.h"
> +#include "../codecs/da7219.h"
> +#include "../codecs/da7219-aad.h"
> +#include "../codecs/rt5514.h"
> +
> +#define DRV_NAME "rockchip-sound"
> +
> +#define SOUND_FS	256
> +
> +static struct snd_soc_jack rockchip_sound_jack;
> +
> +static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
> +	SND_SOC_DAPM_HP("Headphones", NULL),
> +	SND_SOC_DAPM_SPK("Speakers", NULL),
> +	SND_SOC_DAPM_MIC("Headset Mic", NULL),
> +	SND_SOC_DAPM_MIC("Int Mic", NULL),
> +};
> +
> +static const struct snd_soc_dapm_route rockchip_dapm_routes[] = {
> +	/* Input Lines */
> +	{"MIC", NULL, "Headset Mic"},
> +	{"DMIC1L", NULL, "Int Mic"},
> +	{"DMIC1R", NULL, "Int Mic"},
> +
> +	/* Output Lines */
> +	{"Headphones", NULL, "HPL"},
> +	{"Headphones", NULL, "HPR"},
> +	{"Speakers", NULL, "Speakers"},
> +};
> +
> +static const struct snd_kcontrol_new rockchip_controls[] = {
> +	SOC_DAPM_PIN_SWITCH("Headphones"),
> +	SOC_DAPM_PIN_SWITCH("Speakers"),
> +	SOC_DAPM_PIN_SWITCH("Headset Mic"),
> +	SOC_DAPM_PIN_SWITCH("Int Mic"),
> +};
> +
> +static int rockchip_sound_max98357a_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_dapm_context *dapm = &rtd->card->dapm;
> +	unsigned int mclk;
> +	int ret;
> +
> +	/* max98357a supports these sample rates */
> +	switch (params_rate(params)) {
> +	case 8000:
> +	case 16000:
> +	case 48000:
> +	case 96000:
> +		mclk = params_rate(params) * SOUND_FS;
> +		break;
> +	default:
> +		dev_err(rtd->card->dev, "%s() doesn't support this sample rate: 
%d\n",
> +				__func__, params_rate(params));
> +		return -EINVAL;
> +	}
> +
> +	ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0);
> +	if (ret) {
> +		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
> +				__func__, mclk, ret);
> +		return ret;
> +	}
> +
> +	snd_soc_dapm_disable_pin(dapm, "Headphones");
> +	snd_soc_dapm_enable_pin(dapm, "Speakers");
> +	snd_soc_dapm_sync(dapm);
> +
> +	return 0;
> +}
> +
> +static int rockchip_sound_rt5514_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;
> +	struct snd_soc_dai *codec_dai = rtd->codec_dai;
> +	unsigned int mclk;
> +	int ret;
> +
> +	mclk = params_rate(params) * SOUND_FS;
> +
> +	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
> +				     SND_SOC_CLOCK_OUT);
> +	if (ret < 0) {
> +		dev_err(rtd->card->dev, "Can't set cpu clock out %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK,
> +				     mclk, SND_SOC_CLOCK_IN);
> +	if (ret) {
> +		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
> +				__func__, params_rate(params) * 512, ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rockchip_sound_da7219_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;
> +	struct snd_soc_dai *codec_dai = rtd->codec_dai;
> +	struct snd_soc_dapm_context *dapm = &rtd->card->dapm;
> +	int mclk, ret;
> +
> +	/* in bypass mode, the mclk has to be one of the frequencies below */
> +	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(codec_dai->dev, "Can't set cpu clock out %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
> +				     SND_SOC_CLOCK_IN);
> +	if (ret < 0) {
> +		dev_err(codec_dai->dev, "Can't set codec clock in %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
> +	if (ret < 0) {
> +		dev_err(codec_dai->dev, "Can't set pll sysclk mclk %d\n", ret);
> +		return ret;
> +	}
> +
> +	snd_soc_dapm_disable_pin(dapm, "Speakers");
> +	snd_soc_dapm_enable_pin(dapm, "Headphones");
> +	snd_soc_dapm_sync(dapm);
> +
> +	return 0;
> +}
> +
> +static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
> +{
> +	struct snd_soc_codec *codec = rtd->codec_dais[0]->codec;
> +	int ret;
> +
> +	/* Enable Headset and 4 Buttons Jack detection */
> +	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
> +				    SND_JACK_HEADSET |
> +				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
> +				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
> +				    &rockchip_sound_jack, NULL, 0);
> +
> +	if (ret) {
> +		dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
> +		return ret;
> +	}
> +
> +	da7219_aad_jack_det(codec, &rockchip_sound_jack);
> +
> +	return 0;
> +}
> +
> +static struct snd_soc_ops rockchip_sound_max98357a_ops = {
> +	.hw_params = rockchip_sound_max98357a_hw_params,
> +};
> +
> +static struct snd_soc_ops rockchip_sound_rt5514_ops = {
> +	.hw_params = rockchip_sound_rt5514_hw_params,
> +};
> +
> +static struct snd_soc_ops rockchip_sound_da7219_ops = {
> +	.hw_params = rockchip_sound_da7219_hw_params,
> +};
> +
> +enum {
> +	DAILINK_MAX98357A,
> +	DAILINK_RT5514,
> +	DAILINK_DA7219,
> +};
> +
> +static struct snd_soc_dai_link rockchip_dailinks[] = {
> +	[DAILINK_MAX98357A] = {
> +		.name = "MAX98357A",
> +		.stream_name = "MAX98357A PCM",
> +		.codec_dai_name = "HiFi",
> +		.ops = &rockchip_sound_max98357a_ops,
> +		/* set max98357a as slave */
> +		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
> +			SND_SOC_DAIFMT_CBS_CFS,
> +	},
> +	[DAILINK_RT5514] = {
> +		.name = "RT5514",
> +		.stream_name = "RT5514 PCM",
> +		.codec_dai_name = "rt5514-aif1",
> +		.ops = &rockchip_sound_rt5514_ops,
> +		/* set rt5514 as slave */
> +		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
> +			SND_SOC_DAIFMT_CBS_CFS,
> +	},
> +	[DAILINK_DA7219] = {
> +		.name = "DA7219",
> +		.stream_name = "DA7219 PCM",
> +		.codec_dai_name = "da7219-hifi",
> +		.init = rockchip_sound_da7219_init,
> +		.ops = &rockchip_sound_da7219_ops,
> +		/* set da7219 as slave */
> +		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
> +			SND_SOC_DAIFMT_CBS_CFS,
> +	},
> +};
> +
> +static struct snd_soc_card rockchip_sound_card = {
> +	.name = "rockchip-sound",
> +	.owner = THIS_MODULE,
> +	.dai_link = rockchip_dailinks,
> +	.num_links =  ARRAY_SIZE(rockchip_dailinks),
> +	.dapm_widgets = rockchip_dapm_widgets,
> +	.num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
> +	.dapm_routes = rockchip_dapm_routes,
> +	.num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes),
> +	.controls = rockchip_controls,
> +	.num_controls = ARRAY_SIZE(rockchip_controls),
> +};
> +
> +static int rockchip_sound_probe(struct platform_device *pdev)
> +{
> +	struct snd_soc_card *card = &rockchip_sound_card;
> +	struct device_node *cpu_node;
> +	int i, ret;
> +
> +	for (i = 0; i < card->num_links; i++) {
> +		cpu_node = of_parse_phandle(pdev->dev.of_node,
> +					 "rockchip,cpu", i);
> +		if (!cpu_node) {
> +			dev_err(&pdev->dev, "Property[%d] 'rockchip,cpu' missing or
> invalid\n", i); +			return -EINVAL;
> +		}
> +
> +		rockchip_dailinks[i].platform_of_node = cpu_node;
> +		rockchip_dailinks[i].cpu_of_node = cpu_node;
> +
> +		rockchip_dailinks[i].codec_of_node =
> +			of_parse_phandle(pdev->dev.of_node, "rockchip,codec", i);
> +		if (!rockchip_dailinks[i].codec_of_node) {
> +			dev_err(&pdev->dev,
> +				"Property[%d] 'rockchip,codec' missing or invalid\n", i);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	card->dev = &pdev->dev;
> +	platform_set_drvdata(pdev, card);
> +
> +	ret = devm_snd_soc_register_card(&pdev->dev, card);
> +	if (ret)
> +		dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
> +			__func__, ret);
> +
> +	return ret;
> +}
> +
> +static const struct of_device_id rockchip_sound_of_match[] = {
> +	{ .compatible = "rockchip,rockchip-sound", },
> +	{},
> +};
> +
> +static struct platform_driver rockchip_sound_driver = {
> +	.probe = rockchip_sound_probe,
> +	.driver = {
> +		.name = DRV_NAME,
> +		.of_match_table = rockchip_sound_of_match,
> +#ifdef CONFIG_PM
> +		.pm = &snd_soc_pm_ops,
> +#endif
> +	},
> +};
> +
> +module_platform_driver(rockchip_sound_driver);
> +
> +MODULE_AUTHOR("Xing Zheng <zhengxing at rock-chips.com>");
> +MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:" DRV_NAME);
> +MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);



From heiko at sntech.de  Mon May 23 07:58:56 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Mon, 23 May 2016 16:58:56 +0200
Subject: [PATCH 0/3] Rockchip: generalize GRF setup
Message-ID: <1464015539-19521-1-git-send-email-heiko@sntech.de>

The General register files contain a big bunch of settings for various
components. Things like the automatic sdmmc/jtag switch may even affect
us in a bad way, while that property (and possibly others) are not even
part of the dw_mmc controller itself.

And while the rk3288 could still carry adaptions to these defaults
in its mach files, this is no longer possible on the arm64 socs, while
things like the jtag-switch from above still can affect us there.

So introduce a separate driver that binds to the already set soc-
specific grf compatibles and does the necessary setup for things.

It could also take over handling the grf pclk so that we don't have
to have the clock-framework keep control of it, as disabling causes
havok on the system.


Heiko Stuebner (3):
  dt-bindings: add used but undocumented rockchip grf compatible values
  soc: rockchip: add driver handling grf setup
  ARM: rockchip: drop jtag/mmc switch handling

 .../devicetree/bindings/soc/rockchip/grf.txt       |   4 +
 arch/arm/mach-rockchip/rockchip.c                  |  12 --
 drivers/soc/rockchip/Kconfig                       |  10 ++
 drivers/soc/rockchip/Makefile                      |   1 +
 drivers/soc/rockchip/grf.c                         | 138 +++++++++++++++++++++
 5 files changed, 153 insertions(+), 12 deletions(-)
 create mode 100644 drivers/soc/rockchip/grf.c

-- 
2.6.4



From heiko at sntech.de  Mon May 23 07:58:59 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Mon, 23 May 2016 16:58:59 +0200
Subject: [PATCH 3/3] ARM: rockchip: drop rk3288 jtag/mmc switch handling
In-Reply-To: <1464015539-19521-1-git-send-email-heiko@sntech.de>
References: <1464015539-19521-1-git-send-email-heiko@sntech.de>
Message-ID: <1464015539-19521-4-git-send-email-heiko@sntech.de>

We moved that functionality to a more generic place where it can also
be used for other socs, so drop it from architecture code.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 arch/arm/mach-rockchip/rockchip.c | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index beb71da..e7b2aa7 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -29,13 +29,11 @@
 #include "core.h"
 #include "pm.h"
 
-#define RK3288_GRF_SOC_CON0 0x244
 #define RK3288_TIMER6_7_PHYS 0xff810000
 
 static void __init rockchip_timer_init(void)
 {
 	if (of_machine_is_compatible("rockchip,rk3288")) {
-		struct regmap *grf;
 		void __iomem *reg_base;
 
 		/*
@@ -54,16 +52,6 @@ static void __init rockchip_timer_init(void)
 		} else {
 			pr_err("rockchip: could not map timer7 registers\n");
 		}
-
-		/*
-		 * Disable auto jtag/sdmmc switching that causes issues
-		 * with the mmc controllers making them unreliable
-		 */
-		grf = syscon_regmap_lookup_by_compatible("rockchip,rk3288-grf");
-		if (!IS_ERR(grf))
-			regmap_write(grf, RK3288_GRF_SOC_CON0, 0x10000000);
-		else
-			pr_err("rockchip: could not get grf syscon\n");
 	}
 
 	of_clk_init(NULL);
-- 
2.6.4



From heiko at sntech.de  Mon May 23 07:58:57 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Mon, 23 May 2016 16:58:57 +0200
Subject: [PATCH 1/3] dt-bindings: add used but undocumented rockchip grf
 compatible values
In-Reply-To: <1464015539-19521-1-git-send-email-heiko@sntech.de>
References: <1464015539-19521-1-git-send-email-heiko@sntech.de>
Message-ID: <1464015539-19521-2-git-send-email-heiko@sntech.de>

There are some more General Register Files used in devicetree files
already, but as of now undocumented in the binding document, fix that.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 Documentation/devicetree/bindings/soc/rockchip/grf.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.txt b/Documentation/devicetree/bindings/soc/rockchip/grf.txt
index 013e71a..c6e62cb 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/grf.txt
+++ b/Documentation/devicetree/bindings/soc/rockchip/grf.txt
@@ -5,11 +5,13 @@ is composed of many registers for system control.
 
 From RK3368 SoCs, the GRF is divided into two sections,
 - GRF, used for general non-secure system,
+- SGRF, used for general secure system,
 - PMUGRF, used for always on system
 
 Required Properties:
 
 - compatible: GRF should be one of the followings
+   - "rockchip,rk3036-grf", "syscon": for rk3036
    - "rockchip,rk3066-grf", "syscon": for rk3066
    - "rockchip,rk3188-grf", "syscon": for rk3188
    - "rockchip,rk3228-grf", "syscon": for rk3228
@@ -19,6 +21,8 @@ Required Properties:
 - compatible: PMUGRF should be one of the followings
    - "rockchip,rk3368-pmugrf", "syscon": for rk3368
    - "rockchip,rk3399-pmugrf", "syscon": for rk3399
+- compatible: SGRF should be one of the following
+   - "rockchip,rk3288-sgrf", "syscon": for rk3288
 - reg: physical base address of the controller and length of memory mapped
   region.
 
-- 
2.6.4



From heiko at sntech.de  Mon May 23 07:58:58 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Mon, 23 May 2016 16:58:58 +0200
Subject: [PATCH 2/3] soc: rockchip: add driver handling grf setup
In-Reply-To: <1464015539-19521-1-git-send-email-heiko@sntech.de>
References: <1464015539-19521-1-git-send-email-heiko@sntech.de>
Message-ID: <1464015539-19521-3-git-send-email-heiko@sntech.de>

The General Register Files are an area of registers containing a lot
of single-bit settings for numerous components as well full components
like usbphy control. Therefore all used components are accessed
via the syscon provided by the grf nodes or from the sub-devices
created through the simple-mfd created from the grf node.

Some settings are not used by anything but will need to be set up
according to expectations on the kernel side.

Best example is the force_jtag setting, which defaults to on and
results in the soc switching the pin-outputs between jtag and sdmmc
automatically depending on the card-detect status. This conflicts
heavily with how the dw_mmc driver expects to do its work and also
with the clock-controller, which has most likely deactivated the
jtag clock due to it being unused.

So far the handling of this setting was living in the mach-rockchip
code for the arm32-based rk3288 but that of course doesn't work
for arm64 socs and would also look ugly for further arm32 socs.

So introduce a top-level driver for the grf that handles these
settings that need to be a certain way but nobody cares about.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/soc/rockchip/Kconfig  |  10 +++
 drivers/soc/rockchip/Makefile |   1 +
 drivers/soc/rockchip/grf.c    | 138 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 149 insertions(+)
 create mode 100644 drivers/soc/rockchip/grf.c

diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
index 7140ff8..20da55d 100644
--- a/drivers/soc/rockchip/Kconfig
+++ b/drivers/soc/rockchip/Kconfig
@@ -3,6 +3,16 @@ if ARCH_ROCKCHIP || COMPILE_TEST
 #
 # Rockchip Soc drivers
 #
+
+config ROCKCHIP_GRF
+	bool
+	default y
+	help
+	  The General Register Files are a central component providing
+	  special additional settings registers for a lot of soc-components.
+	  In a lot of cases there also need to be default settings initialized
+	  to make some of them conform to expectations of the kernel.
+
 config ROCKCHIP_PM_DOMAINS
         bool "Rockchip generic power domain"
         depends on PM
diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
index 3d73d06..c851fa0 100644
--- a/drivers/soc/rockchip/Makefile
+++ b/drivers/soc/rockchip/Makefile
@@ -1,4 +1,5 @@
 #
 # Rockchip Soc drivers
 #
+obj-$(CONFIG_ROCKCHIP_GRF) += grf.o
 obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o
diff --git a/drivers/soc/rockchip/grf.c b/drivers/soc/rockchip/grf.c
new file mode 100644
index 0000000..25a1fd3
--- /dev/null
+++ b/drivers/soc/rockchip/grf.c
@@ -0,0 +1,138 @@
+/*
+ * Rockchip Generic Register Files setup
+ *
+ * Copyright (c) 2016 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define HIWORD_UPDATE(val, mask, shift) \
+		((val) << (shift) | (mask) << ((shift) + 16))
+
+struct rockchip_grf_value {
+	const char *desc;
+	u32 reg;
+	u32 val;
+};
+
+struct rockchip_grf_info {
+	const struct rockchip_grf_value *values;
+	int num_values;
+};
+
+#define RK3036_GRF_SOC_CON0		0x140
+
+static const struct rockchip_grf_value rk3036_defaults[] = {
+	/*
+	 * Disable auto jtag/sdmmc switching that causes issues with the
+	 * clock-framework and the mmc controllers making them unreliable.
+	 */
+	{ "jtag switching", RK3036_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 11) },
+};
+
+static const struct rockchip_grf_info rk3036_grf = {
+	.values = rk3036_defaults,
+	.num_values = ARRAY_SIZE(rk3036_defaults),
+};
+
+#define RK3288_GRF_SOC_CON0		0x244
+
+static const struct rockchip_grf_value rk3288_defaults[] = {
+	{ "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) },
+};
+
+static const struct rockchip_grf_info rk3288_grf = {
+	.values = rk3288_defaults,
+	.num_values = ARRAY_SIZE(rk3288_defaults),
+};
+
+#define RK3399_GRF_SOC_CON7		0xe21c
+
+static const struct rockchip_grf_value rk3399_defaults[] = {
+	{ "jtag switching", RK3399_GRF_SOC_CON7, HIWORD_UPDATE(0, 1, 12) },
+
+};
+
+static const struct rockchip_grf_info rk3399_grf = {
+	.values = rk3399_defaults,
+	.num_values = ARRAY_SIZE(rk3399_defaults),
+};
+
+static const struct of_device_id rockchip_grf_dt_match[] = {
+	{
+		.compatible = "rockchip,rk3036-grf",
+		.data = (void *)&rk3036_grf,
+	}, {
+		.compatible = "rockchip,rk3288-grf",
+		.data = (void *)&rk3288_grf,
+	}, {
+		.compatible = "rockchip,rk3399-grf",
+		.data = (void *)&rk3399_grf,
+	},
+	{ /* sentinel */ },
+};
+
+static int rockchip_grf_probe(struct platform_device *pdev)
+{
+	const struct rockchip_grf_info *grf_info;
+	const struct of_device_id *match;
+	struct device *dev = &pdev->dev;
+	struct regmap *grf;
+	int i;
+
+	if (!dev->of_node)
+		return -ENODEV;
+
+	match = of_match_device(rockchip_grf_dt_match, dev);
+	if (!match || !match->data) {
+		dev_err(dev, "missing grf data\n");
+		return -EINVAL;
+	}
+
+	grf_info = match->data;
+
+	grf = syscon_node_to_regmap(dev->of_node);
+	if (IS_ERR(grf)) {
+		dev_err(dev, "rockchip: could not get grf syscon\n");
+		return PTR_ERR(grf);
+	}
+
+	for (i = 0; i < grf_info->num_values; i++) {
+		const struct rockchip_grf_value *val = &grf_info->values[i];
+
+		dev_dbg(dev, "adjusting %s in 0x%x to 0x%x\n",
+			val->desc, val->reg, val->val);
+		regmap_write(grf, val->reg, val->val);
+	}
+
+	return 0;
+}
+
+static struct platform_driver rockchip_grf_driver = {
+	.probe = rockchip_grf_probe,
+	.driver = {
+		.name   = "rockchip-grf",
+		.of_match_table = rockchip_grf_dt_match,
+		/*
+		 * The General Register Files are a central component
+		 * accessed by numerous ip blocks and we're setting
+		 * defaults which should only happen once.
+		 */
+		.suppress_bind_attrs = true,
+	},
+};
+
+static int __init rockchip_grf_drv_register(void)
+{
+	return platform_driver_register(&rockchip_grf_driver);
+}
+postcore_initcall(rockchip_grf_drv_register);
-- 
2.6.4



From swarren at wwwdotorg.org  Mon May 23 08:07:14 2016
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Mon, 23 May 2016 09:07:14 -0600
Subject: [PATCH 07/54] MAINTAINERS: Add file patterns for bcm2835 device
 tree bindings
In-Reply-To: <1463907991-7916-8-git-send-email-geert@linux-m68k.org>
References: <1463907991-7916-1-git-send-email-geert@linux-m68k.org>
 <1463907991-7916-8-git-send-email-geert@linux-m68k.org>
Message-ID: <57431CA2.3020102@wwwdotorg.org>

On 05/22/2016 03:05 AM, Geert Uytterhoeven wrote:
> Submitters of device tree binding documentation may forget to CC
> the subsystem maintainer if this is missing.


> @@ -2505,6 +2505,7 @@ L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
>  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rpi/linux-rpi.git
>  S:	Maintained
>  N:	bcm2835
> +F:	Documentation/devicetree/bindings/soc/bcm/

This looks wrong; the kernel supports more Broadcom chips than just the 
bcm283[567]. I'd suggest using a regex to make sure it only matches the 
appropriate chips. Perhaps:

N: bcm283[567]

? That also has the advantage of matching all the bindings in other 
directories in Documentation/devicetree/bindings, and indeed all the 
drivers and DT files too.



From gabriele.paoloni at huawei.com  Mon May 23 08:16:01 2016
From: gabriele.paoloni at huawei.com (Gabriele Paoloni)
Date: Mon, 23 May 2016 15:16:01 +0000
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <20160523105655.GA22902@red-moon>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
Message-ID: <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>

Hi Lorenzo

> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
> Sent: 23 May 2016 11:57
> To: Ard Biesheuvel
> Cc: Gabriele Paoloni; Jon Masters; Tomasz Nowicki; helgaas at kernel.org;
> arnd at arndb.de; will.deacon at arm.com; catalin.marinas at arm.com;
> rafael at kernel.org; hanjun.guo at linaro.org; okaya at codeaurora.org;
> jchandra at broadcom.com; linaro-acpi at lists.linaro.org; linux-
> pci at vger.kernel.org; dhdang at apm.com; Liviu.Dudau at arm.com;
> ddaney at caviumnetworks.com; jeremy.linton at arm.com; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org;
> robert.richter at caviumnetworks.com; Suravee.Suthikulpanit at amd.com;
> msalter at redhat.com; Wangyijing; mw at semihalf.com;
> andrea.gallo at linaro.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI host
> controller
> 
> On Fri, May 20, 2016 at 11:14:03AM +0200, Ard Biesheuvel wrote:
> > On 20 May 2016 at 10:40, Gabriele Paoloni
> <gabriele.paoloni at huawei.com> wrote:
> > > Hi Ard
> > >
> > >> -----Original Message-----
> > >> From: Ard Biesheuvel [mailto:ard.biesheuvel at linaro.org]
> > [...]
> > >>
> > >> Is the PCIe root complex so special that you cannot simply
> describe an
> > >> implementation that is not PNP0408 compatible as something else,
> under
> > >> its own unique HID? If everybody is onboard with using ACPI, how
> is
> > >> this any different from describing other parts of the platform
> > >> topology? Even if the SBSA mandates generic PCI, they already
> deviated
> > >> from that when they built the hardware, so pretending that it is a
> > >> PNP0408 with quirks really does not buy us anything.
> > >
> > > From my understanding we want to avoid this as this would allow
> each
> > > vendor to come up with his own code and it would be much more
> effort
> > > for the PCI maintainer to rework the PCI framework to accommodate
> X86
> > > and "all" ARM64 Host Controllers...
> > >
> > > I guess this approach is too risky and we want to avoid this.
> Through
> > > standardization we can more easily maintain the code and scale it
> to
> > > multiple SoCs...
> > >
> > > So this is my understanding; maybe Jon, Tomasz or Lorenzo can give
> > > a bit more explanation...
> > >
> >
> > OK, so that boils down to recommending to vendors to represent known
> > non-compliant hardware as compliant, just so that we don't have to
> > change the code to support additional flavors of ECAM ? It's fine to
> > be pragmatic, but that sucks.
> >
> > We keep confusing the x86 case with the ARM case here: for x86, they
> > needed to deal with broken hardware *after* the fact, and all they
> > could do is find /some/ distinguishing feature in order to guess
> which
> > exact hardware they might be running on. For arm64, it is the
> opposite
> > case. We are currently in a position where we can demand vendors to
> > comply with the standards they endorsed themselves, and (ab)using
> ACPI
> > + DMI as a de facto platform description rather than plain ACPI makes
> > me think the DT crowd were actually right from the beginning. It
> > *directly* violates the standardization principle, since it requires
> a
> > priori knowledge inside the OS that a certain 'generic' device must
> be
> > driven in a special way.
> >
> > So can anyone comment on the feasibility of adding support for
> devices
> > with vendor specific HIDs (and no generic CIDs) to the current ACPI
> > ECAM driver in Linux?
> 
> Host bridges in ACPI are handled through PNP0A08/PNP0A03 ids, and
> most of the arch specific code is handled in the respective arch
> directories (X86 and IA64, even though IA64 does not rely on ECAM/MCFG
> for
> PCI ops), it is not a driver per-se, PNP0A08/PNP0A03 are detected
> through
> ACPI scan handlers and the respective arch code (ie pci_acpi_scan_root)
> sets-up resources AND config space on an arch specific basis.
> 
> X86 deals with that with code in arch/x86 that sets-up the pci_raw_ops
> on a platform specific basis (and it is not nice, but it works because
> as you all know the number of platforms in X86 world is contained).
> 
> Will this happen for ARM64 in arch/arm64 based on vendor specific
> HIDs ?
> 
> No.
> 
> So given the current state of play (we were requested to move the
> arch/arm64 specific ACPI PCI bits to arch/arm64), we would end up
> with arch/arm64 code requiring code in /drivers to set-up pci_ops
> in a platform specific way, it is horrible, if feasible at all.
> 
> The only way this can be implemented is by pretending that the
> ACPI/PCI arch/arm64 implementation is generic code (that's what this
> series does), move it to /drivers (where it is in this series), and
> implement _DSD vendor specific bindings (per HID) to set-up the pci
> operations; whether this solution should go upstream, given that it
> is just a short-term solution for early platforms bugs, it is another
> story and my personal answer is no.

I think it shouldn't be too bad to move quirk handling mechanism to
arch/arm64. Effectively we would not move platform specific code into
arch/arm64 but just the mechanism checking if there is any quirk that
is defined.

i.e.:

extern struct pci_cfg_fixup __start_acpi_mcfg_fixups[];
extern struct pci_cfg_fixup __end_acpi_mcfg_fixups[];

static struct pci_ecam_ops *pci_acpi_get_ops(struct acpi_pci_root *root)
{
        int bus_num = root->secondary.start;
        int domain = root->segment;
        struct pci_cfg_fixup *f;

        /*
         * Match against platform specific quirks and return corresponding
         * CAM ops.
         *
         * First match against PCI topology <domain:bus> then use DMI or
         * custom match handler.
         */
        for (f = __start_acpi_mcfg_fixups; f < __end_acpi_mcfg_fixups; f++) {
                if ((f->domain == domain || f->domain == PCI_MCFG_DOMAIN_ANY) &&
                    (f->bus_num == bus_num || f->bus_num == PCI_MCFG_BUS_ANY) &&
                    (f->system ? dmi_check_system(f->system) : 1) &&
                    (f->match ? f->match(f, root) : 1))
                        return f->ops;
        }
        /* No quirks, use ECAM */
        return &pci_generic_ecam_ops;
}

Such quirks will be defined anyway in drivers/pci/host/ in the vendor
specific quirk implementations.

e.g. in HiSilicon case we would have

DECLARE_ACPI_MCFG_FIXUP(NULL, hisi_pcie_match, &hisi_pcie_ecam_ops,
			PCI_MCFG_DOMAIN_ANY, PCI_MCFG_BUS_ANY);

in "drivers/pci/host/pcie-hisi-acpi.c "

Thanks

Gab

> 
> Lorenzo


From jean.guyomarch at openwide.fr  Mon May 23 08:16:25 2016
From: jean.guyomarch at openwide.fr (Jean Guyomarc'h)
Date: Mon, 23 May 2016 17:16:25 +0200
Subject: [PATCH] ARM: mach-imx6q: fix spelling mistake in error message
Message-ID: <1464016585-31852-1-git-send-email-jean.guyomarch@openwide.fr>

The compatible device tree node that is searched for is imx6q-iomuxc-gpr
but was misspelled imx6q-iomux-gpr in the error handling message.

Signed-off-by: Jean Guyomarc'h <jean.guyomarch at openwide.fr>
---
 arch/arm/mach-imx/mach-imx6q.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 3ab6154..6e0a64e 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -220,7 +220,7 @@ static void __init imx6q_1588_init(void)
 				IMX6Q_GPR1_ENET_CLK_SEL_MASK,
 				clksel);
 	else
-		pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
+		pr_err("failed to find fsl,imx6q-iomuxc-gpr regmap\n");
 
 	clk_put(enet_ref);
 put_ptp_clk:
-- 
2.1.4



From eric.auger at linaro.org  Mon May 23 08:20:06 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 23 May 2016 17:20:06 +0200
Subject: [PATCH V5 6/6] vfio, platform: make reset driver a requirement by
 default
In-Reply-To: <1463364819-477-7-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
 <1463364819-477-7-git-send-email-okaya@codeaurora.org>
Message-ID: <57431FA6.8060405@linaro.org>

Hi Sinan,
On 05/16/2016 04:13 AM, Sinan Kaya wrote:
> The code was allowing platform devices to be used without a supporting
> VFIO reset driver. The hardware can be left in some inconsistent state
> after a guest machine abort.
> 
> The reset driver will put the hardware back to safe state and disable
> interrupts before returning the control back to the host machine.

The commit message should describe the new module option.

You should also describe this is not just a matter of having a reset
function implemented & found somewhere but also a matter of having the
reset call to succeed. A reset failure now induce a failure on the first
open(). Shouldn't we handle this failure in a separate patch to make
this clearer?
> 
> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
> ---
>  drivers/vfio/platform/vfio_amba.c             |  5 +++++
>  drivers/vfio/platform/vfio_platform.c         |  5 +++++
>  drivers/vfio/platform/vfio_platform_common.c  | 18 ++++++++++++++----
>  drivers/vfio/platform/vfio_platform_private.h |  1 +
>  4 files changed, 25 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c
> index a66479b..7585902 100644
> --- a/drivers/vfio/platform/vfio_amba.c
> +++ b/drivers/vfio/platform/vfio_amba.c
> @@ -23,6 +23,10 @@
>  #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis at virtualopensystems.com>"
>  #define DRIVER_DESC     "VFIO for AMBA devices - User Level meta-driver"
>  
> +static bool reset_required = true;
> +module_param(reset_required, bool, 0644);
> +MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)");
> +
>  /* probing devices from the AMBA bus */
>  
>  static struct resource *get_amba_resource(struct vfio_platform_device *vdev,
> @@ -68,6 +72,7 @@ static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
>  	vdev->get_resource = get_amba_resource;
>  	vdev->get_irq = get_amba_irq;
>  	vdev->parent_module = THIS_MODULE;
> +	vdev->reset_required = reset_required;
>  
>  	ret = vfio_platform_probe_common(vdev, &adev->dev);
>  	if (ret) {
> diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
> index b1cc3a7..ef89146 100644
> --- a/drivers/vfio/platform/vfio_platform.c
> +++ b/drivers/vfio/platform/vfio_platform.c
> @@ -23,6 +23,10 @@
>  #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis at virtualopensystems.com>"
>  #define DRIVER_DESC     "VFIO for platform devices - User Level meta-driver"
>  
> +static bool reset_required = true;
> +module_param(reset_required, bool, 0644);
> +MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)");
> +
>  /* probing devices from the linux platform bus */
>  
>  static struct resource *get_platform_resource(struct vfio_platform_device *vdev,
> @@ -66,6 +70,7 @@ static int vfio_platform_probe(struct platform_device *pdev)
>  	vdev->get_resource = get_platform_resource;
>  	vdev->get_irq = get_platform_irq;
>  	vdev->parent_module = THIS_MODULE;
> +	vdev->reset_required = reset_required;
>  
>  	ret = vfio_platform_probe_common(vdev, &pdev->dev);
>  	if (ret)
> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
> index 095d5b7..89fb18f 100644
> --- a/drivers/vfio/platform/vfio_platform_common.c
> +++ b/drivers/vfio/platform/vfio_platform_common.c
> @@ -121,10 +121,10 @@ static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
>  	return vdev->of_reset ? true : false;
>  }
>  
> -static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
> +static int vfio_platform_get_reset(struct vfio_platform_device *vdev)
>  {
>  	if (vdev->acpihid)
> -		return;
> +		return vfio_platform_acpi_has_reset(vdev) ? 0 : -EINVAL;
-ENOENT instead?
>  
>  	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
>  						    &vdev->reset_module);
> @@ -133,6 +133,8 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>  		vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
>  							&vdev->reset_module);
>  	}
> +
> +	return vdev->of_reset ? 0 : -EINVAL;
same
>  }
>  
>  static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
> @@ -263,7 +265,9 @@ static int vfio_platform_open(void *device_data)
>  		if (ret)
>  			goto err_irq;
>  
> -		vfio_platform_call_reset(vdev);
> +		ret = vfio_platform_call_reset(vdev);
> +		if (ret && vdev->reset_required)
> +			goto err_irq;

what do we do at release time in case the reset fails. You did not
change anything. Shouldn't we at least emit a warning to the user if the
reset becomes mandated (separate patch as evoked above)?

Thanks

Eric
>  	}
>  
>  	vdev->refcnt++;
> @@ -669,7 +673,13 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>  		return ret;
>  	}
>  
> -	vfio_platform_get_reset(vdev);
> +	ret = vfio_platform_get_reset(vdev);
> +	if (ret && vdev->reset_required) {
> +		pr_err("vfio: no reset function found for device %s\n",
> +		       vdev->name);
> +		iommu_group_put(group);
> +		return ret;

> +	}
>  
>  	mutex_init(&vdev->igate);
>  
> diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
> index ba9e4f8..68fbc00 100644
> --- a/drivers/vfio/platform/vfio_platform_private.h
> +++ b/drivers/vfio/platform/vfio_platform_private.h
> @@ -50,6 +50,7 @@ struct vfio_platform_region {
>  };
>  
>  struct vfio_platform_device {
> +	bool				reset_required;
>  	struct vfio_platform_region	*regions;
>  	u32				num_regions;
>  	struct vfio_platform_irq	*irqs;
> 



From eric.auger at linaro.org  Mon May 23 08:21:27 2016
From: eric.auger at linaro.org (Eric Auger)
Date: Mon, 23 May 2016 17:21:27 +0200
Subject: [PATCH V5 5/6] vfio: platform: call _RST method when using ACPI
In-Reply-To: <1463364819-477-6-git-send-email-okaya@codeaurora.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
 <1463364819-477-6-git-send-email-okaya@codeaurora.org>
Message-ID: <57431FF7.2060807@linaro.org>

Hi Sinan,
On 05/16/2016 04:13 AM, Sinan Kaya wrote:
> The device tree code checks for the presence of a reset driver and calls
> the of_reset function pointer by looking up the reset driver as a module.
> 
> ACPI defines _RST method to perform device level reset. After the _RST
> method is executed, the OS can resume using the device.
> 
> This patch checks the presence of _RST method and calls the _RST
> method when reset is requested.
> 
> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
> ---
>  drivers/vfio/platform/vfio_platform_common.c | 44 ++++++++++++++++++++++++++++
>  1 file changed, 44 insertions(+)
> 
> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
> index d859d3b..095d5b7 100644
> --- a/drivers/vfio/platform/vfio_platform_common.c
> +++ b/drivers/vfio/platform/vfio_platform_common.c
> @@ -73,21 +73,59 @@ int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
>  	}
>  	return 0;
>  }
> +
> +static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
> +{
> +	struct device *dev = vdev->device;
> +	acpi_handle handle = ACPI_HANDLE(dev);
> +	acpi_status acpi_ret;
> +	unsigned long long val;
> +
> +	acpi_ret = acpi_evaluate_integer(handle, "_RST", NULL, &val);
> +	if (ACPI_FAILURE(acpi_ret))
> +		return -EINVAL;
Can't you return something more explicit here? The error code will be
visible to the userspace. Difficult for him to understand the cause of
the failure in that case.

Eric
> +
> +	return 0;
> +}
> +
> +static bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
> +{
> +	struct device *dev = vdev->device;
> +	acpi_handle handle = ACPI_HANDLE(dev);
> +
> +	return acpi_has_method(handle, "_RST");
> +}
>  #else
>  int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
>  			     struct device *dev)
>  {
>  	return -EINVAL;
>  }
> +
> +static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
> +{
> +	return -EINVAL;
> +}
> +
> +static bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
> +{
> +	return false;
> +}
>  #endif
>  
>  static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
>  {
> +	if (vdev->acpihid)
> +		return vfio_platform_acpi_has_reset(vdev);
> +
>  	return vdev->of_reset ? true : false;
>  }
>  
>  static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>  {
> +	if (vdev->acpihid)
> +		return;
> +
>  	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
>  						    &vdev->reset_module);
>  	if (!vdev->of_reset) {
> @@ -99,6 +137,9 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>  
>  static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
>  {
> +	if (vdev->acpihid)
> +		return;
> +
>  	if (vdev->of_reset)
>  		module_put(vdev->reset_module);
>  }
> @@ -177,6 +218,9 @@ static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
>  		dev_info(vdev->device, "reset\n");
>  		vdev->of_reset(vdev);
>  		return 0;
> +	} else if (vdev->acpihid) {
> +		dev_info(vdev->device, "reset\n");
> +		return vfio_platform_acpi_call_reset(vdev);
>  	}
>  
>  	dev_warn(vdev->device, "no reset function found!\n");
> 



From okaya at codeaurora.org  Mon May 23 08:36:14 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Mon, 23 May 2016 11:36:14 -0400
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <1462893601-8937-1-git-send-email-tn@semihalf.com>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
Message-ID: <5743236E.6090801@codeaurora.org>

On 5/10/2016 11:19 AM, Tomasz Nowicki wrote:
> From the functionality point of view this series may be split into the
> following logic parts:
> 1. New ECAM API and update for users of the pci-host-common API
> 2. Necessary fixes as the preparation for using driver on ARM64.
> 3. Use new MCFG interface and implement generic ACPI based PCI host controller driver.
> 4. Enable above driver on ARM64
> 
> Patches has been built on top of 4.6-rc7 and can be found here:
> git at github.com:semihalf-nowicki-tomasz/linux.git (pci-acpi-v7)
> 
> This has been tested on Cavium ThunderX server. Any help in reviewing and
> testing is very appreciated.
> 

Tested on Qualcomm QDF2XXX server using Mellanox CX3 and Intel e1000e adapters.

Tested-by: Sinan Kaya <okaya at codeaurora.org>



-- 
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


From greg at kroah.com  Mon May 23 08:36:19 2016
From: greg at kroah.com (Greg KH)
Date: Mon, 23 May 2016 08:36:19 -0700
Subject: [PATCH 0/2 (linux-stable-4.5.y)] net: stmmac: MDIO fixes
In-Reply-To: <1464009463-23654-1-git-send-email-peppe.cavallaro@st.com>
References: <1464009463-23654-1-git-send-email-peppe.cavallaro@st.com>
Message-ID: <20160523153619.GA30179@kroah.com>

On Mon, May 23, 2016 at 03:17:41PM +0200, Giuseppe Cavallaro wrote:
> These patches port some recent fixes for linux-4.5.y stable branch.
> They fix the MDIO settings trying to cover the all possible scenario
> when the stmmac is connected to a real transceiver or a switch.
> 
> These patches are needed for Kernel 4.5 where Lime2, BananaPi and Cubieboard2
> show problems when use the stmmac:
> 
> https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=823493

What are the git commit id for these patches in Linus's tree?

thanks,

greg k-h


From robh at kernel.org  Mon May 23 08:41:38 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 23 May 2016 10:41:38 -0500
Subject: [PATCH v2 1/5] dt-bindings: mediatek: add descriptions for
 mediatek mt2701 iommu and smi
In-Reply-To: <1463658558-567-2-git-send-email-honghui.zhang@mediatek.com>
References: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
 <1463658558-567-2-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <20160523154138.GA31426@rob-hp-laptop>

On Thu, May 19, 2016 at 07:49:14PM +0800, honghui.zhang at mediatek.com wrote:
> From: Honghui Zhang <honghui.zhang at mediatek.com>
> 
> This patch defines the local arbitor port IDs for mediatek SoC MT2701 and
> add descriptions of binding for mediatek generation one iommu and smi.
> 
> Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
> ---
>  .../devicetree/bindings/iommu/mediatek,iommu.txt   | 13 +++-
>  .../memory-controllers/mediatek,smi-common.txt     | 21 +++++-
>  .../memory-controllers/mediatek,smi-larb.txt       |  4 +-
>  include/dt-bindings/memory/mt2701-larb-port.h      | 85 ++++++++++++++++++++++
>  4 files changed, 115 insertions(+), 8 deletions(-)
>  create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h

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


From nleeder at codeaurora.org  Mon May 23 08:43:15 2016
From: nleeder at codeaurora.org (Neil Leeder)
Date: Mon, 23 May 2016 11:43:15 -0400
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
In-Reply-To: <573F7F5C.1050100@codeaurora.org>
References: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
 <573F7F5C.1050100@codeaurora.org>
Message-ID: <4ad1d1b2-f0eb-3780-21e7-9dd1b23d6934@codeaurora.org>



On 5/20/2016 05:19 PM, Stephen Boyd wrote:
> On 05/20/2016 12:13 PM, Neil Leeder wrote:
>> diff --git a/drivers/soc/qcom/l2-accessors.c b/drivers/soc/qcom/l2-accessors.c
>> new file mode 100644
>> index 0000000..fbb69bd
>> --- /dev/null
>> +++ b/drivers/soc/qcom/l2-accessors.c
>> @@ -0,0 +1,66 @@
>> +/*
>> + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 and
>> + * only version 2 as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <linux/spinlock.h>
>> +#include <linux/module.h>
> 
> export.h instead?

OK, will address in v2

> 
>> +#include <linux/soc/qcom/l2-accessors.h>
>> +#include <asm/cputype.h>
>> +#include <asm/sysreg.h>
> 
> Is there a patch to add sysreg.h to arch/arm? It would be nice to use
> one l2 accessor API on arm64 and arm.
> 

Sounds like a good thing for the next person who submits a krait L2 patch to consider.

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


From wens at csie.org  Mon May 23 07:36:04 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 23 May 2016 22:36:04 +0800
Subject: [PATCH 14/16] clk: sunxi-ng: Add N-K-M-P factor clock
In-Reply-To: <1462737711-10017-15-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-15-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v66b7jXrAs0rBrcHWskQQPqrhRVzY6OmCSoGZg2tfDJrDA@mail.gmail.com>

Hi,

On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Introduce support for clocks that use a combination of two linear
> multipliers (N and K factors), one linear divider (M) and one power of two
> divider (P).
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile   |   1 +
>  drivers/clk/sunxi-ng/ccu_nkmp.c | 157 ++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_nkmp.h |  43 +++++++++++
>  3 files changed, 201 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu_nkmp.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu_nkmp.h
>
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 2bb8bc22e907..c794f57b6fb1 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -9,6 +9,7 @@ obj-y += ccu_mp.o
>  obj-y += ccu_mux.o
>  obj-y += ccu_nk.o
>  obj-y += ccu_nkm.o
> +obj-y += ccu_nkmp.o
>  obj-y += ccu_nm.o
>  obj-y += ccu_p.o
>  obj-y += ccu_phase.o
> diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c
> new file mode 100644
> index 000000000000..b7da00773cd6
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c
> @@ -0,0 +1,157 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard
> + * Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/rational.h>
> +
> +#include "ccu_gate.h"
> +#include "ccu_nkmp.h"
> +
> +void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
> +                       unsigned long max_n, unsigned long max_k,
> +                       unsigned long max_m, unsigned long max_p,
> +                       unsigned long *n, unsigned long *k,
> +                       unsigned long *m, unsigned long *p)

We definitely should just pass struct ccu_nkmp* here.

> +{
> +       unsigned long best_rate = 0;
> +       unsigned long best_n = 0, best_k = 0, best_m = 0, best_p = 0;
> +       unsigned long _n, _k, _m, _p;
> +
> +       for (_k = 1; _k <= max_k; _k++) {
> +               for (_p = 0; _p <= max_p; _p++) {
> +                       unsigned long tmp_rate;
> +
> +                       rational_best_approximation(rate / _k, parent << _p,

I think you mean "parent >> _p" ?

In general we might lose some precision if parent is too small or _p is
too large. But the only place we see this type of clock is the CPU PLL,
and parent (24 MHz) are divisible by all the possible values of P.

This brings up another issue: P does not go all the way up to (1 << width - 1).
A register value of 3, or P = 8 is not valid, and it's not restricted in
the driver. This is not true for all the SoCs though.

The manual also says P should only be used when rate < 288 MHz. Moving
P to the outer loop, and maybe adding a short circuit exit when the rate
matches exactly would help.

> +                                                   max_n, max_m, &_n, &_m);
> +
> +                       tmp_rate = (parent * _n * _k >> _p) / _m;
> +
> +                       if (tmp_rate > rate)
> +                               continue;
> +
> +                       if ((rate - tmp_rate) < (rate - best_rate)) {
> +                               best_rate = tmp_rate;
> +                               best_n = _n;
> +                               best_k = _k;
> +                               best_m = _m;
> +                               best_p = _p;
> +                       }
> +               }
> +       }
> +
> +       *n = best_n;
> +       *k = best_k;
> +       *m = best_m;
> +       *p = best_p;
> +}
> +
> +static void ccu_nkmp_disable(struct clk_hw *hw)
> +{
> +       struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
> +
> +       return ccu_gate_helper_disable(&nkmp->common, nkmp->enable);
> +}
> +
> +static int ccu_nkmp_enable(struct clk_hw *hw)
> +{
> +       struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
> +
> +       return ccu_gate_helper_enable(&nkmp->common, nkmp->enable);
> +}
> +
> +static int ccu_nkmp_is_enabled(struct clk_hw *hw)
> +{
> +       struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
> +
> +       return ccu_gate_helper_is_enabled(&nkmp->common, nkmp->enable);
> +}
> +
> +static unsigned long ccu_nkmp_recalc_rate(struct clk_hw *hw,
> +                                       unsigned long parent_rate)
> +{
> +       struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
> +       unsigned long n, m, k, p;
> +       u32 reg;
> +
> +       reg = readl(nkmp->common.base + nkmp->common.reg);
> +
> +       n = reg >> nkmp->n.shift;
> +       n &= (1 << nkmp->n.width) - 1;
> +
> +       k = reg >> nkmp->k.shift;
> +       k &= (1 << nkmp->k.width) - 1;
> +
> +       m = reg >> nkmp->m.shift;
> +       m &= (1 << nkmp->m.width) - 1;
> +
> +       p = reg >> nkmp->p.shift;
> +       p &= (1 << nkmp->p.width) - 1;
> +
> +       return (parent_rate * (n + 1) * (k + 1) >> p) / (m + 1);
> +}
> +
> +static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
> +                             unsigned long *parent_rate)
> +{
> +       struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
> +       unsigned long n, k, m, p;
> +
> +       ccu_nkmp_find_best(*parent_rate, rate,
> +                          1 << nkmp->n.width, 1 << nkmp->k.width,
> +                          1 << nkmp->m.width, (1 << nkmp->p.width) - 1,
> +                          &n, &k, &m, &p);
> +
> +       return (*parent_rate * n * k >> p) / m;
> +}
> +
> +static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
> +                          unsigned long parent_rate)
> +{
> +       struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
> +       unsigned long n, k, m, p;
> +       unsigned long flags;
> +       u32 reg;
> +
> +       ccu_nkmp_find_best(parent_rate, rate,
> +                          1 << nkmp->n.width, 1 << nkmp->k.width,
> +                          1 << nkmp->m.width, (1 << nkmp->p.width) - 1,
> +                          &n, &k, &m, &p);
> +
> +       spin_lock_irqsave(nkmp->common.lock, flags);
> +
> +       reg = readl(nkmp->common.base + nkmp->common.reg);
> +       reg &= ~GENMASK(nkmp->n.width + nkmp->n.shift, nkmp->n.shift);
> +       reg &= ~GENMASK(nkmp->k.width + nkmp->k.shift, nkmp->k.shift);
> +       reg &= ~GENMASK(nkmp->m.width + nkmp->m.shift, nkmp->m.shift);
> +       reg &= ~GENMASK(nkmp->p.width + nkmp->p.shift, nkmp->p.shift);

GENMASK(width + shift - 1, shift)

> +
> +       reg |= (n - 1) << nkmp->m.shift;
> +       reg |= (k - 1) << nkmp->m.shift;
> +       reg |= (m - 1) << nkmp->m.shift;
> +       reg |= p << nkmp->p.shift;
> +
> +       writel(reg, nkmp->common.base + nkmp->common.reg);
> +
> +       spin_unlock_irqrestore(nkmp->common.lock, flags);
> +
> +       ccu_helper_wait_for_lock(&nkmp->common, nkmp->lock);
> +
> +       return 0;
> +}
> +
> +const struct clk_ops ccu_nkmp_ops = {
> +       .disable        = ccu_nkmp_disable,
> +       .enable         = ccu_nkmp_enable,
> +       .is_enabled     = ccu_nkmp_is_enabled,
> +
> +       .recalc_rate    = ccu_nkmp_recalc_rate,
> +       .round_rate     = ccu_nkmp_round_rate,
> +       .set_rate       = ccu_nkmp_set_rate,
> +};
> diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.h b/drivers/clk/sunxi-ng/ccu_nkmp.h
> new file mode 100644
> index 000000000000..8a91f2c837a4
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu_nkmp.h
> @@ -0,0 +1,43 @@
> +/*
> + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _CCU_NKMP_H_
> +#define _CCU_NKMP_H_
> +
> +#include <linux/clk-provider.h>
> +
> +#include "ccu_factor.h"
> +#include "ccu_common.h"
> +
> +struct ccu_nkmp {
> +       u32                     enable;
> +       u32                     lock;
> +
> +       struct ccu_factor       n;
> +       struct ccu_factor       k;
> +       struct ccu_factor       m;
> +       struct ccu_factor       p;
> +
> +       struct ccu_common       common;
> +};
> +
> +static inline struct ccu_nkmp *hw_to_ccu_nkmp(struct clk_hw *hw)
> +{
> +       struct ccu_common *common = hw_to_ccu_common(hw);
> +
> +       return container_of(common, struct ccu_nkmp, common);
> +}
> +
> +extern const struct clk_ops ccu_nkmp_ops;

Macro please. :)


Regards
ChenYu

> +
> +#endif /* _CCU_NKMP_H_ */
> --
> 2.8.2
>


From yendapally.reddy at broadcom.com  Mon May 23 09:20:47 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Mon, 23 May 2016 12:20:47 -0400
Subject: [PATCH 0/4] hw rng support for NSP SoC
Message-ID: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>

This patchset contains the hw random number generator support for the
Broadcom's NSP SoC. The block is similar to the block available in
bcm2835 with different default interrupt mask value. Due to lack of
documentation, I cannot confirm the interrupt mask register details
in bcm2835. In an effort to not break the existing functionality of
bcm2835, I used a different compatible string to mask the interrupt
for NSP SoC. Please let me know. Also supported providing requested
number of random numbers instead of static size of four bytes.

The first patch contains the documentation changes and the second patch
contains the support for rng available in NSP SoC. The third patch
contains the device tree changes for NSP SoC. The fourth patch contains
the support for reading requested number of random numbers.

This patch set has been tested on NSP bcm958625HR board.
This patch set is based on v4.6.0-rc1 and is available from github
repo: https://github.com/Broadcom/cygnus-linux.git
branch: nsp-rng-v1

Yendapally Reddy Dhananjaya Reddy (4):
  dt-bindings: rng: Northstar Plus SoC rng bindings
  hwrng: bcm2835: Support Broadcom NSP SoC rng
  ARM: dts: nsp: Add rng device tree entry
  hwrng: bcm2835: Read as much data as available

 .../devicetree/bindings/rng/brcm,bcm2835.txt       |  7 +++-
 arch/arm/boot/dts/bcm-nsp.dtsi                     |  5 +++
 drivers/char/hw_random/Kconfig                     |  2 +-
 drivers/char/hw_random/bcm2835-rng.c               | 46 +++++++++++++++++++---
 4 files changed, 52 insertions(+), 8 deletions(-)

-- 
2.1.0



From yendapally.reddy at broadcom.com  Mon May 23 09:20:48 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Mon, 23 May 2016 12:20:48 -0400
Subject: [PATCH 1/4] dt-bindings: rng: Northstar Plus SoC rng bindings
In-Reply-To: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1464020451-16520-2-git-send-email-yendapally.reddy@broadcom.com>

Document the bindings used by Northstar Plus(NSP) SoC random number
generator.

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
---
 Documentation/devicetree/bindings/rng/brcm,bcm2835.txt | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt b/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt
index 07ccdaa..aa304d4 100644
--- a/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt
+++ b/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt
@@ -2,7 +2,7 @@ BCM2835 Random number generator
 
 Required properties:
 
-- compatible : should be "brcm,bcm2835-rng"
+- compatible : should be "brcm,bcm2835-rng"  or "brcm,bcm-nsp-rng"
 - reg : Specifies base physical address and size of the registers.
 
 Example:
@@ -11,3 +11,8 @@ rng {
         compatible = "brcm,bcm2835-rng";
         reg = <0x7e104000 0x10>;
 };
+
+rng at 18033000 {
+	compatible = "brcm,bcm-nsp-rng";
+	reg = <0x18033000 0x14>;
+};
-- 
2.1.0



From yendapally.reddy at broadcom.com  Mon May 23 09:20:49 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Mon, 23 May 2016 12:20:49 -0400
Subject: [PATCH 2/4] hwrng: bcm2835: Support Broadcom NSP SoC rng
In-Reply-To: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1464020451-16520-3-git-send-email-yendapally.reddy@broadcom.com>

This supports the random number generator available in NSP SoC.
Masks the rng interrupt for NSP.

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
---
 drivers/char/hw_random/Kconfig       |  2 +-
 drivers/char/hw_random/bcm2835-rng.c | 34 ++++++++++++++++++++++++++++++----
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 67ee8b0..f8d1a2b 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -90,7 +90,7 @@ config HW_RANDOM_BCM63XX
 
 config HW_RANDOM_BCM2835
 	tristate "Broadcom BCM2835 Random Number Generator support"
-	depends on ARCH_BCM2835
+	depends on ARCH_BCM2835 || ARCH_BCM_NSP
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
index 7192ec2..b1e8b78 100644
--- a/drivers/char/hw_random/bcm2835-rng.c
+++ b/drivers/char/hw_random/bcm2835-rng.c
@@ -19,6 +19,7 @@
 #define RNG_CTRL	0x0
 #define RNG_STATUS	0x4
 #define RNG_DATA	0x8
+#define RNG_INT_MASK	0x10
 
 /* enable rng */
 #define RNG_RBGEN	0x1
@@ -26,6 +27,18 @@
 /* the initial numbers generated are "less random" so will be discarded */
 #define RNG_WARMUP_COUNT 0x40000
 
+#define RNG_INT_OFF	0x1
+
+static void __init nsp_rng_init(void __iomem *base)
+{
+	u32 val;
+
+	/* mask the interrupt */
+	val = readl(base + RNG_INT_MASK);
+	val |= RNG_INT_OFF;
+	writel(val, base + RNG_INT_MASK);
+}
+
 static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
 			       bool wait)
 {
@@ -46,10 +59,18 @@ static struct hwrng bcm2835_rng_ops = {
 	.read	= bcm2835_rng_read,
 };
 
+static const struct of_device_id bcm2835_rng_of_match[] = {
+	{ .compatible = "brcm,bcm2835-rng"},
+	{ .compatible = "brcm,bcm-nsp-rng", .data = nsp_rng_init},
+	{},
+};
+
 static int bcm2835_rng_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
+	void (*rng_setup)(void __iomem *base);
+	const struct of_device_id *rng_id;
 	void __iomem *rng_base;
 	int err;
 
@@ -61,6 +82,15 @@ static int bcm2835_rng_probe(struct platform_device *pdev)
 	}
 	bcm2835_rng_ops.priv = (unsigned long)rng_base;
 
+	rng_id = of_match_node(bcm2835_rng_of_match, np);
+	if (!rng_id)
+		return -EINVAL;
+
+	/* Check for rng init function, execute it */
+	rng_setup = rng_id->data;
+	if (rng_setup)
+		rng_setup(rng_base);
+
 	/* set warm-up count & enable */
 	__raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS);
 	__raw_writel(RNG_RBGEN, rng_base + RNG_CTRL);
@@ -90,10 +120,6 @@ static int bcm2835_rng_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id bcm2835_rng_of_match[] = {
-	{ .compatible = "brcm,bcm2835-rng", },
-	{},
-};
 MODULE_DEVICE_TABLE(of, bcm2835_rng_of_match);
 
 static struct platform_driver bcm2835_rng_driver = {
-- 
2.1.0



From yendapally.reddy at broadcom.com  Mon May 23 09:20:50 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Mon, 23 May 2016 12:20:50 -0400
Subject: [PATCH 3/4] ARM: dts: nsp: Add rng device tree entry
In-Reply-To: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1464020451-16520-4-git-send-email-yendapally.reddy@broadcom.com>

Add support for the random number generator to the Northstar Plus
SoC device tree.

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
---
 arch/arm/boot/dts/bcm-nsp.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi
index def9e78..1ed829e 100644
--- a/arch/arm/boot/dts/bcm-nsp.dtsi
+++ b/arch/arm/boot/dts/bcm-nsp.dtsi
@@ -206,6 +206,11 @@
 			brcm,nand-has-wp;
 		};
 
+		rng: rng at 33000 {
+			compatible = "brcm,bcm-nsp-rng";
+			reg = <0x33000 0x14>;
+		};
+
 		ccbtimer0: timer at 34000 {
 			compatible = "arm,sp804";
 			reg = <0x34000 0x1000>;
-- 
2.1.0



From yendapally.reddy at broadcom.com  Mon May 23 09:20:51 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Mon, 23 May 2016 12:20:51 -0400
Subject: [PATCH 4/4] hwrng: bcm2835: Read as much data as available
In-Reply-To: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1464020451-16520-5-git-send-email-yendapally.reddy@broadcom.com>

Read the requested number of data from the fifo

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
---
 drivers/char/hw_random/bcm2835-rng.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
index b1e8b78..9bbdc07 100644
--- a/drivers/char/hw_random/bcm2835-rng.c
+++ b/drivers/char/hw_random/bcm2835-rng.c
@@ -43,6 +43,8 @@ static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
 			       bool wait)
 {
 	void __iomem *rng_base = (void __iomem *)rng->priv;
+	u32 max_words = max/sizeof(u32);
+	u32 num_words, count;
 
 	while ((__raw_readl(rng_base + RNG_STATUS) >> 24) == 0) {
 		if (!wait)
@@ -50,8 +52,14 @@ static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
 		cpu_relax();
 	}
 
-	*(u32 *)buf = __raw_readl(rng_base + RNG_DATA);
-	return sizeof(u32);
+	num_words = (readl(rng_base + RNG_STATUS) >> 24);
+	if (num_words > max_words)
+		num_words = max_words;
+
+	for (count = 0; count < num_words; count++)
+		((u32 *)buf)[count] = readl(rng_base + RNG_DATA);
+
+	return (num_words * sizeof(u32));
 }
 
 static struct hwrng bcm2835_rng_ops = {
-- 
2.1.0



From carlo at caione.org  Mon May 23 09:30:20 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 23 May 2016 18:30:20 +0200
Subject: [PATCH v3 0/4] Add Amlogic secure monitor driver
Message-ID: <1464021024-29380-1-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

In the Amlogic SoCs the secure monitor calls are used for a lot of reasons:
interact with the NVMEM (efuses), check the reboot reason, set USB boot, ...

This driver defines a generic interface towards the secure monitor that can be
used by more specialized drivers to interact with the secure monitor itself
without worrying about bounce buffers managing.

Changelog:

v3:
  * Moved driver to drivers/firmware
  * Added EXPORT_SYMBOL macros
  * Changed '_' in '-'
  * Introduced 'struct meson_sm_firmware' and 'meson_sm_get_fw()' to be used by
    drivers using the secure-monitor to enforce probe ordering

v2:
  * All the SMC function identifiers are now in a SoC-specific header file to
    be included by the DTS files so the SMC commands are now defined in the DT
    instead to be hardcoded into the driver
  * Patchset is no longer an RFC
  * Better error management and boundary checking
  * s/unsigned int/u32/
  * SMC call not only on CPU 0
  * Fix memory leaking
  * s/amlogic/meson/ in the directory names


Carlo Caione (4):
  firmware: Amlogic: Add secure monitor driver
  firmware: dt-bindings: Add secure monitor header file for GXBB
  ARM64: dts: amlogic: gxbb: Enable secure monitor
  documentation: Add secure monitor binding documentation

 .../bindings/firmware/meson/meson_sm.txt           |  51 ++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  11 ++
 drivers/firmware/Kconfig                           |   1 +
 drivers/firmware/Makefile                          |   1 +
 drivers/firmware/meson/Kconfig                     |   8 +
 drivers/firmware/meson/Makefile                    |   1 +
 drivers/firmware/meson/meson_sm.c                  | 179 +++++++++++++++++++++
 include/dt-bindings/firmware/meson-gxbb-sm.h       |  44 +++++
 include/linux/firmware/meson/meson_sm.h            |  38 +++++
 9 files changed, 334 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
 create mode 100644 drivers/firmware/meson/Kconfig
 create mode 100644 drivers/firmware/meson/Makefile
 create mode 100644 drivers/firmware/meson/meson_sm.c
 create mode 100644 include/dt-bindings/firmware/meson-gxbb-sm.h
 create mode 100644 include/linux/firmware/meson/meson_sm.h

-- 
2.7.4



From carlo at caione.org  Mon May 23 09:30:21 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 23 May 2016 18:30:21 +0200
Subject: [PATCH v3 1/4] firmware: Amlogic: Add secure monitor driver
In-Reply-To: <1464021024-29380-1-git-send-email-carlo@caione.org>
References: <1464021024-29380-1-git-send-email-carlo@caione.org>
Message-ID: <1464021024-29380-2-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Introduce a driver to provide calls into secure monitor mode.

In the Amlogic SoCs these calls are used for multiple reasons: access to
NVMEM, set USB boot, enable JTAG, etc...

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 drivers/firmware/Kconfig                |   1 +
 drivers/firmware/Makefile               |   1 +
 drivers/firmware/meson/Kconfig          |   8 ++
 drivers/firmware/meson/Makefile         |   1 +
 drivers/firmware/meson/meson_sm.c       | 179 ++++++++++++++++++++++++++++++++
 include/linux/firmware/meson/meson_sm.h |  38 +++++++
 6 files changed, 228 insertions(+)
 create mode 100644 drivers/firmware/meson/Kconfig
 create mode 100644 drivers/firmware/meson/Makefile
 create mode 100644 drivers/firmware/meson/meson_sm.c
 create mode 100644 include/linux/firmware/meson/meson_sm.h

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 6664f11..686e395 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -199,5 +199,6 @@ config HAVE_ARM_SMCCC
 source "drivers/firmware/broadcom/Kconfig"
 source "drivers/firmware/google/Kconfig"
 source "drivers/firmware/efi/Kconfig"
+source "drivers/firmware/meson/Kconfig"
 
 endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 474bada..fc4bb09 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_QCOM_SCM_32)	+= qcom_scm-32.o
 CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
 
 obj-y				+= broadcom/
+obj-y				+= meson/
 obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
 obj-$(CONFIG_EFI)		+= efi/
 obj-$(CONFIG_UEFI_CPER)		+= efi/
diff --git a/drivers/firmware/meson/Kconfig b/drivers/firmware/meson/Kconfig
new file mode 100644
index 0000000..fff11a3
--- /dev/null
+++ b/drivers/firmware/meson/Kconfig
@@ -0,0 +1,8 @@
+#
+# Amlogic Secure Monitor driver
+#
+config MESON_SM
+	bool
+	default ARCH_MESON
+	help
+	  Say y here to enable the Amlogic secure monitor driver
diff --git a/drivers/firmware/meson/Makefile b/drivers/firmware/meson/Makefile
new file mode 100644
index 0000000..9ab3884
--- /dev/null
+++ b/drivers/firmware/meson/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MESON_SM) +=	meson_sm.o
diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
new file mode 100644
index 0000000..445bc7f
--- /dev/null
+++ b/drivers/firmware/meson/meson_sm.c
@@ -0,0 +1,179 @@
+/*
+ * Amlogic Secure Monitor driver
+ *
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <stdarg.h>
+#include <asm/cacheflush.h>
+#include <asm/compiler.h>
+#include <linux/arm-smccc.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/smp.h>
+
+#include <linux/firmware/meson/meson_sm.h>
+
+#define SM_MEM_SIZE	0x1000
+
+struct meson_sm_data {
+	u32 cmd;
+	u32 arg0;
+	u32 arg1;
+	u32 arg2;
+	u32 arg3;
+	u32 arg4;
+	u32 ret;
+};
+
+static void __meson_sm_call(void *info)
+{
+	struct meson_sm_data *data = info;
+	struct arm_smccc_res res;
+
+	arm_smccc_smc(data->cmd,
+		      data->arg0, data->arg1, data->arg2,
+		      data->arg3, data->arg4, 0, 0, &res);
+	data->ret = res.a0;
+}
+
+u32 meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2,
+		  u32 arg3, u32 arg4)
+{
+	struct meson_sm_data data;
+
+	data.cmd = cmd;
+	data.arg0 = arg0;
+	data.arg1 = arg1;
+	data.arg2 = arg2;
+	data.arg3 = arg3;
+	data.arg4 = arg4;
+	data.ret = 0;
+
+	__meson_sm_call(&data);
+
+	return data.ret;
+}
+EXPORT_SYMBOL(meson_sm_call);
+
+u32 meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
+		       u32 cmd, u32 arg0, u32 arg1, u32 arg2,
+		       u32 arg3, u32 arg4)
+{
+	u32 size;
+
+	if (!fw)
+		return -EINVAL;
+
+	size = meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
+
+	if (!size || size > SM_MEM_SIZE)
+		return -EINVAL;
+
+	memcpy(buffer, fw->sm_sharemem_out_base, size);
+	return size;
+}
+EXPORT_SYMBOL(meson_sm_call_read);
+
+u32 meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
+			unsigned int b_size, u32 cmd, u32 arg0,
+			u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 size;
+
+	if (!fw)
+		return -EINVAL;
+
+	if (b_size > SM_MEM_SIZE)
+		return -EINVAL;
+
+	memcpy(fw->sm_sharemem_in_base, buffer, b_size);
+
+	size = meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
+
+	if (!size)
+		return -EINVAL;
+
+	return size;
+}
+EXPORT_SYMBOL(meson_sm_call_write);
+
+static int meson_sm_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct meson_sm_firmware *fw;
+	u32 sm_phy_in_base, sm_phy_out_base;
+	int cmd_in, cmd_out;
+
+	fw = devm_kzalloc(&pdev->dev, sizeof(*fw), GFP_KERNEL);
+	if (!fw)
+		return -ENOMEM;
+
+	fw->dev = &pdev->dev;
+
+	if (of_property_read_u32(np, "amlogic,sm-cmd-input-base", &cmd_in))
+		return -EINVAL;
+
+	if (of_property_read_u32(np, "amlogic,sm-cmd-output-base", &cmd_out))
+		return -EINVAL;
+
+	sm_phy_in_base = meson_sm_call(cmd_in, 0, 0, 0, 0, 0);
+	fw->sm_sharemem_in_base = ioremap_cache(sm_phy_in_base, SM_MEM_SIZE);
+	if (!fw->sm_sharemem_in_base)
+		return -EINVAL;
+
+	sm_phy_out_base = meson_sm_call(cmd_out, 0, 0, 0, 0, 0);
+	fw->sm_sharemem_out_base = ioremap_cache(sm_phy_out_base, SM_MEM_SIZE);
+	if (!fw->sm_sharemem_out_base) {
+		iounmap(fw->sm_sharemem_in_base);
+		return -EINVAL;
+	}
+
+	platform_set_drvdata(pdev, fw);
+
+	return 0;
+}
+
+struct meson_sm_firmware *meson_sm_get_fw(struct device_node *firmware_node)
+{
+	struct platform_device *pdev = of_find_device_by_node(firmware_node);
+
+	/*
+	 * Returns NULL is the firmware device is not ready.
+	 */
+	if (!pdev)
+		return NULL;
+
+	return platform_get_drvdata(pdev);
+}
+EXPORT_SYMBOL(meson_sm_get_fw);
+
+static const struct of_device_id meson_sm_ids[] = {
+	{ .compatible = "amlogic,meson-sm" },
+	{ /* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, meson_sm_ids);
+
+static struct platform_driver meson_sm_platform_driver = {
+	.probe	= meson_sm_probe,
+	.driver	= {
+		.name		= "secmon",
+		.of_match_table	= meson_sm_ids,
+	},
+};
+module_platform_driver(meson_sm_platform_driver);
+
+MODULE_AUTHOR("Carlo Caione <carlo at endlessm.com>");
+MODULE_DESCRIPTION("Amlogic secure monitor driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/firmware/meson/meson_sm.h b/include/linux/firmware/meson/meson_sm.h
new file mode 100644
index 0000000..7b6b524
--- /dev/null
+++ b/include/linux/firmware/meson/meson_sm.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MESON_SM_H_
+#define _MESON_SM_H_
+
+#include <linux/types.h>
+#include <linux/of_device.h>
+
+struct meson_sm_firmware {
+	struct device *dev;
+	void __iomem *sm_sharemem_in_base;
+	void __iomem *sm_sharemem_out_base;
+};
+
+u32 meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2,
+		  u32 arg3, u32 arg4);
+
+u32 meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
+			unsigned int b_size, u32 cmd, u32 arg0,
+			u32 arg1, u32 arg2, u32 arg3, u32 arg4);
+
+u32 meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
+		       u32 cmd, u32 arg0, u32 arg1, u32 arg2,
+		       u32 arg3, u32 arg4);
+
+struct meson_sm_firmware *meson_sm_get_fw(struct device_node *firmware_node);
+
+#endif /* _MESON_SM_H_ */
-- 
2.7.4



From carlo at caione.org  Mon May 23 09:30:23 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 23 May 2016 18:30:23 +0200
Subject: [PATCH v3 3/4] ARM64: dts: amlogic: gxbb: Enable secure monitor
In-Reply-To: <1464021024-29380-1-git-send-email-carlo@caione.org>
References: <1464021024-29380-1-git-send-email-carlo@caione.org>
Message-ID: <1464021024-29380-4-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add the secure monitor node in the Amlogic Meson GXBB DTSI file to
enable it.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 76b3b6d..aeff919 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -44,6 +44,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/gpio/meson-gxbb-gpio.h>
+#include <dt-bindings/firmware/meson-gxbb-sm.h>
 
 / {
 	compatible = "amlogic,meson-gxbb";
@@ -98,6 +99,16 @@
 		method = "smc";
 	};
 
+	firmware {
+		compatible = "simple-bus";
+
+		sm: secure-monitor {
+			compatible = "amlogic,meson-sm";
+			amlogic,sm-cmd-input-base = <SM_GET_SHARE_MEM_INPUT_BASE>;
+			amlogic,sm-cmd-output-base = <SM_GET_SHARE_MEM_OUTPUT_BASE>;
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13
-- 
2.7.4



From carlo at caione.org  Mon May 23 09:30:24 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 23 May 2016 18:30:24 +0200
Subject: [PATCH v3 4/4] documentation: Add secure monitor binding documentation
In-Reply-To: <1464021024-29380-1-git-send-email-carlo@caione.org>
References: <1464021024-29380-1-git-send-email-carlo@caione.org>
Message-ID: <1464021024-29380-5-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add the binding documentation for the Amlogic secure monitor driver.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 .../bindings/firmware/meson/meson_sm.txt           | 51 ++++++++++++++++++++++
 1 file changed, 51 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt

diff --git a/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt b/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
new file mode 100644
index 0000000..2b71716
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
@@ -0,0 +1,51 @@
+* Amlogic Secure Monitor
+
+In the Amlogic SoCs the Secure Monitor code is used to provide access to the
+NVMEM, enable JTAG, set USB boot, etc...
+
+Required properties for the secure monitor node:
+- compatible: Should be "amlogic,meson-sm"
+- amlogic,sm-cmd-input-base: SMC32 function identifier to read the physical
+                             address of the input buffer
+- amlogic,sm-cmd-output-base: SMC32 function identifier to read the physical
+                              address of the output buffer
+
+Example:
+
+	#include <dt-bindings/firmware/meson-gxbb-sm.h>
+
+	...
+
+	firmware {
+		compatible = "simple-bus";
+
+		sm: secure-monitor {
+			compatible = "amlogic,meson-sm";
+			amlogic,sm-cmd-input-base = <SM_GET_SHARE_MEM_INPUT_BASE>;
+			amlogic,sm-cmd-output-base = <SM_GET_SHARE_MEM_OUTPUT_BASE>;
+		};
+	};
+
+Node of a device using the secure monitor must have a custom property to
+specify the SMC32 function the driver is going to use. The values of all the
+SMC function identifiers are listed in a SoC-specific header file:
+
+"include/dt-bindings/firmware/meson-gxbb-sm.h" - for the Meson GXBB secure monitor.
+
+Example of the node using the secure monitor:
+
+	#include <dt-bindings/firmware/meson-gxbb-sm.h>
+
+	...
+
+	efuse: efuse {
+		compatible = "amlogic,meson-gxbb-efuse";
+		secure-monitor = <&sm>;
+		amlogic,sm-cmd-read-efuse = <SM_EFUSE_READ>;
+		amlogic,sm-cmd-max-efuse = <SM_EFUSE_USER_MAX>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		...
+	};
+
-- 
2.7.4



From carlo at caione.org  Mon May 23 09:30:22 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 23 May 2016 18:30:22 +0200
Subject: [PATCH v3 2/4] firmware: dt-bindings: Add secure monitor header file
 for GXBB
In-Reply-To: <1464021024-29380-1-git-send-email-carlo@caione.org>
References: <1464021024-29380-1-git-send-email-carlo@caione.org>
Message-ID: <1464021024-29380-3-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

This patch adds the header file describing all the SMC function
identifiers for the Amlogic Meson GXBB SoC.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 include/dt-bindings/firmware/meson-gxbb-sm.h | 44 ++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)
 create mode 100644 include/dt-bindings/firmware/meson-gxbb-sm.h

diff --git a/include/dt-bindings/firmware/meson-gxbb-sm.h b/include/dt-bindings/firmware/meson-gxbb-sm.h
new file mode 100644
index 0000000..b7d02df
--- /dev/null
+++ b/include/dt-bindings/firmware/meson-gxbb-sm.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MESON_SM_GXBB_H_
+#define _MESON_SM_GXBB_H_
+
+#define SM_GET_SHARE_MEM_INPUT_BASE		0x82000020
+#define SM_GET_SHARE_MEM_OUTPUT_BASE		0x82000021
+#define SM_GET_REBOOT_REASON			0x82000022
+#define SM_GET_SHARE_STORAGE_IN_BASE		0x82000023
+#define SM_GET_SHARE_STORAGE_OUT_BASE		0x82000024
+#define SM_GET_SHARE_STORAGE_BLOCK_BASE		0x82000025
+#define SM_GET_SHARE_STORAGE_MESSAGE_BASE	0x82000026
+#define SM_GET_SHARE_STORAGE_BLOCK_SIZE		0x82000027
+#define SM_EFUSE_READ				0x82000030
+#define SM_EFUSE_WRITE				0x82000031
+#define SM_EFUSE_WRITE_PATTERN			0x82000032
+#define SM_EFUSE_USER_MAX			0x82000033
+#define SM_JTAG_ON				0x82000040
+#define SM_JTAG_OFF				0x82000041
+#define SM_SET_USB_BOOT_FUNC			0x82000043
+#define SM_SECURITY_KEY_QUERY			0x82000060
+#define SM_SECURITY_KEY_READ			0x82000061
+#define SM_SECURITY_KEY_WRITE			0x82000062
+#define SM_SECURITY_KEY_TELL			0x82000063
+#define SM_SECURITY_KEY_VERIFY			0x82000064
+#define SM_SECURITY_KEY_STATUS			0x82000065
+#define SM_SECURITY_KEY_NOTIFY			0x82000066
+#define SM_SECURITY_KEY_LIST			0x82000067
+#define SM_SECURITY_KEY_REMOVE			0x82000068
+#define SM_DEBUG_EFUSE_WRITE_PATTERN		0x820000F0
+#define SM_DEBUG_EFUSE_READ_PATTERN		0x820000F1
+#define SM_AML_DATA_PROCESS			0x820000FF
+
+#endif /* _MESON_SM_GXBB_H_ */
-- 
2.7.4



From mark.rutland at arm.com  Mon May 23 09:38:15 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 23 May 2016 17:38:15 +0100
Subject: [PATCH v3 4/4] documentation: Add secure monitor binding
 documentation
In-Reply-To: <1464021024-29380-5-git-send-email-carlo@caione.org>
References: <1464021024-29380-1-git-send-email-carlo@caione.org>
 <1464021024-29380-5-git-send-email-carlo@caione.org>
Message-ID: <20160523163815.GE4976@leverpostej>

Hi,

Minor nit, but please put the binding earlier in the series than the
code implementing it, as per
Documentation/devicetree/bindings/submitting-patches.txt

This makes it possible to review a series in a linear fashion.

On Mon, May 23, 2016 at 06:30:24PM +0200, Carlo Caione wrote:
> From: Carlo Caione <carlo at endlessm.com>
> 
> Add the binding documentation for the Amlogic secure monitor driver.
> 
> Signed-off-by: Carlo Caione <carlo at endlessm.com>
> ---
>  .../bindings/firmware/meson/meson_sm.txt           | 51 ++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
> 
> diff --git a/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt b/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
> new file mode 100644
> index 0000000..2b71716
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
> @@ -0,0 +1,51 @@
> +* Amlogic Secure Monitor
> +
> +In the Amlogic SoCs the Secure Monitor code is used to provide access to the
> +NVMEM, enable JTAG, set USB boot, etc...
> +
> +Required properties for the secure monitor node:
> +- compatible: Should be "amlogic,meson-sm"
> +- amlogic,sm-cmd-input-base: SMC32 function identifier to read the physical
> +                             address of the input buffer
> +- amlogic,sm-cmd-output-base: SMC32 function identifier to read the physical
> +                              address of the output buffer

Do the IDs for these actually differ per board?

Are some functions simply not implemented on some boards?

> +
> +Example:
> +
> +	#include <dt-bindings/firmware/meson-gxbb-sm.h>
> +
> +	...
> +
> +	firmware {
> +		compatible = "simple-bus";
> +
> +		sm: secure-monitor {
> +			compatible = "amlogic,meson-sm";
> +			amlogic,sm-cmd-input-base = <SM_GET_SHARE_MEM_INPUT_BASE>;
> +			amlogic,sm-cmd-output-base = <SM_GET_SHARE_MEM_OUTPUT_BASE>;
> +		};
> +	};
> +
> +Node of a device using the secure monitor must have a custom property to
> +specify the SMC32 function the driver is going to use. The values of all the
> +SMC function identifiers are listed in a SoC-specific header file:
> +
> +"include/dt-bindings/firmware/meson-gxbb-sm.h" - for the Meson GXBB secure monitor.
> +
> +Example of the node using the secure monitor:
> +
> +	#include <dt-bindings/firmware/meson-gxbb-sm.h>
> +
> +	...
> +
> +	efuse: efuse {
> +		compatible = "amlogic,meson-gxbb-efuse";
> +		secure-monitor = <&sm>;
> +		amlogic,sm-cmd-read-efuse = <SM_EFUSE_READ>;
> +		amlogic,sm-cmd-max-efuse = <SM_EFUSE_USER_MAX>;

Likewise for these?

Mark.

> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +
> +		...
> +	};
> +
> -- 
> 2.7.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


From mark.rutland at arm.com  Mon May 23 09:49:10 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 23 May 2016 17:49:10 +0100
Subject: [PATCH 3/3] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
In-Reply-To: <f0bf43ef-0be5-484c-5066-ab1929105b82@redhat.com>
References: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
 <1463486765-31827-4-git-send-email-aleksey.makarov@linaro.org>
 <20160517124629.GE14955@leverpostej>
 <f0bf43ef-0be5-484c-5066-ab1929105b82@redhat.com>
Message-ID: <20160523164909.GF4976@leverpostej>

On Tue, May 17, 2016 at 12:44:02PM -0400, Jon Masters wrote:
> Hi Mark,
> 
> On 05/17/2016 08:46 AM, Mark Rutland wrote:
> > On Tue, May 17, 2016 at 03:06:03PM +0300, Aleksey Makarov wrote:
> >> From: Jon Masters <jcm at redhat.com>
> >>
> >> This patch adds support for ACPI_TABLE_UPGRADE for ARM64
> > 
> > This feels like a tool to paper over problems rather than solve them.
> 
> Generally, it's an arrow in the quiver used to triage problems, and then
> solve them by getting firmware updates made.

Ok. The feature is _hideously_ misnamed for that purpose, however.

> > If vendors are shipping horrendously broken tables today, clearly no
> > software has ever really supported them. So why add workarounds?
> 
> That's not (always) the case. These patches help with:
> 
> 1). During development of a platform, it is much easier to debug
> problems with tables if you can test replacement ones without having to
> respin the firmware. In the server world, you usually don't have the
> firmware source code, so to get it respun could be days-weeks even if
> you are working with the authors closely. We have practically used this
> feature on a number of platforms already and it will continue.

I was under the impression that that was already possible with GRUB
today (though I see below this may not be the case).

> 2). They empower (advanced) users and developers to work around problems
> that they find on platforms. Sure, we want firmware to always be fixed
> and working well, but it is better if folks have the tools.
> 
> > Why is this necessary? Is there a particular case for this, or is this
> > just for parity with x86?
> 
> The use cases are as above. It's also required for parity with x86
> functionality on servers.

Parity for case 1 above, or is this used in other scenarios on x86
today?

> > IMO it would be better to put pressure on vendors to fix their FW and
> > provide sensible OS-agnostic update mechanisms.
> 
> It's easier to put pressure on them after we know what the problems are.
> I agree that alternative update mechanisms are also good. We also have
> the ability (but it is not implemented on ARM) in GRUB2 to override ACPI
> tables, BUT it's kinda atrophied on all arches and requires that you
> rebuild GRUB with an additional module.

This feels like something that could/should be rectified.

> The reality is that by incorporating this feature we are able to
> provide the same capability that already exists on x86 systems for
> ACPI table triage.

To be clear, I do not disagree that this feature can be useful for that
case. I am just concerned that this is easily abused, and the
description implies a more general set of use cases than we would like.

Thanks,
Mark.


From carlo at caione.org  Mon May 23 09:59:31 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 23 May 2016 18:59:31 +0200
Subject: [PATCH v3 4/4] documentation: Add secure monitor binding
 documentation
In-Reply-To: <20160523163815.GE4976@leverpostej>
References: <1464021024-29380-1-git-send-email-carlo@caione.org>
 <1464021024-29380-5-git-send-email-carlo@caione.org>
 <20160523163815.GE4976@leverpostej>
Message-ID: <20160523165931.GA31299@mephisto>

On 23/05/16 17:38, Mark Rutland wrote:
> Hi,
> 
> Minor nit, but please put the binding earlier in the series than the
> code implementing it, as per
> Documentation/devicetree/bindings/submitting-patches.txt
> 
> This makes it possible to review a series in a linear fashion.

I'll do. Thanks for the pointer.

[...]
> > +
> > +Required properties for the secure monitor node:
> > +- compatible: Should be "amlogic,meson-sm"
> > +- amlogic,sm-cmd-input-base: SMC32 function identifier to read the physical
> > +                             address of the input buffer
> > +- amlogic,sm-cmd-output-base: SMC32 function identifier to read the physical
> > +                              address of the output buffer
> 
> Do the IDs for these actually differ per board?

I expect these to differ per SoC (GXBB in this case), not per board. The
driver is generic enough to be (hopefully) used for several SoCs just
changing the related header file that defines the SCM commands.

> Are some functions simply not implemented on some boards?

I don't think this is possible.

[...]
> > +
> > +Example of the node using the secure monitor:
> > +
> > +	#include <dt-bindings/firmware/meson-gxbb-sm.h>
> > +
> > +	...
> > +
> > +	efuse: efuse {
> > +		compatible = "amlogic,meson-gxbb-efuse";
> > +		secure-monitor = <&sm>;
> > +		amlogic,sm-cmd-read-efuse = <SM_EFUSE_READ>;
> > +		amlogic,sm-cmd-max-efuse = <SM_EFUSE_USER_MAX>;
> 
> Likewise for these?

AFAIK the secure monitor code and related commands are SoC specific.

Thanks,

-- 
Carlo Caione


From maxime.ripard at free-electrons.com  Mon May 23 10:01:29 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 23 May 2016 19:01:29 +0200
Subject: [PATCH 07/16] clk: sunxi-ng: Add phase clock support
In-Reply-To: <CAGb2v661dvdPKj9DWL7LWGgiDCEk7G-a_7jv5gb+KBMoWbR8Lg@mail.gmail.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-8-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v661dvdPKj9DWL7LWGgiDCEk7G-a_7jv5gb+KBMoWbR8Lg@mail.gmail.com>
Message-ID: <20160523170129.GB27618@lukather>

Hi,

On Sun, May 22, 2016 at 12:43:48AM +0800, Chen-Yu Tsai wrote:
> > +static int ccu_phase_set_phase(struct clk_hw *hw, int degrees)
> > +{
> > +       struct ccu_phase *phase = hw_to_ccu_phase(hw);
> > +       struct clk_hw *parent, *pparent;
> > +       unsigned int parent_rate, pparent_rate;
> 
> grandparent(_rate) would be easier to understand.

Ack.

> 
> > +       unsigned long flags;
> > +       u32 reg;
> > +       u8 delay;
> > +
> > +       /* Get our parent clock, it's the one that can adjust its rate */
> > +       parent = clk_hw_get_parent(hw);
> > +       if (!parent)
> > +               return -EINVAL;
> > +
> > +       /* And its rate */
> > +       parent_rate = clk_hw_get_rate(parent);
> > +       if (!parent_rate)
> > +               return -EINVAL;
> > +
> > +       /* Now, get our parent's parent (most likely some PLL) */
> > +       pparent = clk_hw_get_parent(parent);
> > +       if (!pparent)
> > +               return -EINVAL;
> > +
> > +       /* And its rate */
> > +       pparent_rate = clk_hw_get_rate(pparent);
> > +       if (!pparent_rate)
> > +               return -EINVAL;
> > +
> > +       if (degrees != 180) {
> > +               u16 step, parent_div;
> > +
> > +               /* Get our parent divider */
> > +               parent_div = pparent_rate / parent_rate;
> > +
> > +               /*
> > +                * We can only outphase the clocks by multiple of the
> > +                * PLL's period.
> > +                *
> > +                * Since our parent clock is only a divider, and the
> > +                * formula to get the outphasing in degrees is deg =
> > +                * 360 * delta / period
> > +                *
> > +                * If we simplify this formula, we can see that the
> > +                * only thing that we're concerned about is the number
> > +                * of period we want to outphase our clock from, and
> > +                * the divider set by our parent clock.
> > +                */
> > +               step = DIV_ROUND_CLOSEST(360, parent_div);
> > +               delay = DIV_ROUND_CLOSEST(degrees, step);
> 
> Doesn't this mean some delay values are impossible to set?
> 
> For instance, for PLL = 600 MHz and this clock = 50 MHz, div would be 12,
> and a step would be 30 degrees. This means we can't ask for a delay of 6,
> which is 180 degrees.
> 
> For PLL = 600 MHz, clock = 100 MHz, div would be 6, and a step is 60
> degrees. Therefor we can't ask for a delay of 3.

You don't ask for a delay, you ask for an outphasing in degrees. In
the hardware, in the register 0 means an outphasing of 180 degrees
(and this has been confirmed by Allwinner a while back). In the two
cases you point out, we would have two ways of achieving the same
thing, we prefer one over another, but I don't see how it's
problematic.

It's also a direct copy of the current code we have, which didn't
raise any objection, or had any known bugs.

> > +struct ccu_phase {
> > +       u8                      shift;
> > +       u8                      width;
> 
> Not sure why you used struct ccu_factor in the divider table clock,
> but separate fields directly in ccu_phase here.

Because this is not meant for the same thing. ccu_factor is probably
going to go away anyway because of the dividers consolidation.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160523/2ae847cb/attachment-0001.sig>

From sboyd at codeaurora.org  Mon May 23 10:04:16 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Mon, 23 May 2016 10:04:16 -0700
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
In-Reply-To: <4ad1d1b2-f0eb-3780-21e7-9dd1b23d6934@codeaurora.org>
References: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
 <573F7F5C.1050100@codeaurora.org>
 <4ad1d1b2-f0eb-3780-21e7-9dd1b23d6934@codeaurora.org>
Message-ID: <57433810.6000400@codeaurora.org>

On 05/23/2016 08:43 AM, Neil Leeder wrote:
>
> On 5/20/2016 05:19 PM, Stephen Boyd wrote:
>
>>
>> Is there a patch to add sysreg.h to arch/arm? It would be nice to use
>> one l2 accessor API on arm64 and arm.
>>
> Sounds like a good thing for the next person who submits a krait L2 patch to consider.
>

Heh, ok. If it isn't supported in this patch then we need to make the
config depend on ARM64 so that this doesn't fail to compile on ARM.

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



From matthias.bgg at gmail.com  Mon May 23 10:04:14 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 23 May 2016 19:04:14 +0200
Subject: [PATCH v3 0/4] Add Amlogic secure monitor driver
In-Reply-To: <1464021024-29380-1-git-send-email-carlo@caione.org>
References: <1464021024-29380-1-git-send-email-carlo@caione.org>
Message-ID: <5743380E.9010402@gmail.com>



On 23/05/16 18:30, Carlo Caione wrote:
> From: Carlo Caione <carlo at endlessm.com>
>
> In the Amlogic SoCs the secure monitor calls are used for a lot of reasons:
> interact with the NVMEM (efuses), check the reboot reason, set USB boot, ...
>
> This driver defines a generic interface towards the secure monitor that can be
> used by more specialized drivers to interact with the secure monitor itself
> without worrying about bounce buffers managing.
>

For the whole series:
Reviewed-by: Matthias Brugger <matthias.bgg at gmail.com>

> Changelog:
>
> v3:
>    * Moved driver to drivers/firmware
>    * Added EXPORT_SYMBOL macros
>    * Changed '_' in '-'
>    * Introduced 'struct meson_sm_firmware' and 'meson_sm_get_fw()' to be used by
>      drivers using the secure-monitor to enforce probe ordering
>
> v2:
>    * All the SMC function identifiers are now in a SoC-specific header file to
>      be included by the DTS files so the SMC commands are now defined in the DT
>      instead to be hardcoded into the driver
>    * Patchset is no longer an RFC
>    * Better error management and boundary checking
>    * s/unsigned int/u32/
>    * SMC call not only on CPU 0
>    * Fix memory leaking
>    * s/amlogic/meson/ in the directory names
>
>
> Carlo Caione (4):
>    firmware: Amlogic: Add secure monitor driver
>    firmware: dt-bindings: Add secure monitor header file for GXBB
>    ARM64: dts: amlogic: gxbb: Enable secure monitor
>    documentation: Add secure monitor binding documentation
>
>   .../bindings/firmware/meson/meson_sm.txt           |  51 ++++++
>   arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  11 ++
>   drivers/firmware/Kconfig                           |   1 +
>   drivers/firmware/Makefile                          |   1 +
>   drivers/firmware/meson/Kconfig                     |   8 +
>   drivers/firmware/meson/Makefile                    |   1 +
>   drivers/firmware/meson/meson_sm.c                  | 179 +++++++++++++++++++++
>   include/dt-bindings/firmware/meson-gxbb-sm.h       |  44 +++++
>   include/linux/firmware/meson/meson_sm.h            |  38 +++++
>   9 files changed, 334 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
>   create mode 100644 drivers/firmware/meson/Kconfig
>   create mode 100644 drivers/firmware/meson/Makefile
>   create mode 100644 drivers/firmware/meson/meson_sm.c
>   create mode 100644 include/dt-bindings/firmware/meson-gxbb-sm.h
>   create mode 100644 include/linux/firmware/meson/meson_sm.h
>


From mark.rutland at arm.com  Mon May 23 10:11:59 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 23 May 2016 18:11:59 +0100
Subject: [PATCH v3 4/4] documentation: Add secure monitor binding
 documentation
In-Reply-To: <20160523165931.GA31299@mephisto>
References: <1464021024-29380-1-git-send-email-carlo@caione.org>
 <1464021024-29380-5-git-send-email-carlo@caione.org>
 <20160523163815.GE4976@leverpostej>
 <20160523165931.GA31299@mephisto>
Message-ID: <20160523171159.GH4976@leverpostej>

On Mon, May 23, 2016 at 06:59:31PM +0200, Carlo Caione wrote:
> On 23/05/16 17:38, Mark Rutland wrote:
> > > +Required properties for the secure monitor node:
> > > +- compatible: Should be "amlogic,meson-sm"
> > > +- amlogic,sm-cmd-input-base: SMC32 function identifier to read the physical
> > > +                             address of the input buffer
> > > +- amlogic,sm-cmd-output-base: SMC32 function identifier to read the physical
> > > +                              address of the output buffer
> > 
> > Do the IDs for these actually differ per board?
> 
> I expect these to differ per SoC (GXBB in this case), not per board. The
> driver is generic enough to be (hopefully) used for several SoCs just
> changing the related header file that defines the SCM commands.
> 
> > Are some functions simply not implemented on some boards?
> 
> I don't think this is possible.

Given that, I think it may be better to just have a
"amlogic,meson-gxbb-sm" compatible string, and derive the set of
functions and associated IDs from that.

That is, unless you know that future revisions have functions with the
exact same semantics but differing IDs.

Regardless, it would make sense to have a GXBB-specific compatible
string prepended to the list. That way in the future we can handle
anything specific to the GXBB variant of the secure monitor if
necessary.

Thanks,
Mark.


From festevam at gmail.com  Mon May 23 10:13:29 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 23 May 2016 14:13:29 -0300
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAJZ5v0i3h9Jepcxq5xZd1juCWxgOhT1-NBhV9zUXGz4A_j=XeA@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
 <CAOMZO5BBXmXAJayo8YpX4eV-_rTtAoDvjf91CUhWnLV8A0mx0g@mail.gmail.com>
 <CAOMZO5DjgXuYiuOrUdbap3x2PVyUXbp2V1VGnU=2THRSM8Hfow@mail.gmail.com>
 <CAJZ5v0i3h9Jepcxq5xZd1juCWxgOhT1-NBhV9zUXGz4A_j=XeA@mail.gmail.com>
Message-ID: <CAOMZO5Cry5WNnMZ+WYRJNt0i8WHBXViZwijWHaYeJ=GACaWcLA@mail.gmail.com>

On Fri, May 20, 2016 at 10:31 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:

> The patch is just a workaround for a problem in the arch code showing
> up on your platform, though.

Not sure where the problem in the arch code is located though.

Ping, Shawn, Sascha, any ideas?

Thanks


From sudipm.mukherjee at gmail.com  Mon May 23 05:44:08 2016
From: sudipm.mukherjee at gmail.com (Sudip Mukherjee)
Date: Mon, 23 May 2016 18:14:08 +0530
Subject: [PATCH] hwrng: stm32 - fix build warning
Message-ID: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>

We have been getting build warning about:
drivers/char/hw_random/stm32-rng.c: In function 'stm32_rng_read':
drivers/char/hw_random/stm32-rng.c:82:19: warning: 'sr' may be used
					uninitialized in this function

On checking the code it turns out that sr can never be used
uninitialized as sr is getting initialized in the while loop and while
loop will always execute as the minimum value of max can be 32.
So just initialize sr to 0 while declaring it to silence the compiler.

Signed-off-by: Sudip Mukherjee <sudip.mukherjee at codethink.co.uk>
---

build log at:
https://travis-ci.org/sudipm-mukherjee/parport/jobs/132180906

 drivers/char/hw_random/stm32-rng.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 92a8106..0533370 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -52,7 +52,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 {
 	struct stm32_rng_private *priv =
 	    container_of(rng, struct stm32_rng_private, rng);
-	u32 sr;
+	u32 sr = 0;
 	int retval = 0;
 
 	pm_runtime_get_sync((struct device *) priv->rng.priv);
-- 
1.9.1



From maxime.ripard at free-electrons.com  Mon May 23 10:18:45 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 23 May 2016 19:18:45 +0200
Subject: [PATCH 10/16] clk: sunxi-ng: Add M-P factor clock support
In-Reply-To: <CAGb2v67F3UvSCYDTxeLkCJL3FzmcpkogM4RAQgDseXMJDv7bUw@mail.gmail.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-11-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v67F3UvSCYDTxeLkCJL3FzmcpkogM4RAQgDseXMJDv7bUw@mail.gmail.com>
Message-ID: <20160523171845.GC27618@lukather>

Hi,

On Mon, May 23, 2016 at 09:45:16PM +0800, Chen-Yu Tsai wrote:
> Hi,
> 
> On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
> <maxime.ripard at free-electrons.com> wrote:
> > Introduce support for the clocks that combine a linear divider and a
> > power-of-two based one.
> 
> A description or formula in the source code (for those of us that forget)
> would be nice. :)

Ack :)

> 
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/clk/sunxi-ng/Makefile |   1 +
> >  drivers/clk/sunxi-ng/ccu_mp.c | 158 ++++++++++++++++++++++++++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu_mp.h |  79 +++++++++++++++++++++
> >  3 files changed, 238 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_mp.c
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_mp.h
> >
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> > index 063c50f35ad4..09fce7467784 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -5,6 +5,7 @@ obj-y += ccu_div_table.o
> >  obj-y += ccu_fixed_factor.o
> >  obj-y += ccu_gate.o
> >  obj-y += ccu_m.o
> > +obj-y += ccu_mp.o
> >  obj-y += ccu_mux.o
> >  obj-y += ccu_p.o
> >  obj-y += ccu_phase.o
> > diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
> > new file mode 100644
> > index 000000000000..7181188deba7
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_mp.c
> > @@ -0,0 +1,158 @@
> > +/*
> > + * Copyright (C) 2016 Maxime Ripard
> > + * Maxime Ripard <maxime.ripard at free-electrons.com>
> > + *
> > + * 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.
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +
> > +#include "ccu_gate.h"
> > +#include "ccu_mp.h"
> > +
> > +static void ccu_mp_find_best(unsigned long parent, unsigned long rate,
> > +                            unsigned int max_m, unsigned int max_p,
> > +                            unsigned int *m, unsigned int *p)
> > +{
> > +       unsigned long best_rate = 0;
> > +       unsigned int best_m = 0, best_p = 0;
> > +       unsigned int _m, _p;
> > +
> > +       for (_p = 0; _p <= max_p; _p++) {
> > +               for (_m = 1; _m <= max_m; _m++) {
> > +                       unsigned long tmp_rate = (parent >> _p) / _m;
> > +
> > +                       if (tmp_rate > rate)
> > +                               continue;
> > +
> > +                       if ((rate - tmp_rate) < (rate - best_rate)) {
> > +                               best_rate = tmp_rate;
> > +                               best_m = _m;
> > +                               best_p = _p;
> > +                       }
> > +               }
> > +       }
> > +
> > +       *m = best_m;
> > +       *p = best_p;
> > +}
> > +
> > +static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
> > +                                      unsigned long parent_rate,
> > +                                      unsigned long rate,
> > +                                      void *data)
> > +{
> > +       struct ccu_mp *cmp = data;
> > +       unsigned int m, p;
> > +
> > +       ccu_mp_find_best(parent_rate, rate,
> > +                        1 << cmp->m.width, (1 << cmp->p.width) - 1,
> > +                        &m, &p);
> > +
> > +       return (parent_rate >> p) / m;
> > +}
> > +
> > +static void ccu_mp_disable(struct clk_hw *hw)
> > +{
> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> > +
> > +       return ccu_gate_helper_disable(&cmp->common, cmp->enable);
> > +}
> > +
> > +static int ccu_mp_enable(struct clk_hw *hw)
> > +{
> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> > +
> > +       return ccu_gate_helper_enable(&cmp->common, cmp->enable);
> > +}
> > +
> > +static int ccu_mp_is_enabled(struct clk_hw *hw)
> > +{
> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> > +
> > +       return ccu_gate_helper_is_enabled(&cmp->common, cmp->enable);
> > +}
> > +
> > +static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
> > +                                       unsigned long parent_rate)
> > +{
> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> > +       unsigned int m, p;
> > +       u32 reg;
> > +
> > +       reg = readl(cmp->common.base + cmp->common.reg);
> > +
> > +       m = reg >> cmp->m.shift;
> > +       m &= (1 << cmp->m.width) - 1;
> > +
> > +       p = reg >> cmp->p.shift;
> > +       p &= (1 << cmp->p.width) - 1;
> > +
> > +       return (parent_rate >> p) / (m + 1);
> > +}
> > +
> > +static int ccu_mp_determine_rate(struct clk_hw *hw,
> > +                                struct clk_rate_request *req)
> > +{
> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> > +
> > +       return ccu_mux_helper_determine_rate(&cmp->common, &cmp->mux,
> > +                                            req, ccu_mp_round_rate, cmp);
> > +}
> > +
> > +static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
> > +                          unsigned long parent_rate)
> > +{
> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> > +       unsigned long flags;
> > +       unsigned int m, p;
> > +       u32 reg;
> > +
> > +       ccu_mp_find_best(parent_rate, rate,
> > +                        1 << cmp->m.width, (1 << cmp->p.width) - 1,
> > +                        &m, &p);
> > +
> > +
> > +       spin_lock_irqsave(cmp->common.lock, flags);
> > +
> > +       reg = readl(cmp->common.base + cmp->common.reg);
> > +       reg &= ~GENMASK(cmp->m.width + cmp->m.shift, cmp->m.shift);
> > +       reg &= ~GENMASK(cmp->p.width + cmp->p.shift, cmp->p.shift);
> 
> width + shift - 1 ? IIRC GENMASK is inclusive at both ends.

Indeed, will fix.

> 
> > +
> > +       writel(reg | (p << cmp->p.shift) | ((m - 1) << cmp->m.shift),
> > +              cmp->common.base + cmp->common.reg);
> > +
> > +       spin_unlock_irqrestore(cmp->common.lock, flags);
> > +
> > +       return 0;
> > +}
> > +
> > +static u8 ccu_mp_get_parent(struct clk_hw *hw)
> > +{
> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> > +
> > +       return ccu_mux_helper_get_parent(&cmp->common, &cmp->mux);
> > +}
> > +
> > +static int ccu_mp_set_parent(struct clk_hw *hw, u8 index)
> > +{
> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
> > +
> > +       return ccu_mux_helper_set_parent(&cmp->common, &cmp->mux, index);
> > +}
> > +
> > +const struct clk_ops ccu_mp_ops = {
> > +       .disable        = ccu_mp_disable,
> > +       .enable         = ccu_mp_enable,
> > +       .is_enabled     = ccu_mp_is_enabled,
> > +
> > +       .get_parent     = ccu_mp_get_parent,
> > +       .set_parent     = ccu_mp_set_parent,
> > +
> > +       .determine_rate = ccu_mp_determine_rate,
> > +       .recalc_rate    = ccu_mp_recalc_rate,
> > +       .set_rate       = ccu_mp_set_rate,
> > +};
> > diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
> > new file mode 100644
> > index 000000000000..95da9c46cd4f
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_mp.h
> > @@ -0,0 +1,79 @@
> > +/*
> > + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> > + *
> > + * This software is licensed under the terms of the GNU General Public
> > + * License version 2, as published by the Free Software Foundation, and
> > + * may be copied, distributed, and modified under those terms.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef _CCU_MP_H_
> > +#define _CCU_MP_H_
> > +
> > +#include <linux/clk-provider.h>
> > +
> > +#include "ccu_common.h"
> > +#include "ccu_factor.h"
> > +#include "ccu_mux.h"
> > +
> > +struct ccu_mp {
> > +       u32                     enable;
> > +
> > +       struct ccu_factor       m;
> > +       struct ccu_factor       p;
> > +       struct ccu_mux_internal mux;
> > +       struct ccu_common       common;
> > +};
> > +
> > +#define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg,          \
> > +                             _mshift, _mwidth,                         \
> > +                             _pshift, _pwidth,                         \
> > +                             _muxshift, _muxwidth,                     \
> > +                             _flags)                                   \
> > +       struct ccu_mp _struct = {                                       \
> > +               .m      = SUNXI_CLK_FACTOR(_mshift, _mwidth),           \
> > +               .p      = SUNXI_CLK_FACTOR(_pshift, _pwidth),           \
> > +               .mux    = SUNXI_CLK_MUX(_muxshift, _muxwidth),          \
> > +               .common = {                                             \
> > +                       .reg            = _reg,                         \
> > +                       .hw.init        = SUNXI_HW_INIT_PARENTS(_name,  \
> > +                                                               _parents, \
> > +                                                               &ccu_mp_ops, \
> > +                                                               _flags), \
> > +               }                                                       \
> > +       }
> 
> Use the latter to simplify this one?
> 
> > +
> > +#define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,     \
> 
> We could merge _struct with _name ...
> 
> > +                                  _mshift, _mwidth,                    \
> > +                                  _pshift, _pwidth,                    \
> > +                                  _muxshift, _muxwidth,                \
> > +                                  _gate, _flags)                       \
> > +       struct ccu_mp _struct = {                                       \
> 
> and have struct ccu_mp _name##_clk = {

Unfortunately, that prevents to use dashes as clock names, which is
something we've done in the past. Having a separate name allows us to
use whatever we want.

Maxime

---
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160523/f648848f/attachment-0001.sig>

From mark.rutland at arm.com  Mon May 23 10:25:27 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Mon, 23 May 2016 18:25:27 +0100
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
In-Reply-To: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
References: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
Message-ID: <20160523172527.GK4976@leverpostej>

On Fri, May 20, 2016 at 03:13:07PM -0400, Neil Leeder wrote:
> L2 registers are accessed using a select register and data
> register pair. To prevent multiple concurrent writes to the
> select register by independent drivers, the write to the
> select register and the associated access of the data register
> are protected with a lock. All drivers accessing the L2
> registers use the set and get functions provided by
> l2-accessors to ensure correct reads and writes to L2 registers.

What will this be used for? (i.e. which drivers want to touch the L2
registers?).

Generally we expect FW to configure the caches and interconnect
appropriately.

> Signed-off-by: Neil Leeder <nleeder at codeaurora.org>
> ---
>  drivers/soc/qcom/Kconfig              |  9 +++++
>  drivers/soc/qcom/Makefile             |  1 +
>  drivers/soc/qcom/l2-accessors.c       | 66 +++++++++++++++++++++++++++++++++++
>  include/linux/soc/qcom/l2-accessors.h | 27 ++++++++++++++
>  4 files changed, 103 insertions(+)
>  create mode 100644 drivers/soc/qcom/l2-accessors.c
>  create mode 100644 include/linux/soc/qcom/l2-accessors.h

These are awfully generic file names (and function names). Which SoCs
does this apply to?

It would be good to give these more specific names.

> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
> index 461b387..c8498cd 100644
> --- a/drivers/soc/qcom/Kconfig
> +++ b/drivers/soc/qcom/Kconfig
> @@ -10,6 +10,15 @@ config QCOM_GSBI
>            functions for connecting the underlying serial UART, SPI, and I2C
>            devices to the output pins.
>  
> +config QCOM_L2_ACCESSORS
> +	bool "Qualcomm Technologies L2-cache accessors"
> +	depends on ARCH_QCOM
> +	help
> +	  Say y here to enable support for the Qualcomm Technologies
> +	  L2 accessors.
> +	  Provides support for accessing registers in the L2 cache
> +	  for Qualcomm Technologies chips.
> +
>  config QCOM_PM
>  	bool "Qualcomm Power Management"
>  	depends on ARCH_QCOM && !ARM64
> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> index fdd664e..6ef29b9 100644
> --- a/drivers/soc/qcom/Makefile
> +++ b/drivers/soc/qcom/Makefile
> @@ -1,4 +1,5 @@
>  obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
> +obj-$(CONFIG_QCOM_L2_ACCESSORS) += l2-accessors.o
>  obj-$(CONFIG_QCOM_PM)	+=	spm.o
>  obj-$(CONFIG_QCOM_SMD) +=	smd.o
>  obj-$(CONFIG_QCOM_SMD_RPM)	+= smd-rpm.o
> diff --git a/drivers/soc/qcom/l2-accessors.c b/drivers/soc/qcom/l2-accessors.c
> new file mode 100644
> index 0000000..fbb69bd
> --- /dev/null
> +++ b/drivers/soc/qcom/l2-accessors.c
> @@ -0,0 +1,66 @@
> +/*
> + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/spinlock.h>
> +#include <linux/module.h>
> +#include <linux/soc/qcom/l2-accessors.h>
> +#include <asm/cputype.h>
> +#include <asm/sysreg.h>
> +
> +#define	L2CPUSRSELR_EL1	S3_3_c15_c0_6
> +#define	L2CPUSRDR_EL1	S3_3_c15_c0_7
> +
> +static DEFINE_RAW_SPINLOCK(l2_access_lock);
> +
> +/**
> + * set_l2_indirect_reg: write value to an L2 register
> + * @reg: Address of L2 register.
> + * @value: Value to be written to register.
> + *
> + * Use architecturally required barriers for ordering between system register
> + * accesses
> + */
> +void set_l2_indirect_reg(u64 reg, u64 val)
> +{
> +	unsigned long flags;
> +
> +	raw_spin_lock_irqsave(&l2_access_lock, flags);
> +	write_sysreg(reg, L2CPUSRSELR_EL1);
> +	isb();
> +	write_sysreg(val, L2CPUSRDR_EL1);
> +	isb();
> +	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> +}
> +EXPORT_SYMBOL(set_l2_indirect_reg);
> +
> +/**
> + * get_l2_indirect_reg: read an L2 register value
> + * @reg: Address of L2 register.
> + *
> + * Use architecturally required barriers for ordering between system register
> + * accesses
> + */
> +u64 get_l2_indirect_reg(u64 reg)
> +{
> +	u64 val;
> +	unsigned long flags;
> +
> +	raw_spin_lock_irqsave(&l2_access_lock, flags);
> +	write_sysreg(reg, L2CPUSRSELR_EL1);
> +	isb();
> +	val = read_sysreg(L2CPUSRDR_EL1);
> +	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
> +
> +	return val;
> +}
> +EXPORT_SYMBOL(get_l2_indirect_reg);
> diff --git a/include/linux/soc/qcom/l2-accessors.h b/include/linux/soc/qcom/l2-accessors.h
> new file mode 100644
> index 0000000..563c114
> --- /dev/null
> +++ b/include/linux/soc/qcom/l2-accessors.h
> @@ -0,0 +1,27 @@
> +/*
> + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +

> +#ifndef __QCOM_L2_ACCESSORS_H
> +#define __QCOM_L2_ACCESSORS_H
> +
> +#ifdef CONFIG_QCOM_L2_ACCESSORS
> +void set_l2_indirect_reg(u64 reg_addr, u64 val);
> +u64 get_l2_indirect_reg(u64 reg_addr);
> +#else
> +static inline void set_l2_indirect_reg(u64 reg_addr, u64 val) {}
> +static inline u64 get_l2_indirect_reg(u64 reg_addr)
> +{
> +	return 0;
> +}

Surely it would be better to error out on any unintentional use of these
at build time?

Thanks,
Mark.


From austinwc at codeaurora.org  Mon May 23 10:45:51 2016
From: austinwc at codeaurora.org (Christ, Austin)
Date: Mon, 23 May 2016 11:45:51 -0600
Subject: [PATCH v2 2/2] i2c: qup: support SMBus block read
In-Reply-To: <000501d1b271$fef3bc90$fcdb35b0$@codeaurora.org>
References: <1463006736-24652-1-git-send-email-nkaje@codeaurora.org>
 <1463006736-24652-2-git-send-email-nkaje@codeaurora.org>
 <000d01d1b0d3$d70e1f30$852a5d90$@codeaurora.org>
 <757c18e2-562a-9f43-0fb6-ab3e7ac3af88@codeaurora.org>
 <000501d1b271$fef3bc90$fcdb35b0$@codeaurora.org>
Message-ID: <4ca84ab1-f558-25b1-2fa5-dbcf9e8cc2e7@codeaurora.org>



On 5/20/2016 2:31 AM, Sricharan wrote:
> Hi,
>
> <snip..>
>>>> @@ -1128,6 +1173,22 @@ static int qup_i2c_read_one_v2(struct
>>>> qup_i2c_dev *qup, struct i2c_msg *msg)
>>>>    			goto err;
>>>>
>>>>    		qup->blk.pos++;
>>>> +
>>>> +		/* Handle SMBus block read length */
>>>> +		if (qup_i2c_check_msg_len(msg) && (msg->len == 1)) {
>>>> +			if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
>>>> +				ret = -EPROTO;
>>>> +				goto err;
>>>> +			}
>>>> +			msg->len += msg->buf[0];
>>>> +			qup->pos = 0;
>>>> +			qup_i2c_set_read_mode_v2(qup, msg->len);
>>>> +			qup_i2c_issue_xfer_v2(qup, msg);
>>>> +			ret = qup_i2c_wait_for_complete(qup, msg);
>>>> +			if (ret)
>>>> +				goto err;
>>> 		Is the issue_xfer_v2 needed inside this here ?
>> No, qup_i2c_issue_xfer_v2 is needed so that we read rest of the data
>> that is indicated by the length we read earlier.
> So qup_i2c_issue_xfer_v2 writes the tags and there is one already in the loop above this
>   check. So if you just do qup_i2c_set_read_mode_v2 and qup_i2c_set_blk_data inside this
>   check, will not be enough ?
>
> Regards,
>   Sricharan
>
In testing, removing the call to qup_i2c_issue_xfer_v2() within the 
conditional statement for SMBus length causes failures. That transfer 
request is needed to read that block of data.

Thanks,
Austin


From festevam at gmail.com  Mon May 23 10:49:12 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 23 May 2016 14:49:12 -0300
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
Message-ID: <CAOMZO5C5goJUdHKB9a=eOv9TKDkJWxnkWWb-G7E5Kvceg6sZVg@mail.gmail.com>

On Sun, May 22, 2016 at 7:47 PM,  <christopher.spinrath at rwth-aachen.de> wrote:

> diff --git a/arch/arm/boot/dts/imx6q-utilite-pro.dts b/arch/arm/boot/dts/imx6q-utilite-pro.dts
> new file mode 100644
> index 0000000..bcd8e0d
> --- /dev/null
> +++ b/arch/arm/boot/dts/imx6q-utilite-pro.dts
> @@ -0,0 +1,128 @@
> +/*
> + * Copyright 2016 Christopher Spinrath
> + * Copyright 2013 CompuLab Ltd.
> + *
> + * Based on the GPLv2 licensed devicetree distributed with the vendor
> + * kernel for the Utilite Pro:
> + *     Copyright 2013 CompuLab Ltd.
> + *     Author: Valentin Raevsky <valentin at compulab.co.il>
> + *
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:

Can you make this dual GPL/X11 license?

For reference take a look at:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/imx6sl-warp.dts?id=refs/tags/v4.6


> +       gpio-keys {
> +               compatible = "gpio-keys";
> +               power {
> +                       label = "Power Button";
> +                       gpios = <&gpio1 29 1>;

Better to use a label like:
gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;

> +&iomuxc {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_hog>;
> +
> +       hog {
> +               pinctrl_hog: hoggrp {
> +                       fsl,pins = <
> +                               /* power button */
> +                               MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000

Better to avoid 0x80000000. Replace it with the real iomux value
instead so that you don't need to rely on the bootloader
configuration.

> +
> +       imx6q-utilite-pro {
> +               pinctrl_i2c1: i2c1grp {
> +                       fsl,pins = <
> +                               MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
> +                               MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
> +                       >;
> +               };

You should better remove one level of indentation. Check this commit
for reference:
https://git.kernel.org/cgit/linux/kernel/git/shawnguo/linux.git/commit/arch/arm/boot/dts/imx6q-tbs2910.dts?h=for-next&id=aa7871b53bc3c36b4adefe67f728143e2deeec93

> +&uart2 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_uart2>;
> +       fsl,uart-has-rtscts;
> +       dma-names = "rx", "tx";
> +       dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;

No need to add the dma nodes as they are already present in imx6qdl.dtsi.


From broonie at kernel.org  Mon May 23 10:50:54 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 23 May 2016 18:50:54 +0100
Subject: Applied "regulator: mt6397: Constify struct regulator_ops" to the
 regulator tree
In-Reply-To: <1463988616-18803-1-git-send-email-henryc.chen@mediatek.com>
Message-ID: <E1b4u0E-0006j4-3g@debutante>

The patch

   regulator: mt6397: Constify struct regulator_ops

has been applied to the regulator tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 7e3fc9960169ec5eab0ec6810fa24518ea3f3608 Mon Sep 17 00:00:00 2001
From: Henry Chen <henryc.chen at mediatek.com>
Date: Mon, 23 May 2016 15:30:16 +0800
Subject: [PATCH] regulator: mt6397: Constify struct regulator_ops

Consitify the structure of regulator operations.

Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 drivers/regulator/mt6397-regulator.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c
index 17a5b6c2d6a9..1c45abb94409 100644
--- a/drivers/regulator/mt6397-regulator.c
+++ b/drivers/regulator/mt6397-regulator.c
@@ -160,7 +160,7 @@ static int mt6397_get_status(struct regulator_dev *rdev)
 	return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
 }
 
-static struct regulator_ops mt6397_volt_range_ops = {
+static const struct regulator_ops mt6397_volt_range_ops = {
 	.list_voltage = regulator_list_voltage_linear_range,
 	.map_voltage = regulator_map_voltage_linear_range,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -172,7 +172,7 @@ static struct regulator_ops mt6397_volt_range_ops = {
 	.get_status = mt6397_get_status,
 };
 
-static struct regulator_ops mt6397_volt_table_ops = {
+static const struct regulator_ops mt6397_volt_table_ops = {
 	.list_voltage = regulator_list_voltage_table,
 	.map_voltage = regulator_map_voltage_iterate,
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -184,7 +184,7 @@ static struct regulator_ops mt6397_volt_table_ops = {
 	.get_status = mt6397_get_status,
 };
 
-static struct regulator_ops mt6397_volt_fixed_ops = {
+static const struct regulator_ops mt6397_volt_fixed_ops = {
 	.list_voltage = regulator_list_voltage_linear,
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
-- 
2.8.1



From broonie at kernel.org  Mon May 23 10:50:50 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 23 May 2016 18:50:50 +0100
Subject: Applied "regulator: mt6397: Add buck change mode regulator interface
 for mt6397" to the regulator tree
In-Reply-To: <1463987611-32139-4-git-send-email-henryc.chen@mediatek.com>
Message-ID: <E1b4u0A-0006i6-Eg@debutante>

The patch

   regulator: mt6397: Add buck change mode regulator interface for mt6397

has been applied to the regulator tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 6d26507bd45bf09374d3744ee07fabebc87266f5 Mon Sep 17 00:00:00 2001
From: Henry Chen <henryc.chen at mediatek.com>
Date: Mon, 23 May 2016 15:13:31 +0800
Subject: [PATCH] regulator: mt6397: Add buck change mode regulator interface
 for mt6397

BUCKs of mt6397 have auto mode and pwm mode.
User can use regulator interfaces to control modes

Signed-off-by: Henry Chen <henryc.chen at mediatek.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 drivers/regulator/mt6397-regulator.c | 89 ++++++++++++++++++++++++++++++++----
 1 file changed, 80 insertions(+), 9 deletions(-)

diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c
index 1c45abb94409..c6c6aa85e4e8 100644
--- a/drivers/regulator/mt6397-regulator.c
+++ b/drivers/regulator/mt6397-regulator.c
@@ -23,6 +23,9 @@
 #include <linux/regulator/mt6397-regulator.h>
 #include <linux/regulator/of_regulator.h>
 
+#define MT6397_BUCK_MODE_AUTO	0
+#define MT6397_BUCK_MODE_FORCE_PWM	1
+
 /*
  * MT6397 regulators' information
  *
@@ -38,10 +41,14 @@ struct mt6397_regulator_info {
 	u32 vselon_reg;
 	u32 vselctrl_reg;
 	u32 vselctrl_mask;
+	u32 modeset_reg;
+	u32 modeset_mask;
+	u32 modeset_shift;
 };
 
 #define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg,	\
-		vosel, vosel_mask, voselon, vosel_ctrl)			\
+		vosel, vosel_mask, voselon, vosel_ctrl, _modeset_reg,	\
+		_modeset_shift)					\
 [MT6397_ID_##vreg] = {							\
 	.desc = {							\
 		.name = #vreg,						\
@@ -62,6 +69,9 @@ struct mt6397_regulator_info {
 	.vselon_reg = voselon,						\
 	.vselctrl_reg = vosel_ctrl,					\
 	.vselctrl_mask = BIT(1),					\
+	.modeset_reg = _modeset_reg,					\
+	.modeset_mask = BIT(_modeset_shift),				\
+	.modeset_shift = _modeset_shift					\
 }
 
 #define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel,	\
@@ -145,6 +155,63 @@ static const u32 ldo_volt_table7[] = {
 	1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,
 };
 
+static int mt6397_regulator_set_mode(struct regulator_dev *rdev,
+				     unsigned int mode)
+{
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret, val;
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		val = MT6397_BUCK_MODE_FORCE_PWM;
+		break;
+	case REGULATOR_MODE_NORMAL:
+		val = MT6397_BUCK_MODE_AUTO;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err_mode;
+	}
+
+	dev_dbg(&rdev->dev, "mt6397 buck set_mode %#x, %#x, %#x, %#x\n",
+		info->modeset_reg, info->modeset_mask,
+		info->modeset_shift, val);
+
+	val <<= info->modeset_shift;
+	ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
+				 info->modeset_mask, val);
+err_mode:
+	if (ret != 0) {
+		dev_err(&rdev->dev,
+			"Failed to set mt6397 buck mode: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static unsigned int mt6397_regulator_get_mode(struct regulator_dev *rdev)
+{
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret, regval;
+
+	ret = regmap_read(rdev->regmap, info->modeset_reg, &regval);
+	if (ret != 0) {
+		dev_err(&rdev->dev,
+			"Failed to get mt6397 buck mode: %d\n", ret);
+		return ret;
+	}
+
+	switch ((regval & info->modeset_mask) >> info->modeset_shift) {
+	case MT6397_BUCK_MODE_AUTO:
+		return REGULATOR_MODE_NORMAL;
+	case MT6397_BUCK_MODE_FORCE_PWM:
+		return REGULATOR_MODE_FAST;
+	default:
+		return -EINVAL;
+	}
+}
+
 static int mt6397_get_status(struct regulator_dev *rdev)
 {
 	int ret;
@@ -170,6 +237,8 @@ static const struct regulator_ops mt6397_volt_range_ops = {
 	.disable = regulator_disable_regmap,
 	.is_enabled = regulator_is_enabled_regmap,
 	.get_status = mt6397_get_status,
+	.set_mode = mt6397_regulator_set_mode,
+	.get_mode = mt6397_regulator_get_mode,
 };
 
 static const struct regulator_ops mt6397_volt_table_ops = {
@@ -196,28 +265,30 @@ static const struct regulator_ops mt6397_volt_fixed_ops = {
 static struct mt6397_regulator_info mt6397_regulators[] = {
 	MT6397_BUCK("buck_vpca15", VPCA15, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VCA15_CON7, MT6397_VCA15_CON9, 0x7f,
-		MT6397_VCA15_CON10, MT6397_VCA15_CON5),
+		MT6397_VCA15_CON10, MT6397_VCA15_CON5, MT6397_VCA15_CON2, 11),
 	MT6397_BUCK("buck_vpca7", VPCA7, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VPCA7_CON7, MT6397_VPCA7_CON9, 0x7f,
-		MT6397_VPCA7_CON10, MT6397_VPCA7_CON5),
+		MT6397_VPCA7_CON10, MT6397_VPCA7_CON5, MT6397_VPCA7_CON2, 8),
 	MT6397_BUCK("buck_vsramca15", VSRAMCA15, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VSRMCA15_CON7, MT6397_VSRMCA15_CON9,
-		0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5),
+		0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5,
+		MT6397_VSRMCA15_CON2, 8),
 	MT6397_BUCK("buck_vsramca7", VSRAMCA7, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VSRMCA7_CON7, MT6397_VSRMCA7_CON9,
-		0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5),
+		0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5,
+		MT6397_VSRMCA7_CON2, 8),
 	MT6397_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250,
 		buck_volt_range1, MT6397_VCORE_CON7, MT6397_VCORE_CON9, 0x7f,
-		MT6397_VCORE_CON10, MT6397_VCORE_CON5),
+		MT6397_VCORE_CON10, MT6397_VCORE_CON5, MT6397_VCORE_CON2, 8),
 	MT6397_BUCK("buck_vgpu", VGPU, 700000, 1493750, 6250, buck_volt_range1,
 		MT6397_VGPU_CON7, MT6397_VGPU_CON9, 0x7f,
-		MT6397_VGPU_CON10, MT6397_VGPU_CON5),
+		MT6397_VGPU_CON10, MT6397_VGPU_CON5, MT6397_VGPU_CON2, 8),
 	MT6397_BUCK("buck_vdrm", VDRM, 800000, 1593750, 6250, buck_volt_range2,
 		MT6397_VDRM_CON7, MT6397_VDRM_CON9, 0x7f,
-		MT6397_VDRM_CON10, MT6397_VDRM_CON5),
+		MT6397_VDRM_CON10, MT6397_VDRM_CON5, MT6397_VDRM_CON2, 8),
 	MT6397_BUCK("buck_vio18", VIO18, 1500000, 2120000, 20000,
 		buck_volt_range3, MT6397_VIO18_CON7, MT6397_VIO18_CON9, 0x1f,
-		MT6397_VIO18_CON10, MT6397_VIO18_CON5),
+		MT6397_VIO18_CON10, MT6397_VIO18_CON5, MT6397_VIO18_CON2, 8),
 	MT6397_REG_FIXED("ldo_vtcxo", VTCXO, MT6397_ANALDO_CON0, 10, 2800000),
 	MT6397_REG_FIXED("ldo_va28", VA28, MT6397_ANALDO_CON1, 14, 2800000),
 	MT6397_LDO("ldo_vcama", VCAMA, ldo_volt_table1,
-- 
2.8.1



From lorenzo.pieralisi at arm.com  Mon May 23 10:56:32 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Mon, 23 May 2016 18:56:32 +0100
Subject: [PATCH 3/3] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
In-Reply-To: <b0933a59-239d-536f-4f63-a65e469f62a1@redhat.com>
References: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
 <1463486765-31827-4-git-send-email-aleksey.makarov@linaro.org>
 <20160517124629.GE14955@leverpostej>
 <f0bf43ef-0be5-484c-5066-ab1929105b82@redhat.com>
 <b0933a59-239d-536f-4f63-a65e469f62a1@redhat.com>
Message-ID: <20160523175632.GA16456@red-moon>

On Tue, May 17, 2016 at 12:48:53PM -0400, Jon Masters wrote:
> On 05/17/2016 12:44 PM, Jon Masters wrote:
> 
> > 1). During development of a platform, it is much easier to debug
> > problems with tables if you can test replacement ones without having to
> > respin the firmware. In the server world, you usually don't have the
> > firmware source code, so to get it respun could be days-weeks even if
> > you are working with the authors closely. We have practically used this
> > feature on a number of platforms already and it will continue.
> 
> For example, on one platform we were unable to fully boot RHEL(SA) due
> to a bug in one of the ACPI tables. But I was able to boot the system to
> a ramdisk containing a uuencode library and then write out the content
> of the tables over the serial port, then decompile/patch/recompile, and
> override replacement tables on the system. Then we beat the vendor up
> with the fixes and the official firmware was corrected.

Can you explain to me please why you can't do it with GRUB ?

I am using mainline GRUB and its acpi command all the time to update
static ACPI tables for testing new features (ie IORT) and it works
just fine for me (and you can still override the DSDT, which is
likely to be the main source of bugs, through the CONFIG_ACPI_CUSTOM_DSDT
config option, that works on ARM in mainline with no changes required).

I just want to understand if there is really a compelling reason
for adding this stuff when we can easily implement its features
through something that is usable today without any kernel changes.

Thanks,
Lorenzo


From nleeder at codeaurora.org  Mon May 23 11:12:50 2016
From: nleeder at codeaurora.org (Neil Leeder)
Date: Mon, 23 May 2016 14:12:50 -0400
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
In-Reply-To: <57433810.6000400@codeaurora.org>
References: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
 <573F7F5C.1050100@codeaurora.org>
 <4ad1d1b2-f0eb-3780-21e7-9dd1b23d6934@codeaurora.org>
 <57433810.6000400@codeaurora.org>
Message-ID: <5738cfe3-4299-703f-52c9-24f6e6a58adc@codeaurora.org>



On 5/23/2016 01:04 PM, Stephen Boyd wrote:
> On 05/23/2016 08:43 AM, Neil Leeder wrote:
>>
>> On 5/20/2016 05:19 PM, Stephen Boyd wrote:
>>
>>>
>>> Is there a patch to add sysreg.h to arch/arm? It would be nice to use
>>> one l2 accessor API on arm64 and arm.
>>>
>> Sounds like a good thing for the next person who submits a krait L2 patch to consider.
>>
> 
> Heh, ok. If it isn't supported in this patch then we need to make the
> config depend on ARM64 so that this doesn't fail to compile on ARM.
> 

Ok, I'll add that in v2 too.

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


From nleeder at codeaurora.org  Mon May 23 11:22:59 2016
From: nleeder at codeaurora.org (Neil Leeder)
Date: Mon, 23 May 2016 14:22:59 -0400
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
In-Reply-To: <20160523172527.GK4976@leverpostej>
References: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
 <20160523172527.GK4976@leverpostej>
Message-ID: <f49d58ed-38b4-6284-11c2-8708d8443b14@codeaurora.org>


On 5/23/2016 01:25 PM, Mark Rutland wrote:
> On Fri, May 20, 2016 at 03:13:07PM -0400, Neil Leeder wrote:
>> L2 registers are accessed using a select register and data
>> register pair. To prevent multiple concurrent writes to the
>> select register by independent drivers, the write to the
>> select register and the associated access of the data register
>> are protected with a lock. All drivers accessing the L2
>> registers use the set and get functions provided by
>> l2-accessors to ensure correct reads and writes to L2 registers.
> 
> What will this be used for? (i.e. which drivers want to touch the L2
> registers?).
> 
> Generally we expect FW to configure the caches and interconnect
> appropriately.

The primary use is in the L2 PMU driver, which will be posted shortly.

> 
>> Signed-off-by: Neil Leeder <nleeder at codeaurora.org>
>> ---
>>  drivers/soc/qcom/Kconfig              |  9 +++++
>>  drivers/soc/qcom/Makefile             |  1 +
>>  drivers/soc/qcom/l2-accessors.c       | 66 +++++++++++++++++++++++++++++++++++
>>  include/linux/soc/qcom/l2-accessors.h | 27 ++++++++++++++
>>  4 files changed, 103 insertions(+)
>>  create mode 100644 drivers/soc/qcom/l2-accessors.c
>>  create mode 100644 include/linux/soc/qcom/l2-accessors.h
> 
> These are awfully generic file names (and function names). Which SoCs
> does this apply to?
> 
> It would be good to give these more specific names.

It's under soc/qcom, and dependent on ARCH_QCOM and (in v2) also on ARM64. It applies to all QCOM ARM64 SoCs.
Given that it can only be used in a QCOM driver, and the include path has qcom in it, I'd
prefer not to add redundancy by adding another qcom in there.

>> diff --git a/include/linux/soc/qcom/l2-accessors.h b/include/linux/soc/qcom/l2-accessors.h
>> new file mode 100644
>> index 0000000..563c114
>> --- /dev/null
>> +++ b/include/linux/soc/qcom/l2-accessors.h
>> @@ -0,0 +1,27 @@
>> +/*
>> + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 and
>> + * only version 2 as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
> 
>> +#ifndef __QCOM_L2_ACCESSORS_H
>> +#define __QCOM_L2_ACCESSORS_H
>> +
>> +#ifdef CONFIG_QCOM_L2_ACCESSORS
>> +void set_l2_indirect_reg(u64 reg_addr, u64 val);
>> +u64 get_l2_indirect_reg(u64 reg_addr);
>> +#else
>> +static inline void set_l2_indirect_reg(u64 reg_addr, u64 val) {}
>> +static inline u64 get_l2_indirect_reg(u64 reg_addr)
>> +{
>> +	return 0;
>> +}
> 
> Surely it would be better to error out on any unintentional use of these
> at build time?

This allows building code which is common to ARM SoCs and QCOM SoCs without having to ifdef out the
QCOM-specific pieces.

> 
> Thanks,
> Mark.
> 

Thanks,
Neil

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


From linux at armlinux.org.uk  Mon May 23 11:28:07 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Mon, 23 May 2016 19:28:07 +0100
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <2148724.oQlEHos3jS@vostro.rjw.lan>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
Message-ID: <20160523182807.GY19428@n2100.arm.linux.org.uk>

On Sat, May 21, 2016 at 02:56:20AM +0200, Rafael J. Wysocki wrote:
> The root of the problem seems to be arch_irq_work_raise() and specifically
> the __smp_cross_call function that appears to have problems.

We've been through this before.  The bottom line is that on ARM, there
is major wide-spread understanding that we want to be able to run a
kernel compiled for SMP on uniprocessor hardware.

This is something that's been going for years, and has worked fine for
years.

Now, someone has introduced this irq work stuff.  Great.  But they
haven't considered that people want to be able to run a SMP kernel
on UP hardware which _may_ have no hardware present which is capable
of raising IPIs.

I don't know what the situation is with the platform concerned here,
I don't know whether it uses the GIC (presumably, because it doesn't
NULL-pointer ref on calling smp_cross_call(), it is using the GIC.)
If so, the GIC isn't delivering the IPI because the IPI hardware is
missing.

Now, whether we could detect whether the GIC is IPI capable, I've
no idea, I don't have such a platform I could run tests on.  People
don't give me hardware anymore now that arm-soc is split off from
core ARM maintanence - it all goes into Linaro build farms.  So I'm
powerless to help here.

My attitude towards this is that it's a core kernel problem: the
core kernel is assuming that it can raise IPIs even on non-SMP
capable hardware.  Much non-SMP hardware doesn't have that ability.
While folk can try to push it into arch code, my feeling is that it
really needs to have a generic solution, even if it's some generic
solution that architectures in this situation can plug into.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From jcm at redhat.com  Mon May 23 11:29:06 2016
From: jcm at redhat.com (Jon Masters)
Date: Mon, 23 May 2016 14:29:06 -0400
Subject: [PATCH 3/3] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
In-Reply-To: <20160523175632.GA16456@red-moon>
References: <1463486765-31827-1-git-send-email-aleksey.makarov@linaro.org>
 <1463486765-31827-4-git-send-email-aleksey.makarov@linaro.org>
 <20160517124629.GE14955@leverpostej>
 <f0bf43ef-0be5-484c-5066-ab1929105b82@redhat.com>
 <b0933a59-239d-536f-4f63-a65e469f62a1@redhat.com>
 <20160523175632.GA16456@red-moon>
Message-ID: <401c89a2-5dde-a4ae-6791-ccab7b4d366f@redhat.com>

On 05/23/2016 01:56 PM, Lorenzo Pieralisi wrote:
> On Tue, May 17, 2016 at 12:48:53PM -0400, Jon Masters wrote:
>> On 05/17/2016 12:44 PM, Jon Masters wrote:
>>
>>> 1). During development of a platform, it is much easier to debug
>>> problems with tables if you can test replacement ones without having to
>>> respin the firmware. In the server world, you usually don't have the
>>> firmware source code, so to get it respun could be days-weeks even if
>>> you are working with the authors closely. We have practically used this
>>> feature on a number of platforms already and it will continue.
>>
>> For example, on one platform we were unable to fully boot RHEL(SA) due
>> to a bug in one of the ACPI tables. But I was able to boot the system to
>> a ramdisk containing a uuencode library and then write out the content
>> of the tables over the serial port, then decompile/patch/recompile, and
>> override replacement tables on the system. Then we beat the vendor up
>> with the fixes and the official firmware was corrected.
> 
> Can you explain to me please why you can't do it with GRUB ?

It's doable with GRUB (if you rebuild GRUB modules to include it)

> I am using mainline GRUB and its acpi command all the time to update
> static ACPI tables for testing new features (ie IORT) and it works
> just fine for me (and you can still override the DSDT, which is
> likely to be the main source of bugs, through the CONFIG_ACPI_CUSTOM_DSDT
> config option, that works on ARM in mainline with no changes required).
> 
> I just want to understand if there is really a compelling reason
> for adding this stuff when we can easily implement its features
> through something that is usable today without any kernel changes.

We're looking for x86 feature parity in the base platform. Every time
there's a gratuitous differentiation it's a waste of time for folks
trying to figure out what is different on an ARM system. So if we
completely remove the ACPI override feature from the kernel and make
everyone use GRUB instead, then fine, but ARM shouldn't be special.

Jon.

-- 
Computer Architect | Sent from my Fedora powered laptop



From khilman at kernel.org  Mon May 23 12:26:10 2016
From: khilman at kernel.org (Kevin Hilman)
Date: Mon, 23 May 2016 12:26:10 -0700
Subject: [Patch v5 5/8] firmware: qcom: scm: Convert to streaming DMA APIS
In-Reply-To: <1463111221-6963-6-git-send-email-andy.gross@linaro.org>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
 <1463111221-6963-6-git-send-email-andy.gross@linaro.org>
Message-ID: <CAOi56cVB1Z-gO6Dx0KOSr9wiRF3Y9ahDHe0=qT9WW4MdFMhjng@mail.gmail.com>

Hi Andy,

On Thu, May 12, 2016 at 8:46 PM, Andy Gross <andy.gross at linaro.org> wrote:
> This patch converts the Qualcomm SCM driver to use the streaming DMA APIs
> for communication buffers.
>
> Signed-off-by: Andy Gross <andy.gross at linaro.org>

This patch has landed in linux-next in the form of commit a551c3dbd689
(firmware: qcom: scm: Convert to streaming DMA APIS), and kernelci.org
found some boot breakage in next-20160523 on apq8064[1] which was
bisected down to this commit.

I reverted this commit on top of next-20160523 and it no longer
builds, so I didn't validate if things boot again with this patch
reverted.

Kevin

[1] https://kernelci.org/boot/all/job/next/kernel/next-20160523/


From robin.murphy at arm.com  Mon May 23 12:31:45 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Mon, 23 May 2016 20:31:45 +0100
Subject: [PATCH v2 4/5] iommu/mediatek: add support for mtk iommu
 generation one HW
In-Reply-To: <1463658558-567-5-git-send-email-honghui.zhang@mediatek.com>
References: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
 <1463658558-567-5-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <57435AA1.3090602@arm.com>

On 19/05/16 12:49, honghui.zhang at mediatek.com wrote:
> From: Honghui Zhang <honghui.zhang at mediatek.com>
>
> Mediatek SoC's M4U has two generations of HW architcture. Generation one
> uses flat, one layer pagetable, and was shipped with ARM architecture, it
> only supports 4K size page mapping. MT2701 SoC uses this generation one
> m4u HW. Generation two uses the ARM short-descriptor translation table
> format for address translation, and was shipped with ARM64 architecture,
> MT8173 uses this generation two m4u HW. All the two generation iommu HW
> only have one iommu domain, and all its iommu clients share the same
> iova address.
>
> These two generation m4u HW have slit different register groups and
> register offset, but most register names are the same. This patch add iommu
> support for mediatek SoC mt2701.
>
> Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
> ---
>   drivers/iommu/Kconfig        |  19 ++
>   drivers/iommu/Makefile       |   1 +
>   drivers/iommu/mtk_iommu.h    |   3 +
>   drivers/iommu/mtk_iommu_v1.c | 742 +++++++++++++++++++++++++++++++++++++++++++
>   4 files changed, 765 insertions(+)
>   create mode 100644 drivers/iommu/mtk_iommu_v1.c
>
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index dd1dc39..2e17d70 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -354,4 +354,23 @@ config MTK_IOMMU
>
>   	  If unsure, say N here.
>
> +config MTK_IOMMU_V1
> +	bool "MTK IOMMU Version 1 (M4U gen1) Support"
> +	depends on ARM || ARM64

The commit message states that gen1 shipped in 32-bit hardware, and 
64-bit hardware has gen2, which implies that ARM64 here is unnecessary - 
does any SoC with 64-bit-capable CPUs and a gen1 IOMMU actually exist?

> +	depends on ARCH_MEDIATEK || COMPILE_TEST
> +	select ARM_DMA_USE_IOMMU
> +	select IOMMU_API
> +	select IOMMU_DMA

Either way you don't need this - arm64 already selects it as necessary, 
and it's not used on 32-bit.

> +	select MEMORY
> +	select MTK_SMI
> +	select COMMON_CLK_MT2701_MMSYS
> +	select COMMON_CLK_MT2701_IMGSYS
> +	select COMMON_CLK_MT2701_VDECSYS
> +	help
> +	  Support for the M4U on certain Mediatek SoCs. M4U generation 1 HW is
> +	  Multimedia Memory Managememt Unit. This option enables remapping of
> +	  DMA memory accesses for the multimedia subsystem.
> +
> +	  if unsure, say N here.
> +
>   endif # IOMMU_SUPPORT
> diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
> index c6edb31..778baf5 100644
> --- a/drivers/iommu/Makefile
> +++ b/drivers/iommu/Makefile
> @@ -18,6 +18,7 @@ obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
>   obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
>   obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
>   obj-$(CONFIG_MTK_IOMMU) += mtk_iommu.o
> +obj-$(CONFIG_MTK_IOMMU_V1) += mtk_iommu_v1.o
>   obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
>   obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
>   obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index 5656355..8d60f21 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -48,6 +48,9 @@ struct mtk_iommu_domain {
>   	struct io_pgtable_ops		*iop;
>
>   	struct iommu_domain		domain;
> +	void				*pgt_va;
> +	dma_addr_t			pgt_pa;
> +	void				*cookie;

These are going to be mutually exclusive with the cfg and iop members, 
which implies it might be a good idea to use a union and not waste 
space. Or better, just forward-declare struct mtk_iommu_domain here and 
leave separate definitions private to each driver. The void *cookie is 
also an unnecessary level of abstraction, I think.

>   };
>
>   struct mtk_iommu_data {
> diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
> new file mode 100644
> index 0000000..55023e1
> --- /dev/null
> +++ b/drivers/iommu/mtk_iommu_v1.c
> @@ -0,0 +1,742 @@
> +/*
> + * Copyright (c) 2015-2016 MediaTek Inc.
> + * Author: Yong Wu <yong.wu at mediatek.com>

Nit: is that in the sense that this patch should also have Yong's 
signed-off-by on it, or in that it's your work derived from his version 
in mtk_iommu.c?

> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +#include <linux/bootmem.h>
> +#include <linux/bug.h>
> +#include <linux/clk.h>
> +#include <linux/component.h>
> +#include <linux/device.h>
> +#include <linux/dma-iommu.h>
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/iommu.h>
> +#include <linux/iopoll.h>
> +#include <linux/kmemleak.h>
> +#include <linux/list.h>
> +#include <linux/of_address.h>
> +#include <linux/of_iommu.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <asm/barrier.h>
> +#include <asm/dma-iommu.h>
> +#include <linux/module.h>
> +#include <dt-bindings/memory/mt2701-larb-port.h>
> +#include <soc/mediatek/smi.h>
> +#include "mtk_iommu.h"
> +
> +#define REG_MMU_PT_BASE_ADDR			0x000
> +
> +#define F_ALL_INVLD				0x2
> +#define F_MMU_INV_RANGE				0x1
> +#define F_INVLD_EN0				BIT(0)
> +#define F_INVLD_EN1				BIT(1)
> +
> +#define F_MMU_FAULT_VA_MSK			0xfffff000
> +#define MTK_PROTECT_PA_ALIGN			128
> +
> +#define REG_MMU_CTRL_REG			0x210
> +#define F_MMU_CTRL_COHERENT_EN			BIT(8)
> +#define REG_MMU_IVRP_PADDR			0x214
> +#define REG_MMU_INT_CONTROL			0x220
> +#define F_INT_TRANSLATION_FAULT			BIT(0)
> +#define F_INT_MAIN_MULTI_HIT_FAULT		BIT(1)
> +#define F_INT_INVALID_PA_FAULT			BIT(2)
> +#define F_INT_ENTRY_REPLACEMENT_FAULT		BIT(3)
> +#define F_INT_TABLE_WALK_FAULT			BIT(4)
> +#define F_INT_TLB_MISS_FAULT			BIT(5)
> +#define F_INT_PFH_DMA_FIFO_OVERFLOW		BIT(6)
> +#define F_INT_MISS_DMA_FIFO_OVERFLOW		BIT(7)
> +
> +#define F_MMU_TF_PROTECT_SEL(prot)		(((prot) & 0x3) << 5)
> +#define F_INT_CLR_BIT				BIT(12)
> +
> +#define REG_MMU_FAULT_ST			0x224
> +#define REG_MMU_FAULT_VA			0x228
> +#define REG_MMU_INVLD_PA			0x22C
> +#define REG_MMU_INT_ID				0x388
> +#define REG_MMU_INVALIDATE			0x5c0
> +#define REG_MMU_INVLD_START_A			0x5c4
> +#define REG_MMU_INVLD_END_A			0x5c8
> +
> +#define REG_MMU_INV_SEL				0x5d8
> +#define REG_MMU_STANDARD_AXI_MODE		0x5e8
> +
> +#define REG_MMU_DCM				0x5f0
> +#define F_MMU_DCM_ON				BIT(1)
> +#define REG_MMU_CPE_DONE			0x60c
> +#define F_DESC_VALID				0x2
> +#define F_DESC_NONSEC				BIT(3)
> +#define MT2701_M4U_TF_LARB(TF)			(6 - (((TF) >> 13) & 0x7))
> +#define MT2701_M4U_TF_PORT(TF)			(((TF) >> 8) & 0xF)
> +/* MTK generation one iommu HW only support 4K size mapping */
> +#define MT2701_IOMMU_PAGE_SHIFT			12
> +#define MT2701_IOMMU_PAGE_SIZE			(1UL << MT2701_IOMMU_PAGE_SHIFT)
> +
> +/*
> + * MTK m4u support 4GB iova address space, and oly support 4K page

Nit: s/oly/only/

> + * mapping. So the pagetable size should be exactly as 4M.
> + */
> +#define M2701_IOMMU_PGT_SIZE			SZ_4M
> +
> +static const int mt2701_m4u_in_larb[] = {
> +	LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
> +	LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
> +};
> +
> +static inline int mt2701_m4u_to_larb(int id)
> +{
> +	int i;
> +
> +	for (i = ARRAY_SIZE(mt2701_m4u_in_larb); i >= 0; i--)
> +		if ((id) >= mt2701_m4u_in_larb[i])
> +			return i;
> +
> +	return 0;
> +}

As far as I can tell, this is going to dereference mt2701_m4u_in_larb[4] 
on the first iteration. Not good.

> +
> +static inline int mt2701_m4u_to_port(int id)
> +{
> +	int larb = mt2701_m4u_to_larb(id);
> +
> +	return id - mt2701_m4u_in_larb[larb];
> +}
> +
> +static void mtk_iommu_tlb_flush_all(void *cookie)
> +{
> +	struct mtk_iommu_data *data = cookie;

You're not bound by the using the io-pgtable TLB ops interface here, so 
just make the argument of type struct mtk_iommu_data*.

> +
> +	writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
> +			data->base + REG_MMU_INV_SEL);
> +	writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
> +	wmb(); /* Make sure the tlb flush all done */
> +}
> +
> +static void mtk_iommu_tlb_flush_range(void *cookie,
> +				unsigned long iova, size_t size)
> +{
> +	struct mtk_iommu_data *data = cookie;

Ditto.

> +	int ret;
> +	u32 tmp;
> +
> +	writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
> +		data->base + REG_MMU_INV_SEL);
> +	writel_relaxed(iova & F_MMU_FAULT_VA_MSK,
> +		data->base + REG_MMU_INVLD_START_A);
> +	writel_relaxed((iova + size - 1) & F_MMU_FAULT_VA_MSK,
> +		data->base + REG_MMU_INVLD_END_A);
> +	writel_relaxed(F_MMU_INV_RANGE, data->base + REG_MMU_INVALIDATE);
> +
> +	ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE,
> +				tmp, tmp != 0, 10, 100000);
> +	if (ret) {
> +		dev_warn(data->dev,
> +			 "Partial TLB flush timed out, falling back to full flush\n");
> +		mtk_iommu_tlb_flush_all(cookie);
> +	}
> +	/* Clear the CPE status */
> +	writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
> +}
> +
> +static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
> +{
> +	struct mtk_iommu_data *data = dev_id;
> +	struct mtk_iommu_domain *dom = data->m4u_dom;
> +	u32 int_state, regval, fault_iova, fault_pa;
> +	unsigned int fault_larb, fault_port;
> +
> +	/* Read error information from registers */
> +	int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST);
> +	fault_iova = readl_relaxed(data->base + REG_MMU_FAULT_VA);
> +
> +	fault_iova &= F_MMU_FAULT_VA_MSK;
> +	fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
> +	regval = readl_relaxed(data->base + REG_MMU_INT_ID);
> +	fault_larb = MT2701_M4U_TF_LARB(regval);
> +	fault_port = MT2701_M4U_TF_PORT(regval);
> +
> +	/*
> +	 * MTK v1 iommu HW could not determin whether the fault is read or

Nit: s/determin/determine/

> +	 * write fault, report as read fault.
> +	 */
> +	if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
> +			IOMMU_FAULT_READ))
> +		dev_err_ratelimited(data->dev,
> +			"fault type=0x%x iova=0x%x pa=0x%x larb=%d port=%d\n",
> +			int_state, fault_iova, fault_pa,
> +			fault_larb, fault_port);
> +
> +	/* Interrupt clear */
> +	regval = readl_relaxed(data->base + REG_MMU_INT_CONTROL);
> +	regval |= F_INT_CLR_BIT;
> +	writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL);
> +
> +	mtk_iommu_tlb_flush_all(data);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void mtk_iommu_config(struct mtk_iommu_data *data,
> +			     struct device *dev, bool enable)
> +{
> +	struct mtk_iommu_client_priv *head, *cur, *next;
> +	struct mtk_smi_larb_iommu    *larb_mmu;
> +	unsigned int                 larbid, portid;
> +
> +	head = dev->archdata.iommu;
> +	list_for_each_entry_safe(cur, next, &head->client, client) {
> +		larbid = mt2701_m4u_to_larb(cur->mtk_m4u_id);
> +		portid = mt2701_m4u_to_port(cur->mtk_m4u_id);
> +		larb_mmu = &data->smi_imu.larb_imu[larbid];
> +
> +		dev_dbg(dev, "%s iommu port: %d\n",
> +			enable ? "enable" : "disable", portid);
> +
> +		if (enable)
> +			larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
> +		else
> +			larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
> +	}
> +}
> +
> +static void *mtk_iommu_alloc_pgt(struct device *dev,
> +				dma_addr_t *dma, gfp_t gfp)
> +{
> +	void *pages = dma_alloc_coherent(dev,
> +				M2701_IOMMU_PGT_SIZE, dma, gfp | __GFP_ZERO);

There's a dma_zalloc_coherent() wrapper macro you can use for that.

> +
> +	if (!pages)
> +		return NULL;
> +
> +	kmemleak_ignore(pages);

Kmemleak should be able to find the live reference in dom->pgt_va, so 
this is unnecessary - it's only there in the other code because of the 
tracking-allocations-by-physical-address trickery which you've otherwise 
gotten rid of here.

> +	return pages;
> +}
> +
> +static void mtk_iommu_free_pgt(struct device *dev,
> +				void *pages, dma_addr_t dma)
> +{
> +	dma_free_coherent(dev, M2701_IOMMU_PGT_SIZE, pages, dma);
> +}

In fact, I'd just inline the dma_{alloc,free} calls at the callsites of 
these functions, since they're sufficiently self-documenting.

> +
> +static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data)
> +{
> +	struct mtk_iommu_domain *dom = data->m4u_dom;
> +
> +	spin_lock_init(&dom->pgtlock);
> +
> +	dom->pgt_va = mtk_iommu_alloc_pgt(data->dev,
> +				&dom->pgt_pa, GFP_KERNEL);
> +	if (!dom->pgt_va)
> +		return -ENOMEM;
> +
> +	writel(dom->pgt_pa, data->base + REG_MMU_PT_BASE_ADDR);
> +
> +	dom->cookie = (void *)data;
> +
> +	return 0;
> +}
> +
> +static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type)
> +{
> +	struct mtk_iommu_domain *dom;
> +
> +	if (type != IOMMU_DOMAIN_UNMANAGED)
> +		return NULL;
> +
> +	dom = kzalloc(sizeof(*dom), GFP_KERNEL);
> +	if (!dom)
> +		return NULL;
> +
> +	return &dom->domain;
> +}
> +
> +static void mtk_iommu_domain_free(struct iommu_domain *domain)
> +{

The page table belongs to the domain, so it should be freed from here, 
not anywhere else.

> +	kfree(to_mtk_domain(domain));
> +}
> +
> +static int mtk_iommu_attach_device(struct iommu_domain *domain,
> +				   struct device *dev)
> +{
> +	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
> +	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
> +	struct mtk_iommu_data *data;
> +	int ret;
> +
> +	if (!priv)
> +		return -ENODEV;
> +
> +	data = dev_get_drvdata(priv->m4udev);
> +	if (!data->m4u_dom) {
> +		data->m4u_dom = dom;
> +		ret = mtk_iommu_domain_finalise(data);
> +		if (ret) {
> +			data->m4u_dom = NULL;
> +			return ret;
> +		}
> +	} else if (data->m4u_dom != dom) {

This will never happen, because you make sure all devices are in the 
same group, so the IOMMU core code will always call you with the same 
domain here. You can safely just attach dev to dom.

> +		/* All the client devices should be in the same m4u domain */
> +		dev_err(dev, "try to attach into the error iommu domain\n");
> +		return -EPERM;
> +	}
> +
> +	mtk_iommu_config(data, dev, true);
> +	return 0;
> +}
> +
> +static void mtk_iommu_detach_device(struct iommu_domain *domain,
> +				    struct device *dev)
> +{
> +	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
> +	struct mtk_iommu_data *data;
> +
> +	if (!priv)
> +		return;
> +
> +	data = dev_get_drvdata(priv->m4udev);
> +	mtk_iommu_config(data, dev, false);
> +}
> +
> +static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
> +			 phys_addr_t paddr, size_t size, int prot)
> +{
> +	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
> +	struct mtk_iommu_data *data = dom->cookie;
> +	unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT;
> +	unsigned long flags;
> +	unsigned int i;
> +	u32 *pgt_base_iova = dom->pgt_va;
> +	u32 pabase = (u32)paddr;
> +	int map_size = 0;
> +
> +	spin_lock_irqsave(&dom->pgtlock, flags);
> +	pgt_base_iova += iova  >> MT2701_IOMMU_PAGE_SHIFT;

It took me a while to figure out why this isn't just part of the 
initialisation expression; just make dom->pgt_va a u32* so that it can be.

> +	for (i = 0; i < page_num; i++) {
> +		if (pgt_base_iova[i])
> +			break;

The error case also needs to roll back any partial mapping it's managed 
so far - otherwise you end up making the initial problem worse by 
leaving behind yet more unexpected PTEs in areas that the caller thinks 
are unmapped.

> +		pgt_base_iova[i] = pabase | F_DESC_VALID | F_DESC_NONSEC;
> +		pabase += MT2701_IOMMU_PAGE_SIZE;
> +		map_size += MT2701_IOMMU_PAGE_SIZE;
> +	}
> +
> +	spin_unlock_irqrestore(&dom->pgtlock, flags);
> +
> +	mtk_iommu_tlb_flush_range(data, iova, size);
> +
> +	return map_size == size ? 0 : -EEXIST;
> +}
> +
> +static size_t mtk_iommu_unmap(struct iommu_domain *domain,
> +			      unsigned long iova, size_t size)
> +{
> +	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
> +	struct mtk_iommu_data *data = dom->cookie;
> +	unsigned long flags;
> +	u32 *pgt_base_iova = dom->pgt_va;
> +	unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT;
> +
> +	spin_lock_irqsave(&dom->pgtlock, flags);
> +	pgt_base_iova += iova  >> MT2701_IOMMU_PAGE_SHIFT;

Same complaint as for mtk_iommu_map().

> +	memset(pgt_base_iova, 0, page_num * sizeof(u32));
> +
> +	spin_unlock_irqrestore(&dom->pgtlock, flags);
> +
> +	mtk_iommu_tlb_flush_range(data, iova, size);
> +
> +	return size;
> +}
> +
> +static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
> +					  dma_addr_t iova)
> +{
> +	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
> +	unsigned long flags;
> +	phys_addr_t pa;
> +
> +	spin_lock_irqsave(&dom->pgtlock, flags);
> +	pa = *((u32 *)((u32 *)dom->pgt_va + (iova >> MT2701_IOMMU_PAGE_SHIFT)));

Yikes! _Definitely_ make dom->pgt_va a u32*.

> +	pa = pa & (~(MT2701_IOMMU_PAGE_SIZE - 1));
> +	spin_unlock_irqrestore(&dom->pgtlock, flags);
> +
> +	return pa;
> +}
> +
> +/*
> + * MTK generaion one iommu HW only support one iommu domain, and all the client

Nit: s/generaion/generation/

> + * sharing the same iova address space.
> + */
> +static int mtk_iommu_create_mapping(struct device *dev,
> +				    struct of_phandle_args *args)
> +{
> +	struct mtk_iommu_client_priv *head, *priv, *next;
> +	struct platform_device *m4updev;
> +	struct dma_iommu_mapping *mtk_mapping;
> +	struct device *m4udev;
> +	int ret;
> +
> +	if (args->args_count != 1) {
> +		dev_err(dev, "invalid #iommu-cells(%d) property for IOMMU\n",
> +			args->args_count);
> +		return -EINVAL;
> +	}
> +
> +	if (!dev->archdata.iommu) {
> +		/* Get the m4u device */
> +		m4updev = of_find_device_by_node(args->np);
> +		of_node_put(args->np);
> +		if (WARN_ON(!m4updev))
> +			return -EINVAL;
> +
> +		head = kzalloc(sizeof(*head), GFP_KERNEL);
> +		if (!head)
> +			return -ENOMEM;
> +
> +		dev->archdata.iommu = head;
> +		INIT_LIST_HEAD(&head->client);
> +		head->m4udev = &m4updev->dev;
> +	} else {
> +		head = dev->archdata.iommu;
> +	}
> +
> +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		ret = -ENOMEM;
> +		goto err_free_mem;
> +	}
> +	priv->mtk_m4u_id = args->args[0];
> +	list_add_tail(&priv->client, &head->client);
> +
> +	m4udev = head->m4udev;
> +	mtk_mapping = m4udev->archdata.iommu;
> +	if (!mtk_mapping) {
> +		/* MTK iommu support 4GB iova address space. */
> +		mtk_mapping = arm_iommu_create_mapping(&platform_bus_type,
> +						0, 1ULL << 32);
> +		if (IS_ERR(mtk_mapping)) {
> +			ret = PTR_ERR(mtk_mapping);
> +			goto err_free_mem;
> +		}
> +		m4udev->archdata.iommu = mtk_mapping;
> +	}
> +
> +	ret = arm_iommu_attach_device(dev, mtk_mapping);
> +	if (ret)
> +		goto err_release_mapping;
> +
> +	return 0;
> +
> +err_release_mapping:
> +	arm_iommu_release_mapping(mtk_mapping);
> +	m4udev->archdata.iommu = NULL;
> +err_free_mem:
> +	list_for_each_entry_safe(priv, next, &head->client, client)
> +		kfree(priv);
> +	kfree(head);
> +	dev->archdata.iommu = NULL;
> +	return ret;
> +}
> +
> +static int mtk_iommu_add_device(struct device *dev)
> +{
> +	struct iommu_group *group;
> +	struct device_node *np;
> +	struct of_phandle_args iommu_spec;
> +	int idx = 0;
> +
> +	while (!of_parse_phandle_with_args(dev->of_node, "iommus",
> +				   "#iommu-cells", idx,
> +				   &iommu_spec)) {

Hang on, this doesn't seem right - why do you need to reimplement all 
this instead of using IOMMU_OF_DECLARE()?

> +		np = iommu_spec.np;
> +		mtk_iommu_create_mapping(dev, &iommu_spec);
> +
> +		of_node_put(np);
> +		idx++;
> +	}
> +
> +	if (!dev->archdata.iommu) /* Not a iommu client device */
> +		return -ENODEV;
> +
> +	group = iommu_group_get_for_dev(dev);
> +	if (IS_ERR(group))
> +		return PTR_ERR(group);
> +
> +	iommu_group_put(group);
> +	return 0;
> +}
> +
> +static void mtk_iommu_remove_device(struct device *dev)
> +{
> +	struct mtk_iommu_client_priv *head, *cur, *next;
> +
> +	head = dev->archdata.iommu;
> +	if (!head)
> +		return;
> +
> +	list_for_each_entry_safe(cur, next, &head->client, client) {
> +		list_del(&cur->client);
> +		kfree(cur);
> +	}
> +	kfree(head);
> +	dev->archdata.iommu = NULL;
> +
> +	iommu_group_remove_device(dev);
> +}
> +
> +static struct iommu_group *mtk_iommu_device_group(struct device *dev)
> +{
> +	struct mtk_iommu_data *data;
> +	struct mtk_iommu_client_priv *priv;
> +
> +	priv = dev->archdata.iommu;
> +	if (!priv)
> +		return ERR_PTR(-ENODEV);
> +
> +	/* All the client devices are in the same m4u iommu-group */
> +	data = dev_get_drvdata(priv->m4udev);
> +	if (!data->m4u_group) {
> +		data->m4u_group = iommu_group_alloc();
> +		if (IS_ERR(data->m4u_group))
> +			dev_err(dev, "Failed to allocate M4U IOMMU group\n");
> +	}
> +	return data->m4u_group;
> +}
> +
> +static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
> +{
> +	u32 regval;
> +	int ret;
> +
> +	ret = clk_prepare_enable(data->bclk);
> +	if (ret) {
> +		dev_err(data->dev, "Failed to enable iommu bclk(%d)\n", ret);
> +		return ret;
> +	}
> +
> +	regval = F_MMU_CTRL_COHERENT_EN | F_MMU_TF_PROTECT_SEL(2);
> +	writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
> +
> +	regval = F_INT_TRANSLATION_FAULT |
> +		F_INT_MAIN_MULTI_HIT_FAULT |
> +		F_INT_INVALID_PA_FAULT |
> +		F_INT_ENTRY_REPLACEMENT_FAULT |
> +		F_INT_TABLE_WALK_FAULT |
> +		F_INT_TLB_MISS_FAULT |
> +		F_INT_PFH_DMA_FIFO_OVERFLOW |
> +		F_INT_MISS_DMA_FIFO_OVERFLOW;
> +	writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL);
> +
> +	/* protect memory,hw will write here while translation fault */
> +	writel_relaxed(data->protect_base,
> +			data->base + REG_MMU_IVRP_PADDR);
> +
> +	writel_relaxed(F_MMU_DCM_ON, data->base + REG_MMU_DCM);
> +
> +	if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
> +			     dev_name(data->dev), (void *)data)) {
> +		writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR);
> +		clk_disable_unprepare(data->bclk);
> +		dev_err(data->dev, "Failed @ IRQ-%d Request\n", data->irq);
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct iommu_ops mtk_iommu_ops = {
> +	.domain_alloc	= mtk_iommu_domain_alloc,
> +	.domain_free	= mtk_iommu_domain_free,
> +	.attach_dev	= mtk_iommu_attach_device,
> +	.detach_dev	= mtk_iommu_detach_device,
> +	.map		= mtk_iommu_map,
> +	.unmap		= mtk_iommu_unmap,
> +	.map_sg		= default_iommu_map_sg,
> +	.iova_to_phys	= mtk_iommu_iova_to_phys,
> +	.add_device	= mtk_iommu_add_device,
> +	.remove_device	= mtk_iommu_remove_device,
> +	.device_group	= mtk_iommu_device_group,
> +	.pgsize_bitmap	= ~0UL << MT2701_IOMMU_PAGE_SHIFT,
> +};
> +
> +static const struct of_device_id mtk_iommu_of_ids[] = {
> +	{ .compatible = "mediatek,mt2701-m4u", },
> +	{}
> +};
> +
> +static const struct component_master_ops mtk_iommu_com_ops = {
> +	.bind		= mtk_iommu_bind,
> +	.unbind		= mtk_iommu_unbind,
> +};
> +
> +static int mtk_iommu_probe(struct platform_device *pdev)
> +{
> +	struct mtk_iommu_data		*data;
> +	struct device			*dev = &pdev->dev;
> +	struct resource			*res;
> +	struct component_match		*match = NULL;
> +	void				*protect;
> +	int				i, larb_nr, ret;
> +
> +	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->dev = dev;
> +
> +	/* Protect memory. HW will access here while translation fault.*/
> +	protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL);

I think strictly this ought to have GFP_DMA as well.

> +	if (!protect)
> +		return -ENOMEM;
> +	data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	data->base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(data->base))
> +		return PTR_ERR(data->base);
> +
> +	data->irq = platform_get_irq(pdev, 0);
> +	if (data->irq < 0)
> +		return data->irq;
> +
> +	data->bclk = devm_clk_get(dev, "bclk");
> +	if (IS_ERR(data->bclk))
> +		return PTR_ERR(data->bclk);
> +
> +	larb_nr = of_count_phandle_with_args(dev->of_node,
> +					"mediatek,larbs", NULL);
> +	if (larb_nr < 0)
> +		return larb_nr;
> +	data->smi_imu.larb_nr = larb_nr;
> +
> +	for (i = 0; i < larb_nr; i++) {
> +		struct device_node *larbnode;
> +		struct platform_device *plarbdev;

Nit: I wonder if the new of_for_each_phandle() iterator might make this 
larb-discovery logic cleaner? It might be worth a go now that that's 
landed in the current merge window.

> +
> +		larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
> +		if (!larbnode)
> +			return -EINVAL;
> +
> +		if (!of_device_is_available(larbnode))
> +			continue;
> +
> +		plarbdev = of_find_device_by_node(larbnode);
> +		of_node_put(larbnode);
> +		if (!plarbdev) {
> +			plarbdev = of_platform_device_create(
> +						larbnode, NULL,
> +						platform_bus_type.dev_root);
> +			if (!plarbdev)
> +				return -EPROBE_DEFER;
> +		}
> +		data->smi_imu.larb_imu[i].dev = &plarbdev->dev;
> +
> +		component_match_add(dev, &match, compare_of, larbnode);
> +	}
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	ret = mtk_iommu_hw_init(data);
> +	if (ret)
> +		return ret;
> +
> +	if (!iommu_present(&platform_bus_type))
> +		bus_set_iommu(&platform_bus_type,  &mtk_iommu_ops);
> +
> +	return component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
> +}
> +
> +static int mtk_iommu_remove(struct platform_device *pdev)
> +{
> +	struct mtk_iommu_data *data = platform_get_drvdata(pdev);
> +	struct mtk_iommu_domain *dom = data->m4u_dom;
> +	struct device *dev = &pdev->dev;
> +
> +	mtk_iommu_free_pgt(dev, dom->pgt_va, dom->pgt_pa);
> +
> +	if (iommu_present(&platform_bus_type))
> +		bus_set_iommu(&platform_bus_type, NULL);
> +
> +	clk_disable_unprepare(data->bclk);
> +	devm_free_irq(&pdev->dev, data->irq, data);
> +	component_master_del(&pdev->dev, &mtk_iommu_com_ops);
> +	return 0;
> +}
> +
> +static int __maybe_unused mtk_iommu_suspend(struct device *dev)
> +{
> +	struct mtk_iommu_data *data = dev_get_drvdata(dev);
> +	struct mtk_iommu_suspend_reg *reg = &data->reg;
> +	void __iomem *base = data->base;
> +
> +	reg->standard_axi_mode = readl_relaxed(base +
> +					       REG_MMU_STANDARD_AXI_MODE);
> +	reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM);
> +	reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG);
> +	reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL);
> +	return 0;
> +}
> +
> +static int __maybe_unused mtk_iommu_resume(struct device *dev)
> +{
> +	struct mtk_iommu_data *data = dev_get_drvdata(dev);
> +	struct mtk_iommu_suspend_reg *reg = &data->reg;
> +	void __iomem *base = data->base;
> +
> +	writel_relaxed(data->m4u_dom->pgt_pa, base + REG_MMU_PT_BASE_ADDR);

Hmm, this looks like the only case where m4u_dom actually seems 
necessary - I'm pretty sure all the others could be fairly easily 
reworked to not use it (I might try having a quick hack at the existing 
M4U driver to see) - at which point we could just explicitly 
save/restore the base register here and get rid of m4u_dom entirely.

> +	writel_relaxed(reg->standard_axi_mode,
> +		       base + REG_MMU_STANDARD_AXI_MODE);
> +	writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM);
> +	writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG);
> +	writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL);
> +	writel_relaxed(data->protect_base, base + REG_MMU_IVRP_PADDR);
> +	return 0;
> +}
> +
> +const struct dev_pm_ops mtk_iommu_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume)
> +};
> +
> +static struct platform_driver mtk_iommu_driver = {
> +	.probe	= mtk_iommu_probe,
> +	.remove	= mtk_iommu_remove,
> +	.driver	= {
> +		.name = "mtk-iommu",
> +		.of_match_table = mtk_iommu_of_ids,
> +		.pm = &mtk_iommu_pm_ops,
> +	}
> +};
> +
> +static int __init m4u_init(void)
> +{
> +	int ret;
> +
> +	ret = platform_driver_register(&mtk_iommu_driver);
> +	if (ret)
> +		bus_set_iommu(&platform_bus_type, NULL);

That doesn't seem necessary - the bus ops won't be set until having 
successfully probed an M4U, and you definitely won't have managed that 
before registering the driver ;)

Robin.

> +
> +	return ret;
> +}
> +
> +static void __exit m4u_exit(void)
> +{
> +	return platform_driver_unregister(&mtk_iommu_driver);
> +}
> +
> +subsys_initcall(m4u_init);
> +module_exit(m4u_exit);
> +
> +MODULE_DESCRIPTION("IOMMU API for MTK architected m4u v1 implementations");
> +MODULE_AUTHOR("Honghui Zhang <honghui.zhang at mediatek.com>");
> +MODULE_LICENSE("GPL v2");
>



From rafael at kernel.org  Mon May 23 13:16:41 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Mon, 23 May 2016 22:16:41 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <20160523182807.GY19428@n2100.arm.linux.org.uk>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
 <20160523182807.GY19428@n2100.arm.linux.org.uk>
Message-ID: <CAJZ5v0ipPVsZmu+RVfrPChA7banMGFNsfMt=if0V3XfVdstRNQ@mail.gmail.com>

On Mon, May 23, 2016 at 8:28 PM, Russell King - ARM Linux
<linux at armlinux.org.uk> wrote:
> On Sat, May 21, 2016 at 02:56:20AM +0200, Rafael J. Wysocki wrote:
>> The root of the problem seems to be arch_irq_work_raise() and specifically
>> the __smp_cross_call function that appears to have problems.
>
> We've been through this before.  The bottom line is that on ARM, there
> is major wide-spread understanding that we want to be able to run a
> kernel compiled for SMP on uniprocessor hardware.
>
> This is something that's been going for years, and has worked fine for
> years.
>
> Now, someone has introduced this irq work stuff.  Great.  But they
> haven't considered that people want to be able to run a SMP kernel
> on UP hardware which _may_ have no hardware present which is capable
> of raising IPIs.
>
> I don't know what the situation is with the platform concerned here,
> I don't know whether it uses the GIC (presumably, because it doesn't
> NULL-pointer ref on calling smp_cross_call(), it is using the GIC.)
> If so, the GIC isn't delivering the IPI because the IPI hardware is
> missing.
>
> Now, whether we could detect whether the GIC is IPI capable, I've
> no idea, I don't have such a platform I could run tests on.  People
> don't give me hardware anymore now that arm-soc is split off from
> core ARM maintanence - it all goes into Linaro build farms.  So I'm
> powerless to help here.
>
> My attitude towards this is that it's a core kernel problem: the
> core kernel is assuming that it can raise IPIs even on non-SMP
> capable hardware.  Much non-SMP hardware doesn't have that ability.
> While folk can try to push it into arch code, my feeling is that it
> really needs to have a generic solution, even if it's some generic
> solution that architectures in this situation can plug into.

Well, this particular case isn't about IPIs at all.

irq_work_queue() can work without IPIs and it works like that on other
ARM platforms where SMP kernels are run on UP hardware (without IPI
support).

Something seems to be missing in kernel config or similar here, but I
can't really say what it is right away.


From rafael at kernel.org  Mon May 23 13:23:52 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Mon, 23 May 2016 22:23:52 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAJZ5v0ipPVsZmu+RVfrPChA7banMGFNsfMt=if0V3XfVdstRNQ@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
 <20160523182807.GY19428@n2100.arm.linux.org.uk>
 <CAJZ5v0ipPVsZmu+RVfrPChA7banMGFNsfMt=if0V3XfVdstRNQ@mail.gmail.com>
Message-ID: <CAJZ5v0j0VbyHNT_ZmThsdQfRWzf7SG65A8-bPxoAUxZJgR96og@mail.gmail.com>

On Mon, May 23, 2016 at 10:16 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:
> On Mon, May 23, 2016 at 8:28 PM, Russell King - ARM Linux
> <linux at armlinux.org.uk> wrote:
>> On Sat, May 21, 2016 at 02:56:20AM +0200, Rafael J. Wysocki wrote:
>>> The root of the problem seems to be arch_irq_work_raise() and specifically
>>> the __smp_cross_call function that appears to have problems.
>>
>> We've been through this before.  The bottom line is that on ARM, there
>> is major wide-spread understanding that we want to be able to run a
>> kernel compiled for SMP on uniprocessor hardware.
>>
>> This is something that's been going for years, and has worked fine for
>> years.
>>
>> Now, someone has introduced this irq work stuff.  Great.  But they
>> haven't considered that people want to be able to run a SMP kernel
>> on UP hardware which _may_ have no hardware present which is capable
>> of raising IPIs.
>>
>> I don't know what the situation is with the platform concerned here,
>> I don't know whether it uses the GIC (presumably, because it doesn't
>> NULL-pointer ref on calling smp_cross_call(), it is using the GIC.)
>> If so, the GIC isn't delivering the IPI because the IPI hardware is
>> missing.
>>
>> Now, whether we could detect whether the GIC is IPI capable, I've
>> no idea, I don't have such a platform I could run tests on.  People
>> don't give me hardware anymore now that arm-soc is split off from
>> core ARM maintanence - it all goes into Linaro build farms.  So I'm
>> powerless to help here.
>>
>> My attitude towards this is that it's a core kernel problem: the
>> core kernel is assuming that it can raise IPIs even on non-SMP
>> capable hardware.  Much non-SMP hardware doesn't have that ability.
>> While folk can try to push it into arch code, my feeling is that it
>> really needs to have a generic solution, even if it's some generic
>> solution that architectures in this situation can plug into.
>
> Well, this particular case isn't about IPIs at all.
>
> irq_work_queue() can work without IPIs and it works like that on other
> ARM platforms where SMP kernels are run on UP hardware (without IPI
> support).
>
> Something seems to be missing in kernel config or similar here, but I
> can't really say what it is right away.

For one, if that platform is not capable of raising interrupts for IRQ
works, I'm not sure why arch_irq_work_has_interrupt() returns true on
it.


From robh at kernel.org  Mon May 23 13:30:44 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 23 May 2016 15:30:44 -0500
Subject: [PATCH 1/3] Documentation: dtb: xgene: Add hwmon dts binding
 documentation
In-Reply-To: <1463415447-29903-2-git-send-email-hotran@apm.com>
References: <1463415447-29903-1-git-send-email-hotran@apm.com>
 <1463415447-29903-2-git-send-email-hotran@apm.com>
Message-ID: <20160523203044.GA17450@rob-hp-laptop>

On Mon, May 16, 2016 at 09:17:25AM -0700, Hoan Tran wrote:
> This patch adds the APM X-Gene hwmon device tree node documentation.
> 
> Signed-off-by: Hoan Tran <hotran at apm.com>
> ---
>  .../devicetree/bindings/hwmon/apm-xgene-hwmon.txt          | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt
> 
> diff --git a/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt b/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt
> new file mode 100644
> index 0000000..49a482e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt
> @@ -0,0 +1,14 @@
> +APM X-Gene hwmon driver
> +
> +Hwmon driver accesses sensors over the "SLIMpro" mailbox.

DT bindings describe h/w, not driver data. I'm not sure this belongs in 
DT and perhaps the devices for the mailbox should be created by the 
mailbox driver.

> +
> +Required properties :
> + - compatible : should be "apm,xgene-slimpro-hwmon"
> + - mboxes : use the label reference for the mailbox as the first parameter.
> +	    The second parameter is the channel number.

When do you expect this to be different mailbox numbers? 

> +
> +Example :
> +	hwmonslimpro {
> +		compatible = "apm,xgene-slimpro-hwmon";
> +		mboxes = <&mailbox 7>;
> +	};
> -- 
> 1.9.1
> 


From arnd at arndb.de  Mon May 23 13:35:49 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 23 May 2016 22:35:49 +0200
Subject: [PATCH] hwrng: stm32 - fix build warning
In-Reply-To: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>
References: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>
Message-ID: <6297051.TAxtzW5OIB@wuerfel>

On Monday, May 23, 2016 6:14:08 PM CEST Sudip Mukherjee wrote:
> We have been getting build warning about:
> drivers/char/hw_random/stm32-rng.c: In function 'stm32_rng_read':
> drivers/char/hw_random/stm32-rng.c:82:19: warning: 'sr' may be used
> 					uninitialized in this function
> 
> On checking the code it turns out that sr can never be used
> uninitialized as sr is getting initialized in the while loop and while
> loop will always execute as the minimum value of max can be 32.
> So just initialize sr to 0 while declaring it to silence the compiler.
> 
> Signed-off-by: Sudip Mukherjee <sudip.mukherjee at codethink.co.uk>
> ---

I notice that you are using a really old compiler. While this warning
seems to be valid in the sense that the compiler should figure out that
the variable might be used uninitialized, please update your toolchain
before reporting other such problems, as gcc-4.6 had a lot more false
positives that newer ones (5.x or 6.x) have.

> 
> build log at:
> https://travis-ci.org/sudipm-mukherjee/parport/jobs/132180906
> 
>  drivers/char/hw_random/stm32-rng.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
> index 92a8106..0533370 100644
> --- a/drivers/char/hw_random/stm32-rng.c
> +++ b/drivers/char/hw_random/stm32-rng.c
> @@ -52,7 +52,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
>  {
>  	struct stm32_rng_private *priv =
>  	    container_of(rng, struct stm32_rng_private, rng);
> -	u32 sr;
> +	u32 sr = 0;
>  	int retval = 0;
>  
>  	pm_runtime_get_sync((struct device *) priv->rng.priv);

Does this work as well?

diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 92a810648bd0..5c836b0afa40 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -79,7 +79,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 		max -= sizeof(u32);
 	}
 
-	if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
+	if (WARN_ONCE(retval > 0 && (sr & (RNG_SR_SEIS | RNG_SR_CEIS)),
 		      "bad RNG status - %x\n", sr))
 		writel_relaxed(0, priv->base + RNG_SR);
 
I think it would be nicer to not add a bogus initialization.

	Arnd


From dianders at chromium.org  Mon May 23 13:46:00 2016
From: dianders at chromium.org (Doug Anderson)
Date: Mon, 23 May 2016 13:46:00 -0700
Subject: [PATCH 2/3] soc: rockchip: add driver handling grf setup
In-Reply-To: <1464015539-19521-3-git-send-email-heiko@sntech.de>
References: <1464015539-19521-1-git-send-email-heiko@sntech.de>
 <1464015539-19521-3-git-send-email-heiko@sntech.de>
Message-ID: <CAD=FV=VbrhpyQ8Y+5qnYHmkSvq12im2tZtpgnryGeEdc7mci9g@mail.gmail.com>

Heiko,

On Mon, May 23, 2016 at 7:58 AM, Heiko Stuebner <heiko at sntech.de> wrote:
> +struct rockchip_grf_info {
> +       const struct rockchip_grf_value *values;
> +       int num_values;
> +};
> +
> +#define RK3036_GRF_SOC_CON0            0x140
> +
> +static const struct rockchip_grf_value rk3036_defaults[] = {

Worth saving the little bit of space by marking several of these
structures as __initconst ?


> +#define RK3399_GRF_SOC_CON7            0xe21c
> +
> +static const struct rockchip_grf_value rk3399_defaults[] = {
> +       { "jtag switching", RK3399_GRF_SOC_CON7, HIWORD_UPDATE(0, 1, 12) },
> +
> +};

nit: extra blank line in rk3399_defaults?


> +static int rockchip_grf_probe(struct platform_device *pdev)
> +{
> +       const struct rockchip_grf_info *grf_info;
> +       const struct of_device_id *match;
> +       struct device *dev = &pdev->dev;
> +       struct regmap *grf;
> +       int i;
> +
> +       if (!dev->of_node)
> +               return -ENODEV;
> +
> +       match = of_match_device(rockchip_grf_dt_match, dev);
> +       if (!match || !match->data) {
> +               dev_err(dev, "missing grf data\n");
> +               return -EINVAL;
> +       }
> +
> +       grf_info = match->data;
> +
> +       grf = syscon_node_to_regmap(dev->of_node);
> +       if (IS_ERR(grf)) {
> +               dev_err(dev, "rockchip: could not get grf syscon\n");
> +               return PTR_ERR(grf);
> +       }
> +
> +       for (i = 0; i < grf_info->num_values; i++) {
> +               const struct rockchip_grf_value *val = &grf_info->values[i];
> +
> +               dev_dbg(dev, "adjusting %s in 0x%x to 0x%x\n",

optional-nitty-nit saves a character: s/0x%x/%#x/

...or even force to 4 hex digits: %#6x

> +                       val->desc, val->reg, val->val);
> +               regmap_write(grf, val->reg, val->val);

Dunno if we care, but regmap_write() does return an error.  Presumably
it might return an error here if you somehow specified an offset that
was outside of the range for the GRF?


-Doug


From dianders at chromium.org  Mon May 23 13:47:20 2016
From: dianders at chromium.org (Doug Anderson)
Date: Mon, 23 May 2016 13:47:20 -0700
Subject: [PATCH 3/3] ARM: rockchip: drop rk3288 jtag/mmc switch handling
In-Reply-To: <1464015539-19521-4-git-send-email-heiko@sntech.de>
References: <1464015539-19521-1-git-send-email-heiko@sntech.de>
 <1464015539-19521-4-git-send-email-heiko@sntech.de>
Message-ID: <CAD=FV=UC1uL9SeF5ZWKBO+b1AJJLCB91nTt1bi92ysEt9Nhekw@mail.gmail.com>

Heiko,

On Mon, May 23, 2016 at 7:58 AM, Heiko Stuebner <heiko at sntech.de> wrote:
> We moved that functionality to a more generic place where it can also
> be used for other socs, so drop it from architecture code.
>
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---
>  arch/arm/mach-rockchip/rockchip.c | 12 ------------
>  1 file changed, 12 deletions(-)

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


From dianders at chromium.org  Mon May 23 13:47:26 2016
From: dianders at chromium.org (Doug Anderson)
Date: Mon, 23 May 2016 13:47:26 -0700
Subject: [PATCH 1/3] dt-bindings: add used but undocumented rockchip grf
 compatible values
In-Reply-To: <1464015539-19521-2-git-send-email-heiko@sntech.de>
References: <1464015539-19521-1-git-send-email-heiko@sntech.de>
 <1464015539-19521-2-git-send-email-heiko@sntech.de>
Message-ID: <CAD=FV=Vss6kx1Rpmi5iYGCfNBfRPU3pX4-2SysjSmhwVM_uGyA@mail.gmail.com>

Heiko,

On Mon, May 23, 2016 at 7:58 AM, Heiko Stuebner <heiko at sntech.de> wrote:
> There are some more General Register Files used in devicetree files
> already, but as of now undocumented in the binding document, fix that.
>
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---
>  Documentation/devicetree/bindings/soc/rockchip/grf.txt | 4 ++++
>  1 file changed, 4 insertions(+)

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


From stefan.wahren at i2se.com  Mon May 23 13:56:02 2016
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Mon, 23 May 2016 22:56:02 +0200 (CEST)
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
Message-ID: <190621859.107797.9eb91969-99a2-4cb3-babf-7e80dfe80a5e.open-xchange@email.1und1.de>

Hi Christopher,

> christopher.spinrath at rwth-aachen.de hat am 23. Mai 2016 um 00:47 geschrieben:
> 
> 
> From: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>
> 
> The CompuLab Utilite Pro is a miniature fanless desktop pc based on
> the i.MX6 Quad powered cm-fx6 module. It features two serial ports,
> USB OTG, 4x USB, analog audio and S/PDIF, 2x Gb Ethernet, HDMI and
> DVI ports, an on-board 32GB SSD, a mmc slot, and on-board wifi/bt.
> 
> Add initial support for it including USB, Ethernet (both ports), sata
> and HDMI support.
> 
> Signed-off-by: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>
> ---
>  arch/arm/boot/dts/Makefile              |   1 +
>  arch/arm/boot/dts/imx6q-utilite-pro.dts | 128
> ++++++++++++++++++++++++++++++++
>  2 files changed, 129 insertions(+)
>  create mode 100644 arch/arm/boot/dts/imx6q-utilite-pro.dts
> 
> ...
> diff --git a/arch/arm/boot/dts/imx6q-utilite-pro.dts
> b/arch/arm/boot/dts/imx6q-utilite-pro.dts
> new file mode 100644
> index 0000000..bcd8e0d
> --- /dev/null
> +++ b/arch/arm/boot/dts/imx6q-utilite-pro.dts
> @@ -0,0 +1,128 @@
> +/*
> + * Copyright 2016 Christopher Spinrath
> + * Copyright 2013 CompuLab Ltd.
> + *
> + * Based on the GPLv2 licensed devicetree distributed with the vendor
> + * kernel for the Utilite Pro:
> + *	Copyright 2013 CompuLab Ltd.
> + *	Author: Valentin Raevsky <valentin at compulab.co.il>
> + *
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/gpl-license.html
> + * http://www.gnu.org/copyleft/gpl.html
> + */
> +
> ...
> +
> +		pinctrl_uart2: uart2grp {
> +			fsl,pins = <
> +				MX6QDL_PAD_GPIO_7__UART2_TX_DATA 0x1b0b1
> +				MX6QDL_PAD_GPIO_8__UART2_RX_DATA 0x1b0b1
> +				MX6QDL_PAD_SD4_DAT5__UART2_RTS_B 0x1b0b1
> +				MX6QDL_PAD_SD4_DAT6__UART2_CTS_B 0x1b0b1
> +			>;
> +		};
> +	};
> +};
> +
> +&pcie {
> +	pcie at 0,0 {
> +		reg = <0x000000 0 0 0 0>;
> +		#address-cells = <3>;
> +		#size-cells = <2>;
> +
> +		/* non-removable i211 ethernet card */
> +		eth1: intel,i211 at pcie0,0 {
> +			reg = <0x010000 0 0 0 0>;
> +		};
> +	};
> +};
> +
> +&uart2 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_uart2>;
> +	fsl,uart-has-rtscts;

this property is deprecated so please use the generic one:

https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/?id=1006ed7e1b258dac3e85c9fafe9d38b6020c917f

Stefan

> +	dma-names = "rx", "tx";
> +	dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
> +	status = "okay";
> +};
> -- 
> 2.8.2
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From khilman at baylibre.com  Mon May 23 13:58:05 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Mon, 23 May 2016 13:58:05 -0700
Subject: [PATCH v3 1/4] firmware: Amlogic: Add secure monitor driver
In-Reply-To: <1464021024-29380-2-git-send-email-carlo@caione.org> (Carlo
 Caione's message of "Mon, 23 May 2016 18:30:21 +0200")
References: <1464021024-29380-1-git-send-email-carlo@caione.org>
 <1464021024-29380-2-git-send-email-carlo@caione.org>
Message-ID: <m2posco5k2.fsf@baylibre.com>

Carlo Caione <carlo at caione.org> writes:

> From: Carlo Caione <carlo at endlessm.com>
>
> Introduce a driver to provide calls into secure monitor mode.
>
> In the Amlogic SoCs these calls are used for multiple reasons: access to
> NVMEM, set USB boot, enable JTAG, etc...
>
> Signed-off-by: Carlo Caione <carlo at endlessm.com>

[...]

> +static int meson_sm_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct meson_sm_firmware *fw;
> +	u32 sm_phy_in_base, sm_phy_out_base;
> +	int cmd_in, cmd_out;
> +
> +	fw = devm_kzalloc(&pdev->dev, sizeof(*fw), GFP_KERNEL);
> +	if (!fw)
> +		return -ENOMEM;
> +
> +	fw->dev = &pdev->dev;
> +
> +	if (of_property_read_u32(np, "amlogic,sm-cmd-input-base", &cmd_in))
> +		return -EINVAL;
> +
> +	if (of_property_read_u32(np, "amlogic,sm-cmd-output-base", &cmd_out))
> +		return -EINVAL;
> +
> +	sm_phy_in_base = meson_sm_call(cmd_in, 0, 0, 0, 0, 0);

Should there be any error checking here?  Do we have any info on the
return values here in case of error, or in case of missing firmware,
etc.

Kevin


From festevam at gmail.com  Mon May 23 13:59:37 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 23 May 2016 17:59:37 -0300
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAJZ5v0j0VbyHNT_ZmThsdQfRWzf7SG65A8-bPxoAUxZJgR96og@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
 <20160523182807.GY19428@n2100.arm.linux.org.uk>
 <CAJZ5v0ipPVsZmu+RVfrPChA7banMGFNsfMt=if0V3XfVdstRNQ@mail.gmail.com>
 <CAJZ5v0j0VbyHNT_ZmThsdQfRWzf7SG65A8-bPxoAUxZJgR96og@mail.gmail.com>
Message-ID: <CAOMZO5Cbue9L2JGA0kv7nTZ=78oKDhNu6WLRUmcsSuLHscDVUQ@mail.gmail.com>

On Mon, May 23, 2016 at 5:23 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:

> For one, if that platform is not capable of raising interrupts for IRQ
> works, I'm not sure why arch_irq_work_has_interrupt() returns true on
> it.

It returns true because the kernel was built with CONFIG_SMP=y.

On ARM we have:

static inline bool arch_irq_work_has_interrupt(void)
{
    return is_smp();
}

and then:

static inline bool is_smp(void)
{
#ifndef CONFIG_SMP
    return false;
#elif defined(CONFIG_SMP_ON_UP)
    extern unsigned int smp_on_up;
    return !!smp_on_up;
#else
    return true;
#endif
}

So if CONFIG_SMP=y,  is_smp() returns 1.

As I mentioned before, the reboot problem does not happen with CONFIG_SMP=n.


From andy.gross at linaro.org  Mon May 23 14:02:06 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Mon, 23 May 2016 16:02:06 -0500
Subject: [Patch v5 5/8] firmware: qcom: scm: Convert to streaming DMA APIS
In-Reply-To: <CAOi56cVB1Z-gO6Dx0KOSr9wiRF3Y9ahDHe0=qT9WW4MdFMhjng@mail.gmail.com>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
 <1463111221-6963-6-git-send-email-andy.gross@linaro.org>
 <CAOi56cVB1Z-gO6Dx0KOSr9wiRF3Y9ahDHe0=qT9WW4MdFMhjng@mail.gmail.com>
Message-ID: <CAPBZ5Qc0oZ+k_5OiUGU6c9jFfcmAfsK3Uy-s=ONGCSGzCDyYNw@mail.gmail.com>

On 23 May 2016 at 14:26, Kevin Hilman <khilman at kernel.org> wrote:
> Hi Andy,
>
> On Thu, May 12, 2016 at 8:46 PM, Andy Gross <andy.gross at linaro.org> wrote:
>> This patch converts the Qualcomm SCM driver to use the streaming DMA APIs
>> for communication buffers.
>>
>> Signed-off-by: Andy Gross <andy.gross at linaro.org>
>
> This patch has landed in linux-next in the form of commit a551c3dbd689
> (firmware: qcom: scm: Convert to streaming DMA APIS), and kernelci.org
> found some boot breakage in next-20160523 on apq8064[1] which was
> bisected down to this commit.
>
> I reverted this commit on top of next-20160523 and it no longer
> builds, so I didn't validate if things boot again with this patch
> reverted.

Ouch I missed this failure.  I'll investigate and get it fixed.

Thanks!

Andy


From rafael at kernel.org  Mon May 23 14:03:01 2016
From: rafael at kernel.org (Rafael J. Wysocki)
Date: Mon, 23 May 2016 23:03:01 +0200
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAOMZO5Cbue9L2JGA0kv7nTZ=78oKDhNu6WLRUmcsSuLHscDVUQ@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
 <20160523182807.GY19428@n2100.arm.linux.org.uk>
 <CAJZ5v0ipPVsZmu+RVfrPChA7banMGFNsfMt=if0V3XfVdstRNQ@mail.gmail.com>
 <CAJZ5v0j0VbyHNT_ZmThsdQfRWzf7SG65A8-bPxoAUxZJgR96og@mail.gmail.com>
 <CAOMZO5Cbue9L2JGA0kv7nTZ=78oKDhNu6WLRUmcsSuLHscDVUQ@mail.gmail.com>
Message-ID: <CAJZ5v0jO++9d7bpXAg9Zs5GOPPZvg6E+OY3avDmNdor8EDxn4w@mail.gmail.com>

On Mon, May 23, 2016 at 10:59 PM, Fabio Estevam <festevam at gmail.com> wrote:
> On Mon, May 23, 2016 at 5:23 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:
>
>> For one, if that platform is not capable of raising interrupts for IRQ
>> works, I'm not sure why arch_irq_work_has_interrupt() returns true on
>> it.
>
> It returns true because the kernel was built with CONFIG_SMP=y.
>
> On ARM we have:
>
> static inline bool arch_irq_work_has_interrupt(void)
> {
>     return is_smp();
> }
>
> and then:
>
> static inline bool is_smp(void)
> {
> #ifndef CONFIG_SMP
>     return false;
> #elif defined(CONFIG_SMP_ON_UP)
>     extern unsigned int smp_on_up;
>     return !!smp_on_up;
> #else
>     return true;
> #endif
> }
>
> So if CONFIG_SMP=y,  is_smp() returns 1.
>
> As I mentioned before, the reboot problem does not happen with CONFIG_SMP=n.

First, why don't the other ARM UP platforms have this problem when SMP
kernels are run on them?

Second, quite evidently, the platform says "I can raise interrupts for
IRQ works", but then it doesn't do that.  That doesn't seem
particularly consistent to me ...


From robh at kernel.org  Mon May 23 14:04:06 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 23 May 2016 16:04:06 -0500
Subject: [PATCH 2/3] dt-bindings: reset: Add bindings for the Meson GXBB
 Reset Controller
In-Reply-To: <1463732875-23141-3-git-send-email-narmstrong@baylibre.com>
References: <1463732875-23141-1-git-send-email-narmstrong@baylibre.com>
 <1463732875-23141-3-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160523210406.GA26743@rob-hp-laptop>

On Fri, May 20, 2016 at 10:27:54AM +0200, Neil Armstrong wrote:
> Add DT bindings for the Meson GXBB SoC Reset Controller documentation and the
> associated include file.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  .../bindings/reset/amlogic,meson-gxbb-reset.txt    |  18 ++
>  .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 199 +++++++++++++++++++++
>  2 files changed, 217 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/amlogic,meson-gxbb-reset.txt
>  create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h

Other than the whitespace comments,

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


From linux at armlinux.org.uk  Mon May 23 14:07:38 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Mon, 23 May 2016 22:07:38 +0100
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAOMZO5Cbue9L2JGA0kv7nTZ=78oKDhNu6WLRUmcsSuLHscDVUQ@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
 <20160523182807.GY19428@n2100.arm.linux.org.uk>
 <CAJZ5v0ipPVsZmu+RVfrPChA7banMGFNsfMt=if0V3XfVdstRNQ@mail.gmail.com>
 <CAJZ5v0j0VbyHNT_ZmThsdQfRWzf7SG65A8-bPxoAUxZJgR96og@mail.gmail.com>
 <CAOMZO5Cbue9L2JGA0kv7nTZ=78oKDhNu6WLRUmcsSuLHscDVUQ@mail.gmail.com>
Message-ID: <20160523210738.GZ19428@n2100.arm.linux.org.uk>

On Mon, May 23, 2016 at 05:59:37PM -0300, Fabio Estevam wrote:
> On Mon, May 23, 2016 at 5:23 PM, Rafael J. Wysocki <rafael at kernel.org> wrote:
> > For one, if that platform is not capable of raising interrupts for IRQ
> > works, I'm not sure why arch_irq_work_has_interrupt() returns true on
> > it.
> 
> It returns true because the kernel was built with CONFIG_SMP=y.
> 
> On ARM we have:
> 
> static inline bool arch_irq_work_has_interrupt(void)
> {
>     return is_smp();
> }
> 
> and then:
> 
> static inline bool is_smp(void)
> {
> #ifndef CONFIG_SMP
>     return false;
> #elif defined(CONFIG_SMP_ON_UP)
>     extern unsigned int smp_on_up;
>     return !!smp_on_up;
> #else
>     return true;
> #endif
> }
> 
> So if CONFIG_SMP=y,  is_smp() returns 1.
> 
> As I mentioned before, the reboot problem does not happen with CONFIG_SMP=n.

Read the code again.  There's three states:

1. CONFIG_SMP=n - it always returns false.
2. CONFIG_SMP=y, CONFIG_SMP_ON_UP=n - it always returns true.  Such a
   kernel can _only_ be run on SMP capable systems.
3. CONFIG_SMP=y, CONFIG_SMP_ON_UP=y - it returns depending on whether
   we detect that the CPU is SMP capable.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From linux at armlinux.org.uk  Mon May 23 14:11:14 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Mon, 23 May 2016 22:11:14 +0100
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAJZ5v0jO++9d7bpXAg9Zs5GOPPZvg6E+OY3avDmNdor8EDxn4w@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
 <20160523182807.GY19428@n2100.arm.linux.org.uk>
 <CAJZ5v0ipPVsZmu+RVfrPChA7banMGFNsfMt=if0V3XfVdstRNQ@mail.gmail.com>
 <CAJZ5v0j0VbyHNT_ZmThsdQfRWzf7SG65A8-bPxoAUxZJgR96og@mail.gmail.com>
 <CAOMZO5Cbue9L2JGA0kv7nTZ=78oKDhNu6WLRUmcsSuLHscDVUQ@mail.gmail.com>
 <CAJZ5v0jO++9d7bpXAg9Zs5GOPPZvg6E+OY3avDmNdor8EDxn4w@mail.gmail.com>
Message-ID: <20160523211114.GA19428@n2100.arm.linux.org.uk>

On Mon, May 23, 2016 at 11:03:01PM +0200, Rafael J. Wysocki wrote:
> On Mon, May 23, 2016 at 10:59 PM, Fabio Estevam <festevam at gmail.com> wrote:
> > On ARM we have:
> >
> > static inline bool arch_irq_work_has_interrupt(void)
> > {
> >     return is_smp();
> > }
> >
> > and then:
> >
> > static inline bool is_smp(void)
> > {
> > #ifndef CONFIG_SMP
> >     return false;
> > #elif defined(CONFIG_SMP_ON_UP)
> >     extern unsigned int smp_on_up;
> >     return !!smp_on_up;
> > #else
> >     return true;
> > #endif
> > }
> >
> > So if CONFIG_SMP=y,  is_smp() returns 1.
> >
> > As I mentioned before, the reboot problem does not happen with CONFIG_SMP=n.
> 
> First, why don't the other ARM UP platforms have this problem when SMP
> kernels are run on them?
> 
> Second, quite evidently, the platform says "I can raise interrupts for
> IRQ works", but then it doesn't do that.  That doesn't seem
> particularly consistent to me ...

Maybe someone has implemented a SoC which has a CPU capable of SMP
but the GIC isn't...  I'm just guessing again.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From robh at kernel.org  Mon May 23 14:18:13 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 23 May 2016 16:18:13 -0500
Subject: [PATCH v3 4/4] soc: Add SoC driver for Freescale Vybrid platform
In-Reply-To: <ffef165d05f71a1b19437171d8fdb4bc78f6b1e3.1463737502.git.maitysanchayan@gmail.com>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
 <ffef165d05f71a1b19437171d8fdb4bc78f6b1e3.1463737502.git.maitysanchayan@gmail.com>
Message-ID: <20160523211813.GA30237@rob-hp-laptop>

On Fri, May 20, 2016 at 03:32:05PM +0530, Sanchayan Maity wrote:
> This adds a SoC driver to be used by Freescale Vybrid SoC's.
> Driver utilises syscon and nvmem consumer API's to get the
> various register values needed and expose the SoC specific
> properties via sysfs.
> 
> A sample output from Colibri Vybrid VF61 is below:
> 
> root at colibri-vf:~# cd /sys/bus/soc/devices/soc0
> root at colibri-vf:/sys/bus/soc/devices/soc0# ls
> family     machine    power      revision   soc_id     subsystem  uevent
> root at colibri-vf:/sys/bus/soc/devices/soc0# cat family
> Freescale Vybrid VF610
> root at colibri-vf:/sys/bus/soc/devices/soc0# cat machine
> Freescale Vybrid
> root at colibri-vf:/sys/bus/soc/devices/soc0# cat revision
> 00000013
> root at colibri-vf:/sys/bus/soc/devices/soc0# cat soc_id
> df6472a6130f29d4
> 
> Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
> ---
>  .../bindings/arm/freescale/fsl,vf610-soc.txt       |  20 +++
>  drivers/soc/Kconfig                                |   1 +
>  drivers/soc/fsl/Kconfig                            |  10 ++
>  drivers/soc/fsl/Makefile                           |   1 +
>  drivers/soc/fsl/soc-vf610.c                        | 198 +++++++++++++++++++++
>  5 files changed, 230 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>  create mode 100644 drivers/soc/fsl/Kconfig
>  create mode 100644 drivers/soc/fsl/soc-vf610.c
> 
> diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> new file mode 100644
> index 0000000..338905d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> @@ -0,0 +1,20 @@
> +Vybrid System-on-Chip
> +---------------------
> +
> +Required properties:
> +
> +- compatible: "fsl,vf610-soc"
> +- rom-revision: phandle to the on-chip ROM node
> +- mscm: phandle to the MSCM CPU configuration node
> +- nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
> +- nvmem-cell-names: should contain string names "cfg0" and "cfg1"

I still have similar concerns as the discussion on the last version. 
This version only proves that you aren't describing h/w, but rather just 
a collection of data that some driver wants.

A driver can just as easily look-up all the nodes directly that these 
phandles point to.

And as long as we have inconsistent use of soc_device, I don't want to 
see any compatible strings related to it.

Rob


From robh at kernel.org  Mon May 23 14:23:13 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 23 May 2016 16:23:13 -0500
Subject: [PATCH V5 2/7] documentation: iommu: Add bindings for
 msm,iommu-v0 ip
In-Reply-To: <1463741694-1735-3-git-send-email-sricharan@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
 <1463741694-1735-3-git-send-email-sricharan@codeaurora.org>
Message-ID: <20160523212313.GA4647@rob-hp-laptop>

On Fri, May 20, 2016 at 04:24:49PM +0530, Sricharan R wrote:
> The MSM IOMMU is an implementation compatible with the ARM VMSA short
> descriptor page tables. It provides address translation for bus masters outside
> of the CPU, each connected to the IOMMU through a port called micro-TLB.
> Adding the DT bindings for the same.
> 
> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> ---
>  .../devicetree/bindings/iommu/msm,iommu-v0.txt     | 64 ++++++++++++++++++++++
>  1 file changed, 64 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iommu/msm,iommu-v0.txt

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


From festevam at gmail.com  Mon May 23 14:38:31 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 23 May 2016 18:38:31 -0300
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <20160523210738.GZ19428@n2100.arm.linux.org.uk>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
 <20160523182807.GY19428@n2100.arm.linux.org.uk>
 <CAJZ5v0ipPVsZmu+RVfrPChA7banMGFNsfMt=if0V3XfVdstRNQ@mail.gmail.com>
 <CAJZ5v0j0VbyHNT_ZmThsdQfRWzf7SG65A8-bPxoAUxZJgR96og@mail.gmail.com>
 <CAOMZO5Cbue9L2JGA0kv7nTZ=78oKDhNu6WLRUmcsSuLHscDVUQ@mail.gmail.com>
 <20160523210738.GZ19428@n2100.arm.linux.org.uk>
Message-ID: <CAOMZO5DjjgNk+uHyH7Avvfrt_TNPaZ+SUtHzON5fPU=25_gKOg@mail.gmail.com>

On Mon, May 23, 2016 at 6:07 PM, Russell King - ARM Linux
<linux at armlinux.org.uk> wrote:

> Read the code again.  There's three states:
>
> 1. CONFIG_SMP=n - it always returns false.
> 2. CONFIG_SMP=y, CONFIG_SMP_ON_UP=n - it always returns true.  Such a
>    kernel can _only_ be run on SMP capable systems.
> 3. CONFIG_SMP=y, CONFIG_SMP_ON_UP=y - it returns depending on whether
>    we detect that the CPU is SMP capable.

Yes, I meant that on imx6ul we have option 2 above with imx_v6_v7_defconfig.

Also tested option 3 and is_smp() returns true as well.

I will try to see why GIC on this SoC cannot work in SMP.


From robh at kernel.org  Mon May 23 14:38:34 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 23 May 2016 16:38:34 -0500
Subject: [PATCH 1/3] dt-bindings: add used but undocumented rockchip grf
 compatible values
In-Reply-To: <1464015539-19521-2-git-send-email-heiko@sntech.de>
References: <1464015539-19521-1-git-send-email-heiko@sntech.de>
 <1464015539-19521-2-git-send-email-heiko@sntech.de>
Message-ID: <20160523213834.GA12860@rob-hp-laptop>

On Mon, May 23, 2016 at 04:58:57PM +0200, Heiko Stuebner wrote:
> There are some more General Register Files used in devicetree files
> already, but as of now undocumented in the binding document, fix that.
> 
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---
>  Documentation/devicetree/bindings/soc/rockchip/grf.txt | 4 ++++
>  1 file changed, 4 insertions(+)

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


From robh at kernel.org  Mon May 23 14:39:37 2016
From: robh at kernel.org (Rob Herring)
Date: Mon, 23 May 2016 16:39:37 -0500
Subject: [PATCH 1/4] dt-bindings: rng: Northstar Plus SoC rng bindings
In-Reply-To: <1464020451-16520-2-git-send-email-yendapally.reddy@broadcom.com>
References: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>
 <1464020451-16520-2-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <20160523213937.GA13580@rob-hp-laptop>

On Mon, May 23, 2016 at 12:20:48PM -0400, Yendapally Reddy Dhananjaya Reddy wrote:
> Document the bindings used by Northstar Plus(NSP) SoC random number
> generator.
> 
> Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
> ---
>  Documentation/devicetree/bindings/rng/brcm,bcm2835.txt | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)

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


From linux at armlinux.org.uk  Mon May 23 15:05:14 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Mon, 23 May 2016 23:05:14 +0100
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <CAOMZO5DjjgNk+uHyH7Avvfrt_TNPaZ+SUtHzON5fPU=25_gKOg@mail.gmail.com>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
 <20160523182807.GY19428@n2100.arm.linux.org.uk>
 <CAJZ5v0ipPVsZmu+RVfrPChA7banMGFNsfMt=if0V3XfVdstRNQ@mail.gmail.com>
 <CAJZ5v0j0VbyHNT_ZmThsdQfRWzf7SG65A8-bPxoAUxZJgR96og@mail.gmail.com>
 <CAOMZO5Cbue9L2JGA0kv7nTZ=78oKDhNu6WLRUmcsSuLHscDVUQ@mail.gmail.com>
 <20160523210738.GZ19428@n2100.arm.linux.org.uk>
 <CAOMZO5DjjgNk+uHyH7Avvfrt_TNPaZ+SUtHzON5fPU=25_gKOg@mail.gmail.com>
Message-ID: <20160523220514.GB19428@n2100.arm.linux.org.uk>

On Mon, May 23, 2016 at 06:38:31PM -0300, Fabio Estevam wrote:
> On Mon, May 23, 2016 at 6:07 PM, Russell King - ARM Linux
> <linux at armlinux.org.uk> wrote:
> 
> > Read the code again.  There's three states:
> >
> > 1. CONFIG_SMP=n - it always returns false.
> > 2. CONFIG_SMP=y, CONFIG_SMP_ON_UP=n - it always returns true.  Such a
> >    kernel can _only_ be run on SMP capable systems.
> > 3. CONFIG_SMP=y, CONFIG_SMP_ON_UP=y - it returns depending on whether
> >    we detect that the CPU is SMP capable.
> 
> Yes, I meant that on imx6ul we have option 2 above with imx_v6_v7_defconfig.

I don't think so, unless you specifically turn off CONFIG_SMP_ON_UP.
It defaults to 'y', so imx_v6_v7_defconfig should result in this being
'y'.

> Also tested option 3 and is_smp() returns true as well.

So that means the MPIDR register is telling the kernel...

* The boot CPU has multiprocessor extensions.
* The boot CPU is not part of a uniprocessor system.

> I will try to see why GIC on this SoC cannot work in SMP.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From festevam at gmail.com  Mon May 23 15:25:28 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 23 May 2016 19:25:28 -0300
Subject: Crash after 'reboot' due to 9be4fd2c7723a
In-Reply-To: <20160523220514.GB19428@n2100.arm.linux.org.uk>
References: <CAOMZO5A62LgnyT0sQw5N-xeHaD0nSGTjAFxUx=_6OpUm02robA@mail.gmail.com>
 <CAJZ5v0hX1dZ+79-KCyumf57o02WKivxcRLJ1Zi8akrqu_2CZEQ@mail.gmail.com>
 <CAOMZO5CD08cX0yDBZTdFV+iwgr__fjSaaWvgjimotr5L1yrbaQ@mail.gmail.com>
 <2148724.oQlEHos3jS@vostro.rjw.lan>
 <20160523182807.GY19428@n2100.arm.linux.org.uk>
 <CAJZ5v0ipPVsZmu+RVfrPChA7banMGFNsfMt=if0V3XfVdstRNQ@mail.gmail.com>
 <CAJZ5v0j0VbyHNT_ZmThsdQfRWzf7SG65A8-bPxoAUxZJgR96og@mail.gmail.com>
 <CAOMZO5Cbue9L2JGA0kv7nTZ=78oKDhNu6WLRUmcsSuLHscDVUQ@mail.gmail.com>
 <20160523210738.GZ19428@n2100.arm.linux.org.uk>
 <CAOMZO5DjjgNk+uHyH7Avvfrt_TNPaZ+SUtHzON5fPU=25_gKOg@mail.gmail.com>
 <20160523220514.GB19428@n2100.arm.linux.org.uk>
Message-ID: <CAOMZO5D8-GF-0MDExM=2si1yNcqwO07pNWUkjRz0uuzkdYka_Q@mail.gmail.com>

On Mon, May 23, 2016 at 7:05 PM, Russell King - ARM Linux
<linux at armlinux.org.uk> wrote:

> I don't think so, unless you specifically turn off CONFIG_SMP_ON_UP.
> It defaults to 'y', so imx_v6_v7_defconfig should result in this being
> 'y'.

Sorry, you are right: option 3 (CONFIG_SMP=y and CONFIG_SMP_ON_UP=y)
is the default one with imx_v6_v7_defconfig.


From cov at codeaurora.org  Mon May 23 15:26:25 2016
From: cov at codeaurora.org (Christopher Covington)
Date: Mon, 23 May 2016 18:26:25 -0400
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
In-Reply-To: <f49d58ed-38b4-6284-11c2-8708d8443b14@codeaurora.org>
References: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
 <20160523172527.GK4976@leverpostej>
 <f49d58ed-38b4-6284-11c2-8708d8443b14@codeaurora.org>
Message-ID: <57438391.7090405@codeaurora.org>

On 05/23/2016 02:22 PM, Neil Leeder wrote:
> 
> On 5/23/2016 01:25 PM, Mark Rutland wrote:
>> On Fri, May 20, 2016 at 03:13:07PM -0400, Neil Leeder wrote:
>>> L2 registers are accessed using a select register and data
>>> register pair. To prevent multiple concurrent writes to the
>>> select register by independent drivers, the write to the
>>> select register and the associated access of the data register
>>> are protected with a lock. All drivers accessing the L2
>>> registers use the set and get functions provided by
>>> l2-accessors to ensure correct reads and writes to L2 registers.
>>
>> What will this be used for? (i.e. which drivers want to touch the L2
>> registers?).
>>
>> Generally we expect FW to configure the caches and interconnect
>> appropriately.
> 
> The primary use is in the L2 PMU driver, which will be posted shortly.
> 
>>
>>> Signed-off-by: Neil Leeder <nleeder at codeaurora.org>
>>> ---
>>>  drivers/soc/qcom/Kconfig              |  9 +++++
>>>  drivers/soc/qcom/Makefile             |  1 +
>>>  drivers/soc/qcom/l2-accessors.c       | 66 +++++++++++++++++++++++++++++++++++
>>>  include/linux/soc/qcom/l2-accessors.h | 27 ++++++++++++++
>>>  4 files changed, 103 insertions(+)
>>>  create mode 100644 drivers/soc/qcom/l2-accessors.c
>>>  create mode 100644 include/linux/soc/qcom/l2-accessors.h
>>
>> These are awfully generic file names (and function names). Which SoCs
>> does this apply to?
>>
>> It would be good to give these more specific names.
> 
> It's under soc/qcom, and dependent on ARCH_QCOM and (in v2) also on ARM64. It applies to all QCOM ARM64 SoCs.
> Given that it can only be used in a QCOM driver, and the include path has qcom in it, I'd
> prefer not to add redundancy by adding another qcom in there.

They ended up calling the pinctrl file qcom/pinctrl/qdf2xxx.c.

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=8f1338cd80648adf5434798f5393ad7c55d10848

Regards,
Cov

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


From christopher.spinrath at rwth-aachen.de  Mon May 23 15:37:28 2016
From: christopher.spinrath at rwth-aachen.de (Christopher Spinrath)
Date: Tue, 24 May 2016 00:37:28 +0200
Subject: [PATCH 1/2] ARM: dts: imx6q: extend support for the cm-fx6
In-Reply-To: <1c18d1b1f80b47cab2d06b1167407ae8@rwthex-s2-a.rwth-ad.de>
References: <709d6b3d522f4fcb8112830e0426dbb3@rwthex-s1-b.rwth-ad.de>
 <1c18d1b1f80b47cab2d06b1167407ae8@rwthex-s2-a.rwth-ad.de>
Message-ID: <b8378072-b645-ebf1-c4c5-26bed85a97ae@rwth-aachen.de>

Hi Lucas,

Thanks for your review!

On 05/23/2016 11:03 AM, Lucas Stach wrote:
> Am Montag, den 23.05.2016, 00:47 +0200 schrieb
> christopher.spinrath at rwth-aachen.de:
>> From: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>
>>
>> The cm-fx6 module has an on-board spi-flash chip for its firmware, an
>> eeprom (containing e.g. the mac address of the on-board Ethernet),
>> a sata port, a pcie controller, an USB hub, and an USB otg port.
>> Enable support for them. In addition, enable syscon poweroff support.
>>
>> Signed-off-by: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>
>> ---
>>  arch/arm/boot/dts/imx6q-cm-fx6.dts | 136 +++++++++++++++++++++++++++++++++++++
>>  1 file changed, 136 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/imx6q-cm-fx6.dts b/arch/arm/boot/dts/imx6q-cm-fx6.dts
>> index 99b46f8..f4fc22e 100644
>> --- a/arch/arm/boot/dts/imx6q-cm-fx6.dts
>> +++ b/arch/arm/boot/dts/imx6q-cm-fx6.dts
>> @@ -31,6 +31,61 @@
>>  			linux,default-trigger = "heartbeat";
>>  		};
>>  	};
>> +
>> +	regulators {
>> +		compatible = "simple-bus";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +
> 
> Please remove this regulator pseudo-bus. It doesn't exist in hardware.
> The regulators are direct children of the module.
> 

OK, I will remove it. I added it because it seems to be common (e.g.
sabrelite and wandboard use it).

>> +		reg_usb_otg_vbus: usb_otg_vbus {
>> +			compatible = "regulator-fixed";
>> +			regulator-name = "usb_otg_vbus";
>> +			regulator-min-microvolt = <5000000>;
>> +			regulator-max-microvolt = <5000000>;
>> +			gpio = <&gpio3 22 0>;
>> +			enable-active-high;
>> +		};
>> +
>> +		reg_usb_h1_vbus: usb_h1_vbus {
>> +			compatible = "regulator-fixed";
>> +			regulator-name = "usb_h1_vbus";
>> +			regulator-min-microvolt = <5000000>;
>> +			regulator-max-microvolt = <5000000>;
>> +			gpio = <&gpio7 8 0>;
>> +			enable-active-high;
>> +		};
>> +	};
>> +};
>> +
>> +&ecspi1 {
>> +	fsl,spi-num-chipselects = <2>;
>> +	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
>> +	pinctrl-names = "default";
>> +	pinctrl-0 = <&pinctrl_ecspi1>;
>> +	status = "okay";
>> +
>> +	flash: m25p80 at 0 {
>> +		#address-cells = <1>;
>> +		#size-cells = <1>;
>> +		compatible = "st,m25p", "jedec,spi-nor";
>> +		spi-max-frequency = <20000000>;
>> +		reg = <0>;
>> +
>> +		partition at 0 {
>> +			label = "uboot";
>> +			reg = <0x0 0xc0000>;
>> +		};
>> +
>> +		partition at c0000 {
>> +			label = "uboot environment";
>> +			reg = <0xc0000 0x40000>;
>> +		};
>> +
>> +		partition at 100000 {
>> +			label = "reserved";
>> +			reg = <0x100000 0x100000>;
>> +		};
> 
> Partition layouts don't belong in the upstream DT, as it a device
> configuration thing. Please kep them in the bootloader/firmware and make
> this one pass the partition layout to the kernel.
> 
OK, removed (although I do not like to patch the firmware/uboot).

>> +	};
>>  };
>>  
>>  &fec {
>> @@ -46,8 +101,31 @@
>>  	status = "okay";
>>  };
>>  
>> +&i2c3 {
>> +	pinctrl-names = "default";
>> +	pinctrl-0 = <&pinctrl_i2c3>;
>> +	status = "okay";
>> +	clock-frequency = <100000>;
>> +
>> +	eeprom at 50 {
>> +		compatible = "at24,24c02";
>> +		reg = <0x50>;
>> +		pagesize = <16>;
>> +	};
>> +};
>> +
>>  &iomuxc {
>>  	imx6q-cm-fx6 {
>> +		pinctrl_ecspi1: ecspi1grp {
>> +			fsl,pins = <
>> +				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		 0x100b1
>> +				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		 0x100b1
>> +				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		 0x100b1
>> +				MX6QDL_PAD_EIM_EB2__GPIO2_IO30		0x100b1
>> +				MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x100b1
>> +			>;
>> +		};
>> +
>>  		pinctrl_enet: enetgrp {
>>  			fsl,pins = <
>>  				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
>> @@ -91,17 +169,75 @@
>>  			>;
>>  		};
>>  
>> +		pinctrl_i2c3: i2c3grp {
>> +			fsl,pins = <
>> +				MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
>> +				MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
>> +			>;
>> +		};
>> +
>> +		pinctrl_pcie: pciegrp {
>> +			fsl,pins = <
>> +				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000
>> +				MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x80000000
>> +			>;
>> +		};
>> +
>>  		pinctrl_uart4: uart4grp {
>>  			fsl,pins = <
>>  				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
>>  				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
>>  			>;
>>  		};
>> +
>> +		pinctrl_usbh1: usbh1grp {
>> +			fsl,pins = <
>> +				MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x80000000
>> +			>;
>> +		};
>> +
>> +		pinctrl_usbotg: usbotggrp {
>> +			fsl,pins = <
>> +				MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
>> +				MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
>> +			>;
>> +		};
>>  	};
>>  };
>>  
>> +&pcie {
>> +	pinctrl-names = "default";
>> +	pinctrl-0 = <&pinctrl_pcie>;
>> +	reset-gpio = <&gpio1 26 0>;
>> +	power-on-gpio = <&gpio2 24 0>;
> 
> There is no power-on-gpio in the upstream binding.
> 

uh, this one slipped through my clean up. Removed.

>> +	status = "okay";
>> +};
>> +
>> +&sata {
>> +	status = "okay";
>> +};
>> +
>> +&snvs_poweroff {
>> +	status = "okay";
>> +};
>> +
>>  &uart4 {
>>  	pinctrl-names = "default";
>>  	pinctrl-0 = <&pinctrl_uart4>;
>>  	status = "okay";
>>  };
>> +
>> +&usbotg {
>> +	vbus-supply = <&reg_usb_otg_vbus>;
>> +	pinctrl-names = "default";
>> +	pinctrl-0 = <&pinctrl_usbotg>;
>> +	dr_mode = "otg";
>> +	status = "okay";
>> +};
>> +
>> +&usbh1 {
>> +	vbus-supply = <&reg_usb_h1_vbus>;
>> +	pinctrl-names = "default";
>> +	pinctrl-0 = <&pinctrl_usbh1>;
>> +	status = "okay";
>> +};

Cheers,
Christopher


From timur at codeaurora.org  Mon May 23 16:04:44 2016
From: timur at codeaurora.org (Timur Tabi)
Date: Mon, 23 May 2016 18:04:44 -0500
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
In-Reply-To: <57438391.7090405@codeaurora.org>
References: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
 <20160523172527.GK4976@leverpostej>
 <f49d58ed-38b4-6284-11c2-8708d8443b14@codeaurora.org>
 <57438391.7090405@codeaurora.org>
Message-ID: <57438C8C.7050109@codeaurora.org>

Christopher Covington wrote:
> They ended up calling the pinctrl file qcom/pinctrl/qdf2xxx.c.
>
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=8f1338cd80648adf5434798f5393ad7c55d10848

To be fair, none of the other drivers in drivers/soc/ specify any 
specific SOCs.  They all have generic file names.

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora
Forum, a Linux Foundation collaborative project.


From christopher.spinrath at rwth-aachen.de  Mon May 23 16:08:00 2016
From: christopher.spinrath at rwth-aachen.de (Christopher Spinrath)
Date: Tue, 24 May 2016 01:08:00 +0200
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <20abc2f6769b4369ba87ec27274a090e@rwthex-s2-a.rwth-ad.de>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
 <20abc2f6769b4369ba87ec27274a090e@rwthex-s2-a.rwth-ad.de>
Message-ID: <644530ff6bb04b5898dc33604dc7a93a@rwthex-s1-b.rwth-ad.de>

Hi Fabio,

On 05/23/2016 07:49 PM, Fabio Estevam wrote:
> On Sun, May 22, 2016 at 7:47 PM,  <christopher.spinrath at rwth-aachen.de> wrote:
> 
>> diff --git a/arch/arm/boot/dts/imx6q-utilite-pro.dts b/arch/arm/boot/dts/imx6q-utilite-pro.dts
>> new file mode 100644
>> index 0000000..bcd8e0d
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/imx6q-utilite-pro.dts
>> @@ -0,0 +1,128 @@
>> +/*
>> + * Copyright 2016 Christopher Spinrath
>> + * Copyright 2013 CompuLab Ltd.
>> + *
>> + * Based on the GPLv2 licensed devicetree distributed with the vendor
>> + * kernel for the Utilite Pro:
>> + *     Copyright 2013 CompuLab Ltd.
>> + *     Author: Valentin Raevsky <valentin at compulab.co.il>
>> + *
>> + * The code contained herein is licensed under the GNU General Public
>> + * License. You may obtain a copy of the GNU General Public License
>> + * Version 2 or later at the following locations:
> 
> Can you make this dual GPL/X11 license?
> 
> For reference take a look at:
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/imx6sl-warp.dts?id=refs/tags/v4.6
> 
I would like to but I'm not sure if I'm allowed to. As I stated in the
license header some nodes are copied (and cleaned up) from the vendor
kernel/devicetree. They are licensed GPL-v2 only. So I don't know, can I
add the X11 license?

> 
>> +       gpio-keys {
>> +               compatible = "gpio-keys";
>> +               power {
>> +                       label = "Power Button";
>> +                       gpios = <&gpio1 29 1>;
> 
> Better to use a label like:
> gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
> 
>> +&iomuxc {
>> +       pinctrl-names = "default";
>> +       pinctrl-0 = <&pinctrl_hog>;
>> +
>> +       hog {
>> +               pinctrl_hog: hoggrp {
>> +                       fsl,pins = <
>> +                               /* power button */
>> +                               MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
> 
> Better to avoid 0x80000000. Replace it with the real iomux value
> instead so that you don't need to rely on the bootloader
> configuration.
hmm, I don't know how to determine this value. The device documentation
I have does not say anything about it and the vendor kernel uses
0x80000000...

> 
>> +
>> +       imx6q-utilite-pro {
>> +               pinctrl_i2c1: i2c1grp {
>> +                       fsl,pins = <
>> +                               MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
>> +                               MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
>> +                       >;
>> +               };
> 
> You should better remove one level of indentation. Check this commit
> for reference:
> https://git.kernel.org/cgit/linux/kernel/git/shawnguo/linux.git/commit/arch/arm/boot/dts/imx6q-tbs2910.dts?h=for-next&id=aa7871b53bc3c36b4adefe67f728143e2deeec93
> 
OK, done (I also had to change this in the imx6q-cm-fx6.dts to make it
work).

>> +&uart2 {
>> +       pinctrl-names = "default";
>> +       pinctrl-0 = <&pinctrl_uart2>;
>> +       fsl,uart-has-rtscts;
>> +       dma-names = "rx", "tx";
>> +       dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
> 
> No need to add the dma nodes as they are already present in imx6qdl.dtsi.
> 
Indeed, I removed them.


Thanks for your review!

Cheers,
Christopher


From christopher.spinrath at rwth-aachen.de  Mon May 23 16:13:11 2016
From: christopher.spinrath at rwth-aachen.de (Christopher Spinrath)
Date: Tue, 24 May 2016 01:13:11 +0200
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <20abc2f6769b4369ba87ec27274a090e@rwthex-s2-a.rwth-ad.de>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
 <20abc2f6769b4369ba87ec27274a090e@rwthex-s2-a.rwth-ad.de>
Message-ID: <098a5b4b7b8a4ad9a5711842959c4a53@rwthex-s1-b.rwth-ad.de>

Hi Fabio,

sorry I forgot in my last reply to mention:

On 05/23/2016 07:49 PM, Fabio Estevam wrote:

-- snip --

> 
>> +       gpio-keys {
>> +               compatible = "gpio-keys";
>> +               power {
>> +                       label = "Power Button";
>> +                       gpios = <&gpio1 29 1>;
> 
> Better to use a label like:
> gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;

Will do. Thanks!

Cheers,
Christopher

> 
>> +&iomuxc {
>> +       pinctrl-names = "default";
>> +       pinctrl-0 = <&pinctrl_hog>;
>> +
>> +       hog {
>> +               pinctrl_hog: hoggrp {
>> +                       fsl,pins = <
>> +                               /* power button */
>> +                               MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
> 
> Better to avoid 0x80000000. Replace it with the real iomux value
> instead so that you don't need to rely on the bootloader
> configuration.
> 
>> +
>> +       imx6q-utilite-pro {
>> +               pinctrl_i2c1: i2c1grp {
>> +                       fsl,pins = <
>> +                               MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
>> +                               MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
>> +                       >;
>> +               };
> 
> You should better remove one level of indentation. Check this commit
> for reference:
> https://git.kernel.org/cgit/linux/kernel/git/shawnguo/linux.git/commit/arch/arm/boot/dts/imx6q-tbs2910.dts?h=for-next&id=aa7871b53bc3c36b4adefe67f728143e2deeec93
> 
>> +&uart2 {
>> +       pinctrl-names = "default";
>> +       pinctrl-0 = <&pinctrl_uart2>;
>> +       fsl,uart-has-rtscts;
>> +       dma-names = "rx", "tx";
>> +       dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
> 
> No need to add the dma nodes as they are already present in imx6qdl.dtsi.
> 


From christopher.spinrath at rwth-aachen.de  Mon May 23 16:15:07 2016
From: christopher.spinrath at rwth-aachen.de (Christopher Spinrath)
Date: Tue, 24 May 2016 01:15:07 +0200
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <9b24c4b30f424407902589fcc4598ec5@rwthex-w2-a.rwth-ad.de>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
 <9b24c4b30f424407902589fcc4598ec5@rwthex-w2-a.rwth-ad.de>
Message-ID: <2d1541bdd75c48a593f0e180c411cd4b@rwthex-s1-b.rwth-ad.de>

Hi Stefan,

On 05/23/2016 10:56 PM, Stefan Wahren wrote:
> Hi Christopher,
> 
>> christopher.spinrath at rwth-aachen.de hat am 23. Mai 2016 um 00:47 geschrieben:
>>
>>
>> From: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>
>>
>> The CompuLab Utilite Pro is a miniature fanless desktop pc based on
>> the i.MX6 Quad powered cm-fx6 module. It features two serial ports,
>> USB OTG, 4x USB, analog audio and S/PDIF, 2x Gb Ethernet, HDMI and
>> DVI ports, an on-board 32GB SSD, a mmc slot, and on-board wifi/bt.
>>
>> Add initial support for it including USB, Ethernet (both ports), sata
>> and HDMI support.
>>
>> Signed-off-by: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>
>> ---
>>  arch/arm/boot/dts/Makefile              |   1 +
>>  arch/arm/boot/dts/imx6q-utilite-pro.dts | 128
>> ++++++++++++++++++++++++++++++++
>>  2 files changed, 129 insertions(+)
>>  create mode 100644 arch/arm/boot/dts/imx6q-utilite-pro.dts
>>
>> ...
>> diff --git a/arch/arm/boot/dts/imx6q-utilite-pro.dts
>> b/arch/arm/boot/dts/imx6q-utilite-pro.dts
>> new file mode 100644
>> index 0000000..bcd8e0d
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/imx6q-utilite-pro.dts
>> @@ -0,0 +1,128 @@
>> +/*
>> + * Copyright 2016 Christopher Spinrath
>> + * Copyright 2013 CompuLab Ltd.
>> + *
>> + * Based on the GPLv2 licensed devicetree distributed with the vendor
>> + * kernel for the Utilite Pro:
>> + *	Copyright 2013 CompuLab Ltd.
>> + *	Author: Valentin Raevsky <valentin at compulab.co.il>
>> + *
>> + * The code contained herein is licensed under the GNU General Public
>> + * License. You may obtain a copy of the GNU General Public License
>> + * Version 2 or later at the following locations:
>> + *
>> + * http://www.opensource.org/licenses/gpl-license.html
>> + * http://www.gnu.org/copyleft/gpl.html
>> + */
>> +
>> ...
>> +
>> +		pinctrl_uart2: uart2grp {
>> +			fsl,pins = <
>> +				MX6QDL_PAD_GPIO_7__UART2_TX_DATA 0x1b0b1
>> +				MX6QDL_PAD_GPIO_8__UART2_RX_DATA 0x1b0b1
>> +				MX6QDL_PAD_SD4_DAT5__UART2_RTS_B 0x1b0b1
>> +				MX6QDL_PAD_SD4_DAT6__UART2_CTS_B 0x1b0b1
>> +			>;
>> +		};
>> +	};
>> +};
>> +
>> +&pcie {
>> +	pcie at 0,0 {
>> +		reg = <0x000000 0 0 0 0>;
>> +		#address-cells = <3>;
>> +		#size-cells = <2>;
>> +
>> +		/* non-removable i211 ethernet card */
>> +		eth1: intel,i211 at pcie0,0 {
>> +			reg = <0x010000 0 0 0 0>;
>> +		};
>> +	};
>> +};
>> +
>> +&uart2 {
>> +	pinctrl-names = "default";
>> +	pinctrl-0 = <&pinctrl_uart2>;
>> +	fsl,uart-has-rtscts;
> 
> this property is deprecated so please use the generic one:
> 
> https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/?id=1006ed7e1b258dac3e85c9fafe9d38b6020c917f
> 

Thanks for pointing that out. I will switch to the generic property.

Cheers,
Christopher

> Stefan
> 
>> +	dma-names = "rx", "tx";
>> +	dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
>> +	status = "okay";
>> +};
>> -- 
>> 2.8.2
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From bryantly at linux.vnet.ibm.com  Mon May 23 16:17:35 2016
From: bryantly at linux.vnet.ibm.com (Bryant G Ly)
Date: Mon, 23 May 2016 19:17:35 -0400
Subject: [PATCH] Fix for hang of Ordered task in TCM
In-Reply-To: <1463550825.22249.17.camel@haakon3.risingtidesystems.com>
References: <1463177741-4385-1-git-send-email-mikecyr@linux.vnet.ibm.com>
 <1463550825.22249.17.camel@haakon3.risingtidesystems.com>
Message-ID: <20160523191735.Horde.6wmWQ7EiiPavHDD7pNfVtQ1@ltc.linux.ibm.com>


Quoting "Nicholas A. Bellinger" <nab at linux-iscsi.org>:

<SNIP>
>
> So AFAICT for delayed commands, the above patch ends up skipping these
> three checks subsequently when doing __target_execute_cmd() directly
> from target_restart_delayed_cmds(), no..?
>
> After pondering this some more, what about moving these checks into
> __target_execute_cmd() to handle both target_core_transport.c cases
> instead..?
>
> We'll also need a parameter for internal COMPARE_AND_WRITE usage
> within compare_and_write_callback(), to bypass checks upon secondary
> ->execute_cmd() WRITE payload submission after READ + COMPARE has
> completed successfully.
>
> WDYT..?
>
> diff --git a/drivers/target/target_core_internal.h  
> b/drivers/target/target_core_internal.h
> index fc91e85..e2c970a 100644
> --- a/drivers/target/target_core_internal.h
> +++ b/drivers/target/target_core_internal.h
> @@ -146,6 +146,7 @@ sense_reason_t	target_cmd_size_check(struct  
> se_cmd *cmd, unsigned int size);
>  void	target_qf_do_work(struct work_struct *work);
>  bool	target_check_wce(struct se_device *dev);
>  bool	target_check_fua(struct se_device *dev);
> +void	__target_execute_cmd(struct se_cmd *, bool);
>
>  /* target_core_stat.c */
>  void	target_stat_setup_dev_default_groups(struct se_device *);
> diff --git a/drivers/target/target_core_sbc.c  
> b/drivers/target/target_core_sbc.c
> index a9057aa..04f616b 100644
> --- a/drivers/target/target_core_sbc.c
> +++ b/drivers/target/target_core_sbc.c
> @@ -602,7 +602,7 @@ static sense_reason_t  
> compare_and_write_callback(struct se_cmd *cmd, bool succes
>  	cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
>  	spin_unlock_irq(&cmd->t_state_lock);
>
> -	__target_execute_cmd(cmd);
> +	__target_execute_cmd(cmd, false);
>
>  	kfree(buf);
>  	return ret;
> diff --git a/drivers/target/target_core_transport.c  
> b/drivers/target/target_core_transport.c
> index 6c089af..f3e93dd 100644
> --- a/drivers/target/target_core_transport.c
> +++ b/drivers/target/target_core_transport.c
> @@ -1761,20 +1761,45 @@ queue_full:
>  }
>  EXPORT_SYMBOL(transport_generic_request_failure);
>
> -void __target_execute_cmd(struct se_cmd *cmd)
> +void __target_execute_cmd(struct se_cmd *cmd, bool do_checks)
>  {
>  	sense_reason_t ret;
>
> -	if (cmd->execute_cmd) {
> -		ret = cmd->execute_cmd(cmd);
> -		if (ret) {
> -			spin_lock_irq(&cmd->t_state_lock);
> -			cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
> -			spin_unlock_irq(&cmd->t_state_lock);
> +	if (!cmd->execute_cmd) {
> +		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> +		goto err;
> +	}
> +	if (do_checks) {
> +		/*
> +		 * Check for an existing UNIT ATTENTION condition after
> +		 * target_handle_task_attr() has done SAM task attr
> +		 * checking, and possibly have already defered execution
> +		 * out to target_restart_delayed_cmds() context.
> +		 */
> +		ret = target_scsi3_ua_check(cmd);
> +		if (ret)
> +			goto err;
>
> -			transport_generic_request_failure(cmd, ret);
> +		ret = target_alua_state_check(cmd);
> +		if (ret)
> +			goto err;
> +
> +		ret = target_check_reservation(cmd);
> +		if (ret) {
> +			cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
> +			goto err;
>  		}
>  	}
> +
> +	ret = cmd->execute_cmd(cmd);
> +	if (!ret)
> +		return;
> +err:
> +	spin_lock_irq(&cmd->t_state_lock);
> +	cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
> +	spin_unlock_irq(&cmd->t_state_lock);
> +
> +	transport_generic_request_failure(cmd, ret);
>  }
>
>  static int target_write_prot_action(struct se_cmd *cmd)
> @@ -1899,7 +1924,7 @@ void target_execute_cmd(struct se_cmd *cmd)
>  		return;
>  	}
>
> -	__target_execute_cmd(cmd);
> +	__target_execute_cmd(cmd, true);
>  }
>  EXPORT_SYMBOL(target_execute_cmd);
>
> @@ -1923,7 +1948,7 @@ static void target_restart_delayed_cmds(struct  
> se_device *dev)
>  		list_del(&cmd->se_delayed_node);
>  		spin_unlock(&dev->delayed_cmd_lock);
>
> -		__target_execute_cmd(cmd);
> +		__target_execute_cmd(cmd, true);
>
>  		if (cmd->sam_task_attr == TCM_ORDERED_TAG)
>  			break;
> diff --git a/include/target/target_core_fabric.h  
> b/include/target/target_core_fabric.h
> index ec79da3..334f107 100644
> --- a/include/target/target_core_fabric.h
> +++ b/include/target/target_core_fabric.h
> @@ -163,7 +163,6 @@ int	core_tmr_alloc_req(struct se_cmd *, void *,  
> u8, gfp_t);
>  void	core_tmr_release_req(struct se_tmr_req *);
>  int	transport_generic_handle_tmr(struct se_cmd *);
>  void	transport_generic_request_failure(struct se_cmd *, sense_reason_t);
> -void	__target_execute_cmd(struct se_cmd *);
>  int	transport_lookup_tmr_lun(struct se_cmd *, u64);
>  void	core_allocate_nexus_loss_ua(struct se_node_acl *acl);
>

Looks good to me. Nick just to let you know I've been working with  
Mike on VSCSI
Target Fabric and we need this patch in kernel 4.4 do you know of the  
process in
getting that there?

Thanks

-Bryant

> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe target-devel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html




From festevam at gmail.com  Mon May 23 16:20:35 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 23 May 2016 20:20:35 -0300
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <644530ff6bb04b5898dc33604dc7a93a@rwthex-s1-b.rwth-ad.de>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
 <20abc2f6769b4369ba87ec27274a090e@rwthex-s2-a.rwth-ad.de>
 <644530ff6bb04b5898dc33604dc7a93a@rwthex-s1-b.rwth-ad.de>
Message-ID: <CAOMZO5CMjaxxR-_i9O1U_r_LxW0L61Rg8uySaThVPD2w2xgafg@mail.gmail.com>

Hi Christopher,

On Mon, May 23, 2016 at 8:08 PM, Christopher Spinrath
<christopher.spinrath at rwth-aachen.de> wrote:

> I would like to but I'm not sure if I'm allowed to. As I stated in the
> license header some nodes are copied (and cleaned up) from the vendor
> kernel/devicetree. They are licensed GPL-v2 only. So I don't know, can I
> add the X11 license?

Maybe you could contact the original author anc check?

>> Better to avoid 0x80000000. Replace it with the real iomux value
>> instead so that you don't need to rely on the bootloader
>> configuration.
> hmm, I don't know how to determine this value. The device documentation
> I have does not say anything about it and the vendor kernel uses
> 0x80000000...

The default value of register IOMUXC_SW_PAD_CTL_PAD_ENET_TX_DATA1 is
0x1b0b0, so you can use this value.

Another thing I forgot to comment: instead of putting this pin inside
the hog group you could put it inside the gpio-keys node.


From helgaas at kernel.org  Mon May 23 16:39:18 2016
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Mon, 23 May 2016 18:39:18 -0500
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>
References: <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>
Message-ID: <20160523233918.GA32555@localhost>

On Mon, May 23, 2016 at 03:16:01PM +0000, Gabriele Paoloni wrote:
> Hi Lorenzo
> 
> > -----Original Message-----
> > From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
> > Sent: 23 May 2016 11:57
> > To: Ard Biesheuvel
> > Cc: Gabriele Paoloni; Jon Masters; Tomasz Nowicki; helgaas at kernel.org;
> > arnd at arndb.de; will.deacon at arm.com; catalin.marinas at arm.com;
> > rafael at kernel.org; hanjun.guo at linaro.org; okaya at codeaurora.org;
> > jchandra at broadcom.com; linaro-acpi at lists.linaro.org; linux-
> > pci at vger.kernel.org; dhdang at apm.com; Liviu.Dudau at arm.com;
> > ddaney at caviumnetworks.com; jeremy.linton at arm.com; linux-
> > kernel at vger.kernel.org; linux-acpi at vger.kernel.org;
> > robert.richter at caviumnetworks.com; Suravee.Suthikulpanit at amd.com;
> > msalter at redhat.com; Wangyijing; mw at semihalf.com;
> > andrea.gallo at linaro.org; linux-arm-kernel at lists.infradead.org
> > Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI host
> > controller
> > 
> > On Fri, May 20, 2016 at 11:14:03AM +0200, Ard Biesheuvel wrote:
> > > On 20 May 2016 at 10:40, Gabriele Paoloni
> > <gabriele.paoloni at huawei.com> wrote:
> > > > Hi Ard
> > > >
> > > >> -----Original Message-----
> > > >> From: Ard Biesheuvel [mailto:ard.biesheuvel at linaro.org]
> > > [...]
> > > >>
> > > >> Is the PCIe root complex so special that you cannot simply
> > describe an
> > > >> implementation that is not PNP0408 compatible as something else,
> > under
> > > >> its own unique HID? If everybody is onboard with using ACPI, how
> > is
> > > >> this any different from describing other parts of the platform
> > > >> topology? Even if the SBSA mandates generic PCI, they already
> > deviated
> > > >> from that when they built the hardware, so pretending that it is a
> > > >> PNP0408 with quirks really does not buy us anything.
> > > >
> > > > From my understanding we want to avoid this as this would allow
> > each
> > > > vendor to come up with his own code and it would be much more
> > effort
> > > > for the PCI maintainer to rework the PCI framework to accommodate
> > X86
> > > > and "all" ARM64 Host Controllers...
> > > >
> > > > I guess this approach is too risky and we want to avoid this.
> > Through
> > > > standardization we can more easily maintain the code and scale it
> > to
> > > > multiple SoCs...
> > > >
> > > > So this is my understanding; maybe Jon, Tomasz or Lorenzo can give
> > > > a bit more explanation...
> > > >
> > >
> > > OK, so that boils down to recommending to vendors to represent known
> > > non-compliant hardware as compliant, just so that we don't have to
> > > change the code to support additional flavors of ECAM ? It's fine to
> > > be pragmatic, but that sucks.
> > >
> > > We keep confusing the x86 case with the ARM case here: for x86, they
> > > needed to deal with broken hardware *after* the fact, and all they
> > > could do is find /some/ distinguishing feature in order to guess
> > which
> > > exact hardware they might be running on. For arm64, it is the
> > opposite
> > > case. We are currently in a position where we can demand vendors to
> > > comply with the standards they endorsed themselves, and (ab)using
> > ACPI
> > > + DMI as a de facto platform description rather than plain ACPI makes
> > > me think the DT crowd were actually right from the beginning. It
> > > *directly* violates the standardization principle, since it requires
> > a
> > > priori knowledge inside the OS that a certain 'generic' device must
> > be
> > > driven in a special way.
> > >
> > > So can anyone comment on the feasibility of adding support for
> > devices
> > > with vendor specific HIDs (and no generic CIDs) to the current ACPI
> > > ECAM driver in Linux?

I don't think of ECAM support itself as a "driver".  It's just a
service available to drivers, similar to OF resource parsing.

Per PCI Firmware r3.2, sec 4.1.5, "PNP0A03" means a PCI/PCI-X/PCIe
host bridge.  "PNP0A08" means a PCI-X Mode 2 or PCIe bridge that
supports extended config space.  It doesn't specify how we access that
config space, so I think hardware with non-standard ECAM should still
have PNP0A03 and PNP0A08 in _CID or _HID.

"ECAM" as used in the specs (PCIe r3.0, sec 7.2.2, and PCI Firmware
r3.2, sec 4.1) means:

  (a) a memory-mapped model for config space access, and
  (b) a specific mapping of address bits to bus/device/function/
      register

MCFG and _CBA assume both (a) and (b), so I think a device with
non-standard ECAM mappings should not be described in MCFG or _CBA.

If a bridge has ECAM with non-standard mappings, I think either a
vendor-specific _HID or a device-specific method, e.g., _DSM, could
communicate that.

Jon, I agree that we should avoid describing non-standardized hardware
in Linux-specific ways.  Is there a mechanism in use already?  How
does Windows handle this?  DMI is a poor long-term solution because it
requires ongoing maintenance for new platforms, but I think it's OK
for getting started with platforms already shipping.

A _DSM has the advantage that once it is defined and supported, OEMs
can ship new platforms without requiring a new quirk or a new _HID to
be added to a driver.

There would still be the problem of config access before the namespace
is available, i.e., the MCFG use case.  I don't know how important
that is.  Defining an MCFG extension seems like the most obvious
solution.

If we only expect a few non-standard devices, maybe it's enough to
have DMI quirks to statically set up ECAM and just live with the
inconvenience of requiring a kernel change for every new non-standard
device.

> > Host bridges in ACPI are handled through PNP0A08/PNP0A03 ids, and
> > most of the arch specific code is handled in the respective arch
> > directories (X86 and IA64, even though IA64 does not rely on ECAM/MCFG
> > for
> > PCI ops), it is not a driver per-se, PNP0A08/PNP0A03 are detected
> > through
> > ACPI scan handlers and the respective arch code (ie pci_acpi_scan_root)
> > sets-up resources AND config space on an arch specific basis.
> > 
> > X86 deals with that with code in arch/x86 that sets-up the pci_raw_ops
> > on a platform specific basis (and it is not nice, but it works because
> > as you all know the number of platforms in X86 world is contained).
> > 
> > Will this happen for ARM64 in arch/arm64 based on vendor specific
> > HIDs ?
> > 
> > No.
> > 
> > So given the current state of play (we were requested to move the
> > arch/arm64 specific ACPI PCI bits to arch/arm64), we would end up
> > with arch/arm64 code requiring code in /drivers to set-up pci_ops
> > in a platform specific way, it is horrible, if feasible at all.
> > 
> > The only way this can be implemented is by pretending that the
> > ACPI/PCI arch/arm64 implementation is generic code (that's what this
> > series does), move it to /drivers (where it is in this series), and
> > implement _DSD vendor specific bindings (per HID) to set-up the pci
> > operations; whether this solution should go upstream, given that it
> > is just a short-term solution for early platforms bugs, it is another
> > story and my personal answer is no.

It seems like there should be a way to look for a _DSM before we call
acpi_pci_root_get_mcfg_addr() to look for _CBA.

Currently we call acpi_pci_root_get_mcfg_addr() (to read _CBA) from
the generic acpi_pci_root_add(), but the result (root->mcfg_addr) is
only used in x86-specific code.  I think it would be nicer if the
lookup and the use were together.  Then it would be easier to override
it because the mapping assumptions would all be in one place.

> I think it shouldn't be too bad to move quirk handling mechanism to
> arch/arm64. Effectively we would not move platform specific code into
> arch/arm64 but just the mechanism checking if there is any quirk that
> is defined.
> 
> i.e.:
> 
> extern struct pci_cfg_fixup __start_acpi_mcfg_fixups[];
> extern struct pci_cfg_fixup __end_acpi_mcfg_fixups[];
> 
> static struct pci_ecam_ops *pci_acpi_get_ops(struct acpi_pci_root *root)
> {
>         int bus_num = root->secondary.start;
>         int domain = root->segment;
>         struct pci_cfg_fixup *f;
> 
>         /*
>          * Match against platform specific quirks and return corresponding
>          * CAM ops.
>          *
>          * First match against PCI topology <domain:bus> then use DMI or
>          * custom match handler.
>          */
>         for (f = __start_acpi_mcfg_fixups; f < __end_acpi_mcfg_fixups; f++) {
>                 if ((f->domain == domain || f->domain == PCI_MCFG_DOMAIN_ANY) &&
>                     (f->bus_num == bus_num || f->bus_num == PCI_MCFG_BUS_ANY) &&
>                     (f->system ? dmi_check_system(f->system) : 1) &&
>                     (f->match ? f->match(f, root) : 1))
>                         return f->ops;
>         }
>         /* No quirks, use ECAM */
>         return &pci_generic_ecam_ops;
> }
> 
> Such quirks will be defined anyway in drivers/pci/host/ in the vendor
> specific quirk implementations.
> 
> e.g. in HiSilicon case we would have
> 
> DECLARE_ACPI_MCFG_FIXUP(NULL, hisi_pcie_match, &hisi_pcie_ecam_ops,
> 			PCI_MCFG_DOMAIN_ANY, PCI_MCFG_BUS_ANY);
> 
> in "drivers/pci/host/pcie-hisi-acpi.c "
> 
> Thanks
> 
> Gab

Sorry Gab, I guess I was really responding to earlier messages :)

I don't really have much to say here, except that it doesn't seem
right to have an MCFG that describes a non-standard ECAM mapping.
I suppose there's already firmware in the field that does that,
though?

Bjorn


From ynorov at caviumnetworks.com  Mon May 23 17:04:29 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:29 +0300
Subject: [PATCH v6 00/21] ILP32 for ARM64
Message-ID: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>

This series enables aarch64 with ilp32 mode, and as supporting work,
introduces compat wrappers based on s390 solution, and also introduces
ARCH_32BIT_OFF_T configuration option that is enabled for existing
32-bit architectures but disabled for new arches (so 64-bit off_t is 
is used by new userspace).

This version is based on kernel v4.6.
It works with glibc-2.23, and tested with LTP.

It was tested on QEMU and ThunderX machines. No major differences found.

This is not RFC anymore, because ILP32 is now tested in big-endian mode;
signals, vDSO and other subsystems are tested, and look working

 v3: https://lkml.org/lkml/2014/9/3/704
 v4: https://lkml.org/lkml/2015/4/13/691
 v5: https://lkml.org/lkml/2015/9/29/911
 v6: ABI reworked significantly;
    - syscall input arguments are deloused with compat wrappers;
    - vDSO is now working for both BE and LE;
    - signal subsystem is reworked to handle signal context properly;
    - binfmt_elf is reworked, and now most of places where execution mode
      should be detected, are handled statically;
    - many other less-important fixes.

ILP32 glibc branch is available here:
https://github.com/norov/glibc/tree/ilp32-2.23

It is tested with this series with no major downsides. I will send it to 
glibc-alpha soon, after final revise. Please review and comment it as well.

Andrew Pinski (6):
  arm64: ensure the kernel is compiled for LP64
  arm64: rename COMPAT to AARCH32_EL0 in Kconfig
  arm64:uapi: set __BITS_PER_LONG correctly for ILP32 and LP64
  arm64: ilp32: add sys_ilp32.c and a separate table (in entry.S) to use
    it
  arm64: ilp32: introduce ilp32-specific handlers for sigframe and
    ucontext
  arm64:ilp32: add ARM64_ILP32 to Kconfig

Philipp Tomsich (1):
  arm64:ilp32: add vdso-ilp32 and use for signal return

Yury Norov (15):
  all: introduce COMPAT_WRAPPER option and enable it for s390
  all: s390: move wrapper infrastructure to generic headers
  all: s390: move compat_wrappers.c from arch/s390/kernel to kernel/
  all: wrap needed syscalls in generic unistd
  compat ABI: use non-compat openat and open_by_handle_at variants
  32-bit ABI: introduce ARCH_32BIT_OFF_T config option
  arm64: ilp32: add documentation on the ILP32 ABI for ARM64
  thread: move thread bits accessors to separated file
  arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)
  arm64: ilp32: add is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64
  arm64: introduce binfmt_elf32.c
  arm64: ilp32: introduce binfmt_ilp32.c
  arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32
  arm64: signal: share lp64 signal routines to ilp32
  arm64: signal32: move ilp32 and aarch32 common code to separated file

 Documentation/arm64/ilp32.txt                 |  25 +++
 arch/Kconfig                                  |   8 +
 arch/arc/Kconfig                              |   1 +
 arch/arm/Kconfig                              |   1 +
 arch/arm64/Kconfig                            |  20 +-
 arch/arm64/Makefile                           |   5 +
 arch/arm64/include/asm/compat.h               |  19 +-
 arch/arm64/include/asm/elf.h                  |  35 +---
 arch/arm64/include/asm/fpsimd.h               |   2 +-
 arch/arm64/include/asm/ftrace.h               |   2 +-
 arch/arm64/include/asm/hwcap.h                |   6 +-
 arch/arm64/include/asm/is_compat.h            |  84 ++++++++
 arch/arm64/include/asm/memory.h               |   3 +-
 arch/arm64/include/asm/processor.h            |  11 +-
 arch/arm64/include/asm/ptrace.h               |   2 +-
 arch/arm64/include/asm/signal32.h             |   6 +-
 arch/arm64/include/asm/signal32_common.h      |  25 +++
 arch/arm64/include/asm/signal_common.h        |  33 +++
 arch/arm64/include/asm/signal_ilp32.h         |  34 ++++
 arch/arm64/include/asm/syscall.h              |   2 +-
 arch/arm64/include/asm/thread_info.h          |   4 +-
 arch/arm64/include/asm/unistd.h               |  11 +-
 arch/arm64/include/asm/unistd32.h             |   2 +-
 arch/arm64/include/asm/vdso.h                 |   6 +
 arch/arm64/include/uapi/asm/bitsperlong.h     |   9 +-
 arch/arm64/kernel/Makefile                    |  14 +-
 arch/arm64/kernel/asm-offsets.c               |   9 +-
 arch/arm64/kernel/binfmt_elf32.c              |  33 +++
 arch/arm64/kernel/binfmt_ilp32.c              |  91 +++++++++
 arch/arm64/kernel/cpufeature.c                |   8 +-
 arch/arm64/kernel/cpuinfo.c                   |   4 +-
 arch/arm64/kernel/entry.S                     |  16 +-
 arch/arm64/kernel/entry_ilp32.S               |  23 +++
 arch/arm64/kernel/head.S                      |   2 +-
 arch/arm64/kernel/hw_breakpoint.c             |  10 +-
 arch/arm64/kernel/perf_regs.c                 |   2 +-
 arch/arm64/kernel/process.c                   |   7 +-
 arch/arm64/kernel/ptrace.c                    |  67 ++++++-
 arch/arm64/kernel/signal.c                    | 100 ++++++----
 arch/arm64/kernel/signal32.c                  |  85 --------
 arch/arm64/kernel/signal32_common.c           | 115 +++++++++++
 arch/arm64/kernel/signal_ilp32.c              | 192 ++++++++++++++++++
 arch/arm64/kernel/sys32.c                     |   1 +
 arch/arm64/kernel/sys_ilp32.c                 |  86 ++++++++
 arch/arm64/kernel/traps.c                     |   5 +-
 arch/arm64/kernel/vdso-ilp32/.gitignore       |   2 +
 arch/arm64/kernel/vdso-ilp32/Makefile         |  74 +++++++
 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S     |  33 +++
 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S |  95 +++++++++
 arch/arm64/kernel/vdso.c                      |  65 ++++--
 arch/arm64/kernel/vdso/gettimeofday.S         |  20 +-
 arch/blackfin/Kconfig                         |   1 +
 arch/cris/Kconfig                             |   1 +
 arch/frv/Kconfig                              |   1 +
 arch/h8300/Kconfig                            |   1 +
 arch/hexagon/Kconfig                          |   1 +
 arch/m32r/Kconfig                             |   1 +
 arch/m68k/Kconfig                             |   1 +
 arch/metag/Kconfig                            |   1 +
 arch/microblaze/Kconfig                       |   1 +
 arch/mips/Kconfig                             |   1 +
 arch/mn10300/Kconfig                          |   1 +
 arch/nios2/Kconfig                            |   1 +
 arch/openrisc/Kconfig                         |   1 +
 arch/parisc/Kconfig                           |   1 +
 arch/powerpc/Kconfig                          |   1 +
 arch/s390/Kconfig                             |   1 +
 arch/s390/include/asm/compat.h                |  17 +-
 arch/s390/kernel/Makefile                     |   2 +-
 arch/s390/kernel/compat_linux.c               |   4 +
 arch/s390/kernel/compat_wrapper.c             | 180 -----------------
 arch/score/Kconfig                            |   1 +
 arch/sh/Kconfig                               |   1 +
 arch/sparc/Kconfig                            |   1 +
 arch/tile/Kconfig                             |   1 +
 arch/tile/kernel/compat.c                     |   3 +
 arch/unicore32/Kconfig                        |   1 +
 arch/x86/Kconfig                              |   1 +
 arch/x86/um/Kconfig                           |   1 +
 arch/xtensa/Kconfig                           |   1 +
 drivers/clocksource/arm_arch_timer.c          |   2 +-
 include/linux/compat.h                        | 277 ++++++++++++++++++++++++++
 include/linux/fcntl.h                         |   2 +-
 include/linux/ptrace.h                        |   6 +
 include/linux/syscalls.h                      |  57 +-----
 include/linux/syscalls_structs.h              |  60 ++++++
 include/linux/thread_bits.h                   |  55 +++++
 include/linux/thread_info.h                   |  44 +---
 include/uapi/asm-generic/unistd.h             | 231 ++++++++++-----------
 kernel/Makefile                               |   1 +
 kernel/compat_wrapper.c                       | 175 ++++++++++++++++
 kernel/ptrace.c                               |  10 +-
 92 files changed, 2024 insertions(+), 641 deletions(-)
 create mode 100644 Documentation/arm64/ilp32.txt
 create mode 100644 arch/arm64/include/asm/is_compat.h
 create mode 100644 arch/arm64/include/asm/signal32_common.h
 create mode 100644 arch/arm64/include/asm/signal_common.h
 create mode 100644 arch/arm64/include/asm/signal_ilp32.h
 create mode 100644 arch/arm64/kernel/binfmt_elf32.c
 create mode 100644 arch/arm64/kernel/binfmt_ilp32.c
 create mode 100644 arch/arm64/kernel/entry_ilp32.S
 create mode 100644 arch/arm64/kernel/signal32_common.c
 create mode 100644 arch/arm64/kernel/signal_ilp32.c
 create mode 100644 arch/arm64/kernel/sys_ilp32.c
 create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore
 create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile
 create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
 create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
 delete mode 100644 arch/s390/kernel/compat_wrapper.c
 create mode 100644 include/linux/syscalls_structs.h
 create mode 100644 include/linux/thread_bits.h
 create mode 100644 kernel/compat_wrapper.c

-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:31 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:31 +0300
Subject: [PATCH 02/23] all: introduce COMPAT_WRAPPER option and enable it for
 s390
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-3-git-send-email-ynorov@caviumnetworks.com>

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/Kconfig      | 4 ++++
 arch/s390/Kconfig | 1 +
 2 files changed, 5 insertions(+)

diff --git a/arch/Kconfig b/arch/Kconfig
index 81869a5..92fcbd4 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -589,6 +589,10 @@ config HAVE_STACK_VALIDATION
 	  Architecture supports the 'objtool check' host tool command, which
 	  performs compile-time stack metadata validation.
 
+config COMPAT_WRAPPER
+	bool
+	depends on COMPAT
+
 #
 # ABI hall of shame
 #
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index bf24ab1..6d643b3 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -340,6 +340,7 @@ config COMPAT
 	select COMPAT_BINFMT_ELF if BINFMT_ELF
 	select ARCH_WANT_OLD_COMPAT_IPC
 	select COMPAT_OLD_SIGACTION
+	select COMPAT_WRAPPER
 	depends on MULTIUSER
 	help
 	  Select this option if you want to enable your system kernel to
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:30 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:30 +0300
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-2-git-send-email-ynorov@caviumnetworks.com>

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 Documentation/adding-syscalls.txt | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/Documentation/adding-syscalls.txt b/Documentation/adding-syscalls.txt
index cc2d4ac..d02a6bd 100644
--- a/Documentation/adding-syscalls.txt
+++ b/Documentation/adding-syscalls.txt
@@ -341,6 +341,38 @@ To summarize, you need:
  - instance of __SC_COMP not __SYSCALL in include/uapi/asm-generic/unistd.h
 
 
+Compatibility System Calls Wrappers
+--------------------------------
+
+Some architectures prevent 32-bit userspace from access to top halves of 64-bit
+registers, but some not. It's not a problem if specific argument is the same
+size in kernel and userspace. It also is not a problem if system call is already
+handled by compatible routine. Otherwise we'd take care of it. Usually, glibc
+and compiler handles register's top halve, but from kernel side, we cannot rely
+on it, as malicious code may cause incorrect behaviour and/or security
+vulnerabilities.
+
+For now, only s390 and arm64/ilp32 are affected.
+
+To clear that top halves, automatic wrappers are introduced. They clear all
+required registers before passing control to regular syscall handler.
+
+If your architecture allows userspace code to access top halves of register,
+you need to:
+ - enable COMPAT_WRAPPER in configuration file;
+ - declare: "#define __SC_WRAP(nr, sym) [nr] = compat_##sym,", just before
+   compatible syscall table declaration, if you use generic unistd; or
+ - declare compat wrappers manually, if you use non-generic syscall table.
+   The list of unsafe syscalls is in kernel/compat_wrapper.
+
+If you write new syscall, make sure, its arguments are the same size in both
+64- and 32-bits modes. If no, and if there's no explicit compat version for
+syscall handler, you need to:
+ - declare compat version prototype in 'include/linux/compat.h';
+ - in 'include/uapi/asm-generic/unistd.h' declare syscall with macro '__SC_WRAP'
+   instead of '__SYSCALL';
+ - add corresponding line to 'kernel/compat_wrapper.c' to let it generate wrapper.
+
 Compatibility System Calls (x86)
 --------------------------------
 
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:32 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:32 +0300
Subject: [PATCH 03/23] all: s390: move wrapper infrastructure to generic
 headers
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-4-git-send-email-ynorov@caviumnetworks.com>

This patch moves required calls to generic files to let other arches use
it if needed. Here also, additional code is introduced, as s390 uses asm
syscall tables, while in general case, wrappers may be used in C code.

__SC_COMPAT_CAST for s390 is too specific due to 31-bit pointer length, so it's
moved to arch/s390/include/asm/compat.h. Generic declaration assumes that long,
unsigned long and pointer types are all 32-bit length.

linux/syscalls_structs.h header is introduced, because from now (see next patch)
structure types listed there are needed for both normal and compat mode.

cond_syscall_wrapped now defined two symbols: sys_foo() and compat_sys_foo(), if
compat wrappers are enabled.

Here __SC_WRAP() macro is introduced as well. s390 doesn't need it as it uses
asm-generated syscall table. But architectures that generate that tables with
C code (ARM64/ILP32) should redefine it as '#define __SC_WRAP(name) compat_##name'.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/s390/include/asm/compat.h    | 17 +++++++++--
 arch/s390/kernel/compat_wrapper.c | 51 ---------------------------------
 include/linux/compat.h            | 52 +++++++++++++++++++++++++++++++++
 include/linux/syscalls.h          | 57 +------------------------------------
 include/linux/syscalls_structs.h  | 60 +++++++++++++++++++++++++++++++++++++++
 include/uapi/asm-generic/unistd.h |  4 +++
 6 files changed, 132 insertions(+), 109 deletions(-)
 create mode 100644 include/linux/syscalls_structs.h

diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index 352f7bd..f412723 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -7,13 +7,26 @@
 #include <linux/sched.h>
 #include <linux/thread_info.h>
 
-#define __TYPE_IS_PTR(t) (!__builtin_types_compatible_p(typeof(0?(t)0:0ULL), u64))
-
 #define __SC_DELOUSE(t,v) ({ \
 	BUILD_BUG_ON(sizeof(t) > 4 && !__TYPE_IS_PTR(t)); \
 	(t)(__TYPE_IS_PTR(t) ? ((v) & 0x7fffffff) : (v)); \
 })
 
+#define __SC_COMPAT_CAST(t, a)						\
+({									\
+	long __ReS = a;							\
+									\
+	BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) &&		\
+		     !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t));		\
+	if (__TYPE_IS_L(t))						\
+		__ReS = (s32)a;						\
+	if (__TYPE_IS_UL(t))						\
+		__ReS = (u32)a;						\
+	if (__TYPE_IS_PTR(t))						\
+		__ReS = a & 0x7fffffff;					\
+	(t)__ReS;							\
+})
+
 #define PSW32_MASK_PER		0x40000000UL
 #define PSW32_MASK_DAT		0x04000000UL
 #define PSW32_MASK_IO		0x02000000UL
diff --git a/arch/s390/kernel/compat_wrapper.c b/arch/s390/kernel/compat_wrapper.c
index ae2cda5..1614e15 100644
--- a/arch/s390/kernel/compat_wrapper.c
+++ b/arch/s390/kernel/compat_wrapper.c
@@ -8,57 +8,6 @@
 #include <linux/compat.h>
 #include "entry.h"
 
-#define COMPAT_SYSCALL_WRAP1(name, ...) \
-	COMPAT_SYSCALL_WRAPx(1, _##name, __VA_ARGS__)
-#define COMPAT_SYSCALL_WRAP2(name, ...) \
-	COMPAT_SYSCALL_WRAPx(2, _##name, __VA_ARGS__)
-#define COMPAT_SYSCALL_WRAP3(name, ...) \
-	COMPAT_SYSCALL_WRAPx(3, _##name, __VA_ARGS__)
-#define COMPAT_SYSCALL_WRAP4(name, ...) \
-	COMPAT_SYSCALL_WRAPx(4, _##name, __VA_ARGS__)
-#define COMPAT_SYSCALL_WRAP5(name, ...) \
-	COMPAT_SYSCALL_WRAPx(5, _##name, __VA_ARGS__)
-#define COMPAT_SYSCALL_WRAP6(name, ...) \
-	COMPAT_SYSCALL_WRAPx(6, _##name, __VA_ARGS__)
-
-#define __SC_COMPAT_TYPE(t, a) \
-	__typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
-
-#define __SC_COMPAT_CAST(t, a)						\
-({									\
-	long __ReS = a;							\
-									\
-	BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) &&		\
-		     !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t));		\
-	if (__TYPE_IS_L(t))						\
-		__ReS = (s32)a;						\
-	if (__TYPE_IS_UL(t))						\
-		__ReS = (u32)a;						\
-	if (__TYPE_IS_PTR(t))						\
-		__ReS = a & 0x7fffffff;					\
-	(t)__ReS;							\
-})
-
-/*
- * The COMPAT_SYSCALL_WRAP macro generates system call wrappers to be used by
- * compat tasks. These wrappers will only be used for system calls where only
- * the system call arguments need sign or zero extension or zeroing of the upper
- * 33 bits of pointers.
- * Note: since the wrapper function will afterwards call a system call which
- * again performs zero and sign extension for all system call arguments with
- * a size of less than eight bytes, these compat wrappers only touch those
- * system call arguments with a size of eight bytes ((unsigned) long and
- * pointers). Zero and sign extension for e.g. int parameters will be done by
- * the regular system call wrappers.
- */
-#define COMPAT_SYSCALL_WRAPx(x, name, ...)					\
-asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));			\
-asmlinkage long notrace compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__));\
-asmlinkage long notrace compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__))	\
-{										\
-	return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__));		\
-}
-
 COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
 COMPAT_SYSCALL_WRAP2(link, const char __user *, oldname, const char __user *, newname);
 COMPAT_SYSCALL_WRAP1(unlink, const char __user *, pathname);
diff --git a/include/linux/compat.h b/include/linux/compat.h
index f964ef7..4eba16e 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -30,6 +30,10 @@
 #define __SC_DELOUSE(t,v) ((t)(unsigned long)(v))
 #endif
 
+#ifndef __TYPE_IS_PTR
+#define __TYPE_IS_PTR(t) (!__builtin_types_compatible_p(typeof(0?(t)0:0ULL), u64))
+#endif
+
 #define COMPAT_SYSCALL_DEFINE0(name) \
 	asmlinkage long compat_sys_##name(void)
 
@@ -739,4 +743,52 @@ static inline bool in_compat_syscall(void) { return false; }
 
 #endif /* CONFIG_COMPAT */
 
+#ifdef CONFIG_COMPAT_WRAPPER
+
+#define COMPAT_SYSCALL_WRAP1(name, ...) COMPAT_SYSCALL_WRAPx(1, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP2(name, ...) COMPAT_SYSCALL_WRAPx(2, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP3(name, ...) COMPAT_SYSCALL_WRAPx(3, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP4(name, ...) COMPAT_SYSCALL_WRAPx(4, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP5(name, ...) COMPAT_SYSCALL_WRAPx(5, _##name, __VA_ARGS__)
+#define COMPAT_SYSCALL_WRAP6(name, ...) COMPAT_SYSCALL_WRAPx(6, _##name, __VA_ARGS__)
+
+#ifndef __SC_COMPAT_TYPE
+#define __SC_COMPAT_TYPE(t, a) \
+	__typeof(__builtin_choose_expr(sizeof(t) > 4, 0L, (t)0)) a
+#endif
+
+#ifndef __SC_COMPAT_CAST
+#define __SC_COMPAT_CAST(t, a) ({					\
+	BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) &&		\
+		     !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t));		\
+	((t) ((t)(-1) < 0 ? (s64)(s32)(a) : (u64)(u32)(a)));		\
+})
+#endif
+
+#ifndef COMPAT_SYSCALL_WRAPx
+/*
+ * The COMPAT_SYSCALL_WRAP macro generates system call wrappers to be used by
+ * compat tasks. These wrappers will only be used for system calls where only
+ * the system call arguments need sign or zero extension or zeroing of the upper
+ * parts of arguments passed in register.
+ * Note: since the wrapper function will afterwards call a system call which
+ * again performs zero and sign extension for all system call arguments with
+ * a size of less than eight bytes, these compat wrappers only touch those
+ * system call arguments with a size of eight bytes ((unsigned) long and
+ * pointers). Zero and sign extension for e.g. int parameters will be done by
+ * the regular system call wrappers.
+ */
+#define COMPAT_SYSCALL_WRAPx(x, name, ...)						\
+asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));				\
+asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))			\
+		__attribute__((alias(__stringify(compat_SyS##name))));			\
+asmlinkage long notrace compat_SyS##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__));	\
+asmlinkage long notrace compat_SyS##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__))		\
+{											\
+	return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__));			\
+}
+#endif
+
+#endif /* CONFIG_COMPAT_WRAPPER */
+
 #endif /* _LINUX_COMPAT_H */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index d795472..9d345eb 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -11,62 +11,7 @@
 #ifndef _LINUX_SYSCALLS_H
 #define _LINUX_SYSCALLS_H
 
-struct epoll_event;
-struct iattr;
-struct inode;
-struct iocb;
-struct io_event;
-struct iovec;
-struct itimerspec;
-struct itimerval;
-struct kexec_segment;
-struct linux_dirent;
-struct linux_dirent64;
-struct list_head;
-struct mmap_arg_struct;
-struct msgbuf;
-struct user_msghdr;
-struct mmsghdr;
-struct msqid_ds;
-struct new_utsname;
-struct nfsctl_arg;
-struct __old_kernel_stat;
-struct oldold_utsname;
-struct old_utsname;
-struct pollfd;
-struct rlimit;
-struct rlimit64;
-struct rusage;
-struct sched_param;
-struct sched_attr;
-struct sel_arg_struct;
-struct semaphore;
-struct sembuf;
-struct shmid_ds;
-struct sockaddr;
-struct stat;
-struct stat64;
-struct statfs;
-struct statfs64;
-struct __sysctl_args;
-struct sysinfo;
-struct timespec;
-struct timeval;
-struct timex;
-struct timezone;
-struct tms;
-struct utimbuf;
-struct mq_attr;
-struct compat_stat;
-struct compat_timeval;
-struct robust_list_head;
-struct getcpu_cache;
-struct old_linux_dirent;
-struct perf_event_attr;
-struct file_handle;
-struct sigaltstack;
-union bpf_attr;
-
+#include <linux/syscalls_structs.h>
 #include <linux/types.h>
 #include <linux/aio_abi.h>
 #include <linux/capability.h>
diff --git a/include/linux/syscalls_structs.h b/include/linux/syscalls_structs.h
new file mode 100644
index 0000000..a920cbc
--- /dev/null
+++ b/include/linux/syscalls_structs.h
@@ -0,0 +1,60 @@
+#ifndef _LINUX_SYSCALL_STRUCTS_H
+#define _LINUX_SYSCALL_STRUCTS_H
+
+struct epoll_event;
+struct iattr;
+struct inode;
+struct iocb;
+struct io_event;
+struct iovec;
+struct itimerspec;
+struct itimerval;
+struct kexec_segment;
+struct linux_dirent;
+struct linux_dirent64;
+struct list_head;
+struct mmap_arg_struct;
+struct msgbuf;
+struct user_msghdr;
+struct mmsghdr;
+struct msqid_ds;
+struct new_utsname;
+struct nfsctl_arg;
+struct __old_kernel_stat;
+struct oldold_utsname;
+struct old_utsname;
+struct pollfd;
+struct rlimit;
+struct rlimit64;
+struct rusage;
+struct sched_param;
+struct sched_attr;
+struct sel_arg_struct;
+struct semaphore;
+struct sembuf;
+struct shmid_ds;
+struct sockaddr;
+struct stat;
+struct stat64;
+struct statfs;
+struct statfs64;
+struct __sysctl_args;
+struct sysinfo;
+struct timespec;
+struct timeval;
+struct timex;
+struct timezone;
+struct tms;
+struct utimbuf;
+struct mq_attr;
+struct compat_stat;
+struct compat_timeval;
+struct robust_list_head;
+struct getcpu_cache;
+struct old_linux_dirent;
+struct perf_event_attr;
+struct file_handle;
+struct sigaltstack;
+union bpf_attr;
+
+#endif /* _LINUX_SYSCALL_STRUCTS_H */
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index c51afb7..7e91d83 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -29,6 +29,10 @@
 #define __SC_COMP_3264(_nr, _32, _64, _comp) __SC_3264(_nr, _32, _64)
 #endif
 
+#ifndef __SC_WRAP
+#define __SC_WRAP __SYSCALL
+#endif
+
 #define __NR_io_setup 0
 __SC_COMP(__NR_io_setup, sys_io_setup, compat_sys_io_setup)
 #define __NR_io_destroy 1
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:33 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:33 +0300
Subject: [PATCH 04/23] all: s390: move compat_wrappers.c from arch/s390/kernel
 to kernel/
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-5-git-send-email-ynorov@caviumnetworks.com>

Some syscalls are declared conditionally, so corresponding wrappers
are conditional accordingly.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/s390/kernel/Makefile         |   2 +-
 arch/s390/kernel/compat_linux.c   |   4 +
 arch/s390/kernel/compat_wrapper.c | 129 ----------------------------
 kernel/Makefile                   |   1 +
 kernel/compat_wrapper.c           | 175 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 181 insertions(+), 130 deletions(-)
 delete mode 100644 arch/s390/kernel/compat_wrapper.c
 create mode 100644 kernel/compat_wrapper.c

diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 2f5586a..145d3d8 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -57,7 +57,7 @@ obj-$(CONFIG_HIBERNATION)	+= suspend.o swsusp.o
 obj-$(CONFIG_AUDIT)		+= audit.o
 compat-obj-$(CONFIG_AUDIT)	+= compat_audit.o
 obj-$(CONFIG_COMPAT)		+= compat_linux.o compat_signal.o
-obj-$(CONFIG_COMPAT)		+= compat_wrapper.o $(compat-obj-y)
+obj-$(CONFIG_COMPAT)		+= $(compat-obj-y)
 
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 437e611..783c208 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -86,6 +86,10 @@
 #define SET_STAT_UID(stat, uid)		(stat).st_uid = high2lowuid(uid)
 #define SET_STAT_GID(stat, gid)		(stat).st_gid = high2lowgid(gid)
 
+COMPAT_SYSCALL_WRAP3(s390_pci_mmio_write, const unsigned long, mmio_addr, const void __user *, user_buffer, const size_t, length);
+
+COMPAT_SYSCALL_WRAP3(s390_pci_mmio_read, const unsigned long, mmio_addr, void __user *, user_buffer, const size_t, length);
+
 COMPAT_SYSCALL_DEFINE3(s390_chown16, const char __user *, filename,
 		       u16, user, u16, group)
 {
diff --git a/arch/s390/kernel/compat_wrapper.c b/arch/s390/kernel/compat_wrapper.c
deleted file mode 100644
index 1614e15..0000000
--- a/arch/s390/kernel/compat_wrapper.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- *  Compat system call wrappers.
- *
- *    Copyright IBM Corp. 2014
- */
-
-#include <linux/syscalls.h>
-#include <linux/compat.h>
-#include "entry.h"
-
-COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
-COMPAT_SYSCALL_WRAP2(link, const char __user *, oldname, const char __user *, newname);
-COMPAT_SYSCALL_WRAP1(unlink, const char __user *, pathname);
-COMPAT_SYSCALL_WRAP1(chdir, const char __user *, filename);
-COMPAT_SYSCALL_WRAP3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev);
-COMPAT_SYSCALL_WRAP2(chmod, const char __user *, filename, umode_t, mode);
-COMPAT_SYSCALL_WRAP1(oldumount, char __user *, name);
-COMPAT_SYSCALL_WRAP2(access, const char __user *, filename, int, mode);
-COMPAT_SYSCALL_WRAP2(rename, const char __user *, oldname, const char __user *, newname);
-COMPAT_SYSCALL_WRAP2(mkdir, const char __user *, pathname, umode_t, mode);
-COMPAT_SYSCALL_WRAP1(rmdir, const char __user *, pathname);
-COMPAT_SYSCALL_WRAP1(pipe, int __user *, fildes);
-COMPAT_SYSCALL_WRAP1(brk, unsigned long, brk);
-COMPAT_SYSCALL_WRAP2(signal, int, sig, __sighandler_t, handler);
-COMPAT_SYSCALL_WRAP1(acct, const char __user *, name);
-COMPAT_SYSCALL_WRAP2(umount, char __user *, name, int, flags);
-COMPAT_SYSCALL_WRAP1(chroot, const char __user *, filename);
-COMPAT_SYSCALL_WRAP3(sigsuspend, int, unused1, int, unused2, old_sigset_t, mask);
-COMPAT_SYSCALL_WRAP2(sethostname, char __user *, name, int, len);
-COMPAT_SYSCALL_WRAP2(symlink, const char __user *, old, const char __user *, new);
-COMPAT_SYSCALL_WRAP3(readlink, const char __user *, path, char __user *, buf, int, bufsiz);
-COMPAT_SYSCALL_WRAP1(uselib, const char __user *, library);
-COMPAT_SYSCALL_WRAP2(swapon, const char __user *, specialfile, int, swap_flags);
-COMPAT_SYSCALL_WRAP4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg);
-COMPAT_SYSCALL_WRAP2(munmap, unsigned long, addr, size_t, len);
-COMPAT_SYSCALL_WRAP3(syslog, int, type, char __user *, buf, int, len);
-COMPAT_SYSCALL_WRAP1(swapoff, const char __user *, specialfile);
-COMPAT_SYSCALL_WRAP2(setdomainname, char __user *, name, int, len);
-COMPAT_SYSCALL_WRAP1(newuname, struct new_utsname __user *, name);
-COMPAT_SYSCALL_WRAP3(mprotect, unsigned long, start, size_t, len, unsigned long, prot);
-COMPAT_SYSCALL_WRAP3(init_module, void __user *, umod, unsigned long, len, const char __user *, uargs);
-COMPAT_SYSCALL_WRAP2(delete_module, const char __user *, name_user, unsigned int, flags);
-COMPAT_SYSCALL_WRAP4(quotactl, unsigned int, cmd, const char __user *, special, qid_t, id, void __user *, addr);
-COMPAT_SYSCALL_WRAP2(bdflush, int, func, long, data);
-COMPAT_SYSCALL_WRAP3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2);
-COMPAT_SYSCALL_WRAP5(llseek, unsigned int, fd, unsigned long, high, unsigned long, low, loff_t __user *, result, unsigned int, whence);
-COMPAT_SYSCALL_WRAP3(msync, unsigned long, start, size_t, len, int, flags);
-COMPAT_SYSCALL_WRAP2(mlock, unsigned long, start, size_t, len);
-COMPAT_SYSCALL_WRAP2(munlock, unsigned long, start, size_t, len);
-COMPAT_SYSCALL_WRAP2(sched_setparam, pid_t, pid, struct sched_param __user *, param);
-COMPAT_SYSCALL_WRAP2(sched_getparam, pid_t, pid, struct sched_param __user *, param);
-COMPAT_SYSCALL_WRAP3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param);
-COMPAT_SYSCALL_WRAP5(mremap, unsigned long, addr, unsigned long, old_len, unsigned long, new_len, unsigned long, flags, unsigned long, new_addr);
-COMPAT_SYSCALL_WRAP3(poll, struct pollfd __user *, ufds, unsigned int, nfds, int, timeout);
-COMPAT_SYSCALL_WRAP5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5);
-COMPAT_SYSCALL_WRAP2(getcwd, char __user *, buf, unsigned long, size);
-COMPAT_SYSCALL_WRAP2(capget, cap_user_header_t, header, cap_user_data_t, dataptr);
-COMPAT_SYSCALL_WRAP2(capset, cap_user_header_t, header, const cap_user_data_t, data);
-COMPAT_SYSCALL_WRAP3(lchown, const char __user *, filename, uid_t, user, gid_t, group);
-COMPAT_SYSCALL_WRAP2(getgroups, int, gidsetsize, gid_t __user *, grouplist);
-COMPAT_SYSCALL_WRAP2(setgroups, int, gidsetsize, gid_t __user *, grouplist);
-COMPAT_SYSCALL_WRAP3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid);
-COMPAT_SYSCALL_WRAP3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid);
-COMPAT_SYSCALL_WRAP3(chown, const char __user *, filename, uid_t, user, gid_t, group);
-COMPAT_SYSCALL_WRAP2(pivot_root, const char __user *, new_root, const char __user *, put_old);
-COMPAT_SYSCALL_WRAP3(mincore, unsigned long, start, size_t, len, unsigned char __user *, vec);
-COMPAT_SYSCALL_WRAP3(madvise, unsigned long, start, size_t, len, int, behavior);
-COMPAT_SYSCALL_WRAP5(setxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags);
-COMPAT_SYSCALL_WRAP5(lsetxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags);
-COMPAT_SYSCALL_WRAP5(fsetxattr, int, fd, const char __user *, name, const void __user *, value, size_t, size, int, flags);
-COMPAT_SYSCALL_WRAP3(getdents64, unsigned int, fd, struct linux_dirent64 __user *, dirent, unsigned int, count);
-COMPAT_SYSCALL_WRAP4(getxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size);
-COMPAT_SYSCALL_WRAP4(lgetxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size);
-COMPAT_SYSCALL_WRAP4(fgetxattr, int, fd, const char __user *, name, void __user *, value, size_t, size);
-COMPAT_SYSCALL_WRAP3(listxattr, const char __user *, path, char __user *, list, size_t, size);
-COMPAT_SYSCALL_WRAP3(llistxattr, const char __user *, path, char __user *, list, size_t, size);
-COMPAT_SYSCALL_WRAP3(flistxattr, int, fd, char __user *, list, size_t, size);
-COMPAT_SYSCALL_WRAP2(removexattr, const char __user *, path, const char __user *, name);
-COMPAT_SYSCALL_WRAP2(lremovexattr, const char __user *, path, const char __user *, name);
-COMPAT_SYSCALL_WRAP2(fremovexattr, int, fd, const char __user *, name);
-COMPAT_SYSCALL_WRAP1(set_tid_address, int __user *, tidptr);
-COMPAT_SYSCALL_WRAP4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event);
-COMPAT_SYSCALL_WRAP4(epoll_wait, int, epfd, struct epoll_event __user *, events, int, maxevents, int, timeout);
-COMPAT_SYSCALL_WRAP1(io_destroy, aio_context_t, ctx);
-COMPAT_SYSCALL_WRAP3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, struct io_event __user *, result);
-COMPAT_SYSCALL_WRAP1(mq_unlink, const char __user *, name);
-COMPAT_SYSCALL_WRAP5(add_key, const char __user *, tp, const char __user *, dsc, const void __user *, pld, size_t, len, key_serial_t, id);
-COMPAT_SYSCALL_WRAP4(request_key, const char __user *, tp, const char __user *, dsc, const char __user *, info, key_serial_t, id);
-COMPAT_SYSCALL_WRAP5(remap_file_pages, unsigned long, start, unsigned long, size, unsigned long, prot, unsigned long, pgoff, unsigned long, flags);
-COMPAT_SYSCALL_WRAP3(inotify_add_watch, int, fd, const char __user *, path, u32, mask);
-COMPAT_SYSCALL_WRAP3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode);
-COMPAT_SYSCALL_WRAP4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, unsigned, dev);
-COMPAT_SYSCALL_WRAP5(fchownat, int, dfd, const char __user *, filename, uid_t, user, gid_t, group, int, flag);
-COMPAT_SYSCALL_WRAP3(unlinkat, int, dfd, const char __user *, pathname, int, flag);
-COMPAT_SYSCALL_WRAP4(renameat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname);
-COMPAT_SYSCALL_WRAP5(linkat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, int, flags);
-COMPAT_SYSCALL_WRAP3(symlinkat, const char __user *, oldname, int, newdfd, const char __user *, newname);
-COMPAT_SYSCALL_WRAP4(readlinkat, int, dfd, const char __user *, path, char __user *, buf, int, bufsiz);
-COMPAT_SYSCALL_WRAP3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode);
-COMPAT_SYSCALL_WRAP3(faccessat, int, dfd, const char __user *, filename, int, mode);
-COMPAT_SYSCALL_WRAP1(unshare, unsigned long, unshare_flags);
-COMPAT_SYSCALL_WRAP6(splice, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags);
-COMPAT_SYSCALL_WRAP4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags);
-COMPAT_SYSCALL_WRAP3(getcpu, unsigned __user *, cpu, unsigned __user *, node, struct getcpu_cache __user *, cache);
-COMPAT_SYSCALL_WRAP2(pipe2, int __user *, fildes, int, flags);
-COMPAT_SYSCALL_WRAP5(perf_event_open, struct perf_event_attr __user *, attr_uptr, pid_t, pid, int, cpu, int, group_fd, unsigned long, flags);
-COMPAT_SYSCALL_WRAP5(clone, unsigned long, newsp, unsigned long, clone_flags, int __user *, parent_tidptr, int __user *, child_tidptr, unsigned long, tls);
-COMPAT_SYSCALL_WRAP4(prlimit64, pid_t, pid, unsigned int, resource, const struct rlimit64 __user *, new_rlim, struct rlimit64 __user *, old_rlim);
-COMPAT_SYSCALL_WRAP5(name_to_handle_at, int, dfd, const char __user *, name, struct file_handle __user *, handle, int __user *, mnt_id, int, flag);
-COMPAT_SYSCALL_WRAP5(kcmp, pid_t, pid1, pid_t, pid2, int, type, unsigned long, idx1, unsigned long, idx2);
-COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, flags);
-COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
-COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags);
-COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags);
-COMPAT_SYSCALL_WRAP3(seccomp, unsigned int, op, unsigned int, flags, const char __user *, uargs)
-COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags)
-COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags)
-COMPAT_SYSCALL_WRAP3(bpf, int, cmd, union bpf_attr *, attr, unsigned int, size);
-COMPAT_SYSCALL_WRAP3(s390_pci_mmio_write, const unsigned long, mmio_addr, const void __user *, user_buffer, const size_t, length);
-COMPAT_SYSCALL_WRAP3(s390_pci_mmio_read, const unsigned long, mmio_addr, void __user *, user_buffer, const size_t, length);
-COMPAT_SYSCALL_WRAP4(socketpair, int, family, int, type, int, protocol, int __user *, usockvec);
-COMPAT_SYSCALL_WRAP3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen);
-COMPAT_SYSCALL_WRAP3(connect, int, fd, struct sockaddr __user *, uservaddr, int, addrlen);
-COMPAT_SYSCALL_WRAP4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, int __user *, upeer_addrlen, int, flags);
-COMPAT_SYSCALL_WRAP3(getsockname, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
-COMPAT_SYSCALL_WRAP3(getpeername, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
-COMPAT_SYSCALL_WRAP6(sendto, int, fd, void __user *, buff, size_t, len, unsigned int, flags, struct sockaddr __user *, addr, int, addr_len);
-COMPAT_SYSCALL_WRAP3(mlock2, unsigned long, start, size_t, len, int, flags);
-COMPAT_SYSCALL_WRAP6(copy_file_range, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags);
diff --git a/kernel/Makefile b/kernel/Makefile
index f0c40bf..882eec03 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
 obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o
 obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_COMPAT_WRAPPER) += compat_wrapper.o
 obj-$(CONFIG_CGROUPS) += cgroup.o
 obj-$(CONFIG_CGROUP_FREEZER) += cgroup_freezer.o
 obj-$(CONFIG_CGROUP_PIDS) += cgroup_pids.o
diff --git a/kernel/compat_wrapper.c b/kernel/compat_wrapper.c
new file mode 100644
index 0000000..b6c050e
--- /dev/null
+++ b/kernel/compat_wrapper.c
@@ -0,0 +1,175 @@
+/*
+ *  Compat system call wrappers.
+ *
+ *    Copyright IBM Corp. 2014
+ */
+
+#include <linux/syscalls.h>
+#include <linux/compat.h>
+
+COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
+COMPAT_SYSCALL_WRAP2(link, const char __user *, oldname, const char __user *, newname);
+COMPAT_SYSCALL_WRAP1(unlink, const char __user *, pathname);
+COMPAT_SYSCALL_WRAP1(chdir, const char __user *, filename);
+COMPAT_SYSCALL_WRAP3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev);
+COMPAT_SYSCALL_WRAP2(chmod, const char __user *, filename, umode_t, mode);
+
+#ifdef __ARCH_WANT_SYS_OLDUMOUNT
+COMPAT_SYSCALL_WRAP1(oldumount, char __user *, name);
+#endif
+
+COMPAT_SYSCALL_WRAP2(access, const char __user *, filename, int, mode);
+COMPAT_SYSCALL_WRAP2(rename, const char __user *, oldname, const char __user *, newname);
+COMPAT_SYSCALL_WRAP2(mkdir, const char __user *, pathname, umode_t, mode);
+COMPAT_SYSCALL_WRAP1(rmdir, const char __user *, pathname);
+COMPAT_SYSCALL_WRAP1(pipe, int __user *, fildes);
+COMPAT_SYSCALL_WRAP1(brk, unsigned long, brk);
+
+#ifdef __ARCH_WANT_SYS_SIGNAL
+COMPAT_SYSCALL_WRAP2(signal, int, sig, __sighandler_t, handler);
+#endif
+
+COMPAT_SYSCALL_WRAP1(acct, const char __user *, name);
+COMPAT_SYSCALL_WRAP2(umount, char __user *, name, int, flags);
+COMPAT_SYSCALL_WRAP1(chroot, const char __user *, filename);
+
+#ifdef CONFIG_OLD_SIGSUSPEND
+SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask);
+#endif
+
+#ifdef CONFIG_OLD_SIGSUSPEND3
+COMPAT_SYSCALL_WRAP3(sigsuspend, int, unused1, int, unused2, old_sigset_t, mask);
+#endif
+
+COMPAT_SYSCALL_WRAP2(sethostname, char __user *, name, int, len);
+COMPAT_SYSCALL_WRAP2(symlink, const char __user *, old, const char __user *, new);
+COMPAT_SYSCALL_WRAP3(readlink, const char __user *, path, char __user *, buf, int, bufsiz);
+COMPAT_SYSCALL_WRAP1(uselib, const char __user *, library);
+COMPAT_SYSCALL_WRAP2(swapon, const char __user *, specialfile, int, swap_flags);
+COMPAT_SYSCALL_WRAP4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg);
+COMPAT_SYSCALL_WRAP2(munmap, unsigned long, addr, size_t, len);
+COMPAT_SYSCALL_WRAP3(syslog, int, type, char __user *, buf, int, len);
+COMPAT_SYSCALL_WRAP1(swapoff, const char __user *, specialfile);
+COMPAT_SYSCALL_WRAP2(setdomainname, char __user *, name, int, len);
+COMPAT_SYSCALL_WRAP1(newuname, struct new_utsname __user *, name);
+COMPAT_SYSCALL_WRAP3(mprotect, unsigned long, start, size_t, len, unsigned long, prot);
+COMPAT_SYSCALL_WRAP3(init_module, void __user *, umod, unsigned long, len, const char __user *, uargs);
+COMPAT_SYSCALL_WRAP2(delete_module, const char __user *, name_user, unsigned int, flags);
+COMPAT_SYSCALL_WRAP4(quotactl, unsigned int, cmd, const char __user *, special, qid_t, id, void __user *, addr);
+COMPAT_SYSCALL_WRAP2(bdflush, int, func, long, data);
+COMPAT_SYSCALL_WRAP3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2);
+
+#ifdef __ARCH_WANT_SYS_LLSEEK
+COMPAT_SYSCALL_WRAP5(llseek, unsigned int, fd, unsigned long, high, unsigned long, low, loff_t __user *, result, unsigned int, whence);
+#endif
+
+COMPAT_SYSCALL_WRAP3(msync, unsigned long, start, size_t, len, int, flags);
+COMPAT_SYSCALL_WRAP2(mlock, unsigned long, start, size_t, len);
+COMPAT_SYSCALL_WRAP2(munlock, unsigned long, start, size_t, len);
+COMPAT_SYSCALL_WRAP2(sched_setparam, pid_t, pid, struct sched_param __user *, param);
+COMPAT_SYSCALL_WRAP2(sched_getparam, pid_t, pid, struct sched_param __user *, param);
+COMPAT_SYSCALL_WRAP3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param);
+COMPAT_SYSCALL_WRAP5(mremap, unsigned long, addr, unsigned long, old_len, unsigned long, new_len, unsigned long, flags, unsigned long, new_addr);
+COMPAT_SYSCALL_WRAP3(poll, struct pollfd __user *, ufds, unsigned int, nfds, int, timeout);
+COMPAT_SYSCALL_WRAP5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5);
+COMPAT_SYSCALL_WRAP2(getcwd, char __user *, buf, unsigned long, size);
+COMPAT_SYSCALL_WRAP2(capget, cap_user_header_t, header, cap_user_data_t, dataptr);
+COMPAT_SYSCALL_WRAP2(capset, cap_user_header_t, header, const cap_user_data_t, data);
+COMPAT_SYSCALL_WRAP3(lchown, const char __user *, filename, uid_t, user, gid_t, group);
+COMPAT_SYSCALL_WRAP2(getgroups, int, gidsetsize, gid_t __user *, grouplist);
+COMPAT_SYSCALL_WRAP2(setgroups, int, gidsetsize, gid_t __user *, grouplist);
+COMPAT_SYSCALL_WRAP3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid);
+COMPAT_SYSCALL_WRAP3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid);
+COMPAT_SYSCALL_WRAP3(chown, const char __user *, filename, uid_t, user, gid_t, group);
+COMPAT_SYSCALL_WRAP2(pivot_root, const char __user *, new_root, const char __user *, put_old);
+COMPAT_SYSCALL_WRAP3(mincore, unsigned long, start, size_t, len, unsigned char __user *, vec);
+COMPAT_SYSCALL_WRAP3(madvise, unsigned long, start, size_t, len, int, behavior);
+COMPAT_SYSCALL_WRAP5(setxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags);
+COMPAT_SYSCALL_WRAP5(lsetxattr, const char __user *, path, const char __user *, name, const void __user *, value, size_t, size, int, flags);
+COMPAT_SYSCALL_WRAP5(fsetxattr, int, fd, const char __user *, name, const void __user *, value, size_t, size, int, flags);
+
+#ifndef __ARCH_WANT_COMPAT_SYS_GETDENTS64
+COMPAT_SYSCALL_WRAP3(getdents64, unsigned int, fd, struct linux_dirent64 __user *, dirent, unsigned int, count);
+#endif
+
+COMPAT_SYSCALL_WRAP4(getxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size);
+COMPAT_SYSCALL_WRAP4(lgetxattr, const char __user *, path, const char __user *, name, void __user *, value, size_t, size);
+COMPAT_SYSCALL_WRAP4(fgetxattr, int, fd, const char __user *, name, void __user *, value, size_t, size);
+COMPAT_SYSCALL_WRAP3(listxattr, const char __user *, path, char __user *, list, size_t, size);
+COMPAT_SYSCALL_WRAP3(llistxattr, const char __user *, path, char __user *, list, size_t, size);
+COMPAT_SYSCALL_WRAP3(flistxattr, int, fd, char __user *, list, size_t, size);
+COMPAT_SYSCALL_WRAP2(removexattr, const char __user *, path, const char __user *, name);
+COMPAT_SYSCALL_WRAP2(lremovexattr, const char __user *, path, const char __user *, name);
+COMPAT_SYSCALL_WRAP2(fremovexattr, int, fd, const char __user *, name);
+COMPAT_SYSCALL_WRAP1(set_tid_address, int __user *, tidptr);
+COMPAT_SYSCALL_WRAP4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event);
+COMPAT_SYSCALL_WRAP4(epoll_wait, int, epfd, struct epoll_event __user *, events, int, maxevents, int, timeout);
+COMPAT_SYSCALL_WRAP1(io_destroy, aio_context_t, ctx);
+COMPAT_SYSCALL_WRAP3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, struct io_event __user *, result);
+COMPAT_SYSCALL_WRAP1(mq_unlink, const char __user *, name);
+COMPAT_SYSCALL_WRAP5(add_key, const char __user *, tp, const char __user *, dsc, const void __user *, pld, size_t, len, key_serial_t, id);
+COMPAT_SYSCALL_WRAP4(request_key, const char __user *, tp, const char __user *, dsc, const char __user *, info, key_serial_t, id);
+COMPAT_SYSCALL_WRAP5(remap_file_pages, unsigned long, start, unsigned long, size, unsigned long, prot, unsigned long, pgoff, unsigned long, flags);
+COMPAT_SYSCALL_WRAP3(inotify_add_watch, int, fd, const char __user *, path, u32, mask);
+COMPAT_SYSCALL_WRAP3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode);
+COMPAT_SYSCALL_WRAP4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, unsigned, dev);
+COMPAT_SYSCALL_WRAP5(fchownat, int, dfd, const char __user *, filename, uid_t, user, gid_t, group, int, flag);
+COMPAT_SYSCALL_WRAP3(unlinkat, int, dfd, const char __user *, pathname, int, flag);
+COMPAT_SYSCALL_WRAP4(renameat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname);
+COMPAT_SYSCALL_WRAP5(linkat, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, int, flags);
+COMPAT_SYSCALL_WRAP3(symlinkat, const char __user *, oldname, int, newdfd, const char __user *, newname);
+COMPAT_SYSCALL_WRAP4(readlinkat, int, dfd, const char __user *, path, char __user *, buf, int, bufsiz);
+COMPAT_SYSCALL_WRAP3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode);
+COMPAT_SYSCALL_WRAP3(faccessat, int, dfd, const char __user *, filename, int, mode);
+COMPAT_SYSCALL_WRAP1(unshare, unsigned long, unshare_flags);
+COMPAT_SYSCALL_WRAP6(splice, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags);
+COMPAT_SYSCALL_WRAP4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags);
+COMPAT_SYSCALL_WRAP3(getcpu, unsigned __user *, cpu, unsigned __user *, node, struct getcpu_cache __user *, cache);
+COMPAT_SYSCALL_WRAP2(pipe2, int __user *, fildes, int, flags);
+COMPAT_SYSCALL_WRAP5(perf_event_open, struct perf_event_attr __user *, attr_uptr, pid_t, pid, int, cpu, int, group_fd, unsigned long, flags);
+
+#ifdef __ARCH_WANT_SYS_CLONE
+#ifdef CONFIG_CLONE_BACKWARDS
+COMPAT_SYSCALL_WRAP5(clone, unsigned long, clone_flags, unsigned long, newsp,
+                int __user *, parent_tidptr,
+                unsigned long, tls,
+                int __user *, child_tidptr);
+#elif defined(CONFIG_CLONE_BACKWARDS2)
+       COMPAT_SYSCALL_WRAP5(clone, unsigned long, newsp, unsigned long, clone_flags,
+               int __user *, parent_tidptr,
+               int __user *, child_tidptr,
+               unsigned long, tls);
+#elif defined(CONFIG_CLONE_BACKWARDS3)
+       COMPAT_SYSCALL_WRAP6(clone, unsigned long, clone_flags, unsigned long, newsp,
+              int, stack_size,
+              int __user *, parent_tidptr,
+              int __user *, child_tidptr,
+               unsigned long, tls);
+#else
+COMPAT_SYSCALL_WRAP5(clone, unsigned long, clone_flags, unsigned long, newsp,
+       int __user *, parent_tidptr,
+       int __user *, child_tidptr,
+       unsigned long, tls);
+#endif
+#endif
+
+COMPAT_SYSCALL_WRAP4(prlimit64, pid_t, pid, unsigned int, resource, const struct rlimit64 __user *, new_rlim, struct rlimit64 __user *, old_rlim);
+COMPAT_SYSCALL_WRAP5(name_to_handle_at, int, dfd, const char __user *, name, struct file_handle __user *, handle, int __user *, mnt_id, int, flag);
+COMPAT_SYSCALL_WRAP5(kcmp, pid_t, pid1, pid_t, pid2, int, type, unsigned long, idx1, unsigned long, idx2);
+COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, flags);
+COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
+COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags);
+COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags);
+COMPAT_SYSCALL_WRAP3(seccomp, unsigned int, op, unsigned int, flags, const char __user *, uargs)
+COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags)
+COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags)
+COMPAT_SYSCALL_WRAP3(bpf, int, cmd, union bpf_attr *, attr, unsigned int, size);
+COMPAT_SYSCALL_WRAP4(socketpair, int, family, int, type, int, protocol, int __user *, usockvec);
+COMPAT_SYSCALL_WRAP3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen);
+COMPAT_SYSCALL_WRAP3(connect, int, fd, struct sockaddr __user *, uservaddr, int, addrlen);
+COMPAT_SYSCALL_WRAP4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, int __user *, upeer_addrlen, int, flags);
+COMPAT_SYSCALL_WRAP3(getsockname, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
+COMPAT_SYSCALL_WRAP3(getpeername, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
+COMPAT_SYSCALL_WRAP6(sendto, int, fd, void __user *, buff, size_t, len, unsigned int, flags, struct sockaddr __user *, addr, int, addr_len);
+COMPAT_SYSCALL_WRAP3(mlock2, unsigned long, start, size_t, len, int, flags);
+COMPAT_SYSCALL_WRAP6(copy_file_range, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags);
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:35 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:35 +0300
Subject: [PATCH 06/23] compat ABI: use non-compat openat and open_by_handle_at
 variants
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-7-git-send-email-ynorov@caviumnetworks.com>

The only difference is that non-compat version forces O_LARGEFILE,
and it should be the default behaviour for all architectures, as
we don't support 32-bit off_t. The only exception is tile32, that
continues with compat version of syscalls.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
Acked-by: Arnd Bergmann <arnd at arndb.de>
Acked-by: Chris Metcalf <cmetcalf at ezchip.com> [for tile]
---
 arch/tile/kernel/compat.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c
index 4912084..489ae19 100644
--- a/arch/tile/kernel/compat.c
+++ b/arch/tile/kernel/compat.c
@@ -94,6 +94,9 @@ COMPAT_SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned int, offset_high,
 #define compat_sys_readahead sys32_readahead
 #define sys_llseek compat_sys_llseek
 
+#define sys_openat		compat_sys_openat
+#define sys_open_by_handle_at	compat_sys_open_by_handle_at
+
 /* Call the assembly trampolines where necessary. */
 #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn
 #define sys_clone _sys_clone
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:34 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:34 +0300
Subject: [PATCH 05/23] all: wrap needed syscalls in generic unistd
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-6-git-send-email-ynorov@caviumnetworks.com>

As generic unistd syscall table is written in C, syscall
prototypes declaration is needed. It's added to compat header.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 include/linux/compat.h            | 225 +++++++++++++++++++++++++++++++++++++
 include/uapi/asm-generic/unistd.h | 227 +++++++++++++++++++-------------------
 2 files changed, 338 insertions(+), 114 deletions(-)

diff --git a/include/linux/compat.h b/include/linux/compat.h
index 4eba16e..248e015 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -789,6 +789,231 @@ asmlinkage long notrace compat_SyS##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__))
 }
 #endif
 
+/* Compat wrappers */
+#include <linux/syscalls_structs.h>
+asmlinkage long compat_sys_creat(const char __user *pathname, umode_t mode);
+asmlinkage long compat_sys_link(const char __user *oldname,
+				const char __user *newname);
+asmlinkage long compat_sys_chdir(const char __user *filename);
+asmlinkage long compat_sys_mknod(const char __user *filename, umode_t mode,
+				unsigned dev);
+asmlinkage long compat_sys_chmod(const char __user *filename, umode_t mode);
+asmlinkage long compat_sys_oldumount(char __user *name);
+asmlinkage long compat_sys_access(const char __user *filename, int mode);
+asmlinkage long compat_sys_rename(const char __user *oldname,
+				const char __user *newname);
+asmlinkage long compat_sys_mkdir(const char __user *pathname, umode_t mode);
+asmlinkage long compat_sys_rmdir(const char __user *pathname);
+asmlinkage long compat_sys_pipe(int __user *fildes);
+asmlinkage long compat_sys_brk(unsigned long brk);
+asmlinkage long compat_sys_signal(int sig, __sighandler_t handler);
+asmlinkage long compat_sys_acct(const char __user *name);
+asmlinkage long compat_sys_umount(char __user *name, int flags);
+asmlinkage long compat_sys_chroot(const char __user *filename);
+
+#ifdef CONFIG_OLD_SIGSUSPEND
+asmlinkage long compat_sys_sigsuspend(old_sigset_t mask);
+#endif
+
+#ifdef CONFIG_OLD_SIGSUSPEND3
+asmlinkage long compat_sys_sigsuspend(int unused1, int unused2, old_sigset_t mask);
+#endif
+
+asmlinkage long compat_sys_sethostname(char __user *name, int len);
+asmlinkage long compat_sys_symlink(const char __user *old, const char __user *new);
+asmlinkage long compat_sys_readlink(const char __user *path,
+				char __user *buf, int bufsiz);
+asmlinkage long compat_sys_uselib(const char __user *library);
+asmlinkage long compat_sys_swapon(const char __user *specialfile, int swap_flags);
+asmlinkage long compat_sys_reboot(int magic1, int magic2, unsigned int cmd,
+				void __user *arg);
+asmlinkage long compat_sys_munmap(unsigned long addr, size_t len);
+asmlinkage long compat_sys_munmap(unsigned long addr, size_t len);
+asmlinkage long compat_sys_syslog(int type, char __user *buf, int len);
+asmlinkage long compat_sys_swapoff(const char __user *specialfile);
+asmlinkage long compat_sys_setdomainname(char __user *name, int len);
+asmlinkage long compat_sys_newuname(struct new_utsname __user *name);
+asmlinkage long compat_sys_mprotect(unsigned long start, size_t len,
+				unsigned long prot);
+asmlinkage long compat_sys_init_module(void __user *umod, unsigned long len,
+				const char __user *uargs);
+asmlinkage long compat_sys_delete_module(const char __user *name_user,
+				unsigned int flags);
+asmlinkage long compat_sys_quotactl(unsigned int cmd, const char __user *special,
+				qid_t id, void __user *addr);
+asmlinkage long compat_sys_bdflush(int func, long data);
+asmlinkage long compat_sys_sysfs(int option,
+				unsigned long arg1, unsigned long arg2);
+asmlinkage long compat_sys_llseek(unsigned int fd, unsigned long offset_high,
+			unsigned long offset_low, loff_t __user *result,
+			unsigned int whence);
+asmlinkage long compat_sys_msync(unsigned long start, size_t len, int flags);
+asmlinkage long compat_sys_mlock(unsigned long start, size_t len);
+asmlinkage long compat_sys_munlock(unsigned long start, size_t len);
+asmlinkage long compat_sys_sched_setparam(pid_t pid,
+					struct sched_param __user *param);
+asmlinkage long compat_sys_sched_getparam(pid_t pid,
+					struct sched_param __user *param);
+asmlinkage long compat_sys_sched_setscheduler(pid_t pid, int policy,
+					struct sched_param __user *param);
+asmlinkage long compat_sys_mremap(unsigned long addr,
+			   unsigned long old_len, unsigned long new_len,
+			   unsigned long flags, unsigned long new_addr);
+asmlinkage long compat_sys_poll(struct pollfd __user *ufds, unsigned int nfds,
+				int timeout);
+asmlinkage long compat_sys_prctl(int option, unsigned long arg2, unsigned long arg3,
+			unsigned long arg4, unsigned long arg5);
+asmlinkage long compat_sys_getcwd(char __user *buf, unsigned long size);
+asmlinkage long compat_sys_capget(cap_user_header_t header,
+				cap_user_data_t dataptr);
+asmlinkage long compat_sys_capset(cap_user_header_t header,
+				const cap_user_data_t data);
+asmlinkage long compat_sys_lchown(const char __user *filename,
+				uid_t user, gid_t group);
+asmlinkage long compat_sys_getgroups(int gidsetsize, gid_t __user *grouplist);
+asmlinkage long compat_sys_setgroups(int gidsetsize, gid_t __user *grouplist);
+asmlinkage long compat_sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid);
+asmlinkage long compat_sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid);
+asmlinkage long compat_sys_chown(const char __user *filename,
+				uid_t user, gid_t group);
+asmlinkage long compat_sys_pivot_root(const char __user *new_root,
+				const char __user *put_old);
+asmlinkage long compat_sys_mincore(unsigned long start, size_t len,
+				unsigned char __user * vec);
+asmlinkage long compat_sys_madvise(unsigned long start, size_t len, int behavior);
+asmlinkage long compat_sys_setxattr(const char __user *path, const char __user *name,
+			     const void __user *value, size_t size, int flags);
+asmlinkage long compat_sys_lsetxattr(const char __user *path, const char __user *name,
+			      const void __user *value, size_t size, int flags);
+asmlinkage long compat_sys_fsetxattr(int fd, const char __user *name,
+			      const void __user *value, size_t size, int flags);
+asmlinkage long compat_sys_getdents64(unsigned int fd,
+				struct linux_dirent64 __user *dirent,
+				unsigned int count);
+asmlinkage long compat_sys_getxattr(const char __user *path, const char __user *name,
+			     void __user *value, size_t size);
+asmlinkage long compat_sys_lgetxattr(const char __user *path, const char __user *name,
+			      void __user *value, size_t size);
+asmlinkage long compat_sys_fgetxattr(int fd, const char __user *name,
+			      void __user *value, size_t size);
+asmlinkage long compat_sys_listxattr(const char __user *path, char __user *list,
+			      size_t size);
+asmlinkage long compat_sys_llistxattr(const char __user *path, char __user *list,
+			       size_t size);
+asmlinkage long compat_sys_flistxattr(int fd, char __user *list, size_t size);
+asmlinkage long compat_sys_listxattr(const char __user *path, char __user *list,
+			      size_t size);
+asmlinkage long compat_sys_llistxattr(const char __user *path, char __user *list,
+			       size_t size);
+asmlinkage long compat_sys_flistxattr(int fd, char __user *list, size_t size);
+asmlinkage long compat_sys_removexattr(const char __user *path,
+				const char __user *name);
+asmlinkage long compat_sys_lremovexattr(const char __user *path,
+				 const char __user *name);
+asmlinkage long compat_sys_fremovexattr(int fd, const char __user *name);
+asmlinkage long compat_sys_set_tid_address(int __user *tidptr);
+asmlinkage long compat_sys_epoll_ctl(int epfd, int op, int fd,
+				struct epoll_event __user *event);
+asmlinkage long compat_sys_epoll_wait(int epfd, struct epoll_event __user *events,
+				int maxevents, int timeout);
+asmlinkage long compat_sys_io_destroy(aio_context_t ctx);
+asmlinkage long compat_sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
+			      struct io_event __user *result);
+asmlinkage long compat_sys_mq_unlink(const char __user *name);
+asmlinkage long compat_sys_add_key(const char __user *_type,
+			    const char __user *_description,
+			    const void __user *_payload,
+			    size_t plen,
+			    key_serial_t destringid);
+asmlinkage long compat_sys_request_key(const char __user *_type,
+				const char __user *_description,
+				const char __user *_callout_info,
+				key_serial_t destringid);
+asmlinkage long compat_sys_remap_file_pages(unsigned long start, unsigned long size,
+			unsigned long prot, unsigned long pgoff,
+			unsigned long flags);
+asmlinkage long compat_sys_inotify_add_watch(int fd, const char __user *path,
+					u32 mask);
+asmlinkage long compat_sys_mknodat(int dfd, const char __user * filename, umode_t mode,
+			    unsigned dev);
+asmlinkage long compat_sys_mkdirat(int dfd, const char __user * pathname, umode_t mode);
+asmlinkage long compat_sys_fchownat(int dfd, const char __user *filename, uid_t user,
+			     gid_t group, int flag);
+asmlinkage long compat_sys_unlinkat(int dfd, const char __user * pathname, int flag);
+asmlinkage long compat_sys_renameat(int olddfd, const char __user * oldname,
+			     int newdfd, const char __user * newname);
+asmlinkage long compat_sys_symlinkat(const char __user * oldname,
+			      int newdfd, const char __user * newname);
+asmlinkage long compat_sys_linkat(int olddfd, const char __user *oldname,
+			   int newdfd, const char __user *newname, int flags);
+asmlinkage long compat_sys_readlinkat(int dfd, const char __user *path, char __user *buf,
+			       int bufsiz);
+asmlinkage long compat_sys_fchmodat(int dfd, const char __user * filename,
+			     umode_t mode);
+asmlinkage long compat_sys_faccessat(int dfd, const char __user *filename, int mode);
+asmlinkage long compat_sys_unshare(unsigned long unshare_flags);
+asmlinkage long compat_sys_splice(int fd_in, loff_t __user *off_in,
+			   int fd_out, loff_t __user *off_out,
+			   size_t len, unsigned int flags);
+asmlinkage long compat_sys_tee(int fdin, int fdout, size_t len, unsigned int flags);
+asmlinkage long compat_sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache);
+asmlinkage long compat_sys_pipe2(int __user *fildes, int flags);
+asmlinkage long compat_sys_perf_event_open(
+		struct perf_event_attr __user *attr_uptr,
+		pid_t pid, int cpu, int group_fd, unsigned long flags);
+
+#ifdef CONFIG_CLONE_BACKWARDS
+asmlinkage long compat_sys_clone(unsigned long, unsigned long, int __user *, unsigned long,
+	       int __user *);
+#else
+#ifdef CONFIG_CLONE_BACKWARDS3
+asmlinkage long compat_sys_clone(unsigned long, unsigned long, int, int __user *,
+			  int __user *, unsigned long);
+#else
+asmlinkage long compat_sys_clone(unsigned long, unsigned long, int __user *,
+	       int __user *, unsigned long);
+#endif
+#endif
+
+asmlinkage long compat_sys_prlimit64(pid_t pid, unsigned int resource,
+				const struct rlimit64 __user *new_rlim,
+				struct rlimit64 __user *old_rlim);
+asmlinkage long compat_sys_name_to_handle_at(int dfd, const char __user *name,
+				      struct file_handle __user *handle,
+				      int __user *mnt_id, int flag);
+asmlinkage long compat_sys_kcmp(pid_t pid1, pid_t pid2, int type,
+			 unsigned long idx1, unsigned long idx2);
+asmlinkage long compat_sys_finit_module(int fd, const char __user *uargs, int flags);
+asmlinkage long compat_sys_sched_setattr(pid_t pid,
+					struct sched_attr __user *attr,
+					unsigned int flags);
+asmlinkage long compat_sys_sched_getattr(pid_t pid,
+					struct sched_attr __user *attr,
+					unsigned int size,
+					unsigned int flags);
+asmlinkage long compat_sys_renameat2(int olddfd, const char __user *oldname,
+			      int newdfd, const char __user *newname,
+			      unsigned int flags);
+asmlinkage long compat_sys_seccomp(unsigned int op, unsigned int flags,
+			    const char __user *uargs);
+asmlinkage long compat_sys_getrandom(char __user *buf, size_t count,
+			      unsigned int flags);
+asmlinkage long compat_sys_memfd_create(const char __user *uname_ptr, unsigned int flags);
+asmlinkage long compat_sys_bpf(int cmd, union bpf_attr *attr, unsigned int size);
+asmlinkage long compat_sys_socketpair(int, int, int, int __user *);
+asmlinkage long compat_sys_bind(int, struct sockaddr __user *, int);
+asmlinkage long compat_sys_connect(int, struct sockaddr __user *, int);
+asmlinkage long compat_sys_accept4(int, struct sockaddr __user *, int __user *, int);
+asmlinkage long compat_sys_getsockname(int, struct sockaddr __user *, int __user *);
+asmlinkage long compat_sys_getpeername(int, struct sockaddr __user *, int __user *);
+asmlinkage long compat_sys_sendto(int, void __user *, size_t, unsigned,
+				struct sockaddr __user *, int);
+asmlinkage long compat_sys_mlock2(unsigned long start, size_t len, int flags);
+
+asmlinkage long compat_sys_copy_file_range(int fd_in, loff_t __user *off_in,
+				    int fd_out, loff_t __user *off_out,
+				    size_t len, unsigned int flags);
+
 #endif /* CONFIG_COMPAT_WRAPPER */
 
 #endif /* _LINUX_COMPAT_H */
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 7e91d83..6ed4613 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -36,43 +36,43 @@
 #define __NR_io_setup 0
 __SC_COMP(__NR_io_setup, sys_io_setup, compat_sys_io_setup)
 #define __NR_io_destroy 1
-__SYSCALL(__NR_io_destroy, sys_io_destroy)
+__SC_WRAP(__NR_io_destroy, sys_io_destroy)
 #define __NR_io_submit 2
 __SC_COMP(__NR_io_submit, sys_io_submit, compat_sys_io_submit)
 #define __NR_io_cancel 3
-__SYSCALL(__NR_io_cancel, sys_io_cancel)
+__SC_WRAP(__NR_io_cancel, sys_io_cancel)
 #define __NR_io_getevents 4
 __SC_COMP(__NR_io_getevents, sys_io_getevents, compat_sys_io_getevents)
 
 /* fs/xattr.c */
 #define __NR_setxattr 5
-__SYSCALL(__NR_setxattr, sys_setxattr)
+__SC_WRAP(__NR_setxattr, sys_setxattr)
 #define __NR_lsetxattr 6
-__SYSCALL(__NR_lsetxattr, sys_lsetxattr)
+__SC_WRAP(__NR_lsetxattr, sys_lsetxattr)
 #define __NR_fsetxattr 7
-__SYSCALL(__NR_fsetxattr, sys_fsetxattr)
+__SC_WRAP(__NR_fsetxattr, sys_fsetxattr)
 #define __NR_getxattr 8
-__SYSCALL(__NR_getxattr, sys_getxattr)
+__SC_WRAP(__NR_getxattr, sys_getxattr)
 #define __NR_lgetxattr 9
-__SYSCALL(__NR_lgetxattr, sys_lgetxattr)
+__SC_WRAP(__NR_lgetxattr, sys_lgetxattr)
 #define __NR_fgetxattr 10
-__SYSCALL(__NR_fgetxattr, sys_fgetxattr)
+__SC_WRAP(__NR_fgetxattr, sys_fgetxattr)
 #define __NR_listxattr 11
-__SYSCALL(__NR_listxattr, sys_listxattr)
+__SC_WRAP(__NR_listxattr, sys_listxattr)
 #define __NR_llistxattr 12
-__SYSCALL(__NR_llistxattr, sys_llistxattr)
+__SC_WRAP(__NR_llistxattr, sys_llistxattr)
 #define __NR_flistxattr 13
-__SYSCALL(__NR_flistxattr, sys_flistxattr)
+__SC_WRAP(__NR_flistxattr, sys_flistxattr)
 #define __NR_removexattr 14
-__SYSCALL(__NR_removexattr, sys_removexattr)
+__SC_WRAP(__NR_removexattr, sys_removexattr)
 #define __NR_lremovexattr 15
-__SYSCALL(__NR_lremovexattr, sys_lremovexattr)
+__SC_WRAP(__NR_lremovexattr, sys_lremovexattr)
 #define __NR_fremovexattr 16
-__SYSCALL(__NR_fremovexattr, sys_fremovexattr)
+__SC_WRAP(__NR_fremovexattr, sys_fremovexattr)
 
 /* fs/dcache.c */
 #define __NR_getcwd 17
-__SYSCALL(__NR_getcwd, sys_getcwd)
+__SC_WRAP(__NR_getcwd, sys_getcwd)
 
 /* fs/cookies.c */
 #define __NR_lookup_dcookie 18
@@ -86,7 +86,7 @@ __SYSCALL(__NR_eventfd2, sys_eventfd2)
 #define __NR_epoll_create1 20
 __SYSCALL(__NR_epoll_create1, sys_epoll_create1)
 #define __NR_epoll_ctl 21
-__SYSCALL(__NR_epoll_ctl, sys_epoll_ctl)
+__SC_WRAP(__NR_epoll_ctl, sys_epoll_ctl)
 #define __NR_epoll_pwait 22
 __SC_COMP(__NR_epoll_pwait, sys_epoll_pwait, compat_sys_epoll_pwait)
 
@@ -102,7 +102,7 @@ __SC_COMP_3264(__NR3264_fcntl, sys_fcntl64, sys_fcntl, compat_sys_fcntl64)
 #define __NR_inotify_init1 26
 __SYSCALL(__NR_inotify_init1, sys_inotify_init1)
 #define __NR_inotify_add_watch 27
-__SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch)
+__SC_WRAP(__NR_inotify_add_watch, sys_inotify_add_watch)
 #define __NR_inotify_rm_watch 28
 __SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch)
 
@@ -122,17 +122,17 @@ __SYSCALL(__NR_flock, sys_flock)
 
 /* fs/namei.c */
 #define __NR_mknodat 33
-__SYSCALL(__NR_mknodat, sys_mknodat)
+__SC_WRAP(__NR_mknodat, sys_mknodat)
 #define __NR_mkdirat 34
-__SYSCALL(__NR_mkdirat, sys_mkdirat)
+__SC_WRAP(__NR_mkdirat, sys_mkdirat)
 #define __NR_unlinkat 35
-__SYSCALL(__NR_unlinkat, sys_unlinkat)
+__SC_WRAP(__NR_unlinkat, sys_unlinkat)
 #define __NR_symlinkat 36
-__SYSCALL(__NR_symlinkat, sys_symlinkat)
+__SC_WRAP(__NR_symlinkat, sys_symlinkat)
 #define __NR_linkat 37
-__SYSCALL(__NR_linkat, sys_linkat)
+__SC_WRAP(__NR_linkat, sys_linkat)
 #define __NR_renameat 38
-__SYSCALL(__NR_renameat, sys_renameat)
+__SC_WRAP(__NR_renameat, sys_renameat)
 
 /* fs/namespace.c */
 #define __NR_umount2 39
@@ -140,7 +140,7 @@ __SYSCALL(__NR_umount2, sys_umount)
 #define __NR_mount 40
 __SC_COMP(__NR_mount, sys_mount, compat_sys_mount)
 #define __NR_pivot_root 41
-__SYSCALL(__NR_pivot_root, sys_pivot_root)
+__SC_WRAP(__NR_pivot_root, sys_pivot_root)
 
 /* fs/nfsctl.c */
 #define __NR_nfsservctl 42
@@ -163,23 +163,23 @@ __SC_COMP_3264(__NR3264_ftruncate, sys_ftruncate64, sys_ftruncate, \
 #define __NR_fallocate 47
 __SC_COMP(__NR_fallocate, sys_fallocate, compat_sys_fallocate)
 #define __NR_faccessat 48
-__SYSCALL(__NR_faccessat, sys_faccessat)
+__SC_WRAP(__NR_faccessat, sys_faccessat)
 #define __NR_chdir 49
-__SYSCALL(__NR_chdir, sys_chdir)
+__SC_WRAP(__NR_chdir, sys_chdir)
 #define __NR_fchdir 50
 __SYSCALL(__NR_fchdir, sys_fchdir)
 #define __NR_chroot 51
-__SYSCALL(__NR_chroot, sys_chroot)
+__SC_WRAP(__NR_chroot, sys_chroot)
 #define __NR_fchmod 52
 __SYSCALL(__NR_fchmod, sys_fchmod)
 #define __NR_fchmodat 53
-__SYSCALL(__NR_fchmodat, sys_fchmodat)
+__SC_WRAP(__NR_fchmodat, sys_fchmodat)
 #define __NR_fchownat 54
-__SYSCALL(__NR_fchownat, sys_fchownat)
+__SC_WRAP(__NR_fchownat, sys_fchownat)
 #define __NR_fchown 55
 __SYSCALL(__NR_fchown, sys_fchown)
 #define __NR_openat 56
-__SC_COMP(__NR_openat, sys_openat, compat_sys_openat)
+__SYSCALL(__NR_openat, sys_openat)
 #define __NR_close 57
 __SYSCALL(__NR_close, sys_close)
 #define __NR_vhangup 58
@@ -187,11 +187,11 @@ __SYSCALL(__NR_vhangup, sys_vhangup)
 
 /* fs/pipe.c */
 #define __NR_pipe2 59
-__SYSCALL(__NR_pipe2, sys_pipe2)
+__SC_WRAP(__NR_pipe2, sys_pipe2)
 
 /* fs/quota.c */
 #define __NR_quotactl 60
-__SYSCALL(__NR_quotactl, sys_quotactl)
+__SC_WRAP(__NR_quotactl, sys_quotactl)
 
 /* fs/readdir.c */
 #define __NR_getdents64 61
@@ -236,13 +236,13 @@ __SC_COMP(__NR_signalfd4, sys_signalfd4, compat_sys_signalfd4)
 #define __NR_vmsplice 75
 __SC_COMP(__NR_vmsplice, sys_vmsplice, compat_sys_vmsplice)
 #define __NR_splice 76
-__SYSCALL(__NR_splice, sys_splice)
+__SC_WRAP(__NR_splice, sys_splice)
 #define __NR_tee 77
-__SYSCALL(__NR_tee, sys_tee)
+__SC_WRAP(__NR_tee, sys_tee)
 
 /* fs/stat.c */
 #define __NR_readlinkat 78
-__SYSCALL(__NR_readlinkat, sys_readlinkat)
+__SC_WRAP(__NR_readlinkat, sys_readlinkat)
 #define __NR3264_fstatat 79
 __SC_3264(__NR3264_fstatat, sys_fstatat64, sys_newfstatat)
 #define __NR3264_fstat 80
@@ -281,13 +281,13 @@ __SC_COMP(__NR_utimensat, sys_utimensat, compat_sys_utimensat)
 
 /* kernel/acct.c */
 #define __NR_acct 89
-__SYSCALL(__NR_acct, sys_acct)
+__SC_WRAP(__NR_acct, sys_acct)
 
 /* kernel/capability.c */
 #define __NR_capget 90
-__SYSCALL(__NR_capget, sys_capget)
+__SC_WRAP(__NR_capget, sys_capget)
 #define __NR_capset 91
-__SYSCALL(__NR_capset, sys_capset)
+__SC_WRAP(__NR_capset, sys_capset)
 
 /* kernel/exec_domain.c */
 #define __NR_personality 92
@@ -303,9 +303,9 @@ __SC_COMP(__NR_waitid, sys_waitid, compat_sys_waitid)
 
 /* kernel/fork.c */
 #define __NR_set_tid_address 96
-__SYSCALL(__NR_set_tid_address, sys_set_tid_address)
+__SC_WRAP(__NR_set_tid_address, sys_set_tid_address)
 #define __NR_unshare 97
-__SYSCALL(__NR_unshare, sys_unshare)
+__SC_WRAP(__NR_unshare, sys_unshare)
 
 /* kernel/futex.c */
 #define __NR_futex 98
@@ -333,9 +333,9 @@ __SC_COMP(__NR_kexec_load, sys_kexec_load, compat_sys_kexec_load)
 
 /* kernel/module.c */
 #define __NR_init_module 105
-__SYSCALL(__NR_init_module, sys_init_module)
+__SC_WRAP(__NR_init_module, sys_init_module)
 #define __NR_delete_module 106
-__SYSCALL(__NR_delete_module, sys_delete_module)
+__SC_WRAP(__NR_delete_module, sys_delete_module)
 
 /* kernel/posix-timers.c */
 #define __NR_timer_create 107
@@ -360,7 +360,7 @@ __SC_COMP(__NR_clock_nanosleep, sys_clock_nanosleep, \
 
 /* kernel/printk.c */
 #define __NR_syslog 116
-__SYSCALL(__NR_syslog, sys_syslog)
+__SC_WRAP(__NR_syslog, sys_syslog)
 
 /* kernel/ptrace.c */
 #define __NR_ptrace 117
@@ -368,13 +368,13 @@ __SYSCALL(__NR_ptrace, sys_ptrace)
 
 /* kernel/sched/core.c */
 #define __NR_sched_setparam 118
-__SYSCALL(__NR_sched_setparam, sys_sched_setparam)
+__SC_WRAP(__NR_sched_setparam, sys_sched_setparam)
 #define __NR_sched_setscheduler 119
-__SYSCALL(__NR_sched_setscheduler, sys_sched_setscheduler)
+__SC_WRAP(__NR_sched_setscheduler, sys_sched_setscheduler)
 #define __NR_sched_getscheduler 120
 __SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler)
 #define __NR_sched_getparam 121
-__SYSCALL(__NR_sched_getparam, sys_sched_getparam)
+__SC_WRAP(__NR_sched_getparam, sys_sched_getparam)
 #define __NR_sched_setaffinity 122
 __SC_COMP(__NR_sched_setaffinity, sys_sched_setaffinity, \
 	  compat_sys_sched_setaffinity)
@@ -425,7 +425,7 @@ __SYSCALL(__NR_setpriority, sys_setpriority)
 #define __NR_getpriority 141
 __SYSCALL(__NR_getpriority, sys_getpriority)
 #define __NR_reboot 142
-__SYSCALL(__NR_reboot, sys_reboot)
+__SC_WRAP(__NR_reboot, sys_reboot)
 #define __NR_setregid 143
 __SYSCALL(__NR_setregid, sys_setregid)
 #define __NR_setgid 144
@@ -437,11 +437,11 @@ __SYSCALL(__NR_setuid, sys_setuid)
 #define __NR_setresuid 147
 __SYSCALL(__NR_setresuid, sys_setresuid)
 #define __NR_getresuid 148
-__SYSCALL(__NR_getresuid, sys_getresuid)
+__SC_WRAP(__NR_getresuid, sys_getresuid)
 #define __NR_setresgid 149
 __SYSCALL(__NR_setresgid, sys_setresgid)
 #define __NR_getresgid 150
-__SYSCALL(__NR_getresgid, sys_getresgid)
+__SC_WRAP(__NR_getresgid, sys_getresgid)
 #define __NR_setfsuid 151
 __SYSCALL(__NR_setfsuid, sys_setfsuid)
 #define __NR_setfsgid 152
@@ -457,15 +457,15 @@ __SYSCALL(__NR_getsid, sys_getsid)
 #define __NR_setsid 157
 __SYSCALL(__NR_setsid, sys_setsid)
 #define __NR_getgroups 158
-__SYSCALL(__NR_getgroups, sys_getgroups)
+__SC_WRAP(__NR_getgroups, sys_getgroups)
 #define __NR_setgroups 159
-__SYSCALL(__NR_setgroups, sys_setgroups)
+__SC_WRAP(__NR_setgroups, sys_setgroups)
 #define __NR_uname 160
-__SYSCALL(__NR_uname, sys_newuname)
+__SC_WRAP(__NR_uname, sys_newuname)
 #define __NR_sethostname 161
-__SYSCALL(__NR_sethostname, sys_sethostname)
+__SC_WRAP(__NR_sethostname, sys_sethostname)
 #define __NR_setdomainname 162
-__SYSCALL(__NR_setdomainname, sys_setdomainname)
+__SC_WRAP(__NR_setdomainname, sys_setdomainname)
 #define __NR_getrlimit 163
 __SC_COMP(__NR_getrlimit, sys_getrlimit, compat_sys_getrlimit)
 #define __NR_setrlimit 164
@@ -475,9 +475,9 @@ __SC_COMP(__NR_getrusage, sys_getrusage, compat_sys_getrusage)
 #define __NR_umask 166
 __SYSCALL(__NR_umask, sys_umask)
 #define __NR_prctl 167
-__SYSCALL(__NR_prctl, sys_prctl)
+__SC_WRAP(__NR_prctl, sys_prctl)
 #define __NR_getcpu 168
-__SYSCALL(__NR_getcpu, sys_getcpu)
+__SC_WRAP(__NR_getcpu, sys_getcpu)
 
 /* kernel/time.c */
 #define __NR_gettimeofday 169
@@ -509,7 +509,7 @@ __SC_COMP(__NR_sysinfo, sys_sysinfo, compat_sys_sysinfo)
 #define __NR_mq_open 180
 __SC_COMP(__NR_mq_open, sys_mq_open, compat_sys_mq_open)
 #define __NR_mq_unlink 181
-__SYSCALL(__NR_mq_unlink, sys_mq_unlink)
+__SC_WRAP(__NR_mq_unlink, sys_mq_unlink)
 #define __NR_mq_timedsend 182
 __SC_COMP(__NR_mq_timedsend, sys_mq_timedsend, compat_sys_mq_timedsend)
 #define __NR_mq_timedreceive 183
@@ -554,21 +554,21 @@ __SYSCALL(__NR_shmdt, sys_shmdt)
 #define __NR_socket 198
 __SYSCALL(__NR_socket, sys_socket)
 #define __NR_socketpair 199
-__SYSCALL(__NR_socketpair, sys_socketpair)
+__SC_WRAP(__NR_socketpair, sys_socketpair)
 #define __NR_bind 200
-__SYSCALL(__NR_bind, sys_bind)
+__SC_WRAP(__NR_bind, sys_bind)
 #define __NR_listen 201
 __SYSCALL(__NR_listen, sys_listen)
 #define __NR_accept 202
 __SYSCALL(__NR_accept, sys_accept)
 #define __NR_connect 203
-__SYSCALL(__NR_connect, sys_connect)
+__SC_WRAP(__NR_connect, sys_connect)
 #define __NR_getsockname 204
-__SYSCALL(__NR_getsockname, sys_getsockname)
+__SC_WRAP(__NR_getsockname, sys_getsockname)
 #define __NR_getpeername 205
-__SYSCALL(__NR_getpeername, sys_getpeername)
+__SC_WRAP(__NR_getpeername, sys_getpeername)
 #define __NR_sendto 206
-__SYSCALL(__NR_sendto, sys_sendto)
+__SC_WRAP(__NR_sendto, sys_sendto)
 #define __NR_recvfrom 207
 __SC_COMP(__NR_recvfrom, sys_recvfrom, compat_sys_recvfrom)
 #define __NR_setsockopt 208
@@ -588,23 +588,23 @@ __SC_COMP(__NR_readahead, sys_readahead, compat_sys_readahead)
 
 /* mm/nommu.c, also with MMU */
 #define __NR_brk 214
-__SYSCALL(__NR_brk, sys_brk)
+__SC_WRAP(__NR_brk, sys_brk)
 #define __NR_munmap 215
-__SYSCALL(__NR_munmap, sys_munmap)
+__SC_WRAP(__NR_munmap, sys_munmap)
 #define __NR_mremap 216
-__SYSCALL(__NR_mremap, sys_mremap)
+__SC_WRAP(__NR_mremap, sys_mremap)
 
 /* security/keys/keyctl.c */
 #define __NR_add_key 217
-__SYSCALL(__NR_add_key, sys_add_key)
+__SC_WRAP(__NR_add_key, sys_add_key)
 #define __NR_request_key 218
-__SYSCALL(__NR_request_key, sys_request_key)
+__SC_WRAP(__NR_request_key, sys_request_key)
 #define __NR_keyctl 219
 __SC_COMP(__NR_keyctl, sys_keyctl, compat_sys_keyctl)
 
 /* arch/example/kernel/sys_example.c */
 #define __NR_clone 220
-__SYSCALL(__NR_clone, sys_clone)
+__SC_WRAP(__NR_clone, sys_clone)
 #define __NR_execve 221
 __SC_COMP(__NR_execve, sys_execve, compat_sys_execve)
 
@@ -617,27 +617,27 @@ __SC_COMP(__NR3264_fadvise64, sys_fadvise64_64, compat_sys_fadvise64_64)
 /* mm/, CONFIG_MMU only */
 #ifndef __ARCH_NOMMU
 #define __NR_swapon 224
-__SYSCALL(__NR_swapon, sys_swapon)
+__SC_WRAP(__NR_swapon, sys_swapon)
 #define __NR_swapoff 225
-__SYSCALL(__NR_swapoff, sys_swapoff)
+__SC_WRAP(__NR_swapoff, sys_swapoff)
 #define __NR_mprotect 226
-__SYSCALL(__NR_mprotect, sys_mprotect)
+__SC_WRAP(__NR_mprotect, sys_mprotect)
 #define __NR_msync 227
-__SYSCALL(__NR_msync, sys_msync)
+__SC_WRAP(__NR_msync, sys_msync)
 #define __NR_mlock 228
-__SYSCALL(__NR_mlock, sys_mlock)
+__SC_WRAP(__NR_mlock, sys_mlock)
 #define __NR_munlock 229
-__SYSCALL(__NR_munlock, sys_munlock)
+__SC_WRAP(__NR_munlock, sys_munlock)
 #define __NR_mlockall 230
 __SYSCALL(__NR_mlockall, sys_mlockall)
 #define __NR_munlockall 231
 __SYSCALL(__NR_munlockall, sys_munlockall)
 #define __NR_mincore 232
-__SYSCALL(__NR_mincore, sys_mincore)
+__SC_WRAP(__NR_mincore, sys_mincore)
 #define __NR_madvise 233
-__SYSCALL(__NR_madvise, sys_madvise)
+__SC_WRAP(__NR_madvise, sys_madvise)
 #define __NR_remap_file_pages 234
-__SYSCALL(__NR_remap_file_pages, sys_remap_file_pages)
+__SC_WRAP(__NR_remap_file_pages, sys_remap_file_pages)
 #define __NR_mbind 235
 __SC_COMP(__NR_mbind, sys_mbind, compat_sys_mbind)
 #define __NR_get_mempolicy 236
@@ -654,9 +654,9 @@ __SC_COMP(__NR_move_pages, sys_move_pages, compat_sys_move_pages)
 __SC_COMP(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo, \
 	  compat_sys_rt_tgsigqueueinfo)
 #define __NR_perf_event_open 241
-__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
+__SC_WRAP(__NR_perf_event_open, sys_perf_event_open)
 #define __NR_accept4 242
-__SYSCALL(__NR_accept4, sys_accept4)
+__SC_WRAP(__NR_accept4, sys_accept4)
 #define __NR_recvmmsg 243
 __SC_COMP(__NR_recvmmsg, sys_recvmmsg, compat_sys_recvmmsg)
 
@@ -669,16 +669,15 @@ __SC_COMP(__NR_recvmmsg, sys_recvmmsg, compat_sys_recvmmsg)
 #define __NR_wait4 260
 __SC_COMP(__NR_wait4, sys_wait4, compat_sys_wait4)
 #define __NR_prlimit64 261
-__SYSCALL(__NR_prlimit64, sys_prlimit64)
+__SC_WRAP(__NR_prlimit64, sys_prlimit64)
 #define __NR_fanotify_init 262
 __SYSCALL(__NR_fanotify_init, sys_fanotify_init)
 #define __NR_fanotify_mark 263
 __SYSCALL(__NR_fanotify_mark, sys_fanotify_mark)
 #define __NR_name_to_handle_at         264
-__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
+__SC_WRAP(__NR_name_to_handle_at, sys_name_to_handle_at)
 #define __NR_open_by_handle_at         265
-__SC_COMP(__NR_open_by_handle_at, sys_open_by_handle_at, \
-	  compat_sys_open_by_handle_at)
+__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
 #define __NR_clock_adjtime 266
 __SC_COMP(__NR_clock_adjtime, sys_clock_adjtime, compat_sys_clock_adjtime)
 #define __NR_syncfs 267
@@ -694,23 +693,23 @@ __SC_COMP(__NR_process_vm_readv, sys_process_vm_readv, \
 __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \
           compat_sys_process_vm_writev)
 #define __NR_kcmp 272
-__SYSCALL(__NR_kcmp, sys_kcmp)
+__SC_WRAP(__NR_kcmp, sys_kcmp)
 #define __NR_finit_module 273
-__SYSCALL(__NR_finit_module, sys_finit_module)
+__SC_WRAP(__NR_finit_module, sys_finit_module)
 #define __NR_sched_setattr 274
-__SYSCALL(__NR_sched_setattr, sys_sched_setattr)
+__SC_WRAP(__NR_sched_setattr, sys_sched_setattr)
 #define __NR_sched_getattr 275
-__SYSCALL(__NR_sched_getattr, sys_sched_getattr)
+__SC_WRAP(__NR_sched_getattr, sys_sched_getattr)
 #define __NR_renameat2 276
-__SYSCALL(__NR_renameat2, sys_renameat2)
+__SC_WRAP(__NR_renameat2, sys_renameat2)
 #define __NR_seccomp 277
-__SYSCALL(__NR_seccomp, sys_seccomp)
+__SC_WRAP(__NR_seccomp, sys_seccomp)
 #define __NR_getrandom 278
-__SYSCALL(__NR_getrandom, sys_getrandom)
+__SC_WRAP(__NR_getrandom, sys_getrandom)
 #define __NR_memfd_create 279
-__SYSCALL(__NR_memfd_create, sys_memfd_create)
+__SC_WRAP(__NR_memfd_create, sys_memfd_create)
 #define __NR_bpf 280
-__SYSCALL(__NR_bpf, sys_bpf)
+__SC_WRAP(__NR_bpf, sys_bpf)
 #define __NR_execveat 281
 __SC_COMP(__NR_execveat, sys_execveat, compat_sys_execveat)
 #define __NR_userfaultfd 282
@@ -718,9 +717,9 @@ __SYSCALL(__NR_userfaultfd, sys_userfaultfd)
 #define __NR_membarrier 283
 __SYSCALL(__NR_membarrier, sys_membarrier)
 #define __NR_mlock2 284
-__SYSCALL(__NR_mlock2, sys_mlock2)
+__SC_WRAP(__NR_mlock2, sys_mlock2)
 #define __NR_copy_file_range 285
-__SYSCALL(__NR_copy_file_range, sys_copy_file_range)
+__SC_WRAP(__NR_copy_file_range, sys_copy_file_range)
 #define __NR_preadv2 286
 __SC_COMP(__NR_preadv2, sys_preadv2, compat_sys_preadv2)
 #define __NR_pwritev2 287
@@ -741,29 +740,29 @@ __SC_COMP(__NR_pwritev2, sys_pwritev2, compat_sys_pwritev2)
 #define __NR_open 1024
 __SYSCALL(__NR_open, sys_open)
 #define __NR_link 1025
-__SYSCALL(__NR_link, sys_link)
+__SC_WRAP(__NR_link, sys_link)
 #define __NR_unlink 1026
-__SYSCALL(__NR_unlink, sys_unlink)
+__SC_WRAP(__NR_unlink, sys_unlink)
 #define __NR_mknod 1027
-__SYSCALL(__NR_mknod, sys_mknod)
+__SC_WRAP(__NR_mknod, sys_mknod)
 #define __NR_chmod 1028
-__SYSCALL(__NR_chmod, sys_chmod)
+__SC_WRAP(__NR_chmod, sys_chmod)
 #define __NR_chown 1029
-__SYSCALL(__NR_chown, sys_chown)
+__SC_WRAP(__NR_chown, sys_chown)
 #define __NR_mkdir 1030
-__SYSCALL(__NR_mkdir, sys_mkdir)
+__SC_WRAP(__NR_mkdir, sys_mkdir)
 #define __NR_rmdir 1031
-__SYSCALL(__NR_rmdir, sys_rmdir)
+__SC_WRAP(__NR_rmdir, sys_rmdir)
 #define __NR_lchown 1032
-__SYSCALL(__NR_lchown, sys_lchown)
+__SC_WRAP(__NR_lchown, sys_lchown)
 #define __NR_access 1033
-__SYSCALL(__NR_access, sys_access)
+__SC_WRAP(__NR_access, sys_access)
 #define __NR_rename 1034
-__SYSCALL(__NR_rename, sys_rename)
+__SC_WRAP(__NR_rename, sys_rename)
 #define __NR_readlink 1035
-__SYSCALL(__NR_readlink, sys_readlink)
+__SC_WRAP(__NR_readlink, sys_readlink)
 #define __NR_symlink 1036
-__SYSCALL(__NR_symlink, sys_symlink)
+__SC_WRAP(__NR_symlink, sys_symlink)
 #define __NR_utimes 1037
 __SYSCALL(__NR_utimes, sys_utimes)
 #define __NR3264_stat 1038
@@ -777,7 +776,7 @@ __SC_3264(__NR3264_lstat, sys_lstat64, sys_newlstat)
 
 #ifdef __ARCH_WANT_SYSCALL_NO_FLAGS
 #define __NR_pipe 1040
-__SYSCALL(__NR_pipe, sys_pipe)
+__SC_WRAP(__NR_pipe, sys_pipe)
 #define __NR_dup2 1041
 __SYSCALL(__NR_dup2, sys_dup2)
 #define __NR_epoll_create 1042
@@ -847,7 +846,7 @@ __SYSCALL(__NR_time, sys_time)
 __SYSCALL(__NR_utime, sys_utime)
 
 #define __NR_creat 1064
-__SYSCALL(__NR_creat, sys_creat)
+__SC_WRAP(__NR_creat, sys_creat)
 #define __NR_getdents 1065
 #define __ARCH_WANT_SYS_GETDENTS
 __SYSCALL(__NR_getdents, sys_getdents)
@@ -857,9 +856,9 @@ __SYSCALL(__NR_futimesat, sys_futimesat)
 #define __ARCH_WANT_SYS_SELECT
 __SYSCALL(__NR_select, sys_select)
 #define __NR_poll 1068
-__SYSCALL(__NR_poll, sys_poll)
+__SC_WRAP(__NR_poll, sys_poll)
 #define __NR_epoll_wait 1069
-__SYSCALL(__NR_epoll_wait, sys_epoll_wait)
+__SC_WRAP(__NR_epoll_wait, sys_epoll_wait)
 #define __NR_ustat 1070
 __SYSCALL(__NR_ustat, sys_ustat)
 #define __NR_vfork 1071
@@ -871,12 +870,12 @@ __SYSCALL(__NR_recv, sys_recv)
 #define __NR_send 1074
 __SYSCALL(__NR_send, sys_send)
 #define __NR_bdflush 1075
-__SYSCALL(__NR_bdflush, sys_bdflush)
+__SC_WRAP(__NR_bdflush, sys_bdflush)
 #define __NR_umount 1076
-__SYSCALL(__NR_umount, sys_oldumount)
+__SC_WRAP(__NR_umount, sys_oldumount)
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __NR_uselib 1077
-__SYSCALL(__NR_uselib, sys_uselib)
+__SC_WRAP(__NR_uselib, sys_uselib)
 #define __NR__sysctl 1078
 __SYSCALL(__NR__sysctl, sys_sysctl)
 
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:36 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:36 +0300
Subject: [PATCH 07/23] 32-bit ABI: introduce ARCH_32BIT_OFF_T config option
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-8-git-send-email-ynorov@caviumnetworks.com>

All new 32-bit architectures should have 64-bit off_t type, but existing
architectures has 32-bit ones.

To handle it, new config option is added to arch/Kconfig that defaults
ARCH_32BIT_OFF_T to be disabled for non-64 bit architectures. All existing
32-bit architectures enable it explicitly here.

New option affects force_o_largefile() behaviour. Namely, if off_t is
64-bits long, we have no reason to reject user to open big files.

Note that even if architectures has only 64-bit off_t in the kernel
(arc, c6x, h8300, hexagon, metag, nios2, openrisc, tile32 and unicore32),
a libc may use 32-bit off_t, and therefore want to limit the file size
to 4GB unless specified differently in the open flags.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/Kconfig            | 4 ++++
 arch/arc/Kconfig        | 1 +
 arch/arm/Kconfig        | 1 +
 arch/blackfin/Kconfig   | 1 +
 arch/cris/Kconfig       | 1 +
 arch/frv/Kconfig        | 1 +
 arch/h8300/Kconfig      | 1 +
 arch/hexagon/Kconfig    | 1 +
 arch/m32r/Kconfig       | 1 +
 arch/m68k/Kconfig       | 1 +
 arch/metag/Kconfig      | 1 +
 arch/microblaze/Kconfig | 1 +
 arch/mips/Kconfig       | 1 +
 arch/mn10300/Kconfig    | 1 +
 arch/nios2/Kconfig      | 1 +
 arch/openrisc/Kconfig   | 1 +
 arch/parisc/Kconfig     | 1 +
 arch/powerpc/Kconfig    | 1 +
 arch/score/Kconfig      | 1 +
 arch/sh/Kconfig         | 1 +
 arch/sparc/Kconfig      | 1 +
 arch/tile/Kconfig       | 1 +
 arch/unicore32/Kconfig  | 1 +
 arch/x86/Kconfig        | 1 +
 arch/x86/um/Kconfig     | 1 +
 arch/xtensa/Kconfig     | 1 +
 include/linux/fcntl.h   | 2 +-
 27 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 92fcbd4..a2b7cf3 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -230,6 +230,10 @@ config ARCH_THREAD_INFO_ALLOCATOR
 config ARCH_WANTS_DYNAMIC_TASK_STRUCT
 	bool
 
+config ARCH_32BIT_OFF_T
+	bool
+	depends on !64BIT
+
 config HAVE_REGS_AND_STACK_ACCESS_API
 	bool
 	help
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index a876743..13f66cc 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -9,6 +9,7 @@
 config ARC
 	def_bool y
 	select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC
+	select ARCH_32BIT_OFF_T
 	select BUILDTIME_EXTABLE_SORT
 	select COMMON_CLK
 	select CLONE_BACKWARDS
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index cdfa6c2..efe3ca2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1,6 +1,7 @@
 config ARM
 	bool
 	default y
+	select ARCH_32BIT_OFF_T
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_ELF_RANDOMIZE
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index a63c122..ef4368e 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -12,6 +12,7 @@ config RWSEM_XCHGADD_ALGORITHM
 
 config BLACKFIN
 	def_bool y
+	select ARCH_32BIT_OFF_T
 	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_DYNAMIC_FTRACE
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index e086f9e..5bc9203 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -50,6 +50,7 @@ config LOCKDEP_SUPPORT
 config CRIS
 	bool
 	default y
+	select ARCH_32BIT_OFF_T
 	select HAVE_IDE
 	select GENERIC_ATOMIC64
 	select HAVE_UID16
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index eefd9a4..2f14904 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -1,6 +1,7 @@
 config FRV
 	bool
 	default y
+	select ARCH_32BIT_OFF_T
 	select HAVE_IDE
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_PERF_EVENTS
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 986ea84..8c221f1 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -1,5 +1,6 @@
 config H8300
         def_bool y
+	select ARCH_32BIT_OFF_T
 	select GENERIC_ATOMIC64
 	select HAVE_UID16
 	select VIRT_TO_BUS
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index 57298e7..df84602 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -3,6 +3,7 @@ comment "Linux Kernel Configuration for Hexagon"
 
 config HEXAGON
 	def_bool y
+	select ARCH_32BIT_OFF_T
 	select HAVE_OPROFILE
 	# Other pending projects/to-do items.
 	# select HAVE_REGS_AND_STACK_ACCESS_API
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index c82b292..7866bca 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -1,6 +1,7 @@
 config M32R
 	bool
 	default y
+	select ARCH_32BIT_OFF_T
 	select HAVE_IDE
 	select HAVE_OPROFILE
 	select INIT_ALL_POSSIBLE
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 498b567..e9897e4 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -1,6 +1,7 @@
 config M68K
 	bool
 	default y
+	select ARCH_32BIT_OFF_T
 	select ARCH_MIGHT_HAVE_PC_PARPORT if ISA
 	select HAVE_IDE
 	select HAVE_AOUT if MMU
diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig
index a0fa88d..5b7620a 100644
--- a/arch/metag/Kconfig
+++ b/arch/metag/Kconfig
@@ -1,5 +1,6 @@
 config METAG
 	def_bool y
+	select ARCH_32BIT_OFF_T
 	select EMBEDDED
 	select GENERIC_ATOMIC64
 	select GENERIC_CLOCKEVENTS
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 3d793b5..bdb0f83 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -1,5 +1,6 @@
 config MICROBLAZE
 	def_bool y
+	select ARCH_32BIT_OFF_T
 	select ARCH_HAS_GCOV_PROFILE_ALL
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_WANT_IPC_PARSE_VERSION
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 2018c2b..079a6d2 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1,6 +1,7 @@
 config MIPS
 	bool
 	default y
+	select ARCH_32BIT_OFF_T if !64BIT
 	select ARCH_SUPPORTS_UPROBES
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_MIGHT_HAVE_PC_SERIO
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index 06ddb55..bc1aae5 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -1,5 +1,6 @@
 config MN10300
 	def_bool y
+	select ARCH_32BIT_OFF_T
 	select HAVE_OPROFILE
 	select HAVE_UID16
 	select GENERIC_IRQ_SHOW
diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig
index 4375554..a38fc38 100644
--- a/arch/nios2/Kconfig
+++ b/arch/nios2/Kconfig
@@ -1,5 +1,6 @@
 config NIOS2
 	def_bool y
+	select ARCH_32BIT_OFF_T
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select CLKSRC_OF
 	select GENERIC_ATOMIC64
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index e118c02..0271714 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -5,6 +5,7 @@
 
 config OPENRISC
 	def_bool y
+	select ARCH_32BIT_OFF_T
 	select OF
 	select OF_EARLY_FLATTREE
 	select IRQ_DOMAIN
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 88cfaa8..affad75 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -1,5 +1,6 @@
 config PARISC
 	def_bool y
+	select ARCH_32BIT_OFF_T if !64BIT
 	select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select HAVE_IDE
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 7cd32c0..2c7a795 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -85,6 +85,7 @@ config ARCH_HAS_DMA_SET_COHERENT_MASK
 config PPC
 	bool
 	default y
+	select ARCH_32BIT_OFF_T if PPC32
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select BINFMT_ELF
diff --git a/arch/score/Kconfig b/arch/score/Kconfig
index 366e1b5..bc7bc7a 100644
--- a/arch/score/Kconfig
+++ b/arch/score/Kconfig
@@ -2,6 +2,7 @@ menu "Machine selection"
 
 config SCORE
        def_bool y
+       select ARCH_32BIT_OFF_T
        select GENERIC_IRQ_SHOW
        select GENERIC_IOMAP
        select GENERIC_ATOMIC64
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 7ed20fc..2438390 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -52,6 +52,7 @@ config SUPERH
 
 config SUPERH32
 	def_bool ARCH = "sh"
+	select ARCH_32BIT_OFF_T
 	select HAVE_KPROBES
 	select HAVE_KRETPROBES
 	select HAVE_IOREMAP_PROT if MMU && !X2TLB
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 57ffaf2..c88b82d 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -45,6 +45,7 @@ config SPARC
 
 config SPARC32
 	def_bool !64BIT
+	select ARCH_32BIT_OFF_T
 	select GENERIC_ATOMIC64
 	select CLZ_TAB
 	select HAVE_UID16
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 8171930..f9d61e7 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -3,6 +3,7 @@
 
 config TILE
 	def_bool y
+	select ARCH_32BIT_OFF_T if !64BIT
 	select HAVE_PERF_EVENTS
 	select USE_PMC if PERF_EVENTS
 	select HAVE_DMA_API_DEBUG
diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
index e5602ee..b995104 100644
--- a/arch/unicore32/Kconfig
+++ b/arch/unicore32/Kconfig
@@ -1,6 +1,7 @@
 config UNICORE32
 	def_bool y
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
+	select ARCH_32BIT_OFF_T
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select HAVE_MEMBLOCK
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 2dc18605..3628b14 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -20,6 +20,7 @@ config X86
 	select ACPI_LEGACY_TABLES_LOOKUP	if ACPI
 	select ACPI_SYSTEM_POWER_STATES_SUPPORT	if ACPI
 	select ANON_INODES
+	select ARCH_32BIT_OFF_T			if X86_32
 	select ARCH_CLOCKSOURCE_DATA
 	select ARCH_DISCARD_MEMBLOCK
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index ed56a1c..8436bcd 100644
--- a/arch/x86/um/Kconfig
+++ b/arch/x86/um/Kconfig
@@ -21,6 +21,7 @@ config 64BIT
 config X86_32
 	def_bool !64BIT
 	select HAVE_AOUT
+	select ARCH_32BIT_OFF_T
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select MODULES_USE_ELF_REL
 	select CLONE_BACKWARDS
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index e832d3e..b68de31 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -3,6 +3,7 @@ config ZONE_DMA
 
 config XTENSA
 	def_bool y
+	select ARCH_32BIT_OFF_T
 	select ARCH_WANT_FRAME_POINTERS
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index 76ce329..46960a1 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -5,7 +5,7 @@
 
 
 #ifndef force_o_largefile
-#define force_o_largefile() (BITS_PER_LONG != 32)
+#define force_o_largefile() (!IS_ENABLED(CONFIG_ARCH_32BIT_OFF_T))
 #endif
 
 #if BITS_PER_LONG == 32
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:44 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:44 +0300
Subject: [PATCH 15/23] arm64: introduce binfmt_elf32.c
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-16-git-send-email-ynorov@caviumnetworks.com>

As we support more than one compat formats, it looks more reasonable
to not use fs/compat_binfmt.c. Custom binfmt_elf32.c allows to move aarch32
specific definitions there and make code more maintainable and readable.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/Kconfig               |  1 -
 arch/arm64/include/asm/elf.h     | 24 ------------------------
 arch/arm64/include/asm/hwcap.h   |  2 --
 arch/arm64/kernel/Makefile       |  2 +-
 arch/arm64/kernel/binfmt_elf32.c | 33 +++++++++++++++++++++++++++++++++
 5 files changed, 34 insertions(+), 28 deletions(-)
 create mode 100644 arch/arm64/kernel/binfmt_elf32.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index ede9b2e..0bb7adc 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -932,7 +932,6 @@ config AARCH32_EL0
 	bool "Kernel support for 32-bit EL0"
 	def_bool y
 	depends on ARM64_4K_PAGES || EXPERT
-	select COMPAT_BINFMT_ELF
 	select HAVE_UID16
 	select OLD_SIGSUSPEND3
 	select COMPAT_OLD_SIGACTION
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index e18bb8a..7a39683 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -166,12 +166,6 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 
 #ifdef CONFIG_COMPAT
 
-#ifdef __AARCH64EB__
-#define COMPAT_ELF_PLATFORM		("v8b")
-#else
-#define COMPAT_ELF_PLATFORM		("v8l")
-#endif
-
 #define COMPAT_ELF_ET_DYN_BASE		(2 * TASK_SIZE_32 / 3)
 
 /* AArch32 registers. */
@@ -179,24 +173,6 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 typedef unsigned int			compat_elf_greg_t;
 typedef compat_elf_greg_t		compat_elf_gregset_t[COMPAT_ELF_NGREG];
 
-/* AArch32 EABI. */
-#define EF_ARM_EABI_MASK		0xff000000
-#define compat_elf_check_arch(x)	(((x)->e_machine == EM_ARM) && \
-					 ((x)->e_flags & EF_ARM_EABI_MASK))
-
-#define compat_start_thread		compat_start_thread
-#define COMPAT_SET_PERSONALITY(ex)		\
-do {						\
-	clear_thread_flag(TIF_32BIT_AARCH64);	\
-	set_thread_flag(TIF_32BIT);		\
-} while (0)
-
-#define COMPAT_ARCH_DLINFO
-extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
-				      int uses_interp);
-#define compat_arch_setup_additional_pages \
-					aarch32_setup_vectors_page
-
 #endif /* CONFIG_COMPAT */
 
 #endif /* !__ASSEMBLY__ */
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index 2c7fc5d..99dfd92 100644
--- a/arch/arm64/include/asm/hwcap.h
+++ b/arch/arm64/include/asm/hwcap.h
@@ -47,8 +47,6 @@
 #define ELF_HWCAP		(elf_hwcap)
 
 #ifdef CONFIG_AARCH32_EL0
-#define COMPAT_ELF_HWCAP	(compat_elf_hwcap)
-#define COMPAT_ELF_HWCAP2	(compat_elf_hwcap2)
 extern unsigned int compat_elf_hwcap, compat_elf_hwcap2;
 #endif
 
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 75dd250..6bc9738 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -27,7 +27,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 
 arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
-					   ../../arm/kernel/opcodes.o
+					   ../../arm/kernel/opcodes.o binfmt_elf32.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
diff --git a/arch/arm64/kernel/binfmt_elf32.c b/arch/arm64/kernel/binfmt_elf32.c
new file mode 100644
index 0000000..5487872
--- /dev/null
+++ b/arch/arm64/kernel/binfmt_elf32.c
@@ -0,0 +1,33 @@
+/*
+ * Support for AArch32 Linux ELF binaries.
+ */
+
+/* AArch32 EABI. */
+#define EF_ARM_EABI_MASK		0xff000000
+#define compat_elf_check_arch(x)	(((x)->e_machine == EM_ARM) && \
+					 ((x)->e_flags & EF_ARM_EABI_MASK))
+
+#define compat_start_thread		compat_start_thread
+#define COMPAT_SET_PERSONALITY(ex)		\
+do {						\
+	clear_thread_flag(TIF_32BIT_AARCH64);	\
+	set_thread_flag(TIF_32BIT);		\
+} while (0)
+
+#define COMPAT_ARCH_DLINFO
+#define COMPAT_ELF_HWCAP		(compat_elf_hwcap)
+#define COMPAT_ELF_HWCAP2		(compat_elf_hwcap2)
+
+#ifdef __AARCH64EB__
+#define COMPAT_ELF_PLATFORM		("v8b")
+#else
+#define COMPAT_ELF_PLATFORM		("v8l")
+#endif
+
+#define compat_arch_setup_additional_pages \
+					aarch32_setup_vectors_page
+struct linux_binprm;
+extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
+				      int uses_interp);
+
+#include "../../../fs/compat_binfmt_elf.c"
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:45 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:45 +0300
Subject: [PATCH 16/23] arm64: ilp32: introduce binfmt_ilp32.c
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-17-git-send-email-ynorov@caviumnetworks.com>

to handle ILP32 binaries

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/kernel/Makefile       |  1 +
 arch/arm64/kernel/binfmt_ilp32.c | 91 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 92 insertions(+)
 create mode 100644 arch/arm64/kernel/binfmt_ilp32.c

diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 6bc9738..9dfdf86 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -28,6 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
 					   ../../arm/kernel/opcodes.o binfmt_elf32.o
+arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
new file mode 100644
index 0000000..a934fd4
--- /dev/null
+++ b/arch/arm64/kernel/binfmt_ilp32.c
@@ -0,0 +1,91 @@
+/*
+ * Support for ILP32 Linux/aarch64 ELF binaries.
+ */
+
+#include <linux/elfcore-compat.h>
+#include <linux/time.h>
+
+#undef	ELF_CLASS
+#define ELF_CLASS	ELFCLASS32
+
+#undef	elfhdr
+#undef	elf_phdr
+#undef	elf_shdr
+#undef	elf_note
+#undef	elf_addr_t
+#define elfhdr		elf32_hdr
+#define elf_phdr	elf32_phdr
+#define elf_shdr	elf32_shdr
+#define elf_note	elf32_note
+#define elf_addr_t	Elf32_Addr
+
+/*
+ * Some data types as stored in coredump.
+ */
+#define user_long_t		compat_long_t
+#define user_siginfo_t		compat_siginfo_t
+#define copy_siginfo_to_user	copy_siginfo_to_user32
+
+/*
+ * The machine-dependent core note format types are defined in elfcore-compat.h,
+ * which requires asm/elf.h to define compat_elf_gregset_t et al.
+ */
+#define elf_prstatus	compat_elf_prstatus
+#define elf_prpsinfo	compat_elf_prpsinfo
+
+/*
+ * Compat version of cputime_to_compat_timeval, perhaps this
+ * should be an inline in <linux/compat.h>.
+ */
+static void cputime_to_compat_timeval(const cputime_t cputime,
+				      struct compat_timeval *value)
+{
+	struct timeval tv;
+	cputime_to_timeval(cputime, &tv);
+	value->tv_sec = tv.tv_sec;
+	value->tv_usec = tv.tv_usec;
+}
+
+#undef cputime_to_timeval
+#define cputime_to_timeval cputime_to_compat_timeval
+
+/* AARCH64 ILP32 EABI. */
+#undef elf_check_arch
+#define elf_check_arch(x)		(((x)->e_machine == EM_AARCH64)	\
+					&& (x)->e_ident[EI_CLASS] == ELFCLASS32)
+
+#undef SET_PERSONALITY
+#define SET_PERSONALITY(ex)						\
+do {									\
+	set_thread_flag(TIF_32BIT_AARCH64);				\
+	clear_thread_flag(TIF_32BIT);					\
+} while (0)
+
+#undef ARCH_DLINFO
+#define ARCH_DLINFO							\
+do {									\
+	NEW_AUX_ENT(AT_SYSINFO_EHDR,					\
+		    (elf_addr_t)(long)current->mm->context.vdso);	\
+} while (0)
+
+#ifdef __AARCH64EB__
+#define COMPAT_ELF_PLATFORM		("aarch64_be:ilp32")
+#else
+#define COMPAT_ELF_PLATFORM		("aarch64:ilp32")
+#endif
+
+#undef ELF_HWCAP
+#undef ELF_HWCAP2
+#define ELF_HWCAP			((u32) elf_hwcap)
+#define ELF_HWCAP2			((u32) (elf_hwcap >> 32))
+
+/*
+ * Rename a few of the symbols that binfmt_elf.c will define.
+ * These are all local so the names don't really matter, but it
+ * might make some debugging less confusing not to duplicate them.
+ */
+#define elf_format		compat_elf_format
+#define init_elf_binfmt		init_compat_elf_binfmt
+#define exit_elf_binfmt		exit_compat_elf_binfmt
+
+#include "../../../fs/binfmt_elf.c"
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:38 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:38 +0300
Subject: [PATCH 09/23] arm64: ensure the kernel is compiled for LP64
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-10-git-send-email-ynorov@caviumnetworks.com>

From: Andrew Pinski <apinski at cavium.com>

The kernel needs to be compiled as a LP64 binary for ARM64, even when
using a compiler that defaults to code-generation for the ILP32 ABI.
Consequently, we need to explicitly pass '-mabi=lp64' (supported on
gcc-4.9 and newer).

Signed-off-by: Andrew Pinski <Andrew.Pinski at caviumnetworks.com>
Signed-off-by: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
Signed-off-by: Christoph Muellner <christoph.muellner at theobroma-systems.com>
Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
Reviewed-by: David Daney <ddaney at caviumnetworks.com>
---
 arch/arm64/Makefile | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 354d754..29ebf23 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -35,14 +35,19 @@ KBUILD_CFLAGS	+= -fno-asynchronous-unwind-tables
 KBUILD_CFLAGS	+= $(call cc-option, -mpc-relative-literal-loads)
 KBUILD_AFLAGS	+= $(lseinstr)
 
+KBUILD_CFLAGS	+= $(call cc-option,-mabi=lp64)
+KBUILD_AFLAGS	+= $(call cc-option,-mabi=lp64)
+
 ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
 KBUILD_CPPFLAGS	+= -mbig-endian
 AS		+= -EB
 LD		+= -EB
+LDFLAGS		+= -maarch64linuxb
 else
 KBUILD_CPPFLAGS	+= -mlittle-endian
 AS		+= -EL
 LD		+= -EL
+LDFLAGS		+= -maarch64linux
 endif
 
 CHECKFLAGS	+= -D__aarch64__
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:40 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:40 +0300
Subject: [PATCH 11/23] arm64:uapi: set __BITS_PER_LONG correctly for ILP32 and
 LP64
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-12-git-send-email-ynorov@caviumnetworks.com>

From: Andrew Pinski <apinski at cavium.com>

Define __BITS_PER_LONG depending on the ABI used (i.e. check whether
__ILP32__ or __LP64__ is defined).  This is necessary for glibc to
determine the appropriate type definitions for the system call interface.

Signed-off-by: Andrew Pinski <apinski at cavium.com>
Signed-off-by: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
Signed-off-by: Christoph Muellner <christoph.muellner at theobroma-systems.com>
Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
Reviewed-by: David Daney <ddaney at caviumnetworks.com>
---
 arch/arm64/include/uapi/asm/bitsperlong.h | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/uapi/asm/bitsperlong.h b/arch/arm64/include/uapi/asm/bitsperlong.h
index fce9c29..4265243 100644
--- a/arch/arm64/include/uapi/asm/bitsperlong.h
+++ b/arch/arm64/include/uapi/asm/bitsperlong.h
@@ -16,7 +16,14 @@
 #ifndef __ASM_BITSPERLONG_H
 #define __ASM_BITSPERLONG_H
 
-#define __BITS_PER_LONG 64
+#if defined(__LP64__)
+/* Assuming __LP64__ will be defined for native ELF64's and not for ILP32. */
+#  define __BITS_PER_LONG 64
+#elif defined(__ILP32__)
+#  define __BITS_PER_LONG 32
+#else
+#  error "Neither LP64 nor ILP32: unsupported ABI in asm/bitsperlong.h"
+#endif
 
 #include <asm-generic/bitsperlong.h>
 
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:37 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:37 +0300
Subject: [PATCH 08/23] arm64: ilp32: add documentation on the ILP32 ABI for
 ARM64
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-9-git-send-email-ynorov@caviumnetworks.com>

Based on Andrew Pinski's patch-series.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 Documentation/arm64/ilp32.txt | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 Documentation/arm64/ilp32.txt

diff --git a/Documentation/arm64/ilp32.txt b/Documentation/arm64/ilp32.txt
new file mode 100644
index 0000000..8e74d67
--- /dev/null
+++ b/Documentation/arm64/ilp32.txt
@@ -0,0 +1,25 @@
+ILP32 AARCH64 SYSCALL ABI
+=========================
+
+This document describes the ILP32 syscall ABI and where it differs
+from the generic compat linux syscall interface.
+
+Syscalls which normally would pass 64bit values as two arguments;
+now pass the 64bit value as one argument. Next syscalls are affected:
+fadvise64_64,
+fallocate,
+ftruncate,
+lookup_dcookie,
+pread64,
+pwrite64,
+readahead,
+shmat,
+sync_file_range,
+truncate,
+lseek,
+mmap
+
+struct rt_sigframe is redefined and contains struct compat_siginfo,
+as compat syscalls expects, and struct ilp32_sigframe, to handle
+AARCH64 register set and 32-bit userspace register representation.
+
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:46 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:46 +0300
Subject: [PATCH 17/23] arm64: ptrace: handle ptrace_request differently for
 aarch32 and ilp32
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-18-git-send-email-ynorov@caviumnetworks.com>

Here new aarch32 ptrace syscall handler is introsuced to avoid run-time
detection of the task type.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/include/asm/unistd32.h |  2 +-
 arch/arm64/kernel/ptrace.c        | 50 ++++++++++++++++++++++++++++++++++++++-
 arch/arm64/kernel/sys32.c         |  1 +
 include/linux/ptrace.h            |  6 +++++
 kernel/ptrace.c                   | 10 ++++----
 5 files changed, 62 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index 5b925b7..f57bbe3 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -74,7 +74,7 @@ __SYSCALL(__NR_getuid, sys_getuid16)
 			/* 25 was sys_stime */
 __SYSCALL(25, sys_ni_syscall)
 #define __NR_ptrace 26
-__SYSCALL(__NR_ptrace, compat_sys_ptrace)
+__SYSCALL(__NR_ptrace, compat_sys_aarch32_ptrace)
 			/* 27 was sys_alarm */
 __SYSCALL(27, sys_ni_syscall)
 			/* 28 was sys_fstat */
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 38a09338..a861105 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -29,6 +29,7 @@
 #include <linux/user.h>
 #include <linux/seccomp.h>
 #include <linux/security.h>
+#include <linux/syscalls.h>
 #include <linux/init.h>
 #include <linux/signal.h>
 #include <linux/uaccess.h>
@@ -1114,7 +1115,7 @@ static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num,
 }
 #endif	/* CONFIG_HAVE_HW_BREAKPOINT */
 
-long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+static long compat_a32_ptrace(struct task_struct *child, compat_long_t request,
 			compat_ulong_t caddr, compat_ulong_t cdata)
 {
 	unsigned long addr = caddr;
@@ -1191,8 +1192,55 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 
 	return ret;
 }
+
+COMPAT_SYSCALL_DEFINE4(aarch32_ptrace, compat_long_t, request, compat_long_t, pid,
+		       compat_long_t, addr, compat_long_t, data)
+{
+	struct task_struct *child;
+	long ret;
+
+	if (request == PTRACE_TRACEME) {
+		ret = ptrace_traceme();
+		goto out;
+	}
+
+	child = ptrace_get_task_struct(pid);
+	if (IS_ERR(child)) {
+		ret = PTR_ERR(child);
+		goto out;
+	}
+
+	if (request == PTRACE_ATTACH || request == PTRACE_SEIZE) {
+		ret = ptrace_attach(child, request, addr, data);
+		goto out_put_task_struct;
+	}
+
+	ret = ptrace_check_attach(child, request == PTRACE_KILL ||
+				  request == PTRACE_INTERRUPT);
+	if (!ret) {
+		ret = compat_a32_ptrace(child, request, addr, data);
+		if (ret || request != PTRACE_DETACH)
+			ptrace_unfreeze_traced(child);
+	}
+
+ out_put_task_struct:
+	put_task_struct(child);
+ out:
+	return ret;
+}
+
 #endif /* CONFIG_AARCH32_EL0 */
 
+#ifdef CONFIG_COMPAT
+
+long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+			compat_ulong_t caddr, compat_ulong_t cdata)
+{
+	return compat_ptrace_request(child, request, caddr, cdata);
+}
+
+#endif /* CONFIG_COMPAT */
+
 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 {
 #ifdef CONFIG_AARCH32_EL0
diff --git a/arch/arm64/kernel/sys32.c b/arch/arm64/kernel/sys32.c
index a40b134..3752443 100644
--- a/arch/arm64/kernel/sys32.c
+++ b/arch/arm64/kernel/sys32.c
@@ -38,6 +38,7 @@ asmlinkage long compat_sys_fadvise64_64_wrapper(void);
 asmlinkage long compat_sys_sync_file_range2_wrapper(void);
 asmlinkage long compat_sys_fallocate_wrapper(void);
 asmlinkage long compat_sys_mmap2_wrapper(void);
+asmlinkage long compat_sys_aarch32_ptrace(void);
 
 #undef __SYSCALL
 #define __SYSCALL(nr, sym)	[nr] = sym,
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 504c98a..75887a0 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -97,6 +97,12 @@ int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
 			    unsigned long data);
 int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
 			    unsigned long data);
+int ptrace_traceme(void);
+struct task_struct *ptrace_get_task_struct(pid_t pid);
+int ptrace_attach(struct task_struct *task, long request,
+			 unsigned long addr, unsigned long flags);
+int ptrace_check_attach(struct task_struct *child, bool ignore_state);
+void ptrace_unfreeze_traced(struct task_struct *task);
 
 /**
  * ptrace_parent - return the task that is tracing the given task
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index d49bfa1..cadf24c 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -136,7 +136,7 @@ static bool ptrace_freeze_traced(struct task_struct *task)
 	return ret;
 }
 
-static void ptrace_unfreeze_traced(struct task_struct *task)
+void ptrace_unfreeze_traced(struct task_struct *task)
 {
 	if (task->state != __TASK_TRACED)
 		return;
@@ -168,7 +168,7 @@ static void ptrace_unfreeze_traced(struct task_struct *task)
  * RETURNS:
  * 0 on success, -ESRCH if %child is not ready.
  */
-static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
+int ptrace_check_attach(struct task_struct *child, bool ignore_state)
 {
 	int ret = -ESRCH;
 
@@ -292,7 +292,7 @@ bool ptrace_may_access(struct task_struct *task, unsigned int mode)
 	return !err;
 }
 
-static int ptrace_attach(struct task_struct *task, long request,
+int ptrace_attach(struct task_struct *task, long request,
 			 unsigned long addr,
 			 unsigned long flags)
 {
@@ -406,7 +406,7 @@ out:
  * Performs checks and sets PT_PTRACED.
  * Should be used by all ptrace implementations for PTRACE_TRACEME.
  */
-static int ptrace_traceme(void)
+ int ptrace_traceme(void)
 {
 	int ret = -EPERM;
 
@@ -1056,7 +1056,7 @@ int ptrace_request(struct task_struct *child, long request,
 	return ret;
 }
 
-static struct task_struct *ptrace_get_task_struct(pid_t pid)
+struct task_struct *ptrace_get_task_struct(pid_t pid)
 {
 	struct task_struct *child;
 
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:43 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:43 +0300
Subject: [PATCH 14/23] arm64: ilp32: add is_ilp32_compat_{task,
 thread} and TIF_32BIT_AARCH64
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-15-git-send-email-ynorov@caviumnetworks.com>

ILP32 tasks are needed to be distinguished from lp64 and aarch32.
This patch adds helper functions is_ilp32_compat_{task,thread} and
thread flag TIF_32BIT_AARCH64 to address it. This is a preparation
for following patches in ilp32 patchset.

For consistency, SET_PERSONALITY is changed here accordingly.

Signed-off-by: Andrew Pinski <Andrew.Pinski at caviumnetworks.com>
Signed-off-by: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
Signed-off-by: Christoph Muellner <christoph.muellner at theobroma-systems.com>
Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
Reviewed-by: David Daney <ddaney at caviumnetworks.com>
---
 arch/arm64/include/asm/elf.h         | 13 +++++++++++--
 arch/arm64/include/asm/is_compat.h   | 28 +++++++++++++++++++++++++++-
 arch/arm64/include/asm/thread_info.h |  2 ++
 3 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index b5437c5..e18bb8a 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -142,7 +142,11 @@ typedef struct user_fpsimd_state elf_fpregset_t;
  */
 #define ELF_PLAT_INIT(_r, load_addr)	(_r)->regs[0] = 0
 
-#define SET_PERSONALITY(ex)		clear_thread_flag(TIF_32BIT);
+#define SET_PERSONALITY(ex)		\
+do {						\
+	clear_thread_flag(TIF_32BIT_AARCH64);	\
+	clear_thread_flag(TIF_32BIT);		\
+} while (0)
 
 #define ARCH_DLINFO							\
 do {									\
@@ -181,7 +185,12 @@ typedef compat_elf_greg_t		compat_elf_gregset_t[COMPAT_ELF_NGREG];
 					 ((x)->e_flags & EF_ARM_EABI_MASK))
 
 #define compat_start_thread		compat_start_thread
-#define COMPAT_SET_PERSONALITY(ex)	set_thread_flag(TIF_32BIT);
+#define COMPAT_SET_PERSONALITY(ex)		\
+do {						\
+	clear_thread_flag(TIF_32BIT_AARCH64);	\
+	set_thread_flag(TIF_32BIT);		\
+} while (0)
+
 #define COMPAT_ARCH_DLINFO
 extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
 				      int uses_interp);
diff --git a/arch/arm64/include/asm/is_compat.h b/arch/arm64/include/asm/is_compat.h
index 6139b5a..55134cf 100644
--- a/arch/arm64/include/asm/is_compat.h
+++ b/arch/arm64/include/asm/is_compat.h
@@ -45,11 +45,37 @@ static inline int is_a32_compat_thread(struct thread_info *thread)
 
 #endif /* CONFIG_AARCH32_EL0 */
 
+#ifdef CONFIG_ARM64_ILP32
+
+static inline int is_ilp32_compat_task(void)
+{
+	return test_thread_flag(TIF_32BIT_AARCH64);
+}
+
+static inline int is_ilp32_compat_thread(struct thread_info *thread)
+{
+	return test_ti_thread_flag(thread, TIF_32BIT_AARCH64);
+}
+
+#else
+
+static inline int is_ilp32_compat_task(void)
+{
+	return 0;
+}
+
+static inline int is_ilp32_compat_thread(struct thread_info *thread)
+{
+	return 0;
+}
+
+#endif /* CONFIG_ARM64_ILP32 */
+
 #ifdef CONFIG_COMPAT
 
 static inline int is_compat_task(void)
 {
-	return is_a32_compat_task();
+	return is_a32_compat_task() || is_ilp32_compat_task();
 }
 
 #endif /* CONFIG_COMPAT */
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 4daa559..8802645 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -119,6 +119,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_RESTORE_SIGMASK	20
 #define TIF_SINGLESTEP		21
 #define TIF_32BIT		22	/* AARCH32 process */
+#define TIF_32BIT_AARCH64	23	/* 32 bit process on AArch64(ILP32) */
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
@@ -130,6 +131,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_32BIT		(1 << TIF_32BIT)
+#define _TIF_32BIT_AARCH64	(1 << TIF_32BIT_AARCH64)
 
 #define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
 				 _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE)
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:39 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:39 +0300
Subject: [PATCH 10/23] arm64: rename COMPAT to AARCH32_EL0 in Kconfig
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-11-git-send-email-ynorov@caviumnetworks.com>

From: Andrew Pinski <apinski at cavium.com>

In this patchset  ILP32 ABI support is added. Additionally to AARCH32,
which is binary-compatible with ARM, ILP32 is (mostly) ABI-compatible.

>From now, AARCH32_EL0 (former COMPAT) config option means the support of
AARCH32 userspace, ARM64_ILP32 - support of ILP32 ABI (see next patches),
and COMPAT indicates that one of them, or both, is enabled.

Where needed, CONFIG_COMPAT is changed over to use CONFIG_AARCH32_EL0 instead

Reviewed-by: David Daney <ddaney at caviumnetworks.com>
Signed-off-by: Andrew Pinski <Andrew.Pinski at caviumnetworks.com>
Signed-off-by: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
Signed-off-by: Christoph Muellner <christoph.muellner at theobroma-systems.com>
Signed-off-by: Bamvor Jian Zhang <bamvor.zhangjian at linaro.org>
Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/Kconfig                   | 9 +++++++--
 arch/arm64/include/asm/fpsimd.h      | 2 +-
 arch/arm64/include/asm/hwcap.h       | 4 ++--
 arch/arm64/include/asm/processor.h   | 6 +++---
 arch/arm64/include/asm/ptrace.h      | 2 +-
 arch/arm64/include/asm/signal32.h    | 6 ++++--
 arch/arm64/include/asm/unistd.h      | 2 +-
 arch/arm64/kernel/Makefile           | 2 +-
 arch/arm64/kernel/asm-offsets.c      | 2 +-
 arch/arm64/kernel/cpufeature.c       | 8 ++++----
 arch/arm64/kernel/cpuinfo.c          | 4 ++--
 arch/arm64/kernel/entry.S            | 6 +++---
 arch/arm64/kernel/head.S             | 2 +-
 arch/arm64/kernel/ptrace.c           | 8 ++++----
 arch/arm64/kernel/traps.c            | 2 +-
 arch/arm64/kernel/vdso.c             | 4 ++--
 drivers/clocksource/arm_arch_timer.c | 2 +-
 17 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 4f43622..ede9b2e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -370,7 +370,7 @@ config ARM64_ERRATUM_834220
 
 config ARM64_ERRATUM_845719
 	bool "Cortex-A53: 845719: a load might read incorrect data"
-	depends on COMPAT
+	depends on AARCH32_EL0
 	default y
 	help
 	  This option adds an alternative code sequence to work around ARM
@@ -655,7 +655,7 @@ config FORCE_MAX_ZONEORDER
 
 menuconfig ARMV8_DEPRECATED
 	bool "Emulate deprecated/obsolete ARMv8 instructions"
-	depends on COMPAT
+	depends on AARCH32_EL0
 	help
 	  Legacy software support may require certain instructions
 	  that have been deprecated or obsoleted in the architecture.
@@ -925,7 +925,12 @@ menu "Userspace binary formats"
 source "fs/Kconfig.binfmt"
 
 config COMPAT
+	bool
+	depends on AARCH32_EL0
+
+config AARCH32_EL0
 	bool "Kernel support for 32-bit EL0"
+	def_bool y
 	depends on ARM64_4K_PAGES || EXPERT
 	select COMPAT_BINFMT_ELF
 	select HAVE_UID16
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 50f559f..63b19f1 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -52,7 +52,7 @@ struct fpsimd_partial_state {
 };
 
 
-#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+#if defined(__KERNEL__) && defined(CONFIG_AARCH32_EL0)
 /* Masks for extracting the FPSR and FPCR from the FPSCR */
 #define VFP_FPSCR_STAT_MASK	0xf800009f
 #define VFP_FPSCR_CTRL_MASK	0x07f79f00
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index 400b80b..2c7fc5d 100644
--- a/arch/arm64/include/asm/hwcap.h
+++ b/arch/arm64/include/asm/hwcap.h
@@ -46,7 +46,7 @@
  */
 #define ELF_HWCAP		(elf_hwcap)
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 #define COMPAT_ELF_HWCAP	(compat_elf_hwcap)
 #define COMPAT_ELF_HWCAP2	(compat_elf_hwcap2)
 extern unsigned int compat_elf_hwcap, compat_elf_hwcap2;
@@ -54,7 +54,7 @@ extern unsigned int compat_elf_hwcap, compat_elf_hwcap2;
 
 enum {
 	CAP_HWCAP = 1,
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	CAP_COMPAT_HWCAP,
 	CAP_COMPAT_HWCAP2,
 #endif
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index cef1cf3..5bbdbb4 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -81,7 +81,7 @@ struct cpu_context {
 struct thread_struct {
 	struct cpu_context	cpu_context;	/* cpu context */
 	unsigned long		tp_value;	/* TLS register */
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	unsigned long		tp2_value;
 #endif
 	struct fpsimd_state	fpsimd_state;
@@ -90,7 +90,7 @@ struct thread_struct {
 	struct debug_info	debug;		/* debugging */
 };
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 #define task_user_tls(t)						\
 ({									\
 	unsigned long *__tls;						\
@@ -121,7 +121,7 @@ static inline void start_thread(struct pt_regs *regs, unsigned long pc,
 	regs->sp = sp;
 }
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
 				       unsigned long sp)
 {
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index a307eb6..4c730c3 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -121,7 +121,7 @@ struct pt_regs {
 
 #define arch_has_single_step()	(1)
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 #define compat_thumb_mode(regs) \
 	(((regs)->pstate & COMPAT_PSR_T_BIT))
 #else
diff --git a/arch/arm64/include/asm/signal32.h b/arch/arm64/include/asm/signal32.h
index eeaa975..e68fcce 100644
--- a/arch/arm64/include/asm/signal32.h
+++ b/arch/arm64/include/asm/signal32.h
@@ -17,7 +17,9 @@
 #define __ASM_SIGNAL32_H
 
 #ifdef __KERNEL__
-#ifdef CONFIG_COMPAT
+
+#ifdef CONFIG_AARCH32_EL0
+
 #include <linux/compat.h>
 
 #define AARCH32_KERN_SIGRET_CODE_OFFSET	0x500
@@ -47,6 +49,6 @@ static inline int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t
 static inline void compat_setup_restart_syscall(struct pt_regs *regs)
 {
 }
-#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_AARCH32_EL0 */
 #endif /* __KERNEL__ */
 #endif /* __ASM_SIGNAL32_H */
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 41e58fe..2971dea 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -13,7 +13,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 #define __ARCH_WANT_COMPAT_SYS_GETDENTS64
 #define __ARCH_WANT_COMPAT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 3793003..75dd250 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -25,7 +25,7 @@ OBJCOPYFLAGS := --prefix-symbols=__efistub_
 $(obj)/%.stub.o: $(obj)/%.o FORCE
 	$(call if_changed,objcopy)
 
-arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
+arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
 					   ../../arm/kernel/opcodes.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 3ae6b31..e229525 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -52,7 +52,7 @@ int main(void)
   DEFINE(S_X7,			offsetof(struct pt_regs, regs[7]));
   DEFINE(S_LR,			offsetof(struct pt_regs, regs[30]));
   DEFINE(S_SP,			offsetof(struct pt_regs, sp));
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
   DEFINE(S_COMPAT_SP,		offsetof(struct pt_regs, compat_sp));
 #endif
   DEFINE(S_PSTATE,		offsetof(struct pt_regs, pstate));
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 943f514..6f77412 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -32,7 +32,7 @@
 unsigned long elf_hwcap __read_mostly;
 EXPORT_SYMBOL_GPL(elf_hwcap);
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 #define COMPAT_ELF_HWCAP_DEFAULT	\
 				(COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\
 				 COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\
@@ -751,7 +751,7 @@ static const struct arm64_cpu_capabilities arm64_hwcaps[] = {
 	HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_FPHP),
 	HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_ASIMD),
 	HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_ASIMDHP),
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL),
 	HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES),
 	HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA1),
@@ -767,7 +767,7 @@ static void __init cap_set_hwcap(const struct arm64_cpu_capabilities *cap)
 	case CAP_HWCAP:
 		elf_hwcap |= cap->hwcap;
 		break;
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	case CAP_COMPAT_HWCAP:
 		compat_elf_hwcap |= (u32)cap->hwcap;
 		break;
@@ -790,7 +790,7 @@ static bool __maybe_unused cpus_have_hwcap(const struct arm64_cpu_capabilities *
 	case CAP_HWCAP:
 		rc = (elf_hwcap & cap->hwcap) != 0;
 		break;
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	case CAP_COMPAT_HWCAP:
 		rc = (compat_elf_hwcap & (u32)cap->hwcap) != 0;
 		break;
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 84c8684..32fb4f3 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -127,7 +127,7 @@ static int c_show(struct seq_file *m, void *v)
 		 */
 		seq_puts(m, "Features\t:");
 		if (personality(current->personality) == PER_LINUX32) {
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 			for (j = 0; compat_hwcap_str[j]; j++)
 				if (compat_elf_hwcap & (1 << j))
 					seq_printf(m, " %s", compat_hwcap_str[j]);
@@ -135,7 +135,7 @@ static int c_show(struct seq_file *m, void *v)
 			for (j = 0; compat_hwcap2_str[j]; j++)
 				if (compat_elf_hwcap2 & (1 << j))
 					seq_printf(m, " %s", compat_hwcap2_str[j]);
-#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_AARCH32_EL0 */
 		} else {
 			for (j = 0; hwcap_str[j]; j++)
 				if (elf_hwcap & (1 << j))
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index ec8bb48..21a0624 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -260,7 +260,7 @@ ENTRY(vectors)
 	ventry	el0_fiq_invalid			// FIQ 64-bit EL0
 	ventry	el0_error_invalid		// Error 64-bit EL0
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	ventry	el0_sync_compat			// Synchronous 32-bit EL0
 	ventry	el0_irq_compat			// IRQ 32-bit EL0
 	ventry	el0_fiq_invalid_compat		// FIQ 32-bit EL0
@@ -300,7 +300,7 @@ el0_error_invalid:
 	inv_entry 0, BAD_ERROR
 ENDPROC(el0_error_invalid)
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 el0_fiq_invalid_compat:
 	inv_entry 0, BAD_FIQ, 32
 ENDPROC(el0_fiq_invalid_compat)
@@ -463,7 +463,7 @@ el0_sync:
 	b.ge	el0_dbg
 	b	el0_inv
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	.align	6
 el0_sync_compat:
 	kernel_entry 0, 32
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 85da0f5..35e70d8 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -608,7 +608,7 @@ CPU_LE(	movk	x0, #0x30d0, lsl #16	)	// Clear EE and E0E on LE systems
 	msr	cptr_el2, x0			// Disable copro. traps to EL2
 1:
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	msr	hstr_el2, xzr			// Disable CP15 traps to EL2
 #endif
 
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 3f6cd5c..aa79e81 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -82,7 +82,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
 		.si_addr	= (void __user *)(bkpt->trigger),
 	};
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	int i;
 
 	if (!is_compat_task())
@@ -657,7 +657,7 @@ static const struct user_regset_view user_aarch64_view = {
 	.regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets)
 };
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 #include <linux/compat.h>
 
 enum compat_regset {
@@ -1192,11 +1192,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 
 	return ret;
 }
-#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_AARCH32_EL0 */
 
 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 {
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	/*
 	 * Core dumping of 32-bit tasks or compat ptrace requests must use the
 	 * user_aarch32_view compatible with arm32. Native ptrace requests on
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index e16ae22..85461e8 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -409,7 +409,7 @@ long compat_arm_syscall(struct pt_regs *regs);
 
 asmlinkage long do_ni_syscall(struct pt_regs *regs)
 {
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	long ret;
 	if (is_compat_task()) {
 		ret = compat_arm_syscall(regs);
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 97bc68f..26352a6 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -49,7 +49,7 @@ static union {
 } vdso_data_store __page_aligned_data;
 struct vdso_data *vdso_data = &vdso_data_store.data;
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 /*
  * Create and map the vectors page for AArch32 tasks.
  */
@@ -107,7 +107,7 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
 
 	return PTR_ERR_OR_ZERO(ret);
 }
-#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_AARCH32_EL0 */
 
 static struct vm_special_mapping vdso_spec[2];
 
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 5152b38..d5e699d 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -321,7 +321,7 @@ static void arch_timer_evtstrm_enable(int divider)
 			| ARCH_TIMER_VIRT_EVT_EN;
 	arch_timer_set_cntkctl(cntkctl);
 	elf_hwcap |= HWCAP_EVTSTRM;
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
 	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
 #endif
 }
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:41 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:41 +0300
Subject: [PATCH 12/23] thread: move thread bits accessors to separated file
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-13-git-send-email-ynorov@caviumnetworks.com>

They may be accessed from low-level code, so isolating is a measure to
avoid circular dependencies in header files.

The exact reason for circular dependency is WARN_ON() macro added by Al
Viro in patch [edd63a27] "set_restore_sigmask() is never called without
SIGPENDING (and never should be)"

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 include/linux/thread_bits.h | 55 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/thread_info.h | 44 +-----------------------------------
 2 files changed, 56 insertions(+), 43 deletions(-)
 create mode 100644 include/linux/thread_bits.h

diff --git a/include/linux/thread_bits.h b/include/linux/thread_bits.h
new file mode 100644
index 0000000..0d05d16
--- /dev/null
+++ b/include/linux/thread_bits.h
@@ -0,0 +1,55 @@
+
+/* thread_bits.h: common low-level thread bits accessors */
+
+#ifndef _LINUX_THREAD_BITS_H
+#define _LINUX_THREAD_BITS_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/bitops.h>
+#include <asm/thread_info.h>
+
+/*
+ * flag set/clear/test wrappers
+ * - pass TIF_xxxx constants to these functions
+ */
+
+static inline void set_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	set_bit(flag, (unsigned long *)&ti->flags);
+}
+
+static inline void clear_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	clear_bit(flag, (unsigned long *)&ti->flags);
+}
+
+static inline int test_and_set_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	return test_and_set_bit(flag, (unsigned long *)&ti->flags);
+}
+
+static inline int test_and_clear_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	return test_and_clear_bit(flag, (unsigned long *)&ti->flags);
+}
+
+static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
+{
+	return test_bit(flag, (unsigned long *)&ti->flags);
+}
+
+#define set_thread_flag(flag) \
+	set_ti_thread_flag(current_thread_info(), flag)
+#define clear_thread_flag(flag) \
+	clear_ti_thread_flag(current_thread_info(), flag)
+#define test_and_set_thread_flag(flag) \
+	test_and_set_ti_thread_flag(current_thread_info(), flag)
+#define test_and_clear_thread_flag(flag) \
+	test_and_clear_ti_thread_flag(current_thread_info(), flag)
+#define test_thread_flag(flag) \
+	test_ti_thread_flag(current_thread_info(), flag)
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _LINUX_THREAD_BITS_H */
+
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index b4c2a48..b094aed 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -50,8 +50,7 @@ struct restart_block {
 
 extern long do_no_restart_syscall(struct restart_block *parm);
 
-#include <linux/bitops.h>
-#include <asm/thread_info.h>
+#include <linux/thread_bits.h>
 
 #ifdef __KERNEL__
 
@@ -62,47 +61,6 @@ extern long do_no_restart_syscall(struct restart_block *parm);
 # define THREADINFO_GFP		(GFP_KERNEL_ACCOUNT | __GFP_NOTRACK)
 #endif
 
-/*
- * flag set/clear/test wrappers
- * - pass TIF_xxxx constants to these functions
- */
-
-static inline void set_ti_thread_flag(struct thread_info *ti, int flag)
-{
-	set_bit(flag, (unsigned long *)&ti->flags);
-}
-
-static inline void clear_ti_thread_flag(struct thread_info *ti, int flag)
-{
-	clear_bit(flag, (unsigned long *)&ti->flags);
-}
-
-static inline int test_and_set_ti_thread_flag(struct thread_info *ti, int flag)
-{
-	return test_and_set_bit(flag, (unsigned long *)&ti->flags);
-}
-
-static inline int test_and_clear_ti_thread_flag(struct thread_info *ti, int flag)
-{
-	return test_and_clear_bit(flag, (unsigned long *)&ti->flags);
-}
-
-static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
-{
-	return test_bit(flag, (unsigned long *)&ti->flags);
-}
-
-#define set_thread_flag(flag) \
-	set_ti_thread_flag(current_thread_info(), flag)
-#define clear_thread_flag(flag) \
-	clear_ti_thread_flag(current_thread_info(), flag)
-#define test_and_set_thread_flag(flag) \
-	test_and_set_ti_thread_flag(current_thread_info(), flag)
-#define test_and_clear_thread_flag(flag) \
-	test_and_clear_ti_thread_flag(current_thread_info(), flag)
-#define test_thread_flag(flag) \
-	test_ti_thread_flag(current_thread_info(), flag)
-
 #define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)
 
 #if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:47 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:47 +0300
Subject: [PATCH 18/23] arm64: ilp32: add sys_ilp32.c and a separate table (in
 entry.S) to use it
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-19-git-send-email-ynorov@caviumnetworks.com>

From: Andrew Pinski <apinski at cavium.com>

Add a separate syscall-table for ILP32, which dispatches either to native
LP64 system call implementation or to compat-syscalls, as appropriate.

Signed-off-by: Andrew Pinski <Andrew.Pinski at caviumnetworks.com>
Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/include/asm/unistd.h | 11 +++++-
 arch/arm64/kernel/Makefile      |  2 +-
 arch/arm64/kernel/entry.S       | 10 ++++-
 arch/arm64/kernel/sys_ilp32.c   | 83 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 102 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm64/kernel/sys_ilp32.c

diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 2971dea..5ea18ef 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -13,9 +13,18 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+
+#ifdef CONFIG_COMPAT
+#define __ARCH_WANT_COMPAT_STAT64
+#endif
+
+#ifdef CONFIG_ARM64_ILP32
+#define __ARCH_WANT_COMPAT_SYS_PREADV64
+#define __ARCH_WANT_COMPAT_SYS_PWRITEV64
+#endif
+
 #ifdef CONFIG_AARCH32_EL0
 #define __ARCH_WANT_COMPAT_SYS_GETDENTS64
-#define __ARCH_WANT_COMPAT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_GETPGRP
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 9dfdf86..7aa65ea 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -28,7 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
 					   ../../arm/kernel/opcodes.o binfmt_elf32.o
-arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
+arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 21a0624..acea2cb 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -501,6 +501,7 @@ el0_svc_compat:
 	 * AArch32 syscall handling
 	 */
 	adrp	stbl, compat_sys_call_table	// load compat syscall table pointer
+	ldr     x16, [tsk, #TI_FLAGS]
 	uxtw	scno, w7			// syscall number in w7 (r7)
 	mov     sc_nr, #__NR_compat_syscalls
 	b	el0_svc_naked
@@ -717,15 +718,20 @@ ENDPROC(ret_from_fork)
 	.align	6
 el0_svc:
 	adrp	stbl, sys_call_table		// load syscall table pointer
+	ldr	x16, [tsk, #TI_FLAGS]
 	uxtw	scno, w8			// syscall number in w8
 	mov	sc_nr, #__NR_syscalls
+#ifdef CONFIG_ARM64_ILP32
+	adrp	x17, sys_call_ilp32_table	// load ilp32 syscall table pointer
+	tst	x16, #_TIF_32BIT_AARCH64
+	csel    stbl, stbl, x17, eq		// We are using ILP32
+#endif
 el0_svc_naked:					// compat entry point
 	stp	x0, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
 	enable_dbg_and_irq
 	ct_user_exit 1
 
-	ldr	x16, [tsk, #TI_FLAGS]		// check for syscall hooks
-	tst	x16, #_TIF_SYSCALL_WORK
+	tst	x16, #_TIF_SYSCALL_WORK		// check for syscall hooks
 	b.ne	__sys_trace
 	cmp     scno, sc_nr                     // check upper syscall limit
 	b.hs	ni_sys
diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
new file mode 100644
index 0000000..d4cd2a9
--- /dev/null
+++ b/arch/arm64/kernel/sys_ilp32.c
@@ -0,0 +1,83 @@
+/*
+ * AArch64- ILP32 specific system calls implementation
+ *
+ * Copyright (C) 2016 Cavium Inc.
+ * Author: Andrew Pinski <apinski at cavium.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define __SYSCALL_COMPAT
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/msg.h>
+#include <linux/export.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/compat.h>
+#include <asm-generic/syscalls.h>
+
+/* Using non-compat syscalls where necessary */
+#define compat_sys_fadvise64_64		sys_fadvise64_64
+#define compat_sys_fallocate		sys_fallocate
+#define compat_sys_ftruncate64		sys_ftruncate
+#define compat_sys_lookup_dcookie	sys_lookup_dcookie
+#define compat_sys_readahead		sys_readahead
+#define compat_sys_shmat		sys_shmat
+#define compat_sys_sync_file_range	sys_sync_file_range
+#define compat_sys_truncate64		sys_truncate
+#define sys_llseek			sys_lseek
+#define sys_mmap2			compat_sys_mmap2
+
+static unsigned long compat_sys_mmap2(compat_uptr_t addr, compat_size_t len,
+       int prot, int flags, int fd, off_t pgoff)
+{
+       if (pgoff & (~PAGE_MASK >> 12))
+               return -EINVAL;
+
+       return sys_mmap_pgoff(addr, len, prot, flags, fd,
+		       pgoff >> (PAGE_SHIFT - 12));
+}
+
+static unsigned long compat_sys_pread64(unsigned int fd,
+		compat_uptr_t __user *ubuf, compat_size_t count, off_t offset)
+{
+	return sys_pread64(fd, (char *) ubuf, count, offset);
+}
+
+static unsigned long compat_sys_pwrite64(unsigned int fd,
+		compat_uptr_t __user *ubuf, compat_size_t count, off_t offset)
+{
+	return sys_pwrite64(fd, (char *) ubuf, count, offset);
+}
+
+#include <asm/syscall.h>
+
+#undef __SYSCALL
+#undef __SC_WRAP
+
+#define __SYSCALL(nr, sym)	[nr] = sym,
+#define __SC_WRAP(nr, sym)	[nr] = compat_##sym,
+
+/*
+ * The sys_call_ilp32_table array must be 4K aligned to be accessible from
+ * kernel/entry.S.
+ */
+void *sys_call_ilp32_table[__NR_syscalls] __aligned(4096) = {
+	[0 ... __NR_syscalls - 1] = sys_ni_syscall,
+#include <asm/unistd.h>
+};
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:52 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:52 +0300
Subject: [PATCH 23/23] arm64:ilp32: add ARM64_ILP32 to Kconfig
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-24-git-send-email-ynorov@caviumnetworks.com>

From: Andrew Pinski <apinski at cavium.com>

This patch adds the config option for ILP32.

Signed-off-by: Andrew Pinski <Andrew.Pinski at caviumnetworks.com>
Signed-off-by: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
Signed-off-by: Christoph Muellner <christoph.muellner at theobroma-systems.com>
Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
Reviewed-by: David Daney <ddaney at caviumnetworks.com>
---
 arch/arm64/Kconfig | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 0bb7adc..765d7c2 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -926,12 +926,13 @@ source "fs/Kconfig.binfmt"
 
 config COMPAT
 	bool
-	depends on AARCH32_EL0
+	depends on AARCH32_EL0 || ARM64_ILP32
 
 config AARCH32_EL0
 	bool "Kernel support for 32-bit EL0"
 	def_bool y
 	depends on ARM64_4K_PAGES || EXPERT
+	select COMPAT
 	select HAVE_UID16
 	select OLD_SIGSUSPEND3
 	select COMPAT_OLD_SIGACTION
@@ -947,6 +948,15 @@ config AARCH32_EL0
 
 	  If you want to execute 32-bit userspace applications, say Y.
 
+config ARM64_ILP32
+	bool "Kernel support for ILP32"
+	select COMPAT
+	select COMPAT_WRAPPER
+	help
+	  This option enables support for AArch64 ILP32 user space.  ILP32
+	  is an ABI where long and pointers are 32bits but it uses the AARCH64
+	  instruction set.
+
 config SYSVIPC_COMPAT
 	def_bool y
 	depends on COMPAT && SYSVIPC
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:48 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:48 +0300
Subject: [PATCH 19/23] arm64: signal: share lp64 signal routines to ilp32
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-20-git-send-email-ynorov@caviumnetworks.com>

After that, it will be possible to reuse it in ilp32.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/include/asm/signal_common.h | 33 ++++++++++++
 arch/arm64/kernel/signal.c             | 91 +++++++++++++++++++++-------------
 2 files changed, 90 insertions(+), 34 deletions(-)
 create mode 100644 arch/arm64/include/asm/signal_common.h

diff --git a/arch/arm64/include/asm/signal_common.h b/arch/arm64/include/asm/signal_common.h
new file mode 100644
index 0000000..756ed2c
--- /dev/null
+++ b/arch/arm64/include/asm/signal_common.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2016 Cavium Networks.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_SIGNAL_COMMON_H
+#define __ASM_SIGNAL_COMMON_H
+
+#include <linux/uaccess.h>
+#include <asm/ucontext.h>
+#include <asm/fpsimd.h>
+
+int preserve_fpsimd_context(struct fpsimd_context __user *ctx);
+int restore_fpsimd_context(struct fpsimd_context __user *ctx);
+int setup_sigcontext(struct sigcontext __user *uc_mcontext, struct pt_regs *regs);
+int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sf);
+void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+			void __user *frame, off_t sigframe_off, int usig);
+
+#endif /* __ASM_SIGNAL_COMMON_H */
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index be02f65..f9fbf8a 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -34,18 +34,23 @@
 #include <asm/fpsimd.h>
 #include <asm/signal32.h>
 #include <asm/vdso.h>
+#include <asm/signal_common.h>
+
+struct sigframe {
+	struct ucontext uc;
+	u64 fp;
+	u64 lr;
+};
 
 /*
  * Do a signal return; undo the signal stack. These are aligned to 128-bit.
  */
 struct rt_sigframe {
 	struct siginfo info;
-	struct ucontext uc;
-	u64 fp;
-	u64 lr;
+	struct sigframe sig;
 };
 
-static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
+int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
 {
 	struct fpsimd_state *fpsimd = &current->thread.fpsimd_state;
 	int err;
@@ -65,7 +70,7 @@ static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
 	return err ? -EFAULT : 0;
 }
 
-static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
+int restore_fpsimd_context(struct fpsimd_context __user *ctx)
 {
 	struct fpsimd_state fpsimd;
 	__u32 magic, size;
@@ -93,22 +98,30 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
 }
 
 static int restore_sigframe(struct pt_regs *regs,
-			    struct rt_sigframe __user *sf)
+			    struct sigframe __user *sf)
 {
 	sigset_t set;
-	int i, err;
-	void *aux = sf->uc.uc_mcontext.__reserved;
-
+	int err;
 	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
 	if (err == 0)
 		set_current_blocked(&set);
 
+	err |= restore_sigcontext(regs, &sf->uc.uc_mcontext);
+	return err;
+}
+
+
+int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *uc_mcontext)
+{
+	int i, err = 0;
+	void *aux = uc_mcontext->__reserved;
+
 	for (i = 0; i < 31; i++)
-		__get_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
+		__get_user_error(regs->regs[i], &uc_mcontext->regs[i],
 				 err);
-	__get_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
-	__get_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
-	__get_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err);
+	__get_user_error(regs->sp, &uc_mcontext->sp, err);
+	__get_user_error(regs->pc, &uc_mcontext->pc, err);
+	__get_user_error(regs->pstate, &uc_mcontext->pstate, err);
 
 	/*
 	 * Avoid sys_rt_sigreturn() restarting.
@@ -145,10 +158,10 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
 	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
 		goto badframe;
 
-	if (restore_sigframe(regs, frame))
+	if (restore_sigframe(regs, &frame->sig))
 		goto badframe;
 
-	if (restore_altstack(&frame->uc.uc_stack))
+	if (restore_altstack(&frame->sig.uc.uc_stack))
 		goto badframe;
 
 	return regs->regs[0];
@@ -162,27 +175,36 @@ badframe:
 	return 0;
 }
 
-static int setup_sigframe(struct rt_sigframe __user *sf,
+static int setup_sigframe(struct sigframe __user *sf,
 			  struct pt_regs *regs, sigset_t *set)
 {
-	int i, err = 0;
-	void *aux = sf->uc.uc_mcontext.__reserved;
-	struct _aarch64_ctx *end;
+	int err = 0;
 
 	/* set up the stack frame for unwinding */
 	__put_user_error(regs->regs[29], &sf->fp, err);
 	__put_user_error(regs->regs[30], &sf->lr, err);
+	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
+	err |= setup_sigcontext(&sf->uc.uc_mcontext, regs);
+
+	return err;
+}
+
+int setup_sigcontext(struct sigcontext __user *uc_mcontext,
+			struct pt_regs *regs)
+{
+	void *aux = uc_mcontext->__reserved;
+	struct _aarch64_ctx *end;
+	int i, err = 0;
 
 	for (i = 0; i < 31; i++)
-		__put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
+		__put_user_error(regs->regs[i], &uc_mcontext->regs[i],
 				 err);
-	__put_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
-	__put_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
-	__put_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err);
 
-	__put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err);
+	__put_user_error(regs->sp, &uc_mcontext->sp, err);
+	__put_user_error(regs->pc, &uc_mcontext->pc, err);
+	__put_user_error(regs->pstate, &uc_mcontext->pstate, err);
 
-	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
+	__put_user_error(current->thread.fault_address, &uc_mcontext->fault_address, err);
 
 	if (err == 0) {
 		struct fpsimd_context *fpsimd_ctx =
@@ -229,14 +251,14 @@ static struct rt_sigframe __user *get_sigframe(struct ksignal *ksig,
 	return frame;
 }
 
-static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
-			 void __user *frame, int usig)
+void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+			 void __user *frame, off_t sigframe_off, int usig)
 {
 	__sigrestore_t sigtramp;
 
 	regs->regs[0] = usig;
 	regs->sp = (unsigned long)frame;
-	regs->regs[29] = regs->sp + offsetof(struct rt_sigframe, fp);
+	regs->regs[29] = regs->sp + sigframe_off + offsetof(struct sigframe, fp);
 	regs->pc = (unsigned long)ka->sa.sa_handler;
 
 	if (ka->sa.sa_flags & SA_RESTORER)
@@ -257,17 +279,18 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
 	if (!frame)
 		return 1;
 
-	__put_user_error(0, &frame->uc.uc_flags, err);
-	__put_user_error(NULL, &frame->uc.uc_link, err);
+	__put_user_error(0, &frame->sig.uc.uc_flags, err);
+	__put_user_error(NULL, &frame->sig.uc.uc_link, err);
 
-	err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
-	err |= setup_sigframe(frame, regs, set);
+	err |= __save_altstack(&frame->sig.uc.uc_stack, regs->sp);
+	err |= setup_sigframe(&frame->sig, regs, set);
 	if (err == 0) {
-		setup_return(regs, &ksig->ka, frame, usig);
+		setup_return(regs, &ksig->ka, frame,
+			offsetof(struct rt_sigframe, sig), usig);
 		if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
 			err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 			regs->regs[1] = (unsigned long)&frame->info;
-			regs->regs[2] = (unsigned long)&frame->uc;
+			regs->regs[2] = (unsigned long)&frame->sig.uc;
 		}
 	}
 
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:42 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:42 +0300
Subject: [PATCH 13/23] arm64: introduce is_a32_task and is_a32_thread (for
 AArch32 compat)
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-14-git-send-email-ynorov@caviumnetworks.com>

Based on patch of Andrew Pinski.

This patch introduces is_a32_compat_task and is_a32_thread so it is
easier to say this is a a32 specific thread or a generic compat thread/task.
Corresponding functions are located in <asm/is_compat.h> to avoid mess in
headers.

Some files include both <linux/compat.h> and <asm/compat.h>,
and this is wrong because <linux/compat.h> has <asm/compat.h> already
included. It was fixed too.

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
Signed-off-by: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
Signed-off-by: Christoph Muellner <christoph.muellner at theobroma-systems.com>
Signed-off-by: Andrew Pinski <Andrew.Pinski at caviumnetworks.com>
Reviewed-by: David Daney <ddaney at caviumnetworks.com>
---
 arch/arm64/include/asm/compat.h      | 19 ++----------
 arch/arm64/include/asm/elf.h         | 10 +++----
 arch/arm64/include/asm/ftrace.h      |  2 +-
 arch/arm64/include/asm/is_compat.h   | 58 ++++++++++++++++++++++++++++++++++++
 arch/arm64/include/asm/memory.h      |  3 +-
 arch/arm64/include/asm/processor.h   |  5 ++--
 arch/arm64/include/asm/syscall.h     |  2 +-
 arch/arm64/include/asm/thread_info.h |  2 +-
 arch/arm64/kernel/hw_breakpoint.c    | 10 +++----
 arch/arm64/kernel/perf_regs.c        |  2 +-
 arch/arm64/kernel/process.c          |  7 ++---
 arch/arm64/kernel/ptrace.c           | 11 ++++---
 arch/arm64/kernel/signal.c           |  4 +--
 arch/arm64/kernel/traps.c            |  3 +-
 14 files changed, 91 insertions(+), 47 deletions(-)
 create mode 100644 arch/arm64/include/asm/is_compat.h

diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index eb8432b..df2f72d 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -24,6 +24,8 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 
+#include <asm/is_compat.h>
+
 #define COMPAT_USER_HZ		100
 #ifdef __AARCH64EB__
 #define COMPAT_UTS_MACHINE	"armv8b\0\0"
@@ -298,23 +300,6 @@ struct compat_shmid64_ds {
 	compat_ulong_t __unused5;
 };
 
-static inline int is_compat_task(void)
-{
-	return test_thread_flag(TIF_32BIT);
-}
-
-static inline int is_compat_thread(struct thread_info *thread)
-{
-	return test_ti_thread_flag(thread, TIF_32BIT);
-}
-
-#else /* !CONFIG_COMPAT */
-
-static inline int is_compat_thread(struct thread_info *thread)
-{
-	return 0;
-}
-
 #endif /* CONFIG_COMPAT */
 #endif /* __KERNEL__ */
 #endif /* __ASM_COMPAT_H */
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 24ed037..b5437c5 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -16,6 +16,10 @@
 #ifndef __ASM_ELF_H
 #define __ASM_ELF_H
 
+#ifndef __ASSEMBLY__
+#include <linux/compat.h>
+#endif
+
 #include <asm/hwcap.h>
 
 /*
@@ -152,13 +156,9 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 				       int uses_interp);
 
 /* 1GB of VA */
-#ifdef CONFIG_COMPAT
-#define STACK_RND_MASK			(test_thread_flag(TIF_32BIT) ? \
+#define STACK_RND_MASK			(is_compat_task() ? \
 						0x7ff >> (PAGE_SHIFT - 12) : \
 						0x3ffff >> (PAGE_SHIFT - 12))
-#else
-#define STACK_RND_MASK			(0x3ffff >> (PAGE_SHIFT - 12))
-#endif
 
 #ifdef CONFIG_COMPAT
 
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index caa955f..0feb28a 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -54,7 +54,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 #define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
 static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
 {
-	return is_compat_task();
+	return is_a32_compat_task();
 }
 #endif /* ifndef __ASSEMBLY__ */
 
diff --git a/arch/arm64/include/asm/is_compat.h b/arch/arm64/include/asm/is_compat.h
new file mode 100644
index 0000000..6139b5a
--- /dev/null
+++ b/arch/arm64/include/asm/is_compat.h
@@ -0,0 +1,58 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_IS_COMPAT_H
+#define __ASM_IS_COMPAT_H
+#ifndef __ASSEMBLY__
+
+#include <linux/thread_bits.h>
+
+#ifdef CONFIG_AARCH32_EL0
+
+static inline int is_a32_compat_task(void)
+{
+	return test_thread_flag(TIF_32BIT);
+}
+
+static inline int is_a32_compat_thread(struct thread_info *thread)
+{
+	return test_ti_thread_flag(thread, TIF_32BIT);
+}
+
+#else
+
+static inline int is_a32_compat_task(void)
+
+{
+	return 0;
+}
+
+static inline int is_a32_compat_thread(struct thread_info *thread)
+{
+	return 0;
+}
+
+#endif /* CONFIG_AARCH32_EL0 */
+
+#ifdef CONFIG_COMPAT
+
+static inline int is_compat_task(void)
+{
+	return is_a32_compat_task();
+}
+
+#endif /* CONFIG_COMPAT */
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_IS_COMPAT_H */
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 12f8a00..a66a0f7 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -26,6 +26,7 @@
 #include <linux/types.h>
 #include <asm/bug.h>
 #include <asm/sizes.h>
+#include <asm/is_compat.h>
 
 /*
  * Allow for constants defined here to be used from assembly code
@@ -61,7 +62,7 @@
 
 #ifdef CONFIG_COMPAT
 #define TASK_SIZE_32		UL(0x100000000)
-#define TASK_SIZE		(test_thread_flag(TIF_32BIT) ? \
+#define TASK_SIZE		(is_compat_task() ?		\
 				TASK_SIZE_32 : TASK_SIZE_64)
 #define TASK_SIZE_OF(tsk)	(test_tsk_thread_flag(tsk, TIF_32BIT) ? \
 				TASK_SIZE_32 : TASK_SIZE_64)
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 5bbdbb4..1eccf47 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -30,6 +30,7 @@
 #include <linux/string.h>
 
 #include <asm/alternative.h>
+#include <asm/is_compat.h>
 #include <asm/fpsimd.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/lse.h>
@@ -41,7 +42,7 @@
 #define STACK_TOP_MAX		TASK_SIZE_64
 #ifdef CONFIG_COMPAT
 #define AARCH32_VECTORS_BASE	0xffff0000
-#define STACK_TOP		(test_thread_flag(TIF_32BIT) ? \
+#define STACK_TOP		(is_compat_task() ? \
 				AARCH32_VECTORS_BASE : STACK_TOP_MAX)
 #else
 #define STACK_TOP		STACK_TOP_MAX
@@ -94,7 +95,7 @@ struct thread_struct {
 #define task_user_tls(t)						\
 ({									\
 	unsigned long *__tls;						\
-	if (is_compat_thread(task_thread_info(t)))			\
+	if (is_a32_compat_thread(task_thread_info(t)))			\
 		__tls = &(t)->thread.tp2_value;				\
 	else								\
 		__tls = &(t)->thread.tp_value;				\
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 709a574..ce09641 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -113,7 +113,7 @@ static inline void syscall_set_arguments(struct task_struct *task,
  */
 static inline int syscall_get_arch(void)
 {
-	if (is_compat_task())
+	if (is_a32_compat_task())
 		return AUDIT_ARCH_ARM;
 
 	return AUDIT_ARCH_AARCH64;
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index abd64bd..4daa559 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -118,7 +118,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_FREEZE		19
 #define TIF_RESTORE_SIGMASK	20
 #define TIF_SINGLESTEP		21
-#define TIF_32BIT		22	/* 32bit process */
+#define TIF_32BIT		22	/* AARCH32 process */
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index b45c95d..baa1eba 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -164,7 +164,7 @@ enum hw_breakpoint_ops {
 	HW_BREAKPOINT_RESTORE
 };
 
-static int is_compat_bp(struct perf_event *bp)
+static int is_a32_compat_bp(struct perf_event *bp)
 {
 	struct task_struct *tsk = bp->hw.target;
 
@@ -175,7 +175,7 @@ static int is_compat_bp(struct perf_event *bp)
 	 * deprecated behaviour if we use unaligned watchpoints in
 	 * AArch64 state.
 	 */
-	return tsk && is_compat_thread(task_thread_info(tsk));
+	return tsk && is_a32_compat_thread(task_thread_info(tsk));
 }
 
 /**
@@ -435,7 +435,7 @@ static int arch_build_bp_info(struct perf_event *bp)
 	 * Watchpoints can be of length 1, 2, 4 or 8 bytes.
 	 */
 	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
-		if (is_compat_bp(bp)) {
+		if (is_a32_compat_bp(bp)) {
 			if (info->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
 			    info->ctrl.len != ARM_BREAKPOINT_LEN_4)
 				return -EINVAL;
@@ -492,7 +492,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
 	 * AArch32 tasks expect some simple alignment fixups, so emulate
 	 * that here.
 	 */
-	if (is_compat_bp(bp)) {
+	if (is_a32_compat_bp(bp)) {
 		if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
 			alignment_mask = 0x7;
 		else
@@ -679,7 +679,7 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
 
 		info = counter_arch_bp(wp);
 		/* AArch32 watchpoints are either 4 or 8 bytes aligned. */
-		if (is_compat_task()) {
+		if (is_a32_compat_task()) {
 			if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
 				alignment_mask = 0x7;
 			else
diff --git a/arch/arm64/kernel/perf_regs.c b/arch/arm64/kernel/perf_regs.c
index 3f62b35..a79058f 100644
--- a/arch/arm64/kernel/perf_regs.c
+++ b/arch/arm64/kernel/perf_regs.c
@@ -45,7 +45,7 @@ int perf_reg_validate(u64 mask)
 
 u64 perf_reg_abi(struct task_struct *task)
 {
-	if (is_compat_thread(task_thread_info(task)))
+	if (is_a32_compat_thread(task_thread_info(task)))
 		return PERF_SAMPLE_REGS_ABI_32;
 	else
 		return PERF_SAMPLE_REGS_ABI_64;
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 8062482..746f2d3 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -47,7 +47,6 @@
 #include <trace/events/power.h>
 
 #include <asm/alternative.h>
-#include <asm/compat.h>
 #include <asm/cacheflush.h>
 #include <asm/fpsimd.h>
 #include <asm/mmu_context.h>
@@ -211,7 +210,7 @@ static void tls_thread_flush(void)
 {
 	asm ("msr tpidr_el0, xzr");
 
-	if (is_compat_task()) {
+	if (is_a32_compat_task()) {
 		current->thread.tp_value = 0;
 
 		/*
@@ -263,7 +262,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
 		asm("mrs %0, tpidr_el0" : "=r" (*task_user_tls(p)));
 
 		if (stack_start) {
-			if (is_compat_thread(task_thread_info(p)))
+			if (is_a32_compat_thread(task_thread_info(p)))
 				childregs->compat_sp = stack_start;
 			/* 16-byte aligned stack mandatory on AArch64 */
 			else if (stack_start & 15)
@@ -303,7 +302,7 @@ static void tls_thread_switch(struct task_struct *next)
 	*task_user_tls(current) = tpidr;
 
 	tpidr = *task_user_tls(next);
-	tpidrro = is_compat_thread(task_thread_info(next)) ?
+	tpidrro = is_a32_compat_thread(task_thread_info(next)) ?
 		  next->thread.tp_value : 0;
 
 	asm(
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index aa79e81..38a09338 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -38,7 +38,6 @@
 #include <linux/tracehook.h>
 #include <linux/elf.h>
 
-#include <asm/compat.h>
 #include <asm/debug-monitors.h>
 #include <asm/pgtable.h>
 #include <asm/syscall.h>
@@ -85,7 +84,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
 #ifdef CONFIG_AARCH32_EL0
 	int i;
 
-	if (!is_compat_task())
+	if (!is_a32_compat_task())
 		goto send_sig;
 
 	for (i = 0; i < ARM_MAX_BRP; ++i) {
@@ -1203,9 +1202,9 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 	 * 32-bit children use an extended user_aarch32_ptrace_view to allow
 	 * access to the TLS register.
 	 */
-	if (is_compat_task())
+	if (is_a32_compat_task())
 		return &user_aarch32_view;
-	else if (is_compat_thread(task_thread_info(task)))
+	else if (is_a32_compat_thread(task_thread_info(task)))
 		return &user_aarch32_ptrace_view;
 #endif
 	return &user_aarch64_view;
@@ -1232,7 +1231,7 @@ static void tracehook_report_syscall(struct pt_regs *regs,
 	 * A scratch register (ip(r12) on AArch32, x7 on AArch64) is
 	 * used to denote syscall entry/exit:
 	 */
-	regno = (is_compat_task() ? 12 : 7);
+	regno = (is_a32_compat_task() ? 12 : 7);
 	saved_reg = regs->regs[regno];
 	regs->regs[regno] = dir;
 
@@ -1343,7 +1342,7 @@ int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task)
 	if (!test_tsk_thread_flag(task, TIF_SINGLESTEP))
 		regs->pstate &= ~DBG_SPSR_SS;
 
-	if (is_compat_thread(task_thread_info(task)))
+	if (is_a32_compat_thread(task_thread_info(task)))
 		return valid_compat_regs(regs);
 	else
 		return valid_native_regs(regs);
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index a8eafdb..be02f65 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -276,7 +276,7 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
 
 static void setup_restart_syscall(struct pt_regs *regs)
 {
-	if (is_compat_task())
+	if (is_a32_compat_task())
 		compat_setup_restart_syscall(regs);
 	else
 		regs->regs[8] = __NR_restart_syscall;
@@ -295,7 +295,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 	/*
 	 * Set up the stack frame
 	 */
-	if (is_compat_task()) {
+	if (is_a32_compat_task()) {
 		if (ksig->ka.sa.sa_flags & SA_SIGINFO)
 			ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
 		else
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 85461e8..515444a 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/bug.h>
+#include <linux/compat.h>
 #include <linux/signal.h>
 #include <linux/personality.h>
 #include <linux/kallsyms.h>
@@ -411,7 +412,7 @@ asmlinkage long do_ni_syscall(struct pt_regs *regs)
 {
 #ifdef CONFIG_AARCH32_EL0
 	long ret;
-	if (is_compat_task()) {
+	if (is_a32_compat_task()) {
 		ret = compat_arm_syscall(regs);
 		if (ret != -ENOSYS)
 			return ret;
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:49 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:49 +0300
Subject: [PATCH 20/23] arm64: signal32: move ilp32 and aarch32 common code to
 separated file
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-21-git-send-email-ynorov@caviumnetworks.com>

Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/include/asm/signal32_common.h |  25 +++++++
 arch/arm64/kernel/Makefile               |   1 +
 arch/arm64/kernel/signal32.c             |  85 -----------------------
 arch/arm64/kernel/signal32_common.c      | 115 +++++++++++++++++++++++++++++++
 4 files changed, 141 insertions(+), 85 deletions(-)
 create mode 100644 arch/arm64/include/asm/signal32_common.h
 create mode 100644 arch/arm64/kernel/signal32_common.c

diff --git a/arch/arm64/include/asm/signal32_common.h b/arch/arm64/include/asm/signal32_common.h
new file mode 100644
index 0000000..b4f2099
--- /dev/null
+++ b/arch/arm64/include/asm/signal32_common.h
@@ -0,0 +1,25 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SIGNAL32_COMMON_H
+#define __ASM_SIGNAL32_COMMON_H
+
+#ifdef CONFIG_COMPAT
+
+int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from);
+int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from);
+
+#endif /* CONFIG_COMPAT*/
+
+#endif /* __ASM_SIGNAL32_COMMON_H */
+
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7aa65ea..3ed55eb 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -29,6 +29,7 @@ arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
 					   ../../arm/kernel/opcodes.o binfmt_elf32.o
 arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o
+arm64-obj-$(CONFIG_COMPAT)		+= signal32_common.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index b7063de..b103af3 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -125,91 +125,6 @@ static inline int get_sigset_t(sigset_t *set,
 	return 0;
 }
 
-int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
-{
-	int err;
-
-	if (!access_ok(VERIFY_WRITE, to, sizeof(*to)))
-		return -EFAULT;
-
-	/* If you change siginfo_t structure, please be sure
-	 * this code is fixed accordingly.
-	 * It should never copy any pad contained in the structure
-	 * to avoid security leaks, but must copy the generic
-	 * 3 ints plus the relevant union member.
-	 * This routine must convert siginfo from 64bit to 32bit as well
-	 * at the same time.
-	 */
-	err = __put_user(from->si_signo, &to->si_signo);
-	err |= __put_user(from->si_errno, &to->si_errno);
-	err |= __put_user((short)from->si_code, &to->si_code);
-	if (from->si_code < 0)
-		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad,
-				      SI_PAD_SIZE);
-	else switch (from->si_code & __SI_MASK) {
-	case __SI_KILL:
-		err |= __put_user(from->si_pid, &to->si_pid);
-		err |= __put_user(from->si_uid, &to->si_uid);
-		break;
-	case __SI_TIMER:
-		 err |= __put_user(from->si_tid, &to->si_tid);
-		 err |= __put_user(from->si_overrun, &to->si_overrun);
-		 err |= __put_user(from->si_int, &to->si_int);
-		break;
-	case __SI_POLL:
-		err |= __put_user(from->si_band, &to->si_band);
-		err |= __put_user(from->si_fd, &to->si_fd);
-		break;
-	case __SI_FAULT:
-		err |= __put_user((compat_uptr_t)(unsigned long)from->si_addr,
-				  &to->si_addr);
-#ifdef BUS_MCEERR_AO
-		/*
-		 * Other callers might not initialize the si_lsb field,
-		 * so check explicitly for the right codes here.
-		 */
-		if (from->si_signo == SIGBUS &&
-		    (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
-			err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
-#endif
-		break;
-	case __SI_CHLD:
-		err |= __put_user(from->si_pid, &to->si_pid);
-		err |= __put_user(from->si_uid, &to->si_uid);
-		err |= __put_user(from->si_status, &to->si_status);
-		err |= __put_user(from->si_utime, &to->si_utime);
-		err |= __put_user(from->si_stime, &to->si_stime);
-		break;
-	case __SI_RT: /* This is not generated by the kernel as of now. */
-	case __SI_MESGQ: /* But this is */
-		err |= __put_user(from->si_pid, &to->si_pid);
-		err |= __put_user(from->si_uid, &to->si_uid);
-		err |= __put_user(from->si_int, &to->si_int);
-		break;
-	case __SI_SYS:
-		err |= __put_user((compat_uptr_t)(unsigned long)
-				from->si_call_addr, &to->si_call_addr);
-		err |= __put_user(from->si_syscall, &to->si_syscall);
-		err |= __put_user(from->si_arch, &to->si_arch);
-		break;
-	default: /* this is just in case for now ... */
-		err |= __put_user(from->si_pid, &to->si_pid);
-		err |= __put_user(from->si_uid, &to->si_uid);
-		break;
-	}
-	return err;
-}
-
-int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
-{
-	if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) ||
-	    copy_from_user(to->_sifields._pad,
-			   from->_sifields._pad, SI_PAD_SIZE))
-		return -EFAULT;
-
-	return 0;
-}
-
 /*
  * VFP save/restore code.
  *
diff --git a/arch/arm64/kernel/signal32_common.c b/arch/arm64/kernel/signal32_common.c
new file mode 100644
index 0000000..8fbb609
--- /dev/null
+++ b/arch/arm64/kernel/signal32_common.c
@@ -0,0 +1,115 @@
+/*
+ * Based on arch/arm/kernel/signal.c
+ *
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Modified by Will Deacon <will.deacon at arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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/compat.h>
+#include <linux/signal.h>
+#include <linux/ratelimit.h>
+
+#include <asm/esr.h>
+#include <asm/fpsimd.h>
+#include <asm/signal32_common.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+
+int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
+{
+	int err;
+
+	if (!access_ok(VERIFY_WRITE, to, sizeof(*to)))
+		return -EFAULT;
+
+	/* If you change siginfo_t structure, please be sure
+	 * this code is fixed accordingly.
+	 * It should never copy any pad contained in the structure
+	 * to avoid security leaks, but must copy the generic
+	 * 3 ints plus the relevant union member.
+	 * This routine must convert siginfo from 64bit to 32bit as well
+	 * at the same time.
+	 */
+	err = __put_user(from->si_signo, &to->si_signo);
+	err |= __put_user(from->si_errno, &to->si_errno);
+	err |= __put_user((short)from->si_code, &to->si_code);
+	if (from->si_code < 0)
+		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad,
+				      SI_PAD_SIZE);
+	else switch (from->si_code & __SI_MASK) {
+	case __SI_KILL:
+		err |= __put_user(from->si_pid, &to->si_pid);
+		err |= __put_user(from->si_uid, &to->si_uid);
+		break;
+	case __SI_TIMER:
+		 err |= __put_user(from->si_tid, &to->si_tid);
+		 err |= __put_user(from->si_overrun, &to->si_overrun);
+		 err |= __put_user(from->si_int, &to->si_int);
+		break;
+	case __SI_POLL:
+		err |= __put_user(from->si_band, &to->si_band);
+		err |= __put_user(from->si_fd, &to->si_fd);
+		break;
+	case __SI_FAULT:
+		err |= __put_user((compat_uptr_t)(unsigned long)from->si_addr,
+				  &to->si_addr);
+#ifdef BUS_MCEERR_AO
+		/*
+		 * Other callers might not initialize the si_lsb field,
+		 * so check explicitly for the right codes here.
+		 */
+		if (from->si_signo == SIGBUS &&
+		    (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
+			err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
+#endif
+		break;
+	case __SI_CHLD:
+		err |= __put_user(from->si_pid, &to->si_pid);
+		err |= __put_user(from->si_uid, &to->si_uid);
+		err |= __put_user(from->si_status, &to->si_status);
+		err |= __put_user(from->si_utime, &to->si_utime);
+		err |= __put_user(from->si_stime, &to->si_stime);
+		break;
+	case __SI_RT: /* This is not generated by the kernel as of now. */
+	case __SI_MESGQ: /* But this is */
+		err |= __put_user(from->si_pid, &to->si_pid);
+		err |= __put_user(from->si_uid, &to->si_uid);
+		err |= __put_user(from->si_int, &to->si_int);
+		break;
+	case __SI_SYS:
+		err |= __put_user((compat_uptr_t)(unsigned long)
+				from->si_call_addr, &to->si_call_addr);
+		err |= __put_user(from->si_syscall, &to->si_syscall);
+		err |= __put_user(from->si_arch, &to->si_arch);
+		break;
+	default: /* this is just in case for now ... */
+		err |= __put_user(from->si_pid, &to->si_pid);
+		err |= __put_user(from->si_uid, &to->si_uid);
+		break;
+	}
+	return err;
+}
+
+int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
+{
+	if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) ||
+	    copy_from_user(to->_sifields._pad,
+			   from->_sifields._pad, SI_PAD_SIZE))
+		return -EFAULT;
+
+	return 0;
+}
+
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:50 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:50 +0300
Subject: [PATCH 21/23] arm64: ilp32: introduce ilp32-specific handlers for
 sigframe and ucontext
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-22-git-send-email-ynorov@caviumnetworks.com>

From: Andrew Pinski <apinski at cavium.com>

ILP32 uses AARCH32 compat structures and syscall handlers for signals.
But ILP32 struct rt_sigframe  and ucontext differs from both LP64 and
AARCH32. So some specific mechanism is needed to take care of it.

Signed-off-by: Andrew Pinski <Andrew.Pinski at caviumnetworks.com>
Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/include/asm/signal_ilp32.h |  34 ++++++
 arch/arm64/kernel/Makefile            |   3 +-
 arch/arm64/kernel/entry_ilp32.S       |  23 ++++
 arch/arm64/kernel/signal.c            |   3 +
 arch/arm64/kernel/signal_ilp32.c      | 192 ++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/sys_ilp32.c         |   3 +
 6 files changed, 257 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/signal_ilp32.h
 create mode 100644 arch/arm64/kernel/entry_ilp32.S
 create mode 100644 arch/arm64/kernel/signal_ilp32.c

diff --git a/arch/arm64/include/asm/signal_ilp32.h b/arch/arm64/include/asm/signal_ilp32.h
new file mode 100644
index 0000000..30eff23
--- /dev/null
+++ b/arch/arm64/include/asm/signal_ilp32.h
@@ -0,0 +1,34 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SIGNAL_ILP32_H
+#define __ASM_SIGNAL_ILP32_H
+
+#ifdef CONFIG_ARM64_ILP32
+
+#include <linux/compat.h>
+
+int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs);
+
+#else
+
+static inline int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+			  struct pt_regs *regs)
+{
+	return -ENOSYS;
+}
+
+#endif /* CONFIG_ARM64_ILP32 */
+
+#endif /* __ASM_SIGNAL_ILP32_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 3ed55eb..09e4373 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -28,7 +28,8 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o entry32.o		\
 					   ../../arm/kernel/opcodes.o binfmt_elf32.o
-arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o
+arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o sys_ilp32.o 		\
+					   signal_ilp32.o entry_ilp32.o
 arm64-obj-$(CONFIG_COMPAT)		+= signal32_common.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
diff --git a/arch/arm64/kernel/entry_ilp32.S b/arch/arm64/kernel/entry_ilp32.S
new file mode 100644
index 0000000..5063172
--- /dev/null
+++ b/arch/arm64/kernel/entry_ilp32.S
@@ -0,0 +1,23 @@
+/*
+ * ILP32 system call wrappers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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/linkage.h>
+
+ENTRY(ilp32_sys_rt_sigreturn_wrapper)
+	mov	x0, sp
+	b	ilp32_sys_rt_sigreturn
+ENDPROC(ilp32_sys_rt_sigreturn_wrapper)
+
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index f9fbf8a..45bcd96 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -35,6 +35,7 @@
 #include <asm/signal32.h>
 #include <asm/vdso.h>
 #include <asm/signal_common.h>
+#include <asm/signal_ilp32.h>
 
 struct sigframe {
 	struct ucontext uc;
@@ -323,6 +324,8 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 			ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
 		else
 			ret = compat_setup_frame(usig, ksig, oldset, regs);
+	} else if (is_ilp32_compat_task()) {
+		ret = ilp32_setup_rt_frame(usig, ksig, oldset, regs);
 	} else {
 		ret = setup_rt_frame(usig, ksig, oldset, regs);
 	}
diff --git a/arch/arm64/kernel/signal_ilp32.c b/arch/arm64/kernel/signal_ilp32.c
new file mode 100644
index 0000000..841e8f8
--- /dev/null
+++ b/arch/arm64/kernel/signal_ilp32.c
@@ -0,0 +1,192 @@
+/*
+ * Based on arch/arm/kernel/signal.c
+ *
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2016 Cavium Networks.
+ * Yury Norov <ynorov at caviumnetworks.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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/compat.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/ratelimit.h>
+
+#include <asm/esr.h>
+#include <asm/fpsimd.h>
+#include <asm/signal32_common.h>
+#include <asm/signal_common.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+#include <asm/ucontext.h>
+
+
+struct ilp32_ucontext {
+        u32		uc_flags;
+        u32		uc_link;
+        compat_stack_t  uc_stack;
+        compat_sigset_t uc_sigmask;
+        /* glibc uses a 1024-bit sigset_t */
+        __u8            __unused[1024 / 8 - sizeof(compat_sigset_t)];
+        /* last for future expansion */
+        struct sigcontext uc_mcontext;
+};
+
+struct ilp32_sigframe {
+	struct ilp32_ucontext uc;
+	u64 fp;
+	u64 lr;
+};
+
+struct ilp32_rt_sigframe {
+	struct compat_siginfo info;
+	struct ilp32_sigframe sig;
+};
+
+static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)
+{
+	compat_sigset_t cset;
+
+	cset.sig[0] = set->sig[0] & 0xffffffffull;
+	cset.sig[1] = set->sig[0] >> 32;
+
+	return copy_to_user(uset, &cset, sizeof(*uset));
+}
+
+static inline int get_sigset_t(sigset_t *set,
+                               const compat_sigset_t __user *uset)
+{
+	compat_sigset_t s32;
+
+	if (copy_from_user(&s32, uset, sizeof(*uset)))
+		return -EFAULT;
+
+	set->sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
+	return 0;
+}
+
+static int restore_ilp32_sigframe(struct pt_regs *regs,
+                            struct ilp32_sigframe __user *sf)
+{
+	sigset_t set;
+	int err;
+	err = get_sigset_t(&set, &sf->uc.uc_sigmask);
+	if (err == 0)
+		set_current_blocked(&set);
+	err |= restore_sigcontext(regs, &sf->uc.uc_mcontext);
+	return err;
+}
+
+static int setup_ilp32_sigframe(struct ilp32_sigframe __user *sf,
+                          struct pt_regs *regs, sigset_t *set)
+{
+	int err = 0;
+	/* set up the stack frame for unwinding */
+	__put_user_error(regs->regs[29], &sf->fp, err);
+	__put_user_error(regs->regs[30], &sf->lr, err);
+
+	err |= put_sigset_t(&sf->uc.uc_sigmask, set);
+	err |= setup_sigcontext(&sf->uc.uc_mcontext, regs);
+	return err;
+}
+
+asmlinkage long ilp32_sys_rt_sigreturn(struct pt_regs *regs)
+{
+	struct ilp32_rt_sigframe __user *frame;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current->restart_block.fn = do_no_restart_syscall;
+
+	/*
+	 * Since we stacked the signal on a 128-bit boundary,
+	 * then 'sp' should be word aligned here.  If it's
+	 * not, then the user is trying to mess with us.
+	 */
+	if (regs->sp & 15)
+		goto badframe;
+
+	frame = (struct ilp32_rt_sigframe __user *)regs->sp;
+
+	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
+		goto badframe;
+
+	if (restore_ilp32_sigframe(regs, &frame->sig))
+		goto badframe;
+
+	if (compat_restore_altstack(&frame->sig.uc.uc_stack))
+		goto badframe;
+
+	return regs->regs[0];
+
+badframe:
+	if (show_unhandled_signals)
+		pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n",
+				    current->comm, task_pid_nr(current), __func__,
+				    regs->pc, regs->compat_sp);
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+static struct ilp32_rt_sigframe __user *ilp32_get_sigframe(struct ksignal *ksig,
+					       struct pt_regs *regs)
+{
+	unsigned long sp, sp_top;
+	struct ilp32_rt_sigframe __user *frame;
+
+	sp = sp_top = sigsp(regs->sp, ksig);
+
+	sp = (sp - sizeof(struct ilp32_rt_sigframe)) & ~15;
+	frame = (struct ilp32_rt_sigframe __user *)sp;
+
+	/*
+	 * Check that we can actually write to the signal frame.
+	 */
+	if (!access_ok(VERIFY_WRITE, frame, sp_top - sp))
+		frame = NULL;
+
+	return frame;
+}
+
+/*
+ * ILP32 signal handling routines called from signal.c
+ */
+int ilp32_setup_rt_frame(int usig, struct ksignal *ksig,
+			  sigset_t *set, struct pt_regs *regs)
+{
+	struct ilp32_rt_sigframe __user *frame;
+	int err = 0;
+
+	frame = ilp32_get_sigframe(ksig, regs);
+
+	if (!frame)
+		return 1;
+
+	err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
+
+	__put_user_error(0, &frame->sig.uc.uc_flags, err);
+	__put_user_error(0, &frame->sig.uc.uc_link, err);
+
+	err |= __compat_save_altstack(&frame->sig.uc.uc_stack, regs->sp);
+	err |= setup_ilp32_sigframe(&frame->sig, regs, set);
+	if (err == 0) {
+		setup_return(regs, &ksig->ka, frame,
+				offsetof(struct ilp32_rt_sigframe, sig), usig);
+		regs->regs[1] = (unsigned long)&frame->info;
+		regs->regs[2] = (unsigned long)&frame->sig.uc;
+	}
+
+	return err;
+}
+
diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
index d4cd2a9..a31d538 100644
--- a/arch/arm64/kernel/sys_ilp32.c
+++ b/arch/arm64/kernel/sys_ilp32.c
@@ -65,6 +65,9 @@ static unsigned long compat_sys_pwrite64(unsigned int fd,
 	return sys_pwrite64(fd, (char *) ubuf, count, offset);
 }
 
+asmlinkage long ilp32_sys_rt_sigreturn_wrapper(void);
+#define compat_sys_rt_sigreturn        ilp32_sys_rt_sigreturn_wrapper
+
 #include <asm/syscall.h>
 
 #undef __SYSCALL
-- 
2.5.0



From ynorov at caviumnetworks.com  Mon May 23 17:04:51 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Tue, 24 May 2016 03:04:51 +0300
Subject: [PATCH 22/23] arm64:ilp32: add vdso-ilp32 and use for signal return
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <1464048292-30136-23-git-send-email-ynorov@caviumnetworks.com>

From: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>

ILP32 VDSO exports next symbols:
 __kernel_rt_sigreturn;
 __kernel_gettimeofday;
 __kernel_clock_gettime;
 __kernel_clock_getres;

What shared object to use, kernel selects depending on result of
is_ilp32_compat_task() in arch/arm64/kernel/vdso.c, so it substitutes
correct pages and spec.

Adjusted to move the move data page before code pages in sync with
commit 601255ae3c98fdeeee3a8bb4696425e4f868b4f1

Signed-off-by: Philipp Tomsich <philipp.tomsich at theobroma-systems.com>
Signed-off-by: Christoph Muellner <christoph.muellner at theobroma-systems.com>
Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
---
 arch/arm64/include/asm/vdso.h                 |  6 ++
 arch/arm64/kernel/Makefile                    |  7 ++
 arch/arm64/kernel/asm-offsets.c               |  7 ++
 arch/arm64/kernel/signal.c                    |  2 +
 arch/arm64/kernel/vdso-ilp32/.gitignore       |  2 +
 arch/arm64/kernel/vdso-ilp32/Makefile         | 74 +++++++++++++++++++++
 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S     | 33 ++++++++++
 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 95 +++++++++++++++++++++++++++
 arch/arm64/kernel/vdso.c                      | 61 ++++++++++++++---
 arch/arm64/kernel/vdso/gettimeofday.S         | 20 +++++-
 10 files changed, 294 insertions(+), 13 deletions(-)
 create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore
 create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile
 create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
 create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S

diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
index 839ce00..649a9a4 100644
--- a/arch/arm64/include/asm/vdso.h
+++ b/arch/arm64/include/asm/vdso.h
@@ -29,6 +29,12 @@
 
 #include <generated/vdso-offsets.h>
 
+#ifdef CONFIG_ARM64_ILP32
+#include <generated/vdso-ilp32-offsets.h>
+#else
+#define vdso_offset_sigtramp_ilp32
+#endif
+
 #define VDSO_SYMBOL(base, name)						   \
 ({									   \
 	(void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 09e4373..e98add5 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -50,6 +50,7 @@ arm64-obj-$(CONFIG_PARAVIRT)		+= paravirt.o
 arm64-obj-$(CONFIG_RANDOMIZE_BASE)	+= kaslr.o
 
 obj-y					+= $(arm64-obj-y) vdso/
+obj-$(CONFIG_ARM64_ILP32)		+= vdso-ilp32/
 obj-m					+= $(arm64-obj-m)
 head-y					:= head.o
 extra-y					+= $(head-y) vmlinux.lds
@@ -57,3 +58,9 @@ extra-y					+= $(head-y) vmlinux.lds
 # vDSO - this must be built first to generate the symbol offsets
 $(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h
 $(obj)/vdso/vdso-offsets.h: $(obj)/vdso
+
+ifeq ($(CONFIG_ARM64_ILP32),y)
+# vDSO - this must be built first to generate the symbol offsets
+$(call objectify,$(arm64-obj-y)): $(obj)/vdso-ilp32/vdso-ilp32-offsets.h
+$(obj)/vdso-ilp32/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32
+endif
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index e229525..af69b81 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -101,6 +101,13 @@ int main(void)
   DEFINE(TSPEC_TV_SEC,		offsetof(struct timespec, tv_sec));
   DEFINE(TSPEC_TV_NSEC,		offsetof(struct timespec, tv_nsec));
   BLANK();
+#ifdef CONFIG_COMPAT
+  DEFINE(COMPAT_TVAL_TV_SEC,	offsetof(struct compat_timeval, tv_sec));
+  DEFINE(COMPAT_TVAL_TV_USEC,	offsetof(struct compat_timeval, tv_usec));
+  DEFINE(COMPAT_TSPEC_TV_SEC,	offsetof(struct compat_timespec, tv_sec));
+  DEFINE(COMPAT_TSPEC_TV_NSEC,	offsetof(struct compat_timespec, tv_nsec));
+  BLANK();
+#endif
   DEFINE(TZ_MINWEST,		offsetof(struct timezone, tz_minuteswest));
   DEFINE(TZ_DSTTIME,		offsetof(struct timezone, tz_dsttime));
   BLANK();
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 45bcd96..933cdcf 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -264,6 +264,8 @@ void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
 
 	if (ka->sa.sa_flags & SA_RESTORER)
 		sigtramp = ka->sa.sa_restorer;
+	else if (is_ilp32_compat_task())
+		sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp_ilp32);
 	else
 		sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
 
diff --git a/arch/arm64/kernel/vdso-ilp32/.gitignore b/arch/arm64/kernel/vdso-ilp32/.gitignore
new file mode 100644
index 0000000..61806c3
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/.gitignore
@@ -0,0 +1,2 @@
+vdso-ilp32.lds
+vdso-ilp32-offsets.h
diff --git a/arch/arm64/kernel/vdso-ilp32/Makefile b/arch/arm64/kernel/vdso-ilp32/Makefile
new file mode 100644
index 0000000..0671e88
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/Makefile
@@ -0,0 +1,74 @@
+#
+# Building a vDSO image for AArch64.
+#
+# Author: Will Deacon <will.deacon at arm.com>
+# Heavily based on the vDSO Makefiles for other archs.
+#
+
+obj-ilp32-vdso := gettimeofday-ilp32.o note-ilp32.o sigreturn-ilp32.o
+
+# Build rules
+targets := $(obj-ilp32-vdso) vdso-ilp32.so vdso-ilp32.so.dbg
+obj-ilp32-vdso := $(addprefix $(obj)/, $(obj-ilp32-vdso))
+
+ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-ilp32-vdso.so.1 \
+		$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+
+obj-y += vdso-ilp32.o
+extra-y += vdso-ilp32.lds vdso-ilp32-offsets.h
+CPPFLAGS_vdso-ilp32.lds += -P -C -U$(ARCH) -mabi=ilp32
+
+# Force dependency (incbin is bad)
+$(obj)/vdso-ilp32.o : $(obj)/vdso-ilp32.so
+
+# Link rule for the .so file, .lds has to be first
+$(obj)/vdso-ilp32.so.dbg: $(src)/vdso-ilp32.lds $(obj-ilp32-vdso)
+	$(call if_changed,vdso-ilp32ld)
+
+# Strip rule for the .so file
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+	$(call if_changed,objcopy)
+
+# Generate VDSO offsets using helper script
+gen-vdsosym := $(srctree)/$(src)/../vdso/gen_vdso_offsets.sh
+quiet_cmd_vdsosym = VDSOSYM $@
+define cmd_vdsosym
+	$(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ && \
+	cp $@ include/generated/
+endef
+
+$(obj)/vdso-ilp32-offsets.h: $(obj)/vdso-ilp32.so.dbg FORCE
+	$(call if_changed,vdsosym)
+
+# Assembly rules for the .S files
+#$(obj-ilp32-vdso): %.o: $(src)/../vdso/$(subst -ilp32,,%.S)
+#	$(call if_changed_dep,vdso-ilp32as)
+
+$(obj)/gettimeofday-ilp32.o: $(src)/../vdso/gettimeofday.S
+	$(call if_changed_dep,vdso-ilp32as)
+
+$(obj)/note-ilp32.o: $(src)/../vdso/note.S
+	$(call if_changed_dep,vdso-ilp32as)
+
+# This one should be fine because ILP32 uses the same generic
+# __NR_rt_sigreturn syscall number.
+$(obj)/sigreturn-ilp32.o: $(src)/../vdso/sigreturn.S
+	$(call if_changed_dep,vdso-ilp32as)
+
+# Actual build commands
+quiet_cmd_vdso-ilp32ld = VDSOILP32L $@
+      cmd_vdso-ilp32ld = $(CC) $(c_flags) -mabi=ilp32  -Wl,-n -Wl,-T $^ -o $@
+quiet_cmd_vdso-ilp32as = VDSOILP32A $@
+      cmd_vdso-ilp32as = $(CC) $(a_flags) -mabi=ilp32 -c -o $@ $<
+
+# Install commands for the unstripped file
+quiet_cmd_vdso_install = INSTALL $@
+      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+
+vdso-ilp32.so: $(obj)/vdso-ilp32.so.dbg
+	@mkdir -p $(MODLIB)/vdso
+	$(call cmd,vdso_install)
+
+vdso_install: vdso-ilp32.so
diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
new file mode 100644
index 0000000..46ac072
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon at arm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/const.h>
+#include <asm/page.h>
+
+	__PAGE_ALIGNED_DATA
+
+	.globl vdso_ilp32_start, vdso_ilp32_end
+	.balign PAGE_SIZE
+vdso_ilp32_start:
+	.incbin "arch/arm64/kernel/vdso-ilp32/vdso-ilp32.so"
+	.balign PAGE_SIZE
+vdso_ilp32_end:
+
+	.previous
diff --git a/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
new file mode 100644
index 0000000..1dde31f
--- /dev/null
+++ b/arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
@@ -0,0 +1,95 @@
+/*
+ * GNU linker script for the VDSO library.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon at arm.com>
+ * Heavily based on the vDSO linker scripts for other archs.
+ */
+
+#include <linux/const.h>
+#include <asm/page.h>
+#include <asm/vdso.h>
+
+SECTIONS
+{
+	PROVIDE(_vdso_data = . - PAGE_SIZE);
+	. = VDSO_LBASE + SIZEOF_HEADERS;
+
+	.hash		: { *(.hash) }			:text
+	.gnu.hash	: { *(.gnu.hash) }
+	.dynsym		: { *(.dynsym) }
+	.dynstr		: { *(.dynstr) }
+	.gnu.version	: { *(.gnu.version) }
+	.gnu.version_d	: { *(.gnu.version_d) }
+	.gnu.version_r	: { *(.gnu.version_r) }
+
+	.note		: { *(.note.*) }		:text	:note
+
+	. = ALIGN(16);
+
+	.text		: { *(.text*) }			:text	=0xd503201f
+	PROVIDE (__etext = .);
+	PROVIDE (_etext = .);
+	PROVIDE (etext = .);
+
+	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
+	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
+
+	.dynamic	: { *(.dynamic) }		:text	:dynamic
+
+	.rodata		: { *(.rodata*) }		:text
+
+	_end = .;
+	PROVIDE(end = .);
+
+	/DISCARD/	: {
+		*(.note.GNU-stack)
+		*(.data .data.* .gnu.linkonce.d.* .sdata*)
+		*(.bss .sbss .dynbss .dynsbss)
+	}
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
+	note		PT_NOTE		FLAGS(4);		/* PF_R */
+	eh_frame_hdr	PT_GNU_EH_FRAME;
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+	LINUX_4.6 {
+	global:
+		__kernel_rt_sigreturn;
+		__kernel_gettimeofday;
+		__kernel_clock_gettime;
+		__kernel_clock_getres;
+	local: *;
+	};
+}
+
+/*
+ * Make the sigreturn code visible to the kernel.
+ */
+VDSO_sigtramp_ilp32		= __kernel_rt_sigreturn;
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 26352a6..521a8e4 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -40,6 +40,12 @@ extern char vdso_start, vdso_end;
 static unsigned long vdso_pages;
 static struct page **vdso_pagelist;
 
+#ifdef CONFIG_ARM64_ILP32
+extern char vdso_ilp32_start, vdso_ilp32_end;
+static unsigned long vdso_ilp32_pages;
+static struct page **vdso_ilp32_pagelist;
+#endif
+
 /*
  * The vDSO data page.
  */
@@ -109,24 +115,29 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
 }
 #endif /* CONFIG_AARCH32_EL0 */
 
-static struct vm_special_mapping vdso_spec[2];
-
-static int __init vdso_init(void)
+static int __init vdso_init_common(char *vdso_start, char *vdso_end,
+					  unsigned long *vdso_pagesp,
+					  struct page ***vdso_pagelistp,
+					  struct vm_special_mapping* vdso_spec)
 {
 	int i;
+	unsigned long vdso_pages;
+	struct page **vdso_pagelist;
 
-	if (memcmp(&vdso_start, "\177ELF", 4)) {
+	if (memcmp(vdso_start, "\177ELF", 4)) {
 		pr_err("vDSO is not a valid ELF object!\n");
 		return -EINVAL;
 	}
 
-	vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
+	vdso_pages = (vdso_end - vdso_start) >> PAGE_SHIFT;
+	*vdso_pagesp = vdso_pages;
 	pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
-		vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data);
+		vdso_pages + 1, vdso_pages, vdso_start, 1L, vdso_data);
 
 	/* Allocate the vDSO pagelist, plus a page for the data. */
 	vdso_pagelist = kcalloc(vdso_pages + 1, sizeof(struct page *),
 				GFP_KERNEL);
+	*vdso_pagelistp = vdso_pagelist;
 	if (vdso_pagelist == NULL)
 		return -ENOMEM;
 
@@ -135,7 +146,7 @@ static int __init vdso_init(void)
 
 	/* Grab the vDSO code pages. */
 	for (i = 0; i < vdso_pages; i++)
-		vdso_pagelist[i + 1] = virt_to_page(&vdso_start + i * PAGE_SIZE);
+		vdso_pagelist[i + 1] = virt_to_page(vdso_start + i * PAGE_SIZE);
 
 	/* Populate the special mapping structures */
 	vdso_spec[0] = (struct vm_special_mapping) {
@@ -150,16 +161,46 @@ static int __init vdso_init(void)
 
 	return 0;
 }
+
+static struct vm_special_mapping vdso_spec[2];
+
+static int __init vdso_init(void)
+{
+	return vdso_init_common(&vdso_start, &vdso_end,
+				&vdso_pages, &vdso_pagelist,
+				vdso_spec);
+}
 arch_initcall(vdso_init);
 
+#ifdef CONFIG_ARM64_ILP32
+static struct vm_special_mapping vdso_ilp32_spec[2];
+
+static int __init vdso_ilp32_init(void)
+{
+	return vdso_init_common(&vdso_ilp32_start, &vdso_ilp32_end,
+				&vdso_ilp32_pages, &vdso_ilp32_pagelist,
+				vdso_ilp32_spec);
+}
+arch_initcall(vdso_ilp32_init);
+#endif
+
 int arch_setup_additional_pages(struct linux_binprm *bprm,
 				int uses_interp)
 {
 	struct mm_struct *mm = current->mm;
 	unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
 	void *ret;
+	unsigned long pages = vdso_pages;
+	struct vm_special_mapping *spec = vdso_spec;
+
+#ifdef CONFIG_ARM64_ILP32
+	if (is_ilp32_compat_task()) {
+	        pages = vdso_ilp32_pages;
+	        spec = vdso_ilp32_spec;
+	}
+#endif
 
-	vdso_text_len = vdso_pages << PAGE_SHIFT;
+	vdso_text_len = pages << PAGE_SHIFT;
 	/* Be sure to map the data page */
 	vdso_mapping_len = vdso_text_len + PAGE_SIZE;
 
@@ -171,7 +212,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	}
 	ret = _install_special_mapping(mm, vdso_base, PAGE_SIZE,
 				       VM_READ|VM_MAYREAD,
-				       &vdso_spec[0]);
+				       &spec[0]);
 	if (IS_ERR(ret))
 		goto up_fail;
 
@@ -180,7 +221,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	ret = _install_special_mapping(mm, vdso_base, vdso_text_len,
 				       VM_READ|VM_EXEC|
 				       VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
-				       &vdso_spec[1]);
+				       &spec[1]);
 	if (IS_ERR(ret))
 		goto up_fail;
 
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index efa79e8..a2d8a70 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -25,6 +25,16 @@
 #define NSEC_PER_SEC_LO16	0xca00
 #define NSEC_PER_SEC_HI16	0x3b9a
 
+#ifdef __LP64__
+#define PTR_REG(n)	x##n
+#define OFFSET(n)	n
+#define DELOUSE(n)
+#else
+#define PTR_REG(n)	w##n
+#define OFFSET(n)	COMPAT_##n
+#define DELOUSE(n)	mov     w##n, w##n
+#endif
+
 vdso_data	.req	x6
 use_syscall	.req	w7
 seqcnt		.req	w8
@@ -51,6 +61,8 @@ seqcnt		.req	w8
 /* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */
 ENTRY(__kernel_gettimeofday)
 	.cfi_startproc
+	DELOUSE(0)
+	DELOUSE(1)
 	mov	x2, x30
 	.cfi_register x30, x2
 
@@ -68,7 +80,7 @@ ENTRY(__kernel_gettimeofday)
 	mov	x13, #1000
 	lsl	x13, x13, x12
 	udiv	x11, x11, x13
-	stp	x10, x11, [x0, #TVAL_TV_SEC]
+	stp	PTR_REG(10), PTR_REG(11), [x0, #OFFSET(TVAL_TV_SEC)]
 2:
 	/* If tz is NULL, return 0. */
 	cbz	x1, 3f
@@ -88,6 +100,7 @@ ENDPROC(__kernel_gettimeofday)
 /* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */
 ENTRY(__kernel_clock_gettime)
 	.cfi_startproc
+	DELOUSE(1)
 	cmp	w0, #CLOCK_REALTIME
 	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
 	b.ne	2f
@@ -159,7 +172,7 @@ ENTRY(__kernel_clock_gettime)
 
 6:	/* Store to the user timespec. */
 	lsr	x11, x11, x12
-	stp	x10, x11, [x1, #TSPEC_TV_SEC]
+	stp	PTR_REG(10), PTR_REG(11), [x1, #OFFSET(TSPEC_TV_SEC)]
 	mov	x0, xzr
 	ret
 7:
@@ -174,6 +187,7 @@ ENDPROC(__kernel_clock_gettime)
 /* int __kernel_clock_getres(clockid_t clock_id, struct timespec *res); */
 ENTRY(__kernel_clock_getres)
 	.cfi_startproc
+	DELOUSE(1)
 	cmp	w0, #CLOCK_REALTIME
 	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
 	b.ne	1f
@@ -187,7 +201,7 @@ ENTRY(__kernel_clock_getres)
 	ldr	x2, 6f
 2:
 	cbz	w1, 3f
-	stp	xzr, x2, [x1]
+	stp	PTR_REG(zr), PTR_REG(2), [x1]
 
 3:	/* res == NULL. */
 	mov	w0, wzr
-- 
2.5.0



From horms at verge.net.au  Mon May 23 17:13:09 2016
From: horms at verge.net.au (Simon Horman)
Date: Tue, 24 May 2016 09:13:09 +0900
Subject: [PATCH v2 11/23] ARM: dts: armadillo800eva: Fix W=1 dtc warnings
In-Reply-To: <CAMuHMdXPhMToHhZggdKo=i65nS_mQT1o44YBd_Lz-B2Td3Jm9Q@mail.gmail.com>
References: <1463728214-13838-1-git-send-email-geert+renesas@glider.be>
 <1463728214-13838-12-git-send-email-geert+renesas@glider.be>
 <e0a1fbc1-ac95-2c79-65ed-d0328679bb8a@cogentembedded.com>
 <CAMuHMdXPhMToHhZggdKo=i65nS_mQT1o44YBd_Lz-B2Td3Jm9Q@mail.gmail.com>
Message-ID: <20160524001309.GA2477@verge.net.au>

On Mon, May 23, 2016 at 02:52:20PM +0200, Geert Uytterhoeven wrote:
> On Fri, May 20, 2016 at 5:38 PM, Sergei Shtylyov
> <sergei.shtylyov at cogentembedded.com> wrote:
> > On 05/20/2016 10:10 AM, Geert Uytterhoeven wrote:
> >> Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
> >> Warning (unit_address_vs_reg): Node /regulator at 0 has a unit name, but no reg property
> >> Warning (unit_address_vs_reg): Node /regulator at 1 has a unit name, but no reg property
> >> Warning (unit_address_vs_reg): Node /regulator at 2 has a unit name, but no reg property
> >> Warning (unit_address_vs_reg): Node /regulator at 3 has a unit name, but no reg property
> >> Warning (unit_address_vs_reg): Node /i2c at 2 has a unit name, but no reg property
> >>
> >> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
> >> ---
> >> v2:
> >>   - No changes.
> >> ---
> >>  arch/arm/boot/dts/r8a7740-armadillo800eva.dts | 12 ++++++------
> >>  1 file changed, 6 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
> >> b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
> >> index 2c82dab2b6f45f9c..b3f0ac4b99bd5a3d 100644
> >> --- a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
> >> +++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
> >
> > [...]
> >>
> >> @@ -127,7 +127,7 @@
> >>                 };
> >>         };
> >>
> >> -       i2c2: i2c at 2 {
> >> +       i2c2: i2c2 {
> >
> >    Not "i2c-2" as in the other patches?
> 
> Oops... Thanks for noticing!
> 
> Simon: Do you want me to repost the whole series once again, or
> can you fix this up while applying?

I'll just fix it up.
No need to repost for this.


From horms at verge.net.au  Mon May 23 17:33:57 2016
From: horms at verge.net.au (Simon Horman)
Date: Tue, 24 May 2016 09:33:57 +0900
Subject: [PATCH v2 11/23] ARM: dts: armadillo800eva: Fix W=1 dtc warnings
In-Reply-To: <20160524001309.GA2477@verge.net.au>
References: <1463728214-13838-1-git-send-email-geert+renesas@glider.be>
 <1463728214-13838-12-git-send-email-geert+renesas@glider.be>
 <e0a1fbc1-ac95-2c79-65ed-d0328679bb8a@cogentembedded.com>
 <CAMuHMdXPhMToHhZggdKo=i65nS_mQT1o44YBd_Lz-B2Td3Jm9Q@mail.gmail.com>
 <20160524001309.GA2477@verge.net.au>
Message-ID: <20160524003356.GB2477@verge.net.au>

On Tue, May 24, 2016 at 09:13:09AM +0900, Simon Horman wrote:
> On Mon, May 23, 2016 at 02:52:20PM +0200, Geert Uytterhoeven wrote:
> > On Fri, May 20, 2016 at 5:38 PM, Sergei Shtylyov
> > <sergei.shtylyov at cogentembedded.com> wrote:
> > > On 05/20/2016 10:10 AM, Geert Uytterhoeven wrote:
> > >> Warning (unit_address_vs_reg): Node /memory has a reg or ranges property, but no unit name
> > >> Warning (unit_address_vs_reg): Node /regulator at 0 has a unit name, but no reg property
> > >> Warning (unit_address_vs_reg): Node /regulator at 1 has a unit name, but no reg property
> > >> Warning (unit_address_vs_reg): Node /regulator at 2 has a unit name, but no reg property
> > >> Warning (unit_address_vs_reg): Node /regulator at 3 has a unit name, but no reg property
> > >> Warning (unit_address_vs_reg): Node /i2c at 2 has a unit name, but no reg property
> > >>
> > >> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
> > >> ---
> > >> v2:
> > >>   - No changes.
> > >> ---
> > >>  arch/arm/boot/dts/r8a7740-armadillo800eva.dts | 12 ++++++------
> > >>  1 file changed, 6 insertions(+), 6 deletions(-)
> > >>
> > >> diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
> > >> b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
> > >> index 2c82dab2b6f45f9c..b3f0ac4b99bd5a3d 100644
> > >> --- a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
> > >> +++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
> > >
> > > [...]
> > >>
> > >> @@ -127,7 +127,7 @@
> > >>                 };
> > >>         };
> > >>
> > >> -       i2c2: i2c at 2 {
> > >> +       i2c2: i2c2 {
> > >
> > >    Not "i2c-2" as in the other patches?
> > 
> > Oops... Thanks for noticing!
> > 
> > Simon: Do you want me to repost the whole series once again, or
> > can you fix this up while applying?
> 
> I'll just fix it up.
> No need to repost for this.

I have queued this up with the above hunk changed to the following.
Please check the resulting patch and let me know if I've messed things up
somehow.

@@ -127,7 +127,7 @@
 		};
 	};
 
-	i2c2: i2c at 2 {
+	i2c2: i2c-2 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "i2c-gpio";


From horms at verge.net.au  Mon May 23 17:34:11 2016
From: horms at verge.net.au (Simon Horman)
Date: Tue, 24 May 2016 09:34:11 +0900
Subject: [PATCH v2 00/23] ARM/arm64: dts: renesas: Fix W=1 dtc warnings
In-Reply-To: <1463728214-13838-1-git-send-email-geert+renesas@glider.be>
References: <1463728214-13838-1-git-send-email-geert+renesas@glider.be>
Message-ID: <20160524003410.GC2477@verge.net.au>

On Fri, May 20, 2016 at 09:09:51AM +0200, Geert Uytterhoeven wrote:
> 	Hi Simon, Magnus, Morimoto-san, Rob,
> 
> This patch series fixes the new warnings related to Renesas arm32/arm64
> DTSes that can be seen in -next using "make W=1 dtbs", courtesy of
> commit b993734718c01064 ("scripts/dtc: Update to upstream version
> 53bf130b1cdd") in Rob herring's for-next branch. For testing, you can just
> cherry-pick that commit (showing the warning for W=1 only was a separate
> commit).

Thanks, I have queued this up.


From hotran at apm.com  Mon May 23 18:01:14 2016
From: hotran at apm.com (Hoan Tran)
Date: Mon, 23 May 2016 18:01:14 -0700
Subject: [PATCH 1/3] Documentation: dtb: xgene: Add hwmon dts binding
 documentation
In-Reply-To: <20160523203044.GA17450@rob-hp-laptop>
References: <1463415447-29903-1-git-send-email-hotran@apm.com>
 <1463415447-29903-2-git-send-email-hotran@apm.com>
 <20160523203044.GA17450@rob-hp-laptop>
Message-ID: <CAFHUOYyYt8pE6sggezCR=TFcsimcjakbYmcWFtpLyQ3Et_gZaA@mail.gmail.com>

Hi Rob,

Thanks for your review !

On Mon, May 23, 2016 at 1:30 PM, Rob Herring <robh at kernel.org> wrote:
>
> On Mon, May 16, 2016 at 09:17:25AM -0700, Hoan Tran wrote:
> > This patch adds the APM X-Gene hwmon device tree node documentation.
> >
> > Signed-off-by: Hoan Tran <hotran at apm.com>
> > ---
> >  .../devicetree/bindings/hwmon/apm-xgene-hwmon.txt          | 14 ++++++++++++++
> >  1 file changed, 14 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt
> >
> > diff --git a/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt b/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt
> > new file mode 100644
> > index 0000000..49a482e
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt
> > @@ -0,0 +1,14 @@
> > +APM X-Gene hwmon driver
> > +
> > +Hwmon driver accesses sensors over the "SLIMpro" mailbox.
>
> DT bindings describe h/w, not driver data.
How about this description: "APM X-Gene SOC sensors are accessed over
the "SLIMpro" mailbox" ?
> I'm not sure this belongs in
> DT and perhaps the devices for the mailbox should be created by the
> mailbox driver.
I don't think the current mailbox supports it.
>
> > +
> > +Required properties :
> > + - compatible : should be "apm,xgene-slimpro-hwmon"
> > + - mboxes : use the label reference for the mailbox as the first parameter.
> > +         The second parameter is the channel number.
>
> When do you expect this to be different mailbox numbers?
No, this number is not changed. This "mboxes" property is used and
required by mailbox.c when hwmon driver requests a mailbox channel

Thanks and Regards
Hoan
>
>
> > +
> > +Example :
> > +     hwmonslimpro {
> > +             compatible = "apm,xgene-slimpro-hwmon";
> > +             mboxes = <&mailbox 7>;
> > +     };
> > --
> > 1.9.1
> >


From jcm at redhat.com  Mon May 23 18:11:13 2016
From: jcm at redhat.com (Jon Masters)
Date: Mon, 23 May 2016 21:11:13 -0400 (EDT)
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <20160523233918.GA32555@localhost>
References: <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>
 <20160523233918.GA32555@localhost>
Message-ID: <426907D3-FBE7-458F-AB94-F64489AB0337@redhat.com>

Bjorn,

Out walking so sorry about top posting. Quick reply though:

1. I checked with the Windows team. They usually avoid quirks entirely but when it has happened, it has been done via the MCFG/FADT not DSDT.

2. They would be ok if we were to key off the OEM  name and revision for the IP in the MCFG table.

3. I have already verified existing shipping ARMv8 systems provide enough unique data in that entry, and have asked that vendors guarantee to rev it in future IP (which I will verify on models pre tapeout and certainly in early firmware builds). One vendor has a platform that isn't public yet that uses a non-public name in the MCFG but I spoke with them on Friday and they will shortly update their firmware so that a quirk could be posted.

4. I have requested (and Linaro are investigating) that Linaro (with ARM's assistance) begin to drive a separate thread around upstreaming (independent of this core effort) quirks that use the OEM fields in the MCFG as a more scalable approach than one per platform via DMI.

5. I will drive a clarification to the SBBR that does not encourage or endorse quirks but does merely reinforce that data must be unique in such tables. I am driving a separate series of conversations with vendors to ensure that this is the case on all future platforms - though just generally, there is no more high end top shelf "Xeon class" silicon needing common quirks in the pipeline.

More later.

Jon.

-- 
Computer Architect | Sent from my 64-bit #ARM Powered phone

> On May 23, 2016, at 19:39, Bjorn Helgaas <helgaas at kernel.org> wrote:
> 
>> On Mon, May 23, 2016 at 03:16:01PM +0000, Gabriele Paoloni wrote:
>> Hi Lorenzo
>> 
>>> -----Original Message-----
>>> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
>>> Sent: 23 May 2016 11:57
>>> To: Ard Biesheuvel
>>> Cc: Gabriele Paoloni; Jon Masters; Tomasz Nowicki; helgaas at kernel.org;
>>> arnd at arndb.de; will.deacon at arm.com; catalin.marinas at arm.com;
>>> rafael at kernel.org; hanjun.guo at linaro.org; okaya at codeaurora.org;
>>> jchandra at broadcom.com; linaro-acpi at lists.linaro.org; linux-
>>> pci at vger.kernel.org; dhdang at apm.com; Liviu.Dudau at arm.com;
>>> ddaney at caviumnetworks.com; jeremy.linton at arm.com; linux-
>>> kernel at vger.kernel.org; linux-acpi at vger.kernel.org;
>>> robert.richter at caviumnetworks.com; Suravee.Suthikulpanit at amd.com;
>>> msalter at redhat.com; Wangyijing; mw at semihalf.com;
>>> andrea.gallo at linaro.org; linux-arm-kernel at lists.infradead.org
>>> Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI host
>>> controller
>>> 
>>>> On Fri, May 20, 2016 at 11:14:03AM +0200, Ard Biesheuvel wrote:
>>>> On 20 May 2016 at 10:40, Gabriele Paoloni
>>> <gabriele.paoloni at huawei.com> wrote:
>>>>> Hi Ard
>>>>> 
>>>>>> -----Original Message-----
>>>>>> From: Ard Biesheuvel [mailto:ard.biesheuvel at linaro.org]
>>>> [...]
>>>>>> 
>>>>>> Is the PCIe root complex so special that you cannot simply
>>> describe an
>>>>>> implementation that is not PNP0408 compatible as something else,
>>> under
>>>>>> its own unique HID? If everybody is onboard with using ACPI, how
>>> is
>>>>>> this any different from describing other parts of the platform
>>>>>> topology? Even if the SBSA mandates generic PCI, they already
>>> deviated
>>>>>> from that when they built the hardware, so pretending that it is a
>>>>>> PNP0408 with quirks really does not buy us anything.
>>>>> 
>>>>> From my understanding we want to avoid this as this would allow
>>> each
>>>>> vendor to come up with his own code and it would be much more
>>> effort
>>>>> for the PCI maintainer to rework the PCI framework to accommodate
>>> X86
>>>>> and "all" ARM64 Host Controllers...
>>>>> 
>>>>> I guess this approach is too risky and we want to avoid this.
>>> Through
>>>>> standardization we can more easily maintain the code and scale it
>>> to
>>>>> multiple SoCs...
>>>>> 
>>>>> So this is my understanding; maybe Jon, Tomasz or Lorenzo can give
>>>>> a bit more explanation...
>>>> 
>>>> OK, so that boils down to recommending to vendors to represent known
>>>> non-compliant hardware as compliant, just so that we don't have to
>>>> change the code to support additional flavors of ECAM ? It's fine to
>>>> be pragmatic, but that sucks.
>>>> 
>>>> We keep confusing the x86 case with the ARM case here: for x86, they
>>>> needed to deal with broken hardware *after* the fact, and all they
>>>> could do is find /some/ distinguishing feature in order to guess
>>> which
>>>> exact hardware they might be running on. For arm64, it is the
>>> opposite
>>>> case. We are currently in a position where we can demand vendors to
>>>> comply with the standards they endorsed themselves, and (ab)using
>>> ACPI
>>>> + DMI as a de facto platform description rather than plain ACPI makes
>>>> me think the DT crowd were actually right from the beginning. It
>>>> *directly* violates the standardization principle, since it requires
>>> a
>>>> priori knowledge inside the OS that a certain 'generic' device must
>>> be
>>>> driven in a special way.
>>>> 
>>>> So can anyone comment on the feasibility of adding support for
>>> devices
>>>> with vendor specific HIDs (and no generic CIDs) to the current ACPI
>>>> ECAM driver in Linux?
> 
> I don't think of ECAM support itself as a "driver".  It's just a
> service available to drivers, similar to OF resource parsing.
> 
> Per PCI Firmware r3.2, sec 4.1.5, "PNP0A03" means a PCI/PCI-X/PCIe
> host bridge.  "PNP0A08" means a PCI-X Mode 2 or PCIe bridge that
> supports extended config space.  It doesn't specify how we access that
> config space, so I think hardware with non-standard ECAM should still
> have PNP0A03 and PNP0A08 in _CID or _HID.
> 
> "ECAM" as used in the specs (PCIe r3.0, sec 7.2.2, and PCI Firmware
> r3.2, sec 4.1) means:
> 
>  (a) a memory-mapped model for config space access, and
>  (b) a specific mapping of address bits to bus/device/function/
>      register
> 
> MCFG and _CBA assume both (a) and (b), so I think a device with
> non-standard ECAM mappings should not be described in MCFG or _CBA.
> 
> If a bridge has ECAM with non-standard mappings, I think either a
> vendor-specific _HID or a device-specific method, e.g., _DSM, could
> communicate that.
> 
> Jon, I agree that we should avoid describing non-standardized hardware
> in Linux-specific ways.  Is there a mechanism in use already?  How
> does Windows handle this?  DMI is a poor long-term solution because it
> requires ongoing maintenance for new platforms, but I think it's OK
> for getting started with platforms already shipping.
> 
> A _DSM has the advantage that once it is defined and supported, OEMs
> can ship new platforms without requiring a new quirk or a new _HID to
> be added to a driver.
> 
> There would still be the problem of config access before the namespace
> is available, i.e., the MCFG use case.  I don't know how important
> that is.  Defining an MCFG extension seems like the most obvious
> solution.
> 
> If we only expect a few non-standard devices, maybe it's enough to
> have DMI quirks to statically set up ECAM and just live with the
> inconvenience of requiring a kernel change for every new non-standard
> device.
> 
>>> Host bridges in ACPI are handled through PNP0A08/PNP0A03 ids, and
>>> most of the arch specific code is handled in the respective arch
>>> directories (X86 and IA64, even though IA64 does not rely on ECAM/MCFG
>>> for
>>> PCI ops), it is not a driver per-se, PNP0A08/PNP0A03 are detected
>>> through
>>> ACPI scan handlers and the respective arch code (ie pci_acpi_scan_root)
>>> sets-up resources AND config space on an arch specific basis.
>>> 
>>> X86 deals with that with code in arch/x86 that sets-up the pci_raw_ops
>>> on a platform specific basis (and it is not nice, but it works because
>>> as you all know the number of platforms in X86 world is contained).
>>> 
>>> Will this happen for ARM64 in arch/arm64 based on vendor specific
>>> HIDs ?
>>> 
>>> No.
>>> 
>>> So given the current state of play (we were requested to move the
>>> arch/arm64 specific ACPI PCI bits to arch/arm64), we would end up
>>> with arch/arm64 code requiring code in /drivers to set-up pci_ops
>>> in a platform specific way, it is horrible, if feasible at all.
>>> 
>>> The only way this can be implemented is by pretending that the
>>> ACPI/PCI arch/arm64 implementation is generic code (that's what this
>>> series does), move it to /drivers (where it is in this series), and
>>> implement _DSD vendor specific bindings (per HID) to set-up the pci
>>> operations; whether this solution should go upstream, given that it
>>> is just a short-term solution for early platforms bugs, it is another
>>> story and my personal answer is no.
> 
> It seems like there should be a way to look for a _DSM before we call
> acpi_pci_root_get_mcfg_addr() to look for _CBA.
> 
> Currently we call acpi_pci_root_get_mcfg_addr() (to read _CBA) from
> the generic acpi_pci_root_add(), but the result (root->mcfg_addr) is
> only used in x86-specific code.  I think it would be nicer if the
> lookup and the use were together.  Then it would be easier to override
> it because the mapping assumptions would all be in one place.
> 
>> I think it shouldn't be too bad to move quirk handling mechanism to
>> arch/arm64. Effectively we would not move platform specific code into
>> arch/arm64 but just the mechanism checking if there is any quirk that
>> is defined.
>> 
>> i.e.:
>> 
>> extern struct pci_cfg_fixup __start_acpi_mcfg_fixups[];
>> extern struct pci_cfg_fixup __end_acpi_mcfg_fixups[];
>> 
>> static struct pci_ecam_ops *pci_acpi_get_ops(struct acpi_pci_root *root)
>> {
>>        int bus_num = root->secondary.start;
>>        int domain = root->segment;
>>        struct pci_cfg_fixup *f;
>> 
>>        /*
>>         * Match against platform specific quirks and return corresponding
>>         * CAM ops.
>>         *
>>         * First match against PCI topology <domain:bus> then use DMI or
>>         * custom match handler.
>>         */
>>        for (f = __start_acpi_mcfg_fixups; f < __end_acpi_mcfg_fixups; f++) {
>>                if ((f->domain == domain || f->domain == PCI_MCFG_DOMAIN_ANY) &&
>>                    (f->bus_num == bus_num || f->bus_num == PCI_MCFG_BUS_ANY) &&
>>                    (f->system ? dmi_check_system(f->system) : 1) &&
>>                    (f->match ? f->match(f, root) : 1))
>>                        return f->ops;
>>        }
>>        /* No quirks, use ECAM */
>>        return &pci_generic_ecam_ops;
>> }
>> 
>> Such quirks will be defined anyway in drivers/pci/host/ in the vendor
>> specific quirk implementations.
>> 
>> e.g. in HiSilicon case we would have
>> 
>> DECLARE_ACPI_MCFG_FIXUP(NULL, hisi_pcie_match, &hisi_pcie_ecam_ops,
>>            PCI_MCFG_DOMAIN_ANY, PCI_MCFG_BUS_ANY);
>> 
>> in "drivers/pci/host/pcie-hisi-acpi.c "
>> 
>> Thanks
>> 
>> Gab
> 
> Sorry Gab, I guess I was really responding to earlier messages :)
> 
> I don't really have much to say here, except that it doesn't seem
> right to have an MCFG that describes a non-standard ECAM mapping.
> I suppose there's already firmware in the field that does that,
> though?
> 
> Bjorn


From henryc.chen at mediatek.com  Mon May 23 18:33:39 2016
From: henryc.chen at mediatek.com (Henry Chen)
Date: Tue, 24 May 2016 09:33:39 +0800
Subject: [PATCH] regulator: mt6397: Constify struct regulator_ops
In-Reply-To: <20160523113222.GT8206@sirena.org.uk>
References: <1463988616-18803-1-git-send-email-henryc.chen@mediatek.com>
 <20160523113222.GT8206@sirena.org.uk>
Message-ID: <1464053619.18442.11.camel@mtksdaap41>

Hi Mark,

On Mon, 2016-05-23 at 12:32 +0100, Mark Brown wrote:
> On Mon, May 23, 2016 at 03:30:16PM +0800, Henry Chen wrote:
> > Consitify the structure of regulator operations.
> 
> Oh, actually the mode setting patch does apply but it depends on this
> one (which was sent after...).  It would have been better to send a
> patch series for the driver and separately a patch series for the core,
> the driver changes are orthogonal to the core ones here.

Got it. Sorry for unawareness of the dependency issue and thanks for
kindly reminder.




From zhengxing at rock-chips.com  Mon May 23 18:36:14 2016
From: zhengxing at rock-chips.com (Xing Zheng)
Date: Tue, 24 May 2016 09:36:14 +0800
Subject: [RESEND PATCH v2] ASoC: rockchip: Add machine driver for
 MAX98357A/RT5514/DA7219
Message-ID: <1464053774-15914-1-git-send-email-zhengxing@rock-chips.com>

There are multi codec devices on the RK3399 platform, we can use
this patch support and control these codecs.

Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
---

Changes in v2:
- use the FS 256 to set mclks of the max98357a and rt5514 danamically
- add more sample rate for da7219

 .../sound/rockchip-max98357a-rt5514-da7219.txt     |   15 +
 sound/soc/rockchip/Kconfig                         |   11 +
 sound/soc/rockchip/Makefile                        |    2 +
 .../rockchip/rockchip_max98357a_rt5514_da7219.c    |  333 ++++++++++++++++++++
 4 files changed, 361 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
 create mode 100644 sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c

diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt b/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
new file mode 100644
index 0000000..5928384
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
@@ -0,0 +1,15 @@
+ROCKCHIP with MAX98357A/RT5514/DA7219 codecs
+
+Required properties:
+- compatible: "rockchip,rockchip-sound"
+- rockchip,cpu: The phandle of the Rockchip I2S controller that's
+  connected to the codecs
+- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs
+
+Example:
+
+sound {
+	compatible = "rockchip,rockchip-sound";
+	rockchip,cpu = <&i2s0 &i2s0 &i2s1>;
+	rockchip,codec = <&max98357a &headsetcodec &codec>;
+};
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index f1e0c70..d02aa94 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -41,3 +41,14 @@ config SND_SOC_ROCKCHIP_RT5645
 	help
 	  Say Y or M here if you want to add support for SoC audio on Rockchip
 	  boards using the RT5645/RT5650 codec, such as Veyron.
+
+config SND_SOC_ROCKCHIP_MAX98357A_RT5514_DA7219
+	tristate "ASoC support for Rockchip boards using the MAX98357A/RT5514/DA7219"
+	depends on SND_SOC_ROCKCHIP && GPIOLIB
+	select SND_SOC_ROCKCHIP_I2S
+	select SND_SOC_MAX98357A
+	select SND_SOC_RT5514
+	select SND_SOC_DA7219
+	help
+	  Say Y or M here if you want to add support for SoC audio on Rockchip
+	  boards using the MAX98357A/RT5514/DA7219.
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
index c0bf560..ca97489 100644
--- a/sound/soc/rockchip/Makefile
+++ b/sound/soc/rockchip/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o
 
 snd-soc-rockchip-max98090-objs := rockchip_max98090.o
 snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o
+snd-soc-rockchip-max98357a-rt5514-da7219-objs := rockchip_max98357a_rt5514_da7219.o
 
 obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o
+obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98357A_RT5514_DA7219) += snd-soc-rockchip-max98357a-rt5514-da7219.o
diff --git a/sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c b/sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c
new file mode 100644
index 0000000..818c47e
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c
@@ -0,0 +1,333 @@
+/*
+ * Rockchip machine ASoC driver for boards using MAX98357A/RT5514/DA7219
+ *
+ * Copyright (c) 2016, ROCKCHIP CORPORATION.  All rights reserved.
+ *
+ * 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 <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include "rockchip_i2s.h"
+#include "../codecs/da7219.h"
+#include "../codecs/da7219-aad.h"
+#include "../codecs/rt5514.h"
+
+#define DRV_NAME "rockchip-sound"
+
+#define SOUND_FS	256
+
+static struct snd_soc_jack rockchip_sound_jack;
+
+static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphones", NULL),
+	SND_SOC_DAPM_SPK("Speakers", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Int Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route rockchip_dapm_routes[] = {
+	/* Input Lines */
+	{"MIC", NULL, "Headset Mic"},
+	{"DMIC1L", NULL, "Int Mic"},
+	{"DMIC1R", NULL, "Int Mic"},
+
+	/* Output Lines */
+	{"Headphones", NULL, "HPL"},
+	{"Headphones", NULL, "HPR"},
+	{"Speakers", NULL, "Speakers"},
+};
+
+static const struct snd_kcontrol_new rockchip_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphones"),
+	SOC_DAPM_PIN_SWITCH("Speakers"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Int Mic"),
+};
+
+static int rockchip_sound_max98357a_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_dapm_context *dapm = &rtd->card->dapm;
+	unsigned int mclk;
+	int ret;
+
+	/* max98357a supports these sample rates */
+	switch (params_rate(params)) {
+	case 8000:
+	case 16000:
+	case 48000:
+	case 96000:
+		mclk = params_rate(params) * SOUND_FS;
+		break;
+	default:
+		dev_err(rtd->card->dev, "%s() doesn't support this sample rate: %d\n",
+				__func__, params_rate(params));
+		return -EINVAL;
+	}
+
+	ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0);
+	if (ret) {
+		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
+				__func__, mclk, ret);
+		return ret;
+	}
+
+	snd_soc_dapm_disable_pin(dapm, "Headphones");
+	snd_soc_dapm_enable_pin(dapm, "Speakers");
+	snd_soc_dapm_sync(dapm);
+
+	return 0;
+}
+
+static int rockchip_sound_rt5514_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;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	unsigned int mclk;
+	int ret;
+
+	mclk = params_rate(params) * SOUND_FS;
+
+	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
+				     SND_SOC_CLOCK_OUT);
+	if (ret < 0) {
+		dev_err(rtd->card->dev, "Can't set cpu clock out %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK,
+				     mclk, SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
+				__func__, params_rate(params) * 512, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rockchip_sound_da7219_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;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dapm_context *dapm = &rtd->card->dapm;
+	int mclk, ret;
+
+	/* in bypass mode, the mclk has to be one of the frequencies below */
+	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(codec_dai->dev, "Can't set cpu clock out %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
+				     SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		dev_err(codec_dai->dev, "Can't set codec clock in %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
+	if (ret < 0) {
+		dev_err(codec_dai->dev, "Can't set pll sysclk mclk %d\n", ret);
+		return ret;
+	}
+
+	snd_soc_dapm_disable_pin(dapm, "Speakers");
+	snd_soc_dapm_enable_pin(dapm, "Headphones");
+	snd_soc_dapm_sync(dapm);
+
+	return 0;
+}
+
+static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec_dais[0]->codec;
+	int ret;
+
+	/* Enable Headset and 4 Buttons Jack detection */
+	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
+				    SND_JACK_HEADSET |
+				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
+				    &rockchip_sound_jack, NULL, 0);
+
+	if (ret) {
+		dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
+		return ret;
+	}
+
+	da7219_aad_jack_det(codec, &rockchip_sound_jack);
+
+	return 0;
+}
+
+static struct snd_soc_ops rockchip_sound_max98357a_ops = {
+	.hw_params = rockchip_sound_max98357a_hw_params,
+};
+
+static struct snd_soc_ops rockchip_sound_rt5514_ops = {
+	.hw_params = rockchip_sound_rt5514_hw_params,
+};
+
+static struct snd_soc_ops rockchip_sound_da7219_ops = {
+	.hw_params = rockchip_sound_da7219_hw_params,
+};
+
+enum {
+	DAILINK_MAX98357A,
+	DAILINK_RT5514,
+	DAILINK_DA7219,
+};
+
+static struct snd_soc_dai_link rockchip_dailinks[] = {
+	[DAILINK_MAX98357A] = {
+		.name = "MAX98357A",
+		.stream_name = "MAX98357A PCM",
+		.codec_dai_name = "HiFi",
+		.ops = &rockchip_sound_max98357a_ops,
+		/* set max98357a as slave */
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+	[DAILINK_RT5514] = {
+		.name = "RT5514",
+		.stream_name = "RT5514 PCM",
+		.codec_dai_name = "rt5514-aif1",
+		.ops = &rockchip_sound_rt5514_ops,
+		/* set rt5514 as slave */
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+	[DAILINK_DA7219] = {
+		.name = "DA7219",
+		.stream_name = "DA7219 PCM",
+		.codec_dai_name = "da7219-hifi",
+		.init = rockchip_sound_da7219_init,
+		.ops = &rockchip_sound_da7219_ops,
+		/* set da7219 as slave */
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+};
+
+static struct snd_soc_card rockchip_sound_card = {
+	.name = "rockchip-sound",
+	.owner = THIS_MODULE,
+	.dai_link = rockchip_dailinks,
+	.num_links =  ARRAY_SIZE(rockchip_dailinks),
+	.dapm_widgets = rockchip_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
+	.dapm_routes = rockchip_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes),
+	.controls = rockchip_controls,
+	.num_controls = ARRAY_SIZE(rockchip_controls),
+};
+
+static int rockchip_sound_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &rockchip_sound_card;
+	struct device_node *cpu_node;
+	int i, ret;
+
+	for (i = 0; i < card->num_links; i++) {
+		cpu_node = of_parse_phandle(pdev->dev.of_node,
+					 "rockchip,cpu", i);
+		if (!cpu_node) {
+			dev_err(&pdev->dev, "Property[%d] 'rockchip,cpu' missing or invalid\n", i);
+			return -EINVAL;
+		}
+
+		rockchip_dailinks[i].platform_of_node = cpu_node;
+		rockchip_dailinks[i].cpu_of_node = cpu_node;
+
+		rockchip_dailinks[i].codec_of_node =
+			of_parse_phandle(pdev->dev.of_node, "rockchip,codec", i);
+		if (!rockchip_dailinks[i].codec_of_node) {
+			dev_err(&pdev->dev,
+				"Property[%d] 'rockchip,codec' missing or invalid\n", i);
+			return -EINVAL;
+		}
+	}
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret)
+		dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
+			__func__, ret);
+
+	return ret;
+}
+
+static const struct of_device_id rockchip_sound_of_match[] = {
+	{ .compatible = "rockchip,rockchip-sound", },
+	{},
+};
+
+static struct platform_driver rockchip_sound_driver = {
+	.probe = rockchip_sound_probe,
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = rockchip_sound_of_match,
+#ifdef CONFIG_PM
+		.pm = &snd_soc_pm_ops,
+#endif
+	},
+};
+
+module_platform_driver(rockchip_sound_driver);
+
+MODULE_AUTHOR("Xing Zheng <zhengxing at rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);
-- 
1.7.9.5




From zhengxing at rock-chips.com  Mon May 23 18:38:24 2016
From: zhengxing at rock-chips.com (Xing Zheng)
Date: Tue, 24 May 2016 09:38:24 +0800
Subject: [PATCH v2] ASoC: rockchip: Add machine driver for
 MAX98357A/RT5514/DA7219
In-Reply-To: <6209835.s95gRr0Nsp@phil>
References: <1464014612-14396-1-git-send-email-zhengxing@rock-chips.com>
 <6209835.s95gRr0Nsp@phil>
Message-ID: <5743B090.50401@rock-chips.com>

Hi Heiko,

On 2016?05?23? 22:51, Heiko Stuebner wrote:
> Hi Xing,
>
> Am Montag, 23. Mai 2016, 22:43:32 schrieb Xing Zheng:
>> There are multi codec devices on the RK3399 platform, we can use
>> this patch support and control these codecs.
>>
>> ---
>>
>> Changes in v2:
>> Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
> something seems to have gone wrong here.
>
> The Signed-off needs to be above the "---" and the changelog itself seems
> empty while at least the number of lines in your
> rockchip_max98357a_rt5514_da7219.c seems to have changed.
>
Sorry to forgot to add the changelog. I resent this patch_v2.

Thank you for your reminding.

-- 
- Xing Zheng




From horms at verge.net.au  Mon May 23 18:42:53 2016
From: horms at verge.net.au (Simon Horman)
Date: Tue, 24 May 2016 10:42:53 +0900
Subject: [PATCH v2 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <5742B66C.7080102@rvc.renesas.com>
References: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>
 <1463966906-15129-2-git-send-email-horms+renesas@verge.net.au>
 <CAMuHMdXsu=O13rLysob1Xp+5vWcp7gq6byCffR-6hGc+W-837A@mail.gmail.com>
 <5742B66C.7080102@rvc.renesas.com>
Message-ID: <20160524014249.GA22751@verge.net.au>

On Mon, May 23, 2016 at 02:51:08PM +0700, Khiem Nguyen wrote:
> Hi Simon, Geert,
> 
> On 5/23/2016 2:07 PM, Geert Uytterhoeven wrote:
> >On Mon, May 23, 2016 at 3:28 AM, Simon Horman
> ><horms+renesas at verge.net.au> wrote:
> >>Basic support for the Gen 3 R-Car M3-W SoC.
> >>
> >>Based on work for the r8a7795 and r8a7796 SoCs by
> >>Takeshi Kihara, Dirk Behme and Geert Uytterhoeven.
> >>
> >>Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
> >
> >>--- /dev/null
> >>+++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> >>@@ -0,0 +1,120 @@
> >>+       psci {
> >>+               compatible = "arm,psci-1.0";
> >
> >Do we want to use 1.0 on r8a7795, too?
> 
> I think we should apply same setting as r8a7795.
> i.e compatible = "arm,psci-0.2";
> 
> Using 1.0 will open Suspend-to-RAM support if secure firmware supports that
> feature.
> However, we might need additional work in drivers to support suspend/resume
> handlers.
> So, I suggest that we keep using 0.2 until Suspend-to-RAM feature is
> confirmed in r8a7795/r8a7796.

Sure, I will use 0.2.


From horms at verge.net.au  Mon May 23 18:44:28 2016
From: horms at verge.net.au (Simon Horman)
Date: Tue, 24 May 2016 10:44:28 +0900
Subject: [PATCH v2 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <CAMuHMdXsu=O13rLysob1Xp+5vWcp7gq6byCffR-6hGc+W-837A@mail.gmail.com>
References: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>
 <1463966906-15129-2-git-send-email-horms+renesas@verge.net.au>
 <CAMuHMdXsu=O13rLysob1Xp+5vWcp7gq6byCffR-6hGc+W-837A@mail.gmail.com>
Message-ID: <20160524014427.GB22751@verge.net.au>

On Mon, May 23, 2016 at 09:07:20AM +0200, Geert Uytterhoeven wrote:
> On Mon, May 23, 2016 at 3:28 AM, Simon Horman
> <horms+renesas at verge.net.au> wrote:
> > Basic support for the Gen 3 R-Car M3-W SoC.
> >
> > Based on work for the r8a7795 and r8a7796 SoCs by
> > Takeshi Kihara, Dirk Behme and Geert Uytterhoeven.
> >
> > Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
> 
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> > @@ -0,0 +1,120 @@
> > +       psci {
> > +               compatible = "arm,psci-1.0";
> 
> Do we want to use 1.0 on r8a7795, too?
> 
> > +               method = "smc";
> > +       };
> 
> > +       soc {
> > +               compatible = "simple-bus";
> > +               interrupt-parent = <&gic>;
> > +               #address-cells = <2>;
> > +               #size-cells = <2>;
> > +               ranges;
> > +
> > +               gic: interrupt-controller at 0xf1010000 {
> 
> If you drop the "0x" (which is BTW also present in r8a7795.dtsi), you can add
> my
> Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

Deal :)


From jcm at redhat.com  Mon May 23 18:48:26 2016
From: jcm at redhat.com (Jon Masters)
Date: Mon, 23 May 2016 21:48:26 -0400 (EDT)
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <426907D3-FBE7-458F-AB94-F64489AB0337@redhat.com>
References: <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>
 <20160523233918.GA32555@localhost>
 <426907D3-FBE7-458F-AB94-F64489AB0337@redhat.com>
Message-ID: <7D3F6BBE-A810-489F-A257-AD305B21A288@redhat.com>

Additional: I would like to thank Ard for suggesting this approach. It turns out (apparently) that Mark Salter's initial X-Gene quirks internal to RH did it this way as well. You great minds think alike. If this works for folks then I hope it leads to upstream kernel support in F25 (we have a bunch of Moonshot hardware we would like to deeply in Fedora but can't without the PCIe network...). I rant only because I care :)

Jon.

-- 
Computer Architect | Sent from my 64-bit #ARM Powered phone

> On May 23, 2016, at 21:11, Jon Masters <jcm at redhat.com> wrote:
> 
> Bjorn,
> 
> Out walking so sorry about top posting. Quick reply though:
> 
> 1. I checked with the Windows team. They usually avoid quirks entirely but when it has happened, it has been done via the MCFG/FADT not DSDT.
> 
> 2. They would be ok if we were to key off the OEM  name and revision for the IP in the MCFG table.
> 
> 3. I have already verified existing shipping ARMv8 systems provide enough unique data in that entry, and have asked that vendors guarantee to rev it in future IP (which I will verify on models pre tapeout and certainly in early firmware builds). One vendor has a platform that isn't public yet that uses a non-public name in the MCFG but I spoke with them on Friday and they will shortly update their firmware so that a quirk could be posted.
> 
> 4. I have requested (and Linaro are investigating) that Linaro (with ARM's assistance) begin to drive a separate thread around upstreaming (independent of this core effort) quirks that use the OEM fields in the MCFG as a more scalable approach than one per platform via DMI.
> 
> 5. I will drive a clarification to the SBBR that does not encourage or endorse quirks but does merely reinforce that data must be unique in such tables. I am driving a separate series of conversations with vendors to ensure that this is the case on all future platforms - though just generally, there is no more high end top shelf "Xeon class" silicon needing common quirks in the pipeline.
> 
> More later.
> 
> Jon.
> 
> -- 
> Computer Architect | Sent from my 64-bit #ARM Powered phone
> 
>>> On May 23, 2016, at 19:39, Bjorn Helgaas <helgaas at kernel.org> wrote:
>>> 
>>> On Mon, May 23, 2016 at 03:16:01PM +0000, Gabriele Paoloni wrote:
>>> Hi Lorenzo
>>> 
>>>> -----Original Message-----
>>>> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
>>>> Sent: 23 May 2016 11:57
>>>> To: Ard Biesheuvel
>>>> Cc: Gabriele Paoloni; Jon Masters; Tomasz Nowicki; helgaas at kernel.org;
>>>> arnd at arndb.de; will.deacon at arm.com; catalin.marinas at arm.com;
>>>> rafael at kernel.org; hanjun.guo at linaro.org; okaya at codeaurora.org;
>>>> jchandra at broadcom.com; linaro-acpi at lists.linaro.org; linux-
>>>> pci at vger.kernel.org; dhdang at apm.com; Liviu.Dudau at arm.com;
>>>> ddaney at caviumnetworks.com; jeremy.linton at arm.com; linux-
>>>> kernel at vger.kernel.org; linux-acpi at vger.kernel.org;
>>>> robert.richter at caviumnetworks.com; Suravee.Suthikulpanit at amd.com;
>>>> msalter at redhat.com; Wangyijing; mw at semihalf.com;
>>>> andrea.gallo at linaro.org; linux-arm-kernel at lists.infradead.org
>>>> Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI host
>>>> controller
>>>> 
>>>>> On Fri, May 20, 2016 at 11:14:03AM +0200, Ard Biesheuvel wrote:
>>>>> On 20 May 2016 at 10:40, Gabriele Paoloni
>>>> <gabriele.paoloni at huawei.com> wrote:
>>>>>> Hi Ard
>>>>>> 
>>>>>>> -----Original Message-----
>>>>>>> From: Ard Biesheuvel [mailto:ard.biesheuvel at linaro.org]
>>>>> [...]
>>>>>>> 
>>>>>>> Is the PCIe root complex so special that you cannot simply
>>>> describe an
>>>>>>> implementation that is not PNP0408 compatible as something else,
>>>> under
>>>>>>> its own unique HID? If everybody is onboard with using ACPI, how
>>>> is
>>>>>>> this any different from describing other parts of the platform
>>>>>>> topology? Even if the SBSA mandates generic PCI, they already
>>>> deviated
>>>>>>> from that when they built the hardware, so pretending that it is a
>>>>>>> PNP0408 with quirks really does not buy us anything.
>>>>>> 
>>>>>> From my understanding we want to avoid this as this would allow
>>>> each
>>>>>> vendor to come up with his own code and it would be much more
>>>> effort
>>>>>> for the PCI maintainer to rework the PCI framework to accommodate
>>>> X86
>>>>>> and "all" ARM64 Host Controllers...
>>>>>> 
>>>>>> I guess this approach is too risky and we want to avoid this.
>>>> Through
>>>>>> standardization we can more easily maintain the code and scale it
>>>> to
>>>>>> multiple SoCs...
>>>>>> 
>>>>>> So this is my understanding; maybe Jon, Tomasz or Lorenzo can give
>>>>>> a bit more explanation...
>>>>> 
>>>>> OK, so that boils down to recommending to vendors to represent known
>>>>> non-compliant hardware as compliant, just so that we don't have to
>>>>> change the code to support additional flavors of ECAM ? It's fine to
>>>>> be pragmatic, but that sucks.
>>>>> 
>>>>> We keep confusing the x86 case with the ARM case here: for x86, they
>>>>> needed to deal with broken hardware *after* the fact, and all they
>>>>> could do is find /some/ distinguishing feature in order to guess
>>>> which
>>>>> exact hardware they might be running on. For arm64, it is the
>>>> opposite
>>>>> case. We are currently in a position where we can demand vendors to
>>>>> comply with the standards they endorsed themselves, and (ab)using
>>>> ACPI
>>>>> + DMI as a de facto platform description rather than plain ACPI makes
>>>>> me think the DT crowd were actually right from the beginning. It
>>>>> *directly* violates the standardization principle, since it requires
>>>> a
>>>>> priori knowledge inside the OS that a certain 'generic' device must
>>>> be
>>>>> driven in a special way.
>>>>> 
>>>>> So can anyone comment on the feasibility of adding support for
>>>> devices
>>>>> with vendor specific HIDs (and no generic CIDs) to the current ACPI
>>>>> ECAM driver in Linux?
>> 
>> I don't think of ECAM support itself as a "driver".  It's just a
>> service available to drivers, similar to OF resource parsing.
>> 
>> Per PCI Firmware r3.2, sec 4.1.5, "PNP0A03" means a PCI/PCI-X/PCIe
>> host bridge.  "PNP0A08" means a PCI-X Mode 2 or PCIe bridge that
>> supports extended config space.  It doesn't specify how we access that
>> config space, so I think hardware with non-standard ECAM should still
>> have PNP0A03 and PNP0A08 in _CID or _HID.
>> 
>> "ECAM" as used in the specs (PCIe r3.0, sec 7.2.2, and PCI Firmware
>> r3.2, sec 4.1) means:
>> 
>> (a) a memory-mapped model for config space access, and
>> (b) a specific mapping of address bits to bus/device/function/
>>     register
>> 
>> MCFG and _CBA assume both (a) and (b), so I think a device with
>> non-standard ECAM mappings should not be described in MCFG or _CBA.
>> 
>> If a bridge has ECAM with non-standard mappings, I think either a
>> vendor-specific _HID or a device-specific method, e.g., _DSM, could
>> communicate that.
>> 
>> Jon, I agree that we should avoid describing non-standardized hardware
>> in Linux-specific ways.  Is there a mechanism in use already?  How
>> does Windows handle this?  DMI is a poor long-term solution because it
>> requires ongoing maintenance for new platforms, but I think it's OK
>> for getting started with platforms already shipping.
>> 
>> A _DSM has the advantage that once it is defined and supported, OEMs
>> can ship new platforms without requiring a new quirk or a new _HID to
>> be added to a driver.
>> 
>> There would still be the problem of config access before the namespace
>> is available, i.e., the MCFG use case.  I don't know how important
>> that is.  Defining an MCFG extension seems like the most obvious
>> solution.
>> 
>> If we only expect a few non-standard devices, maybe it's enough to
>> have DMI quirks to statically set up ECAM and just live with the
>> inconvenience of requiring a kernel change for every new non-standard
>> device.
>> 
>>>> Host bridges in ACPI are handled through PNP0A08/PNP0A03 ids, and
>>>> most of the arch specific code is handled in the respective arch
>>>> directories (X86 and IA64, even though IA64 does not rely on ECAM/MCFG
>>>> for
>>>> PCI ops), it is not a driver per-se, PNP0A08/PNP0A03 are detected
>>>> through
>>>> ACPI scan handlers and the respective arch code (ie pci_acpi_scan_root)
>>>> sets-up resources AND config space on an arch specific basis.
>>>> 
>>>> X86 deals with that with code in arch/x86 that sets-up the pci_raw_ops
>>>> on a platform specific basis (and it is not nice, but it works because
>>>> as you all know the number of platforms in X86 world is contained).
>>>> 
>>>> Will this happen for ARM64 in arch/arm64 based on vendor specific
>>>> HIDs ?
>>>> 
>>>> No.
>>>> 
>>>> So given the current state of play (we were requested to move the
>>>> arch/arm64 specific ACPI PCI bits to arch/arm64), we would end up
>>>> with arch/arm64 code requiring code in /drivers to set-up pci_ops
>>>> in a platform specific way, it is horrible, if feasible at all.
>>>> 
>>>> The only way this can be implemented is by pretending that the
>>>> ACPI/PCI arch/arm64 implementation is generic code (that's what this
>>>> series does), move it to /drivers (where it is in this series), and
>>>> implement _DSD vendor specific bindings (per HID) to set-up the pci
>>>> operations; whether this solution should go upstream, given that it
>>>> is just a short-term solution for early platforms bugs, it is another
>>>> story and my personal answer is no.
>> 
>> It seems like there should be a way to look for a _DSM before we call
>> acpi_pci_root_get_mcfg_addr() to look for _CBA.
>> 
>> Currently we call acpi_pci_root_get_mcfg_addr() (to read _CBA) from
>> the generic acpi_pci_root_add(), but the result (root->mcfg_addr) is
>> only used in x86-specific code.  I think it would be nicer if the
>> lookup and the use were together.  Then it would be easier to override
>> it because the mapping assumptions would all be in one place.
>> 
>>> I think it shouldn't be too bad to move quirk handling mechanism to
>>> arch/arm64. Effectively we would not move platform specific code into
>>> arch/arm64 but just the mechanism checking if there is any quirk that
>>> is defined.
>>> 
>>> i.e.:
>>> 
>>> extern struct pci_cfg_fixup __start_acpi_mcfg_fixups[];
>>> extern struct pci_cfg_fixup __end_acpi_mcfg_fixups[];
>>> 
>>> static struct pci_ecam_ops *pci_acpi_get_ops(struct acpi_pci_root *root)
>>> {
>>>       int bus_num = root->secondary.start;
>>>       int domain = root->segment;
>>>       struct pci_cfg_fixup *f;
>>> 
>>>       /*
>>>        * Match against platform specific quirks and return corresponding
>>>        * CAM ops.
>>>        *
>>>        * First match against PCI topology <domain:bus> then use DMI or
>>>        * custom match handler.
>>>        */
>>>       for (f = __start_acpi_mcfg_fixups; f < __end_acpi_mcfg_fixups; f++) {
>>>               if ((f->domain == domain || f->domain == PCI_MCFG_DOMAIN_ANY) &&
>>>                   (f->bus_num == bus_num || f->bus_num == PCI_MCFG_BUS_ANY) &&
>>>                   (f->system ? dmi_check_system(f->system) : 1) &&
>>>                   (f->match ? f->match(f, root) : 1))
>>>                       return f->ops;
>>>       }
>>>       /* No quirks, use ECAM */
>>>       return &pci_generic_ecam_ops;
>>> }
>>> 
>>> Such quirks will be defined anyway in drivers/pci/host/ in the vendor
>>> specific quirk implementations.
>>> 
>>> e.g. in HiSilicon case we would have
>>> 
>>> DECLARE_ACPI_MCFG_FIXUP(NULL, hisi_pcie_match, &hisi_pcie_ecam_ops,
>>>           PCI_MCFG_DOMAIN_ANY, PCI_MCFG_BUS_ANY);
>>> 
>>> in "drivers/pci/host/pcie-hisi-acpi.c "
>>> 
>>> Thanks
>>> 
>>> Gab
>> 
>> Sorry Gab, I guess I was really responding to earlier messages :)
>> 
>> I don't really have much to say here, except that it doesn't seem
>> right to have an MCFG that describes a non-standard ECAM mapping.
>> I suppose there's already firmware in the field that does that,
>> though?
>> 
>> Bjorn


From horms+renesas at verge.net.au  Mon May 23 18:54:38 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Tue, 24 May 2016 10:54:38 +0900
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC support
In-Reply-To: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>

Basic support for the Gen 3 R-Car M3-W SoC.

Based on work for the r8a7795 and r8a7796 SoCs by
Takeshi Kihara, Dirk Behme and Geert Uytterhoeven.

Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
v3
* As suggested by Geert Uytterhoeven:
  - Drop 0x from unit address of gic
* As suggested by Khiem Nguyen:
  - Use psci-0.2
* Added Reviewed-by tag from Geert Uytterhoeven

v2
* As suggested by Geert Uytterhoeven:
  - Move L2_CA57 node under cpus node and include reg property
  - Omit status = "disabled" from scif_clk node
---
 Documentation/devicetree/bindings/arm/shmobile.txt |   4 +
 arch/arm64/Kconfig.platforms                       |   6 ++
 arch/arm64/boot/dts/renesas/r8a7796.dtsi           | 120 +++++++++++++++++++++
 3 files changed, 130 insertions(+)
 create mode 100644 arch/arm64/boot/dts/renesas/r8a7796.dtsi

diff --git a/Documentation/devicetree/bindings/arm/shmobile.txt b/Documentation/devicetree/bindings/arm/shmobile.txt
index 9cf67e48f222..d5ed554830d7 100644
--- a/Documentation/devicetree/bindings/arm/shmobile.txt
+++ b/Documentation/devicetree/bindings/arm/shmobile.txt
@@ -29,6 +29,8 @@ SoCs:
     compatible = "renesas,r8a7794"
   - R-Car H3 (R8A77950)
     compatible = "renesas,r8a7795"
+  - R-Car M3-W (R8A77960)
+    compatible = "renesas,r8a7796"
 
 
 Boards:
@@ -61,5 +63,7 @@ Boards:
     compatible = "renesas,porter", "renesas,r8a7791"
   - Salvator-X (RTP0RC7795SIPB0010S)
     compatible = "renesas,salvator-x", "renesas,r8a7795";
+  - Salvator-X
+    compatible = "renesas,salvator-x", "renesas,r8a7796";
   - SILK (RTP0RC7794LCB00011S)
     compatible = "renesas,silk", "renesas,r8a7794"
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index efa77c146415..16d8d26839ea 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -114,6 +114,12 @@ config ARCH_R8A7795
 	help
 	  This enables support for the Renesas R-Car H3 SoC.
 
+config ARCH_R8A7796
+	bool "Renesas R-Car M3-W SoC Platform"
+	depends on ARCH_RENESAS
+	help
+	  This enables support for the Renesas R-Car M3-W SoC.
+
 config ARCH_STRATIX10
 	bool "Altera's Stratix 10 SoCFPGA Family"
 	help
diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
new file mode 100644
index 000000000000..178debf68318
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
@@ -0,0 +1,120 @@
+/*
+ * Device Tree Source for the r8a7796 SoC
+ *
+ * Copyright (C) 2016 Renesas Electronics Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/clock/r8a7796-cpg-mssr.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "renesas,r8a7796";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* 1 core only at this point */
+		a57_0: cpu at 0 {
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x0>;
+			device_type = "cpu";
+			next-level-cache = <&L2_CA57>;
+			enable-method = "psci";
+		};
+
+		L2_CA57: cache-controller at 0 {
+			compatible = "cache";
+			reg = <0>;
+			cache-unified;
+			cache-level = <2>;
+		};
+	};
+
+	extal_clk: extal {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	extalr_clk: extalr {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	/* External SCIF clock - to be overridden by boards that provide it */
+	scif_clk: scif {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gic: interrupt-controller at f1010000 {
+			compatible = "arm,gic-400";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0x0 0xf1010000 0 0x1000>,
+			      <0x0 0xf1020000 0 0x20000>,
+			      <0x0 0xf1040000 0 0x20000>,
+			      <0x0 0xf1060000 0 0x20000>;
+			interrupts = <GIC_PPI 9
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+		};
+
+		timer {
+			compatible = "arm,armv8-timer";
+			interrupts = <GIC_PPI 13
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 14
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 11
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 10
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
+		};
+
+		cpg: clock-controller at e6150000 {
+			compatible = "renesas,r8a7796-cpg-mssr";
+			reg = <0 0xe6150000 0 0x1000>;
+			clocks = <&extal_clk>, <&extalr_clk>;
+			clock-names = "extal", "extalr";
+			#clock-cells = <2>;
+			#power-domain-cells = <0>;
+		};
+
+		scif2: serial at e6e88000 {
+			compatible = "renesas,scif-r8a7796",
+				     "renesas,rcar-gen3-scif", "renesas,scif";
+			reg = <0 0xe6e88000 0 64>;
+			interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 310>,
+				 <&cpg CPG_CORE R8A7796_CLK_S3D1>,
+				 <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			power-domains = <&cpg>;
+			status = "disabled";
+		};
+	};
+};
-- 
2.1.4



From horms+renesas at verge.net.au  Mon May 23 18:54:39 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Tue, 24 May 2016 10:54:39 +0900
Subject: [PATCH v3 2/3] arm64: dts: salvator-x: add Salvator-X board on
 R8A7796 SoC
In-Reply-To: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1464054880-25843-3-git-send-email-horms+renesas@verge.net.au>

From: Takeshi Kihara <takeshi.kihara.df at renesas.com>

This patch adds initial board support for R8A7796 Salvator-X.

Signed-off-by: Takeshi Kihara <takeshi.kihara.df at renesas.com>
Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
--
v2 [Simon Horman]
* Added Reviewed-by tag from Geert Uytterhoeven

v1 [Simon Horman]
* Drop use of pfc, that can be added once pfc support is present in mainline
* Set size of memory (bank 0) to 2GiB instead of 1GiB
* Omit scif0
* Add scif_clk, from patch by Hiromitsu Yamasaki

v0 [Takeshi Kihara]
---
 arch/arm64/boot/dts/renesas/Makefile               |  1 +
 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts | 45 ++++++++++++++++++++++
 2 files changed, 46 insertions(+)
 create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts

diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
index 9ce1890a650e..17139f7003a6 100644
--- a/arch/arm64/boot/dts/renesas/Makefile
+++ b/arch/arm64/boot/dts/renesas/Makefile
@@ -1,4 +1,5 @@
 dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x.dtb
+dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb
 
 always		:= $(dtb-y)
 clean-files	:= *.dtb
diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
new file mode 100644
index 000000000000..9c52613fb88c
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
@@ -0,0 +1,45 @@
+/*
+ * Device Tree Source for the Salvator-X board
+ *
+ * Copyright (C) 2016 Renesas Electronics Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+#include "r8a7796.dtsi"
+
+/ {
+	model = "Renesas Salvator-X board based on r8a7796";
+	compatible = "renesas,salvator-x", "renesas,r8a7796";
+
+	aliases {
+		serial0 = &scif2;
+	};
+
+	chosen {
+		bootargs = "ignore_loglevel";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory at 48000000 {
+		device_type = "memory";
+		/* first 128MB is reserved for secure area. */
+		reg = <0x0 0x48000000 0x0 0x78000000>;
+	};
+};
+
+&extal_clk {
+	clock-frequency = <16666666>;
+};
+
+&scif2 {
+	status = "okay";
+};
+
+&scif_clk {
+	clock-frequency = <14745600>;
+	status = "okay";
+};
-- 
2.1.4



From horms+renesas at verge.net.au  Mon May 23 18:54:40 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Tue, 24 May 2016 10:54:40 +0900
Subject: [PATCH v3 3/3] arm64: defconfig: enable Renesas R8A7796 SoC
In-Reply-To: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1464054880-25843-4-git-send-email-horms+renesas@verge.net.au>

From: Takeshi Kihara <takeshi.kihara.df at renesas.com>

This patch enables the Renesas R8A7796 SoC in the arm64 defconfig.

Signed-off-by: Takeshi Kihara <takeshi.kihara.df at renesas.com>
Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
Acked-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
v2 [Simon Horman]
* Added Acked-by tag from Geert Uytterhoeven
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index f70505186820..0d37fa5a59aa 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -44,6 +44,7 @@ CONFIG_ARCH_ROCKCHIP=y
 CONFIG_ARCH_SEATTLE=y
 CONFIG_ARCH_RENESAS=y
 CONFIG_ARCH_R8A7795=y
+CONFIG_ARCH_R8A7796=y
 CONFIG_ARCH_STRATIX10=y
 CONFIG_ARCH_TEGRA=y
 CONFIG_ARCH_SPRD=y
-- 
2.1.4



From horms+renesas at verge.net.au  Mon May 23 18:54:37 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Tue, 24 May 2016 10:54:37 +0900
Subject: [PATCH v3 0/3] arm64: Add Renesas R8A7796 SoC support
Message-ID: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>

Hi,

this short series aims to add basic support for the
Gen 3 R-Car M3-W (r8a7796) SoC.

It has few bells and whistles but is sufficient to bring up
an r8a7795/salvator-x. I have provided a boot-log at the bottom
of this email in case it is of interest.


Dependency:

"[PATCH 0/4] clk: renesas: cpg-mssr: Add support for R-Car M3-W"


Availability:

In order to aid review this series, its dependency (above)
and the related patch "serial: sh-sci: Document SoC specific bindings for
r8a7796", which has been posted separately, are available at:

git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git topic/r8a7796-v3

To be entirely clear, at the time of writing I have _not_ queued up this
series for mainline.


Changes between v2 and v3:
* Drop 0x from unit address of gic
* Use arm,psci-0.2
* Accumulate Reviewed-by tag

Changes between v1 and v2:
* Move L2_CA57 node under cpus node and include reg property
* Omit status = "disabled" from scif_clk node
* Accumulate Ack and Reviewed-by tags


Simon Horman (1):
  arm64: dts: r8a7796: Add Renesas R8A7796 SoC support

Takeshi Kihara (2):
  arm64: dts: salvator-x: add Salvator-X board on R8A7796 SoC
  arm64: defconfig: enable Renesas R8A7796 SoC

 Documentation/devicetree/bindings/arm/shmobile.txt |   4 +
 arch/arm64/Kconfig.platforms                       |   6 ++
 arch/arm64/boot/dts/renesas/Makefile               |   1 +
 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts |  45 ++++++++
 arch/arm64/boot/dts/renesas/r8a7796.dtsi           | 120 +++++++++++++++++++++
 arch/arm64/configs/defconfig                       |   1 +
 6 files changed, 177 insertions(+)
 create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
 create mode 100644 arch/arm64/boot/dts/renesas/r8a7796.dtsi


Boot Log:

The following boot log was generated by booting this patch set,
in its form in the topic/r8a7796 branch. It was compiled using
the ARM64 defconfig with initrd enabled to provide a working userspace.


[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.6.0-rc1+ (horms at ayumi.isobedori.kobe.vergenet.net) (gcc version 4.8.5 (Linaro GCC 4.8-2015.06) ) #98 SMP PREEMPT Tue May 24 10:47:31 JST 2016
[    0.000000] Boot CPU: AArch64 Processor [411fd073]
[    0.000000] debug: ignoring loglevel setting.
[    0.000000] efi: Getting EFI parameters from FDT:
[    0.000000] efi: UEFI not found.
[    0.000000] cma: Reserved 16 MiB at 0x00000000bf000000
[    0.000000] On node 0 totalpages: 1015808
[    0.000000]   DMA zone: 7680 pages used for memmap
[    0.000000]   DMA zone: 0 pages reserved
[    0.000000]   DMA zone: 491520 pages, LIFO batch:31
[    0.000000]   Normal zone: 8192 pages used for memmap
[    0.000000]   Normal zone: 524288 pages, LIFO batch:31
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv1.0 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: Trusted OS migration not required
[    0.000000] percpu: Embedded 20 pages/cpu @ffffffc63ffad000 s43008 r8192 d30720 u81920
[    0.000000] pcpu-alloc: s43008 r8192 d30720 u81920 alloc=20*4096
[    0.000000] pcpu-alloc: [0] 0 
[    0.000000] Detected PIPT I-cache on CPU0
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 999936
[    0.000000] Kernel command line: ignore_loglevel rw root=/dev/nfs ip=dhcp nfsroot=10.3.3.135:/srv/nfs/salvator-x-arm64
[    0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes)
[    0.000000] Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes)
[    0.000000] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes)
[    0.000000] software IO TLB [mem 0xbafff000-0xbefff000] (64MB) mapped at [ffffffc07afff000-ffffffc07effefff]
[    0.000000] Memory: 3896020K/4063232K available (6796K kernel code, 619K rwdata, 2880K rodata, 2256K init, 241K bss, 150828K reserved, 16384K cma-reserved)
[    0.000000] Virtual kernel memory layout:
[    0.000000]     modules : 0xffffff8000000000 - 0xffffff8008000000   (   128 MB)
[    0.000000]     vmalloc : 0xffffff8008000000 - 0xffffffbdbfff0000   (   246 GB)
[    0.000000]       .text : 0xffffff8008080000 - 0xffffff8008721000   (  6788 KB)
[    0.000000]     .rodata : 0xffffff8008721000 - 0xffffff80089f5000   (  2896 KB)
[    0.000000]       .init : 0xffffff80089f5000 - 0xffffff8008c29000   (  2256 KB)
[    0.000000]       .data : 0xffffff8008c29000 - 0xffffff8008cc3e00   (   620 KB)
[    0.000000]     vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000   (     8 GB maximum)
[    0.000000]               0xffffffbdc0200000 - 0xffffffbdd9000000   (   398 MB actual)
[    0.000000]     fixed   : 0xffffffbffe7fd000 - 0xffffffbffec00000   (  4108 KB)
[    0.000000]     PCI I/O : 0xffffffbffee00000 - 0xffffffbfffe00000   (    16 MB)
[    0.000000]     memory  : 0xffffffc008000000 - 0xffffffc640000000   ( 25472 MB)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] Preemptible hierarchical RCU implementation.
[    0.000000]  Build-time adjustment of leaf fanout to 64.
[    0.000000]  RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=1.
[    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=64, nr_cpu_ids=1
[    0.000000] NR_IRQS:64 nr_irqs:64 0
[    0.000000] Architected cp15 timer(s) running at 8.33MHz (virt).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1ec02923e, max_idle_ns: 440795202125 ns
[    0.000003] sched_clock: 56 bits at 8MHz, resolution 120ns, wraps every 2199023255496ns
[    0.000078] Console: colour dummy device 80x25
[    0.000382] console [tty0] enabled
[    0.000402] Calibrating delay loop (skipped), value calculated using timer frequency.. 16.66 BogoMIPS (lpj=33333)
[    0.000419] pid_max: default: 32768 minimum: 301
[    0.000463] Security Framework initialized
[    0.000495] Mount-cache hash table entries: 8192 (order: 4, 65536 bytes)
[    0.000505] Mountpoint-cache hash table entries: 8192 (order: 4, 65536 bytes)
[    0.001204] ASID allocator initialised with 65536 entries
[    0.001721] EFI services will not be available.
[    0.001826] Brought up 1 CPUs
[    0.001836] SMP: Total of 1 processors activated.
[    0.001850] CPU: All CPU(s) started at EL1
[    0.002615] devtmpfs: initialized
[    0.003177] DMI not present or invalid.
[    0.003369] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.003738] pinctrl core: initialized pinctrl subsystem
[    0.004515] NET: Registered protocol family 16
[    0.016065] cpuidle: using governor menu
[    0.016218] vdso: 2 pages (1 code @ ffffff8008727000, 1 data @ ffffff8008c30000)
[    0.016254] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[    0.016750] DMA: preallocated 256 KiB pool for atomic allocations
[    0.016906] Serial: AMBA PL011 UART driver
[    0.040435] HugeTLB registered 2 MB page size, pre-allocated 0 pages
[    0.052844] vgaarb: loaded
[    0.053040] SCSI subsystem initialized
[    0.056288] libata version 3.00 loaded.
[    0.056470] usbcore: registered new interface driver usbfs
[    0.056509] usbcore: registered new interface driver hub
[    0.056541] usbcore: registered new device driver usb
[    0.056625] pps_core: LinuxPPS API ver. 1 registered
[    0.056634] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti at linux.it>
[    0.056660] PTP clock support registered
[    0.056737] dmi: Firmware registration failed.
[    0.057028] Advanced Linux Sound Architecture Driver Initialized.
[    0.057989] clocksource: Switched to clocksource arch_sys_counter
[    0.058133] VFS: Disk quotas dquot_6.6.0
[    0.058179] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[    0.068090] NET: Registered protocol family 2
[    0.068508] TCP established hash table entries: 32768 (order: 6, 262144 bytes)
[    0.068625] TCP bind hash table entries: 32768 (order: 7, 524288 bytes)
[    0.069071] TCP: Hash tables configured (established 32768 bind 32768)
[    0.069176] UDP hash table entries: 2048 (order: 4, 65536 bytes)
[    0.069209] UDP-Lite hash table entries: 2048 (order: 4, 65536 bytes)
[    0.069373] NET: Registered protocol family 1
[    0.069706] RPC: Registered named UNIX socket transport module.
[    0.069725] RPC: Registered udp transport module.
[    0.069732] RPC: Registered tcp transport module.
[    0.069739] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.069765] PCI: CLS 0 bytes, default 128
[    0.116499] kvm [1]: HYP mode not available
[    0.118272] futex hash table entries: 256 (order: 3, 32768 bytes)
[    0.118353] audit: initializing netlink subsys (disabled)
[    0.118398] audit: type=2000 audit(0.115:1): initialized
[    0.119105] workingset: timestamp_bits=44 max_order=20 bucket_order=0
[    0.128905] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.129921] NFS: Registering the id_resolver key type
[    0.129976] Key type id_resolver registered
[    0.129984] Key type id_legacy registered
[    0.130194] fuse init (API version 7.24)
[    0.130623] 9p: Installing v9fs 9p2000 file system support
[    0.132356] io scheduler noop registered
[    0.132526] io scheduler cfq registered (default)
[    0.135682] xenfs: not registering filesystem on non-xen platform
[    0.140609] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    0.142028] SuperH (H)SCI(F) driver initialized
[    0.142217] e6e88000.serial: ttySC0 at MMIO 0xe6e88000 (irq = 6, base_baud = 0) is a scif
[    0.812036] console [ttySC0] enabled
[    0.815989] msm_serial: driver initialized
[    0.848254] loop: module loaded
[    0.852907] tun: Universal TUN/TAP device driver, 1.6
[    0.858608] tun: (C) 1999-2004 Max Krasnyansky <maxk at qualcomm.com>
[    0.865182] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[    0.871284] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    0.877303] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.3.0-k
[    0.884340] igb: Copyright (c) 2007-2014 Intel Corporation.
[    0.889981] igbvf: Intel(R) Gigabit Virtual Function Network Driver - version 2.0.2-k
[    0.897843] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
[    0.903823] sky2: driver version 1.30
[    0.907854] VFIO - User Level meta-driver version: 0.3
[    0.915399] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    0.922168] ehci-pci: EHCI PCI platform driver
[    0.926767] ehci-platform: EHCI generic platform driver
[    0.932151] ehci-msm: Qualcomm On-Chip EHCI Host Controller
[    0.937808] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    0.944041] ohci-pci: OHCI PCI platform driver
[    0.948553] ohci-platform: OHCI generic platform driver
[    0.954029] usbcore: registered new interface driver usb-storage
[    0.960813] mousedev: PS/2 mouse device common for all mice
[    0.967093] i2c /dev entries driver
[    0.971519] sdhci: Secure Digital Host Controller Interface driver
[    0.978118] sdhci: Copyright(c) Pierre Ossman
[    0.982619] Synopsys Designware Multimedia Card Interface Driver
[    0.988896] sdhci-pltfm: SDHCI platform and OF driver helper
[    0.994818] ledtrig-cpu: registered to indicate activity on CPUs
[    1.001589] usbcore: registered new interface driver usbhid
[    1.007437] usbhid: USB HID core driver
[    1.012433] NET: Registered protocol family 17
[    1.017379] 9pnet: Installing 9P2000 support
[    1.021779] Key type dns_resolver registered
[    1.026695] registered taskstats version 1
[    1.031222] hctosys: unable to open rtc device (rtc0)
[   13.081547] ALSA device list:
[   13.084527]   No soundcards found.
[   13.089430] Freeing unused kernel memory: 2256K (ffffff80089f5000 - ffffff8008c29000)


boot (Linux 4.6.0-rc1+, BusyBox v1.16.0.git, kexec-tools 2.0.1-git)
/ # cat /proc/interrupts 
           CPU0       
  3:        253     GIC-0  27 Edge      arch_timer
  6:         79     GIC-0 196 Level     e6e88000.serial:mux
IPI0:         0       Rescheduling interrupts
IPI1:         0       Function call interrupts
IPI2:         0       CPU stop interrupts
IPI3:         0       Timer broadcast interrupts
IPI4:         0       IRQ work interrupts
IPI5:         0       CPU wake-up interrupts
Err: 


From shawn.lin at rock-chips.com  Mon May 23 19:05:58 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Tue, 24 May 2016 10:05:58 +0800
Subject: [PATCH 1/3] dt-bindings: add used but undocumented rockchip grf
 compatible values
In-Reply-To: <1464015539-19521-2-git-send-email-heiko@sntech.de>
References: <1464015539-19521-1-git-send-email-heiko@sntech.de>
 <1464015539-19521-2-git-send-email-heiko@sntech.de>
Message-ID: <a31feead-5bc1-a77d-d4c5-111b7ba82b9d@rock-chips.com>

? 2016/5/23 22:58, Heiko Stuebner ??:
> There are some more General Register Files used in devicetree files
> already, but as of now undocumented in the binding document, fix that.
>
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---

Reviewed-by: Shawn Lin <shawn.lin at rock-chips.com>

>  Documentation/devicetree/bindings/soc/rockchip/grf.txt | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.txt b/Documentation/devicetree/bindings/soc/rockchip/grf.txt
> index 013e71a..c6e62cb 100644
> --- a/Documentation/devicetree/bindings/soc/rockchip/grf.txt
> +++ b/Documentation/devicetree/bindings/soc/rockchip/grf.txt
> @@ -5,11 +5,13 @@ is composed of many registers for system control.
>
>  From RK3368 SoCs, the GRF is divided into two sections,
>  - GRF, used for general non-secure system,
> +- SGRF, used for general secure system,
>  - PMUGRF, used for always on system
>
>  Required Properties:
>
>  - compatible: GRF should be one of the followings
> +   - "rockchip,rk3036-grf", "syscon": for rk3036
>     - "rockchip,rk3066-grf", "syscon": for rk3066
>     - "rockchip,rk3188-grf", "syscon": for rk3188
>     - "rockchip,rk3228-grf", "syscon": for rk3228
> @@ -19,6 +21,8 @@ Required Properties:
>  - compatible: PMUGRF should be one of the followings
>     - "rockchip,rk3368-pmugrf", "syscon": for rk3368
>     - "rockchip,rk3399-pmugrf", "syscon": for rk3399
> +- compatible: SGRF should be one of the following
> +   - "rockchip,rk3288-sgrf", "syscon": for rk3288
>  - reg: physical base address of the controller and length of memory mapped
>    region.
>
>


-- 
Best Regards
Shawn Lin



From shawn.lin at rock-chips.com  Mon May 23 19:09:41 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Tue, 24 May 2016 10:09:41 +0800
Subject: [PATCH 3/3] ARM: rockchip: drop rk3288 jtag/mmc switch handling
In-Reply-To: <1464015539-19521-4-git-send-email-heiko@sntech.de>
References: <1464015539-19521-1-git-send-email-heiko@sntech.de>
 <1464015539-19521-4-git-send-email-heiko@sntech.de>
Message-ID: <feee590b-e9a9-7c36-cf99-9dd1cb229eb7@rock-chips.com>

? 2016/5/23 22:58, Heiko Stuebner ??:
> We moved that functionality to a more generic place where it can also
> be used for other socs, so drop it from architecture code.
>
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>

It looks good to drop this Soc related setting from
architecture code.

Reviewed-by: Shawn Lin <shawn.lin at rock-chips.com>

> ---
>  arch/arm/mach-rockchip/rockchip.c | 12 ------------
>  1 file changed, 12 deletions(-)
>
> diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
> index beb71da..e7b2aa7 100644
> --- a/arch/arm/mach-rockchip/rockchip.c
> +++ b/arch/arm/mach-rockchip/rockchip.c
> @@ -29,13 +29,11 @@
>  #include "core.h"
>  #include "pm.h"
>
> -#define RK3288_GRF_SOC_CON0 0x244
>  #define RK3288_TIMER6_7_PHYS 0xff810000
>
>  static void __init rockchip_timer_init(void)
>  {
>  	if (of_machine_is_compatible("rockchip,rk3288")) {
> -		struct regmap *grf;
>  		void __iomem *reg_base;
>
>  		/*
> @@ -54,16 +52,6 @@ static void __init rockchip_timer_init(void)
>  		} else {
>  			pr_err("rockchip: could not map timer7 registers\n");
>  		}
> -
> -		/*
> -		 * Disable auto jtag/sdmmc switching that causes issues
> -		 * with the mmc controllers making them unreliable
> -		 */
> -		grf = syscon_regmap_lookup_by_compatible("rockchip,rk3288-grf");
> -		if (!IS_ERR(grf))
> -			regmap_write(grf, RK3288_GRF_SOC_CON0, 0x10000000);
> -		else
> -			pr_err("rockchip: could not get grf syscon\n");
>  	}
>
>  	of_clk_init(NULL);
>


-- 
Best Regards
Shawn Lin



From eric at anholt.net  Mon May 23 19:14:09 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon, 23 May 2016 19:14:09 -0700
Subject: [PATCH 2/4] hwrng: bcm2835: Support Broadcom NSP SoC rng
In-Reply-To: <1464020451-16520-3-git-send-email-yendapally.reddy@broadcom.com>
References: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>
 <1464020451-16520-3-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <87oa7w2oem.fsf@eliezer.anholt.net>

Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
writes:

> This supports the random number generator available in NSP SoC.
> Masks the rng interrupt for NSP.

The interrupt reg is also present on the 2835.  I would prefer for
simplicity if you also initialized the register to the same value on the
Pi, even though the firmware has presumably been setting it for us
already.

However, this patch is still correct and I'm fine with it, so it's:

Acked-by: Eric Anholt <eric at anholt.net>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160523/b46b26ff/attachment-0001.sig>

From okaya at codeaurora.org  Mon May 23 19:14:59 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Mon, 23 May 2016 22:14:59 -0400
Subject: [PATCH V5 2/6] vfio: platform: move reset call to a common
 function
In-Reply-To: <5742FF59.6090108@linaro.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
 <1463364819-477-3-git-send-email-okaya@codeaurora.org>
 <5742FF59.6090108@linaro.org>
Message-ID: <5743B923.4090307@codeaurora.org>

On 5/23/2016 9:02 AM, Eric Auger wrote:
> Hi Sinan,
> On 05/16/2016 04:13 AM, Sinan Kaya wrote:
>> The reset call sequence seems to replicate itself multiple times
>> across the file. Grouping them together for maintenance reasons.
>>
>> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
>> ---
>>  drivers/vfio/platform/vfio_platform_common.c | 31 ++++++++++++++--------------
>>  1 file changed, 15 insertions(+), 16 deletions(-)
>>
>> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
>> index 08fd7c2..cb91dd3 100644
>> --- a/drivers/vfio/platform/vfio_platform_common.c
>> +++ b/drivers/vfio/platform/vfio_platform_common.c
>> @@ -134,6 +134,18 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
>>  	kfree(vdev->regions);
>>  }
>>  
>> +static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
>> +{
>> +	if (vdev->of_reset) {
>> +		dev_info(vdev->device, "reset\n");
>> +		vdev->of_reset(vdev);
>> +		return 0;
> you should return vdev->of_reset(vdev) to keep the existing
> VFIO_DEVICE_RESET ioctl behavior

will do.

> 
> Once fixed, Reviewed-by: Eric Auger <eric.auger at linaro.org>
> 
thanks.

> Besides, but this goes beyond the scope of your series, maybe we should
> reconsider in the future what happens in case the reset fails on
> open/release.
> 

I like giving an error immediately to be honest on open. 

> Best Regards
> 
> Eric
>> +	}
>> +
>> +	dev_warn(vdev->device, "no reset function found!\n");
>> +	return -EINVAL;
>> +}
>> +
>>  static void vfio_platform_release(void *device_data)
>>  {
>>  	struct vfio_platform_device *vdev = device_data;
>> @@ -141,12 +153,7 @@ static void vfio_platform_release(void *device_data)
>>  	mutex_lock(&driver_lock);
>>  
>>  	if (!(--vdev->refcnt)) {
>> -		if (vdev->of_reset) {
>> -			dev_info(vdev->device, "reset\n");
>> -			vdev->of_reset(vdev);
>> -		} else {
>> -			dev_warn(vdev->device, "no reset function found!\n");
>> -		}
>> +		vfio_platform_call_reset(vdev);
>>  		vfio_platform_regions_cleanup(vdev);
>>  		vfio_platform_irq_cleanup(vdev);
>>  	}
>> @@ -175,12 +182,7 @@ static int vfio_platform_open(void *device_data)
>>  		if (ret)
>>  			goto err_irq;
>>  
>> -		if (vdev->of_reset) {
>> -			dev_info(vdev->device, "reset\n");
>> -			vdev->of_reset(vdev);
>> -		} else {
>> -			dev_warn(vdev->device, "no reset function found!\n");
>> -		}
>> +		vfio_platform_call_reset(vdev);
>>  	}
>>  
>>  	vdev->refcnt++;
>> @@ -312,10 +314,7 @@ static long vfio_platform_ioctl(void *device_data,
>>  		return ret;
>>  
>>  	} else if (cmd == VFIO_DEVICE_RESET) {
>> -		if (vdev->of_reset)
>> -			return vdev->of_reset(vdev);
>> -		else
>> -			return -EINVAL;
>> +		return vfio_platform_call_reset(vdev);
>>  	}
>>  
>>  	return -ENOTTY;
>>
> 


-- 
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


From okaya at codeaurora.org  Mon May 23 19:18:37 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Mon, 23 May 2016 22:18:37 -0400
Subject: [PATCH V5 4/6] vfio: platform: add support for ACPI probe
In-Reply-To: <5743031B.5000208@linaro.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
 <1463364819-477-5-git-send-email-okaya@codeaurora.org>
 <5743031B.5000208@linaro.org>
Message-ID: <5743B9FD.5030501@codeaurora.org>

On 5/23/2016 9:18 AM, Eric Auger wrote:
> On 05/16/2016 04:13 AM, Sinan Kaya wrote:
>> The code is using the compatible DT string to associate a reset driver
>> with the actual device itself. The compatible string does not exist on
>> ACPI based systems. HID is the unique identifier for a device driver
>> instead.
>>
>> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
>> ---
>>  drivers/vfio/platform/vfio_platform_common.c  | 58 ++++++++++++++++++++++++---
>>  drivers/vfio/platform/vfio_platform_private.h |  1 +
>>  2 files changed, 54 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
>> index 25378bd..d859d3b 100644
>> --- a/drivers/vfio/platform/vfio_platform_common.c
>> +++ b/drivers/vfio/platform/vfio_platform_common.c
>> @@ -13,6 +13,7 @@
>>   */
>>  
>>  #include <linux/device.h>
>> +#include <linux/acpi.h>
>>  #include <linux/iommu.h>
>>  #include <linux/module.h>
>>  #include <linux/mutex.h>
>> @@ -49,6 +50,37 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
>>  	return reset_fn;
>>  }
>>  
>> +#ifdef CONFIG_ACPI
>> +int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
>> +			     struct device *dev)
> should be static

makes sense

>> +{
>> +	struct acpi_device *adev = ACPI_COMPANION(dev);
>> +
>> +	if (acpi_disabled)
>> +		return -ENODEV;
>> +
>> +	if (!adev) {
>> +		pr_err("VFIO: ACPI companion device not found for %s\n",
>> +			vdev->name);
>> +		return -ENODEV;
>> +	}
>> +
>> +	vdev->acpihid = acpi_device_hid(adev);
>> +	if (!vdev->acpihid) {
>> +		pr_err("VFIO: cannot find ACPI HID for %s\n",
>> +		       vdev->name);
>> +		return -ENODEV;
>> +	}
>> +	return 0;
>> +}
>> +#else
>> +int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
>> +			     struct device *dev)
> static inline?

yup

>> +{
>> +	return -EINVAL;
> nit: -ENOENT ?

OK

>> +}
>> +#endif
>> +
>>  static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
>>  {
>>  	return vdev->of_reset ? true : false;
>> @@ -548,6 +580,21 @@ static const struct vfio_device_ops vfio_platform_ops = {
>>  	.mmap		= vfio_platform_mmap,
>>  };
>>  
>> +int vfio_platform_of_probe(struct vfio_platform_device *vdev,
>> +			   struct device *dev)
>> +{
>> +	int ret;
>> +
>> +	ret = device_property_read_string(dev, "compatible",
>> +					  &vdev->compat);
>> +	if (ret) {
>> +		pr_err("VFIO: cannot retrieve compat for %s\n",
>> +			vdev->name);
>> +		return ret;
>> +	}
>> +	return 0;
> nit: can be simplified by returning ret in any case.

will do

> 
> Best Regards
> 
> Eric
> 
>> +}
>> +
>>  int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>>  			       struct device *dev)
>>  {
>> @@ -557,11 +604,12 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>>  	if (!vdev)
>>  		return -EINVAL;
>>  
>> -	ret = device_property_read_string(dev, "compatible", &vdev->compat);
>> -	if (ret) {
>> -		pr_err("VFIO: cannot retrieve compat for %s\n", vdev->name);
>> -		return -EINVAL;
>> -	}
>> +	ret = vfio_platform_acpi_probe(vdev, dev);
>> +	if (ret)
>> +		ret = vfio_platform_of_probe(vdev, dev);
>> +
>> +	if (ret)
>> +		return ret;
>>  
>>  	vdev->device = dev;
>>  
>> diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
>> index 71ed7d1..ba9e4f8 100644
>> --- a/drivers/vfio/platform/vfio_platform_private.h
>> +++ b/drivers/vfio/platform/vfio_platform_private.h
>> @@ -58,6 +58,7 @@ struct vfio_platform_device {
>>  	struct mutex			igate;
>>  	struct module			*parent_module;
>>  	const char			*compat;
>> +	const char			*acpihid;
>>  	struct module			*reset_module;
>>  	struct device			*device;
>>  
>>
> 


-- 
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


From eric at anholt.net  Mon May 23 19:21:00 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon, 23 May 2016 19:21:00 -0700
Subject: [PATCH 4/4] hwrng: bcm2835: Read as much data as available
In-Reply-To: <1464020451-16520-5-git-send-email-yendapally.reddy@broadcom.com>
References: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>
 <1464020451-16520-5-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <87k2ik2o37.fsf@eliezer.anholt.net>

Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
writes:

> Read the requested number of data from the fifo
>
> Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
> ---
>  drivers/char/hw_random/bcm2835-rng.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
> index b1e8b78..9bbdc07 100644
> --- a/drivers/char/hw_random/bcm2835-rng.c
> +++ b/drivers/char/hw_random/bcm2835-rng.c
> @@ -43,6 +43,8 @@ static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
>  			       bool wait)
>  {
>  	void __iomem *rng_base = (void __iomem *)rng->priv;
> +	u32 max_words = max/sizeof(u32);

Style fix: Binary operators get a space on each side, so
"max / sizeof(u32);"

> @@ -50,8 +52,14 @@ static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
>  		cpu_relax();
>  	}
>  
> -	*(u32 *)buf = __raw_readl(rng_base + RNG_DATA);
> -	return sizeof(u32);
> +	num_words = (readl(rng_base + RNG_STATUS) >> 24);

Optional cleanup: here and in the return statement, drop the extra
parenthesis.

Functionality-wise, this patch looks great to me, and should make the
driver more efficient.  With at least the binary operators change done,
it will be:

Reviewed-by: Eric Anholt <eric at anholt.net>

Thanks!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160523/14498083/attachment.sig>

From eric at anholt.net  Mon May 23 19:22:44 2016
From: eric at anholt.net (Eric Anholt)
Date: Mon, 23 May 2016 19:22:44 -0700
Subject: [PATCH 1/4] dt-bindings: rng: Northstar Plus SoC rng bindings
In-Reply-To: <1464020451-16520-2-git-send-email-yendapally.reddy@broadcom.com>
References: <1464020451-16520-1-git-send-email-yendapally.reddy@broadcom.com>
 <1464020451-16520-2-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <87h9do2o0b.fsf@eliezer.anholt.net>

Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
writes:

> Document the bindings used by Northstar Plus(NSP) SoC random number
> generator.
>
> Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>

Acked-by: Eric Anholt <eric at anholt.net>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160523/5923e826/attachment.sig>

From okaya at codeaurora.org  Mon May 23 19:23:26 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Mon, 23 May 2016 22:23:26 -0400
Subject: [PATCH V5 5/6] vfio: platform: call _RST method when using ACPI
In-Reply-To: <574316B0.5080306@linaro.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
 <1463364819-477-6-git-send-email-okaya@codeaurora.org>
 <574316B0.5080306@linaro.org>
Message-ID: <5743BB1E.10607@codeaurora.org>

On 5/23/2016 10:41 AM, Eric Auger wrote:
> On 05/16/2016 04:13 AM, Sinan Kaya wrote:
>> The device tree code checks for the presence of a reset driver and calls
>> the of_reset function pointer by looking up the reset driver as a module.
>>
>> ACPI defines _RST method to perform device level reset. After the _RST
>> method is executed, the OS can resume using the device.
>>
>> This patch checks the presence of _RST method and calls the _RST
>> method when reset is requested.
>>
>> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
>> ---
>>  drivers/vfio/platform/vfio_platform_common.c | 44 ++++++++++++++++++++++++++++
>>  1 file changed, 44 insertions(+)
>>
>> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
>> index d859d3b..095d5b7 100644
>> --- a/drivers/vfio/platform/vfio_platform_common.c
>> +++ b/drivers/vfio/platform/vfio_platform_common.c
>> @@ -73,21 +73,59 @@ int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
>>  	}
>>  	return 0;
>>  }
>> +
>> +static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
>> +{
>> +	struct device *dev = vdev->device;
>> +	acpi_handle handle = ACPI_HANDLE(dev);
>> +	acpi_status acpi_ret;
>> +	unsigned long long val;
>> +
>> +	acpi_ret = acpi_evaluate_integer(handle, "_RST", NULL, &val);
>> +	if (ACPI_FAILURE(acpi_ret))
>> +		return -EINVAL;
>> +
>> +	return 0;
>> +}
>> +
>> +static bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
>> +{
>> +	struct device *dev = vdev->device;
>> +	acpi_handle handle = ACPI_HANDLE(dev);
>> +
>> +	return acpi_has_method(handle, "_RST");
>> +}
>>  #else
>>  int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
>>  			     struct device *dev)
>>  {
>>  	return -EINVAL;
>>  }
>> +
>> +static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev)
>> +{
> nit: inline
>> +	return -EINVAL;
>> +}
>> +
>> +static bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
> nit: inline

sure

> 
> Besides Reviewed-by: Eric Auger <eric.auger at linaro.org>
>

thanks
 
> It is not explictly written in the ACPI spec that _RST is expected to
> stop DMA transfers and IRQs although this may be implicit in the notion
> of "function level reset ". May be worth adding this info in the commit msg?
> 

yes, I'll add DMA and IRQ requirement to the commit message.

> Best Regards
> 
> Eric
>> +{
>> +	return false;
>> +}
>>  #endif
>>  
>>  static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
>>  {
>> +	if (vdev->acpihid)
>> +		return vfio_platform_acpi_has_reset(vdev);
>> +
>>  	return vdev->of_reset ? true : false;
>>  }
>>  
>>  static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>>  {
>> +	if (vdev->acpihid)
>> +		return;
>> +
>>  	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
>>  						    &vdev->reset_module);
>>  	if (!vdev->of_reset) {
>> @@ -99,6 +137,9 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>>  
>>  static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
>>  {
>> +	if (vdev->acpihid)
>> +		return;
>> +
>>  	if (vdev->of_reset)
>>  		module_put(vdev->reset_module);
>>  }
>> @@ -177,6 +218,9 @@ static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
>>  		dev_info(vdev->device, "reset\n");
>>  		vdev->of_reset(vdev);
>>  		return 0;
>> +	} else if (vdev->acpihid) {
>> +		dev_info(vdev->device, "reset\n");
>> +		return vfio_platform_acpi_call_reset(vdev);
>>  	}
>>  
>>  	dev_warn(vdev->device, "no reset function found!\n");
>>
> 


-- 
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


From okaya at codeaurora.org  Mon May 23 19:25:17 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Mon, 23 May 2016 22:25:17 -0400
Subject: [PATCH V5 5/6] vfio: platform: call _RST method when using ACPI
In-Reply-To: <57431FF7.2060807@linaro.org>
References: <1463364819-477-1-git-send-email-okaya@codeaurora.org>
 <1463364819-477-6-git-send-email-okaya@codeaurora.org>
 <57431FF7.2060807@linaro.org>
Message-ID: <5743BB8D.7050408@codeaurora.org>

On 5/23/2016 11:21 AM, Eric Auger wrote:
>> +	acpi_ret = acpi_evaluate_integer(handle, "_RST", NULL, &val);
>> > +	if (ACPI_FAILURE(acpi_ret))
>> > +		return -EINVAL;
> Can't you return something more explicit here? The error code will be
> visible to the userspace. Difficult for him to understand the cause of
> the failure in that case.

I can also add a reset failed message to both DT and ACPI reset calls.

Will that work?

-- 
Sinan Kaya
Qualcomm Technologies, Inc. on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


From shawn.lin at rock-chips.com  Mon May 23 19:22:09 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Tue, 24 May 2016 10:22:09 +0800
Subject: [PATCH 2/3] soc: rockchip: add driver handling grf setup
In-Reply-To: <1464015539-19521-3-git-send-email-heiko@sntech.de>
References: <1464015539-19521-1-git-send-email-heiko@sntech.de>
 <1464015539-19521-3-git-send-email-heiko@sntech.de>
Message-ID: <6a6e87ee-688d-90a3-2407-22847bd80971@rock-chips.com>

Hi Heiko,

On 2016/5/23 22:58, Heiko Stuebner wrote:
> The General Register Files are an area of registers containing a lot
> of single-bit settings for numerous components as well full components
> like usbphy control. Therefore all used components are accessed
> via the syscon provided by the grf nodes or from the sub-devices
> created through the simple-mfd created from the grf node.
>
> Some settings are not used by anything but will need to be set up
> according to expectations on the kernel side.
>
> Best example is the force_jtag setting, which defaults to on and
> results in the soc switching the pin-outputs between jtag and sdmmc
> automatically depending on the card-detect status. This conflicts
> heavily with how the dw_mmc driver expects to do its work and also
> with the clock-controller, which has most likely deactivated the
> jtag clock due to it being unused.

I agree we should disable force_jtag for real product. But on my local
branch we add a callback to parse a tag from cmdline. Sometime it's
useful for debugging in case of we need to setup JTAG for reproducing
and comfirming serious issue in which state the CPU cannot reponse to
any console input or FIQ-debug triggering.

Should we need it for upstream as you move all related code in this
new driver?  I'm not sure.

>
> So far the handling of this setting was living in the mach-rockchip
> code for the arm32-based rk3288 but that of course doesn't work
> for arm64 socs and would also look ugly for further arm32 socs.
>
> So introduce a top-level driver for the grf that handles these
> settings that need to be a certain way but nobody cares about.
>
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---
>  drivers/soc/rockchip/Kconfig  |  10 +++
>  drivers/soc/rockchip/Makefile |   1 +
>  drivers/soc/rockchip/grf.c    | 138 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 149 insertions(+)
>  create mode 100644 drivers/soc/rockchip/grf.c
>
> diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
> index 7140ff8..20da55d 100644
> --- a/drivers/soc/rockchip/Kconfig
> +++ b/drivers/soc/rockchip/Kconfig
> @@ -3,6 +3,16 @@ if ARCH_ROCKCHIP || COMPILE_TEST
>  #
>  # Rockchip Soc drivers
>  #
> +
> +config ROCKCHIP_GRF
> +	bool
> +	default y
> +	help
> +	  The General Register Files are a central component providing
> +	  special additional settings registers for a lot of soc-components.
> +	  In a lot of cases there also need to be default settings initialized
> +	  to make some of them conform to expectations of the kernel.
> +
>  config ROCKCHIP_PM_DOMAINS
>          bool "Rockchip generic power domain"
>          depends on PM
> diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
> index 3d73d06..c851fa0 100644
> --- a/drivers/soc/rockchip/Makefile
> +++ b/drivers/soc/rockchip/Makefile
> @@ -1,4 +1,5 @@
>  #
>  # Rockchip Soc drivers
>  #
> +obj-$(CONFIG_ROCKCHIP_GRF) += grf.o
>  obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o
> diff --git a/drivers/soc/rockchip/grf.c b/drivers/soc/rockchip/grf.c
> new file mode 100644
> index 0000000..25a1fd3
> --- /dev/null
> +++ b/drivers/soc/rockchip/grf.c
> @@ -0,0 +1,138 @@
> +/*
> + * Rockchip Generic Register Files setup
> + *
> + * Copyright (c) 2016 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 version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#define HIWORD_UPDATE(val, mask, shift) \
> +		((val) << (shift) | (mask) << ((shift) + 16))
> +
> +struct rockchip_grf_value {
> +	const char *desc;
> +	u32 reg;
> +	u32 val;
> +};
> +
> +struct rockchip_grf_info {
> +	const struct rockchip_grf_value *values;
> +	int num_values;
> +};
> +
> +#define RK3036_GRF_SOC_CON0		0x140
> +
> +static const struct rockchip_grf_value rk3036_defaults[] = {
> +	/*
> +	 * Disable auto jtag/sdmmc switching that causes issues with the
> +	 * clock-framework and the mmc controllers making them unreliable.
> +	 */
> +	{ "jtag switching", RK3036_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 11) },
> +};
> +
> +static const struct rockchip_grf_info rk3036_grf = {
> +	.values = rk3036_defaults,
> +	.num_values = ARRAY_SIZE(rk3036_defaults),
> +};
> +
> +#define RK3288_GRF_SOC_CON0		0x244
> +
> +static const struct rockchip_grf_value rk3288_defaults[] = {
> +	{ "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) },
> +};
> +
> +static const struct rockchip_grf_info rk3288_grf = {
> +	.values = rk3288_defaults,
> +	.num_values = ARRAY_SIZE(rk3288_defaults),
> +};
> +
> +#define RK3399_GRF_SOC_CON7		0xe21c
> +
> +static const struct rockchip_grf_value rk3399_defaults[] = {
> +	{ "jtag switching", RK3399_GRF_SOC_CON7, HIWORD_UPDATE(0, 1, 12) },
> +
> +};
> +
> +static const struct rockchip_grf_info rk3399_grf = {
> +	.values = rk3399_defaults,
> +	.num_values = ARRAY_SIZE(rk3399_defaults),
> +};
> +
> +static const struct of_device_id rockchip_grf_dt_match[] = {
> +	{
> +		.compatible = "rockchip,rk3036-grf",
> +		.data = (void *)&rk3036_grf,
> +	}, {
> +		.compatible = "rockchip,rk3288-grf",
> +		.data = (void *)&rk3288_grf,
> +	}, {
> +		.compatible = "rockchip,rk3399-grf",
> +		.data = (void *)&rk3399_grf,
> +	},
> +	{ /* sentinel */ },
> +};
> +
> +static int rockchip_grf_probe(struct platform_device *pdev)
> +{
> +	const struct rockchip_grf_info *grf_info;
> +	const struct of_device_id *match;
> +	struct device *dev = &pdev->dev;
> +	struct regmap *grf;
> +	int i;
> +
> +	if (!dev->of_node)
> +		return -ENODEV;
> +
> +	match = of_match_device(rockchip_grf_dt_match, dev);
> +	if (!match || !match->data) {
> +		dev_err(dev, "missing grf data\n");
> +		return -EINVAL;
> +	}
> +
> +	grf_info = match->data;
> +
> +	grf = syscon_node_to_regmap(dev->of_node);
> +	if (IS_ERR(grf)) {
> +		dev_err(dev, "rockchip: could not get grf syscon\n");
> +		return PTR_ERR(grf);
> +	}
> +
> +	for (i = 0; i < grf_info->num_values; i++) {
> +		const struct rockchip_grf_value *val = &grf_info->values[i];
> +
> +		dev_dbg(dev, "adjusting %s in 0x%x to 0x%x\n",
> +			val->desc, val->reg, val->val);
> +		regmap_write(grf, val->reg, val->val);
> +	}
> +
> +	return 0;
> +}
> +
> +static struct platform_driver rockchip_grf_driver = {
> +	.probe = rockchip_grf_probe,
> +	.driver = {
> +		.name   = "rockchip-grf",
> +		.of_match_table = rockchip_grf_dt_match,
> +		/*
> +		 * The General Register Files are a central component
> +		 * accessed by numerous ip blocks and we're setting
> +		 * defaults which should only happen once.
> +		 */
> +		.suppress_bind_attrs = true,
> +	},
> +};
> +
> +static int __init rockchip_grf_drv_register(void)
> +{
> +	return platform_driver_register(&rockchip_grf_driver);
> +}
> +postcore_initcall(rockchip_grf_drv_register);
>


-- 
Best Regards
Shawn Lin



From ck.hu at mediatek.com  Mon May 23 20:05:59 2016
From: ck.hu at mediatek.com (CK Hu)
Date: Tue, 24 May 2016 11:05:59 +0800
Subject: [PATCH v7 2/4] CMDQ: Mediatek CMDQ driver
In-Reply-To: <1464006190-344-3-git-send-email-hs.liao@mediatek.com>
References: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
 <1464006190-344-3-git-send-email-hs.liao@mediatek.com>
Message-ID: <1464059159.7425.6.camel@mtksdaap41>

Hi, HS:

Some comments below.

On Mon, 2016-05-23 at 20:23 +0800, HS Liao wrote:
> This patch is first version of Mediatek Command Queue(CMDQ) driver. The
> CMDQ is used to help read/write registers with critical time limitation,
> such as updating display configuration during the vblank. It controls
> Global Command Engine (GCE) hardware to achieve this requirement.
> Currently, CMDQ only supports display related hardwares, but we expect
> it can be extended to other hardwares for future requirements.
> 
> Signed-off-by: HS Liao <hs.liao at mediatek.com>
> Signed-off-by: CK Hu <ck.hu at mediatek.com>
> ---
>  drivers/soc/mediatek/Kconfig    |  10 +
>  drivers/soc/mediatek/Makefile   |   1 +
>  drivers/soc/mediatek/mtk-cmdq.c | 904 ++++++++++++++++++++++++++++++++++++++++
>  include/soc/mediatek/cmdq.h     | 197 +++++++++
>  4 files changed, 1112 insertions(+)
>  create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
>  create mode 100644 include/soc/mediatek/cmdq.h
> 
> diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
> index 0a4ea80..c4ad75c 100644
> --- a/drivers/soc/mediatek/Kconfig
> +++ b/drivers/soc/mediatek/Kconfig
> @@ -1,6 +1,16 @@
>  #
>  # MediaTek SoC drivers
>  #
> +config MTK_CMDQ
> +	bool "MediaTek CMDQ Support"
> +	depends on ARCH_MEDIATEK || COMPILE_TEST
> +	select MTK_INFRACFG
> +	help
> +	  Say yes here to add support for the MediaTek Command Queue (CMDQ)
> +	  driver. The CMDQ is used to help read/write registers with critical
> +	  time limitation, such as updating display configuration during the
> +	  vblank.
> +
>  config MTK_INFRACFG
>  	bool "MediaTek INFRACFG Support"
>  	depends on ARCH_MEDIATEK || COMPILE_TEST
> diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
> index 12998b0..f7397ef 100644
> --- a/drivers/soc/mediatek/Makefile
> +++ b/drivers/soc/mediatek/Makefile
> @@ -1,3 +1,4 @@
> +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq.o
>  obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
>  obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
>  obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
> diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
> new file mode 100644
> index 0000000..f8c5d02
> --- /dev/null
> +++ b/drivers/soc/mediatek/mtk-cmdq.c
> @@ -0,0 +1,904 @@
> +/*
> + * Copyright (c) 2015 MediaTek Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/errno.h>
> +#include <linux/interrupt.h>
> +#include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +#include <linux/kthread.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/suspend.h>
> +#include <linux/workqueue.h>
> +#include <soc/mediatek/cmdq.h>
> +
> +#define CMDQ_INITIAL_CMD_BLOCK_SIZE	PAGE_SIZE
> +#define CMDQ_INST_SIZE			8 /* instruction is 64-bit */
> +
> +#define CMDQ_DEFAULT_TIMEOUT_MS		1000
> +
> +#define CMDQ_DRIVER_DEVICE_NAME		"mtk_cmdq"
> +#define CMDQ_CLK_NAME			"gce"
> +
> +#define CMDQ_CURR_IRQ_STATUS		0x010
> +#define CMDQ_THR_SLOT_CYCLES		0x030
> +
> +#define CMDQ_THR_BASE			0x100
> +#define CMDQ_THR_SHIFT			0x080
> +#define CMDQ_THR_WARM_RESET		0x00
> +#define CMDQ_THR_ENABLE_TASK		0x04
> +#define CMDQ_THR_SUSPEND_TASK		0x08
> +#define CMDQ_THR_CURR_STATUS		0x0c
> +#define CMDQ_THR_IRQ_STATUS		0x10
> +#define CMDQ_THR_IRQ_ENABLE		0x14
> +#define CMDQ_THR_CURR_ADDR		0x20
> +#define CMDQ_THR_END_ADDR		0x24
> +#define CMDQ_THR_CFG			0x40
> +
> +#define CMDQ_IRQ_MASK			0xffff
> +
> +#define CMDQ_THR_ENABLED		0x1
> +#define CMDQ_THR_DISABLED		0x0
> +#define CMDQ_THR_SUSPEND		0x1
> +#define CMDQ_THR_RESUME			0x0
> +#define CMDQ_THR_STATUS_SUSPENDED	BIT(1)
> +#define CMDQ_THR_DO_WARM_RESET		BIT(0)
> +#define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
> +#define CMDQ_THR_PRIORITY		3
> +#define CMDQ_THR_IRQ_DONE		0x1
> +#define CMDQ_THR_IRQ_ERROR		0x12
> +#define CMDQ_THR_IRQ_EN			0x13 /* done + error */
> +#define CMDQ_THR_IRQ_MASK		0x13
> +#define CMDQ_THR_EXECUTING		BIT(31)
> +
> +#define CMDQ_ARG_A_WRITE_MASK		0xffff
> +#define CMDQ_SUBSYS_MASK		0x1f
> +
> +#define CMDQ_OP_CODE_SHIFT		24
> +#define CMDQ_SUBSYS_SHIFT		16
> +
> +#define CMDQ_JUMP_BY_OFFSET		0x10000000
> +#define CMDQ_JUMP_BY_PA			0x10000001
> +#define CMDQ_JUMP_PASS			CMDQ_INST_SIZE
> +
> +#define CMDQ_WFE_UPDATE			BIT(31)
> +#define CMDQ_WFE_WAIT			BIT(15)
> +#define CMDQ_WFE_WAIT_VALUE		0x1
> +
> +#define CMDQ_EOC_IRQ_EN			BIT(0)
> +
> +#define CMDQ_ENABLE_MASK		BIT(0)
> +
> +#define CMDQ_OP_CODE_MASK		0xff000000
> +
> +enum cmdq_thread_index {
> +	CMDQ_THR_DISP_MAIN_IDX,	/* main */
> +	CMDQ_THR_DISP_SUB_IDX,	/* sub */
> +	CMDQ_THR_DISP_MISC_IDX,	/* misc */
> +	CMDQ_THR_MAX_COUNT,	/* max */
> +};
> +
> +/*
> + * CMDQ_CODE_MOVE:
> + *   move value into internal register as mask
> + *   format: op mask
> + * CMDQ_CODE_WRITE:
> + *   write value into target register
> + *   format: op subsys address value
> + * CMDQ_CODE_JUMP:
> + *   jump by offset
> + *   format: op offset
> + * CMDQ_CODE_WFE:
> + *   wait for event and clear
> + *   it is just clear if no wait
> + *   format: [wait]  op event update:1 to_wait:1 wait:1
> + *           [clear] op event update:1 to_wait:0 wait:0
> + * CMDQ_CODE_EOC:
> + *   end of command
> + *   format: op irq_flag
> + */
> +enum cmdq_code {
> +	CMDQ_CODE_MOVE = 0x02,
> +	CMDQ_CODE_WRITE = 0x04,
> +	CMDQ_CODE_JUMP = 0x10,
> +	CMDQ_CODE_WFE = 0x20,
> +	CMDQ_CODE_EOC = 0x40,
> +};
> +
> +enum cmdq_task_state {
> +	TASK_STATE_BUSY,	/* task running on a thread */
> +	TASK_STATE_ERROR,	/* task execution error */
> +	TASK_STATE_DONE,	/* task finished */
> +};
> +
> +struct cmdq_task_cb {
> +	cmdq_async_flush_cb	cb;
> +	void			*data;
> +};
> +
> +struct cmdq_thread {
> +	void __iomem		*base;
> +	struct list_head	task_busy_list;
> +	wait_queue_head_t	wait_queue; /* wait task done */
> +};
> +
> +
> +struct cmdq_task {
> +	struct cmdq		*cmdq;
> +	struct list_head	list_entry;
> +	enum cmdq_task_state	task_state;
> +	void			*va_base; /* va */

It's obviously that va_base is va, so the comment is redundant.

> +	dma_addr_t		mva_base; /* pa */
> +	u64			engine_flag;
> +	size_t			command_size;
> +	u32			num_cmd;
> +	struct cmdq_thread	*thread;
> +	struct cmdq_task_cb	cb;
> +	struct work_struct	release_work;
> +};
> +
> +struct cmdq {
> +	struct device		*dev;
> +	void __iomem		*base;
> +	u32			irq;
> +	struct workqueue_struct	*task_release_wq;
> +	struct cmdq_thread	thread[CMDQ_THR_MAX_COUNT];
> +	spinlock_t		exec_lock;	/* for exec task */
> +	struct clk		*clock;
> +};
> +
> +struct cmdq_subsys {
> +	u32	base_addr;
> +	int	id;
> +};
> +
> +static const struct cmdq_subsys g_subsys[] = {
> +	{0x1400, 1},
> +	{0x1401, 2},
> +	{0x1402, 3},
> +};
> +
> +static int cmdq_subsys_base_addr_to_id(u32 base_addr)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(g_subsys); i++)
> +		if (g_subsys[i].base_addr == base_addr)
> +			return g_subsys[i].id;
> +	return -EFAULT;
> +}
> +
> +static int cmdq_eng_get_thread(u64 flag)
> +{
> +	if (flag & BIT_ULL(CMDQ_ENG_DISP_DSI0))
> +		return CMDQ_THR_DISP_MAIN_IDX;
> +	else if (flag & BIT_ULL(CMDQ_ENG_DISP_DPI0))
> +		return CMDQ_THR_DISP_SUB_IDX;
> +	else
> +		return CMDQ_THR_DISP_MISC_IDX;
> +}
> +
> +static void cmdq_task_release(struct cmdq_task *task)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +
> +	dma_free_coherent(cmdq->dev, task->command_size, task->va_base,
> +			  task->mva_base);
> +	kfree(task);
> +}
> +
> +static struct cmdq_task *cmdq_task_acquire(struct cmdq_rec *rec,
> +					   struct cmdq_task_cb cb)
> +{
> +	struct cmdq *cmdq = rec->cmdq;
> +	struct device *dev = cmdq->dev;
> +	struct cmdq_task *task;
> +
> +	task = kzalloc(sizeof(*task), GFP_KERNEL);
> +	INIT_LIST_HEAD(&task->list_entry);
> +	task->va_base = dma_alloc_coherent(dev, rec->command_size,
> +					   &task->mva_base, GFP_KERNEL);
> +	if (!task->va_base) {
> +		dev_err(dev, "allocate command buffer failed\n");
> +		kfree(task);
> +		return NULL;
> +	}
> +
> +	task->cmdq = cmdq;
> +	task->command_size = rec->command_size;
> +	task->engine_flag = rec->engine_flag;
> +	task->task_state = TASK_STATE_BUSY;
> +	task->cb = cb;
> +	memcpy(task->va_base, rec->buf, rec->command_size);
> +	task->num_cmd = task->command_size / sizeof(u64);

Already define CMDQ_INST_SIZE, so use it and the readability is better.

> +	return task;
> +}
> +
> +static void cmdq_thread_writel(struct cmdq_thread *thread, u32 value,
> +			       u32 offset)
> +{
> +	writel(value, thread->base + offset);
> +}
> +
> +static u32 cmdq_thread_readl(struct cmdq_thread *thread, u32 offset)
> +{
> +	return readl(thread->base + offset);
> +}
> +
> +static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
> +{
> +	u32 enabled;
> +	u32 status;
> +
> +	cmdq_thread_writel(thread, CMDQ_THR_SUSPEND, CMDQ_THR_SUSPEND_TASK);
> +
> +	/* If already disabled, treat as suspended successful. */
> +	enabled = cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK);
> +	if (!(enabled & CMDQ_THR_ENABLED))
> +		return 0;
> +
> +	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_CURR_STATUS,
> +				      status,
> +				      status & CMDQ_THR_STATUS_SUSPENDED,
> +				      0, 10)) {
> +		dev_err(cmdq->dev, "Suspend HW thread 0x%x failed\n",
> +			(u32)(thread->base - cmdq->base));
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static void cmdq_thread_resume(struct cmdq_thread *thread)
> +{
> +	cmdq_thread_writel(thread, CMDQ_THR_RESUME, CMDQ_THR_SUSPEND_TASK);
> +}
> +
> +static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
> +{
> +	void __iomem *gce_base = cmdq->base;
> +	u32 warm_reset;
> +
> +	cmdq_thread_writel(thread, CMDQ_THR_DO_WARM_RESET, CMDQ_THR_WARM_RESET);
> +	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET,
> +				      warm_reset,
> +				      !(warm_reset & CMDQ_THR_DO_WARM_RESET),
> +				      0, 10)) {
> +		dev_err(cmdq->dev, "Reset HW thread 0x%x failed\n",
> +			(u32)(thread->base - cmdq->base));
> +		return -EFAULT;
> +	}
> +	writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, gce_base + CMDQ_THR_SLOT_CYCLES);
> +	return 0;
> +}
> +
> +static void cmdq_thread_disable(struct cmdq *cmdq, struct cmdq_thread *thread)
> +{
> +	cmdq_thread_reset(cmdq, thread);
> +	cmdq_thread_writel(thread, CMDQ_THR_DISABLED, CMDQ_THR_ENABLE_TASK);
> +}
> +
> +/* notify GCE to re-fetch commands by setting HW thread PC */
> +static void cmdq_thread_invalidate_fetched_data(struct cmdq_thread *thread)
> +{
> +	cmdq_thread_writel(thread,
> +			   cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR),
> +			   CMDQ_THR_CURR_ADDR);
> +}
> +
> +static void cmdq_task_insert_into_thread(struct cmdq_task *task)
> +{
> +	struct cmdq_thread *thread = task->thread;
> +	struct cmdq_task *prev_task = list_last_entry(
> +			&thread->task_busy_list, typeof(*task), list_entry);
> +	u64 *prev_task_base = prev_task->va_base;
> +
> +	/* let previous task jump to this task */
> +	prev_task_base[prev_task->num_cmd - 1] = (u64)CMDQ_JUMP_BY_PA << 32 |
> +						 task->mva_base;
> +
> +	cmdq_thread_invalidate_fetched_data(thread);
> +}
> +
> +/* we assume tasks in the same display thread are waiting the same event. */
> +static void cmdq_task_remove_wfe(struct cmdq_task *task)
> +{
> +	u32 wfe_option = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
> +	u32 wfe_op = CMDQ_CODE_WFE << CMDQ_OP_CODE_SHIFT;
> +	u32 *base = task->va_base;
> +	u32 num_cmd = task->num_cmd << 1;
> +	int i;
> +
> +	for (i = 0; i < num_cmd; i += 2)
> +		if (base[i] == wfe_option &&
> +		    (base[i + 1] & CMDQ_OP_CODE_MASK) == wfe_op) {
> +			base[i] = CMDQ_JUMP_PASS;
> +			base[i + 1] = CMDQ_JUMP_BY_OFFSET;
> +		}
> +}
> +
> +static void cmdq_task_exec(struct cmdq_task *task, struct cmdq_thread *thread)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +	unsigned long flags;
> +	unsigned long curr_pa, end_pa;
> +
> +	WARN_ON(clk_prepare_enable(cmdq->clock) < 0);
> +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> +	task->thread = thread;
> +	task->task_state = TASK_STATE_BUSY;

Once a task is created, its state is already BUSY, so this assignment is
redundant.

> +	if (list_empty(&thread->task_busy_list)) {
> +		WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
> +
> +		cmdq_thread_writel(thread, task->mva_base, CMDQ_THR_CURR_ADDR);
> +		cmdq_thread_writel(thread, task->mva_base + task->command_size,
> +				   CMDQ_THR_END_ADDR);
> +		cmdq_thread_writel(thread, CMDQ_THR_PRIORITY, CMDQ_THR_CFG);
> +		cmdq_thread_writel(thread, CMDQ_THR_IRQ_EN,
> +				   CMDQ_THR_IRQ_ENABLE);
> +
> +		list_move_tail(&task->list_entry,
> +			       &thread->task_busy_list);

Moving this statement to just before spin_unlock_irqrestore() can reduce
the duplicated code in else part.

> +
> +		cmdq_thread_writel(thread, CMDQ_THR_ENABLED,
> +				   CMDQ_THR_ENABLE_TASK);
> +	} else {
> +		WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
> +
> +		/*
> +		 * check boundary condition
> +		 * PC = END - 8, EOC is executed
> +		 * PC = END, all CMDs are executed
> +		 */
> +		curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
> +		end_pa = cmdq_thread_readl(thread, CMDQ_THR_END_ADDR);
> +		if (curr_pa == end_pa - 8 || curr_pa == end_pa) {
> +			/* set to this task directly */
> +			cmdq_thread_writel(thread, task->mva_base,
> +					   CMDQ_THR_CURR_ADDR);
> +		} else {
> +			cmdq_task_insert_into_thread(task);
> +
> +			if (thread == &cmdq->thread[CMDQ_THR_DISP_MAIN_IDX] ||
> +			    thread == &cmdq->thread[CMDQ_THR_DISP_SUB_IDX])
> +				cmdq_task_remove_wfe(task);
> +
> +			smp_mb(); /* modify jump before enable thread */
> +		}
> +
> +		cmdq_thread_writel(thread, task->mva_base + task->command_size,
> +				   CMDQ_THR_END_ADDR);
> +		list_move_tail(&task->list_entry, &thread->task_busy_list);
> +		cmdq_thread_resume(thread);
> +	}
> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +}
> +
> +static void cmdq_handle_error_done(struct cmdq *cmdq,
> +				   struct cmdq_thread *thread, bool err)
> +{
> +	struct cmdq_task *task, *tmp, *curr_task = NULL;
> +	u32 curr_pa;
> +	struct cmdq_cb_data cmdq_cb_data;
> +
> +	curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
> +
> +	list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
> +				 list_entry) {
> +		if (curr_pa >= task->mva_base &&
> +		    curr_pa < (task->mva_base + task->command_size))
> +			curr_task = task;
> +		if (task->cb.cb) {
> +			cmdq_cb_data.err = curr_task ? err : false;
> +			cmdq_cb_data.data = task->cb.data;
> +			task->cb.cb(cmdq_cb_data);
> +		}
> +		task->task_state = (curr_task && err) ? TASK_STATE_ERROR :
> +				TASK_STATE_DONE;
> +		list_del(&task->list_entry);
> +		if (curr_task)
> +			break;
> +	}
> +
> +	wake_up(&thread->wait_queue);
> +}
> +
> +static void cmdq_thread_irq_handler(struct cmdq *cmdq, int tid)
> +{
> +	struct cmdq_thread *thread = &cmdq->thread[tid];
> +	unsigned long flags = 0L;
> +	int value;
> +
> +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> +
> +	/*
> +	 * it is possible for another CPU core
> +	 * to run "release task" right before we acquire the spin lock
> +	 * and thus reset / disable this HW thread
> +	 * so we check both the IRQ flag and the enable bit of this thread
> +	 */
> +	value = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> +	if (!(value & CMDQ_THR_IRQ_MASK)) {
> +		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +		return;
> +	}

If this case happen and just return without clearing irq status, the irq
would keep triggering and system hang up. So just remove this checking
and go down to clear irq status.

> +
> +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> +	      CMDQ_THR_ENABLED)) {
> +		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +		return;
> +	}
> +
> +	cmdq_thread_writel(thread, ~value, CMDQ_THR_IRQ_STATUS);
> +
> +	if (value & CMDQ_THR_IRQ_ERROR)
> +		cmdq_handle_error_done(cmdq, thread, true);
> +	else if (value & CMDQ_THR_IRQ_DONE)
> +		cmdq_handle_error_done(cmdq, thread, false);

These irq status checking and clearing code here is the same as those in
cmdq_task_handle_error_result(). To move the checking and clearing code
into cmdq_handle_error_done() and here just to call
cmdq_handle_error_done(cmdq, thread) would reduce duplicated code.

> +
> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +}
> +
> +static irqreturn_t cmdq_irq_handler(int irq, void *dev)
> +{
> +	struct cmdq *cmdq = dev;
> +	u32 irq_status;
> +	int i;
> +
> +	irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS);
> +	irq_status &= CMDQ_IRQ_MASK;
> +	irq_status ^= CMDQ_IRQ_MASK;
> +
> +	if (!irq_status)
> +		return IRQ_NONE;
> +
> +	while (irq_status) {
> +		i = ffs(irq_status) - 1;
> +		irq_status &= ~BIT(i);
> +		cmdq_thread_irq_handler(cmdq, i);
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int cmdq_task_handle_error_result(struct cmdq_task *task)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +	struct device *dev = cmdq->dev;
> +	struct cmdq_thread *thread = task->thread;
> +	struct cmdq_task *next_task, *prev_task;
> +	u32 irq_flag;
> +
> +	/* suspend HW thread to ensure consistency */
> +	WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
> +
> +	/*
> +	 * Save next_task and prev_task in advance
> +	 * since cmdq_handle_error_done will remove list_entry.
> +	 */
> +	next_task = prev_task = NULL;
> +	if (task->list_entry.next != &thread->task_busy_list)
> +		next_task = list_next_entry(task, list_entry);
> +	if (task->list_entry.prev != &thread->task_busy_list)
> +		prev_task = list_prev_entry(task, list_entry);
> +
> +	/*
> +	 * Although IRQ is disabled, GCE continues to execute.
> +	 * It may have pending IRQ before HW thread is suspended,
> +	 * so check this condition again.
> +	 */
> +	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> +	if (irq_flag & CMDQ_THR_IRQ_ERROR)
> +		cmdq_handle_error_done(cmdq, thread, true);
> +	else if (irq_flag & CMDQ_THR_IRQ_DONE)
> +		cmdq_handle_error_done(cmdq, thread, false);
> +	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
> +
> +	if (task->task_state == TASK_STATE_DONE) {
> +		cmdq_thread_resume(thread);
> +		return 0;
> +	}
> +
> +	if (task->task_state == TASK_STATE_ERROR) {
> +		dev_err(dev, "task 0x%p error\n", task);
> +		if (next_task) /* move to next task */
> +			cmdq_thread_writel(thread, next_task->mva_base,
> +					   CMDQ_THR_CURR_ADDR);
> +		cmdq_thread_resume(thread);
> +		return -ECANCELED;
> +	}
> +
> +	/* If task is running, force to remove it. */
> +	dev_err(dev, "task 0x%p timeout or killed\n", task);
> +
> +	if (task->task_state == TASK_STATE_BUSY)

The state must be BUSY here, so the checking is redundant.

> +		task->task_state = TASK_STATE_ERROR;
> +
> +	if (prev_task) {
> +		u64 *prev_va = prev_task->va_base;
> +		u64 *curr_va = task->va_base;
> +
> +		/* copy JUMP instruction */
> +		prev_va[prev_task->num_cmd - 1] = curr_va[task->num_cmd - 1];
> +
> +		cmdq_thread_invalidate_fetched_data(thread);
> +	} else if (next_task) { /* move to next task */
> +		cmdq_thread_writel(thread, next_task->mva_base,
> +				   CMDQ_THR_CURR_ADDR);
> +	}
> +
> +	list_del(&task->list_entry);
> +	cmdq_thread_resume(thread);
> +
> +	/* call cb here to prevent lock */
> +	if (task->cb.cb) {
> +		struct cmdq_cb_data cmdq_cb_data;
> +
> +		cmdq_cb_data.err = true;
> +		cmdq_cb_data.data = task->cb.data;
> +		task->cb.cb(cmdq_cb_data);
> +	}
> +
> +	return -ECANCELED;
> +}
> +
> +static int cmdq_task_wait_and_release(struct cmdq_task *task)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +	struct device *dev = cmdq->dev;
> +	struct cmdq_thread *thread = task->thread;
> +	int wait_q;
> +	int err = 0;
> +	unsigned long flags;
> +
> +	wait_q = wait_event_timeout(thread->wait_queue,
> +				    task->task_state != TASK_STATE_BUSY,
> +				    msecs_to_jiffies(CMDQ_DEFAULT_TIMEOUT_MS));
> +	if (!wait_q)
> +		dev_dbg(dev, "timeout!\n");

Task state may be changed in cmdq_task_handle_error_result() and the
actual time out message print is in cmdq_task_handle_error_result(), so
this print should be removed.

> +
> +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> +	if (task->task_state != TASK_STATE_DONE)
> +		err = cmdq_task_handle_error_result(task);
> +	if (list_empty(&thread->task_busy_list))
> +		cmdq_thread_disable(cmdq, thread);
> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +
> +	/* release regardless of success or not */
> +	clk_disable_unprepare(cmdq->clock);
> +	cmdq_task_release(task);
> +
> +	return err;
> +}
> +
> +static void cmdq_task_wait_release_work(struct work_struct *work_item)
> +{
> +	struct cmdq_task *task = container_of(work_item, struct cmdq_task,
> +					      release_work);
> +
> +	cmdq_task_wait_and_release(task);
> +}
> +
> +static void cmdq_task_wait_release_schedule(struct cmdq_task *task)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +
> +	INIT_WORK(&task->release_work, cmdq_task_wait_release_work);
> +	queue_work(cmdq->task_release_wq, &task->release_work);
> +}
> +
> +static int cmdq_rec_realloc_cmd_buffer(struct cmdq_rec *rec, size_t size)
> +{
> +	void *new_buf;
> +
> +	new_buf = krealloc(rec->buf, size, GFP_KERNEL | __GFP_ZERO);
> +	if (!new_buf)
> +		return -ENOMEM;
> +	rec->buf = new_buf;
> +	rec->buf_size = size;
> +	return 0;
> +}
> +
> +struct cmdq_base *cmdq_register_device(struct device *dev)
> +{
> +	struct cmdq_base *cmdq_base;
> +	struct resource res;
> +	int subsys;
> +	u32 base;
> +
> +	if (of_address_to_resource(dev->of_node, 0, &res))
> +		return NULL;
> +	base = (u32)res.start;
> +
> +	subsys = cmdq_subsys_base_addr_to_id(base >> 16);
> +	if (subsys < 0)
> +		return NULL;
> +
> +	cmdq_base = devm_kmalloc(dev, sizeof(*cmdq_base), GFP_KERNEL);
> +	if (!cmdq_base)
> +		return NULL;
> +	cmdq_base->subsys = subsys;
> +	cmdq_base->base = base;
> +
> +	return cmdq_base;
> +}
> +EXPORT_SYMBOL(cmdq_register_device);
> +
> +int cmdq_rec_create(struct device *dev, u64 engine_flag,
> +		    struct cmdq_rec **rec_ptr)
> +{
> +	struct cmdq_rec *rec;
> +	int err;
> +
> +	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
> +	if (!rec)
> +		return -ENOMEM;
> +	rec->cmdq = dev_get_drvdata(dev);
> +	rec->engine_flag = engine_flag;
> +	err = cmdq_rec_realloc_cmd_buffer(rec, CMDQ_INITIAL_CMD_BLOCK_SIZE);
> +	if (err < 0) {
> +		kfree(rec);
> +		return err;
> +	}
> +	*rec_ptr = rec;
> +	return 0;
> +}
> +EXPORT_SYMBOL(cmdq_rec_create);
> +
> +static int cmdq_rec_append_command(struct cmdq_rec *rec, enum cmdq_code code,
> +				   u32 arg_a, u32 arg_b)
> +{
> +	u64 *cmd_ptr;
> +	int err;
> +
> +	if (WARN_ON(rec->finalized))
> +		return -EBUSY;
> +	if (code < CMDQ_CODE_MOVE || code > CMDQ_CODE_EOC)
> +		return -EINVAL;
> +	if (unlikely(rec->command_size + CMDQ_INST_SIZE > rec->buf_size)) {
> +		err = cmdq_rec_realloc_cmd_buffer(rec, rec->buf_size * 2);
> +		if (err < 0)
> +			return err;
> +	}
> +	cmd_ptr = rec->buf + rec->command_size;
> +	(*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b;
> +	rec->command_size += CMDQ_INST_SIZE;
> +	return 0;
> +}
> +
> +int cmdq_rec_write(struct cmdq_rec *rec, u32 value, struct cmdq_base *base,
> +		   u32 offset)
> +{
> +	u32 arg_a = ((base->base + offset) & CMDQ_ARG_A_WRITE_MASK) |
> +		    ((base->subsys & CMDQ_SUBSYS_MASK) << CMDQ_SUBSYS_SHIFT);
> +	return cmdq_rec_append_command(rec, CMDQ_CODE_WRITE, arg_a, value);
> +}
> +EXPORT_SYMBOL(cmdq_rec_write);
> +
> +int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
> +			struct cmdq_base *base, u32 offset, u32 mask)
> +{
> +	u32 offset_mask = offset;
> +	int err;
> +
> +	if (mask != 0xffffffff) {
> +		err = cmdq_rec_append_command(rec, CMDQ_CODE_MOVE, 0, ~mask);
> +		if (err < 0)
> +			return err;
> +		offset_mask |= CMDQ_ENABLE_MASK;
> +	}
> +	return cmdq_rec_write(rec, value, base, offset_mask);
> +}
> +EXPORT_SYMBOL(cmdq_rec_write_mask);
> +
> +int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event)
> +{
> +	u32 arg_b;
> +
> +	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
> +		return -EINVAL;
> +
> +	/*
> +	 * bit 0-11: wait value
> +	 * bit 15: 1 - wait, 0 - no wait
> +	 * bit 16-27: update value
> +	 * bit 31: 1 - update, 0 - no update
> +	 */
> +	arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
> +	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event, arg_b);
> +}
> +EXPORT_SYMBOL(cmdq_rec_wfe);
> +
> +int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event)
> +{
> +	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
> +		return -EINVAL;
> +
> +	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event,
> +				       CMDQ_WFE_UPDATE);
> +}
> +EXPORT_SYMBOL(cmdq_rec_clear_event);
> +
> +static int cmdq_rec_finalize(struct cmdq_rec *rec)
> +{
> +	int err;
> +
> +	if (rec->finalized)
> +		return 0;
> +
> +	/* insert EOC and generate IRQ for each command iteration */
> +	err = cmdq_rec_append_command(rec, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN);
> +	if (err < 0)
> +		return err;
> +
> +	/* JUMP to end */
> +	err = cmdq_rec_append_command(rec, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS);
> +	if (err < 0)
> +		return err;
> +
> +	rec->finalized = true;
> +	return 0;
> +}
> +
> +static int _cmdq_rec_flush(struct cmdq_rec *rec, struct cmdq_task **task_out,
> +			   cmdq_async_flush_cb cb, void *data)
> +{
> +	struct cmdq *cmdq = rec->cmdq;
> +	struct cmdq_task_cb task_cb;
> +	struct cmdq_thread *thread;
> +	int err;
> +
> +	err = cmdq_rec_finalize(rec);
> +	if (err < 0)
> +		return err;
> +
> +	task_cb.cb = cb;
> +	task_cb.data = data;
> +	*task_out = cmdq_task_acquire(rec, task_cb);
> +	if (!(*task_out))
> +		return -EFAULT;
> +
> +	thread = &cmdq->thread[cmdq_eng_get_thread((*task_out)->engine_flag)];
> +	cmdq_task_exec(*task_out, thread);
> +	return 0;
> +}
> +
> +int cmdq_rec_flush(struct cmdq_rec *rec)
> +{
> +	struct cmdq_task *task;
> +	int err;
> +
> +	err = _cmdq_rec_flush(rec, &task, NULL, NULL);
> +	if (err < 0)
> +		return err;
> +	return cmdq_task_wait_and_release(task);
> +}
> +EXPORT_SYMBOL(cmdq_rec_flush);
> +
> +int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
> +			 void *data)
> +{
> +	struct cmdq_task *task;
> +	int err;
> +
> +	err = _cmdq_rec_flush(rec, &task, cb, data);
> +	if (err < 0)
> +		return err;
> +	cmdq_task_wait_release_schedule(task);
> +	return 0;
> +}
> +EXPORT_SYMBOL(cmdq_rec_flush_async);
> +
> +void cmdq_rec_destroy(struct cmdq_rec *rec)
> +{
> +	kfree(rec->buf);
> +	kfree(rec);
> +}
> +EXPORT_SYMBOL(cmdq_rec_destroy);
> +
> +static int cmdq_remove(struct platform_device *pdev)
> +{
> +	struct cmdq *cmdq = platform_get_drvdata(pdev);
> +
> +	destroy_workqueue(cmdq->task_release_wq);
> +	cmdq->task_release_wq = NULL;
> +	return 0;
> +}
> +
> +static int cmdq_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *node = dev->of_node;
> +	struct resource *res;
> +	struct cmdq *cmdq;
> +	int err, i;
> +
> +	cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
> +	if (!cmdq)
> +		return -ENOMEM;
> +	cmdq->dev = dev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	cmdq->base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(cmdq->base)) {
> +		dev_err(dev, "failed to ioremap gce\n");
> +		return PTR_ERR(cmdq->base);
> +	}
> +
> +	cmdq->irq = irq_of_parse_and_map(node, 0);
> +	if (!cmdq->irq) {
> +		dev_err(dev, "failed to get irq\n");
> +		return -EINVAL;
> +	}
> +
> +	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
> +		dev, cmdq->base, cmdq->irq);
> +
> +	spin_lock_init(&cmdq->exec_lock);
> +	cmdq->task_release_wq = alloc_ordered_workqueue(
> +			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI,
> +			"cmdq_task_wait_release");
> +
> +	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
> +		cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
> +				CMDQ_THR_SHIFT * i;
> +		init_waitqueue_head(&cmdq->thread[i].wait_queue);
> +		INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list);
> +	}
> +
> +	platform_set_drvdata(pdev, cmdq);
> +
> +	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
> +			       CMDQ_DRIVER_DEVICE_NAME, cmdq);
> +	if (err < 0) {
> +		dev_err(dev, "failed to register ISR (%d)\n", err);
> +		goto fail;
> +	}
> +
> +	cmdq->clock = devm_clk_get(dev, CMDQ_CLK_NAME);
> +	if (IS_ERR(cmdq->clock)) {
> +		dev_err(dev, "failed to get clk:%s\n", CMDQ_CLK_NAME);
> +		err = PTR_ERR(cmdq->clock);
> +		goto fail;
> +	}
> +	return 0;
> +
> +fail:
> +	cmdq_remove(pdev);
> +	return err;
> +}
> +
> +static const struct of_device_id cmdq_of_ids[] = {
> +	{.compatible = "mediatek,mt8173-gce",},
> +	{}
> +};
> +
> +static struct platform_driver cmdq_drv = {
> +	.probe = cmdq_probe,
> +	.remove = cmdq_remove,
> +	.driver = {
> +		.name = CMDQ_DRIVER_DEVICE_NAME,
> +		.owner = THIS_MODULE,
> +		.of_match_table = cmdq_of_ids,
> +	}
> +};
> +
> +builtin_platform_driver(cmdq_drv);
> diff --git a/include/soc/mediatek/cmdq.h b/include/soc/mediatek/cmdq.h
> new file mode 100644
> index 0000000..60eef3d
> --- /dev/null
> +++ b/include/soc/mediatek/cmdq.h
> @@ -0,0 +1,197 @@
> +/*
> + * Copyright (c) 2015 MediaTek Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MTK_CMDQ_H__
> +#define __MTK_CMDQ_H__
> +
> +#include <linux/platform_device.h>
> +#include <linux/types.h>
> +
> +enum cmdq_eng {
> +	CMDQ_ENG_DISP_AAL,
> +	CMDQ_ENG_DISP_COLOR0,
> +	CMDQ_ENG_DISP_COLOR1,
> +	CMDQ_ENG_DISP_DPI0,
> +	CMDQ_ENG_DISP_DSI0,
> +	CMDQ_ENG_DISP_DSI1,
> +	CMDQ_ENG_DISP_GAMMA,
> +	CMDQ_ENG_DISP_OD,
> +	CMDQ_ENG_DISP_OVL0,
> +	CMDQ_ENG_DISP_OVL1,
> +	CMDQ_ENG_DISP_PWM0,
> +	CMDQ_ENG_DISP_PWM1,
> +	CMDQ_ENG_DISP_RDMA0,
> +	CMDQ_ENG_DISP_RDMA1,
> +	CMDQ_ENG_DISP_RDMA2,
> +	CMDQ_ENG_DISP_UFOE,
> +	CMDQ_ENG_DISP_WDMA0,
> +	CMDQ_ENG_DISP_WDMA1,
> +	CMDQ_ENG_MAX,
> +};
> +
> +/* events for CMDQ and display */
> +enum cmdq_event {
> +	/* Display start of frame(SOF) events */
> +	CMDQ_EVENT_DISP_OVL0_SOF = 11,
> +	CMDQ_EVENT_DISP_OVL1_SOF = 12,
> +	CMDQ_EVENT_DISP_RDMA0_SOF = 13,
> +	CMDQ_EVENT_DISP_RDMA1_SOF = 14,
> +	CMDQ_EVENT_DISP_RDMA2_SOF = 15,
> +	CMDQ_EVENT_DISP_WDMA0_SOF = 16,
> +	CMDQ_EVENT_DISP_WDMA1_SOF = 17,
> +	/* Display end of frame(EOF) events */
> +	CMDQ_EVENT_DISP_OVL0_EOF = 39,
> +	CMDQ_EVENT_DISP_OVL1_EOF = 40,
> +	CMDQ_EVENT_DISP_RDMA0_EOF = 41,
> +	CMDQ_EVENT_DISP_RDMA1_EOF = 42,
> +	CMDQ_EVENT_DISP_RDMA2_EOF = 43,
> +	CMDQ_EVENT_DISP_WDMA0_EOF = 44,
> +	CMDQ_EVENT_DISP_WDMA1_EOF = 45,
> +	/* Mutex end of frame(EOF) events */
> +	CMDQ_EVENT_MUTEX0_STREAM_EOF = 53,
> +	CMDQ_EVENT_MUTEX1_STREAM_EOF = 54,
> +	CMDQ_EVENT_MUTEX2_STREAM_EOF = 55,
> +	CMDQ_EVENT_MUTEX3_STREAM_EOF = 56,
> +	CMDQ_EVENT_MUTEX4_STREAM_EOF = 57,
> +	/* Display underrun events */
> +	CMDQ_EVENT_DISP_RDMA0_UNDERRUN = 63,
> +	CMDQ_EVENT_DISP_RDMA1_UNDERRUN = 64,
> +	CMDQ_EVENT_DISP_RDMA2_UNDERRUN = 65,
> +	/* Keep this at the end of HW events */
> +	CMDQ_MAX_HW_EVENT_COUNT = 260,
> +};
> +
> +struct cmdq_cb_data {
> +	bool	err;
> +	void	*data;
> +};
> +
> +typedef int (*cmdq_async_flush_cb)(struct cmdq_cb_data data);
> +
> +struct cmdq_task;
> +struct cmdq;
> +
> +struct cmdq_rec {
> +	struct cmdq		*cmdq;
> +	u64			engine_flag;
> +	size_t			command_size;
> +	void			*buf;
> +	size_t			buf_size;
> +	bool			finalized;
> +};
> +
> +struct cmdq_base {
> +	int	subsys;
> +	u32	base;
> +};
> +
> +/**
> + * cmdq_register_device() - register device which needs CMDQ
> + * @dev:		device
> + *
> + * Return: cmdq_base pointer or NULL for failed
> + */
> +struct cmdq_base *cmdq_register_device(struct device *dev);
> +
> +/**
> + * cmdq_rec_create() - create command queue record
> + * @dev:		device
> + * @engine_flag:	command queue engine flag
> + * @rec_ptr:		command queue record pointer to retrieve cmdq_rec
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_create(struct device *dev, u64 engine_flag,
> +		    struct cmdq_rec **rec_ptr);
> +
> +/**
> + * cmdq_rec_write() - append write command to the command queue record
> + * @rec:	the command queue record
> + * @value:	the specified target register value
> + * @base:	the command queue base
> + * @offset:	register offset from module base
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_write(struct cmdq_rec *rec, u32 value,
> +		   struct cmdq_base *base, u32 offset);
> +
> +/**
> + * cmdq_rec_write_mask() - append write command with mask to the command
> + *			   queue record
> + * @rec:	the command queue record
> + * @value:	the specified target register value
> + * @base:	the command queue base
> + * @offset:	register offset from module base
> + * @mask:	the specified target register mask
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
> +			struct cmdq_base *base, u32 offset, u32 mask);
> +
> +/**
> + * cmdq_rec_wfe() - append wait for event command to the command queue record
> + * @rec:	the command queue record
> + * @event:	the desired event type to "wait and CLEAR"
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event);
> +
> +/**
> + * cmdq_rec_clear_event() - append clear event command to the command queue
> + *			    record
> + * @rec:	the command queue record
> + * @event:	the desired event to be cleared
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event);
> +
> +/**
> + * cmdq_rec_flush() - trigger CMDQ to execute the recorded commands
> + * @rec:	the command queue record
> + *
> + * Return: 0 for success; else the error code is returned
> + *
> + * Trigger CMDQ to execute the recorded commands. Note that this is a
> + * synchronous flush function. When the function returned, the recorded
> + * commands have been done.
> + */
> +int cmdq_rec_flush(struct cmdq_rec *rec);
> +
> +/**
> + * cmdq_rec_flush_async() - trigger CMDQ to asynchronously execute the recorded
> + *			    commands and call back after ISR is finished
> + * @rec:	the command queue record
> + * @cb:		called in the end of CMDQ ISR
> + * @data:	this data will pass back to cb
> + *
> + * Return: 0 for success; else the error code is returned
> + *
> + * Trigger CMDQ to asynchronously execute the recorded commands and call back
> + * after ISR is finished. Note that this is an ASYNC function. When the function
> + * returned, it may or may not be finished. The ISR callback function is called
> + * in the end of ISR.
> + */
> +int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
> +			 void *data);
> +
> +/**
> + * cmdq_rec_destroy() - destroy command queue record
> + * @rec:	the command queue record
> + */
> +void cmdq_rec_destroy(struct cmdq_rec *rec);
> +
> +#endif	/* __MTK_CMDQ_H__ */


Regards,
CK




From edubezval at gmail.com  Mon May 23 20:08:27 2016
From: edubezval at gmail.com (Eduardo Valentin)
Date: Mon, 23 May 2016 20:08:27 -0700
Subject: [PATCH v2 0/5] Thermal: Support for hardware-tracked trip points
In-Reply-To: <5742B217.4080405@gmail.com>
References: <1462268013-14992-1-git-send-email-wxt@rock-chips.com>
 <5742B217.4080405@gmail.com>
Message-ID: <20160524030825.GA3489@localhost.localdomain>

On Mon, May 23, 2016 at 03:32:39PM +0800, Caesar Wang wrote:
> Hello Eduardo & 'Zhang Rui'
> 
> Do we have the chance to merge this series patches for next kernel?
> I had picked them up in my github, and tested for a period of time with
> rockchip inside kernel.
> 
> Let me know if someone have some suggestions or against opinios.
> Thanks,

I will have a look after after the current merge window.

Thanks.



From hongkun.cao at mediatek.com  Mon May 23 20:10:54 2016
From: hongkun.cao at mediatek.com (hongkun.cao)
Date: Tue, 24 May 2016 11:10:54 +0800
Subject: [PATCH] pinctrl: mediatek: fix dual-edge code defect
In-Reply-To: <5742DDE5.7050701@gmail.com>
References: <1463815419-11719-1-git-send-email-hongkun.cao@mediatek.com>
 <5742DDE5.7050701@gmail.com>
Message-ID: <1464059454.27362.16.camel@mtksdaap41>

On Mon, 2016-05-23 at 12:39 +0200, Matthias Brugger wrote:
> 
> On 21/05/16 09:23, hongkun.cao at mediatek.com wrote:
> > From: "hongkun.cao" <hongkun.cao at mediatek.com>
> >
> > When a dual-edge irq is triggered, an incorrect irq will be reported on
> > condition that the external signal is not stable and this incorrect irq
> > has been registered.
> > Correct the register offset.
> >
> 
> I'm not sure what you want to say. From what I can see the without this 
> fix, the the wrong IRQ will be cleared and raised. Is this what you are 
> addressing?
> 
> If so:

Hi, Matthias,
Thanks for your comments.
Yes, you are right.
Suppose there are two irqs registered in our system with special
relationship, One hardware irq  number is 17 with both edge trigger, and
the other hardware irq number is 49(17+32),then hardware irq 49 may be
reported unexpectedly if hardware irq 17 occurred.

> Reviewed-by: Matthias Brugger <matthias.bgg at gmail.com>
> 
> > Signed-off-by: hongkun.cao <hongkun.cao at mediatek.com>
> > ---
> >   drivers/pinctrl/mediatek/pinctrl-mtk-common.c |    5 +++--
> >   1 file changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
> > index 2bbe6f7..92ae49f 100644
> > --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
> > +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
> > @@ -1255,9 +1255,10 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
> >   	const struct mtk_desc_pin *pin;
> >
> >   	chained_irq_enter(chip, desc);
> > -	for (eint_num = 0; eint_num < pctl->devdata->ap_num; eint_num += 32) {
> > +	for (eint_num = 0;
> > +	     eint_num < pctl->devdata->ap_num;
> > +	     eint_num += 32, reg += 4) {
> >   		status = readl(reg);
> > -		reg += 4;
> >   		while (status) {
> >   			offset = __ffs(status);
> >   			index = eint_num + offset;
> >




From lokeshvutla at ti.com  Mon May 23 20:36:16 2016
From: lokeshvutla at ti.com (Lokesh Vutla)
Date: Tue, 24 May 2016 09:06:16 +0530
Subject: [PATCH 2/3] arm: mach-keystone: Enable PINCTRL config
In-Reply-To: <1464006547-19569-3-git-send-email-j-keerthy@ti.com>
References: <1464006547-19569-1-git-send-email-j-keerthy@ti.com>
 <1464006547-19569-3-git-send-email-j-keerthy@ti.com>
Message-ID: <5743CC30.6010009@ti.com>



On Monday 23 May 2016 05:59 PM, Keerthy wrote:
> keystone-k2l uses pinmux and is compliant with PINCTRL_SINGLE
> which depends on PINCTRL. Hence enable PINCTRL.
> 
> Signed-off-by: Keerthy <j-keerthy at ti.com>
> ---
>  arch/arm/mach-keystone/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm/mach-keystone/Kconfig b/arch/arm/mach-keystone/Kconfig
> index ea955f6db..7a432ee 100644
> --- a/arch/arm/mach-keystone/Kconfig
> +++ b/arch/arm/mach-keystone/Kconfig
> @@ -11,6 +11,7 @@ config ARCH_KEYSTONE
>  	select ZONE_DMA if ARM_LPAE
>  	select MIGHT_HAVE_PCI
>  	select PCI_DOMAINS if PCI
> +	select PINCTRL

I guess a similar patch[1] is already posted

[1] https://patchwork.kernel.org/patch/8958081/

Thanks and regards,
Lokesh

>  	help
>  	  Support for boards based on the Texas Instruments Keystone family of
>  	  SoCs.
> 


From lokeshvutla at ti.com  Mon May 23 20:37:36 2016
From: lokeshvutla at ti.com (Lokesh Vutla)
Date: Tue, 24 May 2016 09:07:36 +0530
Subject: [PATCH 3/3] ARM: configs: keystone: Enable PINCTRL_SINGLE Config
In-Reply-To: <1464006547-19569-4-git-send-email-j-keerthy@ti.com>
References: <1464006547-19569-1-git-send-email-j-keerthy@ti.com>
 <1464006547-19569-4-git-send-email-j-keerthy@ti.com>
Message-ID: <5743CC80.4070404@ti.com>



On Monday 23 May 2016 05:59 PM, Keerthy wrote:
> keystone-k2l devices use pinmux and are compliant with PINCTRL_SINGLE.
> Hence enable the config option.
> 
> Signed-off-by: Keerthy <j-keerthy at ti.com>

A similar patch[1] is already posted.

[1]https://patchwork.kernel.org/patch/8958091/

Thanks and regards,
Lokesh

> ---
>  arch/arm/configs/keystone_defconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig
> index faba04d..71b42e6 100644
> --- a/arch/arm/configs/keystone_defconfig
> +++ b/arch/arm/configs/keystone_defconfig
> @@ -144,6 +144,7 @@ CONFIG_I2C_DAVINCI=y
>  CONFIG_SPI=y
>  CONFIG_SPI_DAVINCI=y
>  CONFIG_SPI_SPIDEV=y
> +CONFIG_PINCTRL_SINGLE=y
>  CONFIG_GPIOLIB=y
>  CONFIG_GPIO_SYSFS=y
>  CONFIG_GPIO_DAVINCI=y
> 


From zhengxing at rock-chips.com  Mon May 23 20:47:46 2016
From: zhengxing at rock-chips.com (Xing Zheng)
Date: Tue, 24 May 2016 11:47:46 +0800
Subject: [PATCH] ASoC: rockchip: i2s: rename I2S_CKR_TRCM_TX/RXSHARE to
 I2S_CKR_TRCM_TX/RXONLY
Message-ID: <1464061667-16477-1-git-send-email-zhengxing@rock-chips.com>

From: Sugar Zhang <sugar.zhang at rock-chips.com>

this patch make it more reasonable and readable, because when we chose
I2S_CKR_TRCM_TXONLY, we only output clk_lrck_tx, and hardware need to
confirm this signal is wired to external codec lrck_tx/rx at the same time.

for convenience, we just handle lrck_txonly if we enable symmetric_rates
in driver and dai_link. otherwise, we use the separate lrck_tx/rx.

Signed-off-by: Sugar Zhang <sugar.zhang at rock-chips.com>
Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
---

 sound/soc/rockchip/rockchip_i2s.c |    4 ++--
 sound/soc/rockchip/rockchip_i2s.h |    4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 574c6af..92a405f 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -306,8 +306,8 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
 			   I2S_DMACR_RDL(16));
 
 	val = I2S_CKR_TRCM_TXRX;
-	if (dai->driver->symmetric_rates || rtd->dai_link->symmetric_rates)
-		val = I2S_CKR_TRCM_TXSHARE;
+	if (dai->driver->symmetric_rates && rtd->dai_link->symmetric_rates)
+		val = I2S_CKR_TRCM_TXONLY;
 
 	regmap_update_bits(i2s->regmap, I2S_CKR,
 			   I2S_CKR_TRCM_MASK,
diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h
index dc6e2c7..13b1d44 100644
--- a/sound/soc/rockchip/rockchip_i2s.h
+++ b/sound/soc/rockchip/rockchip_i2s.h
@@ -81,8 +81,8 @@
 #define I2S_CKR_TRCM_SHIFT	28
 #define I2S_CKR_TRCM(x)	(x << I2S_CKR_TRCM_SHIFT)
 #define I2S_CKR_TRCM_TXRX	(0 << I2S_CKR_TRCM_SHIFT)
-#define I2S_CKR_TRCM_TXSHARE	(1 << I2S_CKR_TRCM_SHIFT)
-#define I2S_CKR_TRCM_RXSHARE	(2 << I2S_CKR_TRCM_SHIFT)
+#define I2S_CKR_TRCM_TXONLY	(1 << I2S_CKR_TRCM_SHIFT)
+#define I2S_CKR_TRCM_RXONLY	(2 << I2S_CKR_TRCM_SHIFT)
 #define I2S_CKR_TRCM_MASK	(3 << I2S_CKR_TRCM_SHIFT)
 #define I2S_CKR_MSS_SHIFT	27
 #define I2S_CKR_MSS_MASTER	(0 << I2S_CKR_MSS_SHIFT)
-- 
1.7.9.5




From a0393675 at ti.com  Mon May 23 20:56:45 2016
From: a0393675 at ti.com (Keerthy)
Date: Tue, 24 May 2016 09:26:45 +0530
Subject: [PATCH 3/3] ARM: configs: keystone: Enable PINCTRL_SINGLE Config
In-Reply-To: <5743CC80.4070404@ti.com>
References: <1464006547-19569-1-git-send-email-j-keerthy@ti.com>
 <1464006547-19569-4-git-send-email-j-keerthy@ti.com>
 <5743CC80.4070404@ti.com>
Message-ID: <5743D0FD.5070804@ti.com>



On Tuesday 24 May 2016 09:07 AM, Lokesh Vutla wrote:
>
>
> On Monday 23 May 2016 05:59 PM, Keerthy wrote:
>> keystone-k2l devices use pinmux and are compliant with PINCTRL_SINGLE.
>> Hence enable the config option.
>>
>> Signed-off-by: Keerthy <j-keerthy at ti.com>
>
> A similar patch[1] is already posted.
>
> [1]https://patchwork.kernel.org/patch/8958091/

Ah I had not seen them. If they are already reviewed and closer to be 
merged then Patch 2 and Patch 3 of this series can be dropped.

Regards,
Keerthy

>
> Thanks and regards,
> Lokesh
>
>> ---
>>   arch/arm/configs/keystone_defconfig | 1 +
>>   1 file changed, 1 insertion(+)
>>
>> diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig
>> index faba04d..71b42e6 100644
>> --- a/arch/arm/configs/keystone_defconfig
>> +++ b/arch/arm/configs/keystone_defconfig
>> @@ -144,6 +144,7 @@ CONFIG_I2C_DAVINCI=y
>>   CONFIG_SPI=y
>>   CONFIG_SPI_DAVINCI=y
>>   CONFIG_SPI_SPIDEV=y
>> +CONFIG_PINCTRL_SINGLE=y
>>   CONFIG_GPIOLIB=y
>>   CONFIG_GPIO_SYSFS=y
>>   CONFIG_GPIO_DAVINCI=y
>>


From wens at csie.org  Mon May 23 21:14:09 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 24 May 2016 12:14:09 +0800
Subject: [PATCH 10/16] clk: sunxi-ng: Add M-P factor clock support
In-Reply-To: <20160523171845.GC27618@lukather>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-11-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v67F3UvSCYDTxeLkCJL3FzmcpkogM4RAQgDseXMJDv7bUw@mail.gmail.com>
 <20160523171845.GC27618@lukather>
Message-ID: <CAGb2v65GbZosmh56Z7wBa5gHOe1Ox2Jz3tcOq1kugBHO54OvbQ@mail.gmail.com>

Hi,

On Tue, May 24, 2016 at 1:18 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Hi,
>
> On Mon, May 23, 2016 at 09:45:16PM +0800, Chen-Yu Tsai wrote:
>> Hi,
>>
>> On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
>> <maxime.ripard at free-electrons.com> wrote:
>> > Introduce support for the clocks that combine a linear divider and a
>> > power-of-two based one.
>>
>> A description or formula in the source code (for those of us that forget)
>> would be nice. :)
>
> Ack :)
>
>>
>> >
>> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
>> > ---
>> >  drivers/clk/sunxi-ng/Makefile |   1 +
>> >  drivers/clk/sunxi-ng/ccu_mp.c | 158 ++++++++++++++++++++++++++++++++++++++++++
>> >  drivers/clk/sunxi-ng/ccu_mp.h |  79 +++++++++++++++++++++
>> >  3 files changed, 238 insertions(+)
>> >  create mode 100644 drivers/clk/sunxi-ng/ccu_mp.c
>> >  create mode 100644 drivers/clk/sunxi-ng/ccu_mp.h
>> >
>> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
>> > index 063c50f35ad4..09fce7467784 100644
>> > --- a/drivers/clk/sunxi-ng/Makefile
>> > +++ b/drivers/clk/sunxi-ng/Makefile
>> > @@ -5,6 +5,7 @@ obj-y += ccu_div_table.o
>> >  obj-y += ccu_fixed_factor.o
>> >  obj-y += ccu_gate.o
>> >  obj-y += ccu_m.o
>> > +obj-y += ccu_mp.o
>> >  obj-y += ccu_mux.o
>> >  obj-y += ccu_p.o
>> >  obj-y += ccu_phase.o
>> > diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
>> > new file mode 100644
>> > index 000000000000..7181188deba7
>> > --- /dev/null
>> > +++ b/drivers/clk/sunxi-ng/ccu_mp.c
>> > @@ -0,0 +1,158 @@
>> > +/*
>> > + * Copyright (C) 2016 Maxime Ripard
>> > + * Maxime Ripard <maxime.ripard at free-electrons.com>
>> > + *
>> > + * 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.
>> > + */
>> > +
>> > +#include <linux/clk-provider.h>
>> > +
>> > +#include "ccu_gate.h"
>> > +#include "ccu_mp.h"
>> > +
>> > +static void ccu_mp_find_best(unsigned long parent, unsigned long rate,
>> > +                            unsigned int max_m, unsigned int max_p,
>> > +                            unsigned int *m, unsigned int *p)
>> > +{
>> > +       unsigned long best_rate = 0;
>> > +       unsigned int best_m = 0, best_p = 0;
>> > +       unsigned int _m, _p;
>> > +
>> > +       for (_p = 0; _p <= max_p; _p++) {
>> > +               for (_m = 1; _m <= max_m; _m++) {
>> > +                       unsigned long tmp_rate = (parent >> _p) / _m;
>> > +
>> > +                       if (tmp_rate > rate)
>> > +                               continue;
>> > +
>> > +                       if ((rate - tmp_rate) < (rate - best_rate)) {
>> > +                               best_rate = tmp_rate;
>> > +                               best_m = _m;
>> > +                               best_p = _p;
>> > +                       }
>> > +               }
>> > +       }
>> > +
>> > +       *m = best_m;
>> > +       *p = best_p;
>> > +}
>> > +
>> > +static unsigned long ccu_mp_round_rate(struct ccu_mux_internal *mux,
>> > +                                      unsigned long parent_rate,
>> > +                                      unsigned long rate,
>> > +                                      void *data)
>> > +{
>> > +       struct ccu_mp *cmp = data;
>> > +       unsigned int m, p;
>> > +
>> > +       ccu_mp_find_best(parent_rate, rate,
>> > +                        1 << cmp->m.width, (1 << cmp->p.width) - 1,
>> > +                        &m, &p);
>> > +
>> > +       return (parent_rate >> p) / m;
>> > +}
>> > +
>> > +static void ccu_mp_disable(struct clk_hw *hw)
>> > +{
>> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
>> > +
>> > +       return ccu_gate_helper_disable(&cmp->common, cmp->enable);
>> > +}
>> > +
>> > +static int ccu_mp_enable(struct clk_hw *hw)
>> > +{
>> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
>> > +
>> > +       return ccu_gate_helper_enable(&cmp->common, cmp->enable);
>> > +}
>> > +
>> > +static int ccu_mp_is_enabled(struct clk_hw *hw)
>> > +{
>> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
>> > +
>> > +       return ccu_gate_helper_is_enabled(&cmp->common, cmp->enable);
>> > +}
>> > +
>> > +static unsigned long ccu_mp_recalc_rate(struct clk_hw *hw,
>> > +                                       unsigned long parent_rate)
>> > +{
>> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
>> > +       unsigned int m, p;
>> > +       u32 reg;
>> > +
>> > +       reg = readl(cmp->common.base + cmp->common.reg);
>> > +
>> > +       m = reg >> cmp->m.shift;
>> > +       m &= (1 << cmp->m.width) - 1;
>> > +
>> > +       p = reg >> cmp->p.shift;
>> > +       p &= (1 << cmp->p.width) - 1;
>> > +
>> > +       return (parent_rate >> p) / (m + 1);
>> > +}
>> > +
>> > +static int ccu_mp_determine_rate(struct clk_hw *hw,
>> > +                                struct clk_rate_request *req)
>> > +{
>> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
>> > +
>> > +       return ccu_mux_helper_determine_rate(&cmp->common, &cmp->mux,
>> > +                                            req, ccu_mp_round_rate, cmp);
>> > +}
>> > +
>> > +static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
>> > +                          unsigned long parent_rate)
>> > +{
>> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
>> > +       unsigned long flags;
>> > +       unsigned int m, p;
>> > +       u32 reg;
>> > +
>> > +       ccu_mp_find_best(parent_rate, rate,
>> > +                        1 << cmp->m.width, (1 << cmp->p.width) - 1,
>> > +                        &m, &p);
>> > +
>> > +
>> > +       spin_lock_irqsave(cmp->common.lock, flags);
>> > +
>> > +       reg = readl(cmp->common.base + cmp->common.reg);
>> > +       reg &= ~GENMASK(cmp->m.width + cmp->m.shift, cmp->m.shift);
>> > +       reg &= ~GENMASK(cmp->p.width + cmp->p.shift, cmp->p.shift);
>>
>> width + shift - 1 ? IIRC GENMASK is inclusive at both ends.
>
> Indeed, will fix.
>
>>
>> > +
>> > +       writel(reg | (p << cmp->p.shift) | ((m - 1) << cmp->m.shift),
>> > +              cmp->common.base + cmp->common.reg);
>> > +
>> > +       spin_unlock_irqrestore(cmp->common.lock, flags);
>> > +
>> > +       return 0;
>> > +}
>> > +
>> > +static u8 ccu_mp_get_parent(struct clk_hw *hw)
>> > +{
>> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
>> > +
>> > +       return ccu_mux_helper_get_parent(&cmp->common, &cmp->mux);
>> > +}
>> > +
>> > +static int ccu_mp_set_parent(struct clk_hw *hw, u8 index)
>> > +{
>> > +       struct ccu_mp *cmp = hw_to_ccu_mp(hw);
>> > +
>> > +       return ccu_mux_helper_set_parent(&cmp->common, &cmp->mux, index);
>> > +}
>> > +
>> > +const struct clk_ops ccu_mp_ops = {
>> > +       .disable        = ccu_mp_disable,
>> > +       .enable         = ccu_mp_enable,
>> > +       .is_enabled     = ccu_mp_is_enabled,
>> > +
>> > +       .get_parent     = ccu_mp_get_parent,
>> > +       .set_parent     = ccu_mp_set_parent,
>> > +
>> > +       .determine_rate = ccu_mp_determine_rate,
>> > +       .recalc_rate    = ccu_mp_recalc_rate,
>> > +       .set_rate       = ccu_mp_set_rate,
>> > +};
>> > diff --git a/drivers/clk/sunxi-ng/ccu_mp.h b/drivers/clk/sunxi-ng/ccu_mp.h
>> > new file mode 100644
>> > index 000000000000..95da9c46cd4f
>> > --- /dev/null
>> > +++ b/drivers/clk/sunxi-ng/ccu_mp.h
>> > @@ -0,0 +1,79 @@
>> > +/*
>> > + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
>> > + *
>> > + * This software is licensed under the terms of the GNU General Public
>> > + * License version 2, as published by the Free Software Foundation, and
>> > + * may be copied, distributed, and modified under those terms.
>> > + *
>> > + * This program is distributed in the hope that it will be useful,
>> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> > + * GNU General Public License for more details.
>> > + */
>> > +
>> > +#ifndef _CCU_MP_H_
>> > +#define _CCU_MP_H_
>> > +
>> > +#include <linux/clk-provider.h>
>> > +
>> > +#include "ccu_common.h"
>> > +#include "ccu_factor.h"
>> > +#include "ccu_mux.h"
>> > +
>> > +struct ccu_mp {
>> > +       u32                     enable;
>> > +
>> > +       struct ccu_factor       m;
>> > +       struct ccu_factor       p;
>> > +       struct ccu_mux_internal mux;
>> > +       struct ccu_common       common;
>> > +};
>> > +
>> > +#define SUNXI_CCU_MP_WITH_MUX(_struct, _name, _parents, _reg,          \
>> > +                             _mshift, _mwidth,                         \
>> > +                             _pshift, _pwidth,                         \
>> > +                             _muxshift, _muxwidth,                     \
>> > +                             _flags)                                   \
>> > +       struct ccu_mp _struct = {                                       \
>> > +               .m      = SUNXI_CLK_FACTOR(_mshift, _mwidth),           \
>> > +               .p      = SUNXI_CLK_FACTOR(_pshift, _pwidth),           \
>> > +               .mux    = SUNXI_CLK_MUX(_muxshift, _muxwidth),          \
>> > +               .common = {                                             \
>> > +                       .reg            = _reg,                         \
>> > +                       .hw.init        = SUNXI_HW_INIT_PARENTS(_name,  \
>> > +                                                               _parents, \
>> > +                                                               &ccu_mp_ops, \
>> > +                                                               _flags), \
>> > +               }                                                       \
>> > +       }
>>
>> Use the latter to simplify this one?
>>
>> > +
>> > +#define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,     \
>>
>> We could merge _struct with _name ...
>>
>> > +                                  _mshift, _mwidth,                    \
>> > +                                  _pshift, _pwidth,                    \
>> > +                                  _muxshift, _muxwidth,                \
>> > +                                  _gate, _flags)                       \
>> > +       struct ccu_mp _struct = {                                       \
>>
>> and have struct ccu_mp _name##_clk = {
>
> Unfortunately, that prevents to use dashes as clock names, which is
> something we've done in the past. Having a separate name allows us to
> use whatever we want.

We could do some replacement in the register function, but that seems
hackish. Also I noticed we aren't using clock-output-names from the DT
anymore?

ChenYu


From jcm at redhat.com  Mon May 23 21:20:55 2016
From: jcm at redhat.com (Jon Masters)
Date: Tue, 24 May 2016 00:20:55 -0400
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <20160523105655.GA22902@red-moon>
References: <1462893601-8937-1-git-send-email-tn@semihalf.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
Message-ID: <f9c8b16b-3027-d90d-c0d1-6afcd45c1e0f@redhat.com>

On 05/23/2016 06:56 AM, Lorenzo Pieralisi wrote:

> The only way this can be implemented is by pretending that the
> ACPI/PCI arch/arm64 implementation is generic code (that's what this
> series does), move it to /drivers (where it is in this series), and
> implement _DSD vendor specific bindings (per HID) to set-up the pci
> operations; whether this solution should go upstream, given that it
> is just a short-term solution for early platforms bugs, it is another
> story and my personal answer is no.

Just for completeness, let me also followup to this one.

We have real, shipping, systems in the field based on ARMv8. For
example, HPE Moonshot ProLiant m400. Not everyone loves the first
generation of anything (Applied get a lot of stick, but the reality is
that someone had to go first, and whoever that was was going to learn
all of the lessons that others don't need to) but it is out there and we
need an upstream kernel solution that includes support for that.

In the server world, we (speaking as a major distro vendor here) are not
going to entertain a situation in which non-upstream patches are needed
to even boot a platform. That simply won't do. We need to separate out
the issue of getting the core in place from the quirks, but then we need
quirks that include support for all early ARMv8 platforms that are out
there today. If we can't get to a point where a Moonshot[0] cartridge
boots out of the box with an upstream kernel, let's just give up and do
something else instead :) (joke)

Jon.

[0] HPE have been *amazingly* patient with this stuff. They've reworked
the firmware when someone (cough) pointed out that the early stuff
they'd been fed was not built according to the standards (U-Boot). They
have *really good* UEFI and ACPI enabled firmware that is running
RHEL(SA) great. But that's not good enough. We don't ship a distro with
hacks. We ship a distro derived from upstream code (although we might
have to backport a lot of stuff later). There's wiggle room, but there
is not wiggle room for core platforms. On ARM, users and developers
*will* be able to take an upstream kernel and boot it on their RHEL
install. And they *will* be able to reproduce problems against upstream,
and help develop against upstream, and further the upstream first
mentality in the ARM ecosystem. There will not be "oh well, it runs RHEL
so that's good enough for the early generation...".

-- 
Computer Architect | Sent from my Fedora powered laptop


From maitysanchayan at gmail.com  Mon May 23 21:14:47 2016
From: maitysanchayan at gmail.com (maitysanchayan at gmail.com)
Date: Tue, 24 May 2016 09:44:47 +0530
Subject: [PATCH v3 4/4] soc: Add SoC driver for Freescale Vybrid platform
In-Reply-To: <20160523211813.GA30237@rob-hp-laptop>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
 <ffef165d05f71a1b19437171d8fdb4bc78f6b1e3.1463737502.git.maitysanchayan@gmail.com>
 <20160523211813.GA30237@rob-hp-laptop>
Message-ID: <20160524041447.GA2884@Sanchayan-Arch.localdomain>

Hello Rob,

On 16-05-23 16:18:13, Rob Herring wrote:
> On Fri, May 20, 2016 at 03:32:05PM +0530, Sanchayan Maity wrote:
> > This adds a SoC driver to be used by Freescale Vybrid SoC's.
> > Driver utilises syscon and nvmem consumer API's to get the
> > various register values needed and expose the SoC specific
> > properties via sysfs.
> > 
> > A sample output from Colibri Vybrid VF61 is below:
> > 
> > root at colibri-vf:~# cd /sys/bus/soc/devices/soc0
> > root at colibri-vf:/sys/bus/soc/devices/soc0# ls
> > family     machine    power      revision   soc_id     subsystem  uevent
> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat family
> > Freescale Vybrid VF610
> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat machine
> > Freescale Vybrid
> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat revision
> > 00000013
> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat soc_id
> > df6472a6130f29d4
> > 
> > Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
> > ---
> >  .../bindings/arm/freescale/fsl,vf610-soc.txt       |  20 +++
> >  drivers/soc/Kconfig                                |   1 +
> >  drivers/soc/fsl/Kconfig                            |  10 ++
> >  drivers/soc/fsl/Makefile                           |   1 +
> >  drivers/soc/fsl/soc-vf610.c                        | 198 +++++++++++++++++++++
> >  5 files changed, 230 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> >  create mode 100644 drivers/soc/fsl/Kconfig
> >  create mode 100644 drivers/soc/fsl/soc-vf610.c
> > 
> > diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> > new file mode 100644
> > index 0000000..338905d
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> > @@ -0,0 +1,20 @@
> > +Vybrid System-on-Chip
> > +---------------------
> > +
> > +Required properties:
> > +
> > +- compatible: "fsl,vf610-soc"
> > +- rom-revision: phandle to the on-chip ROM node
> > +- mscm: phandle to the MSCM CPU configuration node
> > +- nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
> > +- nvmem-cell-names: should contain string names "cfg0" and "cfg1"
> 
> I still have similar concerns as the discussion on the last version. 
> This version only proves that you aren't describing h/w, but rather just 
> a collection of data that some driver wants.
> 
> A driver can just as easily look-up all the nodes directly that these 
> phandles point to.

Agreed, that we can look up all the nodes directly that these phandles
refer to but I would still need a DT entry to bind to. While I could
bind to existing nodes like mscm cpucfg but that doesn't seem right.

The very first approach that we had taken was to integrate this functionality
in mach-vf610.c code under mach-imx
http://www.spinics.net/lists/devicetree/msg80654.html

and then it was recommended to migrate this to drivers/soc where we did use
phandles or direct look up via compatible strings

http://www.spinics.net/lists/arm-kernel/msg420847.html

and

http://lkml.iu.edu/hypermail/linux/kernel/1506.0/03787.html

There hasn't been a consensus since v1.

> 
> And as long as we have inconsistent use of soc_device, I don't want to 
> see any compatible strings related to it.
> 

Regards,
Sanchayan.




From dianders at chromium.org  Mon May 23 21:51:19 2016
From: dianders at chromium.org (Doug Anderson)
Date: Mon, 23 May 2016 21:51:19 -0700
Subject: [PATCH 2/4] phy: rockchip-emmc: configure frequency range and
 drive impedance
In-Reply-To: <CAD=FV=UwocUy_bOUrJZB47taHWdV1KGkvi5CyZf74Y8cvGgVmw@mail.gmail.com>
References: <1463092986-61777-1-git-send-email-briannorris@chromium.org>
 <1463092986-61777-2-git-send-email-briannorris@chromium.org>
 <3695875b-09c3-cd80-3062-55d985e51f70@rock-chips.com>
 <CAD=FV=UwocUy_bOUrJZB47taHWdV1KGkvi5CyZf74Y8cvGgVmw@mail.gmail.com>
Message-ID: <CAD=FV=VYPs22rGX9Latecb0EWFA0kOCFmoSQ83wPecrFkL0m7w@mail.gmail.com>

Hi,

On Fri, May 13, 2016 at 11:46 AM, Doug Anderson <dianders at chromium.org> wrote:
>> Per the commit msg, signal may vary from board to board, so I guess
>> 50ohm may not always be the best selection?
>
> Starting out with something sane like 50 ohms seems like it makes
> sense for now.  It's OK to start with a default for now to get things
> basically working and then add device tree support once we have a
> second user.
>
>
> When we're ready to make this more generic, IMHO we might consider
> having the PHY implement the pinctrl API and officially be a pin
> controller and we use those bindings.  We are controlling pins so
> using the pinctrl API seems like it might make sense?
>
> I _think_ that perhaps what we're specifying here is actually slew
> rate, but feel free to correct me if I'm wrong.  It looks as if "drive
> strength" is supposed to be specified in terms of mA and the docs I
> find show that we're actually controlling how fast the pins will
> toggle.
>
> I'm not 100% certain I know how the pinctrl bindings apply in this
> case (maybe Heiko has ideas, or maybe we should send a proposal to
> Linus W?), but from the bindings they look like they offer some
> flexibility.
>
> Maybe this would look like below (or maybe you need some extra sub-nodes)
>
>        sdhci: sdhci at fe330000 {
>                compatible = "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1";
>                reg = <0x0 0xfe330000 0x0 0x10000>;
>                interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
>                clocks = <&cru SCLK_EMMC>, <&cru ACLK_EMMC>;
>                clock-names = "clk_xin", "clk_ahb";
>                assigned-clocks = <&cru SCLK_EMMC>;
>                assigned-clock-rates = <200000000>;
>                phys = <&emmc_phy>;
>                phy-names = "phy_arasan";
>                pinctrl-names = "default";
>                pinctrl-0 = <&pcfg_emmc_slew_rate_x1_00>;
>                status = "disabled";
>        };
>
>                emmc_phy: phy at f780 {
>                        compatible = "rockchip,rk3399-emmc-phy";
>                        reg = <0xf780 0x20>;
>                        #phy-cells = <0>;
>                        status = "disabled";
>
>                        pcfg_emmc_slew_rate_x1_00: pcfg-emmc-slew-rate-x1-00 {
>                                slew-rate = <100>;
>                        };
>                        pcfg_emmc_slew_rate_x1_50: pcfg-emmc-slew-rate-x1-50 {
>                                slew-rate = <150>;
>                        };
>                        pcfg_emmc_slew_rate_x0_75: pcfg-emmc-slew-rate-x0-75 {
>                                slew-rate = <75>;
>                        };
>                        pcfg_emmc_slew_rate_x0_50: pcfg-emmc-slew-rate-x0-50 {
>                                slew-rate = <50>;
>                        };
>                        pcfg_emmc_slew_rate_x1_20: pcfg-emmc-slew-rate-x1-20 {
>                                slew-rate = <120>;
>                        };
>                        pcfg_emmc_slew_rate_x1_20: pcfg-emmc-slew-rate-x1-20 {
>                                slew-rate = <120>;
>                        };
>            };
>
> The nice thing about using the pinctrl API is that:
>
> * It allows us to _also_ control pullups / pulldowns.  We probably
> want to control those also since some boards may use external pullups
> and others may want to use the internal ones.
>
> * If SDHCI needs to dynamically adjust things (like turning on pulls,
> adjusting drive strengths, etc) it can do it in a sane API.

Note that I still believe that we could land the 50 Ohm first (AKA
land the patch Brian posted), but I'm also convinced that my pinctrl
proposal above is not a good idea for the way to move forward, at
least in terms of the "driver strength" part.  Specifically it seems
like the 50 Ohm / 33 Ohm / 66 Ohm / 100 Ohm / 40 Ohm is a concept from
eMMC 5.0 and probably doesn't fit to pinctrl.

I also _think_ it needs to be matched against what's available from
the card (card->drive_strength) and the card needs to be told about
it, but I could be wrong about that.



-Doug


From vigneshr at ti.com  Mon May 23 22:09:26 2016
From: vigneshr at ti.com (Vignesh R)
Date: Tue, 24 May 2016 10:39:26 +0530
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <20160523131808.GN23704@pengutronix.de>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
 <1463648641-6931-2-git-send-email-vigneshr@ti.com>
 <20160522102606.GB23704@pengutronix.de> <5742E710.9@ti.com>
 <20160523131808.GN23704@pengutronix.de>
Message-ID: <5743E206.2050602@ti.com>

Hi,

On 05/23/2016 06:48 PM, Uwe Kleine-K?nig wrote:
> Hello,
> 
> On Mon, May 23, 2016 at 04:48:40PM +0530, R, Vignesh wrote:
>> On 5/22/2016 3:56 PM, Uwe Kleine-K?nig wrote:
>>> Hello,
>>>
>>> On Thu, May 19, 2016 at 02:34:00PM +0530, Vignesh R wrote:
>>>> There are rotary-encoders where GPIO lines reflect the actual position
>>>> of the rotary encoder dial. For example, if dial points to 9, then four
>>>> GPIO lines connected to the rotary encoder will read HLLH(1001b = 9).
>>>> Add support for such rotary-encoder.
>>>> The driver relies on rotary-encoder,absolute-encoder DT property to
>>>> detect such encoders.
>>>> Since, GPIO IRQs are not necessary to work with
>>>> such encoders, optional polling mode support is added using
>>>
>>> I don't understand this. It's necessary in the same way as with the
>>> already supported devices. I.e. you want to trigger an irq when the
>>> encoder is moved and then check for it's position in the handler.
>>>
>>
>> Unlike already supported device, there is no need to count steps or
>> determine the direction of rotation. Hence, IRQ is not a requirement,
>> periodically polling the gpio lines is more than sufficient. With
>> absolute encoder, you are able to determine the current position at any
>> time just by looking at the gpio inputs.
> 
> The timing might not be that critical, but there is no reason to operate
> this device without irqs, is there?

No, I am not against the use of IRQs. In fact, my patches add support
for both IRQ based(default) and polling based operation(optional). If
rotary-encoder does not have interrupt capable gpio lines connected to
it (like am335x-ice) then one can make use of the polling mode support.

> 
>> Suppose we poll device at t=0ms and see gpio values are LLLH(1), if we
>> again poll device at t=500ms(which is what input_poll_dev helps to do)
>> and see that gpio values is LLHH(3), then we know that rotary encoder
>> has changed to 3. This can be done w/o IRQ for absolute encoders.
>>
>>>> diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
>>>> index 6c9f0c8a846c..9c928dbd1500 100644
>>>> --- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
>>>> +++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
>>>> @@ -12,6 +12,10 @@ Optional properties:
>>>>  - rotary-encoder,relative-axis: register a relative axis rather than an
>>>>    absolute one. Relative axis will only generate +1/-1 events on the input
>>>>    device, hence no steps need to be passed.
>>>> +- rotary-encoder,absolute-encoder: support encoders where GPIO lines
>>>> +  reflect the actual position of the rotary encoder dial. For example,
>>>> +  if dial points to 9, then four GPIO lines read HLLH(1001b = 9).
>>>> +  In this case, rotary-encoder,steps-per-period needed not be defined.
>>>
>>> IMHO this is wrong, I'd formalize this device as:
>>>
>>> 	{
>>> 		compatible = "rotary-encoder";
>>> 		gpios = <&gpio 19 1>, <&gpio 20 0>, <...>, <...>;
>>> 		rotary-encoder,encoding = "binary";
>>> 		rotary-encoder,steps = <16>;
>>> 		rotary-encoder,steps-per-period = <16>;
>>
>> The above bindings essential means quarter_period device. I would not
>> like to bother with all the logic in rotary_encoder_quarter_period_irq()
>> when we can know encoder->pos by directly reading state of gpio lines.
> 
> OK, we have code that is more complex than it needs to be for your
> device. But your device is a special case of the supported devices, so
> I'd say don't bother that there is more logic in the driver than you
> need and be lucky.
> 

More complexity is just a overhead. Since, encoder can be turned at a
rate faster than handling of IRQs (rotary_encoder_quarter_period_irq()
is threaded IRQ hence, priority is not close to real time), some states
can be missed. rotary_encoder_quarter_period_irq() is not robust in this
case, reading gpios directly is more suitable option. I see similar
views expressed in previously[1]

[1]http://lists.infradead.org/pipermail/linux-arm-kernel/2015-December/391196.html

-- 
Regards
Vignesh


From nava.manne at xilinx.com  Mon May 23 22:21:08 2016
From: nava.manne at xilinx.com (Nava kishore Manne)
Date: Tue, 24 May 2016 10:51:08 +0530
Subject: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
Message-ID: <1464067268-35299-1-git-send-email-navam@xilinx.com>

This patch updates the driver to support 64-bit DMA addressing.

Signed-off-by: Nava kishore Manne <navam at xilinx.com>
---
Changes for v3:
                -Added new compatable string for 5.00 IP version as suggested by
                 Arnd Bergmann.
                -Used write_fn() insted of lo_hi_writeq() as suggested by
                 Arnd Bergmann.

Changes for v2:
                -Added dma-ranges property in device tree as suggested by Arnd Bergmann.
                -Modified the driver code based on the xlnx,addrwidth.

 .../devicetree/bindings/usb/udc-xilinx.txt         | 21 +++++----
 drivers/usb/gadget/udc/udc-xilinx.c                | 53 ++++++++++++++++++++--
 2 files changed, 63 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/udc-xilinx.txt b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
index 47b4e39..09df757 100644
--- a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
+++ b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
@@ -1,18 +1,23 @@
 Xilinx USB2 device controller
 
 Required properties:
-- compatible		: Should be "xlnx,usb2-device-4.00.a"
+- compatible		: Should be "xlnx,usb2-device-4.00.a" or
+			  "xlnx,usb2-device-5.00"
 - reg			: Physical base address and size of the USB2
 			  device registers map.
 - interrupts		: Should contain single irq line of USB2 device
 			  controller
 - xlnx,has-builtin-dma	: if DMA is included
+- dma-ranges		: Should be as the following
+			  <child-bus-address, parent-bus-address, length>
+- xlnx,addrwidth	: Should be the dma addressing size in bits(ex: 64 bits)
 
 Example:
- 		axi-usb2-device at 42e00000 {
-                        compatible = "xlnx,usb2-device-4.00.a";
-                        interrupts = <0x0 0x39 0x1>;
-                        reg = <0x42e00000 0x10000>;
-                        xlnx,has-builtin-dma;
-                };
-
+		axi-usb2-device at 42e00000 {
+			compatible = "xlnx,usb2-device-4.00.a";
+			interrupts = <0x0 0x39 0x1>;
+			reg = <0x42e00000 0x10000>;
+			dma-ranges = <0x00000000 0x00000000 0x40000000>;
+			xlnx,has-builtin-dma;
+			xlnx,addrwidth = <0x40>;
+		};
diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c
index 1cbb0ac..112a6f3 100644
--- a/drivers/usb/gadget/udc/udc-xilinx.c
+++ b/drivers/usb/gadget/udc/udc-xilinx.c
@@ -47,6 +47,15 @@
 #define XUSB_DMA_LENGTH_OFFSET		0x0210	/* DMA Length Register */
 #define XUSB_DMA_STATUS_OFFSET		0x0214	/* DMA Status Register */
 
+/* DMA source Address Reg for LSB */
+#define XUSB_DMA_DSAR_ADDR_OFFSET_LSB   0x0308
+/* DMA source Address Reg for MSB */
+#define XUSB_DMA_DSAR_ADDR_OFFSET_MSB   0x030C
+/* DMA destination Addr Reg LSB */
+#define XUSB_DMA_DDAR_ADDR_OFFSET_LSB   0x0310
+/* DMA destination Addr Reg MSB */
+#define XUSB_DMA_DDAR_ADDR_OFFSET_MSB   0x0314
+
 /* Endpoint Configuration Space offsets */
 #define XUSB_EP_CFGSTATUS_OFFSET	0x00	/* Endpoint Config Status  */
 #define XUSB_EP_BUF0COUNT_OFFSET	0x08	/* Buffer 0 Count */
@@ -193,7 +202,7 @@ struct xusb_udc {
 	void __iomem *addr;
 	spinlock_t lock;
 	bool dma_enabled;
-
+	u32 dma_addrwidth;
 	unsigned int (*read_fn)(void __iomem *);
 	void (*write_fn)(void __iomem *, u32, u32);
 };
@@ -214,6 +223,20 @@ static const struct usb_endpoint_descriptor config_bulk_out_desc = {
 	.wMaxPacketSize		= cpu_to_le16(EP0_MAX_PACKET),
 };
 
+/**
+ * xudc_write64 - write 64bit value to device registers
+ * @addr: base addr of device registers
+ * @offset: register offset
+ * @val: data to be written
+ **/
+static void xudc_write64(struct xusb_ep *ep, u32 offset, u64 val)
+{
+	struct xusb_udc *udc = ep->udc;
+
+	udc->write_fn(udc->addr, offset, lower_32_bits(val));
+	udc->write_fn(udc->addr, offset+0x04, upper_32_bits(val));
+}
+
 /**
  * xudc_write32 - little endian write to device registers
  * @addr: base addr of device registers
@@ -330,8 +353,13 @@ static int xudc_start_dma(struct xusb_ep *ep, dma_addr_t src,
 	 * destination registers and then set the length
 	 * into the DMA length register.
 	 */
-	udc->write_fn(udc->addr, XUSB_DMA_DSAR_ADDR_OFFSET, src);
-	udc->write_fn(udc->addr, XUSB_DMA_DDAR_ADDR_OFFSET, dst);
+	if (udc->dma_addrwidth > 32) {
+		xudc_write64(ep, XUSB_DMA_DSAR_ADDR_OFFSET_LSB, src);
+		xudc_write64(ep, XUSB_DMA_DDAR_ADDR_OFFSET_LSB, dst);
+	} else {
+		udc->write_fn(udc->addr, XUSB_DMA_DSAR_ADDR_OFFSET, src);
+		udc->write_fn(udc->addr, XUSB_DMA_DDAR_ADDR_OFFSET, dst);
+	}
 	udc->write_fn(udc->addr, XUSB_DMA_LENGTH_OFFSET, length);
 
 	/*
@@ -2097,6 +2125,24 @@ static int xudc_probe(struct platform_device *pdev)
 
 	udc->dma_enabled = of_property_read_bool(np, "xlnx,has-builtin-dma");
 
+	if (of_device_is_compatible(np, "xlnx,usb2-device-5.00")) {
+		ret = of_property_read_u32(np, "xlnx,addrwidth",
+						&udc->dma_addrwidth);
+		if (ret < 0)
+			dev_warn(&pdev->dev,
+				"missing xlnx,addrwidth property\n");
+	} else {
+		udc->dma_addrwidth = 32;
+	}
+
+	/* Set the dma mask bits */
+	ret = dma_set_mask_and_coherent(&pdev->dev,
+					DMA_BIT_MASK(udc->dma_addrwidth));
+	if (ret < 0) {
+		dev_dbg(&pdev->dev, "no usable DMA configuration");
+		goto fail;
+	}
+
 	/* Setup gadget structure */
 	udc->gadget.ops = &xusb_udc_ops;
 	udc->gadget.max_speed = USB_SPEED_HIGH;
@@ -2168,6 +2214,7 @@ static int xudc_remove(struct platform_device *pdev)
 /* Match table for of_platform binding */
 static const struct of_device_id usb_of_match[] = {
 	{ .compatible = "xlnx,usb2-device-4.00.a", },
+	{ .compatible = "xlnx,usb2-device-5.00", },
 	{ /* end of list */ },
 };
 MODULE_DEVICE_TABLE(of, usb_of_match);
-- 
2.8.3.394.g3916adf



From nab at linux-iscsi.org  Mon May 23 22:31:44 2016
From: nab at linux-iscsi.org (Nicholas A. Bellinger)
Date: Mon, 23 May 2016 22:31:44 -0700
Subject: [PATCH] Fix for hang of Ordered task in TCM
In-Reply-To: <82ddb84d-1a3c-f7ad-3f91-0a9506317bdf@linux.vnet.ibm.com>
References: <1463177741-4385-1-git-send-email-mikecyr@linux.vnet.ibm.com>
 <1463550825.22249.17.camel@haakon3.risingtidesystems.com>
 <82ddb84d-1a3c-f7ad-3f91-0a9506317bdf@linux.vnet.ibm.com>
Message-ID: <1464067904.22249.53.camel@haakon3.risingtidesystems.com>

On Wed, 2016-05-18 at 14:35 -0500, Michael Cyr wrote:
> On 5/18/16 12:53 AM, Nicholas A. Bellinger wrote:
> > Hi Michael,
> >
> > On Fri, 2016-05-13 at 17:15 -0500, Michael Cyr wrote:
> >> If a command with a Simple task attribute is failed due to a Unit
> >> Attention, then a subsequent command with an Ordered task attribute will
> >> hang forever.  The reason for this is that the Unit Attention status is
> >> checked for in target_setup_cmd_from_cdb, before the call to
> >> target_execute_cmd, which calls target_handle_task_attr, which in turn
> >> increments dev->simple_cmds.  However, transport_generic_request_failure
> >> still calls transport_complete_task_attr, which will decrement
> >> dev->simple_cmds.  In this case, simple_cmds is now -1.  So when a
> >> command with the Ordered task attribute is sent, target_handle_task_attr
> >> sees that dev->simple_cmds is not 0, so it decides it can't execute the
> >> command until all the (nonexistent) Simple commands have completed.
> >>
> > Thanks for reporting this bug.  Comments below.

<SNIP>

> > So AFAICT for delayed commands, the above patch ends up skipping these
> > three checks subsequently when doing __target_execute_cmd() directly
> > from target_restart_delayed_cmds(), no..?
> >
> > After pondering this some more, what about moving these checks into
> > __target_execute_cmd() to handle both target_core_transport.c cases
> > instead..?
>>
> You're right, __target_execute_cmd is clearly the right place for the 
> checks.
>
> > We'll also need a parameter for internal COMPARE_AND_WRITE usage
> > within compare_and_write_callback(), to bypass checks upon secondary
> > ->execute_cmd() WRITE payload submission after READ + COMPARE has
> > completed successfully.
>>
> I'm still learning about the target code, and I was unaware of 
> COMPARE_AND_WRITE.  Thanks for pointing this out to me.  You're right 
> here too, we need to make sure we only make the tests when the Compare 
> and Write is first executed (to do the read), and not later when the 
> write is done.
> >
> > WDYT..?
>>
> You've covered all the places that call __target_execute_cmd, so I think 
> it's good.

Thanks for the feedback.

Given the nature of the change, it needs some more Reviewed-by +
Tested-By (across different drivers) ahead of pushing this patch into
mainline.

So for the moment it's in target-pending/queue as a post v4.7-rc1 item
here:

https://git.kernel.org/cgit/linux/kernel/git/nab/target-pending.git/commit/?h=queue&id=0c141c33b667b6538e38b87db87232523bcd4f5b



From dirk.behme at de.bosch.com  Mon May 23 22:30:17 2016
From: dirk.behme at de.bosch.com (Dirk Behme)
Date: Tue, 24 May 2016 07:30:17 +0200
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
Message-ID: <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>

Hi Simon,

On 24.05.2016 03:54, Simon Horman wrote:
> Basic support for the Gen 3 R-Car M3-W SoC.
>
> Based on work for the r8a7795 and r8a7796 SoCs by
> Takeshi Kihara, Dirk Behme and Geert Uytterhoeven.
>
> Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
> Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
> ---
> v3
> * As suggested by Geert Uytterhoeven:
>   - Drop 0x from unit address of gic
> * As suggested by Khiem Nguyen:
>   - Use psci-0.2
> * Added Reviewed-by tag from Geert Uytterhoeven
>
> v2
> * As suggested by Geert Uytterhoeven:
>   - Move L2_CA57 node under cpus node and include reg property
>   - Omit status = "disabled" from scif_clk node
> ---
>  Documentation/devicetree/bindings/arm/shmobile.txt |   4 +
>  arch/arm64/Kconfig.platforms                       |   6 ++
>  arch/arm64/boot/dts/renesas/r8a7796.dtsi           | 120 +++++++++++++++++++++
>  3 files changed, 130 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/renesas/r8a7796.dtsi
>
> diff --git a/Documentation/devicetree/bindings/arm/shmobile.txt b/Documentation/devicetree/bindings/arm/shmobile.txt
> index 9cf67e48f222..d5ed554830d7 100644
> --- a/Documentation/devicetree/bindings/arm/shmobile.txt
> +++ b/Documentation/devicetree/bindings/arm/shmobile.txt
> @@ -29,6 +29,8 @@ SoCs:
>      compatible = "renesas,r8a7794"
>    - R-Car H3 (R8A77950)
>      compatible = "renesas,r8a7795"
> +  - R-Car M3-W (R8A77960)
> +    compatible = "renesas,r8a7796"
>
>
>  Boards:
> @@ -61,5 +63,7 @@ Boards:
>      compatible = "renesas,porter", "renesas,r8a7791"
>    - Salvator-X (RTP0RC7795SIPB0010S)
>      compatible = "renesas,salvator-x", "renesas,r8a7795";
> +  - Salvator-X
> +    compatible = "renesas,salvator-x", "renesas,r8a7796";
>    - SILK (RTP0RC7794LCB00011S)
>      compatible = "renesas,silk", "renesas,r8a7794"
> diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
> index efa77c146415..16d8d26839ea 100644
> --- a/arch/arm64/Kconfig.platforms
> +++ b/arch/arm64/Kconfig.platforms
> @@ -114,6 +114,12 @@ config ARCH_R8A7795
>  	help
>  	  This enables support for the Renesas R-Car H3 SoC.
>
> +config ARCH_R8A7796
> +	bool "Renesas R-Car M3-W SoC Platform"
> +	depends on ARCH_RENESAS
> +	help
> +	  This enables support for the Renesas R-Car M3-W SoC.
> +
>  config ARCH_STRATIX10
>  	bool "Altera's Stratix 10 SoCFPGA Family"
>  	help
> diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> new file mode 100644
> index 000000000000..178debf68318
> --- /dev/null
> +++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> @@ -0,0 +1,120 @@
> +/*
> + * Device Tree Source for the r8a7796 SoC
> + *
> + * Copyright (C) 2016 Renesas Electronics Corp.
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2.  This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#include <dt-bindings/clock/r8a7796-cpg-mssr.h>
> +#include <dt-bindings/interrupt-controller/arm-gic.h>


With Renesas R-Car3 we will get a whole family of SoCs. I.e. different 
computing power (e.g. different number of Cores) with more or less 
similar peripherals.

I would think that we want to reflect this in the device tree, too. 
Therefore I think what we want is a hierarchy of device trees. Similar 
what's done with other SoC families (compare e.g. i.MX6).

E.g. we want an initial rcar3.dtsi, which contains all common parts of 
all R-Car3 SoCs. E.g. one CA57 core, the SCIF where its common etc.

Then you will have the r8a779x.dtsi which includes the rcar3.dtsi and 
extends it for SoC specific parts. Which then will be included by the 
board device trees, as already done, now.

Or in other words: As soon as you have similar parts in the 
r8a779x.dtsi's, it's time to think about moving the parts one hierarchy 
level up into the rcar3.dtsi. Else you will end up in a maintenance hell 
once you have to change/fix anything.

Best regards

Dirk





From nab at linux-iscsi.org  Mon May 23 22:47:34 2016
From: nab at linux-iscsi.org (Nicholas A. Bellinger)
Date: Mon, 23 May 2016 22:47:34 -0700
Subject: [PATCH] Fix for hang of Ordered task in TCM
In-Reply-To: <20160523191735.Horde.6wmWQ7EiiPavHDD7pNfVtQ1@ltc.linux.ibm.com>
References: <1463177741-4385-1-git-send-email-mikecyr@linux.vnet.ibm.com>
 <1463550825.22249.17.camel@haakon3.risingtidesystems.com>
 <20160523191735.Horde.6wmWQ7EiiPavHDD7pNfVtQ1@ltc.linux.ibm.com>
Message-ID: <1464068854.22249.69.camel@haakon3.risingtidesystems.com>

Hi Bryant,

On Mon, 2016-05-23 at 19:17 -0400, Bryant G Ly wrote:
> Quoting "Nicholas A. Bellinger" <nab at linux-iscsi.org>:
> 
> <SNIP>
> >
> > So AFAICT for delayed commands, the above patch ends up skipping these
> > three checks subsequently when doing __target_execute_cmd() directly
> > from target_restart_delayed_cmds(), no..?
> >
> > After pondering this some more, what about moving these checks into
> > __target_execute_cmd() to handle both target_core_transport.c cases
> > instead..?
> >
> > We'll also need a parameter for internal COMPARE_AND_WRITE usage
> > within compare_and_write_callback(), to bypass checks upon secondary
> > ->execute_cmd() WRITE payload submission after READ + COMPARE has
> > completed successfully.

<SNIP>

> Looks good to me.

Thanks for the review!

> Nick just to let you know I've been working with  
> Mike on VSCSI Target Fabric and we need this patch in kernel 4.4 do
> you know of the process in getting that there?

So pending a bit more list feedback + testing across multiple fabric
drivers, it's been added for the moment to target-pending/queue as post
-rc1 material.

As it merged into target-pending/master next week, the extra stable CC'
can be added to be picked up for linux-4.4.y stable and friends.

Also AFAIK, we've not had reports of other SCSI host environments
triggering this bug, but it's still a good idea to consider it for
linux-3.x.y backport at some point as well.



From k.kozlowski at samsung.com  Mon May 23 23:28:07 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 24 May 2016 08:28:07 +0200
Subject: [PATCH 1/4] dma-mapping: Constify attrs passed to dma_get_attr
In-Reply-To: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>
References: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1464071290-15948-2-git-send-email-k.kozlowski@samsung.com>

The dma_get_attr() does not modify passed dma_attrs so the pointer can
point to const data.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 include/linux/dma-attrs.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
index 5246239a4953..f3c5aeadb100 100644
--- a/include/linux/dma-attrs.h
+++ b/include/linux/dma-attrs.h
@@ -60,7 +60,8 @@ static inline void dma_set_attr(enum dma_attr attr, struct dma_attrs *attrs)
  * @attr: attribute to set
  * @attrs: struct dma_attrs (may be NULL)
  */
-static inline int dma_get_attr(enum dma_attr attr, struct dma_attrs *attrs)
+static inline int dma_get_attr(enum dma_attr attr,
+			       const struct dma_attrs *attrs)
 {
 	if (attrs == NULL)
 		return 0;
-- 
1.9.1



From k.kozlowski at samsung.com  Mon May 23 23:28:06 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 24 May 2016 08:28:06 +0200
Subject: [PATCH 0/4] dma-mapping: Constify dma_attrs
Message-ID: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>

Hi,

The patchset is divided into two parts:
1. (patch 1-3): Constify dma_attrs passed to some of functions. The
   first patch is a dependency for all other. This is not intrusive.

2. patch 4: request for comments, constify dma_attrs everywhere (struct
   dma_map_ops and implementations).
   Constness may protect from certain coding bugs and, what is more
   important, is a direct documentation of how the core deals
   with passed data. Some of the dma-mapping users allocate attrs
   on the stack so the ownership cannot be transferred. 'Const' here
   means exactly that - the ownership stays with the caller.

   Unfortunately this cannot be done separately per-implementation
   without introducing build warnings so the patch touches multiple
   subsystems. Maybe using some casts in intermediate steps might help
   splitting it into separate patches?

   This is not finished because there is no point of my effort if
   I will hear short NACK soon. :)

Comments are welcomed.

Best regards,
Krzysztof

Krzysztof Kozlowski (4):
  dma-mapping: Constify attrs passed to dma_get_attr
  ARM: dma-mapping: Constify attrs passed to internal functions
  arm64: dma-mapping: Constify attrs passed to internal functions
  dma-mapping: Constify dma_attrs

 arch/arm/include/asm/dma-mapping.h | 12 +++---
 arch/arm/mm/dma-mapping.c          | 87 ++++++++++++++++++++------------------
 arch/arm/xen/mm.c                  |  4 +-
 arch/arm64/mm/dma-mapping.c        | 53 +++++++++++------------
 drivers/iommu/dma-iommu.c          |  6 +--
 include/linux/dma-attrs.h          |  3 +-
 include/linux/dma-iommu.h          |  6 +--
 include/linux/dma-mapping.h        | 34 ++++++++-------
 include/linux/swiotlb.h            |  9 ++--
 lib/dma-noop.c                     |  9 ++--
 lib/swiotlb.c                      |  9 ++--
 11 files changed, 123 insertions(+), 109 deletions(-)

-- 
1.9.1



From k.kozlowski at samsung.com  Mon May 23 23:28:09 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 24 May 2016 08:28:09 +0200
Subject: [PATCH 3/4] arm64: dma-mapping: Constify attrs passed to internal
 functions
In-Reply-To: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>
References: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1464071290-15948-4-git-send-email-k.kozlowski@samsung.com>

Some of the non-exported functions do not modify passed dma_attrs so the
pointer can point to const data.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm64/mm/dma-mapping.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index c566ec83719f..0ef620a34c4e 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -29,7 +29,7 @@
 
 #include <asm/cacheflush.h>
 
-static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
+static pgprot_t __get_dma_pgprot(const struct dma_attrs *attrs, pgprot_t prot,
 				 bool coherent)
 {
 	if (!coherent || dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs))
@@ -88,7 +88,7 @@ static int __free_from_pool(void *start, size_t size)
 
 static void *__dma_alloc_coherent(struct device *dev, size_t size,
 				  dma_addr_t *dma_handle, gfp_t flags,
-				  struct dma_attrs *attrs)
+				  const struct dma_attrs *attrs)
 {
 	if (dev == NULL) {
 		WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
@@ -118,7 +118,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
 
 static void __dma_free_coherent(struct device *dev, size_t size,
 				void *vaddr, dma_addr_t dma_handle,
-				struct dma_attrs *attrs)
+				const struct dma_attrs *attrs)
 {
 	bool freed;
 	phys_addr_t paddr = dma_to_phys(dev, dma_handle);
-- 
1.9.1



From k.kozlowski at samsung.com  Mon May 23 23:28:08 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 24 May 2016 08:28:08 +0200
Subject: [PATCH 2/4] ARM: dma-mapping: Constify attrs passed to internal
 functions
In-Reply-To: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>
References: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1464071290-15948-3-git-send-email-k.kozlowski@samsung.com>

Some of the non-exported functions do not modify passed dma_attrs so the
pointer can point to const data.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm/mm/dma-mapping.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index ff7ed5697d3e..4abc50952451 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -621,7 +621,7 @@ static void __free_from_contiguous(struct device *dev, struct page *page,
 	dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
 }
 
-static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
+static inline pgprot_t __get_dma_pgprot(const struct dma_attrs *attrs, pgprot_t prot)
 {
 	prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
 			    pgprot_writecombine(prot) :
@@ -732,7 +732,7 @@ static struct arm_dma_allocator remap_allocator = {
 
 static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 			 gfp_t gfp, pgprot_t prot, bool is_coherent,
-			 struct dma_attrs *attrs, const void *caller)
+			 const struct dma_attrs *attrs, const void *caller)
 {
 	u64 mask = get_coherent_dma_mask(dev);
 	struct page *page = NULL;
@@ -878,7 +878,7 @@ int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
  * Free a buffer as defined by the above mapping.
  */
 static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-			   dma_addr_t handle, struct dma_attrs *attrs,
+			   dma_addr_t handle, const struct dma_attrs *attrs,
 			   bool is_coherent)
 {
 	struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
@@ -1253,7 +1253,8 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping,
 static const int iommu_order_array[] = { 9, 8, 4, 0 };
 
 static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
-					  gfp_t gfp, struct dma_attrs *attrs)
+					  gfp_t gfp,
+					  const struct dma_attrs *attrs)
 {
 	struct page **pages;
 	int count = size >> PAGE_SHIFT;
@@ -1342,7 +1343,7 @@ error:
 }
 
 static int __iommu_free_buffer(struct device *dev, struct page **pages,
-			       size_t size, struct dma_attrs *attrs)
+			       size_t size, const struct dma_attrs *attrs)
 {
 	int count = size >> PAGE_SHIFT;
 	int i;
@@ -1439,7 +1440,8 @@ static struct page **__atomic_get_pages(void *addr)
 	return (struct page **)page;
 }
 
-static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
+static struct page **__iommu_get_pages(void *cpu_addr,
+				       const struct dma_attrs *attrs)
 {
 	struct vm_struct *area;
 
@@ -1633,8 +1635,8 @@ static int __dma_direction_to_prot(enum dma_data_direction dir)
  */
 static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
 			  size_t size, dma_addr_t *handle,
-			  enum dma_data_direction dir, struct dma_attrs *attrs,
-			  bool is_coherent)
+			  enum dma_data_direction dir,
+			  const struct dma_attrs *attrs, bool is_coherent)
 {
 	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
 	dma_addr_t iova, iova_base;
@@ -1676,8 +1678,8 @@ fail:
 }
 
 static int __iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-		     enum dma_data_direction dir, struct dma_attrs *attrs,
-		     bool is_coherent)
+		     enum dma_data_direction dir,
+		     const struct dma_attrs *attrs, bool is_coherent)
 {
 	struct scatterlist *s = sg, *dma = sg, *start = sg;
 	int i, count = 0;
@@ -1758,8 +1760,8 @@ int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg,
 }
 
 static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
-		int nents, enum dma_data_direction dir, struct dma_attrs *attrs,
-		bool is_coherent)
+		int nents, enum dma_data_direction dir,
+		const struct dma_attrs *attrs, bool is_coherent)
 {
 	struct scatterlist *s;
 	int i;
-- 
1.9.1



From k.kozlowski at samsung.com  Mon May 23 23:28:10 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 24 May 2016 08:28:10 +0200
Subject: [RFC 4/4] dma-mapping: Constify dma_attrs
In-Reply-To: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>
References: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1464071290-15948-5-git-send-email-k.kozlowski@samsung.com>

Pointer to dma_attrs passed to all dma-mapping implementations can point
to const data. This brings some benefits:
 - const-safeness,
 - is a direct indication that ownership of memory is not transferred to
   called functions so it can be safely allocated on the stack (which is
   a pattern already used).

Please have in mind that this is RFC, not finished yet. Only ARM and
ARM64 are fixed. However other API users also have to be converted which
is quite intrusive. I would rather avoid it until the overall approach
is accepted.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 arch/arm/include/asm/dma-mapping.h | 12 ++++----
 arch/arm/mm/dma-mapping.c          | 61 +++++++++++++++++++++-----------------
 arch/arm/xen/mm.c                  |  4 +--
 arch/arm64/mm/dma-mapping.c        | 47 +++++++++++++++--------------
 drivers/iommu/dma-iommu.c          |  6 ++--
 include/linux/dma-iommu.h          |  6 ++--
 include/linux/dma-mapping.h        | 34 +++++++++++----------
 include/linux/swiotlb.h            |  9 +++---
 lib/dma-noop.c                     |  9 +++---
 lib/swiotlb.c                      |  9 +++---
 10 files changed, 104 insertions(+), 93 deletions(-)

diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index a83570f10124..07202beed663 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -174,7 +174,7 @@ static inline void dma_mark_clean(void *addr, size_t size) { }
  * to be the device-viewed address.
  */
 extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-			   gfp_t gfp, struct dma_attrs *attrs);
+			   gfp_t gfp, const struct dma_attrs *attrs);
 
 /**
  * arm_dma_free - free memory allocated by arm_dma_alloc
@@ -191,7 +191,7 @@ extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
  * during and after this call executing are illegal.
  */
 extern void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-			 dma_addr_t handle, struct dma_attrs *attrs);
+			 dma_addr_t handle, const struct dma_attrs *attrs);
 
 /**
  * arm_dma_mmap - map a coherent DMA allocation into user space
@@ -208,7 +208,7 @@ extern void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
  */
 extern int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 			void *cpu_addr, dma_addr_t dma_addr, size_t size,
-			struct dma_attrs *attrs);
+			const struct dma_attrs *attrs);
 
 /*
  * This can be called during early boot to increase the size of the atomic
@@ -262,16 +262,16 @@ extern void dmabounce_unregister_dev(struct device *);
  * The scatter list versions of the above methods.
  */
 extern int arm_dma_map_sg(struct device *, struct scatterlist *, int,
-		enum dma_data_direction, struct dma_attrs *attrs);
+		enum dma_data_direction, const struct dma_attrs *attrs);
 extern void arm_dma_unmap_sg(struct device *, struct scatterlist *, int,
-		enum dma_data_direction, struct dma_attrs *attrs);
+		enum dma_data_direction, const struct dma_attrs *attrs);
 extern void arm_dma_sync_sg_for_cpu(struct device *, struct scatterlist *, int,
 		enum dma_data_direction);
 extern void arm_dma_sync_sg_for_device(struct device *, struct scatterlist *, int,
 		enum dma_data_direction);
 extern int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
 		void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		struct dma_attrs *attrs);
+		const struct dma_attrs *attrs);
 
 #endif /* __KERNEL__ */
 #endif
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 4abc50952451..245954e7e343 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -124,7 +124,7 @@ static void __dma_page_dev_to_cpu(struct page *, unsigned long,
  */
 static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
 	     unsigned long offset, size_t size, enum dma_data_direction dir,
-	     struct dma_attrs *attrs)
+	     const struct dma_attrs *attrs)
 {
 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__dma_page_cpu_to_dev(page, offset, size, dir);
@@ -133,7 +133,7 @@ static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
 
 static dma_addr_t arm_coherent_dma_map_page(struct device *dev, struct page *page,
 	     unsigned long offset, size_t size, enum dma_data_direction dir,
-	     struct dma_attrs *attrs)
+	     const struct dma_attrs *attrs)
 {
 	return pfn_to_dma(dev, page_to_pfn(page)) + offset;
 }
@@ -154,7 +154,7 @@ static dma_addr_t arm_coherent_dma_map_page(struct device *dev, struct page *pag
  */
 static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir,
-		struct dma_attrs *attrs)
+		const struct dma_attrs *attrs)
 {
 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
@@ -194,12 +194,13 @@ struct dma_map_ops arm_dma_ops = {
 EXPORT_SYMBOL(arm_dma_ops);
 
 static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
-	dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs);
+	dma_addr_t *handle, gfp_t gfp, const struct dma_attrs *attrs);
 static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
-				  dma_addr_t handle, struct dma_attrs *attrs);
+				  dma_addr_t handle,
+				  const struct dma_attrs *attrs);
 static int arm_coherent_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		 struct dma_attrs *attrs);
+		 const struct dma_attrs *attrs);
 
 struct dma_map_ops arm_coherent_dma_ops = {
 	.alloc			= arm_coherent_dma_alloc,
@@ -814,7 +815,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
  * virtual and bus address for that space.
  */
 void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-		    gfp_t gfp, struct dma_attrs *attrs)
+		    gfp_t gfp, const struct dma_attrs *attrs)
 {
 	pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
 
@@ -823,7 +824,7 @@ void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 }
 
 static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
-	dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+	dma_addr_t *handle, gfp_t gfp, const struct dma_attrs *attrs)
 {
 	return __dma_alloc(dev, size, handle, gfp, PAGE_KERNEL, true,
 			   attrs, __builtin_return_address(0));
@@ -831,7 +832,7 @@ static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
 
 static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		 struct dma_attrs *attrs)
+		 const struct dma_attrs *attrs)
 {
 	int ret = -ENXIO;
 #ifdef CONFIG_MMU
@@ -859,14 +860,14 @@ static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
  */
 static int arm_coherent_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		 struct dma_attrs *attrs)
+		 const struct dma_attrs *attrs)
 {
 	return __arm_dma_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
 }
 
 int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		 struct dma_attrs *attrs)
+		 const struct dma_attrs *attrs)
 {
 #ifdef CONFIG_MMU
 	vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
@@ -900,20 +901,20 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
 }
 
 void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-		  dma_addr_t handle, struct dma_attrs *attrs)
+		  dma_addr_t handle, const struct dma_attrs *attrs)
 {
 	__arm_dma_free(dev, size, cpu_addr, handle, attrs, false);
 }
 
 static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
-				  dma_addr_t handle, struct dma_attrs *attrs)
+				  dma_addr_t handle, const struct dma_attrs *attrs)
 {
 	__arm_dma_free(dev, size, cpu_addr, handle, attrs, true);
 }
 
 int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
 		 void *cpu_addr, dma_addr_t handle, size_t size,
-		 struct dma_attrs *attrs)
+		 const struct dma_attrs *attrs)
 {
 	struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
 	int ret;
@@ -1046,7 +1047,7 @@ static void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
  * here.
  */
 int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-		enum dma_data_direction dir, struct dma_attrs *attrs)
+		enum dma_data_direction dir, const struct dma_attrs *attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	struct scatterlist *s;
@@ -1080,7 +1081,7 @@ int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
  * rules concerning calls here are the same as for dma_unmap_single().
  */
 void arm_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-		enum dma_data_direction dir, struct dma_attrs *attrs)
+		enum dma_data_direction dir, const struct dma_attrs *attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	struct scatterlist *s;
@@ -1486,7 +1487,7 @@ static void __iommu_free_atomic(struct device *dev, void *cpu_addr,
 }
 
 static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
-	    dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+	    dma_addr_t *handle, gfp_t gfp, const struct dma_attrs *attrs)
 {
 	pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
 	struct page **pages;
@@ -1534,7 +1535,7 @@ err_buffer:
 
 static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 		    void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		    struct dma_attrs *attrs)
+		    const struct dma_attrs *attrs)
 {
 	unsigned long uaddr = vma->vm_start;
 	unsigned long usize = vma->vm_end - vma->vm_start;
@@ -1570,7 +1571,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
  * Must not be called with IRQs disabled.
  */
 void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
-			  dma_addr_t handle, struct dma_attrs *attrs)
+			  dma_addr_t handle, const struct dma_attrs *attrs)
 {
 	struct page **pages;
 	size = PAGE_ALIGN(size);
@@ -1597,7 +1598,7 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
 
 static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
 				 void *cpu_addr, dma_addr_t dma_addr,
-				 size_t size, struct dma_attrs *attrs)
+				 size_t size, const struct dma_attrs *attrs)
 {
 	unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
 	struct page **pages = __iommu_get_pages(cpu_addr, attrs);
@@ -1736,7 +1737,8 @@ bad_mapping:
  * obtained via sg_dma_{address,length}.
  */
 int arm_coherent_iommu_map_sg(struct device *dev, struct scatterlist *sg,
-		int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+		int nents, enum dma_data_direction dir,
+		const struct dma_attrs *attrs)
 {
 	return __iommu_map_sg(dev, sg, nents, dir, attrs, true);
 }
@@ -1754,7 +1756,8 @@ int arm_coherent_iommu_map_sg(struct device *dev, struct scatterlist *sg,
  * sg_dma_{address,length}.
  */
 int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg,
-		int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+		int nents, enum dma_data_direction dir,
+		const struct dma_attrs *attrs)
 {
 	return __iommu_map_sg(dev, sg, nents, dir, attrs, false);
 }
@@ -1788,7 +1791,8 @@ static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
  * rules concerning calls here are the same as for dma_unmap_single().
  */
 void arm_coherent_iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
-		int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+		int nents, enum dma_data_direction dir,
+		const struct dma_attrs *attrs)
 {
 	__iommu_unmap_sg(dev, sg, nents, dir, attrs, true);
 }
@@ -1804,7 +1808,8 @@ void arm_coherent_iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
  * rules concerning calls here are the same as for dma_unmap_single().
  */
 void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-			enum dma_data_direction dir, struct dma_attrs *attrs)
+			enum dma_data_direction dir,
+			const struct dma_attrs *attrs)
 {
 	__iommu_unmap_sg(dev, sg, nents, dir, attrs, false);
 }
@@ -1857,7 +1862,7 @@ void arm_iommu_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
  */
 static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *page,
 	     unsigned long offset, size_t size, enum dma_data_direction dir,
-	     struct dma_attrs *attrs)
+	     const struct dma_attrs *attrs)
 {
 	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
 	dma_addr_t dma_addr;
@@ -1891,7 +1896,7 @@ fail:
  */
 static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
 	     unsigned long offset, size_t size, enum dma_data_direction dir,
-	     struct dma_attrs *attrs)
+	     const struct dma_attrs *attrs)
 {
 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__dma_page_cpu_to_dev(page, offset, size, dir);
@@ -1910,7 +1915,7 @@ static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
  */
 static void arm_coherent_iommu_unmap_page(struct device *dev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir,
-		struct dma_attrs *attrs)
+		const struct dma_attrs *attrs)
 {
 	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
 	dma_addr_t iova = handle & PAGE_MASK;
@@ -1935,7 +1940,7 @@ static void arm_coherent_iommu_unmap_page(struct device *dev, dma_addr_t handle,
  */
 static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir,
-		struct dma_attrs *attrs)
+		const struct dma_attrs *attrs)
 {
 	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
 	dma_addr_t iova = handle & PAGE_MASK;
diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
index c5f9a9e3d1f3..0af2fbbc25be 100644
--- a/arch/arm/xen/mm.c
+++ b/arch/arm/xen/mm.c
@@ -98,7 +98,7 @@ static void __xen_dma_page_cpu_to_dev(struct device *hwdev, dma_addr_t handle,
 
 void __xen_dma_map_page(struct device *hwdev, struct page *page,
 	     dma_addr_t dev_addr, unsigned long offset, size_t size,
-	     enum dma_data_direction dir, struct dma_attrs *attrs)
+	     enum dma_data_direction dir, const struct dma_attrs *attrs)
 {
 	if (is_device_dma_coherent(hwdev))
 		return;
@@ -110,7 +110,7 @@ void __xen_dma_map_page(struct device *hwdev, struct page *page,
 
 void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir,
-		struct dma_attrs *attrs)
+		const struct dma_attrs *attrs)
 
 {
 	if (is_device_dma_coherent(hwdev))
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 0ef620a34c4e..9f6c6b12db30 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -137,7 +137,7 @@ static void __dma_free_coherent(struct device *dev, size_t size,
 
 static void *__dma_alloc(struct device *dev, size_t size,
 			 dma_addr_t *dma_handle, gfp_t flags,
-			 struct dma_attrs *attrs)
+			 const struct dma_attrs *attrs)
 {
 	struct page *page;
 	void *ptr, *coherent_ptr;
@@ -185,7 +185,7 @@ no_mem:
 
 static void __dma_free(struct device *dev, size_t size,
 		       void *vaddr, dma_addr_t dma_handle,
-		       struct dma_attrs *attrs)
+		       const struct dma_attrs *attrs)
 {
 	void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
 
@@ -202,7 +202,7 @@ static void __dma_free(struct device *dev, size_t size,
 static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
 				     unsigned long offset, size_t size,
 				     enum dma_data_direction dir,
-				     struct dma_attrs *attrs)
+				     const struct dma_attrs *attrs)
 {
 	dma_addr_t dev_addr;
 
@@ -216,7 +216,7 @@ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
 
 static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
 				 size_t size, enum dma_data_direction dir,
-				 struct dma_attrs *attrs)
+				 const struct dma_attrs *attrs)
 {
 	if (!is_device_dma_coherent(dev))
 		__dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
@@ -225,7 +225,7 @@ static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
 
 static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
 				  int nelems, enum dma_data_direction dir,
-				  struct dma_attrs *attrs)
+				  const struct dma_attrs *attrs)
 {
 	struct scatterlist *sg;
 	int i, ret;
@@ -242,7 +242,7 @@ static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
 static void __swiotlb_unmap_sg_attrs(struct device *dev,
 				     struct scatterlist *sgl, int nelems,
 				     enum dma_data_direction dir,
-				     struct dma_attrs *attrs)
+				     const struct dma_attrs *attrs)
 {
 	struct scatterlist *sg;
 	int i;
@@ -303,7 +303,7 @@ static void __swiotlb_sync_sg_for_device(struct device *dev,
 static int __swiotlb_mmap(struct device *dev,
 			  struct vm_area_struct *vma,
 			  void *cpu_addr, dma_addr_t dma_addr, size_t size,
-			  struct dma_attrs *attrs)
+			  const struct dma_attrs *attrs)
 {
 	int ret = -ENXIO;
 	unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >>
@@ -330,7 +330,7 @@ static int __swiotlb_mmap(struct device *dev,
 
 static int __swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt,
 				 void *cpu_addr, dma_addr_t handle, size_t size,
-				 struct dma_attrs *attrs)
+				 const struct dma_attrs *attrs)
 {
 	int ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
 
@@ -425,21 +425,21 @@ out:
 
 static void *__dummy_alloc(struct device *dev, size_t size,
 			   dma_addr_t *dma_handle, gfp_t flags,
-			   struct dma_attrs *attrs)
+			   const struct dma_attrs *attrs)
 {
 	return NULL;
 }
 
 static void __dummy_free(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle,
-			 struct dma_attrs *attrs)
+			 const struct dma_attrs *attrs)
 {
 }
 
 static int __dummy_mmap(struct device *dev,
 			struct vm_area_struct *vma,
 			void *cpu_addr, dma_addr_t dma_addr, size_t size,
-			struct dma_attrs *attrs)
+			const struct dma_attrs *attrs)
 {
 	return -ENXIO;
 }
@@ -447,20 +447,20 @@ static int __dummy_mmap(struct device *dev,
 static dma_addr_t __dummy_map_page(struct device *dev, struct page *page,
 				   unsigned long offset, size_t size,
 				   enum dma_data_direction dir,
-				   struct dma_attrs *attrs)
+				   const struct dma_attrs *attrs)
 {
 	return DMA_ERROR_CODE;
 }
 
 static void __dummy_unmap_page(struct device *dev, dma_addr_t dev_addr,
 			       size_t size, enum dma_data_direction dir,
-			       struct dma_attrs *attrs)
+			       const struct dma_attrs *attrs)
 {
 }
 
 static int __dummy_map_sg(struct device *dev, struct scatterlist *sgl,
 			  int nelems, enum dma_data_direction dir,
-			  struct dma_attrs *attrs)
+			  const struct dma_attrs *attrs)
 {
 	return 0;
 }
@@ -468,7 +468,7 @@ static int __dummy_map_sg(struct device *dev, struct scatterlist *sgl,
 static void __dummy_unmap_sg(struct device *dev,
 			     struct scatterlist *sgl, int nelems,
 			     enum dma_data_direction dir,
-			     struct dma_attrs *attrs)
+			     const struct dma_attrs *attrs)
 {
 }
 
@@ -540,7 +540,7 @@ static void flush_page(struct device *dev, const void *virt, phys_addr_t phys)
 
 static void *__iommu_alloc_attrs(struct device *dev, size_t size,
 				 dma_addr_t *handle, gfp_t gfp,
-				 struct dma_attrs *attrs)
+				 const struct dma_attrs *attrs)
 {
 	bool coherent = is_device_dma_coherent(dev);
 	int ioprot = dma_direction_to_prot(DMA_BIDIRECTIONAL, coherent);
@@ -600,7 +600,8 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
 }
 
 static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
-			       dma_addr_t handle, struct dma_attrs *attrs)
+			       dma_addr_t handle,
+			       const struct dma_attrs *attrs)
 {
 	size_t iosize = size;
 
@@ -633,7 +634,7 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
 
 static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 			      void *cpu_addr, dma_addr_t dma_addr, size_t size,
-			      struct dma_attrs *attrs)
+			      const struct dma_attrs *attrs)
 {
 	struct vm_struct *area;
 	int ret;
@@ -653,7 +654,7 @@ static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 
 static int __iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
 			       void *cpu_addr, dma_addr_t dma_addr,
-			       size_t size, struct dma_attrs *attrs)
+			       size_t size, const struct dma_attrs *attrs)
 {
 	unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
 	struct vm_struct *area = find_vm_area(cpu_addr);
@@ -694,7 +695,7 @@ static void __iommu_sync_single_for_device(struct device *dev,
 static dma_addr_t __iommu_map_page(struct device *dev, struct page *page,
 				   unsigned long offset, size_t size,
 				   enum dma_data_direction dir,
-				   struct dma_attrs *attrs)
+				   const struct dma_attrs *attrs)
 {
 	bool coherent = is_device_dma_coherent(dev);
 	int prot = dma_direction_to_prot(dir, coherent);
@@ -709,7 +710,7 @@ static dma_addr_t __iommu_map_page(struct device *dev, struct page *page,
 
 static void __iommu_unmap_page(struct device *dev, dma_addr_t dev_addr,
 			       size_t size, enum dma_data_direction dir,
-			       struct dma_attrs *attrs)
+			       const struct dma_attrs *attrs)
 {
 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__iommu_sync_single_for_cpu(dev, dev_addr, size, dir);
@@ -747,7 +748,7 @@ static void __iommu_sync_sg_for_device(struct device *dev,
 
 static int __iommu_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
 				int nelems, enum dma_data_direction dir,
-				struct dma_attrs *attrs)
+				const struct dma_attrs *attrs)
 {
 	bool coherent = is_device_dma_coherent(dev);
 
@@ -761,7 +762,7 @@ static int __iommu_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
 static void __iommu_unmap_sg_attrs(struct device *dev,
 				   struct scatterlist *sgl, int nelems,
 				   enum dma_data_direction dir,
-				   struct dma_attrs *attrs)
+				   const struct dma_attrs *attrs)
 {
 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__iommu_sync_sg_for_cpu(dev, sgl, nelems, dir);
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index ea5a9ebf0f78..69eb1fdce971 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -286,7 +286,7 @@ void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
  *	   or NULL on failure.
  */
 struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
-		struct dma_attrs *attrs, int prot, dma_addr_t *handle,
+		const struct dma_attrs *attrs, int prot, dma_addr_t *handle,
 		void (*flush_page)(struct device *, const void *, phys_addr_t))
 {
 	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
@@ -400,7 +400,7 @@ dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
 }
 
 void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
-		enum dma_data_direction dir, struct dma_attrs *attrs)
+		enum dma_data_direction dir, const struct dma_attrs *attrs)
 {
 	__iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
 }
@@ -560,7 +560,7 @@ out_restore_sg:
 }
 
 void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-		enum dma_data_direction dir, struct dma_attrs *attrs)
+		enum dma_data_direction dir, const struct dma_attrs *attrs)
 {
 	/*
 	 * The scatterlist segments are mapped into a single
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 8443bbb5c071..797b47bc6dae 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -39,7 +39,7 @@ int dma_direction_to_prot(enum dma_data_direction dir, bool coherent);
  * the arch code to take care of attributes and cache maintenance
  */
 struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
-		struct dma_attrs *attrs, int prot, dma_addr_t *handle,
+		const struct dma_attrs *attrs, int prot, dma_addr_t *handle,
 		void (*flush_page)(struct device *, const void *, phys_addr_t));
 void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
 		dma_addr_t *handle);
@@ -56,9 +56,9 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
  * directly as DMA mapping callbacks for simplicity
  */
 void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
-		enum dma_data_direction dir, struct dma_attrs *attrs);
+		enum dma_data_direction dir, const struct dma_attrs *attrs);
 void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-		enum dma_data_direction dir, struct dma_attrs *attrs);
+		enum dma_data_direction dir, const struct dma_attrs *attrs);
 int iommu_dma_supported(struct device *dev, u64 mask);
 int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
 
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 71c1b215ef66..c8b339436dfa 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -21,34 +21,35 @@
 struct dma_map_ops {
 	void* (*alloc)(struct device *dev, size_t size,
 				dma_addr_t *dma_handle, gfp_t gfp,
-				struct dma_attrs *attrs);
+				const struct dma_attrs *attrs);
 	void (*free)(struct device *dev, size_t size,
 			      void *vaddr, dma_addr_t dma_handle,
-			      struct dma_attrs *attrs);
+			      const struct dma_attrs *attrs);
 	int (*mmap)(struct device *, struct vm_area_struct *,
-			  void *, dma_addr_t, size_t, struct dma_attrs *attrs);
+			  void *, dma_addr_t, size_t,
+			  const struct dma_attrs *attrs);
 
 	int (*get_sgtable)(struct device *dev, struct sg_table *sgt, void *,
-			   dma_addr_t, size_t, struct dma_attrs *attrs);
+			   dma_addr_t, size_t, const struct dma_attrs *attrs);
 
 	dma_addr_t (*map_page)(struct device *dev, struct page *page,
 			       unsigned long offset, size_t size,
 			       enum dma_data_direction dir,
-			       struct dma_attrs *attrs);
+			       const struct dma_attrs *attrs);
 	void (*unmap_page)(struct device *dev, dma_addr_t dma_handle,
 			   size_t size, enum dma_data_direction dir,
-			   struct dma_attrs *attrs);
+			   const struct dma_attrs *attrs);
 	/*
 	 * map_sg returns 0 on error and a value > 0 on success.
 	 * It should never return a value < 0.
 	 */
 	int (*map_sg)(struct device *dev, struct scatterlist *sg,
 		      int nents, enum dma_data_direction dir,
-		      struct dma_attrs *attrs);
+		      const struct dma_attrs *attrs);
 	void (*unmap_sg)(struct device *dev,
 			 struct scatterlist *sg, int nents,
 			 enum dma_data_direction dir,
-			 struct dma_attrs *attrs);
+			 const struct dma_attrs *attrs);
 	void (*sync_single_for_cpu)(struct device *dev,
 				    dma_addr_t dma_handle, size_t size,
 				    enum dma_data_direction dir);
@@ -123,7 +124,7 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
 static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
 					      size_t size,
 					      enum dma_data_direction dir,
-					      struct dma_attrs *attrs)
+					      const struct dma_attrs *attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	dma_addr_t addr;
@@ -142,7 +143,7 @@ static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
 static inline void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr,
 					  size_t size,
 					  enum dma_data_direction dir,
-					  struct dma_attrs *attrs)
+					  const struct dma_attrs *attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 
@@ -158,7 +159,7 @@ static inline void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr,
  */
 static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
 				   int nents, enum dma_data_direction dir,
-				   struct dma_attrs *attrs)
+				   const struct dma_attrs *attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	int i, ents;
@@ -176,7 +177,7 @@ static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
 
 static inline void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
 				      int nents, enum dma_data_direction dir,
-				      struct dma_attrs *attrs)
+				      const struct dma_attrs *attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 
@@ -321,7 +322,7 @@ void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags);
  */
 static inline int
 dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr,
-	       dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
+	       dma_addr_t dma_addr, size_t size, const struct dma_attrs *attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	BUG_ON(!ops);
@@ -338,7 +339,8 @@ dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
 
 static inline int
 dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr,
-		      dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
+		      dma_addr_t dma_addr, size_t size,
+		      const struct dma_attrs *attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	BUG_ON(!ops);
@@ -356,7 +358,7 @@ dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr,
 
 static inline void *dma_alloc_attrs(struct device *dev, size_t size,
 				       dma_addr_t *dma_handle, gfp_t flag,
-				       struct dma_attrs *attrs)
+				       const struct dma_attrs *attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	void *cpu_addr;
@@ -378,7 +380,7 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size,
 
 static inline void dma_free_attrs(struct device *dev, size_t size,
 				     void *cpu_addr, dma_addr_t dma_handle,
-				     struct dma_attrs *attrs)
+				     const struct dma_attrs *attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 017fced60242..0ff87d75982b 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -68,10 +68,10 @@ swiotlb_free_coherent(struct device *hwdev, size_t size,
 extern dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 				   unsigned long offset, size_t size,
 				   enum dma_data_direction dir,
-				   struct dma_attrs *attrs);
+				   const struct dma_attrs *attrs);
 extern void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
 			       size_t size, enum dma_data_direction dir,
-			       struct dma_attrs *attrs);
+			       const struct dma_attrs *attrs);
 
 extern int
 swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
@@ -83,12 +83,13 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
 
 extern int
 swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
-		     enum dma_data_direction dir, struct dma_attrs *attrs);
+		     enum dma_data_direction dir,
+		     const struct dma_attrs *attrs);
 
 extern void
 swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
 		       int nelems, enum dma_data_direction dir,
-		       struct dma_attrs *attrs);
+		       const struct dma_attrs *attrs);
 
 extern void
 swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
diff --git a/lib/dma-noop.c b/lib/dma-noop.c
index 72145646857e..22e44fc26eba 100644
--- a/lib/dma-noop.c
+++ b/lib/dma-noop.c
@@ -10,7 +10,7 @@
 
 static void *dma_noop_alloc(struct device *dev, size_t size,
 			    dma_addr_t *dma_handle, gfp_t gfp,
-			    struct dma_attrs *attrs)
+			    const struct dma_attrs *attrs)
 {
 	void *ret;
 
@@ -22,7 +22,7 @@ static void *dma_noop_alloc(struct device *dev, size_t size,
 
 static void dma_noop_free(struct device *dev, size_t size,
 			  void *cpu_addr, dma_addr_t dma_addr,
-			  struct dma_attrs *attrs)
+			  const struct dma_attrs *attrs)
 {
 	free_pages((unsigned long)cpu_addr, get_order(size));
 }
@@ -30,13 +30,14 @@ static void dma_noop_free(struct device *dev, size_t size,
 static dma_addr_t dma_noop_map_page(struct device *dev, struct page *page,
 				      unsigned long offset, size_t size,
 				      enum dma_data_direction dir,
-				      struct dma_attrs *attrs)
+				      const struct dma_attrs *attrs)
 {
 	return page_to_phys(page) + offset;
 }
 
 static int dma_noop_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
-			     enum dma_data_direction dir, struct dma_attrs *attrs)
+			     enum dma_data_direction dir,
+			     const struct dma_attrs *attrs)
 {
 	int i;
 	struct scatterlist *sg;
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 76f29ecba8f4..f881405d0b17 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -738,7 +738,7 @@ swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir,
 dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 			    unsigned long offset, size_t size,
 			    enum dma_data_direction dir,
-			    struct dma_attrs *attrs)
+			    const struct dma_attrs *attrs)
 {
 	phys_addr_t map, phys = page_to_phys(page) + offset;
 	dma_addr_t dev_addr = phys_to_dma(dev, phys);
@@ -807,7 +807,7 @@ static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
 
 void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
 			size_t size, enum dma_data_direction dir,
-			struct dma_attrs *attrs)
+			const struct dma_attrs *attrs)
 {
 	unmap_single(hwdev, dev_addr, size, dir);
 }
@@ -877,7 +877,7 @@ EXPORT_SYMBOL(swiotlb_sync_single_for_device);
  */
 int
 swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
-		     enum dma_data_direction dir, struct dma_attrs *attrs)
+		     enum dma_data_direction dir, const struct dma_attrs *attrs)
 {
 	struct scatterlist *sg;
 	int i;
@@ -924,7 +924,8 @@ EXPORT_SYMBOL(swiotlb_map_sg);
  */
 void
 swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
-		       int nelems, enum dma_data_direction dir, struct dma_attrs *attrs)
+		       int nelems, enum dma_data_direction dir,
+		       const struct dma_attrs *attrs)
 {
 	struct scatterlist *sg;
 	int i;
-- 
1.9.1



From geert at linux-m68k.org  Mon May 23 23:35:13 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Tue, 24 May 2016 08:35:13 +0200
Subject: [PATCH v2 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <5742B66C.7080102@rvc.renesas.com>
References: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>
 <1463966906-15129-2-git-send-email-horms+renesas@verge.net.au>
 <CAMuHMdXsu=O13rLysob1Xp+5vWcp7gq6byCffR-6hGc+W-837A@mail.gmail.com>
 <5742B66C.7080102@rvc.renesas.com>
Message-ID: <CAMuHMdV+atFKJjxcH7RkBCdabsBqk5Y3TTHCPN+sprDaM1xj_w@mail.gmail.com>

Hi Khiem,

On Mon, May 23, 2016 at 9:51 AM, Khiem Nguyen
<khiem.nguyen.xt at rvc.renesas.com> wrote:
> Using 1.0 will open Suspend-to-RAM support if secure firmware supports that
> feature.
> However, we might need additional work in drivers to support suspend/resume
> handlers.
> So, I suggest that we keep using 0.2 until Suspend-to-RAM feature is
> confirmed in r8a7795/r8a7796.

Note that we do have suspend/resume support on R-Car Gen2, albeit some
drivers may lack code to save/restore state when their devices are powered
down, as R-Car Gen2 doesn't have power domains for devices.

So I'd expect everything to work fine, as long as no R-Car Gen3-specific
drivers or devices residing in multimedia power domains are involved.

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 peppe.cavallaro at st.com  Tue May 24 00:08:47 2016
From: peppe.cavallaro at st.com (Giuseppe CAVALLARO)
Date: Tue, 24 May 2016 09:08:47 +0200
Subject: [PATCH 0/2 (linux-stable-4.5.y)] net: stmmac: MDIO fixes
In-Reply-To: <20160523153619.GA30179@kroah.com>
References: <1464009463-23654-1-git-send-email-peppe.cavallaro@st.com>
 <20160523153619.GA30179@kroah.com>
Message-ID: <5743FDFF.9000704@st.com>

On 5/23/2016 5:36 PM, Greg KH wrote:
> On Mon, May 23, 2016 at 03:17:41PM +0200, Giuseppe Cavallaro wrote:
>> These patches port some recent fixes for linux-4.5.y stable branch.
>> They fix the MDIO settings trying to cover the all possible scenario
>> when the stmmac is connected to a real transceiver or a switch.
>>
>> These patches are needed for Kernel 4.5 where Lime2, BananaPi and Cubieboard2
>> show problems when use the stmmac:
>>
>> https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=823493
>
> What are the git commit id for these patches in Linus's tree?

Commits are:

stmmac: fix MDIO settings

    a7657f128c279ae5796ab2ca7d04a7819f4259f0

and

Revert "stmmac: Fix 'eth0: No PHY found' regression"

    d7e944c8ddc0983640a9a32868fb217485d12ca2

Regards
Peppe

>
> thanks,
>
> greg k-h
>
>



From daniel at fooishbar.org  Tue May 24 00:19:10 2016
From: daniel at fooishbar.org (Daniel Stone)
Date: Tue, 24 May 2016 09:19:10 +0200
Subject: [PATCH] drm/rockchip: Return -EBUSY if there's already a pending
 flip event v3
In-Reply-To: <CAAObsKAyeg9JsPhCyWqLpg3n6V9Ab8OCJKXX41A86rQWWs+SdQ@mail.gmail.com>
References: <1459778134-30693-1-git-send-email-tomeu.vizoso@collabora.com>
 <CAPj87rPtP1ph-1FMxSKUANjeKwwjwgfMzbUGHvqudEx7nYCESQ@mail.gmail.com>
 <CAAObsKAyeg9JsPhCyWqLpg3n6V9Ab8OCJKXX41A86rQWWs+SdQ@mail.gmail.com>
Message-ID: <CAPj87rPgvjs5W68Cou6ODDqbqbPXQvFxLPtegBkdxdtPaRMX7A@mail.gmail.com>

Hi Tomeu,

On 5 April 2016 at 16:07, Tomeu Vizoso <tomeu.vizoso at collabora.com> wrote:
> On 4 April 2016 at 17:44, Daniel Stone <daniel at fooishbar.org> wrote:
>> On 4 April 2016 at 14:55, Tomeu Vizoso <tomeu.vizoso at collabora.com> wrote:
>>> +       if (async) {
>>> +               for_each_crtc_in_state(state, crtc, crtc_state, i) {
>>> +                       if (crtc->state->event ||
>>> +                           rockchip_drm_crtc_has_pending_event(crtc)) {
>>> +                               return -EBUSY;
>>> +                       }
>>> +               }
>>> +       }
>>
>> Hmmm ...
>>
>> Doesn't this trigger before the VOP atomic_begin() helper, meaning
>> that anything with an event set will trigger the check? Seems like it
>> should be && rather than ||.
>
> So, these are the two cases that this code aims to handle:
>
> 1. A previous request with an event set hasn't progressed to
> atomic_begin yet, so the event field in drm_crtc_state (at this point,
> the old state) is still populated but vop->event still isn't.

Ah right, this was what I was missing: the async (non-blocking)
implementation. Sounds good to me then.

Cheers,
Daniel


From gabriele.paoloni at huawei.com  Tue May 24 00:23:08 2016
From: gabriele.paoloni at huawei.com (Gabriele Paoloni)
Date: Tue, 24 May 2016 07:23:08 +0000
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <20160523233918.GA32555@localhost>
References: <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>
 <20160523233918.GA32555@localhost>
Message-ID: <EE11001F9E5DDD47B7634E2F8A612F2E1EDB438E@lhreml503-mbs>

Hi Bjorn

> -----Original Message-----
> From: Bjorn Helgaas [mailto:helgaas at kernel.org]
> Sent: 24 May 2016 00:39
> To: Gabriele Paoloni
> Cc: Lorenzo Pieralisi; Ard Biesheuvel; Jon Masters; Tomasz Nowicki;
> arnd at arndb.de; will.deacon at arm.com; catalin.marinas at arm.com;
> rafael at kernel.org; hanjun.guo at linaro.org; okaya at codeaurora.org;
> jchandra at broadcom.com; linaro-acpi at lists.linaro.org; linux-
> pci at vger.kernel.org; dhdang at apm.com; Liviu.Dudau at arm.com;
> ddaney at caviumnetworks.com; jeremy.linton at arm.com; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org;
> robert.richter at caviumnetworks.com; Suravee.Suthikulpanit at amd.com;
> msalter at redhat.com; Wangyijing; mw at semihalf.com;
> andrea.gallo at linaro.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI host
> controller
> 
> On Mon, May 23, 2016 at 03:16:01PM +0000, Gabriele Paoloni wrote:
> > Hi Lorenzo
> >
> > > -----Original Message-----
> > > From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
> > > Sent: 23 May 2016 11:57
> > > To: Ard Biesheuvel
> > > Cc: Gabriele Paoloni; Jon Masters; Tomasz Nowicki;
> helgaas at kernel.org;
> > > arnd at arndb.de; will.deacon at arm.com; catalin.marinas at arm.com;
> > > rafael at kernel.org; hanjun.guo at linaro.org; okaya at codeaurora.org;
> > > jchandra at broadcom.com; linaro-acpi at lists.linaro.org; linux-
> > > pci at vger.kernel.org; dhdang at apm.com; Liviu.Dudau at arm.com;
> > > ddaney at caviumnetworks.com; jeremy.linton at arm.com; linux-
> > > kernel at vger.kernel.org; linux-acpi at vger.kernel.org;
> > > robert.richter at caviumnetworks.com; Suravee.Suthikulpanit at amd.com;
> > > msalter at redhat.com; Wangyijing; mw at semihalf.com;
> > > andrea.gallo at linaro.org; linux-arm-kernel at lists.infradead.org
> > > Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI
> host
> > > controller
> > >
> > > On Fri, May 20, 2016 at 11:14:03AM +0200, Ard Biesheuvel wrote:
> > > > On 20 May 2016 at 10:40, Gabriele Paoloni
> > > <gabriele.paoloni at huawei.com> wrote:
> > > > > Hi Ard
> > > > >
> > > > >> -----Original Message-----
> > > > >> From: Ard Biesheuvel [mailto:ard.biesheuvel at linaro.org]
> > > > [...]
> > > > >>
> > > > >> Is the PCIe root complex so special that you cannot simply
> > > describe an
> > > > >> implementation that is not PNP0408 compatible as something
> else,
> > > under
> > > > >> its own unique HID? If everybody is onboard with using ACPI,
> how
> > > is
> > > > >> this any different from describing other parts of the platform
> > > > >> topology? Even if the SBSA mandates generic PCI, they already
> > > deviated
> > > > >> from that when they built the hardware, so pretending that it
> is a
> > > > >> PNP0408 with quirks really does not buy us anything.
> > > > >
> > > > > From my understanding we want to avoid this as this would allow
> > > each
> > > > > vendor to come up with his own code and it would be much more
> > > effort
> > > > > for the PCI maintainer to rework the PCI framework to
> accommodate
> > > X86
> > > > > and "all" ARM64 Host Controllers...
> > > > >
> > > > > I guess this approach is too risky and we want to avoid this.
> > > Through
> > > > > standardization we can more easily maintain the code and scale
> it
> > > to
> > > > > multiple SoCs...
> > > > >
> > > > > So this is my understanding; maybe Jon, Tomasz or Lorenzo can
> give
> > > > > a bit more explanation...
> > > > >
> > > >
> > > > OK, so that boils down to recommending to vendors to represent
> known
> > > > non-compliant hardware as compliant, just so that we don't have
> to
> > > > change the code to support additional flavors of ECAM ? It's fine
> to
> > > > be pragmatic, but that sucks.
> > > >
> > > > We keep confusing the x86 case with the ARM case here: for x86,
> they
> > > > needed to deal with broken hardware *after* the fact, and all
> they
> > > > could do is find /some/ distinguishing feature in order to guess
> > > which
> > > > exact hardware they might be running on. For arm64, it is the
> > > opposite
> > > > case. We are currently in a position where we can demand vendors
> to
> > > > comply with the standards they endorsed themselves, and (ab)using
> > > ACPI
> > > > + DMI as a de facto platform description rather than plain ACPI
> makes
> > > > me think the DT crowd were actually right from the beginning. It
> > > > *directly* violates the standardization principle, since it
> requires
> > > a
> > > > priori knowledge inside the OS that a certain 'generic' device
> must
> > > be
> > > > driven in a special way.
> > > >
> > > > So can anyone comment on the feasibility of adding support for
> > > devices
> > > > with vendor specific HIDs (and no generic CIDs) to the current
> ACPI
> > > > ECAM driver in Linux?
> 
> I don't think of ECAM support itself as a "driver".  It's just a
> service available to drivers, similar to OF resource parsing.
> 
> Per PCI Firmware r3.2, sec 4.1.5, "PNP0A03" means a PCI/PCI-X/PCIe
> host bridge.  "PNP0A08" means a PCI-X Mode 2 or PCIe bridge that
> supports extended config space.  It doesn't specify how we access that
> config space, so I think hardware with non-standard ECAM should still
> have PNP0A03 and PNP0A08 in _CID or _HID.
> 
> "ECAM" as used in the specs (PCIe r3.0, sec 7.2.2, and PCI Firmware
> r3.2, sec 4.1) means:
> 
>   (a) a memory-mapped model for config space access, and
>   (b) a specific mapping of address bits to bus/device/function/
>       register
> 
> MCFG and _CBA assume both (a) and (b), so I think a device with
> non-standard ECAM mappings should not be described in MCFG or _CBA.
> 
> If a bridge has ECAM with non-standard mappings, I think either a
> vendor-specific _HID or a device-specific method, e.g., _DSM, could
> communicate that.
> 
> Jon, I agree that we should avoid describing non-standardized hardware
> in Linux-specific ways.  Is there a mechanism in use already?  How
> does Windows handle this?  DMI is a poor long-term solution because it
> requires ongoing maintenance for new platforms, but I think it's OK
> for getting started with platforms already shipping.
> 
> A _DSM has the advantage that once it is defined and supported, OEMs
> can ship new platforms without requiring a new quirk or a new _HID to
> be added to a driver.
> 
> There would still be the problem of config access before the namespace
> is available, i.e., the MCFG use case.  I don't know how important
> that is.  Defining an MCFG extension seems like the most obvious
> solution.
> 
> If we only expect a few non-standard devices, maybe it's enough to
> have DMI quirks to statically set up ECAM and just live with the
> inconvenience of requiring a kernel change for every new non-standard
> device.
> 
> > > Host bridges in ACPI are handled through PNP0A08/PNP0A03 ids, and
> > > most of the arch specific code is handled in the respective arch
> > > directories (X86 and IA64, even though IA64 does not rely on
> ECAM/MCFG
> > > for
> > > PCI ops), it is not a driver per-se, PNP0A08/PNP0A03 are detected
> > > through
> > > ACPI scan handlers and the respective arch code (ie
> pci_acpi_scan_root)
> > > sets-up resources AND config space on an arch specific basis.
> > >
> > > X86 deals with that with code in arch/x86 that sets-up the
> pci_raw_ops
> > > on a platform specific basis (and it is not nice, but it works
> because
> > > as you all know the number of platforms in X86 world is contained).
> > >
> > > Will this happen for ARM64 in arch/arm64 based on vendor specific
> > > HIDs ?
> > >
> > > No.
> > >
> > > So given the current state of play (we were requested to move the
> > > arch/arm64 specific ACPI PCI bits to arch/arm64), we would end up
> > > with arch/arm64 code requiring code in /drivers to set-up pci_ops
> > > in a platform specific way, it is horrible, if feasible at all.
> > >
> > > The only way this can be implemented is by pretending that the
> > > ACPI/PCI arch/arm64 implementation is generic code (that's what
> this
> > > series does), move it to /drivers (where it is in this series), and
> > > implement _DSD vendor specific bindings (per HID) to set-up the pci
> > > operations; whether this solution should go upstream, given that it
> > > is just a short-term solution for early platforms bugs, it is
> another
> > > story and my personal answer is no.
> 
> It seems like there should be a way to look for a _DSM before we call
> acpi_pci_root_get_mcfg_addr() to look for _CBA.
> 
> Currently we call acpi_pci_root_get_mcfg_addr() (to read _CBA) from
> the generic acpi_pci_root_add(), but the result (root->mcfg_addr) is
> only used in x86-specific code.  I think it would be nicer if the
> lookup and the use were together.  Then it would be easier to override
> it because the mapping assumptions would all be in one place.
> 
> > I think it shouldn't be too bad to move quirk handling mechanism to
> > arch/arm64. Effectively we would not move platform specific code into
> > arch/arm64 but just the mechanism checking if there is any quirk that
> > is defined.
> >
> > i.e.:
> >
> > extern struct pci_cfg_fixup __start_acpi_mcfg_fixups[];
> > extern struct pci_cfg_fixup __end_acpi_mcfg_fixups[];
> >
> > static struct pci_ecam_ops *pci_acpi_get_ops(struct acpi_pci_root
> *root)
> > {
> >         int bus_num = root->secondary.start;
> >         int domain = root->segment;
> >         struct pci_cfg_fixup *f;
> >
> >         /*
> >          * Match against platform specific quirks and return
> corresponding
> >          * CAM ops.
> >          *
> >          * First match against PCI topology <domain:bus> then use DMI
> or
> >          * custom match handler.
> >          */
> >         for (f = __start_acpi_mcfg_fixups; f <
> __end_acpi_mcfg_fixups; f++) {
> >                 if ((f->domain == domain || f->domain ==
> PCI_MCFG_DOMAIN_ANY) &&
> >                     (f->bus_num == bus_num || f->bus_num ==
> PCI_MCFG_BUS_ANY) &&
> >                     (f->system ? dmi_check_system(f->system) : 1) &&
> >                     (f->match ? f->match(f, root) : 1))
> >                         return f->ops;
> >         }
> >         /* No quirks, use ECAM */
> >         return &pci_generic_ecam_ops;
> > }
> >
> > Such quirks will be defined anyway in drivers/pci/host/ in the vendor
> > specific quirk implementations.
> >
> > e.g. in HiSilicon case we would have
> >
> > DECLARE_ACPI_MCFG_FIXUP(NULL, hisi_pcie_match, &hisi_pcie_ecam_ops,
> > 			PCI_MCFG_DOMAIN_ANY, PCI_MCFG_BUS_ANY);
> >
> > in "drivers/pci/host/pcie-hisi-acpi.c "
> >
> > Thanks
> >
> > Gab
> 
> Sorry Gab, I guess I was really responding to earlier messages :)
> 
> I don't really have much to say here, except that it doesn't seem
> right to have an MCFG that describes a non-standard ECAM mapping.

The ACPI table that this mechanism relies upon is the one discussed
in:
https://lkml.org/lkml/2016/3/9/91

As you can see MCFG describes ECAM mappings, but we have a motherboard
reserved resource outside the MCFG:
Device (RES0)
{
	Name (_HID, "HISI0081") // HiSi PCIe RC config base address
	Name (_CID, "PNP0C02") // Motherboard reserved resource
	Name (_CRS, ResourceTemplate (){
	Memory32Fixed (ReadWrite, 0xb0080000 , 0x10000)
	})
}

This allows us to retrieve the address we need for accessing
the config space on the RC (that is non-ECAM).

I was thinking that such mechanism could fit different vendors
and allow them define their own quirks without spoiling the 
official and standard MCFG; also from the thread discussion
you seemed quite ok with such solution...?

> I suppose there's already firmware in the field that does that,
> though?

We have "experimental" firmware that is based on the ACPI table
described above, however it is not widely distributed and, obviously,
it is not supported by Linux mainline (so we have room to rework
if we decide that another solution is more appropriate)

Thanks and Regards

Gab

> 
> Bjorn


From tomeu.vizoso at collabora.com  Tue May 24 00:26:01 2016
From: tomeu.vizoso at collabora.com (Tomeu Vizoso)
Date: Tue, 24 May 2016 09:26:01 +0200
Subject: [PATCH] drm/rockchip: Return -EBUSY if there's already a pending flip
 event v4
Message-ID: <1464074761-5194-1-git-send-email-tomeu.vizoso@collabora.com>

As per the docs, atomic_commit should return -EBUSY "if an asycnhronous
updated is requested and there is an earlier updated pending".

v2: Use the status of the workqueue instead of vop->event, and don't add
a superfluous wait on the workqueue.

v3: Drop work_busy, as there's a sizeable delay when the worker
finishes, which introduces a race in which the client has already
received the last flip event but the next page flip ioctl will still
return -EBUSY because work_busy returns outdated information.

v4: Hold dev->event_lock while checking the VOP's event field as
suggested by Daniel Stone.

v5: Only block if there's outstanding work if it's a blocking call.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  1 +
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 25 ++++++++++++++++++++++---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  6 ++++++
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 56f43a364c7f..0b46617decd9 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -76,6 +76,7 @@ void rockchip_drm_atomic_work(struct work_struct *work);
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
 				 const struct rockchip_crtc_funcs *crtc_funcs);
 void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
+bool rockchip_drm_crtc_has_pending_event(struct drm_crtc *crtc);
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
 				   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 755cfdba61cd..e9531353b8d2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -279,15 +279,34 @@ int rockchip_drm_atomic_commit(struct drm_device *dev,
 {
 	struct rockchip_drm_private *private = dev->dev_private;
 	struct rockchip_atomic_commit *commit = &private->commit;
-	int ret;
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned long flags;
+	int i, ret;
+
+	if (nonblock) {
+		for_each_crtc_in_state(state, crtc, crtc_state, i) {
+			spin_lock_irqsave(&dev->event_lock, flags);
+
+			if (crtc->state->event ||
+			    rockchip_drm_crtc_has_pending_event(crtc)) {
+				spin_unlock_irqrestore(&dev->event_lock, flags);
+				return -EBUSY;
+			}
+
+			spin_unlock_irqrestore(&dev->event_lock, flags);
+		}
+	}
 
 	ret = drm_atomic_helper_prepare_planes(dev, state);
 	if (ret)
 		return ret;
 
-	/* serialize outstanding nonblocking commits */
 	mutex_lock(&commit->lock);
-	flush_work(&commit->work);
+
+	/* serialize outstanding nonblocking commits */
+	if (!nonblock)
+		flush_work(&commit->work);
 
 	drm_atomic_helper_swap_state(dev, state);
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 1c4d5b5a70a2..3f980f52c640 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -836,6 +836,12 @@ static const struct drm_plane_funcs vop_plane_funcs = {
 	.atomic_destroy_state = vop_atomic_plane_destroy_state,
 };
 
+bool rockchip_drm_crtc_has_pending_event(struct drm_crtc *crtc)
+{
+	assert_spin_locked(&crtc->dev->event_lock);
+	return to_vop(crtc)->event;
+}
+
 static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
 {
 	struct vop *vop = to_vop(crtc);
-- 
2.5.5



From tomeu.vizoso at collabora.com  Tue May 24 00:27:37 2016
From: tomeu.vizoso at collabora.com (Tomeu Vizoso)
Date: Tue, 24 May 2016 09:27:37 +0200
Subject: [PATCH] drm/rockchip: Return -EBUSY if there's already a pending flip
 event v5
In-Reply-To: <1464074761-5194-1-git-send-email-tomeu.vizoso@collabora.com>
References: <1464074761-5194-1-git-send-email-tomeu.vizoso@collabora.com>
Message-ID: <1464074857-5515-1-git-send-email-tomeu.vizoso@collabora.com>

As per the docs, atomic_commit should return -EBUSY "if an asycnhronous
updated is requested and there is an earlier updated pending".

v2: Use the status of the workqueue instead of vop->event, and don't add
a superfluous wait on the workqueue.

v3: Drop work_busy, as there's a sizeable delay when the worker
finishes, which introduces a race in which the client has already
received the last flip event but the next page flip ioctl will still
return -EBUSY because work_busy returns outdated information.

v4: Hold dev->event_lock while checking the VOP's event field as
suggested by Daniel Stone.

v5: Only block if there's outstanding work if it's a blocking call.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  1 +
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 25 ++++++++++++++++++++++---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  6 ++++++
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 56f43a364c7f..0b46617decd9 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -76,6 +76,7 @@ void rockchip_drm_atomic_work(struct work_struct *work);
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
 				 const struct rockchip_crtc_funcs *crtc_funcs);
 void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
+bool rockchip_drm_crtc_has_pending_event(struct drm_crtc *crtc);
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
 				   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 755cfdba61cd..e9531353b8d2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -279,15 +279,34 @@ int rockchip_drm_atomic_commit(struct drm_device *dev,
 {
 	struct rockchip_drm_private *private = dev->dev_private;
 	struct rockchip_atomic_commit *commit = &private->commit;
-	int ret;
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned long flags;
+	int i, ret;
+
+	if (nonblock) {
+		for_each_crtc_in_state(state, crtc, crtc_state, i) {
+			spin_lock_irqsave(&dev->event_lock, flags);
+
+			if (crtc->state->event ||
+			    rockchip_drm_crtc_has_pending_event(crtc)) {
+				spin_unlock_irqrestore(&dev->event_lock, flags);
+				return -EBUSY;
+			}
+
+			spin_unlock_irqrestore(&dev->event_lock, flags);
+		}
+	}
 
 	ret = drm_atomic_helper_prepare_planes(dev, state);
 	if (ret)
 		return ret;
 
-	/* serialize outstanding nonblocking commits */
 	mutex_lock(&commit->lock);
-	flush_work(&commit->work);
+
+	/* serialize outstanding nonblocking commits */
+	if (!nonblock)
+		flush_work(&commit->work);
 
 	drm_atomic_helper_swap_state(dev, state);
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 1c4d5b5a70a2..3f980f52c640 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -836,6 +836,12 @@ static const struct drm_plane_funcs vop_plane_funcs = {
 	.atomic_destroy_state = vop_atomic_plane_destroy_state,
 };
 
+bool rockchip_drm_crtc_has_pending_event(struct drm_crtc *crtc)
+{
+	assert_spin_locked(&crtc->dev->event_lock);
+	return to_vop(crtc)->event;
+}
+
 static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
 {
 	struct vop *vop = to_vop(crtc);
-- 
2.5.5



From khiem.nguyen.xt at rvc.renesas.com  Tue May 24 00:29:28 2016
From: khiem.nguyen.xt at rvc.renesas.com (Khiem Nguyen)
Date: Tue, 24 May 2016 14:29:28 +0700
Subject: [PATCH v2 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <CAMuHMdV+atFKJjxcH7RkBCdabsBqk5Y3TTHCPN+sprDaM1xj_w@mail.gmail.com>
References: <1463966906-15129-1-git-send-email-horms+renesas@verge.net.au>
 <1463966906-15129-2-git-send-email-horms+renesas@verge.net.au>
 <CAMuHMdXsu=O13rLysob1Xp+5vWcp7gq6byCffR-6hGc+W-837A@mail.gmail.com>
 <5742B66C.7080102@rvc.renesas.com>
 <CAMuHMdV+atFKJjxcH7RkBCdabsBqk5Y3TTHCPN+sprDaM1xj_w@mail.gmail.com>
Message-ID: <574402D8.6030400@rvc.renesas.com>

Hi Geert,

On 5/24/2016 1:35 PM, Geert Uytterhoeven wrote:
> Hi Khiem,
>
> On Mon, May 23, 2016 at 9:51 AM, Khiem Nguyen
> <khiem.nguyen.xt at rvc.renesas.com> wrote:
>> Using 1.0 will open Suspend-to-RAM support if secure firmware supports that
>> feature.
>> However, we might need additional work in drivers to support suspend/resume
>> handlers.
>> So, I suggest that we keep using 0.2 until Suspend-to-RAM feature is
>> confirmed in r8a7795/r8a7796.
>
> Note that we do have suspend/resume support on R-Car Gen2, albeit some
> drivers may lack code to save/restore state when their devices are powered
> down, as R-Car Gen2 doesn't have power domains for devices.
>
> So I'd expect everything to work fine, as long as no R-Car Gen3-specific
> drivers or devices residing in multimedia power domains are involved.

In my test environment using latest integration branch in 
renesas-drivers (v4.6), it failed to resume due to operation inside 
rcar_du_pm_resume().
Probably, it should be fixed soon.

FYI, your secure firmware will have Suspend-to-RAM support if below log 
is output.
    psci: PSCIv1.0 detected in firmware.

Thanks.

Best regards,
KHIEM Nguyen


From daniel at fooishbar.org  Tue May 24 00:34:50 2016
From: daniel at fooishbar.org (Daniel Stone)
Date: Tue, 24 May 2016 09:34:50 +0200
Subject: [PATCH] drm/rockchip: Return -EBUSY if there's already a pending
 flip event v5
In-Reply-To: <1464074857-5515-1-git-send-email-tomeu.vizoso@collabora.com>
References: <1464074761-5194-1-git-send-email-tomeu.vizoso@collabora.com>
 <1464074857-5515-1-git-send-email-tomeu.vizoso@collabora.com>
Message-ID: <CAPj87rPfakpstxmK3rodunVp2aX-gkLqoqQJ+gfoazaH0ej29g@mail.gmail.com>

On 24 May 2016 at 09:27, Tomeu Vizoso <tomeu.vizoso at collabora.com> wrote:
> As per the docs, atomic_commit should return -EBUSY "if an asycnhronous
> updated is requested and there is an earlier updated pending".
>
> v2: Use the status of the workqueue instead of vop->event, and don't add
> a superfluous wait on the workqueue.
>
> v3: Drop work_busy, as there's a sizeable delay when the worker
> finishes, which introduces a race in which the client has already
> received the last flip event but the next page flip ioctl will still
> return -EBUSY because work_busy returns outdated information.
>
> v4: Hold dev->event_lock while checking the VOP's event field as
> suggested by Daniel Stone.
>
> v5: Only block if there's outstanding work if it's a blocking call.
>
> Signed-off-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>

Reviewed-by: Daniel Stone <daniels at collabora.com>

Cheers,
Daniel


From geert at linux-m68k.org  Tue May 24 00:37:04 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Tue, 24 May 2016 09:37:04 +0200
Subject: [PATCH v2 11/23] ARM: dts: armadillo800eva: Fix W=1 dtc warnings
In-Reply-To: <20160524003356.GB2477@verge.net.au>
References: <1463728214-13838-1-git-send-email-geert+renesas@glider.be>
 <1463728214-13838-12-git-send-email-geert+renesas@glider.be>
 <e0a1fbc1-ac95-2c79-65ed-d0328679bb8a@cogentembedded.com>
 <CAMuHMdXPhMToHhZggdKo=i65nS_mQT1o44YBd_Lz-B2Td3Jm9Q@mail.gmail.com>
 <20160524001309.GA2477@verge.net.au>
 <20160524003356.GB2477@verge.net.au>
Message-ID: <CAMuHMdW8a3jOibXmMxv34RF+cZ7aE5x_fRzAQW4qVb_RB=6sCw@mail.gmail.com>

Hi Simon,

On Tue, May 24, 2016 at 2:33 AM, Simon Horman <horms at verge.net.au> wrote:
>> > >> --- a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
>> > >> +++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts

> I have queued this up with the above hunk changed to the following.
> Please check the resulting patch and let me know if I've messed things up
> somehow.
>
> @@ -127,7 +127,7 @@
>                 };
>         };
>
> -       i2c2: i2c at 2 {
> +       i2c2: i2c-2 {

Thanks, looks fine.

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 arnaud.pouliquen at st.com  Tue May 24 00:40:26 2016
From: arnaud.pouliquen at st.com (Arnaud Pouliquen)
Date: Tue, 24 May 2016 09:40:26 +0200
Subject: [PATCH 00/11] Clock improvement for video playback
In-Reply-To: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <5744056A.7020606@st.com>

Hello Gabriel,

Tested with success on stih407 family platforms

Reviewed-by: Arnaud Pouliquen <arnaud.pouliquen at st.com>
Tested-by: Arnaud Pouliquen <arnaud.pouliquen at st.com>

Regards
Arnaud

On 05/18/2016 10:41 AM, Gabriel Fernandez wrote:
> This serie allows to increase video resolutions and make audio
> adjustment during a video playback.
> 
> Gabriel Fernandez (11):
>   drivers: clk: st: Add fs660c32 synthesizer algorithm
>   drivers: clk: st: Add clock propagation for audio clocks
>   drivers: clk: st: Handle clkgenD2 clk synchronous mode
>   ARM: DT: STiH407: Add compatibility string on clkgend0 for audio
>     clocks
>   ARM: DT: STiH410: Add compatibility string on clkgend0 for audio
>     clocks
>   ARM: DT: STiH418: Add compatibility string on clkgend0 for audio
>     clocks
>   ARM: DT: STiH407: Enable synchronous clock mode on clkgend2
>   ARM: DT: STiH410: Enable synchronous clock mode on clkgend2
>   ARM: DT: STiH418: Enable synchronous clock mode on clkgend2
>   ARM: DT: STi: STiH407: clock configuration to address 720p and 1080p
>   ARM: DT: STi: STiH410: clock configuration to address 720p and 1080p
> 
>  .../devicetree/bindings/clock/st/st,flexgen.txt    |   3 +
>  arch/arm/boot/dts/stih407-clock.dtsi               |   4 +-
>  arch/arm/boot/dts/stih407.dtsi                     |  16 ++-
>  arch/arm/boot/dts/stih410-clock.dtsi               |   4 +-
>  arch/arm/boot/dts/stih410.dtsi                     |  16 ++-
>  arch/arm/boot/dts/stih418-clock.dtsi               |   4 +-
>  drivers/clk/st/clk-flexgen.c                       |  61 +++++++-
>  drivers/clk/st/clkgen-fsyn.c                       | 159 +++++++++++++++------
>  8 files changed, 211 insertions(+), 56 deletions(-)
> 


From mcoquelin.stm32 at gmail.com  Tue May 24 00:59:41 2016
From: mcoquelin.stm32 at gmail.com (Maxime Coquelin)
Date: Tue, 24 May 2016 09:59:41 +0200
Subject: [PATCH] hwrng: stm32 - fix build warning
In-Reply-To: <6297051.TAxtzW5OIB@wuerfel>
References: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>
 <6297051.TAxtzW5OIB@wuerfel>
Message-ID: <CALszF6AxXY0LK5fToFg3095+gz6xcZz8KHaYqc=o39vjpBYDmA@mail.gmail.com>

2016-05-23 22:35 GMT+02:00 Arnd Bergmann <arnd at arndb.de>:
> On Monday, May 23, 2016 6:14:08 PM CEST Sudip Mukherjee wrote:
>> We have been getting build warning about:
>> drivers/char/hw_random/stm32-rng.c: In function 'stm32_rng_read':
>> drivers/char/hw_random/stm32-rng.c:82:19: warning: 'sr' may be used
>>                                       uninitialized in this function
>>
>> On checking the code it turns out that sr can never be used
>> uninitialized as sr is getting initialized in the while loop and while
>> loop will always execute as the minimum value of max can be 32.
>> So just initialize sr to 0 while declaring it to silence the compiler.
>>
>> Signed-off-by: Sudip Mukherjee <sudip.mukherjee at codethink.co.uk>
>> ---
>
> I notice that you are using a really old compiler. While this warning
> seems to be valid in the sense that the compiler should figure out that
> the variable might be used uninitialized, please update your toolchain
> before reporting other such problems, as gcc-4.6 had a lot more false
> positives that newer ones (5.x or 6.x) have.
>
>>
>> build log at:
>> https://travis-ci.org/sudipm-mukherjee/parport/jobs/132180906
>>
>>  drivers/char/hw_random/stm32-rng.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
>> index 92a8106..0533370 100644
>> --- a/drivers/char/hw_random/stm32-rng.c
>> +++ b/drivers/char/hw_random/stm32-rng.c
>> @@ -52,7 +52,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
>>  {
>>       struct stm32_rng_private *priv =
>>           container_of(rng, struct stm32_rng_private, rng);
>> -     u32 sr;
>> +     u32 sr = 0;
>>       int retval = 0;
>>
>>       pm_runtime_get_sync((struct device *) priv->rng.priv);
>
> Does this work as well?
>
> diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
> index 92a810648bd0..5c836b0afa40 100644
> --- a/drivers/char/hw_random/stm32-rng.c
> +++ b/drivers/char/hw_random/stm32-rng.c
> @@ -79,7 +79,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
>                 max -= sizeof(u32);
>         }
>
> -       if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
> +       if (WARN_ONCE(retval > 0 && (sr & (RNG_SR_SEIS | RNG_SR_CEIS)),
>                       "bad RNG status - %x\n", sr))
>                 writel_relaxed(0, priv->base + RNG_SR);
>
> I think it would be nicer to not add a bogus initialization.
Hmm, no sure this nicer.
The while loop can break before retval is incremented when sr value is
not expected (sr != RNG_SR_DRDY).
In that case, we certainly want to print sr value.

Maybe the better way is just to initialize sr with status register content?

diff --git a/drivers/char/hw_random/stm32-rng.c
b/drivers/char/hw_random/stm32-rng.c
index 92a810648bd0..07a6659d0fe6 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -57,8 +57,8 @@ static int stm32_rng_read(struct hwrng *rng, void
*data, size_t max, bool wait)

        pm_runtime_get_sync((struct device *) priv->rng.priv);

+       sr = readl_relaxed(priv->base + RNG_SR);
        while (max > sizeof(u32)) {
-               sr = readl_relaxed(priv->base + RNG_SR);
                if (!sr && wait) {
                        unsigned int timeout = RNG_TIMEOUT;

@@ -77,6 +77,8 @@ static int stm32_rng_read(struct hwrng *rng, void
*data, size_t max, bool wait)
                retval += sizeof(u32);
                data += sizeof(u32);
                max -= sizeof(u32);
+
+               sr = readl_relaxed(priv->base + RNG_SR);
        }

        if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),


Regards,
Maxime


From carlo at caione.org  Tue May 24 01:03:28 2016
From: carlo at caione.org (Carlo Caione)
Date: Tue, 24 May 2016 10:03:28 +0200
Subject: [PATCH v3 4/4] documentation: Add secure monitor binding
 documentation
In-Reply-To: <20160523171159.GH4976@leverpostej>
References: <1464021024-29380-1-git-send-email-carlo@caione.org>
 <1464021024-29380-5-git-send-email-carlo@caione.org>
 <20160523163815.GE4976@leverpostej>
 <20160523165931.GA31299@mephisto>
 <20160523171159.GH4976@leverpostej>
Message-ID: <20160524080328.GA18935@mephisto>

On 23/05/16 18:11, Mark Rutland wrote:
> On Mon, May 23, 2016 at 06:59:31PM +0200, Carlo Caione wrote:
> > On 23/05/16 17:38, Mark Rutland wrote:
> > > > +Required properties for the secure monitor node:
> > > > +- compatible: Should be "amlogic,meson-sm"
> > > > +- amlogic,sm-cmd-input-base: SMC32 function identifier to read the physical
> > > > +                             address of the input buffer
> > > > +- amlogic,sm-cmd-output-base: SMC32 function identifier to read the physical
> > > > +                              address of the output buffer
> > > 
> > > Do the IDs for these actually differ per board?
> > 
> > I expect these to differ per SoC (GXBB in this case), not per board. The
> > driver is generic enough to be (hopefully) used for several SoCs just
> > changing the related header file that defines the SCM commands.
> > 
> > > Are some functions simply not implemented on some boards?
> > 
> > I don't think this is possible.
> 
> Given that, I think it may be better to just have a
> "amlogic,meson-gxbb-sm" compatible string, and derive the set of
> functions and associated IDs from that.

I can reference a specific SMC function using an index in the DT, the
same index for all the SoCs. The index is then associated to the actual
SoC-specific command ID in the driver according to the compatible string
used for the secure-monitor node.

Something like:

  // Not SoC-specific
  #include <dt-bindings/firmware/meson.h>

  sm: sm {
  	compatible = "amlogic,meson-gxbb-sm";
  };
  
  efuse {
  	compatible = "amlogic,meson-gxbb-efuse";
  	secure-monitor = <&sm>;
  	amlogic,cmd-read-efuse = <READ_EFUSE>;
  	...
  };

Is this any better?

At this point I wonder if it makes sense having the driver-specific
function IDs (like 'amlogic,cmd-read-efuse' above) defined in the DT.

> That is, unless you know that future revisions have functions with the
> exact same semantics but differing IDs.

This is most probably the case.

Also the driver exports really generic functions to access the
secure-monitor on purpose, so that the driver using it can define the
semantic of the SMC call. I really would like to avoid fixing the
semantic in the SM driver itself since we will end up with: different
semantics for each SMC call and for each SoC.

> Regardless, it would make sense to have a GXBB-specific compatible
> string prepended to the list. That way in the future we can handle
> anything specific to the GXBB variant of the secure monitor if
> necessary.

Agree on this.

Cheers,

-- 
Carlo Caione


From carlo at caione.org  Tue May 24 01:08:03 2016
From: carlo at caione.org (Carlo Caione)
Date: Tue, 24 May 2016 10:08:03 +0200
Subject: [PATCH v3 1/4] firmware: Amlogic: Add secure monitor driver
In-Reply-To: <m2posco5k2.fsf@baylibre.com>
References: <1464021024-29380-1-git-send-email-carlo@caione.org>
 <1464021024-29380-2-git-send-email-carlo@caione.org>
 <m2posco5k2.fsf@baylibre.com>
Message-ID: <20160524080803.GB18935@mephisto>

On 23/05/16 13:58, Kevin Hilman wrote:

[...]
> > +	if (of_property_read_u32(np, "amlogic,sm-cmd-input-base", &cmd_in))
> > +		return -EINVAL;
> > +
> > +	if (of_property_read_u32(np, "amlogic,sm-cmd-output-base", &cmd_out))
> > +		return -EINVAL;
> > +
> > +	sm_phy_in_base = meson_sm_call(cmd_in, 0, 0, 0, 0, 0);
> 
> Should there be any error checking here?  Do we have any info on the
> return values here in case of error, or in case of missing firmware,
> etc.

We do not have any info on that but I can assume 0 is considered an
error as for other SMC calls. Fix in v4.

-- 
Carlo Caione


From u.kleine-koenig at pengutronix.de  Tue May 24 01:20:40 2016
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Tue, 24 May 2016 10:20:40 +0200
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <5743E206.2050602@ti.com>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
 <1463648641-6931-2-git-send-email-vigneshr@ti.com>
 <20160522102606.GB23704@pengutronix.de> <5742E710.9@ti.com>
 <20160523131808.GN23704@pengutronix.de> <5743E206.2050602@ti.com>
Message-ID: <20160524082040.GR23704@pengutronix.de>

Hello,

On Tue, May 24, 2016 at 10:39:26AM +0530, Vignesh R wrote:
> On 05/23/2016 06:48 PM, Uwe Kleine-K?nig wrote:
> > On Mon, May 23, 2016 at 04:48:40PM +0530, R, Vignesh wrote:
> >> On 5/22/2016 3:56 PM, Uwe Kleine-K?nig wrote:
> >>> On Thu, May 19, 2016 at 02:34:00PM +0530, Vignesh R wrote:
> >>>> +- rotary-encoder,absolute-encoder: support encoders where GPIO lines
> >>>> +  reflect the actual position of the rotary encoder dial. For example,
> >>>> +  if dial points to 9, then four GPIO lines read HLLH(1001b = 9).
> >>>> +  In this case, rotary-encoder,steps-per-period needed not be defined.
> >>>
> >>> IMHO this is wrong, I'd formalize this device as:
> >>>
> >>> 	{
> >>> 		compatible = "rotary-encoder";
> >>> 		gpios = <&gpio 19 1>, <&gpio 20 0>, <...>, <...>;
> >>> 		rotary-encoder,encoding = "binary";
> >>> 		rotary-encoder,steps = <16>;
> >>> 		rotary-encoder,steps-per-period = <16>;
> >>
> >> The above bindings essential means quarter_period device. I would not
> >> like to bother with all the logic in rotary_encoder_quarter_period_irq()
> >> when we can know encoder->pos by directly reading state of gpio lines.
> > 
> > OK, we have code that is more complex than it needs to be for your
> > device. But your device is a special case of the supported devices, so
> > I'd say don't bother that there is more logic in the driver than you
> > need and be lucky.
> 
> More complexity is just a overhead. Since, encoder can be turned at a
> rate faster than handling of IRQs (rotary_encoder_quarter_period_irq()
> is threaded IRQ hence, priority is not close to real time), some states

This problem isn't unique to your hardware. An "ordinary" encoder with
just two GPIOs and more than one period can be rotated faster than
1/irq_latency, too. There are two things that can be done:

 - undo the conversion to threaded irqs; or
 - read out the gpios in the fast handler and only delay decoding and
   reporting of the event

Both approaches have their disadvantages.

> can be missed. rotary_encoder_quarter_period_irq() is not robust in this
> case, reading gpios directly is more suitable option. I see similar
> views expressed in previously[1]
> 
> [1]http://lists.infradead.org/pipermail/linux-arm-kernel/2015-December/391196.html

IMHO the right thing to do is to improve
rotary_encoder_quarter_period_irq (and also the other handlers for full
and half period mode) to make use of additional GPIOs. This way all
types of devices benefit and more code is shared.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From heiko at sntech.de  Tue May 24 01:28:42 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue, 24 May 2016 10:28:42 +0200
Subject: [PATCH] drm/rockchip: Return -EBUSY if there's already a pending
 flip event v5
In-Reply-To: <1464074857-5515-1-git-send-email-tomeu.vizoso@collabora.com>
References: <1464074761-5194-1-git-send-email-tomeu.vizoso@collabora.com>
 <1464074857-5515-1-git-send-email-tomeu.vizoso@collabora.com>
Message-ID: <7363560.k3ytHeYgtM@phil>

Hi Tomeu,

Patch subject: please put the version into the brackets, so [PATCH v5] as it 
shouldn't be part of the commit log.

Am Dienstag, 24. Mai 2016, 09:27:37 schrieb Tomeu Vizoso:
> As per the docs, atomic_commit should return -EBUSY "if an asycnhronous
> updated is requested and there is an earlier updated pending".

> v2: Use the status of the workqueue instead of vop->event, and don't add
> a superfluous wait on the workqueue.
> 
> v3: Drop work_busy, as there's a sizeable delay when the worker
> finishes, which introduces a race in which the client has already
> received the last flip event but the next page flip ioctl will still
> return -EBUSY because work_busy returns outdated information.
> 
> v4: Hold dev->event_lock while checking the VOP's event field as
> suggested by Daniel Stone.
> 
> v5: Only block if there's outstanding work if it's a blocking call.

similarly, please put the changelog below the "---" and above the diffstat.


> Signed-off-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>
> ---

aka here.

>  drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  1 +
>  drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 25
> ++++++++++++++++++++++--- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 
> 6 ++++++
>  3 files changed, 29 insertions(+), 3 deletions(-)

Heiko


From daniel at ffwll.ch  Tue May 24 01:30:50 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Tue, 24 May 2016 10:30:50 +0200
Subject: [PATCH] drm/rockchip: Return -EBUSY if there's already a pending
 flip event v5
In-Reply-To: <7363560.k3ytHeYgtM@phil>
References: <1464074761-5194-1-git-send-email-tomeu.vizoso@collabora.com>
 <1464074857-5515-1-git-send-email-tomeu.vizoso@collabora.com>
 <7363560.k3ytHeYgtM@phil>
Message-ID: <20160524083050.GQ27098@phenom.ffwll.local>

On Tue, May 24, 2016 at 10:28:42AM +0200, Heiko Stuebner wrote:
> Hi Tomeu,
> 
> Patch subject: please put the version into the brackets, so [PATCH v5] as it 
> shouldn't be part of the commit log.
> 
> Am Dienstag, 24. Mai 2016, 09:27:37 schrieb Tomeu Vizoso:
> > As per the docs, atomic_commit should return -EBUSY "if an asycnhronous
> > updated is requested and there is an earlier updated pending".
> 
> > v2: Use the status of the workqueue instead of vop->event, and don't add
> > a superfluous wait on the workqueue.
> > 
> > v3: Drop work_busy, as there's a sizeable delay when the worker
> > finishes, which introduces a race in which the client has already
> > received the last flip event but the next page flip ioctl will still
> > return -EBUSY because work_busy returns outdated information.
> > 
> > v4: Hold dev->event_lock while checking the VOP's event field as
> > suggested by Daniel Stone.
> > 
> > v5: Only block if there's outstanding work if it's a blocking call.
> 
> similarly, please put the changelog below the "---" and above the diffstat.

drm culture is to keep it above, since it's kinda useful sometimes when
later on trying to reconstruct wtf was discussed and why a patch was
merged.
-Daniel

> 
> 
> > Signed-off-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>
> > ---
> 
> aka here.
> 
> >  drivers/gpu/drm/rockchip/rockchip_drm_drv.h |  1 +
> >  drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 25
> > ++++++++++++++++++++++--- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 
> > 6 ++++++
> >  3 files changed, 29 insertions(+), 3 deletions(-)
> 
> Heiko
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From arnd at arndb.de  Tue May 24 01:32:34 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 24 May 2016 10:32:34 +0200
Subject: [PATCH] hwrng: stm32 - fix build warning
In-Reply-To: <CALszF6AxXY0LK5fToFg3095+gz6xcZz8KHaYqc=o39vjpBYDmA@mail.gmail.com>
References: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>
 <6297051.TAxtzW5OIB@wuerfel>
 <CALszF6AxXY0LK5fToFg3095+gz6xcZz8KHaYqc=o39vjpBYDmA@mail.gmail.com>
Message-ID: <12548318.auB4PSA3KC@wuerfel>

On Tuesday, May 24, 2016 9:59:41 AM CEST Maxime Coquelin wrote:
> 2016-05-23 22:35 GMT+02:00 Arnd Bergmann <arnd at arndb.de>:
> > On Monday, May 23, 2016 6:14:08 PM CEST Sudip Mukherjee wrote:
> >> diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
> >> index 92a8106..0533370 100644
> >> --- a/drivers/char/hw_random/stm32-rng.c
> >> +++ b/drivers/char/hw_random/stm32-rng.c
> >> @@ -52,7 +52,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
> >>  {
> >>       struct stm32_rng_private *priv =
> >>           container_of(rng, struct stm32_rng_private, rng);
> >> -     u32 sr;
> >> +     u32 sr = 0;
> >>       int retval = 0;
> >>
> >>       pm_runtime_get_sync((struct device *) priv->rng.priv);
> >
> > Does this work as well?
> >
> > diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
> > index 92a810648bd0..5c836b0afa40 100644
> > --- a/drivers/char/hw_random/stm32-rng.c
> > +++ b/drivers/char/hw_random/stm32-rng.c
> > @@ -79,7 +79,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
> >                 max -= sizeof(u32);
> >         }
> >
> > -       if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
> > +       if (WARN_ONCE(retval > 0 && (sr & (RNG_SR_SEIS | RNG_SR_CEIS)),
> >                       "bad RNG status - %x\n", sr))
> >                 writel_relaxed(0, priv->base + RNG_SR);
> >
> > I think it would be nicer to not add a bogus initialization.
> Hmm, no sure this nicer.
> The while loop can break before retval is incremented when sr value is
> not expected (sr != RNG_SR_DRDY).
> In that case, we certainly want to print sr value.

Ah, you are right.

> Maybe the better way is just to initialize sr with status register content?

>        pm_runtime_get_sync((struct device *) priv->rng.priv);
>
>+       sr = readl_relaxed(priv->base + RNG_SR);
>        while (max > sizeof(u32)) {
>-               sr = readl_relaxed(priv->base + RNG_SR);
>                if (!sr && wait) {
>                        unsigned int timeout = RNG_TIMEOUT;


I think that introduces a bug: you really want to read the status
register on each loop iteration.

How about moving the error handling into the loop itself?

	Arnd


diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 92a810648bd0..fceacd809462 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -59,6 +59,10 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 
 	while (max > sizeof(u32)) {
 		sr = readl_relaxed(priv->base + RNG_SR);
+		if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
+			      "bad RNG status - %x\n", sr))
+			writel_relaxed(0, priv->base + RNG_SR);
+
 		if (!sr && wait) {
 			unsigned int timeout = RNG_TIMEOUT;
 
@@ -79,10 +83,6 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 		max -= sizeof(u32);
 	}
 
-	if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
-		      "bad RNG status - %x\n", sr))
-		writel_relaxed(0, priv->base + RNG_SR);
-
 	pm_runtime_mark_last_busy((struct device *) priv->rng.priv);
 	pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv);
 



From linux at armlinux.org.uk  Tue May 24 01:35:19 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Tue, 24 May 2016 09:35:19 +0100
Subject: [PATCH 2/4] ARM: dma-mapping: Constify attrs passed to internal
 functions
In-Reply-To: <1464071290-15948-3-git-send-email-k.kozlowski@samsung.com>
References: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>
 <1464071290-15948-3-git-send-email-k.kozlowski@samsung.com>
Message-ID: <20160524083519.GC19428@n2100.arm.linux.org.uk>

On Tue, May 24, 2016 at 08:28:08AM +0200, Krzysztof Kozlowski wrote:
> Some of the non-exported functions do not modify passed dma_attrs so the
> pointer can point to const data.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

Acked-by: Russell King <rmk+kernel at armlinux.org.uk>

Thanks.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From daniel at ffwll.ch  Tue May 24 01:37:49 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Tue, 24 May 2016 10:37:49 +0200
Subject: [PATCH] drm/rockchip: Return -EBUSY if there's already a pending
 flip event v5
In-Reply-To: <20160524083050.GQ27098@phenom.ffwll.local>
References: <1464074761-5194-1-git-send-email-tomeu.vizoso@collabora.com>
 <1464074857-5515-1-git-send-email-tomeu.vizoso@collabora.com>
 <7363560.k3ytHeYgtM@phil>
 <20160524083050.GQ27098@phenom.ffwll.local>
Message-ID: <20160524083749.GR27098@phenom.ffwll.local>

On Tue, May 24, 2016 at 10:30:50AM +0200, Daniel Vetter wrote:
> On Tue, May 24, 2016 at 10:28:42AM +0200, Heiko Stuebner wrote:
> > Hi Tomeu,
> > 
> > Patch subject: please put the version into the brackets, so [PATCH v5] as it 
> > shouldn't be part of the commit log.
> > 
> > Am Dienstag, 24. Mai 2016, 09:27:37 schrieb Tomeu Vizoso:
> > > As per the docs, atomic_commit should return -EBUSY "if an asycnhronous
> > > updated is requested and there is an earlier updated pending".
> > 
> > > v2: Use the status of the workqueue instead of vop->event, and don't add
> > > a superfluous wait on the workqueue.
> > > 
> > > v3: Drop work_busy, as there's a sizeable delay when the worker
> > > finishes, which introduces a race in which the client has already
> > > received the last flip event but the next page flip ioctl will still
> > > return -EBUSY because work_busy returns outdated information.
> > > 
> > > v4: Hold dev->event_lock while checking the VOP's event field as
> > > suggested by Daniel Stone.
> > > 
> > > v5: Only block if there's outstanding work if it's a blocking call.
> > 
> > similarly, please put the changelog below the "---" and above the diffstat.
> 
> drm culture is to keep it above, since it's kinda useful sometimes when
> later on trying to reconstruct wtf was discussed and why a patch was
> merged.

Maybe needs a bit more context: The only stuff you raised in your review
is tiny style nits of pretty much utter irrelevance. No substantial and
material feedback anywehere, and in my opinion in such a case either fix
up the nits when applying (when you feel really strongly about perfect
patches), or just merge as-is.

But sending out content-less bikesheds like these just adds noise and
helps no-one. I think at least some spelling stuff is the minimal bar (but
then just include your r-b tag), but personally I don't even care about
that so much, as long as it's still legible.

Thanks, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From heiko at sntech.de  Tue May 24 01:41:30 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue, 24 May 2016 10:41:30 +0200
Subject: [PATCH] drm/rockchip: Return -EBUSY if there's already a pending
 flip event v5
In-Reply-To: <20160524083749.GR27098@phenom.ffwll.local>
References: <1464074761-5194-1-git-send-email-tomeu.vizoso@collabora.com>
 <20160524083050.GQ27098@phenom.ffwll.local>
 <20160524083749.GR27098@phenom.ffwll.local>
Message-ID: <1885816.5oayNdNrp7@phil>

Am Dienstag, 24. Mai 2016, 10:37:49 schrieb Daniel Vetter:
> On Tue, May 24, 2016 at 10:30:50AM +0200, Daniel Vetter wrote:
> > On Tue, May 24, 2016 at 10:28:42AM +0200, Heiko Stuebner wrote:
> > > Hi Tomeu,
> > > 
> > > Patch subject: please put the version into the brackets, so [PATCH v5]
> > > as it shouldn't be part of the commit log.
> > > 
> > > Am Dienstag, 24. Mai 2016, 09:27:37 schrieb Tomeu Vizoso:
> > > > As per the docs, atomic_commit should return -EBUSY "if an
> > > > asycnhronous
> > > > updated is requested and there is an earlier updated pending".
> > > > 
> > > > v2: Use the status of the workqueue instead of vop->event, and don't
> > > > add
> > > > a superfluous wait on the workqueue.
> > > > 
> > > > v3: Drop work_busy, as there's a sizeable delay when the worker
> > > > finishes, which introduces a race in which the client has already
> > > > received the last flip event but the next page flip ioctl will still
> > > > return -EBUSY because work_busy returns outdated information.
> > > > 
> > > > v4: Hold dev->event_lock while checking the VOP's event field as
> > > > suggested by Daniel Stone.
> > > > 
> > > > v5: Only block if there's outstanding work if it's a blocking call.
> > > 
> > > similarly, please put the changelog below the "---" and above the
> > > diffstat.> 
> > drm culture is to keep it above, since it's kinda useful sometimes when
> > later on trying to reconstruct wtf was discussed and why a patch was
> > merged.
> 
> Maybe needs a bit more context: The only stuff you raised in your review
> is tiny style nits of pretty much utter irrelevance. No substantial and
> material feedback anywehere, and in my opinion in such a case either fix
> up the nits when applying (when you feel really strongly about perfect
> patches), or just merge as-is.
> 
> But sending out content-less bikesheds like these just adds noise and
> helps no-one. I think at least some spelling stuff is the minimal bar (but
> then just include your r-b tag), but personally I don't even care about
> that so much, as long as it's still legible.

ok, will keep that (both mails) in mind for future stuff.

Heiko


From mcoquelin.stm32 at gmail.com  Tue May 24 01:50:17 2016
From: mcoquelin.stm32 at gmail.com (Maxime Coquelin)
Date: Tue, 24 May 2016 10:50:17 +0200
Subject: [PATCH] hwrng: stm32 - fix build warning
In-Reply-To: <12548318.auB4PSA3KC@wuerfel>
References: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>
 <6297051.TAxtzW5OIB@wuerfel>
 <CALszF6AxXY0LK5fToFg3095+gz6xcZz8KHaYqc=o39vjpBYDmA@mail.gmail.com>
 <12548318.auB4PSA3KC@wuerfel>
Message-ID: <CALszF6BPPA=tezMLhmdC4YFwmH1tGhDxCNDZNwGp1cTDWP7Fmg@mail.gmail.com>

2016-05-24 10:32 GMT+02:00 Arnd Bergmann <arnd at arndb.de>:
> On Tuesday, May 24, 2016 9:59:41 AM CEST Maxime Coquelin wrote:
>> 2016-05-23 22:35 GMT+02:00 Arnd Bergmann <arnd at arndb.de>:
>> > On Monday, May 23, 2016 6:14:08 PM CEST Sudip Mukherjee wrote:
>> >> diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
>> >> index 92a8106..0533370 100644
>> >> --- a/drivers/char/hw_random/stm32-rng.c
>> >> +++ b/drivers/char/hw_random/stm32-rng.c
>> >> @@ -52,7 +52,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
>> >>  {
>> >>       struct stm32_rng_private *priv =
>> >>           container_of(rng, struct stm32_rng_private, rng);
>> >> -     u32 sr;
>> >> +     u32 sr = 0;
>> >>       int retval = 0;
>> >>
>> >>       pm_runtime_get_sync((struct device *) priv->rng.priv);
>> >
>> > Does this work as well?
>> >
>> > diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
>> > index 92a810648bd0..5c836b0afa40 100644
>> > --- a/drivers/char/hw_random/stm32-rng.c
>> > +++ b/drivers/char/hw_random/stm32-rng.c
>> > @@ -79,7 +79,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
>> >                 max -= sizeof(u32);
>> >         }
>> >
>> > -       if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
>> > +       if (WARN_ONCE(retval > 0 && (sr & (RNG_SR_SEIS | RNG_SR_CEIS)),
>> >                       "bad RNG status - %x\n", sr))
>> >                 writel_relaxed(0, priv->base + RNG_SR);
>> >
>> > I think it would be nicer to not add a bogus initialization.
>> Hmm, no sure this nicer.
>> The while loop can break before retval is incremented when sr value is
>> not expected (sr != RNG_SR_DRDY).
>> In that case, we certainly want to print sr value.
>
> Ah, you are right.
>
>> Maybe the better way is just to initialize sr with status register content?
>
>>        pm_runtime_get_sync((struct device *) priv->rng.priv);
>>
>>+       sr = readl_relaxed(priv->base + RNG_SR);
>>        while (max > sizeof(u32)) {
>>-               sr = readl_relaxed(priv->base + RNG_SR);
>>                if (!sr && wait) {
>>                        unsigned int timeout = RNG_TIMEOUT;
>
>
> I think that introduces a bug: you really want to read the status
> register on each loop iteration.
Actually, I read the status again at the end of the loop.
But my implementation isn't good anyway, because I read the status
register one time more every time.

>
> How about moving the error handling into the loop itself?
That would be better, indeed, but there is one problem with your below proposal:
>
>         Arnd
>
>
> diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
> index 92a810648bd0..fceacd809462 100644
> --- a/drivers/char/hw_random/stm32-rng.c
> +++ b/drivers/char/hw_random/stm32-rng.c
> @@ -59,6 +59,10 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
>
>         while (max > sizeof(u32)) {
>                 sr = readl_relaxed(priv->base + RNG_SR);
> +               if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
> +                             "bad RNG status - %x\n", sr))
> +                       writel_relaxed(0, priv->base + RNG_SR);
> +
The error handling should be moved after the last status register read.

>                 if (!sr && wait) {
>                         unsigned int timeout = RNG_TIMEOUT;
>
> @@ -79,10 +83,6 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
>                 max -= sizeof(u32);
>         }
>
> -       if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
> -                     "bad RNG status - %x\n", sr))
> -               writel_relaxed(0, priv->base + RNG_SR);
> -
>         pm_runtime_mark_last_busy((struct device *) priv->rng.priv);
>         pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv);


diff --git a/drivers/char/hw_random/stm32-rng.c
b/drivers/char/hw_random/stm32-rng.c
index 92a810648bd0..2a0fc90e4dc3 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -68,6 +68,10 @@ static int stm32_rng_read(struct hwrng *rng, void
*data, size_t max, bool wait)
                        } while (!sr && --timeout);
                }

+               if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
+                               "bad RNG status - %x\n", sr))
+                       writel_relaxed(0, priv->base + RNG_SR);
+
                /* If error detected or data not ready... */
                if (sr != RNG_SR_DRDY)
                        break;
@@ -79,10 +83,6 @@ static int stm32_rng_read(struct hwrng *rng, void
*data, size_t max, bool wait)
                max -= sizeof(u32);
        }

-       if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
-                     "bad RNG status - %x\n", sr))
-               writel_relaxed(0, priv->base + RNG_SR);
-
        pm_runtime_mark_last_busy((struct device *) priv->rng.priv);
        pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv);

Thanks,
Maxime


From arnd at arndb.de  Tue May 24 01:50:37 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 24 May 2016 10:50:37 +0200
Subject: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
In-Reply-To: <1464067268-35299-1-git-send-email-navam@xilinx.com>
References: <1464067268-35299-1-git-send-email-navam@xilinx.com>
Message-ID: <14123451.MsNvJvqaJX@wuerfel>

On Tuesday, May 24, 2016 10:51:08 AM CEST Nava kishore Manne wrote:
> diff --git a/Documentation/devicetree/bindings/usb/udc-xilinx.txt b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> index 47b4e39..09df757 100644
> --- a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> +++ b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> @@ -1,18 +1,23 @@
>  Xilinx USB2 device controller
>  
>  Required properties:
> -- compatible		: Should be "xlnx,usb2-device-4.00.a"
> +- compatible		: Should be "xlnx,usb2-device-4.00.a" or
> +			  "xlnx,usb2-device-5.00"
>  - reg			: Physical base address and size of the USB2
>  			  device registers map.
>  - interrupts		: Should contain single irq line of USB2 device
>  			  controller
>  - xlnx,has-builtin-dma	: if DMA is included
> +- dma-ranges		: Should be as the following
> +			  <child-bus-address, parent-bus-address, length>

A USB host should not have any children that are DMA capable, I think, so this
property doesn't make sense here. It should be part of the parent bus.

> +- xlnx,addrwidth	: Should be the dma addressing size in bits(ex: 64 bits)

I'm still unconvinced about the property definition here. What are the possible
options for the IP block? I don't think I ever saw a reply from you to my earlier
questions.

> @@ -214,6 +223,20 @@ static const struct usb_endpoint_descriptor config_bulk_out_desc = {
>  	.wMaxPacketSize		= cpu_to_le16(EP0_MAX_PACKET),
>  };
>  
> +/**
> + * xudc_write64 - write 64bit value to device registers
> + * @addr: base addr of device registers
> + * @offset: register offset
> + * @val: data to be written
> + **/
> +static void xudc_write64(struct xusb_ep *ep, u32 offset, u64 val)
> +{
> +	struct xusb_udc *udc = ep->udc;
> +
> +	udc->write_fn(udc->addr, offset, lower_32_bits(val));
> +	udc->write_fn(udc->addr, offset+0x04, upper_32_bits(val));
> +}
> +
>  /**
>   * xudc_write32 - little endian write to device registers
>   * @addr: base addr of device registers
> @@ -330,8 +353,13 @@ static int xudc_start_dma(struct xusb_ep *ep, dma_addr_t src,
>  	 * destination registers and then set the length
>  	 * into the DMA length register.
>  	 */
> -	udc->write_fn(udc->addr, XUSB_DMA_DSAR_ADDR_OFFSET, src);
> -	udc->write_fn(udc->addr, XUSB_DMA_DDAR_ADDR_OFFSET, dst);
> +	if (udc->dma_addrwidth > 32) {
> +		xudc_write64(ep, XUSB_DMA_DSAR_ADDR_OFFSET_LSB, src);
> +		xudc_write64(ep, XUSB_DMA_DDAR_ADDR_OFFSET_LSB, dst);
> +	} else {
> +		udc->write_fn(udc->addr, XUSB_DMA_DSAR_ADDR_OFFSET, src);
> +		udc->write_fn(udc->addr, XUSB_DMA_DDAR_ADDR_OFFSET, dst);
> +	}
>  	udc->write_fn(udc->addr, XUSB_DMA_LENGTH_OFFSET, length);
>  

This looks good.

	Arnd


From arnd at arndb.de  Tue May 24 01:58:33 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 24 May 2016 10:58:33 +0200
Subject: [PATCH] hwrng: stm32 - fix build warning
In-Reply-To: <CALszF6BPPA=tezMLhmdC4YFwmH1tGhDxCNDZNwGp1cTDWP7Fmg@mail.gmail.com>
References: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>
 <12548318.auB4PSA3KC@wuerfel>
 <CALszF6BPPA=tezMLhmdC4YFwmH1tGhDxCNDZNwGp1cTDWP7Fmg@mail.gmail.com>
Message-ID: <6044541.yeLQbYg2Jv@wuerfel>

On Tuesday, May 24, 2016 10:50:17 AM CEST Maxime Coquelin wrote:
> diff --git a/drivers/char/hw_random/stm32-rng.c
> b/drivers/char/hw_random/stm32-rng.c
> index 92a810648bd0..2a0fc90e4dc3 100644
> --- a/drivers/char/hw_random/stm32-rng.c
> +++ b/drivers/char/hw_random/stm32-rng.c
> @@ -68,6 +68,10 @@ static int stm32_rng_read(struct hwrng *rng, void
> *data, size_t max, bool wait)
>                         } while (!sr && --timeout);
>                 }
> 
> +               if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
> +                               "bad RNG status - %x\n", sr))
> +                       writel_relaxed(0, priv->base + RNG_SR);
> +
>                 /* If error detected or data not ready... */
>                 if (sr != RNG_SR_DRDY)
>                         break;
> @@ -79,10 +83,6 @@ static int stm32_rng_read(struct hwrng *rng, void
> *data, size_t max, bool wait)
>                 max -= sizeof(u32);
>         }
> 
> -       if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
> -                     "bad RNG status - %x\n", sr))
> -               writel_relaxed(0, priv->base + RNG_SR);
> -
>         pm_runtime_mark_last_busy((struct device *) priv->rng.priv);
>         pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv);
> 
> Thanks,
> 

Yes, that looks good to me.

	Arnd



From wens at csie.org  Tue May 24 02:01:46 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 24 May 2016 17:01:46 +0800
Subject: [PATCH 07/16] clk: sunxi-ng: Add phase clock support
In-Reply-To: <20160523170129.GB27618@lukather>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-8-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v661dvdPKj9DWL7LWGgiDCEk7G-a_7jv5gb+KBMoWbR8Lg@mail.gmail.com>
 <20160523170129.GB27618@lukather>
Message-ID: <CAGb2v641TqdnDLAET7NPFsAgB4d4aroCWOw8G85pbOJhNs-Rnw@mail.gmail.com>

On Tue, May 24, 2016 at 1:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Hi,
>
> On Sun, May 22, 2016 at 12:43:48AM +0800, Chen-Yu Tsai wrote:
>> > +static int ccu_phase_set_phase(struct clk_hw *hw, int degrees)
>> > +{
>> > +       struct ccu_phase *phase = hw_to_ccu_phase(hw);
>> > +       struct clk_hw *parent, *pparent;
>> > +       unsigned int parent_rate, pparent_rate;
>>
>> grandparent(_rate) would be easier to understand.
>
> Ack.
>
>>
>> > +       unsigned long flags;
>> > +       u32 reg;
>> > +       u8 delay;
>> > +
>> > +       /* Get our parent clock, it's the one that can adjust its rate */
>> > +       parent = clk_hw_get_parent(hw);
>> > +       if (!parent)
>> > +               return -EINVAL;
>> > +
>> > +       /* And its rate */
>> > +       parent_rate = clk_hw_get_rate(parent);
>> > +       if (!parent_rate)
>> > +               return -EINVAL;
>> > +
>> > +       /* Now, get our parent's parent (most likely some PLL) */
>> > +       pparent = clk_hw_get_parent(parent);
>> > +       if (!pparent)
>> > +               return -EINVAL;
>> > +
>> > +       /* And its rate */
>> > +       pparent_rate = clk_hw_get_rate(pparent);
>> > +       if (!pparent_rate)
>> > +               return -EINVAL;
>> > +
>> > +       if (degrees != 180) {
>> > +               u16 step, parent_div;
>> > +
>> > +               /* Get our parent divider */
>> > +               parent_div = pparent_rate / parent_rate;
>> > +
>> > +               /*
>> > +                * We can only outphase the clocks by multiple of the
>> > +                * PLL's period.
>> > +                *
>> > +                * Since our parent clock is only a divider, and the
>> > +                * formula to get the outphasing in degrees is deg =
>> > +                * 360 * delta / period
>> > +                *
>> > +                * If we simplify this formula, we can see that the
>> > +                * only thing that we're concerned about is the number
>> > +                * of period we want to outphase our clock from, and
>> > +                * the divider set by our parent clock.
>> > +                */
>> > +               step = DIV_ROUND_CLOSEST(360, parent_div);
>> > +               delay = DIV_ROUND_CLOSEST(degrees, step);
>>
>> Doesn't this mean some delay values are impossible to set?
>>
>> For instance, for PLL = 600 MHz and this clock = 50 MHz, div would be 12,
>> and a step would be 30 degrees. This means we can't ask for a delay of 6,
>> which is 180 degrees.
>>
>> For PLL = 600 MHz, clock = 100 MHz, div would be 6, and a step is 60
>> degrees. Therefor we can't ask for a delay of 3.
>
> You don't ask for a delay, you ask for an outphasing in degrees. In
> the hardware, in the register 0 means an outphasing of 180 degrees
> (and this has been confirmed by Allwinner a while back). In the two
> cases you point out, we would have two ways of achieving the same
> thing, we prefer one over another, but I don't see how it's
> problematic.

I guess I find the outphasing degrees not being increasing somewhat
odd...

> It's also a direct copy of the current code we have, which didn't
> raise any objection, or had any known bugs.

I had a hard time wrapping this around my head when I was working on
the MMC DDR stuff. Allwinner's code directly asks for a delay, not a
outphasing. I just checked and it seems I converted some values
incorrectly. I need to do some more tests for the A80...

Thanks for the explanation.


Regards
ChenYu

>
>> > +struct ccu_phase {
>> > +       u8                      shift;
>> > +       u8                      width;
>>
>> Not sure why you used struct ccu_factor in the divider table clock,
>> but separate fields directly in ccu_phase here.
>
> Because this is not meant for the same thing. ccu_factor is probably
> going to go away anyway because of the dividers consolidation.
>
> Thanks!
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com


From daniel at ffwll.ch  Tue May 24 02:03:20 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Tue, 24 May 2016 11:03:20 +0200
Subject: [PATCH] drm/rockchip: Return -EBUSY if there's already a pending
 flip event v5
In-Reply-To: <1885816.5oayNdNrp7@phil>
References: <1464074761-5194-1-git-send-email-tomeu.vizoso@collabora.com>
 <20160524083050.GQ27098@phenom.ffwll.local>
 <20160524083749.GR27098@phenom.ffwll.local>
 <1885816.5oayNdNrp7@phil>
Message-ID: <20160524090320.GS27098@phenom.ffwll.local>

On Tue, May 24, 2016 at 10:41:30AM +0200, Heiko Stuebner wrote:
> Am Dienstag, 24. Mai 2016, 10:37:49 schrieb Daniel Vetter:
> > On Tue, May 24, 2016 at 10:30:50AM +0200, Daniel Vetter wrote:
> > > On Tue, May 24, 2016 at 10:28:42AM +0200, Heiko Stuebner wrote:
> > > > Hi Tomeu,
> > > > 
> > > > Patch subject: please put the version into the brackets, so [PATCH v5]
> > > > as it shouldn't be part of the commit log.
> > > > 
> > > > Am Dienstag, 24. Mai 2016, 09:27:37 schrieb Tomeu Vizoso:
> > > > > As per the docs, atomic_commit should return -EBUSY "if an
> > > > > asycnhronous
> > > > > updated is requested and there is an earlier updated pending".
> > > > > 
> > > > > v2: Use the status of the workqueue instead of vop->event, and don't
> > > > > add
> > > > > a superfluous wait on the workqueue.
> > > > > 
> > > > > v3: Drop work_busy, as there's a sizeable delay when the worker
> > > > > finishes, which introduces a race in which the client has already
> > > > > received the last flip event but the next page flip ioctl will still
> > > > > return -EBUSY because work_busy returns outdated information.
> > > > > 
> > > > > v4: Hold dev->event_lock while checking the VOP's event field as
> > > > > suggested by Daniel Stone.
> > > > > 
> > > > > v5: Only block if there's outstanding work if it's a blocking call.
> > > > 
> > > > similarly, please put the changelog below the "---" and above the
> > > > diffstat.> 
> > > drm culture is to keep it above, since it's kinda useful sometimes when
> > > later on trying to reconstruct wtf was discussed and why a patch was
> > > merged.
> > 
> > Maybe needs a bit more context: The only stuff you raised in your review
> > is tiny style nits of pretty much utter irrelevance. No substantial and
> > material feedback anywehere, and in my opinion in such a case either fix
> > up the nits when applying (when you feel really strongly about perfect
> > patches), or just merge as-is.
> > 
> > But sending out content-less bikesheds like these just adds noise and
> > helps no-one. I think at least some spelling stuff is the minimal bar (but
> > then just include your r-b tag), but personally I don't even care about
> > that so much, as long as it's still legible.
> 
> ok, will keep that (both mails) in mind for future stuff.

And to clarify, review of patches is very much appreciated, but to be
effective it should be top down. First assess whether it's a good idea,
then whether the implementation makes sense, then go down into style
naming and details like that. And it's important to tell the submitter
where they are in that process, too. More in-depth writeup of a good
review approach:

http://sarah.thesharps.us/2014/09/01/the-gentle-art-of-patch-review/

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From pavel at ucw.cz  Tue May 24 02:04:33 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Tue, 24 May 2016 11:04:33 +0200
Subject: [PATCHv3] support for AD5820 camera auto-focus coil
In-Reply-To: <574049EF.2090208@gmail.com>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com> <20160521105607.GA20071@amd>
 <574049EF.2090208@gmail.com>
Message-ID: <20160524090433.GA1277@amd>

Hi!

> >+static int ad5820_registered(struct v4l2_subdev *subdev)
> >+{
> >+	struct ad5820_device *coil = to_ad5820_device(subdev);
> >+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
> >+
> >+	coil->vana = regulator_get(&client->dev, "VANA");
> 
> devm_regulator_get()?

I'd rather avoid devm_ here. Driver is simple enough to allow it.

> >+#define AD5820_RAMP_MODE_LINEAR		(0 << 3)
> >+#define AD5820_RAMP_MODE_64_16		(1 << 3)
> >+
> >+struct ad5820_platform_data {
> >+	int (*set_xshutdown)(struct v4l2_subdev *subdev, int set);
> >+};
> >+
> >+#define to_ad5820_device(sd)	container_of(sd, struct ad5820_device, subdev)
> >+
> >+struct ad5820_device {
> >+	struct v4l2_subdev subdev;
> >+	struct ad5820_platform_data *platform_data;
> >+	struct regulator *vana;
> >+
> >+	struct v4l2_ctrl_handler ctrls;
> >+	u32 focus_absolute;
> >+	u32 focus_ramp_time;
> >+	u32 focus_ramp_mode;
> >+
> >+	struct mutex power_lock;
> >+	int power_count;
> >+
> >+	int standby : 1;
> >+};
> >+
> 
> The same for struct ad5820_device, is it really part of the public API?

Let me check what can be done with it.
									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From naga.sureshkumar.relli at xilinx.com  Tue May 24 02:04:41 2016
From: naga.sureshkumar.relli at xilinx.com (Naga Sureshkumar Relli)
Date: Tue, 24 May 2016 14:34:41 +0530
Subject: [PATCH 1/3] spi: xilinx: Remove bitbang and register with spi core
Message-ID: <1464080681-25109-1-git-send-email-nagasure@xilinx.com>

This patch removes the bitbang layer registration.
it directly register with spi core using spi_register_master and uses
the call backs provided by spi_master struct.

Signed-off-by: Naga Sureshkumar Relli <nagasure at xilinx.com>
---
 drivers/spi/spi-xilinx.c | 733 +++++++++++++++++++++++++++--------------------
 1 file changed, 418 insertions(+), 315 deletions(-)

diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 3009121..bc12e0c 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -18,10 +18,9 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
 #include <linux/spi/xilinx_spi.h>
 #include <linux/io.h>
-
+#include <linux/delay.h>
 #define XILINX_SPI_MAX_CS	32
 
 #define XILINX_SPI_NAME "xilinx_spi"
@@ -29,8 +28,18 @@
 /* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
  * Product Specification", DS464
  */
-#define XSPI_CR_OFFSET		0x60	/* Control Register */
-
+/* Register Offsets */
+#define XSPI_CR_OFFSET		0x60
+#define XSPI_SR_OFFSET		0x64
+#define XSPI_TXD_OFFSET		0x68
+#define XSPI_RXD_OFFSET		0x6c
+#define XSPI_SSR_OFFSET		0x70
+#define XIPIF_V123B_DGIER_OFFSET	0x1c
+#define XIPIF_V123B_IISR_OFFSET		0x20
+#define XIPIF_V123B_IIER_OFFSET		0x28
+#define XIPIF_V123B_RESETR_OFFSET	0x40
+
+/* Register bit masks */
 #define XSPI_CR_LOOP		0x01
 #define XSPI_CR_ENABLE		0x02
 #define XSPI_CR_MASTER_MODE	0x04
@@ -43,133 +52,188 @@
 #define XSPI_CR_MANUAL_SSELECT	0x80
 #define XSPI_CR_TRANS_INHIBIT	0x100
 #define XSPI_CR_LSB_FIRST	0x200
-
-#define XSPI_SR_OFFSET		0x64	/* Status Register */
-
-#define XSPI_SR_RX_EMPTY_MASK	0x01	/* Receive FIFO is empty */
-#define XSPI_SR_RX_FULL_MASK	0x02	/* Receive FIFO is full */
-#define XSPI_SR_TX_EMPTY_MASK	0x04	/* Transmit FIFO is empty */
-#define XSPI_SR_TX_FULL_MASK	0x08	/* Transmit FIFO is full */
-#define XSPI_SR_MODE_FAULT_MASK	0x10	/* Mode fault error */
-
-#define XSPI_TXD_OFFSET		0x68	/* Data Transmit Register */
-#define XSPI_RXD_OFFSET		0x6c	/* Data Receive Register */
-
-#define XSPI_SSR_OFFSET		0x70	/* 32-bit Slave Select Register */
-
-/* Register definitions as per "OPB IPIF (v3.01c) Product Specification", DS414
- * IPIF registers are 32 bit
- */
-#define XIPIF_V123B_DGIER_OFFSET	0x1c	/* IPIF global int enable reg */
+#define XSPI_SR_RX_EMPTY_MASK	0x01
+#define XSPI_SR_RX_FULL_MASK	0x02
+#define XSPI_SR_TX_EMPTY_MASK	0x04
+#define XSPI_SR_TX_FULL_MASK	0x08
+#define XSPI_SR_MODE_FAULT_MASK	0x10
 #define XIPIF_V123B_GINTR_ENABLE	0x80000000
-
-#define XIPIF_V123B_IISR_OFFSET		0x20	/* IPIF interrupt status reg */
-#define XIPIF_V123B_IIER_OFFSET		0x28	/* IPIF interrupt enable reg */
-
-#define XSPI_INTR_MODE_FAULT		0x01	/* Mode fault error */
-#define XSPI_INTR_SLAVE_MODE_FAULT	0x02	/* Selected as slave while
-						 * disabled */
-#define XSPI_INTR_TX_EMPTY		0x04	/* TxFIFO is empty */
-#define XSPI_INTR_TX_UNDERRUN		0x08	/* TxFIFO was underrun */
-#define XSPI_INTR_RX_FULL		0x10	/* RxFIFO is full */
-#define XSPI_INTR_RX_OVERRUN		0x20	/* RxFIFO was overrun */
-#define XSPI_INTR_TX_HALF_EMPTY		0x40	/* TxFIFO is half empty */
-
-#define XIPIF_V123B_RESETR_OFFSET	0x40	/* IPIF reset register */
-#define XIPIF_V123B_RESET_MASK		0x0a	/* the value to write */
-
+#define XSPI_INTR_MODE_FAULT		0x01
+#define XSPI_INTR_SLAVE_MODE_FAULT	0x02
+#define XSPI_INTR_TX_EMPTY		0x04
+#define XSPI_INTR_TX_UNDERRUN		0x08
+#define XSPI_INTR_RX_FULL		0x10
+#define XSPI_INTR_RX_OVERRUN		0x20
+#define XSPI_INTR_TX_HALF_EMPTY		0x40
+#define XIPIF_V123B_RESET_MASK		0x0a
+
+/* Number of bits per word */
+#define XSPI_ONE_BITS_PER_WORD 1
+#define XSPI_TWO_BITS_PER_WORD 2
+#define XSPI_FOUR_BITS_PER_WORD 4
+
+/* Number of data lines used to receive */
+#define XSPI_RX_ONE_WIRE	1
+
+/**
+ * struct xilinx_spi - This definition define spi driver instance
+ * @regs:		virt. address of the control registers
+ * @irq:		IRQ number
+ * @rx_ptr:		Pointer to the RX buffer
+ * @tx_ptr:		Pointer to the TX buffer
+ * @bytes_per_word:	Number of bytes in a word
+ * @buffer_size:	Buffer size in words
+ * @cs_inactive:	Level of the CS pins when inactive
+ * @read_fn:		For reading data from SPI registers
+ * @write_fn:		For writing data to SPI registers
+ * @bytes_to_transfer:	Number of bytes left to transfer
+ * @bytes_to_receive:	Number of bytes left to receive
+ * @rx_bus_width:	Number of wires used to receive data
+ * @tx_fifo:		For writing data to fifo
+ * @rx_fifo:		For reading data from fifo
+ */
 struct xilinx_spi {
-	/* bitbang has to be first */
-	struct spi_bitbang bitbang;
-	struct completion done;
-	void __iomem	*regs;	/* virt. address of the control registers */
-
-	int		irq;
-
-	u8 *rx_ptr;		/* pointer in the Tx buffer */
-	const u8 *tx_ptr;	/* pointer in the Rx buffer */
+	void __iomem *regs;
+	int irq;
+	u8 *rx_ptr;
+	const u8 *tx_ptr;
 	u8 bytes_per_word;
-	int buffer_size;	/* buffer size in words */
-	u32 cs_inactive;	/* Level of the CS pins when inactive*/
+	int buffer_size;
+	u32 cs_inactive;
 	unsigned int (*read_fn)(void __iomem *);
 	void (*write_fn)(u32, void __iomem *);
+	u32 bytes_to_transfer;
+	u32 bytes_to_receive;
+	u32 rx_bus_width;
+	void (*tx_fifo)(struct xilinx_spi *xqspi);
+	void (*rx_fifo)(struct xilinx_spi *xqspi);
 };
 
+/**
+ * XSPI_FIFO_READ - Generate xspi_read_rx_fifo_* functions
+ * @size: bits_per_word that are read from RX FIFO
+ * @type: C type of value argument
+ *
+ * Generates xspi_read_rx_fifo_* functions used to write
+ * data into RX FIFO for different transaction widths.
+ */
+#define XSPI_FIFO_READ(size, type)					\
+static void xspi_read_rx_fifo_##size(struct xilinx_spi *xqspi)		\
+{									\
+	int i;								\
+	int count = (xqspi->bytes_to_receive > xqspi->buffer_size) ?	\
+			xqspi->buffer_size : xqspi->bytes_to_receive;	\
+	u32 data;							\
+	for (i = 0; i < count; i += (size/8)) {				\
+		data = readl_relaxed(xqspi->regs + XSPI_RXD_OFFSET);	\
+		if (xqspi->rx_ptr)					\
+			((type *)xqspi->rx_ptr)[i] = (type)data;	\
+	}								\
+	xqspi->bytes_to_receive -= count;				\
+	if (xqspi->rx_ptr)						\
+		xqspi->rx_ptr += count;					\
+}
+
+/**
+ * XSPI_FIFO_WRITE - Generate xspi_fill_tx_fifo_* functions
+ * @size: bits_per_word that are written into TX FIFO
+ * @type: C type of value argument
+ *
+ * Generates xspi_fill_tx_fifo_* functions used to write
+ * data into TX FIFO for different transaction widths.
+ */
+#define XSPI_FIFO_WRITE(size, type)					\
+static void xspi_fill_tx_fifo_##size(struct xilinx_spi *xqspi)		\
+{									\
+	int i;								\
+	int count = (xqspi->bytes_to_transfer > xqspi->buffer_size) ?	\
+			xqspi->buffer_size : xqspi->bytes_to_transfer;	\
+	u32 data = 0;							\
+	for (i = 0; i < count; i += (size/8)) {				\
+		if (xqspi->tx_ptr)					\
+			data = (type)((u8 *)xqspi->tx_ptr)[i];		\
+		writel_relaxed(data, (xqspi->regs + XSPI_TXD_OFFSET));	\
+	}								\
+	xqspi->bytes_to_transfer -= count;				\
+	if (xqspi->tx_ptr)						\
+		xqspi->tx_ptr += count;					\
+}
+
+XSPI_FIFO_READ(8, u8)
+XSPI_FIFO_READ(16, u16)
+XSPI_FIFO_READ(32, u32)
+XSPI_FIFO_WRITE(8, u8)
+XSPI_FIFO_WRITE(16, u16)
+XSPI_FIFO_WRITE(32, u32)
+
+/**
+ * xspi_write32 - Write a value to the device register little endian
+ * @val:	Value to write at the Register offset
+ * @addr:	Register offset
+ *
+ * Write data to the paricular SPI register
+ */
 static void xspi_write32(u32 val, void __iomem *addr)
 {
 	iowrite32(val, addr);
 }
 
+/**
+ * xspi_read32 - read a value from the device register little endian
+ * @addr:	Register offset
+ *
+ * Read data from the paricular SPI register
+ *
+ * Return:	return value from the SPI register.
+ */
 static unsigned int xspi_read32(void __iomem *addr)
 {
 	return ioread32(addr);
 }
 
+/**
+ * xspi_write32_be - Write a value to the device register big endian
+ * @val:	Value to write at the Register offset
+ * @addr:	Register offset
+ *
+ * Write data to the paricular SPI register
+ */
 static void xspi_write32_be(u32 val, void __iomem *addr)
 {
 	iowrite32be(val, addr);
 }
 
+/**
+ * xspi_read32_be - read a value from the device register big endian
+ * @addr:	Register offset
+ *
+ * Read data from the paricular SPI register
+ *
+ * Return:	return value from the SPI register.
+ */
 static unsigned int xspi_read32_be(void __iomem *addr)
 {
 	return ioread32be(addr);
 }
 
-static void xilinx_spi_tx(struct xilinx_spi *xspi)
-{
-	u32 data = 0;
-
-	if (!xspi->tx_ptr) {
-		xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
-		return;
-	}
-
-	switch (xspi->bytes_per_word) {
-	case 1:
-		data = *(u8 *)(xspi->tx_ptr);
-		break;
-	case 2:
-		data = *(u16 *)(xspi->tx_ptr);
-		break;
-	case 4:
-		data = *(u32 *)(xspi->tx_ptr);
-		break;
-	}
-
-	xspi->write_fn(data, xspi->regs + XSPI_TXD_OFFSET);
-	xspi->tx_ptr += xspi->bytes_per_word;
-}
-
-static void xilinx_spi_rx(struct xilinx_spi *xspi)
-{
-	u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
-
-	if (!xspi->rx_ptr)
-		return;
-
-	switch (xspi->bytes_per_word) {
-	case 1:
-		*(u8 *)(xspi->rx_ptr) = data;
-		break;
-	case 2:
-		*(u16 *)(xspi->rx_ptr) = data;
-		break;
-	case 4:
-		*(u32 *)(xspi->rx_ptr) = data;
-		break;
-	}
-
-	xspi->rx_ptr += xspi->bytes_per_word;
-}
-
+/**
+ * xspi_init_hw - Initialize the hardware
+ * @xspi:	Pointer to the zynqmp_qspi structure
+ *
+ * This function performs the following actions
+ *	- Disable and clear all the interrupts
+ *	- Enable manual slave select
+ *	- Enable the SPI controller
+ */
 static void xspi_init_hw(struct xilinx_spi *xspi)
 {
 	void __iomem *regs_base = xspi->regs;
 
 	/* Reset the SPI device */
 	xspi->write_fn(XIPIF_V123B_RESET_MASK,
-		regs_base + XIPIF_V123B_RESETR_OFFSET);
-	/* Enable the transmit empty interrupt, which we use to determine
+			regs_base + XIPIF_V123B_RESETR_OFFSET);
+	/*
+	 * Enable the transmit empty interrupt, which we use to determine
 	 * progress on the transmission.
 	 */
 	xspi->write_fn(XSPI_INTR_TX_EMPTY,
@@ -178,203 +242,223 @@ static void xspi_init_hw(struct xilinx_spi *xspi)
 	xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
 	/* Deselect the slave on the SPI bus */
 	xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET);
-	/* Disable the transmitter, enable Manual Slave Select Assertion,
+	/*
+	 * Disable the transmitter, enable Manual Slave Select Assertion,
 	 * put SPI controller into master mode, and enable it */
 	xspi->write_fn(XSPI_CR_MANUAL_SSELECT |	XSPI_CR_MASTER_MODE |
 		XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET |	XSPI_CR_RXFIFO_RESET,
 		regs_base + XSPI_CR_OFFSET);
 }
 
-static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
+/**
+ * xspi_chipselect -	Select or deselect the chip select line
+ * @qspi:	Pointer to the spi_device structure
+ * @is_high:	Select(0) or deselect (1) the chip select line
+ *
+ */
+static void xspi_chipselect(struct spi_device *qspi, bool is_high)
 {
-	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
-	u16 cr;
+	struct xilinx_spi *xqspi = spi_master_get_devdata(qspi->master);
 	u32 cs;
 
-	if (is_on == BITBANG_CS_INACTIVE) {
-		/* Deselect the slave on the SPI bus */
-		xspi->write_fn(xspi->cs_inactive, xspi->regs + XSPI_SSR_OFFSET);
-		return;
+	if (is_high) {
+		/* Deselect the slave */
+		xqspi->write_fn(xqspi->cs_inactive,
+			xqspi->regs + XSPI_SSR_OFFSET);
+	} else {
+		cs = xqspi->cs_inactive;
+		cs ^= BIT(qspi->chip_select);
+		/* Activate the chip select */
+		xqspi->write_fn(cs, xqspi->regs + XSPI_SSR_OFFSET);
 	}
+}
 
-	/* Set the SPI clock phase and polarity */
-	cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET)	& ~XSPI_CR_MODE_MASK;
-	if (spi->mode & SPI_CPHA)
-		cr |= XSPI_CR_CPHA;
-	if (spi->mode & SPI_CPOL)
-		cr |= XSPI_CR_CPOL;
-	if (spi->mode & SPI_LSB_FIRST)
-		cr |= XSPI_CR_LSB_FIRST;
-	if (spi->mode & SPI_LOOP)
-		cr |= XSPI_CR_LOOP;
-	xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-
-	/* We do not check spi->max_speed_hz here as the SPI clock
-	 * frequency is not software programmable (the IP block design
-	 * parameter)
-	 */
+/**
+ * xilinx_spi_irq -	Interrupt service routine of the SPI controller
+ * @irq:	IRQ number
+ * @dev_id:	Pointer to the xspi structure
+ *
+ * This function handles TX empty only.
+ * On TX empty interrupt this function reads the received data from RX FIFO
+ * and fills the TX FIFO if there is any data remaining to be transferred.
+ *
+ * Return:	IRQ_HANDLED when interrupt is handled
+ *		IRQ_NONE otherwise.
+ */
+static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
+{
+	struct spi_master *master = dev_id;
+	struct xilinx_spi *xspi = spi_master_get_devdata(dev_id);
+	u32 ipif_isr;
+	int status = IRQ_NONE;
 
-	cs = xspi->cs_inactive;
-	cs ^= BIT(spi->chip_select);
+	/* Get the IPIF interrupts, and clear them immediately */
+	ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
+	xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);
+	if (ipif_isr & XSPI_INTR_TX_EMPTY)  {
+		/* Transmission completed */
+		xspi->rx_fifo(xspi);
+		if (xspi->bytes_to_transfer) {
+			/* There is more data to send */
+			xspi->tx_fifo(xspi);
+		}
+		status = IRQ_HANDLED;
+	}
+
+	if (!xspi->bytes_to_receive && !xspi->bytes_to_transfer) {
+		spi_finalize_current_transfer(master);
+		/* Disable the interrupts here. */
+		xspi->write_fn(0x0, xspi->regs + XIPIF_V123B_DGIER_OFFSET);
+	}
 
-	/* Activate the chip select */
-	xspi->write_fn(cs, xspi->regs + XSPI_SSR_OFFSET);
+	return status;
 }
 
-/* spi_bitbang requires custom setup_transfer() to be defined if there is a
- * custom txrx_bufs().
+/**
+ * xspi_setup_transfer - Configure SPI controller for specified
+ *			 transfer
+ * @qspi:	Pointer to the spi_device structure
+ * @transfer:	Pointer to the spi_transfer structure which provides
+ *		information about next transfer setup parameters
+ *
+ * Sets the operational mode of QSPI controller for the next QSPI
+ * transfer.
+ *
+ * Return:	0 always
  */
-static int xilinx_spi_setup_transfer(struct spi_device *spi,
-		struct spi_transfer *t)
+static int xspi_setup_transfer(struct spi_device *qspi,
+				    struct spi_transfer *transfer)
 {
-	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
-
-	if (spi->mode & SPI_CS_HIGH)
-		xspi->cs_inactive &= ~BIT(spi->chip_select);
+	struct xilinx_spi *xqspi = spi_master_get_devdata(qspi->master);
+	u32 config_reg;
+
+	config_reg = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET);
+	/* Set the QSPI clock phase and clock polarity */
+	config_reg &= ~(XSPI_CR_CPHA | XSPI_CR_CPOL);
+	if (qspi->mode & SPI_CPHA)
+		config_reg |= XSPI_CR_CPHA;
+	if (qspi->mode & SPI_CPOL)
+		config_reg |= XSPI_CR_CPOL;
+	if (qspi->mode & SPI_LSB_FIRST)
+		config_reg |= XSPI_CR_LSB_FIRST;
+	xqspi->write_fn(config_reg, xqspi->regs + XSPI_CR_OFFSET);
+
+	if (qspi->mode & SPI_CS_HIGH)
+		xqspi->cs_inactive &= ~BIT(qspi->chip_select);
 	else
-		xspi->cs_inactive |= BIT(spi->chip_select);
+		xqspi->cs_inactive |= BIT(qspi->chip_select);
 
 	return 0;
 }
 
-static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+/**
+ * xspi_setup -	Configure the SPI controller
+ * @qspi:	Pointer to the spi_device structure
+ *
+ * Sets the operational mode of QSPI controller for the next QSPI
+ * transfer.
+ *
+ * Return:	0 on success; error value otherwise.
+ */
+static int xspi_setup(struct spi_device *qspi)
 {
-	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
-	int remaining_words;	/* the number of words left to transfer */
-	bool use_irq = false;
-	u16 cr = 0;
-
-	/* We get here with transmitter inhibited */
-
-	xspi->tx_ptr = t->tx_buf;
-	xspi->rx_ptr = t->rx_buf;
-	remaining_words = t->len / xspi->bytes_per_word;
-
-	if (xspi->irq >= 0 &&  remaining_words > xspi->buffer_size) {
-		u32 isr;
-		use_irq = true;
-		/* Inhibit irq to avoid spurious irqs on tx_empty*/
-		cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
-		xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
-			       xspi->regs + XSPI_CR_OFFSET);
-		/* ACK old irqs (if any) */
-		isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
-		if (isr)
-			xspi->write_fn(isr,
-				       xspi->regs + XIPIF_V123B_IISR_OFFSET);
-		/* Enable the global IPIF interrupt */
-		xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
-				xspi->regs + XIPIF_V123B_DGIER_OFFSET);
-		reinit_completion(&xspi->done);
-	}
-
-	while (remaining_words) {
-		int n_words, tx_words, rx_words;
-		u32 sr;
-
-		n_words = min(remaining_words, xspi->buffer_size);
-
-		tx_words = n_words;
-		while (tx_words--)
-			xilinx_spi_tx(xspi);
-
-		/* Start the transfer by not inhibiting the transmitter any
-		 * longer
-		 */
-
-		if (use_irq) {
-			xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-			wait_for_completion(&xspi->done);
-			/* A transmit has just completed. Process received data
-			 * and check for more data to transmit. Always inhibit
-			 * the transmitter while the Isr refills the transmit
-			 * register/FIFO, or make sure it is stopped if we're
-			 * done.
-			 */
-			xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
-				       xspi->regs + XSPI_CR_OFFSET);
-			sr = XSPI_SR_TX_EMPTY_MASK;
-		} else
-			sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
-
-		/* Read out all the data from the Rx FIFO */
-		rx_words = n_words;
-		while (rx_words) {
-			if ((sr & XSPI_SR_TX_EMPTY_MASK) && (rx_words > 1)) {
-				xilinx_spi_rx(xspi);
-				rx_words--;
-				continue;
-			}
-
-			sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
-			if (!(sr & XSPI_SR_RX_EMPTY_MASK)) {
-				xilinx_spi_rx(xspi);
-				rx_words--;
-			}
-		}
+	if (qspi->master->busy)
+		return -EBUSY;
 
-		remaining_words -= n_words;
-	}
+	return xspi_setup_transfer(qspi, NULL);
+}
 
-	if (use_irq) {
-		xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET);
-		xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-	}
+/**
+ * xspi_start_transfer - Initiates the SPI transfer
+ * @master:	Pointer to the spi_master structure which provides
+ *		information about the controller.
+ * @qspi:	Pointer to the spi_device structure
+ * @transfer:	Pointer to the spi_transfer structure which provide information
+ *		about next transfer parameters
+ *
+ * This function fills the TX FIFO, starts the SPI transfer, and waits for the
+ * transfer to be completed.
+ *
+ * Return:	Number of bytes transferred in the last transfer
+ */
 
-	return t->len;
+static int xspi_start_transfer(struct spi_master *master,
+				    struct spi_device *qspi,
+				    struct spi_transfer *transfer)
+{
+	struct xilinx_spi *xqspi = spi_master_get_devdata(master);
+	u32 cr;
+
+	xqspi->tx_ptr = transfer->tx_buf;
+	xqspi->rx_ptr = transfer->rx_buf;
+	xqspi->bytes_to_transfer = transfer->len;
+	xqspi->bytes_to_receive = transfer->len;
+
+	xspi_setup_transfer(qspi, transfer);
+	cr = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET);
+	/* Enable master transaction inhibit */
+	cr |= XSPI_CR_TRANS_INHIBIT;
+	xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET);
+	xqspi->tx_fifo(xqspi);
+	/* Disable master transaction inhibit */
+	cr &= ~XSPI_CR_TRANS_INHIBIT;
+	xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET);
+	xqspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
+			xqspi->regs + XIPIF_V123B_DGIER_OFFSET);
+
+	return transfer->len;
 }
 
-
-/* This driver supports single master mode only. Hence Tx FIFO Empty
- * is the only interrupt we care about.
- * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode
- * Fault are not to happen.
+/**
+ * xspi_prepare_transfer_hardware -	Prepares hardware for transfer.
+ * @master:	Pointer to the spi_master structure which provides
+ *		information about the controller.
+ *
+ * This function enables SPI master controller.
+ *
+ * Return:	0 on success; error value otherwise
  */
-static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
+static int xspi_prepare_transfer_hardware(struct spi_master *master)
 {
-	struct xilinx_spi *xspi = dev_id;
-	u32 ipif_isr;
+	struct xilinx_spi *xqspi = spi_master_get_devdata(master);
+	u32 cr;
 
-	/* Get the IPIF interrupts, and clear them immediately */
-	ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
-	xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);
+	cr = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET);
+	cr |= XSPI_CR_ENABLE;
+	xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET);
 
-	if (ipif_isr & XSPI_INTR_TX_EMPTY) {	/* Transmission completed */
-		complete(&xspi->done);
-	}
-
-	return IRQ_HANDLED;
+	return 0;
 }
 
-static int xilinx_spi_find_buffer_size(struct xilinx_spi *xspi)
+/**
+ * xspi_unprepare_transfer_hardware -	Relaxes hardware after transfer
+ * @master:	Pointer to the spi_master structure which provides
+ *		information about the controller.
+ *
+ * This function disables the SPI master controller.
+ *
+ * Return:	Always 0
+ */
+static int xspi_unprepare_transfer_hardware(struct spi_master *master)
 {
-	u8 sr;
-	int n_words = 0;
+	struct xilinx_spi *xqspi = spi_master_get_devdata(master);
+	u32 cr;
 
-	/*
-	 * Before the buffer_size detection we reset the core
-	 * to make sure we start with a clean state.
-	 */
-	xspi->write_fn(XIPIF_V123B_RESET_MASK,
-		xspi->regs + XIPIF_V123B_RESETR_OFFSET);
+	cr = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET);
+	cr &= ~XSPI_CR_ENABLE;
+	xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET);
 
-	/* Fill the Tx FIFO with as many words as possible */
-	do {
-		xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
-		sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
-		n_words++;
-	} while (!(sr & XSPI_SR_TX_FULL_MASK));
-
-	return n_words;
+	return 0;
 }
 
-static const struct of_device_id xilinx_spi_of_match[] = {
-	{ .compatible = "xlnx,xps-spi-2.00.a", },
-	{ .compatible = "xlnx,xps-spi-2.00.b", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
-
+/**
+ * xilinx_spi_probe -	Probe method for the SPI driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function initializes the driver data structures and the hardware.
+ *
+ * Return:	0 on success; error value otherwise
+ */
 static int xilinx_spi_probe(struct platform_device *pdev)
 {
 	struct xilinx_spi *xspi;
@@ -382,23 +466,14 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 	struct resource *res;
 	int ret, num_cs = 0, bits_per_word = 8;
 	struct spi_master *master;
-	u32 tmp;
-	u8 i;
+	struct device_node *nc;
+	u32 tmp, rx_bus_width, fifo_size = 0;
 
 	pdata = dev_get_platdata(&pdev->dev);
-	if (pdata) {
-		num_cs = pdata->num_chipselect;
-		bits_per_word = pdata->bits_per_word;
-	} else {
-		of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits",
-					  &num_cs);
-	}
-
-	if (!num_cs) {
-		dev_err(&pdev->dev,
-			"Missing slave select configuration data\n");
-		return -EINVAL;
-	}
+	of_property_read_u32(pdev->dev.of_node, "num-cs",
+				&num_cs);
+	if (!num_cs)
+		num_cs = 1;
 
 	if (num_cs > XILINX_SPI_MAX_CS) {
 		dev_err(&pdev->dev, "Invalid number of spi slaves\n");
@@ -409,18 +484,9 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 	if (!master)
 		return -ENODEV;
 
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP |
-			    SPI_CS_HIGH;
-
 	xspi = spi_master_get_devdata(master);
-	xspi->cs_inactive = 0xffffffff;
-	xspi->bitbang.master = master;
-	xspi->bitbang.chipselect = xilinx_spi_chipselect;
-	xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
-	xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
-	init_completion(&xspi->done);
-
+	master->dev.of_node = pdev->dev.of_node;
+	platform_set_drvdata(pdev, master);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	xspi->regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(xspi->regs)) {
@@ -428,20 +494,28 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 		goto put_master;
 	}
 
-	master->bus_num = pdev->id;
-	master->num_chipselect = num_cs;
-	master->dev.of_node = pdev->dev.of_node;
-
-	/*
-	 * Detect endianess on the IP via loop bit in CR. Detection
-	 * must be done before reset is sent because incorrect reset
-	 * value generates error interrupt.
-	 * Setup little endian helper functions first and try to use them
-	 * and check if bit was correctly setup or not.
-	 */
+	of_property_read_u32(pdev->dev.of_node, "fifo-size",
+				&fifo_size);
+	if (!fifo_size) {
+		dev_err(&pdev->dev,
+			"Missing fifo size\n");
+		return -EINVAL;
+	}
+	of_property_read_u32(pdev->dev.of_node, "bits-per-word",
+				&bits_per_word);
+
+	xspi->rx_bus_width = XSPI_ONE_BITS_PER_WORD;
+	for_each_available_child_of_node(pdev->dev.of_node, nc) {
+		ret = of_property_read_u32(nc, "spi-rx-bus-width",
+						&rx_bus_width);
+		if (!ret) {
+			xspi->rx_bus_width = rx_bus_width;
+			break;
+		}
+	}
 	xspi->read_fn = xspi_read32;
 	xspi->write_fn = xspi_write32;
-
+	/* Detect endianness on the IP via loop bit in CR register*/
 	xspi->write_fn(XSPI_CR_LOOP, xspi->regs + XSPI_CR_OFFSET);
 	tmp = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
 	tmp &= XSPI_CR_LOOP;
@@ -450,15 +524,12 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 		xspi->write_fn = xspi_write32_be;
 	}
 
-	master->bits_per_word_mask = SPI_BPW_MASK(bits_per_word);
-	xspi->bytes_per_word = bits_per_word / 8;
-	xspi->buffer_size = xilinx_spi_find_buffer_size(xspi);
-
+	xspi->buffer_size = fifo_size;
 	xspi->irq = platform_get_irq(pdev, 0);
 	if (xspi->irq >= 0) {
 		/* Register for SPI Interrupt */
-		ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0,
-				dev_name(&pdev->dev), xspi);
+		ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq,
+					0, dev_name(&pdev->dev), master);
 		if (ret)
 			goto put_master;
 	}
@@ -466,22 +537,39 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 	/* SPI controller initializations */
 	xspi_init_hw(xspi);
 
-	ret = spi_bitbang_start(&xspi->bitbang);
-	if (ret) {
-		dev_err(&pdev->dev, "spi_bitbang_start FAILED\n");
+	master->bus_num = pdev->id;
+	master->num_chipselect = num_cs;
+	master->setup = xspi_setup;
+	master->set_cs = xspi_chipselect;
+	master->transfer_one = xspi_start_transfer;
+	master->prepare_transfer_hardware = xspi_prepare_transfer_hardware;
+	master->unprepare_transfer_hardware = xspi_unprepare_transfer_hardware;
+	master->bits_per_word_mask = SPI_BPW_MASK(8);
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	xspi->bytes_per_word = bits_per_word / 8;
+	xspi->tx_fifo = xspi_fill_tx_fifo_8;
+	xspi->rx_fifo = xspi_read_rx_fifo_8;
+	if (xspi->rx_bus_width == XSPI_RX_ONE_WIRE) {
+		if (xspi->bytes_per_word == XSPI_TWO_BITS_PER_WORD) {
+			xspi->tx_fifo = xspi_fill_tx_fifo_16;
+			xspi->rx_fifo = xspi_read_rx_fifo_16;
+		} else if (xspi->bytes_per_word == XSPI_FOUR_BITS_PER_WORD) {
+			xspi->tx_fifo = xspi_fill_tx_fifo_32;
+			xspi->rx_fifo = xspi_read_rx_fifo_32;
+		}
+	} else {
+		dev_err(&pdev->dev, "Dual/Quad Modes are not supported\n");
 		goto put_master;
 	}
-
-	dev_info(&pdev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n",
-		(unsigned long long)res->start, xspi->regs, xspi->irq);
-
-	if (pdata) {
-		for (i = 0; i < pdata->num_devices; i++)
-			spi_new_device(master, pdata->devices + i);
+	xspi->cs_inactive = 0xffffffff;
+	ret = spi_register_master(master);
+	if (ret) {
+		dev_err(&pdev->dev, "spi_register_master failed\n");
+		goto put_master;
 	}
 
-	platform_set_drvdata(pdev, master);
-	return 0;
+	return ret;
 
 put_master:
 	spi_master_put(master);
@@ -489,20 +577,28 @@ put_master:
 	return ret;
 }
 
+/**
+ * xilinx_spi_remove -	Remove method for the SPI driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function is called if a device is physically removed from the system or
+ * if the driver module is being unloaded. It frees all resources allocated to
+ * the device.
+ *
+ * Return:	0 Always
+ */
 static int xilinx_spi_remove(struct platform_device *pdev)
 {
 	struct spi_master *master = platform_get_drvdata(pdev);
 	struct xilinx_spi *xspi = spi_master_get_devdata(master);
 	void __iomem *regs_base = xspi->regs;
 
-	spi_bitbang_stop(&xspi->bitbang);
-
 	/* Disable all the interrupts just in case */
 	xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET);
 	/* Disable the global IPIF interrupt */
 	xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
 
-	spi_master_put(xspi->bitbang.master);
+	spi_unregister_master(master);
 
 	return 0;
 }
@@ -510,6 +606,13 @@ static int xilinx_spi_remove(struct platform_device *pdev)
 /* work with hotplug and coldplug */
 MODULE_ALIAS("platform:" XILINX_SPI_NAME);
 
+static const struct of_device_id xilinx_spi_of_match[] = {
+	{ .compatible = "xlnx,xps-spi-2.00.a", },
+	{ .compatible = "xlnx,xps-spi-2.00.b", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
+
 static struct platform_driver xilinx_spi_driver = {
 	.probe = xilinx_spi_probe,
 	.remove = xilinx_spi_remove,
-- 
2.1.1



From naga.sureshkumar.relli at xilinx.com  Tue May 24 02:04:48 2016
From: naga.sureshkumar.relli at xilinx.com (Naga Sureshkumar Relli)
Date: Tue, 24 May 2016 14:34:48 +0530
Subject: [PATCH 2/3] spi: xilinx: Add QUAD support
Message-ID: <1464080688-25158-1-git-send-email-nagasure@xilinx.com>

This patch adds QUAD mode support to axi spi controller.
updated supported mode bits to SPI_TX_QUAD and SPI_RX_QUAD.

Signed-off-by: Naga Sureshkumar Relli <nagasure at xilinx.com>
---
 drivers/spi/spi-xilinx.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index bc12e0c..8dd4577 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -74,6 +74,7 @@
 
 /* Number of data lines used to receive */
 #define XSPI_RX_ONE_WIRE	1
+#define XSPI_RX_FOUR_WIRE	4
 
 /**
  * struct xilinx_spi - This definition define spi driver instance
@@ -558,8 +559,10 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 			xspi->tx_fifo = xspi_fill_tx_fifo_32;
 			xspi->rx_fifo = xspi_read_rx_fifo_32;
 		}
+	} else if (xspi->rx_bus_width == XSPI_RX_FOUR_WIRE) {
+		master->mode_bits |= SPI_TX_QUAD | SPI_RX_QUAD;
 	} else {
-		dev_err(&pdev->dev, "Dual/Quad Modes are not supported\n");
+		dev_err(&pdev->dev, "Dual Mode not supported\n");
 		goto put_master;
 	}
 	xspi->cs_inactive = 0xffffffff;
-- 
2.1.1



From naga.sureshkumar.relli at xilinx.com  Tue May 24 02:04:54 2016
From: naga.sureshkumar.relli at xilinx.com (Naga Sureshkumar Relli)
Date: Tue, 24 May 2016 14:34:54 +0530
Subject: [PATCH 3/3] spi: xilinx: Update devicetree bindings for spi-xilinx
Message-ID: <1464080694-25207-1-git-send-email-nagasure@xilinx.com>

Update bindings for spi-xilinx.
as per spi-bus.txt rename num-ss-bits to num-cs.
and add fifo-size and bits-per-word properties.

Signed-off-by: Naga Sureshkumar Relli <nagasure at xilinx.com>
---
 Documentation/devicetree/bindings/spi/spi-xilinx.txt | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-xilinx.txt b/Documentation/devicetree/bindings/spi/spi-xilinx.txt
index c7b7856..539bbe9 100644
--- a/Documentation/devicetree/bindings/spi/spi-xilinx.txt
+++ b/Documentation/devicetree/bindings/spi/spi-xilinx.txt
@@ -7,9 +7,11 @@ Required properties:
 - interrupts		: Property with a value describing the interrupt
 			  number.
 - interrupt-parent	: Must be core interrupt controller
+- fifo-size		: Depth of TX/RX Fifos
 
 Optional properties:
-- xlnx,num-ss-bits	: Number of chip selects used.
+- num-cs		: Number of chip selects used.
+- bits-per-word		: Number of bits per word.
 
 Example:
 	axi_quad_spi at 41e00000 {
@@ -17,6 +19,8 @@ Example:
 			interrupt-parent = <&intc>;
 			interrupts = <0 31 1>;
 			reg = <0x41e00000 0x10000>;
-			xlnx,num-ss-bits = <0x1>;
+			num-cs = <0x1>;
+			fifo-size = <256>;
+			bits-per-word = <8>;
 	};
 
-- 
2.1.1



From hch at infradead.org  Tue May 24 02:09:38 2016
From: hch at infradead.org (Christoph Hellwig)
Date: Tue, 24 May 2016 02:09:38 -0700
Subject: [PATCH 0/4] dma-mapping: Constify dma_attrs
In-Reply-To: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>
References: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <20160524090938.GA13166@infradead.org>

I think this is moving into the wrong direction.  The right fix here
is to get of all the dma_attrs boilerplate code and just replace it
with a simple enum dma_flags.  This would simplify both the callers
and most importantly the wrappers for the flag-less versions a lot.


From christoffer.dall at linaro.org  Tue May 24 02:08:56 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:08:56 +0200
Subject: [PULL 02/59] KVM: arm/arm64: vgic: streamline
 vgic_update_irq_pending() interface
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-3-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

We actually don't use the irq_phys_map parameter in
vgic_update_irq_pending(), so let's just remove it.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 60668a7..f6c6172 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1521,7 +1521,6 @@ static int vgic_validate_injection(struct kvm_vcpu *vcpu, int irq, int level)
 }
 
 static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
-				   struct irq_phys_map *map,
 				   unsigned int irq_num, bool level)
 {
 	struct vgic_dist *dist = &kvm->arch.vgic;
@@ -1660,7 +1659,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 	if (map)
 		return -EINVAL;
 
-	return vgic_update_irq_pending(kvm, cpuid, NULL, irq_num, level);
+	return vgic_update_irq_pending(kvm, cpuid, irq_num, level);
 }
 
 /**
@@ -1686,7 +1685,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 	if (ret)
 		return ret;
 
-	return vgic_update_irq_pending(kvm, cpuid, map, map->virt_irq, level);
+	return vgic_update_irq_pending(kvm, cpuid, map->virt_irq, level);
 }
 
 static irqreturn_t vgic_maintenance_handler(int irq, void *data)
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:08:54 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:08:54 +0200
Subject: [PULL 00/59] KVM/ARM Changes for v4.7 take 2
Message-ID: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>

Hi Paolo and Radim,

Here's another set of changes for v4.7.

This set of changes include the new vgic, which is a reimplementation of
our horribly broken legacy vgic implementation.  The two implementations
will live side-by-side (with the new being the configured default) for
one kernel release and then we'll remove the legacy one.

Also fixes a non-critical issue with virtual abort injection to guests.

The following changes since commit 06485053244480f5f403d8f89b8617bd7d549113:

  kvm: arm64: Enable hardware updates of the Access Flag for Stage 2 page tables (2016-05-09 22:23:08 +0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git tags/kvm-arm-for-4-7-take2

for you to fetch changes up to 35a2d58588f0992627e74b447ccab21570544c86:

  KVM: arm/arm64: vgic-new: Synchronize changes to active state (2016-05-20 16:26:38 +0200)


Thanks,
-Christoffer


Andre Przywara (29):
      KVM: arm/arm64: vgic: streamline vgic_update_irq_pending() interface
      KVM: arm/arm64: vgic: avoid map in kvm_vgic_inject_mapped_irq()
      KVM: arm/arm64: vgic: avoid map in kvm_vgic_map_is_active()
      KVM: arm/arm64: vgic: avoid map in kvm_vgic_unmap_phys_irq()
      KVM: arm/arm64: arch_timer: Remove irq_phys_map
      KVM: arm/arm64: vgic: Remove irq_phys_map from interface
      KVM: arm/arm64: pmu: abstract access to number of SPIs
      KVM: arm/arm64: move GICv2 emulation defines into arm-gic-v3.h
      KVM: arm/arm64: vgic-new: Add GICv2 MMIO handling framework
      KVM: arm/arm64: vgic-new: Add ENABLE registers handlers
      KVM: arm/arm64: vgic-new: Add PENDING registers handlers
      KVM: arm/arm64: vgic-new: Add ACTIVE registers handlers
      KVM: arm/arm64: vgic-new: Add PRIORITY registers handlers
      KVM: arm/arm64: vgic-new: Add CONFIG registers handlers
      KVM: arm/arm64: vgic-new: Add TARGET registers handlers
      KVM: arm/arm64: vgic-new: Add SGIR register handler
      KVM: arm/arm64: vgic-new: Add SGIPENDR register handlers
      KVM: arm/arm64: vgic-new: Add GICv3 MMIO handling framework
      KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR, TYPER handlers
      KVM: arm/arm64: vgic-new: Add GICv3 redistributor IIDR and TYPER handler
      KVM: arm/arm64: vgic-new: Add GICv3 IDREGS register handler
      KVM: arm/arm64: vgic-new: Add GICv3 IROUTER register handlers
      KVM: arm/arm64: vgic-new: Add GICv3 SGI system register trap handler
      KVM: arm/arm64: vgic-new: Add userland access to VGIC dist registers
      KVM: arm/arm64: vgic-new: Add GICH_VMCR accessors
      KVM: arm/arm64: vgic-new: Add userland GIC CPU interface access
      KVM: arm/arm64: vgic-new: Wire up irqfd injection
      KVM: arm/arm64: vgic-new: implement mapped IRQ handling
      KVM: arm/arm64: vgic-new: enable build

Christoffer Dall (12):
      KVM: arm/arm64: Remove the IRQ field from struct irq_phys_map
      KVM: arm/arm64: Move timer IRQ map to latest possible time
      KVM: arm/arm64: Get rid of vgic_cpu->nr_lr
      KVM: arm/arm64: Fix MMIO emulation data handling
      KVM: arm/arm64: Export mmio_read/write_bus
      KVM: arm/arm64: Provide functionality to pause and resume a guest
      KVM: arm/arm64: vgic-new: Add data structure definitions
      KVM: arm/arm64: vgic-new: Add acccessor to new struct vgic_irq instance
      KVM: arm/arm64: vgic-new: Implement virtual IRQ injection
      KVM: arm/arm64: vgic-new: Add IRQ sorting
      KVM: arm/arm64: vgic-new: Export register access interface
      KVM: arm/arm64: vgic-new: Synchronize changes to active state

Eric Auger (12):
      KVM: arm/arm64: vgic-new: Implement kvm_vgic_vcpu_pending_irq
      KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM device ops registration
      KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_NR_IRQS
      KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_CTRL
      KVM: arm/arm64: vgic-new: vgic_kvm_device: implement kvm_vgic_addr
      KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_ADDR
      KVM: arm/arm64: vgic-new: vgic_kvm_device: access to VGIC registers
      KVM: arm/arm64: vgic-new: vgic_init: implement kvm_vgic_hyp_init
      KVM: arm/arm64: vgic-new: vgic_init: implement vgic_create
      KVM: arm/arm64: vgic-new: vgic_init: implement vgic_init
      KVM: arm/arm64: vgic-new: vgic_init: implement map_resources
      KVM: arm/arm64: vgic-new: Add vgic_v2/v3_enable

Marc Zyngier (5):
      KVM: arm/arm64: vgic-new: Add IRQ sync/flush framework
      KVM: arm/arm64: vgic-new: Add GICv2 world switch backend
      KVM: arm/arm64: vgic-new: Add GICv3 world switch backend
      KVM: arm/arm64: vgic-new: Add MMIO handling framework
      KVM: arm/arm64: vgic-new: Add CTLR, TYPER and IIDR handlers

Matt Evans (1):
      kvm: arm64: Fix EC field in inject_abt64

 arch/arm/include/asm/kvm_host.h     |   6 +
 arch/arm/include/asm/kvm_mmio.h     |   3 +
 arch/arm/kvm/Kconfig                |   7 +
 arch/arm/kvm/Makefile               |  11 +
 arch/arm/kvm/arm.c                  |  37 ++-
 arch/arm/kvm/mmio.c                 |  24 +-
 arch/arm64/include/asm/kvm_host.h   |   6 +
 arch/arm64/include/asm/kvm_mmio.h   |   3 +
 arch/arm64/kvm/Kconfig              |   7 +
 arch/arm64/kvm/Makefile             |  12 +
 arch/arm64/kvm/inject_fault.c       |   2 +-
 include/kvm/arm_arch_timer.h        |  11 +-
 include/kvm/arm_vgic.h              |  20 +-
 include/kvm/vgic/vgic.h             | 246 ++++++++++++++
 include/linux/irqchip/arm-gic-v3.h  |   6 +
 include/linux/irqchip/arm-gic.h     |   2 +
 virt/kvm/arm/arch_timer.c           |  68 ++--
 virt/kvm/arm/hyp/timer-sr.c         |   5 +-
 virt/kvm/arm/hyp/vgic-v2-sr.c       |  17 +-
 virt/kvm/arm/pmu.c                  |  25 +-
 virt/kvm/arm/vgic-v2.c              |   4 +-
 virt/kvm/arm/vgic-v3.c              |   8 +-
 virt/kvm/arm/vgic.c                 |  86 ++---
 virt/kvm/arm/vgic/vgic-init.c       | 452 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-irqfd.c      |  52 +++
 virt/kvm/arm/vgic/vgic-kvm-device.c | 431 +++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 446 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio-v3.c    | 455 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c       | 526 ++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h       | 150 +++++++++
 virt/kvm/arm/vgic/vgic-v2.c         | 352 ++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c         | 330 +++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c            | 619 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            | 131 ++++++++
 34 files changed, 4404 insertions(+), 156 deletions(-)
 create mode 100644 include/kvm/vgic/vgic.h
 create mode 100644 virt/kvm/arm/vgic/vgic-init.c
 create mode 100644 virt/kvm/arm/vgic/vgic-irqfd.c
 create mode 100644 virt/kvm/arm/vgic/vgic-kvm-device.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v2.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h
 create mode 100644 virt/kvm/arm/vgic/vgic-v2.c
 create mode 100644 virt/kvm/arm/vgic/vgic-v3.c
 create mode 100644 virt/kvm/arm/vgic/vgic.c
 create mode 100644 virt/kvm/arm/vgic/vgic.h


From christoffer.dall at linaro.org  Tue May 24 02:08:55 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:08:55 +0200
Subject: [PULL 01/59] kvm: arm64: Fix EC field in inject_abt64
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-2-git-send-email-christoffer.dall@linaro.org>

From: Matt Evans <matt.evans at arm.com>

The EC field of the constructed ESR is conditionally modified by ORing in
ESR_ELx_EC_DABT_LOW for a data abort.  However, ESR_ELx_EC_SHIFT is missing
from this condition.

Signed-off-by: Matt Evans <matt.evans at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Cc: <stable at vger.kernel.org>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 arch/arm64/kvm/inject_fault.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index 4d1ac81..e9e0e6d 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -162,7 +162,7 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
 		esr |= (ESR_ELx_EC_IABT_CUR << ESR_ELx_EC_SHIFT);
 
 	if (!is_iabt)
-		esr |= ESR_ELx_EC_DABT_LOW;
+		esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
 
 	vcpu_sys_reg(vcpu, ESR_EL1) = esr | ESR_ELx_FSC_EXTABT;
 }
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:08:58 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:08:58 +0200
Subject: [PULL 04/59] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_map_is_active()
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-5-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

For getting the active state of a mapped IRQ, we actually only need
the virtual IRQ number, not the pointer to the mapping entry.
Pass the virtual IRQ number from the arch timer to the VGIC directly.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/arm_vgic.h    | 2 +-
 virt/kvm/arm/arch_timer.c | 6 ++----
 virt/kvm/arm/vgic.c       | 6 +++---
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index e22f015..9830232 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -348,7 +348,7 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 					   int virt_irq, int irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index a9c6c1c..37f82c1 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -274,10 +274,8 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* to ensure that hardware interrupts from the timer triggers a guest
 	* exit.
 	*/
-	if (timer->irq.level || kvm_vgic_map_is_active(vcpu, timer->map))
-		phys_active = true;
-	else
-		phys_active = false;
+	phys_active = timer->irq.level ||
+			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
 
 	/*
 	 * We want to avoid hitting the (re)distributor as much as
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 81c557c..2fd43a6 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1102,18 +1102,18 @@ static bool dist_active_irq(struct kvm_vcpu *vcpu)
 	return test_bit(vcpu->vcpu_id, dist->irq_active_on_cpu);
 }
 
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map)
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	int i;
 
 	for (i = 0; i < vcpu->arch.vgic_cpu.nr_lr; i++) {
 		struct vgic_lr vlr = vgic_get_lr(vcpu, i);
 
-		if (vlr.irq == map->virt_irq && vlr.state & LR_STATE_ACTIVE)
+		if (vlr.irq == virt_irq && vlr.state & LR_STATE_ACTIVE)
 			return true;
 	}
 
-	return vgic_irq_is_active(vcpu, map->virt_irq);
+	return vgic_irq_is_active(vcpu, virt_irq);
 }
 
 /*
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:08:57 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:08:57 +0200
Subject: [PULL 03/59] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_inject_mapped_irq()
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-4-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

When we want to inject a hardware mapped IRQ into a guest, we actually
only need the virtual IRQ number from the irq_phys_map.
So let's pass this number directly from the arch timer to the VGIC
to avoid using the map as a parameter.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/arm_vgic.h    | 2 +-
 virt/kvm/arm/arch_timer.c | 2 +-
 virt/kvm/arm/vgic.c       | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index be6037a..e22f015 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -342,7 +342,7 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 			bool level);
 int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
-			       struct irq_phys_map *map, bool level);
+			       unsigned int virt_irq, bool level);
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 409db33..a9c6c1c 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -177,7 +177,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
 				   timer->irq.level);
 	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->map,
+					 timer->map->virt_irq,
 					 timer->irq.level);
 	WARN_ON(ret);
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index f6c6172..81c557c 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1666,7 +1666,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
  * kvm_vgic_inject_mapped_irq - Inject a physically mapped IRQ to the vgic
  * @kvm:     The VM structure pointer
  * @cpuid:   The CPU for PPIs
- * @map:     Pointer to a irq_phys_map structure describing the mapping
+ * @virt_irq: The virtual IRQ to be injected
  * @level:   Edge-triggered:  true:  to trigger the interrupt
  *			      false: to ignore the call
  *	     Level-sensitive  true:  raise the input signal
@@ -1677,7 +1677,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
  * being HIGH and 0 being LOW and all devices being active-HIGH.
  */
 int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
-			       struct irq_phys_map *map, bool level)
+			       unsigned int virt_irq, bool level)
 {
 	int ret;
 
@@ -1685,7 +1685,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 	if (ret)
 		return ret;
 
-	return vgic_update_irq_pending(kvm, cpuid, map->virt_irq, level);
+	return vgic_update_irq_pending(kvm, cpuid, virt_irq, level);
 }
 
 static irqreturn_t vgic_maintenance_handler(int irq, void *data)
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:08:59 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:08:59 +0200
Subject: [PULL 05/59] KVM: arm/arm64: vgic: avoid map in
 kvm_vgic_unmap_phys_irq()
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-6-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

kvm_vgic_unmap_phys_irq() only needs the virtual IRQ number, so let's
just pass that between the arch timer and the VGIC to get rid of
the irq_phys_map pointer.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/arm_vgic.h    |  2 +-
 virt/kvm/arm/arch_timer.c |  2 +-
 virt/kvm/arm/vgic.c       | 11 ++++-------
 3 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 9830232..c7bb184 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -347,7 +347,7 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 					   int virt_irq, int irq);
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 37f82c1..962b442 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -486,7 +486,7 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 
 	timer_disarm(timer);
 	if (timer->map)
-		kvm_vgic_unmap_phys_irq(vcpu, timer->map);
+		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
 }
 
 void kvm_timer_enable(struct kvm *kvm)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 2fd43a6..06abd59 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1812,25 +1812,22 @@ static void vgic_free_phys_irq_map_rcu(struct rcu_head *rcu)
 /**
  * kvm_vgic_unmap_phys_irq - Remove a virtual to physical IRQ mapping
  * @vcpu: The VCPU pointer
- * @map: The pointer to a mapping obtained through kvm_vgic_map_phys_irq
+ * @virt_irq: The virtual IRQ number to be unmapped
  *
  * Remove an existing mapping between virtual and physical interrupts.
  */
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map)
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct irq_phys_map_entry *entry;
 	struct list_head *root;
 
-	if (!map)
-		return -EINVAL;
-
-	root = vgic_get_irq_phys_map_list(vcpu, map->virt_irq);
+	root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 
 	spin_lock(&dist->irq_phys_map_lock);
 
 	list_for_each_entry(entry, root, entry) {
-		if (&entry->map == map) {
+		if (entry->map.virt_irq == virt_irq) {
 			list_del_rcu(&entry->entry);
 			call_rcu(&entry->rcu, vgic_free_phys_irq_map_rcu);
 			break;
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:04 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:04 +0200
Subject: [PULL 10/59] KVM: arm/arm64: Get rid of vgic_cpu->nr_lr
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-11-git-send-email-christoffer.dall@linaro.org>

The number of list registers is a property of the underlying system, not
of emulated VGIC CPU interface.

As we are about to move this variable to global state in the new vgic
for clarity, move it from the legacy implementation as well to make the
merge of the new code easier.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Andre Przywara <andre.przywara at arm.com>
---
 include/kvm/arm_vgic.h        |  3 ---
 virt/kvm/arm/hyp/vgic-v2-sr.c | 12 +++++++-----
 virt/kvm/arm/vgic-v2.c        |  4 +++-
 virt/kvm/arm/vgic.c           | 12 ++----------
 4 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 3e17fb4..67a6637 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -304,9 +304,6 @@ struct vgic_cpu {
 	unsigned long   *active_shared;
 	unsigned long   *pend_act_shared;
 
-	/* Number of list registers on this CPU */
-	int		nr_lr;
-
 	/* CPU vif control registers for world switch */
 	union {
 		struct vgic_v2_cpu_if	vgic_v2;
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index 674bdf8..caac41f 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -21,11 +21,13 @@
 
 #include <asm/kvm_hyp.h>
 
+extern struct vgic_params vgic_v2_params;
+
 static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 					    void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	u32 eisr0, eisr1;
 	int i;
 	bool expect_mi;
@@ -67,7 +69,7 @@ static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	u32 elrsr0, elrsr1;
 
 	elrsr0 = readl_relaxed(base + GICH_ELRSR0);
@@ -86,7 +88,7 @@ static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
 static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
 {
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-	int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
 	int i;
 
 	for (i = 0; i < nr_lr; i++) {
@@ -141,13 +143,13 @@ void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
 	struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
 	struct vgic_dist *vgic = &kvm->arch.vgic;
 	void __iomem *base = kern_hyp_va(vgic->vctrl_base);
-	int i, nr_lr;
+	int nr_lr = (kern_hyp_va(&vgic_v2_params))->nr_lr;
+	int i;
 	u64 live_lrs = 0;
 
 	if (!base)
 		return;
 
-	nr_lr = vcpu->arch.vgic_cpu.nr_lr;
 
 	for (i = 0; i < nr_lr; i++)
 		if (cpu_if->vgic_lr[i] & GICH_LR_STATE)
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
index 7e826c9..334cd7a 100644
--- a/virt/kvm/arm/vgic-v2.c
+++ b/virt/kvm/arm/vgic-v2.c
@@ -171,7 +171,7 @@ static const struct vgic_ops vgic_v2_ops = {
 	.enable			= vgic_v2_enable,
 };
 
-static struct vgic_params vgic_v2_params;
+struct vgic_params __section(.hyp.text) vgic_v2_params;
 
 static void vgic_cpu_init_lrs(void *params)
 {
@@ -201,6 +201,8 @@ int vgic_v2_probe(const struct gic_kvm_info *gic_kvm_info,
 	const struct resource *vctrl_res = &gic_kvm_info->vctrl;
 	const struct resource *vcpu_res = &gic_kvm_info->vcpu;
 
+	memset(vgic, 0, sizeof(*vgic));
+
 	if (!gic_kvm_info->maint_irq) {
 		kvm_err("error getting vgic maintenance irq\n");
 		ret = -ENXIO;
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 91d42a8..f76bb64 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -690,12 +690,11 @@ bool vgic_handle_cfg_reg(u32 *reg, struct kvm_exit_mmio *mmio,
  */
 void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
 {
-	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
 	u64 elrsr = vgic_get_elrsr(vcpu);
 	unsigned long *elrsr_ptr = u64_to_bitmask(&elrsr);
 	int i;
 
-	for_each_clear_bit(i, elrsr_ptr, vgic_cpu->nr_lr) {
+	for_each_clear_bit(i, elrsr_ptr, vgic->nr_lr) {
 		struct vgic_lr lr = vgic_get_lr(vcpu, i);
 
 		/*
@@ -1106,7 +1105,7 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
 {
 	int i;
 
-	for (i = 0; i < vcpu->arch.vgic_cpu.nr_lr; i++) {
+	for (i = 0; i < vgic->nr_lr; i++) {
 		struct vgic_lr vlr = vgic_get_lr(vcpu, i);
 
 		if (vlr.irq == virt_irq && vlr.state & LR_STATE_ACTIVE)
@@ -1866,13 +1865,6 @@ static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
 		return -ENOMEM;
 	}
 
-	/*
-	 * Store the number of LRs per vcpu, so we don't have to go
-	 * all the way to the distributor structure to find out. Only
-	 * assembly code should use this one.
-	 */
-	vgic_cpu->nr_lr = vgic->nr_lr;
-
 	return 0;
 }
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:01 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:01 +0200
Subject: [PULL 07/59] KVM: arm/arm64: arch_timer: Remove irq_phys_map
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-8-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

Now that the interface between the arch timer and the VGIC does not
require passing the irq_phys_map entry pointer anymore, let's remove
it from the virtual arch timer and use the virtual IRQ number instead
directly.
The remaining pointer returned by kvm_vgic_map_phys_irq() will be
removed in the following patch.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/arm_arch_timer.h |  3 ---
 virt/kvm/arm/arch_timer.c    | 10 ++++------
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index b651aed..a47b7de 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -53,9 +53,6 @@ struct arch_timer_cpu {
 	/* Timer IRQ */
 	struct kvm_irq_level		irq;
 
-	/* VGIC mapping */
-	struct irq_phys_map		*map;
-
 	/* Active IRQ state caching */
 	bool				active_cleared_last;
 };
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index e45895a..458d4d8 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -175,10 +175,10 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 
 	timer->active_cleared_last = false;
 	timer->irq.level = new_level;
-	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
+	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
 				   timer->irq.level);
 	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->map->virt_irq,
+					 timer->irq.irq,
 					 timer->irq.level);
 	WARN_ON(ret);
 }
@@ -276,7 +276,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* exit.
 	*/
 	phys_active = timer->irq.level ||
-			kvm_vgic_map_is_active(vcpu, timer->map->virt_irq);
+			kvm_vgic_map_is_active(vcpu, timer->irq.irq);
 
 	/*
 	 * We want to avoid hitting the (re)distributor as much as
@@ -378,7 +378,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	if (WARN_ON(IS_ERR(map)))
 		return PTR_ERR(map);
 
-	timer->map = map;
 	return 0;
 }
 
@@ -504,8 +503,7 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 
 	timer_disarm(timer);
-	if (timer->map)
-		kvm_vgic_unmap_phys_irq(vcpu, timer->map->virt_irq);
+	kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq);
 }
 
 void kvm_timer_enable(struct kvm *kvm)
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:00 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:00 +0200
Subject: [PULL 06/59] KVM: arm/arm64: Remove the IRQ field from struct
 irq_phys_map
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-7-git-send-email-christoffer.dall@linaro.org>

The communication of a Linux IRQ number from outside the VGIC to the
vgic was a leftover from the day when the vgic code cared about how a
particular device injects virtual interrupts mapped to a physical
interrupt.

We can safely remove this notion, leaving all physical IRQ handling to
be done in the device driver (the arch timer in this case), which makes
room for a saner API for the new VGIC.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 include/kvm/arm_vgic.h    |  3 +--
 virt/kvm/arm/arch_timer.c | 23 +++++++++++++++++++++--
 virt/kvm/arm/vgic.c       | 28 ++++++----------------------
 3 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index c7bb184..9ad7625 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -158,7 +158,6 @@ struct vgic_io_device {
 struct irq_phys_map {
 	u32			virt_irq;
 	u32			phys_irq;
-	u32			irq;
 };
 
 struct irq_phys_map_entry {
@@ -346,7 +345,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int irq);
+					   int virt_irq, int phys_irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 962b442..e45895a 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -20,6 +20,7 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <clocksource/arm_arch_timer.h>
 #include <asm/arch_timer.h>
@@ -300,7 +301,7 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	if (timer->active_cleared_last && !phys_active)
 		return;
 
-	ret = irq_set_irqchip_state(timer->map->irq,
+	ret = irq_set_irqchip_state(host_vtimer_irq,
 				    IRQCHIP_STATE_ACTIVE,
 				    phys_active);
 	WARN_ON(ret);
@@ -333,6 +334,9 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 	struct irq_phys_map *map;
+	struct irq_desc *desc;
+	struct irq_data *data;
+	int phys_irq;
 
 	/*
 	 * The vcpu timer irq number cannot be determined in
@@ -352,10 +356,25 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	kvm_timer_update_state(vcpu);
 
 	/*
+	 * Find the physical IRQ number corresponding to the host_vtimer_irq
+	 */
+	desc = irq_to_desc(host_vtimer_irq);
+	if (!desc) {
+		kvm_err("%s: no interrupt descriptor\n", __func__);
+		return -EINVAL;
+	}
+
+	data = irq_desc_get_irq_data(desc);
+	while (data->parent_data)
+		data = data->parent_data;
+
+	phys_irq = data->hwirq;
+
+	/*
 	 * Tell the VGIC that the virtual interrupt is tied to a
 	 * physical interrupt. We do that once per VCPU.
 	 */
-	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, host_vtimer_irq);
+	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
 	if (WARN_ON(IS_ERR(map)))
 		return PTR_ERR(map);
 
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 06abd59..a7e496a 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1711,38 +1711,24 @@ static struct list_head *vgic_get_irq_phys_map_list(struct kvm_vcpu *vcpu,
 /**
  * kvm_vgic_map_phys_irq - map a virtual IRQ to a physical IRQ
  * @vcpu: The VCPU pointer
- * @virt_irq: The virtual irq number
- * @irq: The Linux IRQ number
+ * @virt_irq: The virtual IRQ number for the guest
+ * @phys_irq: The hardware IRQ number of the host
  *
  * Establish a mapping between a guest visible irq (@virt_irq) and a
- * Linux irq (@irq). On injection, @virt_irq will be associated with
- * the physical interrupt represented by @irq. This mapping can be
+ * hardware irq (@phys_irq). On injection, @virt_irq will be associated with
+ * the physical interrupt represented by @phys_irq. This mapping can be
  * established multiple times as long as the parameters are the same.
  *
  * Returns a valid pointer on success, and an error pointer otherwise
  */
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int irq)
+					   int virt_irq, int phys_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct list_head *root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 	struct irq_phys_map *map;
 	struct irq_phys_map_entry *entry;
-	struct irq_desc *desc;
-	struct irq_data *data;
-	int phys_irq;
 
-	desc = irq_to_desc(irq);
-	if (!desc) {
-		kvm_err("%s: no interrupt descriptor\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
-
-	data = irq_desc_get_irq_data(desc);
-	while (data->parent_data)
-		data = data->parent_data;
-
-	phys_irq = data->hwirq;
 
 	/* Create a new mapping */
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
@@ -1755,8 +1741,7 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	map = vgic_irq_map_search(vcpu, virt_irq);
 	if (map) {
 		/* Make sure this mapping matches */
-		if (map->phys_irq != phys_irq	||
-		    map->irq      != irq)
+		if (map->phys_irq != phys_irq)
 			map = ERR_PTR(-EINVAL);
 
 		/* Found an existing, valid mapping */
@@ -1766,7 +1751,6 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	map           = &entry->map;
 	map->virt_irq = virt_irq;
 	map->phys_irq = phys_irq;
-	map->irq      = irq;
 
 	list_add_tail_rcu(&entry->entry, root);
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:07 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:07 +0200
Subject: [PULL 13/59] KVM: arm/arm64: pmu: abstract access to number of SPIs
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-14-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

Currently the PMU uses a member of the struct vgic_dist directly,
which not only breaks abstraction, but will fail with the new VGIC.
Abstract this access in the VGIC header file and refactor the validity
check in the PMU code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 include/kvm/arm_vgic.h |  2 ++
 virt/kvm/arm/pmu.c     | 25 ++++++++++++++-----------
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 67a6637..ade7005 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -348,6 +348,8 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(!!((k)->arch.vgic.nr_cpus))
 #define vgic_ready(k)		((k)->arch.vgic.ready)
+#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
+				 ((i) < (k)->arch.vgic.nr_irqs))
 
 int vgic_v2_probe(const struct gic_kvm_info *gic_kvm_info,
 		  const struct vgic_ops **ops,
diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
index 575c7aa..a027569 100644
--- a/virt/kvm/arm/pmu.c
+++ b/virt/kvm/arm/pmu.c
@@ -436,7 +436,14 @@ static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
-static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
+#define irq_is_ppi(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS)
+
+/*
+ * For one VM the interrupt type must be same for each vcpu.
+ * As a PPI, the interrupt number is the same for all vcpus,
+ * while as an SPI it must be a separate number per vcpu.
+ */
+static bool pmu_irq_is_valid(struct kvm *kvm, int irq)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
@@ -445,7 +452,7 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
 		if (!kvm_arm_pmu_irq_initialized(vcpu))
 			continue;
 
-		if (is_ppi) {
+		if (irq_is_ppi(irq)) {
 			if (vcpu->arch.pmu.irq_num != irq)
 				return false;
 		} else {
@@ -457,7 +464,6 @@ static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
 	return true;
 }
 
-
 int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 {
 	switch (attr->attr) {
@@ -471,14 +477,11 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 		if (get_user(irq, uaddr))
 			return -EFAULT;
 
-		/*
-		 * The PMU overflow interrupt could be a PPI or SPI, but for one
-		 * VM the interrupt type must be same for each vcpu. As a PPI,
-		 * the interrupt number is the same for all vcpus, while as an
-		 * SPI it must be a separate number per vcpu.
-		 */
-		if (irq < VGIC_NR_SGIS || irq >= vcpu->kvm->arch.vgic.nr_irqs ||
-		    !irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
+		/* The PMU overflow interrupt can be a PPI or a valid SPI. */
+		if (!(irq_is_ppi(irq) || vgic_valid_spi(vcpu->kvm, irq)))
+			return -EINVAL;
+
+		if (!pmu_irq_is_valid(vcpu->kvm, irq))
 			return -EINVAL;
 
 		if (kvm_arm_pmu_irq_initialized(vcpu))
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:02 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:02 +0200
Subject: [PULL 08/59] KVM: arm/arm64: vgic: Remove irq_phys_map from interface
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-9-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

Now that the virtual arch timer does not care about the irq_phys_map
anymore, let's rework kvm_vgic_map_phys_irq() to return an error
value instead. Any reference to that mapping can later be done by
passing the correct combination of VCPU and virtual IRQ number.
This makes the irq_phys_map handling completely private to the
VGIC code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/arm_vgic.h    |  3 +--
 virt/kvm/arm/arch_timer.c |  7 +------
 virt/kvm/arm/vgic.c       | 15 +++++++--------
 3 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 9ad7625..3e17fb4 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -344,8 +344,7 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
 			       unsigned int virt_irq, bool level);
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
-struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int phys_irq);
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, int virt_irq, int phys_irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 458d4d8..3232105 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -333,7 +333,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 			 const struct kvm_irq_level *irq)
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-	struct irq_phys_map *map;
 	struct irq_desc *desc;
 	struct irq_data *data;
 	int phys_irq;
@@ -374,11 +373,7 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	 * Tell the VGIC that the virtual interrupt is tied to a
 	 * physical interrupt. We do that once per VCPU.
 	 */
-	map = kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
-	if (WARN_ON(IS_ERR(map)))
-		return PTR_ERR(map);
-
-	return 0;
+	return kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
 }
 
 void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index a7e496a..91d42a8 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1719,21 +1719,20 @@ static struct list_head *vgic_get_irq_phys_map_list(struct kvm_vcpu *vcpu,
  * the physical interrupt represented by @phys_irq. This mapping can be
  * established multiple times as long as the parameters are the same.
  *
- * Returns a valid pointer on success, and an error pointer otherwise
+ * Returns 0 on success or an error value otherwise.
  */
-struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
-					   int virt_irq, int phys_irq)
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, int virt_irq, int phys_irq)
 {
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct list_head *root = vgic_get_irq_phys_map_list(vcpu, virt_irq);
 	struct irq_phys_map *map;
 	struct irq_phys_map_entry *entry;
-
+	int ret = 0;
 
 	/* Create a new mapping */
 	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	spin_lock(&dist->irq_phys_map_lock);
 
@@ -1742,7 +1741,7 @@ struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
 	if (map) {
 		/* Make sure this mapping matches */
 		if (map->phys_irq != phys_irq)
-			map = ERR_PTR(-EINVAL);
+			ret = -EINVAL;
 
 		/* Found an existing, valid mapping */
 		goto out;
@@ -1758,9 +1757,9 @@ out:
 	spin_unlock(&dist->irq_phys_map_lock);
 	/* If we've found a hit in the existing list, free the useless
 	 * entry */
-	if (IS_ERR(map) || map != &entry->map)
+	if (ret || map != &entry->map)
 		kfree(entry);
-	return map;
+	return ret;
 }
 
 static struct irq_phys_map *vgic_irq_map_search(struct kvm_vcpu *vcpu,
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:03 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:03 +0200
Subject: [PULL 09/59] KVM: arm/arm64: Move timer IRQ map to latest possible
 time
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-10-git-send-email-christoffer.dall@linaro.org>

We are about to modify the VGIC to allocate all data structures
dynamically and store mapped IRQ information on a per-IRQ struct, which
is indeed allocated dynamically at init time.

Therefore, we cannot record the mapped IRQ info from the timer at timer
reset time like it's done now, because VCPU reset happens before timer
init.

A possible later time to do this is on the first run of a per VCPU, it
just requires us to move the enable state to be a per-VCPU state and do
the lookup of the physical IRQ number when we are about to run the VCPU.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/kvm/arm.c           |  6 ++--
 include/kvm/arm_arch_timer.h |  8 +++---
 virt/kvm/arm/arch_timer.c    | 66 +++++++++++++++++++++++++-------------------
 virt/kvm/arm/hyp/timer-sr.c  |  5 ++--
 4 files changed, 47 insertions(+), 38 deletions(-)

diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index be4b639..ceb9345 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -459,7 +459,7 @@ static void update_vttbr(struct kvm *kvm)
 static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
-	int ret;
+	int ret = 0;
 
 	if (likely(vcpu->arch.has_run_once))
 		return 0;
@@ -482,9 +482,9 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 	 * interrupts from the virtual timer with a userspace gic.
 	 */
 	if (irqchip_in_kernel(kvm) && vgic_initialized(kvm))
-		kvm_timer_enable(kvm);
+		ret = kvm_timer_enable(vcpu);
 
-	return 0;
+	return ret;
 }
 
 bool kvm_arch_intc_initialized(struct kvm *kvm)
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index a47b7de..dda39d8 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -24,9 +24,6 @@
 #include <linux/workqueue.h>
 
 struct arch_timer_kvm {
-	/* Is the timer enabled */
-	bool			enabled;
-
 	/* Virtual offset */
 	cycle_t			cntvoff;
 };
@@ -55,10 +52,13 @@ struct arch_timer_cpu {
 
 	/* Active IRQ state caching */
 	bool				active_cleared_last;
+
+	/* Is the timer enabled */
+	bool			enabled;
 };
 
 int kvm_timer_hyp_init(void);
-void kvm_timer_enable(struct kvm *kvm);
+int kvm_timer_enable(struct kvm_vcpu *vcpu);
 void kvm_timer_init(struct kvm *kvm);
 int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 			 const struct kvm_irq_level *irq);
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 3232105..e2d5b6f 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -197,7 +197,7 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
 	 * because the guest would never see the interrupt.  Instead wait
 	 * until we call this function from kvm_timer_flush_hwstate.
 	 */
-	if (!vgic_initialized(vcpu->kvm))
+	if (!vgic_initialized(vcpu->kvm) || !timer->enabled)
 		return -ENODEV;
 
 	if (kvm_timer_should_fire(vcpu) != timer->irq.level)
@@ -333,9 +333,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 			 const struct kvm_irq_level *irq)
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-	struct irq_desc *desc;
-	struct irq_data *data;
-	int phys_irq;
 
 	/*
 	 * The vcpu timer irq number cannot be determined in
@@ -354,26 +351,7 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 	timer->cntv_ctl = 0;
 	kvm_timer_update_state(vcpu);
 
-	/*
-	 * Find the physical IRQ number corresponding to the host_vtimer_irq
-	 */
-	desc = irq_to_desc(host_vtimer_irq);
-	if (!desc) {
-		kvm_err("%s: no interrupt descriptor\n", __func__);
-		return -EINVAL;
-	}
-
-	data = irq_desc_get_irq_data(desc);
-	while (data->parent_data)
-		data = data->parent_data;
-
-	phys_irq = data->hwirq;
-
-	/*
-	 * Tell the VGIC that the virtual interrupt is tied to a
-	 * physical interrupt. We do that once per VCPU.
-	 */
-	return kvm_vgic_map_phys_irq(vcpu, irq->irq, phys_irq);
+	return 0;
 }
 
 void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
@@ -501,10 +479,40 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 	kvm_vgic_unmap_phys_irq(vcpu, timer->irq.irq);
 }
 
-void kvm_timer_enable(struct kvm *kvm)
+int kvm_timer_enable(struct kvm_vcpu *vcpu)
 {
-	if (kvm->arch.timer.enabled)
-		return;
+	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+	struct irq_desc *desc;
+	struct irq_data *data;
+	int phys_irq;
+	int ret;
+
+	if (timer->enabled)
+		return 0;
+
+	/*
+	 * Find the physical IRQ number corresponding to the host_vtimer_irq
+	 */
+	desc = irq_to_desc(host_vtimer_irq);
+	if (!desc) {
+		kvm_err("%s: no interrupt descriptor\n", __func__);
+		return -EINVAL;
+	}
+
+	data = irq_desc_get_irq_data(desc);
+	while (data->parent_data)
+		data = data->parent_data;
+
+	phys_irq = data->hwirq;
+
+	/*
+	 * Tell the VGIC that the virtual interrupt is tied to a
+	 * physical interrupt. We do that once per VCPU.
+	 */
+	ret = kvm_vgic_map_phys_irq(vcpu, timer->irq.irq, phys_irq);
+	if (ret)
+		return ret;
+
 
 	/*
 	 * There is a potential race here between VCPUs starting for the first
@@ -515,7 +523,9 @@ void kvm_timer_enable(struct kvm *kvm)
 	 * the arch timers are enabled.
 	 */
 	if (timecounter && wqueue)
-		kvm->arch.timer.enabled = 1;
+		timer->enabled = 1;
+
+	return 0;
 }
 
 void kvm_timer_init(struct kvm *kvm)
diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c
index ea00d69..798866a 100644
--- a/virt/kvm/arm/hyp/timer-sr.c
+++ b/virt/kvm/arm/hyp/timer-sr.c
@@ -24,11 +24,10 @@
 /* vcpu is already in the HYP VA space */
 void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu)
 {
-	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 	u64 val;
 
-	if (kvm->arch.timer.enabled) {
+	if (timer->enabled) {
 		timer->cntv_ctl = read_sysreg_el0(cntv_ctl);
 		timer->cntv_cval = read_sysreg_el0(cntv_cval);
 	}
@@ -60,7 +59,7 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
 	val |= CNTHCTL_EL1PCTEN;
 	write_sysreg(val, cnthctl_el2);
 
-	if (kvm->arch.timer.enabled) {
+	if (timer->enabled) {
 		write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2);
 		write_sysreg_el0(timer->cntv_cval, cntv_cval);
 		isb();
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:08 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:08 +0200
Subject: [PULL 14/59] KVM: arm/arm64: Provide functionality to pause and
 resume a guest
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-15-git-send-email-christoffer.dall@linaro.org>

For some rare corner cases in our VGIC emulation later we have to stop
the guest to make sure the VGIC state is consistent.
Provide the necessary framework to pause and resume a guest.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/include/asm/kvm_host.h   |  4 ++++
 arch/arm/kvm/arm.c                | 25 +++++++++++++------------
 arch/arm64/include/asm/kvm_host.h |  4 ++++
 3 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 3850701..832be03 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -41,6 +41,8 @@
 
 #define KVM_MAX_VCPUS VGIC_V2_MAX_CPUS
 
+#define KVM_REQ_VCPU_EXIT	8
+
 u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode);
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
@@ -225,6 +227,8 @@ static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
 
 struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
+void kvm_arm_halt_guest(struct kvm *kvm);
+void kvm_arm_resume_guest(struct kvm *kvm);
 
 int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
 unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index ceb9345..e89329d 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -492,30 +492,31 @@ bool kvm_arch_intc_initialized(struct kvm *kvm)
 	return vgic_initialized(kvm);
 }
 
-static void kvm_arm_halt_guest(struct kvm *kvm) __maybe_unused;
-static void kvm_arm_resume_guest(struct kvm *kvm) __maybe_unused;
-
-static void kvm_arm_halt_guest(struct kvm *kvm)
+void kvm_arm_halt_guest(struct kvm *kvm)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
 
 	kvm_for_each_vcpu(i, vcpu, kvm)
 		vcpu->arch.pause = true;
-	force_vm_exit(cpu_all_mask);
+	kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT);
+}
+
+static void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
+{
+	struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
+
+	vcpu->arch.pause = false;
+	swake_up(wq);
 }
 
-static void kvm_arm_resume_guest(struct kvm *kvm)
+void kvm_arm_resume_guest(struct kvm *kvm)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
 
-	kvm_for_each_vcpu(i, vcpu, kvm) {
-		struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
-
-		vcpu->arch.pause = false;
-		swake_up(wq);
-	}
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_arm_resume_vcpu(vcpu);
 }
 
 static void vcpu_sleep(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 4cd4196..fa94f91 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -44,6 +44,8 @@
 
 #define KVM_VCPU_MAX_FEATURES 4
 
+#define KVM_REQ_VCPU_EXIT	8
+
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
 int kvm_arch_dev_ioctl_check_extension(long ext);
@@ -325,6 +327,8 @@ static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
 
 struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
+void kvm_arm_halt_guest(struct kvm *kvm);
+void kvm_arm_resume_guest(struct kvm *kvm);
 
 u64 __kvm_call_hyp(void *hypfn, ...);
 #define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__)
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:06 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:06 +0200
Subject: [PULL 12/59] KVM: arm/arm64: Export mmio_read/write_bus
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-13-git-send-email-christoffer.dall@linaro.org>

Rename mmio_{read,write}_bus to kvm_mmio_{read,write}_bus and export
them out of mmio.c.
This will be needed later for the new VGIC implementation.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/include/asm/kvm_mmio.h   |  3 +++
 arch/arm/kvm/mmio.c               | 10 +++++-----
 arch/arm64/include/asm/kvm_mmio.h |  3 +++
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmio.h b/arch/arm/include/asm/kvm_mmio.h
index d8e90c8..f3a7de7 100644
--- a/arch/arm/include/asm/kvm_mmio.h
+++ b/arch/arm/include/asm/kvm_mmio.h
@@ -28,6 +28,9 @@ struct kvm_decode {
 	bool sign_extend;
 };
 
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
+
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		 phys_addr_t fault_ipa);
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 0158e9e..10f80a6 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -23,7 +23,7 @@
 
 #include "trace.h"
 
-static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data)
 {
 	void *datap = NULL;
 	union {
@@ -55,7 +55,7 @@ static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
 	memcpy(buf, datap, len);
 }
 
-static unsigned long mmio_read_buf(char *buf, unsigned int len)
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len)
 {
 	unsigned long data = 0;
 	union {
@@ -66,7 +66,7 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len)
 
 	switch (len) {
 	case 1:
-		data = buf[0];
+		data = *(u8 *)buf;
 		break;
 	case 2:
 		memcpy(&tmp.hword, buf, len);
@@ -103,7 +103,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		if (len > sizeof(unsigned long))
 			return -EINVAL;
 
-		data = mmio_read_buf(run->mmio.data, len);
+		data = kvm_mmio_read_buf(run->mmio.data, len);
 
 		if (vcpu->arch.mmio_decode.sign_extend &&
 		    len < sizeof(unsigned long)) {
@@ -189,7 +189,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 					       len);
 
 		trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data);
-		mmio_write_buf(data_buf, len, data);
+		kvm_mmio_write_buf(data_buf, len, data);
 
 		ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
 				       data_buf);
diff --git a/arch/arm64/include/asm/kvm_mmio.h b/arch/arm64/include/asm/kvm_mmio.h
index fe612a9..75ea420 100644
--- a/arch/arm64/include/asm/kvm_mmio.h
+++ b/arch/arm64/include/asm/kvm_mmio.h
@@ -30,6 +30,9 @@ struct kvm_decode {
 	bool sign_extend;
 };
 
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
+
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		 phys_addr_t fault_ipa);
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:14 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:14 +0200
Subject: [PULL 20/59] KVM: arm/arm64: vgic-new: Add IRQ sync/flush framework
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-21-git-send-email-christoffer.dall@linaro.org>

From: Marc Zyngier <marc.zyngier at arm.com>

Implement the framework for syncing IRQs between our emulation and
the list registers, which represent the guest's view of IRQs.
This is done in kvm_vgic_flush_hwstate and kvm_vgic_sync_hwstate,
which gets called on guest entry and exit.
The code talking to the actual GICv2/v3 hardware is added in the
following patches.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/vgic/vgic.h  |   4 +
 virt/kvm/arm/vgic/vgic.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h |   2 +
 3 files changed, 198 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 7b6ca90..9506267 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -190,6 +190,10 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
 			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
 
+bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
+void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
+void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
+
 /**
  * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
  *
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index bce17de..08a862a 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -307,3 +307,195 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 {
 	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
 }
+
+/**
+ * vgic_prune_ap_list - Remove non-relevant interrupts from the list
+ *
+ * @vcpu: The VCPU pointer
+ *
+ * Go over the list of "interesting" interrupts, and prune those that we
+ * won't have to consider in the near future.
+ */
+static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq, *tmp;
+
+retry:
+	spin_lock(&vgic_cpu->ap_list_lock);
+
+	list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
+		struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
+
+		spin_lock(&irq->irq_lock);
+
+		BUG_ON(vcpu != irq->vcpu);
+
+		target_vcpu = vgic_target_oracle(irq);
+
+		if (!target_vcpu) {
+			/*
+			 * We don't need to process this interrupt any
+			 * further, move it off the list.
+			 */
+			list_del(&irq->ap_list);
+			irq->vcpu = NULL;
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		if (target_vcpu == vcpu) {
+			/* We're on the right CPU */
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		/* This interrupt looks like it has to be migrated. */
+
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vgic_cpu->ap_list_lock);
+
+		/*
+		 * Ensure locking order by always locking the smallest
+		 * ID first.
+		 */
+		if (vcpu->vcpu_id < target_vcpu->vcpu_id) {
+			vcpuA = vcpu;
+			vcpuB = target_vcpu;
+		} else {
+			vcpuA = target_vcpu;
+			vcpuB = vcpu;
+		}
+
+		spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+		spin_lock_nested(&vcpuB->arch.vgic_cpu.ap_list_lock,
+				 SINGLE_DEPTH_NESTING);
+		spin_lock(&irq->irq_lock);
+
+		/*
+		 * If the affinity has been preserved, move the
+		 * interrupt around. Otherwise, it means things have
+		 * changed while the interrupt was unlocked, and we
+		 * need to replay this.
+		 *
+		 * In all cases, we cannot trust the list not to have
+		 * changed, so we restart from the beginning.
+		 */
+		if (target_vcpu == vgic_target_oracle(irq)) {
+			struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;
+
+			list_del(&irq->ap_list);
+			irq->vcpu = target_vcpu;
+			list_add_tail(&irq->ap_list, &new_cpu->ap_list_head);
+		}
+
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
+		spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+		goto retry;
+	}
+
+	spin_unlock(&vgic_cpu->ap_list_lock);
+}
+
+static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+}
+
+/* Requires the irq_lock to be held. */
+static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
+				    struct vgic_irq *irq, int lr)
+{
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+}
+
+static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+}
+
+static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
+{
+}
+
+/* Requires the ap_list_lock to be held. */
+static int compute_ap_list_depth(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	int count = 0;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+		/* GICv2 SGIs can count for more than one... */
+		if (vgic_irq_is_sgi(irq->intid) && irq->source)
+			count += hweight8(irq->source);
+		else
+			count++;
+		spin_unlock(&irq->irq_lock);
+	}
+	return count;
+}
+
+/* Requires the VCPU's ap_list_lock to be held. */
+static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	int count = 0;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	if (compute_ap_list_depth(vcpu) > kvm_vgic_global_state.nr_lr) {
+		vgic_set_underflow(vcpu);
+		vgic_sort_ap_list(vcpu);
+	}
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+
+		if (unlikely(vgic_target_oracle(irq) != vcpu))
+			goto next;
+
+		/*
+		 * If we get an SGI with multiple sources, try to get
+		 * them in all at once.
+		 */
+		do {
+			vgic_populate_lr(vcpu, irq, count++);
+		} while (irq->source && count < kvm_vgic_global_state.nr_lr);
+
+next:
+		spin_unlock(&irq->irq_lock);
+
+		if (count == kvm_vgic_global_state.nr_lr)
+			break;
+	}
+
+	vcpu->arch.vgic_cpu.used_lrs = count;
+
+	/* Nuke remaining LRs */
+	for ( ; count < kvm_vgic_global_state.nr_lr; count++)
+		vgic_clear_lr(vcpu, count);
+}
+
+/* Sync back the hardware VGIC state into our emulation after a guest's run. */
+void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
+{
+	vgic_process_maintenance_interrupt(vcpu);
+	vgic_fold_lr_state(vcpu);
+	vgic_prune_ap_list(vcpu);
+}
+
+/* Flush our emulation state into the GIC hardware before entering the guest. */
+void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
+{
+	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+	vgic_flush_lr_state(vcpu);
+	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index c625767..29b96b9 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,6 +16,8 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:16 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:16 +0200
Subject: [PULL 22/59] KVM: arm/arm64: vgic-new: Add GICv3 world switch backend
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-23-git-send-email-christoffer.dall@linaro.org>

From: Marc Zyngier <marc.zyngier at arm.com>

As the GICv3 virtual interface registers differ from their GICv2
siblings, we need different handlers for processing maintenance
interrupts and reading/writing to the LRs.
Implement the respective handler functions and connect them to
existing code to be called if the host is using a GICv3.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/linux/irqchip/arm-gic-v3.h |   1 +
 virt/kvm/arm/vgic/vgic-v3.c        | 162 +++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c           |  25 ++++--
 virt/kvm/arm/vgic/vgic.h           |  29 +++++++
 4 files changed, 212 insertions(+), 5 deletions(-)
 create mode 100644 virt/kvm/arm/vgic/vgic-v3.c

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index ec938d1..35e93cf 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -275,6 +275,7 @@
 #define ICH_LR_ACTIVE_BIT		(1ULL << 63)
 #define ICH_LR_PHYS_ID_SHIFT		32
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
+#define ICH_LR_PRIORITY_SHIFT		48
 
 /* These are for GICv2 emulation only */
 #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
new file mode 100644
index 0000000..fb547da
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -0,0 +1,162 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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/irqchip/arm-gic-v3.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+
+	if (cpuif->vgic_misr & ICH_MISR_EOI) {
+		unsigned long eisr_bmap = cpuif->vgic_eisr;
+		int lr;
+
+		for_each_set_bit(lr, &eisr_bmap, kvm_vgic_global_state.nr_lr) {
+			u32 intid;
+			u64 val = cpuif->vgic_lr[lr];
+
+			if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+				intid = val & ICH_LR_VIRTUAL_ID_MASK;
+			else
+				intid = val & GICH_LR_VIRTUALID;
+
+			WARN_ON(cpuif->vgic_lr[lr] & ICH_LR_STATE);
+
+			kvm_notify_acked_irq(vcpu->kvm, 0,
+					     intid - VGIC_NR_PRIVATE_IRQS);
+		}
+
+		/*
+		 * In the next iterations of the vcpu loop, if we sync
+		 * the vgic state after flushing it, but before
+		 * entering the guest (this happens for pending
+		 * signals and vmid rollovers), then make sure we
+		 * don't pick up any old maintenance interrupts here.
+		 */
+		cpuif->vgic_eisr = 0;
+	}
+
+	cpuif->vgic_hcr &= ~ICH_HCR_UIE;
+}
+
+void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+
+	cpuif->vgic_hcr |= ICH_HCR_UIE;
+}
+
+void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+	int lr;
+
+	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
+		u64 val = cpuif->vgic_lr[lr];
+		u32 intid;
+		struct vgic_irq *irq;
+
+		if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+			intid = val & ICH_LR_VIRTUAL_ID_MASK;
+		else
+			intid = val & GICH_LR_VIRTUALID;
+		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+
+		/* Always preserve the active bit */
+		irq->active = !!(val & ICH_LR_ACTIVE_BIT);
+
+		/* Edge is the only case where we preserve the pending bit */
+		if (irq->config == VGIC_CONFIG_EDGE &&
+		    (val & ICH_LR_PENDING_BIT)) {
+			irq->pending = true;
+
+			if (vgic_irq_is_sgi(intid) &&
+			    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
+
+				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+				irq->source |= (1 << cpuid);
+			}
+		}
+
+		/* Clear soft pending state when level irqs have been acked */
+		if (irq->config == VGIC_CONFIG_LEVEL &&
+		    !(val & ICH_LR_PENDING_BIT)) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+/* Requires the irq to be locked already */
+void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
+{
+	u32 model = vcpu->kvm->arch.vgic.vgic_model;
+	u64 val = irq->intid;
+
+	if (irq->pending) {
+		val |= ICH_LR_PENDING_BIT;
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			irq->pending = false;
+
+		if (vgic_irq_is_sgi(irq->intid) &&
+		    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+			u32 src = ffs(irq->source);
+
+			BUG_ON(!src);
+			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
+			irq->source &= ~(1 << (src - 1));
+			if (irq->source)
+				irq->pending = true;
+		}
+	}
+
+	if (irq->active)
+		val |= ICH_LR_ACTIVE_BIT;
+
+	if (irq->hw) {
+		val |= ICH_LR_HW;
+		val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
+	} else {
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			val |= ICH_LR_EOI;
+	}
+
+	/*
+	 * We currently only support Group1 interrupts, which is a
+	 * known defect. This needs to be addressed at some point.
+	 */
+	if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+		val |= ICH_LR_GROUP;
+
+	val |= (u64)irq->priority << ICH_LR_PRIORITY_SHIFT;
+
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = val;
+}
+
+void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 44d2533..0bf0d20 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -400,12 +400,18 @@ retry:
 
 static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_process_maintenance(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_process_maintenance(vcpu);
+	else
+		vgic_v3_process_maintenance(vcpu);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_fold_lr_state(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_fold_lr_state(vcpu);
+	else
+		vgic_v3_fold_lr_state(vcpu);
 }
 
 /* Requires the irq_lock to be held. */
@@ -414,17 +420,26 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
 {
 	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
 
-	vgic_v2_populate_lr(vcpu, irq, lr);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_populate_lr(vcpu, irq, lr);
+	else
+		vgic_v3_populate_lr(vcpu, irq, lr);
 }
 
 static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
-	vgic_v2_clear_lr(vcpu, lr);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_clear_lr(vcpu, lr);
+	else
+		vgic_v3_clear_lr(vcpu, lr);
 }
 
 static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
 {
-	vgic_v2_set_underflow(vcpu);
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_set_underflow(vcpu);
+	else
+		vgic_v3_set_underflow(vcpu);
 }
 
 /* Requires the ap_list_lock to be held. */
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 0db490e..81b1a20 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -28,4 +28,33 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
+void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
+void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
+void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
+void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+#else
+static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+}
+
+static inline void vgic_v3_populate_lr(struct kvm_vcpu *vcpu,
+				       struct vgic_irq *irq, int lr)
+{
+}
+
+static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+}
+
+static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
+{
+}
+#endif
+
 #endif
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:15 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:15 +0200
Subject: [PULL 21/59] KVM: arm/arm64: vgic-new: Add GICv2 world switch backend
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-22-git-send-email-christoffer.dall@linaro.org>

From: Marc Zyngier <marc.zyngier at arm.com>

Processing maintenance interrupts and accessing the list registers
are dependent on the host's GIC version.
Introduce vgic-v2.c to contain GICv2 specific functions.
Implement the GICv2 specific code for syncing the emulation state
into the VGIC registers.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/linux/irqchip/arm-gic.h |   1 +
 virt/kvm/arm/vgic/vgic-v2.c     | 176 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c        |   6 ++
 virt/kvm/arm/vgic/vgic.h        |   6 ++
 4 files changed, 189 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-v2.c

diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 9c94026..be0d26f 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -76,6 +76,7 @@
 #define GICH_LR_VIRTUALID		(0x3ff << 0)
 #define GICH_LR_PHYSID_CPUID_SHIFT	(10)
 #define GICH_LR_PHYSID_CPUID		(0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
+#define GICH_LR_PRIORITY_SHIFT		23
 #define GICH_LR_STATE			(3 << 28)
 #define GICH_LR_PENDING_BIT		(1 << 28)
 #define GICH_LR_ACTIVE_BIT		(1 << 29)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
new file mode 100644
index 0000000..fb5e65c
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/irqchip/arm-gic.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+/*
+ * Call this function to convert a u64 value to an unsigned long * bitmask
+ * in a way that works on both 32-bit and 64-bit LE and BE platforms.
+ *
+ * Warning: Calling this function may modify *val.
+ */
+static unsigned long *u64_to_bitmask(u64 *val)
+{
+#if defined(CONFIG_CPU_BIG_ENDIAN) && BITS_PER_LONG == 32
+	*val = (*val >> 32) | (*val << 32);
+#endif
+	return (unsigned long *)val;
+}
+
+void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+
+	if (cpuif->vgic_misr & GICH_MISR_EOI) {
+		u64 eisr = cpuif->vgic_eisr;
+		unsigned long *eisr_bmap = u64_to_bitmask(&eisr);
+		int lr;
+
+		for_each_set_bit(lr, eisr_bmap, kvm_vgic_global_state.nr_lr) {
+			u32 intid = cpuif->vgic_lr[lr] & GICH_LR_VIRTUALID;
+
+			WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
+
+			kvm_notify_acked_irq(vcpu->kvm, 0,
+					     intid - VGIC_NR_PRIVATE_IRQS);
+		}
+	}
+
+	/* check and disable underflow maintenance IRQ */
+	cpuif->vgic_hcr &= ~GICH_HCR_UIE;
+
+	/*
+	 * In the next iterations of the vcpu loop, if we sync the
+	 * vgic state after flushing it, but before entering the guest
+	 * (this happens for pending signals and vmid rollovers), then
+	 * make sure we don't pick up any old maintenance interrupts
+	 * here.
+	 */
+	cpuif->vgic_eisr = 0;
+}
+
+void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+
+	cpuif->vgic_hcr |= GICH_HCR_UIE;
+}
+
+/*
+ * transfer the content of the LRs back into the corresponding ap_list:
+ * - active bit is transferred as is
+ * - pending bit is
+ *   - transferred as is in case of edge sensitive IRQs
+ *   - set to the line-level (resample time) for level sensitive IRQs
+ */
+void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
+{
+	struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
+	int lr;
+
+	for (lr = 0; lr < vcpu->arch.vgic_cpu.used_lrs; lr++) {
+		u32 val = cpuif->vgic_lr[lr];
+		u32 intid = val & GICH_LR_VIRTUALID;
+		struct vgic_irq *irq;
+
+		irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+
+		/* Always preserve the active bit */
+		irq->active = !!(val & GICH_LR_ACTIVE_BIT);
+
+		/* Edge is the only case where we preserve the pending bit */
+		if (irq->config == VGIC_CONFIG_EDGE &&
+		    (val & GICH_LR_PENDING_BIT)) {
+			irq->pending = true;
+
+			if (vgic_irq_is_sgi(intid)) {
+				u32 cpuid = val & GICH_LR_PHYSID_CPUID;
+
+				cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+				irq->source |= (1 << cpuid);
+			}
+		}
+
+		/* Clear soft pending state when level IRQs have been acked */
+		if (irq->config == VGIC_CONFIG_LEVEL &&
+		    !(val & GICH_LR_PENDING_BIT)) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+/*
+ * Populates the particular LR with the state of a given IRQ:
+ * - for an edge sensitive IRQ the pending state is cleared in struct vgic_irq
+ * - for a level sensitive IRQ the pending state value is unchanged;
+ *   it is dictated directly by the input level
+ *
+ * If @irq describes an SGI with multiple sources, we choose the
+ * lowest-numbered source VCPU and clear that bit in the source bitmap.
+ *
+ * The irq_lock must be held by the caller.
+ */
+void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
+{
+	u32 val = irq->intid;
+
+	if (irq->pending) {
+		val |= GICH_LR_PENDING_BIT;
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			irq->pending = false;
+
+		if (vgic_irq_is_sgi(irq->intid)) {
+			u32 src = ffs(irq->source);
+
+			BUG_ON(!src);
+			val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
+			irq->source &= ~(1 << (src - 1));
+			if (irq->source)
+				irq->pending = true;
+		}
+	}
+
+	if (irq->active)
+		val |= GICH_LR_ACTIVE_BIT;
+
+	if (irq->hw) {
+		val |= GICH_LR_HW;
+		val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
+	} else {
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			val |= GICH_LR_EOI;
+	}
+
+	/* The GICv2 LR only holds five bits of priority. */
+	val |= (irq->priority >> 3) << GICH_LR_PRIORITY_SHIFT;
+
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = val;
+}
+
+void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
+{
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 08a862a..44d2533 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -400,10 +400,12 @@ retry:
 
 static inline void vgic_process_maintenance_interrupt(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_process_maintenance(vcpu);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_fold_lr_state(vcpu);
 }
 
 /* Requires the irq_lock to be held. */
@@ -411,14 +413,18 @@ static inline void vgic_populate_lr(struct kvm_vcpu *vcpu,
 				    struct vgic_irq *irq, int lr)
 {
 	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+	vgic_v2_populate_lr(vcpu, irq, lr);
 }
 
 static inline void vgic_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
+	vgic_v2_clear_lr(vcpu, lr);
 }
 
 static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
 {
+	vgic_v2_set_underflow(vcpu);
 }
 
 /* Requires the ap_list_lock to be held. */
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 29b96b9..0db490e 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -22,4 +22,10 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
 
+void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
+void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
+void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
+void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
+void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+
 #endif
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:12 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:12 +0200
Subject: [PULL 18/59] KVM: arm/arm64: vgic-new: Implement virtual IRQ injection
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-19-git-send-email-christoffer.dall@linaro.org>

Provide a vgic_queue_irq_unlock() function which decides whether a
given IRQ needs to be queued to a VCPU's ap_list.
This should be called whenever an IRQ becomes pending or enabled,
either as a result of userspace injection, from in-kernel emulated
devices like the architected timer or from MMIO accesses to the
distributor emulation.
Also provides the necessary functions to allow userland to inject an
IRQ to a guest.
Since this is the first code that starts using our locking mechanism, we
add some (hopefully) clear documentation of our locking strategy and
requirements along with this patch.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 include/kvm/vgic/vgic.h  |   3 +
 virt/kvm/arm/vgic/vgic.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h |   1 +
 3 files changed, 215 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 6ca0781..7b6ca90 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -181,6 +181,9 @@ struct vgic_cpu {
 	u64 live_lrs;
 };
 
+int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			bool level);
+
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(false)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index fb45537..ada1d02 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -19,8 +19,31 @@
 
 #include "vgic.h"
 
+#define CREATE_TRACE_POINTS
+#include "../trace.h"
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+#define DEBUG_SPINLOCK_BUG_ON(p) BUG_ON(p)
+#else
+#define DEBUG_SPINLOCK_BUG_ON(p)
+#endif
+
 struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
 
+/*
+ * Locking order is always:
+ *   vgic_cpu->ap_list_lock
+ *     vgic_irq->irq_lock
+ *
+ * (that is, always take the ap_list_lock before the struct vgic_irq lock).
+ *
+ * When taking more than one ap_list_lock at the same time, always take the
+ * lowest numbered VCPU's ap_list_lock first, so:
+ *   vcpuX->vcpu_id < vcpuY->vcpu_id:
+ *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
+ *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
+ */
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid)
 {
@@ -39,3 +62,191 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 	WARN(1, "Looking up struct vgic_irq for reserved INTID");
 	return NULL;
 }
+
+/**
+ * kvm_vgic_target_oracle - compute the target vcpu for an irq
+ *
+ * @irq:	The irq to route. Must be already locked.
+ *
+ * Based on the current state of the interrupt (enabled, pending,
+ * active, vcpu and target_vcpu), compute the next vcpu this should be
+ * given to. Return NULL if this shouldn't be injected at all.
+ *
+ * Requires the IRQ lock to be held.
+ */
+static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
+{
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+	/* If the interrupt is active, it must stay on the current vcpu */
+	if (irq->active)
+		return irq->vcpu ? : irq->target_vcpu;
+
+	/*
+	 * If the IRQ is not active but enabled and pending, we should direct
+	 * it to its configured target VCPU.
+	 * If the distributor is disabled, pending interrupts shouldn't be
+	 * forwarded.
+	 */
+	if (irq->enabled && irq->pending) {
+		if (unlikely(irq->target_vcpu &&
+			     !irq->target_vcpu->kvm->arch.vgic.enabled))
+			return NULL;
+
+		return irq->target_vcpu;
+	}
+
+	/* If neither active nor pending and enabled, then this IRQ should not
+	 * be queued to any VCPU.
+	 */
+	return NULL;
+}
+
+/*
+ * Only valid injection if changing level for level-triggered IRQs or for a
+ * rising edge.
+ */
+static bool vgic_validate_injection(struct vgic_irq *irq, bool level)
+{
+	switch (irq->config) {
+	case VGIC_CONFIG_LEVEL:
+		return irq->line_level != level;
+	case VGIC_CONFIG_EDGE:
+		return level;
+	}
+
+	return false;
+}
+
+/*
+ * Check whether an IRQ needs to (and can) be queued to a VCPU's ap list.
+ * Do the queuing if necessary, taking the right locks in the right order.
+ * Returns true when the IRQ was queued, false otherwise.
+ *
+ * Needs to be entered with the IRQ lock already held, but will return
+ * with all locks dropped.
+ */
+bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq)
+{
+	struct kvm_vcpu *vcpu;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&irq->irq_lock));
+
+retry:
+	vcpu = vgic_target_oracle(irq);
+	if (irq->vcpu || !vcpu) {
+		/*
+		 * If this IRQ is already on a VCPU's ap_list, then it
+		 * cannot be moved or modified and there is no more work for
+		 * us to do.
+		 *
+		 * Otherwise, if the irq is not pending and enabled, it does
+		 * not need to be inserted into an ap_list and there is also
+		 * no more work for us to do.
+		 */
+		spin_unlock(&irq->irq_lock);
+		return false;
+	}
+
+	/*
+	 * We must unlock the irq lock to take the ap_list_lock where
+	 * we are going to insert this new pending interrupt.
+	 */
+	spin_unlock(&irq->irq_lock);
+
+	/* someone can do stuff here, which we re-check below */
+
+	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+	spin_lock(&irq->irq_lock);
+
+	/*
+	 * Did something change behind our backs?
+	 *
+	 * There are two cases:
+	 * 1) The irq lost its pending state or was disabled behind our
+	 *    backs and/or it was queued to another VCPU's ap_list.
+	 * 2) Someone changed the affinity on this irq behind our
+	 *    backs and we are now holding the wrong ap_list_lock.
+	 *
+	 * In both cases, drop the locks and retry.
+	 */
+
+	if (unlikely(irq->vcpu || vcpu != vgic_target_oracle(irq))) {
+		spin_unlock(&irq->irq_lock);
+		spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+		spin_lock(&irq->irq_lock);
+		goto retry;
+	}
+
+	list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
+	irq->vcpu = vcpu;
+
+	spin_unlock(&irq->irq_lock);
+	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+
+	kvm_vcpu_kick(vcpu);
+
+	return true;
+}
+
+static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
+				   unsigned int intid, bool level,
+				   bool mapped_irq)
+{
+	struct kvm_vcpu *vcpu;
+	struct vgic_irq *irq;
+	int ret;
+
+	trace_vgic_update_irq_pending(cpuid, intid, level);
+
+	vcpu = kvm_get_vcpu(kvm, cpuid);
+	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
+		return -EINVAL;
+
+	irq = vgic_get_irq(kvm, vcpu, intid);
+	if (!irq)
+		return -EINVAL;
+
+	if (irq->hw != mapped_irq)
+		return -EINVAL;
+
+	spin_lock(&irq->irq_lock);
+
+	if (!vgic_validate_injection(irq, level)) {
+		/* Nothing to see here, move along... */
+		spin_unlock(&irq->irq_lock);
+		return 0;
+	}
+
+	if (irq->config == VGIC_CONFIG_LEVEL) {
+		irq->line_level = level;
+		irq->pending = level || irq->soft_pending;
+	} else {
+		irq->pending = true;
+	}
+
+	vgic_queue_irq_unlock(kvm, irq);
+
+	return 0;
+}
+
+/**
+ * kvm_vgic_inject_irq - Inject an IRQ from a device to the vgic
+ * @kvm:     The VM structure pointer
+ * @cpuid:   The CPU for PPIs
+ * @intid:   The INTID to inject a new state to.
+ * @level:   Edge-triggered:  true:  to trigger the interrupt
+ *			      false: to ignore the call
+ *	     Level-sensitive  true:  raise the input signal
+ *			      false: lower the input signal
+ *
+ * The VGIC is not concerned with devices being active-LOW or active-HIGH for
+ * level-sensitive interrupts.  You can think of the level parameter as 1
+ * being HIGH and 0 being LOW and all devices being active-HIGH.
+ */
+int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			bool level)
+{
+	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 61b8d22..c625767 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -18,5 +18,6 @@
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
+bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
 
 #endif
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:17 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:17 +0200
Subject: [PULL 23/59] KVM: arm/arm64: vgic-new: Implement
 kvm_vgic_vcpu_pending_irq
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-24-git-send-email-christoffer.dall@linaro.org>

From: Eric Auger <eric.auger at linaro.org>

Tell KVM whether a particular VCPU has an IRQ that needs handling
in the guest. This is used to decide whether a VCPU is runnable.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
 include/kvm/vgic/vgic.h  |  2 ++
 virt/kvm/arm/vgic/vgic.c | 25 +++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 9506267..f663288 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -184,6 +184,8 @@ struct vgic_cpu {
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
 
+int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
+
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)	(false)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 0bf0d20..7e01008 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -520,3 +520,28 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 	vgic_flush_lr_state(vcpu);
 	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
 }
+
+int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	struct vgic_irq *irq;
+	bool pending = false;
+
+	if (!vcpu->kvm->arch.vgic.enabled)
+		return false;
+
+	spin_lock(&vgic_cpu->ap_list_lock);
+
+	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+		spin_lock(&irq->irq_lock);
+		pending = irq->pending && irq->enabled;
+		spin_unlock(&irq->irq_lock);
+
+		if (pending)
+			break;
+	}
+
+	spin_unlock(&vgic_cpu->ap_list_lock);
+
+	return pending;
+}
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:24 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:24 +0200
Subject: [PULL 30/59] KVM: arm/arm64: vgic-new: Add PRIORITY registers handlers
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-31-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

The priority register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.
There is a corner case when we change the priority of a pending
interrupt which we don't handle at the moment.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 40 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  7 +++++++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 4 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 12e101b..d564a30 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -90,7 +90,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 79a4622..6f4e05b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -236,6 +236,46 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
+				      gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->priority << (i * 8);
+	}
+
+	return val;
+}
+
+/*
+ * We currently don't handle changing the priority of an interrupt that
+ * is already pending on a VCPU. If there is a need for this, we would
+ * need to make this VCPU exit and re-evaluate the priorities, potentially
+ * leading to this interrupt getting presented now to the guest (if it has
+ * been masked by the priority mask before).
+ */
+void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		/* Narrow the priority range to what we actually support */
+		irq->priority = (val >> (i * 8)) & GENMASK(7, 8 - VGIC_PRI_BITS);
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 50b4464..7e73f10 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -129,6 +129,13 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val);
 
+unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
+				      gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index cf62015..e57f8d5 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,8 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define VGIC_PRI_BITS		5
+
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:26 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:26 +0200
Subject: [PULL 32/59] KVM: arm/arm64: vgic-new: Add TARGET registers handlers
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-33-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

The target register handlers are v2 emulation specific, so their
implementation lives entirely in vgic-mmio-v2.c.
We copy the old VGIC behaviour of assigning an IRQ to the first VCPU
set in the target mask instead of making it possibly pending on
multiple VCPUs.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index bb7389e..52389ff 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -64,6 +64,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
+					   gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->targets << (i * 8);
+	}
+
+	return val;
+}
+
+static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
+				   gpa_t addr, unsigned int len,
+				   unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 8);
+	int i;
+
+	/* GICD_ITARGETSR[0-7] are read-only */
+	if (intid < VGIC_NR_PRIVATE_IRQS)
+		return;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
+		int target;
+
+		spin_lock(&irq->irq_lock);
+
+		irq->targets = (val >> (i * 8)) & 0xff;
+		target = irq->targets ? __ffs(irq->targets) : 0;
+		irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target);
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
@@ -93,7 +134,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		vgic_mmio_read_target, vgic_mmio_write_target, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
 		vgic_mmio_read_config, vgic_mmio_write_config, 2,
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:25 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:25 +0200
Subject: [PULL 31/59] KVM: arm/arm64: vgic-new: Add CONFIG registers handlers
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-32-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

The config register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c |  2 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 47 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  7 ++++++
 3 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index d564a30..bb7389e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -96,7 +96,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 2,
+		vgic_mmio_read_config, vgic_mmio_write_config, 2,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 6f4e05b..9de80be 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -276,6 +276,53 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 2);
+	u32 value = 0;
+	int i;
+
+	for (i = 0; i < len * 4; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->config == VGIC_CONFIG_EDGE)
+			value |= (2U << (i * 2));
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
+			    gpa_t addr, unsigned int len,
+			    unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 2);
+	int i;
+
+	for (i = 0; i < len * 4; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		/*
+		 * The configuration cannot be changed for SGIs in general,
+		 * for PPIs this is IMPLEMENTATION DEFINED. The arch timer
+		 * code relies on PPIs being level triggered, so we also
+		 * make them read-only here.
+		 */
+		if (intid + i < VGIC_NR_PRIVATE_IRQS)
+			continue;
+
+		spin_lock(&irq->irq_lock);
+		if (test_bit(i * 2 + 1, &val)) {
+			irq->config = VGIC_CONFIG_EDGE;
+		} else {
+			irq->config = VGIC_CONFIG_LEVEL;
+			irq->pending = irq->line_level | irq->soft_pending;
+		}
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 7e73f10..d1348ac 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -136,6 +136,13 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
 			      gpa_t addr, unsigned int len,
 			      unsigned long val);
 
+unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
+			    gpa_t addr, unsigned int len,
+			    unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:21 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:21 +0200
Subject: [PULL 27/59] KVM: arm/arm64: vgic-new: Add ENABLE registers handlers
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-28-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

As the enable register handlers are shared between the v2 and v3
emulation, their implementation goes into vgic-mmio.c, to be easily
referenced from the v3 emulation as well later.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
 virt/kvm/arm/vgic/vgic-mmio.c    | 56 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 11 ++++++++
 3 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index d812c93..d5355b5 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -72,10 +72,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 1a97765..32ed8db 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -39,6 +39,62 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 	/* Ignore */
 }
 
+/*
+ * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
+ * of the enabled bit, so there is only one function for both here.
+ */
+unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->enabled)
+			value |= (1U << i);
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		irq->enabled = true;
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
+void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->enabled = false;
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 5b928d4..57e19fe 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -96,6 +96,17 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
 void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 			unsigned int len, unsigned long val);
 
+unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
+void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:23 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:23 +0200
Subject: [PULL 29/59] KVM: arm/arm64: vgic-new: Add ACTIVE registers handlers
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-30-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

The active register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be
easily referenced from the v3 emulation as well later.
Since activation/deactivation of an interrupt may happen entirely
in the guest without it ever exiting, we need some extra logic to
properly track the active state.
For clearing the active state, we basically have to halt the guest to
make sure this is properly propagated into the respective VCPUs.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +-
 virt/kvm/arm/vgic/vgic-mmio.c    | 81 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 10 +++++
 3 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index c13a708..12e101b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -84,10 +84,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index d8dc8f6..79a4622 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -155,6 +155,87 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->active)
+			value |= (1U << i);
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	kvm_arm_halt_guest(vcpu->kvm);
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		/*
+		 * If this virtual IRQ was written into a list register, we
+		 * have to make sure the CPU that runs the VCPU thread has
+		 * synced back LR state to the struct vgic_irq.  We can only
+		 * know this for sure, when either this irq is not assigned to
+		 * anyone's AP list anymore, or the VCPU thread is not
+		 * running on any CPUs.
+		 *
+		 * In the opposite case, we know the VCPU thread may be on its
+		 * way back from the guest and still has to sync back this
+		 * IRQ, so we release and re-acquire the spin_lock to let the
+		 * other thread sync back the IRQ.
+		 */
+		while (irq->vcpu && /* IRQ may have state in an LR somewhere */
+		       irq->vcpu->cpu != -1) /* VCPU thread is running */
+			cond_resched_lock(&irq->irq_lock);
+
+		irq->active = false;
+		spin_unlock(&irq->irq_lock);
+	}
+	kvm_arm_resume_guest(vcpu->kvm);
+}
+
+void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		/*
+		 * If the IRQ was already active or there is no target VCPU
+		 * assigned at the moment, then just proceed.
+		 */
+		if (irq->active || !irq->target_vcpu) {
+			irq->active = true;
+
+			spin_unlock(&irq->irq_lock);
+			continue;
+		}
+
+		irq->active = true;
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 97ee703..50b4464 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -118,6 +118,16 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
 			      gpa_t addr, unsigned int len,
 			      unsigned long val);
 
+unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
+
+void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
+			     gpa_t addr, unsigned int len,
+			     unsigned long val);
 
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:22 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:22 +0200
Subject: [PULL 28/59] KVM: arm/arm64: vgic-new: Add PENDING registers handlers
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-29-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

The pending register handlers are shared between the v2 and v3
emulation, so their implementation goes into vgic-mmio.c, to be easily
referenced from the v3 emulation as well later.
For level triggered interrupts the real line level is unaffected by
this write, so we keep this state separate and combine it with the
device's level to get the actual pending state.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c |  4 +--
 virt/kvm/arm/vgic/vgic-mmio.c    | 60 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    | 12 ++++++++
 3 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index d5355b5..c13a708 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -78,10 +78,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 32ed8db..d8dc8f6 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -95,6 +95,66 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
 	}
 }
 
+unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	u32 value = 0;
+	int i;
+
+	/* Loop over all IRQs affected by this read */
+	for (i = 0; i < len * 8; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->pending)
+			value |= (1U << i);
+	}
+
+	return value;
+}
+
+void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+		if (irq->config == VGIC_CONFIG_LEVEL)
+			irq->soft_pending = true;
+
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
+
+void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val)
+{
+	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+	int i;
+
+	for_each_set_bit(i, &val, len * 8) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		if (irq->config == VGIC_CONFIG_LEVEL) {
+			irq->soft_pending = false;
+			irq->pending = irq->line_level;
+		} else {
+			irq->pending = false;
+		}
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 57e19fe..97ee703 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -107,6 +107,18 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val);
 
+unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
+void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+			      gpa_t addr, unsigned int len,
+			      unsigned long val);
+
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 #endif
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:30 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:30 +0200
Subject: [PULL 36/59] KVM: arm/arm64: vgic-new: Add GICv3 CTLR, IIDR,
 TYPER handlers
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-37-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

As in the GICv2 emulation we handle those three registers in one
function.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 48 +++++++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.h         |  1 +
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 83a6654..bd062b8 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -22,6 +22,52 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 value = 0;
+
+	switch (addr & 0x0c) {
+	case GICD_CTLR:
+		if (vcpu->kvm->arch.vgic.enabled)
+			value |= GICD_CTLR_ENABLE_SS_G1;
+		value |= GICD_CTLR_ARE_NS | GICD_CTLR_DS;
+		break;
+	case GICD_TYPER:
+		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+		value = (value >> 5) - 1;
+		value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19;
+		break;
+	case GICD_IIDR:
+		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+		break;
+	default:
+		return 0;
+	}
+
+	return value;
+}
+
+static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+	bool was_enabled = dist->enabled;
+
+	switch (addr & 0x0c) {
+	case GICD_CTLR:
+		dist->enabled = val & GICD_CTLR_ENABLE_SS_G1;
+
+		if (!was_enabled && dist->enabled)
+			vgic_kick_vcpus(vcpu->kvm);
+		break;
+	case GICD_TYPER:
+	case GICD_IIDR:
+		return;
+	}
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -48,7 +94,7 @@
 
 static const struct vgic_register_region vgic_v3_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc, 16,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 6742b11..44c6a1b 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,7 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define INTERRUPT_ID_BITS_SPIS	10
 #define VGIC_PRI_BITS		5
 
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:27 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:27 +0200
Subject: [PULL 33/59] KVM: arm/arm64: vgic-new: Add SGIR register handler
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-34-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

Triggering an IPI via this register is v2 specific, so the
implementation lives entirely in vgic-mmio-v2.c.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 43 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 52389ff..c884e9b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -64,6 +64,47 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
+				 gpa_t addr, unsigned int len,
+				 unsigned long val)
+{
+	int nr_vcpus = atomic_read(&source_vcpu->kvm->online_vcpus);
+	int intid = val & 0xf;
+	int targets = (val >> 16) & 0xff;
+	int mode = (val >> 24) & 0x03;
+	int c;
+	struct kvm_vcpu *vcpu;
+
+	switch (mode) {
+	case 0x0:		/* as specified by targets */
+		break;
+	case 0x1:
+		targets = (1U << nr_vcpus) - 1;			/* all, ... */
+		targets &= ~(1U << source_vcpu->vcpu_id);	/* but self */
+		break;
+	case 0x2:		/* this very vCPU only */
+		targets = (1U << source_vcpu->vcpu_id);
+		break;
+	case 0x3:		/* reserved */
+		return;
+	}
+
+	kvm_for_each_vcpu(c, vcpu, source_vcpu->kvm) {
+		struct vgic_irq *irq;
+
+		if (!(targets & (1U << c)))
+			continue;
+
+		irq = vgic_get_irq(source_vcpu->kvm, vcpu, intid);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+		irq->source |= 1U << source_vcpu->vcpu_id;
+
+		vgic_queue_irq_unlock(source_vcpu->kvm, irq);
+	}
+}
+
 static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
 					   gpa_t addr, unsigned int len)
 {
@@ -140,7 +181,7 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_config, vgic_mmio_write_config, 2,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:29 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:29 +0200
Subject: [PULL 35/59] KVM: arm/arm64: vgic-new: Add GICv3 MMIO handling
 framework
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-36-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

Create a new file called vgic-mmio-v3.c and describe the GICv3
distributor and redistributor registers there.
This adds a special macro to deal with the split of SGI/PPI in the
redistributor and SPIs in the distributor, which allows us to reuse
the existing GICv2 handlers for those registers which are compatible.
Also we provide a function to deal with the registration of the two
separate redistributor frames per VCPU.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 224 +++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c    |   5 +
 virt/kvm/arm/vgic/vgic-mmio.h    |   2 +
 virt/kvm/arm/vgic/vgic.h         |   7 ++
 4 files changed, 238 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v3.c

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
new file mode 100644
index 0000000..83a6654
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -0,0 +1,224 @@
+/*
+ * VGICv3 MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irqchip/arm-gic-v3.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include <asm/kvm_emulate.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+/*
+ * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
+ * redistributors, while SPIs are covered by registers in the distributor
+ * block. Trying to set private IRQs in this block gets ignored.
+ * We take some special care here to fix the calculation of the register
+ * offset.
+ */
+#define REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(off, rd, wr, bpi, acc)	\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = bpi,					\
+		.len = (bpi * VGIC_NR_PRIVATE_IRQS) / 8,		\
+		.access_flags = acc,					\
+		.read = vgic_mmio_read_raz,				\
+		.write = vgic_mmio_write_wi,				\
+	}, {								\
+		.reg_offset = off + (bpi * VGIC_NR_PRIVATE_IRQS) / 8,	\
+		.bits_per_irq = bpi,					\
+		.len = (bpi * (1024 - VGIC_NR_PRIVATE_IRQS)) / 8,	\
+		.access_flags = acc,					\
+		.read = rd,						\
+		.write = wr,						\
+	}
+
+static const struct vgic_register_region vgic_v3_dist_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICENABLER,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ITARGETSR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICFGR,
+		vgic_mmio_read_config, vgic_mmio_write_config, 2,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGRPMODR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		VGIC_ACCESS_32bit),
+};
+
+static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICR_CTLR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_PENDBASER,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		VGIC_ACCESS_32bit),
+};
+
+static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
+		vgic_mmio_read_enable, vgic_mmio_write_senable, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0,
+		vgic_mmio_read_enable, vgic_mmio_write_cenable, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISPENDR0,
+		vgic_mmio_read_pending, vgic_mmio_write_spending, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICPENDR0,
+		vgic_mmio_read_pending, vgic_mmio_write_cpending, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ISACTIVER0,
+		vgic_mmio_read_active, vgic_mmio_write_sactive, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICACTIVER0,
+		vgic_mmio_read_active, vgic_mmio_write_cactive, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0,
+		vgic_mmio_read_priority, vgic_mmio_write_priority, 32,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0,
+		vgic_mmio_read_config, vgic_mmio_write_config, 8,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GICR_NSACR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+};
+
+unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
+{
+	dev->regions = vgic_v3_dist_registers;
+	dev->nr_regions = ARRAY_SIZE(vgic_v3_dist_registers);
+
+	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
+
+	return SZ_64K;
+}
+
+int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
+{
+	int nr_vcpus = atomic_read(&kvm->online_vcpus);
+	struct kvm_vcpu *vcpu;
+	struct vgic_io_device *devices;
+	int c, ret = 0;
+
+	devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
+			  GFP_KERNEL);
+	if (!devices)
+		return -ENOMEM;
+
+	kvm_for_each_vcpu(c, vcpu, kvm) {
+		gpa_t rd_base = redist_base_address + c * SZ_64K * 2;
+		gpa_t sgi_base = rd_base + SZ_64K;
+		struct vgic_io_device *rd_dev = &devices[c * 2];
+		struct vgic_io_device *sgi_dev = &devices[c * 2 + 1];
+
+		kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops);
+		rd_dev->base_addr = rd_base;
+		rd_dev->regions = vgic_v3_rdbase_registers;
+		rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
+		rd_dev->redist_vcpu = vcpu;
+
+		mutex_lock(&kvm->slots_lock);
+		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base,
+					      SZ_64K, &rd_dev->dev);
+		mutex_unlock(&kvm->slots_lock);
+
+		if (ret)
+			break;
+
+		kvm_iodevice_init(&sgi_dev->dev, &kvm_io_gic_ops);
+		sgi_dev->base_addr = sgi_base;
+		sgi_dev->regions = vgic_v3_sgibase_registers;
+		sgi_dev->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
+		sgi_dev->redist_vcpu = vcpu;
+
+		mutex_lock(&kvm->slots_lock);
+		ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, sgi_base,
+					      SZ_64K, &sgi_dev->dev);
+		mutex_unlock(&kvm->slots_lock);
+		if (ret) {
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &rd_dev->dev);
+			break;
+		}
+	}
+
+	if (ret) {
+		/* The current c failed, so we start with the previous one. */
+		for (c--; c >= 0; c--) {
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2].dev);
+			kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+						  &devices[c * 2 + 1].dev);
+		}
+		kfree(devices);
+	} else {
+		kvm->arch.vgic.redist_iodevs = devices;
+	}
+
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 9de80be..4ef3571 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -478,6 +478,11 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 	case VGIC_V2:
 		len = vgic_v2_init_dist_iodev(io_device);
 		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case VGIC_V3:
+		len = vgic_v3_init_dist_iodev(io_device);
+		break;
+#endif
 	default:
 		BUG_ON(1);
 	}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index d1348ac..8509014 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -145,4 +145,6 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
 
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
+unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
+
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index e57f8d5..6742b11 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -42,6 +42,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
 {
@@ -63,6 +64,12 @@ static inline void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 }
+
+static inline int vgic_register_redist_iodevs(struct kvm *kvm,
+					      gpa_t dist_base_address)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:28 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:28 +0200
Subject: [PULL 34/59] KVM: arm/arm64: vgic-new: Add SGIPENDR register handlers
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-35-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

As this register is v2 specific, its implementation lives entirely
in vgic-mmio-v2.c.
This register allows setting the source mask of an IPI.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 62 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 60 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index c884e9b..3925d4c 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -146,6 +146,64 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		val |= (u64)irq->source << (i * 8);
+	}
+	return val;
+}
+
+static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len,
+				     unsigned long val)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->source &= ~((val >> (i * 8)) & 0xff);
+		if (!irq->source)
+			irq->pending = false;
+
+		spin_unlock(&irq->irq_lock);
+	}
+}
+
+static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
+				     gpa_t addr, unsigned int len,
+				     unsigned long val)
+{
+	u32 intid = addr & 0x0f;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+
+		irq->source |= (val >> (i * 8)) & 0xff;
+
+		if (irq->source) {
+			irq->pending = true;
+			vgic_queue_irq_unlock(vcpu->kvm, irq);
+		} else {
+			spin_unlock(&irq->irq_lock);
+		}
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
@@ -184,10 +242,10 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_sgir, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		vgic_mmio_read_sgipend, vgic_mmio_write_sgipendc, 16,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		vgic_mmio_read_sgipend, vgic_mmio_write_sgipends, 16,
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 };
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:31 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:31 +0200
Subject: [PULL 37/59] KVM: arm/arm64: vgic-new: Add GICv3 redistributor IIDR
 and TYPER handler
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-38-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

The redistributor TYPER tells the OS about the associated MPIDR,
also the LAST bit is crucial to determine the number of redistributors.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index bd062b8..64edd23 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -22,6 +22,13 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+/* extract @num bytes at @offset bytes offset in data */
+static unsigned long extract_bytes(unsigned long data, unsigned int offset,
+				   unsigned int num)
+{
+	return (data >> (offset * 8)) & GENMASK_ULL(num * 8 - 1, 0);
+}
+
 static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
 					    gpa_t addr, unsigned int len)
 {
@@ -68,6 +75,27 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
+					      gpa_t addr, unsigned int len)
+{
+	unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
+	int target_vcpu_id = vcpu->vcpu_id;
+	u64 value;
+
+	value = (mpidr & GENMASK(23, 0)) << 32;
+	value |= ((target_vcpu_id & 0xffff) << 8);
+	if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
+		value |= GICR_TYPER_LAST;
+
+	return extract_bytes(value, addr & 7, len);
+}
+
+static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
+					     gpa_t addr, unsigned int len)
+{
+	return (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -142,10 +170,10 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_IIDR,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		vgic_mmio_read_v3r_iidr, vgic_mmio_write_wi, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_TYPER,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, 8,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_PROPBASER,
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:37 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:37 +0200
Subject: [PULL 43/59] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_CTRL
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-44-git-send-email-christoffer.dall@linaro.org>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_CTRL group API
featuring KVM_DEV_ARM_VGIC_CTRL_INIT attribute. The vgic_init
function is not yet implemented though.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 05ff925..e153f12 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -23,6 +23,8 @@
 static int vgic_set_common_attr(struct kvm_device *dev,
 				struct kvm_device_attr *attr)
 {
+	int r;
+
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
@@ -55,6 +57,16 @@ static int vgic_set_common_attr(struct kvm_device *dev,
 
 		return ret;
 	}
+	case KVM_DEV_ARM_VGIC_GRP_CTRL: {
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			mutex_lock(&dev->kvm->lock);
+			r = vgic_init(dev->kvm);
+			mutex_unlock(&dev->kvm->lock);
+			return r;
+		}
+		break;
+	}
 	}
 
 	return -ENXIO;
@@ -131,6 +143,11 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
+	case KVM_DEV_ARM_VGIC_GRP_CTRL:
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			return 0;
+		}
 	}
 	return -ENXIO;
 }
@@ -166,6 +183,11 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
+	case KVM_DEV_ARM_VGIC_GRP_CTRL:
+		switch (attr->attr) {
+		case KVM_DEV_ARM_VGIC_CTRL_INIT:
+			return 0;
+		}
 	}
 	return -ENXIO;
 }
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:35 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:35 +0200
Subject: [PULL 41/59] KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM device
 ops registration
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-42-git-send-email-christoffer.dall@linaro.org>

From: Eric Auger <eric.auger at linaro.org>

This patch introduces the skeleton for the KVM device operations
associated to KVM_DEV_TYPE_ARM_VGIC_V2 and KVM_DEV_TYPE_ARM_VGIC_V3.

At that stage kvm_vgic_create is stubbed.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 108 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |   2 +
 2 files changed, 110 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-kvm-device.c

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
new file mode 100644
index 0000000..ff332f3
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -0,0 +1,108 @@
+/*
+ * VGIC: KVM DEVICE API
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ * Author: Marc Zyngier <marc.zyngier at arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+
+/* common helpers */
+
+static int vgic_create(struct kvm_device *dev, u32 type)
+{
+	return kvm_vgic_create(dev->kvm, type);
+}
+
+static void vgic_destroy(struct kvm_device *dev)
+{
+	kfree(dev);
+}
+
+void kvm_register_vgic_device(unsigned long type)
+{
+	switch (type) {
+	case KVM_DEV_TYPE_ARM_VGIC_V2:
+		kvm_register_device_ops(&kvm_arm_vgic_v2_ops,
+					KVM_DEV_TYPE_ARM_VGIC_V2);
+		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case KVM_DEV_TYPE_ARM_VGIC_V3:
+		kvm_register_device_ops(&kvm_arm_vgic_v3_ops,
+					KVM_DEV_TYPE_ARM_VGIC_V3);
+		break;
+#endif
+	}
+}
+
+/* V2 ops */
+
+static int vgic_v2_set_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v2_get_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v2_has_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+struct kvm_device_ops kvm_arm_vgic_v2_ops = {
+	.name = "kvm-arm-vgic-v2",
+	.create = vgic_create,
+	.destroy = vgic_destroy,
+	.set_attr = vgic_v2_set_attr,
+	.get_attr = vgic_v2_get_attr,
+	.has_attr = vgic_v2_has_attr,
+};
+
+/* V3 ops */
+
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+
+static int vgic_v3_set_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v3_get_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+static int vgic_v3_has_attr(struct kvm_device *dev,
+			    struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+struct kvm_device_ops kvm_arm_vgic_v3_ops = {
+	.name = "kvm-arm-vgic-v3",
+	.create = vgic_create,
+	.destroy = vgic_destroy,
+	.set_attr = vgic_v3_set_attr,
+	.get_attr = vgic_v3_get_attr,
+	.has_attr = vgic_v3_has_attr,
+};
+
+#endif /* CONFIG_KVM_ARM_VGIC_V3 */
+
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 44c6a1b..77b0ab3 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -73,4 +73,6 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 }
 #endif
 
+void kvm_register_vgic_device(unsigned long type);
+
 #endif
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:36 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:36 +0200
Subject: [PULL 42/59] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_NR_IRQS
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-43-git-send-email-christoffer.dall@linaro.org>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_NR_IRQS group. This
modality is supported by both VGIC V2 and V3 KVM device as will be
other groups, hence the introduction of common helpers.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 83 +++++++++++++++++++++++++++++++++++--
 1 file changed, 79 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index ff332f3..05ff925 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -15,9 +15,69 @@
  */
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
+#include <linux/uaccess.h>
+#include "vgic.h"
 
 /* common helpers */
 
+static int vgic_set_common_attr(struct kvm_device *dev,
+				struct kvm_device_attr *attr)
+{
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 val;
+		int ret = 0;
+
+		if (get_user(val, uaddr))
+			return -EFAULT;
+
+		/*
+		 * We require:
+		 * - at least 32 SPIs on top of the 16 SGIs and 16 PPIs
+		 * - at most 1024 interrupts
+		 * - a multiple of 32 interrupts
+		 */
+		if (val < (VGIC_NR_PRIVATE_IRQS + 32) ||
+		    val > VGIC_MAX_RESERVED ||
+		    (val & 31))
+			return -EINVAL;
+
+		mutex_lock(&dev->kvm->lock);
+
+		if (vgic_ready(dev->kvm) || dev->kvm->arch.vgic.nr_spis)
+			ret = -EBUSY;
+		else
+			dev->kvm->arch.vgic.nr_spis =
+				val - VGIC_NR_PRIVATE_IRQS;
+
+		mutex_unlock(&dev->kvm->lock);
+
+		return ret;
+	}
+	}
+
+	return -ENXIO;
+}
+
+static int vgic_get_common_attr(struct kvm_device *dev,
+				struct kvm_device_attr *attr)
+{
+	int r = -ENXIO;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+
+		r = put_user(dev->kvm->arch.vgic.nr_spis +
+			     VGIC_NR_PRIVATE_IRQS, uaddr);
+		break;
+	}
+	}
+
+	return r;
+}
+
 static int vgic_create(struct kvm_device *dev, u32 type)
 {
 	return kvm_vgic_create(dev->kvm, type);
@@ -49,18 +109,29 @@ void kvm_register_vgic_device(unsigned long type)
 static int vgic_v2_set_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	int ret;
+
+	ret = vgic_set_common_attr(dev, attr);
+	return ret;
+
 }
 
 static int vgic_v2_get_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	int ret;
+
+	ret = vgic_get_common_attr(dev, attr);
+	return ret;
 }
 
 static int vgic_v2_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
+		return 0;
+	}
 	return -ENXIO;
 }
 
@@ -80,18 +151,22 @@ struct kvm_device_ops kvm_arm_vgic_v2_ops = {
 static int vgic_v3_set_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	return vgic_set_common_attr(dev, attr);
 }
 
 static int vgic_v3_get_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	return vgic_get_common_attr(dev, attr);
 }
 
 static int vgic_v3_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
+		return 0;
+	}
 	return -ENXIO;
 }
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:38 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:38 +0200
Subject: [PULL 44/59] KVM: arm/arm64: vgic-new: vgic_kvm_device: implement
 kvm_vgic_addr
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-45-git-send-email-christoffer.dall@linaro.org>

From: Eric Auger <eric.auger at linaro.org>

kvm_vgic_addr is used by the userspace to set the base address of
the following register regions, as seen by the guest:
- distributor(v2 and v3),
- re-distributors (v3),
- CPU interface (v2).

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/vgic/vgic.h             |  2 +
 virt/kvm/arm/vgic/vgic-kvm-device.c | 86 +++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |  3 ++
 3 files changed, 91 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 00e3dca..3689b9b 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -194,6 +194,8 @@ struct vgic_cpu {
 	u64 live_lrs;
 };
 
+int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
 
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index e153f12..082829a 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -16,10 +16,96 @@
 #include <linux/kvm_host.h>
 #include <kvm/arm_vgic.h>
 #include <linux/uaccess.h>
+#include <asm/kvm_mmu.h>
 #include "vgic.h"
 
 /* common helpers */
 
+static int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
+			     phys_addr_t addr, phys_addr_t alignment)
+{
+	if (addr & ~KVM_PHYS_MASK)
+		return -E2BIG;
+
+	if (!IS_ALIGNED(addr, alignment))
+		return -EINVAL;
+
+	if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
+		return -EEXIST;
+
+	return 0;
+}
+
+/**
+ * kvm_vgic_addr - set or get vgic VM base addresses
+ * @kvm:   pointer to the vm struct
+ * @type:  the VGIC addr type, one of KVM_VGIC_V[23]_ADDR_TYPE_XXX
+ * @addr:  pointer to address value
+ * @write: if true set the address in the VM address space, if false read the
+ *          address
+ *
+ * Set or get the vgic base addresses for the distributor and the virtual CPU
+ * interface in the VM physical address space.  These addresses are properties
+ * of the emulated core/SoC and therefore user space initially knows this
+ * information.
+ * Check them for sanity (alignment, double assignment). We can't check for
+ * overlapping regions in case of a virtual GICv3 here, since we don't know
+ * the number of VCPUs yet, so we defer this check to map_resources().
+ */
+int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
+{
+	int r = 0;
+	struct vgic_dist *vgic = &kvm->arch.vgic;
+	int type_needed;
+	phys_addr_t *addr_ptr, alignment;
+
+	mutex_lock(&kvm->lock);
+	switch (type) {
+	case KVM_VGIC_V2_ADDR_TYPE_DIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+		addr_ptr = &vgic->vgic_dist_base;
+		alignment = SZ_4K;
+		break;
+	case KVM_VGIC_V2_ADDR_TYPE_CPU:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+		addr_ptr = &vgic->vgic_cpu_base;
+		alignment = SZ_4K;
+		break;
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	case KVM_VGIC_V3_ADDR_TYPE_DIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+		addr_ptr = &vgic->vgic_dist_base;
+		alignment = SZ_64K;
+		break;
+	case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+		type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+		addr_ptr = &vgic->vgic_redist_base;
+		alignment = SZ_64K;
+		break;
+#endif
+	default:
+		r = -ENODEV;
+		goto out;
+	}
+
+	if (vgic->vgic_model != type_needed) {
+		r = -ENODEV;
+		goto out;
+	}
+
+	if (write) {
+		r = vgic_check_ioaddr(kvm, addr_ptr, *addr, alignment);
+		if (!r)
+			*addr_ptr = *addr;
+	} else {
+		*addr = *addr_ptr;
+	}
+
+out:
+	mutex_unlock(&kvm->lock);
+	return r;
+}
+
 static int vgic_set_common_attr(struct kvm_device *dev,
 				struct kvm_device_attr *attr)
 {
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 77b0ab3..6abc9a3 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -19,6 +19,9 @@
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
+#define VGIC_ADDR_UNDEF		(-1)
+#define IS_VGIC_ADDR_UNDEF(_x)  ((_x) == VGIC_ADDR_UNDEF)
+
 #define INTERRUPT_ID_BITS_SPIS	10
 #define VGIC_PRI_BITS		5
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:39 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:39 +0200
Subject: [PULL 45/59] KVM: arm/arm64: vgic-new: vgic_kvm_device:
 KVM_DEV_ARM_VGIC_GRP_ADDR
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-46-git-send-email-christoffer.dall@linaro.org>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the KVM_DEV_ARM_VGIC_GRP_ADDR group which
enables to set the base address of GIC regions as seen by the guest.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 38 +++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 082829a..a709097 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -112,6 +112,17 @@ static int vgic_set_common_attr(struct kvm_device *dev,
 	int r;
 
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 addr;
+		unsigned long type = (unsigned long)attr->attr;
+
+		if (copy_from_user(&addr, uaddr, sizeof(addr)))
+			return -EFAULT;
+
+		r = kvm_vgic_addr(dev->kvm, type, &addr, true);
+		return (r == -ENODEV) ? -ENXIO : r;
+	}
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
 		u32 val;
@@ -164,6 +175,19 @@ static int vgic_get_common_attr(struct kvm_device *dev,
 	int r = -ENXIO;
 
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 addr;
+		unsigned long type = (unsigned long)attr->attr;
+
+		r = kvm_vgic_addr(dev->kvm, type, &addr, false);
+		if (r)
+			return (r == -ENODEV) ? -ENXIO : r;
+
+		if (copy_to_user(uaddr, &addr, sizeof(addr)))
+			return -EFAULT;
+		break;
+	}
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
 		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
 
@@ -227,6 +251,13 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR:
+		switch (attr->attr) {
+		case KVM_VGIC_V2_ADDR_TYPE_DIST:
+		case KVM_VGIC_V2_ADDR_TYPE_CPU:
+			return 0;
+		}
+		break;
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
@@ -267,6 +298,13 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
 			    struct kvm_device_attr *attr)
 {
 	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_ADDR:
+		switch (attr->attr) {
+		case KVM_VGIC_V3_ADDR_TYPE_DIST:
+		case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+			return 0;
+		}
+		break;
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:45 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:45 +0200
Subject: [PULL 51/59] KVM: arm/arm64: vgic-new: vgic_init: implement
 kvm_vgic_hyp_init
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-52-git-send-email-christoffer.dall@linaro.org>

From: Eric Auger <eric.auger at linaro.org>

Implements kvm_vgic_hyp_init and vgic_probe function.
This uses the new firmware independent VGIC probing to support both ACPI
and DT based systems (code from Marc Zyngier).

The vgic_global struct is enriched with new fields populated
by those functions.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/vgic/vgic.h       |   1 +
 virt/kvm/arm/vgic/vgic-init.c | 123 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   |  64 ++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c   |  49 +++++++++++++++++
 virt/kvm/arm/vgic/vgic.h      |   9 ++++
 5 files changed, 246 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-init.c

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 3689b9b..393489f 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -195,6 +195,7 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
new file mode 100644
index 0000000..4523beb
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/cpu.h>
+#include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
+#include "vgic.h"
+
+/* GENERIC PROBE */
+
+static void vgic_init_maintenance_interrupt(void *info)
+{
+	enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0);
+}
+
+static int vgic_cpu_notify(struct notifier_block *self,
+			   unsigned long action, void *cpu)
+{
+	switch (action) {
+	case CPU_STARTING:
+	case CPU_STARTING_FROZEN:
+		vgic_init_maintenance_interrupt(NULL);
+		break;
+	case CPU_DYING:
+	case CPU_DYING_FROZEN:
+		disable_percpu_irq(kvm_vgic_global_state.maint_irq);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block vgic_cpu_nb = {
+	.notifier_call = vgic_cpu_notify,
+};
+
+static irqreturn_t vgic_maintenance_handler(int irq, void *data)
+{
+	/*
+	 * We cannot rely on the vgic maintenance interrupt to be
+	 * delivered synchronously. This means we can only use it to
+	 * exit the VM, and we perform the handling of EOIed
+	 * interrupts on the exit path (see vgic_process_maintenance).
+	 */
+	return IRQ_HANDLED;
+}
+
+/**
+ * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable
+ * according to the host GIC model. Accordingly calls either
+ * vgic_v2/v3_probe which registers the KVM_DEVICE that can be
+ * instantiated by a guest later on .
+ */
+int kvm_vgic_hyp_init(void)
+{
+	const struct gic_kvm_info *gic_kvm_info;
+	int ret;
+
+	gic_kvm_info = gic_get_kvm_info();
+	if (!gic_kvm_info)
+		return -ENODEV;
+
+	if (!gic_kvm_info->maint_irq) {
+		kvm_err("No vgic maintenance irq\n");
+		return -ENXIO;
+	}
+
+	switch (gic_kvm_info->type) {
+	case GIC_V2:
+		ret = vgic_v2_probe(gic_kvm_info);
+		break;
+	case GIC_V3:
+		ret = vgic_v3_probe(gic_kvm_info);
+		break;
+	default:
+		ret = -ENODEV;
+	};
+
+	if (ret)
+		return ret;
+
+	kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
+	ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
+				 vgic_maintenance_handler,
+				 "vgic", kvm_get_running_vcpus());
+	if (ret) {
+		kvm_err("Cannot register interrupt %d\n",
+			kvm_vgic_global_state.maint_irq);
+		return ret;
+	}
+
+	ret = __register_cpu_notifier(&vgic_cpu_nb);
+	if (ret) {
+		kvm_err("Cannot register vgic CPU notifier\n");
+		goto out_free_irq;
+	}
+
+	on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1);
+
+	kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq);
+	return 0;
+
+out_free_irq:
+	free_percpu_irq(kvm_vgic_global_state.maint_irq,
+			kvm_get_running_vcpus());
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index d943059..09777c8 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -17,6 +17,8 @@
 #include <linux/irqchip/arm-gic.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
 
 #include "vgic.h"
 
@@ -203,3 +205,65 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
 			GICH_VMCR_PRIMASK_SHIFT;
 }
+
+/**
+ * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
+ * @node:	pointer to the DT node
+ *
+ * Returns 0 if a GICv2 has been found, returns an error code otherwise
+ */
+int vgic_v2_probe(const struct gic_kvm_info *info)
+{
+	int ret;
+	u32 vtr;
+
+	if (!info->vctrl.start) {
+		kvm_err("GICH not present in the firmware table\n");
+		return -ENXIO;
+	}
+
+	if (!PAGE_ALIGNED(info->vcpu.start)) {
+		kvm_err("GICV physical address 0x%llx not page aligned\n",
+			(unsigned long long)info->vcpu.start);
+		return -ENXIO;
+	}
+
+	if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
+		kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+			(unsigned long long)resource_size(&info->vcpu),
+			PAGE_SIZE);
+		return -ENXIO;
+	}
+
+	kvm_vgic_global_state.vctrl_base = ioremap(info->vctrl.start,
+						   resource_size(&info->vctrl));
+	if (!kvm_vgic_global_state.vctrl_base) {
+		kvm_err("Cannot ioremap GICH\n");
+		return -ENOMEM;
+	}
+
+	vtr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
+	kvm_vgic_global_state.nr_lr = (vtr & 0x3f) + 1;
+
+	ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
+				     kvm_vgic_global_state.vctrl_base +
+					 resource_size(&info->vctrl),
+				     info->vctrl.start);
+
+	if (ret) {
+		kvm_err("Cannot map VCTRL into hyp\n");
+		iounmap(kvm_vgic_global_state.vctrl_base);
+		return ret;
+	}
+
+	kvm_vgic_global_state.can_emulate_gicv2 = true;
+	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+
+	kvm_vgic_global_state.vcpu_base = info->vcpu.start;
+	kvm_vgic_global_state.type = VGIC_V2;
+	kvm_vgic_global_state.max_gic_vcpus = VGIC_V2_MAX_CPUS;
+
+	kvm_info("vgic-v2@%llx\n", info->vctrl.start);
+
+	return 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 8548297..de0e8e0 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -15,6 +15,9 @@
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <kvm/arm_vgic.h>
+#include <asm/kvm_mmu.h>
+#include <asm/kvm_asm.h>
 
 #include "vgic.h"
 
@@ -182,3 +185,49 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
+
+/**
+ * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
+ * @node:	pointer to the DT node
+ *
+ * Returns 0 if a GICv3 has been found, returns an error code otherwise
+ */
+int vgic_v3_probe(const struct gic_kvm_info *info)
+{
+	u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
+
+	/*
+	 * The ListRegs field is 5 bits, but there is a architectural
+	 * maximum of 16 list registers. Just ignore bit 4...
+	 */
+	kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
+	kvm_vgic_global_state.can_emulate_gicv2 = false;
+
+	if (!info->vcpu.start) {
+		kvm_info("GICv3: no GICV resource entry\n");
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else if (!PAGE_ALIGNED(info->vcpu.start)) {
+		pr_warn("GICV physical address 0x%llx not page aligned\n",
+			(unsigned long long)info->vcpu.start);
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
+		pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
+			(unsigned long long)resource_size(&info->vcpu),
+			PAGE_SIZE);
+		kvm_vgic_global_state.vcpu_base = 0;
+	} else {
+		kvm_vgic_global_state.vcpu_base = info->vcpu.start;
+		kvm_vgic_global_state.can_emulate_gicv2 = true;
+		kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+		kvm_info("vgic-v2@%llx\n", info->vcpu.start);
+	}
+	if (kvm_vgic_global_state.vcpu_base == 0)
+		kvm_info("disabling GICv2 emulation\n");
+	kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V3);
+
+	kvm_vgic_global_state.vctrl_base = NULL;
+	kvm_vgic_global_state.type = VGIC_V3;
+	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
+
+	return 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index de9dc71..f4244b6 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,6 +16,8 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#include <linux/irqchip/arm-gic-common.h>
+
 #define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
 #define IMPLEMENTER_ARM		0x43b
 
@@ -51,6 +53,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+int vgic_v2_probe(const struct gic_kvm_info *info);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -62,6 +65,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+int vgic_v3_probe(const struct gic_kvm_info *info);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -95,6 +99,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
 {
 }
 
+static inline int vgic_v3_probe(const struct gic_kvm_info *info)
+{
+	return -ENODEV;
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:48 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:48 +0200
Subject: [PULL 54/59] KVM: arm/arm64: vgic-new: vgic_init: implement
 map_resources
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-55-git-send-email-christoffer.dall@linaro.org>

From: Eric Auger <eric.auger at linaro.org>

map_resources is the last initialization step. It is executed on
first VCPU run. At that stage the code checks that userspace has provided
the base addresses for the relevant VGIC regions, which depend on the
type of VGIC that is exposed to the guest.  Also we check if the two
regions overlap.
If the checks succeeded, we register the respective register frames with
the kvm_io_bus framework.

If we emulate a GICv2, the function also forces vgic_init execution if
it has not been executed yet. Also we map the virtual GIC CPU interface
onto the guest's CPU interface.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/vgic/vgic.h       |  1 +
 virt/kvm/arm/vgic/vgic-init.c | 28 +++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   | 69 +++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c   | 71 +++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h      |  7 +++++
 5 files changed, 176 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index e7ae36b..17b2a73 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -201,6 +201,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type);
 void kvm_vgic_destroy(struct kvm *kvm);
 void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
+int kvm_vgic_map_resources(struct kvm *kvm);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index bed3240..a1442f7 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -323,6 +323,34 @@ int vgic_lazy_init(struct kvm *kvm)
 	return ret;
 }
 
+/* RESOURCE MAPPING */
+
+/**
+ * Map the MMIO regions depending on the VGIC model exposed to the guest
+ * called on the first VCPU run.
+ * Also map the virtual CPU interface into the VM.
+ * v2/v3 derivatives call vgic_init if not already done.
+ * vgic_ready() returns true if this function has succeeded.
+ * @kvm: kvm struct pointer
+ */
+int kvm_vgic_map_resources(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	int ret = 0;
+
+	mutex_lock(&kvm->lock);
+	if (!irqchip_in_kernel(kvm))
+		goto out;
+
+	if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+		ret = vgic_v2_map_resources(kvm);
+	else
+		ret = vgic_v3_map_resources(kvm);
+out:
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index fcbfa38..1fe031b 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -211,6 +211,75 @@ void vgic_v2_enable(struct kvm_vcpu *vcpu)
 {
 }
 
+/* check for overlapping regions and for regions crossing the end of memory */
+static bool vgic_v2_check_base(gpa_t dist_base, gpa_t cpu_base)
+{
+	if (dist_base + KVM_VGIC_V2_DIST_SIZE < dist_base)
+		return false;
+	if (cpu_base + KVM_VGIC_V2_CPU_SIZE < cpu_base)
+		return false;
+
+	if (dist_base + KVM_VGIC_V2_DIST_SIZE <= cpu_base)
+		return true;
+	if (cpu_base + KVM_VGIC_V2_CPU_SIZE <= dist_base)
+		return true;
+
+	return false;
+}
+
+int vgic_v2_map_resources(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	int ret = 0;
+
+	if (vgic_ready(kvm))
+		goto out;
+
+	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
+	    IS_VGIC_ADDR_UNDEF(dist->vgic_cpu_base)) {
+		kvm_err("Need to set vgic cpu and dist addresses first\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	if (!vgic_v2_check_base(dist->vgic_dist_base, dist->vgic_cpu_base)) {
+		kvm_err("VGIC CPU and dist frames overlap\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Initialize the vgic if this hasn't already been done on demand by
+	 * accessing the vgic state from userspace.
+	 */
+	ret = vgic_init(kvm);
+	if (ret) {
+		kvm_err("Unable to initialize VGIC dynamic data structures\n");
+		goto out;
+	}
+
+	ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V2);
+	if (ret) {
+		kvm_err("Unable to register VGIC MMIO regions\n");
+		goto out;
+	}
+
+	ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base,
+				    kvm_vgic_global_state.vcpu_base,
+				    KVM_VGIC_V2_CPU_SIZE, true);
+	if (ret) {
+		kvm_err("Unable to remap VGIC CPU to VCPU\n");
+		goto out;
+	}
+
+	dist->ready = true;
+
+out:
+	if (ret)
+		kvm_vgic_destroy(kvm);
+	return ret;
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index d1c0285..637ff2b 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -191,6 +191,77 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
 }
 
+/* check for overlapping regions and for regions crossing the end of memory */
+static bool vgic_v3_check_base(struct kvm *kvm)
+{
+	struct vgic_dist *d = &kvm->arch.vgic;
+	gpa_t redist_size = KVM_VGIC_V3_REDIST_SIZE;
+
+	redist_size *= atomic_read(&kvm->online_vcpus);
+
+	if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base)
+		return false;
+	if (d->vgic_redist_base + redist_size < d->vgic_redist_base)
+		return false;
+
+	if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE <= d->vgic_redist_base)
+		return true;
+	if (d->vgic_redist_base + redist_size <= d->vgic_dist_base)
+		return true;
+
+	return false;
+}
+
+int vgic_v3_map_resources(struct kvm *kvm)
+{
+	int ret = 0;
+	struct vgic_dist *dist = &kvm->arch.vgic;
+
+	if (vgic_ready(kvm))
+		goto out;
+
+	if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
+	    IS_VGIC_ADDR_UNDEF(dist->vgic_redist_base)) {
+		kvm_err("Need to set vgic distributor addresses first\n");
+		ret = -ENXIO;
+		goto out;
+	}
+
+	if (!vgic_v3_check_base(kvm)) {
+		kvm_err("VGIC redist and dist frames overlap\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * For a VGICv3 we require the userland to explicitly initialize
+	 * the VGIC before we need to use it.
+	 */
+	if (!vgic_initialized(kvm)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V3);
+	if (ret) {
+		kvm_err("Unable to register VGICv3 dist MMIO regions\n");
+		goto out;
+	}
+
+	ret = vgic_register_redist_iodevs(kvm, dist->vgic_redist_base);
+	if (ret) {
+		kvm_err("Unable to register VGICv3 redist MMIO regions\n");
+		goto out;
+	}
+
+	dist->ready = true;
+
+out:
+	if (ret)
+		kvm_vgic_destroy(kvm);
+	return ret;
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 5951551..7b300ca 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -55,6 +55,7 @@ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_enable(struct kvm_vcpu *vcpu);
 int vgic_v2_probe(const struct gic_kvm_info *info);
+int vgic_v2_map_resources(struct kvm *kvm);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -68,6 +69,7 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_enable(struct kvm_vcpu *vcpu);
 int vgic_v3_probe(const struct gic_kvm_info *info);
+int vgic_v3_map_resources(struct kvm *kvm);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -110,6 +112,11 @@ static inline int vgic_v3_probe(const struct gic_kvm_info *info)
 	return -ENODEV;
 }
 
+static inline int vgic_v3_map_resources(struct kvm *kvm)
+{
+	return -ENODEV;
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:47 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:47 +0200
Subject: [PULL 53/59] KVM: arm/arm64: vgic-new: vgic_init: implement vgic_init
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-54-git-send-email-christoffer.dall@linaro.org>

From: Eric Auger <eric.auger at linaro.org>

This patch allocates and initializes the data structures used
to model the vgic distributor and virtual cpu interfaces. At that
stage the number of IRQs and number of virtual CPUs is frozen.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/vgic/vgic.h       |   7 +-
 virt/kvm/arm/vgic/vgic-init.c | 217 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v2.c   |   5 +
 virt/kvm/arm/vgic/vgic-v3.c   |   5 +
 virt/kvm/arm/vgic/vgic.c      |   4 +
 virt/kvm/arm/vgic/vgic.h      |   8 ++
 6 files changed, 245 insertions(+), 1 deletion(-)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 0634d89..e7ae36b 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -119,6 +119,7 @@ struct vgic_io_device {
 struct vgic_dist {
 	bool			in_kernel;
 	bool			ready;
+	bool			initialized;
 
 	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
 	u32			vgic_model;
@@ -195,7 +196,11 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+void kvm_vgic_early_init(struct kvm *kvm);
 int kvm_vgic_create(struct kvm *kvm, u32 type);
+void kvm_vgic_destroy(struct kvm *kvm);
+void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
+void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
@@ -204,7 +209,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
 #define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
-#define vgic_initialized(k)	(false)
+#define vgic_initialized(k)	((k)->arch.vgic.initialized)
 #define vgic_ready(k)		((k)->arch.vgic.ready)
 #define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
 			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 15d5428..bed3240 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -22,6 +22,42 @@
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
+/*
+ * Initialization rules: there are multiple stages to the vgic
+ * initialization, both for the distributor and the CPU interfaces.
+ *
+ * Distributor:
+ *
+ * - kvm_vgic_early_init(): initialization of static data that doesn't
+ *   depend on any sizing information or emulation type. No allocation
+ *   is allowed there.
+ *
+ * - vgic_init(): allocation and initialization of the generic data
+ *   structures that depend on sizing information (number of CPUs,
+ *   number of interrupts). Also initializes the vcpu specific data
+ *   structures. Can be executed lazily for GICv2.
+ *
+ * CPU Interface:
+ *
+ * - kvm_vgic_cpu_early_init(): initialization of static data that
+ *   doesn't depend on any sizing information or emulation type. No
+ *   allocation is allowed there.
+ */
+
+/* EARLY INIT */
+
+/*
+ * Those 2 functions should not be needed anymore but they
+ * still are called from arm.c
+ */
+void kvm_vgic_early_init(struct kvm *kvm)
+{
+}
+
+void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu)
+{
+}
+
 /* CREATION */
 
 /**
@@ -29,6 +65,8 @@
  * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only)
  * or through the generic KVM_CREATE_DEVICE API ioctl.
  * irqchip_in_kernel() tells you if this function succeeded or not.
+ * @kvm: kvm struct pointer
+ * @type: KVM_DEV_TYPE_ARM_VGIC_V[23]
  */
 int kvm_vgic_create(struct kvm *kvm, u32 type)
 {
@@ -106,6 +144,185 @@ out:
 	return ret;
 }
 
+/* INIT/DESTROY */
+
+/**
+ * kvm_vgic_dist_init: initialize the dist data structures
+ * @kvm: kvm struct pointer
+ * @nr_spis: number of spis, frozen by caller
+ */
+static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct kvm_vcpu *vcpu0 = kvm_get_vcpu(kvm, 0);
+	int i;
+
+	dist->spis = kcalloc(nr_spis, sizeof(struct vgic_irq), GFP_KERNEL);
+	if (!dist->spis)
+		return  -ENOMEM;
+
+	/*
+	 * In the following code we do not take the irq struct lock since
+	 * no other action on irq structs can happen while the VGIC is
+	 * not initialized yet:
+	 * If someone wants to inject an interrupt or does a MMIO access, we
+	 * require prior initialization in case of a virtual GICv3 or trigger
+	 * initialization when using a virtual GICv2.
+	 */
+	for (i = 0; i < nr_spis; i++) {
+		struct vgic_irq *irq = &dist->spis[i];
+
+		irq->intid = i + VGIC_NR_PRIVATE_IRQS;
+		INIT_LIST_HEAD(&irq->ap_list);
+		spin_lock_init(&irq->irq_lock);
+		irq->vcpu = NULL;
+		irq->target_vcpu = vcpu0;
+		if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+			irq->targets = 0;
+		else
+			irq->mpidr = 0;
+	}
+	return 0;
+}
+
+/**
+ * kvm_vgic_vcpu_init: initialize the vcpu data structures and
+ * enable the VCPU interface
+ * @vcpu: the VCPU which's VGIC should be initialized
+ */
+static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+	int i;
+
+	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
+	spin_lock_init(&vgic_cpu->ap_list_lock);
+
+	/*
+	 * Enable and configure all SGIs to be edge-triggered and
+	 * configure all PPIs as level-triggered.
+	 */
+	for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
+		struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
+
+		INIT_LIST_HEAD(&irq->ap_list);
+		spin_lock_init(&irq->irq_lock);
+		irq->intid = i;
+		irq->vcpu = NULL;
+		irq->target_vcpu = vcpu;
+		irq->targets = 1U << vcpu->vcpu_id;
+		if (vgic_irq_is_sgi(i)) {
+			/* SGIs */
+			irq->enabled = 1;
+			irq->config = VGIC_CONFIG_EDGE;
+		} else {
+			/* PPIs */
+			irq->config = VGIC_CONFIG_LEVEL;
+		}
+	}
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_enable(vcpu);
+	else
+		vgic_v3_enable(vcpu);
+}
+
+/*
+ * vgic_init: allocates and initializes dist and vcpu data structures
+ * depending on two dimensioning parameters:
+ * - the number of spis
+ * - the number of vcpus
+ * The function is generally called when nr_spis has been explicitly set
+ * by the guest through the KVM DEVICE API. If not nr_spis is set to 256.
+ * vgic_initialized() returns true when this function has succeeded.
+ * Must be called with kvm->lock held!
+ */
+int vgic_init(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct kvm_vcpu *vcpu;
+	int ret = 0, i;
+
+	if (vgic_initialized(kvm))
+		return 0;
+
+	/* freeze the number of spis */
+	if (!dist->nr_spis)
+		dist->nr_spis = VGIC_NR_IRQS_LEGACY - VGIC_NR_PRIVATE_IRQS;
+
+	ret = kvm_vgic_dist_init(kvm, dist->nr_spis);
+	if (ret)
+		goto out;
+
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_vgic_vcpu_init(vcpu);
+
+	dist->initialized = true;
+out:
+	return ret;
+}
+
+static void kvm_vgic_dist_destroy(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+
+	mutex_lock(&kvm->lock);
+
+	dist->ready = false;
+	dist->initialized = false;
+
+	kfree(dist->spis);
+	kfree(dist->redist_iodevs);
+	dist->nr_spis = 0;
+
+	mutex_unlock(&kvm->lock);
+}
+
+void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
+}
+
+void kvm_vgic_destroy(struct kvm *kvm)
+{
+	struct kvm_vcpu *vcpu;
+	int i;
+
+	kvm_vgic_dist_destroy(kvm);
+
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_vgic_vcpu_destroy(vcpu);
+}
+
+/**
+ * vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest
+ * is a GICv2. A GICv3 must be explicitly initialized by the guest using the
+ * KVM_DEV_ARM_VGIC_GRP_CTRL KVM_DEVICE group.
+ * @kvm: kvm struct pointer
+ */
+int vgic_lazy_init(struct kvm *kvm)
+{
+	int ret = 0;
+
+	if (unlikely(!vgic_initialized(kvm))) {
+		/*
+		 * We only provide the automatic initialization of the VGIC
+		 * for the legacy case of a GICv2. Any other type must
+		 * be explicitly initialized once setup with the respective
+		 * KVM device call.
+		 */
+		if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2)
+			return -EBUSY;
+
+		mutex_lock(&kvm->lock);
+		ret = vgic_init(kvm);
+		mutex_unlock(&kvm->lock);
+	}
+
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 09777c8..fcbfa38 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -206,6 +206,11 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 			GICH_VMCR_PRIMASK_SHIFT;
 }
 
+/* not yet implemented */
+void vgic_v2_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index de0e8e0..d1c0285 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -186,6 +186,11 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
 
+/* not yet implemented */
+void vgic_v3_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 12ae84b..3318855 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -257,6 +257,10 @@ static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
 
 	trace_vgic_update_irq_pending(cpuid, intid, level);
 
+	ret = vgic_lazy_init(kvm);
+	if (ret)
+		return ret;
+
 	vcpu = kvm_get_vcpu(kvm, cpuid);
 	if (!vcpu && intid < VGIC_NR_PRIVATE_IRQS)
 		return -EINVAL;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index f4244b6..5951551 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -53,6 +53,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v2_enable(struct kvm_vcpu *vcpu);
 int vgic_v2_probe(const struct gic_kvm_info *info);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
@@ -65,6 +66,7 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v3_enable(struct kvm_vcpu *vcpu);
 int vgic_v3_probe(const struct gic_kvm_info *info);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
@@ -99,6 +101,10 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
 {
 }
 
+static inline void vgic_v3_enable(struct kvm_vcpu *vcpu)
+{
+}
+
 static inline int vgic_v3_probe(const struct gic_kvm_info *info)
 {
 	return -ENODEV;
@@ -112,5 +118,7 @@ static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 #endif
 
 void kvm_register_vgic_device(unsigned long type);
+int vgic_lazy_init(struct kvm *kvm);
+int vgic_init(struct kvm *kvm);
 
 #endif
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:46 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:46 +0200
Subject: [PULL 52/59] KVM: arm/arm64: vgic-new: vgic_init: implement
 vgic_create
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-53-git-send-email-christoffer.dall@linaro.org>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the vgic_creation function which is
called on CREATE_IRQCHIP VM IOCTL (v2 only) or KVM_CREATE_DEVICE

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/vgic/vgic.h       |  1 +
 virt/kvm/arm/vgic/vgic-init.c | 84 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 393489f..0634d89 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -195,6 +195,7 @@ struct vgic_cpu {
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
+int kvm_vgic_create(struct kvm *kvm, u32 type);
 int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 4523beb..15d5428 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -22,6 +22,90 @@
 #include <asm/kvm_mmu.h>
 #include "vgic.h"
 
+/* CREATION */
+
+/**
+ * kvm_vgic_create: triggered by the instantiation of the VGIC device by
+ * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only)
+ * or through the generic KVM_CREATE_DEVICE API ioctl.
+ * irqchip_in_kernel() tells you if this function succeeded or not.
+ */
+int kvm_vgic_create(struct kvm *kvm, u32 type)
+{
+	int i, vcpu_lock_idx = -1, ret;
+	struct kvm_vcpu *vcpu;
+
+	mutex_lock(&kvm->lock);
+
+	if (irqchip_in_kernel(kvm)) {
+		ret = -EEXIST;
+		goto out;
+	}
+
+	/*
+	 * This function is also called by the KVM_CREATE_IRQCHIP handler,
+	 * which had no chance yet to check the availability of the GICv2
+	 * emulation. So check this here again. KVM_CREATE_DEVICE does
+	 * the proper checks already.
+	 */
+	if (type == KVM_DEV_TYPE_ARM_VGIC_V2 &&
+		!kvm_vgic_global_state.can_emulate_gicv2) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/*
+	 * Any time a vcpu is run, vcpu_load is called which tries to grab the
+	 * vcpu->mutex.  By grabbing the vcpu->mutex of all VCPUs we ensure
+	 * that no other VCPUs are run while we create the vgic.
+	 */
+	ret = -EBUSY;
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		if (!mutex_trylock(&vcpu->mutex))
+			goto out_unlock;
+		vcpu_lock_idx = i;
+	}
+
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		if (vcpu->arch.has_run_once)
+			goto out_unlock;
+	}
+	ret = 0;
+
+	if (type == KVM_DEV_TYPE_ARM_VGIC_V2)
+		kvm->arch.max_vcpus = VGIC_V2_MAX_CPUS;
+	else
+		kvm->arch.max_vcpus = VGIC_V3_MAX_CPUS;
+
+	if (atomic_read(&kvm->online_vcpus) > kvm->arch.max_vcpus) {
+		ret = -E2BIG;
+		goto out_unlock;
+	}
+
+	kvm->arch.vgic.in_kernel = true;
+	kvm->arch.vgic.vgic_model = type;
+
+	/*
+	 * kvm_vgic_global_state.vctrl_base is set on vgic probe (kvm_arch_init)
+	 * it is stored in distributor struct for asm save/restore purpose
+	 */
+	kvm->arch.vgic.vctrl_base = kvm_vgic_global_state.vctrl_base;
+
+	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
+	kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
+	kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
+
+out_unlock:
+	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
+		vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
+		mutex_unlock(&vcpu->mutex);
+	}
+
+out:
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
 /* GENERIC PROBE */
 
 static void vgic_init_maintenance_interrupt(void *info)
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:50 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:50 +0200
Subject: [PULL 56/59] KVM: arm/arm64: vgic-new: Wire up irqfd injection
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-57-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

Connect to the new VGIC to the irqfd framework, so that we can
inject IRQs.
GSI routing and MSI routing is not yet implemented.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-irqfd.c | 52 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-irqfd.c

diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
new file mode 100644
index 0000000..c675513
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/kvm.h>
+#include <linux/kvm_host.h>
+#include <trace/events/kvm.h>
+
+int kvm_irq_map_gsi(struct kvm *kvm,
+		    struct kvm_kernel_irq_routing_entry *entries,
+		    int gsi)
+{
+	return 0;
+}
+
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned int irqchip,
+			 unsigned int pin)
+{
+	return pin;
+}
+
+int kvm_set_irq(struct kvm *kvm, int irq_source_id,
+		u32 irq, int level, bool line_status)
+{
+	unsigned int spi = irq + VGIC_NR_PRIVATE_IRQS;
+
+	trace_kvm_set_irq(irq, level, irq_source_id);
+
+	BUG_ON(!vgic_initialized(kvm));
+
+	return kvm_vgic_inject_irq(kvm, 0, spi, level);
+}
+
+/* MSI not implemented yet */
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
+		struct kvm *kvm, int irq_source_id,
+		int level, bool line_status)
+{
+	return 0;
+}
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:49 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:49 +0200
Subject: [PULL 55/59] KVM: arm/arm64: vgic-new: Add vgic_v2/v3_enable
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-56-git-send-email-christoffer.dall@linaro.org>

From: Eric Auger <eric.auger at linaro.org>

Enable the VGIC operation by properly initialising the registers
in the hypervisor GIC interface.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-v2.c | 11 ++++++++++-
 virt/kvm/arm/vgic/vgic-v3.c | 23 ++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 1fe031b..8ad42c2 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -206,9 +206,18 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 			GICH_VMCR_PRIMASK_SHIFT;
 }
 
-/* not yet implemented */
 void vgic_v2_enable(struct kvm_vcpu *vcpu)
 {
+	/*
+	 * By forcing VMCR to zero, the GIC will restore the binary
+	 * points to their reset values. Anything else resets to zero
+	 * anyway.
+	 */
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = 0;
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr = ~0;
+
+	/* Get the show on the road... */
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr = GICH_HCR_EN;
 }
 
 /* check for overlapping regions and for regions crossing the end of memory */
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 637ff2b..336a461 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -186,9 +186,30 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
 }
 
-/* not yet implemented */
 void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
+	struct vgic_v3_cpu_if *vgic_v3 = &vcpu->arch.vgic_cpu.vgic_v3;
+
+	/*
+	 * By forcing VMCR to zero, the GIC will restore the binary
+	 * points to their reset values. Anything else resets to zero
+	 * anyway.
+	 */
+	vgic_v3->vgic_vmcr = 0;
+	vgic_v3->vgic_elrsr = ~0;
+
+	/*
+	 * If we are emulating a GICv3, we do it in an non-GICv2-compatible
+	 * way, so we force SRE to 1 to demonstrate this to the guest.
+	 * This goes with the spec allowing the value to be RAO/WI.
+	 */
+	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+		vgic_v3->vgic_sre = ICC_SRE_EL1_SRE;
+	else
+		vgic_v3->vgic_sre = 0;
+
+	/* Get the show on the road... */
+	vgic_v3->vgic_hcr = ICH_HCR_EN;
 }
 
 /* check for overlapping regions and for regions crossing the end of memory */
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:51 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:51 +0200
Subject: [PULL 57/59] KVM: arm/arm64: vgic-new: implement mapped IRQ handling
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-58-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

We now store the mapped hardware IRQ number in our struct, so we
don't need the irq_phys_map for the new VGIC.
Implement the hardware IRQ mapping on top of the reworked arch
timer interface.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/vgic/vgic.h  |  5 +++++
 virt/kvm/arm/vgic/vgic.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index 17b2a73..3fbd175 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -206,6 +206,11 @@ int kvm_vgic_hyp_init(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level);
+int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			       bool level);
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq);
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
 
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 3318855..69b61ab 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -312,6 +312,47 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 	return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
 }
 
+int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
+			       bool level)
+{
+	return vgic_update_irq_pending(kvm, cpuid, intid, level, true);
+}
+
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+
+	BUG_ON(!irq);
+
+	spin_lock(&irq->irq_lock);
+
+	irq->hw = true;
+	irq->hwintid = phys_irq;
+
+	spin_unlock(&irq->irq_lock);
+
+	return 0;
+}
+
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+
+	BUG_ON(!irq);
+
+	if (!vgic_initialized(vcpu->kvm))
+		return -EAGAIN;
+
+	spin_lock(&irq->irq_lock);
+
+	irq->hw = false;
+	irq->hwintid = 0;
+
+	spin_unlock(&irq->irq_lock);
+
+	return 0;
+}
+
 /**
  * vgic_prune_ap_list - Remove non-relevant interrupts from the list
  *
@@ -564,3 +605,15 @@ void vgic_kick_vcpus(struct kvm *kvm)
 			kvm_vcpu_kick(vcpu);
 	}
 }
+
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+	bool map_is_active;
+
+	spin_lock(&irq->irq_lock);
+	map_is_active = irq->hw && irq->active;
+	spin_unlock(&irq->irq_lock);
+
+	return map_is_active;
+}
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:52 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:52 +0200
Subject: [PULL 58/59] KVM: arm/arm64: vgic-new: enable build
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-59-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

Now that the new VGIC implementation has reached feature parity with
the old one, add the new files to the build system and add a Kconfig
option to switch between the two versions.
We set the default to the new version to get maximum test coverage,
in case people experience problems they can switch back to the old
behaviour if needed.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 arch/arm/kvm/Kconfig          |  7 +++++++
 arch/arm/kvm/Makefile         | 11 +++++++++++
 arch/arm64/kvm/Kconfig        |  7 +++++++
 arch/arm64/kvm/Makefile       | 12 ++++++++++++
 virt/kvm/arm/hyp/vgic-v2-sr.c |  5 +++++
 5 files changed, 42 insertions(+)

diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 95a0005..02abfff 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -46,6 +46,13 @@ config KVM_ARM_HOST
 	---help---
 	  Provides host support for ARM processors.
 
+config KVM_NEW_VGIC
+	bool "New VGIC implementation"
+	depends on KVM
+	default y
+	---help---
+	  uses the new VGIC implementation
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index eb1bf43..a596b58 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -21,7 +21,18 @@ obj-$(CONFIG_KVM_ARM_HOST) += hyp/
 obj-y += kvm-arm.o init.o interrupts.o
 obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
+
+ifeq ($(CONFIG_KVM_NEW_VGIC),y)
+obj-y += $(KVM)/arm/vgic/vgic.o
+obj-y += $(KVM)/arm/vgic/vgic-init.o
+obj-y += $(KVM)/arm/vgic/vgic-irqfd.o
+obj-y += $(KVM)/arm/vgic/vgic-v2.o
+obj-y += $(KVM)/arm/vgic/vgic-mmio.o
+obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
+obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
+else
 obj-y += $(KVM)/arm/vgic.o
 obj-y += $(KVM)/arm/vgic-v2.o
 obj-y += $(KVM)/arm/vgic-v2-emul.o
+endif
 obj-y += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index aa2e34e..c4f26ef 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -54,6 +54,13 @@ config KVM_ARM_PMU
 	  Adds support for a virtual Performance Monitoring Unit (PMU) in
 	  virtual machines.
 
+config KVM_NEW_VGIC
+	bool "New VGIC implementation"
+	depends on KVM
+	default y
+        ---help---
+          uses the new VGIC implementation
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 122cff4..a7a958c 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -20,10 +20,22 @@ kvm-$(CONFIG_KVM_ARM_HOST) += emulate.o inject_fault.o regmap.o
 kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
 kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
 
+ifeq ($(CONFIG_KVM_NEW_VGIC),y)
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-irqfd.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
+else
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2-emul.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3-emul.o
+endif
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
 kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index caac41f..a3f12b3 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -21,7 +21,12 @@
 
 #include <asm/kvm_hyp.h>
 
+#ifdef CONFIG_KVM_NEW_VGIC
+extern struct vgic_global kvm_vgic_global_state;
+#define vgic_v2_params kvm_vgic_global_state
+#else
 extern struct vgic_params vgic_v2_params;
+#endif
 
 static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
 					    void __iomem *base)
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:53 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:53 +0200
Subject: [PULL 59/59] KVM: arm/arm64: vgic-new: Synchronize changes to active
 state
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-60-git-send-email-christoffer.dall@linaro.org>

When modifying the active state of an interrupt via the MMIO interface,
we should ensure that the write has the intended effect.

If a guest sets an interrupt to active, but that interrupt is already
flushed into a list register on a running VCPU, then that VCPU will
write the active state back into the struct vgic_irq upon returning from
the guest and syncing its state.  This is a non-benign race, because the
guest can observe that an interrupt is not active, and it can have a
reasonable expectations that other VCPUs will not ack any IRQs, and then
set the state to active, and expect it to stay that way.  Currently we
are not honoring this case.

Thefore, change both the SACTIVE and CACTIVE mmio handlers to stop the
world, change the irq state, potentially queue the irq if we're setting
it to active, and then continue.

We take this chance to slightly optimize these functions by not stopping
the world when touching private interrupts where there is inherently no
possible race.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 arch/arm/include/asm/kvm_host.h   |   2 +
 arch/arm/kvm/arm.c                |   8 ++-
 arch/arm64/include/asm/kvm_host.h |   2 +
 virt/kvm/arm/vgic/vgic-mmio.c     | 105 ++++++++++++++++++++++++--------------
 4 files changed, 77 insertions(+), 40 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 832be03..987da9f 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -229,6 +229,8 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
 void kvm_arm_halt_guest(struct kvm *kvm);
 void kvm_arm_resume_guest(struct kvm *kvm);
+void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu);
+void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu);
 
 int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
 unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index e89329d..5a599c2 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -502,7 +502,13 @@ void kvm_arm_halt_guest(struct kvm *kvm)
 	kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT);
 }
 
-static void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
+void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu)
+{
+	vcpu->arch.pause = true;
+	kvm_vcpu_kick(vcpu);
+}
+
+void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
 {
 	struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
 
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index fa94f91..38746d2 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -329,6 +329,8 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
 void kvm_arm_halt_guest(struct kvm *kvm);
 void kvm_arm_resume_guest(struct kvm *kvm);
+void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu);
+void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu);
 
 u64 __kvm_call_hyp(void *hypfn, ...);
 #define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__)
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 4ef3571..059595e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -173,6 +173,66 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
 	return value;
 }
 
+static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
+				    bool new_active_state)
+{
+	spin_lock(&irq->irq_lock);
+	/*
+	 * If this virtual IRQ was written into a list register, we
+	 * have to make sure the CPU that runs the VCPU thread has
+	 * synced back LR state to the struct vgic_irq.  We can only
+	 * know this for sure, when either this irq is not assigned to
+	 * anyone's AP list anymore, or the VCPU thread is not
+	 * running on any CPUs.
+	 *
+	 * In the opposite case, we know the VCPU thread may be on its
+	 * way back from the guest and still has to sync back this
+	 * IRQ, so we release and re-acquire the spin_lock to let the
+	 * other thread sync back the IRQ.
+	 */
+	while (irq->vcpu && /* IRQ may have state in an LR somewhere */
+	       irq->vcpu->cpu != -1) { /* VCPU thread is running */
+		BUG_ON(irq->intid < VGIC_NR_PRIVATE_IRQS);
+		cond_resched_lock(&irq->irq_lock);
+	}
+
+	irq->active = new_active_state;
+	if (new_active_state)
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	else
+		spin_unlock(&irq->irq_lock);
+}
+
+/*
+ * If we are fiddling with an IRQ's active state, we have to make sure the IRQ
+ * is not queued on some running VCPU's LRs, because then the change to the
+ * active state can be overwritten when the VCPU's state is synced coming back
+ * from the guest.
+ *
+ * For shared interrupts, we have to stop all the VCPUs because interrupts can
+ * be migrated while we don't hold the IRQ locks and we don't want to be
+ * chasing moving targets.
+ *
+ * For private interrupts, we only have to make sure the single and only VCPU
+ * that can potentially queue the IRQ is stopped.
+ */
+static void vgic_change_active_prepare(struct kvm_vcpu *vcpu, u32 intid)
+{
+	if (intid < VGIC_NR_PRIVATE_IRQS)
+		kvm_arm_halt_vcpu(vcpu);
+	else
+		kvm_arm_halt_guest(vcpu->kvm);
+}
+
+/* See vgic_change_active_prepare */
+static void vgic_change_active_finish(struct kvm_vcpu *vcpu, u32 intid)
+{
+	if (intid < VGIC_NR_PRIVATE_IRQS)
+		kvm_arm_resume_vcpu(vcpu);
+	else
+		kvm_arm_resume_guest(vcpu->kvm);
+}
+
 void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
 			     gpa_t addr, unsigned int len,
 			     unsigned long val)
@@ -180,32 +240,12 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
 	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
 	int i;
 
-	kvm_arm_halt_guest(vcpu->kvm);
+	vgic_change_active_prepare(vcpu, intid);
 	for_each_set_bit(i, &val, len * 8) {
 		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-
-		spin_lock(&irq->irq_lock);
-		/*
-		 * If this virtual IRQ was written into a list register, we
-		 * have to make sure the CPU that runs the VCPU thread has
-		 * synced back LR state to the struct vgic_irq.  We can only
-		 * know this for sure, when either this irq is not assigned to
-		 * anyone's AP list anymore, or the VCPU thread is not
-		 * running on any CPUs.
-		 *
-		 * In the opposite case, we know the VCPU thread may be on its
-		 * way back from the guest and still has to sync back this
-		 * IRQ, so we release and re-acquire the spin_lock to let the
-		 * other thread sync back the IRQ.
-		 */
-		while (irq->vcpu && /* IRQ may have state in an LR somewhere */
-		       irq->vcpu->cpu != -1) /* VCPU thread is running */
-			cond_resched_lock(&irq->irq_lock);
-
-		irq->active = false;
-		spin_unlock(&irq->irq_lock);
+		vgic_mmio_change_active(vcpu, irq, false);
 	}
-	kvm_arm_resume_guest(vcpu->kvm);
+	vgic_change_active_finish(vcpu, intid);
 }
 
 void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
@@ -215,25 +255,12 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
 	u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
 	int i;
 
+	vgic_change_active_prepare(vcpu, intid);
 	for_each_set_bit(i, &val, len * 8) {
 		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-
-		spin_lock(&irq->irq_lock);
-
-		/*
-		 * If the IRQ was already active or there is no target VCPU
-		 * assigned at the moment, then just proceed.
-		 */
-		if (irq->active || !irq->target_vcpu) {
-			irq->active = true;
-
-			spin_unlock(&irq->irq_lock);
-			continue;
-		}
-
-		irq->active = true;
-		vgic_queue_irq_unlock(vcpu->kvm, irq);
+		vgic_mmio_change_active(vcpu, irq, true);
 	}
+	vgic_change_active_finish(vcpu, intid);
 }
 
 unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
-- 
2.1.2.330.g565301e.dirty



From ivo.g.dimitrov.75 at gmail.com  Tue May 24 02:16:40 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Tue, 24 May 2016 12:16:40 +0300
Subject: [PATCHv3] support for AD5820 camera auto-focus coil
In-Reply-To: <20160524090433.GA1277@amd>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com> <20160521105607.GA20071@amd>
 <574049EF.2090208@gmail.com> <20160524090433.GA1277@amd>
Message-ID: <57441BF8.60606@gmail.com>



On 24.05.2016 12:04, Pavel Machek wrote:
> Hi!
>
>>> +static int ad5820_registered(struct v4l2_subdev *subdev)
>>> +{
>>> +	struct ad5820_device *coil = to_ad5820_device(subdev);
>>> +	struct i2c_client *client = v4l2_get_subdevdata(subdev);
>>> +
>>> +	coil->vana = regulator_get(&client->dev, "VANA");
>>
>> devm_regulator_get()?
>
> I'd rather avoid devm_ here. Driver is simple enough to allow it.
>

Now thinking about it, what would happen here if regulator_get() returns 
-EPROBE_DEFER? Wouldn't it be better to move regulator_get to the 
probe() function, something like:

static int ad5820_probe(struct i2c_client *client,
			const struct i2c_device_id *devid)
{
	struct ad5820_device *coil;
	int ret = 0;

	coil = devm_kzalloc(sizeof(*coil), GFP_KERNEL);
	if (coil == NULL)
		return -ENOMEM;

	coil->vana = devm_regulator_get(&client->dev, NULL);
	if (IS_ERR(coil->vana)) {
		ret = PTR_ERR(coil->vana);
		if (ret != -EPROBE_DEFER)
			dev_err(&client->dev, "could not get regulator for vana\n");
		return ret;
	}

	mutex_init(&coil->power_lock);
...

with the appropriate changes to remove() because of the devm API usage.

>>> +#define AD5820_RAMP_MODE_LINEAR		(0 << 3)
>>> +#define AD5820_RAMP_MODE_64_16		(1 << 3)
>>> +
>>> +struct ad5820_platform_data {
>>> +	int (*set_xshutdown)(struct v4l2_subdev *subdev, int set);
>>> +};
>>> +
>>> +#define to_ad5820_device(sd)	container_of(sd, struct ad5820_device, subdev)
>>> +
>>> +struct ad5820_device {
>>> +	struct v4l2_subdev subdev;
>>> +	struct ad5820_platform_data *platform_data;
>>> +	struct regulator *vana;
>>> +
>>> +	struct v4l2_ctrl_handler ctrls;
>>> +	u32 focus_absolute;
>>> +	u32 focus_ramp_time;
>>> +	u32 focus_ramp_mode;
>>> +
>>> +	struct mutex power_lock;
>>> +	int power_count;
>>> +
>>> +	int standby : 1;
>>> +};
>>> +
>>
>> The same for struct ad5820_device, is it really part of the public API?
>
> Let me check what can be done with it.
> 									Pavel
>


From ck.hu at mediatek.com  Tue May 24 02:16:50 2016
From: ck.hu at mediatek.com (CK Hu)
Date: Tue, 24 May 2016 17:16:50 +0800
Subject: [PATCH v7 4/4] CMDQ: suspend/resume protection
In-Reply-To: <1464006190-344-5-git-send-email-hs.liao@mediatek.com>
References: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
 <1464006190-344-5-git-send-email-hs.liao@mediatek.com>
Message-ID: <1464081410.30351.20.camel@mtksdaap41>

On Mon, 2016-05-23 at 20:23 +0800, HS Liao wrote:
> Add suspend/resume protection mechanism to prevent active task(s) in
> suspend.
> 
> Signed-off-by: HS Liao <hs.liao at mediatek.com>
> ---
>  drivers/soc/mediatek/mtk-cmdq.c | 174 ++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 166 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
> index f8c5d02..1a51cfb 100644
> --- a/drivers/soc/mediatek/mtk-cmdq.c
> +++ b/drivers/soc/mediatek/mtk-cmdq.c
> @@ -39,6 +39,7 @@
>  #define CMDQ_CLK_NAME			"gce"
>  
>  #define CMDQ_CURR_IRQ_STATUS		0x010
> +#define CMDQ_CURR_LOADED_THR		0x018
>  #define CMDQ_THR_SLOT_CYCLES		0x030
>  
>  #define CMDQ_THR_BASE			0x100
> @@ -125,6 +126,7 @@ enum cmdq_code {
>  
>  enum cmdq_task_state {
>  	TASK_STATE_BUSY,	/* task running on a thread */
> +	TASK_STATE_KILLED,	/* task process being killed */
>  	TASK_STATE_ERROR,	/* task execution error */
>  	TASK_STATE_DONE,	/* task finished */
>  };
> @@ -161,8 +163,12 @@ struct cmdq {
>  	u32			irq;
>  	struct workqueue_struct	*task_release_wq;
>  	struct cmdq_thread	thread[CMDQ_THR_MAX_COUNT];
> -	spinlock_t		exec_lock;	/* for exec task */
> +	atomic_t		thread_usage;
> +	struct mutex		task_mutex;	/* for task */
> +	spinlock_t		exec_lock;	/* for exec */
>  	struct clk		*clock;
> +	bool			suspending;
> +	bool			suspended;
>  };
>  
>  struct cmdq_subsys {
> @@ -196,15 +202,27 @@ static int cmdq_eng_get_thread(u64 flag)
>  		return CMDQ_THR_DISP_MISC_IDX;
>  }
>  
> -static void cmdq_task_release(struct cmdq_task *task)
> +static void cmdq_task_release_unlocked(struct cmdq_task *task)
>  {
>  	struct cmdq *cmdq = task->cmdq;
>  
> +	/* This func should be inside cmdq->task_mutex mutex */
> +	lockdep_assert_held(&cmdq->task_mutex);
> +
>  	dma_free_coherent(cmdq->dev, task->command_size, task->va_base,
>  			  task->mva_base);
>  	kfree(task);
>  }
>  
> +static void cmdq_task_release(struct cmdq_task *task)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +
> +	mutex_lock(&cmdq->task_mutex);
> +	cmdq_task_release_unlocked(task);
> +	mutex_unlock(&cmdq->task_mutex);
> +}
> +
>  static struct cmdq_task *cmdq_task_acquire(struct cmdq_rec *rec,
>  					   struct cmdq_task_cb cb)
>  {
> @@ -576,6 +594,12 @@ static int cmdq_task_wait_and_release(struct cmdq_task *task)
>  		dev_dbg(dev, "timeout!\n");
>  
>  	spin_lock_irqsave(&cmdq->exec_lock, flags);
> +
> +	if (cmdq->suspending && task->task_state == TASK_STATE_KILLED) {
> +		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +		return 0;
> +	}
> +
>  	if (task->task_state != TASK_STATE_DONE)
>  		err = cmdq_task_handle_error_result(task);
>  	if (list_empty(&thread->task_busy_list))
> @@ -584,7 +608,9 @@ static int cmdq_task_wait_and_release(struct cmdq_task *task)
>  
>  	/* release regardless of success or not */
>  	clk_disable_unprepare(cmdq->clock);
> -	cmdq_task_release(task);
> +	atomic_dec(&cmdq->thread_usage);
> +	if (!(task->cmdq->suspending && task->task_state == TASK_STATE_KILLED))
> +		cmdq_task_release(task);
>  
>  	return err;
>  }
> @@ -597,12 +623,28 @@ static void cmdq_task_wait_release_work(struct work_struct *work_item)
>  	cmdq_task_wait_and_release(task);
>  }
>  
> -static void cmdq_task_wait_release_schedule(struct cmdq_task *task)
> +static void cmdq_task_wait_release_schedule(struct cmdq *cmdq,
> +					    struct cmdq_task *task)
>  {
> -	struct cmdq *cmdq = task->cmdq;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> +
> +	if (cmdq->suspending || cmdq->suspended) {
> +		/*
> +		 * This means system is suspened between
> +		 * cmdq_task_submit_async() and
> +		 * cmdq_task_wait_release_schedule(), so return immediately.
> +		 * This task should be forced to remove by suspend flow.
> +		 */
> +		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +		return;
> +	}
>  
>  	INIT_WORK(&task->release_work, cmdq_task_wait_release_work);
>  	queue_work(cmdq->task_release_wq, &task->release_work);
> +
> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
>  }
>  
>  static int cmdq_rec_realloc_cmd_buffer(struct cmdq_rec *rec, size_t size)
> @@ -766,18 +808,31 @@ static int _cmdq_rec_flush(struct cmdq_rec *rec, struct cmdq_task **task_out,
>  	struct cmdq_thread *thread;
>  	int err;
>  
> +	mutex_lock(&cmdq->task_mutex);
> +	if (rec->cmdq->suspending || rec->cmdq->suspended) {
> +		dev_err(rec->cmdq->dev,
> +			"%s is called after suspending\n", __func__);
> +		mutex_unlock(&cmdq->task_mutex);
> +		return -EPERM;
> +	}
> +
>  	err = cmdq_rec_finalize(rec);
> -	if (err < 0)
> +	if (err < 0) {
> +		mutex_unlock(&cmdq->task_mutex);
>  		return err;
> +	}
>  
>  	task_cb.cb = cb;
>  	task_cb.data = data;
>  	*task_out = cmdq_task_acquire(rec, task_cb);
> -	if (!(*task_out))
> +	if (!(*task_out)) {
> +		mutex_unlock(&cmdq->task_mutex);
>  		return -EFAULT;
> +	}
>  
>  	thread = &cmdq->thread[cmdq_eng_get_thread((*task_out)->engine_flag)];
>  	cmdq_task_exec(*task_out, thread);
> +	mutex_unlock(&cmdq->task_mutex);
>  	return 0;
>  }
>  
> @@ -802,7 +857,13 @@ int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
>  	err = _cmdq_rec_flush(rec, &task, cb, data);
>  	if (err < 0)
>  		return err;
> -	cmdq_task_wait_release_schedule(task);
> +
> +	/*
> +	 * Task could be released in suspend flow,
> +	 * so we have to pass cmdq as parameter.
> +	 */
> +	cmdq_task_wait_release_schedule(rec->cmdq, task);
> +
>  	return 0;
>  }
>  EXPORT_SYMBOL(cmdq_rec_flush_async);
> @@ -814,6 +875,95 @@ void cmdq_rec_destroy(struct cmdq_rec *rec)
>  }
>  EXPORT_SYMBOL(cmdq_rec_destroy);
>  
> +static int cmdq_suspend(struct device *dev)
> +{
> +	struct cmdq *cmdq = dev_get_drvdata(dev);
> +	u32 exec_threads;
> +	int ref_count;
> +	unsigned long flags;
> +	struct cmdq_thread *thread;
> +	struct cmdq_task *task, *tmp;
> +	int i;
> +
> +	/* lock to prevent new tasks */
> +	mutex_lock(&cmdq->task_mutex);
> +	cmdq->suspending = true;
> +
> +	exec_threads = readl(cmdq->base + CMDQ_CURR_LOADED_THR);
> +	ref_count = atomic_read(&cmdq->thread_usage);
> +	if (ref_count <= 0 && !(exec_threads & CMDQ_THR_EXECUTING))
> +		goto exit;
> +
> +	dev_err(dev, "suspend: kill running, tasks.\n");
> +	dev_err(dev, "threads: 0x%08x, ref:%d\n", exec_threads, ref_count);
> +
> +	/*
> +	 * We need to ensure the system is ready to suspend,
> +	 * so kill all running CMDQ tasks and release HW engines.
> +	 */
> +
> +	/* remove all active tasks from thread and disable thread */
> +	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
> +		thread = &cmdq->thread[i];
> +
> +		if (list_empty(&thread->task_busy_list))
> +			continue;
> +
> +		/* prevent clk disable in release flow */
> +		clk_prepare_enable(cmdq->clock);
> +		cmdq_thread_suspend(cmdq, thread);
> +
> +		list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
> +					 list_entry) {
> +			bool already_done = false;
> +
> +			spin_lock_irqsave(&cmdq->exec_lock, flags);
> +			if (task->task_state == TASK_STATE_BUSY) {
> +				/* still wait_event */
> +				list_del(&task->list_entry);
> +				task->task_state = TASK_STATE_KILLED;
> +			} else {
> +				/* almost finish its work */
> +				already_done = true;
> +			}
> +			spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +
> +			/*
> +			 * TASK_STATE_KILLED will unlock
> +			 * wait_event_timeout in cmdq_task_wait_and_release(),
> +			 * so flush_work to wait auto release flow.
> +			 *
> +			 * We don't know processes running order,
> +			 * so call cmdq_task_release_unlocked() here to
> +			 * prevent releasing task before flush_work, and
> +			 * also to prevent deadlock of task_mutex.
> +			 */
> +			if (!already_done) {
> +				flush_work(&task->release_work);
> +				cmdq_task_release_unlocked(task);
> +			}
> +		}
> +
> +		cmdq_thread_resume(thread);
> +		cmdq_thread_disable(cmdq, &cmdq->thread[i]);
> +		clk_disable_unprepare(cmdq->clock);
> +	}

It's cmdq client's bug if there are some tasks have not been executed
while cmdq is suspending. I think cmdq can simply wait these tasks to be
done or timeout rather than killing them because it's unnecessary to
speed up anything in error state. Just wait for cmdq client to fix this
bug.

This 'for loop' can be simply replace by:

flush_workqueue(cmdq->task_release_wq);

But this does not wait for task which is created by cmdq_rec_flush().
One solution for this is to re-write cmdq_rec_flush() as below:

struct cmdq_flush_completion {
	struct completion cmplt;
	bool err;
};

static int cmdq_rec_flush_cb(struct cmdq_cb_data data)
{
	struct cmdq_flush_completion *cmplt = data.data;

	cmplt->err = data.err;
	complete(&cmplt->cmplt);

	return 0;
}

int cmdq_rec_flush(struct cmdq_rec *rec)
{
	int err;
	struct cmdq_flush_completion cmplt;

	init_completion(&cmplt.cmplt);
	err = cmdq_rec_flush_async(rec, cmdq_rec_flush_cb, &cmplt);
	if (err < 0)
		return err;
	wait_for_completion(&cmplt.cmplt);
	return cmplt.err ? -EFAULT : 0;
}


> +
> +exit:
> +	cmdq->suspended = true;
> +	cmdq->suspending = false;
> +	mutex_unlock(&cmdq->task_mutex);
> +	return 0; /* ALWAYS allow suspend */
> +}
> +
> +static int cmdq_resume(struct device *dev)
> +{
> +	struct cmdq *cmdq = dev_get_drvdata(dev);
> +
> +	cmdq->suspended = false;
> +	return 0;
> +}
> +
>  static int cmdq_remove(struct platform_device *pdev)
>  {
>  	struct cmdq *cmdq = platform_get_drvdata(pdev);
> @@ -852,6 +1002,7 @@ static int cmdq_probe(struct platform_device *pdev)
>  	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
>  		dev, cmdq->base, cmdq->irq);
>  
> +	mutex_init(&cmdq->task_mutex);
>  	spin_lock_init(&cmdq->exec_lock);
>  	cmdq->task_release_wq = alloc_ordered_workqueue(
>  			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI,
> @@ -879,6 +1030,7 @@ static int cmdq_probe(struct platform_device *pdev)
>  		err = PTR_ERR(cmdq->clock);
>  		goto fail;
>  	}
> +
>  	return 0;
>  
>  fail:
> @@ -886,6 +1038,11 @@ fail:
>  	return err;
>  }
>  
> +static const struct dev_pm_ops cmdq_pm_ops = {
> +	.suspend = cmdq_suspend,
> +	.resume = cmdq_resume,
> +};
> +
>  static const struct of_device_id cmdq_of_ids[] = {
>  	{.compatible = "mediatek,mt8173-gce",},
>  	{}
> @@ -897,6 +1054,7 @@ static struct platform_driver cmdq_drv = {
>  	.driver = {
>  		.name = CMDQ_DRIVER_DEVICE_NAME,
>  		.owner = THIS_MODULE,
> +		.pm = &cmdq_pm_ops,
>  		.of_match_table = cmdq_of_ids,
>  	}
>  };




From pavel at ucw.cz  Tue May 24 02:17:46 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Tue, 24 May 2016 11:17:46 +0200
Subject: [PATCHv4] support for AD5820 camera auto-focus coil
In-Reply-To: <20160524090433.GA1277@amd>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com> <20160521105607.GA20071@amd>
 <574049EF.2090208@gmail.com> <20160524090433.GA1277@amd>
Message-ID: <20160524091746.GA14536@amd>

This adds support for AD5820 autofocus coil, found for example in
Nokia N900 smartphone.

Signed-off-by: Pavel Machek <pavel at ucw.cz>

---
v2: simple cleanups, fix error paths, simplify probe
v3: more cleanups, remove printk, add include
v4: remove header file.

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 993dc50..77313a1 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -279,6 +279,13 @@ config VIDEO_ML86V7667
 	  To compile this driver as a module, choose M here: the
 	  module will be called ml86v7667.
 
+config VIDEO_AD5820
+	tristate "AD5820 lens voice coil support"
+	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+	---help---
+	  This is a driver for the AD5820 camera lens voice coil.
+	  It is used for example in Nokia N900 (RX-51).
+
 config VIDEO_SAA7110
 	tristate "Philips SAA7110 video decoder"
 	depends on VIDEO_V4L2 && I2C
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 94f2c99..34434ae 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -19,6 +20,7 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
 obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
 obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
+obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o
 obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
 obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
 obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
new file mode 100644
index 0000000..f956bd3
--- /dev/null
+++ b/drivers/media/i2c/ad5820.c
@@ -0,0 +1,438 @@
+/*
+ * drivers/media/i2c/ad5820.c
+ *
+ * AD5820 DAC driver for camera voice coil focus.
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2007 Texas Instruments
+ * Copyright (C) 2016 Pavel Machek <pavel at ucw.cz>
+ *
+ * Contact: Tuukka Toivonen
+ *          Sakari Ailus
+ *
+ * Based on af_d88.c by Texas Instruments.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/regulator/consumer.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#define AD5820_NAME		"ad5820"
+
+/* Register definitions */
+#define AD5820_POWER_DOWN		(1 << 15)
+#define AD5820_DAC_SHIFT		4
+#define AD5820_RAMP_MODE_LINEAR		(0 << 3)
+#define AD5820_RAMP_MODE_64_16		(1 << 3)
+
+#define CODE_TO_RAMP_US(s)	((s) == 0 ? 0 : (1 << ((s) - 1)) * 50)
+#define RAMP_US_TO_CODE(c)	fls(((c) + ((c)>>1)) / 50)
+
+#define to_ad5820_device(sd)	container_of(sd, struct ad5820_device, subdev)
+
+struct ad5820_device {
+	struct v4l2_subdev subdev;
+	struct ad5820_platform_data *platform_data;
+	struct regulator *vana;
+
+	struct v4l2_ctrl_handler ctrls;
+	u32 focus_absolute;
+	u32 focus_ramp_time;
+	u32 focus_ramp_mode;
+
+	struct mutex power_lock;
+	int power_count;
+
+	int standby : 1;
+};
+
+/**
+ * @brief I2C write using i2c_transfer().
+ * @param coil - the driver data structure
+ * @param data - register value to be written
+ * @returns nonnegative on success, negative if failed
+ */
+static int ad5820_write(struct ad5820_device *coil, u16 data)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&coil->subdev);
+	struct i2c_msg msg;
+	int r;
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	data = cpu_to_be16(data);
+	msg.addr  = client->addr;
+	msg.flags = 0;
+	msg.len   = 2;
+	msg.buf   = (u8 *)&data;
+
+	r = i2c_transfer(client->adapter, &msg, 1);
+	if (r < 0) {
+		dev_err(&client->dev, "write failed, error %d\n", r);
+		return r;
+	}
+
+	return 0;
+}
+
+/*
+ * Calculate status word and write it to the device based on current
+ * values of V4L2 controls. It is assumed that the stored V4L2 control
+ * values are properly limited and rounded.
+ */
+static int ad5820_update_hw(struct ad5820_device *coil)
+{
+	u16 status;
+
+	status = RAMP_US_TO_CODE(coil->focus_ramp_time);
+	status |= coil->focus_ramp_mode
+		? AD5820_RAMP_MODE_64_16 : AD5820_RAMP_MODE_LINEAR;
+	status |= coil->focus_absolute << AD5820_DAC_SHIFT;
+
+	if (coil->standby)
+		status |= AD5820_POWER_DOWN;
+
+	return ad5820_write(coil, status);
+}
+
+/*
+ * Power handling
+ */
+static int ad5820_power_off(struct ad5820_device *coil, int standby)
+{
+	int ret = 0;
+
+	/*
+	 * Go to standby first as real power off my be denied by the hardware
+	 * (single power line control for both coil and sensor).
+	 */
+	if (standby) {
+		coil->standby = 1;
+		ret = ad5820_update_hw(coil);
+	}
+
+	ret |= regulator_disable(coil->vana);
+
+	return ret;
+}
+
+static int ad5820_power_on(struct ad5820_device *coil, int restore)
+{
+	int ret;
+
+	ret = regulator_enable(coil->vana);
+	if (ret < 0)
+		return ret;
+
+	if (restore) {
+		/* Restore the hardware settings. */
+		coil->standby = 0;
+		ret = ad5820_update_hw(coil);
+		if (ret)
+			goto fail;
+	}
+	return 0;
+
+fail:
+	coil->standby = 1;
+	regulator_disable(coil->vana);
+
+	return ret;
+}
+
+/*
+ * V4L2 controls
+ */
+static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ad5820_device *coil =
+		container_of(ctrl->handler, struct ad5820_device, ctrls);
+	u32 code;
+
+	switch (ctrl->id) {
+	case V4L2_CID_FOCUS_ABSOLUTE:
+		coil->focus_absolute = ctrl->val;
+		return ad5820_update_hw(coil);
+
+	case V4L2_CID_FOCUS_AD5820_RAMP_TIME:
+		code = RAMP_US_TO_CODE(ctrl->val);
+		ctrl->val = CODE_TO_RAMP_US(code);
+		coil->focus_ramp_time = ctrl->val;
+		break;
+
+	case V4L2_CID_FOCUS_AD5820_RAMP_MODE:
+		coil->focus_ramp_mode = ctrl->val;
+		break;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops ad5820_ctrl_ops = {
+	.s_ctrl = ad5820_set_ctrl,
+};
+
+static const char * const ad5820_focus_menu[] = {
+	"Linear ramp",
+	"64/16 ramp",
+};
+
+static const struct v4l2_ctrl_config ad5820_ctrls[] = {
+	{
+		.ops		= &ad5820_ctrl_ops,
+		.id		= V4L2_CID_FOCUS_AD5820_RAMP_TIME,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Focus ramping time [us]",
+		.min		= 0,
+		.max		= 3200,
+		.step		= 50,
+		.def		= 0,
+		.flags		= 0,
+	},
+	{
+		.ops		= &ad5820_ctrl_ops,
+		.id		= V4L2_CID_FOCUS_AD5820_RAMP_MODE,
+		.type		= V4L2_CTRL_TYPE_MENU,
+		.name		= "Focus ramping mode",
+		.min		= 0,
+		.max		= ARRAY_SIZE(ad5820_focus_menu),
+		.step		= 0,
+		.def		= 0,
+		.flags		= 0,
+		.qmenu		= ad5820_focus_menu,
+	},
+};
+
+
+static int ad5820_init_controls(struct ad5820_device *coil)
+{
+	unsigned int i;
+
+	v4l2_ctrl_handler_init(&coil->ctrls, ARRAY_SIZE(ad5820_ctrls) + 1);
+
+	/*
+	 * V4L2_CID_FOCUS_ABSOLUTE
+	 *
+	 * Minimum current is 0 mA, maximum is 100 mA. Thus, 1 code is
+	 * equivalent to 100/1023 = 0.0978 mA. Nevertheless, we do not use [mA]
+	 * for focus position, because it is meaningless for user. Meaningful
+	 * would be to use focus distance or even its inverse, but since the
+	 * driver doesn't have sufficiently knowledge to do the conversion, we
+	 * will just use abstract codes here. In any case, smaller value = focus
+	 * position farther from camera. The default zero value means focus at
+	 * infinity, and also least current consumption.
+	 */
+	v4l2_ctrl_new_std(&coil->ctrls, &ad5820_ctrl_ops,
+			  V4L2_CID_FOCUS_ABSOLUTE, 0, 1023, 1, 0);
+
+	/* V4L2_CID_TEST_PATTERN and V4L2_CID_MODE_* */
+	for (i = 0; i < ARRAY_SIZE(ad5820_ctrls); ++i)
+		v4l2_ctrl_new_custom(&coil->ctrls, &ad5820_ctrls[i], NULL);
+
+	if (coil->ctrls.error)
+		return coil->ctrls.error;
+
+	coil->focus_absolute = 0;
+	coil->focus_ramp_time = 0;
+	coil->focus_ramp_mode = 0;
+
+	coil->subdev.ctrl_handler = &coil->ctrls;
+
+	return 0;
+}
+
+/*
+ * V4L2 subdev operations
+ */
+static int ad5820_registered(struct v4l2_subdev *subdev)
+{
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+
+	coil->vana = regulator_get(&client->dev, "VANA");
+	if (IS_ERR(coil->vana)) {
+		dev_err(&client->dev, "could not get regulator for vana\n");
+		return -ENODEV;
+	}
+
+	return ad5820_init_controls(coil);
+}
+
+static int
+ad5820_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+	int ret = 0;
+
+	mutex_lock(&coil->power_lock);
+
+	/*
+	 * If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (coil->power_count == !on) {
+		ret = on ? ad5820_power_on(coil, 1) : ad5820_power_off(coil, 1);
+		if (ret < 0)
+			goto done;
+	}
+
+	/* Update the power count. */
+	coil->power_count += on ? 1 : -1;
+	WARN_ON(coil->power_count < 0);
+
+done:
+	mutex_unlock(&coil->power_lock);
+	return ret;
+}
+
+static int ad5820_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return ad5820_set_power(sd, 1);
+}
+
+static int ad5820_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return ad5820_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_core_ops ad5820_core_ops = {
+	.s_power = ad5820_set_power,
+};
+
+static const struct v4l2_subdev_ops ad5820_ops = {
+	.core = &ad5820_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops ad5820_internal_ops = {
+	.registered = ad5820_registered,
+	.open = ad5820_open,
+	.close = ad5820_close,
+};
+
+/*
+ * I2C driver
+ */
+#ifdef CONFIG_PM
+
+static int ad5820_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	if (!coil->power_count)
+		return 0;
+
+	return ad5820_power_off(coil, 0);
+}
+
+static int ad5820_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	if (!coil->power_count)
+		return 0;
+
+	return ad5820_power_on(coil, 1);
+}
+
+#else
+
+#define ad5820_suspend	NULL
+#define ad5820_resume	NULL
+
+#endif /* CONFIG_PM */
+
+static int ad5820_probe(struct i2c_client *client,
+			const struct i2c_device_id *devid)
+{
+	struct ad5820_device *coil;
+	int ret = 0;
+
+	coil = kzalloc(sizeof(*coil), GFP_KERNEL);
+	if (!coil)
+		return -ENOMEM;
+
+	mutex_init(&coil->power_lock);
+
+	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
+	coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	coil->subdev.internal_ops = &ad5820_internal_ops;
+	strcpy(coil->subdev.name, "ad5820 focus");
+
+	ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
+	if (ret < 0)
+		goto free;
+
+	ret = v4l2_async_register_subdev(&coil->subdev);
+	if (ret < 0)
+		goto cleanup;
+
+	return ret;
+
+cleanup:
+	media_entity_cleanup(&coil->subdev.entity);
+
+free:
+	kfree(coil);
+
+	return ret;
+}
+
+static int __exit ad5820_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	v4l2_device_unregister_subdev(&coil->subdev);
+	v4l2_ctrl_handler_free(&coil->ctrls);
+	media_entity_cleanup(&coil->subdev.entity);
+	if (coil->vana)
+		regulator_put(coil->vana);
+
+	kfree(coil);
+
+	return 0;
+}
+
+static const struct i2c_device_id ad5820_id_table[] = {
+	{ AD5820_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ad5820_id_table);
+
+static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume);
+
+static struct i2c_driver ad5820_i2c_driver = {
+	.driver		= {
+		.name	= AD5820_NAME,
+		.pm	= &ad5820_pm,
+	},
+	.probe		= ad5820_probe,
+	.remove		= __exit_p(ad5820_remove),
+	.id_table	= ad5820_id_table,
+};
+
+module_i2c_driver(ad5820_i2c_driver);
+
+MODULE_AUTHOR("Tuukka Toivonen");
+MODULE_DESCRIPTION("AD5820 camera lens driver");
+MODULE_LICENSE("GPL");


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From mcoquelin.stm32 at gmail.com  Tue May 24 02:20:11 2016
From: mcoquelin.stm32 at gmail.com (Maxime Coquelin)
Date: Tue, 24 May 2016 11:20:11 +0200
Subject: [PATCH] hwrng: stm32 - fix build warning
In-Reply-To: <6044541.yeLQbYg2Jv@wuerfel>
References: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>
 <12548318.auB4PSA3KC@wuerfel>
 <CALszF6BPPA=tezMLhmdC4YFwmH1tGhDxCNDZNwGp1cTDWP7Fmg@mail.gmail.com>
 <6044541.yeLQbYg2Jv@wuerfel>
Message-ID: <CALszF6BAFgoccC6fmkdnwQxwHmQ35oLcor6v9yOLyVeXrt-KGA@mail.gmail.com>

2016-05-24 10:58 GMT+02:00 Arnd Bergmann <arnd at arndb.de>:
> On Tuesday, May 24, 2016 10:50:17 AM CEST Maxime Coquelin wrote:
>> diff --git a/drivers/char/hw_random/stm32-rng.c
>> b/drivers/char/hw_random/stm32-rng.c
>> index 92a810648bd0..2a0fc90e4dc3 100644
>> --- a/drivers/char/hw_random/stm32-rng.c
>> +++ b/drivers/char/hw_random/stm32-rng.c
>> @@ -68,6 +68,10 @@ static int stm32_rng_read(struct hwrng *rng, void
>> *data, size_t max, bool wait)
>>                         } while (!sr && --timeout);
>>                 }
>>
>> +               if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
>> +                               "bad RNG status - %x\n", sr))
>> +                       writel_relaxed(0, priv->base + RNG_SR);
>> +
>>                 /* If error detected or data not ready... */
>>                 if (sr != RNG_SR_DRDY)
>>                         break;
>> @@ -79,10 +83,6 @@ static int stm32_rng_read(struct hwrng *rng, void
>> *data, size_t max, bool wait)
>>                 max -= sizeof(u32);
>>         }
>>
>> -       if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
>> -                     "bad RNG status - %x\n", sr))
>> -               writel_relaxed(0, priv->base + RNG_SR);
>> -
>>         pm_runtime_mark_last_busy((struct device *) priv->rng.priv);
>>         pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv);
>>
>> Thanks,
>>
>
> Yes, that looks good to me.

Thanks!
Sudip, do you want to send the patch, or I manage to do it?

Maxime


From linus.walleij at linaro.org  Tue May 24 02:23:37 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 24 May 2016 11:23:37 +0200
Subject: [PATCH 0/7] pinctrl: meson: Add a bunch more pins
In-Reply-To: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
Message-ID: <CACRpkdY9oGZLt431NwTaFmZk98O8n3ZnMA1odhYZtcH7P1p=Jg@mail.gmail.com>

On Fri, May 6, 2016 at 4:21 PM, Kevin Hilman <khilman at baylibre.com> wrote:

> Add support for several more devices, both in the EE domain and in the
> AO domain.  Also, add the pins to the corresponding DTS files.
>
> Tested on odroid-c2 and Amlogic P200 boards, and verified with working
> ethernet.
>
> Depends on the initial GXBB pinctrl support from Carlo[1].  Also
> available in my git tree[2] with all the dependencies included.

These don't apply anomore sadly, Kevin can you rebase on
Torvalds' HEAD and resend, and include Carlo's ACK on them
so I can merge them in the next kernel cycle?

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 24 02:28:04 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 24 May 2016 11:28:04 +0200
Subject: [PATCH v2 1/2] pinctrl: Add Oxford Semiconductor OXNAS pinctrl
 and gpio driver
In-Reply-To: <1462952062-5316-2-git-send-email-narmstrong@baylibre.com>
References: <1462952062-5316-1-git-send-email-narmstrong@baylibre.com>
 <1462952062-5316-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <CACRpkdaJ_aXVqYwrWL_F9D6tgeD8A9R5FmNo5X7uyf4pxmo5WA@mail.gmail.com>

On Wed, May 11, 2016 at 9:34 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:

> Add pinctrl and gpio control support to Oxford Semiconductor OXNAS SoC Family.
> This version supports the ARM926EJ-S based OX810SE SoC with 34 IO pins.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>

Patch applied for the next kernel cycle.
Looks clean and nice.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 24 02:29:37 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 24 May 2016 11:29:37 +0200
Subject: [PATCH v2 2/2] dt-bindings: Add Oxford Semiconductor OXNAS
 pinctrl and gpio bindings
In-Reply-To: <1462952062-5316-3-git-send-email-narmstrong@baylibre.com>
References: <1462952062-5316-1-git-send-email-narmstrong@baylibre.com>
 <1462952062-5316-3-git-send-email-narmstrong@baylibre.com>
Message-ID: <CACRpkdZi5t3onQvXJeWcTfnVV7zn1Z=F_NPTzht0E5CAOsDh6A@mail.gmail.com>

On Wed, May 11, 2016 at 9:34 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:

> Add pinctrl and gpio DT bindings for Oxford Semiconductor OXNAS SoC Family.
> This version supports the ARM926EJ-S based OX810SE SoC with 34 IO pins.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>

Patch applied with Rob's ACK.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 24 02:35:20 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 24 May 2016 11:35:20 +0200
Subject: [PATCH v2 1/2] pinctrl: Add Oxford Semiconductor OXNAS pinctrl
 and gpio driver
In-Reply-To: <1462952062-5316-2-git-send-email-narmstrong@baylibre.com>
References: <1462952062-5316-1-git-send-email-narmstrong@baylibre.com>
 <1462952062-5316-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <CACRpkdZPMqRNn9rmcC4HYVKrdS7cxBD7O7oE4YPrP7L-0_Wakg@mail.gmail.com>

On Wed, May 11, 2016 at 9:34 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:

> Add pinctrl and gpio control support to Oxford Semiconductor OXNAS SoC Family.
> This version supports the ARM926EJ-S based OX810SE SoC with 34 IO pins.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>

I tried implementing a .get_direction() callback for the Oxnas GPIO
(this is good to have, for debugfs and for the new userspace ABI).

However:

> +/* GPIO Registers */
> +#define INPUT_VALUE    0x00
> +#define IRQ_PENDING    0x0c
> +#define OUTPUT_SET     0x14
> +#define OUTPUT_CLEAR   0x18
> +#define OUTPUT_EN_SET  0x1c
> +#define OUTPUT_EN_CLEAR        0x20
> +#define RE_IRQ_ENABLE  0x28
> +#define FE_IRQ_ENABLE  0x2c

No pure OUTPUT_EN register to read the direction from?
Or is it one of the undocumented ones?

Could you take a stab at implementing .get_direction() and
send a patch?

Yours,
Linus Walleij


From narmstrong at baylibre.com  Tue May 24 02:37:15 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 24 May 2016 11:37:15 +0200
Subject: [PATCH v2 1/2] pinctrl: Add Oxford Semiconductor OXNAS pinctrl
 and gpio driver
In-Reply-To: <CACRpkdZPMqRNn9rmcC4HYVKrdS7cxBD7O7oE4YPrP7L-0_Wakg@mail.gmail.com>
References: <1462952062-5316-1-git-send-email-narmstrong@baylibre.com>
 <1462952062-5316-2-git-send-email-narmstrong@baylibre.com>
 <CACRpkdZPMqRNn9rmcC4HYVKrdS7cxBD7O7oE4YPrP7L-0_Wakg@mail.gmail.com>
Message-ID: <574420CB.30908@baylibre.com>

On 05/24/2016 11:35 AM, Linus Walleij wrote:
> On Wed, May 11, 2016 at 9:34 AM, Neil Armstrong <narmstrong at baylibre.com> wrote:
> 
>> Add pinctrl and gpio control support to Oxford Semiconductor OXNAS SoC Family.
>> This version supports the ARM926EJ-S based OX810SE SoC with 34 IO pins.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> 
> I tried implementing a .get_direction() callback for the Oxnas GPIO
> (this is good to have, for debugfs and for the new userspace ABI).
> 
> However:
> 
>> +/* GPIO Registers */
>> +#define INPUT_VALUE    0x00
>> +#define IRQ_PENDING    0x0c
>> +#define OUTPUT_SET     0x14
>> +#define OUTPUT_CLEAR   0x18
>> +#define OUTPUT_EN_SET  0x1c
>> +#define OUTPUT_EN_CLEAR        0x20
>> +#define RE_IRQ_ENABLE  0x28
>> +#define FE_IRQ_ENABLE  0x2c
> 
> No pure OUTPUT_EN register to read the direction from?
> Or is it one of the undocumented ones?
I'm not sure it was documented, I can have a look further.

> 
> Could you take a stab at implementing .get_direction() and
> send a patch?
I can have a look ASAP.

Neil
> 
> Yours,
> Linus Walleij
> 



From christoffer.dall at linaro.org  Tue May 24 02:09:19 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:19 +0200
Subject: [PULL 25/59] KVM: arm/arm64: vgic-new: Add GICv2 MMIO handling
 framework
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-26-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

Create vgic-mmio-v2.c to describe GICv2 emulation specific handlers
using the initializer macros provided by the VGIC MMIO framework.
Provide a function to register the GICv2 distributor registers to
the kvm_io_bus framework.
The actual handler functions are still stubs in this patch.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 76 ++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.c    | 26 ++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h    |  2 ++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 4 files changed, 106 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio-v2.c

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
new file mode 100644
index 0000000..a3e31a9
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -0,0 +1,76 @@
+/*
+ * VGICv2 MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/irqchip/arm-gic.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+static const struct vgic_register_region vgic_v2_dist_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 12,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
+		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_TARGET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_CONFIG,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 2,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SOFTINT,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_CLEAR,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_DIST_SGI_PENDING_SET,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+};
+
+unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
+{
+	dev->regions = vgic_v2_dist_registers;
+	dev->nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
+
+	kvm_iodevice_init(&dev->dev, &kvm_io_gic_ops);
+
+	return SZ_4K;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 012b82b..1a97765 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -182,3 +182,29 @@ struct kvm_io_device_ops kvm_io_gic_ops = {
 	.read = dispatch_mmio_read,
 	.write = dispatch_mmio_write,
 };
+
+int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
+			     enum vgic_type type)
+{
+	struct vgic_io_device *io_device = &kvm->arch.vgic.dist_iodev;
+	int ret = 0;
+	unsigned int len;
+
+	switch (type) {
+	case VGIC_V2:
+		len = vgic_v2_init_dist_iodev(io_device);
+		break;
+	default:
+		BUG_ON(1);
+	}
+
+	io_device->base_addr = dist_base_address;
+	io_device->redist_vcpu = NULL;
+
+	mutex_lock(&kvm->slots_lock);
+	ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address,
+				      len, &io_device->dev);
+	mutex_unlock(&kvm->slots_lock);
+
+	return ret;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 3023ecf..5b928d4 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -96,4 +96,6 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
 void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
 			unsigned int len, unsigned long val);
 
+unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
+
 #endif
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 81b1a20..fd9acaa 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -27,6 +27,8 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
+			     enum vgic_type);
 
 #ifdef CONFIG_KVM_ARM_VGIC_V3
 void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:43 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:43 +0200
Subject: [PULL 49/59] KVM: arm/arm64: vgic-new: Add GICH_VMCR accessors
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-50-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

Since the GIC CPU interface is always virtualized by the hardware,
we don't have CPU interface state information readily available in our
emulation if userland wants to save or restore it.
Fortunately the GIC hypervisor interface provides the VMCR register to
access the required virtual CPU interface bits.
Provide wrappers for GICv2 and GICv3 hosts to have access to this
register.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-v2.c | 29 +++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c | 22 ++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h    | 21 +++++++++++++++++++++
 3 files changed, 72 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index fb5e65c..d943059 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -174,3 +174,32 @@ void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
 	vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = 0;
 }
+
+void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr;
+
+	vmcr  = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK;
+	vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) &
+		GICH_VMCR_ALIAS_BINPOINT_MASK;
+	vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) &
+		GICH_VMCR_BINPOINT_MASK;
+	vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) &
+		GICH_VMCR_PRIMASK_MASK;
+
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr = vmcr;
+}
+
+void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v2.vgic_vmcr;
+
+	vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >>
+			GICH_VMCR_CTRL_SHIFT;
+	vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >>
+			GICH_VMCR_ALIAS_BINPOINT_SHIFT;
+	vmcrp->bpr  = (vmcr & GICH_VMCR_BINPOINT_MASK) >>
+			GICH_VMCR_BINPOINT_SHIFT;
+	vmcrp->pmr  = (vmcr & GICH_VMCR_PRIMASK_MASK) >>
+			GICH_VMCR_PRIMASK_SHIFT;
+}
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index fb547da..8548297 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -160,3 +160,25 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 {
 	vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = 0;
 }
+
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr;
+
+	vmcr  = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK;
+	vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
+	vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
+	vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
+
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
+}
+
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
+{
+	u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
+
+	vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT;
+	vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
+	vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
+	vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index f826026..d2c1fd5 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -27,6 +27,13 @@
 
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
+struct vgic_vmcr {
+	u32	ctlr;
+	u32	abpr;
+	u32	bpr;
+	u32	pmr;
+};
+
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
@@ -40,6 +47,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val);
+void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
@@ -49,6 +58,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 #else
 static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
@@ -72,6 +83,16 @@ static inline void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 }
 
+static inline
+void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+}
+
+static inline
+void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+}
+
 static inline int vgic_register_redist_iodevs(struct kvm *kvm,
 					      gpa_t dist_base_address)
 {
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:42 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:42 +0200
Subject: [PULL 48/59] KVM: arm/arm64: vgic-new: Add userland access to VGIC
 dist registers
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-49-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

Userland may want to save and restore the state of the in-kernel VGIC,
so we provide the code which takes a userland request and translate
that into calls to our MMIO framework.

>From Christoffer:
When accessing the VGIC state from userspace we really don't want a VCPU
to be messing with the state at the same time, and the API specifies
that we should return -EBUSY if any VCPUs are running.
Check and prevent VCPUs from running by grabbing their mutexes, one by
one, and error out if we fail.
(Note: This could potentially be simplified to just do a simple check
and see if any VCPUs are running, and return -EBUSY then, without
enforcing the locking throughout the duration of the uaccess, if we
think that taking/releasing all these mutexes for every single GIC
register access is too heavyweight.)

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 55 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 78621283..9ee27cb 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -238,7 +238,60 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 				 struct kvm_device_attr *attr,
 				 u32 *reg, bool is_write)
 {
-	return -ENXIO;
+	gpa_t addr;
+	int cpuid, ret, c;
+	struct kvm_vcpu *vcpu, *tmp_vcpu;
+	int vcpu_lock_idx = -1;
+
+	cpuid = (attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK) >>
+		 KVM_DEV_ARM_VGIC_CPUID_SHIFT;
+	vcpu = kvm_get_vcpu(dev->kvm, cpuid);
+	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+	mutex_lock(&dev->kvm->lock);
+
+	ret = vgic_init(dev->kvm);
+	if (ret)
+		goto out;
+
+	if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Any time a vcpu is run, vcpu_load is called which tries to grab the
+	 * vcpu->mutex.  By grabbing the vcpu->mutex of all VCPUs we ensure
+	 * that no other VCPUs are run and fiddle with the vgic state while we
+	 * access it.
+	 */
+	ret = -EBUSY;
+	kvm_for_each_vcpu(c, tmp_vcpu, dev->kvm) {
+		if (!mutex_trylock(&tmp_vcpu->mutex))
+			goto out;
+		vcpu_lock_idx = c;
+	}
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		ret = -EINVAL;
+		break;
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+out:
+	for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
+		tmp_vcpu = kvm_get_vcpu(dev->kvm, vcpu_lock_idx);
+		mutex_unlock(&tmp_vcpu->mutex);
+	}
+
+	mutex_unlock(&dev->kvm->lock);
+	return ret;
 }
 
 /* V2 ops */
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:41 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:41 +0200
Subject: [PULL 47/59] KVM: arm/arm64: vgic-new: Export register access
 interface
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-48-git-send-email-christoffer.dall@linaro.org>

Userland can access the emulated GIC to save and restore its state
for initialization or migration purposes.
The kvm_io_bus API requires an absolute gpa, which does not fit the
KVM_DEV_ARM_VGIC_GRP_DIST_REGS user API, that only provides relative
offsets. So we provide a wrapper to plug into our MMIO framework and
find the respective register handler.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 36 ++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h         |  2 ++
 2 files changed, 38 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 7189690..a255122 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -296,3 +296,39 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 
 	return -ENXIO;
 }
+
+/*
+ * When userland tries to access the VGIC register handlers, we need to
+ * create a usable struct vgic_io_device to be passed to the handlers and we
+ * have to set up a buffer similar to what would have happened if a guest MMIO
+ * access occurred, including doing endian conversions on BE systems.
+ */
+static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
+			bool is_write, int offset, u32 *val)
+{
+	unsigned int len = 4;
+	u8 buf[4];
+	int ret;
+
+	if (is_write) {
+		vgic_data_host_to_mmio_bus(buf, len, *val);
+		ret = kvm_io_gic_ops.write(vcpu, &dev->dev, offset, len, buf);
+	} else {
+		ret = kvm_io_gic_ops.read(vcpu, &dev->dev, offset, len, buf);
+		if (!ret)
+			*val = vgic_data_mmio_bus_to_host(buf, len);
+	}
+
+	return ret;
+}
+
+int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			 int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_dist_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_dist_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index a264c5f..f826026 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -38,6 +38,8 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
+int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			 int offset, u32 *val);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:40 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:40 +0200
Subject: [PULL 46/59] KVM: arm/arm64: vgic-new: vgic_kvm_device: access to
 VGIC registers
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-47-git-send-email-christoffer.dall@linaro.org>

From: Eric Auger <eric.auger at linaro.org>

This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
access VGIC registers.

Signed-off-by: Eric Auger <eric.auger at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 53 +++++++++++++++++++++++++++++++++++--
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 38 ++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h            |  1 +
 3 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index a709097..78621283 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -226,6 +226,21 @@ void kvm_register_vgic_device(unsigned long type)
 	}
 }
 
+/** vgic_attr_regs_access: allows user space to read/write VGIC registers
+ *
+ * @dev: kvm device handle
+ * @attr: kvm device attribute
+ * @reg: address the value is read or written
+ * @is_write: write flag
+ *
+ */
+static int vgic_attr_regs_access(struct kvm_device *dev,
+				 struct kvm_device_attr *attr,
+				 u32 *reg, bool is_write)
+{
+	return -ENXIO;
+}
+
 /* V2 ops */
 
 static int vgic_v2_set_attr(struct kvm_device *dev,
@@ -234,8 +249,23 @@ static int vgic_v2_set_attr(struct kvm_device *dev,
 	int ret;
 
 	ret = vgic_set_common_attr(dev, attr);
-	return ret;
+	if (ret != -ENXIO)
+		return ret;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 reg;
+
+		if (get_user(reg, uaddr))
+			return -EFAULT;
 
+		return vgic_attr_regs_access(dev, attr, &reg, true);
+	}
+	}
+
+	return -ENXIO;
 }
 
 static int vgic_v2_get_attr(struct kvm_device *dev,
@@ -244,7 +274,23 @@ static int vgic_v2_get_attr(struct kvm_device *dev,
 	int ret;
 
 	ret = vgic_get_common_attr(dev, attr);
-	return ret;
+	if (ret != -ENXIO)
+		return ret;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u32 reg = 0;
+
+		ret = vgic_attr_regs_access(dev, attr, &reg, false);
+		if (ret)
+			return ret;
+		return put_user(reg, uaddr);
+	}
+	}
+
+	return -ENXIO;
 }
 
 static int vgic_v2_has_attr(struct kvm_device *dev,
@@ -258,6 +304,9 @@ static int vgic_v2_has_attr(struct kvm_device *dev,
 			return 0;
 		}
 		break;
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		return vgic_v2_has_attr_regs(dev, attr);
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 3925d4c..7189690 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -258,3 +258,41 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
 
 	return SZ_4K;
 }
+
+int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+	int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+	const struct vgic_register_region *regions;
+	gpa_t addr;
+	int nr_regions, i, len;
+
+	addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+
+	switch (attr->group) {
+	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+		regions = vgic_v2_dist_registers;
+		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
+		break;
+	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+		return -ENXIO;		/* TODO: describe CPU i/f regs also */
+	default:
+		return -ENXIO;
+	}
+
+	/* We only support aligned 32-bit accesses. */
+	if (addr & 3)
+		return -ENXIO;
+
+	for (i = 0; i < nr_regions; i++) {
+		if (regions[i].bits_per_irq)
+			len = (regions[i].bits_per_irq * nr_irqs) / 8;
+		else
+			len = regions[i].len;
+
+		if (regions[i].reg_offset <= addr &&
+		    regions[i].reg_offset + len > addr)
+			return 0;
+	}
+
+	return -ENXIO;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 6abc9a3..a264c5f 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -37,6 +37,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
 void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
 void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
+int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 			     enum vgic_type);
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:33 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:33 +0200
Subject: [PULL 39/59] KVM: arm/arm64: vgic-new: Add GICv3 IROUTER register
 handlers
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-40-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

Since GICv3 supports much more than the 8 CPUs the GICv2 ITARGETSR
register can handle, the new IROUTER register covers the whole range
of possible target (V)CPUs by using the same MPIDR that the cores
report themselves.
In addition to translating this MPIDR into a vcpu pointer we store
the originally written value as well. The architecture allows to
write any values into the register, which must be read back as written.

Since we don't support affinity level 3, we don't need to take care
about the upper word of this 64-bit register, which simplifies the
handling a bit.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 41 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 22e512c..4dcef9e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -75,6 +75,45 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
 	}
 }
 
+static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	int intid = VGIC_ADDR_TO_INTID(addr, 64);
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+
+	if (!irq)
+		return 0;
+
+	/* The upper word is RAZ for us. */
+	if (addr & 4)
+		return 0;
+
+	return extract_bytes(READ_ONCE(irq->mpidr), addr & 7, len);
+}
+
+static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	int intid = VGIC_ADDR_TO_INTID(addr, 64);
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+
+	if (!irq)
+		return;
+
+	/* The upper word is WI for us since we don't implement Aff3. */
+	if (addr & 4)
+		return;
+
+	spin_lock(&irq->irq_lock);
+
+	/* We only care about and preserve Aff0, Aff1 and Aff2. */
+	irq->mpidr = val & GENMASK(23, 0);
+	irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, irq->mpidr);
+
+	spin_unlock(&irq->irq_lock);
+}
+
 static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
 					      gpa_t addr, unsigned int len)
 {
@@ -170,7 +209,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IROUTER,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
+		vgic_mmio_read_irouter, vgic_mmio_write_irouter, 64,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
 		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:13 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:13 +0200
Subject: [PULL 19/59] KVM: arm/arm64: vgic-new: Add IRQ sorting
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-20-git-send-email-christoffer.dall@linaro.org>

Adds the sorting function to cover the case where you have more IRQs
to consider than you have LRs. We now consider priorities.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/vgic/vgic.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index ada1d02..bce17de 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -16,6 +16,7 @@
 
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <linux/list_sort.h>
 
 #include "vgic.h"
 
@@ -103,6 +104,62 @@ static struct kvm_vcpu *vgic_target_oracle(struct vgic_irq *irq)
 }
 
 /*
+ * The order of items in the ap_lists defines how we'll pack things in LRs as
+ * well, the first items in the list being the first things populated in the
+ * LRs.
+ *
+ * A hard rule is that active interrupts can never be pushed out of the LRs
+ * (and therefore take priority) since we cannot reliably trap on deactivation
+ * of IRQs and therefore they have to be present in the LRs.
+ *
+ * Otherwise things should be sorted by the priority field and the GIC
+ * hardware support will take care of preemption of priority groups etc.
+ *
+ * Return negative if "a" sorts before "b", 0 to preserve order, and positive
+ * to sort "b" before "a".
+ */
+static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+	struct vgic_irq *irqa = container_of(a, struct vgic_irq, ap_list);
+	struct vgic_irq *irqb = container_of(b, struct vgic_irq, ap_list);
+	bool penda, pendb;
+	int ret;
+
+	spin_lock(&irqa->irq_lock);
+	spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING);
+
+	if (irqa->active || irqb->active) {
+		ret = (int)irqb->active - (int)irqa->active;
+		goto out;
+	}
+
+	penda = irqa->enabled && irqa->pending;
+	pendb = irqb->enabled && irqb->pending;
+
+	if (!penda || !pendb) {
+		ret = (int)pendb - (int)penda;
+		goto out;
+	}
+
+	/* Both pending and enabled, sort by priority */
+	ret = irqa->priority - irqb->priority;
+out:
+	spin_unlock(&irqb->irq_lock);
+	spin_unlock(&irqa->irq_lock);
+	return ret;
+}
+
+/* Must be called with the ap_list_lock held */
+static void vgic_sort_ap_list(struct kvm_vcpu *vcpu)
+{
+	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+	DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
+
+	list_sort(NULL, &vgic_cpu->ap_list_head, vgic_irq_cmp);
+}
+
+/*
  * Only valid injection if changing level for level-triggered IRQs or for a
  * rising edge.
  */
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:10 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:10 +0200
Subject: [PULL 16/59] KVM: arm/arm64: vgic-new: Add data structure definitions
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-17-git-send-email-christoffer.dall@linaro.org>

Add a new header file for the new and improved GIC implementation.
The big change is that we now have a struct vgic_irq per IRQ instead
of spreading all the information over various bitmaps.

We include this new header conditionally from within the old header
file for the time being to avoid touching all the users.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
---
 include/kvm/arm_vgic.h  |   5 ++
 include/kvm/vgic/vgic.h | 201 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 206 insertions(+)
 create mode 100644 include/kvm/vgic/vgic.h

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index ade7005..da0a5248 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -19,6 +19,10 @@
 #ifndef __ASM_ARM_KVM_VGIC_H
 #define __ASM_ARM_KVM_VGIC_H
 
+#ifdef CONFIG_KVM_NEW_VGIC
+#include <kvm/vgic/vgic.h>
+#else
+
 #include <linux/kernel.h>
 #include <linux/kvm.h>
 #include <linux/irqreturn.h>
@@ -367,4 +371,5 @@ static inline int vgic_v3_probe(const struct gic_kvm_info *gic_kvm_info,
 }
 #endif
 
+#endif	/* old VGIC include */
 #endif
diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
new file mode 100644
index 0000000..6ca0781
--- /dev/null
+++ b/include/kvm/vgic/vgic.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_ARM_KVM_VGIC_VGIC_H
+#define __ASM_ARM_KVM_VGIC_VGIC_H
+
+#include <linux/kernel.h>
+#include <linux/kvm.h>
+#include <linux/irqreturn.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <kvm/iodev.h>
+
+#define VGIC_V3_MAX_CPUS	255
+#define VGIC_V2_MAX_CPUS	8
+#define VGIC_NR_IRQS_LEGACY     256
+#define VGIC_NR_SGIS		16
+#define VGIC_NR_PPIS		16
+#define VGIC_NR_PRIVATE_IRQS	(VGIC_NR_SGIS + VGIC_NR_PPIS)
+#define VGIC_MAX_PRIVATE	(VGIC_NR_PRIVATE_IRQS - 1)
+#define VGIC_MAX_SPI		1019
+#define VGIC_MAX_RESERVED	1023
+#define VGIC_MIN_LPI		8192
+
+enum vgic_type {
+	VGIC_V2,		/* Good ol' GICv2 */
+	VGIC_V3,		/* New fancy GICv3 */
+};
+
+/* same for all guests, as depending only on the _host's_ GIC model */
+struct vgic_global {
+	/* type of the host GIC */
+	enum vgic_type		type;
+
+	/* Physical address of vgic virtual cpu interface */
+	phys_addr_t		vcpu_base;
+
+	/* virtual control interface mapping */
+	void __iomem		*vctrl_base;
+
+	/* Number of implemented list registers */
+	int			nr_lr;
+
+	/* Maintenance IRQ number */
+	unsigned int		maint_irq;
+
+	/* maximum number of VCPUs allowed (GICv2 limits us to 8) */
+	int			max_gic_vcpus;
+
+	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
+	bool			can_emulate_gicv2;
+};
+
+extern struct vgic_global kvm_vgic_global_state;
+
+#define VGIC_V2_MAX_LRS		(1 << 6)
+#define VGIC_V3_MAX_LRS		16
+#define VGIC_V3_LR_INDEX(lr)	(VGIC_V3_MAX_LRS - 1 - lr)
+
+enum vgic_irq_config {
+	VGIC_CONFIG_EDGE = 0,
+	VGIC_CONFIG_LEVEL
+};
+
+struct vgic_irq {
+	spinlock_t irq_lock;		/* Protects the content of the struct */
+	struct list_head ap_list;
+
+	struct kvm_vcpu *vcpu;		/* SGIs and PPIs: The VCPU
+					 * SPIs and LPIs: The VCPU whose ap_list
+					 * this is queued on.
+					 */
+
+	struct kvm_vcpu *target_vcpu;	/* The VCPU that this interrupt should
+					 * be sent to, as a result of the
+					 * targets reg (v2) or the
+					 * affinity reg (v3).
+					 */
+
+	u32 intid;			/* Guest visible INTID */
+	bool pending;
+	bool line_level;		/* Level only */
+	bool soft_pending;		/* Level only */
+	bool active;			/* not used for LPIs */
+	bool enabled;
+	bool hw;			/* Tied to HW IRQ */
+	u32 hwintid;			/* HW INTID number */
+	union {
+		u8 targets;			/* GICv2 target VCPUs mask */
+		u32 mpidr;			/* GICv3 target VCPU */
+	};
+	u8 source;			/* GICv2 SGIs only */
+	u8 priority;
+	enum vgic_irq_config config;	/* Level or edge */
+};
+
+struct vgic_dist {
+	bool			in_kernel;
+	bool			ready;
+
+	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
+	u32			vgic_model;
+
+	int			nr_spis;
+
+	/* TODO: Consider moving to global state */
+	/* Virtual control interface mapping */
+	void __iomem		*vctrl_base;
+
+	/* base addresses in guest physical address space: */
+	gpa_t			vgic_dist_base;		/* distributor */
+	union {
+		/* either a GICv2 CPU interface */
+		gpa_t			vgic_cpu_base;
+		/* or a number of GICv3 redistributor regions */
+		gpa_t			vgic_redist_base;
+	};
+
+	/* distributor enabled */
+	bool			enabled;
+
+	struct vgic_irq		*spis;
+};
+
+struct vgic_v2_cpu_if {
+	u32		vgic_hcr;
+	u32		vgic_vmcr;
+	u32		vgic_misr;	/* Saved only */
+	u64		vgic_eisr;	/* Saved only */
+	u64		vgic_elrsr;	/* Saved only */
+	u32		vgic_apr;
+	u32		vgic_lr[VGIC_V2_MAX_LRS];
+};
+
+struct vgic_v3_cpu_if {
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+	u32		vgic_hcr;
+	u32		vgic_vmcr;
+	u32		vgic_sre;	/* Restored only, change ignored */
+	u32		vgic_misr;	/* Saved only */
+	u32		vgic_eisr;	/* Saved only */
+	u32		vgic_elrsr;	/* Saved only */
+	u32		vgic_ap0r[4];
+	u32		vgic_ap1r[4];
+	u64		vgic_lr[VGIC_V3_MAX_LRS];
+#endif
+};
+
+struct vgic_cpu {
+	/* CPU vif control registers for world switch */
+	union {
+		struct vgic_v2_cpu_if	vgic_v2;
+		struct vgic_v3_cpu_if	vgic_v3;
+	};
+
+	unsigned int used_lrs;
+	struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
+
+	spinlock_t ap_list_lock;	/* Protects the ap_list */
+
+	/*
+	 * List of IRQs that this VCPU should consider because they are either
+	 * Active or Pending (hence the name; AP list), or because they recently
+	 * were one of the two and need to be migrated off this list to another
+	 * VCPU.
+	 */
+	struct list_head ap_list_head;
+
+	u64 live_lrs;
+};
+
+#define irqchip_in_kernel(k)	(!!((k)->arch.vgic.in_kernel))
+#define vgic_initialized(k)	(false)
+#define vgic_ready(k)		((k)->arch.vgic.ready)
+#define vgic_valid_spi(k, i)	(((i) >= VGIC_NR_PRIVATE_IRQS) && \
+			((i) < (k)->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS))
+
+/**
+ * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
+ *
+ * The host's GIC naturally limits the maximum amount of VCPUs a guest
+ * can use.
+ */
+static inline int kvm_vgic_get_max_vcpus(void)
+{
+	return kvm_vgic_global_state.max_gic_vcpus;
+}
+
+#endif /* __ASM_ARM_KVM_VGIC_VGIC_H */
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:09 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:09 +0200
Subject: [PULL 15/59] KVM: arm/arm64: move GICv2 emulation defines into
 arm-gic-v3.h
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-16-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

As (some) GICv3 hosts can emulate a GICv2, some GICv2 specific masks
for the list register definition also apply to GICv3 LRs.
At the moment we have those definitions in the KVM VGICv3
implementation, so let's move them into the GICv3 header file to
have them automatically defined.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
---
 include/linux/irqchip/arm-gic-v3.h | 5 +++++
 virt/kvm/arm/vgic-v3.c             | 8 +-------
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index d5d798b..ec938d1 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -276,6 +276,11 @@
 #define ICH_LR_PHYS_ID_SHIFT		32
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
 
+/* These are for GICv2 emulation only */
+#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
+#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
+#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
+
 #define ICH_MISR_EOI			(1 << 0)
 #define ICH_MISR_U			(1 << 1)
 
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index c02a1b1..75b02fa 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -29,12 +29,6 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmu.h>
 
-/* These are for GICv2 emulation only */
-#define GICH_LR_VIRTUALID		(0x3ffUL << 0)
-#define GICH_LR_PHYSID_CPUID_SHIFT	(10)
-#define GICH_LR_PHYSID_CPUID		(7UL << GICH_LR_PHYSID_CPUID_SHIFT)
-#define ICH_LR_VIRTUALID_MASK		(BIT_ULL(32) - 1)
-
 static u32 ich_vtr_el2;
 
 static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
@@ -43,7 +37,7 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
 	u64 val = vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr];
 
 	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
-		lr_desc.irq = val & ICH_LR_VIRTUALID_MASK;
+		lr_desc.irq = val & ICH_LR_VIRTUAL_ID_MASK;
 	else
 		lr_desc.irq = val & GICH_LR_VIRTUALID;
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:05 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:05 +0200
Subject: [PULL 11/59] KVM: arm/arm64: Fix MMIO emulation data handling
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-12-git-send-email-christoffer.dall@linaro.org>

When the kernel was handling a guest MMIO read access internally, we
need to copy the emulation result into the run->mmio structure in order
for the kvm_handle_mmio_return() function to pick it up and inject the
	result back into the guest.

Currently the only user of kvm_io_bus for ARM is the VGIC, which did
this copying itself, so this was not causing issues so far.

But with the upcoming new vgic implementation we need this done
properly.

Update the kvm_handle_mmio_return description and cleanup the code to
only perform a single copying when needed.

Code and commit message inspired by Andre Przywara.

Reported-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Andre Przywara <andre.przywara at arm.com>
---
 arch/arm/kvm/mmio.c | 14 +++++++-------
 virt/kvm/arm/vgic.c |  7 -------
 2 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 0f6600f..0158e9e 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -87,11 +87,10 @@ static unsigned long mmio_read_buf(char *buf, unsigned int len)
 
 /**
  * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation
+ *			     or in-kernel IO emulation
+ *
  * @vcpu: The VCPU pointer
  * @run:  The VCPU run struct containing the mmio data
- *
- * This should only be called after returning from userspace for MMIO load
- * emulation.
  */
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
@@ -206,18 +205,19 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 	run->mmio.is_write	= is_write;
 	run->mmio.phys_addr	= fault_ipa;
 	run->mmio.len		= len;
-	if (is_write)
-		memcpy(run->mmio.data, data_buf, len);
 
 	if (!ret) {
 		/* We handled the access successfully in the kernel. */
+		if (!is_write)
+			memcpy(run->mmio.data, data_buf, len);
 		vcpu->stat.mmio_exit_kernel++;
 		kvm_handle_mmio_return(vcpu, run);
 		return 1;
-	} else {
-		vcpu->stat.mmio_exit_user++;
 	}
 
+	if (is_write)
+		memcpy(run->mmio.data, data_buf, len);
+	vcpu->stat.mmio_exit_user++;
 	run->exit_reason	= KVM_EXIT_MMIO;
 	return 0;
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index f76bb64..c3bfbb9 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -819,7 +819,6 @@ static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
 	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
 	struct vgic_io_device *iodev = container_of(this,
 						    struct vgic_io_device, dev);
-	struct kvm_run *run = vcpu->run;
 	const struct vgic_io_range *range;
 	struct kvm_exit_mmio mmio;
 	bool updated_state;
@@ -848,12 +847,6 @@ static int vgic_handle_mmio_access(struct kvm_vcpu *vcpu,
 		updated_state = false;
 	}
 	spin_unlock(&dist->lock);
-	run->mmio.is_write	= is_write;
-	run->mmio.len		= len;
-	run->mmio.phys_addr	= addr;
-	memcpy(run->mmio.data, val, len);
-
-	kvm_handle_mmio_return(vcpu, run);
 
 	if (updated_state)
 		vgic_kick_vcpus(vcpu->kvm);
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:44 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:44 +0200
Subject: [PULL 50/59] KVM: arm/arm64: vgic-new: Add userland GIC CPU interface
 access
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-51-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

Using the VMCR accessors we provide access to GIC CPU interface state
to userland by wiring it up to the existing userland interface.
[Marc: move and make VMCR accessors static, streamline MMIO handlers]

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c |   2 +-
 virt/kvm/arm/vgic/vgic-mmio-v2.c    | 114 +++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.h            |   2 +
 3 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 9ee27cb..0130c4b 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -274,7 +274,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		ret = -EINVAL;
+		ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
 		ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index a255122..a213936 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -204,6 +204,84 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_set_vmcr(vcpu, vmcr);
+	else
+		vgic_v3_set_vmcr(vcpu, vmcr);
+}
+
+static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+	if (kvm_vgic_global_state.type == VGIC_V2)
+		vgic_v2_get_vmcr(vcpu, vmcr);
+	else
+		vgic_v3_get_vmcr(vcpu, vmcr);
+}
+
+#define GICC_ARCH_VERSION_V2	0x2
+
+/* These are for userland accesses only, there is no guest-facing emulation. */
+static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
+					   gpa_t addr, unsigned int len)
+{
+	struct vgic_vmcr vmcr;
+	u32 val;
+
+	vgic_get_vmcr(vcpu, &vmcr);
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		val = vmcr.ctlr;
+		break;
+	case GIC_CPU_PRIMASK:
+		val = vmcr.pmr;
+		break;
+	case GIC_CPU_BINPOINT:
+		val = vmcr.bpr;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		val = vmcr.abpr;
+		break;
+	case GIC_CPU_IDENT:
+		val = ((PRODUCT_ID_KVM << 20) |
+		       (GICC_ARCH_VERSION_V2 << 16) |
+		       IMPLEMENTER_ARM);
+		break;
+	default:
+		return 0;
+	}
+
+	return val;
+}
+
+static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
+				   gpa_t addr, unsigned int len,
+				   unsigned long val)
+{
+	struct vgic_vmcr vmcr;
+
+	vgic_get_vmcr(vcpu, &vmcr);
+
+	switch (addr & 0xff) {
+	case GIC_CPU_CTRL:
+		vmcr.ctlr = val;
+		break;
+	case GIC_CPU_PRIMASK:
+		vmcr.pmr = val;
+		break;
+	case GIC_CPU_BINPOINT:
+		vmcr.bpr = val;
+		break;
+	case GIC_CPU_ALIAS_BINPOINT:
+		vmcr.abpr = val;
+		break;
+	}
+
+	vgic_set_vmcr(vcpu, &vmcr);
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
 		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
@@ -249,6 +327,27 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
 		VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
 };
 
+static const struct vgic_register_region vgic_v2_cpu_registers[] = {
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_CTRL,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_PRIMASK,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ALIAS_BINPOINT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_ACTIVEPRIO,
+		vgic_mmio_read_raz, vgic_mmio_write_wi, 16,
+		VGIC_ACCESS_32bit),
+	REGISTER_DESC_WITH_LENGTH(GIC_CPU_IDENT,
+		vgic_mmio_read_vcpuif, vgic_mmio_write_vcpuif, 4,
+		VGIC_ACCESS_32bit),
+};
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev)
 {
 	dev->regions = vgic_v2_dist_registers;
@@ -274,7 +373,9 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 		nr_regions = ARRAY_SIZE(vgic_v2_dist_registers);
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
-		return -ENXIO;		/* TODO: describe CPU i/f regs also */
+		regions = vgic_v2_cpu_registers;
+		nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers);
+		break;
 	default:
 		return -ENXIO;
 	}
@@ -322,6 +423,17 @@ static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
 	return ret;
 }
 
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val)
+{
+	struct vgic_io_device dev = {
+		.regions = vgic_v2_cpu_registers,
+		.nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers),
+	};
+
+	return vgic_uaccess(vcpu, &dev, is_write, offset, val);
+}
+
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val)
 {
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index d2c1fd5..de9dc71 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -47,6 +47,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
 int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
 int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 int offset, u32 *val);
+int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+			  int offset, u32 *val);
 void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:34 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:34 +0200
Subject: [PULL 40/59] KVM: arm/arm64: vgic-new: Add GICv3 SGI system register
 trap handler
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-41-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

In contrast to GICv2 SGIs in a GICv3 implementation are not triggered
by a MMIO write, but with a system register write. KVM knows about
that register already, we just need to implement the handler and wire
it up to the core KVM/ARM code.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/vgic/vgic.h          |   8 +++
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 106 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index ff3f9c2..00e3dca 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -209,6 +209,14 @@ bool kvm_vcpu_has_pending_irqs(struct kvm_vcpu *vcpu);
 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
 
+#ifdef CONFIG_KVM_ARM_VGIC_V3
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
+#else
+static inline void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
+{
+}
+#endif
+
 /**
  * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
  *
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 4dcef9e..a0c515a 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -347,3 +347,109 @@ int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
 
 	return ret;
 }
+
+/*
+ * Compare a given affinity (level 1-3 and a level 0 mask, from the SGI
+ * generation register ICC_SGI1R_EL1) with a given VCPU.
+ * If the VCPU's MPIDR matches, return the level0 affinity, otherwise
+ * return -1.
+ */
+static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct kvm_vcpu *vcpu)
+{
+	unsigned long affinity;
+	int level0;
+
+	/*
+	 * Split the current VCPU's MPIDR into affinity level 0 and the
+	 * rest as this is what we have to compare against.
+	 */
+	affinity = kvm_vcpu_get_mpidr_aff(vcpu);
+	level0 = MPIDR_AFFINITY_LEVEL(affinity, 0);
+	affinity &= ~MPIDR_LEVEL_MASK;
+
+	/* bail out if the upper three levels don't match */
+	if (sgi_aff != affinity)
+		return -1;
+
+	/* Is this VCPU's bit set in the mask ? */
+	if (!(sgi_cpu_mask & BIT(level0)))
+		return -1;
+
+	return level0;
+}
+
+/*
+ * The ICC_SGI* registers encode the affinity differently from the MPIDR,
+ * so provide a wrapper to use the existing defines to isolate a certain
+ * affinity level.
+ */
+#define SGI_AFFINITY_LEVEL(reg, level) \
+	((((reg) & ICC_SGI1R_AFFINITY_## level ##_MASK) \
+	>> ICC_SGI1R_AFFINITY_## level ##_SHIFT) << MPIDR_LEVEL_SHIFT(level))
+
+/**
+ * vgic_v3_dispatch_sgi - handle SGI requests from VCPUs
+ * @vcpu: The VCPU requesting a SGI
+ * @reg: The value written into the ICC_SGI1R_EL1 register by that VCPU
+ *
+ * With GICv3 (and ARE=1) CPUs trigger SGIs by writing to a system register.
+ * This will trap in sys_regs.c and call this function.
+ * This ICC_SGI1R_EL1 register contains the upper three affinity levels of the
+ * target processors as well as a bitmask of 16 Aff0 CPUs.
+ * If the interrupt routing mode bit is not set, we iterate over all VCPUs to
+ * check for matching ones. If this bit is set, we signal all, but not the
+ * calling VCPU.
+ */
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
+{
+	struct kvm *kvm = vcpu->kvm;
+	struct kvm_vcpu *c_vcpu;
+	u16 target_cpus;
+	u64 mpidr;
+	int sgi, c;
+	int vcpu_id = vcpu->vcpu_id;
+	bool broadcast;
+
+	sgi = (reg & ICC_SGI1R_SGI_ID_MASK) >> ICC_SGI1R_SGI_ID_SHIFT;
+	broadcast = reg & BIT(ICC_SGI1R_IRQ_ROUTING_MODE_BIT);
+	target_cpus = (reg & ICC_SGI1R_TARGET_LIST_MASK) >> ICC_SGI1R_TARGET_LIST_SHIFT;
+	mpidr = SGI_AFFINITY_LEVEL(reg, 3);
+	mpidr |= SGI_AFFINITY_LEVEL(reg, 2);
+	mpidr |= SGI_AFFINITY_LEVEL(reg, 1);
+
+	/*
+	 * We iterate over all VCPUs to find the MPIDRs matching the request.
+	 * If we have handled one CPU, we clear its bit to detect early
+	 * if we are already finished. This avoids iterating through all
+	 * VCPUs when most of the times we just signal a single VCPU.
+	 */
+	kvm_for_each_vcpu(c, c_vcpu, kvm) {
+		struct vgic_irq *irq;
+
+		/* Exit early if we have dealt with all requested CPUs */
+		if (!broadcast && target_cpus == 0)
+			break;
+
+		/* Don't signal the calling VCPU */
+		if (broadcast && c == vcpu_id)
+			continue;
+
+		if (!broadcast) {
+			int level0;
+
+			level0 = match_mpidr(mpidr, target_cpus, c_vcpu);
+			if (level0 == -1)
+				continue;
+
+			/* remove this matching VCPU from the mask */
+			target_cpus &= ~BIT(level0);
+		}
+
+		irq = vgic_get_irq(vcpu->kvm, c_vcpu, sgi);
+
+		spin_lock(&irq->irq_lock);
+		irq->pending = true;
+
+		vgic_queue_irq_unlock(vcpu->kvm, irq);
+	}
+}
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:32 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:32 +0200
Subject: [PULL 38/59] KVM: arm/arm64: vgic-new: Add GICv3 IDREGS register
 handler
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-39-git-send-email-christoffer.dall@linaro.org>

From: Andre Przywara <andre.przywara at arm.com>

We implement the only one ID register that is required by the
architecture, also this is the one that Linux actually checks.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 64edd23..22e512c 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -96,6 +96,18 @@ static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu,
 	return (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
 }
 
+static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu,
+					      gpa_t addr, unsigned int len)
+{
+	switch (addr & 0xffff) {
+	case GICD_PIDR2:
+		/* report a GICv3 compliant implementation */
+		return 0x3b;
+	}
+
+	return 0;
+}
+
 /*
  * The GICv3 per-IRQ registers are split to control PPIs and SGIs in the
  * redistributors, while SPIs are covered by registers in the distributor
@@ -161,7 +173,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 64,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICD_IDREGS,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
 		VGIC_ACCESS_32bit),
 };
 
@@ -182,7 +194,7 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
 		vgic_mmio_read_raz, vgic_mmio_write_wi, 8,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_LENGTH(GICR_IDREGS,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 48,
+		vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48,
 		VGIC_ACCESS_32bit),
 };
 
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:18 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:18 +0200
Subject: [PULL 24/59] KVM: arm/arm64: vgic-new: Add MMIO handling framework
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-25-git-send-email-christoffer.dall@linaro.org>

From: Marc Zyngier <marc.zyngier at arm.com>

Add an MMIO handling framework to the VGIC emulation:
Each register is described by its offset, size (or number of bits per
IRQ, if applicable) and the read/write handler functions. We provide
initialization macros to describe each GIC register later easily.

Separate dispatch functions for read and write accesses are connected
to the kvm_io_bus framework and binary-search for the responsible
register handler based on the offset address within the region.
We convert the incoming data (referenced by a pointer) to the host's
endianess and use pass-by-value to hand the data over to the actual
handler functions.

The register handler prototype and the endianess conversion are
courtesy of Christoffer Dall.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/kvm/vgic/vgic.h       |  13 +++
 virt/kvm/arm/vgic/vgic-mmio.c | 184 ++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h |  99 +++++++++++++++++++++++
 3 files changed, 296 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.c
 create mode 100644 virt/kvm/arm/vgic/vgic-mmio.h

diff --git a/include/kvm/vgic/vgic.h b/include/kvm/vgic/vgic.h
index f663288..ff3f9c2 100644
--- a/include/kvm/vgic/vgic.h
+++ b/include/kvm/vgic/vgic.h
@@ -106,6 +106,16 @@ struct vgic_irq {
 	enum vgic_irq_config config;	/* Level or edge */
 };
 
+struct vgic_register_region;
+
+struct vgic_io_device {
+	gpa_t base_addr;
+	struct kvm_vcpu *redist_vcpu;
+	const struct vgic_register_region *regions;
+	int nr_regions;
+	struct kvm_io_device dev;
+};
+
 struct vgic_dist {
 	bool			in_kernel;
 	bool			ready;
@@ -132,6 +142,9 @@ struct vgic_dist {
 	bool			enabled;
 
 	struct vgic_irq		*spis;
+
+	struct vgic_io_device	dist_iodev;
+	struct vgic_io_device	*redist_iodevs;
 };
 
 struct vgic_v2_cpu_if {
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
new file mode 100644
index 0000000..012b82b
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -0,0 +1,184 @@
+/*
+ * VGIC MMIO handling functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/bsearch.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <kvm/iodev.h>
+#include <kvm/arm_vgic.h>
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len)
+{
+	return 0;
+}
+
+unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len)
+{
+	return -1UL;
+}
+
+void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
+			unsigned int len, unsigned long val)
+{
+	/* Ignore */
+}
+
+static int match_region(const void *key, const void *elt)
+{
+	const unsigned int offset = (unsigned long)key;
+	const struct vgic_register_region *region = elt;
+
+	if (offset < region->reg_offset)
+		return -1;
+
+	if (offset >= region->reg_offset + region->len)
+		return 1;
+
+	return 0;
+}
+
+/* Find the proper register handler entry given a certain address offset. */
+static const struct vgic_register_region *
+vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
+		      unsigned int offset)
+{
+	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
+		       sizeof(region[0]), match_region);
+}
+
+/*
+ * kvm_mmio_read_buf() returns a value in a format where it can be converted
+ * to a byte array and be directly observed as the guest wanted it to appear
+ * in memory if it had done the store itself, which is LE for the GIC, as the
+ * guest knows the GIC is always LE.
+ *
+ * We convert this value to the CPUs native format to deal with it as a data
+ * value.
+ */
+unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len)
+{
+	unsigned long data = kvm_mmio_read_buf(val, len);
+
+	switch (len) {
+	case 1:
+		return data;
+	case 2:
+		return le16_to_cpu(data);
+	case 4:
+		return le32_to_cpu(data);
+	default:
+		return le64_to_cpu(data);
+	}
+}
+
+/*
+ * kvm_mmio_write_buf() expects a value in a format such that if converted to
+ * a byte array it is observed as the guest would see it if it could perform
+ * the load directly.  Since the GIC is LE, and the guest knows this, the
+ * guest expects a value in little endian format.
+ *
+ * We convert the data value from the CPUs native format to LE so that the
+ * value is returned in the proper format.
+ */
+void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
+				unsigned long data)
+{
+	switch (len) {
+	case 1:
+		break;
+	case 2:
+		data = cpu_to_le16(data);
+		break;
+	case 4:
+		data = cpu_to_le32(data);
+		break;
+	default:
+		data = cpu_to_le64(data);
+	}
+
+	kvm_mmio_write_buf(buf, len, data);
+}
+
+static
+struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
+{
+	return container_of(dev, struct vgic_io_device, dev);
+}
+
+static bool check_region(const struct vgic_register_region *region,
+			 gpa_t addr, int len)
+{
+	if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1)
+		return true;
+	if ((region->access_flags & VGIC_ACCESS_32bit) &&
+	    len == sizeof(u32) && !(addr & 3))
+		return true;
+	if ((region->access_flags & VGIC_ACCESS_64bit) &&
+	    len == sizeof(u64) && !(addr & 7))
+		return true;
+
+	return false;
+}
+
+static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
+			      gpa_t addr, int len, void *val)
+{
+	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
+	const struct vgic_register_region *region;
+	struct kvm_vcpu *r_vcpu;
+	unsigned long data;
+
+	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
+				       addr - iodev->base_addr);
+	if (!region || !check_region(region, addr, len)) {
+		memset(val, 0, len);
+		return 0;
+	}
+
+	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
+	data = region->read(r_vcpu, addr, len);
+	vgic_data_host_to_mmio_bus(val, len, data);
+	return 0;
+}
+
+static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
+			       gpa_t addr, int len, const void *val)
+{
+	struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev);
+	const struct vgic_register_region *region;
+	struct kvm_vcpu *r_vcpu;
+	unsigned long data = vgic_data_mmio_bus_to_host(val, len);
+
+	region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
+				       addr - iodev->base_addr);
+	if (!region)
+		return 0;
+
+	if (!check_region(region, addr, len))
+		return 0;
+
+	r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
+	region->write(r_vcpu, addr, len, data);
+	return 0;
+}
+
+struct kvm_io_device_ops kvm_io_gic_ops = {
+	.read = dispatch_mmio_read,
+	.write = dispatch_mmio_write,
+};
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
new file mode 100644
index 0000000..3023ecf
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __KVM_ARM_VGIC_MMIO_H__
+#define __KVM_ARM_VGIC_MMIO_H__
+
+struct vgic_register_region {
+	unsigned int reg_offset;
+	unsigned int len;
+	unsigned int bits_per_irq;
+	unsigned int access_flags;
+	unsigned long (*read)(struct kvm_vcpu *vcpu, gpa_t addr,
+			      unsigned int len);
+	void (*write)(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
+		      unsigned long val);
+};
+
+extern struct kvm_io_device_ops kvm_io_gic_ops;
+
+#define VGIC_ACCESS_8bit	1
+#define VGIC_ACCESS_32bit	2
+#define VGIC_ACCESS_64bit	4
+
+/*
+ * Generate a mask that covers the number of bytes required to address
+ * up to 1024 interrupts, each represented by <bits> bits. This assumes
+ * that <bits> is a power of two.
+ */
+#define VGIC_ADDR_IRQ_MASK(bits) (((bits) * 1024 / 8) - 1)
+
+/*
+ * (addr & mask) gives us the byte offset for the INT ID, so we want to
+ * divide this with 'bytes per irq' to get the INT ID, which is given
+ * by '(bits) / 8'.  But we do this with fixed-point-arithmetic and
+ * take advantage of the fact that division by a fraction equals
+ * multiplication with the inverted fraction, and scale up both the
+ * numerator and denominator with 8 to support at most 64 bits per IRQ:
+ */
+#define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
+					64 / (bits) / 8)
+
+/*
+ * Some VGIC registers store per-IRQ information, with a different number
+ * of bits per IRQ. For those registers this macro is used.
+ * The _WITH_LENGTH version instantiates registers with a fixed length
+ * and is mutually exclusive with the _PER_IRQ version.
+ */
+#define REGISTER_DESC_WITH_BITS_PER_IRQ(off, rd, wr, bpi, acc)		\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = bpi,					\
+		.len = bpi * 1024 / 8,					\
+		.access_flags = acc,					\
+		.read = rd,						\
+		.write = wr,						\
+	}
+
+#define REGISTER_DESC_WITH_LENGTH(off, rd, wr, length, acc)		\
+	{								\
+		.reg_offset = off,					\
+		.bits_per_irq = 0,					\
+		.len = length,						\
+		.access_flags = acc,					\
+		.read = rd,						\
+		.write = wr,						\
+	}
+
+int kvm_vgic_register_mmio_region(struct kvm *kvm, struct kvm_vcpu *vcpu,
+				  struct vgic_register_region *reg_desc,
+				  struct vgic_io_device *region,
+				  int nr_irqs, bool offset_private);
+
+unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len);
+
+void vgic_data_host_to_mmio_bus(void *buf, unsigned int len,
+				unsigned long data);
+
+unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len);
+
+unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
+				 gpa_t addr, unsigned int len);
+
+void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
+			unsigned int len, unsigned long val);
+
+#endif
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:20 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:20 +0200
Subject: [PULL 26/59] KVM: arm/arm64: vgic-new: Add CTLR,
 TYPER and IIDR handlers
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-27-git-send-email-christoffer.dall@linaro.org>

From: Marc Zyngier <marc.zyngier at arm.com>

Those three registers are v2 emulation specific, so their implementation
lives entirely in vgic-mmio-v2.c. Also they are handled in one function,
as their implementation is pretty simple.
When the guest enables the distributor, we kick all VCPUs to get
potentially pending interrupts serviced.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
---
 include/linux/irqchip/arm-gic.h  |  1 +
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 46 +++++++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic.c         | 15 +++++++++++++
 virt/kvm/arm/vgic/vgic.h         |  4 ++++
 4 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index be0d26f..fd05185 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -33,6 +33,7 @@
 
 #define GIC_DIST_CTRL			0x000
 #define GIC_DIST_CTR			0x004
+#define GIC_DIST_IIDR			0x008
 #define GIC_DIST_IGROUP			0x080
 #define GIC_DIST_ENABLE_SET		0x100
 #define GIC_DIST_ENABLE_CLEAR		0x180
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index a3e31a9..d812c93 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -20,9 +20,53 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
+					    gpa_t addr, unsigned int len)
+{
+	u32 value;
+
+	switch (addr & 0x0c) {
+	case GIC_DIST_CTRL:
+		value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
+		break;
+	case GIC_DIST_CTR:
+		value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+		value = (value >> 5) - 1;
+		value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
+		break;
+	case GIC_DIST_IIDR:
+		value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+		break;
+	default:
+		return 0;
+	}
+
+	return value;
+}
+
+static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
+				    gpa_t addr, unsigned int len,
+				    unsigned long val)
+{
+	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+	bool was_enabled = dist->enabled;
+
+	switch (addr & 0x0c) {
+	case GIC_DIST_CTRL:
+		dist->enabled = val & GICD_ENABLE;
+		if (!was_enabled && dist->enabled)
+			vgic_kick_vcpus(vcpu->kvm);
+		break;
+	case GIC_DIST_CTR:
+	case GIC_DIST_IIDR:
+		/* Nothing to do */
+		return;
+	}
+}
+
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
 	REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
-		vgic_mmio_read_raz, vgic_mmio_write_wi, 12,
+		vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
 		VGIC_ACCESS_32bit),
 	REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
 		vgic_mmio_read_rao, vgic_mmio_write_wi, 1,
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 7e01008..12ae84b 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -545,3 +545,18 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 
 	return pending;
 }
+
+void vgic_kick_vcpus(struct kvm *kvm)
+{
+	struct kvm_vcpu *vcpu;
+	int c;
+
+	/*
+	 * We've injected an interrupt, time to find out who deserves
+	 * a good kick...
+	 */
+	kvm_for_each_vcpu(c, vcpu, kvm) {
+		if (kvm_vgic_vcpu_pending_irq(vcpu))
+			kvm_vcpu_kick(vcpu);
+	}
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index fd9acaa..cf62015 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -16,11 +16,15 @@
 #ifndef __KVM_ARM_VGIC_NEW_H__
 #define __KVM_ARM_VGIC_NEW_H__
 
+#define PRODUCT_ID_KVM		0x4b	/* ASCII code K */
+#define IMPLEMENTER_ARM		0x43b
+
 #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
 
 struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
 			      u32 intid);
 bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
+void vgic_kick_vcpus(struct kvm *kvm);
 
 void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu);
 void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
-- 
2.1.2.330.g565301e.dirty



From christoffer.dall at linaro.org  Tue May 24 02:09:11 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 11:09:11 +0200
Subject: [PULL 17/59] KVM: arm/arm64: vgic-new: Add acccessor to new struct
 vgic_irq instance
In-Reply-To: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
References: <1464080993-10884-1-git-send-email-christoffer.dall@linaro.org>
Message-ID: <1464080993-10884-18-git-send-email-christoffer.dall@linaro.org>

The new VGIC implementation centers around a struct vgic_irq instance
per virtual IRQ.
Provide a function to retrieve the right instance for a given IRQ
number and (in case of private interrupts) the right VCPU.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Andre Przywara <andre.przywara at arm.com>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/vgic/vgic.c | 41 +++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h | 22 ++++++++++++++++++++++
 2 files changed, 63 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic.c
 create mode 100644 virt/kvm/arm/vgic/vgic.h

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
new file mode 100644
index 0000000..fb45537
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * 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/kvm.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
+
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
+			      u32 intid)
+{
+	/* SGIs and PPIs */
+	if (intid <= VGIC_MAX_PRIVATE)
+		return &vcpu->arch.vgic_cpu.private_irqs[intid];
+
+	/* SPIs */
+	if (intid <= VGIC_MAX_SPI)
+		return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS];
+
+	/* LPIs are not yet covered */
+	if (intid >= VGIC_MIN_LPI)
+		return NULL;
+
+	WARN(1, "Looking up struct vgic_irq for reserved INTID");
+	return NULL;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
new file mode 100644
index 0000000..61b8d22
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015, 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __KVM_ARM_VGIC_NEW_H__
+#define __KVM_ARM_VGIC_NEW_H__
+
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
+			      u32 intid);
+
+#endif
-- 
2.1.2.330.g565301e.dirty



From honghui.zhang at mediatek.com  Tue May 24 02:57:19 2016
From: honghui.zhang at mediatek.com (Honghui Zhang)
Date: Tue, 24 May 2016 17:57:19 +0800
Subject: [PATCH v2 4/5] iommu/mediatek: add support for mtk iommu
 generation one HW
In-Reply-To: <57435AA1.3090602@arm.com>
References: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
 <1463658558-567-5-git-send-email-honghui.zhang@mediatek.com>
 <57435AA1.3090602@arm.com>
Message-ID: <1464083839.30939.54.camel@mtksdaap41>

Hi, Robin,
Thanks very much for your comments.

On Mon, 2016-05-23 at 20:31 +0100, Robin Murphy wrote:
> On 19/05/16 12:49, honghui.zhang at mediatek.com wrote:
> > From: Honghui Zhang <honghui.zhang at mediatek.com>
> >
> > Mediatek SoC's M4U has two generations of HW architcture. Generation one
> > uses flat, one layer pagetable, and was shipped with ARM architecture, it
> > only supports 4K size page mapping. MT2701 SoC uses this generation one
> > m4u HW. Generation two uses the ARM short-descriptor translation table
> > format for address translation, and was shipped with ARM64 architecture,
> > MT8173 uses this generation two m4u HW. All the two generation iommu HW
> > only have one iommu domain, and all its iommu clients share the same
> > iova address.
> >
> > These two generation m4u HW have slit different register groups and
> > register offset, but most register names are the same. This patch add iommu
> > support for mediatek SoC mt2701.
> >
> > Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
> > ---
> >   drivers/iommu/Kconfig        |  19 ++
> >   drivers/iommu/Makefile       |   1 +
> >   drivers/iommu/mtk_iommu.h    |   3 +
> >   drivers/iommu/mtk_iommu_v1.c | 742 +++++++++++++++++++++++++++++++++++++++++++
> >   4 files changed, 765 insertions(+)
> >   create mode 100644 drivers/iommu/mtk_iommu_v1.c
> >
> > diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> > index dd1dc39..2e17d70 100644
> > --- a/drivers/iommu/Kconfig
> > +++ b/drivers/iommu/Kconfig
> > @@ -354,4 +354,23 @@ config MTK_IOMMU
> >
> >   	  If unsure, say N here.
> >
> > +config MTK_IOMMU_V1
> > +	bool "MTK IOMMU Version 1 (M4U gen1) Support"
> > +	depends on ARM || ARM64
> 
> The commit message states that gen1 shipped in 32-bit hardware, and 
> 64-bit hardware has gen2, which implies that ARM64 here is unnecessary - 
> does any SoC with 64it-capable CPUs and a gen1 IOMMU actually exist?

Thanks, there's no any SoC with ARM64 CPUs and gen1 IOMMU for now, I
will remove the un-necessary dependency.

> 
> > +	depends on ARCH_MEDIATEK || COMPILE_TEST
> > +	select ARM_DMA_USE_IOMMU
> > +	select IOMMU_API
> > +	select IOMMU_DMA
> 
> Either way you don't need this - arm64 already selects it as necessary, 
> and it's not used on 32-bit.

Thanks.

> 
> > +	select MEMORY
> > +	select MTK_SMI
> > +	select COMMON_CLK_MT2701_MMSYS
> > +	select COMMON_CLK_MT2701_IMGSYS
> > +	select COMMON_CLK_MT2701_VDECSYS
> > +	help
> > +	  Support for the M4U on certain Mediatek SoCs. M4U generation 1 HW is
> > +	  Multimedia Memory Managememt Unit. This option enables remapping of
> > +	  DMA memory accesses for the multimedia subsystem.
> > +
> > +	  if unsure, say N here.
> > +
> >   endif # IOMMU_SUPPORT
> > diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
> > index c6edb31..778baf5 100644
> > --- a/drivers/iommu/Makefile
> > +++ b/drivers/iommu/Makefile
> > @@ -18,6 +18,7 @@ obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
> >   obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
> >   obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
> >   obj-$(CONFIG_MTK_IOMMU) += mtk_iommu.o
> > +obj-$(CONFIG_MTK_IOMMU_V1) += mtk_iommu_v1.o
> >   obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
> >   obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
> >   obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o
> > diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> > index 5656355..8d60f21 100644
> > --- a/drivers/iommu/mtk_iommu.h
> > +++ b/drivers/iommu/mtk_iommu.h
> > @@ -48,6 +48,9 @@ struct mtk_iommu_domain {
> >   	struct io_pgtable_ops		*iop;
> >
> >   	struct iommu_domain		domain;
> > +	void				*pgt_va;
> > +	dma_addr_t			pgt_pa;
> > +	void				*cookie;
> 
> These are going to be mutually exclusive with the cfg and iop members, 
> which implies it might be a good idea to use a union and not waste 
> space. Or better, just forward-declare struct mtk_iommu_domain here and 
> leave separate definitions private to each driver. The void *cookie is 
> also an unnecessary level of abstraction, I think.
> 

Do you mean declare struct mtk_iommu_domain here, and implement a new
struct in mtk_iommu_v1.c like
struct mtk_iommu_domain_v1 {
	struct mtk_iommu_domain	domain;
	u32			*pgt_va;
	dma_addr_t		pgt_pa;
	mtk_iommu_data		*data;
};
If this is acceptable I would implement it in the next version.

> >   };
> >
> >   struct mtk_iommu_data {
> > diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
> > new file mode 100644
> > index 0000000..55023e1
> > --- /dev/null
> > +++ b/drivers/iommu/mtk_iommu_v1.c
> > @@ -0,0 +1,742 @@
> > +/*
> > + * Copyright (c) 2015-2016 MediaTek Inc.
> > + * Author: Yong Wu <yong.wu at mediatek.com>
> 
> Nit: is that in the sense that this patch should also have Yong's 
> signed-off-by on it, or in that it's your work derived from his version 
> in mtk_iommu.c?

I write this driver based on Yong's version of mtk_iommu.c, should I add
his signed-off-by for this patch? Or should I put a comment about this?
Thanks.

> 
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +#include <linux/bootmem.h>
> > +#include <linux/bug.h>
> > +#include <linux/clk.h>
> > +#include <linux/component.h>
> > +#include <linux/device.h>
> > +#include <linux/dma-iommu.h>
> > +#include <linux/err.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/io.h>
> > +#include <linux/iommu.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/kmemleak.h>
> > +#include <linux/list.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_iommu.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/slab.h>
> > +#include <linux/spinlock.h>
> > +#include <asm/barrier.h>
> > +#include <asm/dma-iommu.h>
> > +#include <linux/module.h>
> > +#include <dt-bindings/memory/mt2701-larb-port.h>
> > +#include <soc/mediatek/smi.h>
> > +#include "mtk_iommu.h"
> > +
> > +#define REG_MMU_PT_BASE_ADDR			0x000
> > +
> > +#define F_ALL_INVLD				0x2
> > +#define F_MMU_INV_RANGE				0x1
> > +#define F_INVLD_EN0				BIT(0)
> > +#define F_INVLD_EN1				BIT(1)
> > +
> > +#define F_MMU_FAULT_VA_MSK			0xfffff000
> > +#define MTK_PROTECT_PA_ALIGN			128
> > +
> > +#define REG_MMU_CTRL_REG			0x210
> > +#define F_MMU_CTRL_COHERENT_EN			BIT(8)
> > +#define REG_MMU_IVRP_PADDR			0x214
> > +#define REG_MMU_INT_CONTROL			0x220
> > +#define F_INT_TRANSLATION_FAULT			BIT(0)
> > +#define F_INT_MAIN_MULTI_HIT_FAULT		BIT(1)
> > +#define F_INT_INVALID_PA_FAULT			BIT(2)
> > +#define F_INT_ENTRY_REPLACEMENT_FAULT		BIT(3)
> > +#define F_INT_TABLE_WALK_FAULT			BIT(4)
> > +#define F_INT_TLB_MISS_FAULT			BIT(5)
> > +#define F_INT_PFH_DMA_FIFO_OVERFLOW		BIT(6)
> > +#define F_INT_MISS_DMA_FIFO_OVERFLOW		BIT(7)
> > +
> > +#define F_MMU_TF_PROTECT_SEL(prot)		(((prot) & 0x3) << 5)
> > +#define F_INT_CLR_BIT				BIT(12)
> > +
> > +#define REG_MMU_FAULT_ST			0x224
> > +#define REG_MMU_FAULT_VA			0x228
> > +#define REG_MMU_INVLD_PA			0x22C
> > +#define REG_MMU_INT_ID				0x388
> > +#define REG_MMU_INVALIDATE			0x5c0
> > +#define REG_MMU_INVLD_START_A			0x5c4
> > +#define REG_MMU_INVLD_END_A			0x5c8
> > +
> > +#define REG_MMU_INV_SEL				0x5d8
> > +#define REG_MMU_STANDARD_AXI_MODE		0x5e8
> > +
> > +#define REG_MMU_DCM				0x5f0
> > +#define F_MMU_DCM_ON				BIT(1)
> > +#define REG_MMU_CPE_DONE			0x60c
> > +#define F_DESC_VALID				0x2
> > +#define F_DESC_NONSEC				BIT(3)
> > +#define MT2701_M4U_TF_LARB(TF)			(6 - (((TF) >> 13) & 0x7))
> > +#define MT2701_M4U_TF_PORT(TF)			(((TF) >> 8) & 0xF)
> > +/* MTK generation one iommu HW only support 4K size mapping */
> > +#define MT2701_IOMMU_PAGE_SHIFT			12
> > +#define MT2701_IOMMU_PAGE_SIZE			(1UL << MT2701_IOMMU_PAGE_SHIFT)
> > +
> > +/*
> > + * MTK m4u support 4GB iova address space, and oly support 4K page
> 
> Nit: s/oly/only/
> 
> > + * mapping. So the pagetable size should be exactly as 4M.
> > + */
> > +#define M2701_IOMMU_PGT_SIZE			SZ_4M
> > +
> > +static const int mt2701_m4u_in_larb[] = {
> > +	LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
> > +	LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
> > +};
> > +
> > +static inline int mt2701_m4u_to_larb(int id)
> > +{
> > +	int i;
> > +
> > +	for (i = ARRAY_SIZE(mt2701_m4u_in_larb); i >= 0; i--)
> > +		if ((id) >= mt2701_m4u_in_larb[i])
> > +			return i;
> > +
> > +	return 0;
> > +}
> 
> As far as I can tell, this is going to dereference mt2701_m4u_in_larb[4] 
> on the first iteration. Not good.

Thanks, I will fix this in the next version.

> 
> > +
> > +static inline int mt2701_m4u_to_port(int id)
> > +{
> > +	int larb = mt2701_m4u_to_larb(id);
> > +
> > +	return id - mt2701_m4u_in_larb[larb];
> > +}
> > +
> > +static void mtk_iommu_tlb_flush_all(void *cookie)
> > +{
> > +	struct mtk_iommu_data *data = cookie;
> 
> You're not bound by the using the io-pgtable TLB ops interface here, so 
> just make the argument of type struct mtk_iommu_data*.
> 
> > +
> > +	writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
> > +			data->base + REG_MMU_INV_SEL);
> > +	writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
> > +	wmb(); /* Make sure the tlb flush all done */
> > +}
> > +
> > +static void mtk_iommu_tlb_flush_range(void *cookie,
> > +				unsigned long iova, size_t size)
> > +{
> > +	struct mtk_iommu_data *data = cookie;
> 
> Ditto.
> 
> > +	int ret;
> > +	u32 tmp;
> > +
> > +	writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
> > +		data->base + REG_MMU_INV_SEL);
> > +	writel_relaxed(iova & F_MMU_FAULT_VA_MSK,
> > +		data->base + REG_MMU_INVLD_START_A);
> > +	writel_relaxed((iova + size - 1) & F_MMU_FAULT_VA_MSK,
> > +		data->base + REG_MMU_INVLD_END_A);
> > +	writel_relaxed(F_MMU_INV_RANGE, data->base + REG_MMU_INVALIDATE);
> > +
> > +	ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE,
> > +				tmp, tmp != 0, 10, 100000);
> > +	if (ret) {
> > +		dev_warn(data->dev,
> > +			 "Partial TLB flush timed out, falling back to full flush\n");
> > +		mtk_iommu_tlb_flush_all(cookie);
> > +	}
> > +	/* Clear the CPE status */
> > +	writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
> > +}
> > +
> > +static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
> > +{
> > +	struct mtk_iommu_data *data = dev_id;
> > +	struct mtk_iommu_domain *dom = data->m4u_dom;
> > +	u32 int_state, regval, fault_iova, fault_pa;
> > +	unsigned int fault_larb, fault_port;
> > +
> > +	/* Read error information from registers */
> > +	int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST);
> > +	fault_iova = readl_relaxed(data->base + REG_MMU_FAULT_VA);
> > +
> > +	fault_iova &= F_MMU_FAULT_VA_MSK;
> > +	fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
> > +	regval = readl_relaxed(data->base + REG_MMU_INT_ID);
> > +	fault_larb = MT2701_M4U_TF_LARB(regval);
> > +	fault_port = MT2701_M4U_TF_PORT(regval);
> > +
> > +	/*
> > +	 * MTK v1 iommu HW could not determin whether the fault is read or
> 
> Nit: s/determin/determine/
> 
> > +	 * write fault, report as read fault.
> > +	 */
> > +	if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
> > +			IOMMU_FAULT_READ))
> > +		dev_err_ratelimited(data->dev,
> > +			"fault type=0x%x iova=0x%x pa=0x%x larb=%d port=%d\n",
> > +			int_state, fault_iova, fault_pa,
> > +			fault_larb, fault_port);
> > +
> > +	/* Interrupt clear */
> > +	regval = readl_relaxed(data->base + REG_MMU_INT_CONTROL);
> > +	regval |= F_INT_CLR_BIT;
> > +	writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL);
> > +
> > +	mtk_iommu_tlb_flush_all(data);
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static void mtk_iommu_config(struct mtk_iommu_data *data,
> > +			     struct device *dev, bool enable)
> > +{
> > +	struct mtk_iommu_client_priv *head, *cur, *next;
> > +	struct mtk_smi_larb_iommu    *larb_mmu;
> > +	unsigned int                 larbid, portid;
> > +
> > +	head = dev->archdata.iommu;
> > +	list_for_each_entry_safe(cur, next, &head->client, client) {
> > +		larbid = mt2701_m4u_to_larb(cur->mtk_m4u_id);
> > +		portid = mt2701_m4u_to_port(cur->mtk_m4u_id);
> > +		larb_mmu = &data->smi_imu.larb_imu[larbid];
> > +
> > +		dev_dbg(dev, "%s iommu port: %d\n",
> > +			enable ? "enable" : "disable", portid);
> > +
> > +		if (enable)
> > +			larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
> > +		else
> > +			larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
> > +	}
> > +}
> > +
> > +static void *mtk_iommu_alloc_pgt(struct device *dev,
> > +				dma_addr_t *dma, gfp_t gfp)
> > +{
> > +	void *pages = dma_alloc_coherent(dev,
> > +				M2701_IOMMU_PGT_SIZE, dma, gfp | __GFP_ZERO);
> 
> There's a dma_zalloc_coherent() wrapper macro you can use for that.
> 
> > +
> > +	if (!pages)
> > +		return NULL;
> > +
> > +	kmemleak_ignore(pages);
> 
> Kmemleak should be able to find the live reference in dom->pgt_va, so 
> this is unnecessary - it's only there in the other code because of the 
> tracking-allocations-by-physical-address trickery which you've otherwise 
> gotten rid of here.

Thanks, I will remove the un-necessary kmemleak_ignore.

> 
> > +	return pages;
> > +}
> > +
> > +static void mtk_iommu_free_pgt(struct device *dev,
> > +				void *pages, dma_addr_t dma)
> > +{
> > +	dma_free_coherent(dev, M2701_IOMMU_PGT_SIZE, pages, dma);
> > +}
> 
> In fact, I'd just inline the dma_{alloc,free} calls at the callsites of 
> these functions, since they're sufficiently self-documenting.

Thanks, I will use dma_zalloc_coherent and put it inline.

> 
> > +
> > +static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data)
> > +{
> > +	struct mtk_iommu_domain *dom = data->m4u_dom;
> > +
> > +	spin_lock_init(&dom->pgtlock);
> > +
> > +	dom->pgt_va = mtk_iommu_alloc_pgt(data->dev,
> > +				&dom->pgt_pa, GFP_KERNEL);
> > +	if (!dom->pgt_va)
> > +		return -ENOMEM;
> > +
> > +	writel(dom->pgt_pa, data->base + REG_MMU_PT_BASE_ADDR);
> > +
> > +	dom->cookie = (void *)data;
> > +
> > +	return 0;
> > +}
> > +
> > +static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type)
> > +{
> > +	struct mtk_iommu_domain *dom;
> > +
> > +	if (type != IOMMU_DOMAIN_UNMANAGED)
> > +		return NULL;
> > +
> > +	dom = kzalloc(sizeof(*dom), GFP_KERNEL);
> > +	if (!dom)
> > +		return NULL;
> > +
> > +	return &dom->domain;
> > +}
> > +
> > +static void mtk_iommu_domain_free(struct iommu_domain *domain)
> > +{
> 
> The page table belongs to the domain, so it should be freed from here, 
> not anywhere else.

Thanks, I would put it here.

> 
> > +	kfree(to_mtk_domain(domain));
> > +}
> > +
> > +static int mtk_iommu_attach_device(struct iommu_domain *domain,
> > +				   struct device *dev)
> > +{
> > +	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
> > +	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
> > +	struct mtk_iommu_data *data;
> > +	int ret;
> > +
> > +	if (!priv)
> > +		return -ENODEV;
> > +
> > +	data = dev_get_drvdata(priv->m4udev);
> > +	if (!data->m4u_dom) {
> > +		data->m4u_dom = dom;
> > +		ret = mtk_iommu_domain_finalise(data);
> > +		if (ret) {
> > +			data->m4u_dom = NULL;
> > +			return ret;
> > +		}
> > +	} else if (data->m4u_dom != dom) {
> 
> This will never happen, because you make sure all devices are in the 
> same group, so the IOMMU core code will always call you with the same 
> domain here. You can safely just attach dev to dom.
> 
> > +		/* All the client devices should be in the same m4u domain */
> > +		dev_err(dev, "try to attach into the error iommu domain\n");
> > +		return -EPERM;
> > +	}
> > +
> > +	mtk_iommu_config(data, dev, true);
> > +	return 0;
> > +}
> > +
> > +static void mtk_iommu_detach_device(struct iommu_domain *domain,
> > +				    struct device *dev)
> > +{
> > +	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
> > +	struct mtk_iommu_data *data;
> > +
> > +	if (!priv)
> > +		return;
> > +
> > +	data = dev_get_drvdata(priv->m4udev);
> > +	mtk_iommu_config(data, dev, false);
> > +}
> > +
> > +static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
> > +			 phys_addr_t paddr, size_t size, int prot)
> > +{
> > +	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
> > +	struct mtk_iommu_data *data = dom->cookie;
> > +	unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT;
> > +	unsigned long flags;
> > +	unsigned int i;
> > +	u32 *pgt_base_iova = dom->pgt_va;
> > +	u32 pabase = (u32)paddr;
> > +	int map_size = 0;
> > +
> > +	spin_lock_irqsave(&dom->pgtlock, flags);
> > +	pgt_base_iova += iova  >> MT2701_IOMMU_PAGE_SHIFT;
> 
> It took me a while to figure out why this isn't just part of the 
> initialisation expression; just make dom->pgt_va a u32* so that it can be.
> 
> > +	for (i = 0; i < page_num; i++) {
> > +		if (pgt_base_iova[i])
> > +			break;
> 
> The error case also needs to roll back any partial mapping it's managed 
> so far - otherwise you end up making the initial problem worse by 
> leaving behind yet more unexpected PTEs in areas that the caller thinks 
> are unmapped.

Yes, I will update this in the next version.

> 
> > +		pgt_base_iova[i] = pabase | F_DESC_VALID | F_DESC_NONSEC;
> > +		pabase += MT2701_IOMMU_PAGE_SIZE;
> > +		map_size += MT2701_IOMMU_PAGE_SIZE;
> > +	}
> > +
> > +	spin_unlock_irqrestore(&dom->pgtlock, flags);
> > +
> > +	mtk_iommu_tlb_flush_range(data, iova, size);
> > +
> > +	return map_size == size ? 0 : -EEXIST;
> > +}
> > +
> > +static size_t mtk_iommu_unmap(struct iommu_domain *domain,
> > +			      unsigned long iova, size_t size)
> > +{
> > +	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
> > +	struct mtk_iommu_data *data = dom->cookie;
> > +	unsigned long flags;
> > +	u32 *pgt_base_iova = dom->pgt_va;
> > +	unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT;
> > +
> > +	spin_lock_irqsave(&dom->pgtlock, flags);
> > +	pgt_base_iova += iova  >> MT2701_IOMMU_PAGE_SHIFT;
> 
> Same complaint as for mtk_iommu_map().
> 
> > +	memset(pgt_base_iova, 0, page_num * sizeof(u32));
> > +
> > +	spin_unlock_irqrestore(&dom->pgtlock, flags);
> > +
> > +	mtk_iommu_tlb_flush_range(data, iova, size);
> > +
> > +	return size;
> > +}
> > +
> > +static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
> > +					  dma_addr_t iova)
> > +{
> > +	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
> > +	unsigned long flags;
> > +	phys_addr_t pa;
> > +
> > +	spin_lock_irqsave(&dom->pgtlock, flags);
> > +	pa = *((u32 *)((u32 *)dom->pgt_va + (iova >> MT2701_IOMMU_PAGE_SHIFT)));
> 
> Yikes! _Definitely_ make dom->pgt_va a u32*.
> 
> > +	pa = pa & (~(MT2701_IOMMU_PAGE_SIZE - 1));
> > +	spin_unlock_irqrestore(&dom->pgtlock, flags);
> > +
> > +	return pa;
> > +}
> > +
> > +/*
> > + * MTK generaion one iommu HW only support one iommu domain, and all the client
> 
> Nit: s/generaion/generation/
> 
> > + * sharing the same iova address space.
> > + */
> > +static int mtk_iommu_create_mapping(struct device *dev,
> > +				    struct of_phandle_args *args)
> > +{
> > +	struct mtk_iommu_client_priv *head, *priv, *next;
> > +	struct platform_device *m4updev;
> > +	struct dma_iommu_mapping *mtk_mapping;
> > +	struct device *m4udev;
> > +	int ret;
> > +
> > +	if (args->args_count != 1) {
> > +		dev_err(dev, "invalid #iommu-cells(%d) property for IOMMU\n",
> > +			args->args_count);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (!dev->archdata.iommu) {
> > +		/* Get the m4u device */
> > +		m4updev = of_find_device_by_node(args->np);
> > +		of_node_put(args->np);
> > +		if (WARN_ON(!m4updev))
> > +			return -EINVAL;
> > +
> > +		head = kzalloc(sizeof(*head), GFP_KERNEL);
> > +		if (!head)
> > +			return -ENOMEM;
> > +
> > +		dev->archdata.iommu = head;
> > +		INIT_LIST_HEAD(&head->client);
> > +		head->m4udev = &m4updev->dev;
> > +	} else {
> > +		head = dev->archdata.iommu;
> > +	}
> > +
> > +	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > +	if (!priv) {
> > +		ret = -ENOMEM;
> > +		goto err_free_mem;
> > +	}
> > +	priv->mtk_m4u_id = args->args[0];
> > +	list_add_tail(&priv->client, &head->client);
> > +
> > +	m4udev = head->m4udev;
> > +	mtk_mapping = m4udev->archdata.iommu;
> > +	if (!mtk_mapping) {
> > +		/* MTK iommu support 4GB iova address space. */
> > +		mtk_mapping = arm_iommu_create_mapping(&platform_bus_type,
> > +						0, 1ULL << 32);
> > +		if (IS_ERR(mtk_mapping)) {
> > +			ret = PTR_ERR(mtk_mapping);
> > +			goto err_free_mem;
> > +		}
> > +		m4udev->archdata.iommu = mtk_mapping;
> > +	}
> > +
> > +	ret = arm_iommu_attach_device(dev, mtk_mapping);
> > +	if (ret)
> > +		goto err_release_mapping;
> > +
> > +	return 0;
> > +
> > +err_release_mapping:
> > +	arm_iommu_release_mapping(mtk_mapping);
> > +	m4udev->archdata.iommu = NULL;
> > +err_free_mem:
> > +	list_for_each_entry_safe(priv, next, &head->client, client)
> > +		kfree(priv);
> > +	kfree(head);
> > +	dev->archdata.iommu = NULL;
> > +	return ret;
> > +}
> > +
> > +static int mtk_iommu_add_device(struct device *dev)
> > +{
> > +	struct iommu_group *group;
> > +	struct device_node *np;
> > +	struct of_phandle_args iommu_spec;
> > +	int idx = 0;
> > +
> > +	while (!of_parse_phandle_with_args(dev->of_node, "iommus",
> > +				   "#iommu-cells", idx,
> > +				   &iommu_spec)) {
> 
> Hang on, this doesn't seem right - why do you need to reimplement all 
> this instead of using IOMMU_OF_DECLARE()?

All the clients of mtk generation one iommu share the same iommu domain,
as a matter of fact, mtk generation one iommu only support one iommu
domain. ALl the clients share the same iova address and use the same
pagetable. That means all iommu clients needed to be attached to the
same dma_iommu_mapping.

If use IOMMU_OF_DELCARE, we need to call of_iommu_set_ops to set the
iommu_ops, I do not want the iommu_ops be set since it would cause iommu
client device in different dma_iommu_mapping.

When an iommu client device has been created, the following sequence is
called.

of_platform_device_create
	->of_dma_config
		->arch_setup_dma_ops
			->arch_setup_iommu_dma_ops
In this function of arch_setup_iommu_dma_ops would create a new
dma_iommu_mapping for each iommu client device and then attach the
device to this new dma_iommu_mapping. Since all the iommu clients share
the very same pagetable, this will not workable for our HW.
I could not release the dma_iommu_mapping in attach_device since the
to_dma_iommu_mapping was set after device_attached.
Any suggest for this?

> 
> > +		np = iommu_spec.np;
> > +		mtk_iommu_create_mapping(dev, &iommu_spec);
> > +
> > +		of_node_put(np);
> > +		idx++;
> > +	}
> > +
> > +	if (!dev->archdata.iommu) /* Not a iommu client device */
> > +		return -ENODEV;
> > +
> > +	group = iommu_group_get_for_dev(dev);
> > +	if (IS_ERR(group))
> > +		return PTR_ERR(group);
> > +
> > +	iommu_group_put(group);
> > +	return 0;
> > +}
> > +
> > +static void mtk_iommu_remove_device(struct device *dev)
> > +{
> > +	struct mtk_iommu_client_priv *head, *cur, *next;
> > +
> > +	head = dev->archdata.iommu;
> > +	if (!head)
> > +		return;
> > +
> > +	list_for_each_entry_safe(cur, next, &head->client, client) {
> > +		list_del(&cur->client);
> > +		kfree(cur);
> > +	}
> > +	kfree(head);
> > +	dev->archdata.iommu = NULL;
> > +
> > +	iommu_group_remove_device(dev);
> > +}
> > +
> > +static struct iommu_group *mtk_iommu_device_group(struct device *dev)
> > +{
> > +	struct mtk_iommu_data *data;
> > +	struct mtk_iommu_client_priv *priv;
> > +
> > +	priv = dev->archdata.iommu;
> > +	if (!priv)
> > +		return ERR_PTR(-ENODEV);
> > +
> > +	/* All the client devices are in the same m4u iommu-group */
> > +	data = dev_get_drvdata(priv->m4udev);
> > +	if (!data->m4u_group) {
> > +		data->m4u_group = iommu_group_alloc();
> > +		if (IS_ERR(data->m4u_group))
> > +			dev_err(dev, "Failed to allocate M4U IOMMU group\n");
> > +	}
> > +	return data->m4u_group;
> > +}
> > +
> > +static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
> > +{
> > +	u32 regval;
> > +	int ret;
> > +
> > +	ret = clk_prepare_enable(data->bclk);
> > +	if (ret) {
> > +		dev_err(data->dev, "Failed to enable iommu bclk(%d)\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	regval = F_MMU_CTRL_COHERENT_EN | F_MMU_TF_PROTECT_SEL(2);
> > +	writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
> > +
> > +	regval = F_INT_TRANSLATION_FAULT |
> > +		F_INT_MAIN_MULTI_HIT_FAULT |
> > +		F_INT_INVALID_PA_FAULT |
> > +		F_INT_ENTRY_REPLACEMENT_FAULT |
> > +		F_INT_TABLE_WALK_FAULT |
> > +		F_INT_TLB_MISS_FAULT |
> > +		F_INT_PFH_DMA_FIFO_OVERFLOW |
> > +		F_INT_MISS_DMA_FIFO_OVERFLOW;
> > +	writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL);
> > +
> > +	/* protect memory,hw will write here while translation fault */
> > +	writel_relaxed(data->protect_base,
> > +			data->base + REG_MMU_IVRP_PADDR);
> > +
> > +	writel_relaxed(F_MMU_DCM_ON, data->base + REG_MMU_DCM);
> > +
> > +	if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
> > +			     dev_name(data->dev), (void *)data)) {
> > +		writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR);
> > +		clk_disable_unprepare(data->bclk);
> > +		dev_err(data->dev, "Failed @ IRQ-%d Request\n", data->irq);
> > +		return -ENODEV;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static struct iommu_ops mtk_iommu_ops = {
> > +	.domain_alloc	= mtk_iommu_domain_alloc,
> > +	.domain_free	= mtk_iommu_domain_free,
> > +	.attach_dev	= mtk_iommu_attach_device,
> > +	.detach_dev	= mtk_iommu_detach_device,
> > +	.map		= mtk_iommu_map,
> > +	.unmap		= mtk_iommu_unmap,
> > +	.map_sg		= default_iommu_map_sg,
> > +	.iova_to_phys	= mtk_iommu_iova_to_phys,
> > +	.add_device	= mtk_iommu_add_device,
> > +	.remove_device	= mtk_iommu_remove_device,
> > +	.device_group	= mtk_iommu_device_group,
> > +	.pgsize_bitmap	= ~0UL << MT2701_IOMMU_PAGE_SHIFT,
> > +};
> > +
> > +static const struct of_device_id mtk_iommu_of_ids[] = {
> > +	{ .compatible = "mediatek,mt2701-m4u", },
> > +	{}
> > +};
> > +
> > +static const struct component_master_ops mtk_iommu_com_ops = {
> > +	.bind		= mtk_iommu_bind,
> > +	.unbind		= mtk_iommu_unbind,
> > +};
> > +
> > +static int mtk_iommu_probe(struct platform_device *pdev)
> > +{
> > +	struct mtk_iommu_data		*data;
> > +	struct device			*dev = &pdev->dev;
> > +	struct resource			*res;
> > +	struct component_match		*match = NULL;
> > +	void				*protect;
> > +	int				i, larb_nr, ret;
> > +
> > +	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> > +	if (!data)
> > +		return -ENOMEM;
> > +
> > +	data->dev = dev;
> > +
> > +	/* Protect memory. HW will access here while translation fault.*/
> > +	protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL);
> 
> I think strictly this ought to have GFP_DMA as well.
> 
> > +	if (!protect)
> > +		return -ENOMEM;
> > +	data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	data->base = devm_ioremap_resource(dev, res);
> > +	if (IS_ERR(data->base))
> > +		return PTR_ERR(data->base);
> > +
> > +	data->irq = platform_get_irq(pdev, 0);
> > +	if (data->irq < 0)
> > +		return data->irq;
> > +
> > +	data->bclk = devm_clk_get(dev, "bclk");
> > +	if (IS_ERR(data->bclk))
> > +		return PTR_ERR(data->bclk);
> > +
> > +	larb_nr = of_count_phandle_with_args(dev->of_node,
> > +					"mediatek,larbs", NULL);
> > +	if (larb_nr < 0)
> > +		return larb_nr;
> > +	data->smi_imu.larb_nr = larb_nr;
> > +
> > +	for (i = 0; i < larb_nr; i++) {
> > +		struct device_node *larbnode;
> > +		struct platform_device *plarbdev;
> 
> Nit: I wonder if the new of_for_each_phandle() iterator might make this 
> larb-discovery logic cleaner? It might be worth a go now that that's 
> landed in the current merge window.

Thanks, I will take a look at that.

> 
> > +
> > +		larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
> > +		if (!larbnode)
> > +			return -EINVAL;
> > +
> > +		if (!of_device_is_available(larbnode))
> > +			continue;
> > +
> > +		plarbdev = of_find_device_by_node(larbnode);
> > +		of_node_put(larbnode);
> > +		if (!plarbdev) {
> > +			plarbdev = of_platform_device_create(
> > +						larbnode, NULL,
> > +						platform_bus_type.dev_root);
> > +			if (!plarbdev)
> > +				return -EPROBE_DEFER;
> > +		}
> > +		data->smi_imu.larb_imu[i].dev = &plarbdev->dev;
> > +
> > +		component_match_add(dev, &match, compare_of, larbnode);
> > +	}
> > +
> > +	platform_set_drvdata(pdev, data);
> > +
> > +	ret = mtk_iommu_hw_init(data);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (!iommu_present(&platform_bus_type))
> > +		bus_set_iommu(&platform_bus_type,  &mtk_iommu_ops);
> > +
> > +	return component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
> > +}
> > +
> > +static int mtk_iommu_remove(struct platform_device *pdev)
> > +{
> > +	struct mtk_iommu_data *data = platform_get_drvdata(pdev);
> > +	struct mtk_iommu_domain *dom = data->m4u_dom;
> > +	struct device *dev = &pdev->dev;
> > +
> > +	mtk_iommu_free_pgt(dev, dom->pgt_va, dom->pgt_pa);
> > +
> > +	if (iommu_present(&platform_bus_type))
> > +		bus_set_iommu(&platform_bus_type, NULL);
> > +
> > +	clk_disable_unprepare(data->bclk);
> > +	devm_free_irq(&pdev->dev, data->irq, data);
> > +	component_master_del(&pdev->dev, &mtk_iommu_com_ops);
> > +	return 0;
> > +}
> > +
> > +static int __maybe_unused mtk_iommu_suspend(struct device *dev)
> > +{
> > +	struct mtk_iommu_data *data = dev_get_drvdata(dev);
> > +	struct mtk_iommu_suspend_reg *reg = &data->reg;
> > +	void __iomem *base = data->base;
> > +
> > +	reg->standard_axi_mode = readl_relaxed(base +
> > +					       REG_MMU_STANDARD_AXI_MODE);
> > +	reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM);
> > +	reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG);
> > +	reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL);
> > +	return 0;
> > +}
> > +
> > +static int __maybe_unused mtk_iommu_resume(struct device *dev)
> > +{
> > +	struct mtk_iommu_data *data = dev_get_drvdata(dev);
> > +	struct mtk_iommu_suspend_reg *reg = &data->reg;
> > +	void __iomem *base = data->base;
> > +
> > +	writel_relaxed(data->m4u_dom->pgt_pa, base + REG_MMU_PT_BASE_ADDR);
> 
> Hmm, this looks like the only case where m4u_dom actually seems 
> necessary - I'm pretty sure all the others could be fairly easily 
> reworked to not use it (I might try having a quick hack at the existing 
> M4U driver to see) - at which point we could just explicitly 
> save/restore the base register here and get rid of m4u_dom entirely.

Let me take a while to think about this.

> 
> > +	writel_relaxed(reg->standard_axi_mode,
> > +		       base + REG_MMU_STANDARD_AXI_MODE);
> > +	writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM);
> > +	writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG);
> > +	writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL);
> > +	writel_relaxed(data->protect_base, base + REG_MMU_IVRP_PADDR);
> > +	return 0;
> > +}
> > +
> > +const struct dev_pm_ops mtk_iommu_pm_ops = {
> > +	SET_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume)
> > +};
> > +
> > +static struct platform_driver mtk_iommu_driver = {
> > +	.probe	= mtk_iommu_probe,
> > +	.remove	= mtk_iommu_remove,
> > +	.driver	= {
> > +		.name = "mtk-iommu",
> > +		.of_match_table = mtk_iommu_of_ids,
> > +		.pm = &mtk_iommu_pm_ops,
> > +	}
> > +};
> > +
> > +static int __init m4u_init(void)
> > +{
> > +	int ret;
> > +
> > +	ret = platform_driver_register(&mtk_iommu_driver);
> > +	if (ret)
> > +		bus_set_iommu(&platform_bus_type, NULL);
> 
> That doesn't seem necessary - the bus ops won't be set until having 
> successfully probed an M4U, and you definitely won't have managed that 
> before registering the driver ;)
> 

Thanks.

> Robin.
> 
> > +
> > +	return ret;
> > +}
> > +
> > +static void __exit m4u_exit(void)
> > +{
> > +	return platform_driver_unregister(&mtk_iommu_driver);
> > +}
> > +
> > +subsys_initcall(m4u_init);
> > +module_exit(m4u_exit);
> > +
> > +MODULE_DESCRIPTION("IOMMU API for MTK architected m4u v1 implementations");
> > +MODULE_AUTHOR("Honghui Zhang <honghui.zhang at mediatek.com>");
> > +MODULE_LICENSE("GPL v2");
> >
> 
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek




From narmstrong at baylibre.com  Tue May 24 03:03:24 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 24 May 2016 12:03:24 +0200
Subject: [PATCH] pinctrl: oxnas: Add GPIO get_direction
Message-ID: <1464084204-2271-1-git-send-email-narmstrong@baylibre.com>

Implement a get_direction callback for the OXNAS GPIO driver in order
to have pin output polarity in debugfs and new userspace ABI.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/pinctrl/pinctrl-oxnas.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

Linus,

Sorry, I should have implemented it earlier but I was focused to
have a clean driver for upstream !

Thanks,
Neil

diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c
index 5fd113c..2c6abef 100644
--- a/drivers/pinctrl/pinctrl-oxnas.c
+++ b/drivers/pinctrl/pinctrl-oxnas.c
@@ -49,6 +49,7 @@
 
 /* GPIO Registers */
 #define INPUT_VALUE	0x00
+#define OUTPUT_EN	0x04
 #define IRQ_PENDING	0x0c
 #define OUTPUT_SET	0x14
 #define OUTPUT_CLEAR	0x18
@@ -431,6 +432,15 @@ static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev,
 	return 0;
 }
 
+static int oxnas_gpio_get_direction(struct gpio_chip *chip,
+				      unsigned int offset)
+{
+	struct oxnas_gpio_bank *bank = gpiochip_get_data(chip);
+	u32 mask = BIT(offset);
+
+	return !(readl_relaxed(bank->reg_base + OUTPUT_EN) & mask);
+}
+
 static int oxnas_gpio_direction_input(struct gpio_chip *chip,
 				      unsigned int offset)
 {
@@ -664,6 +674,7 @@ static void oxnas_gpio_irq_handler(struct irq_desc *desc)
 			.label = "GPIO" #_bank,				\
 			.request = gpiochip_generic_request,		\
 			.free = gpiochip_generic_free,			\
+			.get_direction = oxnas_gpio_get_direction,	\
 			.direction_input = oxnas_gpio_direction_input,	\
 			.direction_output = oxnas_gpio_direction_output, \
 			.get = oxnas_gpio_get,				\
-- 
1.9.1



From daniel.thompson at linaro.org  Tue May 24 03:09:42 2016
From: daniel.thompson at linaro.org (Daniel Thompson)
Date: Tue, 24 May 2016 11:09:42 +0100
Subject: [PATCH] hwrng: stm32 - fix build warning
In-Reply-To: <CALszF6BPPA=tezMLhmdC4YFwmH1tGhDxCNDZNwGp1cTDWP7Fmg@mail.gmail.com>
References: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>
 <6297051.TAxtzW5OIB@wuerfel>
 <CALszF6AxXY0LK5fToFg3095+gz6xcZz8KHaYqc=o39vjpBYDmA@mail.gmail.com>
 <12548318.auB4PSA3KC@wuerfel>
 <CALszF6BPPA=tezMLhmdC4YFwmH1tGhDxCNDZNwGp1cTDWP7Fmg@mail.gmail.com>
Message-ID: <56bb8ec4-fe7e-ec09-adc3-ec7eea2d7ddd@linaro.org>

On 24/05/16 09:50, Maxime Coquelin wrote:
> diff --git a/drivers/char/hw_random/stm32-rng.c
> b/drivers/char/hw_random/stm32-rng.c
> index 92a810648bd0..2a0fc90e4dc3 100644
> --- a/drivers/char/hw_random/stm32-rng.c
> +++ b/drivers/char/hw_random/stm32-rng.c
> @@ -68,6 +68,10 @@ static int stm32_rng_read(struct hwrng *rng, void
> *data, size_t max, bool wait)
>                         } while (!sr && --timeout);
>                 }
>
> +               if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
> +                               "bad RNG status - %x\n", sr))
> +                       writel_relaxed(0, priv->base + RNG_SR);
> +
>                 /* If error detected or data not ready... */
>                 if (sr != RNG_SR_DRDY)
>                         break;

Minor quibble but I might prefer that the error handling/recovery 
actually be put on the error path itself (included in the if (sr != 
RNG_SR_DRDY) ).


Daniel.


From tomeu.vizoso at collabora.com  Tue May 24 03:11:27 2016
From: tomeu.vizoso at collabora.com (Tomeu Vizoso)
Date: Tue, 24 May 2016 12:11:27 +0200
Subject: [PATCH 1/2] drm/rockchip: vop: Do check if an update is pending
 during disable
In-Reply-To: <5742A41B.8030308@rock-chips.com>
References: <1459937686-9142-1-git-send-email-tomeu.vizoso@collabora.com>
 <5707043D.6060706@rock-chips.com>
 <CAAObsKAeAjUP1retiZqo5geOK2OkVjKvSB6g6nvGTh_rdNiFJQ@mail.gmail.com>
 <570AFAC2.8080907@rock-chips.com>
 <CAAObsKCmPZBaSudVJy8BPThhoZw8VVqxicqsmc8diApajD57nA@mail.gmail.com>
 <CAAObsKBXxb8ZS3CqLy4qsDRWLvT=w2ACANCcDLE5B47nRKtvBw@mail.gmail.com>
 <5742A41B.8030308@rock-chips.com>
Message-ID: <CAAObsKAj9Ja56buTixvp0EVBk=xE4JCXPPwXdviweHkmUQb2xg@mail.gmail.com>

On 23 May 2016 at 08:32, Mark yao <mark.yao at rock-chips.com> wrote:
> On 2016?05?05? 17:34, Tomeu Vizoso wrote:
>>
>> On 20 April 2016 at 16:23, Tomeu Vizoso <tomeu.vizoso at collabora.com>
>> wrote:
>>>
>>> On 11 April 2016 at 03:15, Mark yao <mark.yao at rock-chips.com> wrote:
>>>>
>>>> On 2016?04?08? 18:54, Tomeu Vizoso wrote:
>>>>>
>>>>> On 8 April 2016 at 03:07, Mark yao <mark.yao at rock-chips.com> wrote:
>>>>>>
>>>>>> On 2016?04?06? 18:14, Tomeu Vizoso wrote:
>>>>>>
>>>>>> When a plane is being disabled but it's still enabled, do check if the
>>>>>> previous update has been completed by reading yrgb_mst back.
>>>>>>
>>>>>> Otherwise, pending pageflips would remain pending after a CRTC is
>>>>>> disabled.
>>>>>>
>>>>>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>
>>>>>> ---
>>>>>>    drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +++--
>>>>>>    1 file changed, 3 insertions(+), 2 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>>>> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>>>> index a9b1e8b5ac85..f46b1fd1887b 100644
>>>>>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>>>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>>>>>> @@ -1064,8 +1064,9 @@ static bool vop_win_pending_is_complete(struct
>>>>>> vop_win
>>>>>> *vop_win)
>>>>>>     struct vop_plane_state *state = to_vop_plane_state(plane->state);
>>>>>>     dma_addr_t yrgb_mst;
>>>>>>
>>>>>> - if (!state->enable)
>>>>>> - return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;
>>>>>> + if (!state->enable &&
>>>>>> +    VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0)
>>>>>> + return true;
>>>>>>
>>>>>>
>>>>>> It is wrong, the patch would cause a bug.
>>>>>>
>>>>>> when state->enable is 0, check yrgb_mst == state->yrgb_mst always be
>>>>>> true,
>>>>>> because state->yrgb_mst not update on plane disabled funtion, that
>>>>>> would
>>>>>> cause iommu crash.
>>>>>
>>>>> Sorry, but I don't understand where's the bug and what could cause
>>>>> that crash. What the existing code was doing is saying that a pageflip
>>>>> event is still pending if we have told the plane to disable but for
>>>>> some reason it hasn't yet.
>>>>>
>>>>> With this modification, if we read back that it's already disabled, we
>>>>> return true as before. But if we read back that it isn't disabled yet,
>>>>> then we still check the fb pointers and compare them.
>>>>>
>>>>> The iommu mapping is removed when the _CRTC_ is disabled, and what
>>>>> this series does is to wait for the pending pageflip to finish before
>>>>> conitnuing with CRTC disablement.
>>>>
>>>>
>>>> the iommu mapping will unmap after plane disabled, we need sure that the
>>>> plane really disabled before unmap, if not, the unmap may call before
>>>> plane
>>>> really disable, vop may access unmap address, then would get iommu page
>>>> fault.
>>>
>>> Sorry, but I still don't see the error condition that you are
>>> describing. AFAICS, the unmap will happen after the last pageflip has
>>> completed.
>>>
>>>>>> About pending pageflips would remain pending, can you  describe more
>>>>>> info
>>>>>> about it? I think those pending pageflips should be ignore when CRTC
>>>>>> is
>>>>>> disabled.
>>>>>
>>>>> Well, right now in rockchip-drm pending pageflips won't be ignored
>>>>> when a CRTC is disabled, but will be delivered when it's re-enabled.
>>>>>
>>>>> If they would be to be ignored (understanding that as dropped), that
>>>>> would require modifications to clients so they keep track of which fbs
>>>>> were used in a particular crtc and destroy them when the crtc is
>>>>> disabled, but that would be incorrect when using the i915 DRM driver
>>>>> (I also assume others do the same). Given that the pageflip ioctl
>>>>> isn't driver-specific, I think there cannot be such a difference in
>>>>> behavior between drivers.
>>>>>
>>>>> With the current behavior (pending pageflip events being delayed until
>>>>> the CRTC is enabled again), compositors and other clients will be
>>>>> holding on to the fb in the pending pageflip until an arbitrary point
>>>>> in the future that may not ever come. To me that sounds like a serious
>>>>> modification of the assumptions on fb lifecycle that might not be
>>>>> warranted.
>>>>>
>>>>> So in summary, even if I haven't found any explicit documentation on
>>>>> this, I think the ABI is that any pending pageflips are to be
>>>>> delivered when that CRTC is being disabled and not later.
>>>>
>>>>
>>>> on drivers/gpu/drm/rockchip/rockchip_drm_fb.c
>>>>
>>>> drm_atomic_helper_commit_planes(dev, state, true);
>>>> rockchip_atomic_wait_for_complete(dev, state);
>>>>
>>>> We set active_only = true, I think planes can only update when crtc is
>>>> active. and rockchip_atomic_wait_for_complete only wait when crtc is
>>>> active.
>>>
>>> That's fine, but if a pageflip is pending when the client requests the
>>> CRTC to be disabled, we need to wait for the event to be emitted
>>> before we actually disable the HW.
>>
>> Hi Mark,
>>
>> could you tell me if you agree that there's a bug that needs to be
>> solved, and if so, what do you think we should do about it?
>
> Hi Tomeu
>
> Sorry for reply late.
> I don't agree the changes:
>
> - if (!state->enable)
> - return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;
> + if (!state->enable &&
> +    VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0)
> + return true;
>
> This changes actually would lead a bug.
> when we disable a plane, the vop_win_pending_is_complete would always return
> true, That is not allowed, would cause fb free too early.

Ok, maybe I need to ask you first what the original block of code
intended to achieve. The TRM I have is very terse and I don't find any
explanation there. The battery of tests I have pass just fine without
it.

> Does this patch is needed for "[PATCH 2/2] drm/rockchip: vop: Wait for
> pending events when disabling a CRTC"

Yes, this function is currently returning false when the pageflip has
been completed but the plan has been already disabled.

If you have any different idea of how to fix this bug, please share.

Thanks,

Tomeu


From m.szyprowski at samsung.com  Tue May 24 03:21:17 2016
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Tue, 24 May 2016 12:21:17 +0200
Subject: [RESEND PATCH] [media] s5p-mfc: don't close instance after free
 OUTPUT buffers
In-Reply-To: <1462572682-5195-1-git-send-email-javier@osg.samsung.com>
References: <1462572682-5195-1-git-send-email-javier@osg.samsung.com>
Message-ID: <ae33ff08-0766-973e-3181-98fb01a76b9e@samsung.com>

Hello,


On 2016-05-07 00:11, Javier Martinez Canillas wrote:
> From: ayaka <ayaka at soulik.info>
>
> User-space applications can use the VIDIOC_REQBUFS ioctl to determine if a
> memory mapped, user pointer or DMABUF based I/O is supported by the driver.
>
> So a set of VIDIOC_REQBUFS ioctl calls will be made with count 0 and then
> the real VIDIOC_REQBUFS call with count == n. But for count 0, the driver
> not only frees the buffer but also closes the MFC instance and s5p_mfc_ctx
> state is set to MFCINST_FREE.
>
> The VIDIOC_REQBUFS handler for the output device checks if the s5p_mfc_ctx
> state is set to MFCINST_INIT (which happens on an VIDIOC_S_FMT) and fails
> otherwise. So after a VIDIOC_REQBUFS(n), future VIDIOC_REQBUFS(n) calls
> will fails unless a VIDIOC_S_FMT ioctl calls happens before the reqbufs.
>
> But applications may first set the format and then attempt to determine
> the I/O methods supported by the driver (for example Gstramer does it) so
> the state won't be set to MFCINST_INIT again and VIDIOC_REQBUFS will fail.
>
> To avoid this issue, only free the buffers on VIDIOC_REQBUFS(0) but don't
> close the MFC instance to allow future VIDIOC_REQBUFS(n) calls to succeed.
>
> Signed-off-by: ayaka <ayaka at soulik.info>
> [javier: Rewrote changelog to explain the problem more detailed]
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>

>
> ---
> Hello,
>
> This is a resend of a patch posted by Ayaka some time ago [0].
> Without $SUBJECT, trying to decode a video using Gstramer fails
> on an Exynos5422 Odroid XU4 board with following error message:
>
> $ gst-launch-1.0 filesrc location=test.mov ! qtdemux ! h264parse ! v4l2video0dec ! videoconvert ! autovideosink
>
> Setting pipeline to PAUSED ...
> Pipeline is PREROLLING ...
> [ 3947.114756] vidioc_reqbufs:576: Only V4L2_MEMORY_MAP is supported
> [ 3947.114771] vidioc_reqbufs:576: Only V4L2_MEMORY_MAP is supported
> [ 3947.114903] reqbufs_output:484: Reqbufs called in an invalid state
> [ 3947.114913] reqbufs_output:510: Failed allocating buffers for OUTPUT queue
> ERROR: from element /GstPipeline:pipeline0/v4l2video0dec:v4l2video0dec0: Failed to allocate required memory.
> Additional debug info:
> gstv4l2videodec.c(575): gst_v4l2_video_dec_handle_frame (): /GstPipeline:pipeline0/v4l2video0dec:v4l2video0dec0:
> Buffer pool activation failed
> ERROR: pipeline doesn't want to preroll.
> Setting pipeline to NULL ...
> Freeing pipeline ...
>
> [0]: https://patchwork.linuxtv.org/patch/32794/
>
> Best regards,
> Javier
>
>   drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 1 -
>   1 file changed, 1 deletion(-)
>
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> index f2d6376ce618..8b9467de2d6a 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> @@ -474,7 +474,6 @@ static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
>   		ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
>   		if (ret)
>   			goto out;
> -		s5p_mfc_close_mfc_inst(dev, ctx);
>   		ctx->src_bufs_cnt = 0;
>   		ctx->output_state = QUEUE_FREE;
>   	} else if (ctx->output_state == QUEUE_FREE) {

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



From m.szyprowski at samsung.com  Tue May 24 03:22:22 2016
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Tue, 24 May 2016 12:22:22 +0200
Subject: [PATCH 0/3] [media] s5p-mfc: Fixes for issues when module is
 removed
In-Reply-To: <1462307238-21815-1-git-send-email-javier@osg.samsung.com>
References: <1462307238-21815-1-git-send-email-javier@osg.samsung.com>
Message-ID: <a64533b5-9af2-5f15-0ed3-28015b695ee0@samsung.com>

Hello,


On 2016-05-03 22:27, Javier Martinez Canillas wrote:
> Hello,
>
> This patch series fixes some issues that I noticed when trying to remove
> the s5p-mfc driver when built as a module.
>
> Some of these issues will be fixed once Marek's patches to convert the
> custom memory region reservation code is replaced by a generic one that
> supports named memory region reservation [0]. But the fixes are trivial
> so we can fix the current code until his rework patch lands.

For the whole series:

Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>

Please queue it as fixes to v4.7-rcX.

>
> [0]: https://patchwork.linuxtv.org/patch/32287/
>
> Best regards,
> Javier
>
>
> Javier Martinez Canillas (3):
>    [media] s5p-mfc: Set device name for reserved memory region devs
>    [media] s5p-mfc: Add release callback for memory region devs
>    [media] s5p-mfc: Fix race between s5p_mfc_probe() and s5p_mfc_open()
>
>   drivers/media/platform/s5p-mfc/s5p_mfc.c | 50 ++++++++++++++++++++------------
>   1 file changed, 32 insertions(+), 18 deletions(-)
>

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



From linus.walleij at linaro.org  Tue May 24 03:57:10 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 24 May 2016 12:57:10 +0200
Subject: [PATCH] gpio: lpc32xx: disable broken to_irq support
In-Reply-To: <1462988400-21738-1-git-send-email-slemieux.tyco@gmail.com>
References: <1462988400-21738-1-git-send-email-slemieux.tyco@gmail.com>
Message-ID: <CACRpkdZuT-NQJSQAK6RMdGUqiMTo3d31uGoXqgSS1cCyGzy5ow@mail.gmail.com>

On Wed, May 11, 2016 at 7:40 PM, Sylvain Lemieux
<slemieux.tyco at gmail.com> wrote:

> From: Sylvain Lemieux <slemieux at tycoint.com>
>
> The "to_irq" functionality is broken inside this driver since commit
> 76ba59f8366f ("genirq: Add irq_domain-aware core IRQ handler").
>
> The addition of the new lpc32xx irqchip driver in 4.7, fixed the
> lpc32xx platform interrupt issue.
>
> When switching to the new lpc32xx irqchip driver, a warning appear
> in the lpc32xx gpio driver: warning: "NR_IRQS" redefined.
>
> To remove this warning (temporary solution), this patch
> disables the broken "to_irq" mapping functionality support.
>
> Signed-off-by: Sylvain Lemieux <slemieux at tycoint.com>

Patch applied for fixes with Vladimir's ACK.

> * The final solution is to replace the existing lpc32xx gpio driver.
>   This work is currently in progress; refer to the following URL:
>   http://thread.gmane.org/gmane.linux.drivers.devicetree/144696

Hm, I see that the ambition was to merge the new irqchip
driver and the new GPIO driver in the same merge window.
Sorry if I was being too lazy/picky/whatever about the patch(es)
I guess I didn't quite get the scope of this change. :(

I should say that as long as we can agree that the new code
makes the kernel as a whole a better place, I am happy to
merge it. Sometimes also I need to zoom out from the GPIO
and pin control subsystem(s) and see the big picture.

Yours,
Linus Walleij


From mcoquelin.stm32 at gmail.com  Tue May 24 03:57:56 2016
From: mcoquelin.stm32 at gmail.com (Maxime Coquelin)
Date: Tue, 24 May 2016 12:57:56 +0200
Subject: [PATCH] hwrng: stm32 - fix build warning
In-Reply-To: <56bb8ec4-fe7e-ec09-adc3-ec7eea2d7ddd@linaro.org>
References: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>
 <6297051.TAxtzW5OIB@wuerfel>
 <CALszF6AxXY0LK5fToFg3095+gz6xcZz8KHaYqc=o39vjpBYDmA@mail.gmail.com>
 <12548318.auB4PSA3KC@wuerfel>
 <CALszF6BPPA=tezMLhmdC4YFwmH1tGhDxCNDZNwGp1cTDWP7Fmg@mail.gmail.com>
 <56bb8ec4-fe7e-ec09-adc3-ec7eea2d7ddd@linaro.org>
Message-ID: <CALszF6AmE3yzJL_Wn8nVa3hmTb8eHOoNbvyAh5GiiB2r4PHiyA@mail.gmail.com>

2016-05-24 12:09 GMT+02:00 Daniel Thompson <daniel.thompson at linaro.org>:
> On 24/05/16 09:50, Maxime Coquelin wrote:
>>
>> diff --git a/drivers/char/hw_random/stm32-rng.c
>> b/drivers/char/hw_random/stm32-rng.c
>> index 92a810648bd0..2a0fc90e4dc3 100644
>> --- a/drivers/char/hw_random/stm32-rng.c
>> +++ b/drivers/char/hw_random/stm32-rng.c
>> @@ -68,6 +68,10 @@ static int stm32_rng_read(struct hwrng *rng, void
>> *data, size_t max, bool wait)
>>                         } while (!sr && --timeout);
>>                 }
>>
>> +               if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
>> +                               "bad RNG status - %x\n", sr))
>> +                       writel_relaxed(0, priv->base + RNG_SR);
>> +
>>                 /* If error detected or data not ready... */
>>                 if (sr != RNG_SR_DRDY)
>>                         break;
>
>
> Minor quibble but I might prefer that the error handling/recovery actually
> be put on the error path itself (included in the if (sr != RNG_SR_DRDY) ).
Yes, it would be better.

Regards,
Maxime


From linus.walleij at linaro.org  Tue May 24 03:58:57 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 24 May 2016 12:58:57 +0200
Subject: [PATCH 6/6] pinctrl: mt8173: set GPIO16 to usb iddig mode
In-Reply-To: <1463021701.25171.5.camel@mussux00>
References: <1462868614-20602-1-git-send-email-chunfeng.yun@mediatek.com>
 <1462868614-20602-7-git-send-email-chunfeng.yun@mediatek.com>
 <CACRpkdaeD5mk7LXEWnE0=Xute8-JA-fa4tVt4fYhujEXeq2+9w@mail.gmail.com>
 <1462991546.11623.3.camel@mussux00>
 <1463017282.11651.82.camel@mhfsdcap03>
 <1463018942.1608.5.camel@mussux00>
 <1463021701.25171.5.camel@mussux00>
Message-ID: <CACRpkdZe6iLPC7EHnq0UZGsULP3-WDGtXkTdEcwHdihtAZQaRg@mail.gmail.com>

On Thu, May 12, 2016 at 4:55 AM, Hongzhou Yang
<hongzhou.yang at mediatek.com> wrote:

> We find there are some other pins still have the same problem, so please
> hold on it. Sorry for so much noise.

It's OK. Get me a big patch fixing it all when you're combed through
things and we can apply it for fixes/stable.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 24 04:04:33 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 24 May 2016 13:04:33 +0200
Subject: [PATCH 0/2] pinctrl: stm32: .pin_config_dbg_show fixes
In-Reply-To: <1463064395-4669-1-git-send-email-patrice.chotard@st.com>
References: <1463064395-4669-1-git-send-email-patrice.chotard@st.com>
Message-ID: <CACRpkdb5NedA9wTyW1yfvpCMXxHYbG5a3Q+V-E2kK6yu=esGTg@mail.gmail.com>

On Thu, May 12, 2016 at 4:46 PM,  <patrice.chotard at st.com> wrote:

> From: Patrice Chotard <patrice.chotard at st.com>
>
> Patrice Chotard (2):
>   pinctrl: stm32: fix warning
>   pinctrl: stm32: factorize stm32_pconf_input/output_get()

Patrice, can you rebase these two on top of Torvalds' fix and
resend?

Yours,
Linus Walleij


From patrice.chotard at st.com  Tue May 24 04:12:24 2016
From: patrice.chotard at st.com (Patrice Chotard)
Date: Tue, 24 May 2016 13:12:24 +0200
Subject: [PATCH 0/2] pinctrl: stm32: .pin_config_dbg_show fixes
In-Reply-To: <CACRpkdb5NedA9wTyW1yfvpCMXxHYbG5a3Q+V-E2kK6yu=esGTg@mail.gmail.com>
References: <1463064395-4669-1-git-send-email-patrice.chotard@st.com>
 <CACRpkdb5NedA9wTyW1yfvpCMXxHYbG5a3Q+V-E2kK6yu=esGTg@mail.gmail.com>
Message-ID: <57443718.2030604@st.com>



On 05/24/2016 01:04 PM, Linus Walleij wrote:
> On Thu, May 12, 2016 at 4:46 PM,  <patrice.chotard at st.com> wrote:
>
>> From: Patrice Chotard <patrice.chotard at st.com>
>>
>> Patrice Chotard (2):
>>    pinctrl: stm32: fix warning
>>    pinctrl: stm32: factorize stm32_pconf_input/output_get()
> Patrice, can you rebase these two on top of Torvalds' fix and
> resend?
Hi Linus

Sure

Patrice
>
> Yours,
> Linus Walleij



From thunder.leizhen at huawei.com  Tue May 24 04:16:37 2016
From: thunder.leizhen at huawei.com (Zhen Lei)
Date: Tue, 24 May 2016 19:16:37 +0800
Subject: [PATCH 1/1] arm64: fix flush_cache_range
Message-ID: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>

When we ran mprotect04(a test case in LTP) infinitely, it would always
failed after a few seconds. The case can be described briefly that: copy
a empty function from code area into a new memory area(created by mmap),
then call mprotect to change the protection to PROT_EXEC. The syscall
sys_mprotect will finally invoke flush_cache_range, but this function
currently only invalid icache, the operation of flush dcache is missed.

Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
---
 arch/arm64/mm/flush.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
index dbd12ea..eda4124 100644
--- a/arch/arm64/mm/flush.c
+++ b/arch/arm64/mm/flush.c
@@ -31,7 +31,7 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
 		       unsigned long end)
 {
 	if (vma->vm_flags & VM_EXEC)
-		__flush_icache_all();
+		flush_icache_range(start, end);
 }

 static void sync_icache_aliases(void *kaddr, unsigned long len)
--
2.5.0




From mark.rutland at arm.com  Tue May 24 04:23:26 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 24 May 2016 12:23:26 +0100
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
In-Reply-To: <f49d58ed-38b4-6284-11c2-8708d8443b14@codeaurora.org>
References: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
 <20160523172527.GK4976@leverpostej>
 <f49d58ed-38b4-6284-11c2-8708d8443b14@codeaurora.org>
Message-ID: <20160524112326.GC25374@leverpostej>

On Mon, May 23, 2016 at 02:22:59PM -0400, Neil Leeder wrote:
> 
> On 5/23/2016 01:25 PM, Mark Rutland wrote:
> > On Fri, May 20, 2016 at 03:13:07PM -0400, Neil Leeder wrote:
> >> L2 registers are accessed using a select register and data
> >> register pair. To prevent multiple concurrent writes to the
> >> select register by independent drivers, the write to the
> >> select register and the associated access of the data register
> >> are protected with a lock. All drivers accessing the L2
> >> registers use the set and get functions provided by
> >> l2-accessors to ensure correct reads and writes to L2 registers.
> > 
> > What will this be used for? (i.e. which drivers want to touch the L2
> > registers?).
> > 
> > Generally we expect FW to configure the caches and interconnect
> > appropriately.
> 
> The primary use is in the L2 PMU driver, which will be posted shortly.

Ok.

> >> Signed-off-by: Neil Leeder <nleeder at codeaurora.org>
> >> ---
> >>  drivers/soc/qcom/Kconfig              |  9 +++++
> >>  drivers/soc/qcom/Makefile             |  1 +
> >>  drivers/soc/qcom/l2-accessors.c       | 66 +++++++++++++++++++++++++++++++++++
> >>  include/linux/soc/qcom/l2-accessors.h | 27 ++++++++++++++
> >>  4 files changed, 103 insertions(+)
> >>  create mode 100644 drivers/soc/qcom/l2-accessors.c
> >>  create mode 100644 include/linux/soc/qcom/l2-accessors.h
> > 
> > These are awfully generic file names (and function names). Which SoCs
> > does this apply to?
> > 
> > It would be good to give these more specific names.
> 
> It's under soc/qcom, and dependent on ARCH_QCOM and (in v2) also on ARM64. It applies to all QCOM ARM64 SoCs.

Per Christopher's comment, it sounds like this applies to QDF24xx.

Given that the code uses IMPLEMENTATION DEFINED system registers, I
presume that this does not apply to MSM8916 which uses Cortex-A53, for
example (though perhaps it does, and I am mistaken).

> Given that it can only be used in a QCOM driver, and the include path has qcom in it, I'd
> prefer not to add redundancy by adding another qcom in there.

I'm not asking for another "qcom", but simply the SoC variant or family
(e.g. "qdf24xx" would be fine).

> >> diff --git a/include/linux/soc/qcom/l2-accessors.h b/include/linux/soc/qcom/l2-accessors.h
> >> new file mode 100644
> >> index 0000000..563c114
> >> --- /dev/null
> >> +++ b/include/linux/soc/qcom/l2-accessors.h
> >> @@ -0,0 +1,27 @@
> >> +/*
> >> + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
> >> + *
> >> + * This program is free software; you can redistribute it and/or modify
> >> + * it under the terms of the GNU General Public License version 2 and
> >> + * only version 2 as published by the Free Software Foundation.
> >> + *
> >> + * This program is distributed in the hope that it will be useful,
> >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >> + * GNU General Public License for more details.
> >> + */
> >> +
> > 
> >> +#ifndef __QCOM_L2_ACCESSORS_H
> >> +#define __QCOM_L2_ACCESSORS_H
> >> +
> >> +#ifdef CONFIG_QCOM_L2_ACCESSORS
> >> +void set_l2_indirect_reg(u64 reg_addr, u64 val);
> >> +u64 get_l2_indirect_reg(u64 reg_addr);
> >> +#else
> >> +static inline void set_l2_indirect_reg(u64 reg_addr, u64 val) {}
> >> +static inline u64 get_l2_indirect_reg(u64 reg_addr)
> >> +{
> >> +	return 0;
> >> +}
> > 
> > Surely it would be better to error out on any unintentional use of these
> > at build time?
> 
> This allows building code which is common to ARM SoCs and QCOM SoCs without having to ifdef out the
> QCOM-specific pieces.

These shouldn't appear in generic code.

Other than the L2 PMU driver (which presumably depends on or selects
CONFIG_QCOM_L2_ACCESSORS), what code would you have to ifdef?

I don't have a major concern on this, I just don't see where it should
matter.

Thanks,
Mark.


From mark.rutland at arm.com  Tue May 24 04:37:27 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 24 May 2016 12:37:27 +0100
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
Message-ID: <20160524113727.GD25374@leverpostej>

On Tue, May 24, 2016 at 07:16:37PM +0800, Zhen Lei wrote:
> When we ran mprotect04(a test case in LTP) infinitely, it would always
> failed after a few seconds. The case can be described briefly that: copy
> a empty function from code area into a new memory area(created by mmap),
> then call mprotect to change the protection to PROT_EXEC. The syscall
> sys_mprotect will finally invoke flush_cache_range, but this function
> currently only invalid icache, the operation of flush dcache is missed.

In the LTP code I see powerpc-specific D-cache / I-cache synchronisation
(i.e. d-cache cleaning followed by I-cache invalidation), so there
appears to be some expectation of userspace maintenance. Hoever, there
is no such ARM-specific I-cache maintenance.

It looks like the test may be missing I-cache maintenance regardless of
the semantics of mprotect in this case.

I have not yet devled into flush_cache_range and how it is called.

Thanks,
Mark.

> Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
> ---
>  arch/arm64/mm/flush.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
> index dbd12ea..eda4124 100644
> --- a/arch/arm64/mm/flush.c
> +++ b/arch/arm64/mm/flush.c
> @@ -31,7 +31,7 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
>  		       unsigned long end)
>  {
>  	if (vma->vm_flags & VM_EXEC)
> -		__flush_icache_all();
> +		flush_icache_range(start, end);
>  }
> 
>  static void sync_icache_aliases(void *kaddr, unsigned long len)
> --
> 2.5.0
> 
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


From nava.manne at xilinx.com  Tue May 24 04:47:31 2016
From: nava.manne at xilinx.com (Nava kishore Manne)
Date: Tue, 24 May 2016 11:47:31 +0000
Subject: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
In-Reply-To: <14123451.MsNvJvqaJX@wuerfel>
References: <1464067268-35299-1-git-send-email-navam@xilinx.com>
 <14123451.MsNvJvqaJX@wuerfel>
Message-ID: <C89496FEAE474D468F30D558A9468D9F26CED772@XAP-PVEXMBX01.xlnx.xilinx.com>



> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd at arndb.de]
> Sent: Tuesday, May 24, 2016 2:21 PM
> To: Nava kishore Manne <navam at xilinx.com>
> Cc: robh+dt at kernel.org; pawel.moll at arm.com; mark.rutland at arm.com;
> ijc+devicetree at hellion.org.uk; galak at codeaurora.org; Michal Simek
> <michals at xilinx.com>; Soren Brinkmann <sorenb at xilinx.com>;
> balbi at ti.com; gregkh at linuxfoundation.org; Hyun Kwon
> <hyunk at xilinx.com>; Nava kishore Manne <navam at xilinx.com>; Radhey
> Shyam Pandey <radheys at xilinx.com>; devicetree at vger.kernel.org; linux-
> arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> Subject: Re: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
> 
> On Tuesday, May 24, 2016 10:51:08 AM CEST Nava kishore Manne wrote:
> > diff --git a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> > b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> > index 47b4e39..09df757 100644
> > --- a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> > +++ b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> > @@ -1,18 +1,23 @@
> >  Xilinx USB2 device controller
> >
> >  Required properties:
> > -- compatible		: Should be "xlnx,usb2-device-4.00.a"
> > +- compatible		: Should be "xlnx,usb2-device-4.00.a" or
> > +			  "xlnx,usb2-device-5.00"
> >  - reg			: Physical base address and size of the USB2
> >  			  device registers map.
> >  - interrupts		: Should contain single irq line of USB2 device
> >  			  controller
> >  - xlnx,has-builtin-dma	: if DMA is included
> > +- dma-ranges		: Should be as the following
> > +			  <child-bus-address, parent-bus-address, length>
> 
> A USB host should not have any children that are DMA capable, I think, so
> this property doesn't make sense here. It should be part of the parent bus.
> 
Will send next version (v4) by removing this property from the DT.

> > +- xlnx,addrwidth	: Should be the dma addressing size in bits(ex: 64
> bits)
> 
> I'm still unconvinced about the property definition here. What are the
> possible options for the IP block? I don't think I ever saw a reply from you to
> my earlier questions.
> 

Sorry Let me clearly explain

>From the IP version 5.0 onwards The IP support both 32-bit and 64-bit addressing.
But the older version of the IP's supports only 32-bit addressing.

This addrwidth property differentiates the address width for the new IP (I mean 5.0 version on wards)
For older IP it will be always 32-bit.

Please let me know if you are still not clear.

Regards,
Navakishore.


> > @@ -214,6 +223,20 @@ static const struct usb_endpoint_descriptor
> config_bulk_out_desc = {
> >  	.wMaxPacketSize		= cpu_to_le16(EP0_MAX_PACKET),
> >  };
> >
> > +/**
> > + * xudc_write64 - write 64bit value to device registers
> > + * @addr: base addr of device registers
> > + * @offset: register offset
> > + * @val: data to be written
> > + **/
> > +static void xudc_write64(struct xusb_ep *ep, u32 offset, u64 val) {
> > +	struct xusb_udc *udc = ep->udc;
> > +
> > +	udc->write_fn(udc->addr, offset, lower_32_bits(val));
> > +	udc->write_fn(udc->addr, offset+0x04, upper_32_bits(val)); }
> > +
> >  /**
> >   * xudc_write32 - little endian write to device registers
> >   * @addr: base addr of device registers @@ -330,8 +353,13 @@ static
> > int xudc_start_dma(struct xusb_ep *ep, dma_addr_t src,
> >  	 * destination registers and then set the length
> >  	 * into the DMA length register.
> >  	 */
> > -	udc->write_fn(udc->addr, XUSB_DMA_DSAR_ADDR_OFFSET, src);
> > -	udc->write_fn(udc->addr, XUSB_DMA_DDAR_ADDR_OFFSET, dst);
> > +	if (udc->dma_addrwidth > 32) {
> > +		xudc_write64(ep, XUSB_DMA_DSAR_ADDR_OFFSET_LSB,
> src);
> > +		xudc_write64(ep, XUSB_DMA_DDAR_ADDR_OFFSET_LSB,
> dst);
> > +	} else {
> > +		udc->write_fn(udc->addr,
> XUSB_DMA_DSAR_ADDR_OFFSET, src);
> > +		udc->write_fn(udc->addr,
> XUSB_DMA_DDAR_ADDR_OFFSET, dst);
> > +	}
> >  	udc->write_fn(udc->addr, XUSB_DMA_LENGTH_OFFSET, length);
> >
> 
> This looks good.
> 
> 	Arnd


From patrice.chotard at st.com  Tue May 24 04:57:42 2016
From: patrice.chotard at st.com (patrice.chotard at st.com)
Date: Tue, 24 May 2016 13:57:42 +0200
Subject: [PATCH v2] pinctrl: stm32: .pin_config_dbg_show fixes
Message-ID: <1464091063-22341-1-git-send-email-patrice.chotard@st.com>

From: Patrice Chotard <patrice.chotard at st.com>

v1 -> v2
	_ rebase on top of Linus Torsvald tree.
	_ remove "[PATCH 1/2]: pinctrl: stm32: fix warning", already fixed by Linus Torvalds

Patrice Chotard (1):
  pinctrl: stm32: factorize stm32_pconf_input/output_get()

 drivers/pinctrl/stm32/pinctrl-stm32.c | 31 ++++++++++---------------------
 1 file changed, 10 insertions(+), 21 deletions(-)

-- 
1.9.1



From patrice.chotard at st.com  Tue May 24 04:57:43 2016
From: patrice.chotard at st.com (patrice.chotard at st.com)
Date: Tue, 24 May 2016 13:57:43 +0200
Subject: [PATCH v2] pinctrl: stm32: factorize stm32_pconf_input/output_get()
In-Reply-To: <1464091063-22341-1-git-send-email-patrice.chotard@st.com>
References: <1464091063-22341-1-git-send-email-patrice.chotard@st.com>
Message-ID: <1464091063-22341-2-git-send-email-patrice.chotard@st.com>

From: Patrice Chotard <patrice.chotard at st.com>

As these 2 functions code are 95% similar, factorize them.

Signed-off-by: Patrice Chotard <patrice.chotard at st.com>
---
 drivers/pinctrl/stm32/pinctrl-stm32.c | 31 ++++++++++---------------------
 1 file changed, 10 insertions(+), 21 deletions(-)

diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
index ae9fab8..4ae596b 100644
--- a/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ b/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -638,8 +638,8 @@ static u32 stm32_pconf_get_bias(struct stm32_gpio_bank *bank,
 	return (val >> (offset * 2));
 }
 
-static bool stm32_pconf_input_get(struct stm32_gpio_bank *bank,
-	unsigned int offset)
+static bool stm32_pconf_get(struct stm32_gpio_bank *bank,
+	unsigned int offset, bool dir)
 {
 	unsigned long flags;
 	u32 val;
@@ -647,23 +647,12 @@ static bool stm32_pconf_input_get(struct stm32_gpio_bank *bank,
 	clk_enable(bank->clk);
 	spin_lock_irqsave(&bank->lock, flags);
 
-	val = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset));
-
-	spin_unlock_irqrestore(&bank->lock, flags);
-	clk_disable(bank->clk);
-
-	return val;
-}
-
-static bool stm32_pconf_output_get(struct stm32_gpio_bank *bank,
-	unsigned int offset)
-{
-	unsigned long flags;
-	u32 val;
-
-	clk_enable(bank->clk);
-	spin_lock_irqsave(&bank->lock, flags);
-	val = !!(readl_relaxed(bank->base + STM32_GPIO_ODR) & BIT(offset));
+	if (dir)
+		val = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) &
+			 BIT(offset));
+	else
+		val = !!(readl_relaxed(bank->base + STM32_GPIO_ODR) &
+			 BIT(offset));
 
 	spin_unlock_irqrestore(&bank->lock, flags);
 	clk_disable(bank->clk);
@@ -772,7 +761,7 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
 	switch (mode) {
 	/* input */
 	case 0:
-		val = stm32_pconf_input_get(bank, offset);
+		val = stm32_pconf_get(bank, offset, true);
 		seq_printf(s, "- %s - %s",
 			   val ? "high" : "low",
 			   biasing[bias]);
@@ -782,7 +771,7 @@ static void stm32_pconf_dbg_show(struct pinctrl_dev *pctldev,
 	case 1:
 		drive = stm32_pconf_get_driving(bank, offset);
 		speed = stm32_pconf_get_speed(bank, offset);
-		val = stm32_pconf_output_get(bank, offset);
+		val = stm32_pconf_get(bank, offset, false);
 		seq_printf(s, "- %s - %s - %s - %s %s",
 			   val ? "high" : "low",
 			   drive ? "open drain" : "push pull",
-- 
1.9.1



From maxime.coquelin at st.com  Tue May 24 05:04:21 2016
From: maxime.coquelin at st.com (Maxime Coquelin)
Date: Tue, 24 May 2016 14:04:21 +0200
Subject: [PATCH v2] pinctrl: stm32: factorize
 stm32_pconf_input/output_get()
In-Reply-To: <1464091063-22341-2-git-send-email-patrice.chotard@st.com>
References: <1464091063-22341-1-git-send-email-patrice.chotard@st.com>
 <1464091063-22341-2-git-send-email-patrice.chotard@st.com>
Message-ID: <57444345.9030107@st.com>



On 05/24/2016 01:57 PM, patrice.chotard at st.com wrote:
> From: Patrice Chotard<patrice.chotard at st.com>
>
> As these 2 functions code are 95% similar, factorize them.
>
> Signed-off-by: Patrice Chotard<patrice.chotard at st.com>
> ---
>   drivers/pinctrl/stm32/pinctrl-stm32.c | 31 ++++++++++---------------------
>   1 file changed, 10 insertions(+), 21 deletions(-)

Acked-by: Maxime Coquelin <maxime.coquelin at st.com>

Thanks!
Maxime


From thunder.leizhen at huawei.com  Tue May 24 05:19:05 2016
From: thunder.leizhen at huawei.com (Leizhen (ThunderTown))
Date: Tue, 24 May 2016 20:19:05 +0800
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <20160524113727.GD25374@leverpostej>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
 <20160524113727.GD25374@leverpostej>
Message-ID: <574446B9.8040105@huawei.com>



On 2016/5/24 19:37, Mark Rutland wrote:
> On Tue, May 24, 2016 at 07:16:37PM +0800, Zhen Lei wrote:
>> When we ran mprotect04(a test case in LTP) infinitely, it would always
>> failed after a few seconds. The case can be described briefly that: copy
>> a empty function from code area into a new memory area(created by mmap),
>> then call mprotect to change the protection to PROT_EXEC. The syscall
>> sys_mprotect will finally invoke flush_cache_range, but this function
>> currently only invalid icache, the operation of flush dcache is missed.
> 
> In the LTP code I see powerpc-specific D-cache / I-cache synchronisation
> (i.e. d-cache cleaning followed by I-cache invalidation), so there
> appears to be some expectation of userspace maintenance. Hoever, there
> is no such ARM-specific I-cache maintenance.
But I see some other platforms have D-cache maintenance, like: arch/nios2/mm/cacheflush.c
And according to the name of flush_cache_range, it should do this, I judged. Otherwise,
mprotect04 will be failed on more platforms, it's easy to discover. Only PPC have specific
cache synchronization, maybe it meets some hardware limitation. It's impossible a programmer
fixed a common bug on only one platform but leave others unchanged.

> 
> It looks like the test may be missing I-cache maintenance regardless of
> the semantics of mprotect in this case.
> 
> I have not yet devled into flush_cache_range and how it is called.

SYSCALL_DEFINE3(mprotect ---> mprotect_fixup ---> change_protection ---> change_protection_range --> flush_cache_range

> 
> Thanks,
> Mark.
> 
>> Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
>> ---
>>  arch/arm64/mm/flush.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
>> index dbd12ea..eda4124 100644
>> --- a/arch/arm64/mm/flush.c
>> +++ b/arch/arm64/mm/flush.c
>> @@ -31,7 +31,7 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
>>  		       unsigned long end)
>>  {
>>  	if (vma->vm_flags & VM_EXEC)
>> -		__flush_icache_all();
>> +		flush_icache_range(start, end);
>>  }
>>
>>  static void sync_icache_aliases(void *kaddr, unsigned long len)
>> --
>> 2.5.0
>>
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
> 
> .
> 



From hs.liao at mediatek.com  Tue May 24 05:27:09 2016
From: hs.liao at mediatek.com (Horng-Shyang Liao)
Date: Tue, 24 May 2016 20:27:09 +0800
Subject: [PATCH v7 2/4] CMDQ: Mediatek CMDQ driver
In-Reply-To: <1464059159.7425.6.camel@mtksdaap41>
References: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
 <1464006190-344-3-git-send-email-hs.liao@mediatek.com>
 <1464059159.7425.6.camel@mtksdaap41>
Message-ID: <1464092829.19894.16.camel@mtksdaap41>

Hi CK,

Reply in line.

On Tue, 2016-05-24 at 11:05 +0800, CK Hu wrote:
> Hi, HS:
> 
> Some comments below.
> 
> On Mon, 2016-05-23 at 20:23 +0800, HS Liao wrote:
...
> > +struct cmdq_task {
> > +	struct cmdq		*cmdq;
> > +	struct list_head	list_entry;
> > +	enum cmdq_task_state	task_state;
> > +	void			*va_base; /* va */
> 
> It's obviously that va_base is va, so the comment is redundant.

Will remove comment.

> > +	dma_addr_t		mva_base; /* pa */
> > +	u64			engine_flag;
> > +	size_t			command_size;
> > +	u32			num_cmd;
> > +	struct cmdq_thread	*thread;
> > +	struct cmdq_task_cb	cb;
> > +	struct work_struct	release_work;
> > +};
...
> > +static struct cmdq_task *cmdq_task_acquire(struct cmdq_rec *rec,
> > +					   struct cmdq_task_cb cb)
> > +{
> > +	struct cmdq *cmdq = rec->cmdq;
> > +	struct device *dev = cmdq->dev;
> > +	struct cmdq_task *task;
> > +
> > +	task = kzalloc(sizeof(*task), GFP_KERNEL);
> > +	INIT_LIST_HEAD(&task->list_entry);
> > +	task->va_base = dma_alloc_coherent(dev, rec->command_size,
> > +					   &task->mva_base, GFP_KERNEL);
> > +	if (!task->va_base) {
> > +		dev_err(dev, "allocate command buffer failed\n");
> > +		kfree(task);
> > +		return NULL;
> > +	}
> > +
> > +	task->cmdq = cmdq;
> > +	task->command_size = rec->command_size;
> > +	task->engine_flag = rec->engine_flag;
> > +	task->task_state = TASK_STATE_BUSY;
> > +	task->cb = cb;
> > +	memcpy(task->va_base, rec->buf, rec->command_size);
> > +	task->num_cmd = task->command_size / sizeof(u64);
> 
> Already define CMDQ_INST_SIZE, so use it and the readability is better.

Will use CMDQ_INST_SIZE.

> > +	return task;
> > +}
...
> > +static void cmdq_task_exec(struct cmdq_task *task, struct cmdq_thread *thread)
> > +{
> > +	struct cmdq *cmdq = task->cmdq;
> > +	unsigned long flags;
> > +	unsigned long curr_pa, end_pa;
> > +
> > +	WARN_ON(clk_prepare_enable(cmdq->clock) < 0);
> > +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> > +	task->thread = thread;
> > +	task->task_state = TASK_STATE_BUSY;
> 
> Once a task is created, its state is already BUSY, so this assignment is
> redundant.

I prefer to keep this because task may add, remove, or reorder states in
the future. If we remove this, it is easy to cause a bug here.

> > +	if (list_empty(&thread->task_busy_list)) {
> > +		WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
> > +
> > +		cmdq_thread_writel(thread, task->mva_base, CMDQ_THR_CURR_ADDR);
> > +		cmdq_thread_writel(thread, task->mva_base + task->command_size,
> > +				   CMDQ_THR_END_ADDR);
> > +		cmdq_thread_writel(thread, CMDQ_THR_PRIORITY, CMDQ_THR_CFG);
> > +		cmdq_thread_writel(thread, CMDQ_THR_IRQ_EN,
> > +				   CMDQ_THR_IRQ_ENABLE);
> > +
> > +		list_move_tail(&task->list_entry,
> > +			       &thread->task_busy_list);
> 
> Moving this statement to just before spin_unlock_irqrestore() can reduce
> the duplicated code in else part.

Will do.

> > +
> > +		cmdq_thread_writel(thread, CMDQ_THR_ENABLED,
> > +				   CMDQ_THR_ENABLE_TASK);
> > +	} else {
> > +		WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
> > +
> > +		/*
> > +		 * check boundary condition
> > +		 * PC = END - 8, EOC is executed
> > +		 * PC = END, all CMDs are executed
> > +		 */
> > +		curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
> > +		end_pa = cmdq_thread_readl(thread, CMDQ_THR_END_ADDR);
> > +		if (curr_pa == end_pa - 8 || curr_pa == end_pa) {
> > +			/* set to this task directly */
> > +			cmdq_thread_writel(thread, task->mva_base,
> > +					   CMDQ_THR_CURR_ADDR);
> > +		} else {
> > +			cmdq_task_insert_into_thread(task);
> > +
> > +			if (thread == &cmdq->thread[CMDQ_THR_DISP_MAIN_IDX] ||
> > +			    thread == &cmdq->thread[CMDQ_THR_DISP_SUB_IDX])
> > +				cmdq_task_remove_wfe(task);
> > +
> > +			smp_mb(); /* modify jump before enable thread */
> > +		}
> > +
> > +		cmdq_thread_writel(thread, task->mva_base + task->command_size,
> > +				   CMDQ_THR_END_ADDR);
> > +		list_move_tail(&task->list_entry, &thread->task_busy_list);
> > +		cmdq_thread_resume(thread);
> > +	}
> > +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > +}
...
> > +static void cmdq_thread_irq_handler(struct cmdq *cmdq, int tid)
> > +{
> > +	struct cmdq_thread *thread = &cmdq->thread[tid];
> > +	unsigned long flags = 0L;
> > +	int value;
> > +
> > +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> > +
> > +	/*
> > +	 * it is possible for another CPU core
> > +	 * to run "release task" right before we acquire the spin lock
> > +	 * and thus reset / disable this HW thread
> > +	 * so we check both the IRQ flag and the enable bit of this thread
> > +	 */
> > +	value = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> > +	if (!(value & CMDQ_THR_IRQ_MASK)) {
> > +		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > +		return;
> > +	}
> 
> If this case happen and just return without clearing irq status, the irq
> would keep triggering and system hang up. So just remove this checking
> and go down to clear irq status.

This case is safe because irq status is cleared.
But, next if condition has the problem which you mentioned.

I will change it as below.

	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
	      CMDQ_THR_ENABLED)) {
		cmdq_thread_writel(thread, ~value, CMDQ_THR_IRQ_STATUS);
		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
		return;
	}

If thread is disabled, tasks must be all finished.
Therefore, just clear irq status and return.

> > +
> > +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> > +	      CMDQ_THR_ENABLED)) {
> > +		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > +		return;
> > +	}
> > +
> > +	cmdq_thread_writel(thread, ~value, CMDQ_THR_IRQ_STATUS);
> > +
> > +	if (value & CMDQ_THR_IRQ_ERROR)
> > +		cmdq_handle_error_done(cmdq, thread, true);
> > +	else if (value & CMDQ_THR_IRQ_DONE)
> > +		cmdq_handle_error_done(cmdq, thread, false);
> 
> These irq status checking and clearing code here is the same as those in
> cmdq_task_handle_error_result(). To move the checking and clearing code
> into cmdq_handle_error_done() and here just to call
> cmdq_handle_error_done(cmdq, thread) would reduce duplicated code.

Will do.

> > +
> > +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > +}
...
> > +static int cmdq_task_handle_error_result(struct cmdq_task *task)
> > +{
> > +	struct cmdq *cmdq = task->cmdq;
> > +	struct device *dev = cmdq->dev;
> > +	struct cmdq_thread *thread = task->thread;
> > +	struct cmdq_task *next_task, *prev_task;
> > +	u32 irq_flag;
> > +
> > +	/* suspend HW thread to ensure consistency */
> > +	WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
> > +
> > +	/*
> > +	 * Save next_task and prev_task in advance
> > +	 * since cmdq_handle_error_done will remove list_entry.
> > +	 */
> > +	next_task = prev_task = NULL;
> > +	if (task->list_entry.next != &thread->task_busy_list)
> > +		next_task = list_next_entry(task, list_entry);
> > +	if (task->list_entry.prev != &thread->task_busy_list)
> > +		prev_task = list_prev_entry(task, list_entry);
> > +
> > +	/*
> > +	 * Although IRQ is disabled, GCE continues to execute.
> > +	 * It may have pending IRQ before HW thread is suspended,
> > +	 * so check this condition again.
> > +	 */
> > +	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> > +	if (irq_flag & CMDQ_THR_IRQ_ERROR)
> > +		cmdq_handle_error_done(cmdq, thread, true);
> > +	else if (irq_flag & CMDQ_THR_IRQ_DONE)
> > +		cmdq_handle_error_done(cmdq, thread, false);
> > +	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
> > +
> > +	if (task->task_state == TASK_STATE_DONE) {
> > +		cmdq_thread_resume(thread);
> > +		return 0;
> > +	}
> > +
> > +	if (task->task_state == TASK_STATE_ERROR) {
> > +		dev_err(dev, "task 0x%p error\n", task);
> > +		if (next_task) /* move to next task */
> > +			cmdq_thread_writel(thread, next_task->mva_base,
> > +					   CMDQ_THR_CURR_ADDR);
> > +		cmdq_thread_resume(thread);
> > +		return -ECANCELED;
> > +	}
> > +
> > +	/* If task is running, force to remove it. */
> > +	dev_err(dev, "task 0x%p timeout or killed\n", task);
> > +
> > +	if (task->task_state == TASK_STATE_BUSY)
> 
> The state must be BUSY here, so the checking is redundant.

Will remove.

> > +		task->task_state = TASK_STATE_ERROR;
> > +
> > +	if (prev_task) {
> > +		u64 *prev_va = prev_task->va_base;
> > +		u64 *curr_va = task->va_base;
> > +
> > +		/* copy JUMP instruction */
> > +		prev_va[prev_task->num_cmd - 1] = curr_va[task->num_cmd - 1];
> > +
> > +		cmdq_thread_invalidate_fetched_data(thread);
> > +	} else if (next_task) { /* move to next task */
> > +		cmdq_thread_writel(thread, next_task->mva_base,
> > +				   CMDQ_THR_CURR_ADDR);
> > +	}
> > +
> > +	list_del(&task->list_entry);
> > +	cmdq_thread_resume(thread);
> > +
> > +	/* call cb here to prevent lock */
> > +	if (task->cb.cb) {
> > +		struct cmdq_cb_data cmdq_cb_data;
> > +
> > +		cmdq_cb_data.err = true;
> > +		cmdq_cb_data.data = task->cb.data;
> > +		task->cb.cb(cmdq_cb_data);
> > +	}
> > +
> > +	return -ECANCELED;
> > +}
> > +
> > +static int cmdq_task_wait_and_release(struct cmdq_task *task)
> > +{
> > +	struct cmdq *cmdq = task->cmdq;
> > +	struct device *dev = cmdq->dev;
> > +	struct cmdq_thread *thread = task->thread;
> > +	int wait_q;
> > +	int err = 0;
> > +	unsigned long flags;
> > +
> > +	wait_q = wait_event_timeout(thread->wait_queue,
> > +				    task->task_state != TASK_STATE_BUSY,
> > +				    msecs_to_jiffies(CMDQ_DEFAULT_TIMEOUT_MS));
> > +	if (!wait_q)
> > +		dev_dbg(dev, "timeout!\n");
> 
> Task state may be changed in cmdq_task_handle_error_result() and the
> actual time out message print is in cmdq_task_handle_error_result(), so
> this print should be removed.

Will remove.

> > +
> > +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> > +	if (task->task_state != TASK_STATE_DONE)
> > +		err = cmdq_task_handle_error_result(task);
> > +	if (list_empty(&thread->task_busy_list))
> > +		cmdq_thread_disable(cmdq, thread);
> > +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > +
> > +	/* release regardless of success or not */
> > +	clk_disable_unprepare(cmdq->clock);
> > +	cmdq_task_release(task);
> > +
> > +	return err;
> > +}
...
> 
> Regards,
> CK

Thanks,
HS



From hs.liao at mediatek.com  Tue May 24 05:34:51 2016
From: hs.liao at mediatek.com (Horng-Shyang Liao)
Date: Tue, 24 May 2016 20:34:51 +0800
Subject: [PATCH v7 4/4] CMDQ: suspend/resume protection
In-Reply-To: <1464081410.30351.20.camel@mtksdaap41>
References: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
 <1464006190-344-5-git-send-email-hs.liao@mediatek.com>
 <1464081410.30351.20.camel@mtksdaap41>
Message-ID: <1464093291.19894.20.camel@mtksdaap41>

Hi CK,

On Tue, 2016-05-24 at 17:16 +0800, CK Hu wrote:
> On Mon, 2016-05-23 at 20:23 +0800, HS Liao wrote:
...  
> > +static int cmdq_suspend(struct device *dev)
> > +{
> > +	struct cmdq *cmdq = dev_get_drvdata(dev);
> > +	u32 exec_threads;
> > +	int ref_count;
> > +	unsigned long flags;
> > +	struct cmdq_thread *thread;
> > +	struct cmdq_task *task, *tmp;
> > +	int i;
> > +
> > +	/* lock to prevent new tasks */
> > +	mutex_lock(&cmdq->task_mutex);
> > +	cmdq->suspending = true;
> > +
> > +	exec_threads = readl(cmdq->base + CMDQ_CURR_LOADED_THR);
> > +	ref_count = atomic_read(&cmdq->thread_usage);
> > +	if (ref_count <= 0 && !(exec_threads & CMDQ_THR_EXECUTING))
> > +		goto exit;
> > +
> > +	dev_err(dev, "suspend: kill running, tasks.\n");
> > +	dev_err(dev, "threads: 0x%08x, ref:%d\n", exec_threads, ref_count);
> > +
> > +	/*
> > +	 * We need to ensure the system is ready to suspend,
> > +	 * so kill all running CMDQ tasks and release HW engines.
> > +	 */
> > +
> > +	/* remove all active tasks from thread and disable thread */
> > +	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
> > +		thread = &cmdq->thread[i];
> > +
> > +		if (list_empty(&thread->task_busy_list))
> > +			continue;
> > +
> > +		/* prevent clk disable in release flow */
> > +		clk_prepare_enable(cmdq->clock);
> > +		cmdq_thread_suspend(cmdq, thread);
> > +
> > +		list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
> > +					 list_entry) {
> > +			bool already_done = false;
> > +
> > +			spin_lock_irqsave(&cmdq->exec_lock, flags);
> > +			if (task->task_state == TASK_STATE_BUSY) {
> > +				/* still wait_event */
> > +				list_del(&task->list_entry);
> > +				task->task_state = TASK_STATE_KILLED;
> > +			} else {
> > +				/* almost finish its work */
> > +				already_done = true;
> > +			}
> > +			spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > +
> > +			/*
> > +			 * TASK_STATE_KILLED will unlock
> > +			 * wait_event_timeout in cmdq_task_wait_and_release(),
> > +			 * so flush_work to wait auto release flow.
> > +			 *
> > +			 * We don't know processes running order,
> > +			 * so call cmdq_task_release_unlocked() here to
> > +			 * prevent releasing task before flush_work, and
> > +			 * also to prevent deadlock of task_mutex.
> > +			 */
> > +			if (!already_done) {
> > +				flush_work(&task->release_work);
> > +				cmdq_task_release_unlocked(task);
> > +			}
> > +		}
> > +
> > +		cmdq_thread_resume(thread);
> > +		cmdq_thread_disable(cmdq, &cmdq->thread[i]);
> > +		clk_disable_unprepare(cmdq->clock);
> > +	}
> 
> It's cmdq client's bug if there are some tasks have not been executed
> while cmdq is suspending. I think cmdq can simply wait these tasks to be
> done or timeout rather than killing them because it's unnecessary to
> speed up anything in error state. Just wait for cmdq client to fix this
> bug.
> 
> This 'for loop' can be simply replace by:
> 
> flush_workqueue(cmdq->task_release_wq);
> 
> But this does not wait for task which is created by cmdq_rec_flush().
> One solution for this is to re-write cmdq_rec_flush() as below:
> 
> struct cmdq_flush_completion {
> 	struct completion cmplt;
> 	bool err;
> };
> 
> static int cmdq_rec_flush_cb(struct cmdq_cb_data data)
> {
> 	struct cmdq_flush_completion *cmplt = data.data;
> 
> 	cmplt->err = data.err;
> 	complete(&cmplt->cmplt);
> 
> 	return 0;
> }
> 
> int cmdq_rec_flush(struct cmdq_rec *rec)
> {
> 	int err;
> 	struct cmdq_flush_completion cmplt;
> 
> 	init_completion(&cmplt.cmplt);
> 	err = cmdq_rec_flush_async(rec, cmdq_rec_flush_cb, &cmplt);
> 	if (err < 0)
> 		return err;
> 	wait_for_completion(&cmplt.cmplt);
> 	return cmplt.err ? -EFAULT : 0;
> }
> 

Will do and merge into CMDQ driver.

> > +
> > +exit:
> > +	cmdq->suspended = true;
> > +	cmdq->suspending = false;
> > +	mutex_unlock(&cmdq->task_mutex);
> > +	return 0; /* ALWAYS allow suspend */
> > +}
> > +
...

Thanks,
HS



From linus.walleij at linaro.org  Tue May 24 05:41:10 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 24 May 2016 14:41:10 +0200
Subject: [PATCH] pinctrl: nomadik: fix inversion of gpio direction
Message-ID: <1464093670-29370-1-git-send-email-linus.walleij@linaro.org>

The input/output directions were inversed on the GPIO direction
read function. Loose a ! and it is correct.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 drivers/pinctrl/nomadik/pinctrl-nomadik.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
index ccbfc325c778..38faceff2f08 100644
--- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
@@ -854,7 +854,7 @@ static int nmk_gpio_get_dir(struct gpio_chip *chip, unsigned offset)
 
 	clk_enable(nmk_chip->clk);
 
-	dir = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset));
+	dir = !(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset));
 
 	clk_disable(nmk_chip->clk);
 
-- 
2.4.11



From christoffer.dall at linaro.org  Tue May 24 05:45:09 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 14:45:09 +0200
Subject: [PATCH 5/7] arm64: KVM: Make ICC_SRE_EL1 access return the
 configured SRE value
In-Reply-To: <1464007023-11736-6-git-send-email-marc.zyngier@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
 <1464007023-11736-6-git-send-email-marc.zyngier@arm.com>
Message-ID: <20160524124509.GE3582@cbox>

On Mon, May 23, 2016 at 01:37:01PM +0100, Marc Zyngier wrote:
> When we trap ICC_SRE_EL1, we handle it as RAZ/WI. It would be
> more correct to actual make it RO, and return the configured
> value when read.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>

>  arch/arm64/kvm/sys_regs.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 7bbe3ff..a57d650 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -134,6 +134,17 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
>  	return true;
>  }
>  
> +static bool access_gic_sre(struct kvm_vcpu *vcpu,
> +			   struct sys_reg_params *p,
> +			   const struct sys_reg_desc *r)
> +{
> +	if (p->is_write)
> +		return ignore_write(vcpu, p);
> +
> +	p->regval = vcpu->arch.vgic_cpu.vgic_v3.vgic_sre;
> +	return true;
> +}
> +
>  static bool trap_raz_wi(struct kvm_vcpu *vcpu,
>  			struct sys_reg_params *p,
>  			const struct sys_reg_desc *r)
> @@ -958,7 +969,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
>  	  access_gic_sgi },
>  	/* ICC_SRE_EL1 */
>  	{ Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b101),
> -	  trap_raz_wi },
> +	  access_gic_sre },
>  
>  	/* CONTEXTIDR_EL1 */
>  	{ Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b001),
> -- 
> 2.1.4
> 


From christoffer.dall at linaro.org  Tue May 24 05:49:31 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 14:49:31 +0200
Subject: [PATCH 6/7] arm64: KVM: vgic-v3: Prevent the guest from messing
 with ICC_SRE_EL1
In-Reply-To: <1464007023-11736-7-git-send-email-marc.zyngier@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
 <1464007023-11736-7-git-send-email-marc.zyngier@arm.com>
Message-ID: <20160524124931.GF3582@cbox>

On Mon, May 23, 2016 at 01:37:02PM +0100, Marc Zyngier wrote:
> Both our GIC emulations are "strict", in the sense that we either
> emulate a GICv2 or a GICv3, and not a GICv3 with GICv2 legacy
> support.
> 
> But when running on a GICv3 host, we still allow the guest to
> tinker with the ICC_SRE_EL1 register during its time slice:
> it can switch SRE off, observe that it is off, and yet on the
> next world switch, find the SRE bit to be set again. Not very
> nice.
> 
> An obvious solution is to always trap accesses to ICC_SRE_EL1
> (by clearing ICC_SRE_EL2.Enable), and to let the handler return
> the programmed value on a read, or ignore the write.
> 
> That way, the guest can always observe that our GICv3 is SRE==1
> only.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From linus.walleij at linaro.org  Tue May 24 05:51:56 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 24 May 2016 14:51:56 +0200
Subject: [PATCH] pinctrl: oxnas: Add GPIO get_direction
In-Reply-To: <1464084204-2271-1-git-send-email-narmstrong@baylibre.com>
References: <1464084204-2271-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <CACRpkdb1zaMk4sL3yowDMb83NAfN0SXiYwcbctEAPe-S5V7w=w@mail.gmail.com>

On Tue, May 24, 2016 at 12:03 PM, Neil Armstrong
<narmstrong at baylibre.com> wrote:

> Implement a get_direction callback for the OXNAS GPIO driver in order
> to have pin output polarity in debugfs and new userspace ABI.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>

Patch applied.

Yours,
Linus Walleij


From christoffer.dall at linaro.org  Tue May 24 05:52:33 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 14:52:33 +0200
Subject: [PATCH 7/7] arm64: KVM: vgic-v3: Relax synchronization when SRE==1
In-Reply-To: <1464007023-11736-8-git-send-email-marc.zyngier@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
 <1464007023-11736-8-git-send-email-marc.zyngier@arm.com>
Message-ID: <20160524125233.GG3582@cbox>

On Mon, May 23, 2016 at 01:37:03PM +0100, Marc Zyngier wrote:
> The GICv3 backend of the vgic is quite barrier heavy, in order
> to ensure synchronization of the system registers and the
> memory mapped view for a potential GICv2 guest.
> 
> But when the guest is using a GICv3 model, there is absolutely
> no need to execute all these heavy barriers, and it is actually
> beneficial to avoid them altogether.
> 
> This patch makes the synchonization conditional, and ensures
> that we do not change the EL1 SRE settings if we do not need to.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
>  arch/arm64/kvm/hyp/vgic-v3-sr.c | 23 ++++++++++++++++-------
>  1 file changed, 16 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c
> index 40c3b4c..5f8f80b 100644
> --- a/arch/arm64/kvm/hyp/vgic-v3-sr.c
> +++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c
> @@ -169,7 +169,8 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
>  	 * Make sure stores to the GIC via the memory mapped interface
>  	 * are now visible to the system register interface.
>  	 */
> -	dsb(st);
> +	if (!cpu_if->vgic_sre)
> +		dsb(st);
>  
>  	cpu_if->vgic_vmcr  = read_gicreg(ICH_VMCR_EL2);
>  
> @@ -235,8 +236,12 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
>  
>  	val = read_gicreg(ICC_SRE_EL2);
>  	write_gicreg(val | ICC_SRE_EL2_ENABLE, ICC_SRE_EL2);
> -	isb(); /* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
> -	write_gicreg(1, ICC_SRE_EL1);
> +
> +	if (!cpu_if->vgic_sre) {
> +		/* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
> +		isb();
> +		write_gicreg(1, ICC_SRE_EL1);

why the change in behavior to only write 1 to the register when
(!cpu_if->vgic_sre) ?

> +	}
>  }
>  
>  void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
> @@ -255,8 +260,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
>  	 * been actually programmed with the value we want before
>  	 * starting to mess with the rest of the GIC.
>  	 */
> -	write_gicreg(cpu_if->vgic_sre, ICC_SRE_EL1);
> -	isb();
> +	if (!cpu_if->vgic_sre) {
> +		write_gicreg(0, ICC_SRE_EL1);
> +		isb();
> +	}
>  
>  	val = read_gicreg(ICH_VTR_EL2);
>  	max_lr_idx = vtr_to_max_lr_idx(val);
> @@ -305,8 +312,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
>  	 * (re)distributors. This ensure the guest will read the
>  	 * correct values from the memory-mapped interface.
>  	 */
> -	isb();
> -	dsb(sy);
> +	if (!cpu_if->vgic_sre) {
> +		isb();
> +		dsb(sy);
> +	}
>  	vcpu->arch.vgic_cpu.live_lrs = live_lrs;
>  
>  	/*
> -- 
> 2.1.4
> 


From slemieux.tyco at gmail.com  Tue May 24 05:54:04 2016
From: slemieux.tyco at gmail.com (Sylvain Lemieux)
Date: Tue, 24 May 2016 08:54:04 -0400
Subject: [PATCH] gpio: lpc32xx: disable broken to_irq support
In-Reply-To: <CACRpkdZuT-NQJSQAK6RMdGUqiMTo3d31uGoXqgSS1cCyGzy5ow@mail.gmail.com>
References: <1462988400-21738-1-git-send-email-slemieux.tyco@gmail.com>
 <CACRpkdZuT-NQJSQAK6RMdGUqiMTo3d31uGoXqgSS1cCyGzy5ow@mail.gmail.com>
Message-ID: <1464094444.27117.7.camel@localhost>

Hi Linus,

On Tue, 2016-05-24 at 12:57 +0200, Linus Walleij wrote:
> On Wed, May 11, 2016 at 7:40 PM, Sylvain Lemieux
> <slemieux.tyco at gmail.com> wrote:
> 
> > From: Sylvain Lemieux <slemieux at tycoint.com>
> >
> > The "to_irq" functionality is broken inside this driver since commit
> > 76ba59f8366f ("genirq: Add irq_domain-aware core IRQ handler").
> >
> > The addition of the new lpc32xx irqchip driver in 4.7, fixed the
> > lpc32xx platform interrupt issue.
> >
> > When switching to the new lpc32xx irqchip driver, a warning appear
> > in the lpc32xx gpio driver: warning: "NR_IRQS" redefined.
> >
> > To remove this warning (temporary solution), this patch
> > disables the broken "to_irq" mapping functionality support.
> >
> > Signed-off-by: Sylvain Lemieux <slemieux at tycoint.com>
> 
> Patch applied for fixes with Vladimir's ACK.
> 
> > * The final solution is to replace the existing lpc32xx gpio driver.
> >   This work is currently in progress; refer to the following URL:
> >   http://thread.gmane.org/gmane.linux.drivers.devicetree/144696
> 
> Hm, I see that the ambition was to merge the new irqchip
> driver and the new GPIO driver in the same merge window.
> Sorry if I was being too lazy/picky/whatever about the patch(es)
> I guess I didn't quite get the scope of this change. :(
> 
The new LPC32xx GPIO driver can go in a separate merge window; 
another version of the patchset is required.

For 4.7, the goal was to remove the broken dependency in the 
existing driver.

> I should say that as long as we can agree that the new code
> makes the kernel as a whole a better place, I am happy to
> merge it. Sometimes also I need to zoom out from the GPIO
> and pin control subsystem(s) and see the big picture.
> 
> Yours,
> Linus Walleij

Sylvain Lemieux



From marc.zyngier at arm.com  Tue May 24 06:02:19 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Tue, 24 May 2016 14:02:19 +0100
Subject: [PATCH 7/7] arm64: KVM: vgic-v3: Relax synchronization when SRE==1
In-Reply-To: <20160524125233.GG3582@cbox>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
 <1464007023-11736-8-git-send-email-marc.zyngier@arm.com>
 <20160524125233.GG3582@cbox>
Message-ID: <574450DB.5010409@arm.com>

On 24/05/16 13:52, Christoffer Dall wrote:
> On Mon, May 23, 2016 at 01:37:03PM +0100, Marc Zyngier wrote:
>> The GICv3 backend of the vgic is quite barrier heavy, in order
>> to ensure synchronization of the system registers and the
>> memory mapped view for a potential GICv2 guest.
>>
>> But when the guest is using a GICv3 model, there is absolutely
>> no need to execute all these heavy barriers, and it is actually
>> beneficial to avoid them altogether.
>>
>> This patch makes the synchonization conditional, and ensures
>> that we do not change the EL1 SRE settings if we do not need to.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>> ---
>>  arch/arm64/kvm/hyp/vgic-v3-sr.c | 23 ++++++++++++++++-------
>>  1 file changed, 16 insertions(+), 7 deletions(-)
>>
>> diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c
>> index 40c3b4c..5f8f80b 100644
>> --- a/arch/arm64/kvm/hyp/vgic-v3-sr.c
>> +++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c
>> @@ -169,7 +169,8 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
>>  	 * Make sure stores to the GIC via the memory mapped interface
>>  	 * are now visible to the system register interface.
>>  	 */
>> -	dsb(st);
>> +	if (!cpu_if->vgic_sre)
>> +		dsb(st);
>>  
>>  	cpu_if->vgic_vmcr  = read_gicreg(ICH_VMCR_EL2);
>>  
>> @@ -235,8 +236,12 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
>>  
>>  	val = read_gicreg(ICC_SRE_EL2);
>>  	write_gicreg(val | ICC_SRE_EL2_ENABLE, ICC_SRE_EL2);
>> -	isb(); /* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
>> -	write_gicreg(1, ICC_SRE_EL1);
>> +
>> +	if (!cpu_if->vgic_sre) {
>> +		/* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
>> +		isb();
>> +		write_gicreg(1, ICC_SRE_EL1);
> 
> why the change in behavior to only write 1 to the register when
> (!cpu_if->vgic_sre) ?

If we're on a GICv3 host and emulating a GICv3 guest, then we never
changed the SRE mode (i.e. it is still set to 1). The only case we
change it is when we when have a GICv2 guest (i.e. when vgic_sre is zero).

So there is no need to restore the host configuration unless we actually
changed it...

> 
>> +	}
>>  }
>>  
>>  void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
>> @@ -255,8 +260,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
>>  	 * been actually programmed with the value we want before
>>  	 * starting to mess with the rest of the GIC.
>>  	 */
>> -	write_gicreg(cpu_if->vgic_sre, ICC_SRE_EL1);
>> -	isb();
>> +	if (!cpu_if->vgic_sre) {
>> +		write_gicreg(0, ICC_SRE_EL1);
>> +		isb();
>> +	}

... here.

Does it make sense? I could also split this as part of another patch if
you think that's clearer.

	M.
-- 
Jazz is not dead. It just smells funny...


From catalin.marinas at arm.com  Tue May 24 06:02:56 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 24 May 2016 14:02:56 +0100
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <574446B9.8040105@huawei.com>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
 <20160524113727.GD25374@leverpostej> <574446B9.8040105@huawei.com>
Message-ID: <20160524130255.GU4892@e104818-lin.cambridge.arm.com>

On Tue, May 24, 2016 at 08:19:05PM +0800, Leizhen (ThunderTown) wrote:
> On 2016/5/24 19:37, Mark Rutland wrote:
> > On Tue, May 24, 2016 at 07:16:37PM +0800, Zhen Lei wrote:
> >> When we ran mprotect04(a test case in LTP) infinitely, it would always
> >> failed after a few seconds. The case can be described briefly that: copy
> >> a empty function from code area into a new memory area(created by mmap),
> >> then call mprotect to change the protection to PROT_EXEC. The syscall
> >> sys_mprotect will finally invoke flush_cache_range, but this function
> >> currently only invalid icache, the operation of flush dcache is missed.
> > 
> > In the LTP code I see powerpc-specific D-cache / I-cache synchronisation
> > (i.e. d-cache cleaning followed by I-cache invalidation), so there
> > appears to be some expectation of userspace maintenance. Hoever, there
> > is no such ARM-specific I-cache maintenance.
> 
> But I see some other platforms have D-cache maintenance, like: arch/nios2/mm/cacheflush.c
> And according to the name of flush_cache_range, it should do this, I judged. Otherwise,
> mprotect04 will be failed on more platforms, it's easy to discover. Only PPC have specific
> cache synchronization, maybe it meets some hardware limitation. It's impossible a programmer
> fixed a common bug on only one platform but leave others unchanged.

flush_cache_range() is primarily used on VIVT caches before changing the
mapping and should not really be implemented on arm64. I don't recall
why we still have the I-cache invalidation, possibly for the ASID-tagged
VIVT I-cache case, though we should have a specific check for this.

There are some other cases where flush_cache_range() is called and no
D-cache maintenance is necessary on arm64, so I don't want to penalise
them by implementing flush_cache_range().

> > It looks like the test may be missing I-cache maintenance regardless of
> > the semantics of mprotect in this case.
> > 
> > I have not yet devled into flush_cache_range and how it is called.
> 
> SYSCALL_DEFINE3(mprotect ---> mprotect_fixup ---> change_protection ---> change_protection_range --> flush_cache_range

The change_protection() shouldn't need to flush the caches in
flush_cache_range(). The change_pte_range() function eventually ends up
calling set_pte_at() which calls __sync_icache_dcache() if the mapping
is executable.

Can you be more specific about the kernel version you are using, its
configuration?

-- 
Catalin


From heiko at sntech.de  Tue May 24 06:07:52 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue, 24 May 2016 15:07:52 +0200
Subject: [PATCH 2/3] soc: rockchip: add driver handling grf setup
In-Reply-To: <6a6e87ee-688d-90a3-2407-22847bd80971@rock-chips.com>
References: <1464015539-19521-1-git-send-email-heiko@sntech.de>
 <1464015539-19521-3-git-send-email-heiko@sntech.de>
 <6a6e87ee-688d-90a3-2407-22847bd80971@rock-chips.com>
Message-ID: <7631878.OiMWPcBrqd@phil>

Am Dienstag, 24. Mai 2016, 10:22:09 schrieb Shawn Lin:
> Hi Heiko,
> 
> On 2016/5/23 22:58, Heiko Stuebner wrote:
> > The General Register Files are an area of registers containing a lot
> > of single-bit settings for numerous components as well full components
> > like usbphy control. Therefore all used components are accessed
> > via the syscon provided by the grf nodes or from the sub-devices
> > created through the simple-mfd created from the grf node.
> > 
> > Some settings are not used by anything but will need to be set up
> > according to expectations on the kernel side.
> > 
> > Best example is the force_jtag setting, which defaults to on and
> > results in the soc switching the pin-outputs between jtag and sdmmc
> > automatically depending on the card-detect status. This conflicts
> > heavily with how the dw_mmc driver expects to do its work and also
> > with the clock-controller, which has most likely deactivated the
> > jtag clock due to it being unused.
> 
> I agree we should disable force_jtag for real product. But on my local
> branch we add a callback to parse a tag from cmdline. Sometime it's
> useful for debugging in case of we need to setup JTAG for reproducing
> and comfirming serious issue in which state the CPU cannot reponse to
> any console input or FIQ-debug triggering.
>
> Should we need it for upstream as you move all related code in this
> new driver?  I'm not sure.

This driver really _should not_ become a catchall for settings stuff.
I.e. the jtag/sdmmc switch handles the automatic switching done inside the 
soc based on the card-detect state. Which confuses the dw_mmc driver.

If I'm reading that correctly in the TRM, jtag on Rockchip SoCs is part of 
the coresight infrastructure - in the DAP block.
There are generic drivers + devicetree bindings for (I think most) coresight 
blocks existing now, but I haven't found anything related to the DAP itself.

In theory I'd think real handling of jtag pins/clocks should be done 
somewhere in that area and and if jtag is to be used,it could then be set up 
using in-kernel mechanics, like disabling sdmmc that claims the shared pins 
and enabling the jtag pinctrl and clocks.

This could even be doable at runtime via devicetree overlays.


Most likely way out of scope for now, but that is where I would imagine this 
stuff to be.

Heiko


From christoffer.dall at linaro.org  Tue May 24 06:18:38 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 24 May 2016 15:18:38 +0200
Subject: [PATCH 7/7] arm64: KVM: vgic-v3: Relax synchronization when SRE==1
In-Reply-To: <574450DB.5010409@arm.com>
References: <1464007023-11736-1-git-send-email-marc.zyngier@arm.com>
 <1464007023-11736-8-git-send-email-marc.zyngier@arm.com>
 <20160524125233.GG3582@cbox> <574450DB.5010409@arm.com>
Message-ID: <20160524131838.GH3582@cbox>

On Tue, May 24, 2016 at 02:02:19PM +0100, Marc Zyngier wrote:
> On 24/05/16 13:52, Christoffer Dall wrote:
> > On Mon, May 23, 2016 at 01:37:03PM +0100, Marc Zyngier wrote:
> >> The GICv3 backend of the vgic is quite barrier heavy, in order
> >> to ensure synchronization of the system registers and the
> >> memory mapped view for a potential GICv2 guest.
> >>
> >> But when the guest is using a GICv3 model, there is absolutely
> >> no need to execute all these heavy barriers, and it is actually
> >> beneficial to avoid them altogether.
> >>
> >> This patch makes the synchonization conditional, and ensures
> >> that we do not change the EL1 SRE settings if we do not need to.
> >>
> >> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> >> ---
> >>  arch/arm64/kvm/hyp/vgic-v3-sr.c | 23 ++++++++++++++++-------
> >>  1 file changed, 16 insertions(+), 7 deletions(-)
> >>
> >> diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c
> >> index 40c3b4c..5f8f80b 100644
> >> --- a/arch/arm64/kvm/hyp/vgic-v3-sr.c
> >> +++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c
> >> @@ -169,7 +169,8 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
> >>  	 * Make sure stores to the GIC via the memory mapped interface
> >>  	 * are now visible to the system register interface.
> >>  	 */
> >> -	dsb(st);
> >> +	if (!cpu_if->vgic_sre)
> >> +		dsb(st);
> >>  
> >>  	cpu_if->vgic_vmcr  = read_gicreg(ICH_VMCR_EL2);
> >>  
> >> @@ -235,8 +236,12 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
> >>  
> >>  	val = read_gicreg(ICC_SRE_EL2);
> >>  	write_gicreg(val | ICC_SRE_EL2_ENABLE, ICC_SRE_EL2);
> >> -	isb(); /* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
> >> -	write_gicreg(1, ICC_SRE_EL1);
> >> +
> >> +	if (!cpu_if->vgic_sre) {
> >> +		/* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
> >> +		isb();
> >> +		write_gicreg(1, ICC_SRE_EL1);
> > 
> > why the change in behavior to only write 1 to the register when
> > (!cpu_if->vgic_sre) ?
> 
> If we're on a GICv3 host and emulating a GICv3 guest, then we never
> changed the SRE mode (i.e. it is still set to 1). The only case we
> change it is when we when have a GICv2 guest (i.e. when vgic_sre is zero).
> 
> So there is no need to restore the host configuration unless we actually
> changed it...
> 
> > 
> >> +	}
> >>  }
> >>  
> >>  void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
> >> @@ -255,8 +260,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
> >>  	 * been actually programmed with the value we want before
> >>  	 * starting to mess with the rest of the GIC.
> >>  	 */
> >> -	write_gicreg(cpu_if->vgic_sre, ICC_SRE_EL1);
> >> -	isb();
> >> +	if (!cpu_if->vgic_sre) {
> >> +		write_gicreg(0, ICC_SRE_EL1);
> >> +		isb();
> >> +	}
> 
> ... here.
> 
> Does it make sense? I could also split this as part of another patch if
> you think that's clearer.

No makes totally sense, I just didn't see it because I'm GICed these
days.

Thanks for the explanation, and:

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>


From b.zolnierkie at samsung.com  Tue May 24 06:19:14 2016
From: b.zolnierkie at samsung.com (Bartlomiej Zolnierkiewicz)
Date: Tue, 24 May 2016 15:19:14 +0200
Subject: [PATCH 0/3] clk: samsung: add Exynos5433 CPU clocks
Message-ID: <1464095957-25851-1-git-send-email-b.zolnierkie@samsung.com>

Hi,

The following patches add a support for CPU clocks for Exynos5433.

Please note that for full cpufreq-dt support there are also DTS and
cpufreq-dt-platdev changes needed.  They will be sent separately
later.

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics


Bartlomiej Zolnierkiewicz (3):
  clk: samsung: exynos5433: prepare for adding CPU clocks
  clk: samsung: cpu: prepare for adding Exynos5433 CPU clocks
  clk: samsung: exynos5433: add CPU clocks configuration data and
    instantiate CPU clocks

 drivers/clk/samsung/clk-cpu.c        | 131 +++++++++++++++++++++++++++++-
 drivers/clk/samsung/clk-cpu.h        |   4 +-
 drivers/clk/samsung/clk-exynos5433.c | 149 +++++++++++++++++++++++++++--------
 drivers/clk/samsung/clk.c            |  12 +--
 drivers/clk/samsung/clk.h            |   4 +
 5 files changed, 258 insertions(+), 42 deletions(-)

-- 
1.9.1



From b.zolnierkie at samsung.com  Tue May 24 06:19:15 2016
From: b.zolnierkie at samsung.com (Bartlomiej Zolnierkiewicz)
Date: Tue, 24 May 2016 15:19:15 +0200
Subject: [PATCH 1/3] clk: samsung: exynos5433: prepare for adding CPU clocks
In-Reply-To: <1464095957-25851-1-git-send-email-b.zolnierkie@samsung.com>
References: <1464095957-25851-1-git-send-email-b.zolnierkie@samsung.com>
Message-ID: <1464095957-25851-2-git-send-email-b.zolnierkie@samsung.com>

Open-code samsung_cmu_register_one() calls for CMU_APOLLO and
CMU_ATLAS setup code as a preparation for adding CPU clocks
support for Exynos5433.

There should be no functional change resulting from this patch.

Cc: Kukjin Kim <kgene at kernel.org>
CC: Krzysztof Kozlowski <k.kozlowski at samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie at samsung.com>
---
 drivers/clk/samsung/clk-exynos5433.c | 85 +++++++++++++++++++++++-------------
 drivers/clk/samsung/clk.c            | 12 ++---
 drivers/clk/samsung/clk.h            |  4 ++
 3 files changed, 65 insertions(+), 36 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 128527b..6dd81ed 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -11,6 +11,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <dt-bindings/clock/exynos5433.h>
 
@@ -3594,23 +3595,35 @@ static struct samsung_gate_clock apollo_gate_clks[] __initdata = {
 			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_cmu_info apollo_cmu_info __initdata = {
-	.pll_clks		= apollo_pll_clks,
-	.nr_pll_clks		= ARRAY_SIZE(apollo_pll_clks),
-	.mux_clks		= apollo_mux_clks,
-	.nr_mux_clks		= ARRAY_SIZE(apollo_mux_clks),
-	.div_clks		= apollo_div_clks,
-	.nr_div_clks		= ARRAY_SIZE(apollo_div_clks),
-	.gate_clks		= apollo_gate_clks,
-	.nr_gate_clks		= ARRAY_SIZE(apollo_gate_clks),
-	.nr_clk_ids		= APOLLO_NR_CLK,
-	.clk_regs		= apollo_clk_regs,
-	.nr_clk_regs		= ARRAY_SIZE(apollo_clk_regs),
-};
-
 static void __init exynos5433_cmu_apollo_init(struct device_node *np)
 {
-	samsung_cmu_register_one(np, &apollo_cmu_info);
+	void __iomem *reg_base;
+	struct samsung_clk_provider *ctx;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		panic("%s: failed to map registers\n", __func__);
+		return;
+	}
+
+	ctx = samsung_clk_init(np, reg_base, APOLLO_NR_CLK);
+	if (!ctx) {
+		panic("%s: unable to allocate ctx\n", __func__);
+		return;
+	}
+
+	samsung_clk_register_pll(ctx, apollo_pll_clks,
+				 ARRAY_SIZE(apollo_pll_clks), reg_base);
+	samsung_clk_register_mux(ctx, apollo_mux_clks,
+				 ARRAY_SIZE(apollo_mux_clks));
+	samsung_clk_register_div(ctx, apollo_div_clks,
+				 ARRAY_SIZE(apollo_div_clks));
+	samsung_clk_register_gate(ctx, apollo_gate_clks,
+				  ARRAY_SIZE(apollo_gate_clks));
+	samsung_clk_sleep_init(reg_base, apollo_clk_regs,
+			       ARRAY_SIZE(apollo_clk_regs));
+
+	samsung_clk_of_add_provider(np, ctx);
 }
 CLK_OF_DECLARE(exynos5433_cmu_apollo, "samsung,exynos5433-cmu-apollo",
 		exynos5433_cmu_apollo_init);
@@ -3806,23 +3819,35 @@ static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
 			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
-static struct samsung_cmu_info atlas_cmu_info __initdata = {
-	.pll_clks		= atlas_pll_clks,
-	.nr_pll_clks		= ARRAY_SIZE(atlas_pll_clks),
-	.mux_clks		= atlas_mux_clks,
-	.nr_mux_clks		= ARRAY_SIZE(atlas_mux_clks),
-	.div_clks		= atlas_div_clks,
-	.nr_div_clks		= ARRAY_SIZE(atlas_div_clks),
-	.gate_clks		= atlas_gate_clks,
-	.nr_gate_clks		= ARRAY_SIZE(atlas_gate_clks),
-	.nr_clk_ids		= ATLAS_NR_CLK,
-	.clk_regs		= atlas_clk_regs,
-	.nr_clk_regs		= ARRAY_SIZE(atlas_clk_regs),
-};
-
 static void __init exynos5433_cmu_atlas_init(struct device_node *np)
 {
-	samsung_cmu_register_one(np, &atlas_cmu_info);
+	void __iomem *reg_base;
+	struct samsung_clk_provider *ctx;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		panic("%s: failed to map registers\n", __func__);
+		return;
+	}
+
+	ctx = samsung_clk_init(np, reg_base, ATLAS_NR_CLK);
+	if (!ctx) {
+		panic("%s: unable to allocate ctx\n", __func__);
+		return;
+	}
+
+	samsung_clk_register_pll(ctx, atlas_pll_clks,
+				 ARRAY_SIZE(atlas_pll_clks), reg_base);
+	samsung_clk_register_mux(ctx, atlas_mux_clks,
+				 ARRAY_SIZE(atlas_mux_clks));
+	samsung_clk_register_div(ctx, atlas_div_clks,
+				 ARRAY_SIZE(atlas_div_clks));
+	samsung_clk_register_gate(ctx, atlas_gate_clks,
+				  ARRAY_SIZE(atlas_gate_clks));
+	samsung_clk_sleep_init(reg_base, atlas_clk_regs,
+			       ARRAY_SIZE(atlas_clk_regs));
+
+	samsung_clk_of_add_provider(np, ctx);
 }
 CLK_OF_DECLARE(exynos5433_cmu_atlas, "samsung,exynos5433-cmu-atlas",
 		exynos5433_cmu_atlas_init);
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index f38a6c4..f20a15c 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -346,9 +346,9 @@ static struct syscore_ops samsung_clk_syscore_ops = {
 	.resume = samsung_clk_resume,
 };
 
-static void samsung_clk_sleep_init(void __iomem *reg_base,
-		const unsigned long *rdump,
-		unsigned long nr_rdump)
+void samsung_clk_sleep_init(void __iomem *reg_base,
+			const unsigned long *rdump,
+			unsigned long nr_rdump)
 {
 	struct samsung_clock_reg_cache *reg_cache;
 
@@ -370,9 +370,9 @@ static void samsung_clk_sleep_init(void __iomem *reg_base,
 }
 
 #else
-static void samsung_clk_sleep_init(void __iomem *reg_base,
-		const unsigned long *rdump,
-		unsigned long nr_rdump) {}
+void samsung_clk_sleep_init(void __iomem *reg_base,
+			const unsigned long *rdump,
+			unsigned long nr_rdump) {}
 #endif
 
 /*
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index aa872d2..ab2b101 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -399,6 +399,10 @@ extern struct samsung_clk_provider __init *samsung_cmu_register_one(
 
 extern unsigned long _get_rate(const char *clk_name);
 
+extern void samsung_clk_sleep_init(void __iomem *reg_base,
+			const unsigned long *rdump,
+			unsigned long nr_rdump);
+
 extern void samsung_clk_save(void __iomem *base,
 			struct samsung_clk_reg_dump *rd,
 			unsigned int num_regs);
-- 
1.9.1



From b.zolnierkie at samsung.com  Tue May 24 06:19:16 2016
From: b.zolnierkie at samsung.com (Bartlomiej Zolnierkiewicz)
Date: Tue, 24 May 2016 15:19:16 +0200
Subject: [PATCH 2/3] clk: samsung: cpu: prepare for adding Exynos5433 CPU
 clocks
In-Reply-To: <1464095957-25851-1-git-send-email-b.zolnierkie@samsung.com>
References: <1464095957-25851-1-git-send-email-b.zolnierkie@samsung.com>
Message-ID: <1464095957-25851-3-git-send-email-b.zolnierkie@samsung.com>

Exynos5433 uses different register layout for CPU clock registers
than earlier SoCs so add new code for handling this layout.  Also
add new CLK_CPU_HAS_E5433_REGS_LAYOUT flag to request using it.

There should be no functional change resulting from this patch.

Cc: Kukjin Kim <kgene at kernel.org>
CC: Krzysztof Kozlowski <k.kozlowski at samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie at samsung.com>
---
 drivers/clk/samsung/clk-cpu.c | 131 +++++++++++++++++++++++++++++++++++++++++-
 drivers/clk/samsung/clk-cpu.h |   4 +-
 2 files changed, 133 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c
index 813003d..8bf7e80 100644
--- a/drivers/clk/samsung/clk-cpu.c
+++ b/drivers/clk/samsung/clk-cpu.c
@@ -45,6 +45,13 @@
 #define E4210_DIV_STAT_CPU0	0x400
 #define E4210_DIV_STAT_CPU1	0x404
 
+#define E5433_MUX_SEL2		0x008
+#define E5433_MUX_STAT2		0x208
+#define E5433_DIV_CPU0		0x400
+#define E5433_DIV_CPU1		0x404
+#define E5433_DIV_STAT_CPU0	0x500
+#define E5433_DIV_STAT_CPU1	0x504
+
 #define E4210_DIV0_RATIO0_MASK	0x7
 #define E4210_DIV1_HPM_MASK	(0x7 << 4)
 #define E4210_DIV1_COPY_MASK	(0x7 << 0)
@@ -253,6 +260,102 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
 }
 
 /*
+ * Helper function to set the 'safe' dividers for the CPU clock. The parameters
+ * div and mask contain the divider value and the register bit mask of the
+ * dividers to be programmed.
+ */
+static void exynos5433_set_safe_div(void __iomem *base, unsigned long div,
+					unsigned long mask)
+{
+	unsigned long div0;
+
+	div0 = readl(base + E5433_DIV_CPU0);
+	div0 = (div0 & ~mask) | (div & mask);
+	writel(div0, base + E5433_DIV_CPU0);
+	wait_until_divider_stable(base + E5433_DIV_STAT_CPU0, mask);
+}
+
+/* handler for pre-rate change notification from parent clock */
+static int exynos5433_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
+			struct exynos_cpuclk *cpuclk, void __iomem *base)
+{
+	const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg;
+	unsigned long alt_prate = clk_get_rate(cpuclk->alt_parent);
+	unsigned long alt_div = 0, alt_div_mask = DIV_MASK;
+	unsigned long div0, div1 = 0, mux_reg;
+	unsigned long flags;
+
+	/* find out the divider values to use for clock data */
+	while ((cfg_data->prate * 1000) != ndata->new_rate) {
+		if (cfg_data->prate == 0)
+			return -EINVAL;
+		cfg_data++;
+	}
+
+	spin_lock_irqsave(cpuclk->lock, flags);
+
+	/*
+	 * For the selected PLL clock frequency, get the pre-defined divider
+	 * values.
+	 */
+	div0 = cfg_data->div0;
+	div1 = cfg_data->div1;
+
+	/*
+	 * If the old parent clock speed is less than the clock speed of
+	 * the alternate parent, then it should be ensured that at no point
+	 * the armclk speed is more than the old_prate until the dividers are
+	 * set.  Also workaround the issue of the dividers being set to lower
+	 * values before the parent clock speed is set to new lower speed
+	 * (this can result in too high speed of armclk output clocks).
+	 */
+	if (alt_prate > ndata->old_rate || ndata->old_rate > ndata->new_rate) {
+		unsigned long tmp_rate = min(ndata->old_rate, ndata->new_rate);
+
+		alt_div = DIV_ROUND_UP(alt_prate, tmp_rate) - 1;
+		WARN_ON(alt_div >= MAX_DIV);
+
+		exynos5433_set_safe_div(base, alt_div, alt_div_mask);
+		div0 |= alt_div;
+	}
+
+	/* select the alternate parent */
+	mux_reg = readl(base + E5433_MUX_SEL2);
+	writel(mux_reg | 1, base + E5433_MUX_SEL2);
+	wait_until_mux_stable(base + E5433_MUX_STAT2, 0, 2);
+
+	/* alternate parent is active now. set the dividers */
+	writel(div0, base + E5433_DIV_CPU0);
+	wait_until_divider_stable(base + E5433_DIV_STAT_CPU0, DIV_MASK_ALL);
+
+	writel(div1, base + E5433_DIV_CPU1);
+	wait_until_divider_stable(base + E5433_DIV_STAT_CPU1, DIV_MASK_ALL);
+
+	spin_unlock_irqrestore(cpuclk->lock, flags);
+	return 0;
+}
+
+/* handler for post-rate change notification from parent clock */
+static int exynos5433_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
+			struct exynos_cpuclk *cpuclk, void __iomem *base)
+{
+	unsigned long div = 0, div_mask = DIV_MASK;
+	unsigned long mux_reg;
+	unsigned long flags;
+
+	spin_lock_irqsave(cpuclk->lock, flags);
+
+	/* select apll as the alternate parent */
+	mux_reg = readl(base + E5433_MUX_SEL2);
+	writel(mux_reg & ~1, base + E5433_MUX_SEL2);
+	wait_until_mux_stable(base + E5433_MUX_STAT2, 0, 1);
+
+	exynos5433_set_safe_div(base, div, div_mask);
+	spin_unlock_irqrestore(cpuclk->lock, flags);
+	return 0;
+}
+
+/*
  * This notifier function is called for the pre-rate and post-rate change
  * notifications of the parent clock of cpuclk.
  */
@@ -275,6 +378,29 @@ static int exynos_cpuclk_notifier_cb(struct notifier_block *nb,
 	return notifier_from_errno(err);
 }
 
+/*
+ * This notifier function is called for the pre-rate and post-rate change
+ * notifications of the parent clock of cpuclk.
+ */
+static int exynos5433_cpuclk_notifier_cb(struct notifier_block *nb,
+				unsigned long event, void *data)
+{
+	struct clk_notifier_data *ndata = data;
+	struct exynos_cpuclk *cpuclk;
+	void __iomem *base;
+	int err = 0;
+
+	cpuclk = container_of(nb, struct exynos_cpuclk, clk_nb);
+	base = cpuclk->ctrl_base;
+
+	if (event == PRE_RATE_CHANGE)
+		err = exynos5433_cpuclk_pre_rate_change(ndata, cpuclk, base);
+	else if (event == POST_RATE_CHANGE)
+		err = exynos5433_cpuclk_post_rate_change(ndata, cpuclk, base);
+
+	return notifier_from_errno(err);
+}
+
 /* helper function to register a CPU clock */
 int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
 		unsigned int lookup_id, const char *name, const char *parent,
@@ -301,7 +427,10 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
 	cpuclk->ctrl_base = ctx->reg_base + offset;
 	cpuclk->lock = &ctx->lock;
 	cpuclk->flags = flags;
-	cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb;
+	if (flags & CLK_CPU_HAS_E5433_REGS_LAYOUT)
+		cpuclk->clk_nb.notifier_call = exynos5433_cpuclk_notifier_cb;
+	else
+		cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb;
 
 	cpuclk->alt_parent = __clk_lookup(alt_parent);
 	if (!cpuclk->alt_parent) {
diff --git a/drivers/clk/samsung/clk-cpu.h b/drivers/clk/samsung/clk-cpu.h
index 37874d3..d4b6b51 100644
--- a/drivers/clk/samsung/clk-cpu.h
+++ b/drivers/clk/samsung/clk-cpu.h
@@ -57,10 +57,12 @@ struct exynos_cpuclk {
 	struct notifier_block			clk_nb;
 	unsigned long				flags;
 
-/* The CPU clock registers has DIV1 configuration register */
+/* The CPU clock registers have DIV1 configuration register */
 #define CLK_CPU_HAS_DIV1		(1 << 0)
 /* When ALT parent is active, debug clocks need safe divider values */
 #define CLK_CPU_NEEDS_DEBUG_ALT_DIV	(1 << 1)
+/* The CPU clock registers have Exynos5433-compatible layout */
+#define CLK_CPU_HAS_E5433_REGS_LAYOUT	(1 << 2)
 };
 
 extern int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
-- 
1.9.1



From b.zolnierkie at samsung.com  Tue May 24 06:19:17 2016
From: b.zolnierkie at samsung.com (Bartlomiej Zolnierkiewicz)
Date: Tue, 24 May 2016 15:19:17 +0200
Subject: [PATCH 3/3] clk: samsung: exynos5433: add CPU clocks configuration
 data and instantiate CPU clocks
In-Reply-To: <1464095957-25851-1-git-send-email-b.zolnierkie@samsung.com>
References: <1464095957-25851-1-git-send-email-b.zolnierkie@samsung.com>
Message-ID: <1464095957-25851-4-git-send-email-b.zolnierkie@samsung.com>

Add the CPU clocks configuration data and instantiate the CPU clocks
type for Exynos5433.

Cc: Kukjin Kim <kgene at kernel.org>
CC: Krzysztof Kozlowski <k.kozlowski at samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie at samsung.com>
---
 drivers/clk/samsung/clk-exynos5433.c | 72 ++++++++++++++++++++++++++++++++----
 1 file changed, 64 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 6dd81ed..9ff6160 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -16,6 +16,7 @@
 #include <dt-bindings/clock/exynos5433.h>
 
 #include "clk.h"
+#include "clk-cpu.h"
 #include "clk-pll.h"
 
 /*
@@ -3509,7 +3510,8 @@ static struct samsung_pll_clock apollo_pll_clks[] __initdata = {
 static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
 	/* MUX_SEL_APOLLO0 */
 	MUX_F(CLK_MOUT_APOLLO_PLL, "mout_apollo_pll", mout_apollo_pll_p,
-			MUX_SEL_APOLLO0, 0, 1, CLK_SET_RATE_PARENT, 0),
+			MUX_SEL_APOLLO0, 0, 1, CLK_SET_RATE_PARENT |
+			CLK_RECALC_NEW_RATES, 0),
 
 	/* MUX_SEL_APOLLO1 */
 	MUX(CLK_MOUT_BUS_PLL_APOLLO_USER, "mout_bus_pll_apollo_user",
@@ -3590,9 +3592,27 @@ static struct samsung_gate_clock apollo_gate_clks[] __initdata = {
 			ENABLE_SCLK_APOLLO, 3, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_SCLK_HPM_APOLLO, "sclk_hpm_apollo", "div_sclk_hpm_apollo",
 			ENABLE_SCLK_APOLLO, 1, CLK_IGNORE_UNUSED, 0),
-	GATE(CLK_SCLK_APOLLO, "sclk_apollo", "div_apollo2",
-			ENABLE_SCLK_APOLLO, 0,
-			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+};
+
+#define E5433_APOLLO_DIV0(cntclk, pclk_dbg, atclk, pclk, aclk) \
+		(((cntclk) << 24) | ((pclk_dbg) << 20) | ((atclk) << 16) | \
+		 ((pclk) << 12) | ((aclk) << 8))
+
+#define E5433_APOLLO_DIV1(hpm, copy) \
+		(((hpm) << 4) | ((copy) << 0))
+
+static const struct exynos_cpuclk_cfg_data exynos5433_apolloclk_d[] __initconst = {
+	{ 1300000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+	{ 1200000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+	{ 1100000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+	{ 1000000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+	{  900000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+	{  800000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+	{  700000, E5433_APOLLO_DIV0(3, 7, 7, 7, 2), E5433_APOLLO_DIV1(7, 1), },
+	{  600000, E5433_APOLLO_DIV0(3, 7, 7, 7, 1), E5433_APOLLO_DIV1(7, 1), },
+	{  500000, E5433_APOLLO_DIV0(3, 7, 7, 7, 1), E5433_APOLLO_DIV1(7, 1), },
+	{  400000, E5433_APOLLO_DIV0(3, 7, 7, 7, 1), E5433_APOLLO_DIV1(7, 1), },
+	{  0 },
 };
 
 static void __init exynos5433_cmu_apollo_init(struct device_node *np)
@@ -3620,6 +3640,12 @@ static void __init exynos5433_cmu_apollo_init(struct device_node *np)
 				 ARRAY_SIZE(apollo_div_clks));
 	samsung_clk_register_gate(ctx, apollo_gate_clks,
 				  ARRAY_SIZE(apollo_gate_clks));
+
+	exynos_register_cpu_clock(ctx, CLK_SCLK_APOLLO, "apolloclk",
+		mout_apollo_p[0], mout_apollo_p[1], 0x200,
+		exynos5433_apolloclk_d, ARRAY_SIZE(exynos5433_apolloclk_d),
+		CLK_CPU_HAS_E5433_REGS_LAYOUT);
+
 	samsung_clk_sleep_init(reg_base, apollo_clk_regs,
 			       ARRAY_SIZE(apollo_clk_regs));
 
@@ -3707,7 +3733,8 @@ static struct samsung_pll_clock atlas_pll_clks[] __initdata = {
 static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
 	/* MUX_SEL_ATLAS0 */
 	MUX_F(CLK_MOUT_ATLAS_PLL, "mout_atlas_pll", mout_atlas_pll_p,
-			MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT, 0),
+			MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT |
+			CLK_RECALC_NEW_RATES, 0),
 
 	/* MUX_SEL_ATLAS1 */
 	MUX(CLK_MOUT_BUS_PLL_ATLAS_USER, "mout_bus_pll_atlas_user",
@@ -3814,9 +3841,32 @@ static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
 			ENABLE_SCLK_ATLAS, 2, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ATCLK, "atclk", "div_atclk_atlas",
 			ENABLE_SCLK_ATLAS, 1, CLK_IGNORE_UNUSED, 0),
-	GATE(CLK_SCLK_ATLAS, "sclk_atlas", "div_atlas2",
-			ENABLE_SCLK_ATLAS, 0,
-			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+};
+
+#define E5433_ATLAS_DIV0(cntclk, pclk_dbg, atclk, pclk, aclk) \
+		(((cntclk) << 24) | ((pclk_dbg) << 20) | ((atclk) << 16) | \
+		 ((pclk) << 12) | ((aclk) << 8))
+
+#define E5433_ATLAS_DIV1(hpm, copy) \
+		(((hpm) << 4) | ((copy) << 0))
+
+static const struct exynos_cpuclk_cfg_data exynos5433_atlasclk_d[] __initconst = {
+	{ 1900000, E5433_ATLAS_DIV0(7, 7, 7, 7, 4), E5433_ATLAS_DIV1(7, 1), },
+	{ 1800000, E5433_ATLAS_DIV0(7, 7, 7, 7, 4), E5433_ATLAS_DIV1(7, 1), },
+	{ 1700000, E5433_ATLAS_DIV0(7, 7, 7, 7, 4), E5433_ATLAS_DIV1(7, 1), },
+	{ 1600000, E5433_ATLAS_DIV0(7, 7, 7, 7, 4), E5433_ATLAS_DIV1(7, 1), },
+	{ 1500000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), },
+	{ 1400000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), },
+	{ 1300000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), },
+	{ 1200000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), },
+	{ 1100000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), },
+	{ 1000000, E5433_ATLAS_DIV0(7, 7, 7, 7, 3), E5433_ATLAS_DIV1(7, 1), },
+	{  900000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), },
+	{  800000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), },
+	{  700000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), },
+	{  600000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), },
+	{  500000, E5433_ATLAS_DIV0(7, 7, 7, 7, 2), E5433_ATLAS_DIV1(7, 1), },
+	{  0 },
 };
 
 static void __init exynos5433_cmu_atlas_init(struct device_node *np)
@@ -3844,6 +3894,12 @@ static void __init exynos5433_cmu_atlas_init(struct device_node *np)
 				 ARRAY_SIZE(atlas_div_clks));
 	samsung_clk_register_gate(ctx, atlas_gate_clks,
 				  ARRAY_SIZE(atlas_gate_clks));
+
+	exynos_register_cpu_clock(ctx, CLK_SCLK_ATLAS, "atlasclk",
+		mout_atlas_p[0], mout_atlas_p[1], 0x200,
+		exynos5433_atlasclk_d, ARRAY_SIZE(exynos5433_atlasclk_d),
+		CLK_CPU_HAS_E5433_REGS_LAYOUT);
+
 	samsung_clk_sleep_init(reg_base, atlas_clk_regs,
 			       ARRAY_SIZE(atlas_clk_regs));
 
-- 
1.9.1



From k.kozlowski at samsung.com  Tue May 24 06:28:12 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 24 May 2016 15:28:12 +0200
Subject: [PATCH 1/2] drm/exynos: g2d: Add support for old S5Pv210 type
Message-ID: <1464096493-13378-1-git-send-email-k.kozlowski@samsung.com>

The non-DRM s5p-g2d driver supports two versions of G2D: v3.0 on
S5Pv210 and v4.x on Exynos 4x12 (or newer). The driver for 3.0 device
version is doing two things differently:
1. Before starting the render process, it invalidates caches (pattern,
   source buffer and mask buffer). Cache control is not present on v4.x
   device.
2. Scalling is done through StretchEn command (in BITBLT_COMMAND_REG
   register) instead of SRC_SCALE_CTRL_REG as in v4.x. However the
   exynos_drm_g2d driver does not implement the scalling so this
   difference can be eliminated.

After adding support for v3.0 to exynos_drm_g2d driver, the old driver
can be removed.

Cc: Kyungmin Park <kyungmin.park at samsung.com>
Cc: Kamil Debski <k.debski at samsung.com>
Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_g2d.c | 37 +++++++++++++++++++++++++++++++--
 drivers/gpu/drm/exynos/exynos_drm_g2d.h |  7 +++++++
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 493552368295..44d8b28e9d98 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -19,6 +19,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/dma-attrs.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <drm/drmP.h>
 #include <drm/exynos_drm.h>
@@ -38,6 +39,7 @@
 #define G2D_SOFT_RESET			0x0000
 #define G2D_INTEN			0x0004
 #define G2D_INTC_PEND			0x000C
+#define G2D_CACHECTL			0x0018 /* S5PV210 specific */
 #define G2D_DMA_SFR_BASE_ADDR		0x0080
 #define G2D_DMA_COMMAND			0x0084
 #define G2D_DMA_STATUS			0x008C
@@ -78,6 +80,11 @@
 #define G2D_INTP_GCMD_FIN		(1 << 1)
 #define G2D_INTP_SCMD_FIN		(1 << 0)
 
+/* G2D_CACHECTL, S5PV210 specific */
+#define G2D_CACHECTL_PATCACHE		(BIT(2))
+#define G2D_CACHECTL_SRCBUFFER		(BIT(1))
+#define G2D_CACHECTL_MASKBUFFER		(BIT(0))
+
 /* G2D_DMA_COMMAND */
 #define G2D_DMA_HALT			(1 << 2)
 #define G2D_DMA_CONTINUE		(1 << 1)
@@ -245,6 +252,7 @@ struct g2d_data {
 
 	unsigned long			current_pool;
 	unsigned long			max_pool;
+	enum exynos_drm_g2d_type	type;
 };
 
 static int g2d_init_cmdlist(struct g2d_data *g2d)
@@ -1125,6 +1133,13 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
 	cmdlist->data[cmdlist->last++] = G2D_SRC_BASE_ADDR;
 	cmdlist->data[cmdlist->last++] = 0;
 
+	if (g2d->type == EXYNOS_DRM_G2D_TYPE_3X) {
+		cmdlist->data[cmdlist->last++] = G2D_CACHECTL;
+		cmdlist->data[cmdlist->last++] = G2D_CACHECTL_PATCACHE |
+						 G2D_CACHECTL_SRCBUFFER |
+						 G2D_CACHECTL_MASKBUFFER;
+	}
+
 	/*
 	 * 'LIST_HOLD' command should be set to the DMA_HOLD_CMD_REG
 	 * and GCF bit should be set to INTEN register if user wants
@@ -1369,10 +1384,20 @@ static int g2d_probe(struct platform_device *pdev)
 	struct exynos_drm_subdrv *subdrv;
 	int ret;
 
+	/* Sanity check, we can be instatiated only from DT */
+	if (!dev->of_node)
+		return -EINVAL;
+
 	g2d = devm_kzalloc(dev, sizeof(*g2d), GFP_KERNEL);
 	if (!g2d)
 		return -ENOMEM;
 
+	g2d->type = (enum exynos_drm_g2d_type)of_device_get_match_data(dev);
+	if (g2d->type == EXYNOS_DRM_G2D_TYPE_UNKNOWN) {
+		dev_err(dev, "failed to get type of device\n");
+		return -EINVAL;
+	}
+
 	g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab",
 			sizeof(struct g2d_runqueue_node), 0, 0, NULL);
 	if (!g2d->runqueue_slab)
@@ -1535,8 +1560,16 @@ static const struct dev_pm_ops g2d_pm_ops = {
 };
 
 static const struct of_device_id exynos_g2d_match[] = {
-	{ .compatible = "samsung,exynos5250-g2d" },
-	{ .compatible = "samsung,exynos4212-g2d" },
+	{
+		.compatible = "samsung,exynos5250-g2d",
+		.data = (void *)EXYNOS_DRM_G2D_TYPE_4X,
+	}, {
+		.compatible = "samsung,exynos4212-g2d",
+		.data = (void *)EXYNOS_DRM_G2D_TYPE_4X,
+	}, {
+		.compatible = "samsung,s5pv210-g2d",
+		.data = (void *)EXYNOS_DRM_G2D_TYPE_3X,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, exynos_g2d_match);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.h b/drivers/gpu/drm/exynos/exynos_drm_g2d.h
index 1a9c7ca8c15b..84ec8aff6f0a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.h
@@ -7,6 +7,13 @@
  * published by the Free Software Foundationr
  */
 
+enum exynos_drm_g2d_type {
+	EXYNOS_DRM_G2D_TYPE_UNKNOWN,
+
+	EXYNOS_DRM_G2D_TYPE_3X,
+	EXYNOS_DRM_G2D_TYPE_4X,
+};
+
 #ifdef CONFIG_DRM_EXYNOS_G2D
 extern int exynos_g2d_get_ver_ioctl(struct drm_device *dev, void *data,
 				    struct drm_file *file_priv);
-- 
1.9.1



From k.kozlowski at samsung.com  Tue May 24 06:28:13 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 24 May 2016 15:28:13 +0200
Subject: [PATCH 2/2] [media] s5p-g2d: Replace old driver with DRM version
In-Reply-To: <1464096493-13378-1-git-send-email-k.kozlowski@samsung.com>
References: <1464096493-13378-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1464096493-13378-2-git-send-email-k.kozlowski@samsung.com>

Remove the old non-DRM driver because it is now entirely supported by
exynos_drm_g2d driver.

Cc: Kyungmin Park <kyungmin.park at samsung.com>
Cc: Kamil Debski <k.debski at samsung.com>
Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 MAINTAINERS                               |   8 -
 drivers/gpu/drm/exynos/Kconfig            |   1 -
 drivers/media/platform/Kconfig            |  12 -
 drivers/media/platform/Makefile           |   1 -
 drivers/media/platform/s5p-g2d/Makefile   |   3 -
 drivers/media/platform/s5p-g2d/g2d-hw.c   | 117 -----
 drivers/media/platform/s5p-g2d/g2d-regs.h | 122 -----
 drivers/media/platform/s5p-g2d/g2d.c      | 800 ------------------------------
 drivers/media/platform/s5p-g2d/g2d.h      |  91 ----
 9 files changed, 1155 deletions(-)
 delete mode 100644 drivers/media/platform/s5p-g2d/Makefile
 delete mode 100644 drivers/media/platform/s5p-g2d/g2d-hw.c
 delete mode 100644 drivers/media/platform/s5p-g2d/g2d-regs.h
 delete mode 100644 drivers/media/platform/s5p-g2d/g2d.c
 delete mode 100644 drivers/media/platform/s5p-g2d/g2d.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 243c0811a4d8..01763419c6a1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1616,14 +1616,6 @@ L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-s5pv210/
 
-ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT
-M:	Kyungmin Park <kyungmin.park at samsung.com>
-M:	Kamil Debski <k.debski at samsung.com>
-L:	linux-arm-kernel at lists.infradead.org
-L:	linux-media at vger.kernel.org
-S:	Maintained
-F:	drivers/media/platform/s5p-g2d/
-
 ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
 M:	Kyungmin Park <kyungmin.park at samsung.com>
 M:	Kamil Debski <k.debski at samsung.com>
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index d814b3048ee5..b0eb20ba1b28 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -95,7 +95,6 @@ comment "Sub-drivers"
 
 config DRM_EXYNOS_G2D
 	bool "G2D"
-	depends on VIDEO_SAMSUNG_S5P_G2D=n
 	select FRAME_VECTOR
 	help
 	  Choose this option if you want to use Exynos G2D for DRM.
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 84e041c0a70e..171005c53d62 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -161,18 +161,6 @@ config VIDEO_MEM2MEM_DEINTERLACE
 	help
 	    Generic deinterlacing V4L2 driver.
 
-config VIDEO_SAMSUNG_S5P_G2D
-	tristate "Samsung S5P and EXYNOS4 G2D 2d graphics accelerator driver"
-	depends on VIDEO_DEV && VIDEO_V4L2
-	depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
-	depends on HAS_DMA
-	select VIDEOBUF2_DMA_CONTIG
-	select V4L2_MEM2MEM_DEV
-	default n
-	---help---
-	  This is a v4l2 driver for Samsung S5P and EXYNOS4 G2D
-	  2d graphics accelerator.
-
 config VIDEO_SAMSUNG_S5P_JPEG
 	tristate "Samsung S5P/Exynos3250/Exynos4 JPEG codec driver"
 	depends on VIDEO_DEV && VIDEO_V4L2
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index bbb7bd1eb268..ad5e26a0bd17 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -32,7 +32,6 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG)	+= s5p-jpeg/
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC)	+= s5p-mfc/
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV)	+= s5p-tv/
 
-obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D)	+= s5p-g2d/
 obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC)	+= exynos-gsc/
 
 obj-$(CONFIG_VIDEO_STI_BDISP)		+= sti/bdisp/
diff --git a/drivers/media/platform/s5p-g2d/Makefile b/drivers/media/platform/s5p-g2d/Makefile
deleted file mode 100644
index 2c48c416a804..000000000000
--- a/drivers/media/platform/s5p-g2d/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-s5p-g2d-objs := g2d.o g2d-hw.o
-
-obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D)	+= s5p-g2d.o
diff --git a/drivers/media/platform/s5p-g2d/g2d-hw.c b/drivers/media/platform/s5p-g2d/g2d-hw.c
deleted file mode 100644
index e87bd93811d4..000000000000
--- a/drivers/media/platform/s5p-g2d/g2d-hw.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Samsung S5P G2D - 2D Graphics Accelerator Driver
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Kamil Debski, <k.debski at samsung.com>
- *
- * 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
- */
-
-#include <linux/io.h>
-
-#include "g2d.h"
-#include "g2d-regs.h"
-
-#define w(x, a)	writel((x), d->regs + (a))
-#define r(a)	readl(d->regs + (a))
-
-/* g2d_reset clears all g2d registers */
-void g2d_reset(struct g2d_dev *d)
-{
-	w(1, SOFT_RESET_REG);
-}
-
-void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f)
-{
-	u32 n;
-
-	w(0, SRC_SELECT_REG);
-	w(f->stride & 0xFFFF, SRC_STRIDE_REG);
-
-	n = f->o_height & 0xFFF;
-	n <<= 16;
-	n |= f->o_width & 0xFFF;
-	w(n, SRC_LEFT_TOP_REG);
-
-	n = f->bottom & 0xFFF;
-	n <<= 16;
-	n |= f->right & 0xFFF;
-	w(n, SRC_RIGHT_BOTTOM_REG);
-
-	w(f->fmt->hw, SRC_COLOR_MODE_REG);
-}
-
-void g2d_set_src_addr(struct g2d_dev *d, dma_addr_t a)
-{
-	w(a, SRC_BASE_ADDR_REG);
-}
-
-void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f)
-{
-	u32 n;
-
-	w(0, DST_SELECT_REG);
-	w(f->stride & 0xFFFF, DST_STRIDE_REG);
-
-	n = f->o_height & 0xFFF;
-	n <<= 16;
-	n |= f->o_width & 0xFFF;
-	w(n, DST_LEFT_TOP_REG);
-
-	n = f->bottom & 0xFFF;
-	n <<= 16;
-	n |= f->right & 0xFFF;
-	w(n, DST_RIGHT_BOTTOM_REG);
-
-	w(f->fmt->hw, DST_COLOR_MODE_REG);
-}
-
-void g2d_set_dst_addr(struct g2d_dev *d, dma_addr_t a)
-{
-	w(a, DST_BASE_ADDR_REG);
-}
-
-void g2d_set_rop4(struct g2d_dev *d, u32 r)
-{
-	w(r, ROP4_REG);
-}
-
-void g2d_set_flip(struct g2d_dev *d, u32 r)
-{
-	w(r, SRC_MSK_DIRECT_REG);
-}
-
-void g2d_set_v41_stretch(struct g2d_dev *d, struct g2d_frame *src,
-					struct g2d_frame *dst)
-{
-	w(DEFAULT_SCALE_MODE, SRC_SCALE_CTRL_REG);
-
-	/* inversed scaling factor: src is numerator */
-	w((src->c_width << 16) / dst->c_width, SRC_XSCALE_REG);
-	w((src->c_height << 16) / dst->c_height, SRC_YSCALE_REG);
-}
-
-void g2d_set_cmd(struct g2d_dev *d, u32 c)
-{
-	w(c, BITBLT_COMMAND_REG);
-}
-
-void g2d_start(struct g2d_dev *d)
-{
-	/* Clear cache */
-	if (d->variant->hw_rev == TYPE_G2D_3X)
-		w(0x7, CACHECTL_REG);
-
-	/* Enable interrupt */
-	w(1, INTEN_REG);
-	/* Start G2D engine */
-	w(1, BITBLT_START_REG);
-}
-
-void g2d_clear_int(struct g2d_dev *d)
-{
-	w(1, INTC_PEND_REG);
-}
diff --git a/drivers/media/platform/s5p-g2d/g2d-regs.h b/drivers/media/platform/s5p-g2d/g2d-regs.h
deleted file mode 100644
index 9bf31ad35d47..000000000000
--- a/drivers/media/platform/s5p-g2d/g2d-regs.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Samsung S5P G2D - 2D Graphics Accelerator Driver
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Kamil Debski, <k.debski at samsung.com>
- *
- * 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
- */
-
-/* General Registers */
-#define SOFT_RESET_REG		0x0000	/* Software reset reg */
-#define INTEN_REG		0x0004	/* Interrupt Enable reg */
-#define INTC_PEND_REG		0x000C	/* Interrupt Control Pending reg */
-#define FIFO_STAT_REG		0x0010	/* Command FIFO Status reg */
-#define AXI_ID_MODE_REG		0x0014	/* AXI Read ID Mode reg */
-#define CACHECTL_REG		0x0018	/* Cache & Buffer clear reg */
-#define AXI_MODE_REG		0x001C	/* AXI Mode reg */
-
-/* Command Registers */
-#define BITBLT_START_REG	0x0100	/* BitBLT Start reg */
-#define BITBLT_COMMAND_REG	0x0104	/* Command reg for BitBLT */
-
-/* Parameter Setting Registers (Rotate & Direction) */
-#define ROTATE_REG		0x0200	/* Rotation reg */
-#define SRC_MSK_DIRECT_REG	0x0204	/* Src and Mask Direction reg */
-#define DST_PAT_DIRECT_REG	0x0208	/* Dest and Pattern Direction reg */
-
-/* Parameter Setting Registers (Src) */
-#define SRC_SELECT_REG		0x0300	/* Src Image Selection reg */
-#define SRC_BASE_ADDR_REG	0x0304	/* Src Image Base Address reg */
-#define SRC_STRIDE_REG		0x0308	/* Src Stride reg */
-#define SRC_COLOR_MODE_REG	0x030C	/* Src Image Color Mode reg */
-#define SRC_LEFT_TOP_REG	0x0310	/* Src Left Top Coordinate reg */
-#define SRC_RIGHT_BOTTOM_REG	0x0314	/* Src Right Bottom Coordinate reg */
-#define SRC_SCALE_CTRL_REG	0x0328	/* Src Scaling type select */
-#define SRC_XSCALE_REG		0x032c	/* Src X Scaling ratio */
-#define SRC_YSCALE_REG		0x0330	/* Src Y Scaling ratio */
-
-/* Parameter Setting Registers (Dest) */
-#define DST_SELECT_REG		0x0400	/* Dest Image Selection reg */
-#define DST_BASE_ADDR_REG	0x0404	/* Dest Image Base Address reg */
-#define DST_STRIDE_REG		0x0408	/* Dest Stride reg */
-#define DST_COLOR_MODE_REG	0x040C	/* Dest Image Color Mode reg */
-#define DST_LEFT_TOP_REG	0x0410	/* Dest Left Top Coordinate reg */
-#define DST_RIGHT_BOTTOM_REG	0x0414	/* Dest Right Bottom Coordinate reg */
-
-/* Parameter Setting Registers (Pattern) */
-#define PAT_BASE_ADDR_REG	0x0500	/* Pattern Image Base Address reg */
-#define PAT_SIZE_REG		0x0504	/* Pattern Image Size reg */
-#define PAT_COLOR_MODE_REG	0x0508	/* Pattern Image Color Mode reg */
-#define PAT_OFFSET_REG		0x050C	/* Pattern Left Top Coordinate reg */
-#define PAT_STRIDE_REG		0x0510	/* Pattern Stride reg */
-
-/* Parameter Setting Registers (Mask) */
-#define MASK_BASE_ADDR_REG	0x0520	/* Mask Base Address reg */
-#define MASK_STRIDE_REG		0x0524	/* Mask Stride reg */
-
-/* Parameter Setting Registers (Clipping Window) */
-#define CW_LT_REG		0x0600	/* LeftTop coordinates of Clip Window */
-#define CW_RB_REG		0x0604	/* RightBottom coordinates of Clip
-								Window */
-
-/* Parameter Setting Registers (ROP & Alpha Setting) */
-#define THIRD_OPERAND_REG	0x0610	/* Third Operand Selection reg */
-#define ROP4_REG		0x0614	/* Raster Operation reg */
-#define ALPHA_REG		0x0618	/* Alpha value, Fading offset value */
-
-/* Parameter Setting Registers (Color) */
-#define FG_COLOR_REG		0x0700	/* Foreground Color reg */
-#define BG_COLOR_REG		0x0704	/* Background Color reg */
-#define BS_COLOR_REG		0x0708	/* Blue Screen Color reg */
-
-/* Parameter Setting Registers (Color Key) */
-#define SRC_COLORKEY_CTRL_REG	0x0710	/* Src Colorkey control reg */
-#define SRC_COLORKEY_DR_MIN_REG	0x0714	/* Src Colorkey Decision Reference
-								Min reg */
-#define SRC_COLORKEY_DR_MAX_REG	0x0718	/* Src Colorkey Decision Reference
-								Max reg */
-#define DST_COLORKEY_CTRL_REG	0x071C	/* Dest Colorkey control reg */
-#define DST_COLORKEY_DR_MIN_REG	0x0720	/* Dest Colorkey Decision Reference
-								Min reg */
-#define DST_COLORKEY_DR_MAX_REG	0x0724	/* Dest Colorkey Decision Reference
-								Max reg */
-
-/* Color mode values */
-
-#define ORDER_XRGB		0
-#define ORDER_RGBX		1
-#define ORDER_XBGR		2
-#define ORDER_BGRX		3
-
-#define MODE_XRGB_8888		0
-#define MODE_ARGB_8888		1
-#define MODE_RGB_565		2
-#define MODE_XRGB_1555		3
-#define MODE_ARGB_1555		4
-#define MODE_XRGB_4444		5
-#define MODE_ARGB_4444		6
-#define MODE_PACKED_RGB_888	7
-
-#define COLOR_MODE(o, m)	(((o) << 4) | (m))
-
-/* ROP4 operation values */
-#define ROP4_COPY		0xCCCC
-#define ROP4_INVERT		0x3333
-
-/* Hardware limits */
-#define MAX_WIDTH		8000
-#define MAX_HEIGHT		8000
-
-#define G2D_TIMEOUT		500
-
-#define DEFAULT_WIDTH		100
-#define DEFAULT_HEIGHT		100
-
-#define DEFAULT_SCALE_MODE	(2 << 0)
-
-/* Command mode register values */
-#define CMD_V3_ENABLE_STRETCH	(1 << 4)
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
deleted file mode 100644
index 612d1ea514f1..000000000000
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ /dev/null
@@ -1,800 +0,0 @@
-/*
- * Samsung S5P G2D - 2D Graphics Accelerator Driver
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Kamil Debski, <k.debski at samsung.com>
- *
- * 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
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-
-#include <linux/platform_device.h>
-#include <media/v4l2-mem2mem.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-v4l2.h>
-#include <media/videobuf2-dma-contig.h>
-
-#include "g2d.h"
-#include "g2d-regs.h"
-
-#define fh2ctx(__fh) container_of(__fh, struct g2d_ctx, fh)
-
-static struct g2d_fmt formats[] = {
-	{
-		.name	= "XRGB_8888",
-		.fourcc	= V4L2_PIX_FMT_RGB32,
-		.depth	= 32,
-		.hw	= COLOR_MODE(ORDER_XRGB, MODE_XRGB_8888),
-	},
-	{
-		.name	= "RGB_565",
-		.fourcc	= V4L2_PIX_FMT_RGB565X,
-		.depth	= 16,
-		.hw	= COLOR_MODE(ORDER_XRGB, MODE_RGB_565),
-	},
-	{
-		.name	= "XRGB_1555",
-		.fourcc	= V4L2_PIX_FMT_RGB555X,
-		.depth	= 16,
-		.hw	= COLOR_MODE(ORDER_XRGB, MODE_XRGB_1555),
-	},
-	{
-		.name	= "XRGB_4444",
-		.fourcc	= V4L2_PIX_FMT_RGB444,
-		.depth	= 16,
-		.hw	= COLOR_MODE(ORDER_XRGB, MODE_XRGB_4444),
-	},
-	{
-		.name	= "PACKED_RGB_888",
-		.fourcc	= V4L2_PIX_FMT_RGB24,
-		.depth	= 24,
-		.hw	= COLOR_MODE(ORDER_XRGB, MODE_PACKED_RGB_888),
-	},
-};
-#define NUM_FORMATS ARRAY_SIZE(formats)
-
-static struct g2d_frame def_frame = {
-	.width		= DEFAULT_WIDTH,
-	.height		= DEFAULT_HEIGHT,
-	.c_width	= DEFAULT_WIDTH,
-	.c_height	= DEFAULT_HEIGHT,
-	.o_width	= 0,
-	.o_height	= 0,
-	.fmt		= &formats[0],
-	.right		= DEFAULT_WIDTH,
-	.bottom		= DEFAULT_HEIGHT,
-};
-
-static struct g2d_fmt *find_fmt(struct v4l2_format *f)
-{
-	unsigned int i;
-	for (i = 0; i < NUM_FORMATS; i++) {
-		if (formats[i].fourcc == f->fmt.pix.pixelformat)
-			return &formats[i];
-	}
-	return NULL;
-}
-
-
-static struct g2d_frame *get_frame(struct g2d_ctx *ctx,
-							enum v4l2_buf_type type)
-{
-	switch (type) {
-	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-		return &ctx->in;
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		return &ctx->out;
-	default:
-		return ERR_PTR(-EINVAL);
-	}
-}
-
-static int g2d_queue_setup(struct vb2_queue *vq,
-			   unsigned int *nbuffers, unsigned int *nplanes,
-			   unsigned int sizes[], void *alloc_ctxs[])
-{
-	struct g2d_ctx *ctx = vb2_get_drv_priv(vq);
-	struct g2d_frame *f = get_frame(ctx, vq->type);
-
-	if (IS_ERR(f))
-		return PTR_ERR(f);
-
-	sizes[0] = f->size;
-	*nplanes = 1;
-	alloc_ctxs[0] = ctx->dev->alloc_ctx;
-
-	if (*nbuffers == 0)
-		*nbuffers = 1;
-
-	return 0;
-}
-
-static int g2d_buf_prepare(struct vb2_buffer *vb)
-{
-	struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-	struct g2d_frame *f = get_frame(ctx, vb->vb2_queue->type);
-
-	if (IS_ERR(f))
-		return PTR_ERR(f);
-	vb2_set_plane_payload(vb, 0, f->size);
-	return 0;
-}
-
-static void g2d_buf_queue(struct vb2_buffer *vb)
-{
-	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-	struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
-}
-
-static struct vb2_ops g2d_qops = {
-	.queue_setup	= g2d_queue_setup,
-	.buf_prepare	= g2d_buf_prepare,
-	.buf_queue	= g2d_buf_queue,
-};
-
-static int queue_init(void *priv, struct vb2_queue *src_vq,
-						struct vb2_queue *dst_vq)
-{
-	struct g2d_ctx *ctx = priv;
-	int ret;
-
-	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-	src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
-	src_vq->drv_priv = ctx;
-	src_vq->ops = &g2d_qops;
-	src_vq->mem_ops = &vb2_dma_contig_memops;
-	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-	src_vq->lock = &ctx->dev->mutex;
-
-	ret = vb2_queue_init(src_vq);
-	if (ret)
-		return ret;
-
-	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
-	dst_vq->drv_priv = ctx;
-	dst_vq->ops = &g2d_qops;
-	dst_vq->mem_ops = &vb2_dma_contig_memops;
-	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-	dst_vq->lock = &ctx->dev->mutex;
-
-	return vb2_queue_init(dst_vq);
-}
-
-static int g2d_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx,
-								ctrl_handler);
-	unsigned long flags;
-
-	spin_lock_irqsave(&ctx->dev->ctrl_lock, flags);
-	switch (ctrl->id) {
-	case V4L2_CID_COLORFX:
-		if (ctrl->val == V4L2_COLORFX_NEGATIVE)
-			ctx->rop = ROP4_INVERT;
-		else
-			ctx->rop = ROP4_COPY;
-		break;
-
-	case V4L2_CID_HFLIP:
-		ctx->flip = ctx->ctrl_hflip->val | (ctx->ctrl_vflip->val << 1);
-		break;
-
-	}
-	spin_unlock_irqrestore(&ctx->dev->ctrl_lock, flags);
-	return 0;
-}
-
-static const struct v4l2_ctrl_ops g2d_ctrl_ops = {
-	.s_ctrl		= g2d_s_ctrl,
-};
-
-static int g2d_setup_ctrls(struct g2d_ctx *ctx)
-{
-	struct g2d_dev *dev = ctx->dev;
-
-	v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
-
-	ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops,
-						V4L2_CID_HFLIP, 0, 1, 1, 0);
-
-	ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops,
-						V4L2_CID_VFLIP, 0, 1, 1, 0);
-
-	v4l2_ctrl_new_std_menu(
-		&ctx->ctrl_handler,
-		&g2d_ctrl_ops,
-		V4L2_CID_COLORFX,
-		V4L2_COLORFX_NEGATIVE,
-		~((1 << V4L2_COLORFX_NONE) | (1 << V4L2_COLORFX_NEGATIVE)),
-		V4L2_COLORFX_NONE);
-
-	if (ctx->ctrl_handler.error) {
-		int err = ctx->ctrl_handler.error;
-		v4l2_err(&dev->v4l2_dev, "g2d_setup_ctrls failed\n");
-		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
-		return err;
-	}
-
-	v4l2_ctrl_cluster(2, &ctx->ctrl_hflip);
-
-	return 0;
-}
-
-static int g2d_open(struct file *file)
-{
-	struct g2d_dev *dev = video_drvdata(file);
-	struct g2d_ctx *ctx = NULL;
-	int ret = 0;
-
-	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-	if (!ctx)
-		return -ENOMEM;
-	ctx->dev = dev;
-	/* Set default formats */
-	ctx->in		= def_frame;
-	ctx->out	= def_frame;
-
-	if (mutex_lock_interruptible(&dev->mutex)) {
-		kfree(ctx);
-		return -ERESTARTSYS;
-	}
-	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
-	if (IS_ERR(ctx->fh.m2m_ctx)) {
-		ret = PTR_ERR(ctx->fh.m2m_ctx);
-		mutex_unlock(&dev->mutex);
-		kfree(ctx);
-		return ret;
-	}
-	v4l2_fh_init(&ctx->fh, video_devdata(file));
-	file->private_data = &ctx->fh;
-	v4l2_fh_add(&ctx->fh);
-
-	g2d_setup_ctrls(ctx);
-
-	/* Write the default values to the ctx struct */
-	v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
-
-	ctx->fh.ctrl_handler = &ctx->ctrl_handler;
-	mutex_unlock(&dev->mutex);
-
-	v4l2_info(&dev->v4l2_dev, "instance opened\n");
-	return 0;
-}
-
-static int g2d_release(struct file *file)
-{
-	struct g2d_dev *dev = video_drvdata(file);
-	struct g2d_ctx *ctx = fh2ctx(file->private_data);
-
-	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
-	v4l2_fh_del(&ctx->fh);
-	v4l2_fh_exit(&ctx->fh);
-	kfree(ctx);
-	v4l2_info(&dev->v4l2_dev, "instance closed\n");
-	return 0;
-}
-
-
-static int vidioc_querycap(struct file *file, void *priv,
-				struct v4l2_capability *cap)
-{
-	strncpy(cap->driver, G2D_NAME, sizeof(cap->driver) - 1);
-	strncpy(cap->card, G2D_NAME, sizeof(cap->card) - 1);
-	cap->bus_info[0] = 0;
-	cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	return 0;
-}
-
-static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f)
-{
-	struct g2d_fmt *fmt;
-	if (f->index >= NUM_FORMATS)
-		return -EINVAL;
-	fmt = &formats[f->index];
-	f->pixelformat = fmt->fourcc;
-	strncpy(f->description, fmt->name, sizeof(f->description) - 1);
-	return 0;
-}
-
-static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f)
-{
-	struct g2d_ctx *ctx = prv;
-	struct vb2_queue *vq;
-	struct g2d_frame *frm;
-
-	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-	if (!vq)
-		return -EINVAL;
-	frm = get_frame(ctx, f->type);
-	if (IS_ERR(frm))
-		return PTR_ERR(frm);
-
-	f->fmt.pix.width		= frm->width;
-	f->fmt.pix.height		= frm->height;
-	f->fmt.pix.field		= V4L2_FIELD_NONE;
-	f->fmt.pix.pixelformat		= frm->fmt->fourcc;
-	f->fmt.pix.bytesperline		= (frm->width * frm->fmt->depth) >> 3;
-	f->fmt.pix.sizeimage		= frm->size;
-	return 0;
-}
-
-static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f)
-{
-	struct g2d_fmt *fmt;
-	enum v4l2_field *field;
-
-	fmt = find_fmt(f);
-	if (!fmt)
-		return -EINVAL;
-
-	field = &f->fmt.pix.field;
-	if (*field == V4L2_FIELD_ANY)
-		*field = V4L2_FIELD_NONE;
-	else if (*field != V4L2_FIELD_NONE)
-		return -EINVAL;
-
-	if (f->fmt.pix.width > MAX_WIDTH)
-		f->fmt.pix.width = MAX_WIDTH;
-	if (f->fmt.pix.height > MAX_HEIGHT)
-		f->fmt.pix.height = MAX_HEIGHT;
-
-	if (f->fmt.pix.width < 1)
-		f->fmt.pix.width = 1;
-	if (f->fmt.pix.height < 1)
-		f->fmt.pix.height = 1;
-
-	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
-	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-	return 0;
-}
-
-static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f)
-{
-	struct g2d_ctx *ctx = prv;
-	struct g2d_dev *dev = ctx->dev;
-	struct vb2_queue *vq;
-	struct g2d_frame *frm;
-	struct g2d_fmt *fmt;
-	int ret = 0;
-
-	/* Adjust all values accordingly to the hardware capabilities
-	 * and chosen format. */
-	ret = vidioc_try_fmt(file, prv, f);
-	if (ret)
-		return ret;
-	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-	if (vb2_is_busy(vq)) {
-		v4l2_err(&dev->v4l2_dev, "queue (%d) bust\n", f->type);
-		return -EBUSY;
-	}
-	frm = get_frame(ctx, f->type);
-	if (IS_ERR(frm))
-		return PTR_ERR(frm);
-	fmt = find_fmt(f);
-	if (!fmt)
-		return -EINVAL;
-	frm->width	= f->fmt.pix.width;
-	frm->height	= f->fmt.pix.height;
-	frm->size	= f->fmt.pix.sizeimage;
-	/* Reset crop settings */
-	frm->o_width	= 0;
-	frm->o_height	= 0;
-	frm->c_width	= frm->width;
-	frm->c_height	= frm->height;
-	frm->right	= frm->width;
-	frm->bottom	= frm->height;
-	frm->fmt	= fmt;
-	frm->stride	= f->fmt.pix.bytesperline;
-	return 0;
-}
-
-static int vidioc_cropcap(struct file *file, void *priv,
-					struct v4l2_cropcap *cr)
-{
-	struct g2d_ctx *ctx = priv;
-	struct g2d_frame *f;
-
-	f = get_frame(ctx, cr->type);
-	if (IS_ERR(f))
-		return PTR_ERR(f);
-
-	cr->bounds.left		= 0;
-	cr->bounds.top		= 0;
-	cr->bounds.width	= f->width;
-	cr->bounds.height	= f->height;
-	cr->defrect		= cr->bounds;
-	return 0;
-}
-
-static int vidioc_g_crop(struct file *file, void *prv, struct v4l2_crop *cr)
-{
-	struct g2d_ctx *ctx = prv;
-	struct g2d_frame *f;
-
-	f = get_frame(ctx, cr->type);
-	if (IS_ERR(f))
-		return PTR_ERR(f);
-
-	cr->c.left	= f->o_height;
-	cr->c.top	= f->o_width;
-	cr->c.width	= f->c_width;
-	cr->c.height	= f->c_height;
-	return 0;
-}
-
-static int vidioc_try_crop(struct file *file, void *prv, const struct v4l2_crop *cr)
-{
-	struct g2d_ctx *ctx = prv;
-	struct g2d_dev *dev = ctx->dev;
-	struct g2d_frame *f;
-
-	f = get_frame(ctx, cr->type);
-	if (IS_ERR(f))
-		return PTR_ERR(f);
-
-	if (cr->c.top < 0 || cr->c.left < 0) {
-		v4l2_err(&dev->v4l2_dev,
-			"doesn't support negative values for top & left\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int vidioc_s_crop(struct file *file, void *prv, const struct v4l2_crop *cr)
-{
-	struct g2d_ctx *ctx = prv;
-	struct g2d_frame *f;
-	int ret;
-
-	ret = vidioc_try_crop(file, prv, cr);
-	if (ret)
-		return ret;
-	f = get_frame(ctx, cr->type);
-	if (IS_ERR(f))
-		return PTR_ERR(f);
-
-	f->c_width	= cr->c.width;
-	f->c_height	= cr->c.height;
-	f->o_width	= cr->c.left;
-	f->o_height	= cr->c.top;
-	f->bottom	= f->o_height + f->c_height;
-	f->right	= f->o_width + f->c_width;
-	return 0;
-}
-
-static void job_abort(void *prv)
-{
-	struct g2d_ctx *ctx = prv;
-	struct g2d_dev *dev = ctx->dev;
-
-	if (dev->curr == NULL) /* No job currently running */
-		return;
-
-	wait_event_timeout(dev->irq_queue,
-			   dev->curr == NULL,
-			   msecs_to_jiffies(G2D_TIMEOUT));
-}
-
-static void device_run(void *prv)
-{
-	struct g2d_ctx *ctx = prv;
-	struct g2d_dev *dev = ctx->dev;
-	struct vb2_buffer *src, *dst;
-	unsigned long flags;
-	u32 cmd = 0;
-
-	dev->curr = ctx;
-
-	src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-	dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-
-	clk_enable(dev->gate);
-	g2d_reset(dev);
-
-	spin_lock_irqsave(&dev->ctrl_lock, flags);
-
-	g2d_set_src_size(dev, &ctx->in);
-	g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0));
-
-	g2d_set_dst_size(dev, &ctx->out);
-	g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0));
-
-	g2d_set_rop4(dev, ctx->rop);
-	g2d_set_flip(dev, ctx->flip);
-
-	if (ctx->in.c_width != ctx->out.c_width ||
-		ctx->in.c_height != ctx->out.c_height) {
-		if (dev->variant->hw_rev == TYPE_G2D_3X)
-			cmd |= CMD_V3_ENABLE_STRETCH;
-		else
-			g2d_set_v41_stretch(dev, &ctx->in, &ctx->out);
-	}
-
-	g2d_set_cmd(dev, cmd);
-	g2d_start(dev);
-
-	spin_unlock_irqrestore(&dev->ctrl_lock, flags);
-}
-
-static irqreturn_t g2d_isr(int irq, void *prv)
-{
-	struct g2d_dev *dev = prv;
-	struct g2d_ctx *ctx = dev->curr;
-	struct vb2_v4l2_buffer *src, *dst;
-
-	g2d_clear_int(dev);
-	clk_disable(dev->gate);
-
-	BUG_ON(ctx == NULL);
-
-	src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-	dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-
-	BUG_ON(src == NULL);
-	BUG_ON(dst == NULL);
-
-	dst->timecode = src->timecode;
-	dst->vb2_buf.timestamp = src->vb2_buf.timestamp;
-	dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-	dst->flags |=
-		src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-
-	v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
-	v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
-	v4l2_m2m_job_finish(dev->m2m_dev, ctx->fh.m2m_ctx);
-
-	dev->curr = NULL;
-	wake_up(&dev->irq_queue);
-	return IRQ_HANDLED;
-}
-
-static const struct v4l2_file_operations g2d_fops = {
-	.owner		= THIS_MODULE,
-	.open		= g2d_open,
-	.release	= g2d_release,
-	.poll		= v4l2_m2m_fop_poll,
-	.unlocked_ioctl	= video_ioctl2,
-	.mmap		= v4l2_m2m_fop_mmap,
-};
-
-static const struct v4l2_ioctl_ops g2d_ioctl_ops = {
-	.vidioc_querycap	= vidioc_querycap,
-
-	.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt,
-	.vidioc_g_fmt_vid_cap		= vidioc_g_fmt,
-	.vidioc_try_fmt_vid_cap		= vidioc_try_fmt,
-	.vidioc_s_fmt_vid_cap		= vidioc_s_fmt,
-
-	.vidioc_enum_fmt_vid_out	= vidioc_enum_fmt,
-	.vidioc_g_fmt_vid_out		= vidioc_g_fmt,
-	.vidioc_try_fmt_vid_out		= vidioc_try_fmt,
-	.vidioc_s_fmt_vid_out		= vidioc_s_fmt,
-
-	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,
-	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
-	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
-	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
-
-	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
-	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
-
-	.vidioc_g_crop			= vidioc_g_crop,
-	.vidioc_s_crop			= vidioc_s_crop,
-	.vidioc_cropcap			= vidioc_cropcap,
-};
-
-static struct video_device g2d_videodev = {
-	.name		= G2D_NAME,
-	.fops		= &g2d_fops,
-	.ioctl_ops	= &g2d_ioctl_ops,
-	.minor		= -1,
-	.release	= video_device_release,
-	.vfl_dir	= VFL_DIR_M2M,
-};
-
-static struct v4l2_m2m_ops g2d_m2m_ops = {
-	.device_run	= device_run,
-	.job_abort	= job_abort,
-};
-
-static const struct of_device_id exynos_g2d_match[];
-
-static int g2d_probe(struct platform_device *pdev)
-{
-	struct g2d_dev *dev;
-	struct video_device *vfd;
-	struct resource *res;
-	const struct of_device_id *of_id;
-	int ret = 0;
-
-	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return -ENOMEM;
-
-	spin_lock_init(&dev->ctrl_lock);
-	mutex_init(&dev->mutex);
-	atomic_set(&dev->num_inst, 0);
-	init_waitqueue_head(&dev->irq_queue);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	dev->regs = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dev->regs))
-		return PTR_ERR(dev->regs);
-
-	dev->clk = clk_get(&pdev->dev, "sclk_fimg2d");
-	if (IS_ERR(dev->clk)) {
-		dev_err(&pdev->dev, "failed to get g2d clock\n");
-		return -ENXIO;
-	}
-
-	ret = clk_prepare(dev->clk);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to prepare g2d clock\n");
-		goto put_clk;
-	}
-
-	dev->gate = clk_get(&pdev->dev, "fimg2d");
-	if (IS_ERR(dev->gate)) {
-		dev_err(&pdev->dev, "failed to get g2d clock gate\n");
-		ret = -ENXIO;
-		goto unprep_clk;
-	}
-
-	ret = clk_prepare(dev->gate);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to prepare g2d clock gate\n");
-		goto put_clk_gate;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "failed to find IRQ\n");
-		ret = -ENXIO;
-		goto unprep_clk_gate;
-	}
-
-	dev->irq = res->start;
-
-	ret = devm_request_irq(&pdev->dev, dev->irq, g2d_isr,
-						0, pdev->name, dev);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to install IRQ\n");
-		goto put_clk_gate;
-	}
-
-	dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
-	if (IS_ERR(dev->alloc_ctx)) {
-		ret = PTR_ERR(dev->alloc_ctx);
-		goto unprep_clk_gate;
-	}
-
-	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-	if (ret)
-		goto alloc_ctx_cleanup;
-	vfd = video_device_alloc();
-	if (!vfd) {
-		v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
-		ret = -ENOMEM;
-		goto unreg_v4l2_dev;
-	}
-	*vfd = g2d_videodev;
-	vfd->lock = &dev->mutex;
-	vfd->v4l2_dev = &dev->v4l2_dev;
-	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
-	if (ret) {
-		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
-		goto rel_vdev;
-	}
-	video_set_drvdata(vfd, dev);
-	snprintf(vfd->name, sizeof(vfd->name), "%s", g2d_videodev.name);
-	dev->vfd = vfd;
-	v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n",
-								vfd->num);
-	platform_set_drvdata(pdev, dev);
-	dev->m2m_dev = v4l2_m2m_init(&g2d_m2m_ops);
-	if (IS_ERR(dev->m2m_dev)) {
-		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
-		ret = PTR_ERR(dev->m2m_dev);
-		goto unreg_video_dev;
-	}
-
-	def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
-
-	of_id = of_match_node(exynos_g2d_match, pdev->dev.of_node);
-	if (!of_id) {
-		ret = -ENODEV;
-		goto unreg_video_dev;
-	}
-	dev->variant = (struct g2d_variant *)of_id->data;
-
-	return 0;
-
-unreg_video_dev:
-	video_unregister_device(dev->vfd);
-rel_vdev:
-	video_device_release(vfd);
-unreg_v4l2_dev:
-	v4l2_device_unregister(&dev->v4l2_dev);
-alloc_ctx_cleanup:
-	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
-unprep_clk_gate:
-	clk_unprepare(dev->gate);
-put_clk_gate:
-	clk_put(dev->gate);
-unprep_clk:
-	clk_unprepare(dev->clk);
-put_clk:
-	clk_put(dev->clk);
-
-	return ret;
-}
-
-static int g2d_remove(struct platform_device *pdev)
-{
-	struct g2d_dev *dev = platform_get_drvdata(pdev);
-
-	v4l2_info(&dev->v4l2_dev, "Removing " G2D_NAME);
-	v4l2_m2m_release(dev->m2m_dev);
-	video_unregister_device(dev->vfd);
-	v4l2_device_unregister(&dev->v4l2_dev);
-	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
-	clk_unprepare(dev->gate);
-	clk_put(dev->gate);
-	clk_unprepare(dev->clk);
-	clk_put(dev->clk);
-	return 0;
-}
-
-static struct g2d_variant g2d_drvdata_v3x = {
-	.hw_rev = TYPE_G2D_3X, /* Revision 3.0 for S5PV210 and Exynos4210 */
-};
-
-static struct g2d_variant g2d_drvdata_v4x = {
-	.hw_rev = TYPE_G2D_4X, /* Revision 4.1 for Exynos4X12 and Exynos5 */
-};
-
-static const struct of_device_id exynos_g2d_match[] = {
-	{
-		.compatible = "samsung,s5pv210-g2d",
-		.data = &g2d_drvdata_v3x,
-	}, {
-		.compatible = "samsung,exynos4212-g2d",
-		.data = &g2d_drvdata_v4x,
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, exynos_g2d_match);
-
-static struct platform_driver g2d_pdrv = {
-	.probe		= g2d_probe,
-	.remove		= g2d_remove,
-	.driver		= {
-		.name = G2D_NAME,
-		.of_match_table = exynos_g2d_match,
-	},
-};
-
-module_platform_driver(g2d_pdrv);
-
-MODULE_AUTHOR("Kamil Debski <k.debski at samsung.com>");
-MODULE_DESCRIPTION("S5P G2D 2d graphics accelerator driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/s5p-g2d/g2d.h b/drivers/media/platform/s5p-g2d/g2d.h
deleted file mode 100644
index e31df541aa62..000000000000
--- a/drivers/media/platform/s5p-g2d/g2d.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Samsung S5P G2D - 2D Graphics Accelerator Driver
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Kamil Debski, <k.debski at samsung.com>
- *
- * 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
- */
-
-#include <linux/platform_device.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-
-#define G2D_NAME "s5p-g2d"
-#define TYPE_G2D_3X 3
-#define TYPE_G2D_4X 4
-
-struct g2d_dev {
-	struct v4l2_device	v4l2_dev;
-	struct v4l2_m2m_dev	*m2m_dev;
-	struct video_device	*vfd;
-	struct mutex		mutex;
-	spinlock_t		ctrl_lock;
-	atomic_t		num_inst;
-	struct vb2_alloc_ctx	*alloc_ctx;
-	void __iomem		*regs;
-	struct clk		*clk;
-	struct clk		*gate;
-	struct g2d_ctx		*curr;
-	struct g2d_variant	*variant;
-	int irq;
-	wait_queue_head_t	irq_queue;
-};
-
-struct g2d_frame {
-	/* Original dimensions */
-	u32	width;
-	u32	height;
-	/* Crop size */
-	u32	c_width;
-	u32	c_height;
-	/* Offset */
-	u32	o_width;
-	u32	o_height;
-	/* Image format */
-	struct g2d_fmt *fmt;
-	/* Variables that can calculated once and reused */
-	u32	stride;
-	u32	bottom;
-	u32	right;
-	u32	size;
-};
-
-struct g2d_ctx {
-	struct v4l2_fh fh;
-	struct g2d_dev		*dev;
-	struct g2d_frame	in;
-	struct g2d_frame	out;
-	struct v4l2_ctrl	*ctrl_hflip;
-	struct v4l2_ctrl	*ctrl_vflip;
-	struct v4l2_ctrl_handler ctrl_handler;
-	u32 rop;
-	u32 flip;
-};
-
-struct g2d_fmt {
-	char	*name;
-	u32	fourcc;
-	int	depth;
-	u32	hw;
-};
-
-struct g2d_variant {
-	unsigned short hw_rev;
-};
-
-void g2d_reset(struct g2d_dev *d);
-void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f);
-void g2d_set_src_addr(struct g2d_dev *d, dma_addr_t a);
-void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f);
-void g2d_set_dst_addr(struct g2d_dev *d, dma_addr_t a);
-void g2d_start(struct g2d_dev *d);
-void g2d_clear_int(struct g2d_dev *d);
-void g2d_set_rop4(struct g2d_dev *d, u32 r);
-void g2d_set_flip(struct g2d_dev *d, u32 r);
-void g2d_set_v41_stretch(struct g2d_dev *d,
-			struct g2d_frame *src, struct g2d_frame *dst);
-void g2d_set_cmd(struct g2d_dev *d, u32 c);
-- 
1.9.1



From fu.wei at linaro.org  Tue May 24 06:30:27 2016
From: fu.wei at linaro.org (fu.wei at linaro.org)
Date: Tue, 24 May 2016 21:30:27 +0800
Subject: [PATCH v5 0/6] acpi,
 clocksource: add GTDT driver and GTDT support in arm_arch_timer
Message-ID: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>

From: Fu Wei <fu.wei at linaro.org>

This patchset:
    (1)Preparation for adding GTDT support in arm_arch_timer
        1. Move some enums and marcos to header file
        2. Add a new enum for spi type.
        3. Improve printk relevant code

    (2)Introduce ACPI GTDT parser: drivers/acpi/gtdt.c
    Parse all kinds of timer in GTDT table of ACPI:arch timer,
    memory-mapped timer and SBSA Generic Watchdog timer.
    This driver can help to simplify all the relevant timer drivers,
    and separate all the ACPI GTDT knowledge from them.

    (3)Simplify ACPI code for arm_arch_timer

    (4)Add GTDT support for ARM memory-mapped timer

This patchset has been tested on the following platforms:
    (1)ARM Foundation v8 model

Changelog:
v5: Sorting out all patches, simplify the API of GTDT driver:
    GTDT driver just fills the data struct for arm_arch_timer driver.

v4: https://lists.linaro.org/pipermail/linaro-acpi/2016-March/006667.html
    Delete the kvm relevant patches
    Separate two patches for sorting out the code for arm_arch_timer.
    Improve irq info export code to allow missing irq info in GTDT table.

v3: https://lkml.org/lkml/2016/2/1/658
    Improve GTDT driver code:
      (1)improve pr_* by defining pr_fmt(fmt)
      (2)simplify gtdt_sbsa_gwdt_init
      (3)improve gtdt_arch_timer_data_init, if table is NULL, it will try
      to get GTDT table.
    Move enum ppi_nr to arm_arch_timer.h, and add enum spi_nr.
    Add arm_arch_timer get ppi from DT and GTDT support for kvm.

v2: https://lkml.org/lkml/2015/12/2/10
    Rebase to latest kernel version(4.4-rc3).
    Fix the bug about the config problem,
    use CONFIG_ACPI_GTDT instead of CONFIG_ACPI in arm_arch_timer.c

v1: The first upstreaming version: https://lkml.org/lkml/2015/10/28/553


Fu Wei (6):
  clocksource/drivers/arm_arch_timer: Move enums and defines to header
    file
  clocksource/drivers/arm_arch_timer: Add a new enum for spi type
  clocksource/drivers/arm_arch_timer: Improve printk relevant code
  acpi: Add GTDT table parse driver into ACPI driver
  clocksource/drivers/arm_arch_timer: Simplify ACPI support code.
  clocksource/drivers/arm_arch_timer: Add GTDT support for memory-mapped
    timer

 drivers/acpi/Kconfig                 |   9 +
 drivers/acpi/Makefile                |   1 +
 drivers/acpi/acpi_gtdt.c             | 309 +++++++++++++++++++++++++++++++++++
 drivers/clocksource/Kconfig          |   1 +
 drivers/clocksource/arm_arch_timer.c | 233 ++++++++++++++++++--------
 include/clocksource/arm_arch_timer.h |  33 ++++
 include/linux/acpi.h                 |   6 +
 7 files changed, 522 insertions(+), 70 deletions(-)
 create mode 100644 drivers/acpi/acpi_gtdt.c

-- 
2.5.5



From fu.wei at linaro.org  Tue May 24 06:30:28 2016
From: fu.wei at linaro.org (fu.wei at linaro.org)
Date: Tue, 24 May 2016 21:30:28 +0800
Subject: [PATCH v5 1/6] clocksource/drivers/arm_arch_timer: Move enums and
 defines to header file
In-Reply-To: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
References: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
Message-ID: <1464096633-9309-2-git-send-email-fu.wei@linaro.org>

From: Fu Wei <fu.wei at linaro.org>

To support the arm_arch_timer via ACPI we need to share defines and enums
between the driver and the ACPI parser code.

Split out the relevant defines and enums into arm_arch_timer.h.
No functional change.

Signed-off-by: Fu Wei <fu.wei at linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 11 -----------
 include/clocksource/arm_arch_timer.h | 11 +++++++++++
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 4814446..5d7272e 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -48,8 +48,6 @@
 #define CNTV_TVAL	0x38
 #define CNTV_CTL	0x3c
 
-#define ARCH_CP15_TIMER	BIT(0)
-#define ARCH_MEM_TIMER	BIT(1)
 static unsigned arch_timers_present __initdata;
 
 static void __iomem *arch_counter_base;
@@ -62,15 +60,6 @@ struct arch_timer {
 #define to_arch_timer(e) container_of(e, struct arch_timer, evt)
 
 static u32 arch_timer_rate;
-
-enum ppi_nr {
-	PHYS_SECURE_PPI,
-	PHYS_NONSECURE_PPI,
-	VIRT_PPI,
-	HYP_PPI,
-	MAX_TIMER_PPI
-};
-
 static int arch_timer_ppi[MAX_TIMER_PPI];
 
 static struct clock_event_device __percpu *arch_timer_evt;
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index caedb74..6f06481 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -19,6 +19,9 @@
 #include <linux/timecounter.h>
 #include <linux/types.h>
 
+#define ARCH_CP15_TIMER			BIT(0)
+#define ARCH_MEM_TIMER			BIT(1)
+
 #define ARCH_TIMER_CTRL_ENABLE		(1 << 0)
 #define ARCH_TIMER_CTRL_IT_MASK		(1 << 1)
 #define ARCH_TIMER_CTRL_IT_STAT		(1 << 2)
@@ -34,6 +37,14 @@ enum arch_timer_reg {
 	ARCH_TIMER_REG_TVAL,
 };
 
+enum ppi_nr {
+	PHYS_SECURE_PPI,
+	PHYS_NONSECURE_PPI,
+	VIRT_PPI,
+	HYP_PPI,
+	MAX_TIMER_PPI
+};
+
 #define ARCH_TIMER_PHYS_ACCESS		0
 #define ARCH_TIMER_VIRT_ACCESS		1
 #define ARCH_TIMER_MEM_PHYS_ACCESS	2
-- 
2.5.5



From fu.wei at linaro.org  Tue May 24 06:30:29 2016
From: fu.wei at linaro.org (fu.wei at linaro.org)
Date: Tue, 24 May 2016 21:30:29 +0800
Subject: [PATCH v5 2/6] clocksource/drivers/arm_arch_timer: Add a new enum for
 spi type
In-Reply-To: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
References: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
Message-ID: <1464096633-9309-3-git-send-email-fu.wei@linaro.org>

From: Fu Wei <fu.wei at linaro.org>

This patch add a new enum "spi_nr" and use it in the driver.
Just for code's readability, no functional change.

Signed-off-by: Fu Wei <fu.wei at linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 4 ++--
 include/clocksource/arm_arch_timer.h | 6 ++++++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 5d7272e..966c574 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -826,9 +826,9 @@ static void __init arch_timer_mem_init(struct device_node *np)
 	}
 
 	if (arch_timer_mem_use_virtual)
-		irq = irq_of_parse_and_map(best_frame, 1);
+		irq = irq_of_parse_and_map(best_frame, VIRT_SPI);
 	else
-		irq = irq_of_parse_and_map(best_frame, 0);
+		irq = irq_of_parse_and_map(best_frame, PHYS_SPI);
 
 	if (!irq) {
 		pr_err("arch_timer: Frame missing %s irq",
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 6f06481..16dcd10 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -45,6 +45,12 @@ enum ppi_nr {
 	MAX_TIMER_PPI
 };
 
+enum spi_nr {
+	PHYS_SPI,
+	VIRT_SPI,
+	MAX_TIMER_SPI
+};
+
 #define ARCH_TIMER_PHYS_ACCESS		0
 #define ARCH_TIMER_VIRT_ACCESS		1
 #define ARCH_TIMER_MEM_PHYS_ACCESS	2
-- 
2.5.5



From fu.wei at linaro.org  Tue May 24 06:30:30 2016
From: fu.wei at linaro.org (fu.wei at linaro.org)
Date: Tue, 24 May 2016 21:30:30 +0800
Subject: [PATCH v5 3/6] clocksource/drivers/arm_arch_timer: Improve printk
 relevant code
In-Reply-To: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
References: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
Message-ID: <1464096633-9309-4-git-send-email-fu.wei@linaro.org>

From: Fu Wei <fu.wei at linaro.org>

This patch defines pr_fmt(fmt) for all pr_* functions,
then the pr_* don't need to add "arch_timer:" everytime.

Also delete some Blank Spaces in arch_timer_banner,
according to the suggestion from checkpatch.pl.

No functional change.

Signed-off-by: Fu Wei <fu.wei at linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 52 +++++++++++++++++++-----------------
 1 file changed, 27 insertions(+), 25 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 966c574..9540e9d 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -29,6 +29,9 @@
 
 #include <clocksource/arm_arch_timer.h>
 
+#undef pr_fmt
+#define pr_fmt(fmt) "arch_timer: " fmt
+
 #define CNTTIDR		0x08
 #define CNTTIDR_VIRT(n)	(BIT(1) << ((n) * 4))
 
@@ -388,24 +391,24 @@ arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
 
 	/* Check the timer frequency. */
 	if (arch_timer_rate == 0)
-		pr_warn("Architected timer frequency not available\n");
+		pr_warn("frequency not available\n");
 }
 
 static void arch_timer_banner(unsigned type)
 {
-	pr_info("Architected %s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
-		     type & ARCH_CP15_TIMER ? "cp15" : "",
-		     type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ?  " and " : "",
-		     type & ARCH_MEM_TIMER ? "mmio" : "",
-		     (unsigned long)arch_timer_rate / 1000000,
-		     (unsigned long)(arch_timer_rate / 10000) % 100,
-		     type & ARCH_CP15_TIMER ?
-		     (arch_timer_uses_ppi == VIRT_PPI) ? "virt" : "phys" :
-			"",
-		     type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ?  "/" : "",
-		     type & ARCH_MEM_TIMER ?
-			arch_timer_mem_use_virtual ? "virt" : "phys" :
-			"");
+	pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
+		type & ARCH_CP15_TIMER ? "cp15" : "",
+		type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ?  " and " : "",
+		type & ARCH_MEM_TIMER ? "mmio" : "",
+		(unsigned long)arch_timer_rate / 1000000,
+		(unsigned long)(arch_timer_rate / 10000) % 100,
+		type & ARCH_CP15_TIMER ?
+		(arch_timer_uses_ppi == VIRT_PPI) ? "virt" : "phys" :
+		"",
+		type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ?  "/" : "",
+		type & ARCH_MEM_TIMER ?
+		arch_timer_mem_use_virtual ? "virt" : "phys" :
+		"");
 }
 
 u32 arch_timer_get_rate(void)
@@ -498,7 +501,7 @@ static void __init arch_counter_register(unsigned type)
 
 static void arch_timer_stop(struct clock_event_device *clk)
 {
-	pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n",
+	pr_debug("teardown, disable IRQ%d cpu #%d\n",
 		 clk->irq, smp_processor_id());
 
 	disable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi]);
@@ -597,8 +600,7 @@ static int __init arch_timer_register(void)
 	}
 
 	if (err) {
-		pr_err("arch_timer: can't register interrupt %d (%d)\n",
-		       ppi, err);
+		pr_err("can't register interrupt %d (%d)\n", ppi, err);
 		goto out_free;
 	}
 
@@ -650,7 +652,7 @@ static int __init arch_timer_mem_register(void __iomem *base, unsigned int irq)
 
 	ret = request_irq(irq, func, IRQF_TIMER, "arch_mem_timer", &t->evt);
 	if (ret) {
-		pr_err("arch_timer: Failed to request mem timer irq\n");
+		pr_err("Failed to request mem timer irq\n");
 		kfree(t);
 	}
 
@@ -727,7 +729,7 @@ static void __init arch_timer_init(void)
 		}
 
 		if (!has_ppi) {
-			pr_warn("arch_timer: No interrupt available, giving up\n");
+			pr_warn("No interrupt available, giving up\n");
 			return;
 		}
 	}
@@ -743,7 +745,7 @@ static void __init arch_timer_of_init(struct device_node *np)
 	int i;
 
 	if (arch_timers_present & ARCH_CP15_TIMER) {
-		pr_warn("arch_timer: multiple nodes in dt, skipping\n");
+		pr_warn("multiple nodes in dt, skipping\n");
 		return;
 	}
 
@@ -778,7 +780,7 @@ static void __init arch_timer_mem_init(struct device_node *np)
 	arch_timers_present |= ARCH_MEM_TIMER;
 	cntctlbase = of_iomap(np, 0);
 	if (!cntctlbase) {
-		pr_err("arch_timer: Can't find CNTCTLBase\n");
+		pr_err("Can't find CNTCTLBase\n");
 		return;
 	}
 
@@ -793,7 +795,7 @@ static void __init arch_timer_mem_init(struct device_node *np)
 		u32 cntacr;
 
 		if (of_property_read_u32(frame, "frame-number", &n)) {
-			pr_err("arch_timer: Missing frame-number\n");
+			pr_err("Missing frame-number\n");
 			of_node_put(frame);
 			goto out;
 		}
@@ -821,7 +823,7 @@ static void __init arch_timer_mem_init(struct device_node *np)
 
 	base = arch_counter_base = of_iomap(best_frame, 0);
 	if (!base) {
-		pr_err("arch_timer: Can't map frame's registers\n");
+		pr_err("Can't map frame's registers\n");
 		goto out;
 	}
 
@@ -831,7 +833,7 @@ static void __init arch_timer_mem_init(struct device_node *np)
 		irq = irq_of_parse_and_map(best_frame, PHYS_SPI);
 
 	if (!irq) {
-		pr_err("arch_timer: Frame missing %s irq",
+		pr_err("Frame missing %s irq",
 		       arch_timer_mem_use_virtual ? "virt" : "phys");
 		goto out;
 	}
@@ -869,7 +871,7 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 	struct acpi_table_gtdt *gtdt;
 
 	if (arch_timers_present & ARCH_CP15_TIMER) {
-		pr_warn("arch_timer: already initialized, skipping\n");
+		pr_warn("already initialized, skipping\n");
 		return -EINVAL;
 	}
 
-- 
2.5.5



From fu.wei at linaro.org  Tue May 24 06:30:31 2016
From: fu.wei at linaro.org (fu.wei at linaro.org)
Date: Tue, 24 May 2016 21:30:31 +0800
Subject: [PATCH v5 4/6] acpi: Add GTDT table parse driver into ACPI driver
In-Reply-To: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
References: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
Message-ID: <1464096633-9309-5-git-send-email-fu.wei@linaro.org>

From: Fu Wei <fu.wei at linaro.org>

This driver adds support for parsing all kinds of timer in GTDT:
(1)arch timer: provide a kernel API to parse all the PPIs and
always-on info in GTDT and export them by filling the structs
which provided by parameters(pointer of them).

(2)memory-mapped timer: provide a kernel APIs to parse
GT Block Structure in GTDT, export all the timer info by filling
the struct which provided by parameter(pointer of the struct).

(3)SBSA Generic Watchdog: parse all info in SBSA Generic Watchdog
Structure in GTDT, and creating a platform device with that
information. This allows the operating system to obtain device
data from the resource of platform device.
The platform device named "sbsa-gwdt" can be used by the ARM SBSA
Generic Watchdog driver.

By this driver, we can simplify all the relevant drivers, and
separate all the ACPI GTDT knowledge from them.

Signed-off-by: Fu Wei <fu.wei at linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
---
 drivers/acpi/Kconfig                 |   9 +
 drivers/acpi/Makefile                |   1 +
 drivers/acpi/acpi_gtdt.c             | 309 +++++++++++++++++++++++++++++++++++
 include/clocksource/arm_arch_timer.h |  16 ++
 include/linux/acpi.h                 |   6 +
 5 files changed, 341 insertions(+)

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index b7e2e77..27a5cf9 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -521,4 +521,13 @@ config XPOWER_PMIC_OPREGION
 
 endif
 
+config ACPI_GTDT
+	bool "ACPI GTDT Support"
+	depends on ARM64
+	help
+	  GTDT (Generic Timer Description Table) provides information
+	  for per-processor timers and Platform (memory-mapped) timers
+	  for ARM platforms. Select this option to provide information
+	  needed for the timers init.
+
 endif	# ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 251ce85..848aa8a 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -99,5 +99,6 @@ obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
 obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
 obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
 obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
+obj-$(CONFIG_ACPI_GTDT)		+= acpi_gtdt.o
 
 video-objs			+= acpi_video.o video_detect.o
diff --git a/drivers/acpi/acpi_gtdt.c b/drivers/acpi/acpi_gtdt.c
new file mode 100644
index 0000000..e54fadf
--- /dev/null
+++ b/drivers/acpi/acpi_gtdt.c
@@ -0,0 +1,309 @@
+/*
+ * ARM Specific GTDT table Support
+ *
+ * Copyright (C) 2015, Linaro Ltd.
+ * Author: Fu Wei <fu.wei at linaro.org>
+ *         Hanjun Guo <hanjun.guo at linaro.org>
+ *
+ * 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/acpi.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <clocksource/arm_arch_timer.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "GTDT: " fmt
+
+typedef int (*platform_timer_handler)(void *platform_timer, int index,
+				      void *data);
+
+static void *platform_timer_struct __initdata;
+static u32 platform_timer_count __initdata;
+static void *gtdt_end __initdata;
+
+static int __init for_platform_timer(enum acpi_gtdt_type type,
+				     platform_timer_handler handler, void *data)
+{
+	struct acpi_gtdt_header *header;
+	int i, index, ret;
+	void *platform_timer = platform_timer_struct;
+
+	for (i = 0, index = 0; i < platform_timer_count; i++) {
+		if (platform_timer > gtdt_end) {
+			pr_err(FW_BUG "subtable pointer overflows.\n");
+			platform_timer_count = i;
+			break;
+		}
+		header = (struct acpi_gtdt_header *)platform_timer;
+		if (header->type == type) {
+			ret = handler(platform_timer, index, data);
+			if (ret)
+				pr_err("failed to handler subtable %d.\n", i);
+			else
+				index++;
+		}
+		platform_timer += header->length;
+	}
+
+	return index;
+}
+
+/*
+ * Get some basic info from GTDT table, and init the global variables above
+ * for all timers initialization of Generic Timer.
+ * This function does some validation on GTDT table, and will be run only once.
+ */
+static void __init platform_timer_init(struct acpi_table_header *table,
+				       struct acpi_table_gtdt *gtdt)
+{
+	gtdt_end = (void *)table + table->length;
+
+	if (table->revision < 2) {
+		pr_info("Revision:%d doesn't support Platform Timers.\n",
+			table->revision);
+		return;
+	}
+
+	platform_timer_count = gtdt->platform_timer_count;
+	if (!platform_timer_count) {
+		pr_info("No Platform Timer structures.\n");
+		return;
+	}
+
+	platform_timer_struct = (void *)gtdt + gtdt->platform_timer_offset;
+	if (platform_timer_struct < (void *)table +
+				    sizeof(struct acpi_table_gtdt)) {
+		pr_err(FW_BUG "Platform Timer pointer error.\n");
+		platform_timer_struct = NULL;
+		platform_timer_count = 0;
+	}
+}
+
+static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
+{
+	int trigger, polarity;
+
+	if (!interrupt)
+		return 0;
+
+	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+			: ACPI_LEVEL_SENSITIVE;
+
+	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+			: ACPI_ACTIVE_HIGH;
+
+	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/*
+ * Get the necessary info of arch_timer from GTDT table.
+ */
+int __init gtdt_arch_timer_init(struct acpi_table_header *table, int *ppi,
+				bool *c3stop, u32 *timer_count)
+{
+	struct acpi_table_gtdt *gtdt;
+
+	if (acpi_disabled || !table || !ppi || !c3stop)
+		return -EINVAL;
+
+	gtdt = container_of(table, struct acpi_table_gtdt, header);
+	if (!gtdt) {
+		pr_err("table pointer error.\n");
+		return -EINVAL;
+	}
+
+	ppi[PHYS_SECURE_PPI] =
+		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
+					    gtdt->secure_el1_flags);
+
+	ppi[PHYS_NONSECURE_PPI] =
+		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
+					    gtdt->non_secure_el1_flags);
+
+	ppi[VIRT_PPI] =
+		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
+					    gtdt->virtual_timer_flags);
+
+	ppi[HYP_PPI] =
+		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
+					    gtdt->non_secure_el2_flags);
+
+	*c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
+
+	platform_timer_init(table, gtdt);
+	if (timer_count)
+		*timer_count = platform_timer_count;
+
+	return 0;
+}
+
+/*
+ * Helper function for getting the pointer of a timer frame in GT block.
+ */
+static void __init *gtdt_gt_timer_frame(struct acpi_gtdt_timer_block *gt_block,
+					int index)
+{
+	void *timer_frame = (void *)gt_block + gt_block->timer_offset +
+			    sizeof(struct acpi_gtdt_timer_entry) * index;
+
+	if (timer_frame <= (void *)gt_block + gt_block->header.length -
+			   sizeof(struct acpi_gtdt_timer_entry))
+		return timer_frame;
+
+	return NULL;
+}
+
+static int __init gtdt_parse_gt_block(void *platform_timer, int index,
+				      void *data)
+{
+	struct acpi_gtdt_timer_block *block;
+	struct acpi_gtdt_timer_entry *frame;
+	struct gt_block_data *block_data;
+	int i, j;
+
+	if (!platform_timer || !data)
+		return -EINVAL;
+
+	block = platform_timer;
+	block_data = data + sizeof(struct gt_block_data) * index;
+
+	if (!block->block_address || !block->timer_count) {
+		pr_err(FW_BUG "invalid GT Block data.\n");
+		return -EINVAL;
+	}
+	block_data->cntctlbase_phy = (phys_addr_t)block->block_address;
+	block_data->timer_count = block->timer_count;
+
+	/*
+	 * Get the GT timer Frame data for every GT Block Timer
+	 */
+	for (i = 0, j = 0; i < block->timer_count; i++) {
+		frame = gtdt_gt_timer_frame(block, i);
+		if (!frame || !frame->base_address || !frame->timer_interrupt) {
+			pr_err(FW_BUG "invalid GT Block Timer data, skip.\n");
+			continue;
+		}
+		block_data->timer[j].frame_nr = frame->frame_number;
+		block_data->timer[j].cntbase_phy = frame->base_address;
+		block_data->timer[j].irq = map_generic_timer_interrupt(
+						   frame->timer_interrupt,
+						   frame->timer_flags);
+		if (frame->virtual_timer_interrupt)
+			block_data->timer[j].virt_irq =
+				map_generic_timer_interrupt(
+					frame->virtual_timer_interrupt,
+					frame->virtual_timer_flags);
+		j++;
+	}
+
+	if (j)
+		return 0;
+
+	block_data->cntctlbase_phy = (phys_addr_t)NULL;
+	block_data->timer_count = 0;
+
+	return -EINVAL;
+}
+
+/*
+ * Get the GT block info for memory-mapped timer from GTDT table.
+ * Please make sure we have called gtdt_arch_timer_init, because it helps to
+ * init the global variables.
+ */
+int __init gtdt_arch_timer_mem_init(struct gt_block_data *data)
+{
+	int ret = for_platform_timer(ACPI_GTDT_TYPE_TIMER_BLOCK,
+				     gtdt_parse_gt_block, (void *)data);
+
+	pr_info("found %d memory-mapped timer block.\n", ret);
+
+	return ret;
+}
+
+/*
+ * Initialize a SBSA generic Watchdog platform device info from GTDT
+ */
+static int __init gtdt_import_sbsa_gwdt(void *platform_timer,
+					int index, void *data)
+{
+	struct platform_device *pdev;
+	struct acpi_gtdt_watchdog *wd = platform_timer;
+	int irq = map_generic_timer_interrupt(wd->timer_interrupt,
+					      wd->timer_flags);
+	int no_irq = 1;
+
+	/*
+	 * According to SBSA specification the size of refresh and control
+	 * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 ? 0xFFF).
+	 */
+	struct resource res[] = {
+		DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
+		DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
+		DEFINE_RES_IRQ(irq),
+	};
+
+	pr_debug("a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x).\n",
+		 wd->refresh_frame_address, wd->control_frame_address,
+		 wd->timer_interrupt, wd->timer_flags);
+
+	if (!(wd->refresh_frame_address && wd->control_frame_address)) {
+		pr_err(FW_BUG "failed getting the Watchdog GT frame addr.\n");
+		return -EINVAL;
+	}
+
+	if (!wd->timer_interrupt)
+		pr_warn(FW_BUG "failed getting the Watchdog GT GSIV.\n");
+	else if (irq <= 0)
+		pr_warn("failed to map the Watchdog GT GSIV.\n");
+	else
+		no_irq = 0;
+
+	/*
+	 * Add a platform device named "sbsa-gwdt" to match the platform driver.
+	 * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
+	 * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
+	 * info below by matching this name.
+	 */
+	pdev = platform_device_register_simple("sbsa-gwdt", index, res,
+					       ARRAY_SIZE(res) - no_irq);
+	if (IS_ERR(pdev)) {
+		acpi_unregister_gsi(wd->timer_interrupt);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
+
+static int __init gtdt_sbsa_gwdt_init(void)
+{
+	struct acpi_table_header *table;
+	struct acpi_table_gtdt *gtdt;
+	int ret;
+
+	if (acpi_disabled)
+		return 0;
+
+	if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_GTDT, 0, &table)))
+		return -EINVAL;
+
+	/* global variables initialization */
+	gtdt_end = (void *)table + table->length;
+	gtdt = container_of(table, struct acpi_table_gtdt, header);
+	platform_timer_struct = (void *)gtdt + gtdt->platform_timer_offset;
+
+	ret = for_platform_timer(ACPI_GTDT_TYPE_WATCHDOG,
+				 gtdt_import_sbsa_gwdt, NULL);
+	pr_info("found %d SBSA generic Watchdog.\n", ret);
+
+	return 0;
+}
+
+device_initcall(gtdt_sbsa_gwdt_init);
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 16dcd10..4e5b2a2 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -21,6 +21,7 @@
 
 #define ARCH_CP15_TIMER			BIT(0)
 #define ARCH_MEM_TIMER			BIT(1)
+#define ARCH_WD_TIMER			BIT(2)
 
 #define ARCH_TIMER_CTRL_ENABLE		(1 << 0)
 #define ARCH_TIMER_CTRL_IT_MASK		(1 << 1)
@@ -56,6 +57,8 @@ enum spi_nr {
 #define ARCH_TIMER_MEM_PHYS_ACCESS	2
 #define ARCH_TIMER_MEM_VIRT_ACCESS	3
 
+#define ARCH_TIMER_MEM_MAX_FRAME	8
+
 #define ARCH_TIMER_USR_PCT_ACCESS_EN	(1 << 0) /* physical counter */
 #define ARCH_TIMER_USR_VCT_ACCESS_EN	(1 << 1) /* virtual counter */
 #define ARCH_TIMER_VIRT_EVT_EN		(1 << 2)
@@ -71,6 +74,19 @@ struct arch_timer_kvm_info {
 	int virtual_irq;
 };
 
+struct gt_timer_data {
+	int frame_nr;
+	phys_addr_t cntbase_phy;
+	int irq;
+	int virt_irq;
+};
+
+struct gt_block_data {
+	phys_addr_t cntctlbase_phy;
+	int timer_count;
+	struct gt_timer_data timer[ARCH_TIMER_MEM_MAX_FRAME];
+};
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 288fac5..53b35d4 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -532,6 +532,12 @@ void acpi_walk_dep_device_list(acpi_handle handle);
 struct platform_device *acpi_create_platform_device(struct acpi_device *);
 #define ACPI_PTR(_ptr)	(_ptr)
 
+#ifdef CONFIG_ACPI_GTDT
+int __init gtdt_arch_timer_init(struct acpi_table_header *table, int *ppi,
+				bool *c3stop, u32 *timer_count);
+int __init gtdt_arch_timer_mem_init(struct gt_block_data *data);
+#endif
+
 #else	/* !CONFIG_ACPI */
 
 #define acpi_disabled 1
-- 
2.5.5



From fu.wei at linaro.org  Tue May 24 06:30:32 2016
From: fu.wei at linaro.org (fu.wei at linaro.org)
Date: Tue, 24 May 2016 21:30:32 +0800
Subject: [PATCH v5 5/6] clocksource/drivers/arm_arch_timer: Simplify ACPI
 support code.
In-Reply-To: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
References: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
Message-ID: <1464096633-9309-6-git-send-email-fu.wei@linaro.org>

From: Fu Wei <fu.wei at linaro.org>

The patch update arm_arch_timer driver to use the function
provided by the new GTDT driver of ACPI.
By this way, arm_arch_timer.c can be simplified, and separate
all the ACPI GTDT knowledge from this timer driver.

Signed-off-by: Fu Wei <fu.wei at linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
---
 drivers/clocksource/Kconfig          |  1 +
 drivers/clocksource/arm_arch_timer.c | 45 ++++--------------------------------
 2 files changed, 6 insertions(+), 40 deletions(-)

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 47352d2..5a5baa1 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -8,6 +8,7 @@ config CLKSRC_OF
 config CLKSRC_ACPI
 	bool
 	select CLKSRC_PROBE
+	select ACPI_GTDT
 
 config CLKSRC_PROBE
 	bool
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 9540e9d..505e65c 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -848,60 +848,25 @@ out:
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
 		       arch_timer_mem_init);
 
-#ifdef CONFIG_ACPI
-static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
-{
-	int trigger, polarity;
-
-	if (!interrupt)
-		return 0;
-
-	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
-			: ACPI_LEVEL_SENSITIVE;
-
-	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
-			: ACPI_ACTIVE_HIGH;
-
-	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
-}
-
+#ifdef CONFIG_ACPI_GTDT
 /* Initialize per-processor generic timer */
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
-	struct acpi_table_gtdt *gtdt;
-
 	if (arch_timers_present & ARCH_CP15_TIMER) {
 		pr_warn("already initialized, skipping\n");
 		return -EINVAL;
 	}
 
-	gtdt = container_of(table, struct acpi_table_gtdt, header);
-
 	arch_timers_present |= ARCH_CP15_TIMER;
 
-	arch_timer_ppi[PHYS_SECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
-		gtdt->secure_el1_flags);
-
-	arch_timer_ppi[PHYS_NONSECURE_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
-		gtdt->non_secure_el1_flags);
-
-	arch_timer_ppi[VIRT_PPI] =
-		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
-		gtdt->virtual_timer_flags);
-
-	arch_timer_ppi[HYP_PPI] =
-		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
-		gtdt->non_secure_el2_flags);
+	if (gtdt_arch_timer_init(table, arch_timer_ppi, &arch_timer_c3stop,
+				 NULL))
+		return -EINVAL;
 
 	/* Get the frequency from CNTFRQ */
 	arch_timer_detect_rate(NULL, NULL);
-
-	/* Always-on capability */
-	arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
-
 	arch_timer_init();
+
 	return 0;
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
-- 
2.5.5



From fu.wei at linaro.org  Tue May 24 06:30:33 2016
From: fu.wei at linaro.org (fu.wei at linaro.org)
Date: Tue, 24 May 2016 21:30:33 +0800
Subject: [PATCH v5 6/6] clocksource/drivers/arm_arch_timer: Add GTDT support
 for memory-mapped timer
In-Reply-To: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
References: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
Message-ID: <1464096633-9309-7-git-send-email-fu.wei@linaro.org>

From: Fu Wei <fu.wei at linaro.org>

The patch add memory-mapped timer register support by using the information
provided by the new GTDT driver of ACPI.

Signed-off-by: Fu Wei <fu.wei at linaro.org>
---
 drivers/clocksource/arm_arch_timer.c | 147 +++++++++++++++++++++++++++++++++--
 1 file changed, 142 insertions(+), 5 deletions(-)

diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 505e65c..3ac0fda 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -849,24 +849,161 @@ CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
 		       arch_timer_mem_init);
 
 #ifdef CONFIG_ACPI_GTDT
-/* Initialize per-processor generic timer */
+static struct gt_timer_data __init *arch_timer_mem_get_timer(
+						struct gt_block_data *gt_blocks)
+{
+	struct gt_block_data *gt_block = gt_blocks;
+	struct gt_timer_data *best_frame = NULL;
+	void __iomem *cntctlbase;
+	u32 cnttidr;
+	int i;
+
+	/*
+	 * According to ARMv8 Architecture Reference Manual(ARM),
+	 * the size of CNTCTLBase frame of memory-mapped timer
+	 * is SZ_4K(Offset 0x000 ? 0xFFF).
+	 */
+	cntctlbase = ioremap(gt_block->cntctlbase_phy, SZ_4K);
+	if (!cntctlbase) {
+		pr_err("Can't map CNTCTLBase\n");
+		return NULL;
+	}
+	cnttidr = readl_relaxed(cntctlbase + CNTTIDR);
+
+	/*
+	 * Try to find a virtual capable frame. Otherwise fall back to a
+	 * physical capable frame.
+	 */
+	for (i = 0; i < gt_block->timer_count; i++) {
+		int n;
+		u32 cntacr;
+
+		n = gt_block->timer[i].frame_nr;
+
+		/* Try enabling everything, and see what sticks */
+		cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
+			 CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
+		writel_relaxed(cntacr, cntctlbase + CNTACR(n));
+		cntacr = readl_relaxed(cntctlbase + CNTACR(n));
+
+		if ((cnttidr & CNTTIDR_VIRT(n)) &&
+		    !(~cntacr & (CNTACR_RWVT | CNTACR_RVCT))) {
+			best_frame = &gt_block->timer[i];
+			arch_timer_mem_use_virtual = true;
+			break;
+		}
+
+		if (~cntacr & (CNTACR_RWPT | CNTACR_RPCT))
+			continue;
+
+		best_frame = &gt_block->timer[i];
+	}
+	iounmap(cntctlbase);
+
+	return best_frame;
+}
+
+static int __init arch_timer_mem_acpi_init(u32 timer_count)
+{
+	struct gt_block_data *gt_blocks;
+	struct gt_timer_data *gt_timer;
+	void __iomem *timer_cntbase;
+	int ret = -EINVAL;
+	int timer_irq;
+
+	/*
+	 * If we have some Platform Timer Structures,
+	 * try to find and register a memory-mapped timer.
+	 * If not, just return.
+	 */
+	if (!timer_count)
+		return 0;
+
+	if (arch_timers_present & ARCH_MEM_TIMER) {
+		pr_warn("memory-mapped timer already initialized, skipping\n");
+		return 0;
+	}
+	arch_timers_present |= ARCH_MEM_TIMER;
+	/*
+	 * before really check all the Platform Timer Structures,
+	 * we assume they are GT block, and allocate memory for them.
+	 * We will free these memory once we finish the initialization.
+	 */
+	gt_blocks = kcalloc(timer_count, sizeof(*gt_blocks), GFP_KERNEL);
+	if (!gt_blocks)
+		return -ENOMEM;
+
+	if (gtdt_arch_timer_mem_init(gt_blocks)) {
+		gt_timer = arch_timer_mem_get_timer(gt_blocks);
+		if (!gt_timer) {
+			pr_err("Failed to get mem timer info.\n");
+			goto error;
+		}
+
+		if (arch_timer_mem_use_virtual)
+			timer_irq = gt_timer->virt_irq;
+		else
+			timer_irq = gt_timer->irq;
+		if (!timer_irq) {
+			pr_err("Frame missing %s irq",
+			       arch_timer_mem_use_virtual ? "virt" : "phys");
+			goto error;
+		}
+
+		/*
+		 * According to ARMv8 Architecture Reference Manual(ARM),
+		 * the size of CNTBaseN frames of memory-mapped timer
+		 * is SZ_4K(Offset 0x000 ? 0xFFF).
+		 */
+		timer_cntbase = ioremap(gt_timer->cntbase_phy, SZ_4K);
+		if (!timer_cntbase) {
+			pr_err("Can't map CntBase.\n");
+			goto error;
+		}
+		arch_counter_base = timer_cntbase;
+		ret = arch_timer_mem_register(timer_cntbase, timer_irq);
+		if (ret) {
+			iounmap(timer_cntbase);
+			arch_counter_base = NULL;
+			pr_err("Failed to register mem timer.\n");
+		}
+	}
+
+error:
+	kfree(gt_blocks);
+	return ret;
+}
+
+/* Initialize per-processor generic timer and memory-mapped timer(if present) */
 static int __init arch_timer_acpi_init(struct acpi_table_header *table)
 {
+	u32 timer_count;
+
 	if (arch_timers_present & ARCH_CP15_TIMER) {
 		pr_warn("already initialized, skipping\n");
 		return -EINVAL;
 	}
-
 	arch_timers_present |= ARCH_CP15_TIMER;
 
+	/*
+	 * Get the per-processor generic timer info.
+	 */
 	if (gtdt_arch_timer_init(table, arch_timer_ppi, &arch_timer_c3stop,
-				 NULL))
+				 &timer_count))
 		return -EINVAL;
 
-	/* Get the frequency from CNTFRQ */
+	/*
+	 * Because in a system that implements both Secure and
+	 * Non-secure states, CNTFRQ is only accessible in Secure state.
+	 * So we just try to get the system counter frequency from cntfrq_el0
+	 * (system coprocessor register) here .
+	 */
 	arch_timer_detect_rate(NULL, NULL);
-	arch_timer_init();
 
+	if (arch_timer_mem_acpi_init(timer_count))
+		pr_err("Failed to initialize memory-mapped timer, skipping\n");
+
+	arch_timer_init();
 	return 0;
 }
 CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
-- 
2.5.5



From nm at ti.com  Tue May 24 06:35:37 2016
From: nm at ti.com (Nishanth Menon)
Date: Tue, 24 May 2016 08:35:37 -0500
Subject: [PATCH 0/3] ARM: OMAP: DRA7: Update to latest TRM and cleanup
Message-ID: <1464096940-27145-1-git-send-email-nm@ti.com>

Hi,

Here are the final(hopefully) pending patches for DRA7 based on recent
TRM updates. Updates include removing retention support on L3init and
L4per as per latest SoC updates.

Test Log: X15 (no modules): http://pastebin.ubuntu.com/16655027/

Latest TRM (rev F): http://www.ti.com/lit/pdf/spruhz6 (public on May 18)

Nishanth Menon (3):
  ARM: OMAP: DRA7: powerdomain data: Set L3init and L4per to ON
  ARM: OMAP: DRA7: powerdomain data: Remove unused pwrsts_logic_ret
  ARM: OMAP: DRA7: powerdomain data: Remove unused pwrsts_mem_ret

 arch/arm/mach-omap2/powerdomains7xx_data.c | 76 +-----------------------------
 1 file changed, 2 insertions(+), 74 deletions(-)

-- 
2.8.0



From nm at ti.com  Tue May 24 06:35:39 2016
From: nm at ti.com (Nishanth Menon)
Date: Tue, 24 May 2016 08:35:39 -0500
Subject: [PATCH 2/3] ARM: OMAP: DRA7: powerdomain data: Remove unused
 pwrsts_logic_ret
In-Reply-To: <1464096940-27145-1-git-send-email-nm@ti.com>
References: <1464096940-27145-1-git-send-email-nm@ti.com>
Message-ID: <1464096940-27145-3-git-send-email-nm@ti.com>

As per the latest revision F of public TRM for DRA7/AM57xx SoCs
SPRUHZ6F[1] (April 2016), with the exception of MPU power domain (and
CPUx sub power domains), all other power domains can either operate
in "ON" mode OR in some cases, "OFF" mode. For these power states,
the logic retention state is basically ignored by PRCM and does not
require to be programmed.

[1] http://www.ti.com/lit/pdf/spruhz6

Signed-off-by: Nishanth Menon <nm at ti.com>
---
 arch/arm/mach-omap2/powerdomains7xx_data.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomains7xx_data.c b/arch/arm/mach-omap2/powerdomains7xx_data.c
index 8ea447ed4dc4..88107b449710 100644
--- a/arch/arm/mach-omap2/powerdomains7xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains7xx_data.c
@@ -36,7 +36,6 @@ static struct powerdomain iva_7xx_pwrdm = {
 	.prcm_offs	  = DRA7XX_PRM_IVA_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 4,
 	.pwrsts_mem_ret	= {
 		[0] = PWRSTS_OFF_RET,	/* hwa_mem */
@@ -76,7 +75,6 @@ static struct powerdomain ipu_7xx_pwrdm = {
 	.prcm_offs	  = DRA7XX_PRM_IPU_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 2,
 	.pwrsts_mem_ret	= {
 		[0] = PWRSTS_OFF_RET,	/* aessmem */
@@ -95,7 +93,6 @@ static struct powerdomain dss_7xx_pwrdm = {
 	.prcm_offs	  = DRA7XX_PRM_DSS_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
 		[0] = PWRSTS_OFF_RET,	/* dss_mem */
@@ -112,7 +109,6 @@ static struct powerdomain l4per_7xx_pwrdm = {
 	.prcm_offs	  = DRA7XX_PRM_L4PER_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_ON,
-	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 2,
 	.pwrsts_mem_ret	= {
 		[0] = PWRSTS_OFF_RET,	/* nonretained_bank */
@@ -161,7 +157,6 @@ static struct powerdomain core_7xx_pwrdm = {
 	.prcm_offs	  = DRA7XX_PRM_CORE_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_ON,
-	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 5,
 	.pwrsts_mem_ret	= {
 		[0] = PWRSTS_OFF_RET,	/* core_nret_bank */
@@ -226,7 +221,6 @@ static struct powerdomain vpe_7xx_pwrdm = {
 	.prcm_offs	  = DRA7XX_PRM_VPE_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
 		[0] = PWRSTS_OFF_RET,	/* vpe_bank */
@@ -261,7 +255,6 @@ static struct powerdomain l3init_7xx_pwrdm = {
 	.prcm_offs	  = DRA7XX_PRM_L3INIT_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_ON,
-	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 3,
 	.pwrsts_mem_ret	= {
 		[0] = PWRSTS_OFF_RET,	/* gmac_bank */
-- 
2.8.0



From nm at ti.com  Tue May 24 06:35:38 2016
From: nm at ti.com (Nishanth Menon)
Date: Tue, 24 May 2016 08:35:38 -0500
Subject: [PATCH 1/3] ARM: OMAP: DRA7: powerdomain data: Set L3init and L4per
 to ON
In-Reply-To: <1464096940-27145-1-git-send-email-nm@ti.com>
References: <1464096940-27145-1-git-send-email-nm@ti.com>
Message-ID: <1464096940-27145-2-git-send-email-nm@ti.com>

As per the latest revision F of public TRM for DRA7/AM57xx SoCs
SPRUHZ6F[1] (April 2016), L4Per and L3init power domains now operate in
always "ON" mode due to asymmetric aging limitations. Update the same

[1] http://www.ti.com/lit/pdf/spruhz6

Signed-off-by: Nishanth Menon <nm at ti.com>
---
 arch/arm/mach-omap2/powerdomains7xx_data.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomains7xx_data.c b/arch/arm/mach-omap2/powerdomains7xx_data.c
index 0ec2d00f4237..8ea447ed4dc4 100644
--- a/arch/arm/mach-omap2/powerdomains7xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains7xx_data.c
@@ -111,7 +111,7 @@ static struct powerdomain l4per_7xx_pwrdm = {
 	.name		  = "l4per_pwrdm",
 	.prcm_offs	  = DRA7XX_PRM_L4PER_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
-	.pwrsts		  = PWRSTS_RET_ON,
+	.pwrsts		  = PWRSTS_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 2,
 	.pwrsts_mem_ret	= {
@@ -260,7 +260,7 @@ static struct powerdomain l3init_7xx_pwrdm = {
 	.name		  = "l3init_pwrdm",
 	.prcm_offs	  = DRA7XX_PRM_L3INIT_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
-	.pwrsts		  = PWRSTS_RET_ON,
+	.pwrsts		  = PWRSTS_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 3,
 	.pwrsts_mem_ret	= {
-- 
2.8.0



From nm at ti.com  Tue May 24 06:35:40 2016
From: nm at ti.com (Nishanth Menon)
Date: Tue, 24 May 2016 08:35:40 -0500
Subject: [PATCH 3/3] ARM: OMAP: DRA7: powerdomain data: Remove unused
 pwrsts_mem_ret
In-Reply-To: <1464096940-27145-1-git-send-email-nm@ti.com>
References: <1464096940-27145-1-git-send-email-nm@ti.com>
Message-ID: <1464096940-27145-4-git-send-email-nm@ti.com>

As per the latest revision F of public TRM for DRA7/AM57xx SoCs
SPRUHZ6F[1] (April 2016), with the exception of MPU power domain, all
other power domains do not have memories capable of retention since
they all operate in either "ON" or "OFF" mode. For these power states,
the retention state for memories are basically ignored by PRCM and does
not require to be programmed.

[1] http://www.ti.com/lit/pdf/spruhz6

Signed-off-by: Nishanth Menon <nm at ti.com>
---
 arch/arm/mach-omap2/powerdomains7xx_data.c | 65 ------------------------------
 1 file changed, 65 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomains7xx_data.c b/arch/arm/mach-omap2/powerdomains7xx_data.c
index 88107b449710..eb350a673133 100644
--- a/arch/arm/mach-omap2/powerdomains7xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains7xx_data.c
@@ -37,12 +37,6 @@ static struct powerdomain iva_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 4,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* hwa_mem */
-		[1] = PWRSTS_OFF_RET,	/* sl2_mem */
-		[2] = PWRSTS_OFF_RET,	/* tcm1_mem */
-		[3] = PWRSTS_OFF_RET,	/* tcm2_mem */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* hwa_mem */
 		[1] = PWRSTS_ON,	/* sl2_mem */
@@ -76,10 +70,6 @@ static struct powerdomain ipu_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 2,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* aessmem */
-		[1] = PWRSTS_OFF_RET,	/* periphmem */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* aessmem */
 		[1] = PWRSTS_ON,	/* periphmem */
@@ -94,9 +84,6 @@ static struct powerdomain dss_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* dss_mem */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* dss_mem */
 	},
@@ -110,10 +97,6 @@ static struct powerdomain l4per_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 2,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* nonretained_bank */
-		[1] = PWRSTS_OFF_RET,	/* retained_bank */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* nonretained_bank */
 		[1] = PWRSTS_ON,	/* retained_bank */
@@ -128,9 +111,6 @@ static struct powerdomain gpu_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* gpu_mem */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* gpu_mem */
 	},
@@ -144,8 +124,6 @@ static struct powerdomain wkupaon_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* wkup_bank */
 	},
@@ -158,13 +136,6 @@ static struct powerdomain core_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 5,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* core_nret_bank */
-		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
-		[2] = PWRSTS_OFF_RET,	/* core_other_bank */
-		[3] = PWRSTS_OFF_RET,	/* ipu_l2ram */
-		[4] = PWRSTS_OFF_RET,	/* ipu_unicache */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* core_nret_bank */
 		[1] = PWRSTS_ON,	/* core_ocmram */
@@ -222,9 +193,6 @@ static struct powerdomain vpe_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* vpe_bank */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* vpe_bank */
 	},
@@ -256,11 +224,6 @@ static struct powerdomain l3init_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 3,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* gmac_bank */
-		[1] = PWRSTS_OFF_RET,	/* l3init_bank1 */
-		[2] = PWRSTS_OFF_RET,	/* l3init_bank2 */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* gmac_bank */
 		[1] = PWRSTS_ON,	/* l3init_bank1 */
@@ -276,9 +239,6 @@ static struct powerdomain eve3_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* eve3_bank */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* eve3_bank */
 	},
@@ -292,9 +252,6 @@ static struct powerdomain emu_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* emu_bank */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* emu_bank */
 	},
@@ -307,11 +264,6 @@ static struct powerdomain dsp2_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 3,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* dsp2_edma */
-		[1] = PWRSTS_OFF_RET,	/* dsp2_l1 */
-		[2] = PWRSTS_OFF_RET,	/* dsp2_l2 */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* dsp2_edma */
 		[1] = PWRSTS_ON,	/* dsp2_l1 */
@@ -327,11 +279,6 @@ static struct powerdomain dsp1_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 3,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* dsp1_edma */
-		[1] = PWRSTS_OFF_RET,	/* dsp1_l1 */
-		[2] = PWRSTS_OFF_RET,	/* dsp1_l2 */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* dsp1_edma */
 		[1] = PWRSTS_ON,	/* dsp1_l1 */
@@ -347,9 +294,6 @@ static struct powerdomain cam_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* vip_bank */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* vip_bank */
 	},
@@ -363,9 +307,6 @@ static struct powerdomain eve4_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* eve4_bank */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* eve4_bank */
 	},
@@ -379,9 +320,6 @@ static struct powerdomain eve2_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* eve2_bank */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* eve2_bank */
 	},
@@ -395,9 +333,6 @@ static struct powerdomain eve1_7xx_pwrdm = {
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* eve1_bank */
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* eve1_bank */
 	},
-- 
2.8.0



From tjakobi at math.uni-bielefeld.de  Tue May 24 06:49:25 2016
From: tjakobi at math.uni-bielefeld.de (Tobias Jakobi)
Date: Tue, 24 May 2016 15:49:25 +0200
Subject: [PATCH 1/2] drm/exynos: g2d: Add support for old S5Pv210 type
In-Reply-To: <1464096493-13378-1-git-send-email-k.kozlowski@samsung.com>
References: <1464096493-13378-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <57445BE5.7060702@math.uni-bielefeld.de>

Hello Krzysztof,

are you sure that these are the only differences. Because AFAIK there
are quite a few more:
- DMA submission of commands
- blend mode / rounding
- solid fill
- YCrCb support
- and probably more

One would need to add least split the command list parser into a v3 and
v41 version to accomodate for the differences. In fact userspace/libdrm
would need to know which hw type it currently uses, but you currently
always return 4.1 in the corresponding ioctl.


Krzysztof Kozlowski wrote:
> The non-DRM s5p-g2d driver supports two versions of G2D: v3.0 on
> S5Pv210 and v4.x on Exynos 4x12 (or newer). The driver for 3.0 device
> version is doing two things differently:
> 1. Before starting the render process, it invalidates caches (pattern,
>    source buffer and mask buffer). Cache control is not present on v4.x
>    device.
> 2. Scalling is done through StretchEn command (in BITBLT_COMMAND_REG
>    register) instead of SRC_SCALE_CTRL_REG as in v4.x. However the
>    exynos_drm_g2d driver does not implement the scalling so this
>    difference can be eliminated.
Huh? Where did you get this from? Scaling works with the DRM driver.


With best wishes,
Tobias


> After adding support for v3.0 to exynos_drm_g2d driver, the old driver
> can be removed.
> 
> Cc: Kyungmin Park <kyungmin.park at samsung.com>
> Cc: Kamil Debski <k.debski at samsung.com>
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_g2d.c | 37 +++++++++++++++++++++++++++++++--
>  drivers/gpu/drm/exynos/exynos_drm_g2d.h |  7 +++++++
>  2 files changed, 42 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> index 493552368295..44d8b28e9d98 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> @@ -19,6 +19,7 @@
>  #include <linux/dma-mapping.h>
>  #include <linux/dma-attrs.h>
>  #include <linux/of.h>
> +#include <linux/of_device.h>
>  
>  #include <drm/drmP.h>
>  #include <drm/exynos_drm.h>
> @@ -38,6 +39,7 @@
>  #define G2D_SOFT_RESET			0x0000
>  #define G2D_INTEN			0x0004
>  #define G2D_INTC_PEND			0x000C
> +#define G2D_CACHECTL			0x0018 /* S5PV210 specific */
>  #define G2D_DMA_SFR_BASE_ADDR		0x0080
>  #define G2D_DMA_COMMAND			0x0084
>  #define G2D_DMA_STATUS			0x008C
> @@ -78,6 +80,11 @@
>  #define G2D_INTP_GCMD_FIN		(1 << 1)
>  #define G2D_INTP_SCMD_FIN		(1 << 0)
>  
> +/* G2D_CACHECTL, S5PV210 specific */
> +#define G2D_CACHECTL_PATCACHE		(BIT(2))
> +#define G2D_CACHECTL_SRCBUFFER		(BIT(1))
> +#define G2D_CACHECTL_MASKBUFFER		(BIT(0))
> +
>  /* G2D_DMA_COMMAND */
>  #define G2D_DMA_HALT			(1 << 2)
>  #define G2D_DMA_CONTINUE		(1 << 1)
> @@ -245,6 +252,7 @@ struct g2d_data {
>  
>  	unsigned long			current_pool;
>  	unsigned long			max_pool;
> +	enum exynos_drm_g2d_type	type;
>  };
>  
>  static int g2d_init_cmdlist(struct g2d_data *g2d)
> @@ -1125,6 +1133,13 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
>  	cmdlist->data[cmdlist->last++] = G2D_SRC_BASE_ADDR;
>  	cmdlist->data[cmdlist->last++] = 0;
>  
> +	if (g2d->type == EXYNOS_DRM_G2D_TYPE_3X) {
> +		cmdlist->data[cmdlist->last++] = G2D_CACHECTL;
> +		cmdlist->data[cmdlist->last++] = G2D_CACHECTL_PATCACHE |
> +						 G2D_CACHECTL_SRCBUFFER |
> +						 G2D_CACHECTL_MASKBUFFER;
> +	}
> +
>  	/*
>  	 * 'LIST_HOLD' command should be set to the DMA_HOLD_CMD_REG
>  	 * and GCF bit should be set to INTEN register if user wants
> @@ -1369,10 +1384,20 @@ static int g2d_probe(struct platform_device *pdev)
>  	struct exynos_drm_subdrv *subdrv;
>  	int ret;
>  
> +	/* Sanity check, we can be instatiated only from DT */
> +	if (!dev->of_node)
> +		return -EINVAL;
> +
>  	g2d = devm_kzalloc(dev, sizeof(*g2d), GFP_KERNEL);
>  	if (!g2d)
>  		return -ENOMEM;
>  
> +	g2d->type = (enum exynos_drm_g2d_type)of_device_get_match_data(dev);
> +	if (g2d->type == EXYNOS_DRM_G2D_TYPE_UNKNOWN) {
> +		dev_err(dev, "failed to get type of device\n");
> +		return -EINVAL;
> +	}
> +
>  	g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab",
>  			sizeof(struct g2d_runqueue_node), 0, 0, NULL);
>  	if (!g2d->runqueue_slab)
> @@ -1535,8 +1560,16 @@ static const struct dev_pm_ops g2d_pm_ops = {
>  };
>  
>  static const struct of_device_id exynos_g2d_match[] = {
> -	{ .compatible = "samsung,exynos5250-g2d" },
> -	{ .compatible = "samsung,exynos4212-g2d" },
> +	{
> +		.compatible = "samsung,exynos5250-g2d",
> +		.data = (void *)EXYNOS_DRM_G2D_TYPE_4X,
> +	}, {
> +		.compatible = "samsung,exynos4212-g2d",
> +		.data = (void *)EXYNOS_DRM_G2D_TYPE_4X,
> +	}, {
> +		.compatible = "samsung,s5pv210-g2d",
> +		.data = (void *)EXYNOS_DRM_G2D_TYPE_3X,
> +	},
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, exynos_g2d_match);
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.h b/drivers/gpu/drm/exynos/exynos_drm_g2d.h
> index 1a9c7ca8c15b..84ec8aff6f0a 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.h
> +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.h
> @@ -7,6 +7,13 @@
>   * published by the Free Software Foundationr
>   */
>  
> +enum exynos_drm_g2d_type {
> +	EXYNOS_DRM_G2D_TYPE_UNKNOWN,
> +
> +	EXYNOS_DRM_G2D_TYPE_3X,
> +	EXYNOS_DRM_G2D_TYPE_4X,
> +};
> +
>  #ifdef CONFIG_DRM_EXYNOS_G2D
>  extern int exynos_g2d_get_ver_ioctl(struct drm_device *dev, void *data,
>  				    struct drm_file *file_priv);
> 



From k.kozlowski at samsung.com  Tue May 24 06:58:46 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 24 May 2016 15:58:46 +0200
Subject: [PATCH 1/2] drm/exynos: g2d: Add support for old S5Pv210 type
In-Reply-To: <57445BE5.7060702@math.uni-bielefeld.de>
References: <1464096493-13378-1-git-send-email-k.kozlowski@samsung.com>
 <57445BE5.7060702@math.uni-bielefeld.de>
Message-ID: <57445E16.90301@samsung.com>

On 05/24/2016 03:49 PM, Tobias Jakobi wrote:
> Hello Krzysztof,
> 
> are you sure that these are the only differences. Because AFAIK there
> are quite a few more:
> - DMA submission of commands
> - blend mode / rounding
> - solid fill
> - YCrCb support
> - and probably more
> 
> One would need to add least split the command list parser into a v3 and
> v41 version to accomodate for the differences. In fact userspace/libdrm
> would need to know which hw type it currently uses, but you currently
> always return 4.1 in the corresponding ioctl.

Eh, so probably my patch does not cover fully the support for v3 G2D. I
looked mostly at the differences between v3 and v4 in the s5p-g2d driver
itself. However you are right that this might be not sufficient because
exynos-g2d moved forward and is different than s5p-g2d.

> Krzysztof Kozlowski wrote:
>> The non-DRM s5p-g2d driver supports two versions of G2D: v3.0 on
>> S5Pv210 and v4.x on Exynos 4x12 (or newer). The driver for 3.0 device
>> version is doing two things differently:
>> 1. Before starting the render process, it invalidates caches (pattern,
>>    source buffer and mask buffer). Cache control is not present on v4.x
>>    device.
>> 2. Scalling is done through StretchEn command (in BITBLT_COMMAND_REG
>>    register) instead of SRC_SCALE_CTRL_REG as in v4.x. However the
>>    exynos_drm_g2d driver does not implement the scalling so this
>>    difference can be eliminated.
> Huh? Where did you get this from? Scaling works with the DRM driver.

I was looking for the usage of scaling reg (as there is no scaling
command). How the scaling is implemented then?

Thanks for feedback!

Best regards,
Krzysztof



From arnd at arndb.de  Tue May 24 07:00:06 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 24 May 2016 16:00:06 +0200
Subject: [PATCH V5 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <000601d1b4b9$119c2410$34d46c30$@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
 <3164695.VzCnHHyi7r@wuerfel> <000601d1b4b9$119c2410$34d46c30$@codeaurora.org>
Message-ID: <7555154.mU2oTAdECP@wuerfel>

On Monday, May 23, 2016 11:35:04 AM CEST Sricharan wrote:
> Hi Arnd,
> 
> >> @@ -124,6 +124,9 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
> >>  		SET_TLBLKCR(base, ctx, 0);
> >>  		SET_CONTEXTIDR(base, ctx, 0);
> >>  	}
> >> +
> >> +	/* Ensure completion of relaxed writes from the above SET macros */
> >> +	mb();
> >>  }
> >
> >Why do the above use the relaxed writes? Do you have any performance
> >numbers showing that skipping the sync for the reset makes a measurable
> >difference?
> >
> >How did you prove that skipping the sync before the write is safe?
> >
> >How about resetting the iommu less often instead?
> >
> 
> I had measured the numbers only for the full usecase path, not for the
> reset path alone. I saw improvement of about 5% on full numbers.
> As you said, the reset path would be called only less often
> and might not bring a measurable change. I did not see a difference in behavior
> when changing the sync to happen after the writes.

Ok, then better not change it.

> But my understanding was that
> the sync after the writes was required to ensure write completion. 

Can you cite the relevant documentation on this? Is this specific
to the Qualcomm CPU implementation or the IOMMU? I don't think
the ARM architecture requires anything like this in general.

> I should have made smaller patches to do this change.
> The only patch relevant for this series is the one that changes the write in _iotlb_range
> function. Rest of the changes, should be added one by one in a separate series.

If you see the same 5% performance improvement with a simpler change, then
better do only that. The IOMMU infrastructure is rather sensitive to
having correct barriers everywhere, so this minimizes the risk of getting
it wrong somewhere.


> >> @@ -181,7 +187,8 @@ fail:
> >>
> >>  static void __flush_iotlb_sync(void *cookie)
> >>  {
> >> -	/* To avoid a null function pointer */
> >> +	/* To ensure completion of the TLBIVA in __flush_iotlb_range */
> >> +	mb();
> >>  }
> >
> >I don't understand the specific race from the comment.
> >
> >What operation comes after this that relies on __flush_iotlb_range
> >having completed, and how does an mb() guarantee this?
> >
> 
> The flush_iotlb_range operation invalidates the tlb for writes to
> pagetable and the finally calls the sync operation to ensure completion
> of the flush and this is required before returning back to the client
> of the iommu. In the case of this iommu, only a barrier is required to
> ensure completion of the invalidate operation. 

This doesn't answer my question: What operation would a client do
that requires the flush to be completed here? A barrier is always
defined in terms of things that come before it in combination with
things that come after it.

Any operation that could trigger a DMA from a device is required
to have a barrier preceding it (usually wmb() one implied by writel()),
so this is clearly not about a driver that installs a DMA mapping
before starting a DMA, but I don't see what else it would be.

> >This seems to be a bug fix that is unrelated to the change to
> >use writel_relaxed(), so better split it out into a separate
> >patch, with a longer changeset description. Did you spot this
> >race by running into incorrect data, or by inspection?
> >
> 
> No i did not see a data corruption issue without the mb(),
> but that it would have been hidden in someother way as well.
> Another difference was the sync  was done before the write
> previously and now its moved after the write. As i understand
> sync after the write is correct. So i will change this patch with more
> description and move rest of that changes out.

Ok.

> >> @@ -500,7 +516,8 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
> >>  	/* Invalidate context TLB */
> >>  	SET_CTX_TLBIALL(iommu->base, master->num, 0);
> >>  	SET_V2PPR(iommu->base, master->num, va & V2Pxx_VA);
> >> -
> >> +	/* Ensure completion of relaxed writes from the above SET macros */
> >> +	mb();
> >>  	par = GET_PAR(iommu->base, master->num);
> >>
> >>  	/* We are dealing with a supersection */
> >
> >In this case, I'd say it's better to rewrite the function to avoid the
> >read: iova_to_phys() should be fast, and not require hardware access.
> >Getting rid of the hardware access by using an in-memory cache for
> >this should gain more than just removing the barriers, as an MMIO read
> >is always slow
> 
> Ok, you mean using the software walk through ? I will check on this to measure
>  the latency difference. If thats true, then the iopgtable ops itself provides a
> function for iova_to_phys conversion, so that can be used.

I hadn't realized that this is a lookup in the hardware, rather than
reading a static register. It's probably a good idea to check this
anyway.


	Arnd


From gabriele.paoloni at huawei.com  Tue May 24 07:33:43 2016
From: gabriele.paoloni at huawei.com (Gabriele Paoloni)
Date: Tue, 24 May 2016 14:33:43 +0000
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <426907D3-FBE7-458F-AB94-F64489AB0337@redhat.com>
References: <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>
 <20160523233918.GA32555@localhost>
 <426907D3-FBE7-458F-AB94-F64489AB0337@redhat.com>
Message-ID: <EE11001F9E5DDD47B7634E2F8A612F2E1EDB4C52@lhreml503-mbs>

Hi Jon

> -----Original Message-----
> From: Jon Masters [mailto:jcm at redhat.com]
> Sent: 24 May 2016 02:11
> To: Bjorn Helgaas
> Cc: Gabriele Paoloni; Lorenzo Pieralisi; Ard Biesheuvel; Tomasz
> Nowicki; arnd at arndb.de; will.deacon at arm.com; catalin.marinas at arm.com;
> rafael at kernel.org; hanjun.guo at linaro.org; okaya at codeaurora.org;
> jchandra at broadcom.com; linaro-acpi at lists.linaro.org; linux-
> pci at vger.kernel.org; dhdang at apm.com; Liviu.Dudau at arm.com;
> ddaney at caviumnetworks.com; jeremy.linton at arm.com; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org;
> robert.richter at caviumnetworks.com; Suravee.Suthikulpanit at amd.com;
> msalter at redhat.com; Wangyijing; mw at semihalf.com;
> andrea.gallo at linaro.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI host
> controller
> 
> Bjorn,
> 
> Out walking so sorry about top posting. Quick reply though:
> 
> 1. I checked with the Windows team. They usually avoid quirks entirely
> but when it has happened, it has been done via the MCFG/FADT not DSDT.
> 
> 2. They would be ok if we were to key off the OEM  name and revision
> for the IP in the MCFG table.

I see some problems with this approach:

1) We would need to modify the ACPI specs to accommodate quirks in the MCFG,
   correct?

2) Just adding OEM info would not fit some other people (like us for Designware
   based solutions). In our case for example the addresses defined in the MCFG
   are not compatible with the ones used by the Designware IP, therefore we would
   also need specific quirk data

I think that we can use an approach where we use MCFG entries for the ECAM
address spaces and motherboard reserved resources for those BUSes that are
outside the MCFG table and therefore are non ECAM.

I think it is a more generic approach that would suit anybody and there
is no need to redefine the ACPI specs for MCFG... ?

Thanks

Gab

> 
> 3. I have already verified existing shipping ARMv8 systems provide
> enough unique data in that entry, and have asked that vendors guarantee
> to rev it in future IP (which I will verify on models pre tapeout and
> certainly in early firmware builds). One vendor has a platform that
> isn't public yet that uses a non-public name in the MCFG but I spoke
> with them on Friday and they will shortly update their firmware so that
> a quirk could be posted.
> 
> 4. I have requested (and Linaro are investigating) that Linaro (with
> ARM's assistance) begin to drive a separate thread around upstreaming
> (independent of this core effort) quirks that use the OEM fields in the
> MCFG as a more scalable approach than one per platform via DMI.
> 
> 5. I will drive a clarification to the SBBR that does not encourage or
> endorse quirks but does merely reinforce that data must be unique in
> such tables. I am driving a separate series of conversations with
> vendors to ensure that this is the case on all future platforms -
> though just generally, there is no more high end top shelf "Xeon class"
> silicon needing common quirks in the pipeline.
> 
> More later.
> 
> Jon.
> 
> --
> Computer Architect | Sent from my 64-bit #ARM Powered phone
> 
> > On May 23, 2016, at 19:39, Bjorn Helgaas <helgaas at kernel.org> wrote:
> >
> >> On Mon, May 23, 2016 at 03:16:01PM +0000, Gabriele Paoloni wrote:
> >> Hi Lorenzo
> >>
> >>> -----Original Message-----
> >>> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
> >>> Sent: 23 May 2016 11:57
> >>> To: Ard Biesheuvel
> >>> Cc: Gabriele Paoloni; Jon Masters; Tomasz Nowicki;
> helgaas at kernel.org;
> >>> arnd at arndb.de; will.deacon at arm.com; catalin.marinas at arm.com;
> >>> rafael at kernel.org; hanjun.guo at linaro.org; okaya at codeaurora.org;
> >>> jchandra at broadcom.com; linaro-acpi at lists.linaro.org; linux-
> >>> pci at vger.kernel.org; dhdang at apm.com; Liviu.Dudau at arm.com;
> >>> ddaney at caviumnetworks.com; jeremy.linton at arm.com; linux-
> >>> kernel at vger.kernel.org; linux-acpi at vger.kernel.org;
> >>> robert.richter at caviumnetworks.com; Suravee.Suthikulpanit at amd.com;
> >>> msalter at redhat.com; Wangyijing; mw at semihalf.com;
> >>> andrea.gallo at linaro.org; linux-arm-kernel at lists.infradead.org
> >>> Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI
> host
> >>> controller
> >>>
> >>>> On Fri, May 20, 2016 at 11:14:03AM +0200, Ard Biesheuvel wrote:
> >>>> On 20 May 2016 at 10:40, Gabriele Paoloni
> >>> <gabriele.paoloni at huawei.com> wrote:
> >>>>> Hi Ard
> >>>>>
> >>>>>> -----Original Message-----
> >>>>>> From: Ard Biesheuvel [mailto:ard.biesheuvel at linaro.org]
> >>>> [...]
> >>>>>>
> >>>>>> Is the PCIe root complex so special that you cannot simply
> >>> describe an
> >>>>>> implementation that is not PNP0408 compatible as something else,
> >>> under
> >>>>>> its own unique HID? If everybody is onboard with using ACPI, how
> >>> is
> >>>>>> this any different from describing other parts of the platform
> >>>>>> topology? Even if the SBSA mandates generic PCI, they already
> >>> deviated
> >>>>>> from that when they built the hardware, so pretending that it is
> a
> >>>>>> PNP0408 with quirks really does not buy us anything.
> >>>>>
> >>>>> From my understanding we want to avoid this as this would allow
> >>> each
> >>>>> vendor to come up with his own code and it would be much more
> >>> effort
> >>>>> for the PCI maintainer to rework the PCI framework to accommodate
> >>> X86
> >>>>> and "all" ARM64 Host Controllers...
> >>>>>
> >>>>> I guess this approach is too risky and we want to avoid this.
> >>> Through
> >>>>> standardization we can more easily maintain the code and scale it
> >>> to
> >>>>> multiple SoCs...
> >>>>>
> >>>>> So this is my understanding; maybe Jon, Tomasz or Lorenzo can
> give
> >>>>> a bit more explanation...
> >>>>
> >>>> OK, so that boils down to recommending to vendors to represent
> known
> >>>> non-compliant hardware as compliant, just so that we don't have to
> >>>> change the code to support additional flavors of ECAM ? It's fine
> to
> >>>> be pragmatic, but that sucks.
> >>>>
> >>>> We keep confusing the x86 case with the ARM case here: for x86,
> they
> >>>> needed to deal with broken hardware *after* the fact, and all they
> >>>> could do is find /some/ distinguishing feature in order to guess
> >>> which
> >>>> exact hardware they might be running on. For arm64, it is the
> >>> opposite
> >>>> case. We are currently in a position where we can demand vendors
> to
> >>>> comply with the standards they endorsed themselves, and (ab)using
> >>> ACPI
> >>>> + DMI as a de facto platform description rather than plain ACPI
> makes
> >>>> me think the DT crowd were actually right from the beginning. It
> >>>> *directly* violates the standardization principle, since it
> requires
> >>> a
> >>>> priori knowledge inside the OS that a certain 'generic' device
> must
> >>> be
> >>>> driven in a special way.
> >>>>
> >>>> So can anyone comment on the feasibility of adding support for
> >>> devices
> >>>> with vendor specific HIDs (and no generic CIDs) to the current
> ACPI
> >>>> ECAM driver in Linux?
> >
> > I don't think of ECAM support itself as a "driver".  It's just a
> > service available to drivers, similar to OF resource parsing.
> >
> > Per PCI Firmware r3.2, sec 4.1.5, "PNP0A03" means a PCI/PCI-X/PCIe
> > host bridge.  "PNP0A08" means a PCI-X Mode 2 or PCIe bridge that
> > supports extended config space.  It doesn't specify how we access
> that
> > config space, so I think hardware with non-standard ECAM should still
> > have PNP0A03 and PNP0A08 in _CID or _HID.
> >
> > "ECAM" as used in the specs (PCIe r3.0, sec 7.2.2, and PCI Firmware
> > r3.2, sec 4.1) means:
> >
> >  (a) a memory-mapped model for config space access, and
> >  (b) a specific mapping of address bits to bus/device/function/
> >      register
> >
> > MCFG and _CBA assume both (a) and (b), so I think a device with
> > non-standard ECAM mappings should not be described in MCFG or _CBA.
> >
> > If a bridge has ECAM with non-standard mappings, I think either a
> > vendor-specific _HID or a device-specific method, e.g., _DSM, could
> > communicate that.
> >
> > Jon, I agree that we should avoid describing non-standardized
> hardware
> > in Linux-specific ways.  Is there a mechanism in use already?  How
> > does Windows handle this?  DMI is a poor long-term solution because
> it
> > requires ongoing maintenance for new platforms, but I think it's OK
> > for getting started with platforms already shipping.
> >
> > A _DSM has the advantage that once it is defined and supported, OEMs
> > can ship new platforms without requiring a new quirk or a new _HID to
> > be added to a driver.
> >
> > There would still be the problem of config access before the
> namespace
> > is available, i.e., the MCFG use case.  I don't know how important
> > that is.  Defining an MCFG extension seems like the most obvious
> > solution.
> >
> > If we only expect a few non-standard devices, maybe it's enough to
> > have DMI quirks to statically set up ECAM and just live with the
> > inconvenience of requiring a kernel change for every new non-standard
> > device.
> >
> >>> Host bridges in ACPI are handled through PNP0A08/PNP0A03 ids, and
> >>> most of the arch specific code is handled in the respective arch
> >>> directories (X86 and IA64, even though IA64 does not rely on
> ECAM/MCFG
> >>> for
> >>> PCI ops), it is not a driver per-se, PNP0A08/PNP0A03 are detected
> >>> through
> >>> ACPI scan handlers and the respective arch code (ie
> pci_acpi_scan_root)
> >>> sets-up resources AND config space on an arch specific basis.
> >>>
> >>> X86 deals with that with code in arch/x86 that sets-up the
> pci_raw_ops
> >>> on a platform specific basis (and it is not nice, but it works
> because
> >>> as you all know the number of platforms in X86 world is contained).
> >>>
> >>> Will this happen for ARM64 in arch/arm64 based on vendor specific
> >>> HIDs ?
> >>>
> >>> No.
> >>>
> >>> So given the current state of play (we were requested to move the
> >>> arch/arm64 specific ACPI PCI bits to arch/arm64), we would end up
> >>> with arch/arm64 code requiring code in /drivers to set-up pci_ops
> >>> in a platform specific way, it is horrible, if feasible at all.
> >>>
> >>> The only way this can be implemented is by pretending that the
> >>> ACPI/PCI arch/arm64 implementation is generic code (that's what
> this
> >>> series does), move it to /drivers (where it is in this series), and
> >>> implement _DSD vendor specific bindings (per HID) to set-up the pci
> >>> operations; whether this solution should go upstream, given that it
> >>> is just a short-term solution for early platforms bugs, it is
> another
> >>> story and my personal answer is no.
> >
> > It seems like there should be a way to look for a _DSM before we call
> > acpi_pci_root_get_mcfg_addr() to look for _CBA.
> >
> > Currently we call acpi_pci_root_get_mcfg_addr() (to read _CBA) from
> > the generic acpi_pci_root_add(), but the result (root->mcfg_addr) is
> > only used in x86-specific code.  I think it would be nicer if the
> > lookup and the use were together.  Then it would be easier to
> override
> > it because the mapping assumptions would all be in one place.
> >
> >> I think it shouldn't be too bad to move quirk handling mechanism to
> >> arch/arm64. Effectively we would not move platform specific code
> into
> >> arch/arm64 but just the mechanism checking if there is any quirk
> that
> >> is defined.
> >>
> >> i.e.:
> >>
> >> extern struct pci_cfg_fixup __start_acpi_mcfg_fixups[];
> >> extern struct pci_cfg_fixup __end_acpi_mcfg_fixups[];
> >>
> >> static struct pci_ecam_ops *pci_acpi_get_ops(struct acpi_pci_root
> *root)
> >> {
> >>        int bus_num = root->secondary.start;
> >>        int domain = root->segment;
> >>        struct pci_cfg_fixup *f;
> >>
> >>        /*
> >>         * Match against platform specific quirks and return
> corresponding
> >>         * CAM ops.
> >>         *
> >>         * First match against PCI topology <domain:bus> then use DMI
> or
> >>         * custom match handler.
> >>         */
> >>        for (f = __start_acpi_mcfg_fixups; f <
> __end_acpi_mcfg_fixups; f++) {
> >>                if ((f->domain == domain || f->domain ==
> PCI_MCFG_DOMAIN_ANY) &&
> >>                    (f->bus_num == bus_num || f->bus_num ==
> PCI_MCFG_BUS_ANY) &&
> >>                    (f->system ? dmi_check_system(f->system) : 1) &&
> >>                    (f->match ? f->match(f, root) : 1))
> >>                        return f->ops;
> >>        }
> >>        /* No quirks, use ECAM */
> >>        return &pci_generic_ecam_ops;
> >> }
> >>
> >> Such quirks will be defined anyway in drivers/pci/host/ in the
> vendor
> >> specific quirk implementations.
> >>
> >> e.g. in HiSilicon case we would have
> >>
> >> DECLARE_ACPI_MCFG_FIXUP(NULL, hisi_pcie_match, &hisi_pcie_ecam_ops,
> >>            PCI_MCFG_DOMAIN_ANY, PCI_MCFG_BUS_ANY);
> >>
> >> in "drivers/pci/host/pcie-hisi-acpi.c "
> >>
> >> Thanks
> >>
> >> Gab
> >
> > Sorry Gab, I guess I was really responding to earlier messages :)
> >
> > I don't really have much to say here, except that it doesn't seem
> > right to have an MCFG that describes a non-standard ECAM mapping.
> > I suppose there's already firmware in the field that does that,
> > though?
> >
> > Bjorn


From jcm at redhat.com  Tue May 24 07:38:32 2016
From: jcm at redhat.com (Jon Masters)
Date: Tue, 24 May 2016 10:38:32 -0400
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <EE11001F9E5DDD47B7634E2F8A612F2E1EDB438E@lhreml503-mbs>
References: <EE11001F9E5DDD47B7634E2F8A612F2E1ED8DF51@lhreml503-mbs>
 <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>
 <20160523233918.GA32555@localhost>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDB438E@lhreml503-mbs>
Message-ID: <de9e81d2-1aea-674a-97f2-b6caeab3cc47@redhat.com>

Hi Gabriele, all,

On 05/24/2016 03:23 AM, Gabriele Paoloni wrote:

>> Sorry Gab, I guess I was really responding to earlier messages :)
>>
>> I don't really have much to say here, except that it doesn't seem
>> right to have an MCFG that describes a non-standard ECAM mapping.
> 
> The ACPI table that this mechanism relies upon is the one discussed
> in:
> https://lkml.org/lkml/2016/3/9/91
> 
> As you can see MCFG describes ECAM mappings, but we have a motherboard
> reserved resource outside the MCFG:
> Device (RES0)
> {
> 	Name (_HID, "HISI0081") // HiSi PCIe RC config base address
> 	Name (_CID, "PNP0C02") // Motherboard reserved resource
> 	Name (_CRS, ResourceTemplate (){
> 	Memory32Fixed (ReadWrite, 0xb0080000 , 0x10000)
> 	})
> }
> 
> This allows us to retrieve the address we need for accessing
> the config space on the RC (that is non-ECAM).
> 
> I was thinking that such mechanism could fit different vendors
> and allow them define their own quirks without spoiling the 
> official and standard MCFG; also from the thread discussion
> you seemed quite ok with such solution...?

This could have been useful 2-3 years ago (when myself and others first
pulled the fire alarm concerning the lack of upstreaming of the ACPI
enablement for PCIe - which should have been fully upstream before the
first platforms ever even shipped) but at this time we have shipping
platforms that don't have tables built in this way. While we can go back
around to vendors and try to get them to rebuild firmware, it would be
by far preferable to adopt a solution that works with what is already
being deployed in the field today. Such as OEM match in MCFG.

Jon.

-- 
Computer Architect | Sent from my Fedora powered laptop


From mark.rutland at arm.com  Tue May 24 08:12:35 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 24 May 2016 16:12:35 +0100
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <574446B9.8040105@huawei.com>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
 <20160524113727.GD25374@leverpostej> <574446B9.8040105@huawei.com>
Message-ID: <20160524151235.GA11605@leverpostej>

On Tue, May 24, 2016 at 08:19:05PM +0800, Leizhen (ThunderTown) wrote:
> 
> 
> On 2016/5/24 19:37, Mark Rutland wrote:
> > On Tue, May 24, 2016 at 07:16:37PM +0800, Zhen Lei wrote:
> >> When we ran mprotect04(a test case in LTP) infinitely, it would always
> >> failed after a few seconds. The case can be described briefly that: copy
> >> a empty function from code area into a new memory area(created by mmap),
> >> then call mprotect to change the protection to PROT_EXEC. The syscall
> >> sys_mprotect will finally invoke flush_cache_range, but this function
> >> currently only invalid icache, the operation of flush dcache is missed.
> > 
> > In the LTP code I see powerpc-specific D-cache / I-cache synchronisation
> > (i.e. d-cache cleaning followed by I-cache invalidation), so there
> > appears to be some expectation of userspace maintenance. Hoever, there
> > is no such ARM-specific I-cache maintenance.
> But I see some other platforms have D-cache maintenance, like: arch/nios2/mm/cacheflush.c
> And according to the name of flush_cache_range, it should do this, I judged. Otherwise,
> mprotect04 will be failed on more platforms, it's easy to discover.

>From my experience with the LTP, it's likely that the test was written
and tested on very few architectures and kernel configurations, and has
seen very little testing on others.

> Only PPC have specific cache synchronization, maybe it meets some
> hardware limitation. 

Per [1] that "hardware limitation" is  simply the presence of a Harvard
cache architecture, similar to that of ARM.

> It's impossible a programmer fixed a common bug on only one platform
> but leave others unchanged.

The common problem here is I-cache coherency, but that must be managed
in an architecture-specific way. The patch for PPC [1] added
PPC-specific assembly to achieve that, and hence doesn't apply to other
platforms.

Jumping back to the problem at hand:

It looks like we inherited this from ARM, which has done this for all
executable mappings since commit  6060e8df517847bf ("ARM: I-cache: flush
executable mappings in flush_cache_range()"). The commit message refers
to a4db94d, which doesn't seem to exist, and I assume is
115b22474eb1905d ("ARM: 5794/1: Flush the D-cache during
copy_user_highpage()") which happened to get rebased at some point.

That all implies that the icache maintenance is only intended to ensure
that CoW does not result in unexpected incoherency. Which in turn
implies that flipping permissions with mprotect is not expected to
synchronise the D and I caches.

Russell, does that analysis make sense to you?

Ben, Paul, Michael, I take it that the LTP commit for PPC [1] is as
expected? i.e. you similarly do not expect flipping execute permission
with mprotect to imply that the kernel must synchronise the D & I
caches?

Thanks,
Mark.

> > It looks like the test may be missing I-cache maintenance regardless of
> > the semantics of mprotect in this case.
> > 
> > I have not yet devled into flush_cache_range and how it is called.
> 
> SYSCALL_DEFINE3(mprotect ---> mprotect_fixup ---> change_protection ---> change_protection_range --> flush_cache_range
> 
> > 
> > Thanks,
> > Mark.
> > 
> >> Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
> >> ---
> >>  arch/arm64/mm/flush.c | 2 +-
> >>  1 file changed, 1 insertion(+), 1 deletion(-)
> >>
> >> diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
> >> index dbd12ea..eda4124 100644
> >> --- a/arch/arm64/mm/flush.c
> >> +++ b/arch/arm64/mm/flush.c
> >> @@ -31,7 +31,7 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
> >>  		       unsigned long end)
> >>  {
> >>  	if (vma->vm_flags & VM_EXEC)
> >> -		__flush_icache_all();
> >> +		flush_icache_range(start, end);
> >>  }
> >>
> >>  static void sync_icache_aliases(void *kaddr, unsigned long len)
> >> --
> >> 2.5.0
> >>
> >>
> >>
> >> _______________________________________________
> >> linux-arm-kernel mailing list
> >> linux-arm-kernel at lists.infradead.org
> >> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> >>
> > 
> > .
> > 
> 

[1] https://github.com/linux-test-project/ltp/commit/cf9a0800cd0d71c8c471adc5631216f995ab7e02


From robin.murphy at arm.com  Tue May 24 08:36:45 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 24 May 2016 16:36:45 +0100
Subject: [PATCH v2 4/5] iommu/mediatek: add support for mtk iommu
 generation one HW
In-Reply-To: <1464083839.30939.54.camel@mtksdaap41>
References: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
 <1463658558-567-5-git-send-email-honghui.zhang@mediatek.com>
 <57435AA1.3090602@arm.com> <1464083839.30939.54.camel@mtksdaap41>
Message-ID: <5744750D.9080006@arm.com>

On 24/05/16 10:57, Honghui Zhang wrote:
[...]
>>> @@ -48,6 +48,9 @@ struct mtk_iommu_domain {
>>>    	struct io_pgtable_ops		*iop;
>>>
>>>    	struct iommu_domain		domain;
>>> +	void				*pgt_va;
>>> +	dma_addr_t			pgt_pa;
>>> +	void				*cookie;
>>
>> These are going to be mutually exclusive with the cfg and iop members,
>> which implies it might be a good idea to use a union and not waste
>> space. Or better, just forward-declare struct mtk_iommu_domain here and
>> leave separate definitions private to each driver. The void *cookie is
>> also an unnecessary level of abstraction, I think.
>>
>
> Do you mean declare struct mtk_iommu_domain here, and implement a new
> struct in mtk_iommu_v1.c like
> struct mtk_iommu_domain_v1 {
> 	struct mtk_iommu_domain	domain;
> 	u32			*pgt_va;
> 	dma_addr_t		pgt_pa;
> 	mtk_iommu_data		*data;
> };
> If this is acceptable I would implement it in the next version.

Pretty much, except they both want to be called struct mtk_iommu_domain, 
so that a *declaration* for the sake of the m4u_dom member of struct 
mtk_iommu_data in the header file can remain common to both drivers - it 
then just picks up whichever private *definition* from the .c file being 
compiled.

>>>    };
>>>
>>>    struct mtk_iommu_data {
>>> diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
>>> new file mode 100644
>>> index 0000000..55023e1
>>> --- /dev/null
>>> +++ b/drivers/iommu/mtk_iommu_v1.c
>>> @@ -0,0 +1,742 @@
>>> +/*
>>> + * Copyright (c) 2015-2016 MediaTek Inc.
>>> + * Author: Yong Wu <yong.wu at mediatek.com>
>>
>> Nit: is that in the sense that this patch should also have Yong's
>> signed-off-by on it, or in that it's your work derived from his version
>> in mtk_iommu.c?
>
> I write this driver based on Yong's version of mtk_iommu.c, should I add
> his signed-off-by for this patch? Or should I put a comment about this?
> Thanks.

OK, in that case I think the appropriate attribution would be along the 
lines of "Author: Honghui Zhang, based on mtk_iommu.c by Yong Wu" (if in 
doubt, grepping for "Based on" gives a feel for how this is commonly 
done). If the work that comprises this patch itself (i.e. the copying 
and modification of the existing code) is all yours then your sign-off 
alone is fine.

[...]
>>> +static int mtk_iommu_add_device(struct device *dev)
>>> +{
>>> +	struct iommu_group *group;
>>> +	struct device_node *np;
>>> +	struct of_phandle_args iommu_spec;
>>> +	int idx = 0;
>>> +
>>> +	while (!of_parse_phandle_with_args(dev->of_node, "iommus",
>>> +				   "#iommu-cells", idx,
>>> +				   &iommu_spec)) {
>>
>> Hang on, this doesn't seem right - why do you need to reimplement all
>> this instead of using IOMMU_OF_DECLARE()?
>
> All the clients of mtk generation one iommu share the same iommu domain,
> as a matter of fact, mtk generation one iommu only support one iommu
> domain. ALl the clients share the same iova address and use the same
> pagetable. That means all iommu clients needed to be attached to the
> same dma_iommu_mapping.

Ugh, right - I'd forgotten that the arch/arm DMA mapping code doesn't 
respect IOMMU groups or default domains at all. That's the real root 
cause of the issue here.

> If use IOMMU_OF_DELCARE, we need to call of_iommu_set_ops to set the
> iommu_ops, I do not want the iommu_ops be set since it would cause iommu
> client device in different dma_iommu_mapping.
>
> When an iommu client device has been created, the following sequence is
> called.
>
> of_platform_device_create
> 	->of_dma_config
> 		->arch_setup_dma_ops
> 			->arch_setup_iommu_dma_ops
> In this function of arch_setup_iommu_dma_ops would create a new
> dma_iommu_mapping for each iommu client device and then attach the
> device to this new dma_iommu_mapping. Since all the iommu clients share
> the very same pagetable, this will not workable for our HW.
> I could not release the dma_iommu_mapping in attach_device since the
> to_dma_iommu_mapping was set after device_attached.
> Any suggest for this?

On a second look, you're doing more or less the same thing that the 
Renesas IPMMU driver currently does, so it's probably OK as a workaround 
for now. Fixing the arch/arm code is part of the bigger ongoing problem 
of sorting out IOMMU probing and DMA configuration, and it doesn't seem 
fair to force that on you for the sake of one driver ;)

[...]
>>> +static int __maybe_unused mtk_iommu_resume(struct device *dev)
>>> +{
>>> +	struct mtk_iommu_data *data = dev_get_drvdata(dev);
>>> +	struct mtk_iommu_suspend_reg *reg = &data->reg;
>>> +	void __iomem *base = data->base;
>>> +
>>> +	writel_relaxed(data->m4u_dom->pgt_pa, base + REG_MMU_PT_BASE_ADDR);
>>
>> Hmm, this looks like the only case where m4u_dom actually seems
>> necessary - I'm pretty sure all the others could be fairly easily
>> reworked to not use it (I might try having a quick hack at the existing
>> M4U driver to see) - at which point we could just explicitly
>> save/restore the base register here and get rid of m4u_dom entirely.
>
> Let me take a while to think about this.

That was true in the context of arm64, but you're right that the current 
state of the 32-bit code does make m4u_dom more necessary, so I guess we 
may as well leave it as-is for now.

Robin.


From robin.murphy at arm.com  Tue May 24 08:45:17 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 24 May 2016 16:45:17 +0100
Subject: [RFC 5/9] drivers: platform: Configure dma operations at probe
 time
In-Reply-To: <1461599894-1969-6-git-send-email-sricharan@codeaurora.org>
References: <1461599894-1969-1-git-send-email-sricharan@codeaurora.org>
 <1461599894-1969-6-git-send-email-sricharan@codeaurora.org>
Message-ID: <5744770D.9090303@arm.com>

On 25/04/16 16:58, Sricharan R wrote:
> From: Laurent Pinchart <laurent.pinchart+renesas at ideasonboard.com>
>
> Configuring DMA ops at probe time will allow deferring device probe when
> the IOMMU isn't available yet.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas at ideasonboard.com>
> ---
>   drivers/base/platform.c | 13 +++++++++++++
>   drivers/of/platform.c   |  7 +++----
>   2 files changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> index f437afa..17e64a4 100644
> --- a/drivers/base/platform.c
> +++ b/drivers/base/platform.c
> @@ -557,6 +557,12 @@ static int platform_drv_probe(struct device *_dev)
>   	if (ret < 0)
>   		return ret;
>
> +	if (of_have_populated_dt()) {
> +		ret = of_dma_configure_ops(_dev, _dev->of_node);
> +		if (ret < 0)
> +			goto done;
> +	}
> +
>   	ret = dev_pm_domain_attach(_dev, true);
>   	if (ret != -EPROBE_DEFER) {
>   		if (drv->probe) {
> @@ -569,6 +575,11 @@ static int platform_drv_probe(struct device *_dev)
>   		}
>   	}
>
> +	if (of_have_populated_dt()) {
> +		if (ret)
> +			of_dma_deconfigure(_dev);
> +	}
> +done:
>   	if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
>   		dev_warn(_dev, "probe deferral not supported\n");
>   		ret = -ENXIO;
> @@ -591,6 +602,8 @@ static int platform_drv_remove(struct device *_dev)
>   	if (drv->remove)
>   		ret = drv->remove(dev);
>   	dev_pm_domain_detach(_dev, true);
> +	if (of_have_populated_dt())
> +		of_dma_deconfigure(_dev);
>
>   	return ret;
>   }
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 17ee8d5..12bbc8e1 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -180,11 +180,9 @@ static struct platform_device *of_platform_device_create_pdata(
>   	dev->dev.bus = &platform_bus_type;
>   	dev->dev.platform_data = platform_data;
>   	of_dma_configure_masks(&dev->dev, dev->dev.of_node);
> -	of_dma_configure_ops(&dev->dev, dev->dev.of_node);
>   	of_msi_configure(&dev->dev, dev->dev.of_node);
>
>   	if (of_device_add(dev) != 0) {
> -		of_dma_deconfigure(&dev->dev);
>   		platform_device_put(dev);
>   		goto err_clear_flag;
>   	}
> @@ -481,11 +479,12 @@ static int of_platform_device_destroy(struct device *dev, void *data)
>   	if (dev->bus == &platform_bus_type)
>   		platform_device_unregister(to_platform_device(dev));
>   #ifdef CONFIG_ARM_AMBA
> -	else if (dev->bus == &amba_bustype)
> +	else if (dev->bus == &amba_bustype) {
>   		amba_device_unregister(to_amba_device(dev));
> +		of_dma_deconfigure(dev);
> +	}

Note that we definitely need this to happen properly on other buses, 
too. I had something for the AMBA bus back when I last looked at 
this[0], but since then we now have PCI devices going through the 
of_dma_configure() path as well (hence 226d89cbb242).

There's also now some initial ACPI code in flight[1], so it's probably 
about time to take another closer look at how this can be properly 
generalised, but I'm not necessarily averse to starting with a 
DT-focused solution that gets at least half way, then building on top of 
that.

Robin.

[0]:http://www.linux-arm.org/git?p=linux-rm.git;a=commitdiff;h=1f38b62b05e17ccbfcc68e4229c69fee74922e2a
[1]:http://thread.gmane.org/gmane.linux.kernel.iommu/13046

>   #endif
>
> -	of_dma_deconfigure(dev);
>   	of_node_clear_flag(dev->of_node, OF_POPULATED);
>   	of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
>   	return 0;
>



From mathieu.poirier at linaro.org  Tue May 24 08:51:22 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue, 24 May 2016 09:51:22 -0600
Subject: [PATCH 0011/1529] Fix typo
In-Reply-To: <20160521113648.31841-1-andrea.gelmini@gelma.net>
References: <20160521113648.31841-1-andrea.gelmini@gelma.net>
Message-ID: <CANLsYkxtvYmHRsisjO2DyW85yF3EQ+Jy6Gx4AZ+pkzt7cZM8-Q@mail.gmail.com>

On 21 May 2016 at 05:36, Andrea Gelmini <andrea.gelmini at gelma.net> wrote:
> Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
> ---
>  Documentation/devicetree/bindings/arm/coresight.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
> index 93147c0c..a846d4b 100644
> --- a/Documentation/devicetree/bindings/arm/coresight.txt
> +++ b/Documentation/devicetree/bindings/arm/coresight.txt
> @@ -6,7 +6,7 @@ SoCs tracing needs. These trace components can generally be classified as
>  sinks, links and sources. Trace data produced by one or more sources flows
>  through the intermediate links connecting the source to the currently selected
>  sink. Each CoreSight component device should use these properties to describe
> -its hardware characteristcs.
> +its hardware characteristics.

Thank you for that.

Acked-by: Mathieu Poirier <mathieu.poirier at linaro.org>

>
>  * Required properties for all components *except* non-configurable replicators:
>
> --
> 2.8.2.534.g1f66975
>


From robin.murphy at arm.com  Tue May 24 08:59:28 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 24 May 2016 16:59:28 +0100
Subject: [RFC 8/9] drivers: of: call iommu_bus_add_dev after
 iommu_configure_ops
In-Reply-To: <1461599894-1969-9-git-send-email-sricharan@codeaurora.org>
References: <1461599894-1969-1-git-send-email-sricharan@codeaurora.org>
 <1461599894-1969-9-git-send-email-sricharan@codeaurora.org>
Message-ID: <57447A60.4060805@arm.com>

On 25/04/16 16:58, Sricharan R wrote:
> Now that the device's iommu ops are configured at probe time,
> the device has to be added to the iommu late.
>
> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
> ---
>   drivers/of/device.c | 4 ++++
>   1 file changed, 4 insertions(+)
>
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index 57a5f2d..722115c 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -6,6 +6,7 @@
>   #include <linux/of_iommu.h>
>   #include <linux/dma-mapping.h>
>   #include <linux/init.h>
> +#include <linux/iommu.h>
>   #include <linux/module.h>
>   #include <linux/mod_devicetable.h>
>   #include <linux/slab.h>
> @@ -154,6 +155,9 @@ int of_dma_configure_ops(struct device *dev, struct device_node *np)
>   	dev_dbg(dev, "device is%sbehind an iommu\n",
>   		iommu ? " " : " not ");
>
> +	if (iommu)
> +		iommu_bus_add_dev(dev);

This (in conjunction with the previous patch) seems unnecessarily 
convoluted - if of_iommu_configure() has found some iommu_ops for a 
device, why not just call .add_device() directly there and then? There 
are already systems that could warrant having two different IOMMU 
drivers active simultaneously (but thankfully don't _need_ to), so 
trying to escape from per-bus IOMMU ops makes more sense than 
entrenching the horrible notion of "the" IOMMU on "the" platform bus any 
further.

Robin.

> +
>   	arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
>
>   	return 0;
>



From tjakobi at math.uni-bielefeld.de  Tue May 24 09:05:46 2016
From: tjakobi at math.uni-bielefeld.de (Tobias Jakobi)
Date: Tue, 24 May 2016 18:05:46 +0200
Subject: [PATCH 1/2] drm/exynos: g2d: Add support for old S5Pv210 type
In-Reply-To: <57445E16.90301@samsung.com>
References: <1464096493-13378-1-git-send-email-k.kozlowski@samsung.com>
 <57445BE5.7060702@math.uni-bielefeld.de> <57445E16.90301@samsung.com>
Message-ID: <57447BDA.2000004@math.uni-bielefeld.de>

Hello Krzysztof,


Krzysztof Kozlowski wrote:
> On 05/24/2016 03:49 PM, Tobias Jakobi wrote:
>> Hello Krzysztof,
>>
>> are you sure that these are the only differences. Because AFAIK there
>> are quite a few more:
>> - DMA submission of commands
>> - blend mode / rounding
>> - solid fill
>> - YCrCb support
>> - and probably more
>>
>> One would need to add least split the command list parser into a v3 and
>> v41 version to accomodate for the differences. In fact userspace/libdrm
>> would need to know which hw type it currently uses, but you currently
>> always return 4.1 in the corresponding ioctl.
> 
> Eh, so probably my patch does not cover fully the support for v3 G2D. I
> looked mostly at the differences between v3 and v4 in the s5p-g2d driver
> itself. However you are right that this might be not sufficient because
> exynos-g2d moved forward and is different than s5p-g2d.
> 
>> Krzysztof Kozlowski wrote:
>>> The non-DRM s5p-g2d driver supports two versions of G2D: v3.0 on
>>> S5Pv210 and v4.x on Exynos 4x12 (or newer). The driver for 3.0 device
>>> version is doing two things differently:
>>> 1. Before starting the render process, it invalidates caches (pattern,
>>>    source buffer and mask buffer). Cache control is not present on v4.x
>>>    device.
>>> 2. Scalling is done through StretchEn command (in BITBLT_COMMAND_REG
>>>    register) instead of SRC_SCALE_CTRL_REG as in v4.x. However the
>>>    exynos_drm_g2d driver does not implement the scalling so this
>>>    difference can be eliminated.
>> Huh? Where did you get this from? Scaling works with the DRM driver.
> 
> I was looking for the usage of scaling reg (as there is no scaling
> command). How the scaling is implemented then?
Like you said above the drivers work completly different. The DRM one
receives a command list that is constructed by userspace (libdrm
mostly), copies it to a contiguous buffer and passes the memory address
of that buffer to the engine which then works on it. Of course
everything is slightly more complex.

You don't see any reference to scaling in the driver because the scaling
regs don't need any kind of specific validation.

If you want to know how the command list is constructed, the best way is
to look into libdrm. The Exynos specific tests actually cover scaling.


With best wishes,
Tobias


> Thanks for feedback!
> 
> Best regards,
> Krzysztof
> 



From d-gerlach at ti.com  Tue May 24 09:12:29 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Tue, 24 May 2016 11:12:29 -0500
Subject: [PATCH] ARM: OMAP2+: Select OMAP_INTERCONNECT for SOC_AM43XX
Message-ID: <4af329be31b140a7cd71351cf8f2d2006194e42b.1464105749.git.d-gerlach@ti.com>

AM43XX SoCs make use of the omap_l3_noc driver so explicitly select
OMAP_INTERCONNECT in the Kconfig for SOC_AM43XX to ensure it always gets
enabled for AM43XX only builds.

Signed-off-by: Dave Gerlach <d-gerlach at ti.com>
---
Based on next-20160524.

 arch/arm/mach-omap2/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 415a0bd0cda6..efbc4649a3c5 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -69,6 +69,7 @@ config SOC_AM43XX
 	select HAVE_ARM_TWD
 	select ARM_ERRATA_754322
 	select ARM_ERRATA_775420
+	select OMAP_INTERCONNECT
 
 config SOC_DRA7XX
 	bool "TI DRA7XX"
-- 
2.7.3



From khilman at baylibre.com  Tue May 24 09:14:28 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Tue, 24 May 2016 09:14:28 -0700
Subject: [PATCH 0/7] pinctrl: meson: Add a bunch more pins
In-Reply-To: <CACRpkdY9oGZLt431NwTaFmZk98O8n3ZnMA1odhYZtcH7P1p=Jg@mail.gmail.com>
 (Linus Walleij's message of "Tue, 24 May 2016 11:23:37 +0200")
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
 <CACRpkdY9oGZLt431NwTaFmZk98O8n3ZnMA1odhYZtcH7P1p=Jg@mail.gmail.com>
Message-ID: <m2eg8rigbf.fsf@baylibre.com>

Linus Walleij <linus.walleij at linaro.org> writes:

> On Fri, May 6, 2016 at 4:21 PM, Kevin Hilman <khilman at baylibre.com> wrote:
>
>> Add support for several more devices, both in the EE domain and in the
>> AO domain.  Also, add the pins to the corresponding DTS files.
>>
>> Tested on odroid-c2 and Amlogic P200 boards, and verified with working
>> ethernet.
>>
>> Depends on the initial GXBB pinctrl support from Carlo[1].  Also
>> available in my git tree[2] with all the dependencies included.
>
> These don't apply anomore sadly, Kevin can you rebase on
> Torvalds' HEAD and resend, and include Carlo's ACK on them
> so I can merge them in the next kernel cycle?

Coming right up...

Kevin


From broonie at kernel.org  Tue May 24 09:25:59 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 24 May 2016 17:25:59 +0100
Subject: Applied "ASoC: rockchip: i2s: rename I2S_CKR_TRCM_TX/RXSHARE to
 I2S_CKR_TRCM_TX/RXONLY" to the asoc tree
In-Reply-To: <1464061667-16477-1-git-send-email-zhengxing@rock-chips.com>
Message-ID: <E1b5F9b-0003ax-0p@debutante>

The patch

   ASoC: rockchip: i2s: rename I2S_CKR_TRCM_TX/RXSHARE to I2S_CKR_TRCM_TX/RXONLY

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 7ec4a1c34a190297540626dfa240dc033beca196 Mon Sep 17 00:00:00 2001
From: Sugar Zhang <sugar.zhang at rock-chips.com>
Date: Tue, 24 May 2016 11:47:46 +0800
Subject: [PATCH] ASoC: rockchip: i2s: rename I2S_CKR_TRCM_TX/RXSHARE to
 I2S_CKR_TRCM_TX/RXONLY

this patch make it more reasonable and readable, because when we chose
I2S_CKR_TRCM_TXONLY, we only output clk_lrck_tx, and hardware need to
confirm this signal is wired to external codec lrck_tx/rx at the same time.

for convenience, we just handle lrck_txonly if we enable symmetric_rates
in driver and dai_link. otherwise, we use the separate lrck_tx/rx.

Signed-off-by: Sugar Zhang <sugar.zhang at rock-chips.com>
Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 sound/soc/rockchip/rockchip_i2s.c | 4 ++--
 sound/soc/rockchip/rockchip_i2s.h | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index d4f7eac5cfd4..ca1cf3b085a4 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -316,8 +316,8 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
 			   I2S_DMACR_RDL(16));
 
 	val = I2S_CKR_TRCM_TXRX;
-	if (dai->driver->symmetric_rates || rtd->dai_link->symmetric_rates)
-		val = I2S_CKR_TRCM_TXSHARE;
+	if (dai->driver->symmetric_rates && rtd->dai_link->symmetric_rates)
+		val = I2S_CKR_TRCM_TXONLY;
 
 	regmap_update_bits(i2s->regmap, I2S_CKR,
 			   I2S_CKR_TRCM_MASK,
diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h
index 8e239d301bc7..31f11fd25393 100644
--- a/sound/soc/rockchip/rockchip_i2s.h
+++ b/sound/soc/rockchip/rockchip_i2s.h
@@ -81,8 +81,8 @@
 #define I2S_CKR_TRCM_SHIFT	28
 #define I2S_CKR_TRCM(x)	(x << I2S_CKR_TRCM_SHIFT)
 #define I2S_CKR_TRCM_TXRX	(0 << I2S_CKR_TRCM_SHIFT)
-#define I2S_CKR_TRCM_TXSHARE	(1 << I2S_CKR_TRCM_SHIFT)
-#define I2S_CKR_TRCM_RXSHARE	(2 << I2S_CKR_TRCM_SHIFT)
+#define I2S_CKR_TRCM_TXONLY	(1 << I2S_CKR_TRCM_SHIFT)
+#define I2S_CKR_TRCM_RXONLY	(2 << I2S_CKR_TRCM_SHIFT)
 #define I2S_CKR_TRCM_MASK	(3 << I2S_CKR_TRCM_SHIFT)
 #define I2S_CKR_MSS_SHIFT	27
 #define I2S_CKR_MSS_MASTER	(0 << I2S_CKR_MSS_SHIFT)
-- 
2.8.1



From santosh.shilimkar at oracle.com  Tue May 24 09:29:29 2016
From: santosh.shilimkar at oracle.com (Santosh Shilimkar)
Date: Tue, 24 May 2016 09:29:29 -0700
Subject: [PATCH 3/3] ARM: configs: keystone: Enable PINCTRL_SINGLE Config
In-Reply-To: <5743D0FD.5070804@ti.com>
References: <1464006547-19569-1-git-send-email-j-keerthy@ti.com>
 <1464006547-19569-4-git-send-email-j-keerthy@ti.com>
 <5743CC80.4070404@ti.com> <5743D0FD.5070804@ti.com>
Message-ID: <6325832e-24d2-43c7-09b4-a73b6549ee2c@oracle.com>

Hi Keerthy,

On 5/23/2016 8:56 PM, Keerthy wrote:
>
>
> On Tuesday 24 May 2016 09:07 AM, Lokesh Vutla wrote:
>>
>>
>> On Monday 23 May 2016 05:59 PM, Keerthy wrote:
>>> keystone-k2l devices use pinmux and are compliant with PINCTRL_SINGLE.
>>> Hence enable the config option.
>>>
>>> Signed-off-by: Keerthy <j-keerthy at ti.com>
>>
>> A similar patch[1] is already posted.
>>
>> [1]https://patchwork.kernel.org/patch/8958091/
>
> Ah I had not seen them. If they are already reviewed and closer to be
> merged then Patch 2 and Patch 3 of this series can be dropped.
>
Once the 4.7-rc2 is out, please rebase these floating patches
against it and post a consolidated patches. I will line them
up for 4.8

Regards,
Santosh


From robh at kernel.org  Tue May 24 10:09:41 2016
From: robh at kernel.org (Rob Herring)
Date: Tue, 24 May 2016 12:09:41 -0500
Subject: [PATCH v3 4/4] soc: Add SoC driver for Freescale Vybrid platform
In-Reply-To: <20160524041447.GA2884@Sanchayan-Arch.localdomain>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
 <ffef165d05f71a1b19437171d8fdb4bc78f6b1e3.1463737502.git.maitysanchayan@gmail.com>
 <20160523211813.GA30237@rob-hp-laptop>
 <20160524041447.GA2884@Sanchayan-Arch.localdomain>
Message-ID: <CAL_JsqKCwy=aXveTfnaQuZ5b3Ld9nzABgPfdPm1JX3CBuvzG+Q@mail.gmail.com>

On Mon, May 23, 2016 at 11:14 PM,  <maitysanchayan at gmail.com> wrote:
> Hello Rob,
>
> On 16-05-23 16:18:13, Rob Herring wrote:
>> On Fri, May 20, 2016 at 03:32:05PM +0530, Sanchayan Maity wrote:
>> > This adds a SoC driver to be used by Freescale Vybrid SoC's.
>> > Driver utilises syscon and nvmem consumer API's to get the
>> > various register values needed and expose the SoC specific
>> > properties via sysfs.
>> >
>> > A sample output from Colibri Vybrid VF61 is below:
>> >
>> > root at colibri-vf:~# cd /sys/bus/soc/devices/soc0
>> > root at colibri-vf:/sys/bus/soc/devices/soc0# ls
>> > family     machine    power      revision   soc_id     subsystem  uevent
>> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat family
>> > Freescale Vybrid VF610
>> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat machine
>> > Freescale Vybrid
>> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat revision
>> > 00000013
>> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat soc_id
>> > df6472a6130f29d4
>> >
>> > Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
>> > ---
>> >  .../bindings/arm/freescale/fsl,vf610-soc.txt       |  20 +++
>> >  drivers/soc/Kconfig                                |   1 +
>> >  drivers/soc/fsl/Kconfig                            |  10 ++
>> >  drivers/soc/fsl/Makefile                           |   1 +
>> >  drivers/soc/fsl/soc-vf610.c                        | 198 +++++++++++++++++++++
>> >  5 files changed, 230 insertions(+)
>> >  create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>> >  create mode 100644 drivers/soc/fsl/Kconfig
>> >  create mode 100644 drivers/soc/fsl/soc-vf610.c
>> >
>> > diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>> > new file mode 100644
>> > index 0000000..338905d
>> > --- /dev/null
>> > +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
>> > @@ -0,0 +1,20 @@
>> > +Vybrid System-on-Chip
>> > +---------------------
>> > +
>> > +Required properties:
>> > +
>> > +- compatible: "fsl,vf610-soc"
>> > +- rom-revision: phandle to the on-chip ROM node
>> > +- mscm: phandle to the MSCM CPU configuration node
>> > +- nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
>> > +- nvmem-cell-names: should contain string names "cfg0" and "cfg1"
>>
>> I still have similar concerns as the discussion on the last version.
>> This version only proves that you aren't describing h/w, but rather just
>> a collection of data that some driver wants.
>>
>> A driver can just as easily look-up all the nodes directly that these
>> phandles point to.
>
> Agreed, that we can look up all the nodes directly that these phandles
> refer to but I would still need a DT entry to bind to. While I could
> bind to existing nodes like mscm cpucfg but that doesn't seem right.
>
> The very first approach that we had taken was to integrate this functionality
> in mach-vf610.c code under mach-imx
> http://www.spinics.net/lists/devicetree/msg80654.html

Yes, everyone wants to move all platform devices in the kernel to a
corresponding DT node. The result is often making up nodes to do this.
It's the same thing with cpufreq.

> and then it was recommended to migrate this to drivers/soc where we did use
> phandles or direct look up via compatible strings

The location in the tree is an orthogonal issue. You could move it and
use of_machine_is_compatible without any DT change.

The primary issue I have here is how do we bind soc_bus to DT in a
consistent way. Sorry, but vybrid specific patches alone are never
going to solve that issue.

> http://www.spinics.net/lists/arm-kernel/msg420847.html
>
> and
>
> http://lkml.iu.edu/hypermail/linux/kernel/1506.0/03787.html
>
> There hasn't been a consensus since v1.

I actually prefer your previous version binding soc_bus to the root
bus node to this version. I think that is closer to the right
direction. After all, pretty much everything is an SOC and every SOC
has an SOC bus. Pretty much every SOC and board have revisions and may
need to expose that revision info as well. We have to do this
consistently which means having a default implementation for
simple-bus that is not opt-in.

Alternatively, we should just deprecate soc_bus and come up a
different solution. Either way, I think we have a half implemented
solution currently.

Rob


From lorenzo.pieralisi at arm.com  Tue May 24 10:24:23 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Tue, 24 May 2016 18:24:23 +0100
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <20160523233918.GA32555@localhost>
References: <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>
 <20160523233918.GA32555@localhost>
Message-ID: <20160524172423.GA15855@red-moon>

Hi Bjorn,

On Mon, May 23, 2016 at 06:39:18PM -0500, Bjorn Helgaas wrote:

[...]

> On Mon, May 23, 2016 at 03:16:01PM +0000, Gabriele Paoloni wrote:
> I don't think of ECAM support itself as a "driver".  It's just a
> service available to drivers, similar to OF resource parsing.
> 
> Per PCI Firmware r3.2, sec 4.1.5, "PNP0A03" means a PCI/PCI-X/PCIe
> host bridge.  "PNP0A08" means a PCI-X Mode 2 or PCIe bridge that
> supports extended config space.  It doesn't specify how we access that
> config space, so I think hardware with non-standard ECAM should still
> have PNP0A03 and PNP0A08 in _CID or _HID.
> 
> "ECAM" as used in the specs (PCIe r3.0, sec 7.2.2, and PCI Firmware
> r3.2, sec 4.1) means:
> 
>   (a) a memory-mapped model for config space access, and
>   (b) a specific mapping of address bits to bus/device/function/
>       register
> 
> MCFG and _CBA assume both (a) and (b), so I think a device with
> non-standard ECAM mappings should not be described in MCFG or _CBA.
> 
> If a bridge has ECAM with non-standard mappings, I think either a
> vendor-specific _HID or a device-specific method, e.g., _DSM, could
> communicate that.
> 
> Jon, I agree that we should avoid describing non-standardized hardware
> in Linux-specific ways.  Is there a mechanism in use already?  How
> does Windows handle this?  DMI is a poor long-term solution because it
> requires ongoing maintenance for new platforms, but I think it's OK
> for getting started with platforms already shipping.
> 
> A _DSM has the advantage that once it is defined and supported, OEMs
> can ship new platforms without requiring a new quirk or a new _HID to
> be added to a driver.
> 
> There would still be the problem of config access before the namespace
> is available, i.e., the MCFG use case.  I don't know how important
> that is.  Defining an MCFG extension seems like the most obvious
> solution.

Your summary above is a perfect representation of the situation.

We had an opportunity to sync-up on the current status of ACPI PCI
for ARM64 (and talked about a way forward for this series, which
includes quirks handling), let me summarize it here for everyone
involved so that we can agree on a way forward.

1) ACPI PCI support for PNP0A03/PNP0A08 host bridges on top of MCFG
   ECAM for config space is basically ready (Tomasz and JC addressed
   Rafael's concerns in relation to ARM64 specific code, and managed
   to find a way to allocate domain numbers in preparation for Arnd
   pci_create_root_bus() clean-up, v8 to be posted shortly and should
   be final). This provides support for de-facto ACPI/PCI ECAM base
   standard for ARM64 (with a clean-split between generic code and ARM64
   bits, where ARM64, like X86 and IA64, manages in arch code IO space and
   PCI resources, to be further consolidated in the near future).
   I do not think anyone can complain about the generality of what we
   achieved, for systems that are PCI standard (yes, PCI STANDARD) this
   would just be sufficient.
2) In a real world (1) is not enough. Some ARM64 platforms, not entirely
   ECAM compliant, already shipped with the corresponding firmware that
   we can't update. HW has ECAM quirks and to work around it in the kernel
   we put forward many solutions to the problem, it is time we found a
   solution (when, of course, (1) is completed and upstream).
   Using the MCFG table OEMID matching floated around in this thread
   would work fine for most of the platforms (and cross-OS) that have
   shipped with HW ECAM quirks, so I think that's the starting point for
   our solution and that's how we can sort this out, _today_.

   The solution is a trivial look-up table:
   MCFG OEMID <-> PCI config space ops

3) (2) does not just work on some platforms (and we can't predict the
   future either - actually I can, it is three letters, ECAM), simply
   because MCFG OEMID matching does not provide a way to attach further
   data to the MCFG (eg if config space for, say, bus 0 domain 0, is not
   ECAM compliant, the config region can't be handled and must not be
   handled through a corresponding MCFG region.
   That's the problem Gabriele is facing and wants to solve through
   something like:

   https://lkml.org/lkml/2016/3/9/91

   in the respective ACPI tables-bindings. It may be an idea worth
   pursuing, it does not solve (2) simply because that FW has shipped,
   we can't patch it any longer.

Hence to finally support ACPI PCI on ARM64 I suggest we carry out the
following steps, in order:

- Let's complete/merge (1), that's fundamental to this whole thread
- On top of (1) we apply a quirking mechanism based on (2) that allows
  us to boot mainline with boxes shipping today with no FW update required.
- We devise a way to handle quirks that is more generic than (2) so that
  can we can accomodate further platforms that can't rely on (2) but
  have more leeway in terms of FW updates.

I hope that's a reasonable plan, Tomasz's v8 series coming to kick it off.

Thank you,
Lorenzo


From jcm at redhat.com  Tue May 24 10:35:08 2016
From: jcm at redhat.com (Jon Masters)
Date: Tue, 24 May 2016 13:35:08 -0400 (EDT)
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <20160524172423.GA15855@red-moon>
References: <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>
 <20160523233918.GA32555@localhost> <20160524172423.GA15855@red-moon>
Message-ID: <D22FCD78-6814-452F-9B6F-8B262D065BBD@redhat.com>

A big +1 to the below :) :) :)

-- 
Computer Architect | Sent from my 64-bit #ARM Powered phone

> On May 24, 2016, at 13:24, Lorenzo Pieralisi <lorenzo.pieralisi at arm.com> wrote:
> 
> Hi Bjorn,
> 
> On Mon, May 23, 2016 at 06:39:18PM -0500, Bjorn Helgaas wrote:
> 
> [...]
> 
>> On Mon, May 23, 2016 at 03:16:01PM +0000, Gabriele Paoloni wrote:
>> I don't think of ECAM support itself as a "driver".  It's just a
>> service available to drivers, similar to OF resource parsing.
>> 
>> Per PCI Firmware r3.2, sec 4.1.5, "PNP0A03" means a PCI/PCI-X/PCIe
>> host bridge.  "PNP0A08" means a PCI-X Mode 2 or PCIe bridge that
>> supports extended config space.  It doesn't specify how we access that
>> config space, so I think hardware with non-standard ECAM should still
>> have PNP0A03 and PNP0A08 in _CID or _HID.
>> 
>> "ECAM" as used in the specs (PCIe r3.0, sec 7.2.2, and PCI Firmware
>> r3.2, sec 4.1) means:
>> 
>>  (a) a memory-mapped model for config space access, and
>>  (b) a specific mapping of address bits to bus/device/function/
>>      register
>> 
>> MCFG and _CBA assume both (a) and (b), so I think a device with
>> non-standard ECAM mappings should not be described in MCFG or _CBA.
>> 
>> If a bridge has ECAM with non-standard mappings, I think either a
>> vendor-specific _HID or a device-specific method, e.g., _DSM, could
>> communicate that.
>> 
>> Jon, I agree that we should avoid describing non-standardized hardware
>> in Linux-specific ways.  Is there a mechanism in use already?  How
>> does Windows handle this?  DMI is a poor long-term solution because it
>> requires ongoing maintenance for new platforms, but I think it's OK
>> for getting started with platforms already shipping.
>> 
>> A _DSM has the advantage that once it is defined and supported, OEMs
>> can ship new platforms without requiring a new quirk or a new _HID to
>> be added to a driver.
>> 
>> There would still be the problem of config access before the namespace
>> is available, i.e., the MCFG use case.  I don't know how important
>> that is.  Defining an MCFG extension seems like the most obvious
>> solution.
> 
> Your summary above is a perfect representation of the situation.
> 
> We had an opportunity to sync-up on the current status of ACPI PCI
> for ARM64 (and talked about a way forward for this series, which
> includes quirks handling), let me summarize it here for everyone
> involved so that we can agree on a way forward.
> 
> 1) ACPI PCI support for PNP0A03/PNP0A08 host bridges on top of MCFG
>   ECAM for config space is basically ready (Tomasz and JC addressed
>   Rafael's concerns in relation to ARM64 specific code, and managed
>   to find a way to allocate domain numbers in preparation for Arnd
>   pci_create_root_bus() clean-up, v8 to be posted shortly and should
>   be final). This provides support for de-facto ACPI/PCI ECAM base
>   standard for ARM64 (with a clean-split between generic code and ARM64
>   bits, where ARM64, like X86 and IA64, manages in arch code IO space and
>   PCI resources, to be further consolidated in the near future).
>   I do not think anyone can complain about the generality of what we
>   achieved, for systems that are PCI standard (yes, PCI STANDARD) this
>   would just be sufficient.
> 2) In a real world (1) is not enough. Some ARM64 platforms, not entirely
>   ECAM compliant, already shipped with the corresponding firmware that
>   we can't update. HW has ECAM quirks and to work around it in the kernel
>   we put forward many solutions to the problem, it is time we found a
>   solution (when, of course, (1) is completed and upstream).
>   Using the MCFG table OEMID matching floated around in this thread
>   would work fine for most of the platforms (and cross-OS) that have
>   shipped with HW ECAM quirks, so I think that's the starting point for
>   our solution and that's how we can sort this out, _today_.
> 
>   The solution is a trivial look-up table:
>   MCFG OEMID <-> PCI config space ops
> 
> 3) (2) does not just work on some platforms (and we can't predict the
>   future either - actually I can, it is three letters, ECAM), simply
>   because MCFG OEMID matching does not provide a way to attach further
>   data to the MCFG (eg if config space for, say, bus 0 domain 0, is not
>   ECAM compliant, the config region can't be handled and must not be
>   handled through a corresponding MCFG region.
>   That's the problem Gabriele is facing and wants to solve through
>   something like:
> 
>   https://lkml.org/lkml/2016/3/9/91
> 
>   in the respective ACPI tables-bindings. It may be an idea worth
>   pursuing, it does not solve (2) simply because that FW has shipped,
>   we can't patch it any longer.
> 
> Hence to finally support ACPI PCI on ARM64 I suggest we carry out the
> following steps, in order:
> 
> - Let's complete/merge (1), that's fundamental to this whole thread
> - On top of (1) we apply a quirking mechanism based on (2) that allows
>  us to boot mainline with boxes shipping today with no FW update required.
> - We devise a way to handle quirks that is more generic than (2) so that
>  can we can accomodate further platforms that can't rely on (2) but
>  have more leeway in terms of FW updates.
> 
> I hope that's a reasonable plan, Tomasz's v8 series coming to kick it off.
> 
> Thank you,
> Lorenzo


From javier at osg.samsung.com  Tue May 24 10:41:00 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 24 May 2016 13:41:00 -0400
Subject: [PATCH 0/2] ARM: dts: Fix imprecise external abort error when
 accessing Exynos MFC
Message-ID: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>

Hello,

This series fixes an imprecise external abort error when accessing the
Exynos MFC registers due the power domain configuration requiring the
aclk333 clock to be enabled during a domain switch.

There isn't a dependency between the clock and Linux Samsung SoC trees
because the CLK_ACLK333 clock ID is already defined so the patches can
be picked indepedently by the relevant subsystem maintainers.

Best regards,
Javier


Javier Martinez Canillas (2):
  clk: exynos5420: Set ID for aclk333 gate clock
  ARM: dts: Add async-bridge clock to MFC power domain for Exynos5420

 arch/arm/boot/dts/exynos5420.dtsi    | 5 +++--
 drivers/clk/samsung/clk-exynos5420.c | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

-- 
2.5.5



From javier at osg.samsung.com  Tue May 24 10:41:01 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 24 May 2016 13:41:01 -0400
Subject: [PATCH 1/2] clk: exynos5420: Set ID for aclk333 gate clock
In-Reply-To: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
References: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
Message-ID: <1464111662-15336-2-git-send-email-javier@osg.samsung.com>

The aclk333 clock needs to be ungated during the MFC power domain switch,
so set the clock ID to allow the Exynos power domain logic to lookup this
clock if is defined in the MFC PD device tree node.

Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
---

 drivers/clk/samsung/clk-exynos5420.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 92382cef9f90..469bcae5de3a 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -946,7 +946,7 @@ static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = {
 			GATE_BUS_TOP, 13, 0, 0),
 	GATE(0, "aclk166", "mout_user_aclk166",
 			GATE_BUS_TOP, 14, CLK_IGNORE_UNUSED, 0),
-	GATE(0, "aclk333", "mout_user_aclk333",
+	GATE(CLK_ACLK333, "aclk333", "mout_user_aclk333",
 			GATE_BUS_TOP, 15, CLK_IGNORE_UNUSED, 0),
 	GATE(0, "aclk400_isp", "mout_user_aclk400_isp",
 			GATE_BUS_TOP, 16, 0, 0),
-- 
2.5.5



From javier at osg.samsung.com  Tue May 24 10:41:02 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 24 May 2016 13:41:02 -0400
Subject: [PATCH 2/2] ARM: dts: Add async-bridge clock to MFC power domain for
 Exynos5420
In-Reply-To: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
References: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
Message-ID: <1464111662-15336-3-git-send-email-javier@osg.samsung.com>

The MFC IP is also inter-connected by an Async-Bridge so the CLK_ACLK333
has to be ungated during a power domain switch. Trying to do it when the
clock is gated will fail and lead to an imprecise external abort error
when the driver tries to access the MFC registers with the PD disabled.

For example, if the s5p-mfc module is removed and the MFC PD turned off:

[  186.835606] Power domain power-domain at 10044060 disable failed
[  186.835671] s5p-mfc 11000000.codec: Removing 11000000.codec
[  186.837670] Power domain power-domain at 10044060 disable failed

And when the module is inserted again:

[ 2395.176956] s5p_mfc_wait_for_done_dev:34: Interrupt (dev->int_type:0, command:12) timed out
[ 2395.177031] s5p_mfc_init_hw:272: Failed to load firmware
[ 2395.177384] Unhandled fault: imprecise external abort (0x1406) at 0x00000000
[ 2395.177441] pgd = ec3b4000
[ 2395.177467] [00000000] *pgd=00000000
[ 2395.177507] Internal error: : 1406 [#1] PREEMPT SMP ARM
[ 2395.177550] Modules linked in: s5p_mfc mwifiex_sdio mwifiex uvcvideo s5p_jpeg v4l2_mem2mem videobuf2_vmalloc videobuf2_dma_contig videobuf2_memops videobuf2_v4l2 videobuf2_core v4l2_common videodev media [last unloaded: s5p_mfc]
[ 2395.177774] CPU: 1 PID: 2382 Comm: v4l_id Tainted: G        W       4.6.0-rc6-next-20160502-00010-g7730dc64d2c1-dirty #179
[ 2395.177857] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[ 2395.177906] task: ed275500 ti: e6c8c000 task.ti: e6c8c000
[ 2395.177996] PC is at s5p_mfc_reset+0x1c4/0x284 [s5p_mfc]
[ 2395.178057] LR is at s5p_mfc_reset+0x1a4/0x284 [s5p_mfc]

This patch fixes this issue by adding the CLK_ACLK333 as an Async-Bridge
clock for the MFC power domain, so the PD configuration works properly.

Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

 arch/arm/boot/dts/exynos5420.dtsi | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 4c8523471c65..f3e9d873633e 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -313,8 +313,9 @@
 	mfc_pd: power-domain at 10044060 {
 		compatible = "samsung,exynos4210-pd";
 		reg = <0x10044060 0x20>;
-		clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_USER_ACLK333>;
-		clock-names = "oscclk", "clk0";
+		clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_USER_ACLK333>,
+			 <&clock CLK_ACLK333>;
+		clock-names = "oscclk", "clk0","asb0";
 		#power-domain-cells = <0>;
 	};
 
-- 
2.5.5



From robin.murphy at arm.com  Tue May 24 10:55:41 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 24 May 2016 18:55:41 +0100
Subject: [PATCH 2/3] ARM: Remove orphaned __addr_ok() definition
In-Reply-To: <4656e09e40e832b2690fb0280975c70a541fb7ef.1464111462.git.robin.murphy@arm.com>
References: <4656e09e40e832b2690fb0280975c70a541fb7ef.1464111462.git.robin.murphy@arm.com>
Message-ID: <ada1b17d509429958e4117b86d37ec3f93ec2753.1464111462.git.robin.murphy@arm.com>

Since commit 8c56cc8be5b3 ("ARM: 7449/1: use generic strnlen_user and
strncpy_from_user functions"), the definition of __addr_ok() has been
languishing unused; eradicate the sucker.

CC: Russell King <linux at armlinux.org.uk>
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 arch/arm/include/asm/uaccess.h | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 35c9db857ebe..7badc3e55109 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -104,14 +104,6 @@ static inline void set_fs(mm_segment_t fs)
 
 #define segment_eq(a, b)	((a) == (b))
 
-#define __addr_ok(addr) ({ \
-	unsigned long flag; \
-	__asm__("cmp %2, %0; movlo %0, #0" \
-		: "=&r" (flag) \
-		: "0" (current_thread_info()->addr_limit), "r" (addr) \
-		: "cc"); \
-	(flag == 0); })
-
 /* We use 33-bit arithmetic here... */
 #define __range_ok(addr, size) ({ \
 	unsigned long flag, roksum; \
-- 
2.8.1.dirty



From robin.murphy at arm.com  Tue May 24 10:55:40 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 24 May 2016 18:55:40 +0100
Subject: [PATCH 1/3] arm64: Remove orphaned __addr_ok() definition
Message-ID: <4656e09e40e832b2690fb0280975c70a541fb7ef.1464111462.git.robin.murphy@arm.com>

Since commit 12a0ef7b0ac3 ("arm64: use generic strnlen_user and
strncpy_from_user functions"), the definition of __addr_ok() has been
languishing unused; eradicate the sucker.

CC: Will Deacon <will.deacon at arm.com>
CC: Catalin Marinas <catalin.marinas at arm.com>
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 arch/arm64/include/asm/uaccess.h | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 0685d74572af..9e397a542756 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -81,19 +81,6 @@ static inline void set_fs(mm_segment_t fs)
 #define segment_eq(a, b)	((a) == (b))
 
 /*
- * Return 1 if addr < current->addr_limit, 0 otherwise.
- */
-#define __addr_ok(addr)							\
-({									\
-	unsigned long flag;						\
-	asm("cmp %1, %0; cset %0, lo"					\
-		: "=&r" (flag)						\
-		: "r" (addr), "0" (current_thread_info()->addr_limit)	\
-		: "cc");						\
-	flag;								\
-})
-
-/*
  * Test whether a block of memory is a valid user space address.
  * Returns 1 if the range is valid, 0 otherwise.
  *
-- 
2.8.1.dirty



From robin.murphy at arm.com  Tue May 24 10:55:42 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 24 May 2016 18:55:42 +0100
Subject: [PATCH 3/3] openrisc: Remove orphaned __addr_ok() definition
In-Reply-To: <4656e09e40e832b2690fb0280975c70a541fb7ef.1464111462.git.robin.murphy@arm.com>
References: <4656e09e40e832b2690fb0280975c70a541fb7ef.1464111462.git.robin.murphy@arm.com>
Message-ID: <2d34650818ced1b3c362dfc75d087b70c0f7edef.1464111462.git.robin.murphy@arm.com>

Since commit b48b2c3e5043 ("openrisc: use generic strnlen_user()
function"), the definition of __addr_ok() has been languishing unused;
eradicate the sucker.

CC: Jonas Bonn <jonas at southpole.se>
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---
 arch/openrisc/include/asm/uaccess.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/arch/openrisc/include/asm/uaccess.h b/arch/openrisc/include/asm/uaccess.h
index a6bd07ca3d6c..74bcb34c6d0b 100644
--- a/arch/openrisc/include/asm/uaccess.h
+++ b/arch/openrisc/include/asm/uaccess.h
@@ -59,9 +59,6 @@
  */
 #define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs()-size))
 
-/* Ensure that addr is below task's addr_limit */
-#define __addr_ok(addr) ((unsigned long) addr < get_fs())
-
 #define access_ok(type, addr, size) \
 	__range_ok((unsigned long)addr, (unsigned long)size)
 
-- 
2.8.1.dirty



From rob.rice at broadcom.com  Tue May 24 11:07:27 2016
From: rob.rice at broadcom.com (Rob Rice)
Date: Tue, 24 May 2016 14:07:27 -0400
Subject: [PATCH 0/3] Add Broadcom PDC mailbox driver
Message-ID: <1464113250-15629-1-git-send-email-rob.rice@broadcom.com>

From: Rob Rice <rrice at broadcom.com>

The Broadcom PDC mailbox driver is a ring manager for the Broadcom
Secure Processing Unit (SPU) kernel driver and other mailbox clients.
The PDC driver registers with the Linux mailbox framework a mailbox
controller, once for each PDC instance. Ring 0 for each PDC is registered as
a mailbox channel. The PDC driver uses interrupts to determine when ring
transfers to and from an offload engine are complete. The PDC driver uses
threaded IRQs so that response messages are handled outside of interrupt
context.

Rob Rice (3):
  dt-bindings: add bindings documentation for PDC driver.
  mailbox: Add Broadcom PDC mailbox driver
  arm64: dts: Add Broadcom Northstar2 device tree entries for PDC
    driver.

 .../bindings/mailbox/brcm,iproc-pdc-mbox.txt       |   23 +
 arch/arm64/boot/dts/broadcom/ns2.dtsi              |   36 +
 drivers/mailbox/Kconfig                            |    9 +
 drivers/mailbox/Makefile                           |    2 +
 drivers/mailbox/mailbox-pdc/Makefile               |    8 +
 drivers/mailbox/mailbox-pdc/pdc.c                  | 1181 ++++++++++++++++++++
 drivers/mailbox/mailbox-pdc/pdc.h                  |  303 +++++
 drivers/mailbox/mailbox-pdc/pdc_debug.c            |  101 ++
 drivers/mailbox/mailbox-pdc/pdc_debug.h            |   24 +
 include/linux/mailbox/brcm-message.h               |   56 +
 10 files changed, 1743 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/brcm,iproc-pdc-mbox.txt
 create mode 100644 drivers/mailbox/mailbox-pdc/Makefile
 create mode 100644 drivers/mailbox/mailbox-pdc/pdc.c
 create mode 100644 drivers/mailbox/mailbox-pdc/pdc.h
 create mode 100644 drivers/mailbox/mailbox-pdc/pdc_debug.c
 create mode 100644 drivers/mailbox/mailbox-pdc/pdc_debug.h
 create mode 100644 include/linux/mailbox/brcm-message.h

-- 
2.1.0



From rob.rice at broadcom.com  Tue May 24 11:07:28 2016
From: rob.rice at broadcom.com (Rob Rice)
Date: Tue, 24 May 2016 14:07:28 -0400
Subject: [PATCH 1/3] dt-bindings: add bindings documentation for PDC driver.
In-Reply-To: <1464113250-15629-1-git-send-email-rob.rice@broadcom.com>
References: <1464113250-15629-1-git-send-email-rob.rice@broadcom.com>
Message-ID: <1464113250-15629-2-git-send-email-rob.rice@broadcom.com>

From: Rob Rice <rrice at broadcom.com>

Add the device tree binding documentation for the PDC hardware
in Broadcom iProc SoCs.

Signed-off-by: Rob Rice <rob.rice at broadcom.com>
Reviewed-by: Ray Jui <ray.jui at broadcom.com>
Reviewed-by: Anup Patel <anup.patel at broadcom.com>
Reviewed-by: Scott Branden <scott.branden at broadcom.com>
---
 .../bindings/mailbox/brcm,iproc-pdc-mbox.txt       | 23 ++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/brcm,iproc-pdc-mbox.txt

diff --git a/Documentation/devicetree/bindings/mailbox/brcm,iproc-pdc-mbox.txt b/Documentation/devicetree/bindings/mailbox/brcm,iproc-pdc-mbox.txt
new file mode 100644
index 0000000..411ccf4
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/brcm,iproc-pdc-mbox.txt
@@ -0,0 +1,23 @@
+The PDC driver manages data transfer to and from various offload engines
+on some Broadcom SoCs. An SoC may have multiple PDC hardware blocks. There is
+one device tree entry per block.
+
+Required properties:
+- compatible : Should be "brcm,iproc-pdc-mbox".
+- reg: Should contain PDC registers location and length.
+- interrupts: Should contain the IRQ line for the PDC.
+- #mbox-cells: 1
+- brcm,rx-status-len: Length of metadata preceding received frames, in bytes.
+
+Optional properties:
+- brcm,use-bcm-hdr:  present if a BCM header precedes each frame.
+
+Example:
+	pdc0: iproc-pdc0 at 0x612c0000 {
+		compatible = "brcm,iproc-pdc-mbox";
+		reg = <0 0x612c0000 0 0x445>;  /* PDC FS0 regs */
+		interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+		#mbox-cells = <1>;   /* one cell per mailbox channel */
+		brcm,rx-status-len = <32>;
+		brcm,use-bcm-hdr;
+	};
-- 
2.1.0



From rob.rice at broadcom.com  Tue May 24 11:07:29 2016
From: rob.rice at broadcom.com (Rob Rice)
Date: Tue, 24 May 2016 14:07:29 -0400
Subject: [PATCH 2/3] mailbox: Add Broadcom PDC mailbox driver
In-Reply-To: <1464113250-15629-1-git-send-email-rob.rice@broadcom.com>
References: <1464113250-15629-1-git-send-email-rob.rice@broadcom.com>
Message-ID: <1464113250-15629-3-git-send-email-rob.rice@broadcom.com>

From: Rob Rice <rrice at broadcom.com>

The Broadcom PDC mailbox driver is a mailbox controller that
manages data transfers to and from one or more offload engines.

Signed-off-by: Rob Rice <rob.rice at broadcom.com>
Reviewed-by: Scott Branden <scott.branden at broadcom.com>
Reviewed-by: Ray Jui <ray.jui at broadcom.com>
---
 drivers/mailbox/Kconfig                 |    9 +
 drivers/mailbox/Makefile                |    2 +
 drivers/mailbox/mailbox-pdc/Makefile    |    8 +
 drivers/mailbox/mailbox-pdc/pdc.c       | 1181 +++++++++++++++++++++++++++++++
 drivers/mailbox/mailbox-pdc/pdc.h       |  303 ++++++++
 drivers/mailbox/mailbox-pdc/pdc_debug.c |  101 +++
 drivers/mailbox/mailbox-pdc/pdc_debug.h |   24 +
 include/linux/mailbox/brcm-message.h    |   56 ++
 8 files changed, 1684 insertions(+)
 create mode 100644 drivers/mailbox/mailbox-pdc/Makefile
 create mode 100644 drivers/mailbox/mailbox-pdc/pdc.c
 create mode 100644 drivers/mailbox/mailbox-pdc/pdc.h
 create mode 100644 drivers/mailbox/mailbox-pdc/pdc_debug.c
 create mode 100644 drivers/mailbox/mailbox-pdc/pdc_debug.h
 create mode 100644 include/linux/mailbox/brcm-message.h

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 5305923..19c8c9a 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -123,4 +123,13 @@ config XGENE_SLIMPRO_MBOX
 	  It is used to send short messages between ARM64-bit cores and
 	  the SLIMpro Management Engine, primarily for PM. Say Y here if you
 	  want to use the APM X-Gene SLIMpro IPCM support.
+
+config BCM_PDC_MBOX
+	tristate "Broadcom PDC Mailbox"
+	depends on ARM64
+	default ARCH_BCM_IPROC
+	help
+	  Mailbox implementation for the Broadcom PDC ring manager,
+	  which provides access to various offload engines on Broadcom
+	  SoCs. Say Y here if you want to use the Broadcom PDC.
 endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 0be3e74..2c14a03 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -25,3 +25,5 @@ obj-$(CONFIG_TI_MESSAGE_MANAGER) += ti-msgmgr.o
 obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o
 
 obj-$(CONFIG_HI6220_MBOX)	+= hi6220-mailbox.o
+
+obj-$(CONFIG_BCM_PDC_MBOX)	+= mailbox-pdc/
diff --git a/drivers/mailbox/mailbox-pdc/Makefile b/drivers/mailbox/mailbox-pdc/Makefile
new file mode 100644
index 0000000..5dc78c3
--- /dev/null
+++ b/drivers/mailbox/mailbox-pdc/Makefile
@@ -0,0 +1,8 @@
+# Makefile for Broadcom PDC Mailbox driver
+
+# Uncomment to enable debug tracing in the PDC driver
+# CFLAGS_pdc.o := -DDEBUG
+# CFLAGS_pdc_debug.o := -DDEBUG
+
+pdc-mbox-objs := pdc.o pdc_debug.o
+obj-$(CONFIG_BCM_PDC_MBOX) := pdc-mbox.o
diff --git a/drivers/mailbox/mailbox-pdc/pdc.c b/drivers/mailbox/mailbox-pdc/pdc.c
new file mode 100644
index 0000000..1c24ea8
--- /dev/null
+++ b/drivers/mailbox/mailbox-pdc/pdc.c
@@ -0,0 +1,1181 @@
+/*
+ * Copyright 2016 Broadcom
+ *
+ * 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 (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+
+/*
+ * Broadcom PDC Mailbox Driver
+ * The PDC provides a ring based programming interface to one or more hardware
+ * offload engines. For example, the PDC driver works with both SPU-M and SPU2
+ * cryptographic offload hardware. In some chips the PDC is referred to as MDE.
+ *
+ * The PDC driver registers with the Linux mailbox framework as a mailbox
+ * controller, once for each PDC instance. Ring 0 for each PDC is registered as
+ * a mailbox channel. The PDC driver uses interrupts to determine when data
+ * transfers to and from an offload engine are complete. The PDC driver uses
+ * threaded IRQs so that response messages are handled outside of interrupt
+ * context.
+ *
+ * The PDC driver allows multiple messages to be pending in the descriptor
+ * rings. The tx_msg_start descriptor index indicates where the last message
+ * starts. The txin_numd value at this index indicates how many descriptor
+ * indexes make up the message. Similar state is kept on the receive side. When
+ * an rx interrupt indicates a response is ready, the PDC driver processes numd
+ * descriptors from the tx and rx ring, thus processing one response at a time.
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/mailbox_controller.h>
+#include <linux/mailbox/brcm-message.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-direction.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+
+#include "pdc.h"
+#include "pdc_debug.h"
+
+/* Length of BCM header at start of SPU msg, in bytes */
+#define BCM_HDR_LEN  8
+
+/*
+ * PDC driver reserves ringset 0 on each SPU for its own use. The driver does
+ * not currently support use of multiple ringsets on a single PDC engine.
+ */
+#define PDC_RINGSET  0
+
+/*
+ * Interrupt mask and status definitions. Enable interrupts for tx and rx on
+ * ring 0
+ */
+#define PDC_XMTINT_0         (24 + PDC_RINGSET)
+#define PDC_RCVINT_0         (16 + PDC_RINGSET)
+#define PDC_XMTINTEN_0       BIT(PDC_XMTINT_0)
+#define PDC_RCVINTEN_0       BIT(PDC_RCVINT_0)
+#define PDC_INTMASK  (PDC_XMTINTEN_0 | PDC_RCVINTEN_0)
+#define PDC_LAZY_FRAMECOUNT  1
+#define PDC_LAZY_TIMEOUT     10000
+#define PDC_LAZY_INT  (PDC_LAZY_TIMEOUT | (PDC_LAZY_FRAMECOUNT << 24))
+#define PDC_INTMASK_OFFSET   0x24
+#define PDC_INTSTATUS_OFFSET 0x20
+#define PDC_RCVLAZY0_OFFSET  (0x30 + 4 * PDC_RINGSET)
+
+/*
+ * For SPU2, configure MDE_CKSUM_CONTROL to write 17 bytes of metadata
+ * before frame
+ */
+#define PDC_SPU2_RESP_HDR_LEN  17
+#define PDC_CKSUM_CTRL         BIT(27)
+#define PDC_CKSUM_CTRL_OFFSET  0x400
+
+#define PDC_SPUM_RESP_HDR_LEN  32
+
+/*
+ * Sets the following bits for write to transmit control reg:
+ *  0    - XmtEn - enable activity on the tx channel
+ * 11    - PtyChkDisable - parity check is disabled
+ * 20:18 - BurstLen = 3 -> 2^7 = 128 byte data reads from memory
+ */
+#define PDC_TX_CTL              0x000C0801
+
+/*
+ * Sets the following bits for write to receive control reg:
+ * 0     - RcvEn - enable activity on the rx channel
+ * 7:1   - RcvOffset - size in bytes of status region at start of rx frame buf
+ * 9     - SepRxHdrDescEn - place start of new frames only in descriptors
+ *                          that have StartOfFrame set
+ * 10    - OflowContinue - on rx FIFO overflow, clear rx fifo, discard all
+ *                         remaining bytes in current frame, report error
+ *                         in rx frame status for current frame
+ * 11    - PtyChkDisable - parity check is disabled
+ * 20:18 - BurstLen = 3 -> 2^7 = 128 byte data reads from memory
+ */
+#define PDC_RX_CTL              0x000C0E01
+
+#define CRYPTO_D64_RS0_CD_MASK   ((PDC_RING_ENTRIES * RING_ENTRY_SIZE) - 1)
+
+/* descriptor flags */
+#define D64_CTRL1_EOT   BIT(28)	/* end of descriptor table */
+#define D64_CTRL1_IOC   BIT(29)	/* interrupt on complete */
+#define D64_CTRL1_EOF   BIT(30)	/* end of frame */
+#define D64_CTRL1_SOF   BIT(31)	/* start of frame */
+
+#define RX_STATUS_OVERFLOW       0x00800000
+#define RX_STATUS_LEN            0x0000FFFF
+
+#define PDC_TXREGS_OFFSET  0x200
+#define PDC_RXREGS_OFFSET  0x220
+
+/* Maximum size buffer the DMA engine can handle */
+#define PDC_DMA_BUF_MAX 16384
+
+/* Global variables */
+
+struct pdc_globals {
+	/* Actual number of SPUs in hardware, as reported by device tree */
+	u32 num_spu;
+};
+
+static struct pdc_globals pdcg;
+
+/**
+ * pdc_build_rxd() - Build DMA descriptor to receive SPU result.
+ * @pdcs:      PDC state for SPU that will generate result
+ * @dma_addr:  DMA address of buffer that descriptor is being built for
+ * @buf_len:   Length of the receive buffer, in bytes
+ * @flags:     Flags to be stored in descriptor
+ */
+static inline void
+pdc_build_rxd(struct pdc_state *pdcs, dma_addr_t dma_addr,
+	      u32 buf_len, u32 flags)
+{
+	struct device *dev = &pdcs->pdev->dev;
+
+	dev_dbg(dev,
+		"Writing rx descriptor for PDC %u at index %u with length %u. flags %#x\n",
+		pdcs->pdc_idx, pdcs->rxout, buf_len, flags);
+
+	iowrite32(lower_32_bits(dma_addr),
+		  (void *)&pdcs->rxd_64[pdcs->rxout].addrlow);
+	iowrite32(upper_32_bits(dma_addr),
+		  (void *)&pdcs->rxd_64[pdcs->rxout].addrhigh);
+	iowrite32(flags, (void *)&pdcs->rxd_64[pdcs->rxout].ctrl1);
+	iowrite32(buf_len, (void *)&pdcs->rxd_64[pdcs->rxout].ctrl2);
+	/* bump ring index and return */
+	pdcs->rxout = NEXTRXD(pdcs->rxout, pdcs->nrxpost);
+}
+
+/**
+ * pdc_build_txd() - Build a DMA descriptor to transmit a SPU request to
+ * hardware.
+ * @pdcs:        PDC state for the SPU that will process this request
+ * @dma_addr:    DMA address of packet to be transmitted
+ * @buf_len:     Length of tx buffer, in bytes
+ * @flags:       Flags to be stored in descriptor
+ */
+static inline void
+pdc_build_txd(struct pdc_state *pdcs, dma_addr_t dma_addr, u32 buf_len,
+	      u32 flags)
+{
+	struct device *dev = &pdcs->pdev->dev;
+
+	dev_dbg(dev,
+		"Writing tx descriptor for PDC %u at index %u with length %u, flags %#x\n",
+		pdcs->pdc_idx, pdcs->txout, buf_len, flags);
+
+	iowrite32(lower_32_bits(dma_addr),
+		  (void *)&pdcs->txd_64[pdcs->txout].addrlow);
+	iowrite32(upper_32_bits(dma_addr),
+		  (void *)&pdcs->txd_64[pdcs->txout].addrhigh);
+	iowrite32(flags, (void *)&pdcs->txd_64[pdcs->txout].ctrl1);
+	iowrite32(buf_len, (void *)&pdcs->txd_64[pdcs->txout].ctrl2);
+
+	/* bump ring index and return */
+	pdcs->txout = NEXTTXD(pdcs->txout, pdcs->ntxpost);
+}
+
+/**
+ * pdc_receive() - Receive a response message from a given SPU.
+ * @pdcs:    PDC state for the SPU to receive from
+ * @mssg:    mailbox message to be returned to client
+ *
+ * When the return code indicates success, the response message is available in
+ * the receive buffers provided prior to submission of the request.
+ *
+ * Input:
+ *   pdcs - PDC state structure for the SPU to be polled
+ *   mssg - mailbox message to be returned to client. This function sets the
+ *	    context pointer on the message to help the client associate the
+ *	    response with a request.
+ *
+ * Return:  PDC_SUCCESS if one or more receive descriptors was processed
+ *          -EAGAIN indicates that no response message is available
+ *          -EIO an error occurred
+ */
+static int
+pdc_receive(struct pdc_state *pdcs, struct brcm_message *mssg)
+{
+	struct device *dev = &pdcs->pdev->dev;
+	u32 len, rx_status;
+	u32 num_frags;
+	int i;
+	u8 *resp_hdr;    /* virtual addr of start of resp message DMA header */
+	u32 frags_rdy;   /* number of fragments ready to read */
+	u32 rx_idx;      /* ring index of start of receive frame */
+	dma_addr_t resp_hdr_daddr;
+
+	spin_lock(&pdcs->pdc_lock);
+
+	/*
+	 * return if a complete response message is not yet ready.
+	 * rxin_numd[rxin] is the number of fragments in the next msg
+	 * to read.
+	 */
+	frags_rdy = NRXDACTIVE(pdcs->rxin, pdcs->last_rx_curr, pdcs->nrxpost);
+	if ((frags_rdy == 0) || (frags_rdy < pdcs->rxin_numd[pdcs->rxin])) {
+		/* See if the hw has written more fragments than we know */
+		pdcs->last_rx_curr =
+		    (ioread32((void *)&pdcs->rxregs_64->status0) &
+		     CRYPTO_D64_RS0_CD_MASK) / RING_ENTRY_SIZE;
+		frags_rdy = NRXDACTIVE(pdcs->rxin, pdcs->last_rx_curr,
+				       pdcs->nrxpost);
+		if ((frags_rdy == 0) ||
+		    (frags_rdy < pdcs->rxin_numd[pdcs->rxin])) {
+			/* No response ready */
+			spin_unlock(&pdcs->pdc_lock);
+			return -EAGAIN;
+		}
+		/* can't read descriptors/data until write index is read */
+		rmb();
+	}
+
+	num_frags = pdcs->txin_numd[pdcs->txin];
+	dma_unmap_sg(dev, pdcs->src_sg[pdcs->txin],
+		     sg_nents(pdcs->src_sg[pdcs->txin]), DMA_TO_DEVICE);
+
+	for (i = 0; i < num_frags; i++)
+		pdcs->txin = NEXTTXD(pdcs->txin, pdcs->ntxpost);
+
+	dev_dbg(dev, "PDC %u reclaimed %d tx descriptors",
+		pdcs->pdc_idx, num_frags);
+
+	rx_idx = pdcs->rxin;
+	num_frags = pdcs->rxin_numd[rx_idx];
+	/* Return opaque context with result */
+	mssg->ctx = pdcs->rxp_ctx[rx_idx];
+	pdcs->rxp_ctx[rx_idx] = NULL;
+	resp_hdr = pdcs->resp_hdr[rx_idx];
+	resp_hdr_daddr = pdcs->resp_hdr_daddr[rx_idx];
+	dma_unmap_sg(dev, pdcs->dst_sg[rx_idx],
+		     sg_nents(pdcs->dst_sg[rx_idx]), DMA_FROM_DEVICE);
+
+	for (i = 0; i < num_frags; i++)
+		pdcs->rxin = NEXTRXD(pdcs->rxin, pdcs->nrxpost);
+
+	spin_unlock(&pdcs->pdc_lock);
+
+	dev_dbg(dev, "PDC %u reclaimed %d rx descriptors",
+		pdcs->pdc_idx, num_frags);
+
+	dev_dbg(dev,
+		"PDC %u txin %u, txout %u, rxin %u, rxout %u, last_rx_curr %u\n",
+		pdcs->pdc_idx, pdcs->txin, pdcs->txout, pdcs->rxin,
+		pdcs->rxout, pdcs->last_rx_curr);
+
+	if (pdcs->pdc_resp_hdr_len == PDC_SPUM_RESP_HDR_LEN) {
+		/*
+		 * For SPU-M, get length of response msg and rx overflow status.
+		 */
+		rx_status = *((u32 *)resp_hdr);
+		len = rx_status & RX_STATUS_LEN;
+		dev_dbg(dev,
+			"SPU response length %u bytes", len);
+		if (unlikely(((rx_status & RX_STATUS_OVERFLOW) || (!len)))) {
+			if (rx_status & RX_STATUS_OVERFLOW) {
+				dev_err_ratelimited(dev,
+						    "crypto receive overflow");
+				pdcs->rx_oflow++;
+			} else {
+				dev_info_ratelimited(dev, "crypto rx len = 0");
+			}
+			return -EIO;
+		}
+	}
+
+	dma_pool_free(pdcs->rx_buf_pool, resp_hdr, resp_hdr_daddr);
+
+	pdcs->pdc_replies++;
+	/* if we read one or more rx descriptors, claim success */
+	if (num_frags > 0)
+		return PDC_SUCCESS;
+	else
+		return -EIO;
+}
+
+/**
+ * pdc_tx_list_sg_add() - Add the buffers in a scatterlist to the transmit
+ * descriptors for a given SPU. The scatterlist buffers contain the data for a
+ * SPU request message.
+ * @spu_idx:   The index of the SPU to submit the request to, [0, max_spu)
+ * @sg:        Scatterlist whose buffers contain part of the SPU request
+ *
+ * If a scatterlist buffer is larger than PDC_DMA_BUF_MAX, multiple descriptors
+ * are written for that buffer, each <= PDC_DMA_BUF_MAX byte in length.
+ *
+ * Return: PDC_SUCCESS if successful
+ *         < 0 otherwise
+ */
+static int pdc_tx_list_sg_add(struct pdc_state *pdcs, struct scatterlist *sg)
+{
+	u32 flags = 0;
+	u32 eot;
+	u32 tx_avail;
+
+	/*
+	 * Num descriptors needed. Conservatively assume we need a descriptor
+	 * for every entry in sg.
+	 */
+	u32 num_desc;
+	u32 desc_w = 0;	/* Number of tx descriptors written */
+	u32 bufcnt;	/* Number of bytes of buffer pointed to by descriptor */
+	dma_addr_t databufptr;	/* DMA address to put in descriptor */
+
+	num_desc = (u32)sg_nents(sg);
+
+	/* check whether enough tx descriptors are available */
+	tx_avail = pdcs->ntxpost - NTXDACTIVE(pdcs->txin, pdcs->txout,
+					      pdcs->ntxpost);
+	if (unlikely(num_desc > tx_avail)) {
+		pdcs->txnobuf++;
+		return -ENOSPC;
+	}
+
+	/* build tx descriptors */
+	if (pdcs->tx_msg_start == pdcs->txout) {
+		/* Start of frame */
+		pdcs->txin_numd[pdcs->tx_msg_start] = 0;
+		pdcs->src_sg[pdcs->txout] = sg;
+		flags = D64_CTRL1_SOF;
+	}
+
+	while (sg) {
+		if (unlikely(pdcs->txout == (pdcs->ntxd - 1)))
+			eot = D64_CTRL1_EOT;
+		else
+			eot = 0;
+
+		/*
+		 * If sg buffer larger than PDC limit, split across
+		 * multiple descriptors
+		 */
+		bufcnt = sg_dma_len(sg);
+		databufptr = sg_dma_address(sg);
+		while (bufcnt > PDC_DMA_BUF_MAX) {
+			pdc_build_txd(pdcs, databufptr, PDC_DMA_BUF_MAX,
+				      flags | eot);
+			desc_w++;
+			bufcnt -= PDC_DMA_BUF_MAX;
+			databufptr += PDC_DMA_BUF_MAX;
+			if (unlikely(pdcs->txout == (pdcs->ntxd - 1)))
+				eot = D64_CTRL1_EOT;
+			else
+				eot = 0;
+		}
+		sg = sg_next(sg);
+		if (!sg)
+			/* Writing last descriptor for frame */
+			flags |= (D64_CTRL1_EOF | D64_CTRL1_IOC);
+		pdc_build_txd(pdcs, databufptr, bufcnt, flags | eot);
+		desc_w++;
+		/* Clear start of frame after first descriptor */
+		flags &= ~D64_CTRL1_SOF;
+	}
+	pdcs->txin_numd[pdcs->tx_msg_start] += desc_w;
+
+	return PDC_SUCCESS;
+}
+
+/**
+ * pdc_tx_list_final() - Initiate DMA transfer of last frame written to tx
+ * ring.
+ * @pdcs:  PDC state for SPU to process the request
+ *
+ * Sets the index of the last descriptor written in both the rx and tx ring.
+ *
+ * Return: PDC_SUCCESS
+ */
+static int pdc_tx_list_final(struct pdc_state *pdcs)
+{
+	/*
+	 * write barrier to ensure all register writes are complete
+	 * before chip starts to process new request
+	 */
+	wmb();
+	iowrite32(pdcs->rxout << 4, (void *)&pdcs->rxregs_64->ptr);
+	iowrite32(pdcs->txout << 4, (void *)&pdcs->txregs_64->ptr);
+	pdcs->pdc_requests++;
+
+	return PDC_SUCCESS;
+}
+
+/**
+ * pdc_rx_list_init() - Start a new receive descriptor list for a given PDC.
+ * @pdcs:   PDC state for SPU handling request
+ * @dst_sg: scatterlist providing rx buffers for response to be returned to
+ *	    mailbox client
+ * @ctx:    Opaque context for this request
+ *
+ * Posts a single receive descriptor to hold the metadata that precedes a
+ * response. For example, with SPU-M, the metadata is a 32-byte DMA header and
+ * an 8-byte BCM header. Moves the msg_start descriptor indexes for both tx and
+ * rx to indicate the start of a new message.
+ *
+ * Return:  PDC_SUCCESS if successful
+ *          < 0 if an error (e.g., rx ring is full)
+ */
+static int pdc_rx_list_init(struct pdc_state *pdcs, struct scatterlist *dst_sg,
+			    void *ctx)
+{
+	u32 flags = 0;
+	u32 rx_avail;
+	u32 rx_pkt_cnt = 1;	/* Adding a single rx buffer */
+	dma_addr_t daddr;
+	void *vaddr;
+
+	rx_avail = pdcs->nrxpost - NRXDACTIVE(pdcs->rxin, pdcs->rxout,
+					      pdcs->nrxpost);
+	if (unlikely(rx_pkt_cnt > rx_avail)) {
+		pdcs->rxnobuf++;
+		return -ENOSPC;
+	}
+
+	/* allocate a buffer for the dma rx status */
+	vaddr = dma_pool_zalloc(pdcs->rx_buf_pool, GFP_ATOMIC, &daddr);
+	if (!vaddr)
+		return -ENOMEM;
+
+	/*
+	 * Update msg_start indexes for both tx and rx to indicate the start
+	 * of a new sequence of descriptor indexes that contain the fragments
+	 * of the same message.
+	 */
+	pdcs->rx_msg_start = pdcs->rxout;
+	pdcs->tx_msg_start = pdcs->txout;
+
+	/* This is always the first descriptor in the receive sequence */
+	flags = D64_CTRL1_SOF;
+	pdcs->rxin_numd[pdcs->rx_msg_start] = 1;
+
+	if (unlikely(pdcs->rxout == (pdcs->nrxd - 1)))
+		flags |= D64_CTRL1_EOT;
+
+	pdcs->rxp_ctx[pdcs->rxout] = ctx;
+	pdcs->dst_sg[pdcs->rxout] = dst_sg;
+	pdcs->resp_hdr[pdcs->rxout] = vaddr;
+	pdcs->resp_hdr_daddr[pdcs->rxout] = daddr;
+	pdc_build_rxd(pdcs, daddr, pdcs->pdc_resp_hdr_len, flags);
+	return PDC_SUCCESS;
+}
+
+/**
+ * pdc_rx_list_sg_add() - Add the buffers in a scatterlist to the receive
+ * descriptors for a given SPU. The caller must have already DMA mapped the
+ * scatterlist.
+ * @spu_idx:    Indicates which SPU the buffers are for
+ * @sg:         Scatterlist whose buffers are added to the receive ring
+ *
+ * If a receive buffer in the scatterlist is larger than PDC_DMA_BUF_MAX,
+ * multiple receive descriptors are written, each with a buffer <=
+ * PDC_DMA_BUF_MAX.
+ *
+ * Return: PDC_SUCCESS if successful
+ *         < 0 otherwise (e.g., receive ring is full)
+ */
+static int pdc_rx_list_sg_add(struct pdc_state *pdcs, struct scatterlist *sg)
+{
+	u32 flags = 0;
+	u32 rx_avail;
+
+	/*
+	 * Num descriptors needed. Conservatively assume we need a descriptor
+	 * for every entry from our starting point in the scatterlist.
+	 */
+	u32 num_desc;
+	u32 desc_w = 0;	/* Number of tx descriptors written */
+	u32 bufcnt;	/* Number of bytes of buffer pointed to by descriptor */
+	dma_addr_t databufptr;	/* DMA address to put in descriptor */
+
+	num_desc = (u32)sg_nents(sg);
+
+	rx_avail = pdcs->nrxpost - NRXDACTIVE(pdcs->rxin, pdcs->rxout,
+					      pdcs->nrxpost);
+	if (unlikely(num_desc > rx_avail)) {
+		pdcs->rxnobuf++;
+		return -ENOSPC;
+	}
+
+	while (sg) {
+		if (unlikely(pdcs->rxout == (pdcs->nrxd - 1)))
+			flags = D64_CTRL1_EOT;
+		else
+			flags = 0;
+
+		/*
+		 * If sg buffer larger than PDC limit, split across
+		 * multiple descriptors
+		 */
+		bufcnt = sg_dma_len(sg);
+		databufptr = sg_dma_address(sg);
+		while (bufcnt > PDC_DMA_BUF_MAX) {
+			pdc_build_rxd(pdcs, databufptr, PDC_DMA_BUF_MAX, flags);
+			desc_w++;
+			bufcnt -= PDC_DMA_BUF_MAX;
+			databufptr += PDC_DMA_BUF_MAX;
+			if (unlikely(pdcs->rxout == (pdcs->nrxd - 1)))
+				flags = D64_CTRL1_EOT;
+			else
+				flags = 0;
+		}
+		pdc_build_rxd(pdcs, databufptr, bufcnt, flags);
+		desc_w++;
+		sg = sg_next(sg);
+	}
+	pdcs->rxin_numd[pdcs->rx_msg_start] += desc_w;
+
+	return PDC_SUCCESS;
+}
+
+/**
+ * pdc_irq_handler() - Interrupt handler called in interrupt context.
+ * @irq:      Interrupt number that has fired
+ * @cookie:   PDC state for DMA engine that generated the interrupt
+ *
+ * We have to clear the device interrupt status flags here. So cache the
+ * status for later use in the thread function. Other than that, just return
+ * WAKE_THREAD to invoke the thread function.
+ *
+ * Return: IRQ_WAKE_THREAD if interrupt is ours
+ *         IRQ_NONE otherwise
+ */
+static irqreturn_t pdc_irq_handler(int irq, void *cookie)
+{
+	struct pdc_state *pdcs = cookie;
+	u32 intstatus = ioread32(pdcs->pdc_reg_vbase + PDC_INTSTATUS_OFFSET);
+
+	if (intstatus & PDC_XMTINTEN_0)
+		set_bit(PDC_XMTINT_0, &pdcs->intstatus);
+	if (intstatus & PDC_RCVINTEN_0)
+		set_bit(PDC_RCVINT_0, &pdcs->intstatus);
+
+	/* Clear interrupt flags in device */
+	iowrite32(intstatus, pdcs->pdc_reg_vbase + PDC_INTSTATUS_OFFSET);
+
+	/* Wakeup IRQ thread */
+	if (pdcs && (irq == pdcs->pdc_irq) && (intstatus & PDC_INTMASK))
+		return IRQ_WAKE_THREAD;
+
+	return IRQ_NONE;
+}
+
+/**
+ * pdc_irq_thread() - Function invoked on deferred thread when a DMA tx has
+ * completed or data is available to receive.
+ * @irq:    Interrupt number
+ * @cookie: PDC state for PDC that generated the interrupt
+ *
+ * On DMA tx complete, notify the mailbox client. On DMA rx complete, process
+ * as many SPU response messages as are available and send each to the mailbox
+ * client.
+ *
+ * Return: IRQ_HANDLED if we recognized and handled the interrupt
+ *         IRQ_NONE otherwise
+ */
+static irqreturn_t pdc_irq_thread(int irq, void *cookie)
+{
+	struct pdc_state *pdcs = cookie;
+	struct mbox_controller *mbc;
+	struct mbox_chan *chan;
+	bool tx_int;
+	bool rx_int;
+	int rx_status;
+	struct brcm_message mssg;
+
+	tx_int = test_and_clear_bit(PDC_XMTINT_0, &pdcs->intstatus);
+	rx_int = test_and_clear_bit(PDC_RCVINT_0, &pdcs->intstatus);
+
+	if (pdcs && (tx_int || rx_int)) {
+		dev_dbg(&pdcs->pdev->dev,
+			"%s() got irq %d with tx_int %s, rx_int %s",
+			__func__, irq,
+			tx_int ? "set" : "clear", rx_int ? "set" : "clear");
+
+		mbc = &pdcs->mbc;
+		chan = &mbc->chans[0];
+
+		if (tx_int) {
+			dev_dbg(&pdcs->pdev->dev, "%s(): tx done", __func__);
+			/* only one frame in flight at a time */
+			mbox_chan_txdone(chan, PDC_SUCCESS);
+		}
+		if (rx_int) {
+			while (1) {
+				/* Could be many frames ready */
+				memset(&mssg, 0, sizeof(mssg));
+				mssg.type = BRCM_MESSAGE_SPU;
+				rx_status = pdc_receive(pdcs, &mssg);
+				if (rx_status >= 0) {
+					dev_dbg(&pdcs->pdev->dev,
+						"%s(): invoking client rx cb",
+						__func__);
+					mbox_chan_received_data(chan, &mssg);
+				} else {
+					dev_dbg(&pdcs->pdev->dev,
+						"%s(): no SPU response available",
+						__func__);
+					break;
+				}
+			}
+		}
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+/**
+ * pdc_ring_init() - Allocate DMA rings and initialize constant fields of
+ * descriptors in one ringset.
+ * @pdcs:    PDC instance state
+ * @ringset: index of ringset being used
+ *
+ * Return: PDC_SUCCESS if ring initialized
+ *         < 0 otherwise
+ */
+static int pdc_ring_init(struct pdc_state *pdcs, int ringset)
+{
+	int i;
+	int err = PDC_SUCCESS;
+	struct dma64 *dma_reg;
+	struct device *dev = &pdcs->pdev->dev;
+	struct pdc_ring_alloc tx;
+	struct pdc_ring_alloc rx;
+
+	/* Allocate tx ring */
+	tx.vbase = dma_pool_zalloc(pdcs->ring_pool, GFP_KERNEL, &tx.dmabase);
+	if (!tx.vbase) {
+		err = -ENOMEM;
+		goto done;
+	}
+
+	/* Allocate rx ring */
+	rx.vbase = dma_pool_zalloc(pdcs->ring_pool, GFP_KERNEL, &rx.dmabase);
+	if (!rx.vbase) {
+		err = -ENOMEM;
+		goto fail_dealloc;
+	}
+
+	dev_dbg(dev, " - base DMA addr of tx ring      %#llx", tx.dmabase);
+	dev_dbg(dev, " - base virtual addr of tx ring  %p", tx.vbase);
+	dev_dbg(dev, " - base DMA addr of rx ring      %#llx", rx.dmabase);
+	dev_dbg(dev, " - base virtual addr of rx ring  %p", rx.vbase);
+
+	/* lock after ring allocation to avoid scheduling while atomic */
+	spin_lock(&pdcs->pdc_lock);
+
+	memcpy(&pdcs->tx_ring_alloc, &tx, sizeof(tx));
+	memcpy(&pdcs->rx_ring_alloc, &rx, sizeof(rx));
+
+	pdcs->rxin = 0;
+	pdcs->rx_msg_start = 0;
+	pdcs->last_rx_curr = 0;
+	pdcs->rxout = 0;
+	pdcs->txin = 0;
+	pdcs->tx_msg_start = 0;
+	pdcs->txout = 0;
+
+	/* Set descriptor array base addresses */
+	pdcs->txd_64 = (struct dma64dd *)pdcs->tx_ring_alloc.vbase;
+	pdcs->rxd_64 = (struct dma64dd *)pdcs->rx_ring_alloc.vbase;
+
+	/* Tell device the base DMA address of each ring */
+	dma_reg = &pdcs->regs->dmaregs[ringset];
+	iowrite32(lower_32_bits(pdcs->tx_ring_alloc.dmabase),
+		  (void *)&dma_reg->dmaxmt.addrlow);
+	iowrite32(upper_32_bits(pdcs->tx_ring_alloc.dmabase),
+		  (void *)&dma_reg->dmaxmt.addrhigh);
+
+	iowrite32(lower_32_bits(pdcs->rx_ring_alloc.dmabase),
+		  (void *)&dma_reg->dmarcv.addrlow);
+	iowrite32(upper_32_bits(pdcs->rx_ring_alloc.dmabase),
+		  (void *)&dma_reg->dmarcv.addrhigh);
+
+	/* Initialize descriptors */
+	for (i = 0; i < PDC_RING_ENTRIES; i++) {
+		/* Every tx descriptor can be used for start of frame. */
+		if (i != pdcs->ntxpost) {
+			iowrite32(D64_CTRL1_SOF | D64_CTRL1_EOF,
+				  (void *)&pdcs->txd_64[i].ctrl1);
+		} else {
+			/* Last descriptor in ringset. Set End of Table. */
+			iowrite32(D64_CTRL1_SOF | D64_CTRL1_EOF |
+				  D64_CTRL1_EOT,
+				  (void *)&pdcs->txd_64[i].ctrl1);
+		}
+
+		/* Every rx descriptor can be used for start of frame */
+		if (i != pdcs->nrxpost) {
+			iowrite32(D64_CTRL1_SOF,
+				  (void *)&pdcs->rxd_64[i].ctrl1);
+		} else {
+			/* Last descriptor in ringset. Set End of Table. */
+			iowrite32(D64_CTRL1_SOF | D64_CTRL1_EOT,
+				  (void *)&pdcs->rxd_64[i].ctrl1);
+		}
+	}
+	spin_unlock(&pdcs->pdc_lock);
+	return PDC_SUCCESS;
+
+fail_dealloc:
+	dma_pool_free(pdcs->ring_pool, tx.vbase, tx.dmabase);
+done:
+	return err;
+}
+
+static void pdc_ring_free(struct pdc_state *pdcs)
+{
+	if (pdcs->tx_ring_alloc.vbase) {
+		dma_pool_free(pdcs->ring_pool, pdcs->tx_ring_alloc.vbase,
+			      pdcs->tx_ring_alloc.dmabase);
+		pdcs->tx_ring_alloc.vbase = NULL;
+	}
+
+	if (pdcs->rx_ring_alloc.vbase) {
+		dma_pool_free(pdcs->ring_pool, pdcs->rx_ring_alloc.vbase,
+			      pdcs->rx_ring_alloc.dmabase);
+		pdcs->rx_ring_alloc.vbase = NULL;
+	}
+}
+
+/**
+ * pdc_send_data() - mailbox send_data function
+ * @chan:	The mailbox channel on which the data is sent. The channel
+ *              corresponds to a DMA ringset.
+ * @data:	The mailbox message to be sent. The message must be a
+ *              brcm_message structure.
+ *
+ * This function is registered as the send_data function for the mailbox
+ * controller. From the destination scatterlist in the mailbox message, it
+ * creates a sequence of receive descriptors in the rx ring. From the source
+ * scatterlist, it creates a sequence of transmit descriptors in the tx ring.
+ * After creating the descriptors, it writes the rx ptr and tx ptr registers to
+ * initiate the DMA transfer.
+ *
+ * This function does the DMA map and unmap of the src and dst scatterlists in
+ * the mailbox message.
+ *
+ * Return: 0 if successful
+ *	   -ENOTSUPP if the mailbox message is a type this driver does not
+ *			support
+ *         < 0 if an error
+ */
+static int pdc_send_data(struct mbox_chan *chan, void *data)
+{
+	struct pdc_state *pdcs = chan->con_priv;
+	struct device *dev = &pdcs->pdev->dev;
+	struct brcm_message *mssg = data;
+	int err = PDC_SUCCESS;
+	int src_nent;
+	int dst_nent;
+	int nent;
+
+	if (mssg->type != BRCM_MESSAGE_SPU)
+		return -ENOTSUPP;
+
+	src_nent = sg_nents(mssg->spu.src);
+	if (src_nent) {
+		nent = dma_map_sg(dev, mssg->spu.src, src_nent, DMA_TO_DEVICE);
+		if (nent == 0)
+			return -EIO;
+	}
+
+	dst_nent = sg_nents(mssg->spu.dst);
+	if (dst_nent) {
+		nent = dma_map_sg(dev, mssg->spu.dst, dst_nent,
+				  DMA_FROM_DEVICE);
+		if (nent == 0) {
+			dma_unmap_sg(dev, mssg->spu.src, src_nent,
+				     DMA_TO_DEVICE);
+			return -EIO;
+		}
+	}
+
+	spin_lock(&pdcs->pdc_lock);
+
+	/* Create rx descriptors to SPU catch response */
+	err = pdc_rx_list_init(pdcs, mssg->spu.dst, mssg->ctx);
+	err |= pdc_rx_list_sg_add(pdcs, mssg->spu.dst);
+
+	/* Create tx descriptors to submit SPU request */
+	err |= pdc_tx_list_sg_add(pdcs, mssg->spu.src);
+	err |= pdc_tx_list_final(pdcs);	/* initiate transfer */
+
+	spin_unlock(&pdcs->pdc_lock);
+
+	if (err)
+		dev_err(&pdcs->pdev->dev,
+			"%s failed with error %d", __func__, err);
+
+	return err;
+}
+
+static int pdc_startup(struct mbox_chan *chan)
+{
+	return pdc_ring_init(chan->con_priv, PDC_RINGSET);
+}
+
+static void pdc_shutdown(struct mbox_chan *chan)
+{
+	struct pdc_state *pdcs = chan->con_priv;
+
+	if (pdcs)
+		dev_dbg(&pdcs->pdev->dev,
+			"Shutdown mailbox channel for PDC %u", pdcs->pdc_idx);
+
+	pdc_ring_free(pdcs);
+}
+
+/**
+ * pdc_hw_init() - Use the given initialization parameters to initialize the
+ * state for one of the PDCs.
+ * @dev:   device structure for PDC
+ * @pdcs:  state of the PDC
+ * @parms: parameter values to set
+ */
+static
+void pdc_hw_init(struct device *dev, struct pdc_state *pdcs,
+		 struct hw_init_parms *parms)
+{
+	struct dma64 *dma_reg;
+
+	int ringset = PDC_RINGSET;
+
+	dev_dbg(dev, "PDC %u initial values:", pdcs->pdc_idx);
+	dev_dbg(dev, "state structure:                   %p",
+		pdcs);
+	dev_dbg(dev, " - base physical addr of hw regs   %#llx",
+		parms->hw_pbase);
+	dev_dbg(dev, " - base virtual addr of hw regs    %p",
+		parms->hw_vbase);
+
+	/* initialize data structures */
+	pdcs->regs = (struct pdc_regs *)parms->hw_vbase;
+	pdcs->txregs_64 = (struct dma64_regs *)
+	    (void *)(((u8 *)parms->hw_vbase) +
+		     PDC_TXREGS_OFFSET + (sizeof(struct dma64) * ringset));
+	pdcs->rxregs_64 = (struct dma64_regs *)
+	    (void *)(((u8 *)parms->hw_vbase) +
+		     PDC_RXREGS_OFFSET + (sizeof(struct dma64) * ringset));
+
+	pdcs->ntxd = parms->ring_entries;
+	pdcs->nrxd = parms->ring_entries;
+	pdcs->ntxpost = parms->ring_entries - 1;
+	pdcs->nrxpost = parms->ring_entries - 1;
+	pdcs->regs->intmask = 0;
+
+	dma_reg = &pdcs->regs->dmaregs[ringset];
+	iowrite32(0, (void *)&dma_reg->dmaxmt.ptr);
+	iowrite32(0, (void *)&dma_reg->dmarcv.ptr);
+
+	iowrite32(PDC_TX_CTL, (void *)&dma_reg->dmaxmt.control);
+
+	iowrite32(PDC_RX_CTL + (pdcs->rx_status_len << 1),
+		  (void *)&dma_reg->dmarcv.control);
+
+	if (pdcs->pdc_resp_hdr_len == PDC_SPU2_RESP_HDR_LEN)
+		iowrite32(PDC_CKSUM_CTRL,
+			  pdcs->pdc_reg_vbase + PDC_CKSUM_CTRL_OFFSET);
+}
+
+/**
+ * pdc_rx_buf_pool_create() - Pool of receive buffers used to catch the metadata
+ * header returned with each response message.
+ * @dev:  device structure
+ * @pdcs: PDC state structure
+ *
+ * The metadata is not returned to the mailbox client. So the PDC driver
+ * manages these buffers.
+ *
+ * Return: PDC_SUCCESS
+ *         -ENOMEM if pool creation fails
+ */
+static int pdc_rx_buf_pool_create(struct device *dev, struct pdc_state *pdcs)
+{
+	pdcs->pdc_resp_hdr_len = pdcs->rx_status_len;
+	if (pdcs->use_bcm_hdr)
+		pdcs->pdc_resp_hdr_len += BCM_HDR_LEN;
+
+	pdcs->rx_buf_pool = dma_pool_create("pdc rx bufs", dev,
+					    pdcs->pdc_resp_hdr_len,
+					    RX_BUF_ALIGN, 0);
+	if (!pdcs->rx_buf_pool)
+		return -ENOMEM;
+
+	return PDC_SUCCESS;
+}
+
+/**
+ * pdc_interrupts_init() - Initialize the interrupt configuration for a PDC and
+ * specify a threaded IRQ handler for deferred handling of interrupts outside of
+ * interrupt context.
+ * @pdev:   platform device
+ * @pdcs:   PDC state
+ *
+ * Set the interrupt mask for transmit and receive done.
+ * Set the lazy interrupt frame count to generate an interrupt for just one pkt.
+ *
+ * Return:  PDC_SUCCESS
+ *          <0 if threaded irq request fails
+ */
+static int pdc_interrupts_init(struct platform_device *pdev,
+			       struct pdc_state *pdcs)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *dn = pdev->dev.of_node;
+	int err;
+
+	pdcs->intstatus = 0;
+
+	/* interrupt configuration */
+	iowrite32(PDC_INTMASK, pdcs->pdc_reg_vbase + PDC_INTMASK_OFFSET);
+	iowrite32(PDC_LAZY_INT, pdcs->pdc_reg_vbase + PDC_RCVLAZY0_OFFSET);
+
+	/* read irq from device tree */
+	pdcs->pdc_irq = irq_of_parse_and_map(dn, 0);
+	dev_dbg(dev, "pdc device %s irq %u for pdcs %p",
+		dev_name(dev), pdcs->pdc_irq, pdcs);
+	err = devm_request_threaded_irq(dev, pdcs->pdc_irq,
+					pdc_irq_handler,
+					pdc_irq_thread, 0, dev_name(dev), pdcs);
+	if (err) {
+		dev_err(dev, "threaded tx IRQ %u request failed with err %d\n",
+			pdcs->pdc_irq, err);
+		return err;
+	}
+	return PDC_SUCCESS;
+}
+
+static const struct mbox_chan_ops pdc_mbox_chan_ops = {
+	.send_data = pdc_send_data,
+	.startup = pdc_startup,
+	.shutdown = pdc_shutdown
+};
+
+/**
+ * pdc_mb_init() - Initialize the mailbox controller.
+ * @pdcs:  PDC state
+ *
+ * Each PDC is a mailbox controller. Each ringset is a mailbox channel. Kernel
+ * driver only uses one ringset and thus one mb channel. PDC uses the transmit
+ * complete interrupt to determine when a mailbox message has successfully been
+ * transmitted.
+ *
+ * Return: 0 on success
+ *         < 0 if there is an allocation or registration failure
+ */
+static int pdc_mb_init(struct pdc_state *pdcs)
+{
+	struct device *dev = &pdcs->pdev->dev;
+	struct mbox_controller *mbc;
+	int chan_index;
+	int err;
+
+	mbc = &pdcs->mbc;
+	mbc->dev = dev;
+	mbc->ops = &pdc_mbox_chan_ops;
+	mbc->num_chans = 1;
+	mbc->chans = devm_kcalloc(dev, mbc->num_chans, sizeof(*mbc->chans),
+				  GFP_KERNEL);
+	if (!mbc->chans)
+		return -ENOMEM;
+
+	mbc->txdone_irq = true;
+	mbc->txdone_poll = false;
+	for (chan_index = 0; chan_index < mbc->num_chans; chan_index++)
+		mbc->chans[chan_index].con_priv = pdcs;
+
+	/* Register mailbox controller */
+	err = mbox_controller_register(mbc);
+	if (err) {
+		dev_crit(dev,
+			 "Failed to register PDC mailbox controller. Error %d.",
+			 err);
+		return err;
+	}
+	return 0;
+}
+
+/**
+ * pdc_dt_read() - Read application-specific data from device tree.
+ * @pdev:  Platform device
+ * @pdcs:  PDC state
+ *
+ * Reads the number of bytes of receive status that precede each received frame.
+ * Reads whether transmit and received frames should be preceded by an 8-byte
+ * BCM header.
+ *
+ * Return: 0 if successful
+ *         -ENODEV if device not available
+ */
+static int pdc_dt_read(struct platform_device *pdev, struct pdc_state *pdcs)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *dn = pdev->dev.of_node;
+	int err;
+
+	err = of_property_read_u32(dn, "brcm,rx-status-len",
+				   &pdcs->rx_status_len);
+	if (err < 0)
+		dev_err(dev,
+			"%s failed to get DMA receive status length from device tree",
+			__func__);
+
+	pdcs->use_bcm_hdr = of_property_read_bool(dn, "brcm,use-bcm-hdr");
+
+	return 0;
+}
+
+/**
+ * pdc_probe() - Probe function for PDC driver.
+ * @pdev:   PDC platform device
+ *
+ * Reserve and map register regions defined in device tree.
+ * Allocate and initialize tx and rx DMA rings.
+ * Initialize a mailbox controller for each PDC.
+ *
+ * Return: 0 if successful
+ *         < 0 if an error
+ */
+static int pdc_probe(struct platform_device *pdev)
+{
+	int err = 0;
+	struct device *dev = &pdev->dev;
+	struct resource *pdc_regs;
+	struct pdc_state *pdcs;
+	struct hw_init_parms hw_parms;	/* params for initializing spu-dma */
+
+	/* PDC state for one SPU */
+	pdcs = devm_kzalloc(dev, sizeof(*pdcs), GFP_KERNEL);
+	if (!pdcs) {
+		err = -ENOMEM;
+		goto cleanup;
+	}
+
+	spin_lock_init(&pdcs->pdc_lock);
+	pdcs->pdev = pdev;
+	platform_set_drvdata(pdev, pdcs);
+	pdcs->pdc_idx = pdcg.num_spu;
+	pdcg.num_spu++;
+
+	err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+	if (err) {
+		dev_warn(dev, "PDC device cannot perform DMA. Error %d.", err);
+		goto cleanup;
+	}
+
+	/* Create DMA pool for tx ring */
+	pdcs->ring_pool = dma_pool_create("pdc rings", dev, PDC_RING_SIZE,
+					  RING_ALIGN, 0);
+	if (!pdcs->ring_pool) {
+		err = -ENOMEM;
+		goto cleanup;
+	}
+
+	err = pdc_dt_read(pdev, pdcs);
+	if (err)
+		goto cleanup_ring_pool;
+
+	pdc_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!pdc_regs) {
+		err = -ENODEV;
+		goto cleanup_ring_pool;
+	}
+	dev_dbg(dev, "PDC register region res.start = %#llx, res.end = %#llx",
+		pdc_regs->start, pdc_regs->end);
+
+	pdcs->pdc_reg_vbase = devm_ioremap_resource(&pdev->dev, pdc_regs);
+	if (IS_ERR(pdcs->pdc_reg_vbase)) {
+		err = PTR_ERR(pdcs->pdc_reg_vbase);
+		dev_err(&pdev->dev, "Failed to map registers: %d\n", err);
+		goto cleanup_ring_pool;
+	}
+
+	/* create rx buffer pool after dt read to know how big buffers are */
+	err = pdc_rx_buf_pool_create(dev, pdcs);
+	if (err)
+		goto cleanup_ring_pool;
+
+	hw_parms.hw_pbase = (dma_addr_t)(pdc_regs->start);
+	hw_parms.hw_vbase = pdcs->pdc_reg_vbase;
+
+	hw_parms.ring_entries = PDC_RING_ENTRIES;
+
+	pdc_hw_init(dev, pdcs, &hw_parms);
+
+	err = pdc_interrupts_init(pdev, pdcs);
+	if (err)
+		goto cleanup_buf_pool;
+
+	/* Initialize mailbox controller */
+	err = pdc_mb_init(pdcs);
+	if (err)
+		goto cleanup_buf_pool;
+
+	pdcs->debugfs_stats = NULL;
+	pdc_setup_debugfs(pdcs);
+
+	dev_dbg(dev, "pdc_probe() successful");
+	return PDC_SUCCESS;
+
+cleanup_buf_pool:
+	dma_pool_destroy(pdcs->rx_buf_pool);
+
+cleanup_ring_pool:
+	dma_pool_destroy(pdcs->ring_pool);
+
+cleanup:
+	return err;
+}
+
+static int pdc_remove(struct platform_device *pdev)
+{
+	struct pdc_state *pdcs = platform_get_drvdata(pdev);
+
+	pdc_free_debugfs();
+
+	mbox_controller_unregister(&pdcs->mbc);
+
+	dma_pool_destroy(pdcs->rx_buf_pool);
+	dma_pool_destroy(pdcs->ring_pool);
+	return 0;
+}
+
+static const struct of_device_id pdc_mbox_of_match[] = {
+	{.compatible = "brcm,iproc-pdc-mbox"},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pdc_mbox_of_match);
+
+static struct platform_driver pdc_mbox_driver = {
+	.probe = pdc_probe,
+	.remove = pdc_remove,
+	.driver = {
+		   .name = "brcm-iproc-pdc-mbox",
+		   .of_match_table = of_match_ptr(pdc_mbox_of_match),
+		   },
+};
+module_platform_driver(pdc_mbox_driver);
+
+MODULE_AUTHOR("Rob Rice <rob.rice at broadcom.com>");
+MODULE_DESCRIPTION("Broadcom PDC mailbox driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mailbox/mailbox-pdc/pdc.h b/drivers/mailbox/mailbox-pdc/pdc.h
new file mode 100644
index 0000000..17e1464
--- /dev/null
+++ b/drivers/mailbox/mailbox-pdc/pdc.h
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2016 Broadcom
+ *
+ * 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 (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+#ifndef PDC_H
+#define PDC_H
+
+#include <linux/scatterlist.h>
+#include <linux/mailbox_controller.h>
+
+#define PDC_SUCCESS  0
+
+#define RING_ENTRY_SIZE   sizeof(struct dma64dd)
+
+/* # entries in PDC dma ring */
+#define PDC_RING_ENTRIES  128
+#define PDC_RING_SIZE    (PDC_RING_ENTRIES * RING_ENTRY_SIZE)
+/* Rings are 8k aligned */
+#define RING_ALIGN_ORDER  13
+#define RING_ALIGN        BIT(RING_ALIGN_ORDER)
+
+#define RX_BUF_ALIGN_ORDER  5
+#define RX_BUF_ALIGN	    BIT(RX_BUF_ALIGN_ORDER)
+
+/* descriptor bumping macros */
+#define XXD(x, max_mask)              ((x) & (max_mask))
+#define TXD(x, max_mask)              XXD((x), (max_mask))
+#define RXD(x, max_mask)              XXD((x), (max_mask))
+#define NEXTTXD(i, max_mask)          TXD((i) + 1, (max_mask))
+#define PREVTXD(i, max_mask)          TXD((i) - 1, (max_mask))
+#define NEXTRXD(i, max_mask)          RXD((i) + 1, (max_mask))
+#define PREVRXD(i, max_mask)          RXD((i) - 1, (max_mask))
+#define NTXDACTIVE(h, t, max_mask)    TXD((t) - (h), (max_mask))
+#define NRXDACTIVE(h, t, max_mask)    RXD((t) - (h), (max_mask))
+
+struct pdc_dma_map {
+	void *ctx;          /* opaque context associated with frame */
+};
+
+struct hw_init_parms {
+	dma_addr_t hw_pbase;         /* base physical addr of PDC regs */
+	void *hw_vbase;              /* base virtual addr of PDC regs */
+
+	u32  ring_entries;           /* number of ring entries */
+};
+
+/* dma descriptor */
+struct dma64dd {
+	u32 ctrl1;      /* misc control bits */
+	u32 ctrl2;      /* buffer count and address extension */
+	u32 addrlow;    /* memory address of the date buffer, bits 31:0 */
+	u32 addrhigh;   /* memory address of the date buffer, bits 63:32 */
+};
+
+/* dma registers per channel(xmt or rcv) */
+struct dma64_regs {
+	u32  control;   /* enable, et al */
+	u32  ptr;       /* last descriptor posted to chip */
+	u32  addrlow;   /* descriptor ring base address low 32-bits */
+	u32  addrhigh;  /* descriptor ring base address bits 63:32 */
+	u32  status0;   /* last rx descriptor written by hw */
+	u32  status1;   /* driver does not use */
+};
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef PAD
+#define _PADLINE(line)  pad ## line
+#define _XSTR(line)     _PADLINE(line)
+#define PAD             _XSTR(__LINE__)
+#endif  /* PAD */
+
+/* dma registers. matches hw layout. */
+struct dma64 {
+	struct dma64_regs dmaxmt;  /* dma tx */
+	u32          PAD[2];
+	struct dma64_regs dmarcv;  /* dma rx */
+	u32          PAD[2];
+};
+
+/* PDC registers */
+struct pdc_regs {
+	u32  devcontrol;             /* 0x000 */
+	u32  devstatus;              /* 0x004 */
+	u32  PAD;
+	u32  biststatus;             /* 0x00c */
+	u32  PAD[4];
+	u32  intstatus;              /* 0x020 */
+	u32  intmask;                /* 0x024 */
+	u32  gptimer;                /* 0x028 */
+
+	u32  PAD;
+	u32  intrcvlazy_0;           /* 0x030 */
+	u32  intrcvlazy_1;           /* 0x034 */
+	u32  intrcvlazy_2;           /* 0x038 */
+	u32  intrcvlazy_3;           /* 0x03c */
+
+	u32  PAD[48];
+	u32  removed_intrecvlazy;    /* 0x100 */
+	u32  flowctlthresh;          /* 0x104 */
+	u32  wrrthresh;              /* 0x108 */
+	u32  gmac_idle_cnt_thresh;   /* 0x10c */
+
+	u32  PAD[4];
+	u32  ifioaccessaddr;         /* 0x120 */
+	u32  ifioaccessbyte;         /* 0x124 */
+	u32  ifioaccessdata;         /* 0x128 */
+
+	u32  PAD[21];
+	u32  phyaccess;              /* 0x180 */
+	u32  PAD;
+	u32  phycontrol;             /* 0x188 */
+	u32  txqctl;                 /* 0x18c */
+	u32  rxqctl;                 /* 0x190 */
+	u32  gpioselect;             /* 0x194 */
+	u32  gpio_output_en;         /* 0x198 */
+	u32  PAD;                    /* 0x19c */
+	u32  txq_rxq_mem_ctl;        /* 0x1a0 */
+	u32  memory_ecc_status;      /* 0x1a4 */
+	u32  serdes_ctl;             /* 0x1a8 */
+	u32  serdes_status0;         /* 0x1ac */
+	u32  serdes_status1;         /* 0x1b0 */
+	u32  PAD[11];                /* 0x1b4-1dc */
+	u32  clk_ctl_st;             /* 0x1e0 */
+	u32  hw_war;                 /* 0x1e4 */
+	u32  pwrctl;                 /* 0x1e8 */
+	u32  PAD[5];
+
+#define PDC_NUM_DMA_RINGS   4
+	struct dma64 dmaregs[PDC_NUM_DMA_RINGS];  /* 0x0200 - 0x2fc */
+
+	/* more registers follow, but we don't use them */
+};
+
+/* structure for allocating/freeing DMA rings */
+struct pdc_ring_alloc {
+	dma_addr_t  dmabase; /* DMA address of start of ring */
+	void	   *vbase;   /* base kernel virtual address of ring */
+	u32	    size;    /* ring allocation size in bytes */
+};
+
+/* PDC state structure */
+struct pdc_state {
+	/* synchronize access to this PDC state structure */
+	spinlock_t pdc_lock;
+
+	/* Index of the PDC whose state is in this structure instance */
+	u8 pdc_idx;
+
+	/* Platform device for this PDC instance */
+	struct platform_device *pdev;
+
+	/*
+	 * Each PDC instance has a mailbox controller. PDC receives request
+	 * messages through mailboxes, and sends response messages through the
+	 * mailbox framework.
+	 */
+	struct mbox_controller mbc;
+
+	unsigned int pdc_irq;
+
+	/*
+	 * Last interrupt status read from PDC device. Saved in interrupt
+	 * handler so the handler can clear the interrupt in the device,
+	 * and the interrupt thread called later can know which interrupt
+	 * bits are active.
+	 */
+	unsigned long intstatus;
+
+	/* Number of bytes of receive status prior to each rx frame */
+	u32 rx_status_len;
+	/* Whether a BCM header is prepended to each frame */
+	bool use_bcm_hdr;
+	/* Sum of length of BCM header and rx status header */
+	u32 pdc_resp_hdr_len;
+
+	/* The base virtual address of DMA hw registers */
+	void __iomem *pdc_reg_vbase;
+
+	/* Pool for allocation of DMA rings */
+	struct dma_pool *ring_pool;
+
+	/* Pool for allocation of metadata buffers for response messages */
+	struct dma_pool *rx_buf_pool;
+
+	/*
+	 * The base virtual address of DMA tx/rx descriptor rings. Corresponding
+	 * DMA address and size of ring allocation.
+	 */
+	struct pdc_ring_alloc tx_ring_alloc;
+	struct pdc_ring_alloc rx_ring_alloc;
+
+	struct pdc_regs *regs;    /* start of PDC registers */
+
+	struct dma64_regs *txregs_64; /* dma tx engine registers */
+	struct dma64_regs *rxregs_64; /* dma rx engine registers */
+
+	/*
+	 * Arrays of PDC_RING_ENTRIES descriptors
+	 * To use multiple ringsets, this needs to be extended
+	 */
+	struct dma64dd   *txd_64;  /* tx descriptor ring */
+	struct dma64dd   *rxd_64;  /* rx descriptor ring */
+
+	/* descriptor ring sizes */
+	u32      ntxd;       /* # tx descriptors */
+	u32      nrxd;       /* # rx descriptors */
+	u32      nrxpost;    /* # rx buffers to keep posted */
+	u32      ntxpost;    /* max number of tx buffers that can be posted */
+
+	/*
+	 * Index of next tx descriptor to reclaim. That is, the descriptor
+	 * index of the oldest tx buffer for which the host has yet to process
+	 * the corresponding response.
+	 */
+	u32  txin;
+
+	/*
+	 * Index of the first receive descriptor for the sequence of
+	 * message fragments currently under construction. Used to build up
+	 * the rxin_numd count for a message. Updated to rxout when the host
+	 * starts a new sequence of rx buffers for a new message.
+	 */
+	u32  tx_msg_start;
+
+	/* Index of next tx descriptor to post. */
+	u32  txout;
+
+	/*
+	 * Number of tx descriptors associated with the message that starts
+	 * at this tx descriptor index.
+	 */
+	u32      txin_numd[PDC_RING_ENTRIES];
+
+	/*
+	 * Index of next rx descriptor to reclaim. This is the index of
+	 * the next descriptor whose data has yet to be processed by the host.
+	 */
+	u32  rxin;
+
+	/*
+	 * Index of the first receive descriptor for the sequence of
+	 * message fragments currently under construction. Used to build up
+	 * the rxin_numd count for a message. Updated to rxout when the host
+	 * starts a new sequence of rx buffers for a new message.
+	 */
+	u32  rx_msg_start;
+
+	/*
+	 * Saved value of current hardware rx descriptor index.
+	 * The last rx buffer written by the hw is the index previous to
+	 * this one.
+	 */
+	u32  last_rx_curr;
+
+	/* Index of next rx descriptor to post. */
+	u32  rxout;
+
+	/*
+	 * opaque context associated with frame that starts at each
+	 * rx ring index.
+	 */
+	void *rxp_ctx[PDC_RING_ENTRIES];
+
+	/*
+	 * Scatterlists used to form request and reply frames beginning at a
+	 * given ring index. Retained in order to unmap each sg after reply
+	 * is processed
+	 */
+	struct scatterlist *src_sg[PDC_RING_ENTRIES];
+	struct scatterlist *dst_sg[PDC_RING_ENTRIES];
+
+	/*
+	 * Number of rx descriptors associated with the message that starts
+	 * at this descriptor index. Not set for every index. For example,
+	 * if descriptor index i points to a scatterlist with 4 entries, then
+	 * the next three descriptor indexes don't have a value set.
+	 */
+	u32  rxin_numd[PDC_RING_ENTRIES];
+
+	void *resp_hdr[PDC_RING_ENTRIES];
+	dma_addr_t resp_hdr_daddr[PDC_RING_ENTRIES];
+
+	struct dentry *debugfs_stats;  /* debug FS stats file for this PDC */
+
+	/* counters */
+	u32  pdc_requests;    /* number of request messages submitted */
+	u32  pdc_replies;     /* number of reply messages received */
+	u32  txnobuf;         /* count of tx ring full */
+	u32  rxnobuf;         /* count of rx ring full */
+	u32  rx_oflow;        /* count of rx overflows */
+};
+#endif
diff --git a/drivers/mailbox/mailbox-pdc/pdc_debug.c b/drivers/mailbox/mailbox-pdc/pdc_debug.c
new file mode 100644
index 0000000..891a937
--- /dev/null
+++ b/drivers/mailbox/mailbox-pdc/pdc_debug.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2016 Broadcom
+ *
+ * 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 (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+
+#include "pdc.h"
+
+/* top level debug FS directory for PDC driver */
+static struct dentry *debugfs_dir;
+
+static ssize_t pdc_debugfs_read(struct file *filp, char __user *ubuf,
+				size_t count, loff_t *offp)
+{
+	struct pdc_state *pdcs;
+	char *buf;
+	ssize_t ret, out_offset, out_count;
+
+	out_count = 512;
+
+	buf = kmalloc(out_count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	pdcs = filp->private_data;
+	out_offset = 0;
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "SPU %u stats:\n", pdcs->pdc_idx);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "PDC requests............%u\n",
+			       pdcs->pdc_requests);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "PDC responses...........%u\n",
+			       pdcs->pdc_replies);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "Tx err ring full........%u\n",
+			       pdcs->txnobuf);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "Rx err ring full........%u\n",
+			       pdcs->rxnobuf);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "Receive overflow........%u\n",
+			       pdcs->rx_oflow);
+
+	if (out_offset > out_count)
+		out_offset = out_count;
+
+	ret = simple_read_from_buffer(ubuf, count, offp, buf, out_offset);
+	kfree(buf);
+	return ret;
+}
+
+static const struct file_operations pdc_debugfs_stats = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read = pdc_debugfs_read,
+};
+
+/**
+ * pdc_setup_debugfs() - Create the debug FS directories. If the top-level
+ * directory has not yet been created, create it now. Create a stats file in
+ * this directory for a SPU.
+ * @pdcs: PDC state structure
+ */
+void pdc_setup_debugfs(struct pdc_state *pdcs)
+{
+	char spu_stats_name[16];
+
+	if (!debugfs_initialized())
+		return;
+
+	snprintf(spu_stats_name, 16, "pdc%d_stats", pdcs->pdc_idx);
+	if (!debugfs_dir)
+		debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
+
+	pdcs->debugfs_stats = debugfs_create_file(spu_stats_name, S_IRUSR,
+						  debugfs_dir, pdcs,
+						  &pdc_debugfs_stats);
+}
+
+void pdc_free_debugfs(void)
+{
+	if (debugfs_dir && simple_empty(debugfs_dir)) {
+		debugfs_remove_recursive(debugfs_dir);
+		debugfs_dir = NULL;
+	}
+}
diff --git a/drivers/mailbox/mailbox-pdc/pdc_debug.h b/drivers/mailbox/mailbox-pdc/pdc_debug.h
new file mode 100644
index 0000000..f5120a2
--- /dev/null
+++ b/drivers/mailbox/mailbox-pdc/pdc_debug.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 Broadcom
+ *
+ * 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 (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+
+#ifndef _PDC_DEBUG_H
+#define _PDC_DEBUG_H
+
+#include "pdc.h"
+
+void pdc_setup_debugfs(struct pdc_state *pdcs);
+void pdc_free_debugfs(void);
+#endif
diff --git a/include/linux/mailbox/brcm-message.h b/include/linux/mailbox/brcm-message.h
new file mode 100644
index 0000000..6b55c93
--- /dev/null
+++ b/include/linux/mailbox/brcm-message.h
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (C) 2016 Broadcom
+ *
+ * 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.
+ *
+ * Common header for Broadcom mailbox messages which is shared across
+ * Broadcom SoCs and Broadcom mailbox client drivers.
+ */
+
+#ifndef _LINUX_BRCM_MESSAGE_H_
+#define _LINUX_BRCM_MESSAGE_H_
+
+#include <linux/scatterlist.h>
+
+enum brcm_message_type {
+	BRCM_MESSAGE_UNKNOWN = 0,
+	BRCM_MESSAGE_SPU,
+	BRCM_MESSAGE_SBA,
+	BRCM_MESSAGE_MAX,
+};
+
+struct brcm_sba_command {
+	u64 cmd;
+#define BRCM_SBA_CMD_TYPE_A		BIT(0)
+#define BRCM_SBA_CMD_TYPE_B		BIT(1)
+#define BRCM_SBA_CMD_TYPE_C		BIT(2)
+#define BRCM_SBA_CMD_HAS_RESP		BIT(3)
+#define BRCM_SBA_CMD_HAS_OUTPUT		BIT(4)
+	u64 flags;
+	dma_addr_t input;
+	size_t input_len;
+	dma_addr_t resp;
+	size_t resp_len;
+	dma_addr_t output;
+	size_t output_len;
+};
+
+struct brcm_message {
+	enum brcm_message_type type;
+	union {
+		struct {
+			struct scatterlist *src;
+			struct scatterlist *dst;
+		} spu;
+		struct {
+			struct brcm_sba_command *cmds;
+			unsigned int cmds_count;
+		} sba;
+	};
+	void *ctx;
+	int error;
+};
+
+#endif /* _LINUX_BRCM_MESSAGE_H_ */
-- 
2.1.0



From rob.rice at broadcom.com  Tue May 24 11:07:30 2016
From: rob.rice at broadcom.com (Rob Rice)
Date: Tue, 24 May 2016 14:07:30 -0400
Subject: [PATCH 3/3] arm64: dts: Add Broadcom Northstar2 device tree entries
 for PDC driver.
In-Reply-To: <1464113250-15629-1-git-send-email-rob.rice@broadcom.com>
References: <1464113250-15629-1-git-send-email-rob.rice@broadcom.com>
Message-ID: <1464113250-15629-4-git-send-email-rob.rice@broadcom.com>

From: Rob Rice <rrice at broadcom.com>

Add Broadcom Northstar2 SoC device tree entries for PDC driver.

Signed-off-by: Rob Rice <rob.rice at broadcom.com>
Reviewed-by: Ray Jui <ray.jui at broadcom.com>
Reviewed-by: Scott Branden <scott.branden at broadcom.com>
---
 arch/arm64/boot/dts/broadcom/ns2.dtsi | 36 +++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi
index ec68ec1..ba12702 100644
--- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
+++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
@@ -191,6 +191,42 @@
 
 		#include "ns2-clock.dtsi"
 
+		pdc0: iproc-pdc0 at 612c0000 {
+			compatible = "brcm,iproc-pdc-mbox";
+			reg = <0x612c0000 0x445>;  /* PDC FS0 regs */
+			interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+			#mbox-cells = <1>;
+			brcm,rx-status-len = <32>;
+			brcm,use-bcm-hdr;
+		};
+
+		pdc1: iproc-pdc1 at 612e0000 {
+			compatible = "brcm,iproc-pdc-mbox";
+			reg = <0x612e0000 0x445>;  /* PDC FS1 regs */
+			interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+			#mbox-cells = <1>;
+			brcm,rx-status-len = <32>;
+			brcm,use-bcm-hdr;
+		};
+
+		pdc2: iproc-pdc2 at 61300000 {
+			compatible = "brcm,iproc-pdc-mbox";
+			reg = <0x61300000 0x445>;  /* PDC FS2 regs */
+			interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+			#mbox-cells = <1>;
+			brcm,rx-status-len = <32>;
+			brcm,use-bcm-hdr;
+		};
+
+		pdc3: iproc-pdc3 at 61320000 {
+			compatible = "brcm,iproc-pdc-mbox";
+			reg = <0x61320000 0x445>;  /* PDC FS3 regs */
+			interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
+			#mbox-cells = <1>;
+			brcm,rx-status-len = <32>;
+			brcm,use-bcm-hdr;
+		};
+
 		dma0: dma at 61360000 {
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x61360000 0x1000>;
-- 
2.1.0



From khilman at baylibre.com  Tue May 24 11:29:00 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Tue, 24 May 2016 11:29:00 -0700
Subject: [PATCH 0/7] pinctrl: meson: Add a bunch more pins
In-Reply-To: <CACRpkdY9oGZLt431NwTaFmZk98O8n3ZnMA1odhYZtcH7P1p=Jg@mail.gmail.com>
 (Linus Walleij's message of "Tue, 24 May 2016 11:23:37 +0200")
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
 <CACRpkdY9oGZLt431NwTaFmZk98O8n3ZnMA1odhYZtcH7P1p=Jg@mail.gmail.com>
Message-ID: <m260u3ia37.fsf@baylibre.com>

Linus Walleij <linus.walleij at linaro.org> writes:

> On Fri, May 6, 2016 at 4:21 PM, Kevin Hilman <khilman at baylibre.com> wrote:
>
>> Add support for several more devices, both in the EE domain and in the
>> AO domain.  Also, add the pins to the corresponding DTS files.
>>
>> Tested on odroid-c2 and Amlogic P200 boards, and verified with working
>> ethernet.
>>
>> Depends on the initial GXBB pinctrl support from Carlo[1].  Also
>> available in my git tree[2] with all the dependencies included.
>
> These don't apply anomore sadly, Kevin can you rebase on
> Torvalds' HEAD and resend, and include Carlo's ACK on them
> so I can merge them in the next kernel cycle?

Looking closer, these have dependencies on the DT changes that you've
suggested we take through arm-soc, so it would be cleaner if I take
these with your ack through the amlogic tree.

Since it's a brand new driver, I don't expect there to be conflicts.

Does that work for you?

Kevin


From helgaas at kernel.org  Tue May 24 12:00:48 2016
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Tue, 24 May 2016 14:00:48 -0500
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <20160524172423.GA15855@red-moon>
References: <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>
 <20160523233918.GA32555@localhost>
 <20160524172423.GA15855@red-moon>
Message-ID: <20160524190048.GA4288@localhost>

On Tue, May 24, 2016 at 06:24:23PM +0100, Lorenzo Pieralisi wrote:
> Hi Bjorn,
> 
> On Mon, May 23, 2016 at 06:39:18PM -0500, Bjorn Helgaas wrote:
> 
> [...]
> 
> > On Mon, May 23, 2016 at 03:16:01PM +0000, Gabriele Paoloni wrote:
> > I don't think of ECAM support itself as a "driver".  It's just a
> > service available to drivers, similar to OF resource parsing.
> > 
> > Per PCI Firmware r3.2, sec 4.1.5, "PNP0A03" means a PCI/PCI-X/PCIe
> > host bridge.  "PNP0A08" means a PCI-X Mode 2 or PCIe bridge that
> > supports extended config space.  It doesn't specify how we access that
> > config space, so I think hardware with non-standard ECAM should still
> > have PNP0A03 and PNP0A08 in _CID or _HID.
> > 
> > "ECAM" as used in the specs (PCIe r3.0, sec 7.2.2, and PCI Firmware
> > r3.2, sec 4.1) means:
> > 
> >   (a) a memory-mapped model for config space access, and
> >   (b) a specific mapping of address bits to bus/device/function/
> >       register
> > 
> > MCFG and _CBA assume both (a) and (b), so I think a device with
> > non-standard ECAM mappings should not be described in MCFG or _CBA.
> > 
> > If a bridge has ECAM with non-standard mappings, I think either a
> > vendor-specific _HID or a device-specific method, e.g., _DSM, could
> > communicate that.
> > 
> > Jon, I agree that we should avoid describing non-standardized hardware
> > in Linux-specific ways.  Is there a mechanism in use already?  How
> > does Windows handle this?  DMI is a poor long-term solution because it
> > requires ongoing maintenance for new platforms, but I think it's OK
> > for getting started with platforms already shipping.
> > 
> > A _DSM has the advantage that once it is defined and supported, OEMs
> > can ship new platforms without requiring a new quirk or a new _HID to
> > be added to a driver.
> > 
> > There would still be the problem of config access before the namespace
> > is available, i.e., the MCFG use case.  I don't know how important
> > that is.  Defining an MCFG extension seems like the most obvious
> > solution.
> 
> Your summary above is a perfect representation of the situation.
> 
> We had an opportunity to sync-up on the current status of ACPI PCI
> for ARM64 (and talked about a way forward for this series, which
> includes quirks handling), let me summarize it here for everyone
> involved so that we can agree on a way forward.
> 
> 1) ACPI PCI support for PNP0A03/PNP0A08 host bridges on top of MCFG
>    ECAM for config space is basically ready (Tomasz and JC addressed
>    Rafael's concerns in relation to ARM64 specific code, and managed
>    to find a way to allocate domain numbers in preparation for Arnd
>    pci_create_root_bus() clean-up, v8 to be posted shortly and should
>    be final). This provides support for de-facto ACPI/PCI ECAM base
>    standard for ARM64 (with a clean-split between generic code and ARM64
>    bits, where ARM64, like X86 and IA64, manages in arch code IO space and
>    PCI resources, to be further consolidated in the near future).
>    I do not think anyone can complain about the generality of what we
>    achieved, for systems that are PCI standard (yes, PCI STANDARD) this
>    would just be sufficient.

Sounds good to me.

> 2) In a real world (1) is not enough. Some ARM64 platforms, not entirely
>    ECAM compliant, already shipped with the corresponding firmware that
>    we can't update. HW has ECAM quirks and to work around it in the kernel
>    we put forward many solutions to the problem, it is time we found a
>    solution (when, of course, (1) is completed and upstream).
>    Using the MCFG table OEMID matching floated around in this thread
>    would work fine for most of the platforms (and cross-OS) that have
>    shipped with HW ECAM quirks, so I think that's the starting point for
>    our solution and that's how we can sort this out, _today_.
> 
>    The solution is a trivial look-up table:
>    MCFG OEMID <-> PCI config space ops

Sounds reasonable to me.

> 3) (2) does not just work on some platforms (and we can't predict the
>    future either - actually I can, it is three letters, ECAM), simply
>    because MCFG OEMID matching does not provide a way to attach further
>    data to the MCFG (eg if config space for, say, bus 0 domain 0, is not
>    ECAM compliant, the config region can't be handled and must not be
>    handled through a corresponding MCFG region.

Couldn't this be handled by custom pci_ops that do something special
for bus 0 domain 0, and default to some different pci_ops for the
rest?

>    That's the problem Gabriele is facing and wants to solve through
>    something like:
> 
>    https://lkml.org/lkml/2016/3/9/91
> 
>    in the respective ACPI tables-bindings. It may be an idea worth
>    pursuing, it does not solve (2) simply because that FW has shipped,
>    we can't patch it any longer.

(2) is for quirks to deal with MCFG.  Gabriele's post is a proposal
for ACPI namespace.  We can't use anything in the namespace to
implement MCFG quirks because MCFG is needed before the namespace is
available.

I think Gabriele's post is a good proposal for the namespace, but I
would propose the following modifications:

  - Add PNP0A08 to the PCI1 _CID since this is a PCIe host bridge
  - Add a PCI1 _DSM describing the ECAM space
  - Remove the HISI0081 _HID

The result would be:

  Device (PCI1) {
    Name(_HID, "HISI0080")
    Name(_CID, "PNP0A03,PNP0A08")
    Method(_CRS) { ... }
    Method(_DSM) { <describe ECAM base and mapping function> }
  }
  Device (RES0) {
    Name(_HID, "PNP0C02")
    Name(_CRS) { <describe ECAM base and size> }
  }

RES0 could also be contained within PCI1, as Gabriele suggested.  I
don't really care whether it's contained or not, and making it
contained might make it easier for firmware, because addition/removal
of PCI1 and RES0 should always happen together.

I think the _DSM is important because it is really ugly if the
HISI0080 driver has to look for a separate HISI0081 device to learn
about the ECAM space.  There are several PCI drivers that do something
similar, using for_each_pci_dev(), and I cringe every time I see them,
because this totally screws up the driver model.  A driver should
claim a device via a .probe() method called by the core, and it
shouldn't look at devices it hasn't claimed.  This is required to make
hotplug work correctly.

> Hence to finally support ACPI PCI on ARM64 I suggest we carry out the
> following steps, in order:
> 
> - Let's complete/merge (1), that's fundamental to this whole thread
> - On top of (1) we apply a quirking mechanism based on (2) that allows
>   us to boot mainline with boxes shipping today with no FW update required.
> - We devise a way to handle quirks that is more generic than (2) so that
>   can we can accomodate further platforms that can't rely on (2) but
>   have more leeway in terms of FW updates.
> 
> I hope that's a reasonable plan, Tomasz's v8 series coming to kick it off.

Sounds very good to me; I'm looking forward to v8.

Bjorn


From pavel at ucw.cz  Tue May 24 12:49:03 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Tue, 24 May 2016 21:49:03 +0200
Subject: Can not play audio with screen off
In-Reply-To: <20160516150650.GA14639@amd>
References: <20160515193106.GA18685@amd> <5739D7B6.7060102@ti.com>
 <20160516150650.GA14639@amd>
Message-ID: <20160524194544.GA18011@amd>

Hi!

> > > I'm playing some more with N900, this time I'd like to use it as a
> > > alarm clock...
> > > 
> > > And now I realized I can not, because system performance is so
> > > horrible with screen off that mpg123 + pulseaudio skips horribly. This
> > > is without tweaking serial parameters, so CPU is definitely not going
> > > into the idle/off modes.
> > > 
> > > Loading CPU fixes the issue (I used cat /dev/zero > /dev/null).
> > > 
> > > Hmm. And it seems to work better if I ssh in and launch mpg123
> > > remotely. Weird.
> > > 
> > > Kernel 4.5-rc0. Will try on different ones.
> > > 
> > > Any ideas? Is there interface to tell kernel that better performance
> > > is needed for a while?
> 
> > pm_qos cpu_dma_latency? Drivers will have to be properly instrumented
> > with appropriate latency values -> this will control the depth in C
> > states that the system will attempt. NOTE: it is a dual edged sword,
> > bad configurations can result in none of the C-states being entered.
> 
> Ok, so far it looks like artefact of -rc0 kernel. Lets see if it
> reappers...

Hmm. So it happens in vanilla 4.4, too... let me see if it happens in
v4.6.

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From nleeder at codeaurora.org  Tue May 24 12:54:50 2016
From: nleeder at codeaurora.org (Neil Leeder)
Date: Tue, 24 May 2016 15:54:50 -0400
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
In-Reply-To: <20160524112326.GC25374@leverpostej>
References: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
 <20160523172527.GK4976@leverpostej>
 <f49d58ed-38b4-6284-11c2-8708d8443b14@codeaurora.org>
 <20160524112326.GC25374@leverpostej>
Message-ID: <e0173486-896e-4897-702a-ccd1c1f6c609@codeaurora.org>



On 5/24/2016 07:23 AM, Mark Rutland wrote:
> On Mon, May 23, 2016 at 02:22:59PM -0400, Neil Leeder wrote:
>>
>> On 5/23/2016 01:25 PM, Mark Rutland wrote:
>>> On Fri, May 20, 2016 at 03:13:07PM -0400, Neil Leeder wrote:

>>>> Signed-off-by: Neil Leeder <nleeder at codeaurora.org>
>>>> ---
>>>>  drivers/soc/qcom/Kconfig              |  9 +++++
>>>>  drivers/soc/qcom/Makefile             |  1 +
>>>>  drivers/soc/qcom/l2-accessors.c       | 66 +++++++++++++++++++++++++++++++++++
>>>>  include/linux/soc/qcom/l2-accessors.h | 27 ++++++++++++++
>>>>  4 files changed, 103 insertions(+)
>>>>  create mode 100644 drivers/soc/qcom/l2-accessors.c
>>>>  create mode 100644 include/linux/soc/qcom/l2-accessors.h
>>>
>>> These are awfully generic file names (and function names). Which SoCs
>>> does this apply to?
>>>
>>> It would be good to give these more specific names.
>>
>> It's under soc/qcom, and dependent on ARCH_QCOM and (in v2) also on ARM64. It applies to all QCOM ARM64 SoCs.
> 
> Per Christopher's comment, it sounds like this applies to QDF24xx.
> 
> Given that the code uses IMPLEMENTATION DEFINED system registers, I
> presume that this does not apply to MSM8916 which uses Cortex-A53, for
> example (though perhaps it does, and I am mistaken).
> 
>> Given that it can only be used in a QCOM driver, and the include path has qcom in it, I'd
>> prefer not to add redundancy by adding another qcom in there.
> 
> I'm not asking for another "qcom", but simply the SoC variant or family
> (e.g. "qdf24xx" would be fine).
> 

It applies to all ARMv8 SoCs with QCOM processors in them. So QDF24xx and mobile 820, but not SoCs
with ARM processors in them such as MSM8916. So neither msm_ nor qdf_ are accurate prefixes. As Timur
pointed out, the majority of source files in drivers/soc/qcom don't have any prefix, which is a
reason why I didn't include one.

>>>> diff --git a/include/linux/soc/qcom/l2-accessors.h b/include/linux/soc/qcom/l2-accessors.h
>>>> new file mode 100644
>>>> index 0000000..563c114
>>>> --- /dev/null
>>>> +++ b/include/linux/soc/qcom/l2-accessors.h
>>>> @@ -0,0 +1,27 @@
>>>> +/*
>>>> + * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or modify
>>>> + * it under the terms of the GNU General Public License version 2 and
>>>> + * only version 2 as published by the Free Software Foundation.
>>>> + *
>>>> + * This program is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>> + * GNU General Public License for more details.
>>>> + */
>>>> +
>>>
>>>> +#ifndef __QCOM_L2_ACCESSORS_H
>>>> +#define __QCOM_L2_ACCESSORS_H
>>>> +
>>>> +#ifdef CONFIG_QCOM_L2_ACCESSORS
>>>> +void set_l2_indirect_reg(u64 reg_addr, u64 val);
>>>> +u64 get_l2_indirect_reg(u64 reg_addr);
>>>> +#else
>>>> +static inline void set_l2_indirect_reg(u64 reg_addr, u64 val) {}
>>>> +static inline u64 get_l2_indirect_reg(u64 reg_addr)
>>>> +{
>>>> +	return 0;
>>>> +}
>>>
>>> Surely it would be better to error out on any unintentional use of these
>>> at build time?
>>
>> This allows building code which is common to ARM SoCs and QCOM SoCs without having to ifdef out the
>> QCOM-specific pieces.
> 
> These shouldn't appear in generic code.
> 
> Other than the L2 PMU driver (which presumably depends on or selects
> CONFIG_QCOM_L2_ACCESSORS), what code would you have to ifdef?
> 
> I don't have a major concern on this, I just don't see where it should
> matter.

Ok, I agree, I will remove this. Thanks.

> 
> Thanks,
> Mark.
> 

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


From misael.lopez at ti.com  Tue May 24 13:00:40 2016
From: misael.lopez at ti.com (Misael Lopez Cruz)
Date: Tue, 24 May 2016 15:00:40 -0500
Subject: [PATCH] ARM: dts: dra72-evm: Rename 3.3V regulator tag
Message-ID: <1464120040-28776-1-git-send-email-misael.lopez@ti.com>

Rename the tag of the 3.3 V regulator used in the DRA72 EVM in
order to have a consistent tag name with the DRA7 EVM.  This
is useful when the regulator needs to be referenced in common
dtsi files (i.e. for common companion boards like JAMR3 [1]).

[1] http://www.ti.com.cn/cn/lit/ug/sprui52/sprui52.pdf

Signed-off-by: Misael Lopez Cruz <misael.lopez at ti.com>
---
 arch/arm/boot/dts/dra72-evm-common.dtsi |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/dra72-evm-common.dtsi b/arch/arm/boot/dts/dra72-evm-common.dtsi
index 093538e..9d3cf50 100644
--- a/arch/arm/boot/dts/dra72-evm-common.dtsi
+++ b/arch/arm/boot/dts/dra72-evm-common.dtsi
@@ -18,7 +18,7 @@
 		display0 = &hdmi0;
 	};
 
-	evm_3v3: fixedregulator-evm_3v3 {
+	evm_3v3_sw: fixedregulator-evm_3v3 {
 		compatible = "regulator-fixed";
 		regulator-name = "evm_3v3";
 		regulator-min-microvolt = <3300000>;
@@ -29,7 +29,7 @@
 		/* TPS77018DBVT */
 		compatible = "regulator-fixed";
 		regulator-name = "aic_dvdd";
-		vin-supply = <&evm_3v3>;
+		vin-supply = <&evm_3v3_sw>;
 		regulator-min-microvolt = <1800000>;
 		regulator-max-microvolt = <1800000>;
 	};
@@ -414,9 +414,9 @@
 		status = "okay";
 
 		/* Regulators */
-		AVDD-supply = <&evm_3v3>;
-		IOVDD-supply = <&evm_3v3>;
-		DRVDD-supply = <&evm_3v3>;
+		AVDD-supply = <&evm_3v3_sw>;
+		IOVDD-supply = <&evm_3v3_sw>;
+		DRVDD-supply = <&evm_3v3_sw>;
 		DVDD-supply = <&aic_dvdd>;
 	};
 };
@@ -597,7 +597,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc2_pins_default>;
 
-	vmmc-supply = <&evm_3v3>;
+	vmmc-supply = <&evm_3v3_sw>;
 	bus-width = <8>;
 	ti,non-removable;
 	max-frequency = <192000000>;
-- 
1.7.9.5



From arnd at arndb.de  Tue May 24 13:07:57 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 24 May 2016 22:07:57 +0200
Subject: [GIT PULL] ARM: SoC: late DT updates for v4.7
In-Reply-To: <6880123.QJWf7jilUK@wuerfel>
References: <6880123.QJWf7jilUK@wuerfel>
Message-ID: <5530966.8xa1nqVXh4@wuerfel>

The following changes since commit ab065e969640d9afd3967266eb3193fb3ac298bd:

  usb: xhci: tegra: Add Tegra210 support (2016-04-29 16:48:59 +0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/armsoc-late

for you to fetch changes up to 88f1847639d68d732f83adb7aae94e0d989f7e28:

  Merge tag 'samsung-dt-devfreq-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into next/late (2016-05-10 16:17:55 +0200)

----------------------------------------------------------------
This is a collection of a few late fixes and other misc. stuff that
had dependencies on things being merged from other trees.

The Renesas R-Car power domain handling, and the Nvidia Tegra USB
support both hand notable changes that required changing the DT binding
in a way that only provides compatibility with old DT blobs on new
kernels but not vice versa. As a consequence, the DT changes
are based on top of the driver changes and are now in this branch.

For NXP i.MX and Samsung Exynos, the changes in here depend on
other changes that got merged through the clk maintainer tree.

----------------------------------------------------------------
Arnd Bergmann (6):
      Merge tag 'renesas-dt-pm-domain-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/late
      Merge tag 'renesas-arm64-dt-pm-domain-for-v4.7' of git://git.kernel.org/.../horms/renesas into next/late
      Merge branches 'tegra/pci' and 'tegra/usb' into next/late
      Merge tag 'tegra-for-4.7-xusb-no-defconfig' of git://git.kernel.org/.../tegra/linux into next/late
      Merge tag 'imx-dt-clkdep-4.7' of git://git.kernel.org/.../shawnguo/linux into next/late
      Merge tag 'samsung-dt-devfreq-4.7' of git://git.kernel.org/.../krzk/linux into next/late

Chanwoo Choi (15):
      dt-bindings: clock: Add the clock id for ACLK clock of Exynos542x SoC
      clk: samsung: exynos542x: Add the clock id for ACLK
      ARM: dts: exynos: Add DMC bus node for Exynos3250
      ARM: dts: exynos: Add DMC bus frequency for exynos3250-rinato/monk
      ARM: dts: exynos: Add bus nodes using VDD_INT for Exynos3250
      ARM: dts: exynos: Add bus nodes using VDD_MIF for Exynos4x12
      ARM: dts: exynos: Add bus nodes using VDD_INT for Exynos4x12
      ARM: dts: exynos: Add bus nodes using VDD_MIF for Exynos4210
      ARM: dts: exynos: Add exynos4412-ppmu-common dtsi to delete duplicate PPMU nodes
      ARM: dts: exynos: Add support of bus frequency using VDD_INT for exynos3250-rinato
      ARM: dts: exynos: Expand the voltage range of buck1/3 regulator for exynos4412-odroidu3
      ARM: dts: exynos: Add support of bus frequency for exynos4412-trats/odroidu3
      ARM: dts: exynos: Add NoC Probe dt node for Exynos542x SoC
      ARM: dts: exynos: Add bus nodes using VDD_INT for Exynos542x SoC
      ARM: dts: exynos: Add support of Bus frequency using VDD_INT for exynos5422-odroidxu3

Fabio Estevam (1):
      clk: imx6sx: Register SAI clocks as shared clocks

Gary Bisson (4):
      clk: imx: add ckil clock for i.MX7
      ARM: dts: imx7d: add lcdif support
      ARM: dts: imx7d: add flexcan support
      ARM: dts: imx: add Boundary Devices Nitrogen7 board

Geert Uytterhoeven (12):
      arm64: dts: r8a7795: Add SYSC PM Domains
      arm64: dts: r8a7795: Use SYSC "always-on" PM Domain
      ARM: dts: r8a7779: Add SYSC PM Domains
      ARM: dts: r8a7790: Add SYSC PM Domains
      ARM: dts: r8a7791: Add SYSC PM Domains
      ARM: dts: r8a7793: Add SYSC PM Domains
      ARM: dts: r8a7794: Add SYSC PM Domains
      ARM: dts: r8a7779: Use SYSC "always-on" PM Domain
      ARM: dts: r8a7790: Use SYSC "always-on" PM Domain
      ARM: dts: r8a7791: Use SYSC "always-on" PM Domain
      ARM: dts: r8a7793: Use SYSC "always-on" PM Domain
      ARM: dts: r8a7794: Use SYSC "always-on" PM Domain

Krzysztof Kozlowski (1):
      Merge tag 'clk-v4.7-exynos542x' of git://linuxtv.org/snawrocki/samsung into for-v4.7-late/dts-exynos-devfreq

Shawn Guo (2):
      clk: imx: vf610: fix whitespace in vf610-clock.h
      Merge tag 'imx-clk-4.7' into imx/dt-clkdep

Simon Horman (2):
      Merge tag 'renesas-rcar-sysc2-for-v4.7' into dt-pm-domain-for-v4.7
      Merge tag 'renesas-rcar-sysc2-for-v4.7' into arm64-dt-pm-domain-for-v4.7

Stefan Agner (8):
      clk: imx: clk-gate2: allow custom gate configuration
      clk: imx: vf610: leave DDR clock on
      clk: imx: vf610: add WKPU unit
      clk: imx: vf610: add suspend/resume support
      clk: imx: vf610: fix DCU clock tree
      clk: imx: vf610: add TCON ipg clock
      ARM: dts: vf610: add display nodes
      ARM: dts: vf610-colibri: enable display controller

Thierry Reding (8):
      Merge branch 'for-4.7/phy' into for-4.7/xusb
      Merge branch 'for-4.7/pci' into for-4.7/xusb
      Merge branch 'for-4.7/xhci' into for-4.7/xusb
      ARM: tegra: Move Tegra124 to the new XUSB pad controller binding
      ARM: tegra: Add Tegra124 XUSB controller
      ARM: tegra: Enable XUSB on Venice2
      ARM: tegra: Enable XUSB on Jetson TK1
      ARM: tegra: Enable XUSB on Nyan

 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/exynos3250-monk.dts              |  47 +--
 arch/arm/boot/dts/exynos3250-rinato.dts            |  88 +++---
 arch/arm/boot/dts/exynos3250.dtsi                  | 181 +++++++++++
 arch/arm/boot/dts/exynos4210.dtsi                  | 159 ++++++++++
 arch/arm/boot/dts/exynos4412-odroid-common.dtsi    |  56 +++-
 arch/arm/boot/dts/exynos4412-ppmu-common.dtsi      |  50 ++++
 arch/arm/boot/dts/exynos4412-trats2.dts            |  88 +++---
 arch/arm/boot/dts/exynos4x12.dtsi                  | 174 +++++++++++
 arch/arm/boot/dts/exynos5420.dtsi                  | 407 +++++++++++++++++++++++++
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi |  99 ++++++
 arch/arm/boot/dts/imx7d-nitrogen7.dts              | 745 ++++++++++++++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/imx7d.dtsi                       |  31 ++
 arch/arm/boot/dts/r8a7779.dtsi                     |  54 ++--
 arch/arm/boot/dts/r8a7790.dtsi                     | 155 +++++-----
 arch/arm/boot/dts/r8a7791.dtsi                     | 156 +++++-----
 arch/arm/boot/dts/r8a7793.dtsi                     | 111 +++----
 arch/arm/boot/dts/r8a7794.dtsi                     | 116 ++++----
 arch/arm/boot/dts/tegra124-jetson-tk1.dts          | 116 +++++++-
 arch/arm/boot/dts/tegra124-nyan.dtsi               | 122 ++++++--
 arch/arm/boot/dts/tegra124-venice2.dts             | 101 ++++++-
 arch/arm/boot/dts/tegra124.dtsi                    | 167 ++++++++++-
 arch/arm/boot/dts/vf-colibri-eval-v3.dtsi          |  16 +
 arch/arm/boot/dts/vf-colibri.dtsi                  |  33 ++
 arch/arm/boot/dts/vfxxx.dtsi                       |  19 ++
 arch/arm64/boot/dts/renesas/r8a7795.dtsi           | 123 ++++----
 26 files changed, 2918 insertions(+), 497 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos4412-ppmu-common.dtsi
 create mode 100644 arch/arm/boot/dts/imx7d-nitrogen7.dts



From arnd at arndb.de  Tue May 24 13:03:32 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 24 May 2016 22:03:32 +0200
Subject: [GIT PULL] ARM: SoC fixes for v4.7
Message-ID: <6880123.QJWf7jilUK@wuerfel>

The following changes since commit 4a5219edcdae52bfb5eea0dfc2a7bd575961dad7:

  Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc (2016-05-18 13:14:02 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/armsoc-fixes

for you to fetch changes up to 09564b7d84d753e4aa1198017b5a5e86c7b0539f:

  ARM: lpc32xx: fix NR_IRQS confict (2016-05-24 19:32:46 +0000)

----------------------------------------------------------------
ARM: SoC fixes for 4.7

This is a first set of bug fixes on top of what was merged for 4.7.
Two patches for lpc32xx address a harmless build warning that was
just introduced, one patch for the mediatek soc driver fixes a warning
for arm64, and the pxa changes are minor cleanups that should have
been part of the original pull requests but that I forgot to apply
to the cleanup-fixes branch earlier.

----------------------------------------------------------------
Arnd Bergmann (3):
      soc: mtk-pmic-wrap: avoid integer overflow warning
      Merge tag 'pxa-for-4.7' of https://github.com/rjarzmik/linux into fixes
      ARM: lpc32xx: fix NR_IRQS confict

Robert Jarzmik (1):
      ARM: pxa: activate pinctrl for device-tree machines

Stephen Boyd (1):
      ARM: pxa: Remove CLK_IS_ROOT

Vladimir Zapolskiy (1):
      ARM: lpc32xx: remove legacy irq controller driver

 arch/arm/mach-lpc32xx/Makefile            |   2 +-
 arch/arm/mach-lpc32xx/include/mach/irqs.h |   2 +-
 arch/arm/mach-lpc32xx/irq.c               | 477 ------------------------------
 arch/arm/mach-pxa/Kconfig                 |   2 +
 arch/arm/mach-pxa/eseries.c               |   2 +-
 drivers/soc/mediatek/mtk-pmic-wrap.c      |   6 +-
 6 files changed, 8 insertions(+), 483 deletions(-)
 delete mode 100644 arch/arm/mach-lpc32xx/irq.c



From pavel at ucw.cz  Tue May 24 13:20:59 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Tue, 24 May 2016 22:20:59 +0200
Subject: [PATCHv3] support for AD5820 camera auto-focus coil
In-Reply-To: <57441BF8.60606@gmail.com>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com> <20160521105607.GA20071@amd>
 <574049EF.2090208@gmail.com> <20160524090433.GA1277@amd>
 <57441BF8.60606@gmail.com>
Message-ID: <20160524202059.GB18536@amd>

Hi!

> >>devm_regulator_get()?
> >
> >I'd rather avoid devm_ here. Driver is simple enough to allow it.
> >
> 
> Now thinking about it, what would happen here if regulator_get() returns
> -EPROBE_DEFER? Wouldn't it be better to move regulator_get to the probe()
> function, something like:

Ok, I can do it.

Oh, and don't try to complain about newlines before returns. It looks
better this way.

> static int ad5820_probe(struct i2c_client *client,
> 			const struct i2c_device_id *devid)
> {
> 	struct ad5820_device *coil;
> 	int ret = 0;
> 
> 	coil = devm_kzalloc(sizeof(*coil), GFP_KERNEL);
> 	if (coil == NULL)
> 		return -ENOMEM;
> 
> 	coil->vana = devm_regulator_get(&client->dev, NULL);
> 	if (IS_ERR(coil->vana)) {
> 		ret = PTR_ERR(coil->vana);
> 		if (ret != -EPROBE_DEFER)
> 			dev_err(&client->dev, "could not get regulator for vana\n");
> 		return ret;
> 	}
> 
> 	mutex_init(&coil->power_lock);
> ...
> 
> with the appropriate changes to remove() because of the devm API
> 			usage.

Something like this?

diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
index f956bd3..f871366 100644
--- a/drivers/media/i2c/ad5820.c
+++ b/drivers/media/i2c/ad5820.c
@@ -8,7 +8,7 @@
  * Copyright (C) 2016 Pavel Machek <pavel at ucw.cz>
  *
  * Contact: Tuukka Toivonen
- *          Sakari Ailus
+ *	    Sakari Ailus
  *
  * Based on af_d88.c by Texas Instruments.
  *
@@ -263,13 +263,6 @@ static int ad5820_init_controls(struct ad5820_device *coil)
 static int ad5820_registered(struct v4l2_subdev *subdev)
 {
 	struct ad5820_device *coil = to_ad5820_device(subdev);
-	struct i2c_client *client = v4l2_get_subdevdata(subdev);
-
-	coil->vana = regulator_get(&client->dev, "VANA");
-	if (IS_ERR(coil->vana)) {
-		dev_err(&client->dev, "could not get regulator for vana\n");
-		return -ENODEV;
-	}
 
 	return ad5820_init_controls(coil);
 }
@@ -367,10 +360,18 @@ static int ad5820_probe(struct i2c_client *client,
 	struct ad5820_device *coil;
 	int ret = 0;
 
-	coil = kzalloc(sizeof(*coil), GFP_KERNEL);
+	coil = devm_kzalloc(sizeof(*coil), GFP_KERNEL);
 	if (!coil)
 		return -ENOMEM;
 
+	coil->vana = devm_regulator_get(&client->dev, NULL);
+	if (IS_ERR(coil->vana)) {
+		ret = PTR_ERR(coil->vana);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&client->dev, "could not get regulator for vana\n");
+		return ret;
+	}
+	
 	mutex_init(&coil->power_lock);
 
 	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
@@ -390,10 +391,6 @@ static int ad5820_probe(struct i2c_client *client,
 
 cleanup:
 	media_entity_cleanup(&coil->subdev.entity);
-
-free:
-	kfree(coil);
-
 	return ret;
 }
 
@@ -405,11 +402,6 @@ static int __exit ad5820_remove(struct i2c_client *client)
 	v4l2_device_unregister_subdev(&coil->subdev);
 	v4l2_ctrl_handler_free(&coil->ctrls);
 	media_entity_cleanup(&coil->subdev.entity);
-	if (coil->vana)
-		regulator_put(coil->vana);
-
-	kfree(coil);
-
 	return 0;
 }
 


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From maxime.ripard at free-electrons.com  Tue May 24 14:07:33 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Tue, 24 May 2016 23:07:33 +0200
Subject: [PATCH 10/16] clk: sunxi-ng: Add M-P factor clock support
In-Reply-To: <CAGb2v65GbZosmh56Z7wBa5gHOe1Ox2Jz3tcOq1kugBHO54OvbQ@mail.gmail.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-11-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v67F3UvSCYDTxeLkCJL3FzmcpkogM4RAQgDseXMJDv7bUw@mail.gmail.com>
 <20160523171845.GC27618@lukather>
 <CAGb2v65GbZosmh56Z7wBa5gHOe1Ox2Jz3tcOq1kugBHO54OvbQ@mail.gmail.com>
Message-ID: <20160524210733.GK27618@lukather>

Hi,

On Tue, May 24, 2016 at 12:14:09PM +0800, Chen-Yu Tsai wrote:
> >> > +#define SUNXI_CCU_MP_WITH_MUX_GATE(_struct, _name, _parents, _reg,     \
> >>
> >> We could merge _struct with _name ...
> >>
> >> > +                                  _mshift, _mwidth,                    \
> >> > +                                  _pshift, _pwidth,                    \
> >> > +                                  _muxshift, _muxwidth,                \
> >> > +                                  _gate, _flags)                       \
> >> > +       struct ccu_mp _struct = {                                       \
> >>
> >> and have struct ccu_mp _name##_clk = {
> >
> > Unfortunately, that prevents to use dashes as clock names, which is
> > something we've done in the past. Having a separate name allows us to
> > use whatever we want.
> 
> We could do some replacement in the register function, but that seems
> hackish

Indeed

> Also I noticed we aren't using clock-output-names from the DT
> anymore?

Yep, there's just too many clocks to be practical, and you have to
have the name in the source code anyway for the parenting
relationships.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160524/3297fc91/attachment.sig>

From ttnguyen at apm.com  Tue May 24 14:12:19 2016
From: ttnguyen at apm.com (Tai Tri Nguyen)
Date: Tue, 24 May 2016 14:12:19 -0700
Subject: [PATCH v2 2/4] Documentation: Add documentation for APM X-Gene
 SoC PMU DTS binding
In-Reply-To: <CACgAJHyHEOe70pOG2yi-XUQS3BYdGmfYD-yTE0wFM9knDtHOiQ@mail.gmail.com>
References: <1460510547-17611-1-git-send-email-ttnguyen@apm.com>
 <1460510547-17611-3-git-send-email-ttnguyen@apm.com>
 <20160418170009.GA15338@rob-hp-laptop>
 <CACgAJHyBbO_LXwtfNVK1f=dY3v1Jfxwxq1dw98EZ0aYdhjPpAg@mail.gmail.com>
 <20160420113121.GE2514@arm.com>
 <20160502205648.GA7374@rob-hp-laptop>
 <CACgAJHyT31DuVNoyRQZVKjv=zM5Fc-EY0gy=y=pHHrBTT+1Xow@mail.gmail.com>
 <CACgAJHyHEOe70pOG2yi-XUQS3BYdGmfYD-yTE0wFM9knDtHOiQ@mail.gmail.com>
Message-ID: <CACgAJHz8bRb6E1xNFwhKpHDGxPhEsQ3J=H_u3woVLgzK0j==Bg@mail.gmail.com>

Hi all,

It's been weeks.
I just want to ping again if you have any more comments on this patch set?

Thanks,
Tai

On Tue, May 10, 2016 at 4:43 PM, Tai Tri Nguyen <ttnguyen at apm.com> wrote:
> Hi Rob/Mark,
>
> Do you have any more comments, please?
>
> Thanks,
> Tai
>
> On Mon, May 2, 2016 at 2:46 PM, Tai Tri Nguyen <ttnguyen at apm.com> wrote:
>> Hi Rob,
>>
>> On Mon, May 2, 2016 at 1:56 PM, Rob Herring <robh at kernel.org> wrote:
>>> On Wed, Apr 20, 2016 at 12:31:22PM +0100, Will Deacon wrote:
>>>> On Mon, Apr 18, 2016 at 01:04:53PM -0700, Tai Tri Nguyen wrote:
>>>> > >> +Required properties for MCB subnode:
>>>> > >> +- compatible         : Shall be "apm,xgene-pmu-mcb".
>>>> > >> +- reg                        : First resource shall be the MCB PMU resource.
>>>> > >> +- index                      : Instance number of the MCB PMU.
>>>> > >> +
>>>> > >> +Required properties for MC subnode:
>>>> > >> +- compatible         : Shall be "apm,xgene-pmu-mc".
>>>> > >> +- reg                        : First resource shall be the MC PMU resource.
>>>> > >> +- index                      : Instance number of the MC PMU.
>>>> > >
>>>> > > Don't use indexes. You probably need phandles to the nodes these are
>>>> > > related to.
>>>> > >
>>>> > > How many variations of child nodes do you expect to have? 2, 10, 50? You
>>>> > > might want to just collapse all this down to a single node and put this
>>>> > > information in the driver if it is fixed for each SoC and there's only a
>>>> > > handful.
>>>> > >
>>>> >
>>>> > For each kind of PMU, for example memory controller PMU, I expect to
>>>> > have the number of instances up to 8.
>>>> > They are actually all independent PMU nodes and have their own CSR memory bases.
>>>> > The indexes are used for exposing the devices to perf user only. It
>>>> > doesn't have an impact on the programming model.
>>>> > Mark also had the same concern.
>>>>
>>>> Regardless, I'll need an ack from Rob or Mark before I can merge this.
>>>
>>> I still have a concern with this. Needing an index to expose to the user
>>> is generally not a valid reason. That's OS specific and therefore
>>> doesn't belong in DT.
>>>
>>> Rob
>>
>> I can use device name here. However, the perf event names will be
>> different between DT and ACPI which I want to avoid.
>> And the names don't look good at all.
>> Also, specifically for MC and MCB PMUs, the indexes are compared
>> against the active MC/MCB mask to find out whether they are populated
>> or not.
>> Without using the index property, I will also need a mapping function
>> of physical device addresses and their physical ids.
>>
>> Thanks,
>> --
>> Tai
>
>
>
> --
> Tai



-- 
Tai


From khilman at baylibre.com  Tue May 24 14:45:17 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Tue, 24 May 2016 14:45:17 -0700
Subject: [PATCH 0/7] pinctrl: meson: Add a bunch more pins
In-Reply-To: <m260u3ia37.fsf@baylibre.com> (Kevin Hilman's message of "Tue, 24
 May 2016 11:29:00 -0700")
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
 <CACRpkdY9oGZLt431NwTaFmZk98O8n3ZnMA1odhYZtcH7P1p=Jg@mail.gmail.com>
 <m260u3ia37.fsf@baylibre.com>
Message-ID: <m2posbgmfm.fsf@baylibre.com>

Kevin Hilman <khilman at baylibre.com> writes:

> Linus Walleij <linus.walleij at linaro.org> writes:
>
>> On Fri, May 6, 2016 at 4:21 PM, Kevin Hilman <khilman at baylibre.com> wrote:
>>
>>> Add support for several more devices, both in the EE domain and in the
>>> AO domain.  Also, add the pins to the corresponding DTS files.
>>>
>>> Tested on odroid-c2 and Amlogic P200 boards, and verified with working
>>> ethernet.
>>>
>>> Depends on the initial GXBB pinctrl support from Carlo[1].  Also
>>> available in my git tree[2] with all the dependencies included.
>>
>> These don't apply anomore sadly, Kevin can you rebase on
>> Torvalds' HEAD and resend, and include Carlo's ACK on them
>> so I can merge them in the next kernel cycle?
>
> Looking closer, these have dependencies on the DT changes that you've
> suggested we take through arm-soc, so it would be cleaner if I take
> these with your ack through the amlogic tree.
>
> Since it's a brand new driver, I don't expect there to be conflicts.
>
> Does that work for you?

FWIW, rebase available here (with all deps, some of which I think
you'ved already merged):

git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux.git amlogic/v4.7/pinctrl

Kevin


From ddaney.cavm at gmail.com  Tue May 24 15:35:30 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:30 -0700
Subject: [PATCH v7 00/15] ACPI NUMA support for ARM64
Message-ID: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>

From: David Daney <david.daney at cavium.com>

Rebased to Linus' master branch at commit 1d6da87a3241 ("Merge branch
'drm-next' of git://people.freedesktop.org/~airlied/linux")

ACPI 5.1 already introduced NUMA support for ARM64, which can get the
NUMA domain information from SRAT and SLIT table, so parse those two
tables to get mappings from cpu/mem to numa node configuration and
system locality.

v7 updates:

 - Rebased to resolve one merge conflict.

 - New patch 13/15 to enable use of existing MADT parsing code instead
   of adding an additional implementation of the parser.

 - Added some Acked-by headers to patches in arm64 arch directories.

v6 updates:

 - Changed message printed in 13/14 to omit meaningless "cpu"
   number. (noted by Dennis Chen and Hanjun Guo)

 - New patch 7/14 to print different messages for NUMA disabled case.
   (noted by Dennis Chen)

 - Squashed two patches into 14/14.

 - Added Reviewed-by to 4/14

v5 updates:

 - Fixed ia64 build failure by gating some unused functions with #if
   CONFIG_{X86,ARM64}.

 - Fixed section mismatch errors for X86 case.

 - Removed unneeded #include from some files.

 - Tested to build cleanly on ARM64, X86_64, IA64

v4 updates:

 - Updated from Hanjun Guo's v3 patches.

 - Rebased on top of v16 of device-tree NUMA patches.

 - Reordered some of the changes so that we don't introduce code and
   then change it several times in the patch set.  New code is
   introduced in its final form.  Code reused from x86 is first moved
   with no change, and then a separate patch to make any needed
   changes.

 - code that is used only by ia64, moved to architecture specific
   files.

v3 updates:
 - Deep investigation about the ACPI_DEBUG_PRINT() and remvoe
   that for acpi/numa.c (patch 2/12)

 - Remove the duplicate NULL check for table print (patch 3/12)

 - Introduce CONFIG_ACPI_HAS_NUMA_ARCH_FIXUP to remove duplicate
   dummy function for acpi_numa_arch_fixup()

 - Solve the problem that the mapping from logical cpu to numa node
   is wrong which spotted out by Lorenzo

 - cleanups for x86 and move acpi_numa_slit_init() and some other
   functions to common place, then reduce the duplicate of x86
   and arm64 (patch 7-12/12).

 - rebased on top of 4.4 and Ganapat's v9 patch set.

David Daney (4):
  arm64, numa: Cleanup NUMA disabled messages.
  acpi, numa: move bad_srat() and srat_disabled() to
    drivers/acpi/numa.c
  acpi, numa, srat: Improve SRAT error detection and add messages.
  ACPI / processor: Add acpi_map_madt_entry().

Hanjun Guo (10):
  acpi, numa: Use pr_fmt() instead of printk
  acpi, numa: Replace ACPI_DEBUG_PRINT() with pr_debug()
  acpi, numa: remove duplicate NULL check
  acpi, numa: move acpi_numa_slit_init() to drivers/acpi/numa.c
  arm64, numa: rework numa_add_memblk()
  x86, acpi, numa: cleanup acpi_numa_processor_affinity_init()
  acpi, numa: remove unneeded acpi_numa=1
  acpi, numa: Move acpi_numa_memory_affinity_init() to
    drivers/acpi/numa.c
  arm64, acpi, numa: NUMA support based on SRAT and SLIT
  acpi, numa: Enable ACPI based NUMA on ARM64

Robert Richter (1):
  acpi, numa: Move acpi_numa_arch_fixup() to ia64 only

 arch/arm64/include/asm/acpi.h |   8 ++
 arch/arm64/include/asm/numa.h |   2 +
 arch/arm64/kernel/Makefile    |   1 +
 arch/arm64/kernel/acpi_numa.c | 112 +++++++++++++++++++++
 arch/arm64/kernel/smp.c       |   2 +
 arch/arm64/mm/numa.c          |  28 ++++--
 arch/ia64/include/asm/acpi.h  |   3 +
 arch/ia64/kernel/acpi.c       |   2 +-
 arch/ia64/kernel/setup.c      |   1 +
 arch/x86/include/asm/acpi.h   |   1 -
 arch/x86/mm/numa.c            |   2 +-
 arch/x86/mm/srat.c            | 116 +---------------------
 drivers/acpi/Kconfig          |   4 +-
 drivers/acpi/numa.c           | 226 ++++++++++++++++++++++++++++++++----------
 drivers/acpi/processor_core.c |  26 ++++-
 drivers/of/of_numa.c          |   4 +-
 include/acpi/acpi_numa.h      |   4 +
 include/acpi/processor.h      |   1 +
 include/linux/acpi.h          |  18 +++-
 19 files changed, 369 insertions(+), 192 deletions(-)
 create mode 100644 arch/arm64/kernel/acpi_numa.c

-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:31 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:31 -0700
Subject: [PATCH v7 01/15] acpi, numa: Use pr_fmt() instead of printk
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-2-git-send-email-ddaney.cavm@gmail.com>

From: Hanjun Guo <hanjun.guo at linaro.org>

Just do some cleanups to replace printk with pr_fmt().

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Robert Richter <rrichter at cavium.com>
Signed-off-by: David Daney <david.daney at cavium.com>
---
 drivers/acpi/numa.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index d176e0e..bdb7622 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -18,6 +18,9 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
  */
+
+#define pr_fmt(fmt) "ACPI: " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -28,8 +31,6 @@
 #include <linux/nodemask.h>
 #include <linux/topology.h>
 
-#define PREFIX "ACPI: "
-
 #define ACPI_NUMA	0x80000000
 #define _COMPONENT	ACPI_NUMA
 ACPI_MODULE_NAME("numa");
@@ -187,9 +188,8 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
 #endif				/* ACPI_DEBUG_OUTPUT */
 		break;
 	default:
-		printk(KERN_WARNING PREFIX
-		       "Found unsupported SRAT entry (type = 0x%x)\n",
-		       header->type);
+		pr_warn("Found unsupported SRAT entry (type = 0x%x)\n",
+			header->type);
 		break;
 	}
 }
@@ -222,7 +222,7 @@ static int __init acpi_parse_slit(struct acpi_table_header *table)
 	struct acpi_table_slit *slit = (struct acpi_table_slit *)table;
 
 	if (!slit_valid(slit)) {
-		printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
+		pr_info("SLIT table looks invalid. Not used.\n");
 		return -EINVAL;
 	}
 	acpi_numa_slit_init(slit);
@@ -233,12 +233,9 @@ static int __init acpi_parse_slit(struct acpi_table_header *table)
 void __init __weak
 acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
 {
-	printk(KERN_WARNING PREFIX
-	       "Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id);
-	return;
+	pr_warn("Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id);
 }
 
-
 static int __init
 acpi_parse_x2apic_affinity(struct acpi_subtable_header *header,
 			   const unsigned long end)
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:34 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:34 -0700
Subject: [PATCH v7 04/15] acpi, numa: Move acpi_numa_arch_fixup() to ia64 only
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-5-git-send-email-ddaney.cavm@gmail.com>

From: Robert Richter <rrichter at cavium.com>

Since acpi_numa_arch_fixup() is only used in arch ia64, move it there
to make a generic interface easier. This avoids empty function stubs
or some complex kconfig options for x86 and arm64.

Signed-off-by: Robert Richter <rrichter at cavium.com>
Reviewed-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: David Daney <david.daney at cavium.com>
---
 arch/ia64/include/asm/acpi.h | 3 +++
 arch/ia64/kernel/acpi.c      | 2 +-
 arch/ia64/kernel/setup.c     | 1 +
 arch/x86/mm/srat.c           | 2 --
 drivers/acpi/numa.c          | 2 --
 include/linux/acpi.h         | 1 -
 6 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h
index aa0fdf1..a3d0211 100644
--- a/arch/ia64/include/asm/acpi.h
+++ b/arch/ia64/include/asm/acpi.h
@@ -140,6 +140,9 @@ static inline void per_cpu_scan_finalize(int min_cpus, int reserve_cpus)
 		}
 	}
 }
+
+extern void acpi_numa_fixup(void);
+
 #endif /* CONFIG_ACPI_NUMA */
 
 #endif /*__KERNEL__*/
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index b1698bc..92b7bc9 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -524,7 +524,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 	return 0;
 }
 
-void __init acpi_numa_arch_fixup(void)
+void __init acpi_numa_fixup(void)
 {
 	int i, j, node_from, node_to;
 
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 2029a38..afddb3e 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -552,6 +552,7 @@ setup_arch (char **cmdline_p)
 	early_acpi_boot_init();
 # ifdef CONFIG_ACPI_NUMA
 	acpi_numa_init();
+	acpi_numa_fixup();
 #  ifdef CONFIG_ACPI_HOTPLUG_CPU
 	prefill_possible_map();
 #  endif
diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c
index b5f8218..90b6ed9 100644
--- a/arch/x86/mm/srat.c
+++ b/arch/x86/mm/srat.c
@@ -212,8 +212,6 @@ out_err:
 	return -1;
 }
 
-void __init acpi_numa_arch_fixup(void) {}
-
 int __init x86_acpi_numa_init(void)
 {
 	int ret;
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 6f1cad8..fb2c0d6 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -324,8 +324,6 @@ int __init acpi_numa_init(void)
 	/* SLIT: System Locality Information Table */
 	acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
 
-	acpi_numa_arch_fixup();
-
 	if (cnt < 0)
 		return cnt;
 	else if (!parsed_numa_memblks)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 288fac5..8010b26 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -237,7 +237,6 @@ void acpi_numa_slit_init (struct acpi_table_slit *slit);
 void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa);
 void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);
 int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
-void acpi_numa_arch_fixup(void);
 
 #ifndef PHYS_CPUID_INVALID
 typedef u32 phys_cpuid_t;
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:32 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:32 -0700
Subject: [PATCH v7 02/15] acpi,
 numa: Replace ACPI_DEBUG_PRINT() with pr_debug()
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-3-git-send-email-ddaney.cavm@gmail.com>

From: Hanjun Guo <hanjun.guo at linaro.org>

ACPI_DEBUG_PRINT is a bit fragile in acpi/numa.c, the first thing
is that component ACPI_NUMA(0x80000000) is not described in the
Documentation/acpi/debug.txt, and even not defined in the struct
acpi_dlayer acpi_debug_layers which we can not dynamically enable/disable
it with /sys/modules/acpi/parameters/debug_layer. another thing
is that ACPI_DEBUG_OUTPUT is controlled by ACPICA which not coordinate
well with ACPI drivers.

Replace ACPI_DEBUG_PRINT() with pr_debug() in this patch as pr_debug
will do the same thing for debug purpose and it can make the code much
cleaner, also remove the related code which not needed anymore if
ACPI_DEBUG_PRINT() is gone.

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Robert Richter <rrichter at cavium.com>
Signed-off-by: David Daney <david.daney at cavium.com>
---
 drivers/acpi/numa.c | 59 +++++++++++++++++++----------------------------------
 1 file changed, 21 insertions(+), 38 deletions(-)

diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index bdb7622..a089c39 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -31,10 +31,6 @@
 #include <linux/nodemask.h>
 #include <linux/topology.h>
 
-#define ACPI_NUMA	0x80000000
-#define _COMPONENT	ACPI_NUMA
-ACPI_MODULE_NAME("numa");
-
 static nodemask_t nodes_found_map = NODE_MASK_NONE;
 
 /* maps to convert between proximity domain and logical node ID */
@@ -129,64 +125,51 @@ EXPORT_SYMBOL(acpi_map_pxm_to_online_node);
 static void __init
 acpi_table_print_srat_entry(struct acpi_subtable_header *header)
 {
-
-	ACPI_FUNCTION_NAME("acpi_table_print_srat_entry");
-
 	if (!header)
 		return;
 
 	switch (header->type) {
-
 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
-#ifdef ACPI_DEBUG_OUTPUT
 		{
 			struct acpi_srat_cpu_affinity *p =
 			    (struct acpi_srat_cpu_affinity *)header;
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					  "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
-					  p->apic_id, p->local_sapic_eid,
-					  p->proximity_domain_lo,
-					  (p->flags & ACPI_SRAT_CPU_ENABLED)?
-					  "enabled" : "disabled"));
+			pr_debug("SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
+				 p->apic_id, p->local_sapic_eid,
+				 p->proximity_domain_lo,
+				 (p->flags & ACPI_SRAT_CPU_ENABLED) ?
+				 "enabled" : "disabled");
 		}
-#endif				/* ACPI_DEBUG_OUTPUT */
 		break;
 
 	case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
-#ifdef ACPI_DEBUG_OUTPUT
 		{
 			struct acpi_srat_mem_affinity *p =
 			    (struct acpi_srat_mem_affinity *)header;
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					  "SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n",
-					  (unsigned long)p->base_address,
-					  (unsigned long)p->length,
-					  p->proximity_domain,
-					  (p->flags & ACPI_SRAT_MEM_ENABLED)?
-					  "enabled" : "disabled",
-					  (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)?
-					  " hot-pluggable" : "",
-					  (p->flags & ACPI_SRAT_MEM_NON_VOLATILE)?
-					  " non-volatile" : ""));
+			pr_debug("SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n",
+				 (unsigned long)p->base_address,
+				 (unsigned long)p->length,
+				 p->proximity_domain,
+				 (p->flags & ACPI_SRAT_MEM_ENABLED) ?
+				 "enabled" : "disabled",
+				 (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ?
+				 " hot-pluggable" : "",
+				 (p->flags & ACPI_SRAT_MEM_NON_VOLATILE) ?
+				 " non-volatile" : "");
 		}
-#endif				/* ACPI_DEBUG_OUTPUT */
 		break;
 
 	case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
-#ifdef ACPI_DEBUG_OUTPUT
 		{
 			struct acpi_srat_x2apic_cpu_affinity *p =
 			    (struct acpi_srat_x2apic_cpu_affinity *)header;
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					  "SRAT Processor (x2apicid[0x%08x]) in"
-					  " proximity domain %d %s\n",
-					  p->apic_id,
-					  p->proximity_domain,
-					  (p->flags & ACPI_SRAT_CPU_ENABLED) ?
-					  "enabled" : "disabled"));
+			pr_debug("SRAT Processor (x2apicid[0x%08x]) in proximity domain %d %s\n",
+				 p->apic_id,
+				 p->proximity_domain,
+				 (p->flags & ACPI_SRAT_CPU_ENABLED) ?
+				 "enabled" : "disabled");
 		}
-#endif				/* ACPI_DEBUG_OUTPUT */
 		break;
+
 	default:
 		pr_warn("Found unsupported SRAT entry (type = 0x%x)\n",
 			header->type);
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:33 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:33 -0700
Subject: [PATCH v7 03/15] acpi, numa: remove duplicate NULL check
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-4-git-send-email-ddaney.cavm@gmail.com>

From: Hanjun Guo <hanjun.guo at linaro.org>

The argument "header" for acpi_table_print_srat_entry()
is always checked before the function is called, it's
duplicate to check it again, remove it.

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Robert Richter <rrichter at cavium.com>
Signed-off-by: David Daney <david.daney at cavium.com>
---
 drivers/acpi/numa.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index a089c39..6f1cad8 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -125,9 +125,6 @@ EXPORT_SYMBOL(acpi_map_pxm_to_online_node);
 static void __init
 acpi_table_print_srat_entry(struct acpi_subtable_header *header)
 {
-	if (!header)
-		return;
-
 	switch (header->type) {
 	case ACPI_SRAT_TYPE_CPU_AFFINITY:
 		{
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:36 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:36 -0700
Subject: [PATCH v7 06/15] arm64, numa: rework numa_add_memblk()
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-7-git-send-email-ddaney.cavm@gmail.com>

From: Hanjun Guo <hanjun.guo at linaro.org>

Rework numa_add_memblk() to update the parameter "u64 size" to "u64
end", this will make it consistent with x86 and simplifies the arm64
ACPI NUMA code to be added later.

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Robert Richter <rrichter at cavium.com>
Signed-off-by: David Daney <david.daney at cavium.com>
Acked-by: Catalin Marinas <catalin.marinas at arm.com>
---
 arch/arm64/mm/numa.c | 12 ++++++------
 drivers/of/of_numa.c |  4 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
index 98dc104..6cb03f9 100644
--- a/arch/arm64/mm/numa.c
+++ b/arch/arm64/mm/numa.c
@@ -131,25 +131,25 @@ void __init early_map_cpu_to_node(unsigned int cpu, int nid)
  * numa_add_memblk - Set node id to memblk
  * @nid: NUMA node ID of the new memblk
  * @start: Start address of the new memblk
- * @size:  Size of the new memblk
+ * @end:  End address of the new memblk
  *
  * RETURNS:
  * 0 on success, -errno on failure.
  */
-int __init numa_add_memblk(int nid, u64 start, u64 size)
+int __init numa_add_memblk(int nid, u64 start, u64 end)
 {
 	int ret;
 
-	ret = memblock_set_node(start, size, &memblock.memory, nid);
+	ret = memblock_set_node(start, (end - start), &memblock.memory, nid);
 	if (ret < 0) {
 		pr_err("NUMA: memblock [0x%llx - 0x%llx] failed to add on node %d\n",
-			start, (start + size - 1), nid);
+			start, (end - 1), nid);
 		return ret;
 	}
 
 	node_set(nid, numa_nodes_parsed);
 	pr_info("NUMA: Adding memblock [0x%llx - 0x%llx] on node %d\n",
-			start, (start + size - 1), nid);
+			start, (end - 1), nid);
 	return ret;
 }
 
@@ -367,7 +367,7 @@ static int __init dummy_numa_init(void)
 	       0LLU, PFN_PHYS(max_pfn) - 1);
 
 	for_each_memblock(memory, mblk) {
-		ret = numa_add_memblk(0, mblk->base, mblk->size);
+		ret = numa_add_memblk(0, mblk->base, mblk->base + mblk->size);
 		if (!ret)
 			continue;
 
diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
index 0f2784b..ed5a097 100644
--- a/drivers/of/of_numa.c
+++ b/drivers/of/of_numa.c
@@ -91,8 +91,8 @@ static int __init of_numa_parse_memory_nodes(void)
 		pr_debug("NUMA:  base = %llx len = %llx, node = %u\n",
 			 rsrc.start, rsrc.end - rsrc.start + 1, nid);
 
-		r = numa_add_memblk(nid, rsrc.start,
-				    rsrc.end - rsrc.start + 1);
+
+		r = numa_add_memblk(nid, rsrc.start, rsrc.end + 1);
 		if (r)
 			break;
 	}
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:35 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:35 -0700
Subject: [PATCH v7 05/15] acpi,
 numa: move acpi_numa_slit_init() to drivers/acpi/numa.c
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-6-git-send-email-ddaney.cavm@gmail.com>

From: Hanjun Guo <hanjun.guo at linaro.org>

Identical implementations of acpi_numa_slit_init() are used by both
x86 and follow-on arm64 support.  Move it to drivers/acpi/numa.c, and
guard with CONFIG_X86 || CONFIG_ARM64 because ia64 has its own
architecture specific implementation.

No code change.

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Robert Richter <rrichter at cavium.com>
Signed-off-by: David Daney <david.daney at cavium.com>
---
 arch/x86/mm/srat.c  | 27 ---------------------------
 drivers/acpi/numa.c | 29 +++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 27 deletions(-)

diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c
index 90b6ed9..f242a11 100644
--- a/arch/x86/mm/srat.c
+++ b/arch/x86/mm/srat.c
@@ -42,33 +42,6 @@ static __init inline int srat_disabled(void)
 	return acpi_numa < 0;
 }
 
-/*
- * Callback for SLIT parsing.  pxm_to_node() returns NUMA_NO_NODE for
- * I/O localities since SRAT does not list them.  I/O localities are
- * not supported at this point.
- */
-void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
-{
-	int i, j;
-
-	for (i = 0; i < slit->locality_count; i++) {
-		const int from_node = pxm_to_node(i);
-
-		if (from_node == NUMA_NO_NODE)
-			continue;
-
-		for (j = 0; j < slit->locality_count; j++) {
-			const int to_node = pxm_to_node(j);
-
-			if (to_node == NUMA_NO_NODE)
-				continue;
-
-			numa_set_distance(from_node, to_node,
-				slit->entry[slit->locality_count * i + j]);
-		}
-	}
-}
-
 /* Callback for Proximity Domain -> x2APIC mapping */
 void __init
 acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index fb2c0d6..7e0649d 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -197,6 +197,35 @@ static int __init slit_valid(struct acpi_table_slit *slit)
 	return 1;
 }
 
+#if defined(CONFIG_X86) || defined(CONFIG_ARM64)
+/*
+ * Callback for SLIT parsing.  pxm_to_node() returns NUMA_NO_NODE for
+ * I/O localities since SRAT does not list them.  I/O localities are
+ * not supported at this point.
+ */
+void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
+{
+	int i, j;
+
+	for (i = 0; i < slit->locality_count; i++) {
+		const int from_node = pxm_to_node(i);
+
+		if (from_node == NUMA_NO_NODE)
+			continue;
+
+		for (j = 0; j < slit->locality_count; j++) {
+			const int to_node = pxm_to_node(j);
+
+			if (to_node == NUMA_NO_NODE)
+				continue;
+
+			numa_set_distance(from_node, to_node,
+				slit->entry[slit->locality_count * i + j]);
+		}
+	}
+}
+#endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */
+
 static int __init acpi_parse_slit(struct acpi_table_header *table)
 {
 	struct acpi_table_slit *slit = (struct acpi_table_slit *)table;
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:38 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:38 -0700
Subject: [PATCH v7 08/15] x86, acpi,
 numa: cleanup acpi_numa_processor_affinity_init()
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-9-git-send-email-ddaney.cavm@gmail.com>

From: Hanjun Guo <hanjun.guo at linaro.org>

Cleanup acpi_numa_processor_affinity_init() in preparation for its
move to drivers/acpi/numa.c.  It will be reused by arm64, this has no
functional change.

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Robert Richter <rrichter at cavium.com>
Signed-off-by: David Daney <david.daney at cavium.com>
---
 arch/x86/mm/srat.c | 21 +++++----------------
 1 file changed, 5 insertions(+), 16 deletions(-)

diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c
index f242a11..9e2a833 100644
--- a/arch/x86/mm/srat.c
+++ b/arch/x86/mm/srat.c
@@ -26,11 +26,6 @@
 
 int acpi_numa __initdata;
 
-static __init int setup_node(int pxm)
-{
-	return acpi_map_pxm_to_node(pxm);
-}
-
 static __init void bad_srat(void)
 {
 	printk(KERN_ERR "SRAT: SRAT not used.\n");
@@ -64,7 +59,7 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
 			 pxm, apic_id);
 		return;
 	}
-	node = setup_node(pxm);
+	node = acpi_map_pxm_to_node(pxm);
 	if (node < 0) {
 		printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
 		bad_srat();
@@ -100,7 +95,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
 	pxm = pa->proximity_domain_lo;
 	if (acpi_srat_revision >= 2)
 		pxm |= *((unsigned int*)pa->proximity_domain_hi) << 8;
-	node = setup_node(pxm);
+	node = acpi_map_pxm_to_node(pxm);
 	if (node < 0) {
 		printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
 		bad_srat();
@@ -124,12 +119,6 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
 	       pxm, apic_id, node);
 }
 
-#ifdef CONFIG_MEMORY_HOTPLUG
-static inline int save_add_info(void) {return 1;}
-#else
-static inline int save_add_info(void) {return 0;}
-#endif
-
 /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
 int __init
 acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
@@ -145,7 +134,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 	if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
 		goto out_err;
 	hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE;
-	if (hotpluggable && !save_add_info())
+	if (hotpluggable && !IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
 		goto out_err;
 
 	start = ma->base_address;
@@ -154,7 +143,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 	if (acpi_srat_revision <= 1)
 		pxm &= 0xff;
 
-	node = setup_node(pxm);
+	node = acpi_map_pxm_to_node(pxm);
 	if (node < 0) {
 		printk(KERN_ERR "SRAT: Too many proximity domains.\n");
 		goto out_err_bad_srat;
@@ -182,7 +171,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 out_err_bad_srat:
 	bad_srat();
 out_err:
-	return -1;
+	return -EINVAL;
 }
 
 int __init x86_acpi_numa_init(void)
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:37 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:37 -0700
Subject: [PATCH v7 07/15] arm64, numa: Cleanup NUMA disabled messages.
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-8-git-send-email-ddaney.cavm@gmail.com>

From: David Daney <david.daney at cavium.com>

As noted by Dennis Chen, we don't want to print "No NUMA configuration
found" if NUMA was forced off from the command line.

Change the type of numa_off to bool, and clean up printing code.
Print "NUMA disabled" if forced off on command line and "No NUMA
configuration found" if there was no firmware NUMA information.

Signed-off-by: David Daney <david.daney at cavium.com>
Acked-by: Catalin Marinas <catalin.marinas at arm.com>
---
 arch/arm64/mm/numa.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
index 6cb03f9..1def1de 100644
--- a/arch/arm64/mm/numa.c
+++ b/arch/arm64/mm/numa.c
@@ -29,7 +29,7 @@ static int cpu_to_node_map[NR_CPUS] = { [0 ... NR_CPUS-1] = NUMA_NO_NODE };
 
 static int numa_distance_cnt;
 static u8 *numa_distance;
-static int numa_off;
+static bool numa_off;
 
 static __init int numa_parse_early_param(char *opt)
 {
@@ -37,7 +37,7 @@ static __init int numa_parse_early_param(char *opt)
 		return -EINVAL;
 	if (!strncmp(opt, "off", 3)) {
 		pr_info("%s\n", "NUMA turned off");
-		numa_off = 1;
+		numa_off = true;
 	}
 	return 0;
 }
@@ -362,7 +362,10 @@ static int __init dummy_numa_init(void)
 	int ret;
 	struct memblock_region *mblk;
 
-	pr_info("%s\n", "No NUMA configuration found");
+	if (numa_off)
+		pr_info("NUMA disabled\n"); /* Forced off on command line. */
+	else
+		pr_info("No NUMA configuration found\n");
 	pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
 	       0LLU, PFN_PHYS(max_pfn) - 1);
 
@@ -375,7 +378,7 @@ static int __init dummy_numa_init(void)
 		return ret;
 	}
 
-	numa_off = 1;
+	numa_off = true;
 	return 0;
 }
 
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:39 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:39 -0700
Subject: [PATCH v7 09/15] acpi,
 numa: move bad_srat() and srat_disabled() to drivers/acpi/numa.c
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-10-git-send-email-ddaney.cavm@gmail.com>

From: David Daney <david.daney at cavium.com>

bad_srat() and srat_disabled() are shared by x86 and follow-on arm64
patches.  Move them to drivers/acpi/numa.c in preparation for arm64
support.

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Robert Richter <rrichter at cavium.com>
[david.daney at cavium.com moved definitions to drivers/acpi/numa.c]
Signed-off-by: David Daney <david.daney at cavium.com>
---
 arch/x86/include/asm/acpi.h |  1 -
 arch/x86/mm/numa.c          |  2 +-
 arch/x86/mm/srat.c          | 13 -------------
 drivers/acpi/numa.c         | 12 ++++++++++++
 include/acpi/acpi_numa.h    |  4 ++++
 5 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 94c18eb..65f1e95 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -145,7 +145,6 @@ static inline void disable_acpi(void) { }
 #define ARCH_HAS_POWER_INIT	1
 
 #ifdef CONFIG_ACPI_NUMA
-extern int acpi_numa;
 extern int x86_acpi_numa_init(void);
 #endif /* CONFIG_ACPI_NUMA */
 
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index 9c086c5..968ac02 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -1,4 +1,5 @@
 /* Common code for 32 and 64-bit NUMA */
+#include <linux/acpi.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/string.h>
@@ -15,7 +16,6 @@
 #include <asm/e820.h>
 #include <asm/proto.h>
 #include <asm/dma.h>
-#include <asm/acpi.h>
 #include <asm/amd_nb.h>
 
 #include "numa_internal.h"
diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c
index 9e2a833..4217071f 100644
--- a/arch/x86/mm/srat.c
+++ b/arch/x86/mm/srat.c
@@ -24,19 +24,6 @@
 #include <asm/apic.h>
 #include <asm/uv/uv.h>
 
-int acpi_numa __initdata;
-
-static __init void bad_srat(void)
-{
-	printk(KERN_ERR "SRAT: SRAT not used.\n");
-	acpi_numa = -1;
-}
-
-static __init inline int srat_disabled(void)
-{
-	return acpi_numa < 0;
-}
-
 /* Callback for Proximity Domain -> x2APIC mapping */
 void __init
 acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 7e0649d..af0c8d5 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -40,6 +40,7 @@ static int node_to_pxm_map[MAX_NUMNODES]
 			= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
 
 unsigned char acpi_srat_revision __initdata;
+int acpi_numa __initdata;
 
 int pxm_to_node(int pxm)
 {
@@ -197,6 +198,17 @@ static int __init slit_valid(struct acpi_table_slit *slit)
 	return 1;
 }
 
+void __init bad_srat(void)
+{
+	pr_err("SRAT: SRAT not used.\n");
+	acpi_numa = -1;
+}
+
+int __init srat_disabled(void)
+{
+	return acpi_numa < 0;
+}
+
 #if defined(CONFIG_X86) || defined(CONFIG_ARM64)
 /*
  * Callback for SLIT parsing.  pxm_to_node() returns NUMA_NO_NODE for
diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h
index 94a37cd..d4b7294 100644
--- a/include/acpi/acpi_numa.h
+++ b/include/acpi/acpi_numa.h
@@ -15,6 +15,10 @@ extern int pxm_to_node(int);
 extern int node_to_pxm(int);
 extern int acpi_map_pxm_to_node(int);
 extern unsigned char acpi_srat_revision;
+extern int acpi_numa __initdata;
+
+extern void bad_srat(void);
+extern int srat_disabled(void);
 
 #endif				/* CONFIG_ACPI_NUMA */
 #endif				/* __ACP_NUMA_H */
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:44 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:44 -0700
Subject: [PATCH v7 14/15] arm64, acpi,
 numa: NUMA support based on SRAT and SLIT
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-15-git-send-email-ddaney.cavm@gmail.com>

From: Hanjun Guo <hanjun.guo at linaro.org>

Introduce a new file to hold ACPI based NUMA information parsing from
SRAT and SLIT.

SRAT includes the CPU ACPI ID to Proximity Domain mappings and memory
ranges to Proximity Domain mapping.  SLIT has the information of inter
node distances(relative number for access latency).

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Ganapatrao Kulkarni <gkulkarni at caviumnetworks.com>
[rrichter at cavium.com Reworked for numa v10 series ]
Signed-off-by: Robert Richter <rrichter at cavium.com>
[david.daney at cavium.com reorderd and combinded with other patches in
Hanjun Guo's original set, removed get_mpidr_in_madt() and use
acpi_map_madt_entry() instead.]
Signed-off-by: David Daney <david.daney at cavium.com>
---
 arch/arm64/include/asm/acpi.h |   8 +++
 arch/arm64/include/asm/numa.h |   2 +
 arch/arm64/kernel/Makefile    |   1 +
 arch/arm64/kernel/acpi_numa.c | 112 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/smp.c       |   2 +
 arch/arm64/mm/numa.c          |   5 +-
 6 files changed, 129 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/acpi_numa.c

diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index aee323b..4b13ecd 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -113,4 +113,12 @@ static inline const char *acpi_get_enable_method(int cpu)
 pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr);
 #endif
 
+#ifdef CONFIG_ACPI_NUMA
+int arm64_acpi_numa_init(void);
+int acpi_numa_get_nid(unsigned int cpu, u64 hwid);
+#else
+static inline int arm64_acpi_numa_init(void) { return -ENOSYS; }
+static inline int acpi_numa_get_nid(unsigned int cpu, u64 hwid) { return NUMA_NO_NODE; }
+#endif /* CONFIG_ACPI_NUMA */
+
 #endif /*_ASM_ACPI_H*/
diff --git a/arch/arm64/include/asm/numa.h b/arch/arm64/include/asm/numa.h
index e9b4f29..600887e 100644
--- a/arch/arm64/include/asm/numa.h
+++ b/arch/arm64/include/asm/numa.h
@@ -5,6 +5,8 @@
 
 #ifdef CONFIG_NUMA
 
+#define NR_NODE_MEMBLKS		(MAX_NUMNODES * 2)
+
 /* currently, arm64 implements flat NUMA topology */
 #define parent_node(node)	(node)
 
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2173149..a5125c6 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -42,6 +42,7 @@ arm64-obj-$(CONFIG_EFI)			+= efi.o efi-entry.stub.o
 arm64-obj-$(CONFIG_PCI)			+= pci.o
 arm64-obj-$(CONFIG_ARMV8_DEPRECATED)	+= armv8_deprecated.o
 arm64-obj-$(CONFIG_ACPI)		+= acpi.o
+arm64-obj-$(CONFIG_ACPI_NUMA)		+= acpi_numa.o
 arm64-obj-$(CONFIG_ARM64_ACPI_PARKING_PROTOCOL)	+= acpi_parking_protocol.o
 arm64-obj-$(CONFIG_PARAVIRT)		+= paravirt.o
 arm64-obj-$(CONFIG_RANDOMIZE_BASE)	+= kaslr.o
diff --git a/arch/arm64/kernel/acpi_numa.c b/arch/arm64/kernel/acpi_numa.c
new file mode 100644
index 0000000..f85149c
--- /dev/null
+++ b/arch/arm64/kernel/acpi_numa.c
@@ -0,0 +1,112 @@
+/*
+ * ACPI 5.1 based NUMA setup for ARM64
+ * Lots of code was borrowed from arch/x86/mm/srat.c
+ *
+ * Copyright 2004 Andi Kleen, SuSE Labs.
+ * Copyright (C) 2013-2016, Linaro Ltd.
+ *		Author: Hanjun Guo <hanjun.guo at linaro.org>
+ *
+ * Reads the ACPI SRAT table to figure out what memory belongs to which CPUs.
+ *
+ * Called from acpi_numa_init while reading the SRAT and SLIT tables.
+ * Assumes all memory regions belonging to a single proximity domain
+ * are in one chunk. Holes between them will be included in the node.
+ */
+
+#define pr_fmt(fmt) "ACPI: NUMA: " fmt
+
+#include <linux/acpi.h>
+#include <linux/bitmap.h>
+#include <linux/bootmem.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/memblock.h>
+#include <linux/mmzone.h>
+#include <linux/module.h>
+#include <linux/topology.h>
+
+#include <acpi/processor.h>
+#include <asm/numa.h>
+
+static int cpus_in_srat;
+
+struct __node_cpu_hwid {
+	u32 node_id;    /* logical node containing this CPU */
+	u64 cpu_hwid;   /* MPIDR for this CPU */
+};
+
+static struct __node_cpu_hwid early_node_cpu_hwid[NR_CPUS] = {
+[0 ... NR_CPUS - 1] = {NUMA_NO_NODE, PHYS_CPUID_INVALID} };
+
+int acpi_numa_get_nid(unsigned int cpu, u64 hwid)
+{
+	int i;
+
+	for (i = 0; i < cpus_in_srat; i++) {
+		if (hwid == early_node_cpu_hwid[i].cpu_hwid)
+			return early_node_cpu_hwid[i].node_id;
+	}
+
+	return NUMA_NO_NODE;
+}
+
+/* Callback for Proximity Domain -> ACPI processor UID mapping */
+void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa)
+{
+	int pxm, node;
+	phys_cpuid_t mpidr;
+
+	if (srat_disabled())
+		return;
+
+	if (pa->header.length < sizeof(struct acpi_srat_gicc_affinity)) {
+		pr_err("SRAT: Invalid SRAT header length: %d\n",
+			pa->header.length);
+		bad_srat();
+		return;
+	}
+
+	if (!(pa->flags & ACPI_SRAT_GICC_ENABLED))
+		return;
+
+	if (cpus_in_srat >= NR_CPUS) {
+		pr_warn_once("SRAT: cpu_to_node_map[%d] is too small, may not be able to use all cpus\n",
+			     NR_CPUS);
+		return;
+	}
+
+	pxm = pa->proximity_domain;
+	node = acpi_map_pxm_to_node(pxm);
+
+	if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
+		pr_err("SRAT: Too many proximity domains %d\n", pxm);
+		bad_srat();
+		return;
+	}
+
+	mpidr = acpi_map_madt_entry(pa->acpi_processor_uid);
+	if (mpidr == PHYS_CPUID_INVALID) {
+		pr_err("SRAT: PXM %d with ACPI ID %d has no valid MPIDR in MADT\n",
+			pxm, pa->acpi_processor_uid);
+		bad_srat();
+		return;
+	}
+
+	early_node_cpu_hwid[cpus_in_srat].node_id = node;
+	early_node_cpu_hwid[cpus_in_srat].cpu_hwid =  mpidr;
+	node_set(node, numa_nodes_parsed);
+	cpus_in_srat++;
+	pr_info("SRAT: PXM %d -> MPIDR 0x%Lx -> Node %d\n",
+		pxm, mpidr, node);
+}
+
+int __init arm64_acpi_numa_init(void)
+{
+	int ret;
+
+	ret = acpi_numa_init();
+	if (ret)
+		return ret;
+
+	return srat_disabled() ? -EINVAL : 0;
+}
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 678e084..d099306 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -560,6 +560,8 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
 	 */
 	acpi_set_mailbox_entry(cpu_count, processor);
 
+	early_map_cpu_to_node(cpu_count, acpi_numa_get_nid(cpu_count, hwid));
+
 	cpu_count++;
 }
 
diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
index 1def1de..c7fe3ec 100644
--- a/arch/arm64/mm/numa.c
+++ b/arch/arm64/mm/numa.c
@@ -17,6 +17,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
 #include <linux/module.h>
@@ -391,7 +392,9 @@ static int __init dummy_numa_init(void)
 void __init arm64_numa_init(void)
 {
 	if (!numa_off) {
-		if (!numa_init(of_numa_init))
+		if (!acpi_disabled && !numa_init(arm64_acpi_numa_init))
+			return;
+		if (acpi_disabled && !numa_init(of_numa_init))
 			return;
 	}
 
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:40 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:40 -0700
Subject: [PATCH v7 10/15] acpi, numa: remove unneeded acpi_numa=1
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-11-git-send-email-ddaney.cavm@gmail.com>

From: Hanjun Guo <hanjun.guo at linaro.org>

acpi_numa is default to 0, it's set to -1 when disable acpi numa or
when a bad SRAT is parsed, and it's only consumed in srat_disabled()
(compare it with 0) to continue parse the SRAT or not, so we don't
need to set acpi_numa to 1 when we get a valid SRAT entry.

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Robert Richter <rrichter at cavium.com>
Signed-off-by: David Daney <david.daney at cavium.com>
---
 arch/x86/mm/srat.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c
index 4217071f..30460f5 100644
--- a/arch/x86/mm/srat.c
+++ b/arch/x86/mm/srat.c
@@ -59,7 +59,6 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
 	}
 	set_apicid_to_node(apic_id, node);
 	node_set(node, numa_nodes_parsed);
-	acpi_numa = 1;
 	printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u\n",
 	       pxm, apic_id, node);
 }
@@ -101,7 +100,6 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
 
 	set_apicid_to_node(apic_id, node);
 	node_set(node, numa_nodes_parsed);
-	acpi_numa = 1;
 	printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u\n",
 	       pxm, apic_id, node);
 }
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:43 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:43 -0700
Subject: [PATCH v7 13/15] ACPI / processor: Add acpi_map_madt_entry().
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-14-git-send-email-ddaney.cavm@gmail.com>

From: David Daney <david.daney at cavium.com>

Follow-on arm64 ACPI/NUMA patches need to map MADT entries very early
(before kmalloc is usable).

Add acpi_map_madt_entry() which, indirectly, uses
early_memremap()/early_memunmap() to access the table and parse out
the mpidr.  The existing implementation of map_madt_entry() is
modified to take a pointer to the MADT as a parameter and the callers
adjusted.

Signed-off-by: David Daney <david.daney at cavium.com>
---
 drivers/acpi/processor_core.c | 26 ++++++++++++++++++++++----
 include/acpi/processor.h      |  1 +
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 33a38d6..9125d7d 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -108,13 +108,12 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry,
 	return -EINVAL;
 }
 
-static phys_cpuid_t map_madt_entry(int type, u32 acpi_id)
+static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
+				   int type, u32 acpi_id)
 {
 	unsigned long madt_end, entry;
 	phys_cpuid_t phys_id = PHYS_CPUID_INVALID;	/* CPU hardware ID */
-	struct acpi_table_madt *madt;
 
-	madt = get_madt_table();
 	if (!madt)
 		return phys_id;
 
@@ -145,6 +144,25 @@ static phys_cpuid_t map_madt_entry(int type, u32 acpi_id)
 	return phys_id;
 }
 
+phys_cpuid_t __init acpi_map_madt_entry(u32 acpi_id)
+{
+	struct acpi_table_madt *madt = NULL;
+	acpi_size tbl_size;
+	phys_cpuid_t rv;
+
+	acpi_get_table_with_size(ACPI_SIG_MADT, 0,
+				 (struct acpi_table_header **)&madt,
+				 &tbl_size);
+	if (!madt)
+		return PHYS_CPUID_INVALID;
+
+	rv = map_madt_entry(madt, 1, acpi_id);
+
+	early_acpi_os_unmap_memory(madt, tbl_size);
+
+	return rv;
+}
+
 static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
 {
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -185,7 +203,7 @@ phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id)
 
 	phys_id = map_mat_entry(handle, type, acpi_id);
 	if (invalid_phys_cpuid(phys_id))
-		phys_id = map_madt_entry(type, acpi_id);
+		phys_id = map_madt_entry(get_madt_table(), type, acpi_id);
 
 	return phys_id;
 }
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 6f1805d..f473e66 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -309,6 +309,7 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
 
 /* in processor_core.c */
 phys_cpuid_t acpi_get_phys_id(acpi_handle, int type, u32 acpi_id);
+phys_cpuid_t acpi_map_madt_entry(u32 acpi_id);
 int acpi_map_cpuid(phys_cpuid_t phys_id, u32 acpi_id);
 int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id);
 
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:42 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:42 -0700
Subject: [PATCH v7 12/15] acpi, numa,
 srat: Improve SRAT error detection and add messages.
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-13-git-send-email-ddaney.cavm@gmail.com>

From: David Daney <david.daney at cavium.com>

Loosely based on code from Robert Richter and Hanjun Guo.

Improve out of range node detection as well as allow for Larger SRAT
entities.

Add printing of nice messages.

Signed-off-by: David Daney <david.daney at cavium.com>
---
 drivers/acpi/numa.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 811f90a..fad6d28 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -252,8 +252,11 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 
 	if (srat_disabled())
 		goto out_err;
-	if (ma->header.length != sizeof(struct acpi_srat_mem_affinity))
+	if (ma->header.length < sizeof(struct acpi_srat_mem_affinity)) {
+		pr_err("SRAT: Unexpected header length: %d\n",
+		       ma->header.length);
 		goto out_err_bad_srat;
+	}
 	if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
 		goto out_err;
 	hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE;
@@ -267,13 +270,17 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 		pxm &= 0xff;
 
 	node = acpi_map_pxm_to_node(pxm);
-	if (node < 0) {
-		printk(KERN_ERR "SRAT: Too many proximity domains.\n");
+	if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
+		pr_err("SRAT: Too many proximity domains.\n");
 		goto out_err_bad_srat;
 	}
 
-	if (numa_add_memblk(node, start, end) < 0)
+	if (numa_add_memblk(node, start, end) < 0) {
+		pr_err("SRAT: Failed to add memblk to node %u [mem %#010Lx-%#010Lx]\n",
+		       node, (unsigned long long) start,
+		       (unsigned long long) end - 1);
 		goto out_err_bad_srat;
+	}
 
 	node_set(node, numa_nodes_parsed);
 
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:41 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:41 -0700
Subject: [PATCH v7 11/15] acpi,
 numa: Move acpi_numa_memory_affinity_init() to drivers/acpi/numa.c
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-12-git-send-email-ddaney.cavm@gmail.com>

From: Hanjun Guo <hanjun.guo at linaro.org>

acpi_numa_memory_affinity_init() will be reused by arm64.  Move it to
drivers/acpi/numa.c to facilitate reuse.

No code change.

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Robert Richter <rrichter at cavium.com>
Signed-off-by: David Daney <david.daney at cavium.com>
---
 arch/x86/mm/srat.c  | 57 --------------------------------------------------
 drivers/acpi/numa.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 57 deletions(-)

diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c
index 30460f5..b1ecff4 100644
--- a/arch/x86/mm/srat.c
+++ b/arch/x86/mm/srat.c
@@ -15,8 +15,6 @@
 #include <linux/bitmap.h>
 #include <linux/module.h>
 #include <linux/topology.h>
-#include <linux/bootmem.h>
-#include <linux/memblock.h>
 #include <linux/mm.h>
 #include <asm/proto.h>
 #include <asm/numa.h>
@@ -104,61 +102,6 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
 	       pxm, apic_id, node);
 }
 
-/* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
-int __init
-acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
-{
-	u64 start, end;
-	u32 hotpluggable;
-	int node, pxm;
-
-	if (srat_disabled())
-		goto out_err;
-	if (ma->header.length != sizeof(struct acpi_srat_mem_affinity))
-		goto out_err_bad_srat;
-	if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
-		goto out_err;
-	hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE;
-	if (hotpluggable && !IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
-		goto out_err;
-
-	start = ma->base_address;
-	end = start + ma->length;
-	pxm = ma->proximity_domain;
-	if (acpi_srat_revision <= 1)
-		pxm &= 0xff;
-
-	node = acpi_map_pxm_to_node(pxm);
-	if (node < 0) {
-		printk(KERN_ERR "SRAT: Too many proximity domains.\n");
-		goto out_err_bad_srat;
-	}
-
-	if (numa_add_memblk(node, start, end) < 0)
-		goto out_err_bad_srat;
-
-	node_set(node, numa_nodes_parsed);
-
-	pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s%s\n",
-		node, pxm,
-		(unsigned long long) start, (unsigned long long) end - 1,
-		hotpluggable ? " hotplug" : "",
-		ma->flags & ACPI_SRAT_MEM_NON_VOLATILE ? " non-volatile" : "");
-
-	/* Mark hotplug range in memblock. */
-	if (hotpluggable && memblock_mark_hotplug(start, ma->length))
-		pr_warn("SRAT: Failed to mark hotplug range [mem %#010Lx-%#010Lx] in memblock\n",
-			(unsigned long long)start, (unsigned long long)end - 1);
-
-	max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1));
-
-	return 0;
-out_err_bad_srat:
-	bad_srat();
-out_err:
-	return -EINVAL;
-}
-
 int __init x86_acpi_numa_init(void)
 {
 	int ret;
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index af0c8d5..811f90a 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -27,6 +27,8 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/acpi.h>
+#include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/numa.h>
 #include <linux/nodemask.h>
 #include <linux/topology.h>
@@ -236,6 +238,64 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
 		}
 	}
 }
+
+/*
+ * Default callback for parsing of the Proximity Domain <-> Memory
+ * Area mappings
+ */
+int __init
+acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
+{
+	u64 start, end;
+	u32 hotpluggable;
+	int node, pxm;
+
+	if (srat_disabled())
+		goto out_err;
+	if (ma->header.length != sizeof(struct acpi_srat_mem_affinity))
+		goto out_err_bad_srat;
+	if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
+		goto out_err;
+	hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE;
+	if (hotpluggable && !IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
+		goto out_err;
+
+	start = ma->base_address;
+	end = start + ma->length;
+	pxm = ma->proximity_domain;
+	if (acpi_srat_revision <= 1)
+		pxm &= 0xff;
+
+	node = acpi_map_pxm_to_node(pxm);
+	if (node < 0) {
+		printk(KERN_ERR "SRAT: Too many proximity domains.\n");
+		goto out_err_bad_srat;
+	}
+
+	if (numa_add_memblk(node, start, end) < 0)
+		goto out_err_bad_srat;
+
+	node_set(node, numa_nodes_parsed);
+
+	pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s%s\n",
+		node, pxm,
+		(unsigned long long) start, (unsigned long long) end - 1,
+		hotpluggable ? " hotplug" : "",
+		ma->flags & ACPI_SRAT_MEM_NON_VOLATILE ? " non-volatile" : "");
+
+	/* Mark hotplug range in memblock. */
+	if (hotpluggable && memblock_mark_hotplug(start, ma->length))
+		pr_warn("SRAT: Failed to mark hotplug range [mem %#010Lx-%#010Lx] in memblock\n",
+			(unsigned long long)start, (unsigned long long)end - 1);
+
+	max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1));
+
+	return 0;
+out_err_bad_srat:
+	bad_srat();
+out_err:
+	return -EINVAL;
+}
 #endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */
 
 static int __init acpi_parse_slit(struct acpi_table_header *table)
-- 
1.7.11.7



From ddaney.cavm at gmail.com  Tue May 24 15:35:45 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Tue, 24 May 2016 15:35:45 -0700
Subject: [PATCH v7 15/15] acpi, numa: Enable ACPI based NUMA on ARM64
In-Reply-To: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <1464129345-18985-16-git-send-email-ddaney.cavm@gmail.com>

From: Hanjun Guo <hanjun.guo at linaro.org>

Add function needed for cpu to node mapping, and enable ACPI based
NUMA for ARM64 in Kconfig

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Robert Richter <rrichter at cavium.com>
[david.daney at cavium.com added ACPI_NUMA default to y for ARM64]
Signed-off-by: David Daney <david.daney at cavium.com>
Acked-by: Catalin Marinas <catalin.marinas at arm.com>
---
 drivers/acpi/Kconfig |  4 ++--
 drivers/acpi/numa.c  | 37 ++++++++++++++++++++++++++++++++++++-
 include/linux/acpi.h | 17 ++++++++++++++++-
 3 files changed, 54 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index b7e2e77..dd76b36 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -291,8 +291,8 @@ config ACPI_THERMAL
 config ACPI_NUMA
 	bool "NUMA support"
 	depends on NUMA
-	depends on (X86 || IA64)
-	default y if IA64_GENERIC || IA64_SGI_SN2
+	depends on (X86 || IA64 || ARM64)
+	default y if IA64_GENERIC || IA64_SGI_SN2 || ARM64
 
 config ACPI_CUSTOM_DSDT_FILE
 	string "Custom DSDT Table file to include"
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index fad6d28..9b7ce40 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -170,6 +170,18 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
 		}
 		break;
 
+	case ACPI_SRAT_TYPE_GICC_AFFINITY:
+		{
+			struct acpi_srat_gicc_affinity *p =
+			    (struct acpi_srat_gicc_affinity *)header;
+			pr_debug("SRAT Processor (acpi id[0x%04x]) in proximity domain %d %s\n",
+				 p->acpi_processor_uid,
+				 p->proximity_domain,
+				 (p->flags & ACPI_SRAT_GICC_ENABLED) ?
+				 "enabled" : "disabled");
+		}
+		break;
+
 	default:
 		pr_warn("Found unsupported SRAT entry (type = 0x%x)\n",
 			header->type);
@@ -360,6 +372,24 @@ acpi_parse_processor_affinity(struct acpi_subtable_header *header,
 	return 0;
 }
 
+static int __init
+acpi_parse_gicc_affinity(struct acpi_subtable_header *header,
+			 const unsigned long end)
+{
+	struct acpi_srat_gicc_affinity *processor_affinity;
+
+	processor_affinity = (struct acpi_srat_gicc_affinity *)header;
+	if (!processor_affinity)
+		return -EINVAL;
+
+	acpi_table_print_srat_entry(header);
+
+	/* let architecture-dependent part to do it */
+	acpi_numa_gicc_affinity_init(processor_affinity);
+
+	return 0;
+}
+
 static int __initdata parsed_numa_memblks;
 
 static int __init
@@ -404,6 +434,9 @@ int __init acpi_numa_init(void)
 {
 	int cnt = 0;
 
+	if (acpi_disabled)
+		return -EINVAL;
+
 	/*
 	 * Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
 	 * SRAT cpu entries could have different order with that in MADT.
@@ -412,13 +445,15 @@ int __init acpi_numa_init(void)
 
 	/* SRAT: Static Resource Affinity Table */
 	if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
-		struct acpi_subtable_proc srat_proc[2];
+		struct acpi_subtable_proc srat_proc[3];
 
 		memset(srat_proc, 0, sizeof(srat_proc));
 		srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY;
 		srat_proc[0].handler = acpi_parse_processor_affinity;
 		srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY;
 		srat_proc[1].handler = acpi_parse_x2apic_affinity;
+		srat_proc[1].id = ACPI_SRAT_TYPE_GICC_AFFINITY;
+		srat_proc[1].handler = acpi_parse_gicc_affinity;
 
 		acpi_table_parse_entries_array(ACPI_SIG_SRAT,
 					sizeof(struct acpi_table_srat),
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 8010b26..9515db6 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -232,10 +232,25 @@ int acpi_table_parse_madt(enum acpi_madt_type id,
 int acpi_parse_mcfg (struct acpi_table_header *header);
 void acpi_table_print_madt_entry (struct acpi_subtable_header *madt);
 
-/* the following four functions are architecture-dependent */
+/* the following numa functions are architecture-dependent */
 void acpi_numa_slit_init (struct acpi_table_slit *slit);
+
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
 void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa);
+#else
+static inline void
+acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) { }
+#endif
+
 void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);
+
+#ifdef CONFIG_ARM64
+void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa);
+#else
+static inline void
+acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { }
+#endif
+
 int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
 
 #ifndef PHYS_CPUID_INVALID
-- 
1.7.11.7



From horms at verge.net.au  Tue May 24 17:48:25 2016
From: horms at verge.net.au (Simon Horman)
Date: Wed, 25 May 2016 09:48:25 +0900
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
Message-ID: <20160525004825.GC7292@verge.net.au>

Hi Dirk,

On Tue, May 24, 2016 at 07:30:17AM +0200, Dirk Behme wrote:
> Hi Simon,

[...]

> With Renesas R-Car3 we will get a whole family of SoCs. I.e. different
> computing power (e.g. different number of Cores) with more or less similar
> peripherals.
> 
> I would think that we want to reflect this in the device tree, too.
> Therefore I think what we want is a hierarchy of device trees. Similar
> what's done with other SoC families (compare e.g. i.MX6).
> 
> E.g. we want an initial rcar3.dtsi, which contains all common parts of all
> R-Car3 SoCs. E.g. one CA57 core, the SCIF where its common etc.
> 
> Then you will have the r8a779x.dtsi which includes the rcar3.dtsi and
> extends it for SoC specific parts. Which then will be included by the board
> device trees, as already done, now.
> 
> Or in other words: As soon as you have similar parts in the r8a779x.dtsi's,
> it's time to think about moving the parts one hierarchy level up into the
> rcar3.dtsi. Else you will end up in a maintenance hell once you have to
> change/fix anything.

Thanks for raising this issue.

I agree entirely that we should work towards a situation where maintenance
is as easy as it can be. However, due to the per-SoC binding scheme that
we are using for IP related to Renesas SoCs I suspect that very few DT nodes
can be shared between SoCs verbatim.

Probably some sort of scheme can be cooked up using preprocessor macros.
And probably there are other ways to resolve this problem. But I would
prefer if we worked towards resolving this maintenance problem in parallel
with rather than as a dependency of merging r8a7796 support into mainline.


From horms at verge.net.au  Tue May 24 18:01:51 2016
From: horms at verge.net.au (Simon Horman)
Date: Wed, 25 May 2016 10:01:51 +0900
Subject: [PATCH] ARM: shmobile: rcar-gen2: Use ICRAM1 for jump stub on
 all SoCs
In-Reply-To: <1463498133-23918-1-git-send-email-geert+renesas@glider.be>
References: <1463498133-23918-1-git-send-email-geert+renesas@glider.be>
Message-ID: <20160525010150.GD7292@verge.net.au>

On Tue, May 17, 2016 at 05:15:33PM +0200, Geert Uytterhoeven wrote:
> Currently the different SoCs in the R-Car Gen2 family use different
> types of on-chip RAM for the jump stub:
>   - R-Car H2 uses Media RAM,
>   - R-Car M2-W uses another type of optional On-chip RAM, as it doesn't
>     have Media RAM,
>   - R-Car M2-N uses Inter Connect RAM in Magnus Damm's "ARM: shmobile:
>     r8a7793 boot address update".
> 
> As all R-Car Gen2 SoCs have 4 KiB of Inter Connect RAM, consolidate the
> code by always using that.
> 
> Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
> ---
> Tested on r8a7790/lager and r8a7791/koelsch.
> ---
>  arch/arm/mach-shmobile/pm-rcar-gen2.c | 13 ++++---------
>  1 file changed, 4 insertions(+), 9 deletions(-)

Thanks, I have queued this up.


From horms+renesas at verge.net.au  Tue May 24 18:11:40 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Wed, 25 May 2016 10:11:40 +0900
Subject: [PATCH] rm64: dts: r8a7795: Drop 0x from unit address of gic
Message-ID: <1464138700-12219-1-git-send-email-horms+renesas@verge.net.au>

Drop 0x from unit address of gic as this is the desired form for
a unit address.

Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
---
As suggested by Geert Uytterhoeven
---
 arch/arm64/boot/dts/renesas/r8a7795.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
index a4f4ec8daa21..04eb0bc65634 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
@@ -153,7 +153,7 @@
 		#size-cells = <2>;
 		ranges;
 
-		gic: interrupt-controller at 0xf1010000 {
+		gic: interrupt-controller at f1010000 {
 			compatible = "arm,gic-400";
 			#interrupt-cells = <3>;
 			#address-cells = <0>;
-- 
2.1.4



From josephl at nvidia.com  Tue May 24 19:11:51 2016
From: josephl at nvidia.com (Joseph Lo)
Date: Wed, 25 May 2016 10:11:51 +0800
Subject: [PATCH] arm64: tegra: Fix CPU compatible string for Tegra132
In-Reply-To: <20160523074221.7135-1-josephl@nvidia.com>
References: <20160523074221.7135-1-josephl@nvidia.com>
Message-ID: <574509E7.4030208@nvidia.com>

On 05/23/2016 03:42 PM, Joseph Lo wrote:
> As per commit f634da375fc96 ("Documentation: DT bindings: add nvidia,
> tegra132-denver compatible string"), fixing the CPU compatible string for
> Tegra132 to match the binding document currently.
>
> Signed-off-by: Joseph Lo <josephl at nvidia.com>
> ---
>   arch/arm64/boot/dts/nvidia/tegra132.dtsi | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
> index 2013f8916084..7b1cdc029de3 100644
> --- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
> +++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
> @@ -964,13 +964,13 @@
>
>   		cpu at 0 {
>   			device_type = "cpu";
> -			compatible = "nvidia,denver", "arm,armv8";
> +			compatible = "nvidia,tegra132-denver", "arm,armv8";

Hi Stephen, Thierry,

Should we fix this or fix the compatible string in the binding document 
as just "nvidia,denver" to represent all the Devner CPU revisions just 
like some other CPUs did? e.g. arm,cortex-a57, which represents all the 
A57 revisions.

Thanks,
-Joseph

>   			reg = <0>;
>   		};
>
>   		cpu at 1 {
>   			device_type = "cpu";
> -			compatible = "nvidia,denver", "arm,armv8";
> +			compatible = "nvidia,tegra132-denver", "arm,armv8";
>   			reg = <1>;
>   		};
>   	};
>


From a0393675 at ti.com  Tue May 24 20:21:26 2016
From: a0393675 at ti.com (Keerthy)
Date: Wed, 25 May 2016 08:51:26 +0530
Subject: [PATCH 3/3] ARM: configs: keystone: Enable PINCTRL_SINGLE Config
In-Reply-To: <6325832e-24d2-43c7-09b4-a73b6549ee2c@oracle.com>
References: <1464006547-19569-1-git-send-email-j-keerthy@ti.com>
 <1464006547-19569-4-git-send-email-j-keerthy@ti.com>
 <5743CC80.4070404@ti.com> <5743D0FD.5070804@ti.com>
 <6325832e-24d2-43c7-09b4-a73b6549ee2c@oracle.com>
Message-ID: <57451A36.8050809@ti.com>

Hi Santosh,

On Tuesday 24 May 2016 09:59 PM, Santosh Shilimkar wrote:
> Hi Keerthy,
>
> On 5/23/2016 8:56 PM, Keerthy wrote:
>>
>>
>> On Tuesday 24 May 2016 09:07 AM, Lokesh Vutla wrote:
>>>
>>>
>>> On Monday 23 May 2016 05:59 PM, Keerthy wrote:
>>>> keystone-k2l devices use pinmux and are compliant with PINCTRL_SINGLE.
>>>> Hence enable the config option.
>>>>
>>>> Signed-off-by: Keerthy <j-keerthy at ti.com>
>>>
>>> A similar patch[1] is already posted.
>>>
>>> [1]https://patchwork.kernel.org/patch/8958091/
>>
>> Ah I had not seen them. If they are already reviewed and closer to be
>> merged then Patch 2 and Patch 3 of this series can be dropped.
>>
> Once the 4.7-rc2 is out, please rebase these floating patches
> against it and post a consolidated patches. I will line them
> up for 4.8

Thanks for the quick response. I will wait for 4.7-rc2 and send the 
re-based series.

Regards,
Keerthy

>
> Regards,
> Santosh


From andy.gross at linaro.org  Tue May 24 20:37:31 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Tue, 24 May 2016 22:37:31 -0500
Subject: [Patch v5 5/8] firmware: qcom: scm: Convert to streaming DMA APIS
In-Reply-To: <CAPBZ5Qc0oZ+k_5OiUGU6c9jFfcmAfsK3Uy-s=ONGCSGzCDyYNw@mail.gmail.com>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
 <1463111221-6963-6-git-send-email-andy.gross@linaro.org>
 <CAOi56cVB1Z-gO6Dx0KOSr9wiRF3Y9ahDHe0=qT9WW4MdFMhjng@mail.gmail.com>
 <CAPBZ5Qc0oZ+k_5OiUGU6c9jFfcmAfsK3Uy-s=ONGCSGzCDyYNw@mail.gmail.com>
Message-ID: <20160525033731.GA30220@hector.attlocal.net>

On Mon, May 23, 2016 at 04:02:06PM -0500, Andy Gross wrote:
> On 23 May 2016 at 14:26, Kevin Hilman <khilman at kernel.org> wrote:
> > Hi Andy,
> >
> > On Thu, May 12, 2016 at 8:46 PM, Andy Gross <andy.gross at linaro.org> wrote:
> >> This patch converts the Qualcomm SCM driver to use the streaming DMA APIs
> >> for communication buffers.
> >>
> >> Signed-off-by: Andy Gross <andy.gross at linaro.org>
> >
> > This patch has landed in linux-next in the form of commit a551c3dbd689
> > (firmware: qcom: scm: Convert to streaming DMA APIS), and kernelci.org
> > found some boot breakage in next-20160523 on apq8064[1] which was
> > bisected down to this commit.
> >
> > I reverted this commit on top of next-20160523 and it no longer
> > builds, so I didn't validate if things boot again with this patch
> > reverted.
> 
> Ouch I missed this failure.  I'll investigate and get it fixed.

So the root cause was the fact that the DFAB clock required by the SCM is an RPM
clock.  That support isn't present yet in the kernel, so SCM probe fails.

The core clock is really only accessed so that we can bump the clock on it up to
the max for performance.  As such, I'll make it optional in the platform code.

This does bring up the issue of probe defer causing issues with the spm driver,
as it calls set_warm_boot_addr.  That may have to be addressed, but is probably
a problem best fixed in the spm.

Regards,

Andy


From thunder.leizhen at huawei.com  Tue May 24 20:36:38 2016
From: thunder.leizhen at huawei.com (Leizhen (ThunderTown))
Date: Wed, 25 May 2016 11:36:38 +0800
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <5744FDD0.8060504@huawei.com>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
 <20160524113727.GD25374@leverpostej> <574446B9.8040105@huawei.com>
 <20160524130255.GU4892@e104818-lin.cambridge.arm.com>
 <5744FDD0.8060504@huawei.com>
Message-ID: <57451DC6.7080106@huawei.com>



On 2016/5/25 9:20, Leizhen (ThunderTown) wrote:
> 
> 
> On 2016/5/24 21:02, Catalin Marinas wrote:
>> On Tue, May 24, 2016 at 08:19:05PM +0800, Leizhen (ThunderTown) wrote:
>>> On 2016/5/24 19:37, Mark Rutland wrote:
>>>> On Tue, May 24, 2016 at 07:16:37PM +0800, Zhen Lei wrote:
>>>>> When we ran mprotect04(a test case in LTP) infinitely, it would always
>>>>> failed after a few seconds. The case can be described briefly that: copy
>>>>> a empty function from code area into a new memory area(created by mmap),
>>>>> then call mprotect to change the protection to PROT_EXEC. The syscall
>>>>> sys_mprotect will finally invoke flush_cache_range, but this function
>>>>> currently only invalid icache, the operation of flush dcache is missed.
>>>>
>>>> In the LTP code I see powerpc-specific D-cache / I-cache synchronisation
>>>> (i.e. d-cache cleaning followed by I-cache invalidation), so there
>>>> appears to be some expectation of userspace maintenance. Hoever, there
>>>> is no such ARM-specific I-cache maintenance.
>>>
>>> But I see some other platforms have D-cache maintenance, like: arch/nios2/mm/cacheflush.c
>>> And according to the name of flush_cache_range, it should do this, I judged. Otherwise,
>>> mprotect04 will be failed on more platforms, it's easy to discover. Only PPC have specific
>>> cache synchronization, maybe it meets some hardware limitation. It's impossible a programmer
>>> fixed a common bug on only one platform but leave others unchanged.
>>
>> flush_cache_range() is primarily used on VIVT caches before changing the
>> mapping and should not really be implemented on arm64. I don't recall
>> why we still have the I-cache invalidation, possibly for the ASID-tagged
>> VIVT I-cache case, though we should have a specific check for this.
>>
>> There are some other cases where flush_cache_range() is called and no
>> D-cache maintenance is necessary on arm64, so I don't want to penalise
>> them by implementing flush_cache_range().
>>
>>>> It looks like the test may be missing I-cache maintenance regardless of
>>>> the semantics of mprotect in this case.
>>>>
>>>> I have not yet devled into flush_cache_range and how it is called.
>>>
>>> SYSCALL_DEFINE3(mprotect ---> mprotect_fixup ---> change_protection ---> change_protection_range --> flush_cache_range
>>
>> The change_protection() shouldn't need to flush the caches in
>> flush_cache_range(). The change_pte_range() function eventually ends up
>> calling set_pte_at() which calls __sync_icache_dcache() if the mapping
>> is executable.
> 
> OK, I see.
> But I'm afraid it entered the "if (pte_present(oldpte))" branch in function change_pte_range.
> Because the test case called mmap to create pte first, then called pte_modify.
> I will check it later.

I have checked that it entered "if (pte_present(oldpte))" branch.

But I don't known why I add flush_icache_range is OK, but add __sync_icache_dcache have no effect.

> 
>>
>> Can you be more specific about the kernel version you are using, its
>> configuration?
>>
> I used the latest mainline kernel version, and built with arch/arm64/configs/defconfig, ran on our D02 board.
> I have attached the testcase, you can simply run: sh test.sh
> 



From wxt at rock-chips.com  Tue May 24 20:47:44 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 25 May 2016 11:47:44 +0800
Subject: [PATCH v3 0/5] Thermal: Support for hardware-tracked trip points
Message-ID: <1464148069-26254-1-git-send-email-wxt@rock-chips.com>

The history patches come from Mikko and Sascha.
    http://thread.gmane.org/gmane.linux.power-management.general/59451

Now, I pick them up to continue upstream.
Nevermind!

This series history patches:
v2: https://lkml.org/lkml/2016/5/3/220
v1: https://lkml.org/lkml/2016/4/24/227

This series adds support for hardware trip points. It picks up earlier
work from Mikko Perttunen. Mikko implemented hardware trip points as part
of the device tree support. It was suggested back then to move the
functionality to the thermal core instead of putting more code into the
device tree support. This series does exactly that.

This series patches rebase the conflicts.
Note that the hardware-tracked trip points are very well tested currently.

Verified and tested on https://github.com/Caesar-github/rockchip/tree/wip/fixes-thermal-0525
That's based on linux-kernel 20160524.


Changes in v3:
- as Javi comments on https://patchwork.kernel.org/patch/9001281/.
- add the lock for preventing the called from multi placce
- add the note for pre_low/high_trip.
- as the Javi comments on https://patchwork.kernel.org/patch/9001311/.
- add the select if they set the option for devicetree.
- Add the peter's ACK.

Changes in v2:
- update the sysfs-api.txt for set_trips.
- add the commit in patch[v2 2/5].
- Update the commit for patch[v2 4/5].

Caesar Wang (1):
  thermal: rockchip: add the set_trips function

Sascha Hauer (4):
  thermal: Add support for hardware-tracked trip points
  thermal: of: implement .set_trips for device tree thermal zones
  thermal: streamline get_trend callbacks
  thermal: bang-bang governor: act on lower trip boundary

 Documentation/thermal/sysfs-api.txt                |  7 +++
 drivers/thermal/gov_bang_bang.c                    |  2 +-
 drivers/thermal/of-thermal.c                       | 30 ++++++++-----
 drivers/thermal/rockchip_thermal.c                 | 39 ++++++++++++++++
 drivers/thermal/thermal_core.c                     | 52 ++++++++++++++++++++++
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 25 ++++-------
 include/linux/thermal.h                            | 13 +++++-
 7 files changed, 139 insertions(+), 29 deletions(-)

-- 
1.9.1



From wxt at rock-chips.com  Tue May 24 20:47:49 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 25 May 2016 11:47:49 +0800
Subject: [PATCH v3 5/5] thermal: rockchip: add the set_trips function
In-Reply-To: <1464148069-26254-1-git-send-email-wxt@rock-chips.com>
References: <1464148069-26254-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1464148069-26254-6-git-send-email-wxt@rock-chips.com>

Whenever the current temperature is updated, the trip points immediately
below and above the current temperature are found. A sensor driver
callback `set_trips' is then called with the temperatures.
Lastly, The sensor will trigger the hardware high temperature interrupts
to increase the sampleing rate and throttle frequency to limit the
temperature rising When performing passive cooling.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Zhang Rui <rui.zhang at intel.com>
Cc: Eduardo Valentin <edubezval at gmail.com>
Cc: linux-pm at vger.kernel.org

---

Changes in v3: None
Changes in v2: None

 drivers/thermal/rockchip_thermal.c | 39 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index 86a1ab0..39e2eec 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -96,6 +96,7 @@ struct chip_tsadc_table {
  * @initialize: SoC special initialize tsadc controller method
  * @irq_ack: clear the interrupt
  * @get_temp: get the temperature
+ * @set_alarm_temp: set the high temperature interrupt
  * @set_tshut_temp: set the hardware-controlled shutdown temperature
  * @set_tshut_mode: set the hardware-controlled shutdown mode
  * @table: the chip-specific conversion table
@@ -119,6 +120,8 @@ struct rockchip_tsadc_chip {
 	/* Per-sensor methods */
 	int (*get_temp)(struct chip_tsadc_table table,
 			int chn, void __iomem *reg, int *temp);
+	void (*set_alarm_temp)(struct chip_tsadc_table table,
+			       int chn, void __iomem *reg, int temp);
 	void (*set_tshut_temp)(struct chip_tsadc_table table,
 			       int chn, void __iomem *reg, int temp);
 	void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
@@ -183,6 +186,7 @@ struct rockchip_thermal_data {
 #define TSADCV2_INT_EN				0x08
 #define TSADCV2_INT_PD				0x0c
 #define TSADCV2_DATA(chn)			(0x20 + (chn) * 0x04)
+#define TSADCV2_COMP_INT(chn)		        (0x30 + (chn) * 0x04)
 #define TSADCV2_COMP_SHUT(chn)		        (0x40 + (chn) * 0x04)
 #define TSADCV2_HIGHT_INT_DEBOUNCE		0x60
 #define TSADCV2_HIGHT_TSHUT_DEBOUNCE		0x64
@@ -628,6 +632,20 @@ static int rk_tsadcv2_get_temp(struct chip_tsadc_table table,
 	return rk_tsadcv2_code_to_temp(table, val, temp);
 }
 
+static void rk_tsadcv2_alarm_temp(struct chip_tsadc_table table,
+				  int chn, void __iomem *regs, int temp)
+{
+	u32 alarm_value, int_en;
+
+	alarm_value = rk_tsadcv2_temp_to_code(table, temp);
+	writel_relaxed(alarm_value & table.data_mask,
+		       regs + TSADCV2_COMP_INT(chn));
+
+	int_en = readl_relaxed(regs + TSADCV2_INT_EN);
+	int_en |= TSADCV2_INT_SRC_EN(chn);
+	writel_relaxed(int_en, regs + TSADCV2_INT_EN);
+}
+
 static void rk_tsadcv2_tshut_temp(struct chip_tsadc_table table,
 				  int chn, void __iomem *regs, int temp)
 {
@@ -670,6 +688,7 @@ static const struct rockchip_tsadc_chip rk3228_tsadc_data = {
 	.irq_ack = rk_tsadcv3_irq_ack,
 	.control = rk_tsadcv3_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -694,6 +713,7 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
 	.irq_ack = rk_tsadcv2_irq_ack,
 	.control = rk_tsadcv2_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -718,6 +738,7 @@ static const struct rockchip_tsadc_chip rk3366_tsadc_data = {
 	.irq_ack = rk_tsadcv3_irq_ack,
 	.control = rk_tsadcv3_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -742,6 +763,7 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = {
 	.irq_ack = rk_tsadcv2_irq_ack,
 	.control = rk_tsadcv2_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -766,6 +788,7 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
 	.irq_ack = rk_tsadcv3_irq_ack,
 	.control = rk_tsadcv3_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -826,6 +849,21 @@ static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
+static int rockchip_thermal_set_trips(void *_sensor, int low, int high)
+{
+	struct rockchip_thermal_sensor *sensor = _sensor;
+	struct rockchip_thermal_data *thermal = sensor->thermal;
+	const struct rockchip_tsadc_chip *tsadc = thermal->chip;
+
+	dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n",
+		__func__, sensor->id, low, high);
+
+	tsadc->set_alarm_temp(tsadc->table,
+			      sensor->id, thermal->regs, high);
+
+	return 0;
+}
+
 static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
 {
 	struct rockchip_thermal_sensor *sensor = _sensor;
@@ -843,6 +881,7 @@ static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
 
 static const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = {
 	.get_temp = rockchip_thermal_get_temp,
+	.set_trips = rockchip_thermal_set_trips,
 };
 
 static int rockchip_configure_from_dt(struct device *dev,
-- 
1.9.1



From wxt at rock-chips.com  Tue May 24 21:27:04 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 25 May 2016 12:27:04 +0800
Subject: [PATCH] ARM64: dts: rockchip: add thermal zone node for rk3399 SoCs
Message-ID: <1464150424-27809-1-git-send-email-wxt@rock-chips.com>

This adds thermal zone node to rk3399 dtsi, rk3399 thermal data is
including the cpu and gpu sensor zone node.
At the moment, remove the rk3368 thermal data from rk399 dtsi.

The thermal zone node is the node containing all the required info
for describing a thermal zone, including its cooling device bindings.
The thermal zone node must contain, apart from its own properties, one
sub-node containing trip nodes and one sub-node containing all the zone
cooling maps.

The following is the parameter is introduced:
* polling-delay:
The maximum number of milliseconds to wait between polls

* polling-delay-passive:
The maximum number of milliseconds to wait between polls when performing
passive cooling.

* trips:
A sub-node which is a container of only trip point nodes required to
describe the thermal zone.

* cooling-maps:
A sub-node which is a container of only cooling device map nodes, used to
describe the relation between trips and cooling devices.

* cooling-device:
A phandle of a cooling device with its specifier, referring to which
cooling device is used in this cooling specifier binding. In the cooling
specifier, the first cell is the minimum cooling state and the second cell
is the maximum cooling state used in this map.

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

 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 100 +++++++++++++++++++++++++++++++
 1 file changed, 100 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 46f325a..cc4ca2a 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -45,6 +45,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
 	compatible = "rockchip,rk3399";
@@ -389,6 +390,95 @@
 		status = "disabled";
 	};
 
+	thermal-zones {
+		cpu-thermal: cpu {
+			polling-delay-passive = <100>; /* milliseconds */
+			polling-delay = <1000>; /* milliseconds */
+
+			thermal-sensors = <&tsadc 0>;
+
+			trips {
+				cpu_alert0: cpu_alert0 {
+					temperature = <70000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				cpu_alert1: cpu_alert1 {
+					temperature = <75000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				cpu_crit: cpu_crit {
+					temperature = <95000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert0>;
+					cooling-device =
+						<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+				map1 {
+					trip = <&cpu_alert1>;
+					cooling-device =
+						<&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+						<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+
+		gpu-thermal: gpu {
+			polling-delay-passive = <100>; /* milliseconds */
+			polling-delay = <1000>; /* milliseconds */
+
+			thermal-sensors = <&tsadc 1>;
+
+			trips {
+				gpu_alert0: gpu_alert0 {
+					temperature = <75000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				gpu_crit: gpu_crit {
+					temperature = <95000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&gpu_alert0>;
+					cooling-device =
+						<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+	};
+
+	tsadc: tsadc at ff260000 {
+		compatible = "rockchip,rk3399-tsadc";
+		reg = <0x0 0xff260000 0x0 0x100>;
+		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+		rockchip,grf = <&grf>;
+		clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
+		clock-names = "tsadc", "apb_pclk";
+		assigned-clocks = <&cru SCLK_TSADC>;
+		assigned-clock-rates = <750000>;
+		resets = <&cru SRST_TSADC>;
+		reset-names = "tsadc-apb";
+		pinctrl-names = "init", "default", "sleep";
+		pinctrl-0 = <&otp_gpio>;
+		pinctrl-1 = <&otp_out>;
+		pinctrl-2 = <&otp_gpio>;
+		#thermal-sensor-cells = <1>;
+		rockchip,hw-tshut-temp = <95000>;
+		status = "disabled";
+	};
+
 	pmugrf: syscon at ff320000 {
 		compatible = "rockchip,rk3399-pmugrf", "syscon";
 		reg = <0x0 0xff320000 0x0 0x1000>;
@@ -881,6 +971,16 @@
 			};
 		};
 
+		tsadc {
+			otp_gpio: otp-gpio {
+				rockchip,pins = <1 6 RK_FUNC_GPIO &pcfg_pull_none>;
+			};
+
+			otp_out: otp-out {
+				rockchip,pins = <1 6 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
 		uart0 {
 			uart0_xfer: uart0-xfer {
 				rockchip,pins =
-- 
1.9.1



From dirk.behme at de.bosch.com  Tue May 24 22:10:26 2016
From: dirk.behme at de.bosch.com (Dirk Behme)
Date: Wed, 25 May 2016 07:10:26 +0200
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <20160525004825.GC7292@verge.net.au>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
 <20160525004825.GC7292@verge.net.au>
Message-ID: <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>

Hi Simon,

On 25.05.2016 02:48, Simon Horman wrote:
> Hi Dirk,
>
> On Tue, May 24, 2016 at 07:30:17AM +0200, Dirk Behme wrote:
>> Hi Simon,
>
> [...]
>
>> With Renesas R-Car3 we will get a whole family of SoCs. I.e. different
>> computing power (e.g. different number of Cores) with more or less similar
>> peripherals.
>>
>> I would think that we want to reflect this in the device tree, too.
>> Therefore I think what we want is a hierarchy of device trees. Similar
>> what's done with other SoC families (compare e.g. i.MX6).
>>
>> E.g. we want an initial rcar3.dtsi, which contains all common parts of all
>> R-Car3 SoCs. E.g. one CA57 core, the SCIF where its common etc.
>>
>> Then you will have the r8a779x.dtsi which includes the rcar3.dtsi and
>> extends it for SoC specific parts. Which then will be included by the board
>> device trees, as already done, now.
>>
>> Or in other words: As soon as you have similar parts in the r8a779x.dtsi's,
>> it's time to think about moving the parts one hierarchy level up into the
>> rcar3.dtsi. Else you will end up in a maintenance hell once you have to
>> change/fix anything.
>
> Thanks for raising this issue.
>
> I agree entirely that we should work towards a situation where maintenance
> is as easy as it can be. However, due to the per-SoC binding scheme that
> we are using for IP related to Renesas SoCs I suspect that very few DT nodes
> can be shared between SoCs verbatim.


Could you kindly share an example for this? Looking into the H3 and the 
M3-W manual, it looks to me that ~90% (?) of the peripherals are the same.


> Probably some sort of scheme can be cooked up using preprocessor macros.
> And probably there are other ways to resolve this problem. But I would
> prefer if we worked towards resolving this maintenance problem in parallel
> with rather than as a dependency of merging r8a7796 support into mainline.


I'd propose to do it correct from the beginning.

Doing it later would either be more work or forgotten, and never be 
done, then.

For a starting point, I'd propose to put the r8a7795.dtsi and 
r8a7796.dtsi into a graphical diff tool and move all common parts to a 
rcar3.dtsi (I'd be happy to discuss the name, though)

Best regards

Dirk


From yamada.masahiro at socionext.com  Tue May 24 22:58:52 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Wed, 25 May 2016 14:58:52 +0900
Subject: [PATCH] pinctrl: digicolor: add missing platform_set_drvdata() call
Message-ID: <1464155932-25344-1-git-send-email-yamada.masahiro@socionext.com>

gc_pinctrl_remove() calls platform_get_drvdata(), but I see neither
platform_set_drvdata() nor dev_set_drvdata() anywhere in this driver.

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

 drivers/pinctrl/pinctrl-digicolor.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-digicolor.c b/drivers/pinctrl/pinctrl-digicolor.c
index 30ee564..c8073d4 100644
--- a/drivers/pinctrl/pinctrl-digicolor.c
+++ b/drivers/pinctrl/pinctrl-digicolor.c
@@ -332,6 +332,8 @@ static int dc_pinctrl_probe(struct platform_device *pdev)
 		return PTR_ERR(pmap->pctl);
 	}
 
+	platform_set_drvdata(pdev, pmap);
+
 	return dc_gpiochip_add(pmap, pdev->dev.of_node);
 }
 
-- 
1.9.1



From alim.akhtar at samsung.com  Tue May 24 23:04:04 2016
From: alim.akhtar at samsung.com (Alim Akhtar)
Date: Wed, 25 May 2016 11:34:04 +0530
Subject: [PATCH] clk: samsung: exynos7: Don't gate CMU_{CCORE,
 FSYS0} blocks clock
In-Reply-To: <5711180A.8030809@samsung.com>
References: <1460608972-13878-1-git-send-email-alim.akhtar@samsung.com>
 <570F4BE0.1010102@samsung.com> <5710E082.2050303@samsung.com>
 <5711180A.8030809@samsung.com>
Message-ID: <57454054.1010001@samsung.com>

Hi Sylwester,

On 04/15/2016 10:04 PM, Sylwester Nawrocki wrote:
> On 04/15/2016 02:37 PM, Alim Akhtar wrote:
>> On 04/14/2016 01:20 PM, Krzysztof Kozlowski wrote:
>>>> On 04/14/2016 06:42 AM, Alim Akhtar wrote:
>>>>>> This patch adds CLK_IS_CRITICAL flag to ACLK_CCORE_133 and ACLK_FSYS0_200
>>>>>> clocks. These clocks are critical for accessing CMU_CCORE and CMU_FSYS0
>>>>>> blocks registers. Let these clocks to be enabled all the time.
>>>>>>
>>>>>> Signed-off-by: Alim Akhtar <alim.akhtar at samsung.com>
>>>>>> ---
>>>>>>    drivers/clk/samsung/clk-exynos7.c |    5 +++--
>>>>>>    1 file changed, 3 insertions(+), 2 deletions(-)
>>>>
>>>> Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
>>>>
>> Thanks Krzysztof,
>> Sylwester, do you have any concern here?
>
> I'm fine with the patch, if it fixes all the issues for you.
> I will apply it and will likely send it upstream after v4.7-rc1 release.
>
Looks like this patch is not available on your tree.


From panand at redhat.com  Tue May 24 23:16:08 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 25 May 2016 11:46:08 +0530
Subject: [PATCH kexec-tools 01/32] kdump: mmap() and munmap() only work on
 page-aligned quantites
In-Reply-To: <E1axXS0-0004gz-5a@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXS0-0004gz-5a@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GupQcopOR7Qn5Nk0kNvYT_p0AWTzp+vJe87b+BsQTwr1CQ@mail.gmail.com>

On Tue, May 3, 2016 at 3:51 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> The man page for mmap() and munmap() says that mmap() and munmap()
> only works for page-aligned addresses, sizes and offsets.  Arrange
> to give these interfaces what they want.
>

If I read correctly, it talks only offsets to be page aligned.

> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Anyway, changes looks good to me.
Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kdump/kdump.c | 19 ++++++++++++++++---
>  1 file changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/kdump/kdump.c b/kdump/kdump.c
> index 821ee7c..3247a54 100644
> --- a/kdump/kdump.c
> +++ b/kdump/kdump.c
> @@ -25,22 +25,35 @@
>  #define MAP_WINDOW_SIZE (64*1024*1024)
>  #define DEV_MEM "/dev/mem"
>
> +#define ALIGN_MASK(x,y) (((x) + (y)) & ~(y))
> +#define ALIGN(x,y)     ALIGN_MASK(x, (y) - 1)
> +
>  static void *map_addr(int fd, unsigned long size, off_t offset)
>  {
> +       unsigned long page_size = getpagesize();
> +       unsigned long map_offset = offset & (page_size - 1);
> +       size_t len = ALIGN(size + map_offset, page_size);
>         void *result;
> -       result = mmap(0, size, PROT_READ, MAP_SHARED, fd, offset);
> +
> +       result = mmap(0, len, PROT_READ, MAP_SHARED, fd, offset - map_offset);
>         if (result == MAP_FAILED) {
>                 fprintf(stderr, "Cannot mmap " DEV_MEM " offset: %llu size: %lu: %s\n",
>                         (unsigned long long)offset, size, strerror(errno));
>                 exit(5);
>         }
> -       return result;
> +       return result + map_offset;
>  }
>
>  static void unmap_addr(void *addr, unsigned long size)
>  {
> +       unsigned long page_size = getpagesize();
> +       unsigned long map_offset = (uintptr_t)addr & (page_size - 1);
> +       size_t len = ALIGN(size + map_offset, page_size);
>         int ret;
> -       ret = munmap(addr, size);
> +
> +       addr -= map_offset;
> +
> +       ret = munmap(addr, len);
>         if (ret < 0) {
>                 fprintf(stderr, "munmap failed: %s\n",
>                         strerror(errno));
> --
> 1.9.1
>


From panand at redhat.com  Tue May 24 23:16:26 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 25 May 2016 11:46:26 +0530
Subject: [PATCH kexec-tools 02/32] kdump: fix multiple program header
 entries
In-Reply-To: <E1axXS5-0004h5-Cb@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXS5-0004h5-Cb@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_Guq7=qKeK+P_yG_6H7WYwtfEjMkqPD+_wP8h9W425jYTmQ@mail.gmail.com>

On Tue, May 3, 2016 at 3:51 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> generate_new_headers() forgot to increment the program header pointer
> after adding each program header from the kexec template. Fix it to
> increment it correctly.
>
> Without this, the program headers contain only the last entry, which
> means we will be missing most of the kernel image in the dump.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kdump/kdump.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/kdump/kdump.c b/kdump/kdump.c
> index 3247a54..99a1789 100644
> --- a/kdump/kdump.c
> +++ b/kdump/kdump.c
> @@ -192,6 +192,7 @@ static void *generate_new_headers(
>                 }
>                 memcpy(nphdr, &phdr[i], sizeof(*nphdr));
>                 nphdr->p_offset = offset;
> +               nphdr++;
>                 offset += phdr[i].p_filesz;
>         }
>
> --
> 1.9.1
>


From panand at redhat.com  Tue May 24 23:16:45 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 25 May 2016 11:46:45 +0530
Subject: [PATCH kexec-tools 03/32] kdump: actually write out the memory
In-Reply-To: <E1axXSA-0004hB-Ix@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSA-0004hB-Ix@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GuqS=z-v=r_1MOn4PgNf-Dzz=RQp=cJ_Ysc7xB8gg7mmmA@mail.gmail.com>

On Tue, May 3, 2016 at 3:51 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Actually write out the memory rather than writing the notes a second
> time.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kdump/kdump.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kdump/kdump.c b/kdump/kdump.c
> index 99a1789..1f5b984 100644
> --- a/kdump/kdump.c
> +++ b/kdump/kdump.c
> @@ -300,7 +300,7 @@ int main(int argc, char **argv)
>         for(i = 0; i < ehdr->e_phnum; i++) {
>                 unsigned long long offset, size;
>                 size_t wsize;
> -               if (phdr[i].p_type != PT_NOTE) {
> +               if (phdr[i].p_type == PT_NOTE) {
>                         continue;
>                 }
>                 offset = phdr[i].p_offset;
> --
> 1.9.1
>


From panand at redhat.com  Tue May 24 23:17:33 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 25 May 2016 11:47:33 +0530
Subject: [PATCH kexec-tools 04/32] kdump: fix kdump mapping
In-Reply-To: <E1axXSF-0004hH-Oo@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSF-0004hH-Oo@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GurQ44ybkxaYJJQeGgnuw=3tKOk7xyB6FTAursMLuZGrJg@mail.gmail.com>

On Tue, May 3, 2016 at 3:51 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> When kdump tries to map the program header, it fails to take account
> of ehdr->e_phoff being an offset from the start of the ELF "file",
> which causes:
>
> Cannot mmap /dev/mem offset: 64 size: 392: Invalid argument
>
> Ensure that we take account of the start address when mapping this.
>
> This fix has been extracted from a larger patch by Vitaly Andrianov
> adding support for Keystone 2.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>
> ---
>  kdump/kdump.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/kdump/kdump.c b/kdump/kdump.c
> index 1f5b984..34d2149 100644
> --- a/kdump/kdump.c
> +++ b/kdump/kdump.c
> @@ -284,7 +284,8 @@ int main(int argc, char **argv)
>         }
>
>         /* Get the program header */
> -       phdr = map_addr(fd, sizeof(*phdr)*(ehdr->e_phnum), ehdr->e_phoff);
> +       phdr = map_addr(fd, sizeof(*phdr)*(ehdr->e_phnum),
> +                       start_addr + ehdr->e_phoff);

This is fine. But at the same time should n't we also fix the offset
for mmap of memory segments?  For memory segments, offset is
phdr[i].p_offset, and I do not see generate_new_headers() taking care
of start_addr.

>
>         /* Collect up the notes */
>         note_bytes = 0;
> --
> 1.9.1
>

~Pratyush


From panand at redhat.com  Tue May 24 23:21:47 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 25 May 2016 11:51:47 +0530
Subject: [PATCH kexec-tools 06/32] kdump: print mmap() offset in hex
In-Reply-To: <E1axXSQ-0004hT-54@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSQ-0004hT-54@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GurzXYbK5Nx7LT9TdXGbHF3ufGEfYMW68Y-9vSrefqBhjA@mail.gmail.com>

On Tue, May 3, 2016 at 3:51 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> When mmap() fails, printing a large decimal number is mostly
> meaningless - it's not obvious what it means.  Printing a hex number
> is more obvious, because we can see whether it's over 32-bit, or not
> page aligned.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Looks good to me.
Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kdump/kdump.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kdump/kdump.c b/kdump/kdump.c
> index 34d2149..f34727f 100644
> --- a/kdump/kdump.c
> +++ b/kdump/kdump.c
> @@ -37,7 +37,7 @@ static void *map_addr(int fd, unsigned long size, off_t offset)
>
>         result = mmap(0, len, PROT_READ, MAP_SHARED, fd, offset - map_offset);
>         if (result == MAP_FAILED) {
> -               fprintf(stderr, "Cannot mmap " DEV_MEM " offset: %llu size: %lu: %s\n",
> +               fprintf(stderr, "Cannot mmap " DEV_MEM " offset: %#llx size: %lu: %s\n",
>                         (unsigned long long)offset, size, strerror(errno));
>                 exit(5);
>         }
> --
> 1.9.1
>


From sudipm.mukherjee at gmail.com  Tue May 24 19:00:09 2016
From: sudipm.mukherjee at gmail.com (Sudip Mukherjee)
Date: Wed, 25 May 2016 07:30:09 +0530
Subject: [PATCH] hwrng: stm32 - fix build warning
In-Reply-To: <CALszF6BAFgoccC6fmkdnwQxwHmQ35oLcor6v9yOLyVeXrt-KGA@mail.gmail.com>
References: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>	<12548318.auB4PSA3KC@wuerfel>	<CALszF6BPPA=tezMLhmdC4YFwmH1tGhDxCNDZNwGp1cTDWP7Fmg@mail.gmail.com>	<6044541.yeLQbYg2Jv@wuerfel>
 <CALszF6BAFgoccC6fmkdnwQxwHmQ35oLcor6v9yOLyVeXrt-KGA@mail.gmail.com>
Message-ID: <57450729.3000609@gmail.com>

On Tuesday 24 May 2016 02:50 PM, Maxime Coquelin wrote:
> 2016-05-24 10:58 GMT+02:00 Arnd Bergmann <arnd at arndb.de>:
>> On Tuesday, May 24, 2016 10:50:17 AM CEST Maxime Coquelin wrote:
>>> diff --git a/drivers/char/hw_random/stm32-rng.c
>>> b/drivers/char/hw_random/stm32-rng.c
>>> index 92a810648bd0..2a0fc90e4dc3 100644
>>> --- a/drivers/char/hw_random/stm32-rng.c
>>> +++ b/drivers/char/hw_random/stm32-rng.c
>>> @@ -68,6 +68,10 @@ static int stm32_rng_read(struct hwrng *rng, void
>>> *data, size_t max, bool wait)
>>>                          } while (!sr && --timeout);
>>>                  }
>>>
>>> +               if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
>>> +                               "bad RNG status - %x\n", sr))
>>> +                       writel_relaxed(0, priv->base + RNG_SR);
>>> +
>>>                  /* If error detected or data not ready... */
>>>                  if (sr != RNG_SR_DRDY)
>>>                          break;
>>> @@ -79,10 +83,6 @@ static int stm32_rng_read(struct hwrng *rng, void
>>> *data, size_t max, bool wait)
>>>                  max -= sizeof(u32);
>>>          }
>>>
>>> -       if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
>>> -                     "bad RNG status - %x\n", sr))
>>> -               writel_relaxed(0, priv->base + RNG_SR);
>>> -
>>>          pm_runtime_mark_last_busy((struct device *) priv->rng.priv);
>>>          pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv);
>>>
>>> Thanks,
>>>
>>
>> Yes, that looks good to me.
>
> Thanks!
> Sudip, do you want to send the patch, or I manage to do it?

Maybe you should send it, i have not done anything in reaching its final 
form.

Regards
Sudip


From panand at redhat.com  Tue May 24 23:31:32 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 25 May 2016 12:01:32 +0530
Subject: [PATCH kexec-tools 09/32] kexec: phys_to_virt() must take
 unsigned long long
In-Reply-To: <E1axXSf-0004hl-PC@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSf-0004hl-PC@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_Guqx-TaVk7_ORbFNxB3HhxvByeu5obFLXPg9UR-axDoyBA@mail.gmail.com>

On Tue, May 3, 2016 at 3:51 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> crashdump-elf.c passes unsigned long long addresses into phys_to_virt()
> so make phys_to_virt() accept such addresses without truncating them.
> This is important for ARM LPAE systems.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/phys_to_virt.c | 2 +-
>  kexec/crashdump.h             | 2 +-
>  kexec/phys_to_virt.c          | 2 +-
>  3 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/kexec/arch/arm/phys_to_virt.c b/kexec/arch/arm/phys_to_virt.c
> index bcced52..c2fe2ea 100644
> --- a/kexec/arch/arm/phys_to_virt.c
> +++ b/kexec/arch/arm/phys_to_virt.c
> @@ -14,7 +14,7 @@
>   * http://lists.arm.linux.org.uk/lurker/message/20010723.185051.94ce743c.en.html
>   */
>  unsigned long
> -phys_to_virt(struct crash_elf_info *elf_info, unsigned long paddr)
> +phys_to_virt(struct crash_elf_info *elf_info, unsigned long long paddr)
>  {
>         return paddr + elf_info->page_offset - phys_offset;
>  }
> diff --git a/kexec/crashdump.h b/kexec/crashdump.h
> index 95f1f0c..96219a8 100644
> --- a/kexec/crashdump.h
> +++ b/kexec/crashdump.h
> @@ -55,7 +55,7 @@ int crash_create_elf64_headers(struct kexec_info *info,
>  unsigned long crash_architecture(struct crash_elf_info *elf_info);
>
>  unsigned long phys_to_virt(struct crash_elf_info *elf_info,
> -                          unsigned long paddr);
> +                          unsigned long long paddr);
>
>  unsigned long xen_architecture(struct crash_elf_info *elf_info);
>  int xen_get_nr_phys_cpus(void);
> diff --git a/kexec/phys_to_virt.c b/kexec/phys_to_virt.c
> index 91b6d01..5e8c4e3 100644
> --- a/kexec/phys_to_virt.c
> +++ b/kexec/phys_to_virt.c
> @@ -10,7 +10,7 @@
>   * their own implementation.
>   */
>  unsigned long
> -phys_to_virt(struct crash_elf_info *elf_info, unsigned long paddr)
> +phys_to_virt(struct crash_elf_info *elf_info, unsigned long long paddr)
>  {
>         return paddr + elf_info->page_offset;
>  }
> --
> 1.9.1
>


From gabriele.paoloni at huawei.com  Tue May 24 23:31:29 2016
From: gabriele.paoloni at huawei.com (Gabriele Paoloni)
Date: Wed, 25 May 2016 06:31:29 +0000
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <20160524172423.GA15855@red-moon>
References: <57331290.7070104@semihalf.com>
 <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>
 <20160523233918.GA32555@localhost> <20160524172423.GA15855@red-moon>
Message-ID: <EE11001F9E5DDD47B7634E2F8A612F2E1EDB59F6@lhreml503-mbs>

Hi Lorenzo

> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
> Sent: 24 May 2016 18:24
> To: Bjorn Helgaas
> Cc: Gabriele Paoloni; Ard Biesheuvel; Jon Masters; Tomasz Nowicki;
> arnd at arndb.de; will.deacon at arm.com; catalin.marinas at arm.com;
> rafael at kernel.org; hanjun.guo at linaro.org; okaya at codeaurora.org;
> jchandra at broadcom.com; linaro-acpi at lists.linaro.org; linux-
> pci at vger.kernel.org; dhdang at apm.com; Liviu.Dudau at arm.com;
> ddaney at caviumnetworks.com; jeremy.linton at arm.com; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org;
> robert.richter at caviumnetworks.com; Suravee.Suthikulpanit at amd.com;
> msalter at redhat.com; Wangyijing; mw at semihalf.com;
> andrea.gallo at linaro.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI host
> controller
> 
> Hi Bjorn,
> 
> On Mon, May 23, 2016 at 06:39:18PM -0500, Bjorn Helgaas wrote:
> 
> [...]
> 
> > On Mon, May 23, 2016 at 03:16:01PM +0000, Gabriele Paoloni wrote:
> > I don't think of ECAM support itself as a "driver".  It's just a
> > service available to drivers, similar to OF resource parsing.
> >
> > Per PCI Firmware r3.2, sec 4.1.5, "PNP0A03" means a PCI/PCI-X/PCIe
> > host bridge.  "PNP0A08" means a PCI-X Mode 2 or PCIe bridge that
> > supports extended config space.  It doesn't specify how we access
> that
> > config space, so I think hardware with non-standard ECAM should still
> > have PNP0A03 and PNP0A08 in _CID or _HID.
> >
> > "ECAM" as used in the specs (PCIe r3.0, sec 7.2.2, and PCI Firmware
> > r3.2, sec 4.1) means:
> >
> >   (a) a memory-mapped model for config space access, and
> >   (b) a specific mapping of address bits to bus/device/function/
> >       register
> >
> > MCFG and _CBA assume both (a) and (b), so I think a device with
> > non-standard ECAM mappings should not be described in MCFG or _CBA.
> >
> > If a bridge has ECAM with non-standard mappings, I think either a
> > vendor-specific _HID or a device-specific method, e.g., _DSM, could
> > communicate that.
> >
> > Jon, I agree that we should avoid describing non-standardized
> hardware
> > in Linux-specific ways.  Is there a mechanism in use already?  How
> > does Windows handle this?  DMI is a poor long-term solution because
> it
> > requires ongoing maintenance for new platforms, but I think it's OK
> > for getting started with platforms already shipping.
> >
> > A _DSM has the advantage that once it is defined and supported, OEMs
> > can ship new platforms without requiring a new quirk or a new _HID to
> > be added to a driver.
> >
> > There would still be the problem of config access before the
> namespace
> > is available, i.e., the MCFG use case.  I don't know how important
> > that is.  Defining an MCFG extension seems like the most obvious
> > solution.
> 
> Your summary above is a perfect representation of the situation.
> 
> We had an opportunity to sync-up on the current status of ACPI PCI
> for ARM64 (and talked about a way forward for this series, which
> includes quirks handling), let me summarize it here for everyone
> involved so that we can agree on a way forward.
> 
> 1) ACPI PCI support for PNP0A03/PNP0A08 host bridges on top of MCFG
>    ECAM for config space is basically ready (Tomasz and JC addressed
>    Rafael's concerns in relation to ARM64 specific code, and managed
>    to find a way to allocate domain numbers in preparation for Arnd
>    pci_create_root_bus() clean-up, v8 to be posted shortly and should
>    be final). This provides support for de-facto ACPI/PCI ECAM base
>    standard for ARM64 (with a clean-split between generic code and
> ARM64
>    bits, where ARM64, like X86 and IA64, manages in arch code IO space
> and
>    PCI resources, to be further consolidated in the near future).
>    I do not think anyone can complain about the generality of what we
>    achieved, for systems that are PCI standard (yes, PCI STANDARD) this
>    would just be sufficient.
> 2) In a real world (1) is not enough. Some ARM64 platforms, not
> entirely
>    ECAM compliant, already shipped with the corresponding firmware that
>    we can't update. HW has ECAM quirks and to work around it in the
> kernel
>    we put forward many solutions to the problem, it is time we found a
>    solution (when, of course, (1) is completed and upstream).
>    Using the MCFG table OEMID matching floated around in this thread
>    would work fine for most of the platforms (and cross-OS) that have
>    shipped with HW ECAM quirks, so I think that's the starting point
> for
>    our solution and that's how we can sort this out, _today_.
> 
>    The solution is a trivial look-up table:
>    MCFG OEMID <-> PCI config space ops
> 
> 3) (2) does not just work on some platforms (and we can't predict the
>    future either - actually I can, it is three letters, ECAM), simply
>    because MCFG OEMID matching does not provide a way to attach further
>    data to the MCFG (eg if config space for, say, bus 0 domain 0, is
> not
>    ECAM compliant, the config region can't be handled and must not be
>    handled through a corresponding MCFG region.
>    That's the problem Gabriele is facing and wants to solve through
>    something like:
> 
>    https://lkml.org/lkml/2016/3/9/91
> 
>    in the respective ACPI tables-bindings. It may be an idea worth
>    pursuing, it does not solve (2) simply because that FW has shipped,
>    we can't patch it any longer.
> 
> Hence to finally support ACPI PCI on ARM64 I suggest we carry out the
> following steps, in order:
> 
> - Let's complete/merge (1), that's fundamental to this whole thread
> - On top of (1) we apply a quirking mechanism based on (2) that allows
>   us to boot mainline with boxes shipping today with no FW update
> required.
> - We devise a way to handle quirks that is more generic than (2) so
> that
>   can we can accomodate further platforms that can't rely on (2) but
>   have more leeway in terms of FW updates.
> 
> I hope that's a reasonable plan, Tomasz's v8 series coming to kick it
> off.

Thanks for summarizing.

100% agree on the summary and next steps.

Cheers

Gab


> 
> Thank you,
> Lorenzo


From sudipm.mukherjee at gmail.com  Tue May 24 19:05:17 2016
From: sudipm.mukherjee at gmail.com (Sudip Mukherjee)
Date: Wed, 25 May 2016 07:35:17 +0530
Subject: [PATCH] hwrng: stm32 - fix build warning
In-Reply-To: <6297051.TAxtzW5OIB@wuerfel>
References: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>
 <6297051.TAxtzW5OIB@wuerfel>
Message-ID: <5745085D.6000104@gmail.com>

On Tuesday 24 May 2016 02:05 AM, Arnd Bergmann wrote:
> On Monday, May 23, 2016 6:14:08 PM CEST Sudip Mukherjee wrote:
>> We have been getting build warning about:
>> drivers/char/hw_random/stm32-rng.c: In function 'stm32_rng_read':
>> drivers/char/hw_random/stm32-rng.c:82:19: warning: 'sr' may be used
>> 					uninitialized in this function
>>
>> On checking the code it turns out that sr can never be used
>> uninitialized as sr is getting initialized in the while loop and while
>> loop will always execute as the minimum value of max can be 32.
>> So just initialize sr to 0 while declaring it to silence the compiler.
>>
>> Signed-off-by: Sudip Mukherjee <sudip.mukherjee at codethink.co.uk>
>> ---
>
> I notice that you are using a really old compiler. While this warning
> seems to be valid in the sense that the compiler should figure out that
> the variable might be used uninitialized, please update your toolchain
> before reporting other such problems, as gcc-4.6 had a lot more false
> positives that newer ones (5.x or 6.x) have.

yes, i need to upgrade gcc in my travis bot. But in my local system I am 
having gcc-4.8.4 and there also I am having this error and i am sure 
4.8.4 is still being used by many people.

Regards
Sudip


From baruch at tkos.co.il  Tue May 24 23:48:32 2016
From: baruch at tkos.co.il (Baruch Siach)
Date: Wed, 25 May 2016 09:48:32 +0300
Subject: [PATCH] pinctrl: digicolor: add missing platform_set_drvdata()
 call
In-Reply-To: <1464155932-25344-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464155932-25344-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <20160525064832.GG2178@tarshish>

Hi Masahiro Yamada,

On Wed, May 25, 2016 at 02:58:52PM +0900, Masahiro Yamada wrote:
> gc_pinctrl_remove() calls platform_get_drvdata(), but I see neither
> platform_set_drvdata() nor dev_set_drvdata() anywhere in this driver.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Acked-by: Baruch Siach <baruch at tkos.co.il>

Thanks,
baruch

>  drivers/pinctrl/pinctrl-digicolor.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/pinctrl/pinctrl-digicolor.c b/drivers/pinctrl/pinctrl-digicolor.c
> index 30ee564..c8073d4 100644
> --- a/drivers/pinctrl/pinctrl-digicolor.c
> +++ b/drivers/pinctrl/pinctrl-digicolor.c
> @@ -332,6 +332,8 @@ static int dc_pinctrl_probe(struct platform_device *pdev)
>  		return PTR_ERR(pmap->pctl);
>  	}
>  
> +	platform_set_drvdata(pdev, pmap);
> +
>  	return dc_gpiochip_add(pmap, pdev->dev.of_node);
>  }

-- 
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -


From m.szyprowski at samsung.com  Tue May 24 23:51:05 2016
From: m.szyprowski at samsung.com (Marek Szyprowski)
Date: Wed, 25 May 2016 08:51:05 +0200
Subject: [PATCH 0/2] ARM: dts: Fix imprecise external abort error when
 accessing Exynos MFC
In-Reply-To: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
References: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
Message-ID: <6479e0c0-97fb-ca3b-1337-6ed11410d94f@samsung.com>

Hello,


On 2016-05-24 19:41, Javier Martinez Canillas wrote:
> This series fixes an imprecise external abort error when accessing the
> Exynos MFC registers due the power domain configuration requiring the
> aclk333 clock to be enabled during a domain switch.
>
> There isn't a dependency between the clock and Linux Samsung SoC trees
> because the CLK_ACLK333 clock ID is already defined so the patches can
> be picked indepedently by the relevant subsystem maintainers.

Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>

I'm really curious what kind of async-bridge is there, but this patch
really fixes the problem with mfc power domain.

> Best regards,
> Javier
>
>
> Javier Martinez Canillas (2):
>    clk: exynos5420: Set ID for aclk333 gate clock
>    ARM: dts: Add async-bridge clock to MFC power domain for Exynos5420
>
>   arch/arm/boot/dts/exynos5420.dtsi    | 5 +++--
>   drivers/clk/samsung/clk-exynos5420.c | 2 +-
>   2 files changed, 4 insertions(+), 3 deletions(-)
>

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland



From geert at linux-m68k.org  Wed May 25 00:02:17 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Wed, 25 May 2016 09:02:17 +0200
Subject: [PATCH] rm64: dts: r8a7795: Drop 0x from unit address of gic
In-Reply-To: <1464138700-12219-1-git-send-email-horms+renesas@verge.net.au>
References: <1464138700-12219-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <CAMuHMdVUSmRtFHFA1E9_sqFUEo9KER2CSW4qtjcsY0LWs6tfeA@mail.gmail.com>

On Wed, May 25, 2016 at 3:11 AM, Simon Horman
<horms+renesas at verge.net.au> wrote:
> Drop 0x from unit address of gic as this is the desired form for
> a unit address.
>
> Signed-off-by: Simon Horman <horms+renesas at verge.net.au>

If you increase the entropy of the universe even more by adding the missing
"a" prefix to the one-line summary, you can add my

Acked-by: Geert Uytterhoeven <geert+renesas at glider.be>

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 k.kozlowski at samsung.com  Wed May 25 00:11:08 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 25 May 2016 09:11:08 +0200
Subject: [PATCH 1/2] clk: exynos5420: Set ID for aclk333 gate clock
In-Reply-To: <1464111662-15336-2-git-send-email-javier@osg.samsung.com>
References: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
 <1464111662-15336-2-git-send-email-javier@osg.samsung.com>
Message-ID: <5745500C.1060309@samsung.com>

On 05/24/2016 07:41 PM, Javier Martinez Canillas wrote:
> The aclk333 clock needs to be ungated during the MFC power domain switch,
> so set the clock ID to allow the Exynos power domain logic to lookup this
> clock if is defined in the MFC PD device tree node.
> 
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
> ---
> 
>  drivers/clk/samsung/clk-exynos5420.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

Best regards,
Krzysztof



From dirk.behme at de.bosch.com  Wed May 25 00:32:15 2016
From: dirk.behme at de.bosch.com (Dirk Behme)
Date: Wed, 25 May 2016 09:32:15 +0200
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
 <20160525004825.GC7292@verge.net.au>
 <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>
Message-ID: <edee7345-280a-0d7c-7e5a-798215fbd2b9@de.bosch.com>

On 25.05.2016 07:10, Dirk Behme wrote:
> Hi Simon,
>
> On 25.05.2016 02:48, Simon Horman wrote:
>> Hi Dirk,
>>
>> On Tue, May 24, 2016 at 07:30:17AM +0200, Dirk Behme wrote:
>>> Hi Simon,
>>
>> [...]
>>
>>> With Renesas R-Car3 we will get a whole family of SoCs. I.e. different
>>> computing power (e.g. different number of Cores) with more or less
>>> similar
>>> peripherals.
>>>
>>> I would think that we want to reflect this in the device tree, too.
>>> Therefore I think what we want is a hierarchy of device trees. Similar
>>> what's done with other SoC families (compare e.g. i.MX6).
>>>
>>> E.g. we want an initial rcar3.dtsi, which contains all common parts
>>> of all
>>> R-Car3 SoCs. E.g. one CA57 core, the SCIF where its common etc.
>>>
>>> Then you will have the r8a779x.dtsi which includes the rcar3.dtsi and
>>> extends it for SoC specific parts. Which then will be included by the
>>> board
>>> device trees, as already done, now.
>>>
>>> Or in other words: As soon as you have similar parts in the
>>> r8a779x.dtsi's,
>>> it's time to think about moving the parts one hierarchy level up into
>>> the
>>> rcar3.dtsi. Else you will end up in a maintenance hell once you have to
>>> change/fix anything.
>>
>> Thanks for raising this issue.
>>
>> I agree entirely that we should work towards a situation where
>> maintenance
>> is as easy as it can be. However, due to the per-SoC binding scheme that
>> we are using for IP related to Renesas SoCs I suspect that very few DT
>> nodes
>> can be shared between SoCs verbatim.
>
>
> Could you kindly share an example for this? Looking into the H3 and the
> M3-W manual, it looks to me that ~90% (?) of the peripherals are the same.
>
>
>> Probably some sort of scheme can be cooked up using preprocessor macros.
>> And probably there are other ways to resolve this problem. But I would
>> prefer if we worked towards resolving this maintenance problem in
>> parallel
>> with rather than as a dependency of merging r8a7796 support into
>> mainline.
>
>
> I'd propose to do it correct from the beginning.
>
> Doing it later would either be more work or forgotten, and never be
> done, then.
>
> For a starting point, I'd propose to put the r8a7795.dtsi and
> r8a7796.dtsi into a graphical diff tool and move all common parts to a
> rcar3.dtsi (I'd be happy to discuss the name, though)


To give an example what I'm talking about kindly have a look to the 
attached (draft) patch.

Best regards

Dirk

P.S.: This also results in the question why we need similar 
r8a7795-cpg-mssr.h and r8a7796-cpg-mssr.h with just different "numbers" 
for the same clocks. Can't we use the same numbers on all SoCs, with 
just having wholes in the list where the clocks don't exist on a SoC? I 
haven't looked into the manual if these numbers are given by the 
hardware, though.

-------------- next part --------------
>From 08078bf12780176ab116fe5f39a378f5ee374ae3 Mon Sep 17 00:00:00 2001
From: Dirk Behme <dirk.behme at de.bosch.com>
Date: Wed, 25 May 2016 09:23:58 +0200
Subject: [PATCH] arm64: dts: Renesas R-Car3: Introduce common rcar3.dtsi

The R-Car3 SoC family will contain several similar SoCs, sharing
several peripherals.

Introduce a common rcar3.dtsi containing the common parts of all
R-Car3 family SoCs.

Signed-off-by: Dirk Behme <dirk.behme at de.bosch.com>
---
 arch/arm64/boot/dts/renesas/r8a7795.dtsi | 109 ++----------------------------
 arch/arm64/boot/dts/renesas/r8a7796.dtsi | 109 ++----------------------------
 arch/arm64/boot/dts/renesas/rcar3.dtsi   | 112 +++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+), 205 deletions(-)
 create mode 100644 arch/arm64/boot/dts/renesas/rcar3.dtsi

diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
index a7315eb..0737ed2 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
@@ -10,11 +10,10 @@
 
 #include <dt-bindings/clock/r8a7795-cpg-mssr.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "rcar3.dtsi"
 
 / {
 	compatible = "renesas,r8a7795";
-	#address-cells = <2>;
-	#size-cells = <2>;
 
 	aliases {
 		i2c0 = &i2c0;
@@ -26,23 +25,7 @@
 		i2c6 = &i2c6;
 	};
 
-	psci {
-		compatible = "arm,psci-0.2";
-		method = "smc";
-	};
-
 	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		a57_0: cpu at 0 {
-			compatible = "arm,cortex-a57", "arm,armv8";
-			reg = <0x0>;
-			device_type = "cpu";
-			next-level-cache = <&L2_CA57>;
-			enable-method = "psci";
-		};
-
 		a57_1: cpu at 1 {
 			compatible = "arm,cortex-a57","arm,armv8";
 			reg = <0x1>;
@@ -66,32 +49,12 @@
 		};
 	};
 
-	L2_CA57: cache-controller at 0 {
-		compatible = "cache";
-		cache-unified;
-		cache-level = <2>;
-	};
-
 	L2_CA53: cache-controller at 1 {
 		compatible = "cache";
 		cache-unified;
 		cache-level = <2>;
 	};
 
-	extal_clk: extal {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		/* This value must be overridden by the board */
-		clock-frequency = <0>;
-	};
-
-	extalr_clk: extalr {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		/* This value must be overridden by the board */
-		clock-frequency = <0>;
-	};
-
 	/*
 	 * The external audio clocks are configured as 0 Hz fixed frequency
 	 * clocks by default.
@@ -115,35 +78,7 @@
 		clock-frequency = <0>;
 	};
 
-	/* External SCIF clock - to be overridden by boards that provide it */
-	scif_clk: scif {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <0>;
-		status = "disabled";
-	};
-
 	soc {
-		compatible = "simple-bus";
-		interrupt-parent = <&gic>;
-
-		#address-cells = <2>;
-		#size-cells = <2>;
-		ranges;
-
-		gic: interrupt-controller at 0xf1010000 {
-			compatible = "arm,gic-400";
-			#interrupt-cells = <3>;
-			#address-cells = <0>;
-			interrupt-controller;
-			reg = <0x0 0xf1010000 0 0x1000>,
-			      <0x0 0xf1020000 0 0x2000>,
-			      <0x0 0xf1040000 0 0x20000>,
-			      <0x0 0xf1060000 0 0x2000>;
-			interrupts = <GIC_PPI 9
-					(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
-		};
-
 		gpio0: gpio at e6050000 {
 			compatible = "renesas,gpio-r8a7795",
 				     "renesas,gpio-rcar";
@@ -268,27 +203,6 @@
 					     <&a57_3>;
 		};
 
-		timer {
-			compatible = "arm,armv8-timer";
-			interrupts = <GIC_PPI 13
-					(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-				     <GIC_PPI 14
-					(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-				     <GIC_PPI 11
-					(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
-				     <GIC_PPI 10
-					(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
-		};
-
-		cpg: clock-controller at e6150000 {
-			compatible = "renesas,r8a7795-cpg-mssr";
-			reg = <0 0xe6150000 0 0x1000>;
-			clocks = <&extal_clk>, <&extalr_clk>;
-			clock-names = "extal", "extalr";
-			#clock-cells = <2>;
-			#power-domain-cells = <0>;
-		};
-
 		audma0: dma-controller at ec700000 {
 			compatible = "renesas,rcar-dmac";
 			reg = <0 0xec700000 0 0x10000>;
@@ -625,21 +539,6 @@
 			status = "disabled";
 		};
 
-		scif2: serial at e6e88000 {
-			compatible = "renesas,scif-r8a7795",
-				     "renesas,rcar-gen3-scif", "renesas,scif";
-			reg = <0 0xe6e88000 0 64>;
-			interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&cpg CPG_MOD 310>,
-				 <&cpg CPG_CORE R8A7795_CLK_S3D1>,
-				 <&scif_clk>;
-			clock-names = "fck", "brg_int", "scif_clk";
-			dmas = <&dmac1 0x13>, <&dmac1 0x12>;
-			dma-names = "tx", "rx";
-			power-domains = <&cpg>;
-			status = "disabled";
-		};
-
 		scif3: serial at e6c50000 {
 			compatible = "renesas,scif-r8a7795",
 				     "renesas,rcar-gen3-scif", "renesas,scif";
@@ -1120,3 +1019,9 @@
 		};
 	};
 };
+
+&scif2 {
+	clocks = <&cpg CPG_MOD 310>,
+		 <&cpg CPG_CORE R8A7795_CLK_S3D1>,
+		 <&scif_clk>;
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
index 178debf..3e480d9 100644
--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
@@ -10,111 +10,14 @@
 
 #include <dt-bindings/clock/r8a7796-cpg-mssr.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "rcar3.dtsi"
 
 / {
 	compatible = "renesas,r8a7796";
-	#address-cells = <2>;
-	#size-cells = <2>;
-
-	psci {
-		compatible = "arm,psci-0.2";
-		method = "smc";
-	};
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		/* 1 core only at this point */
-		a57_0: cpu at 0 {
-			compatible = "arm,cortex-a57", "arm,armv8";
-			reg = <0x0>;
-			device_type = "cpu";
-			next-level-cache = <&L2_CA57>;
-			enable-method = "psci";
-		};
-
-		L2_CA57: cache-controller at 0 {
-			compatible = "cache";
-			reg = <0>;
-			cache-unified;
-			cache-level = <2>;
-		};
-	};
-
-	extal_clk: extal {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		/* This value must be overridden by the board */
-		clock-frequency = <0>;
-	};
-
-	extalr_clk: extalr {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		/* This value must be overridden by the board */
-		clock-frequency = <0>;
-	};
-
-	/* External SCIF clock - to be overridden by boards that provide it */
-	scif_clk: scif {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <0>;
-	};
-
-	soc {
-		compatible = "simple-bus";
-		interrupt-parent = <&gic>;
-		#address-cells = <2>;
-		#size-cells = <2>;
-		ranges;
-
-		gic: interrupt-controller at f1010000 {
-			compatible = "arm,gic-400";
-			#interrupt-cells = <3>;
-			#address-cells = <0>;
-			interrupt-controller;
-			reg = <0x0 0xf1010000 0 0x1000>,
-			      <0x0 0xf1020000 0 0x20000>,
-			      <0x0 0xf1040000 0 0x20000>,
-			      <0x0 0xf1060000 0 0x20000>;
-			interrupts = <GIC_PPI 9
-					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
-		};
-
-		timer {
-			compatible = "arm,armv8-timer";
-			interrupts = <GIC_PPI 13
-					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
-				     <GIC_PPI 14
-					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
-				     <GIC_PPI 11
-					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
-				     <GIC_PPI 10
-					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
-		};
-
-		cpg: clock-controller at e6150000 {
-			compatible = "renesas,r8a7796-cpg-mssr";
-			reg = <0 0xe6150000 0 0x1000>;
-			clocks = <&extal_clk>, <&extalr_clk>;
-			clock-names = "extal", "extalr";
-			#clock-cells = <2>;
-			#power-domain-cells = <0>;
-		};
+};
 
-		scif2: serial at e6e88000 {
-			compatible = "renesas,scif-r8a7796",
-				     "renesas,rcar-gen3-scif", "renesas,scif";
-			reg = <0 0xe6e88000 0 64>;
-			interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&cpg CPG_MOD 310>,
-				 <&cpg CPG_CORE R8A7796_CLK_S3D1>,
-				 <&scif_clk>;
-			clock-names = "fck", "brg_int", "scif_clk";
-			power-domains = <&cpg>;
-			status = "disabled";
-		};
-	};
+&scif2 {
+	clocks = <&cpg CPG_MOD 310>,
+		 <&cpg CPG_CORE R8A7796_CLK_S3D1>,
+		 <&scif_clk>;
 };
diff --git a/arch/arm64/boot/dts/renesas/rcar3.dtsi b/arch/arm64/boot/dts/renesas/rcar3.dtsi
new file mode 100644
index 0000000..c02c8e4
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/rcar3.dtsi
@@ -0,0 +1,112 @@
+/*
+ * Device Tree Source for the R-Car3 SoC family
+ *
+ * Copyright (C) 2015-2016 Renesas Electronics Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		a57_0: cpu at 0 {
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x0>;
+			device_type = "cpu";
+			next-level-cache = <&L2_CA57>;
+			enable-method = "psci";
+		};
+	};
+
+	L2_CA57: cache-controller at 0 {
+		compatible = "cache";
+		cache-unified;
+		cache-level = <2>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	extal_clk: extal {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	extalr_clk: extalr {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	/* External SCIF clock - to be overridden by boards that provide it */
+	scif_clk: scif {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+		status = "disabled";
+	};
+
+	soc {
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gic: interrupt-controller at f1010000 {
+			compatible = "arm,gic-400";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0x0 0xf1010000 0 0x1000>,
+			      <0x0 0xf1020000 0 0x20000>,
+			      <0x0 0xf1040000 0 0x20000>,
+			      <0x0 0xf1060000 0 0x20000>;
+			interrupts = <GIC_PPI 9
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+		};
+
+		timer {
+			compatible = "arm,armv8-timer";
+			interrupts = <GIC_PPI 13
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 14
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 11
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 10
+					(GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
+		};
+
+		cpg: clock-controller at e6150000 {
+			compatible = "renesas,r8a7795-cpg-mssr", "renesas,r8a7796-cpg-mssr";
+			reg = <0 0xe6150000 0 0x1000>;
+			clocks = <&extal_clk>, <&extalr_clk>;
+			clock-names = "extal", "extalr";
+			#clock-cells = <2>;
+			#power-domain-cells = <0>;
+		};
+
+		scif2: serial at e6e88000 {
+			compatible = "renesas,scif-r8a7795", "renesas,scif-r8a7796",
+				     "renesas,rcar-gen3-scif", "renesas,scif";
+			reg = <0 0xe6e88000 0 64>;
+			interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			power-domains = <&cpg>;
+			status = "disabled";
+		};
+	};
+};
-- 
2.8.0


From dirk.behme at de.bosch.com  Wed May 25 00:38:23 2016
From: dirk.behme at de.bosch.com (Dirk Behme)
Date: Wed, 25 May 2016 09:38:23 +0200
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
Message-ID: <25947777-9871-ccc4-011b-0775c2b88d8b@de.bosch.com>

On 24.05.2016 03:54, Simon Horman wrote:
> Basic support for the Gen 3 R-Car M3-W SoC.
>
> Based on work for the r8a7795 and r8a7796 SoCs by
> Takeshi Kihara, Dirk Behme and Geert Uytterhoeven.
>
> Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
> Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
> ---
> v3
> * As suggested by Geert Uytterhoeven:
>   - Drop 0x from unit address of gic
> * As suggested by Khiem Nguyen:
>   - Use psci-0.2
> * Added Reviewed-by tag from Geert Uytterhoeven
>
> v2
> * As suggested by Geert Uytterhoeven:
>   - Move L2_CA57 node under cpus node and include reg property
>   - Omit status = "disabled" from scif_clk node
> ---
>  Documentation/devicetree/bindings/arm/shmobile.txt |   4 +
>  arch/arm64/Kconfig.platforms                       |   6 ++
>  arch/arm64/boot/dts/renesas/r8a7796.dtsi           | 120 +++++++++++++++++++++
>  3 files changed, 130 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/renesas/r8a7796.dtsi
>
> diff --git a/Documentation/devicetree/bindings/arm/shmobile.txt b/Documentation/devicetree/bindings/arm/shmobile.txt
> index 9cf67e48f222..d5ed554830d7 100644
> --- a/Documentation/devicetree/bindings/arm/shmobile.txt
> +++ b/Documentation/devicetree/bindings/arm/shmobile.txt
> @@ -29,6 +29,8 @@ SoCs:
>      compatible = "renesas,r8a7794"
>    - R-Car H3 (R8A77950)
>      compatible = "renesas,r8a7795"
> +  - R-Car M3-W (R8A77960)
> +    compatible = "renesas,r8a7796"
>
>
>  Boards:
> @@ -61,5 +63,7 @@ Boards:
>      compatible = "renesas,porter", "renesas,r8a7791"
>    - Salvator-X (RTP0RC7795SIPB0010S)
>      compatible = "renesas,salvator-x", "renesas,r8a7795";
> +  - Salvator-X
> +    compatible = "renesas,salvator-x", "renesas,r8a7796";
>    - SILK (RTP0RC7794LCB00011S)
>      compatible = "renesas,silk", "renesas,r8a7794"
> diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
> index efa77c146415..16d8d26839ea 100644
> --- a/arch/arm64/Kconfig.platforms
> +++ b/arch/arm64/Kconfig.platforms
> @@ -114,6 +114,12 @@ config ARCH_R8A7795
>  	help
>  	  This enables support for the Renesas R-Car H3 SoC.
>
> +config ARCH_R8A7796
> +	bool "Renesas R-Car M3-W SoC Platform"
> +	depends on ARCH_RENESAS
> +	help
> +	  This enables support for the Renesas R-Car M3-W SoC.
> +
>  config ARCH_STRATIX10
>  	bool "Altera's Stratix 10 SoCFPGA Family"
>  	help
> diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> new file mode 100644
> index 000000000000..178debf68318
> --- /dev/null
> +++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> @@ -0,0 +1,120 @@
> +/*
> + * Device Tree Source for the r8a7796 SoC
> + *
> + * Copyright (C) 2016 Renesas Electronics Corp.
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2.  This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#include <dt-bindings/clock/r8a7796-cpg-mssr.h>
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +/ {
> +	compatible = "renesas,r8a7796";
> +	#address-cells = <2>;
> +	#size-cells = <2>;
> +
> +	psci {
> +		compatible = "arm,psci-0.2";
> +		method = "smc";
> +	};
> +
> +	cpus {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		/* 1 core only at this point */
> +		a57_0: cpu at 0 {
> +			compatible = "arm,cortex-a57", "arm,armv8";
> +			reg = <0x0>;
> +			device_type = "cpu";
> +			next-level-cache = <&L2_CA57>;
> +			enable-method = "psci";
> +		};
> +
> +		L2_CA57: cache-controller at 0 {
> +			compatible = "cache";
> +			reg = <0>;
> +			cache-unified;
> +			cache-level = <2>;
> +		};
> +	};


It looks to me that in the r8a7795.dtsi the cache-controller node is 
outside the cpus node? I'd think that we should keep is consistent.

Best regards

Dirk


From wxt at rock-chips.com  Wed May 25 00:39:35 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 25 May 2016 15:39:35 +0800
Subject: [RESEND PATCH] ARM64: dts: rockchip: add thermal zone node for rk3399
 SoCs
Message-ID: <1464161975-31299-1-git-send-email-wxt@rock-chips.com>

This adds thermal zone node to rk3399 dtsi, rk3399 thermal data is
including the cpu and gpu sensor zone node.

The thermal zone node is the node containing all the required info
for describing a thermal zone, including its cooling device bindings.
The thermal zone node must contain, apart from its own properties, one
sub-node containing trip nodes and one sub-node containing all the zone
cooling maps.

The following is the parameter is introduced:
* polling-delay:
The maximum number of milliseconds to wait between polls

* polling-delay-passive:
The maximum number of milliseconds to wait between polls when performing
passive cooling.

* trips:
A sub-node which is a container of only trip point nodes required to
describe the thermal zone.

* cooling-maps:
A sub-node which is a container of only cooling device map nodes, used to
describe the relation between trips and cooling devices.

* cooling-device:
A phandle of a cooling device with its specifier, referring to which
cooling device is used in this cooling specifier binding. In the cooling
specifier, the first cell is the minimum cooling state and the second cell
is the maximum cooling state used in this map.

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

 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 100 +++++++++++++++++++++++++++++++
 1 file changed, 100 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 46f325a..f8a80c2 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -45,6 +45,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
 	compatible = "rockchip,rk3399";
@@ -389,6 +390,95 @@
 		status = "disabled";
 	};
 
+	thermal-zones {
+		cpu_thermal: cpu {
+			polling-delay-passive = <100>; /* milliseconds */
+			polling-delay = <1000>; /* milliseconds */
+
+			thermal-sensors = <&tsadc 0>;
+
+			trips {
+				cpu_alert0: cpu_alert0 {
+					temperature = <70000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				cpu_alert1: cpu_alert1 {
+					temperature = <75000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				cpu_crit: cpu_crit {
+					temperature = <95000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert0>;
+					cooling-device =
+						<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+				map1 {
+					trip = <&cpu_alert1>;
+					cooling-device =
+						<&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+						<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+
+		gpu_thermal: gpu {
+			polling-delay-passive = <100>; /* milliseconds */
+			polling-delay = <1000>; /* milliseconds */
+
+			thermal-sensors = <&tsadc 1>;
+
+			trips {
+				gpu_alert0: gpu_alert0 {
+					temperature = <75000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				gpu_crit: gpu_crit {
+					temperature = <95000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&gpu_alert0>;
+					cooling-device =
+						<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+	};
+
+	tsadc: tsadc at ff260000 {
+		compatible = "rockchip,rk3399-tsadc";
+		reg = <0x0 0xff260000 0x0 0x100>;
+		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+		rockchip,grf = <&grf>;
+		clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
+		clock-names = "tsadc", "apb_pclk";
+		assigned-clocks = <&cru SCLK_TSADC>;
+		assigned-clock-rates = <750000>;
+		resets = <&cru SRST_TSADC>;
+		reset-names = "tsadc-apb";
+		pinctrl-names = "init", "default", "sleep";
+		pinctrl-0 = <&otp_gpio>;
+		pinctrl-1 = <&otp_out>;
+		pinctrl-2 = <&otp_gpio>;
+		#thermal-sensor-cells = <1>;
+		rockchip,hw-tshut-temp = <95000>;
+		status = "disabled";
+	};
+
 	pmugrf: syscon at ff320000 {
 		compatible = "rockchip,rk3399-pmugrf", "syscon";
 		reg = <0x0 0xff320000 0x0 0x1000>;
@@ -881,6 +971,16 @@
 			};
 		};
 
+		tsadc {
+			otp_gpio: otp-gpio {
+				rockchip,pins = <1 6 RK_FUNC_GPIO &pcfg_pull_none>;
+			};
+
+			otp_out: otp-out {
+				rockchip,pins = <1 6 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
 		uart0 {
 			uart0_xfer: uart0-xfer {
 				rockchip,pins =
-- 
1.9.1



From k.kozlowski at samsung.com  Wed May 25 00:48:47 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 25 May 2016 09:48:47 +0200
Subject: [PATCH 2/2] ARM: dts: Add async-bridge clock to MFC power domain
 for Exynos5420
In-Reply-To: <1464111662-15336-3-git-send-email-javier@osg.samsung.com>
References: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
 <1464111662-15336-3-git-send-email-javier@osg.samsung.com>
Message-ID: <574558DF.1090000@samsung.com>

On 05/24/2016 07:41 PM, Javier Martinez Canillas wrote:
> The MFC IP is also inter-connected by an Async-Bridge so the CLK_ACLK333
> has to be ungated during a power domain switch. Trying to do it when the
> clock is gated will fail and lead to an imprecise external abort error
> when the driver tries to access the MFC registers with the PD disabled.
> 
> For example, if the s5p-mfc module is removed and the MFC PD turned off:
> 
> [  186.835606] Power domain power-domain at 10044060 disable failed
> [  186.835671] s5p-mfc 11000000.codec: Removing 11000000.codec
> [  186.837670] Power domain power-domain at 10044060 disable failed
> 
> And when the module is inserted again:
> 
> [ 2395.176956] s5p_mfc_wait_for_done_dev:34: Interrupt (dev->int_type:0, command:12) timed out
> [ 2395.177031] s5p_mfc_init_hw:272: Failed to load firmware
> [ 2395.177384] Unhandled fault: imprecise external abort (0x1406) at 0x00000000
> [ 2395.177441] pgd = ec3b4000
> [ 2395.177467] [00000000] *pgd=00000000
> [ 2395.177507] Internal error: : 1406 [#1] PREEMPT SMP ARM
> [ 2395.177550] Modules linked in: s5p_mfc mwifiex_sdio mwifiex uvcvideo s5p_jpeg v4l2_mem2mem videobuf2_vmalloc videobuf2_dma_contig videobuf2_memops videobuf2_v4l2 videobuf2_core v4l2_common videodev media [last unloaded: s5p_mfc]
> [ 2395.177774] CPU: 1 PID: 2382 Comm: v4l_id Tainted: G        W       4.6.0-rc6-next-20160502-00010-g7730dc64d2c1-dirty #179
> [ 2395.177857] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [ 2395.177906] task: ed275500 ti: e6c8c000 task.ti: e6c8c000
> [ 2395.177996] PC is at s5p_mfc_reset+0x1c4/0x284 [s5p_mfc]
> [ 2395.178057] LR is at s5p_mfc_reset+0x1a4/0x284 [s5p_mfc]
> 
> This patch fixes this issue by adding the CLK_ACLK333 as an Async-Bridge
> clock for the MFC power domain, so the PD configuration works properly.
> 
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
> 
> ---
> 
>  arch/arm/boot/dts/exynos5420.dtsi | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)

Indeed patch #1 is not a hard dependency here because there are no other
asb clocks. It is entirely obvious but works fine.

Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

Unless all other patches are meant to current fixes cycle (and/or
cc-stable), I do not plan to apply it now. I'll take it for v4.8, because:
1. Your previous patches are needed. Without them bind/unbind won't work.
2. This is not reproducible in a regular driver operation.
3. It needs clock change to actually be useful.

Is it okay?

Best regards,
Krzysztof

> 
> diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
> index 4c8523471c65..f3e9d873633e 100644
> --- a/arch/arm/boot/dts/exynos5420.dtsi
> +++ b/arch/arm/boot/dts/exynos5420.dtsi
> @@ -313,8 +313,9 @@
>  	mfc_pd: power-domain at 10044060 {
>  		compatible = "samsung,exynos4210-pd";
>  		reg = <0x10044060 0x20>;
> -		clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_USER_ACLK333>;
> -		clock-names = "oscclk", "clk0";
> +		clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_USER_ACLK333>,
> +			 <&clock CLK_ACLK333>;
> +		clock-names = "oscclk", "clk0","asb0";
>  		#power-domain-cells = <0>;
>  	};
>  
> 



From pankaj.dubey at samsung.com  Wed May 25 00:58:22 2016
From: pankaj.dubey at samsung.com (Pankaj Dubey)
Date: Wed, 25 May 2016 13:28:22 +0530
Subject: [PATCH v6 0/2] Introducing Exynos ChipId driver
Message-ID: <1464163104-8163-1-git-send-email-pankaj.dubey@samsung.com>

Once again I am respinning this quite old patch series to introduce 
Exynos Chipid driver.

This patch series introduces Exynos Chipid platform driver.
Each Exynos SoC has ChipID block which can give information about SoC's
product Id and revision number.
At the same time it reduces dependency of mach-exynos files from plat-samsung,
by removing samsung_rev API, similar API is introduced in chipid driver itself
to get revision number and product id. 

I have tested this patch series on Exynos5880 based Chromebook for
normal system boot and S2R.

Revisiion 5 and it's discussion can be found here
 - http://lists.infradead.org/pipermail/linux-arm-kernel/2014-December/310046.html
Revision 4 and it's discussion can be found here
 - https://lkml.org/lkml/2014/12/3/115

Change since v5:
 - Addressed Rob's review comments.
 - Rebased on latest krzk/for-next branch and retested.

Changes since v4:
 - Removed custom sysfs entries as they were not providing any new information
   as pointed out by Arnd.
 - Removed functions exporting product_id and revision, instead we will export
   exynos_chipid_info structure. It will be helpfull when we need to provide more
   fields of chipid outside of chipid, as commented by Yadwinder
 - Converted all funcions as __init. 

Change since v3: 
 - This patch set contains 5/6 and 6/6 patch from v3 series.
 - Made EXYNOS_CHIPID config option non-user selectable,
   as suggested by Tomasz Figa.
 - Made uniform macro for EXYNOS4/5_SOC_MASK as EXYNOS_SOC_MASK as
   suggested by Tomasz Figa.
 - Made local variables static in chipid driver.
 - Added existing SoC's product id's.
 - Added platform driver support.

Changes since v2:
 - Reorganized patches as suggested by Tomasz Figa.
 - Addressed review comments of Tomasz Figa in i2c-s3c2410.c file.

Changes since v1:
 - Added patch to move i2c interrupt re-configuration code from exynos.c
   to i2c driver, as suggested by Arnd.
 - After above patch only user of SYS_I2C_CFG register is pm.c so moving
   save/restore of this register also into i2c driver.
 - Spiltted up exynos4 and exynos5 machine descriptors to get rid from
   soc_is_exynos4/exynos5 kind of macros, as suggested by Arnd.
 - Changed location of chipid driver to "drivers/soc".
 - Added drivers/base/soc.c provided infrastructure to make SoC specific 
   information avaible to user space via sysfs entry, as suggested by Arnd.

Pankaj Dubey (2):
  soc: samsung: add exynos chipid driver support
  ARM: EXYNOS: refactoring of mach-exynos to enable chipid driver

 arch/arm/mach-exynos/Kconfig                 |   1 +
 arch/arm/mach-exynos/common.h                |  53 ++++-----
 arch/arm/mach-exynos/exynos.c                |  49 ++------
 arch/arm/mach-exynos/include/mach/map.h      |   2 -
 arch/arm/mach-exynos/platsmp.c               |   2 +-
 arch/arm/mach-exynos/pm.c                    |   8 +-
 arch/arm/plat-samsung/cpu.c                  |  14 ---
 arch/arm/plat-samsung/include/plat/cpu.h     |   2 -
 arch/arm/plat-samsung/include/plat/map-s5p.h |   1 -
 drivers/soc/samsung/Kconfig                  |   5 +
 drivers/soc/samsung/Makefile                 |   1 +
 drivers/soc/samsung/exynos-chipid.c          | 172 +++++++++++++++++++++++++++
 include/linux/soc/samsung/exynos-soc.h       |  51 ++++++++
 13 files changed, 266 insertions(+), 95 deletions(-)
 create mode 100644 drivers/soc/samsung/exynos-chipid.c
 create mode 100644 include/linux/soc/samsung/exynos-soc.h

-- 
2.4.5



From pankaj.dubey at samsung.com  Wed May 25 00:58:23 2016
From: pankaj.dubey at samsung.com (Pankaj Dubey)
Date: Wed, 25 May 2016 13:28:23 +0530
Subject: [PATCH v6 1/2] soc: samsung: add exynos chipid driver support
In-Reply-To: <1464163104-8163-1-git-send-email-pankaj.dubey@samsung.com>
References: <1464163104-8163-1-git-send-email-pankaj.dubey@samsung.com>
Message-ID: <1464163104-8163-2-git-send-email-pankaj.dubey@samsung.com>

Exynos SoCs have Chipid, for identification of product IDs
and SoC revisions. This patch intends to provide initialization
code for all these functionalities, at the same time it provides some
sysfs entries for accessing these information to user-space.

This driver uses existing binding for exynos-chipid.

CC: Grant Likely <grant.likely at linaro.org>
CC: Rob Herring <robh+dt at kernel.org>
CC: Linus Walleij <linus.walleij at linaro.org>
Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
---
 drivers/soc/samsung/Kconfig            |   5 +
 drivers/soc/samsung/Makefile           |   1 +
 drivers/soc/samsung/exynos-chipid.c    | 172 +++++++++++++++++++++++++++++++++
 include/linux/soc/samsung/exynos-soc.h |  51 ++++++++++
 4 files changed, 229 insertions(+)
 create mode 100644 drivers/soc/samsung/exynos-chipid.c
 create mode 100644 include/linux/soc/samsung/exynos-soc.h

diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
index d7fc123..fc793f3 100644
--- a/drivers/soc/samsung/Kconfig
+++ b/drivers/soc/samsung/Kconfig
@@ -10,4 +10,9 @@ config EXYNOS_PMU
 	bool "Exynos PMU controller driver" if COMPILE_TEST
 	depends on (ARM && ARCH_EXYNOS) || ((ARM || ARM64) && COMPILE_TEST)
 
+config EXYNOS_CHIPID
+	bool "Exynos Chipid controller driver" if COMPILE_TEST
+	depends on (ARM && ARCH_EXYNOS) || ((ARM || ARM64) && COMPILE_TEST)
+	select SOC_BUS
+
 endif
diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
index f64ac4d..81023ed 100644
--- a/drivers/soc/samsung/Makefile
+++ b/drivers/soc/samsung/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_EXYNOS_PMU)	+= exynos-pmu.o exynos3250-pmu.o exynos4-pmu.o \
 					exynos5250-pmu.o exynos5420-pmu.o
+obj-$(CONFIG_EXYNOS_CHIPID)	+= exynos-chipid.o
diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
new file mode 100644
index 0000000..fa20fdd
--- /dev/null
+++ b/drivers/soc/samsung/exynos-chipid.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *	      http://www.samsung.com/
+ *
+ * EXYNOS - CHIP ID support
+ * Author: Pankaj Dubey <pankaj.dubey at samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+#include <linux/soc/samsung/exynos-soc.h>
+
+#define EXYNOS_SUBREV_MASK	(0xF << 4)
+#define EXYNOS_MAINREV_MASK	(0xF << 0)
+#define EXYNOS_REV_MASK		(EXYNOS_SUBREV_MASK | EXYNOS_MAINREV_MASK)
+
+static void __iomem *exynos_chipid_base;
+
+struct exynos_chipid_info exynos_soc_info;
+EXPORT_SYMBOL(exynos_soc_info);
+
+static const char * __init product_id_to_name(unsigned int product_id)
+{
+	const char *soc_name;
+	unsigned int soc_id = product_id & EXYNOS_SOC_MASK;
+
+	switch (soc_id) {
+	case EXYNOS3250_SOC_ID:
+		soc_name = "EXYNOS3250";
+		break;
+	case EXYNOS4210_SOC_ID:
+		soc_name = "EXYNOS4210";
+		break;
+	case EXYNOS4212_SOC_ID:
+		soc_name = "EXYNOS4212";
+		break;
+	case EXYNOS4412_SOC_ID:
+		soc_name = "EXYNOS4412";
+		break;
+	case EXYNOS4415_SOC_ID:
+		soc_name = "EXYNOS4415";
+		break;
+	case EXYNOS5250_SOC_ID:
+		soc_name = "EXYNOS5250";
+		break;
+	case EXYNOS5260_SOC_ID:
+		soc_name = "EXYNOS5260";
+		break;
+	case EXYNOS5420_SOC_ID:
+		soc_name = "EXYNOS5420";
+		break;
+	case EXYNOS5440_SOC_ID:
+		soc_name = "EXYNOS5440";
+		break;
+	case EXYNOS5800_SOC_ID:
+		soc_name = "EXYNOS5800";
+		break;
+	default:
+		soc_name = "UNKNOWN";
+	}
+	return soc_name;
+}
+
+static const struct of_device_id of_exynos_chipid_ids[] = {
+	{
+		.compatible	= "samsung,exynos4210-chipid",
+	},
+	{},
+};
+
+/**
+ *  exynos_chipid_early_init: Early chipid initialization
+ *  @dev: pointer to chipid device
+ */
+int __init exynos_chipid_early_init(struct device *dev)
+{
+	struct device_node *np;
+	const struct of_device_id *match;
+
+	if (exynos_chipid_base)
+		return 0;
+
+	if (!dev)
+		np = of_find_matching_node_and_match(NULL,
+			of_exynos_chipid_ids, &match);
+	else
+		np = dev->of_node;
+
+	if (!np)
+		return -ENODEV;
+
+	exynos_chipid_base = of_iomap(np, 0);
+
+	if (!exynos_chipid_base)
+		return PTR_ERR(exynos_chipid_base);
+	
+	exynos_soc_info.product_id  = __raw_readl(exynos_chipid_base);
+	exynos_soc_info.revision = exynos_soc_info.product_id & EXYNOS_REV_MASK;
+
+	return 0;
+}
+
+static int __init exynos_chipid_probe(struct platform_device *pdev)
+{
+	struct soc_device_attribute *soc_dev_attr;
+	struct soc_device *soc_dev;
+	struct device_node *root;
+	int ret;
+
+	ret = exynos_chipid_early_init(&pdev->dev);
+	if (ret) {
+		dev_dbg(&pdev->dev, "Exynos chipid probe failed: %d\n", ret);
+		return ret;
+	}
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return -ENODEV;
+
+	soc_dev_attr->family = "Samsung Exynos";
+
+	root = of_find_node_by_path("/");
+	ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
+	of_node_put(root);
+	if (ret)
+		goto free_soc;
+
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d",
+					exynos_soc_info.revision);
+	if (!soc_dev_attr->revision)
+		goto free_soc;
+
+	soc_dev_attr->soc_id = product_id_to_name(exynos_soc_info.product_id);
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR(soc_dev))
+		goto free_rev;
+
+	soc_device_to_device(soc_dev);
+
+	dev_info(&pdev->dev, "Exynos: CPU[%s] CPU_REV[0x%x] Detected\n",
+			product_id_to_name(exynos_soc_info.product_id),
+			exynos_soc_info.revision);
+	return 0;
+free_rev:
+	kfree(soc_dev_attr->revision);
+free_soc:
+	kfree(soc_dev_attr);
+	return -EINVAL;
+}
+
+static struct platform_driver exynos_chipid_driver = {
+	.driver = {
+		.name = "exynos-chipid",
+		.of_match_table = of_exynos_chipid_ids,
+	},
+};
+
+static int __init exynos_chipid_init(void)
+{
+	return platform_driver_probe(&exynos_chipid_driver, exynos_chipid_probe);
+}
+device_initcall(exynos_chipid_init);
diff --git a/include/linux/soc/samsung/exynos-soc.h b/include/linux/soc/samsung/exynos-soc.h
new file mode 100644
index 0000000..38b95ad
--- /dev/null
+++ b/include/linux/soc/samsung/exynos-soc.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header for EXYNOS SoC Chipid support
+ *
+ * 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.
+ */
+
+#ifndef __EXYNOS_SOC_H
+#define __EXYNOS_SOC_H
+
+#define EXYNOS3250_SOC_ID	0xE3472000
+#define EXYNOS4210_SOC_ID	0x43210000
+#define EXYNOS4212_SOC_ID	0x43220000
+#define EXYNOS4412_SOC_ID	0xE4412000
+#define EXYNOS4415_SOC_ID	0xE4415000
+#define EXYNOS5250_SOC_ID	0x43520000
+#define EXYNOS5260_SOC_ID	0xE5260000
+#define EXYNOS5410_SOC_ID	0xE5410000
+#define EXYNOS5420_SOC_ID	0xE5420000
+#define EXYNOS5440_SOC_ID	0xE5440000
+#define EXYNOS5800_SOC_ID	0xE5422000
+
+#define EXYNOS_SOC_MASK		0xFFFFF000
+
+#define EXYNOS4210_REV_0	0x0
+#define EXYNOS4210_REV_1_0	0x10
+#define EXYNOS4210_REV_1_1	0x11
+
+/**
+ * Struct exynos_chipid_info
+ * @soc_product_id: product id allocated to exynos SoC
+ * @soc_revision: revision of exynos SoC
+ */
+
+struct exynos_chipid_info {
+	u32 product_id;
+	u32 revision;
+};
+
+extern struct exynos_chipid_info exynos_soc_info;
+
+/* Since we need chipid to be initialized as early as possible
+ * during secondary core bootup adding early initialization function
+ */
+extern int exynos_chipid_early_init(struct device *dev);
+
+#endif /* __EXYNOS_SOC_H */
-- 
2.4.5



From pankaj.dubey at samsung.com  Wed May 25 00:58:24 2016
From: pankaj.dubey at samsung.com (Pankaj Dubey)
Date: Wed, 25 May 2016 13:28:24 +0530
Subject: [PATCH v6 2/2] ARM: EXYNOS: refactoring of mach-exynos to enable
 chipid driver
In-Reply-To: <1464163104-8163-1-git-send-email-pankaj.dubey@samsung.com>
References: <1464163104-8163-1-git-send-email-pankaj.dubey@samsung.com>
Message-ID: <1464163104-8163-3-git-send-email-pankaj.dubey@samsung.com>

This patch enables chipid driver for ARCH_EXYNOS and refactors
machine code for using chipid driver for identification of
SoC ID and SoC rev.

Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
---
 arch/arm/mach-exynos/Kconfig                 |  1 +
 arch/arm/mach-exynos/common.h                | 53 ++++++++++++----------------
 arch/arm/mach-exynos/exynos.c                | 49 +++++--------------------
 arch/arm/mach-exynos/include/mach/map.h      |  2 --
 arch/arm/mach-exynos/platsmp.c               |  2 +-
 arch/arm/mach-exynos/pm.c                    |  8 ++---
 arch/arm/plat-samsung/cpu.c                  | 14 --------
 arch/arm/plat-samsung/include/plat/cpu.h     |  2 --
 arch/arm/plat-samsung/include/plat/map-s5p.h |  1 -
 9 files changed, 37 insertions(+), 95 deletions(-)

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 20dcf6e..f93c790 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -16,6 +16,7 @@ menuconfig ARCH_EXYNOS
 	select ARM_AMBA
 	select ARM_GIC
 	select COMMON_CLK_SAMSUNG
+	select EXYNOS_CHIPID
 	select EXYNOS_THERMAL
 	select EXYNOS_PMU
 	select EXYNOS_SROM
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 5365bf1..566ad2b 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -13,39 +13,26 @@
 #define __ARCH_ARM_MACH_EXYNOS_COMMON_H
 
 #include <linux/platform_data/cpuidle-exynos.h>
+#include <linux/soc/samsung/exynos-soc.h>
 
-#define EXYNOS3250_SOC_ID	0xE3472000
-#define EXYNOS3_SOC_MASK	0xFFFFF000
-
-#define EXYNOS4210_CPU_ID	0x43210000
-#define EXYNOS4212_CPU_ID	0x43220000
-#define EXYNOS4412_CPU_ID	0xE4412200
-#define EXYNOS4_CPU_MASK	0xFFFE0000
-
-#define EXYNOS5250_SOC_ID	0x43520000
-#define EXYNOS5410_SOC_ID	0xE5410000
-#define EXYNOS5420_SOC_ID	0xE5420000
-#define EXYNOS5440_SOC_ID	0xE5440000
-#define EXYNOS5800_SOC_ID	0xE5422000
-#define EXYNOS5_SOC_MASK	0xFFFFF000
-
-extern unsigned long samsung_cpu_id;
+static inline u32 exynos_product_id(void);
 
 #define IS_SAMSUNG_CPU(name, id, mask)		\
 static inline int is_samsung_##name(void)	\
 {						\
-	return ((samsung_cpu_id & mask) == (id & mask));	\
+	u32 product_id = exynos_product_id();	\
+	return ((product_id & mask) == (id));	\
 }
 
-IS_SAMSUNG_CPU(exynos3250, EXYNOS3250_SOC_ID, EXYNOS3_SOC_MASK)
-IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK)
-IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
-IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
-IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK)
-IS_SAMSUNG_CPU(exynos5410, EXYNOS5410_SOC_ID, EXYNOS5_SOC_MASK)
-IS_SAMSUNG_CPU(exynos5420, EXYNOS5420_SOC_ID, EXYNOS5_SOC_MASK)
-IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK)
-IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK)
+IS_SAMSUNG_CPU(exynos3250, EXYNOS3250_SOC_ID, EXYNOS_SOC_MASK)
+IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_SOC_ID, EXYNOS_SOC_MASK)
+IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_SOC_ID, EXYNOS_SOC_MASK)
+IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_SOC_ID, EXYNOS_SOC_MASK)
+IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS_SOC_MASK)
+IS_SAMSUNG_CPU(exynos5410, EXYNOS5410_SOC_ID, EXYNOS_SOC_MASK)
+IS_SAMSUNG_CPU(exynos5420, EXYNOS5420_SOC_ID, EXYNOS_SOC_MASK)
+IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS_SOC_MASK)
+IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS_SOC_MASK)
 
 #if defined(CONFIG_SOC_EXYNOS3250)
 # define soc_is_exynos3250()	is_samsung_exynos3250()
@@ -71,10 +58,6 @@ IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK)
 # define soc_is_exynos4412()	0
 #endif
 
-#define EXYNOS4210_REV_0	(0x0)
-#define EXYNOS4210_REV_1_0	(0x10)
-#define EXYNOS4210_REV_1_1	(0x11)
-
 #if defined(CONFIG_SOC_EXYNOS5250)
 # define soc_is_exynos5250()	is_samsung_exynos5250()
 #else
@@ -172,6 +155,16 @@ extern void exynos_core_restart(u32 core_id);
 extern int exynos_set_boot_addr(u32 core_id, unsigned long boot_addr);
 extern int exynos_get_boot_addr(u32 core_id, unsigned long *boot_addr);
 
+static inline u32 exynos_product_id(void)
+{
+	return exynos_soc_info.product_id;
+}
+
+static inline u32 exynos_revision(void)
+{
+	return exynos_soc_info.revision;
+}
+
 static inline void pmu_raw_writel(u32 val, u32 offset)
 {
 	__raw_writel(val, pmu_base_addr + offset);
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index f977eea..89d7254 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -92,50 +92,11 @@ static void __init exynos_init_late(void)
 	exynos_pm_init();
 }
 
-static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
-					int depth, void *data)
-{
-	struct map_desc iodesc;
-	const __be32 *reg;
-	int len;
-
-	if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
-		!of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
-		return 0;
-
-	reg = of_get_flat_dt_prop(node, "reg", &len);
-	if (reg == NULL || len != (sizeof(unsigned long) * 2))
-		return 0;
-
-	iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0]));
-	iodesc.length = be32_to_cpu(reg[1]) - 1;
-	iodesc.virtual = (unsigned long)S5P_VA_CHIPID;
-	iodesc.type = MT_DEVICE;
-	iotable_init(&iodesc, 1);
-	return 1;
-}
-
-/*
- * exynos_map_io
- *
- * register the standard cpu IO areas
- */
-static void __init exynos_map_io(void)
-{
-	if (soc_is_exynos4())
-		iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
-}
-
 static void __init exynos_init_io(void)
 {
 	debug_ll_io_init();
-
-	of_scan_flat_dt(exynos_fdt_map_chipid, NULL);
-
-	/* detect cpu id and rev. */
-	s5p_init_cpu(S5P_VA_CHIPID);
-
-	exynos_map_io();
+	if (soc_is_exynos4())
+		iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
 }
 
 /*
@@ -187,6 +148,8 @@ static void exynos_map_pmu(void)
 
 static void __init exynos_init_irq(void)
 {
+	int ret;
+
 	irqchip_init();
 	/*
 	 * Since platsmp.c needs pmu base address by the time
@@ -194,6 +157,10 @@ static void __init exynos_init_irq(void)
 	 * init_irq
 	 */
 	exynos_map_pmu();
+
+	ret = exynos_chipid_early_init(NULL);
+	if (ret)
+		pr_warn("Exynos chipid early initialization failed\n");
 }
 
 static const struct of_device_id exynos_cpufreq_matches[] = {
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index c48ba4f..15548ef 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -16,8 +16,6 @@
 
 #include <plat/map-s5p.h>
 
-#define EXYNOS_PA_CHIPID		0x10000000
-
 #define EXYNOS4_PA_CMU			0x10030000
 
 #define EXYNOS4_PA_DMC0			0x10400000
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 85c3be6..a45528d 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -170,7 +170,7 @@ int exynos_cluster_power_state(int cluster)
 
 static void __iomem *cpu_boot_reg_base(void)
 {
-	if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
+	if (soc_is_exynos4210() && exynos_revision() == EXYNOS4210_REV_1_1)
 		return pmu_base_addr + S5P_INFORM5;
 	return sysram_base_addr;
 }
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index c43b776..cd120ac 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -32,18 +32,18 @@
 
 static inline void __iomem *exynos_boot_vector_addr(void)
 {
-	if (samsung_rev() == EXYNOS4210_REV_1_1)
+	if (exynos_revision() == EXYNOS4210_REV_1_1)
 		return pmu_base_addr + S5P_INFORM7;
-	else if (samsung_rev() == EXYNOS4210_REV_1_0)
+	else if (exynos_revision() == EXYNOS4210_REV_1_0)
 		return sysram_base_addr + 0x24;
 	return pmu_base_addr + S5P_INFORM0;
 }
 
 static inline void __iomem *exynos_boot_vector_flag(void)
 {
-	if (samsung_rev() == EXYNOS4210_REV_1_1)
+	if (exynos_revision() == EXYNOS4210_REV_1_1)
 		return pmu_base_addr + S5P_INFORM6;
-	else if (samsung_rev() == EXYNOS4210_REV_1_0)
+	else if (exynos_revision() == EXYNOS4210_REV_1_0)
 		return sysram_base_addr + 0x20;
 	return pmu_base_addr + S5P_INFORM1;
 }
diff --git a/arch/arm/plat-samsung/cpu.c b/arch/arm/plat-samsung/cpu.c
index 71333bb..02d95fd 100644
--- a/arch/arm/plat-samsung/cpu.c
+++ b/arch/arm/plat-samsung/cpu.c
@@ -21,12 +21,6 @@
 unsigned long samsung_cpu_id;
 static unsigned int samsung_cpu_rev;
 
-unsigned int samsung_rev(void)
-{
-	return samsung_cpu_rev;
-}
-EXPORT_SYMBOL(samsung_rev);
-
 void __init s3c64xx_init_cpu(void)
 {
 	samsung_cpu_id = __raw_readl(S3C_VA_SYS + 0x118);
@@ -43,11 +37,3 @@ void __init s3c64xx_init_cpu(void)
 
 	pr_info("Samsung CPU ID: 0x%08lx\n", samsung_cpu_id);
 }
-
-void __init s5p_init_cpu(void __iomem *cpuid_addr)
-{
-	samsung_cpu_id = __raw_readl(cpuid_addr);
-	samsung_cpu_rev = samsung_cpu_id & 0xFF;
-
-	pr_info("Samsung CPU ID: 0x%08lx\n", samsung_cpu_id);
-}
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 61d14f3..fa7d0d6 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -114,8 +114,6 @@ extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
 
 extern void s3c64xx_init_cpu(void);
 
-extern unsigned int samsung_rev(void);
-
 extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 
 extern void s3c24xx_init_clocks(int xtal);
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
index b63aeeb..3708ae5 100644
--- a/arch/arm/plat-samsung/include/plat/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -13,7 +13,6 @@
 #ifndef __ASM_PLAT_MAP_S5P_H
 #define __ASM_PLAT_MAP_S5P_H __FILE__
 
-#define S5P_VA_CHIPID		S3C_ADDR(0x02000000)
 #define S5P_VA_CMU		S3C_ADDR(0x02100000)
 
 #define S5P_VA_DMC0		S3C_ADDR(0x02440000)
-- 
2.4.5



From honghui.zhang at mediatek.com  Wed May 25 00:58:50 2016
From: honghui.zhang at mediatek.com (Honghui Zhang)
Date: Wed, 25 May 2016 15:58:50 +0800
Subject: [PATCH v2 4/5] iommu/mediatek: add support for mtk iommu
 generation one HW
In-Reply-To: <5744750D.9080006@arm.com>
References: <1463658558-567-1-git-send-email-honghui.zhang@mediatek.com>
 <1463658558-567-5-git-send-email-honghui.zhang@mediatek.com>
 <57435AA1.3090602@arm.com> <1464083839.30939.54.camel@mtksdaap41>
 <5744750D.9080006@arm.com>
Message-ID: <1464163130.30939.59.camel@mtksdaap41>

On Tue, 2016-05-24 at 16:36 +0100, Robin Murphy wrote:
> On 24/05/16 10:57, Honghui Zhang wrote:
> [...]
> >>> @@ -48,6 +48,9 @@ struct mtk_iommu_domain {
> >>>    	struct io_pgtable_ops		*iop;
> >>>
> >>>    	struct iommu_domain		domain;
> >>> +	void				*pgt_va;
> >>> +	dma_addr_t			pgt_pa;
> >>> +	void				*cookie;
> >>
> >> These are going to be mutually exclusive with the cfg and iop members,
> >> which implies it might be a good idea to use a union and not waste
> >> space. Or better, just forward-declare struct mtk_iommu_domain here and
> >> leave separate definitions private to each driver. The void *cookie is
> >> also an unnecessary level of abstraction, I think.
> >>
> >
> > Do you mean declare struct mtk_iommu_domain here, and implement a new
> > struct in mtk_iommu_v1.c like
> > struct mtk_iommu_domain_v1 {
> > 	struct mtk_iommu_domain	domain;
> > 	u32			*pgt_va;
> > 	dma_addr_t		pgt_pa;
> > 	mtk_iommu_data		*data;
> > };
> > If this is acceptable I would implement it in the next version.
> 
> Pretty much, except they both want to be called struct mtk_iommu_domain, 
> so that a *declaration* for the sake of the m4u_dom member of struct 
> mtk_iommu_data in the header file can remain common to both drivers - it 
> then just picks up whichever private *definition* from the .c file being 
> compiled.

I will follow your advise in the next version, thanks very much.

> 
> >>>    };
> >>>
> >>>    struct mtk_iommu_data {
> >>> diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
> >>> new file mode 100644
> >>> index 0000000..55023e1
> >>> --- /dev/null
> >>> +++ b/drivers/iommu/mtk_iommu_v1.c
> >>> @@ -0,0 +1,742 @@
> >>> +/*
> >>> + * Copyright (c) 2015-2016 MediaTek Inc.
> >>> + * Author: Yong Wu <yong.wu at mediatek.com>
> >>
> >> Nit: is that in the sense that this patch should also have Yong's
> >> signed-off-by on it, or in that it's your work derived from his version
> >> in mtk_iommu.c?
> >
> > I write this driver based on Yong's version of mtk_iommu.c, should I add
> > his signed-off-by for this patch? Or should I put a comment about this?
> > Thanks.
> 
> OK, in that case I think the appropriate attribution would be along the 
> lines of "Author: Honghui Zhang, based on mtk_iommu.c by Yong Wu" (if in 
> doubt, grepping for "Based on" gives a feel for how this is commonly 
> done). If the work that comprises this patch itself (i.e. the copying 
> and modification of the existing code) is all yours then your sign-off 
> alone is fine.
> 
> [...]
> >>> +static int mtk_iommu_add_device(struct device *dev)
> >>> +{
> >>> +	struct iommu_group *group;
> >>> +	struct device_node *np;
> >>> +	struct of_phandle_args iommu_spec;
> >>> +	int idx = 0;
> >>> +
> >>> +	while (!of_parse_phandle_with_args(dev->of_node, "iommus",
> >>> +				   "#iommu-cells", idx,
> >>> +				   &iommu_spec)) {
> >>
> >> Hang on, this doesn't seem right - why do you need to reimplement all
> >> this instead of using IOMMU_OF_DECLARE()?
> >
> > All the clients of mtk generation one iommu share the same iommu domain,
> > as a matter of fact, mtk generation one iommu only support one iommu
> > domain. ALl the clients share the same iova address and use the same
> > pagetable. That means all iommu clients needed to be attached to the
> > same dma_iommu_mapping.
> 
> Ugh, right - I'd forgotten that the arch/arm DMA mapping code doesn't 
> respect IOMMU groups or default domains at all. That's the real root 
> cause of the issue here.
> 
> > If use IOMMU_OF_DELCARE, we need to call of_iommu_set_ops to set the
> > iommu_ops, I do not want the iommu_ops be set since it would cause iommu
> > client device in different dma_iommu_mapping.
> >
> > When an iommu client device has been created, the following sequence is
> > called.
> >
> > of_platform_device_create
> > 	->of_dma_config
> > 		->arch_setup_dma_ops
> > 			->arch_setup_iommu_dma_ops
> > In this function of arch_setup_iommu_dma_ops would create a new
> > dma_iommu_mapping for each iommu client device and then attach the
> > device to this new dma_iommu_mapping. Since all the iommu clients share
> > the very same pagetable, this will not workable for our HW.
> > I could not release the dma_iommu_mapping in attach_device since the
> > to_dma_iommu_mapping was set after device_attached.
> > Any suggest for this?
> 
> On a second look, you're doing more or less the same thing that the 
> Renesas IPMMU driver currently does, so it's probably OK as a workaround 
> for now. Fixing the arch/arm code is part of the bigger ongoing problem 
> of sorting out IOMMU probing and DMA configuration, and it doesn't seem 
> fair to force that on you for the sake of one driver ;)
> 

Yes, I did read the IPMMU driver before I coding this driver. Thanks.

> [...]
> >>> +static int __maybe_unused mtk_iommu_resume(struct device *dev)
> >>> +{
> >>> +	struct mtk_iommu_data *data = dev_get_drvdata(dev);
> >>> +	struct mtk_iommu_suspend_reg *reg = &data->reg;
> >>> +	void __iomem *base = data->base;
> >>> +
> >>> +	writel_relaxed(data->m4u_dom->pgt_pa, base + REG_MMU_PT_BASE_ADDR);
> >>
> >> Hmm, this looks like the only case where m4u_dom actually seems
> >> necessary - I'm pretty sure all the others could be fairly easily
> >> reworked to not use it (I might try having a quick hack at the existing
> >> M4U driver to see) - at which point we could just explicitly
> >> save/restore the base register here and get rid of m4u_dom entirely.
> >
> > Let me take a while to think about this.
> 
> That was true in the context of arm64, but you're right that the current 
> state of the 32-bit code does make m4u_dom more necessary, so I guess we 
> may as well leave it as-is for now.
> 
> Robin.

Thanks very much for your comments.
I will fix all of this later.




From panand at redhat.com  Wed May 25 01:00:12 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 25 May 2016 13:30:12 +0530
Subject: [PATCH kexec-tools 10/32] kexec: add generic helper to add to
 memory_regions
In-Reply-To: <E1axXSl-0004hr-0T@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSl-0004hr-0T@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GuohKypNtesrjfT3H=U74_X4gudqS5jw+Tu1u1BsO_QF_A@mail.gmail.com>

On Tue, May 3, 2016 at 3:51 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Add a helper to add a memory range to a memory_regions array.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/Makefile      |  4 ++++
>  kexec/mem_regions.c | 30 ++++++++++++++++++++++++++++++
>  kexec/mem_regions.h |  9 +++++++++
>  3 files changed, 43 insertions(+)
>  create mode 100644 kexec/mem_regions.c
>  create mode 100644 kexec/mem_regions.h
>
> diff --git a/kexec/Makefile b/kexec/Makefile
> index a758b4a..e2aee84 100644
> --- a/kexec/Makefile
> +++ b/kexec/Makefile
> @@ -69,6 +69,10 @@ dist                         += kexec/fs2dt.c kexec/fs2dt.h
>  $(ARCH)_FS2DT                  =
>  KEXEC_SRCS                     += $($(ARCH)_FS2DT)
>
> +dist                           += kexec/mem_regions.c kexec/mem_regions.h
> +$(ARCH)_MEM_REGIONS            =
> +KEXEC_SRCS                     += $($(ARCH)_MEM_REGIONS)
> +
>  include $(srcdir)/kexec/arch/alpha/Makefile
>  include $(srcdir)/kexec/arch/arm/Makefile
>  include $(srcdir)/kexec/arch/i386/Makefile
> diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c
> new file mode 100644
> index 0000000..a4952ff
> --- /dev/null
> +++ b/kexec/mem_regions.c
> @@ -0,0 +1,30 @@
> +#include "kexec.h"
> +#include "mem_regions.h"
> +
> +/**
> + * mem_regions_add() - add a memory region to a set of ranges
> + * @ranges: ranges to add the memory region to
> + * @max: maximum number of entries in memory region
> + * @base: base address of memory region
> + * @length: length of memory region in bytes
> + * @type: type of memory region
> + *
> + * Add the memory region to the set of ranges, and return %0 if successful,
> + * or %-1 if we ran out of space.
> + */
> +int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
> +                    unsigned long long length, int type)
> +{
> +       struct memory_range *range;
> +
> +       if (ranges->size >= ranges->max_size)
> +               return -1;
> +
> +       range = ranges->ranges + ranges->size++;
> +       range->start = base;
> +       range->end = base + length - 1;
> +       range->type = type;
> +
> +       return 0;
> +}
> +
> diff --git a/kexec/mem_regions.h b/kexec/mem_regions.h
> new file mode 100644
> index 0000000..b9cfba1
> --- /dev/null
> +++ b/kexec/mem_regions.h
> @@ -0,0 +1,9 @@
> +#ifndef MEM_REGIONS_H
> +#define MEM_REGIONS_H
> +
> +struct memory_ranges;
> +
> +int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
> +                    unsigned long long length, int type);
> +
> +#endif
> --
> 1.9.1
>


From panand at redhat.com  Wed May 25 01:00:27 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 25 May 2016 13:30:27 +0530
Subject: [PATCH kexec-tools 11/32] kexec: add mem_regions sorting
 implementation
In-Reply-To: <E1axXSq-0004hx-8H@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSq-0004hx-8H@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_Gur=Lf7-wX+=ddfEwXrC7U0mduSGTbV2hPp4HSG7nx-8yA@mail.gmail.com>

On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Add a mem_regions sorting implementation taken from the arm code.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/mem_regions.c | 27 +++++++++++++++++++++++++++
>  kexec/mem_regions.h |  2 ++
>  2 files changed, 29 insertions(+)
>
> diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c
> index a4952ff..804984a 100644
> --- a/kexec/mem_regions.c
> +++ b/kexec/mem_regions.c
> @@ -1,6 +1,33 @@
> +#include <stdlib.h>
> +
>  #include "kexec.h"
>  #include "mem_regions.h"
>
> +static int mem_range_cmp(const void *a1, const void *a2)
> +{
> +       const struct memory_range *r1 = a1;
> +       const struct memory_range *r2 = a2;
> +
> +       if (r1->start > r2->start)
> +               return 1;
> +       if (r1->start < r2->start)
> +               return -1;
> +
> +       return 0;
> +}
> +
> +/**
> + * mem_regions_sort() - sort ranges into ascending address order
> + * @ranges: ranges to sort
> + *
> + * Sort the memory regions into ascending address order.
> + */
> +void mem_regions_sort(struct memory_ranges *ranges)
> +{
> +       qsort(ranges->ranges, ranges->size, sizeof(ranges->ranges),
> +             mem_range_cmp);
> +}
> +
>  /**
>   * mem_regions_add() - add a memory region to a set of ranges
>   * @ranges: ranges to add the memory region to
> diff --git a/kexec/mem_regions.h b/kexec/mem_regions.h
> index b9cfba1..da7b5e8 100644
> --- a/kexec/mem_regions.h
> +++ b/kexec/mem_regions.h
> @@ -3,6 +3,8 @@
>
>  struct memory_ranges;
>
> +void mem_regions_sort(struct memory_ranges *ranges);
> +
>  int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
>                      unsigned long long length, int type);
>
> --
> 1.9.1
>


From panand at redhat.com  Wed May 25 01:00:55 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 25 May 2016 13:30:55 +0530
Subject: [PATCH kexec-tools 13/32] arm: fix pointer signedness warning in
 kexec-uImage-arm.c
In-Reply-To: <E1axXT0-0004i9-Nv@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXT0-0004i9-Nv@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_Guo5Z+1Esn9Pc075ChRxBj6beNEXVuExxN5Lr537RPUQ+Q@mail.gmail.com>

On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> kexec/arch/arm/kexec-uImage-arm.c: In function 'uImage_arm_probe':
> kexec/arch/arm/kexec-uImage-arm.c:14:2: warning: pointer targets in passing argument 1 of 'uImage_probe_kernel' differ in signedness [-Wpointer-sign]
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/kexec-uImage-arm.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/kexec/arch/arm/kexec-uImage-arm.c b/kexec/arch/arm/kexec-uImage-arm.c
> index 03c2f4d..8e0a9ac 100644
> --- a/kexec/arch/arm/kexec-uImage-arm.c
> +++ b/kexec/arch/arm/kexec-uImage-arm.c
> @@ -11,7 +11,8 @@
>
>  int uImage_arm_probe(const char *buf, off_t len)
>  {
> -       return uImage_probe_kernel(buf, len, IH_ARCH_ARM);
> +       return uImage_probe_kernel((const unsigned char *)buf, len,
> +                                  IH_ARCH_ARM);
>  }
>
>  int uImage_arm_load(int argc, char **argv, const char *buf, off_t len,
> --
> 1.9.1
>


From panand at redhat.com  Wed May 25 01:00:44 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 25 May 2016 13:30:44 +0530
Subject: [PATCH kexec-tools 12/32] kexec: add helper to exlude a region
 from a set of memory ranges
In-Reply-To: <E1axXSv-0004i3-Gi@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSv-0004i3-Gi@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_Guo_ozXhAnkGk_NrdBME2fSYDoKTHwu3kLBvsrmbwxOdww@mail.gmail.com>

On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Add a helper to exclude a region from a set of memory ranges.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>
> ---
>  kexec/mem_regions.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  kexec/mem_regions.h |  4 ++++
>  2 files changed, 59 insertions(+)
>
> diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c
> index 804984a..c6ba942 100644
> --- a/kexec/mem_regions.c
> +++ b/kexec/mem_regions.c
> @@ -29,6 +29,61 @@ void mem_regions_sort(struct memory_ranges *ranges)
>  }
>
>  /**
> + * mem_regions_exclude() - excludes a memory region from a set of memory ranges
> + * @ranges: memory ranges to exclude the region from
> + * @range: memory range to exclude
> + *
> + * Exclude a memory region from a set of memory ranges.  We assume that
> + * the region to be excluded is either wholely located within one of the
> + * memory ranges, or not at all.
> + */
> +int mem_regions_exclude(struct memory_ranges *ranges,
> +                       const struct memory_range *range)
> +{
> +       int i;
> +
> +       for (i = 0; i < ranges->size; i++) {
> +               struct memory_range *r = ranges->ranges + i;
> +
> +               /*
> +                * We assume that crash area is fully contained in
> +                * some larger memory area.
> +                */
> +               if (r->start <= range->start && r->end >= range->end) {
> +                       if (r->start == range->start) {
> +                               /* Shrink the start of this memory range */
> +                               r->start = range->end + 1;
> +                       } else if (r->end == range->end) {
> +                               /* Shrink the end of this memory range */
> +                               r->end = range->start - 1;

What if r->start == range->start) && (r->end == range->end)?

> +                       } else {
> +                               struct memory_range *new;
> +
> +                               /*
> +                                * Split this area into 2 smaller ones and
> +                                * remove excluded range from between. First
> +                                * create new entry for the remaining area.
> +                                */
> +                               if (ranges->size >= ranges->max_size)
> +                                       return -1;
> +
> +                               new = ranges->ranges + ranges->size++;
> +                               new->start = range->end + 1;
> +                               new->end = r->end;
> +
> +                               /*
> +                                * Update this area to end before excluded
> +                                * range.
> +                                */
> +                               r->end = range->start - 1;
> +                               break;
> +                       }
> +               }
> +       }
> +       return 0;
> +}
> +
> +/**
>   * mem_regions_add() - add a memory region to a set of ranges
>   * @ranges: ranges to add the memory region to
>   * @max: maximum number of entries in memory region
> diff --git a/kexec/mem_regions.h b/kexec/mem_regions.h
> index da7b5e8..ae9e972 100644
> --- a/kexec/mem_regions.h
> +++ b/kexec/mem_regions.h
> @@ -2,9 +2,13 @@
>  #define MEM_REGIONS_H
>
>  struct memory_ranges;
> +struct memory_range;
>
>  void mem_regions_sort(struct memory_ranges *ranges);
>
> +int mem_regions_exclude(struct memory_ranges *ranges,
> +                       const struct memory_range *range);
> +
>  int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
>                      unsigned long long length, int type);
>
> --
> 1.9.1
>


From panand at redhat.com  Wed May 25 01:01:12 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 25 May 2016 13:31:12 +0530
Subject: [PATCH kexec-tools 14/32] arm: fix off-by-one on memory end
In-Reply-To: <E1axXT5-0004iJ-VX@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXT5-0004iJ-VX@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GuqVx4v3o4J=_PqQw=FFJmeXQ_LQPAKGADxL+bgRFor=0w@mail.gmail.com>

On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> The memory range end is inclusive, not exclusive (see x86).  We should
> not be adding one to the value parsed from the /proc/iomem resources.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

I think, this also need to be fixed for ARM64 patches. +Geoff

> ---
>  kexec/arch/arm/kexec-arm.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/kexec/arch/arm/kexec-arm.c b/kexec/arch/arm/kexec-arm.c
> index 4e90e69..e47fc00 100644
> --- a/kexec/arch/arm/kexec-arm.c
> +++ b/kexec/arch/arm/kexec-arm.c
> @@ -51,7 +51,6 @@ int get_memory_ranges(struct memory_range **range, int *ranges,
>                 if (count != 2)
>                         continue;
>                 str = line + consumed;
> -               end = end + 1;
>
>                 if (memcmp(str, "System RAM\n", 11) == 0) {
>                         type = RANGE_RAM;
> --
> 1.9.1
>


From panand at redhat.com  Wed May 25 01:01:41 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 25 May 2016 13:31:41 +0530
Subject: [PATCH kexec-tools 15/32] arm: fix get_kernel_stext_sym() to
 close its file
In-Reply-To: <E1axXTB-0004iP-5Y@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXTB-0004iP-5Y@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GuqYJV4oLiPCQjHckyfR+B=JqoYXKnU2DqaemNhaApc+9Q@mail.gmail.com>

On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Fix get_kernel_stext_sym() so that it closes its file once it's
> finsihed with it - there's no need to leak file descriptors.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/crashdump-arm.c | 23 ++++++++++++++++-------
>  1 file changed, 16 insertions(+), 7 deletions(-)
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index b523e5f..a390187 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -71,25 +71,34 @@ static unsigned long long get_kernel_stext_sym(void)
>         char sym[128];
>         char line[128];
>         FILE *fp;
> -       unsigned long long vaddr;
> +       unsigned long long vaddr = 0;
>         char type;
>
> -       fp = fopen(kallsyms, "r");      if (!fp) {
> +       fp = fopen(kallsyms, "r");
> +       if (!fp) {
>                 fprintf(stderr, "Cannot open %s\n", kallsyms);
>                 return 0;
>         }
>
>         while(fgets(line, sizeof(line), fp) != NULL) {
> -               if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
> +               unsigned long long addr;
> +
> +               if (sscanf(line, "%Lx %c %s", &addr, &type, sym) != 3)
>                         continue;
> +
>                 if (strcmp(sym, stext) == 0) {
> -                       dbgprintf("kernel symbol %s vaddr = %16llx\n", stext, vaddr);
> -                       return vaddr;
> +                       dbgprintf("kernel symbol %s vaddr = %#llx\n", stext, addr);
> +                       vaddr = addr;
> +                       break;
>                 }
>         }
>
> -       fprintf(stderr, "Cannot get kernel %s symbol address\n", stext);
> -       return 0;
> +       fclose(fp);
> +
> +       if (vaddr == 0)
> +               fprintf(stderr, "Cannot get kernel %s symbol address\n", stext);
> +
> +       return vaddr;
>  }
>
>  static int get_kernel_page_offset(struct kexec_info *info,
> --
> 1.9.1
>


From k.kozlowski at samsung.com  Wed May 25 01:01:52 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 25 May 2016 10:01:52 +0200
Subject: [PATCH 2/2] ARM: dts: Add async-bridge clock to MFC power domain
 for Exynos5420
In-Reply-To: <574558DF.1090000@samsung.com>
References: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
 <1464111662-15336-3-git-send-email-javier@osg.samsung.com>
 <574558DF.1090000@samsung.com>
Message-ID: <57455BF0.8080609@samsung.com>

On 05/25/2016 09:48 AM, Krzysztof Kozlowski wrote:
> On 05/24/2016 07:41 PM, Javier Martinez Canillas wrote:
>> The MFC IP is also inter-connected by an Async-Bridge so the CLK_ACLK333
>> has to be ungated during a power domain switch. Trying to do it when the
>> clock is gated will fail and lead to an imprecise external abort error
>> when the driver tries to access the MFC registers with the PD disabled.
>>
>> For example, if the s5p-mfc module is removed and the MFC PD turned off:
>>
>> [  186.835606] Power domain power-domain at 10044060 disable failed
>> [  186.835671] s5p-mfc 11000000.codec: Removing 11000000.codec
>> [  186.837670] Power domain power-domain at 10044060 disable failed
>>
>> And when the module is inserted again:
>>
>> [ 2395.176956] s5p_mfc_wait_for_done_dev:34: Interrupt (dev->int_type:0, command:12) timed out
>> [ 2395.177031] s5p_mfc_init_hw:272: Failed to load firmware
>> [ 2395.177384] Unhandled fault: imprecise external abort (0x1406) at 0x00000000
>> [ 2395.177441] pgd = ec3b4000
>> [ 2395.177467] [00000000] *pgd=00000000
>> [ 2395.177507] Internal error: : 1406 [#1] PREEMPT SMP ARM
>> [ 2395.177550] Modules linked in: s5p_mfc mwifiex_sdio mwifiex uvcvideo s5p_jpeg v4l2_mem2mem videobuf2_vmalloc videobuf2_dma_contig videobuf2_memops videobuf2_v4l2 videobuf2_core v4l2_common videodev media [last unloaded: s5p_mfc]
>> [ 2395.177774] CPU: 1 PID: 2382 Comm: v4l_id Tainted: G        W       4.6.0-rc6-next-20160502-00010-g7730dc64d2c1-dirty #179
>> [ 2395.177857] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>> [ 2395.177906] task: ed275500 ti: e6c8c000 task.ti: e6c8c000
>> [ 2395.177996] PC is at s5p_mfc_reset+0x1c4/0x284 [s5p_mfc]
>> [ 2395.178057] LR is at s5p_mfc_reset+0x1a4/0x284 [s5p_mfc]
>>
>> This patch fixes this issue by adding the CLK_ACLK333 as an Async-Bridge
>> clock for the MFC power domain, so the PD configuration works properly.
>>
>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>
>> ---
>>
>>  arch/arm/boot/dts/exynos5420.dtsi | 5 +++--
>>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> Indeed patch #1 is not a hard dependency here because there are no other
> asb clocks. It is entirely obvious but works fine.

Damn, I wanted to write:
"It is not entirely obvious but works fine."
(in Exynos pm_domains driver the clk_get() returns -ENOENT and the loop
is escaped early)

BR,
Krzysztof

> 
> Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> 
> Unless all other patches are meant to current fixes cycle (and/or
> cc-stable), I do not plan to apply it now. I'll take it for v4.8, because:
> 1. Your previous patches are needed. Without them bind/unbind won't work.
> 2. This is not reproducible in a regular driver operation.
> 3. It needs clock change to actually be useful.
> 
> Is it okay?
> 
> Best regards,
> Krzysztof
> 
>>
>> diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
>> index 4c8523471c65..f3e9d873633e 100644
>> --- a/arch/arm/boot/dts/exynos5420.dtsi
>> +++ b/arch/arm/boot/dts/exynos5420.dtsi
>> @@ -313,8 +313,9 @@
>>  	mfc_pd: power-domain at 10044060 {
>>  		compatible = "samsung,exynos4210-pd";
>>  		reg = <0x10044060 0x20>;
>> -		clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_USER_ACLK333>;
>> -		clock-names = "oscclk", "clk0";
>> +		clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_USER_ACLK333>,
>> +			 <&clock CLK_ACLK333>;
>> +		clock-names = "oscclk", "clk0","asb0";
>>  		#power-domain-cells = <0>;
>>  	};
>>  
>>
> 
> 



From raashidmuhammed at zilogic.com  Wed May 25 01:15:05 2016
From: raashidmuhammed at zilogic.com (Raashid Muhammed)
Date: Wed, 25 May 2016 13:45:05 +0530
Subject: [PATCH 1/2] ARM: at91/dt: at91sam9260: Remove leading zeros in OHCI
 node.
Message-ID: <1464164106-28359-1-git-send-email-raashidmuhammed@zilogic.com>

From: Raashid Muhammed <raashidmuhammed at zilogic.com>

Remove leading zeros in OHCI node for at91sam9260 based boards.

Signed-off-by: Raashid Muhammed <raashidmuhammed at zilogic.com>
Reviewed-by: Vijay Kumar B. <vijaykumar at bravegnu.org>
---
 arch/arm/boot/dts/aks-cdu.dts               | 2 +-
 arch/arm/boot/dts/animeo_ip.dts             | 2 +-
 arch/arm/boot/dts/at91-foxg20.dts           | 2 +-
 arch/arm/boot/dts/at91-kizbox.dts           | 2 +-
 arch/arm/boot/dts/at91-qil_a9260.dts        | 2 +-
 arch/arm/boot/dts/at91sam9260.dtsi          | 2 +-
 arch/arm/boot/dts/at91sam9g20ek_common.dtsi | 2 +-
 arch/arm/boot/dts/ethernut5.dts             | 2 +-
 arch/arm/boot/dts/evk-pro3.dts              | 2 +-
 arch/arm/boot/dts/usb_a9260_common.dtsi     | 2 +-
 10 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/arm/boot/dts/aks-cdu.dts b/arch/arm/boot/dts/aks-cdu.dts
index d9c50fb..5b1bf92 100644
--- a/arch/arm/boot/dts/aks-cdu.dts
+++ b/arch/arm/boot/dts/aks-cdu.dts
@@ -57,7 +57,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/animeo_ip.dts b/arch/arm/boot/dts/animeo_ip.dts
index 0962f2f..8bcbad3 100644
--- a/arch/arm/boot/dts/animeo_ip.dts
+++ b/arch/arm/boot/dts/animeo_ip.dts
@@ -114,7 +114,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			atmel,vbus-gpio = <&pioB 15 GPIO_ACTIVE_LOW>;
 			status = "okay";
diff --git a/arch/arm/boot/dts/at91-foxg20.dts b/arch/arm/boot/dts/at91-foxg20.dts
index 6bf873e..42a535d 100644
--- a/arch/arm/boot/dts/at91-foxg20.dts
+++ b/arch/arm/boot/dts/at91-foxg20.dts
@@ -128,7 +128,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/at91-kizbox.dts b/arch/arm/boot/dts/at91-kizbox.dts
index 229e989..0e3f34e 100644
--- a/arch/arm/boot/dts/at91-kizbox.dts
+++ b/arch/arm/boot/dts/at91-kizbox.dts
@@ -54,7 +54,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <1>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/at91-qil_a9260.dts b/arch/arm/boot/dts/at91-qil_a9260.dts
index 4f2eebf..5309e19 100644
--- a/arch/arm/boot/dts/at91-qil_a9260.dts
+++ b/arch/arm/boot/dts/at91-qil_a9260.dts
@@ -111,7 +111,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index d4884dd..af5ba31 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -1007,7 +1007,7 @@
 			status = "disabled";
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			compatible = "atmel,at91rm9200-ohci", "usb-ohci";
 			reg = <0x00500000 0x100000>;
 			interrupts = <20 IRQ_TYPE_LEVEL_HIGH 2>;
diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
index e9cc99b..1395b30 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -170,7 +170,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/ethernut5.dts b/arch/arm/boot/dts/ethernut5.dts
index 2430443..298ee2f 100644
--- a/arch/arm/boot/dts/ethernut5.dts
+++ b/arch/arm/boot/dts/ethernut5.dts
@@ -77,7 +77,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/evk-pro3.dts b/arch/arm/boot/dts/evk-pro3.dts
index f72969e..312d3e8 100644
--- a/arch/arm/boot/dts/evk-pro3.dts
+++ b/arch/arm/boot/dts/evk-pro3.dts
@@ -46,7 +46,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/usb_a9260_common.dtsi b/arch/arm/boot/dts/usb_a9260_common.dtsi
index 9beea89..12119b5 100644
--- a/arch/arm/boot/dts/usb_a9260_common.dtsi
+++ b/arch/arm/boot/dts/usb_a9260_common.dtsi
@@ -90,7 +90,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
-- 
2.1.4



From raashidmuhammed at zilogic.com  Wed May 25 01:15:06 2016
From: raashidmuhammed at zilogic.com (Raashid Muhammed)
Date: Wed, 25 May 2016 13:45:06 +0530
Subject: [PATCH 2/2] ARM: at91: Add DT support for Olimex SAM9-L9260 board.
In-Reply-To: <1464164106-28359-1-git-send-email-raashidmuhammed@zilogic.com>
References: <1464164106-28359-1-git-send-email-raashidmuhammed@zilogic.com>
Message-ID: <1464164106-28359-2-git-send-email-raashidmuhammed@zilogic.com>

From: Raashid Muhammed <raashidmuhammed at zilogic.com>

sam9-l9260 is a low cost board designed by Olimex.

More information is available at:
https://www.olimex.com/Products/ARM/Atmel/SAM9-L9260/

Signed-off-by: Raashid Muhammed <raashidmuhammed at zilogic.com>
Reviewed-by: Vijay Kumar B. <vijaykumar at bravegnu.org>
---
 Documentation/devicetree/bindings/arm/olimex.txt |   8 +-
 arch/arm/boot/dts/Makefile                       |   1 +
 arch/arm/boot/dts/at91-sam9_l9260.dts            | 115 +++++++++++++++++++++++
 3 files changed, 122 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/boot/dts/at91-sam9_l9260.dts

diff --git a/Documentation/devicetree/bindings/arm/olimex.txt b/Documentation/devicetree/bindings/arm/olimex.txt
index 007fb5c..d726aec 100644
--- a/Documentation/devicetree/bindings/arm/olimex.txt
+++ b/Documentation/devicetree/bindings/arm/olimex.txt
@@ -1,5 +1,9 @@
-Olimex i.MX Platforms Device Tree Bindings
-------------------------------------------
+Olimex Device Tree Bindings
+---------------------------
+
+SAM9-L9260 Board
+Required root node properties:
+    - compatible = "olimex,sam9-l9260", "atmel,at91sam9260";
 
 i.MX23 Olinuxino Low Cost Board
 Required root node properties:
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 0f89d87..d27f09d 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -19,6 +19,7 @@ dtb-$(CONFIG_SOC_SAM_V4_V5) += \
 	usb_a9260.dtb \
 	at91sam9261ek.dtb \
 	at91sam9263ek.dtb \
+	at91-sam9_l9260.dtb \
 	tny_a9263.dtb \
 	usb_a9263.dtb \
 	at91-foxg20.dtb \
diff --git a/arch/arm/boot/dts/at91-sam9_l9260.dts b/arch/arm/boot/dts/at91-sam9_l9260.dts
new file mode 100644
index 0000000..e2da9b906
--- /dev/null
+++ b/arch/arm/boot/dts/at91-sam9_l9260.dts
@@ -0,0 +1,115 @@
+/*
+ * at91-sam9_l9260.dts - Device Tree file for Olimex SAM9-L9260 board
+ *
+ *  Copyright (C) 2016 Raashid Muhammed <raashidmuhammed at zilogic.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+#include "at91sam9260.dtsi"
+
+/ {
+	model = "Olimex sam9-l9260";
+	compatible = "olimex,sam9-l9260", "atmel,at91sam9260", "atmel,at91sam9";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	 };
+
+	 memory {
+		reg = <0x20000000 0x4000000>;
+	 };
+
+	 clocks {
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
+	 };
+
+	 ahb {
+		apb {
+			mmc0: mmc at fffa8000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc0
+					&pinctrl_mmc0_clk
+					&pinctrl_mmc0_slot1_cmd_dat0
+					&pinctrl_mmc0_slot1_dat1_3>;
+				status = "okay";
+
+				slot at 1 {
+					reg = <1>;
+					bus-width = <4>;
+					cd-gpios = <&pioC 8 GPIO_ACTIVE_HIGH>;
+					wp-gpios = <&pioC 4 GPIO_ACTIVE_HIGH>;
+				};
+			};
+
+			macb0: ethernet at fffc4000 {
+				phy-mode = "mii";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "okay";
+
+				ethernet-phy at 1 {
+					reg = <0x1>;
+				};
+			 };
+
+			spi0: spi at fffc8000 {
+				cs-gpios = <&pioC 11 0>, <0>, <0>, <0>;
+				status = "okay";
+
+				mtd_dataflash at 0 {
+					compatible = "atmel,at45", "atmel,dataflash";
+					spi-max-frequency = <15000000>;
+					reg = <0>;
+				};
+			};
+
+			dbgu: serial at fffff200 {
+				status = "okay";
+			 };
+
+			pinctrl at fffff400 {
+				mmc0 {
+					pinctrl_board_mmc0: mmc0-board {
+						atmel,pins =
+							<AT91_PIOC 8 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH	/* CD pin */
+							 AT91_PIOC 4 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP>;	/* WP pin */
+					};
+				};
+			};
+		 };
+
+		nand0: nand at 40000000 {
+		       nand-bus-width = <8>;
+		       nand-ecc-mode = "soft";
+		       nand-on-flash-bbt = <1>;
+		       status = "okay";
+		 };
+
+		 usb0: ohci at 500000 {
+		       status = "okay";
+		 };
+
+	 };
+
+	 i2c at 0 {
+		status = "okay";
+	 };
+
+	 leds {
+		compatible = "gpio-leds";
+
+		b0 {
+			label = "b0";
+			gpios = <&pioA 6 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+
+	};
+};
-- 
2.1.4



From sricharan at codeaurora.org  Wed May 25 01:16:50 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Wed, 25 May 2016 13:46:50 +0530
Subject: [PATCH V3 0/2] i2c: qup: Some misc fixes
Message-ID: <1464164212-11377-1-git-send-email-sricharan@codeaurora.org>

One for fixing the bug with CONFIG_DEBUG_SG enabled and another
to suspend the transfer for all errors instead of just for NACK.

[V3] Added more commit description. Return more appropriate
     error codes for NACK and other bus errors. Corrected
     other bus errors handling procedure for dma mode as well.
     Removed the dev_err log for NACKs.

[V2] Removed the use of unnecessary variable assignment.

Kept the reviewed and Tested by tag for patch#1,
as there was no code change.

Depends on patch[1] for the error handling to be complete.

[1] https://lkml.org/lkml/2016/5/9/447

Sricharan R (2):
  i2c: qup: Fix broken dma when CONFIG_DEBUG_SG is enabled
  i2c: qup: Fix error handling

 drivers/i2c/busses/i2c-qup.c | 129 +++++++++++++++++++------------------------
 1 file changed, 58 insertions(+), 71 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Wed May 25 01:16:51 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Wed, 25 May 2016 13:46:51 +0530
Subject: [PATCH V3 1/2] i2c: qup: Fix broken dma when CONFIG_DEBUG_SG is
 enabled
In-Reply-To: <1464164212-11377-1-git-send-email-sricharan@codeaurora.org>
References: <1464164212-11377-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1464164212-11377-2-git-send-email-sricharan@codeaurora.org>

With CONFIG_DEBUG_SG is enabled and when dma mode is used, below dump is seen,

------------[ cut here ]------------
kernel BUG at include/linux/scatterlist.h:140!
Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.0-00459-g9f087b9-dirty #7
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
task: ffffffc036868000 ti: ffffffc036870000 task.ti: ffffffc036870000
PC is at qup_sg_set_buf.isra.13+0x138/0x154
LR is at qup_sg_set_buf.isra.13+0x50/0x154
pc : [<ffffffc0005a0ed8>] lr : [<ffffffc0005a0df0>] pstate: 60000145
sp : ffffffc0368735c0
x29: ffffffc0368735c0 x28: ffffffc036873752
x27: ffffffc035233018 x26: ffffffc000c4e000
x25: 0000000000000000 x24: 0000000000000004
x23: 0000000000000000 x22: ffffffc035233668
x21: ffffff80004e3000 x20: ffffffc0352e0018
x19: 0000004000000000 x18: 0000000000000028
x17: 0000000000000004 x16: ffffffc0017a39c8
x15: 0000000000001cdf x14: ffffffc0019929d8
x13: ffffffc0352e0018 x12: 0000000000000000
x11: 0000000000000001 x10: 0000000000000001
x9 : ffffffc0012b2d70 x8 : ffffff80004e3000
x7 : 0000000000000018 x6 : 0000000030000000
x5 : ffffffc00199f018 x4 : ffffffc035233018
x3 : 0000000000000004 x2 : 00000000c0000000
x1 : 0000000000000003 x0 : 0000000000000000

Process swapper/0 (pid: 1, stack limit = 0xffffffc036870020)
Stack: (0xffffffc0368735c0 to 0xffffffc036874000)

sg_set_buf expects that the buf parameter passed in should be from
lowmem and a valid pageframe. This is not true for pages from
dma_alloc_coherent which can be carveouts, hence the check fails.
Change allocation of sg buffers from dma_coherent memory to kzalloc
to fix the issue.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
Reviewed-by: Andy Gross <andy.gross at linaro.org>
Tested-by: Naveen Kaje <nkaje at codeaurora.org>
---
[V3] Added more commit description.

 drivers/i2c/busses/i2c-qup.c | 53 ++++++++++++++------------------------------
 1 file changed, 17 insertions(+), 36 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 23eaabb..8620e99 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -585,8 +585,8 @@ static void qup_i2c_bam_cb(void *data)
 }
 
 static int qup_sg_set_buf(struct scatterlist *sg, void *buf,
-			  struct qup_i2c_tag *tg, unsigned int buflen,
-			  struct qup_i2c_dev *qup, int map, int dir)
+			  unsigned int buflen, struct qup_i2c_dev *qup,
+			  int dir)
 {
 	int ret;
 
@@ -595,9 +595,6 @@ static int qup_sg_set_buf(struct scatterlist *sg, void *buf,
 	if (!ret)
 		return -EINVAL;
 
-	if (!map)
-		sg_dma_address(sg) = tg->addr + ((u8 *)buf - tg->start);
-
 	return 0;
 }
 
@@ -670,16 +667,15 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 				/* scratch buf to read the start and len tags */
 				ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
 						     &qup->brx.tag.start[0],
-						     &qup->brx.tag,
-						     2, qup, 0, 0);
+						     2, qup, DMA_FROM_DEVICE);
 
 				if (ret)
 					return ret;
 
 				ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
 						     &msg->buf[limit * i],
-						     NULL, tlen, qup,
-						     1, DMA_FROM_DEVICE);
+						     tlen, qup,
+						     DMA_FROM_DEVICE);
 				if (ret)
 					return ret;
 
@@ -688,7 +684,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 			}
 			ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
 					     &qup->start_tag.start[off],
-					     &qup->start_tag, len, qup, 0, 0);
+					     len, qup, DMA_TO_DEVICE);
 			if (ret)
 				return ret;
 
@@ -696,8 +692,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 			/* scratch buf to read the BAM EOT and FLUSH tags */
 			ret = qup_sg_set_buf(&qup->brx.sg[rx_buf++],
 					     &qup->brx.tag.start[0],
-					     &qup->brx.tag, 2,
-					     qup, 0, 0);
+					     2, qup, DMA_FROM_DEVICE);
 			if (ret)
 				return ret;
 		} else {
@@ -709,17 +704,15 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 				len = qup_i2c_set_tags(tags, qup, msg, 1);
 
 				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
-						     tags,
-						     &qup->start_tag, len,
-						     qup, 0, 0);
+						     tags, len,
+						     qup, DMA_TO_DEVICE);
 				if (ret)
 					return ret;
 
 				tx_len += len;
 				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
 						     &msg->buf[limit * i],
-						     NULL, tlen, qup, 1,
-						     DMA_TO_DEVICE);
+						     tlen, qup, DMA_TO_DEVICE);
 				if (ret)
 					return ret;
 				i++;
@@ -738,8 +731,7 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 							QUP_BAM_FLUSH_STOP;
 				ret = qup_sg_set_buf(&qup->btx.sg[tx_buf++],
 						     &qup->btx.tag.start[0],
-						     &qup->btx.tag, len,
-						     qup, 0, 0);
+						     len, qup, DMA_TO_DEVICE);
 				if (ret)
 					return ret;
 				tx_nents += 1;
@@ -1268,6 +1260,8 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
 		}
 	}
 
+	idx = 0;
+
 	do {
 		if (msgs[idx].len == 0) {
 			ret = -EINVAL;
@@ -1407,27 +1401,21 @@ static int qup_i2c_probe(struct platform_device *pdev)
 
 		/* 2 tag bytes for each block + 5 for start, stop tags */
 		size = blocks * 2 + 5;
-		qup->dpool = dma_pool_create("qup_i2c-dma-pool", &pdev->dev,
-					     size, 4, 0);
 
-		qup->start_tag.start = dma_pool_alloc(qup->dpool, GFP_KERNEL,
-						      &qup->start_tag.addr);
+		qup->start_tag.start = devm_kzalloc(&pdev->dev,
+						    size, GFP_KERNEL);
 		if (!qup->start_tag.start) {
 			ret = -ENOMEM;
 			goto fail_dma;
 		}
 
-		qup->brx.tag.start = dma_pool_alloc(qup->dpool,
-						    GFP_KERNEL,
-						    &qup->brx.tag.addr);
+		qup->brx.tag.start = devm_kzalloc(&pdev->dev, 2, GFP_KERNEL);
 		if (!qup->brx.tag.start) {
 			ret = -ENOMEM;
 			goto fail_dma;
 		}
 
-		qup->btx.tag.start = dma_pool_alloc(qup->dpool,
-						    GFP_KERNEL,
-						    &qup->btx.tag.addr);
+		qup->btx.tag.start = devm_kzalloc(&pdev->dev, 2, GFP_KERNEL);
 		if (!qup->btx.tag.start) {
 			ret = -ENOMEM;
 			goto fail_dma;
@@ -1566,13 +1554,6 @@ static int qup_i2c_remove(struct platform_device *pdev)
 	struct qup_i2c_dev *qup = platform_get_drvdata(pdev);
 
 	if (qup->is_dma) {
-		dma_pool_free(qup->dpool, qup->start_tag.start,
-			      qup->start_tag.addr);
-		dma_pool_free(qup->dpool, qup->brx.tag.start,
-			      qup->brx.tag.addr);
-		dma_pool_free(qup->dpool, qup->btx.tag.start,
-			      qup->btx.tag.addr);
-		dma_pool_destroy(qup->dpool);
 		dma_release_channel(qup->btx.dma);
 		dma_release_channel(qup->brx.dma);
 	}
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Wed May 25 01:16:52 2016
From: sricharan at codeaurora.org (Sricharan R)
Date: Wed, 25 May 2016 13:46:52 +0530
Subject: [PATCH V3 2/2] i2c: qup: Fix error handling
In-Reply-To: <1464164212-11377-1-git-send-email-sricharan@codeaurora.org>
References: <1464164212-11377-1-git-send-email-sricharan@codeaurora.org>
Message-ID: <1464164212-11377-3-git-send-email-sricharan@codeaurora.org>

Among the bus errors reported from the QUP_MASTER_STATUS register
only NACK is considered and transfer gets suspended, while
other errors are ignored. Correct this and suspend the transfer
for other errors as well. This avoids unnecessary 'timeouts' which
happens when waiting for events that would never happen when there
is already an error condition on the bus. Also the error handling
procedure should be the same for both NACK and other bus errors in
case of dma mode. So correct that as well.

Signed-off-by: Sricharan R <sricharan at codeaurora.org>
---
[V3] Change the return error code for NACK and other bus errors.
     Added the error handling procedure for other bus errors in
     dma mode. Removed the dev_err print in case of NACK.

 drivers/i2c/busses/i2c-qup.c | 76 ++++++++++++++++++++++++--------------------
 1 file changed, 41 insertions(+), 35 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 8620e99..edced86 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -310,6 +310,7 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
 	u32 opflags;
 	u32 status;
 	u32 shift = __ffs(op);
+	int ret = 0;
 
 	len *= qup->one_byte_t;
 	/* timeout after a wait of twice the max time */
@@ -321,18 +322,28 @@ static int qup_i2c_wait_ready(struct qup_i2c_dev *qup, int op, bool val,
 
 		if (((opflags & op) >> shift) == val) {
 			if ((op == QUP_OUT_NOT_EMPTY) && qup->is_last) {
-				if (!(status & I2C_STATUS_BUS_ACTIVE))
-					return 0;
+				if (!(status & I2C_STATUS_BUS_ACTIVE)) {
+					ret = 0;
+					goto done;
+				}
 			} else {
-				return 0;
+				ret = 0;
+				goto done;
 			}
 		}
 
-		if (time_after(jiffies, timeout))
-			return -ETIMEDOUT;
-
+		if (time_after(jiffies, timeout)) {
+			ret = -ETIMEDOUT;
+			goto done;
+		}
 		usleep_range(len, len * 2);
 	}
+
+done:
+	if (qup->bus_err || qup->qup_err)
+		ret =  (qup->bus_err & QUP_I2C_NACK_FLAG) ? -ENXIO : -EIO;
+
+	return ret;
 }
 
 static void qup_i2c_set_write_mode_v2(struct qup_i2c_dev *qup,
@@ -793,39 +804,35 @@ static int qup_i2c_bam_do_xfer(struct qup_i2c_dev *qup, struct i2c_msg *msg,
 	}
 
 	if (ret || qup->bus_err || qup->qup_err) {
-		if (qup->bus_err & QUP_I2C_NACK_FLAG) {
-			msg--;
-			dev_err(qup->dev, "NACK from %x\n", msg->addr);
-			ret = -EIO;
+		if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
+			dev_err(qup->dev, "change to run state timed out");
+			goto desc_err;
+		}
 
-			if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
-				dev_err(qup->dev, "change to run state timed out");
-				return ret;
-			}
+		if (rx_nents)
+			writel(QUP_BAM_INPUT_EOT,
+			       qup->base + QUP_OUT_FIFO_BASE);
 
-			if (rx_nents)
-				writel(QUP_BAM_INPUT_EOT,
-				       qup->base + QUP_OUT_FIFO_BASE);
+		writel(QUP_BAM_FLUSH_STOP, qup->base + QUP_OUT_FIFO_BASE);
 
-			writel(QUP_BAM_FLUSH_STOP,
-			       qup->base + QUP_OUT_FIFO_BASE);
+		qup_i2c_flush(qup);
 
-			qup_i2c_flush(qup);
+		/* wait for remaining interrupts to occur */
+		if (!wait_for_completion_timeout(&qup->xfer, HZ))
+			dev_err(qup->dev, "flush timed out\n");
 
-			/* wait for remaining interrupts to occur */
-			if (!wait_for_completion_timeout(&qup->xfer, HZ))
-				dev_err(qup->dev, "flush timed out\n");
+		qup_i2c_rel_dma(qup);
 
-			qup_i2c_rel_dma(qup);
-		}
+		ret =  (qup->bus_err & QUP_I2C_NACK_FLAG) ? -ENXIO : -EIO;
 	}
 
+desc_err:
 	dma_unmap_sg(qup->dev, qup->btx.sg, tx_nents, DMA_TO_DEVICE);
 
 	if (rx_nents)
 		dma_unmap_sg(qup->dev, qup->brx.sg, rx_nents,
 			     DMA_FROM_DEVICE);
-desc_err:
+
 	return ret;
 }
 
@@ -841,9 +848,6 @@ static int qup_i2c_bam_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
 	if (ret)
 		goto out;
 
-	qup->bus_err = 0;
-	qup->qup_err = 0;
-
 	writel(0, qup->base + QUP_MX_INPUT_CNT);
 	writel(0, qup->base + QUP_MX_OUTPUT_CNT);
 
@@ -881,12 +885,8 @@ static int qup_i2c_wait_for_complete(struct qup_i2c_dev *qup,
 		ret = -ETIMEDOUT;
 	}
 
-	if (qup->bus_err || qup->qup_err) {
-		if (qup->bus_err & QUP_I2C_NACK_FLAG) {
-			dev_err(qup->dev, "NACK from %x\n", msg->addr);
-			ret = -EIO;
-		}
-	}
+	if (qup->bus_err || qup->qup_err)
+		ret =  (qup->bus_err & QUP_I2C_NACK_FLAG) ? -ENXIO : -EIO;
 
 	return ret;
 }
@@ -1178,6 +1178,9 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 	if (ret < 0)
 		goto out;
 
+	qup->bus_err = 0;
+	qup->qup_err = 0;
+
 	writel(1, qup->base + QUP_SW_RESET);
 	ret = qup_i2c_poll_state(qup, QUP_RESET_STATE);
 	if (ret)
@@ -1227,6 +1230,9 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
 	struct qup_i2c_dev *qup = i2c_get_adapdata(adap);
 	int ret, len, idx = 0, use_dma = 0;
 
+	qup->bus_err = 0;
+	qup->qup_err = 0;
+
 	ret = pm_runtime_get_sync(qup->dev);
 	if (ret < 0)
 		goto out;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation



From sricharan at codeaurora.org  Wed May 25 01:18:34 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Wed, 25 May 2016 13:48:34 +0530
Subject: [PATCH v3 1/2] i2c: qup: add ACPI support
In-Reply-To: <1463694268-9473-1-git-send-email-austinwc@codeaurora.org>
References: <1463694268-9473-1-git-send-email-austinwc@codeaurora.org>
Message-ID: <000001d1b65e$0bfbfde0$23f3f9a0$@codeaurora.org>

Hi,

>From: Naveen Kaje <nkaje at codeaurora.org>
>
>Add support to get the device parameters from ACPI. Assume
>that the clocks are managed by firmware.
>
>Signed-off-by: Naveen Kaje <nkaje at codeaurora.org>
>Signed-off-by: Austin Christ <austinwc at codeaurora.org>
>---
> drivers/i2c/busses/i2c-qup.c | 60 ++++++++++++++++++++++++++++++++------------
> 1 file changed, 44 insertions(+), 16 deletions(-)
>
>Changes:
>- v3:
> - clean up unused variable
>- v2:
> - clean up redundant checks and variables
>
>diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
>index dddd4da..ea6ca5f 100644
>--- a/drivers/i2c/busses/i2c-qup.c
>+++ b/drivers/i2c/busses/i2c-qup.c
>@@ -29,6 +29,7 @@
> #include <linux/platform_device.h>
> #include <linux/pm_runtime.h>
> #include <linux/scatterlist.h>
>+#include <linux/acpi.h>
>
> /* QUP Registers */
> #define QUP_CONFIG		0x000
>@@ -132,6 +133,10 @@
> /* Max timeout in ms for 32k bytes */
> #define TOUT_MAX			300
>
>+/* Default values. Use these if FW query fails */
>+#define DEFAULT_CLK_FREQ 100000
>+#define DEFAULT_SRC_CLK 20000000
>+
> struct qup_i2c_block {
> 	int	count;
> 	int	pos;
>@@ -1354,14 +1359,13 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
> static int qup_i2c_probe(struct platform_device *pdev)
> {
> 	static const int blk_sizes[] = {4, 16, 32};
>-	struct device_node *node = pdev->dev.of_node;
> 	struct qup_i2c_dev *qup;
> 	unsigned long one_bit_t;
> 	struct resource *res;
> 	u32 io_mode, hw_ver, size;
> 	int ret, fs_div, hs_div;
>-	int src_clk_freq;
>-	u32 clk_freq = 100000;
>+	u32 src_clk_freq = 0;
>+	u32 clk_freq = 0;
> 	int blocks;
>
> 	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
>@@ -1372,7 +1376,12 @@ static int qup_i2c_probe(struct platform_device *pdev)
> 	init_completion(&qup->xfer);
> 	platform_set_drvdata(pdev, qup);
>
>-	of_property_read_u32(node, "clock-frequency", &clk_freq);
>+	ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
>+	if (ret) {
>+		dev_warn(qup->dev, "using default clock-frequency %d",
>+			DEFAULT_CLK_FREQ);
>+		clk_freq = DEFAULT_CLK_FREQ;
>+	}
>
> 	if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
> 		qup->adap.algo = &qup_i2c_algo;
>@@ -1454,20 +1463,31 @@ nodma:
> 		return qup->irq;
> 	}
>
>-	qup->clk = devm_clk_get(qup->dev, "core");
>-	if (IS_ERR(qup->clk)) {
>-		dev_err(qup->dev, "Could not get core clock\n");
>-		return PTR_ERR(qup->clk);
>-	}
>+	if (ACPI_HANDLE(qup->dev)) {
>+		ret = device_property_read_u32(qup->dev,
>+				"src-clock-hz", &src_clk_freq);
>+		if (ret) {
>+			dev_warn(qup->dev, "using default src-clock-hz %d",
>+				DEFAULT_SRC_CLK);
>+			src_clk_freq = DEFAULT_SRC_CLK;
>+		}
>+		ACPI_COMPANION_SET(&qup->adap.dev, ACPI_COMPANION(qup->dev));
>+	} else {
>+		qup->clk = devm_clk_get(qup->dev, "core");
>+		if (IS_ERR(qup->clk)) {
>+			dev_err(qup->dev, "Could not get core clock\n");
>+			return PTR_ERR(qup->clk);
>+		}
>
>-	qup->pclk = devm_clk_get(qup->dev, "iface");
>-	if (IS_ERR(qup->pclk)) {
>-		dev_err(qup->dev, "Could not get iface clock\n");
>-		return PTR_ERR(qup->pclk);
>+		qup->pclk = devm_clk_get(qup->dev, "iface");
>+		if (IS_ERR(qup->pclk)) {
>+			dev_err(qup->dev, "Could not get iface clock\n");
>+			return PTR_ERR(qup->pclk);
>+		}
>+		qup_i2c_enable_clocks(qup);
>+		src_clk_freq = clk_get_rate(qup->clk);
> 	}
>
>-	qup_i2c_enable_clocks(qup);
>-
> 	/*
> 	 * Bootloaders might leave a pending interrupt on certain QUP's,
> 	 * so we reset the core before registering for interrupts.
>@@ -1514,7 +1534,6 @@ nodma:
> 	size = QUP_INPUT_FIFO_SIZE(io_mode);
> 	qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
>
>-	src_clk_freq = clk_get_rate(qup->clk);
> 	fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
> 	hs_div = 3;
> 	qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
>@@ -1639,6 +1658,14 @@ static const struct of_device_id qup_i2c_dt_match[] = {
> };
> MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
>
>+#if IS_ENABLED(CONFIG_ACPI)
>+static const struct acpi_device_id qup_i2c_acpi_match[] = {
>+	{ "QCOM8010"},
>+	{ },
>+};
>+MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_ids);
>+#endif
>+
> static struct platform_driver qup_i2c_driver = {
> 	.probe  = qup_i2c_probe,
> 	.remove = qup_i2c_remove,
>@@ -1646,6 +1673,7 @@ static struct platform_driver qup_i2c_driver = {
> 		.name = "i2c_qup",
> 		.pm = &qup_i2c_qup_pm_ops,
> 		.of_match_table = qup_i2c_dt_match,
>+		.acpi_match_table = ACPI_PTR(qup_i2c_acpi_match),
> 	},
> };

Reviewed-by: sricharan at codeaurora.org

Regards,
 Sricharan



From sricharan at codeaurora.org  Wed May 25 01:19:14 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Wed, 25 May 2016 13:49:14 +0530
Subject: [PATCH v3 2/2] i2c: qup: support SMBus block read
In-Reply-To: <1463694268-9473-2-git-send-email-austinwc@codeaurora.org>
References: <1463694268-9473-1-git-send-email-austinwc@codeaurora.org>
 <1463694268-9473-2-git-send-email-austinwc@codeaurora.org>
Message-ID: <000201d1b65e$256a7590$703f60b0$@codeaurora.org>

Hi,

>From: Naveen Kaje <nkaje at codeaurora.org>
>
>I2C QUP driver relies on SMBus emulation support from the framework.
>To handle SMBus block reads, the driver should check I2C_M_RECV_LEN
>flag and should read the first byte received as the message length.
>
>The driver configures the QUP hardware to read one byte. Once the
>message length is known from this byte, the QUP hardware is configured
>to read the rest.
>
>Signed-off-by: Naveen Kaje <nkaje at codeaurora.org>
>Signed-off-by: Austin Christ <austinwc at codeaurora.org>
>---
> drivers/i2c/busses/i2c-qup.c | 68 ++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 65 insertions(+), 3 deletions(-)
>
>Changes:
>- v3:
> - clean up redundant checks
> - use constant instead of variable for smbus length field
>- v2:
> - rework the smbus block read and break into separate function
>
>diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
>index ea6ca5f..9fbed83 100644
>--- a/drivers/i2c/busses/i2c-qup.c
>+++ b/drivers/i2c/busses/i2c-qup.c
>@@ -517,6 +517,33 @@ static int qup_i2c_get_data_len(struct qup_i2c_dev *qup)
> 	return data_len;
> }
>
>+static bool qup_i2c_check_msg_len(struct i2c_msg *msg)
>+{
>+	return ((msg->flags & I2C_M_RD) && (msg->flags & I2C_M_RECV_LEN));
>+}
>+
>+static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev *qup,
>+			struct i2c_msg *msg)
>+{
>+	int len = 0;
>+
>+	if (msg->len > 1) {
>+		tags[len++] = QUP_TAG_V2_DATARD_STOP;
>+		tags[len++] = qup_i2c_get_data_len(qup) - 1;
>+	} else {
>+		tags[len++] = QUP_TAG_V2_START;
>+		tags[len++] = addr & 0xff;
>+
>+		if (msg->flags & I2C_M_TEN)
>+			tags[len++] = addr >> 8;
>+
>+		tags[len++] = QUP_TAG_V2_DATARD;
>+		/* Read 1 byte indicating the length of the SMBus message */
>+		tags[len++] = 1;
>+	}
>+	return len;
>+}
>+
> static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
> 			    struct i2c_msg *msg,  int is_dma)
> {
>@@ -526,6 +553,10 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
>
> 	int last = (qup->blk.pos == (qup->blk.count - 1)) && (qup->is_last);
>
>+	/* Handle tags for SMBus block read */
>+	if (qup_i2c_check_msg_len(msg))
>+		return qup_i2c_set_tags_smb(addr, tags, qup, msg);
>+
> 	if (qup->blk.pos == 0) {
> 		tags[len++] = QUP_TAG_V2_START;
> 		tags[len++] = addr & 0xff;
>@@ -1065,9 +1096,17 @@ static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
> 				struct i2c_msg *msg)
> {
> 	u32 val;
>-	int idx, pos = 0, ret = 0, total;
>+	int idx, pos = 0, ret = 0, total, msg_offset = 0;
>
>+	/*
>+	 * If the message length is already read in
>+	 * the first byte of the buffer, account for
>+	 * that by setting the offset
>+	 */
>+	if (qup_i2c_check_msg_len(msg) && (msg->len > 1))
>+		msg_offset = 1;
> 	total = qup_i2c_get_data_len(qup);
>+	total -= msg_offset;
>
> 	/* 2 extra bytes for read tags */
> 	while (pos < (total + 2)) {
>@@ -1087,8 +1126,8 @@ static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
>
> 			if (pos >= (total + 2))
> 				goto out;
>-
>-			msg->buf[qup->pos++] = val & 0xff;
>+			msg->buf[qup->pos + msg_offset] = val & 0xff;
>+			qup->pos++;
> 		}
> 	}
>
>@@ -1128,6 +1167,24 @@ static int qup_i2c_read_one_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
> 			goto err;
>
> 		qup->blk.pos++;
>+
>+		/* Handle SMBus block read length */
>+		if (qup_i2c_check_msg_len(msg) && (msg->len == 1)) {
>+			if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
>+				ret = -EPROTO;
>+				goto err;
>+			}
>+			msg->len += msg->buf[0];
>+			qup->pos = 0;
>+			qup_i2c_set_read_mode_v2(qup, msg->len);
>+			ret = qup_i2c_issue_xfer_v2(qup, msg);
>+			if (ret)
>+				goto err;
>+			ret = qup_i2c_wait_for_complete(qup, msg);
>+			if (ret)
>+				goto err;
>+			qup_i2c_set_blk_data(qup, msg);
>+		}
> 	} while (qup->blk.pos < qup->blk.count);
>
> err:
>@@ -1210,6 +1267,11 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
> 			goto out;
> 		}
>
>+		if (qup_i2c_check_msg_len(&msgs[idx])) {
>+			ret = -EOPNOTSUPP;
>+			goto out;
>+		}
>+
> 		if (msgs[idx].flags & I2C_M_RD)
> 			ret = qup_i2c_read_one(qup, &msgs[idx]);
> 		else

Reviewed-by: sricharan at codeaurora.org

Regards,
 Sricharan



From k.kozlowski at samsung.com  Wed May 25 01:19:40 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 25 May 2016 10:19:40 +0200
Subject: [PATCH 1/3] clk: samsung: exynos5433: prepare for adding CPU
 clocks
In-Reply-To: <1464095957-25851-2-git-send-email-b.zolnierkie@samsung.com>
References: <1464095957-25851-1-git-send-email-b.zolnierkie@samsung.com>
 <1464095957-25851-2-git-send-email-b.zolnierkie@samsung.com>
Message-ID: <5745601C.6000806@samsung.com>

On 05/24/2016 03:19 PM, Bartlomiej Zolnierkiewicz wrote:
> Open-code samsung_cmu_register_one() calls for CMU_APOLLO and
> CMU_ATLAS setup code as a preparation for adding CPU clocks
> support for Exynos5433.
> 
> There should be no functional change resulting from this patch.
> 
> Cc: Kukjin Kim <kgene at kernel.org>
> CC: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie at samsung.com>
> ---
>  drivers/clk/samsung/clk-exynos5433.c | 85 +++++++++++++++++++++++-------------
>  drivers/clk/samsung/clk.c            | 12 ++---
>  drivers/clk/samsung/clk.h            |  4 ++
>  3 files changed, 65 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
> index 128527b..6dd81ed 100644
> --- a/drivers/clk/samsung/clk-exynos5433.c
> +++ b/drivers/clk/samsung/clk-exynos5433.c
> @@ -11,6 +11,7 @@
>  
>  #include <linux/clk-provider.h>
>  #include <linux/of.h>
> +#include <linux/of_address.h>
>  
>  #include <dt-bindings/clock/exynos5433.h>
>  
> @@ -3594,23 +3595,35 @@ static struct samsung_gate_clock apollo_gate_clks[] __initdata = {
>  			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
>  };
>  
> -static struct samsung_cmu_info apollo_cmu_info __initdata = {
> -	.pll_clks		= apollo_pll_clks,
> -	.nr_pll_clks		= ARRAY_SIZE(apollo_pll_clks),
> -	.mux_clks		= apollo_mux_clks,
> -	.nr_mux_clks		= ARRAY_SIZE(apollo_mux_clks),
> -	.div_clks		= apollo_div_clks,
> -	.nr_div_clks		= ARRAY_SIZE(apollo_div_clks),
> -	.gate_clks		= apollo_gate_clks,
> -	.nr_gate_clks		= ARRAY_SIZE(apollo_gate_clks),
> -	.nr_clk_ids		= APOLLO_NR_CLK,
> -	.clk_regs		= apollo_clk_regs,
> -	.nr_clk_regs		= ARRAY_SIZE(apollo_clk_regs),
> -};
> -
>  static void __init exynos5433_cmu_apollo_init(struct device_node *np)
>  {
> -	samsung_cmu_register_one(np, &apollo_cmu_info);
> +	void __iomem *reg_base;
> +	struct samsung_clk_provider *ctx;
> +
> +	reg_base = of_iomap(np, 0);
> +	if (!reg_base) {
> +		panic("%s: failed to map registers\n", __func__);
> +		return;
> +	}
> +
> +	ctx = samsung_clk_init(np, reg_base, APOLLO_NR_CLK);
> +	if (!ctx) {
> +		panic("%s: unable to allocate ctx\n", __func__);
> +		return;
> +	}
> +
> +	samsung_clk_register_pll(ctx, apollo_pll_clks,
> +				 ARRAY_SIZE(apollo_pll_clks), reg_base);
> +	samsung_clk_register_mux(ctx, apollo_mux_clks,
> +				 ARRAY_SIZE(apollo_mux_clks));
> +	samsung_clk_register_div(ctx, apollo_div_clks,
> +				 ARRAY_SIZE(apollo_div_clks));
> +	samsung_clk_register_gate(ctx, apollo_gate_clks,
> +				  ARRAY_SIZE(apollo_gate_clks));
> +	samsung_clk_sleep_init(reg_base, apollo_clk_regs,
> +			       ARRAY_SIZE(apollo_clk_regs));
> +
> +	samsung_clk_of_add_provider(np, ctx);
>  }
>  CLK_OF_DECLARE(exynos5433_cmu_apollo, "samsung,exynos5433-cmu-apollo",
>  		exynos5433_cmu_apollo_init);
> @@ -3806,23 +3819,35 @@ static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
>  			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
>  };
>  
> -static struct samsung_cmu_info atlas_cmu_info __initdata = {
> -	.pll_clks		= atlas_pll_clks,
> -	.nr_pll_clks		= ARRAY_SIZE(atlas_pll_clks),
> -	.mux_clks		= atlas_mux_clks,
> -	.nr_mux_clks		= ARRAY_SIZE(atlas_mux_clks),
> -	.div_clks		= atlas_div_clks,
> -	.nr_div_clks		= ARRAY_SIZE(atlas_div_clks),
> -	.gate_clks		= atlas_gate_clks,
> -	.nr_gate_clks		= ARRAY_SIZE(atlas_gate_clks),
> -	.nr_clk_ids		= ATLAS_NR_CLK,
> -	.clk_regs		= atlas_clk_regs,
> -	.nr_clk_regs		= ARRAY_SIZE(atlas_clk_regs),
> -};
> -
>  static void __init exynos5433_cmu_atlas_init(struct device_node *np)
>  {
> -	samsung_cmu_register_one(np, &atlas_cmu_info);
> +	void __iomem *reg_base;
> +	struct samsung_clk_provider *ctx;
> +
> +	reg_base = of_iomap(np, 0);
> +	if (!reg_base) {
> +		panic("%s: failed to map registers\n", __func__);
> +		return;

Return is useless here.

> +	}
> +
> +	ctx = samsung_clk_init(np, reg_base, ATLAS_NR_CLK);
> +	if (!ctx) {
> +		panic("%s: unable to allocate ctx\n", __func__);
> +		return;
> +	}

This entire if() is useless. The samsung_clk_init() already panics. I
recently tried to make it consistent across our drivers:
http://www.spinics.net/lists/arm-kernel/msg503014.html

Beside that, looks fine.

Best regards,
Krzysztof



From pankaj.dubey at samsung.com  Wed May 25 01:33:08 2016
From: pankaj.dubey at samsung.com (pankaj.dubey)
Date: Wed, 25 May 2016 14:03:08 +0530
Subject: ARM: dts: exynos: Add MFC memory banks for Peach boards
In-Reply-To: <1461871311-18344-1-git-send-email-javier@osg.samsung.com>
References: <1461871311-18344-1-git-send-email-javier@osg.samsung.com>
Message-ID: <57456344.7020708@samsung.com>

Hi Javier,

On Friday 29 April 2016 12:51 AM, Javier Martinez Canillas wrote:
> The MFC nodes with the memory regions reserved for memory allocations
> are missing in the Exynos5420 Peach Pit and Exynos5800 Peach Pi DTS.
> 
> This causes the s5p-mfc driver probe to fail with the following error:
> 
> [    4.140647] s5p_mfc_alloc_memdevs:1072: Failed to declare coherent memory for MFC device
> [    4.216163] s5p-mfc: probe of 11000000.codec failed with error -12
> 
> Add the missing nodes so the driver probes and the {en,de}coder video
> nodes are registered correctly:
> 
> [    4.096277] s5p-mfc 11000000.codec: decoder registered as /dev/video4
> [    4.102282] s5p-mfc 11000000.codec: encoder registered as /dev/video5
> 
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

Just noticed that, current krzk/for-next failed to boot on Exynos5880
based Chromebook device. Git bisect is showing culprit as this patch.
When I reverted this patch, its able to boot normally.
Is there any missing patches that we need to take on krzk/for-next to
boot on Chromebook.

Thanks,
Pankaj Dubey


From k.kozlowski at samsung.com  Wed May 25 01:31:54 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 25 May 2016 10:31:54 +0200
Subject: [PATCH 2/3] clk: samsung: cpu: prepare for adding Exynos5433 CPU
 clocks
In-Reply-To: <1464095957-25851-3-git-send-email-b.zolnierkie@samsung.com>
References: <1464095957-25851-1-git-send-email-b.zolnierkie@samsung.com>
 <1464095957-25851-3-git-send-email-b.zolnierkie@samsung.com>
Message-ID: <574562FA.1050103@samsung.com>

On 05/24/2016 03:19 PM, Bartlomiej Zolnierkiewicz wrote:
> Exynos5433 uses different register layout for CPU clock registers
> than earlier SoCs so add new code for handling this layout.  Also
> add new CLK_CPU_HAS_E5433_REGS_LAYOUT flag to request using it.
> 
> There should be no functional change resulting from this patch.
> 
> Cc: Kukjin Kim <kgene at kernel.org>
> CC: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie at samsung.com>
> ---
>  drivers/clk/samsung/clk-cpu.c | 131 +++++++++++++++++++++++++++++++++++++++++-
>  drivers/clk/samsung/clk-cpu.h |   4 +-
>  2 files changed, 133 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c
> index 813003d..8bf7e80 100644
> --- a/drivers/clk/samsung/clk-cpu.c
> +++ b/drivers/clk/samsung/clk-cpu.c
> @@ -45,6 +45,13 @@
>  #define E4210_DIV_STAT_CPU0	0x400
>  #define E4210_DIV_STAT_CPU1	0x404
>  
> +#define E5433_MUX_SEL2		0x008
> +#define E5433_MUX_STAT2		0x208
> +#define E5433_DIV_CPU0		0x400
> +#define E5433_DIV_CPU1		0x404
> +#define E5433_DIV_STAT_CPU0	0x500
> +#define E5433_DIV_STAT_CPU1	0x504

I got a problem matching it with datasheed. The base is 0x200?

> +
>  #define E4210_DIV0_RATIO0_MASK	0x7
>  #define E4210_DIV1_HPM_MASK	(0x7 << 4)
>  #define E4210_DIV1_COPY_MASK	(0x7 << 0)
> @@ -253,6 +260,102 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
>  }
>  
>  /*
> + * Helper function to set the 'safe' dividers for the CPU clock. The parameters
> + * div and mask contain the divider value and the register bit mask of the
> + * dividers to be programmed.
> + */
> +static void exynos5433_set_safe_div(void __iomem *base, unsigned long div,
> +					unsigned long mask)

Please align the argument.

> +{
> +	unsigned long div0;
> +
> +	div0 = readl(base + E5433_DIV_CPU0);
> +	div0 = (div0 & ~mask) | (div & mask);
> +	writel(div0, base + E5433_DIV_CPU0);
> +	wait_until_divider_stable(base + E5433_DIV_STAT_CPU0, mask);
> +}
> +
> +/* handler for pre-rate change notification from parent clock */
> +static int exynos5433_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
> +			struct exynos_cpuclk *cpuclk, void __iomem *base)
> +{
> +	const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg;
> +	unsigned long alt_prate = clk_get_rate(cpuclk->alt_parent);
> +	unsigned long alt_div = 0, alt_div_mask = DIV_MASK;
> +	unsigned long div0, div1 = 0, mux_reg;
> +	unsigned long flags;
> +
> +	/* find out the divider values to use for clock data */
> +	while ((cfg_data->prate * 1000) != ndata->new_rate) {
> +		if (cfg_data->prate == 0)
> +			return -EINVAL;
> +		cfg_data++;
> +	}
> +
> +	spin_lock_irqsave(cpuclk->lock, flags);
> +
> +	/*
> +	 * For the selected PLL clock frequency, get the pre-defined divider
> +	 * values.
> +	 */
> +	div0 = cfg_data->div0;
> +	div1 = cfg_data->div1;
> +
> +	/*
> +	 * If the old parent clock speed is less than the clock speed of
> +	 * the alternate parent, then it should be ensured that at no point
> +	 * the armclk speed is more than the old_prate until the dividers are
> +	 * set.  Also workaround the issue of the dividers being set to lower
> +	 * values before the parent clock speed is set to new lower speed
> +	 * (this can result in too high speed of armclk output clocks).

In entire sentence: s/speed/rate/

> +	 */
> +	if (alt_prate > ndata->old_rate || ndata->old_rate > ndata->new_rate) {
> +		unsigned long tmp_rate = min(ndata->old_rate, ndata->new_rate);
> +
> +		alt_div = DIV_ROUND_UP(alt_prate, tmp_rate) - 1;
> +		WARN_ON(alt_div >= MAX_DIV);
> +
> +		exynos5433_set_safe_div(base, alt_div, alt_div_mask);
> +		div0 |= alt_div;
> +	}
> +
> +	/* select the alternate parent */
> +	mux_reg = readl(base + E5433_MUX_SEL2);
> +	writel(mux_reg | 1, base + E5433_MUX_SEL2);
> +	wait_until_mux_stable(base + E5433_MUX_STAT2, 0, 2);
> +
> +	/* alternate parent is active now. set the dividers */
> +	writel(div0, base + E5433_DIV_CPU0);
> +	wait_until_divider_stable(base + E5433_DIV_STAT_CPU0, DIV_MASK_ALL);
> +
> +	writel(div1, base + E5433_DIV_CPU1);
> +	wait_until_divider_stable(base + E5433_DIV_STAT_CPU1, DIV_MASK_ALL);
> +
> +	spin_unlock_irqrestore(cpuclk->lock, flags);

One blank line please.

> +	return 0;
> +}
> +
> +/* handler for post-rate change notification from parent clock */
> +static int exynos5433_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
> +			struct exynos_cpuclk *cpuclk, void __iomem *base)
> +{
> +	unsigned long div = 0, div_mask = DIV_MASK;
> +	unsigned long mux_reg;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(cpuclk->lock, flags);
> +
> +	/* select apll as the alternate parent */
> +	mux_reg = readl(base + E5433_MUX_SEL2);
> +	writel(mux_reg & ~1, base + E5433_MUX_SEL2);
> +	wait_until_mux_stable(base + E5433_MUX_STAT2, 0, 1);
> +
> +	exynos5433_set_safe_div(base, div, div_mask);
> +	spin_unlock_irqrestore(cpuclk->lock, flags);

One blank line please.

> +	return 0;
> +}
> +
> +/*
>   * This notifier function is called for the pre-rate and post-rate change
>   * notifications of the parent clock of cpuclk.
>   */
> @@ -275,6 +378,29 @@ static int exynos_cpuclk_notifier_cb(struct notifier_block *nb,
>  	return notifier_from_errno(err);
>  }
>  
> +/*
> + * This notifier function is called for the pre-rate and post-rate change
> + * notifications of the parent clock of cpuclk.
> + */
> +static int exynos5433_cpuclk_notifier_cb(struct notifier_block *nb,
> +				unsigned long event, void *data)
> +{
> +	struct clk_notifier_data *ndata = data;
> +	struct exynos_cpuclk *cpuclk;
> +	void __iomem *base;
> +	int err = 0;
> +
> +	cpuclk = container_of(nb, struct exynos_cpuclk, clk_nb);
> +	base = cpuclk->ctrl_base;
> +
> +	if (event == PRE_RATE_CHANGE)
> +		err = exynos5433_cpuclk_pre_rate_change(ndata, cpuclk, base);
> +	else if (event == POST_RATE_CHANGE)
> +		err = exynos5433_cpuclk_post_rate_change(ndata, cpuclk, base);
> +
> +	return notifier_from_errno(err);
> +}

Entire function is a duplication of exynos_cpuclk_notifier_cb(), except
the {pre,post}_rate_change. How about checking the flags here and using
only one notifier? Overall the code should be smaller...

Another, more robust solution would be to define new members in:
struct exynos_cpuclk {
	int (pre_rate_change) *(....);
	int (post_rate_change) *(....);
}
This way the notifier_cb would be exactly the same for all implementations.

Best regards,
Krzysztof

> +
>  /* helper function to register a CPU clock */
>  int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
>  		unsigned int lookup_id, const char *name, const char *parent,
> @@ -301,7 +427,10 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
>  	cpuclk->ctrl_base = ctx->reg_base + offset;
>  	cpuclk->lock = &ctx->lock;
>  	cpuclk->flags = flags;
> -	cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb;
> +	if (flags & CLK_CPU_HAS_E5433_REGS_LAYOUT)
> +		cpuclk->clk_nb.notifier_call = exynos5433_cpuclk_notifier_cb;
> +	else
> +		cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb;
>  
>  	cpuclk->alt_parent = __clk_lookup(alt_parent);
>  	if (!cpuclk->alt_parent) {
> diff --git a/drivers/clk/samsung/clk-cpu.h b/drivers/clk/samsung/clk-cpu.h
> index 37874d3..d4b6b51 100644
> --- a/drivers/clk/samsung/clk-cpu.h
> +++ b/drivers/clk/samsung/clk-cpu.h
> @@ -57,10 +57,12 @@ struct exynos_cpuclk {
>  	struct notifier_block			clk_nb;
>  	unsigned long				flags;
>  
> -/* The CPU clock registers has DIV1 configuration register */
> +/* The CPU clock registers have DIV1 configuration register */
>  #define CLK_CPU_HAS_DIV1		(1 << 0)
>  /* When ALT parent is active, debug clocks need safe divider values */
>  #define CLK_CPU_NEEDS_DEBUG_ALT_DIV	(1 << 1)
> +/* The CPU clock registers have Exynos5433-compatible layout */
> +#define CLK_CPU_HAS_E5433_REGS_LAYOUT	(1 << 2)
>  };
>  
>  extern int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
> 



From vigneshr at ti.com  Wed May 25 01:44:12 2016
From: vigneshr at ti.com (Vignesh R)
Date: Wed, 25 May 2016 14:14:12 +0530
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <20160524082040.GR23704@pengutronix.de>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
 <1463648641-6931-2-git-send-email-vigneshr@ti.com>
 <20160522102606.GB23704@pengutronix.de> <5742E710.9@ti.com>
 <20160523131808.GN23704@pengutronix.de> <5743E206.2050602@ti.com>
 <20160524082040.GR23704@pengutronix.de>
Message-ID: <574565DC.4010502@ti.com>



On 05/24/2016 01:50 PM, Uwe Kleine-K?nig wrote:
> Hello,
> 
> On Tue, May 24, 2016 at 10:39:26AM +0530, Vignesh R wrote:
>> On 05/23/2016 06:48 PM, Uwe Kleine-K?nig wrote:
>>> On Mon, May 23, 2016 at 04:48:40PM +0530, R, Vignesh wrote:
>>>> On 5/22/2016 3:56 PM, Uwe Kleine-K?nig wrote:
>>>>> On Thu, May 19, 2016 at 02:34:00PM +0530, Vignesh R wrote:
[...]
>>>
>>> OK, we have code that is more complex than it needs to be for your
>>> device. But your device is a special case of the supported devices, so
>>> I'd say don't bother that there is more logic in the driver than you
>>> need and be lucky.
>>
>> More complexity is just a overhead. Since, encoder can be turned at a
>> rate faster than handling of IRQs (rotary_encoder_quarter_period_irq()
>> is threaded IRQ hence, priority is not close to real time), some states
> 
> This problem isn't unique to your hardware. An "ordinary" encoder with
> just two GPIOs and more than one period can be rotated faster than
> 1/irq_latency, too.

But my hardware should not be affected by this problem. The whole point
of absolute encoder is to overcome the difficulty of software keeping
track of steps, one can read the gpios state anytime and find out what
value is the encoder pointing to.

> There are two things that can be done:
> 
>  - undo the conversion to threaded irqs; or
>  - read out the gpios in the fast handler and only delay decoding and
>    reporting of the event
> 
> Both approaches have their disadvantages.
> 

And both cannot guarantee that an event is not missed (on a loaded
system) and all of the state logic goes for a toss. For binary encoding
multiple IRQs(thats why incremental encoders are usually gray coded)
will fire at same time and handling all of the them is a considerable
overhead, there is good chance that some events are missed.

>> can be missed. rotary_encoder_quarter_period_irq() is not robust in this
>> case, reading gpios directly is more suitable option. I see similar
>> views expressed in previously[1]
>>
>> [1]http://lists.infradead.org/pipermail/linux-arm-kernel/2015-December/391196.html
> 
> IMHO the right thing to do is to improve
> rotary_encoder_quarter_period_irq (and also the other handlers for full
> and half period mode) to make use of additional GPIOs. 

I doubt there exists any incremental encoder with more than 2
gpios(except for the extra reference GPIO or Z signal). So modifying
full/half period handlers maybe unnecessary.

> This way all types of devices benefit and more code is shared.

Sorry.. but IMHO, there is little code sharing and more complexity. So,
I will leave it to the maintainer to decide whats the best approach here.

-- 
Regards
Vignesh


From vigneshr at ti.com  Wed May 25 01:44:29 2016
From: vigneshr at ti.com (Vignesh R)
Date: Wed, 25 May 2016 14:14:29 +0530
Subject: [RFC PATCH 1/2] Input: rotary-encoder- Add support for absolute
 encoder
In-Reply-To: <5742CB03.8010805@ti.com>
References: <1463648641-6931-1-git-send-email-vigneshr@ti.com>
 <1463648641-6931-2-git-send-email-vigneshr@ti.com>
 <20160520163404.GC14951@dtor-ws> <5742CB03.8010805@ti.com>
Message-ID: <574565ED.3060205@ti.com>

Hi Dmitry,

On 05/23/2016 02:48 PM, R, Vignesh wrote:
> 
> 
> On 5/20/2016 10:04 PM, Dmitry Torokhov wrote:
>> On Thu, May 19, 2016 at 02:34:00PM +0530, Vignesh R wrote:
>>> There are rotary-encoders where GPIO lines reflect the actual position
>>> of the rotary encoder dial. For example, if dial points to 9, then four
>>> GPIO lines connected to the rotary encoder will read HLLH(1001b = 9).
>>> Add support for such rotary-encoder.
>>> The driver relies on rotary-encoder,absolute-encoder DT property to
>>> detect such encoders.
>>> Since, GPIO IRQs are not necessary to work with
>>> such encoders, optional polling mode support is added using
>>> input_poll_dev skeleton. This is can be used by enabling
>>> CONFIG_INPUT_GPIO_ROTARY_ENCODER_POLL_MODE_SUPPORT.
>>
>> Does this really belong to a rotary encoder and not a new driver that
>> simply translates gpio-encoded value into ABS* event?
>>
> 
> Currently rotary encoder driver only supports incremental/step counting
> rotary devices. However, the device that is there on am335x-ice is an
> absolute encoder but, IMO, nevertheless a kind of rotary encoder. The
> only difference is that there is no need to count steps and the absolute
> position value is always available as binary encoded state of connected
> GPIOs.
> The hardware on am335x-ice is a mechanical rotary encoder switch
> connected over 4 GPIOs. It is same as binary encoder described at [1]
> (except there are 4 GPIO lines), so this lead me to add support in
> rotary-encoder.
> 
> [1]https://en.wikipedia.org/wiki/Rotary_encoder#Standard_binary_encoding
> 

Could you please comment on how would you like to support above
described encoder: As a new driver or with existing driver with new
compatible/mode setting via DT or as suggest by Uwe in another reply?
IMHO, supporting using existing driver with new mode/compatible string
looks a better option as the hardware is a kind of rotary-encoder.

-- 
Regards
Vignesh


From arnd at arndb.de  Wed May 25 01:49:53 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 25 May 2016 10:49:53 +0200
Subject: [PATCH v6 1/2] soc: samsung: add exynos chipid driver support
In-Reply-To: <1464163104-8163-2-git-send-email-pankaj.dubey@samsung.com>
References: <1464163104-8163-1-git-send-email-pankaj.dubey@samsung.com>
 <1464163104-8163-2-git-send-email-pankaj.dubey@samsung.com>
Message-ID: <15114439.HIyt1ChUT2@wuerfel>

On Wednesday, May 25, 2016 1:28:23 PM CEST Pankaj Dubey wrote:
> Exynos SoCs have Chipid, for identification of product IDs
> and SoC revisions. This patch intends to provide initialization
> code for all these functionalities, at the same time it provides some
> sysfs entries for accessing these information to user-space.
> 
> This driver uses existing binding for exynos-chipid.
> 
> CC: Grant Likely <grant.likely at linaro.org>
> CC: Rob Herring <robh+dt at kernel.org>
> CC: Linus Walleij <linus.walleij at linaro.org>
> Signed-off-by: Pankaj Dubey <pankaj.dubey at samsung.com>
> ---
>  drivers/soc/samsung/Kconfig            |   5 +
>  drivers/soc/samsung/Makefile           |   1 +
>  drivers/soc/samsung/exynos-chipid.c    | 172 +++++++++++++++++++++++++++++++++
>  include/linux/soc/samsung/exynos-soc.h |  51 ++++++++++
> 


I don't like how this exposes the internals of the samsung SoC in a global header
file, after we spent a considerable amount of work on keeping it confined
to arch/arm/{mach-exynos,mach-s3c64xx,plat-samsung}.

Please remove the external interface of the driver, in particular the global
data structure. We keep coming back to this for a lot of platforms, and
I still think we should have an architecture-independent way of matching
platforms to struct soc_device, using an exported function from drivers/base/soc.c
that uses glob_match() to compare a platform string against the running system.

	Arnd


From zhengxing at rock-chips.com  Wed May 25 01:51:56 2016
From: zhengxing at rock-chips.com (Xing Zheng)
Date: Wed, 25 May 2016 16:51:56 +0800
Subject: [PATCH] clk: rockchip: add a dummy clock for the watchdog pclk on
 rk3399
Message-ID: <1464166316-22480-1-git-send-email-zhengxing@rock-chips.com>

Like rk3288, the pclk supplying the watchdog is controlled via the
SGRF register area. Additionally the SGRF isn't even writable in
every boot mode.

But still the clock control is available and in the future someone
might want to use it. Therefore define a simple clock for the time
being so that the watchdog driver can read its rate.

Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
---

 drivers/clk/rockchip/clk-rk3399.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
index 291543f..b6742fa 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -1498,6 +1498,7 @@ static void __init rk3399_clk_init(struct device_node *np)
 {
 	struct rockchip_clk_provider *ctx;
 	void __iomem *reg_base;
+	struct clk *clk;
 
 	reg_base = of_iomap(np, 0);
 	if (!reg_base) {
@@ -1511,6 +1512,14 @@ static void __init rk3399_clk_init(struct device_node *np)
 		return;
 	}
 
+	/* Watchdog pclk is controlled by RK3399 SECURE_GRF_SOC_CON3[8]. */
+	clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_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(ctx, clk, PCLK_WDT);
+
 	rockchip_clk_register_plls(ctx, rk3399_pll_clks,
 				   ARRAY_SIZE(rk3399_pll_clks), -1);
 
-- 
1.7.9.5




From rajeevkumar.linux at gmail.com  Wed May 25 02:31:29 2016
From: rajeevkumar.linux at gmail.com (rajeev kumar)
Date: Wed, 25 May 2016 15:01:29 +0530
Subject: [PATCH v3 2/2] i2c: qup: support SMBus block read
In-Reply-To: <1463694268-9473-2-git-send-email-austinwc@codeaurora.org>
References: <1463694268-9473-1-git-send-email-austinwc@codeaurora.org>
 <1463694268-9473-2-git-send-email-austinwc@codeaurora.org>
Message-ID: <CAA7nrtgAh6EDJO_qTgMawE=tpZe6F_Ae1G0OhuUME0QF4W5AJA@mail.gmail.com>

On Fri, May 20, 2016 at 3:14 AM, Austin Christ <austinwc at codeaurora.org> wrote:
> From: Naveen Kaje <nkaje at codeaurora.org>
>
> I2C QUP driver relies on SMBus emulation support from the framework.
> To handle SMBus block reads, the driver should check I2C_M_RECV_LEN
> flag and should read the first byte received as the message length.
>
> The driver configures the QUP hardware to read one byte. Once the
> message length is known from this byte, the QUP hardware is configured
> to read the rest.
>
> Signed-off-by: Naveen Kaje <nkaje at codeaurora.org>
> Signed-off-by: Austin Christ <austinwc at codeaurora.org>
> ---
>  drivers/i2c/busses/i2c-qup.c | 68 ++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 65 insertions(+), 3 deletions(-)
>
> Changes:
> - v3:
>  - clean up redundant checks
>  - use constant instead of variable for smbus length field
> - v2:
>  - rework the smbus block read and break into separate function
>
> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
> index ea6ca5f..9fbed83 100644
> --- a/drivers/i2c/busses/i2c-qup.c
> +++ b/drivers/i2c/busses/i2c-qup.c
> @@ -517,6 +517,33 @@ static int qup_i2c_get_data_len(struct qup_i2c_dev *qup)
>         return data_len;
>  }
>
> +static bool qup_i2c_check_msg_len(struct i2c_msg *msg)
> +{
> +       return ((msg->flags & I2C_M_RD) && (msg->flags & I2C_M_RECV_LEN));
> +}
> +
> +static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev *qup,
> +                       struct i2c_msg *msg)
> +{
> +       int len = 0;
> +
> +       if (msg->len > 1) {
> +               tags[len++] = QUP_TAG_V2_DATARD_STOP;
> +               tags[len++] = qup_i2c_get_data_len(qup) - 1;
> +       } else {
> +               tags[len++] = QUP_TAG_V2_START;
> +               tags[len++] = addr & 0xff;
> +
> +               if (msg->flags & I2C_M_TEN)
> +                       tags[len++] = addr >> 8;
> +
> +               tags[len++] = QUP_TAG_V2_DATARD;
> +               /* Read 1 byte indicating the length of the SMBus message */
> +               tags[len++] = 1;
> +       }
> +       return len;
> +}
> +
>  static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
>                             struct i2c_msg *msg,  int is_dma)
>  {
> @@ -526,6 +553,10 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
>
>         int last = (qup->blk.pos == (qup->blk.count - 1)) && (qup->is_last);
>
> +       /* Handle tags for SMBus block read */
> +       if (qup_i2c_check_msg_len(msg))
> +               return qup_i2c_set_tags_smb(addr, tags, qup, msg);
> +
>         if (qup->blk.pos == 0) {
>                 tags[len++] = QUP_TAG_V2_START;
>                 tags[len++] = addr & 0xff;
> @@ -1065,9 +1096,17 @@ static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
>                                 struct i2c_msg *msg)
>  {
>         u32 val;
> -       int idx, pos = 0, ret = 0, total;
> +       int idx, pos = 0, ret = 0, total, msg_offset = 0;
>
> +       /*
> +        * If the message length is already read in
> +        * the first byte of the buffer, account for
> +        * that by setting the offset
> +        */
> +       if (qup_i2c_check_msg_len(msg) && (msg->len > 1))
> +               msg_offset = 1;
>         total = qup_i2c_get_data_len(qup);
> +       total -= msg_offset;
>
>         /* 2 extra bytes for read tags */
>         while (pos < (total + 2)) {
> @@ -1087,8 +1126,8 @@ static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
>
>                         if (pos >= (total + 2))
>                                 goto out;
> -
> -                       msg->buf[qup->pos++] = val & 0xff;
> +                       msg->buf[qup->pos + msg_offset] = val & 0xff;
> +                       qup->pos++;
>                 }
>         }
>
> @@ -1128,6 +1167,24 @@ static int qup_i2c_read_one_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>                         goto err;
>
>                 qup->blk.pos++;
> +
> +               /* Handle SMBus block read length */
> +               if (qup_i2c_check_msg_len(msg) && (msg->len == 1)) {
> +                       if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
> +                               ret = -EPROTO;
> +                               goto err;
> +                       }
> +                       msg->len += msg->buf[0];
> +                       qup->pos = 0;
> +                       qup_i2c_set_read_mode_v2(qup, msg->len);
> +                       ret = qup_i2c_issue_xfer_v2(qup, msg);
> +                       if (ret)
> +                               goto err;
> +                       ret = qup_i2c_wait_for_complete(qup, msg);
> +                       if (ret)
> +                               goto err;
> +                       qup_i2c_set_blk_data(qup, msg);
> +               }
>         } while (qup->blk.pos < qup->blk.count);
>
>  err:
> @@ -1210,6 +1267,11 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>                         goto out;
>                 }
>
> +               if (qup_i2c_check_msg_len(&msgs[idx])) {
> +                       ret = -EOPNOTSUPP;

Could you please rethink on this return value ? It should not be "EOPNOTSUPP"

~Rajeev

> +                       goto out;
> +               }
> +
>                 if (msgs[idx].flags & I2C_M_RD)
>                         ret = qup_i2c_read_one(qup, &msgs[idx]);
>                 else
> --
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project.
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From k.kozlowski at samsung.com  Wed May 25 02:34:20 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 25 May 2016 11:34:20 +0200
Subject: [PATCH 3/3] clk: samsung: exynos5433: add CPU clocks configuration
 data and instantiate CPU clocks
In-Reply-To: <1464095957-25851-4-git-send-email-b.zolnierkie@samsung.com>
References: <1464095957-25851-1-git-send-email-b.zolnierkie@samsung.com>
 <1464095957-25851-4-git-send-email-b.zolnierkie@samsung.com>
Message-ID: <5745719C.4000106@samsung.com>

On 05/24/2016 03:19 PM, Bartlomiej Zolnierkiewicz wrote:
> Add the CPU clocks configuration data and instantiate the CPU clocks
> type for Exynos5433.
> 
> Cc: Kukjin Kim <kgene at kernel.org>
> CC: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie at samsung.com>
> ---
>  drivers/clk/samsung/clk-exynos5433.c | 72 ++++++++++++++++++++++++++++++++----
>  1 file changed, 64 insertions(+), 8 deletions(-)
> 

Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

Best regards,
Krzysztof



From vigneshr at ti.com  Wed May 25 02:46:50 2016
From: vigneshr at ti.com (Vignesh R)
Date: Wed, 25 May 2016 15:16:50 +0530
Subject: [PATCH] ARM: dts: keystone-k2*: Increase SPI Flash partition size for
 U-Boot
Message-ID: <20160525094650.6169-1-vigneshr@ti.com>

U-Boot SPI Boot image is now more than 512KB for Keystone2 devices and
cannot fit into existing partition. So, increase the SPI Flash partition
for U-Boot to 1MB for all Keystone2 devices.

Signed-off-by: Vignesh R <vigneshr at ti.com>
---
 arch/arm/boot/dts/keystone-k2e-evm.dts  | 4 ++--
 arch/arm/boot/dts/keystone-k2hk-evm.dts | 4 ++--
 arch/arm/boot/dts/keystone-k2l-evm.dts  | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/keystone-k2e-evm.dts b/arch/arm/boot/dts/keystone-k2e-evm.dts
index 4c32ebc1425a..39c91185e112 100644
--- a/arch/arm/boot/dts/keystone-k2e-evm.dts
+++ b/arch/arm/boot/dts/keystone-k2e-evm.dts
@@ -129,13 +129,13 @@
 
 		partition at 0 {
 			label = "u-boot-spl";
-			reg = <0x0 0x80000>;
+			reg = <0x0 0x100000>;
 			read-only;
 		};
 
 		partition at 1 {
 			label = "misc";
-			reg = <0x80000 0xf80000>;
+			reg = <0x100000 0xf00000>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/keystone-k2hk-evm.dts b/arch/arm/boot/dts/keystone-k2hk-evm.dts
index b38b3441818b..afc70d0481d4 100644
--- a/arch/arm/boot/dts/keystone-k2hk-evm.dts
+++ b/arch/arm/boot/dts/keystone-k2hk-evm.dts
@@ -157,13 +157,13 @@
 
 		partition at 0 {
 			label = "u-boot-spl";
-			reg = <0x0 0x80000>;
+			reg = <0x0 0x100000>;
 			read-only;
 		};
 
 		partition at 1 {
 			label = "misc";
-			reg = <0x80000 0xf80000>;
+			reg = <0x100000 0xf00000>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/keystone-k2l-evm.dts b/arch/arm/boot/dts/keystone-k2l-evm.dts
index 7f9c2e94d605..cabbdf69ddf5 100644
--- a/arch/arm/boot/dts/keystone-k2l-evm.dts
+++ b/arch/arm/boot/dts/keystone-k2l-evm.dts
@@ -106,13 +106,13 @@
 
 		partition at 0 {
 			label = "u-boot-spl";
-			reg = <0x0 0x80000>;
+			reg = <0x0 0x100000>;
 			read-only;
 		};
 
 		partition at 1 {
 			label = "misc";
-			reg = <0x80000 0xf80000>;
+			reg = <0x100000 0xf00000>;
 		};
 	};
 };
-- 
2.8.3



From narmstrong at baylibre.com  Wed May 25 02:49:14 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Wed, 25 May 2016 11:49:14 +0200
Subject: [PATCH v2 0/4] Amlogic: Meson: Add reset controller
Message-ID: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>

Patchset to add and enable the reset controller driver on Meson SoCs platforms.

This reset controller has up to 256 reset lines with reset pulse generation only,
so the assert and deassert calls are not available.

Depends on the patch :
 - "reset: add devm_reset_controller_register API" [1]

Changes since v1 at http://lkml.kernel.org/r/1463732875-23141-1-git-send-email-narmstrong at baylibre.com :
- Remove _gxbb_ in names
- Depends build on ARCH_MESON only
- Add meson8b compatible and bindings
- Re-indent dt-bindings headers
- Switch to devm_ reset controller register
- Remove platform "remove" callback
- Update Dual BSD/GPL file headers

Changes since the RFC at http://lkml.kernel.org/r/1463148012-25988-1-git-send-email-narmstrong at baylibre.com :
- Fix register mapping and bit defines in bindings header
- Remove assert and unassert calls
- Fix missing __iomem

[1] https://patchwork.kernel.org/patch/8988471/

Neil Armstrong (4):
  reset: Add support for the Amlogic Meson SoC Reset Controller
  dt-bindings: reset: Add bindings for the Meson SoC Reset Controller
  ARM64: dts: amlogic: Enable Reset Controller on GXBB-based platforms
  ARM: dts: amlogic: Enable Reset Controller on Meson8b platforms

 .../bindings/reset/amlogic,meson-reset.txt         |  18 ++
 arch/arm/boot/dts/meson8b.dtsi                     |   7 +
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   7 +
 drivers/reset/Makefile                             |   1 +
 drivers/reset/reset-meson.c                        | 137 ++++++++++++++
 .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 210 +++++++++++++++++++++
 include/dt-bindings/reset/amlogic,meson8b-reset.h  | 175 +++++++++++++++++
 7 files changed, 555 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt
 create mode 100644 drivers/reset/reset-meson.c
 create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
 create mode 100644 include/dt-bindings/reset/amlogic,meson8b-reset.h

-- 
2.7.0



From narmstrong at baylibre.com  Wed May 25 02:49:15 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Wed, 25 May 2016 11:49:15 +0200
Subject: [PATCH v2 1/4] reset: Add support for the Amlogic Meson SoC Reset
 Controller
In-Reply-To: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
References: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464169758-26975-2-git-send-email-narmstrong@baylibre.com>

This patch adds the platform driver for the Amlogic Meson SoC Reset
Controller.

The Meson8b and GXBB SoCs are supported.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/reset/Makefile      |   1 +
 drivers/reset/reset-meson.c | 137 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 138 insertions(+)
 create mode 100644 drivers/reset/reset-meson.c

diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index f173fc3..03dc1bb 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
 obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
 obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
 obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o
+obj-$(CONFIG_ARCH_MESON) += reset-meson.o
 obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_HISI) += hisilicon/
diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
new file mode 100644
index 0000000..98087ae
--- /dev/null
+++ b/drivers/reset/reset-meson.c
@@ -0,0 +1,137 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define REG_COUNT	8
+#define BITS_PER_REG	32
+
+struct meson_reset {
+	void __iomem *reg_base;
+	struct reset_controller_dev rcdev;
+};
+
+static int meson_reset_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct meson_reset *data =
+		container_of(rcdev, struct meson_reset, rcdev);
+	unsigned int bank = id / BITS_PER_REG;
+	unsigned int offset = id % BITS_PER_REG;
+	void *reg_addr = data->reg_base + (bank << 2);
+
+	if (bank >= REG_COUNT)
+		return -EINVAL;
+
+	writel(BIT(offset), reg_addr);
+
+	return 0;
+}
+
+static const struct reset_control_ops meson_reset_ops = {
+	.reset		= meson_reset_reset,
+};
+
+static const struct of_device_id meson_reset_dt_ids[] = {
+	 { .compatible = "amlogic,meson8b-reset", },
+	 { .compatible = "amlogic,meson-gxbb-reset", },
+	 { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
+
+static int meson_reset_probe(struct platform_device *pdev)
+{
+	struct meson_reset *data;
+	struct resource *res;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(data->reg_base))
+		return PTR_ERR(data->reg_base);
+
+	platform_set_drvdata(pdev, data);
+
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = REG_COUNT * BITS_PER_REG;
+	data->rcdev.ops = &meson_reset_ops;
+	data->rcdev.of_node = pdev->dev.of_node;
+
+	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
+}
+
+static struct platform_driver meson_reset_driver = {
+	.probe	= meson_reset_probe,
+	.driver = {
+		.name		= "meson_reset",
+		.of_match_table	= meson_reset_dt_ids,
+	},
+};
+
+module_platform_driver(meson_reset_driver);
+
+MODULE_ALIAS("platform:meson_reset");
+MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
+MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver");
+MODULE_LICENSE("Dual BSD/GPL");
-- 
2.7.0



From narmstrong at baylibre.com  Wed May 25 02:49:17 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Wed, 25 May 2016 11:49:17 +0200
Subject: [PATCH v2 3/4] ARM64: dts: amlogic: Enable Reset Controller on
 GXBB-based platforms
In-Reply-To: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
References: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464169758-26975-4-git-send-email-narmstrong@baylibre.com>

Update DTSI file to add the reset controller node.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 832815d..45e9c55 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -43,6 +43,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
 
 / {
 	compatible = "amlogic,meson-gxbb";
@@ -129,6 +130,12 @@
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
 
+			reset: reset-controller at 4404 {
+				compatible = "amlogic,meson-gxbb-reset";
+				reg = <0x0 0x04404 0x0 0x20>;
+				#reset-cells = <1>;
+			};
+
 			uart_A: serial at 84c0 {
 				compatible = "amlogic,meson-uart";
 				reg = <0x0 0x084c0 0x0 0x14>;
-- 
2.7.0



From narmstrong at baylibre.com  Wed May 25 02:49:18 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Wed, 25 May 2016 11:49:18 +0200
Subject: [PATCH v2 4/4] ARM: dts: amlogic: Enable Reset Controller on Meson8b
 platforms
In-Reply-To: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
References: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464169758-26975-5-git-send-email-narmstrong@baylibre.com>

Update DTSI file to add the reset controller node.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm/boot/dts/meson8b.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index 2bfe401..fc4080d 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -46,6 +46,7 @@
 
 #include <dt-bindings/clock/meson8b-clkc.h>
 #include <dt-bindings/gpio/meson8b-gpio.h>
+#include <dt-bindings/reset/amlogic,meson8b-reset.h>
 #include "skeleton.dtsi"
 
 / {
@@ -105,6 +106,12 @@
 			#interrupt-cells = <3>;
 		};
 
+		reset: reset-controller at c1104404 {
+			compatible = "amlogic,meson8b-reset";
+			reg = <0xc1104404 0x20>;
+			#reset-cells = <1>;
+		};
+
 		wdt: watchdog at c1109900 {
 			compatible = "amlogic,meson8b-wdt";
 			reg = <0xc1109900 0x8>;
-- 
2.7.0



From narmstrong at baylibre.com  Wed May 25 02:49:16 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Wed, 25 May 2016 11:49:16 +0200
Subject: [PATCH v2 2/4] dt-bindings: reset: Add bindings for the Meson SoC
 Reset Controller
In-Reply-To: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
References: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464169758-26975-3-git-send-email-narmstrong@baylibre.com>

Add DT bindings for the Meson SoC Reset Controller documentation and the
associated include file.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 .../bindings/reset/amlogic,meson-reset.txt         |  18 ++
 .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 210 +++++++++++++++++++++
 include/dt-bindings/reset/amlogic,meson8b-reset.h  | 175 +++++++++++++++++
 3 files changed, 403 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt
 create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
 create mode 100644 include/dt-bindings/reset/amlogic,meson8b-reset.h

diff --git a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt
new file mode 100644
index 0000000..e746b63
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt
@@ -0,0 +1,18 @@
+Amlogic Meson SoC Reset Controller
+=======================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "amlogic,meson8b-reset" or "amlogic,meson-gxbb-reset"
+- reg: should contain the register address base
+- #reset-cells: 1, see below
+
+example:
+
+reset: reset-controller {
+	compatible = "amlogic,meson-gxbb-reset";
+	reg = <0x0 0x04404 0x0 0x20>;
+	#reset-cells = <1>;
+};
diff --git a/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
new file mode 100644
index 0000000..524d607
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
@@ -0,0 +1,210 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
+
+/*	RESET0					*/
+#define RESET_HIU			0
+/*					1	*/
+#define RESET_DOS_RESET			2
+#define RESET_DDR_TOP			3
+#define RESET_DCU_RESET			4
+#define RESET_VIU			5
+#define RESET_AIU			6
+#define RESET_VID_PLL_DIV		7
+/*					8	*/
+#define RESET_PMUX			9
+#define RESET_VENC			10
+#define RESET_ASSIST			11
+#define RESET_AFIFO2			12
+#define RESET_VCBUS			13
+/*					14	*/
+/*					15	*/
+#define RESET_GIC			16
+#define RESET_CAPB3_DECODE		17
+#define RESET_NAND_CAPB3		18
+#define RESET_HDMITX_CAPB3		19
+#define RESET_MALI_CAPB3		20
+#define RESET_DOS_CAPB3			21
+#define RESET_SYS_CPU_CAPB3		22
+#define RESET_CBUS_CAPB3		23
+#define RESET_AHB_CNTL			24
+#define RESET_AHB_DATA			25
+#define RESET_VCBUS_CLK81		26
+#define RESET_MMC			27
+#define RESET_MIPI_0			28
+#define RESET_MIPI_1			29
+#define RESET_MIPI_2			30
+#define RESET_MIPI_3			31
+/*	RESET1					*/
+#define RESET_CPPM			32
+#define RESET_DEMUX			33
+#define RESET_USB_OTG			34
+#define RESET_DDR			35
+#define RESET_AO_RESET			36
+#define RESET_BT656			37
+#define RESET_AHB_SRAM			38
+/*					39	*/
+#define RESET_PARSER			40
+#define RESET_BLKMV			41
+#define RESET_ISA			42
+#define RESET_ETHERNET			43
+#define RESET_SD_EMMC_A			44
+#define RESET_SD_EMMC_B			45
+#define RESET_SD_EMMC_C			46
+#define RESET_ROM_BOOT			47
+#define RESET_SYS_CPU_0			48
+#define RESET_SYS_CPU_1			49
+#define RESET_SYS_CPU_2			50
+#define RESET_SYS_CPU_3			51
+#define RESET_SYS_CPU_CORE_0		52
+#define RESET_SYS_CPU_CORE_1		53
+#define RESET_SYS_CPU_CORE_2		54
+#define RESET_SYS_CPU_CORE_3		55
+#define RESET_SYS_PLL_DIV		56
+#define RESET_SYS_CPU_AXI		57
+#define RESET_SYS_CPU_L2		58
+#define RESET_SYS_CPU_P			59
+#define RESET_SYS_CPU_MBIST		60
+/*					61	*/
+/*					62	*/
+/*					63	*/
+/*	RESET2					*/
+#define RESET_VD_RMEM			64
+#define RESET_AUDIN			65
+#define RESET_HDMI_TX			66
+/*					67	*/
+/*					68	*/
+/*					69	*/
+#define RESET_GE2D			70
+#define RESET_PARSER_REG		71
+#define RESET_PARSER_FETCH		72
+#define RESET_PARSER_CTL		73
+#define RESET_PARSER_TOP		74
+/*					75	*/
+/*					76	*/
+#define RESET_AO_CPU_RESET		77
+#define RESET_MALI			78
+#define RESET_HDMI_SYSTEM_RESET		79
+/*					80-95	*/
+/*	RESET3					*/
+#define RESET_RING_OSCILLATOR		96
+#define RESET_SYS_CPU			97
+#define RESET_EFUSE			98
+#define RESET_SYS_CPU_BVCI		99
+#define RESET_AIFIFO			100
+#define RESET_TVFE			101
+#define RESET_AHB_BRIDGE_CNTL		102
+/*					103	*/
+#define RESET_AUDIO_DAC			104
+#define RESET_DEMUX_TOP			105
+#define RESET_DEMUX_DES			106
+#define RESET_DEMUX_S2P_0		107
+#define RESET_DEMUX_S2P_1		108
+#define RESET_DEMUX_RESET_0		109
+#define RESET_DEMUX_RESET_1		110
+#define RESET_DEMUX_RESET_2		111
+/*					112-127	*/
+/*	RESET4					*/
+/*					128	*/
+/*					129	*/
+/*					130	*/
+/*					131	*/
+#define RESET_DVIN_RESET		132
+#define RESET_RDMA			133
+#define RESET_VENCI			134
+#define RESET_VENCP			135
+/*					136	*/
+#define RESET_VDAC			137
+#define RESET_RTC			138
+/*					139	*/
+#define RESET_VDI6			140
+#define RESET_VENCL			141
+#define RESET_I2C_MASTER_2		142
+#define RESET_I2C_MASTER_1		143
+/*					144-159	*/
+/*	RESET5					*/
+/*					160-191	*/
+/*	RESET6					*/
+#define RESET_PERIPHS_GENERAL		192
+#define RESET_PERIPHS_SPICC		193
+#define RESET_PERIPHS_SMART_CARD	194
+#define RESET_PERIPHS_SAR_ADC		195
+#define RESET_PERIPHS_I2C_MASTER_0	196
+#define RESET_SANA			197
+/*					198	*/
+#define RESET_PERIPHS_STREAM_INTERFACE	199
+#define RESET_PERIPHS_SDIO		200
+#define RESET_PERIPHS_UART_0		201
+#define RESET_PERIPHS_UART_1_2		202
+#define RESET_PERIPHS_ASYNC_0		203
+#define RESET_PERIPHS_ASYNC_1		204
+#define RESET_PERIPHS_SPI_0		205
+#define RESET_PERIPHS_SDHC		206
+#define RESET_UART_SLIP			207
+/*					208-223	*/
+/*	RESET7					*/
+#define RESET_USB_DDR_0			224
+#define RESET_USB_DDR_1			225
+#define RESET_USB_DDR_2			226
+#define RESET_USB_DDR_3			227
+/*					228	*/
+#define RESET_DEVICE_MMC_ARB		229
+/*					230	*/
+#define RESET_VID_LOCK			231
+#define RESET_A9_DMC_PIPEL		232
+/*					233-255	*/
+
+#endif
diff --git a/include/dt-bindings/reset/amlogic,meson8b-reset.h b/include/dt-bindings/reset/amlogic,meson8b-reset.h
new file mode 100644
index 0000000..614aff2
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson8b-reset.h
@@ -0,0 +1,175 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _DT_BINDINGS_AMLOGIC_MESON8B_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON8B_RESET_H
+
+/*	RESET0					*/
+#define RESET_HIU			0
+#define RESET_VLD			1
+#define RESET_IQIDCT			2
+#define RESET_MC			3
+/*					8	*/
+#define RESET_VIU			5
+#define RESET_AIU			6
+#define RESET_MCPU			7
+#define RESET_CCPU			8
+#define RESET_PMUX			9
+#define RESET_VENC			10
+#define RESET_ASSIST			11
+#define RESET_AFIFO2			12
+#define RESET_MDEC			13
+#define RESET_VLD_PART			14
+#define RESET_VIFIFO			15
+/*					16-31	*/
+/*	RESET1					*/
+/*					32	*/
+#define RESET_DEMUX			33
+#define RESET_USB_OTG			34
+#define RESET_DDR			35
+#define RESET_VDAC_1			36
+#define RESET_BT656			37
+#define RESET_AHB_SRAM			38
+#define RESET_AHB_BRIDGE		39
+#define RESET_PARSER			40
+#define RESET_BLKMV			41
+#define RESET_ISA			42
+#define RESET_ETHERNET			43
+#define RESET_ABUF			44
+#define RESET_AHB_DATA			45
+#define RESET_AHB_CNTL			46
+#define RESET_ROM_BOOT			47
+/*					48-63	*/
+/*	RESET2					*/
+#define RESET_VD_RMEM			64
+#define RESET_AUDIN			65
+#define RESET_DBLK			66
+#define RESET_PIC_DC			66
+#define RESET_PSC			66
+#define RESET_NAND			66
+#define RESET_GE2D			70
+#define RESET_PARSER_REG		71
+#define RESET_PARSER_FETCH		72
+#define RESET_PARSER_CTL		73
+#define RESET_PARSER_TOP		74
+#define RESET_HDMI_APB			75
+#define RESET_AUDIO_APB			76
+#define RESET_MEDIA_CPU			77
+#define RESET_MALI			78
+#define RESET_HDMI_SYSTEM_RESET		79
+/*					80-95	*/
+/*	RESET3					*/
+#define RESET_RING_OSCILLATOR		96
+#define RESET_SYS_CPU_0			97
+#define RESET_EFUSE			98
+#define RESET_SYS_CPU_BVCI		99
+#define RESET_AIFIFO			100
+#define RESET_AUDIO_PLL_MODULATOR	101
+#define RESET_AHB_BRIDGE_CNTL		102
+#define RESET_SYS_CPU_1			103
+#define RESET_AUDIO_DAC			104
+#define RESET_DEMUX_TOP			105
+#define RESET_DEMUX_DES			106
+#define RESET_DEMUX_S2P_0		107
+#define RESET_DEMUX_S2P_1		108
+#define RESET_DEMUX_RESET_0		109
+#define RESET_DEMUX_RESET_1		110
+#define RESET_DEMUX_RESET_2		111
+/*					112-127	*/
+/*	RESET4					*/
+#define RESET_PL310			128
+#define RESET_A5_APB			129
+#define RESET_A5_AXI			130
+#define RESET_A5			131
+#define RESET_DVIN			132
+#define RESET_RDMA			133
+#define RESET_VENCI			134
+#define RESET_VENCP			135
+#define RESET_VENCT			136
+#define RESET_VDAC_4			137
+#define RESET_RTC			138
+#define RESET_A5_DEBUG			139
+#define RESET_VDI6			140
+#define RESET_VENCL			141
+/*					142-159	*/
+/*	RESET5					*/
+#define RESET_DDR_PLL			160
+#define RESET_MISC_PLL			161
+#define RESET_SYS_PLL			162
+#define RESET_HPLL_PLL			163
+#define RESET_AUDIO_PLL			164
+#define RESET_VID2_PLL			165
+/*					166-191	*/
+/*	RESET6					*/
+#define RESET_PERIPHS_GENERAL		192
+#define RESET_PERIPHS_IR_REMOTE		193
+#define RESET_PERIPHS_SMART_CARD	194
+#define RESET_PERIPHS_SAR_ADC		195
+#define RESET_PERIPHS_I2C_MASTER_0	196
+#define RESET_PERIPHS_I2C_MASTER_1	197
+#define RESET_PERIPHS_I2C_SLAVE		198
+#define RESET_PERIPHS_STREAM_INTERFACE	199
+#define RESET_PERIPHS_SDIO		200
+#define RESET_PERIPHS_UART_0		201
+#define RESET_PERIPHS_UART_1		202
+#define RESET_PERIPHS_ASYNC_0		203
+#define RESET_PERIPHS_ASYNC_1		204
+#define RESET_PERIPHS_SPI_0		205
+#define RESET_PERIPHS_SPI_1		206
+#define RESET_PERIPHS_LED_PWM		207
+/*					208-223	*/
+/*	RESET7					*/
+/*					224-255	*/
+
+#endif
-- 
2.7.0



From wxt at rock-chips.com  Wed May 25 02:49:57 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 25 May 2016 17:49:57 +0800
Subject: [PATCH 0/5] clocksource: rockchip/timer: Support rktimer for rk3399
Message-ID: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>

This series patches had been tested on rockchip inside kernel.
In order to support the rk3399 SoC timer and turn off interrupts and IPIs to
save power in idle.
Okay, it still works bootup on rk3288/other SoCs, even though many socs hasn't used
the broadcast timer.

Easy to test for my borad.
localhost / # cat /proc/interrupts
CPU0       CPU1       CPU2       CPU3       CPU4       CPU5
1:          0          0          0          0          0          0     GICv3  29 Edge      arch_timer
...
5:          0          0          0          0          0          0     GICv3 113 Level     rk_timer
..

localhost / # cat /proc/timer_list | grep event_handler
get "event_handler:  hrtimer_interrupt"
event_handler:  tick_handle_oneshot_broadcast
event_handler:  hrtimer_interrupt

That should work for my board.



Huang Tao (5):
  dt-bindings: document rk3399 rk-timer bindings
  clocksource: rockchip: remove unnecessary clear irq before request_irq
  clocksource: rockchip: add dynamic irq flag to the timer
  clocksource: rockchip: add support for rk3399 SoC
  ARM64: dts: rockchip: add rktimer device node for rk3399

 ...chip,rk3288-timer.txt => rockchip,rk-timer.txt} |   6 +-
 arch/arm64/boot/dts/rockchip/rk3399.dtsi           |   8 ++
 drivers/clocksource/rockchip_timer.c               | 120 ++++++++++++++++-----
 3 files changed, 106 insertions(+), 28 deletions(-)
 rename Documentation/devicetree/bindings/timer/{rockchip,rk3288-timer.txt => rockchip,rk-timer.txt} (75%)

-- 
1.9.1



From wxt at rock-chips.com  Wed May 25 02:49:59 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 25 May 2016 17:49:59 +0800
Subject: [PATCH 2/5] clocksource: rockchip: remove unnecessary clear irq
 before request_irq
In-Reply-To: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1464169802-6033-3-git-send-email-wxt@rock-chips.com>

From: Huang Tao <huangtao at rock-chips.com>

rk_timer_interrupt_clear and rk_timer_disable is unnecessary before
request_irq. Timer should keep disabled before booting Linux.

Signed-off-by: Huang Tao <huangtao at rock-chips.com>
Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Heiko Stuebner <heiko at sntech.de>
Tested-by: Jianqun Xu <jay.xu at rock-chips.com>
Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 drivers/clocksource/rockchip_timer.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c
index b991b28..b93fed6 100644
--- a/drivers/clocksource/rockchip_timer.c
+++ b/drivers/clocksource/rockchip_timer.c
@@ -158,9 +158,6 @@ static void __init rk_timer_init(struct device_node *np)
 	ce->cpumask = cpumask_of(0);
 	ce->rating = 250;
 
-	rk_timer_interrupt_clear(ce);
-	rk_timer_disable(ce);
-
 	ret = request_irq(irq, rk_timer_interrupt, IRQF_TIMER, TIMER_NAME, ce);
 	if (ret) {
 		pr_err("Failed to initialize '%s': %d\n", TIMER_NAME, ret);
-- 
1.9.1



From wxt at rock-chips.com  Wed May 25 02:49:58 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 25 May 2016 17:49:58 +0800
Subject: [PATCH 1/5] dt-bindings: document rk3399 rk-timer bindings
In-Reply-To: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1464169802-6033-2-git-send-email-wxt@rock-chips.com>

From: Huang Tao <huangtao at rock-chips.com>

Add compatible string for rk3399 because which timer is a little
different from older SoCs. So rename the file name from
rockchip,rk3288-timer.txt to rockchip,rk-timer.txt.
Clarify rockchip,rk3288-timer supported SoCs.

Signed-off-by: Huang Tao <huangtao at rock-chips.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Heiko Stuebner <heiko at sntech.de>
Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 .../timer/{rockchip,rk3288-timer.txt => rockchip,rk-timer.txt}      | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
 rename Documentation/devicetree/bindings/timer/{rockchip,rk3288-timer.txt => rockchip,rk-timer.txt} (75%)

diff --git a/Documentation/devicetree/bindings/timer/rockchip,rk3288-timer.txt b/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt
similarity index 75%
rename from Documentation/devicetree/bindings/timer/rockchip,rk3288-timer.txt
rename to Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt
index 87f0b00..a41b184 100644
--- a/Documentation/devicetree/bindings/timer/rockchip,rk3288-timer.txt
+++ b/Documentation/devicetree/bindings/timer/rockchip,rk-timer.txt
@@ -1,7 +1,9 @@
-Rockchip rk3288 timer
+Rockchip rk timer
 
 Required properties:
-- compatible: shall be "rockchip,rk3288-timer"
+- compatible: shall be one of:
+  "rockchip,rk3288-timer" - for rk3066, rk3036, rk3188, rk322x, rk3288, rk3368
+  "rockchip,rk3399-timer" - for rk3399
 - reg: base address of the timer register starting with TIMERS CONTROL register
 - interrupts: should contain the interrupts for Timer0
 - clocks : must contain an entry for each entry in clock-names
-- 
1.9.1



From wxt at rock-chips.com  Wed May 25 02:50:00 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 25 May 2016 17:50:00 +0800
Subject: [PATCH 3/5] clocksource: rockchip: add dynamic irq flag to the timer
In-Reply-To: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1464169802-6033-4-git-send-email-wxt@rock-chips.com>

From: Huang Tao <huangtao at rock-chips.com>

The rockchip timer is broadcast timer. Add CLOCK_EVT_FEAT_DYNIRQ
flag and set cpumask to all cpu to save power by avoid unnecessary
wakeups and IPIs.

Signed-off-by: Huang Tao <huangtao at rock-chips.com>
Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Heiko Stuebner <heiko at sntech.de>
Tested-by: Jianqun Xu <jay.xu at rock-chips.com>
Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 drivers/clocksource/rockchip_timer.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c
index b93fed6..f3dfb1a 100644
--- a/drivers/clocksource/rockchip_timer.c
+++ b/drivers/clocksource/rockchip_timer.c
@@ -150,12 +150,13 @@ static void __init rk_timer_init(struct device_node *np)
 	}
 
 	ce->name = TIMER_NAME;
-	ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
+		       CLOCK_EVT_FEAT_DYNIRQ;
 	ce->set_next_event = rk_timer_set_next_event;
 	ce->set_state_shutdown = rk_timer_shutdown;
 	ce->set_state_periodic = rk_timer_set_periodic;
 	ce->irq = irq;
-	ce->cpumask = cpumask_of(0);
+	ce->cpumask = cpu_all_mask;
 	ce->rating = 250;
 
 	ret = request_irq(irq, rk_timer_interrupt, IRQF_TIMER, TIMER_NAME, ce);
-- 
1.9.1



From wxt at rock-chips.com  Wed May 25 02:50:01 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 25 May 2016 17:50:01 +0800
Subject: [PATCH 4/5] clocksource: rockchip: add support for rk3399 SoC
In-Reply-To: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1464169802-6033-5-git-send-email-wxt@rock-chips.com>

From: Huang Tao <huangtao at rock-chips.com>

The CONTROL register offset is different from old SoCs.
For Linux driver, there are not functional changes at all.
Let's call it v2.

Signed-off-by: Huang Tao <huangtao at rock-chips.com>
Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Heiko Stuebner <heiko at sntech.de>
Tested-by: Jianqun Xu <jay.xu at rock-chips.com>
Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 drivers/clocksource/rockchip_timer.c | 112 ++++++++++++++++++++++++++++-------
 1 file changed, 91 insertions(+), 21 deletions(-)

diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c
index f3dfb1a..7ce1d08 100644
--- a/drivers/clocksource/rockchip_timer.c
+++ b/drivers/clocksource/rockchip_timer.c
@@ -19,8 +19,9 @@
 
 #define TIMER_LOAD_COUNT0	0x00
 #define TIMER_LOAD_COUNT1	0x04
-#define TIMER_CONTROL_REG	0x10
+#define TIMER_V1_CONTROL_REG	0x10
 #define TIMER_INT_STATUS	0x18
+#define TIMER_V2_CONTROL_REG	0x1c
 
 #define TIMER_DISABLE		0x0
 #define TIMER_ENABLE		0x1
@@ -46,15 +47,26 @@ static inline void __iomem *rk_base(struct clock_event_device *ce)
 	return rk_timer(ce)->base;
 }
 
-static inline void rk_timer_disable(struct clock_event_device *ce)
+static inline void rk_timer_v1_disable(struct clock_event_device *ce)
 {
-	writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_CONTROL_REG);
+	writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_V1_CONTROL_REG);
 }
 
-static inline void rk_timer_enable(struct clock_event_device *ce, u32 flags)
+static inline void rk_timer_v1_enable(struct clock_event_device *ce, u32 flags)
 {
 	writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags,
-		       rk_base(ce) + TIMER_CONTROL_REG);
+		       rk_base(ce) + TIMER_V1_CONTROL_REG);
+}
+
+static inline void rk_timer_v2_disable(struct clock_event_device *ce)
+{
+	writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_V2_CONTROL_REG);
+}
+
+static inline void rk_timer_v2_enable(struct clock_event_device *ce, u32 flags)
+{
+	writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags,
+		       rk_base(ce) + TIMER_V2_CONTROL_REG);
 }
 
 static void rk_timer_update_counter(unsigned long cycles,
@@ -69,44 +81,82 @@ static void rk_timer_interrupt_clear(struct clock_event_device *ce)
 	writel_relaxed(1, rk_base(ce) + TIMER_INT_STATUS);
 }
 
-static inline int rk_timer_set_next_event(unsigned long cycles,
-					  struct clock_event_device *ce)
+static int rk_timer_v1_set_next_event(unsigned long cycles,
+				      struct clock_event_device *ce)
 {
-	rk_timer_disable(ce);
+	rk_timer_v1_disable(ce);
 	rk_timer_update_counter(cycles, ce);
-	rk_timer_enable(ce, TIMER_MODE_USER_DEFINED_COUNT);
+	rk_timer_v1_enable(ce, TIMER_MODE_USER_DEFINED_COUNT);
 	return 0;
 }
 
-static int rk_timer_shutdown(struct clock_event_device *ce)
+static int rk_timer_v1_shutdown(struct clock_event_device *ce)
 {
-	rk_timer_disable(ce);
+	rk_timer_v1_disable(ce);
 	return 0;
 }
 
-static int rk_timer_set_periodic(struct clock_event_device *ce)
+static int rk_timer_v1_set_periodic(struct clock_event_device *ce)
 {
-	rk_timer_disable(ce);
+	rk_timer_v1_disable(ce);
 	rk_timer_update_counter(rk_timer(ce)->freq / HZ - 1, ce);
-	rk_timer_enable(ce, TIMER_MODE_FREE_RUNNING);
+	rk_timer_v1_enable(ce, TIMER_MODE_FREE_RUNNING);
 	return 0;
 }
 
-static irqreturn_t rk_timer_interrupt(int irq, void *dev_id)
+static irqreturn_t rk_timer_v1_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *ce = dev_id;
 
 	rk_timer_interrupt_clear(ce);
 
 	if (clockevent_state_oneshot(ce))
-		rk_timer_disable(ce);
+		rk_timer_v1_disable(ce);
 
 	ce->event_handler(ce);
 
 	return IRQ_HANDLED;
 }
 
-static void __init rk_timer_init(struct device_node *np)
+static int rk_timer_v2_set_next_event(unsigned long cycles,
+				      struct clock_event_device *ce)
+{
+	rk_timer_v2_disable(ce);
+	rk_timer_update_counter(cycles, ce);
+	rk_timer_v2_enable(ce, TIMER_MODE_USER_DEFINED_COUNT);
+	return 0;
+}
+
+static int rk_timer_v2_shutdown(struct clock_event_device *ce)
+{
+	rk_timer_v2_disable(ce);
+	return 0;
+}
+
+static int rk_timer_v2_set_periodic(struct clock_event_device *ce)
+{
+	rk_timer_v2_disable(ce);
+	rk_timer_update_counter(rk_timer(ce)->freq / HZ - 1, ce);
+	rk_timer_v2_enable(ce, TIMER_MODE_FREE_RUNNING);
+	return 0;
+}
+
+static irqreturn_t rk_timer_v2_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *ce = dev_id;
+
+	rk_timer_interrupt_clear(ce);
+
+	if (clockevent_state_oneshot(ce))
+		rk_timer_v2_disable(ce);
+
+	ce->event_handler(ce);
+
+	return IRQ_HANDLED;
+}
+
+static void __init rk_timer_init(struct device_node *np,
+				 irq_handler_t rk_timer_interrupt)
 {
 	struct clock_event_device *ce = &bc_timer.ce;
 	struct clk *timer_clk;
@@ -152,9 +202,6 @@ static void __init rk_timer_init(struct device_node *np)
 	ce->name = TIMER_NAME;
 	ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
 		       CLOCK_EVT_FEAT_DYNIRQ;
-	ce->set_next_event = rk_timer_set_next_event;
-	ce->set_state_shutdown = rk_timer_shutdown;
-	ce->set_state_periodic = rk_timer_set_periodic;
 	ce->irq = irq;
 	ce->cpumask = cpu_all_mask;
 	ce->rating = 250;
@@ -177,4 +224,27 @@ out_unmap:
 	iounmap(bc_timer.base);
 }
 
-CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init);
+static void __init rk_timer_v1_init(struct device_node *np)
+{
+	struct clock_event_device *ce = &bc_timer.ce;
+
+	ce->set_next_event = rk_timer_v1_set_next_event;
+	ce->set_state_shutdown = rk_timer_v1_shutdown;
+	ce->set_state_periodic = rk_timer_v1_set_periodic;
+
+	rk_timer_init(np, rk_timer_v1_interrupt);
+}
+
+static void __init rk_timer_v2_init(struct device_node *np)
+{
+	struct clock_event_device *ce = &bc_timer.ce;
+
+	ce->set_next_event = rk_timer_v2_set_next_event;
+	ce->set_state_shutdown = rk_timer_v2_shutdown;
+	ce->set_state_periodic = rk_timer_v2_set_periodic;
+
+	rk_timer_init(np, rk_timer_v2_interrupt);
+}
+
+CLOCKSOURCE_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", rk_timer_v1_init);
+CLOCKSOURCE_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", rk_timer_v2_init);
-- 
1.9.1



From wxt at rock-chips.com  Wed May 25 02:50:02 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Wed, 25 May 2016 17:50:02 +0800
Subject: [PATCH 5/5] ARM64: dts: rockchip: add rktimer device node for rk3399
In-Reply-To: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1464169802-6033-6-git-send-email-wxt@rock-chips.com>

From: Huang Tao <huangtao at rock-chips.com>

Select rktimer0 as broadcast timer.

Signed-off-by: Huang Tao <huangtao at rock-chips.com>
Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Heiko Stuebner <heiko at sntech.de>
Tested-by: Jianqun Xu <jay.xu at rock-chips.com>

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

 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 46f325a..f0c0d76 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -492,6 +492,14 @@
 		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
+	rktimer: rktimer at ff850000 {
+		compatible = "rockchip,rk3399-timer";
+		reg = <0x0 0xff850000 0x0 0x1000>;
+		interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru PCLK_TIMER0>, <&cru SCLK_TIMER00>;
+		clock-names = "pclk", "timer";
+	};
+
 	spdif: spdif at ff870000 {
 		compatible = "rockchip,rk3399-spdif";
 		reg = <0x0 0xff870000 0x0 0x1000>;
-- 
1.9.1



From lokeshvutla at ti.com  Wed May 25 02:53:58 2016
From: lokeshvutla at ti.com (Lokesh Vutla)
Date: Wed, 25 May 2016 15:23:58 +0530
Subject: [PATCH] ARM: omap2: am437x: rollback to use
 omap3_gptimer_timer_init()
In-Reply-To: <20160412184250.GT5995@atomide.com>
References: <1460457775-23850-1-git-send-email-grygorii.strashko@ti.com>
 <20160412160448.GN5995@atomide.com> <570D3EC8.7090807@ti.com>
 <20160412184250.GT5995@atomide.com>
Message-ID: <57457636.3010409@ti.com>



On Wednesday 13 April 2016 12:12 AM, Tony Lindgren wrote:
> * Grygorii Strashko <grygorii.strashko at ti.com> [160412 11:31]:
>> On 04/12/2016 07:04 PM, Tony Lindgren wrote:
>>> * Grygorii Strashko <grygorii.strashko at ti.com> [160412 03:44]:
>>>> The commit 55ee7017ee31 ("arm: omap2: board-generic: use
>>>> omap4_local_timer_init for AM437x") unintentionally changes the
>>>> clocksource devices for AM437x from OMAP GP Timer to SyncTimer32K.
>>>>
>>>> Unfortunately, the SyncTimer32K is starving from frequency deviation
>>>> as mentioned in commit 5b5c01359152 ("ARM: OMAP2+: AM43x: Use gptimer
>>>> as clocksource") and, as reported by Franklin [1], even its monotonic
>>>> nature is under question (most probably there is a HW issue, but it's
>>>> still under investigation).
>>>>
>>>> Taking into account above facts It's reasonable to rollback to the use
>>>> of omap3_gptimer_timer_init().
>>>
>>> I thought only the ePOS EVM does not have the 32k clock available?
>>> Maybe this is the the old sync timer autocorrection drift issue?
>>>
>>
>> May be, as i mentioned in [1] it could be errata same as for Watchdog
>> Advisory 22 (or OMAP_TIMER_ERRATA_I103_I767).
>>
>> But as per commit 5b5c01359152 ("ARM: OMAP2+: AM43x: Use gptimer
>> as clocksource") there is no reason to use SyncTimer32K as
>> clocksource any way (not only on epos):
>>
>> commit 5b5c01359152f3ddaa1aa0e5d1141bc2b29ba2c5
>> Author: Rajendra Nayak <rnayak at ti.com>
>> Date:   Fri Feb 7 15:51:26 2014 +0530
>>
>>     ARM: OMAP2+: AM43x: Use gptimer as clocksource
>>     
>>     The SyncTimer in AM43x is clocked using the following two sources:
>>     1) An inaccuarte 32k clock (CLK_32KHZ) derived from PER DPLL, causing system
>>        time to go slowly (~10% deviation).
>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I don't think this statement is right. If clock from PER DPLL is
inaccurate then all the IPs which uses PER DPLL are in danger. It is the
On-Chip 32K RC Osc clock that is not an accurate clock-source as per the
design/spec.

>>     2) external 32KHz RTC clock, which may not always be available on board like
>>        in the case of ePOS EVM

Also this 32KHz RTC clock is not enabled by default and is handled by RTC.

IMO, it is better to change the clock source of sync timer to
CLK_32KHz(like it is done in case of am43x-epos). Or do you have any
other reason to shift to gptimer?

Thanks and regards,
Lokesh


From arnd at arndb.de  Wed May 25 03:06:24 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 25 May 2016 12:06:24 +0200
Subject: [PATCH] hwrng: stm32 - fix build warning
In-Reply-To: <5745085D.6000104@gmail.com>
References: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>
 <6297051.TAxtzW5OIB@wuerfel> <5745085D.6000104@gmail.com>
Message-ID: <7211115.EdoBLRGZ1i@wuerfel>

On Wednesday, May 25, 2016 7:35:17 AM CEST Sudip Mukherjee wrote:
> On Tuesday 24 May 2016 02:05 AM, Arnd Bergmann wrote:
> > On Monday, May 23, 2016 6:14:08 PM CEST Sudip Mukherjee wrote:
> >> We have been getting build warning about:
> >> drivers/char/hw_random/stm32-rng.c: In function 'stm32_rng_read':
> >> drivers/char/hw_random/stm32-rng.c:82:19: warning: 'sr' may be used
> >>                                      uninitialized in this function
> >>
> >> On checking the code it turns out that sr can never be used
> >> uninitialized as sr is getting initialized in the while loop and while
> >> loop will always execute as the minimum value of max can be 32.
> >> So just initialize sr to 0 while declaring it to silence the compiler.
> >>
> >> Signed-off-by: Sudip Mukherjee <sudip.mukherjee at codethink.co.uk>
> >> ---
> >
> > I notice that you are using a really old compiler. While this warning
> > seems to be valid in the sense that the compiler should figure out that
> > the variable might be used uninitialized, please update your toolchain
> > before reporting other such problems, as gcc-4.6 had a lot more false
> > positives that newer ones (5.x or 6.x) have.
> 
> yes, i need to upgrade gcc in my travis bot. But in my local system I am 
> having gcc-4.8.4 and there also I am having this error and i am sure 
> 4.8.4 is still being used by many people.

Right, the change from gcc-4.8 to 4.9 is what drastically changed hte
maybe-uninitialized warnings, introducing a number of additional warnings
(many of them correct) but removing many others (mostly false positives).
I tend to care only about the ones in 4.9+ for this reason. I haven't
run statistics on this in a while, but I guess we could consider turning
off this warning for 4.8 and earlier (though IIRC the switch to turn it
off only appeared in 4.9).

BTW, regarding your build infrastructure, I'd also recommend building
with 'make -s' to make the output more compact.

	Arnd


From p.zabel at pengutronix.de  Wed May 25 03:14:23 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Wed, 25 May 2016 12:14:23 +0200
Subject: [PATCH v2 1/4] reset: Add support for the Amlogic Meson SoC
 Reset Controller
In-Reply-To: <1464169758-26975-2-git-send-email-narmstrong@baylibre.com>
References: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
 <1464169758-26975-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464171263.3545.40.camel@pengutronix.de>

Hi Neil,

looks fine, just two comments below.

Am Mittwoch, den 25.05.2016, 11:49 +0200 schrieb Neil Armstrong:
> This patch adds the platform driver for the Amlogic Meson SoC Reset
> Controller.
> 
> The Meson8b and GXBB SoCs are supported.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  drivers/reset/Makefile      |   1 +
>  drivers/reset/reset-meson.c | 137 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 138 insertions(+)
>  create mode 100644 drivers/reset/reset-meson.c
> 
[...]
> diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
> new file mode 100644
> index 0000000..98087ae
> --- /dev/null
> +++ b/drivers/reset/reset-meson.c
[...]
> +static int meson_reset_reset(struct reset_controller_dev *rcdev,
> +			      unsigned long id)
> +{
> +	struct meson_reset *data =
> +		container_of(rcdev, struct meson_reset, rcdev);
> +	unsigned int bank = id / BITS_PER_REG;
> +	unsigned int offset = id % BITS_PER_REG;
> +	void *reg_addr = data->reg_base + (bank << 2);

We lost the __iomem here.

> +
> +	if (bank >= REG_COUNT)
> +		return -EINVAL;
> +
> +	writel(BIT(offset), reg_addr);
> +
> +	return 0;
> +}
> +
> +static const struct reset_control_ops meson_reset_ops = {
> +	.reset		= meson_reset_reset,
> +};
> +
> +static const struct of_device_id meson_reset_dt_ids[] = {
> +	 { .compatible = "amlogic,meson8b-reset", },
> +	 { .compatible = "amlogic,meson-gxbb-reset", },
> +	 { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
[...]
> +MODULE_ALIAS("platform:meson_reset");

And I think you can drop the MODULE_ALIAS since of: modaliases will be
generated from the MODULE_DEVICE_TABLE above. This driver is only ever
going to be probed from device tree, isn't it?

> +MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
> +MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver");
> +MODULE_LICENSE("Dual BSD/GPL");

regards
Philipp



From szabolcs.nagy at arm.com  Wed May 25 03:42:04 2016
From: szabolcs.nagy at arm.com (Szabolcs Nagy)
Date: Wed, 25 May 2016 11:42:04 +0100
Subject: [PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <5745817C.1070406@arm.com>

On 24/05/16 01:04, Yury Norov wrote:
> This version is based on kernel v4.6.
> It works with glibc-2.23, and tested with LTP.
> 
...
> ILP32 glibc branch is available here:
> https://github.com/norov/glibc/tree/ilp32-2.23
> 
> It is tested with this series with no major downsides. I will send it to 
> glibc-alpha soon, after final revise. Please review and comment it as well.

i spotted one __ilp32__ vs __ILP32__ typo in the glibc code,
i can review it in detail when there is a cleaned up patch set.

in general the approach seems ok, the ugly part is when lp64
and ilp32 share code, but ilp32 needs some tweaks compared to
the current code (e.g. x vs w regs in asm, long changed to
long long in syscalls, different relocations etc) those will
be hard to review. the naming is sometimes _be_ilp32 sometimes
ilp32_be, but let's hope there will be no new abi variant to
confuse this further.



From sricharan at codeaurora.org  Wed May 25 03:45:31 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Wed, 25 May 2016 16:15:31 +0530
Subject: [PATCH V5 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <7555154.mU2oTAdECP@wuerfel>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
 <3164695.VzCnHHyi7r@wuerfel> <000601d1b4b9$119c2410$34d46c30$@codeaurora.org>
 <7555154.mU2oTAdECP@wuerfel>
Message-ID: <000a01d1b672$93d54690$bb7fd3b0$@codeaurora.org>

Hi Arnd,

<snip..>

>> I had measured the numbers only for the full usecase path, not for the
>> reset path alone. I saw improvement of about 5% on full numbers.
>> As you said, the reset path would be called only less often
>> and might not bring a measurable change. I did not see a difference in behavior
>> when changing the sync to happen after the writes.
>
>Ok, then better not change it.
>

Ok.

>> But my understanding was that
>> the sync after the writes was required to ensure write completion.
>
>Can you cite the relevant documentation on this? Is this specific
>to the Qualcomm CPU implementation or the IOMMU? I don't think
>the ARM architecture requires anything like this in general.
>

My explanation was not correct. So the whole reason for doing the
sync here was to make sure that client is going to observe the effect
the of tlb invalidation before starting any dma operation.
But as you have explained below, if it is implicit that any operation
 from a device that could trigger a dma should have an barrier preceding
that, then the a sync here may not be needed.

>
>> >> @@ -181,7 +187,8 @@ fail:
>> >>
>> >>  static void __flush_iotlb_sync(void *cookie)
>> >>  {
>> >> -	/* To avoid a null function pointer */
>> >> +	/* To ensure completion of the TLBIVA in __flush_iotlb_range */
>> >> +	mb();
>> >>  }
>> >
>> >I don't understand the specific race from the comment.
>> >
>> >What operation comes after this that relies on __flush_iotlb_range
>> >having completed, and how does an mb() guarantee this?
>> >
>>
>> The flush_iotlb_range operation invalidates the tlb for writes to
>> pagetable and the finally calls the sync operation to ensure completion
>> of the flush and this is required before returning back to the client
>> of the iommu. In the case of this iommu, only a barrier is required to
>> ensure completion of the invalidate operation.
>
>This doesn't answer my question: What operation would a client do
>that requires the flush to be completed here? A barrier is always
>defined in terms of things that come before it in combination with
>things that come after it.
>
>Any operation that could trigger a DMA from a device is required
>to have a barrier preceding it (usually wmb() one implied by writel()),
>so this is clearly not about a driver that installs a DMA mapping
>before starting a DMA, but I don't see what else it would be.
>

Ok, so i was doing this from the idea that, other iommu drivers
 where polling on a status bit in their sync call to ensure completion
of pending TLB invalidations. But in this case, there is no status bit.
 So added a barrier to have no ordering issues before the client
triggers the dma operation. But as you say above that it is implicit that
the device would have a barrier before starting the trigger, then the
barrier here becomes redundant.

<snip..>

>> >In this case, I'd say it's better to rewrite the function to avoid the
>> >read: iova_to_phys() should be fast, and not require hardware access.
>> >Getting rid of the hardware access by using an in-memory cache for
>> >this should gain more than just removing the barriers, as an MMIO read
>> >is always slow
>>
>> Ok, you mean using the software walk through ? I will check on this to measure
>>  the latency difference. If thats true, then the iopgtable ops itself provides a
>> function for iova_to_phys conversion, so that can be used.
>
>I hadn't realized that this is a lookup in the hardware, rather than
>reading a static register. It's probably a good idea to check this
>anyway.

Ok, will measure the difference and have the better one.

Regards,
 Sricharan



From s.nawrocki at samsung.com  Wed May 25 03:49:02 2016
From: s.nawrocki at samsung.com (Sylwester Nawrocki)
Date: Wed, 25 May 2016 12:49:02 +0200
Subject: [PATCH] clk: samsung: exynos7: Don't gate CMU_{CCORE,
 FSYS0} blocks clock
In-Reply-To: <57454054.1010001@samsung.com>
References: <1460608972-13878-1-git-send-email-alim.akhtar@samsung.com>
 <570F4BE0.1010102@samsung.com> <5710E082.2050303@samsung.com>
 <5711180A.8030809@samsung.com> <57454054.1010001@samsung.com>
Message-ID: <5745831E.2060004@samsung.com>

Hi Alim,

On 05/25/2016 08:04 AM, Alim Akhtar wrote:
> Looks like this patch is not available on your tree.

Thanks for the reminder, I'll apply it next week, after 3.7-rc1 is released.

-- 
Regards,
Sylwester


From catalin.marinas at arm.com  Wed May 25 03:50:22 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 25 May 2016 11:50:22 +0100
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <57451DC6.7080106@huawei.com>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
 <20160524113727.GD25374@leverpostej> <574446B9.8040105@huawei.com>
 <20160524130255.GU4892@e104818-lin.cambridge.arm.com>
 <5744FDD0.8060504@huawei.com> <57451DC6.7080106@huawei.com>
Message-ID: <20160525105022.GC5996@e104818-lin.cambridge.arm.com>

On Wed, May 25, 2016 at 11:36:38AM +0800, Leizhen (ThunderTown) wrote:
> On 2016/5/25 9:20, Leizhen (ThunderTown) wrote:
> > On 2016/5/24 21:02, Catalin Marinas wrote:
> >> On Tue, May 24, 2016 at 08:19:05PM +0800, Leizhen (ThunderTown) wrote:
> >>> On 2016/5/24 19:37, Mark Rutland wrote:
> >>>> It looks like the test may be missing I-cache maintenance regardless of
> >>>> the semantics of mprotect in this case.
> >>>>
> >>>> I have not yet devled into flush_cache_range and how it is called.
> >>>
> >>> SYSCALL_DEFINE3(mprotect ---> mprotect_fixup ---> change_protection ---> change_protection_range --> flush_cache_range
> >>
> >> The change_protection() shouldn't need to flush the caches in
> >> flush_cache_range(). The change_pte_range() function eventually ends up
> >> calling set_pte_at() which calls __sync_icache_dcache() if the mapping
> >> is executable.
> > 
> > OK, I see.
> > But I'm afraid it entered the "if (pte_present(oldpte))" branch in
> > function change_pte_range. Because the test case called mmap to
> > create pte first, then called pte_modify. I will check it later.
> 
> I have checked that it entered "if (pte_present(oldpte))" branch.

This path eventually calls set_pte_at() via ptep_modify_prot_commit().

> But I don't known why I add flush_icache_range is OK, but add
> __sync_icache_dcache have no effect.

Do you mean you modified set_pte_at() to use flush_icache_range()
instead of __sync_icache_dcache() and it works?

What happens is that __sync_icache_dcache() only takes care of the first
time a page is mapped in user space and flushes the caches, marking it
as "clean" (PG_dcache_clean) afterwards. Subsequent changes to this
mapping or writes to it are entirely the responsibility of the user. So
if the user plans to execute instructions, it better explicitly flush
the caches (as Mark Rutland already stated in a previous reply).

I ran our internal LTP version yesterday and it was fine but didn't
realise that we actually patched mprotect04.c to include:

	__clear_cache((char *)func, (char *)func + page_sz);

just after memcpy().

(we still need to investigate whether the I-cache invalidation is
actually needed in flush_cache_range() or it's just something we forgot
to remove)

-- 
Catalin


From stanimir.varbanov at linaro.org  Wed May 25 04:13:38 2016
From: stanimir.varbanov at linaro.org (Stanimir Varbanov)
Date: Wed, 25 May 2016 14:13:38 +0300
Subject: [PATCH v2 4/9] remoteproc: Introduce Qualcomm WCNSS firmware
 loader
In-Reply-To: <1459222625-11440-5-git-send-email-bjorn.andersson@linaro.org>
References: <1459222625-11440-1-git-send-email-bjorn.andersson@linaro.org>
 <1459222625-11440-5-git-send-email-bjorn.andersson@linaro.org>
Message-ID: <574588E2.60506@linaro.org>

On 03/29/2016 06:37 AM, Bjorn Andersson wrote:
> From: Bjorn Andersson <bjorn.andersson at sonymobile.com>
> 
> This introduces the peripheral image loader, for loading WCNSS firmware
> and boot the core on e.g. MSM8974. The firmware is verified and booted
> with the help of the Peripheral Authentication System (PAS) in
> TrustZone.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson at sonymobile.com>
> Signed-off-by: Bjorn Andersson <bjorn.andersson at linaro.org>
> ---
> 
> Changes since v1:
> - Split iris definition into separate driver/dt-node
> - Move constants from DT to code
> - Make stop-state and some of interrupts optional to properly work on 8064
> - Cleaned up and made mdt loader support relocation, which is needed on 8016.
> 
>  drivers/remoteproc/Kconfig           |  12 +
>  drivers/remoteproc/Makefile          |   2 +
>  drivers/remoteproc/qcom_mdt_loader.c | 172 +++++++++++
>  drivers/remoteproc/qcom_mdt_loader.h |   7 +
>  drivers/remoteproc/qcom_wcnss.c      | 579 +++++++++++++++++++++++++++++++++++
>  drivers/remoteproc/qcom_wcnss.h      |  22 ++
>  drivers/remoteproc/qcom_wcnss_iris.c | 185 +++++++++++
>  7 files changed, 979 insertions(+)
>  create mode 100644 drivers/remoteproc/qcom_mdt_loader.c
>  create mode 100644 drivers/remoteproc/qcom_mdt_loader.h
>  create mode 100644 drivers/remoteproc/qcom_wcnss.c
>  create mode 100644 drivers/remoteproc/qcom_wcnss.h
>  create mode 100644 drivers/remoteproc/qcom_wcnss_iris.c
> 

<cut>

> +
> +static int wcnss_remove(struct platform_device *pdev)
> +{
> +	struct qcom_wcnss *wcnss = platform_get_drvdata(pdev);
> +
> +	of_platform_depopulate(&pdev->dev);
> +
> +	qcom_smem_state_put(wcnss->state);
> +	rproc_put(wcnss->rproc);

might be need to call rproc_del() too ?

> +
> +	return 0;
> +}
> +

<cut>

-- 
regards,
Stan


From dennis.chen at arm.com  Wed May 25 04:16:14 2016
From: dennis.chen at arm.com (Dennis Chen)
Date: Wed, 25 May 2016 19:16:14 +0800
Subject: [PATCH] arm64:efi fix the format of debug message from efi
Message-ID: <1464174974-4733-1-git-send-email-dennis.chen@arm.com>

When enable debug of efi and memblock with 'efi=debug memblock=debug' appended
to the kernel command line, the debug message output for earyly_con looks like:
[    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] memblock_add: [0x00008000000000-0x00008001e7ffff] flags 0x0 early_init_dt_add_memory_arch+0x54/0x5c
[    0.000000] *
...
This patch is trying to fix the above output messed up by memblock_add(), so we can get below debug mesg looks
more formally after applied:
[    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] memblock_add: [0x00008000000000-0x00008001e7ffff] flags 0x0 early_init_dt_add_memory_arch+0x54/0x5c
...

Signed-off-by: Dennis Chen <dennis.chen at arm.com>
Acked-by: Mark Rutland <mark.rutland at arm.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Steve Capper <steve.capper at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
---
 drivers/firmware/efi/arm-init.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index a850cbc..272f674 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -174,6 +174,7 @@ static __init void reserve_regions(void)
 {
        efi_memory_desc_t *md;
        u64 paddr, npages, size;
+       int resv;

        if (efi_enabled(EFI_DBG))
                pr_info("Processing EFI memory map:\n");
@@ -190,12 +191,16 @@ static __init void reserve_regions(void)
                paddr = md->phys_addr;
                npages = md->num_pages;

+               resv = is_reserve_region(md);
                if (efi_enabled(EFI_DBG)) {
                        char buf[64];

                        pr_info("  0x%012llx-0x%012llx %s%s",
                                paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
-                               efi_md_typeattr_format(buf, sizeof(buf), md));
+                               efi_md_typeattr_format(buf, sizeof(buf), md),
+                               resv ? "*" : "");
+
+                       pr_cont("\n");
                }

                memrange_efi_to_native(&paddr, &npages);
@@ -204,14 +209,9 @@ static __init void reserve_regions(void)
                if (is_normal_ram(md))
                        early_init_dt_add_memory_arch(paddr, size);

-               if (is_reserve_region(md)) {
+               if (resv)
                        memblock_mark_nomap(paddr, size);
-                       if (efi_enabled(EFI_DBG))
-                               pr_cont("*");
-               }

-               if (efi_enabled(EFI_DBG))
-                       pr_cont("\n");
        }

        set_bit(EFI_MEMMAP, &efi.flags);
--
2.7.4

IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.



From mark.rutland at arm.com  Wed May 25 04:25:49 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 25 May 2016 12:25:49 +0100
Subject: [PATCH] arm64:efi fix the format of debug message from efi
In-Reply-To: <1464174974-4733-1-git-send-email-dennis.chen@arm.com>
References: <1464174974-4733-1-git-send-email-dennis.chen@arm.com>
Message-ID: <20160525112549.GJ1337@leverpostej>

On Wed, May 25, 2016 at 07:16:14PM +0800, Dennis Chen wrote:
> When enable debug of efi and memblock with 'efi=debug memblock=debug' appended
> to the kernel command line, the debug message output for earyly_con looks like:
> [    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] memblock_add: [0x00008000000000-0x00008001e7ffff] flags 0x0 early_init_dt_add_memory_arch+0x54/0x5c
> [    0.000000] *
> ...
> This patch is trying to fix the above output messed up by memblock_add(), so we can get below debug mesg looks
> more formally after applied:
> [    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] memblock_add: [0x00008000000000-0x00008001e7ffff] flags 0x0 early_init_dt_add_memory_arch+0x54/0x5c
> ...
> 
> Signed-off-by: Dennis Chen <dennis.chen at arm.com>
> Acked-by: Mark Rutland <mark.rutland at arm.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Steve Capper <steve.capper at arm.com>
> Cc: Will Deacon <will.deacon at arm.com>
> ---
>  drivers/firmware/efi/arm-init.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
> index a850cbc..272f674 100644
> --- a/drivers/firmware/efi/arm-init.c
> +++ b/drivers/firmware/efi/arm-init.c
> @@ -174,6 +174,7 @@ static __init void reserve_regions(void)
>  {
>         efi_memory_desc_t *md;
>         u64 paddr, npages, size;
> +       int resv;
> 
>         if (efi_enabled(EFI_DBG))
>                 pr_info("Processing EFI memory map:\n");
> @@ -190,12 +191,16 @@ static __init void reserve_regions(void)
>                 paddr = md->phys_addr;
>                 npages = md->num_pages;
> 
> +               resv = is_reserve_region(md);
>                 if (efi_enabled(EFI_DBG)) {
>                         char buf[64];
> 
>                         pr_info("  0x%012llx-0x%012llx %s%s",
>                                 paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
> -                               efi_md_typeattr_format(buf, sizeof(buf), md));
> +                               efi_md_typeattr_format(buf, sizeof(buf), md),
> +                               resv ? "*" : "");
> +
> +                       pr_cont("\n");

As I mentioned in my (off-list) mail previously, please fold this
pr_cont in. You just need to move the "\n" into the end of the format
string for the pr_info.

Thanks,
Mark,


From andre.przywara at arm.com  Wed May 25 04:37:57 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 25 May 2016 12:37:57 +0100
Subject: [PATCH v4 06/12] KVM: arm64: implement basic ITS register handlers
In-Reply-To: <5706704C.5060307@arm.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-7-git-send-email-andre.przywara@arm.com>
 <5706704C.5060307@arm.com>
Message-ID: <671b7144-7929-df7b-14f4-20dc6a32abdb@arm.com>

Hi Marc,

this series is mostly obsolete now, but I wanted to elaborate on the
locking scheme, which hasn't changed.

On 07/04/16 15:35, Marc Zyngier wrote:
> On 26/03/16 02:14, Andre Przywara wrote:

....

>> --- a/virt/kvm/arm/vgic/its-emul.c
>> +++ b/virt/kvm/arm/vgic/its-emul.c
>> @@ -31,23 +31,263 @@
>>  #include "vgic.h"
>>  #include "vgic_mmio.h"
>>  
>> +#define BASER_BASE_ADDRESS(x) ((x) & 0xfffffffff000ULL)
>> +
>> +static int vgic_mmio_read_its_ctlr(struct kvm_vcpu *vcpu,
>> +				   struct kvm_io_device *this,
>> +				   gpa_t addr, int len, void *val)
>> +{
>> +	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>> +	u32 reg;
>> +
>> +	reg = GITS_CTLR_QUIESCENT;
> 
> So your ITS is always in a quiescent state? Even when you're processing
> the command queue? You'll have to convince me...

Does QUIESCENT actually cover the command queue status? I was under the
impression that this is purely to cope with distributed implementations
and the possible delays caused by propagating commands.
If not so, I can surely take the lock here and respect
(creadr == cwriter) upon setting the bit.

> 
>> +	if (its->enabled)
>> +		reg |= GITS_CTLR_ENABLE;
>> +
>> +	write_mask32(reg, addr & 3, len, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int vgic_mmio_write_its_ctlr(struct kvm_vcpu *vcpu,
>> +				    struct kvm_io_device *this,
>> +				    gpa_t addr, int len, const void *val)
>> +{
>> +	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>> +	struct vgic_io_device *iodev = container_of(this,
>> +						    struct vgic_io_device, dev);
>> +
>> +        if (addr - iodev->base_addr == 0)
> 
> whitespace issue.
> 
>> +		its->enabled = !!(*(u8*)val & GITS_CTLR_ENABLE);
>> +
>> +	return 0;
>> +}
>> +
>> +static int vgic_mmio_read_its_typer(struct kvm_vcpu *vcpu,
>> +				    struct kvm_io_device *this,
>> +				    gpa_t addr, int len, void *val)
>> +{
>> +	u64 reg = GITS_TYPER_PLPIS;
>> +
>> +	/*
>> +	 * We use linear CPU numbers for redistributor addressing,
>> +	 * so GITS_TYPER.PTA is 0.
>> +	 * To avoid memory waste on the guest side, we keep the
>> +	 * number of IDBits and DevBits low for the time being.
>> +	 * This could later be made configurable by userland.
>> +	 * Since we have all collections in linked list, we claim
>> +	 * that we can hold all of the collection tables in our
>> +	 * own memory and that the ITT entry size is 1 byte (the
>> +	 * smallest possible one).
> 
> All of this is going to bite us when we want to implement migration,
> specially the HW collection bit.

How so? Clearly we keep the number of VCPUs constant, so everything
guest visible stays the same even upon migrating to a much different
host? Or are we talking about different things here?

> 
>> +	 */
>> +	reg |= 0xff << GITS_TYPER_HWCOLLCNT_SHIFT;
>> +	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
>> +	reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
>> +
>> +	write_mask64(reg, addr & 7, len, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int vgic_mmio_read_its_iidr(struct kvm_vcpu *vcpu,
>> +				   struct kvm_io_device *this,
>> +				   gpa_t addr, int len, void *val)
>> +{
>> +	u32 reg = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
>> +
>> +	write_mask32(reg, addr & 3, len, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int vgic_mmio_read_its_idregs(struct kvm_vcpu *vcpu,
>> +				     struct kvm_io_device *this,
>> +				     gpa_t addr, int len, void *val)
>> +{
>> +	struct vgic_io_device *iodev = container_of(this,
>> +						    struct vgic_io_device, dev);
>> +	u32 reg = 0;
>> +	int idreg = (addr & ~3) - iodev->base_addr + GITS_IDREGS_BASE;
>> +
>> +	switch (idreg) {
>> +	case GITS_PIDR2:
>> +		reg = GIC_PIDR2_ARCH_GICv3;
> 
> Are we leaving the lowest 4 bits to zero?

I couldn't stuff "42" in 4 bits, so: yes ;-)

>> +		break;
>> +	case GITS_PIDR4:
>> +		/* This is a 64K software visible page */
>> +		reg = 0x40;
> 
> Same question.
> 
> Also, how about all the others PIDR registers?

I guess I was halfway undecided between going with the pure
architectural requirements (which only mandate bits 7:4 in PIDR2) and
complying with the recommendation later in the spec.
So I will just fill PIDR0, PIDR2 and the rest of PIDR2 as well.

>> +		break;
>> +	/* Those are the ID registers for (any) GIC. */
>> +	case GITS_CIDR0:
>> +		reg = 0x0d;
>> +		break;
>> +	case GITS_CIDR1:
>> +		reg = 0xf0;
>> +		break;
>> +	case GITS_CIDR2:
>> +		reg = 0x05;
>> +		break;
>> +	case GITS_CIDR3:
>> +		reg = 0xb1;
>> +		break;
>> +	}
> 
> Given that these values are directly taken from the architecture, and
> seem common to the whole GICv3 architecture when implemented by ARM, we
> could have a common handler for the whole GICv3 implementatuin. Not a
> bit deal though.

Agreed.

>> +
>> +	write_mask32(reg, addr & 3, len, val);
>> +
>> +	return 0;
>> +}
>> +
>> +/*
>> + * This function is called with both the ITS and the distributor lock dropped,
>> + * so the actual command handlers must take the respective locks when needed.
>> + */
>> +static int vits_handle_command(struct kvm_vcpu *vcpu, u64 *its_cmd)
>> +{
>> +	return -ENODEV;
>> +}
>> +
>> +static int vgic_mmio_read_its_cbaser(struct kvm_vcpu *vcpu,
>> +				    struct kvm_io_device *this,
>> +				    gpa_t addr, int len, void *val)
>> +{
>> +	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>> +
>> +	write_mask64(its->cbaser, addr & 7, len, val);
>> +
>> +	return 0;
>> +}
>> +
>> +static int vgic_mmio_write_its_cbaser(struct kvm_vcpu *vcpu,
>> +				      struct kvm_io_device *this,
>> +				      gpa_t addr, int len, const void *val)
>> +{
>> +	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>> +
>> +	if (its->enabled)
>> +		return 0;
>> +
>> +	its->cbaser = mask64(its->cbaser, addr & 7, len, val);
>> +	its->creadr = 0;
> 
> Don't you need to acquire the command queue lock here?

I don't think so, because we "return 0;" above if the ITS is enabled,
which means that nothing is going on at the moment.
But I guess I can just take the lock anyway to be sure.

>> +
>> +	return 0;
>> +}
>> +
>> +static int its_cmd_buffer_size(struct kvm *kvm)
>> +{
>> +	struct vgic_its *its = &kvm->arch.vgic.its;
>> +
>> +	return ((its->cbaser & 0xff) + 1) << 12;
>> +}
>> +
>> +static gpa_t its_cmd_buffer_base(struct kvm *kvm)
>> +{
>> +	struct vgic_its *its = &kvm->arch.vgic.its;
>> +
>> +	return BASER_BASE_ADDRESS(its->cbaser);
>> +}
>> +
>> +/*
>> + * By writing to CWRITER the guest announces new commands to be processed.
>> + * Since we cannot read from guest memory inside the ITS spinlock, we
>> + * iterate over the command buffer (with the lock dropped) until the read
>> + * pointer matches the write pointer. Other VCPUs writing this register in the
>> + * meantime will just update the write pointer, leaving the command
>> + * processing to the first instance of the function.
>> + */
>> +static int vgic_mmio_write_its_cwriter(struct kvm_vcpu *vcpu,
>> +				       struct kvm_io_device *this,
>> +				       gpa_t addr, int len, const void *val)
>> +{
>> +	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>> +	struct vgic_its *its = &dist->its;
>> +	gpa_t cbaser = its_cmd_buffer_base(vcpu->kvm);
>> +	u64 cmd_buf[4];
>> +	u32 reg;
>> +	bool finished;
>> +
>> +	reg = mask64(its->cwriter & 0xfffe0, addr & 7, len, val);
>> +	reg &= 0xfffe0;
>> +	if (reg > its_cmd_buffer_size(vcpu->kvm))
>> +		return 0;
>> +
>> +	spin_lock(&its->lock);
>> +
>> +	/*
>> +	 * If there is still another VCPU handling commands, let this
>> +	 * one pick up the new CWRITER and process "our" new commands as well.
>> +	 */
> 
> How do you detect that condition? All I see is a massive race here, with
> two threads processing the queue in parallel, possibly corrupting each
> other's data.
> 
> Please explain why you think this is safe.

OK, here you go: Actually we are handling the command queue
synchronously: The first writer to CWRITER will end up here and will
iterate over all commands below. From the guests point of view it will
take some time to do the CWRITER MMIO write, but upon the writel
returning the queue is actually already empty again.
That means that any _sane_ guest will _never_ trigger the case where two
threads/VCPUs are handling the queue, because a concurrent write to
CWRITER without a lock in the guest would be broken by design.

However I am not sure we can rely on this, so I added this precaution
scheme:
The first writer takes our ITS (emulation) lock and examines cwriter and
creadr to see if they are equal. If they are, then the queue is
currently empty, which means we are the first one and need to take care
of the commands. We update our copy of cwriter (now marking the queue as
non-empty) and drop the lock. As we kept the queue-was-empty status in a
local variable, we now can start iterating through the queue. We only
take the lock briefly when really needed in this process (for instance
when one command has been processed and creadr is incremented).

If now a second VCPU writes CWRITER, we also take the lock and compare
creadr and cwriter. Now they are different, because the first thread is
still busy with handling the commands and hasn't finished yet.
So we set our local "finished" to true. Also we update cwriter to the
new value, then drop the lock. The while loop below will not be entered
in this thread and we return to the guest.
Now the first thread has handled another command, takes the lock to
increase creadr and compares it with cwriter. Without the second writer
it may have been finished already, but now cwriter has grown, so it will
just carry on with handling the commands.

A bit like someone washing the dishes while another person adds some
more dirty plates to the pile ;-)

But again: this is just insurance against broken guests and due to guest
locking requirements this would actually never happen.

Does that make sense?

Btw: I have finished rebasing this upon the new VGIC and will post a new
version after -rc1.

Cheers,
Andre.


From linus.walleij at linaro.org  Wed May 25 04:55:28 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 25 May 2016 13:55:28 +0200
Subject: [PATCH 1/3] ARM: dts: Ux500: move compatible string to chipset
Message-ID: <1464177328-27416-1-git-send-email-linus.walleij@linaro.org>

Move the compatible string "stericsson,ab8500" from the board
definitions into the main node in the chipset file where it
belongs.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 arch/arm/boot/dts/ste-dbx5x0.dtsi  | 1 +
 arch/arm/boot/dts/ste-href.dtsi    | 1 -
 arch/arm/boot/dts/ste-snowball.dts | 1 -
 3 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi
index 6ae56838bd3a..d309314f3a36 100644
--- a/arch/arm/boot/dts/ste-dbx5x0.dtsi
+++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi
@@ -604,6 +604,7 @@
 				#interrupt-cells = <2>;
 
 				ab8500_gpio: ab8500-gpio {
+					compatible = "stericsson,ab8500-gpio";
 					gpio-controller;
 					#gpio-cells = <2>;
 				};
diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi
index 6d8ce154347e..48dc38482633 100644
--- a/arch/arm/boot/dts/ste-href.dtsi
+++ b/arch/arm/boot/dts/ste-href.dtsi
@@ -223,7 +223,6 @@
 		prcmu at 80157000 {
 			ab8500 {
 				ab8500-gpio {
-					compatible = "stericsson,ab8500-gpio";
 				};
 
 				ab8500-regulators {
diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts
index 36e84efc401c..37ae6166b0e6 100644
--- a/arch/arm/boot/dts/ste-snowball.dts
+++ b/arch/arm/boot/dts/ste-snowball.dts
@@ -352,7 +352,6 @@
 
 			ab8500 {
 				ab8500-gpio {
-					compatible = "stericsson,ab8500-gpio";
 				};
 
 				ext_regulators: ab8500-ext-regulators {
-- 
2.4.11



From linus.walleij at linaro.org  Wed May 25 04:55:39 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 25 May 2016 13:55:39 +0200
Subject: [PATCH 2/3] ARM: dts: Ux500: name the GPIO lines on Snowball
Message-ID: <1464177339-27463-1-git-send-email-linus.walleij@linaro.org>

Using the new line naming mechanism from the GPIO subsystem, name
the GPIO lines on the Snowball board that are connected as
GPIO on this design.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 arch/arm/boot/dts/ste-snowball.dts | 83 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)

diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts
index 37ae6166b0e6..b3df1c60d465 100644
--- a/arch/arm/boot/dts/ste-snowball.dts
+++ b/arch/arm/boot/dts/ste-snowball.dts
@@ -95,6 +95,70 @@
 	};
 
 	soc {
+		/* Name the GPIO muxed rails on the Snowball board */
+		gpio at 8012e000 {
+			/* GPIOs 0 - 31 */
+			gpio-line-names = "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "",
+				     "AP_GPIO31";
+		};
+
+		gpio at 8012e080 {
+			/* GPIOs 32 - 63 */
+			gpio-line-names = "USR PB", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "";
+		};
+
+		gpio at 8000e000 {
+			/* GPIOs 64 - 95 */
+			gpio-line-names = "", "", "", "", "AP_GPIO68", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "";
+		};
+
+		gpio at 8000e100 {
+			/* GPIOs 128 - 159 */
+			gpio-line-names = "", "", "", "", "", "", "", "",
+				     "", "", "", "", "IRQ_LAN", "RSTn_LAN",
+				     "USR_LED", "", "", "", "", "", "",
+				     "", "", "AP_GPIO151", "AP_GPIO152",
+				     "", "", "", "", "", "", "";
+		};
+
+		gpio at 8000e180 {
+			/* GPIOs 160 - 191 */
+			gpio-line-names = "", "AP_GPIO161", "AP_GPIO162",
+				     "ACCELEROMETER_INT1_RDY",
+				     "ACCELEROMETER_INT2", "MAG_DRDY",
+				     "GYRO_DRDY", "RSTn_MLC", "RSTn_SLC",
+				     "GYRO_INT", "UART_WAKE", "GBF_RESET",
+				     "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "";
+		};
+
+		gpio at 8011e000 {
+			/* GPIOs 192 - 223 */
+			gpio-line-names = "HDTV_INTn", "", "", "", "HDTV_RST",
+				     "", "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "", "",
+				     "WLAN_RESETN", "WLAN_IRQ", "MMC_EN",
+				     "MMC_CD", "", "", "", "", "";
+		};
+
+		gpio at 8011e080 {
+			/* GPIOs 224 - 255 */
+			gpio-line-names = "", "", "", "", "SD_SEL", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "";
+		};
+
 		usb_per5 at a03e0000 {
 			pinctrl-names = "default", "sleep";
 			pinctrl-0 = <&musb_default_mode>;
@@ -352,6 +416,25 @@
 
 			ab8500 {
 				ab8500-gpio {
+					/*
+					 * AB8500 GPIOs are numbered starting from 1, so the first
+					 * index 0 is what in the datasheet is called "GPIO1", and
+					 * the second is "GPIO2" and so forth. Confusingly, the
+					 * Snowball schematic then names the "GPIO2" line "PM_GPIO1".
+					 * while later naming "GPIO4" as "PM_GPIO4".
+					 */
+					gpio-line-names = "", /* AB8500 GPIO1 */
+						     "PM_GPIO1", /* AB8500 GPIO2 */
+						     "WLAN_CLK_REQ", /* AB8500 GPIO3 */
+						     "PM_GPIO4", /* AB8500 GPIO4 */
+						     "", "", "", "", "", "", "", "", "", "", "",
+						     "EN_3V6", /* AB8500 GPIO16 */
+						     "", "", "", "" ,"", "", "", "", "",
+						     "EN_3V3", /* AB8500 GPIO26 */
+						     "", "", "", "", "", "", "", "", "", "", "", "", "",
+						     "PM_GPIO40", /* AB8500 GPIO40 */
+						     "PM_GPIO41", /* AB8500 GPIO41 */
+						     "PM_GPIO42"; /* AB8500 GPIO42 */
 				};
 
 				ext_regulators: ab8500-ext-regulators {
-- 
2.4.11



From linus.walleij at linaro.org  Wed May 25 04:55:46 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 25 May 2016 13:55:46 +0200
Subject: [PATCH 3/3] ARM: dts: UX500: name the GPIO lines on HREFv60plus
Message-ID: <1464177346-27510-1-git-send-email-linus.walleij@linaro.org>

Using the new line naming mechanism from the GPIO subsystem, name
the GPIO lines on the HREFv60plus board that are connected as
GPIO on this design.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 arch/arm/boot/dts/ste-hrefv60plus.dtsi | 120 +++++++++++++++++++++++++++++++++
 1 file changed, 120 insertions(+)

diff --git a/arch/arm/boot/dts/ste-hrefv60plus.dtsi b/arch/arm/boot/dts/ste-hrefv60plus.dtsi
index 45d7af326718..7187676836be 100644
--- a/arch/arm/boot/dts/ste-hrefv60plus.dtsi
+++ b/arch/arm/boot/dts/ste-hrefv60plus.dtsi
@@ -18,6 +18,126 @@
 	compatible = "st-ericsson,hrefv60+", "st-ericsson,u8500";
 
 	soc {
+		/* Name the GPIO muxed rails on the HREF boards */
+		gpio at 8012e000 {
+			/* GPIOs 0 - 31 */
+			gpio-line-names =
+				     /* GPIO0,1 used for UART0 BT RX/TX */
+				     "", "",
+				     "UART_WAKE",
+				     "BT_WAKE",
+				     "",
+				     "SDMMC_1V8_3V_SEL",
+				     "FLASH_LED_SYNC (FLASH_CTRL_0)",
+				     "XENON_READY (FLASH_CTRL_1)",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "",
+				     "",
+				     "FLASH_LED_EN (FLASH_CTRL_3)",
+				     "", "",
+				     "", "", "", "", "",
+				     /* Used by UART2 (console) */
+				     "", "",
+				     "MAGNETOMETER_INT";
+		};
+
+		gpio at 8012e080 {
+			/* GPIOs 32 - 63 */
+			gpio-line-names =
+				     "MAGNETOMETER_DRDY",
+				     "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "";
+		};
+
+		gpio at 8000e000 {
+			/* GPIOs 64 - 95 */
+			gpio-line-names = "XENON_EN2 (FLASH_CTRL_4)",
+				     "DISP1_RST",
+				     "DISP2_RST",
+				     "TOUCH_INT2",
+				     "LCD_VSI0_A",
+				     "LCD_VSI1_A",
+				     /* GPIO 70-77 used for ETM */
+				     "", "", "", "", "", "", "", "",
+				     /* GPIO 78-81 used for YCBCR */
+				     "", "", "", "",
+				     "ACCELEROMETER_INT1_RDY",
+				     "ACCELEROMETER_INT2",
+				     "TOUCH_INT",
+				     "WLAN_ENA",
+				     "", "", "", "", "",
+				     "FORCE_SENSING_INT",
+				     "FORCE_SENSING_RESET",
+				     "", "",
+				     "SDMMC_CD";
+		};
+
+		gpio at 8000e080 {
+			/* GPIOs 96 - 127 */
+			gpio-line-names = "",
+				     "FORCE_SENSING_WU",
+				     "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "";
+		};
+
+		gpio at 8000e100 {
+			/* GPIOs 128 - 159 */
+			gpio-line-names = "", "", "", "", "", "", "", "",
+				     "", "", "",
+				     "DIPRO_INT", /* GPIO139 */
+				     "XSHUTDOWN_SECONDARY_SENSOR",
+				     "XSHUTDOWN_PRIMARY_SENSOR",
+				     "NFC_RST (NFC_CTRL_",
+				     "TOUCH_RST",
+				     "NFC_IRQ (NFC_CTRL_1)",
+				     "HAL_SW",
+				     "TOUCH_RST2",
+				     "", "",
+				     "VAUDIO_HF_EN", /* GPIO149 */
+				     "", "", "", "", "", "", "", "", "", "";
+		};
+
+		gpio at 8000e180 {
+			/* GPIOs 160 - 191 */
+			gpio-line-names = "", "", "", "", "", "", "", "",
+				     "",
+				     "SDMMC_EN",
+				     "XENON_CHARGE (FLASH_CONTROL_5)",
+				     "GBF_ENA_RESET",
+				     "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "";
+		};
+
+		gpio at 8011e000 {
+			/* GPIOs 192 - 223 */
+			gpio-line-names = "HDTV_INTN",
+				     "", "", "",
+				     "HDTV_RSTN",
+				     "", "", "",
+				     "", /* GPIO200 */
+				     "", "", "", "", "", "", "",
+				     /* GPIO208-216 used for WGBF_MC1 */
+				     "", "", "", "", "", "", "", "", "",
+				     "SW_FRONT_PROXIMITY", /* GPIO217 */
+				     "KPD_CTRL_INT", /* Keypad controller */
+				     "", "", "", "", "";
+		};
+
+		gpio at 8011e080 {
+			/* GPIOs 224 - 255 */
+			gpio-line-names = "", "",
+				     "HSIT_ACWAKE0",
+				     "", "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "",
+				     "", "", "", "", "", "", "", "";
+		};
+
 		// External Micro SD slot
 		sdi0_per1 at 80126000 {
 			cd-gpios  = <&gpio2 31 GPIO_ACTIVE_HIGH>; // 95
-- 
2.4.11



From maxime.ripard at free-electrons.com  Wed May 25 05:01:56 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 25 May 2016 14:01:56 +0200
Subject: [PATCH 06/20] drm/sun4i: allow dclk to modify its parent rate
In-Reply-To: <CAGb2v65tiUt9FvmJ2RaZdXaAFEznKZZjycO+tZcP-4spOAjObQ@mail.gmail.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-7-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v65tiUt9FvmJ2RaZdXaAFEznKZZjycO+tZcP-4spOAjObQ@mail.gmail.com>
Message-ID: <20160525120156.GA9232@lukather>

On Tue, May 17, 2016 at 01:18:44AM +0800, Chen-Yu Tsai wrote:
> Hi,
> 
> On Mon, May 16, 2016 at 8:47 PM, Maxime Ripard
> <maxime.ripard at free-electrons.com> wrote:
> > The pixel clock being only a divider of its parent clock, depending on the
> > resolution, it's expected to change its parent rate. Add that flag so that
> > the clock framework knows it.
> 
> This should be squashed into the previous patch. Otherwise, the previous one
> doesn't really fix things, and probably makes things worse as it assumes the
> parent clock would be changed.

Merged the two patches and applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160525/d359e38d/attachment.sig>

From maxime.ripard at free-electrons.com  Wed May 25 05:06:37 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 25 May 2016 14:06:37 +0200
Subject: [PATCH 08/20] drm/sun4i: rgb: panel is an error pointer
In-Reply-To: <CAGb2v6485nF_e9GeANLsy2Rq1XOn4nV5wD_eWskTmL2ME316+w@mail.gmail.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-9-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v6485nF_e9GeANLsy2Rq1XOn4nV5wD_eWskTmL2ME316+w@mail.gmail.com>
Message-ID: <20160525120637.GB9232@lukather>

On Tue, May 17, 2016 at 11:51:36AM +0800, Chen-Yu Tsai wrote:
> Hi,
> 
> On Mon, May 16, 2016 at 8:47 PM, Maxime Ripard
> <maxime.ripard at free-electrons.com> wrote:
> > In case of an error, our pointer to the drm_panel structure attached to our
> > encoder will hold an error pointer, not a NULL pointer.
> >
> > Make sure we check the right thing.
> >
> > Fixes: 29e57fab97fc ("drm: sun4i: Add RGB output")
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/gpu/drm/sun4i/sun4i_rgb.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > index 923f55039cb1..b46d2c15dc95 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> > @@ -217,7 +217,7 @@ int sun4i_rgb_init(struct drm_device *drm)
> >         int ret;
> >
> >         /* If we don't have a panel, there's no point in going on */
> > -       if (!tcon->panel)
> > +       if (IS_ERR(tcon->panel))
> 
> Without the next patch, tcon->panel could be the result of of_drm_find_panel(),
> which could be NULL.
> 
> Use IS_ERR_OR_NULL here, or reorder/squash the patches.

Switched the order, and applied both, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160525/c766743b/attachment.sig>

From maxime.ripard at free-electrons.com  Wed May 25 05:09:15 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 25 May 2016 14:09:15 +0200
Subject: [PATCH 09/20] drm/sun4i: defer only if we didn't find our panel
In-Reply-To: <CAGb2v655q_w8s7Eg8xnpzdX9PDxSEhRLvMu3bNOd==U4APgg0Q@mail.gmail.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-10-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v655q_w8s7Eg8xnpzdX9PDxSEhRLvMu3bNOd==U4APgg0Q@mail.gmail.com>
Message-ID: <20160525120915.GC9232@lukather>

On Tue, May 17, 2016 at 11:52:10AM +0800, Chen-Yu Tsai wrote:
> Hi,
> 
> On Mon, May 16, 2016 at 8:47 PM, Maxime Ripard
> <maxime.ripard at free-electrons.com> wrote:
> > Our code currently defers our probe on any error, even if we were not
> > expecting to have one at all.
> >
> > Make sure we return -EPROBE_DEFER only when we were supposed to have a
> > panel, but it's not probed yet.
> >
> > Fixes: 29e57fab97fc ("drm: sun4i: Add RGB output")
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/gpu/drm/sun4i/sun4i_tcon.c | 15 ++++++++-------
> >  1 file changed, 8 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > index 9f19b0e08560..eed6a9e8d9a6 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > @@ -429,7 +429,7 @@ static struct drm_panel *sun4i_tcon_find_panel(struct device_node *node)
> >                 return ERR_PTR(-EINVAL);
> >         }
> >
> > -       return of_drm_find_panel(remote);
> > +       return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER);
> 
> There's also a typo in the DRM_DEBUG_DRIVER call a few lines up. Could you
> fix it as well?

Done, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160525/7695e4da/attachment.sig>

From k.kozlowski at samsung.com  Wed May 25 05:13:20 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 25 May 2016 14:13:20 +0200
Subject: [PATCH 1/2] drm/exynos: g2d: Add support for old S5Pv210 type
In-Reply-To: <57447BDA.2000004@math.uni-bielefeld.de>
References: <1464096493-13378-1-git-send-email-k.kozlowski@samsung.com>
 <57445BE5.7060702@math.uni-bielefeld.de> <57445E16.90301@samsung.com>
 <57447BDA.2000004@math.uni-bielefeld.de>
Message-ID: <574596E0.4090104@samsung.com>

On 05/24/2016 06:05 PM, Tobias Jakobi wrote:
> Hello Krzysztof,
> 
> 
> Krzysztof Kozlowski wrote:
>> On 05/24/2016 03:49 PM, Tobias Jakobi wrote:
>>> Hello Krzysztof,
>>>
>>> are you sure that these are the only differences. Because AFAIK there
>>> are quite a few more:
>>> - DMA submission of commands
>>> - blend mode / rounding
>>> - solid fill
>>> - YCrCb support
>>> - and probably more
>>>
>>> One would need to add least split the command list parser into a v3 and
>>> v41 version to accomodate for the differences. In fact userspace/libdrm
>>> would need to know which hw type it currently uses, but you currently
>>> always return 4.1 in the corresponding ioctl.
>>
>> Eh, so probably my patch does not cover fully the support for v3 G2D. I
>> looked mostly at the differences between v3 and v4 in the s5p-g2d driver
>> itself. However you are right that this might be not sufficient because
>> exynos-g2d moved forward and is different than s5p-g2d.
>>
>>> Krzysztof Kozlowski wrote:
>>>> The non-DRM s5p-g2d driver supports two versions of G2D: v3.0 on
>>>> S5Pv210 and v4.x on Exynos 4x12 (or newer). The driver for 3.0 device
>>>> version is doing two things differently:
>>>> 1. Before starting the render process, it invalidates caches (pattern,
>>>>    source buffer and mask buffer). Cache control is not present on v4.x
>>>>    device.
>>>> 2. Scalling is done through StretchEn command (in BITBLT_COMMAND_REG
>>>>    register) instead of SRC_SCALE_CTRL_REG as in v4.x. However the
>>>>    exynos_drm_g2d driver does not implement the scalling so this
>>>>    difference can be eliminated.
>>> Huh? Where did you get this from? Scaling works with the DRM driver.
>>
>> I was looking for the usage of scaling reg (as there is no scaling
>> command). How the scaling is implemented then?
> Like you said above the drivers work completly different. The DRM one
> receives a command list that is constructed by userspace (libdrm
> mostly), copies it to a contiguous buffer and passes the memory address
> of that buffer to the engine which then works on it. Of course
> everything is slightly more complex.
> 
> You don't see any reference to scaling in the driver because the scaling
> regs don't need any kind of specific validation.
> 
> If you want to know how the command list is constructed, the best way is
> to look into libdrm. The Exynos specific tests actually cover scaling.

Thanks for explanations. The patch is insufficient then and it requires
much more effort. Please drop the series as of now.

Best regards,
Krzysztof



From arnd at arndb.de  Wed May 25 05:18:12 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 25 May 2016 14:18:12 +0200
Subject: [PATCH V5 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <000a01d1b672$93d54690$bb7fd3b0$@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
 <7555154.mU2oTAdECP@wuerfel> <000a01d1b672$93d54690$bb7fd3b0$@codeaurora.org>
Message-ID: <14302911.qQPb4UMJ8d@wuerfel>

On Wednesday, May 25, 2016 4:15:31 PM CEST Sricharan wrote:
> >
> >Any operation that could trigger a DMA from a device is required
> >to have a barrier preceding it (usually wmb() one implied by writel()),
> >so this is clearly not about a driver that installs a DMA mapping
> >before starting a DMA, but I don't see what else it would be.
> >
> 
> Ok, so i was doing this from the idea that, other iommu drivers
>  where polling on a status bit in their sync call to ensure completion
> of pending TLB invalidations. But in this case, there is no status bit.
>  So added a barrier to have no ordering issues before the client
> triggers the dma operation. But as you say above that it is implicit that
> the device would have a barrier before starting the trigger, then the
> barrier here becomes redundant.

Ok. There are two more things to note here:

* On other platforms, polling the register is likely required because
  an MMIO write is "posted", meaning that a sync after writel() will
  only ensure that it has left the CPU write queue, but it may still be
  on the bus fabric and whatever side-effects are triggered by the
  write are normally not guaranteed to be completed even after the
  'sync'. You need to check the datasheet for your IOMMU to find out
  whether the 'dsb' instruction actually has any effect on the IOMMU.
  If not, then neither the barrier that you add here nor the barrier
  in the following writel() is sufficient.

* The one barrier that is normally required in an IOMMU is between
  updating the in-memory page tables and the following MMIO store
  that triggers the TLB flush for that entry. This barrier is
  implied by writel() but not writel_relaxed(). If you don't have
  a hardware page table walker in your IOMMU, you don't need to worry
  about this.

	Arnd


From maxime.ripard at free-electrons.com  Wed May 25 05:33:04 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 25 May 2016 14:33:04 +0200
Subject: [PATCH 14/20] ARM: sun5i: a13: Add LCD pins
In-Reply-To: <CAGb2v66g_xZEyOf8ky_TKpT70D_EQwirVKNMQbubT5U2cD8rnw@mail.gmail.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-15-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v66g_xZEyOf8ky_TKpT70D_EQwirVKNMQbubT5U2cD8rnw@mail.gmail.com>
Message-ID: <20160525123304.GD9232@lukather>

On Tue, May 17, 2016 at 01:13:01AM +0800, Chen-Yu Tsai wrote:
> >  arch/arm/boot/dts/sun5i-a13.dtsi | 10 ++++++++++
> >  1 file changed, 10 insertions(+)
> >
> > diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
> > index 263d46dbc7e6..79b5d513c142 100644
> > --- a/arch/arm/boot/dts/sun5i-a13.dtsi
> > +++ b/arch/arm/boot/dts/sun5i-a13.dtsi
> > @@ -237,6 +237,16 @@
> >  &pio {
> >         compatible = "allwinner,sun5i-a13-pinctrl";
> >
> > +       lcd_rgb666_pins: lcd_rgb666 at 0 {
> > +               allwinner,pins = "PD2", "PD3", "PD4", "PD5", "PD6", "PD7",
> > +                                "PD10", "PD11", "PD12", "PD13", "PD14", "PD15",
> > +                                "PD18", "PD19", "PD20", "PD21", "PD22", "PD23",
> > +                                "PD24", "PD25", "PD26", "PD27";
> > +               allwinner,function = "lcd0";
> > +               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
> 
> Just a thought: would we ever need to increase the drive strength for very high
> resolutions?

I don't think we need to, but we can always change that later.

Applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160525/48adf3f9/attachment-0001.sig>

From k.kozlowski at samsung.com  Wed May 25 05:37:13 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 25 May 2016 14:37:13 +0200
Subject: [PATCH 0/4] dma-mapping: Constify dma_attrs
In-Reply-To: <20160524090938.GA13166@infradead.org>
References: <1464071290-15948-1-git-send-email-k.kozlowski@samsung.com>
 <20160524090938.GA13166@infradead.org>
Message-ID: <57459C79.8060204@samsung.com>

On 05/24/2016 11:09 AM, Christoph Hellwig wrote:
> I think this is moving into the wrong direction.  The right fix here
> is to get of all the dma_attrs boilerplate code and just replace it
> with a simple enum dma_flags.  This would simplify both the callers
> and most importantly the wrappers for the flag-less versions a lot.

The dma attrs are additive so maybe not an enum but an unsigned long and
#defines:

#define	DMA_ATTR_WRITE_BARRIER		0x0001u
#define DMA_ATTR_WEAK_ORDERING		0x0002u
#define DMA_ATTR_WRITE_COMBINE		0x0004u
...

The intrusiveness of it would be similar but indeed looks simpler - when
reading the code and when setting the dma_attrs.

If that seems reasonable, I will send a follow up with new approach.

Thanks for feedback!

Best regards,
Krzysztof


From maxime.ripard at free-electrons.com  Wed May 25 05:38:08 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 25 May 2016 14:38:08 +0200
Subject: [PATCH 1/6] drm: sun4i: do cleanup if RGB output init fails
In-Reply-To: <1463500571-28970-2-git-send-email-wens@csie.org>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
 <1463500571-28970-2-git-send-email-wens@csie.org>
Message-ID: <20160525123808.GE9232@lukather>

On Tue, May 17, 2016 at 11:56:06PM +0800, Chen-Yu Tsai wrote:
> sun4i_rgb_init() can fail, which results in TCON failing to bind.
> In this case we need to do cleanup, specificly unregistering the
> dotclock, which is regmap based, and the regmap is registered as
> part of the sun4i_tcon_bind().
> 
> Failing to do so results in a NULL pointer reference when the CCF
> tries to turn off unused clocks.
> 
> Fixes: 29e57fab97fc ("drm: sun4i: Add RGB output")
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>

Applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160525/fd557265/attachment.sig>

From maxime.ripard at free-electrons.com  Wed May 25 05:39:24 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 25 May 2016 14:39:24 +0200
Subject: [PATCH 2/6] ARM: dts: axp209: Disable ldo5 by default
In-Reply-To: <1463500571-28970-3-git-send-email-wens@csie.org>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
 <1463500571-28970-3-git-send-email-wens@csie.org>
Message-ID: <20160525123924.GF9232@lukather>

On Tue, May 17, 2016 at 11:56:07PM +0800, Chen-Yu Tsai wrote:
> The output pin of LDO is also a GPIO pin, and the on/off settings of the
> regulator are actually pinmux settings.
> 
> Disable it by default so it doesn't conflict with GPIO usage.
> 
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>

Applied, thanks!

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160525/67730757/attachment.sig>

From dennis.chen at arm.com  Wed May 25 05:40:27 2016
From: dennis.chen at arm.com (Dennis Chen)
Date: Wed, 25 May 2016 20:40:27 +0800
Subject: [PATCH] arm64:efi fix the format of debug message from efi
In-Reply-To: <20160525112549.GJ1337@leverpostej>
References: <1464174974-4733-1-git-send-email-dennis.chen@arm.com>
 <20160525112549.GJ1337@leverpostej>
Message-ID: <20160525124024.GA4798@arm.com>

On Wed, May 25, 2016 at 12:25:49PM +0100, Mark Rutland wrote:
> On Wed, May 25, 2016 at 07:16:14PM +0800, Dennis Chen wrote:
> > When enable debug of efi and memblock with 'efi=debug memblock=debug' appended
> > to the kernel command line, the debug message output for earyly_con looks like:
> > [    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > [    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > [    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > [    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] memblock_add: [0x00008000000000-0x00008001e7ffff] flags 0x0 early_init_dt_add_memory_arch+0x54/0x5c
> > [    0.000000] *
> > ...
> > This patch is trying to fix the above output messed up by memblock_add(), so we can get below debug mesg looks
> > more formally after applied:
> > [    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > [    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > [    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > [    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
> > [    0.000000] memblock_add: [0x00008000000000-0x00008001e7ffff] flags 0x0 early_init_dt_add_memory_arch+0x54/0x5c
> > ...
> >
> > Signed-off-by: Dennis Chen <dennis.chen at arm.com>
> > Acked-by: Mark Rutland <mark.rutland at arm.com>
> > Cc: Catalin Marinas <catalin.marinas at arm.com>
> > Cc: Steve Capper <steve.capper at arm.com>
> > Cc: Will Deacon <will.deacon at arm.com>
> > ---
> >  drivers/firmware/efi/arm-init.c | 14 +++++++-------
> >  1 file changed, 7 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
> > index a850cbc..272f674 100644
> > --- a/drivers/firmware/efi/arm-init.c
> > +++ b/drivers/firmware/efi/arm-init.c
> > @@ -174,6 +174,7 @@ static __init void reserve_regions(void)
> >  {
> >         efi_memory_desc_t *md;
> >         u64 paddr, npages, size;
> > +       int resv;
> >
> >         if (efi_enabled(EFI_DBG))
> >                 pr_info("Processing EFI memory map:\n");
> > @@ -190,12 +191,16 @@ static __init void reserve_regions(void)
> >                 paddr = md->phys_addr;
> >                 npages = md->num_pages;
> >
> > +               resv = is_reserve_region(md);
> >                 if (efi_enabled(EFI_DBG)) {
> >                         char buf[64];
> >
> >                         pr_info("  0x%012llx-0x%012llx %s%s",
> >                                 paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
> > -                               efi_md_typeattr_format(buf, sizeof(buf), md));
> > +                               efi_md_typeattr_format(buf, sizeof(buf), md),
> > +                               resv ? "*" : "");
> > +
> > +                       pr_cont("\n");
>
> As I mentioned in my (off-list) mail previously, please fold this
> pr_cont in. You just need to move the "\n" into the end of the format
> string for the pr_info.
>
Yes, my careless mistake. Will be updated in v2...;-)

Regards,
Dennis
>
> Thanks,
> Mark,
>
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.



From maxime.ripard at free-electrons.com  Wed May 25 05:40:53 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 25 May 2016 14:40:53 +0200
Subject: [PATCH 0/6] ARM: dts: sun5i: q8-common: Enable various peripherals
In-Reply-To: <abbb9686-bbc7-cfad-ec1d-e5f099ac124b@redhat.com>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
 <abbb9686-bbc7-cfad-ec1d-e5f099ac124b@redhat.com>
Message-ID: <20160525124053.GG9232@lukather>

Hi Hans,

On Wed, May 18, 2016 at 10:13:52AM +0200, Hans de Goede wrote:
> Hi Chen-Yu,
> 
> On 17-05-16 17:56, Chen-Yu Tsai wrote:
> >Hi everyone,
> >
> >This series enables more peripherals for Allwinner A13-based Q8 devices.
> >The peripherals include the WiFi, the PMIC's micro-usb power supply
> >(driver), audio codec (headphone and speaker), and full display support
> >with the new DRM KMS driver. The series is based on parts of Maxime's
> >"drm: Add Support for Passive RGB to VGA bridges" series, specifically
> >the clk and drm fixes, and common DTS bits.
> >
> >Hans, since you have a collection of q8 tablets, I'm hoping you could
> >test these bits and provide some feedback.
> 
> I've not run any tests, just looked at the patches, the stuff in
> patch 3 is already present in arch/arm/boot/dts/sun5i-a13-q8-tablet.dts
> I put it there because I saw some .fex files which don't use ldo3 for wifi
> I'm fine with moving it to -common though, I believe that you're right
> that it makes more sense there, having it in 2 places is not really
> useful though.

I'm not quite sure what you mean, do you want Chen-Yu to send a second
version, or are you ok with this patch?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160525/2d9b7f8e/attachment-0001.sig>

From maxime.ripard at free-electrons.com  Wed May 25 05:41:59 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 25 May 2016 14:41:59 +0200
Subject: [PATCH 4/6] ARM: dts: sun5i: q8-common: Enable USB power supply
In-Reply-To: <1463500571-28970-5-git-send-email-wens@csie.org>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
 <1463500571-28970-5-git-send-email-wens@csie.org>
Message-ID: <20160525124159.GH9232@lukather>

On Tue, May 17, 2016 at 11:56:09PM +0800, Chen-Yu Tsai wrote:
> On the A13 Q8 tablets, the PMIC's USB power supply (VBUS) is connected
> to the external OTG port. This can be used to provide power and OTG VBUS
> sensing.
> 
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>

Applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160525/ee47c2a1/attachment.sig>

From mark.rutland at arm.com  Wed May 25 05:42:41 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 25 May 2016 13:42:41 +0100
Subject: [PATCH] arm64:efi fix the format of debug message from efi
In-Reply-To: <20160525124024.GA4798@arm.com>
References: <1464174974-4733-1-git-send-email-dennis.chen@arm.com>
 <20160525112549.GJ1337@leverpostej> <20160525124024.GA4798@arm.com>
Message-ID: <20160525124241.GM1337@leverpostej>

On Wed, May 25, 2016 at 08:40:27PM +0800, Dennis Chen wrote:
> On Wed, May 25, 2016 at 12:25:49PM +0100, Mark Rutland wrote:
> > On Wed, May 25, 2016 at 07:16:14PM +0800, Dennis Chen wrote:
> > > When enable debug of efi and memblock with 'efi=debug memblock=debug' appended
> > > to the kernel command line, the debug message output for earyly_con looks like:
> > > [    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > > [    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > > [    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > > [    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]
> > > [    0.000000] memblock_add: [0x00008000000000-0x00008001e7ffff] flags 0x0 early_init_dt_add_memory_arch+0x54/0x5c
> > > [    0.000000] *
> > > ...
> > > This patch is trying to fix the above output messed up by memblock_add(), so we can get below debug mesg looks
> > > more formally after applied:
> > > [    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > > [    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > > [    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > > [    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
> > > [    0.000000] memblock_add: [0x00008000000000-0x00008001e7ffff] flags 0x0 early_init_dt_add_memory_arch+0x54/0x5c
> > > ...
> > > 
> > > Signed-off-by: Dennis Chen <dennis.chen at arm.com>
> > > Acked-by: Mark Rutland <mark.rutland at arm.com>
> > > Cc: Catalin Marinas <catalin.marinas at arm.com>
> > > Cc: Steve Capper <steve.capper at arm.com>
> > > Cc: Will Deacon <will.deacon at arm.com>
> > > ---
> > >  drivers/firmware/efi/arm-init.c | 14 +++++++-------
> > >  1 file changed, 7 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
> > > index a850cbc..272f674 100644
> > > --- a/drivers/firmware/efi/arm-init.c
> > > +++ b/drivers/firmware/efi/arm-init.c
> > > @@ -174,6 +174,7 @@ static __init void reserve_regions(void)
> > >  {
> > >         efi_memory_desc_t *md;
> > >         u64 paddr, npages, size;
> > > +       int resv;
> > > 
> > >         if (efi_enabled(EFI_DBG))
> > >                 pr_info("Processing EFI memory map:\n");
> > > @@ -190,12 +191,16 @@ static __init void reserve_regions(void)
> > >                 paddr = md->phys_addr;
> > >                 npages = md->num_pages;
> > > 
> > > +               resv = is_reserve_region(md);
> > >                 if (efi_enabled(EFI_DBG)) {
> > >                         char buf[64];
> > > 
> > >                         pr_info("  0x%012llx-0x%012llx %s%s",
> > >                                 paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
> > > -                               efi_md_typeattr_format(buf, sizeof(buf), md));
> > > +                               efi_md_typeattr_format(buf, sizeof(buf), md),
> > > +                               resv ? "*" : "");
> > > +
> > > +                       pr_cont("\n");
> > 
> > As I mentioned in my (off-list) mail previously, please fold this
> > pr_cont in. You just need to move the "\n" into the end of the format
> > string for the pr_info.
> >
> Yes, my careless mistake. Will be updated in v2...;-)

Thanks. With that, my Acked-by holds.

I've just spotted that this has not gone to linux-efi, Matt Fleming, or
Ard Biesheuvel, who should all have been Cc'd. Please use
get_maintainer.pl, and send this to the relevant maintainers and lists.

Thanks,
Mark.


From maxime.ripard at free-electrons.com  Wed May 25 05:43:36 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 25 May 2016 14:43:36 +0200
Subject: [PATCH 5/6] ARM: dts: sun5i: q8-common: Enable audio codec
In-Reply-To: <1463500571-28970-6-git-send-email-wens@csie.org>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
 <1463500571-28970-6-git-send-email-wens@csie.org>
Message-ID: <20160525124336.GI9232@lukather>

On Tue, May 17, 2016 at 11:56:10PM +0800, Chen-Yu Tsai wrote:
> The Q8 tablets use the audio codec to provide audio output via a
> headphone jack or a small mono speaker. A GPIO output is used to
> control speaker amp.
> 
> The tablets may or may not have an internal microphone.
> 
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>

Applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160525/4ba23d8c/attachment.sig>

From grygorii.strashko at ti.com  Wed May 25 05:44:09 2016
From: grygorii.strashko at ti.com (Grygorii Strashko)
Date: Wed, 25 May 2016 15:44:09 +0300
Subject: [PATCH] ARM: omap2: am437x: rollback to use
 omap3_gptimer_timer_init()
In-Reply-To: <57457636.3010409@ti.com>
References: <1460457775-23850-1-git-send-email-grygorii.strashko@ti.com>
 <20160412160448.GN5995@atomide.com> <570D3EC8.7090807@ti.com>
 <20160412184250.GT5995@atomide.com> <57457636.3010409@ti.com>
Message-ID: <57459E19.40901@ti.com>

On 05/25/2016 12:53 PM, Lokesh Vutla wrote:
> 
> 
> On Wednesday 13 April 2016 12:12 AM, Tony Lindgren wrote:
>> * Grygorii Strashko <grygorii.strashko at ti.com> [160412 11:31]:
>>> On 04/12/2016 07:04 PM, Tony Lindgren wrote:
>>>> * Grygorii Strashko <grygorii.strashko at ti.com> [160412 03:44]:
>>>>> The commit 55ee7017ee31 ("arm: omap2: board-generic: use
>>>>> omap4_local_timer_init for AM437x") unintentionally changes the
>>>>> clocksource devices for AM437x from OMAP GP Timer to SyncTimer32K.
>>>>>
>>>>> Unfortunately, the SyncTimer32K is starving from frequency deviation
>>>>> as mentioned in commit 5b5c01359152 ("ARM: OMAP2+: AM43x: Use gptimer
>>>>> as clocksource") and, as reported by Franklin [1], even its monotonic
>>>>> nature is under question (most probably there is a HW issue, but it's
>>>>> still under investigation).
>>>>>
>>>>> Taking into account above facts It's reasonable to rollback to the use
>>>>> of omap3_gptimer_timer_init().
>>>>
>>>> I thought only the ePOS EVM does not have the 32k clock available?
>>>> Maybe this is the the old sync timer autocorrection drift issue?
>>>>
>>>
>>> May be, as i mentioned in [1] it could be errata same as for Watchdog
>>> Advisory 22 (or OMAP_TIMER_ERRATA_I103_I767).
>>>
>>> But as per commit 5b5c01359152 ("ARM: OMAP2+: AM43x: Use gptimer
>>> as clocksource") there is no reason to use SyncTimer32K as
>>> clocksource any way (not only on epos):
>>>
>>> commit 5b5c01359152f3ddaa1aa0e5d1141bc2b29ba2c5
>>> Author: Rajendra Nayak <rnayak at ti.com>
>>> Date:   Fri Feb 7 15:51:26 2014 +0530
>>>
>>>      ARM: OMAP2+: AM43x: Use gptimer as clocksource
>>>      
>>>      The SyncTimer in AM43x is clocked using the following two sources:
>>>      1) An inaccuarte 32k clock (CLK_32KHZ) derived from PER DPLL, causing system
>>>         time to go slowly (~10% deviation).
>>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 
> I don't think this statement is right. If clock from PER DPLL is
> inaccurate then all the IPs which uses PER DPLL are in danger. It is the
> On-Chip 32K RC Osc clock that is not an accurate clock-source as per the
> design/spec.
> 
>>>      2) external 32KHz RTC clock, which may not always be available on board like
>>>         in the case of ePOS EVM
> 
> Also this 32KHz RTC clock is not enabled by default and is handled by RTC.
> 
> IMO, it is better to change the clock source of sync timer to
> CLK_32KHz(like it is done in case of am43x-epos). Or do you have any
> other reason to shift to gptimer?
> 

In my opinion this is because of HW issue - OMAP4 errata i103, which,
for some reasons, is not mentioned for am437x (and I do not have confirmation). 

Originally issue was described and fix implemented for OMAP4 by commit

commit 73152a98a25392a451bb0d588a1fbe2796b3c909
Author: Santosh Shilimkar <santosh.shilimkar at ti.com>
Date: Mon Mar 12 20:34:45 2012 +0530

OMAP4: Workaround the OCP synchronisation issue with 32K synctimer.

I saw exactly similar behavior by my self:
- for some reason  ti_32k_read_cycles() return value lower the previously read value
- this causes timekeeping_get_delta() to return negative value
- which, in turn, causes big jiffies shift: 4294939981 -> 13079884
- and this blow up Timekeeping core brain and causes RCU stall error messages,
which is reasonable because all jiffies based timeout will misbehave.

>From registers I can see that 32K synctimer is in no-idle mode

32K synctimer.SYSC = 0x00000008
PRCM_CM_WKUP_SYNCTIMER_CLKCTRL = 0x00000102

and, seems, it's impossible to use static dep on am437x.

So, right now, I don't know how this issues can be W/A, so rallback.

-- 
regards,
-grygorii


From maxime.ripard at free-electrons.com  Wed May 25 05:44:45 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 25 May 2016 14:44:45 +0200
Subject: [PATCH 6/6] ARM: dts: sun5i: q8-common: Enable display pipeline
 and LCD display
In-Reply-To: <1463500571-28970-7-git-send-email-wens@csie.org>
References: <1463500571-28970-1-git-send-email-wens@csie.org>
 <1463500571-28970-7-git-send-email-wens@csie.org>
Message-ID: <20160525124445.GJ9232@lukather>

On Tue, May 17, 2016 at 11:56:11PM +0800, Chen-Yu Tsai wrote:
> Q8 form factor A13 tablets have a 7" LCD panel. Unfortunately we
> don't know the exact model of the panel. Just pick a panel with
> display timings close to what we know.
> 
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>

Applied, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160525/50918e19/attachment.sig>

From rk at ti.com  Wed May 25 05:53:39 2016
From: rk at ti.com (Ravikumar Kattekola)
Date: Wed, 25 May 2016 18:23:39 +0530
Subject: [PATCH 0/2] arm: dra7: Add i2c6 instance hwmod and dt entries
Message-ID: <20160525125341.10044-1-rk@ti.com>

DRA72x devices have a sixth i2c ocntroller instance.
Following patches add the required hwmod structure and
device tree nodes.

Reference doc: DRA72x TRM [ SPRUHP2Q ]

Tested on :
DRA72x Rev B EVM

Ravikumar Kattekola (2):
  arm: dra7: Add hwmod entry for i2c6
  dts: dra7: Add device tree node for i2c6

 arch/arm/boot/dts/dra7.dtsi               | 11 +++++++++++
 arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 23 +++++++++++++++++++++++
 2 files changed, 34 insertions(+)

-- 
2.8.2.396.g5fe494c



From rk at ti.com  Wed May 25 05:53:41 2016
From: rk at ti.com (Ravikumar Kattekola)
Date: Wed, 25 May 2016 18:23:41 +0530
Subject: [PATCH 2/2] dts: dra7: Add device tree node for i2c6
In-Reply-To: <20160525125341.10044-1-rk@ti.com>
References: <20160525125341.10044-1-rk@ti.com>
Message-ID: <20160525125341.10044-3-rk@ti.com>

DRA72x devices have an extra i2c controller instance - i2c6
Adding device description for the same.

Reference : DRA72x_SR1.0 TRM [ SPRUHP2Q ]

Signed-off-by: Ravikumar Kattekola <rk at ti.com>
---
 arch/arm/boot/dts/dra7.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 3a8f397..84729a1 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -27,6 +27,7 @@
 		i2c2 = &i2c3;
 		i2c3 = &i2c4;
 		i2c4 = &i2c5;
+		i2c5 = &i2c6;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
@@ -929,6 +930,16 @@
 			status = "disabled";
 		};
 
+		i2c6: i2c at 48458000 {
+			compatible = "ti,omap4-i2c";
+			reg = <0x48458000 0x100>;
+			interrupts = <GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c6";
+			status = "disabled";
+		};
+
 		mmc1: mmc at 4809c000 {
 			compatible = "ti,omap4-hsmmc";
 			reg = <0x4809c000 0x400>;
-- 
2.8.2.396.g5fe494c



From rk at ti.com  Wed May 25 05:53:40 2016
From: rk at ti.com (Ravikumar Kattekola)
Date: Wed, 25 May 2016 18:23:40 +0530
Subject: [PATCH 1/2] arm: dra7: Add hwmod entry for i2c6
In-Reply-To: <20160525125341.10044-1-rk@ti.com>
References: <20160525125341.10044-1-rk@ti.com>
Message-ID: <20160525125341.10044-2-rk@ti.com>

dra72x device has i2c6 controller.
Adding hwmod definition for the same.

Reference DRA72x TRM [ SPRUHP2Q ]

Signed-off-by: Ravikumar Kattekola <rk at ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
index d0e7e525..b84c0f7 100644
--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
@@ -1127,6 +1127,20 @@ static struct omap_hwmod dra7xx_i2c5_hwmod = {
 	.dev_attr	= &i2c_dev_attr,
 };
 
+/* i2c6 */
+static struct omap_hwmod dra7xx_i2c6_hwmod = {
+	.name		= "i2c6",
+	.class		= &dra7xx_i2c_hwmod_class,
+	.clkdm_name	= "l4per2_clkdm",
+	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.main_clk	= "func_96m_fclk",
+	.prcm = {
+		.omap4 = {
+		},
+	},
+	.dev_attr	= &i2c_dev_attr,
+};
+
 /*
  * 'mailbox' class
  *
@@ -3186,6 +3200,14 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per1__i2c5 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_per2 -> i2c6 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__i2c6 = {
+	.master		= &dra7xx_l4_per2_hwmod,
+	.slave		= &dra7xx_i2c6_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_cfg -> mailbox1 */
 static struct omap_hwmod_ocp_if dra7xx_l4_cfg__mailbox1 = {
 	.master		= &dra7xx_l4_cfg_hwmod,
@@ -3857,6 +3879,7 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
 	&dra7xx_l4_per1__i2c3,
 	&dra7xx_l4_per1__i2c4,
 	&dra7xx_l4_per1__i2c5,
+	&dra7xx_l4_per2__i2c6,
 	&dra7xx_l4_cfg__mailbox1,
 	&dra7xx_l4_per3__mailbox2,
 	&dra7xx_l4_per3__mailbox3,
-- 
2.8.2.396.g5fe494c



From tjakobi at math.uni-bielefeld.de  Wed May 25 05:59:48 2016
From: tjakobi at math.uni-bielefeld.de (Tobias Jakobi)
Date: Wed, 25 May 2016 14:59:48 +0200
Subject: [PATCH 1/2] drm/exynos: g2d: Add support for old S5Pv210 type
In-Reply-To: <574596E0.4090104@samsung.com>
References: <1464096493-13378-1-git-send-email-k.kozlowski@samsung.com>
 <57445BE5.7060702@math.uni-bielefeld.de> <57445E16.90301@samsung.com>
 <57447BDA.2000004@math.uni-bielefeld.de> <574596E0.4090104@samsung.com>
Message-ID: <5745A1C4.6060405@math.uni-bielefeld.de>

Hey Krzysztof,


Krzysztof Kozlowski wrote:
> On 05/24/2016 06:05 PM, Tobias Jakobi wrote:
>> Hello Krzysztof,
>>
>>
>> Krzysztof Kozlowski wrote:
>>> On 05/24/2016 03:49 PM, Tobias Jakobi wrote:
>>>> Hello Krzysztof,
>>>>
>>>> are you sure that these are the only differences. Because AFAIK there
>>>> are quite a few more:
>>>> - DMA submission of commands
>>>> - blend mode / rounding
>>>> - solid fill
>>>> - YCrCb support
>>>> - and probably more
>>>>
>>>> One would need to add least split the command list parser into a v3 and
>>>> v41 version to accomodate for the differences. In fact userspace/libdrm
>>>> would need to know which hw type it currently uses, but you currently
>>>> always return 4.1 in the corresponding ioctl.
>>>
>>> Eh, so probably my patch does not cover fully the support for v3 G2D. I
>>> looked mostly at the differences between v3 and v4 in the s5p-g2d driver
>>> itself. However you are right that this might be not sufficient because
>>> exynos-g2d moved forward and is different than s5p-g2d.
>>>
>>>> Krzysztof Kozlowski wrote:
>>>>> The non-DRM s5p-g2d driver supports two versions of G2D: v3.0 on
>>>>> S5Pv210 and v4.x on Exynos 4x12 (or newer). The driver for 3.0 device
>>>>> version is doing two things differently:
>>>>> 1. Before starting the render process, it invalidates caches (pattern,
>>>>>    source buffer and mask buffer). Cache control is not present on v4.x
>>>>>    device.
>>>>> 2. Scalling is done through StretchEn command (in BITBLT_COMMAND_REG
>>>>>    register) instead of SRC_SCALE_CTRL_REG as in v4.x. However the
>>>>>    exynos_drm_g2d driver does not implement the scalling so this
>>>>>    difference can be eliminated.
>>>> Huh? Where did you get this from? Scaling works with the DRM driver.
>>>
>>> I was looking for the usage of scaling reg (as there is no scaling
>>> command). How the scaling is implemented then?
>> Like you said above the drivers work completly different. The DRM one
>> receives a command list that is constructed by userspace (libdrm
>> mostly), copies it to a contiguous buffer and passes the memory address
>> of that buffer to the engine which then works on it. Of course
>> everything is slightly more complex.
>>
>> You don't see any reference to scaling in the driver because the scaling
>> regs don't need any kind of specific validation.
>>
>> If you want to know how the command list is constructed, the best way is
>> to look into libdrm. The Exynos specific tests actually cover scaling.
> 
> Thanks for explanations. The patch is insufficient then and it requires
> much more effort. Please drop the series as of now.
If you intend to add support for v3 hardware we might want to join
forces. I have an (ongoing) rewrite of the driver to enable additional
functionality and to make it more suitable to provide EXA for a X11 DDX.
However this breaks the existing API and rewrites quite a bit of the driver

Here's what's there so far.
https://github.com/tobiasjakobi/linux-odroid-public/compare/e35ca9aca1214c5e104e6906c1d9affeb80fe5df...3d1ddb86db73b0d664f3e339709e8e8dacdc8e91

And here's the DDX:
https://github.com/tobiasjakobi/xf86-video-armsoc/commits/g2d


With best wishes,
Tobias



> 
> Best regards,
> Krzysztof
> 



From sricharan at codeaurora.org  Wed May 25 06:19:18 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Wed, 25 May 2016 18:49:18 +0530
Subject: [PATCH V5 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <14302911.qQPb4UMJ8d@wuerfel>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
 <7555154.mU2oTAdECP@wuerfel> <000a01d1b672$93d54690$bb7fd3b0$@codeaurora.org>
 <14302911.qQPb4UMJ8d@wuerfel>
Message-ID: <004c01d1b688$0f6379c0$2e2a6d40$@codeaurora.org>

Hi Arnd,

>> Ok, so i was doing this from the idea that, other iommu drivers
>>  where polling on a status bit in their sync call to ensure completion
>> of pending TLB invalidations. But in this case, there is no status bit.
>>  So added a barrier to have no ordering issues before the client
>> triggers the dma operation. But as you say above that it is implicit that
>> the device would have a barrier before starting the trigger, then the
>> barrier here becomes redundant.
>
>Ok. There are two more things to note here:
>
>* On other platforms, polling the register is likely required because
>  an MMIO write is "posted", meaning that a sync after writel() will
>  only ensure that it has left the CPU write queue, but it may still be
>  on the bus fabric and whatever side-effects are triggered by the
>  write are normally not guaranteed to be completed even after the
>  'sync'. You need to check the datasheet for your IOMMU to find out
>  whether the 'dsb' instruction actually has any effect on the IOMMU.
>  If not, then neither the barrier that you add here nor the barrier
>  in the following writel() is sufficient.
>
   Thanks for the detailed explanation.
i will check this. So with this, i think that if the iommu does not
 support polling for its status, then it should listen to 'dsb' otherwise
 there will no be no way of make it coherent ?

>* The one barrier that is normally required in an IOMMU is between
>  updating the in-memory page tables and the following MMIO store
>  that triggers the TLB flush for that entry. This barrier is
>  implied by writel() but not writel_relaxed(). If you don't have
>  a hardware page table walker in your IOMMU, you don't need to worry
>  about this.
>
  To get my understanding correct here, is the barrier required here because
   of speculative fetch ?

Regards,
 Sricharan




From robert.richter at cavium.com  Wed May 25 06:22:29 2016
From: robert.richter at cavium.com (Robert Richter)
Date: Wed, 25 May 2016 15:22:29 +0200
Subject: [PATCH v5] irqchip, gicv3-its, numa: Enable workaround for
 Cavium thunderx erratum 23144
In-Reply-To: <20160422090052.GA4236@arm.com>
References: <1460748606-28390-1-git-send-email-rrichter@caviumnetworks.com>
 <20160421174042.GD24726@rric.localdomain> <5719DA41.60304@arm.com>
 <20160422090052.GA4236@arm.com>
Message-ID: <20160525132229.GG1535@rric.localdomain>

Will, Marc,

On 22.04.16 10:00:52, Will Deacon wrote:
> On Fri, Apr 22, 2016 at 09:01:05AM +0100, Marc Zyngier wrote:
> > On 21/04/16 18:40, Robert Richter wrote:
> > > On 15.04.16 21:30:05, Robert Richter wrote:
> > >> From: Ganapatrao Kulkarni <gkulkarni at caviumnetworks.com>
> > >>
> > >> The erratum fixes the hang of ITS SYNC command by avoiding inter node
> > >> io and collections/cpu mapping on thunderx dual-socket platform.
> > >>
> > >> This fix is only applicable for Cavium's ThunderX dual-socket platform.
> > >>
> > >> This is based on NUMA v16 series.
> > >> Message-Id: <1460155828-8690-1-git-send-email-ddaney.cavm at gmail.com>
> > > 
> > > Will, Catalin,
> > > 
> > > after NUMA base patches went into linux-next (many thanks), please
> > > consider this pass 1.x errata workaround for inclusion too.
> > 
> > I'll queue it as a fix once the NUMA patches are merged into mainline.
> 
> Yeah, this can probably go in as -rc1 material if you're happy with it.

I am going to send a rebased version 6 as there is a minor conflict
with upstream. Please include that one as numa fix after rc1 is out.

Thanks,

-Robert


From rrichter at cavium.com  Wed May 25 06:29:20 2016
From: rrichter at cavium.com (Robert Richter)
Date: Wed, 25 May 2016 15:29:20 +0200
Subject: [PATCH v6] irqchip, gicv3-its,
 numa: Enable workaround for Cavium thunderx erratum 23144
Message-ID: <1464182961-9167-1-git-send-email-rrichter@cavium.com>

From: Ganapatrao Kulkarni <gkulkarni at caviumnetworks.com>

The erratum fixes the hang of ITS SYNC command by avoiding inter node
io and collections/cpu mapping on thunderx dual-socket platform.

This fix is only applicable for Cavium's ThunderX dual-socket platform.

This is based on NUMA upstream patches (Linus tree
v4.6-10530-g28165ec7a99b).

v6 (by Robert Richter):
rebased onto v4.6-10530-g28165ec7a99b to solve minor conflicts with
upstream, no further changes

v5 (by Robert Richter):
fixed use of cpumask_of_node() only for (node >= 0)
minor style fixes

v4:
updated silicon-errata.txt
updated as per Robert Richter review comment.

v3:
updatated as per Marc Zyngier's review comments.
http://www.spinics.net/lists/arm-kernel/msg443462.html

v2:
updatated as per Marc Zyngier's review comments.

Reviewed-by: Robert Richter <rrichter at cavium.com>
Signed-off-by: Ganapatrao Kulkarni <gkulkarni at caviumnetworks.com>
Signed-off-by: Robert Richter <rrichter at cavium.com>
---
 Documentation/arm64/silicon-errata.txt |  1 +
 arch/arm64/Kconfig                     |  9 +++++++
 drivers/irqchip/irq-gic-v3-its.c       | 49 ++++++++++++++++++++++++++++++++--
 3 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
index c6938e50e71f..4da60b463995 100644
--- a/Documentation/arm64/silicon-errata.txt
+++ b/Documentation/arm64/silicon-errata.txt
@@ -56,6 +56,7 @@ stable kernels.
 | ARM            | MMU-500         | #841119,#826419 | N/A                     |
 |                |                 |                 |                         |
 | Cavium         | ThunderX ITS    | #22375, #24313  | CAVIUM_ERRATUM_22375    |
+| Cavium         | ThunderX ITS    | #23144          | CAVIUM_ERRATUM_23144    |
 | Cavium         | ThunderX GICv3  | #23154          | CAVIUM_ERRATUM_23154    |
 | Cavium         | ThunderX Core   | #27456          | CAVIUM_ERRATUM_27456    |
 | Cavium         | ThunderX SMMUv2 | #27704          | N/A		       |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 76747d92bc72..57a9f67971d3 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -426,6 +426,15 @@ config CAVIUM_ERRATUM_22375
 
 	  If unsure, say Y.
 
+config CAVIUM_ERRATUM_23144
+	bool "Cavium erratum 23144: ITS SYNC hang on dual socket system"
+	depends on NUMA
+	default y
+	help
+	  ITS SYNC command hang for cross node io and collections/cpu mapping.
+
+	  If unsure, say Y.
+
 config CAVIUM_ERRATUM_23154
 	bool "Cavium erratum 23154: Access to ICC_IAR1_EL1 is not sync'ed"
 	default y
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 6bd881be24ea..5eb1f9e17a98 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -41,6 +41,7 @@
 
 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING		(1ULL << 0)
 #define ITS_FLAGS_WORKAROUND_CAVIUM_22375	(1ULL << 1)
+#define ITS_FLAGS_WORKAROUND_CAVIUM_23144	(1ULL << 2)
 
 #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING	(1 << 0)
 
@@ -82,6 +83,7 @@ struct its_node {
 	u64			flags;
 	u32			ite_size;
 	u32			device_ids;
+	int			numa_node;
 };
 
 #define ITS_ITT_ALIGN		SZ_256
@@ -613,11 +615,23 @@ static void its_unmask_irq(struct irq_data *d)
 static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 			    bool force)
 {
-	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
+	unsigned int cpu;
+	const struct cpumask *cpu_mask = cpu_online_mask;
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
 	struct its_collection *target_col;
 	u32 id = its_get_event_id(d);
 
+       /* lpi cannot be routed to a redistributor that is on a foreign node */
+	if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
+		if (its_dev->its->numa_node >= 0) {
+			cpu_mask = cpumask_of_node(its_dev->its->numa_node);
+			if (!cpumask_intersects(mask_val, cpu_mask))
+				return -EINVAL;
+		}
+	}
+
+	cpu = cpumask_any_and(mask_val, cpu_mask);
+
 	if (cpu >= nr_cpu_ids)
 		return -EINVAL;
 
@@ -1101,6 +1115,16 @@ static void its_cpu_init_collection(void)
 	list_for_each_entry(its, &its_nodes, entry) {
 		u64 target;
 
+		/* avoid cross node collections and its mapping */
+		if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
+			struct device_node *cpu_node;
+
+			cpu_node = of_get_cpu_node(cpu, NULL);
+			if (its->numa_node != NUMA_NO_NODE &&
+				its->numa_node != of_node_to_nid(cpu_node))
+				continue;
+		}
+
 		/*
 		 * We now have to bind each collection to its target
 		 * redistributor.
@@ -1351,9 +1375,14 @@ static void its_irq_domain_activate(struct irq_domain *domain,
 {
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
 	u32 event = its_get_event_id(d);
+	const struct cpumask *cpu_mask = cpu_online_mask;
+
+	/* get the cpu_mask of local node */
+	if (its_dev->its->numa_node >= 0)
+		cpu_mask = cpumask_of_node(its_dev->its->numa_node);
 
 	/* Bind the LPI to the first possible CPU */
-	its_dev->event_map.col_map[event] = cpumask_first(cpu_online_mask);
+	its_dev->event_map.col_map[event] = cpumask_first(cpu_mask);
 
 	/* Map the GIC IRQ and event to the device */
 	its_send_mapvi(its_dev, d->hwirq, event);
@@ -1443,6 +1472,13 @@ static void __maybe_unused its_enable_quirk_cavium_22375(void *data)
 	its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_22375;
 }
 
+static void __maybe_unused its_enable_quirk_cavium_23144(void *data)
+{
+	struct its_node *its = data;
+
+	its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_23144;
+}
+
 static const struct gic_quirk its_quirks[] = {
 #ifdef CONFIG_CAVIUM_ERRATUM_22375
 	{
@@ -1452,6 +1488,14 @@ static const struct gic_quirk its_quirks[] = {
 		.init	= its_enable_quirk_cavium_22375,
 	},
 #endif
+#ifdef CONFIG_CAVIUM_ERRATUM_23144
+	{
+		.desc	= "ITS: Cavium erratum 23144",
+		.iidr	= 0xa100034c,	/* ThunderX pass 1.x */
+		.mask	= 0xffff0fff,
+		.init	= its_enable_quirk_cavium_23144,
+	},
+#endif
 	{
 	}
 };
@@ -1514,6 +1558,7 @@ static int __init its_probe(struct device_node *node,
 	its->base = its_base;
 	its->phys_base = res.start;
 	its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
+	its->numa_node = of_node_to_nid(node);
 
 	its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
 	if (!its->cmd_base) {
-- 
2.7.0.rc3



From andre.przywara at arm.com  Wed May 25 06:49:03 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 25 May 2016 14:49:03 +0100
Subject: [PATCH v4 06/12] KVM: arm64: implement basic ITS register handlers
In-Reply-To: <5704D8B8.4000504@linaro.org>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-7-git-send-email-andre.przywara@arm.com>
 <5704D8B8.4000504@linaro.org>
Message-ID: <0c89ea29-4c40-ce87-f499-d600c466ace4@arm.com>

Hi Eric,

On 06/04/16 10:36, Eric Auger wrote:
> Hi Andre,
> On 03/26/2016 03:14 AM, Andre Przywara wrote:
>> Add emulation for some basic MMIO registers used in the ITS emulation.

...

>> +
>> +/*
>> + * By writing to CWRITER the guest announces new commands to be processed.
>> + * Since we cannot read from guest memory inside the ITS spinlock, we
>> + * iterate over the command buffer (with the lock dropped) until the read
>> + * pointer matches the write pointer. Other VCPUs writing this register in the
>> + * meantime will just update the write pointer, leaving the command
>> + * processing to the first instance of the function.
>> + */
>> +static int vgic_mmio_write_its_cwriter(struct kvm_vcpu *vcpu,
>> +				       struct kvm_io_device *this,
>> +				       gpa_t addr, int len, const void *val)
>> +{
>> +	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>> +	struct vgic_its *its = &dist->its;
>> +	gpa_t cbaser = its_cmd_buffer_base(vcpu->kvm);
>> +	u64 cmd_buf[4];
>> +	u32 reg;
>> +	bool finished;
>> +
>> +	reg = mask64(its->cwriter & 0xfffe0, addr & 7, len, val);
>> +	reg &= 0xfffe0;
>> +	if (reg > its_cmd_buffer_size(vcpu->kvm))
>> +		return 0;
>> +
>> +	spin_lock(&its->lock);
>> +
>> +	/*
>> +	 * If there is still another VCPU handling commands, let this
>> +	 * one pick up the new CWRITER and process "our" new commands as well.
>> +	 */
>> +	finished = (its->cwriter != its->creadr);
> empty?

Maybe that is indeed less misleading ...

>> +	its->cwriter = reg;
>> +
>> +	spin_unlock(&its->lock);
> Assuming we have 2 vcpus attempting a cwriter write at the same moment I
> don't understand what does guarantee they are not going to execute the
> following loop concurrently and possibly execute vits_handle_command
> twice on the same cmd from the same its->creadr start?

So does my explanation of the algorithm in that other mail today explain
it? Or do you still see a hole in the locking scheme here?

>> +
>> +	while (!finished) {
>> +		int ret = kvm_read_guest(vcpu->kvm, cbaser + its->creadr,
>> +					 cmd_buf, 32);
>> +		if (ret) {
>> +			/*
>> +			 * Gah, we are screwed. Reset CWRITER to that command
>> +			 * that we have finished processing and return.
>> +			 */
>> +			spin_lock(&its->lock);
>> +			its->cwriter = its->creadr;
> don't get why do you set the queue empty?

So from a guest's point of view this is something like an ITS internal
error which shouldn't happen. So I just bail out, but leave the queue in
a consistent (read: empty) state to allow possible future commands to be
processed at best effort.
I guess this is the best we can come up with, since there is no feasible
way of communicating errors back(?)

Cheers,
Andre.


From christopher.spinrath at rwth-aachen.de  Wed May 25 07:05:13 2016
From: christopher.spinrath at rwth-aachen.de (Christopher Spinrath)
Date: Wed, 25 May 2016 16:05:13 +0200
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <9b905766c6cc4680be4b33f79a179d5a@rwthex-w1-b.rwth-ad.de>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
 <20abc2f6769b4369ba87ec27274a090e@rwthex-s2-a.rwth-ad.de>
 <644530ff6bb04b5898dc33604dc7a93a@rwthex-s1-b.rwth-ad.de>
 <9b905766c6cc4680be4b33f79a179d5a@rwthex-w1-b.rwth-ad.de>
Message-ID: <0cf90ebe86e0461f82cb22b2a6b6ea83@rwthex-s1-b.rwth-ad.de>

Hi Fabio,

On 05/24/2016 01:20 AM, Fabio Estevam wrote:
> Hi Christopher,
> 
> On Mon, May 23, 2016 at 8:08 PM, Christopher Spinrath
> <christopher.spinrath at rwth-aachen.de> wrote:
> 
>> I would like to but I'm not sure if I'm allowed to. As I stated in the
>> license header some nodes are copied (and cleaned up) from the vendor
>> kernel/devicetree. They are licensed GPL-v2 only. So I don't know, can I
>> add the X11 license?
> 
> Maybe you could contact the original author anc check?
> 
I have sent an email to the author and will wait about a week for a
reply before I send v2.

>>> Better to avoid 0x80000000. Replace it with the real iomux value
>>> instead so that you don't need to rely on the bootloader
>>> configuration.
>> hmm, I don't know how to determine this value. The device documentation
>> I have does not say anything about it and the vendor kernel uses
>> 0x80000000...
> 
> The default value of register IOMUXC_SW_PAD_CTL_PAD_ENET_TX_DATA1 is
> 0x1b0b0, so you can use this value.
>
> Another thing I forgot to comment: instead of putting this pin inside
> the hog group you could put it inside the gpio-keys node.
> 

OK, done. Can I always use the default value in this case? If yes, can
you point me to a proper documentation of these?

Thanks,
Christopher


From arnd at arndb.de  Wed May 25 07:15:33 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 25 May 2016 16:15:33 +0200
Subject: [PATCH V5 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <004c01d1b688$0f6379c0$2e2a6d40$@codeaurora.org>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
 <14302911.qQPb4UMJ8d@wuerfel>
 <004c01d1b688$0f6379c0$2e2a6d40$@codeaurora.org>
Message-ID: <7715835.BXgVNoY5UO@wuerfel>

On Wednesday, May 25, 2016 6:49:18 PM CEST Sricharan wrote:
> Hi Arnd,
> 
> >> Ok, so i was doing this from the idea that, other iommu drivers
> >>  where polling on a status bit in their sync call to ensure completion
> >> of pending TLB invalidations. But in this case, there is no status bit.
> >>  So added a barrier to have no ordering issues before the client
> >> triggers the dma operation. But as you say above that it is implicit that
> >> the device would have a barrier before starting the trigger, then the
> >> barrier here becomes redundant.
> >
> >Ok. There are two more things to note here:
> >
> >* On other platforms, polling the register is likely required because
> >  an MMIO write is "posted", meaning that a sync after writel() will
> >  only ensure that it has left the CPU write queue, but it may still be
> >  on the bus fabric and whatever side-effects are triggered by the
> >  write are normally not guaranteed to be completed even after the
> >  'sync'. You need to check the datasheet for your IOMMU to find out
> >  whether the 'dsb' instruction actually has any effect on the IOMMU.
> >  If not, then neither the barrier that you add here nor the barrier
> >  in the following writel() is sufficient.
> >
>    Thanks for the detailed explanation.
> i will check this. So with this, i think that if the iommu does not
>  support polling for its status, then it should listen to 'dsb' otherwise
>  there will no be no way of make it coherent ?

It's more likely that you have to do a readl() after the writel() to
any address inside of the device in order to ensure the writel()
has completed, but that is something that the hardware manual for
the iommu should describe.

> >* The one barrier that is normally required in an IOMMU is between
> >  updating the in-memory page tables and the following MMIO store
> >  that triggers the TLB flush for that entry. This barrier is
> >  implied by writel() but not writel_relaxed(). If you don't have
> >  a hardware page table walker in your IOMMU, you don't need to worry
> >  about this.
> >
>   To get my understanding correct here, is the barrier required here because
>    of speculative fetch ?

It doesn't have to be a speculative fetch, it could also be a normal
fetch triggered by a DMA. The point is that the CPU is free to reorder
the store to (io page table) memory relative to the store to the
IOMMU flush register, and when you directly follow up with a store to
the DMA master that triggers a transfer, this transfer can hit the
IOMMU and cause the stale page table entry to be read.

I guess in practice the barrier that comes before the MMIO write to the
DMA master would ensure ordering of the DMA after both the IOPTE
update and the MMIO flush (unless there was the speculative fetch you
mentioned), but this is where I'm no longer confident enough in my
pwn understanding of th ordering rules to rely on that. Having the
barrier between the IOPTE update and the flush certainly leaves
no room for ambiguity.

	Arnd


From peter.ujfalusi at ti.com  Wed May 25 07:15:49 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:15:49 +0300
Subject: [PATCH v4 0/7] ARM/ASoC: OMAP3: Fix McBSP2/3 sidetone support
Message-ID: <1464185756-28401-1-git-send-email-peter.ujfalusi@ti.com>

Hi,

Changes since v3:
- Rebased on next-20160525 [1] to apply cleanly
- Fixed subject line for patch5
- Added Mark's acked-by to the ASoC patches

[1] "ASoC: omap-mcbsp: Enable/disable sidetone block auto clock
gating for omap3" is gone missing from linux-next - it was in next-20160517 and
I'm not sure when it got dropped.

Tony: since Paul did not replied to the series, I'm sending the v4 now, I hope
he will have time to look at this.

Commit message from v3:

Based on the ongoing discussion on v2 (ARM: OMAP3: Fix McBSP2/3 hwmod setup for
sidetone) I have dropped the removal of the sidetone hwmod and only corrected
it. The series now includes all related changes needed to have correct sidetone
support whenever we boot in legacy or in DT mode.

This time the ASoC part have dependency on earlier patches so they can not be
applied separately.

Regards,
Peter
---
Peter Ujfalusi (7):
  ARM: OMAP3: hwmod data: Fix McBSP2/3 sidetone data
  ARM: dts: omap3: Add clocks to McBSP nodes
  ARM: OMAP3: McBSP: New callback for McBSP2/3 ICLK idle configuration
  ARM: OMAP3: pdata-quirks: Add support for McBSP2/3 sidetone handling
  ASoC: omap-mcbsp: Rename omap_mcbsp_sysfs_remove() to
    omap_mcbsp_cleanup()
  ASoC: omap-mcbsp: sidetone: Use the new callback for iclk handling
  ARM: OMAP2+: McBSP: Remove the old iclk allow/deny idle code

 arch/arm/boot/dts/omap3.dtsi                | 10 ++++++++++
 arch/arm/mach-omap2/mcbsp.c                 | 31 ++++++++++++++++-------------
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c  | 24 ++++------------------
 arch/arm/mach-omap2/pdata-quirks.c          | 18 +++++++++++++++++
 include/linux/platform_data/asoc-ti-mcbsp.h |  4 +++-
 sound/soc/omap/mcbsp.c                      | 21 +++++++++++++------
 sound/soc/omap/mcbsp.h                      |  3 ++-
 sound/soc/omap/omap-mcbsp.c                 |  5 ++++-
 8 files changed, 73 insertions(+), 43 deletions(-)

-- 
2.8.2



From javier at osg.samsung.com  Wed May 25 07:17:52 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 25 May 2016 10:17:52 -0400
Subject: [PATCH 0/2] ARM: dts: Fix imprecise external abort error when
 accessing Exynos MFC
In-Reply-To: <6479e0c0-97fb-ca3b-1337-6ed11410d94f@samsung.com>
References: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
 <6479e0c0-97fb-ca3b-1337-6ed11410d94f@samsung.com>
Message-ID: <d90b6245-1ed4-32c6-c98d-cc5f12601205@osg.samsung.com>

Hello Marek,

On 05/25/2016 02:51 AM, Marek Szyprowski wrote:
> Hello,
> 
> 
> On 2016-05-24 19:41, Javier Martinez Canillas wrote:
>> This series fixes an imprecise external abort error when accessing the
>> Exynos MFC registers due the power domain configuration requiring the
>> aclk333 clock to be enabled during a domain switch.
>>
>> There isn't a dependency between the clock and Linux Samsung SoC trees
>> because the CLK_ACLK333 clock ID is already defined so the patches can
>> be picked indepedently by the relevant subsystem maintainers.
> 
> Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
> 
> I'm really curious what kind of async-bridge is there, but this patch
> really fixes the problem with mfc power domain.
>

Yes, the Exynos manual is not that clear about what clocks have to remain
enabled during a power domain switch for an IP block so maybe I got wrong.

I see that the MFC block has an async-bridge in "Figure 15-1" at section 
"15.2.1 NoC Probes in 5420 Bus". And I thought that since the IP block
has an async-bridge, the clock needs to remain ungated when the PMU turn
it on and off on a power domain switch.

I chose that clock because "Figure 7-10 MFC Clock Diagram" at section
"7.4.7 MFC Clock Diagram" shows that ACLK_333 is associated with the
MFC internal buses, or at least that's my understanding.

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From peter.ujfalusi at ti.com  Wed May 25 07:15:50 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:15:50 +0300
Subject: [PATCH v4 1/7] ARM: OMAP3: hwmod data: Fix McBSP2/3 sidetone data
In-Reply-To: <1464185756-28401-1-git-send-email-peter.ujfalusi@ti.com>
References: <1464185756-28401-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1464185756-28401-2-git-send-email-peter.ujfalusi@ti.com>

The McBSPLP's sidetone main clock is the McBSPLP's ICLK, not FCLK as the
sidetone only receives the ICLK from the main McBSP module.
Since the McBSP and sidetone is using the very same clock from PRCM level
the sidetone must not have the prcm section to check the clock status since
the sidetone is only used when McBSP is already configured.
If two separate hwmods looking at the same bit and they would use
pm_runtime in nested way (as it must happen with McBSP and it's ST module)
the hwmod would warn, because the idlest will not match what it is expected
after enable/disable of the clocks.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 24 ++++--------------------
 1 file changed, 4 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 9869a75c5d96..d72ee6185d5e 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1322,16 +1322,8 @@ static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
 	.name		= "mcbsp2_sidetone",
 	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp2_sidetone_irqs,
-	.main_clk	= "mcbsp2_fck",
-	.prcm		= {
-		.omap2 = {
-			.prcm_reg_id = 1,
-			 .module_bit = OMAP3430_EN_MCBSP2_SHIFT,
-			.module_offs = OMAP3430_PER_MOD,
-			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_MCBSP2_SHIFT,
-		},
-	},
+	.main_clk	= "mcbsp2_ick",
+	.flags		= HWMOD_NO_IDLEST,
 };
 
 /* mcbsp3_sidetone */
@@ -1344,16 +1336,8 @@ static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
 	.name		= "mcbsp3_sidetone",
 	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp3_sidetone_irqs,
-	.main_clk	= "mcbsp3_fck",
-	.prcm		= {
-		.omap2 = {
-			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_MCBSP3_SHIFT,
-			.module_offs = OMAP3430_PER_MOD,
-			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_MCBSP3_SHIFT,
-		},
-	},
+	.main_clk	= "mcbsp3_ick",
+	.flags		= HWMOD_NO_IDLEST,
 };
 
 /* SR common */
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 25 07:15:51 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:15:51 +0300
Subject: [PATCH v4 2/7] ARM: dts: omap3: Add clocks to McBSP nodes
In-Reply-To: <1464185756-28401-1-git-send-email-peter.ujfalusi@ti.com>
References: <1464185756-28401-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1464185756-28401-3-git-send-email-peter.ujfalusi@ti.com>

Add clock properties to the McBSP nodes. McBSP2 and 3 need to have ick also
since the Sidetone block of these modules are operating using the McBSP
interface clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap3.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 9fbda38528dc..4c3c471d2a83 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -493,6 +493,8 @@
 			dmas = <&sdma 31>,
 			       <&sdma 32>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp1_fck>;
+			clock-names = "fck";
 			status = "disabled";
 		};
 
@@ -511,6 +513,8 @@
 			dmas = <&sdma 33>,
 			       <&sdma 34>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp2_fck>, <&mcbsp2_ick>;
+			clock-names = "fck", "ick";
 			status = "disabled";
 		};
 
@@ -529,6 +533,8 @@
 			dmas = <&sdma 17>,
 			       <&sdma 18>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp3_fck>, <&mcbsp3_ick>;
+			clock-names = "fck", "ick";
 			status = "disabled";
 		};
 
@@ -545,6 +551,8 @@
 			dmas = <&sdma 19>,
 			       <&sdma 20>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp4_fck>;
+			clock-names = "fck";
 			status = "disabled";
 		};
 
@@ -561,6 +569,8 @@
 			dmas = <&sdma 21>,
 			       <&sdma 22>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp5_fck>;
+			clock-names = "fck";
 			status = "disabled";
 		};
 
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 25 07:15:52 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:15:52 +0300
Subject: [PATCH v4 3/7] ARM: OMAP3: McBSP: New callback for McBSP2/3 ICLK idle
 configuration
In-Reply-To: <1464185756-28401-1-git-send-email-peter.ujfalusi@ti.com>
References: <1464185756-28401-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1464185756-28401-4-git-send-email-peter.ujfalusi@ti.com>

McBSP2/3 module's sidetone module operates using the module's ICLK clock.
When the Sidetone is in use the interface clock of the module must not
idle. The new callback expects to receive the *clk of the module's ick and
not the id number of the McBSP. This will allow us more cleanups and going
to simplify the ICLK handling.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/mach-omap2/mcbsp.c                 | 12 ++++++++++++
 include/linux/platform_data/asoc-ti-mcbsp.h |  1 +
 2 files changed, 13 insertions(+)

diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index b4ac3af1160c..959cb4cb1062 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -48,6 +48,17 @@ static int omap3_enable_st_clock(unsigned int id, bool enable)
 		return omap2_clk_allow_idle(mcbsp_iclks[id]);
 }
 
+static int omap3_mcbsp_force_ick_on(struct clk *clk, bool force_on)
+{
+	if (!clk)
+		return 0;
+
+	if (force_on)
+		return omap2_clk_deny_idle(clk);
+	else
+		return omap2_clk_allow_idle(clk);
+}
+
 static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 {
 	int id, count = 1;
@@ -97,6 +108,7 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 		oh_device[1] = omap_hwmod_lookup((
 		(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
 		pdata->enable_st_clock = omap3_enable_st_clock;
+		pdata->force_ick_on = omap3_mcbsp_force_ick_on;
 		sprintf(clk_name, "mcbsp%d_ick", id);
 		mcbsp_iclks[id] = clk_get(NULL, clk_name);
 		count++;
diff --git a/include/linux/platform_data/asoc-ti-mcbsp.h b/include/linux/platform_data/asoc-ti-mcbsp.h
index 3c73c045f8da..73e5e832fa23 100644
--- a/include/linux/platform_data/asoc-ti-mcbsp.h
+++ b/include/linux/platform_data/asoc-ti-mcbsp.h
@@ -45,6 +45,7 @@ struct omap_mcbsp_platform_data {
 	bool has_wakeup; /* Wakeup capability */
 	bool has_ccr; /* Transceiver has configuration control registers */
 	int (*enable_st_clock)(unsigned int, bool);
+	int (*force_ick_on)(struct clk *clk, bool force_on);
 };
 
 /**
-- 
2.8.2



From javier at osg.samsung.com  Wed May 25 07:22:02 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 25 May 2016 10:22:02 -0400
Subject: [PATCH 2/2] ARM: dts: Add async-bridge clock to MFC power domain
 for Exynos5420
In-Reply-To: <574558DF.1090000@samsung.com>
References: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
 <1464111662-15336-3-git-send-email-javier@osg.samsung.com>
 <574558DF.1090000@samsung.com>
Message-ID: <32174210-ad4e-8fae-1142-80e06dcd319f@osg.samsung.com>

Hello Krzysztof,

On 05/25/2016 03:48 AM, Krzysztof Kozlowski wrote:
> On 05/24/2016 07:41 PM, Javier Martinez Canillas wrote:
>> The MFC IP is also inter-connected by an Async-Bridge so the CLK_ACLK333
>> has to be ungated during a power domain switch. Trying to do it when the
>> clock is gated will fail and lead to an imprecise external abort error
>> when the driver tries to access the MFC registers with the PD disabled.
>>
>> For example, if the s5p-mfc module is removed and the MFC PD turned off:
>>
>> [  186.835606] Power domain power-domain at 10044060 disable failed
>> [  186.835671] s5p-mfc 11000000.codec: Removing 11000000.codec
>> [  186.837670] Power domain power-domain at 10044060 disable failed
>>
>> And when the module is inserted again:
>>
>> [ 2395.176956] s5p_mfc_wait_for_done_dev:34: Interrupt (dev->int_type:0, command:12) timed out
>> [ 2395.177031] s5p_mfc_init_hw:272: Failed to load firmware
>> [ 2395.177384] Unhandled fault: imprecise external abort (0x1406) at 0x00000000
>> [ 2395.177441] pgd = ec3b4000
>> [ 2395.177467] [00000000] *pgd=00000000
>> [ 2395.177507] Internal error: : 1406 [#1] PREEMPT SMP ARM
>> [ 2395.177550] Modules linked in: s5p_mfc mwifiex_sdio mwifiex uvcvideo s5p_jpeg v4l2_mem2mem videobuf2_vmalloc videobuf2_dma_contig videobuf2_memops videobuf2_v4l2 videobuf2_core v4l2_common videodev media [last unloaded: s5p_mfc]
>> [ 2395.177774] CPU: 1 PID: 2382 Comm: v4l_id Tainted: G        W       4.6.0-rc6-next-20160502-00010-g7730dc64d2c1-dirty #179
>> [ 2395.177857] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>> [ 2395.177906] task: ed275500 ti: e6c8c000 task.ti: e6c8c000
>> [ 2395.177996] PC is at s5p_mfc_reset+0x1c4/0x284 [s5p_mfc]
>> [ 2395.178057] LR is at s5p_mfc_reset+0x1a4/0x284 [s5p_mfc]
>>
>> This patch fixes this issue by adding the CLK_ACLK333 as an Async-Bridge
>> clock for the MFC power domain, so the PD configuration works properly.
>>
>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>
>> ---
>>
>>  arch/arm/boot/dts/exynos5420.dtsi | 5 +++--
>>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> Indeed patch #1 is not a hard dependency here because there are no other
> asb clocks. It is entirely obvious but works fine.
>

You are right, the reason why is not a hard dependency is because it fails
anyways so this patch (which will make it fail due the clock being missed)
won't have any effect.
 
> Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> 

Thanks!

> Unless all other patches are meant to current fixes cycle (and/or
> cc-stable), I do not plan to apply it now. I'll take it for v4.8, because:
> 1. Your previous patches are needed. Without them bind/unbind won't work.
> 2. This is not reproducible in a regular driver operation.
> 3. It needs clock change to actually be useful.
> 
> Is it okay?
>

Agreed, that's also why I didn't cc stable on this series.
 
> Best regards,
> Krzysztof
> 

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From peter.ujfalusi at ti.com  Wed May 25 07:20:54 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:20:54 +0300
Subject: [PATCH v4 0/7] ARM/ASoC: OMAP3: Fix McBSP2/3 sidetone support
Message-ID: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>

Hi,

Changes since v3:
- Rebased on next-20160525 [1] to apply cleanly
- Fixed subject line for patch5
- Added Mark's acked-by to the ASoC patches

[1] "ASoC: omap-mcbsp: Enable/disable sidetone block auto clock
gating for omap3" is gone missing from linux-next - it was in next-20160517 and
I'm not sure when it got dropped.

Tony: since Paul did not replied to the series, I'm sending the v4 now, I hope
he will have time to look at this.

Commit message from v3:

Based on the ongoing discussion on v2 (ARM: OMAP3: Fix McBSP2/3 hwmod setup for
sidetone) I have dropped the removal of the sidetone hwmod and only corrected
it. The series now includes all related changes needed to have correct sidetone
support whenever we boot in legacy or in DT mode.

This time the ASoC part have dependency on earlier patches so they can not be
applied separately.

Regards,
Peter
---
Peter Ujfalusi (7):
  ARM: OMAP3: hwmod data: Fix McBSP2/3 sidetone data
  ARM: dts: omap3: Add clocks to McBSP nodes
  ARM: OMAP3: McBSP: New callback for McBSP2/3 ICLK idle configuration
  ARM: OMAP3: pdata-quirks: Add support for McBSP2/3 sidetone handling
  ASoC: omap-mcbsp: Rename omap_mcbsp_sysfs_remove() to
    omap_mcbsp_cleanup()
  ASoC: omap-mcbsp: sidetone: Use the new callback for iclk handling
  ARM: OMAP2+: McBSP: Remove the old iclk allow/deny idle code

 arch/arm/boot/dts/omap3.dtsi                | 10 ++++++++++
 arch/arm/mach-omap2/mcbsp.c                 | 31 ++++++++++++++++-------------
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c  | 24 ++++------------------
 arch/arm/mach-omap2/pdata-quirks.c          | 18 +++++++++++++++++
 include/linux/platform_data/asoc-ti-mcbsp.h |  4 +++-
 sound/soc/omap/mcbsp.c                      | 21 +++++++++++++------
 sound/soc/omap/mcbsp.h                      |  3 ++-
 sound/soc/omap/omap-mcbsp.c                 |  5 ++++-
 8 files changed, 73 insertions(+), 43 deletions(-)

-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 25 07:20:55 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:20:55 +0300
Subject: [PATCH v4 1/7] ARM: OMAP3: hwmod data: Fix McBSP2/3 sidetone data
In-Reply-To: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
References: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1464186061-28639-2-git-send-email-peter.ujfalusi@ti.com>

The McBSPLP's sidetone main clock is the McBSPLP's ICLK, not FCLK as the
sidetone only receives the ICLK from the main McBSP module.
Since the McBSP and sidetone is using the very same clock from PRCM level
the sidetone must not have the prcm section to check the clock status since
the sidetone is only used when McBSP is already configured.
If two separate hwmods looking at the same bit and they would use
pm_runtime in nested way (as it must happen with McBSP and it's ST module)
the hwmod would warn, because the idlest will not match what it is expected
after enable/disable of the clocks.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 24 ++++--------------------
 1 file changed, 4 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 9869a75c5d96..d72ee6185d5e 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1322,16 +1322,8 @@ static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
 	.name		= "mcbsp2_sidetone",
 	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp2_sidetone_irqs,
-	.main_clk	= "mcbsp2_fck",
-	.prcm		= {
-		.omap2 = {
-			.prcm_reg_id = 1,
-			 .module_bit = OMAP3430_EN_MCBSP2_SHIFT,
-			.module_offs = OMAP3430_PER_MOD,
-			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_MCBSP2_SHIFT,
-		},
-	},
+	.main_clk	= "mcbsp2_ick",
+	.flags		= HWMOD_NO_IDLEST,
 };
 
 /* mcbsp3_sidetone */
@@ -1344,16 +1336,8 @@ static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
 	.name		= "mcbsp3_sidetone",
 	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp3_sidetone_irqs,
-	.main_clk	= "mcbsp3_fck",
-	.prcm		= {
-		.omap2 = {
-			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_MCBSP3_SHIFT,
-			.module_offs = OMAP3430_PER_MOD,
-			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_MCBSP3_SHIFT,
-		},
-	},
+	.main_clk	= "mcbsp3_ick",
+	.flags		= HWMOD_NO_IDLEST,
 };
 
 /* SR common */
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 25 07:20:56 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:20:56 +0300
Subject: [PATCH v4 2/7] ARM: dts: omap3: Add clocks to McBSP nodes
In-Reply-To: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
References: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1464186061-28639-3-git-send-email-peter.ujfalusi@ti.com>

Add clock properties to the McBSP nodes. McBSP2 and 3 need to have ick also
since the Sidetone block of these modules are operating using the McBSP
interface clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap3.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 9fbda38528dc..4c3c471d2a83 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -493,6 +493,8 @@
 			dmas = <&sdma 31>,
 			       <&sdma 32>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp1_fck>;
+			clock-names = "fck";
 			status = "disabled";
 		};
 
@@ -511,6 +513,8 @@
 			dmas = <&sdma 33>,
 			       <&sdma 34>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp2_fck>, <&mcbsp2_ick>;
+			clock-names = "fck", "ick";
 			status = "disabled";
 		};
 
@@ -529,6 +533,8 @@
 			dmas = <&sdma 17>,
 			       <&sdma 18>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp3_fck>, <&mcbsp3_ick>;
+			clock-names = "fck", "ick";
 			status = "disabled";
 		};
 
@@ -545,6 +551,8 @@
 			dmas = <&sdma 19>,
 			       <&sdma 20>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp4_fck>;
+			clock-names = "fck";
 			status = "disabled";
 		};
 
@@ -561,6 +569,8 @@
 			dmas = <&sdma 21>,
 			       <&sdma 22>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp5_fck>;
+			clock-names = "fck";
 			status = "disabled";
 		};
 
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 25 07:20:57 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:20:57 +0300
Subject: [PATCH v4 3/7] ARM: OMAP3: McBSP: New callback for McBSP2/3 ICLK idle
 configuration
In-Reply-To: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
References: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1464186061-28639-4-git-send-email-peter.ujfalusi@ti.com>

McBSP2/3 module's sidetone module operates using the module's ICLK clock.
When the Sidetone is in use the interface clock of the module must not
idle. The new callback expects to receive the *clk of the module's ick and
not the id number of the McBSP. This will allow us more cleanups and going
to simplify the ICLK handling.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/mach-omap2/mcbsp.c                 | 12 ++++++++++++
 include/linux/platform_data/asoc-ti-mcbsp.h |  1 +
 2 files changed, 13 insertions(+)

diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index b4ac3af1160c..959cb4cb1062 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -48,6 +48,17 @@ static int omap3_enable_st_clock(unsigned int id, bool enable)
 		return omap2_clk_allow_idle(mcbsp_iclks[id]);
 }
 
+static int omap3_mcbsp_force_ick_on(struct clk *clk, bool force_on)
+{
+	if (!clk)
+		return 0;
+
+	if (force_on)
+		return omap2_clk_deny_idle(clk);
+	else
+		return omap2_clk_allow_idle(clk);
+}
+
 static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 {
 	int id, count = 1;
@@ -97,6 +108,7 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 		oh_device[1] = omap_hwmod_lookup((
 		(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
 		pdata->enable_st_clock = omap3_enable_st_clock;
+		pdata->force_ick_on = omap3_mcbsp_force_ick_on;
 		sprintf(clk_name, "mcbsp%d_ick", id);
 		mcbsp_iclks[id] = clk_get(NULL, clk_name);
 		count++;
diff --git a/include/linux/platform_data/asoc-ti-mcbsp.h b/include/linux/platform_data/asoc-ti-mcbsp.h
index 3c73c045f8da..73e5e832fa23 100644
--- a/include/linux/platform_data/asoc-ti-mcbsp.h
+++ b/include/linux/platform_data/asoc-ti-mcbsp.h
@@ -45,6 +45,7 @@ struct omap_mcbsp_platform_data {
 	bool has_wakeup; /* Wakeup capability */
 	bool has_ccr; /* Transceiver has configuration control registers */
 	int (*enable_st_clock)(unsigned int, bool);
+	int (*force_ick_on)(struct clk *clk, bool force_on);
 };
 
 /**
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 25 07:20:58 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:20:58 +0300
Subject: [PATCH v4 4/7] ARM: OMAP3: pdata-quirks: Add support for McBSP2/3
 sidetone handling
In-Reply-To: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
References: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1464186061-28639-5-git-send-email-peter.ujfalusi@ti.com>

McBSP2/3 module's sidetone module operates using the module's ICLK clock.
When the Sidetone is in use the interface clock of the module must not
idle. To prevent the iclk idling the driver expects to have pdata callback
to call. With this patch the callback is going to be set up for DT boot
also.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/mach-omap2/mcbsp.c                 |  9 +++++++++
 arch/arm/mach-omap2/pdata-quirks.c          | 18 ++++++++++++++++++
 include/linux/platform_data/asoc-ti-mcbsp.h |  2 ++
 3 files changed, 29 insertions(+)

diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index 959cb4cb1062..edf4f41c0135 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -59,6 +59,15 @@ static int omap3_mcbsp_force_ick_on(struct clk *clk, bool force_on)
 		return omap2_clk_allow_idle(clk);
 }
 
+void __init omap3_mcbsp_init_pdata_callback(
+					struct omap_mcbsp_platform_data *pdata)
+{
+	if (!pdata)
+		return;
+
+	pdata->force_ick_on = omap3_mcbsp_force_ick_on;
+}
+
 static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 {
 	int id, count = 1;
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 6571ad959908..ab2b2b2b90e5 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -26,6 +26,7 @@
 #include <linux/platform_data/wkup_m3.h>
 #include <linux/platform_data/pwm_omap_dmtimer.h>
 #include <linux/platform_data/media/ir-rx51.h>
+#include <linux/platform_data/asoc-ti-mcbsp.h>
 #include <plat/dmtimer.h>
 
 #include "common.h"
@@ -505,6 +506,16 @@ static struct platform_device __maybe_unused rx51_lirc_device = {
 	},
 };
 
+#if IS_ENABLED(CONFIG_SND_OMAP_SOC_MCBSP)
+static struct omap_mcbsp_platform_data mcbsp_pdata;
+static void __init omap3_mcbsp_init(void)
+{
+	omap3_mcbsp_init_pdata_callback(&mcbsp_pdata);
+}
+#else
+static void __init omap3_mcbsp_init(void) {}
+#endif
+
 /*
  * Few boards still need auxdata populated before we populate
  * the dev entries in of_platform_populate().
@@ -536,6 +547,11 @@ static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
 	OF_DEV_AUXDATA("ti,am3517-emac", 0x5c000000, "davinci_emac.0",
 		       &am35xx_emac_pdata),
+	/* McBSP modules with sidetone core */
+#if IS_ENABLED(CONFIG_SND_OMAP_SOC_MCBSP)
+	OF_DEV_AUXDATA("ti,omap3-mcbsp", 0x49022000, "49022000.mcbsp", &mcbsp_pdata),
+	OF_DEV_AUXDATA("ti,omap3-mcbsp", 0x49024000, "49024000.mcbsp", &mcbsp_pdata),
+#endif
 #endif
 #ifdef CONFIG_SOC_AM33XX
 	OF_DEV_AUXDATA("ti,am3352-wkup-m3", 0x44d00000, "44d00000.wkup_m3",
@@ -608,6 +624,8 @@ void __init pdata_quirks_init(const struct of_device_id *omap_dt_match_table)
 	    of_machine_is_compatible("ti,omap3"))
 		omap_sdrc_init(NULL, NULL);
 
+	if (of_machine_is_compatible("ti,omap3"))
+		omap3_mcbsp_init();
 	pdata_quirks_check(auxdata_quirks);
 	of_platform_populate(NULL, omap_dt_match_table,
 			     omap_auxdata_lookup, NULL);
diff --git a/include/linux/platform_data/asoc-ti-mcbsp.h b/include/linux/platform_data/asoc-ti-mcbsp.h
index 73e5e832fa23..5530971abf4d 100644
--- a/include/linux/platform_data/asoc-ti-mcbsp.h
+++ b/include/linux/platform_data/asoc-ti-mcbsp.h
@@ -56,4 +56,6 @@ struct omap_mcbsp_dev_attr {
 	const char *sidetone;
 };
 
+void omap3_mcbsp_init_pdata_callback(struct omap_mcbsp_platform_data *pdata);
+
 #endif
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 25 07:20:59 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:20:59 +0300
Subject: [PATCH v4 5/7] ASoC: omap-mcbsp: Rename omap_mcbsp_sysfs_remove() to
 omap_mcbsp_cleanup()
In-Reply-To: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
References: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1464186061-28639-6-git-send-email-peter.ujfalusi@ti.com>

The function will do more then removing the sysfs files in the future.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
Acked-by: Mark Brown <broonie at kernel.org>
---
 sound/soc/omap/mcbsp.c      | 2 +-
 sound/soc/omap/mcbsp.h      | 2 +-
 sound/soc/omap/omap-mcbsp.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
index c7563e230c7d..75cd1761d383 100644
--- a/sound/soc/omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -1080,7 +1080,7 @@ err_thres:
 	return ret;
 }
 
-void omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp)
+void omap_mcbsp_cleanup(struct omap_mcbsp *mcbsp)
 {
 	if (mcbsp->pdata->buffer_size)
 		sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
index 96d1b086bcf8..ce6cbbf923a4 100644
--- a/sound/soc/omap/mcbsp.h
+++ b/sound/soc/omap/mcbsp.h
@@ -349,6 +349,6 @@ int omap_st_disable(struct omap_mcbsp *mcbsp);
 int omap_st_is_enabled(struct omap_mcbsp *mcbsp);
 
 int omap_mcbsp_init(struct platform_device *pdev);
-void omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp);
+void omap_mcbsp_cleanup(struct omap_mcbsp *mcbsp);
 
 #endif /* __ASOC_MCBSP_H */
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index fd99d89de6a8..db07debb4a9c 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -832,7 +832,7 @@ static int asoc_mcbsp_remove(struct platform_device *pdev)
 	if (mcbsp->pdata->ops && mcbsp->pdata->ops->free)
 		mcbsp->pdata->ops->free(mcbsp->id);
 
-	omap_mcbsp_sysfs_remove(mcbsp);
+	omap_mcbsp_cleanup(mcbsp);
 
 	clk_put(mcbsp->fclk);
 
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 25 07:21:00 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:21:00 +0300
Subject: [PATCH v4 6/7] ASoC: omap-mcbsp: sidetone: Use the new callback for
 iclk handling
In-Reply-To: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
References: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1464186061-28639-7-git-send-email-peter.ujfalusi@ti.com>

The McBSP sidetone (in OMAP3 McBSP2 and 3 module) is working with the
module's interface clock. When the sidetone is enabled the iclk must not
idle because it will result in choppy sidetone.
Switch to use the new callback for handling the iclk allow/deny idle
configuration.
For this the driver needs to get the module's ick clock and pass the clk
pointer to the callback.
In DT boot, the pdata-quirk is going to set up the callback for the driver
so save it if it is set in the pdata of the device.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
Acked-by: Mark Brown <broonie at kernel.org>
---
 sound/soc/omap/mcbsp.c      | 19 ++++++++++++++-----
 sound/soc/omap/mcbsp.h      |  1 +
 sound/soc/omap/omap-mcbsp.c |  3 +++
 3 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
index 75cd1761d383..5c3fdfe4c6b9 100644
--- a/sound/soc/omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -257,8 +257,8 @@ static void omap_st_on(struct omap_mcbsp *mcbsp)
 {
 	unsigned int w;
 
-	if (mcbsp->pdata->enable_st_clock)
-		mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
+	if (mcbsp->pdata->force_ick_on)
+		mcbsp->pdata->force_ick_on(mcbsp->st_data->mcbsp_iclk, true);
 
 	/* Enable McBSP Sidetone */
 	w = MCBSP_READ(mcbsp, SSELCR);
@@ -279,8 +279,8 @@ static void omap_st_off(struct omap_mcbsp *mcbsp)
 	w = MCBSP_READ(mcbsp, SSELCR);
 	MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
 
-	if (mcbsp->pdata->enable_st_clock)
-		mcbsp->pdata->enable_st_clock(mcbsp->id, 0);
+	if (mcbsp->pdata->force_ick_on)
+		mcbsp->pdata->force_ick_on(mcbsp->st_data->mcbsp_iclk, false);
 }
 
 static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
@@ -938,6 +938,13 @@ static int omap_st_add(struct omap_mcbsp *mcbsp, struct resource *res)
 	if (!st_data)
 		return -ENOMEM;
 
+	st_data->mcbsp_iclk = clk_get(mcbsp->dev, "ick");
+	if (IS_ERR(st_data->mcbsp_iclk)) {
+		dev_warn(mcbsp->dev,
+			 "Failed to get ick, sidetone might be broken\n");
+		st_data->mcbsp_iclk = NULL;
+	}
+
 	st_data->io_base_st = devm_ioremap(mcbsp->dev, res->start,
 					   resource_size(res));
 	if (!st_data->io_base_st)
@@ -1085,6 +1092,8 @@ void omap_mcbsp_cleanup(struct omap_mcbsp *mcbsp)
 	if (mcbsp->pdata->buffer_size)
 		sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
 
-	if (mcbsp->st_data)
+	if (mcbsp->st_data) {
 		sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
+		clk_put(mcbsp->st_data->mcbsp_iclk);
+	}
 }
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
index ce6cbbf923a4..61e93b1c185d 100644
--- a/sound/soc/omap/mcbsp.h
+++ b/sound/soc/omap/mcbsp.h
@@ -280,6 +280,7 @@ struct omap_mcbsp_reg_cfg {
 
 struct omap_mcbsp_st_data {
 	void __iomem *io_base_st;
+	struct clk *mcbsp_iclk;
 	bool running;
 	bool enabled;
 	s16 taps[128];	/* Sidetone filter coefficients */
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index db07debb4a9c..d018e966e533 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -788,6 +788,7 @@ static int asoc_mcbsp_probe(struct platform_device *pdev)
 	match = of_match_device(omap_mcbsp_of_match, &pdev->dev);
 	if (match) {
 		struct device_node *node = pdev->dev.of_node;
+		struct omap_mcbsp_platform_data *pdata_quirk = pdata;
 		int buffer_size;
 
 		pdata = devm_kzalloc(&pdev->dev,
@@ -799,6 +800,8 @@ static int asoc_mcbsp_probe(struct platform_device *pdev)
 		memcpy(pdata, match->data, sizeof(*pdata));
 		if (!of_property_read_u32(node, "ti,buffer-size", &buffer_size))
 			pdata->buffer_size = buffer_size;
+		if (pdata_quirk)
+			pdata->force_ick_on = pdata_quirk->force_ick_on;
 	} else if (!pdata) {
 		dev_err(&pdev->dev, "missing platform data.\n");
 		return -EINVAL;
-- 
2.8.2



From peter.ujfalusi at ti.com  Wed May 25 07:21:01 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:21:01 +0300
Subject: [PATCH v4 7/7] ARM: OMAP2+: McBSP: Remove the old iclk allow/deny
 idle code
In-Reply-To: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
References: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <1464186061-28639-8-git-send-email-peter.ujfalusi@ti.com>

The new pdata callback (force_ick_on) is now used by the driver and the old
callback related code can be removed.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/mach-omap2/mcbsp.c                 | 18 ------------------
 include/linux/platform_data/asoc-ti-mcbsp.h |  1 -
 2 files changed, 19 deletions(-)

diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index edf4f41c0135..fc04be74e064 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -34,20 +34,6 @@
 #include "cm3xxx.h"
 #include "cm-regbits-34xx.h"
 
-static struct clk *mcbsp_iclks[5];
-
-static int omap3_enable_st_clock(unsigned int id, bool enable)
-{
-	/*
-	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
-	 * are enabled or sidetones start sounding ugly.
-	 */
-	if (enable)
-		return omap2_clk_deny_idle(mcbsp_iclks[id]);
-	else
-		return omap2_clk_allow_idle(mcbsp_iclks[id]);
-}
-
 static int omap3_mcbsp_force_ick_on(struct clk *clk, bool force_on)
 {
 	if (!clk)
@@ -75,7 +61,6 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 	struct omap_hwmod *oh_device[2];
 	struct omap_mcbsp_platform_data *pdata = NULL;
 	struct platform_device *pdev;
-	char clk_name[11];
 
 	sscanf(oh->name, "mcbsp%d", &id);
 
@@ -116,10 +101,7 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 	if (oh->dev_attr) {
 		oh_device[1] = omap_hwmod_lookup((
 		(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
-		pdata->enable_st_clock = omap3_enable_st_clock;
 		pdata->force_ick_on = omap3_mcbsp_force_ick_on;
-		sprintf(clk_name, "mcbsp%d_ick", id);
-		mcbsp_iclks[id] = clk_get(NULL, clk_name);
 		count++;
 	}
 	pdev = omap_device_build_ss(name, id, oh_device, count, pdata,
diff --git a/include/linux/platform_data/asoc-ti-mcbsp.h b/include/linux/platform_data/asoc-ti-mcbsp.h
index 5530971abf4d..e684543254f3 100644
--- a/include/linux/platform_data/asoc-ti-mcbsp.h
+++ b/include/linux/platform_data/asoc-ti-mcbsp.h
@@ -44,7 +44,6 @@ struct omap_mcbsp_platform_data {
 	/* McBSP platform and instance specific features */
 	bool has_wakeup; /* Wakeup capability */
 	bool has_ccr; /* Transceiver has configuration control registers */
-	int (*enable_st_clock)(unsigned int, bool);
 	int (*force_ick_on)(struct clk *clk, bool force_on);
 };
 
-- 
2.8.2



From marc.zyngier at arm.com  Wed May 25 07:26:33 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 25 May 2016 15:26:33 +0100
Subject: [PATCH v2 1/7] KVM: arm/arm64: vgic-v2: Clear all dirty LRs
In-Reply-To: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
References: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464186399-16604-2-git-send-email-marc.zyngier@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

When saving the state of the list registers, it is critical to
reset them zero, as we could otherwise leave unexpected EOI
interrupts pending for virtual level interrupts.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/hyp/vgic-v2-sr.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index a3f12b3..3a3a699 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -100,12 +100,11 @@ static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
 		if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
 			continue;
 
-		if (cpu_if->vgic_elrsr & (1UL << i)) {
+		if (cpu_if->vgic_elrsr & (1UL << i))
 			cpu_if->vgic_lr[i] &= ~GICH_LR_STATE;
-			continue;
-		}
+		else
+			cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
 
-		cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
 		writel_relaxed(0, base + GICH_LR0 + (i * 4));
 	}
 }
-- 
2.1.4



From marc.zyngier at arm.com  Wed May 25 07:26:32 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 25 May 2016 15:26:32 +0100
Subject: [PATCH v2 0/7] vgic fixes for 4.7-rc1
Message-ID: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>

The dust has not yet settled on the new vgic, but here's the first
batch of fixes anyway!

The first two patches are courtesy of Christoffer, who noticed that we
fail to clear LRs that generate a maintenance interrupt, leading to
potential screaming interrupts. This bug already exists in the current
mainline (cc stable?)

The next two address a bug where we fail to properly resample the line
level on exit, which could result in spurious interrupts being
injected. This is specific to the new vgic implementation.

The following two patches tighten our GICv3 emulation by preventing
the guest from changing the SRE setting. This bug already exists in
mainline, though it is hardly critical.

The last patch is actually a performance optimization: if the guest is
using GICv3, we can drop a number of barriers (since we don't need to
change SRE, and there is no memory-mapped view to synchronize
with). This results in a world switch that is 2.5% faster on my LS2085
box when running GICv3 guests. I suspect that the bigger the box, the
bigger this impact this change will have (system-wide DSBs don't really
come cheap).

These patches have been tested on top of the kvmarm/next branch.

Thanks,

	M.

- From v1: Fix pending bit regeneration by adding the soft_pending bit
  to the mix.

Christoffer Dall (2):
  KVM: arm/arm64: vgic-v2: Clear all dirty LRs
  KVM: arm/arm64: vgic-v3: Clear all dirty LRs

Marc Zyngier (5):
  KVM: arm/arm64: vgic-v2: Always resample level interrupts
  KVM: arm/arm64: vgic-v3: Always resample level interrupts
  arm64: KVM: Make ICC_SRE_EL1 access return the configured SRE value
  arm64: KVM: vgic-v3: Prevent the guest from messing with ICC_SRE_EL1
  arm64: KVM: vgic-v3: Relax synchronization when SRE==1

 arch/arm64/kvm/hyp/vgic-v3-sr.c | 36 +++++++++++++++++++++---------------
 arch/arm64/kvm/sys_regs.c       | 13 ++++++++++++-
 virt/kvm/arm/hyp/vgic-v2-sr.c   |  7 +++----
 virt/kvm/arm/vgic/vgic-v2.c     | 14 +++++++++-----
 virt/kvm/arm/vgic/vgic-v3.c     | 14 +++++++++-----
 5 files changed, 54 insertions(+), 30 deletions(-)

-- 
2.1.4



From marc.zyngier at arm.com  Wed May 25 07:26:35 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 25 May 2016 15:26:35 +0100
Subject: [PATCH v2 3/7] KVM: arm/arm64: vgic-v2: Always resample level
 interrupts
In-Reply-To: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
References: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464186399-16604-4-git-send-email-marc.zyngier@arm.com>

When reading back from the list registers, we need to perform
two actions for level interrupts:
1) clear the soft-pending bit if the interrupt is not pending
   anymore *in the list register*
2) resample the line level and propagate it to the pending state

But these two actions shouldn't be linked, and we should *always*
resample the line level, no matter what state is in the list
register. Otherwise, we may end-up injecting spurious interrupts
that have been already retired.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/vgic/vgic-v2.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 8ad42c2..e31405e 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -112,11 +112,15 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
 			}
 		}
 
-		/* Clear soft pending state when level IRQs have been acked */
-		if (irq->config == VGIC_CONFIG_LEVEL &&
-		    !(val & GICH_LR_PENDING_BIT)) {
-			irq->soft_pending = false;
-			irq->pending = irq->line_level;
+		/*
+		 * Clear soft pending state when level irqs have been acked.
+		 * Always regenerate the pending state.
+		 */
+		if (irq->config == VGIC_CONFIG_LEVEL) {
+			if (!(val & GICH_LR_PENDING_BIT))
+				irq->soft_pending = false;
+
+			irq->pending = irq->line_level || irq->soft_pending;
 		}
 
 		spin_unlock(&irq->irq_lock);
-- 
2.1.4



From marc.zyngier at arm.com  Wed May 25 07:26:34 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 25 May 2016 15:26:34 +0100
Subject: [PATCH v2 2/7] KVM: arm/arm64: vgic-v3: Clear all dirty LRs
In-Reply-To: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
References: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464186399-16604-3-git-send-email-marc.zyngier@arm.com>

From: Christoffer Dall <christoffer.dall at linaro.org>

When saving the state of the list registers, it is critical to
reset them zero, as we could otherwise leave unexpected EOI
interrupts pending for virtual level interrupts.

Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm64/kvm/hyp/vgic-v3-sr.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c
index fff7cd4..3129df9 100644
--- a/arch/arm64/kvm/hyp/vgic-v3-sr.c
+++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c
@@ -190,12 +190,11 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 			if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
 				continue;
 
-			if (cpu_if->vgic_elrsr & (1 << i)) {
+			if (cpu_if->vgic_elrsr & (1 << i))
 				cpu_if->vgic_lr[i] &= ~ICH_LR_STATE;
-				continue;
-			}
+			else
+				cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
 
-			cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
 			__gic_v3_set_lr(0, i);
 		}
 
-- 
2.1.4



From marc.zyngier at arm.com  Wed May 25 07:26:36 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 25 May 2016 15:26:36 +0100
Subject: [PATCH v2 4/7] KVM: arm/arm64: vgic-v3: Always resample level
 interrupts
In-Reply-To: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
References: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464186399-16604-5-git-send-email-marc.zyngier@arm.com>

When reading back from the list registers, we need to perform
two actions for level interrupts:
1) clear the soft-pending bit if the interrupt is not pending
   anymore *in the list register*
2) resample the line level and propagate it to the pending state

But these two actions shouldn't be linked, and we should *always*
resample the line level, no matter what state is in the list
register. Otherwise, we may end-up injecting spurious interrupts
that have been already retired.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 virt/kvm/arm/vgic/vgic-v3.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 336a461..346b4ad 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -101,11 +101,15 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
 			}
 		}
 
-		/* Clear soft pending state when level irqs have been acked */
-		if (irq->config == VGIC_CONFIG_LEVEL &&
-		    !(val & ICH_LR_PENDING_BIT)) {
-			irq->soft_pending = false;
-			irq->pending = irq->line_level;
+		/*
+		 * Clear soft pending state when level irqs have been acked.
+		 * Always regenerate the pending state.
+		 */
+		if (irq->config == VGIC_CONFIG_LEVEL) {
+			if (!(val & ICH_LR_PENDING_BIT))
+				irq->soft_pending = false;
+
+			irq->pending = irq->line_level || irq->soft_pending;
 		}
 
 		spin_unlock(&irq->irq_lock);
-- 
2.1.4



From marc.zyngier at arm.com  Wed May 25 07:26:38 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 25 May 2016 15:26:38 +0100
Subject: [PATCH v2 6/7] arm64: KVM: vgic-v3: Prevent the guest from messing
 with ICC_SRE_EL1
In-Reply-To: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
References: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464186399-16604-7-git-send-email-marc.zyngier@arm.com>

Both our GIC emulations are "strict", in the sense that we either
emulate a GICv2 or a GICv3, and not a GICv3 with GICv2 legacy
support.

But when running on a GICv3 host, we still allow the guest to
tinker with the ICC_SRE_EL1 register during its time slice:
it can switch SRE off, observe that it is off, and yet on the
next world switch, find the SRE bit to be set again. Not very
nice.

An obvious solution is to always trap accesses to ICC_SRE_EL1
(by clearing ICC_SRE_EL2.Enable), and to let the handler return
the programmed value on a read, or ignore the write.

That way, the guest can always observe that our GICv3 is SRE==1
only.

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm64/kvm/hyp/vgic-v3-sr.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c
index 3129df9..40c3b4c 100644
--- a/arch/arm64/kvm/hyp/vgic-v3-sr.c
+++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c
@@ -313,10 +313,8 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 	 * Prevent the guest from touching the GIC system registers if
 	 * SRE isn't enabled for GICv3 emulation.
 	 */
-	if (!cpu_if->vgic_sre) {
-		write_gicreg(read_gicreg(ICC_SRE_EL2) & ~ICC_SRE_EL2_ENABLE,
-			     ICC_SRE_EL2);
-	}
+	write_gicreg(read_gicreg(ICC_SRE_EL2) & ~ICC_SRE_EL2_ENABLE,
+		     ICC_SRE_EL2);
 }
 
 void __hyp_text __vgic_v3_init_lrs(void)
-- 
2.1.4



From marc.zyngier at arm.com  Wed May 25 07:26:39 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 25 May 2016 15:26:39 +0100
Subject: [PATCH v2 7/7] arm64: KVM: vgic-v3: Relax synchronization when SRE==1
In-Reply-To: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
References: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464186399-16604-8-git-send-email-marc.zyngier@arm.com>

The GICv3 backend of the vgic is quite barrier heavy, in order
to ensure synchronization of the system registers and the
memory mapped view for a potential GICv2 guest.

But when the guest is using a GICv3 model, there is absolutely
no need to execute all these heavy barriers, and it is actually
beneficial to avoid them altogether.

This patch makes the synchonization conditional, and ensures
that we do not change the EL1 SRE settings if we do not need to.

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm64/kvm/hyp/vgic-v3-sr.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c
index 40c3b4c..5f8f80b 100644
--- a/arch/arm64/kvm/hyp/vgic-v3-sr.c
+++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c
@@ -169,7 +169,8 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 	 * Make sure stores to the GIC via the memory mapped interface
 	 * are now visible to the system register interface.
 	 */
-	dsb(st);
+	if (!cpu_if->vgic_sre)
+		dsb(st);
 
 	cpu_if->vgic_vmcr  = read_gicreg(ICH_VMCR_EL2);
 
@@ -235,8 +236,12 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 
 	val = read_gicreg(ICC_SRE_EL2);
 	write_gicreg(val | ICC_SRE_EL2_ENABLE, ICC_SRE_EL2);
-	isb(); /* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
-	write_gicreg(1, ICC_SRE_EL1);
+
+	if (!cpu_if->vgic_sre) {
+		/* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
+		isb();
+		write_gicreg(1, ICC_SRE_EL1);
+	}
 }
 
 void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
@@ -255,8 +260,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 	 * been actually programmed with the value we want before
 	 * starting to mess with the rest of the GIC.
 	 */
-	write_gicreg(cpu_if->vgic_sre, ICC_SRE_EL1);
-	isb();
+	if (!cpu_if->vgic_sre) {
+		write_gicreg(0, ICC_SRE_EL1);
+		isb();
+	}
 
 	val = read_gicreg(ICH_VTR_EL2);
 	max_lr_idx = vtr_to_max_lr_idx(val);
@@ -305,8 +312,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 	 * (re)distributors. This ensure the guest will read the
 	 * correct values from the memory-mapped interface.
 	 */
-	isb();
-	dsb(sy);
+	if (!cpu_if->vgic_sre) {
+		isb();
+		dsb(sy);
+	}
 	vcpu->arch.vgic_cpu.live_lrs = live_lrs;
 
 	/*
-- 
2.1.4



From marc.zyngier at arm.com  Wed May 25 07:26:37 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 25 May 2016 15:26:37 +0100
Subject: [PATCH v2 5/7] arm64: KVM: Make ICC_SRE_EL1 access return the
 configured SRE value
In-Reply-To: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
References: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <1464186399-16604-6-git-send-email-marc.zyngier@arm.com>

When we trap ICC_SRE_EL1, we handle it as RAZ/WI. It would be
more correct to actual make it RO, and return the configured
value when read.

Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm64/kvm/sys_regs.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 7bbe3ff..a57d650 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -134,6 +134,17 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
 	return true;
 }
 
+static bool access_gic_sre(struct kvm_vcpu *vcpu,
+			   struct sys_reg_params *p,
+			   const struct sys_reg_desc *r)
+{
+	if (p->is_write)
+		return ignore_write(vcpu, p);
+
+	p->regval = vcpu->arch.vgic_cpu.vgic_v3.vgic_sre;
+	return true;
+}
+
 static bool trap_raz_wi(struct kvm_vcpu *vcpu,
 			struct sys_reg_params *p,
 			const struct sys_reg_desc *r)
@@ -958,7 +969,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	  access_gic_sgi },
 	/* ICC_SRE_EL1 */
 	{ Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b101),
-	  trap_raz_wi },
+	  access_gic_sre },
 
 	/* CONTEXTIDR_EL1 */
 	{ Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b001),
-- 
2.1.4



From andre.przywara at arm.com  Wed May 25 07:34:32 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 25 May 2016 15:34:32 +0100
Subject: [PATCH v4 10/12] KVM: arm64: implement ITS command queue command
 handlers
In-Reply-To: <3F572EDF-329A-4D6D-BA06-7E6F3B89C819@caviumnetworks.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-11-git-send-email-andre.przywara@arm.com>
 <3F572EDF-329A-4D6D-BA06-7E6F3B89C819@caviumnetworks.com>
Message-ID: <904cef0a-4f9e-2510-c6bc-19c45bd2ef1e@arm.com>

Hi Tirumalesh,

....

>> +/* The MOVI command moves an ITTE to a different collection. */
>> +static int vits_cmd_handle_movi(struct kvm *kvm, u64 *its_cmd)
>> +{
>> +	struct vgic_its *its = &kvm->arch.vgic.its;
>> +	u32 device_id = its_cmd_get_deviceid(its_cmd);
>> +	u32 event_id = its_cmd_get_id(its_cmd);
>> +	u32 coll_id = its_cmd_get_collection(its_cmd);
>> +	struct its_itte *itte;
>> +	struct its_collection *collection;
>> +	int ret;
>> +
>> +	spin_lock(&its->lock);
>> +	itte = find_itte(kvm, device_id, event_id);
>> +	if (!itte) {
>> +		ret = E_ITS_MOVI_UNMAPPED_INTERRUPT;
>> +		goto out_unlock;
>> +	}
>> +	if (!its_is_collection_mapped(itte->collection)) {
>> +		ret = E_ITS_MOVI_UNMAPPED_COLLECTION;
>> +		goto out_unlock;
>> +	}
>> +
>> +	collection = find_collection(kvm, coll_id);
>> +	if (!its_is_collection_mapped(collection)) {
>> +		ret = E_ITS_MOVI_UNMAPPED_COLLECTION;
>> +		goto out_unlock;
>> +	}
>> +
>> +	itte->collection = collection;
>> +	update_affinity(kvm, collection);
>> +
> 
> Not planning to send this down to Physical ITS in case of VFIO for performance reasons?

Why should we?
So in general: this virtual ITS is a purely emulated one, it does not
depend on any hardware ITS to work. Also at this point we don't focus on
VFIO (in fact this doesn't even work without further patches).
So it would break abstraction to pass on commands. Besides I don't see
the benefit of passing a 32-byte structure around, which needs to be
validated (and thus touched) anyway.
Also in this particular case: Why would a change of the _virtual_
affinity affect a VFIO IRQ on the host at all?
Actually the collection IDs of the guests are _totally_ separate and
unrelated to a host collection ID.

Cheers,
Andre


From agustinv at codeaurora.org  Wed May 25 07:37:36 2016
From: agustinv at codeaurora.org (agustinv at codeaurora.org)
Date: Wed, 25 May 2016 10:37:36 -0400
Subject: [PATCH V3 0/2] irqchip: qcom: Add IRQ combiner driver
In-Reply-To: <1463156203-10970-1-git-send-email-agustinv@codeaurora.org>
References: <1463156203-10970-1-git-send-email-agustinv@codeaurora.org>
Message-ID: <a7f49bb9ecfb9181d9d9f76cc45d6dbf@codeaurora.org>

Adding linux-arm-kernel and linux-acpi

On 2016-05-13 12:16, Agustin Vega-Frias wrote:
> Add support for IRQ combiners in the Top-level Control and Status
> Registers (TCSR) hardware block in Qualcomm Technologies chips.
> 
> The first patch adds support for ResourceSource/IRQ domain mapping
> when using Extended IRQ Resources with a specific ResourceSource.
> The core ACPI resource management code has been changed to lookup
> the IRQ domain when an IRQ resource indicates a ResourceSource,
> and register the IRQ on that domain, instead of a GSI.
> 
> The second patch takes advantage of the new capabilities to implement
> the driver for the IRQ combiners.
> 
> Changes V1 -> V2:
> * Remove use of GPIO library for the combiner
> * Refactor to use fwnode/ResourceSource to IRQ domain mapping
>   introduced in ACPI core
> 
> Changes V2 -> V3:
> * Removed parsing of _PRS to find IRQs
> * Removed acpi_irq_domain_create and acpi_irq_domain_remove
> 
> Agustin Vega-Frias (2):
>   ACPI: Add support for ResourceSource/IRQ domain mapping
>   irqchip: qcom: Add IRQ combiner driver
> 
>  drivers/acpi/Makefile               |   1 +
>  drivers/acpi/irqdomain.c            | 108 +++++++++++
>  drivers/acpi/resource.c             |  23 ++-
>  drivers/irqchip/Kconfig             |   8 +
>  drivers/irqchip/Makefile            |   1 +
>  drivers/irqchip/qcom-irq-combiner.c | 344 
> ++++++++++++++++++++++++++++++++++++
>  include/linux/acpi.h                |   6 +
>  7 files changed, 483 insertions(+), 8 deletions(-)
>  create mode 100644 drivers/acpi/irqdomain.c
>  create mode 100644 drivers/irqchip/qcom-irq-combiner.c
> 
> --
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
> Forum,
> a Linux Foundation Collaborative Project.

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


From agustinv at codeaurora.org  Wed May 25 07:38:07 2016
From: agustinv at codeaurora.org (agustinv at codeaurora.org)
Date: Wed, 25 May 2016 10:38:07 -0400
Subject: [PATCH V3 1/2] ACPI: Add support for ResourceSource/IRQ domain
 mapping
In-Reply-To: <1463156203-10970-2-git-send-email-agustinv@codeaurora.org>
References: <1463156203-10970-1-git-send-email-agustinv@codeaurora.org>
 <1463156203-10970-2-git-send-email-agustinv@codeaurora.org>
Message-ID: <24448d48e2e62cec20993d0d0ac96737@codeaurora.org>

Adding linux-arm-kernel and linux-acpi

On 2016-05-13 12:16, Agustin Vega-Frias wrote:
> This allows irqchip drivers to associate an ACPI DSDT device to
> an IRQ domain and provides support for using the ResourceSource
> in Extended IRQ Resources to find the domain and map the IRQs
> specified on that domain.
> 
> Signed-off-by: Agustin Vega-Frias <agustinv at codeaurora.org>
> ---
>  drivers/acpi/Makefile    |   1 +
>  drivers/acpi/irqdomain.c | 108 
> +++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/acpi/resource.c  |  23 ++++++----
>  include/linux/acpi.h     |   6 +++
>  4 files changed, 130 insertions(+), 8 deletions(-)
>  create mode 100644 drivers/acpi/irqdomain.c
> 
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index b12fa64..79db78f 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -56,6 +56,7 @@ acpi-$(CONFIG_ACPI_NUMA)	+= numa.o
>  acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
>  acpi-y				+= acpi_lpat.o
>  acpi-$(CONFIG_ACPI_GENERIC_GSI) += gsi.o
> +acpi-y				+= irqdomain.o
> 
>  # These are (potentially) separate modules
> 
> diff --git a/drivers/acpi/irqdomain.c b/drivers/acpi/irqdomain.c
> new file mode 100644
> index 0000000..0fd10a9
> --- /dev/null
> +++ b/drivers/acpi/irqdomain.c
> @@ -0,0 +1,108 @@
> +/*
> + * ACPI ResourceSource/IRQ domain mapping support
> + *
> + * Copyright (c) 2016, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or 
> modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +#include <linux/acpi.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +
> +/**
> + * acpi_irq_domain_register_irq() - Register the mapping for an IRQ 
> produced
> + *                                  by the given acpi_resource_source 
> to a
> + *                                  Linux IRQ number
> + * @source: IRQ source
> + * @rcirq: IRQ number
> + * @trigger: trigger type of the IRQ number to be mapped
> + * @polarity: polarity of the IRQ to be mapped
> + *
> + * Returns: a valid linux IRQ number on success
> + *          -ENODEV if the given acpi_resource_source cannot be found
> + *          -EPROBE_DEFER if the IRQ domain has not been registered
> + *          -EINVAL for all other errors
> + */
> +int acpi_irq_domain_register_irq(struct acpi_resource_source *source,
> u32 rcirq,
> +				 int trigger, int polarity)
> +{
> +	struct irq_domain *domain;
> +	struct acpi_device *device;
> +	acpi_handle handle;
> +	acpi_status status;
> +	unsigned int type;
> +	int ret;
> +
> +	status = acpi_get_handle(NULL, source->string_ptr, &handle);
> +	if (ACPI_FAILURE(status))
> +		return -ENODEV;
> +
> +	device = acpi_bus_get_acpi_device(handle);
> +	if (!device)
> +		return -ENODEV;
> +
> +	domain = irq_find_matching_fwnode(&device->fwnode, DOMAIN_BUS_ANY);
> +	if (!domain) {
> +		ret = -EPROBE_DEFER;
> +		goto out_put_device;
> +	}
> +
> +	type = acpi_dev_get_irq_type(trigger, polarity);
> +	ret = irq_create_mapping(domain, rcirq);
> +	if (ret)
> +		irq_set_irq_type(ret, type);
> +
> +out_put_device:
> +	acpi_bus_put_acpi_device(device);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(acpi_irq_domain_register_irq);
> +
> +/**
> + * acpi_irq_domain_unregister_irq() - Delete the mapping for an IRQ 
> produced
> + *                                    by the given 
> acpi_resource_source to a
> + *                                    Linux IRQ number
> + * @source: IRQ source
> + * @rcirq: IRQ number
> + *
> + * Returns: 0 on success
> + *          -ENODEV if the given acpi_resource_source cannot be found
> + *          -EINVAL for all other errors
> + */
> +int acpi_irq_domain_unregister_irq(struct acpi_resource_source 
> *source,
> +				   u32 rcirq)
> +{
> +	struct irq_domain *domain;
> +	struct acpi_device *device;
> +	acpi_handle handle;
> +	acpi_status status;
> +	int ret = 0;
> +
> +	status = acpi_get_handle(NULL, source->string_ptr, &handle);
> +	if (ACPI_FAILURE(status))
> +		return -ENODEV;
> +
> +	device = acpi_bus_get_acpi_device(handle);
> +	if (!device)
> +		return -ENODEV;
> +
> +	domain = irq_find_matching_fwnode(&device->fwnode, DOMAIN_BUS_ANY);
> +	if (!domain) {
> +		ret = -EINVAL;
> +		goto out_put_device;
> +	}
> +
> +	irq_dispose_mapping(irq_find_mapping(domain, rcirq));
> +
> +out_put_device:
> +	acpi_bus_put_acpi_device(device);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(acpi_irq_domain_unregister_irq);
> diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
> index 56241eb..1551698 100644
> --- a/drivers/acpi/resource.c
> +++ b/drivers/acpi/resource.c
> @@ -381,14 +381,15 @@ static void acpi_dev_irqresource_disabled(struct
> resource *res, u32 gsi)
>  	res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET;
>  }
> 
> -static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
> +static void acpi_dev_get_irqresource(struct resource *res, u32 rcirq,
> +				     struct acpi_resource_source *source,
>  				     u8 triggering, u8 polarity, u8 shareable,
>  				     bool legacy)
>  {
>  	int irq, p, t;
> 
> -	if (!valid_IRQ(gsi)) {
> -		acpi_dev_irqresource_disabled(res, gsi);
> +	if ((source->string_length == 0) && !valid_IRQ(rcirq)) {
> +		acpi_dev_irqresource_disabled(res, rcirq);
>  		return;
>  	}
> 
> @@ -402,12 +403,12 @@ static void acpi_dev_get_irqresource(struct
> resource *res, u32 gsi,
>  	 * using extended IRQ descriptors we take the IRQ configuration
>  	 * from _CRS directly.
>  	 */
> -	if (legacy && !acpi_get_override_irq(gsi, &t, &p)) {
> +	if (legacy && !acpi_get_override_irq(rcirq, &t, &p)) {
>  		u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
>  		u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
> 
>  		if (triggering != trig || polarity != pol) {
> -			pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi,
> +			pr_warning("ACPI: IRQ %d override to %s, %s\n", rcirq,
>  				   t ? "level" : "edge", p ? "low" : "high");
>  			triggering = trig;
>  			polarity = pol;
> @@ -415,12 +416,16 @@ static void acpi_dev_get_irqresource(struct
> resource *res, u32 gsi,
>  	}
> 
>  	res->flags = acpi_dev_irq_flags(triggering, polarity, shareable);
> -	irq = acpi_register_gsi(NULL, gsi, triggering, polarity);
> +	if (source->string_length > 0)
> +		irq = acpi_irq_domain_register_irq(source, rcirq, triggering,
> +						   polarity);
> +	else
> +		irq = acpi_register_gsi(NULL, rcirq, triggering, polarity);
>  	if (irq >= 0) {
>  		res->start = irq;
>  		res->end = irq;
>  	} else {
> -		acpi_dev_irqresource_disabled(res, gsi);
> +		acpi_dev_irqresource_disabled(res, rcirq);
>  	}
>  }
> 
> @@ -448,6 +453,7 @@ bool acpi_dev_resource_interrupt(struct
> acpi_resource *ares, int index,
>  {
>  	struct acpi_resource_irq *irq;
>  	struct acpi_resource_extended_irq *ext_irq;
> +	struct acpi_resource_source dummy = { 0, 0, NULL };
> 
>  	switch (ares->type) {
>  	case ACPI_RESOURCE_TYPE_IRQ:
> @@ -460,7 +466,7 @@ bool acpi_dev_resource_interrupt(struct
> acpi_resource *ares, int index,
>  			acpi_dev_irqresource_disabled(res, 0);
>  			return false;
>  		}
> -		acpi_dev_get_irqresource(res, irq->interrupts[index],
> +		acpi_dev_get_irqresource(res, irq->interrupts[index], &dummy,
>  					 irq->triggering, irq->polarity,
>  					 irq->sharable, true);
>  		break;
> @@ -471,6 +477,7 @@ bool acpi_dev_resource_interrupt(struct
> acpi_resource *ares, int index,
>  			return false;
>  		}
>  		acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
> +					 &ext_irq->resource_source,
>  					 ext_irq->triggering, ext_irq->polarity,
>  					 ext_irq->sharable, false);
>  		break;
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 06ed7e5..f4f515e 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -26,6 +26,7 @@
>  #include <linux/resource_ext.h>
>  #include <linux/device.h>
>  #include <linux/property.h>
> +#include <linux/irqdomain.h>
> 
>  #ifndef _LINUX
>  #define _LINUX
> @@ -294,6 +295,11 @@ int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 
> *gsi);
>  void acpi_set_irq_model(enum acpi_irq_model_id model,
>  			struct fwnode_handle *fwnode);
> 
> +int acpi_irq_domain_register_irq(struct acpi_resource_source *source,
> u32 rcirq,
> +		      int trigger, int polarity);
> +int acpi_irq_domain_unregister_irq(struct acpi_resource_source 
> *source,
> +				   u32 rcirq);
> +
>  #ifdef CONFIG_X86_IO_APIC
>  extern int acpi_get_override_irq(u32 gsi, int *trigger, int 
> *polarity);
>  #else
> --
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
> Forum,
> a Linux Foundation Collaborative Project.

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


From agustinv at codeaurora.org  Wed May 25 07:38:33 2016
From: agustinv at codeaurora.org (agustinv at codeaurora.org)
Date: Wed, 25 May 2016 10:38:33 -0400
Subject: [PATCH V3 2/2] irqchip: qcom: Add IRQ combiner driver
In-Reply-To: <1463156203-10970-3-git-send-email-agustinv@codeaurora.org>
References: <1463156203-10970-1-git-send-email-agustinv@codeaurora.org>
 <1463156203-10970-3-git-send-email-agustinv@codeaurora.org>
Message-ID: <5e01650b27dc2e92ccae50078cdecfb7@codeaurora.org>

Adding linux-arm-kernel and linux-acpi

On 2016-05-13 12:16, Agustin Vega-Frias wrote:
> Driver for interrupt combiners in the Top-level Control and Status
> Registers (TCSR) hardware block in Qualcomm Technologies chips.
> 
> An interrupt combiner in this block combines a set of interrupts by
> OR'ing the individual interrupt signals into a summary interrupt
> signal routed to a parent interrupt controller, and provides read-
> only, 32-bit registers to query the status of individual interrupts.
> The status bit for IRQ n is bit (n % 32) within register (n / 32)
> of the given combiner. Thus, each combiner can be described as a set
> of register offsets and the number of IRQs managed.
> 
> Signed-off-by: Agustin Vega-Frias <agustinv at codeaurora.org>
> ---
>  drivers/irqchip/Kconfig             |   8 +
>  drivers/irqchip/Makefile            |   1 +
>  drivers/irqchip/qcom-irq-combiner.c | 344 
> ++++++++++++++++++++++++++++++++++++
>  3 files changed, 353 insertions(+)
>  create mode 100644 drivers/irqchip/qcom-irq-combiner.c
> 
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index f582e0d..609ff28 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -245,3 +245,11 @@ config IRQ_MXS
>  config MVEBU_ODMI
>  	bool
>  	select GENERIC_MSI_IRQ_DOMAIN
> +
> +config QCOM_IRQ_COMBINER
> +	bool "QCOM IRQ combiner support"
> +	depends on ARCH_QCOM
> +	select IRQ_DOMAIN
> +	help
> +	  Say yes here to add support for the IRQ combiner devices embedded
> +	  in Qualcomm Technologies chips.
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index b03cfcb..05c688b 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -65,3 +65,4 @@ obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
>  obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
>  obj-$(CONFIG_PIC32_EVIC)		+= irq-pic32-evic.o
>  obj-$(CONFIG_MVEBU_ODMI)		+= irq-mvebu-odmi.o
> +obj-$(CONFIG_QCOM_IRQ_COMBINER)		+= qcom-irq-combiner.o
> diff --git a/drivers/irqchip/qcom-irq-combiner.c
> b/drivers/irqchip/qcom-irq-combiner.c
> new file mode 100644
> index 0000000..b4f767c
> --- /dev/null
> +++ b/drivers/irqchip/qcom-irq-combiner.c
> @@ -0,0 +1,344 @@
> +/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or 
> modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +/*
> + * Driver for interrupt combiners in the Top-level Control and Status
> + * Registers (TCSR) hardware block in Qualcomm Technologies chips.
> + * An interrupt combiner in this block combines a set of interrupts by
> + * OR'ing the individual interrupt signals into a summary interrupt
> + * signal routed to a parent interrupt controller, and provides read-
> + * only, 32-bit registers to query the status of individual 
> interrupts.
> + * The status bit for IRQ n is bit (n % 32) within register (n / 32)
> + * of the given combiner. Thus, each combiner can be described as a 
> set
> + * of register offsets and the number of IRQs managed.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/property.h>
> +#include <linux/slab.h>
> +
> +#define REG_SIZE 32
> +
> +struct combiner_reg {
> +	void __iomem *addr;
> +	unsigned long mask;
> +};
> +
> +struct combiner {
> +	struct irq_chip     irq_chip;
> +	struct irq_domain   *domain;
> +	int                 parent_irq;
> +	u32                 nirqs;
> +	u32                 nregs;
> +	struct combiner_reg regs[0];
> +};
> +
> +static inline u32 irq_register(int irq)
> +{
> +	return irq / REG_SIZE;
> +}
> +
> +static inline u32 irq_bit(int irq)
> +{
> +	return irq % REG_SIZE;
> +
> +}
> +
> +static inline int irq_nr(u32 reg, u32 bit)
> +{
> +	return reg * REG_SIZE + bit;
> +}
> +
> +/*
> + * Handler for the cascaded IRQ.
> + */
> +static void combiner_handle_irq(struct irq_desc *desc)
> +{
> +	struct combiner *combiner = irq_desc_get_handler_data(desc);
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	u32 reg;
> +
> +	chained_irq_enter(chip, desc);
> +
> +	for (reg = 0; reg < combiner->nregs; reg++) {
> +		int virq;
> +		int hwirq;
> +		u32 bit;
> +		u32 status;
> +
> +		if (combiner->regs[reg].mask == 0)
> +			continue;
> +
> +		status = readl_relaxed(combiner->regs[reg].addr);
> +		status &= combiner->regs[reg].mask;
> +
> +		while (status) {
> +			bit = __ffs(status);
> +			status &= ~(1 << bit);
> +			hwirq = irq_nr(reg, bit);
> +			virq = irq_find_mapping(combiner->domain, hwirq);
> +			if (virq >= 0)
> +				generic_handle_irq(virq);
> +
> +		}
> +	}
> +
> +	chained_irq_exit(chip, desc);
> +}
> +
> +/*
> + * irqchip callbacks
> + */
> +
> +static void combiner_irq_chip_mask_irq(struct irq_data *data)
> +{
> +	struct combiner *combiner = irq_data_get_irq_chip_data(data);
> +	struct combiner_reg *reg = combiner->regs + 
> irq_register(data->hwirq);
> +
> +	clear_bit(irq_bit(data->hwirq), &reg->mask);
> +}
> +
> +static void combiner_irq_chip_unmask_irq(struct irq_data *data)
> +{
> +	struct combiner *combiner = irq_data_get_irq_chip_data(data);
> +	struct combiner_reg *reg = combiner->regs + 
> irq_register(data->hwirq);
> +
> +	set_bit(irq_bit(data->hwirq), &reg->mask);
> +}
> +
> +#ifdef CONFIG_SMP
> +static int combiner_irq_chip_set_affinity(struct irq_data *data,
> +					 const struct cpumask *mask, bool force)
> +{
> +	struct combiner *combiner = irq_data_get_irq_chip_data(data);
> +	struct irq_data *pdata = irq_get_irq_data(combiner->parent_irq);
> +
> +	if (pdata->chip && pdata->chip->irq_set_affinity)
> +		return pdata->chip->irq_set_affinity(pdata, mask, force);
> +	else
> +		return -EINVAL;
> +}
> +#endif
> +
> +/*
> + * domain callbacks
> + */
> +
> +static int combiner_irq_map(struct irq_domain *domain, unsigned int 
> irq,
> +				   irq_hw_number_t hwirq)
> +{
> +	struct combiner *combiner = domain->host_data;
> +
> +	if (hwirq >= combiner->nirqs)
> +		return -EINVAL;
> +
> +	irq_set_chip_and_handler(irq, &combiner->irq_chip, handle_level_irq);
> +	irq_set_chip_data(irq, combiner);
> +	irq_set_parent(irq, combiner->parent_irq);
> +	irq_set_noprobe(irq);
> +	return 0;
> +}
> +
> +static void combiner_irq_unmap(struct irq_domain *domain, unsigned int 
> irq)
> +{
> +	irq_set_chip_and_handler(irq, NULL, NULL);
> +	irq_set_chip_data(irq, NULL);
> +	irq_set_parent(irq, -1);
> +}
> +
> +static struct irq_domain_ops domain_ops = {
> +	.map = combiner_irq_map,
> +	.unmap = combiner_irq_unmap
> +};
> +
> +/*
> + * Probing and initialization.
> + *
> + * Combiner devices reside inside the TCSR block so the resulting DSDT
> + * topology is:
> + *
> + * Device (TCS0)
> + * {
> + *         Name (_HID, "QCOM80B0") // Qualcomm TCSR controller
> + *         Name (_UID, 0)
> + *
> + *         Method (_CRS, 0x0, Serialized) {
> + *                 Name (RBUF, ResourceTemplate ()
> + *                 {
> + *                         Memory32Fixed (ReadWrite, 0x2E10000, 
> 0x00001000)
> + *                 })
> + *                 Return (RBUF)
> + *         }
> + *
> + *         Device (QIC0)
> + *         {
> + *                 Name(_HID,"QCOM80B1") // Qualcomm TCSR IRQ combiner
> + *                 ...
> + *         } // end Device QIC0
> + *         ...
> + * }
> + *
> + * Thus all combiner devices same the same memory mapping from the 
> parent
> + * device.
> + */
> +
> +static int __init combiner_probe(struct platform_device *pdev)
> +{
> +	struct platform_device *tcsr_pdev;
> +	struct combiner *combiner;
> +	void __iomem *tcsr_base;
> +	size_t alloc_sz;
> +	u32 nregs;
> +	u32 nirqs;
> +
> +	tcsr_pdev = to_platform_device(pdev->dev.parent);
> +	tcsr_base = platform_get_drvdata(tcsr_pdev);
> +	if (!tcsr_base)
> +		return -ENODEV;
> +
> +	if (device_property_read_u32(&pdev->dev, "qcom,combiner-nr-irqs",
> +				     &nirqs)) {
> +		dev_err(&pdev->dev, "Error reading number of IRQs\n");
> +		return -EINVAL;
> +	}
> +
> +	nregs = device_property_read_u32_array(&pdev->dev, 
> "qcom,combiner-regs",
> +					       NULL, 0);
> +	if (nregs < DIV_ROUND_UP(nirqs, REG_SIZE)) {
> +		dev_err(&pdev->dev, "Error reading regs property\n");
> +		return -EINVAL;
> +	}
> +
> +	alloc_sz = sizeof(*combiner) + sizeof(struct combiner_reg) * nregs;
> +	combiner = devm_kzalloc(&pdev->dev, alloc_sz, GFP_KERNEL);
> +	if (combiner) {
> +		int i;
> +		u32 regs[nregs];
> +
> +		if (device_property_read_u32_array(&pdev->dev,
> +						   "qcom,combiner-regs",
> +						   regs, nregs)) {
> +			dev_err(&pdev->dev, "Error reading regs property\n");
> +			return -EINVAL;
> +		}
> +
> +		combiner->nirqs = nirqs;
> +		combiner->nregs = nregs;
> +		for (i = 0; i < nregs; i++) {
> +			combiner->regs[i].addr = tcsr_base + regs[i];
> +			combiner->regs[i].mask = 0;
> +		}
> +	} else {
> +		return -ENOMEM;
> +	}
> +
> +	combiner->irq_chip.irq_mask   = combiner_irq_chip_mask_irq;
> +	combiner->irq_chip.irq_unmask = combiner_irq_chip_unmask_irq;
> +#ifdef CONFIG_SMP
> +	combiner->irq_chip.irq_set_affinity = combiner_irq_chip_set_affinity;
> +#endif
> +
> +	combiner->parent_irq = platform_get_irq(pdev, 0);
> +	if (combiner->parent_irq <= 0) {
> +		dev_err(&pdev->dev, "Error getting IRQ resource\n");
> +		return -EINVAL;
> +	}
> +
> +	combiner->domain = irq_domain_create_linear(pdev->dev.fwnode, nirqs,
> +						    &domain_ops, combiner);
> +	if (!combiner->domain)
> +		/* Errors printed by irq_domain_create_linear */
> +		return -ENODEV;
> +
> +	irq_set_chained_handler_and_data(combiner->parent_irq,
> +					 combiner_handle_irq, combiner);
> +
> +	if (device_property_read_string(&pdev->dev, "qcom,combiner-name",
> +					&combiner->irq_chip.name) != 0)
> +		combiner->irq_chip.name = "qcom-irq-combiner";
> +
> +	dev_info(&pdev->dev, "Initialized with [p=%d,n=%d,r=%p]\n",
> +		 combiner->parent_irq, nirqs, combiner->regs[0].addr);
> +	return 0;
> +}
> +
> +static const struct acpi_device_id qcom_irq_combiner_acpi_match[] = {
> +	{ "QCOM80B1", },
> +	{ }
> +};
> +
> +static struct platform_driver qcom_irq_combiner_probe = {
> +	.driver = {
> +		.name = "qcom-irq-combiner",
> +		.owner = THIS_MODULE,
> +		.acpi_match_table = ACPI_PTR(qcom_irq_combiner_acpi_match),
> +	},
> +	.probe = combiner_probe,
> +};
> +
> +static int __init register_qcom_irq_combiner(void)
> +{
> +	return platform_driver_register(&qcom_irq_combiner_probe);
> +}
> +arch_initcall(register_qcom_irq_combiner);
> +
> +static int __init tcsr_probe(struct platform_device *pdev)
> +{
> +	struct resource *mr;
> +	void __iomem *tcsr_base;
> +
> +	mr = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (mr == NULL) {
> +		dev_err(&pdev->dev, "Error getting memory resource\n");
> +		return -EINVAL;
> +	}
> +
> +	tcsr_base = devm_ioremap_resource(&pdev->dev, mr);
> +	if (IS_ERR(tcsr_base)) {
> +		dev_err(&pdev->dev, "Error mapping memory resource\n");
> +		return PTR_ERR(tcsr_base);
> +	}
> +
> +	dev_info(&pdev->dev, "Initialized TCSR block @%pa\n", &mr->start);
> +	platform_set_drvdata(pdev, tcsr_base);
> +	return 0;
> +}
> +
> +static const struct acpi_device_id qcom_tcsr_acpi_match[] = {
> +	{ "QCOM80B0", },
> +	{ }
> +};
> +
> +static struct platform_driver qcom_tcsr_probe = {
> +	.driver = {
> +		.name = "qcom-tcsr",
> +		.owner = THIS_MODULE,
> +		.acpi_match_table = ACPI_PTR(qcom_tcsr_acpi_match),
> +	},
> +	.probe = tcsr_probe,
> +};
> +
> +static int __init register_qcom_tcsr(void)
> +{
> +	return platform_driver_register(&qcom_tcsr_probe);
> +}
> +arch_initcall(register_qcom_tcsr);
> --
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
> Forum,
> a Linux Foundation Collaborative Project.

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


From peter.ujfalusi at ti.com  Wed May 25 07:37:36 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Wed, 25 May 2016 17:37:36 +0300
Subject: [PATCH v4 0/7] ARM/ASoC: OMAP3: Fix McBSP2/3 sidetone support
In-Reply-To: <1464185756-28401-1-git-send-email-peter.ujfalusi@ti.com>
References: <1464185756-28401-1-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <a709475e-03b5-69ef-01d4-ef3919d2b4e3@ti.com>

Hi,

my git send-email got interrupted by my ISP :o
The complete series should be up by now.

Sorry about it.

-- 
P?ter

On 05/25/2016 05:15 PM, Peter Ujfalusi wrote:
> Hi,
> 
> Changes since v3:
> - Rebased on next-20160525 [1] to apply cleanly
> - Fixed subject line for patch5
> - Added Mark's acked-by to the ASoC patches
> 
> [1] "ASoC: omap-mcbsp: Enable/disable sidetone block auto clock
> gating for omap3" is gone missing from linux-next - it was in next-20160517 and
> I'm not sure when it got dropped.
> 
> Tony: since Paul did not replied to the series, I'm sending the v4 now, I hope
> he will have time to look at this.
> 
> Commit message from v3:
> 
> Based on the ongoing discussion on v2 (ARM: OMAP3: Fix McBSP2/3 hwmod setup for
> sidetone) I have dropped the removal of the sidetone hwmod and only corrected
> it. The series now includes all related changes needed to have correct sidetone
> support whenever we boot in legacy or in DT mode.
> 
> This time the ASoC part have dependency on earlier patches so they can not be
> applied separately.
> 
> Regards,
> Peter
> ---
> Peter Ujfalusi (7):
>   ARM: OMAP3: hwmod data: Fix McBSP2/3 sidetone data
>   ARM: dts: omap3: Add clocks to McBSP nodes
>   ARM: OMAP3: McBSP: New callback for McBSP2/3 ICLK idle configuration
>   ARM: OMAP3: pdata-quirks: Add support for McBSP2/3 sidetone handling
>   ASoC: omap-mcbsp: Rename omap_mcbsp_sysfs_remove() to
>     omap_mcbsp_cleanup()
>   ASoC: omap-mcbsp: sidetone: Use the new callback for iclk handling
>   ARM: OMAP2+: McBSP: Remove the old iclk allow/deny idle code
> 
>  arch/arm/boot/dts/omap3.dtsi                | 10 ++++++++++
>  arch/arm/mach-omap2/mcbsp.c                 | 31 ++++++++++++++++-------------
>  arch/arm/mach-omap2/omap_hwmod_3xxx_data.c  | 24 ++++------------------
>  arch/arm/mach-omap2/pdata-quirks.c          | 18 +++++++++++++++++
>  include/linux/platform_data/asoc-ti-mcbsp.h |  4 +++-
>  sound/soc/omap/mcbsp.c                      | 21 +++++++++++++------
>  sound/soc/omap/mcbsp.h                      |  3 ++-
>  sound/soc/omap/omap-mcbsp.c                 |  5 ++++-
>  8 files changed, 73 insertions(+), 43 deletions(-)
> 



From catalin.marinas at arm.com  Wed May 25 07:42:26 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 25 May 2016 15:42:26 +0100
Subject: [PATCH v7 13/15] ACPI / processor: Add acpi_map_madt_entry().
In-Reply-To: <1464129345-18985-14-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
 <1464129345-18985-14-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <20160525144225.GF5996@e104818-lin.cambridge.arm.com>

On Tue, May 24, 2016 at 03:35:43PM -0700, David Daney wrote:
> From: David Daney <david.daney at cavium.com>
> 
> Follow-on arm64 ACPI/NUMA patches need to map MADT entries very early
> (before kmalloc is usable).
> 
> Add acpi_map_madt_entry() which, indirectly, uses
> early_memremap()/early_memunmap() to access the table and parse out
> the mpidr.  The existing implementation of map_madt_entry() is
> modified to take a pointer to the MADT as a parameter and the callers
> adjusted.
> 
> Signed-off-by: David Daney <david.daney at cavium.com>

Acked-by: Catalin Marinas <catalin.marinas at arm.com>


From catalin.marinas at arm.com  Wed May 25 07:42:57 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 25 May 2016 15:42:57 +0100
Subject: [PATCH v7 14/15] arm64, acpi, numa: NUMA support based on SRAT
 and SLIT
In-Reply-To: <1464129345-18985-15-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
 <1464129345-18985-15-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <20160525144256.GG5996@e104818-lin.cambridge.arm.com>

On Tue, May 24, 2016 at 03:35:44PM -0700, David Daney wrote:
> From: Hanjun Guo <hanjun.guo at linaro.org>
> 
> Introduce a new file to hold ACPI based NUMA information parsing from
> SRAT and SLIT.
> 
> SRAT includes the CPU ACPI ID to Proximity Domain mappings and memory
> ranges to Proximity Domain mapping.  SLIT has the information of inter
> node distances(relative number for access latency).
> 
> Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
> Signed-off-by: Ganapatrao Kulkarni <gkulkarni at caviumnetworks.com>
> [rrichter at cavium.com Reworked for numa v10 series ]
> Signed-off-by: Robert Richter <rrichter at cavium.com>
> [david.daney at cavium.com reorderd and combinded with other patches in
> Hanjun Guo's original set, removed get_mpidr_in_madt() and use
> acpi_map_madt_entry() instead.]
> Signed-off-by: David Daney <david.daney at cavium.com>

Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>


From robh+dt at kernel.org  Wed May 25 07:46:49 2016
From: robh+dt at kernel.org (Rob Herring)
Date: Wed, 25 May 2016 09:46:49 -0500
Subject: [PATCH v4 01/18] of/platform: Add common method to populate
 default bus
In-Reply-To: <1463054775-18170-2-git-send-email-wangkefeng.wang@huawei.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463054775-18170-2-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <CAL_JsqJt9qa+3eAO95kvM7h2beRfq3q1Bi39K7uhURTp=f_DtQ@mail.gmail.com>

On Thu, May 12, 2016 at 7:05 AM, Kefeng Wang <wangkefeng.wang at huawei.com> wrote:
> The arch code calls of_platform_populate() with default match table
> when it want to populate default bus.
>
> This patch introduce a new of_platform_default_populate_init() and make it
> arch_initcall_sync(it should be later than some iommu configration, eg,
> of_iommu_init() and swiotlb_late_init in arm64), then we can finish above
> job in common method.
>
> In order to avoid the default bus being populated twice, simply checking
> the flag of bus node whether has be set OF_POPULATED_BUS or not.
>
> After that, we can safely remove the caller in arch code.
>
> Btw, add debug print in of_platform_populate(), and use __func__ to
> print function's name of of_platform_bus_create().
>
> Cc: Rob Herring <robh+dt at kernel.org>
> Cc: Frank Rowand <frowand.list at gmail.com>
> Cc: Grant Likely <grant.likely at linaro.org>
> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> ---
>  drivers/of/platform.c | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 8d103e4..f601b30 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -11,6 +11,7 @@
>   *  2 of the License, or (at your option) any later version.
>   *
>   */
> +#include <linux/acpi.h>
>  #include <linux/errno.h>
>  #include <linux/module.h>
>  #include <linux/amba/bus.h>
> @@ -345,6 +346,12 @@ static int of_platform_bus_create(struct device_node *bus,
>                 return 0;
>         }
>
> +       if (of_node_check_flag(bus, OF_POPULATED_BUS)) {
> +               pr_debug("%s() - skipping %s, already populated\n",
> +                       __func__, bus->full_name);
> +               return 0;
> +       }
> +
>         auxdata = of_dev_lookup(lookup, bus);
>         if (auxdata) {
>                 bus_id = auxdata->name;
> @@ -396,7 +403,7 @@ int of_platform_bus_probe(struct device_node *root,
>         if (!root)
>                 return -EINVAL;
>
> -       pr_debug("of_platform_bus_probe()\n");
> +       pr_debug("%s()\n", __func__);
>         pr_debug(" starting at: %s\n", root->full_name);
>
>         /* Do a self check of bus type, if there's a match, create children */
> @@ -448,6 +455,9 @@ int of_platform_populate(struct device_node *root,
>         if (!root)
>                 return -EINVAL;
>
> +       pr_debug("%s()\n", __func__);
> +       pr_debug(" starting at: %s\n", root->full_name);
> +
>         for_each_child_of_node(root, child) {
>                 rc = of_platform_bus_create(child, matches, lookup, parent, true);
>                 if (rc) {
> @@ -471,6 +481,17 @@ int of_platform_default_populate(struct device_node *root,
>  }
>  EXPORT_SYMBOL_GPL(of_platform_default_populate);
>
> +static int __init of_platform_default_populate_init(void)
> +{
> +       if (of_have_populated_dt())
> +               of_platform_default_populate(NULL, NULL, NULL);
> +       else if (acpi_disabled)

This ACPI dependency needs to go. The error msg is somewhat pointless
as if both DT and ACPI are not used, the boot will be horribly broken
and I'm not sure that you would actually see the message given you
have no information to setup a console.

Rob


From javier at osg.samsung.com  Wed May 25 08:02:04 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Wed, 25 May 2016 11:02:04 -0400
Subject: ARM: dts: exynos: Add MFC memory banks for Peach boards
In-Reply-To: <57456344.7020708@samsung.com>
References: <1461871311-18344-1-git-send-email-javier@osg.samsung.com>
 <57456344.7020708@samsung.com>
Message-ID: <d045b880-4a44-acd8-f7f6-e521caf374aa@osg.samsung.com>

Hello Pankaj,

On 05/25/2016 04:33 AM, pankaj.dubey wrote:
> Hi Javier,
> 
> On Friday 29 April 2016 12:51 AM, Javier Martinez Canillas wrote:
>> The MFC nodes with the memory regions reserved for memory allocations
>> are missing in the Exynos5420 Peach Pit and Exynos5800 Peach Pi DTS.
>>
>> This causes the s5p-mfc driver probe to fail with the following error:
>>
>> [    4.140647] s5p_mfc_alloc_memdevs:1072: Failed to declare coherent memory for MFC device
>> [    4.216163] s5p-mfc: probe of 11000000.codec failed with error -12
>>
>> Add the missing nodes so the driver probes and the {en,de}coder video
>> nodes are registered correctly:
>>
>> [    4.096277] s5p-mfc 11000000.codec: decoder registered as /dev/video4
>> [    4.102282] s5p-mfc 11000000.codec: encoder registered as /dev/video5
>>
>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
> 
> Just noticed that, current krzk/for-next failed to boot on Exynos5880
> based Chromebook device. Git bisect is showing culprit as this patch.

Strange, krzk/for-next boots correctly on my Exynos5800 Peach Pi:

$ git log --pretty=oneline --abbrev-commit HEAD
35e691cf5165 Merge branch 'fixes-v4.7' into for-next

$ uname -r
4.6.0-00073-g35e691cf5165

> When I reverted this patch, its able to boot normally.
> Is there any missing patches that we need to take on krzk/for-next to
> boot on Chromebook.
>

No that I'm aware of. I wonder why it boots for me but fails for
you. Can you please share your complete boot log to see if there
are any hints there?
 
> Thanks,
> Pankaj Dubey
> 

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From festevam at gmail.com  Wed May 25 08:07:56 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Wed, 25 May 2016 12:07:56 -0300
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <0cf90ebe86e0461f82cb22b2a6b6ea83@rwthex-s1-b.rwth-ad.de>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
 <20abc2f6769b4369ba87ec27274a090e@rwthex-s2-a.rwth-ad.de>
 <644530ff6bb04b5898dc33604dc7a93a@rwthex-s1-b.rwth-ad.de>
 <9b905766c6cc4680be4b33f79a179d5a@rwthex-w1-b.rwth-ad.de>
 <0cf90ebe86e0461f82cb22b2a6b6ea83@rwthex-s1-b.rwth-ad.de>
Message-ID: <CAOMZO5DpTrxE+=d6saCowkncR=xpDY060_uTV_WGYxoN7dKUpA@mail.gmail.com>

On Wed, May 25, 2016 at 11:05 AM, Christopher Spinrath
<christopher.spinrath at rwth-aachen.de> wrote:

> OK, done. Can I always use the default value in this case? If yes, can
> you point me to a proper documentation of these?

You can look at
"36.4.316 Pad Control Register
(IOMUXC_SW_PAD_CTL_PAD_ENET_TX_DATA1)" in the mx6quad reference manual.

For GPIO functionality the default power-on-reset value should work fine.

You can confirm this by reading address 0x20E0500 in the bootloader:
mw.l 0x20E0500 1

and then use this value on the dts. This way the kernel will always
have a sane value instead of relying in the value passed from the
bootloader.


From mark.rutland at arm.com  Wed May 25 08:11:56 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 25 May 2016 16:11:56 +0100
Subject: [PATCH] arm64/efi: remove spurious WARN_ON for !4K kernels
Message-ID: <1464189116-30898-1-git-send-email-mark.rutland@arm.com>

Since commit 1fd55a9a09b0293a ("arm64/efi: Apply strict permissions to
UEFI Runtime Services regions"), booting a !4K page kernel results in a
boot-time splat on some systems, due to to a WARN_ONCE added in that
commit which fires if the base address of an EFI memory descriptor is
not aligned to the kernel page size (which might be 4K, 16K, or 64K).

On page 38 of the UEFI 2.6 specification it is stated:

	If a 64KiB physical page contains any 4KiB page with any of the
	following types listed below, then all 4KiB pages in the 64KiB
	page must use identical ARM Memory Page Attributes (as described
	in Table 8):
	? EfiRuntimeServicesCode
	? EfiRuntimeServicesData
	? EfiReserved
	? EfiACPIMemoryNVS
	Mixed attribute mappings within a larger page are not allowed.

On page 158 of the UEFI 2.6 specification, in the description of a
memory descriptor, the PhysicalStart and VirtualStart fields are
mandated as being 4K aligned, with NumberOfPages describing the number
of 4K pages in the region.

No further restriction on alignment is provided in the UEFI
specification, neither generically nor in a rule specific to AArch64.

So while attributes within a naturally-aligned 64K region must be
consistent across memory descriptors, the regions described by those
descriptors are not mandated to be 64K aligned.

Not being able to apply strict permissions is sub-optimal, and worthy of
some notice, but it is not helpful to erroneously suggest that firmware
is buggy, nor is it beneficial to have a noisy backtrace at boot time.

This patch downgrades the WARN_ONCE to a pr_warn_once, and re-words the
message to also describe the implication of the insufficient alignment.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org> 
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Jeremy Linton <jeremy.linton at arm.com>
Cc: Leif Lindholm <leif.lindholm at linaro.org>
Cc: Matt Fleming <matt at codeblueprint.co.uk>
Cc: Will Deacon <will.deacon at arm.com>
Cc: linux-efi at vger.kernel.org
---
 arch/arm64/kernel/efi.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 78f5248..95e748e 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -30,14 +30,15 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
 	if (type == EFI_MEMORY_MAPPED_IO)
 		return PROT_DEVICE_nGnRE;
 
-	if (WARN_ONCE(!PAGE_ALIGNED(md->phys_addr),
-		      "UEFI Runtime regions are not aligned to 64 KB -- buggy firmware?"))
+	if (!PAGE_ALIGNED(md->phys_addr)) {
+		pr_warn_once("UEFI Runtime regions insufficiently aligned for strict permissions\n");
 		/*
 		 * If the region is not aligned to the page size of the OS, we
 		 * can not use strict permissions, since that would also affect
 		 * the mapping attributes of the adjacent regions.
 		 */
 		return pgprot_val(PAGE_KERNEL_EXEC);
+	}
 
 	/* R-- */
 	if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) ==
-- 
1.9.1



From arnd at arndb.de  Wed May 25 08:18:22 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 25 May 2016 17:18:22 +0200
Subject: [PATCH v3 4/4] soc: Add SoC driver for Freescale Vybrid platform
In-Reply-To: <CAL_JsqKCwy=aXveTfnaQuZ5b3Ld9nzABgPfdPm1JX3CBuvzG+Q@mail.gmail.com>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
 <20160524041447.GA2884@Sanchayan-Arch.localdomain>
 <CAL_JsqKCwy=aXveTfnaQuZ5b3Ld9nzABgPfdPm1JX3CBuvzG+Q@mail.gmail.com>
Message-ID: <5922111.afqro67xTI@wuerfel>

On Tuesday, May 24, 2016 12:09:41 PM CEST Rob Herring wrote:
> On Mon, May 23, 2016 at 11:14 PM,  <maitysanchayan at gmail.com> wrote:
> > Hello Rob,
> >
> > On 16-05-23 16:18:13, Rob Herring wrote:
> >> On Fri, May 20, 2016 at 03:32:05PM +0530, Sanchayan Maity wrote:
> >> > This adds a SoC driver to be used by Freescale Vybrid SoC's.
> >> > Driver utilises syscon and nvmem consumer API's to get the
> >> > various register values needed and expose the SoC specific
> >> > properties via sysfs.
> >> >
> >> > A sample output from Colibri Vybrid VF61 is below:
> >> >
> >> > root at colibri-vf:~# cd /sys/bus/soc/devices/soc0
> >> > root at colibri-vf:/sys/bus/soc/devices/soc0# ls
> >> > family     machine    power      revision   soc_id     subsystem  uevent
> >> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat family
> >> > Freescale Vybrid VF610
> >> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat machine
> >> > Freescale Vybrid
> >> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat revision
> >> > 00000013
> >> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat soc_id
> >> > df6472a6130f29d4
> >> >
> >> > Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
> >> > ---
> >> >  .../bindings/arm/freescale/fsl,vf610-soc.txt       |  20 +++
> >> >  drivers/soc/Kconfig                                |   1 +
> >> >  drivers/soc/fsl/Kconfig                            |  10 ++
> >> >  drivers/soc/fsl/Makefile                           |   1 +
> >> >  drivers/soc/fsl/soc-vf610.c                        | 198 +++++++++++++++++++++
> >> >  5 files changed, 230 insertions(+)
> >> >  create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> >> >  create mode 100644 drivers/soc/fsl/Kconfig
> >> >  create mode 100644 drivers/soc/fsl/soc-vf610.c
> >> >
> >> > diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> >> > new file mode 100644
> >> > index 0000000..338905d
> >> > --- /dev/null
> >> > +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> >> > @@ -0,0 +1,20 @@
> >> > +Vybrid System-on-Chip
> >> > +---------------------
> >> > +
> >> > +Required properties:
> >> > +
> >> > +- compatible: "fsl,vf610-soc"
> >> > +- rom-revision: phandle to the on-chip ROM node
> >> > +- mscm: phandle to the MSCM CPU configuration node
> >> > +- nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
> >> > +- nvmem-cell-names: should contain string names "cfg0" and "cfg1"
> >>
> >> I still have similar concerns as the discussion on the last version.
> >> This version only proves that you aren't describing h/w, but rather just
> >> a collection of data that some driver wants.
> >>
> >> A driver can just as easily look-up all the nodes directly that these
> >> phandles point to.
> >
> > Agreed, that we can look up all the nodes directly that these phandles
> > refer to but I would still need a DT entry to bind to. While I could
> > bind to existing nodes like mscm cpucfg but that doesn't seem right.
> >
> > The very first approach that we had taken was to integrate this functionality
> > in mach-vf610.c code under mach-imx
> > http://www.spinics.net/lists/devicetree/msg80654.html
> 
> Yes, everyone wants to move all platform devices in the kernel to a
> corresponding DT node. The result is often making up nodes to do this.
> It's the same thing with cpufreq.
> 
> > and then it was recommended to migrate this to drivers/soc where we did use
> > phandles or direct look up via compatible strings
> 
> The location in the tree is an orthogonal issue. You could move it and
> use of_machine_is_compatible without any DT change.
> 
> The primary issue I have here is how do we bind soc_bus to DT in a
> consistent way. Sorry, but vybrid specific patches alone are never
> going to solve that issue.

On a lot of chips, there is actually one device that holds the soc
identification registers, and that can easily be used for this purpose.

Originally, the soc_device was meant to be the parent device for all
other on-chip devices and be bound to the DT node that holds that
bus (unlike things like external clocks that are not part of the SoC).

However, that model has never really caught on, and we have stopped
doing this for new chips. Instead, the soc_device now somewhat
stands for itself.

> > http://www.spinics.net/lists/arm-kernel/msg420847.html
> >
> > and
> >
> > http://lkml.iu.edu/hypermail/linux/kernel/1506.0/03787.html
> >
> > There hasn't been a consensus since v1.
> 
> I actually prefer your previous version binding soc_bus to the root
> bus node to this version. I think that is closer to the right
> direction. After all, pretty much everything is an SOC and every SOC
> has an SOC bus. Pretty much every SOC and board have revisions and may
> need to expose that revision info as well. We have to do this
> consistently which means having a default implementation for
> simple-bus that is not opt-in.
> 
> Alternatively, we should just deprecate soc_bus and come up a
> different solution. Either way, I think we have a half implemented
> solution currently.

We have had several drivers in the past that needed to figure out
whether they were running on a particular version of a SoC, and that
could not get this information from the DT. My suggested solution
for this is to provide an API from soc_bus that compares a
glob string to the available soc_device instance(s) in order to
figure out whether we are running on a particular kind of system.

	Arnd


From catalin.marinas at arm.com  Wed May 25 08:22:55 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 25 May 2016 16:22:55 +0100
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <20160524151235.GA11605@leverpostej>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
 <20160524113727.GD25374@leverpostej> <574446B9.8040105@huawei.com>
 <20160524151235.GA11605@leverpostej>
Message-ID: <20160525152255.GH5996@e104818-lin.cambridge.arm.com>

On Tue, May 24, 2016 at 04:12:35PM +0100, Mark Rutland wrote:
> On Tue, May 24, 2016 at 08:19:05PM +0800, Leizhen (ThunderTown) wrote:
> > On 2016/5/24 19:37, Mark Rutland wrote:
> > > On Tue, May 24, 2016 at 07:16:37PM +0800, Zhen Lei wrote:
> > >> When we ran mprotect04(a test case in LTP) infinitely, it would always
> > >> failed after a few seconds. The case can be described briefly that: copy
> > >> a empty function from code area into a new memory area(created by mmap),
> > >> then call mprotect to change the protection to PROT_EXEC. The syscall
> > >> sys_mprotect will finally invoke flush_cache_range, but this function
> > >> currently only invalid icache, the operation of flush dcache is missed.
[...]
> Jumping back to the problem at hand:
> 
> It looks like we inherited this from ARM, which has done this for all
> executable mappings since commit  6060e8df517847bf ("ARM: I-cache: flush
> executable mappings in flush_cache_range()"). The commit message refers
> to a4db94d, which doesn't seem to exist, and I assume is
> 115b22474eb1905d ("ARM: 5794/1: Flush the D-cache during
> copy_user_highpage()") which happened to get rebased at some point.
> 
> That all implies that the icache maintenance is only intended to ensure
> that CoW does not result in unexpected incoherency. Which in turn
> implies that flipping permissions with mprotect is not expected to
> synchronise the D and I caches.

Looking through the arm32 history:

2.6.33:
  115b22474eb1 ("ARM: 5794/1: Flush the D-cache during copy_user_highpage()")
  6060e8df5178 ("ARM: I-cache: flush executable mappings in flush_cache_range()")

These both take care of the CoW issue with executable pages.

2.6.37:
  6012191aa9c6 ("ARM: 6380/1: Introduce __sync_icache_dcache() for VIPT caches")

The above is a fix for SMP systems where update_mmu_cache() happens
after the PTE was actually written, so slight chance of race with
another CPU. We generalised it to all ARMv6+ systems (so VIPT caches).

3.1:
  c7e89b16eb90 ("ARM: 6995/2: mm: remove unnecessary cache flush on v6 copypage")

That's when we realised that the CoW problem no longer exists for
non-aliasing VIPT caches. However, the I-cache counterpart 6060e8df5178
has not been reverted.

So I think that for arm64 and arm32 with non-aliasing VIPT,
flush_cache_range() can safely be a no-op.

-- 
Catalin


From ard.biesheuvel at linaro.org  Wed May 25 08:23:01 2016
From: ard.biesheuvel at linaro.org (Ard Biesheuvel)
Date: Wed, 25 May 2016 17:23:01 +0200
Subject: [PATCH] arm64/efi: remove spurious WARN_ON for !4K kernels
In-Reply-To: <1464189116-30898-1-git-send-email-mark.rutland@arm.com>
References: <1464189116-30898-1-git-send-email-mark.rutland@arm.com>
Message-ID: <BA565A9C-8CC0-42E4-9821-7941852F835A@linaro.org>



> On 25 mei 2016, at 17:11, Mark Rutland <mark.rutland at arm.com> wrote:
> 
> Since commit 1fd55a9a09b0293a ("arm64/efi: Apply strict permissions to
> UEFI Runtime Services regions"), booting a !4K page kernel results in a
> boot-time splat on some systems, due to to a WARN_ONCE added in that
> commit which fires if the base address of an EFI memory descriptor is
> not aligned to the kernel page size (which might be 4K, 16K, or 64K).
> 
> On page 38 of the UEFI 2.6 specification it is stated:
> 
>    If a 64KiB physical page contains any 4KiB page with any of the
>    following types listed below, then all 4KiB pages in the 64KiB
>    page must use identical ARM Memory Page Attributes (as described
>    in Table 8):
>    ? EfiRuntimeServicesCode
>    ? EfiRuntimeServicesData
>    ? EfiReserved
>    ? EfiACPIMemoryNVS
>    Mixed attribute mappings within a larger page are not allowed.
> 

The same section mentions that the ro/xp etc attributes are unused on arm, so if we go by the letter here, we need to remove those memory protection features entirely. So a spec update is clearly in order here.

That still means the patch is correct, of course ...

> On page 158 of the UEFI 2.6 specification, in the description of a
> memory descriptor, the PhysicalStart and VirtualStart fields are
> mandated as being 4K aligned, with NumberOfPages describing the number
> of 4K pages in the region.
> 
> No further restriction on alignment is provided in the UEFI
> specification, neither generically nor in a rule specific to AArch64.
> 
> So while attributes within a naturally-aligned 64K region must be
> consistent across memory descriptors, the regions described by those
> descriptors are not mandated to be 64K aligned.
> 
> Not being able to apply strict permissions is sub-optimal, and worthy of
> some notice, but it is not helpful to erroneously suggest that firmware
> is buggy, nor is it beneficial to have a noisy backtrace at boot time.
> 
> This patch downgrades the WARN_ONCE to a pr_warn_once, and re-words the
> message to also describe the implication of the insufficient alignment.
> 
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org> 
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Jeremy Linton <jeremy.linton at arm.com>
> Cc: Leif Lindholm <leif.lindholm at linaro.org>
> Cc: Matt Fleming <matt at codeblueprint.co.uk>
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: linux-efi at vger.kernel.org
> ---
> arch/arm64/kernel/efi.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
> index 78f5248..95e748e 100644
> --- a/arch/arm64/kernel/efi.c
> +++ b/arch/arm64/kernel/efi.c
> @@ -30,14 +30,15 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
>    if (type == EFI_MEMORY_MAPPED_IO)
>        return PROT_DEVICE_nGnRE;
> 
> -    if (WARN_ONCE(!PAGE_ALIGNED(md->phys_addr),
> -              "UEFI Runtime regions are not aligned to 64 KB -- buggy firmware?"))
> +    if (!PAGE_ALIGNED(md->phys_addr)) {
> +        pr_warn_once("UEFI Runtime regions insufficiently aligned for strict permissions\n");
>        /*
>         * If the region is not aligned to the page size of the OS, we
>         * can not use strict permissions, since that would also affect
>         * the mapping attributes of the adjacent regions.
>         */
>        return pgprot_val(PAGE_KERNEL_EXEC);
> +    }
> 
>    /* R-- */
>    if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) ==
> -- 
> 1.9.1
> 


From catalin.marinas at arm.com  Wed May 25 08:31:33 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 25 May 2016 16:31:33 +0100
Subject: [PATCH] arm64/efi: remove spurious WARN_ON for !4K kernels
In-Reply-To: <1464189116-30898-1-git-send-email-mark.rutland@arm.com>
References: <1464189116-30898-1-git-send-email-mark.rutland@arm.com>
Message-ID: <20160525153133.GI5996@e104818-lin.cambridge.arm.com>

On Wed, May 25, 2016 at 04:11:56PM +0100, Mark Rutland wrote:
> Since commit 1fd55a9a09b0293a ("arm64/efi: Apply strict permissions to
> UEFI Runtime Services regions"), booting a !4K page kernel results in a
> boot-time splat on some systems, due to to a WARN_ONCE added in that
> commit which fires if the base address of an EFI memory descriptor is
> not aligned to the kernel page size (which might be 4K, 16K, or 64K).
> 
> On page 38 of the UEFI 2.6 specification it is stated:
> 
> 	If a 64KiB physical page contains any 4KiB page with any of the
> 	following types listed below, then all 4KiB pages in the 64KiB
> 	page must use identical ARM Memory Page Attributes (as described
> 	in Table 8):
> 	? EfiRuntimeServicesCode
> 	? EfiRuntimeServicesData
> 	? EfiReserved
> 	? EfiACPIMemoryNVS
> 	Mixed attribute mappings within a larger page are not allowed.
> 
> On page 158 of the UEFI 2.6 specification, in the description of a
> memory descriptor, the PhysicalStart and VirtualStart fields are
> mandated as being 4K aligned, with NumberOfPages describing the number
> of 4K pages in the region.
> 
> No further restriction on alignment is provided in the UEFI
> specification, neither generically nor in a rule specific to AArch64.
> 
> So while attributes within a naturally-aligned 64K region must be
> consistent across memory descriptors, the regions described by those
> descriptors are not mandated to be 64K aligned.
> 
> Not being able to apply strict permissions is sub-optimal, and worthy of
> some notice, but it is not helpful to erroneously suggest that firmware
> is buggy, nor is it beneficial to have a noisy backtrace at boot time.
> 
> This patch downgrades the WARN_ONCE to a pr_warn_once, and re-words the
> message to also describe the implication of the insufficient alignment.
> 
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org> 
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Jeremy Linton <jeremy.linton at arm.com>
> Cc: Leif Lindholm <leif.lindholm at linaro.org>
> Cc: Matt Fleming <matt at codeblueprint.co.uk>
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: linux-efi at vger.kernel.org

Acked-by: Catalin Marinas <catalin.marinas at arm.com>

Not sure how this will go in (Matt or Will?).


From jeremy.linton at arm.com  Wed May 25 08:38:19 2016
From: jeremy.linton at arm.com (Jeremy Linton)
Date: Wed, 25 May 2016 10:38:19 -0500
Subject: [PATCH] arm64/efi: remove spurious WARN_ON for !4K kernels
In-Reply-To: <1464189116-30898-1-git-send-email-mark.rutland@arm.com>
References: <1464189116-30898-1-git-send-email-mark.rutland@arm.com>
Message-ID: <5745C6EB.8090004@arm.com>

On 05/25/2016 10:11 AM, Mark Rutland wrote:
> Since commit 1fd55a9a09b0293a ("arm64/efi: Apply strict permissions to
> UEFI Runtime Services regions"), booting a !4K page kernel results in a
> boot-time splat on some systems, due to to a WARN_ONCE added in that
> commit which fires if the base address of an EFI memory descriptor is
> not aligned to the kernel page size (which might be 4K, 16K, or 64K).
>
> On page 38 of the UEFI 2.6 specification it is stated:
>
> 	If a 64KiB physical page contains any 4KiB page with any of the
> 	following types listed below, then all 4KiB pages in the 64KiB
> 	page must use identical ARM Memory Page Attributes (as described
> 	in Table 8):
> 	? EfiRuntimeServicesCode
> 	? EfiRuntimeServicesData
> 	? EfiReserved
> 	? EfiACPIMemoryNVS
> 	Mixed attribute mappings within a larger page are not allowed.
>
> On page 158 of the UEFI 2.6 specification, in the description of a
> memory descriptor, the PhysicalStart and VirtualStart fields are
> mandated as being 4K aligned, with NumberOfPages describing the number
> of 4K pages in the region.
>
> No further restriction on alignment is provided in the UEFI
> specification, neither generically nor in a rule specific to AArch64.
>
> So while attributes within a naturally-aligned 64K region must be
> consistent across memory descriptors, the regions described by those
> descriptors are not mandated to be 64K aligned.
>
> Not being able to apply strict permissions is sub-optimal, and worthy of
> some notice, but it is not helpful to erroneously suggest that firmware
> is buggy, nor is it beneficial to have a noisy backtrace at boot time.



>
> This patch downgrades the WARN_ONCE to a pr_warn_once, and re-words the
> message to also describe the implication of the insufficient alignment.

I've been seeing this a lot, and this should help to lower the noise level.

Reviewed-by: Jeremy Linton <jeremy.linton at arm.com>

Thanks,

>
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Jeremy Linton <jeremy.linton at arm.com>
> Cc: Leif Lindholm <leif.lindholm at linaro.org>
> Cc: Matt Fleming <matt at codeblueprint.co.uk>
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: linux-efi at vger.kernel.org
> ---
>   arch/arm64/kernel/efi.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
> index 78f5248..95e748e 100644
> --- a/arch/arm64/kernel/efi.c
> +++ b/arch/arm64/kernel/efi.c
> @@ -30,14 +30,15 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
>   	if (type == EFI_MEMORY_MAPPED_IO)
>   		return PROT_DEVICE_nGnRE;
>
> -	if (WARN_ONCE(!PAGE_ALIGNED(md->phys_addr),
> -		      "UEFI Runtime regions are not aligned to 64 KB -- buggy firmware?"))
> +	if (!PAGE_ALIGNED(md->phys_addr)) {
> +		pr_warn_once("UEFI Runtime regions insufficiently aligned for strict permissions\n");
>   		/*
>   		 * If the region is not aligned to the page size of the OS, we
>   		 * can not use strict permissions, since that would also affect
>   		 * the mapping attributes of the adjacent regions.
>   		 */
>   		return pgprot_val(PAGE_KERNEL_EXEC);
> +	}
>
>   	/* R-- */
>   	if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) ==
>



From swarren at wwwdotorg.org  Wed May 25 08:42:28 2016
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Wed, 25 May 2016 09:42:28 -0600
Subject: [PATCH] arm64: tegra: Fix CPU compatible string for Tegra132
In-Reply-To: <574509E7.4030208@nvidia.com>
References: <20160523074221.7135-1-josephl@nvidia.com>
 <574509E7.4030208@nvidia.com>
Message-ID: <5745C7E4.2050908@wwwdotorg.org>

On 05/24/2016 08:11 PM, Joseph Lo wrote:
> On 05/23/2016 03:42 PM, Joseph Lo wrote:
>> As per commit f634da375fc96 ("Documentation: DT bindings: add nvidia,
>> tegra132-denver compatible string"), fixing the CPU compatible string for
>> Tegra132 to match the binding document currently.
>>
>> Signed-off-by: Joseph Lo <josephl at nvidia.com>
>> ---
>>   arch/arm64/boot/dts/nvidia/tegra132.dtsi | 4 ++--
>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
>> b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
>> index 2013f8916084..7b1cdc029de3 100644
>> --- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
>> +++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
>> @@ -964,13 +964,13 @@
>>
>>           cpu at 0 {
>>               device_type = "cpu";
>> -            compatible = "nvidia,denver", "arm,armv8";
>> +            compatible = "nvidia,tegra132-denver", "arm,armv8";
>
> Hi Stephen, Thierry,
>
> Should we fix this or fix the compatible string in the binding document
> as just "nvidia,denver" to represent all the Devner CPU revisions just
> like some other CPUs did? e.g. arm,cortex-a57, which represents all the
> A57 revisions.

I would expect compatible to be:

compatible = "nvidia,tegra132-denver", "nvidia,denver", "arm,armv8";

The "nvidia,denver" entry is already present, and hence probably 
shouldn't be removed. It can represent "Denver 1.0". We should add the 
T132 entry to indicate the specific implementation. Admittedly right now 
there's a 1:1 relation between SoC and Denver version. Either/both of 
those could in theory be required to trigger specific bug-fixes/WARs.

For later chips which have a different Denver version, I'd expect to see 
something like:

compatible = "nvidia,tegraNNN-denver", "nvidia,denverMMM", "arm,armv8";

... where NNN is the SoC version/name and MMM is the Denver version. 
There could be extra entries in the property if the new versions are 
backwards-compatible with old versions.


From d-gerlach at ti.com  Wed May 25 08:45:55 2016
From: d-gerlach at ti.com (Dave Gerlach)
Date: Wed, 25 May 2016 10:45:55 -0500
Subject: [RFC PATCH 1/3] asm-generic: io: Add exec versions of ioremap
In-Reply-To: <20160518205758.GY5783@n2100.arm.linux.org.uk>
References: <1462830111-28172-1-git-send-email-d-gerlach@ti.com>
 <573C7844.5030107@ti.com> <20160518175102.GX5783@n2100.arm.linux.org.uk>
 <3861017.ZJOlWYvEFT@wuerfel> <20160518205758.GY5783@n2100.arm.linux.org.uk>
Message-ID: <5745C8B3.2050609@ti.com>

On 05/18/2016 03:57 PM, Russell King - ARM Linux wrote:
> On Wed, May 18, 2016 at 10:25:03PM +0200, Arnd Bergmann wrote:
>> The ARM version of ioremap_exec() that gets added in this patch is cached
>> (like memremap()), but then the asm-generic version is not? This is
>> even more confusing, it should at least do roughly the same thing across
>> architectures.
>>
>> There should also be some documentation about what the expected behavior is, e.g.:
>>
>> - is memremap_exec() by default cached or not? (I assume it would
>>    be like memremap())
>> - If we have an interface that does explicit uncached executable mapping,
>>    what about architectures on which this is not possible? Should they
>>    fall back to cached or non-executable, or cause a link error?

Yes by default memremap_exec is cached, I do plan to add more explicit 
documentation.

Well, I dont think that memremap_exec will be called directly but rather 
using a flag with memremap as arch_memremap_wb is now, to keep the 
memremap API unified, so a link error will prevent this. Also, the 
function may be present in code but not actually used in all cases, the 
example that comes to mind is the drivers/misc/sram.c code where other 
runtime options are perfectly valid for determining how to map memory 
even on architectures that can't memremap_exec_nocache.

I think that a remap that can't deliver what you have asked for should 
return NULL here because if you are requesting executable, noncached 
memory you presumably will try to execute from it and fail, so the 
mapping should fail as it isn't actually valid if it can't do what you want.

>
> Another important point is whether atomic instructions / kernel locks
> can be located within the mapped memory.
>

At this point I'd imagine most of the users of this would be copying 
small chunks of relocatable code (likely written in assembly) that would 
handle low-level tasks without the need for atomic instructions/locks, 
but is this something we should explicitly forbid in documentation?

Regards,
Dave



From andre.przywara at arm.com  Wed May 25 08:55:39 2016
From: andre.przywara at arm.com (Andre Przywara)
Date: Wed, 25 May 2016 16:55:39 +0100
Subject: [PATCH v4 01/12] KVM: extend struct kvm_msi to hold a 32-bit
 device ID
In-Reply-To: <20160403091508.GA5261@cbox>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-2-git-send-email-andre.przywara@arm.com>
 <20160403091508.GA5261@cbox>
Message-ID: <e520a5a8-b259-27f3-f33c-f87e008f1c6f@arm.com>

Hi Christoffer,

On 03/04/16 10:15, Christoffer Dall wrote:
> On Sat, Mar 26, 2016 at 02:13:59AM +0000, Andre Przywara wrote:
>> The ARM GICv3 ITS MSI controller requires a device ID to be able to
>> assign the proper interrupt vector. On real hardware, this ID is
>> sampled from the bus. To be able to emulate an ITS controller, extend
>> the KVM MSI interface to let userspace provide such a device ID. For
>> PCI devices, the device ID is simply the 16-bit bus-device-function
>> triplet, which should be easily available to the userland tool.
>>
>> Also there is a new KVM capability which advertises whether the
>> current VM requires a device ID to be set along with the MSI data.
>> This flag is still reported as not available everywhere, later we will
>> enable it when ITS emulation is used.
>>
>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>> Reviewed-by: Eric Auger <eric.auger at linaro.org>
>> ---
>>  Documentation/virtual/kvm/api.txt | 12 ++++++++++--
>>  include/uapi/linux/kvm.h          |  5 ++++-
>>  2 files changed, 14 insertions(+), 3 deletions(-)
>>
>> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
>> index cb2ef0b..8f7351d 100644
>> --- a/Documentation/virtual/kvm/api.txt
>> +++ b/Documentation/virtual/kvm/api.txt
>> @@ -2163,10 +2163,18 @@ struct kvm_msi {
>>  	__u32 address_hi;
>>  	__u32 data;
>>  	__u32 flags;
>> -	__u8  pad[16];
>> +	__u32 devid;
> 
> Are we imposing any unfortunate restrictions for other architectures by
> using a u32 over a u64 for the device ID?

Mmmh, good point. I guess not only for other architectures, but also for
the future in general.

Are there any objections against increasing this to a u64?

Cheers,
Andre.

>> +	__u8  pad[12];
>>  };
>>  
>> -No flags are defined so far. The corresponding field must be 0.
>> +flags: KVM_MSI_VALID_DEVID: devid contains a valid value
>> +devid: If KVM_MSI_VALID_DEVID is set, contains a unique device identifier
>> +       for the device that wrote the MSI message.
>> +       For PCI, this is usually a BFD identifier in the lower 16 bits.
>> +
>> +The per-VM KVM_CAP_MSI_DEVID capability advertises the need to provide
>> +the device ID. If this capability is not set, userland cannot rely on
>> +the kernel to allow the KVM_MSI_VALID_DEVID flag being set.
>>  
>>  
>>  4.71 KVM_CREATE_PIT2
>> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
>> index 50f44a2..6a02871 100644
>> --- a/include/uapi/linux/kvm.h
>> +++ b/include/uapi/linux/kvm.h
>> @@ -852,6 +852,7 @@ struct kvm_ppc_smmu_info {
>>  #define KVM_CAP_S390_RI 124
>>  #define KVM_CAP_ARM_PMU_V3 125
>>  #define KVM_CAP_VCPU_ATTRIBUTES 126
>> +#define KVM_CAP_MSI_DEVID 127
>>  
>>  #ifdef KVM_CAP_IRQ_ROUTING
>>  
>> @@ -1010,12 +1011,14 @@ struct kvm_one_reg {
>>  	__u64 addr;
>>  };
>>  
>> +#define KVM_MSI_VALID_DEVID	(1U << 0)
>>  struct kvm_msi {
>>  	__u32 address_lo;
>>  	__u32 address_hi;
>>  	__u32 data;
>>  	__u32 flags;
>> -	__u8  pad[16];
>> +	__u32 devid;
>> +	__u8  pad[12];
>>  };
>>  
>>  struct kvm_arm_device_addr {
>> -- 
>> 2.7.3
>>
> 


From peter.griffin at linaro.org  Wed May 25 09:06:33 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:33 +0100
Subject: [PATCH 00/18] Add support for FDMA DMA controller and xp70 rproc
 found on STi chipsets
Message-ID: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>

Hi Vinod / Maxime / Bjorn,

This patchset adds support for the Flexible Direct Memory Access (FDMA) core
found on STi chipsets from STMicroelectronics. The FDMA is a slim (xp70) core CPU
with a dedicated firmware. It is a general purpose DMA controller supporting
16 independent channels and data can be moved from memory to memory or between
memory and paced latency critical real time targets.

After some discussion with the DT maintainers I've removed the firmware
name from DT, and now generate the name based on the compatible string.
This is in keeping with how most other kernel drivers request firmware, and avoids
a new DT firmware name or fdma id binding.

I've also dropped the xbar support for the moment, as I believe it should be
re-worked based on some of the xbar API's that TI recently added. As requested
I've also split it into smaller patches to help with a faster review.

V3 also included some updates to the ASoC DT documentation, and extra DT patches
for Maximes STi DT tree to enable ASoC on STi407 based platforms using the fdma
driver.

v4 includes a new xp70 rproc driver for loading the XP70 elf firmware. This
enables us to use the generic rproc elf loading code. This has deliberately not
been implemented as a platform_driver, to avoid having to have double mappings of
I/O memory from two device drivers, and also to ensure that the DT node reflects
the actual hardware rather than Linux subsystems. The xp70 slimcore is the basis
for various pieces of IP in STi chipsets and the intention is that other drivers
(demux, display) can also be migrated over to using the xp70 rproc for their
elf firmware loading and start/stop control.

regards,

Peter.

Changes since v3:
 - Remove elf loading code from fdma driver (Vinod)
 - Remove fdma_ prefix for clock names (Arnd)
 - Make _xlate use dma_get_any_channel rather than request_channel (Arnd)
 - Make a common function for _prep_ routines (Vinod)
 - Make driver depend on COMPILE_TEST (Arnd)
 - Remove unnecessary st_fdma_filter_fn (Arnd)
 - Enable FDMA as a module (Arnd)
 - Drop fdma_ clock prefix (Arnd)
 - Fix description as well as example for st, prefix (Arnd)
 - Remove string concatenation from fdma register macros to ease grep'ability (Arnd)
 - Add a XP70 rproc driver for ELF firmware loading and start/stop control (Peter)
 - Add myself as a author of the driver (Peter)

Changes since v2:
 - Change to dma-controller (Arnd)
 - Remove platform data header file and simplifiy code (Arnd)
 - Remove FW_LOADER_USER_HELPER_FALLBACK and rework firmware loading to device config (Vinod)
 - Use SET_RUNTIME_PM_OPS helpers (Vinod)
 - Remove fdma-id dt prop and use compatibles to generate different fdma firmware names (Arnd / Lee)
 - Add sti-asoc-card DT nodes and pinmux config for uniperif player & reader (Peter)
 - Update sti-asoc-card DT binding documentation (Peter)
 - Enable STi audio drivers in multi_v7_defconfig (Peter)

Changes since v1:
 - split into smaller patches for easier / faster review (Vinod)
 - new fill_hw_mode() with common code (Vinod)
 - new config_reqctrl() called from *_prep() instead of device_config cb (Vinod)
 - fdma-xbar support removed (Peter)
 - rework firmware name mechanism so fwname isn't in DT (Peter / Lee)
 - st_fdma_seg_to_mem can be static (Paul)
 - EXPORT_SYMBOL st_fdma_filter_fn not required (Paul)
 - s/channel/channels (vinod)
 - better describe "Must be <3>" (vinod)
 - sizeof(*ehdr) (vinod)
 - print values on error debug (vinod)
 - empty line (Vinod)
 - Update to -EIO (Vinod)
 - Make st_fdma tristate (Paul)
 - Remove __exit tag from .remove (Maxime)
 - Update MAINTAINERS rule to fdma* (Lee)
 - Unit address should match reg property (Lee)

Peter Griffin (18):
  dmaengine: st_fdma: Add STMicroelectronics FDMA DT binding
    documentation
  dmaengine: st_fdma:  Add STMicroelectronics FDMA driver header file
  dmaengine: st_fdma: Add STMicroelectronics FDMA engine driver support
  dmaengine: st_fdma: Add xp70 firmware loading mechanism.
  dmaengine: st_fdma: Add fdma suspend and resume callbacks.
  ARM: STi: DT: STiH407: Add FDMA driver dt nodes.
  MAINTAINERS: Add FDMA driver files to STi section.
  ARM: multi_v7_defconfig: Enable STi FDMA driver
  ASoC: sti: Update DT example to match the driver code
  ASoC: sti: Update example to include assigned-clocks and mclk-fs
  ARM: multi_v7_defconfig: Enable STi and simple-card drivers.
  ARM: DT: STiH407: Add i2s_out pinctrl configuration
  ARM: DT: STiH407: Add i2s_in pinctrl configuration
  ARM: DT: STiH407: Add spdif_out pinctrl config
  ARM: STi: DT: STiH407: Add sti-sasg-codec dt node
  ARM: STi: DT: STiH407: Add uniperif player dt nodes
  ARM: STi: DT: STiH407: Add uniperif reader dt nodes
  ARM: DT: STi: stihxxx-b2120: Add DT nodes for STi audio card

 Documentation/devicetree/bindings/dma/st_fdma.txt  |   87 ++
 .../devicetree/bindings/sound/st,sti-asoc-card.txt |   22 +-
 MAINTAINERS                                        |    1 +
 arch/arm/boot/dts/stih407-family.dtsi              |  164 +++
 arch/arm/boot/dts/stih407-pinctrl.dtsi             |   55 +
 arch/arm/boot/dts/stihxxx-b2120.dtsi               |   40 +
 arch/arm/configs/multi_v7_defconfig                |    4 +
 drivers/dma/Kconfig                                |   12 +
 drivers/dma/Makefile                               |    1 +
 drivers/dma/st_fdma.c                              | 1203 ++++++++++++++++++++
 drivers/dma/st_fdma.h                              |  281 +++++
 11 files changed, 1863 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/dma/st_fdma.txt
 create mode 100644 drivers/dma/st_fdma.c
 create mode 100644 drivers/dma/st_fdma.h

-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:34 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:34 +0100
Subject: [PATCH v4 00/18] Add support for FDMA DMA controller and xp70 rproc
 found on STi chipsets
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-2-git-send-email-peter.griffin@linaro.org>

Hi Vinod / Maxime / Bjorn,

This patchset adds support for the Flexible Direct Memory Access (FDMA) core
found on STi chipsets from STMicroelectronics. The FDMA is a slim (xp70) core CPU
with a dedicated firmware. It is a general purpose DMA controller supporting
16 independent channels and data can be moved from memory to memory or between
memory and paced latency critical real time targets.

After some discussion with the DT maintainers I've removed the firmware
name from DT, and now generate the name based on the compatible string.
This is in keeping with how most other kernel drivers request firmware, and avoids
a new DT firmware name or fdma id binding.

I've also dropped the xbar support for the moment, as I believe it should be
re-worked based on some of the xbar API's that TI recently added. As requested
I've also split it into smaller patches to help with a faster review.

V3 also included some updates to the ASoC DT documentation, and extra DT patches
for Maximes STi DT tree to enable ASoC on STi407 based platforms using the fdma
driver.

v4 includes a new xp70 rproc driver for loading the XP70 elf firmware. This
enables us to use the generic rproc elf loading code. This has deliberately not
been implemented as a platform_driver, to avoid having to have double mappings of
I/O memory from two device drivers, and also to ensure that the DT node reflects
the actual hardware rather than Linux subsystems. The xp70 slimcore is the basis
for various pieces of IP in STi chipsets and the intention is that other drivers
(demux, display) can also be migrated over to using the xp70 rproc for their
elf firmware loading and start/stop control.

regards,

Peter.

Changes since v3:
 - Remove elf loading code from fdma driver (Vinod)
 - Remove fdma_ prefix for clock names (Arnd)
 - Make _xlate use dma_get_any_channel rather than request_channel (Arnd)
 - Make a common function for _prep_ routines (Vinod)
 - Make driver depend on COMPILE_TEST (Arnd)
 - Remove unnecessary st_fdma_filter_fn (Arnd)
 - Enable FDMA as a module (Arnd)
 - Drop fdma_ clock prefix (Arnd)
 - Fix description as well as example for st, prefix (Arnd)
 - Remove string concatenation from fdma register macros to ease grep'ability (Arnd)
 - Add a XP70 rproc driver for ELF firmware loading and start/stop control (Peter)
 - Add myself as a author of the driver (Peter)

Changes since v2:
 - Change to dma-controller (Arnd)
 - Remove platform data header file and simplifiy code (Arnd)
 - Remove FW_LOADER_USER_HELPER_FALLBACK and rework firmware loading to device config (Vinod)
 - Use SET_RUNTIME_PM_OPS helpers (Vinod)
 - Remove fdma-id dt prop and use compatibles to generate different fdma firmware names (Arnd / Lee)
 - Add sti-asoc-card DT nodes and pinmux config for uniperif player & reader (Peter)
 - Update sti-asoc-card DT binding documentation (Peter)
 - Enable STi audio drivers in multi_v7_defconfig (Peter)

Changes since v1:
 - split into smaller patches for easier / faster review (Vinod)
 - new fill_hw_mode() with common code (Vinod)
 - new config_reqctrl() called from *_prep() instead of device_config cb (Vinod)
 - fdma-xbar support removed (Peter)
 - rework firmware name mechanism so fwname isn't in DT (Peter / Lee)
 - st_fdma_seg_to_mem can be static (Paul)
 - EXPORT_SYMBOL st_fdma_filter_fn not required (Paul)
 - s/channel/channels (vinod)
 - better describe "Must be <3>" (vinod)
 - sizeof(*ehdr) (vinod)
 - print values on error debug (vinod)
 - empty line (Vinod)
 - Update to -EIO (Vinod)
 - Make st_fdma tristate (Paul)
 - Remove __exit tag from .remove (Maxime)
 - Update MAINTAINERS rule to fdma* (Lee)
 - Unit address should match reg property (Lee)

Peter Griffin (18):
  remoteproc: st_xp70_rproc: add a xp70 slimcore rproc driver
  ARM: multi_v7_defconfig: enable st xp70 rproc driver.
  MAINTAINERS: Add st xp70 rproc driver to STi section.
  dmaengine: st_fdma: Add STMicroelectronics FDMA DT binding
    documentation
  dmaengine: st_fdma: Add STMicroelectronics FDMA driver header file
  dmaengine: st_fdma: Add STMicroelectronics FDMA engine driver support
  ARM: STi: DT: STiH407: Add FDMA driver dt nodes.
  MAINTAINERS: Add FDMA driver files to STi section.
  ARM: multi_v7_defconfig: Enable STi FDMA driver
  ASoC: sti: Update DT example to match the driver code
  ARM: multi_v7_defconfig: Enable STi and simple-card drivers.
  ARM: DT: STiH407: Add i2s_out pinctrl configuration
  ARM: DT: STiH407: Add i2s_in pinctrl configuration
  ARM: DT: STiH407: Add spdif_out pinctrl config
  ARM: STi: DT: STiH407: Add sti-sasg-codec dt node
  ARM: STi: DT: STiH407: Add uniperif player dt nodes
  ARM: STi: DT: STiH407: Add uniperif reader dt nodes
  ARM: DT: STi: stihxxx-b2120: Add DT nodes for STi audio card

 Documentation/devicetree/bindings/dma/st_fdma.txt  |  87 ++
 .../devicetree/bindings/sound/st,sti-asoc-card.txt |  20 +-
 MAINTAINERS                                        |   3 +
 arch/arm/boot/dts/stih407-family.dtsi              | 165 ++++
 arch/arm/boot/dts/stih407-pinctrl.dtsi             |  55 ++
 arch/arm/boot/dts/stihxxx-b2120.dtsi               |  40 +
 arch/arm/configs/multi_v7_defconfig                |   5 +
 drivers/dma/Kconfig                                |  12 +
 drivers/dma/Makefile                               |   1 +
 drivers/dma/st_fdma.c                              | 882 +++++++++++++++++++++
 drivers/dma/st_fdma.h                              | 243 ++++++
 drivers/remoteproc/Kconfig                         |   8 +
 drivers/remoteproc/Makefile                        |   1 +
 drivers/remoteproc/st_xp70_rproc.c                 | 380 +++++++++
 include/linux/remoteproc/st_xp70_rproc.h           |  56 ++
 15 files changed, 1948 insertions(+), 10 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/dma/st_fdma.txt
 create mode 100644 drivers/dma/st_fdma.c
 create mode 100644 drivers/dma/st_fdma.h
 create mode 100644 drivers/remoteproc/st_xp70_rproc.c
 create mode 100644 include/linux/remoteproc/st_xp70_rproc.h

-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:35 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:35 +0100
Subject: [PATCH v4 01/18] remoteproc: st_xp70_rproc: add a xp70 slimcore rproc
 driver
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-3-git-send-email-peter.griffin@linaro.org>

XP70 slim core is used as a basis for many IPs in the STi
chipsets such as fdma, display, and demux. To avoid
duplicating the elf loading code in each device driver
an xp70 rproc driver has been created.

This driver is designed to be used by other device drivers
such as fdma, or demux whose IP is based around a xp70 slimcore.
The device driver can call xp70_rproc_alloc() to allocate
an xp70 rproc and xp70_rproc_put() when finished.

This driver takes care of ioremapping the xp70
registers (dmem, imem, slimcore, peripherals), whose offsets
and sizes can change between IP's. It also obtains and enables
any clocks used by the device. This approach avoids having
a double mapping of the registers as xp70_rproc does not register
its own platform device. It also maps well to device tree
abstraction as it allows us to have one dt node for the whole
device.

All of the generic rproc elf loading code can be reused, and
we provide start() stop() hooks to start and stop the xp70
core once the firmware has been loaded. This has been tested
successfully with fdma driver.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 drivers/remoteproc/Kconfig               |   8 +
 drivers/remoteproc/Makefile              |   1 +
 drivers/remoteproc/st_xp70_rproc.c       | 380 +++++++++++++++++++++++++++++++
 include/linux/remoteproc/st_xp70_rproc.h |  56 +++++
 4 files changed, 445 insertions(+)
 create mode 100644 drivers/remoteproc/st_xp70_rproc.c
 create mode 100644 include/linux/remoteproc/st_xp70_rproc.h

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 72e97d7..9e48fd1 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -86,4 +86,12 @@ config ST_REMOTEPROC
 	  processor framework.
 	  This can be either built-in or a loadable module.
 
+config ST_XP70_REMOTEPROC
+	tristate "XP70 slim remoteproc support"
+	depends on ARCH_STI
+	select REMOTEPROC
+	help
+	  Say y here to support xp70 slim core.
+	  If unsure say N.
+
 endmenu
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 279cb2e..b5dab8e 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_STE_MODEM_RPROC)	 	+= ste_modem_rproc.o
 obj-$(CONFIG_WKUP_M3_RPROC)		+= wkup_m3_rproc.o
 obj-$(CONFIG_DA8XX_REMOTEPROC)		+= da8xx_remoteproc.o
 obj-$(CONFIG_ST_REMOTEPROC)		+= st_remoteproc.o
+obj-$(CONFIG_ST_XP70_REMOTEPROC)	+= st_xp70_rproc.o
diff --git a/drivers/remoteproc/st_xp70_rproc.c b/drivers/remoteproc/st_xp70_rproc.c
new file mode 100644
index 0000000..6a78e7c
--- /dev/null
+++ b/drivers/remoteproc/st_xp70_rproc.c
@@ -0,0 +1,380 @@
+/*
+ * st_xp70_rproc.c
+ *
+ * Copyright (C) 2016 STMicroelectronics
+ * Author: Peter Griffin <peter.griffin at st.com>
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/elf.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/remoteproc.h>
+#include <linux/remoteproc/st_xp70_rproc.h>
+#include "remoteproc_internal.h"
+
+/* slimcore registers */
+#define XP70_ID_OFST		0x0
+#define XP70_VER_OFST		0x4
+
+#define XP70_EN_OFST		0x8
+#define XP70_EN_RUN			BIT(0)
+
+#define XP70_CLK_GATE_OFST	0xC
+#define XP70_CLK_GATE_DIS		BIT(0)
+#define XP70_CLK_GATE_RESET		BIT(2)
+
+#define XP70_SLIM_PC_OFST	0x20
+
+/* dmem registers */
+#define XP70_REV_ID_OFST	0x0
+#define XP70_REV_ID_MIN_MASK		GENMASK(15, 8)
+#define XP70_REV_ID_MIN(id)		((id & XP70_REV_ID_MIN_MASK) >> 8)
+#define XP70_REV_ID_MAJ_MASK		GENMASK(23, 16)
+#define XP70_REV_ID_MAJ(id)		((id & XP70_REV_ID_MAJ_MASK) >> 16)
+
+
+/* peripherals registers */
+#define XP70_STBUS_SYNC_OFST	0xF88
+#define XP70_STBUS_SYNC_DIS		BIT(0)
+
+#define XP70_INT_SET_OFST	0xFD4
+#define XP70_INT_CLR_OFST	0xFD8
+#define XP70_INT_MASK_OFST	0xFDC
+
+#define XP70_CMD_CLR_OFST	0xFC8
+#define XP70_CMD_MASK_OFST	0xFCC
+
+const char *mem_names[XP70_MEM_MAX] = {
+	[DMEM]		= "dmem",
+	[IMEM]		= "imem",
+};
+
+static int xp70_clk_get(struct st_xp70_rproc *xp70_rproc, struct device *dev)
+{
+	int clk, err = 0;
+
+	for (clk = 0; clk < XP70_MAX_CLK; clk++) {
+		xp70_rproc->clks[clk] = of_clk_get(dev->of_node, clk);
+		if (IS_ERR(xp70_rproc->clks[clk])) {
+			err = PTR_ERR(xp70_rproc->clks[clk]);
+			if (err == -EPROBE_DEFER)
+				goto err_put_clks;
+			xp70_rproc->clks[clk] = NULL;
+			break;
+		}
+	}
+
+	return 0;
+
+err_put_clks:
+	while (--clk >= 0)
+		clk_put(xp70_rproc->clks[clk]);
+
+	return err;
+}
+
+static void xp70_clk_disable(struct st_xp70_rproc *xp70_rproc)
+{
+	int clk;
+
+	for (clk = 0; clk < XP70_MAX_CLK && xp70_rproc->clks[clk]; clk++)
+		clk_disable_unprepare(xp70_rproc->clks[clk]);
+}
+
+static int xp70_clk_enable(struct st_xp70_rproc *xp70_rproc)
+{
+	int clk, ret;
+
+	for (clk = 0; clk < XP70_MAX_CLK && xp70_rproc->clks[clk]; clk++) {
+		ret = clk_prepare_enable(xp70_rproc->clks[clk]);
+		if (ret)
+			goto err_disable_clks;
+	}
+
+	return 0;
+
+err_disable_clks:
+	while (--clk >= 0)
+		clk_disable_unprepare(xp70_rproc->clks[clk]);
+
+	return ret;
+}
+
+/**
+ * Remoteproc xp70 specific device handlers
+ */
+static int xp70_rproc_start(struct rproc *rproc)
+{
+	struct device *dev = &rproc->dev;
+	struct st_xp70_rproc *xp70_rproc = rproc->priv;
+	unsigned long hw_id, hw_ver, fw_rev;
+	u32 val, ret = 0;
+
+	ret = xp70_clk_enable(xp70_rproc);
+	if (ret) {
+		dev_err(dev, "Failed to enable clocks\n");
+		goto err_clk;
+	}
+
+	/* disable CPU pipeline clock & reset cpu pipeline */
+	val = XP70_CLK_GATE_DIS | XP70_CLK_GATE_RESET;
+	writel_relaxed(val, xp70_rproc->slimcore + XP70_CLK_GATE_OFST);
+
+	/* disable SLIM core STBus sync */
+	writel_relaxed(XP70_STBUS_SYNC_DIS,
+		xp70_rproc->peri + XP70_STBUS_SYNC_OFST);
+
+	/* enable cpu pipeline clock */
+	writel_relaxed(!XP70_CLK_GATE_DIS,
+		xp70_rproc->slimcore + XP70_CLK_GATE_OFST);
+
+	/* clear int & cmd mailbox */
+	writel_relaxed(~0UL, xp70_rproc->peri + XP70_INT_CLR_OFST);
+	writel_relaxed(~0UL, xp70_rproc->peri + XP70_CMD_CLR_OFST);
+
+	/* enable all channels cmd & int */
+	writel_relaxed(~0UL, xp70_rproc->peri + XP70_INT_MASK_OFST);
+	writel_relaxed(~0UL, xp70_rproc->peri + XP70_CMD_MASK_OFST);
+
+	/* enable cpu */
+	writel(XP70_EN_RUN, xp70_rproc->slimcore + XP70_EN_OFST);
+
+	hw_id = readl_relaxed(xp70_rproc->slimcore + XP70_ID_OFST);
+	hw_ver = readl_relaxed(xp70_rproc->slimcore + XP70_VER_OFST);
+
+	fw_rev = readl_relaxed(xp70_rproc->mem[DMEM].cpu_addr +
+			XP70_REV_ID_OFST);
+
+	dev_info(dev, "fw rev:%ld.%ld on SLIM %ld.%ld\n",
+		 XP70_REV_ID_MAJ(fw_rev), XP70_REV_ID_MIN(fw_rev),
+		 hw_id, hw_ver);
+
+	dev_dbg(dev, "XP70 started\n");
+
+err_clk:
+	return ret;
+}
+
+static int xp70_rproc_stop(struct rproc *rproc)
+{
+	struct st_xp70_rproc *xp70_rproc = rproc->priv;
+	u32 val;
+
+	/* mask all (cmd & int) channels */
+	writel_relaxed(0UL, xp70_rproc->peri + XP70_INT_MASK_OFST);
+	writel_relaxed(0UL, xp70_rproc->peri + XP70_CMD_MASK_OFST);
+
+	/* disable cpu pipeline clock */
+	writel_relaxed(XP70_CLK_GATE_DIS
+		, xp70_rproc->slimcore + XP70_CLK_GATE_OFST);
+
+	writel_relaxed(!XP70_EN_RUN, xp70_rproc->slimcore + XP70_EN_OFST);
+
+	val = readl_relaxed(xp70_rproc->slimcore + XP70_EN_OFST);
+	if (val & XP70_EN_RUN)
+		dev_warn(&rproc->dev, "Failed to disable XP70");
+
+	xp70_clk_disable(xp70_rproc);
+
+	dev_dbg(&rproc->dev, "xp70 stopped\n");
+
+	return 0;
+}
+
+static void *xp70_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+{
+	struct st_xp70_rproc *xp70_rproc = rproc->priv;
+	void *va = NULL;
+	int i;
+
+	for (i = 0; i < XP70_MEM_MAX; i++) {
+
+		if (da != xp70_rproc->mem[i].bus_addr)
+			continue;
+
+		va = xp70_rproc->mem[i].cpu_addr;
+			break;
+	}
+
+	dev_dbg(&rproc->dev, "%s: da = 0x%llx len = 0x%x va = 0x%p\n"
+		, __func__, da, len, va);
+
+	return va;
+}
+
+static struct rproc_ops xp70_rproc_ops = {
+	.start		= xp70_rproc_start,
+	.stop		= xp70_rproc_stop,
+	.da_to_va       = xp70_rproc_da_to_va,
+};
+
+/**
+ * Firmware handler operations: sanity, boot address, load ...
+ */
+
+static struct resource_table empty_rsc_tbl = {
+	.ver = 1,
+	.num = 0,
+};
+
+static struct resource_table *xp70_rproc_find_rsc_table(struct rproc *rproc,
+					       const struct firmware *fw,
+					       int *tablesz)
+{
+	if (!fw)
+		return NULL;
+
+	*tablesz = sizeof(empty_rsc_tbl);
+	return &empty_rsc_tbl;
+}
+
+static struct resource_table *xp70_rproc_find_loaded_rsc_table(struct rproc *rproc,
+						      const struct firmware *fw)
+{
+	if (!fw)
+		return NULL;
+
+	return &empty_rsc_tbl;
+}
+
+static struct rproc_fw_ops xp70_rproc_fw_ops = {
+	.find_rsc_table = xp70_rproc_find_rsc_table,
+	.find_loaded_rsc_table = xp70_rproc_find_loaded_rsc_table,
+};
+
+/**
+  * xp70_rproc_alloc - allocate and initialise xp70 rproc
+  * @pdev: Pointer to the platform_device struct
+  * @fw_name: Name of firmware for rproc to use
+  *
+  * Function for allocating and initialising a xp70 rproc for use by
+  * device drivers whose IP is based around the xp70 slim core. It
+  * obtains and enables any clocks required by the xp70 core and also
+  * ioremaps the various IO.
+  *
+  * Returns rproc pointer or PTR_ERR() on error.
+  */
+
+struct rproc *xp70_rproc_alloc(struct platform_device *pdev, char *fw_name)
+{
+	struct device *dev = &pdev->dev;
+	struct st_xp70_rproc *xp70_rproc;
+	struct device_node *np = dev->of_node;
+	struct rproc *rproc;
+	struct resource *res;
+	int err, i;
+	const struct rproc_fw_ops *elf_ops;
+
+	if (!np || !fw_name)
+		return ERR_PTR(-EINVAL);
+
+	if (!of_device_is_compatible(np, "st,xp70-rproc"))
+		return ERR_PTR(-EINVAL);
+
+	rproc = rproc_alloc(dev, np->name, &xp70_rproc_ops,
+			fw_name, sizeof(*xp70_rproc));
+	if (!rproc)
+		return ERR_PTR(-ENOMEM);
+
+	rproc->has_iommu = false;
+
+	xp70_rproc = rproc->priv;
+	xp70_rproc->rproc = rproc;
+
+	/* Get standard ELF ops */
+	elf_ops = rproc_get_elf_ops();
+
+	/* Use some generic elf ops */
+	xp70_rproc_fw_ops.load = elf_ops->load;
+	xp70_rproc_fw_ops.sanity_check = elf_ops->sanity_check;
+
+	rproc->fw_ops = &xp70_rproc_fw_ops;
+
+	/* get imem and dmem */
+	for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
+		res = xp70_rproc->mem[i].io_res;
+
+		res = platform_get_resource_byname
+			(pdev, IORESOURCE_MEM, mem_names[i]);
+
+		xp70_rproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res);
+		if (IS_ERR(xp70_rproc->mem[i].cpu_addr)) {
+			dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
+			err = PTR_ERR(xp70_rproc->mem[i].cpu_addr);
+			goto err;
+		}
+		xp70_rproc->mem[i].bus_addr = res->start;
+		xp70_rproc->mem[i].size = resource_size(res);
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "slimcore");
+
+	xp70_rproc->slimcore = devm_ioremap_resource(dev, res);
+	if (IS_ERR(xp70_rproc->slimcore)) {
+		dev_err(&pdev->dev, "devm_ioremap_resource failed for slimcore\n");
+		err = PTR_ERR(xp70_rproc->slimcore);
+		goto err;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "peripherals");
+
+	xp70_rproc->peri = devm_ioremap_resource(dev, res);
+	if (IS_ERR(xp70_rproc->peri)) {
+		dev_err(&pdev->dev, "devm_ioremap_resource failed for peri\n");
+		err = PTR_ERR(xp70_rproc->peri);
+		goto err;
+	}
+
+	err = xp70_clk_get(xp70_rproc, dev);
+	if (err)
+		goto err;
+
+	/* Register as a remoteproc device */
+	err = rproc_add(rproc);
+	if (err) {
+		dev_err(dev, "registration of xp70 remoteproc failed\n");
+		goto err;
+	}
+
+	dev_dbg(dev, "XP70 rproc init successful\n");
+	return rproc;
+
+err:
+	rproc_put(rproc);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL(xp70_rproc_alloc);
+
+/**
+  * xp70_rproc_put - put xp70 rproc resources
+  * @xp70_rproc: Pointer to the st_xp70_rproc struct
+  *
+  * Function for calling respective _put() functions on
+  * xp70_rproc resources.
+  *
+  * Returns rproc pointer or PTR_ERR() on error.
+  */
+void xp70_rproc_put(struct st_xp70_rproc *xp70_rproc)
+{
+	int clk;
+
+	if (!xp70_rproc)
+		return;
+
+	rproc_put(xp70_rproc->rproc);
+
+	for (clk = 0; clk < XP70_MAX_CLK && xp70_rproc->clks[clk]; clk++)
+		clk_put(xp70_rproc->clks[clk]);
+
+}
+EXPORT_SYMBOL(xp70_rproc_put);
+
+MODULE_AUTHOR("Peter Griffin");
+MODULE_DESCRIPTION("STMicroelectronics XP70 rproc driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/remoteproc/st_xp70_rproc.h b/include/linux/remoteproc/st_xp70_rproc.h
new file mode 100644
index 0000000..3aba2de
--- /dev/null
+++ b/include/linux/remoteproc/st_xp70_rproc.h
@@ -0,0 +1,56 @@
+/*
+ * st_xp70_rproc.h
+ *
+ * Copyright (C) 2016 STMicroelectronics
+ * Author: Peter Griffin <peter.griffin at linaro.org>
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+#ifndef _ST_XP70_H
+#define _ST_XP70_H
+
+#define XP70_MEM_MAX 2
+#define XP70_MAX_CLK 4
+#define NAME_SZ 10
+
+enum {
+	DMEM,
+	IMEM,
+};
+
+/**
+ * struct xp70_mem - xp70 internal memory structure
+ * @cpu_addr: MPU virtual address of the memory region
+ * @bus_addr: Bus address used to access the memory region
+ * @dev_addr: Device address from Wakeup M3 view
+ * @size: Size of the memory region
+ */
+struct xp70_mem {
+	void __iomem *cpu_addr;
+	phys_addr_t bus_addr;
+	u32 dev_addr;
+	size_t size;
+	struct resource *io_res;
+};
+
+/**
+ * struct st_xp70_rproc - XP70 slim core
+ * @rproc: rproc handle
+ * @pdev: pointer to platform device
+ * @mem: xp70 memory information
+ * @slimcore: xp70 slimcore regs
+ * @peri: xp70 peripheral regs
+ * @clks: xp70 clocks
+ */
+struct st_xp70_rproc {
+	struct rproc *rproc;
+	struct platform_device *pdev;
+	struct xp70_mem mem[XP70_MEM_MAX];
+	void __iomem *slimcore;
+	void __iomem *peri;
+	struct clk *clks[XP70_MAX_CLK];
+};
+
+struct rproc *xp70_rproc_alloc(struct platform_device *pdev, char *fw_name);
+void xp70_rproc_put(struct st_xp70_rproc *xp70_rproc);
+
+#endif
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:37 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:37 +0100
Subject: [PATCH v4 03/18] MAINTAINERS: Add st xp70 rproc driver to STi section.
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-5-git-send-email-peter.griffin@linaro.org>

This patch adds the xp70 rproc driver to the STi section
of the MAINTAINERS file.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 MAINTAINERS | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 61a323a..de99aec 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1647,6 +1647,7 @@ F:	drivers/phy/phy-miphy365x.c
 F:	drivers/phy/phy-stih407-usb.c
 F:	drivers/phy/phy-stih41x-usb.c
 F:	drivers/pinctrl/pinctrl-st.c
+F:	drivers/remoteproc/st_xp70_rproc.c
 F:	drivers/reset/sti/
 F:	drivers/rtc/rtc-st-lpc.c
 F:	drivers/tty/serial/st-asc.c
@@ -1655,6 +1656,7 @@ F:	drivers/usb/host/ehci-st.c
 F:	drivers/usb/host/ohci-st.c
 F:	drivers/watchdog/st_lpc_wdt.c
 F:	drivers/ata/ahci_st.c
+F:	include/linux/remoteproc/st_xp70_rproc.h
 
 ARM/STM32 ARCHITECTURE
 M:	Maxime Coquelin <mcoquelin.stm32 at gmail.com>
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:36 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:36 +0100
Subject: [PATCH v4 02/18] ARM: multi_v7_defconfig: enable st xp70 rproc driver.
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-4-git-send-email-peter.griffin@linaro.org>

This is used by other device drivers whose IP is based
around the xp70 slim core (such as fdma) to load and
boot the firmware in the slimcore.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 2823490..d319d8f 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -503,6 +503,7 @@ CONFIG_REGULATOR_TPS6586X=y
 CONFIG_REGULATOR_TPS65910=y
 CONFIG_REGULATOR_TWL4030=y
 CONFIG_REGULATOR_VEXPRESS=y
+CONFIG_ST_XP70_REMOTEPROC=m
 CONFIG_MEDIA_SUPPORT=m
 CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:38 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:38 +0100
Subject: [PATCH v4 04/18] dmaengine: st_fdma: Add STMicroelectronics FDMA DT
 binding documentation
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-6-git-send-email-peter.griffin@linaro.org>

This patch adds the DT binding documentation for the FDMA constroller
found on STi based chipsets from STMicroelectronics.

Signed-off-by: Ludovic Barre <ludovic.barre at st.com>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 Documentation/devicetree/bindings/dma/st_fdma.txt | 87 +++++++++++++++++++++++
 1 file changed, 87 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/st_fdma.txt

diff --git a/Documentation/devicetree/bindings/dma/st_fdma.txt b/Documentation/devicetree/bindings/dma/st_fdma.txt
new file mode 100644
index 0000000..8fd60a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/st_fdma.txt
@@ -0,0 +1,87 @@
+* STMicroelectronics Flexible Direct Memory Access Device Tree bindings
+
+The FDMA is a general-purpose direct memory access controller capable of
+supporting 16 independent DMA channels. It accepts up to 32 DMA requests.
+The FDMA is based on a Slim processor which requires a firmware.
+
+* FDMA Controller
+
+Required properties:
+- compatible	: Should be one of
+		 - st,stih407-fdma-mpe31-11, "st,xp70-rproc";
+		 - st,stih407-fdma-mpe31-12, "st,xp70-rproc";
+		 - st,stih407-fdma-mpe31-13, "st,xp70-rproc";
+- reg		: Should contain an entry for each name in reg-names
+- reg-names	: Must contain "slimcore", "dmem", "peripherals", "imem" entries
+- interrupts	: Should contain one interrupt shared by all channels
+- dma-channels	: Number of channels supported by the controller
+- #dma-cells	: Must be <3>. See DMA client section below
+- clocks	: Must contain an entry for each clock
+See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+
+Example:
+
+	fdma0: dma-controller at 8e20000 {
+		compatible = "st,stih407-fdma-mpe31-11", "st,xp70-rproc";
+		reg = <0x8e20000 0x8000>,
+		      <0x8e30000 0x3000>,
+		      <0x8e37000 0x1000>,
+		      <0x8e38000 0x8000>;
+		reg-names = "slimcore", "dmem", "peripherals", "imem";
+		clocks = <&clk_s_c0_flexgen CLK_FDMA>,
+			 <&clk_s_c0_flexgen CLK_EXT2F_A9>,
+			 <&clk_s_c0_flexgen CLK_EXT2F_A9>,
+			 <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+		interrupts = <GIC_SPI 5 IRQ_TYPE_NONE>;
+		dma-channels = <16>;
+		#dma-cells = <3>;
+	};
+
+* DMA client
+
+Required properties:
+- dmas: Comma separated list of dma channel requests
+- dma-names: Names of the aforementioned requested channels
+
+Each dmas request consists of 4 cells:
+1. A phandle pointing to the FDMA controller
+2. The request line number
+3. A 32bit mask specifying (see include/linux/platform_data/dma-st-fdma.h)
+ -bit 2-0: Holdoff value, dreq will be masked for
+	0x0: 0-0.5us
+	0x1: 0.5-1us
+	0x2: 1-1.5us
+ -bit 17: data swap
+	0x0: disabled
+	0x1: enabled
+ -bit 21: Increment Address
+	0x0: no address increment between transfers
+	0x1: increment address between transfers
+ -bit 22: 2 STBus Initiator Coprocessor interface
+	0x0: high priority port
+	0x1: low priority port
+4. transfers type
+ 0 free running
+ 1 paced
+
+Example:
+
+	sti_uni_player2: sti-uni-player at 2 {
+		compatible = "st,sti-uni-player";
+		status = "disabled";
+		#sound-dai-cells = <0>;
+		st,syscfg = <&syscfg_core>;
+		clocks = <&clk_s_d0_flexgen CLK_PCM_2>;
+		assigned-clocks = <&clk_s_d0_flexgen CLK_PCM_2>;
+		assigned-clock-parents = <&clk_s_d0_quadfs 2>;
+		assigned-clock-rates = <50000000>;
+		reg = <0x8D82000 0x158>;
+		interrupts = <GIC_SPI 86 IRQ_TYPE_NONE>;
+		dmas = <&fdma0 4 0 1>;
+		dai-name = "Uni Player #1 (DAC)";
+		dma-names = "tx";
+		st,uniperiph-id = <2>;
+		st,version = <5>;
+		st,mode = "PCM";
+	};
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:40 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:40 +0100
Subject: [PATCH v4 06/18] dmaengine: st_fdma: Add STMicroelectronics FDMA
 engine driver support
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-8-git-send-email-peter.griffin@linaro.org>

This patch adds support for the Flexible Direct Memory Access (FDMA) core
driver. The FDMA is a slim core CPU with a dedicated firmware.
It is a general purpose DMA controller capable of supporting 16
independent DMA channels. Data moves maybe from memory to memory
or between memory and paced latency critical real time targets and it
is found on al STi based chipsets.

Signed-off-by: Ludovic Barre <ludovic.barre at st.com>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 drivers/dma/Kconfig   |  12 +
 drivers/dma/Makefile  |   1 +
 drivers/dma/st_fdma.c | 882 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 895 insertions(+)
 create mode 100644 drivers/dma/st_fdma.c

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d96d87c..a65b8b3 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -527,6 +527,18 @@ config ZX_DMA
 	help
 	  Support the DMA engine for ZTE ZX296702 platform devices.
 
+config ST_FDMA
+	tristate "ST FDMA dmaengine support"
+	depends on ARCH_STI || COMPILE_TEST
+        depends on ST_XP70_REMOTEPROC
+	select DMA_ENGINE
+	select DMA_VIRTUAL_CHANNELS
+	help
+	  Enable support for ST FDMA controller.
+	  It supports 16 independent DMA channels, accepts up to 32 DMA requests
+
+	  Say Y here if you have such a chipset.
+	  If unsure, say N.
 
 # driver files
 source "drivers/dma/bestcomm/Kconfig"
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 6084127..b81ca99 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_TI_DMA_CROSSBAR) += ti-dma-crossbar.o
 obj-$(CONFIG_TI_EDMA) += edma.o
 obj-$(CONFIG_XGENE_DMA) += xgene-dma.o
 obj-$(CONFIG_ZX_DMA) += zx296702_dma.o
+obj-$(CONFIG_ST_FDMA) += st_fdma.o
 
 obj-y += qcom/
 obj-y += xilinx/
diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c
new file mode 100644
index 0000000..34496b0
--- /dev/null
+++ b/drivers/dma/st_fdma.c
@@ -0,0 +1,882 @@
+/*
+ * st_fdma.c
+ *
+ * Copyright (C) 2014 STMicroelectronics
+ * Author: Ludovic Barre <Ludovic.barre at st.com>
+ *	   Peter Griffin <peter.griffin at st.com>
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/firmware.h>
+#include <linux/elf.h>
+#include <linux/atomic.h>
+#include <linux/remoteproc.h>
+#include <linux/io.h>
+
+#include "st_fdma.h"
+#include "dmaengine.h"
+#include "virt-dma.h"
+
+static inline struct st_fdma_chan *to_st_fdma_chan(struct dma_chan *c)
+{
+	return container_of(c, struct st_fdma_chan, vchan.chan);
+}
+
+static struct st_fdma_desc *to_st_fdma_desc(struct virt_dma_desc *vd)
+{
+	return container_of(vd, struct st_fdma_desc, vdesc);
+}
+
+static int st_fdma_dreq_get(struct st_fdma_chan *fchan)
+{
+	struct st_fdma_dev *fdev = fchan->fdev;
+	u32 req_line_cfg = fchan->cfg.req_line;
+	u32 dreq_line;
+	int try = 0;
+
+	/*
+	 * dreq_mask is shared for n channels of fdma, so all accesses must be
+	 * atomic. if the dreq_mask it change between ffz ant set_bit,
+	 * we retry
+	 */
+	do {
+		if (fdev->dreq_mask == ~0L) {
+			dev_err(fdev->dev, "No req lines available\n");
+			return -EINVAL;
+		}
+
+		if (try || req_line_cfg >= ST_FDMA_NR_DREQS) {
+			dev_err(fdev->dev, "Invalid or used req line\n");
+			return -EINVAL;
+		} else {
+			dreq_line = req_line_cfg;
+		}
+
+		try++;
+	} while (test_and_set_bit(dreq_line, &fdev->dreq_mask));
+
+	dev_dbg(fdev->dev, "get dreq_line:%d mask:%#lx\n",
+		dreq_line, fdev->dreq_mask);
+
+	return dreq_line;
+}
+
+static void st_fdma_dreq_put(struct st_fdma_chan *fchan)
+{
+	struct st_fdma_dev *fdev = fchan->fdev;
+
+	dev_dbg(fdev->dev, "put dreq_line:%#x\n", fchan->dreq_line);
+	clear_bit(fchan->dreq_line, &fdev->dreq_mask);
+}
+
+static void st_fdma_xfer_desc(struct st_fdma_chan *fchan)
+{
+	struct virt_dma_desc *vdesc;
+	unsigned long nbytes, ch_cmd, cmd;
+
+	vdesc = vchan_next_desc(&fchan->vchan);
+	if (!vdesc)
+		return;
+
+	fchan->fdesc = to_st_fdma_desc(vdesc);
+	nbytes = fchan->fdesc->node[0].desc->nbytes;
+	cmd = FDMA_CMD_START(fchan->vchan.chan.chan_id);
+	ch_cmd = fchan->fdesc->node[0].pdesc | FDMA_CH_CMD_STA_START;
+
+	/* start the channel for the descriptor */
+	fnode_write(fchan, nbytes, FDMA_CNTN_OFST);
+	fchan_write(fchan, ch_cmd, FDMA_CH_CMD_OFST);
+	writel(cmd,
+		fchan->fdev->xp70_rproc->peri + FDMA_CMD_SET_OFST);
+
+	dev_dbg(fchan->fdev->dev, "start chan:%d\n", fchan->vchan.chan.chan_id);
+}
+
+static void st_fdma_ch_sta_update(struct st_fdma_chan *fchan,
+				  unsigned long int_sta)
+{
+	unsigned long ch_sta, ch_err;
+	int ch_id = fchan->vchan.chan.chan_id;
+	struct st_fdma_dev *fdev = fchan->fdev;
+
+	ch_sta = fchan_read(fchan, FDMA_CH_CMD_OFST);
+	ch_err = ch_sta & FDMA_CH_CMD_ERR_MASK;
+	ch_sta &= FDMA_CH_CMD_STA_MASK;
+
+	if (int_sta & FDMA_INT_STA_ERR) {
+		dev_warn(fdev->dev, "chan:%d, error:%ld\n", ch_id, ch_err);
+		fchan->status = DMA_ERROR;
+		return;
+	}
+
+	switch (ch_sta) {
+	case FDMA_CH_CMD_STA_PAUSED:
+		fchan->status = DMA_PAUSED;
+		break;
+	case FDMA_CH_CMD_STA_RUNNING:
+		fchan->status = DMA_IN_PROGRESS;
+		break;
+	}
+}
+
+static irqreturn_t st_fdma_irq_handler(int irq, void *dev_id)
+{
+	struct st_fdma_dev *fdev = dev_id;
+	irqreturn_t ret = IRQ_NONE;
+	struct st_fdma_chan *fchan = &fdev->chans[0];
+	unsigned long int_sta, clr;
+
+	int_sta = fdma_read(fdev, FDMA_INT_STA_OFST);
+	clr = int_sta;
+
+	for (; int_sta != 0 ; int_sta >>= 2, fchan++) {
+		if (!(int_sta & (FDMA_INT_STA_CH | FDMA_INT_STA_ERR)))
+			continue;
+
+		spin_lock(&fchan->vchan.lock);
+		st_fdma_ch_sta_update(fchan, int_sta);
+
+		if (fchan->fdesc) {
+			if (!fchan->fdesc->iscyclic) {
+				list_del(&fchan->fdesc->vdesc.node);
+				vchan_cookie_complete(&fchan->fdesc->vdesc);
+				fchan->fdesc = NULL;
+				fchan->status = DMA_COMPLETE;
+			} else {
+				vchan_cyclic_callback(&fchan->fdesc->vdesc);
+			}
+
+			/* Start the next descriptor (if available) */
+			if (!fchan->fdesc)
+				st_fdma_xfer_desc(fchan);
+		}
+
+		spin_unlock(&fchan->vchan.lock);
+		ret = IRQ_HANDLED;
+	}
+
+	fdma_write(fdev, clr, FDMA_INT_CLR_OFST);
+
+	return ret;
+}
+
+static struct dma_chan *st_fdma_of_xlate(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	struct st_fdma_dev *fdev = ofdma->of_dma_data;
+	struct dma_chan *chan;
+	struct st_fdma_chan *fchan;
+
+	if (dma_spec->args_count < 1)
+		return NULL;
+
+	chan = dma_get_any_slave_channel(&fdev->dma_device);
+	if (!chan)
+		return NULL;
+
+	fchan = to_st_fdma_chan(chan);
+
+	if (fchan->fdev->dma_device.dev->of_node != dma_spec->np)
+		return NULL;
+
+	fchan->cfg.of_node = dma_spec->np;
+	fchan->cfg.req_line = dma_spec->args[0];
+	fchan->cfg.req_ctrl = 0;
+	fchan->cfg.type = ST_FDMA_TYPE_FREE_RUN;
+
+	if (dma_spec->args_count > 1)
+		fchan->cfg.req_ctrl = dma_spec->args[1] & REQ_CTRL_CFG_MASK;
+
+	if (dma_spec->args_count > 2)
+		fchan->cfg.type = dma_spec->args[2];
+
+	if (fchan->cfg.type == ST_FDMA_TYPE_FREE_RUN) {
+		fchan->dreq_line = 0;
+	} else {
+		fchan->dreq_line = st_fdma_dreq_get(fchan);
+		if (IS_ERR_VALUE(fchan->dreq_line))
+			return NULL;
+	}
+
+	dev_dbg(fdev->dev, "xlate req_line:%d type:%d req_ctrl:%#lx\n",
+		fchan->cfg.req_line, fchan->cfg.type, fchan->cfg.req_ctrl);
+
+	return chan;
+}
+
+static void st_fdma_free_desc(struct virt_dma_desc *vdesc)
+{
+	struct st_fdma_desc *fdesc;
+	int i;
+
+	fdesc = to_st_fdma_desc(vdesc);
+	for (i = 0; i < fdesc->n_nodes; i++)
+		dma_pool_free(fdesc->fchan->node_pool, fdesc->node[i].desc,
+			      fdesc->node[i].pdesc);
+	kfree(fdesc);
+}
+
+static struct st_fdma_desc *st_fdma_alloc_desc(struct st_fdma_chan *fchan,
+					       int sg_len)
+{
+	struct st_fdma_desc *fdesc;
+	int i;
+
+	fdesc = kzalloc(sizeof(*fdesc) +
+			sizeof(struct st_fdma_sw_node) * sg_len, GFP_NOWAIT);
+	if (!fdesc)
+		return NULL;
+
+	fdesc->fchan = fchan;
+	fdesc->n_nodes = sg_len;
+	for (i = 0; i < sg_len; i++) {
+		fdesc->node[i].desc = dma_pool_alloc(fchan->node_pool,
+				GFP_NOWAIT, &fdesc->node[i].pdesc);
+		if (!fdesc->node[i].desc)
+			goto err;
+	}
+	return fdesc;
+
+err:
+	while (--i >= 0)
+		dma_pool_free(fchan->node_pool, fdesc->node[i].desc,
+			      fdesc->node[i].pdesc);
+	kfree(fdesc);
+	return NULL;
+}
+
+static int st_fdma_alloc_chan_res(struct dma_chan *chan)
+{
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	int ret;
+
+	/* Create the dma pool for descriptor allocation */
+	fchan->node_pool = dma_pool_create(dev_name(&chan->dev->device),
+					    fchan->fdev->dev,
+					    sizeof(struct st_fdma_hw_node),
+					    __alignof__(struct st_fdma_hw_node),
+					    0);
+
+	if (!fchan->node_pool) {
+		dev_err(fchan->fdev->dev, "unable to allocate desc pool\n");
+		return -ENOMEM;
+	}
+
+
+	ret = rproc_boot(fchan->fdev->rproc);
+	if (ret) {
+		dev_err(fchan->fdev->dev, "rproc_boot failed\n");
+		return ret;
+	}
+
+	dev_dbg(fchan->fdev->dev, "alloc ch_id:%d type:%d\n",
+		fchan->vchan.chan.chan_id, fchan->cfg.type);
+
+	return 0;
+}
+
+static void st_fdma_free_chan_res(struct dma_chan *chan)
+{
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	unsigned long flags;
+
+	LIST_HEAD(head);
+
+	dev_dbg(fchan->fdev->dev, "%s: freeing chan:%d\n",
+		__func__, fchan->vchan.chan.chan_id);
+
+	if (fchan->cfg.type != ST_FDMA_TYPE_FREE_RUN)
+		st_fdma_dreq_put(fchan);
+
+	spin_lock_irqsave(&fchan->vchan.lock, flags);
+	fchan->fdesc = NULL;
+	vchan_get_all_descriptors(&fchan->vchan, &head);
+	spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+
+	dma_pool_destroy(fchan->node_pool);
+	fchan->node_pool = NULL;
+	memset(&fchan->cfg, 0, sizeof(struct st_fdma_cfg));
+
+	rproc_shutdown(fchan->fdev->rproc);
+}
+
+static struct dma_async_tx_descriptor *st_fdma_prep_dma_memcpy(
+	struct dma_chan *chan,	dma_addr_t dst, dma_addr_t src,
+	size_t len, unsigned long flags)
+{
+	struct st_fdma_chan *fchan;
+	struct st_fdma_desc *fdesc;
+	struct st_fdma_hw_node *hw_node;
+
+	if (!len)
+		return NULL;
+
+	fchan = to_st_fdma_chan(chan);
+
+	/* We only require a single descriptor */
+	fdesc = st_fdma_alloc_desc(fchan, 1);
+	if (!fdesc) {
+		dev_err(fchan->fdev->dev, "no memory for desc\n");
+		return NULL;
+	}
+
+	hw_node = fdesc->node[0].desc;
+	hw_node->next = 0;
+	hw_node->control = NODE_CTRL_REQ_MAP_FREE_RUN;
+	hw_node->control |= NODE_CTRL_SRC_INCR;
+	hw_node->control |= NODE_CTRL_DST_INCR;
+	hw_node->control |= NODE_CTRL_INT_EON;
+	hw_node->nbytes = len;
+	hw_node->saddr = src;
+	hw_node->daddr = dst;
+	hw_node->generic.length = len;
+	hw_node->generic.sstride = 0;
+	hw_node->generic.dstride = 0;
+
+	return vchan_tx_prep(&fchan->vchan, &fdesc->vdesc, flags);
+}
+
+static int config_reqctrl(struct st_fdma_chan *fchan,
+			  enum dma_transfer_direction direction)
+{
+	u32 maxburst = 0, addr = 0;
+	enum dma_slave_buswidth width;
+	int ch_id = fchan->vchan.chan.chan_id;
+	struct st_fdma_dev *fdev = fchan->fdev;
+
+	switch (direction) {
+
+	case DMA_DEV_TO_MEM:
+		fchan->cfg.req_ctrl &= ~REQ_CTRL_WNR;
+		maxburst = fchan->scfg.src_maxburst;
+		width = fchan->scfg.src_addr_width;
+		addr = fchan->scfg.src_addr;
+		break;
+
+	case DMA_MEM_TO_DEV:
+		fchan->cfg.req_ctrl |= REQ_CTRL_WNR;
+		maxburst = fchan->scfg.dst_maxburst;
+		width = fchan->scfg.dst_addr_width;
+		addr = fchan->scfg.dst_addr;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	fchan->cfg.req_ctrl &= ~REQ_CTRL_OPCODE_MASK;
+
+	switch (width) {
+
+	case DMA_SLAVE_BUSWIDTH_1_BYTE:
+		fchan->cfg.req_ctrl |= REQ_CTRL_OPCODE_LD_ST1;
+		break;
+
+	case DMA_SLAVE_BUSWIDTH_2_BYTES:
+		fchan->cfg.req_ctrl |= REQ_CTRL_OPCODE_LD_ST2;
+		break;
+
+	case DMA_SLAVE_BUSWIDTH_4_BYTES:
+		fchan->cfg.req_ctrl |= REQ_CTRL_OPCODE_LD_ST4;
+		break;
+
+	case DMA_SLAVE_BUSWIDTH_8_BYTES:
+		fchan->cfg.req_ctrl |= REQ_CTRL_OPCODE_LD_ST8;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	fchan->cfg.req_ctrl &= ~REQ_CTRL_NUM_OPS_MASK;
+	fchan->cfg.req_ctrl |= REQ_CTRL_NUM_OPS(maxburst-1);
+	dreq_write(fchan, fchan->cfg.req_ctrl, FDMA_REQ_CTRL_OFST);
+
+	fchan->cfg.dev_addr = addr;
+	fchan->cfg.dir = direction;
+
+	dev_dbg(fdev->dev, "chan:%d config_reqctrl:%#x req_ctrl:%#lx\n",
+		ch_id, addr, fchan->cfg.req_ctrl);
+
+	return 0;
+}
+
+static void fill_hw_node(struct st_fdma_hw_node *hw_node,
+			struct st_fdma_chan *fchan,
+			enum dma_transfer_direction direction)
+{
+	if (direction == DMA_MEM_TO_DEV) {
+		hw_node->control |= NODE_CTRL_SRC_INCR;
+		hw_node->control |= NODE_CTRL_DST_STATIC;
+		hw_node->daddr = fchan->cfg.dev_addr;
+	} else {
+		hw_node->control |= NODE_CTRL_SRC_STATIC;
+		hw_node->control |= NODE_CTRL_DST_INCR;
+		hw_node->saddr = fchan->cfg.dev_addr;
+	}
+
+	hw_node->generic.sstride = 0;
+	hw_node->generic.dstride = 0;
+}
+
+static struct st_fdma_chan *st_fdma_prep_common(struct dma_chan *chan,
+		size_t len, enum dma_transfer_direction direction)
+{
+	struct st_fdma_chan *fchan;
+
+	if (!chan || !len)
+		return NULL;
+
+	fchan = to_st_fdma_chan(chan);
+
+	if (!is_slave_direction(direction)) {
+		dev_err(fchan->fdev->dev, "bad direction?\n");
+		return NULL;
+	}
+
+	return fchan;
+}
+
+static struct dma_async_tx_descriptor *st_fdma_prep_dma_cyclic(
+		struct dma_chan *chan, dma_addr_t buf_addr, size_t len,
+		size_t period_len, enum dma_transfer_direction direction,
+		unsigned long flags)
+{
+	struct st_fdma_chan *fchan;
+	struct st_fdma_desc *fdesc;
+	int sg_len, i;
+
+	fchan = st_fdma_prep_common(chan, len, direction);
+	if (!fchan)
+		return NULL;
+
+	if (!period_len)
+		return NULL;
+
+	if (config_reqctrl(fchan, direction)) {
+		dev_err(fchan->fdev->dev, "bad width or direction\n");
+		return NULL;
+	}
+
+	/* the buffer length must be a multiple of period_len */
+	if (len % period_len != 0) {
+		dev_err(fchan->fdev->dev, "len is not multiple of period\n");
+		return NULL;
+	}
+
+	sg_len = len / period_len;
+	fdesc = st_fdma_alloc_desc(fchan, sg_len);
+	if (!fdesc) {
+		dev_err(fchan->fdev->dev, "no memory for desc\n");
+		return NULL;
+	}
+
+	fdesc->iscyclic = true;
+
+	for (i = 0; i < sg_len; i++) {
+		struct st_fdma_hw_node *hw_node = fdesc->node[i].desc;
+
+		hw_node->next = fdesc->node[(i + 1) % sg_len].pdesc;
+
+		hw_node->control = NODE_CTRL_REQ_MAP_DREQ(fchan->dreq_line);
+		hw_node->control |= NODE_CTRL_INT_EON;
+
+		fill_hw_node(hw_node, fchan, direction);
+
+		if (direction == DMA_MEM_TO_DEV)
+			hw_node->saddr = buf_addr + (i * period_len);
+		else
+			hw_node->daddr = buf_addr + (i * period_len);
+
+		hw_node->nbytes = period_len;
+		hw_node->generic.length = period_len;
+	}
+
+	return vchan_tx_prep(&fchan->vchan, &fdesc->vdesc, flags);
+}
+
+static struct dma_async_tx_descriptor *st_fdma_prep_slave_sg(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_transfer_direction direction,
+		unsigned long flags, void *context)
+{
+	struct st_fdma_chan *fchan;
+	struct st_fdma_desc *fdesc;
+	struct st_fdma_hw_node *hw_node;
+	struct scatterlist *sg;
+	int i;
+
+	fchan = st_fdma_prep_common(chan, sg_len, direction);
+	if (!fchan)
+		return NULL;
+
+	if (!sgl)
+		return NULL;
+
+	fdesc = st_fdma_alloc_desc(fchan, sg_len);
+	if (!fdesc) {
+		dev_err(fchan->fdev->dev, "no memory for desc\n");
+		return NULL;
+	}
+
+	fdesc->iscyclic = false;
+
+	for_each_sg(sgl, sg, sg_len, i) {
+		hw_node = fdesc->node[i].desc;
+
+		hw_node->next = fdesc->node[(i + 1) % sg_len].pdesc;
+		hw_node->control = NODE_CTRL_REQ_MAP_DREQ(fchan->dreq_line);
+
+		fill_hw_node(hw_node, fchan, direction);
+
+		if (direction == DMA_MEM_TO_DEV)
+			hw_node->saddr = sg_dma_address(sg);
+		else
+			hw_node->daddr = sg_dma_address(sg);
+
+		hw_node->nbytes = sg_dma_len(sg);
+		hw_node->generic.length = sg_dma_len(sg);
+	}
+
+	/* interrupt at end of last node */
+	hw_node->control |= NODE_CTRL_INT_EON;
+
+	return vchan_tx_prep(&fchan->vchan, &fdesc->vdesc, flags);
+}
+
+static size_t st_fdma_desc_residue(struct st_fdma_chan *fchan,
+				   struct virt_dma_desc *vdesc,
+				   bool in_progress)
+{
+	struct st_fdma_desc *fdesc = fchan->fdesc;
+	size_t residue = 0;
+	dma_addr_t cur_addr = 0;
+	int i;
+
+	if (in_progress) {
+		cur_addr = fchan_read(fchan, FDMA_CH_CMD_OFST);
+		cur_addr &= FDMA_CH_CMD_DATA_MASK;
+	}
+
+	for (i = fchan->fdesc->n_nodes - 1 ; i >= 0; i--) {
+		if (cur_addr == fdesc->node[i].pdesc) {
+			residue += fnode_read(fchan, FDMA_CNTN_OFST);
+			break;
+		}
+		residue += fdesc->node[i].desc->nbytes;
+	}
+
+	return residue;
+}
+
+static enum dma_status st_fdma_tx_status(struct dma_chan *chan,
+					 dma_cookie_t cookie,
+					 struct dma_tx_state *txstate)
+{
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	struct virt_dma_desc *vd;
+	enum dma_status ret;
+	unsigned long flags;
+
+	ret = dma_cookie_status(chan, cookie, txstate);
+	if (ret == DMA_COMPLETE)
+		return ret;
+
+	spin_lock_irqsave(&fchan->vchan.lock, flags);
+	vd = vchan_find_desc(&fchan->vchan, cookie);
+	if (fchan->fdesc && cookie == fchan->fdesc->vdesc.tx.cookie)
+		txstate->residue = st_fdma_desc_residue(fchan, vd, true);
+	else if (vd)
+		txstate->residue = st_fdma_desc_residue(fchan, vd, false);
+	else
+		txstate->residue = 0;
+
+	spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+
+	return ret;
+}
+
+static void st_fdma_issue_pending(struct dma_chan *chan)
+{
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&fchan->vchan.lock, flags);
+
+	if (vchan_issue_pending(&fchan->vchan) && !fchan->fdesc)
+		st_fdma_xfer_desc(fchan);
+
+	spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+}
+
+static int st_fdma_pause(struct dma_chan *chan)
+{
+	unsigned long flags;
+	LIST_HEAD(head);
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	int ch_id = fchan->vchan.chan.chan_id;
+	unsigned long cmd = FDMA_CMD_PAUSE(ch_id);
+
+	dev_dbg(fchan->fdev->dev, "pause chan:%d\n", ch_id);
+
+	spin_lock_irqsave(&fchan->vchan.lock, flags);
+	if (fchan->fdesc)
+		fdma_write(fchan->fdev, cmd, FDMA_CMD_SET_OFST);
+	spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+
+	return 0;
+}
+
+static int st_fdma_resume(struct dma_chan *chan)
+{
+	unsigned long flags;
+	unsigned long val;
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	int ch_id = fchan->vchan.chan.chan_id;
+
+	dev_dbg(fchan->fdev->dev, "resume chan:%d\n", ch_id);
+
+	spin_lock_irqsave(&fchan->vchan.lock, flags);
+	if (fchan->fdesc) {
+		val = fchan_read(fchan, FDMA_CH_CMD_OFST);
+		val &= FDMA_CH_CMD_DATA_MASK;
+		fchan_write(fchan, val, FDMA_CH_CMD_OFST);
+	}
+	spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+
+	return 0;
+}
+
+static int st_fdma_terminate_all(struct dma_chan *chan)
+{
+	unsigned long flags;
+	LIST_HEAD(head);
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	int ch_id = fchan->vchan.chan.chan_id;
+	unsigned long cmd = FDMA_CMD_PAUSE(ch_id);
+
+	dev_dbg(fchan->fdev->dev, "terminate chan:%d\n", ch_id);
+
+	spin_lock_irqsave(&fchan->vchan.lock, flags);
+	fdma_write(fchan->fdev, cmd, FDMA_CMD_SET_OFST);
+	fchan->fdesc = NULL;
+	vchan_get_all_descriptors(&fchan->vchan, &head);
+	spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+	vchan_dma_desc_free_list(&fchan->vchan, &head);
+
+	return 0;
+}
+
+static int st_fdma_slave_config(struct dma_chan *chan,
+				struct dma_slave_config *slave_cfg)
+{
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+
+	memcpy(&fchan->scfg, slave_cfg, sizeof(fchan->scfg));
+	return 0;
+}
+
+static const struct st_fdma_driverdata fdma_mpe31_stih407_11 = {
+	.name = "STiH407",
+	.id = 0,
+};
+
+static const struct st_fdma_driverdata fdma_mpe31_stih407_12 = {
+	.name = "STiH407",
+	.id = 1,
+};
+
+static const struct st_fdma_driverdata fdma_mpe31_stih407_13 = {
+	.name = "STiH407",
+	.id = 2,
+};
+
+static const struct of_device_id st_fdma_match[] = {
+	{ .compatible = "st,stih407-fdma-mpe31-11"
+	  , .data = &fdma_mpe31_stih407_11 },
+	{ .compatible = "st,stih407-fdma-mpe31-12"
+	  , .data = &fdma_mpe31_stih407_12 },
+	{ .compatible = "st,stih407-fdma-mpe31-13"
+	  , .data = &fdma_mpe31_stih407_13 },
+	{},
+};
+MODULE_DEVICE_TABLE(of, st_fdma_match);
+
+static int st_fdma_parse_dt(struct platform_device *pdev,
+			const struct st_fdma_driverdata *drvdata,
+			struct st_fdma_dev *fdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int ret;
+
+	if (!np)
+		goto err;
+
+	ret = of_property_read_u32(np, "dma-channels", &fdev->nr_channels);
+	if (ret)
+		goto err;
+
+	snprintf(fdev->fw_name, FW_NAME_SIZE, "fdma_%s_%d.elf",
+		drvdata->name, drvdata->id);
+
+err:
+	return ret;
+}
+#define FDMA_DMA_BUSWIDTHS	(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
+				 BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+				 BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
+				 BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
+
+static int st_fdma_probe(struct platform_device *pdev)
+{
+	struct st_fdma_dev *fdev;
+	const struct of_device_id *match;
+	struct device_node *np = pdev->dev.of_node;
+	const struct st_fdma_driverdata *drvdata;
+	int ret, i;
+
+	match = of_match_device((st_fdma_match), &pdev->dev);
+	if (!match || !match->data) {
+		dev_err(&pdev->dev, "No device match found\n");
+		return -ENODEV;
+	}
+
+	drvdata = match->data;
+
+	fdev = devm_kzalloc(&pdev->dev, sizeof(*fdev), GFP_KERNEL);
+	if (!fdev)
+		return -ENOMEM;
+
+	ret = st_fdma_parse_dt(pdev, drvdata, fdev);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to find platform data\n");
+		goto err;
+	}
+
+	fdev->chans = devm_kzalloc(&pdev->dev,
+				   fdev->nr_channels
+				   * sizeof(struct st_fdma_chan), GFP_KERNEL);
+	if (!fdev->chans)
+		return -ENOMEM;
+
+	fdev->dev = &pdev->dev;
+	fdev->drvdata = drvdata;
+	platform_set_drvdata(pdev, fdev);
+
+	fdev->irq = platform_get_irq(pdev, 0);
+	if (fdev->irq < 0) {
+		dev_err(&pdev->dev, "Failed to get irq resource\n");
+		return -EINVAL;
+	}
+
+	ret = devm_request_irq(&pdev->dev, fdev->irq, st_fdma_irq_handler, 0,
+			       dev_name(&pdev->dev), fdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq\n");
+		goto err;
+	}
+
+	fdev->rproc = xp70_rproc_alloc(pdev, fdev->fw_name);
+	if (!fdev->rproc) {
+		dev_err(&pdev->dev, "xp70_rproc_init failed\n");
+		ret = PTR_ERR(fdev->rproc);
+		goto err;
+	}
+
+	fdev->xp70_rproc = fdev->rproc->priv;
+
+	/* Initialise list of FDMA channels */
+	INIT_LIST_HEAD(&fdev->dma_device.channels);
+	for (i = 0; i < fdev->nr_channels; i++) {
+		struct st_fdma_chan *fchan = &fdev->chans[i];
+
+		fchan->fdev = fdev;
+		fchan->vchan.desc_free = st_fdma_free_desc;
+		vchan_init(&fchan->vchan, &fdev->dma_device);
+	}
+
+	/* Initialise the FDMA dreq (reserve 0 & 31 for FDMA use) */
+	fdev->dreq_mask = BIT(0) | BIT(31);
+
+	dma_cap_set(DMA_SLAVE, fdev->dma_device.cap_mask);
+	dma_cap_set(DMA_CYCLIC, fdev->dma_device.cap_mask);
+	dma_cap_set(DMA_MEMCPY, fdev->dma_device.cap_mask);
+
+	fdev->dma_device.dev = &pdev->dev;
+	fdev->dma_device.device_alloc_chan_resources = st_fdma_alloc_chan_res;
+	fdev->dma_device.device_free_chan_resources = st_fdma_free_chan_res;
+	fdev->dma_device.device_prep_dma_cyclic	= st_fdma_prep_dma_cyclic;
+	fdev->dma_device.device_prep_slave_sg = st_fdma_prep_slave_sg;
+	fdev->dma_device.device_prep_dma_memcpy = st_fdma_prep_dma_memcpy;
+	fdev->dma_device.device_tx_status = st_fdma_tx_status;
+	fdev->dma_device.device_issue_pending = st_fdma_issue_pending;
+	fdev->dma_device.device_terminate_all = st_fdma_terminate_all;
+	fdev->dma_device.device_config = st_fdma_slave_config;
+	fdev->dma_device.device_pause = st_fdma_pause;
+	fdev->dma_device.device_resume = st_fdma_resume;
+
+	fdev->dma_device.src_addr_widths = FDMA_DMA_BUSWIDTHS;
+	fdev->dma_device.dst_addr_widths = FDMA_DMA_BUSWIDTHS;
+	fdev->dma_device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+	fdev->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+
+	ret = dma_async_device_register(&fdev->dma_device);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register DMA device\n");
+		goto err_rproc;
+	}
+
+	ret = of_dma_controller_register(np, st_fdma_of_xlate, fdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register controller\n");
+		goto err_dma_dev;
+	}
+
+	dev_info(&pdev->dev, "ST FDMA engine driver, irq:%d\n", fdev->irq);
+
+	return 0;
+
+err_dma_dev:
+	dma_async_device_unregister(&fdev->dma_device);
+err_rproc:
+	xp70_rproc_put(fdev->xp70_rproc);
+err:
+	return ret;
+}
+
+static int st_fdma_remove(struct platform_device *pdev)
+{
+	struct st_fdma_dev *fdev = platform_get_drvdata(pdev);
+
+	devm_free_irq(&pdev->dev, fdev->irq, fdev);
+	xp70_rproc_put(fdev->xp70_rproc);
+	of_dma_controller_free(pdev->dev.of_node);
+	dma_async_device_unregister(&fdev->dma_device);
+
+	return 0;
+}
+
+static struct platform_driver st_fdma_platform_driver = {
+	.driver = {
+		.name = "st-fdma",
+		.of_match_table = st_fdma_match,
+	},
+	.probe = st_fdma_probe,
+	.remove = st_fdma_remove,
+};
+module_platform_driver(st_fdma_platform_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("STMicroelectronics FDMA engine driver");
+MODULE_AUTHOR("Ludovic.barre <Ludovic.barre at st.com>");
+MODULE_AUTHOR("Peter Griffin <peter.griffin at linaro.org>");
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:39 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:39 +0100
Subject: [PATCH v4 05/18] dmaengine: st_fdma: Add STMicroelectronics FDMA
 driver header file
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-7-git-send-email-peter.griffin@linaro.org>

This header file will also be used by the dma xbar driver in the
future.

Signed-off-by: Ludovic Barre <ludovic.barre at st.com>
Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 drivers/dma/st_fdma.h | 243 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 243 insertions(+)
 create mode 100644 drivers/dma/st_fdma.h

diff --git a/drivers/dma/st_fdma.h b/drivers/dma/st_fdma.h
new file mode 100644
index 0000000..6921d21
--- /dev/null
+++ b/drivers/dma/st_fdma.h
@@ -0,0 +1,243 @@
+/*
+ * st_fdma.h
+ *
+ * Copyright (C) 2014 STMicroelectronics
+ * Author: Ludovic Barre <Ludovic.barre at st.com>
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+#ifndef __DMA_ST_FDMA_H
+#define __DMA_ST_FDMA_H
+
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+#include <linux/remoteproc/st_xp70_rproc.h>
+
+#include "virt-dma.h"
+
+#define ST_FDMA_NR_DREQS 32
+
+#define FW_NAME_SIZE 30
+
+/**
+ * struct st_fdma_generic_node - Free running/paced generic node
+ *
+ * @length: Length in bytes of a line in a 2D mem to mem
+ * @sstride: Stride, in bytes, between source lines in a 2D data move
+ * @dstride: Stride, in bytes, between destination lines in a 2D data move
+ */
+struct st_fdma_generic_node {
+	u32 length;
+	u32 sstride;
+	u32 dstride;
+};
+
+/**
+ * struct st_fdma_hw_node - Node structure used by fdma hw
+ *
+ * @next: Pointer to next node
+ * @control: Transfer Control Parameters
+ * @nbytes: Number of Bytes to read
+ * @saddr: Source address
+ * @daddr: Destination address
+ *
+ * @generic: generic node for free running/paced transfert type
+ * 2 others transfert type are possible, but not yet implemented
+ *
+ * The NODE structures must be aligned to a 32 byte boundary
+ */
+struct st_fdma_hw_node {
+	u32 next;
+	u32 control;
+	u32 nbytes;
+	u32 saddr;
+	u32 daddr;
+	union {
+		struct st_fdma_generic_node generic;
+	};
+} __aligned(32);
+
+/*
+ * node control parameters
+ */
+#define NODE_CTRL_REQ_MAP_MASK		GENMASK(4, 0)
+#define NODE_CTRL_REQ_MAP_FREE_RUN	0x0
+#define NODE_CTRL_REQ_MAP_DREQ(n)	((n) & NODE_CTRL_REQ_MAP_MASK)
+#define NODE_CTRL_REQ_MAP_EXT		NODE_CTRL_REQ_MAP_MASK
+#define NODE_CTRL_SRC_MASK		GENMASK(6, 5)
+#define NODE_CTRL_SRC_STATIC		BIT(5)
+#define NODE_CTRL_SRC_INCR		BIT(6)
+#define NODE_CTRL_DST_MASK		GENMASK(8, 7)
+#define NODE_CTRL_DST_STATIC		BIT(7)
+#define NODE_CTRL_DST_INCR		BIT(8)
+#define NODE_CTRL_SECURE		BIT(15)
+#define NODE_CTRL_PAUSE_EON		BIT(30)
+#define NODE_CTRL_INT_EON		BIT(31)
+
+/**
+ * struct st_fdma_sw_node - descriptor structure for link list
+ *
+ * @pdesc: Physical address of desc
+ * @node: link used for putting this into a channel queue
+ */
+struct st_fdma_sw_node {
+	dma_addr_t pdesc;
+	struct st_fdma_hw_node *desc;
+};
+
+#define NAME_SZ 10
+
+struct st_fdma_driverdata {
+	u32 id;
+	char name[NAME_SZ];
+};
+
+struct st_fdma_desc {
+	struct virt_dma_desc vdesc;
+	struct st_fdma_chan *fchan;
+	bool iscyclic;
+	unsigned int n_nodes;
+	struct st_fdma_sw_node node[];
+};
+
+enum st_fdma_type {
+	ST_FDMA_TYPE_FREE_RUN,
+	ST_FDMA_TYPE_PACED,
+};
+
+struct st_fdma_cfg {
+	struct device_node *of_node;
+	enum st_fdma_type type;
+	dma_addr_t dev_addr;
+	enum dma_transfer_direction dir;
+	int req_line; /* request line */
+	long req_ctrl; /* Request control */
+};
+
+struct st_fdma_chan {
+	struct st_fdma_dev *fdev;
+	struct dma_pool *node_pool;
+	struct dma_slave_config scfg;
+	struct st_fdma_cfg cfg;
+
+	int dreq_line;
+
+	struct virt_dma_chan vchan;
+	struct st_fdma_desc *fdesc;
+	enum dma_status	status;
+};
+
+struct st_fdma_dev {
+	struct device *dev;
+	const struct st_fdma_driverdata *drvdata;
+	struct dma_device dma_device;
+
+	struct st_xp70_rproc *xp70_rproc;
+
+	int irq;
+
+	struct st_fdma_chan *chans;
+
+	spinlock_t dreq_lock;
+	unsigned long dreq_mask;
+
+	u32 nr_channels;
+	char fw_name[FW_NAME_SIZE];
+
+	struct rproc *rproc;
+};
+
+/* Peripheral Registers*/
+
+#define FDMA_CMD_STA_OFST	0xFC0
+#define FDMA_CMD_SET_OFST	0xFC4
+#define FDMA_CMD_CLR_OFST	0xFC8
+#define FDMA_CMD_MASK_OFST	0xFCC
+#define FDMA_CMD_START(ch)		(0x1 << (ch << 1))
+#define FDMA_CMD_PAUSE(ch)		(0x2 << (ch << 1))
+#define FDMA_CMD_FLUSH(ch)		(0x3 << (ch << 1))
+
+#define FDMA_INT_STA_OFST	0xFD0
+#define FDMA_INT_STA_CH			0x1
+#define FDMA_INT_STA_ERR		0x2
+
+#define FDMA_INT_SET_OFST	0xFD4
+#define FDMA_INT_CLR_OFST	0xFD8
+#define FDMA_INT_MASK_OFST	0xFDC
+
+#define fdma_read(fdev, name) \
+	readl_relaxed((fdev)->xp70_rproc->peri + name)
+
+#define fdma_write(fdev, val, name) \
+	writel_relaxed((val), (fdev)->xp70_rproc->peri + name)
+
+/* fchan interface (dmem)*/
+#define FDMA_CH_CMD_OFST	0x200
+#define FDMA_CH_CMD_STA_MASK		GENMASK(1, 0)
+#define FDMA_CH_CMD_STA_IDLE		(0x0)
+#define FDMA_CH_CMD_STA_START		(0x1)
+#define FDMA_CH_CMD_STA_RUNNING		(0x2)
+#define FDMA_CH_CMD_STA_PAUSED		(0x3)
+#define FDMA_CH_CMD_ERR_MASK		GENMASK(4, 2)
+#define FDMA_CH_CMD_ERR_INT		(0x0 << 2)
+#define FDMA_CH_CMD_ERR_NAND		(0x1 << 2)
+#define FDMA_CH_CMD_ERR_MCHI		(0x2 << 2)
+#define FDMA_CH_CMD_DATA_MASK		GENMASK(31, 5)
+#define fchan_read(fchan, name) \
+	readl_relaxed((fchan)->fdev->xp70_rproc->mem[DMEM].cpu_addr \
+			+ (fchan)->vchan.chan.chan_id * 0x4 \
+			+ name)
+
+#define fchan_write(fchan, val, name) \
+	writel_relaxed((val), (fchan)->fdev->xp70_rproc->mem[DMEM].cpu_addr \
+			+ (fchan)->vchan.chan.chan_id * 0x4 \
+			+ name)
+
+/* req interface */
+#define FDMA_REQ_CTRL_OFST	0x240
+#define dreq_write(fchan, val, name) \
+	writel_relaxed((val), (fchan)->fdev->xp70_rproc->mem[DMEM].cpu_addr \
+			+ fchan->dreq_line * 0x04 \
+			+ name)
+/* node interface */
+#define FDMA_NODE_SZ 128
+#define FDMA_PTRN_OFST		0x800
+#define FDMA_CNTN_OFST		0x808
+#define FDMA_SADDRN_OFST	0x80c
+#define FDMA_DADDRN_OFST	0x810
+#define fnode_read(fchan, name) \
+	readl_relaxed((fchan)->fdev->xp70_rproc->mem[DMEM].cpu_addr \
+			+ (fchan)->vchan.chan.chan_id * FDMA_NODE_SZ \
+			+ name)
+
+#define fnode_write(fchan, val, name) \
+	writel_relaxed((val), (fchan)->fdev->xp70_rproc->mem[DMEM].cpu_addr \
+			+ (fchan)->vchan.chan.chan_id * FDMA_NODE_SZ \
+			+ name)
+
+/*
+ * request control bits
+ */
+#define REQ_CTRL_NUM_OPS_MASK		GENMASK(31, 24)
+#define REQ_CTRL_NUM_OPS(n)		(REQ_CTRL_NUM_OPS_MASK & ((n) << 24))
+#define REQ_CTRL_INITIATOR_MASK		BIT(22)
+#define	REQ_CTRL_INIT0			(0x0 << 22)
+#define	REQ_CTRL_INIT1			(0x1 << 22)
+#define REQ_CTRL_INC_ADDR_ON		BIT(21)
+#define REQ_CTRL_DATA_SWAP_ON		BIT(17)
+#define REQ_CTRL_WNR			BIT(14)
+#define REQ_CTRL_OPCODE_MASK		GENMASK(7, 4)
+#define REQ_CTRL_OPCODE_LD_ST1		(0x0 << 4)
+#define REQ_CTRL_OPCODE_LD_ST2		(0x1 << 4)
+#define REQ_CTRL_OPCODE_LD_ST4		(0x2 << 4)
+#define REQ_CTRL_OPCODE_LD_ST8		(0x3 << 4)
+#define REQ_CTRL_OPCODE_LD_ST16		(0x4 << 4)
+#define REQ_CTRL_OPCODE_LD_ST32		(0x5 << 4)
+#define REQ_CTRL_OPCODE_LD_ST64		(0x6 << 4)
+#define REQ_CTRL_HOLDOFF_MASK		GENMASK(2, 0)
+#define REQ_CTRL_HOLDOFF(n)		((n) & REQ_CTRL_HOLDOFF_MASK)
+
+/* bits used by client to configure request control */
+#define REQ_CTRL_CFG_MASK (REQ_CTRL_HOLDOFF_MASK | REQ_CTRL_DATA_SWAP_ON \
+			| REQ_CTRL_INC_ADDR_ON | REQ_CTRL_INITIATOR_MASK)
+
+#endif	/* __DMA_ST_FDMA_H */
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:41 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:41 +0100
Subject: [PATCH v4 07/18] ARM: STi: DT: STiH407: Add FDMA driver dt nodes.
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-9-git-send-email-peter.griffin@linaro.org>

These nodes are required to get the fdma driver working
on STiH407 based silicon.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 arch/arm/boot/dts/stih407-family.dtsi | 52 +++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
index 81f8121..b423836 100644
--- a/arch/arm/boot/dts/stih407-family.dtsi
+++ b/arch/arm/boot/dts/stih407-family.dtsi
@@ -694,5 +694,57 @@
 			clocks          = <&clk_sysin>;
 			status		= "okay";
 		};
+
+		/* fdma audio */
+		fdma0: dma-controller at 8e20000 {
+			compatible = "st,stih407-fdma-mpe31-11", "st,xp70-rproc";
+			reg = <0x8e20000 0x8000>,
+			      <0x8e30000 0x3000>,
+			      <0x8e37000 0x1000>,
+			      <0x8e38000 0x8000>;
+			reg-names = "slimcore", "dmem", "peripherals", "imem";
+			clocks = <&clk_s_c0_flexgen CLK_FDMA>,
+				 <&clk_s_c0_flexgen CLK_EXT2F_A9>,
+				 <&clk_s_c0_flexgen CLK_EXT2F_A9>,
+				 <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_NONE>;
+			dma-channels = <16>;
+			#dma-cells = <3>;
+		};
+
+		/* fdma app */
+		fdma1: dma-controller at 8e40000 {
+			compatible = "st,stih407-fdma-mpe31-12", "st,xp70-rproc";
+			reg = <0x8e40000 0x8000>,
+			      <0x8e50000 0x3000>,
+			      <0x8e57000 0x1000>,
+			      <0x8e58000 0x8000>;
+			reg-names = "slimcore", "dmem", "peripherals", "imem";
+			clocks = <&clk_s_c0_flexgen CLK_FDMA>,
+				<&clk_s_c0_flexgen CLK_TX_ICN_DMU>,
+				<&clk_s_c0_flexgen CLK_TX_ICN_DMU>,
+				<&clk_s_c0_flexgen CLK_EXT2F_A9>;
+
+			interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>;
+			dma-channels = <16>;
+			#dma-cells = <3>;
+		};
+
+		/* fdma free running */
+		fdma2: dma-controller at 8e60000 {
+			compatible = "st,stih407-fdma-mpe31-13", "st,xp70-rproc";
+			reg = <0x8e60000 0x8000>,
+			      <0x8e70000 0x3000>,
+			      <0x8e77000 0x1000>,
+			      <0x8e78000 0x8000>;
+			reg-names = "slimcore", "dmem", "peripherals", "imem";
+			interrupts = <GIC_SPI 9 IRQ_TYPE_NONE>;
+			dma-channels = <16>;
+			#dma-cells = <3>;
+			clocks = <&clk_s_c0_flexgen CLK_FDMA>,
+				<&clk_s_c0_flexgen CLK_EXT2F_A9>,
+				<&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
+				<&clk_s_c0_flexgen CLK_EXT2F_A9>;
+		};
 	};
 };
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:42 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:42 +0100
Subject: [PATCH v4 08/18] MAINTAINERS: Add FDMA driver files to STi section.
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-10-git-send-email-peter.griffin@linaro.org>

This patch adds the FDMA driver files to the STi
section of the maintainers file.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
Acked-by: Lee Jones <lee.jones at linaro.org>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index de99aec..627a2e0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1638,6 +1638,7 @@ F:	arch/arm/boot/dts/sti*
 F:	drivers/char/hw_random/st-rng.c
 F:	drivers/clocksource/arm_global_timer.c
 F:	drivers/clocksource/clksrc_st_lpc.c
+F:	drivers/dma/st_fdma*
 F:	drivers/i2c/busses/i2c-st.c
 F:	drivers/media/rc/st_rc.c
 F:	drivers/media/platform/sti/c8sectpfe/
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:43 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:43 +0100
Subject: [PATCH v4 09/18] ARM: multi_v7_defconfig: Enable STi FDMA driver
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-11-git-send-email-peter.griffin@linaro.org>

This DMA controller is found on all STi chipsets.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
Acked-by: Lee Jones <lee.jones at linaro.org>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index d319d8f..5eee45b 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -728,6 +728,7 @@ CONFIG_DMA_OMAP=y
 CONFIG_QCOM_BAM_DMA=y
 CONFIG_XILINX_VDMA=y
 CONFIG_DMA_SUN6I=y
+CONFIG_ST_FDMA=m
 CONFIG_STAGING=y
 CONFIG_SENSORS_ISL29018=y
 CONFIG_SENSORS_ISL29028=y
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:44 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:44 +0100
Subject: [PATCH v4 10/18] ASoC: sti: Update DT example to match the driver code
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-12-git-send-email-peter.griffin@linaro.org>

uniperiph-id, version and mode are ST specific bindings and
need the 'st,' prefix. Update the examples, as otherwise copying
them yields a runtime error parsing the DT node.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
Cc: arnaud.pouliquen at st.com
Cc: broonie at kernel.org
---
 .../devicetree/bindings/sound/st,sti-asoc-card.txt   | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt b/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt
index 028fa1c..fe1b72c 100644
--- a/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt
+++ b/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt
@@ -33,7 +33,7 @@ Required properties:
 	"tx" for "st,sti-uni-player" compatibility
 	"rx" for "st,sti-uni-reader" compatibility
 
-  - version: IP version integrated in SOC.
+  - st,version: IP version integrated in SOC.
 
   - dai-name: DAI name that describes the IP.
 
@@ -41,9 +41,9 @@ Required properties ("st,sti-uni-player" compatibility only):
   - clocks: CPU_DAI IP clock source, listed in the same order than the
 	    CPU_DAI properties.
 
-  - uniperiph-id: internal SOC IP instance ID.
+  - st,uniperiph-id: internal SOC IP instance ID.
 
-  - IP mode: IP working mode depending on associated codec.
+  - st,mode: IP working mode depending on associated codec.
 	"HDMI" connected to HDMI codec IP and IEC HDMI formats.
 	"SPDIF"connected to SPDIF codec and support SPDIF formats.
 	"PCM"  PCM standard mode for I2S or TDM bus.
@@ -67,9 +67,9 @@ Example:
 		dmas = <&fdma0 4 0 1>;
 		dai-name = "Uni Player #1 (DAC)";
 		dma-names = "tx";
-		uniperiph-id = <2>;
-		version = <5>;
-		mode = "PCM";
+		st,uniperiph-id = <2>;
+		st,version = <5>;
+		st,mode = "PCM";
 	};
 
 	sti_uni_player3: sti-uni-player at 3 {
@@ -83,9 +83,9 @@ Example:
 		dmas = <&fdma0 7 0 1>;
 		dma-names = "tx";
 		dai-name = "Uni Player #1 (PIO)";
-		uniperiph-id = <3>;
-		version = <5>;
-		mode = "SPDIF";
+		st,uniperiph-id = <3>;
+		st,version = <5>;
+		st,mode = "SPDIF";
 	};
 
 	sti_uni_reader1: sti-uni-reader at 1 {
@@ -98,7 +98,7 @@ Example:
 		dmas = <&fdma0 6 0 1>;
 		dma-names = "rx";
 		dai-name = "Uni Reader #1 (HDMI RX)";
-		version = <3>;
+		st,version = <3>;
 	};
 
 2) sti-sas-codec: internal audio codec IPs driver
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:46 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:46 +0100
Subject: [PATCH v4 12/18] ARM: DT: STiH407: Add i2s_out pinctrl configuration
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-14-git-send-email-peter.griffin@linaro.org>

This patch adds the pinctrl config for the i2s_out pins
used by the uniperif player IP.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 arch/arm/boot/dts/stih407-pinctrl.dtsi | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm/boot/dts/stih407-pinctrl.dtsi b/arch/arm/boot/dts/stih407-pinctrl.dtsi
index a538ae5..0fb5c8a 100644
--- a/arch/arm/boot/dts/stih407-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stih407-pinctrl.dtsi
@@ -1067,6 +1067,29 @@
 				};
 			};
 
+			i2s_out {
+				pinctrl_i2s_8ch_out: i2s_8ch_out{
+					st,pins {
+						mclk = <&pio33 5 ALT1 OUT>;
+						lrclk = <&pio33 7 ALT1 OUT>;
+						sclk = <&pio33 6 ALT1 OUT>;
+						data0 = <&pio33 4 ALT1 OUT>;
+						data1 = <&pio34 0 ALT1 OUT>;
+						data2 = <&pio34 1 ALT1 OUT>;
+						data3 = <&pio34 2 ALT1 OUT>;
+					};
+				};
+
+				pinctrl_i2s_2ch_out: i2s_2ch_out{
+					st,pins {
+						mclk = <&pio33 5 ALT1 OUT>;
+						lrclk = <&pio33 7 ALT1 OUT>;
+						sclk = <&pio33 6 ALT1 OUT>;
+						data0 = <&pio33 4 ALT1 OUT>;
+					};
+				};
+			};
+
 			serial3 {
 				pinctrl_serial3: serial3-0 {
 					st,pins {
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:45 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:45 +0100
Subject: [PATCH v4 11/18] ARM: multi_v7_defconfig: Enable STi and simple-card
 drivers.
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-13-git-send-email-peter.griffin@linaro.org>

This patch enables the STi ALSA drivers found on STi platforms
as well as the simple-card driver which is a dependency to have
working sound.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
Cc: arnaud.pouliquen at st.com
Cc: broonie at kernel.org
---
 arch/arm/configs/multi_v7_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 5eee45b..0ced665 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -589,6 +589,9 @@ CONFIG_SND_SOC_AK4642=m
 CONFIG_SND_SOC_SGTL5000=m
 CONFIG_SND_SOC_SPDIF=m
 CONFIG_SND_SOC_WM8978=m
+CONFIG_SND_SOC_STI=m
+CONFIG_SND_SOC_STI_SAS=m
+CONFIG_SND_SIMPLE_CARD=m
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_MVEBU=y
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:47 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:47 +0100
Subject: [PATCH v4 13/18] ARM: DT: STiH407: Add i2s_in pinctrl configuration
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-15-git-send-email-peter.griffin@linaro.org>

This patch adds the pinctrl config for the i2s_in pins
used by the uniperif reader IP.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 arch/arm/boot/dts/stih407-pinctrl.dtsi | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/boot/dts/stih407-pinctrl.dtsi b/arch/arm/boot/dts/stih407-pinctrl.dtsi
index 0fb5c8a..537db7e 100644
--- a/arch/arm/boot/dts/stih407-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stih407-pinctrl.dtsi
@@ -1090,6 +1090,30 @@
 				};
 			};
 
+			i2s_in {
+				pinctrl_i2s_8ch_in: i2s_8ch_in{
+					st,pins {
+						mclk = <&pio32 5 ALT1 IN>;
+						lrclk = <&pio32 7 ALT1 IN>;
+						sclk = <&pio32 6 ALT1 IN>;
+						data0 = <&pio32 4 ALT1 IN>;
+						data1 = <&pio33 0 ALT1 IN>;
+						data2 = <&pio33 1 ALT1 IN>;
+						data3 = <&pio33 2 ALT1 IN>;
+						data4 = <&pio33 3 ALT1 IN>;
+					};
+				};
+
+				pinctrl_i2s_2ch_in: i2s_2ch_in{
+					st,pins {
+						mclk = <&pio32 5 ALT1 IN>;
+						lrclk = <&pio32 7 ALT1 IN>;
+						sclk = <&pio32 6 ALT1 IN>;
+						data0 = <&pio32 4 ALT1 IN>;
+					};
+				};
+			};
+
 			serial3 {
 				pinctrl_serial3: serial3-0 {
 					st,pins {
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:48 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:48 +0100
Subject: [PATCH v4 14/18] ARM: DT: STiH407: Add spdif_out pinctrl config
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-16-git-send-email-peter.griffin@linaro.org>

This patch adds the pinctrl config for the spidf out
pins used by the sasg codec IP.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 arch/arm/boot/dts/stih407-pinctrl.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/stih407-pinctrl.dtsi b/arch/arm/boot/dts/stih407-pinctrl.dtsi
index 537db7e..598dbab 100644
--- a/arch/arm/boot/dts/stih407-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stih407-pinctrl.dtsi
@@ -1114,6 +1114,14 @@
 				};
 			};
 
+			spdif_out {
+				pinctrl_spdif_out: spdif_out{
+					st,pins {
+						spdif_out = <&pio34 7 ALT1 OUT>;
+					};
+				};
+			};
+
 			serial3 {
 				pinctrl_serial3: serial3-0 {
 					st,pins {
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:49 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:49 +0100
Subject: [PATCH v4 15/18] ARM: STi: DT: STiH407: Add sti-sasg-codec dt node
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-17-git-send-email-peter.griffin@linaro.org>

This patch adds the dt node for the internal audio
codec IP.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 arch/arm/boot/dts/stih407-family.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
index b423836..60f95b6 100644
--- a/arch/arm/boot/dts/stih407-family.dtsi
+++ b/arch/arm/boot/dts/stih407-family.dtsi
@@ -746,5 +746,14 @@
 				<&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
 				<&clk_s_c0_flexgen CLK_EXT2F_A9>;
 		};
+
+		sti_sasg_codec: sti-sasg-codec {
+			compatible = "st,stih407-sas-codec";
+			#sound-dai-cells = <1>;
+			status = "okay";
+			st,syscfg = <&syscfg_core>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_spdif_out >;
+		};
 	};
 };
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:51 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:51 +0100
Subject: [PATCH v4 17/18] ARM: STi: DT: STiH407: Add uniperif reader dt nodes
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-19-git-send-email-peter.griffin@linaro.org>

This patch adds the DT node for the uniperif reader
IP block found on STiH407 family silicon.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 arch/arm/boot/dts/stih407-family.dtsi | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
index 7ca149b..fb6363e1 100644
--- a/arch/arm/boot/dts/stih407-family.dtsi
+++ b/arch/arm/boot/dts/stih407-family.dtsi
@@ -831,5 +831,33 @@
 			st,version = <5>;
 			st,mode = "SPDIF";
 		};
+
+		sti_uni_reader0: sti-uni-reader at 0 {
+			compatible = "st,sti-uni-reader";
+			status = "disabled";
+			#sound-dai-cells = <0>;
+			st,syscfg = <&syscfg_core>;
+			reg = <0x8D83000 0x158>;
+			interrupts = <GIC_SPI 87 IRQ_TYPE_NONE>;
+			dmas = <&fdma0 5 0 1>;
+			dma-names = "rx";
+			dai-name = "Uni Reader #0 (PCM IN)";
+			st,version = <3>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2s_8ch_in>;
+		};
+
+		sti_uni_reader1: sti-uni-reader at 1 {
+			compatible = "st,sti-uni-reader";
+			status = "disabled";
+			#sound-dai-cells = <0>;
+			st,syscfg = <&syscfg_core>;
+			reg = <0x8D84000 0x158>;
+			interrupts = <GIC_SPI 88 IRQ_TYPE_NONE>;
+			dmas = <&fdma0 6 0 1>;
+			dma-names = "rx";
+			dai-name = "Uni Reader #1 (HDMI RX)";
+			st,version = <3>;
+		};
 	};
 };
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:50 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:50 +0100
Subject: [PATCH v4 16/18] ARM: STi: DT: STiH407: Add uniperif player dt nodes
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-18-git-send-email-peter.griffin@linaro.org>

This patch adds the DT nodes for the uniperif player
IP blocks found on STiH407 family silicon.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 arch/arm/boot/dts/stih407-family.dtsi | 76 +++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
index 60f95b6..7ca149b 100644
--- a/arch/arm/boot/dts/stih407-family.dtsi
+++ b/arch/arm/boot/dts/stih407-family.dtsi
@@ -755,5 +755,81 @@
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_spdif_out >;
 		};
+
+		sti_uni_player0: sti-uni-player at 0 {
+			compatible = "st,sti-uni-player";
+			status = "disabled";
+			#sound-dai-cells = <0>;
+			st,syscfg = <&syscfg_core>;
+			clocks = <&clk_s_d0_flexgen CLK_PCM_0>;
+			assigned-clocks = <&clk_s_d0_flexgen CLK_PCM_0>;
+			assigned-clock-parents = <&clk_s_d0_quadfs 0>;
+			assigned-clock-rates = <50000000>;
+			reg = <0x8D80000 0x158>;
+			interrupts = <GIC_SPI 84 IRQ_TYPE_NONE>;
+			dmas = <&fdma0 2 0 1>;
+			dai-name = "Uni Player #0 (HDMI)";
+			dma-names = "tx";
+			st,uniperiph-id = <0>;
+			st,version = <5>;
+			st,mode = "HDMI";
+		};
+
+		sti_uni_player1: sti-uni-player at 1 {
+			compatible = "st,sti-uni-player";
+			status = "disabled";
+			#sound-dai-cells = <0>;
+			st,syscfg = <&syscfg_core>;
+			clocks = <&clk_s_d0_flexgen CLK_PCM_1>;
+			assigned-clocks = <&clk_s_d0_flexgen CLK_PCM_1>;
+			assigned-clock-parents = <&clk_s_d0_quadfs 1>;
+			assigned-clock-rates = <50000000>;
+			reg = <0x8D81000 0x158>;
+			interrupts = <GIC_SPI 85 IRQ_TYPE_NONE>;
+			dmas = <&fdma0 3 0 1>;
+			dai-name = "Uni Player #1 (PIO)";
+			dma-names = "tx";
+			st,uniperiph-id = <1>;
+			st,version = <5>;
+			st,mode = "PCM";
+		};
+
+		sti_uni_player2: sti-uni-player at 2 {
+			compatible = "st,sti-uni-player";
+			status = "disabled";
+			#sound-dai-cells = <0>;
+			st,syscfg = <&syscfg_core>;
+			clocks = <&clk_s_d0_flexgen CLK_PCM_2>;
+			assigned-clocks = <&clk_s_d0_flexgen CLK_PCM_2>;
+			assigned-clock-parents = <&clk_s_d0_quadfs 2>;
+			assigned-clock-rates = <50000000>;
+			reg = <0x8D82000 0x158>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_NONE>;
+			dmas = <&fdma0 4 0 1>;
+			dai-name = "Uni Player #1 (DAC)";
+			dma-names = "tx";
+			st,uniperiph-id = <2>;
+			st,version = <5>;
+			st,mode = "PCM";
+		};
+
+		sti_uni_player3: sti-uni-player at 3 {
+			compatible = "st,sti-uni-player";
+			status = "disabled";
+			#sound-dai-cells = <0>;
+			st,syscfg = <&syscfg_core>;
+			clocks = <&clk_s_d0_flexgen CLK_SPDIFF>;
+			assigned-clocks = <&clk_s_d0_flexgen CLK_SPDIFF>;
+			assigned-clock-parents = <&clk_s_d0_quadfs 3>;
+			assigned-clock-rates = <50000000>;
+			reg = <0x8D85000 0x158>;
+			interrupts = <GIC_SPI 89 IRQ_TYPE_NONE>;
+			dmas = <&fdma0 7 0 1>;
+			dma-names = "tx";
+			dai-name = "Uni Player #1 (PIO)";
+			st,uniperiph-id = <3>;
+			st,version = <5>;
+			st,mode = "SPDIF";
+		};
 	};
 };
-- 
1.9.1



From peter.griffin at linaro.org  Wed May 25 09:06:52 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Wed, 25 May 2016 17:06:52 +0100
Subject: [PATCH v4 18/18] ARM: DT: STi: stihxxx-b2120: Add DT nodes for STi
 audio card
In-Reply-To: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
Message-ID: <1464192412-16386-20-git-send-email-peter.griffin@linaro.org>

This patch enables the uniperif players 2 & 3 for b2120 boards
and also adds the "simple-audio-card" device node to interconnect
the SoC sound device and the codec.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 arch/arm/boot/dts/stihxxx-b2120.dtsi | 40 ++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi b/arch/arm/boot/dts/stihxxx-b2120.dtsi
index 722c63f..5297f21 100644
--- a/arch/arm/boot/dts/stihxxx-b2120.dtsi
+++ b/arch/arm/boot/dts/stihxxx-b2120.dtsi
@@ -131,5 +131,45 @@
 				dvb-card	= <STV0367_TDA18212_NIMA_1>;
 			};
 		};
+
+		sti_uni_player2: sti-uni-player at 2 {
+			status = "okay";
+		};
+
+		sti_uni_player3: sti-uni-player at 3 {
+			status = "okay";
+		};
+
+		sound {
+			compatible = "simple-audio-card";
+			simple-audio-card,name = "sti audio card";
+			status = "okay";
+
+			simple-audio-card,dai-link at 0 {
+				/* DAC */
+				format = "i2s";
+				dai-tdm-slot-width = <32>;
+				mclk-fs = <256>;
+				cpu {
+					sound-dai = <&sti_uni_player2>;
+				};
+
+				codec {
+					sound-dai = <&sti_sasg_codec 1>;
+				};
+			};
+			simple-audio-card,dai-link at 1 {
+				/* SPDIF */
+				format = "left_j";
+				mclk-fs = <128>;
+				cpu {
+					sound-dai = <&sti_uni_player3>;
+				};
+
+				codec {
+					sound-dai = <&sti_sasg_codec 0>;
+				};
+			};
+		};
 	};
 };
-- 
1.9.1



From nm at ti.com  Wed May 25 09:09:50 2016
From: nm at ti.com (Nishanth Menon)
Date: Wed, 25 May 2016 11:09:50 -0500
Subject: [PATCH 0/2] arm: dra7: Add i2c6 instance hwmod and dt entries
In-Reply-To: <20160525125341.10044-1-rk@ti.com>
References: <20160525125341.10044-1-rk@ti.com>
Message-ID: <5745CE4E.3020903@ti.com>

On 05/25/2016 07:53 AM, Ravikumar Kattekola wrote:
> DRA72x devices have a sixth i2c ocntroller instance.
> Following patches add the required hwmod structure and
> device tree nodes.
> 
> Reference doc: DRA72x TRM [ SPRUHP2Q ]
> 
> Tested on :
> DRA72x Rev B EVM
> 
> Ravikumar Kattekola (2):
>   arm: dra7: Add hwmod entry for i2c6
>   dts: dra7: Add device tree node for i2c6
> 
>  arch/arm/boot/dts/dra7.dtsi               | 11 +++++++++++
>  arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 23 +++++++++++++++++++++++
>  2 files changed, 34 insertions(+)
> 
NAK. reasoning:
a) i2c6 is a custom IP integration with completely non-standard
dependencies with cross device dependencies for pretty much a specific
usecase -> usage is pretty much limited for generic support - the
decision is NOT to support this instance in Linux kernel - internal
discussion forwarded to developer.
b) the patches themselves are wrong -> it applies to DRA72x not
generic DRA7x platform
c) patches themselves are in the wrong format (wrong subject line etc).
d) patches don't handle the SoC internal device dependencies either ->
in short will not function in a generic solution for all variations of
platforms.

-- 
Regards,
Nishanth Menon


From nm at ti.com  Wed May 25 09:10:43 2016
From: nm at ti.com (Nishanth Menon)
Date: Wed, 25 May 2016 11:10:43 -0500
Subject: [PATCH 1/2] arm: dra7: Add hwmod entry for i2c6
In-Reply-To: <20160525125341.10044-2-rk@ti.com>
References: <20160525125341.10044-1-rk@ti.com>
 <20160525125341.10044-2-rk@ti.com>
Message-ID: <5745CE83.9010006@ti.com>

On 05/25/2016 07:53 AM, Ravikumar Kattekola wrote:
> dra72x device has i2c6 controller.
> Adding hwmod definition for the same.
> 
> Reference DRA72x TRM [ SPRUHP2Q ]
> 
> Signed-off-by: Ravikumar Kattekola <rk at ti.com>
> ---
>  arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
> index d0e7e525..b84c0f7 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
> @@ -1127,6 +1127,20 @@ static struct omap_hwmod dra7xx_i2c5_hwmod = {
>  	.dev_attr	= &i2c_dev_attr,
>  };
>  
> +/* i2c6 */
> +static struct omap_hwmod dra7xx_i2c6_hwmod = {
> +	.name		= "i2c6",
> +	.class		= &dra7xx_i2c_hwmod_class,
> +	.clkdm_name	= "l4per2_clkdm",
> +	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
> +	.main_clk	= "func_96m_fclk",
> +	.prcm = {
> +		.omap4 = {
> +		},
> +	},
> +	.dev_attr	= &i2c_dev_attr,
> +};
> +
>  /*
>   * 'mailbox' class
>   *
> @@ -3186,6 +3200,14 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per1__i2c5 = {
>  	.user		= OCP_USER_MPU | OCP_USER_SDMA,
>  };
>  
> +/* l4_per2 -> i2c6 */
> +static struct omap_hwmod_ocp_if dra7xx_l4_per2__i2c6 = {
> +	.master		= &dra7xx_l4_per2_hwmod,
> +	.slave		= &dra7xx_i2c6_hwmod,
> +	.clk		= "l3_iclk_div",
> +	.user		= OCP_USER_MPU | OCP_USER_SDMA,
> +};
> +
>  /* l4_cfg -> mailbox1 */
>  static struct omap_hwmod_ocp_if dra7xx_l4_cfg__mailbox1 = {
>  	.master		= &dra7xx_l4_cfg_hwmod,
> @@ -3857,6 +3879,7 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
>  	&dra7xx_l4_per1__i2c3,
>  	&dra7xx_l4_per1__i2c4,
>  	&dra7xx_l4_per1__i2c5,
> +	&dra7xx_l4_per2__i2c6,
>  	&dra7xx_l4_cfg__mailbox1,
>  	&dra7xx_l4_per3__mailbox2,
>  	&dra7xx_l4_per3__mailbox3,
> 

responding to the specific patches themselves:
NAK. reasoning:
a) i2c6 is a custom IP integration with completely non-standard
dependencies with cross device dependencies for pretty much a specific
usecase -> usage is pretty much limited for generic support - the
decision is NOT to support this instance in Linux kernel - internal
discussion forwarded to developer.
b) the patches themselves are wrong -> it applies to DRA72x not
generic DRA7x platform
c) patches themselves are in the wrong format (wrong subject line etc).
d) patches don't handle the SoC internal device dependencies either ->
in short will not function in a generic solution for all variations of
platforms.

-- 
Regards,
Nishanth Menon


From nm at ti.com  Wed May 25 09:11:05 2016
From: nm at ti.com (Nishanth Menon)
Date: Wed, 25 May 2016 11:11:05 -0500
Subject: [PATCH 2/2] dts: dra7: Add device tree node for i2c6
In-Reply-To: <20160525125341.10044-3-rk@ti.com>
References: <20160525125341.10044-1-rk@ti.com>
 <20160525125341.10044-3-rk@ti.com>
Message-ID: <5745CE99.50704@ti.com>

On 05/25/2016 07:53 AM, Ravikumar Kattekola wrote:
> DRA72x devices have an extra i2c controller instance - i2c6
> Adding device description for the same.
> 
> Reference : DRA72x_SR1.0 TRM [ SPRUHP2Q ]
> 
> Signed-off-by: Ravikumar Kattekola <rk at ti.com>
> ---
>  arch/arm/boot/dts/dra7.dtsi | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
> index 3a8f397..84729a1 100644
> --- a/arch/arm/boot/dts/dra7.dtsi
> +++ b/arch/arm/boot/dts/dra7.dtsi
> @@ -27,6 +27,7 @@
>  		i2c2 = &i2c3;
>  		i2c3 = &i2c4;
>  		i2c4 = &i2c5;
> +		i2c5 = &i2c6;
>  		serial0 = &uart1;
>  		serial1 = &uart2;
>  		serial2 = &uart3;
> @@ -929,6 +930,16 @@
>  			status = "disabled";
>  		};
>  
> +		i2c6: i2c at 48458000 {
> +			compatible = "ti,omap4-i2c";
> +			reg = <0x48458000 0x100>;
> +			interrupts = <GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>;
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			ti,hwmods = "i2c6";
> +			status = "disabled";
> +		};
> +
>  		mmc1: mmc at 4809c000 {
>  			compatible = "ti,omap4-hsmmc";
>  			reg = <0x4809c000 0x400>;
> 
NAK again for the same reasoning.

-- 
Regards,
Nishanth Menon


From marc.zyngier at arm.com  Wed May 25 09:16:54 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Wed, 25 May 2016 17:16:54 +0100
Subject: [PATCH v4 01/12] KVM: extend struct kvm_msi to hold a 32-bit
 device ID
In-Reply-To: <e520a5a8-b259-27f3-f33c-f87e008f1c6f@arm.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-2-git-send-email-andre.przywara@arm.com>
 <20160403091508.GA5261@cbox> <e520a5a8-b259-27f3-f33c-f87e008f1c6f@arm.com>
Message-ID: <5745CFF6.6070001@arm.com>

On 25/05/16 16:55, Andre Przywara wrote:
> Hi Christoffer,
> 
> On 03/04/16 10:15, Christoffer Dall wrote:
>> On Sat, Mar 26, 2016 at 02:13:59AM +0000, Andre Przywara wrote:
>>> The ARM GICv3 ITS MSI controller requires a device ID to be able to
>>> assign the proper interrupt vector. On real hardware, this ID is
>>> sampled from the bus. To be able to emulate an ITS controller, extend
>>> the KVM MSI interface to let userspace provide such a device ID. For
>>> PCI devices, the device ID is simply the 16-bit bus-device-function
>>> triplet, which should be easily available to the userland tool.
>>>
>>> Also there is a new KVM capability which advertises whether the
>>> current VM requires a device ID to be set along with the MSI data.
>>> This flag is still reported as not available everywhere, later we will
>>> enable it when ITS emulation is used.
>>>
>>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
>>> Reviewed-by: Eric Auger <eric.auger at linaro.org>
>>> ---
>>>  Documentation/virtual/kvm/api.txt | 12 ++++++++++--
>>>  include/uapi/linux/kvm.h          |  5 ++++-
>>>  2 files changed, 14 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
>>> index cb2ef0b..8f7351d 100644
>>> --- a/Documentation/virtual/kvm/api.txt
>>> +++ b/Documentation/virtual/kvm/api.txt
>>> @@ -2163,10 +2163,18 @@ struct kvm_msi {
>>>  	__u32 address_hi;
>>>  	__u32 data;
>>>  	__u32 flags;
>>> -	__u8  pad[16];
>>> +	__u32 devid;
>>
>> Are we imposing any unfortunate restrictions for other architectures by
>> using a u32 over a u64 for the device ID?
> 
> Mmmh, good point. I guess not only for other architectures, but also for
> the future in general.
> 
> Are there any objections against increasing this to a u64?

I'm not sure this is really necessary. A PCI RID is 16bit, and expanding
it to 32bit is already making quite a bit of space for further extension.

Also, some architecture might be unhappy of having a 64bit quantity that
is not 64bit aligned...

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From tthayer at opensource.altera.com  Wed May 25 09:29:39 2016
From: tthayer at opensource.altera.com (tthayer at opensource.altera.com)
Date: Wed, 25 May 2016 11:29:39 -0500
Subject: [PATCH 1/5] Documentation: dt: socfpga: Add interrupt-controller to
 ecc-manager
In-Reply-To: <1464193783-5071-1-git-send-email-tthayer@opensource.altera.com>
References: <1464193783-5071-1-git-send-email-tthayer@opensource.altera.com>
Message-ID: <1464193783-5071-2-git-send-email-tthayer@opensource.altera.com>

From: Thor Thayer <tthayer at opensource.altera.com>

Designate the ECC Manager as an interrupt controller and add child
interrupts.

Signed-off-by: Thor Thayer <tthayer at opensource.altera.com>
---
 .../bindings/arm/altera/socfpga-eccmgr.txt         |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt
index 5a6b160..15eb0df 100644
--- a/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt
+++ b/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt
@@ -61,7 +61,9 @@ Required Properties:
 - #address-cells: must be 1
 - #size-cells: must be 1
 - interrupts : Should be single bit error interrupt, then double bit error
-	interrupt. Note the rising edge type.
+	interrupt.
+- interrupt-controller : boolean indicator that ECC Manager is an interrupt controller
+- #interrupt-cells : must be set to 2.
 - ranges : standard definition, should translate from local addresses
 
 Subcomponents:
@@ -70,11 +72,15 @@ L2 Cache ECC
 Required Properties:
 - compatible : Should be "altr,socfpga-a10-l2-ecc"
 - reg : Address and size for ECC error interrupt clear registers.
+- interrupts : Should be single bit error interrupt, then double bit error
+	interrupt, in this order.
 
 On-Chip RAM ECC
 Required Properties:
 - compatible : Should be "altr,socfpga-a10-ocram-ecc"
 - reg        : Address and size for ECC block registers.
+- interrupts : Should be single bit error interrupt, then double bit error
+	interrupt, in this order.
 
 Example:
 
@@ -85,15 +91,21 @@ Example:
 		#size-cells = <1>;
 		interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>,
 			     <0 0 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
 		ranges;
 
 		l2-ecc at ffd06010 {
 			compatible = "altr,socfpga-a10-l2-ecc";
 			reg = <0xffd06010 0x4>;
+			interrupts = <0 IRQ_TYPE_LEVEL_HIGH>,
+				     <32 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		ocram-ecc at ff8c3000 {
 			compatible = "altr,socfpga-a10-ocram-ecc";
 			reg = <0xff8c3000 0x90>;
+			interrupts = <1 IRQ_TYPE_LEVEL_HIGH>,
+				     <33 IRQ_TYPE_LEVEL_HIGH> ;
 		};
 	};
-- 
1.7.9.5



From tthayer at opensource.altera.com  Wed May 25 09:29:38 2016
From: tthayer at opensource.altera.com (tthayer at opensource.altera.com)
Date: Wed, 25 May 2016 11:29:38 -0500
Subject: [PATCH 0/5] Set Arria10 ECC Manager IRQ Controller
Message-ID: <1464193783-5071-1-git-send-email-tthayer@opensource.altera.com>

From: Thor Thayer <tthayer at opensource.altera.com>

The Arria10 IRQs for each peripheral ECC block funnel into 2 IRQs
[1 for single bit errors (SBERR) and 1 for double bit errors (DBERR)]
which are better handled by the IRQ controller and IRQ domain
framework than the IRQ handler in the current implementation.

The IRQ numbers (hwirq) in each peripheral ECC block (currently L2
and OCRAM) device tree node cannot be parsed using of_ functions
in the current implementation because these functions attach the
IRQ to an IRQ domain.

This patch set adds the IRQ controller/IRQ domain framework but
requires some device tree and binding changes as a result.

Thor Thayer (5):
  Documentation: dt: socfpga: Add interrupt-controller to ecc-manager
  EDAC, altera: ECC Manager IRQ controller support
  EDAC, altera: Handle Arria10 SDRAM child node.
  ARM: dts: Arria10 ECC Manager IRQ controller changes
  ARM: dts: Move Arria10 SDRAM as child of ECC Manager

 .../bindings/arm/altera/socfpga-eccmgr.txt         |   14 +-
 arch/arm/boot/dts/socfpga_arria10.dtsi             |   19 +-
 drivers/edac/altera_edac.c                         |  182 +++++++++++++++-----
 drivers/edac/altera_edac.h                         |    5 +-
 4 files changed, 168 insertions(+), 52 deletions(-)

-- 
1.7.9.5



From tthayer at opensource.altera.com  Wed May 25 09:29:40 2016
From: tthayer at opensource.altera.com (tthayer at opensource.altera.com)
Date: Wed, 25 May 2016 11:29:40 -0500
Subject: [PATCH 2/5] EDAC, altera: ECC Manager IRQ controller support
In-Reply-To: <1464193783-5071-1-git-send-email-tthayer@opensource.altera.com>
References: <1464193783-5071-1-git-send-email-tthayer@opensource.altera.com>
Message-ID: <1464193783-5071-3-git-send-email-tthayer@opensource.altera.com>

From: Thor Thayer <tthayer at opensource.altera.com>

To better support child devices, the ECC manager needs to be
implemented as an IRQ controller.

Signed-off-by: Thor Thayer <tthayer at opensource.altera.com>
---
 drivers/edac/altera_edac.c |  162 +++++++++++++++++++++++++++++++++-----------
 drivers/edac/altera_edac.h |    5 +-
 2 files changed, 125 insertions(+), 42 deletions(-)

diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index 5b4d223..3eb73bc 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -22,9 +22,11 @@
 #include <linux/edac.h>
 #include <linux/genalloc.h>
 #include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/kernel.h>
 #include <linux/mfd/syscon.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
@@ -882,22 +884,27 @@ static void ocram_free_mem(void *p, size_t size, void *other)
 	gen_pool_free((struct gen_pool *)other, (u32)p, size);
 }
 
-static irqreturn_t altr_edac_a10_ecc_irq(struct altr_edac_device_dev *dci,
-					 bool sberr)
+static irqreturn_t altr_edac_a10_ecc_irq(int irq, void *dev_id)
 {
+	irqreturn_t ret_value = IRQ_NONE;
+	struct altr_edac_device_dev *dci = dev_id;
 	void __iomem  *base = dci->base;
 
-	if (sberr) {
+	if (irq == dci->sb_irq) {
+		ret_value = IRQ_HANDLED;
 		writel(ALTR_A10_ECC_SERRPENA,
 		       base + ALTR_A10_ECC_INTSTAT_OFST);
 		edac_device_handle_ce(dci->edac_dev, 0, 0, dci->edac_dev_name);
-	} else {
+	} else if (irq == dci->db_irq) {
+		ret_value = IRQ_HANDLED;
 		writel(ALTR_A10_ECC_DERRPENA,
 		       base + ALTR_A10_ECC_INTSTAT_OFST);
 		edac_device_handle_ue(dci->edac_dev, 0, 0, dci->edac_dev_name);
 		panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n");
+	} else {
+		WARN_ON(1);
 	}
-	return IRQ_HANDLED;
+	return ret_value;
 }
 
 const struct edac_device_prv_data ocramecc_data = {
@@ -988,22 +995,28 @@ static int altr_l2_check_deps(struct altr_edac_device_dev *device)
 	return -ENODEV;
 }
 
-static irqreturn_t altr_edac_a10_l2_irq(struct altr_edac_device_dev *dci,
-					bool sberr)
+static irqreturn_t altr_edac_a10_l2_irq(int irq, void *dev_id)
 {
-	if (sberr) {
+	irqreturn_t ret_value = IRQ_NONE;
+	struct altr_edac_device_dev *dci = dev_id;
+
+	if (irq == dci->sb_irq) {
+		ret_value = IRQ_HANDLED;
 		regmap_write(dci->edac->ecc_mgr_map,
 			     A10_SYSGMR_MPU_CLEAR_L2_ECC_OFST,
 			     A10_SYSGMR_MPU_CLEAR_L2_ECC_SB);
 		edac_device_handle_ce(dci->edac_dev, 0, 0, dci->edac_dev_name);
-	} else {
+	} else if (irq == dci->db_irq) {
+		ret_value = IRQ_HANDLED;
 		regmap_write(dci->edac->ecc_mgr_map,
 			     A10_SYSGMR_MPU_CLEAR_L2_ECC_OFST,
 			     A10_SYSGMR_MPU_CLEAR_L2_ECC_MB);
 		edac_device_handle_ue(dci->edac_dev, 0, 0, dci->edac_dev_name);
 		panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n");
+	} else {
+		WARN_ON(1);
 	}
-	return IRQ_HANDLED;
+	return ret_value;
 }
 
 const struct edac_device_prv_data l2ecc_data = {
@@ -1075,28 +1088,27 @@ static ssize_t altr_edac_a10_device_trig(struct file *file,
 	return count;
 }
 
-static irqreturn_t altr_edac_a10_irq_handler(int irq, void *dev_id)
+static void altr_edac_a10_irq_handler(struct irq_desc *desc)
 {
-	irqreturn_t rc = IRQ_NONE;
-	struct altr_arria10_edac *edac = dev_id;
-	struct altr_edac_device_dev *dci;
-	int irq_status;
-	bool sberr = (irq == edac->sb_irq) ? 1 : 0;
-	int sm_offset = sberr ? A10_SYSMGR_ECC_INTSTAT_SERR_OFST :
-				A10_SYSMGR_ECC_INTSTAT_DERR_OFST;
+	int dberr, bit, sm_offset, irq_status;
+	struct altr_arria10_edac *edac = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	int irq = irq_desc_get_irq(desc);
+
+	chained_irq_enter(chip, desc);
+	dberr = (irq == edac->db_irq) ? 1 : 0;
+	sm_offset = dberr ? A10_SYSMGR_ECC_INTSTAT_DERR_OFST :
+			    A10_SYSMGR_ECC_INTSTAT_SERR_OFST;
 
 	regmap_read(edac->ecc_mgr_map, sm_offset, &irq_status);
 
-	if ((irq != edac->sb_irq) && (irq != edac->db_irq)) {
-		WARN_ON(1);
-	} else {
-		list_for_each_entry(dci, &edac->a10_ecc_devices, next) {
-			if (irq_status & dci->data->irq_status_mask)
-				rc = dci->data->ecc_irq_handler(dci, sberr);
-		}
+	for_each_set_bit(bit, (unsigned long *)&irq_status, 32) {
+		irq = irq_linear_revmap(edac->domain, dberr * 32 + bit);
+		if (irq)
+			generic_handle_irq(irq);
 	}
 
-	return rc;
+	chained_irq_exit(chip, desc);
 }
 
 static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,
@@ -1168,6 +1180,34 @@ static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,
 			goto err_release_group1;
 	}
 
+	altdev->sb_irq = irq_of_parse_and_map(np, 0);
+	if (!altdev->sb_irq) {
+		edac_printk(KERN_ERR, EDAC_DEVICE, "Error allocating SBIRQ\n");
+		rc = -ENODEV;
+		goto err_release_group1;
+	}
+	rc = devm_request_irq(edac->dev, altdev->sb_irq,
+			      prv->ecc_irq_handler,
+			      IRQF_SHARED, ecc_name, altdev);
+	if (rc) {
+		edac_printk(KERN_ERR, EDAC_DEVICE, "No DBERR IRQ resource\n");
+		goto err_release_group1;
+	}
+
+	altdev->db_irq = irq_of_parse_and_map(np, 1);
+	if (!altdev->db_irq) {
+		edac_printk(KERN_ERR, EDAC_DEVICE, "Error allocating DBIRQ\n");
+		rc = -ENODEV;
+		goto err_release_group1;
+	}
+	rc = devm_request_irq(edac->dev, altdev->db_irq,
+			      prv->ecc_irq_handler,
+			      IRQF_SHARED, ecc_name, altdev);
+	if (rc) {
+		edac_printk(KERN_ERR, EDAC_DEVICE, "No DBERR IRQ resource\n");
+		goto err_release_group1;
+	}
+
 	rc = edac_device_add_device(dci);
 	if (rc) {
 		dev_err(edac->dev, "edac_device_add_device failed\n");
@@ -1186,7 +1226,6 @@ static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,
 err_release_group1:
 	edac_device_free_ctl_info(dci);
 err_release_group:
-	edac_printk(KERN_ALERT, EDAC_DEVICE, "%s: %d\n", __func__, __LINE__);
 	devres_release_group(edac->dev, NULL);
 	edac_printk(KERN_ERR, EDAC_DEVICE,
 		    "%s:Error setting up EDAC device: %d\n", ecc_name, rc);
@@ -1194,11 +1233,43 @@ err_release_group:
 	return rc;
 }
 
+static void a10_eccmgr_irq_mask(struct irq_data *d)
+{
+	struct altr_arria10_edac *edac = irq_data_get_irq_chip_data(d);
+
+	regmap_write(edac->ecc_mgr_map,	A10_SYSMGR_ECC_INTMASK_SET_OFST,
+		     BIT(d->hwirq));
+}
+
+static void a10_eccmgr_irq_unmask(struct irq_data *d)
+{
+	struct altr_arria10_edac *edac = irq_data_get_irq_chip_data(d);
+
+	regmap_write(edac->ecc_mgr_map,	A10_SYSMGR_ECC_INTMASK_CLR_OFST,
+		     BIT(d->hwirq));
+}
+
+static int a10_eccmgr_irqdomain_map(struct irq_domain *d, unsigned int irq,
+				    irq_hw_number_t hwirq)
+{
+	struct altr_arria10_edac *edac = d->host_data;
+
+	irq_set_chip_and_handler(irq, &edac->irq_chip, handle_simple_irq);
+	irq_set_chip_data(irq, edac);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+struct irq_domain_ops a10_eccmgr_ic_ops = {
+	.map = a10_eccmgr_irqdomain_map,
+	.xlate = irq_domain_xlate_twocell,
+};
+
 static int altr_edac_a10_probe(struct platform_device *pdev)
 {
 	struct altr_arria10_edac *edac;
 	struct device_node *child;
-	int rc;
 
 	edac = devm_kzalloc(&pdev->dev, sizeof(*edac), GFP_KERNEL);
 	if (!edac)
@@ -1216,23 +1287,34 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
 		return PTR_ERR(edac->ecc_mgr_map);
 	}
 
+	edac->irq_chip.name = pdev->dev.of_node->name;
+	edac->irq_chip.irq_mask = a10_eccmgr_irq_mask;
+	edac->irq_chip.irq_unmask = a10_eccmgr_irq_unmask;
+	edac->domain = irq_domain_add_linear(pdev->dev.of_node, 64,
+					     &a10_eccmgr_ic_ops, edac);
+	if (!edac->domain) {
+		dev_err(&pdev->dev, "Error adding IRQ domain\n");
+		return -ENOMEM;
+	}
+
 	edac->sb_irq = platform_get_irq(pdev, 0);
-	rc = devm_request_irq(&pdev->dev, edac->sb_irq,
-			      altr_edac_a10_irq_handler,
-			      IRQF_SHARED, dev_name(&pdev->dev), edac);
-	if (rc) {
-		edac_printk(KERN_ERR, EDAC_DEVICE, "No SBERR IRQ resource\n");
-		return rc;
+	if (edac->sb_irq < 0) {
+		dev_err(&pdev->dev, "No SBERR IRQ resource\n");
+		return edac->sb_irq;
 	}
 
+	irq_set_chained_handler_and_data(edac->sb_irq,
+					 altr_edac_a10_irq_handler,
+					 edac);
+
 	edac->db_irq = platform_get_irq(pdev, 1);
-	rc = devm_request_irq(&pdev->dev, edac->db_irq,
-			      altr_edac_a10_irq_handler,
-			      IRQF_SHARED, dev_name(&pdev->dev), edac);
-	if (rc) {
-		edac_printk(KERN_ERR, EDAC_DEVICE, "No DBERR IRQ resource\n");
-		return rc;
+	if (edac->db_irq < 0) {
+		dev_err(&pdev->dev, "No DBERR IRQ resource\n");
+		return edac->db_irq;
 	}
+	irq_set_chained_handler_and_data(edac->db_irq,
+					 altr_edac_a10_irq_handler,
+					 edac);
 
 	for_each_child_of_node(pdev->dev.of_node, child) {
 		if (!of_device_is_available(child))
diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h
index 42090f3..62b0fa0 100644
--- a/drivers/edac/altera_edac.h
+++ b/drivers/edac/altera_edac.h
@@ -295,8 +295,7 @@ struct edac_device_prv_data {
 	int ce_set_mask;
 	int ue_set_mask;
 	int set_err_ofst;
-	irqreturn_t (*ecc_irq_handler)(struct altr_edac_device_dev *dci,
-				       bool sb);
+	irqreturn_t (*ecc_irq_handler)(int irq, void *dev_id);
 	int trig_alloc_sz;
 	const struct file_operations *inject_fops;
 };
@@ -320,6 +319,8 @@ struct altr_arria10_edac {
 	struct regmap		*ecc_mgr_map;
 	int sb_irq;
 	int db_irq;
+	struct irq_domain	*domain;
+	struct irq_chip		irq_chip;
 	struct list_head	a10_ecc_devices;
 };
 
-- 
1.7.9.5



From tthayer at opensource.altera.com  Wed May 25 09:29:41 2016
From: tthayer at opensource.altera.com (tthayer at opensource.altera.com)
Date: Wed, 25 May 2016 11:29:41 -0500
Subject: [PATCH 3/5] EDAC, altera: Handle Arria10 SDRAM child node.
In-Reply-To: <1464193783-5071-1-git-send-email-tthayer@opensource.altera.com>
References: <1464193783-5071-1-git-send-email-tthayer@opensource.altera.com>
Message-ID: <1464193783-5071-4-git-send-email-tthayer@opensource.altera.com>

From: Thor Thayer <tthayer at opensource.altera.com>

Separate the device match arrays for each platform to prevent
CycloneV matches when calling of_platform_populate() on the
Arria10 ECC manager node.
If the SDRAM is a child node of ECC manager, call probe function
via of_platform_populate().

Signed-off-by: Thor Thayer <tthayer at opensource.altera.com>
---
 drivers/edac/altera_edac.c |   20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index 3eb73bc..dfd5d1b 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -688,11 +688,9 @@ static void altr_create_edacdev_dbgfs(struct edac_device_ctl_info *edac_dci,
 static const struct of_device_id altr_edac_device_of_match[] = {
 #ifdef CONFIG_EDAC_ALTERA_L2C
 	{ .compatible = "altr,socfpga-l2-ecc", .data = &l2ecc_data },
-	{ .compatible = "altr,socfpga-a10-l2-ecc", .data = &a10_l2ecc_data },
 #endif
 #ifdef CONFIG_EDAC_ALTERA_OCRAM
 	{ .compatible = "altr,socfpga-ocram-ecc", .data = &ocramecc_data },
-	{ .compatible = "altr,socfpga-a10-ocram-ecc", .data = &a10_ocramecc_data },
 #endif
 	{},
 };
@@ -1054,6 +1052,17 @@ const struct edac_device_prv_data a10_l2ecc_data = {
 #endif	/* CONFIG_EDAC_ALTERA_L2C */
 
 /********************* Arria10 EDAC Device Functions *************************/
+static const struct of_device_id altr_edac_a10_device_of_match[] = {
+#ifdef CONFIG_EDAC_ALTERA_L2C
+	{ .compatible = "altr,socfpga-a10-l2-ecc", .data = &a10_l2ecc_data },
+#endif
+#ifdef CONFIG_EDAC_ALTERA_OCRAM
+	{ .compatible = "altr,socfpga-a10-ocram-ecc",
+	  .data = &a10_ocramecc_data },
+#endif
+	{},
+};
+MODULE_DEVICE_TABLE(of, altr_edac_a10_device_of_match);
 
 /*
  * The Arria10 EDAC Device Functions differ from the Cyclone5/Arria5
@@ -1123,7 +1132,7 @@ static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,
 	const struct edac_device_prv_data *prv;
 	/* Get matching node and check for valid result */
 	const struct of_device_id *pdev_id =
-		of_match_node(altr_edac_device_of_match, np);
+		of_match_node(altr_edac_a10_device_of_match, np);
 	if (IS_ERR_OR_NULL(pdev_id))
 		return -ENODEV;
 
@@ -1324,6 +1333,11 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
 		else if (of_device_is_compatible(child,
 						 "altr,socfpga-a10-ocram-ecc"))
 			altr_edac_a10_device_add(edac, child);
+		else if (of_device_is_compatible(child,
+						 "altr,sdram-edac-a10"))
+			of_platform_populate(pdev->dev.of_node,
+					     altr_sdram_ctrl_of_match,
+					     NULL, &pdev->dev);
 	}
 
 	return 0;
-- 
1.7.9.5



From tthayer at opensource.altera.com  Wed May 25 09:29:42 2016
From: tthayer at opensource.altera.com (tthayer at opensource.altera.com)
Date: Wed, 25 May 2016 11:29:42 -0500
Subject: [PATCH 4/5] ARM: dts: Arria10 ECC Manager IRQ controller changes
In-Reply-To: <1464193783-5071-1-git-send-email-tthayer@opensource.altera.com>
References: <1464193783-5071-1-git-send-email-tthayer@opensource.altera.com>
Message-ID: <1464193783-5071-5-git-send-email-tthayer@opensource.altera.com>

From: Thor Thayer <tthayer at opensource.altera.com>

Changes to support IRQ controller implementation including adding
new property irq-controller to eccmgr and adding IRQ property
to children.

Signed-off-by: Thor Thayer <tthayer at opensource.altera.com>
---
 arch/arm/boot/dts/socfpga_arria10.dtsi |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi
index 27cc497..0901090 100644
--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
+++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
@@ -606,16 +606,22 @@
 			#size-cells = <1>;
 			interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>,
 				     <0 0 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
 			ranges;
 
 			l2-ecc at ffd06010 {
 				compatible = "altr,socfpga-a10-l2-ecc";
 				reg = <0xffd06010 0x4>;
+				interrupts = <0 IRQ_TYPE_LEVEL_HIGH>,
+					     <32 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
 			ocram-ecc at ff8c3000 {
 				compatible = "altr,socfpga-a10-ocram-ecc";
 				reg = <0xff8c3000 0x400>;
+				interrupts = <1 IRQ_TYPE_LEVEL_HIGH>,
+					     <33 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
-- 
1.7.9.5



From mark.rutland at arm.com  Wed May 25 09:12:07 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Wed, 25 May 2016 17:12:07 +0100
Subject: [PATCH] arm64/efi: remove spurious WARN_ON for !4K kernels
In-Reply-To: <BA565A9C-8CC0-42E4-9821-7941852F835A@linaro.org>
References: <1464189116-30898-1-git-send-email-mark.rutland@arm.com>
 <BA565A9C-8CC0-42E4-9821-7941852F835A@linaro.org>
Message-ID: <20160525161207.GD30956@leverpostej>

On Wed, May 25, 2016 at 05:23:01PM +0200, Ard Biesheuvel wrote:
> 
> 
> > On 25 mei 2016, at 17:11, Mark Rutland <mark.rutland at arm.com> wrote:
> > 
> > Since commit 1fd55a9a09b0293a ("arm64/efi: Apply strict permissions to
> > UEFI Runtime Services regions"), booting a !4K page kernel results in a
> > boot-time splat on some systems, due to to a WARN_ONCE added in that
> > commit which fires if the base address of an EFI memory descriptor is
> > not aligned to the kernel page size (which might be 4K, 16K, or 64K).
> > 
> > On page 38 of the UEFI 2.6 specification it is stated:
> > 
> >    If a 64KiB physical page contains any 4KiB page with any of the
> >    following types listed below, then all 4KiB pages in the 64KiB
> >    page must use identical ARM Memory Page Attributes (as described
> >    in Table 8):
> >    ? EfiRuntimeServicesCode
> >    ? EfiRuntimeServicesData
> >    ? EfiReserved
> >    ? EfiACPIMemoryNVS
> >    Mixed attribute mappings within a larger page are not allowed.
> > 
> 
> The same section mentions that the ro/xp etc attributes are unused on
> arm, so if we go by the letter here, we need to remove those memory
> protection features entirely. So a spec update is clearly in order
> here.

Yes; that definitely needs fixing.

FWIW, I don't think that matters in this case (assuming the usual EFI
memory desc dump stuff prints those).

My memory map (and the remap triggering the WARN_ONCE) look like:

[    0.000000] efi: Getting EFI parameters from FDT:
[    0.000000] efi:   System Table: 0x00000083ff34bf18
[    0.000000] efi:   MemMap Address: 0x00000083fcefd618
[    0.000000] efi:   MemMap Size: 0x00000540
[    0.000000] efi:   MemMap Desc. Size: 0x00000030
[    0.000000] efi:   MemMap Desc. Version: 0x00000001
[    0.000000] efi: EFI v2.40 by American Megatrends
[    0.000000] efi:  ACPI 2.0=0x83ff1c3000  SMBIOS 3.0=0x83ff347798 
[    0.000000] efi: Processing EFI memory map:
[    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x008001e80000-0x008001ffffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x008002000000-0x008002ddffff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x008002de0000-0x00801fdfffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x00801fe00000-0x00801fe0ffff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x00801fe10000-0x00801fffbfff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x00801fffc000-0x00801fffffff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x008020000000-0x0083f0ffffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0083f1000000-0x0083f101ffff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0083f1020000-0x0083fb542fff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0083fb543000-0x0083fc2a2fff [Loader Code        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0083fc2a3000-0x0083fcefcfff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0083fcefd000-0x0083fcefefff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0083fceff000-0x0083fd01afff [Loader Code        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0083fd01b000-0x0083fea67fff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0083fea68000-0x0083febd3fff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0083febd4000-0x0083ff186fff [Boot Code          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0083ff187000-0x0083ff1b6fff [Reserved           |   |  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0083ff1b7000-0x0083ff1c4fff [ACPI Reclaim Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0083ff1c5000-0x0083ff20ffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0083ff210000-0x0083ff224fff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0083ff225000-0x0083ff226fff [ACPI Memory NVS    |   |  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0083ff227000-0x0083ff34bfff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0083ff34c000-0x0083ffe42fff [Runtime Code       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0083ffe43000-0x0083ffffffff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
...
[    0.079000] Remapping and enabling EFI services.
[    0.083677]   EFI remap 0x00000000e1050000 => 0000000020000000
[    0.089551]   EFI remap 0x00000000e1300000 => 0000000020010000
[    0.095421]   EFI remap 0x00000000e8200000 => 0000000020020000
[    0.101324]   EFI remap 0x0000008000000000 => 0000000020200000
[    0.107192] UEFI Runtime regions are not aligned to 64 KB -- buggy firmware?
[    0.114116] ------------[ cut here ]------------
[    0.118941] WARNING: CPU: 0 PID: 1 at arch/arm64/kernel/efi.c:34 efi_create_mapping+0x50/0xdc
[    0.127524] Modules linked in:
[    0.130592] 
[    0.132083] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.6.0-next-20160525 #6
[    0.139180] Hardware name: AMD Seattle (Rev.B0) Development Board (Overdrive) (DT)
[    0.146805] task: ffff8003c01e0000 ti: ffff8003c0200000 task.ti: ffff8003c0200000
[    0.154338] PC is at efi_create_mapping+0x50/0xdc
[    0.159071] LR is at efi_create_mapping+0x50/0xdc
[    0.163800] pc : [<ffff000008b23f34>] lr : [<ffff000008b23f34>] pstate: 60000245
[    0.171248] sp : ffff8003c0203d60
[    0.174579] x29: ffff8003c0203d60 x28: 0000000000000000 
[    0.179925] x27: 0000000000000000 x26: 0000000000000000 
[    0.185269] x25: 0000000000000000 x24: ffff000008ca7be0 
[    0.190616] x23: ffff000008d5b000 x22: ffff000008a76ff8 
[    0.195959] x21: ffff000008c45000 x20: ffff000008ca7be0 
[    0.201303] x19: ffff8003fcefdac8 x18: 0000000000000006 
[    0.206649] x17: 0000000000000007 x16: 0000000000000001 
[    0.211992] x15: ffff000008d15c95 x14: 3f657261776d7269 
[    0.217337] x13: 6620796767756220 x12: 0000000005f5e0ff 
[    0.222683] x11: 206f742064656e67 x10: 000000000001a2b8 
[    0.228026] x9 : ffff8003c0203b60 x8 : 000000000000006c 
[    0.233368] x7 : 2d2d20424b203436 x6 : ffff000008d15cd7 
[    0.238711] x5 : 0000000000000041 x4 : 0000000000000000 
[    0.244055] x3 : 0000000000000000 x2 : 00000000000002e6 
[    0.249439] x1 : ffff8003c0200000 x0 : 0000000000000040 
[    0.254784] 
[    0.256279] ---[ end trace e9947b6ce71b94cd ]---
[    0.260922] Call trace:
[    0.263376] Exception stack(0xffff8003c0203ba0 to 0xffff8003c0203cc0)
[    0.269860] 3ba0: ffff8003fcefdac8 ffff000008ca7be0 ffff8003c0203d60 ffff000008b23f34
[    0.277741] 3bc0: ffff8003c0203be0 ffff000008a08ac0 0000000000000040 0000000000000001
[    0.285624] 3be0: ffff8003c0203c80 ffff0000080f42a8 ffff8003fcefdac8 ffff000008ca7be0
[    0.293508] 3c00: ffff000008c45000 ffff000008a76ff8 ffff000008d5b000 ffff000008ca7be0
[    0.301391] 3c20: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[    0.309271] 3c40: 0000000000000040 ffff8003c0200000 00000000000002e6 0000000000000000
[    0.317154] 3c60: 0000000000000000 0000000000000041 ffff000008d15cd7 2d2d20424b203436
[    0.325037] 3c80: 000000000000006c ffff8003c0203b60 000000000001a2b8 206f742064656e67
[    0.332922] 3ca0: 0000000005f5e0ff 6620796767756220 3f657261776d7269 ffff000008d15c95
[    0.340805] [<ffff000008b23f34>] efi_create_mapping+0x50/0xdc
[    0.346651] [<ffff000008b530e8>] arm_enable_runtime_services+0x130/0x214
[    0.353400] [<ffff000008081990>] do_one_initcall+0x38/0x128
[    0.359009] [<ffff000008b20be4>] kernel_init_freeable+0x84/0x1f0
[    0.365054] [<ffff0000087a9b58>] kernel_init+0x10/0x100
[    0.370311] [<ffff000008084ac0>] ret_from_fork+0x10/0x50
[    0.375661]   EFI remap 0x00000083ff227000 => 0000000022087000
[    0.381544]   EFI remap 0x00000083ff34c000 => 00000000221ac000

Thanks,
Mark.


From tthayer at opensource.altera.com  Wed May 25 09:29:43 2016
From: tthayer at opensource.altera.com (tthayer at opensource.altera.com)
Date: Wed, 25 May 2016 11:29:43 -0500
Subject: [PATCH 5/5] ARM: dts: Move Arria10 SDRAM as child of ECC Manager
In-Reply-To: <1464193783-5071-1-git-send-email-tthayer@opensource.altera.com>
References: <1464193783-5071-1-git-send-email-tthayer@opensource.altera.com>
Message-ID: <1464193783-5071-6-git-send-email-tthayer@opensource.altera.com>

From: Thor Thayer <tthayer at opensource.altera.com>

Changes to support ECC Manager as SDRAM IRQ parent by
1) updating IRQ property values to correct child IRQs
2) moving node under ECC Manager.

Signed-off-by: Thor Thayer <tthayer at opensource.altera.com>
---
 arch/arm/boot/dts/socfpga_arria10.dtsi |   13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi
index 0901090..605c21e 100644
--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
+++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
@@ -568,12 +568,6 @@
 			reg = <0xffcfb100 0x80>;
 		};
 
-		sdramedac {
-			compatible = "altr,sdram-edac-a10";
-			altr,sdr-syscon = <&sdr>;
-			interrupts = <0 2 4>, <0 0 4>;
-		};
-
 		L2: l2-cache at fffff000 {
 			compatible = "arm,pl310-cache";
 			reg = <0xfffff000 0x1000>;
@@ -610,6 +604,13 @@
 			#interrupt-cells = <2>;
 			ranges;
 
+			sdramedac {
+				compatible = "altr,sdram-edac-a10";
+				altr,sdr-syscon = <&sdr>;
+				interrupts = <17 IRQ_TYPE_LEVEL_HIGH>,
+					     <49 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
 			l2-ecc at ffd06010 {
 				compatible = "altr,socfpga-a10-l2-ecc";
 				reg = <0xffd06010 0x4>;
-- 
1.7.9.5



From maxime.ripard at free-electrons.com  Wed May 25 09:29:45 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Wed, 25 May 2016 18:29:45 +0200
Subject: [PATCH 12/20] drm/sun4i: Add bridge support
In-Reply-To: <CAKMK7uG-uq7XSqyesVnPtx0Ajx-FQjVKm_QzjEZgWJQDn8EkPA@mail.gmail.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-13-git-send-email-maxime.ripard@free-electrons.com>
 <CAKMK7uG-uq7XSqyesVnPtx0Ajx-FQjVKm_QzjEZgWJQDn8EkPA@mail.gmail.com>
Message-ID: <20160525162945.GK9232@lukather>

Hi Daniel,

On Mon, May 16, 2016 at 03:12:15PM +0200, Daniel Vetter wrote:
> On Mon, May 16, 2016 at 2:47 PM, Maxime Ripard
> <maxime.ripard at free-electrons.com> wrote:
> > Our RGB bus can be either connected to a bridge or a panel. While the panel
> > support was already there, the bridge was not.
> >
> > Fix that.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> 
> For bridge support the only thing you need is to set
> drm_encoder->bridge. Why do you need to hand-roll your own bridge
> support? That pretty muchmeans you'll do it slightly differently (e.g.
> you don't bother with a lot of the calls), which will make sharing
> bridge drivers ever so harder. And also reviewing code, since using
> shared code but slightly differently is really confusing.

Because I overlooked it :)

I'll change that.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160525/56a7f4a6/attachment-0001.sig>

From ynorov at caviumnetworks.com  Wed May 25 09:41:32 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Wed, 25 May 2016 19:41:32 +0300
Subject: [PATCH v6 00/21] ILP32 for ARM64
In-Reply-To: <5745817C.1070406@arm.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
 <5745817C.1070406@arm.com>
Message-ID: <20160525164132.GB4595@yury-N73SV>

On Wed, May 25, 2016 at 11:42:04AM +0100, Szabolcs Nagy wrote:
> On 24/05/16 01:04, Yury Norov wrote:
> > This version is based on kernel v4.6.
> > It works with glibc-2.23, and tested with LTP.
> > 
> ...
> > ILP32 glibc branch is available here:
> > https://github.com/norov/glibc/tree/ilp32-2.23
> > 
> > It is tested with this series with no major downsides. I will send it to 
> > glibc-alpha soon, after final revise. Please review and comment it as well.
> 
> i spotted one __ilp32__ vs __ILP32__ typo in the glibc code,

Yes, I also found it. Thank you.

> i can review it in detail when there is a cleaned up patch set.
> 
> in general the approach seems ok, the ugly part is when lp64
> and ilp32 share code, but ilp32 needs some tweaks compared to
> the current code (e.g. x vs w regs in asm, long changed to
> long long in syscalls, different relocations etc) those will
> be hard to review. the naming is sometimes _be_ilp32 sometimes
> ilp32_be, but let's hope there will be no new abi variant to
> confuse this further.

I think I shared the link too soon, and patches should be revised 
again. So I continue the work on it. If you curious, find it here.
https://github.com/norov/glibc/tree/ilp32-dev
(I don't promise I'll keep it stable, or will avoid using things like
fast-forward. It's just a branch for my experiments.)

For now, it has fixed:
 - __ilp32__ mess (by introducing DELOUSE() macro);
 - few unneeded patches dropped;
 - 32-bit off_t turned to 64-bit.

With all changes, LPT fail list grows:
peio_3                       FAIL       5    
pipeio_6                       FAIL       1    
abort01                        FAIL       2    
clone02                        FAIL       4    
fcntl11                        FAIL       1    
fcntl14                        FAIL       1    
fcntl17                        FAIL       1    
fcntl19                        FAIL       1    
fcntl20                        FAIL       1    
fcntl21                        FAIL       1    
fpathconf01                    FAIL       1    
ftruncate04                    FAIL       1    
kill11                         FAIL       2    
mmap16                         FAIL       6    
open12                         FAIL       2    
pread01                        FAIL       2    
pread02                        FAIL       2    
pread03                        FAIL       2    
preadv01                       FAIL       6    
preadv02                       FAIL       6    
pwrite01                       FAIL       2    
pwrite02                       FAIL       2    
pwrite04                       FAIL       6    
pwrite02_64                    FAIL       1    
pwritev01                      FAIL       2    
pwritev02                      FAIL       2    
rename11                       FAIL       2    
rmdir02                        FAIL       2    
umount2_01                     FAIL       2    
umount2_02                     FAIL       2    
umount2_03                     FAIL       2    
utime06                        FAIL       2    
mtest01                        FAIL       1    
mtest01w                       FAIL       1    
mtest06                        FAIL       11   
gf01                           FAIL       1    
gf02                           FAIL       1    
gf07                           FAIL       1    
gf10                           FAIL       1    
gf11                           FAIL       1    
gf15                           FAIL       1    
gf18                           FAIL       1    
gf19                           FAIL       1    

Yury


From sricharan at codeaurora.org  Wed May 25 09:49:29 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Wed, 25 May 2016 22:19:29 +0530
Subject: [PATCH V5 6/7] iommu/msm: Use writel_relaxed and add a barrier
In-Reply-To: <7715835.BXgVNoY5UO@wuerfel>
References: <1463741694-1735-1-git-send-email-sricharan@codeaurora.org>
 <14302911.qQPb4UMJ8d@wuerfel>
 <004c01d1b688$0f6379c0$2e2a6d40$@codeaurora.org> <7715835.BXgVNoY5UO@wuerfel>
Message-ID: <000901d1b6a5$6dcd5f90$49681eb0$@codeaurora.org>

Hi Arnd,

>> >* On other platforms, polling the register is likely required because
>> >  an MMIO write is "posted", meaning that a sync after writel() will
>> >  only ensure that it has left the CPU write queue, but it may still be
>> >  on the bus fabric and whatever side-effects are triggered by the
>> >  write are normally not guaranteed to be completed even after the
>> >  'sync'. You need to check the datasheet for your IOMMU to find out
>> >  whether the 'dsb' instruction actually has any effect on the IOMMU.
>> >  If not, then neither the barrier that you add here nor the barrier
>> >  in the following writel() is sufficient.
>> >
>>    Thanks for the detailed explanation.
>> i will check this. So with this, i think that if the iommu does not
>>  support polling for its status, then it should listen to 'dsb' otherwise
>>  there will no be no way of make it coherent ?
>
>It's more likely that you have to do a readl() after the writel() to
>any address inside of the device in order to ensure the writel()
>has completed, but that is something that the hardware manual for
>the iommu should describe.
>
 ok, get it. So will do it as required for here.

>> >* The one barrier that is normally required in an IOMMU is between
>> >  updating the in-memory page tables and the following MMIO store
>> >  that triggers the TLB flush for that entry. This barrier is
>> >  implied by writel() but not writel_relaxed(). If you don't have
>> >  a hardware page table walker in your IOMMU, you don't need to worry
>> >  about this.
>> >
>>   To get my understanding correct here, is the barrier required here because
>>    of speculative fetch ?
>
>It doesn't have to be a speculative fetch, it could also be a normal
>fetch triggered by a DMA. The point is that the CPU is free to reorder
>the store to (io page table) memory relative to the store to the
>IOMMU flush register, and when you directly follow up with a store to
>the DMA master that triggers a transfer, this transfer can hit the
>IOMMU and cause the stale page table entry to be read.
>
>I guess in practice the barrier that comes before the MMIO write to the
>DMA master would ensure ordering of the DMA after both the IOPTE
>update and the MMIO flush (unless there was the speculative fetch you
>mentioned), but this is where I'm no longer confident enough in my
>pwn understanding of th ordering rules to rely on that. Having the
>barrier between the IOPTE update and the flush certainly leaves
>no room for ambiguity.
    Ok understand. Also i think speculative access if any, should 
     go away if unmap is done first and then remap by clients.

Regards,
 Sricharan




From robh at kernel.org  Wed May 25 10:09:12 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 25 May 2016 12:09:12 -0500
Subject: [PATCH 1/3] Documentation: dtb: xgene: Add hwmon dts binding
 documentation
In-Reply-To: <CAFHUOYyYt8pE6sggezCR=TFcsimcjakbYmcWFtpLyQ3Et_gZaA@mail.gmail.com>
References: <1463415447-29903-1-git-send-email-hotran@apm.com>
 <1463415447-29903-2-git-send-email-hotran@apm.com>
 <20160523203044.GA17450@rob-hp-laptop>
 <CAFHUOYyYt8pE6sggezCR=TFcsimcjakbYmcWFtpLyQ3Et_gZaA@mail.gmail.com>
Message-ID: <20160525170912.GA24382@rob-hp-laptop>

On Mon, May 23, 2016 at 06:01:14PM -0700, Hoan Tran wrote:
> Hi Rob,
> 
> Thanks for your review !
> 
> On Mon, May 23, 2016 at 1:30 PM, Rob Herring <robh at kernel.org> wrote:
> >
> > On Mon, May 16, 2016 at 09:17:25AM -0700, Hoan Tran wrote:
> > > This patch adds the APM X-Gene hwmon device tree node documentation.
> > >
> > > Signed-off-by: Hoan Tran <hotran at apm.com>
> > > ---
> > >  .../devicetree/bindings/hwmon/apm-xgene-hwmon.txt          | 14 ++++++++++++++
> > >  1 file changed, 14 insertions(+)
> > >  create mode 100644 Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt
> > >
> > > diff --git a/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt b/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt
> > > new file mode 100644
> > > index 0000000..49a482e
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt
> > > @@ -0,0 +1,14 @@
> > > +APM X-Gene hwmon driver
> > > +
> > > +Hwmon driver accesses sensors over the "SLIMpro" mailbox.
> >
> > DT bindings describe h/w, not driver data.
> How about this description: "APM X-Gene SOC sensors are accessed over
> the "SLIMpro" mailbox" ?
> > I'm not sure this belongs in
> > DT and perhaps the devices for the mailbox should be created by the
> > mailbox driver.
> I don't think the current mailbox supports it.

Then add it. The mailbox binding is really only needed when other h/w 
blocks use a mailbox. As this is purely a firmware interface then the 
mailbox driver can create any devices it needs. The devices don't have 
to be in DT to be created.

Rob


From bjorn.andersson at linaro.org  Wed May 25 10:10:43 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Wed, 25 May 2016 10:10:43 -0700
Subject: [PATCH v4 01/18] remoteproc: st_xp70_rproc: add a xp70 slimcore
 rproc driver
In-Reply-To: <1464192412-16386-3-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
 <1464192412-16386-3-git-send-email-peter.griffin@linaro.org>
Message-ID: <20160525171043.GT1256@tuxbot>

On Wed 25 May 09:06 PDT 2016, Peter Griffin wrote:

> XP70 slim core is used as a basis for many IPs in the STi
> chipsets such as fdma, display, and demux. To avoid
> duplicating the elf loading code in each device driver
> an xp70 rproc driver has been created.
> 
I like this approach.

[..]

> diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
[..]
>  
> +config ST_XP70_REMOTEPROC
> +	tristate "XP70 slim remoteproc support"

As this "driver" in itself doesn't do anything I don't think it makes
sense to have it user selectable. Please make the "clients" select it
instead.

> +	depends on ARCH_STI
> +	select REMOTEPROC
> +	help
> +	  Say y here to support xp70 slim core.
> +	  If unsure say N.
> +
>  endmenu
> diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
[..]
> +#include <linux/clk.h>
> +#include <linux/elf.h>

You should be able to drop inclusion of elf.h now.

[..]
> +static int xp70_clk_get(struct st_xp70_rproc *xp70_rproc, struct device *dev)
> +{
> +	int clk, err = 0;

No need to initialize err.

> +
> +	for (clk = 0; clk < XP70_MAX_CLK; clk++) {
> +		xp70_rproc->clks[clk] = of_clk_get(dev->of_node, clk);
> +		if (IS_ERR(xp70_rproc->clks[clk])) {
> +			err = PTR_ERR(xp70_rproc->clks[clk]);
> +			if (err == -EPROBE_DEFER)
> +				goto err_put_clks;
> +			xp70_rproc->clks[clk] = NULL;
> +			break;
> +		}
> +	}
> +
> +	return 0;
> +
> +err_put_clks:
> +	while (--clk >= 0)
> +		clk_put(xp70_rproc->clks[clk]);
> +
> +	return err;
> +}
> +
[..]
> +/**
> + * Remoteproc xp70 specific device handlers
> + */
> +static int xp70_rproc_start(struct rproc *rproc)
> +{
> +	struct device *dev = &rproc->dev;
> +	struct st_xp70_rproc *xp70_rproc = rproc->priv;
> +	unsigned long hw_id, hw_ver, fw_rev;
> +	u32 val, ret = 0;

ret should be signed and there's no need to initialize it.

> +
> +	ret = xp70_clk_enable(xp70_rproc);
> +	if (ret) {
> +		dev_err(dev, "Failed to enable clocks\n");
> +		goto err_clk;
> +	}
[..]
> +
> +	dev_dbg(dev, "XP70 started\n");
> +
> +err_clk:
> +	return ret;
> +}
> +
> +static int xp70_rproc_stop(struct rproc *rproc)
> +{
> +	struct st_xp70_rproc *xp70_rproc = rproc->priv;
> +	u32 val;
> +
> +	/* mask all (cmd & int) channels */
> +	writel_relaxed(0UL, xp70_rproc->peri + XP70_INT_MASK_OFST);
> +	writel_relaxed(0UL, xp70_rproc->peri + XP70_CMD_MASK_OFST);
> +
> +	/* disable cpu pipeline clock */
> +	writel_relaxed(XP70_CLK_GATE_DIS
> +		, xp70_rproc->slimcore + XP70_CLK_GATE_OFST);
> +
> +	writel_relaxed(!XP70_EN_RUN, xp70_rproc->slimcore + XP70_EN_OFST);

Don't you want to ensure ordering of these writes? Perhaps making this
last one a writel()?

> +
> +	val = readl_relaxed(xp70_rproc->slimcore + XP70_EN_OFST);
> +	if (val & XP70_EN_RUN)
> +		dev_warn(&rproc->dev, "Failed to disable XP70");
> +
> +	xp70_clk_disable(xp70_rproc);
> +
> +	dev_dbg(&rproc->dev, "xp70 stopped\n");
> +
> +	return 0;
> +}
> +
> +static void *xp70_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +{
> +	struct st_xp70_rproc *xp70_rproc = rproc->priv;
> +	void *va = NULL;
> +	int i;
> +
> +	for (i = 0; i < XP70_MEM_MAX; i++) {
> +
> +		if (da != xp70_rproc->mem[i].bus_addr)
> +			continue;
> +
> +		va = xp70_rproc->mem[i].cpu_addr;
> +			break;
> +	}

Please clean up the indentation and drop the extra newline at the
beginning in this loop.

> +
> +	dev_dbg(&rproc->dev, "%s: da = 0x%llx len = 0x%x va = 0x%p\n"
> +		, __func__, da, len, va);
> +
> +	return va;
> +}
> +
> +static struct rproc_ops xp70_rproc_ops = {
> +	.start		= xp70_rproc_start,
> +	.stop		= xp70_rproc_stop,
> +	.da_to_va       = xp70_rproc_da_to_va,
> +};
> +
> +/**
> + * Firmware handler operations: sanity, boot address, load ...
> + */
> +
> +static struct resource_table empty_rsc_tbl = {
> +	.ver = 1,
> +	.num = 0,
> +};


I'm looking at making the resource table optional, good to see another
vote for that. Looks good for now though.

[..]

> +
> +/**
> +  * xp70_rproc_alloc - allocate and initialise xp70 rproc

Drop one of the two spaces indenting this block and add () after then
function name.

> +  * @pdev: Pointer to the platform_device struct
> +  * @fw_name: Name of firmware for rproc to use
> +  *
> +  * Function for allocating and initialising a xp70 rproc for use by
> +  * device drivers whose IP is based around the xp70 slim core. It
> +  * obtains and enables any clocks required by the xp70 core and also
> +  * ioremaps the various IO.
> +  *
> +  * Returns rproc pointer or PTR_ERR() on error.
> +  */
> +
> +struct rproc *xp70_rproc_alloc(struct platform_device *pdev, char *fw_name)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct st_xp70_rproc *xp70_rproc;
> +	struct device_node *np = dev->of_node;
> +	struct rproc *rproc;
> +	struct resource *res;
> +	int err, i;
> +	const struct rproc_fw_ops *elf_ops;
> +
> +	if (!np || !fw_name)
> +		return ERR_PTR(-EINVAL);

This should, I believe, only ever happen in development. So if you want
to keep it to aid developers feel free to throw in a WARN_ON() in the
condition.

> +
> +	if (!of_device_is_compatible(np, "st,xp70-rproc"))
> +		return ERR_PTR(-EINVAL);
> +
> +	rproc = rproc_alloc(dev, np->name, &xp70_rproc_ops,
> +			fw_name, sizeof(*xp70_rproc));
> +	if (!rproc)
> +		return ERR_PTR(-ENOMEM);
> +
> +	rproc->has_iommu = false;
> +
> +	xp70_rproc = rproc->priv;
> +	xp70_rproc->rproc = rproc;
> +
> +	/* Get standard ELF ops */
> +	elf_ops = rproc_get_elf_ops();
> +
> +	/* Use some generic elf ops */
> +	xp70_rproc_fw_ops.load = elf_ops->load;
> +	xp70_rproc_fw_ops.sanity_check = elf_ops->sanity_check;
> +
> +	rproc->fw_ops = &xp70_rproc_fw_ops;
> +
> +	/* get imem and dmem */
> +	for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
> +		res = xp70_rproc->mem[i].io_res;
> +

io_res is NULL here, and res is directly assigned again. So drop this
and io_res from the struct.

> +		res = platform_get_resource_byname
> +			(pdev, IORESOURCE_MEM, mem_names[i]);
> +
> +		xp70_rproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res);
> +		if (IS_ERR(xp70_rproc->mem[i].cpu_addr)) {
> +			dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
> +			err = PTR_ERR(xp70_rproc->mem[i].cpu_addr);
> +			goto err;
> +		}
> +		xp70_rproc->mem[i].bus_addr = res->start;
> +		xp70_rproc->mem[i].size = resource_size(res);
> +	}
> +
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "slimcore");
> +
> +	xp70_rproc->slimcore = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(xp70_rproc->slimcore)) {
> +		dev_err(&pdev->dev, "devm_ioremap_resource failed for slimcore\n");
> +		err = PTR_ERR(xp70_rproc->slimcore);
> +		goto err;
> +	}
> +
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "peripherals");
> +
> +	xp70_rproc->peri = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(xp70_rproc->peri)) {
> +		dev_err(&pdev->dev, "devm_ioremap_resource failed for peri\n");
> +		err = PTR_ERR(xp70_rproc->peri);
> +		goto err;
> +	}
> +
> +	err = xp70_clk_get(xp70_rproc, dev);
> +	if (err)
> +		goto err;
> +
> +	/* Register as a remoteproc device */
> +	err = rproc_add(rproc);
> +	if (err) {
> +		dev_err(dev, "registration of xp70 remoteproc failed\n");
> +		goto err;

In this case you should also put the clocks.

> +	}
> +
> +	dev_dbg(dev, "XP70 rproc init successful\n");
> +	return rproc;
> +
> +err:
> +	rproc_put(rproc);
> +	return ERR_PTR(err);
> +}
> +EXPORT_SYMBOL(xp70_rproc_alloc);
> +
> +/**
> +  * xp70_rproc_put - put xp70 rproc resources
> +  * @xp70_rproc: Pointer to the st_xp70_rproc struct
> +  *
> +  * Function for calling respective _put() functions on
> +  * xp70_rproc resources.
> +  *
> +  * Returns rproc pointer or PTR_ERR() on error.
> +  */
> +void xp70_rproc_put(struct st_xp70_rproc *xp70_rproc)
> +{
> +	int clk;
> +
> +	if (!xp70_rproc)
> +		return;
> +
> +	rproc_put(xp70_rproc->rproc);
> +
> +	for (clk = 0; clk < XP70_MAX_CLK && xp70_rproc->clks[clk]; clk++)
> +		clk_put(xp70_rproc->clks[clk]);

rproc_put() will free your private data, i.e. xp70_rproc, so you must
put your clocks before that.

> +
> +}
> +EXPORT_SYMBOL(xp70_rproc_put);
> +
> +MODULE_AUTHOR("Peter Griffin");
> +MODULE_DESCRIPTION("STMicroelectronics XP70 rproc driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/remoteproc/st_xp70_rproc.h b/include/linux/remoteproc/st_xp70_rproc.h
[..]
> +
> +#define XP70_MEM_MAX 2
> +#define XP70_MAX_CLK 4
> +#define NAME_SZ 10

NAME_SZ seems unused and would be too generic.

> +
> +enum {
> +	DMEM,
> +	IMEM,

These are too generic for a header file.

> +};
> +
> +/**
> + * struct xp70_mem - xp70 internal memory structure
> + * @cpu_addr: MPU virtual address of the memory region
> + * @bus_addr: Bus address used to access the memory region
> + * @dev_addr: Device address from Wakeup M3 view
> + * @size: Size of the memory region
> + */
> +struct xp70_mem {
> +	void __iomem *cpu_addr;
> +	phys_addr_t bus_addr;
> +	u32 dev_addr;

dev_addr is unused.

> +	size_t size;
> +	struct resource *io_res;

io_res is unused.

> +};
> +
> +/**
> + * struct st_xp70_rproc - XP70 slim core
> + * @rproc: rproc handle
> + * @pdev: pointer to platform device
> + * @mem: xp70 memory information
> + * @slimcore: xp70 slimcore regs
> + * @peri: xp70 peripheral regs
> + * @clks: xp70 clocks
> + */
> +struct st_xp70_rproc {
> +	struct rproc *rproc;
> +	struct platform_device *pdev;

pdev is unused.

> +	struct xp70_mem mem[XP70_MEM_MAX];
> +	void __iomem *slimcore;
> +	void __iomem *peri;
> +	struct clk *clks[XP70_MAX_CLK];
> +};

I generally don't like sharing a struct like this between two
implementations, but I don't think it's worth working around it in this
case.

Perhaps you can group the members into a section of "public" and a
section of "private" members; with a /* st_xp70_rproc private */ heading
the latter?

> +
> +struct rproc *xp70_rproc_alloc(struct platform_device *pdev, char *fw_name);

For consistency I think xp70_rproc_alloc() should return a st_xp70_rproc
reference, rather than forcing the clients pull that pointer out of
rproc->priv.

> +void xp70_rproc_put(struct st_xp70_rproc *xp70_rproc);
> +
> +#endif

Regards,
Bjorn


From robh at kernel.org  Wed May 25 10:24:09 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 25 May 2016 12:24:09 -0500
Subject: [PATCH 02/11] drivers: clk: st: Add clock propagation for audio
 clocks
In-Reply-To: <1463560892-7209-3-git-send-email-gabriel.fernandez@linaro.org>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
 <1463560892-7209-3-git-send-email-gabriel.fernandez@linaro.org>
Message-ID: <20160525172409.GA27913@rob-hp-laptop>

On Wed, May 18, 2016 at 10:41:23AM +0200, Gabriel Fernandez wrote:
> This patch allows fine tuning of the quads FS for audio clocks
> accuracy.
> 
> Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
> Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
> ---
>  .../devicetree/bindings/clock/st/st,flexgen.txt    |  1 +
>  drivers/clk/st/clk-flexgen.c                       | 24 ++++++++++++++++++++++
>  2 files changed, 25 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
> index b7ee5c7..15b33c7 100644
> --- a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
> +++ b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
> @@ -60,6 +60,7 @@ This binding uses the common clock binding[2].
>  Required properties:
>  - compatible : shall be:
>    "st,flexgen"
> +  "st,stih407-clkgend0", "st,flexgen" (enable clock propagation on parent)

What do "d0" and "d2" refer to?

This seems to indicate you have too much clock detail in the DT (with 
individual clocks described) or not enough with genericish compatible 
strings. What happens for the mext clock you need to adjust the flags 
on? You should be able to make these adjustments without DT updates. 
Perhaps you need a wider fixing of clock compatible strings.

Rob


From bjorn.andersson at linaro.org  Wed May 25 10:27:23 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Wed, 25 May 2016 10:27:23 -0700
Subject: [PATCH v4 06/18] dmaengine: st_fdma: Add STMicroelectronics FDMA
 engine driver support
In-Reply-To: <1464192412-16386-8-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
 <1464192412-16386-8-git-send-email-peter.griffin@linaro.org>
Message-ID: <20160525172723.GU1256@tuxbot>

On Wed 25 May 09:06 PDT 2016, Peter Griffin wrote:

> diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c
[..]
> +
> +static int st_fdma_alloc_chan_res(struct dma_chan *chan)
> +{
> +	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
> +	int ret;
> +
> +	/* Create the dma pool for descriptor allocation */
> +	fchan->node_pool = dma_pool_create(dev_name(&chan->dev->device),
> +					    fchan->fdev->dev,
> +					    sizeof(struct st_fdma_hw_node),
> +					    __alignof__(struct st_fdma_hw_node),
> +					    0);
> +
> +	if (!fchan->node_pool) {
> +		dev_err(fchan->fdev->dev, "unable to allocate desc pool\n");
> +		return -ENOMEM;
> +	}
> +
> +
> +	ret = rproc_boot(fchan->fdev->rproc);
> +	if (ret) {
> +		dev_err(fchan->fdev->dev, "rproc_boot failed\n");

rproc_boot(), rproc_fw_boot() and xp70_rproc_start() has already given
you specific error messages; drop this generic message.

Don't you want to destroy the dma_pool if this happens?

> +		return ret;
> +	}
> +
> +	dev_dbg(fchan->fdev->dev, "alloc ch_id:%d type:%d\n",
> +		fchan->vchan.chan.chan_id, fchan->cfg.type);
> +
> +	return 0;
> +}
> +
[..]
> +
> +static const struct st_fdma_driverdata fdma_mpe31_stih407_11 = {
> +	.name = "STiH407",
> +	.id = 0,
> +};
> +
> +static const struct st_fdma_driverdata fdma_mpe31_stih407_12 = {
> +	.name = "STiH407",
> +	.id = 1,
> +};
> +
> +static const struct st_fdma_driverdata fdma_mpe31_stih407_13 = {
> +	.name = "STiH407",
> +	.id = 2,
> +};
> +
> +static const struct of_device_id st_fdma_match[] = {
> +	{ .compatible = "st,stih407-fdma-mpe31-11"
> +	  , .data = &fdma_mpe31_stih407_11 },
> +	{ .compatible = "st,stih407-fdma-mpe31-12"
> +	  , .data = &fdma_mpe31_stih407_12 },
> +	{ .compatible = "st,stih407-fdma-mpe31-13"
> +	  , .data = &fdma_mpe31_stih407_13 },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, st_fdma_match);
> +
> +static int st_fdma_parse_dt(struct platform_device *pdev,
> +			const struct st_fdma_driverdata *drvdata,
> +			struct st_fdma_dev *fdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	int ret;
> +
> +	if (!np)
> +		goto err;

ret is left uninitialized here. Also as no error handling is done, just
return your error directly.

> +
> +	ret = of_property_read_u32(np, "dma-channels", &fdev->nr_channels);
> +	if (ret)
> +		goto err;
> +
> +	snprintf(fdev->fw_name, FW_NAME_SIZE, "fdma_%s_%d.elf",
> +		drvdata->name, drvdata->id);
> +
> +err:
> +	return ret;
> +}
> +#define FDMA_DMA_BUSWIDTHS	(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
> +				 BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
> +				 BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
> +				 BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
> +
> +static int st_fdma_probe(struct platform_device *pdev)
> +{
> +	struct st_fdma_dev *fdev;
> +	const struct of_device_id *match;
> +	struct device_node *np = pdev->dev.of_node;
> +	const struct st_fdma_driverdata *drvdata;
> +	int ret, i;
> +
> +	match = of_match_device((st_fdma_match), &pdev->dev);
> +	if (!match || !match->data) {
> +		dev_err(&pdev->dev, "No device match found\n");
> +		return -ENODEV;
> +	}
> +
> +	drvdata = match->data;

Use of_device_get_match_data() instead. This also allows you to keep the
of_match_table and driverdata at the end of the file.

[..]
> +
> +	fdev->rproc = xp70_rproc_alloc(pdev, fdev->fw_name);
> +	if (!fdev->rproc) {
> +		dev_err(&pdev->dev, "xp70_rproc_init failed\n");

All (non-development) error paths in xp70_rproc_alloc() will have
already printed a more specific error message, so no need to print
another generic on here.

> +		ret = PTR_ERR(fdev->rproc);
> +		goto err;
> +	}
> +

Regards,
Bjorn


From linux at armlinux.org.uk  Wed May 25 10:27:07 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Wed, 25 May 2016 18:27:07 +0100
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <20160525152255.GH5996@e104818-lin.cambridge.arm.com>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
 <20160524113727.GD25374@leverpostej> <574446B9.8040105@huawei.com>
 <20160524151235.GA11605@leverpostej>
 <20160525152255.GH5996@e104818-lin.cambridge.arm.com>
Message-ID: <20160525172705.GD19428@n2100.arm.linux.org.uk>

On Wed, May 25, 2016 at 04:22:55PM +0100, Catalin Marinas wrote:
> That's when we realised that the CoW problem no longer exists for
> non-aliasing VIPT caches. However, the I-cache counterpart 6060e8df5178
> has not been reverted.

I think I mostly agree, except for reverting 6060e8df5178, which I don't
think would be correct.  That reintroduces the possibility of flushing
the I-cache twice in that path, once for aliasing vipt dcaches, and again
for asid tagged vivt icaches.  I'd rather have the code structured so we
only do this once.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From robh at kernel.org  Wed May 25 10:32:46 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 25 May 2016 12:32:46 -0500
Subject: [RESEND PATCH v2] ASoC: rockchip: Add machine driver for
 MAX98357A/RT5514/DA7219
In-Reply-To: <1464053774-15914-1-git-send-email-zhengxing@rock-chips.com>
References: <1464053774-15914-1-git-send-email-zhengxing@rock-chips.com>
Message-ID: <20160525173246.GA5125@rob-hp-laptop>

On Tue, May 24, 2016 at 09:36:14AM +0800, Xing Zheng wrote:
> There are multi codec devices on the RK3399 platform, we can use
> this patch support and control these codecs.
> 
> Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
> ---
> 
> Changes in v2:
> - use the FS 256 to set mclks of the max98357a and rt5514 danamically
> - add more sample rate for da7219
> 
>  .../sound/rockchip-max98357a-rt5514-da7219.txt     |   15 +
>  sound/soc/rockchip/Kconfig                         |   11 +
>  sound/soc/rockchip/Makefile                        |    2 +
>  .../rockchip/rockchip_max98357a_rt5514_da7219.c    |  333 ++++++++++++++++++++
>  4 files changed, 361 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
>  create mode 100644 sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c
> 
> diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt b/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
> new file mode 100644
> index 0000000..5928384
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
> @@ -0,0 +1,15 @@
> +ROCKCHIP with MAX98357A/RT5514/DA7219 codecs
> +
> +Required properties:
> +- compatible: "rockchip,rockchip-sound"

This is generic, but the binding seems to be very specific to only 3 
specific codecs. Listing all 3 codecs seems a bit strange. Perhaps a 
name related to the board name would be better.

> +- rockchip,cpu: The phandle of the Rockchip I2S controller that's
> +  connected to the codecs

What's the size? always 3?

> +- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs

Please make the size and ordering clear.

> +
> +Example:
> +
> +sound {
> +	compatible = "rockchip,rockchip-sound";
> +	rockchip,cpu = <&i2s0 &i2s0 &i2s1>;
> +	rockchip,codec = <&max98357a &headsetcodec &codec>;
> +};


From robh at kernel.org  Wed May 25 10:34:19 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 25 May 2016 12:34:19 -0500
Subject: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
In-Reply-To: <C89496FEAE474D468F30D558A9468D9F26CED772@XAP-PVEXMBX01.xlnx.xilinx.com>
References: <1464067268-35299-1-git-send-email-navam@xilinx.com>
 <14123451.MsNvJvqaJX@wuerfel>
 <C89496FEAE474D468F30D558A9468D9F26CED772@XAP-PVEXMBX01.xlnx.xilinx.com>
Message-ID: <20160525173419.GA7510@rob-hp-laptop>

On Tue, May 24, 2016 at 11:47:31AM +0000, Nava kishore Manne wrote:
> 
> 
> > -----Original Message-----
> > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > Sent: Tuesday, May 24, 2016 2:21 PM
> > To: Nava kishore Manne <navam at xilinx.com>
> > Cc: robh+dt at kernel.org; pawel.moll at arm.com; mark.rutland at arm.com;
> > ijc+devicetree at hellion.org.uk; galak at codeaurora.org; Michal Simek
> > <michals at xilinx.com>; Soren Brinkmann <sorenb at xilinx.com>;
> > balbi at ti.com; gregkh at linuxfoundation.org; Hyun Kwon
> > <hyunk at xilinx.com>; Nava kishore Manne <navam at xilinx.com>; Radhey
> > Shyam Pandey <radheys at xilinx.com>; devicetree at vger.kernel.org; linux-
> > arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > Subject: Re: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
> > 
> > On Tuesday, May 24, 2016 10:51:08 AM CEST Nava kishore Manne wrote:
> > > diff --git a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> > > b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> > > index 47b4e39..09df757 100644
> > > --- a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> > > +++ b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> > > @@ -1,18 +1,23 @@
> > >  Xilinx USB2 device controller
> > >
> > >  Required properties:
> > > -- compatible		: Should be "xlnx,usb2-device-4.00.a"
> > > +- compatible		: Should be "xlnx,usb2-device-4.00.a" or
> > > +			  "xlnx,usb2-device-5.00"
> > >  - reg			: Physical base address and size of the USB2
> > >  			  device registers map.
> > >  - interrupts		: Should contain single irq line of USB2 device
> > >  			  controller
> > >  - xlnx,has-builtin-dma	: if DMA is included
> > > +- dma-ranges		: Should be as the following
> > > +			  <child-bus-address, parent-bus-address, length>
> > 
> > A USB host should not have any children that are DMA capable, I think, so
> > this property doesn't make sense here. It should be part of the parent bus.
> > 
> Will send next version (v4) by removing this property from the DT.
> 
> > > +- xlnx,addrwidth	: Should be the dma addressing size in bits(ex: 64
> > bits)
> > 
> > I'm still unconvinced about the property definition here. What are the
> > possible options for the IP block? I don't think I ever saw a reply from you to
> > my earlier questions.
> > 
> 
> Sorry Let me clearly explain
> 
> From the IP version 5.0 onwards The IP support both 32-bit and 64-bit addressing.
> But the older version of the IP's supports only 32-bit addressing.
> 
> This addrwidth property differentiates the address width for the new IP (I mean 5.0 version on wards)
> For older IP it will be always 32-bit.

Then I think you should have a simple boolean property for 64-bit 
configuration.


From ard.biesheuvel at linaro.org  Wed May 25 11:23:35 2016
From: ard.biesheuvel at linaro.org (Ard Biesheuvel)
Date: Wed, 25 May 2016 20:23:35 +0200
Subject: [PATCH] arm64/efi: remove spurious WARN_ON for !4K kernels
In-Reply-To: <20160525161207.GD30956@leverpostej>
References: <1464189116-30898-1-git-send-email-mark.rutland@arm.com>
 <BA565A9C-8CC0-42E4-9821-7941852F835A@linaro.org>
 <20160525161207.GD30956@leverpostej>
Message-ID: <CAKv+Gu94GLWUJBCtNUDb4Jak3KL0-MGkUfk82fZ5UdwWH60P_w@mail.gmail.com>

On 25 May 2016 at 18:12, Mark Rutland <mark.rutland at arm.com> wrote:
> On Wed, May 25, 2016 at 05:23:01PM +0200, Ard Biesheuvel wrote:
>>
>>
>> > On 25 mei 2016, at 17:11, Mark Rutland <mark.rutland at arm.com> wrote:
>> >
>> > Since commit 1fd55a9a09b0293a ("arm64/efi: Apply strict permissions to
>> > UEFI Runtime Services regions"), booting a !4K page kernel results in a
>> > boot-time splat on some systems, due to to a WARN_ONCE added in that
>> > commit which fires if the base address of an EFI memory descriptor is
>> > not aligned to the kernel page size (which might be 4K, 16K, or 64K).
>> >
>> > On page 38 of the UEFI 2.6 specification it is stated:
>> >
>> >    If a 64KiB physical page contains any 4KiB page with any of the
>> >    following types listed below, then all 4KiB pages in the 64KiB
>> >    page must use identical ARM Memory Page Attributes (as described
>> >    in Table 8):
>> >    ? EfiRuntimeServicesCode
>> >    ? EfiRuntimeServicesData
>> >    ? EfiReserved
>> >    ? EfiACPIMemoryNVS
>> >    Mixed attribute mappings within a larger page are not allowed.
>> >
>>
>> The same section mentions that the ro/xp etc attributes are unused on
>> arm, so if we go by the letter here, we need to remove those memory
>> protection features entirely. So a spec update is clearly in order
>> here.
>
> Yes; that definitely needs fixing.
>
> FWIW, I don't think that matters in this case (assuming the usual EFI
> memory desc dump stuff prints those).
>
> My memory map (and the remap triggering the WARN_ONCE) look like:
>
> [    0.000000] efi: Getting EFI parameters from FDT:
> [    0.000000] efi:   System Table: 0x00000083ff34bf18
> [    0.000000] efi:   MemMap Address: 0x00000083fcefd618
> [    0.000000] efi:   MemMap Size: 0x00000540
> [    0.000000] efi:   MemMap Desc. Size: 0x00000030
> [    0.000000] efi:   MemMap Desc. Version: 0x00000001
> [    0.000000] efi: EFI v2.40 by American Megatrends
> [    0.000000] efi:  ACPI 2.0=0x83ff1c3000  SMBIOS 3.0=0x83ff347798
> [    0.000000] efi: Processing EFI memory map:
> [    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x008001e80000-0x008001ffffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x008002000000-0x008002ddffff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x008002de0000-0x00801fdfffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x00801fe00000-0x00801fe0ffff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x00801fe10000-0x00801fffbfff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x00801fffc000-0x00801fffffff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x008020000000-0x0083f0ffffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x0083f1000000-0x0083f101ffff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x0083f1020000-0x0083fb542fff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x0083fb543000-0x0083fc2a2fff [Loader Code        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x0083fc2a3000-0x0083fcefcfff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x0083fcefd000-0x0083fcefefff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x0083fceff000-0x0083fd01afff [Loader Code        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x0083fd01b000-0x0083fea67fff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x0083fea68000-0x0083febd3fff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x0083febd4000-0x0083ff186fff [Boot Code          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x0083ff187000-0x0083ff1b6fff [Reserved           |   |  |  |  |  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0083ff1b7000-0x0083ff1c4fff [ACPI Reclaim Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0083ff1c5000-0x0083ff20ffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x0083ff210000-0x0083ff224fff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] efi:   0x0083ff225000-0x0083ff226fff [ACPI Memory NVS    |   |  |  |  |  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0083ff227000-0x0083ff34bfff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*

OK, so how is this expected to work then, with the regions described
above? Neither are covered by the linear mapping, and both have all of
{WB,WT,WC,UC} set, which means that each region can be mapped by the
OS as any of those types. I don't know which type we use for this
particular ACPI Memory NVS region, but it could be any of those, while
the runtime data regions are mapped as writeback cacheable in the EFI
page tables. So while the spec needs to be updated, I think the de
facto conclusion is that the only way we can do this safely is to
either force 64 KB alignment, or -as a workaround- ensure that regions
that share a 64 KB page frame are limited to the same attributes in
the OS view of the UEFI memory map.


> [    0.000000] efi:   0x0083ff34c000-0x0083ffe42fff [Runtime Code       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] efi:   0x0083ffe43000-0x0083ffffffff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> ...
> [    0.079000] Remapping and enabling EFI services.
> [    0.083677]   EFI remap 0x00000000e1050000 => 0000000020000000
> [    0.089551]   EFI remap 0x00000000e1300000 => 0000000020010000
> [    0.095421]   EFI remap 0x00000000e8200000 => 0000000020020000
> [    0.101324]   EFI remap 0x0000008000000000 => 0000000020200000
> [    0.107192] UEFI Runtime regions are not aligned to 64 KB -- buggy firmware?
> [    0.114116] ------------[ cut here ]------------
> [    0.118941] WARNING: CPU: 0 PID: 1 at arch/arm64/kernel/efi.c:34 efi_create_mapping+0x50/0xdc
> [    0.127524] Modules linked in:
> [    0.130592]
> [    0.132083] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.6.0-next-20160525 #6
> [    0.139180] Hardware name: AMD Seattle (Rev.B0) Development Board (Overdrive) (DT)
> [    0.146805] task: ffff8003c01e0000 ti: ffff8003c0200000 task.ti: ffff8003c0200000
> [    0.154338] PC is at efi_create_mapping+0x50/0xdc
> [    0.159071] LR is at efi_create_mapping+0x50/0xdc
> [    0.163800] pc : [<ffff000008b23f34>] lr : [<ffff000008b23f34>] pstate: 60000245
> [    0.171248] sp : ffff8003c0203d60
> [    0.174579] x29: ffff8003c0203d60 x28: 0000000000000000
> [    0.179925] x27: 0000000000000000 x26: 0000000000000000
> [    0.185269] x25: 0000000000000000 x24: ffff000008ca7be0
> [    0.190616] x23: ffff000008d5b000 x22: ffff000008a76ff8
> [    0.195959] x21: ffff000008c45000 x20: ffff000008ca7be0
> [    0.201303] x19: ffff8003fcefdac8 x18: 0000000000000006
> [    0.206649] x17: 0000000000000007 x16: 0000000000000001
> [    0.211992] x15: ffff000008d15c95 x14: 3f657261776d7269
> [    0.217337] x13: 6620796767756220 x12: 0000000005f5e0ff
> [    0.222683] x11: 206f742064656e67 x10: 000000000001a2b8
> [    0.228026] x9 : ffff8003c0203b60 x8 : 000000000000006c
> [    0.233368] x7 : 2d2d20424b203436 x6 : ffff000008d15cd7
> [    0.238711] x5 : 0000000000000041 x4 : 0000000000000000
> [    0.244055] x3 : 0000000000000000 x2 : 00000000000002e6
> [    0.249439] x1 : ffff8003c0200000 x0 : 0000000000000040
> [    0.254784]
> [    0.256279] ---[ end trace e9947b6ce71b94cd ]---
> [    0.260922] Call trace:
> [    0.263376] Exception stack(0xffff8003c0203ba0 to 0xffff8003c0203cc0)
> [    0.269860] 3ba0: ffff8003fcefdac8 ffff000008ca7be0 ffff8003c0203d60 ffff000008b23f34
> [    0.277741] 3bc0: ffff8003c0203be0 ffff000008a08ac0 0000000000000040 0000000000000001
> [    0.285624] 3be0: ffff8003c0203c80 ffff0000080f42a8 ffff8003fcefdac8 ffff000008ca7be0
> [    0.293508] 3c00: ffff000008c45000 ffff000008a76ff8 ffff000008d5b000 ffff000008ca7be0
> [    0.301391] 3c20: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> [    0.309271] 3c40: 0000000000000040 ffff8003c0200000 00000000000002e6 0000000000000000
> [    0.317154] 3c60: 0000000000000000 0000000000000041 ffff000008d15cd7 2d2d20424b203436
> [    0.325037] 3c80: 000000000000006c ffff8003c0203b60 000000000001a2b8 206f742064656e67
> [    0.332922] 3ca0: 0000000005f5e0ff 6620796767756220 3f657261776d7269 ffff000008d15c95
> [    0.340805] [<ffff000008b23f34>] efi_create_mapping+0x50/0xdc
> [    0.346651] [<ffff000008b530e8>] arm_enable_runtime_services+0x130/0x214
> [    0.353400] [<ffff000008081990>] do_one_initcall+0x38/0x128
> [    0.359009] [<ffff000008b20be4>] kernel_init_freeable+0x84/0x1f0
> [    0.365054] [<ffff0000087a9b58>] kernel_init+0x10/0x100
> [    0.370311] [<ffff000008084ac0>] ret_from_fork+0x10/0x50
> [    0.375661]   EFI remap 0x00000083ff227000 => 0000000022087000
> [    0.381544]   EFI remap 0x00000083ff34c000 => 00000000221ac000
>
> Thanks,
> Mark.


From arnd at arndb.de  Wed May 25 11:29:40 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 25 May 2016 20:29:40 +0200
Subject: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
In-Reply-To: <20160525173419.GA7510@rob-hp-laptop>
References: <1464067268-35299-1-git-send-email-navam@xilinx.com>
 <C89496FEAE474D468F30D558A9468D9F26CED772@XAP-PVEXMBX01.xlnx.xilinx.com>
 <20160525173419.GA7510@rob-hp-laptop>
Message-ID: <5392766.vCAWrASuOA@wuerfel>

On Wednesday, May 25, 2016 12:34:19 PM CEST Rob Herring wrote:
> On Tue, May 24, 2016 at 11:47:31AM +0000, Nava kishore Manne wrote:
> > 
> > 
> > > -----Original Message-----
> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> > > Sent: Tuesday, May 24, 2016 2:21 PM
> > > To: Nava kishore Manne <navam at xilinx.com>
> > > Cc: robh+dt at kernel.org; pawel.moll at arm.com; mark.rutland at arm.com;
> > > ijc+devicetree at hellion.org.uk; galak at codeaurora.org; Michal Simek
> > > <michals at xilinx.com>; Soren Brinkmann <sorenb at xilinx.com>;
> > > balbi at ti.com; gregkh at linuxfoundation.org; Hyun Kwon
> > > <hyunk at xilinx.com>; Nava kishore Manne <navam at xilinx.com>; Radhey
> > > Shyam Pandey <radheys at xilinx.com>; devicetree at vger.kernel.org; linux-
> > > arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> > > Subject: Re: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
> > > 
> > > On Tuesday, May 24, 2016 10:51:08 AM CEST Nava kishore Manne wrote:
> > > > diff --git a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> > > > b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> > > > index 47b4e39..09df757 100644
> > > > --- a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> > > > +++ b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> > > > @@ -1,18 +1,23 @@
> > > >  Xilinx USB2 device controller
> > > >
> > > >  Required properties:
> > > > -- compatible             : Should be "xlnx,usb2-device-4.00.a"
> > > > +- compatible             : Should be "xlnx,usb2-device-4.00.a" or
> > > > +                   "xlnx,usb2-device-5.00"
> > > >  - reg                    : Physical base address and size of the USB2
> > > >                     device registers map.
> > > >  - interrupts             : Should contain single irq line of USB2 device
> > > >                     controller
> > > >  - xlnx,has-builtin-dma   : if DMA is included
> > > > +- dma-ranges             : Should be as the following
> > > > +                   <child-bus-address, parent-bus-address, length>
> > > 
> > > A USB host should not have any children that are DMA capable, I think, so
> > > this property doesn't make sense here. It should be part of the parent bus.
> > > 
> > Will send next version (v4) by removing this property from the DT.
> > 
> > > > +- xlnx,addrwidth : Should be the dma addressing size in bits(ex: 64
> > > bits)
> > > 
> > > I'm still unconvinced about the property definition here. What are the
> > > possible options for the IP block? I don't think I ever saw a reply from you to
> > > my earlier questions.
> > > 
> > 
> > Sorry Let me clearly explain
> > 
> > From the IP version 5.0 onwards The IP support both 32-bit and 64-bit addressing.
> > But the older version of the IP's supports only 32-bit addressing.
> > 
> > This addrwidth property differentiates the address width for the new IP (I mean 5.0 version on wards)
> > For older IP it will be always 32-bit.
> 
> Then I think you should have a simple boolean property for 64-bit 
> configuration.

I think matching on the version number is slightly better, as we have the version
already and it identifies whether the register exists.

Having a boolean property of course works as well, it just duplicates that
information.

	Arnd


From robh at kernel.org  Wed May 25 11:46:12 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 25 May 2016 13:46:12 -0500
Subject: [PATCH 1/3] dt-bindings: add bindings documentation for PDC
 driver.
In-Reply-To: <1464113250-15629-2-git-send-email-rob.rice@broadcom.com>
References: <1464113250-15629-1-git-send-email-rob.rice@broadcom.com>
 <1464113250-15629-2-git-send-email-rob.rice@broadcom.com>
Message-ID: <20160525184612.GA12110@rob-hp-laptop>

On Tue, May 24, 2016 at 02:07:28PM -0400, Rob Rice wrote:
> From: Rob Rice <rrice at broadcom.com>
> 
> Add the device tree binding documentation for the PDC hardware
> in Broadcom iProc SoCs.
> 
> Signed-off-by: Rob Rice <rob.rice at broadcom.com>
> Reviewed-by: Ray Jui <ray.jui at broadcom.com>
> Reviewed-by: Anup Patel <anup.patel at broadcom.com>
> Reviewed-by: Scott Branden <scott.branden at broadcom.com>
> ---
>  .../bindings/mailbox/brcm,iproc-pdc-mbox.txt       | 23 ++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/brcm,iproc-pdc-mbox.txt

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


From robh at kernel.org  Wed May 25 11:53:32 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 25 May 2016 13:53:32 -0500
Subject: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
In-Reply-To: <5392766.vCAWrASuOA@wuerfel>
References: <1464067268-35299-1-git-send-email-navam@xilinx.com>
 <C89496FEAE474D468F30D558A9468D9F26CED772@XAP-PVEXMBX01.xlnx.xilinx.com>
 <20160525173419.GA7510@rob-hp-laptop> <5392766.vCAWrASuOA@wuerfel>
Message-ID: <CAL_Jsq+VL6jjo5QLwnsC8rEfgP4KN5hCSB7QicWWN-uvZU0GHw@mail.gmail.com>

On Wed, May 25, 2016 at 1:29 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> On Wednesday, May 25, 2016 12:34:19 PM CEST Rob Herring wrote:
>> On Tue, May 24, 2016 at 11:47:31AM +0000, Nava kishore Manne wrote:
>> >
>> >
>> > > -----Original Message-----
>> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
>> > > Sent: Tuesday, May 24, 2016 2:21 PM
>> > > To: Nava kishore Manne <navam at xilinx.com>
>> > > Cc: robh+dt at kernel.org; pawel.moll at arm.com; mark.rutland at arm.com;
>> > > ijc+devicetree at hellion.org.uk; galak at codeaurora.org; Michal Simek
>> > > <michals at xilinx.com>; Soren Brinkmann <sorenb at xilinx.com>;
>> > > balbi at ti.com; gregkh at linuxfoundation.org; Hyun Kwon
>> > > <hyunk at xilinx.com>; Nava kishore Manne <navam at xilinx.com>; Radhey
>> > > Shyam Pandey <radheys at xilinx.com>; devicetree at vger.kernel.org; linux-
>> > > arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
>> > > Subject: Re: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
>> > >
>> > > On Tuesday, May 24, 2016 10:51:08 AM CEST Nava kishore Manne wrote:
>> > > > diff --git a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
>> > > > b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
>> > > > index 47b4e39..09df757 100644
>> > > > --- a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
>> > > > +++ b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
>> > > > @@ -1,18 +1,23 @@
>> > > >  Xilinx USB2 device controller
>> > > >
>> > > >  Required properties:
>> > > > -- compatible             : Should be "xlnx,usb2-device-4.00.a"
>> > > > +- compatible             : Should be "xlnx,usb2-device-4.00.a" or
>> > > > +                   "xlnx,usb2-device-5.00"
>> > > >  - reg                    : Physical base address and size of the USB2
>> > > >                     device registers map.
>> > > >  - interrupts             : Should contain single irq line of USB2 device
>> > > >                     controller
>> > > >  - xlnx,has-builtin-dma   : if DMA is included
>> > > > +- dma-ranges             : Should be as the following
>> > > > +                   <child-bus-address, parent-bus-address, length>
>> > >
>> > > A USB host should not have any children that are DMA capable, I think, so
>> > > this property doesn't make sense here. It should be part of the parent bus.
>> > >
>> > Will send next version (v4) by removing this property from the DT.
>> >
>> > > > +- xlnx,addrwidth : Should be the dma addressing size in bits(ex: 64
>> > > bits)
>> > >
>> > > I'm still unconvinced about the property definition here. What are the
>> > > possible options for the IP block? I don't think I ever saw a reply from you to
>> > > my earlier questions.
>> > >
>> >
>> > Sorry Let me clearly explain
>> >
>> > From the IP version 5.0 onwards The IP support both 32-bit and 64-bit addressing.
>> > But the older version of the IP's supports only 32-bit addressing.
>> >
>> > This addrwidth property differentiates the address width for the new IP (I mean 5.0 version on wards)
>> > For older IP it will be always 32-bit.
>>
>> Then I think you should have a simple boolean property for 64-bit
>> configuration.
>
> I think matching on the version number is slightly better, as we have the version
> already and it identifies whether the register exists.
>
> Having a boolean property of course works as well, it just duplicates that
> information.

It doesn't because v5.0 h/w can be configured for either 32 or 64-bit
mode. Normally, we would encode configuration into the compatible
strings, but I view FPGA based blocks to be an exception. Of course,
since they can just "fix the h/w" we could just require h/w version
and feature registers. ;)

Rob


From arnd at arndb.de  Wed May 25 11:54:59 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 25 May 2016 20:54:59 +0200
Subject: [PATCH] phy: exynos-mipi-video: avoid uninitialized variable use
In-Reply-To: <20160511185155.GB8265@kozik-lap>
References: <1462971012-562097-1-git-send-email-arnd@arndb.de>
 <20160511185155.GB8265@kozik-lap>
Message-ID: <14219690.YQPrXjp7cP@wuerfel>

On Wednesday, May 11, 2016 8:51:55 PM CEST Krzysztof Kozlowski wrote:
> On Wed, May 11, 2016 at 02:49:53PM +0200, Arnd Bergmann wrote:
> > A rework of the exynos-mipi-video driver caused a warning
> > about the new __set_phy_state function potentially accessing
> > a variable before its initialization:
> > 
> > drivers/phy/phy-exynos-mipi-video.c: In function '__set_phy_state':
> > drivers/phy/phy-exynos-mipi-video.c:238:13: error: 'val' may be used uninitialized in this function [-Werror=maybe-uninitialized]
> >   return val & data->resetn_val;
> >          ~~~~^~~~~~~~~~~~~~~~~~
> > drivers/phy/phy-exynos-mipi-video.c:235:6: note: 'val' was declared here
> >   u32 val;
> > 
> > The failure scenario here is the offset passed into a the
> > stub regmap_read() function that does not modify its output,
> > however regmap_read() can also fail for other reasons, so
> > adding error handling (in this case, returning zero from
> > is_running) seems the best solution.
> > 
> > Note that this warning showed up with the ARM s5pv210_defconfig,
> > indicating that we most likely want to either enable CONFIG_REGMAP
> > in that defconfig as well, or disable the phy-exynos-mipi-video
> > driver.
> > 
> > Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> > Fixes: 97a3042f7616 ("phy: exynos-mipi-video: Rewrite handling of phy registers")
> > ---
> >  drivers/phy/phy-exynos-mipi-video.c | 6 +++++-
> >  1 file changed, 5 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
> > index cc093ebfda94..8b851f718123 100644
> > --- a/drivers/phy/phy-exynos-mipi-video.c
> > +++ b/drivers/phy/phy-exynos-mipi-video.c
> > @@ -233,8 +233,12 @@ static inline int __is_running(const struct exynos_mipi_phy_desc *data,
> >                       struct exynos_mipi_video_phy *state)
> >  {
> >       u32 val;
> 
> Other way would be to initialize val=0 since there is no real error code
> returned. Anyway:
> 
> Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>


This hasn't made it into linux-next yet, any chance we'll see it in -rc1 or -rc2?

	Arnd


From bjorn.andersson at linaro.org  Wed May 25 12:00:58 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Wed, 25 May 2016 12:00:58 -0700
Subject: [PATCH v2 4/9] remoteproc: Introduce Qualcomm WCNSS firmware
 loader
In-Reply-To: <574588E2.60506@linaro.org>
References: <1459222625-11440-1-git-send-email-bjorn.andersson@linaro.org>
 <1459222625-11440-5-git-send-email-bjorn.andersson@linaro.org>
 <574588E2.60506@linaro.org>
Message-ID: <20160525190058.GV1256@tuxbot>

On Wed 25 May 04:13 PDT 2016, Stanimir Varbanov wrote:

> On 03/29/2016 06:37 AM, Bjorn Andersson wrote:
> > From: Bjorn Andersson <bjorn.andersson at sonymobile.com>
> > 
> > This introduces the peripheral image loader, for loading WCNSS firmware
> > and boot the core on e.g. MSM8974. The firmware is verified and booted
> > with the help of the Peripheral Authentication System (PAS) in
> > TrustZone.
> > 
> > Signed-off-by: Bjorn Andersson <bjorn.andersson at sonymobile.com>
> > Signed-off-by: Bjorn Andersson <bjorn.andersson at linaro.org>
> > ---
> > 
> > Changes since v1:
> > - Split iris definition into separate driver/dt-node
> > - Move constants from DT to code
> > - Make stop-state and some of interrupts optional to properly work on 8064
> > - Cleaned up and made mdt loader support relocation, which is needed on 8016.
> > 
> >  drivers/remoteproc/Kconfig           |  12 +
> >  drivers/remoteproc/Makefile          |   2 +
> >  drivers/remoteproc/qcom_mdt_loader.c | 172 +++++++++++
> >  drivers/remoteproc/qcom_mdt_loader.h |   7 +
> >  drivers/remoteproc/qcom_wcnss.c      | 579 +++++++++++++++++++++++++++++++++++
> >  drivers/remoteproc/qcom_wcnss.h      |  22 ++
> >  drivers/remoteproc/qcom_wcnss_iris.c | 185 +++++++++++
> >  7 files changed, 979 insertions(+)
> >  create mode 100644 drivers/remoteproc/qcom_mdt_loader.c
> >  create mode 100644 drivers/remoteproc/qcom_mdt_loader.h
> >  create mode 100644 drivers/remoteproc/qcom_wcnss.c
> >  create mode 100644 drivers/remoteproc/qcom_wcnss.h
> >  create mode 100644 drivers/remoteproc/qcom_wcnss_iris.c
> > 
> 
> <cut>
> 
> > +
> > +static int wcnss_remove(struct platform_device *pdev)
> > +{
> > +	struct qcom_wcnss *wcnss = platform_get_drvdata(pdev);
> > +
> > +	of_platform_depopulate(&pdev->dev);
> > +
> > +	qcom_smem_state_put(wcnss->state);
> > +	rproc_put(wcnss->rproc);
> 
> might be need to call rproc_del() too ?
> 

You're correct. Thanks for having a look!

Regards,
Bjorn


From robh at kernel.org  Wed May 25 12:08:29 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 25 May 2016 14:08:29 -0500
Subject: [PATCH 2/2] ARM: at91: Add DT support for Olimex SAM9-L9260 board.
In-Reply-To: <1464164106-28359-2-git-send-email-raashidmuhammed@zilogic.com>
References: <1464164106-28359-1-git-send-email-raashidmuhammed@zilogic.com>
 <1464164106-28359-2-git-send-email-raashidmuhammed@zilogic.com>
Message-ID: <20160525190828.GA22435@rob-hp-laptop>

On Wed, May 25, 2016 at 01:45:06PM +0530, Raashid Muhammed wrote:
> From: Raashid Muhammed <raashidmuhammed at zilogic.com>
> 
> sam9-l9260 is a low cost board designed by Olimex.
> 
> More information is available at:
> https://www.olimex.com/Products/ARM/Atmel/SAM9-L9260/
> 
> Signed-off-by: Raashid Muhammed <raashidmuhammed at zilogic.com>
> Reviewed-by: Vijay Kumar B. <vijaykumar at bravegnu.org>
> ---
>  Documentation/devicetree/bindings/arm/olimex.txt |   8 +-
>  arch/arm/boot/dts/Makefile                       |   1 +
>  arch/arm/boot/dts/at91-sam9_l9260.dts            | 115 +++++++++++++++++++++++
>  3 files changed, 122 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arm/boot/dts/at91-sam9_l9260.dts
> 
> diff --git a/Documentation/devicetree/bindings/arm/olimex.txt b/Documentation/devicetree/bindings/arm/olimex.txt
> index 007fb5c..d726aec 100644
> --- a/Documentation/devicetree/bindings/arm/olimex.txt
> +++ b/Documentation/devicetree/bindings/arm/olimex.txt
> @@ -1,5 +1,9 @@
> -Olimex i.MX Platforms Device Tree Bindings
> -------------------------------------------
> +Olimex Device Tree Bindings
> +---------------------------
> +
> +SAM9-L9260 Board
> +Required root node properties:
> +    - compatible = "olimex,sam9-l9260", "atmel,at91sam9260";
>  
>  i.MX23 Olinuxino Low Cost Board
>  Required root node properties:
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index 0f89d87..d27f09d 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -19,6 +19,7 @@ dtb-$(CONFIG_SOC_SAM_V4_V5) += \
>  	usb_a9260.dtb \
>  	at91sam9261ek.dtb \
>  	at91sam9263ek.dtb \
> +	at91-sam9_l9260.dtb \
>  	tny_a9263.dtb \
>  	usb_a9263.dtb \
>  	at91-foxg20.dtb \
> diff --git a/arch/arm/boot/dts/at91-sam9_l9260.dts b/arch/arm/boot/dts/at91-sam9_l9260.dts
> new file mode 100644
> index 0000000..e2da9b906
> --- /dev/null
> +++ b/arch/arm/boot/dts/at91-sam9_l9260.dts
> @@ -0,0 +1,115 @@
> +/*
> + * at91-sam9_l9260.dts - Device Tree file for Olimex SAM9-L9260 board
> + *
> + *  Copyright (C) 2016 Raashid Muhammed <raashidmuhammed at zilogic.com>
> + *
> + * Licensed under GPLv2 or later.
> + */
> +/dts-v1/;
> +#include "at91sam9260.dtsi"
> +
> +/ {
> +	model = "Olimex sam9-l9260";
> +	compatible = "olimex,sam9-l9260", "atmel,at91sam9260", "atmel,at91sam9";
> +
> +	chosen {
> +		stdout-path = "serial0:115200n8";
> +	 };
> +
> +	 memory {
> +		reg = <0x20000000 0x4000000>;
> +	 };
> +
> +	 clocks {
> +		slow_xtal {
> +			clock-frequency = <32768>;
> +		};
> +
> +		main_xtal {
> +			clock-frequency = <18432000>;
> +		};
> +	 };
> +
> +	 ahb {

The whitespace is off here and throughout. You've got a <tab><space>...

Otherwise,

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


From robh at kernel.org  Wed May 25 12:10:26 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 25 May 2016 14:10:26 -0500
Subject: [PATCH v2 2/4] dt-bindings: reset: Add bindings for the Meson
 SoC Reset Controller
In-Reply-To: <1464169758-26975-3-git-send-email-narmstrong@baylibre.com>
References: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
 <1464169758-26975-3-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160525191026.GA24249@rob-hp-laptop>

On Wed, May 25, 2016 at 11:49:16AM +0200, Neil Armstrong wrote:
> Add DT bindings for the Meson SoC Reset Controller documentation and the
> associated include file.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  .../bindings/reset/amlogic,meson-reset.txt         |  18 ++
>  .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 210 +++++++++++++++++++++
>  include/dt-bindings/reset/amlogic,meson8b-reset.h  | 175 +++++++++++++++++
>  3 files changed, 403 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt
>  create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
>  create mode 100644 include/dt-bindings/reset/amlogic,meson8b-reset.h

Please add acks when posting new versions.

Rob


From robh at kernel.org  Wed May 25 12:11:25 2016
From: robh at kernel.org (Rob Herring)
Date: Wed, 25 May 2016 14:11:25 -0500
Subject: [PATCH 1/5] dt-bindings: document rk3399 rk-timer bindings
In-Reply-To: <1464169802-6033-2-git-send-email-wxt@rock-chips.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
 <1464169802-6033-2-git-send-email-wxt@rock-chips.com>
Message-ID: <20160525191125.GA25213@rob-hp-laptop>

On Wed, May 25, 2016 at 05:49:58PM +0800, Caesar Wang wrote:
> From: Huang Tao <huangtao at rock-chips.com>
> 
> Add compatible string for rk3399 because which timer is a little
> different from older SoCs. So rename the file name from
> rockchip,rk3288-timer.txt to rockchip,rk-timer.txt.
> Clarify rockchip,rk3288-timer supported SoCs.
> 
> Signed-off-by: Huang Tao <huangtao at rock-chips.com>
> Cc: Rob Herring <robh+dt at kernel.org>
> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
> Cc: Thomas Gleixner <tglx at linutronix.de>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> ---
> 
>  .../timer/{rockchip,rk3288-timer.txt => rockchip,rk-timer.txt}      | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
>  rename Documentation/devicetree/bindings/timer/{rockchip,rk3288-timer.txt => rockchip,rk-timer.txt} (75%)

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


From davem at davemloft.net  Wed May 25 12:30:17 2016
From: davem at davemloft.net (David Miller)
Date: Wed, 25 May 2016 12:30:17 -0700 (PDT)
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <1464048292-30136-2-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
 <1464048292-30136-2-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <20160525.123017.1597296248000772613.davem@davemloft.net>

From: Yury Norov <ynorov at caviumnetworks.com>
Date: Tue, 24 May 2016 03:04:30 +0300

> +To clear that top halves, automatic wrappers are introduced. They clear all
> +required registers before passing control to regular syscall handler.

Why have one of these for every single compat system call, rather than
simply clearing the top half of all of these registers unconditionally
in the 32-bit system call trap before the system call is invoked?

That's what we do on sparc64.

And with that, you only need wrappers for the case where there needs
to be proper sign extention of a 32-bit signed argument.


From labbott at redhat.com  Wed May 25 12:48:01 2016
From: labbott at redhat.com (Laura Abbott)
Date: Wed, 25 May 2016 12:48:01 -0700
Subject: [RFC][PATCH 0/3] Clean up Ion mapping/caching
Message-ID: <1464205684-5587-1-git-send-email-labbott@redhat.com>

Hi,

This series cleans up Ion a bit to be more in line with existing standards for
caching and dma mapping.

The most controversial part of this is probably going to be the first patch.
Ion takes quite a few liberties with how the DMA APIs are used for cache
syncing. dma_sync_sg is used without calling dma_map first. There isn't a
good way to get the cache synchronization with the DMA APIs. The behavior of
Ion is closer to the DRM framework which uses its own private cache APIs for
synchronization so I took that approach.

Assuming the approach of the first patch is appropriate, the next two patches
are fairly simple. dma_buf added support for a sync ioctl. Ion has a similar
ioctl already so this fixes the Ion APIs to be compatible with the dma_buf
ioctl. My plan would be to put a timeline on deprecation for the old Ion
sync ioctl. The map_dma_buf calls were also missing calls to the underlying
DMA APIs so the final patch in the series adds the appropriate calls.

Feedback is appreciated.

Thanks,
Laura

Laura Abbott (3):
  staging: ion: Move away from the DMA APIs for cache flushing
  staging: ion: Add support for syncing with DMA_BUF_IOCTL_SYNC
  staging: ion: Add dma_map/dma_unmap calls to dma_buf calls

 drivers/staging/android/ion/Kconfig             | 14 ++++-
 drivers/staging/android/ion/Makefile            |  3 +
 drivers/staging/android/ion/ion-arm.c           | 83 ++++++++++++++++++++++++
 drivers/staging/android/ion/ion-arm64.c         | 46 ++++++++++++++
 drivers/staging/android/ion/ion-x86.c           | 34 ++++++++++
 drivers/staging/android/ion/ion.c               | 84 +++++++++++++------------
 drivers/staging/android/ion/ion_carveout_heap.c |  5 +-
 drivers/staging/android/ion/ion_chunk_heap.c    |  7 +--
 drivers/staging/android/ion/ion_page_pool.c     |  3 +-
 drivers/staging/android/ion/ion_priv.h          | 14 ++---
 drivers/staging/android/ion/ion_system_heap.c   |  5 +-
 11 files changed, 235 insertions(+), 63 deletions(-)
 create mode 100644 drivers/staging/android/ion/ion-arm.c
 create mode 100644 drivers/staging/android/ion/ion-arm64.c
 create mode 100644 drivers/staging/android/ion/ion-x86.c

-- 
2.5.5



From labbott at redhat.com  Wed May 25 12:48:03 2016
From: labbott at redhat.com (Laura Abbott)
Date: Wed, 25 May 2016 12:48:03 -0700
Subject: [RFC][PATCH 2/3] staging: ion: Add support for syncing with
 DMA_BUF_IOCTL_SYNC
In-Reply-To: <1464205684-5587-1-git-send-email-labbott@redhat.com>
References: <1464205684-5587-1-git-send-email-labbott@redhat.com>
Message-ID: <1464205684-5587-3-git-send-email-labbott@redhat.com>



dma_buf added support for a userspace syncing ioctl. It is implemented
by calling dma_buf_begin_cpu_access and dma_buf_end_cpu_access. Ion
currently lacks cache operations on this code path. Add them for
compatibility with the dma_buf ioctl.

Signed-off-by: Laura Abbott <labbott at redhat.com>
---
 drivers/staging/android/ion/ion.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 9282d96a..2096592 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -1117,6 +1117,11 @@ static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
 	mutex_lock(&buffer->lock);
 	vaddr = ion_buffer_kmap_get(buffer);
 	mutex_unlock(&buffer->lock);
+
+	if (direction != DMA_TO_DEVICE) {
+		ion_invalidate_buffer(buffer);
+	}
+
 	return PTR_ERR_OR_ZERO(vaddr);
 }
 
@@ -1129,6 +1134,12 @@ static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
 	ion_buffer_kmap_put(buffer);
 	mutex_unlock(&buffer->lock);
 
+	if (direction == DMA_FROM_DEVICE) {
+		ion_invalidate_buffer(buffer);
+	} else {
+		ion_clean_buffer(buffer);
+	}
+
 	return 0;
 }
 
@@ -1259,6 +1270,8 @@ static int ion_sync_for_device(struct ion_client *client, int fd)
 	struct dma_buf *dmabuf;
 	struct ion_buffer *buffer;
 
+	WARN_ONCE(1, "This API is deprecated in favor of the dma_buf ioctl\n");
+
 	dmabuf = dma_buf_get(fd);
 	if (IS_ERR(dmabuf))
 		return PTR_ERR(dmabuf);
-- 
2.5.5



From labbott at redhat.com  Wed May 25 12:48:04 2016
From: labbott at redhat.com (Laura Abbott)
Date: Wed, 25 May 2016 12:48:04 -0700
Subject: [RFC][PATCH 3/3] staging: ion: Add dma_map/dma_unmap calls to dma_buf
 calls
In-Reply-To: <1464205684-5587-1-git-send-email-labbott@redhat.com>
References: <1464205684-5587-1-git-send-email-labbott@redhat.com>
Message-ID: <1464205684-5587-4-git-send-email-labbott@redhat.com>



The .map_dma_buf/.unmap_dma_buf function calls are designed for buffer
users to perform DMA accesses. Ion doesn't call into the lower DMA
layer currently. This may leave mapping incomplete for devices with
more complex topologies (e.g. IOMMUs). Add the appropriate dma_map
calls to the dma_buf call backs.

Signed-off-by: Laura Abbott <labbott at redhat.com>
---
 drivers/staging/android/ion/ion.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 2096592..52dbea4 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -980,7 +980,18 @@ static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment,
 	struct dma_buf *dmabuf = attachment->dmabuf;
 	struct ion_buffer *buffer = dmabuf->priv;
 
+	/* Necessary but not sufficient: This is for userspace */
 	ion_buffer_sync_for_device(buffer, attachment->dev, direction);
+
+	/* The rest of this is for the standard mappings */
+	buffer->sg_table->nents = dma_map_sg(attachment->dev,
+					buffer->sg_table->sgl,
+					buffer->sg_table->orig_nents,
+					direction);
+
+	if (!buffer->sg_table->nents)
+		return ERR_PTR(-EIO);
+
 	return buffer->sg_table;
 }
 
@@ -988,6 +999,7 @@ static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment,
 			      struct sg_table *table,
 			      enum dma_data_direction direction)
 {
+	dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction);
 }
 
 static int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-- 
2.5.5



From labbott at redhat.com  Wed May 25 12:48:02 2016
From: labbott at redhat.com (Laura Abbott)
Date: Wed, 25 May 2016 12:48:02 -0700
Subject: [RFC][PATCH 1/3] staging: ion: Move away from the DMA APIs for cache
 flushing
In-Reply-To: <1464205684-5587-1-git-send-email-labbott@redhat.com>
References: <1464205684-5587-1-git-send-email-labbott@redhat.com>
Message-ID: <1464205684-5587-2-git-send-email-labbott@redhat.com>


Ion is currently using the DMA APIs in non-compliant ways for cache
maintaince. The issue is Ion needs to do cache operations outside of
the regular DMA model. The Ion model matches more closely with the
DRM model which calls cache APIs directly. Add an appropriate
abstraction layer for Ion to call cache operations outside of the
DMA API.

Signed-off-by: Laura Abbott <labbott at redhat.com>
---
 drivers/staging/android/ion/Kconfig             | 14 ++++-
 drivers/staging/android/ion/Makefile            |  3 +
 drivers/staging/android/ion/ion-arm.c           | 83 +++++++++++++++++++++++++
 drivers/staging/android/ion/ion-arm64.c         | 46 ++++++++++++++
 drivers/staging/android/ion/ion-x86.c           | 34 ++++++++++
 drivers/staging/android/ion/ion.c               | 59 ++++++------------
 drivers/staging/android/ion/ion_carveout_heap.c |  5 +-
 drivers/staging/android/ion/ion_chunk_heap.c    |  7 +--
 drivers/staging/android/ion/ion_page_pool.c     |  3 +-
 drivers/staging/android/ion/ion_priv.h          | 14 ++---
 drivers/staging/android/ion/ion_system_heap.c   |  5 +-
 11 files changed, 210 insertions(+), 63 deletions(-)
 create mode 100644 drivers/staging/android/ion/ion-arm.c
 create mode 100644 drivers/staging/android/ion/ion-arm64.c
 create mode 100644 drivers/staging/android/ion/ion-x86.c

diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig
index 19c1572..c1b1813 100644
--- a/drivers/staging/android/ion/Kconfig
+++ b/drivers/staging/android/ion/Kconfig
@@ -1,6 +1,6 @@
 menuconfig ION
 	bool "Ion Memory Manager"
-	depends on HAVE_MEMBLOCK && HAS_DMA && MMU
+	depends on HAVE_MEMBLOCK && HAS_DMA && MMU && (X86 || ARM || ARM64)
 	select GENERIC_ALLOCATOR
 	select DMA_SHARED_BUFFER
 	---help---
@@ -10,6 +10,18 @@ menuconfig ION
 	  If you're not using Android its probably safe to
 	  say N here.
 
+config ION_ARM
+	depends on ION && ARM
+	def_bool y
+
+config ION_ARM64
+	depends on ION && ARM64
+	def_bool y
+
+config ION_X86
+	depends on ION && X86
+	def_bool y
+
 config ION_TEST
 	tristate "Ion Test Device"
 	depends on ION
diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile
index 18cc2aa..1b82bb5 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -1,5 +1,8 @@
 obj-$(CONFIG_ION) +=	ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \
 			ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o
+obj-$(CONFIG_ION_X86) += ion-x86.o
+obj-$(CONFIG_ION_ARM) += ion-arm.o
+obj-$(CONFIG_ION_ARM64) += ion-arm64.o
 obj-$(CONFIG_ION_TEST) += ion_test.o
 ifdef CONFIG_COMPAT
 obj-$(CONFIG_ION) += compat_ion.o
diff --git a/drivers/staging/android/ion/ion-arm.c b/drivers/staging/android/ion/ion-arm.c
new file mode 100644
index 0000000..b91287f
--- /dev/null
+++ b/drivers/staging/android/ion/ion-arm.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 Laura Abbott <laura at labbott.name>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/highmem.h>
+
+#include <asm/cacheflush.h>
+
+#include "ion_priv.h"
+
+
+void ion_clean_page(struct page *page, size_t size)
+{
+	unsigned long pfn;
+	size_t left = size;
+
+	pfn = page_to_pfn(page);
+
+	/*
+	 * A single sg entry may refer to multiple physically contiguous
+	 * pages.  But we still need to process highmem pages individually.
+	 * If highmem is not configured then the bulk of this loop gets
+	 * optimized out.
+	 */
+	do {
+		size_t len = left;
+		void *vaddr;
+
+		page = pfn_to_page(pfn);
+
+		if (PageHighMem(page)) {
+			if (len > PAGE_SIZE)
+				len = PAGE_SIZE;
+
+			if (cache_is_vipt_nonaliasing()) {
+				vaddr = kmap_atomic(page);
+				__cpuc_flush_dcache_area(vaddr, len);
+				kunmap_atomic(vaddr);
+			} else {
+				vaddr = kmap_high_get(page);
+				if (vaddr) {
+					__cpuc_flush_dcache_area(vaddr, len);
+					kunmap_high(page);
+				}
+			}
+		} else {
+			vaddr = page_address(page);
+			__cpuc_flush_dcache_area(vaddr, len);
+		}
+		pfn++;
+		left -= len;
+	} while (left);
+}
+
+/*
+ * ARM has highmem and a bunch of other 'fun' features. It's so much easier just
+ * to do the ISA DMA and call things that way
+ */
+
+void ion_invalidate_buffer(struct ion_buffer *buffer)
+{
+	dma_unmap_sg(NULL, buffer->sg_table->sgl, buffer->sg_table->orig_nents,
+			DMA_BIDIRECTIONAL);
+}
+
+void ion_clean_buffer(struct ion_buffer *buffer)
+{
+	dma_map_sg(NULL, buffer->sg_table->sgl, buffer->sg_table->orig_nents,
+			DMA_BIDIRECTIONAL);
+}
diff --git a/drivers/staging/android/ion/ion-arm64.c b/drivers/staging/android/ion/ion-arm64.c
new file mode 100644
index 0000000..afd387a
--- /dev/null
+++ b/drivers/staging/android/ion/ion-arm64.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 Laura Abbott <laura at labbott.name>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/cacheflush.h>
+
+#include "ion_priv.h"
+
+void ion_clean_page(struct page *page, size_t size)
+{
+	__flush_dcache_area(page_address(page), size);
+}
+
+void ion_invalidate_buffer(struct ion_buffer *buffer)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->orig_nents, i)
+		__dma_unmap_area(page_address(sg_page(sg)), sg->length,
+					DMA_BIDIRECTIONAL);
+}
+
+void ion_clean_buffer(struct ion_buffer *buffer)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->orig_nents, i)
+		__dma_map_area(page_address(sg_page(sg)), sg->length,
+					DMA_BIDIRECTIONAL);
+}
diff --git a/drivers/staging/android/ion/ion-x86.c b/drivers/staging/android/ion/ion-x86.c
new file mode 100644
index 0000000..05fd684
--- /dev/null
+++ b/drivers/staging/android/ion/ion-x86.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 Laura Abbott <laura at labbott.name>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+
+#include "ion_priv.h"
+
+void ion_clean_page(struct page *page, size_t size)
+{
+	/* Do nothing right now */
+}
+
+void ion_invalidate_buffer(struct ion_buffer *buffer)
+{
+	/* Do nothing right now */
+}
+
+void ion_clean_buffer(struct ion_buffer *buffer)
+{
+	/* Do nothing right now */
+}
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index a2cf93b..9282d96a 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -937,42 +937,6 @@ struct sg_table *ion_sg_table(struct ion_client *client,
 }
 EXPORT_SYMBOL(ion_sg_table);
 
-static void ion_buffer_sync_for_device(struct ion_buffer *buffer,
-				       struct device *dev,
-				       enum dma_data_direction direction);
-
-static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment,
-					enum dma_data_direction direction)
-{
-	struct dma_buf *dmabuf = attachment->dmabuf;
-	struct ion_buffer *buffer = dmabuf->priv;
-
-	ion_buffer_sync_for_device(buffer, attachment->dev, direction);
-	return buffer->sg_table;
-}
-
-static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment,
-			      struct sg_table *table,
-			      enum dma_data_direction direction)
-{
-}
-
-void ion_pages_sync_for_device(struct device *dev, struct page *page,
-		size_t size, enum dma_data_direction dir)
-{
-	struct scatterlist sg;
-
-	sg_init_table(&sg, 1);
-	sg_set_page(&sg, page, size, 0);
-	/*
-	 * This is not correct - sg_dma_address needs a dma_addr_t that is valid
-	 * for the targeted device, but this works on the currently targeted
-	 * hardware.
-	 */
-	sg_dma_address(&sg) = page_to_phys(page);
-	dma_sync_sg_for_device(dev, &sg, 1, dir);
-}
-
 struct ion_vma_list {
 	struct list_head list;
 	struct vm_area_struct *vma;
@@ -997,8 +961,7 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer,
 		struct page *page = buffer->pages[i];
 
 		if (ion_buffer_page_is_dirty(page))
-			ion_pages_sync_for_device(dev, ion_buffer_page(page),
-							PAGE_SIZE, dir);
+			ion_clean_page(ion_buffer_page(page), PAGE_SIZE);
 
 		ion_buffer_page_clean(buffer->pages + i);
 	}
@@ -1011,6 +974,22 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer,
 	mutex_unlock(&buffer->lock);
 }
 
+static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment,
+					enum dma_data_direction direction)
+{
+	struct dma_buf *dmabuf = attachment->dmabuf;
+	struct ion_buffer *buffer = dmabuf->priv;
+
+	ion_buffer_sync_for_device(buffer, attachment->dev, direction);
+	return buffer->sg_table;
+}
+
+static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment,
+			      struct sg_table *table,
+			      enum dma_data_direction direction)
+{
+}
+
 static int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct ion_buffer *buffer = vma->vm_private_data;
@@ -1293,8 +1272,8 @@ static int ion_sync_for_device(struct ion_client *client, int fd)
 	}
 	buffer = dmabuf->priv;
 
-	dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
-			       buffer->sg_table->nents, DMA_BIDIRECTIONAL);
+	ion_clean_buffer(buffer);
+
 	dma_buf_put(dmabuf);
 	return 0;
 }
diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c
index 1fb0d81..d213cbf 100644
--- a/drivers/staging/android/ion/ion_carveout_heap.c
+++ b/drivers/staging/android/ion/ion_carveout_heap.c
@@ -116,8 +116,7 @@ static void ion_carveout_heap_free(struct ion_buffer *buffer)
 	ion_heap_buffer_zero(buffer);
 
 	if (ion_buffer_cached(buffer))
-		dma_sync_sg_for_device(NULL, table->sgl, table->nents,
-				       DMA_BIDIRECTIONAL);
+		ion_clean_page(page, buffer->size);
 
 	ion_carveout_free(heap, paddr, buffer->size);
 	sg_free_table(table);
@@ -157,7 +156,7 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
 	page = pfn_to_page(PFN_DOWN(heap_data->base));
 	size = heap_data->size;
 
-	ion_pages_sync_for_device(NULL, page, size, DMA_BIDIRECTIONAL);
+	ion_clean_page(page, size);
 
 	ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL));
 	if (ret)
diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c
index e0553fe..0666529 100644
--- a/drivers/staging/android/ion/ion_chunk_heap.c
+++ b/drivers/staging/android/ion/ion_chunk_heap.c
@@ -104,11 +104,10 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer)
 
 	ion_heap_buffer_zero(buffer);
 
-	if (ion_buffer_cached(buffer))
-		dma_sync_sg_for_device(NULL, table->sgl, table->nents,
-							DMA_BIDIRECTIONAL);
 
 	for_each_sg(table->sgl, sg, table->nents, i) {
+		if (ion_buffer_cached(buffer))
+			ion_clean_page(sg_page(table->sgl), sg->length);
 		gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
 			      sg->length);
 	}
@@ -148,7 +147,7 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
 	page = pfn_to_page(PFN_DOWN(heap_data->base));
 	size = heap_data->size;
 
-	ion_pages_sync_for_device(NULL, page, size, DMA_BIDIRECTIONAL);
+	ion_clean_page(page, size);
 
 	ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL));
 	if (ret)
diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c
index 1fe8016..b854f91 100644
--- a/drivers/staging/android/ion/ion_page_pool.c
+++ b/drivers/staging/android/ion/ion_page_pool.c
@@ -30,8 +30,7 @@ static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool)
 
 	if (!page)
 		return NULL;
-	ion_pages_sync_for_device(NULL, page, PAGE_SIZE << pool->order,
-						DMA_BIDIRECTIONAL);
+	ion_clean_page(page, PAGE_SIZE << pool->order);
 	return page;
 }
 
diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h
index 0239883..b368338 100644
--- a/drivers/staging/android/ion/ion_priv.h
+++ b/drivers/staging/android/ion/ion_priv.h
@@ -392,15 +392,9 @@ void ion_page_pool_free(struct ion_page_pool *, struct page *);
 int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
 			  int nr_to_scan);
 
-/**
- * ion_pages_sync_for_device - cache flush pages for use with the specified
- *                             device
- * @dev:		the device the pages will be used with
- * @page:		the first page to be flushed
- * @size:		size in bytes of region to be flushed
- * @dir:		direction of dma transfer
- */
-void ion_pages_sync_for_device(struct device *dev, struct page *page,
-		size_t size, enum dma_data_direction dir);
+void ion_clean_page(struct page *page, size_t size);
+
+void ion_clean_buffer(struct ion_buffer *buffer);
 
+void ion_invalidate_buffer(struct ion_buffer *buffer);
 #endif /* _ION_PRIV_H */
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index b69dfc7..aa39660 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -70,8 +70,7 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap,
 		page = alloc_pages(gfp_flags | __GFP_COMP, order);
 		if (!page)
 			return NULL;
-		ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order,
-						DMA_BIDIRECTIONAL);
+		ion_clean_page(page, PAGE_SIZE << order);
 	}
 
 	return page;
@@ -360,7 +359,7 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap,
 
 	buffer->priv_virt = table;
 
-	ion_pages_sync_for_device(NULL, page, len, DMA_BIDIRECTIONAL);
+	ion_clean_page(page, len);
 
 	return 0;
 
-- 
2.5.5



From ynorov at caviumnetworks.com  Wed May 25 13:03:27 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Wed, 25 May 2016 23:03:27 +0300
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160525.123017.1597296248000772613.davem@davemloft.net>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
 <1464048292-30136-2-git-send-email-ynorov@caviumnetworks.com>
 <20160525.123017.1597296248000772613.davem@davemloft.net>
Message-ID: <20160525200327.GA22395@yury-N73SV>

On Wed, May 25, 2016 at 12:30:17PM -0700, David Miller wrote:
> From: Yury Norov <ynorov at caviumnetworks.com>
> Date: Tue, 24 May 2016 03:04:30 +0300
> 
> > +To clear that top halves, automatic wrappers are introduced. They clear all
> > +required registers before passing control to regular syscall handler.
> 
> Why have one of these for every single compat system call, rather than
> simply clearing the top half of all of these registers unconditionally
> in the 32-bit system call trap before the system call is invoked?
> 
> That's what we do on sparc64.
> 
> And with that, you only need wrappers for the case where there needs
> to be proper sign extention of a 32-bit signed argument.

It was discussed as one of possible solutions. The downside of it is
that we cannot pass 64-bit types (like off_t) in single register.
The other downside is that we clear top halves for every single
syscall, and it looks excessive. So, from spark64 and s390 approaches
we choosed second.


From carlo at caione.org  Wed May 25 13:18:30 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 25 May 2016 22:18:30 +0200
Subject: [PATCH v4 2/3] documentation: Add secure monitor binding documentation
In-Reply-To: <1464207511-11786-1-git-send-email-carlo@caione.org>
References: <1464207511-11786-1-git-send-email-carlo@caione.org>
Message-ID: <1464207511-11786-3-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add the binding documentation for the Amlogic secure monitor driver.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 .../bindings/firmware/meson/meson_sm.txt           | 42 ++++++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt

diff --git a/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt b/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
new file mode 100644
index 0000000..896758d
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
@@ -0,0 +1,42 @@
+* Amlogic Secure Monitor
+
+In the Amlogic SoCs the Secure Monitor code is used to provide access to the
+NVMEM, enable JTAG, set USB boot, etc...
+
+Required properties for the secure monitor node:
+- compatible: Should be "amlogic,meson-gxbb-sm"
+
+Example:
+
+	#include <dt-bindings/firmware/meson-sm.h>
+
+	...
+
+	firmware {
+		compatible = "simple-bus";
+
+		sm: secure-monitor {
+			compatible = "amlogic,meson-gxbb-sm";
+		};
+	};
+
+Node of a device using the secure monitor must have a custom property to
+specify the SMC32 function ID the driver is going to use.
+
+Example of the node using the secure monitor:
+
+	#include <dt-bindings/firmware/meson-sm.h>
+
+	...
+
+	efuse: efuse {
+		compatible = "amlogic,meson-gxbb-efuse";
+		secure-monitor = <&sm>;
+		amlogic,sm-cmd-read-efuse = <SM_EFUSE_READ>;
+		amlogic,sm-cmd-max-efuse = <SM_EFUSE_USER_MAX>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		...
+	};
+
-- 
2.7.4



From carlo at caione.org  Wed May 25 13:18:28 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 25 May 2016 22:18:28 +0200
Subject: [PATCH v4 0/3] Add Amlogic secure monitor driver
Message-ID: <1464207511-11786-1-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>


In the Amlogic SoCs the secure monitor calls are used for a lot of reasons:
interact with the NVMEM (efuses), check the reboot reason, set USB boot, ...

This driver defines a generic interface towards the secure monitor that can be
used by more specialized drivers to interact with the secure monitor itself
without worrying about bounce buffers managing.

Changelog:

v4:
  * Changed patches order
  * Removed now useless PATCH 2/4
  * Changed compatible to be SoC-specific
  * In the DT now we use SoC-agnostic IDs for the SMC functions. These IDs are
    traslated into SoC specific function IDs inside the driver
  * Added error checking on meson_sm_call() to retrieve the base address
  * Improved printing on errors

v3:
  * Moved driver to drivers/firmware
  * Added EXPORT_SYMBOL macros
  * Changed '_' in '-'
  * Introduced 'struct meson_sm_firmware' and 'meson_sm_get_fw()' to be used by
    drivers using the secure-monitor to enforce probe ordering

v2:
  * All the SMC function identifiers are now in a SoC-specific header file to
    be included by the DTS files so the SMC commands are now defined in the DT
    instead to be hardcoded into the driver
  * Patchset is no longer an RFC
  * Better error management and boundary checking
  * s/unsigned int/u32/
  * SMC call not only on CPU 0
  * Fix memory leaking
  * s/amlogic/meson/ in the directory names

Carlo Caione (3):
  firmware: Amlogic: Add secure monitor driver
  documentation: Add secure monitor binding documentation
  ARM64: dts: amlogic: gxbb: Enable secure monitor

 .../bindings/firmware/meson/meson_sm.txt           |  42 +++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   9 +
 drivers/firmware/Kconfig                           |   1 +
 drivers/firmware/Makefile                          |   1 +
 drivers/firmware/meson/Kconfig                     |   8 +
 drivers/firmware/meson/Makefile                    |   1 +
 drivers/firmware/meson/meson_sm.c                  | 193 +++++++++++++++++++++
 include/dt-bindings/firmware/meson-sm.h            |  20 +++
 include/linux/firmware/meson/meson-sm.h            |  49 ++++++
 9 files changed, 324 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
 create mode 100644 drivers/firmware/meson/Kconfig
 create mode 100644 drivers/firmware/meson/Makefile
 create mode 100644 drivers/firmware/meson/meson_sm.c
 create mode 100644 include/dt-bindings/firmware/meson-sm.h
 create mode 100644 include/linux/firmware/meson/meson-sm.h

-- 
2.7.4



From carlo at caione.org  Wed May 25 13:18:29 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 25 May 2016 22:18:29 +0200
Subject: [PATCH v4 1/3] firmware: Amlogic: Add secure monitor driver
In-Reply-To: <1464207511-11786-1-git-send-email-carlo@caione.org>
References: <1464207511-11786-1-git-send-email-carlo@caione.org>
Message-ID: <1464207511-11786-2-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Introduce a driver to provide calls into secure monitor mode.

In the Amlogic SoCs these calls are used for multiple reasons: access to
NVMEM, set USB boot, enable JTAG, etc...

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 drivers/firmware/Kconfig                |   1 +
 drivers/firmware/Makefile               |   1 +
 drivers/firmware/meson/Kconfig          |   8 ++
 drivers/firmware/meson/Makefile         |   1 +
 drivers/firmware/meson/meson_sm.c       | 193 ++++++++++++++++++++++++++++++++
 include/dt-bindings/firmware/meson-sm.h |  20 ++++
 include/linux/firmware/meson/meson-sm.h |  49 ++++++++
 7 files changed, 273 insertions(+)
 create mode 100644 drivers/firmware/meson/Kconfig
 create mode 100644 drivers/firmware/meson/Makefile
 create mode 100644 drivers/firmware/meson/meson_sm.c
 create mode 100644 include/dt-bindings/firmware/meson-sm.h
 create mode 100644 include/linux/firmware/meson/meson-sm.h

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 6664f11..686e395 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -199,5 +199,6 @@ config HAVE_ARM_SMCCC
 source "drivers/firmware/broadcom/Kconfig"
 source "drivers/firmware/google/Kconfig"
 source "drivers/firmware/efi/Kconfig"
+source "drivers/firmware/meson/Kconfig"
 
 endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 474bada..fc4bb09 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_QCOM_SCM_32)	+= qcom_scm-32.o
 CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
 
 obj-y				+= broadcom/
+obj-y				+= meson/
 obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
 obj-$(CONFIG_EFI)		+= efi/
 obj-$(CONFIG_UEFI_CPER)		+= efi/
diff --git a/drivers/firmware/meson/Kconfig b/drivers/firmware/meson/Kconfig
new file mode 100644
index 0000000..fff11a3
--- /dev/null
+++ b/drivers/firmware/meson/Kconfig
@@ -0,0 +1,8 @@
+#
+# Amlogic Secure Monitor driver
+#
+config MESON_SM
+	bool
+	default ARCH_MESON
+	help
+	  Say y here to enable the Amlogic secure monitor driver
diff --git a/drivers/firmware/meson/Makefile b/drivers/firmware/meson/Makefile
new file mode 100644
index 0000000..9ab3884
--- /dev/null
+++ b/drivers/firmware/meson/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MESON_SM) +=	meson_sm.o
diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
new file mode 100644
index 0000000..7f60248
--- /dev/null
+++ b/drivers/firmware/meson/meson_sm.c
@@ -0,0 +1,193 @@
+/*
+ * Amlogic Secure Monitor driver
+ *
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <stdarg.h>
+#include <asm/cacheflush.h>
+#include <asm/compiler.h>
+#include <linux/arm-smccc.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/smp.h>
+#include <linux/firmware/meson/meson-sm.h>
+
+#include <dt-bindings/firmware/meson-sm.h>
+
+struct meson_sm_chip gxbb_cmd = {
+	.mem_size		= 0x1000,
+	.cmd_sharemem_in_base	= 0x82000020,
+	.cmd_sharemem_out_base	= 0x82000021,
+	.cmd = {
+		CMD(SM_EFUSE_READ,	0x82000030),
+		CMD(SM_EFUSE_WRITE,	0x82000031),
+		CMD(SM_EFUSE_USER_MAX,	0x82000033),
+		{ /* sentinel */ },
+	},
+};
+
+static u32 meson_sm_get_cmd(const struct meson_sm_chip *chip, unsigned int cmd_index)
+{
+	unsigned int i;
+
+	for (i = 0; chip->cmd[i].smc_id; i++)
+		if (chip->cmd[i].index == cmd_index)
+			return chip->cmd[i].smc_id;
+
+	return 0;
+}
+
+static u32 __meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_smc(cmd, arg0, arg1, arg2, arg3, arg4, 0, 0, &res);
+	return res.a0;
+}
+
+u32 meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index,
+		  u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 cmd;
+
+	if (!fw)
+		return -EINVAL;
+
+	cmd = meson_sm_get_cmd(fw->chip, cmd_index);
+	if (!cmd)
+		return -EINVAL;
+
+	return __meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
+}
+EXPORT_SYMBOL(meson_sm_call);
+
+u32 meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
+		       unsigned int cmd_index, u32 arg0, u32 arg1,
+		       u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 size;
+
+	size = meson_sm_call(fw, cmd_index, arg0, arg1, arg2, arg3, arg4);
+	if (size <= 0 || size > fw->chip->mem_size)
+		return -EINVAL;
+
+	memcpy(buffer, fw->sm_sharemem_out_base, size);
+
+	return size;
+}
+EXPORT_SYMBOL(meson_sm_call_read);
+
+u32 meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
+			unsigned int b_size, unsigned int cmd_index,
+			u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 size;
+
+	if (b_size > fw->chip->mem_size)
+		return -EINVAL;
+
+	memcpy(fw->sm_sharemem_in_base, buffer, b_size);
+
+	size = meson_sm_call(fw, cmd_index, arg0, arg1, arg2, arg3, arg4);
+	if (size <= 0)
+		return -EINVAL;
+
+	return size;
+}
+EXPORT_SYMBOL(meson_sm_call_write);
+
+static int meson_sm_probe(struct platform_device *pdev)
+{
+	const struct meson_sm_chip *chip;
+	struct meson_sm_firmware *fw;
+	u32 sm_phy_in_base, sm_phy_out_base;
+
+	fw = devm_kzalloc(&pdev->dev, sizeof(*fw), GFP_KERNEL);
+	if (!fw)
+		return -ENOMEM;
+
+	fw->dev = &pdev->dev;
+
+	chip = of_device_get_match_data(fw->dev);
+	if (!chip) {
+		dev_err(fw->dev, "Unable to setup secure-monitor data\n");
+		return -ENODEV;
+	}
+
+	sm_phy_in_base = __meson_sm_call(chip->cmd_sharemem_in_base, 0, 0, 0, 0, 0);
+	if (!sm_phy_in_base) {
+		dev_err(fw->dev, "Failed to get shared input memory base \n");
+		return -EINVAL;
+	}
+
+	sm_phy_out_base = __meson_sm_call(chip->cmd_sharemem_out_base, 0, 0, 0, 0, 0);
+	if (!sm_phy_out_base) {
+		dev_err(fw->dev, "Failed to get shared output memory base\n");
+		return -EINVAL;
+	}
+
+	fw->sm_sharemem_in_base = ioremap_cache(sm_phy_in_base, chip->mem_size);
+	if (!fw->sm_sharemem_in_base) {
+		dev_err(fw->dev, "Failed iomap()\n");
+		return -EINVAL;
+	}
+
+	fw->sm_sharemem_out_base = ioremap_cache(sm_phy_out_base, chip->mem_size);
+	if (!fw->sm_sharemem_out_base) {
+		dev_err(fw->dev, "Failed iomap()\n");
+		iounmap(fw->sm_sharemem_in_base);
+		return -EINVAL;
+	}
+
+	fw->chip = chip;
+	platform_set_drvdata(pdev, fw);
+
+	dev_info(fw->dev, "secure-monitor enabled\n");
+
+	return 0;
+}
+
+struct meson_sm_firmware *meson_sm_get_fw(struct device_node *firmware_node)
+{
+	struct platform_device *pdev = of_find_device_by_node(firmware_node);
+
+	/*
+	 * Returns NULL is the firmware device is not ready.
+	 */
+	if (!pdev)
+		return NULL;
+
+	return platform_get_drvdata(pdev);
+}
+EXPORT_SYMBOL(meson_sm_get_fw);
+
+static const struct of_device_id meson_sm_ids[] = {
+	{ .compatible = "amlogic,meson-gxbb-sm", .data = &gxbb_cmd },
+	{ /* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, meson_sm_ids);
+
+static struct platform_driver meson_sm_platform_driver = {
+	.probe	= meson_sm_probe,
+	.driver	= {
+		.name		= "secure-monitor",
+		.of_match_table	= meson_sm_ids,
+	},
+};
+module_platform_driver(meson_sm_platform_driver);
+
+MODULE_AUTHOR("Carlo Caione <carlo at endlessm.com>");
+MODULE_DESCRIPTION("Amlogic secure monitor driver");
+MODULE_LICENSE("GPL");
diff --git a/include/dt-bindings/firmware/meson-sm.h b/include/dt-bindings/firmware/meson-sm.h
new file mode 100644
index 0000000..3a52a13
--- /dev/null
+++ b/include/dt-bindings/firmware/meson-sm.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MESON_DT_H_
+#define _MESON_DT_H_
+
+#define SM_EFUSE_READ		0
+#define SM_EFUSE_WRITE		1
+#define SM_EFUSE_USER_MAX	2
+
+#endif /* _MESON_DT_H_ */
diff --git a/include/linux/firmware/meson/meson-sm.h b/include/linux/firmware/meson/meson-sm.h
new file mode 100644
index 0000000..1589c97
--- /dev/null
+++ b/include/linux/firmware/meson/meson-sm.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MESON_SM_H_
+#define _MESON_SM_H_
+
+#include <linux/types.h>
+#include <linux/of_device.h>
+
+struct meson_sm_cmd {
+	unsigned int index;
+	u32 smc_id;
+};
+#define CMD(d, s) { .index = (d), .smc_id = (s), }
+
+struct meson_sm_chip {
+	unsigned int mem_size;
+	u32 cmd_sharemem_in_base;
+	u32 cmd_sharemem_out_base;
+	struct meson_sm_cmd cmd[];
+};
+
+struct meson_sm_firmware {
+	struct device *dev;
+	const struct meson_sm_chip *chip;
+	void __iomem *sm_sharemem_in_base;
+	void __iomem *sm_sharemem_out_base;
+};
+
+u32 meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index,
+		  u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
+u32 meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
+			unsigned int b_size, unsigned int cmd_index,
+			u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
+u32 meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
+		       unsigned int cmd_index, u32 arg0, u32 arg1,
+		       u32 arg2, u32 arg3, u32 arg4);
+struct meson_sm_firmware *meson_sm_get_fw(struct device_node *firmware_node);
+
+#endif /* _MESON_SM_H_ */
-- 
2.7.4



From carlo at caione.org  Wed May 25 13:18:31 2016
From: carlo at caione.org (Carlo Caione)
Date: Wed, 25 May 2016 22:18:31 +0200
Subject: [PATCH v4 3/3] ARM64: dts: amlogic: gxbb: Enable secure monitor
In-Reply-To: <1464207511-11786-1-git-send-email-carlo@caione.org>
References: <1464207511-11786-1-git-send-email-carlo@caione.org>
Message-ID: <1464207511-11786-4-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add the secure monitor node in the Amlogic Meson GXBB DTSI file to
enable it.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 76b3b6d..735a751 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -44,6 +44,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/gpio/meson-gxbb-gpio.h>
+#include <dt-bindings/firmware/meson-sm.h>
 
 / {
 	compatible = "amlogic,meson-gxbb";
@@ -98,6 +99,14 @@
 		method = "smc";
 	};
 
+	firmware {
+		compatible = "simple-bus";
+
+		sm: secure-monitor {
+			compatible = "amlogic,meson-gxbb-sm";
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13
-- 
2.7.4



From davem at davemloft.net  Wed May 25 13:21:45 2016
From: davem at davemloft.net (David Miller)
Date: Wed, 25 May 2016 13:21:45 -0700 (PDT)
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160525200327.GA22395@yury-N73SV>
References: <1464048292-30136-2-git-send-email-ynorov@caviumnetworks.com>
 <20160525.123017.1597296248000772613.davem@davemloft.net>
 <20160525200327.GA22395@yury-N73SV>
Message-ID: <20160525.132145.1271448744307448631.davem@davemloft.net>

From: Yury Norov <ynorov at caviumnetworks.com>
Date: Wed, 25 May 2016 23:03:27 +0300

> On Wed, May 25, 2016 at 12:30:17PM -0700, David Miller wrote:
>> From: Yury Norov <ynorov at caviumnetworks.com>
>> Date: Tue, 24 May 2016 03:04:30 +0300
>> 
>> > +To clear that top halves, automatic wrappers are introduced. They clear all
>> > +required registers before passing control to regular syscall handler.
>> 
>> Why have one of these for every single compat system call, rather than
>> simply clearing the top half of all of these registers unconditionally
>> in the 32-bit system call trap before the system call is invoked?
>> 
>> That's what we do on sparc64.
>> 
>> And with that, you only need wrappers for the case where there needs
>> to be proper sign extention of a 32-bit signed argument.
> 
> It was discussed as one of possible solutions. The downside of it is
> that we cannot pass 64-bit types (like off_t) in single register.

Wrappers can be added for the cases where you'd like to do that.

> The other downside is that we clear top halves for every single
> syscall, and it looks excessive. So, from spark64 and s390 approaches
> we choosed second.

It's like 4 cpu cycles even on crappy sparc64 cpus which only dual
issue. :)

And that's a pretty low cost for the benefits if you ask me.


From arnd at arndb.de  Wed May 25 13:26:54 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 25 May 2016 22:26:54 +0200
Subject: [PATCH 18/23] arm64: ilp32: add sys_ilp32.c and a separate table
 (in entry.S) to use it
In-Reply-To: <1464048292-30136-19-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
 <1464048292-30136-19-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <4731114.hBXBvkC8xh@wuerfel>

On Tuesday, May 24, 2016 3:04:47 AM CEST Yury Norov wrote:
> +static unsigned long compat_sys_mmap2(compat_uptr_t addr, compat_size_t len,
> +       int prot, int flags, int fd, off_t pgoff)
> +{
> +       if (pgoff & (~PAGE_MASK >> 12))
> +               return -EINVAL;
> +
> +       return sys_mmap_pgoff(addr, len, prot, flags, fd,
> +                      pgoff >> (PAGE_SHIFT - 12));
> +}
> +
> +static unsigned long compat_sys_pread64(unsigned int fd,
> +               compat_uptr_t __user *ubuf, compat_size_t count, off_t offset)
> +{
> +       return sys_pread64(fd, (char *) ubuf, count, offset);
> +}
> +
> +static unsigned long compat_sys_pwrite64(unsigned int fd,
> +               compat_uptr_t __user *ubuf, compat_size_t count, off_t offset)
> +{
> +       return sys_pwrite64(fd, (char *) ubuf, count, offset);
> +}
> 

The use of compat_uptr_t seems inconsistent here, and neither of the two
ways of doing it is what we do elsewhere. compat_uptr_t is meant to
be a scalar 32-bit type that gets converted into a pointer using the
compat_ptr() macro, so compat_sys_mmap2 should not use compat_ptr_t
(we don't access it as a pointer in mmap_pgoff) but compat_ulong_t,
and compat_sys_pread64() should have a compat_uptr_t argument, not
pointer to compat_uptr_t.

	Arnd


From arnd at arndb.de  Wed May 25 13:47:33 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 25 May 2016 22:47:33 +0200
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160525.132145.1271448744307448631.davem@davemloft.net>
References: <1464048292-30136-2-git-send-email-ynorov@caviumnetworks.com>
 <20160525200327.GA22395@yury-N73SV>
 <20160525.132145.1271448744307448631.davem@davemloft.net>
Message-ID: <6293194.tGy03QJ9ME@wuerfel>

On Wednesday, May 25, 2016 1:21:45 PM CEST David Miller wrote:
> From: Yury Norov <ynorov at caviumnetworks.com>
> Date: Wed, 25 May 2016 23:03:27 +0300
> 
> > On Wed, May 25, 2016 at 12:30:17PM -0700, David Miller wrote:
> >> From: Yury Norov <ynorov at caviumnetworks.com>
> >> Date: Tue, 24 May 2016 03:04:30 +0300
> >> 
> >> > +To clear that top halves, automatic wrappers are introduced. They clear all
> >> > +required registers before passing control to regular syscall handler.
> >> 
> >> Why have one of these for every single compat system call, rather than
> >> simply clearing the top half of all of these registers unconditionally
> >> in the 32-bit system call trap before the system call is invoked?
> >> 
> >> That's what we do on sparc64.
> >> 
> >> And with that, you only need wrappers for the case where there needs
> >> to be proper sign extention of a 32-bit signed argument.
> > 
> > It was discussed as one of possible solutions. The downside of it is
> > that we cannot pass 64-bit types (like off_t) in single register.
> 
> Wrappers can be added for the cases where you'd like to do that.

If we clear the upper halves on the initial entry, we can't use a wrapper
to restore them, so would have to instead pass them as register
pairs as we do on the other 32-bit architectures.

> > The other downside is that we clear top halves for every single
> > syscall, and it looks excessive. So, from spark64 and s390 approaches
> > we choosed second.
> 
> It's like 4 cpu cycles even on crappy sparc64 cpus which only dual
> issue. :)
> 
> And that's a pretty low cost for the benefits if you ask me.

To clarify what we are talking about: These syscalls that normally
pass 64-bit arguments as register pairs are intentionally overridden
to make them faster on ilp32 mode compare to other compat modes:

+#define compat_sys_fadvise64_64        sys_fadvise64_64
+#define compat_sys_fallocate           sys_fallocate
+#define compat_sys_ftruncate64         sys_ftruncate
+#define compat_sys_lookup_dcookie      sys_lookup_dcookie
+#define compat_sys_readahead           sys_readahead
+#define compat_sys_sync_file_range     sys_sync_file_range
+#define compat_sys_truncate64          sys_truncate
+#define sys_llseek                     sys_lseek
+static unsigned long compat_sys_pread64(unsigned int fd,
+               compat_uptr_t __user *ubuf, compat_size_t count, off_t offset)
+{
+       return sys_pread64(fd, (char *) ubuf, count, offset);
+}
+
+static unsigned long compat_sys_pwrite64(unsigned int fd,
+               compat_uptr_t __user *ubuf, compat_size_t count, off_t offset)
+{
+       return sys_pwrite64(fd, (char *) ubuf, count, offset);
+}

If we use the normal calling conventions, we could remove these overrides
along with the respective special-case handling in glibc. None of them
look particularly performance-sensitive, but I could be wrong there.

	Arnd


From davem at davemloft.net  Wed May 25 13:50:39 2016
From: davem at davemloft.net (David Miller)
Date: Wed, 25 May 2016 13:50:39 -0700 (PDT)
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <6293194.tGy03QJ9ME@wuerfel>
References: <20160525200327.GA22395@yury-N73SV>
 <20160525.132145.1271448744307448631.davem@davemloft.net>
 <6293194.tGy03QJ9ME@wuerfel>
Message-ID: <20160525.135039.244098606649448826.davem@davemloft.net>

From: Arnd Bergmann <arnd at arndb.de>
Date: Wed, 25 May 2016 22:47:33 +0200

> If we use the normal calling conventions, we could remove these overrides
> along with the respective special-case handling in glibc. None of them
> look particularly performance-sensitive, but I could be wrong there.

You could set the lowest bit in the system call entry pointer to indicate
the upper-half clears should be elided.


From khilman at baylibre.com  Wed May 25 13:50:58 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 25 May 2016 13:50:58 -0700
Subject: [Patch v5 5/8] firmware: qcom: scm: Convert to streaming DMA APIS
In-Reply-To: <20160525033731.GA30220@hector.attlocal.net> (Andy Gross's
 message of "Tue, 24 May 2016 22:37:31 -0500")
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
 <1463111221-6963-6-git-send-email-andy.gross@linaro.org>
 <CAOi56cVB1Z-gO6Dx0KOSr9wiRF3Y9ahDHe0=qT9WW4MdFMhjng@mail.gmail.com>
 <CAPBZ5Qc0oZ+k_5OiUGU6c9jFfcmAfsK3Uy-s=ONGCSGzCDyYNw@mail.gmail.com>
 <20160525033731.GA30220@hector.attlocal.net>
Message-ID: <7hbn3tg8ul.fsf@baylibre.com>

Andy Gross <andy.gross at linaro.org> writes:

> On Mon, May 23, 2016 at 04:02:06PM -0500, Andy Gross wrote:
>> On 23 May 2016 at 14:26, Kevin Hilman <khilman at kernel.org> wrote:
>> > Hi Andy,
>> >
>> > On Thu, May 12, 2016 at 8:46 PM, Andy Gross <andy.gross at linaro.org> wrote:
>> >> This patch converts the Qualcomm SCM driver to use the streaming DMA APIs
>> >> for communication buffers.
>> >>
>> >> Signed-off-by: Andy Gross <andy.gross at linaro.org>
>> >
>> > This patch has landed in linux-next in the form of commit a551c3dbd689
>> > (firmware: qcom: scm: Convert to streaming DMA APIS), and kernelci.org
>> > found some boot breakage in next-20160523 on apq8064[1] which was
>> > bisected down to this commit.
>> >
>> > I reverted this commit on top of next-20160523 and it no longer
>> > builds, so I didn't validate if things boot again with this patch
>> > reverted.
>> 
>> Ouch I missed this failure.  I'll investigate and get it fixed.
>
> So the root cause was the fact that the DFAB clock required by the SCM is an RPM
> clock.  That support isn't present yet in the kernel, so SCM probe fails.
>
> The core clock is really only accessed so that we can bump the clock on it up to
> the max for performance.  As such, I'll make it optional in the platform code.
>
> This does bring up the issue of probe defer causing issues with the spm driver,
> as it calls set_warm_boot_addr.  That may have to be addressed, but is probably
> a problem best fixed in the spm.

Nice, thanks for the explanation.

Is there a patch somewhere you'd like me to test? or were you able to
dust off an 8064 platform for testing?

Kevin


From josh.coombs at gmail.com  Wed May 25 13:59:31 2016
From: josh.coombs at gmail.com (Josh Coombs)
Date: Wed, 25 May 2016 16:59:31 -0400
Subject: Modern kernel on a Chumby
Message-ID: <CAMW5UfYH6UiaB1ddRT0KBP1thyyebnCw2h4VigYQQ55v4MYqdA@mail.gmail.com>

I've likely bitten off way more than I can chew but I'd like to see if
this is possible:  I have a i.MX21 powered 'original' Chumby happily
running on a modified 2.6.16 kernel, ideally I'd like to do the
legwork to get it running on a current, mainline kernel.  Looking at
4.6 I see a single i.MX21 device supported by a board file, the
mx21ads.  Flipping through the list archives I see discussions of
i.MX21 being moved to device tree operation but I can't see any signs
of any such devices actually being supported that way.

Should I try to bash up support based on the mx21ads or is there a
device tree template I can start from?

Josh C


From arnd at arndb.de  Wed May 25 14:01:06 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 25 May 2016 23:01:06 +0200
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160525.135039.244098606649448826.davem@davemloft.net>
References: <20160525200327.GA22395@yury-N73SV> <6293194.tGy03QJ9ME@wuerfel>
 <20160525.135039.244098606649448826.davem@davemloft.net>
Message-ID: <6407614.fdv5XFSBue@wuerfel>

On Wednesday, May 25, 2016 1:50:39 PM CEST David Miller wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> Date: Wed, 25 May 2016 22:47:33 +0200
> 
> > If we use the normal calling conventions, we could remove these overrides
> > along with the respective special-case handling in glibc. None of them
> > look particularly performance-sensitive, but I could be wrong there.
> 
> You could set the lowest bit in the system call entry pointer to indicate
> the upper-half clears should be elided.

Right, but that would introduce an extra conditional branch in the syscall
hotpath, and likely eliminate the gains from passing the loff_t arguments
in a single register instead of a pair.

	Arnd


From arnd at arndb.de  Wed May 25 14:09:32 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Wed, 25 May 2016 23:09:32 +0200
Subject: Modern kernel on a Chumby
In-Reply-To: <CAMW5UfYH6UiaB1ddRT0KBP1thyyebnCw2h4VigYQQ55v4MYqdA@mail.gmail.com>
References: <CAMW5UfYH6UiaB1ddRT0KBP1thyyebnCw2h4VigYQQ55v4MYqdA@mail.gmail.com>
Message-ID: <4758440.JnRBmYVBjM@wuerfel>

On Wednesday, May 25, 2016 4:59:31 PM CEST Josh Coombs wrote:
> I've likely bitten off way more than I can chew but I'd like to see if
> this is possible:  I have a i.MX21 powered 'original' Chumby happily
> running on a modified 2.6.16 kernel, ideally I'd like to do the
> legwork to get it running on a current, mainline kernel.  Looking at
> 4.6 I see a single i.MX21 device supported by a board file, the
> mx21ads.  Flipping through the list archives I see discussions of
> i.MX21 being moved to device tree operation but I can't see any signs
> of any such devices actually being supported that way.
> 
> Should I try to bash up support based on the mx21ads or is there a
> device tree template I can start from?

I think your best bet is to start from the imx27 DT support.
As I understand, it's closely related to imx21, though it's possible
that you have to add some other drivers.

Alexander Shiyan (added to Cc here) has written DT support for the imx21
clk controller, he may have other patches that never made it upstream,
or have additional information.

	Arnd


From andy.gross at linaro.org  Wed May 25 14:15:29 2016
From: andy.gross at linaro.org (Andy Gross)
Date: Wed, 25 May 2016 16:15:29 -0500
Subject: [Patch v5 5/8] firmware: qcom: scm: Convert to streaming DMA APIS
In-Reply-To: <7hbn3tg8ul.fsf@baylibre.com>
References: <1463111221-6963-1-git-send-email-andy.gross@linaro.org>
 <1463111221-6963-6-git-send-email-andy.gross@linaro.org>
 <CAOi56cVB1Z-gO6Dx0KOSr9wiRF3Y9ahDHe0=qT9WW4MdFMhjng@mail.gmail.com>
 <CAPBZ5Qc0oZ+k_5OiUGU6c9jFfcmAfsK3Uy-s=ONGCSGzCDyYNw@mail.gmail.com>
 <20160525033731.GA30220@hector.attlocal.net>
 <7hbn3tg8ul.fsf@baylibre.com>
Message-ID: <CAPBZ5QdAYR2puF6SmfKi0khQ4BfcdTiW_j0_T43Gh03bZSf64Q@mail.gmail.com>

On 25 May 2016 at 15:50, Kevin Hilman <khilman at baylibre.com> wrote:
> Andy Gross <andy.gross at linaro.org> writes:
>
>> On Mon, May 23, 2016 at 04:02:06PM -0500, Andy Gross wrote:
>>> On 23 May 2016 at 14:26, Kevin Hilman <khilman at kernel.org> wrote:
>>> > Hi Andy,
>>> >
>>> > On Thu, May 12, 2016 at 8:46 PM, Andy Gross <andy.gross at linaro.org> wrote:
>>> >> This patch converts the Qualcomm SCM driver to use the streaming DMA APIs
>>> >> for communication buffers.
>>> >>
>>> >> Signed-off-by: Andy Gross <andy.gross at linaro.org>
>>> >
>>> > This patch has landed in linux-next in the form of commit a551c3dbd689
>>> > (firmware: qcom: scm: Convert to streaming DMA APIS), and kernelci.org
>>> > found some boot breakage in next-20160523 on apq8064[1] which was
>>> > bisected down to this commit.
>>> >
>>> > I reverted this commit on top of next-20160523 and it no longer
>>> > builds, so I didn't validate if things boot again with this patch
>>> > reverted.
>>>
>>> Ouch I missed this failure.  I'll investigate and get it fixed.
>>
>> So the root cause was the fact that the DFAB clock required by the SCM is an RPM
>> clock.  That support isn't present yet in the kernel, so SCM probe fails.
>>
>> The core clock is really only accessed so that we can bump the clock on it up to
>> the max for performance.  As such, I'll make it optional in the platform code.
>>
>> This does bring up the issue of probe defer causing issues with the spm driver,
>> as it calls set_warm_boot_addr.  That may have to be addressed, but is probably
>> a problem best fixed in the spm.
>
> Nice, thanks for the explanation.
>
> Is there a patch somewhere you'd like me to test? or were you able to
> dust off an 8064 platform for testing?

I had the ifc6410, but it took me a while to find the darn 5V supply.
The docs lie when they say 5V-12V.  In any case, I threw a patch on
top of next to fix this.  I need to amend my set of patches to include
these changes and add the DT information for the 8064.

Regards,

Andy


From sakari.ailus at iki.fi  Wed May 25 14:26:59 2016
From: sakari.ailus at iki.fi (Sakari Ailus)
Date: Thu, 26 May 2016 00:26:59 +0300
Subject: [PATCHv4] support for AD5820 camera auto-focus coil
In-Reply-To: <20160524091746.GA14536@amd>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com> <20160521105607.GA20071@amd>
 <574049EF.2090208@gmail.com> <20160524090433.GA1277@amd>
 <20160524091746.GA14536@amd>
Message-ID: <20160525212659.GK26360@valkosipuli.retiisi.org.uk>

Hi Pavel,

Thanks for your continued work on this! :-)

Some quite minor comments below. I think we're good then.

On Tue, May 24, 2016 at 11:17:46AM +0200, Pavel Machek wrote:
> This adds support for AD5820 autofocus coil, found for example in
> Nokia N900 smartphone.
> 
> Signed-off-by: Pavel Machek <pavel at ucw.cz>
> 
> ---
> v2: simple cleanups, fix error paths, simplify probe
> v3: more cleanups, remove printk, add include
> v4: remove header file.
> 
> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> index 993dc50..77313a1 100644
> --- a/drivers/media/i2c/Kconfig
> +++ b/drivers/media/i2c/Kconfig
> @@ -279,6 +279,13 @@ config VIDEO_ML86V7667
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called ml86v7667.
>  
> +config VIDEO_AD5820
> +	tristate "AD5820 lens voice coil support"
> +	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
> +	---help---
> +	  This is a driver for the AD5820 camera lens voice coil.
> +	  It is used for example in Nokia N900 (RX-51).
> +
>  config VIDEO_SAA7110
>  	tristate "Philips SAA7110 video decoder"
>  	depends on VIDEO_V4L2 && I2C
> diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
> index 94f2c99..34434ae 100644
> --- a/drivers/media/i2c/Makefile
> +++ b/drivers/media/i2c/Makefile
> @@ -19,6 +20,7 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
>  obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
>  obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
>  obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
> +obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o
>  obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
>  obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
>  obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
> diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
> new file mode 100644
> index 0000000..f956bd3
> --- /dev/null
> +++ b/drivers/media/i2c/ad5820.c
> @@ -0,0 +1,438 @@
> +/*
> + * drivers/media/i2c/ad5820.c
> + *
> + * AD5820 DAC driver for camera voice coil focus.
> + *
> + * Copyright (C) 2008 Nokia Corporation
> + * Copyright (C) 2007 Texas Instruments
> + * Copyright (C) 2016 Pavel Machek <pavel at ucw.cz>
> + *
> + * Contact: Tuukka Toivonen
> + *          Sakari Ailus

Could you put the e-mail addresses back, please?

Tuukka's e-mail is tuukkat76 at gmail.com .

> + *
> + * Based on af_d88.c by Texas Instruments.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/kernel.h>
> +#include <linux/regulator/consumer.h>

Alphabetical order would be nice. The same below.

> +
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-subdev.h>
> +
> +#define AD5820_NAME		"ad5820"
> +
> +/* Register definitions */
> +#define AD5820_POWER_DOWN		(1 << 15)
> +#define AD5820_DAC_SHIFT		4
> +#define AD5820_RAMP_MODE_LINEAR		(0 << 3)
> +#define AD5820_RAMP_MODE_64_16		(1 << 3)
> +
> +#define CODE_TO_RAMP_US(s)	((s) == 0 ? 0 : (1 << ((s) - 1)) * 50)
> +#define RAMP_US_TO_CODE(c)	fls(((c) + ((c)>>1)) / 50)
> +
> +#define to_ad5820_device(sd)	container_of(sd, struct ad5820_device, subdev)
> +
> +struct ad5820_device {
> +	struct v4l2_subdev subdev;
> +	struct ad5820_platform_data *platform_data;
> +	struct regulator *vana;
> +
> +	struct v4l2_ctrl_handler ctrls;
> +	u32 focus_absolute;
> +	u32 focus_ramp_time;
> +	u32 focus_ramp_mode;
> +
> +	struct mutex power_lock;
> +	int power_count;
> +
> +	int standby : 1;
> +};
> +
> +/**
> + * @brief I2C write using i2c_transfer().
> + * @param coil - the driver data structure
> + * @param data - register value to be written

This does not look entirely right. But you could just remove the entire
comment. It's useless.

> + * @returns nonnegative on success, negative if failed
> + */
> +static int ad5820_write(struct ad5820_device *coil, u16 data)
> +{
> +	struct i2c_client *client = v4l2_get_subdevdata(&coil->subdev);
> +	struct i2c_msg msg;
> +	int r;
> +
> +	if (!client->adapter)
> +		return -ENODEV;
> +
> +	data = cpu_to_be16(data);
> +	msg.addr  = client->addr;
> +	msg.flags = 0;
> +	msg.len   = 2;
> +	msg.buf   = (u8 *)&data;
> +
> +	r = i2c_transfer(client->adapter, &msg, 1);
> +	if (r < 0) {
> +		dev_err(&client->dev, "write failed, error %d\n", r);
> +		return r;
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * Calculate status word and write it to the device based on current
> + * values of V4L2 controls. It is assumed that the stored V4L2 control
> + * values are properly limited and rounded.
> + */
> +static int ad5820_update_hw(struct ad5820_device *coil)
> +{
> +	u16 status;
> +
> +	status = RAMP_US_TO_CODE(coil->focus_ramp_time);
> +	status |= coil->focus_ramp_mode
> +		? AD5820_RAMP_MODE_64_16 : AD5820_RAMP_MODE_LINEAR;
> +	status |= coil->focus_absolute << AD5820_DAC_SHIFT;
> +
> +	if (coil->standby)
> +		status |= AD5820_POWER_DOWN;
> +
> +	return ad5820_write(coil, status);
> +}
> +
> +/*
> + * Power handling
> + */
> +static int ad5820_power_off(struct ad5820_device *coil, int standby)
> +{
> +	int ret = 0;
> +
> +	/*
> +	 * Go to standby first as real power off my be denied by the hardware
> +	 * (single power line control for both coil and sensor).
> +	 */
> +	if (standby) {
> +		coil->standby = 1;
> +		ret = ad5820_update_hw(coil);
> +	}
> +
> +	ret |= regulator_disable(coil->vana);

This is actually an error code and you shouldn't use or to combine two error
codes. The result will make no sense.

It might be the driver did this in the past but it should not be done. The
right thing, as elsewhere, is to assign the value to ret and check it. The
assigment in declaration may be dropped as well.

I think this happens in a few places in the driver.

> +
> +	return ret;
> +}
> +
> +static int ad5820_power_on(struct ad5820_device *coil, int restore)
> +{
> +	int ret;
> +
> +	ret = regulator_enable(coil->vana);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (restore) {
> +		/* Restore the hardware settings. */
> +		coil->standby = 0;
> +		ret = ad5820_update_hw(coil);
> +		if (ret)
> +			goto fail;
> +	}
> +	return 0;
> +
> +fail:
> +	coil->standby = 1;
> +	regulator_disable(coil->vana);
> +
> +	return ret;
> +}
> +
> +/*
> + * V4L2 controls
> + */
> +static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +	struct ad5820_device *coil =
> +		container_of(ctrl->handler, struct ad5820_device, ctrls);
> +	u32 code;
> +
> +	switch (ctrl->id) {
> +	case V4L2_CID_FOCUS_ABSOLUTE:
> +		coil->focus_absolute = ctrl->val;
> +		return ad5820_update_hw(coil);
> +
> +	case V4L2_CID_FOCUS_AD5820_RAMP_TIME:
> +		code = RAMP_US_TO_CODE(ctrl->val);
> +		ctrl->val = CODE_TO_RAMP_US(code);
> +		coil->focus_ramp_time = ctrl->val;
> +		break;
> +
> +	case V4L2_CID_FOCUS_AD5820_RAMP_MODE:
> +		coil->focus_ramp_mode = ctrl->val;
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_ctrl_ops ad5820_ctrl_ops = {
> +	.s_ctrl = ad5820_set_ctrl,
> +};
> +
> +static const char * const ad5820_focus_menu[] = {
> +	"Linear ramp",
> +	"64/16 ramp",
> +};
> +
> +static const struct v4l2_ctrl_config ad5820_ctrls[] = {
> +	{
> +		.ops		= &ad5820_ctrl_ops,
> +		.id		= V4L2_CID_FOCUS_AD5820_RAMP_TIME,
> +		.type		= V4L2_CTRL_TYPE_INTEGER,
> +		.name		= "Focus ramping time [us]",
> +		.min		= 0,
> +		.max		= 3200,
> +		.step		= 50,
> +		.def		= 0,
> +		.flags		= 0,
> +	},
> +	{
> +		.ops		= &ad5820_ctrl_ops,
> +		.id		= V4L2_CID_FOCUS_AD5820_RAMP_MODE,
> +		.type		= V4L2_CTRL_TYPE_MENU,
> +		.name		= "Focus ramping mode",
> +		.min		= 0,
> +		.max		= ARRAY_SIZE(ad5820_focus_menu),
> +		.step		= 0,
> +		.def		= 0,
> +		.flags		= 0,
> +		.qmenu		= ad5820_focus_menu,
> +	},
> +};
> +
> +
> +static int ad5820_init_controls(struct ad5820_device *coil)
> +{
> +	unsigned int i;
> +
> +	v4l2_ctrl_handler_init(&coil->ctrls, ARRAY_SIZE(ad5820_ctrls) + 1);
> +
> +	/*
> +	 * V4L2_CID_FOCUS_ABSOLUTE
> +	 *
> +	 * Minimum current is 0 mA, maximum is 100 mA. Thus, 1 code is
> +	 * equivalent to 100/1023 = 0.0978 mA. Nevertheless, we do not use [mA]
> +	 * for focus position, because it is meaningless for user. Meaningful
> +	 * would be to use focus distance or even its inverse, but since the
> +	 * driver doesn't have sufficiently knowledge to do the conversion, we
> +	 * will just use abstract codes here. In any case, smaller value = focus
> +	 * position farther from camera. The default zero value means focus at
> +	 * infinity, and also least current consumption.
> +	 */
> +	v4l2_ctrl_new_std(&coil->ctrls, &ad5820_ctrl_ops,
> +			  V4L2_CID_FOCUS_ABSOLUTE, 0, 1023, 1, 0);
> +
> +	/* V4L2_CID_TEST_PATTERN and V4L2_CID_MODE_* */
> +	for (i = 0; i < ARRAY_SIZE(ad5820_ctrls); ++i)
> +		v4l2_ctrl_new_custom(&coil->ctrls, &ad5820_ctrls[i], NULL);
> +
> +	if (coil->ctrls.error)
> +		return coil->ctrls.error;
> +
> +	coil->focus_absolute = 0;
> +	coil->focus_ramp_time = 0;
> +	coil->focus_ramp_mode = 0;
> +
> +	coil->subdev.ctrl_handler = &coil->ctrls;
> +
> +	return 0;
> +}
> +
> +/*
> + * V4L2 subdev operations
> + */
> +static int ad5820_registered(struct v4l2_subdev *subdev)
> +{
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +	struct i2c_client *client = v4l2_get_subdevdata(subdev);
> +
> +	coil->vana = regulator_get(&client->dev, "VANA");

Is there a reason not to acquire this in probe instead?

> +	if (IS_ERR(coil->vana)) {
> +		dev_err(&client->dev, "could not get regulator for vana\n");
> +		return -ENODEV;

I wonder if -EPROBE_DEFER might be the right error code here.

> +	}
> +
> +	return ad5820_init_controls(coil);
> +}
> +
> +static int
> +ad5820_set_power(struct v4l2_subdev *subdev, int on)
> +{
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +	int ret = 0;
> +
> +	mutex_lock(&coil->power_lock);
> +
> +	/*
> +	 * If the power count is modified from 0 to != 0 or from != 0 to 0,
> +	 * update the power state.
> +	 */
> +	if (coil->power_count == !on) {
> +		ret = on ? ad5820_power_on(coil, 1) : ad5820_power_off(coil, 1);
> +		if (ret < 0)
> +			goto done;
> +	}
> +
> +	/* Update the power count. */
> +	coil->power_count += on ? 1 : -1;
> +	WARN_ON(coil->power_count < 0);
> +
> +done:
> +	mutex_unlock(&coil->power_lock);
> +	return ret;
> +}
> +
> +static int ad5820_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> +{
> +	return ad5820_set_power(sd, 1);
> +}
> +
> +static int ad5820_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> +{
> +	return ad5820_set_power(sd, 0);
> +}
> +
> +static const struct v4l2_subdev_core_ops ad5820_core_ops = {
> +	.s_power = ad5820_set_power,
> +};
> +
> +static const struct v4l2_subdev_ops ad5820_ops = {
> +	.core = &ad5820_core_ops,
> +};
> +
> +static const struct v4l2_subdev_internal_ops ad5820_internal_ops = {
> +	.registered = ad5820_registered,
> +	.open = ad5820_open,
> +	.close = ad5820_close,
> +};
> +
> +/*
> + * I2C driver
> + */
> +#ifdef CONFIG_PM
> +
> +static int ad5820_suspend(struct device *dev)
> +{
> +	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
> +	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +
> +	if (!coil->power_count)
> +		return 0;
> +
> +	return ad5820_power_off(coil, 0);
> +}
> +
> +static int ad5820_resume(struct device *dev)
> +{
> +	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
> +	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +
> +	if (!coil->power_count)
> +		return 0;
> +
> +	return ad5820_power_on(coil, 1);
> +}
> +
> +#else
> +
> +#define ad5820_suspend	NULL
> +#define ad5820_resume	NULL
> +
> +#endif /* CONFIG_PM */
> +
> +static int ad5820_probe(struct i2c_client *client,
> +			const struct i2c_device_id *devid)
> +{
> +	struct ad5820_device *coil;
> +	int ret = 0;

No need to assign ret here.

> +
> +	coil = kzalloc(sizeof(*coil), GFP_KERNEL);

You could use devm_kzalloc() here and drop kfree() below and in _remove().

The driver might be actually older than the devm_*() functions. Not sure. At
least they were not widely used back then. :-)

> +	if (!coil)
> +		return -ENOMEM;
> +
> +	mutex_init(&coil->power_lock);
> +
> +	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
> +	coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> +	coil->subdev.internal_ops = &ad5820_internal_ops;
> +	strcpy(coil->subdev.name, "ad5820 focus");
> +
> +	ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
> +	if (ret < 0)
> +		goto free;
> +
> +	ret = v4l2_async_register_subdev(&coil->subdev);
> +	if (ret < 0)
> +		goto cleanup;
> +
> +	return ret;
> +
> +cleanup:
> +	media_entity_cleanup(&coil->subdev.entity);
> +
> +free:
> +	kfree(coil);
> +
> +	return ret;
> +}
> +
> +static int __exit ad5820_remove(struct i2c_client *client)
> +{
> +	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
> +	struct ad5820_device *coil = to_ad5820_device(subdev);
> +
> +	v4l2_device_unregister_subdev(&coil->subdev);
> +	v4l2_ctrl_handler_free(&coil->ctrls);
> +	media_entity_cleanup(&coil->subdev.entity);
> +	if (coil->vana)
> +		regulator_put(coil->vana);

mutex_destroy(&coil->power_lock);

Here. And in probe() error paths as well.

> +
> +	kfree(coil);
> +
> +	return 0;
> +}
> +
> +static const struct i2c_device_id ad5820_id_table[] = {
> +	{ AD5820_NAME, 0 },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, ad5820_id_table);
> +
> +static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume);
> +
> +static struct i2c_driver ad5820_i2c_driver = {
> +	.driver		= {
> +		.name	= AD5820_NAME,
> +		.pm	= &ad5820_pm,
> +	},
> +	.probe		= ad5820_probe,
> +	.remove		= __exit_p(ad5820_remove),
> +	.id_table	= ad5820_id_table,
> +};
> +
> +module_i2c_driver(ad5820_i2c_driver);
> +
> +MODULE_AUTHOR("Tuukka Toivonen");
> +MODULE_DESCRIPTION("AD5820 camera lens driver");
> +MODULE_LICENSE("GPL");

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus at iki.fi	XMPP: sailus at retiisi.org.uk


From davem at davemloft.net  Wed May 25 14:28:21 2016
From: davem at davemloft.net (David Miller)
Date: Wed, 25 May 2016 14:28:21 -0700 (PDT)
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <6407614.fdv5XFSBue@wuerfel>
References: <6293194.tGy03QJ9ME@wuerfel>
 <20160525.135039.244098606649448826.davem@davemloft.net>
 <6407614.fdv5XFSBue@wuerfel>
Message-ID: <20160525.142821.1719403997976778673.davem@davemloft.net>

From: Arnd Bergmann <arnd at arndb.de>
Date: Wed, 25 May 2016 23:01:06 +0200

> On Wednesday, May 25, 2016 1:50:39 PM CEST David Miller wrote:
>> From: Arnd Bergmann <arnd at arndb.de>
>> Date: Wed, 25 May 2016 22:47:33 +0200
>> 
>> > If we use the normal calling conventions, we could remove these overrides
>> > along with the respective special-case handling in glibc. None of them
>> > look particularly performance-sensitive, but I could be wrong there.
>> 
>> You could set the lowest bit in the system call entry pointer to indicate
>> the upper-half clears should be elided.
> 
> Right, but that would introduce an extra conditional branch in the syscall
> hotpath, and likely eliminate the gains from passing the loff_t arguments
> in a single register instead of a pair.

Ok, then, how much are you really gaining from avoiding a 'shift' and
an 'or' to build the full 64-bit value?  3 cycles?  Maybe 4?

And the executing the wrappers, those have a non-trivial cost too.

Cost wise, this seems like it all cancels out in the end, but what
do I know?





From f.fainelli at gmail.com  Wed May 25 14:45:00 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Wed, 25 May 2016 14:45:00 -0700
Subject: interrupts properties and API usage with GPIO controllers/Device Tree
Message-ID: <57461CDC.603@gmail.com>

Hi Linus, Gregory,

Recently came across an use case that looks like the following:

gpio0: gpio at deadbeef {
	compatible = "brcm,brcmstb-gpio";
	#interrrupt-cells = <2>;
	#gpio-cells = <2>;
	gpio-controller;
	interrupt-controller;
	...
};

test at cafeb00b {
	interrupt-parent = <&gpio0>;
	interrupts = <99 3>;
};

The driver consuming the test node's interrupts property tries to get
the interrupt by using platform_get_irq() or of_irq_parse_and_map() and
in the case of the gpio-brcmstb.c, this fails because the interrupt is
out of range  as flagged by kernel/irq/irqdomain.c::irq_domain_associate.

Unlike other GPIO provider drivers gpio-brcmstb.c, this driver registers
one gpiolib irqchip per each of its banks, and still uses the generic
map/unmap functions for its irq_domain_ops, so there is no way we can
provide a valid mapping outside of the gpio_to_irq() function
unfortunately since gpiochip_irq_map() does

So here are a few questions for either of you:

- is this a valid API and Device Tree use case: call
of_irq_parse_and_map on an "interrupts" property which has not been
acquired using the GPIO API and then gpio_to_irq? While gpio_to_irq()
works, are not we losing the second specifier in the interrupt cells
about what kind of interrupt type this is?

- would it be acceptable to export gpiochip_irq_map and
gpiochip_irq_export to make them accessible as helpers so we could just
wrap things a bit around or should I just open code the same things and
allow gpiochip_irqchip_add to be passed custom irq_domain_ops for instance?

Thanks!
-- 
Florian


From stefan at agner.ch  Wed May 25 14:54:07 2016
From: stefan at agner.ch (Stefan Agner)
Date: Wed, 25 May 2016 14:54:07 -0700
Subject: [PATCH 1/2] clk: imx: do not sleep if IRQ's are still disabled
In-Reply-To: <alpine.DEB.2.11.1604271212290.3941@nanos>
References: <1454107764-19876-1-git-send-email-stefan@agner.ch>
 <20160421034520.GA19965@shlinux2.ap.freescale.net>
 <20160426012341.GB8870@tiger>
 <CAA+hA=QTNEAaMfjJoMMO5gPR8VPYBWYx=HZgjngUFJK4LxMp=g@mail.gmail.com>
 <1461663072.7839.17.camel@pengutronix.de>
 <CAA+hA=SSQJPbzbhCY7O8JaxiUgMDjG2ATQXsCW-X5zc2inC6kw@mail.gmail.com>
 <CAA+hA=Q5Un7Sib5QEvK4H2PH5qrySAkRR+=ofuaKxX_PCuT-Yw@mail.gmail.com>
 <20160427015835.GE30692@tiger>
 <CAA+hA=REqJ8JhmKt5_jCAaRTUy2E14ww_MqWSSLpNBKgnf=U9A@mail.gmail.com>
 <alpine.DEB.2.11.1604271212290.3941@nanos>
Message-ID: <c3368a10135e304051a56562a1ae0f99@agner.ch>

On 2016-04-27 03:15, Thomas Gleixner wrote:
> On Wed, 27 Apr 2016, Dong Aisheng wrote:
>> Why Stefan's patch works (checking irqs_disabled()) is because during kernel
>> time init, the irq is still not enabled. It fixes the issue indirectly.
>> See:
>> asmlinkage __visible void __init start_kernel(void)
>> {
>>         /*
>>          * Set up the scheduler prior starting any interrupts (such as the
>>          * timer interrupt). Full topology setup happens at smp_init()
>>          * time - but meanwhile we still have a functioning scheduler.
>>          */
>>         sched_init();
>>         .............
>>         time_init();
>>         ..............
>>         WARN(!irqs_disabled(), "Interrupts were enabled early\n");
>>         early_boot_irqs_disabled = false;
>>         local_irq_enable();
>> }
>>
>> The issue can only happen when PLL enable causes a schedule during
>> imx_clock_init().
> 
> Calling a function which might sleep _BEFORE_ kernel_init() is wrong. Don't
> try to work around such an issue by doing magic irq_disabled() checks and busy
> loops. Fix the call site and be done with it.

What do you mean exactly by fix the call site? The patch I proposed
(https://lkml.org/lkml/2016/1/29/695) fixes the call site...

But I see Dong's argument here, irqs_disabled is the wrong way to figure
out whether we are in kernel_init. What is the right approach to
distinguish whether we are allowed to sleep?

--
Stefan


From marex at denx.de  Wed May 25 15:40:42 2016
From: marex at denx.de (Marek Vasut)
Date: Thu, 26 May 2016 00:40:42 +0200
Subject: [PATCH] ARM: dts: socfpga: Add missing PHY phandle
Message-ID: <1464216042-6477-1-git-send-email-marex@denx.de>

Add missing PHY phandle into the DT, otherwise the stmmac code won't
detect the PHY correctly anymore.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Dinh Nguyen <dinguyen at opensource.altera.com>
---
 arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
index a3601e4..b844473 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
+++ b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
@@ -136,6 +136,7 @@
 &gmac1 {
 	status = "okay";
 	phy-mode = "rgmii";
+	phy-handle = <&phy1>;
 
 	snps,reset-gpio = <&porta 0 GPIO_ACTIVE_LOW>;
 	snps,reset-active-low;
-- 
2.7.0



From fengguang.wu at intel.com  Wed May 25 15:45:03 2016
From: fengguang.wu at intel.com (kbuild test robot)
Date: Thu, 26 May 2016 06:45:03 +0800
Subject: [rjarzmik:work/ac97 5/7] sound/soc/codecs/wm9705.c:216:10: error:
 'soc_ac97_ops' undeclared
Message-ID: <201605260600.1KJon77G%fengguang.wu@intel.com>

tree:   https://github.com/rjarzmik/linux work/ac97
head:   6ebaee487a55e240a38df1557d9e6bde652589d2
commit: 4a88e9608287031bea0c753218347fddf8a26f30 [5/7] ASoC: pxa: switch to new ac97 bus support
config: arm-pxa_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        git checkout 4a88e9608287031bea0c753218347fddf8a26f30
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

Note: the rjarzmik/work/ac97 HEAD 6ebaee487a55e240a38df1557d9e6bde652589d2 builds fine.
      It only hurts bisectibility.

All error/warnings (new ones prefixed by >>):

   sound/soc/codecs/wm9705.c: In function 'ac97_read':
>> sound/soc/codecs/wm9705.c:216:10: error: 'soc_ac97_ops' undeclared (first use in this function)
      return soc_ac97_ops->read(ac97, reg);
             ^
   sound/soc/codecs/wm9705.c:216:10: note: each undeclared identifier is reported only once for each function it appears in
   sound/soc/codecs/wm9705.c: In function 'ac97_write':
   sound/soc/codecs/wm9705.c:233:2: error: 'soc_ac97_ops' undeclared (first use in this function)
     soc_ac97_ops->write(ac97, reg, val);
     ^
   sound/soc/codecs/wm9705.c: In function 'wm9705_soc_suspend':
   sound/soc/codecs/wm9705.c:304:2: error: 'soc_ac97_ops' undeclared (first use in this function)
     soc_ac97_ops->write(ac97, AC97_POWERDOWN, 0xffff);
     ^
   sound/soc/codecs/wm9705.c: In function 'wm9705_soc_resume':
   sound/soc/codecs/wm9705.c:321:3: error: 'soc_ac97_ops' undeclared (first use in this function)
      soc_ac97_ops->write(ac97, i, cache[i>>1]);
      ^
   sound/soc/codecs/wm9705.c: In function 'wm9705_soc_probe':
>> sound/soc/codecs/wm9705.c:335:9: error: implicit declaration of function 'snd_soc_new_ac97_codec' [-Werror=implicit-function-declaration]
     ac97 = snd_soc_new_ac97_codec(codec, WM9705_VENDOR_ID,
            ^
>> sound/soc/codecs/wm9705.c:335:7: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
     ac97 = snd_soc_new_ac97_codec(codec, WM9705_VENDOR_ID,
          ^
   sound/soc/codecs/wm9705.c: In function 'wm9705_soc_remove':
>> sound/soc/codecs/wm9705.c:351:2: error: implicit declaration of function 'snd_soc_free_ac97_codec' [-Werror=implicit-function-declaration]
     snd_soc_free_ac97_codec(ac97);
     ^
   cc1: some warnings being treated as errors

vim +/soc_ac97_ops +216 sound/soc/codecs/wm9705.c

2aceefef Ian Molton         2009-01-16  210  	u16 *cache = codec->reg_cache;
2aceefef Ian Molton         2009-01-16  211  
2aceefef Ian Molton         2009-01-16  212  	switch (reg) {
2aceefef Ian Molton         2009-01-16  213  	case AC97_RESET:
2aceefef Ian Molton         2009-01-16  214  	case AC97_VENDOR_ID1:
2aceefef Ian Molton         2009-01-16  215  	case AC97_VENDOR_ID2:
358a8bb5 Lars-Peter Clausen 2014-11-10 @216  		return soc_ac97_ops->read(ac97, reg);
2aceefef Ian Molton         2009-01-16  217  	default:
2aceefef Ian Molton         2009-01-16  218  		reg = reg >> 1;
2aceefef Ian Molton         2009-01-16  219  
2aceefef Ian Molton         2009-01-16  220  		if (reg >= (ARRAY_SIZE(wm9705_reg)))
2aceefef Ian Molton         2009-01-16  221  			return -EIO;
2aceefef Ian Molton         2009-01-16  222  
2aceefef Ian Molton         2009-01-16  223  		return cache[reg];
2aceefef Ian Molton         2009-01-16  224  	}
2aceefef Ian Molton         2009-01-16  225  }
2aceefef Ian Molton         2009-01-16  226  
2aceefef Ian Molton         2009-01-16  227  static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
2aceefef Ian Molton         2009-01-16  228  	unsigned int val)
2aceefef Ian Molton         2009-01-16  229  {
358a8bb5 Lars-Peter Clausen 2014-11-10  230  	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
2aceefef Ian Molton         2009-01-16  231  	u16 *cache = codec->reg_cache;
2aceefef Ian Molton         2009-01-16  232  
358a8bb5 Lars-Peter Clausen 2014-11-10  233  	soc_ac97_ops->write(ac97, reg, val);
2aceefef Ian Molton         2009-01-16  234  	reg = reg >> 1;
2aceefef Ian Molton         2009-01-16  235  	if (reg < (ARRAY_SIZE(wm9705_reg)))
2aceefef Ian Molton         2009-01-16  236  		cache[reg] = val;
2aceefef Ian Molton         2009-01-16  237  
2aceefef Ian Molton         2009-01-16  238  	return 0;
2aceefef Ian Molton         2009-01-16  239  }
2aceefef Ian Molton         2009-01-16  240  
2aceefef Ian Molton         2009-01-16  241  static int ac97_prepare(struct snd_pcm_substream *substream,
2aceefef Ian Molton         2009-01-16  242  			struct snd_soc_dai *dai)
2aceefef Ian Molton         2009-01-16  243  {
e6968a17 Mark Brown         2012-04-04  244  	struct snd_soc_codec *codec = dai->codec;
2aceefef Ian Molton         2009-01-16  245  	int reg;
2aceefef Ian Molton         2009-01-16  246  	u16 vra;
2aceefef Ian Molton         2009-01-16  247  
2aceefef Ian Molton         2009-01-16  248  	vra = ac97_read(codec, AC97_EXTENDED_STATUS);
2aceefef Ian Molton         2009-01-16  249  	ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
2aceefef Ian Molton         2009-01-16  250  
2aceefef Ian Molton         2009-01-16  251  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
2aceefef Ian Molton         2009-01-16  252  		reg = AC97_PCM_FRONT_DAC_RATE;
2aceefef Ian Molton         2009-01-16  253  	else
2aceefef Ian Molton         2009-01-16  254  		reg = AC97_PCM_LR_ADC_RATE;
2aceefef Ian Molton         2009-01-16  255  
019ec505 Fabio Estevam      2012-04-10  256  	return ac97_write(codec, reg, substream->runtime->rate);
2aceefef Ian Molton         2009-01-16  257  }
2aceefef Ian Molton         2009-01-16  258  
2aceefef Ian Molton         2009-01-16  259  #define WM9705_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \
2aceefef Ian Molton         2009-01-16  260  			SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
2aceefef Ian Molton         2009-01-16  261  			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
2aceefef Ian Molton         2009-01-16  262  			SNDRV_PCM_RATE_48000)
2aceefef Ian Molton         2009-01-16  263  
85e7652d Lars-Peter Clausen 2011-11-23  264  static const struct snd_soc_dai_ops wm9705_dai_ops = {
6335d055 Eric Miao          2009-03-03  265  	.prepare	= ac97_prepare,
6335d055 Eric Miao          2009-03-03  266  };
6335d055 Eric Miao          2009-03-03  267  
f0fba2ad Liam Girdwood      2010-03-17  268  static struct snd_soc_dai_driver wm9705_dai[] = {
2aceefef Ian Molton         2009-01-16  269  	{
f0fba2ad Liam Girdwood      2010-03-17  270  		.name = "wm9705-hifi",
2aceefef Ian Molton         2009-01-16  271  		.playback = {
2aceefef Ian Molton         2009-01-16  272  			.stream_name = "HiFi Playback",
2aceefef Ian Molton         2009-01-16  273  			.channels_min = 1,
2aceefef Ian Molton         2009-01-16  274  			.channels_max = 2,
2aceefef Ian Molton         2009-01-16  275  			.rates = WM9705_AC97_RATES,
33f503c9 Mark Brown         2009-05-02  276  			.formats = SND_SOC_STD_AC97_FMTS,
2aceefef Ian Molton         2009-01-16  277  		},
2aceefef Ian Molton         2009-01-16  278  		.capture = {
2aceefef Ian Molton         2009-01-16  279  			.stream_name = "HiFi Capture",
2aceefef Ian Molton         2009-01-16  280  			.channels_min = 1,
2aceefef Ian Molton         2009-01-16  281  			.channels_max = 2,
2aceefef Ian Molton         2009-01-16  282  			.rates = WM9705_AC97_RATES,
33f503c9 Mark Brown         2009-05-02  283  			.formats = SND_SOC_STD_AC97_FMTS,
2aceefef Ian Molton         2009-01-16  284  		},
6335d055 Eric Miao          2009-03-03  285  		.ops = &wm9705_dai_ops,
2aceefef Ian Molton         2009-01-16  286  	},
2aceefef Ian Molton         2009-01-16  287  	{
f0fba2ad Liam Girdwood      2010-03-17  288  		.name = "wm9705-aux",
2aceefef Ian Molton         2009-01-16  289  		.playback = {
2aceefef Ian Molton         2009-01-16  290  			.stream_name = "Aux Playback",
2aceefef Ian Molton         2009-01-16  291  			.channels_min = 1,
2aceefef Ian Molton         2009-01-16  292  			.channels_max = 1,
2aceefef Ian Molton         2009-01-16  293  			.rates = WM9705_AC97_RATES,
2aceefef Ian Molton         2009-01-16  294  			.formats = SNDRV_PCM_FMTBIT_S16_LE,
2aceefef Ian Molton         2009-01-16  295  		},
2aceefef Ian Molton         2009-01-16  296  	}
2aceefef Ian Molton         2009-01-16  297  };
2aceefef Ian Molton         2009-01-16  298  
0a11b168 Mark Brown         2009-04-02  299  #ifdef CONFIG_PM
84b315ee Lars-Peter Clausen 2011-12-02  300  static int wm9705_soc_suspend(struct snd_soc_codec *codec)
0a11b168 Mark Brown         2009-04-02  301  {
358a8bb5 Lars-Peter Clausen 2014-11-10  302  	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
358a8bb5 Lars-Peter Clausen 2014-11-10  303  
358a8bb5 Lars-Peter Clausen 2014-11-10 @304  	soc_ac97_ops->write(ac97, AC97_POWERDOWN, 0xffff);
0a11b168 Mark Brown         2009-04-02  305  
0a11b168 Mark Brown         2009-04-02  306  	return 0;
0a11b168 Mark Brown         2009-04-02  307  }
0a11b168 Mark Brown         2009-04-02  308  
f0fba2ad Liam Girdwood      2010-03-17  309  static int wm9705_soc_resume(struct snd_soc_codec *codec)
0a11b168 Mark Brown         2009-04-02  310  {
358a8bb5 Lars-Peter Clausen 2014-11-10  311  	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
0a11b168 Mark Brown         2009-04-02  312  	int i, ret;
0a11b168 Mark Brown         2009-04-02  313  	u16 *cache = codec->reg_cache;
0a11b168 Mark Brown         2009-04-02  314  
6e0b73a0 Lars-Peter Clausen 2015-07-21  315  	ret = snd_ac97_reset(ac97, true, WM9705_VENDOR_ID,
6e0b73a0 Lars-Peter Clausen 2015-07-21  316  		WM9705_VENDOR_ID_MASK);
9cf766f6 Lars-Peter Clausen 2014-10-30  317  	if (ret < 0)
0a11b168 Mark Brown         2009-04-02  318  		return ret;
0a11b168 Mark Brown         2009-04-02  319  
0a11b168 Mark Brown         2009-04-02  320  	for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) {
358a8bb5 Lars-Peter Clausen 2014-11-10 @321  		soc_ac97_ops->write(ac97, i, cache[i>>1]);
0a11b168 Mark Brown         2009-04-02  322  	}
0a11b168 Mark Brown         2009-04-02  323  
0a11b168 Mark Brown         2009-04-02  324  	return 0;
0a11b168 Mark Brown         2009-04-02  325  }
0a11b168 Mark Brown         2009-04-02  326  #else
0a11b168 Mark Brown         2009-04-02  327  #define wm9705_soc_suspend NULL
0a11b168 Mark Brown         2009-04-02  328  #define wm9705_soc_resume NULL
0a11b168 Mark Brown         2009-04-02  329  #endif
0a11b168 Mark Brown         2009-04-02  330  
f0fba2ad Liam Girdwood      2010-03-17  331  static int wm9705_soc_probe(struct snd_soc_codec *codec)
2aceefef Ian Molton         2009-01-16  332  {
358a8bb5 Lars-Peter Clausen 2014-11-10  333  	struct snd_ac97 *ac97;
2aceefef Ian Molton         2009-01-16  334  
6e0b73a0 Lars-Peter Clausen 2015-07-21 @335  	ac97 = snd_soc_new_ac97_codec(codec, WM9705_VENDOR_ID,
6e0b73a0 Lars-Peter Clausen 2015-07-21  336  		WM9705_VENDOR_ID_MASK);
358a8bb5 Lars-Peter Clausen 2014-11-10  337  	if (IS_ERR(ac97)) {
9cf766f6 Lars-Peter Clausen 2014-10-30  338  		dev_err(codec->dev, "Failed to register AC97 codec\n");
6e0b73a0 Lars-Peter Clausen 2015-07-21  339  		return PTR_ERR(ac97);
2aceefef Ian Molton         2009-01-16  340  	}
2aceefef Ian Molton         2009-01-16  341  
f8d71be5 Lars-Peter Clausen 2015-01-23  342  	snd_soc_codec_set_drvdata(codec, ac97);
2aceefef Ian Molton         2009-01-16  343  
2aceefef Ian Molton         2009-01-16  344  	return 0;
2aceefef Ian Molton         2009-01-16  345  }
2aceefef Ian Molton         2009-01-16  346  
f0fba2ad Liam Girdwood      2010-03-17  347  static int wm9705_soc_remove(struct snd_soc_codec *codec)
2aceefef Ian Molton         2009-01-16  348  {
358a8bb5 Lars-Peter Clausen 2014-11-10  349  	struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec);
358a8bb5 Lars-Peter Clausen 2014-11-10  350  
358a8bb5 Lars-Peter Clausen 2014-11-10 @351  	snd_soc_free_ac97_codec(ac97);
2aceefef Ian Molton         2009-01-16  352  	return 0;
2aceefef Ian Molton         2009-01-16  353  }
2aceefef Ian Molton         2009-01-16  354  

:::::: The code at line 216 was first introduced by commit
:::::: 358a8bb5628420529e4f0b77068155ca8fa8973b ASoC: ac97: Push snd_ac97 pointer to the driver level

:::::: TO: Lars-Peter Clausen <lars at metafoo.de>
:::::: CC: Mark Brown <broonie at kernel.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 30274 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160526/9534937c/attachment-0001.obj>

From sboyd at codeaurora.org  Wed May 25 15:46:23 2016
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Wed, 25 May 2016 15:46:23 -0700
Subject: [PATCH] tty: serial: msm: Disable restoring Rx interrupts for
 DMA Mode
In-Reply-To: <5cce36b3c1d62816feffb4048f782b20@codeaurora.org>
References: <1462896580-11554-1-git-send-email-absahu@codeaurora.org>
 <20160512014126.GK3492@codeaurora.org>
 <20160512050245.GD8453@hector.attlocal.net>
 <5cce36b3c1d62816feffb4048f782b20@codeaurora.org>
Message-ID: <20160525224623.GS3492@codeaurora.org>

On 05/13, charanya at codeaurora.org wrote:
> Hi Stephen/Andy,
> 
> If both Tx and Rx are used simultaneously, restoring Rx interrupts in
> msm_complete_rx_dma could lead to RXSTALE interrupt being triggered,
> when
> the ISR execution for TXLEV interrupt is completed, since
> msm_port->imr is
> rewritten to UART_IMR in msm_uart_irq. Hence, we do not have to restore
> Rx interrupts since Rx is always in DMA mode once enabled.
> 

Ok, but what's the exact sequence of events that happens? I think
we unlock the spinlock in the dma completion handler and then the
txlev interrupt runs? At that point we may have more data to push
out and then rx stale handling runs and corrupts the fifo state?

I was hoping for some sort of CPU sequence of events like:

 CPU0                   CPU1
 ----                   ----

 msm_start_rx_dma()
                       msm_complete_rx_dma()
		        spin_unlock_irqrestore(&port->lock)
 msm_uart_irq()
  msm_handle_rx_dm()
   <Read from FIFO and breaks>
                        
This patch seems correct, but the commit text isn't fully
describing the sequence of events that causes this to happen, so
it's taking a while to convince myself that this patch fixes
anything.

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


From dhdang at apm.com  Wed May 25 16:13:35 2016
From: dhdang at apm.com (Duc Dang)
Date: Wed, 25 May 2016 16:13:35 -0700
Subject: [PATCH] PCI/MSI: pci-xgene-msi: Enable MSI support in ACPI boot
 for X-Gene v1
In-Reply-To: <20160225173822.GA6349@red-moon>
References: <1455069384-22323-1-git-send-email-dhdang@apm.com>
 <1456330151.5681.46.camel@redhat.com> <56CDD767.6020103@arm.com>
 <CADaLND=mrkxOWOzcEb8os16Rb=SDHfnn_8eSgB4bQYH3UguS3w@mail.gmail.com>
 <20160225173822.GA6349@red-moon>
Message-ID: <CADaLNDnywVPER9QhmK4C6JyCLhta_M_cVSOuSkEHnmnLPFo3JA@mail.gmail.com>

On Thu, Feb 25, 2016 at 9:38 AM, Lorenzo Pieralisi
<lorenzo.pieralisi at arm.com> wrote:
> On Wed, Feb 24, 2016 at 02:28:10PM -0800, Duc Dang wrote:
>> On Wed, Feb 24, 2016 at 8:16 AM, Marc Zyngier <marc.zyngier at arm.com> wrote:
>> > On 24/02/16 16:09, Mark Salter wrote:
>> >> On Tue, 2016-02-09 at 17:56 -0800, Duc Dang wrote:
>> >>> This patch makes pci-xgene-msi driver ACPI-aware and provides
>> >>> MSI capability for X-Gene v1 PCIe controllers in ACPI boot mode.
>> >>>
>> >>> Signed-off-by: Duc Dang <dhdang at apm.com>
>> >>> ---
>> >>>  drivers/pci/host/pci-xgene-msi.c | 35 ++++++++++++++++++++++++++++++++---
>> >>>  1 file changed, 32 insertions(+), 3 deletions(-)
>> >>>
>> >>> diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c
>> >>> index a6456b5..466aa93 100644
>> >>> --- a/drivers/pci/host/pci-xgene-msi.c
>> >>> +++ b/drivers/pci/host/pci-xgene-msi.c
>> >>> @@ -24,6 +24,7 @@
>> >>>  #include <linux/pci.h>
>> >>>  #include <linux/platform_device.h>
>> >>>  #include <linux/of_pci.h>
>> >>> +#include <linux/acpi.h>
>> >>>
>> >>>  #define MSI_IR0                     0x000000
>> >>>  #define MSI_INT0            0x800000
>> >>> @@ -39,7 +40,7 @@ struct xgene_msi_group {
>> >>>  };
>> >>>
>> >>>  struct xgene_msi {
>> >>> -    struct device_node      *node;
>> >>> +    struct fwnode_handle    *fwnode;
>> >>>      struct irq_domain       *inner_domain;
>> >>>      struct irq_domain       *msi_domain;
>> >>>      u64                     msi_addr;
>> >>> @@ -249,6 +250,13 @@ static const struct irq_domain_ops msi_domain_ops = {
>> >>>      .free   = xgene_irq_domain_free,
>> >>>  };
>> >>>
>> >>> +#ifdef CONFIG_ACPI
>> >>> +static struct fwnode_handle *xgene_msi_get_fwnode(struct device *dev)
>> >>> +{
>> >>> +    return xgene_msi_ctrl.fwnode;
>> >>> +}
>> >>> +#endif
>> >>> +
>> >>>  static int xgene_allocate_domains(struct xgene_msi *msi)
>> >>>  {
>> >>>      msi->inner_domain = irq_domain_add_linear(NULL, NR_MSI_VEC,
>> >>> @@ -256,7 +264,7 @@ static int xgene_allocate_domains(struct xgene_msi *msi)
>> >>>      if (!msi->inner_domain)
>> >>>              return -ENOMEM;
>> >>>
>> >>> -    msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(msi->node),
>> >>> +    msi->msi_domain = pci_msi_create_irq_domain(msi->fwnode,
>> >>>                                                  &xgene_msi_domain_info,
>> >>>                                                  msi->inner_domain);
>> >>
>> >> This doesn't work for me (ACPI probing on Mustang) unless I change this
>> >> to be pci_msi_create_default_irq_domain(). The problem seems to be that
>> >> the MSI probe happens after the PCIe RC is probed so there is no MSI domain
>> >> at the time the PCIe root is initialized by ACPI.
>> >
>> > pci_msi_create_default_irq_domain is the wrong thing do use, specially
>> > if you have multiple MSI controllers in the system. I certainly wouldn't
>> > want to see it being used on arm64.
>> >
>> > This is the usual dependency hell. You try moving the probing earlier,
>> > but that may break something else in the process.
>>
>> Hi Mark and Marc,
>>
>> I have modified Tianocore firmware to have MSI node declared before
>> PCIe node in Dsdt table. With this modification, the MSI driver will
>> be loaded before PCIe driver and MSI domain is available at the time
>> PCIe root is initialized.
>
> I am totally against this. We should not hack ACPI tables to make
> the kernel work (on top of that with unwritten ordering rules that may
> well require changes as kernel evolves), we should have a standard set
> of bindings that people use to describe HW in the DSDT and the kernel(s)
> has to cope with that. If there is a dependency problem in the description
> we may solve it at bindings level, but I absolutely do not want to rely
> on DSDT nodes ordering for things to work, that's fragile, no shortcuts
> please.

Hi Lorenzo, Bjorn,

(Refresh this thread on this merge cycle)

I tried to use _DEP method to describe the dependency of PCIe node to
MSI node but it turns out that PCIe driver does not check for the
dependency (only EC (ec.c) and I2C core (i2c-core.c) use
acpi_walk_dep_device_list to check for dependency before loading
dependent drivers)

Do you have other suggestion/example about how to ensure strict
ordering on driver loading in ACPI boot mode without changing the
order of ACPI nodes in DSDT?

Regards,
Duc Dang.
>
> Thanks,
> Lorenzo


From fengguang.wu at intel.com  Wed May 25 16:15:45 2016
From: fengguang.wu at intel.com (kbuild test robot)
Date: Thu, 26 May 2016 07:15:45 +0800
Subject: [rjarzmik:work/ac97 5/7] sound/ac97/bus.c:203:5: error: redefinition
 of 'snd_ac97_controller_register'
Message-ID: <201605260742.grC8535B%fengguang.wu@intel.com>

tree:   https://github.com/rjarzmik/linux work/ac97
head:   6ebaee487a55e240a38df1557d9e6bde652589d2
commit: 4a88e9608287031bea0c753218347fddf8a26f30 [5/7] ASoC: pxa: switch to new ac97 bus support
config: arm-cm_x300_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        git checkout 4a88e9608287031bea0c753218347fddf8a26f30
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

Note: the rjarzmik/work/ac97 HEAD 6ebaee487a55e240a38df1557d9e6bde652589d2 builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

>> sound/ac97/bus.c:154:5: error: redefinition of 'snd_ac97_codec_driver_register'
    int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv)
        ^
   In file included from sound/ac97/bus.c:18:0:
   include/sound/ac97/codec.h:84:12: note: previous definition of 'snd_ac97_codec_driver_register' was here
    static int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv)
               ^
>> sound/ac97/bus.c:174:6: error: redefinition of 'snd_ac97_codec_driver_unregister'
    void snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv)
         ^
   In file included from sound/ac97/bus.c:18:0:
   include/sound/ac97/codec.h:88:13: note: previous definition of 'snd_ac97_codec_driver_unregister' was here
    static void snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv)
                ^
>> sound/ac97/bus.c:203:5: error: redefinition of 'snd_ac97_controller_register'
    int snd_ac97_controller_register(const struct ac97_controller_ops *ops,
        ^
   In file included from sound/ac97/bus.c:19:0:
   include/sound/ac97/controller.h:42:12: note: previous definition of 'snd_ac97_controller_register' was here
    static int snd_ac97_controller_register(const struct ac97_controller_ops *ops,
               ^
>> sound/ac97/bus.c:233:5: error: redefinition of 'snd_ac97_controller_unregister'
    int snd_ac97_controller_unregister(const struct device *dev)
        ^
   In file included from sound/ac97/bus.c:19:0:
   include/sound/ac97/controller.h:49:12: note: previous definition of 'snd_ac97_controller_unregister' was here
    static int snd_ac97_controller_unregister(const struct device *dev)
               ^
   In file included from sound/ac97/bus.c:18:0:
   include/sound/ac97/codec.h:84:12: warning: 'snd_ac97_codec_driver_register' defined but not used [-Wunused-function]
    static int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv)
               ^
   include/sound/ac97/codec.h:88:13: warning: 'snd_ac97_codec_driver_unregister' defined but not used [-Wunused-function]
    static void snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv)
                ^
   In file included from sound/ac97/bus.c:19:0:
   include/sound/ac97/controller.h:42:12: warning: 'snd_ac97_controller_register' defined but not used [-Wunused-function]
    static int snd_ac97_controller_register(const struct ac97_controller_ops *ops,
               ^
   include/sound/ac97/controller.h:49:12: warning: 'snd_ac97_controller_unregister' defined but not used [-Wunused-function]
    static int snd_ac97_controller_unregister(const struct device *dev)
               ^

vim +/snd_ac97_controller_register +203 sound/ac97/bus.c

0db28e61 Robert Jarzmik 2016-04-16  148   *
0db28e61 Robert Jarzmik 2016-04-16  149   * Register an AC97 codec driver to the ac97 bus driver, aka. the AC97 digital
0db28e61 Robert Jarzmik 2016-04-16  150   * controller.
0db28e61 Robert Jarzmik 2016-04-16  151   *
0db28e61 Robert Jarzmik 2016-04-16  152   * Returns 0 on success or error code
0db28e61 Robert Jarzmik 2016-04-16  153   */
0db28e61 Robert Jarzmik 2016-04-16 @154  int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv)
0db28e61 Robert Jarzmik 2016-04-16  155  {
0db28e61 Robert Jarzmik 2016-04-16  156  	int ret;
0db28e61 Robert Jarzmik 2016-04-16  157  
0db28e61 Robert Jarzmik 2016-04-16  158  	drv->driver.bus = &ac97_bus_type;
0db28e61 Robert Jarzmik 2016-04-16  159  
0db28e61 Robert Jarzmik 2016-04-16  160  	ret = driver_register(&drv->driver);
0db28e61 Robert Jarzmik 2016-04-16  161  	if (!ret)
0db28e61 Robert Jarzmik 2016-04-16  162  		ac97_rescan_all_controllers();
0db28e61 Robert Jarzmik 2016-04-16  163  
0db28e61 Robert Jarzmik 2016-04-16  164  	return ret;
0db28e61 Robert Jarzmik 2016-04-16  165  }
0db28e61 Robert Jarzmik 2016-04-16  166  EXPORT_SYMBOL(snd_ac97_codec_driver_register);
0db28e61 Robert Jarzmik 2016-04-16  167  
0db28e61 Robert Jarzmik 2016-04-16  168  /**
0db28e61 Robert Jarzmik 2016-04-16  169   * snd_ac97_codec_driver_unregister - unregister an AC97 codec driver
0db28e61 Robert Jarzmik 2016-04-16  170   * @dev: AC97 codec driver to unregister
0db28e61 Robert Jarzmik 2016-04-16  171   *
0db28e61 Robert Jarzmik 2016-04-16  172   * Unregister a previously registered ac97 codec driver.
0db28e61 Robert Jarzmik 2016-04-16  173   */
0db28e61 Robert Jarzmik 2016-04-16 @174  void snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv)
0db28e61 Robert Jarzmik 2016-04-16  175  {
0db28e61 Robert Jarzmik 2016-04-16  176  	driver_unregister(&drv->driver);
0db28e61 Robert Jarzmik 2016-04-16  177  }
0db28e61 Robert Jarzmik 2016-04-16  178  EXPORT_SYMBOL(snd_ac97_codec_driver_unregister);
0db28e61 Robert Jarzmik 2016-04-16  179  
0db28e61 Robert Jarzmik 2016-04-16  180  static int ac97_ctrl_codecs_unregister(struct ac97_controller *ac97_ctrl)
0db28e61 Robert Jarzmik 2016-04-16  181  {
0db28e61 Robert Jarzmik 2016-04-16  182  	int i;
0db28e61 Robert Jarzmik 2016-04-16  183  
0db28e61 Robert Jarzmik 2016-04-16  184  	for (i = 0; i < AC97_BUS_MAX_CODECS; i++)
0db28e61 Robert Jarzmik 2016-04-16  185  		if (ac97_ctrl->codecs[i])
0db28e61 Robert Jarzmik 2016-04-16  186  			put_device(&ac97_ctrl->codecs[i]->dev);
0db28e61 Robert Jarzmik 2016-04-16  187  
0db28e61 Robert Jarzmik 2016-04-16  188  	return 0;
0db28e61 Robert Jarzmik 2016-04-16  189  }
0db28e61 Robert Jarzmik 2016-04-16  190  
0db28e61 Robert Jarzmik 2016-04-16  191  /**
0db28e61 Robert Jarzmik 2016-04-16  192   * snd_ac97_controller_register - register an ac97 controller
0db28e61 Robert Jarzmik 2016-04-16  193   * @ops: the ac97 bus operations
0db28e61 Robert Jarzmik 2016-04-16  194   * @dev: the device providing the ac97 DC function
0db28e61 Robert Jarzmik 2016-04-16  195   * @slots_available: mask of the ac97 codecs that can be scanned and probed
0db28e61 Robert Jarzmik 2016-04-16  196   *                   bit0 => codec 0, bit1 => codec 1 ... bit 3 => codec 3
0db28e61 Robert Jarzmik 2016-04-16  197   *
0db28e61 Robert Jarzmik 2016-04-16  198   * Register a digital controller which can control up to 4 ac97 codecs. This is
0db28e61 Robert Jarzmik 2016-04-16  199   * the controller side of the AC97 AC-link, while the slave side are the codecs.
0db28e61 Robert Jarzmik 2016-04-16  200   *
0db28e61 Robert Jarzmik 2016-04-16  201   * Returns 0 upon success, negative value upon error
0db28e61 Robert Jarzmik 2016-04-16  202   */
0db28e61 Robert Jarzmik 2016-04-16 @203  int snd_ac97_controller_register(const struct ac97_controller_ops *ops,
0db28e61 Robert Jarzmik 2016-04-16  204  				 struct device *dev,
0db28e61 Robert Jarzmik 2016-04-16  205  				 unsigned short slots_available)
0db28e61 Robert Jarzmik 2016-04-16  206  {
0db28e61 Robert Jarzmik 2016-04-16  207  	struct ac97_controller *ac97_ctrl;
0db28e61 Robert Jarzmik 2016-04-16  208  
0db28e61 Robert Jarzmik 2016-04-16  209  	ac97_ctrl = kzalloc(sizeof(*ac97_ctrl), GFP_KERNEL);
0db28e61 Robert Jarzmik 2016-04-16  210  	if (!ac97_ctrl)
0db28e61 Robert Jarzmik 2016-04-16  211  		return -ENOMEM;
0db28e61 Robert Jarzmik 2016-04-16  212  
0db28e61 Robert Jarzmik 2016-04-16  213  	mutex_lock(&ac97_controllers_mutex);
0db28e61 Robert Jarzmik 2016-04-16  214  	ac97_ctrl->ops = ops;
0db28e61 Robert Jarzmik 2016-04-16  215  	ac97_ctrl->slots_available = slots_available;
0db28e61 Robert Jarzmik 2016-04-16  216  	ac97_ctrl->dev = dev;
0db28e61 Robert Jarzmik 2016-04-16  217  	list_add(&ac97_ctrl->controllers, &ac97_controllers);
0db28e61 Robert Jarzmik 2016-04-16  218  	mutex_unlock(&ac97_controllers_mutex);
0db28e61 Robert Jarzmik 2016-04-16  219  
0db28e61 Robert Jarzmik 2016-04-16  220  	ac97_bus_reset(ac97_ctrl);
0db28e61 Robert Jarzmik 2016-04-16  221  	ac97_bus_scan(ac97_ctrl);
0db28e61 Robert Jarzmik 2016-04-16  222  
0db28e61 Robert Jarzmik 2016-04-16  223  	return 0;
0db28e61 Robert Jarzmik 2016-04-16  224  }
0db28e61 Robert Jarzmik 2016-04-16  225  EXPORT_SYMBOL(snd_ac97_controller_register);
0db28e61 Robert Jarzmik 2016-04-16  226  
0db28e61 Robert Jarzmik 2016-04-16  227  /**
0db28e61 Robert Jarzmik 2016-04-16  228   * snd_ac97_controller_unregister - unregister an ac97 controller
0db28e61 Robert Jarzmik 2016-04-16  229   * @dev: the device previously provided to ac97_controller_register()
0db28e61 Robert Jarzmik 2016-04-16  230   *
0db28e61 Robert Jarzmik 2016-04-16  231   * Returns 0 on success, negative upon error
0db28e61 Robert Jarzmik 2016-04-16  232   */
0db28e61 Robert Jarzmik 2016-04-16 @233  int snd_ac97_controller_unregister(const struct device *dev)
0db28e61 Robert Jarzmik 2016-04-16  234  {
0db28e61 Robert Jarzmik 2016-04-16  235  	struct ac97_controller *ac97_ctrl, *tmp;
0db28e61 Robert Jarzmik 2016-04-16  236  	int ret = -ENODEV, i;

:::::: The code at line 203 was first introduced by commit
:::::: 0db28e61f85c1ce51190acf236629fb33d65b2cd ALSA: ac97: add an ac97 bus

:::::: TO: Robert Jarzmik <robert.jarzmik at free.fr>
:::::: CC: Robert Jarzmik <robert.jarzmik at free.fr>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 17696 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160526/fcc30950/attachment-0001.obj>

From smbarber at chromium.org  Wed May 25 17:07:01 2016
From: smbarber at chromium.org (Stephen Barber)
Date: Wed, 25 May 2016 17:07:01 -0700
Subject: [PATCH] clk: rockchip: add a dummy clock for the watchdog pclk on
 rk3399
In-Reply-To: <1464166316-22480-1-git-send-email-zhengxing@rock-chips.com>
References: <1464166316-22480-1-git-send-email-zhengxing@rock-chips.com>
Message-ID: <CADR9n4_D2WdEvj8XdZ_yW4n5-K6jeDWkhZJbGbmeR59zvyUp+w@mail.gmail.com>

On Wed, May 25, 2016 at 1:51 AM, Xing Zheng <zhengxing at rock-chips.com> wrote:
> Like rk3288, the pclk supplying the watchdog is controlled via the
> SGRF register area. Additionally the SGRF isn't even writable in
> every boot mode.
>
> But still the clock control is available and in the future someone
> might want to use it. Therefore define a simple clock for the time
> being so that the watchdog driver can read its rate.
>
> Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
> ---
>
>  drivers/clk/rockchip/clk-rk3399.c |    9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
> index 291543f..b6742fa 100644
> --- a/drivers/clk/rockchip/clk-rk3399.c
> +++ b/drivers/clk/rockchip/clk-rk3399.c
> @@ -1498,6 +1498,7 @@ static void __init rk3399_clk_init(struct device_node *np)
>  {
>         struct rockchip_clk_provider *ctx;
>         void __iomem *reg_base;
> +       struct clk *clk;
>
>         reg_base = of_iomap(np, 0);
>         if (!reg_base) {
> @@ -1511,6 +1512,14 @@ static void __init rk3399_clk_init(struct device_node *np)
>                 return;
>         }
>
> +       /* Watchdog pclk is controlled by RK3399 SECURE_GRF_SOC_CON3[8]. */
> +       clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_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(ctx, clk, PCLK_WDT);
> +
>         rockchip_clk_register_plls(ctx, rk3399_pll_clks,
>                                    ARRAY_SIZE(rk3399_pll_clks), -1);
>
> --
> 1.7.9.5
>
>

Reviewed-by: Stephen Barber <smbarber at chromium.org>

Steve


From dhdang at apm.com  Wed May 25 16:13:35 2016
From: dhdang at apm.com (Duc Dang)
Date: Wed, 25 May 2016 16:13:35 -0700
Subject: [PATCH] PCI/MSI: pci-xgene-msi: Enable MSI support in ACPI boot
 for X-Gene v1
In-Reply-To: <20160225173822.GA6349@red-moon>
References: <1455069384-22323-1-git-send-email-dhdang@apm.com>
 <1456330151.5681.46.camel@redhat.com> <56CDD767.6020103@arm.com>
 <CADaLND=mrkxOWOzcEb8os16Rb=SDHfnn_8eSgB4bQYH3UguS3w@mail.gmail.com>
 <20160225173822.GA6349@red-moon>
Message-ID: <CADaLNDnywVPER9QhmK4C6JyCLhta_M_cVSOuSkEHnmnLPFo3JA@mail.gmail.com>

On Thu, Feb 25, 2016 at 9:38 AM, Lorenzo Pieralisi
<lorenzo.pieralisi at arm.com> wrote:
> On Wed, Feb 24, 2016 at 02:28:10PM -0800, Duc Dang wrote:
>> On Wed, Feb 24, 2016 at 8:16 AM, Marc Zyngier <marc.zyngier at arm.com> wrote:
>> > On 24/02/16 16:09, Mark Salter wrote:
>> >> On Tue, 2016-02-09 at 17:56 -0800, Duc Dang wrote:
>> >>> This patch makes pci-xgene-msi driver ACPI-aware and provides
>> >>> MSI capability for X-Gene v1 PCIe controllers in ACPI boot mode.
>> >>>
>> >>> Signed-off-by: Duc Dang <dhdang at apm.com>
>> >>> ---
>> >>>  drivers/pci/host/pci-xgene-msi.c | 35 ++++++++++++++++++++++++++++++++---
>> >>>  1 file changed, 32 insertions(+), 3 deletions(-)
>> >>>
>> >>> diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c
>> >>> index a6456b5..466aa93 100644
>> >>> --- a/drivers/pci/host/pci-xgene-msi.c
>> >>> +++ b/drivers/pci/host/pci-xgene-msi.c
>> >>> @@ -24,6 +24,7 @@
>> >>>  #include <linux/pci.h>
>> >>>  #include <linux/platform_device.h>
>> >>>  #include <linux/of_pci.h>
>> >>> +#include <linux/acpi.h>
>> >>>
>> >>>  #define MSI_IR0                     0x000000
>> >>>  #define MSI_INT0            0x800000
>> >>> @@ -39,7 +40,7 @@ struct xgene_msi_group {
>> >>>  };
>> >>>
>> >>>  struct xgene_msi {
>> >>> -    struct device_node      *node;
>> >>> +    struct fwnode_handle    *fwnode;
>> >>>      struct irq_domain       *inner_domain;
>> >>>      struct irq_domain       *msi_domain;
>> >>>      u64                     msi_addr;
>> >>> @@ -249,6 +250,13 @@ static const struct irq_domain_ops msi_domain_ops = {
>> >>>      .free   = xgene_irq_domain_free,
>> >>>  };
>> >>>
>> >>> +#ifdef CONFIG_ACPI
>> >>> +static struct fwnode_handle *xgene_msi_get_fwnode(struct device *dev)
>> >>> +{
>> >>> +    return xgene_msi_ctrl.fwnode;
>> >>> +}
>> >>> +#endif
>> >>> +
>> >>>  static int xgene_allocate_domains(struct xgene_msi *msi)
>> >>>  {
>> >>>      msi->inner_domain = irq_domain_add_linear(NULL, NR_MSI_VEC,
>> >>> @@ -256,7 +264,7 @@ static int xgene_allocate_domains(struct xgene_msi *msi)
>> >>>      if (!msi->inner_domain)
>> >>>              return -ENOMEM;
>> >>>
>> >>> -    msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(msi->node),
>> >>> +    msi->msi_domain = pci_msi_create_irq_domain(msi->fwnode,
>> >>>                                                  &xgene_msi_domain_info,
>> >>>                                                  msi->inner_domain);
>> >>
>> >> This doesn't work for me (ACPI probing on Mustang) unless I change this
>> >> to be pci_msi_create_default_irq_domain(). The problem seems to be that
>> >> the MSI probe happens after the PCIe RC is probed so there is no MSI domain
>> >> at the time the PCIe root is initialized by ACPI.
>> >
>> > pci_msi_create_default_irq_domain is the wrong thing do use, specially
>> > if you have multiple MSI controllers in the system. I certainly wouldn't
>> > want to see it being used on arm64.
>> >
>> > This is the usual dependency hell. You try moving the probing earlier,
>> > but that may break something else in the process.
>>
>> Hi Mark and Marc,
>>
>> I have modified Tianocore firmware to have MSI node declared before
>> PCIe node in Dsdt table. With this modification, the MSI driver will
>> be loaded before PCIe driver and MSI domain is available at the time
>> PCIe root is initialized.
>
> I am totally against this. We should not hack ACPI tables to make
> the kernel work (on top of that with unwritten ordering rules that may
> well require changes as kernel evolves), we should have a standard set
> of bindings that people use to describe HW in the DSDT and the kernel(s)
> has to cope with that. If there is a dependency problem in the description
> we may solve it at bindings level, but I absolutely do not want to rely
> on DSDT nodes ordering for things to work, that's fragile, no shortcuts
> please.

Hi Lorenzo, Bjorn,

(Refresh this thread on this merge cycle)

I tried to use _DEP method to describe the dependency of PCIe node to
MSI node but it turns out that PCIe driver does not check for the
dependency (only EC (ec.c) and I2C core (i2c-core.c) use
acpi_walk_dep_device_list to check for dependency before loading
dependent drivers)

Do you have other suggestion/example about how to ensure strict
ordering on driver loading in ACPI boot mode without changing the
order of ACPI nodes in DSDT?

Regards,
Duc Dang.
>
> Thanks,
> Lorenzo


From johnyoun at synopsys.com  Wed May 25 18:15:45 2016
From: johnyoun at synopsys.com (John Youn)
Date: Wed, 25 May 2016 18:15:45 -0700
Subject: [PATCH] reset: Put back *_optional variants
Message-ID: <ca359e013c30f27c825a9580164b01da5ca6476d.1464224883.git.johnyoun@synopsys.com>

Prior to commit 6c96f05c8bb8 ("reset: Make [of_]reset_control_get[_foo]
functions wrappers"), the optional variants returned -ENOTSUPP when
CONFIG_RESET_CONTROLLER was not set. This patch reverts to this
behavior. Otherwise those calls will return -EINVAL causing users to
think that an error occurred when CONFIG_RESET_CONTROLLER is not set.

Fixes: 6c96f05c8bb8 ("reset: Make [of_]reset_control_get[_foo] functions wrappers")
Signed-off-by: John Youn <johnyoun at synopsys.com>
---

Hi Philipp, Hans,

The commit referenced above breaks an upcoming patch for the dwc2
driver that adds an optional reset control.

https://marc.info/?l=linux-usb&m=146161328211584&w=2

I've attempted to add the optional variants back the way they were
working before. Let me know if I need to do anything else to fix it or
if it should be done another way.

Regards,
John


 include/linux/reset.h | 33 +++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/include/linux/reset.h b/include/linux/reset.h
index ec0306ce..739d33d 100644
--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -14,10 +14,24 @@ int reset_control_status(struct reset_control *rstc);
 
 struct reset_control *__of_reset_control_get(struct device_node *node,
 				     const char *id, int index, int shared);
+
+struct reset_control *__of_reset_control_get_optional(struct device_node *node,
+				     const char *id, int index, int shared)
+{
+	return __of_reset_control_get(node, id, index, shared);
+}
+
 void reset_control_put(struct reset_control *rstc);
 struct reset_control *__devm_reset_control_get(struct device *dev,
 				     const char *id, int index, int shared);
 
+static inline struct reset_control *__devm_reset_control_get_optional(
+					struct device *dev,
+					const char *id, int index, int shared)
+{
+	return __devm_reset_control_get(dev, id, index, shared);
+}
+
 int __must_check device_reset(struct device *dev);
 
 static inline int device_reset_optional(struct device *dev)
@@ -74,6 +88,13 @@ static inline struct reset_control *__of_reset_control_get(
 	return ERR_PTR(-EINVAL);
 }
 
+static inline struct reset_control *__of_reset_control_get_optional(
+					struct device_node *node,
+					const char *id, int index, int shared)
+{
+	return ERR_PTR(-ENOTSUPP);
+}
+
 static inline struct reset_control *__devm_reset_control_get(
 					struct device *dev,
 					const char *id, int index, int shared)
@@ -81,6 +102,13 @@ static inline struct reset_control *__devm_reset_control_get(
 	return ERR_PTR(-EINVAL);
 }
 
+static inline struct reset_control *__devm_reset_control_get_optional(
+					struct device *dev,
+					const char *id, int index, int shared)
+{
+	return ERR_PTR(-ENOTSUPP);
+}
+
 #endif /* CONFIG_RESET_CONTROLLER */
 
 /**
@@ -110,7 +138,8 @@ static inline struct reset_control *__must_check reset_control_get(
 static inline struct reset_control *reset_control_get_optional(
 					struct device *dev, const char *id)
 {
-	return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 0);
+	return __of_reset_control_get_optional(dev ? dev->of_node : NULL,
+					       id, 0, 0);
 }
 
 /**
@@ -194,7 +223,7 @@ static inline struct reset_control *__must_check devm_reset_control_get(
 static inline struct reset_control *devm_reset_control_get_optional(
 					struct device *dev, const char *id)
 {
-	return __devm_reset_control_get(dev, id, 0, 0);
+	return __devm_reset_control_get_optional(dev, id, 0, 0);
 }
 
 /**
-- 
2.8.2



From shawn.lin at rock-chips.com  Wed May 25 19:23:39 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Thu, 26 May 2016 10:23:39 +0800
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <573DBAA5.2070706@samsung.com>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <5502CA4E.9060401@samsung.com>
 <CAD=FV=VX3ix-j4y95W1q8b-aVuVEN+4xsd8WLx2xcE7KPNJwRw@mail.gmail.com>
 <5506707D.40708@samsung.com> <55189F04.8000404@samsung.com>
 <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
 <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
 <573BCC8D.5090606@kernel-upstream.org>
 <CAD=FV=VneQR3wurjezBkRhtQiH+q-FfhDN8=Ym=XqtZpVmsdUw@mail.gmail.com>
 <573C3283.1040606@rock-chips.com>
 <CAD=FV=UoT2GRYWJWXEn_ccvKGgC+PzQM_BCtLHAa7jxzbaQ9SA@mail.gmail.com>
 <10b3dc0e-aebf-664b-b36b-c54692cd9983@rock-chips.com>
 <573DBAA5.2070706@samsung.com>
Message-ID: <4d8f3992-a1d3-6010-4964-8ca13cddc1c5@rock-chips.com>

Hi Jaehoon,

On 2016/5/19 21:07, Jaehoon Chung wrote:
> On 05/19/2016 08:31 PM, Shawn Lin wrote:
>> Hi,
>>
>> On 2016/5/19 1:37, Doug Anderson wrote:
>>> Hi,
>>>
>>> On Wed, May 18, 2016 at 2:14 AM, Shawn Lin <shawn.lin at rock-chips.com> wrote:
>>>> Hi
>>>>
>>>>
>>>> On 2016-5-18 12:12, Doug Anderson wrote:
>>>>>
>>>>> Hi,
>>>>>
>>>>> On Tue, May 17, 2016 at 6:59 PM, Shawn Lin
>>>>> <shawn.lin at kernel-upstream.org> wrote:
>>>>>>
>>>>>> Could you try this patch to see if you can still find HLE?
>>>>>>
>>>>>> @@ -2356,12 +2356,22 @@ static void dw_mci_cmd_interrupt(struct dw_mci
>>>>>> *host, u32 status)
>>>>>>   static void dw_mci_handle_cd(struct dw_mci *host)
>>>>>>   {
>>>>>>          int i;
>>>>>> +       int present;
>>>>>>
>>>>>>          for (i = 0; i < host->num_slots; i++) {
>>>>>>                  struct dw_mci_slot *slot = host->slot[i];
>>>>>>
>>>>>>                  if (!slot)
>>>>>>                          continue;
>>>>>>
>>>>>> +               present = !(mci_readl(slot->host, CDETECT) & (1 <<
>>>>>> slot->id));
>>>>>> +               if (present)
>>>>>> +                       set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>>>>>> +               else
>>>>>> +                       clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>>>>>
>>>>>
>>>>> No, because we don't use the builtin card detect on veyron.  ;)
>>>>>
>>>>> We use GPIO card detect because we didn't like the way JTAG and SD
>>>>> interacted.  Also on rk3288 the builtin card detect line had the wrong
>>>>> voltage domain (you couldn't detect a card when the IO lines were
>>>>> powered off).  The builtin card detect line is always driven low on
>>>>> veyron.
>>>>
>>>>
>>>> Okay, I see.
>>>>
>>>>>
>>>>>
>>>>> I'm nearly certain that the root cause of my HLE errors is actually
>>>>> related to the same problem addressed by the commit 7c5209c315ea
>>>>> ("mmc: core: Increase delay for voltage to stabilize from 3.3V to
>>>>> 1.8V").  I think that on minnie we're still on the hairy edge and
>>>>> sometimes the line doesn't transition fast enough.
>>>>
>>>>
>>>> Things are not so simple from your details.
>>>>
>>>> I was not enabling SD3.0 support, then I also found HLE sometimes.
>>>> So it seems commit 7c5209c315ea does not contibute to this phenomenon.
>>>
>>> Just to clarify, in my case commit 7c5209c315ea didn't make the
>>> problem worse, but made it better.  Just not better enough.  ;)
>>>
>>>
>>>> The scenario looks like:
>>>> remove sd-card -> mmc_sd_detect -> send status(CMD13) ->power_off ->
>>>> set_ios -> setup_bus -> disabled clk , then HLE irq storm coming
>>>>
>>>> From the code of dw_mci_prepare_command:
>>>> SDMMC_CMD_PRV_DAT_WAIT will not be used for CMD13, so we don't
>>>> wait_busy here, then cmd code is loding into queue of dw_mmc but
>>>> still failing send out because it's in busy?
>>>>
>>>> With my patch, things go well:
>>>> remove sd-card -> clear bit of DW_MMC_CARD_PRESENT  -> send
>>>> status(CMD13) return directly -> power_off -> set_ios -> setup_bus ->
>>>> disable clk
>>>>
>>>> So why should we allow inquiry of card status if we sure the card is
>>>> removed? I mean no any further cmds should be delivered.
>>>
>>> Quite honestly just dealing with the HLE error (my patch or
>>> equivalent) might be a sane solution for the problem you describe.
>>
>> Yes, your patch looks good to me, so it should be merged firstly. :)
>> Then let's push it a bit further more that when HLEs are coming,
>> somethings must be wrong(currently I don't see a obvious clue from
>> the code itself although, I'm prone to think it belongs to the
>> software issue).
>
> We don't know what's main cause for HLE..But i also think it's relevant to SW issue.
> But we need to consider all possibilities..
>
>>
>>
>>>
>>> dw_mmc needs to be able to work with an external card detect GPIO.
>>> It's been part of the dw_mmc driver for a long time and is (in fact)
>>> in use upstream at least by rk3288-veyron.  Any solution that only
>>> works for internal card detect is not enough.  Just handling the HLE
>>> error to deal with the interrupt storm and then letting Linux remove
>>> the card (because of the card detect interrupt) seems totally OK to
>>> me.
>>>
>>
>> Sure, some of rockchip Socs use gpio for CD because they don't
>> have a internal CD, such as RK3036, right?
>>
>>> Note: I'd be very curious if your problems get better if you disable
>>
>> Not at all.
>>
>>> the "grf_force_jtag" bit in the GRF.  If you're using the builtin card
>>> detect and you use the boot default of "grf_force_jtag" then your pins
>>> will be unmuxed behind your back when the card is ejected.  This could
>>> be causing the dw_mmc controller to get confused.
>>
>> Right, grf_force_jtag is also not a friend of mine. :)
>> So I had disabled this function before I was debugging it.
>>
>>>
>>>
>>>> And another question: should we wait busy for cmd13?
>>>
>>> I don't think so.  As I understand it CMD13 uses only the CMD line for
>>> communication and it should be appropriate to send this when the bus
>>> is "busy" (which means that the DATA lines are low).
>>
>> Ahh... take back my question.. I was just considering a wired situation
>> that pins are unmuxed on the background(cmd line as well) when cmd13 is
>> delivering....
>>
>>
>>>
>>> Also: it seems odd that the HLE IRQ storm didn't come right after the
>>> CMD 13 in your description above.  Are you sure it was the CMD 13 that
>>> caused the HLEs, or could it has been something else?
>>
>> Actually no. Any cmds be issued can trigger HLEs, I think, after sd card is removed When I hacked mmc_sd_detecd to send other cmds intead
>> of cmd13.
>>
>> From dw_mmc databook v270a(7.2.3 Clock Programming) we can see:
>> The DWC_mobile_storage loads each of these registers only when the
>> start_cmd bit and the Update_clk_regs_only bit in the CMD register are
>> set. When a command is successfully loaded, the DWC_mobile_storage
>> clears this bit, unless the DWC_mobile_storage already has another
>> command in the queue, at which point it gives an HLE (Hardware Locked
>> Error); for details on HLEs, refer to ?Error Handling? on page 233.
>> Software should look for the start_cmd and the Update_clk_regs_only
>> bits, and should also set the wait_prvdata_complete bit to ensure that
>> clock parameters do not change during data transfer.
>>
>> Maybe the cmd is trying to load(or somethings wrong with the
>> controller?) when we disable the clk? That may explain my observation
>> that HLEs came after disabling clk.
>
> I agreed.
>
> To Disable clock, it sends cmd with update_clk_regs_only and wait_prvdata_complete bit.
> I think it's problem..(waiting for prvdata..)
>
> If there are ongoing some data(read/write), then before disabling clock, waiting for completing previous data.
> (But card was already removed, and it couldn't do anything.)
> It's difficult to analyze the HLE..So After applying first, then we can solve this problem, step by step.
>

I saw you send a PR for v4.7-fix to Ulf which didn't include this one.
Do you plan to add it into 4.8 materials? :)

> Best Regards,
> Jaehoon Chung
>
>>
>>
>>>
>>>
>>> -Doug
>>>
>>>
>>>
>>
>>
>
>
>
>


-- 
Best Regards
Shawn Lin



From horms at verge.net.au  Wed May 25 19:28:33 2016
From: horms at verge.net.au (Simon Horman)
Date: Thu, 26 May 2016 11:28:33 +0900
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
 <20160525004825.GC7292@verge.net.au>
 <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>
Message-ID: <20160526022833.GE18393@verge.net.au>

Hi Dirk,

On Wed, May 25, 2016 at 07:10:26AM +0200, Dirk Behme wrote:
> Hi Simon,
> 
> On 25.05.2016 02:48, Simon Horman wrote:
> >Hi Dirk,
> >
> >On Tue, May 24, 2016 at 07:30:17AM +0200, Dirk Behme wrote:
> >>Hi Simon,
> >
> >[...]
> >
> >>With Renesas R-Car3 we will get a whole family of SoCs. I.e. different
> >>computing power (e.g. different number of Cores) with more or less similar
> >>peripherals.
> >>
> >>I would think that we want to reflect this in the device tree, too.
> >>Therefore I think what we want is a hierarchy of device trees. Similar
> >>what's done with other SoC families (compare e.g. i.MX6).
> >>
> >>E.g. we want an initial rcar3.dtsi, which contains all common parts of all
> >>R-Car3 SoCs. E.g. one CA57 core, the SCIF where its common etc.
> >>
> >>Then you will have the r8a779x.dtsi which includes the rcar3.dtsi and
> >>extends it for SoC specific parts. Which then will be included by the board
> >>device trees, as already done, now.
> >>
> >>Or in other words: As soon as you have similar parts in the r8a779x.dtsi's,
> >>it's time to think about moving the parts one hierarchy level up into the
> >>rcar3.dtsi. Else you will end up in a maintenance hell once you have to
> >>change/fix anything.
> >
> >Thanks for raising this issue.
> >
> >I agree entirely that we should work towards a situation where maintenance
> >is as easy as it can be. However, due to the per-SoC binding scheme that
> >we are using for IP related to Renesas SoCs I suspect that very few DT nodes
> >can be shared between SoCs verbatim.
> 
> 
> Could you kindly share an example for this? Looking into the H3 and the M3-W
> manual, it looks to me that ~90% (?) of the peripherals are the same.

The background is that this is a conversation that has been going around
for years. The basic thinking is that at this point we have documentation
that indicates that many hardware blocks on the H3 and M3-W are the same.
But we do not have insight into the internal versioning of the IP blocks
nor if they are really the same. And furthermore even if they are currently
the same we don't really know if that will continue to be the case.

Probably it is. Maybe it isn't. The response has been to take a
conservative approach to DT bindings to give us the flexibility to update
the driver implementation to reflect any differences that subsequently
surface. And by providing per-SoC bindings these driver changes can be
activated on a per-SoC basis without updating DTB files (which may be
burned into ROMs).

There is of course scope to take a different approach. But getting
consensus on this is frankly difficult. And at the very least I would
expect it to take time.

> >Probably some sort of scheme can be cooked up using preprocessor macros.
> >And probably there are other ways to resolve this problem. But I would
> >prefer if we worked towards resolving this maintenance problem in parallel
> >with rather than as a dependency of merging r8a7796 support into mainline.
> 
> 
> I'd propose to do it correct from the beginning.
> 
> Doing it later would either be more work or forgotten, and never be done,
> then.

I'm sorry but I don't agree. I think that having r8a7796 support
in mainline is a higher priority than sorting this out.

> For a starting point, I'd propose to put the r8a7795.dtsi and r8a7796.dtsi
> into a graphical diff tool and move all common parts to a rcar3.dtsi (I'd be
> happy to discuss the name, though)

I'm not opposed to that. But being consistent with my statement above
I would prefer it to be done as follow-up work.

My suspicion is that right now much of the proposed r8a7796.dtsi can be
moved into a hypothetical rcar3.dtsi. But that this is because the proposed
r8a7796.dtsi is very small. I would not expect nearly such a large
proportion of r8a7795.dtsi to be able to be moved into rcar3.dtsi because
it enables more hardware blocks and they typically have (or should have in
keeping with the prevailing policy as described above) per-SoC bindings.

I believe that there is also a another issue which is that we wish
to control enabling features on different SoCs once they are known to work.
Of course things slip through the cracks. But blindly assuming all
IP blocks enabled for one SoC work on another, even if based on the
documentation, seems to be asking for trouble to me. For one thing
it implies that the level of firmware support is the same.

As for a name, I suggest rcar-gen3.dtsi.


From horms at verge.net.au  Wed May 25 19:31:32 2016
From: horms at verge.net.au (Simon Horman)
Date: Thu, 26 May 2016 11:31:32 +0900
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <25947777-9871-ccc4-011b-0775c2b88d8b@de.bosch.com>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <25947777-9871-ccc4-011b-0775c2b88d8b@de.bosch.com>
Message-ID: <20160526023132.GF18393@verge.net.au>

On Wed, May 25, 2016 at 09:38:23AM +0200, Dirk Behme wrote:
> On 24.05.2016 03:54, Simon Horman wrote:
> >Basic support for the Gen 3 R-Car M3-W SoC.
> >
> >Based on work for the r8a7795 and r8a7796 SoCs by
> >Takeshi Kihara, Dirk Behme and Geert Uytterhoeven.
> >
> >Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
> >Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
> >---
> >v3
> >* As suggested by Geert Uytterhoeven:
> >  - Drop 0x from unit address of gic
> >* As suggested by Khiem Nguyen:
> >  - Use psci-0.2
> >* Added Reviewed-by tag from Geert Uytterhoeven
> >
> >v2
> >* As suggested by Geert Uytterhoeven:
> >  - Move L2_CA57 node under cpus node and include reg property
> >  - Omit status = "disabled" from scif_clk node
> >---
> > Documentation/devicetree/bindings/arm/shmobile.txt |   4 +
> > arch/arm64/Kconfig.platforms                       |   6 ++
> > arch/arm64/boot/dts/renesas/r8a7796.dtsi           | 120 +++++++++++++++++++++
> > 3 files changed, 130 insertions(+)
> > create mode 100644 arch/arm64/boot/dts/renesas/r8a7796.dtsi
> >
> >diff --git a/Documentation/devicetree/bindings/arm/shmobile.txt b/Documentation/devicetree/bindings/arm/shmobile.txt
> >index 9cf67e48f222..d5ed554830d7 100644
> >--- a/Documentation/devicetree/bindings/arm/shmobile.txt
> >+++ b/Documentation/devicetree/bindings/arm/shmobile.txt
> >@@ -29,6 +29,8 @@ SoCs:
> >     compatible = "renesas,r8a7794"
> >   - R-Car H3 (R8A77950)
> >     compatible = "renesas,r8a7795"
> >+  - R-Car M3-W (R8A77960)
> >+    compatible = "renesas,r8a7796"
> >
> >
> > Boards:
> >@@ -61,5 +63,7 @@ Boards:
> >     compatible = "renesas,porter", "renesas,r8a7791"
> >   - Salvator-X (RTP0RC7795SIPB0010S)
> >     compatible = "renesas,salvator-x", "renesas,r8a7795";
> >+  - Salvator-X
> >+    compatible = "renesas,salvator-x", "renesas,r8a7796";
> >   - SILK (RTP0RC7794LCB00011S)
> >     compatible = "renesas,silk", "renesas,r8a7794"
> >diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
> >index efa77c146415..16d8d26839ea 100644
> >--- a/arch/arm64/Kconfig.platforms
> >+++ b/arch/arm64/Kconfig.platforms
> >@@ -114,6 +114,12 @@ config ARCH_R8A7795
> > 	help
> > 	  This enables support for the Renesas R-Car H3 SoC.
> >
> >+config ARCH_R8A7796
> >+	bool "Renesas R-Car M3-W SoC Platform"
> >+	depends on ARCH_RENESAS
> >+	help
> >+	  This enables support for the Renesas R-Car M3-W SoC.
> >+
> > config ARCH_STRATIX10
> > 	bool "Altera's Stratix 10 SoCFPGA Family"
> > 	help
> >diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> >new file mode 100644
> >index 000000000000..178debf68318
> >--- /dev/null
> >+++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> >@@ -0,0 +1,120 @@
> >+/*
> >+ * Device Tree Source for the r8a7796 SoC
> >+ *
> >+ * Copyright (C) 2016 Renesas Electronics Corp.
> >+ *
> >+ * This file is licensed under the terms of the GNU General Public License
> >+ * version 2.  This program is licensed "as is" without any warranty of any
> >+ * kind, whether express or implied.
> >+ */
> >+
> >+#include <dt-bindings/clock/r8a7796-cpg-mssr.h>
> >+#include <dt-bindings/interrupt-controller/arm-gic.h>
> >+
> >+/ {
> >+	compatible = "renesas,r8a7796";
> >+	#address-cells = <2>;
> >+	#size-cells = <2>;
> >+
> >+	psci {
> >+		compatible = "arm,psci-0.2";
> >+		method = "smc";
> >+	};
> >+
> >+	cpus {
> >+		#address-cells = <1>;
> >+		#size-cells = <0>;
> >+
> >+		/* 1 core only at this point */
> >+		a57_0: cpu at 0 {
> >+			compatible = "arm,cortex-a57", "arm,armv8";
> >+			reg = <0x0>;
> >+			device_type = "cpu";
> >+			next-level-cache = <&L2_CA57>;
> >+			enable-method = "psci";
> >+		};
> >+
> >+		L2_CA57: cache-controller at 0 {
> >+			compatible = "cache";
> >+			reg = <0>;
> >+			cache-unified;
> >+			cache-level = <2>;
> >+		};
> >+	};
> 
> 
> It looks to me that in the r8a7795.dtsi the cache-controller node is outside
> the cpus node? I'd think that we should keep is consistent.

As of c10cdf93a119 ("arm64: dts: r8a7795: Fix W=1 dtc warnings"),
which was recently added to the devel branch of the renesas tree,
the cache-controller is inside the cpu node on the r8a7795.dtsi.

This patch aims to be consistent with that change.


From khilman at baylibre.com  Wed May 25 19:42:59 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Wed, 25 May 2016 19:42:59 -0700
Subject: [PATCH v2 1/4] reset: Add support for the Amlogic Meson SoC Reset
 Controller
In-Reply-To: <1464169758-26975-2-git-send-email-narmstrong@baylibre.com> (Neil
 Armstrong's message of "Wed, 25 May 2016 11:49:15 +0200")
References: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
 <1464169758-26975-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <m2iny1h74c.fsf@baylibre.com>

Neil Armstrong <narmstrong at baylibre.com> writes:

> This patch adds the platform driver for the Amlogic Meson SoC Reset
> Controller.
>
> The Meson8b and GXBB SoCs are supported.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>

Maybe a question for Philipp, but when testog this version with the
stmmac ethernet driver on the Amlogic boards, I noticed that ->reset was
never getting called.

Turns out, the stmmac driver only uses reset_control_assert() and
reset_control_deassert(), both of which return -ENOTSUPP since this
driver doesn't provide ->assert or ->deassert, so the driver's ->reset()
never gets called.

I haven't looked into the reset framework in detail, but if there's only
a ->reset hook, I kind of expected that reset_control_deassert() would
use that instead of returning -ENOTSUPP.

If not, what's the proper way of handling hardware that only supports a
write-only reset pulse?  Should users of reset_control_* be adapted to
check if ->deassert returns -ENOTSUPP and call ->reset?

Kevin


From thunder.leizhen at huawei.com  Wed May 25 19:43:59 2016
From: thunder.leizhen at huawei.com (Zhen Lei)
Date: Thu, 26 May 2016 10:43:59 +0800
Subject: [PATCH 3/3] arm64/numa: fix type info
In-Reply-To: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
References: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
Message-ID: <1464230639-9852-3-git-send-email-thunder.leizhen@huawei.com>

numa_init(of_numa_init) may returned error because of numa configuration
error. So "No NUMA configuration found" is inaccurate. In fact, specific
configuration error information can be immediately printed by the
testing branch. So "No NUMA..." only needs to be printed when numa_off.

Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
---
 arch/arm64/mm/numa.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
index 98dc104..9937cc1 100644
--- a/arch/arm64/mm/numa.c
+++ b/arch/arm64/mm/numa.c
@@ -362,7 +362,8 @@ static int __init dummy_numa_init(void)
 	int ret;
 	struct memblock_region *mblk;

-	pr_info("%s\n", "No NUMA configuration found");
+	if (numa_off)
+		pr_info("%s\n", "No NUMA configuration found");
 	pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
 	       0LLU, PFN_PHYS(max_pfn) - 1);

--
2.5.0




From thunder.leizhen at huawei.com  Wed May 25 19:43:57 2016
From: thunder.leizhen at huawei.com (Zhen Lei)
Date: Thu, 26 May 2016 10:43:57 +0800
Subject: [PATCH 1/3] of/numa: remove a duplicated pr_debug information
Message-ID: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>

This information will be printed in the subfunction numa_add_memblk.
They are not the same, but very similar.

Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
---
 drivers/of/of_numa.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
index 0f2784b..21d831f 100644
--- a/drivers/of/of_numa.c
+++ b/drivers/of/of_numa.c
@@ -88,9 +88,6 @@ static int __init of_numa_parse_memory_nodes(void)
 			break;
 		}

-		pr_debug("NUMA:  base = %llx len = %llx, node = %u\n",
-			 rsrc.start, rsrc.end - rsrc.start + 1, nid);
-
 		r = numa_add_memblk(nid, rsrc.start,
 				    rsrc.end - rsrc.start + 1);
 		if (r)
--
2.5.0




From thunder.leizhen at huawei.com  Wed May 25 19:43:58 2016
From: thunder.leizhen at huawei.com (Zhen Lei)
Date: Thu, 26 May 2016 10:43:58 +0800
Subject: [PATCH 2/3] of/numa: fix a memory@ dt node can only contains one
 memory block
In-Reply-To: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
References: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
Message-ID: <1464230639-9852-2-git-send-email-thunder.leizhen@huawei.com>

For a normal memory@ devicetree node, its reg property can contains more
memory blocks.

Because we don't known how many memory blocks maybe contained, so we try
from index=0, increase 1 until error returned(the end).

Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
---
 drivers/of/of_numa.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
index 21d831f..2c5f249 100644
--- a/drivers/of/of_numa.c
+++ b/drivers/of/of_numa.c
@@ -63,7 +63,7 @@ static int __init of_numa_parse_memory_nodes(void)
 	struct device_node *np = NULL;
 	struct resource rsrc;
 	u32 nid;
-	int r = 0;
+	int i, r = 0;

 	for (;;) {
 		np = of_find_node_by_type(np, "memory");
@@ -82,17 +82,27 @@ static int __init of_numa_parse_memory_nodes(void)
 			/* some other error */
 			break;

-		r = of_address_to_resource(np, 0, &rsrc);
-		if (r) {
-			pr_err("NUMA: bad reg property in memory node\n");
-			break;
+		for (i = 0; ; i++) {
+			r = of_address_to_resource(np, i, &rsrc);
+			if (r) {
+				/* reached the end of of_address */
+				if (i > 0) {
+					r = 0;
+					break;
+				}
+
+				pr_err("NUMA: bad reg property in memory node\n");
+				goto finished;
+			}
+
+			r = numa_add_memblk(nid, rsrc.start,
+					    rsrc.end - rsrc.start + 1);
+			if (r)
+				goto finished;
 		}
-
-		r = numa_add_memblk(nid, rsrc.start,
-				    rsrc.end - rsrc.start + 1);
-		if (r)
-			break;
 	}
+
+finished:
 	of_node_put(np);

 	return r;
--
2.5.0




From computersforpeace at gmail.com  Wed May 25 20:10:05 2016
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 25 May 2016 20:10:05 -0700
Subject: [PATCH 1/2] Revert "mtd: atmel_nand: Support variable RB_EDGE
 interrupts"
In-Reply-To: <20160523095557.1efea63d@bbrezillon>
References: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
 <1462776680-5284-2-git-send-email-wenyou.yang@atmel.com>
 <20160523095557.1efea63d@bbrezillon>
Message-ID: <20160526031005.GA137092@google.com>

Hi,

On Mon, May 23, 2016 at 09:55:57AM +0200, Boris Brezillon wrote:
> On Mon, 9 May 2016 14:51:18 +0800
> Wenyou Yang <wenyou.yang at atmel.com> wrote:
> 
> > This reverts commit 5ddc7bd43ccc ("mtd: atmel_nand: Support variable
> > RB_EDGE interrupts")
> > 
> > Because for current SoCs, the RB_EDGE3(i.e. bit 27) of HSMC_SR
> > register does not exist, the RB_EDGE0 (i.e. bit 24) is the ready/busy
> > line edge status bit. It is a datasheet bug.
> > 
> > Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> 
> Wenyou, I know you sent it before v4.6 was released, but now we should
> probably add

Sorry for the delay...

> Cc: <stable at vger.kernel.org>

Added that and a Fixes: tag.

> Brian, can you apply this patch directly in your tree (as previously
> discussed, I'm not sure creating a nand/fixes branch is really useful)?

Pushed to linux-mtd.git. I'll probably send it to Linus in the next day
or two.

Brian


From computersforpeace at gmail.com  Wed May 25 20:16:54 2016
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 25 May 2016 20:16:54 -0700
Subject: [PATCH 1/2] Revert "mtd: atmel_nand: Support variable RB_EDGE
 interrupts"
In-Reply-To: <1462776680-5284-2-git-send-email-wenyou.yang@atmel.com>
References: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
 <1462776680-5284-2-git-send-email-wenyou.yang@atmel.com>
Message-ID: <20160526031654.GA107505@google.com>

Hi,

On Mon, May 09, 2016 at 02:51:18PM +0800, Wenyou Yang wrote:
> This reverts commit 5ddc7bd43ccc ("mtd: atmel_nand: Support variable
> RB_EDGE interrupts")
> 
> Because for current SoCs, the RB_EDGE3(i.e. bit 27) of HSMC_SR
> register does not exist, the RB_EDGE0 (i.e. bit 24) is the ready/busy
> line edge status bit. It is a datasheet bug.
> 
> Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> ---
> 
>  .../devicetree/bindings/mtd/atmel-nand.txt         |  2 +-
>  drivers/mtd/nand/atmel_nand.c                      | 35 +++++-----------------
>  drivers/mtd/nand/atmel_nand_nfc.h                  |  3 +-
>  3 files changed, 10 insertions(+), 30 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> index d53aba9..3e7ee99 100644
> --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> @@ -39,7 +39,7 @@ Optional properties:
>  
>  Nand Flash Controller(NFC) is an optional sub-node
>  Required properties:
> -- compatible : "atmel,sama5d3-nfc" or "atmel,sama5d4-nfc".
> +- compatible : "atmel,sama5d3-nfc".
>  - reg : should specify the address and size used for NFC command registers,
>          NFC registers and NFC SRAM. NFC SRAM address and size can be absent
>          if don't want to use it.
> diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
> index efc8ea2..68b9160 100644
> --- a/drivers/mtd/nand/atmel_nand.c
> +++ b/drivers/mtd/nand/atmel_nand.c
[...]
>  static const struct of_device_id atmel_nand_nfc_match[] = {
> -	{ .compatible = "atmel,sama5d3-nfc", .data = &sama5d3_nfc_caps },
> -	{ .compatible = "atmel,sama5d4-nfc", .data = &sama5d4_nfc_caps },
> +	{ .compatible = "atmel,sama5d3-nfc" },

Hmm, wait. Didn't Rob and Alexandre suggest that we should *not* drop
the compatible property? We could have easily supported both here, and
just not listed any different capabilities. But I see that Nicholas took
the patch anyway, so I guess it's not a big deal...

>  	{ /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match);

Brian


From pankaj.dubey at samsung.com  Wed May 25 20:43:35 2016
From: pankaj.dubey at samsung.com (pankaj.dubey)
Date: Thu, 26 May 2016 09:13:35 +0530
Subject: ARM: dts: exynos: Add MFC memory banks for Peach boards
In-Reply-To: <d045b880-4a44-acd8-f7f6-e521caf374aa@osg.samsung.com>
References: <1461871311-18344-1-git-send-email-javier@osg.samsung.com>
 <57456344.7020708@samsung.com>
 <d045b880-4a44-acd8-f7f6-e521caf374aa@osg.samsung.com>
Message-ID: <574670E7.3060508@samsung.com>

Hi Javier,

On Wednesday 25 May 2016 08:32 PM, Javier Martinez Canillas wrote:
> Hello Pankaj,
> 
> On 05/25/2016 04:33 AM, pankaj.dubey wrote:
>> Hi Javier,
>>
>>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>
>> Just noticed that, current krzk/for-next failed to boot on Exynos5880
>> based Chromebook device. Git bisect is showing culprit as this patch.
> 
> Strange, krzk/for-next boots correctly on my Exynos5800 Peach Pi:
> 
> $ git log --pretty=oneline --abbrev-commit HEAD
> 35e691cf5165 Merge branch 'fixes-v4.7' into for-next
> 

This is same as mine.

My other build parameters are:
defconfig: exynos_defconfig
CROSS_COMPILE: gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux
rootfs: small cramfs

> $ uname -r
> 4.6.0-00073-g35e691cf5165
> 
>> When I reverted this patch, its able to boot normally.
>> Is there any missing patches that we need to take on krzk/for-next to
>> boot on Chromebook.
>>
> 

Further I checked that, either I revert this patch OR do not reserve
memory for MFC in exynos_reserve using following changes, both cases I
am able to boot kernel on Chromebook (Exynos5800).

diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index f977eea..e615e24 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -268,7 +268,7 @@ static char const *const exynos_dt_compat[]
__initconst = {

 static void __init exynos_reserve(void)
 {
-#ifdef CONFIG_S5P_DEV_MFC
+#ifndef CONFIG_S5P_DEV_MFC
        int i;
        char *mfc_mem[] = {
                "samsung,mfc-v5",
@@ -280,6 +280,8 @@ static void __init exynos_reserve(void)
        for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
                if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
                        break;
+#else
+       pr_err("*****exynos_reserve Bypassing Memory Reservation for MFC
********\n");
 #endif
 }


> No that I'm aware of. I wonder why it boots for me but fails for
> you. Can you please share your complete boot log to see if there
> are any hints there?
>  

Following is failed boot log:
U-Boot 2013.04-g8e3e5ef (May 26 2015 - 16:11:36) for Peach

CPU:    Exynos5422 at 900MHz

Board: Google Peach Pi, rev 11.6
I2C:   ready
DRAM:  3.5 GiB
Relocation Offset dbd54000, base at ffb54000
SPL stack at 2072c00, used 3f0, free 10
PMIC max77802-pmic initialized
CPU:    Exynos5422 at 1800MHz
TPS65090 PMIC EC init
MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
SF: Detected W25Q32DW with page size 4 KiB, total 32 MiB
In:    cros-ec-keyb
Out:   lcd
Err:   lcd
SF: Detected W25Q32DW with page size 4 KiB, total 32 MiB
ELOG: Event(17) added with size 13
Net:   No ethernet found.
Hit any key to stop autoboot:  0
mmc1 is current device
4586144 bytes read in 242 ms (18.1 MiB/s)
26583040 bytes read in 1166 ms (21.7 MiB/s)
## Loading kernel from FIT Image at 20008000 ...
   Using 'conf at 2' configuration
   Trying 'kernel at 1' kernel subimage
     Description:  unavailable
     Type:         Kernel Image (no loading done)
     Compression:  uncompressed
     Data Start:   0x200080c8
     Data Size:    4459024 Bytes = 4.3 MiB
   Verifying Hash Integrity ... OK
## Loading fdt from FIT Image at 20008000 ...
   Using 'conf at 2' configuration
   Trying 'fdt at 2' fdt subimage
     Description:  exynos5800-peach-pi.dtb
     Type:         Flat Device Tree
     Compression:  uncompressed
     Data Start:   0x20458148
     Data Size:    63002 Bytes = 61.5 KiB
     Architecture: ARM
     Hash algo:    sha1
     Hash value:   cd1c1703f744b44b1833ca61ec36b625665548de
   Verifying Hash Integrity ... sha1+ OK
   Booting using the fdt blob at 0x20458148
   XIP Kernel Image (no loading done) ... OK
   Loading Device Tree to 3ffe1000, end 3ffffb49 ... OK
boot_kernel.c: ft_board_setup: warning: Must pass exactly one of vboot
or cdata

Starting kernel ...

Timer summary in microseconds:
       Mark    Elapsed  Stage
          0          0  reset
    122,793    122,793  board_init_f
    143,214     20,421  board_init_r
    238,069     94,855  id=64
    240,278      2,209  main_loop
  4,841,682  4,601,404  bootm_start
  4,841,683          1  id=1
  4,846,604      4,921  id=100
  4,846,607          3  id=101
  4,846,607          0  id=102
  4,850,208      3,601  id=110
  4,877,729     27,521  id=105
  4,877,731          2  id=106
  4,877,734          3  id=107
  4,877,735          1  id=108
  4,877,736          1  id=109
  4,882,406      4,670  id=90
  4,882,408          2  id=92
  4,882,408          0  id=91
  4,927,272     44,864  id=95
  4,927,274          2  id=96
  4,927,276          2  id=97
  4,927,277          1  id=98
  4,927,279          2  id=99
  4,937,617     10,338  id=7
  4,951,899     14,282  id=15
  4,955,112      3,213  start_kernel

Accumulated time:
                 6,948  SPI read
Uncompressing Linux... done, booting the kernel.
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.6.0-00073-g35e691c
(pankaj at chromebld-server) (gcc version 4.9.2 20140904 (prerelease)
(crosstool-NG linaro-1.13.1-4.9-2014.09 - Linaro GCC
4.9-2014.09) ) #59 SMP PREEMPT Thu May 26 08:21:07 IST 2016
[    0.000000] CPU: ARMv7 Processor [412fc0f3] revision 3 (ARMv7),
cr=10c5387d
[    0.000000] CPU: div instructions available: patching division code
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction
cache
[    0.000000] Machine model: Google Peach Pi Rev 10+
[    0.000000] bootconsole [earlycon0] enabled
[    0.000000] cma: Reserved 64 MiB at 0xfbc00000
[    0.000000] Memory policy: Data cache writealloc
[    0.000000] Samsung CPU ID: 0xe5422001
[    0.000000] On node 0 totalpages: 913407
[    0.000000] free_area_init_node: node 0, pgdat c0b42cc0, node_mem_map
ee3f7000
[    0.000000]   Normal zone: 1536 pages used for memmap
[    0.000000]   Normal zone: 0 pages reserved
[    0.000000]   Normal zone: 194560 pages, LIFO batch:31
[    0.000000]   HighMem zone: 718847 pages, LIFO batch:31
[    0.000000] percpu: Embedded 12 pages/cpu @ee341000 s19392 r8192
d21568 u49152
[    0.000000] pcpu-alloc: s19392 r8192 d21568 u49152 alloc=12*4096
[    0.000000] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3 [0] 4 [0] 5 [0] 6 [0] 7
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.
Total pages: 911871
[    0.000000] Kernel command line: cros_legacy console=ttySAC3,115200
debug earlyprintk cros_debug no_console_suspend root=/dev/ram0 rw
ramdisk=32768 initrd=0x42000000,3
2M
[    0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288
bytes)
[    0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144
bytes)
[    0.000000] Memory: 3522460K/3653628K available (6317K kernel code,
271K rwdata, 2204K rodata, 1024K init, 313K bss, 65632K reserved, 65536K
cma-reserved, 2809852K hig
hmem)
[    0.000000] Virtual kernel memory layout:
[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
[    0.000000]     vmalloc : 0xf0800000 - 0xff800000   ( 240 MB)
[    0.000000]     lowmem  : 0xc0000000 - 0xf0000000   ( 768 MB)
[    0.000000]     pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
[    0.000000]     modules : 0xbf000000 - 0xbfe00000   (  14 MB)
[    0.000000]       .text : 0xc0008000 - 0xc09524b8   (9514 kB)
[    0.000000]       .init : 0xc0a00000 - 0xc0b00000   (1024 kB)
[    0.000000]       .data : 0xc0b00000 - 0xc0b43ca0   ( 272 kB)
[    0.000000]        .bss : 0xc0b45000 - 0xc0b937e8   ( 314 kB)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=8, Nodes=1
[    0.000000] Preemptible hierarchical RCU implementation.
[    0.000000]  Build-time adjustment of leaf fanout to 32.
[    0.000000] NR_IRQS:16 nr_irqs:16 16
[    0.000000] GIC physical location is 0x10481000
[    0.000000] Switching to timer-based delay loop, resolution 41ns
[    0.000000] clocksource: mct-frc: mask: 0xffffffff max_cycles:
0xffffffff, max_idle_ns: 79635851949 ns
[    0.000003] sched_clock: 32 bits at 24MHz, resolution 41ns, wraps
every 89478484971ns
[    0.008334] Console: colour dummy device 80x30
[    0.012699] Calibrating delay loop (skipped), value calculated using
timer frequency.. 48.00 BogoMIPS (lpj=120000)
[    0.023090] pid_max: default: 32768 minimum: 301
[    0.027864] Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
[    0.034465] Mountpoint-cache hash table entries: 2048 (order: 1, 8192
bytes)
[    0.041947] CPU: Testing write buffer coherency: ok
[    0.047033] CPU0: update cpu_capacity 1535
[    0.051046] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
[    0.056840] Setting up static identity map for 0x20100000 - 0x20100058
[    0.063593] ARM CCI driver probed
[    0.067193] Exynos MCPM support installed
[    0.124848] CPU1: update cpu_capacity 1535
[    0.124852] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
[    0.144835] CPU2: update cpu_capacity 1535
[    0.144839] CPU2: thread -1, cpu 2, socket 0, mpidr 80000002
[    0.164835] CPU3: update cpu_capacity 1535
[    0.164838] CPU3: thread -1, cpu 3, socket 0, mpidr 80000003
[    0.184910] CPU4: update cpu_capacity 448
[    0.184923] CPU4: thread -1, cpu 0, socket 1, mpidr 80000100
[    0.204875] CPU5: update cpu_capacity 448
[    0.204885] CPU5: thread -1, cpu 1, socket 1, mpidr 80000101
[    0.224875] CPU6: update cpu_capacity 448
[    0.224885] CPU6: thread -1, cpu 2, socket 1, mpidr 80000102
[    0.244876] CPU7: update cpu_capacity 448
[    0.244886] CPU7: thread -1, cpu 3, socket 1, mpidr 80000103
[    0.245053] Brought up 8 CPUs
[    0.316818] SMP: Total of 8 processors activated (384.00 BogoMIPS).
[    0.323151] CPU: All CPU(s) started in SVC mode.
[    0.328619] devtmpfs: initialized
[    0.354746] VFP support v0.3: implementor 41 architecture 4 part 30
variant f rev 0
[    0.362960] clocksource: jiffies: mask: 0xffffffff max_cycles:
0xffffffff, max_idle_ns: 9556302231375000 ns
[    0.374103] pinctrl core: initialized pinctrl subsystem
[    0.379947] NET: Registered protocol family 16
[    0.385336] DMA: preallocated 256 KiB pool for atomic coherent
allocations
[    0.404756] cpuidle: using governor menu
[    0.412891] exynos-audss-clk 3810000.audss-clock-controller: setup
completed
[    0.422092] gpio gpiochip0: (gpy7): added GPIO chardev (254:0)
[    0.427978] gpiochip_setup_dev: registered GPIOs 0 to 7 on device:
gpiochip0 (gpy7)
[    0.435577] gpio gpiochip1: (gpx0): added GPIO chardev (254:1)
[    0.441581] gpiochip_setup_dev: registered GPIOs 8 to 15 on device:
gpiochip1 (gpx0)
[    0.449281] gpio gpiochip2: (gpx1): added GPIO chardev (254:2)
[    0.455286] gpiochip_setup_dev: registered GPIOs 16 to 23 on device:
gpiochip2 (gpx1)
[    0.463074] gpio gpiochip3: (gpx2): added GPIO chardev (254:3)
[    0.469081] gpiochip_setup_dev: registered GPIOs 24 to 31 on device:
gpiochip3 (gpx2)
[    0.476867] gpio gpiochip4: (gpx3): added GPIO chardev (254:4)
[    0.482872] gpiochip_setup_dev: registered GPIOs 32 to 39 on device:
gpiochip4 (gpx3)
[    0.491481] gpio gpiochip5: (gpc0): added GPIO chardev (254:5)
[    0.497348] gpiochip_setup_dev: registered GPIOs 40 to 47 on device:
gpiochip5 (gpc0)
[    0.505131] gpio gpiochip6: (gpc1): added GPIO chardev (254:6)
[    0.511139] gpiochip_setup_dev: registered GPIOs 48 to 55 on device:
gpiochip6 (gpc1)
[    0.518924] gpio gpiochip7: (gpc2): added GPIO chardev (254:7)
[    0.524931] gpiochip_setup_dev: registered GPIOs 56 to 62 on device:
gpiochip7 (gpc2)
[    0.532716] gpio gpiochip8: (gpc3): added GPIO chardev (254:8)
[    0.538722] gpiochip_setup_dev: registered GPIOs 63 to 66 on device:
gpiochip8 (gpc3)
[    0.546510] gpio gpiochip9: (gpc4): added GPIO chardev (254:9)
[    0.552515] gpiochip_setup_dev: registered GPIOs 67 to 68 on device:
gpiochip9 (gpc4)
[    0.560303] gpio gpiochip10: (gpd1): added GPIO chardev (254:10)
[    0.566485] gpiochip_setup_dev: registered GPIOs 69 to 76 on device:
gpiochip10 (gpd1)
[    0.574357] gpio gpiochip11: (gpy0): added GPIO chardev (254:11)
[    0.580535] gpiochip_setup_dev: registered GPIOs 77 to 82 on device:
gpiochip11 (gpy0)
[    0.588410] gpio gpiochip12: (gpy1): added GPIO chardev (254:12)
[    0.594589] gpiochip_setup_dev: registered GPIOs 83 to 86 on device:
gpiochip12 (gpy1)
[    0.602463] gpio gpiochip13: (gpy2): added GPIO chardev (254:13)
[    0.608642] gpiochip_setup_dev: registered GPIOs 87 to 92 on device:
gpiochip13 (gpy2)
[    0.616518] gpio gpiochip14: (gpy3): added GPIO chardev (254:14)
[    0.622701] gpiochip_setup_dev: registered GPIOs 93 to 100 on device:
gpiochip14 (gpy3)
[    0.630657] gpio gpiochip15: (gpy4): added GPIO chardev (254:15)
[    0.636835] gpiochip_setup_dev: registered GPIOs 101 to 108 on
device: gpiochip15 (gpy4)
[    0.644888] gpio gpiochip16: (gpy5): added GPIO chardev (254:16)
[    0.651063] gpiochip_setup_dev: registered GPIOs 109 to 116 on
device: gpiochip16 (gpy5)
[    0.659111] gpio gpiochip17: (gpy6): added GPIO chardev (254:17)
[    0.665289] gpiochip_setup_dev: registered GPIOs 117 to 124 on
device: gpiochip17 (gpy6)
[    0.673856] gpio gpiochip18: (gpe0): added GPIO chardev (254:18)
[    0.679908] gpiochip_setup_dev: registered GPIOs 125 to 132 on
device: gpiochip18 (gpe0)
[    0.687948] gpio gpiochip19: (gpe1): added GPIO chardev (254:19)
[    0.694126] gpiochip_setup_dev: registered GPIOs 133 to 134 on
device: gpiochip19 (gpe1)
[    0.702174] gpio gpiochip20: (gpf0): added GPIO chardev (254:20)
[    0.708356] gpiochip_setup_dev: registered GPIOs 135 to 140 on
device: gpiochip20 (gpf0)
[    0.716401] gpio gpiochip21: (gpf1): added GPIO chardev (254:21)
[    0.722579] gpiochip_setup_dev: registered GPIOs 141 to 148 on
device: gpiochip21 (gpf1)
[    0.730628] gpio gpiochip22: (gpg0): added GPIO chardev (254:22)
[    0.736806] gpiochip_setup_dev: registered GPIOs 149 to 156 on
device: gpiochip22 (gpg0)
[    0.744857] gpio gpiochip23: (gpg1): added GPIO chardev (254:23)
[    0.751033] gpiochip_setup_dev: registered GPIOs 157 to 164 on
device: gpiochip23 (gpg1)
[    0.759081] gpio gpiochip24: (gpg2): added GPIO chardev (254:24)
[    0.765264] gpiochip_setup_dev: registered GPIOs 165 to 166 on
device: gpiochip24 (gpg2)
[    0.773309] gpio gpiochip25: (gpj4): added GPIO chardev (254:25)
[    0.779493] gpiochip_setup_dev: registered GPIOs 167 to 170 on
device: gpiochip25 (gpj4)
[    0.788029] gpio gpiochip26: (gpa0): added GPIO chardev (254:26)
[    0.794075] gpiochip_setup_dev: registered GPIOs 171 to 178 on
device: gpiochip26 (gpa0)
[    0.802119] gpio gpiochip27: (gpa1): added GPIO chardev (254:27)
[    0.808301] gpiochip_setup_dev: registered GPIOs 179 to 184 on
device: gpiochip27 (gpa1)
[    0.816346] gpio gpiochip28: (gpa2): added GPIO chardev (254:28)
[    0.822525] gpiochip_setup_dev: registered GPIOs 185 to 192 on
device: gpiochip28 (gpa2)
[    0.830573] gpio gpiochip29: (gpb0): added GPIO chardev (254:29)
[    0.836751] gpiochip_setup_dev: registered GPIOs 193 to 197 on
device: gpiochip29 (gpb0)
[    0.844800] gpio gpiochip30: (gpb1): added GPIO chardev (254:30)
[    0.850979] gpiochip_setup_dev: registered GPIOs 198 to 202 on
device: gpiochip30 (gpb1)
[    0.859026] gpio gpiochip31: (gpb2): added GPIO chardev (254:31)
[    0.865208] gpiochip_setup_dev: registered GPIOs 203 to 206 on
device: gpiochip31 (gpb2)
[    0.873254] gpio gpiochip32: (gpb3): added GPIO chardev (254:32)
[    0.879433] gpiochip_setup_dev: registered GPIOs 207 to 214 on
device: gpiochip32 (gpb3)
[    0.887480] gpio gpiochip33: (gpb4): added GPIO chardev (254:33)
[    0.893662] gpiochip_setup_dev: registered GPIOs 215 to 216 on
device: gpiochip33 (gpb4)
[    0.901708] gpio gpiochip34: (gph0): added GPIO chardev (254:34)
[    0.907897] gpiochip_setup_dev: registered GPIOs 217 to 224 on
device: gpiochip34 (gph0)
[    0.916503] gpio gpiochip35: (gpz): added GPIO chardev (254:35)
[    0.922456] gpiochip_setup_dev: registered GPIOs 225 to 231 on
device: gpiochip35 (gpz)
[    0.934388] EXYNOS5420 PMU initialized
[    0.966020] of_get_named_gpiod_flags: parsed 'gpio' property of node
'/regulator-usb300[0]' - status (0)
[    0.975689] of_get_named_gpiod_flags: parsed 'gpio' property of node
'/regulator-usb301[0]' - status (0)
[    0.985303] of_get_named_gpiod_flags: can't parse 'gpio' property of
node '/fixed-regulator[0]'
[    0.995569] SCSI subsystem initialized
[    0.999446] usbcore: registered new interface driver usbfs
[    1.004908] usbcore: registered new interface driver hub
[    1.010346] usbcore: registered new device driver usb
[    1.015851] s3c-i2c 12c80000.i2c: slave address 0x50
[    1.020732] s3c-i2c 12c80000.i2c: bus frequency set to 65 KHz
[    1.026817] s3c-i2c 12c80000.i2c: i2c-2: S3C I2C adapter
[    1.032853] Advanced Linux Sound Architecture Driver Initialized.
[    1.039949] clocksource: Switched to clocksource mct-frc
[    1.057595] NET: Registered protocol family 2
[    1.062235] TCP established hash table entries: 8192 (order: 3, 32768
bytes)
[    1.069247] TCP bind hash table entries: 8192 (order: 5, 163840 bytes)
[    1.075883] TCP: Hash tables configured (established 8192 bind 8192)
[    1.082251] UDP hash table entries: 512 (order: 2, 24576 bytes)
[    1.088220] UDP-Lite hash table entries: 512 (order: 2, 24576 bytes)
[    1.094763] NET: Registered protocol family 1
[    1.099356] RPC: Registered named UNIX socket transport module.
[    1.105209] RPC: Registered udp transport module.
[    1.109974] RPC: Registered tcp transport module.
[    1.114725] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    1.121421] Trying to unpack rootfs image as initramfs...
[    1.126940] rootfs image is not initramfs (junk in compressed
archive); looks like an initrd
[    1.160139] Unable to handle kernel paging request at virtual address
e3000000
[    1.167270] pgd = c0004000
[    1.170046] [e3000000] *pgd=00000000
[    1.173693] Internal error: Oops: 5 [#1] PREEMPT SMP ARM
[    1.179068] Modules linked in:
[    1.182194] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
4.6.0-00073-g35e691c #59
[    1.189477] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[    1.195638] task: edc88000 ti: edc76000 task.ti: edc76000
[    1.201111] PC is at memcpy+0x48/0x330
[    1.204923] LR is at iov_iter_copy_from_user_atomic+0x184/0x24c
[    1.210906] pc : [<c0320388>]    lr : [<c0331688>]    psr: 20000013
[    1.210906] sp : edc77cd4  ip : 00000000  fp : c070b640
[    1.222530] r10: 00000000  r9 : 00000000  r8 : ffefe000
[    1.227822] r7 : 00000000  r6 : ffeff000  r5 : 00001000  r4 : edc77dec
[    1.234415] r3 : 01000000  r2 : 00000f80  r1 : e3000000  r0 : ffefe000
[    1.241009] Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM
Segment none
[    1.248208] Control: 10c5387d  Table: 2000406a  DAC: 00000051
[    1.254020] Process swapper/0 (pid: 1, stack limit = 0xedc76210)
[    1.260093] Stack: (0xedc77cd4 to 0xedc78000)
[    1.264518] 7cc0:
00001000 ffeff000 00000000
[    1.272760] 7ce0: ffefe000 ffefe000 edc77dec c0331688 00001000
00001000 edc77df4 ed85508c
[    1.281001] 7d00: 00001000 01000000 00000000 00000000 c070b640
c01966d8 00001000 00000001
[    1.289242] 7d20: edc77d40 edc77d44 00000000 edf0e600 01000000
00000000 edc76000 00000001
[    1.297483] 7d40: eff519e0 c01f6100 00000000 00000000 edc77e08
00000000 edc77df4 edc77df4
[    1.305725] 7d60: edf0e600 ed85508c c0b45050 c0197f88 c0b45050
c06c9d3c c0b67b58 c0b67b58
[    1.313966] 7d80: 000000a8 00000003 ed855018 edc77e08 ed855018
edf0e600 edc77df4 02000000
[    1.322207] 7da0: 00000000 c0b4504c c0b45050 c0198118 eded6860
c0b4504c c0b45050 c01ec01c
[    1.330448] 7dc0: edf0e600 02000000 00000000 00000000 edc77e60
eded6860 c0b4504c c01dd0b8
[    1.338690] 7de0: 02000000 00000301 00000002 e2000000 02000000
00000003 01000000 01000000
[    1.346931] 7e00: edc77dec 00000001 edf0e600 00000000 00000000
00000000 00000000 00000000
[    1.355172] 7e20: 00000000 00000000 edf0e600 02000000 e2000000
edc77e60 00000000 c01dddac
[    1.363414] 7e40: ed854fa0 edf0e608 edf0e600 edf0e600 e2000000
02000000 00000000 c01dead8
[    1.371655] 7e60: 00000000 00000000 c08781c0 02000000 e2000000
00000000 00000000 c0a027a8
[    1.379896] 7e80: 00000000 00000000 eded6800 c0b43a4c 00000000
c0a02eb4 c0871494 eded685b
[    1.388137] 7ea0: 00000001 00000068 000241ed 00000000 00000000
00000000 00001000 00000000
[    1.396378] 7ec0: 57465fab 00000000 57465fab 00000000 00000000
376eac80 00000000 00000000
[    1.404619] 7ee0: 00000000 c0b05a50 c0b05a50 c0a02d70 00000000
edf24ac0 000000d4 c0a34848
[    1.412861] 7f00: 00000000 c0101814 c0b0a98c edc77f18 c0b47668
c06c98b0 60000000 c0b0933c
[    1.421102] 7f20: 00000000 c0b0933c c0926578 c0716b3c 000000d4
c0135ef0 0000cccd 00000000
[    1.429343] 7f40: c08dd0e0 00000000 00000005 00000005 c0b09318
efffc8c0 c0a5ba5c 00000005
[    1.437585] 7f60: c0a3483c c0b45000 c0b45000 000000d4 c0a34848
c0a00db8 00000005 00000005
[    1.445826] 7f80: 00000000 c0a005a0 00000000 c06c6254 00000000
00000000 00000000 00000000
[    1.454067] 7fa0: 00000000 c06c625c 00000000 c0107a38 00000000
00000000 00000000 00000000
[    1.462308] 7fc0: 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000
[    1.470549] 7fe0: 00000000 00000000 00000000 00000000 00000013
00000000 f7ffffff a7ffefff
[    1.478797] [<c0320388>] (memcpy) from [<c0331688>]
(iov_iter_copy_from_user_atomic+0x184/0x24c)
[    1.487646] [<c0331688>] (iov_iter_copy_from_user_atomic) from
[<c01966d8>] (generic_perform_write+0xf8/0x1c8)
[    1.497706] [<c01966d8>] (generic_perform_write) from [<c0197f88>]
(__generic_file_write_iter+0x198/0x1f4)
[    1.507420] [<c0197f88>] (__generic_file_write_iter) from
[<c0198118>] (generic_file_write_iter+0x134/0x260)
[    1.517311] [<c0198118>] (generic_file_write_iter) from [<c01dd0b8>]
(__vfs_write+0xa8/0xd8)
[    1.525811] [<c01dd0b8>] (__vfs_write) from [<c01dddac>]
(vfs_write+0x90/0x164)
[    1.533184] [<c01dddac>] (vfs_write) from [<c01dead8>]
(SyS_write+0x44/0x9c)
[    1.540301] [<c01dead8>] (SyS_write) from [<c0a027a8>] (xwrite+0x2c/0x68)
[    1.547152] [<c0a027a8>] (xwrite) from [<c0a02eb4>]
(populate_rootfs+0x144/0x268)
[    1.554700] [<c0a02eb4>] (populate_rootfs) from [<c0101814>]
(do_one_initcall+0x90/0x1d8)
[    1.562939] [<c0101814>] (do_one_initcall) from [<c0a00db8>]
(kernel_init_freeable+0x15c/0x1fc)
[    1.571706] [<c0a00db8>] (kernel_init_freeable) from [<c06c625c>]
(kernel_init+0x8/0x114)
[    1.579945] [<c06c625c>] (kernel_init) from [<c0107a38>]
(ret_from_fork+0x14/0x3c)
[    1.587576] Code: ba000002 f5d1f03c f5d1f05c f5d1f07c (e8b151f8)
[    1.593751] ---[ end trace 065c5ae2b4577941 ]---
[    1.598420] note: swapper/0[1] exited with preempt_count 1
[    1.604062] Kernel panic - not syncing: Attempted to kill init!
exitcode=0x0000000b
[    1.604062]
[    1.613263] CPU5: stopping
[    1.616048] CPU: 5 PID: 0 Comm: swapper/5 Tainted: G      D
4.6.0-00073-g35e691c #59
[    1.624540] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[    1.630729] [<c010e26c>] (unwind_backtrace) from [<c010afdc>]
(show_stack+0x10/0x14)
[    1.638525] [<c010afdc>] (show_stack) from [<c03217f4>]
(dump_stack+0x88/0x9c)
[    1.645808] [<c03217f4>] (dump_stack) from [<c010d508>]
(handle_IPI+0x190/0x1a4)
[    1.653264] [<c010d508>] (handle_IPI) from [<c01014d8>]
(gic_handle_irq+0x90/0x94)
[    1.660899] [<c01014d8>] (gic_handle_irq) from [<c010ba94>]
(__irq_svc+0x54/0x90)
[    1.668438] Exception stack(0xedcc7f88 to 0xedcc7fd0)
[    1.673562] 7f80:                   00000001 00000000 00000000
c0114120 edcc6000 c0b02454
[    1.681803] 7fa0: 00000000 c0a5f3f8 c0b024bc edcc7fe0 c0b024b4
00000000 f0806000 edcc7fd8
[    1.690040] 7fc0: c0108478 c010847c 60000013 ffffffff
[    1.695166] [<c010ba94>] (__irq_svc) from [<c010847c>]
(arch_cpu_idle+0x38/0x3c)
[    1.702630] [<c010847c>] (arch_cpu_idle) from [<c0152788>]
(cpu_startup_entry+0x1bc/0x240)
[    1.710955] [<c0152788>] (cpu_startup_entry) from [<2010156c>]
(0x2010156c)
[    1.717972] CPU1: stopping
[    1.720764] CPU: 1 PID: 0 Comm: swapper/1 Tainted: G      D
4.6.0-00073-g35e691c #59
[    1.729261] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[    1.735434] [<c010e26c>] (unwind_backtrace) from [<c010afdc>]
(show_stack+0x10/0x14)
[    1.743233] [<c010afdc>] (show_stack) from [<c03217f4>]
(dump_stack+0x88/0x9c)
[    1.750516] [<c03217f4>] (dump_stack) from [<c010d508>]
(handle_IPI+0x190/0x1a4)
[    1.757977] [<c010d508>] (handle_IPI) from [<c01014d8>]
(gic_handle_irq+0x90/0x94)
[    1.765609] [<c01014d8>] (gic_handle_irq) from [<c010ba94>]
(__irq_svc+0x54/0x90)
[    1.773156] Exception stack(0xedcbff88 to 0xedcbffd0)
[    1.778275] ff80:                   00000001 00000000 00000000
c0114120 edcbe000 c0b02454
[    1.786517] ffa0: 00000000 c0a5f3f8 c0b024bc edcbffe0 c0b024b4
00000000 00000000 edcbffd8
[    1.794755] ffc0: c0108478 c010847c 60000013 ffffffff
[    1.799879] [<c010ba94>] (__irq_svc) from [<c010847c>]
(arch_cpu_idle+0x38/0x3c)
[    1.807353] [<c010847c>] (arch_cpu_idle) from [<c0152788>]
(cpu_startup_entry+0x1bc/0x240)
[    1.815664] [<c0152788>] (cpu_startup_entry) from [<2010156c>]
(0x2010156c)
[    1.822697] CPU7: stopping
[    1.825456] CPU: 7 PID: 0 Comm: swapper/7 Tainted: G      D
4.6.0-00073-g35e691c #59
[    1.833952] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[    1.840127] [<c010e26c>] (unwind_backtrace) from [<c010afdc>]
(show_stack+0x10/0x14)
[    1.847931] [<c010afdc>] (show_stack) from [<c03217f4>]
(dump_stack+0x88/0x9c)
[    1.855218] [<c03217f4>] (dump_stack) from [<c010d508>]
(handle_IPI+0x190/0x1a4)
[    1.862675] [<c010d508>] (handle_IPI) from [<c01014d8>]
(gic_handle_irq+0x90/0x94)
[    1.870309] [<c01014d8>] (gic_handle_irq) from [<c010ba94>]
(__irq_svc+0x54/0x90)
[    1.877847] Exception stack(0xedccbf88 to 0xedccbfd0)
[    1.882972] bf80:                   00000001 00000000 00000000
c0114120 edcca000 c0b02454
[    1.891215] bfa0: 00000000 c0a5f3f8 c0b024bc edccbfe0 c0b024b4
00000000 f0806000 edccbfd8
[    1.899452] bfc0: c0108478 c010847c 60000013 ffffffff
[    1.904577] [<c010ba94>] (__irq_svc) from [<c010847c>]
(arch_cpu_idle+0x38/0x3c)
[    1.912040] [<c010847c>] (arch_cpu_idle) from [<c0152788>]
(cpu_startup_entry+0x1bc/0x240)
[    1.920364] [<c0152788>] (cpu_startup_entry) from [<2010156c>]
(0x2010156c)
[    1.927381] CPU2: stopping
[    1.930164] CPU: 2 PID: 0 Comm: swapper/2 Tainted: G      D
4.6.0-00073-g35e691c #59
[    1.938663] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[    1.944826] [<c010e26c>] (unwind_backtrace) from [<c010afdc>]
(show_stack+0x10/0x14)
[    1.952634] [<c010afdc>] (show_stack) from [<c03217f4>]
(dump_stack+0x88/0x9c)
[    1.959918] [<c03217f4>] (dump_stack) from [<c010d508>]
(handle_IPI+0x190/0x1a4)
[    1.967379] [<c010d508>] (handle_IPI) from [<c01014d8>]
(gic_handle_irq+0x90/0x94)
[    1.975012] [<c01014d8>] (gic_handle_irq) from [<c010ba94>]
(__irq_svc+0x54/0x90)
[    1.982558] Exception stack(0xedcc1f88 to 0xedcc1fd0)
[    1.987675] 1f80:                   00000001 00000000 00000000
c0114120 edcc0000 c0b02454
[    1.995919] 1fa0: 00000000 c0a5f3f8 c0b024bc edcc1fe0 c0b024b4
00000000 f0806000 edcc1fd8
[    2.004162] 1fc0: c0108478 c010847c 60000013 ffffffff
[    2.009280] [<c010ba94>] (__irq_svc) from [<c010847c>]
(arch_cpu_idle+0x38/0x3c)
[    2.016742] [<c010847c>] (arch_cpu_idle) from [<c0152788>]
(cpu_startup_entry+0x1bc/0x240)
[    2.025067] [<c0152788>] (cpu_startup_entry) from [<2010156c>]
(0x2010156c)
[    2.032097] CPU4: stopping
[    2.034866] CPU: 4 PID: 0 Comm: swapper/4 Tainted: G      D
4.6.0-00073-g35e691c #59
[    2.043361] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[    2.049538] [<c010e26c>] (unwind_backtrace) from [<c010afdc>]
(show_stack+0x10/0x14)
[    2.057343] [<c010afdc>] (show_stack) from [<c03217f4>]
(dump_stack+0x88/0x9c)
[    2.064628] [<c03217f4>] (dump_stack) from [<c010d508>]
(handle_IPI+0x190/0x1a4)
[    2.072086] [<c010d508>] (handle_IPI) from [<c01014d8>]
(gic_handle_irq+0x90/0x94)
[    2.079719] [<c01014d8>] (gic_handle_irq) from [<c010ba94>]
(__irq_svc+0x54/0x90)
[    2.087259] Exception stack(0xedcc5f88 to 0xedcc5fd0)
[    2.092382] 5f80:                   00000001 00000000 00000000
c0114120 edcc4000 c0b02454
[    2.100626] 5fa0: 00000000 c0a5f3f8 c0b024bc edcc5fe0 c0b024b4
00000000 f0806000 edcc5fd8
[    2.108862] 5fc0: c0108478 c010847c 60000013 ffffffff
[    2.113988] [<c010ba94>] (__irq_svc) from [<c010847c>]
(arch_cpu_idle+0x38/0x3c)
[    2.121451] [<c010847c>] (arch_cpu_idle) from [<c0152788>]
(cpu_startup_entry+0x1bc/0x240)
[    2.129775] [<c0152788>] (cpu_startup_entry) from [<2010156c>]
(0x2010156c)
[    2.136795] CPU6: stopping
[    2.139573] CPU: 6 PID: 0 Comm: swapper/6 Tainted: G      D
4.6.0-00073-g35e691c #59
[    2.148068] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[    2.154244] [<c010e26c>] (unwind_backtrace) from [<c010afdc>]
(show_stack+0x10/0x14)
[    2.162050] [<c010afdc>] (show_stack) from [<c03217f4>]
(dump_stack+0x88/0x9c)
[    2.169335] [<c03217f4>] (dump_stack) from [<c010d508>]
(handle_IPI+0x190/0x1a4)
[    2.176793] [<c010d508>] (handle_IPI) from [<c01014d8>]
(gic_handle_irq+0x90/0x94)
[    2.184426] [<c01014d8>] (gic_handle_irq) from [<c010ba94>]
(__irq_svc+0x54/0x90)
[    2.191966] Exception stack(0xedcc9f88 to 0xedcc9fd0)
[    2.197090] 9f80:                   00000001 00000000 00000000
c0114120 edcc8000 c0b02454
[    2.205333] 9fa0: 00000000 c0a5f3f8 c0b024bc edcc9fe0 c0b024b4
00000000 f0806000 edcc9fd8
[    2.213569] 9fc0: c0108478 c010847c 60000013 ffffffff
[    2.218695] [<c010ba94>] (__irq_svc) from [<c010847c>]
(arch_cpu_idle+0x38/0x3c)
[    2.226157] [<c010847c>] (arch_cpu_idle) from [<c0152788>]
(cpu_startup_entry+0x1bc/0x240)
[    2.234482] [<c0152788>] (cpu_startup_entry) from [<2010156c>]
(0x2010156c)
[    2.241498] CPU3: stopping
[    2.244279] CPU: 3 PID: 0 Comm: swapper/3 Tainted: G      D
4.6.0-00073-g35e691c #59
[    2.252779] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[    2.258944] [<c010e26c>] (unwind_backtrace) from [<c010afdc>]
(show_stack+0x10/0x14)
[    2.266750] [<c010afdc>] (show_stack) from [<c03217f4>]
(dump_stack+0x88/0x9c)
[    2.274036] [<c03217f4>] (dump_stack) from [<c010d508>]
(handle_IPI+0x190/0x1a4)
[    2.281495] [<c010d508>] (handle_IPI) from [<c01014d8>]
(gic_handle_irq+0x90/0x94)
[    2.289129] [<c01014d8>] (gic_handle_irq) from [<c010ba94>]
(__irq_svc+0x54/0x90)
[    2.296675] Exception stack(0xedcc3f88 to 0xedcc3fd0)
[    2.301795] 3f80:                   00000001 00000000 00000000
c0114120 edcc2000 c0b02454
[    2.310036] 3fa0: 00000000 c0a5f3f8 c0b024bc edcc3fe0 c0b024b4
00000000 f0806000 edcc3fd8
[    2.318276] 3fc0: c0108478 c010847c 60000013 ffffffff
[    2.323396] [<c010ba94>] (__irq_svc) from [<c010847c>]
(arch_cpu_idle+0x38/0x3c)
[    2.330858] [<c010847c>] (arch_cpu_idle) from [<c0152788>]
(cpu_startup_entry+0x1bc/0x240)
[    2.339184] [<c0152788>] (cpu_startup_entry) from [<2010156c>]
(0x2010156c)
[    2.346219] ---[ end Kernel panic - not syncing: Attempted to kill
init! exitcode=0x0000000b
[    2.346219]
[   38.194984] random: nonblocking pool is initialized


Thanks,
Pankaj Dubey


From thunder.leizhen at huawei.com  Wed May 25 20:40:34 2016
From: thunder.leizhen at huawei.com (Leizhen (ThunderTown))
Date: Thu, 26 May 2016 11:40:34 +0800
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <20160525105022.GC5996@e104818-lin.cambridge.arm.com>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
 <20160524113727.GD25374@leverpostej> <574446B9.8040105@huawei.com>
 <20160524130255.GU4892@e104818-lin.cambridge.arm.com>
 <5744FDD0.8060504@huawei.com> <57451DC6.7080106@huawei.com>
 <20160525105022.GC5996@e104818-lin.cambridge.arm.com>
Message-ID: <57467032.1030200@huawei.com>



On 2016/5/25 18:50, Catalin Marinas wrote:
> On Wed, May 25, 2016 at 11:36:38AM +0800, Leizhen (ThunderTown) wrote:
>> On 2016/5/25 9:20, Leizhen (ThunderTown) wrote:
>>> On 2016/5/24 21:02, Catalin Marinas wrote:
>>>> On Tue, May 24, 2016 at 08:19:05PM +0800, Leizhen (ThunderTown) wrote:
>>>>> On 2016/5/24 19:37, Mark Rutland wrote:
>>>>>> It looks like the test may be missing I-cache maintenance regardless of
>>>>>> the semantics of mprotect in this case.
>>>>>>
>>>>>> I have not yet devled into flush_cache_range and how it is called.
>>>>>
>>>>> SYSCALL_DEFINE3(mprotect ---> mprotect_fixup ---> change_protection ---> change_protection_range --> flush_cache_range
>>>>
>>>> The change_protection() shouldn't need to flush the caches in
>>>> flush_cache_range(). The change_pte_range() function eventually ends up
>>>> calling set_pte_at() which calls __sync_icache_dcache() if the mapping
>>>> is executable.
>>>
>>> OK, I see.
>>> But I'm afraid it entered the "if (pte_present(oldpte))" branch in
>>> function change_pte_range. Because the test case called mmap to
>>> create pte first, then called pte_modify. I will check it later.
>>
>> I have checked that it entered "if (pte_present(oldpte))" branch.
> 
> This path eventually calls set_pte_at() via ptep_modify_prot_commit().
OK, I see.

> 
>> But I don't known why I add flush_icache_range is OK, but add
>> __sync_icache_dcache have no effect.
> 
> Do you mean you modified set_pte_at() to use flush_icache_range()
Just about. I added in change_pte_range after below statement.
ptent = pte_modify(ptent, newprot);

> instead of __sync_icache_dcache() and it works?
Yes.

> 
> What happens is that __sync_icache_dcache() only takes care of the first
> time a page is mapped in user space and flushes the caches, marking it
> as "clean" (PG_dcache_clean) afterwards. Subsequent changes to this
> mapping or writes to it are entirely the responsibility of the user. So
> if the user plans to execute instructions, it better explicitly flush
> the caches (as Mark Rutland already stated in a previous reply).
> 
> I ran our internal LTP version yesterday and it was fine but didn't
> realise that we actually patched mprotect04.c to include:
> 
> 	__clear_cache((char *)func, (char *)func + page_sz);
> 
> just after memcpy().
Yes, I aslo tried this before I sent this patch. Flush dcache in userspace
or kernel can both fixs this problem.

> 
> (we still need to investigate whether the I-cache invalidation is
> actually needed in flush_cache_range() or it's just something we forgot
> to remove)
> 



From ivo.g.dimitrov.75 at gmail.com  Wed May 25 20:46:08 2016
From: ivo.g.dimitrov.75 at gmail.com (Ivaylo Dimitrov)
Date: Thu, 26 May 2016 06:46:08 +0300
Subject: [PATCHv3] support for AD5820 camera auto-focus coil
In-Reply-To: <20160524202059.GB18536@amd>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com> <20160521105607.GA20071@amd>
 <574049EF.2090208@gmail.com> <20160524090433.GA1277@amd>
 <57441BF8.60606@gmail.com> <20160524202059.GB18536@amd>
Message-ID: <57467180.5070201@gmail.com>



On 24.05.2016 23:20, Pavel Machek wrote:
> Hi!
>
>>>> devm_regulator_get()?
>>>
>>> I'd rather avoid devm_ here. Driver is simple enough to allow it.
>>>
>>
>> Now thinking about it, what would happen here if regulator_get() returns
>> -EPROBE_DEFER? Wouldn't it be better to move regulator_get to the probe()
>> function, something like:
>
> Ok, I can do it.
>
> Oh, and don't try to complain about newlines before returns. It looks
> better this way.
>

All I complain about is missing empty line before a final return at the 
end of a function :). I guess it is a matter of preference though.

>> static int ad5820_probe(struct i2c_client *client,
>> 			const struct i2c_device_id *devid)
>> {
>> 	struct ad5820_device *coil;
>> 	int ret = 0;
>>
>> 	coil = devm_kzalloc(sizeof(*coil), GFP_KERNEL);
>> 	if (coil == NULL)
>> 		return -ENOMEM;
>>
>> 	coil->vana = devm_regulator_get(&client->dev, NULL);
>> 	if (IS_ERR(coil->vana)) {
>> 		ret = PTR_ERR(coil->vana);
>> 		if (ret != -EPROBE_DEFER)
>> 			dev_err(&client->dev, "could not get regulator for vana\n");
>> 		return ret;
>> 	}
>>
>> 	mutex_init(&coil->power_lock);
>> ...
>>
>> with the appropriate changes to remove() because of the devm API
>> 			usage.
>
> Something like this?
>

Didn't try to apply it, but yes, looks right. Besides the missing
mutex_destroy(&coil->power_lock); pointed out by Sakari.

> diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
> index f956bd3..f871366 100644
> --- a/drivers/media/i2c/ad5820.c
> +++ b/drivers/media/i2c/ad5820.c
> @@ -8,7 +8,7 @@
>    * Copyright (C) 2016 Pavel Machek <pavel at ucw.cz>
>    *
>    * Contact: Tuukka Toivonen
> - *          Sakari Ailus
> + *	    Sakari Ailus
>    *
>    * Based on af_d88.c by Texas Instruments.
>    *
> @@ -263,13 +263,6 @@ static int ad5820_init_controls(struct ad5820_device *coil)
>   static int ad5820_registered(struct v4l2_subdev *subdev)
>   {
>   	struct ad5820_device *coil = to_ad5820_device(subdev);
> -	struct i2c_client *client = v4l2_get_subdevdata(subdev);
> -
> -	coil->vana = regulator_get(&client->dev, "VANA");
> -	if (IS_ERR(coil->vana)) {
> -		dev_err(&client->dev, "could not get regulator for vana\n");
> -		return -ENODEV;
> -	}
>
>   	return ad5820_init_controls(coil);
>   }
> @@ -367,10 +360,18 @@ static int ad5820_probe(struct i2c_client *client,
>   	struct ad5820_device *coil;
>   	int ret = 0;
>
> -	coil = kzalloc(sizeof(*coil), GFP_KERNEL);
> +	coil = devm_kzalloc(sizeof(*coil), GFP_KERNEL);
>   	if (!coil)
>   		return -ENOMEM;
>
> +	coil->vana = devm_regulator_get(&client->dev, NULL);
> +	if (IS_ERR(coil->vana)) {
> +		ret = PTR_ERR(coil->vana);
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(&client->dev, "could not get regulator for vana\n");
> +		return ret;
> +	}
> +	
>   	mutex_init(&coil->power_lock);
>
>   	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
> @@ -390,10 +391,6 @@ static int ad5820_probe(struct i2c_client *client,
>
>   cleanup:
>   	media_entity_cleanup(&coil->subdev.entity);
> -
> -free:
> -	kfree(coil);
> -
>   	return ret;
>   }
>
> @@ -405,11 +402,6 @@ static int __exit ad5820_remove(struct i2c_client *client)
>   	v4l2_device_unregister_subdev(&coil->subdev);
>   	v4l2_ctrl_handler_free(&coil->ctrls);
>   	media_entity_cleanup(&coil->subdev.entity);
> -	if (coil->vana)
> -		regulator_put(coil->vana);
> -
> -	kfree(coil);
> -
>   	return 0;
>   }
>


From jh80.chung at samsung.com  Wed May 25 20:59:07 2016
From: jh80.chung at samsung.com (Jaehoon Chung)
Date: Thu, 26 May 2016 12:59:07 +0900
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <4d8f3992-a1d3-6010-4964-8ca13cddc1c5@rock-chips.com>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <5502CA4E.9060401@samsung.com>
 <CAD=FV=VX3ix-j4y95W1q8b-aVuVEN+4xsd8WLx2xcE7KPNJwRw@mail.gmail.com>
 <5506707D.40708@samsung.com> <55189F04.8000404@samsung.com>
 <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
 <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
 <573BCC8D.5090606@kernel-upstream.org>
 <CAD=FV=VneQR3wurjezBkRhtQiH+q-FfhDN8=Ym=XqtZpVmsdUw@mail.gmail.com>
 <573C3283.1040606@rock-chips.com>
 <CAD=FV=UoT2GRYWJWXEn_ccvKGgC+PzQM_BCtLHAa7jxzbaQ9SA@mail.gmail.com>
 <10b3dc0e-aebf-664b-b36b-c54692cd9983@rock-chips.com>
 <573DBAA5.2070706@samsung.com>
 <CGME20160526022412epcas1p1408431e9596aaf84e8b58510ee81d4c4@epcas1p1.samsung.com>
 <4d8f3992-a1d3-6010-4964-8ca13cddc1c5@rock-chips.com>
Message-ID: <5746748B.7080305@samsung.com>

On 05/26/2016 11:23 AM, Shawn Lin wrote:
> Hi Jaehoon,
> 
> On 2016/5/19 21:07, Jaehoon Chung wrote:
>> On 05/19/2016 08:31 PM, Shawn Lin wrote:
>>> Hi,
>>>
>>> On 2016/5/19 1:37, Doug Anderson wrote:
>>>> Hi,
>>>>
>>>> On Wed, May 18, 2016 at 2:14 AM, Shawn Lin <shawn.lin at rock-chips.com> wrote:
>>>>> Hi
>>>>>
>>>>>
>>>>> On 2016-5-18 12:12, Doug Anderson wrote:
>>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> On Tue, May 17, 2016 at 6:59 PM, Shawn Lin
>>>>>> <shawn.lin at kernel-upstream.org> wrote:
>>>>>>>
>>>>>>> Could you try this patch to see if you can still find HLE?
>>>>>>>
>>>>>>> @@ -2356,12 +2356,22 @@ static void dw_mci_cmd_interrupt(struct dw_mci
>>>>>>> *host, u32 status)
>>>>>>>   static void dw_mci_handle_cd(struct dw_mci *host)
>>>>>>>   {
>>>>>>>          int i;
>>>>>>> +       int present;
>>>>>>>
>>>>>>>          for (i = 0; i < host->num_slots; i++) {
>>>>>>>                  struct dw_mci_slot *slot = host->slot[i];
>>>>>>>
>>>>>>>                  if (!slot)
>>>>>>>                          continue;
>>>>>>>
>>>>>>> +               present = !(mci_readl(slot->host, CDETECT) & (1 <<
>>>>>>> slot->id));
>>>>>>> +               if (present)
>>>>>>> +                       set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>>>>>>> +               else
>>>>>>> +                       clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>>>>>>
>>>>>>
>>>>>> No, because we don't use the builtin card detect on veyron.  ;)
>>>>>>
>>>>>> We use GPIO card detect because we didn't like the way JTAG and SD
>>>>>> interacted.  Also on rk3288 the builtin card detect line had the wrong
>>>>>> voltage domain (you couldn't detect a card when the IO lines were
>>>>>> powered off).  The builtin card detect line is always driven low on
>>>>>> veyron.
>>>>>
>>>>>
>>>>> Okay, I see.
>>>>>
>>>>>>
>>>>>>
>>>>>> I'm nearly certain that the root cause of my HLE errors is actually
>>>>>> related to the same problem addressed by the commit 7c5209c315ea
>>>>>> ("mmc: core: Increase delay for voltage to stabilize from 3.3V to
>>>>>> 1.8V").  I think that on minnie we're still on the hairy edge and
>>>>>> sometimes the line doesn't transition fast enough.
>>>>>
>>>>>
>>>>> Things are not so simple from your details.
>>>>>
>>>>> I was not enabling SD3.0 support, then I also found HLE sometimes.
>>>>> So it seems commit 7c5209c315ea does not contibute to this phenomenon.
>>>>
>>>> Just to clarify, in my case commit 7c5209c315ea didn't make the
>>>> problem worse, but made it better.  Just not better enough.  ;)
>>>>
>>>>
>>>>> The scenario looks like:
>>>>> remove sd-card -> mmc_sd_detect -> send status(CMD13) ->power_off ->
>>>>> set_ios -> setup_bus -> disabled clk , then HLE irq storm coming
>>>>>
>>>>> From the code of dw_mci_prepare_command:
>>>>> SDMMC_CMD_PRV_DAT_WAIT will not be used for CMD13, so we don't
>>>>> wait_busy here, then cmd code is loding into queue of dw_mmc but
>>>>> still failing send out because it's in busy?
>>>>>
>>>>> With my patch, things go well:
>>>>> remove sd-card -> clear bit of DW_MMC_CARD_PRESENT  -> send
>>>>> status(CMD13) return directly -> power_off -> set_ios -> setup_bus ->
>>>>> disable clk
>>>>>
>>>>> So why should we allow inquiry of card status if we sure the card is
>>>>> removed? I mean no any further cmds should be delivered.
>>>>
>>>> Quite honestly just dealing with the HLE error (my patch or
>>>> equivalent) might be a sane solution for the problem you describe.
>>>
>>> Yes, your patch looks good to me, so it should be merged firstly. :)
>>> Then let's push it a bit further more that when HLEs are coming,
>>> somethings must be wrong(currently I don't see a obvious clue from
>>> the code itself although, I'm prone to think it belongs to the
>>> software issue).
>>
>> We don't know what's main cause for HLE..But i also think it's relevant to SW issue.
>> But we need to consider all possibilities..
>>
>>>
>>>
>>>>
>>>> dw_mmc needs to be able to work with an external card detect GPIO.
>>>> It's been part of the dw_mmc driver for a long time and is (in fact)
>>>> in use upstream at least by rk3288-veyron.  Any solution that only
>>>> works for internal card detect is not enough.  Just handling the HLE
>>>> error to deal with the interrupt storm and then letting Linux remove
>>>> the card (because of the card detect interrupt) seems totally OK to
>>>> me.
>>>>
>>>
>>> Sure, some of rockchip Socs use gpio for CD because they don't
>>> have a internal CD, such as RK3036, right?
>>>
>>>> Note: I'd be very curious if your problems get better if you disable
>>>
>>> Not at all.
>>>
>>>> the "grf_force_jtag" bit in the GRF.  If you're using the builtin card
>>>> detect and you use the boot default of "grf_force_jtag" then your pins
>>>> will be unmuxed behind your back when the card is ejected.  This could
>>>> be causing the dw_mmc controller to get confused.
>>>
>>> Right, grf_force_jtag is also not a friend of mine. :)
>>> So I had disabled this function before I was debugging it.
>>>
>>>>
>>>>
>>>>> And another question: should we wait busy for cmd13?
>>>>
>>>> I don't think so.  As I understand it CMD13 uses only the CMD line for
>>>> communication and it should be appropriate to send this when the bus
>>>> is "busy" (which means that the DATA lines are low).
>>>
>>> Ahh... take back my question.. I was just considering a wired situation
>>> that pins are unmuxed on the background(cmd line as well) when cmd13 is
>>> delivering....
>>>
>>>
>>>>
>>>> Also: it seems odd that the HLE IRQ storm didn't come right after the
>>>> CMD 13 in your description above.  Are you sure it was the CMD 13 that
>>>> caused the HLEs, or could it has been something else?
>>>
>>> Actually no. Any cmds be issued can trigger HLEs, I think, after sd card is removed When I hacked mmc_sd_detecd to send other cmds intead
>>> of cmd13.
>>>
>>> From dw_mmc databook v270a(7.2.3 Clock Programming) we can see:
>>> The DWC_mobile_storage loads each of these registers only when the
>>> start_cmd bit and the Update_clk_regs_only bit in the CMD register are
>>> set. When a command is successfully loaded, the DWC_mobile_storage
>>> clears this bit, unless the DWC_mobile_storage already has another
>>> command in the queue, at which point it gives an HLE (Hardware Locked
>>> Error); for details on HLEs, refer to ?Error Handling? on page 233.
>>> Software should look for the start_cmd and the Update_clk_regs_only
>>> bits, and should also set the wait_prvdata_complete bit to ensure that
>>> clock parameters do not change during data transfer.
>>>
>>> Maybe the cmd is trying to load(or somethings wrong with the
>>> controller?) when we disable the clk? That may explain my observation
>>> that HLEs came after disabling clk.
>>
>> I agreed.
>>
>> To Disable clock, it sends cmd with update_clk_regs_only and wait_prvdata_complete bit.
>> I think it's problem..(waiting for prvdata..)
>>
>> If there are ongoing some data(read/write), then before disabling clock, waiting for completing previous data.
>> (But card was already removed, and it couldn't do anything.)
>> It's difficult to analyze the HLE..So After applying first, then we can solve this problem, step by step.
>>
> 
> I saw you send a PR for v4.7-fix to Ulf which didn't include this one.
> Do you plan to add it into 4.8 materials? :)

Yes, I think good that this is prepared for next. (Will apply on this weekend.)
Do you have other opinion? :)

If you have other opinion, i will reflect yours. Thanks!

Best Regards,
Jaehoon Chung

> 
>> Best Regards,
>> Jaehoon Chung
>>
>>>
>>>
>>>>
>>>>
>>>> -Doug
>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>>
>>
> 
> 



From lokeshvutla at ti.com  Wed May 25 20:55:24 2016
From: lokeshvutla at ti.com (Lokesh Vutla)
Date: Thu, 26 May 2016 09:25:24 +0530
Subject: [PATCH 1/2] arm: dra7: Add hwmod entry for i2c6
In-Reply-To: <20160525125341.10044-2-rk@ti.com>
References: <20160525125341.10044-1-rk@ti.com>
 <20160525125341.10044-2-rk@ti.com>
Message-ID: <574673AC.2030209@ti.com>



On Wednesday 25 May 2016 06:23 PM, Ravikumar Kattekola wrote:
> dra72x device has i2c6 controller.
> Adding hwmod definition for the same.
> 
> Reference DRA72x TRM [ SPRUHP2Q ]
> 
> Signed-off-by: Ravikumar Kattekola <rk at ti.com>
> ---
>  arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
> index d0e7e525..b84c0f7 100644
> --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
> +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
> @@ -1127,6 +1127,20 @@ static struct omap_hwmod dra7xx_i2c5_hwmod = {
>  	.dev_attr	= &i2c_dev_attr,
>  };
>  
> +/* i2c6 */
> +static struct omap_hwmod dra7xx_i2c6_hwmod = {
> +	.name		= "i2c6",
> +	.class		= &dra7xx_i2c_hwmod_class,
> +	.clkdm_name	= "l4per2_clkdm",
> +	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
> +	.main_clk	= "func_96m_fclk",
> +	.prcm = {
> +		.omap4 = {
> +		},
> +	},
> +	.dev_attr	= &i2c_dev_attr,
> +};
> +
>  /*
>   * 'mailbox' class
>   *
> @@ -3186,6 +3200,14 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per1__i2c5 = {
>  	.user		= OCP_USER_MPU | OCP_USER_SDMA,
>  };
>  
> +/* l4_per2 -> i2c6 */
> +static struct omap_hwmod_ocp_if dra7xx_l4_per2__i2c6 = {
> +	.master		= &dra7xx_l4_per2_hwmod,
> +	.slave		= &dra7xx_i2c6_hwmod,
> +	.clk		= "l3_iclk_div",
> +	.user		= OCP_USER_MPU | OCP_USER_SDMA,
> +};
> +
>  /* l4_cfg -> mailbox1 */
>  static struct omap_hwmod_ocp_if dra7xx_l4_cfg__mailbox1 = {
>  	.master		= &dra7xx_l4_cfg_hwmod,
> @@ -3857,6 +3879,7 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
>  	&dra7xx_l4_per1__i2c3,
>  	&dra7xx_l4_per1__i2c4,
>  	&dra7xx_l4_per1__i2c5,
> +	&dra7xx_l4_per2__i2c6,

If it is available only on dra72x, register the hwmod under
dra72x_hwmod_ocp_ifs. Also in $subject use dra72x to make things clear.

Thanks and regards,
Lokesh

>  	&dra7xx_l4_cfg__mailbox1,
>  	&dra7xx_l4_per3__mailbox2,
>  	&dra7xx_l4_per3__mailbox3,
> 


From sricharan at codeaurora.org  Wed May 25 21:03:39 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Thu, 26 May 2016 09:33:39 +0530
Subject: [RFC 5/9] drivers: platform: Configure dma operations at probe
 time
In-Reply-To: <5744770D.9090303@arm.com>
References: <1461599894-1969-1-git-send-email-sricharan@codeaurora.org>
 <1461599894-1969-6-git-send-email-sricharan@codeaurora.org>
 <5744770D.9090303@arm.com>
Message-ID: <000401d1b703$993446e0$cb9cd4a0$@codeaurora.org>

Hi Robin,

>On 25/04/16 16:58, Sricharan R wrote:
>> From: Laurent Pinchart <laurent.pinchart+renesas at ideasonboard.com>
>>
>> Configuring DMA ops at probe time will allow deferring device probe when
>> the IOMMU isn't available yet.
>>
>> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas at ideasonboard.com>
>> ---
>>   drivers/base/platform.c | 13 +++++++++++++
>>   drivers/of/platform.c   |  7 +++----
>>   2 files changed, 16 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
>> index f437afa..17e64a4 100644
>> --- a/drivers/base/platform.c
>> +++ b/drivers/base/platform.c
>> @@ -557,6 +557,12 @@ static int platform_drv_probe(struct device *_dev)
>>   	if (ret < 0)
>>   		return ret;
>>
>> +	if (of_have_populated_dt()) {
>> +		ret = of_dma_configure_ops(_dev, _dev->of_node);
>> +		if (ret < 0)
>> +			goto done;
>> +	}
>> +
>>   	ret = dev_pm_domain_attach(_dev, true);
>>   	if (ret != -EPROBE_DEFER) {
>>   		if (drv->probe) {
>> @@ -569,6 +575,11 @@ static int platform_drv_probe(struct device *_dev)
>>   		}
>>   	}
>>
>> +	if (of_have_populated_dt()) {
>> +		if (ret)
>> +			of_dma_deconfigure(_dev);
>> +	}
>> +done:
>>   	if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
>>   		dev_warn(_dev, "probe deferral not supported\n");
>>   		ret = -ENXIO;
>> @@ -591,6 +602,8 @@ static int platform_drv_remove(struct device *_dev)
>>   	if (drv->remove)
>>   		ret = drv->remove(dev);
>>   	dev_pm_domain_detach(_dev, true);
>> +	if (of_have_populated_dt())
>> +		of_dma_deconfigure(_dev);
>>
>>   	return ret;
>>   }
>> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
>> index 17ee8d5..12bbc8e1 100644
>> --- a/drivers/of/platform.c
>> +++ b/drivers/of/platform.c
>> @@ -180,11 +180,9 @@ static struct platform_device *of_platform_device_create_pdata(
>>   	dev->dev.bus = &platform_bus_type;
>>   	dev->dev.platform_data = platform_data;
>>   	of_dma_configure_masks(&dev->dev, dev->dev.of_node);
>> -	of_dma_configure_ops(&dev->dev, dev->dev.of_node);
>>   	of_msi_configure(&dev->dev, dev->dev.of_node);
>>
>>   	if (of_device_add(dev) != 0) {
>> -		of_dma_deconfigure(&dev->dev);
>>   		platform_device_put(dev);
>>   		goto err_clear_flag;
>>   	}
>> @@ -481,11 +479,12 @@ static int of_platform_device_destroy(struct device *dev, void *data)
>>   	if (dev->bus == &platform_bus_type)
>>   		platform_device_unregister(to_platform_device(dev));
>>   #ifdef CONFIG_ARM_AMBA
>> -	else if (dev->bus == &amba_bustype)
>> +	else if (dev->bus == &amba_bustype) {
>>   		amba_device_unregister(to_amba_device(dev));
>> +		of_dma_deconfigure(dev);
>> +	}
>
>Note that we definitely need this to happen properly on other buses,
>too. I had something for the AMBA bus back when I last looked at
>this[0], but since then we now have PCI devices going through the
>of_dma_configure() path as well (hence 226d89cbb242).
>
>There's also now some initial ACPI code in flight[1], so it's probably
>about time to take another closer look at how this can be properly
>generalised, but I'm not necessarily averse to starting with a
>DT-focused solution that gets at least half way, then building on top of
>that.

Thanks for direction. I will definitely look at how this can be generalised
 for other buses as well. Based on how that looks, as you said if required
 a DT-only can be done first.

Regards,
 Sricharan




From yangbo.lu at nxp.com  Wed May 25 21:05:26 2016
From: yangbo.lu at nxp.com (Yangbo Lu)
Date: Thu, 26 May 2016 04:05:26 +0000
Subject: [v10, 7/7] mmc: sdhci-of-esdhc: fix host version for
 T4240-R1.0-R2.0
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <4448030.Zs8fVnr3nm@wuerfel>
 <HE1PR04MB0889B52134A43C0E7A452B7BF87C0@HE1PR04MB0889.eurprd04.prod.outlook.com>
 <5159406.HOFrj7pRfW@wuerfel> <1462937186.16584.77.camel@buserror.net> 
Message-ID: <HE1PR04MB0889852B7809A1CCFF8922ACF8410@HE1PR04MB0889.eurprd04.prod.outlook.com>

Hi Uffe,

Could we merge this patchset? ...
It has been a long time to wait for Arnd's response...
 
Thanks a lot.


Best regards,
Yangbo Lu


> -----Original Message-----
> From: Yangbo Lu
> Sent: Friday, May 20, 2016 2:06 PM
> To: 'Scott Wood'; Arnd Bergmann; linux-arm-kernel at lists.infradead.org
> Cc: linuxppc-dev at lists.ozlabs.org; Mark Rutland;
> devicetree at vger.kernel.org; ulf.hansson at linaro.org; Russell King; Bhupesh
> Sharma; netdev at vger.kernel.org; Joerg Roedel; Kumar Gala; linux-
> mmc at vger.kernel.org; linux-kernel at vger.kernel.org; Yang-Leo Li;
> iommu at lists.linux-foundation.org; Rob Herring; linux-i2c at vger.kernel.org;
> Claudiu Manoil; Santosh Shilimkar; Xiaobo Xie; linux-clk at vger.kernel.org;
> Qiang Zhao
> Subject: RE: [v10, 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-
> R1.0-R2.0
> 
> Hi Arnd,
> 
> Any comments?
> Please reply when you see the email since we want this eSDHC issue to be
> fixed soon.
> 
> All the patches are Freescale-specific and is to fix the eSDHC driver.
> Could we let them merged first if you were talking about a new way of
> abstracting getting SoC version.
> 
> 
> Thanks :)
> 
> 
> Best regards,
> Yangbo Lu
> 


From shawn.lin at rock-chips.com  Wed May 25 21:07:25 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Thu, 26 May 2016 12:07:25 +0800
Subject: [PATCH] mmc: dw_mmc: Consider HLE errors to be data and command
 errors
In-Reply-To: <5746748B.7080305@samsung.com>
References: <1426002490-2014-1-git-send-email-dianders@chromium.org>
 <5502CA4E.9060401@samsung.com>
 <CAD=FV=VX3ix-j4y95W1q8b-aVuVEN+4xsd8WLx2xcE7KPNJwRw@mail.gmail.com>
 <5506707D.40708@samsung.com> <55189F04.8000404@samsung.com>
 <CAD=FV=WFAZqAsXOqunt0fxw87M-FruwUrxuzW0MJsG6UvfSjzA@mail.gmail.com>
 <CAD=FV=UJGcwa_biSCGhD=kS-T+fppCniBFfOHb5ohnwSwSwMMA@mail.gmail.com>
 <573BCC8D.5090606@kernel-upstream.org>
 <CAD=FV=VneQR3wurjezBkRhtQiH+q-FfhDN8=Ym=XqtZpVmsdUw@mail.gmail.com>
 <573C3283.1040606@rock-chips.com>
 <CAD=FV=UoT2GRYWJWXEn_ccvKGgC+PzQM_BCtLHAa7jxzbaQ9SA@mail.gmail.com>
 <10b3dc0e-aebf-664b-b36b-c54692cd9983@rock-chips.com>
 <573DBAA5.2070706@samsung.com>
 <CGME20160526022412epcas1p1408431e9596aaf84e8b58510ee81d4c4@epcas1p1.samsung.com>
 <4d8f3992-a1d3-6010-4964-8ca13cddc1c5@rock-chips.com>
 <5746748B.7080305@samsung.com>
Message-ID: <10d2520b-0919-0a5b-f5b6-23b133e63dbb@rock-chips.com>

? 2016/5/26 11:59, Jaehoon Chung ??:
> On 05/26/2016 11:23 AM, Shawn Lin wrote:
>> Hi Jaehoon,
>>
>> On 2016/5/19 21:07, Jaehoon Chung wrote:
>>> On 05/19/2016 08:31 PM, Shawn Lin wrote:
>>>> Hi,
>>>>
>>>> On 2016/5/19 1:37, Doug Anderson wrote:
>>>>> Hi,
>>>>>
>>>>> On Wed, May 18, 2016 at 2:14 AM, Shawn Lin <shawn.lin at rock-chips.com> wrote:
>>>>>> Hi
>>>>>>
>>>>>>
>>>>>> On 2016-5-18 12:12, Doug Anderson wrote:
>>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> On Tue, May 17, 2016 at 6:59 PM, Shawn Lin
>>>>>>> <shawn.lin at kernel-upstream.org> wrote:
>>>>>>>>
>>>>>>>> Could you try this patch to see if you can still find HLE?
>>>>>>>>
>>>>>>>> @@ -2356,12 +2356,22 @@ static void dw_mci_cmd_interrupt(struct dw_mci
>>>>>>>> *host, u32 status)
>>>>>>>>   static void dw_mci_handle_cd(struct dw_mci *host)
>>>>>>>>   {
>>>>>>>>          int i;
>>>>>>>> +       int present;
>>>>>>>>
>>>>>>>>          for (i = 0; i < host->num_slots; i++) {
>>>>>>>>                  struct dw_mci_slot *slot = host->slot[i];
>>>>>>>>
>>>>>>>>                  if (!slot)
>>>>>>>>                          continue;
>>>>>>>>
>>>>>>>> +               present = !(mci_readl(slot->host, CDETECT) & (1 <<
>>>>>>>> slot->id));
>>>>>>>> +               if (present)
>>>>>>>> +                       set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>>>>>>>> +               else
>>>>>>>> +                       clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>>>>>>>
>>>>>>>
>>>>>>> No, because we don't use the builtin card detect on veyron.  ;)
>>>>>>>
>>>>>>> We use GPIO card detect because we didn't like the way JTAG and SD
>>>>>>> interacted.  Also on rk3288 the builtin card detect line had the wrong
>>>>>>> voltage domain (you couldn't detect a card when the IO lines were
>>>>>>> powered off).  The builtin card detect line is always driven low on
>>>>>>> veyron.
>>>>>>
>>>>>>
>>>>>> Okay, I see.
>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> I'm nearly certain that the root cause of my HLE errors is actually
>>>>>>> related to the same problem addressed by the commit 7c5209c315ea
>>>>>>> ("mmc: core: Increase delay for voltage to stabilize from 3.3V to
>>>>>>> 1.8V").  I think that on minnie we're still on the hairy edge and
>>>>>>> sometimes the line doesn't transition fast enough.
>>>>>>
>>>>>>
>>>>>> Things are not so simple from your details.
>>>>>>
>>>>>> I was not enabling SD3.0 support, then I also found HLE sometimes.
>>>>>> So it seems commit 7c5209c315ea does not contibute to this phenomenon.
>>>>>
>>>>> Just to clarify, in my case commit 7c5209c315ea didn't make the
>>>>> problem worse, but made it better.  Just not better enough.  ;)
>>>>>
>>>>>
>>>>>> The scenario looks like:
>>>>>> remove sd-card -> mmc_sd_detect -> send status(CMD13) ->power_off ->
>>>>>> set_ios -> setup_bus -> disabled clk , then HLE irq storm coming
>>>>>>
>>>>>> From the code of dw_mci_prepare_command:
>>>>>> SDMMC_CMD_PRV_DAT_WAIT will not be used for CMD13, so we don't
>>>>>> wait_busy here, then cmd code is loding into queue of dw_mmc but
>>>>>> still failing send out because it's in busy?
>>>>>>
>>>>>> With my patch, things go well:
>>>>>> remove sd-card -> clear bit of DW_MMC_CARD_PRESENT  -> send
>>>>>> status(CMD13) return directly -> power_off -> set_ios -> setup_bus ->
>>>>>> disable clk
>>>>>>
>>>>>> So why should we allow inquiry of card status if we sure the card is
>>>>>> removed? I mean no any further cmds should be delivered.
>>>>>
>>>>> Quite honestly just dealing with the HLE error (my patch or
>>>>> equivalent) might be a sane solution for the problem you describe.
>>>>
>>>> Yes, your patch looks good to me, so it should be merged firstly. :)
>>>> Then let's push it a bit further more that when HLEs are coming,
>>>> somethings must be wrong(currently I don't see a obvious clue from
>>>> the code itself although, I'm prone to think it belongs to the
>>>> software issue).
>>>
>>> We don't know what's main cause for HLE..But i also think it's relevant to SW issue.
>>> But we need to consider all possibilities..
>>>
>>>>
>>>>
>>>>>
>>>>> dw_mmc needs to be able to work with an external card detect GPIO.
>>>>> It's been part of the dw_mmc driver for a long time and is (in fact)
>>>>> in use upstream at least by rk3288-veyron.  Any solution that only
>>>>> works for internal card detect is not enough.  Just handling the HLE
>>>>> error to deal with the interrupt storm and then letting Linux remove
>>>>> the card (because of the card detect interrupt) seems totally OK to
>>>>> me.
>>>>>
>>>>
>>>> Sure, some of rockchip Socs use gpio for CD because they don't
>>>> have a internal CD, such as RK3036, right?
>>>>
>>>>> Note: I'd be very curious if your problems get better if you disable
>>>>
>>>> Not at all.
>>>>
>>>>> the "grf_force_jtag" bit in the GRF.  If you're using the builtin card
>>>>> detect and you use the boot default of "grf_force_jtag" then your pins
>>>>> will be unmuxed behind your back when the card is ejected.  This could
>>>>> be causing the dw_mmc controller to get confused.
>>>>
>>>> Right, grf_force_jtag is also not a friend of mine. :)
>>>> So I had disabled this function before I was debugging it.
>>>>
>>>>>
>>>>>
>>>>>> And another question: should we wait busy for cmd13?
>>>>>
>>>>> I don't think so.  As I understand it CMD13 uses only the CMD line for
>>>>> communication and it should be appropriate to send this when the bus
>>>>> is "busy" (which means that the DATA lines are low).
>>>>
>>>> Ahh... take back my question.. I was just considering a wired situation
>>>> that pins are unmuxed on the background(cmd line as well) when cmd13 is
>>>> delivering....
>>>>
>>>>
>>>>>
>>>>> Also: it seems odd that the HLE IRQ storm didn't come right after the
>>>>> CMD 13 in your description above.  Are you sure it was the CMD 13 that
>>>>> caused the HLEs, or could it has been something else?
>>>>
>>>> Actually no. Any cmds be issued can trigger HLEs, I think, after sd card is removed When I hacked mmc_sd_detecd to send other cmds intead
>>>> of cmd13.
>>>>
>>>> From dw_mmc databook v270a(7.2.3 Clock Programming) we can see:
>>>> The DWC_mobile_storage loads each of these registers only when the
>>>> start_cmd bit and the Update_clk_regs_only bit in the CMD register are
>>>> set. When a command is successfully loaded, the DWC_mobile_storage
>>>> clears this bit, unless the DWC_mobile_storage already has another
>>>> command in the queue, at which point it gives an HLE (Hardware Locked
>>>> Error); for details on HLEs, refer to ?Error Handling? on page 233.
>>>> Software should look for the start_cmd and the Update_clk_regs_only
>>>> bits, and should also set the wait_prvdata_complete bit to ensure that
>>>> clock parameters do not change during data transfer.
>>>>
>>>> Maybe the cmd is trying to load(or somethings wrong with the
>>>> controller?) when we disable the clk? That may explain my observation
>>>> that HLEs came after disabling clk.
>>>
>>> I agreed.
>>>
>>> To Disable clock, it sends cmd with update_clk_regs_only and wait_prvdata_complete bit.
>>> I think it's problem..(waiting for prvdata..)
>>>
>>> If there are ongoing some data(read/write), then before disabling clock, waiting for completing previous data.
>>> (But card was already removed, and it couldn't do anything.)
>>> It's difficult to analyze the HLE..So After applying first, then we can solve this problem, step by step.
>>>
>>
>> I saw you send a PR for v4.7-fix to Ulf which didn't include this one.
>> Do you plan to add it into 4.8 materials? :)
>
> Yes, I think good that this is prepared for next. (Will apply on this weekend.)
> Do you have other opinion? :)

No, thanks. I just wanna make sure this one will be merged. :)

>
> If you have other opinion, i will reflect yours. Thanks!
>
> Best Regards,
> Jaehoon Chung
>
>>
>>> Best Regards,
>>> Jaehoon Chung
>>>
>>>>
>>>>
>>>>>
>>>>>
>>>>> -Doug
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>
>>>
>>>
>>>
>>
>>
>
>
>
>


-- 
Best Regards
Shawn Lin



From bjorn.andersson at linaro.org  Wed May 25 21:48:10 2016
From: bjorn.andersson at linaro.org (Bjorn Andersson)
Date: Wed, 25 May 2016 21:48:10 -0700
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
In-Reply-To: <e0173486-896e-4897-702a-ccd1c1f6c609@codeaurora.org>
References: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
 <20160523172527.GK4976@leverpostej>
 <f49d58ed-38b4-6284-11c2-8708d8443b14@codeaurora.org>
 <20160524112326.GC25374@leverpostej>
 <e0173486-896e-4897-702a-ccd1c1f6c609@codeaurora.org>
Message-ID: <20160526044810.GW1256@tuxbot>

On Tue 24 May 12:54 PDT 2016, Neil Leeder wrote:

> 
> 
> On 5/24/2016 07:23 AM, Mark Rutland wrote:
> > On Mon, May 23, 2016 at 02:22:59PM -0400, Neil Leeder wrote:
> >>
> >> On 5/23/2016 01:25 PM, Mark Rutland wrote:
> >>> On Fri, May 20, 2016 at 03:13:07PM -0400, Neil Leeder wrote:
> 
> >>>> Signed-off-by: Neil Leeder <nleeder at codeaurora.org>
> >>>> ---
> >>>>  drivers/soc/qcom/Kconfig              |  9 +++++
> >>>>  drivers/soc/qcom/Makefile             |  1 +
> >>>>  drivers/soc/qcom/l2-accessors.c       | 66 +++++++++++++++++++++++++++++++++++
> >>>>  include/linux/soc/qcom/l2-accessors.h | 27 ++++++++++++++
> >>>>  4 files changed, 103 insertions(+)
> >>>>  create mode 100644 drivers/soc/qcom/l2-accessors.c
> >>>>  create mode 100644 include/linux/soc/qcom/l2-accessors.h
> >>>
> >>> These are awfully generic file names (and function names). Which SoCs
> >>> does this apply to?
> >>>
> >>> It would be good to give these more specific names.
> >>
> >> It's under soc/qcom, and dependent on ARCH_QCOM and (in v2) also on ARM64. It applies to all QCOM ARM64 SoCs.
> > 
> > Per Christopher's comment, it sounds like this applies to QDF24xx.
> > 
> > Given that the code uses IMPLEMENTATION DEFINED system registers, I
> > presume that this does not apply to MSM8916 which uses Cortex-A53, for
> > example (though perhaps it does, and I am mistaken).
> > 
> >> Given that it can only be used in a QCOM driver, and the include path has qcom in it, I'd
> >> prefer not to add redundancy by adding another qcom in there.
> > 
> > I'm not asking for another "qcom", but simply the SoC variant or family
> > (e.g. "qdf24xx" would be fine).
> > 
> 
> It applies to all ARMv8 SoCs with QCOM processors in them. So QDF24xx
> and mobile 820, but not SoCs with ARM processors in them such as
> MSM8916. So neither msm_ nor qdf_ are accurate prefixes.

What's the code name for the SoC in QDF24xx? The 820 is Kryo, is it the
same core in QDF24xx or does that have some other name.

We should try to pick something adding value, not adding another generic
thing.

> As Timur pointed out, the majority of source files in drivers/soc/qcom
> don't have any prefix, which is a reason why I didn't include one.
> 

There's no reason to add a generic "qcom" to the qcom folder, if
anything we should drop the "qcom" prefix of the only one in there.

Regards,
Bjorn


From t-kristo at ti.com  Wed May 25 22:47:57 2016
From: t-kristo at ti.com (Tero Kristo)
Date: Thu, 26 May 2016 08:47:57 +0300
Subject: [PATCH 0/2] arm: dra7: Add i2c6 instance hwmod and dt entries
In-Reply-To: <5745CE4E.3020903@ti.com>
References: <20160525125341.10044-1-rk@ti.com> <5745CE4E.3020903@ti.com>
Message-ID: <57468E0D.2060504@ti.com>

On 25/05/16 19:09, Nishanth Menon wrote:
> On 05/25/2016 07:53 AM, Ravikumar Kattekola wrote:
>> DRA72x devices have a sixth i2c ocntroller instance.
>> Following patches add the required hwmod structure and
>> device tree nodes.
>>
>> Reference doc: DRA72x TRM [ SPRUHP2Q ]
>>
>> Tested on :
>> DRA72x Rev B EVM
>>
>> Ravikumar Kattekola (2):
>>    arm: dra7: Add hwmod entry for i2c6
>>    dts: dra7: Add device tree node for i2c6
>>
>>   arch/arm/boot/dts/dra7.dtsi               | 11 +++++++++++
>>   arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 23 +++++++++++++++++++++++
>>   2 files changed, 34 insertions(+)
>>
> NAK. reasoning:
> a) i2c6 is a custom IP integration with completely non-standard
> dependencies with cross device dependencies for pretty much a specific
> usecase -> usage is pretty much limited for generic support - the
> decision is NOT to support this instance in Linux kernel - internal
> discussion forwarded to developer.
> b) the patches themselves are wrong -> it applies to DRA72x not
> generic DRA7x platform
> c) patches themselves are in the wrong format (wrong subject line etc).
> d) patches don't handle the SoC internal device dependencies either ->
> in short will not function in a generic solution for all variations of
> platforms.
>

Yes please drop this, attempting to support it in upstream is just going 
to cause unnecessary pain.

-Tero


From sricharan at codeaurora.org  Wed May 25 22:56:36 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Thu, 26 May 2016 11:26:36 +0530
Subject: [RFC 8/9] drivers: of: call iommu_bus_add_dev after
 iommu_configure_ops
In-Reply-To: <57447A60.4060805@arm.com>
References: <1461599894-1969-1-git-send-email-sricharan@codeaurora.org>
 <1461599894-1969-9-git-send-email-sricharan@codeaurora.org>
 <57447A60.4060805@arm.com>
Message-ID: <000001d1b713$61234ca0$2369e5e0$@codeaurora.org>

Hi Robin,

>On 25/04/16 16:58, Sricharan R wrote:
>> Now that the device's iommu ops are configured at probe time,
>> the device has to be added to the iommu late.
>>
>> Signed-off-by: Sricharan R <sricharan at codeaurora.org>
>> ---
>>   drivers/of/device.c | 4 ++++
>>   1 file changed, 4 insertions(+)
>>
>> diff --git a/drivers/of/device.c b/drivers/of/device.c
>> index 57a5f2d..722115c 100644
>> --- a/drivers/of/device.c
>> +++ b/drivers/of/device.c
>> @@ -6,6 +6,7 @@
>>   #include <linux/of_iommu.h>
>>   #include <linux/dma-mapping.h>
>>   #include <linux/init.h>
>> +#include <linux/iommu.h>
>>   #include <linux/module.h>
>>   #include <linux/mod_devicetable.h>
>>   #include <linux/slab.h>
>> @@ -154,6 +155,9 @@ int of_dma_configure_ops(struct device *dev, struct device_node *np)
>>   	dev_dbg(dev, "device is%sbehind an iommu\n",
>>   		iommu ? " " : " not ");
>>
>> +	if (iommu)
>> +		iommu_bus_add_dev(dev);
>
>This (in conjunction with the previous patch) seems unnecessarily
>convoluted - if of_iommu_configure() has found some iommu_ops for a
>device, why not just call .add_device() directly there and then? There
>are already systems that could warrant having two different IOMMU
>drivers active simultaneously (but thankfully don't _need_ to), so
>trying to escape from per-bus IOMMU ops makes more sense than
>entrenching the horrible notion of "the" IOMMU on "the" platform bus any
>further.
>
  Ok, agree on this. This will remove the addition of that api in previous
  patch as well. Will change this.

Regards,
 Sricharan



From kishon at ti.com  Wed May 25 22:59:14 2016
From: kishon at ti.com (Kishon Vijay Abraham I)
Date: Thu, 26 May 2016 11:29:14 +0530
Subject: [PATCH] phy: exynos-mipi-video: avoid uninitialized variable use
In-Reply-To: <14219690.YQPrXjp7cP@wuerfel>
References: <1462971012-562097-1-git-send-email-arnd@arndb.de>
 <20160511185155.GB8265@kozik-lap> <14219690.YQPrXjp7cP@wuerfel>
Message-ID: <574690B2.9010204@ti.com>

Hi Arnd,

On Thursday 26 May 2016 12:24 AM, Arnd Bergmann wrote:
> On Wednesday, May 11, 2016 8:51:55 PM CEST Krzysztof Kozlowski wrote:
>> On Wed, May 11, 2016 at 02:49:53PM +0200, Arnd Bergmann wrote:
>>> A rework of the exynos-mipi-video driver caused a warning
>>> about the new __set_phy_state function potentially accessing
>>> a variable before its initialization:
>>>
>>> drivers/phy/phy-exynos-mipi-video.c: In function '__set_phy_state':
>>> drivers/phy/phy-exynos-mipi-video.c:238:13: error: 'val' may be used uninitialized in this function [-Werror=maybe-uninitialized]
>>>   return val & data->resetn_val;
>>>          ~~~~^~~~~~~~~~~~~~~~~~
>>> drivers/phy/phy-exynos-mipi-video.c:235:6: note: 'val' was declared here
>>>   u32 val;
>>>
>>> The failure scenario here is the offset passed into a the
>>> stub regmap_read() function that does not modify its output,
>>> however regmap_read() can also fail for other reasons, so
>>> adding error handling (in this case, returning zero from
>>> is_running) seems the best solution.
>>>
>>> Note that this warning showed up with the ARM s5pv210_defconfig,
>>> indicating that we most likely want to either enable CONFIG_REGMAP
>>> in that defconfig as well, or disable the phy-exynos-mipi-video
>>> driver.
>>>
>>> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
>>> Fixes: 97a3042f7616 ("phy: exynos-mipi-video: Rewrite handling of phy registers")
>>> ---
>>>  drivers/phy/phy-exynos-mipi-video.c | 6 +++++-
>>>  1 file changed, 5 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
>>> index cc093ebfda94..8b851f718123 100644
>>> --- a/drivers/phy/phy-exynos-mipi-video.c
>>> +++ b/drivers/phy/phy-exynos-mipi-video.c
>>> @@ -233,8 +233,12 @@ static inline int __is_running(const struct exynos_mipi_phy_desc *data,
>>>                       struct exynos_mipi_video_phy *state)
>>>  {
>>>       u32 val;
>>
>> Other way would be to initialize val=0 since there is no real error code
>> returned. Anyway:
>>
>> Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> 
> 
> This hasn't made it into linux-next yet, any chance we'll see it in -rc1 or -rc2?

Not in -rc1. Mostly it'll go in -rc2. Generally I start queuing patches after
-rc1 is tagged.

Thanks
Kishon



From po.liu at nxp.com  Wed May 25 22:59:09 2016
From: po.liu at nxp.com (Po Liu)
Date: Thu, 26 May 2016 13:59:09 +0800
Subject: [PATCH 1/2] freescale/dts: add pcie aer interrupt-name property in
 the dts
Message-ID: <1464242349-15323-1-git-send-email-po.liu@nxp.com>

Freescale some platforms aer interrupt was not MSI/MSI-X/INTx
but using interrupt line independently. This patch add a "aer"
interrupt-names for aer interrupt.

Signed-off-by: Po Liu <po.liu at nxp.com>
---
 .../devicetree/bindings/pci/layerscape-pci.txt         |  2 +-
 arch/arm/boot/dts/ls1021a.dtsi                         |  6 ++++--
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi         | 18 +++++++++---------
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi         | 16 ++++++++--------
 4 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
index ef683b2..858b407 100644
--- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
+++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
@@ -19,7 +19,7 @@ Required properties:
 - interrupts: A list of interrupt outputs of the controller. Must contain an
   entry for each entry in the interrupt-names property.
 - interrupt-names: Must include the following entries:
-  "intr": The interrupt that is asserted for controller interrupts
+  "aer" : The interrupt that is asserted for aer interrupts
 - fsl,pcie-scfg: Must include two entries.
   The first entry must be a link to the SCFG device node
   The second entry must be '0' or '1' based on physical PCIe controller index.
diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index 5ae8e92..b638697 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -633,7 +633,8 @@
 			reg = <0x00 0x03400000 0x0 0x00010000   /* controller registers */
 			       0x40 0x00000000 0x0 0x00002000>; /* configuration space */
 			reg-names = "regs", "config";
-			interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+			interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>; /* aer interrupt */
+			interrupt-names = "aer";
 			fsl,pcie-scfg = <&scfg 0>;
 			#address-cells = <3>;
 			#size-cells = <2>;
@@ -656,7 +657,8 @@
 			reg = <0x00 0x03500000 0x0 0x00010000   /* controller registers */
 			       0x48 0x00000000 0x0 0x00002000>; /* configuration space */
 			reg-names = "regs", "config";
-			interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; /* aer interrupt */
+			interrupt-names = "aer";
 			fsl,pcie-scfg = <&scfg 1>;
 			#address-cells = <3>;
 			#size-cells = <2>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index de0323b..4beb760 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -473,9 +473,9 @@
 			reg = <0x00 0x03400000 0x0 0x00100000   /* controller registers */
 			       0x40 0x00000000 0x0 0x00002000>; /* configuration space */
 			reg-names = "regs", "config";
-			interrupts = <0 118 0x4>, /* controller interrupt */
-				     <0 117 0x4>; /* PME interrupt */
-			interrupt-names = "intr", "pme";
+			interrupts = <0 117 0x4>, /* PME interrupt */
+					 <0 118 0x4>; /* aer interrupt */
+			interrupt-names = "pme", "aer";
 			#address-cells = <3>;
 			#size-cells = <2>;
 			device_type = "pci";
@@ -497,9 +497,9 @@
 			reg = <0x00 0x03500000 0x0 0x00100000   /* controller registers */
 			       0x48 0x00000000 0x0 0x00002000>; /* configuration space */
 			reg-names = "regs", "config";
-			interrupts = <0 128 0x4>,
-				     <0 127 0x4>;
-			interrupt-names = "intr", "pme";
+			interrupts = <0 127 0x4>,
+					 <0 128 0x4>;
+			interrupt-names = "pme", "aer";
 			#address-cells = <3>;
 			#size-cells = <2>;
 			device_type = "pci";
@@ -521,9 +521,9 @@
 			reg = <0x00 0x03600000 0x0 0x00100000   /* controller registers */
 			       0x50 0x00000000 0x0 0x00002000>; /* configuration space */
 			reg-names = "regs", "config";
-			interrupts = <0 162 0x4>,
-				     <0 161 0x4>;
-			interrupt-names = "intr", "pme";
+			interrupts = <0 161 0x4>,
+					 <0 162 0x4>;
+			interrupt-names = "pme", "aer";
 			#address-cells = <3>;
 			#size-cells = <2>;
 			device_type = "pci";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index 3187c82..6edf24b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -559,8 +559,8 @@
 			reg = <0x00 0x03400000 0x0 0x00100000   /* controller registers */
 			       0x10 0x00000000 0x0 0x00002000>; /* configuration space */
 			reg-names = "regs", "config";
-			interrupts = <0 108 0x4>; /* Level high type */
-			interrupt-names = "intr";
+			interrupts = <0 108 0x4>; /* aer interrupt */
+			interrupt-names = "aer";
 			#address-cells = <3>;
 			#size-cells = <2>;
 			device_type = "pci";
@@ -583,8 +583,8 @@
 			reg = <0x00 0x03500000 0x0 0x00100000   /* controller registers */
 			       0x12 0x00000000 0x0 0x00002000>; /* configuration space */
 			reg-names = "regs", "config";
-			interrupts = <0 113 0x4>; /* Level high type */
-			interrupt-names = "intr";
+			interrupts = <0 113 0x4>; /* aer interrupt */
+			interrupt-names = "aer";
 			#address-cells = <3>;
 			#size-cells = <2>;
 			device_type = "pci";
@@ -607,8 +607,8 @@
 			reg = <0x00 0x03600000 0x0 0x00100000   /* controller registers */
 			       0x14 0x00000000 0x0 0x00002000>; /* configuration space */
 			reg-names = "regs", "config";
-			interrupts = <0 118 0x4>; /* Level high type */
-			interrupt-names = "intr";
+			interrupts = <0 118 0x4>; /* aer interrupt */
+			interrupt-names = "aer";
 			#address-cells = <3>;
 			#size-cells = <2>;
 			device_type = "pci";
@@ -631,8 +631,8 @@
 			reg = <0x00 0x03700000 0x0 0x00100000   /* controller registers */
 			       0x16 0x00000000 0x0 0x00002000>; /* configuration space */
 			reg-names = "regs", "config";
-			interrupts = <0 123 0x4>; /* Level high type */
-			interrupt-names = "intr";
+			interrupts = <0 123 0x4>; /* aer interrupt */
+			interrupt-names = "aer";
 			#address-cells = <3>;
 			#size-cells = <2>;
 			device_type = "pci";
-- 
2.1.0.27.g96db324



From po.liu at nxp.com  Wed May 25 23:00:06 2016
From: po.liu at nxp.com (Po Liu)
Date: Thu, 26 May 2016 14:00:06 +0800
Subject: [PATCH 2/2] aer: add support aer interrupt with none MSI/MSI-X/INTx
 mode
Message-ID: <1464242406-20203-1-git-send-email-po.liu@nxp.com>

On some platforms, root port doesn't support MSI/MSI-X/INTx in RC mode.
When chip support the aer interrupt with none MSI/MSI-X/INTx mode,
maybe there is interrupt line for aer pme etc. Search the interrupt
number in the fdt file.

Signed-off-by: Po Liu <po.liu at nxp.com>
---
 drivers/pci/pcie/portdrv_core.c | 31 ++++++++++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 32d4d0a..64833e5 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/pcieport_if.h>
 #include <linux/aer.h>
+#include <linux/of_irq.h>
 
 #include "../pci.h"
 #include "portdrv.h"
@@ -199,6 +200,28 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
 static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
 {
 	int i, irq = -1;
+	int ret;
+	struct device_node *np = NULL;
+
+	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
+		irqs[i] = 0;
+
+	if (dev->bus->dev.of_node)
+		np = dev->bus->dev.of_node;
+
+	/* If root port doesn't support MSI/MSI-X/INTx in RC mode,
+	 * request irq for aer
+	 */
+	if (IS_ENABLED(CONFIG_OF_IRQ) && np &&
+			(mask & PCIE_PORT_SERVICE_PME)) {
+		ret = of_irq_get_byname(np, "aer");
+		if (ret > 0) {
+			irqs[PCIE_PORT_SERVICE_AER_SHIFT] = ret;
+			if (dev->irq)
+				irq = dev->irq;
+			goto no_msi;
+		}
+	}
 
 	/*
 	 * If MSI cannot be used for PCIe PME or hotplug, we have to use
@@ -224,11 +247,13 @@ static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
 		irq = dev->irq;
 
  no_msi:
-	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
-		irqs[i] = irq;
+	for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
+		if (!irqs[i])
+			irqs[i] = irq;
+	}
 	irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1;
 
-	if (irq < 0)
+	if (irq < 0 && irqs[PCIE_PORT_SERVICE_AER_SHIFT] < 0)
 		return -ENODEV;
 	return 0;
 }
-- 
2.1.0.27.g96db324



From boris.brezillon at free-electrons.com  Wed May 25 23:36:15 2016
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Thu, 26 May 2016 08:36:15 +0200
Subject: [PATCH 1/2] Revert "mtd: atmel_nand: Support variable RB_EDGE
 interrupts"
In-Reply-To: <20160526031654.GA107505@google.com>
References: <1462776680-5284-1-git-send-email-wenyou.yang@atmel.com>
 <1462776680-5284-2-git-send-email-wenyou.yang@atmel.com>
 <20160526031654.GA107505@google.com>
Message-ID: <20160526083615.6960686d@bbrezillon>

On Wed, 25 May 2016 20:16:54 -0700
Brian Norris <computersforpeace at gmail.com> wrote:

> Hi,
> 
> On Mon, May 09, 2016 at 02:51:18PM +0800, Wenyou Yang wrote:
> > This reverts commit 5ddc7bd43ccc ("mtd: atmel_nand: Support variable
> > RB_EDGE interrupts")
> > 
> > Because for current SoCs, the RB_EDGE3(i.e. bit 27) of HSMC_SR
> > register does not exist, the RB_EDGE0 (i.e. bit 24) is the ready/busy
> > line edge status bit. It is a datasheet bug.
> > 
> > Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> > ---
> > 
> >  .../devicetree/bindings/mtd/atmel-nand.txt         |  2 +-
> >  drivers/mtd/nand/atmel_nand.c                      | 35 +++++-----------------
> >  drivers/mtd/nand/atmel_nand_nfc.h                  |  3 +-
> >  3 files changed, 10 insertions(+), 30 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> > index d53aba9..3e7ee99 100644
> > --- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> > +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
> > @@ -39,7 +39,7 @@ Optional properties:
> >  
> >  Nand Flash Controller(NFC) is an optional sub-node
> >  Required properties:
> > -- compatible : "atmel,sama5d3-nfc" or "atmel,sama5d4-nfc".
> > +- compatible : "atmel,sama5d3-nfc".
> >  - reg : should specify the address and size used for NFC command registers,
> >          NFC registers and NFC SRAM. NFC SRAM address and size can be absent
> >          if don't want to use it.
> > diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
> > index efc8ea2..68b9160 100644
> > --- a/drivers/mtd/nand/atmel_nand.c
> > +++ b/drivers/mtd/nand/atmel_nand.c  
> [...]
> >  static const struct of_device_id atmel_nand_nfc_match[] = {
> > -	{ .compatible = "atmel,sama5d3-nfc", .data = &sama5d3_nfc_caps },
> > -	{ .compatible = "atmel,sama5d4-nfc", .data = &sama5d4_nfc_caps },
> > +	{ .compatible = "atmel,sama5d3-nfc" },  
> 
> Hmm, wait. Didn't Rob and Alexandre suggest that we should *not* drop
> the compatible property? We could have easily supported both here, and
> just not listed any different capabilities. But I see that Nicholas took
> the patch anyway, so I guess it's not a big deal...

Yes, actually the compatible change was introduced and fixed in the
same release, so I don't think the stable ABI argument stands here.


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


From geert at linux-m68k.org  Thu May 26 00:03:33 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Thu, 26 May 2016 09:03:33 +0200
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <edee7345-280a-0d7c-7e5a-798215fbd2b9@de.bosch.com>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
 <20160525004825.GC7292@verge.net.au>
 <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>
 <edee7345-280a-0d7c-7e5a-798215fbd2b9@de.bosch.com>
Message-ID: <CAMuHMdXnN-GTN4crXeWRvtWT4E2kYFvMdPPcH8z+gJb-B4PbYA@mail.gmail.com>

Hi Dirk,

On Wed, May 25, 2016 at 9:32 AM, Dirk Behme <dirk.behme at de.bosch.com> wrote:
> P.S.: This also results in the question why we need similar
> r8a7795-cpg-mssr.h and r8a7796-cpg-mssr.h with just different "numbers" for
> the same clocks. Can't we use the same numbers on all SoCs, with just having
> wholes in the list where the clocks don't exist on a SoC? I haven't looked

The CPG and MSSR block are the IP blocks that differ most among SoCs of the
same family. Some clocks are present on H3 only, others on M3-W only.

Having a shared driver core, but different defines, is a compromise between
reusability and avoiding mistakes in DTSes (e.g. pointing to a nonexisting
clock due to copy and paste from another SoC).

> into the manual if these numbers are given by the hardware, though.

The actual numbers don't map to numbers in the datasheet, just to an unordered
list in a table. The list of number is considered part of the DT bindings, and
thus append-only (to be considered in case the datasheet is updated).

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 shc_work at mail.ru  Thu May 26 00:13:30 2016
From: shc_work at mail.ru (=?UTF-8?B?QWxleGFuZGVyIFNoaXlhbg==?=)
Date: Thu, 26 May 2016 10:13:30 +0300
Subject: =?UTF-8?B?UmU6IE1vZGVybiBrZXJuZWwgb24gYSBDaHVtYnk=?=
In-Reply-To: <4758440.JnRBmYVBjM@wuerfel>
References: <CAMW5UfYH6UiaB1ddRT0KBP1thyyebnCw2h4VigYQQ55v4MYqdA@mail.gmail.com>
 <4758440.JnRBmYVBjM@wuerfel>
Message-ID: <1464246810.783789508@f42.i.mail.ru>

> ???????, 26 ??? 2016, 0:09 +03:00 ?? Arnd Bergmann <arnd at arndb.de>:
> 
> On Wednesday, May 25, 2016 4:59:31 PM CEST Josh Coombs wrote:
> > I've likely bitten off way more than I can chew but I'd like to see if
> > this is possible:  I have a i.MX21 powered 'original' Chumby happily
> > running on a modified 2.6.16 kernel, ideally I'd like to do the
> > legwork to get it running on a current, mainline kernel.  Looking at
> > 4.6 I see a single i.MX21 device supported by a board file, the
> > mx21ads.  Flipping through the list archives I see discussions of
> > i.MX21 being moved to device tree operation but I can't see any signs
> > of any such devices actually being supported that way.
> > 
> > Should I try to bash up support based on the mx21ads or is there a
> > device tree template I can start from?
> 
> I think your best bet is to start from the imx27 DT support.
> As I understand, it's closely related to imx21, though it's possible
> that you have to add some other drivers.
> 
> Alexander Shiyan (added to Cc here) has written DT support for the imx21
> clk controller, he may have other patches that never made it upstream,
> or have additional information.

Hello.

i.MX21 platform is fully ready for use with DT. To start using DT You need to write
imx21-dt machine startup (which is almost identical to imx27-dt) and basic DT
templates imx21-pinfunc.h & imx21.dtsi and so on. Then you can write DT-support
for your board.
I have no any additional patches for i.MX21.

Thanks.
---


From dirk.behme at de.bosch.com  Thu May 26 00:14:16 2016
From: dirk.behme at de.bosch.com (Dirk Behme)
Date: Thu, 26 May 2016 09:14:16 +0200
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <20160526022833.GE18393@verge.net.au>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
 <20160525004825.GC7292@verge.net.au>
 <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>
 <20160526022833.GE18393@verge.net.au>
Message-ID: <59e6225a-6dfa-8bde-dd2e-3428d6fedfe2@de.bosch.com>

Hi Simon,

On 26.05.2016 04:28, Simon Horman wrote:
> Hi Dirk,
>
> On Wed, May 25, 2016 at 07:10:26AM +0200, Dirk Behme wrote:
>> Hi Simon,
>>
>> On 25.05.2016 02:48, Simon Horman wrote:
>>> Hi Dirk,
>>>
>>> On Tue, May 24, 2016 at 07:30:17AM +0200, Dirk Behme wrote:
>>>> Hi Simon,
>>>
>>> [...]
>>>
>>>> With Renesas R-Car3 we will get a whole family of SoCs. I.e. different
>>>> computing power (e.g. different number of Cores) with more or less similar
>>>> peripherals.
>>>>
>>>> I would think that we want to reflect this in the device tree, too.
>>>> Therefore I think what we want is a hierarchy of device trees. Similar
>>>> what's done with other SoC families (compare e.g. i.MX6).
>>>>
>>>> E.g. we want an initial rcar3.dtsi, which contains all common parts of all
>>>> R-Car3 SoCs. E.g. one CA57 core, the SCIF where its common etc.
>>>>
>>>> Then you will have the r8a779x.dtsi which includes the rcar3.dtsi and
>>>> extends it for SoC specific parts. Which then will be included by the board
>>>> device trees, as already done, now.
>>>>
>>>> Or in other words: As soon as you have similar parts in the r8a779x.dtsi's,
>>>> it's time to think about moving the parts one hierarchy level up into the
>>>> rcar3.dtsi. Else you will end up in a maintenance hell once you have to
>>>> change/fix anything.
>>>
>>> Thanks for raising this issue.
>>>
>>> I agree entirely that we should work towards a situation where maintenance
>>> is as easy as it can be. However, due to the per-SoC binding scheme that
>>> we are using for IP related to Renesas SoCs I suspect that very few DT nodes
>>> can be shared between SoCs verbatim.
>>
>>
>> Could you kindly share an example for this? Looking into the H3 and the M3-W
>> manual, it looks to me that ~90% (?) of the peripherals are the same.
>
> The background is that this is a conversation that has been going around
> for years. The basic thinking is that at this point we have documentation
> that indicates that many hardware blocks on the H3 and M3-W are the same.
> But we do not have insight into the internal versioning of the IP blocks
> nor if they are really the same. And furthermore even if they are currently
> the same we don't really know if that will continue to be the case.
>
> Probably it is. Maybe it isn't. The response has been to take a
> conservative approach to DT bindings to give us the flexibility to update
> the driver implementation to reflect any differences that subsequently
> surface. And by providing per-SoC bindings these driver changes can be
> activated on a per-SoC basis without updating DTB files (which may be
> burned into ROMs).


Sorry, but I don't think that these are good arguments for this kind of 
discussion ;)

The discussion has to be based on facts. And not on "maybe" or 
"probably". The fact is that the documentation tells us that the IPs are 
the same. And the documentation tells us where this isn't the case. This 
is what we can reflect in the code and the device trees.

Or the other way around: I don't ask to not have any SoC specific device 
trees (r8a7795.dtsi, r8a7796.dtsi etc). So we *always* have the option 
to move anything to them, once there might be any difference found or 
documented. But maintaining x (x > 5?) quite similar device trees just 
because there *might* be the possibility that one or two device *might* 
be different doesn't sound like a good argument to me.

Or again, an other way: If I understood correctly, you are working 
already since some time on R-Car, e.g. R-Car Gen2. How many examples do 
you have from the Gen2 family where the IP blocks are different that 
they need to be distinguished in the device tree?


>>> Probably some sort of scheme can be cooked up using preprocessor macros.
>>> And probably there are other ways to resolve this problem. But I would
>>> prefer if we worked towards resolving this maintenance problem in parallel
>>> with rather than as a dependency of merging r8a7796 support into mainline.
>>
>>
>> I'd propose to do it correct from the beginning.
>>
>> Doing it later would either be more work or forgotten, and never be done,
>> then.
>
> I'm sorry but I don't agree. I think that having r8a7796 support
> in mainline is a higher priority than sorting this out.


Looking at the example I gave in

http://article.gmane.org/gmane.linux.kernel.renesas-soc/4013

which took me < 1h to create, I'm not sure what would block us from 
mainlining the r8a7796 *including* this.


>> For a starting point, I'd propose to put the r8a7795.dtsi and r8a7796.dtsi
>> into a graphical diff tool and move all common parts to a rcar3.dtsi (I'd be
>> happy to discuss the name, though)
>
> I'm not opposed to that. But being consistent with my statement above
> I would prefer it to be done as follow-up work.
>
> My suspicion is that right now much of the proposed r8a7796.dtsi can be
> moved into a hypothetical rcar3.dtsi. But that this is because the proposed
> r8a7796.dtsi is very small. I would not expect nearly such a large
> proportion of r8a7795.dtsi to be able to be moved into rcar3.dtsi because
> it enables more hardware blocks and they typically have (or should have in
> keeping with the prevailing policy as described above) per-SoC bindings.


What doesn't prevent us to use a rcar3.dtsi like given in

http://article.gmane.org/gmane.linux.kernel.renesas-soc/4013


Having a rcar3.dtsi gives us *both* options. It doesn't force us to use 
the one or the other. I.e. we have for each IP block the *option* to 
declare it as common (put it onto rcar3.dtsi) *or* SoC specific (put it 
into r8a779x.dtsi).

Without having a common rcar3.dtsi we don't have this option at all.

So I think the conclusion is: Let's have all options (by adding a 
rcar3.dtsi) and then decide for each IP block individually where to 
place it best. Or move it later from the common dtsi to the individual 
dtsi once there is an issue found (what I really doubt that it will 
happen that often, but this is an other topic ;) )


> I believe that there is also a another issue which is that we wish
> to control enabling features on different SoCs once they are known to work.
> Of course things slip through the cracks. But blindly assuming all
> IP blocks enabled for one SoC work on another, even if based on the
> documentation, seems to be asking for trouble to me. For one thing
> it implies that the level of firmware support is the same.
>
> As for a name, I suggest rcar-gen3.dtsi.


Sounds good to me :)


Best regards

Dirk






From narmstrong at baylibre.com  Thu May 26 00:17:28 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 26 May 2016 09:17:28 +0200
Subject: [PATCH v4 1/3] firmware: Amlogic: Add secure monitor driver
In-Reply-To: <1464207511-11786-2-git-send-email-carlo@caione.org>
References: <1464207511-11786-1-git-send-email-carlo@caione.org>
 <1464207511-11786-2-git-send-email-carlo@caione.org>
Message-ID: <5746A308.8070606@baylibre.com>

Hi Carlo,

On 05/25/2016 10:18 PM, Carlo Caione wrote:
> diff --git a/include/dt-bindings/firmware/meson-sm.h b/include/dt-bindings/firmware/meson-sm.h
> new file mode 100644
> index 0000000..3a52a13
> --- /dev/null
> +++ b/include/dt-bindings/firmware/meson-sm.h
> @@ -0,0 +1,20 @@
> +/*
> + * Copyright (C) 2016 Endless Mobile, Inc.
> + * Author: Carlo Caione <carlo at endlessm.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef _MESON_DT_H_
> +#define _MESON_DT_H_
> +
> +#define SM_EFUSE_READ		0
> +#define SM_EFUSE_WRITE		1
> +#define SM_EFUSE_USER_MAX	2
> +
> +#endif /* _MESON_DT_H_ */

Now this has been refactored, I don't see the point of this dt-bindings header ?

These defines should take place in linux/firmware/meson/meson-sm.h

Neil


From narmstrong at baylibre.com  Thu May 26 00:20:27 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 26 May 2016 09:20:27 +0200
Subject: [PATCH v4 2/3] documentation: Add secure monitor binding
 documentation
In-Reply-To: <1464207511-11786-3-git-send-email-carlo@caione.org>
References: <1464207511-11786-1-git-send-email-carlo@caione.org>
 <1464207511-11786-3-git-send-email-carlo@caione.org>
Message-ID: <5746A3BB.3030505@baylibre.com>

Hi Carlo,

On 05/25/2016 10:18 PM, Carlo Caione wrote:
> From: Carlo Caione <carlo at endlessm.com>
> 
> Add the binding documentation for the Amlogic secure monitor driver.
> 
> Signed-off-by: Carlo Caione <carlo at endlessm.com>
> ---
>  .../bindings/firmware/meson/meson_sm.txt           | 42 ++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
> 
> diff --git a/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt b/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
> new file mode 100644
> index 0000000..896758d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
> @@ -0,0 +1,42 @@
> +* Amlogic Secure Monitor
> +
> +In the Amlogic SoCs the Secure Monitor code is used to provide access to the
> +NVMEM, enable JTAG, set USB boot, etc...
> +
> +Required properties for the secure monitor node:
> +- compatible: Should be "amlogic,meson-gxbb-sm"
> +
> +Example:
> +
> +	#include <dt-bindings/firmware/meson-sm.h>
> +
> +	...
> +
> +	firmware {
> +		compatible = "simple-bus";
> +
> +		sm: secure-monitor {
> +			compatible = "amlogic,meson-gxbb-sm";
> +		};
> +	};
> +
> +Node of a device using the secure monitor must have a custom property to
> +specify the SMC32 function ID the driver is going to use.
> +
> +Example of the node using the secure monitor:
> +
> +	#include <dt-bindings/firmware/meson-sm.h>
> +
> +	...
> +
> +	efuse: efuse {
> +		compatible = "amlogic,meson-gxbb-efuse";
> +		secure-monitor = <&sm>;
> +		amlogic,sm-cmd-read-efuse = <SM_EFUSE_READ>;
> +		amlogic,sm-cmd-max-efuse = <SM_EFUSE_USER_MAX>;

Same here, since the compatible is "gxbb" specific, there is no need for these properties, and so no need for the dt-bindings header.

> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +
> +		...
> +	};
> +
> 



From raashidmuhammed at zilogic.com  Thu May 26 00:18:25 2016
From: raashidmuhammed at zilogic.com (Raashid Muhammed)
Date: Thu, 26 May 2016 12:48:25 +0530
Subject: [PATCH v2 1/2] ARM: at91/dt: at91sam9260: Remove leading zeros in
 OHCI node.
Message-ID: <0b33151de87d9249a49a90c3a17ee0d112d45043.1464245706.git.raashidmuhammed@zilogic.com>

From: Raashid Muhammed <raashidmuhammed at zilogic.com>

Remove leading zeros in OHCI node for at91sam9260 based boards.

Signed-off-by: Raashid Muhammed <raashidmuhammed at zilogic.com>
Reviewed-by: Vijay Kumar B. <vijaykumar at bravegnu.org>
---
 arch/arm/boot/dts/aks-cdu.dts               | 2 +-
 arch/arm/boot/dts/animeo_ip.dts             | 2 +-
 arch/arm/boot/dts/at91-foxg20.dts           | 2 +-
 arch/arm/boot/dts/at91-kizbox.dts           | 2 +-
 arch/arm/boot/dts/at91-qil_a9260.dts        | 2 +-
 arch/arm/boot/dts/at91sam9260.dtsi          | 2 +-
 arch/arm/boot/dts/at91sam9g20ek_common.dtsi | 2 +-
 arch/arm/boot/dts/ethernut5.dts             | 2 +-
 arch/arm/boot/dts/evk-pro3.dts              | 2 +-
 arch/arm/boot/dts/usb_a9260_common.dtsi     | 2 +-
 10 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/arm/boot/dts/aks-cdu.dts b/arch/arm/boot/dts/aks-cdu.dts
index d9c50fb..5b1bf92 100644
--- a/arch/arm/boot/dts/aks-cdu.dts
+++ b/arch/arm/boot/dts/aks-cdu.dts
@@ -57,7 +57,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/animeo_ip.dts b/arch/arm/boot/dts/animeo_ip.dts
index 0962f2f..8bcbad3 100644
--- a/arch/arm/boot/dts/animeo_ip.dts
+++ b/arch/arm/boot/dts/animeo_ip.dts
@@ -114,7 +114,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			atmel,vbus-gpio = <&pioB 15 GPIO_ACTIVE_LOW>;
 			status = "okay";
diff --git a/arch/arm/boot/dts/at91-foxg20.dts b/arch/arm/boot/dts/at91-foxg20.dts
index 6bf873e..42a535d 100644
--- a/arch/arm/boot/dts/at91-foxg20.dts
+++ b/arch/arm/boot/dts/at91-foxg20.dts
@@ -128,7 +128,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/at91-kizbox.dts b/arch/arm/boot/dts/at91-kizbox.dts
index 229e989..0e3f34e 100644
--- a/arch/arm/boot/dts/at91-kizbox.dts
+++ b/arch/arm/boot/dts/at91-kizbox.dts
@@ -54,7 +54,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <1>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/at91-qil_a9260.dts b/arch/arm/boot/dts/at91-qil_a9260.dts
index 4f2eebf..5309e19 100644
--- a/arch/arm/boot/dts/at91-qil_a9260.dts
+++ b/arch/arm/boot/dts/at91-qil_a9260.dts
@@ -111,7 +111,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index d4884dd..af5ba31 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -1007,7 +1007,7 @@
 			status = "disabled";
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			compatible = "atmel,at91rm9200-ohci", "usb-ohci";
 			reg = <0x00500000 0x100000>;
 			interrupts = <20 IRQ_TYPE_LEVEL_HIGH 2>;
diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
index e9cc99b..1395b30 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -170,7 +170,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/ethernut5.dts b/arch/arm/boot/dts/ethernut5.dts
index 2430443..298ee2f 100644
--- a/arch/arm/boot/dts/ethernut5.dts
+++ b/arch/arm/boot/dts/ethernut5.dts
@@ -77,7 +77,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/evk-pro3.dts b/arch/arm/boot/dts/evk-pro3.dts
index f72969e..312d3e8 100644
--- a/arch/arm/boot/dts/evk-pro3.dts
+++ b/arch/arm/boot/dts/evk-pro3.dts
@@ -46,7 +46,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/usb_a9260_common.dtsi b/arch/arm/boot/dts/usb_a9260_common.dtsi
index 9beea89..12119b5 100644
--- a/arch/arm/boot/dts/usb_a9260_common.dtsi
+++ b/arch/arm/boot/dts/usb_a9260_common.dtsi
@@ -90,7 +90,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
-- 
2.1.4



From raashidmuhammed at zilogic.com  Thu May 26 00:18:26 2016
From: raashidmuhammed at zilogic.com (Raashid Muhammed)
Date: Thu, 26 May 2016 12:48:26 +0530
Subject: [PATCH v2 2/2] ARM: at91: Add DT support for Olimex SAM9-L9260 board.
In-Reply-To: <0b33151de87d9249a49a90c3a17ee0d112d45043.1464245706.git.raashidmuhammed@zilogic.com>
References: <0b33151de87d9249a49a90c3a17ee0d112d45043.1464245706.git.raashidmuhammed@zilogic.com>
Message-ID: <8720a8d5154bdc6c61f01ee2bd4f52e577db9445.1464245706.git.raashidmuhammed@zilogic.com>

From: Raashid Muhammed <raashidmuhammed at zilogic.com>

sam9-l9260 is a low cost board designed by Olimex.

More information is available at:
https://www.olimex.com/Products/ARM/Atmel/SAM9-L9260/

Signed-off-by: Raashid Muhammed <raashidmuhammed at zilogic.com>
Reviewed-by: Vijay Kumar B. <vijaykumar at bravegnu.org>
---
 Documentation/devicetree/bindings/arm/olimex.txt |   8 +-
 arch/arm/boot/dts/Makefile                       |   1 +
 arch/arm/boot/dts/at91-sam9_l9260.dts            | 115 +++++++++++++++++++++++
 3 files changed, 122 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/boot/dts/at91-sam9_l9260.dts

diff --git a/Documentation/devicetree/bindings/arm/olimex.txt b/Documentation/devicetree/bindings/arm/olimex.txt
index 007fb5c..d726aec 100644
--- a/Documentation/devicetree/bindings/arm/olimex.txt
+++ b/Documentation/devicetree/bindings/arm/olimex.txt
@@ -1,5 +1,9 @@
-Olimex i.MX Platforms Device Tree Bindings
-------------------------------------------
+Olimex Device Tree Bindings
+---------------------------
+
+SAM9-L9260 Board
+Required root node properties:
+    - compatible = "olimex,sam9-l9260", "atmel,at91sam9260";
 
 i.MX23 Olinuxino Low Cost Board
 Required root node properties:
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 0f89d87..d27f09d 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -19,6 +19,7 @@ dtb-$(CONFIG_SOC_SAM_V4_V5) += \
 	usb_a9260.dtb \
 	at91sam9261ek.dtb \
 	at91sam9263ek.dtb \
+	at91-sam9_l9260.dtb \
 	tny_a9263.dtb \
 	usb_a9263.dtb \
 	at91-foxg20.dtb \
diff --git a/arch/arm/boot/dts/at91-sam9_l9260.dts b/arch/arm/boot/dts/at91-sam9_l9260.dts
new file mode 100644
index 0000000..b3d738b
--- /dev/null
+++ b/arch/arm/boot/dts/at91-sam9_l9260.dts
@@ -0,0 +1,115 @@
+/*
+ * at91-sam9_l9260.dts - Device Tree file for Olimex SAM9-L9260 board
+ *
+ *  Copyright (C) 2016 Raashid Muhammed <raashidmuhammed at zilogic.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+#include "at91sam9260.dtsi"
+
+/ {
+	model = "Olimex sam9-l9260";
+	compatible = "olimex,sam9-l9260", "atmel,at91sam9260", "atmel,at91sam9";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		reg = <0x20000000 0x4000000>;
+	};
+
+	clocks {
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
+	};
+
+	ahb {
+		apb {
+			mmc0: mmc at fffa8000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc0
+					&pinctrl_mmc0_clk
+					&pinctrl_mmc0_slot1_cmd_dat0
+					&pinctrl_mmc0_slot1_dat1_3>;
+				status = "okay";
+
+				slot at 1 {
+					reg = <1>;
+					bus-width = <4>;
+					cd-gpios = <&pioC 8 GPIO_ACTIVE_HIGH>;
+					wp-gpios = <&pioC 4 GPIO_ACTIVE_HIGH>;
+				};
+			};
+
+			macb0: ethernet at fffc4000 {
+				phy-mode = "mii";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "okay";
+
+				ethernet-phy at 1 {
+					reg = <0x1>;
+				};
+			};
+
+			spi0: spi at fffc8000 {
+				cs-gpios = <&pioC 11 0>, <0>, <0>, <0>;
+				status = "okay";
+
+				mtd_dataflash at 0 {
+					compatible = "atmel,at45", "atmel,dataflash";
+					spi-max-frequency = <15000000>;
+					reg = <0>;
+				};
+			};
+
+			dbgu: serial at fffff200 {
+				status = "okay";
+			};
+
+			pinctrl at fffff400 {
+				mmc0 {
+					pinctrl_board_mmc0: mmc0-board {
+						atmel,pins =
+							<AT91_PIOC 8 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH	/* CD pin */
+							 AT91_PIOC 4 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP>;	/* WP pin */
+					};
+				};
+			};
+		};
+
+		nand0: nand at 40000000 {
+			nand-bus-width = <8>;
+			nand-ecc-mode = "soft";
+			nand-on-flash-bbt = <1>;
+			status = "okay";
+		};
+
+		usb0: ohci at 500000 {
+			status = "okay";
+		};
+
+	};
+
+	i2c at 0 {
+		status = "okay";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		b0 {
+			label = "b0";
+			gpios = <&pioA 6 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+
+	};
+};
-- 
2.1.4



From ck.hu at mediatek.com  Thu May 26 00:28:28 2016
From: ck.hu at mediatek.com (CK Hu)
Date: Thu, 26 May 2016 15:28:28 +0800
Subject: [PATCH v7 2/4] CMDQ: Mediatek CMDQ driver
In-Reply-To: <1464092829.19894.16.camel@mtksdaap41>
References: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
 <1464006190-344-3-git-send-email-hs.liao@mediatek.com>
 <1464059159.7425.6.camel@mtksdaap41> <1464092829.19894.16.camel@mtksdaap41>
Message-ID: <1464247708.13536.14.camel@mtksdaap41>

Hi, HS:

Replay inline.

On Tue, 2016-05-24 at 20:27 +0800, Horng-Shyang Liao wrote:
> Hi CK,
> 
> Reply in line.
> 
> On Tue, 2016-05-24 at 11:05 +0800, CK Hu wrote:
> > Hi, HS:
> > 
> > Some comments below.
> > 
> ...
> > > +static void cmdq_thread_irq_handler(struct cmdq *cmdq, int tid)
> > > +{
> > > +	struct cmdq_thread *thread = &cmdq->thread[tid];
> > > +	unsigned long flags = 0L;
> > > +	int value;
> > > +
> > > +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> > > +
> > > +	/*
> > > +	 * it is possible for another CPU core
> > > +	 * to run "release task" right before we acquire the spin lock
> > > +	 * and thus reset / disable this HW thread
> > > +	 * so we check both the IRQ flag and the enable bit of this thread
> > > +	 */
> > > +	value = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> > > +	if (!(value & CMDQ_THR_IRQ_MASK)) {
> > > +		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > > +		return;
> > > +	}
> > 
> > If this case happen and just return without clearing irq status, the irq
> > would keep triggering and system hang up. So just remove this checking
> > and go down to clear irq status.
> 
> This case is safe because irq status is cleared.
> But, next if condition has the problem which you mentioned.
> 
> I will change it as below.
> 
> 	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> 	      CMDQ_THR_ENABLED)) {
> 		cmdq_thread_writel(thread, ~value, CMDQ_THR_IRQ_STATUS);
> 		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> 		return;
> 	}
> 
> If thread is disabled, tasks must be all finished.
> Therefore, just clear irq status and return.
> 

For irq status checking part, if irq status & irq mask is zero, remove
this checking and let it go down, it still do nothing because value &
CMDQ_THR_IRQ_ERROR is zero and value & CMDQ_THR_IRQ_DONE is zero. So you
can just remove this checking and get the same result.

In general HW design, once a HW is not enable, it does not trigger
interrupt any more. Be sure that it's necessary to clear irq status even
though thread is disable.


> > > +
> > > +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> > > +	      CMDQ_THR_ENABLED)) {
> > > +		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > > +		return;
> > > +	}
> > > +
> > > +	cmdq_thread_writel(thread, ~value, CMDQ_THR_IRQ_STATUS);
> > > +
> > > +	if (value & CMDQ_THR_IRQ_ERROR)
> > > +		cmdq_handle_error_done(cmdq, thread, true);
> > > +	else if (value & CMDQ_THR_IRQ_DONE)
> > > +		cmdq_handle_error_done(cmdq, thread, false);
> > 
> > These irq status checking and clearing code here is the same as those in
> > cmdq_task_handle_error_result(). To move the checking and clearing code
> > into cmdq_handle_error_done() and here just to call
> > cmdq_handle_error_done(cmdq, thread) would reduce duplicated code.
> 
> Will do.
> 
> > > +
> > > +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > > +}
> ...
> ...
> > 
> > Regards,
> > CK
> 
> Thanks,
> HS
> 

Regards,
CK




From narmstrong at baylibre.com  Thu May 26 00:30:32 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 26 May 2016 09:30:32 +0200
Subject: [PATCH v2 2/4] dt-bindings: reset: Add bindings for the Meson SoC
 Reset Controller
In-Reply-To: <20160525191026.GA24249@rob-hp-laptop>
References: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
 <1464169758-26975-3-git-send-email-narmstrong@baylibre.com>
 <20160525191026.GA24249@rob-hp-laptop>
Message-ID: <5746A618.2020304@baylibre.com>

On 05/25/2016 09:10 PM, Rob Herring wrote:
> On Wed, May 25, 2016 at 11:49:16AM +0200, Neil Armstrong wrote:
>> Add DT bindings for the Meson SoC Reset Controller documentation and the
>> associated include file.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> ---
>>  .../bindings/reset/amlogic,meson-reset.txt         |  18 ++
>>  .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 210 +++++++++++++++++++++
>>  include/dt-bindings/reset/amlogic,meson8b-reset.h  | 175 +++++++++++++++++
>>  3 files changed, 403 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt
>>  create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
>>  create mode 100644 include/dt-bindings/reset/amlogic,meson8b-reset.h
> 
> Please add acks when posting new versions.
> 
> Rob
> 

Hi Rob,

Actually I made a lot of changes here since I added support for the meson8b.
I asked myself if I could carry your ack actually...

If the ack is still valid, I'll won't forget it for v4.

Thanks,
Neil


From dirk.behme at de.bosch.com  Thu May 26 00:32:16 2016
From: dirk.behme at de.bosch.com (Dirk Behme)
Date: Thu, 26 May 2016 09:32:16 +0200
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <CAMuHMdXnN-GTN4crXeWRvtWT4E2kYFvMdPPcH8z+gJb-B4PbYA@mail.gmail.com>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
 <20160525004825.GC7292@verge.net.au>
 <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>
 <edee7345-280a-0d7c-7e5a-798215fbd2b9@de.bosch.com>
 <CAMuHMdXnN-GTN4crXeWRvtWT4E2kYFvMdPPcH8z+gJb-B4PbYA@mail.gmail.com>
Message-ID: <5a697ce7-c02a-707c-55b6-6cc209b63b32@de.bosch.com>

On 26.05.2016 09:03, Geert Uytterhoeven wrote:
> Hi Dirk,
>
> On Wed, May 25, 2016 at 9:32 AM, Dirk Behme <dirk.behme at de.bosch.com> wrote:
>> P.S.: This also results in the question why we need similar
>> r8a7795-cpg-mssr.h and r8a7796-cpg-mssr.h with just different "numbers" for
>> the same clocks. Can't we use the same numbers on all SoCs, with just having
>> wholes in the list where the clocks don't exist on a SoC? I haven't looked
>
> The CPG and MSSR block are the IP blocks that differ most among SoCs of the
> same family. Some clocks are present on H3 only, others on M3-W only.


Yes, this is my understanding as well. Is the H3 a superset? And the 
M3-W drops some clocks? Or are there really clocks which are on M3-W 
only and not on H3?


> Having a shared driver core, but different defines, is a compromise between
> reusability and avoiding mistakes in DTSes (e.g. pointing to a nonexisting
> clock due to copy and paste from another SoC).


Sounds like this is a nice additional argument to don't do all this copy 
& paste and have a common rcar3.dtsi, instead :)


>> into the manual if these numbers are given by the hardware, though.
>
> The actual numbers don't map to numbers in the datasheet, just to an unordered
> list in a table. The list of number is considered part of the DT bindings, and
> thus append-only (to be considered in case the datasheet is updated).


Ok, then there should be the option to find a clever way to define the 
clocks common on all SoCs only once. And the clocks which are different 
somehow on top, then.

To take the example from

http://article.gmane.org/gmane.linux.kernel.renesas-soc/4013

this

&scif2 {
	clocks = <&cpg CPG_MOD 310>,
		 <&cpg CPG_CORE R8A7795_CLK_S3D1>,
		 <&scif_clk>;
};

&scif2 {
	clocks = <&cpg CPG_MOD 310>,
		 <&cpg CPG_CORE R8A7796_CLK_S3D1>,
		 <&scif_clk>;
};

should be done better.

Best regards

Dirk


From ulf.hansson at linaro.org  Thu May 26 00:44:10 2016
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Thu, 26 May 2016 09:44:10 +0200
Subject: [v10,
 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-R1.0-R2.0
In-Reply-To: <HE1PR04MB0889852B7809A1CCFF8922ACF8410@HE1PR04MB0889.eurprd04.prod.outlook.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <4448030.Zs8fVnr3nm@wuerfel>
 <HE1PR04MB0889B52134A43C0E7A452B7BF87C0@HE1PR04MB0889.eurprd04.prod.outlook.com>
 <5159406.HOFrj7pRfW@wuerfel>
 <1462937186.16584.77.camel@buserror.net>
 <HE1PR04MB0889852B7809A1CCFF8922ACF8410@HE1PR04MB0889.eurprd04.prod.outlook.com>
Message-ID: <CAPDyKFqx2JMLzXoDxGCKFYMFV47+SegnkuWFXKvsQHK7L5w-1g@mail.gmail.com>

On 26 May 2016 at 06:05, Yangbo Lu <yangbo.lu at nxp.com> wrote:
> Hi Uffe,
>
> Could we merge this patchset? ...
> It has been a long time to wait for Arnd's response...
>
> Thanks a lot.
>
>

As we are still in the merge window I won't queue anything but fixes.
Let's give Arnd another week or so to respond.

Kind regards
Uffe

> Best regards,
> Yangbo Lu
>
>
>> -----Original Message-----
>> From: Yangbo Lu
>> Sent: Friday, May 20, 2016 2:06 PM
>> To: 'Scott Wood'; Arnd Bergmann; linux-arm-kernel at lists.infradead.org
>> Cc: linuxppc-dev at lists.ozlabs.org; Mark Rutland;
>> devicetree at vger.kernel.org; ulf.hansson at linaro.org; Russell King; Bhupesh
>> Sharma; netdev at vger.kernel.org; Joerg Roedel; Kumar Gala; linux-
>> mmc at vger.kernel.org; linux-kernel at vger.kernel.org; Yang-Leo Li;
>> iommu at lists.linux-foundation.org; Rob Herring; linux-i2c at vger.kernel.org;
>> Claudiu Manoil; Santosh Shilimkar; Xiaobo Xie; linux-clk at vger.kernel.org;
>> Qiang Zhao
>> Subject: RE: [v10, 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-
>> R1.0-R2.0
>>
>> Hi Arnd,
>>
>> Any comments?
>> Please reply when you see the email since we want this eSDHC issue to be
>> fixed soon.
>>
>> All the patches are Freescale-specific and is to fix the eSDHC driver.
>> Could we let them merged first if you were talking about a new way of
>> abstracting getting SoC version.
>>
>>
>> Thanks :)
>>
>>
>> Best regards,
>> Yangbo Lu
>>
>


From wangkefeng.wang at huawei.com  Thu May 26 00:43:00 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Thu, 26 May 2016 15:43:00 +0800
Subject: [PATCH v4 01/18] of/platform: Add common method to populate
 default bus
In-Reply-To: <CAL_JsqJt9qa+3eAO95kvM7h2beRfq3q1Bi39K7uhURTp=f_DtQ@mail.gmail.com>
References: <1463054775-18170-1-git-send-email-wangkefeng.wang@huawei.com>
 <1463054775-18170-2-git-send-email-wangkefeng.wang@huawei.com>
 <CAL_JsqJt9qa+3eAO95kvM7h2beRfq3q1Bi39K7uhURTp=f_DtQ@mail.gmail.com>
Message-ID: <5746A904.6080003@huawei.com>



On 2016/5/25 22:46, Rob Herring wrote:
> On Thu, May 12, 2016 at 7:05 AM, Kefeng Wang <wangkefeng.wang at huawei.com> wrote:
>> The arch code calls of_platform_populate() with default match table
>> when it want to populate default bus.
>>
>> This patch introduce a new of_platform_default_populate_init() and make it
>> arch_initcall_sync(it should be later than some iommu configration, eg,
>> of_iommu_init() and swiotlb_late_init in arm64), then we can finish above
>> job in common method.
>>
>> In order to avoid the default bus being populated twice, simply checking
>> the flag of bus node whether has be set OF_POPULATED_BUS or not.
>>
>> After that, we can safely remove the caller in arch code.
>>
>> Btw, add debug print in of_platform_populate(), and use __func__ to
>> print function's name of of_platform_bus_create().
>>
>> Cc: Rob Herring <robh+dt at kernel.org>
>> Cc: Frank Rowand <frowand.list at gmail.com>
>> Cc: Grant Likely <grant.likely at linaro.org>
>> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
>> ---
>>  drivers/of/platform.c | 23 ++++++++++++++++++++++-
>>  1 file changed, 22 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
>> index 8d103e4..f601b30 100644
>> --- a/drivers/of/platform.c
>> +++ b/drivers/of/platform.c
>> @@ -11,6 +11,7 @@
>>   *  2 of the License, or (at your option) any later version.
>>   *
>>   */
>> +#include <linux/acpi.h>
>>  #include <linux/errno.h>
>>  #include <linux/module.h>
>>  #include <linux/amba/bus.h>
>> @@ -345,6 +346,12 @@ static int of_platform_bus_create(struct device_node *bus,
>>                 return 0;
>>         }
>>
>> +       if (of_node_check_flag(bus, OF_POPULATED_BUS)) {
>> +               pr_debug("%s() - skipping %s, already populated\n",
>> +                       __func__, bus->full_name);
>> +               return 0;
>> +       }
>> +
>>         auxdata = of_dev_lookup(lookup, bus);
>>         if (auxdata) {
>>                 bus_id = auxdata->name;
>> @@ -396,7 +403,7 @@ int of_platform_bus_probe(struct device_node *root,
>>         if (!root)
>>                 return -EINVAL;
>>
>> -       pr_debug("of_platform_bus_probe()\n");
>> +       pr_debug("%s()\n", __func__);
>>         pr_debug(" starting at: %s\n", root->full_name);
>>
>>         /* Do a self check of bus type, if there's a match, create children */
>> @@ -448,6 +455,9 @@ int of_platform_populate(struct device_node *root,
>>         if (!root)
>>                 return -EINVAL;
>>
>> +       pr_debug("%s()\n", __func__);
>> +       pr_debug(" starting at: %s\n", root->full_name);
>> +
>>         for_each_child_of_node(root, child) {
>>                 rc = of_platform_bus_create(child, matches, lookup, parent, true);
>>                 if (rc) {
>> @@ -471,6 +481,17 @@ int of_platform_default_populate(struct device_node *root,
>>  }
>>  EXPORT_SYMBOL_GPL(of_platform_default_populate);
>>
>> +static int __init of_platform_default_populate_init(void)
>> +{
>> +       if (of_have_populated_dt())
>> +               of_platform_default_populate(NULL, NULL, NULL);
>> +       else if (acpi_disabled)
> 
> This ACPI dependency needs to go. The error msg is somewhat pointless
> as if both DT and ACPI are not used, the boot will be horribly broken
> and I'm not sure that you would actually see the message given you
> have no information to setup a console.

Fair enough, will update and rebase patches after 4.7-rc1.

Thanks,
Kefeng

> 
> Rob
> 
> .
> 



From javier at osg.samsung.com  Thu May 26 00:45:01 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 26 May 2016 03:45:01 -0400
Subject: ARM: dts: exynos: Add MFC memory banks for Peach boards
In-Reply-To: <574670E7.3060508@samsung.com>
References: <1461871311-18344-1-git-send-email-javier@osg.samsung.com>
 <57456344.7020708@samsung.com>
 <d045b880-4a44-acd8-f7f6-e521caf374aa@osg.samsung.com>
 <574670E7.3060508@samsung.com>
Message-ID: <476edff1-9f3e-fc5b-4385-d04ae917b58e@osg.samsung.com>

[adding Kevin and Sjoerd who also noticed issues with this patch]

Hi Pankaj,

On 05/25/2016 11:43 PM, pankaj.dubey wrote:
> Hi Javier,
> 
> On Wednesday 25 May 2016 08:32 PM, Javier Martinez Canillas wrote:
>> Hello Pankaj,
>>
>> On 05/25/2016 04:33 AM, pankaj.dubey wrote:
>>> Hi Javier,
>>>
>>>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>>
>>> Just noticed that, current krzk/for-next failed to boot on Exynos5880
>>> based Chromebook device. Git bisect is showing culprit as this patch.
>>
>> Strange, krzk/for-next boots correctly on my Exynos5800 Peach Pi:
>>
>> $ git log --pretty=oneline --abbrev-commit HEAD
>> 35e691cf5165 Merge branch 'fixes-v4.7' into for-next
>>
> 
> This is same as mine.
> 
> My other build parameters are:
> defconfig: exynos_defconfig
> CROSS_COMPILE: gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux

I'm also using exynos_defconfig and a similar compiler
(gcc-linaro-arm-linux-gnueabihf-4.9-2015.01-3).

> rootfs: small cramfs
>
>> $ uname -r
>> 4.6.0-00073-g35e691cf5165
>>
>>> When I reverted this patch, its able to boot normally.
>>> Is there any missing patches that we need to take on krzk/for-next to
>>> boot on Chromebook.
>>>
>>
> 
> Further I checked that, either I revert this patch OR do not reserve
> memory for MFC in exynos_reserve using following changes, both cases I
> am able to boot kernel on Chromebook (Exynos5800).
> 
> diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
> index f977eea..e615e24 100644
> --- a/arch/arm/mach-exynos/exynos.c
> +++ b/arch/arm/mach-exynos/exynos.c
> @@ -268,7 +268,7 @@ static char const *const exynos_dt_compat[]
> __initconst = {
> 
>  static void __init exynos_reserve(void)
>  {
> -#ifdef CONFIG_S5P_DEV_MFC
> +#ifndef CONFIG_S5P_DEV_MFC
>         int i;
>         char *mfc_mem[] = {
>                 "samsung,mfc-v5",
> @@ -280,6 +280,8 @@ static void __init exynos_reserve(void)
>         for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
>                 if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
>                         break;
> +#else
> +       pr_err("*****exynos_reserve Bypassing Memory Reservation for MFC
> ********\n");
>  #endif
>  }
> 
> 
>> No that I'm aware of. I wonder why it boots for me but fails for
>> you. Can you please share your complete boot log to see if there
>> are any hints there?
>>  
> 
> Following is failed boot log:
> U-Boot 2013.04-g8e3e5ef (May 26 2015 - 16:11:36) for Peach
> 
> CPU:    Exynos5422 at 900MHz
> 
> Board: Google Peach Pi, rev 11.6
> I2C:   ready
> DRAM:  3.5 GiB
> Relocation Offset dbd54000, base at ffb54000
> SPL stack at 2072c00, used 3f0, free 10
> PMIC max77802-pmic initialized
> CPU:    Exynos5422 at 1800MHz
> TPS65090 PMIC EC init
> MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
> SF: Detected W25Q32DW with page size 4 KiB, total 32 MiB
> In:    cros-ec-keyb
> Out:   lcd
> Err:   lcd
> SF: Detected W25Q32DW with page size 4 KiB, total 32 MiB
> ELOG: Event(17) added with size 13
> Net:   No ethernet found.
> Hit any key to stop autoboot:  0
> mmc1 is current device
> 4586144 bytes read in 242 ms (18.1 MiB/s)
> 26583040 bytes read in 1166 ms (21.7 MiB/s)
> ## Loading kernel from FIT Image at 20008000 ...
>    Using 'conf at 2' configuration
>    Trying 'kernel at 1' kernel subimage
>      Description:  unavailable
>      Type:         Kernel Image (no loading done)
>      Compression:  uncompressed
>      Data Start:   0x200080c8
>      Data Size:    4459024 Bytes = 4.3 MiB
>    Verifying Hash Integrity ... OK
> ## Loading fdt from FIT Image at 20008000 ...

A difference I see is that I'm chain loading a non-verified u-boot and you
are loading a signed FIT image directly. But Sjoerd also chain loads a nv
u-boot and his Peach doesn't boot either so I don't think that's a cause.

>    Using 'conf at 2' configuration
>    Trying 'fdt at 2' fdt subimage
>      Description:  exynos5800-peach-pi.dtb
>      Type:         Flat Device Tree
>      Compression:  uncompressed
>      Data Start:   0x20458148
>      Data Size:    63002 Bytes = 61.5 KiB
>      Architecture: ARM
>      Hash algo:    sha1
>      Hash value:   cd1c1703f744b44b1833ca61ec36b625665548de
>    Verifying Hash Integrity ... sha1+ OK
>    Booting using the fdt blob at 0x20458148
>    XIP Kernel Image (no loading done) ... OK
>    Loading Device Tree to 3ffe1000, end 3ffffb49 ... OK
> boot_kernel.c: ft_board_setup: warning: Must pass exactly one of vboot
> or cdata
> 
> Starting kernel ...
> 
> Timer summary in microseconds:
>        Mark    Elapsed  Stage
>           0          0  reset
>     122,793    122,793  board_init_f
>     143,214     20,421  board_init_r
>     238,069     94,855  id=64
>     240,278      2,209  main_loop
>   4,841,682  4,601,404  bootm_start
>   4,841,683          1  id=1
>   4,846,604      4,921  id=100
>   4,846,607          3  id=101
>   4,846,607          0  id=102
>   4,850,208      3,601  id=110
>   4,877,729     27,521  id=105
>   4,877,731          2  id=106
>   4,877,734          3  id=107
>   4,877,735          1  id=108
>   4,877,736          1  id=109
>   4,882,406      4,670  id=90
>   4,882,408          2  id=92
>   4,882,408          0  id=91
>   4,927,272     44,864  id=95
>   4,927,274          2  id=96
>   4,927,276          2  id=97
>   4,927,277          1  id=98
>   4,927,279          2  id=99
>   4,937,617     10,338  id=7
>   4,951,899     14,282  id=15
>   4,955,112      3,213  start_kernel
> 
> Accumulated time:
>                  6,948  SPI read
> Uncompressing Linux... done, booting the kernel.
> [    0.000000] Booting Linux on physical CPU 0x0
> [    0.000000] Linux version 4.6.0-00073-g35e691c
> (pankaj at chromebld-server) (gcc version 4.9.2 20140904 (prerelease)
> (crosstool-NG linaro-1.13.1-4.9-2014.09 - Linaro GCC
> 4.9-2014.09) ) #59 SMP PREEMPT Thu May 26 08:21:07 IST 2016
> [    0.000000] CPU: ARMv7 Processor [412fc0f3] revision 3 (ARMv7),
> cr=10c5387d
> [    0.000000] CPU: div instructions available: patching division code
> [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction
> cache
> [    0.000000] Machine model: Google Peach Pi Rev 10+
> [    0.000000] bootconsole [earlycon0] enabled
> [    0.000000] cma: Reserved 64 MiB at 0xfbc00000
> [    0.000000] Memory policy: Data cache writealloc
> [    0.000000] Samsung CPU ID: 0xe5422001
> [    0.000000] On node 0 totalpages: 913407
> [    0.000000] free_area_init_node: node 0, pgdat c0b42cc0, node_mem_map
> ee3f7000
> [    0.000000]   Normal zone: 1536 pages used for memmap
> [    0.000000]   Normal zone: 0 pages reserved
> [    0.000000]   Normal zone: 194560 pages, LIFO batch:31
> [    0.000000]   HighMem zone: 718847 pages, LIFO batch:31
> [    0.000000] percpu: Embedded 12 pages/cpu @ee341000 s19392 r8192
> d21568 u49152
> [    0.000000] pcpu-alloc: s19392 r8192 d21568 u49152 alloc=12*4096
> [    0.000000] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3 [0] 4 [0] 5 [0] 6 [0] 7
> [    0.000000] Built 1 zonelists in Zone order, mobility grouping on.
> Total pages: 911871
> [    0.000000] Kernel command line: cros_legacy console=ttySAC3,115200
> debug earlyprintk cros_debug no_console_suspend root=/dev/ram0 rw
> ramdisk=32768 initrd=0x42000000,3
> 2M

I see that you are loading an initrd at 0x42000000 with size of 32 MiB.

[...]

> [    1.121421] Trying to unpack rootfs image as initramfs...
> [    1.126940] rootfs image is not initramfs (junk in compressed
> archive); looks like an initrd
> [    1.160139] Unable to handle kernel paging request at virtual address
> e3000000

So I wonder if the problem is that the memblock_remove() is called very
early and so the kernel is not able to copy the initrd from 0x42000000
to 0x44000000 since overlaps with the mfc-r mem (0x43000000-0x43800000).

Specially since the NULL pointer dereference below happens in the
populate_rootfs() function when calling xwrite() to do the copy.

Could you please try to change the load address for your initrd, or
change the mfc-r start address to see if that prevents the issue?

> [    1.167270] pgd = c0004000
> [    1.170046] [e3000000] *pgd=00000000
> [    1.173693] Internal error: Oops: 5 [#1] PREEMPT SMP ARM
> [    1.179068] Modules linked in:
> [    1.182194] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
> 4.6.0-00073-g35e691c #59
> [    1.189477] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [    1.195638] task: edc88000 ti: edc76000 task.ti: edc76000
> [    1.201111] PC is at memcpy+0x48/0x330
> [    1.204923] LR is at iov_iter_copy_from_user_atomic+0x184/0x24c
> [    1.210906] pc : [<c0320388>]    lr : [<c0331688>]    psr: 20000013
> [    1.210906] sp : edc77cd4  ip : 00000000  fp : c070b640
> [    1.222530] r10: 00000000  r9 : 00000000  r8 : ffefe000
> [    1.227822] r7 : 00000000  r6 : ffeff000  r5 : 00001000  r4 : edc77dec
> [    1.234415] r3 : 01000000  r2 : 00000f80  r1 : e3000000  r0 : ffefe000
> [    1.241009] Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM
> Segment none
> [    1.248208] Control: 10c5387d  Table: 2000406a  DAC: 00000051
> [    1.254020] Process swapper/0 (pid: 1, stack limit = 0xedc76210)
> [    1.260093] Stack: (0xedc77cd4 to 0xedc78000)
> [    1.264518] 7cc0:
> 00001000 ffeff000 00000000
> [    1.272760] 7ce0: ffefe000 ffefe000 edc77dec c0331688 00001000
> 00001000 edc77df4 ed85508c
> [    1.281001] 7d00: 00001000 01000000 00000000 00000000 c070b640
> c01966d8 00001000 00000001
> [    1.289242] 7d20: edc77d40 edc77d44 00000000 edf0e600 01000000
> 00000000 edc76000 00000001
> [    1.297483] 7d40: eff519e0 c01f6100 00000000 00000000 edc77e08
> 00000000 edc77df4 edc77df4
> [    1.305725] 7d60: edf0e600 ed85508c c0b45050 c0197f88 c0b45050
> c06c9d3c c0b67b58 c0b67b58
> [    1.313966] 7d80: 000000a8 00000003 ed855018 edc77e08 ed855018
> edf0e600 edc77df4 02000000
> [    1.322207] 7da0: 00000000 c0b4504c c0b45050 c0198118 eded6860
> c0b4504c c0b45050 c01ec01c
> [    1.330448] 7dc0: edf0e600 02000000 00000000 00000000 edc77e60
> eded6860 c0b4504c c01dd0b8
> [    1.338690] 7de0: 02000000 00000301 00000002 e2000000 02000000
> 00000003 01000000 01000000
> [    1.346931] 7e00: edc77dec 00000001 edf0e600 00000000 00000000
> 00000000 00000000 00000000
> [    1.355172] 7e20: 00000000 00000000 edf0e600 02000000 e2000000
> edc77e60 00000000 c01dddac
> [    1.363414] 7e40: ed854fa0 edf0e608 edf0e600 edf0e600 e2000000
> 02000000 00000000 c01dead8
> [    1.371655] 7e60: 00000000 00000000 c08781c0 02000000 e2000000
> 00000000 00000000 c0a027a8
> [    1.379896] 7e80: 00000000 00000000 eded6800 c0b43a4c 00000000
> c0a02eb4 c0871494 eded685b
> [    1.388137] 7ea0: 00000001 00000068 000241ed 00000000 00000000
> 00000000 00001000 00000000
> [    1.396378] 7ec0: 57465fab 00000000 57465fab 00000000 00000000
> 376eac80 00000000 00000000
> [    1.404619] 7ee0: 00000000 c0b05a50 c0b05a50 c0a02d70 00000000
> edf24ac0 000000d4 c0a34848
> [    1.412861] 7f00: 00000000 c0101814 c0b0a98c edc77f18 c0b47668
> c06c98b0 60000000 c0b0933c
> [    1.421102] 7f20: 00000000 c0b0933c c0926578 c0716b3c 000000d4
> c0135ef0 0000cccd 00000000
> [    1.429343] 7f40: c08dd0e0 00000000 00000005 00000005 c0b09318
> efffc8c0 c0a5ba5c 00000005
> [    1.437585] 7f60: c0a3483c c0b45000 c0b45000 000000d4 c0a34848
> c0a00db8 00000005 00000005
> [    1.445826] 7f80: 00000000 c0a005a0 00000000 c06c6254 00000000
> 00000000 00000000 00000000
> [    1.454067] 7fa0: 00000000 c06c625c 00000000 c0107a38 00000000
> 00000000 00000000 00000000
> [    1.462308] 7fc0: 00000000 00000000 00000000 00000000 00000000
> 00000000 00000000 00000000
> [    1.470549] 7fe0: 00000000 00000000 00000000 00000000 00000013
> 00000000 f7ffffff a7ffefff
> [    1.478797] [<c0320388>] (memcpy) from [<c0331688>]
> (iov_iter_copy_from_user_atomic+0x184/0x24c)
> [    1.487646] [<c0331688>] (iov_iter_copy_from_user_atomic) from
> [<c01966d8>] (generic_perform_write+0xf8/0x1c8)
> [    1.497706] [<c01966d8>] (generic_perform_write) from [<c0197f88>]
> (__generic_file_write_iter+0x198/0x1f4)
> [    1.507420] [<c0197f88>] (__generic_file_write_iter) from
> [<c0198118>] (generic_file_write_iter+0x134/0x260)
> [    1.517311] [<c0198118>] (generic_file_write_iter) from [<c01dd0b8>]
> (__vfs_write+0xa8/0xd8)
> [    1.525811] [<c01dd0b8>] (__vfs_write) from [<c01dddac>]
> (vfs_write+0x90/0x164)
> [    1.533184] [<c01dddac>] (vfs_write) from [<c01dead8>]
> (SyS_write+0x44/0x9c)
> [    1.540301] [<c01dead8>] (SyS_write) from [<c0a027a8>] (xwrite+0x2c/0x68)
> [    1.547152] [<c0a027a8>] (xwrite) from [<c0a02eb4>]
> (populate_rootfs+0x144/0x268)
> [    1.554700] [<c0a02eb4>] (populate_rootfs) from [<c0101814>]
> (do_one_initcall+0x90/0x1d8)
> [    1.562939] [<c0101814>] (do_one_initcall) from [<c0a00db8>]
> (kernel_init_freeable+0x15c/0x1fc)
> [    1.571706] [<c0a00db8>] (kernel_init_freeable) from [<c06c625c>]
> (kernel_init+0x8/0x114)
> [    1.579945] [<c06c625c>] (kernel_init) from [<c0107a38>]
> (ret_from_fork+0x14/0x3c)
> [    1.587576] Code: ba000002 f5d1f03c f5d1f05c f5d1f07c (e8b151f8)
> [    1.593751] ---[ end trace 065c5ae2b4577941 ]---

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From carlo at caione.org  Thu May 26 00:45:16 2016
From: carlo at caione.org (Carlo Caione)
Date: Thu, 26 May 2016 09:45:16 +0200
Subject: [PATCH v4 1/3] firmware: Amlogic: Add secure monitor driver
In-Reply-To: <5746A308.8070606@baylibre.com>
References: <1464207511-11786-1-git-send-email-carlo@caione.org>
 <1464207511-11786-2-git-send-email-carlo@caione.org>
 <5746A308.8070606@baylibre.com>
Message-ID: <20160526074516.GA14703@mephisto>

On 26/05/16 09:17, Neil Armstrong wrote:
> Hi Carlo,

Hi Neil,

> On 05/25/2016 10:18 PM, Carlo Caione wrote:
> > diff --git a/include/dt-bindings/firmware/meson-sm.h b/include/dt-bindings/firmware/meson-sm.h
> > new file mode 100644
> > index 0000000..3a52a13
> > --- /dev/null
> > +++ b/include/dt-bindings/firmware/meson-sm.h
> > @@ -0,0 +1,20 @@
> > +/*
> > + * Copyright (C) 2016 Endless Mobile, Inc.
> > + * Author: Carlo Caione <carlo at endlessm.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License
> > + * version 2 as published by the Free Software Foundation.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> > + */
> > +
> > +#ifndef _MESON_DT_H_
> > +#define _MESON_DT_H_
> > +
> > +#define SM_EFUSE_READ		0
> > +#define SM_EFUSE_WRITE		1
> > +#define SM_EFUSE_USER_MAX	2
> > +
> > +#endif /* _MESON_DT_H_ */
> 
> Now this has been refactored, I don't see the point of this dt-bindings header ?
> 
> These defines should take place in linux/firmware/meson/meson-sm.h

Yes, that is a possibility I considered before submitting this version
and now it also seems probably the best way to do it. I'll change it in
the next revision.

Thanks,

-- 
Carlo Caione


From narmstrong at baylibre.com  Thu May 26 00:51:49 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 26 May 2016 09:51:49 +0200
Subject: [RFC PATCH 0/3] watchdog: Add Amlogic Meson GXBB Watchdog Timer driver
Message-ID: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>

Adds support for the Amlogic Meson GXBB SoC Watchdog Timer.
It differs from the meson6/meson8b HW, so need for a separate driver.
The HW provides a divider capable of having a 1ms timebase thus simplifying
the counter update.
The restart call is not provided even if the HW is capable of triggering a
system reset immediately because of the PSCI firmare having such functionnality.

Neil Armstrong (3):
  watchdog: Add Meson GXBB Watchdog Driver
  dt-bindings: watchdog: Add Meson GXBB Watchdog bindings
  ARM64: dts: amlogic: meson-gxbb: Add watchdog node

 .../bindings/watchdog/meson-gxbb-wdt.txt           |  13 +
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   6 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/meson_gxbb_wdt.c                  | 287 +++++++++++++++++++++
 4 files changed, 307 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt
 create mode 100644 drivers/watchdog/meson_gxbb_wdt.c

-- 
2.7.0



From narmstrong at baylibre.com  Thu May 26 00:51:51 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 26 May 2016 09:51:51 +0200
Subject: [RFC PATCH 2/3] dt-bindings: watchdog: Add Meson GXBB Watchdog
 bindings
In-Reply-To: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
References: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464249112-13658-3-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 .../devicetree/bindings/watchdog/meson-gxbb-wdt.txt         | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt b/Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt
new file mode 100644
index 0000000..d06c0a0
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt
@@ -0,0 +1,13 @@
+Meson GXBB SoCs Watchdog timer
+
+Required properties:
+
+- compatible : should be "amlogic,meson-gxbb-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Example:
+
+wdt: watchdog at 98d0 {
+	compatible = "amlogic,meson-gxbb-wdt";
+	reg = <0 0x98d0 0x0 0x10>;
+};
-- 
2.7.0



From narmstrong at baylibre.com  Thu May 26 00:51:50 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 26 May 2016 09:51:50 +0200
Subject: [RFC PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
References: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464249112-13658-2-git-send-email-narmstrong@baylibre.com>

Add watchdog specific driver for Amlogic Meson GXBB SoC.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/watchdog/Makefile         |   1 +
 drivers/watchdog/meson_gxbb_wdt.c | 287 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 288 insertions(+)
 create mode 100644 drivers/watchdog/meson_gxbb_wdt.c

diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 9bde095..7679d93 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
 obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
 obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
 obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
+obj-$(CONFIG_MESON_WATCHDOG) += meson_gxbb_wdt.o
 obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
 obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
 obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
diff --git a/drivers/watchdog/meson_gxbb_wdt.c b/drivers/watchdog/meson_gxbb_wdt.c
new file mode 100644
index 0000000..0c7c0d9
--- /dev/null
+++ b/drivers/watchdog/meson_gxbb_wdt.c
@@ -0,0 +1,287 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+#define DEFAULT_TIMEOUT	10	/* seconds */
+
+#define GXBB_WDT_CTRL_REG	0x0
+#define GXBB_WDT_CTRL1_REG	0x4
+#define GXBB_WDT_TCNT_REG	0x8
+#define GXBB_WDT_RSET_REG	0xc
+
+#define GXBB_WDT_CTRL_EE_RESET_NOW	BIT(26)
+
+#define GXBB_WDT_CTRL_CLKDIV_EN	BIT(25)
+#define GXBB_WDT_CTRL_CLK_EN	BIT(24)
+#define GXBB_WDT_CTRL_IRQ_EN	BIT(23)
+#define GXBB_WDT_CTRL_EE_RESET	BIT(21)
+#define GXBB_WDT_CTRL_XTAL_SEL	(0)
+#define GXBB_WDT_CTRL_CLK81_SEL	BIT(19)
+#define GXBB_WDT_CTRL_EN	BIT(18)
+#define GXBB_WDT_CTRL_DIV_MASK	(BIT(18)-1)
+
+#define GXBB_WDT_CTRL1_GPIO_PULSE	BIT(17)
+#define GXBB_WDT_CTRL1_GPIO_POL_RESET_0	BIT(16)
+#define GXBB_WDT_CTRL1_GPIO_POL_RESET_1	(0)
+#define GXBB_WDT_CTRL1_GPIO_PULSE_CNT	(BIT(16)-1)
+
+#define GXBB_WDT_TCNT_SETUP_MASK	(BIT(16)-1)
+#define GXBB_WDT_TCNT_CNT_SHIFT		16
+
+struct meson_gxbb_wdt {
+	void __iomem *reg_base;
+	struct watchdog_device wdt_dev;
+	struct clk *clk;
+};
+
+int meson_gxbb_wdt_start(struct watchdog_device *wdt_dev)
+{
+	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
+
+	writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) | GXBB_WDT_CTRL_EN,
+		data->reg_base + GXBB_WDT_CTRL_REG);
+
+	return 0;
+}
+
+int meson_gxbb_wdt_stop(struct watchdog_device *wdt_dev)
+{
+	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
+
+	writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) & ~GXBB_WDT_CTRL_EN,
+		data->reg_base + GXBB_WDT_CTRL_REG);
+
+	return 0;
+}
+
+unsigned int meson_gxbb_wdt_status(struct watchdog_device *wdt_dev)
+{
+	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
+
+	return !!(readl(data->reg_base + GXBB_WDT_CTRL_REG) & GXBB_WDT_CTRL_EN);
+}
+
+int meson_gxbb_wdt_ping(struct watchdog_device *wdt_dev)
+{
+	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
+
+	writel(0, data->reg_base + GXBB_WDT_RSET_REG);
+
+	return 0;
+}
+
+int meson_gxbb_wdt_set_timeout(struct watchdog_device *wdt_dev,
+			       unsigned int timeout)
+{
+	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
+
+	if (watchdog_active(wdt_dev))
+		meson_gxbb_wdt_stop(wdt_dev);
+
+	meson_gxbb_wdt_ping(wdt_dev);
+
+	writel(timeout*1000, data->reg_base + GXBB_WDT_TCNT_REG);
+
+	if (watchdog_active(wdt_dev))
+		meson_gxbb_wdt_start(wdt_dev);
+
+	return 0;
+}
+
+unsigned int meson_gxbb_wdt_get_timeleft(struct watchdog_device *wdt_dev)
+{
+	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
+	unsigned long reg;
+
+	reg = readl(data->reg_base + GXBB_WDT_TCNT_REG);
+
+	return ((reg >> GXBB_WDT_TCNT_CNT_SHIFT)-
+			(reg & GXBB_WDT_TCNT_SETUP_MASK)) / 1000;
+}
+
+static const struct watchdog_ops meson_gxbb_wdt_ops = {
+	.start = meson_gxbb_wdt_start,
+	.stop = meson_gxbb_wdt_stop,
+	.status = meson_gxbb_wdt_status,
+	.ping = meson_gxbb_wdt_ping,
+	.set_timeout = meson_gxbb_wdt_set_timeout,
+	.get_timeleft = meson_gxbb_wdt_get_timeleft,
+};
+
+static const struct watchdog_info meson_gxbb_wdt_info = {
+	.identity = "meson-gxbb-wdt",
+	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+};
+
+static int __maybe_unused meson_gxbb_wdt_resume(struct device *dev)
+{
+	struct meson_gxbb_wdt *data = dev_get_drvdata(dev);
+
+	if (watchdog_active(&data->wdt_dev))
+		meson_gxbb_wdt_start(&data->wdt_dev);
+
+	return 0;
+}
+
+static int __maybe_unused meson_gxbb_wdt_suspend(struct device *dev)
+{
+	struct meson_gxbb_wdt *data = dev_get_drvdata(dev);
+
+	if (watchdog_active(&data->wdt_dev))
+		meson_gxbb_wdt_stop(&data->wdt_dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops meson_gxbb_wdt_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(meson_gxbb_wdt_suspend, meson_gxbb_wdt_resume)
+};
+
+static const struct of_device_id meson_gxbb_wdt_dt_ids[] = {
+	 { .compatible = "amlogic,meson-gxbb-wdt", },
+	 { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, meson_gxbb_wdt_dt_ids);
+
+static int meson_gxbb_wdt_probe(struct platform_device *pdev)
+{
+	struct meson_gxbb_wdt *data;
+	struct resource *res;
+	int ret;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(data->reg_base))
+		return PTR_ERR(data->reg_base);
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	clk_prepare_enable(data->clk);
+
+	platform_set_drvdata(pdev, data);
+
+	data->wdt_dev.parent = &pdev->dev;
+	data->wdt_dev.info = &meson_gxbb_wdt_info;
+	data->wdt_dev.ops = &meson_gxbb_wdt_ops;
+	data->wdt_dev.max_hw_heartbeat_ms = GXBB_WDT_TCNT_SETUP_MASK;
+	data->wdt_dev.min_hw_heartbeat_ms = 1;
+	data->wdt_dev.timeout = DEFAULT_TIMEOUT;
+	watchdog_set_drvdata(&data->wdt_dev, data);
+
+	watchdog_init_timeout(&data->wdt_dev, DEFAULT_TIMEOUT, &pdev->dev);
+
+	ret = watchdog_register_device(&data->wdt_dev);
+	if (ret)
+		return ret;
+
+	/* Setup with 1ms timebase */
+	writel(((clk_get_rate(data->clk) / 1000) & GXBB_WDT_CTRL_DIV_MASK) |
+		GXBB_WDT_CTRL_EE_RESET |
+		GXBB_WDT_CTRL_CLK_EN |
+		GXBB_WDT_CTRL_CLKDIV_EN,
+		data->reg_base + GXBB_WDT_CTRL_REG);
+	meson_gxbb_wdt_set_timeout(&data->wdt_dev, data->wdt_dev.timeout);
+	meson_gxbb_wdt_ping(&data->wdt_dev);
+
+	return 0;
+}
+
+static int meson_gxbb_wdt_remove(struct platform_device *pdev)
+{
+	struct meson_gxbb_wdt *data = platform_get_drvdata(pdev);
+
+	watchdog_unregister_device(&data->wdt_dev);
+
+	return 0;
+}
+
+static void meson_gxbb_wdt_shutdown(struct platform_device *pdev)
+{
+	struct meson_gxbb_wdt *data = platform_get_drvdata(pdev);
+
+	meson_gxbb_wdt_stop(&data->wdt_dev);
+}
+
+static struct platform_driver meson_gxbb_wdt_driver = {
+	.probe	= meson_gxbb_wdt_probe,
+	.remove	= meson_gxbb_wdt_remove,
+	.shutdown = meson_gxbb_wdt_shutdown,
+	.driver = {
+		.name = "meson-gxbb-wdt",
+		.pm = &meson_gxbb_wdt_pm_ops,
+		.of_match_table	= meson_gxbb_wdt_dt_ids,
+	},
+};
+
+module_platform_driver(meson_gxbb_wdt_driver);
+
+MODULE_ALIAS("platform:meson-gxbb-wdt");
+MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
+MODULE_DESCRIPTION("Amlogic Meson GXBB Watchdog timer driver");
+MODULE_LICENSE("Dual BSD/GPL");
-- 
2.7.0



From narmstrong at baylibre.com  Thu May 26 00:51:52 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 26 May 2016 09:51:52 +0200
Subject: [RFC PATCH 3/3] ARM64: dts: amlogic: meson-gxbb: Add watchdog node
In-Reply-To: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
References: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464249112-13658-4-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 832815d..bcca82f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -136,6 +136,12 @@
 				clocks = <&xtal>;
 				status = "disabled";
 			};
+
+			watchdog at 98d0 {
+				compatible = "amlogic,meson-gxbb-wdt";
+				reg = <0x0 0x098d0 0x0 0x10>;
+				clocks = <&xtal>;
+			};
 		};
 
 		gic: interrupt-controller at c4301000 {
-- 
2.7.0



From geert at linux-m68k.org  Thu May 26 01:05:01 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Thu, 26 May 2016 10:05:01 +0200
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <5a697ce7-c02a-707c-55b6-6cc209b63b32@de.bosch.com>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
 <20160525004825.GC7292@verge.net.au>
 <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>
 <edee7345-280a-0d7c-7e5a-798215fbd2b9@de.bosch.com>
 <CAMuHMdXnN-GTN4crXeWRvtWT4E2kYFvMdPPcH8z+gJb-B4PbYA@mail.gmail.com>
 <5a697ce7-c02a-707c-55b6-6cc209b63b32@de.bosch.com>
Message-ID: <CAMuHMdW7FacxRFf9VCiYPwR5kUEfBteT3+LBCrzof1cmpLjGDg@mail.gmail.com>

Hi Dirk,

On Thu, May 26, 2016 at 9:32 AM, Dirk Behme <dirk.behme at de.bosch.com> wrote:
> On 26.05.2016 09:03, Geert Uytterhoeven wrote:
>> On Wed, May 25, 2016 at 9:32 AM, Dirk Behme <dirk.behme at de.bosch.com>
>> wrote:
>>> P.S.: This also results in the question why we need similar
>>> r8a7795-cpg-mssr.h and r8a7796-cpg-mssr.h with just different "numbers"
>>> for
>>> the same clocks. Can't we use the same numbers on all SoCs, with just
>>> having
>>> wholes in the list where the clocks don't exist on a SoC? I haven't
>>> looked
>>
>> The CPG and MSSR block are the IP blocks that differ most among SoCs of
>> the
>> same family. Some clocks are present on H3 only, others on M3-W only.
>
> Yes, this is my understanding as well. Is the H3 a superset? And the M3-W
> drops some clocks? Or are there really clocks which are on M3-W only and not
> on H3?

H3 is not a superset.
M3-W e.g. has more S0Dx clocks (for x = 2, 3, 6, 8, 12).

> this
>
> &scif2 {
>         clocks = <&cpg CPG_MOD 310>,
>                  <&cpg CPG_CORE R8A7795_CLK_S3D1>,
>                  <&scif_clk>;
> };
>
> &scif2 {
>         clocks = <&cpg CPG_MOD 310>,
>                  <&cpg CPG_CORE R8A7796_CLK_S3D1>,
>                  <&scif_clk>;
> };
>
> should be done better.

That's a bad example, as both SoCs use S3D1 ;-)

Now look at e.g. i2c:
  - On H3, the parent of the i2c module clock is S3D2,
  - On M3-W, the parent of the i2c module clock is S3D2 for i2c0/1/2,
    and S0D6 for i2c3/4/5/6.

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 alexandre.torgue at gmail.com  Thu May 26 01:05:47 2016
From: alexandre.torgue at gmail.com (Alexandre Torgue)
Date: Thu, 26 May 2016 10:05:47 +0200
Subject: [PATCH RFC 00/10] ARM: V7M: Support caches
In-Reply-To: <1461226702-27160-1-git-send-email-vladimir.murzin@arm.com>
References: <1461226702-27160-1-git-send-email-vladimir.murzin@arm.com>
Message-ID: <5746AE5B.3050407@gmail.com>

Hi Vladimir,

On 04/21/2016 10:18 AM, Vladimir Murzin wrote:
> Hi,
>
> This patch set allows M-class cpus benefit of optional cache support.
> It originaly was written by Jonny, I've been keeping it localy mainly
> rebasing over Linux versions.
>
> The main idea behind patches is to reuse existing cache handling code
> from v7A/R. In case v7M cache operations are provided via memory
> mapped interface rather than co-processor instructions, so extra
> macros have been introduced to factor out cache handling logic and
> low-level operations.
>
> Along with the v7M cache support the first user (Cortex-M7) is
> introduced.
>
> Patches were tested on MPS2 platform with Cortex-M3/M4/M7. The later
> one showed significant boot speed-up.
>


Thanks for the series. Maxime and I have just tested it on STM32F7 hardware.
We found an issue on this M7 chip, which is not linked to your patches 
(see below patch that will be send shortly).
Once fixed, we are able to boot but we observe instabilities which 
disappear when D-cache is disabled from kernel config.
We observe random crashes.
Most of them look like this (hardfault):

(gdb) info reg
r0             0xc018c3fc    -1072118788
r1             0x3e0    992
r2             0x4100000b    1090519051
r3             0x0    0
r4             0x0    0
r5             0xc018c3fc    -1072118788
r6             0xc018c7dc    -1072117796
r7             0xc018c3fc    -1072118788
r8             0xc018bb30    -1072121040
r9             0x3e0    992
r10            0x4100000b    1090519051
r11            0x0    0
r12            0x8303c003    -2096906237
sp             0xc016bed0    0xc016bed0 <init_thread_union+7888>
lr             0xfffffff1    -15
pc             0xc000b6bc    0xc000b6bc <__invalid_entry>
xPSR           0x81000003    -2130706429
(gdb) bt
#0  __invalid_entry () at arch/arm/kernel/entry-v7m.S:24
#1  <signal handler called>
#2  vsnprintf (buf=0xc018c3fc <textbuf> "", size=992, fmt=0x4100000b "", 
args=...) at lib/vsprintf.c:1999
#3  0xc0095910 in vscnprintf (buf=<optimized out>, size=992, 
fmt=<optimized out>, args=...) at lib/vsprintf.c:2152
#4  0xc00269dc in vprintk_emit (facility=0, level=-1, dict=0x0, 
dictlen=<optimized out>, fmt=0x4100000b "", args=...) at 
kernel/printk/printk.c:1673
#5  0xc000a20a in arch_local_irq_enable () at 
./arch/arm/include/asm/irqflags.h:38
#6  arch_cpu_idle () at arch/arm/kernel/process.c:73
#7  0x00000000 in ?? ()

We continue to investigate this issue. If you have any idea, please let 
us know.

Thanks.

alex

Patch which will be sent shortly:


Author: Alexandre TORGUE <alexandre.torgue at gmail.com>
Date:   Wed May 25 14:02:35 2016 +0200

     ARM: V7M: Add dsb before jumping in handler mode

     According to ARM AN321 (section 4.12):

     "If the vector table is in writable memory such as SRAM, either 
relocated
     by VTOR or a device dependent memory remapping mechanism, then
     architecturally a memory barrier instruction is required after the 
vector
     table entry is updated, and if the exception is to be activated 
immediately"

     Signed-off-by: Maxime Coquelin <mcoquelin.stm32 at gmail.com>
     Signed-off-by: Alexandre TORGUE <alexandre.torgue at gmail.com>

diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S
index 60387a0..807949f 100644
--- a/arch/arm/mm/proc-v7m.S
+++ b/arch/arm/mm/proc-v7m.S
@@ -124,6 +124,7 @@ __v7m_setup:
         badr    r1, 1f
         ldr     r5, [r12, #11 * 4]      @ read the SVC vector entry
         str     r1, [r12, #11 * 4]      @ write the temporary SVC 
vector entry
+       dsb
         mov     r6, lr                  @ save LR
         ldr     sp, =init_thread_union + THREAD_START_SP
         cpsie   i



From dirk.behme at de.bosch.com  Thu May 26 01:11:01 2016
From: dirk.behme at de.bosch.com (Dirk Behme)
Date: Thu, 26 May 2016 10:11:01 +0200
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <CAMuHMdW7FacxRFf9VCiYPwR5kUEfBteT3+LBCrzof1cmpLjGDg@mail.gmail.com>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
 <20160525004825.GC7292@verge.net.au>
 <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>
 <edee7345-280a-0d7c-7e5a-798215fbd2b9@de.bosch.com>
 <CAMuHMdXnN-GTN4crXeWRvtWT4E2kYFvMdPPcH8z+gJb-B4PbYA@mail.gmail.com>
 <5a697ce7-c02a-707c-55b6-6cc209b63b32@de.bosch.com>
 <CAMuHMdW7FacxRFf9VCiYPwR5kUEfBteT3+LBCrzof1cmpLjGDg@mail.gmail.com>
Message-ID: <8c0ea32b-b722-62ac-6810-b1239d0de4eb@de.bosch.com>

Hi Geert,

On 26.05.2016 10:05, Geert Uytterhoeven wrote:
> Hi Dirk,
>
> On Thu, May 26, 2016 at 9:32 AM, Dirk Behme <dirk.behme at de.bosch.com> wrote:
>> On 26.05.2016 09:03, Geert Uytterhoeven wrote:
>>> On Wed, May 25, 2016 at 9:32 AM, Dirk Behme <dirk.behme at de.bosch.com>
>>> wrote:
>>>> P.S.: This also results in the question why we need similar
>>>> r8a7795-cpg-mssr.h and r8a7796-cpg-mssr.h with just different "numbers"
>>>> for
>>>> the same clocks. Can't we use the same numbers on all SoCs, with just
>>>> having
>>>> wholes in the list where the clocks don't exist on a SoC? I haven't
>>>> looked
>>>
>>> The CPG and MSSR block are the IP blocks that differ most among SoCs of
>>> the
>>> same family. Some clocks are present on H3 only, others on M3-W only.
>>
>> Yes, this is my understanding as well. Is the H3 a superset? And the M3-W
>> drops some clocks? Or are there really clocks which are on M3-W only and not
>> on H3?
>
> H3 is not a superset.
> M3-W e.g. has more S0Dx clocks (for x = 2, 3, 6, 8, 12).


Ok, thanks!


>> this
>>
>> &scif2 {
>>         clocks = <&cpg CPG_MOD 310>,
>>                  <&cpg CPG_CORE R8A7795_CLK_S3D1>,
>>                  <&scif_clk>;
>> };
>>
>> &scif2 {
>>         clocks = <&cpg CPG_MOD 310>,
>>                  <&cpg CPG_CORE R8A7796_CLK_S3D1>,
>>                  <&scif_clk>;
>> };
>>
>> should be done better.
>
> That's a bad example, as both SoCs use S3D1 ;-)


Then, I'd propose to find a clever way to put the common parts into a 
rcar-gen3.dtsi and ...


> Now look at e.g. i2c:
>   - On H3, the parent of the i2c module clock is S3D2,
>   - On M3-W, the parent of the i2c module clock is S3D2 for i2c0/1/2,
>     and S0D6 for i2c3/4/5/6.


... to keep the differences in the r8a7795.dtsi, r8a7796.dtsi etc.


Best regards

Dirk



From grinberg at compulab.co.il  Thu May 26 01:28:59 2016
From: grinberg at compulab.co.il (Igor Grinberg)
Date: Thu, 26 May 2016 11:28:59 +0300
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <CAOMZO5C5goJUdHKB9a=eOv9TKDkJWxnkWWb-G7E5Kvceg6sZVg@mail.gmail.com>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
 <CAOMZO5C5goJUdHKB9a=eOv9TKDkJWxnkWWb-G7E5Kvceg6sZVg@mail.gmail.com>
Message-ID: <5746B3CB.20804@compulab.co.il>

Hi Fabio,

On 05/23/2016 08:49 PM, Fabio Estevam wrote:
> On Sun, May 22, 2016 at 7:47 PM,  <christopher.spinrath at rwth-aachen.de> wrote:
> 
>> diff --git a/arch/arm/boot/dts/imx6q-utilite-pro.dts b/arch/arm/boot/dts/imx6q-utilite-pro.dts
>> new file mode 100644
>> index 0000000..bcd8e0d
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/imx6q-utilite-pro.dts
>> @@ -0,0 +1,128 @@
>> +/*
>> + * Copyright 2016 Christopher Spinrath
>> + * Copyright 2013 CompuLab Ltd.
>> + *
>> + * Based on the GPLv2 licensed devicetree distributed with the vendor
>> + * kernel for the Utilite Pro:
>> + *     Copyright 2013 CompuLab Ltd.
>> + *     Author: Valentin Raevsky <valentin at compulab.co.il>
>> + *
>> + * The code contained herein is licensed under the GNU General Public
>> + * License. You may obtain a copy of the GNU General Public License
>> + * Version 2 or later at the following locations:
> 
> Can you make this dual GPL/X11 license?
> 
> For reference take a look at:
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/imx6sl-warp.dts?id=refs/tags/v4.6

Please excuse me my ignorance, what is the rationale for this change?

-- 
Regards,
Igor.


From linux at armlinux.org.uk  Thu May 26 01:35:28 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Thu, 26 May 2016 09:35:28 +0100
Subject: [PATCH kexec-tools 01/32] kdump: mmap() and munmap() only work
 on page-aligned quantites
In-Reply-To: <CAHB_GupQcopOR7Qn5Nk0kNvYT_p0AWTzp+vJe87b+BsQTwr1CQ@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXS0-0004gz-5a@e0050434b2927.dyn.arm.linux.org.uk>
 <CAHB_GupQcopOR7Qn5Nk0kNvYT_p0AWTzp+vJe87b+BsQTwr1CQ@mail.gmail.com>
Message-ID: <20160526083528.GE19428@n2100.arm.linux.org.uk>

On Wed, May 25, 2016 at 11:46:08AM +0530, Pratyush Anand wrote:
> On Tue, May 3, 2016 at 3:51 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> > The man page for mmap() and munmap() says that mmap() and munmap()
> > only works for page-aligned addresses, sizes and offsets.  Arrange
> > to give these interfaces what they want.
> >
> 
> If I read correctly, it talks only offsets to be page aligned.

Yes, it's not really needed, but as we have to adjust the size anyway to
compensate for the reduced file offset, it makes little difference whether
we align the size or not.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From linus.walleij at linaro.org  Thu May 26 01:40:43 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 26 May 2016 10:40:43 +0200
Subject: [PATCH 2/2] ARM: dts: am335x-icev2: Add DT node for TI PCA9536
In-Reply-To: <1463640450-16762-3-git-send-email-vigneshr@ti.com>
References: <1463640450-16762-1-git-send-email-vigneshr@ti.com>
 <1463640450-16762-3-git-send-email-vigneshr@ti.com>
Message-ID: <CACRpkdbRt4Vi=kzs_gZDkR14KBmFsKKZawbT25PW0sMpuX7LkQ@mail.gmail.com>

On Thu, May 19, 2016 at 8:47 AM, Vignesh R <vigneshr at ti.com> wrote:

> AM335x ICE board has a TI PCA9536 chip connected to I2C0 at address
> 0x41. Add DT entry for the same.
>
> Signed-off-by: Vignesh R <vigneshr at ti.com>

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

Pls take this through the ARM SoC TI git tree.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Thu May 26 01:42:44 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 26 May 2016 10:42:44 +0200
Subject: [PATCH 1/2] gpio: pca953x: Add support for TI PCA9536
In-Reply-To: <1463640450-16762-2-git-send-email-vigneshr@ti.com>
References: <1463640450-16762-1-git-send-email-vigneshr@ti.com>
 <1463640450-16762-2-git-send-email-vigneshr@ti.com>
Message-ID: <CACRpkdbTC6R4Yevdo-GC+EVyrAw_v3wzSA89gUfKSkv50CskOg@mail.gmail.com>

On Thu, May 19, 2016 at 8:47 AM, Vignesh R <vigneshr at ti.com> wrote:

> TI PCA9536 is 4-Bit I2C GPIO expander without interrupt support[1].
> Add support for the same.
>
> [1] TRM: http://www.ti.com/lit/ds/symlink/pca9536.pdf
>
> Signed-off-by: Vignesh R <vigneshr at ti.com>

Patch applied with Rob's ACK.

Yours,
Linus Walleij


From grinberg at compulab.co.il  Thu May 26 01:50:12 2016
From: grinberg at compulab.co.il (Igor Grinberg)
Date: Thu, 26 May 2016 11:50:12 +0300
Subject: [PATCH 1/2] ARM: dts: imx6q: extend support for the cm-fx6
In-Reply-To: <1463994191.2370.3.camel@pengutronix.de>
References: <709d6b3d522f4fcb8112830e0426dbb3@rwthex-s1-b.rwth-ad.de>
 <1463994191.2370.3.camel@pengutronix.de>
Message-ID: <5746B8C4.6020406@compulab.co.il>

Hi Lucas,

Thanks for reviewing the patch(es).

On 05/23/2016 12:03 PM, Lucas Stach wrote:
> Am Montag, den 23.05.2016, 00:47 +0200 schrieb
> christopher.spinrath at rwth-aachen.de:
>> From: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>

[...]

>> +&ecspi1 {
>> +	fsl,spi-num-chipselects = <2>;
>> +	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
>> +	pinctrl-names = "default";
>> +	pinctrl-0 = <&pinctrl_ecspi1>;
>> +	status = "okay";
>> +
>> +	flash: m25p80 at 0 {
>> +		#address-cells = <1>;
>> +		#size-cells = <1>;
>> +		compatible = "st,m25p", "jedec,spi-nor";
>> +		spi-max-frequency = <20000000>;
>> +		reg = <0>;
>> +
>> +		partition at 0 {
>> +			label = "uboot";
>> +			reg = <0x0 0xc0000>;
>> +		};
>> +
>> +		partition at c0000 {
>> +			label = "uboot environment";
>> +			reg = <0xc0000 0x40000>;
>> +		};
>> +
>> +		partition at 100000 {
>> +			label = "reserved";
>> +			reg = <0x100000 0x100000>;
>> +		};
> 
> Partition layouts don't belong in the upstream DT, as it a device
> configuration thing. Please kep them in the bootloader/firmware and make
> this one pass the partition layout to the kernel.

I don't completely agree with this.
We have lots of partition layouts in the upstream DT.
Moreover, this is the default layout and changing it, will
result in incompatibilities and also might result in device "bricking".
Those can be changed from the boot loader in case you need those
the other way around.
Another question of mine is, why should you?


-- 
Regards,
Igor.


From maxime.ripard at free-electrons.com  Thu May 26 01:53:30 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Thu, 26 May 2016 10:53:30 +0200
Subject: [PATCH 13/20] drm/bridge: Add RGB to VGA bridge support
In-Reply-To: <1773896.kpi58ilqqm@avalon>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-14-git-send-email-maxime.ripard@free-electrons.com>
 <1773896.kpi58ilqqm@avalon>
Message-ID: <20160526085330.GM9232@lukather>

Hi Laurent,

On Mon, May 16, 2016 at 04:24:15PM +0300, Laurent Pinchart wrote:
> Hi Maxime,
> 
> Thank you for the patch.
> 
> On Monday 16 May 2016 14:47:13 Maxime Ripard wrote:
> > Some boards have an entirely passive RGB to VGA bridge, based on either
> > DACs or resistor ladders.
> > 
> > Those might or might not have an i2c bus routed to the VGA connector in
> > order to access the screen EDIDs.
> > 
> > Add a bridge that doesn't do anything but expose the modes available on the
> > screen, either based on the EDIDs if available, or based on the XGA
> > standards.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  .../bindings/display/bridge/dumb-vga.txt           |  40 +++++
> >  drivers/gpu/drm/bridge/Kconfig                     |   6 +
> >  drivers/gpu/drm/bridge/Makefile                    |   1 +
> >  drivers/gpu/drm/bridge/dumb-vga.c                  | 186 ++++++++++++++++++
> >  4 files changed, 233 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/display/bridge/dumb-vga.txt create mode
> > 100644 drivers/gpu/drm/bridge/dumb-vga.c
> > 
> > diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
> > b/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt new file
> > mode 100644
> > index 000000000000..757f04de97f3
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
> > @@ -0,0 +1,40 @@
> > +Passive RGB to VGA bridge
> > +-------------------------
> > +
> > +This binding is aimed for entirely passive RGB to VGA bridges that do not
> > +require any configuration.
> > +
> > +Required properties:
> > +
> > +- compatible: Should be "dumb-vga-bridge"
> > +
> > +Optional properties:
> > +
> > +- ddc-i2c-bus: phandle to the i2c bus used to communicate with the monitor
> > +
> > +Required nodes:
> > +
> > +This device has one video port. Its connection is modelled using the OF
> > +graph bindings specified in Documentation/devicetree/bindings/graph.txt.
> > This +connection is meant to be the RGB input bus.
> 
> Should the bridge have two ports, one input port connected to a display engine 
> and one output port connected to a VGA connector ?

And a separate node for the VGA connector? As far as I can see, all
the other bridges are represented using a single node.

> +static int dumb_vga_get_modes(struct drm_connector *connector)
> > +{
> > +	struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
> > +	struct edid *edid;
> > +	int ret;
> > +
> > +	if (!vga->ddc)
> > +		goto fallback;
> > +
> > +	edid = drm_get_edid(connector, vga->ddc);
> > +	if (!edid) {
> > +		DRM_INFO("EDID readout failed, falling back to standard modes\n");
> > +		goto fallback;
> > +	}
> > +
> > +	drm_mode_connector_update_edid_property(connector, edid);
> > +	return drm_add_edid_modes(connector, edid);
> > +
> > +fallback:
> > +	/*
> > +	 * In case we cannot retrieve the EDIDs (broken or missing i2c
> > +	 * bus), fallback on the XGA standards
> > +	 */
> > +	ret = drm_add_modes_noedid(connector, 1920, 1200);
> 
> The DRM core adds modes up to 1024x768 in 
> drm_helper_probe_single_connector_modes(). I wonder if it really makes sense 
> to override that in drivers, compared to increasing the maximum resolution in 
> the core. What we can reasonable expect from a VGA monitor doesn't really 
> depend on which display engine it is connected to.

Actually, I would expect it to come from the connectors. Nowadays, the
core add modes that might not even be relevant at all for a given
connector. Take TV as an example, there's not a single TV output that
can reach 1024x768, but actually rely on very different resolutions.

> 
> > +	/* And prefer a mode pretty much anyone can handle */
> > +	drm_set_preferred_mode(connector, 1024, 768);
> > +
> > +	return ret;
> > +}
> > +
> > +static struct drm_encoder *
> > +dumb_vga_best_encoder(struct drm_connector *connector)
> > +{
> > +	struct dumb_vga *vga = drm_connector_to_dumb_vga(connector);
> > +
> > +	return vga->bridge.encoder;
> > +}
> > +
> > +static struct drm_connector_helper_funcs dumb_vga_con_helper_funcs = {
> > +	.get_modes	= dumb_vga_get_modes,
> > +	.best_encoder	= dumb_vga_best_encoder,
> > +};
> > +
> > +static enum drm_connector_status
> > +dumb_vga_connector_detect(struct drm_connector *connector, bool force)
> > +{
> > +	return connector_status_connected;
> 
> Shouldn't that be connector_status_unknown if you have no information about 
> the connection status ?

Probably :)

What are the side effects from such a change? Does it change anything
related to how the fbdev emulation and how the rest of the display
stack detects and enables the outputs whose status are unknown?

> Would it make sense to add an optional GPIO-based connection detection to this 
> driver ?

I asked for it in our prototypes, and apparently, doing VGA cable
detection is really non-trivial, so I don't really expect it to be
found in a lot of designs.

I looked at three different designs done by different vendors, and
none of them have it, so I don't really expect anyone to have it, nor
do I have any hardware to test the code with. However, if there's an
i2c bus, we can always try to probe for the edid, and see if we have
an error. If there's none, then we know something is connected. If
there's an error, we can return connector_status_unknown.

On a set of three samples, only one has that i2c bus, so it might be
just a marginal improvement, but still.


> > +}
> > +
> > +static void
> > +dumb_vga_connector_destroy(struct drm_connector *connector)
> > +{
> > +	drm_connector_cleanup(connector);
> > +}
> > +
> > +static struct drm_connector_funcs dumb_vga_con_funcs = {
> > +	.dpms			= drm_atomic_helper_connector_dpms,
> > +	.detect			= dumb_vga_connector_detect,
> > +	.fill_modes		= drm_helper_probe_single_connector_modes,
> > +	.destroy		= dumb_vga_connector_destroy,
> > +	.reset			= drm_atomic_helper_connector_reset,
> > +	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
> > +	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
> > +};
> > +
> > +static int dumb_vga_attach(struct drm_bridge *bridge)
> > +{
> > +	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
> > +	int ret;
> > +
> > +	if (!bridge->encoder) {
> > +		DRM_ERROR("Missing encoder\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	drm_connector_helper_add(&vga->connector,
> > +				 &dumb_vga_con_helper_funcs);
> > +	ret = drm_connector_init(bridge->dev, &vga->connector,
> > +				 &dumb_vga_con_funcs, DRM_MODE_CONNECTOR_VGA);
> > +	if (ret) {
> > +		DRM_ERROR("Failed to initialize connector\n");
> > +		return ret;
> > +	}
> > +
> > +	drm_mode_connector_attach_encoder(&vga->connector,
> > +					  bridge->encoder);
> > +
> > +	return 0;
> > +}
> > +
> > +static void dumb_vga_nop(struct drm_bridge *bridge) {};
> > +
> > +static struct drm_bridge_funcs dumb_vga_bridge_funcs = {
> > +	.attach		= dumb_vga_attach,
> > +	.enable		= dumb_vga_nop,
> > +	.disable	= dumb_vga_nop,
> > +	.pre_enable	= dumb_vga_nop,
> > +	.post_disable	= dumb_vga_nop,
> > +};
> > +
> > +static int dumb_vga_probe(struct platform_device *pdev)
> > +{
> > +	struct dumb_vga *vga;
> > +	struct device_node *ddc;
> > +
> > +	vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL);
> > +	if (!vga)
> > +		return -ENOMEM;
> > +	platform_set_drvdata(pdev, vga);
> > +
> > +	ddc = of_parse_phandle(pdev->dev.of_node, "ddc-i2c-bus", 0);
> > +	if (ddc) {
> > +		vga->ddc = of_find_i2c_adapter_by_node(ddc);
> 
> You're leaking the reference to the I2C adapter.
> 
> Also, shouldn't you use of_get_i2c_adapter_by_node() ? Otherwise you won't 
> take a reference to the adapter module.

Indeed, I'll fix it.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160526/985ae173/attachment.sig>

From linux at armlinux.org.uk  Thu May 26 01:56:38 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Thu, 26 May 2016 09:56:38 +0100
Subject: [PATCH kexec-tools 12/32] kexec: add helper to exlude a region
 from a set of memory ranges
In-Reply-To: <CAHB_Guo_ozXhAnkGk_NrdBME2fSYDoKTHwu3kLBvsrmbwxOdww@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSv-0004i3-Gi@e0050434b2927.dyn.arm.linux.org.uk>
 <CAHB_Guo_ozXhAnkGk_NrdBME2fSYDoKTHwu3kLBvsrmbwxOdww@mail.gmail.com>
Message-ID: <20160526085638.GF19428@n2100.arm.linux.org.uk>

On Wed, May 25, 2016 at 01:30:44PM +0530, Pratyush Anand wrote:
> On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> > +int mem_regions_exclude(struct memory_ranges *ranges,
> > +                       const struct memory_range *range)
> > +{
> > +       int i;
> > +
> > +       for (i = 0; i < ranges->size; i++) {
> > +               struct memory_range *r = ranges->ranges + i;
> > +
> > +               /*
> > +                * We assume that crash area is fully contained in
> > +                * some larger memory area.
> > +                */
> > +               if (r->start <= range->start && r->end >= range->end) {
> > +                       if (r->start == range->start) {
> > +                               /* Shrink the start of this memory range */
> > +                               r->start = range->end + 1;
> > +                       } else if (r->end == range->end) {
> > +                               /* Shrink the end of this memory range */
> > +                               r->end = range->start - 1;
> 
> What if r->start == range->start) && (r->end == range->end)?

I suppose that could happen, so what about this patch on top (untested).
This isn't something I'd be able to test on real hardware, it needs a
separate test-suite to be written to do modular testing...

 kexec/mem_regions.c | 94 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 55 insertions(+), 39 deletions(-)

diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c
index c6ba942..4e7061b 100644
--- a/kexec/mem_regions.c
+++ b/kexec/mem_regions.c
@@ -29,6 +29,50 @@ void mem_regions_sort(struct memory_ranges *ranges)
 }
 
 /**
+ * mem_regions_add() - add a memory region to a set of ranges
+ * @ranges: ranges to add the memory region to
+ * @max: maximum number of entries in memory region
+ * @base: base address of memory region
+ * @length: length of memory region in bytes
+ * @type: type of memory region
+ *
+ * Add the memory region to the set of ranges, and return %0 if successful,
+ * or %-1 if we ran out of space.
+ */
+int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
+                    unsigned long long length, int type)
+{
+	struct memory_range *range;
+
+	if (ranges->size >= ranges->max_size)
+		return -1;
+
+	range = ranges->ranges + ranges->size++;
+	range->start = base;
+	range->end = base + length - 1;
+	range->type = type;
+
+	return 0;
+}
+
+static void mem_regions_remove(struct memory_ranges *ranges, int index)
+{
+	int tail_entries;
+
+	/* we are assured to have at least one entry */
+	ranges->size -= 1;
+
+	/* if we have following entries, shuffle them down one place */
+	tail_entries = ranges->size - index;
+	if (tail_entries)
+		memmove(ranges->ranges + index, ranges->ranges + index + 1,
+			tail_entries * sizeof(*ranges->ranges));
+
+	/* zero the new tail entry */
+	memset(ranges->ranges + ranges->size, 0, sizeof(*ranges->ranges));
+}
+
+/**
  * mem_regions_exclude() - excludes a memory region from a set of memory ranges
  * @ranges: memory ranges to exclude the region from
  * @range: memory range to exclude
@@ -40,7 +84,7 @@ void mem_regions_sort(struct memory_ranges *ranges)
 int mem_regions_exclude(struct memory_ranges *ranges,
 			const struct memory_range *range)
 {
-	int i;
+	int i, ret;
 
 	for (i = 0; i < ranges->size; i++) {
 		struct memory_range *r = ranges->ranges + i;
@@ -51,25 +95,25 @@ int mem_regions_exclude(struct memory_ranges *ranges,
 		 */
 		if (r->start <= range->start && r->end >= range->end) {
 			if (r->start == range->start) {
-				/* Shrink the start of this memory range */
-				r->start = range->end + 1;
+				if (r->end == range->end)
+					/* Remove this entry */
+					mem_regions_remove(ranges, i);
+				else
+					/* Shrink the start of this memory range */
+					r->start = range->end + 1;
 			} else if (r->end == range->end) {
 				/* Shrink the end of this memory range */
 				r->end = range->start - 1;
 			} else {
-				struct memory_range *new;
-
 				/*
 				 * Split this area into 2 smaller ones and
 				 * remove excluded range from between. First
 				 * create new entry for the remaining area.
 				 */
-				if (ranges->size >= ranges->max_size)
-					return -1;
-
-				new = ranges->ranges + ranges->size++;
-				new->start = range->end + 1;
-				new->end = r->end;
+				ret = mem_regions_add(ranges, range->end + 1,
+						      r->end, 0);
+				if (ret < 0)
+					return ret;
 
 				/*
 				 * Update this area to end before excluded
@@ -82,31 +126,3 @@ int mem_regions_exclude(struct memory_ranges *ranges,
 	}
 	return 0;
 }
-
-/**
- * mem_regions_add() - add a memory region to a set of ranges
- * @ranges: ranges to add the memory region to
- * @max: maximum number of entries in memory region
- * @base: base address of memory region
- * @length: length of memory region in bytes
- * @type: type of memory region
- *
- * Add the memory region to the set of ranges, and return %0 if successful,
- * or %-1 if we ran out of space.
- */
-int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
-                    unsigned long long length, int type)
-{
-	struct memory_range *range;
-
-	if (ranges->size >= ranges->max_size)
-		return -1;
-
-	range = ranges->ranges + ranges->size++;
-	range->start = base;
-	range->end = base + length - 1;
-	range->type = type;
-
-	return 0;
-}
-


-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From zhengxing at rock-chips.com  Thu May 26 02:04:39 2016
From: zhengxing at rock-chips.com (Xing Zheng)
Date: Thu, 26 May 2016 17:04:39 +0800
Subject: [RESEND PATCH v2] ASoC: rockchip: Add machine driver for
 MAX98357A/RT5514/DA7219
In-Reply-To: <20160525173246.GA5125@rob-hp-laptop>
References: <1464053774-15914-1-git-send-email-zhengxing@rock-chips.com>
 <20160525173246.GA5125@rob-hp-laptop>
Message-ID: <5746BC27.1030008@rock-chips.com>

Hi Rob,

On 2016?05?26? 01:32, Rob Herring wrote:
> On Tue, May 24, 2016 at 09:36:14AM +0800, Xing Zheng wrote:
>> There are multi codec devices on the RK3399 platform, we can use
>> this patch support and control these codecs.
>>
>> Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
>> ---
>>
>> Changes in v2:
>> - use the FS 256 to set mclks of the max98357a and rt5514 danamically
>> - add more sample rate for da7219
>>
>>   .../sound/rockchip-max98357a-rt5514-da7219.txt     |   15 +
>>   sound/soc/rockchip/Kconfig                         |   11 +
>>   sound/soc/rockchip/Makefile                        |    2 +
>>   .../rockchip/rockchip_max98357a_rt5514_da7219.c    |  333 ++++++++++++++++++++
>>   4 files changed, 361 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
>>   create mode 100644 sound/soc/rockchip/rockchip_max98357a_rt5514_da7219.c
>>
>> diff --git a/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt b/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
>> new file mode 100644
>> index 0000000..5928384
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/sound/rockchip-max98357a-rt5514-da7219.txt
>> @@ -0,0 +1,15 @@
>> +ROCKCHIP with MAX98357A/RT5514/DA7219 codecs
>> +
>> +Required properties:
>> +- compatible: "rockchip,rockchip-sound"
> This is generic, but the binding seems to be very specific to only 3
> specific codecs. Listing all 3 codecs seems a bit strange. Perhaps a
> name related to the board name would be better.
Yes, I think that I should rename to rk3399_max98357a_rt5514_da7219.c, 
it is related to the rk3399 boards.
>> +- rockchip,cpu: The phandle of the Rockchip I2S controller that's
>> +  connected to the codecs
> What's the size? always 3?
Not always 3, the size is limited by machine driver, The similar 
approach with mt8173-rt5650-rt5676.txt.
>> +- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs
> Please make the size and ordering clear.
Ditto.

Thanks.

-- 
- Xing Zheng




From linus.walleij at linaro.org  Thu May 26 02:06:48 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 26 May 2016 11:06:48 +0200
Subject: [PATCH v3] gpio: UniPhier: add driver for UniPhier GPIO controller
In-Reply-To: <CAK7LNAQcfrvuG6fD+gN2Ojq4wzCSNa=qpr5kh2QSFJZMCA2UaQ@mail.gmail.com>
References: <1436841787-7734-1-git-send-email-yamada.masahiro@socionext.com>
 <CACRpkdYaAMw5U3pctf96j0QpY2Qf+e=LX740F0okCmVU6pXkhA@mail.gmail.com>
 <CAK7LNAQ+_ynWT944fPZsHCzMBLtfNu5AnppzaOxNgPSBTvj_tw@mail.gmail.com>
 <CACRpkdZK41P-1JQsL6RiywqFEUj6=g5xJMKy86wDdp6BxLJNzQ@mail.gmail.com>
 <CAK7LNASd9z99RBmUgLVEM1WuLNSzGFM8qzrHwDf58tgGDy2SAw@mail.gmail.com>
 <CACRpkdbBfidn_otxzSV-8HMv2AuD-htUbcRHZ8n9CHAUO=TB9w@mail.gmail.com>
 <CAK7LNAQH+Ge61+MJo2rLmjCBJRnYviT3LyCo0nrOPRQL+RtK2g@mail.gmail.com>
 <CAK7LNAQcfrvuG6fD+gN2Ojq4wzCSNa=qpr5kh2QSFJZMCA2UaQ@mail.gmail.com>
Message-ID: <CACRpkdYn3WWAKeKa0dUjXg3QtMYdTrysGGK3aND5VwBH=NPqTA@mail.gmail.com>

On Fri, May 20, 2016 at 6:30 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> So, I'd like to know the recommended driver coding style
> based on 4.7-rc1.

Sure, best is to look at other recently added drivers
I guess.

> Diving into the git-log so far, I came up the following list:
>
> [1] The "dev" member of gpiochip was renamed to "parent"

Yes.

> [2] The most recommended register function is now
>     devm_gpiochip_add_data()

Yes, saves some code.

> [3] Pass the driver private data to the
>     3rd argument of devm_gpiochip_add_data().

Yes.

> [4] Do not use container_of() to covert
>     from gpiochip to driver private data.
>     Instead, gpiochip_get_data() should be used.

Yes.

>     (I used of_mm_gpio_chip in v3,
>      but I needed to use container_of() to
>      convert from gpiochip to of_mm_gpio_chip.
>      I am wondering if you are happy with it or not.)

We will see when we look at the code ;)
I guess it is OK. The alternative is to use gpio-generic instead,
see commit 42178e2a1e42b480ada954750f248b53d3fb5940
"drivers/gpio: Switch gpio-mpc8xxx to use gpio-generic"
for an example of that approach.

> [5] gpiochip.owner is being deprecated.
>     So, platform drivers need not set
>      "gpiochip.owner =  THIS_MODULE".

Yes.

> Correct?

Yes.

> Is there anything else missing?

I advice to add a .get_direction() callback if possible and
also .set_single_ended() if the GPIO chip supports open
drain / open source in hardware.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Thu May 26 02:08:42 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 26 May 2016 11:08:42 +0200
Subject: [PATCH] pinctrl: samsung: Suppress unbinding to prevent
 theoretical attacks
In-Reply-To: <1463464926-17482-1-git-send-email-k.kozlowski@samsung.com>
References: <1463464926-17482-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <CACRpkdYdo5XsJvb9GTYph7P=u31treiDX6HZGbG_AGzW5hp1HQ@mail.gmail.com>

On Tue, May 17, 2016 at 8:02 AM, Krzysztof Kozlowski
<k.kozlowski at samsung.com> wrote:

> Although unbinding a pinctrl driver requires root privileges but it
> still might be used theoretically in certain attacks (by triggering NULL
> pointer exception or memory corruption).

Patch applied with Javier's review tag.

I suspect this kind of patch should be done to a few
GPIO controller :/

Yours,
Linus Walleij


From pankaj.dubey at samsung.com  Thu May 26 02:10:44 2016
From: pankaj.dubey at samsung.com (pankaj.dubey)
Date: Thu, 26 May 2016 14:40:44 +0530
Subject: ARM: dts: exynos: Add MFC memory banks for Peach boards
In-Reply-To: <476edff1-9f3e-fc5b-4385-d04ae917b58e@osg.samsung.com>
References: <1461871311-18344-1-git-send-email-javier@osg.samsung.com>
 <57456344.7020708@samsung.com>
 <d045b880-4a44-acd8-f7f6-e521caf374aa@osg.samsung.com>
 <574670E7.3060508@samsung.com>
 <476edff1-9f3e-fc5b-4385-d04ae917b58e@osg.samsung.com>
Message-ID: <5746BD94.3070903@samsung.com>

Hi Javier,

On Thursday 26 May 2016 01:15 PM, Javier Martinez Canillas wrote:
> [adding Kevin and Sjoerd who also noticed issues with this patch]
> 
> Hi Pankaj,
> 
> On 05/25/2016 11:43 PM, pankaj.dubey wrote:
>> Hi Javier,
>>
>> On Wednesday 25 May 2016 08:32 PM, Javier Martinez Canillas wrote:
>>> Hello Pankaj,
>>>
>>> On 05/25/2016 04:33 AM, pankaj.dubey wrote:
>>>> Hi Javier,
>>>>
>>>>> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
>>>>
>>>> Just noticed that, current krzk/for-next failed to boot on Exynos5880
>>>> based Chromebook device. Git bisect is showing culprit as this patch.
>>>
>>> Strange, krzk/for-next boots correctly on my Exynos5800 Peach Pi:
>>>
>>> $ git log --pretty=oneline --abbrev-commit HEAD
>>> 35e691cf5165 Merge branch 'fixes-v4.7' into for-next
>>>
>>
>> This is same as mine.
>>
>> My other build parameters are:
>> defconfig: exynos_defconfig
>> CROSS_COMPILE: gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux
> 
> I'm also using exynos_defconfig and a similar compiler
> (gcc-linaro-arm-linux-gnueabihf-4.9-2015.01-3).
> 
>> rootfs: small cramfs
>>
>>> $ uname -r
>>> 4.6.0-00073-g35e691cf5165
>>>
>>>> When I reverted this patch, its able to boot normally.
>>>> Is there any missing patches that we need to take on krzk/for-next to
>>>> boot on Chromebook.
>>>>
>>>
>>
>> Further I checked that, either I revert this patch OR do not reserve
>> memory for MFC in exynos_reserve using following changes, both cases I
>> am able to boot kernel on Chromebook (Exynos5800).
>>
>> diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
>> index f977eea..e615e24 100644
>> --- a/arch/arm/mach-exynos/exynos.c
>> +++ b/arch/arm/mach-exynos/exynos.c
>> @@ -268,7 +268,7 @@ static char const *const exynos_dt_compat[]
>> __initconst = {
>>
>>  static void __init exynos_reserve(void)
>>  {
>> -#ifdef CONFIG_S5P_DEV_MFC
>> +#ifndef CONFIG_S5P_DEV_MFC
>>         int i;
>>         char *mfc_mem[] = {
>>                 "samsung,mfc-v5",
>> @@ -280,6 +280,8 @@ static void __init exynos_reserve(void)
>>         for (i = 0; i < ARRAY_SIZE(mfc_mem); i++)
>>                 if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i]))
>>                         break;
>> +#else
>> +       pr_err("*****exynos_reserve Bypassing Memory Reservation for MFC
>> ********\n");
>>  #endif
>>  }
>>
>>
>>> No that I'm aware of. I wonder why it boots for me but fails for
>>> you. Can you please share your complete boot log to see if there
>>> are any hints there?
>>>  
>>
>> Following is failed boot log:
>> U-Boot 2013.04-g8e3e5ef (May 26 2015 - 16:11:36) for Peach
>>
>> CPU:    Exynos5422 at 900MHz
>>
>> Board: Google Peach Pi, rev 11.6
>> I2C:   ready
>> DRAM:  3.5 GiB
>> Relocation Offset dbd54000, base at ffb54000
>> SPL stack at 2072c00, used 3f0, free 10
>> PMIC max77802-pmic initialized
>> CPU:    Exynos5422 at 1800MHz
>> TPS65090 PMIC EC init
>> MMC:   EXYNOS DWMMC: 0, EXYNOS DWMMC: 1
>> SF: Detected W25Q32DW with page size 4 KiB, total 32 MiB
>> In:    cros-ec-keyb
>> Out:   lcd
>> Err:   lcd
>> SF: Detected W25Q32DW with page size 4 KiB, total 32 MiB
>> ELOG: Event(17) added with size 13
>> Net:   No ethernet found.
>> Hit any key to stop autoboot:  0
>> mmc1 is current device
>> 4586144 bytes read in 242 ms (18.1 MiB/s)
>> 26583040 bytes read in 1166 ms (21.7 MiB/s)
>> ## Loading kernel from FIT Image at 20008000 ...
>>    Using 'conf at 2' configuration
>>    Trying 'kernel at 1' kernel subimage
>>      Description:  unavailable
>>      Type:         Kernel Image (no loading done)
>>      Compression:  uncompressed
>>      Data Start:   0x200080c8
>>      Data Size:    4459024 Bytes = 4.3 MiB
>>    Verifying Hash Integrity ... OK
>> ## Loading fdt from FIT Image at 20008000 ...
> 
> A difference I see is that I'm chain loading a non-verified u-boot and you
> are loading a signed FIT image directly. But Sjoerd also chain loads a nv
> u-boot and his Peach doesn't boot either so I don't think that's a cause.
> 
>>    Using 'conf at 2' configuration
>>    Trying 'fdt at 2' fdt subimage
>>      Description:  exynos5800-peach-pi.dtb
>>      Type:         Flat Device Tree
>>      Compression:  uncompressed
>>      Data Start:   0x20458148
>>      Data Size:    63002 Bytes = 61.5 KiB
>>      Architecture: ARM
>>      Hash algo:    sha1
>>      Hash value:   cd1c1703f744b44b1833ca61ec36b625665548de
>>    Verifying Hash Integrity ... sha1+ OK
>>    Booting using the fdt blob at 0x20458148
>>    XIP Kernel Image (no loading done) ... OK
>>    Loading Device Tree to 3ffe1000, end 3ffffb49 ... OK
>> boot_kernel.c: ft_board_setup: warning: Must pass exactly one of vboot
>> or cdata
>>
>> Starting kernel ...
>>
>> Timer summary in microseconds:
>>        Mark    Elapsed  Stage
>>           0          0  reset
>>     122,793    122,793  board_init_f
>>     143,214     20,421  board_init_r
>>     238,069     94,855  id=64
>>     240,278      2,209  main_loop
>>   4,841,682  4,601,404  bootm_start
>>   4,841,683          1  id=1
>>   4,846,604      4,921  id=100
>>   4,846,607          3  id=101
>>   4,846,607          0  id=102
>>   4,850,208      3,601  id=110
>>   4,877,729     27,521  id=105
>>   4,877,731          2  id=106
>>   4,877,734          3  id=107
>>   4,877,735          1  id=108
>>   4,877,736          1  id=109
>>   4,882,406      4,670  id=90
>>   4,882,408          2  id=92
>>   4,882,408          0  id=91
>>   4,927,272     44,864  id=95
>>   4,927,274          2  id=96
>>   4,927,276          2  id=97
>>   4,927,277          1  id=98
>>   4,927,279          2  id=99
>>   4,937,617     10,338  id=7
>>   4,951,899     14,282  id=15
>>   4,955,112      3,213  start_kernel
>>
>> Accumulated time:
>>                  6,948  SPI read
>> Uncompressing Linux... done, booting the kernel.
>> [    0.000000] Booting Linux on physical CPU 0x0
>> [    0.000000] Linux version 4.6.0-00073-g35e691c
>> (pankaj at chromebld-server) (gcc version 4.9.2 20140904 (prerelease)
>> (crosstool-NG linaro-1.13.1-4.9-2014.09 - Linaro GCC
>> 4.9-2014.09) ) #59 SMP PREEMPT Thu May 26 08:21:07 IST 2016
>> [    0.000000] CPU: ARMv7 Processor [412fc0f3] revision 3 (ARMv7),
>> cr=10c5387d
>> [    0.000000] CPU: div instructions available: patching division code
>> [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction
>> cache
>> [    0.000000] Machine model: Google Peach Pi Rev 10+
>> [    0.000000] bootconsole [earlycon0] enabled
>> [    0.000000] cma: Reserved 64 MiB at 0xfbc00000
>> [    0.000000] Memory policy: Data cache writealloc
>> [    0.000000] Samsung CPU ID: 0xe5422001
>> [    0.000000] On node 0 totalpages: 913407
>> [    0.000000] free_area_init_node: node 0, pgdat c0b42cc0, node_mem_map
>> ee3f7000
>> [    0.000000]   Normal zone: 1536 pages used for memmap
>> [    0.000000]   Normal zone: 0 pages reserved
>> [    0.000000]   Normal zone: 194560 pages, LIFO batch:31
>> [    0.000000]   HighMem zone: 718847 pages, LIFO batch:31
>> [    0.000000] percpu: Embedded 12 pages/cpu @ee341000 s19392 r8192
>> d21568 u49152
>> [    0.000000] pcpu-alloc: s19392 r8192 d21568 u49152 alloc=12*4096
>> [    0.000000] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3 [0] 4 [0] 5 [0] 6 [0] 7
>> [    0.000000] Built 1 zonelists in Zone order, mobility grouping on.
>> Total pages: 911871
>> [    0.000000] Kernel command line: cros_legacy console=ttySAC3,115200
>> debug earlyprintk cros_debug no_console_suspend root=/dev/ram0 rw
>> ramdisk=32768 initrd=0x42000000,3
>> 2M
> 
> I see that you are loading an initrd at 0x42000000 with size of 32 MiB.
> 
> [...]
> 
>> [    1.121421] Trying to unpack rootfs image as initramfs...
>> [    1.126940] rootfs image is not initramfs (junk in compressed
>> archive); looks like an initrd
>> [    1.160139] Unable to handle kernel paging request at virtual address
>> e3000000
> 
> So I wonder if the problem is that the memblock_remove() is called very
> early and so the kernel is not able to copy the initrd from 0x42000000
> to 0x44000000 since overlaps with the mfc-r mem (0x43000000-0x43800000).
> 
> Specially since the NULL pointer dereference below happens in the
> populate_rootfs() function when calling xwrite() to do the copy.
> 
> Could you please try to change the load address for your initrd, or
> change the mfc-r start address to see if that prevents the issue?
> 

Yes, you are correct. This was the case.
I changed initrd location from 0x42000000 to 0x44000000, and it is able
to boot without any crash.

Thanks,
Pankaj Dubey


From marc.zyngier at arm.com  Thu May 26 02:10:31 2016
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 26 May 2016 10:10:31 +0100
Subject: [PATCH v4 06/12] KVM: arm64: implement basic ITS register handlers
In-Reply-To: <671b7144-7929-df7b-14f4-20dc6a32abdb@arm.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-7-git-send-email-andre.przywara@arm.com>
 <5706704C.5060307@arm.com> <671b7144-7929-df7b-14f4-20dc6a32abdb@arm.com>
Message-ID: <5746BD87.9060206@arm.com>

On 25/05/16 12:37, Andre Przywara wrote:
> Hi Marc,
> 
> this series is mostly obsolete now, but I wanted to elaborate on the
> locking scheme, which hasn't changed.
> 
> On 07/04/16 15:35, Marc Zyngier wrote:
>> On 26/03/16 02:14, Andre Przywara wrote:
> 
> ....
> 
>>> --- a/virt/kvm/arm/vgic/its-emul.c
>>> +++ b/virt/kvm/arm/vgic/its-emul.c
>>> @@ -31,23 +31,263 @@
>>>  #include "vgic.h"
>>>  #include "vgic_mmio.h"
>>>  
>>> +#define BASER_BASE_ADDRESS(x) ((x) & 0xfffffffff000ULL)
>>> +
>>> +static int vgic_mmio_read_its_ctlr(struct kvm_vcpu *vcpu,
>>> +				   struct kvm_io_device *this,
>>> +				   gpa_t addr, int len, void *val)
>>> +{
>>> +	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>>> +	u32 reg;
>>> +
>>> +	reg = GITS_CTLR_QUIESCENT;
>>
>> So your ITS is always in a quiescent state? Even when you're processing
>> the command queue? You'll have to convince me...
> 
> Does QUIESCENT actually cover the command queue status? I was under the
> impression that this is purely to cope with distributed implementations
> and the possible delays caused by propagating commands.

Here's what the spec says:

"For the ITS to be quiescent, there must be no transactions in progress.
In addition, all operations required to ensure that mapping data is
consistent with external memory must be complete."

How can you enforce consistency if you have command in progress?

> If not so, I can surely take the lock here and respect
> (creadr == cwriter) upon setting the bit.

Please do.

> 
>>
>>> +	if (its->enabled)
>>> +		reg |= GITS_CTLR_ENABLE;
>>> +
>>> +	write_mask32(reg, addr & 3, len, val);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int vgic_mmio_write_its_ctlr(struct kvm_vcpu *vcpu,
>>> +				    struct kvm_io_device *this,
>>> +				    gpa_t addr, int len, const void *val)
>>> +{
>>> +	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>>> +	struct vgic_io_device *iodev = container_of(this,
>>> +						    struct vgic_io_device, dev);
>>> +
>>> +        if (addr - iodev->base_addr == 0)
>>
>> whitespace issue.
>>
>>> +		its->enabled = !!(*(u8*)val & GITS_CTLR_ENABLE);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int vgic_mmio_read_its_typer(struct kvm_vcpu *vcpu,
>>> +				    struct kvm_io_device *this,
>>> +				    gpa_t addr, int len, void *val)
>>> +{
>>> +	u64 reg = GITS_TYPER_PLPIS;
>>> +
>>> +	/*
>>> +	 * We use linear CPU numbers for redistributor addressing,
>>> +	 * so GITS_TYPER.PTA is 0.
>>> +	 * To avoid memory waste on the guest side, we keep the
>>> +	 * number of IDBits and DevBits low for the time being.
>>> +	 * This could later be made configurable by userland.
>>> +	 * Since we have all collections in linked list, we claim
>>> +	 * that we can hold all of the collection tables in our
>>> +	 * own memory and that the ITT entry size is 1 byte (the
>>> +	 * smallest possible one).
>>
>> All of this is going to bite us when we want to implement migration,
>> specially the HW collection bit.
> 
> How so? Clearly we keep the number of VCPUs constant, so everything
> guest visible stays the same even upon migrating to a much different
> host? Or are we talking about different things here?

Let me rephrase this: How are you going to address HW collections from
userspace in order to dump them? Short of having memory tables, you cannot.

> 
>>
>>> +	 */
>>> +	reg |= 0xff << GITS_TYPER_HWCOLLCNT_SHIFT;
>>> +	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
>>> +	reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
>>> +
>>> +	write_mask64(reg, addr & 7, len, val);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int vgic_mmio_read_its_iidr(struct kvm_vcpu *vcpu,
>>> +				   struct kvm_io_device *this,
>>> +				   gpa_t addr, int len, void *val)
>>> +{
>>> +	u32 reg = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
>>> +
>>> +	write_mask32(reg, addr & 3, len, val);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int vgic_mmio_read_its_idregs(struct kvm_vcpu *vcpu,
>>> +				     struct kvm_io_device *this,
>>> +				     gpa_t addr, int len, void *val)
>>> +{
>>> +	struct vgic_io_device *iodev = container_of(this,
>>> +						    struct vgic_io_device, dev);
>>> +	u32 reg = 0;
>>> +	int idreg = (addr & ~3) - iodev->base_addr + GITS_IDREGS_BASE;
>>> +
>>> +	switch (idreg) {
>>> +	case GITS_PIDR2:
>>> +		reg = GIC_PIDR2_ARCH_GICv3;
>>
>> Are we leaving the lowest 4 bits to zero?
> 
> I couldn't stuff "42" in 4 bits, so: yes ;-)

The 4 bottom bits are "Implementation Defined", so you could fit
something in it if you wanted.

> 
>>> +		break;
>>> +	case GITS_PIDR4:
>>> +		/* This is a 64K software visible page */
>>> +		reg = 0x40;
>>
>> Same question.
>>
>> Also, how about all the others PIDR registers?
> 
> I guess I was halfway undecided between going with the pure
> architectural requirements (which only mandate bits 7:4 in PIDR2) and
> complying with the recommendation later in the spec.
> So I will just fill PIDR0, PIDR2 and the rest of PIDR2 as well.
> 
>>> +		break;
>>> +	/* Those are the ID registers for (any) GIC. */
>>> +	case GITS_CIDR0:
>>> +		reg = 0x0d;
>>> +		break;
>>> +	case GITS_CIDR1:
>>> +		reg = 0xf0;
>>> +		break;
>>> +	case GITS_CIDR2:
>>> +		reg = 0x05;
>>> +		break;
>>> +	case GITS_CIDR3:
>>> +		reg = 0xb1;
>>> +		break;
>>> +	}
>>
>> Given that these values are directly taken from the architecture, and
>> seem common to the whole GICv3 architecture when implemented by ARM, we
>> could have a common handler for the whole GICv3 implementatuin. Not a
>> bit deal though.
> 
> Agreed.
> 
>>> +
>>> +	write_mask32(reg, addr & 3, len, val);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +/*
>>> + * This function is called with both the ITS and the distributor lock dropped,
>>> + * so the actual command handlers must take the respective locks when needed.
>>> + */
>>> +static int vits_handle_command(struct kvm_vcpu *vcpu, u64 *its_cmd)
>>> +{
>>> +	return -ENODEV;
>>> +}
>>> +
>>> +static int vgic_mmio_read_its_cbaser(struct kvm_vcpu *vcpu,
>>> +				    struct kvm_io_device *this,
>>> +				    gpa_t addr, int len, void *val)
>>> +{
>>> +	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>>> +
>>> +	write_mask64(its->cbaser, addr & 7, len, val);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int vgic_mmio_write_its_cbaser(struct kvm_vcpu *vcpu,
>>> +				      struct kvm_io_device *this,
>>> +				      gpa_t addr, int len, const void *val)
>>> +{
>>> +	struct vgic_its *its = &vcpu->kvm->arch.vgic.its;
>>> +
>>> +	if (its->enabled)
>>> +		return 0;
>>> +
>>> +	its->cbaser = mask64(its->cbaser, addr & 7, len, val);
>>> +	its->creadr = 0;
>>
>> Don't you need to acquire the command queue lock here?
> 
> I don't think so, because we "return 0;" above if the ITS is enabled,
> which means that nothing is going on at the moment.

What would prevent the ITS from becoming enabled between the two
assignments?

> But I guess I can just take the lock anyway to be sure.

I don't think this is optional.

>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int its_cmd_buffer_size(struct kvm *kvm)
>>> +{
>>> +	struct vgic_its *its = &kvm->arch.vgic.its;
>>> +
>>> +	return ((its->cbaser & 0xff) + 1) << 12;
>>> +}
>>> +
>>> +static gpa_t its_cmd_buffer_base(struct kvm *kvm)
>>> +{
>>> +	struct vgic_its *its = &kvm->arch.vgic.its;
>>> +
>>> +	return BASER_BASE_ADDRESS(its->cbaser);
>>> +}
>>> +
>>> +/*
>>> + * By writing to CWRITER the guest announces new commands to be processed.
>>> + * Since we cannot read from guest memory inside the ITS spinlock, we
>>> + * iterate over the command buffer (with the lock dropped) until the read
>>> + * pointer matches the write pointer. Other VCPUs writing this register in the
>>> + * meantime will just update the write pointer, leaving the command
>>> + * processing to the first instance of the function.
>>> + */
>>> +static int vgic_mmio_write_its_cwriter(struct kvm_vcpu *vcpu,
>>> +				       struct kvm_io_device *this,
>>> +				       gpa_t addr, int len, const void *val)
>>> +{
>>> +	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
>>> +	struct vgic_its *its = &dist->its;
>>> +	gpa_t cbaser = its_cmd_buffer_base(vcpu->kvm);
>>> +	u64 cmd_buf[4];
>>> +	u32 reg;
>>> +	bool finished;
>>> +
>>> +	reg = mask64(its->cwriter & 0xfffe0, addr & 7, len, val);
>>> +	reg &= 0xfffe0;
>>> +	if (reg > its_cmd_buffer_size(vcpu->kvm))
>>> +		return 0;
>>> +
>>> +	spin_lock(&its->lock);
>>> +
>>> +	/*
>>> +	 * If there is still another VCPU handling commands, let this
>>> +	 * one pick up the new CWRITER and process "our" new commands as well.
>>> +	 */
>>
>> How do you detect that condition? All I see is a massive race here, with
>> two threads processing the queue in parallel, possibly corrupting each
>> other's data.
>>
>> Please explain why you think this is safe.
> 
> OK, here you go: Actually we are handling the command queue
> synchronously: The first writer to CWRITER will end up here and will
> iterate over all commands below. From the guests point of view it will
> take some time to do the CWRITER MMIO write, but upon the writel
> returning the queue is actually already empty again.
> That means that any _sane_ guest will _never_ trigger the case where two
> threads/VCPUs are handling the queue, because a concurrent write to
> CWRITER without a lock in the guest would be broken by design.

That feels very fragile, and you're relying on a well behaved guest.

> 
> However I am not sure we can rely on this, so I added this precaution
> scheme:
> The first writer takes our ITS (emulation) lock and examines cwriter and
> creadr to see if they are equal. If they are, then the queue is
> currently empty, which means we are the first one and need to take care
> of the commands. We update our copy of cwriter (now marking the queue as
> non-empty) and drop the lock. As we kept the queue-was-empty status in a
> local variable, we now can start iterating through the queue. We only
> take the lock briefly when really needed in this process (for instance
> when one command has been processed and creadr is incremented).
> 
> If now a second VCPU writes CWRITER, we also take the lock and compare
> creadr and cwriter. Now they are different, because the first thread is
> still busy with handling the commands and hasn't finished yet.
> So we set our local "finished" to true. Also we update cwriter to the
> new value, then drop the lock. The while loop below will not be entered
> in this thread and we return to the guest.
> Now the first thread has handled another command, takes the lock to
> increase creadr and compares it with cwriter. Without the second writer
> it may have been finished already, but now cwriter has grown, so it will
> just carry on with handling the commands.
> 
> A bit like someone washing the dishes while another person adds some
> more dirty plates to the pile ;-)

I'm sorry, this feels incredibly complicated, and will make actual
debugging/tracing a nightmare. It also penalize the first vcpu that gets
to submitting a command, leading to scheduling imbalances.

Why can't you simply turn the ITS lock into a mutex and keep it held,
processing each batch in the context of the vcpu that is writing to
GITC_CWRITER?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...


From linux at armlinux.org.uk  Thu May 26 02:16:59 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Thu, 26 May 2016 10:16:59 +0100
Subject: [PATCH 13/20] drm/bridge: Add RGB to VGA bridge support
In-Reply-To: <20160526085330.GM9232@lukather>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-14-git-send-email-maxime.ripard@free-electrons.com>
 <1773896.kpi58ilqqm@avalon> <20160526085330.GM9232@lukather>
Message-ID: <20160526091659.GG19428@n2100.arm.linux.org.uk>

On Thu, May 26, 2016 at 10:53:30AM +0200, Maxime Ripard wrote:
> Hi Laurent,
> 
> On Mon, May 16, 2016 at 04:24:15PM +0300, Laurent Pinchart wrote:
> > Hi Maxime,
> > 
> > Thank you for the patch.
> > 
> > On Monday 16 May 2016 14:47:13 Maxime Ripard wrote:
> > > +fallback:
> > > +	/*
> > > +	 * In case we cannot retrieve the EDIDs (broken or missing i2c
> > > +	 * bus), fallback on the XGA standards
> > > +	 */
> > > +	ret = drm_add_modes_noedid(connector, 1920, 1200);
> > 
> > The DRM core adds modes up to 1024x768 in 
> > drm_helper_probe_single_connector_modes(). I wonder if it really makes sense 
> > to override that in drivers, compared to increasing the maximum resolution in 
> > the core. What we can reasonable expect from a VGA monitor doesn't really 
> > depend on which display engine it is connected to.
> 
> Actually, I would expect it to come from the connectors. Nowadays, the
> core add modes that might not even be relevant at all for a given
> connector. Take TV as an example, there's not a single TV output that
> can reach 1024x768, but actually rely on very different resolutions.

There is the requirement to support 640x480 almost universally.

> > Would it make sense to add an optional GPIO-based connection detection to this 
> > driver ?
> 
> I asked for it in our prototypes, and apparently, doing VGA cable
> detection is really non-trivial, so I don't really expect it to be
> found in a lot of designs.

... and prone to problems.  Intel designs try to measure the termination
resistance to detect whether something is connected (they pulse the RGB
signals and measure the current.)  This mostly works fine, except if you
have some KVM boxes which can make this very unreliable.

I ended up replacing the bipolar transistors switching the RGB signals
in my KVM switch with FETs because of this problem.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From josephl at nvidia.com  Thu May 26 02:29:21 2016
From: josephl at nvidia.com (Joseph Lo)
Date: Thu, 26 May 2016 17:29:21 +0800
Subject: [PATCH] arm64: tegra: Fix CPU compatible string for Tegra132
In-Reply-To: <5745C7E4.2050908@wwwdotorg.org>
References: <20160523074221.7135-1-josephl@nvidia.com>
 <574509E7.4030208@nvidia.com> <5745C7E4.2050908@wwwdotorg.org>
Message-ID: <5746C1F1.6070703@nvidia.com>

On 05/25/2016 11:42 PM, Stephen Warren wrote:
> On 05/24/2016 08:11 PM, Joseph Lo wrote:
>> On 05/23/2016 03:42 PM, Joseph Lo wrote:
>>> As per commit f634da375fc96 ("Documentation: DT bindings: add nvidia,
>>> tegra132-denver compatible string"), fixing the CPU compatible string
>>> for
>>> Tegra132 to match the binding document currently.
>>>
>>> Signed-off-by: Joseph Lo <josephl at nvidia.com>
>>> ---
>>>   arch/arm64/boot/dts/nvidia/tegra132.dtsi | 4 ++--
>>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
>>> b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
>>> index 2013f8916084..7b1cdc029de3 100644
>>> --- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
>>> +++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
>>> @@ -964,13 +964,13 @@
>>>
>>>           cpu at 0 {
>>>               device_type = "cpu";
>>> -            compatible = "nvidia,denver", "arm,armv8";
>>> +            compatible = "nvidia,tegra132-denver", "arm,armv8";
>>
>> Hi Stephen, Thierry,
>>
>> Should we fix this or fix the compatible string in the binding document
>> as just "nvidia,denver" to represent all the Devner CPU revisions just
>> like some other CPUs did? e.g. arm,cortex-a57, which represents all the
>> A57 revisions.
>
> I would expect compatible to be:
>
> compatible = "nvidia,tegra132-denver", "nvidia,denver", "arm,armv8";

Because we don't have "nvidia,denver" binding in the document, to do 
what you said, supposely I should add that first and fix the binding for 
Tegra132, right?

>
> The "nvidia,denver" entry is already present, and hence probably
> shouldn't be removed. It can represent "Denver 1.0". We should add the
> T132 entry to indicate the specific implementation. Admittedly right now
> there's a 1:1 relation between SoC and Denver version. Either/both of
> those could in theory be required to trigger specific bug-fixes/WARs.
>
> For later chips which have a different Denver version, I'd expect to see
> something like:
>
> compatible = "nvidia,tegraNNN-denver", "nvidia,denverMMM", "arm,armv8";
>
> ... where NNN is the SoC version/name and MMM is the Denver version.
> There could be extra entries in the property if the new versions are
> backwards-compatible with old versions.

Because it's 1:1 relationship, if we have new cores coming later, we 
should add both of the compatible string of SoC version and CPU core 
version in the ARM CPU binding document, is that correct?

Thanks,
Joseph


From linus.walleij at linaro.org  Thu May 26 02:28:44 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Thu, 26 May 2016 11:28:44 +0200
Subject: [PATCH 0/7] pinctrl: meson: Add a bunch more pins
In-Reply-To: <m260u3ia37.fsf@baylibre.com>
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
 <CACRpkdY9oGZLt431NwTaFmZk98O8n3ZnMA1odhYZtcH7P1p=Jg@mail.gmail.com>
 <m260u3ia37.fsf@baylibre.com>
Message-ID: <CACRpkdbURowJNT_ZkKuv7C_3oW3BJGPBK6etKc4cBc4ujQdPXw@mail.gmail.com>

On Tue, May 24, 2016 at 8:29 PM, Kevin Hilman <khilman at baylibre.com> wrote:
> Linus Walleij <linus.walleij at linaro.org> writes:

> Looking closer, these have dependencies on the DT changes that you've
> suggested we take through arm-soc, so it would be cleaner if I take
> these with your ack through the amlogic tree.

I really prefer to take DT changes and driver code in different
trees i possible.

My reasoning is plainly: if the DT stuff was a separate git, as
has been explicitly suggested as a goal off and on, this should
be merge:able still. So DT changes and driver code should ideally
be orthogonal.

I don't know about this case but is it a disaster if one or the other
of the DT changes and the driver arrive in different order to Torvald's
tree, or will it simply be that the lights go on when the last patch
arrives?

Yours,
Linus Walleij


From mcoquelin.stm32 at gmail.com  Thu May 26 02:34:57 2016
From: mcoquelin.stm32 at gmail.com (Maxime Coquelin)
Date: Thu, 26 May 2016 11:34:57 +0200
Subject: [PATCH] hwrng: stm32: fix maybe uninitialized variable warning
Message-ID: <1464255297-21090-1-git-send-email-mcoquelin.stm32@gmail.com>

This patch fixes the following warning:
drivers/char/hw_random/stm32-rng.c: In function 'stm32_rng_read':
drivers/char/hw_random/stm32-rng.c:82:19: warning: 'sr' may be used
                                        uninitialized in this function

Reported-by: Sudip Mukherjee <sudip.mukherjee at codethink.co.uk>
Suggested-by: Arnd Bergmann <arnd at arndb.de>
Cc: Daniel Thompson <daniel.thompson at linaro.org>
Signed-off-by: Maxime Coquelin <mcoquelin.stm32 at gmail.com>
---
 drivers/char/hw_random/stm32-rng.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 92a810648bd0..63d84e6f1891 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -69,8 +69,12 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 		}
 
 		/* If error detected or data not ready... */
-		if (sr != RNG_SR_DRDY)
+		if (sr != RNG_SR_DRDY) {
+			if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
+					"bad RNG status - %x\n", sr))
+				writel_relaxed(0, priv->base + RNG_SR);
 			break;
+		}
 
 		*(u32 *)data = readl_relaxed(priv->base + RNG_DR);
 
@@ -79,10 +83,6 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 		max -= sizeof(u32);
 	}
 
-	if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
-		      "bad RNG status - %x\n", sr))
-		writel_relaxed(0, priv->base + RNG_SR);
-
 	pm_runtime_mark_last_busy((struct device *) priv->rng.priv);
 	pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv);
 
-- 
1.9.1



From maxime.ripard at free-electrons.com  Thu May 26 02:38:12 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Thu, 26 May 2016 11:38:12 +0200
Subject: [PATCH 13/20] drm/bridge: Add RGB to VGA bridge support
In-Reply-To: <CAL_JsqKMJ7X2MU7vF9n7_MmAUQJ2v+yKyazcmMurgbTxYGfw_Q@mail.gmail.com>
References: <1463402840-17062-1-git-send-email-maxime.ripard@free-electrons.com>
 <1463402840-17062-14-git-send-email-maxime.ripard@free-electrons.com>
 <CAL_JsqKMJ7X2MU7vF9n7_MmAUQJ2v+yKyazcmMurgbTxYGfw_Q@mail.gmail.com>
Message-ID: <20160526093812.GN9232@lukather>

Hi Rob,

On Mon, May 16, 2016 at 09:07:18AM -0500, Rob Herring wrote:
> On Mon, May 16, 2016 at 7:47 AM, Maxime Ripard
> <maxime.ripard at free-electrons.com> wrote:
> > Some boards have an entirely passive RGB to VGA bridge, based on either
> > DACs or resistor ladders.
> >
> > Those might or might not have an i2c bus routed to the VGA connector in
> > order to access the screen EDIDs.
> >
> > Add a bridge that doesn't do anything but expose the modes available on the
> > screen, either based on the EDIDs if available, or based on the XGA
> > standards.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  .../bindings/display/bridge/dumb-vga.txt           |  40 +++++
> >  drivers/gpu/drm/bridge/Kconfig                     |   6 +
> >  drivers/gpu/drm/bridge/Makefile                    |   1 +
> >  drivers/gpu/drm/bridge/dumb-vga.c                  | 186 +++++++++++++++++++++
> >  4 files changed, 233 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
> >  create mode 100644 drivers/gpu/drm/bridge/dumb-vga.c
> >
> > diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
> > new file mode 100644
> > index 000000000000..757f04de97f3
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga.txt
> > @@ -0,0 +1,40 @@
> > +Passive RGB to VGA bridge
> > +-------------------------
> > +
> > +This binding is aimed for entirely passive RGB to VGA bridges that do not
> > +require any configuration.
> 
> No reset or enable lines or regulators?

On the three designs I've seen:
  - One doesn't need any of these
  - One has a GPIO enable pin but with it's resistor not populated
  - One has a regulator controlled by a GPIO

So I guess in most cases, we don't need anything, but we still might
to cover all cases.

> > +
> > +Required properties:
> > +
> > +- compatible: Should be "dumb-vga-bridge"
> > +
> > +Optional properties:
> > +
> > +- ddc-i2c-bus: phandle to the i2c bus used to communicate with the monitor
> 
> The i2c bus is a property of the connector, not the bridge chip, so it
> belongs in a VGA connector node (which we already have binding for).
> 
> I think for the really "dumb" (or transparent case), you should only
> have a connector. For anything more complex, then you should have both
> a DAC and connector node.

So, in essence, something like:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/r8a7794-alt.dts#n37
 
> On the driver side, I think we could handle multiple connectors with a
> single driver. Ideally, that would work with any DRM driver that has a
> connector node.

I'm not sure what you mean by that. I really think it should be a
separate driver in order to share the common code that so far the
current implementations put in some driver specific code (even though
it might be completely generic).

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160526/c56e1bc6/attachment.sig>

From narmstrong at baylibre.com  Thu May 26 02:38:09 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 26 May 2016 11:38:09 +0200
Subject: [RFC PATCH 0/2] scpi: Add SCPI framework to handle vendors variants
Message-ID: <1464255491-18503-1-git-send-email-narmstrong@baylibre.com>

Since the current SCPI implementation, based on [0]:
- is (at leat) JUNO specific
- does not specify a strong "standard"
- does not specify a strong MHU interface specification

SoC vendors could implement a variant with slight changes in message
indexes, new messages types, different messages data format or different MHU
communication scheme.

To keep the spirit of the SCPI interface, add a thin "register" layer to get
the ops from the parent node and switch the drivers using the ops to use
the new of_scpi_ops_get() call.

[0] http://infocenter.arm.com/help/topic/com.arm.doc.dui0922b/index.html

Neil Armstrong (2):
  firmware: Add a SCPI framework to handle multiple vendors
    implementation
  firmware: scpi: Switch scpi drivers to use new Framework calls

 drivers/clk/clk-scpi.c         |  18 ++++---
 drivers/cpufreq/scpi-cpufreq.c |   7 +--
 drivers/firmware/Makefile      |   1 +
 drivers/firmware/arm_scpi.c    |  18 +++----
 drivers/firmware/scpi.c        | 110 +++++++++++++++++++++++++++++++++++++++++
 drivers/hwmon/scpi-hwmon.c     |   6 +--
 include/linux/scpi_protocol.h  |  33 ++++++++++++-
 7 files changed, 169 insertions(+), 24 deletions(-)
 create mode 100644 drivers/firmware/scpi.c

-- 
2.7.0



From narmstrong at baylibre.com  Thu May 26 02:38:10 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 26 May 2016 11:38:10 +0200
Subject: [RFC PATCH 1/2] firmware: Add a SCPI framework to handle multiple
 vendors implementation
In-Reply-To: <1464255491-18503-1-git-send-email-narmstrong@baylibre.com>
References: <1464255491-18503-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464255491-18503-2-git-send-email-narmstrong@baylibre.com>

Add a thin "register" interface for SCPI driver in order to register their
ops along their node.

Since nodes using the SCPI ops are currently sub-nodes, does not implement
phandle xlate stuff.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/firmware/Makefile |   1 +
 drivers/firmware/scpi.c   | 110 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+)
 create mode 100644 drivers/firmware/scpi.c

diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 474bada..701a791 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the linux kernel.
 #
 obj-$(CONFIG_ARM_PSCI_FW)	+= psci.o
+obj-$(CONFIG_ARM_SCPI_PROTOCOL)	+= scpi.o
 obj-$(CONFIG_ARM_SCPI_PROTOCOL)	+= arm_scpi.o
 obj-$(CONFIG_DMI)		+= dmi_scan.o
 obj-$(CONFIG_DMI_SYSFS)		+= dmi-sysfs.o
diff --git a/drivers/firmware/scpi.c b/drivers/firmware/scpi.c
new file mode 100644
index 0000000..ba94ac4
--- /dev/null
+++ b/drivers/firmware/scpi.c
@@ -0,0 +1,110 @@
+/*
+ * System Control and Power Interface (SCPI) Message Protocol framework
+ *
+ * SCPI Message Protocol is used between the System Control Processor(SCP)
+ * and the Application Processors(AP). The Message Handling Unit(MHU)
+ * provides a mechanism for inter-processor communication between SCP's
+ * Cortex M3 and AP.
+ *
+ * SCP offers control and management of the core/cluster power states,
+ * various power domain DVFS including the core/cluster, certain system
+ * clocks configuration, thermal sensors and many others.
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ * Copyright (C) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.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/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/scpi_protocol.h>
+#include <linux/spinlock.h>
+
+static DEFINE_MUTEX(scpi_list_mutex);
+static LIST_HEAD(scpi_drivers_list);
+
+struct scpi_ops *of_scpi_ops_get(struct device_node *node)
+{
+	struct scpi_ops *ops = NULL;
+	struct scpi_driver *r;
+
+	if (!node)
+		return ERR_PTR(-EINVAL);
+
+	mutex_lock(&scpi_list_mutex);
+	list_for_each_entry(r, &scpi_drivers_list, list) {
+		if (node == r->node) {
+			ops = r->ops;
+			break;
+		}
+	}
+	mutex_unlock(&scpi_list_mutex);
+
+	if (!ops)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	return ops;
+}
+EXPORT_SYMBOL_GPL(of_scpi_ops_get);
+
+int scpi_driver_register(struct scpi_driver *drv)
+{
+	mutex_lock(&scpi_list_mutex);
+	list_add(&drv->list, &scpi_drivers_list);
+	mutex_unlock(&scpi_list_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(scpi_driver_register);
+
+void scpi_driver_unregister(struct scpi_driver *drv)
+{
+	mutex_lock(&scpi_list_mutex);
+	list_del(&drv->list);
+	mutex_unlock(&scpi_list_mutex);
+}
+EXPORT_SYMBOL_GPL(scpi_driver_unregister);
+
+static void devm_scpi_driver_unregister(struct device *dev, void *res)
+{
+	scpi_driver_unregister(*(struct scpi_driver **)res);
+}
+
+int devm_scpi_driver_register(struct device *dev,
+				struct scpi_driver *drv)
+{
+	struct scpi_driver **rcdrv;
+	int ret;
+
+	rcdrv = devres_alloc(devm_scpi_driver_unregister, sizeof(*drv),
+			     GFP_KERNEL);
+	if (!rcdrv)
+		return -ENOMEM;
+
+	ret = scpi_driver_register(drv);
+	if (!ret) {
+		*rcdrv = drv;
+		devres_add(dev, rcdrv);
+	} else
+		devres_free(rcdrv);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(devm_scpi_driver_register);
-- 
2.7.0



From narmstrong at baylibre.com  Thu May 26 02:38:11 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Thu, 26 May 2016 11:38:11 +0200
Subject: [RFC PATCH 2/2] firmware: scpi: Switch scpi drivers to use new
 Framework calls
In-Reply-To: <1464255491-18503-1-git-send-email-narmstrong@baylibre.com>
References: <1464255491-18503-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464255491-18503-3-git-send-email-narmstrong@baylibre.com>

Update the include/linux/scpi_protocol.h with the new registry calls.

Switch following drivers to use the new SCPI registry layer :
 - drivers/clk/clk-scpi.c
 - drivers/cpufreq/scpi-cpufreq.c
 - drivers/hwmon/scpi-hwmon.c

And finally switch drivers/firmware/arm_scpi.c to use scpi_driver_register().

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/clk/clk-scpi.c         | 18 +++++++++++-------
 drivers/cpufreq/scpi-cpufreq.c |  7 ++++---
 drivers/firmware/arm_scpi.c    | 18 +++++++++---------
 drivers/hwmon/scpi-hwmon.c     |  6 +++---
 include/linux/scpi_protocol.h  | 33 +++++++++++++++++++++++++++++++--
 5 files changed, 58 insertions(+), 24 deletions(-)

diff --git a/drivers/clk/clk-scpi.c b/drivers/clk/clk-scpi.c
index 6962ee5..18ffaf5 100644
--- a/drivers/clk/clk-scpi.c
+++ b/drivers/clk/clk-scpi.c
@@ -148,7 +148,8 @@ static const struct of_device_id scpi_clk_match[] = {
 
 static struct clk *
 scpi_clk_ops_init(struct device *dev, const struct of_device_id *match,
-		  struct scpi_clk *sclk, const char *name)
+		  struct scpi_clk *sclk, const char *name,
+		  struct scpi_ops *scpi_ops)
 {
 	struct clk_init_data init;
 	struct clk *clk;
@@ -159,7 +160,7 @@ scpi_clk_ops_init(struct device *dev, const struct of_device_id *match,
 	init.num_parents = 0;
 	init.ops = match->data;
 	sclk->hw.init = &init;
-	sclk->scpi_ops = get_scpi_ops();
+	sclk->scpi_ops = scpi_ops;
 
 	if (init.ops == &scpi_dvfs_ops) {
 		sclk->info = sclk->scpi_ops->dvfs_get_info(sclk->id);
@@ -200,7 +201,8 @@ scpi_of_clk_src_get(struct of_phandle_args *clkspec, void *data)
 }
 
 static int scpi_clk_add(struct device *dev, struct device_node *np,
-			const struct of_device_id *match)
+			const struct of_device_id *match,
+			struct scpi_ops *scpi_ops)
 {
 	struct clk **clks;
 	int idx, count;
@@ -249,7 +251,7 @@ static int scpi_clk_add(struct device *dev, struct device_node *np,
 
 		sclk->id = val;
 
-		clks[idx] = scpi_clk_ops_init(dev, match, sclk, name);
+		clks[idx] = scpi_clk_ops_init(dev, match, sclk, name, scpi_ops);
 		if (IS_ERR_OR_NULL(clks[idx]))
 			dev_err(dev, "failed to register clock '%s'\n", name);
 		else
@@ -281,15 +283,17 @@ static int scpi_clocks_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct device_node *child, *np = dev->of_node;
 	const struct of_device_id *match;
+	struct scpi_ops *scpi_ops;
 
-	if (!get_scpi_ops())
-		return -ENXIO;
+	scpi_ops = of_scpi_ops_get(of_get_parent(np));
+	if (IS_ERR(scpi_ops))
+		return PTR_ERR(scpi_ops);
 
 	for_each_available_child_of_node(np, child) {
 		match = of_match_node(scpi_clk_match, child);
 		if (!match)
 			continue;
-		ret = scpi_clk_add(dev, child, match);
+		ret = scpi_clk_add(dev, child, match, scpi_ops);
 		if (ret) {
 			scpi_clocks_remove(pdev);
 			of_node_put(child);
diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
index e8a7bf5..158f1d80 100644
--- a/drivers/cpufreq/scpi-cpufreq.c
+++ b/drivers/cpufreq/scpi-cpufreq.c
@@ -25,6 +25,7 @@
 #include <linux/pm_opp.h>
 #include <linux/scpi_protocol.h>
 #include <linux/types.h>
+#include <linux/of.h>
 
 #include "arm_big_little.h"
 
@@ -88,9 +89,9 @@ static struct cpufreq_arm_bL_ops scpi_cpufreq_ops = {
 
 static int scpi_cpufreq_probe(struct platform_device *pdev)
 {
-	scpi_ops = get_scpi_ops();
-	if (!scpi_ops)
-		return -EIO;
+	scpi_ops = of_scpi_ops_get(of_get_parent(pdev->dev.of_node));
+	if (IS_ERR(scpi_ops))
+		return PTR_ERR(scpi_ops);
 
 	return bL_cpufreq_register(&scpi_cpufreq_ops);
 }
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 7e3e595..00fc849 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -162,9 +162,9 @@ struct scpi_drvinfo {
 	u32 firmware_version;
 	int num_chans;
 	atomic_t next_chan;
-	struct scpi_ops *scpi_ops;
 	struct scpi_chan *channels;
 	struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
+	struct scpi_driver drv;
 };
 
 /*
@@ -526,7 +526,7 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
 	return ret;
 }
 
-int scpi_sensor_get_value(u16 sensor, u64 *val)
+static int scpi_sensor_get_value(u16 sensor, u64 *val)
 {
 	__le16 id = cpu_to_le16(sensor);
 	struct sensor_value buf;
@@ -554,12 +554,6 @@ static struct scpi_ops scpi_ops = {
 	.sensor_get_value = scpi_sensor_get_value,
 };
 
-struct scpi_ops *get_scpi_ops(void)
-{
-	return scpi_info ? scpi_info->scpi_ops : NULL;
-}
-EXPORT_SYMBOL_GPL(get_scpi_ops);
-
 static int scpi_init_versions(struct scpi_drvinfo *info)
 {
 	int ret;
@@ -743,7 +737,13 @@ err:
 		  FW_REV_MAJOR(scpi_info->firmware_version),
 		  FW_REV_MINOR(scpi_info->firmware_version),
 		  FW_REV_PATCH(scpi_info->firmware_version));
-	scpi_info->scpi_ops = &scpi_ops;
+
+	scpi_info->drv.node = dev->of_node;
+	scpi_info->drv.ops = &scpi_ops;
+
+	ret = devm_scpi_driver_register(dev, &scpi_info->drv);
+	if (ret)
+		return ret;
 
 	ret = sysfs_create_groups(&dev->kobj, versions_groups);
 	if (ret)
diff --git a/drivers/hwmon/scpi-hwmon.c b/drivers/hwmon/scpi-hwmon.c
index 912b449..45d36d1 100644
--- a/drivers/hwmon/scpi-hwmon.c
+++ b/drivers/hwmon/scpi-hwmon.c
@@ -120,9 +120,9 @@ static int scpi_hwmon_probe(struct platform_device *pdev)
 	struct scpi_sensors *scpi_sensors;
 	int ret, idx;
 
-	scpi_ops = get_scpi_ops();
-	if (!scpi_ops)
-		return -EPROBE_DEFER;
+	scpi_ops = of_scpi_ops_get(of_get_parent(dev.of_node));
+	if (IS_ERR(scpi_ops))
+		return PTR_ERR(scpi_ops);
 
 	ret = scpi_ops->sensor_get_capability(&nr_sensors);
 	if (ret)
diff --git a/include/linux/scpi_protocol.h b/include/linux/scpi_protocol.h
index 35de50a..fc27034 100644
--- a/include/linux/scpi_protocol.h
+++ b/include/linux/scpi_protocol.h
@@ -72,8 +72,37 @@ struct scpi_ops {
 	int (*sensor_get_value)(u16, u64 *);
 };
 
+struct scpi_driver {
+	struct device_node *node;
+	struct scpi_ops *ops;
+	struct list_head list;
+};
+
 #if IS_REACHABLE(CONFIG_ARM_SCPI_PROTOCOL)
-struct scpi_ops *get_scpi_ops(void);
+struct scpi_ops *of_scpi_ops_get(struct device_node *node);
+
+int scpi_driver_register(struct scpi_driver *drv);
+
+void scpi_driver_unregister(struct scpi_driver *drv);
+
+int devm_scpi_driver_register(struct device *dev,
+				struct scpi_driver *drv);
 #else
-static inline struct scpi_ops *get_scpi_ops(void) { return NULL; }
+struct scpi_ops *of_scpi_ops_get(struct device_node *node)
+{
+	return ERR_PTR(-ENOTSUPP);
+}
+
+int scpi_driver_register(struct scpi_driver *drv)
+{
+	return -ENOTSUPP;
+}
+
+void scpi_driver_unregister(struct scpi_driver *drv) { }
+
+int devm_scpi_driver_register(struct device *dev,
+				struct scpi_driver *drv)
+{
+	return -ENOTSUPP;
+}
 #endif
-- 
2.7.0



From gabriel.fernandez at linaro.org  Thu May 26 02:49:46 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Thu, 26 May 2016 11:49:46 +0200
Subject: [PATCH 02/11] drivers: clk: st: Add clock propagation for audio
 clocks
In-Reply-To: <20160525172409.GA27913@rob-hp-laptop>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
 <1463560892-7209-3-git-send-email-gabriel.fernandez@linaro.org>
 <20160525172409.GA27913@rob-hp-laptop>
Message-ID: <CAG374jDTCJfZB+PuAnggjXhbcd3NjJqrESpe_EnMniCAeoph9A@mail.gmail.com>

On 25 May 2016 at 19:24, Rob Herring <robh at kernel.org> wrote:
>
> On Wed, May 18, 2016 at 10:41:23AM +0200, Gabriel Fernandez wrote:
> > This patch allows fine tuning of the quads FS for audio clocks
> > accuracy.
> >
> > Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
> > Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
> > ---
> >  .../devicetree/bindings/clock/st/st,flexgen.txt    |  1 +
> >  drivers/clk/st/clk-flexgen.c                       | 24 ++++++++++++++++++++++
> >  2 files changed, 25 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
> > index b7ee5c7..15b33c7 100644
> > --- a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
> > +++ b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
> > @@ -60,6 +60,7 @@ This binding uses the common clock binding[2].
> >  Required properties:
> >  - compatible : shall be:
> >    "st,flexgen"
> > +  "st,stih407-clkgend0", "st,flexgen" (enable clock propagation on parent)
>
> What do "d0" and "d2" refer to?
>
> This seems to indicate you have too much clock detail in the DT (with
> individual clocks described) or not enough with genericish compatible
> strings. What happens for the mext clock you need to adjust the flags
> on? You should be able to make these adjustments without DT updates.
> Perhaps you need a wider fixing of clock compatible strings.
>
> Rob

Sorry i sent my response in html...

Hi Rob,

Thanks for reviewing.

Can i remove
"
st,stih407-clkgend0" & "
st,stih407-clkgend2" compatible strings and add proprieties instead ?
I only need to activate 2 features and then we can keep generic
compatible strings.

e.g.

clk_s_d2_flexgen: clk-s-d2-flexgen {
#clock-cells = <1>;
compatible = "st,flexgen";
        ...
       st-sync-mode;
        st-update
-parent-rate;
};

for d0_flexgen i will enable only st-sync-mode;

Best Regards


From l.stach at pengutronix.de  Thu May 26 02:50:17 2016
From: l.stach at pengutronix.de (Lucas Stach)
Date: Thu, 26 May 2016 11:50:17 +0200
Subject: [PATCH 1/2] ARM: dts: imx6q: extend support for the cm-fx6
In-Reply-To: <5746B8C4.6020406@compulab.co.il>
References: <709d6b3d522f4fcb8112830e0426dbb3@rwthex-s1-b.rwth-ad.de>
 <1463994191.2370.3.camel@pengutronix.de> <5746B8C4.6020406@compulab.co.il>
Message-ID: <1464256217.14453.10.camel@pengutronix.de>

Hi Igor,

Am Donnerstag, den 26.05.2016, 11:50 +0300 schrieb Igor Grinberg:
> Hi Lucas,
> 
> Thanks for reviewing the patch(es).
> 
> On 05/23/2016 12:03 PM, Lucas Stach wrote:
> > Am Montag, den 23.05.2016, 00:47 +0200 schrieb
> > christopher.spinrath at rwth-aachen.de:
> >> From: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>
> 
> [...]
> 
> >> +&ecspi1 {
> >> +	fsl,spi-num-chipselects = <2>;
> >> +	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
> >> +	pinctrl-names = "default";
> >> +	pinctrl-0 = <&pinctrl_ecspi1>;
> >> +	status = "okay";
> >> +
> >> +	flash: m25p80 at 0 {
> >> +		#address-cells = <1>;
> >> +		#size-cells = <1>;
> >> +		compatible = "st,m25p", "jedec,spi-nor";
> >> +		spi-max-frequency = <20000000>;
> >> +		reg = <0>;
> >> +
> >> +		partition at 0 {
> >> +			label = "uboot";
> >> +			reg = <0x0 0xc0000>;
> >> +		};
> >> +
> >> +		partition at c0000 {
> >> +			label = "uboot environment";
> >> +			reg = <0xc0000 0x40000>;
> >> +		};
> >> +
> >> +		partition at 100000 {
> >> +			label = "reserved";
> >> +			reg = <0x100000 0x100000>;
> >> +		};
> > 
> > Partition layouts don't belong in the upstream DT, as it a device
> > configuration thing. Please kep them in the bootloader/firmware and make
> > this one pass the partition layout to the kernel.
> 
> I don't completely agree with this.
> We have lots of partition layouts in the upstream DT.

No, we don't. At least not for the i.MX6. There are some for the earlier
i.MX boards, but IMO it's wrong to put device configuration into the
upstream DT. Let's not start doing this again.

> Moreover, this is the default layout and changing it, will
> result in incompatibilities and also might result in device "bricking".
> Those can be changed from the boot loader in case you need those
> the other way around.
> Another question of mine is, why should you?
> 
Partition layout is device configuration, which is governed by the
device firmware. By not having the partition layout in the upstream DT
people are forced to set it from the firmware, which is exactly the
right thing to do, weather or not you plan to change it at any time.

Regards,
Lucas




From Liviu.Dudau at arm.com  Thu May 26 02:58:35 2016
From: Liviu.Dudau at arm.com (Liviu Dudau)
Date: Thu, 26 May 2016 10:58:35 +0100
Subject: [RFC][PATCH 1/3] staging: ion: Move away from the DMA APIs for
 cache flushing
In-Reply-To: <1464205684-5587-2-git-send-email-labbott@redhat.com>
References: <1464205684-5587-1-git-send-email-labbott@redhat.com>
 <1464205684-5587-2-git-send-email-labbott@redhat.com>
Message-ID: <20160526095835.GT23566@e106497-lin.cambridge.arm.com>

On Wed, May 25, 2016 at 12:48:02PM -0700, Laura Abbott wrote:
> 
> Ion is currently using the DMA APIs in non-compliant ways for cache
> maintaince. The issue is Ion needs to do cache operations outside of
> the regular DMA model. The Ion model matches more closely with the
> DRM model which calls cache APIs directly. Add an appropriate
> abstraction layer for Ion to call cache operations outside of the
> DMA API.
> 
> Signed-off-by: Laura Abbott <labbott at redhat.com>

Hi Laura,

By no means a full review, just some comments:

> ---
>  drivers/staging/android/ion/Kconfig             | 14 ++++-
>  drivers/staging/android/ion/Makefile            |  3 +
>  drivers/staging/android/ion/ion-arm.c           | 83 +++++++++++++++++++++++++
>  drivers/staging/android/ion/ion-arm64.c         | 46 ++++++++++++++
>  drivers/staging/android/ion/ion-x86.c           | 34 ++++++++++
>  drivers/staging/android/ion/ion.c               | 59 ++++++------------
>  drivers/staging/android/ion/ion_carveout_heap.c |  5 +-
>  drivers/staging/android/ion/ion_chunk_heap.c    |  7 +--
>  drivers/staging/android/ion/ion_page_pool.c     |  3 +-
>  drivers/staging/android/ion/ion_priv.h          | 14 ++---
>  drivers/staging/android/ion/ion_system_heap.c   |  5 +-
>  11 files changed, 210 insertions(+), 63 deletions(-)
>  create mode 100644 drivers/staging/android/ion/ion-arm.c
>  create mode 100644 drivers/staging/android/ion/ion-arm64.c
>  create mode 100644 drivers/staging/android/ion/ion-x86.c
> 
> diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig
> index 19c1572..c1b1813 100644
> --- a/drivers/staging/android/ion/Kconfig
> +++ b/drivers/staging/android/ion/Kconfig
> @@ -1,6 +1,6 @@
>  menuconfig ION
>  	bool "Ion Memory Manager"
> -	depends on HAVE_MEMBLOCK && HAS_DMA && MMU
> +	depends on HAVE_MEMBLOCK && HAS_DMA && MMU && (X86 || ARM || ARM64)
>  	select GENERIC_ALLOCATOR
>  	select DMA_SHARED_BUFFER
>  	---help---
> @@ -10,6 +10,18 @@ menuconfig ION
>  	  If you're not using Android its probably safe to
>  	  say N here.
>  
> +config ION_ARM
> +	depends on ION && ARM
> +	def_bool y
> +
> +config ION_ARM64
> +	depends on ION && ARM64
> +	def_bool y
> +
> +config ION_X86
> +	depends on ION && X86
> +	def_bool y

If you are going to make this arch specific, can I suggest that you make CONFIG_ION
depend on CONFIG_ARCH_ION (or any name you like) and then in each arch select it?
I don't particularly like the enumeration of all ION enabled arches above 
(is the list exhaustive?)

> +
>  config ION_TEST
>  	tristate "Ion Test Device"
>  	depends on ION
> diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile
> index 18cc2aa..1b82bb5 100644
> --- a/drivers/staging/android/ion/Makefile
> +++ b/drivers/staging/android/ion/Makefile
> @@ -1,5 +1,8 @@
>  obj-$(CONFIG_ION) +=	ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \
>  			ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o
> +obj-$(CONFIG_ION_X86) += ion-x86.o
> +obj-$(CONFIG_ION_ARM) += ion-arm.o
> +obj-$(CONFIG_ION_ARM64) += ion-arm64.o
>  obj-$(CONFIG_ION_TEST) += ion_test.o
>  ifdef CONFIG_COMPAT
>  obj-$(CONFIG_ION) += compat_ion.o
> diff --git a/drivers/staging/android/ion/ion-arm.c b/drivers/staging/android/ion/ion-arm.c
> new file mode 100644
> index 0000000..b91287f
> --- /dev/null
> +++ b/drivers/staging/android/ion/ion-arm.c
> @@ -0,0 +1,83 @@
> +/*
> + * Copyright (C) 2016 Laura Abbott <laura at labbott.name>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/types.h>
> +#include <linux/scatterlist.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/highmem.h>
> +
> +#include <asm/cacheflush.h>
> +
> +#include "ion_priv.h"
> +
> +
> +void ion_clean_page(struct page *page, size_t size)
> +{
> +	unsigned long pfn;
> +	size_t left = size;
> +
> +	pfn = page_to_pfn(page);
> +
> +	/*
> +	 * A single sg entry may refer to multiple physically contiguous
> +	 * pages.  But we still need to process highmem pages individually.
> +	 * If highmem is not configured then the bulk of this loop gets
> +	 * optimized out.
> +	 */
> +	do {
> +		size_t len = left;
> +		void *vaddr;
> +
> +		page = pfn_to_page(pfn);
> +
> +		if (PageHighMem(page)) {
> +			if (len > PAGE_SIZE)
> +				len = PAGE_SIZE;
> +
> +			if (cache_is_vipt_nonaliasing()) {
> +				vaddr = kmap_atomic(page);
> +				__cpuc_flush_dcache_area(vaddr, len);
> +				kunmap_atomic(vaddr);
> +			} else {
> +				vaddr = kmap_high_get(page);
> +				if (vaddr) {
> +					__cpuc_flush_dcache_area(vaddr, len);
> +					kunmap_high(page);
> +				}
> +			}
> +		} else {
> +			vaddr = page_address(page);
> +			__cpuc_flush_dcache_area(vaddr, len);
> +		}
> +		pfn++;
> +		left -= len;
> +	} while (left);
> +}
> +
> +/*
> + * ARM has highmem and a bunch of other 'fun' features. It's so much easier just
> + * to do the ISA DMA and call things that way
> + */
> +
> +void ion_invalidate_buffer(struct ion_buffer *buffer)
> +{
> +	dma_unmap_sg(NULL, buffer->sg_table->sgl, buffer->sg_table->orig_nents,

arm_dma_unmap_sg?

> +			DMA_BIDIRECTIONAL);
> +}
> +
> +void ion_clean_buffer(struct ion_buffer *buffer)
> +{
> +	dma_map_sg(NULL, buffer->sg_table->sgl, buffer->sg_table->orig_nents,

arm_dma_map_sg?

Otherwise, these two functions looks quite generic. Can they be the default implementation?

Best regards,
Liviu

> +			DMA_BIDIRECTIONAL);
> +}
> diff --git a/drivers/staging/android/ion/ion-arm64.c b/drivers/staging/android/ion/ion-arm64.c
> new file mode 100644
> index 0000000..afd387a
> --- /dev/null
> +++ b/drivers/staging/android/ion/ion-arm64.c
> @@ -0,0 +1,46 @@
> +/*
> + * Copyright (C) 2016 Laura Abbott <laura at labbott.name>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/types.h>
> +#include <linux/scatterlist.h>
> +#include <linux/dma-mapping.h>
> +
> +#include <asm/cacheflush.h>
> +
> +#include "ion_priv.h"
> +
> +void ion_clean_page(struct page *page, size_t size)
> +{
> +	__flush_dcache_area(page_address(page), size);
> +}
> +
> +void ion_invalidate_buffer(struct ion_buffer *buffer)
> +{
> +	struct scatterlist *sg;
> +	int i;
> +
> +	for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->orig_nents, i)
> +		__dma_unmap_area(page_address(sg_page(sg)), sg->length,
> +					DMA_BIDIRECTIONAL);
> +}
> +
> +void ion_clean_buffer(struct ion_buffer *buffer)
> +{
> +	struct scatterlist *sg;
> +	int i;
> +
> +	for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->orig_nents, i)
> +		__dma_map_area(page_address(sg_page(sg)), sg->length,
> +					DMA_BIDIRECTIONAL);
> +}
> diff --git a/drivers/staging/android/ion/ion-x86.c b/drivers/staging/android/ion/ion-x86.c
> new file mode 100644
> index 0000000..05fd684
> --- /dev/null
> +++ b/drivers/staging/android/ion/ion-x86.c
> @@ -0,0 +1,34 @@
> +/*
> + * Copyright (C) 2016 Laura Abbott <laura at labbott.name>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/types.h>
> +#include <linux/scatterlist.h>
> +#include <linux/dma-mapping.h>
> +
> +#include "ion_priv.h"
> +
> +void ion_clean_page(struct page *page, size_t size)
> +{
> +	/* Do nothing right now */
> +}
> +
> +void ion_invalidate_buffer(struct ion_buffer *buffer)
> +{
> +	/* Do nothing right now */
> +}
> +
> +void ion_clean_buffer(struct ion_buffer *buffer)
> +{
> +	/* Do nothing right now */
> +}
> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
> index a2cf93b..9282d96a 100644
> --- a/drivers/staging/android/ion/ion.c
> +++ b/drivers/staging/android/ion/ion.c
> @@ -937,42 +937,6 @@ struct sg_table *ion_sg_table(struct ion_client *client,
>  }
>  EXPORT_SYMBOL(ion_sg_table);
>  
> -static void ion_buffer_sync_for_device(struct ion_buffer *buffer,
> -				       struct device *dev,
> -				       enum dma_data_direction direction);
> -
> -static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment,
> -					enum dma_data_direction direction)
> -{
> -	struct dma_buf *dmabuf = attachment->dmabuf;
> -	struct ion_buffer *buffer = dmabuf->priv;
> -
> -	ion_buffer_sync_for_device(buffer, attachment->dev, direction);
> -	return buffer->sg_table;
> -}
> -
> -static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment,
> -			      struct sg_table *table,
> -			      enum dma_data_direction direction)
> -{
> -}
> -
> -void ion_pages_sync_for_device(struct device *dev, struct page *page,
> -		size_t size, enum dma_data_direction dir)
> -{
> -	struct scatterlist sg;
> -
> -	sg_init_table(&sg, 1);
> -	sg_set_page(&sg, page, size, 0);
> -	/*
> -	 * This is not correct - sg_dma_address needs a dma_addr_t that is valid
> -	 * for the targeted device, but this works on the currently targeted
> -	 * hardware.
> -	 */
> -	sg_dma_address(&sg) = page_to_phys(page);
> -	dma_sync_sg_for_device(dev, &sg, 1, dir);
> -}
> -
>  struct ion_vma_list {
>  	struct list_head list;
>  	struct vm_area_struct *vma;
> @@ -997,8 +961,7 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer,
>  		struct page *page = buffer->pages[i];
>  
>  		if (ion_buffer_page_is_dirty(page))
> -			ion_pages_sync_for_device(dev, ion_buffer_page(page),
> -							PAGE_SIZE, dir);
> +			ion_clean_page(ion_buffer_page(page), PAGE_SIZE);
>  
>  		ion_buffer_page_clean(buffer->pages + i);
>  	}
> @@ -1011,6 +974,22 @@ static void ion_buffer_sync_for_device(struct ion_buffer *buffer,
>  	mutex_unlock(&buffer->lock);
>  }
>  
> +static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment,
> +					enum dma_data_direction direction)
> +{
> +	struct dma_buf *dmabuf = attachment->dmabuf;
> +	struct ion_buffer *buffer = dmabuf->priv;
> +
> +	ion_buffer_sync_for_device(buffer, attachment->dev, direction);
> +	return buffer->sg_table;
> +}
> +
> +static void ion_unmap_dma_buf(struct dma_buf_attachment *attachment,
> +			      struct sg_table *table,
> +			      enum dma_data_direction direction)
> +{
> +}
> +
>  static int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
>  {
>  	struct ion_buffer *buffer = vma->vm_private_data;
> @@ -1293,8 +1272,8 @@ static int ion_sync_for_device(struct ion_client *client, int fd)
>  	}
>  	buffer = dmabuf->priv;
>  
> -	dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
> -			       buffer->sg_table->nents, DMA_BIDIRECTIONAL);
> +	ion_clean_buffer(buffer);
> +
>  	dma_buf_put(dmabuf);
>  	return 0;
>  }
> diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c
> index 1fb0d81..d213cbf 100644
> --- a/drivers/staging/android/ion/ion_carveout_heap.c
> +++ b/drivers/staging/android/ion/ion_carveout_heap.c
> @@ -116,8 +116,7 @@ static void ion_carveout_heap_free(struct ion_buffer *buffer)
>  	ion_heap_buffer_zero(buffer);
>  
>  	if (ion_buffer_cached(buffer))
> -		dma_sync_sg_for_device(NULL, table->sgl, table->nents,
> -				       DMA_BIDIRECTIONAL);
> +		ion_clean_page(page, buffer->size);
>  
>  	ion_carveout_free(heap, paddr, buffer->size);
>  	sg_free_table(table);
> @@ -157,7 +156,7 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
>  	page = pfn_to_page(PFN_DOWN(heap_data->base));
>  	size = heap_data->size;
>  
> -	ion_pages_sync_for_device(NULL, page, size, DMA_BIDIRECTIONAL);
> +	ion_clean_page(page, size);
>  
>  	ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL));
>  	if (ret)
> diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c
> index e0553fe..0666529 100644
> --- a/drivers/staging/android/ion/ion_chunk_heap.c
> +++ b/drivers/staging/android/ion/ion_chunk_heap.c
> @@ -104,11 +104,10 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer)
>  
>  	ion_heap_buffer_zero(buffer);
>  
> -	if (ion_buffer_cached(buffer))
> -		dma_sync_sg_for_device(NULL, table->sgl, table->nents,
> -							DMA_BIDIRECTIONAL);
>  
>  	for_each_sg(table->sgl, sg, table->nents, i) {
> +		if (ion_buffer_cached(buffer))
> +			ion_clean_page(sg_page(table->sgl), sg->length);
>  		gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
>  			      sg->length);
>  	}
> @@ -148,7 +147,7 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data)
>  	page = pfn_to_page(PFN_DOWN(heap_data->base));
>  	size = heap_data->size;
>  
> -	ion_pages_sync_for_device(NULL, page, size, DMA_BIDIRECTIONAL);
> +	ion_clean_page(page, size);
>  
>  	ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL));
>  	if (ret)
> diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c
> index 1fe8016..b854f91 100644
> --- a/drivers/staging/android/ion/ion_page_pool.c
> +++ b/drivers/staging/android/ion/ion_page_pool.c
> @@ -30,8 +30,7 @@ static void *ion_page_pool_alloc_pages(struct ion_page_pool *pool)
>  
>  	if (!page)
>  		return NULL;
> -	ion_pages_sync_for_device(NULL, page, PAGE_SIZE << pool->order,
> -						DMA_BIDIRECTIONAL);
> +	ion_clean_page(page, PAGE_SIZE << pool->order);
>  	return page;
>  }
>  
> diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h
> index 0239883..b368338 100644
> --- a/drivers/staging/android/ion/ion_priv.h
> +++ b/drivers/staging/android/ion/ion_priv.h
> @@ -392,15 +392,9 @@ void ion_page_pool_free(struct ion_page_pool *, struct page *);
>  int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
>  			  int nr_to_scan);
>  
> -/**
> - * ion_pages_sync_for_device - cache flush pages for use with the specified
> - *                             device
> - * @dev:		the device the pages will be used with
> - * @page:		the first page to be flushed
> - * @size:		size in bytes of region to be flushed
> - * @dir:		direction of dma transfer
> - */
> -void ion_pages_sync_for_device(struct device *dev, struct page *page,
> -		size_t size, enum dma_data_direction dir);
> +void ion_clean_page(struct page *page, size_t size);
> +
> +void ion_clean_buffer(struct ion_buffer *buffer);
>  
> +void ion_invalidate_buffer(struct ion_buffer *buffer);
>  #endif /* _ION_PRIV_H */
> diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
> index b69dfc7..aa39660 100644
> --- a/drivers/staging/android/ion/ion_system_heap.c
> +++ b/drivers/staging/android/ion/ion_system_heap.c
> @@ -70,8 +70,7 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap,
>  		page = alloc_pages(gfp_flags | __GFP_COMP, order);
>  		if (!page)
>  			return NULL;
> -		ion_pages_sync_for_device(NULL, page, PAGE_SIZE << order,
> -						DMA_BIDIRECTIONAL);
> +		ion_clean_page(page, PAGE_SIZE << order);
>  	}
>  
>  	return page;
> @@ -360,7 +359,7 @@ static int ion_system_contig_heap_allocate(struct ion_heap *heap,
>  
>  	buffer->priv_virt = table;
>  
> -	ion_pages_sync_for_device(NULL, page, len, DMA_BIDIRECTIONAL);
> +	ion_clean_page(page, len);
>  
>  	return 0;
>  
> -- 
> 2.5.5
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ?\_(?)_/?


From gabriele.paoloni at huawei.com  Thu May 26 02:58:21 2016
From: gabriele.paoloni at huawei.com (Gabriele Paoloni)
Date: Thu, 26 May 2016 09:58:21 +0000
Subject: [PATCH V7 00/11] Support for generic ACPI based PCI host
 controller
In-Reply-To: <20160524190048.GA4288@localhost>
References: <3d4aae09-51c4-f007-5100-191a4a85e27a@redhat.com>
 <CAKv+Gu8fdeJ9OvRSmtu9zyvcjK3O-4WU=jG=6-7t4xZwvV8d2g@mail.gmail.com>
 <95b1d06e-f9c5-39f3-1003-f536b65eef60@redhat.com>
 <CAKv+Gu-_xp_t_Ze3Pw_-82-fmy=tCy-h=4FbP98eLbuXVk2hHQ@mail.gmail.com>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDAF6AC@lhreml503-mbs>
 <CAKv+Gu_zpoFsDr7e8zPCDKPpRdKDVH+vnC0nfvmGaJ7xcP3Zng@mail.gmail.com>
 <20160523105655.GA22902@red-moon>
 <EE11001F9E5DDD47B7634E2F8A612F2E1EDB35A5@lhreml503-mbs>
 <20160523233918.GA32555@localhost> <20160524172423.GA15855@red-moon>
 <20160524190048.GA4288@localhost>
Message-ID: <EE11001F9E5DDD47B7634E2F8A612F2E1EDB835E@lhreml503-mbs>

Hi Bjorn many thanks for your suggestions

> -----Original Message-----
> From: Bjorn Helgaas [mailto:helgaas at kernel.org]
> Sent: 24 May 2016 20:01
> To: Lorenzo Pieralisi
> Cc: Gabriele Paoloni; Ard Biesheuvel; Jon Masters; Tomasz Nowicki;
> arnd at arndb.de; will.deacon at arm.com; catalin.marinas at arm.com;
> rafael at kernel.org; hanjun.guo at linaro.org; okaya at codeaurora.org;
> jchandra at broadcom.com; linaro-acpi at lists.linaro.org; linux-
> pci at vger.kernel.org; dhdang at apm.com; Liviu.Dudau at arm.com;
> ddaney at caviumnetworks.com; jeremy.linton at arm.com; linux-
> kernel at vger.kernel.org; linux-acpi at vger.kernel.org;
> robert.richter at caviumnetworks.com; Suravee.Suthikulpanit at amd.com;
> msalter at redhat.com; Wangyijing; mw at semihalf.com;
> andrea.gallo at linaro.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH V7 00/11] Support for generic ACPI based PCI host
> controller
> 
> On Tue, May 24, 2016 at 06:24:23PM +0100, Lorenzo Pieralisi wrote:
> > Hi Bjorn,
> >
> > On Mon, May 23, 2016 at 06:39:18PM -0500, Bjorn Helgaas wrote:
> >
> > [...]
> >
> > > On Mon, May 23, 2016 at 03:16:01PM +0000, Gabriele Paoloni wrote:
> > > I don't think of ECAM support itself as a "driver".  It's just a
> > > service available to drivers, similar to OF resource parsing.
> > >
> > > Per PCI Firmware r3.2, sec 4.1.5, "PNP0A03" means a PCI/PCI-X/PCIe
> > > host bridge.  "PNP0A08" means a PCI-X Mode 2 or PCIe bridge that
> > > supports extended config space.  It doesn't specify how we access
> that
> > > config space, so I think hardware with non-standard ECAM should
> still
> > > have PNP0A03 and PNP0A08 in _CID or _HID.
> > >
> > > "ECAM" as used in the specs (PCIe r3.0, sec 7.2.2, and PCI Firmware
> > > r3.2, sec 4.1) means:
> > >
> > >   (a) a memory-mapped model for config space access, and
> > >   (b) a specific mapping of address bits to bus/device/function/
> > >       register
> > >
> > > MCFG and _CBA assume both (a) and (b), so I think a device with
> > > non-standard ECAM mappings should not be described in MCFG or _CBA.
> > >
> > > If a bridge has ECAM with non-standard mappings, I think either a
> > > vendor-specific _HID or a device-specific method, e.g., _DSM, could
> > > communicate that.
> > >
> > > Jon, I agree that we should avoid describing non-standardized
> hardware
> > > in Linux-specific ways.  Is there a mechanism in use already?  How
> > > does Windows handle this?  DMI is a poor long-term solution because
> it
> > > requires ongoing maintenance for new platforms, but I think it's OK
> > > for getting started with platforms already shipping.
> > >
> > > A _DSM has the advantage that once it is defined and supported,
> OEMs
> > > can ship new platforms without requiring a new quirk or a new _HID
> to
> > > be added to a driver.
> > >
> > > There would still be the problem of config access before the
> namespace
> > > is available, i.e., the MCFG use case.  I don't know how important
> > > that is.  Defining an MCFG extension seems like the most obvious
> > > solution.
> >
> > Your summary above is a perfect representation of the situation.
> >
> > We had an opportunity to sync-up on the current status of ACPI PCI
> > for ARM64 (and talked about a way forward for this series, which
> > includes quirks handling), let me summarize it here for everyone
> > involved so that we can agree on a way forward.
> >
> > 1) ACPI PCI support for PNP0A03/PNP0A08 host bridges on top of MCFG
> >    ECAM for config space is basically ready (Tomasz and JC addressed
> >    Rafael's concerns in relation to ARM64 specific code, and managed
> >    to find a way to allocate domain numbers in preparation for Arnd
> >    pci_create_root_bus() clean-up, v8 to be posted shortly and should
> >    be final). This provides support for de-facto ACPI/PCI ECAM base
> >    standard for ARM64 (with a clean-split between generic code and
> ARM64
> >    bits, where ARM64, like X86 and IA64, manages in arch code IO
> space and
> >    PCI resources, to be further consolidated in the near future).
> >    I do not think anyone can complain about the generality of what we
> >    achieved, for systems that are PCI standard (yes, PCI STANDARD)
> this
> >    would just be sufficient.
> 
> Sounds good to me.
> 
> > 2) In a real world (1) is not enough. Some ARM64 platforms, not
> entirely
> >    ECAM compliant, already shipped with the corresponding firmware
> that
> >    we can't update. HW has ECAM quirks and to work around it in the
> kernel
> >    we put forward many solutions to the problem, it is time we found
> a
> >    solution (when, of course, (1) is completed and upstream).
> >    Using the MCFG table OEMID matching floated around in this thread
> >    would work fine for most of the platforms (and cross-OS) that have
> >    shipped with HW ECAM quirks, so I think that's the starting point
> for
> >    our solution and that's how we can sort this out, _today_.
> >
> >    The solution is a trivial look-up table:
> >    MCFG OEMID <-> PCI config space ops
> 
> Sounds reasonable to me.
> 
> > 3) (2) does not just work on some platforms (and we can't predict the
> >    future either - actually I can, it is three letters, ECAM), simply
> >    because MCFG OEMID matching does not provide a way to attach
> further
> >    data to the MCFG (eg if config space for, say, bus 0 domain 0, is
> not
> >    ECAM compliant, the config region can't be handled and must not be
> >    handled through a corresponding MCFG region.
> 
> Couldn't this be handled by custom pci_ops that do something special
> for bus 0 domain 0, and default to some different pci_ops for the
> rest?

My idea was to remove bus 0 from domain 0 MCFG (and also the other
buses corresponding to the root complexes ports)

So the driver would use the ECAM access with addresses retrieved from
MCFG for any devices except the RCs.

For the RC we could retrieve special addresses from the "PNP0C02"
reserved resource... 


> 
> >    That's the problem Gabriele is facing and wants to solve through
> >    something like:
> >
> >    https://lkml.org/lkml/2016/3/9/91
> >
> >    in the respective ACPI tables-bindings. It may be an idea worth
> >    pursuing, it does not solve (2) simply because that FW has
> shipped,
> >    we can't patch it any longer.
> 
> (2) is for quirks to deal with MCFG.  Gabriele's post is a proposal
> for ACPI namespace.  We can't use anything in the namespace to
> implement MCFG quirks because MCFG is needed before the namespace is
> available.

Honestly I have to dig better into this (and I will once V8 is out),
However from my current understanding so far we have look-up where
MCFG OEMID is going to tell which specific pci-ops are going to be used.

Now from my quirk idea I need to retrieve the "special address" from the
ACPI namespace before cfg rd/wr take place...if this is not doable then
I need to find a different solution...than can be the one you proposed
below (many thanks for this).

I will look into details later on once v8 is out.

Thanks

Gab

> 
> I think Gabriele's post is a good proposal for the namespace, but I
> would propose the following modifications:
> 
>   - Add PNP0A08 to the PCI1 _CID since this is a PCIe host bridge
>   - Add a PCI1 _DSM describing the ECAM space
>   - Remove the HISI0081 _HID
> 
> The result would be:
> 
>   Device (PCI1) {
>     Name(_HID, "HISI0080")
>     Name(_CID, "PNP0A03,PNP0A08")
>     Method(_CRS) { ... }
>     Method(_DSM) { <describe ECAM base and mapping function> }
>   }
>   Device (RES0) {
>     Name(_HID, "PNP0C02")
>     Name(_CRS) { <describe ECAM base and size> }
>   }
> 
> RES0 could also be contained within PCI1, as Gabriele suggested.  I
> don't really care whether it's contained or not, and making it
> contained might make it easier for firmware, because addition/removal
> of PCI1 and RES0 should always happen together.
> 
> I think the _DSM is important because it is really ugly if the
> HISI0080 driver has to look for a separate HISI0081 device to learn
> about the ECAM space.  There are several PCI drivers that do something
> similar, using for_each_pci_dev(), and I cringe every time I see them,
> because this totally screws up the driver model.  A driver should
> claim a device via a .probe() method called by the core, and it
> shouldn't look at devices it hasn't claimed.  This is required to make
> hotplug work correctly.
> 
> > Hence to finally support ACPI PCI on ARM64 I suggest we carry out the
> > following steps, in order:
> >
> > - Let's complete/merge (1), that's fundamental to this whole thread
> > - On top of (1) we apply a quirking mechanism based on (2) that
> allows
> >   us to boot mainline with boxes shipping today with no FW update
> required.
> > - We devise a way to handle quirks that is more generic than (2) so
> that
> >   can we can accomodate further platforms that can't rely on (2) but
> >   have more leeway in terms of FW updates.
> >
> > I hope that's a reasonable plan, Tomasz's v8 series coming to kick it
> off.
> 
> Sounds very good to me; I'm looking forward to v8.
> 
> Bjorn


From carlo at caione.org  Thu May 26 03:06:55 2016
From: carlo at caione.org (Carlo Caione)
Date: Thu, 26 May 2016 12:06:55 +0200
Subject: [RFC PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <1464249112-13658-2-git-send-email-narmstrong@baylibre.com>
References: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
 <1464249112-13658-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160526100655.GB14703@mephisto>

On 26/05/16 09:51, Neil Armstrong wrote:
> Add watchdog specific driver for Amlogic Meson GXBB SoC.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> +

[...]
> +#define DEFAULT_TIMEOUT	10	/* seconds */
> +
> +#define GXBB_WDT_CTRL_REG	0x0
> +#define GXBB_WDT_CTRL1_REG	0x4
> +#define GXBB_WDT_TCNT_REG	0x8
> +#define GXBB_WDT_RSET_REG	0xc
> +
> +#define GXBB_WDT_CTRL_EE_RESET_NOW	BIT(26)
> +
> +#define GXBB_WDT_CTRL_CLKDIV_EN	BIT(25)
> +#define GXBB_WDT_CTRL_CLK_EN	BIT(24)
> +#define GXBB_WDT_CTRL_IRQ_EN	BIT(23)
> +#define GXBB_WDT_CTRL_EE_RESET	BIT(21)
> +#define GXBB_WDT_CTRL_XTAL_SEL	(0)
> +#define GXBB_WDT_CTRL_CLK81_SEL	BIT(19)
> +#define GXBB_WDT_CTRL_EN	BIT(18)
> +#define GXBB_WDT_CTRL_DIV_MASK	(BIT(18)-1)
> +
> +#define GXBB_WDT_CTRL1_GPIO_PULSE	BIT(17)
> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_0	BIT(16)
> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_1	(0)
> +#define GXBB_WDT_CTRL1_GPIO_PULSE_CNT	(BIT(16)-1)
> +
> +#define GXBB_WDT_TCNT_SETUP_MASK	(BIT(16)-1)
> +#define GXBB_WDT_TCNT_CNT_SHIFT		16

Indentation

[...]
> +int meson_gxbb_wdt_set_timeout(struct watchdog_device *wdt_dev,
> +			       unsigned int timeout)
> +{
> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> +
> +	if (watchdog_active(wdt_dev))
> +		meson_gxbb_wdt_stop(wdt_dev);
> +
> +	meson_gxbb_wdt_ping(wdt_dev);
> +
> +	writel(timeout*1000, data->reg_base + GXBB_WDT_TCNT_REG);

nit: spaces around "*"

[...]
> +	data->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(data->clk))
> +		return PTR_ERR(data->clk);
> +
> +	clk_prepare_enable(data->clk);

Do we need to merge the clock controller driver before this?

Cheers,

-- 
Carlo Caione


From carlo at caione.org  Thu May 26 03:09:01 2016
From: carlo at caione.org (Carlo Caione)
Date: Thu, 26 May 2016 12:09:01 +0200
Subject: [RFC PATCH 2/3] dt-bindings: watchdog: Add Meson GXBB Watchdog
 bindings
In-Reply-To: <1464249112-13658-3-git-send-email-narmstrong@baylibre.com>
References: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
 <1464249112-13658-3-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160526100901.GC14703@mephisto>

On 26/05/16 09:51, Neil Armstrong wrote:
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>  .../devicetree/bindings/watchdog/meson-gxbb-wdt.txt         | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt
> 
> diff --git a/Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt b/Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt
> new file mode 100644
> index 0000000..d06c0a0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt
> @@ -0,0 +1,13 @@
> +Meson GXBB SoCs Watchdog timer
> +
> +Required properties:
> +
> +- compatible : should be "amlogic,meson-gxbb-wdt"
> +- reg : Specifies base physical address and size of the registers.

'clocks' is also required IIRC.

Thanks,

-- 
Carlo Caione


From mark.rutland at arm.com  Thu May 26 03:56:52 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Thu, 26 May 2016 11:56:52 +0100
Subject: [PATCH] arm64/efi: remove spurious WARN_ON for !4K kernels
In-Reply-To: <CAKv+Gu94GLWUJBCtNUDb4Jak3KL0-MGkUfk82fZ5UdwWH60P_w@mail.gmail.com>
References: <1464189116-30898-1-git-send-email-mark.rutland@arm.com>
 <BA565A9C-8CC0-42E4-9821-7941852F835A@linaro.org>
 <20160525161207.GD30956@leverpostej>
 <CAKv+Gu94GLWUJBCtNUDb4Jak3KL0-MGkUfk82fZ5UdwWH60P_w@mail.gmail.com>
Message-ID: <20160526105652.GD32186@leverpostej>

On Wed, May 25, 2016 at 08:23:35PM +0200, Ard Biesheuvel wrote:
> On 25 May 2016 at 18:12, Mark Rutland <mark.rutland at arm.com> wrote:
> > On Wed, May 25, 2016 at 05:23:01PM +0200, Ard Biesheuvel wrote:
> >>
> >>
> >> > On 25 mei 2016, at 17:11, Mark Rutland <mark.rutland at arm.com> wrote:
> >> >
> >> > Since commit 1fd55a9a09b0293a ("arm64/efi: Apply strict permissions to
> >> > UEFI Runtime Services regions"), booting a !4K page kernel results in a
> >> > boot-time splat on some systems, due to to a WARN_ONCE added in that
> >> > commit which fires if the base address of an EFI memory descriptor is
> >> > not aligned to the kernel page size (which might be 4K, 16K, or 64K).
> >> >
> >> > On page 38 of the UEFI 2.6 specification it is stated:
> >> >
> >> >    If a 64KiB physical page contains any 4KiB page with any of the
> >> >    following types listed below, then all 4KiB pages in the 64KiB
> >> >    page must use identical ARM Memory Page Attributes (as described
> >> >    in Table 8):
> >> >    ? EfiRuntimeServicesCode
> >> >    ? EfiRuntimeServicesData
> >> >    ? EfiReserved
> >> >    ? EfiACPIMemoryNVS
> >> >    Mixed attribute mappings within a larger page are not allowed.
> >> >
> >>
> >> The same section mentions that the ro/xp etc attributes are unused on
> >> arm, so if we go by the letter here, we need to remove those memory
> >> protection features entirely. So a spec update is clearly in order
> >> here.
> >
> > Yes; that definitely needs fixing.
> >
> > FWIW, I don't think that matters in this case (assuming the usual EFI
> > memory desc dump stuff prints those).
> >
> > My memory map (and the remap triggering the WARN_ONCE) look like:
> >
> > [    0.000000] efi: Getting EFI parameters from FDT:
> > [    0.000000] efi:   System Table: 0x00000083ff34bf18
> > [    0.000000] efi:   MemMap Address: 0x00000083fcefd618
> > [    0.000000] efi:   MemMap Size: 0x00000540
> > [    0.000000] efi:   MemMap Desc. Size: 0x00000030
> > [    0.000000] efi:   MemMap Desc. Version: 0x00000001
> > [    0.000000] efi: EFI v2.40 by American Megatrends
> > [    0.000000] efi:  ACPI 2.0=0x83ff1c3000  SMBIOS 3.0=0x83ff347798
> > [    0.000000] efi: Processing EFI memory map:
> > [    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > [    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > [    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> > [    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
> > [    0.000000] efi:   0x008001e80000-0x008001ffffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x008002000000-0x008002ddffff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x008002de0000-0x00801fdfffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x00801fe00000-0x00801fe0ffff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x00801fe10000-0x00801fffbfff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x00801fffc000-0x00801fffffff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x008020000000-0x0083f0ffffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x0083f1000000-0x0083f101ffff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x0083f1020000-0x0083fb542fff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x0083fb543000-0x0083fc2a2fff [Loader Code        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x0083fc2a3000-0x0083fcefcfff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x0083fcefd000-0x0083fcefefff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x0083fceff000-0x0083fd01afff [Loader Code        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x0083fd01b000-0x0083fea67fff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x0083fea68000-0x0083febd3fff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x0083febd4000-0x0083ff186fff [Boot Code          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x0083ff187000-0x0083ff1b6fff [Reserved           |   |  |  |  |  |  |  |   |WB|WT|WC|UC]*
> > [    0.000000] efi:   0x0083ff1b7000-0x0083ff1c4fff [ACPI Reclaim Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]*
> > [    0.000000] efi:   0x0083ff1c5000-0x0083ff20ffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x0083ff210000-0x0083ff224fff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
> > [    0.000000] efi:   0x0083ff225000-0x0083ff226fff [ACPI Memory NVS    |   |  |  |  |  |  |  |   |WB|WT|WC|UC]*
> > [    0.000000] efi:   0x0083ff227000-0x0083ff34bfff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
> 
> OK, so how is this expected to work then, with the regions described
> above? Neither are covered by the linear mapping, and both have all of
> {WB,WT,WC,UC} set, which means that each region can be mapped by the
> OS as any of those types.

I was under the impression that in practice, we only mapped the memory
as WB (which happens to match the attributes for the linear mapping).

Where do we use WT, WC, or UC mappings in the kernel?

> I don't know which type we use for this
> particular ACPI Memory NVS region, but it could be any of those, while
> the runtime data regions are mapped as writeback cacheable in the EFI
> page tables. So while the spec needs to be updated, I think the de
> facto conclusion is that the only way we can do this safely is to
> either force 64 KB alignment, or -as a workaround- ensure that regions
> that share a 64 KB page frame are limited to the same attributes in
> the OS view of the UEFI memory map.

I think that we have to do the latter, given existing systems.

I would prefer the former, and if we can get that into the spec that
would be great.

Thanks,
Mark.


From linux at armlinux.org.uk  Thu May 26 03:59:22 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Thu, 26 May 2016 11:59:22 +0100
Subject: [RFC][PATCH 1/3] staging: ion: Move away from the DMA APIs for
 cache flushing
In-Reply-To: <20160526095835.GT23566@e106497-lin.cambridge.arm.com>
References: <1464205684-5587-1-git-send-email-labbott@redhat.com>
 <1464205684-5587-2-git-send-email-labbott@redhat.com>
 <20160526095835.GT23566@e106497-lin.cambridge.arm.com>
Message-ID: <20160526105922.GH19428@n2100.arm.linux.org.uk>

On Thu, May 26, 2016 at 10:58:35AM +0100, Liviu Dudau wrote:
> On Wed, May 25, 2016 at 12:48:02PM -0700, Laura Abbott wrote:
> > 
> > Ion is currently using the DMA APIs in non-compliant ways for cache
> > maintaince. The issue is Ion needs to do cache operations outside of
> > the regular DMA model. The Ion model matches more closely with the
> > DRM model which calls cache APIs directly. Add an appropriate
> > abstraction layer for Ion to call cache operations outside of the
> > DMA API.

I _really_ hate seeing architecture internal functions being abused in
drivers - architecture internal functions are there to implement the
official kernel APIs and are not for drivers to poke about with.

I've had this happen several times, and each time it makes maintanence
of architecture code harder than it should be.

In any case, the functions you are using are probably not appropriate -
the way I've defined the architecture internal functions is for each
to have a specific purpose.  Eg, if caches need flushing when page tables
change, then the function gets implemented, otherwise it's a no-op.  Using
a function which _seems_ to do the right thing today in a way which is
against its purpose is a recipe for your code breaking.

If you need something from the architecture which isn't already provided,
then you need to talk to architecture people about proposing an official
interface to that functionality, rather than trying to bolt per-
architecture shims into drivers.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From p.zabel at pengutronix.de  Thu May 26 04:02:42 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Thu, 26 May 2016 13:02:42 +0200
Subject: [PATCH v2 1/4] reset: Add support for the Amlogic Meson SoC
 Reset Controller
In-Reply-To: <m2iny1h74c.fsf@baylibre.com>
References: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
 <1464169758-26975-2-git-send-email-narmstrong@baylibre.com>
 <m2iny1h74c.fsf@baylibre.com>
Message-ID: <1464260562.4109.77.camel@pengutronix.de>

Hi Kevin,

Am Mittwoch, den 25.05.2016, 19:42 -0700 schrieb Kevin Hilman:
> Neil Armstrong <narmstrong at baylibre.com> writes:
> 
> > This patch adds the platform driver for the Amlogic Meson SoC Reset
> > Controller.
> >
> > The Meson8b and GXBB SoCs are supported.
> >
> > Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> 
> Maybe a question for Philipp, but when testog this version with the
> stmmac ethernet driver on the Amlogic boards, I noticed that ->reset was
> never getting called.
> 
> Turns out, the stmmac driver only uses reset_control_assert() and
> reset_control_deassert(), both of which return -ENOTSUPP since this
> driver doesn't provide ->assert or ->deassert, so the driver's ->reset()
> never gets called.
> 
> I haven't looked into the reset framework in detail, but if there's only
> a ->reset hook, I kind of expected that reset_control_deassert() would
> use that instead of returning -ENOTSUPP.
> 
> If not, what's the proper way of handling hardware that only supports a
> write-only reset pulse?  Should users of reset_control_* be adapted to
> check if ->deassert returns -ENOTSUPP and call ->reset?

I initially came up with this for i.MX6, which has a reset controller
that just like the Meson ones doesn't support manual assertion and
deassertion of the reset line.
My assumption then was that reset() is the default for all devices that
just need their internal state to be reset at some point. I didn't
expect the clock-like usage of manual deassert()/assert() for power
management to become so common.
So assert() and deassert() return -ENOTSUPP if the reset controller
doesn't support manually asserting or deasserting the reset line.

Of course you can argue that after a reset() pulse the reset line is
deasserted, and if you instead interpret the API in terms of expected
outcome, that would be similar to the state after call to deassert()
(iff the line was asserted before).
That would blur the line between reset() and deassert() somewhat, and in
my opinion having a call to deassert() first doing the exact opposite
isn't good nomenclature.
Personally, I'd prefer if the driver could switch to only using
	reset_control_reset(rstc);
or, if the reset line needs to stay asserted during powerdown where the
reset controller supports it, but doesn't matter whert not, use:
	ret = reset_control_deassert(rstc);
	if (ret == -ENOTSUPP)
		ret = reset_control_reset(rstc);

We could add a helper reset_control_deassert_or_reset() for that.

regards
Philipp



From dongas86 at gmail.com  Thu May 26 04:27:18 2016
From: dongas86 at gmail.com (Dong Aisheng)
Date: Thu, 26 May 2016 19:27:18 +0800
Subject: [PATCH 3/3] mmc: core: support hs speed mode if hs200 mode fails
In-Reply-To: <1463130397.3151.13.camel@toradex.com>
References: <1461171092-30631-1-git-send-email-aisheng.dong@nxp.com>
 <1461171092-30631-3-git-send-email-aisheng.dong@nxp.com>
 <1463130397.3151.13.camel@toradex.com>
Message-ID: <CAA+hA=SZQSjSU73_8sityJ_FZHngqaHZwspyg-iMBRzr_z7vRA@mail.gmail.com>

On Fri, May 13, 2016 at 5:06 PM, Marcel Ziswiler
<marcel.ziswiler at toradex.com> wrote:
> On Thu, 2016-04-21 at 00:51 +0800, Dong Aisheng wrote:
>> Currently if mmc_select_hs200 mode switch fails, MMC core
>> can only use legacy mode to run the card.
>> Let's retry HS speed mode if HS200 fails.
>>
>> Before the fix:
>> mmc0: mmc_select_hs200 failed, error -74
>> : switch to mmc0 failed
>> mmc0: new MMC card at address 0001
>> mmcblk0: mmc0:0001 Q2J55L 7.12 GiB
>> mmcblk0boot0: mmc0:0001 Q2J55L partition 1 2.00 MiB
>> mmcblk0boot1: mmc0:0001 Q2J55L partition 2 2.00 MiB
>> mmcblk0rpmb: mmc0:0001 Q2J55L partition 3 4.00 MiB
>>  mmcblk0: p1 p2
>>
>> After the fix:
>> mmc0: mmc_select_hs200 failed, error -74
>> mmc0: new DDR MMC card at address 0001
>> mmcblk0: mmc0:0001 Q2J55L 7.12 GiB
>> mmcblk0boot0: mmc0:0001 Q2J55L partition 1 2.00 MiB
>> mmcblk0boot1: mmc0:0001 Q2J55L partition 2 2.00 MiB
>> mmcblk0rpmb: mmc0:0001 Q2J55L partition 3 4.00 MiB
>>  mmcblk0: p1 p2
>>
>> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
>> ---
>>  drivers/mmc/core/mmc.c | 3 ++-
>>  1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>> index 55c8201..b573dc7 100644
>> --- a/drivers/mmc/core/mmc.c
>> +++ b/drivers/mmc/core/mmc.c
>> @@ -1315,7 +1315,8 @@ static int mmc_select_timing(struct mmc_card
>> *card)
>>
>>       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
>>               err = mmc_select_hs200(card);
>> -     else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
>> +
>> +     if (err && (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS))
>>               err = mmc_select_hs(card);
>>
>>       if (err && err != -EBADMSG)
>
>
> This seems to break on TK1 where eMMC so far was detected as an 8-bit
> high speed MMC card. With this patch it reverts to detecting a 1-bit only
> MMC card! This has been observed both on a NVIDIA's Jetson TK1 as well as
> our new Toradex Apalis TK1 (CC Tegra mailing list, Jon Hunter and Lucas
> Stach as well). So far T30 is not affected as there we are still doing
> full HS200 with whatever issues that has.
>

Oh, sorry, just found there's a logic error in the patch.
It may wrongly bypass the HS mode select for non hs200 mode eMMCs
due to the 'err' condition.

Will send a fixed version.

Regards
Dong Aisheng

> Before:
> [    3.726894] sdhci: Secure Digital Host Controller Interface driver
> [    3.733081] sdhci: Copyright(c) Pierre Ossman
> [    3.737462] sdhci-pltfm: SDHCI platform and OF driver helper
> [    3.753411] mmc0: Unknown controller version (3). You may experience
>  problems.
> [    3.768345] mmc0: Invalid maximum block size, assuming 512 bytes
> [    3.814896] mmc0: SDHCI controller on 700b0600.sdhci [700b0600.sdhci]
>  using ADMA 64-bit
> [    3.892088] mmc0: new high speed MMC card at address 0001
> [    3.899194] mmcblk0: mmc0:0001 SEM16G 14.7 GiB
> [    3.904217] mmcblk0boot0: mmc0:0001 SEM16G partition 1 4.00 MiB
> [    3.910645] mmcblk0boot1: mmc0:0001 SEM16G partition 2 4.00 MiB
> [    3.917119] mmcblk0rpmb: mmc0:0001 SEM16G partition 3 4.00 MiB
> [    3.926006]  mmcblk0: p1 p2 p3 p4 p5 p6 p7 p8 p9
> root at jetson_tk1:~# cat /sys/kernel/debug/mmc0/ios
> clock:          52000000 Hz
> actual clock:   51000000 Hz
> vdd:            21 (3.3 ~ 3.4 V)
> bus mode:       2 (push-pull)
> chip select:    0 (don't care)
> power mode:     2 (on)
> bus width:      3 (8 bits)
> timing spec:    1 (mmc high-speed)
> signal voltage: 0 (3.30 V)
> driver type:    0 (driver type B)
>
> After:
> [    3.899918] mmc0: new MMC card at address 0001
> root at jetson_tk1:~# cat /sys/kernel/debug/mmc0/ios
> clock:          25000000 Hz
> actual clock:   24727273 Hz
> vdd:            21 (3.3 ~ 3.4 V)
> bus mode:       2 (push-pull)
> chip select:    0 (don't care)
> power mode:     2 (on)
> bus width:      0 (1 bits)
> timing spec:    0 (legacy)
> signal voltage: 0 (3.30 V)
> driver type:    0 (driver type B)
>


From grinberg at compulab.co.il  Thu May 26 04:37:06 2016
From: grinberg at compulab.co.il (Igor Grinberg)
Date: Thu, 26 May 2016 14:37:06 +0300
Subject: [PATCH 1/2] ARM: dts: imx6q: extend support for the cm-fx6
In-Reply-To: <1464256217.14453.10.camel@pengutronix.de>
References: <709d6b3d522f4fcb8112830e0426dbb3@rwthex-s1-b.rwth-ad.de>
 <1463994191.2370.3.camel@pengutronix.de> <5746B8C4.6020406@compulab.co.il>
 <1464256217.14453.10.camel@pengutronix.de>
Message-ID: <5746DFE2.9040903@compulab.co.il>

On 05/26/2016 12:50 PM, Lucas Stach wrote:
> Hi Igor,
> 
> Am Donnerstag, den 26.05.2016, 11:50 +0300 schrieb Igor Grinberg:
>> Hi Lucas,
>>
>> Thanks for reviewing the patch(es).
>>
>> On 05/23/2016 12:03 PM, Lucas Stach wrote:
>>> Am Montag, den 23.05.2016, 00:47 +0200 schrieb
>>> christopher.spinrath at rwth-aachen.de:
>>>> From: Christopher Spinrath <christopher.spinrath at rwth-aachen.de>
>>
>> [...]
>>
>>>> +&ecspi1 {
>>>> +	fsl,spi-num-chipselects = <2>;
>>>> +	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
>>>> +	pinctrl-names = "default";
>>>> +	pinctrl-0 = <&pinctrl_ecspi1>;
>>>> +	status = "okay";
>>>> +
>>>> +	flash: m25p80 at 0 {
>>>> +		#address-cells = <1>;
>>>> +		#size-cells = <1>;
>>>> +		compatible = "st,m25p", "jedec,spi-nor";
>>>> +		spi-max-frequency = <20000000>;
>>>> +		reg = <0>;
>>>> +
>>>> +		partition at 0 {
>>>> +			label = "uboot";
>>>> +			reg = <0x0 0xc0000>;
>>>> +		};
>>>> +
>>>> +		partition at c0000 {
>>>> +			label = "uboot environment";
>>>> +			reg = <0xc0000 0x40000>;
>>>> +		};
>>>> +
>>>> +		partition at 100000 {
>>>> +			label = "reserved";
>>>> +			reg = <0x100000 0x100000>;
>>>> +		};
>>>
>>> Partition layouts don't belong in the upstream DT, as it a device
>>> configuration thing. Please kep them in the bootloader/firmware and make
>>> this one pass the partition layout to the kernel.
>>
>> I don't completely agree with this.
>> We have lots of partition layouts in the upstream DT.
> 
> No, we don't. At least not for the i.MX6. There are some for the earlier
> i.MX boards, but IMO it's wrong to put device configuration into the
> upstream DT. Let's not start doing this again.

Why not?
For i.MX6 there are 2 boards that have the partitioning scheme.
I'm not considering this a device configuration, but rather
a default partitioning layout/scheme.
Current case is for the firmware storage device that is not likely
to change.
Moreover, a DT is not really a part of the kernel, but lays along the kernel
sources for convenience and simplicity (at least IIRC as it was decided
about 5 years ago). It is more a part of the firmware for a device, than
an upstream kernel source code.
I think it is only a meter of time when Linus will decide that he does not
want it inside the kernel anymore...

> 
>> Moreover, this is the default layout and changing it, will
>> result in incompatibilities and also might result in device "bricking".
>> Those can be changed from the boot loader in case you need those
>> the other way around.
>> Another question of mine is, why should you?
>>
> Partition layout is device configuration, which is governed by the
> device firmware.

Yet again, DT is a part of device firmware.
Moreover, the firmware (in that case U-Boot), can be configured
using the very same DT code, so not having this in, might force
various w/a and hacks.

> By not having the partition layout in the upstream DT
> people are forced to set it from the firmware, which is exactly the
> right thing to do, weather or not you plan to change it at any time.

I might be ignorant, sorry for that.
Why? Why is it right and why would you want to force people to do that?


-- 
Regards,
Igor.


From dongas86 at gmail.com  Thu May 26 04:41:28 2016
From: dongas86 at gmail.com (Dong Aisheng)
Date: Thu, 26 May 2016 19:41:28 +0800
Subject: [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt
 during no data transfer
In-Reply-To: <573184F3.50201@intel.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-10-git-send-email-aisheng.dong@nxp.com>
 <573184F3.50201@intel.com>
Message-ID: <20160526114128.GA23988@shlinux2>

On Tue, May 10, 2016 at 09:51:31AM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > Current code will report the wrong data interrupt got when no
> > data operation in progress assumed by getting !host->data in
> > sdhci_data_irq().
> > 
> > For a data command handling process, the driver will call
> > sdhci_finish_data() and clear host->data in case any data error,
> > then card finish_tasklet will do the rest controller reset work.
> > 
> > Before the tasklet got run, however, controllers may report the
> > TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
> > than data CRC error and data end bit error interrupts for single
> > block transfer or the last block of multiblock transfer.
> > 
> > Controller usually detects and generates data CRC/end bit error
> > interrupts once one block on the bus is transferred completely.
> > For single block transfer, since there's only one bock to transfer,
> > the controller will report transfer complete interrupt as well,
> > but until the data in controller FIFO has been successfully
> > transferred to memory. The time gap of TC and CRC interrupt depends on
> > the system busy state at that point and memory bus access speed.
> > 
> > So it is possible when TC interrupt generated, host->data is already
> > equal to NULL due to cleared by former CRC/Data End Bit error which
> > is reasonable.
> > 
> > Thus we DO NOT report the weird data interrupt event for this case.
> > 
> > Else we may easily see warning below during SD3.0 card manually tuning
> > process (calling mmc_send_tuning() which is a single block transfer)
> > mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
> > 
> > The detailed command log is as follows:
> > [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
> > [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
> > [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
> > [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
> > [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
> > [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
> > [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
> > [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
> > [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
> > [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
> > [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
> > [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
> > [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
> > [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
> > [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
> > [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
> > [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
> > [ 1657.929965] sdhci: Host ctl2: 0x000000c8
> > [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
> > [ 1657.929995] sdhci: ===========================================
> > [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
> > [ 1657.930179] mmc0:     0 bytes transferred: -84
> > 
> > It shows we first have a data CRC error interrupt then a data transfer
> > complete interrupt.
> > Then we got the !host->data case in sdhci_data_irq().
> > 
> > CC: stable <stable at vger.kernel.org>
> > Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
> > ---
> >  drivers/mmc/host/sdhci.c | 11 +++++++++++
> >  1 file changed, 11 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index 40e3551..2eb0e34 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
> >  			}
> >  		}
> >  
> > +		/*
> > +		 * The "data complete" interrupt is possible to happen a bit
> > +		 * later than CRC error and data end bit error interrupts
> > +		 * separately for single block transfer or the last block of
> > +		 * multiblock transfer. For this case, we DO NOT report the
> > +		 * weird data interrupt event.
> > +		 */
> > +		if ((intmask & SDHCI_INT_DATA_END) &&
> > +		    (host->mrq && host->mrq->data && host->mrq->data->error))
> > +			return;
> 
> This could be generalized a bit more i.e. what about:
> 
> 		/*
> 		 * After an error and before the the data circuit is reset in
> 		 * sdhci_tasklet_finish, we could get more interrupts, but we
> 		 * already have an error, so ignore them.
> 		 */
> 		if (host->mrq && host->mrq->data && host->mrq->data->error)
> 			return;
> 

Sounds good to me.
If you wouldn't mind, i'd like to add a bit more:
		/*
		 * After an error and before the data circuit is reset in
		 * sdhci_tasklet_finish, we could get more interrupts
		 * e.g. "data complete" interrupt, but we already have
		 * an error, so ignore them.
		 */

Regards
Dong Aisheng

> > +
> >  		pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
> >  		       mmc_hostname(host->mmc), (unsigned)intmask);
> >  		sdhci_dumpregs(host);
> > 
> 


From thunder.leizhen at huawei.com  Thu May 26 04:46:11 2016
From: thunder.leizhen at huawei.com (Leizhen (ThunderTown))
Date: Thu, 26 May 2016 19:46:11 +0800
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <20160525105022.GC5996@e104818-lin.cambridge.arm.com>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
 <20160524113727.GD25374@leverpostej> <574446B9.8040105@huawei.com>
 <20160524130255.GU4892@e104818-lin.cambridge.arm.com>
 <5744FDD0.8060504@huawei.com> <57451DC6.7080106@huawei.com>
 <20160525105022.GC5996@e104818-lin.cambridge.arm.com>
Message-ID: <5746E203.4000906@huawei.com>



On 2016/5/25 18:50, Catalin Marinas wrote:
> On Wed, May 25, 2016 at 11:36:38AM +0800, Leizhen (ThunderTown) wrote:
>> On 2016/5/25 9:20, Leizhen (ThunderTown) wrote:
>>> On 2016/5/24 21:02, Catalin Marinas wrote:
>>>> On Tue, May 24, 2016 at 08:19:05PM +0800, Leizhen (ThunderTown) wrote:
>>>>> On 2016/5/24 19:37, Mark Rutland wrote:
>>>>>> It looks like the test may be missing I-cache maintenance regardless of
>>>>>> the semantics of mprotect in this case.
>>>>>>
>>>>>> I have not yet devled into flush_cache_range and how it is called.
>>>>>
>>>>> SYSCALL_DEFINE3(mprotect ---> mprotect_fixup ---> change_protection ---> change_protection_range --> flush_cache_range
>>>>
>>>> The change_protection() shouldn't need to flush the caches in
>>>> flush_cache_range(). The change_pte_range() function eventually ends up
>>>> calling set_pte_at() which calls __sync_icache_dcache() if the mapping
>>>> is executable.
>>>
>>> OK, I see.
>>> But I'm afraid it entered the "if (pte_present(oldpte))" branch in
>>> function change_pte_range. Because the test case called mmap to
>>> create pte first, then called pte_modify. I will check it later.
>>
>> I have checked that it entered "if (pte_present(oldpte))" branch.
> 
> This path eventually calls set_pte_at() via ptep_modify_prot_commit().
> 
>> But I don't known why I add flush_icache_range is OK, but add
>> __sync_icache_dcache have no effect.
> 
> Do you mean you modified set_pte_at() to use flush_icache_range()
> instead of __sync_icache_dcache() and it works?
> 
> What happens is that __sync_icache_dcache() only takes care of the first
> time a page is mapped in user space and flushes the caches, marking it
> as "clean" (PG_dcache_clean) afterwards. Subsequent changes to this

Hi,
As my tracing, it is returned by "if (!page_mapping(page))", because "mmap" are anonymous pages. I commented below code lines, it works well.
	
	/* no flushing needed for anonymous pages */
	if (!page_mapping(page))
		return;


I printed the page information three times, as below:
page->mapping=ffff8017baf36961, page->flags=0x1000000000040048
page->mapping=ffff8017b265bf51, page->flags=0x1000000000040048
page->mapping=ffff8017b94fc5a1, page->flags=0x1000000000040048

PG_slab=7, PG_arch_1=9, PG_swapcache=15

> mapping or writes to it are entirely the responsibility of the user. So
> if the user plans to execute instructions, it better explicitly flush
> the caches (as Mark Rutland already stated in a previous reply).
> 
> I ran our internal LTP version yesterday and it was fine but didn't
> realise that we actually patched mprotect04.c to include:
> 
> 	__clear_cache((char *)func, (char *)func + page_sz);
> 
> just after memcpy().
> 
> (we still need to investigate whether the I-cache invalidation is
> actually needed in flush_cache_range() or it's just something we forgot
> to remove)
> 



From dongas86 at gmail.com  Thu May 26 04:45:49 2016
From: dongas86 at gmail.com (Dong Aisheng)
Date: Thu, 26 May 2016 19:45:49 +0800
Subject: [PATCH 21/23] mmc: sdhci-esdhc-imx: factor out hw related
 intialization into function
In-Reply-To: <5731D0FF.60807@intel.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-22-git-send-email-aisheng.dong@nxp.com>
 <5731D0FF.60807@intel.com>
Message-ID: <20160526114548.GB23988@shlinux2>

On Tue, May 10, 2016 at 03:15:59PM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > Factor out hw related intialization into a separate function which
> > has two benifits:
> > 1) concentrate hw related intialization at one place
> > 2) ease the hw state restore after resume by simply
> > calling this function
> 
> There are really 2 changes here, please make it 2 patches.
> 

Okay i will do it in V2.
Thanks for the suggestion.

Regards
Dong Aisheng

> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c | 76 +++++++++++++++++++++-----------------
> >  1 file changed, 42 insertions(+), 34 deletions(-)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 3ff213f..95f3632 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -978,6 +978,44 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
> >  	.ops = &sdhci_esdhc_ops,
> >  };
> >  
> > +static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)
> > +{
> > +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > +	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
> > +
> > +	if (esdhc_is_usdhc(imx_data)) {
> > +		/*
> > +		 * The imx6q ROM code will change the default watermark
> > +		 * level setting to something insane.  Change it back here.
> > +		 */
> > +		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> > +
> > +		/*
> > +		 * ROM code will change the bit burst_length_enable setting
> > +		 * to zero if this usdhc is choosed to boot system. Change
> > +		 * it back here, otherwise it will impact the performance a
> > +		 * lot. This bit is used to enable/disable the burst length
> > +		 * for the external AHB2AXI bridge, it's usefully especially
> > +		 * for INCR transfer because without burst length indicator,
> > +		 * the AHB2AXI bridge does not know the burst length in
> > +		 * advance. And without burst length indicator, AHB INCR
> > +		 * transfer can only be converted to singles on the AXI side.
> > +		 */
> > +		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
> > +			| ESDHC_BURST_LEN_EN_INCR,
> > +			host->ioaddr + SDHCI_HOST_CONTROL);
> > +		/*
> > +		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
> > +		* TO1.1, it's harmless for MX6SL
> > +		*/
> > +		writel(readl(host->ioaddr + 0x6c) | BIT(7),
> > +			host->ioaddr + 0x6c);
> > +
> > +		/* disable DLL_CTRL delay line settings */
> > +		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
> > +	}
> > +}
> > +
> >  #ifdef CONFIG_OF
> >  static int
> >  sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
> > @@ -1175,43 +1213,13 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
> >  		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK
> >  			| SDHCI_QUIRK_BROKEN_ADMA;
> >  
> > -	/*
> > -	 * The imx6q ROM code will change the default watermark level setting
> > -	 * to something insane.  Change it back here.
> > -	 */
> > -	if (esdhc_is_usdhc(imx_data)) {
> > -		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> > +	sdhci_esdhc_imx_hwinit(host);
> >  
> > +	if (esdhc_is_usdhc(imx_data)) {
> >  		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
> >  		host->mmc->caps |= MMC_CAP_1_8V_DDR;
> > -
> > -		/*
> > -		 * ROM code will change the bit burst_length_enable setting
> > -		 * to zero if this usdhc is choosed to boot system. Change
> > -		 * it back here, otherwise it will impact the performance a
> > -		 * lot. This bit is used to enable/disable the burst length
> > -		 * for the external AHB2AXI bridge, it's usefully especially
> > -		 * for INCR transfer because without burst length indicator,
> > -		 * the AHB2AXI bridge does not know the burst length in
> > -		 * advance. And without burst length indicator, AHB INCR
> > -		 * transfer can only be converted to singles on the AXI side.
> > -		 */
> > -		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
> > -			| ESDHC_BURST_LEN_EN_INCR,
> > -			host->ioaddr + SDHCI_HOST_CONTROL);
> > -
> >  		if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))
> >  			host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
> > -
> > -		/*
> > -		* errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
> > -		* TO1.1, it's harmless for MX6SL
> > -		*/
> > -		writel(readl(host->ioaddr + 0x6c) | BIT(7),
> > -			host->ioaddr + 0x6c);
> > -
> > -		/* disable DLL_CTRL delay line settings */
> > -		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL);
> >  	}
> >  
> >  	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
> > @@ -1289,8 +1297,8 @@ static int sdhci_esdhc_resume(struct device *dev)
> >  {
> >  	struct sdhci_host *host = dev_get_drvdata(dev);
> >  
> > -	/* restore watermark setting in case it's lost in low power mode */
> > -	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> > +	/* reinitialize hw state in case it's lost in low power mode */
> > +	sdhci_esdhc_imx_hwinit(host);
> >  
> >  	return sdhci_pltfm_resume(dev);
> >  }
> > 
> 


From dongas86 at gmail.com  Thu May 26 04:47:48 2016
From: dongas86 at gmail.com (Dong Aisheng)
Date: Thu, 26 May 2016 19:47:48 +0800
Subject: [PATCH 20/23] mmc: sdhci-esdhc-imx: fix strobe DLL lock wrong
 clock issue
In-Reply-To: <5731CE24.2090002@intel.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-21-git-send-email-aisheng.dong@nxp.com>
 <5731CE24.2090002@intel.com>
Message-ID: <20160526114748.GC23988@shlinux2>

On Tue, May 10, 2016 at 03:03:48PM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > When enable DDR, the clock factor definition is changed.
> > e.g. original 200Mhz will become 100Mhz one MIX_CTRL_DDREN bit is set
> > So we need to update the clock setting then the strobe dll can lock
> > the correct clock rate.
> > 
> > Additionally we also need disable the clock before locking strobe dll.
> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
> 
> Apart from redundant parentheses (refer below):
> 
> Acked-by: Adrian Hunter <adrian.hunter at intel.com>
> 

Could remove in V2.
Thanks for the suggestion.

Regards
Dong Aisheng

> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c | 7 +++++++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 07b1144..3ff213f 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -852,6 +852,11 @@ static void esdhc_set_strobe_dll(struct sdhci_host *host)
> >  	u32 v;
> >  
> >  	if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
> > +		/* disable clock before enabling strobe dll */
> > +		writel(readl(host->ioaddr + ESDHC_VENDOR_SPEC) &
> > +		       (~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON),
> 
> Parentheses look redundant
> 
> > +		       host->ioaddr + ESDHC_VENDOR_SPEC);
> > +
> >  		/* force a reset on strobe dll */
> >  		writel(ESDHC_STROBE_DLL_CTRL_RESET,
> >  			host->ioaddr + ESDHC_STROBE_DLL_CTRL);
> > @@ -913,6 +918,8 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
> >  		m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN;
> >  		writel(m, host->ioaddr + ESDHC_MIX_CTRL);
> >  		imx_data->is_ddr = 1;
> > +		/* update clock after enable DDR for strobe DLL lock */
> > +		host->ops->set_clock(host, host->clock);
> >  		esdhc_set_strobe_dll(host);
> >  		break;
> >  	}
> > 
> 


From adrian.hunter at intel.com  Thu May 26 04:59:34 2016
From: adrian.hunter at intel.com (Adrian Hunter)
Date: Thu, 26 May 2016 14:59:34 +0300
Subject: [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during
 no data transfer
In-Reply-To: <20160526114128.GA23988@shlinux2>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-10-git-send-email-aisheng.dong@nxp.com>
 <573184F3.50201@intel.com> <20160526114128.GA23988@shlinux2>
Message-ID: <5746E526.8020001@intel.com>

On 26/05/16 14:41, Dong Aisheng wrote:
> On Tue, May 10, 2016 at 09:51:31AM +0300, Adrian Hunter wrote:
>> On 15/04/16 20:29, Dong Aisheng wrote:
>>> Current code will report the wrong data interrupt got when no
>>> data operation in progress assumed by getting !host->data in
>>> sdhci_data_irq().
>>>
>>> For a data command handling process, the driver will call
>>> sdhci_finish_data() and clear host->data in case any data error,
>>> then card finish_tasklet will do the rest controller reset work.
>>>
>>> Before the tasklet got run, however, controllers may report the
>>> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
>>> than data CRC error and data end bit error interrupts for single
>>> block transfer or the last block of multiblock transfer.
>>>
>>> Controller usually detects and generates data CRC/end bit error
>>> interrupts once one block on the bus is transferred completely.
>>> For single block transfer, since there's only one bock to transfer,
>>> the controller will report transfer complete interrupt as well,
>>> but until the data in controller FIFO has been successfully
>>> transferred to memory. The time gap of TC and CRC interrupt depends on
>>> the system busy state at that point and memory bus access speed.
>>>
>>> So it is possible when TC interrupt generated, host->data is already
>>> equal to NULL due to cleared by former CRC/Data End Bit error which
>>> is reasonable.
>>>
>>> Thus we DO NOT report the weird data interrupt event for this case.
>>>
>>> Else we may easily see warning below during SD3.0 card manually tuning
>>> process (calling mmc_send_tuning() which is a single block transfer)
>>> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
>>>
>>> The detailed command log is as follows:
>>> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
>>> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
>>> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
>>> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
>>> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
>>> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
>>> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
>>> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
>>> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
>>> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
>>> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
>>> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
>>> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
>>> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
>>> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
>>> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
>>> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
>>> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
>>> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
>>> [ 1657.929995] sdhci: ===========================================
>>> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
>>> [ 1657.930179] mmc0:     0 bytes transferred: -84
>>>
>>> It shows we first have a data CRC error interrupt then a data transfer
>>> complete interrupt.
>>> Then we got the !host->data case in sdhci_data_irq().
>>>
>>> CC: stable <stable at vger.kernel.org>
>>> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
>>> ---
>>>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>>>  1 file changed, 11 insertions(+)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 40e3551..2eb0e34 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>>>  			}
>>>  		}
>>>  
>>> +		/*
>>> +		 * The "data complete" interrupt is possible to happen a bit
>>> +		 * later than CRC error and data end bit error interrupts
>>> +		 * separately for single block transfer or the last block of
>>> +		 * multiblock transfer. For this case, we DO NOT report the
>>> +		 * weird data interrupt event.
>>> +		 */
>>> +		if ((intmask & SDHCI_INT_DATA_END) &&
>>> +		    (host->mrq && host->mrq->data && host->mrq->data->error))
>>> +			return;
>>
>> This could be generalized a bit more i.e. what about:
>>
>> 		/*
>> 		 * After an error and before the the data circuit is reset in
>> 		 * sdhci_tasklet_finish, we could get more interrupts, but we
>> 		 * already have an error, so ignore them.
>> 		 */
>> 		if (host->mrq && host->mrq->data && host->mrq->data->error)
>> 			return;
>>
> 
> Sounds good to me.
> If you wouldn't mind, i'd like to add a bit more:
> 		/*
> 		 * After an error and before the data circuit is reset in
> 		 * sdhci_tasklet_finish, we could get more interrupts
> 		 * e.g. "data complete" interrupt, but we already have
> 		 * an error, so ignore them.
> 		 */
> 

Fine by me




From linux at armlinux.org.uk  Thu May 26 05:04:06 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Thu, 26 May 2016 13:04:06 +0100
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <5746E203.4000906@huawei.com>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
 <20160524113727.GD25374@leverpostej> <574446B9.8040105@huawei.com>
 <20160524130255.GU4892@e104818-lin.cambridge.arm.com>
 <5744FDD0.8060504@huawei.com> <57451DC6.7080106@huawei.com>
 <20160525105022.GC5996@e104818-lin.cambridge.arm.com>
 <5746E203.4000906@huawei.com>
Message-ID: <20160526120406.GI19428@n2100.arm.linux.org.uk>

On Thu, May 26, 2016 at 07:46:11PM +0800, Leizhen (ThunderTown) wrote:
> Hi,
> As my tracing, it is returned by "if (!page_mapping(page))", because "mmap" are anonymous pages. I commented below code lines, it works well.
> 	
> 	/* no flushing needed for anonymous pages */
> 	if (!page_mapping(page))
> 		return;
> 
> 
> I printed the page information three times, as below:
> page->mapping=ffff8017baf36961, page->flags=0x1000000000040048
> page->mapping=ffff8017b265bf51, page->flags=0x1000000000040048
> page->mapping=ffff8017b94fc5a1, page->flags=0x1000000000040048
> 
> PG_slab=7, PG_arch_1=9, PG_swapcache=15

Well, I think we first need to establish what the semantics of changing
any region from PROT_READ|PROT_WRITE to PROT_READ|PROT_EXEC are as far
as cache coherence goes.  As I've already said, POSIX says nothing about
this aspect, so the specifications don't define what the expectations
are here.  So, I don't think we can say that anything is wrong.

> > I ran our internal LTP version yesterday and it was fine but didn't
> > realise that we actually patched mprotect04.c to include:
> > 
> > 	__clear_cache((char *)func, (char *)func + page_sz);
> > 
> > just after memcpy().

The question here is what is the justification for this LTP test -
surely, all tests in LTP should refer to some specification justifying
the test, which allows diagnosis of whether the LTP test is wrong or
whether the environment being tested is wrong.

However, the PPC modifications to it appear to justify our kernel
implementation: as has been pointed out, PPC has some additional code
which deals with the cache coherency.  ARM has similar mechanisms with
the cacheflush syscall, whose whole point of existing is to support
self-modifying code (as userspace is not allowed to touch the cache
maintanence instructions.)

So, in the presence of the test justification vaccuum, and the fact
that PPC has added cache maintanence to the test, I think we should
take the exact same approach.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From hch at infradead.org  Thu May 26 05:06:35 2016
From: hch at infradead.org (Christoph Hellwig)
Date: Thu, 26 May 2016 05:06:35 -0700
Subject: [RFC][PATCH 1/3] staging: ion: Move away from the DMA APIs for
 cache flushing
In-Reply-To: <20160526105922.GH19428@n2100.arm.linux.org.uk>
References: <1464205684-5587-1-git-send-email-labbott@redhat.com>
 <1464205684-5587-2-git-send-email-labbott@redhat.com>
 <20160526095835.GT23566@e106497-lin.cambridge.arm.com>
 <20160526105922.GH19428@n2100.arm.linux.org.uk>
Message-ID: <20160526120635.GA28564@infradead.org>

On Thu, May 26, 2016 at 11:59:22AM +0100, Russell King - ARM Linux wrote:
> I _really_ hate seeing architecture internal functions being abused in
> drivers - architecture internal functions are there to implement the
> official kernel APIs and are not for drivers to poke about with.

Exactly - if drivers like drm and ion want to do something out side the
current DMA API we need to add a proper API, not hack around the lack of
one.


From javier at osg.samsung.com  Thu May 26 05:14:29 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Thu, 26 May 2016 08:14:29 -0400
Subject: ARM: dts: exynos: Add MFC memory banks for Peach boards
In-Reply-To: <5746BD94.3070903@samsung.com>
References: <1461871311-18344-1-git-send-email-javier@osg.samsung.com>
 <57456344.7020708@samsung.com>
 <d045b880-4a44-acd8-f7f6-e521caf374aa@osg.samsung.com>
 <574670E7.3060508@samsung.com>
 <476edff1-9f3e-fc5b-4385-d04ae917b58e@osg.samsung.com>
 <5746BD94.3070903@samsung.com>
Message-ID: <869bee66-9aa8-6c17-d140-3e6644acaf91@osg.samsung.com>

Hello Pankaj,

On 05/26/2016 05:10 AM, pankaj.dubey wrote:

[snip]

>>> [    0.000000] Kernel command line: cros_legacy console=ttySAC3,115200
>>> debug earlyprintk cros_debug no_console_suspend root=/dev/ram0 rw
>>> ramdisk=32768 initrd=0x42000000,3
>>> 2M
>>
>> I see that you are loading an initrd at 0x42000000 with size of 32 MiB.
>>
>> [...]
>>
>>> [    1.121421] Trying to unpack rootfs image as initramfs...
>>> [    1.126940] rootfs image is not initramfs (junk in compressed
>>> archive); looks like an initrd
>>> [    1.160139] Unable to handle kernel paging request at virtual address
>>> e3000000
>>
>> So I wonder if the problem is that the memblock_remove() is called very
>> early and so the kernel is not able to copy the initrd from 0x42000000
>> to 0x44000000 since overlaps with the mfc-r mem (0x43000000-0x43800000).
>>
>> Specially since the NULL pointer dereference below happens in the
>> populate_rootfs() function when calling xwrite() to do the copy.
>>
>> Could you please try to change the load address for your initrd, or
>> change the mfc-r start address to see if that prevents the issue?
>>
> 
> Yes, you are correct. This was the case.
> I changed initrd location from 0x42000000 to 0x44000000, and it is able
> to boot without any crash.
>

Great, good to confirm that this was causing your boot failure.
 
> Thanks,
> Pankaj Dubey
> 

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From dongas86 at gmail.com  Thu May 26 05:11:15 2016
From: dongas86 at gmail.com (Dong Aisheng)
Date: Thu, 26 May 2016 20:11:15 +0800
Subject: [PATCH 17/23] mmc: sdhci: add standard hw auto retuning support
In-Reply-To: <57319D51.8030907@intel.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-18-git-send-email-aisheng.dong@nxp.com>
 <57319D51.8030907@intel.com>
Message-ID: <20160526121115.GD23988@shlinux2>

On Tue, May 10, 2016 at 11:35:29AM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > If HW supports SDHCI_TUNING_MODE_3 which is auto retuning, we won't
> 
> Since this is about tuning mode 3, could you put that in the subject e.g.
> "Add support for auto re-tuning (tuning mode 3)"
> 
> > retune during runtime suspend and resume, instead we use Re-tuning
> > Request signaled via SDHCI_INT_RETUNE interrupt to do retuning and
> > hw auto retuning during data transfer to guarantee the signal sample
> > window correction.
> > 
> > This can avoid a mass of repeatly retuning during small file system
> 
> repeatly -> repeatedly
> 

Got it.

> > data access and improve the performance.
> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
> > ---
> >  drivers/mmc/host/sdhci.c | 18 ++++++++++++++----
> >  drivers/mmc/host/sdhci.h |  3 +++
> >  2 files changed, 17 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index 2eb0e34..0027b87 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -252,6 +252,9 @@ static void sdhci_init(struct sdhci_host *host, int soft)
> >  		    SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
> >  		    SDHCI_INT_RESPONSE;
> >  
> > +	if (host->tuning_mode == SDHCI_TUNING_MODE_3)
> 
> Tuning mode 2 uses this as well.  Might as well add it here.
> 

The origin plan is adding only mode 3 support here to make life
a bit easier. Seems mode 2 does not need much more things added.
So i can add it here too.

> > +		host->ier |= SDHCI_INT_RETUNE;
> > +
> >  	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
> >  	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
> >  
> > @@ -2477,6 +2480,9 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
> >  			pr_err("%s: Card is consuming too much power!\n",
> >  				mmc_hostname(host->mmc));
> >  
> > +		if (intmask & SDHCI_INT_RETUNE)
> > +			mmc_retune_needed(host->mmc);
> > +
> 
> Also need to add SDHCI_INT_RETUNE to the bits cleared further on, otherwise
> it will show up in the "Unexpected interrupt" message
> 

That's true.

> >  		if (intmask & SDHCI_INT_CARD_INT) {
> >  			sdhci_enable_sdio_irq_nolock(host, false);
> >  			host->thread_isr |= SDHCI_INT_CARD_INT;
> > @@ -2575,8 +2581,10 @@ int sdhci_suspend_host(struct sdhci_host *host)
> >  {
> >  	sdhci_disable_card_detection(host);
> >  
> > -	mmc_retune_timer_stop(host->mmc);
> > -	mmc_retune_needed(host->mmc);
> > +	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
> > +		mmc_retune_timer_stop(host->mmc);
> > +		mmc_retune_needed(host->mmc);
> > +	}
> 
> Probably wouldn't hurt to stop the timer always whether it's going or not.

Sounds correct.

> And tuning mode 2 is not auto re-tuning, so I would still expect to need
> re-tuning after power loss i.e.
> 
> 	mmc_retune_timer_stop(host->mmc);
> 	if (host->tuning_mode != SDHCI_TUNING_MODE_3)
> 		mmc_retune_needed(host->mmc);
> 

I agree with you.
Will get it in v2.

Regards
Dong Aisheng

> >  
> >  	if (!device_may_wakeup(mmc_dev(host->mmc))) {
> >  		host->ier = 0;
> > @@ -2651,8 +2659,10 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
> >  {
> >  	unsigned long flags;
> >  
> > -	mmc_retune_timer_stop(host->mmc);
> > -	mmc_retune_needed(host->mmc);
> > +	if (host->tuning_mode == SDHCI_TUNING_MODE_1) {
> > +		mmc_retune_timer_stop(host->mmc);
> > +		mmc_retune_needed(host->mmc);
> > +	}
> 
> Ditto
> 
> >  
> >  	spin_lock_irqsave(&host->lock, flags);
> >  	host->ier &= SDHCI_INT_CARD_INT;
> > diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> > index afa4de8..2c2404f 100644
> > --- a/drivers/mmc/host/sdhci.h
> > +++ b/drivers/mmc/host/sdhci.h
> > @@ -128,6 +128,7 @@
> >  #define  SDHCI_INT_CARD_INSERT	0x00000040
> >  #define  SDHCI_INT_CARD_REMOVE	0x00000080
> >  #define  SDHCI_INT_CARD_INT	0x00000100
> > +#define  SDHCI_INT_RETUNE	0x00001000
> >  #define  SDHCI_INT_ERROR	0x00008000
> >  #define  SDHCI_INT_TIMEOUT	0x00010000
> >  #define  SDHCI_INT_CRC		0x00020000
> > @@ -514,6 +515,8 @@ struct sdhci_host {
> >  	unsigned int		tuning_count;	/* Timer count for re-tuning */
> >  	unsigned int		tuning_mode;	/* Re-tuning mode supported by host */
> >  #define SDHCI_TUNING_MODE_1	0
> > +#define SDHCI_TUNING_MODE_2	1
> > +#define SDHCI_TUNING_MODE_3	2
> >  
> >  	unsigned long private[0] ____cacheline_aligned;
> >  };
> > 
> 


From dongas86 at gmail.com  Thu May 26 05:21:44 2016
From: dongas86 at gmail.com (Dong Aisheng)
Date: Thu, 26 May 2016 20:21:44 +0800
Subject: [PATCH 18/23] mmc: sdhci-esdhc-imx: enable hw auto retuning for
 STD_TUNING
In-Reply-To: <5731C3CC.1000806@intel.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-19-git-send-email-aisheng.dong@nxp.com>
 <5731C3CC.1000806@intel.com>
Message-ID: <20160526122144.GE23988@shlinux2>

On Tue, May 10, 2016 at 02:19:40PM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > Enable HW auto retuning when set SDHCI_CTRL_EXEC_TUNING and clear it
> > when clear SDHCI_CTRL_TUNED_CLK.
> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
> 
> I presume this patch should wait for patch 17, but nevertheless:
> 
> Acked-by: Adrian Hunter <adrian.hunter at intel.com>
> 

Actually the interesting thing here is patch 18 and 19 do not need
patch 17 since our IC guy told me IMX uSDHC auto-tuning will
not Retuning request for mode 3.

Thanks for the pre-ACK.

Regards
Dong Aisheng

> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 9f9be3f..a582a83 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -44,6 +44,7 @@
> >  #define  ESDHC_MIX_CTRL_AC23EN		(1 << 7)
> >  #define  ESDHC_MIX_CTRL_EXE_TUNE	(1 << 22)
> >  #define  ESDHC_MIX_CTRL_SMPCLK_SEL	(1 << 23)
> > +#define  ESDHC_MIX_CTRL_AUTO_TUNE_EN	(1 << 24)
> >  #define  ESDHC_MIX_CTRL_FBCLK_SEL	(1 << 25)
> >  #define  ESDHC_MIX_CTRL_HS400_EN	(1 << 26)
> >  /* Bits 3 and 6 are not SDHCI standard definitions */
> > @@ -484,11 +485,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
> >  			} else {
> >  				v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
> >  				m &= ~ESDHC_MIX_CTRL_FBCLK_SEL;
> > +				m &= ~ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> >  			}
> >  
> >  			if (val & SDHCI_CTRL_EXEC_TUNING) {
> >  				v |= ESDHC_MIX_CTRL_EXE_TUNE;
> >  				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
> > +				m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN;
> >  				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
> >  				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP_DEFAULT;
> >  				if (imx_data->boarddata.tuning_start_tap) {
> > 
> 


From lorenzo.pieralisi at arm.com  Thu May 26 05:34:59 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Thu, 26 May 2016 13:34:59 +0100
Subject: [PATCH] PCI/MSI: pci-xgene-msi: Enable MSI support in ACPI boot
 for X-Gene v1
In-Reply-To: <CADaLNDnywVPER9QhmK4C6JyCLhta_M_cVSOuSkEHnmnLPFo3JA@mail.gmail.com>
References: <1455069384-22323-1-git-send-email-dhdang@apm.com>
 <1456330151.5681.46.camel@redhat.com> <56CDD767.6020103@arm.com>
 <CADaLND=mrkxOWOzcEb8os16Rb=SDHfnn_8eSgB4bQYH3UguS3w@mail.gmail.com>
 <20160225173822.GA6349@red-moon>
 <CADaLNDnywVPER9QhmK4C6JyCLhta_M_cVSOuSkEHnmnLPFo3JA@mail.gmail.com>
Message-ID: <20160526123459.GA23794@red-moon>

Hi Duc,

On Wed, May 25, 2016 at 04:13:35PM -0700, Duc Dang wrote:
> On Thu, Feb 25, 2016 at 9:38 AM, Lorenzo Pieralisi
> <lorenzo.pieralisi at arm.com> wrote:
> > On Wed, Feb 24, 2016 at 02:28:10PM -0800, Duc Dang wrote:
> >> On Wed, Feb 24, 2016 at 8:16 AM, Marc Zyngier <marc.zyngier at arm.com> wrote:
> >> > On 24/02/16 16:09, Mark Salter wrote:
> >> >> On Tue, 2016-02-09 at 17:56 -0800, Duc Dang wrote:
> >> >>> This patch makes pci-xgene-msi driver ACPI-aware and provides
> >> >>> MSI capability for X-Gene v1 PCIe controllers in ACPI boot mode.
> >> >>>
> >> >>> Signed-off-by: Duc Dang <dhdang at apm.com>
> >> >>> ---
> >> >>>  drivers/pci/host/pci-xgene-msi.c | 35 ++++++++++++++++++++++++++++++++---
> >> >>>  1 file changed, 32 insertions(+), 3 deletions(-)
> >> >>>
> >> >>> diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c
> >> >>> index a6456b5..466aa93 100644
> >> >>> --- a/drivers/pci/host/pci-xgene-msi.c
> >> >>> +++ b/drivers/pci/host/pci-xgene-msi.c
> >> >>> @@ -24,6 +24,7 @@
> >> >>>  #include <linux/pci.h>
> >> >>>  #include <linux/platform_device.h>
> >> >>>  #include <linux/of_pci.h>
> >> >>> +#include <linux/acpi.h>
> >> >>>
> >> >>>  #define MSI_IR0                     0x000000
> >> >>>  #define MSI_INT0            0x800000
> >> >>> @@ -39,7 +40,7 @@ struct xgene_msi_group {
> >> >>>  };
> >> >>>
> >> >>>  struct xgene_msi {
> >> >>> -    struct device_node      *node;
> >> >>> +    struct fwnode_handle    *fwnode;
> >> >>>      struct irq_domain       *inner_domain;
> >> >>>      struct irq_domain       *msi_domain;
> >> >>>      u64                     msi_addr;
> >> >>> @@ -249,6 +250,13 @@ static const struct irq_domain_ops msi_domain_ops = {
> >> >>>      .free   = xgene_irq_domain_free,
> >> >>>  };
> >> >>>
> >> >>> +#ifdef CONFIG_ACPI
> >> >>> +static struct fwnode_handle *xgene_msi_get_fwnode(struct device *dev)
> >> >>> +{
> >> >>> +    return xgene_msi_ctrl.fwnode;
> >> >>> +}
> >> >>> +#endif
> >> >>> +
> >> >>>  static int xgene_allocate_domains(struct xgene_msi *msi)
> >> >>>  {
> >> >>>      msi->inner_domain = irq_domain_add_linear(NULL, NR_MSI_VEC,
> >> >>> @@ -256,7 +264,7 @@ static int xgene_allocate_domains(struct xgene_msi *msi)
> >> >>>      if (!msi->inner_domain)
> >> >>>              return -ENOMEM;
> >> >>>
> >> >>> -    msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(msi->node),
> >> >>> +    msi->msi_domain = pci_msi_create_irq_domain(msi->fwnode,
> >> >>>                                                  &xgene_msi_domain_info,
> >> >>>                                                  msi->inner_domain);
> >> >>
> >> >> This doesn't work for me (ACPI probing on Mustang) unless I change this
> >> >> to be pci_msi_create_default_irq_domain(). The problem seems to be that
> >> >> the MSI probe happens after the PCIe RC is probed so there is no MSI domain
> >> >> at the time the PCIe root is initialized by ACPI.
> >> >
> >> > pci_msi_create_default_irq_domain is the wrong thing do use, specially
> >> > if you have multiple MSI controllers in the system. I certainly wouldn't
> >> > want to see it being used on arm64.
> >> >
> >> > This is the usual dependency hell. You try moving the probing earlier,
> >> > but that may break something else in the process.
> >>
> >> Hi Mark and Marc,
> >>
> >> I have modified Tianocore firmware to have MSI node declared before
> >> PCIe node in Dsdt table. With this modification, the MSI driver will
> >> be loaded before PCIe driver and MSI domain is available at the time
> >> PCIe root is initialized.
> >
> > I am totally against this. We should not hack ACPI tables to make
> > the kernel work (on top of that with unwritten ordering rules that may
> > well require changes as kernel evolves), we should have a standard set
> > of bindings that people use to describe HW in the DSDT and the kernel(s)
> > has to cope with that. If there is a dependency problem in the description
> > we may solve it at bindings level, but I absolutely do not want to rely
> > on DSDT nodes ordering for things to work, that's fragile, no shortcuts
> > please.
> 
> Hi Lorenzo, Bjorn,
> 
> (Refresh this thread on this merge cycle)
> 
> I tried to use _DEP method to describe the dependency of PCIe node to
> MSI node but it turns out that PCIe driver does not check for the
> dependency (only EC (ec.c) and I2C core (i2c-core.c) use
> acpi_walk_dep_device_list to check for dependency before loading
> dependent drivers)
> 
> Do you have other suggestion/example about how to ensure strict
> ordering on driver loading in ACPI boot mode without changing the
> order of ACPI nodes in DSDT?

Before doing anything else, I would like to ask you to report the code
paths leading to failures (what fails actually ?) please, and I want
to understand what "this does not work" means.

In particular:

- Why using pci_msi_create_default_irq_domain() works
- Why, if you change the DSDT nodes ordering, things work (please add
  some debugging to MSI allocation functions to detect the code paths
  leading to correct MSI allocation)
- What's the difference wrt the DT probe path

When we have a detailed view of MSI allocation code paths and failures
we can see what we can do to fix it in ACPI.

Thanks,
Lorenzo


From robh at kernel.org  Thu May 26 05:46:40 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 26 May 2016 07:46:40 -0500
Subject: [PATCH 02/11] drivers: clk: st: Add clock propagation for audio
 clocks
In-Reply-To: <CAG374jDTCJfZB+PuAnggjXhbcd3NjJqrESpe_EnMniCAeoph9A@mail.gmail.com>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
 <1463560892-7209-3-git-send-email-gabriel.fernandez@linaro.org>
 <20160525172409.GA27913@rob-hp-laptop>
 <CAG374jDTCJfZB+PuAnggjXhbcd3NjJqrESpe_EnMniCAeoph9A@mail.gmail.com>
Message-ID: <CAL_JsqLOG4P0H+HkQ3mJhfibatuV2T51KqOn-+U+LK8WUx7QgA@mail.gmail.com>

On Thu, May 26, 2016 at 4:49 AM, Gabriel Fernandez
<gabriel.fernandez at linaro.org> wrote:
> On 25 May 2016 at 19:24, Rob Herring <robh at kernel.org> wrote:
>>
>> On Wed, May 18, 2016 at 10:41:23AM +0200, Gabriel Fernandez wrote:
>> > This patch allows fine tuning of the quads FS for audio clocks
>> > accuracy.
>> >
>> > Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
>> > Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
>> > ---
>> >  .../devicetree/bindings/clock/st/st,flexgen.txt    |  1 +
>> >  drivers/clk/st/clk-flexgen.c                       | 24 ++++++++++++++++++++++
>> >  2 files changed, 25 insertions(+)
>> >
>> > diff --git a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>> > index b7ee5c7..15b33c7 100644
>> > --- a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>> > +++ b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>> > @@ -60,6 +60,7 @@ This binding uses the common clock binding[2].
>> >  Required properties:
>> >  - compatible : shall be:
>> >    "st,flexgen"
>> > +  "st,stih407-clkgend0", "st,flexgen" (enable clock propagation on parent)
>>
>> What do "d0" and "d2" refer to?
>>
>> This seems to indicate you have too much clock detail in the DT (with
>> individual clocks described) or not enough with genericish compatible
>> strings. What happens for the mext clock you need to adjust the flags
>> on? You should be able to make these adjustments without DT updates.
>> Perhaps you need a wider fixing of clock compatible strings.
>>
>> Rob
>
> Sorry i sent my response in html...
>
> Hi Rob,
>
> Thanks for reviewing.
>
> Can i remove
> "
> st,stih407-clkgend0" & "
> st,stih407-clkgend2" compatible strings and add proprieties instead ?
> I only need to activate 2 features and then we can keep generic
> compatible strings.

That is no different and suffers the same point I raised. It requires
updating the DT for any clock configuration change or enhancement.

Rob


From pc.liao at mediatek.com  Thu May 26 05:50:50 2016
From: pc.liao at mediatek.com (PC Liao)
Date: Thu, 26 May 2016 20:50:50 +0800
Subject: [PATCH] ASoC: mediatek: Change the order of MCLK clock configuration
Message-ID: <1464267050-57287-1-git-send-email-pc.liao@mediatek.com>

Because MCLK opens later and closes earlier than codec, this patch
changes the order of MCLK clock configuration.

Signed-off-by: PC Liao <pc.liao at mediatek.com>
---
 sound/soc/mediatek/mtk-afe-pcm.c |   16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/sound/soc/mediatek/mtk-afe-pcm.c b/sound/soc/mediatek/mtk-afe-pcm.c
index f1c58a2..440ae06 100644
--- a/sound/soc/mediatek/mtk-afe-pcm.c
+++ b/sound/soc/mediatek/mtk-afe-pcm.c
@@ -360,8 +360,6 @@ static int mtk_afe_i2s_startup(struct snd_pcm_substream *substream,
 	if (dai->active)
 		return 0;
 
-	mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL);
-	mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S2_M], NULL);
 	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
 			   AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 0);
 	return 0;
@@ -380,8 +378,6 @@ static void mtk_afe_i2s_shutdown(struct snd_pcm_substream *substream,
 	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
 			   AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M,
 			   AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M);
-	mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL);
-	mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S2_M], NULL);
 }
 
 static int mtk_afe_i2s_prepare(struct snd_pcm_substream *substream,
@@ -1132,6 +1128,8 @@ static int mtk_afe_runtime_suspend(struct device *dev)
 	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
 			   AUD_TCON0_PDN_AFE, AUD_TCON0_PDN_AFE);
 
+	clk_disable_unprepare(afe->clocks[MTK_CLK_I2S1_M]);
+	clk_disable_unprepare(afe->clocks[MTK_CLK_I2S2_M]);
 	clk_disable_unprepare(afe->clocks[MTK_CLK_BCK0]);
 	clk_disable_unprepare(afe->clocks[MTK_CLK_BCK1]);
 	clk_disable_unprepare(afe->clocks[MTK_CLK_TOP_PDN_AUD]);
@@ -1164,6 +1162,12 @@ static int mtk_afe_runtime_resume(struct device *dev)
 	ret = clk_prepare_enable(afe->clocks[MTK_CLK_BCK1]);
 	if (ret)
 		goto err_bck0;
+	ret = clk_prepare_enable(afe->clocks[MTK_CLK_I2S1_M]);
+	if (ret)
+		goto err_i2s1_m;
+	ret = clk_prepare_enable(afe->clocks[MTK_CLK_I2S2_M]);
+	if (ret)
+		goto err_i2s2_m;
 
 	/* enable AFE clk */
 	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, AUD_TCON0_PDN_AFE, 0);
@@ -1179,6 +1183,10 @@ static int mtk_afe_runtime_resume(struct device *dev)
 	regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1);
 	return 0;
 
+err_i2s1_m:
+	clk_disable_unprepare(afe->clocks[MTK_CLK_I2S1_M]);
+err_i2s2_m:
+	clk_disable_unprepare(afe->clocks[MTK_CLK_I2S2_M]);
 err_bck0:
 	clk_disable_unprepare(afe->clocks[MTK_CLK_BCK0]);
 err_top_aud:
-- 
1.7.9.5



From zhengxing at rock-chips.com  Thu May 26 06:02:22 2016
From: zhengxing at rock-chips.com (Xing Zheng)
Date: Thu, 26 May 2016 21:02:22 +0800
Subject: [PATCH v3] ASoC: rockchip: Add machine driver for
 MAX98357A/RT5514/DA7219
Message-ID: <1464267742-15312-1-git-send-email-zhengxing@rock-chips.com>

There are multi codec devices on the RK3399 platform, we can use
this patch support and control these codecs.

Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
---

Changes in v3:
- rename DOC to rockchip,rk3399-max98357a-rt5514-da7219.txt
- rename compatible to rockchip,rk3399-max98357a-rt5514-da7219
- rename source code to rk3399_max98357a_rt5514_da7219.c

Changes in v2:
- use the FS 256 to set mclks of the max98357a and rt5514 danamically
- add more sample rate for da7219

 .../rockchip,rk3399-max98357a-rt5514-da7219.txt    |   15 +
 sound/soc/rockchip/Kconfig                         |   11 +
 sound/soc/rockchip/Makefile                        |    2 +
 .../soc/rockchip/rk3399_max98357a_rt5514_da7219.c  |  333 ++++++++++++++++++++
 4 files changed, 361 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3399-max98357a-rt5514-da7219.txt
 create mode 100644 sound/soc/rockchip/rk3399_max98357a_rt5514_da7219.c

diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3399-max98357a-rt5514-da7219.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3399-max98357a-rt5514-da7219.txt
new file mode 100644
index 0000000..3ae603e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip,rk3399-max98357a-rt5514-da7219.txt
@@ -0,0 +1,15 @@
+ROCKCHIP with MAX98357A/RT5514/DA7219 codecs
+
+Required properties:
+- compatible: "rockchip,rk3399-max98357a-rt5514-da7219"
+- rockchip,cpu: The phandle of the Rockchip I2S controller that's
+  connected to the codecs
+- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs
+
+Example:
+
+sound {
+	compatible = "rockchip,rk3399-max98357a-rt5514-da7219";
+	rockchip,cpu = <&i2s0 &i2s0 &i2s1>;
+	rockchip,codec = <&max98357a &headsetcodec &codec>;
+};
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index f1e0c70..e5bd1f9 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -41,3 +41,14 @@ config SND_SOC_ROCKCHIP_RT5645
 	help
 	  Say Y or M here if you want to add support for SoC audio on Rockchip
 	  boards using the RT5645/RT5650 codec, such as Veyron.
+
+config SND_SOC_RK3399_MAX98357A_RT5514_DA7219
+	tristate "ASoC support for Rockchip RK3399 boards using the MAX98357A/RT5514/DA7219"
+	depends on SND_SOC_ROCKCHIP && GPIOLIB
+	select SND_SOC_ROCKCHIP_I2S
+	select SND_SOC_MAX98357A
+	select SND_SOC_RT5514
+	select SND_SOC_DA7219
+	help
+	  Say Y or M here if you want to add support for SoC audio on Rockchip RK3399
+	  boards using the MAX98357A/RT5514/DA7219.
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
index c0bf560..0d9ca0a 100644
--- a/sound/soc/rockchip/Makefile
+++ b/sound/soc/rockchip/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o
 
 snd-soc-rockchip-max98090-objs := rockchip_max98090.o
 snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o
+snd-soc-rk3399-max98357a-rt5514-da7219-objs := rk3399_max98357a_rt5514_da7219.o
 
 obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o
+obj-$(CONFIG_SND_SOC_RK3399_MAX98357A_RT5514_DA7219) += snd-soc-rk3399-max98357a-rt5514-da7219.o
diff --git a/sound/soc/rockchip/rk3399_max98357a_rt5514_da7219.c b/sound/soc/rockchip/rk3399_max98357a_rt5514_da7219.c
new file mode 100644
index 0000000..ec88600
--- /dev/null
+++ b/sound/soc/rockchip/rk3399_max98357a_rt5514_da7219.c
@@ -0,0 +1,333 @@
+/*
+ * Rockchip machine ASoC driver for boards using MAX98357A/RT5514/DA7219
+ *
+ * Copyright (c) 2016, ROCKCHIP CORPORATION.  All rights reserved.
+ *
+ * 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 <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include "rockchip_i2s.h"
+#include "../codecs/da7219.h"
+#include "../codecs/da7219-aad.h"
+#include "../codecs/rt5514.h"
+
+#define DRV_NAME "rk3399-max98357a-rt5514-da7219"
+
+#define SOUND_FS	256
+
+static struct snd_soc_jack rockchip_sound_jack;
+
+static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphones", NULL),
+	SND_SOC_DAPM_SPK("Speakers", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Int Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route rockchip_dapm_routes[] = {
+	/* Input Lines */
+	{"MIC", NULL, "Headset Mic"},
+	{"DMIC1L", NULL, "Int Mic"},
+	{"DMIC1R", NULL, "Int Mic"},
+
+	/* Output Lines */
+	{"Headphones", NULL, "HPL"},
+	{"Headphones", NULL, "HPR"},
+	{"Speakers", NULL, "Speakers"},
+};
+
+static const struct snd_kcontrol_new rockchip_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Headphones"),
+	SOC_DAPM_PIN_SWITCH("Speakers"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Int Mic"),
+};
+
+static int rockchip_sound_max98357a_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_dapm_context *dapm = &rtd->card->dapm;
+	unsigned int mclk;
+	int ret;
+
+	/* max98357a supports these sample rates */
+	switch (params_rate(params)) {
+	case 8000:
+	case 16000:
+	case 48000:
+	case 96000:
+		mclk = params_rate(params) * SOUND_FS;
+		break;
+	default:
+		dev_err(rtd->card->dev, "%s() doesn't support this sample rate: %d\n",
+				__func__, params_rate(params));
+		return -EINVAL;
+	}
+
+	ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0);
+	if (ret) {
+		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
+				__func__, mclk, ret);
+		return ret;
+	}
+
+	snd_soc_dapm_disable_pin(dapm, "Headphones");
+	snd_soc_dapm_enable_pin(dapm, "Speakers");
+	snd_soc_dapm_sync(dapm);
+
+	return 0;
+}
+
+static int rockchip_sound_rt5514_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;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	unsigned int mclk;
+	int ret;
+
+	mclk = params_rate(params) * SOUND_FS;
+
+	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
+				     SND_SOC_CLOCK_OUT);
+	if (ret < 0) {
+		dev_err(rtd->card->dev, "Can't set cpu clock out %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK,
+				     mclk, SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
+				__func__, params_rate(params) * 512, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rockchip_sound_da7219_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;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dapm_context *dapm = &rtd->card->dapm;
+	int mclk, ret;
+
+	/* in bypass mode, the mclk has to be one of the frequencies below */
+	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(codec_dai->dev, "Can't set cpu clock out %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
+				     SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		dev_err(codec_dai->dev, "Can't set codec clock in %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
+	if (ret < 0) {
+		dev_err(codec_dai->dev, "Can't set pll sysclk mclk %d\n", ret);
+		return ret;
+	}
+
+	snd_soc_dapm_disable_pin(dapm, "Speakers");
+	snd_soc_dapm_enable_pin(dapm, "Headphones");
+	snd_soc_dapm_sync(dapm);
+
+	return 0;
+}
+
+static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec_dais[0]->codec;
+	int ret;
+
+	/* Enable Headset and 4 Buttons Jack detection */
+	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
+				    SND_JACK_HEADSET |
+				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
+				    &rockchip_sound_jack, NULL, 0);
+
+	if (ret) {
+		dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
+		return ret;
+	}
+
+	da7219_aad_jack_det(codec, &rockchip_sound_jack);
+
+	return 0;
+}
+
+static struct snd_soc_ops rockchip_sound_max98357a_ops = {
+	.hw_params = rockchip_sound_max98357a_hw_params,
+};
+
+static struct snd_soc_ops rockchip_sound_rt5514_ops = {
+	.hw_params = rockchip_sound_rt5514_hw_params,
+};
+
+static struct snd_soc_ops rockchip_sound_da7219_ops = {
+	.hw_params = rockchip_sound_da7219_hw_params,
+};
+
+enum {
+	DAILINK_MAX98357A,
+	DAILINK_RT5514,
+	DAILINK_DA7219,
+};
+
+static struct snd_soc_dai_link rockchip_dailinks[] = {
+	[DAILINK_MAX98357A] = {
+		.name = "MAX98357A",
+		.stream_name = "MAX98357A PCM",
+		.codec_dai_name = "HiFi",
+		.ops = &rockchip_sound_max98357a_ops,
+		/* set max98357a as slave */
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+	[DAILINK_RT5514] = {
+		.name = "RT5514",
+		.stream_name = "RT5514 PCM",
+		.codec_dai_name = "rt5514-aif1",
+		.ops = &rockchip_sound_rt5514_ops,
+		/* set rt5514 as slave */
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+	[DAILINK_DA7219] = {
+		.name = "DA7219",
+		.stream_name = "DA7219 PCM",
+		.codec_dai_name = "da7219-hifi",
+		.init = rockchip_sound_da7219_init,
+		.ops = &rockchip_sound_da7219_ops,
+		/* set da7219 as slave */
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+	},
+};
+
+static struct snd_soc_card rockchip_sound_card = {
+	.name = "rk3399-max98357a-rt5514-da7219",
+	.owner = THIS_MODULE,
+	.dai_link = rockchip_dailinks,
+	.num_links =  ARRAY_SIZE(rockchip_dailinks),
+	.dapm_widgets = rockchip_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
+	.dapm_routes = rockchip_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes),
+	.controls = rockchip_controls,
+	.num_controls = ARRAY_SIZE(rockchip_controls),
+};
+
+static int rockchip_sound_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &rockchip_sound_card;
+	struct device_node *cpu_node;
+	int i, ret;
+
+	for (i = 0; i < card->num_links; i++) {
+		cpu_node = of_parse_phandle(pdev->dev.of_node,
+					 "rockchip,cpu", i);
+		if (!cpu_node) {
+			dev_err(&pdev->dev, "Property[%d] 'rockchip,cpu' missing or invalid\n", i);
+			return -EINVAL;
+		}
+
+		rockchip_dailinks[i].platform_of_node = cpu_node;
+		rockchip_dailinks[i].cpu_of_node = cpu_node;
+
+		rockchip_dailinks[i].codec_of_node =
+			of_parse_phandle(pdev->dev.of_node, "rockchip,codec", i);
+		if (!rockchip_dailinks[i].codec_of_node) {
+			dev_err(&pdev->dev,
+				"Property[%d] 'rockchip,codec' missing or invalid\n", i);
+			return -EINVAL;
+		}
+	}
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret)
+		dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
+			__func__, ret);
+
+	return ret;
+}
+
+static const struct of_device_id rockchip_sound_of_match[] = {
+	{ .compatible = "rockchip,rk3399-max98357a-rt5514-da7219", },
+	{},
+};
+
+static struct platform_driver rockchip_sound_driver = {
+	.probe = rockchip_sound_probe,
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = rockchip_sound_of_match,
+#ifdef CONFIG_PM
+		.pm = &snd_soc_pm_ops,
+#endif
+	},
+};
+
+module_platform_driver(rockchip_sound_driver);
+
+MODULE_AUTHOR("Xing Zheng <zhengxing at rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);
-- 
1.7.9.5




From loic.pallardy at st.com  Thu May 26 06:05:10 2016
From: loic.pallardy at st.com (loic pallardy)
Date: Thu, 26 May 2016 15:05:10 +0200
Subject: [STLinux Kernel] [PATCH 02/11] drivers: clk: st: Add clock
 propagation for audio clocks
In-Reply-To: <CAL_JsqLOG4P0H+HkQ3mJhfibatuV2T51KqOn-+U+LK8WUx7QgA@mail.gmail.com>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
 <1463560892-7209-3-git-send-email-gabriel.fernandez@linaro.org>
 <20160525172409.GA27913@rob-hp-laptop>
 <CAG374jDTCJfZB+PuAnggjXhbcd3NjJqrESpe_EnMniCAeoph9A@mail.gmail.com>
 <CAL_JsqLOG4P0H+HkQ3mJhfibatuV2T51KqOn-+U+LK8WUx7QgA@mail.gmail.com>
Message-ID: <5746F486.602@st.com>



On 05/26/2016 02:46 PM, Rob Herring wrote:
> On Thu, May 26, 2016 at 4:49 AM, Gabriel Fernandez
> <gabriel.fernandez at linaro.org> wrote:
>> On 25 May 2016 at 19:24, Rob Herring <robh at kernel.org> wrote:
>>>
>>> On Wed, May 18, 2016 at 10:41:23AM +0200, Gabriel Fernandez wrote:
>>>> This patch allows fine tuning of the quads FS for audio clocks
>>>> accuracy.
>>>>
>>>> Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
>>>> Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
>>>> ---
>>>>   .../devicetree/bindings/clock/st/st,flexgen.txt    |  1 +
>>>>   drivers/clk/st/clk-flexgen.c                       | 24 ++++++++++++++++++++++
>>>>   2 files changed, 25 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>>>> index b7ee5c7..15b33c7 100644
>>>> --- a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>>>> +++ b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>>>> @@ -60,6 +60,7 @@ This binding uses the common clock binding[2].
>>>>   Required properties:
>>>>   - compatible : shall be:
>>>>     "st,flexgen"
>>>> +  "st,stih407-clkgend0", "st,flexgen" (enable clock propagation on parent)
>>>
>>> What do "d0" and "d2" refer to?
>>>
>>> This seems to indicate you have too much clock detail in the DT (with
>>> individual clocks described) or not enough with genericish compatible
>>> strings. What happens for the mext clock you need to adjust the flags
>>> on? You should be able to make these adjustments without DT updates.
>>> Perhaps you need a wider fixing of clock compatible strings.
>>>
>>> Rob
>>
>> Sorry i sent my response in html...
>>
>> Hi Rob,
>>
>> Thanks for reviewing.
>>
>> Can i remove
>> "
>> st,stih407-clkgend0" & "
>> st,stih407-clkgend2" compatible strings and add proprieties instead ?
>> I only need to activate 2 features and then we can keep generic
>> compatible strings.
>
Hi Rob,
> That is no different and suffers the same point I raised. It requires
> updating the DT for any clock configuration change or enhancement.
>
Agree with you, DT update is needed as soon as a clock configuration 
should be changed. This is due to STiH clock driver design based on DT 
description of SoC clock tree.

This clock driver was accepted 2 years ago. At the time being there was 
discussion about clock tree description location: driver or DT.
Bad choice was done for this driver...

If we decide to redesign STiH clock driver using in-driver clock tree 
description, this will modify STiH clock DT nodes description and so 
break DT backward compatibility.

What's from your pov the best option?

Regards,
Loic

> Rob
>
> _______________________________________________
> Kernel mailing list
> Kernel at stlinux.com
> http://www.stlinux.com/mailman/listinfo/kernel
>


From robh at kernel.org  Thu May 26 06:13:45 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 26 May 2016 08:13:45 -0500
Subject: [PATCH 2/3] of/numa: fix a memory@ dt node can only contains one
 memory block
In-Reply-To: <1464230639-9852-2-git-send-email-thunder.leizhen@huawei.com>
References: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
 <1464230639-9852-2-git-send-email-thunder.leizhen@huawei.com>
Message-ID: <20160526131345.GA12024@rob-hp-laptop>

On Thu, May 26, 2016 at 10:43:58AM +0800, Zhen Lei wrote:
> For a normal memory@ devicetree node, its reg property can contains more
> memory blocks.
> 
> Because we don't known how many memory blocks maybe contained, so we try
> from index=0, increase 1 until error returned(the end).
> 
> Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
> ---
>  drivers/of/of_numa.c | 30 ++++++++++++++++++++----------
>  1 file changed, 20 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
> index 21d831f..2c5f249 100644
> --- a/drivers/of/of_numa.c
> +++ b/drivers/of/of_numa.c
> @@ -63,7 +63,7 @@ static int __init of_numa_parse_memory_nodes(void)
>  	struct device_node *np = NULL;
>  	struct resource rsrc;
>  	u32 nid;
> -	int r = 0;
> +	int i, r = 0;
> 
>  	for (;;) {
>  		np = of_find_node_by_type(np, "memory");
> @@ -82,17 +82,27 @@ static int __init of_numa_parse_memory_nodes(void)
>  			/* some other error */
>  			break;
> 
> -		r = of_address_to_resource(np, 0, &rsrc);
> -		if (r) {
> -			pr_err("NUMA: bad reg property in memory node\n");
> -			break;
> +		for (i = 0; ; i++) {
> +			r = of_address_to_resource(np, i, &rsrc);
> +			if (r) {
> +				/* reached the end of of_address */
> +				if (i > 0) {
> +					r = 0;
> +					break;
> +				}
> +
> +				pr_err("NUMA: bad reg property in memory node\n");
> +				goto finished;
> +			}
> +
> +			r = numa_add_memblk(nid, rsrc.start,
> +					    rsrc.end - rsrc.start + 1);
> +			if (r)
> +				goto finished;
>  		}
> -
> -		r = numa_add_memblk(nid, rsrc.start,
> -				    rsrc.end - rsrc.start + 1);
> -		if (r)
> -			break;
>  	}
> +
> +finished:
>  	of_node_put(np);

This function can be simplified down to:

	for_each_node_by_type(np, "memory") {
		r = of_property_read_u32(np, "numa-node-id", &nid);
		if (r == -EINVAL)
			/*
			 * property doesn't exist if -EINVAL, continue
			 * looking for more memory nodes with
			 * "numa-node-id" property
			 */
			continue;
		else if (r)
			/* some other error */
			break;

		r = of_address_to_resource(np, 0, &rsrc);
		for (i = 0; !r; i++, r = of_address_to_resource(np, i, 
&rsrc)) {
			r = numa_add_memblk(nid, rsrc.start,
				    rsrc.end - rsrc.start + 1);
		}
	}
	of_node_put(np);

	return r;


Perhaps with a "if (!i && r) pr_err()" for an error message at the end.

Rob


From robh at kernel.org  Thu May 26 06:20:39 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 26 May 2016 08:20:39 -0500
Subject: [STLinux Kernel] [PATCH 02/11] drivers: clk: st: Add clock
 propagation for audio clocks
In-Reply-To: <5746F486.602@st.com>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
 <1463560892-7209-3-git-send-email-gabriel.fernandez@linaro.org>
 <20160525172409.GA27913@rob-hp-laptop>
 <CAG374jDTCJfZB+PuAnggjXhbcd3NjJqrESpe_EnMniCAeoph9A@mail.gmail.com>
 <CAL_JsqLOG4P0H+HkQ3mJhfibatuV2T51KqOn-+U+LK8WUx7QgA@mail.gmail.com>
 <5746F486.602@st.com>
Message-ID: <CAL_JsqLeD8uTmMYLFZ5Sh9=JV5s1xthvruXL-W=c=zcVS=G-ZA@mail.gmail.com>

On Thu, May 26, 2016 at 8:05 AM, loic pallardy <loic.pallardy at st.com> wrote:
>
>
> On 05/26/2016 02:46 PM, Rob Herring wrote:
>>
>> On Thu, May 26, 2016 at 4:49 AM, Gabriel Fernandez
>> <gabriel.fernandez at linaro.org> wrote:
>>>
>>> On 25 May 2016 at 19:24, Rob Herring <robh at kernel.org> wrote:
>>>>
>>>>
>>>> On Wed, May 18, 2016 at 10:41:23AM +0200, Gabriel Fernandez wrote:
>>>>>
>>>>> This patch allows fine tuning of the quads FS for audio clocks
>>>>> accuracy.
>>>>>
>>>>> Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
>>>>> Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
>>>>> ---
>>>>>   .../devicetree/bindings/clock/st/st,flexgen.txt    |  1 +
>>>>>   drivers/clk/st/clk-flexgen.c                       | 24
>>>>> ++++++++++++++++++++++
>>>>>   2 files changed, 25 insertions(+)
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>>>>> b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>>>>> index b7ee5c7..15b33c7 100644
>>>>> --- a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>>>>> +++ b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>>>>> @@ -60,6 +60,7 @@ This binding uses the common clock binding[2].
>>>>>   Required properties:
>>>>>   - compatible : shall be:
>>>>>     "st,flexgen"
>>>>> +  "st,stih407-clkgend0", "st,flexgen" (enable clock propagation on
>>>>> parent)
>>>>
>>>>
>>>> What do "d0" and "d2" refer to?
>>>>
>>>> This seems to indicate you have too much clock detail in the DT (with
>>>> individual clocks described) or not enough with genericish compatible
>>>> strings. What happens for the mext clock you need to adjust the flags
>>>> on? You should be able to make these adjustments without DT updates.
>>>> Perhaps you need a wider fixing of clock compatible strings.
>>>>
>>>> Rob
>>>
>>>
>>> Sorry i sent my response in html...
>>>
>>> Hi Rob,
>>>
>>> Thanks for reviewing.
>>>
>>> Can i remove
>>> "
>>> st,stih407-clkgend0" & "
>>> st,stih407-clkgend2" compatible strings and add proprieties instead ?
>>> I only need to activate 2 features and then we can keep generic
>>> compatible strings.
>>
>>
> Hi Rob,
>>
>> That is no different and suffers the same point I raised. It requires
>> updating the DT for any clock configuration change or enhancement.
>>
> Agree with you, DT update is needed as soon as a clock configuration should
> be changed. This is due to STiH clock driver design based on DT description
> of SoC clock tree.
>
> This clock driver was accepted 2 years ago. At the time being there was
> discussion about clock tree description location: driver or DT.
> Bad choice was done for this driver...
>
> If we decide to redesign STiH clock driver using in-driver clock tree
> description, this will modify STiH clock DT nodes description and so break
> DT backward compatibility.
>
> What's from your pov the best option?

You can break it once or every time you need a clock change. I'd go
with the former. Maybe more specific compatible strings throughout
alone would be enough rather than a flag day changing the binding.

Rob


From zhengxing at rock-chips.com  Thu May 26 06:49:08 2016
From: zhengxing at rock-chips.com (Xing Zheng)
Date: Thu, 26 May 2016 21:49:08 +0800
Subject: [PATCH] clk: rockchip: fix cclk error handing
Message-ID: <1464270549-12713-1-git-send-email-zhengxing@rock-chips.com>

It maybe due to a copy-paste error the error handing should be
cclk not clk.

Reported-by: Lin Huang <lin.huang at rock-chips.com>
Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
---

 drivers/clk/rockchip/clk-cpu.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c
index 4bb130c..05b3d73 100644
--- a/drivers/clk/rockchip/clk-cpu.c
+++ b/drivers/clk/rockchip/clk-cpu.c
@@ -321,9 +321,9 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
 	}
 
 	cclk = clk_register(NULL, &cpuclk->hw);
-	if (IS_ERR(clk)) {
+	if (IS_ERR(cclk)) {
 		pr_err("%s: could not register cpuclk %s\n", __func__,	name);
-		ret = PTR_ERR(clk);
+		ret = PTR_ERR(cclk);
 		goto free_rate_table;
 	}
 
-- 
1.7.9.5




From bamvor.zhangjian at huawei.com  Thu May 26 06:49:42 2016
From: bamvor.zhangjian at huawei.com (Zhangjian (Bamvor))
Date: Thu, 26 May 2016 21:49:42 +0800
Subject: [PATCH 16/23] arm64: ilp32: introduce binfmt_ilp32.c
In-Reply-To: <1464048292-30136-17-git-send-email-ynorov@caviumnetworks.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
 <1464048292-30136-17-git-send-email-ynorov@caviumnetworks.com>
Message-ID: <5746FEF6.9070405@huawei.com>

Hi, yury

The coredump is usable in our platform. It miss the following definition:
+#define compat_elf_greg_t	elf_greg_t
+#define compat_elf_gregset_t	elf_gregset_t

And it leads to the wrong register save in core dump. After apply this patch,
gdb could debug core dump files.

Here is the full patch:
 From 102624840aa5dacdd1bbfe3b390290f52f530ea2 Mon Sep 17 00:00:00 2001
From: Bamvor Jian Zhang <bamvor.zhangjian at huawei.com>
Date: Thu, 26 May 2016 21:00:16 +0800
Subject: [PATCH hulk-4.1-next] arm64: ilp32: fix coredump issue

ILP32 use aarch64 register and 32bit signal struct which means it
could not make use of the existing compat_elf_prstatus/elf_prstatus
and compat_elf_prpsinfo/elf_prpsinfo.

This patch fix this issue by introducing the different
compat_elf_greg_t, compat_elf_gregset_t for aarch64 ilp32 and aarch32
el0.

Tested pass on huawei's hardware in bigendian.

Signed-off-by: Bamvor Jian Zhang <bamvor.zhangjian at huawei.com>
---
  arch/arm64/include/asm/elf.h     | 14 +++++++-------
  arch/arm64/kernel/binfmt_elf32.c |  3 +++
  arch/arm64/kernel/binfmt_ilp32.c |  8 +++++++-
  arch/arm64/kernel/ptrace.c       | 20 ++++++++++----------
  4 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 0106d18..9019441 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -154,18 +154,18 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
  				       int uses_interp);

  /* 1GB of VA */
-#define STACK_RND_MASK			(is_compat_task() ? \
-						0x7ff >> (PAGE_SHIFT - 12) : \
-						0x3ffff >> (PAGE_SHIFT - 12))
+#define STACK_RND_MASK		(is_compat_task() ? \
+					0x7ff >> (PAGE_SHIFT - 12) : \
+					0x3ffff >> (PAGE_SHIFT - 12))

  #ifdef CONFIG_COMPAT

-#define COMPAT_ELF_ET_DYN_BASE		(2 * TASK_SIZE_32 / 3)
+#define COMPAT_ELF_ET_DYN_BASE	(2 * TASK_SIZE_32 / 3)

  /* AArch32 registers. */
-#define COMPAT_ELF_NGREG		18
-typedef unsigned int			compat_elf_greg_t;
-typedef compat_elf_greg_t		compat_elf_gregset_t[COMPAT_ELF_NGREG];
+#define COMPAT_ELF_NGREG	18
+typedef unsigned int		compat_a32_elf_greg_t;
+typedef compat_a32_elf_greg_t	compat_a32_elf_gregset_t[COMPAT_ELF_NGREG];

  #endif /* CONFIG_COMPAT */

diff --git a/arch/arm64/kernel/binfmt_elf32.c b/arch/arm64/kernel/binfmt_elf32.c
index 7b9b445..f75253c 100644
--- a/arch/arm64/kernel/binfmt_elf32.c
+++ b/arch/arm64/kernel/binfmt_elf32.c
@@ -31,4 +31,7 @@ struct linux_binprm;
  extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
  				      int uses_interp);

+#define compat_elf_greg_t	compat_a32_elf_greg_t
+#define compat_elf_gregset_t	compat_a32_elf_gregset_t
+
  #include "../../../fs/compat_binfmt_elf.c"
diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
index b827a9a..01baf83 100644
--- a/arch/arm64/kernel/binfmt_ilp32.c
+++ b/arch/arm64/kernel/binfmt_ilp32.c
@@ -2,7 +2,9 @@
   * Support for ILP32 Linux/aarch64 ELF binaries.
   */

-#include <linux/elfcore-compat.h>
+#include <linux/elf.h>
+#include <linux/elfcore.h>
+#include <linux/compat.h>
  #include <linux/time.h>

  #undef	ELF_CLASS
@@ -30,9 +32,13 @@
   * The machine-dependent core note format types are defined in elfcore-compat.h,
   * which requires asm/elf.h to define compat_elf_gregset_t et al.
   */
+#define compat_elf_greg_t	elf_greg_t
+#define compat_elf_gregset_t	elf_gregset_t
  #define elf_prstatus	compat_elf_prstatus
  #define elf_prpsinfo	compat_elf_prpsinfo

+#include <linux/elfcore-compat.h>
+
  /*
   * Compat version of cputime_to_compat_timeval, perhaps this
   * should be an inline in <linux/compat.h>.
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 5c86135..9784c77 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -913,8 +913,8 @@ static const struct user_regset aarch32_regsets[] = {
  	[REGSET_COMPAT_GPR] = {
  		.core_note_type = NT_PRSTATUS,
  		.n = COMPAT_ELF_NGREG,
-		.size = sizeof(compat_elf_greg_t),
-		.align = sizeof(compat_elf_greg_t),
+		.size = sizeof(compat_a32_elf_greg_t),
+		.align = sizeof(compat_a32_elf_greg_t),
  		.get = compat_gpr_get,
  		.set = compat_gpr_set
  	},
@@ -947,7 +947,7 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
  		tmp = tsk->mm->start_data;
  	else if (off == COMPAT_PT_TEXT_END_ADDR)
  		tmp = tsk->mm->end_code;
-	else if (off < sizeof(compat_elf_gregset_t))
+	else if (off < sizeof(compat_a32_elf_gregset_t))
  		return copy_regset_to_user(tsk, &user_aarch32_view,
  					   REGSET_COMPAT_GPR, off,
  					   sizeof(compat_ulong_t), ret);
@@ -968,7 +968,7 @@ static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off,
  	if (off & 3 || off >= COMPAT_USER_SZ)
  		return -EIO;

-	if (off >= sizeof(compat_elf_gregset_t))
+	if (off >= sizeof(compat_a32_elf_gregset_t))
  		return 0;

  	set_fs(KERNEL_DS);
@@ -1116,9 +1116,11 @@ static long compat_a32_ptrace(struct task_struct *child, compat_long_t request,
  	unsigned long addr = caddr;
  	unsigned long data = cdata;
  	void __user *datap = compat_ptr(data);
+	unsigned int pr_reg_size = sizeof(compat_a32_elf_gregset_t);
  	int ret;

  	switch (request) {
+
  		case PTRACE_PEEKUSR:
  			ret = compat_ptrace_read_user(child, addr, datap);
  			break;
@@ -1130,17 +1132,15 @@ static long compat_a32_ptrace(struct task_struct *child, compat_long_t request,
  		case COMPAT_PTRACE_GETREGS:
  			ret = copy_regset_to_user(child,
  						  &user_aarch32_view,
-						  REGSET_COMPAT_GPR,
-						  0, sizeof(compat_elf_gregset_t),
-						  datap);
+						  REGSET_COMPAT_GPR, 0,
+						  pr_reg_size, datap);
  			break;

  		case COMPAT_PTRACE_SETREGS:
  			ret = copy_regset_from_user(child,
  						    &user_aarch32_view,
-						    REGSET_COMPAT_GPR,
-						    0, sizeof(compat_elf_gregset_t),
-						    datap);
+						    REGSET_COMPAT_GPR, 0,
+						    pr_reg_size, datap);
  			break;

  		case COMPAT_PTRACE_GET_THREAD_AREA:
-- 
1.8.4.5


On 2016/5/24 8:04, Yury Norov wrote:
> to handle ILP32 binaries
>
> Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
> ---
>   arch/arm64/kernel/Makefile       |  1 +
>   arch/arm64/kernel/binfmt_ilp32.c | 91 ++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 92 insertions(+)
>   create mode 100644 arch/arm64/kernel/binfmt_ilp32.c
>
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 6bc9738..9dfdf86 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -28,6 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
>   arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
>   					   sys_compat.o entry32.o		\
>   					   ../../arm/kernel/opcodes.o binfmt_elf32.o
> +arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
>   arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
>   arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
>   arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
> diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
> new file mode 100644
> index 0000000..a934fd4
> --- /dev/null
> +++ b/arch/arm64/kernel/binfmt_ilp32.c
> @@ -0,0 +1,91 @@
> +/*
> + * Support for ILP32 Linux/aarch64 ELF binaries.
> + */
> +
> +#include <linux/elfcore-compat.h>
> +#include <linux/time.h>
> +
> +#undef	ELF_CLASS
> +#define ELF_CLASS	ELFCLASS32
> +
> +#undef	elfhdr
> +#undef	elf_phdr
> +#undef	elf_shdr
> +#undef	elf_note
> +#undef	elf_addr_t
> +#define elfhdr		elf32_hdr
> +#define elf_phdr	elf32_phdr
> +#define elf_shdr	elf32_shdr
> +#define elf_note	elf32_note
> +#define elf_addr_t	Elf32_Addr
> +
> +/*
> + * Some data types as stored in coredump.
> + */
> +#define user_long_t		compat_long_t
> +#define user_siginfo_t		compat_siginfo_t
> +#define copy_siginfo_to_user	copy_siginfo_to_user32
> +
> +/*
> + * The machine-dependent core note format types are defined in elfcore-compat.h,
> + * which requires asm/elf.h to define compat_elf_gregset_t et al.
> + */
> +#define elf_prstatus	compat_elf_prstatus
> +#define elf_prpsinfo	compat_elf_prpsinfo
> +
> +/*
> + * Compat version of cputime_to_compat_timeval, perhaps this
> + * should be an inline in <linux/compat.h>.
> + */
> +static void cputime_to_compat_timeval(const cputime_t cputime,
> +				      struct compat_timeval *value)
> +{
> +	struct timeval tv;
> +	cputime_to_timeval(cputime, &tv);
> +	value->tv_sec = tv.tv_sec;
> +	value->tv_usec = tv.tv_usec;
> +}
> +
> +#undef cputime_to_timeval
> +#define cputime_to_timeval cputime_to_compat_timeval
> +
> +/* AARCH64 ILP32 EABI. */
> +#undef elf_check_arch
> +#define elf_check_arch(x)		(((x)->e_machine == EM_AARCH64)	\
> +					&& (x)->e_ident[EI_CLASS] == ELFCLASS32)
> +
> +#undef SET_PERSONALITY
> +#define SET_PERSONALITY(ex)						\
> +do {									\
> +	set_thread_flag(TIF_32BIT_AARCH64);				\
> +	clear_thread_flag(TIF_32BIT);					\
> +} while (0)
> +
> +#undef ARCH_DLINFO
> +#define ARCH_DLINFO							\
> +do {									\
> +	NEW_AUX_ENT(AT_SYSINFO_EHDR,					\
> +		    (elf_addr_t)(long)current->mm->context.vdso);	\
> +} while (0)
> +
> +#ifdef __AARCH64EB__
> +#define COMPAT_ELF_PLATFORM		("aarch64_be:ilp32")
> +#else
> +#define COMPAT_ELF_PLATFORM		("aarch64:ilp32")
> +#endif
> +
> +#undef ELF_HWCAP
> +#undef ELF_HWCAP2
> +#define ELF_HWCAP			((u32) elf_hwcap)
> +#define ELF_HWCAP2			((u32) (elf_hwcap >> 32))
> +
> +/*
> + * Rename a few of the symbols that binfmt_elf.c will define.
> + * These are all local so the names don't really matter, but it
> + * might make some debugging less confusing not to duplicate them.
> + */
> +#define elf_format		compat_elf_format
> +#define init_elf_binfmt		init_compat_elf_binfmt
> +#define exit_elf_binfmt		exit_compat_elf_binfmt
> +
> +#include "../../../fs/binfmt_elf.c"
>



From linux at roeck-us.net  Thu May 26 06:54:46 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Thu, 26 May 2016 06:54:46 -0700
Subject: [RFC PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <1464249112-13658-2-git-send-email-narmstrong@baylibre.com>
References: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
 <1464249112-13658-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <57470026.3000501@roeck-us.net>

On 05/26/2016 12:51 AM, Neil Armstrong wrote:
> Add watchdog specific driver for Amlogic Meson GXBB SoC.
>

Wondering - why RFC ?

> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>   drivers/watchdog/Makefile         |   1 +
>   drivers/watchdog/meson_gxbb_wdt.c | 287 ++++++++++++++++++++++++++++++++++++++
>   2 files changed, 288 insertions(+)
>   create mode 100644 drivers/watchdog/meson_gxbb_wdt.c
>
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index 9bde095..7679d93 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -68,6 +68,7 @@ obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
>   obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
>   obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
>   obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
> +obj-$(CONFIG_MESON_WATCHDOG) += meson_gxbb_wdt.o
>   obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
>   obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
>   obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
> diff --git a/drivers/watchdog/meson_gxbb_wdt.c b/drivers/watchdog/meson_gxbb_wdt.c
> new file mode 100644
> index 0000000..0c7c0d9
> --- /dev/null
> +++ b/drivers/watchdog/meson_gxbb_wdt.c
> @@ -0,0 +1,287 @@
> +/*
> + * This file is provided under a dual BSD/GPLv2 license.  When using or
> + * redistributing this file, you may do so under either license.
> + *
> + * GPL LICENSE SUMMARY
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Neil Armstrong <narmstrong at baylibre.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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + * The full GNU General Public License is included in this distribution
> + * in the file called COPYING.
> + *
> + * BSD LICENSE
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Neil Armstrong <narmstrong at baylibre.com>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + *   * Redistributions of source code must retain the above copyright
> + *     notice, this list of conditions and the following disclaimer.
> + *   * Redistributions in binary form must reproduce the above copyright
> + *     notice, this list of conditions and the following disclaimer in
> + *     the documentation and/or other materials provided with the
> + *     distribution.
> + *   * Neither the name of Intel Corporation nor the names of its
> + *     contributors may be used to endorse or promote products derived
> + *     from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +#include <linux/err.h>
> +#include <linux/module.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/clk.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <linux/watchdog.h>
> +
> +#define DEFAULT_TIMEOUT	10	/* seconds */
> +
> +#define GXBB_WDT_CTRL_REG	0x0
> +#define GXBB_WDT_CTRL1_REG	0x4
> +#define GXBB_WDT_TCNT_REG	0x8
> +#define GXBB_WDT_RSET_REG	0xc
> +
> +#define GXBB_WDT_CTRL_EE_RESET_NOW	BIT(26)
> +
> +#define GXBB_WDT_CTRL_CLKDIV_EN	BIT(25)
> +#define GXBB_WDT_CTRL_CLK_EN	BIT(24)
> +#define GXBB_WDT_CTRL_IRQ_EN	BIT(23)
> +#define GXBB_WDT_CTRL_EE_RESET	BIT(21)
> +#define GXBB_WDT_CTRL_XTAL_SEL	(0)
> +#define GXBB_WDT_CTRL_CLK81_SEL	BIT(19)
> +#define GXBB_WDT_CTRL_EN	BIT(18)
> +#define GXBB_WDT_CTRL_DIV_MASK	(BIT(18)-1)
> +
> +#define GXBB_WDT_CTRL1_GPIO_PULSE	BIT(17)
> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_0	BIT(16)
> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_1	(0)
> +#define GXBB_WDT_CTRL1_GPIO_PULSE_CNT	(BIT(16)-1)
> +

Spaces around operators, please.

> +#define GXBB_WDT_TCNT_SETUP_MASK	(BIT(16)-1)
> +#define GXBB_WDT_TCNT_CNT_SHIFT		16
> +
> +struct meson_gxbb_wdt {
> +	void __iomem *reg_base;
> +	struct watchdog_device wdt_dev;
> +	struct clk *clk;
> +};
> +
> +int meson_gxbb_wdt_start(struct watchdog_device *wdt_dev)

Functions should all be static.

> +{
> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> +
> +	writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) | GXBB_WDT_CTRL_EN,
> +		data->reg_base + GXBB_WDT_CTRL_REG);
> +
> +	return 0;
> +}
> +
> +int meson_gxbb_wdt_stop(struct watchdog_device *wdt_dev)
> +{
> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> +
> +	writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) & ~GXBB_WDT_CTRL_EN,
> +		data->reg_base + GXBB_WDT_CTRL_REG);
> +
> +	return 0;
> +}
> +
> +unsigned int meson_gxbb_wdt_status(struct watchdog_device *wdt_dev)
> +{
> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> +
> +	return !!(readl(data->reg_base + GXBB_WDT_CTRL_REG) & GXBB_WDT_CTRL_EN);

This function is not supposed to return 0/1 but a bit mask with relevant
WDIOF_bits set. sbsa_gwdt.c is buggy (oops, and I reviewed it ;-), so
please don't use it as example; it doesn't make much sense to return
a kernel-only flag to user space.

Overall I would suggest to not implement the function at all. We'll have
to revisit it - its current implementation in the watchdog core does not
make much sense and for the most part only returns 0 to user space.
The only driver implementing it (sbsa) returns a bad value. It is also
_not_ supposed to return the "watchdog running" status as currently
implemented (there is no WDIOF_ flag indicating that the watchdog is
running).

> +}
> +
> +int meson_gxbb_wdt_ping(struct watchdog_device *wdt_dev)
> +{
> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> +
> +	writel(0, data->reg_base + GXBB_WDT_RSET_REG);
> +
> +	return 0;
> +}
> +
> +int meson_gxbb_wdt_set_timeout(struct watchdog_device *wdt_dev,
> +			       unsigned int timeout)
> +{
> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> +
> +	if (watchdog_active(wdt_dev))
> +		meson_gxbb_wdt_stop(wdt_dev);
> +

Is the stop/start sequence mandatory ? It leaves the system unprotected
for a few cycles, so it is undesirable.

> +	meson_gxbb_wdt_ping(wdt_dev);
> +
> +	writel(timeout*1000, data->reg_base + GXBB_WDT_TCNT_REG);
> +
> +	if (watchdog_active(wdt_dev))
> +		meson_gxbb_wdt_start(wdt_dev);
> +
> +	return 0;
> +}
> +
> +unsigned int meson_gxbb_wdt_get_timeleft(struct watchdog_device *wdt_dev)
> +{
> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> +	unsigned long reg;
> +
> +	reg = readl(data->reg_base + GXBB_WDT_TCNT_REG);
> +
> +	return ((reg >> GXBB_WDT_TCNT_CNT_SHIFT)-
> +			(reg & GXBB_WDT_TCNT_SETUP_MASK)) / 1000;
> +}
> +
> +static const struct watchdog_ops meson_gxbb_wdt_ops = {
> +	.start = meson_gxbb_wdt_start,
> +	.stop = meson_gxbb_wdt_stop,
> +	.status = meson_gxbb_wdt_status,
> +	.ping = meson_gxbb_wdt_ping,
> +	.set_timeout = meson_gxbb_wdt_set_timeout,
> +	.get_timeleft = meson_gxbb_wdt_get_timeleft,
> +};
> +
> +static const struct watchdog_info meson_gxbb_wdt_info = {
> +	.identity = "meson-gxbb-wdt",
> +	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
> +};
> +
> +static int __maybe_unused meson_gxbb_wdt_resume(struct device *dev)
> +{
> +	struct meson_gxbb_wdt *data = dev_get_drvdata(dev);
> +
> +	if (watchdog_active(&data->wdt_dev))
> +		meson_gxbb_wdt_start(&data->wdt_dev);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused meson_gxbb_wdt_suspend(struct device *dev)
> +{
> +	struct meson_gxbb_wdt *data = dev_get_drvdata(dev);
> +
> +	if (watchdog_active(&data->wdt_dev))
> +		meson_gxbb_wdt_stop(&data->wdt_dev);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops meson_gxbb_wdt_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(meson_gxbb_wdt_suspend, meson_gxbb_wdt_resume)
> +};
> +
> +static const struct of_device_id meson_gxbb_wdt_dt_ids[] = {
> +	 { .compatible = "amlogic,meson-gxbb-wdt", },
> +	 { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, meson_gxbb_wdt_dt_ids);
> +
> +static int meson_gxbb_wdt_probe(struct platform_device *pdev)
> +{
> +	struct meson_gxbb_wdt *data;
> +	struct resource *res;
> +	int ret;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	data->reg_base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(data->reg_base))
> +		return PTR_ERR(data->reg_base);
> +
> +	data->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(data->clk))
> +		return PTR_ERR(data->clk);
> +
> +	clk_prepare_enable(data->clk);
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	data->wdt_dev.parent = &pdev->dev;
> +	data->wdt_dev.info = &meson_gxbb_wdt_info;
> +	data->wdt_dev.ops = &meson_gxbb_wdt_ops;
> +	data->wdt_dev.max_hw_heartbeat_ms = GXBB_WDT_TCNT_SETUP_MASK;
> +	data->wdt_dev.min_hw_heartbeat_ms = 1;

Does the device require a minimum time between heartbeats ?
Just asking, because you violate it yourself below.

If you want to set the minimum timeout, that would be min_timeout.

> +	data->wdt_dev.timeout = DEFAULT_TIMEOUT;
> +	watchdog_set_drvdata(&data->wdt_dev, data);
> +
> +	watchdog_init_timeout(&data->wdt_dev, DEFAULT_TIMEOUT, &pdev->dev);
> +

DEFAULT_TIMEOUT is unnecessary here. Since the default timeout is already set,
it makes the call useless.

> +	ret = watchdog_register_device(&data->wdt_dev);
> +	if (ret)
> +		return ret;
> +
> +	/* Setup with 1ms timebase */
> +	writel(((clk_get_rate(data->clk) / 1000) & GXBB_WDT_CTRL_DIV_MASK) |
> +		GXBB_WDT_CTRL_EE_RESET |
> +		GXBB_WDT_CTRL_CLK_EN |
> +		GXBB_WDT_CTRL_CLKDIV_EN,
> +		data->reg_base + GXBB_WDT_CTRL_REG);
> +	meson_gxbb_wdt_set_timeout(&data->wdt_dev, data->wdt_dev.timeout);

set_timeout already calls the ping function. Also, the functions should be called
prior to watchdog registration to avoid race conditions.

> +	meson_gxbb_wdt_ping(&data->wdt_dev);

This is unusual. If the watchdog can be already running, it might make sense
to tell the core about it (set WDOG_HW_RUNNING in the status field), so it
can send heartbeats until user space opens the device.

> +
> +	return 0;
> +}
> +
> +static int meson_gxbb_wdt_remove(struct platform_device *pdev)
> +{
> +	struct meson_gxbb_wdt *data = platform_get_drvdata(pdev);
> +
> +	watchdog_unregister_device(&data->wdt_dev);
> +
> +	return 0;
> +}
> +
> +static void meson_gxbb_wdt_shutdown(struct platform_device *pdev)
> +{
> +	struct meson_gxbb_wdt *data = platform_get_drvdata(pdev);
> +
> +	meson_gxbb_wdt_stop(&data->wdt_dev);
> +}
> +
> +static struct platform_driver meson_gxbb_wdt_driver = {
> +	.probe	= meson_gxbb_wdt_probe,
> +	.remove	= meson_gxbb_wdt_remove,
> +	.shutdown = meson_gxbb_wdt_shutdown,
> +	.driver = {
> +		.name = "meson-gxbb-wdt",
> +		.pm = &meson_gxbb_wdt_pm_ops,
> +		.of_match_table	= meson_gxbb_wdt_dt_ids,
> +	},
> +};
> +
> +module_platform_driver(meson_gxbb_wdt_driver);
> +
> +MODULE_ALIAS("platform:meson-gxbb-wdt");
> +MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
> +MODULE_DESCRIPTION("Amlogic Meson GXBB Watchdog timer driver");
> +MODULE_LICENSE("Dual BSD/GPL");
>



From catalin.marinas at arm.com  Thu May 26 07:20:58 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 26 May 2016 15:20:58 +0100
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160525.142821.1719403997976778673.davem@davemloft.net>
References: <6293194.tGy03QJ9ME@wuerfel>
 <20160525.135039.244098606649448826.davem@davemloft.net>
 <6407614.fdv5XFSBue@wuerfel>
 <20160525.142821.1719403997976778673.davem@davemloft.net>
Message-ID: <20160526142057.GA7456@e104818-lin.cambridge.arm.com>

On Wed, May 25, 2016 at 02:28:21PM -0700, David Miller wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> Date: Wed, 25 May 2016 23:01:06 +0200
> 
> > On Wednesday, May 25, 2016 1:50:39 PM CEST David Miller wrote:
> >> From: Arnd Bergmann <arnd at arndb.de>
> >> Date: Wed, 25 May 2016 22:47:33 +0200
> >> 
> >> > If we use the normal calling conventions, we could remove these overrides
> >> > along with the respective special-case handling in glibc. None of them
> >> > look particularly performance-sensitive, but I could be wrong there.
> >> 
> >> You could set the lowest bit in the system call entry pointer to indicate
> >> the upper-half clears should be elided.
> > 
> > Right, but that would introduce an extra conditional branch in the syscall
> > hotpath, and likely eliminate the gains from passing the loff_t arguments
> > in a single register instead of a pair.
> 
> Ok, then, how much are you really gaining from avoiding a 'shift' and
> an 'or' to build the full 64-bit value?  3 cycles?  Maybe 4?

It's possible a few more cycles overall. Whether this is noticeable, I
can't really tell without some benchmarks (e.g. a getpid wrapper zeroing
top 32-bit of all possible 6 arguments, called in a loop).

On arm64 with ILP32 we have three types of syscalls w.r.t. parameter
width (I guess that's true for all other compat implementations):

1. User syscall definition with 32-bit arguments, kernel handling 32-bit
   arguments

2. User 32-bit arguments, kernel 64-bit arguments

3. User 64-bit arguments, kernel 64-bit arguments

For (1), the AArch64 ABI (AAPCS) allows us to ignore the garbage in the
top 32-bit of a 64-bit register as long as the callee has 32-bit
arguments (IOW, the generated code will use 32-git Wn instead of 64-bit
Xn registers). In this case, zeroing the top 32-bit of all 6 arguments
is unnecessary.

In the 2nd case, we need sign or zero extension of 32-bit arguments. For
sign extension we would still need a wrapper as the generic one can only
zero-extend without knowing the underlying type. How many cases do we
have where sign extension is required (off_t is a signed type but does
it actually make sense as a negative value)? The __SC_WRAP and
COMPAT_SYSCALL_WRAP macros introduced by patches 3-5 in this series
handle such conversion for both sign and unsigned arguments.

We don't have such problem with AArch32 tasks since the architecture
guarantees zeroing or preserving the top half of all registers.

For (3), with the current ILP32 approach we wouldn't need any wrapper.
If we are to pass the argument as two 32-bit values, we would need both
the user (glibc) to split the argument and the kernel to re-construct
it. This would be in addition to any default top 32-bit zeroing on
kernel entry.

The overhead may be lost in the noise (we need some data) but IIRC our
decision was mostly based on a cleaner user implementation for point (3)
above. Since an AArch64/ILP32 process can freely use 64-bit registers,
we found it nicer to be able to pass such value directly to the kernel.
Reusing the s390 macros should reduce the amount of new code added to
the kernel.


While writing the above, I realised the current ILP32 patches still miss
on converting pointers passed from user space (unless I got myself
confused in macros). The new __SC_WRAP() and COMPAT_SYSCALL_WRAPx()
macros take care of zero or sign extension via __SC_COMPAT_CAST().
However, we have two more existing cases which I don't see covered:

a) Native syscalls taking a pointer argument and invoked directly from
   ILP32. For example, sys_read() takes a pointer but I don't see any
   __SC_WRAP added by patch 5

b) Current compat syscalls taking a pointer argument. For example,
   compat_sys_vmsplice() gets the iov32 pointer and the compiler assumes
   it is a 64-bit variable. I don't see where the upper half is zeroed

We can solve (a) by adding more __SC_WRAP annotations in the generic
unistd.h. For (b), we would need an __SC_DELOUSE with a bit of penalty
on AArch32/compat support where it isn't needed. So maybe davem has a
point on the overall impact of always zeroing the upper half of the
arguments ;) (both from a performance and maintainability perspective).
I guess this part of the ABI is still up for discussion.

-- 
Catalin


From christopher.spinrath at rwth-aachen.de  Thu May 26 07:26:00 2016
From: christopher.spinrath at rwth-aachen.de (Christopher Spinrath)
Date: Thu, 26 May 2016 16:26:00 +0200
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <a6cc6b85d2fa4994b3cb7e2b047f800d@rwthex-w2-b.rwth-ad.de>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
 <CAOMZO5C5goJUdHKB9a=eOv9TKDkJWxnkWWb-G7E5Kvceg6sZVg@mail.gmail.com>
 <a6cc6b85d2fa4994b3cb7e2b047f800d@rwthex-w2-b.rwth-ad.de>
Message-ID: <9d7793850de942cfb578b0aeb2728f41@rwthex-s1-b.rwth-ad.de>

Hi Igor,

On 05/26/2016 10:28 AM, Igor Grinberg wrote:
> Hi Fabio,
> 
> On 05/23/2016 08:49 PM, Fabio Estevam wrote:
>> On Sun, May 22, 2016 at 7:47 PM,  <christopher.spinrath at rwth-aachen.de> wrote:
>>
>>> diff --git a/arch/arm/boot/dts/imx6q-utilite-pro.dts b/arch/arm/boot/dts/imx6q-utilite-pro.dts
>>> new file mode 100644
>>> index 0000000..bcd8e0d
>>> --- /dev/null
>>> +++ b/arch/arm/boot/dts/imx6q-utilite-pro.dts
>>> @@ -0,0 +1,128 @@
>>> +/*
>>> + * Copyright 2016 Christopher Spinrath
>>> + * Copyright 2013 CompuLab Ltd.
>>> + *
>>> + * Based on the GPLv2 licensed devicetree distributed with the vendor
>>> + * kernel for the Utilite Pro:
>>> + *     Copyright 2013 CompuLab Ltd.
>>> + *     Author: Valentin Raevsky <valentin at compulab.co.il>
>>> + *
>>> + * The code contained herein is licensed under the GNU General Public
>>> + * License. You may obtain a copy of the GNU General Public License
>>> + * Version 2 or later at the following locations:
>>
>> Can you make this dual GPL/X11 license?
>>
>> For reference take a look at:
>> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/imx6sl-warp.dts?id=refs/tags/v4.6
> 
> Please excuse me my ignorance, what is the rationale for this change?
> 

Thanks for joining this discussion. I *guess* the rationale is to share
the same device tree with projects that are incompatible with the GPL
(e.g. *BSD). Even if there is no support for a particular device/board
having all (or most) files dual licensed makes it easier to just pull
them all in.

Cheers,
Christopher


From linux at armlinux.org.uk  Thu May 26 07:33:15 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Thu, 26 May 2016 15:33:15 +0100
Subject: [PATCH kexec-tools 04/32] kdump: fix kdump mapping
In-Reply-To: <CAHB_GurQ44ybkxaYJJQeGgnuw=3tKOk7xyB6FTAursMLuZGrJg@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSF-0004hH-Oo@e0050434b2927.dyn.arm.linux.org.uk>
 <CAHB_GurQ44ybkxaYJJQeGgnuw=3tKOk7xyB6FTAursMLuZGrJg@mail.gmail.com>
Message-ID: <20160526143315.GJ19428@n2100.arm.linux.org.uk>

On Wed, May 25, 2016 at 11:47:33AM +0530, Pratyush Anand wrote:
> On Tue, May 3, 2016 at 3:51 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> > diff --git a/kdump/kdump.c b/kdump/kdump.c
> > index 1f5b984..34d2149 100644
> > --- a/kdump/kdump.c
> > +++ b/kdump/kdump.c
> > @@ -284,7 +284,8 @@ int main(int argc, char **argv)
> >         }
> >
> >         /* Get the program header */
> > -       phdr = map_addr(fd, sizeof(*phdr)*(ehdr->e_phnum), ehdr->e_phoff);
> > +       phdr = map_addr(fd, sizeof(*phdr)*(ehdr->e_phnum),
> > +                       start_addr + ehdr->e_phoff);
> 
> This is fine. But at the same time should n't we also fix the offset
> for mmap of memory segments?  For memory segments, offset is
> phdr[i].p_offset, and I do not see generate_new_headers() taking care
> of start_addr.

Unfortunately not.  The reason is, p_offset is not an offset, but an
absolute address - see kexec/crashdump-elf.c, which is the bit of
code which creates the table and writes it into kernel memory when
loading the panic kernel:

                phdr->p_offset  = phdr->p_paddr = notes_addr;

                phdr->p_offset  = phdr->p_paddr = vmcoreinfo_addr;

                phdr->p_offset  = phdr->p_paddr = elf_info->kern_paddr_start;

                mstart = range->start;
                phdr->p_offset  = mstart;
                phdr->p_paddr = mstart;

etc.  So, p_offset is also the physical address, not the file offset.
Of course, that could be a bug in crashdump-elf.c.  To change that,
we would also need to fix crashdump-elf.c in lock-step as well.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From ulli.kroll at googlemail.com  Thu May 26 09:33:48 2016
From: ulli.kroll at googlemail.com (Hans Ulli Kroll)
Date: Thu, 26 May 2016 18:33:48 +0200 (CEST)
Subject: [PATCH 0095/1529] Fix typo
In-Reply-To: <20160521114905.4276-1-andrea.gelmini@gelma.net>
References: <20160521114905.4276-1-andrea.gelmini@gelma.net>
Message-ID: <alpine.LNX.2.00.1605261832200.15970@T420s>



On Sat, 21 May 2016, Andrea Gelmini wrote:

> Signed-off-by: Andrea Gelmini <andrea.gelmini at gelma.net>
> ---
>  arch/arm/mach-gemini/idle.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-gemini/idle.c b/arch/arm/mach-gemini/idle.c
> index ddf8ec9..cb34fe4e 100644
> --- a/arch/arm/mach-gemini/idle.c
> +++ b/arch/arm/mach-gemini/idle.c
> @@ -10,7 +10,7 @@ static void gemini_idle(void)
>  {
>  	/*
>  	 * Because of broken hardware we have to enable interrupts or the CPU
> -	 * will never wakeup... Acctualy it is not very good to enable
> +	 * will never wakeup... Actually it is not very good to enable
>  	 * interrupts first since scheduler can miss a tick, but there is
>  	 * no other way around this. Platforms that needs it for power saving
>  	 * should enable it in init code, since by default it is
> -- 
> 2.8.2.534.g1f66975
> 
> 

Acked-by: Hans Ulli Kroll <ulli.kroll at googlemail.com>


From szabolcs.nagy at arm.com  Thu May 26 07:50:01 2016
From: szabolcs.nagy at arm.com (Szabolcs Nagy)
Date: Thu, 26 May 2016 15:50:01 +0100
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160526142057.GA7456@e104818-lin.cambridge.arm.com>
References: <6293194.tGy03QJ9ME@wuerfel>
 <20160525.135039.244098606649448826.davem@davemloft.net>
 <6407614.fdv5XFSBue@wuerfel>
 <20160525.142821.1719403997976778673.davem@davemloft.net>
 <20160526142057.GA7456@e104818-lin.cambridge.arm.com>
Message-ID: <57470D19.2000501@arm.com>

On 26/05/16 15:20, Catalin Marinas wrote:
> While writing the above, I realised the current ILP32 patches still miss
> on converting pointers passed from user space (unless I got myself
> confused in macros). The new __SC_WRAP() and COMPAT_SYSCALL_WRAPx()
> macros take care of zero or sign extension via __SC_COMPAT_CAST().
> However, we have two more existing cases which I don't see covered:
> 
> a) Native syscalls taking a pointer argument and invoked directly from
>    ILP32. For example, sys_read() takes a pointer but I don't see any
>    __SC_WRAP added by patch 5
> 
> b) Current compat syscalls taking a pointer argument. For example,
>    compat_sys_vmsplice() gets the iov32 pointer and the compiler assumes
>    it is a 64-bit variable. I don't see where the upper half is zeroed
> 

on x32 sign/zero extension is currently left to userspace,
which is difficult to deal with, (long long)arg does the
wrong thing for pointer args.

> We can solve (a) by adding more __SC_WRAP annotations in the generic
> unistd.h. For (b), we would need an __SC_DELOUSE with a bit of penalty
> on AArch32/compat support where it isn't needed. So maybe davem has a
> point on the overall impact of always zeroing the upper half of the
> arguments ;) (both from a performance and maintainability perspective).
> I guess this part of the ABI is still up for discussion.
> 



From ritesh.list at gmail.com  Thu May 26 07:59:05 2016
From: ritesh.list at gmail.com (Ritesh Harjani)
Date: Thu, 26 May 2016 20:29:05 +0530
Subject: [PATCH 09/23] mmc: sdhci: fix incorrect get data interrupt during
 no data transfer
In-Reply-To: <573AB323.1080207@intel.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-10-git-send-email-aisheng.dong@nxp.com>
 <573184F3.50201@intel.com>
 <CALk7dXpDXS2R0RJ9KNTaMFxBC+VVvrJ+U1X5Z_kZJNxwxrC6iQ@mail.gmail.com>
 <573AB323.1080207@intel.com>
Message-ID: <CALk7dXq=Yv-a8UEbBqgxSEnDEOD1fuAkZhFnP8oyEmoPsrVCrw@mail.gmail.com>

Hi Adrian,


On Tue, May 17, 2016 at 11:28 AM, Adrian Hunter <adrian.hunter at intel.com> wrote:
> On 17/05/16 07:31, Ritesh Harjani wrote:
>> On Tue, May 10, 2016 at 12:21 PM, Adrian Hunter <adrian.hunter at intel.com> wrote:
>>> On 15/04/16 20:29, Dong Aisheng wrote:
>>>> Current code will report the wrong data interrupt got when no
>>>> data operation in progress assumed by getting !host->data in
>>>> sdhci_data_irq().
>>>>
>>>> For a data command handling process, the driver will call
>>>> sdhci_finish_data() and clear host->data in case any data error,
>>>> then card finish_tasklet will do the rest controller reset work.
>>>>
>>>> Before the tasklet got run, however, controllers may report the
>>>> TC(Transfer Complete) interrupt (SDHCI_INT_DATA_END) a bit later
>>>> than data CRC error and data end bit error interrupts for single
>>>> block transfer or the last block of multiblock transfer.
>>
>> What if the controller generates Transfer complete interrupt bit more slower
>> and the tasklet do get a chance to run. In that case even host->mrq
>> will become NULL.
>> Actually if that happens it's even more worse since the driver may
>> start issuing other commands to controller.
>>
>> Are we covering that case here? Do you think that this case is possible?
>
> After data error, the host driver resets the controller so there will be no
> more interrupts relating to that mrq.
Resetting will happen in sdhci_tasklet_finish.
My case was -
1. Controller raised a Data CRC error.
2. sdhci_irq made host->data = NULL in sdhci_finish_data and scheduled
the finish_tasklet.
3. while the tasklet is running and before resetting CMD and Data
machine, TC interrupt is raised by controller.
4. sdhci_irq will call for sdhci_data_irq.

But I get it that the second interrupt will end up printing the same
error since host->data will be found as NULL in sdhci_data_irq and
will return.
So below patch should do the job :)

>
> This patch is avoiding unnecessary warnings until that happens.
Yes.



>
>>
>>
>>>>
>>>> Controller usually detects and generates data CRC/end bit error
>>>> interrupts once one block on the bus is transferred completely.
>>>> For single block transfer, since there's only one bock to transfer,
>>>> the controller will report transfer complete interrupt as well,
>>>> but until the data in controller FIFO has been successfully
>>>> transferred to memory. The time gap of TC and CRC interrupt depends on
>>>> the system busy state at that point and memory bus access speed.
>>>>
>>>> So it is possible when TC interrupt generated, host->data is already
>>>> equal to NULL due to cleared by former CRC/Data End Bit error which
>>>> is reasonable.
>>>>
>>>> Thus we DO NOT report the weird data interrupt event for this case.
>>>>
>>>> Else we may easily see warning below during SD3.0 card manually tuning
>>>> process (calling mmc_send_tuning() which is a single block transfer)
>>>> mmc0: Got data interrupt 0x00000002 even though no data operation was in progress
>>>>
>>>> The detailed command log is as follows:
>>>> [ 1657.920983] mmc0: starting CMD19 arg 00000000 flags 00000035
>>>> [ 1657.921009] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
>>>> [ 1657.921085] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00200001
>>>> [ 1657.921112] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
>>>> [ 1657.921131] mmc0: Got data interrupt 0x00000002 even though no data operation was in progress.
>>>> [ 1657.929761] sdhci: =========== REGISTER DUMP (mmc0)===========
>>>> [ 1657.929780] sdhci: Sys addr: 0x3d5d6380 | Version:  0x00000002
>>>> [ 1657.929796] sdhci: Blk size: 0x00000040 | Blk cnt:  0x00000001
>>>> [ 1657.929814] sdhci: Argument: 0x00000000 | Trn mode: 0x00000013
>>>> [ 1657.929831] sdhci: Present:  0x01fd8008 | Host ctl: 0x00000023
>>>> [ 1657.929847] sdhci: Power:    0x00000002 | Blk gap:  0x00000080
>>>> [ 1657.929863] sdhci: Wake-up:  0x00000008 | Clock:    0x0000000f
>>>> [ 1657.929879] sdhci: Timeout:  0x0000000f | Int stat: 0x00000000
>>>> [ 1657.929896] sdhci: Int enab: 0x107f008b | Sig enab: 0x107f008b
>>>> [ 1657.929914] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000003
>>>> [ 1657.929932] sdhci: Caps:     0x07eb0000 | Caps_1:   0x00002007
>>>> [ 1657.929949] sdhci: Cmd:      0x0000133a | Max curr: 0x00ffffff
>>>> [ 1657.929965] sdhci: Host ctl2: 0x000000c8
>>>> [ 1657.929981] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x8f042208
>>>> [ 1657.929995] sdhci: ===========================================
>>>> [ 1657.930156] mmc0: req done (CMD19): 0: 00000900 00000000 00000000 00000000
>>>> [ 1657.930179] mmc0:     0 bytes transferred: -84
>>>>
>>>> It shows we first have a data CRC error interrupt then a data transfer
>>>> complete interrupt.
>>>> Then we got the !host->data case in sdhci_data_irq().
>>>>
>>>> CC: stable <stable at vger.kernel.org>
>>>> Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
>>>> ---
>>>>  drivers/mmc/host/sdhci.c | 11 +++++++++++
>>>>  1 file changed, 11 insertions(+)
>>>>
>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>> index 40e3551..2eb0e34 100644
>>>> --- a/drivers/mmc/host/sdhci.c
>>>> +++ b/drivers/mmc/host/sdhci.c
>>>> @@ -2325,6 +2325,17 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
>>>>                       }
>>>>               }
>>>>
>>>> +             /*
>>>> +              * The "data complete" interrupt is possible to happen a bit
>>>> +              * later than CRC error and data end bit error interrupts
>>>> +              * separately for single block transfer or the last block of
>>>> +              * multiblock transfer. For this case, we DO NOT report the
>>>> +              * weird data interrupt event.
>>>> +              */
>>>> +             if ((intmask & SDHCI_INT_DATA_END) &&
>>>> +                 (host->mrq && host->mrq->data && host->mrq->data->error))
>>>> +                     return;
>>>
>>> This could be generalized a bit more i.e. what about:
>>>
>>>                 /*
>>>                  * After an error and before the the data circuit is reset in
>>>                  * sdhci_tasklet_finish, we could get more interrupts, but we
>>>                  * already have an error, so ignore them.
>>>                  */
>>>                 if (host->mrq && host->mrq->data && host->mrq->data->error)
>>>                         return;
>>>
>>>> +
>>>>               pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
>>>>                      mmc_hostname(host->mmc), (unsigned)intmask);
>>>>               sdhci_dumpregs(host);
>>>>
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>>> the body of a message to majordomo at vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>


From catalin.marinas at arm.com  Thu May 26 08:19:02 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 26 May 2016 16:19:02 +0100
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <57470D19.2000501@arm.com>
References: <6293194.tGy03QJ9ME@wuerfel>
 <20160525.135039.244098606649448826.davem@davemloft.net>
 <6407614.fdv5XFSBue@wuerfel>
 <20160525.142821.1719403997976778673.davem@davemloft.net>
 <20160526142057.GA7456@e104818-lin.cambridge.arm.com>
 <57470D19.2000501@arm.com>
Message-ID: <20160526151902.GC7456@e104818-lin.cambridge.arm.com>

On Thu, May 26, 2016 at 03:50:01PM +0100, Szabolcs Nagy wrote:
> On 26/05/16 15:20, Catalin Marinas wrote:
> > While writing the above, I realised the current ILP32 patches still miss
> > on converting pointers passed from user space (unless I got myself
> > confused in macros). The new __SC_WRAP() and COMPAT_SYSCALL_WRAPx()
> > macros take care of zero or sign extension via __SC_COMPAT_CAST().
> > However, we have two more existing cases which I don't see covered:
> > 
> > a) Native syscalls taking a pointer argument and invoked directly from
> >    ILP32. For example, sys_read() takes a pointer but I don't see any
> >    __SC_WRAP added by patch 5
> > 
> > b) Current compat syscalls taking a pointer argument. For example,
> >    compat_sys_vmsplice() gets the iov32 pointer and the compiler assumes
> >    it is a 64-bit variable. I don't see where the upper half is zeroed
> 
> on x32 sign/zero extension is currently left to userspace,
> which is difficult to deal with, (long long)arg does the
> wrong thing for pointer args.

I agree, I don't think we should leave sign/zero extension to user. We
should do it in the kernel either in a way similar to s390 (specific
__SC_COMPAT_CAST, __SC_DELOUSE) or by always zeroing the arguments upper
half on kernel entry with a few additional wrappers (where we have
64-bit arguments or they require sign extension). The latter has the
disadvantage of having to split 64-bit arguments in user space while the
former adds more maintenance burden to the kernel.

I can't comment on performance aspects without some real numbers.

-- 
Catalin


From dave.long at linaro.org  Thu May 26 08:26:01 2016
From: dave.long at linaro.org (David Long)
Date: Thu, 26 May 2016 11:26:01 -0400
Subject: [PATCH v12 06/10] arm64: Treat all entry code as non-kprobe-able
In-Reply-To: <573497FA.5030309@arm.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-7-git-send-email-dave.long@linaro.org>
 <573497FA.5030309@arm.com>
Message-ID: <57471589.9030301@linaro.org>

On 05/12/2016 10:49 AM, James Morse wrote:
> Hi David, Pratyush
>
> On 27/04/16 19:53, David Long wrote:
>> From: Pratyush Anand <panand at redhat.com>
>>
>> Entry symbols are not kprobe safe. So blacklist them for kprobing.
>>
>> Signed-off-by: Pratyush Anand <panand at redhat.com>
>
>> diff --git a/arch/arm64/kernel/kprobes.c b/arch/arm64/kernel/kprobes.c
>> index dfa1b1f..6a1292b 100644
>> --- a/arch/arm64/kernel/kprobes.c
>> +++ b/arch/arm64/kernel/kprobes.c
>> @@ -29,6 +29,7 @@
>>   #include <asm/system_misc.h>
>>   #include <asm/insn.h>
>>   #include <asm/uaccess.h>
>> +#include <asm-generic/sections.h>
>>
>>   #include "kprobes-arm64.h"
>>
>> @@ -514,6 +515,15 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
>>   	return 1;
>>   }
>>
>> +bool arch_within_kprobe_blacklist(unsigned long addr)
>> +{
>> +	return  (addr >= (unsigned long)__kprobes_text_start &&
>> +		 addr < (unsigned long)__kprobes_text_end) ||
>> +		(addr >= (unsigned long)__entry_text_start &&
>> +		 addr < (unsigned long)__entry_text_end) ||
>> +		 !!search_exception_tables(addr);
>> +}
>> +
>
> Looking at __kvm_hyp_vector, we don't have support for handling breakpoints at
> EL2, so we should forbid kprobing these address ranges too:
> __hyp_text_start -> __hyp_text_end
> __hyp_idmap_text_start -> __hyp_idmap_text_end
>
> These can probably be guarded with is_kernel_in_hyp_mode(), if this is true then
> we are running with VHE where this code runs at the same exception level as the
> rest of the kernel, so we can probe them. (In this case you may want to add
> 'eret' to aarch64_insn_is_branch() in patch 2)
>
>
> Probing things in the kernel idmap sounds dangerous! Lets blacklist that too:
> __idmap_text_start -> __idmap_text_end
>

I've made these changes.  I noticed there's no include file definitions 
for these symbols so I've added local extern declarations in 
arch_within_kprobe_blacklist().

Thanks,
-dl




From dave.long at linaro.org  Thu May 26 08:40:37 2016
From: dave.long at linaro.org (David Long)
Date: Thu, 26 May 2016 11:40:37 -0400
Subject: [PATCH v12 05/10] arm64: Kprobes with single stepping support
In-Reply-To: <20160517085807.GA842@sha-win-210.asiapac.arm.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-6-git-send-email-dave.long@linaro.org>
 <20160517085807.GA842@sha-win-210.asiapac.arm.com>
Message-ID: <574718F5.2000308@linaro.org>

On 05/17/2016 04:58 AM, Huang Shijie wrote:
> On Wed, Apr 27, 2016 at 02:53:00PM -0400, David Long wrote:
>> +
>> +/*
>> + * Interrupts need to be disabled before single-step mode is set, and not
>> + * reenabled until after single-step mode ends.
>> + * Without disabling interrupt on local CPU, there is a chance of
>> + * interrupt occurrence in the period of exception return and  start of
>> + * out-of-line single-step, that result in wrongly single stepping
>> + * into the interrupt handler.
>> + */
>> +static void __kprobes kprobes_save_local_irqflag(struct pt_regs *regs)
>> +{
>> +     struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
>
> Why not add a parameter for this function to save the @kcb?
>
>> +
>> +     kcb->saved_irqflag = regs->pstate;
>> +     regs->pstate |= PSR_I_BIT;
>> +}
>> +
>> +static void __kprobes kprobes_restore_local_irqflag(struct pt_regs *regs)
>> +{
>> +     struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
> ditto.
>
>> +
>> +     if (kcb->saved_irqflag & PSR_I_BIT)
>> +             regs->pstate |= PSR_I_BIT;
>> +     else
>> +             regs->pstate &= ~PSR_I_BIT;
>> +}
>> +
>> +static void __kprobes
>> +set_ss_context(struct kprobe_ctlblk *kcb, unsigned long addr)
>> +{
>> +     kcb->ss_ctx.ss_pending = true;
>> +     kcb->ss_ctx.match_addr = addr + sizeof(kprobe_opcode_t);
>> +}
>> +
>> +static void __kprobes clear_ss_context(struct kprobe_ctlblk *kcb)
>> +{
>> +     kcb->ss_ctx.ss_pending = false;
>> +     kcb->ss_ctx.match_addr = 0;
>> +}
>> +
>> +static void __kprobes setup_singlestep(struct kprobe *p,
>> +                                    struct pt_regs *regs,
>> +                                    struct kprobe_ctlblk *kcb, int reenter)
>> +{
>> +     unsigned long slot;
>> +
>> +     if (reenter) {
>> +             save_previous_kprobe(kcb);
>> +             set_current_kprobe(p);
>> +             kcb->kprobe_status = KPROBE_REENTER;
>> +     } else {
>> +             kcb->kprobe_status = KPROBE_HIT_SS;
>> +     }
>> +
>> +     if (p->ainsn.insn) {
>> +             /* prepare for single stepping */
>> +             slot = (unsigned long)p->ainsn.insn;
>> +
>> +             set_ss_context(kcb, slot);      /* mark pending ss */
>> +
>> +             if (kcb->kprobe_status == KPROBE_REENTER)
>> +                     spsr_set_debug_flag(regs, 0);
>> +
>> +             /* IRQs and single stepping do not mix well. */
>> +             kprobes_save_local_irqflag(regs);
>> +             kernel_enable_single_step(regs);
>> +             instruction_pointer(regs) = slot;
>> +     } else  {
>> +             BUG();
>> +     }
>> +}
>> +
>> +static int __kprobes reenter_kprobe(struct kprobe *p,
>> +                                 struct pt_regs *regs,
>> +                                 struct kprobe_ctlblk *kcb)
>> +{
>> +     switch (kcb->kprobe_status) {
>> +     case KPROBE_HIT_SSDONE:
>> +     case KPROBE_HIT_ACTIVE:
>> +             kprobes_inc_nmissed_count(p);
>> +             setup_singlestep(p, regs, kcb, 1);
>> +             break;
>> +     case KPROBE_HIT_SS:
>> +     case KPROBE_REENTER:
>> +             pr_warn("Unrecoverable kprobe detected at %p.\n", p->addr);
>> +             dump_kprobe(p);
>> +             BUG();
>> +             break;
>> +     default:
>> +             WARN_ON(1);
>> +             return 0;
>> +     }
>> +
>> +     return 1;
>> +}
>> +
>> +static void __kprobes
>> +post_kprobe_handler(struct kprobe_ctlblk *kcb, struct pt_regs *regs)
>> +{
>> +     struct kprobe *cur = kprobe_running();
>> +
>> +     if (!cur)
>> +             return;
>> +
>> +     /* return addr restore if non-branching insn */
>> +     if (cur->ainsn.restore.type == RESTORE_PC) {
>> +             instruction_pointer(regs) = cur->ainsn.restore.addr;
>> +             if (!instruction_pointer(regs))
>> +                     BUG();
>> +     }
>> +
>> +     /* restore back original saved kprobe variables and continue */
>> +     if (kcb->kprobe_status == KPROBE_REENTER) {
>> +             restore_previous_kprobe(kcb);
>> +             return;
>> +     }
>> +     /* call post handler */
>> +     kcb->kprobe_status = KPROBE_HIT_SSDONE;
>> +     if (cur->post_handler)  {
>> +             /* post_handler can hit breakpoint and single step
>> +              * again, so we enable D-flag for recursive exception.
>> +              */
>> +             cur->post_handler(cur, regs, 0);
>> +     }
>> +
>> +     reset_current_kprobe();
>> +}
>> +
>> +int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
>> +{
>> +     struct kprobe *cur = kprobe_running();
>> +     struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
>> +
>> +     switch (kcb->kprobe_status) {
>> +     case KPROBE_HIT_SS:
>> +     case KPROBE_REENTER:
>> +             /*
>> +              * We are here because the instruction being single
>> +              * stepped caused a page fault. We reset the current
>> +              * kprobe and the ip points back to the probe address
>> +              * and allow the page fault handler to continue as a
>> +              * normal page fault.
>> +              */
>> +             instruction_pointer(regs) = (unsigned long)cur->addr;
>> +             if (!instruction_pointer(regs))
>> +                     BUG();
>> +             if (kcb->kprobe_status == KPROBE_REENTER)
>> +                     restore_previous_kprobe(kcb);
>> +             else
>> +                     reset_current_kprobe();
>> +
>> +             break;
>> +     case KPROBE_HIT_ACTIVE:
>> +     case KPROBE_HIT_SSDONE:
>> +             /*
>> +              * We increment the nmissed count for accounting,
>> +              * we can also use npre/npostfault count for accounting
>> +              * these specific fault cases.
>> +              */
>> +             kprobes_inc_nmissed_count(cur);
>> +
>> +             /*
>> +              * We come here because instructions in the pre/post
>> +              * handler caused the page_fault, this could happen
>> +              * if handler tries to access user space by
>> +              * copy_from_user(), get_user() etc. Let the
>> +              * user-specified handler try to fix it first.
>> +              */
>> +             if (cur->fault_handler && cur->fault_handler(cur, regs, fsr))
>> +                     return 1;
>> +
>> +             /*
>> +              * In case the user-specified fault handler returned
>> +              * zero, try to fix up.
>> +              */
>> +             if (fixup_exception(regs))
>> +                     return 1;
>> +     }
>> +     return 0;
>> +}
>> +
>> +int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
>> +                                    unsigned long val, void *data)
>> +{
>> +     return NOTIFY_DONE;
>> +}
>> +
>> +static void __kprobes kprobe_handler(struct pt_regs *regs)
>> +{
>> +     struct kprobe *p, *cur_kprobe;
>> +     struct kprobe_ctlblk *kcb;
>> +     unsigned long addr = instruction_pointer(regs);
>> +
>> +     kcb = get_kprobe_ctlblk();
>> +     cur_kprobe = kprobe_running();
>> +
>> +     p = get_kprobe((kprobe_opcode_t *) addr);
>> +
>> +     if (p) {
>> +             if (cur_kprobe) {
>> +                     if (reenter_kprobe(p, regs, kcb))
>> +                             return;
>> +             } else {
>> +                     /* Probe hit */
>> +                     set_current_kprobe(p);
>> +                     kcb->kprobe_status = KPROBE_HIT_ACTIVE;
>> +
>> +                     /*
>> +                      * If we have no pre-handler or it returned 0, we
>> +                      * continue with normal processing.  If we have a
>> +                      * pre-handler and it returned non-zero, it prepped
>> +                      * for calling the break_handler below on re-entry,
>> +                      * so get out doing nothing more here.
>> +                      *
>> +                      * pre_handler can hit a breakpoint and can step thru
>> +                      * before return, keep PSTATE D-flag enabled until
>> +                      * pre_handler return back.
>> +                      */
>> +                     if (!p->pre_handler || !p->pre_handler(p, regs)) {
>> +                             kcb->kprobe_status = KPROBE_HIT_SS;
> The above line is duplicated.
> You will set KPROBE_HIT_SS in the setup_singlestep.
>
>> +                             setup_singlestep(p, regs, kcb, 0);
>> +                             return;
>> +                     }
>> +             }
>> +     } else if ((le32_to_cpu(*(kprobe_opcode_t *) addr) ==
>> +         BRK64_OPCODE_KPROBES) && cur_kprobe) {
>> +             /* We probably hit a jprobe.  Call its break handler. */
>> +             if (cur_kprobe->break_handler  &&
>> +                  cur_kprobe->break_handler(cur_kprobe, regs)) {
>> +                     kcb->kprobe_status = KPROBE_HIT_SS;
> ditto
>> +                     setup_singlestep(cur_kprobe, regs, kcb, 0);
>> +                     return;
>> +             }
>> +     }
>> +     /*
>> +      * The breakpoint instruction was removed right
>> +      * after we hit it.  Another cpu has removed
>> +      * either a probepoint or a debugger breakpoint
>> +      * at this address.  In either case, no further
>> +      * handling of this interrupt is appropriate.
>> +      * Return back to original instruction, and continue.
>> +      */
>> +}
> thanks
> Huang Shijie
> IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
>


I've made the above changes for the next version of this patch.

Thanks,
-dl



From austinwc at codeaurora.org  Thu May 26 08:42:46 2016
From: austinwc at codeaurora.org (Christ, Austin)
Date: Thu, 26 May 2016 09:42:46 -0600
Subject: [PATCH v3 2/2] i2c: qup: support SMBus block read
In-Reply-To: <CAA7nrtgAh6EDJO_qTgMawE=tpZe6F_Ae1G0OhuUME0QF4W5AJA@mail.gmail.com>
References: <1463694268-9473-1-git-send-email-austinwc@codeaurora.org>
 <1463694268-9473-2-git-send-email-austinwc@codeaurora.org>
 <CAA7nrtgAh6EDJO_qTgMawE=tpZe6F_Ae1G0OhuUME0QF4W5AJA@mail.gmail.com>
Message-ID: <a658f005-4a1d-0ce8-1e75-7f4bab9c1abc@codeaurora.org>

Hello,


On 5/25/2016 3:31 AM, rajeev kumar wrote:
> On Fri, May 20, 2016 at 3:14 AM, Austin Christ <austinwc at codeaurora.org> wrote:
>> From: Naveen Kaje <nkaje at codeaurora.org>
>>
>> I2C QUP driver relies on SMBus emulation support from the framework.
>> To handle SMBus block reads, the driver should check I2C_M_RECV_LEN
>> flag and should read the first byte received as the message length.
>>
>> The driver configures the QUP hardware to read one byte. Once the
>> message length is known from this byte, the QUP hardware is configured
>> to read the rest.
>>
>> Signed-off-by: Naveen Kaje <nkaje at codeaurora.org>
>> Signed-off-by: Austin Christ <austinwc at codeaurora.org>
>> ---
>>   drivers/i2c/busses/i2c-qup.c | 68 ++++++++++++++++++++++++++++++++++++++++++--
>>   1 file changed, 65 insertions(+), 3 deletions(-)
>>
>> Changes:
>> - v3:
>>   - clean up redundant checks
>>   - use constant instead of variable for smbus length field
>> - v2:
>>   - rework the smbus block read and break into separate function
>>
>> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
>> index ea6ca5f..9fbed83 100644
>> --- a/drivers/i2c/busses/i2c-qup.c
>> +++ b/drivers/i2c/busses/i2c-qup.c
>> @@ -517,6 +517,33 @@ static int qup_i2c_get_data_len(struct qup_i2c_dev *qup)
>>          return data_len;
>>   }
>>
>> +static bool qup_i2c_check_msg_len(struct i2c_msg *msg)
>> +{
>> +       return ((msg->flags & I2C_M_RD) && (msg->flags & I2C_M_RECV_LEN));
>> +}
>> +
>> +static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev *qup,
>> +                       struct i2c_msg *msg)
>> +{
>> +       int len = 0;
>> +
>> +       if (msg->len > 1) {
>> +               tags[len++] = QUP_TAG_V2_DATARD_STOP;
>> +               tags[len++] = qup_i2c_get_data_len(qup) - 1;
>> +       } else {
>> +               tags[len++] = QUP_TAG_V2_START;
>> +               tags[len++] = addr & 0xff;
>> +
>> +               if (msg->flags & I2C_M_TEN)
>> +                       tags[len++] = addr >> 8;
>> +
>> +               tags[len++] = QUP_TAG_V2_DATARD;
>> +               /* Read 1 byte indicating the length of the SMBus message */
>> +               tags[len++] = 1;
>> +       }
>> +       return len;
>> +}
>> +
>>   static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
>>                              struct i2c_msg *msg,  int is_dma)
>>   {
>> @@ -526,6 +553,10 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
>>
>>          int last = (qup->blk.pos == (qup->blk.count - 1)) && (qup->is_last);
>>
>> +       /* Handle tags for SMBus block read */
>> +       if (qup_i2c_check_msg_len(msg))
>> +               return qup_i2c_set_tags_smb(addr, tags, qup, msg);
>> +
>>          if (qup->blk.pos == 0) {
>>                  tags[len++] = QUP_TAG_V2_START;
>>                  tags[len++] = addr & 0xff;
>> @@ -1065,9 +1096,17 @@ static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
>>                                  struct i2c_msg *msg)
>>   {
>>          u32 val;
>> -       int idx, pos = 0, ret = 0, total;
>> +       int idx, pos = 0, ret = 0, total, msg_offset = 0;
>>
>> +       /*
>> +        * If the message length is already read in
>> +        * the first byte of the buffer, account for
>> +        * that by setting the offset
>> +        */
>> +       if (qup_i2c_check_msg_len(msg) && (msg->len > 1))
>> +               msg_offset = 1;
>>          total = qup_i2c_get_data_len(qup);
>> +       total -= msg_offset;
>>
>>          /* 2 extra bytes for read tags */
>>          while (pos < (total + 2)) {
>> @@ -1087,8 +1126,8 @@ static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
>>
>>                          if (pos >= (total + 2))
>>                                  goto out;
>> -
>> -                       msg->buf[qup->pos++] = val & 0xff;
>> +                       msg->buf[qup->pos + msg_offset] = val & 0xff;
>> +                       qup->pos++;
>>                  }
>>          }
>>
>> @@ -1128,6 +1167,24 @@ static int qup_i2c_read_one_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
>>                          goto err;
>>
>>                  qup->blk.pos++;
>> +
>> +               /* Handle SMBus block read length */
>> +               if (qup_i2c_check_msg_len(msg) && (msg->len == 1)) {
>> +                       if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
>> +                               ret = -EPROTO;
>> +                               goto err;
>> +                       }
>> +                       msg->len += msg->buf[0];
>> +                       qup->pos = 0;
>> +                       qup_i2c_set_read_mode_v2(qup, msg->len);
>> +                       ret = qup_i2c_issue_xfer_v2(qup, msg);
>> +                       if (ret)
>> +                               goto err;
>> +                       ret = qup_i2c_wait_for_complete(qup, msg);
>> +                       if (ret)
>> +                               goto err;
>> +                       qup_i2c_set_blk_data(qup, msg);
>> +               }
>>          } while (qup->blk.pos < qup->blk.count);
>>
>>   err:
>> @@ -1210,6 +1267,11 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
>>                          goto out;
>>                  }
>>
>> +               if (qup_i2c_check_msg_len(&msgs[idx])) {
>> +                       ret = -EOPNOTSUPP;
> Could you please rethink on this return value ? It should not be "EOPNOTSUPP"
>
> ~Rajeev

This will be replaced with "EINVAL" in v4 patches.
>
>> +                       goto out;
>> +               }
>> +
>>                  if (msgs[idx].flags & I2C_M_RD)
>>                          ret = qup_i2c_read_one(qup, &msgs[idx]);
>>                  else
>> --
>> Qualcomm Innovation Center, Inc.
>> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
>> a Linux Foundation Collaborative Project.
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Thanks,
Austin


From labath at google.com  Thu May 26 09:04:46 2016
From: labath at google.com (Pavel Labath)
Date: Thu, 26 May 2016 17:04:46 +0100
Subject: Support for unaligned watchpoints in arm/arm64
Message-ID: <CAJt8pk8FBbTVMMM45SaEs86MZOp0o6xChAsMT1sO+_Xy-GENyw@mail.gmail.com>

Hello all,

I've been wondering if there are any plans about adding support for
unaligned watchpoints to the kernel. It seems quite a shame that
applications are not able not use them, even though the hardware
should support that feature.

I've filed a feature request at
<https://bugzilla.kernel.org/show_bug.cgi?id=117621> with a bit more
details about the issue.

cheers,
pl


From gpkulkarni at gmail.com  Thu May 26 09:22:31 2016
From: gpkulkarni at gmail.com (Ganapatrao Kulkarni)
Date: Thu, 26 May 2016 09:22:31 -0700
Subject: [PATCH 3/3] arm64/numa: fix type info
In-Reply-To: <1464230639-9852-3-git-send-email-thunder.leizhen@huawei.com>
References: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
 <1464230639-9852-3-git-send-email-thunder.leizhen@huawei.com>
Message-ID: <CAFpQJXWih2V9Ki-vkL+cDni=VoWL0nA-fx5B5XtfNxFsoUso-g@mail.gmail.com>

On Wed, May 25, 2016 at 7:43 PM, Zhen Lei <thunder.leizhen at huawei.com> wrote:
> numa_init(of_numa_init) may returned error because of numa configuration
> error. So "No NUMA configuration found" is inaccurate. In fact, specific
> configuration error information can be immediately printed by the
> testing branch. So "No NUMA..." only needs to be printed when numa_off.
>
> Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
> ---
>  arch/arm64/mm/numa.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
> index 98dc104..9937cc1 100644
> --- a/arch/arm64/mm/numa.c
> +++ b/arch/arm64/mm/numa.c
> @@ -362,7 +362,8 @@ static int __init dummy_numa_init(void)
>         int ret;
>         struct memblock_region *mblk;
>
> -       pr_info("%s\n", "No NUMA configuration found");
> +       if (numa_off)

IIRC, it should be
if (!numa_off)
we want to print this message when we failed to find proper numa configuration.
when numa_off is set, we will not look for any numa configuration.

> +               pr_info("%s\n", "No NUMA configuration found");
>         pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
>                0LLU, PFN_PHYS(max_pfn) - 1);
>
> --
> 2.5.0

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


From paulmck at linux.vnet.ibm.com  Thu May 26 09:26:06 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Thu, 26 May 2016 09:26:06 -0700
Subject: [GIT PULL arm] Use _rcuidle tracepoints to allow tracing from idle
Message-ID: <20160526162606.GA20023@linux.vnet.ibm.com>

Hello, Ingo,

This series changes a number of event tracepoints to their _rcuidle() form
to allow use from idle without lockdep-RCU complaints, a straightforward
modification that has been successfully applied many times.  These splats
were found in testing by Guenter Roeck and Tony Lindgren, who have
both successfully tested the full series.  Tony asked that I carry these
in -rcu:

	http://lkml.kernel.org/g/20160426213630.GV5995 at atomide.com

These have been posted to LKML, CCing relevant maintainers, who have
not objected to the proposed changes:

	http://lkml.kernel.org/g/20160516184844.GA20144 at linux.vnet.ibm.com

These maintainers are also CCed on this pull request.

They have also been subjected to 0day Test Robot and -next testing.

							Thanx, Paul



From paulmck at linux.vnet.ibm.com  Thu May 26 09:27:27 2016
From: paulmck at linux.vnet.ibm.com (Paul E. McKenney)
Date: Thu, 26 May 2016 09:27:27 -0700
Subject: [GIT PULL arm] Use _rcuidle tracepoints to allow tracing from idle
In-Reply-To: <20160526162606.GA20023@linux.vnet.ibm.com>
References: <20160526162606.GA20023@linux.vnet.ibm.com>
Message-ID: <20160526162727.GA21784@linux.vnet.ibm.com>

On Thu, May 26, 2016 at 09:26:06AM -0700, Paul E. McKenney wrote:
> Hello, Ingo,
> 
> This series changes a number of event tracepoints to their _rcuidle() form
> to allow use from idle without lockdep-RCU complaints, a straightforward
> modification that has been successfully applied many times.  These splats
> were found in testing by Guenter Roeck and Tony Lindgren, who have
> both successfully tested the full series.  Tony asked that I carry these
> in -rcu:
> 
> 	http://lkml.kernel.org/g/20160426213630.GV5995 at atomide.com
> 
> These have been posted to LKML, CCing relevant maintainers, who have
> not objected to the proposed changes:
> 
> 	http://lkml.kernel.org/g/20160516184844.GA20144 at linux.vnet.ibm.com
> 
> These maintainers are also CCed on this pull request.
> 
> They have also been subjected to 0day Test Robot and -next testing.

And this time actually including the pull request...  :-/

							Thanx, Paul

These changes are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git for-mingo

for you to fetch changes up to e7c38dda94b23965a3eb46ef4656bb8cb921933d:

  arm: Use _rcuidle suffix to allow clk_core_enable() to used from idle (2016-05-18 11:55:29 -0700)

----------------------------------------------------------------
Paul E. McKenney (6):
      arm: Use _rcuidle tracepoint to allow use from idle
      arm: Use _rcuidle for suspend/resume tracepoints
      arm: Add _rcuidle tracepoints to allow clk_core_disable() use from idle
      arm: Add _rcuidle suffix to allow rpm_idle() use from idle
      arm: Add _rcuidle suffix to allow rpm_resume() to be called from idle
      arm: Use _rcuidle suffix to allow clk_core_enable() to used from idle

 arch/arm/kernel/smp.c             |  2 +-
 arch/arm/mach-omap2/powerdomain.c |  9 +++++----
 drivers/base/power/runtime.c      | 14 +++++++-------
 drivers/clk/clk.c                 |  8 ++++----
 4 files changed, 17 insertions(+), 16 deletions(-)



From sudeep.holla at arm.com  Thu May 26 09:29:04 2016
From: sudeep.holla at arm.com (Sudeep Holla)
Date: Thu, 26 May 2016 17:29:04 +0100
Subject: [RFC PATCH 0/2] scpi: Add SCPI framework to handle vendors
 variants
In-Reply-To: <1464255491-18503-1-git-send-email-narmstrong@baylibre.com>
References: <1464255491-18503-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <57472450.4000709@arm.com>

Hi Neil,

On 26/05/16 10:38, Neil Armstrong wrote:
> Since the current SCPI implementation, based on [0]:
> - is (at leat) JUNO specific

Agreed.

> - does not specify a strong "standard"

Not exactly, it's extensible. Refer section 3.2.2. Get SCP capability
Extended Set Enabled bit.

> - does not specify a strong MHU interface specification
>

Not really required, any mailbox must do.

> SoC vendors could implement a variant with slight changes in message
> indexes,

I assume you mean command index here

> new messages types,

Also fine with extended command set.

> different messages data format or

you mean the header or payload ? If they don't follow the header, then
how can be group them as same protocol ?

> different MHU communication scheme.

Not a problem as I mentioned above.

>
> To keep the spirit of the SCPI interface, add a thin "register" layer to get
> the ops from the parent node and switch the drivers using the ops to use
> the new of_scpi_ops_get() call.
>

All I can see is that you share the code to register such drivers which
is hardly anything. It's hard to say all drivers use same protocol or
interface after this change. I may be missing to see something here so
it would be easy to appreciate/review this change with one user of this.

My idea of extending this driver if vendor implements extensions based
on SCPI specification is something like below:

-- 
Regards,
Sudeep

-->8

diff --git i/drivers/firmware/arm_scpi.c w/drivers/firmware/arm_scpi.c
index 7e3e595c9f30..7e46aa103690 100644
--- i/drivers/firmware/arm_scpi.c
+++ w/drivers/firmware/arm_scpi.c
@@ -46,6 +46,8 @@

  #define CMD_ID_SHIFT		0
  #define CMD_ID_MASK		0x7f
+#define CMD_SET_SHIFT		7
+#define CMD_SET_MASK		0x1
  #define CMD_TOKEN_ID_SHIFT	8
  #define CMD_TOKEN_ID_MASK	0xff
  #define CMD_DATA_SIZE_SHIFT	16
@@ -53,6 +55,10 @@
  #define PACK_SCPI_CMD(cmd_id, tx_sz)			\
  	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |	\
  	(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
+#define PACK_EXT_SCPI_CMD(cmd_id, tx_sz)		\
+	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |	\
+	(CMD_SET_MASK << CMD_SET_SHIFT) |	\
+	(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
  #define ADD_SCPI_TOKEN(cmd, token)			\
  	((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT))

@@ -132,6 +138,9 @@ enum scpi_std_cmd {
  	SCPI_CMD_COUNT
  };

+enum scpi_vendor_ext_cmd {
+};
+
  struct scpi_xfer {
  	u32 slot; /* has to be first element */
  	u32 cmd;
@@ -165,6 +174,7 @@ struct scpi_drvinfo {
  	struct scpi_ops *scpi_ops;
  	struct scpi_chan *channels;
  	struct scpi_dvfs_info *dvfs[MAX_DVFS_DOMAINS];
+	void *scpi_ext_ops;
  };

  /*
@@ -343,8 +353,8 @@ static void put_scpi_xfer(struct scpi_xfer *t, 
struct scpi_chan *ch)
  	mutex_unlock(&ch->xfers_lock);
  }

-static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
-			     void *rx_buf, unsigned int rx_len)
+static int __scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
+			       void *rx_buf, unsigned int rx_len, bool extn)
  {
  	int ret;
  	u8 chan;
@@ -359,7 +369,8 @@ static int scpi_send_message(u8 cmd, void *tx_buf, 
unsigned int tx_len,
  		return -ENOMEM;

  	msg->slot = BIT(SCPI_SLOT);
-	msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+	msg->cmd = extn ? PACK_EXT_SCPI_CMD(cmd, tx_len) :
+			  PACK_SCPI_CMD(cmd, tx_len);
  	msg->tx_buf = tx_buf;
  	msg->tx_len = tx_len;
  	msg->rx_buf = rx_buf;
@@ -384,6 +395,18 @@ static int scpi_send_message(u8 cmd, void *tx_buf, 
unsigned int tx_len,
  	return ret > 0 ? scpi_to_linux_errno(ret) : ret;
  }

+static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
+			     void *rx_buf, unsigned int rx_len)
+{
+	return __scpi_send_message(cmd, tx_buf, tx_len, rx_buf, rx_len, false);
+}
+
+static int scpi_send_ext_message(u8 cmd, void *tx_buf, unsigned int tx_len,
+				 void *rx_buf, unsigned int rx_len)
+{
+	return __scpi_send_message(cmd, tx_buf, tx_len, rx_buf, rx_len, true);
+}
+
  static u32 scpi_get_version(void)
  {
  	return scpi_info->protocol_version;
@@ -574,6 +597,29 @@ static int scpi_init_versions(struct scpi_drvinfo 
*info)
  	return ret;
  }

+static struct scpi_vendor_ext_ops scpi_vendor_ext_ops = {
+};
+
+void *get_scpi_ext_ops(void)
+{
+	return scpi_info ? scpi_info->scpi_ext_ops : NULL;
+}
+EXPORT_SYMBOL_GPL(get_scpi_ext_ops);
+
+static const struct of_device_id scpi_extentions_of_match[] = {
+	{.compatible = "vendor,scpi", .data = &scpi_vendor_ext_ops},
+	{},
+};
+
+static void
+scpi_init_extensions(struct scpi_drvinfo *info, struct device_node *np)
+{
+	const struct of_device_id *of_id;
+
+	if (np && (of_id = of_match_node(scpi_extentions_of_match, np)))
+		info->scpi_ext_ops = (void *)of_id->data;
+}
+
  static ssize_t protocol_version_show(struct device *dev,
  				     struct device_attribute *attr, char *buf)
  {
@@ -745,6 +791,8 @@ static int scpi_probe(struct platform_device *pdev)
  		  FW_REV_PATCH(scpi_info->firmware_version));
  	scpi_info->scpi_ops = &scpi_ops;

+	scpi_init_extensions(scpi_info, np);
+
  	ret = sysfs_create_groups(&dev->kobj, versions_groups);
  	if (ret)
  		dev_err(dev, "unable to create sysfs version group\n");
diff --git i/include/linux/scpi_protocol.h w/include/linux/scpi_protocol.h
index 35de50a65665..052f6aa1ae4b 100644
--- i/include/linux/scpi_protocol.h
+++ w/include/linux/scpi_protocol.h
@@ -72,8 +72,13 @@ struct scpi_ops {
  	int (*sensor_get_value)(u16, u64 *);
  };

+struct scpi_vendor_ext_ops {
+};
+
  #if IS_REACHABLE(CONFIG_ARM_SCPI_PROTOCOL)
  struct scpi_ops *get_scpi_ops(void);
+void *get_scpi_ext_ops(void);
  #else
  static inline struct scpi_ops *get_scpi_ops(void) { return NULL; }
+static inline void *get_scpi_ext_ops(void) { return NULL; }
  #endif


From swarren at wwwdotorg.org  Thu May 26 09:29:12 2016
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Thu, 26 May 2016 10:29:12 -0600
Subject: [PATCH] arm64: tegra: Fix CPU compatible string for Tegra132
In-Reply-To: <5746C1F1.6070703@nvidia.com>
References: <20160523074221.7135-1-josephl@nvidia.com>
 <574509E7.4030208@nvidia.com> <5745C7E4.2050908@wwwdotorg.org>
 <5746C1F1.6070703@nvidia.com>
Message-ID: <57472458.1010802@wwwdotorg.org>

On 05/26/2016 03:29 AM, Joseph Lo wrote:
> On 05/25/2016 11:42 PM, Stephen Warren wrote:
>> On 05/24/2016 08:11 PM, Joseph Lo wrote:
>>> On 05/23/2016 03:42 PM, Joseph Lo wrote:
>>>> As per commit f634da375fc96 ("Documentation: DT bindings: add nvidia,
>>>> tegra132-denver compatible string"), fixing the CPU compatible string
>>>> for
>>>> Tegra132 to match the binding document currently.
>>>>
>>>> Signed-off-by: Joseph Lo <josephl at nvidia.com>
>>>> ---
>>>>   arch/arm64/boot/dts/nvidia/tegra132.dtsi | 4 ++--
>>>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
>>>> b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
>>>> index 2013f8916084..7b1cdc029de3 100644
>>>> --- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
>>>> +++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
>>>> @@ -964,13 +964,13 @@
>>>>
>>>>           cpu at 0 {
>>>>               device_type = "cpu";
>>>> -            compatible = "nvidia,denver", "arm,armv8";
>>>> +            compatible = "nvidia,tegra132-denver", "arm,armv8";
>>>
>>> Hi Stephen, Thierry,
>>>
>>> Should we fix this or fix the compatible string in the binding document
>>> as just "nvidia,denver" to represent all the Devner CPU revisions just
>>> like some other CPUs did? e.g. arm,cortex-a57, which represents all the
>>> A57 revisions.
>>
>> I would expect compatible to be:
>>
>> compatible = "nvidia,tegra132-denver", "nvidia,denver", "arm,armv8";
>
> Because we don't have "nvidia,denver" binding in the document, to do
> what you said, supposely I should add that first and fix the binding for
> Tegra132, right?

Yes.

>> The "nvidia,denver" entry is already present, and hence probably
>> shouldn't be removed. It can represent "Denver 1.0". We should add the
>> T132 entry to indicate the specific implementation. Admittedly right now
>> there's a 1:1 relation between SoC and Denver version. Either/both of
>> those could in theory be required to trigger specific bug-fixes/WARs.
>>
>> For later chips which have a different Denver version, I'd expect to see
>> something like:
>>
>> compatible = "nvidia,tegraNNN-denver", "nvidia,denverMMM", "arm,armv8";
>>
>> ... where NNN is the SoC version/name and MMM is the Denver version.
>> There could be extra entries in the property if the new versions are
>> backwards-compatible with old versions.
>
> Because it's 1:1 relationship, if we have new cores coming later, we
> should add both of the compatible string of SoC version and CPU core
> version in the ARM CPU binding document, is that correct?

Yes. I suspect that on some future SoCs, it won't be a 1:1 relation; 
we'll re-use a Denver version across multiple SoCs, just like we do with 
some ARM CPU models, but we'll see.


From joe at perches.com  Thu May 26 09:35:03 2016
From: joe at perches.com (Joe Perches)
Date: Thu, 26 May 2016 09:35:03 -0700
Subject: [PATCH 3/3] arm64/numa: fix type info
In-Reply-To: <CAFpQJXWih2V9Ki-vkL+cDni=VoWL0nA-fx5B5XtfNxFsoUso-g@mail.gmail.com>
References: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
 <1464230639-9852-3-git-send-email-thunder.leizhen@huawei.com>
 <CAFpQJXWih2V9Ki-vkL+cDni=VoWL0nA-fx5B5XtfNxFsoUso-g@mail.gmail.com>
Message-ID: <1464280503.16344.40.camel@perches.com>

On Thu, 2016-05-26 at 09:22 -0700, Ganapatrao Kulkarni wrote:
> On Wed, May 25, 2016 at 7:43 PM, Zhen Lei <thunder.leizhen at huawei.com> wrote:
> > numa_init(of_numa_init) may returned error because of numa configuration
> > error. So "No NUMA configuration found" is inaccurate. In fact, specific
> > configuration error information can be immediately printed by the
> > testing branch. So "No NUMA..." only needs to be printed when numa_off.
[]
> > diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
[]
> > @@ -362,7 +362,8 @@ static int __init dummy_numa_init(void)
> > ????????int ret;
> > ????????struct memblock_region *mblk;
> > 
> > -???????pr_info("%s\n", "No NUMA configuration found");
> > +???????if (numa_off)
> IIRC, it should be
> if (!numa_off)
> we want to print this message when we failed to find proper numa configuration.
> when numa_off is set, we will not look for any numa configuration.
> 
> > 
> > +???????????????pr_info("%s\n", "No NUMA configuration found");

trivia:

Using printk("%s\n", "string") just makes the object code larger
for no particular benefit.

	pr_info("No NUMA configuration found\n");

would be smaller, faster and more intelligible for humans too.

Maybe something like this:
---
?arch/arm64/mm/numa.c | 41 ++++++++++++++++++++---------------------
?1 file changed, 20 insertions(+), 21 deletions(-)

diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
index 98dc104..2042452 100644
--- a/arch/arm64/mm/numa.c
+++ b/arch/arm64/mm/numa.c
@@ -17,6 +17,8 @@
? * along with this program.??If not, see <http://www.gnu.org/licenses/>.
? */
?
+#define pr_fmt(fmt) "NUMA: " fmt
+
?#include <linux/bootmem.h>
?#include <linux/memblock.h>
?#include <linux/module.h>
@@ -36,7 +38,7 @@ static __init int numa_parse_early_param(char *opt)
?	if (!opt)
?		return -EINVAL;
?	if (!strncmp(opt, "off", 3)) {
-		pr_info("%s\n", "NUMA turned off");
+		pr_info("NUMA turned off\n");
?		numa_off = 1;
?	}
?	return 0;
@@ -107,7 +109,7 @@ static void __init setup_node_to_cpumask_map(void)
?		set_cpu_numa_node(cpu, NUMA_NO_NODE);
?
?	/* cpumask_of_node() will now work */
-	pr_debug("NUMA: Node to cpumask map for %d nodes\n", nr_node_ids);
+	pr_debug("Node to cpumask map for %d nodes\n", nr_node_ids);
?}
?
?/*
@@ -142,14 +144,14 @@ int __init numa_add_memblk(int nid, u64 start, u64 size)
?
?	ret = memblock_set_node(start, size, &memblock.memory, nid);
?	if (ret < 0) {
-		pr_err("NUMA: memblock [0x%llx - 0x%llx] failed to add on node %d\n",
-			start, (start + size - 1), nid);
+		pr_err("memblock [0x%llx - 0x%llx] failed to add on node %d\n",
+		???????start, (start + size - 1), nid);
?		return ret;
?	}
?
?	node_set(nid, numa_nodes_parsed);
-	pr_info("NUMA: Adding memblock [0x%llx - 0x%llx] on node %d\n",
-			start, (start + size - 1), nid);
+	pr_info("Adding memblock [0x%llx - 0x%llx] on node %d\n",
+		start, (start + size - 1), nid);
?	return ret;
?}
?
@@ -163,19 +165,18 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
?	void *nd;
?	int tnid;
?
-	pr_info("NUMA: Initmem setup node %d [mem %#010Lx-%#010Lx]\n",
-			nid, start_pfn << PAGE_SHIFT,
-			(end_pfn << PAGE_SHIFT) - 1);
+	pr_info("Initmem setup node %d [mem %#010Lx-%#010Lx]\n",
+		nid, start_pfn << PAGE_SHIFT, (end_pfn << PAGE_SHIFT) - 1);
?
?	nd_pa = memblock_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
?	nd = __va(nd_pa);
?
?	/* report and initialize */
-	pr_info("NUMA: NODE_DATA [mem %#010Lx-%#010Lx]\n",
+	pr_info("NODE_DATA [mem %#010Lx-%#010Lx]\n",
?		nd_pa, nd_pa + nd_size - 1);
?	tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
?	if (tnid != nid)
-		pr_info("NUMA: NODE_DATA(%d) on node %d\n", nid, tnid);
+		pr_info("NODE_DATA(%d) on node %d\n", nid, tnid);
?
?	node_data[nid] = nd;
?	memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
@@ -232,8 +233,7 @@ static int __init numa_alloc_distance(void)
?			numa_distance[i * numa_distance_cnt + j] = i == j ?
?				LOCAL_DISTANCE : REMOTE_DISTANCE;
?
-	pr_debug("NUMA: Initialized distance table, cnt=%d\n",
-			numa_distance_cnt);
+	pr_debug("Initialized distance table, cnt=%d\n", numa_distance_cnt);
?
?	return 0;
?}
@@ -254,20 +254,20 @@ static int __init numa_alloc_distance(void)
?void __init numa_set_distance(int from, int to, int distance)
?{
?	if (!numa_distance) {
-		pr_warn_once("NUMA: Warning: distance table not allocated yet\n");
+		pr_warn_once("Warning: distance table not allocated yet\n");
?		return;
?	}
?
?	if (from >= numa_distance_cnt || to >= numa_distance_cnt ||
?			from < 0 || to < 0) {
-		pr_warn_once("NUMA: Warning: node ids are out of bound, from=%d to=%d distance=%d\n",
-			????from, to, distance);
+		pr_warn_once("Warning: node ids are out of bound, from=%d to=%d distance=%d\n",
+			?????from, to, distance);
?		return;
?	}
?
?	if ((u8)distance != distance ||
?	????(from == to && distance != LOCAL_DISTANCE)) {
-		pr_warn_once("NUMA: Warning: invalid distance parameter, from=%d to=%d distance=%d\n",
+		pr_warn_once("Warning: invalid distance parameter, from=%d to=%d distance=%d\n",
?			?????from, to, distance);
?		return;
?	}
@@ -294,7 +294,7 @@ static int __init numa_register_nodes(void)
?	/* Check that valid nid is set to memblks */
?	for_each_memblock(memory, mblk)
?		if (mblk->nid == NUMA_NO_NODE || mblk->nid >= MAX_NUMNODES) {
-			pr_warn("NUMA: Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
+			pr_warn("Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
?				mblk->nid, mblk->base,
?				mblk->base + mblk->size - 1);
?			return -EINVAL;
@@ -362,9 +362,8 @@ static int __init dummy_numa_init(void)
?	int ret;
?	struct memblock_region *mblk;
?
-	pr_info("%s\n", "No NUMA configuration found");
-	pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
-	???????0LLU, PFN_PHYS(max_pfn) - 1);
+	pr_info("No NUMA configuration found - faking a node at [mem %#018Lx-%#018Lx]\n",
+		0LLU, PFN_PHYS(max_pfn) - 1);
?
?	for_each_memblock(memory, mblk) {
?		ret = numa_add_memblk(0, mblk->base, mblk->size);


From catalin.marinas at arm.com  Thu May 26 09:36:05 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 26 May 2016 17:36:05 +0100
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <5746E203.4000906@huawei.com>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
 <20160524113727.GD25374@leverpostej> <574446B9.8040105@huawei.com>
 <20160524130255.GU4892@e104818-lin.cambridge.arm.com>
 <5744FDD0.8060504@huawei.com> <57451DC6.7080106@huawei.com>
 <20160525105022.GC5996@e104818-lin.cambridge.arm.com>
 <5746E203.4000906@huawei.com>
Message-ID: <20160526163604.GD7456@e104818-lin.cambridge.arm.com>

On Thu, May 26, 2016 at 07:46:11PM +0800, Leizhen (ThunderTown) wrote:
> On 2016/5/25 18:50, Catalin Marinas wrote:
> > What happens is that __sync_icache_dcache() only takes care of the first
> > time a page is mapped in user space and flushes the caches, marking it
> > as "clean" (PG_dcache_clean) afterwards. Subsequent changes to this
> 
> As my tracing, it is returned by "if (!page_mapping(page))", because
> "mmap" are anonymous pages. I commented below code lines, it works
> well.
> 	
> 	/* no flushing needed for anonymous pages */
> 	if (!page_mapping(page))
> 		return;

I think it only works by luck. As I said above, even with your
modification for anonymous pages, the first time set_pte_at() is called,
__sync_icache_dcache() would set the PG_dcache_clean bit. Subsequent
set_pte_at() calls for changing the attributes would ignore the D-cache
invalidation as the page seems clean (unless there is a call to
flush_dcache_page() but this shouldn't be done on this path). What
probably happens is that memcpy() for copying the code triggers some
write streaming mode in the CPU and the information makes its way to the
PoU. The I-cache invalidation only removes the stale instructions.

-- 
Catalin


From catalin.marinas at arm.com  Thu May 26 09:44:57 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 26 May 2016 17:44:57 +0100
Subject: [PATCH 1/1] arm64: fix flush_cache_range
In-Reply-To: <20160525172705.GD19428@n2100.arm.linux.org.uk>
References: <1464088597-8820-1-git-send-email-thunder.leizhen@huawei.com>
 <20160524113727.GD25374@leverpostej> <574446B9.8040105@huawei.com>
 <20160524151235.GA11605@leverpostej>
 <20160525152255.GH5996@e104818-lin.cambridge.arm.com>
 <20160525172705.GD19428@n2100.arm.linux.org.uk>
Message-ID: <20160526164456.GE7456@e104818-lin.cambridge.arm.com>

On Wed, May 25, 2016 at 06:27:07PM +0100, Russell King - ARM Linux wrote:
> On Wed, May 25, 2016 at 04:22:55PM +0100, Catalin Marinas wrote:
> > That's when we realised that the CoW problem no longer exists for
> > non-aliasing VIPT caches. However, the I-cache counterpart 6060e8df5178
> > has not been reverted.
> 
> I think I mostly agree, except for reverting 6060e8df5178, which I don't
> think would be correct.  That reintroduces the possibility of flushing
> the I-cache twice in that path, once for aliasing vipt dcaches, and again
> for asid tagged vivt icaches.  I'd rather have the code structured so we
> only do this once.

__sync_icache_dcache() seems to take care of AIVIVT caches as well (i.e.
it invalidates the whole I-cache) so I think we could just remove the
__flush_icache_all() from flush_cache_range().

I can't find a scenario where we still need D-cache clean+invalidate in
flush_cache_range() for aliasing VIPT. As for the I-cache,
__sync_icache_dcache() takes care of all the aliases.

-- 
Catalin


From ddaney.cavm at gmail.com  Thu May 26 10:12:44 2016
From: ddaney.cavm at gmail.com (David Daney)
Date: Thu, 26 May 2016 10:12:44 -0700
Subject: [PATCH 3/3] arm64/numa: fix type info
In-Reply-To: <1464280503.16344.40.camel@perches.com>
References: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
 <1464230639-9852-3-git-send-email-thunder.leizhen@huawei.com>
 <CAFpQJXWih2V9Ki-vkL+cDni=VoWL0nA-fx5B5XtfNxFsoUso-g@mail.gmail.com>
 <1464280503.16344.40.camel@perches.com>
Message-ID: <57472E8C.1050607@gmail.com>

The current patch to correct this problem is here:

https://lkml.org/lkml/2016/5/24/679

Since v7 of the ACPI/NUMA patches are likely going to be added to 
linux-next as soon as the current merge window ends, further 
simplifications of the informational prints should probably be rebased 
on top of it.

David Daney

On 05/26/2016 09:35 AM, Joe Perches wrote:
> On Thu, 2016-05-26 at 09:22 -0700, Ganapatrao Kulkarni wrote:
>> On Wed, May 25, 2016 at 7:43 PM, Zhen Lei <thunder.leizhen at huawei.com> wrote:
>>> numa_init(of_numa_init) may returned error because of numa configuration
>>> error. So "No NUMA configuration found" is inaccurate. In fact, specific
>>> configuration error information can be immediately printed by the
>>> testing branch. So "No NUMA..." only needs to be printed when numa_off.
> []
>>> diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
> []
>>> @@ -362,7 +362,8 @@ static int __init dummy_numa_init(void)
>>>          int ret;
>>>          struct memblock_region *mblk;
>>>
>>> -       pr_info("%s\n", "No NUMA configuration found");
>>> +       if (numa_off)
>> IIRC, it should be
>> if (!numa_off)
>> we want to print this message when we failed to find proper numa configuration.
>> when numa_off is set, we will not look for any numa configuration.
>>
>>>
>>> +               pr_info("%s\n", "No NUMA configuration found");
>
> trivia:
>
> Using printk("%s\n", "string") just makes the object code larger
> for no particular benefit.
>
> 	pr_info("No NUMA configuration found\n");
>
> would be smaller, faster and more intelligible for humans too.
>
> Maybe something like this:
> ---
>   arch/arm64/mm/numa.c | 41 ++++++++++++++++++++---------------------
>   1 file changed, 20 insertions(+), 21 deletions(-)
>
> diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
> index 98dc104..2042452 100644
> --- a/arch/arm64/mm/numa.c
> +++ b/arch/arm64/mm/numa.c
> @@ -17,6 +17,8 @@
>    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>    */
>
> +#define pr_fmt(fmt) "NUMA: " fmt
> +
>   #include <linux/bootmem.h>
>   #include <linux/memblock.h>
>   #include <linux/module.h>
> @@ -36,7 +38,7 @@ static __init int numa_parse_early_param(char *opt)
>   	if (!opt)
>   		return -EINVAL;
>   	if (!strncmp(opt, "off", 3)) {
> -		pr_info("%s\n", "NUMA turned off");
> +		pr_info("NUMA turned off\n");
>   		numa_off = 1;
>   	}
>   	return 0;
> @@ -107,7 +109,7 @@ static void __init setup_node_to_cpumask_map(void)
>   		set_cpu_numa_node(cpu, NUMA_NO_NODE);
>
>   	/* cpumask_of_node() will now work */
> -	pr_debug("NUMA: Node to cpumask map for %d nodes\n", nr_node_ids);
> +	pr_debug("Node to cpumask map for %d nodes\n", nr_node_ids);
>   }
>
>   /*
> @@ -142,14 +144,14 @@ int __init numa_add_memblk(int nid, u64 start, u64 size)
>
>   	ret = memblock_set_node(start, size, &memblock.memory, nid);
>   	if (ret < 0) {
> -		pr_err("NUMA: memblock [0x%llx - 0x%llx] failed to add on node %d\n",
> -			start, (start + size - 1), nid);
> +		pr_err("memblock [0x%llx - 0x%llx] failed to add on node %d\n",
> +		       start, (start + size - 1), nid);
>   		return ret;
>   	}
>
>   	node_set(nid, numa_nodes_parsed);
> -	pr_info("NUMA: Adding memblock [0x%llx - 0x%llx] on node %d\n",
> -			start, (start + size - 1), nid);
> +	pr_info("Adding memblock [0x%llx - 0x%llx] on node %d\n",
> +		start, (start + size - 1), nid);
>   	return ret;
>   }
>
> @@ -163,19 +165,18 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
>   	void *nd;
>   	int tnid;
>
> -	pr_info("NUMA: Initmem setup node %d [mem %#010Lx-%#010Lx]\n",
> -			nid, start_pfn << PAGE_SHIFT,
> -			(end_pfn << PAGE_SHIFT) - 1);
> +	pr_info("Initmem setup node %d [mem %#010Lx-%#010Lx]\n",
> +		nid, start_pfn << PAGE_SHIFT, (end_pfn << PAGE_SHIFT) - 1);
>
>   	nd_pa = memblock_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
>   	nd = __va(nd_pa);
>
>   	/* report and initialize */
> -	pr_info("NUMA: NODE_DATA [mem %#010Lx-%#010Lx]\n",
> +	pr_info("NODE_DATA [mem %#010Lx-%#010Lx]\n",
>   		nd_pa, nd_pa + nd_size - 1);
>   	tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
>   	if (tnid != nid)
> -		pr_info("NUMA: NODE_DATA(%d) on node %d\n", nid, tnid);
> +		pr_info("NODE_DATA(%d) on node %d\n", nid, tnid);
>
>   	node_data[nid] = nd;
>   	memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
> @@ -232,8 +233,7 @@ static int __init numa_alloc_distance(void)
>   			numa_distance[i * numa_distance_cnt + j] = i == j ?
>   				LOCAL_DISTANCE : REMOTE_DISTANCE;
>
> -	pr_debug("NUMA: Initialized distance table, cnt=%d\n",
> -			numa_distance_cnt);
> +	pr_debug("Initialized distance table, cnt=%d\n", numa_distance_cnt);
>
>   	return 0;
>   }
> @@ -254,20 +254,20 @@ static int __init numa_alloc_distance(void)
>   void __init numa_set_distance(int from, int to, int distance)
>   {
>   	if (!numa_distance) {
> -		pr_warn_once("NUMA: Warning: distance table not allocated yet\n");
> +		pr_warn_once("Warning: distance table not allocated yet\n");
>   		return;
>   	}
>
>   	if (from >= numa_distance_cnt || to >= numa_distance_cnt ||
>   			from < 0 || to < 0) {
> -		pr_warn_once("NUMA: Warning: node ids are out of bound, from=%d to=%d distance=%d\n",
> -			    from, to, distance);
> +		pr_warn_once("Warning: node ids are out of bound, from=%d to=%d distance=%d\n",
> +			     from, to, distance);
>   		return;
>   	}
>
>   	if ((u8)distance != distance ||
>   	    (from == to && distance != LOCAL_DISTANCE)) {
> -		pr_warn_once("NUMA: Warning: invalid distance parameter, from=%d to=%d distance=%d\n",
> +		pr_warn_once("Warning: invalid distance parameter, from=%d to=%d distance=%d\n",
>   			     from, to, distance);
>   		return;
>   	}
> @@ -294,7 +294,7 @@ static int __init numa_register_nodes(void)
>   	/* Check that valid nid is set to memblks */
>   	for_each_memblock(memory, mblk)
>   		if (mblk->nid == NUMA_NO_NODE || mblk->nid >= MAX_NUMNODES) {
> -			pr_warn("NUMA: Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
> +			pr_warn("Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
>   				mblk->nid, mblk->base,
>   				mblk->base + mblk->size - 1);
>   			return -EINVAL;
> @@ -362,9 +362,8 @@ static int __init dummy_numa_init(void)
>   	int ret;
>   	struct memblock_region *mblk;
>
> -	pr_info("%s\n", "No NUMA configuration found");
> -	pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
> -	       0LLU, PFN_PHYS(max_pfn) - 1);
> +	pr_info("No NUMA configuration found - faking a node at [mem %#018Lx-%#018Lx]\n",
> +		0LLU, PFN_PHYS(max_pfn) - 1);
>
>   	for_each_memblock(memory, mblk) {
>   		ret = numa_add_memblk(0, mblk->base, mblk->size);
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>



From vz at mleia.com  Thu May 26 10:48:57 2016
From: vz at mleia.com (Vladimir Zapolskiy)
Date: Thu, 26 May 2016 20:48:57 +0300
Subject: DT description of SRAM with power manageable banks
Message-ID: <57473709.1020108@mleia.com>

Hi DT team,

let me ask you for advice how to extend a common "mmio-sram" compatible
binding description with information about power manageable banks,
which are specific to some SRAM. My main interest is to give a better
support of NXP LPC32xx SRAM, but as far as I know it concerns other
controllers from the LPC series, and maybe some other ones.

Taking a simple visual example let's consider NXP LPC3250 SRAM, which
has four banks, three of them has independent power controls:

	0x00000 - 0x0ffff (64KiB), always on-power bank,
	0x10000 - 0x1ffff (64KiB), power manageable bank
	0x20000 - 0x2ffff (64KiB), power manageable bank
	0x30000 - 0x3ffff (64KiB), power manageable bank

All banks together form a single continuous address space, and it seems
important to have just one SRAM device and not 4, since e.g. in normal
runtime operation continuous 100KiB from the whole SRAM area are reserved
for storing MAC RX/TX buffers, it won't fit into one bank, however in
sleep mode (or when there is no users of some SRAM banks in runtime)
it is desirable to turn off unused banks, thus there should be a connection
between each power manageable bank and some power domain like this:

	sram_pd: power-controller at 110 {
		compatible = "nxp,lpc3220-pos";
		reg = <0x110 0x8>;
		#power-domain-cells = <1>;
	};

...

	sram-bank at 08010000 {
		reg = <0x08010000 0x10000>;
		power-domains = <&sram_pd 0>;
	};

...

The ordinary SRAM device node looks like

	sram at 08000000 {
		compatible = "mmio-sram";
		reg = <0x08000000 0x40000>;
	};

and I would happy to have it just like that, and actually it works
perfectly, if the problem with delicate power management is ignored.
At least it demonstrates that a generic wide compatible "mmio-sram"
suits well here.

The problem I face is in setting a proper layout of "sram@" and three
"sram-bank@" device nodes (remember 1 of 4 banks has no power control).
Unfortunately "sram-bank@" device nodes can not be children of "sram@",
because children of "mmio-sram" compatible device node play a role
of reserved areas ("partitions"), and that's not what I want. Moreover
reserved areas and power manageable banks are orthogonal, for instance
one reserved area may overlap with two power manageable banks or
vice versa.

Questions I have concerning this case:

1) would it be correct to add the second compatible like this?

	sram at 08000000 {
		compatible = "mmio-sram", "nxp,lpc3220-sram";
		reg = <0x08000000 0x40000>;
	};

Or should I add the new compatible to device nodes of each of the power
manageable banks?

2) I assume that "sram-bank@" device nodes still should be descendants
of "sram@" node, but because children with "reg" property of "mmio-sram"
compatible device node can not be used to describe power manageable banks,
what name for an umbrella device node would you suggest? Would "banks" be
good enough? Should it have its own compatible?

3) Do you think that reserved areas nodes should be placed under their
own device node with probably own compatible? So, something like it
was done recently with MTD partitions (compatible = "fixed-partitions").

Thank you in advance.
-- 
With best wishes,
Vladimir


From robh+dt at kernel.org  Thu May 26 11:30:31 2016
From: robh+dt at kernel.org (Rob Herring)
Date: Thu, 26 May 2016 13:30:31 -0500
Subject: DT description of SRAM with power manageable banks
In-Reply-To: <57473709.1020108@mleia.com>
References: <57473709.1020108@mleia.com>
Message-ID: <CAL_Jsq+R8E7UwAW+aUcmHPhgMS0D39C77kxgqwLK0_kTWHkWFw@mail.gmail.com>

On Thu, May 26, 2016 at 12:48 PM, Vladimir Zapolskiy <vz at mleia.com> wrote:
> Hi DT team,
>
> let me ask you for advice how to extend a common "mmio-sram" compatible
> binding description with information about power manageable banks,
> which are specific to some SRAM. My main interest is to give a better
> support of NXP LPC32xx SRAM, but as far as I know it concerns other
> controllers from the LPC series, and maybe some other ones.
>
> Taking a simple visual example let's consider NXP LPC3250 SRAM, which
> has four banks, three of them has independent power controls:
>
>         0x00000 - 0x0ffff (64KiB), always on-power bank,
>         0x10000 - 0x1ffff (64KiB), power manageable bank
>         0x20000 - 0x2ffff (64KiB), power manageable bank
>         0x30000 - 0x3ffff (64KiB), power manageable bank
>
> All banks together form a single continuous address space, and it seems
> important to have just one SRAM device and not 4, since e.g. in normal
> runtime operation continuous 100KiB from the whole SRAM area are reserved
> for storing MAC RX/TX buffers, it won't fit into one bank, however in
> sleep mode (or when there is no users of some SRAM banks in runtime)
> it is desirable to turn off unused banks, thus there should be a connection
> between each power manageable bank and some power domain like this:
>
>         sram_pd: power-controller at 110 {
>                 compatible = "nxp,lpc3220-pos";
>                 reg = <0x110 0x8>;
>                 #power-domain-cells = <1>;
>         };
>
> ...
>
>         sram-bank at 08010000 {
>                 reg = <0x08010000 0x10000>;
>                 power-domains = <&sram_pd 0>;
>         };
>
> ...
>
> The ordinary SRAM device node looks like
>
>         sram at 08000000 {
>                 compatible = "mmio-sram";
>                 reg = <0x08000000 0x40000>;
>         };
>
> and I would happy to have it just like that, and actually it works
> perfectly, if the problem with delicate power management is ignored.
> At least it demonstrates that a generic wide compatible "mmio-sram"
> suits well here.
>
> The problem I face is in setting a proper layout of "sram@" and three
> "sram-bank@" device nodes (remember 1 of 4 banks has no power control).
> Unfortunately "sram-bank@" device nodes can not be children of "sram@",
> because children of "mmio-sram" compatible device node play a role
> of reserved areas ("partitions"), and that's not what I want. Moreover
> reserved areas and power manageable banks are orthogonal, for instance
> one reserved area may overlap with two power manageable banks or
> vice versa.
>
> Questions I have concerning this case:
>
> 1) would it be correct to add the second compatible like this?
>
>         sram at 08000000 {
>                 compatible = "mmio-sram", "nxp,lpc3220-sram";

Yes, but reverse the order. Most specific first.

>                 reg = <0x08000000 0x40000>;

You can just add a single property like this:

power-domains = <&sram_pd 0>, <&sram_pd 1>, <&sram_pd 2>;

The knowledge of what range each PD controls is encoded in the fact
that the node is a "nxp,lpc3220-sram" and the information would stay
in your driver.

Of course, if there's a lot of variation in sizes and domains, we may
want to fully describe things in the DT.

>         };
>
> Or should I add the new compatible to device nodes of each of the power
> manageable banks?
>
> 2) I assume that "sram-bank@" device nodes still should be descendants
> of "sram@" node, but because children with "reg" property of "mmio-sram"
> compatible device node can not be used to describe power manageable banks,
> what name for an umbrella device node would you suggest? Would "banks" be
> good enough? Should it have its own compatible?

I don't think you need all this, but in general you want to have
compatible strings in each node (though there are many exceptions).

> 3) Do you think that reserved areas nodes should be placed under their
> own device node with probably own compatible? So, something like it
> was done recently with MTD partitions (compatible = "fixed-partitions").

If we did go down the path of have 2 sets of ranges, then yes.

Rob


From khilman at baylibre.com  Thu May 26 11:42:07 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Thu, 26 May 2016 11:42:07 -0700
Subject: [PATCH v2 1/4] reset: Add support for the Amlogic Meson SoC Reset
 Controller
In-Reply-To: <1464260562.4109.77.camel@pengutronix.de> (Philipp Zabel's
 message of "Thu, 26 May 2016 13:02:42 +0200")
References: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
 <1464169758-26975-2-git-send-email-narmstrong@baylibre.com>
 <m2iny1h74c.fsf@baylibre.com>
 <1464260562.4109.77.camel@pengutronix.de>
Message-ID: <m28tywhda8.fsf@baylibre.com>

Philipp Zabel <p.zabel at pengutronix.de> writes:

> Am Mittwoch, den 25.05.2016, 19:42 -0700 schrieb Kevin Hilman:
>> Neil Armstrong <narmstrong at baylibre.com> writes:
>> 
>> > This patch adds the platform driver for the Amlogic Meson SoC Reset
>> > Controller.
>> >
>> > The Meson8b and GXBB SoCs are supported.
>> >
>> > Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> 
>> Maybe a question for Philipp, but when testog this version with the
>> stmmac ethernet driver on the Amlogic boards, I noticed that ->reset was
>> never getting called.
>> 
>> Turns out, the stmmac driver only uses reset_control_assert() and
>> reset_control_deassert(), both of which return -ENOTSUPP since this
>> driver doesn't provide ->assert or ->deassert, so the driver's ->reset()
>> never gets called.
>> 
>> I haven't looked into the reset framework in detail, but if there's only
>> a ->reset hook, I kind of expected that reset_control_deassert() would
>> use that instead of returning -ENOTSUPP.
>> 
>> If not, what's the proper way of handling hardware that only supports a
>> write-only reset pulse?  Should users of reset_control_* be adapted to
>> check if ->deassert returns -ENOTSUPP and call ->reset?
>
> I initially came up with this for i.MX6, which has a reset controller
> that just like the Meson ones doesn't support manual assertion and
> deassertion of the reset line.
> My assumption then was that reset() is the default for all devices that
> just need their internal state to be reset at some point. I didn't
> expect the clock-like usage of manual deassert()/assert() for power
> management to become so common.
> So assert() and deassert() return -ENOTSUPP if the reset controller
> doesn't support manually asserting or deasserting the reset line.
>
> Of course you can argue that after a reset() pulse the reset line is
> deasserted, and if you instead interpret the API in terms of expected
> outcome, that would be similar to the state after call to deassert()
> (iff the line was asserted before).
> That would blur the line between reset() and deassert() somewhat, and in
> my opinion having a call to deassert() first doing the exact opposite
> isn't good nomenclature.
> Personally, I'd prefer if the driver could switch to only using
> 	reset_control_reset(rstc);

Then what would happen if that same driver is used on platforms that
have ->assert and ->deassert but no -reset?

The bind I'm in is that I'm using an exsting network driver
(stmicro/stmmac) which is used on a bunch of platforms and I dont' know
what all those reset controllers are actually doing, so going and
changing the driver seems problematic.

> or, if the reset line needs to stay asserted during powerdown where the
> reset controller supports it, but doesn't matter whert not, use:
> 	ret = reset_control_deassert(rstc);
> 	if (ret == -ENOTSUPP)
> 		ret = reset_control_reset(rstc);
>
> We could add a helper reset_control_deassert_or_reset() for that.

IMO, that would be a useful helper function, but I still think that
should be the default behavior of _deassert, otherwise it will still
require changing all the drivers.

Kevin



From wsa at the-dreams.de  Thu May 26 11:48:05 2016
From: wsa at the-dreams.de (Wolfram Sang)
Date: Thu, 26 May 2016 20:48:05 +0200
Subject: [PATCH V3 1/2] i2c: qup: Fix broken dma when CONFIG_DEBUG_SG is
 enabled
In-Reply-To: <1464164212-11377-2-git-send-email-sricharan@codeaurora.org>
References: <1464164212-11377-1-git-send-email-sricharan@codeaurora.org>
 <1464164212-11377-2-git-send-email-sricharan@codeaurora.org>
Message-ID: <20160526184805.GC1614@katana>


> sg_set_buf expects that the buf parameter passed in should be from
> lowmem and a valid pageframe. This is not true for pages from
> dma_alloc_coherent which can be carveouts, hence the check fails.

OK, given you mean dma_pool_alloc here, the check fails for the
pageframe because of the pool? Is my understanding correct?

> Change allocation of sg buffers from dma_coherent memory to kzalloc
> to fix the issue.

But why can you drop the coherency?

> @@ -1268,6 +1260,8 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
>  		}
>  	}
>  
> +	idx = 0;
> +

This looks like an unrelated change.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160526/fc8f1e78/attachment.sig>

From yang.shi at linaro.org  Thu May 26 11:43:51 2016
From: yang.shi at linaro.org (Yang Shi)
Date: Thu, 26 May 2016 11:43:51 -0700
Subject: [PATCH] arm64: kasan: instrument user memory access API
Message-ID: <1464288231-11304-1-git-send-email-yang.shi@linaro.org>

The upstream commit 1771c6e1a567ea0ba2cccc0a4ffe68a1419fd8ef
("x86/kasan: instrument user memory access API") added KASAN instrument to
x86 user memory access API, so added such instrument to ARM64 too.

Tested by test_kasan module.

Signed-off-by: Yang Shi <yang.shi at linaro.org>
---
 arch/arm64/include/asm/uaccess.h | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 0685d74..ec352fa 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -23,6 +23,7 @@
  */
 #include <linux/string.h>
 #include <linux/thread_info.h>
+#include <linux/kasan-checks.h>
 
 #include <asm/alternative.h>
 #include <asm/cpufeature.h>
@@ -276,6 +277,8 @@ extern unsigned long __must_check __clear_user(void __user *addr, unsigned long
 
 static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
 {
+	kasan_check_write(to, n);
+
 	if (access_ok(VERIFY_READ, from, n))
 		n = __copy_from_user(to, from, n);
 	else /* security hole - plug it */
@@ -285,6 +288,8 @@ static inline unsigned long __must_check copy_from_user(void *to, const void __u
 
 static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
 {
+	kasan_check_read(from, n);
+
 	if (access_ok(VERIFY_WRITE, to, n))
 		n = __copy_to_user(to, from, n);
 	return n;
@@ -297,8 +302,17 @@ static inline unsigned long __must_check copy_in_user(void __user *to, const voi
 	return n;
 }
 
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
+static inline unsigned long __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
+{
+	kasan_check_read(from, n);
+	return __copy_to_user(to, from, n);
+}
+
+static inline unsigned long __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
+{
+	kasan_check_write(to, n);
+	return __copy_from_user(to, from, n);
+}
 
 static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
 {
-- 
2.0.2



From hramrach at gmail.com  Thu May 26 12:25:23 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: 26 May 2016 19:25:23 -0000
Subject: [PATCH 1/5] spi: sunxi: fix transfer timeout
In-Reply-To: <cover.1464130597.git.hramrach@gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
Message-ID: <cb90b922caa6ac07c1425d726ea19709ee5284f4.1464130597.git.hramrach@gmail.com>

The trasfer timeout is fixed at 1000 ms. Reading a 4Mbyte flash over
1MHz SPI bus takes way longer than that. Calculate the timeout from the
actual time the transfer is supposed to take and multiply by 2 for good
measure.

Signed-off-by: Michal Suchanek <hramrach at gmail.com>
---

v2:
- fix build error
- use unsigned instead of int in max_t
- use tfr->speed_hz instead of sspi->max_speed_hz
---
 drivers/spi/spi-sun4i.c | 11 ++++++++++-
 drivers/spi/spi-sun6i.c | 11 ++++++++++-
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index 1ddd9e2..fe63bbd 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -173,6 +173,7 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
 {
 	struct sun4i_spi *sspi = spi_master_get_devdata(master);
 	unsigned int mclk_rate, div, timeout;
+	unsigned int start, end, tx_time;
 	unsigned int tx_len = 0;
 	int ret = 0;
 	u32 reg;
@@ -279,9 +280,17 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
 	reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
 	sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
 
+	tx_time = max_t(unsigned, tfr->len * 8 * 2 / (tfr->speed_hz / 1000),
+			100);
+	start = jiffies;
 	timeout = wait_for_completion_timeout(&sspi->done,
-					      msecs_to_jiffies(1000));
+					      msecs_to_jiffies(tx_time));
+	end = jiffies;
 	if (!timeout) {
+		dev_warn(&master->dev,
+			 "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
+			 dev_name(&spi->dev), tfr->len, tfr->speed_hz,
+			 jiffies_to_msecs(end - start), tx_time);
 		ret = -ETIMEDOUT;
 		goto out;
 	}
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 42e2c4b..8be5c5c 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -162,6 +162,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
 	unsigned int mclk_rate, div, timeout;
 	unsigned int tx_len = 0;
 	int ret = 0;
+	unsigned int start, end, tx_time;
 	u32 reg;
 
 	/* We don't support transfer larger than the FIFO */
@@ -269,9 +270,17 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
 	reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
 	sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
 
+	tx_time = max_t(unsigned, tfr->len * 8 * 2 / (tfr->speed_hz / 1000),
+			100);
+	start = jiffies;
 	timeout = wait_for_completion_timeout(&sspi->done,
-					      msecs_to_jiffies(1000));
+					      msecs_to_jiffies(tx_time));
+	end = jiffies;
 	if (!timeout) {
+		dev_warn(&master->dev,
+			 "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
+			 dev_name(&spi->dev), tfr->len, tfr->speed_hz,
+			 jiffies_to_msecs(end - start), tx_time);
 		ret = -ETIMEDOUT;
 		goto out;
 	}
-- 
2.8.1



From hramrach at gmail.com  Thu May 26 12:25:24 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: 26 May 2016 19:25:24 -0000
Subject: [PATCH 3/5] spi: sunxi: expose maximum transfer size limit
In-Reply-To: <cover.1464130597.git.hramrach@gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
Message-ID: <5fffb7eca6f4b70853d92be2403595d6d06bede7.1464130597.git.hramrach@gmail.com>

The sun4i spi hardware can trasfer at most 63 bytes of data without DMA
support so report the limitation. Same on sun6i.

Signed-off-by: Michal Suchanek <hramrach at gmail.com>
---
 drivers/spi/spi-sun4i.c | 6 ++++++
 drivers/spi/spi-sun6i.c | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index 04f1b77..bf52b09 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -167,6 +167,11 @@ static void sun4i_spi_set_cs(struct spi_device *spi, bool enable)
 	sun4i_spi_write(sspi, SUN4I_CTL_REG, reg);
 }
 
+static size_t sun4i_spi_max_transfer_size(struct spi_device *spi)
+{
+	return SUN4I_FIFO_DEPTH - 1;
+}
+
 static int sun4i_spi_transfer_one(struct spi_master *master,
 				  struct spi_device *spi,
 				  struct spi_transfer *tfr)
@@ -407,6 +412,7 @@ static int sun4i_spi_probe(struct platform_device *pdev)
 	master->bits_per_word_mask = SPI_BPW_MASK(8);
 	master->dev.of_node = pdev->dev.of_node;
 	master->auto_runtime_pm = true;
+	master->max_transfer_size = sun4i_spi_max_transfer_size;
 
 	sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
 	if (IS_ERR(sspi->hclk)) {
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 8954a62..f491a41 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -154,6 +154,11 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool enable)
 }
 
 
+static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
+{
+	return SUN6I_FIFO_DEPTH - 1;
+}
+
 static int sun6i_spi_transfer_one(struct spi_master *master,
 				  struct spi_device *spi,
 				  struct spi_transfer *tfr)
@@ -418,6 +423,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
 	master->bits_per_word_mask = SPI_BPW_MASK(8);
 	master->dev.of_node = pdev->dev.of_node;
 	master->auto_runtime_pm = true;
+	master->max_transfer_size = sun6i_spi_max_transfer_size;
 
 	sspi->hclk = devm_clk_get(&pdev->dev, "ahb");
 	if (IS_ERR(sspi->hclk)) {
-- 
2.8.1



From hramrach at gmail.com  Thu May 26 12:25:23 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: 26 May 2016 19:25:23 -0000
Subject: [PATCH 2/3] ARM: dts: sun5i: add spi2 on A10s Olinuxino Micro
In-Reply-To: <908ed06eb46f2162e222258aa14df545d0fa5b48.1464129859.git.hramrach@gmail.com>
References: <908ed06eb46f2162e222258aa14df545d0fa5b48.1464129859.git.hramrach@gmail.com>
Message-ID: <602069f7735ad37b1849dac484d2e8e7c9ec08b3.1464129859.git.hramrach@gmail.com>

spi2 is available on the UEXT connector

Signed-off-by: Michal Suchanek <hramrach at gmail.com>
---
 arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
index 86d046a..7d2ff60 100644
--- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
@@ -192,6 +192,13 @@
 	status = "okay";
 };
 
+&spi2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi2_pins_a>,
+		    <&spi2_cs0_pins_a>;
+	status = "okay";
+};
+
 &ohci0 {
 	status = "okay";
 };
-- 
2.8.1



From hramrach at gmail.com  Thu May 26 12:25:24 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: 26 May 2016 19:25:24 -0000
Subject: [PATCH 3/3] ARM: dts: sun5i: Add spi2 alias on A10s Olinuxino
In-Reply-To: <908ed06eb46f2162e222258aa14df545d0fa5b48.1464129859.git.hramrach@gmail.com>
References: <908ed06eb46f2162e222258aa14df545d0fa5b48.1464129859.git.hramrach@gmail.com>
Message-ID: <df27dbe5931dcb7d8f404759ad42e25b15bcf780.1464129859.git.hramrach@gmail.com>

spi2 is available on the UEXT connector

The bus is named spi2 in the A10s manual and Olinuxino manual so it is
pointless to alias it to something else like spi0.

Signed-off-by: Michal Suchanek <hramrach at gmail.com>
---
 arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
index 7d2ff60..9729c37 100644
--- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
@@ -58,6 +58,7 @@
 		serial0 = &uart0;
 		serial1 = &uart2;
 		serial2 = &uart3;
+		spi2 = &spi2;
 	};
 
 	chosen {
-- 
2.8.1



From hramrach at gmail.com  Thu May 26 12:25:25 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: 26 May 2016 19:25:25 -0000
Subject: [PATCH 4/5] spi: sunxi: set maximum and minimum speed of SPI master
In-Reply-To: <cover.1464130597.git.hramrach@gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
Message-ID: <7292b1fa08de4f453a643beb63e9faa7826726f6.1464130597.git.hramrach@gmail.com>

The maximum speed of SPI master is used when maximum speed of SPI slave
is not specified. Also the __spi_validate function should check that
transfer speeds do not exceed the master limits.

The user manual for A10 and A31 specifies maximum
speed of the SPI clock as 100MHz and minimum as 3kHz.

Setting the SPI clock to out-of-spec values can lock up the SoC.

Signed-off-by: Michal Suchanek <hramrach at gmail.com>
---
 drivers/spi/spi-sun4i.c | 2 ++
 drivers/spi/spi-sun6i.c | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index bf52b09..e1a75dd6 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -405,6 +405,8 @@ static int sun4i_spi_probe(struct platform_device *pdev)
 	}
 
 	sspi->master = master;
+	master->max_speed_hz = 100*1000*1000;
+	master->min_speed_hz =        3*1000;
 	master->set_cs = sun4i_spi_set_cs;
 	master->transfer_one = sun4i_spi_transfer_one;
 	master->num_chipselect = 4;
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 1952956..0c378ff 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -400,6 +400,8 @@ static int sun6i_spi_probe(struct platform_device *pdev)
 	}
 
 	sspi->master = master;
+	master->max_speed_hz = 100*1000*1000;
+	master->min_speed_hz =        3*1000;
 	master->set_cs = sun6i_spi_set_cs;
 	master->transfer_one = sun6i_spi_transfer_one;
 	master->num_chipselect = 4;
-- 
2.8.1



From hramrach at gmail.com  Thu May 26 12:25:24 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: 26 May 2016 19:25:24 -0000
Subject: [PATCH 2/5] spi: sun4i: fix FIFO limit
In-Reply-To: <cover.1464130597.git.hramrach@gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
Message-ID: <e315008b5e9dc3f1490507508fd2f6e94767dfbb.1464130597.git.hramrach@gmail.com>

When testing SPI without DMA I noticed that filling the FIFO on the
spi controller causes timeout.

Always leave room for one byte in the FIFO.

Signed-off-by: Michal Suchanek <hramrach at gmail.com>

---
v2:
use EMSGSIZE instead of EINVAL
---
 drivers/spi/spi-sun4i.c | 8 ++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index fe63bbd..04f1b77 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -180,7 +180,9 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
 
 	/* We don't support transfer larger than the FIFO */
 	if (tfr->len > SUN4I_FIFO_DEPTH)
-		return -EINVAL;
+		return -EMSGSIZE;
+	if (tfr->tx_buf && tfr->len >= SUN4I_FIFO_DEPTH)
+		return -EMSGSIZE;
 
 	reinit_completion(&sspi->done);
 	sspi->tx_buf = tfr->tx_buf;
@@ -271,7 +273,9 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
 	sun4i_spi_write(sspi, SUN4I_XMIT_CNT_REG, SUN4I_XMIT_CNT(tx_len));
 
 	/* Fill the TX FIFO */
-	sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
+	/* Filling the FIFO fully causes timeout for some reason
+	 * at least on spi2 on A10s */
+	sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH - 1);
 
 	/* Enable the interrupts */
 	sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC);


From hramrach at gmail.com  Tue May 24 15:56:37 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: Wed, 25 May 2016 00:56:37 +0200
Subject: [PATCH 0/5] sunxi spi fixes
Message-ID: <cover.1464130597.git.hramrach@gmail.com>

Hello,

This series addresses some issues with sunxi SPI drivers.

The last patch adding DMA support is not completed. It addresses some issues
with the previous version of the patch and it works in practice but some issues
still remain.

Thanks

Michal

Emilio L?pez (1):
  RFC spi: sun4i: add DMA support

Michal Suchanek (4):
  spi: sunxi: fix transfer timeout
  spi: sun4i: fix FIFO limit
  spi: sunxi: expose maximum transfer size limit
  spi: sunxi: set maximum and minimum speed of SPI master

 drivers/spi/spi-sun4i.c | 186 +++++++++++++++++++++++++++++++++++++++++++++---
 drivers/spi/spi-sun6i.c |  20 +++++-
 2 files changed, 194 insertions(+), 12 deletions(-)

-- 
2.8.1



From hramrach at gmail.com  Thu May 26 12:25:22 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: 26 May 2016 19:25:22 -0000
Subject: [PATCH 1/3] ARM: dts: sun5i: a10s: add spi2 pins
Message-ID: <908ed06eb46f2162e222258aa14df545d0fa5b48.1464129859.git.hramrach@gmail.com>

Used on A10s Olinuxino.

Signed-off-by: Michal Suchanek <hramrach at gmail.com>
---
 arch/arm/boot/dts/sun5i-a10s.dtsi | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index bddd0de..651837c 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -241,6 +241,20 @@
 		allwinner,drive = <SUN4I_PINCTRL_30_MA>;
 		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 	};
+
+	spi2_pins_a: spi2 at 0 {
+		allwinner,pins = "PB12", "PB13", "PB14";
+		allwinner,function = "spi2";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	spi2_cs0_pins_a: spi2_cs0 at 0 {
+		allwinner,pins = "PB11";
+		allwinner,function = "spi2";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
 };
 
 &sram_a {
-- 
2.8.1



From hramrach at gmail.com  Thu May 26 12:25:25 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: 26 May 2016 19:25:25 -0000
Subject: [PATCH 5/5] RFC spi: sun4i: add DMA support
In-Reply-To: <cover.1464130597.git.hramrach@gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
Message-ID: <ba0d6eb37cc4b0d2c46acbf9fcd7d644b3545ce8.1464130597.git.hramrach@gmail.com>

From: Emilio L?pez <emilio at elopez.com.ar>

This patch adds support for 64 byte or bigger transfers on the
sun4i SPI controller. Said transfers will be performed via DMA.

Signed-off-by: Emilio L?pez <emilio at elopez.com.ar>
Signed-off-by: Michal Suchanek <hramrach at gmail.com>

---
v2:
 - fallback to previous behaviour when DMA initialization fails

   + this has the problem that when the driver happens to load before the dma
     driver it will not use dma - can be addressed with a module parameter
 + the issue with dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL; ...
   dma_wait_for_async_tx(desc_rx); remains unaddressed

---
 drivers/spi/spi-sun4i.c | 171 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 158 insertions(+), 13 deletions(-)

diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
index e1a75dd6..ed2269c 100644
--- a/drivers/spi/spi-sun4i.c
+++ b/drivers/spi/spi-sun4i.c
@@ -14,6 +14,8 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -34,6 +36,7 @@
 #define SUN4I_CTL_CPHA				BIT(2)
 #define SUN4I_CTL_CPOL				BIT(3)
 #define SUN4I_CTL_CS_ACTIVE_LOW			BIT(4)
+#define SUN4I_CTL_DMAMC_DEDICATED		BIT(5)
 #define SUN4I_CTL_LMTF				BIT(6)
 #define SUN4I_CTL_TF_RST			BIT(8)
 #define SUN4I_CTL_RF_RST			BIT(9)
@@ -51,6 +54,8 @@
 #define SUN4I_INT_STA_REG		0x10
 
 #define SUN4I_DMA_CTL_REG		0x14
+#define SUN4I_DMA_CTL_RF_READY			BIT(0)
+#define SUN4I_DMA_CTL_TF_NOT_FULL		BIT(10)
 
 #define SUN4I_WAIT_REG			0x18
 
@@ -130,6 +135,13 @@ static inline void sun4i_spi_fill_fifo(struct sun4i_spi *sspi, int len)
 	}
 }
 
+static bool sun4i_spi_can_dma(struct spi_master *master,
+			      struct spi_device *spi,
+			      struct spi_transfer *tfr)
+{
+	return tfr->len >= SUN4I_FIFO_DEPTH;
+}
+
 static void sun4i_spi_set_cs(struct spi_device *spi, bool enable)
 {
 	struct sun4i_spi *sspi = spi_master_get_devdata(spi->master);
@@ -177,17 +189,20 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
 				  struct spi_transfer *tfr)
 {
 	struct sun4i_spi *sspi = spi_master_get_devdata(master);
+	struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
 	unsigned int mclk_rate, div, timeout;
 	unsigned int start, end, tx_time;
 	unsigned int tx_len = 0;
+	u32 reg, trigger = 0;
 	int ret = 0;
-	u32 reg;
 
-	/* We don't support transfer larger than the FIFO */
-	if (tfr->len > SUN4I_FIFO_DEPTH)
-		return -EMSGSIZE;
-	if (tfr->tx_buf && tfr->len >= SUN4I_FIFO_DEPTH)
-		return -EMSGSIZE;
+	if (!master->can_dma) {
+		/* We don't support transfer larger than the FIFO */
+		if (tfr->len > SUN4I_FIFO_DEPTH)
+			return -EMSGSIZE;
+		if (tfr->tx_buf && tfr->len >= SUN4I_FIFO_DEPTH)
+			return -EMSGSIZE;
+	}
 
 	reinit_completion(&sspi->done);
 	sspi->tx_buf = tfr->tx_buf;
@@ -277,14 +292,67 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
 	sun4i_spi_write(sspi, SUN4I_BURST_CNT_REG, SUN4I_BURST_CNT(tfr->len));
 	sun4i_spi_write(sspi, SUN4I_XMIT_CNT_REG, SUN4I_XMIT_CNT(tx_len));
 
-	/* Fill the TX FIFO */
-	/* Filling the FIFO fully causes timeout for some reason
-	 * at least on spi2 on A10s */
-	sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH - 1);
-
 	/* Enable the interrupts */
 	sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC);
 
+	if (sun4i_spi_can_dma(master, spi, tfr)) {
+		dev_dbg(&sspi->master->dev, "Using DMA mode for transfer\n");
+
+		if (sspi->tx_buf) {
+			desc_tx = dmaengine_prep_slave_sg(master->dma_tx,
+					tfr->tx_sg.sgl, tfr->tx_sg.nents,
+					DMA_TO_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+			if (!desc_tx) {
+				dev_err(&sspi->master->dev,
+					"Couldn't prepare dma slave\n");
+				return -EIO;
+			}
+
+			trigger |= SUN4I_DMA_CTL_TF_NOT_FULL;
+
+			dmaengine_submit(desc_tx);
+			dma_async_issue_pending(master->dma_tx);
+
+		}
+
+		if (sspi->rx_buf) {
+			desc_rx = dmaengine_prep_slave_sg(master->dma_rx,
+					tfr->rx_sg.sgl, tfr->rx_sg.nents,
+					DMA_FROM_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+			if (!desc_rx) {
+				dev_err(&sspi->master->dev,
+					"Couldn't prepare dma slave\n");
+				return -EIO;
+			}
+
+			trigger |= SUN4I_DMA_CTL_RF_READY;
+
+			dmaengine_submit(desc_rx);
+			dma_async_issue_pending(master->dma_rx);
+		}
+
+		/* Enable Dedicated DMA requests */
+		reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
+		reg |= SUN4I_CTL_DMAMC_DEDICATED;
+		sun4i_spi_write(sspi, SUN4I_CTL_REG, reg);
+		sun4i_spi_write(sspi, SUN4I_DMA_CTL_REG, trigger);
+	} else {
+		dev_dbg(&sspi->master->dev, "Using PIO mode for transfer\n");
+
+		/* Disable DMA requests */
+		reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
+		sun4i_spi_write(sspi, SUN4I_CTL_REG,
+				reg & ~SUN4I_CTL_DMAMC_DEDICATED);
+		sun4i_spi_write(sspi, SUN4I_DMA_CTL_REG, 0);
+
+		/* Fill the TX FIFO */
+		/* Filling the FIFO fully causes timeout for some reason
+		 * at least on spi2 on A10s */
+		sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH - 1);
+	}
+
 	/* Start the transfer */
 	reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
 	sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
@@ -304,7 +372,16 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
 		goto out;
 	}
 
-	sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
+	if (sun4i_spi_can_dma(master, spi, tfr) && desc_rx) {
+		/* The receive transfer should be the last one to finish */
+			/* This seems to work OK.
+			 * TODO: look for some drivers which do something
+			 * more sensible here. */
+		dma_wait_for_async_tx(desc_rx);
+	} else {
+		/* This should be noop with tx only dma */
+		sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
+	}
 
 out:
 	sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0);
@@ -369,6 +446,7 @@ static int sun4i_spi_runtime_suspend(struct device *dev)
 
 static int sun4i_spi_probe(struct platform_device *pdev)
 {
+	struct dma_slave_config dma_sconfig;
 	struct spi_master *master;
 	struct sun4i_spi *sspi;
 	struct resource	*res;
@@ -404,6 +482,7 @@ static int sun4i_spi_probe(struct platform_device *pdev)
 		goto err_free_master;
 	}
 
+	init_completion(&sspi->done);
 	sspi->master = master;
 	master->max_speed_hz = 100*1000*1000;
 	master->min_speed_hz =        3*1000;
@@ -430,8 +509,55 @@ static int sun4i_spi_probe(struct platform_device *pdev)
 		goto err_free_master;
 	}
 
-	init_completion(&sspi->done);
+	master->dma_tx = dma_request_slave_channel_reason(&pdev->dev, "tx");
+	if (IS_ERR(master->dma_tx)) {
+		dev_err(&pdev->dev, "Unable to acquire DMA channel TX\n");
+		ret = PTR_ERR(master->dma_tx);
+		master->dma_tx = NULL;
+		goto wakeup;
+	}
+
+	dma_sconfig.direction = DMA_MEM_TO_DEV;
+	dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	dma_sconfig.dst_addr = res->start + SUN4I_TXDATA_REG;
+	dma_sconfig.src_maxburst = 1;
+	dma_sconfig.dst_maxburst = 1;
 
+	ret = dmaengine_slave_config(master->dma_tx, &dma_sconfig);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to configure TX DMA slave\n");
+		goto err_tx_dma_release;
+	}
+
+	master->dma_rx = dma_request_slave_channel_reason(&pdev->dev, "rx");
+	if (IS_ERR(master->dma_rx)) {
+		dev_err(&pdev->dev, "Unable to acquire DMA channel RX\n");
+		ret = PTR_ERR(master->dma_rx);
+		goto err_tx_dma_release;
+	}
+
+	dma_sconfig.direction = DMA_DEV_TO_MEM;
+	dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	dma_sconfig.src_addr = res->start + SUN4I_RXDATA_REG;
+	dma_sconfig.src_maxburst = 1;
+	dma_sconfig.dst_maxburst = 1;
+
+	ret = dmaengine_slave_config(master->dma_rx, &dma_sconfig);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to configure RX DMA slave\n");
+		goto err_rx_dma_release;
+	}
+
+	/* This is a bit dodgy. If you set can_dma then map_msg in spi.c
+	 * apparently dereferences your dma channels if non-NULL even if your
+	 * can_dma never returns true (and crashes if the channel is an error
+	 * pointer). So just don't set can_dma unless both channels are valid.
+	 */
+	master->can_dma = sun4i_spi_can_dma;
+	master->max_transfer_size = NULL; /* no known limit */
+wakeup:
 	/*
 	 * This wake-up/shutdown pattern is to be able to have the
 	 * device woken up, even if runtime_pm is disabled
@@ -454,18 +580,37 @@ static int sun4i_spi_probe(struct platform_device *pdev)
 
 	return 0;
 
+err_rx_dma_release:
+	dma_release_channel(master->dma_rx);
+err_tx_dma_release:
+	dma_release_channel(master->dma_tx);
+	master->dma_tx = NULL;
+	master->dma_rx = NULL;
+	goto wakeup;
+
 err_pm_disable:
 	pm_runtime_disable(&pdev->dev);
 	sun4i_spi_runtime_suspend(&pdev->dev);
 err_free_master:
+	if (master->can_dma) {
+		dma_release_channel(master->dma_rx);
+		dma_release_channel(master->dma_tx);
+	}
 	spi_master_put(master);
 	return ret;
 }
 
 static int sun4i_spi_remove(struct platform_device *pdev)
 {
+	struct spi_master *master = platform_get_drvdata(pdev);
+
 	pm_runtime_disable(&pdev->dev);
 
+	if (master->can_dma) {
+		dma_release_channel(master->dma_rx);
+		dma_release_channel(master->dma_tx);
+	}
+
 	return 0;
 }
 
-- 
2.8.1



From dave.long at linaro.org  Thu May 26 12:25:54 2016
From: dave.long at linaro.org (David Long)
Date: Thu, 26 May 2016 15:25:54 -0400
Subject: [PATCH v12 05/10] arm64: Kprobes with single stepping support
In-Reply-To: <20160518122935.39fd7acc63d6f9c17fcbe275@kernel.org>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-6-git-send-email-dave.long@linaro.org>
 <20160517085807.GA842@sha-win-210.asiapac.arm.com>
 <20160518122935.39fd7acc63d6f9c17fcbe275@kernel.org>
Message-ID: <57474DC2.5070400@linaro.org>

On 05/17/2016 11:29 PM, Masami Hiramatsu wrote:
> On Tue, 17 May 2016 16:58:09 +0800
> Huang Shijie <shijie.huang at arm.com> wrote:
>
>> On Wed, Apr 27, 2016 at 02:53:00PM -0400, David Long wrote:
>>> +
>>> +/*
>>> + * Interrupts need to be disabled before single-step mode is set, and not
>>> + * reenabled until after single-step mode ends.
>>> + * Without disabling interrupt on local CPU, there is a chance of
>>> + * interrupt occurrence in the period of exception return and  start of
>>> + * out-of-line single-step, that result in wrongly single stepping
>>> + * into the interrupt handler.
>>> + */
>>> +static void __kprobes kprobes_save_local_irqflag(struct pt_regs *regs)
>>> +{
>>> +     struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
>>
>> Why not add a parameter for this function to save the @kcb?
>
> Good catch, it should use same kcb of caller.
>

I've made the change for the next version of the patch.

>>
>>> +
>>> +     kcb->saved_irqflag = regs->pstate;
>>> +     regs->pstate |= PSR_I_BIT;
>>> +}
>>> +
>>> +static void __kprobes kprobes_restore_local_irqflag(struct pt_regs *regs)
>>> +{
>>> +     struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
>> ditto.
>>

I've made the change.

>>> +
>>> +     if (kcb->saved_irqflag & PSR_I_BIT)
>>> +             regs->pstate |= PSR_I_BIT;
>>> +     else
>>> +             regs->pstate &= ~PSR_I_BIT;
>>> +}
>>> +
>>> +static void __kprobes
>>> +set_ss_context(struct kprobe_ctlblk *kcb, unsigned long addr)
>>> +{
>>> +     kcb->ss_ctx.ss_pending = true;
>>> +     kcb->ss_ctx.match_addr = addr + sizeof(kprobe_opcode_t);
>>> +}
>>> +
>>> +static void __kprobes clear_ss_context(struct kprobe_ctlblk *kcb)
>>> +{
>>> +     kcb->ss_ctx.ss_pending = false;
>>> +     kcb->ss_ctx.match_addr = 0;
>>> +}
>>> +
>>> +static void __kprobes setup_singlestep(struct kprobe *p,
>>> +                                    struct pt_regs *regs,
>>> +                                    struct kprobe_ctlblk *kcb, int reenter)
>>> +{
>>> +     unsigned long slot;
>>> +
>>> +     if (reenter) {
>>> +             save_previous_kprobe(kcb);
>>> +             set_current_kprobe(p);
>>> +             kcb->kprobe_status = KPROBE_REENTER;
>>> +     } else {
>>> +             kcb->kprobe_status = KPROBE_HIT_SS;
>>> +     }
>>> +
>>> +     if (p->ainsn.insn) {
>>> +             /* prepare for single stepping */
>>> +             slot = (unsigned long)p->ainsn.insn;
>>> +
>>> +             set_ss_context(kcb, slot);      /* mark pending ss */
>>> +
>>> +             if (kcb->kprobe_status == KPROBE_REENTER)
>>> +                     spsr_set_debug_flag(regs, 0);
>>> +
>>> +             /* IRQs and single stepping do not mix well. */
>>> +             kprobes_save_local_irqflag(regs);
>>> +             kernel_enable_single_step(regs);
>>> +             instruction_pointer(regs) = slot;
>>> +     } else  {
>>> +             BUG();
>
> You'd better use BUG_ON(!p->ainsn.insn);
>

I have that change ready but the BUG*() is removed entirely in patch 
07/10 and the indentation changed back to the above, resulting in more 
diffs and the same final code.

>>> +     }
>>> +}
>>> +
>>> +static int __kprobes reenter_kprobe(struct kprobe *p,
>>> +                                 struct pt_regs *regs,
>>> +                                 struct kprobe_ctlblk *kcb)
>>> +{
>>> +     switch (kcb->kprobe_status) {
>>> +     case KPROBE_HIT_SSDONE:
>>> +     case KPROBE_HIT_ACTIVE:
>>> +             kprobes_inc_nmissed_count(p);
>>> +             setup_singlestep(p, regs, kcb, 1);
>>> +             break;
>>> +     case KPROBE_HIT_SS:
>>> +     case KPROBE_REENTER:
>>> +             pr_warn("Unrecoverable kprobe detected at %p.\n", p->addr);
>>> +             dump_kprobe(p);
>>> +             BUG();
>>> +             break;
>>> +     default:
>>> +             WARN_ON(1);
>>> +             return 0;
>>> +     }
>>> +
>>> +     return 1;
>>> +}
>>> +
>>> +static void __kprobes
>>> +post_kprobe_handler(struct kprobe_ctlblk *kcb, struct pt_regs *regs)
>>> +{
>>> +     struct kprobe *cur = kprobe_running();
>>> +
>>> +     if (!cur)
>>> +             return;
>>> +
>>> +     /* return addr restore if non-branching insn */
>>> +     if (cur->ainsn.restore.type == RESTORE_PC) {
>>> +             instruction_pointer(regs) = cur->ainsn.restore.addr;
>>> +             if (!instruction_pointer(regs))
>>> +                     BUG();
>>> +     }
>>> +
>>> +     /* restore back original saved kprobe variables and continue */
>>> +     if (kcb->kprobe_status == KPROBE_REENTER) {
>>> +             restore_previous_kprobe(kcb);
>>> +             return;
>>> +     }
>>> +     /* call post handler */
>>> +     kcb->kprobe_status = KPROBE_HIT_SSDONE;
>>> +     if (cur->post_handler)  {
>>> +             /* post_handler can hit breakpoint and single step
>>> +              * again, so we enable D-flag for recursive exception.
>>> +              */
>>> +             cur->post_handler(cur, regs, 0);
>>> +     }
>>> +
>>> +     reset_current_kprobe();
>>> +}
>>> +
>>> +int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
>>> +{
>>> +     struct kprobe *cur = kprobe_running();
>>> +     struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
>>> +
>>> +     switch (kcb->kprobe_status) {
>>> +     case KPROBE_HIT_SS:
>>> +     case KPROBE_REENTER:
>>> +             /*
>>> +              * We are here because the instruction being single
>>> +              * stepped caused a page fault. We reset the current
>>> +              * kprobe and the ip points back to the probe address
>>> +              * and allow the page fault handler to continue as a
>>> +              * normal page fault.
>>> +              */
>>> +             instruction_pointer(regs) = (unsigned long)cur->addr;
>>> +             if (!instruction_pointer(regs))
>>> +                     BUG();
>
> This can be BUG_ON(!instruction_pointer(regs)).
>

I've made the change.

>>> +             if (kcb->kprobe_status == KPROBE_REENTER)
>>> +                     restore_previous_kprobe(kcb);
>>> +             else
>>> +                     reset_current_kprobe();
>>> +
>>> +             break;
>>> +     case KPROBE_HIT_ACTIVE:
>>> +     case KPROBE_HIT_SSDONE:
>>> +             /*
>>> +              * We increment the nmissed count for accounting,
>>> +              * we can also use npre/npostfault count for accounting
>>> +              * these specific fault cases.
>>> +              */
>>> +             kprobes_inc_nmissed_count(cur);
>>> +
>>> +             /*
>>> +              * We come here because instructions in the pre/post
>>> +              * handler caused the page_fault, this could happen
>>> +              * if handler tries to access user space by
>>> +              * copy_from_user(), get_user() etc. Let the
>>> +              * user-specified handler try to fix it first.
>>> +              */
>>> +             if (cur->fault_handler && cur->fault_handler(cur, regs, fsr))
>>> +                     return 1;
>>> +
>>> +             /*
>>> +              * In case the user-specified fault handler returned
>>> +              * zero, try to fix up.
>>> +              */
>>> +             if (fixup_exception(regs))
>>> +                     return 1;
>>> +     }
>>> +     return 0;
>>> +}
>>> +
>>> +int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
>>> +                                    unsigned long val, void *data)
>>> +{
>>> +     return NOTIFY_DONE;
>>> +}
>>> +
>>> +static void __kprobes kprobe_handler(struct pt_regs *regs)
>>> +{
>>> +     struct kprobe *p, *cur_kprobe;
>>> +     struct kprobe_ctlblk *kcb;
>>> +     unsigned long addr = instruction_pointer(regs);
>>> +
>>> +     kcb = get_kprobe_ctlblk();
>>> +     cur_kprobe = kprobe_running();
>>> +
>>> +     p = get_kprobe((kprobe_opcode_t *) addr);
>>> +
>>> +     if (p) {
>>> +             if (cur_kprobe) {
>>> +                     if (reenter_kprobe(p, regs, kcb))
>>> +                             return;
>>> +             } else {
>>> +                     /* Probe hit */
>>> +                     set_current_kprobe(p);
>>> +                     kcb->kprobe_status = KPROBE_HIT_ACTIVE;
>>> +
>>> +                     /*
>>> +                      * If we have no pre-handler or it returned 0, we
>>> +                      * continue with normal processing.  If we have a
>>> +                      * pre-handler and it returned non-zero, it prepped
>>> +                      * for calling the break_handler below on re-entry,
>>> +                      * so get out doing nothing more here.
>>> +                      *
>>> +                      * pre_handler can hit a breakpoint and can step thru
>>> +                      * before return, keep PSTATE D-flag enabled until
>>> +                      * pre_handler return back.
>>> +                      */
>>> +                     if (!p->pre_handler || !p->pre_handler(p, regs)) {
>>> +                             kcb->kprobe_status = KPROBE_HIT_SS;
>> The above line is duplicated.
>> You will set KPROBE_HIT_SS in the setup_singlestep.
>
> Right.
>

I've removed it.

>>
>>> +                             setup_singlestep(p, regs, kcb, 0);
>>> +                             return;
>>> +                     }
>>> +             }
>>> +     } else if ((le32_to_cpu(*(kprobe_opcode_t *) addr) ==
>>> +         BRK64_OPCODE_KPROBES) && cur_kprobe) {
>>> +             /* We probably hit a jprobe.  Call its break handler. */
>>> +             if (cur_kprobe->break_handler  &&
>>> +                  cur_kprobe->break_handler(cur_kprobe, regs)) {
>>> +                     kcb->kprobe_status = KPROBE_HIT_SS;
>> ditto

I've removed it.

>>> +                     setup_singlestep(cur_kprobe, regs, kcb, 0);
>>> +                     return;
>>> +             }
>>> +     }
>>> +     /*
>>> +      * The breakpoint instruction was removed right
>>> +      * after we hit it.  Another cpu has removed
>>> +      * either a probepoint or a debugger breakpoint
>>> +      * at this address.  In either case, no further
>>> +      * handling of this interrupt is appropriate.
>>> +      * Return back to original instruction, and continue.
>>> +      */
>>> +}
>
> Thanks,
>
>
>

Thanks,
-dl



From dave.long at linaro.org  Thu May 26 12:28:32 2016
From: dave.long at linaro.org (David Long)
Date: Thu, 26 May 2016 15:28:32 -0400
Subject: [PATCH v12 07/10] arm64: kprobes instruction simulation support
In-Reply-To: <20160519015222.GA25870@sha-win-210.asiapac.arm.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-8-git-send-email-dave.long@linaro.org>
 <20160519015222.GA25870@sha-win-210.asiapac.arm.com>
Message-ID: <57474E60.3050802@linaro.org>

On 05/18/2016 09:52 PM, Huang Shijie wrote:
> On Wed, Apr 27, 2016 at 02:53:02PM -0400, David Long wrote:
>> From: Sandeepa Prabhu <sandeepa.s.prabhu at gmail.com>
>>
>> Kprobes needs simulation of instructions that cannot be stepped
>> from a different memory location, e.g.: those instructions
>> that uses PC-relative addressing. In simulation, the behaviour
>> of the instruction is implemented using a copy of pt_regs.
>>
>> The following instruction categories are simulated:
>>   - All branching instructions(conditional, register, and immediate)
>>   - Literal access instructions(load-literal, adr/adrp)
>>
>> Conditional execution is limited to branching instructions in
>> ARM v8. If conditions at PSTATE do not match the condition fields
>> of opcode, the instruction is effectively NOP.
>>
>> Thanks to Will Cohen for assorted suggested changes.
>>
>> Signed-off-by: Sandeepa Prabhu <sandeepa.s.prabhu at gmail.com>
>> Signed-off-by: William Cohen <wcohen at redhat.com>
>> Signed-off-by: David A. Long <dave.long at linaro.org>
>> ---
>>   arch/arm64/include/asm/insn.h            |   1 +
>>   arch/arm64/include/asm/probes.h          |   5 +-
>>   arch/arm64/kernel/Makefile               |   3 +-
>>   arch/arm64/kernel/insn.c                 |   1 +
>>   arch/arm64/kernel/kprobes-arm64.c        |  29 ++++
>>   arch/arm64/kernel/kprobes.c              |  32 ++++-
>>   arch/arm64/kernel/probes-simulate-insn.c | 218 +++++++++++++++++++++++++++++++
>>   arch/arm64/kernel/probes-simulate-insn.h |  28 ++++
>>   8 files changed, 311 insertions(+), 6 deletions(-)
>>   create mode 100644 arch/arm64/kernel/probes-simulate-insn.c
>>   create mode 100644 arch/arm64/kernel/probes-simulate-insn.h
>>
>> diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
>> index b9567a1..26cee10 100644
>> --- a/arch/arm64/include/asm/insn.h
>> +++ b/arch/arm64/include/asm/insn.h
>> @@ -410,6 +410,7 @@ u32 aarch32_insn_mcr_extract_crm(u32 insn);
>>
>>   typedef bool (pstate_check_t)(unsigned long);
>>   extern pstate_check_t * const opcode_condition_checks[16];
>> +
>>   #endif /* __ASSEMBLY__ */
>>
>>   #endif	/* __ASM_INSN_H */
>> diff --git a/arch/arm64/include/asm/probes.h b/arch/arm64/include/asm/probes.h
>> index c5fcbe6..d524f7d 100644
>> --- a/arch/arm64/include/asm/probes.h
>> +++ b/arch/arm64/include/asm/probes.h
>> @@ -15,11 +15,12 @@
>>   #ifndef _ARM_PROBES_H
>>   #define _ARM_PROBES_H
>>
>> +#include <asm/opcodes.h>
>> +
>>   struct kprobe;
>>   struct arch_specific_insn;
>>
>>   typedef u32 kprobe_opcode_t;
>> -typedef unsigned long (kprobes_pstate_check_t)(unsigned long);
>>   typedef void (kprobes_handler_t) (u32 opcode, long addr, struct pt_regs *);
>>
>>   enum pc_restore_type {
>> @@ -35,7 +36,7 @@ struct kprobe_pc_restore {
>>   /* architecture specific copy of original instruction */
>>   struct arch_specific_insn {
>>   	kprobe_opcode_t *insn;
>> -	kprobes_pstate_check_t *pstate_cc;
>> +	pstate_check_t *pstate_cc;
>>   	kprobes_handler_t *handler;
>>   	/* restore address after step xol */
>>   	struct kprobe_pc_restore restore;
>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>> index 8816de2..43bf6cc 100644
>> --- a/arch/arm64/kernel/Makefile
>> +++ b/arch/arm64/kernel/Makefile
>> @@ -37,7 +37,8 @@ arm64-obj-$(CONFIG_CPU_PM)		+= sleep.o suspend.o
>>   arm64-obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
>>   arm64-obj-$(CONFIG_JUMP_LABEL)		+= jump_label.o
>>   arm64-obj-$(CONFIG_KGDB)		+= kgdb.o
>> -arm64-obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-arm64.o
>> +arm64-obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-arm64.o		\
>> +					   probes-simulate-insn.o
>>   arm64-obj-$(CONFIG_EFI)			+= efi.o efi-entry.stub.o
>>   arm64-obj-$(CONFIG_PCI)			+= pci.o
>>   arm64-obj-$(CONFIG_ARMV8_DEPRECATED)	+= armv8_deprecated.o
>> diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
>> index f79e72e..bb2738c 100644
>> --- a/arch/arm64/kernel/insn.c
>> +++ b/arch/arm64/kernel/insn.c
>> @@ -30,6 +30,7 @@
>>   #include <asm/cacheflush.h>
>>   #include <asm/debug-monitors.h>
>>   #include <asm/fixmap.h>
>> +#include <asm/opcodes.h>
>>   #include <asm/insn.h>
>>
>>   #define AARCH64_INSN_SF_BIT	BIT(31)
>> diff --git a/arch/arm64/kernel/kprobes-arm64.c b/arch/arm64/kernel/kprobes-arm64.c
>> index e07727a..487238a 100644
>> --- a/arch/arm64/kernel/kprobes-arm64.c
>> +++ b/arch/arm64/kernel/kprobes-arm64.c
>> @@ -21,6 +21,7 @@
>>   #include <asm/sections.h>
>>
>>   #include "kprobes-arm64.h"
>> +#include "probes-simulate-insn.h"
>>
>>   static bool __kprobes aarch64_insn_is_steppable(u32 insn)
>>   {
>> @@ -62,8 +63,36 @@ arm_probe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
>>   	 */
>>   	if (aarch64_insn_is_steppable(insn))
>>   		return INSN_GOOD;
>> +
>> +	if (aarch64_insn_is_bcond(insn)) {
>> +		asi->handler = simulate_b_cond;
>> +	} else if (aarch64_insn_is_cbz(insn) ||
>> +	    aarch64_insn_is_cbnz(insn)) {
>> +		asi->handler = simulate_cbz_cbnz;
>> +	} else if (aarch64_insn_is_tbz(insn) ||
>> +	    aarch64_insn_is_tbnz(insn)) {
>> +		asi->handler = simulate_tbz_tbnz;
>> +	} else if (aarch64_insn_is_adr_adrp(insn))
>> +		asi->handler = simulate_adr_adrp;
>> +	else if (aarch64_insn_is_b(insn) ||
>> +	    aarch64_insn_is_bl(insn))
>> +		asi->handler = simulate_b_bl;
>
> For the same codingstyle, we'd better add more "{}" here and below.
>
> thanks
> Huang Shijie
>
>> +	else if (aarch64_insn_is_br(insn) ||
>> +	    aarch64_insn_is_blr(insn) ||
>> +	    aarch64_insn_is_ret(insn))
>> +		asi->handler = simulate_br_blr_ret;
>> +	else if (aarch64_insn_is_ldr_lit(insn))
>> +		asi->handler = simulate_ldr_literal;
>> +	else if (aarch64_insn_is_ldrsw_lit(insn))
>> +		asi->handler = simulate_ldrsw_literal;
>>   	else
>> +		/*
>> +		 * Instruction cannot be stepped out-of-line and we don't
>> +		 * (yet) simulate it.
>> +		 */
>>   		return INSN_REJECTED;
>> +
>> +	return INSN_GOOD_NO_SLOT;
>>   }
>

I've made this change for the next version of the patch.

Thanks,
-dl



From austinwc at codeaurora.org  Thu May 26 12:37:56 2016
From: austinwc at codeaurora.org (Austin Christ)
Date: Thu, 26 May 2016 13:37:56 -0600
Subject: [PATCH 1/2][v3] i2c: qup: add ACPI support
Message-ID: <1464291477-4705-1-git-send-email-austinwc@codeaurora.org>

From: Naveen Kaje <nkaje at codeaurora.org>

Add support to get the device parameters from ACPI. Assume
that the clocks are managed by firmware.

Signed-off-by: Naveen Kaje <nkaje at codeaurora.org>
Signed-off-by: Austin Christ <austinwc at codeaurora.org>
---
 drivers/i2c/busses/i2c-qup.c | 60 ++++++++++++++++++++++++++++++++------------
 1 file changed, 44 insertions(+), 16 deletions(-)

Changes:
- v3:
 - clean up unused variable
- v2:
 - clean up redundant checks and variables

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index dddd4da..ea6ca5f 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -29,6 +29,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/scatterlist.h>
+#include <linux/acpi.h>
 
 /* QUP Registers */
 #define QUP_CONFIG		0x000
@@ -132,6 +133,10 @@
 /* Max timeout in ms for 32k bytes */
 #define TOUT_MAX			300
 
+/* Default values. Use these if FW query fails */
+#define DEFAULT_CLK_FREQ 100000
+#define DEFAULT_SRC_CLK 20000000
+
 struct qup_i2c_block {
 	int	count;
 	int	pos;
@@ -1354,14 +1359,13 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
 static int qup_i2c_probe(struct platform_device *pdev)
 {
 	static const int blk_sizes[] = {4, 16, 32};
-	struct device_node *node = pdev->dev.of_node;
 	struct qup_i2c_dev *qup;
 	unsigned long one_bit_t;
 	struct resource *res;
 	u32 io_mode, hw_ver, size;
 	int ret, fs_div, hs_div;
-	int src_clk_freq;
-	u32 clk_freq = 100000;
+	u32 src_clk_freq = 0;
+	u32 clk_freq = 0;
 	int blocks;
 
 	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
@@ -1372,7 +1376,12 @@ static int qup_i2c_probe(struct platform_device *pdev)
 	init_completion(&qup->xfer);
 	platform_set_drvdata(pdev, qup);
 
-	of_property_read_u32(node, "clock-frequency", &clk_freq);
+	ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
+	if (ret) {
+		dev_warn(qup->dev, "using default clock-frequency %d",
+			DEFAULT_CLK_FREQ);
+		clk_freq = DEFAULT_CLK_FREQ;
+	}
 
 	if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
 		qup->adap.algo = &qup_i2c_algo;
@@ -1454,20 +1463,31 @@ nodma:
 		return qup->irq;
 	}
 
-	qup->clk = devm_clk_get(qup->dev, "core");
-	if (IS_ERR(qup->clk)) {
-		dev_err(qup->dev, "Could not get core clock\n");
-		return PTR_ERR(qup->clk);
-	}
+	if (ACPI_HANDLE(qup->dev)) {
+		ret = device_property_read_u32(qup->dev,
+				"src-clock-hz", &src_clk_freq);
+		if (ret) {
+			dev_warn(qup->dev, "using default src-clock-hz %d",
+				DEFAULT_SRC_CLK);
+			src_clk_freq = DEFAULT_SRC_CLK;
+		}
+		ACPI_COMPANION_SET(&qup->adap.dev, ACPI_COMPANION(qup->dev));
+	} else {
+		qup->clk = devm_clk_get(qup->dev, "core");
+		if (IS_ERR(qup->clk)) {
+			dev_err(qup->dev, "Could not get core clock\n");
+			return PTR_ERR(qup->clk);
+		}
 
-	qup->pclk = devm_clk_get(qup->dev, "iface");
-	if (IS_ERR(qup->pclk)) {
-		dev_err(qup->dev, "Could not get iface clock\n");
-		return PTR_ERR(qup->pclk);
+		qup->pclk = devm_clk_get(qup->dev, "iface");
+		if (IS_ERR(qup->pclk)) {
+			dev_err(qup->dev, "Could not get iface clock\n");
+			return PTR_ERR(qup->pclk);
+		}
+		qup_i2c_enable_clocks(qup);
+		src_clk_freq = clk_get_rate(qup->clk);
 	}
 
-	qup_i2c_enable_clocks(qup);
-
 	/*
 	 * Bootloaders might leave a pending interrupt on certain QUP's,
 	 * so we reset the core before registering for interrupts.
@@ -1514,7 +1534,6 @@ nodma:
 	size = QUP_INPUT_FIFO_SIZE(io_mode);
 	qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
 
-	src_clk_freq = clk_get_rate(qup->clk);
 	fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
 	hs_div = 3;
 	qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
@@ -1639,6 +1658,14 @@ static const struct of_device_id qup_i2c_dt_match[] = {
 };
 MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
 
+#if IS_ENABLED(CONFIG_ACPI)
+static const struct acpi_device_id qup_i2c_acpi_match[] = {
+	{ "QCOM8010"},
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_ids);
+#endif
+
 static struct platform_driver qup_i2c_driver = {
 	.probe  = qup_i2c_probe,
 	.remove = qup_i2c_remove,
@@ -1646,6 +1673,7 @@ static struct platform_driver qup_i2c_driver = {
 		.name = "i2c_qup",
 		.pm = &qup_i2c_qup_pm_ops,
 		.of_match_table = qup_i2c_dt_match,
+		.acpi_match_table = ACPI_PTR(qup_i2c_acpi_match),
 	},
 };
 
-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.



From austinwc at codeaurora.org  Thu May 26 12:37:57 2016
From: austinwc at codeaurora.org (Austin Christ)
Date: Thu, 26 May 2016 13:37:57 -0600
Subject: [PATCH 2/2][v4] i2c: qup: support SMBus block read
In-Reply-To: <1464291477-4705-1-git-send-email-austinwc@codeaurora.org>
References: <1464291477-4705-1-git-send-email-austinwc@codeaurora.org>
Message-ID: <1464291477-4705-2-git-send-email-austinwc@codeaurora.org>

From: Naveen Kaje <nkaje at codeaurora.org>

I2C QUP driver relies on SMBus emulation support from the framework.
To handle SMBus block reads, the driver should check I2C_M_RECV_LEN
flag and should read the first byte received as the message length.

The driver configures the QUP hardware to read one byte. Once the
message length is known from this byte, the QUP hardware is configured
to read the rest.

Signed-off-by: Naveen Kaje <nkaje at codeaurora.org>
Signed-off-by: Austin Christ <austinwc at codeaurora.org>
---
 drivers/i2c/busses/i2c-qup.c | 68 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 65 insertions(+), 3 deletions(-)

Changes:
-v4:
 - correct error code
- v3:
 - clean up redundant checks
 - use constant instead of variable for smbus length field
- v2:
 - rework the smbus block read and break into separate function

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index ea6ca5f..576320f 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -517,6 +517,33 @@ static int qup_i2c_get_data_len(struct qup_i2c_dev *qup)
 	return data_len;
 }
 
+static bool qup_i2c_check_msg_len(struct i2c_msg *msg)
+{
+	return ((msg->flags & I2C_M_RD) && (msg->flags & I2C_M_RECV_LEN));
+}
+
+static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev *qup,
+			struct i2c_msg *msg)
+{
+	int len = 0;
+
+	if (msg->len > 1) {
+		tags[len++] = QUP_TAG_V2_DATARD_STOP;
+		tags[len++] = qup_i2c_get_data_len(qup) - 1;
+	} else {
+		tags[len++] = QUP_TAG_V2_START;
+		tags[len++] = addr & 0xff;
+
+		if (msg->flags & I2C_M_TEN)
+			tags[len++] = addr >> 8;
+
+		tags[len++] = QUP_TAG_V2_DATARD;
+		/* Read 1 byte indicating the length of the SMBus message */
+		tags[len++] = 1;
+	}
+	return len;
+}
+
 static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
 			    struct i2c_msg *msg,  int is_dma)
 {
@@ -526,6 +553,10 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
 
 	int last = (qup->blk.pos == (qup->blk.count - 1)) && (qup->is_last);
 
+	/* Handle tags for SMBus block read */
+	if (qup_i2c_check_msg_len(msg))
+		return qup_i2c_set_tags_smb(addr, tags, qup, msg);
+
 	if (qup->blk.pos == 0) {
 		tags[len++] = QUP_TAG_V2_START;
 		tags[len++] = addr & 0xff;
@@ -1065,9 +1096,17 @@ static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
 				struct i2c_msg *msg)
 {
 	u32 val;
-	int idx, pos = 0, ret = 0, total;
+	int idx, pos = 0, ret = 0, total, msg_offset = 0;
 
+	/*
+	 * If the message length is already read in
+	 * the first byte of the buffer, account for
+	 * that by setting the offset
+	 */
+	if (qup_i2c_check_msg_len(msg) && (msg->len > 1))
+		msg_offset = 1;
 	total = qup_i2c_get_data_len(qup);
+	total -= msg_offset;
 
 	/* 2 extra bytes for read tags */
 	while (pos < (total + 2)) {
@@ -1087,8 +1126,8 @@ static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,
 
 			if (pos >= (total + 2))
 				goto out;
-
-			msg->buf[qup->pos++] = val & 0xff;
+			msg->buf[qup->pos + msg_offset] = val & 0xff;
+			qup->pos++;
 		}
 	}
 
@@ -1128,6 +1167,24 @@ static int qup_i2c_read_one_v2(struct qup_i2c_dev *qup, struct i2c_msg *msg)
 			goto err;
 
 		qup->blk.pos++;
+
+		/* Handle SMBus block read length */
+		if (qup_i2c_check_msg_len(msg) && (msg->len == 1)) {
+			if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
+				ret = -EPROTO;
+				goto err;
+			}
+			msg->len += msg->buf[0];
+			qup->pos = 0;
+			qup_i2c_set_read_mode_v2(qup, msg->len);
+			ret = qup_i2c_issue_xfer_v2(qup, msg);
+			if (ret)
+				goto err;
+			ret = qup_i2c_wait_for_complete(qup, msg);
+			if (ret)
+				goto err;
+			qup_i2c_set_blk_data(qup, msg);
+		}
 	} while (qup->blk.pos < qup->blk.count);
 
 err:
@@ -1210,6 +1267,11 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
 			goto out;
 		}
 
+		if (qup_i2c_check_msg_len(&msgs[idx])) {
+			ret = -EINVAL;
+			goto out;
+		}
+
 		if (msgs[idx].flags & I2C_M_RD)
 			ret = qup_i2c_read_one(qup, &msgs[idx]);
 		else
-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.



From davem at davemloft.net  Thu May 26 12:43:44 2016
From: davem at davemloft.net (David Miller)
Date: Thu, 26 May 2016 12:43:44 -0700 (PDT)
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160526142057.GA7456@e104818-lin.cambridge.arm.com>
References: <6407614.fdv5XFSBue@wuerfel>
 <20160525.142821.1719403997976778673.davem@davemloft.net>
 <20160526142057.GA7456@e104818-lin.cambridge.arm.com>
Message-ID: <20160526.124344.1660236473079504674.davem@davemloft.net>

From: Catalin Marinas <catalin.marinas at arm.com>
Date: Thu, 26 May 2016 15:20:58 +0100

> We can solve (a) by adding more __SC_WRAP annotations in the generic
> unistd.h.
 ...

I really think it's much more robust to clear the tops of the registers
by default.  Then you won't be auditing constantly and adding more and
more wrappers.

You can't even quantify the performance gains for me in any precise
way.  Whatever you gain by avoiding the 64-bit
decompostion/reconstitution for those few system calls with 64-bit
registers, you are losing by calling the wrappers for more common
system calls, more often.

"it's more natural to pass 64-bit values in a register" is not a clear
justification for this change.

This looks way over engineered to me.


From vz at mleia.com  Thu May 26 12:48:01 2016
From: vz at mleia.com (Vladimir Zapolskiy)
Date: Thu, 26 May 2016 22:48:01 +0300
Subject: DT description of SRAM with power manageable banks
In-Reply-To: <CAL_Jsq+R8E7UwAW+aUcmHPhgMS0D39C77kxgqwLK0_kTWHkWFw@mail.gmail.com>
References: <57473709.1020108@mleia.com>
 <CAL_Jsq+R8E7UwAW+aUcmHPhgMS0D39C77kxgqwLK0_kTWHkWFw@mail.gmail.com>
Message-ID: <574752F1.6010408@mleia.com>

Hi Rob,

On 26.05.2016 21:30, Rob Herring wrote:
> On Thu, May 26, 2016 at 12:48 PM, Vladimir Zapolskiy <vz at mleia.com> wrote:
>> Hi DT team,
>>
>> let me ask you for advice how to extend a common "mmio-sram" compatible
>> binding description with information about power manageable banks,
>> which are specific to some SRAM. My main interest is to give a better
>> support of NXP LPC32xx SRAM, but as far as I know it concerns other
>> controllers from the LPC series, and maybe some other ones.
>>
>> Taking a simple visual example let's consider NXP LPC3250 SRAM, which
>> has four banks, three of them has independent power controls:
>>
>>         0x00000 - 0x0ffff (64KiB), always on-power bank,
>>         0x10000 - 0x1ffff (64KiB), power manageable bank
>>         0x20000 - 0x2ffff (64KiB), power manageable bank
>>         0x30000 - 0x3ffff (64KiB), power manageable bank
>>
>> All banks together form a single continuous address space, and it seems
>> important to have just one SRAM device and not 4, since e.g. in normal
>> runtime operation continuous 100KiB from the whole SRAM area are reserved
>> for storing MAC RX/TX buffers, it won't fit into one bank, however in
>> sleep mode (or when there is no users of some SRAM banks in runtime)
>> it is desirable to turn off unused banks, thus there should be a connection
>> between each power manageable bank and some power domain like this:
>>
>>         sram_pd: power-controller at 110 {
>>                 compatible = "nxp,lpc3220-pos";
>>                 reg = <0x110 0x8>;
>>                 #power-domain-cells = <1>;
>>         };
>>
>> ...
>>
>>         sram-bank at 08010000 {
>>                 reg = <0x08010000 0x10000>;
>>                 power-domains = <&sram_pd 0>;
>>         };
>>
>> ...
>>
>> The ordinary SRAM device node looks like
>>
>>         sram at 08000000 {
>>                 compatible = "mmio-sram";
>>                 reg = <0x08000000 0x40000>;
>>         };
>>
>> and I would happy to have it just like that, and actually it works
>> perfectly, if the problem with delicate power management is ignored.
>> At least it demonstrates that a generic wide compatible "mmio-sram"
>> suits well here.
>>
>> The problem I face is in setting a proper layout of "sram@" and three
>> "sram-bank@" device nodes (remember 1 of 4 banks has no power control).
>> Unfortunately "sram-bank@" device nodes can not be children of "sram@",
>> because children of "mmio-sram" compatible device node play a role
>> of reserved areas ("partitions"), and that's not what I want. Moreover
>> reserved areas and power manageable banks are orthogonal, for instance
>> one reserved area may overlap with two power manageable banks or
>> vice versa.
>>
>> Questions I have concerning this case:
>>
>> 1) would it be correct to add the second compatible like this?
>>
>>         sram at 08000000 {
>>                 compatible = "mmio-sram", "nxp,lpc3220-sram";
> 
> Yes, but reverse the order. Most specific first.
> 

Ok, thank you for correction.

>>                 reg = <0x08000000 0x40000>;
> 
> You can just add a single property like this:
> 
> power-domains = <&sram_pd 0>, <&sram_pd 1>, <&sram_pd 2>;
> 

Two notes regarding this.

1) either due to a bug/misfeature in Linux or intentionally power-domains
property handling doesn't accept multiple values, nor there are examples
of power-domains set to an array.

Of course it is quite trivial to extend, but here I want to get a
formal confirmation from DT and/or PM guys, that power-domains of one
device can contain links to several power domains.

2) in general usage of array of values assumes a presence of *-names
property, which might be better to avoid. As an artificial example
by some reason on a board someone would like to control power of
a subset of banks (or whatever device in general):

  power-domains = <&pd 0>, <&pd 2>;

Without power-domains-names or similar property it might be difficult
to describe this case, and I feel reluctant to introduce or anticipate
introduction of power-domains-names property, especially because
so far everyone is happy with just one power domain per device.

> The knowledge of what range each PD controls is encoded in the fact
> that the node is a "nxp,lpc3220-sram" and the information would stay
> in your driver.
> 
> Of course, if there's a lot of variation in sizes and domains, we may
> want to fully describe things in the DT.
> 
>>         };
>>
>> Or should I add the new compatible to device nodes of each of the power
>> manageable banks?
>>
>> 2) I assume that "sram-bank@" device nodes still should be descendants
>> of "sram@" node, but because children with "reg" property of "mmio-sram"
>> compatible device node can not be used to describe power manageable banks,
>> what name for an umbrella device node would you suggest? Would "banks" be
>> good enough? Should it have its own compatible?
> 
> I don't think you need all this, but in general you want to have
> compatible strings in each node (though there are many exceptions).
> 

If power-domains accepts only one value intentionally, then probably
every bank should have its own compatible, again not sure if it is
done by design, but in Linux PM domain consumers are devices only,
device implies own compatible, and, I don't know, in that case (one PM domain
per device) should I convert MMIO SRAM to a simple bus then?

>> 3) Do you think that reserved areas nodes should be placed under their
>> own device node with probably own compatible? So, something like it
>> was done recently with MTD partitions (compatible = "fixed-partitions").
> 
> If we did go down the path of have 2 sets of ranges, then yes.
> 

Please feel free to invite anyone to the discussion, who can advise/ack/nack
a soft conversion change of the currently accepted scheme for reserved
partitions to a potentially new one.

--
With best wishes,
Vladimir


From hdegoede at redhat.com  Thu May 26 13:25:05 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Thu, 26 May 2016 22:25:05 +0200
Subject: [PATCH] reset: Put back *_optional variants
In-Reply-To: <ca359e013c30f27c825a9580164b01da5ca6476d.1464224883.git.johnyoun@synopsys.com>
References: <ca359e013c30f27c825a9580164b01da5ca6476d.1464224883.git.johnyoun@synopsys.com>
Message-ID: <12e450f0-70ea-29f8-0bf7-8a0697263f2d@redhat.com>

Hi,

On 26-05-16 03:15, John Youn wrote:
> Prior to commit 6c96f05c8bb8 ("reset: Make [of_]reset_control_get[_foo]
> functions wrappers"), the optional variants returned -ENOTSUPP when
> CONFIG_RESET_CONTROLLER was not set. This patch reverts to this
> behavior. Otherwise those calls will return -EINVAL causing users to
> think that an error occurred when CONFIG_RESET_CONTROLLER is not set.
>
> Fixes: 6c96f05c8bb8 ("reset: Make [of_]reset_control_get[_foo] functions wrappers")
> Signed-off-by: John Youn <johnyoun at synopsys.com>
> ---
>
> Hi Philipp, Hans,
>
> The commit referenced above breaks an upcoming patch for the dwc2
> driver that adds an optional reset control.
>
> https://marc.info/?l=linux-usb&m=146161328211584&w=2
>
> I've attempted to add the optional variants back the way they were
> working before. Let me know if I need to do anything else to fix it or
> if it should be done another way.
>
> Regards,
> John

Hmm, I don't like all the extra code your patch adds just to fix
a return value...

Looking at the code before my "reset: Make [of_]reset_control_get[_foo]
functions wrappers" patch, all the dev*_get* functions were
returning ENOTSUPP except for [devm_]reset_control_get, so following
your logic we should also change the of_reset_control_get_by_index
variant to return -ENOTSUP.

Or better, simply make them all return -ENOTSUP, that seems both
consistent and more KISS to me, this would mean an error code
change for [devm_]reset_control_get, but will fix all the other
getters from having a changed error-code, and I would callers
of [devm_]reset_control_get to not care which error code they
get, except for -EPROBE_DEFER.

So IMHO the following change would be a better way to fix this:

--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -65,14 +65,14 @@ static inline struct reset_control *__of_reset_control_get(
                                         struct device_node *node,
                                         const char *id, int index, int shared)
  {
-   return ERR_PTR(-EINVAL);
+ return ERR_PTR(-ENOTSUPP);
  }

  static inline struct reset_control *__devm_reset_control_get(
                                         struct device *dev,
                                         const char *id, int index, int shared)
  {
-   return ERR_PTR(-EINVAL);
+ return ERR_PTR(-ENOTSUPP);
  }

  #endif /* CONFIG_RESET_CONTROLLER */



Regards,

Hans



>
>  include/linux/reset.h | 33 +++++++++++++++++++++++++++++++--
>  1 file changed, 31 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/reset.h b/include/linux/reset.h
> index ec0306ce..739d33d 100644
> --- a/include/linux/reset.h
> +++ b/include/linux/reset.h
> @@ -14,10 +14,24 @@ int reset_control_status(struct reset_control *rstc);
>
>  struct reset_control *__of_reset_control_get(struct device_node *node,
>  				     const char *id, int index, int shared);
> +
> +struct reset_control *__of_reset_control_get_optional(struct device_node *node,
> +				     const char *id, int index, int shared)
> +{
> +	return __of_reset_control_get(node, id, index, shared);
> +}
> +
>  void reset_control_put(struct reset_control *rstc);
>  struct reset_control *__devm_reset_control_get(struct device *dev,
>  				     const char *id, int index, int shared);
>
> +static inline struct reset_control *__devm_reset_control_get_optional(
> +					struct device *dev,
> +					const char *id, int index, int shared)
> +{
> +	return __devm_reset_control_get(dev, id, index, shared);
> +}
> +
>  int __must_check device_reset(struct device *dev);
>
>  static inline int device_reset_optional(struct device *dev)
> @@ -74,6 +88,13 @@ static inline struct reset_control *__of_reset_control_get(
>  	return ERR_PTR(-EINVAL);
>  }
>
> +static inline struct reset_control *__of_reset_control_get_optional(
> +					struct device_node *node,
> +					const char *id, int index, int shared)
> +{
> +	return ERR_PTR(-ENOTSUPP);
> +}
> +
>  static inline struct reset_control *__devm_reset_control_get(
>  					struct device *dev,
>  					const char *id, int index, int shared)
> @@ -81,6 +102,13 @@ static inline struct reset_control *__devm_reset_control_get(
>  	return ERR_PTR(-EINVAL);
>  }
>
> +static inline struct reset_control *__devm_reset_control_get_optional(
> +					struct device *dev,
> +					const char *id, int index, int shared)
> +{
> +	return ERR_PTR(-ENOTSUPP);
> +}
> +
>  #endif /* CONFIG_RESET_CONTROLLER */
>
>  /**
> @@ -110,7 +138,8 @@ static inline struct reset_control *__must_check reset_control_get(
>  static inline struct reset_control *reset_control_get_optional(
>  					struct device *dev, const char *id)
>  {
> -	return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 0);
> +	return __of_reset_control_get_optional(dev ? dev->of_node : NULL,
> +					       id, 0, 0);
>  }
>
>  /**
> @@ -194,7 +223,7 @@ static inline struct reset_control *__must_check devm_reset_control_get(
>  static inline struct reset_control *devm_reset_control_get_optional(
>  					struct device *dev, const char *id)
>  {
> -	return __devm_reset_control_get(dev, id, 0, 0);
> +	return __devm_reset_control_get_optional(dev, id, 0, 0);
>  }
>
>  /**
>


From nleeder at codeaurora.org  Thu May 26 13:38:48 2016
From: nleeder at codeaurora.org (Neil Leeder)
Date: Thu, 26 May 2016 16:38:48 -0400
Subject: [PATCH] soc: qcom: provide mechanism for drivers to access L2
 registers
In-Reply-To: <20160526044810.GW1256@tuxbot>
References: <1463771587-7438-1-git-send-email-nleeder@codeaurora.org>
 <20160523172527.GK4976@leverpostej>
 <f49d58ed-38b4-6284-11c2-8708d8443b14@codeaurora.org>
 <20160524112326.GC25374@leverpostej>
 <e0173486-896e-4897-702a-ccd1c1f6c609@codeaurora.org>
 <20160526044810.GW1256@tuxbot>
Message-ID: <3b834d0f-dc8e-86da-0bbd-f7ec72618f5d@codeaurora.org>



On 5/26/2016 12:48 AM, Bjorn Andersson wrote:
> On Tue 24 May 12:54 PDT 2016, Neil Leeder wrote:
> 
>>
>>
>> On 5/24/2016 07:23 AM, Mark Rutland wrote:
>>> On Mon, May 23, 2016 at 02:22:59PM -0400, Neil Leeder wrote:
>>>>
>>>> On 5/23/2016 01:25 PM, Mark Rutland wrote:
>>>>> On Fri, May 20, 2016 at 03:13:07PM -0400, Neil Leeder wrote:
>>
>>>>>> Signed-off-by: Neil Leeder <nleeder at codeaurora.org>
>>>>>> ---
>>>>>>  drivers/soc/qcom/Kconfig              |  9 +++++
>>>>>>  drivers/soc/qcom/Makefile             |  1 +
>>>>>>  drivers/soc/qcom/l2-accessors.c       | 66 +++++++++++++++++++++++++++++++++++
>>>>>>  include/linux/soc/qcom/l2-accessors.h | 27 ++++++++++++++
>>>>>>  4 files changed, 103 insertions(+)
>>>>>>  create mode 100644 drivers/soc/qcom/l2-accessors.c
>>>>>>  create mode 100644 include/linux/soc/qcom/l2-accessors.h
>>>>>
>>>>> These are awfully generic file names (and function names). Which SoCs
>>>>> does this apply to?
>>>>>
>>>>> It would be good to give these more specific names.
>>>>
>>>> It's under soc/qcom, and dependent on ARCH_QCOM and (in v2) also on ARM64. It applies to all QCOM ARM64 SoCs.
>>>
>>> Per Christopher's comment, it sounds like this applies to QDF24xx.
>>>
>>> Given that the code uses IMPLEMENTATION DEFINED system registers, I
>>> presume that this does not apply to MSM8916 which uses Cortex-A53, for
>>> example (though perhaps it does, and I am mistaken).
>>>
>>>> Given that it can only be used in a QCOM driver, and the include path has qcom in it, I'd
>>>> prefer not to add redundancy by adding another qcom in there.
>>>
>>> I'm not asking for another "qcom", but simply the SoC variant or family
>>> (e.g. "qdf24xx" would be fine).
>>>
>>
>> It applies to all ARMv8 SoCs with QCOM processors in them. So QDF24xx
>> and mobile 820, but not SoCs with ARM processors in them such as
>> MSM8916. So neither msm_ nor qdf_ are accurate prefixes.
> 
> What's the code name for the SoC in QDF24xx? The 820 is Kryo, is it the
> same core in QDF24xx or does that have some other name.
> 
> We should try to pick something adding value, not adding another generic
> thing.

There is currently no public name for the QDF24xx core.

> 
>> As Timur pointed out, the majority of source files in drivers/soc/qcom
>> don't have any prefix, which is a reason why I didn't include one.
>>
> 
> There's no reason to add a generic "qcom" to the qcom folder, if
> anything we should drop the "qcom" prefix of the only one in there.
> 
> Regards,
> Bjorn
> 

Neil

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


From ynorov at caviumnetworks.com  Thu May 26 13:48:19 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Thu, 26 May 2016 23:48:19 +0300
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160525.142821.1719403997976778673.davem@davemloft.net>
References: <6293194.tGy03QJ9ME@wuerfel>
 <20160525.135039.244098606649448826.davem@davemloft.net>
 <6407614.fdv5XFSBue@wuerfel>
 <20160525.142821.1719403997976778673.davem@davemloft.net>
Message-ID: <20160526204819.GA10274@yury-N73SV>

On Wed, May 25, 2016 at 02:28:21PM -0700, David Miller wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> Date: Wed, 25 May 2016 23:01:06 +0200
> 
> > On Wednesday, May 25, 2016 1:50:39 PM CEST David Miller wrote:
> >> From: Arnd Bergmann <arnd at arndb.de>
> >> Date: Wed, 25 May 2016 22:47:33 +0200
> >> 
> >> > If we use the normal calling conventions, we could remove these overrides
> >> > along with the respective special-case handling in glibc. None of them
> >> > look particularly performance-sensitive, but I could be wrong there.
> >> 
> >> You could set the lowest bit in the system call entry pointer to indicate
> >> the upper-half clears should be elided.
> > 
> > Right, but that would introduce an extra conditional branch in the syscall
> > hotpath, and likely eliminate the gains from passing the loff_t arguments
> > in a single register instead of a pair.
> 
> Ok, then, how much are you really gaining from avoiding a 'shift' and
> an 'or' to build the full 64-bit value?  3 cycles?  Maybe 4?

4 cycles in kernel and ~same cost in glibc to create a pair. And 8
'mov's that exist for every syscall, even yield().

> And the executing the wrappers, those have a non-trivial cost too.

The cost is pretty trivial though. See kernel/compat_wrapper.o:
COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
0:   a9bf7bfd        stp     x29, x30, [sp,#-16]!
4:   910003fd        mov     x29, sp
8:   2a0003e0        mov     w0, w0
c:   94000000        bl      0 <sys_creat>
10:  a8c17bfd        ldp     x29, x30, [sp],#16
14:  d65f03c0        ret

> Cost wise, this seems like it all cancels out in the end, but what
> do I know?

I think you know something, and I also think Heiko and other s390 guys
know something as well. So I'd like to listen their arguments here.

For me spark64 way is looking reasonable only because it's really simple
and takes less coding. I'll try it on some branch and share here what happened.


From dhdang at apm.com  Thu May 26 13:49:23 2016
From: dhdang at apm.com (Duc Dang)
Date: Thu, 26 May 2016 13:49:23 -0700
Subject: [PATCH] PCI/MSI: pci-xgene-msi: Enable MSI support in ACPI boot
 for X-Gene v1
In-Reply-To: <20160526123459.GA23794@red-moon>
References: <1455069384-22323-1-git-send-email-dhdang@apm.com>
 <1456330151.5681.46.camel@redhat.com> <56CDD767.6020103@arm.com>
 <CADaLND=mrkxOWOzcEb8os16Rb=SDHfnn_8eSgB4bQYH3UguS3w@mail.gmail.com>
 <20160225173822.GA6349@red-moon>
 <CADaLNDnywVPER9QhmK4C6JyCLhta_M_cVSOuSkEHnmnLPFo3JA@mail.gmail.com>
 <20160526123459.GA23794@red-moon>
Message-ID: <CADaLNDnf8SRbUkBN9fZMvrvsnTQs+DLyqnZfVpWqVyyY8Hk=1Q@mail.gmail.com>

Hi Lorenzo,

On Thu, May 26, 2016 at 5:34 AM, Lorenzo Pieralisi
<lorenzo.pieralisi at arm.com> wrote:
> Hi Duc,
>
> On Wed, May 25, 2016 at 04:13:35PM -0700, Duc Dang wrote:
>> On Thu, Feb 25, 2016 at 9:38 AM, Lorenzo Pieralisi
>> <lorenzo.pieralisi at arm.com> wrote:
>> > On Wed, Feb 24, 2016 at 02:28:10PM -0800, Duc Dang wrote:
>> >> On Wed, Feb 24, 2016 at 8:16 AM, Marc Zyngier <marc.zyngier at arm.com> wrote:
>> >> > On 24/02/16 16:09, Mark Salter wrote:
>> >> >> On Tue, 2016-02-09 at 17:56 -0800, Duc Dang wrote:
>> >> >>> This patch makes pci-xgene-msi driver ACPI-aware and provides
>> >> >>> MSI capability for X-Gene v1 PCIe controllers in ACPI boot mode.
>> >> >>>
>> >> >>> Signed-off-by: Duc Dang <dhdang at apm.com>
>> >> >>> ---
>> >> >>>  drivers/pci/host/pci-xgene-msi.c | 35 ++++++++++++++++++++++++++++++++---
>> >> >>>  1 file changed, 32 insertions(+), 3 deletions(-)
>> >> >>>
>> >> >>> diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c
>> >> >>> index a6456b5..466aa93 100644
>> >> >>> --- a/drivers/pci/host/pci-xgene-msi.c
>> >> >>> +++ b/drivers/pci/host/pci-xgene-msi.c
>> >> >>> @@ -24,6 +24,7 @@
>> >> >>>  #include <linux/pci.h>
>> >> >>>  #include <linux/platform_device.h>
>> >> >>>  #include <linux/of_pci.h>
>> >> >>> +#include <linux/acpi.h>
>> >> >>>
>> >> >>>  #define MSI_IR0                     0x000000
>> >> >>>  #define MSI_INT0            0x800000
>> >> >>> @@ -39,7 +40,7 @@ struct xgene_msi_group {
>> >> >>>  };
>> >> >>>
>> >> >>>  struct xgene_msi {
>> >> >>> -    struct device_node      *node;
>> >> >>> +    struct fwnode_handle    *fwnode;
>> >> >>>      struct irq_domain       *inner_domain;
>> >> >>>      struct irq_domain       *msi_domain;
>> >> >>>      u64                     msi_addr;
>> >> >>> @@ -249,6 +250,13 @@ static const struct irq_domain_ops msi_domain_ops = {
>> >> >>>      .free   = xgene_irq_domain_free,
>> >> >>>  };
>> >> >>>
>> >> >>> +#ifdef CONFIG_ACPI
>> >> >>> +static struct fwnode_handle *xgene_msi_get_fwnode(struct device *dev)
>> >> >>> +{
>> >> >>> +    return xgene_msi_ctrl.fwnode;
>> >> >>> +}
>> >> >>> +#endif
>> >> >>> +
>> >> >>>  static int xgene_allocate_domains(struct xgene_msi *msi)
>> >> >>>  {
>> >> >>>      msi->inner_domain = irq_domain_add_linear(NULL, NR_MSI_VEC,
>> >> >>> @@ -256,7 +264,7 @@ static int xgene_allocate_domains(struct xgene_msi *msi)
>> >> >>>      if (!msi->inner_domain)
>> >> >>>              return -ENOMEM;
>> >> >>>
>> >> >>> -    msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(msi->node),
>> >> >>> +    msi->msi_domain = pci_msi_create_irq_domain(msi->fwnode,
>> >> >>>                                                  &xgene_msi_domain_info,
>> >> >>>                                                  msi->inner_domain);
>> >> >>
>> >> >> This doesn't work for me (ACPI probing on Mustang) unless I change this
>> >> >> to be pci_msi_create_default_irq_domain(). The problem seems to be that
>> >> >> the MSI probe happens after the PCIe RC is probed so there is no MSI domain
>> >> >> at the time the PCIe root is initialized by ACPI.
>> >> >
>> >> > pci_msi_create_default_irq_domain is the wrong thing do use, specially
>> >> > if you have multiple MSI controllers in the system. I certainly wouldn't
>> >> > want to see it being used on arm64.
>> >> >
>> >> > This is the usual dependency hell. You try moving the probing earlier,
>> >> > but that may break something else in the process.
>> >>
>> >> Hi Mark and Marc,
>> >>
>> >> I have modified Tianocore firmware to have MSI node declared before
>> >> PCIe node in Dsdt table. With this modification, the MSI driver will
>> >> be loaded before PCIe driver and MSI domain is available at the time
>> >> PCIe root is initialized.
>> >
>> > I am totally against this. We should not hack ACPI tables to make
>> > the kernel work (on top of that with unwritten ordering rules that may
>> > well require changes as kernel evolves), we should have a standard set
>> > of bindings that people use to describe HW in the DSDT and the kernel(s)
>> > has to cope with that. If there is a dependency problem in the description
>> > we may solve it at bindings level, but I absolutely do not want to rely
>> > on DSDT nodes ordering for things to work, that's fragile, no shortcuts
>> > please.
>>
>> Hi Lorenzo, Bjorn,
>>
>> (Refresh this thread on this merge cycle)
>>
>> I tried to use _DEP method to describe the dependency of PCIe node to
>> MSI node but it turns out that PCIe driver does not check for the
>> dependency (only EC (ec.c) and I2C core (i2c-core.c) use
>> acpi_walk_dep_device_list to check for dependency before loading
>> dependent drivers)
>>
>> Do you have other suggestion/example about how to ensure strict
>> ordering on driver loading in ACPI boot mode without changing the
>> order of ACPI nodes in DSDT?
>
> Before doing anything else, I would like to ask you to report the code
> paths leading to failures (what fails actually ?) please, and I want
> to understand what "this does not work" means.
>
> In particular:
>
> - Why using pci_msi_create_default_irq_domain() works
> - Why, if you change the DSDT nodes ordering, things work (please add
>   some debugging to MSI allocation functions to detect the code paths
>   leading to correct MSI allocation)
> - What's the difference wrt the DT probe path

The MSI allocation happens with following code path (I use PMC pm80xx
SAS driver as an example (drivers/scsi/pm8001/pm8001_init.c)):
pci_enable_msix_exact
    pci_enable_msix_range
        pci_enable_msix
            msix_capbility_init
                pci_msi_setup_msi_irqs
                    pci_msi_get_domain
                        dev_get_msi_domain
                        arch_get_pci_msi_domain
                            return pci_msi_default_domain;

In my failing case: pci_msi_get_domain return NULL, so MSI allocation
function (pci_enable_msix_exact) fails.

The expected MSI domain is registered when X-Gene MSI driver is
initialized and is attached to each PCI bus by calling
pci_set_bus_msi_domain during PCIe bus-scan:
pci_scan_root_bus
    pci_scan_root_bus_msi
        pci_scan_child_bus
            pci_scan_bridge
                pci_add_new_bus
                    pci_alloc_child_bus
                        pci_set_bus_msi_domain
                            pci_host_bridge_msi_domain
                                pci_host_bridge_of_msi_domain
                                pci_host_bridge_acpi_msi_domain

+ When booting with DT: X-Gene MSI driver is initialized early
(subsys_initcall level); X-Gene PCIe driver is initialized later at
device_initcall level (using module_platform_driver). Because of that
when PCIe enumeration happens, the X-Gene MSI domain was already
registered and available. So when the driver of PCIe Endpoint devices
gets loaded, the call to pci_enable_msix_exact (to allocate MSI)
succeeds.

+ When booting with ACPI: acpi_scan_init is called at subsys_initcall
level (the same level with X-Gene MSI driver):
acpi_init
    acpi_bus_init (GIC is initialized here)
        acpi_scan_init
            acpi_pci_root_init
            acpi_pci_link_init
            ...
            acpi_bus_scan
                acpi_bus_check_add
 ...

Currently, in DSDT table, X-Gene MSI node is defined right after
X-Gene PCIe nodes. So PCIe driver initialization and PCIe enumeration
happens before MSI driver is initialized. During PCIe bus scan, the
pci_set_bus_msi_domain gets a NULL  irq_domain value from
pci_host_bridge_msi_domain (as MSI driver is not initialized), so
there is no MSI support for PCIe bus.

+ Using pci_msi_create_default_irq_domain() helps MSI allocation
succeed as pci_msi_get_domain (in the code path of
pci_enable_msix_exact above) can fall back to get a valid domain from
arch_get_pci_msi_domain (please note that PCIe endpoint driver gets
called later (at device_initcall level (using module_init)), so at the
time PCIe endpoint driver probe function executes, the MSI driver
already register the global MSI domain with
pci_msi_create_default_irq_domain)

+ If changing DSDT node ordering, to define MSI node before PCIe
nodes, then X-Gene MSI driver will be loaded before PCIe host driver.
At the time PCIe enumeration happens, X-Gene MSI driver already
registered a valid MSI domain (by calling
pci_msi_register_fwnode_provider to register the fwnode provider
function), so all the detected PCIe buses (and PCIe endpoint devices)
will have a valid MSI domain attached to them (as a result of function
pci_set_bus_msi_domain)

Regards,
Duc Dang.
>
> When we have a detailed view of MSI allocation code paths and failures
> we can see what we can do to fix it in ACPI.
>
> Thanks,
> Lorenzo


From khilman at baylibre.com  Thu May 26 14:05:50 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Thu, 26 May 2016 14:05:50 -0700
Subject: [PATCH 0/7] pinctrl: meson: Add a bunch more pins
In-Reply-To: <CACRpkdbURowJNT_ZkKuv7C_3oW3BJGPBK6etKc4cBc4ujQdPXw@mail.gmail.com>
 (Linus Walleij's message of "Thu, 26 May 2016 11:28:44 +0200")
References: <1462544486-9516-1-git-send-email-khilman@baylibre.com>
 <CACRpkdY9oGZLt431NwTaFmZk98O8n3ZnMA1odhYZtcH7P1p=Jg@mail.gmail.com>
 <m260u3ia37.fsf@baylibre.com>
 <CACRpkdbURowJNT_ZkKuv7C_3oW3BJGPBK6etKc4cBc4ujQdPXw@mail.gmail.com>
Message-ID: <m21t4ofs29.fsf@baylibre.com>

Linus Walleij <linus.walleij at linaro.org> writes:

> On Tue, May 24, 2016 at 8:29 PM, Kevin Hilman <khilman at baylibre.com> wrote:
>> Linus Walleij <linus.walleij at linaro.org> writes:
>
>> Looking closer, these have dependencies on the DT changes that you've
>> suggested we take through arm-soc, so it would be cleaner if I take
>> these with your ack through the amlogic tree.
>
> I really prefer to take DT changes and driver code in different
> trees i possible.
>
> My reasoning is plainly: if the DT stuff was a separate git, as
> has been explicitly suggested as a goal off and on, this should
> be merge:able still. So DT changes and driver code should ideally
> be orthogonal.
>
> I don't know about this case but is it a disaster if one or the other
> of the DT changes and the driver arrive in different order to Torvald's
> tree, or will it simply be that the lights go on when the last patch
> arrives?

Actually, it wasn't about built/boot dependencies but rather one of the
patches (mistakenly) had both a pinctrl change and a DT change, so a
simple rebase failed (and I gave up early since I was busy with
something else... and also lazy.)

Anyways, I've now separated things, so the pinctrl patches can go
through your tree, and we'll submit the rest (DT, kconfig etc.)  through
arm-soc, and things will "just work" when they both land in mainline.

I'll repost the series shortly, but if you prefer to just pull, the
pinctrl-only stuff based on linus/master is here:

git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux.git amlogic/v4.7/pinctrl-drv

Thanks for the nudge in the right direction,

Kevin


From ynorov at caviumnetworks.com  Thu May 26 14:08:13 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Fri, 27 May 2016 00:08:13 +0300
Subject: [PATCH 16/23] arm64: ilp32: introduce binfmt_ilp32.c
In-Reply-To: <5746FEF6.9070405@huawei.com>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
 <1464048292-30136-17-git-send-email-ynorov@caviumnetworks.com>
 <5746FEF6.9070405@huawei.com>
Message-ID: <20160526210813.GC10274@yury-N73SV>

On Thu, May 26, 2016 at 09:49:42PM +0800, Zhangjian (Bamvor) wrote:
> Hi, yury
> 
> The coredump is usable in our platform. It miss the following definition:
> +#define compat_elf_greg_t	elf_greg_t
> +#define compat_elf_gregset_t	elf_gregset_t
> 
> And it leads to the wrong register save in core dump. After apply this patch,
> gdb could debug core dump files.
> 
> Here is the full patch:
> From 102624840aa5dacdd1bbfe3b390290f52f530ea2 Mon Sep 17 00:00:00 2001
> From: Bamvor Jian Zhang <bamvor.zhangjian at huawei.com>
> Date: Thu, 26 May 2016 21:00:16 +0800
> Subject: [PATCH hulk-4.1-next] arm64: ilp32: fix coredump issue
> 
> ILP32 use aarch64 register and 32bit signal struct which means it
> could not make use of the existing compat_elf_prstatus/elf_prstatus
> and compat_elf_prpsinfo/elf_prpsinfo.
> 
> This patch fix this issue by introducing the different
> compat_elf_greg_t, compat_elf_gregset_t for aarch64 ilp32 and aarch32
> el0.
> 
> Tested pass on huawei's hardware in bigendian.
> 
> Signed-off-by: Bamvor Jian Zhang <bamvor.zhangjian at huawei.com>
> ---
>  arch/arm64/include/asm/elf.h     | 14 +++++++-------
>  arch/arm64/kernel/binfmt_elf32.c |  3 +++
>  arch/arm64/kernel/binfmt_ilp32.c |  8 +++++++-
>  arch/arm64/kernel/ptrace.c       | 20 ++++++++++----------
>  4 files changed, 27 insertions(+), 18 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
> index 0106d18..9019441 100644
> --- a/arch/arm64/include/asm/elf.h
> +++ b/arch/arm64/include/asm/elf.h
> @@ -154,18 +154,18 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
>  				       int uses_interp);
> 
>  /* 1GB of VA */
> -#define STACK_RND_MASK			(is_compat_task() ? \
> -						0x7ff >> (PAGE_SHIFT - 12) : \
> -						0x3ffff >> (PAGE_SHIFT - 12))
> +#define STACK_RND_MASK		(is_compat_task() ? \
> +					0x7ff >> (PAGE_SHIFT - 12) : \
> +					0x3ffff >> (PAGE_SHIFT - 12))
> 
>  #ifdef CONFIG_COMPAT
> 
> -#define COMPAT_ELF_ET_DYN_BASE		(2 * TASK_SIZE_32 / 3)
> +#define COMPAT_ELF_ET_DYN_BASE	(2 * TASK_SIZE_32 / 3)
> 
>  /* AArch32 registers. */
> -#define COMPAT_ELF_NGREG		18
> -typedef unsigned int			compat_elf_greg_t;
> -typedef compat_elf_greg_t		compat_elf_gregset_t[COMPAT_ELF_NGREG];
> +#define COMPAT_ELF_NGREG	18
> +typedef unsigned int		compat_a32_elf_greg_t;
> +typedef compat_a32_elf_greg_t	compat_a32_elf_gregset_t[COMPAT_ELF_NGREG];
> 
>  #endif /* CONFIG_COMPAT */
> 
> diff --git a/arch/arm64/kernel/binfmt_elf32.c b/arch/arm64/kernel/binfmt_elf32.c
> index 7b9b445..f75253c 100644
> --- a/arch/arm64/kernel/binfmt_elf32.c
> +++ b/arch/arm64/kernel/binfmt_elf32.c
> @@ -31,4 +31,7 @@ struct linux_binprm;
>  extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
>  				      int uses_interp);
> 
> +#define compat_elf_greg_t	compat_a32_elf_greg_t
> +#define compat_elf_gregset_t	compat_a32_elf_gregset_t
> +
>  #include "../../../fs/compat_binfmt_elf.c"
> diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
> index b827a9a..01baf83 100644
> --- a/arch/arm64/kernel/binfmt_ilp32.c
> +++ b/arch/arm64/kernel/binfmt_ilp32.c
> @@ -2,7 +2,9 @@
>   * Support for ILP32 Linux/aarch64 ELF binaries.
>   */
> 
> -#include <linux/elfcore-compat.h>
> +#include <linux/elf.h>
> +#include <linux/elfcore.h>
> +#include <linux/compat.h>
>  #include <linux/time.h>
> 
>  #undef	ELF_CLASS
> @@ -30,9 +32,13 @@
>   * The machine-dependent core note format types are defined in elfcore-compat.h,
>   * which requires asm/elf.h to define compat_elf_gregset_t et al.
>   */
> +#define compat_elf_greg_t	elf_greg_t
> +#define compat_elf_gregset_t	elf_gregset_t
>  #define elf_prstatus	compat_elf_prstatus
>  #define elf_prpsinfo	compat_elf_prpsinfo
> 
> +#include <linux/elfcore-compat.h>
> +
>  /*
>   * Compat version of cputime_to_compat_timeval, perhaps this
>   * should be an inline in <linux/compat.h>.
> diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
> index 5c86135..9784c77 100644
> --- a/arch/arm64/kernel/ptrace.c
> +++ b/arch/arm64/kernel/ptrace.c
> @@ -913,8 +913,8 @@ static const struct user_regset aarch32_regsets[] = {
>  	[REGSET_COMPAT_GPR] = {
>  		.core_note_type = NT_PRSTATUS,
>  		.n = COMPAT_ELF_NGREG,
> -		.size = sizeof(compat_elf_greg_t),
> -		.align = sizeof(compat_elf_greg_t),
> +		.size = sizeof(compat_a32_elf_greg_t),
> +		.align = sizeof(compat_a32_elf_greg_t),
>  		.get = compat_gpr_get,
>  		.set = compat_gpr_set
>  	},
> @@ -947,7 +947,7 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
>  		tmp = tsk->mm->start_data;
>  	else if (off == COMPAT_PT_TEXT_END_ADDR)
>  		tmp = tsk->mm->end_code;
> -	else if (off < sizeof(compat_elf_gregset_t))
> +	else if (off < sizeof(compat_a32_elf_gregset_t))
>  		return copy_regset_to_user(tsk, &user_aarch32_view,
>  					   REGSET_COMPAT_GPR, off,
>  					   sizeof(compat_ulong_t), ret);
> @@ -968,7 +968,7 @@ static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off,
>  	if (off & 3 || off >= COMPAT_USER_SZ)
>  		return -EIO;
> 
> -	if (off >= sizeof(compat_elf_gregset_t))
> +	if (off >= sizeof(compat_a32_elf_gregset_t))
>  		return 0;
> 
>  	set_fs(KERNEL_DS);
> @@ -1116,9 +1116,11 @@ static long compat_a32_ptrace(struct task_struct *child, compat_long_t request,
>  	unsigned long addr = caddr;
>  	unsigned long data = cdata;
>  	void __user *datap = compat_ptr(data);
> +	unsigned int pr_reg_size = sizeof(compat_a32_elf_gregset_t);
>  	int ret;
> 
>  	switch (request) {
> +
>  		case PTRACE_PEEKUSR:
>  			ret = compat_ptrace_read_user(child, addr, datap);
>  			break;
> @@ -1130,17 +1132,15 @@ static long compat_a32_ptrace(struct task_struct *child, compat_long_t request,
>  		case COMPAT_PTRACE_GETREGS:
>  			ret = copy_regset_to_user(child,
>  						  &user_aarch32_view,
> -						  REGSET_COMPAT_GPR,
> -						  0, sizeof(compat_elf_gregset_t),
> -						  datap);
> +						  REGSET_COMPAT_GPR, 0,
> +						  pr_reg_size, datap);
>  			break;
> 
>  		case COMPAT_PTRACE_SETREGS:
>  			ret = copy_regset_from_user(child,
>  						    &user_aarch32_view,
> -						    REGSET_COMPAT_GPR,
> -						    0, sizeof(compat_elf_gregset_t),
> -						    datap);
> +						    REGSET_COMPAT_GPR, 0,
> +						    pr_reg_size, datap);
>  			break;
> 
>  		case COMPAT_PTRACE_GET_THREAD_AREA:
> -- 
> 1.8.4.5
> 
> 
> On 2016/5/24 8:04, Yury Norov wrote:
> >to handle ILP32 binaries
> >
> >Signed-off-by: Yury Norov <ynorov at caviumnetworks.com>
> >---
> >  arch/arm64/kernel/Makefile       |  1 +
> >  arch/arm64/kernel/binfmt_ilp32.c | 91 ++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 92 insertions(+)
> >  create mode 100644 arch/arm64/kernel/binfmt_ilp32.c
> >
> >diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> >index 6bc9738..9dfdf86 100644
> >--- a/arch/arm64/kernel/Makefile
> >+++ b/arch/arm64/kernel/Makefile
> >@@ -28,6 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
> >  arm64-obj-$(CONFIG_AARCH32_EL0)		+= sys32.o kuser32.o signal32.o 	\
> >  					   sys_compat.o entry32.o		\
> >  					   ../../arm/kernel/opcodes.o binfmt_elf32.o
> >+arm64-obj-$(CONFIG_ARM64_ILP32)		+= binfmt_ilp32.o
> >  arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
> >  arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
> >  arm64-obj-$(CONFIG_ARM64_MODULE_PLTS)	+= module-plts.o
> >diff --git a/arch/arm64/kernel/binfmt_ilp32.c b/arch/arm64/kernel/binfmt_ilp32.c
> >new file mode 100644
> >index 0000000..a934fd4
> >--- /dev/null
> >+++ b/arch/arm64/kernel/binfmt_ilp32.c
> >@@ -0,0 +1,91 @@
> >+/*
> >+ * Support for ILP32 Linux/aarch64 ELF binaries.
> >+ */
> >+
> >+#include <linux/elfcore-compat.h>
> >+#include <linux/time.h>
> >+
> >+#undef	ELF_CLASS
> >+#define ELF_CLASS	ELFCLASS32
> >+
> >+#undef	elfhdr
> >+#undef	elf_phdr
> >+#undef	elf_shdr
> >+#undef	elf_note
> >+#undef	elf_addr_t
> >+#define elfhdr		elf32_hdr
> >+#define elf_phdr	elf32_phdr
> >+#define elf_shdr	elf32_shdr
> >+#define elf_note	elf32_note
> >+#define elf_addr_t	Elf32_Addr
> >+
> >+/*
> >+ * Some data types as stored in coredump.
> >+ */
> >+#define user_long_t		compat_long_t
> >+#define user_siginfo_t		compat_siginfo_t
> >+#define copy_siginfo_to_user	copy_siginfo_to_user32
> >+
> >+/*
> >+ * The machine-dependent core note format types are defined in elfcore-compat.h,
> >+ * which requires asm/elf.h to define compat_elf_gregset_t et al.
> >+ */
> >+#define elf_prstatus	compat_elf_prstatus
> >+#define elf_prpsinfo	compat_elf_prpsinfo
> >+
> >+/*
> >+ * Compat version of cputime_to_compat_timeval, perhaps this
> >+ * should be an inline in <linux/compat.h>.
> >+ */
> >+static void cputime_to_compat_timeval(const cputime_t cputime,
> >+				      struct compat_timeval *value)
> >+{
> >+	struct timeval tv;
> >+	cputime_to_timeval(cputime, &tv);
> >+	value->tv_sec = tv.tv_sec;
> >+	value->tv_usec = tv.tv_usec;
> >+}
> >+
> >+#undef cputime_to_timeval
> >+#define cputime_to_timeval cputime_to_compat_timeval
> >+
> >+/* AARCH64 ILP32 EABI. */
> >+#undef elf_check_arch
> >+#define elf_check_arch(x)		(((x)->e_machine == EM_AARCH64)	\
> >+					&& (x)->e_ident[EI_CLASS] == ELFCLASS32)
> >+
> >+#undef SET_PERSONALITY
> >+#define SET_PERSONALITY(ex)						\
> >+do {									\
> >+	set_thread_flag(TIF_32BIT_AARCH64);				\
> >+	clear_thread_flag(TIF_32BIT);					\
> >+} while (0)
> >+
> >+#undef ARCH_DLINFO
> >+#define ARCH_DLINFO							\
> >+do {									\
> >+	NEW_AUX_ENT(AT_SYSINFO_EHDR,					\
> >+		    (elf_addr_t)(long)current->mm->context.vdso);	\
> >+} while (0)
> >+
> >+#ifdef __AARCH64EB__
> >+#define COMPAT_ELF_PLATFORM		("aarch64_be:ilp32")
> >+#else
> >+#define COMPAT_ELF_PLATFORM		("aarch64:ilp32")
> >+#endif
> >+
> >+#undef ELF_HWCAP
> >+#undef ELF_HWCAP2
> >+#define ELF_HWCAP			((u32) elf_hwcap)
> >+#define ELF_HWCAP2			((u32) (elf_hwcap >> 32))
> >+
> >+/*
> >+ * Rename a few of the symbols that binfmt_elf.c will define.
> >+ * These are all local so the names don't really matter, but it
> >+ * might make some debugging less confusing not to duplicate them.
> >+ */
> >+#define elf_format		compat_elf_format
> >+#define init_elf_binfmt		init_compat_elf_binfmt
> >+#define exit_elf_binfmt		exit_compat_elf_binfmt
> >+
> >+#include "../../../fs/binfmt_elf.c"
> >

Thank you, I'll apply it


From khilman at baylibre.com  Thu May 26 14:24:21 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Thu, 26 May 2016 14:24:21 -0700
Subject: [PATCH v2 0/4] pinctrl: meson-gxbb: add a bunch more pins
Message-ID: <1464297865-8965-1-git-send-email-khilman@baylibre.com>

Add support for several more devices, both in the EE domain and in the
AO domain.  Also, add the pins to the corresponding DTS files.

Tested on odroid-c2 and Amlogic P200 boards, and verified with working
ethernet.

Changes since v1:
- dropped the rename of uart_ao -> uart_ao_a (will be done as follow-up)
- rebased on linus/master
- dropped DT from series (will be merged through arm-soc)

Kevin

Kevin Hilman (4):
  pinctrl: amlogic: gxbb: add UART_AO_B, I2C
  pinctrl: amlogic: gxbb: add EMMC and SD pins
  pinctrl: amlogic: gxbb: add more UART pins
  pinctrl: amlogic: gxbb: add ethernet pins

 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 163 ++++++++++++++++++++++++++++-
 1 file changed, 162 insertions(+), 1 deletion(-)

-- 
2.7.4



From khilman at baylibre.com  Thu May 26 14:24:23 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Thu, 26 May 2016 14:24:23 -0700
Subject: [PATCH v2 2/4] pinctrl: amlogic: gxbb: add EMMC and SD pins
In-Reply-To: <1464297865-8965-1-git-send-email-khilman@baylibre.com>
References: <1464297865-8965-1-git-send-email-khilman@baylibre.com>
Message-ID: <1464297865-8965-3-git-send-email-khilman@baylibre.com>

Add EE domain pins for eMMC and SD card.

Acked-by: Carlo Caione <carlo at endlessm.com>
Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 41 ++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index a188d9dae0f2..f0459f26c16c 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -147,6 +147,22 @@ static const struct pinctrl_pin_desc meson_gxbb_periphs_pins[] = {
 	MESON_PIN(GPIO_TEST_N, EE_OFF),
 };
 
+static const unsigned int emmc_nand_d07_pins[] = {
+	PIN(BOOT_0, EE_OFF), PIN(BOOT_1, EE_OFF), PIN(BOOT_2, EE_OFF),
+	PIN(BOOT_3, EE_OFF), PIN(BOOT_4, EE_OFF), PIN(BOOT_5, EE_OFF),
+	PIN(BOOT_6, EE_OFF), PIN(BOOT_7, EE_OFF),
+};
+static const unsigned int emmc_clk_pins[] = { PIN(BOOT_8, EE_OFF) };
+static const unsigned int emmc_cmd_pins[] = { PIN(BOOT_10, EE_OFF) };
+static const unsigned int emmc_ds_pins[] = { PIN(BOOT_15, EE_OFF) };
+
+static const unsigned int sdcard_d0_pins[] = { PIN(CARD_1, EE_OFF) };
+static const unsigned int sdcard_d1_pins[] = { PIN(CARD_0, EE_OFF) };
+static const unsigned int sdcard_d2_pins[] = { PIN(CARD_5, EE_OFF) };
+static const unsigned int sdcard_d3_pins[] = { PIN(CARD_4, EE_OFF) };
+static const unsigned int sdcard_cmd_pins[] = { PIN(CARD_3, EE_OFF) };
+static const unsigned int sdcard_clk_pins[] = { PIN(CARD_2, EE_OFF) };
+
 static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
 	MESON_PIN(GPIOAO_0, 0),
 	MESON_PIN(GPIOAO_1, 0),
@@ -307,6 +323,20 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GPIO_GROUP(GPIOCLK_3, EE_OFF),
 
 	GPIO_GROUP(GPIO_TEST_N, EE_OFF),
+
+	/* Bank BOOT */
+	GROUP(emmc_nand_d07,	4,	30),
+	GROUP(emmc_clk,		4,	18),
+	GROUP(emmc_cmd,		4,	19),
+	GROUP(emmc_ds,		4,	31),
+
+	/* Bank CARD */
+	GROUP(sdcard_d1,	2,	14),
+	GROUP(sdcard_d0,	2,	15),
+	GROUP(sdcard_d3,	2,	12),
+	GROUP(sdcard_d2,	2,	13),
+	GROUP(sdcard_cmd,	2,	10),
+	GROUP(sdcard_clk,	2,	11),
 };
 
 static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
@@ -377,6 +407,15 @@ static const char * const gpio_periphs_groups[] = {
 	"GPIO_TEST_N",
 };
 
+static const char * const emmc_groups[] = {
+	"emmc_nand_d07", "emmc_clk", "emmc_cmd", "emmc_ds",
+};
+
+static const char * const sdcard_groups[] = {
+	"sdcard_d0", "sdcard_d1", "sdcard_d2", "sdcard_d3",
+	"sdcard_cmd", "sdcard_clk",
+};
+
 static const char * const gpio_aobus_groups[] = {
 	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
 	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
@@ -401,6 +440,8 @@ static const char * const i2c_slave_ao_groups[] = {
 
 static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(gpio_periphs),
+	FUNCTION(emmc),
+	FUNCTION(sdcard),
 };
 
 static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
-- 
2.7.4



From khilman at baylibre.com  Thu May 26 14:24:22 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Thu, 26 May 2016 14:24:22 -0700
Subject: [PATCH v2 1/4] pinctrl: amlogic: gxbb: add UART_AO_B, I2C
In-Reply-To: <1464297865-8965-1-git-send-email-khilman@baylibre.com>
References: <1464297865-8965-1-git-send-email-khilman@baylibre.com>
Message-ID: <1464297865-8965-2-git-send-email-khilman@baylibre.com>

Add pins for some more AO domain devices: UART_AO_B and I2C master &
slave.

Acked-by: Carlo Caione <carlo at endlessm.com>
Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 35 +++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index eeabafbbf598..a188d9dae0f2 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -168,6 +168,16 @@ static const unsigned int uart_tx_ao_a_pins[]	= { PIN(GPIOAO_0, 0) };
 static const unsigned int uart_rx_ao_a_pins[]	= { PIN(GPIOAO_1, 0) };
 static const unsigned int uart_cts_ao_a_pins[]	= { PIN(GPIOAO_2, 0) };
 static const unsigned int uart_rts_ao_a_pins[]	= { PIN(GPIOAO_3, 0) };
+static const unsigned int uart_tx_ao_b_pins[]	= { PIN(GPIOAO_0, 0) };
+static const unsigned int uart_rx_ao_b_pins[]	= { PIN(GPIOAO_1, 0),
+						    PIN(GPIOAO_5, 0) };
+static const unsigned int uart_cts_ao_b_pins[]	= { PIN(GPIOAO_2, 0) };
+static const unsigned int uart_rts_ao_b_pins[]	= { PIN(GPIOAO_3, 0) };
+
+static const unsigned int i2c_sck_ao_pins[] = {PIN(GPIOAO_4, 0) };
+static const unsigned int i2c_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
+static const unsigned int i2c_slave_sck_ao_pins[] = {PIN(GPIOAO_4, 0) };
+static const unsigned int i2c_slave_sda_ao_pins[] = {PIN(GPIOAO_5, 0) };
 
 static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GPIO_GROUP(GPIOZ_0, EE_OFF),
@@ -316,10 +326,18 @@ static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
 	GPIO_GROUP(GPIOAO_13, 0),
 
 	/* bank AO */
+	GROUP(uart_tx_ao_b,	0,	26),
+	GROUP(uart_rx_ao_b,	0,	25),
 	GROUP(uart_tx_ao_a,	0,	12),
 	GROUP(uart_rx_ao_a,	0,	11),
 	GROUP(uart_cts_ao_a,	0,	10),
 	GROUP(uart_rts_ao_a,	0,	9),
+	GROUP(uart_cts_ao_b,	0,	8),
+	GROUP(uart_rts_ao_b,	0,	7),
+	GROUP(i2c_sck_ao,	0,	6),
+	GROUP(i2c_sda_ao,	0,	5),
+	GROUP(i2c_slave_sck_ao, 0,	2),
+	GROUP(i2c_slave_sda_ao, 0,	1),
 };
 
 static const char * const gpio_periphs_groups[] = {
@@ -366,7 +384,19 @@ static const char * const gpio_aobus_groups[] = {
 };
 
 static const char * const uart_ao_groups[] = {
-	"uart_tx_ao_a", "uart_rx_ao_a", "uart_cts_ao_a", "uart_rts_ao_a"
+	"uart_tx_ao_a", "uart_rx_ao_a", "uart_cts_ao_a", "uart_rts_ao_a",
+};
+
+static const char * const uart_ao_b_groups[] = {
+	"uart_tx_ao_b", "uart_rx_ao_b", "uart_cts_ao_b", "uart_rts_ao_b",
+};
+
+static const char * const i2c_ao_groups[] = {
+	"i2c_sdk_ao", "i2c_sda_ao",
+};
+
+static const char * const i2c_slave_ao_groups[] = {
+	"i2c_slave_sdk_ao", "i2c_slave_sda_ao",
 };
 
 static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
@@ -376,6 +406,9 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
 	FUNCTION(gpio_aobus),
 	FUNCTION(uart_ao),
+	FUNCTION(uart_ao_b),
+	FUNCTION(i2c_ao),
+	FUNCTION(i2c_slave_ao),
 };
 
 static struct meson_bank meson_gxbb_periphs_banks[] = {
-- 
2.7.4



From khilman at baylibre.com  Thu May 26 14:24:24 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Thu, 26 May 2016 14:24:24 -0700
Subject: [PATCH v2 3/4] pinctrl: amlogic: gxbb: add more UART pins
In-Reply-To: <1464297865-8965-1-git-send-email-khilman@baylibre.com>
References: <1464297865-8965-1-git-send-email-khilman@baylibre.com>
Message-ID: <1464297865-8965-4-git-send-email-khilman@baylibre.com>

Add EE domain pins for UART A, B & C.

Acked-by: Carlo Caione <carlo at endlessm.com>
Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 48 ++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index f0459f26c16c..b2ec5f8ada33 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -163,6 +163,21 @@ static const unsigned int sdcard_d3_pins[] = { PIN(CARD_4, EE_OFF) };
 static const unsigned int sdcard_cmd_pins[] = { PIN(CARD_3, EE_OFF) };
 static const unsigned int sdcard_clk_pins[] = { PIN(CARD_2, EE_OFF) };
 
+static const unsigned int uart_tx_a_pins[]	= { PIN(GPIOX_12, EE_OFF) };
+static const unsigned int uart_rx_a_pins[]	= { PIN(GPIOX_13, EE_OFF) };
+static const unsigned int uart_cts_a_pins[]	= { PIN(GPIOX_14, EE_OFF) };
+static const unsigned int uart_rts_a_pins[]	= { PIN(GPIOX_15, EE_OFF) };
+
+static const unsigned int uart_tx_b_pins[]	= { PIN(GPIODV_24, EE_OFF) };
+static const unsigned int uart_rx_b_pins[]	= { PIN(GPIODV_25, EE_OFF) };
+static const unsigned int uart_cts_b_pins[]	= { PIN(GPIODV_26, EE_OFF) };
+static const unsigned int uart_rts_b_pins[]	= { PIN(GPIODV_27, EE_OFF) };
+
+static const unsigned int uart_tx_c_pins[]	= { PIN(GPIOY_13, EE_OFF) };
+static const unsigned int uart_rx_c_pins[]	= { PIN(GPIOY_14, EE_OFF) };
+static const unsigned int uart_cts_c_pins[]	= { PIN(GPIOX_11, EE_OFF) };
+static const unsigned int uart_rts_c_pins[]	= { PIN(GPIOX_12, EE_OFF) };
+
 static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
 	MESON_PIN(GPIOAO_0, 0),
 	MESON_PIN(GPIOAO_1, 0),
@@ -324,6 +339,24 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 
 	GPIO_GROUP(GPIO_TEST_N, EE_OFF),
 
+	/* Bank X */
+	GROUP(uart_tx_a,	4,	13),
+	GROUP(uart_rx_a,	4,	12),
+	GROUP(uart_cts_a,	4,	11),
+	GROUP(uart_rts_a,	4,	10),
+
+	/* Bank Y */
+	GROUP(uart_cts_c,	1,	19),
+	GROUP(uart_rts_c,	1,	18),
+	GROUP(uart_tx_c,	1,	17),
+	GROUP(uart_rx_c,	1,	16),
+
+	/* Bank DV */
+	GROUP(uart_tx_b,	2,	29),
+	GROUP(uart_rx_b,	2,	28),
+	GROUP(uart_cts_b,	2,	27),
+	GROUP(uart_rts_b,	2,	26),
+
 	/* Bank BOOT */
 	GROUP(emmc_nand_d07,	4,	30),
 	GROUP(emmc_clk,		4,	18),
@@ -416,6 +449,18 @@ static const char * const sdcard_groups[] = {
 	"sdcard_cmd", "sdcard_clk",
 };
 
+static const char * const uart_a_groups[] = {
+	"uart_tx_a", "uart_rx_a", "uart_cts_a", "uart_rts_a",
+};
+
+static const char * const uart_b_groups[] = {
+	"uart_tx_b", "uart_rx_b", "uart_cts_b", "uart_rts_b",
+};
+
+static const char * const uart_c_groups[] = {
+	"uart_tx_c", "uart_rx_c", "uart_cts_c", "uart_rts_c",
+};
+
 static const char * const gpio_aobus_groups[] = {
 	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
 	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
@@ -442,6 +487,9 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(gpio_periphs),
 	FUNCTION(emmc),
 	FUNCTION(sdcard),
+	FUNCTION(uart_a),
+	FUNCTION(uart_b),
+	FUNCTION(uart_c),
 };
 
 static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
-- 
2.7.4



From khilman at baylibre.com  Thu May 26 14:24:25 2016
From: khilman at baylibre.com (Kevin Hilman)
Date: Thu, 26 May 2016 14:24:25 -0700
Subject: [PATCH v2 4/4] pinctrl: amlogic: gxbb: add ethernet pins
In-Reply-To: <1464297865-8965-1-git-send-email-khilman@baylibre.com>
References: <1464297865-8965-1-git-send-email-khilman@baylibre.com>
Message-ID: <1464297865-8965-5-git-send-email-khilman@baylibre.com>

Add EE domain pins for ethernet interface.

Acked-by: Carlo Caione <carlo at endlessm.com>
Signed-off-by: Kevin Hilman <khilman at baylibre.com>
---
 drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 39 ++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index b2ec5f8ada33..cb4d6ad30530 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -178,6 +178,21 @@ static const unsigned int uart_rx_c_pins[]	= { PIN(GPIOY_14, EE_OFF) };
 static const unsigned int uart_cts_c_pins[]	= { PIN(GPIOX_11, EE_OFF) };
 static const unsigned int uart_rts_c_pins[]	= { PIN(GPIOX_12, EE_OFF) };
 
+static const unsigned int eth_mdio_pins[]	= { PIN(GPIOZ_0, EE_OFF) };
+static const unsigned int eth_mdc_pins[]	= { PIN(GPIOZ_1, EE_OFF) };
+static const unsigned int eth_clk_rx_clk_pins[]	= { PIN(GPIOZ_2, EE_OFF) };
+static const unsigned int eth_rx_dv_pins[]	= { PIN(GPIOZ_3, EE_OFF) };
+static const unsigned int eth_rxd0_pins[]	= { PIN(GPIOZ_4, EE_OFF) };
+static const unsigned int eth_rxd1_pins[]	= { PIN(GPIOZ_5, EE_OFF) };
+static const unsigned int eth_rxd2_pins[]	= { PIN(GPIOZ_6, EE_OFF) };
+static const unsigned int eth_rxd3_pins[]	= { PIN(GPIOZ_7, EE_OFF) };
+static const unsigned int eth_rgmii_tx_clk_pins[] = { PIN(GPIOZ_8, EE_OFF) };
+static const unsigned int eth_tx_en_pins[]	= { PIN(GPIOZ_9, EE_OFF) };
+static const unsigned int eth_txd0_pins[]	= { PIN(GPIOZ_10, EE_OFF) };
+static const unsigned int eth_txd1_pins[]	= { PIN(GPIOZ_11, EE_OFF) };
+static const unsigned int eth_txd2_pins[]	= { PIN(GPIOZ_12, EE_OFF) };
+static const unsigned int eth_txd3_pins[]	= { PIN(GPIOZ_13, EE_OFF) };
+
 static const struct pinctrl_pin_desc meson_gxbb_aobus_pins[] = {
 	MESON_PIN(GPIOAO_0, 0),
 	MESON_PIN(GPIOAO_1, 0),
@@ -351,6 +366,22 @@ static struct meson_pmx_group meson_gxbb_periphs_groups[] = {
 	GROUP(uart_tx_c,	1,	17),
 	GROUP(uart_rx_c,	1,	16),
 
+	/* Bank Z */
+	GROUP(eth_mdio,		6,	1),
+	GROUP(eth_mdc,		6,	0),
+	GROUP(eth_clk_rx_clk,	6,	13),
+	GROUP(eth_rx_dv,	6,	12),
+	GROUP(eth_rxd0,		6,	11),
+	GROUP(eth_rxd1,		6,	10),
+	GROUP(eth_rxd2,		6,	9),
+	GROUP(eth_rxd3,		6,	8),
+	GROUP(eth_rgmii_tx_clk,	6,	7),
+	GROUP(eth_tx_en,	6,	6),
+	GROUP(eth_txd0,		6,	5),
+	GROUP(eth_txd1,		6,	4),
+	GROUP(eth_txd2,		6,	3),
+	GROUP(eth_txd3,		6,	2),
+
 	/* Bank DV */
 	GROUP(uart_tx_b,	2,	29),
 	GROUP(uart_rx_b,	2,	28),
@@ -461,6 +492,13 @@ static const char * const uart_c_groups[] = {
 	"uart_tx_c", "uart_rx_c", "uart_cts_c", "uart_rts_c",
 };
 
+static const char * const eth_groups[] = {
+	"eth_mdio", "eth_mdc", "eth_clk_rx_clk", "eth_rx_dv",
+	"eth_rxd0", "eth_rxd1", "eth_rxd2", "eth_rxd3",
+	"eth_rgmii_tx_clk", "eth_tx_en",
+	"eth_txd0", "eth_txd1", "eth_txd2", "eth_txd3",
+};
+
 static const char * const gpio_aobus_groups[] = {
 	"GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4",
 	"GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9",
@@ -490,6 +528,7 @@ static struct meson_pmx_func meson_gxbb_periphs_functions[] = {
 	FUNCTION(uart_a),
 	FUNCTION(uart_b),
 	FUNCTION(uart_c),
+	FUNCTION(eth),
 };
 
 static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
-- 
2.7.4



From John.Youn at synopsys.com  Thu May 26 14:44:40 2016
From: John.Youn at synopsys.com (John Youn)
Date: Thu, 26 May 2016 14:44:40 -0700
Subject: [PATCH] reset: Put back *_optional variants
In-Reply-To: <12e450f0-70ea-29f8-0bf7-8a0697263f2d@redhat.com>
References: <ca359e013c30f27c825a9580164b01da5ca6476d.1464224883.git.johnyoun@synopsys.com>
 <12e450f0-70ea-29f8-0bf7-8a0697263f2d@redhat.com>
Message-ID: <57476E48.2060204@synopsys.com>

On 5/26/2016 1:25 PM, Hans de Goede wrote:
> Hi,
> 
> On 26-05-16 03:15, John Youn wrote:
>> Prior to commit 6c96f05c8bb8 ("reset: Make [of_]reset_control_get[_foo]
>> functions wrappers"), the optional variants returned -ENOTSUPP when
>> CONFIG_RESET_CONTROLLER was not set. This patch reverts to this
>> behavior. Otherwise those calls will return -EINVAL causing users to
>> think that an error occurred when CONFIG_RESET_CONTROLLER is not set.
>>
>> Fixes: 6c96f05c8bb8 ("reset: Make [of_]reset_control_get[_foo] functions wrappers")
>> Signed-off-by: John Youn <johnyoun at synopsys.com>
>> ---
>>
>> Hi Philipp, Hans,
>>
>> The commit referenced above breaks an upcoming patch for the dwc2
>> driver that adds an optional reset control.
>>
>> https://marc.info/?l=linux-usb&m=146161328211584&w=2
>>
>> I've attempted to add the optional variants back the way they were
>> working before. Let me know if I need to do anything else to fix it or
>> if it should be done another way.
>>
>> Regards,
>> John
> 
> Hmm, I don't like all the extra code your patch adds just to fix
> a return value...
> 
> Looking at the code before my "reset: Make [of_]reset_control_get[_foo]
> functions wrappers" patch, all the dev*_get* functions were
> returning ENOTSUPP except for [devm_]reset_control_get, so following
> your logic we should also change the of_reset_control_get_by_index
> variant to return -ENOTSUP.
> 
> Or better, simply make them all return -ENOTSUP, that seems both
> consistent and more KISS to me, this would mean an error code
> change for [devm_]reset_control_get, but will fix all the other
> getters from having a changed error-code, and I would callers
> of [devm_]reset_control_get to not care which error code they
> get, except for -EPROBE_DEFER.
> 
> So IMHO the following change would be a better way to fix this:
> 
> --- a/include/linux/reset.h
> +++ b/include/linux/reset.h
> @@ -65,14 +65,14 @@ static inline struct reset_control *__of_reset_control_get(
>                                          struct device_node *node,
>                                          const char *id, int index, int shared)
>   {
> -   return ERR_PTR(-EINVAL);
> + return ERR_PTR(-ENOTSUPP);
>   }
> 
>   static inline struct reset_control *__devm_reset_control_get(
>                                          struct device *dev,
>                                          const char *id, int index, int shared)
>   {
> -   return ERR_PTR(-EINVAL);
> + return ERR_PTR(-ENOTSUPP);
>   }
> 
>   #endif /* CONFIG_RESET_CONTROLLER */


I'm good with this. However, per Philipp on a previous thread, the
intended behavior is to return -EINVAL for the non-optional functions.

http://marc.info/?l=linux-usb&m=146156945528848&w=2

Philipp,

Any suggestions?

Regards,
John



From heiko at sntech.de  Thu May 26 14:47:39 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 26 May 2016 23:47:39 +0200
Subject: [PATCH] clk: rockchip: fix cclk error handing
In-Reply-To: <1464270549-12713-1-git-send-email-zhengxing@rock-chips.com>
References: <1464270549-12713-1-git-send-email-zhengxing@rock-chips.com>
Message-ID: <1509769.ko7YVcsoMN@phil>

Am Donnerstag, 26. Mai 2016, 21:49:08 schrieb Xing Zheng:
> It maybe due to a copy-paste error the error handing should be
> cclk not clk.
> 
> Reported-by: Lin Huang <lin.huang at rock-chips.com>
> Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>

applied to my clk-fixes branch after adapting the commit message a bit.


Thanks for catching that
Heiko


From sricharan at codeaurora.org  Thu May 26 15:01:13 2016
From: sricharan at codeaurora.org (Sricharan)
Date: Fri, 27 May 2016 03:31:13 +0530
Subject: [PATCH V3 1/2] i2c: qup: Fix broken dma when CONFIG_DEBUG_SG is
 enabled
In-Reply-To: <20160526184805.GC1614@katana>
References: <1464164212-11377-1-git-send-email-sricharan@codeaurora.org>
 <1464164212-11377-2-git-send-email-sricharan@codeaurora.org>
 <20160526184805.GC1614@katana>
Message-ID: <002201d1b79a$22862bc0$67928340$@codeaurora.org>

Hi,

>> sg_set_buf expects that the buf parameter passed in should be from
>> lowmem and a valid pageframe. This is not true for pages from
>> dma_alloc_coherent which can be carveouts, hence the check fails.
>
>OK, given you mean dma_pool_alloc here, the check fails for the
>pageframe because of the pool? Is my understanding correct?
>
Yes right. Since those are carveouts, there is no valid pageframe,
 so the check fails.

>> Change allocation of sg buffers from dma_coherent memory to kzalloc
>> to fix the issue.
>
>But why can you drop the coherency?
>
 The coherency is not dropped here. dma_map/unmap used
 makes the buffer coherent before passing it to
 dmaengine. Previously it was not required.
 I can add this in description if its not clear.

 >> @@ -1268,6 +1260,8 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
>>  		}
>>  	}
>>
>> +	idx = 0;
>> +
>
>This looks like an unrelated change.
    Ha, wrong. This should have been in a separate patch. This was to fix a
    initialization issue in dma mode. Sorry, should not have been here, will
    move it to out.

Regards,
 Sricharan




From festevam at gmail.com  Thu May 26 15:20:38 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Thu, 26 May 2016 19:20:38 -0300
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <9d7793850de942cfb578b0aeb2728f41@rwthex-s1-b.rwth-ad.de>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
 <CAOMZO5C5goJUdHKB9a=eOv9TKDkJWxnkWWb-G7E5Kvceg6sZVg@mail.gmail.com>
 <a6cc6b85d2fa4994b3cb7e2b047f800d@rwthex-w2-b.rwth-ad.de>
 <9d7793850de942cfb578b0aeb2728f41@rwthex-s1-b.rwth-ad.de>
Message-ID: <CAOMZO5C3_bd-2Nz+G956+VPOcKoFaGGJK7G1p=U0yf5OyWekZA@mail.gmail.com>

On Thu, May 26, 2016 at 11:26 AM, Christopher Spinrath
<christopher.spinrath at rwth-aachen.de> wrote:

> Thanks for joining this discussion. I *guess* the rationale is to share
> the same device tree with projects that are incompatible with the GPL
> (e.g. *BSD). Even if there is no support for a particular device/board
> having all (or most) files dual licensed makes it easier to just pull
> them all in.

Yes, that's correct.


From catalin.marinas at arm.com  Thu May 26 15:29:45 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 26 May 2016 23:29:45 +0100
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160526204819.GA10274@yury-N73SV>
References: <6293194.tGy03QJ9ME@wuerfel>
 <20160525.135039.244098606649448826.davem@davemloft.net>
 <6407614.fdv5XFSBue@wuerfel>
 <20160525.142821.1719403997976778673.davem@davemloft.net>
 <20160526204819.GA10274@yury-N73SV>
Message-ID: <20160526222943.GA16729@MBP.local>

On Thu, May 26, 2016 at 11:48:19PM +0300, Yury Norov wrote:
> On Wed, May 25, 2016 at 02:28:21PM -0700, David Miller wrote:
> > From: Arnd Bergmann <arnd at arndb.de>
> > Date: Wed, 25 May 2016 23:01:06 +0200
> > 
> > > On Wednesday, May 25, 2016 1:50:39 PM CEST David Miller wrote:
> > >> From: Arnd Bergmann <arnd at arndb.de>
> > >> Date: Wed, 25 May 2016 22:47:33 +0200
> > >> 
> > >> > If we use the normal calling conventions, we could remove these overrides
> > >> > along with the respective special-case handling in glibc. None of them
> > >> > look particularly performance-sensitive, but I could be wrong there.
> > >> 
> > >> You could set the lowest bit in the system call entry pointer to indicate
> > >> the upper-half clears should be elided.
> > > 
> > > Right, but that would introduce an extra conditional branch in the syscall
> > > hotpath, and likely eliminate the gains from passing the loff_t arguments
> > > in a single register instead of a pair.
> > 
> > Ok, then, how much are you really gaining from avoiding a 'shift' and
> > an 'or' to build the full 64-bit value?  3 cycles?  Maybe 4?
> 
> 4 cycles in kernel and ~same cost in glibc to create a pair.

It would take a single instruction per argument in the kernel to do
shift+or and maybe 1-2 more instructions to move the remaining arguments
in place (we do this for a few wrappers in arch/arm64/kernel/entry32.S).
And the glibc counterpart.

> And 8 'mov's that exist for every syscall, even yield().
> 
> > And the executing the wrappers, those have a non-trivial cost too.
> 
> The cost is pretty trivial though. See kernel/compat_wrapper.o:
> COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
> 0:   a9bf7bfd        stp     x29, x30, [sp,#-16]!
> 4:   910003fd        mov     x29, sp
> 8:   2a0003e0        mov     w0, w0
> c:   94000000        bl      0 <sys_creat>
> 10:  a8c17bfd        ldp     x29, x30, [sp],#16
> 14:  d65f03c0        ret

I would say the above could be more expensive than 8 movs (16 bytes to
write, read, a branch and a ret). You can also add the I-cache locality,
having wrappers for each syscalls instead of a single place for zeroing
the upper half (where no other wrapper is necessary).

Can we trick the compiler into doing a tail call optimisation. This
could have simply been:

COMPAT_SYSCALL_WRAP2(creat, ...):
	mov	w0, w0
	b	<sys_creat>

> > Cost wise, this seems like it all cancels out in the end, but what
> > do I know?
> 
> I think you know something, and I also think Heiko and other s390 guys
> know something as well. So I'd like to listen their arguments here.
> 
> For me spark64 way is looking reasonable only because it's really simple
> and takes less coding. I'll try it on some branch and share here what happened.

The kernel code will definitely look simpler ;). It would be good to see
if there actually is any performance impact. Even with 16 more cycles on
syscall entry, would they be lost in the noise? You don't need a full
implementation, just some dummy mov x0, x0 on the entry path.

-- 
Catalin


From ahs3 at redhat.com  Thu May 26 15:31:24 2016
From: ahs3 at redhat.com (Al Stone)
Date: Thu, 26 May 2016 16:31:24 -0600
Subject: [PATCH v5 0/1] ARM64: ACPI: Update documentation for latest
 specification version
In-Reply-To: <44cda485-1c43-f7c3-676b-f9c47785daf6@linaro.org>
References: <20160516234441.GA7425@arm.com>
 <44cda485-1c43-f7c3-676b-f9c47785daf6@linaro.org>
Message-ID: <baa61d52-083f-574a-ed0e-6b57c9517d06@redhat.com>

On 05/17/2016 10:30 AM, Al Stone wrote:
> On 05/16/2016 05:44 PM, Alexey Klimov wrote:
>> On Mon, May 2, 2016 at 09:19 PM, Al Stone wrote:
>>> On 04/25/2016 03:21 PM, Al Stone wrote:
>>>> The ACPI 6.1 specification was recently released at the end of January
>>>> 2016, but the arm64 kernel documentation for the use of ACPI was written
>>>> for the 5.1 version of the spec.  There were significant additions to the
>>>> spec that had not yet been mentioned -- for example, the 6.0 mechanisms
>>>> added to make it easier to define processors and low power idle states,
>>>> as well as the 6.1 addition allowing regular interrupts (not just from
>>>> GPIO) be used to signal ACPI general purpose events.
>>>>
>>>> This patch reflects going back through and examining the specs in detail
>>>> and updating content appropriately.  Whilst there, a few odds and ends of
>>>> typos were caught as well.  This brings the documentation up to date with
>>>> ACPI 6.1 for arm64.
>>>>
>>>> Changes for v5:
>>>>    -- Miscellaneous typos and corrections (Lorenzo Pieralisi)
>>>>    -- Add linux-acpi@ ML to the distribution list (Alexey Klimov)
>>>>    -- Corrections to CPPC information (Alexey Klimov)
>>>>    -- ACK from Lorenzo Pieralisi
>>>>    -- Updated bibliographic info (Al Stone)
>>>>
>>>> Changes for v4:
>>>>    -- Clarify that IORT can sometimes be optional (Jon Masters).
>>>>    -- Remove "Use as needed" descriptions of ACPI objects; they provide
>>>>       no substantive information and doing so simplifies maintenance of
>>>>       this document over time.  These have been replaced with a simpler
>>>>       notice that states that unless otherwise noted, do what the ACPI
>>>>       specification says is needed.
>>>>    -- Corrected the _OSI object usage recommendation; it described kernel
>>>>       behavior that does not exist (Al Stone).
>>>>
>>>> Changes for v3:
>>>>    -- Clarify use of _LPI/_RDI (Vikas Sajjan)
>>>>    -- Whitespace cleanup as pointed out by checkpatch
>>>>
>>>> Changes for v2:
>>>>    -- Clean up white space (Harb Abdulhahmid)
>>>>    -- Clarification on _CCA usage (Harb Abdulhamid)
>>>>    -- IORT moved to required from recommended (Hanjun Guo)
>>>>    -- Clarify IORT description (Hanjun Guo)
>>>>
>>>>
>>>> Al Stone (1):
>>>>   ARM64: ACPI: Update documentation for latest specification version
>>>>
>>>>  Documentation/arm64/acpi_object_usage.txt | 343 ++++++++++++++++--------------
>>>>  Documentation/arm64/arm-acpi.txt          |  40 ++--
>>>>  2 files changed, 213 insertions(+), 170 deletions(-)
>>>>
>>>
>>> Ping?  If there are no further comments, can this be pulled in through
>>> either the documentation or arm64 tree?
>>>
>>> Thanks.
>>
>> Hi Al,
>> sorry for delay.
>>
>> CPPC and PCC corrections look fine. Thanks.
>>
>>
>> This comment is not to block your patch (maybe some to-do):
>> I greped sources and your patch and I don't see description of _PSD object.
>> This P-state dependancy object is optional but it's presense and correct data
>> are extremely useful for CPPC and can potentially descrease number of performance
>> changing requests.
>>
>> ACPI spec in section about CPPC tells that it may use _PSD (page 503 if I remember
>> correctly) to specify domain belongings of CPUs.
>>
>> You may consider to add description of _PSD object later.
>>
>> Best regards,
>> Alexey.
>>
> 
> Hrm.  Thanks, Alexey.  I'll take a look.  _PSD may be in one of
> the gray areas where we expect people to read the spec and follow
> it properly, but it may make sense to be very explicit about what
> they need to do to use it properly.  Perhaps this would make a good
> FWTS test, too.
> 

Yet another ping...

Just in case it is not clear, Alexey's comment and my reply here are
things that *might* need to be done in the future.  This version of the
patch I believe is sufficient for now, based on the comments received.

Lorenzo has ACKd; Hanjun has reviewed.  Do I need Will and/or Catalin
to ACK?  Any others?

-- 
ciao,
al
-----------------------------------
Al Stone
Software Engineer
Red Hat, Inc.
ahs3 at redhat.com
-----------------------------------


From heiko at sntech.de  Thu May 26 16:17:27 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Fri, 27 May 2016 01:17:27 +0200
Subject: [PATCH] clk: rockchip: add a dummy clock for the watchdog pclk on
 rk3399
In-Reply-To: <1464166316-22480-1-git-send-email-zhengxing@rock-chips.com>
References: <1464166316-22480-1-git-send-email-zhengxing@rock-chips.com>
Message-ID: <7878987.CKGkxk3Y7s@phil>

Am Mittwoch, 25. Mai 2016, 16:51:56 schrieb Xing Zheng:
> Like rk3288, the pclk supplying the watchdog is controlled via the
> SGRF register area. Additionally the SGRF isn't even writable in
> every boot mode.
> 
> But still the clock control is available and in the future someone
> might want to use it. Therefore define a simple clock for the time
> being so that the watchdog driver can read its rate.
> 
> Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>

applied for 4.8

Thanks
Heiko


From ynorov at caviumnetworks.com  Thu May 26 17:37:53 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Fri, 27 May 2016 03:37:53 +0300
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160526222943.GA16729@MBP.local>
References: <6293194.tGy03QJ9ME@wuerfel>
 <20160525.135039.244098606649448826.davem@davemloft.net>
 <6407614.fdv5XFSBue@wuerfel>
 <20160525.142821.1719403997976778673.davem@davemloft.net>
 <20160526204819.GA10274@yury-N73SV>
 <20160526222943.GA16729@MBP.local>
Message-ID: <20160527003753.GA14247@yury-N73SV>

On Thu, May 26, 2016 at 11:29:45PM +0100, Catalin Marinas wrote:
> On Thu, May 26, 2016 at 11:48:19PM +0300, Yury Norov wrote:
> > On Wed, May 25, 2016 at 02:28:21PM -0700, David Miller wrote:
> > > From: Arnd Bergmann <arnd at arndb.de>
> > > Date: Wed, 25 May 2016 23:01:06 +0200
> > > 
> > > > On Wednesday, May 25, 2016 1:50:39 PM CEST David Miller wrote:
> > > >> From: Arnd Bergmann <arnd at arndb.de>
> > > >> Date: Wed, 25 May 2016 22:47:33 +0200
> > > >> 
> > > >> > If we use the normal calling conventions, we could remove these overrides
> > > >> > along with the respective special-case handling in glibc. None of them
> > > >> > look particularly performance-sensitive, but I could be wrong there.
> > > >> 
> > > >> You could set the lowest bit in the system call entry pointer to indicate
> > > >> the upper-half clears should be elided.
> > > > 
> > > > Right, but that would introduce an extra conditional branch in the syscall
> > > > hotpath, and likely eliminate the gains from passing the loff_t arguments
> > > > in a single register instead of a pair.
> > > 
> > > Ok, then, how much are you really gaining from avoiding a 'shift' and
> > > an 'or' to build the full 64-bit value?  3 cycles?  Maybe 4?
> > 
> > 4 cycles in kernel and ~same cost in glibc to create a pair.
> 
> It would take a single instruction per argument in the kernel to do
> shift+or and maybe 1-2 more instructions to move the remaining arguments
> in place (we do this for a few wrappers in arch/arm64/kernel/entry32.S).
> And the glibc counterpart.
> 
> > And 8 'mov's that exist for every syscall, even yield().
> > 
> > > And the executing the wrappers, those have a non-trivial cost too.
> > 
> > The cost is pretty trivial though. See kernel/compat_wrapper.o:
> > COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
> > 0:   a9bf7bfd        stp     x29, x30, [sp,#-16]!
> > 4:   910003fd        mov     x29, sp
> > 8:   2a0003e0        mov     w0, w0
> > c:   94000000        bl      0 <sys_creat>
> > 10:  a8c17bfd        ldp     x29, x30, [sp],#16
> > 14:  d65f03c0        ret
> 
> I would say the above could be more expensive than 8 movs (16 bytes to
> write, read, a branch and a ret). You can also add the I-cache locality,
> having wrappers for each syscalls instead of a single place for zeroing
> the upper half (where no other wrapper is necessary).
> 
> Can we trick the compiler into doing a tail call optimisation. This
> could have simply been:
> 
> COMPAT_SYSCALL_WRAP2(creat, ...):
> 	mov	w0, w0
> 	b	<sys_creat>

What you talk about was in my initial version. But Heiko insisted on having all
wrappers together.
http://www.spinics.net/lists/linux-s390/msg11593.html

Grep your email for discussion.

> 
> > > Cost wise, this seems like it all cancels out in the end, but what
> > > do I know?
> > 
> > I think you know something, and I also think Heiko and other s390 guys
> > know something as well. So I'd like to listen their arguments here.
> > 
> > For me spark64 way is looking reasonable only because it's really simple
> > and takes less coding. I'll try it on some branch and share here what happened.
> 
> The kernel code will definitely look simpler ;). It would be good to see
> if there actually is any performance impact. Even with 16 more cycles on
> syscall entry, would they be lost in the noise? You don't need a full
> implementation, just some dummy mov x0, x0 on the entry path.
> 
> -- 
> Catalin


From horms at verge.net.au  Thu May 26 17:42:56 2016
From: horms at verge.net.au (Simon Horman)
Date: Fri, 27 May 2016 09:42:56 +0900
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <59e6225a-6dfa-8bde-dd2e-3428d6fedfe2@de.bosch.com>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
 <20160525004825.GC7292@verge.net.au>
 <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>
 <20160526022833.GE18393@verge.net.au>
 <59e6225a-6dfa-8bde-dd2e-3428d6fedfe2@de.bosch.com>
Message-ID: <20160527004256.GD14269@verge.net.au>

On Thu, May 26, 2016 at 09:14:16AM +0200, Dirk Behme wrote:
> Hi Simon,
> 
> On 26.05.2016 04:28, Simon Horman wrote:
> >Hi Dirk,
> >
> >On Wed, May 25, 2016 at 07:10:26AM +0200, Dirk Behme wrote:
> >>Hi Simon,
> >>
> >>On 25.05.2016 02:48, Simon Horman wrote:
> >>>Hi Dirk,
> >>>
> >>>On Tue, May 24, 2016 at 07:30:17AM +0200, Dirk Behme wrote:
> >>>>Hi Simon,
> >>>
> >>>[...]
> >>>
> >>>>With Renesas R-Car3 we will get a whole family of SoCs. I.e. different
> >>>>computing power (e.g. different number of Cores) with more or less similar
> >>>>peripherals.
> >>>>
> >>>>I would think that we want to reflect this in the device tree, too.
> >>>>Therefore I think what we want is a hierarchy of device trees. Similar
> >>>>what's done with other SoC families (compare e.g. i.MX6).
> >>>>
> >>>>E.g. we want an initial rcar3.dtsi, which contains all common parts of all
> >>>>R-Car3 SoCs. E.g. one CA57 core, the SCIF where its common etc.
> >>>>
> >>>>Then you will have the r8a779x.dtsi which includes the rcar3.dtsi and
> >>>>extends it for SoC specific parts. Which then will be included by the board
> >>>>device trees, as already done, now.
> >>>>
> >>>>Or in other words: As soon as you have similar parts in the r8a779x.dtsi's,
> >>>>it's time to think about moving the parts one hierarchy level up into the
> >>>>rcar3.dtsi. Else you will end up in a maintenance hell once you have to
> >>>>change/fix anything.
> >>>
> >>>Thanks for raising this issue.
> >>>
> >>>I agree entirely that we should work towards a situation where maintenance
> >>>is as easy as it can be. However, due to the per-SoC binding scheme that
> >>>we are using for IP related to Renesas SoCs I suspect that very few DT nodes
> >>>can be shared between SoCs verbatim.
> >>
> >>
> >>Could you kindly share an example for this? Looking into the H3 and the M3-W
> >>manual, it looks to me that ~90% (?) of the peripherals are the same.
> >
> >The background is that this is a conversation that has been going around
> >for years. The basic thinking is that at this point we have documentation
> >that indicates that many hardware blocks on the H3 and M3-W are the same.
> >But we do not have insight into the internal versioning of the IP blocks
> >nor if they are really the same. And furthermore even if they are currently
> >the same we don't really know if that will continue to be the case.
> >
> >Probably it is. Maybe it isn't. The response has been to take a
> >conservative approach to DT bindings to give us the flexibility to update
> >the driver implementation to reflect any differences that subsequently
> >surface. And by providing per-SoC bindings these driver changes can be
> >activated on a per-SoC basis without updating DTB files (which may be
> >burned into ROMs).
> 
> 
> Sorry, but I don't think that these are good arguments for this kind of
> discussion ;)

>From my point of view this is the central point. It is my believe that we
simply do not have enough information to conclude that the IP blocks will
be the same in perpetuity.

> The discussion has to be based on facts. And not on "maybe" or "probably".
> The fact is that the documentation tells us that the IPs are the same. And
> the documentation tells us where this isn't the case. This is what we can
> reflect in the code and the device trees.
> 
> Or the other way around: I don't ask to not have any SoC specific device
> trees (r8a7795.dtsi, r8a7796.dtsi etc). So we *always* have the option to
> move anything to them, once there might be any difference found or
> documented. But maintaining x (x > 5?) quite similar device trees just
> because there *might* be the possibility that one or two device *might* be
> different doesn't sound like a good argument to me.
> 
> Or again, an other way: If I understood correctly, you are working already
> since some time on R-Car, e.g. R-Car Gen2. How many examples do you have
> from the Gen2 family where the IP blocks are different that they need to be
> distinguished in the device tree?

I think the question is different. The question is, if a difference comes
up, how do we handle it?

So far we have a solution. Not an ideal one, but a solution none the less.
I do agree entirely that replicated DTs leads to significant maintenance
overhead. But lets not throw the baby out with the bath water.

> >>>Probably some sort of scheme can be cooked up using preprocessor macros.
> >>>And probably there are other ways to resolve this problem. But I would
> >>>prefer if we worked towards resolving this maintenance problem in parallel
> >>>with rather than as a dependency of merging r8a7796 support into mainline.
> >>
> >>
> >>I'd propose to do it correct from the beginning.
> >>
> >>Doing it later would either be more work or forgotten, and never be done,
> >>then.
> >
> >I'm sorry but I don't agree. I think that having r8a7796 support
> >in mainline is a higher priority than sorting this out.
> 
> 
> Looking at the example I gave in
> 
> http://article.gmane.org/gmane.linux.kernel.renesas-soc/4013
> 
> which took me < 1h to create, I'm not sure what would block us from
> mainlining the r8a7796 *including* this.

Point taken. Lets discuss the change on its merits.

> >>For a starting point, I'd propose to put the r8a7795.dtsi and r8a7796.dtsi
> >>into a graphical diff tool and move all common parts to a rcar3.dtsi (I'd be
> >>happy to discuss the name, though)
> >
> >I'm not opposed to that. But being consistent with my statement above
> >I would prefer it to be done as follow-up work.
> >
> >My suspicion is that right now much of the proposed r8a7796.dtsi can be
> >moved into a hypothetical rcar3.dtsi. But that this is because the proposed
> >r8a7796.dtsi is very small. I would not expect nearly such a large
> >proportion of r8a7795.dtsi to be able to be moved into rcar3.dtsi because
> >it enables more hardware blocks and they typically have (or should have in
> >keeping with the prevailing policy as described above) per-SoC bindings.
> 
> 
> What doesn't prevent us to use a rcar3.dtsi like given in
> 
> http://article.gmane.org/gmane.linux.kernel.renesas-soc/4013
> 
> 
> Having a rcar3.dtsi gives us *both* options. It doesn't force us to use the
> one or the other. I.e. we have for each IP block the *option* to declare it
> as common (put it onto rcar3.dtsi) *or* SoC specific (put it into
> r8a779x.dtsi).
> 
> Without having a common rcar3.dtsi we don't have this option at all.
> 
> So I think the conclusion is: Let's have all options (by adding a
> rcar3.dtsi) and then decide for each IP block individually where to place it
> best. Or move it later from the common dtsi to the individual dtsi once
> there is an issue found (what I really doubt that it will happen that often,
> but this is an other topic ;) )

I think that most of the nodes you have moved into the common dtsi file
make sense. But there are some I am less sure about:

* cpus

  Probably there are some central aspects of cpus that are shared
  between the r8a7795 and r8a7796. And I think that your patch captures
  that. But I also think that there will be non-shared aspects and
  perhaps the complexity of splitting the cpus node between per-SoC
  and common dtsi files isn't worth it.

  I don't feel strongly about this at this point.

  I am also particularly sensitive about enabling CPU features across
  multiple SoCs. But I think that the scheme you propose allows for
  per-SoC control of features in per-SoC dtsi files. So I think
  I am ok about that at this point.

  Lastly, shouldn't the cache-controller go inside the cpu node
  in the common dtsi file to reflect the change recently made
  upstream to r8a7795.dtsi and the structure of r8a7796.dtsi in
  the current patchset (v3).

* cpg, scif2

  This is the compatibility string issue.

  Could we at least agree to defer this part of the discussion
  and thus omit these nodes from the common dtsi file at this time?

  I understand that you are concerned that if we don't handle this
  now it will be forgotten. FWIW I strongly doubt this particular
  problem will be forgotten.

> >I believe that there is also a another issue which is that we wish
> >to control enabling features on different SoCs once they are known to work.
> >Of course things slip through the cracks. But blindly assuming all
> >IP blocks enabled for one SoC work on another, even if based on the
> >documentation, seems to be asking for trouble to me. For one thing
> >it implies that the level of firmware support is the same.
> >
> >As for a name, I suggest rcar-gen3.dtsi.
> 
> 
> Sounds good to me :)
> 
> 
> Best regards
> 
> Dirk
> 
> 
> 
> 


From horms at verge.net.au  Thu May 26 17:47:07 2016
From: horms at verge.net.au (Simon Horman)
Date: Fri, 27 May 2016 09:47:07 +0900
Subject: [PATCH] rm64: dts: r8a7795: Drop 0x from unit address of gic
In-Reply-To: <CAMuHMdVUSmRtFHFA1E9_sqFUEo9KER2CSW4qtjcsY0LWs6tfeA@mail.gmail.com>
References: <1464138700-12219-1-git-send-email-horms+renesas@verge.net.au>
 <CAMuHMdVUSmRtFHFA1E9_sqFUEo9KER2CSW4qtjcsY0LWs6tfeA@mail.gmail.com>
Message-ID: <20160527004706.GF14269@verge.net.au>

On Wed, May 25, 2016 at 09:02:17AM +0200, Geert Uytterhoeven wrote:
> On Wed, May 25, 2016 at 3:11 AM, Simon Horman
> <horms+renesas at verge.net.au> wrote:
> > Drop 0x from unit address of gic as this is the desired form for
> > a unit address.
> >
> > Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
> 
> If you increase the entropy of the universe even more by adding the missing
> "a" prefix to the one-line summary, you can add my
> 
> Acked-by: Geert Uytterhoeven <geert+renesas at glider.be>

deal.


From julian.calaby at gmail.com  Thu May 26 19:05:12 2016
From: julian.calaby at gmail.com (Julian Calaby)
Date: Fri, 27 May 2016 12:05:12 +1000
Subject: [linux-sunxi] [PATCH 1/5] spi: sunxi: fix transfer timeout
In-Reply-To: <cb90b922caa6ac07c1425d726ea19709ee5284f4.1464130597.git.hramrach@gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
 <cb90b922caa6ac07c1425d726ea19709ee5284f4.1464130597.git.hramrach@gmail.com>
Message-ID: <CAGRGNgWDrVHG26umTSHHAxFC3KXjwmpDejBAfKqvuik0_2-Jcw@mail.gmail.com>

Hi Michal,

On Fri, May 27, 2016 at 5:25 AM, Michal Suchanek <hramrach at gmail.com> wrote:
> The trasfer timeout is fixed at 1000 ms. Reading a 4Mbyte flash over
> 1MHz SPI bus takes way longer than that. Calculate the timeout from the
> actual time the transfer is supposed to take and multiply by 2 for good
> measure.
>
> Signed-off-by: Michal Suchanek <hramrach at gmail.com>
> ---
>
> v2:
> - fix build error
> - use unsigned instead of int in max_t
> - use tfr->speed_hz instead of sspi->max_speed_hz
> ---
>  drivers/spi/spi-sun4i.c | 11 ++++++++++-
>  drivers/spi/spi-sun6i.c | 11 ++++++++++-
>  2 files changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
> index 1ddd9e2..fe63bbd 100644
> --- a/drivers/spi/spi-sun4i.c
> +++ b/drivers/spi/spi-sun4i.c
> @@ -173,6 +173,7 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
>  {
>         struct sun4i_spi *sspi = spi_master_get_devdata(master);
>         unsigned int mclk_rate, div, timeout;
> +       unsigned int start, end, tx_time;
>         unsigned int tx_len = 0;
>         int ret = 0;
>         u32 reg;
> @@ -279,9 +280,17 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
>         reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
>         sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
>
> +       tx_time = max_t(unsigned, tfr->len * 8 * 2 / (tfr->speed_hz / 1000),

You should probably use "unsigned int" instead of just "unsigned" here.

> +                       100);
> +       start = jiffies;
>         timeout = wait_for_completion_timeout(&sspi->done,
> -                                             msecs_to_jiffies(1000));
> +                                             msecs_to_jiffies(tx_time));
> +       end = jiffies;
>         if (!timeout) {
> +               dev_warn(&master->dev,
> +                        "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
> +                        dev_name(&spi->dev), tfr->len, tfr->speed_hz,
> +                        jiffies_to_msecs(end - start), tx_time);

Should the debug changes be in a separate patch?

>                 ret = -ETIMEDOUT;
>                 goto out;
>         }
> diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
> index 42e2c4b..8be5c5c 100644
> --- a/drivers/spi/spi-sun6i.c
> +++ b/drivers/spi/spi-sun6i.c
> @@ -162,6 +162,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
>         unsigned int mclk_rate, div, timeout;
>         unsigned int tx_len = 0;
>         int ret = 0;
> +       unsigned int start, end, tx_time;
>         u32 reg;
>
>         /* We don't support transfer larger than the FIFO */
> @@ -269,9 +270,17 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
>         reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
>         sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
>
> +       tx_time = max_t(unsigned, tfr->len * 8 * 2 / (tfr->speed_hz / 1000),

Ditto, "unsigned int" instead of "unsigned"?

> +                       100);
> +       start = jiffies;
>         timeout = wait_for_completion_timeout(&sspi->done,
> -                                             msecs_to_jiffies(1000));
> +                                             msecs_to_jiffies(tx_time));
> +       end = jiffies;
>         if (!timeout) {
> +               dev_warn(&master->dev,
> +                        "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
> +                        dev_name(&spi->dev), tfr->len, tfr->speed_hz,
> +                        jiffies_to_msecs(end - start), tx_time);

Ditto, separate patch?

Also, should the changes for the drivers be in two separate patches also?

Thanks,

-- 
Julian Calaby

Email: julian.calaby at gmail.com
Profile: http://www.google.com/profiles/julian.calaby/


From thunder.leizhen at huawei.com  Thu May 26 19:35:51 2016
From: thunder.leizhen at huawei.com (Leizhen (ThunderTown))
Date: Fri, 27 May 2016 10:35:51 +0800
Subject: [PATCH 3/3] arm64/numa: fix type info
In-Reply-To: <57472E8C.1050607@gmail.com>
References: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
 <1464230639-9852-3-git-send-email-thunder.leizhen@huawei.com>
 <CAFpQJXWih2V9Ki-vkL+cDni=VoWL0nA-fx5B5XtfNxFsoUso-g@mail.gmail.com>
 <1464280503.16344.40.camel@perches.com> <57472E8C.1050607@gmail.com>
Message-ID: <5747B287.7050309@huawei.com>



On 2016/5/27 1:12, David Daney wrote:
> The current patch to correct this problem is here:
> 
> https://lkml.org/lkml/2016/5/24/679
> 
> Since v7 of the ACPI/NUMA patches are likely going to be added to linux-next as soon as the current merge window ends, further simplifications of the informational prints should probably be rebased on top of it.
> 
> David Daney
> 

>> On Thu, 2016-05-26 at 09:22 -0700, Ganapatrao Kulkarni wrote:
>>> IIRC, it should be
>>> if (!numa_off)
>>> we want to print this message when we failed to find proper numa configuration.
>>> when numa_off is set, we will not look for any numa configuration.
>>>
>>>>
>>>> +               pr_info("%s\n", "No NUMA configuration found");
>>


OK, I think I also missed some cases.

But my problem still have not been resolved by "https://lkml.org/lkml/2016/5/24/679", see below. I will update my patches base on it.


[    0.000000] NUMA: Adding memblock [0x0 - 0x6affffff] on node 0
[    0.000000] NUMA: parsing numa-distance-map-v1
[    0.000000] NUMA: Warning: invalid memblk node 4 [mem 0x6b000000-0x7fbfffff]		//My numa configuration is incorrect, but not "No ... found"
[    0.000000] No NUMA configuration found						//Above warning is very detail, this can be removed
[    0.000000] NUMA: Faking a node at [mem 0x0000000000000000-0x00000017ffffffff]



From yamada.masahiro at socionext.com  Thu May 26 20:23:11 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Fri, 27 May 2016 12:23:11 +0900
Subject: [PATCH v2] ARM: avoid duplicated "Kernel: arch/arm/boot/*Image is
 ready" log
In-Reply-To: <1459736970-21876-1-git-send-email-yamada.masahiro@socionext.com>
References: <1459736970-21876-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CAK7LNATwQn5v_2=-Z++awyOXcHuJkZ8Oxs+f3XtKOksnYwoZTA@mail.gmail.com>

Hi.

Assuming no objection to this patch,
I will put it into Russell's patch tracker after v4.7-rc1 is out.



2016-04-04 11:29 GMT+09:00 Masahiro Yamada <yamada.masahiro at socionext.com>:
> Commit 3939f3345050 ("ARM: 8418/1: add boot image dependencies to not
> generate invalid images") fixed bad image generation in case of
> parallel building, but as a side effect, Kbuild now descends into
> arch/arm/boot/ again and again, duplicating the log messages.  It is
> clumsy, so let's display the same message only once.
>
> I moved the log rules from arch/arm/boot/Makefile to arch/arm/Makefile
> rather than completely deleting them, because *Image are the final
> targets that users are interested in.
>
> Without this commit, the log of incremental build is like follows:
>
> $ make ARCH=arm UIMAGE_LOADADDR=0x80208000 uImage
>   CHK     include/config/kernel.release
>   CHK     include/generated/uapi/linux/version.h
>   CHK     include/generated/utsrelease.h
>   CHK     include/generated/bounds.h
>   CHK     include/generated/timeconst.h
>   CHK     include/generated/asm-offsets.h
>   CALL    scripts/checksyscalls.sh
> <stdin>:1310:2: warning: #warning syscall preadv2 not implemented [-Wcpp]
> <stdin>:1313:2: warning: #warning syscall pwritev2 not implemented [-Wcpp]
>   CHK     include/generated/compile.h
>   Kernel: arch/arm/boot/Image is ready
>   Kernel: arch/arm/boot/Image is ready
>   Kernel: arch/arm/boot/zImage is ready
>   Kernel: arch/arm/boot/Image is ready
>   Kernel: arch/arm/boot/zImage is ready
>   Image arch/arm/boot/uImage is ready
>
> With this commit:
>
> $ make ARCH=arm UIMAGE_LOADADDR=0x80208000 uImage
>   CHK     include/config/kernel.release
>   CHK     include/generated/uapi/linux/version.h
>   CHK     include/generated/utsrelease.h
>   CHK     include/generated/bounds.h
>   CHK     include/generated/timeconst.h
>   CHK     include/generated/asm-offsets.h
>   CALL    scripts/checksyscalls.sh
> <stdin>:1310:2: warning: #warning syscall preadv2 not implemented [-Wcpp]
> <stdin>:1313:2: warning: #warning syscall pwritev2 not implemented [-Wcpp]
>   CHK     include/generated/compile.h
>   Kernel: Image is ready
>   Kernel: zImage is ready
>   Kernel: uImage is ready
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>


-- 
Best Regards
Masahiro Yamada


From thunder.leizhen at huawei.com  Thu May 26 20:36:31 2016
From: thunder.leizhen at huawei.com (Leizhen (ThunderTown))
Date: Fri, 27 May 2016 11:36:31 +0800
Subject: [PATCH 2/3] of/numa: fix a memory@ dt node can only contains one
 memory block
In-Reply-To: <20160526131345.GA12024@rob-hp-laptop>
References: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
 <1464230639-9852-2-git-send-email-thunder.leizhen@huawei.com>
 <20160526131345.GA12024@rob-hp-laptop>
Message-ID: <5747C0BF.505@huawei.com>



On 2016/5/26 21:13, Rob Herring wrote:
> On Thu, May 26, 2016 at 10:43:58AM +0800, Zhen Lei wrote:
>> For a normal memory@ devicetree node, its reg property can contains more
>> memory blocks.
>>
>> Because we don't known how many memory blocks maybe contained, so we try
>> from index=0, increase 1 until error returned(the end).
>>
>> Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
>> ---
>>  drivers/of/of_numa.c | 30 ++++++++++++++++++++----------
>>  1 file changed, 20 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
>> index 21d831f..2c5f249 100644
>> --- a/drivers/of/of_numa.c
>> +++ b/drivers/of/of_numa.c
>> @@ -63,7 +63,7 @@ static int __init of_numa_parse_memory_nodes(void)
>>  	struct device_node *np = NULL;
>>  	struct resource rsrc;
>>  	u32 nid;
>> -	int r = 0;
>> +	int i, r = 0;
>>
>>  	for (;;) {
>>  		np = of_find_node_by_type(np, "memory");
>> @@ -82,17 +82,27 @@ static int __init of_numa_parse_memory_nodes(void)
>>  			/* some other error */
>>  			break;
>>
>> -		r = of_address_to_resource(np, 0, &rsrc);
>> -		if (r) {
>> -			pr_err("NUMA: bad reg property in memory node\n");
>> -			break;
>> +		for (i = 0; ; i++) {
>> +			r = of_address_to_resource(np, i, &rsrc);
>> +			if (r) {
>> +				/* reached the end of of_address */
>> +				if (i > 0) {
>> +					r = 0;
>> +					break;
>> +				}
>> +
>> +				pr_err("NUMA: bad reg property in memory node\n");
>> +				goto finished;
>> +			}
>> +
>> +			r = numa_add_memblk(nid, rsrc.start,
>> +					    rsrc.end - rsrc.start + 1);
>> +			if (r)
>> +				goto finished;
>>  		}
>> -
>> -		r = numa_add_memblk(nid, rsrc.start,
>> -				    rsrc.end - rsrc.start + 1);
>> -		if (r)
>> -			break;
>>  	}
>> +
>> +finished:
>>  	of_node_put(np);
> 
> This function can be simplified down to:
> 
> 	for_each_node_by_type(np, "memory") {
OK, That's good.

> 		r = of_property_read_u32(np, "numa-node-id", &nid);
> 		if (r == -EINVAL)
> 			/*
> 			 * property doesn't exist if -EINVAL, continue
> 			 * looking for more memory nodes with
> 			 * "numa-node-id" property
> 			 */
> 			continue;
Hi, everybody:
    If some "memory" node contains "numa-node-id", but some others missed. Can we simply ignored it?
I think we should break out too, and faking to only have node0.

> 		else if (r)
> 			/* some other error */
> 			break;
> 
> 		r = of_address_to_resource(np, 0, &rsrc);
> 		for (i = 0; !r; i++, r = of_address_to_resource(np, i, 

But r(non-zero) is just break this loop, the original is break the outer for (;;) loop

How about as below?

	for_each_node_by_type(np, "memory") {
		... ...

		for (i = 0; !of_address_to_resource(np, i, &rsrc); i++) {
                        r = numa_add_memblk(nid, rsrc.start,
                                            rsrc.end - rsrc.start + 1);
                        if (r)
                                goto finished;
                }

		if (!i)
			pr_err("NUMA: bad reg property in memory node\n");
	}

finished:
	

> &rsrc)) {
> 			r = numa_add_memblk(nid, rsrc.start,
> 				    rsrc.end - rsrc.start + 1);
> 		}
> 	}
> 	of_node_put(np);
> 
> 	return r;
> 
> 
> Perhaps with a "if (!i && r) pr_err()" for an error message at the end.
> 
> Rob
> 
> .
> 



From robh at kernel.org  Thu May 26 21:20:55 2016
From: robh at kernel.org (Rob Herring)
Date: Thu, 26 May 2016 23:20:55 -0500
Subject: [PATCH 2/3] of/numa: fix a memory@ dt node can only contains one
 memory block
In-Reply-To: <5747C0BF.505@huawei.com>
References: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
 <1464230639-9852-2-git-send-email-thunder.leizhen@huawei.com>
 <20160526131345.GA12024@rob-hp-laptop> <5747C0BF.505@huawei.com>
Message-ID: <CAL_JsqJXu36qYMOZeWDnMQ8BnOxMrixv5N70hvTjDixhMCQKRw@mail.gmail.com>

On Thu, May 26, 2016 at 10:36 PM, Leizhen (ThunderTown)
<thunder.leizhen at huawei.com> wrote:
>
>
> On 2016/5/26 21:13, Rob Herring wrote:
>> On Thu, May 26, 2016 at 10:43:58AM +0800, Zhen Lei wrote:
>>> For a normal memory@ devicetree node, its reg property can contains more
>>> memory blocks.
>>>
>>> Because we don't known how many memory blocks maybe contained, so we try
>>> from index=0, increase 1 until error returned(the end).
>>>
>>> Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
>>> ---
>>>  drivers/of/of_numa.c | 30 ++++++++++++++++++++----------
>>>  1 file changed, 20 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
>>> index 21d831f..2c5f249 100644
>>> --- a/drivers/of/of_numa.c
>>> +++ b/drivers/of/of_numa.c
>>> @@ -63,7 +63,7 @@ static int __init of_numa_parse_memory_nodes(void)
>>>      struct device_node *np = NULL;
>>>      struct resource rsrc;
>>>      u32 nid;
>>> -    int r = 0;
>>> +    int i, r = 0;
>>>
>>>      for (;;) {
>>>              np = of_find_node_by_type(np, "memory");
>>> @@ -82,17 +82,27 @@ static int __init of_numa_parse_memory_nodes(void)
>>>                      /* some other error */
>>>                      break;
>>>
>>> -            r = of_address_to_resource(np, 0, &rsrc);
>>> -            if (r) {
>>> -                    pr_err("NUMA: bad reg property in memory node\n");
>>> -                    break;
>>> +            for (i = 0; ; i++) {
>>> +                    r = of_address_to_resource(np, i, &rsrc);
>>> +                    if (r) {
>>> +                            /* reached the end of of_address */
>>> +                            if (i > 0) {
>>> +                                    r = 0;
>>> +                                    break;
>>> +                            }
>>> +
>>> +                            pr_err("NUMA: bad reg property in memory node\n");
>>> +                            goto finished;
>>> +                    }
>>> +
>>> +                    r = numa_add_memblk(nid, rsrc.start,
>>> +                                        rsrc.end - rsrc.start + 1);
>>> +                    if (r)
>>> +                            goto finished;
>>>              }
>>> -
>>> -            r = numa_add_memblk(nid, rsrc.start,
>>> -                                rsrc.end - rsrc.start + 1);
>>> -            if (r)
>>> -                    break;
>>>      }
>>> +
>>> +finished:
>>>      of_node_put(np);
>>
>> This function can be simplified down to:
>>
>>       for_each_node_by_type(np, "memory") {
> OK, That's good.
>
>>               r = of_property_read_u32(np, "numa-node-id", &nid);
>>               if (r == -EINVAL)
>>                       /*
>>                        * property doesn't exist if -EINVAL, continue
>>                        * looking for more memory nodes with
>>                        * "numa-node-id" property
>>                        */
>>                       continue;
> Hi, everybody:
>     If some "memory" node contains "numa-node-id", but some others missed. Can we simply ignored it?
> I think we should break out too, and faking to only have node0.

Continuing to work is probably better than not.

>
>>               else if (r)
>>                       /* some other error */
>>                       break;
>>
>>               r = of_address_to_resource(np, 0, &rsrc);
>>               for (i = 0; !r; i++, r = of_address_to_resource(np, i,
>
> But r(non-zero) is just break this loop, the original is break the outer for (;;) loop

It is not really the kernel's job to validate the DT. If there's
random things in it then kernel's behavior is undefined.

>
> How about as below?
>
>         for_each_node_by_type(np, "memory") {
>                 ... ...
>
>                 for (i = 0; !of_address_to_resource(np, i, &rsrc); i++) {
>                         r = numa_add_memblk(nid, rsrc.start,
>                                             rsrc.end - rsrc.start + 1);
>                         if (r)
>                                 goto finished;
>                 }
>
>                 if (!i)
>                         pr_err("NUMA: bad reg property in memory node\n");
>         }
>
> finished:

Please try to avoid the goto. You can check r in the outer loop too.

Rob


From hramrach at gmail.com  Thu May 26 22:05:12 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: Fri, 27 May 2016 07:05:12 +0200
Subject: [linux-sunxi] [PATCH 1/5] spi: sunxi: fix transfer timeout
In-Reply-To: <CAGRGNgWDrVHG26umTSHHAxFC3KXjwmpDejBAfKqvuik0_2-Jcw@mail.gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
 <cb90b922caa6ac07c1425d726ea19709ee5284f4.1464130597.git.hramrach@gmail.com>
 <CAGRGNgWDrVHG26umTSHHAxFC3KXjwmpDejBAfKqvuik0_2-Jcw@mail.gmail.com>
Message-ID: <CAOMqctS0AD6rHGt3wjxxyidee=_5xqby95t5TGuozAA12DdPjQ@mail.gmail.com>

On 27 May 2016 at 04:05, Julian Calaby <julian.calaby at gmail.com> wrote:
> Hi Michal,
>
> On Fri, May 27, 2016 at 5:25 AM, Michal Suchanek <hramrach at gmail.com> wrote:
>> The trasfer timeout is fixed at 1000 ms. Reading a 4Mbyte flash over
>> 1MHz SPI bus takes way longer than that. Calculate the timeout from the
>> actual time the transfer is supposed to take and multiply by 2 for good
>> measure.
>>
>> Signed-off-by: Michal Suchanek <hramrach at gmail.com>
>> ---
>>
>> v2:
>> - fix build error
>> - use unsigned instead of int in max_t
>> - use tfr->speed_hz instead of sspi->max_speed_hz
>> ---
>>  drivers/spi/spi-sun4i.c | 11 ++++++++++-
>>  drivers/spi/spi-sun6i.c | 11 ++++++++++-
>>  2 files changed, 20 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
>> index 1ddd9e2..fe63bbd 100644
>> --- a/drivers/spi/spi-sun4i.c
>> +++ b/drivers/spi/spi-sun4i.c
>> @@ -173,6 +173,7 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
>>  {
>>         struct sun4i_spi *sspi = spi_master_get_devdata(master);
>>         unsigned int mclk_rate, div, timeout;
>> +       unsigned int start, end, tx_time;
>>         unsigned int tx_len = 0;
>>         int ret = 0;
>>         u32 reg;
>> @@ -279,9 +280,17 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
>>         reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
>>         sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
>>
>> +       tx_time = max_t(unsigned, tfr->len * 8 * 2 / (tfr->speed_hz / 1000),
>
> You should probably use "unsigned int" instead of just "unsigned" here.
>
>> +                       100);

Or just 100U constant and avoid max_t altogether.

>> +       start = jiffies;
>>         timeout = wait_for_completion_timeout(&sspi->done,
>> -                                             msecs_to_jiffies(1000));
>> +                                             msecs_to_jiffies(tx_time));
>> +       end = jiffies;
>>         if (!timeout) {
>> +               dev_warn(&master->dev,
>> +                        "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
>> +                        dev_name(&spi->dev), tfr->len, tfr->speed_hz,
>> +                        jiffies_to_msecs(end - start), tx_time);
>
> Should the debug changes be in a separate patch?

Is this so big of a change that it needs to be split?

>
>>                 ret = -ETIMEDOUT;
>>                 goto out;
>>         }
>> diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
>> index 42e2c4b..8be5c5c 100644
>> --- a/drivers/spi/spi-sun6i.c
>> +++ b/drivers/spi/spi-sun6i.c
>> @@ -162,6 +162,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
>>         unsigned int mclk_rate, div, timeout;
>>         unsigned int tx_len = 0;
>>         int ret = 0;
>> +       unsigned int start, end, tx_time;
>>         u32 reg;
>>
>>         /* We don't support transfer larger than the FIFO */
>> @@ -269,9 +270,17 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
>>         reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
>>         sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
>>
>> +       tx_time = max_t(unsigned, tfr->len * 8 * 2 / (tfr->speed_hz / 1000),
>
> Ditto, "unsigned int" instead of "unsigned"?
>
>> +                       100);
>> +       start = jiffies;
>>         timeout = wait_for_completion_timeout(&sspi->done,
>> -                                             msecs_to_jiffies(1000));
>> +                                             msecs_to_jiffies(tx_time));
>> +       end = jiffies;
>>         if (!timeout) {
>> +               dev_warn(&master->dev,
>> +                        "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
>> +                        dev_name(&spi->dev), tfr->len, tfr->speed_hz,
>> +                        jiffies_to_msecs(end - start), tx_time);
>
> Ditto, separate patch?
>
> Also, should the changes for the drivers be in two separate patches also?

That's basically the same driver with different constants so I guess not.

Thanks

Michal


From julian.calaby at gmail.com  Thu May 26 22:10:11 2016
From: julian.calaby at gmail.com (Julian Calaby)
Date: Fri, 27 May 2016 15:10:11 +1000
Subject: [linux-sunxi] [PATCH 1/5] spi: sunxi: fix transfer timeout
In-Reply-To: <CAOMqctS0AD6rHGt3wjxxyidee=_5xqby95t5TGuozAA12DdPjQ@mail.gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
 <cb90b922caa6ac07c1425d726ea19709ee5284f4.1464130597.git.hramrach@gmail.com>
 <CAGRGNgWDrVHG26umTSHHAxFC3KXjwmpDejBAfKqvuik0_2-Jcw@mail.gmail.com>
 <CAOMqctS0AD6rHGt3wjxxyidee=_5xqby95t5TGuozAA12DdPjQ@mail.gmail.com>
Message-ID: <CAGRGNgW=UnmwwiREV+nVcws6sk18-4fKz3qf-WKf4LY9-VqBKg@mail.gmail.com>

Hi Michal,

On Fri, May 27, 2016 at 3:05 PM, Michal Suchanek <hramrach at gmail.com> wrote:
> On 27 May 2016 at 04:05, Julian Calaby <julian.calaby at gmail.com> wrote:
>> Hi Michal,
>>
>> On Fri, May 27, 2016 at 5:25 AM, Michal Suchanek <hramrach at gmail.com> wrote:
>>> The trasfer timeout is fixed at 1000 ms. Reading a 4Mbyte flash over
>>> 1MHz SPI bus takes way longer than that. Calculate the timeout from the
>>> actual time the transfer is supposed to take and multiply by 2 for good
>>> measure.
>>>
>>> Signed-off-by: Michal Suchanek <hramrach at gmail.com>
>>> ---
>>>
>>> v2:
>>> - fix build error
>>> - use unsigned instead of int in max_t
>>> - use tfr->speed_hz instead of sspi->max_speed_hz
>>> ---
>>>  drivers/spi/spi-sun4i.c | 11 ++++++++++-
>>>  drivers/spi/spi-sun6i.c | 11 ++++++++++-
>>>  2 files changed, 20 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
>>> index 1ddd9e2..fe63bbd 100644
>>> --- a/drivers/spi/spi-sun4i.c
>>> +++ b/drivers/spi/spi-sun4i.c
>>> @@ -173,6 +173,7 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
>>>  {
>>>         struct sun4i_spi *sspi = spi_master_get_devdata(master);
>>>         unsigned int mclk_rate, div, timeout;
>>> +       unsigned int start, end, tx_time;
>>>         unsigned int tx_len = 0;
>>>         int ret = 0;
>>>         u32 reg;
>>> @@ -279,9 +280,17 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
>>>         reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
>>>         sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
>>>
>>> +       tx_time = max_t(unsigned, tfr->len * 8 * 2 / (tfr->speed_hz / 1000),
>>
>> You should probably use "unsigned int" instead of just "unsigned" here.
>>
>>> +                       100);
>
> Or just 100U constant and avoid max_t altogether.
>
>>> +       start = jiffies;
>>>         timeout = wait_for_completion_timeout(&sspi->done,
>>> -                                             msecs_to_jiffies(1000));
>>> +                                             msecs_to_jiffies(tx_time));
>>> +       end = jiffies;
>>>         if (!timeout) {
>>> +               dev_warn(&master->dev,
>>> +                        "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
>>> +                        dev_name(&spi->dev), tfr->len, tfr->speed_hz,
>>> +                        jiffies_to_msecs(end - start), tx_time);
>>
>> Should the debug changes be in a separate patch?
>
> Is this so big of a change that it needs to be split?

Some people get touchy about changes not being mentioned in the commit
log. Technically this is two changes: fixing the timeout and adding
the timeout debugging, however they're related, so maybe just mention
that you've added this debugging in the commit log.

>
>>
>>>                 ret = -ETIMEDOUT;
>>>                 goto out;
>>>         }
>>> diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
>>> index 42e2c4b..8be5c5c 100644
>>> --- a/drivers/spi/spi-sun6i.c
>>> +++ b/drivers/spi/spi-sun6i.c
>>> @@ -162,6 +162,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
>>>         unsigned int mclk_rate, div, timeout;
>>>         unsigned int tx_len = 0;
>>>         int ret = 0;
>>> +       unsigned int start, end, tx_time;
>>>         u32 reg;
>>>
>>>         /* We don't support transfer larger than the FIFO */
>>> @@ -269,9 +270,17 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
>>>         reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
>>>         sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
>>>
>>> +       tx_time = max_t(unsigned, tfr->len * 8 * 2 / (tfr->speed_hz / 1000),
>>
>> Ditto, "unsigned int" instead of "unsigned"?
>>
>>> +                       100);
>>> +       start = jiffies;
>>>         timeout = wait_for_completion_timeout(&sspi->done,
>>> -                                             msecs_to_jiffies(1000));
>>> +                                             msecs_to_jiffies(tx_time));
>>> +       end = jiffies;
>>>         if (!timeout) {
>>> +               dev_warn(&master->dev,
>>> +                        "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
>>> +                        dev_name(&spi->dev), tfr->len, tfr->speed_hz,
>>> +                        jiffies_to_msecs(end - start), tx_time);
>>
>> Ditto, separate patch?
>>
>> Also, should the changes for the drivers be in two separate patches also?
>
> That's basically the same driver with different constants so I guess not.

Fair enough, I withdraw my comment then.

Thanks,

-- 
Julian Calaby

Email: julian.calaby at gmail.com
Profile: http://www.google.com/profiles/julian.calaby/


From hs.liao at mediatek.com  Thu May 26 22:44:18 2016
From: hs.liao at mediatek.com (Horng-Shyang Liao)
Date: Fri, 27 May 2016 13:44:18 +0800
Subject: [PATCH v7 2/4] CMDQ: Mediatek CMDQ driver
In-Reply-To: <1464247708.13536.14.camel@mtksdaap41>
References: <1464006190-344-1-git-send-email-hs.liao@mediatek.com>
 <1464006190-344-3-git-send-email-hs.liao@mediatek.com>
 <1464059159.7425.6.camel@mtksdaap41> <1464092829.19894.16.camel@mtksdaap41>
 <1464247708.13536.14.camel@mtksdaap41>
Message-ID: <1464327858.8578.6.camel@mtksdaap41>

Hi CK,

Reply in line.

On Thu, 2016-05-26 at 15:28 +0800, CK Hu wrote:
> Hi, HS:
> 
> Replay inline.
> 
> On Tue, 2016-05-24 at 20:27 +0800, Horng-Shyang Liao wrote:
> > Hi CK,
> > 
> > Reply in line.
> > 
> > On Tue, 2016-05-24 at 11:05 +0800, CK Hu wrote:
> > > Hi, HS:
> > > 
> > > Some comments below.
> > > 
> > ...
> > > > +static void cmdq_thread_irq_handler(struct cmdq *cmdq, int tid)
> > > > +{
> > > > +	struct cmdq_thread *thread = &cmdq->thread[tid];
> > > > +	unsigned long flags = 0L;
> > > > +	int value;
> > > > +
> > > > +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> > > > +
> > > > +	/*
> > > > +	 * it is possible for another CPU core
> > > > +	 * to run "release task" right before we acquire the spin lock
> > > > +	 * and thus reset / disable this HW thread
> > > > +	 * so we check both the IRQ flag and the enable bit of this thread
> > > > +	 */
> > > > +	value = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> > > > +	if (!(value & CMDQ_THR_IRQ_MASK)) {
> > > > +		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > > > +		return;
> > > > +	}
> > > 
> > > If this case happen and just return without clearing irq status, the irq
> > > would keep triggering and system hang up. So just remove this checking
> > > and go down to clear irq status.
> > 
> > This case is safe because irq status is cleared.
> > But, next if condition has the problem which you mentioned.
> > 
> > I will change it as below.
> > 
> > 	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> > 	      CMDQ_THR_ENABLED)) {
> > 		cmdq_thread_writel(thread, ~value, CMDQ_THR_IRQ_STATUS);
> > 		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > 		return;
> > 	}
> > 
> > If thread is disabled, tasks must be all finished.
> > Therefore, just clear irq status and return.
> > 
> 
> For irq status checking part, if irq status & irq mask is zero, remove
> this checking and let it go down, it still do nothing because value &
> CMDQ_THR_IRQ_ERROR is zero and value & CMDQ_THR_IRQ_DONE is zero. So you
> can just remove this checking and get the same result.
> 
> In general HW design, once a HW is not enable, it does not trigger
> interrupt any more. Be sure that it's necessary to clear irq status even
> though thread is disable.
> 

I Will remove first if condition,
so rewrite first two if condition parts as below.

value = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
cmdq_thread_writel(thread, ~value, CMDQ_THR_IRQ_STATUS);

if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
			CMDQ_THR_ENABLED))
	value = 0;

> > > > +
> > > > +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> > > > +	      CMDQ_THR_ENABLED)) {
> > > > +		spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > > > +		return;
> > > > +	}
> > > > +
> > > > +	cmdq_thread_writel(thread, ~value, CMDQ_THR_IRQ_STATUS);
> > > > +
> > > > +	if (value & CMDQ_THR_IRQ_ERROR)
> > > > +		cmdq_handle_error_done(cmdq, thread, true);
> > > > +	else if (value & CMDQ_THR_IRQ_DONE)
> > > > +		cmdq_handle_error_done(cmdq, thread, false);
> > > 
> > > These irq status checking and clearing code here is the same as those in
> > > cmdq_task_handle_error_result(). To move the checking and clearing code
> > > into cmdq_handle_error_done() and here just to call
> > > cmdq_handle_error_done(cmdq, thread) would reduce duplicated code.
> > 
> > Will do.
> > 
> > > > +
> > > > +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > > > +}
> > ...
> > ...
> > > 
> > > Regards,
> > > CK
> > 
> > Thanks,
> > HS
> > 
> 
> Regards,
> CK
> 
> 

Thanks,
HS



From heiko.carstens at de.ibm.com  Thu May 26 22:52:54 2016
From: heiko.carstens at de.ibm.com (Heiko Carstens)
Date: Fri, 27 May 2016 07:52:54 +0200
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160525.123017.1597296248000772613.davem@davemloft.net>
References: <1464048292-30136-1-git-send-email-ynorov@caviumnetworks.com>
 <1464048292-30136-2-git-send-email-ynorov@caviumnetworks.com>
 <20160525.123017.1597296248000772613.davem@davemloft.net>
Message-ID: <20160527055254.GA3820@osiris>

On Wed, May 25, 2016 at 12:30:17PM -0700, David Miller wrote:
> From: Yury Norov <ynorov at caviumnetworks.com>
> Date: Tue, 24 May 2016 03:04:30 +0300
> 
> > +To clear that top halves, automatic wrappers are introduced. They clear all
> > +required registers before passing control to regular syscall handler.
> 
> Why have one of these for every single compat system call, rather than
> simply clearing the top half of all of these registers unconditionally
> in the 32-bit system call trap before the system call is invoked?
> 
> That's what we do on sparc64.
> 
> And with that, you only need wrappers for the case where there needs
> to be proper sign extention of a 32-bit signed argument.

That would probably also work for arm. On s390 we still have these odd 31
bit pointers in compat mode which require us to clear 33 bits instead of 32
bits. That makes up for appr. one third of all system calls.

The additional wrappers are only for zero/sign extension, where I count a
total of 27 on s390.

The reason for doing this in C was the constant copy-paste error rate, when
adding new system calls plus I got a rid of a lot of unnecessary asm code.



From zyw at rock-chips.com  Thu May 26 23:02:13 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 14:02:13 +0800
Subject: [PATCH 0/6] Rockchip Type-C and DispplayPort driver
Message-ID: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>

Hi all

This series patch is for rockchip Type-C phy and DisplayPort controller
driver.

The USB Type-C PHY is designed to support the USB3 and DP applications.
The PHY basically has two main components: USB3 and DisplyPort. USB3
operates in SuperSpeed mode and the DP can operate at RBR, HBR and HBR2
data rates. The Type-C cable orientation detection and Power Delivery
(PD) is accomplished using a PD PHY or a exernal PD chip.

The DP controller is compliant with DisplayPort Specification,
Version 1.3, This IP is compatible with the rockchip type-c PHY IP.
There is a uCPU in DP controller, it need a firmware to work, please
put the firmware file to /lib/firmware/cdn/dptx.bin. The uCPU in charge
of aux communication and link training, the host use mailbox to
communicate with the ucpu.

The PHY driver has register a notification, to get the alt mode from PD,
the PD driver need call the tcphy_notifier_call_chain to notify PHY and
DP controller.

This series is based on Mark Yao's branch:
https://github.com/markyzq/kernel-drm-rockchip/tree/drm-rockchip-next-2016-05-23

I test this patches on the rk3399-evb board, with a fusb302 driver,
this branch has no rk3399.dtsi, so the patch about dts is not included
in this series.



Chris Zhong (6):
  phy: Add USB Type-C PHY driver for rk3399
  Documentation: bindings: add dt doc for Rockchip USB Type-C PHY
  drm/rockchip: vop: add cdn DP support for rk3399
  Documentation: bindings: add dt documentation for cdn DP controller
  ASoC: cdn-dp: Add cdn DP codec driver
  ASoC: rockchip: Add machine driver for cdn dp codec

 .../bindings/display/rockchip/cdn-dp-rockchip.txt  |  57 ++
 .../devicetree/bindings/phy/phy-rockchip-typec.txt |  55 ++
 .../bindings/sound/rockchip-cdn-dp-audio.txt       |  12 +
 drivers/gpu/drm/rockchip/Kconfig                   |   9 +
 drivers/gpu/drm/rockchip/Makefile                  |   1 +
 drivers/gpu/drm/rockchip/cdn-dp-core.c             | 620 ++++++++++++++++
 drivers/gpu/drm/rockchip/cdn-dp-core.h             |  95 +++
 drivers/gpu/drm/rockchip/cdn-dp-reg.c              | 730 ++++++++++++++++++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h              | 404 ++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c        |   9 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h        |   2 +
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c        |   2 +
 drivers/phy/Kconfig                                |   7 +
 drivers/phy/Makefile                               |   1 +
 drivers/phy/phy-rockchip-typec.c                   | 823 +++++++++++++++++++++
 include/sound/cdn-dp-audio.h                       |  51 ++
 sound/soc/codecs/Kconfig                           |   3 +
 sound/soc/codecs/Makefile                          |   2 +
 sound/soc/codecs/cdn-dp-audio.c                    | 246 ++++++
 sound/soc/rockchip/Kconfig                         |   9 +
 sound/soc/rockchip/Makefile                        |   2 +
 sound/soc/rockchip/rockchip-cdn-dp-audio.c         | 167 +++++
 22 files changed, 3306 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt
 create mode 100644 Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip-cdn-dp-audio.txt
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-core.c
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-core.h
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-reg.c
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-reg.h
 create mode 100644 drivers/phy/phy-rockchip-typec.c
 create mode 100644 include/sound/cdn-dp-audio.h
 create mode 100644 sound/soc/codecs/cdn-dp-audio.c
 create mode 100644 sound/soc/rockchip/rockchip-cdn-dp-audio.c

-- 
2.6.3



From zyw at rock-chips.com  Thu May 26 23:02:14 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 14:02:14 +0800
Subject: [PATCH 1/6] phy: Add USB Type-C PHY driver for rk3399
In-Reply-To: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1464328939-8073-2-git-send-email-zyw@rock-chips.com>

Add a PHY provider driver for the rk3399 SoC Type-c PHY. The USB
Type-C PHY is designed to support the USB3 and DP applications. The
PHY basically has two main components: USB3 and DisplyPort. USB3
operates in SuperSpeed mode and the DP can operate at RBR, HBR and
HBR2 data rates.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
---

 drivers/phy/Kconfig              |   7 +
 drivers/phy/Makefile             |   1 +
 drivers/phy/phy-rockchip-typec.c | 823 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 831 insertions(+)
 create mode 100644 drivers/phy/phy-rockchip-typec.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 26566db..dc388a3d 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -351,6 +351,13 @@ config PHY_ROCKCHIP_DP
 	help
 	  Enable this to support the Rockchip Display Port PHY.
 
+config PHY_ROCKCHIP_TYPEC
+	tristate "Rockchip TYPEC PHY Driver"
+	depends on ARCH_ROCKCHIP && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the Rockchip USB TYPEC PHY.
+
 config PHY_ST_SPEAR1310_MIPHY
 	tristate "ST SPEAR1310-MIPHY driver"
 	select GENERIC_PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 24596a9..91fa413 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_PHY_QCOM_APQ8064_SATA)	+= phy-qcom-apq8064-sata.o
 obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
 obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o
 obj-$(CONFIG_PHY_ROCKCHIP_DP)		+= phy-rockchip-dp.o
+obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
 obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)	+= phy-qcom-ipq806x-sata.o
 obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY)	+= phy-spear1310-miphy.o
 obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY)	+= phy-spear1340-miphy.o
diff --git a/drivers/phy/phy-rockchip-typec.c b/drivers/phy/phy-rockchip-typec.c
new file mode 100644
index 0000000..6609cfb
--- /dev/null
+++ b/drivers/phy/phy-rockchip-typec.c
@@ -0,0 +1,823 @@
+/*
+ * Rockchip usb3 PHY driver
+ *
+ * Copyright (C) 2016 Kever Yang <kever.yang at rock-chips.com>
+ *                    Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/delay.h>
+#include <linux/phy/phy-rockchip-typec.h>
+
+#define ADDR_ADJ			2
+#define CMN_SSM_BANDGAP			(0x21 << ADDR_ADJ)
+#define CMN_SSM_BIAS			(0x22 << ADDR_ADJ)
+#define CMN_PLLSM0_PLLEN		(0x29 << ADDR_ADJ)
+#define CMN_PLLSM0_PLLPRE		(0x2a << ADDR_ADJ)
+#define CMN_PLLSM0_PLLVREF		(0x2b << ADDR_ADJ)
+#define CMN_PLLSM0_PLLLOCK		(0x2c << ADDR_ADJ)
+#define CMN_PLLSM1_PLLEN		(0x31 << ADDR_ADJ)
+#define CMN_PLLSM1_PLLPRE		(0x32 << ADDR_ADJ)
+#define CMN_PLLSM1_PLLVREF		(0x33 << ADDR_ADJ)
+#define CMN_PLLSM1_PLLLOCK		(0x34 << ADDR_ADJ)
+#define CMN_PLLSM1_USER_DEF_CTRL	(0x37 << ADDR_ADJ)
+#define CMN_ICAL_OVRD			(0xc1 << ADDR_ADJ)
+#define CMN_PLL0_VCOCAL_OVRD		(0x83 << ADDR_ADJ)
+#define CMN_PLL0_VCOCAL_INIT		(0x84 << ADDR_ADJ)
+#define CMN_PLL0_VCOCAL_ITER		(0x85 << ADDR_ADJ)
+#define CMN_PLL0_LOCK_REFCNT_START	(0x90 << ADDR_ADJ)
+#define CMN_PLL0_LOCK_PLLCNT_START	(0x92 << ADDR_ADJ)
+#define CMN_PLL0_LOCK_PLLCNT_THR	(0x93 << ADDR_ADJ)
+#define CMN_PLL0_INTDIV			(0x94 << ADDR_ADJ)
+#define CMN_PLL0_FRACDIV		(0x95 << ADDR_ADJ)
+#define CMN_PLL0_HIGH_THR		(0x96 << ADDR_ADJ)
+#define CMN_PLL0_DSM_DIAG		(0x97 << ADDR_ADJ)
+#define CMN_PLL0_SS_CTRL1		(0x98 << ADDR_ADJ)
+#define CMN_PLL0_SS_CTRL2		(0x99 << ADDR_ADJ)
+#define CMN_PLL1_VCOCAL_START		(0xa1 << ADDR_ADJ)
+#define CMN_PLL1_VCOCAL_OVRD		(0xa3 << ADDR_ADJ)
+#define CMN_PLL1_VCOCAL_INIT		(0xa4 << ADDR_ADJ)
+#define CMN_PLL1_VCOCAL_ITER		(0xa5 << ADDR_ADJ)
+#define CMN_PLL1_LOCK_REFCNT_START	(0xb0 << ADDR_ADJ)
+#define CMN_PLL1_LOCK_PLLCNT_START	(0xb2 << ADDR_ADJ)
+#define CMN_PLL1_LOCK_PLLCNT_THR	(0xb3 << ADDR_ADJ)
+#define CMN_PLL1_INTDIV			(0xb4 << ADDR_ADJ)
+#define CMN_PLL1_FRACDIV		(0xb5 << ADDR_ADJ)
+#define CMN_PLL1_HIGH_THR		(0xb6 << ADDR_ADJ)
+#define CMN_PLL1_DSM_DIAG		(0xb7 << ADDR_ADJ)
+#define CMN_PLL1_SS_CTRL1		(0xb8 << ADDR_ADJ)
+#define CMN_PLL1_SS_CTRL2		(0xb9 << ADDR_ADJ)
+#define CMN_RXCAL_OVRD			(0xd1 << ADDR_ADJ)
+#define CMN_TXPUCAL_CTRL		(0xe0 << ADDR_ADJ)
+#define CMN_TXPUCAL_OVRD		(0xe1 << ADDR_ADJ)
+#define CMN_TXPDCAL_OVRD		(0xf1 << ADDR_ADJ)
+#define CMN_DIAG_PLL0_FBH_OVRD		(0x1c0 << ADDR_ADJ)
+#define CMN_DIAG_PLL0_FBL_OVRD		(0x1c1 << ADDR_ADJ)
+#define CMN_DIAG_PLL0_OVRD		(0x1c2 << ADDR_ADJ)
+#define CMN_DIAG_PLL0_V2I_TUNE		(0x1c5 << ADDR_ADJ)
+#define CMN_DIAG_PLL0_CP_TUNE		(0x1c6 << ADDR_ADJ)
+#define CMN_DIAG_PLL0_LF_PROG		(0x1c7 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_FBH_OVRD		(0x1d0 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_FBL_OVRD		(0x1d1 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_OVRD		(0x1d2 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_V2I_TUNE		(0x1d5 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_CP_TUNE		(0x1d6 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_LF_PROG		(0x1d7 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_PTATIS_TUNE1	(0x1d8 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_PTATIS_TUNE2	(0x1d9 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_INCLK_CTRL	(0x1da << ADDR_ADJ)
+#define CMN_DIAG_HSCLK_SEL		(0x1e0 << ADDR_ADJ)
+
+#define XCVR_PSM_RCTRL(n)		((0x4001 | (n << 9)) << ADDR_ADJ)
+#define XCVR_PSM_CAL_TMR(n)		((0x4002 | (n << 9)) << ADDR_ADJ)
+#define XCVR_PSM_A0IN_TMR(n)		((0x4003 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_CAL_SCLR_MULT(n)	((0x4047 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_CPOST_MULT_00(n)	((0x404c | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_CPOST_MULT_01(n)	((0x404d | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_CPOST_MULT_10(n)	((0x404e | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_CPOST_MULT_11(n)	((0x404f | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_000(n)	((0x4050 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_001(n)	((0x4051 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_010(n)	((0x4052 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_011(n)	((0x4053 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_100(n)	((0x4054 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_101(n)	((0x4055 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_110(n)	((0x4056 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_111(n)	((0x4057 | (n << 9)) << ADDR_ADJ)
+#define XCVR_DIAG_PLLDRC_CTRL(n)	((0x40e0 | (n << 9)) << ADDR_ADJ)
+#define XCVR_DIAG_BIDI_CTRL(n)		((0x40e8 | (n << 9)) << ADDR_ADJ)
+#define XCVR_DIAG_LANE_FCM_EN_MGN(n)	((0x40f2 | (n << 9)) << ADDR_ADJ)
+#define TX_PSC_A0(n)			((0x4100 | (n << 9)) << ADDR_ADJ)
+#define TX_PSC_A1(n)			((0x4101 | (n << 9)) << ADDR_ADJ)
+#define TX_PSC_A2(n)			((0x4102 | (n << 9)) << ADDR_ADJ)
+#define TX_PSC_A3(n)			((0x4103 | (n << 9)) << ADDR_ADJ)
+#define TX_RCVDET_CTRL(n)		((0x4120 | (n << 9)) << ADDR_ADJ)
+#define TX_RCVDET_EN_TMR(n)		((0x4122 | (n << 9)) << ADDR_ADJ)
+#define TX_RCVDET_ST_TMR(n)		((0x4123 | (n << 9)) << ADDR_ADJ)
+#define TX_DIAG_TX_DRV(n)		((0x41e1 | (n << 9)) << ADDR_ADJ)
+#define TX_DIAG_BGREF_PREDRV_DELAY	(0x41e7 << ADDR_ADJ)
+#define TX_ANA_CTRL_REG_1		(0x5020 << ADDR_ADJ)
+#define TX_ANA_CTRL_REG_2		(0x5021 << ADDR_ADJ)
+#define TXDA_COEFF_CALC_CTRL		(0x5022 << ADDR_ADJ)
+#define TX_DIG_CTRL_REG_2		(0x5024 << ADDR_ADJ)
+#define TXDA_CYA_AUXDA_CYA		(0x5025 << ADDR_ADJ)
+#define TX_ANA_CTRL_REG_3		(0x5026 << ADDR_ADJ)
+#define TX_ANA_CTRL_REG_4		(0x5027 << ADDR_ADJ)
+#define TX_ANA_CTRL_REG_5		(0x5029 << ADDR_ADJ)
+
+#define RX_PSC_A0(n)			((0x8000 | (n << 9)) << ADDR_ADJ)
+#define RX_PSC_A1(n)			((0x8001 | (n << 9)) << ADDR_ADJ)
+#define RX_PSC_A2(n)			((0x8002 | (n << 9)) << ADDR_ADJ)
+#define RX_PSC_A3(n)			((0x8003 | (n << 9)) << ADDR_ADJ)
+#define RX_PSC_CAL(n)			((0x8006 | (n << 9)) << ADDR_ADJ)
+#define RX_PSC_RDY(n)			((0x8007 | (n << 9)) << ADDR_ADJ)
+#define RX_IQPI_ILL_CAL_OVRD		(0x8023 << ADDR_ADJ)
+#define RX_EPI_ILL_CAL_OVRD		(0x8033 << ADDR_ADJ)
+#define RX_SDCAL0_OVRD			(0x8041 << ADDR_ADJ)
+#define RX_SDCAL1_OVRD			(0x8049 << ADDR_ADJ)
+#define RX_SLC_INIT			(0x806d << ADDR_ADJ)
+#define RX_SLC_RUN			(0x806e << ADDR_ADJ)
+#define RX_CDRLF_CNFG2			(0x8081 << ADDR_ADJ)
+#define RX_SIGDET_HL_FILT_TMR(n)	((0x8090 | (n << 9)) << ADDR_ADJ)
+#define RX_SLC_IOP0_OVRD		(0x8101 << ADDR_ADJ)
+#define RX_SLC_IOP1_OVRD		(0x8105 << ADDR_ADJ)
+#define RX_SLC_QOP0_OVRD		(0x8109 << ADDR_ADJ)
+#define RX_SLC_QOP1_OVRD		(0x810d << ADDR_ADJ)
+#define RX_SLC_EOP0_OVRD		(0x8111 << ADDR_ADJ)
+#define RX_SLC_EOP1_OVRD		(0x8115 << ADDR_ADJ)
+#define RX_SLC_ION0_OVRD		(0x8119 << ADDR_ADJ)
+#define RX_SLC_ION1_OVRD		(0x811d << ADDR_ADJ)
+#define RX_SLC_QON0_OVRD		(0x8121 << ADDR_ADJ)
+#define RX_SLC_QON1_OVRD		(0x8125 << ADDR_ADJ)
+#define RX_SLC_EON0_OVRD		(0x8129 << ADDR_ADJ)
+#define RX_SLC_EON1_OVRD		(0x812d << ADDR_ADJ)
+#define RX_SLC_IEP0_OVRD		(0x8131 << ADDR_ADJ)
+#define RX_SLC_IEP1_OVRD		(0x8135 << ADDR_ADJ)
+#define RX_SLC_QEP0_OVRD		(0x8139 << ADDR_ADJ)
+#define RX_SLC_QEP1_OVRD		(0x813d << ADDR_ADJ)
+#define RX_SLC_EEP0_OVRD		(0x8141 << ADDR_ADJ)
+#define RX_SLC_EEP1_OVRD		(0x8145 << ADDR_ADJ)
+#define RX_SLC_IEN0_OVRD		(0x8149 << ADDR_ADJ)
+#define RX_SLC_IEN1_OVRD		(0x814d << ADDR_ADJ)
+#define RX_SLC_QEN0_OVRD		(0x8151 << ADDR_ADJ)
+#define RX_SLC_QEN1_OVRD		(0x8155 << ADDR_ADJ)
+#define RX_SLC_EEN0_OVRD		(0x8159 << ADDR_ADJ)
+#define RX_SLC_EEN1_OVRD		(0x815d << ADDR_ADJ)
+#define RX_DIAG_SIGDET_TUNE(n)		((0x81dc | (n << 9)) << ADDR_ADJ)
+#define RX_DIAG_SC2C_DELAY		(0x81e1 << ADDR_ADJ)
+
+#define PMA_LANE_CFG			(0xc000 << ADDR_ADJ)
+#define PIPE_CMN_CTRL1			(0xc001 << ADDR_ADJ)
+#define PIPE_CMN_CTRL2			(0xc002 << ADDR_ADJ)
+#define PIPE_COM_LOCK_CFG1		(0xc003 << ADDR_ADJ)
+#define PIPE_COM_LOCK_CFG2		(0xc004 << ADDR_ADJ)
+#define PIPE_RCV_DET_INH		(0xc005 << ADDR_ADJ)
+#define DP_MODE_CTL			(0xc008 << ADDR_ADJ)
+#define DP_CLK_CTL			(0xc009 << ADDR_ADJ)
+#define STS				(0xc00F << ADDR_ADJ)
+#define PHY_ISO_CMN_CTRL		(0xc010 << ADDR_ADJ)
+#define PHY_DP_TX_CTL			(0xc408 << ADDR_ADJ)
+#define PMA_CMN_CTRL1			(0xc800 << ADDR_ADJ)
+#define PHY_PMA_ISO_CMN_CTRL		(0xc810 << ADDR_ADJ)
+#define PHY_ISOLATION_CTRL		(0xc81f << ADDR_ADJ)
+#define PHY_PMA_ISO_XCVR_CTRL(n)	((0xcc11 | (n << 6)) << ADDR_ADJ)
+#define PHY_PMA_ISO_LINK_MODE(n)	((0xcc12 | (n << 6)) << ADDR_ADJ)
+#define PHY_PMA_ISO_PWRST_CTRL(n)	((0xcc13 | (n << 6)) << ADDR_ADJ)
+#define PHY_PMA_ISO_TX_DATA_LO(n)	((0xcc14 | (n << 6)) << ADDR_ADJ)
+#define PHY_PMA_ISO_TX_DATA_HI(n)	((0xcc15 | (n << 6)) << ADDR_ADJ)
+#define PHY_PMA_ISO_RX_DATA_LO(n)	((0xcc16 | (n << 6)) << ADDR_ADJ)
+#define PHY_PMA_ISO_RX_DATA_HI(n)	((0xcc17 | (n << 6)) << ADDR_ADJ)
+#define TX_BIST_CTRL(n)			((0x4140 | (n << 9)) << ADDR_ADJ)
+#define TX_BIST_UDDWR(n)		((0x4141 | (n << 9)) << ADDR_ADJ)
+
+#define GRF_SOC_CON26			0x6268
+#define UPHY_DP_SEL			BIT(3)
+#define UPHY_DP_SEL_MASK		BIT(19)
+#define DPTX_HDP_SEL			(3 << 12)
+#define DPTX_HDP_SEL_MASK		(3 << 28)
+
+#define PHY_MODE_SET_TIMEOUT		1000000
+
+#define	MODE_DISCONNECT			1
+#define	MODE_UFP			2
+#define	MODE_DFP_USBONLY		3
+#define	MODE_DFP_DPONLY			4
+#define	MODE_DFP_USB3DP			5
+#define	MODE_DFP_USB2DP			6
+
+#define PARSE_GRF_REG(TYPE) { \
+	if (of_find_property(np, "rockchip,usb3phy_"#TYPE, &len)) { \
+		len /= sizeof(u32);\
+		ret = of_property_read_u32_array(np, "rockchip,usb3phy_" #TYPE,\
+						 array, len); \
+		exregs->usb3phy_##TYPE = array[0]; \
+		exregs->usb3phy_##TYPE##_shift = array[1]; \
+		exregs->usb3phy_##TYPE##_mask = array[2]; \
+		pr_info("%s property found %s, %x, %d, %d\n", __func__, \
+			"rockchip,usb3phy_"#TYPE, \
+			array[0], array[1], array[2]); \
+	} else { \
+		pr_info("%s property not found %s\n", __func__, \
+			"rockchip,usb3phy_" #TYPE); \
+	} \
+}
+
+struct rockchip_typec_phy *rockchip_tcphy;
+
+static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy,
+			  unsigned int num_lanes)
+{
+	unsigned int i;
+
+	writel(0x830, tcphy->base + PMA_CMN_CTRL1);
+	for (i = 0; i < num_lanes; i++) {
+		writel(0x90, tcphy->base + XCVR_DIAG_LANE_FCM_EN_MGN(i));
+		writel(0x960, tcphy->base + TX_RCVDET_EN_TMR(i));
+		writel(0x30, tcphy->base + TX_RCVDET_ST_TMR(i));
+	}
+}
+
+static void tcphy_cfg_usb_pll(struct rockchip_typec_phy *tcphy)
+{
+	unsigned int rdata;
+
+	rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
+	writel(rdata & 0xfffc, tcphy->base + CMN_DIAG_HSCLK_SEL);
+	writel(0xf0, tcphy->base + CMN_PLL0_VCOCAL_INIT);
+	writel(0x18, tcphy->base + CMN_PLL0_VCOCAL_ITER);
+	writel(0xd0, tcphy->base + CMN_PLL0_INTDIV);
+	writel(0x4a4a, tcphy->base + CMN_PLL0_FRACDIV);
+	writel(0x34, tcphy->base + CMN_PLL0_HIGH_THR);
+	writel(0x1ee, tcphy->base + CMN_PLL0_SS_CTRL1);
+	writel(0x7f03, tcphy->base + CMN_PLL0_SS_CTRL2);
+	writel(0x20, tcphy->base + CMN_PLL0_DSM_DIAG);
+	writel(0, tcphy->base + CMN_DIAG_PLL0_OVRD);
+	writel(0, tcphy->base + CMN_DIAG_PLL0_FBH_OVRD);
+	writel(0, tcphy->base + CMN_DIAG_PLL0_FBL_OVRD);
+	writel(0x7, tcphy->base + CMN_DIAG_PLL0_V2I_TUNE);
+	writel(0x45, tcphy->base + CMN_DIAG_PLL0_CP_TUNE);
+	writel(0x8, tcphy->base + CMN_DIAG_PLL0_LF_PROG);
+}
+
+static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy)
+{
+	unsigned int rdata;
+
+	writel(0x2405, tcphy->base + DP_CLK_CTL);
+
+	rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
+	rdata = (rdata & 0xffcf) | 0x30;
+	writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL);
+	writel(0xf0, tcphy->base + CMN_PLL1_VCOCAL_INIT);
+	writel(0x18, tcphy->base + CMN_PLL1_VCOCAL_ITER);
+	writel(0x30b9, tcphy->base + CMN_PLL1_VCOCAL_START);
+	writel(0x21c, tcphy->base + CMN_PLL1_INTDIV);
+	writel(0, tcphy->base + CMN_PLL1_FRACDIV);
+	writel(0x5, tcphy->base + CMN_PLL1_HIGH_THR);
+	writel(0x35, tcphy->base + CMN_PLL1_SS_CTRL1);
+	writel(0x7f1e, tcphy->base + CMN_PLL1_SS_CTRL2);
+	writel(0x20, tcphy->base + CMN_PLL1_DSM_DIAG);
+	writel(0, tcphy->base + CMN_PLLSM1_USER_DEF_CTRL);
+	writel(0, tcphy->base + CMN_DIAG_PLL1_OVRD);
+	writel(0, tcphy->base + CMN_DIAG_PLL1_FBH_OVRD);
+	writel(0, tcphy->base + CMN_DIAG_PLL1_FBL_OVRD);
+	writel(0x6, tcphy->base + CMN_DIAG_PLL1_V2I_TUNE);
+	writel(0x45, tcphy->base + CMN_DIAG_PLL1_CP_TUNE);
+	writel(0x8, tcphy->base + CMN_DIAG_PLL1_LF_PROG);
+	writel(0x100, tcphy->base + CMN_DIAG_PLL1_PTATIS_TUNE1);
+	writel(0x7, tcphy->base + CMN_DIAG_PLL1_PTATIS_TUNE2);
+	writel(0x4, tcphy->base + CMN_DIAG_PLL1_INCLK_CTRL);
+}
+
+static void tcphy_tx_usb_cfg_lane(struct rockchip_typec_phy *tcphy,
+				  unsigned int lane)
+{
+	writel(0x7799, tcphy->base + TX_PSC_A0(lane));
+	writel(0x7798, tcphy->base + TX_PSC_A1(lane));
+	writel(0x5098, tcphy->base + TX_PSC_A2(lane));
+	writel(0x5098, tcphy->base + TX_PSC_A3(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
+	writel(0xbf, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
+}
+
+static void tcphy_rx_usb_cfg_lane(struct rockchip_typec_phy *tcphy,
+				  unsigned int lane)
+{
+	writel(0xa6fd, tcphy->base + RX_PSC_A0(lane));
+	writel(0xa6fd, tcphy->base + RX_PSC_A1(lane));
+	writel(0xa410, tcphy->base + RX_PSC_A2(lane));
+	writel(0x2410, tcphy->base + RX_PSC_A3(lane));
+	writel(0x23ff, tcphy->base + RX_PSC_CAL(lane));
+	writel(0x13, tcphy->base + RX_SIGDET_HL_FILT_TMR(lane));
+	writel(0x1004, tcphy->base + RX_DIAG_SIGDET_TUNE(lane));
+	writel(0x2010, tcphy->base + RX_PSC_RDY(lane));
+	writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
+}
+
+static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy,
+			      unsigned int lane)
+{
+	unsigned int rdata;
+
+	writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
+	writel(0x6799, tcphy->base + TX_PSC_A0(lane));
+	writel(0x6798, tcphy->base + TX_PSC_A1(lane));
+	writel(0x98, tcphy->base + TX_PSC_A2(lane));
+	writel(0x98, tcphy->base + TX_PSC_A3(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane));
+
+	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane));
+	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane));
+	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
+	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane));
+
+	writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
+	writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
+
+	rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+	rdata = (rdata & 0x8fff) | 0x6000;
+	writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+}
+
+static void tcphy_cfg_pin_assign(struct rockchip_typec_phy *tcphy)
+{
+	switch (tcphy->map) {
+	case PIN_MAP_A:
+		writel(0x19d5, tcphy->base + PMA_LANE_CFG);
+		break;
+	case PIN_MAP_B:
+		writel(0x1500, tcphy->base + PMA_LANE_CFG);
+		break;
+	case PIN_MAP_C:
+	case PIN_MAP_E:
+		writel(0x51d9, tcphy->base + PMA_LANE_CFG);
+		break;
+	case PIN_MAP_D:
+	case PIN_MAP_F:
+		writel(0x5100, tcphy->base + PMA_LANE_CFG);
+		break;
+	};
+}
+
+static void tcphy_cfg_lanes(struct rockchip_typec_phy *tcphy,
+			    unsigned int link_cfg)
+{
+	unsigned int i;
+
+	/* PMA lane configuration DP or USB3 */
+	for (i = 0; i < 4; i++) {
+		if ((link_cfg >> i) & 0x1) {
+			tcphy_dp_cfg_lane(tcphy, i);
+		} else {
+			/*
+			 * lan0 TX and lan1 RX for USB3 Normal direction
+			 * lan3 TX and lan2 RX for USB3 Flip direction
+			 */
+			if ((i == 0) | (i == 3))
+				tcphy_tx_usb_cfg_lane(tcphy, i);
+			else
+				tcphy_rx_usb_cfg_lane(tcphy, i);
+		}
+	}
+}
+
+static void tcphy_cfg_flip_set(struct rockchip_typec_phy *tcphy)
+{
+	regmap_write(tcphy->grf_regs,
+		     tcphy->exregs.usb3phy_con0,
+		     tcphy->flip | BIT(16));
+
+	tcphy_cfg_24m(tcphy, 0x4);
+
+	if (tcphy->mode == MODE_UFP ||
+	    tcphy->mode == MODE_DFP_USBONLY ||
+	    tcphy->mode == MODE_DFP_USB3DP)
+		tcphy_cfg_usb_pll(tcphy);
+
+	if (tcphy->mode == MODE_DFP_DPONLY ||
+	    tcphy->mode == MODE_DFP_USB2DP ||
+	    tcphy->mode == MODE_DFP_USB3DP)
+		tcphy_cfg_dp_pll(tcphy);
+
+	if (tcphy->mode == MODE_DFP_DPONLY || tcphy->mode == MODE_DFP_USB2DP)
+		tcphy_cfg_lanes(tcphy, 0xf);
+	else if (tcphy->flip)
+		tcphy_cfg_lanes(tcphy, 0x3);
+	else
+		tcphy_cfg_lanes(tcphy, 0xc);
+}
+
+static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
+{
+	int rdata, rdata2, val;
+
+	rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
+	rdata2 = readl(tcphy->base + CMN_TXPUCAL_CTRL);
+
+	rdata = rdata & 0xdfff;
+	writel(rdata, tcphy->base + TX_ANA_CTRL_REG_1);
+
+	rdata = readl(tcphy->base + TX_DIG_CTRL_REG_2);
+	rdata = rdata & 0xffc0;
+	rdata2 = rdata2 & 0x3f;
+	rdata  = rdata | rdata2;
+	writel(rdata, tcphy->base + TX_DIG_CTRL_REG_2);
+	usleep_range(1000, 2000);
+
+	rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
+	rdata = rdata | 0x2000;
+	writel(rdata, tcphy->base + TX_ANA_CTRL_REG_1);
+
+	usleep_range(150, 200);
+
+	writel(0, tcphy->base + PHY_DP_TX_CTL);
+	writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2);
+	writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2);
+	writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
+	writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1);
+	writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1);
+	writel(0x30C, tcphy->base + TX_ANA_CTRL_REG_2);
+	writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
+	writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4);
+	writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1);
+	writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1);
+	writel(0x30d, tcphy->base + TX_ANA_CTRL_REG_2);
+	writel(0x30f, tcphy->base + TX_ANA_CTRL_REG_2);
+
+	if (tcphy->flip)
+		writel(0xa078, tcphy->base + TX_ANA_CTRL_REG_1);
+	else
+		writel(0xb078, tcphy->base + TX_ANA_CTRL_REG_1);
+
+	writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2);
+	writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
+	writel(0, tcphy->base + TX_ANA_CTRL_REG_4);
+	writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
+	writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL);
+	writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA);
+
+	val = readl(tcphy->base + TX_DIG_CTRL_REG_2);
+	val |= BIT(15);
+	writel(val, tcphy->base + TX_DIG_CTRL_REG_2);
+}
+
+static void tcphy_dp_hpd(struct rockchip_typec_phy *tcphy,
+			 u8 mode)
+{
+	/* force hpd */
+	if (mode)
+		regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
+			     DPTX_HDP_SEL_MASK | DPTX_HDP_SEL);
+	else
+		regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
+			     DPTX_HDP_SEL_MASK);
+}
+
+static int tcphy_usb3_init(struct rockchip_typec_phy *tcphy)
+{
+	int timeout = 0;
+	int ret, val;
+
+	/*wait TCPHY for pipe ready */
+	while (1) {
+		ret = regmap_read(tcphy->grf_regs,
+				  tcphy->exregs.usb3phy_status0, &val);
+		val >>= tcphy->exregs.usb3phy_status0_shift;
+		if ((val & 0x1) == 0)
+			break;
+
+		timeout++;
+		if (timeout > 1000) {
+			pr_warn("%s wait pipe ready timerout!\n", __func__);
+			break;
+		}
+		usleep_range(10, 20);
+	}
+
+	return 0;
+}
+
+static int tcphy_dp_init(struct rockchip_typec_phy *tcphy)
+{
+	int ret, val;
+
+	ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
+				 val, val & BIT(6), 1000, PHY_MODE_SET_TIMEOUT);
+	if (ret < 0) {
+		dev_err(tcphy->dev, "failed to wait TCPHY for DP ready\n");
+		return -EBUSY;
+	}
+
+	tcphy_dp_aux_calibration(tcphy);
+
+	if (tcphy->mode == MODE_DFP_USB3DP)
+		writel(0xc101, tcphy->base + DP_MODE_CTL);
+	else
+		writel(0x0101, tcphy->base + DP_MODE_CTL);
+
+	ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
+				 val, val & BIT(4), 1000, PHY_MODE_SET_TIMEOUT);
+	if (ret < 0) {
+		dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int tcphy_phy_init(struct rockchip_typec_phy *tcphy)
+{
+	int ret;
+	int timeout = 0;
+
+	ret = clk_prepare_enable(tcphy->clk_core);
+	if (ret) {
+		dev_err(tcphy->dev, "Failed to prepare_enable core clock\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(tcphy->clk_ref);
+	if (ret) {
+		dev_err(tcphy->dev, "Failed to prepare_enable ref clock\n");
+		return ret;
+	}
+
+	/* select external psm clock */
+	regmap_write(tcphy->grf_regs, tcphy->exregs.usb3phy_con2,
+		     BIT(14) | BIT(30));
+	regmap_write(tcphy->grf_regs, tcphy->exregs.usb3phy_con0, BIT(19));
+
+	reset_control_assert(tcphy->phy_rst);
+	reset_control_assert(tcphy->pipe_rst);
+	reset_control_assert(tcphy->uphy_rst);
+
+	if (tcphy->num == TYPEC_PHY0)
+		regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
+			     UPHY_DP_SEL_MASK);
+	else
+		regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
+			     UPHY_DP_SEL_MASK | UPHY_DP_SEL);
+
+	reset_control_deassert(tcphy->uphy_rst);
+
+	tcphy_cfg_flip_set(tcphy);
+
+	tcphy_cfg_pin_assign(tcphy);
+
+	if (tcphy->mode == MODE_DFP_USB3DP)
+		writel(0xc104, tcphy->base + DP_MODE_CTL);
+	else if ((tcphy->mode == MODE_DFP_DPONLY) ||
+		 (tcphy->mode == MODE_DFP_USB2DP))
+		writel(0x0104, tcphy->base + DP_MODE_CTL);
+
+	reset_control_deassert(tcphy->phy_rst);
+
+	while (!(readl(tcphy->base + PMA_CMN_CTRL1) & 1)) {
+		timeout++;
+		if (timeout > 1000)
+			break;
+		usleep_range(10, 20);
+	}
+
+	reset_control_deassert(tcphy->pipe_rst);
+
+	return 0;
+}
+
+static int tcphy_phy_deinit(struct rockchip_typec_phy *tcphy)
+{
+	clk_disable_unprepare(tcphy->clk_core);
+	clk_disable_unprepare(tcphy->clk_ref);
+
+	return 0;
+}
+
+int tcphy_register_notifier(struct phy *_phy, struct notifier_block *nb)
+{
+	struct rockchip_typec_phy *tcphy = phy_get_drvdata(_phy);
+
+	return atomic_notifier_chain_register(&tcphy->notifier, nb);
+}
+
+void tcphy_unregister_notifier(struct phy *_phy,
+			       struct notifier_block *nb)
+{
+	struct rockchip_typec_phy *tcphy = phy_get_drvdata(_phy);
+
+	atomic_notifier_chain_unregister(&tcphy->notifier, nb);
+}
+
+void tcphy_notifier_call_chain(struct rockchip_typec_phy *x,
+			       unsigned long val, void *v)
+{
+	atomic_notifier_call_chain(&x->notifier, val, v);
+}
+EXPORT_SYMBOL_GPL(tcphy_notifier_call_chain);
+
+static int tcphy_pd_event(struct notifier_block *nb,
+			  unsigned long event, void *priv)
+{
+	struct rockchip_typec_phy *tcphy;
+	int value = *(int *)priv;
+	u8 is_dp, dfp;
+
+	tcphy = container_of(nb, struct rockchip_typec_phy, event_nb);
+	if (IS_ERR_OR_NULL(tcphy)) {
+		pr_err("initialization issue");
+		return -1;
+	}
+
+	tcphy->flip = GET_FLIP(value);
+	dfp = GET_DFP(value);
+	is_dp = GET_DP(value);
+	tcphy->map = GET_PIN_MAP(value);
+
+	if (event == 0) {
+		if (tcphy->mode == MODE_DISCONNECT)
+			return 0;
+		tcphy->mode = MODE_DISCONNECT;
+	} else if (is_dp) {
+		if (tcphy->map & (PIN_MAP_B | PIN_MAP_D | PIN_MAP_F))
+			tcphy->mode = MODE_DFP_USB3DP;
+		else
+			tcphy->mode = MODE_DFP_DPONLY;
+	} else if (dfp) {
+		tcphy->mode = MODE_DFP_USBONLY;
+	} else {
+		tcphy->mode = MODE_UFP;
+	}
+
+	schedule_delayed_work_on(0, &tcphy->event_wq, 0);
+
+	return 0;
+}
+
+static void tcphy_event_wq(struct work_struct *work)
+{
+	struct rockchip_typec_phy *tcphy;
+
+	tcphy = container_of(work, struct rockchip_typec_phy, event_wq.work);
+	if (IS_ERR_OR_NULL(tcphy)) {
+		pr_err("initialization issue");
+		return;
+	}
+
+	switch (tcphy->mode) {
+	case MODE_DISCONNECT:
+		/* phy enter low power mode */
+		tcphy_phy_deinit(tcphy);
+		tcphy_dp_hpd(tcphy, 0);
+		break;
+	case MODE_UFP:
+		tcphy_phy_init(tcphy);
+		tcphy_usb3_init(tcphy);
+		tcphy_dp_hpd(tcphy, 0);
+		break;
+	case MODE_DFP_USBONLY:
+		tcphy_phy_init(tcphy);
+		tcphy_usb3_init(tcphy);
+		tcphy_dp_hpd(tcphy, 0);
+		break;
+	case MODE_DFP_DPONLY:
+	case MODE_DFP_USB2DP:
+		tcphy_phy_init(tcphy);
+		tcphy_dp_init(tcphy);
+		tcphy_dp_hpd(tcphy, 1);
+		break;
+	case MODE_DFP_USB3DP:
+		tcphy_phy_init(tcphy);
+		tcphy_usb3_init(tcphy);
+		tcphy_dp_init(tcphy);
+		tcphy_dp_hpd(tcphy, 1);
+		break;
+	}
+}
+
+int tcphy_parse_reg(struct rockchip_typec_phy *tcphy, struct device *dev)
+{
+	struct tcphy_grf_reg *exregs = &tcphy->exregs;
+	struct device_node *np = dev->of_node;
+	u32 len = 0, array[3];
+	int ret = 0;
+
+	PARSE_GRF_REG(con0);
+	PARSE_GRF_REG(con1);
+	PARSE_GRF_REG(con2);
+	PARSE_GRF_REG(status0);
+	PARSE_GRF_REG(status1);
+	return ret;
+}
+
+static int rockchip_typec_phy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rockchip_typec_phy *tcphy;
+	struct resource *res;
+	struct phy_provider *phy_provider;
+
+	tcphy = devm_kzalloc(dev, sizeof(*tcphy), GFP_KERNEL);
+	if (!tcphy)
+		return -ENOMEM;
+
+	tcphy->dev = dev;
+	platform_set_drvdata(pdev, tcphy);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	tcphy->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(tcphy->base)) {
+		dev_err(dev, "failed to remap phy regs\n");
+		return PTR_ERR(tcphy->base);
+	}
+	tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node,
+							"rockchip,grf");
+	if (IS_ERR(tcphy->grf_regs)) {
+		dev_err(dev, "%s: could not find grf dt node\n", __func__);
+		return PTR_ERR(tcphy->grf_regs);
+	}
+
+	tcphy->clk_core = of_clk_get_by_name(dev->of_node, "tcpdcore");
+	if (IS_ERR(tcphy->clk_core)) {
+		dev_err(dev, "%s: could not get uphy core clock\n", __func__);
+		tcphy->clk_core = NULL;
+	}
+
+	tcphy->clk_ref = of_clk_get_by_name(dev->of_node, "tcpdphy_ref");
+	if (IS_ERR(tcphy->clk_core)) {
+		dev_err(dev, "%s: could not get uphy ref clock\n", __func__);
+		tcphy->clk_core = NULL;
+	}
+
+	tcphy->phy_rst = devm_reset_control_get(dev, "tcphy_rst");
+	if (IS_ERR(tcphy->phy_rst)) {
+		dev_err(dev, "no phy_rst reset control found\n");
+		return PTR_ERR(tcphy->phy_rst);
+	}
+
+	tcphy->pipe_rst = devm_reset_control_get(dev, "tcphy_pipe_rst");
+	if (IS_ERR(tcphy->pipe_rst)) {
+		dev_err(dev, "no pipe_rst reset control found\n");
+		return PTR_ERR(tcphy->pipe_rst);
+	}
+
+	tcphy->uphy_rst = devm_reset_control_get(dev, "uphy_tcphy_rst");
+	if (IS_ERR(tcphy->uphy_rst)) {
+		dev_err(dev, "no uphy_rst reset control found\n");
+		return PTR_ERR(tcphy->uphy_rst);
+	}
+
+	tcphy_parse_reg(tcphy, dev);
+	tcphy->mode = MODE_DISCONNECT;
+
+	tcphy->phy = devm_phy_create(dev, NULL, NULL);
+
+	phy_set_drvdata(tcphy->phy, tcphy);
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+	/* register notifier for PD event */
+	ATOMIC_INIT_NOTIFIER_HEAD(&tcphy->notifier);
+	tcphy->event_nb.notifier_call = tcphy_pd_event;
+	INIT_DELAYED_WORK(&tcphy->event_wq, tcphy_event_wq);
+	tcphy_register_notifier(tcphy->phy, &tcphy->event_nb);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static int rockchip_typec_phy_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id rockchip_typec_phy_dt_ids[] = {
+	{ .compatible = "rockchip,rk3399-typec-phy", },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, rockchip_typec_phy_dt_ids);
+
+static struct platform_driver rockchip_typec_phy_driver = {
+	.probe		= rockchip_typec_phy_probe,
+	.remove		= rockchip_typec_phy_remove,
+	.driver		= {
+		.name	= "rockchip-typec-phy",
+		.of_match_table = rockchip_typec_phy_dt_ids,
+	},
+};
+
+module_platform_driver(rockchip_typec_phy_driver);
+
+MODULE_AUTHOR("Kever Yang<kever.yang at rock-chips.com>");
+MODULE_AUTHOR("Chris Zhong<zyw at rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip USB TYPE-C PHY driver");
+MODULE_LICENSE("GPL v2");
-- 
2.6.3



From zyw at rock-chips.com  Thu May 26 23:02:15 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 14:02:15 +0800
Subject: [PATCH 2/6] Documentation: bindings: add dt doc for Rockchip USB
 Type-C PHY
In-Reply-To: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1464328939-8073-3-git-send-email-zyw@rock-chips.com>

This patch adds a binding that describes the Rockchip USB Type-C PHY
for rk3399.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
---

 .../devicetree/bindings/phy/phy-rockchip-typec.txt | 55 ++++++++++++++++++++++
 1 file changed, 55 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt

diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
new file mode 100644
index 0000000..402f667
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
@@ -0,0 +1,55 @@
+ROCKCHIP type-c PHY
+
+Required properties:
+ - compatible: should be "rockchip,rk3399-typec-phy"
+ - reg : Address and length of the usb phy control register set
+ - rockchip,grf : phandle to the syscon managing the "general
+   register files"
+ - clocks : phandle + clock specifier for the phy clocks
+ - clock-names: string, clock name, must be "tcpdcore", "tcpdphy_ref";
+ - resets : a list of phandle + reset specifier pairs
+ - reset-names : string reset name, must be:
+		 "tcphy_rst", "tcphy_pipe_rst", "uphy_tcphy_rst"
+ - #phy-cells: Must be 0.  See ./phy-bindings.txt for details.
+ - rockchip,usb3phy*: phy registers embed in grf
+
+Example:
+	tcphy0: phy at ff7c0000 {
+		compatible = "rockchip,rk3399-typec-phy";
+		reg = <0x0 0xff7c0000 0x0 0x40000>;
+		#phy-cells = <0>;
+		rockchip,grf = <&grf>;
+		clocks = <&cru SCLK_UPHY0_TCPDCORE>,
+			 <&cru SCLK_UPHY0_TCPDPHY_REF>;
+		clock-names = "tcpdcore", "tcpdphy_ref";
+		resets = <&cru SRST_UPHY0>,
+			 <&cru SRST_UPHY0_PIPE_L00>,
+			 <&cru SRST_P_UPHY0_TCPHY>;
+		reset-names = "tcphy_rst", "tcphy_pipe_rst", "uphy_tcphy_rst";
+		rockchip,usb3phy_con0 = <0x0e580 0 16>;
+		rockchip,usb3phy_con1 = <0x0e584 0 16>;
+		rockchip,usb3phy_con2 = <0x0e588 0 16>;
+		rockchip,usb3phy_status0 = <0x0e5c0 0 13>;
+		rockchip,usb3phy_status1 = <0x0e5c4 0 12>;
+		status = "disabled";
+	};
+
+	tcphy1: phy at ff800000 {
+		compatible = "rockchip,rk3399-typec-phy";
+		reg = <0x0 0xff800000 0x0 0x40000>;
+		#phy-cells = <0>;
+		rockchip,grf = <&grf>;
+		clocks = <&cru SCLK_UPHY1_TCPDCORE>,
+			 <&cru SCLK_UPHY1_TCPDPHY_REF>;
+		clock-names = "tcpdcore", "tcpdphy_ref";
+		resets = <&cru SRST_UPHY1>,
+		         <&cru SRST_UPHY1_PIPE_L00>,
+			 <&cru SRST_P_UPHY1_TCPHY>;
+		reset-names = "tcphy_rst", "tcphy_pipe_rst", "uphy_tcphy_rst";
+		rockchip,usb3phy_con0 = <0x0e58c 0 16>;
+		rockchip,usb3phy_con1 = <0x0e590 0 16>;
+		rockchip,usb3phy_con2 = <0x0e594 0 16>;
+		rockchip,usb3phy_status0 = <0x0e5c0 16 13>;
+		rockchip,usb3phy_status1 = <0x0e5c4 16 12>;
+		status = "disabled";
+	};
-- 
2.6.3



From zyw at rock-chips.com  Thu May 26 23:02:16 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 14:02:16 +0800
Subject: [PATCH 3/6] drm/rockchip: vop: add cdn DP support for rk3399
In-Reply-To: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1464328939-8073-4-git-send-email-zyw@rock-chips.com>

Add support for cdn DP controller which is embedded in the rk3399
SoCs. The DP is compliant with DisplayPort Specification,
Version 1.3, This IP is compatible with the rockchip type-c PHY IP.
There is a uCPU in DP controller, it need a firmware to work,
please put the firmware file to /lib/firmware/cdn/dptx.bin. The
uCPU in charge of aux communication and link training, the host use
mailbox to communicate with the ucpu.
The dclk pin_pol of vop must not be invert for DP.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
---

 drivers/gpu/drm/rockchip/Kconfig            |   9 +
 drivers/gpu/drm/rockchip/Makefile           |   1 +
 drivers/gpu/drm/rockchip/cdn-dp-core.c      | 620 +++++++++++++++++++++++
 drivers/gpu/drm/rockchip/cdn-dp-core.h      |  95 ++++
 drivers/gpu/drm/rockchip/cdn-dp-reg.c       | 730 ++++++++++++++++++++++++++++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h       | 404 +++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |   9 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   2 +
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c |   2 +
 include/sound/cdn-dp-audio.h                |  51 ++
 10 files changed, 1922 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-core.c
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-core.h
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-reg.c
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-reg.h
 create mode 100644 include/sound/cdn-dp-audio.h

diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index d30bdc3..20da9a8 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -25,6 +25,15 @@ config ROCKCHIP_ANALOGIX_DP
 	  for the Analogix Core DP driver. If you want to enable DP
 	  on RK3288 based SoC, you should selet this option.
 
+config ROCKCHIP_CDN_DP
+        tristate "Rockchip cdn DP"
+        depends on DRM_ROCKCHIP
+        help
+	  This selects support for Rockchip SoC specific extensions
+	  for the cdn Dp driver. If you want to enable Dp on
+	  RK3399 based SoC, you should selet this
+	  option.
+
 config ROCKCHIP_DW_HDMI
         tristate "Rockchip specific extensions for Synopsys DW HDMI"
         depends on DRM_ROCKCHIP
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index 05d0713..abdecd5 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -7,6 +7,7 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
 obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
+obj-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
 obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
new file mode 100644
index 0000000..fdf99f5
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -0,0 +1,620 @@
+/*
+ * cdn dp controller core driver
+ *
+ * Copyright (C) 2016 Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * 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 <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_of.h>
+
+#include <linux/component.h>
+#include <linux/clk.h>
+#include <linux/firmware.h>
+#include <linux/mfd/syscon.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-rockchip-typec.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#include <sound/cdn-dp-audio.h>
+
+#include "rockchip_drm_vop.h"
+#include "cdn-dp-reg.h"
+#include "cdn-dp-core.h"
+
+#define connector_to_dp(c) \
+		container_of(c, struct cdn_dp_device, connector)
+
+#define encoder_to_dp(c) \
+		container_of(c, struct cdn_dp_device, encoder)
+
+/* dp grf register offset */
+#define DP_VOP_SEL		0x6224
+#define DP_SEL_VOP_LIT		BIT(12)
+
+static int cdn_dp_clk_enable(struct cdn_dp_device *dp)
+{
+	int ret = 0;
+	int clk_rate = 200000000;
+
+	ret = clk_prepare_enable(dp->pclk);
+	if (ret < 0) {
+		dev_err(dp->dev, "cannot enable dp pclk %d\n", ret);
+		goto err_pclk;
+	}
+
+	ret = clk_prepare_enable(dp->core_clk);
+	if (ret < 0) {
+		dev_err(dp->dev, "cannot enable core_clk %d\n", ret);
+		goto err_core_clk;
+	}
+
+	ret = clk_set_rate(dp->core_clk, clk_rate);
+	if (ret < 0) {
+		dev_err(dp->dev, "cannot set dp core clk to %d %d\n",
+			clk_rate, ret);
+		goto err_set_rate;
+	}
+
+	/* notice fw the clk freq value */
+	cdn_dp_set_fw_clk(dp, clk_rate);
+
+	return 0;
+
+err_set_rate:
+	clk_disable_unprepare(dp->core_clk);
+err_core_clk:
+	clk_disable_unprepare(dp->pclk);
+err_pclk:
+	return ret;
+}
+
+static enum drm_connector_status
+cdn_dp_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct cdn_dp_device *dp = connector_to_dp(connector);
+	int ret;
+
+	if (!dp->fw_loaded)
+		return connector_status_unknown;
+
+	ret = cdn_dp_get_hpd_status(dp);
+	if (ret < 0)
+		return connector_status_unknown;
+
+	dp->plugged = ret;
+
+	return ret ? connector_status_connected : connector_status_disconnected;
+}
+
+static void cdn_dp_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static struct drm_connector_funcs cdn_dp_atomic_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.detect = cdn_dp_connector_detect,
+	.destroy = cdn_dp_connector_destroy,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int cdn_dp_connector_get_modes(struct drm_connector *connector)
+{
+	struct cdn_dp_device *dp = connector_to_dp(connector);
+	struct edid *edid;
+	int ret;
+
+	if (!dp->fw_loaded)
+		return 0;
+
+	ret = cdn_dp_set_host_cap(dp);
+	if (ret) {
+		dev_err(dp->dev, "set host capabilities failed:%d\n", ret);
+		return ret;
+	}
+
+	edid = drm_do_get_edid(connector, cdn_dp_get_edid_block, dp);
+	if (edid) {
+		dev_dbg(dp->dev, "got edid: width[%d] x height[%d]\n",
+			edid->width_cm, edid->height_cm);
+
+		dp->sink_has_audio = drm_detect_monitor_audio(edid);
+		drm_mode_connector_update_edid_property(connector, edid);
+		drm_add_edid_modes(connector, edid);
+		/* Store the ELD */
+		drm_edid_to_eld(connector, edid);
+		kfree(edid);
+	} else {
+		dev_dbg(dp->dev, "failed to get edid\n");
+	}
+
+	/*
+	 * put the training process here, since the mode_valid need the
+	 * training result to check if the resolution is support.
+	 */
+	ret = cdn_dp_training_start(dp);
+	if (ret) {
+		dev_err(dp->dev, "hw lt err:%d\n", ret);
+		return ret;
+	}
+
+	ret = cdn_dp_get_lt_status(dp);
+	if (ret) {
+		dev_err(dp->dev, "hw lt get status err:%d\n", ret);
+		return ret;
+	}
+
+	dev_dbg(dp->dev, "rate:%d, lanes:%d\n",
+		dp->link.rate, dp->link.num_lanes);
+	return 0;
+}
+
+static struct drm_encoder *
+	cdn_dp_connector_best_encoder(struct drm_connector *connector)
+{
+	struct cdn_dp_device *dp = connector_to_dp(connector);
+
+	return &dp->encoder;
+}
+
+static int cdn_dp_connector_mode_valid(struct drm_connector *connector,
+				       struct drm_display_mode *mode)
+{
+	struct cdn_dp_device *dp = connector_to_dp(connector);
+	struct drm_display_info *display_info = &dp->connector.display_info;
+	long requested = mode->clock * display_info->bpc * 3 / 1000;
+	long actual, rate;
+
+	rate = drm_dp_bw_code_to_link_rate(dp->link.rate);
+	actual = rate * dp->link.num_lanes / 100;
+
+	/* efficiency is about 0.8 */
+	actual = actual * 8 / 10;
+
+	if (requested > actual) {
+		dev_dbg(dp->dev, "requested=%ld, actual=%ld, clock=%d, bpc= %d\n",
+			requested, actual, mode->clock, display_info->bpc);
+		return MODE_H_ILLEGAL;
+	}
+
+	return MODE_OK;
+}
+
+static struct drm_connector_helper_funcs cdn_dp_connector_helper_funcs = {
+	.get_modes = cdn_dp_connector_get_modes,
+	.best_encoder = cdn_dp_connector_best_encoder,
+	.mode_valid = cdn_dp_connector_mode_valid,
+};
+
+static int cdn_dp_commit(struct drm_encoder *encoder)
+{
+	struct cdn_dp_device *dp = encoder_to_dp(encoder);
+	int ret;
+
+	cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+
+	ret = cdn_dp_config_video(dp);
+	if (ret) {
+		dev_err(dp->dev, "unable to config video\n");
+		return ret;
+	}
+
+	cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
+	dp->dpms_mode = DRM_MODE_DPMS_ON;
+
+	return ret;
+}
+
+static void cdn_dp_encoder_mode_set(struct drm_encoder *encoder,
+				    struct drm_display_mode *mode,
+				    struct drm_display_mode *adjusted)
+{
+	struct cdn_dp_device *dp = encoder_to_dp(encoder);
+	struct drm_display_info *display_info = &dp->connector.display_info;
+	struct rockchip_crtc_state *state;
+	struct video_info *video = &dp->video_info;
+	int ret, val;
+
+	switch (display_info->bpc) {
+	case 16:
+	case 12:
+	case 10:
+		video->color_depth = 10;
+		break;
+	case 6:
+		video->color_depth = 6;
+		break;
+	default:
+		video->color_depth = 8;
+		break;
+	}
+
+	video->color_fmt = PXL_RGB;
+
+	video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
+	video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
+
+	ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
+	if (ret < 0)
+		return;
+
+	state = to_rockchip_crtc_state(encoder->crtc->state);
+	if (ret) {
+		val = DP_SEL_VOP_LIT | (DP_SEL_VOP_LIT << 16);
+		state->output_mode = ROCKCHIP_OUT_MODE_P888;
+	} else {
+		val = DP_SEL_VOP_LIT << 16;
+		state->output_mode = ROCKCHIP_OUT_MODE_AAAA;
+	}
+	ret = regmap_write(dp->grf, DP_VOP_SEL, val);
+	if (ret != 0)
+		dev_err(dp->dev, "Could not write to GRF: %d\n", ret);
+
+	memcpy(&dp->mode, adjusted, sizeof(*mode));
+}
+
+static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
+{
+	struct cdn_dp_device *dp = encoder_to_dp(encoder);
+
+	if (dp->dpms_mode == DRM_MODE_DPMS_ON)
+		return;
+
+	cdn_dp_commit(encoder);
+}
+
+static void cdn_dp_encoder_disable(struct drm_encoder *encoder)
+{
+	struct cdn_dp_device *dp = encoder_to_dp(encoder);
+
+	if (dp->dpms_mode != DRM_MODE_DPMS_ON)
+		return;
+
+	cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+
+	dp->dpms_mode = DRM_MODE_DPMS_OFF;
+}
+
+static int
+cdn_dp_encoder_atomic_check(struct drm_encoder *encoder,
+			    struct drm_crtc_state *crtc_state,
+			    struct drm_connector_state *conn_state)
+{
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+
+	s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
+	s->output_type = DRM_MODE_CONNECTOR_DisplayPort;
+
+	return 0;
+}
+
+static struct drm_encoder_helper_funcs cdn_dp_encoder_helper_funcs = {
+	.mode_set = cdn_dp_encoder_mode_set,
+	.enable = cdn_dp_encoder_enable,
+	.disable = cdn_dp_encoder_disable,
+	.atomic_check = cdn_dp_encoder_atomic_check,
+};
+
+static struct drm_encoder_funcs cdn_dp_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int cdn_dp_firmware_init(struct cdn_dp_device *dp)
+{
+	int ret;
+	const u32 *iram_data, *dram_data;
+	const struct firmware *fw;
+	const struct cdn_firmware_header *hdr;
+
+	if (dp->fw_loaded)
+		return 0;
+
+	ret = request_firmware(&fw, "cdn/dptx.bin", dp->dev);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to request firmware %d\n", ret);
+		return ret;
+	}
+
+	hdr = (struct cdn_firmware_header *)fw->data;
+	if (fw->size != le32_to_cpu(hdr->size_bytes))
+		return -EINVAL;
+
+	ret = cdn_dp_clk_enable(dp);
+	if (ret < 0) {
+		dev_err(dp->dev, "cannot enable dp clk %d\n", ret);
+		return ret;
+	}
+
+	dp_clock_reset_seq(dp);
+
+	iram_data = (const u32 *)(fw->data + hdr->header_size);
+	dram_data = (const u32 *)(fw->data + hdr->header_size + hdr->iram_size);
+
+	ret = cdn_dp_load_firmware(dp,
+				   iram_data, hdr->iram_size,
+				   dram_data, hdr->dram_size);
+
+	ret = cdn_dp_active(dp, true);
+	if (ret) {
+		dev_err(dp->dev, "active ucpu failed: %d\n", ret);
+		return ret;
+	}
+
+	cdn_dp_event_config(dp);
+
+	return 0;
+}
+
+static int cdn_dp_init(struct cdn_dp_device *dp)
+{
+	struct device *dev = dp->dev;
+	struct device_node *np = dev->of_node;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct resource *res;
+
+	dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+	if (IS_ERR(dp->grf)) {
+		dev_err(dev, "cdn-dp needs rockchip,grf property\n");
+		return PTR_ERR(dp->grf);
+	}
+
+	dp->irq = platform_get_irq(pdev, 0);
+	if (dp->irq < 0) {
+		dev_err(dev, "cdn-dp can not get irq\n");
+		return dp->irq;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dp->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(dp->regs)) {
+		dev_err(dev, "ioremap reg failed\n");
+		return PTR_ERR(dp->regs);
+	}
+
+	dp->core_clk = devm_clk_get(dev, "core_clk");
+	if (IS_ERR(dp->core_clk)) {
+		dev_err(dev, "cannot get core_clk_dp\n");
+		return PTR_ERR(dp->core_clk);
+	}
+
+	dp->pclk = devm_clk_get(dev, "pclk");
+	if (IS_ERR(dp->pclk)) {
+		dev_err(dev, "cannot get pclk\n");
+		return PTR_ERR(dp->pclk);
+	}
+
+	dp->spdif_clk = devm_clk_get(dev, "spdif");
+	if (IS_ERR(dp->spdif_clk)) {
+		dev_err(dev, "cannot get spdif_clk\n");
+		return PTR_ERR(dp->spdif_clk);
+	}
+
+	dp->dpms_mode = DRM_MODE_DPMS_OFF;
+
+	dev_set_name(dp->dev, "cdn-dp");
+
+	return 0;
+}
+
+static const struct cdn_dp_audio_ops dp_audio_ops = {
+	.audio_startup = cdn_dp_audio_start,
+	.audio_shutdown = cdn_dp_audio_stop,
+	.audio_start = cdn_dp_audio_start,
+	.audio_stop = cdn_dp_audio_stop,
+	.audio_config = cdn_dp_audio_config_set,
+};
+
+static int cdn_dp_pd_event(struct notifier_block *nb,
+			   unsigned long event, void *priv)
+{
+	struct cdn_dp_device *dp;
+	u8 map, is_dp;
+	int value = *(int *)priv;
+
+	dp = container_of(nb, struct cdn_dp_device, event_nb);
+	if (IS_ERR_OR_NULL(dp)) {
+		pr_err("initialization issue");
+		return -1;
+	}
+
+	is_dp = GET_DP(value);
+
+	if (!is_dp)
+		return 0;
+
+	dp->flip = GET_FLIP(value);
+	map = GET_PIN_MAP(value);
+	if (map & (PIN_MAP_B | PIN_MAP_D | PIN_MAP_F))
+		dp->cap_lanes = 2;
+	else
+		dp->cap_lanes = 4;
+
+	schedule_delayed_work_on(0, &dp->event_wq, 100);
+
+	return 0;
+}
+
+static void cdn_dp_pd_event_wq(struct work_struct *work)
+{
+	struct cdn_dp_device *dp;
+
+	dp = container_of(work, struct cdn_dp_device, event_wq.work);
+	if (IS_ERR_OR_NULL(dp)) {
+		pr_err("initialization issue");
+		return;
+	}
+
+	if (cdn_dp_firmware_init(dp))
+		return;
+
+	if ((cdn_dp_get_event(dp) & DPTX_HPD_EVENT) && (dp->drm_dev))
+		drm_helper_hpd_irq_event(dp->drm_dev);
+}
+
+static int cdn_dp_bind(struct device *dev, struct device *master,
+		       void *data)
+{
+	struct cdn_dp_audio_pdata audio_pdata;
+	struct cdn_dp_device *dp = dev_get_drvdata(dev);
+	struct device_node *np = dev->of_node;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	struct drm_device *drm_dev = data;
+	struct phy *phy = devm_of_phy_get_by_index(dev, np, 0);
+	int ret;
+
+	if (IS_ERR(phy))
+		return -EPROBE_DEFER;
+
+	dp->phy = phy;
+
+	ret = cdn_dp_init(dp);
+	if (ret < 0)
+		return ret;
+
+	dp->drm_dev = drm_dev;
+
+	encoder = &dp->encoder;
+
+	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev,
+							     dev->of_node);
+	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
+
+	ret = drm_encoder_init(drm_dev, encoder, &cdn_dp_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS, NULL);
+	if (ret) {
+		DRM_ERROR("failed to initialize encoder with drm\n");
+		return ret;
+	}
+
+	drm_encoder_helper_add(encoder, &cdn_dp_encoder_helper_funcs);
+
+	connector = &dp->connector;
+	connector->polled = DRM_CONNECTOR_POLL_HPD;
+	connector->dpms = DRM_MODE_DPMS_OFF;
+
+	ret = drm_connector_init(drm_dev, connector,
+				 &cdn_dp_atomic_connector_funcs,
+				 DRM_MODE_CONNECTOR_DisplayPort);
+	if (ret) {
+		DRM_ERROR("failed to initialize connector with drm\n");
+		goto err_free_encoder;
+	}
+
+	drm_connector_helper_add(connector, &cdn_dp_connector_helper_funcs);
+
+	ret = drm_mode_connector_attach_encoder(connector, encoder);
+	if (ret) {
+		DRM_ERROR("failed to attach connector and encoder\n");
+		goto err_free_connector;
+	}
+
+	audio_pdata.dev = dev,
+	audio_pdata.ops = &dp_audio_ops,
+	audio_pdata.data = dp;
+
+	dp->audio_pdev = platform_device_register_data(
+		dev, "cdn-dp-audio", PLATFORM_DEVID_NONE,
+		&audio_pdata, sizeof(audio_pdata));
+
+	if (IS_ERR(dp->audio_pdev))
+		return PTR_ERR(dp->audio_pdev);
+
+	dp->event_nb.notifier_call = cdn_dp_pd_event;
+	INIT_DELAYED_WORK(&dp->event_wq, cdn_dp_pd_event_wq);
+	tcphy_register_notifier(phy, &dp->event_nb);
+
+	return 0;
+
+err_free_connector:
+	drm_connector_cleanup(connector);
+err_free_encoder:
+	drm_encoder_cleanup(encoder);
+	return ret;
+}
+
+static void cdn_dp_unbind(struct device *dev, struct device *master, void *data)
+{
+	struct cdn_dp_device *dp = dev_get_drvdata(dev);
+	struct drm_encoder *encoder = &dp->encoder;
+
+	platform_device_unregister(dp->audio_pdev);
+	cdn_dp_encoder_disable(encoder);
+	encoder->funcs->destroy(encoder);
+	drm_connector_unregister(&dp->connector);
+	drm_connector_cleanup(&dp->connector);
+	drm_encoder_cleanup(encoder);
+	tcphy_unregister_notifier(dp->phy, &dp->event_nb);
+}
+
+static const struct component_ops cdn_dp_component_ops = {
+	.bind = cdn_dp_bind,
+	.unbind = cdn_dp_unbind,
+};
+
+static int cdn_dp_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct cdn_dp_device *dp;
+
+	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
+	if (!dp)
+		return -ENOMEM;
+	dp->dev = dev;
+
+	platform_set_drvdata(pdev, dp);
+
+	return component_add(dev, &cdn_dp_component_ops);
+}
+
+static int cdn_dp_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &cdn_dp_component_ops);
+
+	return 0;
+}
+
+static const struct of_device_id cdn_dp_dt_ids[] = {
+	{.compatible = "rockchip,cdn-dp",},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, cdn_dp_dt_ids);
+
+static struct platform_driver cdn_dp_driver = {
+	.probe = cdn_dp_probe,
+	.remove = cdn_dp_remove,
+	.driver = {
+		   .name = "cdn-dp",
+		   .owner = THIS_MODULE,
+		   .of_match_table = of_match_ptr(cdn_dp_dt_ids),
+	},
+};
+
+module_platform_driver(cdn_dp_driver);
+
+MODULE_AUTHOR("Chris Zhong <zyw at rock-chips.com>");
+MODULE_DESCRIPTION("cdn DP Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h
new file mode 100644
index 0000000..99c0123
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ROCKCHIP_EDP_CORE_H
+#define _ROCKCHIP_EDP_CORE_H
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_panel.h>
+#include "rockchip_drm_drv.h"
+#include "cdn-dp-reg.h"
+
+struct video_info {
+	bool h_sync_polarity;
+	bool v_sync_polarity;
+	bool interlaced;
+	int color_depth;
+	enum VIC_PXL_ENCODING_FORMAT color_fmt;
+};
+
+struct cdn_firmware_header {
+	u32 size_bytes; /* size of the entire header+image(s) in bytes */
+	u32 header_size; /* size of just the header in bytes */
+	u32 iram_size; /* size of iram */
+	u32 dram_size; /* size of dram */
+};
+
+struct cdn_dp_device {
+	struct device *dev;
+	struct drm_device *drm_dev;
+	struct drm_connector connector;
+	struct drm_encoder encoder;
+	struct drm_display_mode mode;
+	struct delayed_work hotplug_work;
+	struct platform_device *audio_pdev;
+	bool plugged;
+
+	const struct firmware *fw;	/* cdn dp firmware */
+	unsigned int fw_version;	/* cdn fw version */
+	bool fw_loaded;
+	void __iomem *regs;
+	void __iomem *phy_regs;
+	struct regmap *grf;
+	unsigned int irq;
+	struct clk *core_clk;
+	struct clk *pclk;
+	struct clk *spdif_clk;
+	struct video_info video_info;
+	struct phy *phy;
+	struct notifier_block	event_nb;
+	struct delayed_work	event_wq;
+
+	int cap_lanes;
+	bool flip;
+
+	int dpms_mode;
+	struct drm_dp_link link;
+	bool sink_has_audio;
+};
+
+void dp_clock_reset_seq(struct cdn_dp_device *dp);
+
+void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, int clk);
+int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
+			 u32 i_size, const u32 *d_mem, u32 d_size);
+int cdn_dp_active(struct cdn_dp_device *dp, u8 enable);
+int cdn_dp_set_host_cap(struct cdn_dp_device *dp);
+int cdn_dp_event_config(struct cdn_dp_device *dp);
+int cdn_dp_get_event(struct cdn_dp_device *dp);
+int cdn_dp_get_hpd_status(struct cdn_dp_device *dp);
+int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value);
+int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr);
+int cdn_dp_get_edid_block(void *dp, u8 *edid,
+			  unsigned int block, size_t length);
+int cdn_dp_training_start(struct cdn_dp_device *dp);
+int cdn_dp_get_lt_status(struct cdn_dp_device *dp);
+int cdn_dp_set_video_status(struct cdn_dp_device *dp, int active);
+int cdn_dp_config_video(struct cdn_dp_device *dp);
+int cdn_dp_audio_start(void *dp_dev, struct audio_info *audio);
+int cdn_dp_audio_stop(void *dp_dev, struct audio_info *audio);
+int cdn_dp_audio_config_set(void *dp_dev, struct audio_info *audio);
+
+#endif  /* _ROCKCHIP_EDP_CORE_H */
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
new file mode 100644
index 0000000..d6c9bcb
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -0,0 +1,730 @@
+/*
+ * cdn dp controller register driver
+ *
+ * Copyright (C) 2016 Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/reset.h>
+
+#include <sound/cdn-dp-audio.h>
+
+#include "cdn-dp-core.h"
+#include "cdn-dp-reg.h"
+
+#define FW_ALIVE_TIMEOUT_US		1000000
+#define MAILBOX_TIMEOUT_US		5000000
+
+/* the max size of read buff is 134 */
+static u8 rx_buff[134];
+
+void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, int clk)
+{
+	writel(clk / 1000000, dp->regs + SW_CLK_H);
+}
+
+void dp_clock_reset_seq(struct cdn_dp_device *dp)
+{
+	writel(0xfff, dp->regs + SOURCE_DPTX_CAR);
+	writel(0x7, dp->regs + SOURCE_PHY_CAR);
+	writel(0xf, dp->regs + SOURCE_PKT_CAR);
+	writel(0xff, dp->regs + SOURCE_AIF_CAR);
+	writel(0xf, dp->regs + SOURCE_CIPHER_CAR);
+	writel(0x3, dp->regs + SOURCE_CRYPTO_CAR);
+	writel(0, dp->regs + APB_INT_MASK);
+}
+
+static u8 cdn_dp_mailbox_read(struct cdn_dp_device *dp)
+{
+	int val, ret;
+
+	if (!dp->fw_loaded)
+		return 0;
+
+	ret = readx_poll_timeout(readl, dp->regs + MAILBOX_EMPTY_ADDR,
+				 val, !val, 1000, MAILBOX_TIMEOUT_US);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to wait mailbox response\n");
+		return 0;
+	}
+
+	return readl(dp->regs + MAILBOX0_RD_DATA) & 0xff;
+}
+
+static void cdp_dp_mailbox_write(struct cdn_dp_device *dp, u8 val)
+{
+	int ret, full;
+
+	if (!dp->fw_loaded)
+		return;
+
+	ret = readx_poll_timeout(readl, dp->regs + MAILBOX_FULL_ADDR,
+				 full, !full, 1000, MAILBOX_TIMEOUT_US);
+	if (ret < 0) {
+		dev_err(dp->dev, "mailbox is full\n");
+		return;
+	}
+
+	writel(val, dp->regs + MAILBOX0_WR_DATA);
+}
+
+/* return the size of message */
+int cdn_dp_mailbox_response(struct cdn_dp_device *dp, u8 module_id,
+			    u8 opcode, u8 **message)
+{
+	int size, i = 0;
+
+	memset(rx_buff, 0, 4);
+
+	while (i < sizeof(rx_buff)) {
+		if (i < sizeof(rx_buff))
+			rx_buff[i++] = cdn_dp_mailbox_read(dp);
+
+		size = ((rx_buff[2] << 8) | rx_buff[3]) + 4;
+		if (i >= size)
+			break;
+	}
+
+	if ((opcode != rx_buff[0]) || (module_id != rx_buff[1]))
+		return -EINVAL;
+
+	size = (rx_buff[2] << 8) | rx_buff[3];
+
+	*message = &rx_buff[4];
+
+	return size;
+}
+
+int cdn_dp_mailbox_send(struct cdn_dp_device *dp, u8 module_id, u8 opcode,
+			u16 size, u8 *message)
+{
+	cdp_dp_mailbox_write(dp, opcode);
+	cdp_dp_mailbox_write(dp, module_id);
+	cdp_dp_mailbox_write(dp, size >> 8);
+	cdp_dp_mailbox_write(dp, size & 0xff);
+
+	while (size--)
+		cdp_dp_mailbox_write(dp, *message++);
+
+	return 0;
+}
+
+int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
+			 u32 i_size, const u32 *d_mem, u32 d_size)
+{
+	int i, reg, ret;
+
+	/* reset ucpu before load firmware*/
+	writel(APB_IRAM_PATH | APB_DRAM_PATH | APB_XT_RESET,
+	       dp->regs + APB_CTRL);
+
+	for (i = 0; i < i_size; i += 4)
+		writel(*i_mem++, dp->regs + ADDR_IMEM + i);
+
+	for (i = 0; i < d_size; i += 4)
+		writel(*d_mem++, dp->regs + ADDR_DMEM + i);
+
+	/* un-reset ucpu */
+	writel(0, dp->regs + APB_CTRL);
+
+	/* check the keep alive register to make sure fw working */
+	ret = readx_poll_timeout(readl, dp->regs + KEEP_ALIVE,
+				 reg, reg, 2000, FW_ALIVE_TIMEOUT_US);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to loaded the FW reg = %x\n", reg);
+		return -EINVAL;
+	}
+
+	reg = readl(dp->regs + VER_L) & 0xff;
+	dp->fw_version = reg;
+	reg = readl(dp->regs + VER_H) & 0xff;
+	dp->fw_version |= reg << 8;
+	reg = readl(dp->regs + VER_LIB_L_ADDR) & 0xff;
+	dp->fw_version |= reg << 16;
+	reg = readl(dp->regs + VER_LIB_H_ADDR) & 0xff;
+	dp->fw_version |= reg << 24;
+
+	dp->fw_loaded = 1;
+
+	return 0;
+}
+
+int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val)
+{
+	u8 msg[6];
+
+	msg[0] = (addr >> 8) & 0xff;
+	msg[1] = addr & 0xff;
+	msg[2] = (val >> 24) & 0xff;
+	msg[3] = (val >> 16) & 0xff;
+	msg[4] = (val >> 8) & 0xff;
+	msg[5] = val & 0xff;
+	return cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_REGISTER,
+				   ARRAY_SIZE(msg), msg);
+}
+
+int cdn_dp_reg_read(struct cdn_dp_device *dp, u16 addr)
+{
+	u8 msg[2], *reg = NULL;
+	u16 size;
+
+	msg[0] = (addr >> 8) & 0xff;
+	msg[1] = addr & 0xff;
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_READ_REGISTER,
+			    ARRAY_SIZE(msg), msg);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+				       DPTX_READ_REGISTER, &reg);
+	if (size != 6)
+		return -EINVAL;
+
+	if ((msg[0] == reg[0]) && (msg[1] == reg[1]))
+		return (reg[2] << 24) | (reg[3] << 16) | (reg[4] << 8) | reg[5];
+
+	return -EINVAL;
+}
+
+int cdn_dp_reg_write_bit(struct cdn_dp_device *dp, u16 addr, u8 start_bit,
+			 u8 bits_no, u32 val)
+{
+	u8 field[8];
+
+	field[0] = (addr >> 8) & 0xff;
+	field[1] = addr & 0xff;
+	field[2] = start_bit;
+	field[3] = bits_no;
+	field[4] = (val >> 24) & 0xff;
+	field[5] = (val >> 16) & 0xff;
+	field[6] = (val >> 8) & 0xff;
+	field[7] = val & 0xff;
+
+	return cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_FIELD,
+			    sizeof(field), field);
+}
+
+int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value)
+{
+	u8 msg[6], *reg = NULL;
+	u16 size;
+
+	msg[0] = 0;
+	msg[1] = 1;
+	msg[2] = (addr >> 16) & 0xff;
+	msg[3] = (addr >> 8) & 0xff;
+	msg[4] = addr & 0xff;
+	msg[5] = value;
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_DPCD,
+			    ARRAY_SIZE(msg), msg);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+				       DPTX_WRITE_DPCD, &reg);
+	if (size != 5)
+		return -EINVAL;
+
+	if ((msg[2] == reg[2]) && (msg[3] == reg[3]) && (msg[4] == reg[4]))
+		return 0;
+
+	return -EINVAL;
+}
+
+int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr)
+{
+	u8 msg[5], *reg = NULL;
+	u16 size;
+
+	msg[0] = 0;
+	msg[1] = 1;
+	msg[2] = (addr >> 16) & 0xff;
+	msg[3] = (addr >> 8) & 0xff;
+	msg[4] = addr & 0xff;
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_READ_DPCD,
+			    ARRAY_SIZE(msg), msg);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+				       DPTX_READ_DPCD, &reg);
+	if (size != 6)
+		return -EINVAL;
+
+	if ((msg[2] == reg[2]) && (msg[3] == reg[3]) && (msg[4] == reg[4]))
+		return reg[5];
+
+	return -EINVAL;
+}
+
+int cdn_dp_active(struct cdn_dp_device *dp, u8 enable)
+{
+	u8 active = enable ? 1 : 0;
+	u8 *resp = NULL;
+	int size;
+
+	/* set firmware status, 1: avtive; 0: standby */
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_GENERAL, GENERAL_MAIN_CONTROL,
+			    1, &active);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_GENERAL,
+				       GENERAL_MAIN_CONTROL, &resp);
+	if (size != 1)
+		return -EINVAL;
+
+	return *resp ? 0 : -EINVAL;
+}
+
+int cdn_dp_set_host_cap(struct cdn_dp_device *dp)
+{
+	u8 msg[8];
+
+	msg[0] = DP_LINK_BW_5_4;
+	msg[1] = dp->cap_lanes;
+	msg[2] = VOLTAGE_LEVEL_2;
+	msg[3] = PRE_EMPHASIS_LEVEL_3;
+	msg[4] = PRBS7 | D10_2 | TRAINING_PTN1 | TRAINING_PTN2;
+	msg[5] = FAST_LT_NOT_SUPPORT;
+	msg[6] = LANE_MAPPING_NORMAL;
+	msg[7] = ENHANCED;
+
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX,
+			    DPTX_SET_HOST_CAPABILITIES,
+			    ARRAY_SIZE(msg), msg);
+
+	cdn_dp_reg_write(dp, DP_AUX_SWAP_INVERSION_CONTROL, AUX_HOST_INVERT);
+
+	return 0;
+}
+
+int cdn_dp_event_config(struct cdn_dp_device *dp)
+{
+	u8 msg[5];
+
+	msg[0] = DPTX_EVENT_ENABLE_HPD | DPTX_EVENT_ENABLE_TRAINING;
+
+	return cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_ENABLE_EVENT,
+				    ARRAY_SIZE(msg), msg);
+}
+
+int cdn_dp_get_event(struct cdn_dp_device *dp)
+{
+	return readl(dp->regs + SW_EVENTS0);
+}
+
+int cdn_dp_get_hpd_status(struct cdn_dp_device *dp)
+{
+	u8 *status = NULL;
+	int size;
+
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_HPD_STATE,
+			    0, NULL);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+				       DPTX_HPD_STATE, &status);
+	if (size != 1)
+		return -EINVAL;
+
+	return *status;
+}
+
+int cdn_dp_get_edid_block(void *data, u8 *edid,
+			  unsigned int block, size_t length)
+{
+	struct cdn_dp_device *dp = data;
+	int size;
+	u8 msg[2], *reg = NULL;
+
+	if (length != EDID_BLOCK_SIZE)
+		return -EINVAL;
+
+	msg[0] = block / 2;
+	msg[1] = block % 2;
+
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_GET_EDID,
+			    2, msg);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+				       DPTX_GET_EDID, &reg);
+
+	if (size != EDID_DATA + EDID_BLOCK_SIZE) {
+		dev_err(dp->dev, "read edid failed\n");
+		return -EINVAL;
+	}
+
+	if ((reg[EDID_LENGTH_BYTE] != EDID_BLOCK_SIZE) ||
+	    (reg[EDID_SEGMENT_BUMBER] != block / 2)) {
+		dev_err(dp->dev, "edid block size err\n");
+		return -EINVAL;
+	}
+
+	memcpy(edid, &reg[EDID_DATA], EDID_BLOCK_SIZE);
+
+	return 0;
+}
+
+int cdn_dp_training_start(struct cdn_dp_device *dp)
+{
+	int size;
+	u8 msg, *event = NULL;
+	unsigned long timeout;
+
+	msg = LINK_TRAINING_RUN;
+
+	/* start training */
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_TRAINING_CONTROL,
+			    1, &msg);
+
+	/* the whole training should finish in 500ms */
+	timeout = jiffies + msecs_to_jiffies(500);
+	while (1) {
+		msleep(20);
+		cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_READ_EVENT,
+				    0, NULL);
+
+		size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+					       DPTX_READ_EVENT, &event);
+		if (size != 2)
+			return -EINVAL;
+
+		if (event[1] & EQ_PHASE_FINISHED)
+			break;
+
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+int cdn_dp_get_lt_status(struct cdn_dp_device *dp)
+{
+	u8 *status = NULL;
+	int size;
+
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_READ_LINK_STAT,
+			    0, NULL);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+				       DPTX_READ_LINK_STAT, &status);
+
+	if (size != 10)
+		return -EINVAL;
+
+	dp->link.rate = status[0];
+	dp->link.num_lanes = status[1];
+
+	return 0;
+}
+
+int cdn_dp_set_video_status(struct cdn_dp_device *dp, int active)
+{
+	u8 msg;
+
+	msg = !!active;
+
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_SET_VIDEO,
+			    1, &msg);
+
+	return 0;
+}
+
+int cdn_dp_set_audio_status(struct cdn_dp_device *dp, int active)
+{
+	u8 msg;
+
+	msg = !!active;
+
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_SET_AUDIO,
+			    1, &msg);
+
+	return 0;
+}
+
+static int cdn_dp_get_msa_misc(struct video_info *video,
+			       struct drm_display_mode *mode)
+{
+	u8 val0, val1;
+	u32 msa_misc;
+
+	switch (video->color_fmt) {
+	case PXL_RGB:
+	case Y_ONLY:
+		val0 = 0;
+		break;
+	case YCBCR_4_4_4:
+		val0 = 6;
+		break;
+	case YCBCR_4_2_2:
+		val0 = 5;
+		break;
+	case YCBCR_4_2_0:
+		val0 = 5;
+		break;
+	};
+
+	switch (video->color_depth) {
+	case 6:
+		val1 = 0;
+		break;
+	case 8:
+		val1 = 1;
+		break;
+	case 10:
+		val1 = 2;
+		break;
+	case 12:
+		val1 = 3;
+		break;
+	case 16:
+		val1 = 4;
+		break;
+	};
+
+	msa_misc = 2 * val0 + 32 * val1 +
+		   ((video->color_fmt == Y_ONLY) ? (1 << 14) : 0);
+
+	return msa_misc;
+}
+
+int cdn_dp_config_video(struct cdn_dp_device *dp)
+{
+	struct video_info *video = &dp->video_info;
+	struct drm_display_mode *mode = &dp->mode;
+	u32 val, link_rate;
+	u8 bit_per_pix;
+
+	bit_per_pix = (video->color_fmt == YCBCR_4_2_2) ?
+		      (video->color_depth * 2) : (video->color_depth * 3);
+
+	val = VIF_BYPASS_INTERLACE;
+
+	cdn_dp_reg_write(dp, BND_HSYNC2VSYNC, val);
+
+	cdn_dp_reg_write(dp, HSYNC2VSYNC_POL_CTRL, 0);
+
+	link_rate = drm_dp_bw_code_to_link_rate(dp->link.rate) / 1000;
+
+	val = TU_SIZE * mode->clock * bit_per_pix;
+	val /= dp->link.num_lanes * link_rate * 8 * 1000;
+	/* FIXME: need add 1 to symbols 4K display */
+	if (mode->clock > 500000)
+		val += 1;
+
+	val += TU_SIZE << 8;
+
+	cdn_dp_reg_write(dp, DP_FRAMER_TU, val);
+
+	switch (video->color_depth) {
+	case 6:
+		val = BCS_6;
+		break;
+	case 8:
+		val = BCS_8;
+		break;
+	case 10:
+		val = BCS_10;
+		break;
+	case 12:
+		val = BCS_12;
+		break;
+	case 16:
+		val = BCS_16;
+		break;
+	};
+
+	val += video->color_fmt << 8;
+	cdn_dp_reg_write(dp, DP_FRAMER_PXL_REPR, val);
+
+	val = video->h_sync_polarity ? DP_FRAMER_SP_HSP : 0;
+	val |= video->v_sync_polarity ? DP_FRAMER_SP_VSP : 0;
+	cdn_dp_reg_write(dp, DP_FRAMER_SP, val);
+
+	val = (mode->hsync_start - mode->hdisplay) << 16;
+	val |= mode->htotal - mode->hsync_end;
+	cdn_dp_reg_write(dp, DP_FRONT_BACK_PORCH, val);
+
+	val = mode->hdisplay * bit_per_pix / 8;
+	cdn_dp_reg_write(dp, DP_BYTE_COUNT, val);
+
+	val = mode->htotal | ((mode->htotal - mode->hsync_start) << 16);
+	cdn_dp_reg_write(dp, MSA_HORIZONTAL_0, val);
+
+	val = mode->hsync_end - mode->hsync_start;
+	val |= (mode->hdisplay << 16) | (video->h_sync_polarity << 15);
+	cdn_dp_reg_write(dp, MSA_HORIZONTAL_1, val);
+
+	val = mode->vtotal;
+	val |= ((mode->vtotal - mode->vsync_start) << 16);
+
+	cdn_dp_reg_write(dp, MSA_VERTICAL_0, val);
+
+	val = mode->vsync_end - mode->vsync_start;
+	val |= mode->vdisplay << 16;
+	val |= (video->v_sync_polarity << 15);
+	cdn_dp_reg_write(dp, MSA_VERTICAL_1, val);
+
+	val = cdn_dp_get_msa_misc(video, mode);
+	cdn_dp_reg_write(dp, MSA_MISC, val);
+
+	cdn_dp_reg_write(dp, STREAM_CONFIG, 1);
+
+	val = mode->hsync_end - mode->hsync_start;
+	val |= (mode->hdisplay << 16);
+	cdn_dp_reg_write(dp, DP_HORIZONTAL, val);
+
+	val = mode->vtotal;
+	val -= (mode->vtotal - mode->vdisplay);
+	val |= (mode->vtotal - mode->vsync_start) << 16;
+
+	cdn_dp_reg_write(dp, DP_VERTICAL_0, val);
+
+	val = mode->vtotal;
+	cdn_dp_reg_write(dp, DP_VERTICAL_1, val);
+
+	val =  0;
+	cdn_dp_reg_write_bit(dp, DP_VB_ID, 2, 1, val);
+
+	return 0;
+}
+
+int cdn_dp_audio_start(void *dp_dev, struct audio_info *audio)
+{
+	struct cdn_dp_device *dp = (struct cdn_dp_device *)dp_dev;
+
+	if (audio->type == TYPE_SPDIF) {
+		clk_prepare_enable(dp->spdif_clk);
+		clk_set_rate(dp->spdif_clk, 400000000);
+	}
+
+	return cdn_dp_reg_write(dp, AUDIO_PACK_CONTROL, AUDIO_PACK_EN(1));
+}
+
+int cdn_dp_audio_stop(void *dp_dev, struct audio_info *audio)
+{
+	struct cdn_dp_device *dp = (struct cdn_dp_device *)dp_dev;
+
+	cdn_dp_reg_write(dp, AUDIO_PACK_CONTROL, AUDIO_PACK_EN(0));
+
+	if (audio->type == TYPE_SPDIF)
+		clk_disable_unprepare(dp->spdif_clk);
+
+	return 0;
+}
+
+int cdn_dp_audio_config_set(void *dp_dev, struct audio_info *audio)
+{
+	struct cdn_dp_device *dp = (struct cdn_dp_device *)dp_dev;
+	int lanes_param, i2s_port_en_val, val, i;
+
+	if ((audio->channels == 2) && (dp->link.num_lanes == 1))
+		lanes_param = 1;
+	else if (audio->channels == 2)
+		lanes_param = 3;
+	else
+		lanes_param = 0;
+
+	if (audio->channels == 2)
+		i2s_port_en_val = 1;
+	else if (audio->channels == 4)
+		i2s_port_en_val = 3;
+	else
+		i2s_port_en_val = 0xf;
+
+	cdn_dp_reg_write(dp, CM_LANE_CTRL, 0x8000);
+
+	cdn_dp_reg_write(dp, CM_CTRL, 0);
+
+	if (audio->type == TYPE_I2S) {
+		writel(0x0, dp->regs + SPDIF_CTRL_ADDR);
+
+		writel(SYNC_WR_TO_CH_ZERO, dp->regs + FIFO_CNTL);
+
+		val = audio->channels - 1;
+		val |= (audio->channels / 2 - 1) << 5;
+		val |= BIT(8);
+		val |= lanes_param << 11;
+		writel(val, dp->regs + SMPL2PKT_CNFG);
+
+		if (audio->word_length == 16)
+			val = 0;
+		else if (audio->word_length == 24)
+			val = 1 << 9;
+		else
+			val = 2 << 9;
+
+		val |= (audio->channels - 1) << 2;
+		val |= i2s_port_en_val << 17;
+		val |= 2 << 11;
+		writel(val, dp->regs + AUDIO_SRC_CNFG);
+
+		for (i = 0; i < (audio->channels + 1) / 2; i++) {
+			if (audio->word_length == 16)
+				val = (0x08 << 8) | (0x08 << 20);
+			else if (audio->word_length == 24)
+				val = (0x0b << 8) | (0x0b << 20);
+
+			val |= ((2 * i) << 4) | ((2 * i + 1) << 16);
+			writel(val, dp->regs + STTS_BIT_CH(i));
+		}
+
+		switch (audio->freq) {
+		case 32000:
+			val = SAMPLING_FREQ(3) |
+			      ORIGINAL_SAMP_FREQ(0xc);
+			break;
+		case 44100:
+			val = SAMPLING_FREQ(0) |
+			      ORIGINAL_SAMP_FREQ(0xf);
+			break;
+		case 48000:
+			val = SAMPLING_FREQ(2) |
+			      ORIGINAL_SAMP_FREQ(0xd);
+			break;
+		case 88200:
+			val = SAMPLING_FREQ(8) |
+			      ORIGINAL_SAMP_FREQ(0x7);
+			break;
+		case 96000:
+			val = SAMPLING_FREQ(0xa) |
+			      ORIGINAL_SAMP_FREQ(5);
+			break;
+		case 176400:
+			val = SAMPLING_FREQ(0xc) |
+			      ORIGINAL_SAMP_FREQ(3);
+			break;
+		case 192000:
+			val = SAMPLING_FREQ(0xe) |
+			      ORIGINAL_SAMP_FREQ(1);
+			break;
+		}
+		val |= 4;
+		writel(val, dp->regs + COM_CH_STTS_BITS);
+
+		writel(2, dp->regs + SMPL2PKT_CNTL);
+		writel(2, dp->regs + AUDIO_SRC_CNTL);
+		cdn_dp_reg_write_bit(dp, DP_VB_ID, 4, 1, 0);
+	} else {
+		val = 0x1F0707;
+		writel(val, dp->regs + SPDIF_CTRL_ADDR);
+
+		writel(SYNC_WR_TO_CH_ZERO, dp->regs + FIFO_CNTL);
+
+		val = 0x101 | (3 << 11);
+		writel(val, dp->regs + SMPL2PKT_CNFG);
+		writel(2, dp->regs + SMPL2PKT_CNTL);
+
+		val = 0x3F0707;
+		writel(val, dp->regs + SPDIF_CTRL_ADDR);
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
new file mode 100644
index 0000000..74fc7f9
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2016 Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CDN_DP_REG_H
+#define _CDN_DP_REG_H
+
+#include <linux/bitops.h>
+
+#define ADDR_IMEM		0x10000
+#define ADDR_DMEM		0x20000
+
+/* APB CFG addr */
+#define APB_CTRL			0
+#define XT_INT_CTRL			0x04
+#define MAILBOX_FULL_ADDR		0x08
+#define MAILBOX_EMPTY_ADDR		0x0c
+#define MAILBOX0_WR_DATA		0x10
+#define MAILBOX0_RD_DATA		0x14
+#define KEEP_ALIVE			0x18
+#define VER_L				0x1c
+#define VER_H				0x20
+#define VER_LIB_L_ADDR			0x24
+#define VER_LIB_H_ADDR			0x28
+#define SW_DEBUG_L			0x2c
+#define SW_DEBUG_H			0x30
+#define MAILBOX_INT_MASK		0x34
+#define MAILBOX_INT_STATUS		0x38
+#define SW_CLK_L			0x3c
+#define SW_CLK_H			0x40
+#define SW_EVENTS0			0x44
+#define SW_EVENTS1			0x48
+#define SW_EVENTS2			0x4c
+#define SW_EVENTS3			0x50
+#define XT_OCD_CTRL			0x60
+#define APB_INT_MASK			0x6c
+#define APB_STATUS_MASK			0x70
+
+/* audio decoder addr */
+#define AUDIO_SRC_CNTL			0x30000
+#define AUDIO_SRC_CNFG			0x30004
+#define COM_CH_STTS_BITS		0x30008
+#define STTS_BIT_CH(x)			(0x3000c + (x << 2))
+#define SPDIF_CTRL_ADDR			0x3004c
+#define SPDIF_CH1_CS_3100_ADDR		0x30050
+#define SPDIF_CH1_CS_6332_ADDR		0x30054
+#define SPDIF_CH1_CS_9564_ADDR		0x30058
+#define SPDIF_CH1_CS_12796_ADDR		0x3005c
+#define SPDIF_CH1_CS_159128_ADDR	0x30060
+#define SPDIF_CH1_CS_191160_ADDR	0x30064
+#define SPDIF_CH2_CS_3100_ADDR		0x30068
+#define SPDIF_CH2_CS_6332_ADDR		0x3006c
+#define SPDIF_CH2_CS_9564_ADDR		0x30070
+#define SPDIF_CH2_CS_12796_ADDR		0x30074
+#define SPDIF_CH2_CS_159128_ADDR	0x30078
+#define SPDIF_CH2_CS_191160_ADDR	0x3007c
+#define SMPL2PKT_CNTL			0x30080
+#define SMPL2PKT_CNFG			0x30084
+#define FIFO_CNTL			0x30088
+#define FIFO_STTS			0x3008c
+
+/* source pif addr */
+#define SOURCE_PIF_WR_ADDR		0x30800
+#define SOURCE_PIF_WR_REQ		0x30804
+#define SOURCE_PIF_RD_ADDR		0x30808
+#define SOURCE_PIF_RD_REQ		0x3080c
+#define SOURCE_PIF_DATA_WR		0x30810
+#define SOURCE_PIF_DATA_RD		0x30814
+#define SOURCE_PIF_FIFO1_FLUSH		0x30818
+#define SOURCE_PIF_FIFO2_FLUSH		0x3081c
+#define SOURCE_PIF_STATUS		0x30820
+#define SOURCE_PIF_INTERRUPT_SOURCE	0x30824
+#define SOURCE_PIF_INTERRUPT_MASK	0x30828
+#define SOURCE_PIF_PKT_ALLOC_REG	0x3082c
+#define SOURCE_PIF_PKT_ALLOC_WR_EN	0x30830
+#define SOURCE_PIF_SW_RESET		0x30834
+
+/* bellow registers need access by mailbox */
+/* source car addr */
+#define SOURCE_HDTX_CAR			0x0900
+#define SOURCE_DPTX_CAR			0x0904
+#define SOURCE_PHY_CAR			0x0908
+#define SOURCE_CEC_CAR			0x090c
+#define SOURCE_CBUS_CAR			0x0910
+#define SOURCE_PKT_CAR			0x0918
+#define SOURCE_AIF_CAR			0x091c
+#define SOURCE_CIPHER_CAR		0x0920
+#define SOURCE_CRYPTO_CAR		0x0924
+
+/* clock meters addr */
+#define CM_CTRL				0x0a00
+#define CM_I2S_CTRL			0x0a04
+#define CM_SPDIF_CTRL			0x0a08
+#define CM_VID_CTRL			0x0a0c
+#define CM_LANE_CTRL			0x0a10
+#define I2S_NM_STABLE			0x0a14
+#define I2S_NCTS_STABLE			0x0a18
+#define SPDIF_NM_STABLE			0x0a1c
+#define SPDIF_NCTS_STABLE		0x0a20
+#define NMVID_MEAS_STABLE		0x0a24
+#define I2S_MEAS			0x0a40
+#define SPDIF_MEAS			0x0a80
+#define NMVID_MEAS			0x0ac0
+
+/* source vif addr */
+#define BND_HSYNC2VSYNC			0x0b00
+#define HSYNC2VSYNC_F1_L1		0x0b04
+#define HSYNC2VSYNC_F2_L1		0x0b08
+#define HSYNC2VSYNC_STATUS		0x0b0c
+#define HSYNC2VSYNC_POL_CTRL		0x0b10
+
+/* dptx phy addr */
+#define DP_TX_PHY_CONFIG_REG		0x2000
+#define DP_TX_PHY_STATUS_REG		0x2004
+#define DP_TX_PHY_SW_RESET		0x2008
+#define DP_TX_PHY_SCRAMBLER_SEED	0x200c
+#define DP_TX_PHY_TRAINING_01_04	0x2010
+#define DP_TX_PHY_TRAINING_05_08	0x2014
+#define DP_TX_PHY_TRAINING_09_10	0x2018
+#define TEST_COR			0x23fc
+
+/* dptx hpd addr */
+#define HPD_IRQ_DET_MIN_TIMER		0x2100
+#define HPD_IRQ_DET_MAX_TIMER		0x2104
+#define HPD_UNPLGED_DET_MIN_TIMER	0x2108
+#define HPD_STABLE_TIMER		0x210c
+#define HPD_FILTER_TIMER		0x2110
+#define HPD_EVENT_MASK			0x211c
+#define HPD_EVENT_DET			0x2120
+
+/* dpyx framer addr */
+#define DP_FRAMER_GLOBAL_CONFIG		0x2200
+#define DP_SW_RESET			0x2204
+#define DP_FRAMER_TU			0x2208
+#define DP_FRAMER_PXL_REPR		0x220c
+#define DP_FRAMER_SP			0x2210
+#define AUDIO_PACK_CONTROL		0x2214
+#define DP_VC_TABLE(x)			(0x2218 + (x << 2))
+#define DP_VB_ID			0x2258
+#define DP_MTPH_LVP_CONTROL		0x225c
+#define DP_MTPH_SYMBOL_VALUES		0x2260
+#define DP_MTPH_ECF_CONTROL		0x2264
+#define DP_MTPH_ACT_CONTROL		0x2268
+#define DP_MTPH_STATUS			0x226c
+#define DP_INTERRUPT_SOURCE		0x2270
+#define DP_INTERRUPT_MASK		0x2274
+#define DP_FRONT_BACK_PORCH		0x2278
+#define DP_BYTE_COUNT			0x227c
+
+/* dptx stream addr */
+#define MSA_HORIZONTAL_0		0x2280
+#define MSA_HORIZONTAL_1		0x2284
+#define MSA_VERTICAL_0			0x2288
+#define MSA_VERTICAL_1			0x228c
+#define MSA_MISC			0x2290
+#define STREAM_CONFIG			0x2294
+#define AUDIO_PACK_STATUS		0x2298
+#define VIF_STATUS			0x229c
+#define PCK_STUFF_STATUS_0		0x22a0
+#define PCK_STUFF_STATUS_1		0x22a4
+#define INFO_PACK_STATUS		0x22a8
+#define RATE_GOVERNOR_STATUS		0x22ac
+#define DP_HORIZONTAL			0x22b0
+#define DP_VERTICAL_0			0x22b4
+#define DP_VERTICAL_1			0x22b8
+#define DP_BLOCK_SDP			0x22bc
+
+/* dptx glbl addr */
+#define DPTX_LANE_EN			0x2300
+#define DPTX_ENHNCD			0x2304
+#define DPTX_INT_MASK			0x2308
+#define DPTX_INT_STATUS			0x230c
+
+/* dp aux addr */
+#define DP_AUX_HOST_CONTROL		0x2800
+#define DP_AUX_INTERRUPT_SOURCE		0x2804
+#define DP_AUX_INTERRUPT_MASK		0x2808
+#define DP_AUX_SWAP_INVERSION_CONTROL	0x280c
+#define DP_AUX_SEND_NACK_TRANSACTION	0x2810
+#define DP_AUX_CLEAR_RX			0x2814
+#define DP_AUX_CLEAR_TX			0x2818
+#define DP_AUX_TIMER_STOP		0x281c
+#define DP_AUX_TIMER_CLEAR		0x2820
+#define DP_AUX_RESET_SW			0x2824
+#define DP_AUX_DIVIDE_2M		0x2828
+#define DP_AUX_TX_PREACHARGE_LENGTH	0x282c
+#define DP_AUX_FREQUENCY_1M_MAX		0x2830
+#define DP_AUX_FREQUENCY_1M_MIN		0x2834
+#define DP_AUX_RX_PRE_MIN		0x2838
+#define DP_AUX_RX_PRE_MAX		0x283c
+#define DP_AUX_TIMER_PRESET		0x2840
+#define DP_AUX_NACK_FORMAT		0x2844
+#define DP_AUX_TX_DATA			0x2848
+#define DP_AUX_RX_DATA			0x284c
+#define DP_AUX_TX_STATUS		0x2850
+#define DP_AUX_RX_STATUS		0x2854
+#define DP_AUX_RX_CYCLE_COUNTER		0x2858
+#define DP_AUX_MAIN_STATES		0x285c
+#define DP_AUX_MAIN_TIMER		0x2860
+#define DP_AUX_AFE_OUT			0x2864
+
+/* crypto addr */
+#define CRYPTO_HDCP_REVISION		0x5800
+#define HDCP_CRYPTO_CONFIG		0x5804
+#define CRYPTO_INTERRUPT_SOURCE		0x5808
+#define CRYPTO_INTERRUPT_MASK		0x580c
+#define CRYPTO22_CONFIG			0x5818
+#define CRYPTO22_STATUS			0x581c
+#define SHA_256_DATA_IN			0x583c
+#define SHA_256_DATA_OUT_(x)		(0x5850 + (x << 2))
+#define AES_32_KEY_(x)			(0x5870 + (x << 2))
+#define AES_32_DATA_IN			0x5880
+#define AES_32_DATA_OUT_(x)		(0x5884 + (x << 2))
+#define CRYPTO14_CONFIG			0x58a0
+#define CRYPTO14_STATUS			0x58a4
+#define CRYPTO14_PRNM_OUT		0x58a8
+#define CRYPTO14_KM_0			0x58ac
+#define CRYPTO14_KM_1			0x58b0
+#define CRYPTO14_AN_0			0x58b4
+#define CRYPTO14_AN_1			0x58b8
+#define CRYPTO14_YOUR_KSV_0		0x58bc
+#define CRYPTO14_YOUR_KSV_1		0x58c0
+#define CRYPTO14_MI_0			0x58c4
+#define CRYPTO14_MI_1			0x58c8
+#define CRYPTO14_TI_0			0x58cc
+#define CRYPTO14_KI_0			0x58d0
+#define CRYPTO14_KI_1			0x58d4
+#define CRYPTO14_BLOCKS_NUM		0x58d8
+#define CRYPTO14_KEY_MEM_DATA_0		0x58dc
+#define CRYPTO14_KEY_MEM_DATA_1		0x58e0
+#define CRYPTO14_SHA1_MSG_DATA		0x58e4
+#define CRYPTO14_SHA1_V_VALUE_(x)	(0x58e8 + (x << 2))
+#define TRNG_CTRL			0x58fc
+#define TRNG_DATA_RDY			0x5900
+#define TRNG_DATA			0x5904
+
+/* cipher addr */
+#define HDCP_REVISION			0x60000
+#define INTERRUPT_SOURCE		0x60004
+#define INTERRUPT_MASK			0x60008
+#define HDCP_CIPHER_CONFIG		0x6000c
+#define AES_128_KEY_0			0x60010
+#define AES_128_KEY_1			0x60014
+#define AES_128_KEY_2			0x60018
+#define AES_128_KEY_3			0x6001c
+#define AES_128_RANDOM_0		0x60020
+#define AES_128_RANDOM_1		0x60024
+#define CIPHER14_KM_0			0x60028
+#define CIPHER14_KM_1			0x6002c
+#define CIPHER14_STATUS			0x60030
+#define CIPHER14_RI_PJ_STATUS		0x60034
+#define CIPHER_MODE			0x60038
+#define CIPHER14_AN_0			0x6003c
+#define CIPHER14_AN_1			0x60040
+#define CIPHER22_AUTH			0x60044
+#define CIPHER14_R0_DP_STATUS		0x60048
+#define CIPHER14_BOOTSTRAP		0x6004c
+
+#define APB_IRAM_PATH			BIT(2)
+#define APB_DRAM_PATH			BIT(1)
+#define APB_XT_RESET			BIT(0)
+
+/* mailbox */
+#define MB_OPCODE_ID			0
+#define MB_MODULE_ID			1
+#define MB_SIZE_MSB_ID			2
+#define MB_SIZE_LSB_ID			3
+#define MB_DATA_ID			4
+
+#define MB_MODULE_ID_DP_TX		0x01
+#define MB_MODULE_ID_HDCP_TX		0x07
+#define MB_MODULE_ID_HDCP_RX		0x08
+#define MB_MODULE_ID_HDCP_GENERAL	0x09
+#define MB_MODULE_ID_GENERAL		0x0a
+
+/* general opcode */
+#define GENERAL_MAIN_CONTROL            0x01
+#define GENERAL_TEST_ECHO               0x02
+#define GENERAL_BUS_SETTINGS            0x03
+#define GENERAL_TEST_ACCESS             0x04
+
+#define DPTX_SET_POWER_MNG			0x00
+#define DPTX_SET_HOST_CAPABILITIES		0x01
+#define DPTX_GET_EDID				0x02
+#define DPTX_READ_DPCD				0x03
+#define DPTX_WRITE_DPCD				0x04
+#define DPTX_ENABLE_EVENT			0x05
+#define DPTX_WRITE_REGISTER			0x06
+#define DPTX_READ_REGISTER			0x07
+#define DPTX_WRITE_FIELD			0x08
+#define DPTX_TRAINING_CONTROL			0x09
+#define DPTX_READ_EVENT				0x0a
+#define DPTX_READ_LINK_STAT			0x0b
+#define DPTX_SET_VIDEO				0x0c
+#define DPTX_SET_AUDIO				0x0d
+#define DPTX_GET_LAST_AUX_STAUS			0x0e
+#define DPTX_SET_LINK_BREAK_POINT		0x0f
+#define DPTX_FORCE_LANES			0x10
+#define DPTX_HPD_STATE				0x11
+
+#define DPTX_EVENT_ENABLE_HPD			BIT(0)
+#define DPTX_EVENT_ENABLE_TRAINING		BIT(1)
+
+#define LINK_TRAINING_NOT_ACTIVE		0
+#define LINK_TRAINING_RUN			1
+#define LINK_TRAINING_RESTART			2
+
+#define CONTROL_VIDEO_IDLE			0
+#define CONTROL_VIDEO_VALID			1
+
+#define VIF_BYPASS_INTERLACE			BIT(13)
+#define INTERLACE_FMT_DET			BIT(12)
+#define INTERLACE_DTCT_WIN			0x20
+
+#define DP_FRAMER_SP_INTERLACE_EN		BIT(2)
+#define DP_FRAMER_SP_HSP			BIT(1)
+#define DP_FRAMER_SP_VSP			BIT(0)
+
+/* capability */
+#define AUX_HOST_INVERT				3
+#define	FAST_LT_SUPPORT				1
+#define FAST_LT_NOT_SUPPORT			0
+#define LANE_MAPPING_NORMAL			0xe4
+#define LANE_MAPPING_FLIPPED			0x1b
+#define ENHANCED				1
+
+#define	FULL_LT_STARTED				BIT(0)
+#define FASE_LT_STARTED				BIT(1)
+#define CLK_RECOVERY_FINISHED			BIT(2)
+#define EQ_PHASE_FINISHED			BIT(3)
+#define FASE_LT_START_FINISHED			BIT(4)
+#define CLK_RECOVERY_FAILED			BIT(5)
+#define EQ_PHASE_FAILED				BIT(6)
+#define FASE_LT_FAILED				BIT(7)
+
+#define DPTX_HPD_EVENT				BIT(0)
+#define DPTX_TRAINING_EVENT			BIT(1)
+#define HDCP_TX_STATUS_EVENT			BIT(4)
+#define HDCP2_TX_IS_KM_STORED_EVENT		BIT(5)
+#define HDCP2_TX_STORE_KM_EVENT			BIT(6)
+#define HDCP_TX_IS_RECEIVER_ID_VALID_EVENT	BIT(7)
+
+#define EDID_LENGTH_BYTE			0
+#define EDID_SEGMENT_BUMBER			1
+#define EDID_DATA				2
+#define EDID_BLOCK_SIZE				128
+
+#define TU_SIZE					64
+
+/* audio */
+#define AUDIO_PACK_EN(x)			(x << 8)
+#define SAMPLING_FREQ(x)			(x << 16)
+#define ORIGINAL_SAMP_FREQ(x)			(x << 24)
+#define SYNC_WR_TO_CH_ZERO			BIT(1)
+
+enum voltage_swing_level {
+	VOLTAGE_LEVEL_0,
+	VOLTAGE_LEVEL_1,
+	VOLTAGE_LEVEL_2,
+	VOLTAGE_LEVEL_3,
+};
+
+enum pre_emphasis_level {
+	PRE_EMPHASIS_LEVEL_0,
+	PRE_EMPHASIS_LEVEL_1,
+	PRE_EMPHASIS_LEVEL_2,
+	PRE_EMPHASIS_LEVEL_3,
+};
+
+enum pattern_set {
+	PRBS7		= BIT(0),
+	D10_2		= BIT(1),
+	TRAINING_PTN1	= BIT(2),
+	TRAINING_PTN2	= BIT(3),
+	DP_NONE		= BIT(4)
+};
+
+enum VIC_PXL_ENCODING_FORMAT {
+	PXL_RGB = 0x1,
+	YCBCR_4_4_4 = 0x2,
+	YCBCR_4_2_2 = 0x4,
+	YCBCR_4_2_0 = 0x8,
+	Y_ONLY = 0x10,
+};
+
+enum VIC_COLOR_DEPTH {
+	BCS_6 = 0x1,
+	BCS_8 = 0x2,
+	BCS_10 = 0x4,
+	BCS_12 = 0x8,
+	BCS_16 = 0x10,
+};
+
+#endif /* _CDN_DP_REG_H */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index edd7ec2..623d9e3 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -969,7 +969,10 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
 		vop_dsp_hold_valid_irq_disable(vop);
 	}
 
-	pin_pol = 0x8;
+	if (s->output_type != DRM_MODE_CONNECTOR_DisplayPort)
+		pin_pol = 0x8;
+	else
+		pin_pol = 0;
 	pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
 	pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
 	VOP_CTRL_SET(vop, pin_pol, pin_pol);
@@ -991,6 +994,10 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
 		VOP_CTRL_SET(vop, mipi_pin_pol, pin_pol);
 		VOP_CTRL_SET(vop, mipi_en, 1);
 		break;
+	case DRM_MODE_CONNECTOR_DisplayPort:
+		VOP_CTRL_SET(vop, dp_pin_pol, pin_pol);
+		VOP_CTRL_SET(vop, dp_en, 1);
+		break;
 	default:
 		DRM_ERROR("unsupport connector_type[%d]\n", s->output_type);
 	}
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index ff4f52e..50a045c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -45,6 +45,7 @@ struct vop_ctrl {
 	struct vop_reg edp_en;
 	struct vop_reg hdmi_en;
 	struct vop_reg mipi_en;
+	struct vop_reg dp_en;
 	struct vop_reg out_mode;
 	struct vop_reg dither_down;
 	struct vop_reg dither_up;
@@ -53,6 +54,7 @@ struct vop_ctrl {
 	struct vop_reg hdmi_pin_pol;
 	struct vop_reg edp_pin_pol;
 	struct vop_reg mipi_pin_pol;
+	struct vop_reg dp_pin_pol;
 
 	struct vop_reg htotal_pw;
 	struct vop_reg hact_st_end;
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index 5b1ae1f..dcf172e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -281,6 +281,7 @@ static const struct vop_data rk3288_vop = {
 static const struct vop_ctrl rk3399_ctrl_data = {
 	.standby = VOP_REG(RK3399_SYS_CTRL, 0x1, 22),
 	.gate_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 23),
+	.dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11),
 	.rgb_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 12),
 	.hdmi_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 13),
 	.edp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 14),
@@ -290,6 +291,7 @@ static const struct vop_ctrl rk3399_ctrl_data = {
 	.data_blank = VOP_REG(RK3399_DSP_CTRL0, 0x1, 19),
 	.out_mode = VOP_REG(RK3399_DSP_CTRL0, 0xf, 0),
 	.rgb_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16),
+	.dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16),
 	.hdmi_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 20),
 	.edp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 24),
 	.mipi_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 28),
diff --git a/include/sound/cdn-dp-audio.h b/include/sound/cdn-dp-audio.h
new file mode 100644
index 0000000..8c6e55c
--- /dev/null
+++ b/include/sound/cdn-dp-audio.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __CDN_DP_AUDIO_H__
+#define __CDN_DP_AUDIO_H__
+
+#include <linux/platform_device.h>
+
+#define AUDIO_TYPE_I2S			0
+#define AUDIO_TYPE_SPIDIF_INTERNAL	1
+#define AUDIO_TYPE_SPIDIF_EXTERNAL	2
+
+enum AUDIO_TYPE {
+	TYPE_I2S = 0,
+	TYPE_SPDIF = 1,
+};
+
+struct audio_info {
+	enum AUDIO_TYPE type;
+	int freq;
+	int channels;
+	int word_length;
+};
+
+struct cdn_dp_audio_ops {
+	int (*audio_startup)(void *dp_dev, struct audio_info *audio);
+	int (*audio_shutdown)(void *dp_dev, struct audio_info *audio);
+	int (*audio_start)(void *dp_dev, struct audio_info *audio);
+	int (*audio_stop)(void *dp_dev, struct audio_info *audio);
+	int (*audio_config)(void *dp_dev, struct audio_info *audio);
+};
+
+/* DP audio initalization data */
+struct cdn_dp_audio_pdata {
+	struct device *dev;
+	const struct cdn_dp_audio_ops *ops;
+	void *data;
+};
+
+#endif /* __CDN_DP_AUDIO_H__ */
-- 
2.6.3



From zyw at rock-chips.com  Thu May 26 23:02:17 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 14:02:17 +0800
Subject: [PATCH 4/6] Documentation: bindings: add dt documentation for cdn DP
 controller
In-Reply-To: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1464328939-8073-5-git-send-email-zyw@rock-chips.com>

This patch adds a binding that describes the cdn DP controller for
rk3399.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
---

 .../bindings/display/rockchip/cdn-dp-rockchip.txt  | 57 ++++++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt

diff --git a/Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt
new file mode 100644
index 0000000..60795c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt
@@ -0,0 +1,57 @@
+Rockchip RK3399 specific extensions to the cdn Display Port
+================================
+
+Required properties:
+- compatible: "rockchip,cdn-dp"
+
+- reg: physical base address of the controller and length
+
+- clocks: from common clock binding: handle to dp clock.
+
+- clock-names: from common clock binding:
+	       Required elements: "core_clk" "pclk" "spdif"
+
+- rockchip,grf: this soc should set GRF regs, so need get grf here.
+
+- ports: contain a port nodes with endpoint definitions as defined in
+	 Documentation/devicetree/bindings/media/video-interfaces.txt.
+	 contained 2 endpoints, connecting to the output of vop.
+
+- phys: from general PHY binding: the phandle for the PHY device.
+
+-------------------------------------------------------------------------------
+
+Example:
+	cdn_dp: dp at fec00000 {
+		compatible = "rockchip,cdn-dp";
+		reg = <0x0 0xfec00000 0x0 0x100000>;
+		interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_DP_CORE>, <&cru PCLK_DP_CTRL>,
+			 <&cru SCLK_SPDIF_REC_DPTX>;
+		clock-names = "core_clk", "pclk", "spdif";
+		phys = <&tcphy0>;
+		rockchip,grf = <&grf>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			dp_in: port {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				dp_in_vopb: endpoint at 0 {
+					reg = <0>;
+					remote-endpoint = <&vopb_out_dp>;
+				};
+
+				dp_in_vopl: endpoint at 1 {
+					reg = <1>;
+					remote-endpoint = <&vopl_out_dp>;
+				};
+			};
+		};
+	};
-- 
2.6.3



From zyw at rock-chips.com  Thu May 26 23:02:19 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 14:02:19 +0800
Subject: [PATCH 6/6] ASoC: rockchip: Add machine driver for cdn dp codec
In-Reply-To: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1464328939-8073-7-git-send-email-zyw@rock-chips.com>

The driver is used for cdn dp codec embedded in rk3399

Signed-off-by: Chris Zhong <zyw at rock-chips.com>

---

 .../bindings/sound/rockchip-cdn-dp-audio.txt       |  12 ++
 sound/soc/rockchip/Kconfig                         |   9 ++
 sound/soc/rockchip/Makefile                        |   2 +
 sound/soc/rockchip/rockchip-cdn-dp-audio.c         | 167 +++++++++++++++++++++
 4 files changed, 190 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip-cdn-dp-audio.txt
 create mode 100644 sound/soc/rockchip/rockchip-cdn-dp-audio.c

diff --git a/Documentation/devicetree/bindings/sound/rockchip-cdn-dp-audio.txt b/Documentation/devicetree/bindings/sound/rockchip-cdn-dp-audio.txt
new file mode 100644
index 0000000..b7b0898
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip-cdn-dp-audio.txt
@@ -0,0 +1,12 @@
+Rockchip cdn dp audio bindings
+
+Required properties:
+- compatible: platform specific, must be "rockchip,cdn-dp-audio"
+- i2s-controller: the device of i2s controller
+
+Example:
+
+	cdn_dp_audio: cdn-dp_audio {
+		compatible = "rockchip,cdn-dp-audio";
+		i2s-controller = <&i2s2>;
+	};
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index f1e0c70..7e7d905 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -15,6 +15,15 @@ config SND_SOC_ROCKCHIP_I2S
 	  Rockchip I2S device. The device supports upto maximum of
 	  8 channels each for play and record.
 
+config SND_SOC_ROCKCHIP_CDN_DP_AUDIO
+	tristate "cdn DP audio support"
+	depends on ROCKCHIP_CDN_DP
+	select SND_SOC_ROCKCHIP_I2S
+	select SND_SOC_CDN_DP_AUDIO
+	help
+	  Say Y or M here if you want to add support for SoC audio on Rockchip
+	  boards using the cdn dp codec, such as RK3399.
+
 config SND_SOC_ROCKCHIP_SPDIF
 	tristate "Rockchip SPDIF Device Driver"
 	depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
index c0bf560..9367f55 100644
--- a/sound/soc/rockchip/Makefile
+++ b/sound/soc/rockchip/Makefile
@@ -5,8 +5,10 @@ snd-soc-rockchip-spdif-objs := rockchip_spdif.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-rockchip-i2s.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o
 
+snd-soc-rockchip-cdn-dp-objs := rockchip-cdn-dp-audio.o
 snd-soc-rockchip-max98090-objs := rockchip_max98090.o
 snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o
 
+obj-$(CONFIG_SND_SOC_ROCKCHIP_CDN_DP_AUDIO) += snd-soc-rockchip-cdn-dp.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o
diff --git a/sound/soc/rockchip/rockchip-cdn-dp-audio.c b/sound/soc/rockchip/rockchip-cdn-dp-audio.c
new file mode 100644
index 0000000..2bf6649
--- /dev/null
+++ b/sound/soc/rockchip/rockchip-cdn-dp-audio.c
@@ -0,0 +1,167 @@
+/*
+ * rockchip-cdn-dp-card.c
+ *
+ * ROCKCHIP ALSA SoC DAI driver for cdn dp audio on rockchip processors.
+ *
+ * Copyright (C) 2016 Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * 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/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-cdn-dp-audio"
+
+static int cdn_dp_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_fmt(cpu_dai, dai_fmt);
+	if (ret < 0) {
+		dev_err(cpu_dai->dev, "failed to set cpu_dai fmt.\n");
+		return ret;
+	}
+
+	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 cdn_dp_dai_ops = {
+	.hw_params = cdn_dp_audio_hw_params,
+};
+
+static struct snd_soc_dai_link cdn_dp_dai = {
+	.name = "cdn_dp",
+	.stream_name = "cdn_dp",
+	.codec_name = "cdn-dp-audio",
+	.codec_dai_name = "cdn-dp-hifi",
+	.ops = &cdn_dp_dai_ops,
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBS_CFS,
+};
+
+static struct snd_soc_card cdn_dp_audio_card = {
+	.name = "cdn_dp",
+	.owner = THIS_MODULE,
+	.dai_link = &cdn_dp_dai,
+	.num_links = 1,
+};
+
+static int cdn_dp_audio_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &cdn_dp_audio_card;
+	struct device_node *np = pdev->dev.of_node;
+	int ret;
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+
+	cdn_dp_dai.cpu_of_node = of_parse_phandle(np, "i2s-controller", 0);
+	if (!cdn_dp_dai.cpu_of_node) {
+		dev_err(&pdev->dev, "Property 'i2s-controller' missing !\n");
+		goto free_priv_data;
+	}
+
+	cdn_dp_dai.platform_of_node = cdn_dp_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;
+		goto free_cpu_of_node;
+	}
+
+	dev_info(&pdev->dev, "rockchip cdn dp audio init success.\n");
+
+	return 0;
+
+free_cpu_of_node:
+	cdn_dp_dai.cpu_of_node = NULL;
+	cdn_dp_dai.platform_of_node = NULL;
+free_priv_data:
+	snd_soc_card_set_drvdata(card, NULL);
+	platform_set_drvdata(pdev, NULL);
+	card->dev = NULL;
+
+	return ret;
+}
+
+static int cdn_dp_audio_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+	snd_soc_card_set_drvdata(card, NULL);
+	platform_set_drvdata(pdev, NULL);
+	card->dev = NULL;
+
+	return 0;
+}
+
+static const struct of_device_id cdn_dp_audio_of_match[] = {
+	{ .compatible = "rockchip,cdn-dp-audio", },
+	{},
+};
+
+static struct platform_driver cdn_dp_audio_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+		.of_match_table = cdn_dp_audio_of_match,
+	},
+	.probe = cdn_dp_audio_probe,
+	.remove = cdn_dp_audio_remove,
+};
+module_platform_driver(cdn_dp_audio_driver);
+
+MODULE_AUTHOR("Chris Zhong <zyw at rock-chips.com>");
+MODULE_DESCRIPTION("CDN DP Audio ASoC Interface");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, cdn_dp_audio_of_match);
-- 
2.6.3



From heiko.carstens at de.ibm.com  Thu May 26 23:03:57 2016
From: heiko.carstens at de.ibm.com (Heiko Carstens)
Date: Fri, 27 May 2016 08:03:57 +0200
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160527003753.GA14247@yury-N73SV>
References: <6293194.tGy03QJ9ME@wuerfel>
 <20160525.135039.244098606649448826.davem@davemloft.net>
 <6407614.fdv5XFSBue@wuerfel>
 <20160525.142821.1719403997976778673.davem@davemloft.net>
 <20160526204819.GA10274@yury-N73SV>
 <20160526222943.GA16729@MBP.local>
 <20160527003753.GA14247@yury-N73SV>
Message-ID: <20160527060357.GB3820@osiris>

> > > The cost is pretty trivial though. See kernel/compat_wrapper.o:
> > > COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
> > > 0:   a9bf7bfd        stp     x29, x30, [sp,#-16]!
> > > 4:   910003fd        mov     x29, sp
> > > 8:   2a0003e0        mov     w0, w0
> > > c:   94000000        bl      0 <sys_creat>
> > > 10:  a8c17bfd        ldp     x29, x30, [sp],#16
> > > 14:  d65f03c0        ret
> > 
> > I would say the above could be more expensive than 8 movs (16 bytes to
> > write, read, a branch and a ret). You can also add the I-cache locality,
> > having wrappers for each syscalls instead of a single place for zeroing
> > the upper half (where no other wrapper is necessary).
> > 
> > Can we trick the compiler into doing a tail call optimisation. This
> > could have simply been:
> > 
> > COMPAT_SYSCALL_WRAP2(creat, ...):
> > 	mov	w0, w0
> > 	b	<sys_creat>
> 
> What you talk about was in my initial version. But Heiko insisted on having all
> wrappers together.
> http://www.spinics.net/lists/linux-s390/msg11593.html
> 
> Grep your email for discussion.

I think Catalin's question was more about why there is even a stack frame
generated. It looks like it is not necessary. I did ask this too a couple
of months ago, when we discussed this.

> > > > Cost wise, this seems like it all cancels out in the end, but what
> > > > do I know?
> > > 
> > > I think you know something, and I also think Heiko and other s390 guys
> > > know something as well. So I'd like to listen their arguments here.

If it comes to 64 bit arguments for compat system calls: s390 also has an
x32-like ABI extension which allows user space to use full 64 bit
registers. As far as I know hardly anybody ever made use of that.

However even if that would be widely used, to me it wouldn't make sense to
add new compat system calls which allow 64 bit arguments, simply because
something like

c = (u32)a | (u64)b << 32;

can be done with a single 1-cycle instruction. It's just not worth the
extra effort to maintain additional system call variants.



From geert at linux-m68k.org  Thu May 26 23:39:38 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Fri, 27 May 2016 08:39:38 +0200
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <20160527004256.GD14269@verge.net.au>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
 <20160525004825.GC7292@verge.net.au>
 <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>
 <20160526022833.GE18393@verge.net.au>
 <59e6225a-6dfa-8bde-dd2e-3428d6fedfe2@de.bosch.com>
 <20160527004256.GD14269@verge.net.au>
Message-ID: <CAMuHMdVU+FNsQ7uLN82MiGEak5WYqd_ypJ=MLB8U419ZCiG6ow@mail.gmail.com>

On Fri, May 27, 2016 at 2:42 AM, Simon Horman <horms at verge.net.au> wrote:
>   Probably there are some central aspects of cpus that are shared
>   between the r8a7795 and r8a7796. And I think that your patch captures
>   that. But I also think that there will be non-shared aspects and
>   perhaps the complexity of splitting the cpus node between per-SoC
>   and common dtsi files isn't worth it.

R8a7795 and r8a7796 have different numbers of CPU cores, and different
maximum frequencies, thus needing different operating-point properties.

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 maitysanchayan at gmail.com  Thu May 26 23:33:01 2016
From: maitysanchayan at gmail.com (maitysanchayan at gmail.com)
Date: Fri, 27 May 2016 12:03:01 +0530
Subject: [PATCH v3 4/4] soc: Add SoC driver for Freescale Vybrid platform
In-Reply-To: <CAL_JsqKCwy=aXveTfnaQuZ5b3Ld9nzABgPfdPm1JX3CBuvzG+Q@mail.gmail.com>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
 <ffef165d05f71a1b19437171d8fdb4bc78f6b1e3.1463737502.git.maitysanchayan@gmail.com>
 <20160523211813.GA30237@rob-hp-laptop>
 <20160524041447.GA2884@Sanchayan-Arch.localdomain>
 <CAL_JsqKCwy=aXveTfnaQuZ5b3Ld9nzABgPfdPm1JX3CBuvzG+Q@mail.gmail.com>
Message-ID: <20160527063301.GB1554@Sanchayan-Arch.localdomain>

Hello Rob,

On 16-05-24 12:09:41, Rob Herring wrote:
> On Mon, May 23, 2016 at 11:14 PM,  <maitysanchayan at gmail.com> wrote:
> > Hello Rob,
> >
> > On 16-05-23 16:18:13, Rob Herring wrote:
> >> On Fri, May 20, 2016 at 03:32:05PM +0530, Sanchayan Maity wrote:
> >> > This adds a SoC driver to be used by Freescale Vybrid SoC's.
> >> > Driver utilises syscon and nvmem consumer API's to get the
> >> > various register values needed and expose the SoC specific
> >> > properties via sysfs.
> >> >
> >> > A sample output from Colibri Vybrid VF61 is below:
> >> >
> >> > root at colibri-vf:~# cd /sys/bus/soc/devices/soc0
> >> > root at colibri-vf:/sys/bus/soc/devices/soc0# ls
> >> > family     machine    power      revision   soc_id     subsystem  uevent
> >> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat family
> >> > Freescale Vybrid VF610
> >> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat machine
> >> > Freescale Vybrid
> >> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat revision
> >> > 00000013
> >> > root at colibri-vf:/sys/bus/soc/devices/soc0# cat soc_id
> >> > df6472a6130f29d4
> >> >
> >> > Signed-off-by: Sanchayan Maity <maitysanchayan at gmail.com>
> >> > ---
> >> >  .../bindings/arm/freescale/fsl,vf610-soc.txt       |  20 +++
> >> >  drivers/soc/Kconfig                                |   1 +
> >> >  drivers/soc/fsl/Kconfig                            |  10 ++
> >> >  drivers/soc/fsl/Makefile                           |   1 +
> >> >  drivers/soc/fsl/soc-vf610.c                        | 198 +++++++++++++++++++++
> >> >  5 files changed, 230 insertions(+)
> >> >  create mode 100644 Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> >> >  create mode 100644 drivers/soc/fsl/Kconfig
> >> >  create mode 100644 drivers/soc/fsl/soc-vf610.c
> >> >
> >> > diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> >> > new file mode 100644
> >> > index 0000000..338905d
> >> > --- /dev/null
> >> > +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,vf610-soc.txt
> >> > @@ -0,0 +1,20 @@
> >> > +Vybrid System-on-Chip
> >> > +---------------------
> >> > +
> >> > +Required properties:
> >> > +
> >> > +- compatible: "fsl,vf610-soc"
> >> > +- rom-revision: phandle to the on-chip ROM node
> >> > +- mscm: phandle to the MSCM CPU configuration node
> >> > +- nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
> >> > +- nvmem-cell-names: should contain string names "cfg0" and "cfg1"
> >>
> >> I still have similar concerns as the discussion on the last version.
> >> This version only proves that you aren't describing h/w, but rather just
> >> a collection of data that some driver wants.
> >>
> >> A driver can just as easily look-up all the nodes directly that these
> >> phandles point to.
> >
> > Agreed, that we can look up all the nodes directly that these phandles
> > refer to but I would still need a DT entry to bind to. While I could
> > bind to existing nodes like mscm cpucfg but that doesn't seem right.
> >
> > The very first approach that we had taken was to integrate this functionality
> > in mach-vf610.c code under mach-imx
> > http://www.spinics.net/lists/devicetree/msg80654.html
> 
> Yes, everyone wants to move all platform devices in the kernel to a
> corresponding DT node. The result is often making up nodes to do this.
> It's the same thing with cpufreq.
> 
> > and then it was recommended to migrate this to drivers/soc where we did use
> > phandles or direct look up via compatible strings
> 
> The location in the tree is an orthogonal issue. You could move it and
> use of_machine_is_compatible without any DT change.
> 
> The primary issue I have here is how do we bind soc_bus to DT in a
> consistent way. Sorry, but vybrid specific patches alone are never
> going to solve that issue.
> 
> > http://www.spinics.net/lists/arm-kernel/msg420847.html
> >
> > and
> >
> > http://lkml.iu.edu/hypermail/linux/kernel/1506.0/03787.html
> >
> > There hasn't been a consensus since v1.
> 
> I actually prefer your previous version binding soc_bus to the root
> bus node to this version. I think that is closer to the right
> direction. 

So if I understand correctly, the binding at the SoC level is fine.
Keeping that but removing the additional made-up properties, viz. below

rom-revision: phandle to the on-chip ROM node
mscm: phandle to the MSCM CPU configuration node
nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
nvmem-cell-names: should contain string names "cfg0" and "cfg1"

would be fine?

We would have something similar to here
http://www.spinics.net/lists/devicetree/msg80655.html

but now with the DT binding under SoC bus.

Regards,
Sanchayan.

> After all, pretty much everything is an SOC and every SOC
> has an SOC bus. Pretty much every SOC and board have revisions and may
> need to expose that revision info as well. We have to do this
> consistently which means having a default implementation for
> simple-bus that is not opt-in.
> 
> Alternatively, we should just deprecate soc_bus and come up a
> different solution. Either way, I think we have a half implemented
> solution currently.
> 
> Rob


From thunder.leizhen at huawei.com  Fri May 27 00:04:11 2016
From: thunder.leizhen at huawei.com (Leizhen (ThunderTown))
Date: Fri, 27 May 2016 15:04:11 +0800
Subject: [PATCH 2/3] of/numa: fix a memory@ dt node can only contains one
 memory block
In-Reply-To: <CAL_JsqJXu36qYMOZeWDnMQ8BnOxMrixv5N70hvTjDixhMCQKRw@mail.gmail.com>
References: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
 <1464230639-9852-2-git-send-email-thunder.leizhen@huawei.com>
 <20160526131345.GA12024@rob-hp-laptop> <5747C0BF.505@huawei.com>
 <CAL_JsqJXu36qYMOZeWDnMQ8BnOxMrixv5N70hvTjDixhMCQKRw@mail.gmail.com>
Message-ID: <5747F16B.5050404@huawei.com>



On 2016/5/27 12:20, Rob Herring wrote:
> On Thu, May 26, 2016 at 10:36 PM, Leizhen (ThunderTown)
> <thunder.leizhen at huawei.com> wrote:
>>
>>
>> On 2016/5/26 21:13, Rob Herring wrote:
>>> On Thu, May 26, 2016 at 10:43:58AM +0800, Zhen Lei wrote:
>>>> For a normal memory@ devicetree node, its reg property can contains more
>>>> memory blocks.
>>>>
>>>> Because we don't known how many memory blocks maybe contained, so we try
>>>> from index=0, increase 1 until error returned(the end).
>>>>
>>>> Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
>>>> ---
>>>>  drivers/of/of_numa.c | 30 ++++++++++++++++++++----------
>>>>  1 file changed, 20 insertions(+), 10 deletions(-)
>>>>
>>>> diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
>>>> index 21d831f..2c5f249 100644
>>>> --- a/drivers/of/of_numa.c
>>>> +++ b/drivers/of/of_numa.c
>>>> @@ -63,7 +63,7 @@ static int __init of_numa_parse_memory_nodes(void)
>>>>      struct device_node *np = NULL;
>>>>      struct resource rsrc;
>>>>      u32 nid;
>>>> -    int r = 0;
>>>> +    int i, r = 0;
>>>>
>>>>      for (;;) {
>>>>              np = of_find_node_by_type(np, "memory");
>>>> @@ -82,17 +82,27 @@ static int __init of_numa_parse_memory_nodes(void)
>>>>                      /* some other error */
>>>>                      break;
>>>>
>>>> -            r = of_address_to_resource(np, 0, &rsrc);
>>>> -            if (r) {
>>>> -                    pr_err("NUMA: bad reg property in memory node\n");
>>>> -                    break;
>>>> +            for (i = 0; ; i++) {
>>>> +                    r = of_address_to_resource(np, i, &rsrc);
>>>> +                    if (r) {
>>>> +                            /* reached the end of of_address */
>>>> +                            if (i > 0) {
>>>> +                                    r = 0;
>>>> +                                    break;
>>>> +                            }
>>>> +
>>>> +                            pr_err("NUMA: bad reg property in memory node\n");
>>>> +                            goto finished;
>>>> +                    }
>>>> +
>>>> +                    r = numa_add_memblk(nid, rsrc.start,
>>>> +                                        rsrc.end - rsrc.start + 1);
>>>> +                    if (r)
>>>> +                            goto finished;
>>>>              }
>>>> -
>>>> -            r = numa_add_memblk(nid, rsrc.start,
>>>> -                                rsrc.end - rsrc.start + 1);
>>>> -            if (r)
>>>> -                    break;
>>>>      }
>>>> +
>>>> +finished:
>>>>      of_node_put(np);
>>>
>>> This function can be simplified down to:
>>>
>>>       for_each_node_by_type(np, "memory") {
>> OK, That's good.
>>
>>>               r = of_property_read_u32(np, "numa-node-id", &nid);
>>>               if (r == -EINVAL)
>>>                       /*
>>>                        * property doesn't exist if -EINVAL, continue
>>>                        * looking for more memory nodes with
>>>                        * "numa-node-id" property
>>>                        */
>>>                       continue;
>> Hi, everybody:
>>     If some "memory" node contains "numa-node-id", but some others missed. Can we simply ignored it?
>> I think we should break out too, and faking to only have node0.
> 
> Continuing to work is probably better than not.
> 
>>
>>>               else if (r)
>>>                       /* some other error */
>>>                       break;
>>>
>>>               r = of_address_to_resource(np, 0, &rsrc);
>>>               for (i = 0; !r; i++, r = of_address_to_resource(np, i,
>>
>> But r(non-zero) is just break this loop, the original is break the outer for (;;) loop
> 
> It is not really the kernel's job to validate the DT. If there's
> random things in it then kernel's behavior is undefined.
> 
>>
>> How about as below?
>>
>>         for_each_node_by_type(np, "memory") {
>>                 ... ...
>>
>>                 for (i = 0; !of_address_to_resource(np, i, &rsrc); i++) {
>>                         r = numa_add_memblk(nid, rsrc.start,
>>                                             rsrc.end - rsrc.start + 1);
>>                         if (r)
>>                                 goto finished;
>>                 }
>>
>>                 if (!i)
>>                         pr_err("NUMA: bad reg property in memory node\n");
>>         }
>>
>> finished:
> 
> Please try to avoid the goto. You can check r in the outer loop too.

OK. I have rewritten this function according to your advice.

	for_each_node_by_type(np, "memory") {
                r = of_property_read_u32(np, "numa-node-id", &nid);
                if (r == -EINVAL)
                        /*
                         * property doesn't exist if -EINVAL, continue
                         * looking for more memory nodes with
                         * "numa-node-id" property
                         */
                        continue;
									//I deleted the break of "some other error", and it will break in below "if (!i || r)" branch

                for (i = 0; !r && !of_address_to_resource(np, i, &rsrc); i++)
                        r = numa_add_memblk(nid, rsrc.start,
                                            rsrc.end - rsrc.start + 1);

                if (!i || r) {
                        of_node_put(np);				//I moved here, so that it looks more clear. Because in the normal use of for_each_node_by_type, of_node_put is not required
                        pr_err("NUMA: bad property in memory node\n");	//Deleted "reg", so that it's suitable or harmless for other error cases
                        break;
                }
        }

	return r;

> 
> Rob
> 
> .
> 



From hdegoede at redhat.com  Fri May 27 00:06:40 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Fri, 27 May 2016 09:06:40 +0200
Subject: [PATCH] reset: Put back *_optional variants
In-Reply-To: <57476E48.2060204@synopsys.com>
References: <ca359e013c30f27c825a9580164b01da5ca6476d.1464224883.git.johnyoun@synopsys.com>
 <12e450f0-70ea-29f8-0bf7-8a0697263f2d@redhat.com>
 <57476E48.2060204@synopsys.com>
Message-ID: <dcf6372f-4910-bd03-f1b5-c7e0086fdead@redhat.com>

Hi,

On 26-05-16 23:44, John Youn wrote:
> On 5/26/2016 1:25 PM, Hans de Goede wrote:
>> Hi,
>>
>> On 26-05-16 03:15, John Youn wrote:
>>> Prior to commit 6c96f05c8bb8 ("reset: Make [of_]reset_control_get[_foo]
>>> functions wrappers"), the optional variants returned -ENOTSUPP when
>>> CONFIG_RESET_CONTROLLER was not set. This patch reverts to this
>>> behavior. Otherwise those calls will return -EINVAL causing users to
>>> think that an error occurred when CONFIG_RESET_CONTROLLER is not set.
>>>
>>> Fixes: 6c96f05c8bb8 ("reset: Make [of_]reset_control_get[_foo] functions wrappers")
>>> Signed-off-by: John Youn <johnyoun at synopsys.com>
>>> ---
>>>
>>> Hi Philipp, Hans,
>>>
>>> The commit referenced above breaks an upcoming patch for the dwc2
>>> driver that adds an optional reset control.
>>>
>>> https://marc.info/?l=linux-usb&m=146161328211584&w=2
>>>
>>> I've attempted to add the optional variants back the way they were
>>> working before. Let me know if I need to do anything else to fix it or
>>> if it should be done another way.
>>>
>>> Regards,
>>> John
>>
>> Hmm, I don't like all the extra code your patch adds just to fix
>> a return value...
>>
>> Looking at the code before my "reset: Make [of_]reset_control_get[_foo]
>> functions wrappers" patch, all the dev*_get* functions were
>> returning ENOTSUPP except for [devm_]reset_control_get, so following
>> your logic we should also change the of_reset_control_get_by_index
>> variant to return -ENOTSUP.
>>
>> Or better, simply make them all return -ENOTSUP, that seems both
>> consistent and more KISS to me, this would mean an error code
>> change for [devm_]reset_control_get, but will fix all the other
>> getters from having a changed error-code, and I would callers
>> of [devm_]reset_control_get to not care which error code they
>> get, except for -EPROBE_DEFER.
>>
>> So IMHO the following change would be a better way to fix this:
>>
>> --- a/include/linux/reset.h
>> +++ b/include/linux/reset.h
>> @@ -65,14 +65,14 @@ static inline struct reset_control *__of_reset_control_get(
>>                                          struct device_node *node,
>>                                          const char *id, int index, int shared)
>>   {
>> -   return ERR_PTR(-EINVAL);
>> + return ERR_PTR(-ENOTSUPP);
>>   }
>>
>>   static inline struct reset_control *__devm_reset_control_get(
>>                                          struct device *dev,
>>                                          const char *id, int index, int shared)
>>   {
>> -   return ERR_PTR(-EINVAL);
>> + return ERR_PTR(-ENOTSUPP);
>>   }
>>
>>   #endif /* CONFIG_RESET_CONTROLLER */
>
>
> I'm good with this. However, per Philipp on a previous thread, the
> intended behavior is to return -EINVAL for the non-optional functions.
>
> http://marc.info/?l=linux-usb&m=146156945528848&w=2

As Philipp rightfully points out, calling the non-optional functions
without CONFIG_RESET_CONTROLLER is a no-no, so IMHO we should not have to
care too much about the error code in that case, as long as we return
an error.

Also note that even before my patch things were already inconsistent
with the of_...get... functions already always returning
-ENOTSUPP when CONFIG_RESET_CONTROLLER was not set, to me it seems
best and also KISS to just return -ENOTSUPP from all get functions
when CONFIG_RESET_CONTROLLER is not set.

Anyways this is Philipp's call, this is all just my 2 cents.

Regards,

Hans


From isubramanian at apm.com  Fri May 27 00:22:42 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 27 May 2016 00:22:42 -0700
Subject: [PATCH v1 0/6] drivers: net: xgene: Fix 1G hot-plug and module support
Message-ID: <1464333768-26150-1-git-send-email-isubramanian@apm.com>

This patchset addresses the following issues,

1. hot-plug issue on the SGMII 1G interface
	- by adding a driver for MDIO management
2. fixes the kernel crash when the driver loaded as an kernel module
	- by fixing hardware cleanups and rearrange kernel API calls

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
---

Iyappan Subramanian (6):
  drivers: net: xgene: MAC and PHY configuration changes
  drivers: net: xgene: Backward compatibility with older firmware
  drivers: net: phy: Add MDIO driver
  dtb: xgene: Add MDIO node
  dtb: xgene: Remove clock nodes
  drivers: net: xgene: Fix module load/unload crash

 arch/arm64/boot/dts/apm/apm-merlin.dts            |  10 +
 arch/arm64/boot/dts/apm/apm-mustang.dts           |  12 +
 arch/arm64/boot/dts/apm/apm-shadowcat.dtsi        |  23 +-
 arch/arm64/boot/dts/apm/apm-storm.dtsi            |  38 +-
 drivers/net/ethernet/apm/xgene/Kconfig            |   1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    | 241 ++++++----
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    |  18 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 325 ++++++++-----
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |  36 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 191 +++++++-
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h |   8 +
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c |  66 ++-
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h |   4 +
 drivers/net/phy/Kconfig                           |   7 +
 drivers/net/phy/Makefile                          |   1 +
 drivers/net/phy/mdio-xgene.c                      | 531 ++++++++++++++++++++++
 drivers/net/phy/mdio-xgene.h                      | 140 ++++++
 17 files changed, 1373 insertions(+), 279 deletions(-)
 create mode 100644 drivers/net/phy/mdio-xgene.c
 create mode 100644 drivers/net/phy/mdio-xgene.h

-- 
1.9.1



From isubramanian at apm.com  Fri May 27 00:22:43 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 27 May 2016 00:22:43 -0700
Subject: [PATCH v1 1/6] drivers: net: xgene: MAC and PHY configuration changes
In-Reply-To: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
References: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
Message-ID: <1464333768-26150-2-git-send-email-isubramanian@apm.com>

This patch fixes MAC configuration to support 10/100GbE for SGMII and
link_state call back. It also sets pdata->mdio_driver flag based on
ethernet mdio subnode and prepare for MDIO driver support.

In summary, following are the changes,

- Added set_speed function pointer in mac_ops
- Changed link_state to call the set_speed
- Add 10/100 support for SGMII based 1G
- Fixed mac_init for 1G

- Call mac_ops rx_enable/disable and tx_enable/disable function pointers
- Add acpi_phy_find_device to find PHY using phy-handle reference object
- Changing phy_start and phy_stop calls based on phy_dev object existence
- Calling phy_connect based on pdata->mdio_driver flag

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Fushen Chen <fchen at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    | 189 +++++++++++++---------
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    |   4 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  |  40 +++--
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |   2 +
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 106 +++++++++++-
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h |   8 +
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h |   4 +
 7 files changed, 256 insertions(+), 97 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 2f5638f..6bc8360 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -512,14 +512,11 @@ static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata)
 #endif
 }
 
-static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
+static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
 {
 	struct device *dev = &pdata->pdev->dev;
-	u32 value, mc2;
-	u32 intf_ctl, rgmii;
-	u32 icm0, icm2;
-
-	xgene_gmac_reset(pdata);
+	u32 icm0, icm2, mc2;
+	u32 intf_ctl, rgmii, value;
 
 	xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0);
 	xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2);
@@ -564,7 +561,18 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
 	mc2 |= FULL_DUPLEX2 | PAD_CRC;
 	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
 	xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
+	xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
+	xgene_enet_configure_clock(pdata);
+
+	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, icm0);
+	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2);
+}
 
+static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
+{
+	u32 value;
+
+	xgene_gmac_set_speed(pdata);
 	xgene_gmac_set_mac_addr(pdata);
 
 	/* Adjust MDC clock frequency */
@@ -579,15 +587,10 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
 
 	/* Rtype should be copied from FP */
 	xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0);
-	xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
-	xgene_enet_configure_clock(pdata);
 
 	/* Rx-Tx traffic resume */
 	xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
 
-	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, icm0);
-	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2);
-
 	xgene_enet_rd_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, &value);
 	value &= ~TX_DV_GATE_EN0;
 	value &= ~RX_DV_GATE_EN0;
@@ -671,25 +674,11 @@ bool xgene_ring_mgr_init(struct xgene_enet_pdata *p)
 
 static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
 {
-	u32 val;
-
 	if (!xgene_ring_mgr_init(pdata))
 		return -ENODEV;
 
-	if (!IS_ERR(pdata->clk)) {
-		clk_prepare_enable(pdata->clk);
-		clk_disable_unprepare(pdata->clk);
-		clk_prepare_enable(pdata->clk);
-		xgene_enet_ecc_init(pdata);
-	}
 	xgene_enet_config_ring_if_assoc(pdata);
 
-	/* Enable auto-incr for scanning */
-	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &val);
-	val |= SCAN_AUTO_INCR;
-	MGMT_CLOCK_SEL_SET(&val, 1);
-	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, val);
-
 	return 0;
 }
 
@@ -724,29 +713,49 @@ static int xgene_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
 static void xgene_enet_adjust_link(struct net_device *ndev)
 {
 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	const struct xgene_mac_ops *mac_ops = pdata->mac_ops;
 	struct phy_device *phydev = pdata->phy_dev;
 
 	if (phydev->link) {
 		if (pdata->phy_speed != phydev->speed) {
 			pdata->phy_speed = phydev->speed;
-			xgene_gmac_init(pdata);
-			xgene_gmac_rx_enable(pdata);
-			xgene_gmac_tx_enable(pdata);
+			mac_ops->set_speed(pdata);
+			mac_ops->rx_enable(pdata);
+			mac_ops->tx_enable(pdata);
 			phy_print_status(phydev);
 		}
 	} else {
-		xgene_gmac_rx_disable(pdata);
-		xgene_gmac_tx_disable(pdata);
+		mac_ops->rx_disable(pdata);
+		mac_ops->tx_disable(pdata);
 		pdata->phy_speed = SPEED_UNKNOWN;
 		phy_print_status(phydev);
 	}
 }
 
-static int xgene_enet_phy_connect(struct net_device *ndev)
+#ifdef CONFIG_ACPI
+static struct acpi_device *acpi_phy_find_device(struct device *dev)
+{
+	struct acpi_reference_args args;
+	struct fwnode_handle *fw_node;
+	int status;
+
+	fw_node = acpi_fwnode_handle(ACPI_COMPANION(dev));
+	status = acpi_node_get_property_reference(fw_node, "phy-handle", 0,
+						  &args);
+	if (ACPI_FAILURE(status)) {
+		dev_dbg(dev, "No matching phy in ACPI table\n");
+		return NULL;
+	}
+
+	return args.adev;
+}
+#endif
+
+int xgene_enet_phy_connect(struct net_device *ndev)
 {
 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
 	struct device_node *phy_np;
-	struct phy_device *phy_dev;
+	struct phy_device *phy_dev = NULL;
 	struct device *dev = &pdata->pdev->dev;
 
 	if (dev->of_node) {
@@ -756,23 +765,25 @@ static int xgene_enet_phy_connect(struct net_device *ndev)
 			return -ENODEV;
 		}
 
-		phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link,
-					 0, pdata->phy_mode);
-		if (!phy_dev) {
-			netdev_err(ndev, "Could not connect to PHY\n");
-			return -ENODEV;
-		}
-
-		pdata->phy_dev = phy_dev;
+		pdata->phy_dev = of_phy_find_device(phy_np);
 	} else {
-		phy_dev = pdata->phy_dev;
+#ifdef CONFIG_ACPI
+		if (pdata->mdio_driver) {
+			struct acpi_device *adev;
 
-		if (!phy_dev ||
-		    phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
-				       pdata->phy_mode)) {
-			netdev_err(ndev, "Could not connect to PHY\n");
-			return  -ENODEV;
+			adev = acpi_phy_find_device(dev);
+			if (adev)
+				pdata->phy_dev =  adev->driver_data;
 		}
+#endif
+	}
+
+	phy_dev = pdata->phy_dev;
+	if (!phy_dev ||
+	    phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
+			       pdata->phy_mode)) {
+		netdev_err(ndev, "Could not connect to PHY\n");
+		return  -ENODEV;
 	}
 
 	pdata->phy_speed = SPEED_UNKNOWN;
@@ -788,12 +799,9 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
 				  struct mii_bus *mdio)
 {
 	struct device *dev = &pdata->pdev->dev;
-	struct net_device *ndev = pdata->ndev;
-	struct phy_device *phy;
-	struct device_node *child_np;
 	struct device_node *mdio_np = NULL;
-	int ret;
-	u32 phy_id;
+	struct device_node *child_np;
+	u32 phyid;
 
 	if (dev->of_node) {
 		for_each_child_of_node(dev->of_node, child_np) {
@@ -805,38 +813,50 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
 		}
 
 		if (!mdio_np) {
-			netdev_dbg(ndev, "No mdio node in the dts\n");
-			return -ENXIO;
+			mdiobus_free(mdio);
+			return 0;
 		}
 
+		pdata->mdio_driver = false;
+
 		return of_mdiobus_register(mdio, mdio_np);
-	}
+	} else {
+#ifdef CONFIG_ACPI
+		struct phy_device *phy;
+		int ret;
 
-	/* Mask out all PHYs from auto probing. */
-	mdio->phy_mask = ~0;
+		if (pdata->mdio_driver) {
+			mdiobus_free(mdio);
+			return 0;
+		}
 
-	/* Register the MDIO bus */
-	ret = mdiobus_register(mdio);
-	if (ret)
-		return ret;
+		/* Mask out all PHYs from auto probing. */
+		mdio->phy_mask = ~0;
 
-	ret = device_property_read_u32(dev, "phy-channel", &phy_id);
-	if (ret)
-		ret = device_property_read_u32(dev, "phy-addr", &phy_id);
-	if (ret)
-		return -EINVAL;
+		/* Register the MDIO bus */
+		ret = mdiobus_register(mdio);
+		if (ret)
+			return ret;
 
-	phy = get_phy_device(mdio, phy_id, false);
-	if (IS_ERR(phy))
-		return -EIO;
+		ret = device_property_read_u32(dev, "phy-channel", &phyid);
+		if (ret)
+			ret = device_property_read_u32(dev, "phy-addr", &phyid);
+		if (ret)
+			return -EINVAL;
 
-	ret = phy_device_register(phy);
-	if (ret)
-		phy_device_free(phy);
-	else
-		pdata->phy_dev = phy;
+		phy = get_phy_device(mdio, phy_id, false);
+		if (IS_ERR(phy))
+			return -EIO;
 
-	return ret;
+		ret = phy_device_register(phy);
+		if (ret)
+			phy_device_free(phy);
+		else
+			pdata->phy_dev = phy;
+
+		return ret;
+#endif
+	}
 }
 
 int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
@@ -861,7 +881,13 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
 	ret = xgene_mdiobus_register(pdata, mdio_bus);
 	if (ret) {
 		netdev_err(ndev, "Failed to register MDIO bus\n");
+		if (mdio_bus->state == MDIOBUS_REGISTERED)
+			mdiobus_unregister(pdata->mdio_bus);
 		mdiobus_free(mdio_bus);
+		if (pdata->mdio_driver) {
+			ret = xgene_enet_phy_connect(ndev);
+			return 0;
+		}
 		return ret;
 	}
 	pdata->mdio_bus = mdio_bus;
@@ -873,14 +899,22 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
 	return ret;
 }
 
+void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata)
+{
+	if (pdata->phy_dev)
+		phy_disconnect(pdata->phy_dev);
+}
+
 void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
 {
 	if (pdata->phy_dev)
 		phy_disconnect(pdata->phy_dev);
 
-	mdiobus_unregister(pdata->mdio_bus);
-	mdiobus_free(pdata->mdio_bus);
-	pdata->mdio_bus = NULL;
+	if (!pdata->mdio_driver) {
+		mdiobus_unregister(pdata->mdio_bus);
+		mdiobus_free(pdata->mdio_bus);
+		pdata->mdio_bus = NULL;
+	}
 }
 
 const struct xgene_mac_ops xgene_gmac_ops = {
@@ -890,6 +924,7 @@ const struct xgene_mac_ops xgene_gmac_ops = {
 	.tx_enable = xgene_gmac_tx_enable,
 	.rx_disable = xgene_gmac_rx_disable,
 	.tx_disable = xgene_gmac_tx_disable,
+	.set_speed = xgene_gmac_set_speed,
 	.set_mac_addr = xgene_gmac_set_mac_addr,
 };
 
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 45220be..742520e 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -160,7 +160,9 @@ enum xgene_enet_rm {
 #define CFG_CLE_DSTQID0(val)		(val & GENMASK(11, 0))
 #define CFG_CLE_FPSEL0(val)		((val << 16) & GENMASK(19, 16))
 #define ICM_CONFIG0_REG_0_ADDR		0x0400
+#define ICM_CONFIG0_REG_1_ADDR		0x0408
 #define ICM_CONFIG2_REG_0_ADDR		0x0410
+#define ICM_CONFIG2_REG_1_ADDR		0x0414
 #define RX_DV_GATE_REG_0_ADDR		0x05fc
 #define TX_DV_GATE_EN0			BIT(2)
 #define RX_DV_GATE_EN0			BIT(1)
@@ -347,6 +349,8 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
 int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
 void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
 bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);
+int xgene_enet_phy_connect(struct net_device *ndev);
+void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata);
 
 extern const struct xgene_mac_ops xgene_gmac_ops;
 extern const struct xgene_port_ops xgene_gport_ops;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index d208b17..c698044 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -727,11 +727,12 @@ static int xgene_enet_open(struct net_device *ndev)
 	ret = xgene_enet_register_irq(ndev);
 	if (ret)
 		return ret;
-
-	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
+	if (pdata->phy_dev) {
 		phy_start(pdata->phy_dev);
-	else
+	} else {
 		schedule_delayed_work(&pdata->link_work, PHY_POLL_LINK_OFF);
+		netif_carrier_off(ndev);
+	}
 
 	netif_start_queue(ndev);
 
@@ -746,7 +747,7 @@ static int xgene_enet_close(struct net_device *ndev)
 
 	netif_stop_queue(ndev);
 
-	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
+	if (pdata->phy_dev)
 		phy_stop(pdata->phy_dev);
 	else
 		cancel_delayed_work_sync(&pdata->link_work);
@@ -1291,6 +1292,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
 	struct resource *res;
 	void __iomem *base_addr;
 	u32 offset;
+	const char *ph;
 	int ret = 0;
 
 	pdev = pdata->pdev;
@@ -1368,13 +1370,18 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
 	if (ret)
 		return ret;
 
+	ret = device_property_read_string(dev, "phy-handle", &ph);
+	if (!ret)
+		pdata->mdio_driver = true;
+
 	pdata->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(pdata->clk)) {
 		/* Firmware may have set up the clock already. */
 		dev_info(dev, "clocks have been setup already\n");
 	}
 
-	if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
+	if ((pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) &&
+	    (pdata->enet_id == XGENE_ENET1))
 		base_addr = pdata->base_addr - (pdata->port_id * MAC_OFFSET);
 	else
 		base_addr = pdata->base_addr;
@@ -1577,7 +1584,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
 	struct net_device *ndev;
 	struct xgene_enet_pdata *pdata;
 	struct device *dev = &pdev->dev;
-	const struct xgene_mac_ops *mac_ops;
+	void (*link_state)(struct work_struct *);
 	const struct of_device_id *of_id;
 	int ret;
 
@@ -1603,15 +1610,17 @@ static int xgene_enet_probe(struct platform_device *pdev)
 	if (of_id) {
 		pdata->enet_id = (enum xgene_enet_id)of_id->data;
 	}
-#ifdef CONFIG_ACPI
 	else {
+#ifdef CONFIG_ACPI
 		const struct acpi_device_id *acpi_id;
 
 		acpi_id = acpi_match_device(xgene_enet_acpi_match, &pdev->dev);
-		if (acpi_id)
-			pdata->enet_id = (enum xgene_enet_id) acpi_id->driver_data;
-	}
+		if (acpi_id) {
+			enet_id = (enum xgene_enet_id)acpi_id->driver_data;
+			pdata->enet_id = enet_id;
+		}
 #endif
+	}
 	if (!pdata->enet_id) {
 		free_netdev(ndev);
 		return -ENODEV;
@@ -1645,13 +1654,18 @@ static int xgene_enet_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_netdev;
 
-	mac_ops = pdata->mac_ops;
+	link_state = pdata->mac_ops->link_state;
 	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
 		ret = xgene_enet_mdio_config(pdata);
 		if (ret)
 			goto err_netdev;
+	} else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
+		if (pdata->mdio_driver)
+			ret = xgene_enet_phy_connect(ndev);
+		else
+			INIT_DELAYED_WORK(&pdata->link_work, link_state);
 	} else {
-		INIT_DELAYED_WORK(&pdata->link_work, mac_ops->link_state);
+		INIT_DELAYED_WORK(&pdata->link_work, link_state);
 	}
 
 	xgene_enet_napi_add(pdata);
@@ -1679,6 +1693,8 @@ static int xgene_enet_remove(struct platform_device *pdev)
 	xgene_enet_napi_del(pdata);
 	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
 		xgene_enet_mdio_remove(pdata);
+	else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII)
+		xgene_enet_phy_disconnect(pdata);
 	unregister_netdev(ndev);
 	xgene_enet_delete_desc_rings(pdata);
 	pdata->port_ops->shutdown(pdata);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 092fbec..0fe1a96 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -140,6 +140,7 @@ struct xgene_mac_ops {
 	void (*rx_enable)(struct xgene_enet_pdata *pdata);
 	void (*tx_disable)(struct xgene_enet_pdata *pdata);
 	void (*rx_disable)(struct xgene_enet_pdata *pdata);
+	void (*set_speed)(struct xgene_enet_pdata *pdata);
 	void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
 	void (*set_mss)(struct xgene_enet_pdata *pdata);
 	void (*link_state)(struct work_struct *work);
@@ -211,6 +212,7 @@ struct xgene_enet_pdata {
 	u32 mss;
 	u8 tx_delay;
 	u8 rx_delay;
+	bool mdio_driver;
 };
 
 struct xgene_indirect_ctl {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index 7847551..6d53de4 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -28,6 +28,12 @@ static void xgene_enet_wr_csr(struct xgene_enet_pdata *p, u32 offset, u32 val)
 	iowrite32(val, p->eth_csr_addr + offset);
 }
 
+static void xgene_enet_wr_clkrst_csr(struct xgene_enet_pdata *p, u32 offset,
+				     u32 val)
+{
+	iowrite32(val, p->base_addr + offset);
+}
+
 static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *p,
 				  u32 offset, u32 val)
 {
@@ -93,6 +99,11 @@ static u32 xgene_enet_rd_diag_csr(struct xgene_enet_pdata *p, u32 offset)
 	return ioread32(p->eth_diag_csr_addr + offset);
 }
 
+static u32 xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *p, u32 offset)
+{
+	return ioread32(p->mcx_mac_csr_addr + offset);
+}
+
 static u32 xgene_enet_rd_indirect(struct xgene_indirect_ctl *ctl, u32 rd_addr)
 {
 	u32 rd_data;
@@ -229,21 +240,97 @@ static u32 xgene_enet_link_status(struct xgene_enet_pdata *p)
 
 	data = xgene_mii_phy_read(p, INT_PHY_ADDR,
 				  SGMII_BASE_PAGE_ABILITY_ADDR >> 2);
+	if (LINK_SPEED(data) == PHY_SPEED_1000)
+		p->phy_speed = SPEED_1000;
+	else if (LINK_SPEED(data) == PHY_SPEED_100)
+		p->phy_speed = SPEED_100;
+	else
+		p->phy_speed = SPEED_10;
 
 	return data & LINK_UP;
 }
 
+static void xgene_sgmac_set_speed(struct xgene_enet_pdata *p)
+{
+	u32 icm0_addr, icm2_addr, debug_addr;
+	u32 icm0, icm2, intf_ctl;
+	u32 mc2, value;
+
+	if (p->phy_speed != SPEED_UNKNOWN) {
+		value = xgene_mii_phy_read(p, INT_PHY_ADDR,
+					   SGMII_BASE_PAGE_ABILITY_ADDR >> 2);
+		if (!(value & LINK_UP)) {
+			xgene_mii_phy_write(p, INT_PHY_ADDR,
+					    SGMII_TBI_CONTROL_ADDR >> 2,
+					    0x8000);
+			xgene_mii_phy_write(p, INT_PHY_ADDR,
+					    SGMII_TBI_CONTROL_ADDR >> 2, 0x0);
+		}
+	}
+
+	if (p->enet_id == XGENE_ENET1) {
+		icm0_addr = (!p->port_id) ?
+			ICM_CONFIG0_REG_0_ADDR : ICM_CONFIG0_REG_1_ADDR;
+		icm2_addr = (!p->port_id) ?
+			ICM_CONFIG2_REG_0_ADDR : ICM_CONFIG2_REG_1_ADDR;
+		debug_addr = DEBUG_REG_ADDR;
+	} else {
+		icm0_addr = XG_MCX_ICM_CONFIG0_REG_0_ADDR;
+		icm2_addr = XG_MCX_ICM_CONFIG2_REG_0_ADDR;
+		debug_addr = XG_DEBUG_REG_ADDR;
+	}
+
+	icm0 = xgene_enet_rd_mcx_csr(p, icm0_addr);
+	icm2 = xgene_enet_rd_mcx_csr(p, icm2_addr);
+	mc2 = xgene_enet_rd_mac(p, MAC_CONFIG_2_ADDR);
+	intf_ctl = xgene_enet_rd_mac(p, INTERFACE_CONTROL_ADDR);
+
+	switch (p->phy_speed) {
+	case SPEED_10:
+		ENET_INTERFACE_MODE2_SET(&mc2, 1);
+		intf_ctl &= ~(ENET_LHD_MODE | ENET_GHD_MODE);
+		CFG_MACMODE_SET(&icm0, 0);
+		CFG_WAITASYNCRD_SET(&icm2, 500);
+		break;
+	case SPEED_100:
+		ENET_INTERFACE_MODE2_SET(&mc2, 1);
+		intf_ctl &= ~ENET_GHD_MODE;
+		intf_ctl |= ENET_LHD_MODE;
+		CFG_MACMODE_SET(&icm0, 1);
+		CFG_WAITASYNCRD_SET(&icm2, 80);
+		break;
+	default:
+		ENET_INTERFACE_MODE2_SET(&mc2, 2);
+		intf_ctl &= ~ENET_LHD_MODE;
+		intf_ctl |= ENET_GHD_MODE;
+		CFG_MACMODE_SET(&icm0, 2);
+		CFG_WAITASYNCRD_SET(&icm2, 16);
+		value = xgene_enet_rd_csr(p, debug_addr);
+		value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
+		xgene_enet_wr_csr(p, debug_addr, value);
+		break;
+	}
+
+	mc2 |= FULL_DUPLEX2 | PAD_CRC;
+	xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, mc2);
+	xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, intf_ctl);
+	xgene_enet_wr_mcx_csr(p, icm0_addr, icm0);
+	xgene_enet_wr_mcx_csr(p, icm2_addr, icm2);
+}
+
 static void xgene_sgmac_init(struct xgene_enet_pdata *p)
 {
 	u32 data, loop = 10;
-	u32 offset = p->port_id * 4;
+	u32 offset = 0;
 	u32 enet_spare_cfg_reg, rsif_config_reg;
 	u32 cfg_bypass_reg, rx_dv_gate_reg;
 
 	xgene_sgmac_reset(p);
 
 	/* Enable auto-negotiation */
-	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x1000);
+	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2,
+			    0x8000);
+	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x9000);
 	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2, 0);
 
 	while (loop--) {
@@ -256,16 +343,14 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
 	if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS))
 		netdev_err(p->ndev, "Auto-negotiation failed\n");
 
-	data = xgene_enet_rd_mac(p, MAC_CONFIG_2_ADDR);
-	ENET_INTERFACE_MODE2_SET(&data, 2);
-	xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, data | FULL_DUPLEX2);
-	xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, ENET_GHD_MODE);
+	xgene_sgmac_set_speed(p);
 
 	if (p->enet_id == XGENE_ENET1) {
 		enet_spare_cfg_reg = ENET_SPARE_CFG_REG_ADDR;
 		rsif_config_reg = RSIF_CONFIG_REG_ADDR;
 		cfg_bypass_reg = CFG_BYPASS_ADDR;
 		rx_dv_gate_reg = SG_RX_DV_GATE_REG_0_ADDR;
+		offset = p->port_id * 4;
 	} else {
 		enet_spare_cfg_reg = XG_ENET_SPARE_CFG_REG_ADDR;
 		rsif_config_reg = XG_RSIF_CONFIG_REG_ADDR;
@@ -334,6 +419,9 @@ static int xgene_enet_reset(struct xgene_enet_pdata *p)
 	if (!xgene_ring_mgr_init(p))
 		return -ENODEV;
 
+	if (p->enet_id == XGENE_ENET2)
+		xgene_enet_wr_clkrst_csr(p, XGENET_CONFIG_REG_ADDR, SGMII_EN);
+
 	if (!IS_ERR(p->clk)) {
 		clk_prepare_enable(p->clk);
 		clk_disable_unprepare(p->clk);
@@ -386,10 +474,11 @@ static void xgene_enet_link_state(struct work_struct *work)
 	if (link) {
 		if (!netif_carrier_ok(ndev)) {
 			netif_carrier_on(ndev);
-			xgene_sgmac_init(p);
+			xgene_sgmac_set_speed(p);
 			xgene_sgmac_rx_enable(p);
 			xgene_sgmac_tx_enable(p);
-			netdev_info(ndev, "Link is Up - 1Gbps\n");
+			netdev_info(ndev, "Link is Up - %dMbps\n",
+				    p->phy_speed);
 		}
 		poll_interval = PHY_POLL_LINK_ON;
 	} else {
@@ -412,6 +501,7 @@ const struct xgene_mac_ops xgene_sgmac_ops = {
 	.tx_enable	= xgene_sgmac_tx_enable,
 	.rx_disable	= xgene_sgmac_rx_disable,
 	.tx_disable	= xgene_sgmac_tx_disable,
+	.set_speed	= xgene_sgmac_set_speed,
 	.set_mac_addr	= xgene_sgmac_set_mac_addr,
 	.link_state	= xgene_enet_link_state
 };
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
index 002df5a..3d0ba37 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
@@ -24,6 +24,7 @@
 #define PHY_ADDR(src)		(((src)<<8) & GENMASK(12, 8))
 #define REG_ADDR(src)		((src) & GENMASK(4, 0))
 #define PHY_CONTROL(src)	((src) & GENMASK(15, 0))
+#define LINK_SPEED(src)		(((src) & GENMASK(11, 10)) >> 10)
 #define INT_PHY_ADDR			0x1e
 #define SGMII_TBI_CONTROL_ADDR		0x44
 #define SGMII_CONTROL_ADDR		0x00
@@ -34,6 +35,13 @@
 #define LINK_UP				BIT(15)
 #define MPA_IDLE_WITH_QMI_EMPTY		BIT(12)
 #define SG_RX_DV_GATE_REG_0_ADDR	0x05fc
+#define SGMII_EN			0x1
+
+enum xgene_phy_speed {
+	PHY_SPEED_10,
+	PHY_SPEED_100,
+	PHY_SPEED_1000
+};
 
 extern const struct xgene_mac_ops xgene_sgmac_ops;
 extern const struct xgene_port_ops xgene_sgport_ops;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
index 0a2dca8..aba4c19 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
@@ -65,9 +65,13 @@
 #define XG_CFG_LINK_AGGR_RESUME_0_ADDR	0x0214
 #define XG_LINK_STATUS_ADDR		0x0228
 #define XG_TSIF_MSS_REG0_ADDR		0x02a4
+#define XG_DEBUG_REG_ADDR		0x0400
 #define XG_ENET_SPARE_CFG_REG_ADDR	0x040c
 #define XG_ENET_SPARE_CFG_REG_1_ADDR	0x0410
 #define XGENET_RX_DV_GATE_REG_0_ADDR	0x0804
+#define XG_MCX_ECM_CONFIG0_REG_0_ADDR	0x0070
+#define XG_MCX_ICM_CONFIG0_REG_0_ADDR	0x00e0
+#define XG_MCX_ICM_CONFIG2_REG_0_ADDR	0x00e8
 
 extern const struct xgene_mac_ops xgene_xgmac_ops;
 extern const struct xgene_port_ops xgene_xgport_ops;
-- 
1.9.1



From isubramanian at apm.com  Fri May 27 00:22:46 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 27 May 2016 00:22:46 -0700
Subject: [PATCH v1 4/6] dtb: xgene: Add MDIO node
In-Reply-To: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
References: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
Message-ID: <1464333768-26150-5-git-send-email-isubramanian@apm.com>

Added mdio node for mdio driver.  Also added phy-handle
reference to the ethernet nodes.  Removed unused mdio
subnode within ethernet node.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Fushen Chen <fchen at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 arch/arm64/boot/dts/apm/apm-merlin.dts     | 10 ++++++++++
 arch/arm64/boot/dts/apm/apm-mustang.dts    | 12 ++++++++++++
 arch/arm64/boot/dts/apm/apm-shadowcat.dtsi | 11 +++++++++++
 arch/arm64/boot/dts/apm/apm-storm.dtsi     | 20 ++++++++++----------
 4 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/boot/dts/apm/apm-merlin.dts b/arch/arm64/boot/dts/apm/apm-merlin.dts
index 387c6a8..7d47a0f 100644
--- a/arch/arm64/boot/dts/apm/apm-merlin.dts
+++ b/arch/arm64/boot/dts/apm/apm-merlin.dts
@@ -83,3 +83,13 @@
 		status = "ok";
 	};
 };
+
+&mdio {
+	sgenet0phy: phy at 3 {
+		reg = <0x0>;
+	};
+	sgenet1phy: phy at 2 {
+		reg = <0x2>;
+	};
+};
+
diff --git a/arch/arm64/boot/dts/apm/apm-mustang.dts b/arch/arm64/boot/dts/apm/apm-mustang.dts
index 44db32e..c4e2bc4 100644
--- a/arch/arm64/boot/dts/apm/apm-mustang.dts
+++ b/arch/arm64/boot/dts/apm/apm-mustang.dts
@@ -79,3 +79,15 @@
 &mmc0 {
 	status = "ok";
 };
+
+&mdio {
+	menetphy: phy at 3 {
+		reg = <0x3>;
+	};
+	sgenet0phy: phy at 4 {
+		reg = <0x4>;
+	};
+	sgenet1phy: phy at 5 {
+		reg = <0x5>;
+	};
+};
diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
index ba04877..8106957 100644
--- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
@@ -625,6 +625,15 @@
 			apm,irq-start = <8>;
 		};
 
+		mdio: mdio at 0x1f610000 {
+			compatible = "apm,xgene-mdio-sgmii";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x1f610000 0x0 0x100>,
+			      <0x0 0X1f61d000 0x0 0X100>;
+			clocks = <&xge0clk 0>;
+		};
+
 		sgenet0: ethernet at 1f610000 {
 			compatible = "apm,xgene2-sgenet";
 			status = "disabled";
@@ -637,6 +646,7 @@
 			clocks = <&xge0clk 0>;
 			local-mac-address = [00 01 73 00 00 01];
 			phy-connection-type = "sgmii";
+			phy-handle = <&sgenet0phy>;
 		};
 
 		xgenet1: ethernet at 1f620000 {
@@ -659,6 +669,7 @@
 			clocks = <&xge1clk 0>;
 			local-mac-address = [00 01 73 00 00 02];
 			phy-connection-type = "xgmii";
+			phy-handle = <&sgenet1phy>;
 		};
 
 		rng: rng at 10520000 {
diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi
index 5147d76..18f694ea 100644
--- a/arch/arm64/boot/dts/apm/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi
@@ -921,6 +921,14 @@
 			clocks = <&rtcclk 0>;
 		};
 
+		mdio: mdio at 0x17020000 {
+			compatible = "apm,xgene-mdio-rgmii";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x17020000 0x0 0xd100>;
+			clocks = <&menetclk 0>;
+		};
+
 		menet: ethernet at 17020000 {
 			compatible = "apm,xgene-enet";
 			status = "disabled";
@@ -935,16 +943,6 @@
 			local-mac-address = [00 00 00 00 00 00];
 			phy-connection-type = "rgmii";
 			phy-handle = <&menetphy>;
-			mdio {
-				compatible = "apm,xgene-mdio";
-				#address-cells = <1>;
-				#size-cells = <0>;
-				menetphy: menetphy at 3 {
-					compatible = "ethernet-phy-id001c.c915";
-					reg = <0x3>;
-				};
-
-			};
 		};
 
 		sgenet0: ethernet at 1f210000 {
@@ -960,6 +958,7 @@
 			clocks = <&sge0clk 0>;
 			local-mac-address = [00 00 00 00 00 00];
 			phy-connection-type = "sgmii";
+			phy-handle = <&sgenet0phy>;
 		};
 
 		sgenet1: ethernet at 1f210030 {
@@ -976,6 +975,7 @@
 			clocks = <&sge1clk 0>;
 			local-mac-address = [00 00 00 00 00 00];
 			phy-connection-type = "sgmii";
+			phy-handle = <&sgenet1phy>;
 		};
 
 		xgenet: ethernet at 1f610000 {
-- 
1.9.1



From isubramanian at apm.com  Fri May 27 00:22:44 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 27 May 2016 00:22:44 -0700
Subject: [PATCH v1 2/6] drivers: net: xgene: Backward compatibility with older
 firmware
In-Reply-To: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
References: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
Message-ID: <1464333768-26150-3-git-send-email-isubramanian@apm.com>

This patch looks for CONFIG_MDIO_XGENE and based on phy-handle DT/ACPI
fields, sets the mdio_driver flag.  The rest of the driver uses the
this flag for any MDIO management, in the case of backward compatibility.
Also, some code clean up done around mdio configuration/remove.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Fushen Chen <fchen at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    |  59 +++-----
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 166 +++++++++++++++-------
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |   2 +
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c |  13 +-
 4 files changed, 149 insertions(+), 91 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 6bc8360..38d6ee4 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -476,9 +476,13 @@ static void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
 static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata)
 {
 	struct device *dev = &pdata->pdev->dev;
+	struct clk *parent;
 
 	if (dev->of_node) {
-		struct clk *parent = clk_get_parent(pdata->clk);
+		if (IS_ERR(pdata->clk))
+			return;
+
+		parent = clk_get_parent(pdata->clk);
 
 		switch (pdata->phy_speed) {
 		case SPEED_10:
@@ -572,6 +576,9 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
 {
 	u32 value;
 
+	if (!pdata->mdio_driver)
+		xgene_gmac_reset(pdata);
+
 	xgene_gmac_set_speed(pdata);
 	xgene_gmac_set_mac_addr(pdata);
 
@@ -677,6 +684,14 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
 	if (!xgene_ring_mgr_init(pdata))
 		return -ENODEV;
 
+	if (!pdata->mdio_driver) {
+		if (!IS_ERR(pdata->clk)) {
+			clk_prepare_enable(pdata->clk);
+			clk_disable_unprepare(pdata->clk);
+			clk_prepare_enable(pdata->clk);
+			xgene_enet_ecc_init(pdata);
+		}
+	}
 	xgene_enet_config_ring_if_assoc(pdata);
 
 	return 0;
@@ -799,27 +814,9 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
 				  struct mii_bus *mdio)
 {
 	struct device *dev = &pdata->pdev->dev;
-	struct device_node *mdio_np = NULL;
-	struct device_node *child_np;
-	u32 phyid;
 
 	if (dev->of_node) {
-		for_each_child_of_node(dev->of_node, child_np) {
-			if (of_device_is_compatible(child_np,
-						    "apm,xgene-mdio")) {
-				mdio_np = child_np;
-				break;
-			}
-		}
-
-		if (!mdio_np) {
-			mdiobus_free(mdio);
-			return 0;
-		}
-
-		pdata->mdio_driver = false;
-
-		return of_mdiobus_register(mdio, mdio_np);
+		return of_mdiobus_register(mdio, pdata->mdio_np);
 	} else {
 #ifdef CONFIG_ACPI
 		struct phy_device *phy;
@@ -838,13 +835,7 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
 		if (ret)
 			return ret;
 
-		ret = device_property_read_u32(dev, "phy-channel", &phyid);
-		if (ret)
-			ret = device_property_read_u32(dev, "phy-addr", &phyid);
-		if (ret)
-			return -EINVAL;
-
-		phy = get_phy_device(mdio, phy_id, false);
+		phy = get_phy_device(mdio, pdata->phy_id, false);
 		if (IS_ERR(phy))
 			return -EIO;
 
@@ -857,6 +848,8 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
 		return ret;
 #endif
 	}
+
+	return 0;
 }
 
 int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
@@ -884,10 +877,6 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
 		if (mdio_bus->state == MDIOBUS_REGISTERED)
 			mdiobus_unregister(pdata->mdio_bus);
 		mdiobus_free(mdio_bus);
-		if (pdata->mdio_driver) {
-			ret = xgene_enet_phy_connect(ndev);
-			return 0;
-		}
 		return ret;
 	}
 	pdata->mdio_bus = mdio_bus;
@@ -910,11 +899,9 @@ void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
 	if (pdata->phy_dev)
 		phy_disconnect(pdata->phy_dev);
 
-	if (!pdata->mdio_driver) {
-		mdiobus_unregister(pdata->mdio_bus);
-		mdiobus_free(pdata->mdio_bus);
-		pdata->mdio_bus = NULL;
-	}
+	mdiobus_unregister(pdata->mdio_bus);
+	mdiobus_free(pdata->mdio_bus);
+	pdata->mdio_bus = NULL;
 }
 
 const struct xgene_mac_ops xgene_gmac_ops = {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index c698044..c31ea56 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1182,31 +1182,27 @@ static const struct net_device_ops xgene_ndev_ops = {
 
 #ifdef CONFIG_ACPI
 static void xgene_get_port_id_acpi(struct device *dev,
-				  struct xgene_enet_pdata *pdata)
+				   struct xgene_enet_pdata *pdata)
 {
 	acpi_status status;
 	u64 temp;
 
 	status = acpi_evaluate_integer(ACPI_HANDLE(dev), "_SUN", NULL, &temp);
-	if (ACPI_FAILURE(status)) {
+	if (ACPI_FAILURE(status))
 		pdata->port_id = 0;
-	} else {
+	else
 		pdata->port_id = temp;
-	}
-
-	return;
 }
 #endif
 
-static void xgene_get_port_id_dt(struct device *dev, struct xgene_enet_pdata *pdata)
+static void xgene_get_port_id_dt(struct device *dev,
+				 struct xgene_enet_pdata *pdata)
 {
 	u32 id = 0;
 
 	of_property_read_u32(dev->of_node, "port-id", &id);
 
 	pdata->port_id = id & BIT(0);
-
-	return;
 }
 
 static int xgene_get_tx_delay(struct xgene_enet_pdata *pdata)
@@ -1284,6 +1280,86 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata)
 	return 0;
 }
 
+static int xgene_enet_check_phy_handle(struct xgene_enet_pdata *pdata)
+{
+	struct device *dev = &pdata->pdev->dev;
+	int ret, phy_id, phy_mode = pdata->phy_mode;
+	struct device_node *mdio_np = NULL;
+	const char *ph;
+#ifdef CONFIG_ACPI
+	struct acpi_reference_args args;
+	struct fwnode_handle *fw_node;
+#endif
+
+	if (!IS_ENABLED(CONFIG_MDIO_XGENE))
+		return 0;
+
+	if (dev->of_node) {
+		ret = device_property_read_string(dev, "phy-handle", &ph);
+
+		if (phy_mode == PHY_INTERFACE_MODE_RGMII) {
+			if (ret) {
+				dev_err(dev, "Unable to get phy-handle\n");
+				return ret;
+			}
+
+			mdio_np = of_find_compatible_node(dev->of_node, NULL,
+							  "apm,xgene-mdio");
+			if (!mdio_np)
+				pdata->mdio_driver = true;
+			else
+				pdata->mdio_np = mdio_np;
+		} else {
+			if (!ret)
+				pdata->mdio_driver = true;
+		}
+	} else {
+#ifdef CONFIG_ACPI
+		fw_node = acpi_fwnode_handle(ACPI_COMPANION(dev));
+		ret = acpi_node_get_property_reference(fw_node, "mboxes", 0,
+						       &args);
+		if (!ACPI_FAILURE(ret)) {
+			pdata->mdio_driver = true;
+			pdata->phy_dev =  args.adev->driver_data;
+		} else {
+			ret = device_property_read_u32(dev, "phy-channel",
+						       &phy_id);
+			if (ret) {
+				ret = device_property_read_u32(dev, "phy-addr",
+							       &phy_id);
+			}
+
+			if (!ret)
+				pdata->phy_id = phy_id;
+		}
+#endif
+	}
+
+	return 0;
+}
+
+static int xgene_enet_get_clk(struct xgene_enet_pdata *pdata)
+{
+	struct device *dev = &pdata->pdev->dev;
+
+	if (!dev->of_node)
+		return 0;
+
+	pdata->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(pdata->clk)) {
+		if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+			dev_err(dev, "Unable to get clock\n");
+			return -ENODEV;
+		} else {
+			/* Firmware may have set up the clock already. */
+			dev_info(dev, "clocks have been setup already\n");
+			pdata->clk = NULL;
+		}
+	}
+
+	return 0;
+}
+
 static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
 {
 	struct platform_device *pdev;
@@ -1292,7 +1368,6 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
 	struct resource *res;
 	void __iomem *base_addr;
 	u32 offset;
-	const char *ph;
 	int ret = 0;
 
 	pdev = pdata->pdev;
@@ -1370,15 +1445,13 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
 	if (ret)
 		return ret;
 
-	ret = device_property_read_string(dev, "phy-handle", &ph);
-	if (!ret)
-		pdata->mdio_driver = true;
+	ret = xgene_enet_check_phy_handle(pdata);
+	if (ret)
+		return ret;
 
-	pdata->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(pdata->clk)) {
-		/* Firmware may have set up the clock already. */
-		dev_info(dev, "clocks have been setup already\n");
-	}
+	ret = xgene_enet_get_clk(pdata);
+	if (ret)
+		return ret;
 
 	if ((pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) &&
 	    (pdata->enet_id == XGENE_ENET1))
@@ -1434,8 +1507,6 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
 		}
 	}
 
-	dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
-	buf_pool = pdata->rx_ring[0]->buf_pool;
 	if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
 		/* Initialize and Enable  PreClassifier Tree */
 		enet_cle->max_nodes = 512;
@@ -1451,9 +1522,12 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
 			return ret;
 		}
 	} else {
+		dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
+		buf_pool = pdata->rx_ring[0]->buf_pool;
 		pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
 	}
 
+	pdata->phy_speed = SPEED_UNKNOWN;
 	pdata->mac_ops->init(pdata);
 
 	return ret;
@@ -1563,22 +1637,6 @@ static void xgene_enet_napi_add(struct xgene_enet_pdata *pdata)
 	}
 }
 
-static void xgene_enet_napi_del(struct xgene_enet_pdata *pdata)
-{
-	struct napi_struct *napi;
-	int i;
-
-	for (i = 0; i < pdata->rxq_cnt; i++) {
-		napi = &pdata->rx_ring[i]->napi;
-		netif_napi_del(napi);
-	}
-
-	for (i = 0; i < pdata->cq_cnt; i++) {
-		napi = &pdata->tx_ring[i]->cp_ring->napi;
-		netif_napi_del(napi);
-	}
-}
-
 static int xgene_enet_probe(struct platform_device *pdev)
 {
 	struct net_device *ndev;
@@ -1609,10 +1667,10 @@ static int xgene_enet_probe(struct platform_device *pdev)
 	of_id = of_match_device(xgene_enet_of_match, &pdev->dev);
 	if (of_id) {
 		pdata->enet_id = (enum xgene_enet_id)of_id->data;
-	}
-	else {
+	} else {
 #ifdef CONFIG_ACPI
 		const struct acpi_device_id *acpi_id;
+		enum xgene_enet_id enet_id;
 
 		acpi_id = acpi_match_device(xgene_enet_acpi_match, &pdev->dev);
 		if (acpi_id) {
@@ -1621,6 +1679,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
 		}
 #endif
 	}
+
 	if (!pdata->enet_id) {
 		free_netdev(ndev);
 		return -ENODEV;
@@ -1655,23 +1714,25 @@ static int xgene_enet_probe(struct platform_device *pdev)
 		goto err_netdev;
 
 	link_state = pdata->mac_ops->link_state;
-	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
-		ret = xgene_enet_mdio_config(pdata);
-		if (ret)
-			goto err_netdev;
-	} else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
+	ret = 0;
+	if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
+		INIT_DELAYED_WORK(&pdata->link_work, link_state);
+	} else {
 		if (pdata->mdio_driver)
 			ret = xgene_enet_phy_connect(ndev);
+		else if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
+			ret = xgene_enet_mdio_config(pdata);
 		else
 			INIT_DELAYED_WORK(&pdata->link_work, link_state);
-	} else {
-		INIT_DELAYED_WORK(&pdata->link_work, link_state);
 	}
+	if (ret)
+		goto err;
 
 	xgene_enet_napi_add(pdata);
 	return 0;
 err_netdev:
-	unregister_netdev(ndev);
+	if (ndev->reg_state == NETREG_REGISTERED)
+		unregister_netdev(ndev);
 err:
 	free_netdev(ndev);
 	return ret;
@@ -1690,11 +1751,16 @@ static int xgene_enet_remove(struct platform_device *pdev)
 	mac_ops->rx_disable(pdata);
 	mac_ops->tx_disable(pdata);
 
-	xgene_enet_napi_del(pdata);
-	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
-		xgene_enet_mdio_remove(pdata);
-	else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII)
+	rtnl_lock();
+	if (netif_running(ndev))
+		dev_close(ndev);
+	rtnl_unlock();
+
+	if (pdata->mdio_driver)
 		xgene_enet_phy_disconnect(pdata);
+	else if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
+		xgene_enet_mdio_remove(pdata);
+
 	unregister_netdev(ndev);
 	xgene_enet_delete_desc_rings(pdata);
 	pdata->port_ops->shutdown(pdata);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 0fe1a96..c2804c2 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -212,6 +212,8 @@ struct xgene_enet_pdata {
 	u32 mss;
 	u8 tx_delay;
 	u8 rx_delay;
+	struct device_node *mdio_np;
+	int phy_id;
 	bool mdio_driver;
 };
 
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index 6d53de4..c078cd6 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -257,9 +257,7 @@ static void xgene_sgmac_set_speed(struct xgene_enet_pdata *p)
 	u32 mc2, value;
 
 	if (p->phy_speed != SPEED_UNKNOWN) {
-		value = xgene_mii_phy_read(p, INT_PHY_ADDR,
-					   SGMII_BASE_PAGE_ABILITY_ADDR >> 2);
-		if (!(value & LINK_UP)) {
+		if (!xgene_enet_link_status(p)) {
 			xgene_mii_phy_write(p, INT_PHY_ADDR,
 					    SGMII_TBI_CONTROL_ADDR >> 2,
 					    0x8000);
@@ -325,7 +323,8 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
 	u32 enet_spare_cfg_reg, rsif_config_reg;
 	u32 cfg_bypass_reg, rx_dv_gate_reg;
 
-	xgene_sgmac_reset(p);
+	if (!(p->enet_id == XGENE_ENET2 && p->mdio_driver))
+		xgene_sgmac_reset(p);
 
 	/* Enable auto-negotiation */
 	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2,
@@ -416,6 +415,8 @@ static void xgene_sgmac_tx_disable(struct xgene_enet_pdata *p)
 
 static int xgene_enet_reset(struct xgene_enet_pdata *p)
 {
+	int ret;
+
 	if (!xgene_ring_mgr_init(p))
 		return -ENODEV;
 
@@ -428,7 +429,9 @@ static int xgene_enet_reset(struct xgene_enet_pdata *p)
 		clk_prepare_enable(p->clk);
 	}
 
-	xgene_enet_ecc_init(p);
+	ret = xgene_enet_ecc_init(p);
+	if (ret)
+		return ret;
 	xgene_enet_config_ring_if_assoc(p);
 
 	return 0;
-- 
1.9.1



From isubramanian at apm.com  Fri May 27 00:22:47 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 27 May 2016 00:22:47 -0700
Subject: [PATCH v1 5/6] dtb: xgene: Remove clock nodes
In-Reply-To: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
References: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
Message-ID: <1464333768-26150-6-git-send-email-isubramanian@apm.com>

Since the MDIO will be responsible for clock reset, removing the clock
nodes from shadowcat xge0 and storm sgenet1.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Fushen Chen <fchen at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 arch/arm64/boot/dts/apm/apm-shadowcat.dtsi | 12 ------------
 arch/arm64/boot/dts/apm/apm-storm.dtsi     | 18 ++++--------------
 2 files changed, 4 insertions(+), 26 deletions(-)

diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
index 8106957..f27563d 100644
--- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
@@ -299,17 +299,6 @@
 				clock-output-names = "pcie1clk";
 			};
 
-			xge0clk: xge0clk at 1f61c000 {
-				compatible = "apm,xgene-device-clock";
-				#clock-cells = <1>;
-				clocks = <&socplldiv2 0>;
-				reg = <0x0 0x1f61c000 0x0 0x1000>;
-				reg-names = "csr-reg";
-				enable-mask = <0x3>;
-				csr-mask = <0x3>;
-				clock-output-names = "xge0clk";
-			};
-
 			xge1clk: xge1clk at 1f62c000 {
 				compatible = "apm,xgene-device-clock";
 				#clock-cells = <1>;
@@ -643,7 +632,6 @@
 			interrupts = <0 96 4>,
 				     <0 97 4>;
 			dma-coherent;
-			clocks = <&xge0clk 0>;
 			local-mac-address = [00 01 73 00 00 01];
 			phy-connection-type = "sgmii";
 			phy-handle = <&sgenet0phy>;
diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi
index 18f694ea..f631fe4 100644
--- a/arch/arm64/boot/dts/apm/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi
@@ -237,20 +237,11 @@
 				clocks = <&socplldiv2 0>;
 				reg = <0x0 0x1f21c000 0x0 0x1000>;
 				reg-names = "csr-reg";
-				csr-mask = <0x3>;
+				csr-mask = <0xa>;
+				enable-mask = <0xf>;
 				clock-output-names = "sge0clk";
 			};
 
-			sge1clk: sge1clk at 1f21c000 {
-				compatible = "apm,xgene-device-clock";
-				#clock-cells = <1>;
-				clocks = <&socplldiv2 0>;
-				reg = <0x0 0x1f21c000 0x0 0x1000>;
-				reg-names = "csr-reg";
-				csr-mask = <0xc>;
-				clock-output-names = "sge1clk";
-			};
-
 			xge0clk: xge0clk at 1f61c000 {
 				compatible = "apm,xgene-device-clock";
 				#clock-cells = <1>;
@@ -938,9 +929,9 @@
 			reg-names = "enet_csr", "ring_csr", "ring_cmd";
 			interrupts = <0x0 0x3c 0x4>;
 			dma-coherent;
-			clocks = <&menetclk 0>;
 			/* mac address will be overwritten by the bootloader */
 			local-mac-address = [00 00 00 00 00 00];
+			clocks = <&menetclk 0>;
 			phy-connection-type = "rgmii";
 			phy-handle = <&menetphy>;
 		};
@@ -955,8 +946,8 @@
 			interrupts = <0x0 0xA0 0x4>,
 				     <0x0 0xA1 0x4>;
 			dma-coherent;
-			clocks = <&sge0clk 0>;
 			local-mac-address = [00 00 00 00 00 00];
+			clocks = <&sge0clk 0>;
 			phy-connection-type = "sgmii";
 			phy-handle = <&sgenet0phy>;
 		};
@@ -972,7 +963,6 @@
 				     <0x0 0xAD 0x4>;
 			port-id = <1>;
 			dma-coherent;
-			clocks = <&sge1clk 0>;
 			local-mac-address = [00 00 00 00 00 00];
 			phy-connection-type = "sgmii";
 			phy-handle = <&sgenet1phy>;
-- 
1.9.1



From isubramanian at apm.com  Fri May 27 00:22:45 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 27 May 2016 00:22:45 -0700
Subject: [PATCH v1 3/6] drivers: net: phy: Add MDIO driver
In-Reply-To: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
References: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
Message-ID: <1464333768-26150-4-git-send-email-isubramanian@apm.com>

Currently, SGMII based 1G rely on the hardware registers for link state
and sometimes it's not reliable.  To get most accurate link state, this
interface has to use the MDIO bus to poll the PHY.

In X-Gene SoC, MDIO bus is shared across RGMII and SGMII based 1G
interfaces, so adding this driver to manage MDIO bus.  This driver
registers the mdio bus and registers the PHYs connected to it.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Fushen Chen <fchen at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/Kconfig |   1 +
 drivers/net/phy/Kconfig                |   7 +
 drivers/net/phy/Makefile               |   1 +
 drivers/net/phy/mdio-xgene.c           | 531 +++++++++++++++++++++++++++++++++
 drivers/net/phy/mdio-xgene.h           | 140 +++++++++
 5 files changed, 680 insertions(+)
 create mode 100644 drivers/net/phy/mdio-xgene.c
 create mode 100644 drivers/net/phy/mdio-xgene.h

diff --git a/drivers/net/ethernet/apm/xgene/Kconfig b/drivers/net/ethernet/apm/xgene/Kconfig
index 19e38af..300e3b5 100644
--- a/drivers/net/ethernet/apm/xgene/Kconfig
+++ b/drivers/net/ethernet/apm/xgene/Kconfig
@@ -3,6 +3,7 @@ config NET_XGENE
 	depends on HAS_DMA
 	depends on ARCH_XGENE || COMPILE_TEST
 	select PHYLIB
+	select MDIO_XGENE
 	help
 	  This is the Ethernet driver for the on-chip ethernet interface on the
 	  APM X-Gene SoC.
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 6dad9a9..193f418 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -271,6 +271,13 @@ config MDIO_BCM_IPROC
 	  This module provides a driver for the MDIO busses found in the
 	  Broadcom iProc SoC's.
 
+config MDIO_XGENE
+       tristate "APM X-Gene SoC MDIO bus controller"
+       help
+         This module provides a driver for the MDIO busses found in the
+         APM X-Gene SoC's.
+
+
 endif # PHYLIB
 
 config MICREL_KS8995MA
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index fcdbb92..9cbd2af 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -44,3 +44,4 @@ obj-$(CONFIG_MDIO_MOXART)	+= mdio-moxart.o
 obj-$(CONFIG_MDIO_BCM_UNIMAC)	+= mdio-bcm-unimac.o
 obj-$(CONFIG_MICROCHIP_PHY)	+= microchip.o
 obj-$(CONFIG_MDIO_BCM_IPROC)	+= mdio-bcm-iproc.o
+obj-$(CONFIG_MDIO_XGENE)	+= mdio-xgene.o
diff --git a/drivers/net/phy/mdio-xgene.c b/drivers/net/phy/mdio-xgene.c
new file mode 100644
index 0000000..bd07fd9
--- /dev/null
+++ b/drivers/net/phy/mdio-xgene.c
@@ -0,0 +1,531 @@
+/* Applied Micro X-Gene SoC MDIO Driver
+ *
+ * Copyright (c) 2016, Applied Micro Circuits Corporation
+ * Author: Iyappan Subramanian <isubramanian at apm.com>
+ *
+ * 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.
+ *
+ * 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/acpi.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/efi.h>
+#include <linux/if_vlan.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/of_mdio.h>
+#include <linux/prefetch.h>
+#include <linux/phy.h>
+#include <net/ip.h>
+#include "mdio-xgene.h"
+
+static bool xgene_mdio_status;
+
+static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
+				   void __iomem *cmd, void __iomem *cmd_done,
+				   u32 rd_addr, u32 *rd_data)
+{
+	u32 done;
+	u8 wait = 10;
+
+	iowrite32(rd_addr, addr);
+	iowrite32(XGENE_ENET_RD_CMD, cmd);
+
+	/* wait for read command to complete */
+	while (!(done = ioread32(cmd_done)) && wait--)
+		udelay(1);
+
+	if (!done)
+		return false;
+
+	*rd_data = ioread32(rd);
+	iowrite32(0, cmd);
+
+	return true;
+}
+
+static void xgene_enet_rd_mcx_mac(struct xgene_mdio_pdata *pdata,
+				  u32 rd_addr, u32 *rd_data)
+{
+	void __iomem *addr, *rd, *cmd, *cmd_done;
+
+	addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET;
+	rd = pdata->mac_csr_addr + MAC_READ_REG_OFFSET;
+	cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET;
+	cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+	if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
+		dev_err(pdata->dev, "MCX mac read failed, addr: 0x%04x\n",
+			rd_addr);
+}
+
+static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
+				   void __iomem *cmd, void __iomem *cmd_done,
+				   u32 wr_addr, u32 wr_data)
+{
+	u32 done;
+	u8 wait = 10;
+
+	iowrite32(wr_addr, addr);
+	iowrite32(wr_data, wr);
+	iowrite32(XGENE_ENET_WR_CMD, cmd);
+
+	/* wait for write command to complete */
+	while (!(done = ioread32(cmd_done)) && wait--)
+		udelay(1);
+
+	if (!done)
+		return false;
+
+	iowrite32(0, cmd);
+
+	return true;
+}
+
+static void xgene_enet_wr_mcx_mac(struct xgene_mdio_pdata *pdata,
+				  u32 wr_addr, u32 wr_data)
+{
+	void __iomem *addr, *wr, *cmd, *cmd_done;
+
+	addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET;
+	wr = pdata->mac_csr_addr + MAC_WRITE_REG_OFFSET;
+	cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET;
+	cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+	if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
+		dev_err(pdata->dev, "MCX mac write failed, addr: 0x%04x\n",
+			wr_addr);
+}
+
+static int xgene_mii_phy_read(struct xgene_mdio_pdata *pdata,
+			      u8 phy_id, u32 reg)
+{
+	u32 data, done;
+	u8 wait = 10;
+
+	data = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, data);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
+	do {
+		usleep_range(5, 10);
+		xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done);
+	} while ((done & BUSY_MASK) && wait--);
+
+	if (done & BUSY_MASK) {
+		dev_err(pdata->dev, "MII_MGMT read failed\n");
+		return -EBUSY;
+	}
+
+	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_STATUS_ADDR, &data);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, 0);
+
+	return data;
+}
+
+static int xgene_mii_phy_write(struct xgene_mdio_pdata *pdata, int phy_id,
+			       u32 reg, u16 data)
+{
+	u32 val, done;
+	u8 wait = 10;
+
+	val = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, val);
+
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONTROL_ADDR, data);
+	do {
+		usleep_range(5, 10);
+		xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done);
+	} while ((done & BUSY_MASK) && wait--);
+
+	if (done & BUSY_MASK) {
+		dev_err(pdata->dev, "MII_MGMT write failed\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int xgene_mdio_rgmii_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	struct xgene_mdio_pdata *pdata = bus->priv;
+	u32 val;
+
+	val = xgene_mii_phy_read(pdata, mii_id, regnum);
+	dev_dbg(pdata->dev, "MDIO read: bus=%d reg=%d val=0x%x\n",
+		mii_id, regnum, val);
+
+	return val;
+}
+
+static int xgene_mdio_rgmii_write(struct mii_bus *bus, int mii_id, int regnum,
+				  u16 val)
+{
+	struct xgene_mdio_pdata *pdata = bus->priv;
+
+	dev_dbg(pdata->dev, "MDIO write: bus=%d reg=%d val=0x%x\n",
+		mii_id, regnum, val);
+
+	return xgene_mii_phy_write(pdata, mii_id, regnum, val);
+}
+
+static u32 xgene_menet_rd_diag_csr(struct xgene_mdio_pdata *pdata,
+				   u32 offset)
+{
+	return ioread32(pdata->diag_csr_addr + offset);
+}
+
+static void xgene_menet_wr_diag_csr(struct xgene_mdio_pdata *pdata,
+				    u32 offset, u32 val)
+{
+	iowrite32(val, pdata->diag_csr_addr + offset);
+}
+
+static int xgene_enet_ecc_init(struct xgene_mdio_pdata *pdata)
+{
+	u32 data;
+	u8 wait = 10;
+
+	xgene_menet_wr_diag_csr(pdata, MENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0);
+	do {
+		usleep_range(100, 110);
+		data = xgene_menet_rd_diag_csr(pdata, MENET_BLOCK_MEM_RDY_ADDR);
+	} while ((data != 0xffffffff) && wait--);
+
+	if (data != 0xffffffff) {
+		dev_err(pdata->dev, "Failed to release memory from shutdown\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void xgene_gmac_reset(struct xgene_mdio_pdata *pdata)
+{
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET);
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0);
+}
+
+static int xgene_mdio_reset(struct xgene_mdio_pdata *pdata)
+{
+	int ret;
+
+	if (pdata->mdio_id == XGENE_MDIO_RGMII) {
+		if (pdata->dev->of_node) {
+			clk_prepare_enable(pdata->clk);
+			clk_disable_unprepare(pdata->clk);
+			clk_prepare_enable(pdata->clk);
+		} else {
+#ifdef CONFIG_ACPI
+			acpi_evaluate_object(ACPI_HANDLE(pdata->dev),
+					     "_RST", NULL, NULL);
+#endif
+		}
+	} else {
+#ifdef CONFIG_ACPI
+		acpi_evaluate_object(ACPI_HANDLE(pdata->dev),
+				     "_RST", NULL, NULL);
+#endif
+	}
+
+	ret = xgene_enet_ecc_init(pdata);
+	if (ret)
+		return ret;
+	xgene_gmac_reset(pdata);
+
+	return 0;
+}
+
+static void xgene_enet_rd_mdio_csr(struct xgene_mdio_pdata  *pdata,
+				   u32 offset, u32 *val)
+{
+	void __iomem *addr = pdata->mdio_csr_addr  + offset;
+
+	*val = ioread32(addr);
+}
+
+static void xgene_enet_wr_mdio_csr(struct xgene_mdio_pdata *pdata,
+				   u32 offset, u32 val)
+{
+	void __iomem *addr = pdata->mdio_csr_addr  + offset;
+
+	iowrite32(val, addr);
+}
+
+static int xgene_xfimii_phy_write(struct xgene_mdio_pdata *pdata, int phy_id,
+				  u32 reg, u16 data)
+{
+	int timeout = 100;
+	u32 status, val;
+
+	val = SET_VAL(HSTPHYADX, phy_id) | SET_VAL(HSTREGADX, reg) |
+	      SET_VAL(HSTMIIMWRDAT, data);
+	xgene_enet_wr_mdio_csr(pdata, MIIM_FIELD_ADDR, data);
+
+	val = HSTLDCMD | SET_VAL(HSTMIIMCMD, MIIM_CMD_LEGACY_WRITE);
+	xgene_enet_wr_mdio_csr(pdata, MIIM_COMMAND_ADDR, val);
+
+	do {
+		usleep_range(5, 10);
+		xgene_enet_rd_mdio_csr(pdata, MIIM_INDICATOR_ADDR, &status);
+	} while ((status & BUSY_MASK) && timeout--);
+
+	xgene_enet_wr_mdio_csr(pdata, MIIM_COMMAND_ADDR, 0);
+	return 0;
+}
+
+static int xgene_xfimii_phy_read(struct xgene_mdio_pdata *pdata,
+				 u8 phy_id, u32 reg)
+{
+	u32 data, status, val;
+	int timeout = 100;
+
+	val = SET_VAL(HSTPHYADX, phy_id) | SET_VAL(HSTREGADX, reg);
+	xgene_enet_wr_mdio_csr(pdata, MIIM_FIELD_ADDR, val);
+
+	val = HSTLDCMD | SET_VAL(HSTMIIMCMD, MIIM_CMD_LEGACY_READ);
+	xgene_enet_wr_mdio_csr(pdata, MIIM_COMMAND_ADDR, val);
+
+	do {
+		usleep_range(5, 10);
+		xgene_enet_rd_mdio_csr(pdata, MIIM_INDICATOR_ADDR, &status);
+	} while ((status & BUSY_MASK) && timeout--);
+
+	if (status & BUSY_MASK) {
+		dev_err(pdata->dev, "XGENET_MII_MGMT write failed\n");
+		return -EBUSY;
+	}
+	xgene_enet_rd_mdio_csr(pdata, MIIMRD_FIELD_ADDR, &data);
+	xgene_enet_wr_mdio_csr(pdata, MIIM_COMMAND_ADDR, 0);
+
+	return data;
+}
+
+static int xgene_xfi_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	struct xgene_mdio_pdata  *pdata = bus->priv;
+	u32 val;
+
+	dev_dbg(pdata->dev, "MDIO read: bus=%d reg=%d val=0x%x\n",
+		mii_id, regnum, val);
+	val = xgene_xfimii_phy_read(pdata, mii_id, regnum);
+
+	return val;
+}
+
+static int xgene_xfi_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+				u16 val)
+{
+	struct xgene_mdio_pdata *pdata = bus->priv;
+
+	dev_dbg(pdata->dev, "MDIO write: bus=%d reg=%d val=0x%x\n",
+		mii_id, regnum, val);
+
+	return xgene_xfimii_phy_write(pdata, mii_id, regnum, val);
+}
+
+#ifdef CONFIG_ACPI
+static acpi_status acpi_register_phy(acpi_handle handle, u32 lvl,
+				     void *context, void **ret)
+{
+	struct mii_bus *mdio = context;
+	struct acpi_device *adev;
+	struct phy_device *phy_dev;
+	const union acpi_object *obj;
+	u32 phy_addr;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
+
+	if (acpi_dev_get_property(adev, "phy-channel", ACPI_TYPE_INTEGER, &obj))
+		return AE_OK;
+	phy_addr = obj->integer.value;
+
+	phy_dev = get_phy_device(mdio, phy_addr, false);
+	adev->driver_data = phy_dev;
+	if (!phy_dev || IS_ERR(phy_dev))
+		return AE_OK;
+
+	if (phy_device_register(phy_dev))
+		phy_device_free(phy_dev);
+
+	return AE_OK;
+}
+#endif
+
+bool xgene_mdio_probe_successful(void)
+{
+	return xgene_mdio_status;
+}
+EXPORT_SYMBOL(xgene_mdio_probe_successful);
+
+static int xgene_mdio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mii_bus *mdio_bus;
+	const struct of_device_id *of_id;
+	struct resource *res;
+	struct xgene_mdio_pdata *pdata;
+	void __iomem *csr_addr;
+	int mdio_id = 0, ret = 0;
+
+	of_id = of_match_device(xgene_mdio_of_match, &pdev->dev);
+	if (of_id) {
+		mdio_id = (enum xgene_mdio_id)of_id->data;
+	} else {
+#ifdef CONFIG_ACPI
+		const struct acpi_device_id *acpi_id;
+
+		acpi_id = acpi_match_device(xgene_mdio_acpi_match, &pdev->dev);
+		if (acpi_id)
+			mdio_id = (enum xgene_mdio_id)acpi_id->driver_data;
+#endif
+	}
+
+	if (!mdio_id)
+		return -ENODEV;
+
+	pdata = devm_kzalloc(dev, sizeof(struct xgene_mdio_pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+	pdata->mdio_id = mdio_id;
+	pdata->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "Resource mac_ind_csr not defined\n");
+		return -ENODEV;
+	}
+
+	csr_addr = devm_ioremap(dev, res->start, resource_size(res));
+	if (!csr_addr) {
+		dev_err(dev, "Unable to retrieve mac CSR region\n");
+		return -ENOMEM;
+	}
+	pdata->mac_csr_addr = csr_addr;
+	pdata->mdio_csr_addr = csr_addr + BLOCK_XG_MDIO_CSR_OFFSET;
+	pdata->diag_csr_addr = csr_addr + BLOCK_DIAG_CSR_OFFSET;
+
+	if (dev->of_node) {
+		pdata->clk = devm_clk_get(dev, NULL);
+		if (IS_ERR(pdata->clk)) {
+			dev_err(dev, "Unable to retrieve clk\n");
+			return -ENODEV;
+		}
+	}
+
+	ret = xgene_mdio_reset(pdata);
+	if (ret)
+		return ret;
+
+	mdio_bus = mdiobus_alloc();
+	if (!mdio_bus)
+		return -ENOMEM;
+
+	mdio_bus->name = "APM X-Gene MDIO bus";
+	snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%d", "xgene-mii",
+		 mdio_id);
+
+	if (mdio_id == XGENE_MDIO_RGMII) {
+		mdio_bus->read = xgene_mdio_rgmii_read;
+		mdio_bus->write = xgene_mdio_rgmii_write;
+	} else {
+		mdio_bus->read = xgene_xfi_mdio_read;
+		mdio_bus->write = xgene_xfi_mdio_write;
+	}
+
+	mdio_bus->priv = pdata;
+	mdio_bus->parent = dev;
+	platform_set_drvdata(pdev, mdio_bus);
+
+	if (dev->of_node) {
+		ret = of_mdiobus_register(mdio_bus, dev->of_node);
+	} else {
+#ifdef CONFIG_ACPI
+		/* Mask out all PHYs from auto probing. */
+		mdio_bus->phy_mask = ~0;
+		ret = mdiobus_register(mdio_bus);
+		if (ret)
+			goto out;
+
+		acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_HANDLE(dev), 1,
+				    acpi_register_phy, NULL, mdio_bus, NULL);
+#endif
+	}
+
+	if (ret)
+		goto out;
+
+	xgene_mdio_status = true;
+
+	return 0;
+out:
+	if (mdio_bus->state == MDIOBUS_REGISTERED)
+		mdiobus_unregister(mdio_bus);
+	mdiobus_free(mdio_bus);
+
+	return ret;
+}
+
+static int xgene_mdio_remove(struct platform_device *pdev)
+{
+	struct mii_bus *mdio_bus = platform_get_drvdata(pdev);
+
+	mdiobus_unregister(mdio_bus);
+	mdiobus_free(mdio_bus);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id xgene_mdio_of_match[] = {
+	{
+		.compatible = "apm,xgene-mdio-rgmii",
+		.data = (void *)XGENE_MDIO_RGMII
+	},
+	{
+		.compatible = "apm,xgene-mdio-xfi",
+		.data = (void *)XGENE_MDIO_XFI},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, xgene_mdio_of_match);
+#endif
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id xgene_mdio_acpi_match[] = {
+	{ "APMC0D65", XGENE_MDIO_RGMII },
+	{ "APMC0D66", XGENE_MDIO_XFI },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(acpi, xgene_mdio_acpi_match);
+#endif
+
+static struct platform_driver xgene_mdio_driver = {
+	.driver = {
+		.name = "xgene-mdio",
+		.of_match_table = of_match_ptr(xgene_mdio_of_match),
+		.acpi_match_table = ACPI_PTR(xgene_mdio_acpi_match),
+	},
+	.probe = xgene_mdio_probe,
+	.remove = xgene_mdio_remove,
+};
+
+module_platform_driver(xgene_mdio_driver);
+
+MODULE_DESCRIPTION("APM X-Gene SoC MDIO driver");
+MODULE_AUTHOR("Iyappan Subramanian <isubramanian at apm.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/mdio-xgene.h b/drivers/net/phy/mdio-xgene.h
new file mode 100644
index 0000000..08b4323
--- /dev/null
+++ b/drivers/net/phy/mdio-xgene.h
@@ -0,0 +1,140 @@
+/* Applied Micro X-Gene SoC MDIO Driver
+ *
+ * Copyright (c) 2016, Applied Micro Circuits Corporation
+ * Author: Iyappan Subramanian <isubramanian at apm.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MDIO_XGENE_H__
+#define __MDIO_XGENE_H__
+
+#define BLOCK_XG_MDIO_CSR_OFFSET	0x5000
+#define BLOCK_DIAG_CSR_OFFSET		0xd000
+#define XGENET_CONFIG_REG_ADDR		0x20
+
+#define MAC_ADDR_REG_OFFSET		0x00
+#define MAC_COMMAND_REG_OFFSET		0x04
+#define MAC_WRITE_REG_OFFSET		0x08
+#define MAC_READ_REG_OFFSET		0x0c
+#define MAC_COMMAND_DONE_REG_OFFSET	0x10
+
+#define CLKEN_OFFSET			0x08
+#define SRST_OFFSET			0x00
+
+#define MENET_CFG_MEM_RAM_SHUTDOWN_ADDR	0x70
+#define MENET_BLOCK_MEM_RDY_ADDR	0x74
+
+#define MAC_CONFIG_1_ADDR		0x00
+#define MII_MGMT_COMMAND_ADDR		0x24
+#define MII_MGMT_ADDRESS_ADDR		0x28
+#define MII_MGMT_CONTROL_ADDR		0x2c
+#define MII_MGMT_STATUS_ADDR		0x30
+#define MII_MGMT_INDICATORS_ADDR	0x34
+#define SOFT_RESET			BIT(31)
+
+#define MII_MGMT_CONFIG_ADDR            0x20
+#define MII_MGMT_COMMAND_ADDR           0x24
+#define MII_MGMT_ADDRESS_ADDR           0x28
+#define MII_MGMT_CONTROL_ADDR           0x2c
+#define MII_MGMT_STATUS_ADDR            0x30
+#define MII_MGMT_INDICATORS_ADDR        0x34
+
+#define MIIM_COMMAND_ADDR               0x20
+#define MIIM_FIELD_ADDR                 0x24
+#define MIIM_CONFIGURATION_ADDR         0x28
+#define MIIM_LINKFAILVECTOR_ADDR        0x2c
+#define MIIM_INDICATOR_ADDR             0x30
+#define MIIMRD_FIELD_ADDR               0x34
+
+#define MDIO_CSR_OFFSET			0x5000
+
+#define REG_ADDR_POS			0
+#define REG_ADDR_LEN			5
+#define PHY_ADDR_POS			8
+#define PHY_ADDR_LEN			5
+
+#define HSTMIIMWRDAT_POS		0
+#define HSTMIIMWRDAT_LEN		16
+#define HSTPHYADX_POS			23
+#define HSTPHYADX_LEN			5
+#define HSTREGADX_POS			18
+#define HSTREGADX_LEN			5
+#define HSTLDCMD			BIT(3)
+#define HSTMIIMCMD_POS			0
+#define HSTMIIMCMD_LEN			3
+
+#define BUSY_MASK			BIT(0)
+#define READ_CYCLE_MASK			BIT(0)
+
+enum xgene_enet_cmd {
+	XGENE_ENET_WR_CMD = BIT(31),
+	XGENE_ENET_RD_CMD = BIT(30)
+};
+
+enum {
+	MIIM_CMD_IDLE,
+	MIIM_CMD_LEGACY_WRITE,
+	MIIM_CMD_LEGACY_READ,
+};
+
+enum xgene_mdio_id {
+	XGENE_MDIO_RGMII = 1,
+	XGENE_MDIO_XFI
+};
+
+struct xgene_mdio_pdata {
+	struct clk *clk;
+	struct device *dev;
+	void __iomem *mac_csr_addr;
+	void __iomem *diag_csr_addr;
+	void __iomem *mdio_csr_addr;
+	int mdio_id;
+};
+
+/* Set the specified value into a bit-field defined by its starting position
+ * and length within a single u64.
+ */
+static inline u64 xgene_enet_set_field_value(int pos, int len, u64 val)
+{
+	return (val & ((1ULL << len) - 1)) << pos;
+}
+
+#define SET_VAL(field, val) \
+		xgene_enet_set_field_value(field ## _POS, field ## _LEN, val)
+
+#define SET_BIT(field) \
+		xgene_enet_set_field_value(field ## _POS, 1, 1)
+
+/* Get the value from a bit-field defined by its starting position
+ * and length within the specified u64.
+ */
+static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src)
+{
+	return (src >> pos) & ((1ULL << len) - 1);
+}
+
+#define GET_VAL(field, src) \
+		xgene_enet_get_field_value(field ## _POS, field ## _LEN, src)
+
+#define GET_BIT(field, src) \
+		xgene_enet_get_field_value(field ## _POS, 1, src)
+
+static const struct of_device_id xgene_mdio_of_match[];
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id xgene_mdio_acpi_match[];
+#endif
+bool xgene_mdio_probe_successful(void);
+
+#endif  /* __MDIO_XGENE_H__ */
-- 
1.9.1



From isubramanian at apm.com  Fri May 27 00:22:48 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Fri, 27 May 2016 00:22:48 -0700
Subject: [PATCH v1 6/6] drivers: net: xgene: Fix module load/unload crash
In-Reply-To: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
References: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
Message-ID: <1464333768-26150-7-git-send-email-isubramanian@apm.com>

When the driver is configured as kernel module and when it gets unloaded
and reloaded, kernel crash was observed, due to incomplete hardware
cleanup.  This patch addresses this issue with the following changes,

- Reordered mac enable and disable
- Added hardware prefetch buffer cleanup
- Added Tx completion ring free
- Fixed delete bufpool
- Moved down delete_desc_rings after ring cleanup

- Moved regsiter_netdev call after hardware is ready
- deleted napi_del function call, since it's called by free_netdev
- Calling netif_tx_start_queues and netif_tx_stop_queues
- correcting setting irq_name before calling request_irq.
- Calling dev_close() within remove
- Added shutdown callback
- Changed to use dmam_ APIs

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Fushen Chen <fchen at apm.com>
Tested-by: Toan Le <toanle at apm.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    |  71 +++++++-
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    |  14 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 199 +++++++++++++---------
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |  32 +---
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c |  90 ++++++++--
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c |  66 ++++++-
 6 files changed, 329 insertions(+), 143 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 38d6ee4..8e3827f 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -684,21 +684,75 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
 	if (!xgene_ring_mgr_init(pdata))
 		return -ENODEV;
 
-	if (!pdata->mdio_driver) {
-		if (!IS_ERR(pdata->clk)) {
-			clk_prepare_enable(pdata->clk);
-			clk_disable_unprepare(pdata->clk);
-			clk_prepare_enable(pdata->clk);
-			xgene_enet_ecc_init(pdata);
+	if (pdata->mdio_driver) {
+		xgene_enet_config_ring_if_assoc(pdata);
+		return 0;
+	}
+	if (!IS_ERR(pdata->clk)) {
+		clk_prepare_enable(pdata->clk);
+		clk_disable_unprepare(pdata->clk);
+		clk_prepare_enable(pdata->clk);
+	} else {
+#ifdef CONFIG_ACPI
+		if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev), "_RST")) {
+			acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev),
+					     "_RST", NULL, NULL);
+		} else if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev),
+					 "_INI")) {
+			acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev),
+					     "_INI", NULL, NULL);
 		}
+#endif
 	}
+
+	xgene_enet_ecc_init(pdata);
 	xgene_enet_config_ring_if_assoc(pdata);
 
 	return 0;
 }
 
+static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
+			     struct xgene_enet_desc_ring *ring)
+{
+	u32 addr, val, data;
+
+	val = xgene_enet_ring_bufnum(ring->id);
+
+	if (xgene_enet_is_bufpool(ring->id)) {
+		addr = ENET_CFGSSQMIFPRESET_ADDR;
+		data = BIT(val - 0x20);
+	} else {
+		addr = ENET_CFGSSQMIWQRESET_ADDR;
+		data = BIT(val);
+	}
+
+	xgene_enet_wr_ring_if(pdata, addr, data);
+}
+
 static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
 {
+	struct xgene_enet_desc_ring *ring;
+	u32 pb, val;
+	int i;
+
+	pb = 0;
+	for (i = 0; i < pdata->rxq_cnt; i++) {
+		ring = pdata->rx_ring[i]->buf_pool;
+
+		val = xgene_enet_ring_bufnum(ring->id);
+		pb |= BIT(val - 0x20);
+	}
+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
+
+	pb = 0;
+	for (i = 0; i < pdata->txq_cnt; i++) {
+		ring = pdata->tx_ring[i];
+
+		val = xgene_enet_ring_bufnum(ring->id);
+		pb |= BIT(val);
+	}
+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
+
 	if (!IS_ERR(pdata->clk))
 		clk_disable_unprepare(pdata->clk);
 }
@@ -748,7 +802,7 @@ static void xgene_enet_adjust_link(struct net_device *ndev)
 }
 
 #ifdef CONFIG_ACPI
-static struct acpi_device *acpi_phy_find_device(struct device *dev)
+struct acpi_device *acpi_phy_find_device(struct device *dev)
 {
 	struct acpi_reference_args args;
 	struct fwnode_handle *fw_node;
@@ -869,7 +923,7 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
 		 ndev->name);
 
 	mdio_bus->priv = pdata;
-	mdio_bus->parent = &ndev->dev;
+	mdio_bus->parent = &pdata->pdev->dev;
 
 	ret = xgene_mdiobus_register(pdata, mdio_bus);
 	if (ret) {
@@ -917,6 +971,7 @@ const struct xgene_mac_ops xgene_gmac_ops = {
 
 const struct xgene_port_ops xgene_gport_ops = {
 	.reset = xgene_enet_reset,
+	.clear = xgene_enet_clear,
 	.cle_bypass = xgene_enet_cle_bypass,
 	.shutdown = xgene_gport_shutdown,
 };
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 742520e..8e48d49 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -112,9 +112,13 @@ enum xgene_enet_rm {
 #define BLOCK_ETH_DIAG_CSR_OFFSET	0xD000
 #define BLOCK_ETH_MAC_OFFSET		0x0000
 #define BLOCK_ETH_MAC_CSR_OFFSET	0x2800
+#define BLOCK_ETH_CLKRST_SRST_OFFSET	0xa000
+#define BLOCK_ETH_CLKRST_CLKEN_OFFSET	0xa008
 
 #define CLKEN_ADDR			0xc208
 #define SRST_ADDR			0xc200
+#define XGENE_CLKEN_ADDR		0xa008
+#define XGENE_SRST_ADDR			0xa000
 
 #define MAC_ADDR_REG_OFFSET		0x00
 #define MAC_COMMAND_REG_OFFSET		0x04
@@ -167,6 +171,8 @@ enum xgene_enet_rm {
 #define TX_DV_GATE_EN0			BIT(2)
 #define RX_DV_GATE_EN0			BIT(1)
 #define RESUME_RX0			BIT(0)
+#define ENET_CFGSSQMIFPRESET_ADDR		0x14
+#define ENET_CFGSSQMIWQRESET_ADDR		0x1c
 #define ENET_CFGSSQMIWQASSOC_ADDR		0xe0
 #define ENET_CFGSSQMIFPQASSOC_ADDR		0xdc
 #define ENET_CFGSSQMIQMLITEFPQASSOC_ADDR	0xf0
@@ -299,11 +305,6 @@ enum xgene_enet_ring_bufnum {
 	RING_BUFNUM_INVALID
 };
 
-enum xgene_enet_cmd {
-	XGENE_ENET_WR_CMD = BIT(31),
-	XGENE_ENET_RD_CMD = BIT(30)
-};
-
 enum xgene_enet_err_code {
 	HBF_READ_DATA = 3,
 	HBF_LL_READ = 4,
@@ -351,6 +352,9 @@ void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
 bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);
 int xgene_enet_phy_connect(struct net_device *ndev);
 void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata);
+#ifdef CONFIG_ACPI
+struct acpi_device *acpi_phy_find_device(struct device *dev);
+#endif
 
 extern const struct xgene_mac_ops xgene_gmac_ops;
 extern const struct xgene_port_ops xgene_gport_ops;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index c31ea56..75da192 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -102,25 +102,13 @@ static u8 xgene_enet_hdr_len(const void *data)
 
 static void xgene_enet_delete_bufpool(struct xgene_enet_desc_ring *buf_pool)
 {
-	struct xgene_enet_pdata *pdata = netdev_priv(buf_pool->ndev);
-	struct xgene_enet_raw_desc16 *raw_desc;
-	u32 slots = buf_pool->slots - 1;
-	u32 tail = buf_pool->tail;
-	u32 userinfo;
-	int i, len;
-
-	len = pdata->ring_ops->len(buf_pool);
-	for (i = 0; i < len; i++) {
-		tail = (tail - 1) & slots;
-		raw_desc = &buf_pool->raw_desc16[tail];
+	int i;
 
-		/* Hardware stores descriptor in little endian format */
-		userinfo = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
-		dev_kfree_skb_any(buf_pool->rx_skb[userinfo]);
+	/* Free up the buffers held by hardware */
+	for (i = 0; i < buf_pool->slots; i++) {
+		if (buf_pool->rx_skb[i])
+			dev_kfree_skb_any(buf_pool->rx_skb[i]);
 	}
-
-	pdata->ring_ops->wr_cmd(buf_pool, -len);
-	buf_pool->tail = tail;
 }
 
 static irqreturn_t xgene_enet_rx_irq(const int irq, void *data)
@@ -481,6 +469,7 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
 			 XGENE_ENET_MAX_MTU, DMA_FROM_DEVICE);
 	skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
 	skb = buf_pool->rx_skb[skb_index];
+	buf_pool->rx_skb[skb_index] = NULL;
 
 	/* checking for error */
 	status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) ||
@@ -619,6 +608,30 @@ static void xgene_enet_timeout(struct net_device *ndev)
 	}
 }
 
+static void xgene_enet_set_irq_name(struct net_device *ndev)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct xgene_enet_desc_ring *ring;
+	int i;
+
+	for (i = 0; i < pdata->rxq_cnt; i++) {
+		ring = pdata->rx_ring[i];
+		if (!pdata->cq_cnt) {
+			snprintf(ring->irq_name, IRQ_ID_SIZE, "%s-rx-txc",
+				 ndev->name);
+		} else {
+			snprintf(ring->irq_name, IRQ_ID_SIZE, "%s-rx-%d",
+				 ndev->name, i);
+		}
+	}
+
+	for (i = 0; i < pdata->cq_cnt; i++) {
+		ring = pdata->tx_ring[i]->cp_ring;
+		snprintf(ring->irq_name, IRQ_ID_SIZE, "%s-txc-%d",
+			 ndev->name, i);
+	}
+}
+
 static int xgene_enet_register_irq(struct net_device *ndev)
 {
 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
@@ -626,6 +639,7 @@ static int xgene_enet_register_irq(struct net_device *ndev)
 	struct xgene_enet_desc_ring *ring;
 	int ret = 0, i;
 
+	xgene_enet_set_irq_name(ndev);
 	for (i = 0; i < pdata->rxq_cnt; i++) {
 		ring = pdata->rx_ring[i];
 		irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
@@ -720,9 +734,6 @@ static int xgene_enet_open(struct net_device *ndev)
 	if (ret)
 		return ret;
 
-	mac_ops->tx_enable(pdata);
-	mac_ops->rx_enable(pdata);
-
 	xgene_enet_napi_enable(pdata);
 	ret = xgene_enet_register_irq(ndev);
 	if (ret)
@@ -734,7 +745,9 @@ static int xgene_enet_open(struct net_device *ndev)
 		netif_carrier_off(ndev);
 	}
 
-	netif_start_queue(ndev);
+	mac_ops->tx_enable(pdata);
+	mac_ops->rx_enable(pdata);
+	netif_tx_start_all_queues(ndev);
 
 	return ret;
 }
@@ -745,17 +758,17 @@ static int xgene_enet_close(struct net_device *ndev)
 	const struct xgene_mac_ops *mac_ops = pdata->mac_ops;
 	int i;
 
-	netif_stop_queue(ndev);
+	netif_tx_stop_all_queues(ndev);
+	mac_ops->tx_disable(pdata);
+	mac_ops->rx_disable(pdata);
 
 	if (pdata->phy_dev)
 		phy_stop(pdata->phy_dev);
 	else
 		cancel_delayed_work_sync(&pdata->link_work);
 
-	mac_ops->tx_disable(pdata);
-	mac_ops->rx_disable(pdata);
-
 	xgene_enet_free_irq(ndev);
+	netif_carrier_off(ndev);
 	xgene_enet_napi_disable(pdata);
 	for (i = 0; i < pdata->rxq_cnt; i++)
 		xgene_enet_process_ring(pdata->rx_ring[i], -1);
@@ -772,7 +785,7 @@ static void xgene_enet_delete_ring(struct xgene_enet_desc_ring *ring)
 	dev = ndev_to_dev(ring->ndev);
 
 	pdata->ring_ops->clear(ring);
-	dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
+	dmam_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
 }
 
 static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
@@ -785,6 +798,9 @@ static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
 		ring = pdata->tx_ring[i];
 		if (ring) {
 			xgene_enet_delete_ring(ring);
+			pdata->port_ops->clear(pdata, ring);
+			if (pdata->cq_cnt)
+				xgene_enet_delete_ring(ring->cp_ring);
 			pdata->tx_ring[i] = NULL;
 		}
 	}
@@ -795,6 +811,7 @@ static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
 			buf_pool = ring->buf_pool;
 			xgene_enet_delete_bufpool(buf_pool);
 			xgene_enet_delete_ring(buf_pool);
+			pdata->port_ops->clear(pdata, buf_pool);
 			xgene_enet_delete_ring(ring);
 			pdata->rx_ring[i] = NULL;
 		}
@@ -843,7 +860,7 @@ static void xgene_enet_free_desc_ring(struct xgene_enet_desc_ring *ring)
 
 	if (ring->desc_addr) {
 		pdata->ring_ops->clear(ring);
-		dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
+		dmam_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
 	}
 	devm_kfree(dev, ring);
 }
@@ -920,8 +937,8 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
 	ring->cfgsize = cfgsize;
 	ring->id = ring_id;
 
-	ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma,
-					      GFP_KERNEL);
+	ring->desc_addr = dmam_alloc_coherent(dev, size, &ring->dma,
+					GFP_KERNEL | __GFP_ZERO);
 	if (!ring->desc_addr) {
 		devm_kfree(dev, ring);
 		return NULL;
@@ -929,11 +946,12 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
 	ring->size = size;
 
 	if (is_irq_mbox_required(pdata, ring)) {
-		ring->irq_mbox_addr = dma_zalloc_coherent(dev, INTR_MBOX_SIZE,
-				&ring->irq_mbox_dma, GFP_KERNEL);
+		ring->irq_mbox_addr = dmam_alloc_coherent(dev, INTR_MBOX_SIZE,
+					&ring->irq_mbox_dma,
+					GFP_KERNEL | __GFP_ZERO);
 		if (!ring->irq_mbox_addr) {
-			dma_free_coherent(dev, size, ring->desc_addr,
-					  ring->dma);
+			dmam_free_coherent(dev, size, ring->desc_addr,
+					   ring->dma);
 			devm_kfree(dev, ring);
 			return NULL;
 		}
@@ -1028,13 +1046,6 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
 		rx_ring->nbufpool = NUM_BUFPOOL;
 		rx_ring->buf_pool = buf_pool;
 		rx_ring->irq = pdata->irqs[i];
-		if (!pdata->cq_cnt) {
-			snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx-txc",
-				 ndev->name);
-		} else {
-			snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx%d",
-				 ndev->name, i);
-		}
 		buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots,
 						sizeof(struct sk_buff *),
 						GFP_KERNEL);
@@ -1061,9 +1072,9 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
 		}
 
 		size = (tx_ring->slots / 2) * sizeof(__le64) * MAX_EXP_BUFFS;
-		tx_ring->exp_bufs = dma_zalloc_coherent(dev, size,
-							&dma_exp_bufs,
-							GFP_KERNEL);
+		tx_ring->exp_bufs = dmam_alloc_coherent(dev, size,
+					&dma_exp_bufs,
+					GFP_KERNEL | __GFP_ZERO);
 		if (!tx_ring->exp_bufs) {
 			ret = -ENOMEM;
 			goto err;
@@ -1087,8 +1098,6 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
 
 			cp_ring->irq = pdata->irqs[pdata->rxq_cnt + i];
 			cp_ring->index = i;
-			snprintf(cp_ring->irq_name, IRQ_ID_SIZE, "%s-txc%d",
-				 ndev->name, i);
 		}
 
 		cp_ring->cp_skb = devm_kcalloc(dev, tx_ring->slots,
@@ -1283,56 +1292,68 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata)
 static int xgene_enet_check_phy_handle(struct xgene_enet_pdata *pdata)
 {
 	struct device *dev = &pdata->pdev->dev;
-	int ret, phy_id, phy_mode = pdata->phy_mode;
-	struct device_node *mdio_np = NULL;
+	struct device_node *mdio_np;
+	bool mdio_probe_done;
 	const char *ph;
-#ifdef CONFIG_ACPI
-	struct acpi_reference_args args;
-	struct fwnode_handle *fw_node;
-#endif
+	u32 phy_id;
+	int ret;
+
+	if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII)
+		return 0;
 
 	if (!IS_ENABLED(CONFIG_MDIO_XGENE))
 		return 0;
 
-	if (dev->of_node) {
-		ret = device_property_read_string(dev, "phy-handle", &ph);
+	mdio_probe_done = xgene_mdio_probe_successful();
 
-		if (phy_mode == PHY_INTERFACE_MODE_RGMII) {
+	if (mdio_probe_done) {
+		if (dev->of_node) {
+			ret = device_property_read_string(dev, "phy-handle",
+							  &ph);
 			if (ret) {
-				dev_err(dev, "Unable to get phy-handle\n");
+				dev_err(dev, "Unable to find phy-handle\n");
 				return ret;
 			}
+		} else {
+#ifdef CONFIG_ACPI
+			ret = device_property_present(dev, "phy-handle");
+			if (!ret) {
+				dev_err(dev, "Unable to find phy-handle\n");
+				return -1;
+			}
+#endif
+		}
+
+		pdata->mdio_driver = true;
+	} else {
+		if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII)
+			return 0;
 
+		if (dev->of_node) {
 			mdio_np = of_find_compatible_node(dev->of_node, NULL,
 							  "apm,xgene-mdio");
-			if (!mdio_np)
-				pdata->mdio_driver = true;
-			else
-				pdata->mdio_np = mdio_np;
+			if (!mdio_np) {
+				dev_err(dev, "No mdio node in the dts\n");
+				return -ENXIO;
+			}
+
+			pdata->mdio_np = mdio_np;
+			return 0;
 		} else {
-			if (!ret)
-				pdata->mdio_driver = true;
-		}
-	} else {
 #ifdef CONFIG_ACPI
-		fw_node = acpi_fwnode_handle(ACPI_COMPANION(dev));
-		ret = acpi_node_get_property_reference(fw_node, "mboxes", 0,
-						       &args);
-		if (!ACPI_FAILURE(ret)) {
-			pdata->mdio_driver = true;
-			pdata->phy_dev =  args.adev->driver_data;
-		} else {
 			ret = device_property_read_u32(dev, "phy-channel",
 						       &phy_id);
-			if (ret) {
+			if (ret)
 				ret = device_property_read_u32(dev, "phy-addr",
-							       &phy_id);
+								    &phy_id);
+			if (ret) {
+				dev_err(dev, "Unable to get phy-channel or phy-addr\n");
+				return -EINVAL;
 			}
 
-			if (!ret)
-				pdata->phy_id = phy_id;
-		}
+			pdata->phy_id = phy_id;
 #endif
+		}
 	}
 
 	return 0;
@@ -1703,12 +1724,6 @@ static int xgene_enet_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-	ret = register_netdev(ndev);
-	if (ret) {
-		netdev_err(ndev, "Failed to register netdev\n");
-		goto err;
-	}
-
 	ret = xgene_enet_init_hw(pdata);
 	if (ret)
 		goto err_netdev;
@@ -1729,6 +1744,11 @@ static int xgene_enet_probe(struct platform_device *pdev)
 		goto err;
 
 	xgene_enet_napi_add(pdata);
+	ret = register_netdev(ndev);
+	if (ret) {
+		netdev_err(ndev, "Failed to register netdev\n");
+		goto err;
+	}
 	return 0;
 err_netdev:
 	if (ndev->reg_state == NETREG_REGISTERED)
@@ -1762,13 +1782,27 @@ static int xgene_enet_remove(struct platform_device *pdev)
 		xgene_enet_mdio_remove(pdata);
 
 	unregister_netdev(ndev);
-	xgene_enet_delete_desc_rings(pdata);
 	pdata->port_ops->shutdown(pdata);
+	xgene_enet_delete_desc_rings(pdata);
 	free_netdev(ndev);
 
 	return 0;
 }
 
+static void xgene_enet_shutdown(struct platform_device *pdev)
+{
+	struct xgene_enet_pdata *pdata;
+
+	pdata = platform_get_drvdata(pdev);
+	if (!pdata)
+		return;
+
+	if (!pdata->ndev)
+		return;
+
+	xgene_enet_remove(pdev);
+}
+
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id xgene_enet_acpi_match[] = {
 	{ "APMC0D05", XGENE_ENET1},
@@ -1803,6 +1837,7 @@ static struct platform_driver xgene_enet_driver = {
 	},
 	.probe = xgene_enet_probe,
 	.remove = xgene_enet_remove,
+	.shutdown = xgene_enet_shutdown,
 };
 
 module_platform_driver(xgene_enet_driver);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index c2804c2..9975105 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -38,6 +38,7 @@
 #include "xgene_enet_hw.h"
 #include "xgene_enet_cle.h"
 #include "xgene_enet_ring2.h"
+#include "../../../phy/mdio-xgene.h"
 
 #define XGENE_DRV_VERSION	"v1.0"
 #define XGENE_ENET_MAX_MTU	1536
@@ -103,6 +104,7 @@ struct xgene_enet_desc_ring {
 	void __iomem *cmd_base;
 	void __iomem *cmd;
 	dma_addr_t dma;
+	dma_addr_t dma_exp_bufs;
 	dma_addr_t irq_mbox_dma;
 	void *irq_mbox_addr;
 	u16 dst_ring_num;
@@ -148,6 +150,8 @@ struct xgene_mac_ops {
 
 struct xgene_port_ops {
 	int (*reset)(struct xgene_enet_pdata *pdata);
+	void (*clear)(struct xgene_enet_pdata *pdata,
+		      struct xgene_enet_desc_ring *ring);
 	void (*cle_bypass)(struct xgene_enet_pdata *pdata,
 			   u32 dst_ring_num, u16 bufpool_id);
 	void (*shutdown)(struct xgene_enet_pdata *pdata);
@@ -224,34 +228,6 @@ struct xgene_indirect_ctl {
 	void __iomem *cmd_done;
 };
 
-/* Set the specified value into a bit-field defined by its starting position
- * and length within a single u64.
- */
-static inline u64 xgene_enet_set_field_value(int pos, int len, u64 val)
-{
-	return (val & ((1ULL << len) - 1)) << pos;
-}
-
-#define SET_VAL(field, val) \
-		xgene_enet_set_field_value(field ## _POS, field ## _LEN, val)
-
-#define SET_BIT(field) \
-		xgene_enet_set_field_value(field ## _POS, 1, 1)
-
-/* Get the value from a bit-field defined by its starting position
- * and length within the specified u64.
- */
-static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src)
-{
-	return (src >> pos) & ((1ULL << len) - 1);
-}
-
-#define GET_VAL(field, src) \
-		xgene_enet_get_field_value(field ## _POS, field ## _LEN, src)
-
-#define GET_BIT(field, src) \
-		xgene_enet_get_field_value(field ## _POS, 1, src)
-
 static inline struct device *ndev_to_dev(struct net_device *ndev)
 {
 	return ndev->dev.parent;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index c078cd6..8e40408 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -143,9 +143,18 @@ static u32 xgene_enet_rd_mac(struct xgene_enet_pdata *p, u32 rd_addr)
 static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
 {
 	struct net_device *ndev = p->ndev;
-	u32 data;
+	u32 data, shutdown;
 	int i = 0;
 
+	shutdown = xgene_enet_rd_diag_csr(p, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR);
+	data = xgene_enet_rd_diag_csr(p, ENET_BLOCK_MEM_RDY_ADDR);
+
+	if (!shutdown && data == ~0U) {
+		netdev_dbg(ndev, "+ ecc_init called before, shutdown: %08x mem_ready: %08x\n",
+			   shutdown, data);
+		return 0;
+	}
+
 	xgene_enet_wr_diag_csr(p, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0);
 	do {
 		usleep_range(100, 110);
@@ -327,9 +336,10 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
 		xgene_sgmac_reset(p);
 
 	/* Enable auto-negotiation */
+	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x1000);
 	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2,
 			    0x8000);
-	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x9000);
+	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x9140);
 	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2, 0);
 
 	while (loop--) {
@@ -415,24 +425,40 @@ static void xgene_sgmac_tx_disable(struct xgene_enet_pdata *p)
 
 static int xgene_enet_reset(struct xgene_enet_pdata *p)
 {
-	int ret;
+	struct device *dev = &p->pdev->dev;
 
 	if (!xgene_ring_mgr_init(p))
 		return -ENODEV;
 
+	if (p->mdio_driver && p->enet_id == XGENE_ENET2) {
+		xgene_enet_config_ring_if_assoc(p);
+		return 0;
+	}
+
 	if (p->enet_id == XGENE_ENET2)
 		xgene_enet_wr_clkrst_csr(p, XGENET_CONFIG_REG_ADDR, SGMII_EN);
 
-	if (!IS_ERR(p->clk)) {
-		clk_prepare_enable(p->clk);
-		clk_disable_unprepare(p->clk);
-		clk_prepare_enable(p->clk);
+	if (dev->of_node) {
+		if (!IS_ERR(p->clk)) {
+			clk_prepare_enable(p->clk);
+			clk_disable_unprepare(p->clk);
+			clk_prepare_enable(p->clk);
+		}
+	} else {
+#ifdef CONFIG_ACPI
+		if (acpi_has_method(ACPI_HANDLE(&p->pdev->dev), "_RST"))
+			acpi_evaluate_object(ACPI_HANDLE(&p->pdev->dev),
+					     "_RST", NULL, NULL);
+		else if (acpi_has_method(ACPI_HANDLE(&p->pdev->dev), "_INI"))
+			acpi_evaluate_object(ACPI_HANDLE(&p->pdev->dev),
+					     "_INI", NULL, NULL);
+#endif
 	}
 
-	ret = xgene_enet_ecc_init(p);
-	if (ret)
-		return ret;
-	xgene_enet_config_ring_if_assoc(p);
+	if (!p->port_id) {
+		xgene_enet_ecc_init(p);
+		xgene_enet_config_ring_if_assoc(p);
+	}
 
 	return 0;
 }
@@ -460,10 +486,47 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
 	xgene_enet_wr_csr(p, cle_bypass_reg1 + offset, data);
 }
 
+static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
+			     struct xgene_enet_desc_ring *ring)
+{
+	u32 addr, val, data;
+
+	val = xgene_enet_ring_bufnum(ring->id);
+
+	if (xgene_enet_is_bufpool(ring->id)) {
+		addr = ENET_CFGSSQMIFPRESET_ADDR;
+		data = BIT(val - 0x20);
+	} else {
+		addr = ENET_CFGSSQMIWQRESET_ADDR;
+		data = BIT(val);
+	}
+
+	xgene_enet_wr_ring_if(pdata, addr, data);
+}
+
 static void xgene_enet_shutdown(struct xgene_enet_pdata *p)
 {
-	if (!IS_ERR(p->clk))
-		clk_disable_unprepare(p->clk);
+	struct xgene_enet_desc_ring *ring;
+	u32 pb, val;
+	int i;
+
+	pb = 0;
+	for (i = 0; i < p->rxq_cnt; i++) {
+		ring = p->rx_ring[i]->buf_pool;
+
+		val = xgene_enet_ring_bufnum(ring->id);
+		pb |= BIT(val - 0x20);
+	}
+	xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPRESET_ADDR, pb);
+
+	pb = 0;
+	for (i = 0; i < p->txq_cnt; i++) {
+		ring = p->tx_ring[i];
+
+		val = xgene_enet_ring_bufnum(ring->id);
+		pb |= BIT(val);
+	}
+	xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQRESET_ADDR, pb);
 }
 
 static void xgene_enet_link_state(struct work_struct *work)
@@ -511,6 +574,7 @@ const struct xgene_mac_ops xgene_sgmac_ops = {
 
 const struct xgene_port_ops xgene_sgport_ops = {
 	.reset		= xgene_enet_reset,
+	.clear		= xgene_enet_clear,
 	.cle_bypass	= xgene_enet_cle_bypass,
 	.shutdown	= xgene_enet_shutdown
 };
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index ba030dc..925dc45 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -258,15 +258,29 @@ static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata)
 
 static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
 {
+	struct device *dev = &pdata->pdev->dev;
+
 	if (!xgene_ring_mgr_init(pdata))
 		return -ENODEV;
 
-	if (!IS_ERR(pdata->clk)) {
-		clk_prepare_enable(pdata->clk);
-		clk_disable_unprepare(pdata->clk);
-		clk_prepare_enable(pdata->clk);
+	if (dev->of_node) {
+		if (!IS_ERR(pdata->clk)) {
+			clk_prepare_enable(pdata->clk);
+			clk_disable_unprepare(pdata->clk);
+			clk_prepare_enable(pdata->clk);
+		}
+	} else {
+#ifdef CONFIG_ACPI
+		if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev), "_RST")) {
+			acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev),
+					     "_RST", NULL, NULL);
+		} else if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev),
+					   "_INI")) {
+			acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev),
+					     "_INI", NULL, NULL);
+		}
+#endif
 	}
-
 	xgene_enet_ecc_init(pdata);
 	xgene_enet_config_ring_if_assoc(pdata);
 
@@ -292,8 +306,45 @@ static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
 
 static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
 {
-	if (!IS_ERR(pdata->clk))
-		clk_disable_unprepare(pdata->clk);
+	struct xgene_enet_desc_ring *ring;
+	u32 pb, val;
+	int i;
+
+	pb = 0;
+	for (i = 0; i < pdata->rxq_cnt; i++) {
+		ring = pdata->rx_ring[i]->buf_pool;
+
+		val = xgene_enet_ring_bufnum(ring->id);
+		pb |= BIT(val - 0x20);
+	}
+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
+
+	pb = 0;
+	for (i = 0; i < pdata->txq_cnt; i++) {
+		ring = pdata->tx_ring[i];
+
+		val = xgene_enet_ring_bufnum(ring->id);
+		pb |= BIT(val);
+	}
+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
+}
+
+static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
+			     struct xgene_enet_desc_ring *ring)
+{
+	u32 addr, val, data;
+
+	val = xgene_enet_ring_bufnum(ring->id);
+
+	if (xgene_enet_is_bufpool(ring->id)) {
+		addr = ENET_CFGSSQMIFPRESET_ADDR;
+		data = BIT(val - 0x20);
+	} else {
+		addr = ENET_CFGSSQMIWQRESET_ADDR;
+		data = BIT(val);
+	}
+
+	xgene_enet_wr_ring_if(pdata, addr, data);
 }
 
 static void xgene_enet_link_state(struct work_struct *work)
@@ -340,6 +391,7 @@ const struct xgene_mac_ops xgene_xgmac_ops = {
 
 const struct xgene_port_ops xgene_xgport_ops = {
 	.reset = xgene_enet_reset,
+	.clear = xgene_enet_clear,
 	.cle_bypass = xgene_enet_xgcle_bypass,
 	.shutdown = xgene_enet_shutdown,
 };
-- 
1.9.1



From loic.pallardy at st.com  Fri May 27 00:23:20 2016
From: loic.pallardy at st.com (loic pallardy)
Date: Fri, 27 May 2016 09:23:20 +0200
Subject: [STLinux Kernel] [PATCH 02/11] drivers: clk: st: Add clock
 propagation for audio clocks
In-Reply-To: <CAL_JsqLeD8uTmMYLFZ5Sh9=JV5s1xthvruXL-W=c=zcVS=G-ZA@mail.gmail.com>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
 <1463560892-7209-3-git-send-email-gabriel.fernandez@linaro.org>
 <20160525172409.GA27913@rob-hp-laptop>
 <CAG374jDTCJfZB+PuAnggjXhbcd3NjJqrESpe_EnMniCAeoph9A@mail.gmail.com>
 <CAL_JsqLOG4P0H+HkQ3mJhfibatuV2T51KqOn-+U+LK8WUx7QgA@mail.gmail.com>
 <5746F486.602@st.com>
 <CAL_JsqLeD8uTmMYLFZ5Sh9=JV5s1xthvruXL-W=c=zcVS=G-ZA@mail.gmail.com>
Message-ID: <5747F5E8.5030300@st.com>



On 05/26/2016 03:20 PM, Rob Herring wrote:
> On Thu, May 26, 2016 at 8:05 AM, loic pallardy <loic.pallardy at st.com> wrote:
>>
>>
>> On 05/26/2016 02:46 PM, Rob Herring wrote:
>>>
>>> On Thu, May 26, 2016 at 4:49 AM, Gabriel Fernandez
>>> <gabriel.fernandez at linaro.org> wrote:
>>>>
>>>> On 25 May 2016 at 19:24, Rob Herring <robh at kernel.org> wrote:
>>>>>
>>>>>
>>>>> On Wed, May 18, 2016 at 10:41:23AM +0200, Gabriel Fernandez wrote:
>>>>>>
>>>>>> This patch allows fine tuning of the quads FS for audio clocks
>>>>>> accuracy.
>>>>>>
>>>>>> Signed-off-by: Olivier Bideau <olivier.bideau at st.com>
>>>>>> Signed-off-by: Gabriel Fernandez <gabriel.fernandez at linaro.org>
>>>>>> ---
>>>>>>    .../devicetree/bindings/clock/st/st,flexgen.txt    |  1 +
>>>>>>    drivers/clk/st/clk-flexgen.c                       | 24
>>>>>> ++++++++++++++++++++++
>>>>>>    2 files changed, 25 insertions(+)
>>>>>>
>>>>>> diff --git a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>>>>>> b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>>>>>> index b7ee5c7..15b33c7 100644
>>>>>> --- a/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>>>>>> +++ b/Documentation/devicetree/bindings/clock/st/st,flexgen.txt
>>>>>> @@ -60,6 +60,7 @@ This binding uses the common clock binding[2].
>>>>>>    Required properties:
>>>>>>    - compatible : shall be:
>>>>>>      "st,flexgen"
>>>>>> +  "st,stih407-clkgend0", "st,flexgen" (enable clock propagation on
>>>>>> parent)
>>>>>
>>>>>
>>>>> What do "d0" and "d2" refer to?
>>>>>
>>>>> This seems to indicate you have too much clock detail in the DT (with
>>>>> individual clocks described) or not enough with genericish compatible
>>>>> strings. What happens for the mext clock you need to adjust the flags
>>>>> on? You should be able to make these adjustments without DT updates.
>>>>> Perhaps you need a wider fixing of clock compatible strings.
>>>>>
>>>>> Rob
>>>>
>>>>
>>>> Sorry i sent my response in html...
>>>>
>>>> Hi Rob,
>>>>
>>>> Thanks for reviewing.
>>>>
>>>> Can i remove
>>>> "
>>>> st,stih407-clkgend0" & "
>>>> st,stih407-clkgend2" compatible strings and add proprieties instead ?
>>>> I only need to activate 2 features and then we can keep generic
>>>> compatible strings.
>>>
>>>
>> Hi Rob,
>>>
>>> That is no different and suffers the same point I raised. It requires
>>> updating the DT for any clock configuration change or enhancement.
>>>
>> Agree with you, DT update is needed as soon as a clock configuration should
>> be changed. This is due to STiH clock driver design based on DT description
>> of SoC clock tree.
>>
>> This clock driver was accepted 2 years ago. At the time being there was
>> discussion about clock tree description location: driver or DT.
>> Bad choice was done for this driver...
>>
>> If we decide to redesign STiH clock driver using in-driver clock tree
>> description, this will modify STiH clock DT nodes description and so break
>> DT backward compatibility.
>>
>> What's from your pov the best option?
>
> You can break it once or every time you need a clock change. I'd go
> with the former. Maybe more specific compatible strings throughout
> alone would be enough rather than a flag day changing the binding.

So if I understand you correctly, main issue is d0 and d2 signification.
d0 and d2 are indeed location of the flexgen in the SoC. But that's 
right flexgen are dedicated to clocks generation for features (system, 
audio, video).
What about "st,flexgen-audio" and "st,flexgen-video"?

BR,
Loic

>
> Rob
>


From yt.shen at mediatek.com  Fri May 27 00:29:00 2016
From: yt.shen at mediatek.com (YT Shen)
Date: Fri, 27 May 2016 15:29:00 +0800
Subject: [RFC v2 2/5] drm/mediatke: add support for Mediatek SoC MT2701
In-Reply-To: <1463994590.31921.14.camel@mtksdaap41>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
 <1463756736-46573-3-git-send-email-yt.shen@mediatek.com>
 <1463994590.31921.14.camel@mtksdaap41>
Message-ID: <1464334140.31149.14.camel@mtksdaap41>

Hi CK,


On Mon, 2016-05-23 at 17:09 +0800, CK Hu wrote:
> Hi, YT:
> 
> Some comments below.
> 
> On Fri, 2016-05-20 at 23:05 +0800, yt.shen at mediatek.com wrote:
> > From: YT Shen <yt.shen at mediatek.com>
> > 
> > This patch add support for the Mediatek MT2701 DISP subsystem.
> > There is only one OVL engine in MT2701.
> > 
> > Signed-off-by: YT Shen <yt.shen at mediatek.com>
> >  
> > +static void mtk_ddp_mux_sel(void __iomem *config_regs,
> > +			    enum mtk_ddp_comp_id cur, enum mtk_ddp_comp_id next)
> > +{
> > +	if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
> > +		writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1,
> > +			       config_regs + DISP_REG_CONFIG_OUT_SEL);
> > +	}
> > +}
> > +
> 
> The function name 'mux' looks strange. The register written here
> controls the single output selection. I prefer to rename it as
> mtk_ddp_sout_sel().
OK, I will rename this function in the next version.
> 
> >  
> > -static const enum mtk_ddp_comp_id mtk_ddp_main[] = {
> > +static const enum mtk_ddp_comp_id mtk_ddp_main_2701[] = {
> > +	DDP_COMPONENT_OVL0,
> > +	DDP_COMPONENT_RDMA0,
> > +	DDP_COMPONENT_COLOR0,
> > +	DDP_COMPONENT_BLS,
> > +	DDP_COMPONENT_DSI0,
> > +};
> > +
> > +static const enum mtk_ddp_comp_id mtk_ddp_ext_2701[] = {
> > +	DDP_COMPONENT_OVL0,
> > +	DDP_COMPONENT_DSI0,
> > +};
> > +
> 
> These two pipelines has the same component such as OVL0 and DSI0. I
> think user program could not enable both crtc at the same time. Maybe
> MT2701 has only one crtc, so you should modify initial flow to create
> only one crtc for main display. Or it's typo for external display pipe,
> please correct it.
MT2701 hardware can support two output concurrently, but we haven't
implement DPI path yet.  We will change it like this:
static const enum mtk_ddp_comp_id mtk_ddp_ext_2701[] = {
	DDP_COMPONENT_RDMA1,
	DDP_COMPONENT_DPI0,
};

Thanks.
yt.shen
> 
> 
> Regards,
> CK
> 




From yt.shen at mediatek.com  Fri May 27 00:31:53 2016
From: yt.shen at mediatek.com (YT Shen)
Date: Fri, 27 May 2016 15:31:53 +0800
Subject: [RFC v2 3/5] drm/mediatek: add *driver_data for different
 hardware settings
In-Reply-To: <1463996582.30093.5.camel@mtksdaap41>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
 <1463756736-46573-4-git-send-email-yt.shen@mediatek.com>
 <1463996582.30093.5.camel@mtksdaap41>
Message-ID: <1464334313.31149.16.camel@mtksdaap41>

Hi CK,


On Mon, 2016-05-23 at 17:43 +0800, CK Hu wrote:
> Hi, YT:
> 
> One comment below.
> 
> On Fri, 2016-05-20 at 23:05 +0800, yt.shen at mediatek.com wrote:
> > From: YT Shen <yt.shen at mediatek.com>
> > 
> > There are some hardware settings changed, between MT8173 & MT2701:
> > DISP_OVL address offset changed, color format definition changed.
> > DISP_RDMA fifo size changed.
> > DISP_COLOR offset changed.
> > 
> > Signed-off-by: YT Shen <yt.shen at mediatek.com>
> > ---
> > +
> > +static inline struct mtk_ddp_comp_driver_data *mtk_ovl_get_driver_data(
> > +	struct platform_device *pdev)
> > +{
> > +	const struct of_device_id *of_id =
> > +		of_match_device(mtk_disp_ovl_driver_dt_match, &pdev->dev);
> > +
> > +	return (struct mtk_ddp_comp_driver_data *)of_id->data;
> > +}
> > +
> > +static inline struct mtk_ddp_comp_driver_data *mtk_rdma_get_driver_data(
> > +	struct platform_device *pdev)
> > +{
> > +	const struct of_device_id *of_id =
> > +		of_match_device(mtk_disp_rdma_driver_dt_match, &pdev->dev);
> > +
> > +	return (struct mtk_ddp_comp_driver_data *)of_id->data;
> > +}
> > +
> > +static inline struct mtk_ddp_comp_driver_data *mtk_color_get_driver_data(
> > +	struct device_node *node)
> > +{
> > +	const struct of_device_id *of_id =
> > +		of_match_node(mtk_disp_color_driver_dt_match, node);
> > +
> > +	return (struct mtk_ddp_comp_driver_data *)of_id->data;
> > +}
> > + 
> 
> These three functions looks the same with different parameter:
> mtk_disp_ovl_driver_dt_match, mtk_disp_rdma_driver_dt_match, and
> mtk_disp_color_driver_dt_match. So merge them to prevent duplicated
> code.
OK, I'll do this in the next version.
> 
> Regards,
> CK
> 
> 




From dirk.behme at de.bosch.com  Fri May 27 00:32:18 2016
From: dirk.behme at de.bosch.com (Dirk Behme)
Date: Fri, 27 May 2016 09:32:18 +0200
Subject: [PATCH v3 1/3] arm64: dts: r8a7796: Add Renesas R8A7796 SoC
 support
In-Reply-To: <20160527004256.GD14269@verge.net.au>
References: <1464054880-25843-1-git-send-email-horms+renesas@verge.net.au>
 <1464054880-25843-2-git-send-email-horms+renesas@verge.net.au>
 <b30c9c84-23b6-b088-4983-b2498317492b@de.bosch.com>
 <20160525004825.GC7292@verge.net.au>
 <c0fd13d5-c5c4-579b-6fad-c637bda92398@de.bosch.com>
 <20160526022833.GE18393@verge.net.au>
 <59e6225a-6dfa-8bde-dd2e-3428d6fedfe2@de.bosch.com>
 <20160527004256.GD14269@verge.net.au>
Message-ID: <b03c68c9-6949-519d-2c44-c140eac727a4@de.bosch.com>

Hi Simon,

On 27.05.2016 02:42, Simon Horman wrote:
> On Thu, May 26, 2016 at 09:14:16AM +0200, Dirk Behme wrote:
>> Hi Simon,
>>
>> On 26.05.2016 04:28, Simon Horman wrote:
>>> Hi Dirk,
>>>
>>> On Wed, May 25, 2016 at 07:10:26AM +0200, Dirk Behme wrote:
>>>> Hi Simon,
>>>>
>>>> On 25.05.2016 02:48, Simon Horman wrote:
>>>>> Hi Dirk,
>>>>>
>>>>> On Tue, May 24, 2016 at 07:30:17AM +0200, Dirk Behme wrote:
>>>>>> Hi Simon,
>>>>>
>>>>> [...]
>>>>>
>>>>>> With Renesas R-Car3 we will get a whole family of SoCs. I.e. different
>>>>>> computing power (e.g. different number of Cores) with more or less similar
>>>>>> peripherals.
>>>>>>
>>>>>> I would think that we want to reflect this in the device tree, too.
>>>>>> Therefore I think what we want is a hierarchy of device trees. Similar
>>>>>> what's done with other SoC families (compare e.g. i.MX6).
>>>>>>
>>>>>> E.g. we want an initial rcar3.dtsi, which contains all common parts of all
>>>>>> R-Car3 SoCs. E.g. one CA57 core, the SCIF where its common etc.
>>>>>>
>>>>>> Then you will have the r8a779x.dtsi which includes the rcar3.dtsi and
>>>>>> extends it for SoC specific parts. Which then will be included by the board
>>>>>> device trees, as already done, now.
>>>>>>
>>>>>> Or in other words: As soon as you have similar parts in the r8a779x.dtsi's,
>>>>>> it's time to think about moving the parts one hierarchy level up into the
>>>>>> rcar3.dtsi. Else you will end up in a maintenance hell once you have to
>>>>>> change/fix anything.
>>>>>
>>>>> Thanks for raising this issue.
>>>>>
>>>>> I agree entirely that we should work towards a situation where maintenance
>>>>> is as easy as it can be. However, due to the per-SoC binding scheme that
>>>>> we are using for IP related to Renesas SoCs I suspect that very few DT nodes
>>>>> can be shared between SoCs verbatim.
>>>>
>>>>
>>>> Could you kindly share an example for this? Looking into the H3 and the M3-W
>>>> manual, it looks to me that ~90% (?) of the peripherals are the same.
>>>
>>> The background is that this is a conversation that has been going around
>>> for years. The basic thinking is that at this point we have documentation
>>> that indicates that many hardware blocks on the H3 and M3-W are the same.
>>> But we do not have insight into the internal versioning of the IP blocks
>>> nor if they are really the same. And furthermore even if they are currently
>>> the same we don't really know if that will continue to be the case.
>>>
>>> Probably it is. Maybe it isn't. The response has been to take a
>>> conservative approach to DT bindings to give us the flexibility to update
>>> the driver implementation to reflect any differences that subsequently
>>> surface. And by providing per-SoC bindings these driver changes can be
>>> activated on a per-SoC basis without updating DTB files (which may be
>>> burned into ROMs).
>>
>>
>> Sorry, but I don't think that these are good arguments for this kind of
>> discussion ;)
>
>>From my point of view this is the central point. It is my believe that we
> simply do not have enough information to conclude that the IP blocks will
> be the same in perpetuity.
>
>> The discussion has to be based on facts. And not on "maybe" or "probably".
>> The fact is that the documentation tells us that the IPs are the same. And
>> the documentation tells us where this isn't the case. This is what we can
>> reflect in the code and the device trees.
>>
>> Or the other way around: I don't ask to not have any SoC specific device
>> trees (r8a7795.dtsi, r8a7796.dtsi etc). So we *always* have the option to
>> move anything to them, once there might be any difference found or
>> documented. But maintaining x (x > 5?) quite similar device trees just
>> because there *might* be the possibility that one or two device *might* be
>> different doesn't sound like a good argument to me.
>>
>> Or again, an other way: If I understood correctly, you are working already
>> since some time on R-Car, e.g. R-Car Gen2. How many examples do you have
>> from the Gen2 family where the IP blocks are different that they need to be
>> distinguished in the device tree?
>
> I think the question is different. The question is, if a difference comes
> up, how do we handle it?
>
> So far we have a solution. Not an ideal one, but a solution none the less.
> I do agree entirely that replicated DTs leads to significant maintenance
> overhead. But lets not throw the baby out with the bath water.


Well, we could continue this kind of discussion infinite ;)

But I agree to your below point "Lets discuss the change on its merits" 
and therefore stop here and continue with the technical aspects below ....


>>>>> Probably some sort of scheme can be cooked up using preprocessor macros.
>>>>> And probably there are other ways to resolve this problem. But I would
>>>>> prefer if we worked towards resolving this maintenance problem in parallel
>>>>> with rather than as a dependency of merging r8a7796 support into mainline.
>>>>
>>>>
>>>> I'd propose to do it correct from the beginning.
>>>>
>>>> Doing it later would either be more work or forgotten, and never be done,
>>>> then.
>>>
>>> I'm sorry but I don't agree. I think that having r8a7796 support
>>> in mainline is a higher priority than sorting this out.
>>
>>
>> Looking at the example I gave in
>>
>> http://article.gmane.org/gmane.linux.kernel.renesas-soc/4013
>>
>> which took me < 1h to create, I'm not sure what would block us from
>> mainlining the r8a7796 *including* this.
>
> Point taken. Lets discuss the change on its merits.


I totally agree, thanks! Let's continue below ...


>>>> For a starting point, I'd propose to put the r8a7795.dtsi and r8a7796.dtsi
>>>> into a graphical diff tool and move all common parts to a rcar3.dtsi (I'd be
>>>> happy to discuss the name, though)
>>>
>>> I'm not opposed to that. But being consistent with my statement above
>>> I would prefer it to be done as follow-up work.
>>>
>>> My suspicion is that right now much of the proposed r8a7796.dtsi can be
>>> moved into a hypothetical rcar3.dtsi. But that this is because the proposed
>>> r8a7796.dtsi is very small. I would not expect nearly such a large
>>> proportion of r8a7795.dtsi to be able to be moved into rcar3.dtsi because
>>> it enables more hardware blocks and they typically have (or should have in
>>> keeping with the prevailing policy as described above) per-SoC bindings.
>>
>>
>> What doesn't prevent us to use a rcar3.dtsi like given in
>>
>> http://article.gmane.org/gmane.linux.kernel.renesas-soc/4013
>>
>>
>> Having a rcar3.dtsi gives us *both* options. It doesn't force us to use the
>> one or the other. I.e. we have for each IP block the *option* to declare it
>> as common (put it onto rcar3.dtsi) *or* SoC specific (put it into
>> r8a779x.dtsi).
>>
>> Without having a common rcar3.dtsi we don't have this option at all.
>>
>> So I think the conclusion is: Let's have all options (by adding a
>> rcar3.dtsi) and then decide for each IP block individually where to place it
>> best. Or move it later from the common dtsi to the individual dtsi once
>> there is an issue found (what I really doubt that it will happen that often,
>> but this is an other topic ;) )
>
> I think that most of the nodes you have moved into the common dtsi file
> make sense. But there are some I am less sure about:
>
> * cpus
>
>   Probably there are some central aspects of cpus that are shared
>   between the r8a7795 and r8a7796. And I think that your patch captures
>   that. But I also think that there will be non-shared aspects and
>   perhaps the complexity of splitting the cpus node between per-SoC
>   and common dtsi files isn't worth it.
>
>   I don't feel strongly about this at this point.
>
>   I am also particularly sensitive about enabling CPU features across
>   multiple SoCs. But I think that the scheme you propose allows for
>   per-SoC control of features in per-SoC dtsi files. So I think
>   I am ok about that at this point.
>
>   Lastly, shouldn't the cache-controller go inside the cpu node
>   in the common dtsi file to reflect the change recently made
>   upstream to r8a7795.dtsi and the structure of r8a7796.dtsi in
>   the current patchset (v3).


We already talked about that in an other thread, and I think I missed 
that change you mentioned. So I'm fine with your proposal. I just saw 
that it's different between r8a7795 and r8a7796 and wanted to highlight 
that it should be the same.


> * cpg, scif2
>
>   This is the compatibility string issue.
>
>   Could we at least agree to defer this part of the discussion
>   and thus omit these nodes from the common dtsi file at this time?


Fine with me :)


>   I understand that you are concerned that if we don't handle this
>   now it will be forgotten. FWIW I strongly doubt this particular
>   problem will be forgotten.


Ok.

Thanks!


Best regards

Dirk




From kever.yang at rock-chips.com  Fri May 27 00:38:01 2016
From: kever.yang at rock-chips.com (Kever Yang)
Date: Fri, 27 May 2016 15:38:01 +0800
Subject: [PATCH 0/6] Rockchip Type-C and DispplayPort driver
In-Reply-To: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
Message-ID: <5747F959.7010101@rock-chips.com>

Hi Chris,

On 05/27/2016 02:02 PM, Chris Zhong wrote:
> Hi all
>
> This series patch is for rockchip Type-C phy and DisplayPort controller
> driver.
>
> The USB Type-C PHY is designed to support the USB3 and DP applications.
> The PHY basically has two main components: USB3 and DisplyPort. USB3
> operates in SuperSpeed mode and the DP can operate at RBR, HBR and HBR2
> data rates. The Type-C cable orientation detection and Power Delivery
> (PD) is accomplished using a PD PHY or a exernal PD chip.
>
> The DP controller is compliant with DisplayPort Specification,
> Version 1.3, This IP is compatible with the rockchip type-c PHY IP.
> There is a uCPU in DP controller, it need a firmware to work, please
> put the firmware file to /lib/firmware/cdn/dptx.bin. The uCPU in charge
> of aux communication and link training, the host use mailbox to
> communicate with the ucpu.
>
> The PHY driver has register a notification, to get the alt mode from PD,
> the PD driver need call the tcphy_notifier_call_chain to notify PHY and
> DP controller.
For the notification for the port status change from PD, I think we can
use the extcon class, pls reference the code in drivers/extcon/ for usage.

Thanks,
- Kever
>
> This series is based on Mark Yao's branch:
> https://github.com/markyzq/kernel-drm-rockchip/tree/drm-rockchip-next-2016-05-23
>
> I test this patches on the rk3399-evb board, with a fusb302 driver,
> this branch has no rk3399.dtsi, so the patch about dts is not included
> in this series.
>
>
>
> Chris Zhong (6):
>    phy: Add USB Type-C PHY driver for rk3399
>    Documentation: bindings: add dt doc for Rockchip USB Type-C PHY
>    drm/rockchip: vop: add cdn DP support for rk3399
>    Documentation: bindings: add dt documentation for cdn DP controller
>    ASoC: cdn-dp: Add cdn DP codec driver
>    ASoC: rockchip: Add machine driver for cdn dp codec
>
>   .../bindings/display/rockchip/cdn-dp-rockchip.txt  |  57 ++
>   .../devicetree/bindings/phy/phy-rockchip-typec.txt |  55 ++
>   .../bindings/sound/rockchip-cdn-dp-audio.txt       |  12 +
>   drivers/gpu/drm/rockchip/Kconfig                   |   9 +
>   drivers/gpu/drm/rockchip/Makefile                  |   1 +
>   drivers/gpu/drm/rockchip/cdn-dp-core.c             | 620 ++++++++++++++++
>   drivers/gpu/drm/rockchip/cdn-dp-core.h             |  95 +++
>   drivers/gpu/drm/rockchip/cdn-dp-reg.c              | 730 ++++++++++++++++++
>   drivers/gpu/drm/rockchip/cdn-dp-reg.h              | 404 ++++++++++
>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c        |   9 +-
>   drivers/gpu/drm/rockchip/rockchip_drm_vop.h        |   2 +
>   drivers/gpu/drm/rockchip/rockchip_vop_reg.c        |   2 +
>   drivers/phy/Kconfig                                |   7 +
>   drivers/phy/Makefile                               |   1 +
>   drivers/phy/phy-rockchip-typec.c                   | 823 +++++++++++++++++++++
>   include/sound/cdn-dp-audio.h                       |  51 ++
>   sound/soc/codecs/Kconfig                           |   3 +
>   sound/soc/codecs/Makefile                          |   2 +
>   sound/soc/codecs/cdn-dp-audio.c                    | 246 ++++++
>   sound/soc/rockchip/Kconfig                         |   9 +
>   sound/soc/rockchip/Makefile                        |   2 +
>   sound/soc/rockchip/rockchip-cdn-dp-audio.c         | 167 +++++
>   22 files changed, 3306 insertions(+), 1 deletion(-)
>   create mode 100644 Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt
>   create mode 100644 Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
>   create mode 100644 Documentation/devicetree/bindings/sound/rockchip-cdn-dp-audio.txt
>   create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-core.c
>   create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-core.h
>   create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-reg.c
>   create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-reg.h
>   create mode 100644 drivers/phy/phy-rockchip-typec.c
>   create mode 100644 include/sound/cdn-dp-audio.h
>   create mode 100644 sound/soc/codecs/cdn-dp-audio.c
>   create mode 100644 sound/soc/rockchip/rockchip-cdn-dp-audio.c
>




From pc.liao at mediatek.com  Fri May 27 00:43:17 2016
From: pc.liao at mediatek.com (PC Liao)
Date: Fri, 27 May 2016 15:43:17 +0800
Subject: [PATCH v2] ASoC: mediatek: Change the order of MCLK clock
 configuration
Message-ID: <1464334997-42960-1-git-send-email-pc.liao@mediatek.com>

Because MCLK turns on later and turns off earlier than codec, this patch
changes the order of MCLK clock configuration.

Signed-off-by: PC Liao <pc.liao at mediatek.com>
---
Changes since v1:
update commit message
---
 sound/soc/mediatek/mtk-afe-pcm.c |   16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/sound/soc/mediatek/mtk-afe-pcm.c b/sound/soc/mediatek/mtk-afe-pcm.c
index f1c58a2..440ae06 100644
--- a/sound/soc/mediatek/mtk-afe-pcm.c
+++ b/sound/soc/mediatek/mtk-afe-pcm.c
@@ -360,8 +360,6 @@ static int mtk_afe_i2s_startup(struct snd_pcm_substream *substream,
 	if (dai->active)
 		return 0;
 
-	mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL);
-	mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S2_M], NULL);
 	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
 			   AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 0);
 	return 0;
@@ -380,8 +378,6 @@ static void mtk_afe_i2s_shutdown(struct snd_pcm_substream *substream,
 	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
 			   AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M,
 			   AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M);
-	mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL);
-	mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S2_M], NULL);
 }
 
 static int mtk_afe_i2s_prepare(struct snd_pcm_substream *substream,
@@ -1132,6 +1128,8 @@ static int mtk_afe_runtime_suspend(struct device *dev)
 	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
 			   AUD_TCON0_PDN_AFE, AUD_TCON0_PDN_AFE);
 
+	clk_disable_unprepare(afe->clocks[MTK_CLK_I2S1_M]);
+	clk_disable_unprepare(afe->clocks[MTK_CLK_I2S2_M]);
 	clk_disable_unprepare(afe->clocks[MTK_CLK_BCK0]);
 	clk_disable_unprepare(afe->clocks[MTK_CLK_BCK1]);
 	clk_disable_unprepare(afe->clocks[MTK_CLK_TOP_PDN_AUD]);
@@ -1164,6 +1162,12 @@ static int mtk_afe_runtime_resume(struct device *dev)
 	ret = clk_prepare_enable(afe->clocks[MTK_CLK_BCK1]);
 	if (ret)
 		goto err_bck0;
+	ret = clk_prepare_enable(afe->clocks[MTK_CLK_I2S1_M]);
+	if (ret)
+		goto err_i2s1_m;
+	ret = clk_prepare_enable(afe->clocks[MTK_CLK_I2S2_M]);
+	if (ret)
+		goto err_i2s2_m;
 
 	/* enable AFE clk */
 	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, AUD_TCON0_PDN_AFE, 0);
@@ -1179,6 +1183,10 @@ static int mtk_afe_runtime_resume(struct device *dev)
 	regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1);
 	return 0;
 
+err_i2s1_m:
+	clk_disable_unprepare(afe->clocks[MTK_CLK_I2S1_M]);
+err_i2s2_m:
+	clk_disable_unprepare(afe->clocks[MTK_CLK_I2S2_M]);
 err_bck0:
 	clk_disable_unprepare(afe->clocks[MTK_CLK_BCK0]);
 err_top_aud:
-- 
1.7.9.5



From dennis.chen at linaro.org  Fri May 27 00:58:49 2016
From: dennis.chen at linaro.org (Dennis Chen)
Date: Fri, 27 May 2016 15:58:49 +0800
Subject: [PATCH v7 07/15] arm64, numa: Cleanup NUMA disabled messages.
In-Reply-To: <1464129345-18985-8-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
 <1464129345-18985-8-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <CADKHWac_0TO97JE8ZO43n+fSDWFJnB=QXJxnkpbYYeKausDHmA@mail.gmail.com>

On 25 May 2016 at 06:35, David Daney <ddaney.cavm at gmail.com> wrote:
> From: David Daney <david.daney at cavium.com>
>
> As noted by Dennis Chen, we don't want to print "No NUMA configuration
> found" if NUMA was forced off from the command line.
>
> Change the type of numa_off to bool, and clean up printing code.
> Print "NUMA disabled" if forced off on command line and "No NUMA
> configuration found" if there was no firmware NUMA information.
>
> Signed-off-by: David Daney <david.daney at cavium.com>
> Acked-by: Catalin Marinas <catalin.marinas at arm.com>
> ---
>  arch/arm64/mm/numa.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
> index 6cb03f9..1def1de 100644
> --- a/arch/arm64/mm/numa.c
> +++ b/arch/arm64/mm/numa.c
> @@ -29,7 +29,7 @@ static int cpu_to_node_map[NR_CPUS] = { [0 ... NR_CPUS-1] = NUMA_NO_NODE };
>
>  static int numa_distance_cnt;
>  static u8 *numa_distance;
> -static int numa_off;
> +static bool numa_off;
>
>  static __init int numa_parse_early_param(char *opt)
>  {
> @@ -37,7 +37,7 @@ static __init int numa_parse_early_param(char *opt)
>                 return -EINVAL;
>         if (!strncmp(opt, "off", 3)) {
>                 pr_info("%s\n", "NUMA turned off");
> -               numa_off = 1;
> +               numa_off = true;
>         }
>         return 0;
>  }
> @@ -362,7 +362,10 @@ static int __init dummy_numa_init(void)
>         int ret;
>         struct memblock_region *mblk;
>
> -       pr_info("%s\n", "No NUMA configuration found");
> +       if (numa_off)
> +               pr_info("NUMA disabled\n"); /* Forced off on command line. */
> +       else
> +               pr_info("No NUMA configuration found\n");
>         pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
>                0LLU, PFN_PHYS(max_pfn) - 1);
>
> @@ -375,7 +378,7 @@ static int __init dummy_numa_init(void)
>                 return ret;
>         }
>
> -       numa_off = 1;
> +       numa_off = true;
>         return 0;
>  }
>
> --
> 1.7.11.7
>

Reviewed-by: Dennis Chen <dennis.chen at arm.com>

-- 
Regards,
Dennis


From dennis.chen at linaro.org  Fri May 27 01:04:22 2016
From: dennis.chen at linaro.org (Dennis Chen)
Date: Fri, 27 May 2016 16:04:22 +0800
Subject: [PATCH v7 14/15] arm64, acpi, numa: NUMA support based on SRAT
 and SLIT
In-Reply-To: <1464129345-18985-15-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
 <1464129345-18985-15-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <CADKHWaeyWjagdW-T1GTFRwvXrVUpb3oLaa5qOimhd247Lk5gQg@mail.gmail.com>

On 25 May 2016 at 06:35, David Daney <ddaney.cavm at gmail.com> wrote:
> From: Hanjun Guo <hanjun.guo at linaro.org>
>
> Introduce a new file to hold ACPI based NUMA information parsing from
> SRAT and SLIT.
>
> SRAT includes the CPU ACPI ID to Proximity Domain mappings and memory
> ranges to Proximity Domain mapping.  SLIT has the information of inter
> node distances(relative number for access latency).
>
> Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
> Signed-off-by: Ganapatrao Kulkarni <gkulkarni at caviumnetworks.com>
> [rrichter at cavium.com Reworked for numa v10 series ]
> Signed-off-by: Robert Richter <rrichter at cavium.com>
> [david.daney at cavium.com reorderd and combinded with other patches in
> Hanjun Guo's original set, removed get_mpidr_in_madt() and use
> acpi_map_madt_entry() instead.]
> Signed-off-by: David Daney <david.daney at cavium.com>
> ---

I've tested this patch on Juno board with home made SRAT and SLIT
table, so feel free to add:
Tested-by: Dennis Chen <dennis.chen at arm.com>

-- 
Regards,
Dennis


From kever.yang at rock-chips.com  Fri May 27 01:05:54 2016
From: kever.yang at rock-chips.com (Kever Yang)
Date: Fri, 27 May 2016 16:05:54 +0800
Subject: [PATCH 1/6] phy: Add USB Type-C PHY driver for rk3399
In-Reply-To: <1464328939-8073-2-git-send-email-zyw@rock-chips.com>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
 <1464328939-8073-2-git-send-email-zyw@rock-chips.com>
Message-ID: <5747FFE2.9070302@rock-chips.com>

Hi Chris,

On 05/27/2016 02:02 PM, Chris Zhong wrote:
> Add a PHY provider driver for the rk3399 SoC Type-c PHY. The USB
> Type-C PHY is designed to support the USB3 and DP applications. The
> PHY basically has two main components: USB3 and DisplyPort. USB3
> operates in SuperSpeed mode and the DP can operate at RBR, HBR and
> HBR2 data rates.
>
> Signed-off-by: Chris Zhong <zyw at rock-chips.com>
> ---
>
>   drivers/phy/Kconfig              |   7 +
>   drivers/phy/Makefile             |   1 +
>   drivers/phy/phy-rockchip-typec.c | 823 +++++++++++++++++++++++++++++++++++++++
>   3 files changed, 831 insertions(+)
>   create mode 100644 drivers/phy/phy-rockchip-typec.c
>
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 26566db..dc388a3d 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -351,6 +351,13 @@ config PHY_ROCKCHIP_DP
>   	help
>   	  Enable this to support the Rockchip Display Port PHY.
>   
> +config PHY_ROCKCHIP_TYPEC
> +	tristate "Rockchip TYPEC PHY Driver"
> +	depends on ARCH_ROCKCHIP && OF
> +	select GENERIC_PHY
> +	help
> +	  Enable this to support the Rockchip USB TYPEC PHY.
> +
>   config PHY_ST_SPEAR1310_MIPHY
>   	tristate "ST SPEAR1310-MIPHY driver"
>   	select GENERIC_PHY
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index 24596a9..91fa413 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -39,6 +39,7 @@ obj-$(CONFIG_PHY_QCOM_APQ8064_SATA)	+= phy-qcom-apq8064-sata.o
>   obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
>   obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o
>   obj-$(CONFIG_PHY_ROCKCHIP_DP)		+= phy-rockchip-dp.o
> +obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
>   obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)	+= phy-qcom-ipq806x-sata.o
>   obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY)	+= phy-spear1310-miphy.o
>   obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY)	+= phy-spear1340-miphy.o
> diff --git a/drivers/phy/phy-rockchip-typec.c b/drivers/phy/phy-rockchip-typec.c
> new file mode 100644
> index 0000000..6609cfb
> --- /dev/null
> +++ b/drivers/phy/phy-rockchip-typec.c
> @@ -0,0 +1,823 @@
> +/*
> + * Rockchip usb3 PHY driver
> + *
> + * Copyright (C) 2016 Kever Yang <kever.yang at rock-chips.com>
> + *                    Chris Zhong <zyw at rock-chips.com>
> + * Copyright (C) 2016 ROCKCHIP, Inc.
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/delay.h>
> +#include <linux/phy/phy-rockchip-typec.h>
> +
> +#define ADDR_ADJ			2
> +#define CMN_SSM_BANDGAP			(0x21 << ADDR_ADJ)
> +#define CMN_SSM_BIAS			(0x22 << ADDR_ADJ)
> +#define CMN_PLLSM0_PLLEN		(0x29 << ADDR_ADJ)
> +#define CMN_PLLSM0_PLLPRE		(0x2a << ADDR_ADJ)
> +#define CMN_PLLSM0_PLLVREF		(0x2b << ADDR_ADJ)
> +#define CMN_PLLSM0_PLLLOCK		(0x2c << ADDR_ADJ)
> +#define CMN_PLLSM1_PLLEN		(0x31 << ADDR_ADJ)
> +#define CMN_PLLSM1_PLLPRE		(0x32 << ADDR_ADJ)
> +#define CMN_PLLSM1_PLLVREF		(0x33 << ADDR_ADJ)
> +#define CMN_PLLSM1_PLLLOCK		(0x34 << ADDR_ADJ)
> +#define CMN_PLLSM1_USER_DEF_CTRL	(0x37 << ADDR_ADJ)
> +#define CMN_ICAL_OVRD			(0xc1 << ADDR_ADJ)
> +#define CMN_PLL0_VCOCAL_OVRD		(0x83 << ADDR_ADJ)
> +#define CMN_PLL0_VCOCAL_INIT		(0x84 << ADDR_ADJ)
> +#define CMN_PLL0_VCOCAL_ITER		(0x85 << ADDR_ADJ)
> +#define CMN_PLL0_LOCK_REFCNT_START	(0x90 << ADDR_ADJ)
> +#define CMN_PLL0_LOCK_PLLCNT_START	(0x92 << ADDR_ADJ)
> +#define CMN_PLL0_LOCK_PLLCNT_THR	(0x93 << ADDR_ADJ)
> +#define CMN_PLL0_INTDIV			(0x94 << ADDR_ADJ)
> +#define CMN_PLL0_FRACDIV		(0x95 << ADDR_ADJ)
> +#define CMN_PLL0_HIGH_THR		(0x96 << ADDR_ADJ)
> +#define CMN_PLL0_DSM_DIAG		(0x97 << ADDR_ADJ)
> +#define CMN_PLL0_SS_CTRL1		(0x98 << ADDR_ADJ)
> +#define CMN_PLL0_SS_CTRL2		(0x99 << ADDR_ADJ)
> +#define CMN_PLL1_VCOCAL_START		(0xa1 << ADDR_ADJ)
> +#define CMN_PLL1_VCOCAL_OVRD		(0xa3 << ADDR_ADJ)
> +#define CMN_PLL1_VCOCAL_INIT		(0xa4 << ADDR_ADJ)
> +#define CMN_PLL1_VCOCAL_ITER		(0xa5 << ADDR_ADJ)
> +#define CMN_PLL1_LOCK_REFCNT_START	(0xb0 << ADDR_ADJ)
> +#define CMN_PLL1_LOCK_PLLCNT_START	(0xb2 << ADDR_ADJ)
> +#define CMN_PLL1_LOCK_PLLCNT_THR	(0xb3 << ADDR_ADJ)
> +#define CMN_PLL1_INTDIV			(0xb4 << ADDR_ADJ)
> +#define CMN_PLL1_FRACDIV		(0xb5 << ADDR_ADJ)
> +#define CMN_PLL1_HIGH_THR		(0xb6 << ADDR_ADJ)
> +#define CMN_PLL1_DSM_DIAG		(0xb7 << ADDR_ADJ)
> +#define CMN_PLL1_SS_CTRL1		(0xb8 << ADDR_ADJ)
> +#define CMN_PLL1_SS_CTRL2		(0xb9 << ADDR_ADJ)
> +#define CMN_RXCAL_OVRD			(0xd1 << ADDR_ADJ)
> +#define CMN_TXPUCAL_CTRL		(0xe0 << ADDR_ADJ)
> +#define CMN_TXPUCAL_OVRD		(0xe1 << ADDR_ADJ)
> +#define CMN_TXPDCAL_OVRD		(0xf1 << ADDR_ADJ)
> +#define CMN_DIAG_PLL0_FBH_OVRD		(0x1c0 << ADDR_ADJ)
> +#define CMN_DIAG_PLL0_FBL_OVRD		(0x1c1 << ADDR_ADJ)
> +#define CMN_DIAG_PLL0_OVRD		(0x1c2 << ADDR_ADJ)
> +#define CMN_DIAG_PLL0_V2I_TUNE		(0x1c5 << ADDR_ADJ)
> +#define CMN_DIAG_PLL0_CP_TUNE		(0x1c6 << ADDR_ADJ)
> +#define CMN_DIAG_PLL0_LF_PROG		(0x1c7 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_FBH_OVRD		(0x1d0 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_FBL_OVRD		(0x1d1 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_OVRD		(0x1d2 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_V2I_TUNE		(0x1d5 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_CP_TUNE		(0x1d6 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_LF_PROG		(0x1d7 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_PTATIS_TUNE1	(0x1d8 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_PTATIS_TUNE2	(0x1d9 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_INCLK_CTRL	(0x1da << ADDR_ADJ)
> +#define CMN_DIAG_HSCLK_SEL		(0x1e0 << ADDR_ADJ)
> +
> +#define XCVR_PSM_RCTRL(n)		((0x4001 | (n << 9)) << ADDR_ADJ)
> +#define XCVR_PSM_CAL_TMR(n)		((0x4002 | (n << 9)) << ADDR_ADJ)
> +#define XCVR_PSM_A0IN_TMR(n)		((0x4003 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_CAL_SCLR_MULT(n)	((0x4047 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_CPOST_MULT_00(n)	((0x404c | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_CPOST_MULT_01(n)	((0x404d | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_CPOST_MULT_10(n)	((0x404e | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_CPOST_MULT_11(n)	((0x404f | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_000(n)	((0x4050 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_001(n)	((0x4051 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_010(n)	((0x4052 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_011(n)	((0x4053 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_100(n)	((0x4054 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_101(n)	((0x4055 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_110(n)	((0x4056 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_111(n)	((0x4057 | (n << 9)) << ADDR_ADJ)
> +#define XCVR_DIAG_PLLDRC_CTRL(n)	((0x40e0 | (n << 9)) << ADDR_ADJ)
> +#define XCVR_DIAG_BIDI_CTRL(n)		((0x40e8 | (n << 9)) << ADDR_ADJ)
> +#define XCVR_DIAG_LANE_FCM_EN_MGN(n)	((0x40f2 | (n << 9)) << ADDR_ADJ)
> +#define TX_PSC_A0(n)			((0x4100 | (n << 9)) << ADDR_ADJ)
> +#define TX_PSC_A1(n)			((0x4101 | (n << 9)) << ADDR_ADJ)
> +#define TX_PSC_A2(n)			((0x4102 | (n << 9)) << ADDR_ADJ)
> +#define TX_PSC_A3(n)			((0x4103 | (n << 9)) << ADDR_ADJ)
> +#define TX_RCVDET_CTRL(n)		((0x4120 | (n << 9)) << ADDR_ADJ)
> +#define TX_RCVDET_EN_TMR(n)		((0x4122 | (n << 9)) << ADDR_ADJ)
> +#define TX_RCVDET_ST_TMR(n)		((0x4123 | (n << 9)) << ADDR_ADJ)
> +#define TX_DIAG_TX_DRV(n)		((0x41e1 | (n << 9)) << ADDR_ADJ)
> +#define TX_DIAG_BGREF_PREDRV_DELAY	(0x41e7 << ADDR_ADJ)
> +#define TX_ANA_CTRL_REG_1		(0x5020 << ADDR_ADJ)
> +#define TX_ANA_CTRL_REG_2		(0x5021 << ADDR_ADJ)
> +#define TXDA_COEFF_CALC_CTRL		(0x5022 << ADDR_ADJ)
> +#define TX_DIG_CTRL_REG_2		(0x5024 << ADDR_ADJ)
> +#define TXDA_CYA_AUXDA_CYA		(0x5025 << ADDR_ADJ)
> +#define TX_ANA_CTRL_REG_3		(0x5026 << ADDR_ADJ)
> +#define TX_ANA_CTRL_REG_4		(0x5027 << ADDR_ADJ)
> +#define TX_ANA_CTRL_REG_5		(0x5029 << ADDR_ADJ)
> +
> +#define RX_PSC_A0(n)			((0x8000 | (n << 9)) << ADDR_ADJ)
> +#define RX_PSC_A1(n)			((0x8001 | (n << 9)) << ADDR_ADJ)
> +#define RX_PSC_A2(n)			((0x8002 | (n << 9)) << ADDR_ADJ)
> +#define RX_PSC_A3(n)			((0x8003 | (n << 9)) << ADDR_ADJ)
> +#define RX_PSC_CAL(n)			((0x8006 | (n << 9)) << ADDR_ADJ)
> +#define RX_PSC_RDY(n)			((0x8007 | (n << 9)) << ADDR_ADJ)
> +#define RX_IQPI_ILL_CAL_OVRD		(0x8023 << ADDR_ADJ)
> +#define RX_EPI_ILL_CAL_OVRD		(0x8033 << ADDR_ADJ)
> +#define RX_SDCAL0_OVRD			(0x8041 << ADDR_ADJ)
> +#define RX_SDCAL1_OVRD			(0x8049 << ADDR_ADJ)
> +#define RX_SLC_INIT			(0x806d << ADDR_ADJ)
> +#define RX_SLC_RUN			(0x806e << ADDR_ADJ)
> +#define RX_CDRLF_CNFG2			(0x8081 << ADDR_ADJ)
> +#define RX_SIGDET_HL_FILT_TMR(n)	((0x8090 | (n << 9)) << ADDR_ADJ)
> +#define RX_SLC_IOP0_OVRD		(0x8101 << ADDR_ADJ)
> +#define RX_SLC_IOP1_OVRD		(0x8105 << ADDR_ADJ)
> +#define RX_SLC_QOP0_OVRD		(0x8109 << ADDR_ADJ)
> +#define RX_SLC_QOP1_OVRD		(0x810d << ADDR_ADJ)
> +#define RX_SLC_EOP0_OVRD		(0x8111 << ADDR_ADJ)
> +#define RX_SLC_EOP1_OVRD		(0x8115 << ADDR_ADJ)
> +#define RX_SLC_ION0_OVRD		(0x8119 << ADDR_ADJ)
> +#define RX_SLC_ION1_OVRD		(0x811d << ADDR_ADJ)
> +#define RX_SLC_QON0_OVRD		(0x8121 << ADDR_ADJ)
> +#define RX_SLC_QON1_OVRD		(0x8125 << ADDR_ADJ)
> +#define RX_SLC_EON0_OVRD		(0x8129 << ADDR_ADJ)
> +#define RX_SLC_EON1_OVRD		(0x812d << ADDR_ADJ)
> +#define RX_SLC_IEP0_OVRD		(0x8131 << ADDR_ADJ)
> +#define RX_SLC_IEP1_OVRD		(0x8135 << ADDR_ADJ)
> +#define RX_SLC_QEP0_OVRD		(0x8139 << ADDR_ADJ)
> +#define RX_SLC_QEP1_OVRD		(0x813d << ADDR_ADJ)
> +#define RX_SLC_EEP0_OVRD		(0x8141 << ADDR_ADJ)
> +#define RX_SLC_EEP1_OVRD		(0x8145 << ADDR_ADJ)
> +#define RX_SLC_IEN0_OVRD		(0x8149 << ADDR_ADJ)
> +#define RX_SLC_IEN1_OVRD		(0x814d << ADDR_ADJ)
> +#define RX_SLC_QEN0_OVRD		(0x8151 << ADDR_ADJ)
> +#define RX_SLC_QEN1_OVRD		(0x8155 << ADDR_ADJ)
> +#define RX_SLC_EEN0_OVRD		(0x8159 << ADDR_ADJ)
> +#define RX_SLC_EEN1_OVRD		(0x815d << ADDR_ADJ)
> +#define RX_DIAG_SIGDET_TUNE(n)		((0x81dc | (n << 9)) << ADDR_ADJ)
> +#define RX_DIAG_SC2C_DELAY		(0x81e1 << ADDR_ADJ)
> +
> +#define PMA_LANE_CFG			(0xc000 << ADDR_ADJ)
> +#define PIPE_CMN_CTRL1			(0xc001 << ADDR_ADJ)
> +#define PIPE_CMN_CTRL2			(0xc002 << ADDR_ADJ)
> +#define PIPE_COM_LOCK_CFG1		(0xc003 << ADDR_ADJ)
> +#define PIPE_COM_LOCK_CFG2		(0xc004 << ADDR_ADJ)
> +#define PIPE_RCV_DET_INH		(0xc005 << ADDR_ADJ)
> +#define DP_MODE_CTL			(0xc008 << ADDR_ADJ)
> +#define DP_CLK_CTL			(0xc009 << ADDR_ADJ)
> +#define STS				(0xc00F << ADDR_ADJ)
> +#define PHY_ISO_CMN_CTRL		(0xc010 << ADDR_ADJ)
> +#define PHY_DP_TX_CTL			(0xc408 << ADDR_ADJ)
> +#define PMA_CMN_CTRL1			(0xc800 << ADDR_ADJ)
> +#define PHY_PMA_ISO_CMN_CTRL		(0xc810 << ADDR_ADJ)
> +#define PHY_ISOLATION_CTRL		(0xc81f << ADDR_ADJ)
> +#define PHY_PMA_ISO_XCVR_CTRL(n)	((0xcc11 | (n << 6)) << ADDR_ADJ)
> +#define PHY_PMA_ISO_LINK_MODE(n)	((0xcc12 | (n << 6)) << ADDR_ADJ)
> +#define PHY_PMA_ISO_PWRST_CTRL(n)	((0xcc13 | (n << 6)) << ADDR_ADJ)
> +#define PHY_PMA_ISO_TX_DATA_LO(n)	((0xcc14 | (n << 6)) << ADDR_ADJ)
> +#define PHY_PMA_ISO_TX_DATA_HI(n)	((0xcc15 | (n << 6)) << ADDR_ADJ)
> +#define PHY_PMA_ISO_RX_DATA_LO(n)	((0xcc16 | (n << 6)) << ADDR_ADJ)
> +#define PHY_PMA_ISO_RX_DATA_HI(n)	((0xcc17 | (n << 6)) << ADDR_ADJ)
> +#define TX_BIST_CTRL(n)			((0x4140 | (n << 9)) << ADDR_ADJ)
> +#define TX_BIST_UDDWR(n)		((0x4141 | (n << 9)) << ADDR_ADJ)
> +
> +#define GRF_SOC_CON26			0x6268
> +#define UPHY_DP_SEL			BIT(3)
> +#define UPHY_DP_SEL_MASK		BIT(19)
> +#define DPTX_HDP_SEL			(3 << 12)
> +#define DPTX_HDP_SEL_MASK		(3 << 28)
> +
> +#define PHY_MODE_SET_TIMEOUT		1000000
> +
> +#define	MODE_DISCONNECT			1
> +#define	MODE_UFP			2
> +#define	MODE_DFP_USBONLY		3
> +#define	MODE_DFP_DPONLY			4
> +#define	MODE_DFP_USB3DP			5
> +#define	MODE_DFP_USB2DP			6
> +
> +#define PARSE_GRF_REG(TYPE) { \
> +	if (of_find_property(np, "rockchip,usb3phy_"#TYPE, &len)) { \
> +		len /= sizeof(u32);\
> +		ret = of_property_read_u32_array(np, "rockchip,usb3phy_" #TYPE,\
> +						 array, len); \
> +		exregs->usb3phy_##TYPE = array[0]; \
> +		exregs->usb3phy_##TYPE##_shift = array[1]; \
> +		exregs->usb3phy_##TYPE##_mask = array[2]; \
> +		pr_info("%s property found %s, %x, %d, %d\n", __func__, \
> +			"rockchip,usb3phy_"#TYPE, \
> +			array[0], array[1], array[2]); \
> +	} else { \
> +		pr_info("%s property not found %s\n", __func__, \
> +			"rockchip,usb3phy_" #TYPE); \
> +	} \
> +}
> +
> +struct rockchip_typec_phy *rockchip_tcphy;
> +
> +static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy,
> +			  unsigned int num_lanes)
> +{
> +	unsigned int i;
> +
> +	writel(0x830, tcphy->base + PMA_CMN_CTRL1);
> +	for (i = 0; i < num_lanes; i++) {
> +		writel(0x90, tcphy->base + XCVR_DIAG_LANE_FCM_EN_MGN(i));
> +		writel(0x960, tcphy->base + TX_RCVDET_EN_TMR(i));
> +		writel(0x30, tcphy->base + TX_RCVDET_ST_TMR(i));
> +	}
> +}
> +
> +static void tcphy_cfg_usb_pll(struct rockchip_typec_phy *tcphy)
> +{
> +	unsigned int rdata;
> +
> +	rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
> +	writel(rdata & 0xfffc, tcphy->base + CMN_DIAG_HSCLK_SEL);
> +	writel(0xf0, tcphy->base + CMN_PLL0_VCOCAL_INIT);
> +	writel(0x18, tcphy->base + CMN_PLL0_VCOCAL_ITER);
> +	writel(0xd0, tcphy->base + CMN_PLL0_INTDIV);
> +	writel(0x4a4a, tcphy->base + CMN_PLL0_FRACDIV);
> +	writel(0x34, tcphy->base + CMN_PLL0_HIGH_THR);
> +	writel(0x1ee, tcphy->base + CMN_PLL0_SS_CTRL1);
> +	writel(0x7f03, tcphy->base + CMN_PLL0_SS_CTRL2);
> +	writel(0x20, tcphy->base + CMN_PLL0_DSM_DIAG);
> +	writel(0, tcphy->base + CMN_DIAG_PLL0_OVRD);
> +	writel(0, tcphy->base + CMN_DIAG_PLL0_FBH_OVRD);
> +	writel(0, tcphy->base + CMN_DIAG_PLL0_FBL_OVRD);
> +	writel(0x7, tcphy->base + CMN_DIAG_PLL0_V2I_TUNE);
> +	writel(0x45, tcphy->base + CMN_DIAG_PLL0_CP_TUNE);
> +	writel(0x8, tcphy->base + CMN_DIAG_PLL0_LF_PROG);
> +}
> +
> +static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy)
> +{
> +	unsigned int rdata;
> +
> +	writel(0x2405, tcphy->base + DP_CLK_CTL);
> +
> +	rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
> +	rdata = (rdata & 0xffcf) | 0x30;
> +	writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL);
> +	writel(0xf0, tcphy->base + CMN_PLL1_VCOCAL_INIT);
> +	writel(0x18, tcphy->base + CMN_PLL1_VCOCAL_ITER);
> +	writel(0x30b9, tcphy->base + CMN_PLL1_VCOCAL_START);
> +	writel(0x21c, tcphy->base + CMN_PLL1_INTDIV);
> +	writel(0, tcphy->base + CMN_PLL1_FRACDIV);
> +	writel(0x5, tcphy->base + CMN_PLL1_HIGH_THR);
> +	writel(0x35, tcphy->base + CMN_PLL1_SS_CTRL1);
> +	writel(0x7f1e, tcphy->base + CMN_PLL1_SS_CTRL2);
> +	writel(0x20, tcphy->base + CMN_PLL1_DSM_DIAG);
> +	writel(0, tcphy->base + CMN_PLLSM1_USER_DEF_CTRL);
> +	writel(0, tcphy->base + CMN_DIAG_PLL1_OVRD);
> +	writel(0, tcphy->base + CMN_DIAG_PLL1_FBH_OVRD);
> +	writel(0, tcphy->base + CMN_DIAG_PLL1_FBL_OVRD);
> +	writel(0x6, tcphy->base + CMN_DIAG_PLL1_V2I_TUNE);
> +	writel(0x45, tcphy->base + CMN_DIAG_PLL1_CP_TUNE);
> +	writel(0x8, tcphy->base + CMN_DIAG_PLL1_LF_PROG);
> +	writel(0x100, tcphy->base + CMN_DIAG_PLL1_PTATIS_TUNE1);
> +	writel(0x7, tcphy->base + CMN_DIAG_PLL1_PTATIS_TUNE2);
> +	writel(0x4, tcphy->base + CMN_DIAG_PLL1_INCLK_CTRL);
> +}
> +
> +static void tcphy_tx_usb_cfg_lane(struct rockchip_typec_phy *tcphy,
> +				  unsigned int lane)
> +{
> +	writel(0x7799, tcphy->base + TX_PSC_A0(lane));
> +	writel(0x7798, tcphy->base + TX_PSC_A1(lane));
> +	writel(0x5098, tcphy->base + TX_PSC_A2(lane));
> +	writel(0x5098, tcphy->base + TX_PSC_A3(lane));
> +	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
> +	writel(0xbf, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
> +}
> +
> +static void tcphy_rx_usb_cfg_lane(struct rockchip_typec_phy *tcphy,
> +				  unsigned int lane)
> +{
> +	writel(0xa6fd, tcphy->base + RX_PSC_A0(lane));
> +	writel(0xa6fd, tcphy->base + RX_PSC_A1(lane));
> +	writel(0xa410, tcphy->base + RX_PSC_A2(lane));
> +	writel(0x2410, tcphy->base + RX_PSC_A3(lane));
> +	writel(0x23ff, tcphy->base + RX_PSC_CAL(lane));
> +	writel(0x13, tcphy->base + RX_SIGDET_HL_FILT_TMR(lane));
> +	writel(0x1004, tcphy->base + RX_DIAG_SIGDET_TUNE(lane));
> +	writel(0x2010, tcphy->base + RX_PSC_RDY(lane));
> +	writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
> +}
> +
> +static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy,
> +			      unsigned int lane)
> +{
> +	unsigned int rdata;
> +
> +	writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
> +	writel(0x6799, tcphy->base + TX_PSC_A0(lane));
> +	writel(0x6798, tcphy->base + TX_PSC_A1(lane));
> +	writel(0x98, tcphy->base + TX_PSC_A2(lane));
> +	writel(0x98, tcphy->base + TX_PSC_A3(lane));
> +	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
> +	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane));
> +	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane));
> +	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane));
> +	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane));
> +	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane));
> +	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane));
> +	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane));
> +
> +	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane));
> +	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane));
> +	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
> +	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane));
> +
> +	writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
> +	writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
> +
> +	rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
> +	rdata = (rdata & 0x8fff) | 0x6000;
> +	writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
> +}
> +
> +static void tcphy_cfg_pin_assign(struct rockchip_typec_phy *tcphy)
> +{
> +	switch (tcphy->map) {
> +	case PIN_MAP_A:
> +		writel(0x19d5, tcphy->base + PMA_LANE_CFG);
> +		break;
> +	case PIN_MAP_B:
> +		writel(0x1500, tcphy->base + PMA_LANE_CFG);
> +		break;
> +	case PIN_MAP_C:
> +	case PIN_MAP_E:
> +		writel(0x51d9, tcphy->base + PMA_LANE_CFG);
> +		break;
> +	case PIN_MAP_D:
> +	case PIN_MAP_F:
> +		writel(0x5100, tcphy->base + PMA_LANE_CFG);
> +		break;
> +	};
> +}
> +
> +static void tcphy_cfg_lanes(struct rockchip_typec_phy *tcphy,
> +			    unsigned int link_cfg)
> +{
> +	unsigned int i;
> +
> +	/* PMA lane configuration DP or USB3 */
> +	for (i = 0; i < 4; i++) {
> +		if ((link_cfg >> i) & 0x1) {
> +			tcphy_dp_cfg_lane(tcphy, i);
> +		} else {
> +			/*
> +			 * lan0 TX and lan1 RX for USB3 Normal direction
> +			 * lan3 TX and lan2 RX for USB3 Flip direction
> +			 */
> +			if ((i == 0) | (i == 3))
> +				tcphy_tx_usb_cfg_lane(tcphy, i);
> +			else
> +				tcphy_rx_usb_cfg_lane(tcphy, i);
> +		}
> +	}
> +}
> +
> +static void tcphy_cfg_flip_set(struct rockchip_typec_phy *tcphy)
> +{
> +	regmap_write(tcphy->grf_regs,
> +		     tcphy->exregs.usb3phy_con0,
> +		     tcphy->flip | BIT(16));
> +
> +	tcphy_cfg_24m(tcphy, 0x4);
> +
> +	if (tcphy->mode == MODE_UFP ||
> +	    tcphy->mode == MODE_DFP_USBONLY ||
> +	    tcphy->mode == MODE_DFP_USB3DP)
> +		tcphy_cfg_usb_pll(tcphy);
> +
> +	if (tcphy->mode == MODE_DFP_DPONLY ||
> +	    tcphy->mode == MODE_DFP_USB2DP ||
> +	    tcphy->mode == MODE_DFP_USB3DP)
> +		tcphy_cfg_dp_pll(tcphy);
> +
> +	if (tcphy->mode == MODE_DFP_DPONLY || tcphy->mode == MODE_DFP_USB2DP)
> +		tcphy_cfg_lanes(tcphy, 0xf);
> +	else if (tcphy->flip)
> +		tcphy_cfg_lanes(tcphy, 0x3);
> +	else
> +		tcphy_cfg_lanes(tcphy, 0xc);
> +}
> +
> +static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
> +{
> +	int rdata, rdata2, val;
> +
> +	rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
> +	rdata2 = readl(tcphy->base + CMN_TXPUCAL_CTRL);
> +
> +	rdata = rdata & 0xdfff;
> +	writel(rdata, tcphy->base + TX_ANA_CTRL_REG_1);
> +
> +	rdata = readl(tcphy->base + TX_DIG_CTRL_REG_2);
> +	rdata = rdata & 0xffc0;
> +	rdata2 = rdata2 & 0x3f;
> +	rdata  = rdata | rdata2;
> +	writel(rdata, tcphy->base + TX_DIG_CTRL_REG_2);
> +	usleep_range(1000, 2000);
> +
> +	rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
> +	rdata = rdata | 0x2000;
> +	writel(rdata, tcphy->base + TX_ANA_CTRL_REG_1);
> +
> +	usleep_range(150, 200);
> +
> +	writel(0, tcphy->base + PHY_DP_TX_CTL);
> +	writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2);
> +	writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2);
> +	writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
> +	writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1);
> +	writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1);
> +	writel(0x30C, tcphy->base + TX_ANA_CTRL_REG_2);
> +	writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
> +	writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4);
> +	writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1);
> +	writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1);
> +	writel(0x30d, tcphy->base + TX_ANA_CTRL_REG_2);
> +	writel(0x30f, tcphy->base + TX_ANA_CTRL_REG_2);
> +
> +	if (tcphy->flip)
> +		writel(0xa078, tcphy->base + TX_ANA_CTRL_REG_1);
> +	else
> +		writel(0xb078, tcphy->base + TX_ANA_CTRL_REG_1);
> +
> +	writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2);
> +	writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
> +	writel(0, tcphy->base + TX_ANA_CTRL_REG_4);
> +	writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
> +	writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL);
> +	writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA);
> +
> +	val = readl(tcphy->base + TX_DIG_CTRL_REG_2);
> +	val |= BIT(15);
> +	writel(val, tcphy->base + TX_DIG_CTRL_REG_2);
> +}
> +
> +static void tcphy_dp_hpd(struct rockchip_typec_phy *tcphy,
> +			 u8 mode)
> +{
> +	/* force hpd */
> +	if (mode)
> +		regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
> +			     DPTX_HDP_SEL_MASK | DPTX_HDP_SEL);
> +	else
> +		regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
> +			     DPTX_HDP_SEL_MASK);
> +}
> +
> +static int tcphy_usb3_init(struct rockchip_typec_phy *tcphy)
I don't think we should use this name here, this function actually is
waiting for TypeC PHY for usb3 ready instead of do any initialize,
so I prefer to use tcphy_usb3phy_wait4ready().
> +{
> +	int timeout = 0;
> +	int ret, val;
> +
> +	/*wait TCPHY for pipe ready */
> +	while (1) {
> +		ret = regmap_read(tcphy->grf_regs,
> +				  tcphy->exregs.usb3phy_status0, &val);
> +		val >>= tcphy->exregs.usb3phy_status0_shift;
> +		if ((val & 0x1) == 0)
> +			break;
> +
> +		timeout++;
> +		if (timeout > 1000) {
> +			pr_warn("%s wait pipe ready timerout!\n", __func__);
typo for 'timeout' here.
> +			break;
> +		}
> +		usleep_range(10, 20);
> +	}
> +
> +	return 0;
> +}
> +
> +static int tcphy_dp_init(struct rockchip_typec_phy *tcphy)
> +{
> +	int ret, val;
> +
> +	ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
> +				 val, val & BIT(6), 1000, PHY_MODE_SET_TIMEOUT);
> +	if (ret < 0) {
> +		dev_err(tcphy->dev, "failed to wait TCPHY for DP ready\n");
> +		return -EBUSY;
> +	}
> +
> +	tcphy_dp_aux_calibration(tcphy);
> +
> +	if (tcphy->mode == MODE_DFP_USB3DP)
> +		writel(0xc101, tcphy->base + DP_MODE_CTL);
> +	else
> +		writel(0x0101, tcphy->base + DP_MODE_CTL);
> +
> +	ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
> +				 val, val & BIT(4), 1000, PHY_MODE_SET_TIMEOUT);
> +	if (ret < 0) {
> +		dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
> +		return -EBUSY;
> +	}
> +
> +	return 0;
> +}
> +
> +static int tcphy_phy_init(struct rockchip_typec_phy *tcphy)
> +{
> +	int ret;
> +	int timeout = 0;
> +
> +	ret = clk_prepare_enable(tcphy->clk_core);
> +	if (ret) {
> +		dev_err(tcphy->dev, "Failed to prepare_enable core clock\n");
> +		return ret;
> +	}
We need to init this clock to 50MHz here.
> +
> +	ret = clk_prepare_enable(tcphy->clk_ref);
> +	if (ret) {
> +		dev_err(tcphy->dev, "Failed to prepare_enable ref clock\n");
> +		return ret;
> +	}
> +
> +	/* select external psm clock */
> +	regmap_write(tcphy->grf_regs, tcphy->exregs.usb3phy_con2,
> +		     BIT(14) | BIT(30));
> +	regmap_write(tcphy->grf_regs, tcphy->exregs.usb3phy_con0, BIT(19));
> +
> +	reset_control_assert(tcphy->phy_rst);
> +	reset_control_assert(tcphy->pipe_rst);
> +	reset_control_assert(tcphy->uphy_rst);
> +
> +	if (tcphy->num == TYPEC_PHY0)
There is no code to init tcphy->num, we can add a dts node for it and
init in probe.
> +		regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
> +			     UPHY_DP_SEL_MASK);
> +	else
> +		regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
> +			     UPHY_DP_SEL_MASK | UPHY_DP_SEL);
> +
> +	reset_control_deassert(tcphy->uphy_rst);
> +
> +	tcphy_cfg_flip_set(tcphy);
> +
> +	tcphy_cfg_pin_assign(tcphy);
> +
> +	if (tcphy->mode == MODE_DFP_USB3DP)
> +		writel(0xc104, tcphy->base + DP_MODE_CTL);
> +	else if ((tcphy->mode == MODE_DFP_DPONLY) ||
> +		 (tcphy->mode == MODE_DFP_USB2DP))
> +		writel(0x0104, tcphy->base + DP_MODE_CTL);
> +
> +	reset_control_deassert(tcphy->phy_rst);
> +
> +	while (!(readl(tcphy->base + PMA_CMN_CTRL1) & 1)) {
> +		timeout++;
> +		if (timeout > 1000)
> +			break;
> +		usleep_range(10, 20);
> +	}
> +
> +	reset_control_deassert(tcphy->pipe_rst);
> +
> +	return 0;
> +}
> +
> +static int tcphy_phy_deinit(struct rockchip_typec_phy *tcphy)
> +{
> +	clk_disable_unprepare(tcphy->clk_core);
> +	clk_disable_unprepare(tcphy->clk_ref);
> +
> +	return 0;
> +}
> +
> +int tcphy_register_notifier(struct phy *_phy, struct notifier_block *nb)
> +{
> +	struct rockchip_typec_phy *tcphy = phy_get_drvdata(_phy);
> +
> +	return atomic_notifier_chain_register(&tcphy->notifier, nb);
> +}
> +
> +void tcphy_unregister_notifier(struct phy *_phy,
> +			       struct notifier_block *nb)
> +{
> +	struct rockchip_typec_phy *tcphy = phy_get_drvdata(_phy);
> +
> +	atomic_notifier_chain_unregister(&tcphy->notifier, nb);
> +}
> +
> +void tcphy_notifier_call_chain(struct rockchip_typec_phy *x,
> +			       unsigned long val, void *v)
> +{
> +	atomic_notifier_call_chain(&x->notifier, val, v);
> +}
> +EXPORT_SYMBOL_GPL(tcphy_notifier_call_chain);
Try to use extcon instead of create a notifier chain and other code later.

Thanks,
- Kever
> +
> +static int tcphy_pd_event(struct notifier_block *nb,
> +			  unsigned long event, void *priv)
> +{
> +	struct rockchip_typec_phy *tcphy;
> +	int value = *(int *)priv;
> +	u8 is_dp, dfp;
> +
> +	tcphy = container_of(nb, struct rockchip_typec_phy, event_nb);
> +	if (IS_ERR_OR_NULL(tcphy)) {
> +		pr_err("initialization issue");
> +		return -1;
> +	}
> +
> +	tcphy->flip = GET_FLIP(value);
> +	dfp = GET_DFP(value);
> +	is_dp = GET_DP(value);
> +	tcphy->map = GET_PIN_MAP(value);
> +
> +	if (event == 0) {
> +		if (tcphy->mode == MODE_DISCONNECT)
> +			return 0;
> +		tcphy->mode = MODE_DISCONNECT;
> +	} else if (is_dp) {
> +		if (tcphy->map & (PIN_MAP_B | PIN_MAP_D | PIN_MAP_F))
> +			tcphy->mode = MODE_DFP_USB3DP;
> +		else
> +			tcphy->mode = MODE_DFP_DPONLY;
> +	} else if (dfp) {
> +		tcphy->mode = MODE_DFP_USBONLY;
> +	} else {
> +		tcphy->mode = MODE_UFP;
> +	}
> +
> +	schedule_delayed_work_on(0, &tcphy->event_wq, 0);
> +
> +	return 0;
> +}
> +
> +static void tcphy_event_wq(struct work_struct *work)
> +{
> +	struct rockchip_typec_phy *tcphy;
> +
> +	tcphy = container_of(work, struct rockchip_typec_phy, event_wq.work);
> +	if (IS_ERR_OR_NULL(tcphy)) {
> +		pr_err("initialization issue");
> +		return;
> +	}
> +
> +	switch (tcphy->mode) {
> +	case MODE_DISCONNECT:
> +		/* phy enter low power mode */
> +		tcphy_phy_deinit(tcphy);
> +		tcphy_dp_hpd(tcphy, 0);
> +		break;
> +	case MODE_UFP:
> +		tcphy_phy_init(tcphy);
> +		tcphy_usb3_init(tcphy);
> +		tcphy_dp_hpd(tcphy, 0);
> +		break;
> +	case MODE_DFP_USBONLY:
> +		tcphy_phy_init(tcphy);
> +		tcphy_usb3_init(tcphy);
> +		tcphy_dp_hpd(tcphy, 0);
> +		break;
> +	case MODE_DFP_DPONLY:
> +	case MODE_DFP_USB2DP:
> +		tcphy_phy_init(tcphy);
> +		tcphy_dp_init(tcphy);
> +		tcphy_dp_hpd(tcphy, 1);
> +		break;
> +	case MODE_DFP_USB3DP:
> +		tcphy_phy_init(tcphy);
> +		tcphy_usb3_init(tcphy);
> +		tcphy_dp_init(tcphy);
> +		tcphy_dp_hpd(tcphy, 1);
> +		break;
> +	}
> +}
> +
> +int tcphy_parse_reg(struct rockchip_typec_phy *tcphy, struct device *dev)
> +{
> +	struct tcphy_grf_reg *exregs = &tcphy->exregs;
> +	struct device_node *np = dev->of_node;
> +	u32 len = 0, array[3];
> +	int ret = 0;
> +
> +	PARSE_GRF_REG(con0);
> +	PARSE_GRF_REG(con1);
> +	PARSE_GRF_REG(con2);
> +	PARSE_GRF_REG(status0);
> +	PARSE_GRF_REG(status1);
> +	return ret;
> +}
> +
> +static int rockchip_typec_phy_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct rockchip_typec_phy *tcphy;
> +	struct resource *res;
> +	struct phy_provider *phy_provider;
> +
> +	tcphy = devm_kzalloc(dev, sizeof(*tcphy), GFP_KERNEL);
> +	if (!tcphy)
> +		return -ENOMEM;
> +
> +	tcphy->dev = dev;
> +	platform_set_drvdata(pdev, tcphy);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	tcphy->base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(tcphy->base)) {
> +		dev_err(dev, "failed to remap phy regs\n");
> +		return PTR_ERR(tcphy->base);
> +	}
> +	tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node,
> +							"rockchip,grf");
> +	if (IS_ERR(tcphy->grf_regs)) {
> +		dev_err(dev, "%s: could not find grf dt node\n", __func__);
> +		return PTR_ERR(tcphy->grf_regs);
> +	}
> +
> +	tcphy->clk_core = of_clk_get_by_name(dev->of_node, "tcpdcore");
> +	if (IS_ERR(tcphy->clk_core)) {
> +		dev_err(dev, "%s: could not get uphy core clock\n", __func__);
> +		tcphy->clk_core = NULL;
> +	}
> +
> +	tcphy->clk_ref = of_clk_get_by_name(dev->of_node, "tcpdphy_ref");
> +	if (IS_ERR(tcphy->clk_core)) {
> +		dev_err(dev, "%s: could not get uphy ref clock\n", __func__);
> +		tcphy->clk_core = NULL;
> +	}
> +
> +	tcphy->phy_rst = devm_reset_control_get(dev, "tcphy_rst");
> +	if (IS_ERR(tcphy->phy_rst)) {
> +		dev_err(dev, "no phy_rst reset control found\n");
> +		return PTR_ERR(tcphy->phy_rst);
> +	}
> +
> +	tcphy->pipe_rst = devm_reset_control_get(dev, "tcphy_pipe_rst");
> +	if (IS_ERR(tcphy->pipe_rst)) {
> +		dev_err(dev, "no pipe_rst reset control found\n");
> +		return PTR_ERR(tcphy->pipe_rst);
> +	}
> +
> +	tcphy->uphy_rst = devm_reset_control_get(dev, "uphy_tcphy_rst");
> +	if (IS_ERR(tcphy->uphy_rst)) {
> +		dev_err(dev, "no uphy_rst reset control found\n");
> +		return PTR_ERR(tcphy->uphy_rst);
> +	}
> +
> +	tcphy_parse_reg(tcphy, dev);
> +	tcphy->mode = MODE_DISCONNECT;
> +
> +	tcphy->phy = devm_phy_create(dev, NULL, NULL);
> +
> +	phy_set_drvdata(tcphy->phy, tcphy);
> +
> +	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> +	/* register notifier for PD event */
> +	ATOMIC_INIT_NOTIFIER_HEAD(&tcphy->notifier);
> +	tcphy->event_nb.notifier_call = tcphy_pd_event;
> +	INIT_DELAYED_WORK(&tcphy->event_wq, tcphy_event_wq);
> +	tcphy_register_notifier(tcphy->phy, &tcphy->event_nb);
> +
> +	return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static int rockchip_typec_phy_remove(struct platform_device *pdev)
> +{
> +	return 0;
> +}
> +
> +static const struct of_device_id rockchip_typec_phy_dt_ids[] = {
> +	{ .compatible = "rockchip,rk3399-typec-phy", },
> +	{}
> +};
> +
> +MODULE_DEVICE_TABLE(of, rockchip_typec_phy_dt_ids);
> +
> +static struct platform_driver rockchip_typec_phy_driver = {
> +	.probe		= rockchip_typec_phy_probe,
> +	.remove		= rockchip_typec_phy_remove,
> +	.driver		= {
> +		.name	= "rockchip-typec-phy",
> +		.of_match_table = rockchip_typec_phy_dt_ids,
> +	},
> +};
> +
> +module_platform_driver(rockchip_typec_phy_driver);
> +
> +MODULE_AUTHOR("Kever Yang<kever.yang at rock-chips.com>");
> +MODULE_AUTHOR("Chris Zhong<zyw at rock-chips.com>");
> +MODULE_DESCRIPTION("Rockchip USB TYPE-C PHY driver");
> +MODULE_LICENSE("GPL v2");




From narmstrong at baylibre.com  Fri May 27 01:17:51 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 27 May 2016 10:17:51 +0200
Subject: [RFC PATCH 0/2] scpi: Add SCPI framework to handle vendors
 variants
In-Reply-To: <57472450.4000709@arm.com>
References: <1464255491-18503-1-git-send-email-narmstrong@baylibre.com>
 <57472450.4000709@arm.com>
Message-ID: <574802AF.2080909@baylibre.com>

Hi,
On 05/26/2016 06:29 PM, Sudeep Holla wrote:
> Hi Neil,
> 
> On 26/05/16 10:38, Neil Armstrong wrote:
>> Since the current SCPI implementation, based on [0]:
>> - is (at leat) JUNO specific
> 
> Agreed.
> 
>> - does not specify a strong "standard"
> 
> Not exactly, it's extensible. Refer section 3.2.2. Get SCP capability
> Extended Set Enabled bit.

Well, I was not thinking about an extension, but this should be upstreamed for sure.

> 
>> - does not specify a strong MHU interface specification
>>
> 
> Not really required, any mailbox must do.
> 
>> SoC vendors could implement a variant with slight changes in message
>> indexes,
> 
> I assume you mean command index here
> 
>> new messages types,
> 
> Also fine with extended command set.
> 
>> different messages data format or
> 
> you mean the header or payload ? If they don't follow the header, then
> how can be group them as same protocol ?
> 
>> different MHU communication scheme.
> 
> Not a problem as I mentioned above.
> 
>>
>> To keep the spirit of the SCPI interface, add a thin "register" layer to get
>> the ops from the parent node and switch the drivers using the ops to use
>> the new of_scpi_ops_get() call.
>>
> 
> All I can see is that you share the code to register such drivers which
> is hardly anything. It's hard to say all drivers use same protocol or
> interface after this change. I may be missing to see something here so
> it would be easy to appreciate/review this change with one user of this.

I'm actually working on an "SCPI" implementation from Amlogic for their arm64 plaform,
and their implementation is slightly different but enough to need a separate driver.

For instance, the differences are :
- they do not implement virtual channels
- they pass the command word by the mailbox interface
- they use the "sender id" to group the command in a sort of "class"
- the payload size is shifted by 20 instead of 16
- the command word is not in the SRAM, so we cannot use a rx command queue, only a single command by channel at a single time
- the command indexes are slightly shifted
- in clk_set_value, "rate" is first instead of last entry
- in sensor_value, they only use a 32bit entry
- some commands are only accepted on the high priority channel, the others only on the low priority
- MAX_DVFS_DOMAINS is 3 instead of 8
- MAX_DVFS_OPPS is 16 instead of 8

But, It's still a "SCPI" interface by design and usage because :
- they implement 90% of the same commands, in the same way
- the usage is exactly the same and architecture is similar
- they use the same error code scheme

Finally, it would be stupid to add an exact copy of the scpi-sensors and scpi-clocks !
The scpi-cpufreq is another story since they only have a single A53 cluster, it's not adapted.

This is why I wrote a very thin layer, and it can also clean up the arm_scpi and the scpi driver to use a cleaner registry interface.
It would also be a good point to add a private_data to the ops and pass it to the scpi callbacks, to completely remove the global variables.

I found an issue with scpi-cpufreq, since the device is created by the scpi-clocks probe, it does not have a proper node and my current of_scpi_ops_get won't work...
The scpi-cpufreq should have a proper DT node and use the deffered probe to register after the scpi-clocks.

> 
> My idea of extending this driver if vendor implements extensions based
> on SCPI specification is something like below:
> 

Neil


From narmstrong at baylibre.com  Fri May 27 01:22:07 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 27 May 2016 10:22:07 +0200
Subject: [RFC PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <20160526100655.GB14703@mephisto>
References: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
 <1464249112-13658-2-git-send-email-narmstrong@baylibre.com>
 <20160526100655.GB14703@mephisto>
Message-ID: <574803AF.5020409@baylibre.com>

On 05/26/2016 12:06 PM, Carlo Caione wrote:
> On 26/05/16 09:51, Neil Armstrong wrote:
>> Add watchdog specific driver for Amlogic Meson GXBB SoC.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> +
> 
> [...]
>> +#define DEFAULT_TIMEOUT	10	/* seconds */
>> +
>> +#define GXBB_WDT_CTRL_REG	0x0
>> +#define GXBB_WDT_CTRL1_REG	0x4
>> +#define GXBB_WDT_TCNT_REG	0x8
>> +#define GXBB_WDT_RSET_REG	0xc
>> +
>> +#define GXBB_WDT_CTRL_EE_RESET_NOW	BIT(26)
>> +
>> +#define GXBB_WDT_CTRL_CLKDIV_EN	BIT(25)
>> +#define GXBB_WDT_CTRL_CLK_EN	BIT(24)
>> +#define GXBB_WDT_CTRL_IRQ_EN	BIT(23)
>> +#define GXBB_WDT_CTRL_EE_RESET	BIT(21)
>> +#define GXBB_WDT_CTRL_XTAL_SEL	(0)
>> +#define GXBB_WDT_CTRL_CLK81_SEL	BIT(19)
>> +#define GXBB_WDT_CTRL_EN	BIT(18)
>> +#define GXBB_WDT_CTRL_DIV_MASK	(BIT(18)-1)
>> +
>> +#define GXBB_WDT_CTRL1_GPIO_PULSE	BIT(17)
>> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_0	BIT(16)
>> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_1	(0)
>> +#define GXBB_WDT_CTRL1_GPIO_PULSE_CNT	(BIT(16)-1)
>> +
>> +#define GXBB_WDT_TCNT_SETUP_MASK	(BIT(16)-1)
>> +#define GXBB_WDT_TCNT_CNT_SHIFT		16
> 
> Indentation
> 
> [...]
>> +int meson_gxbb_wdt_set_timeout(struct watchdog_device *wdt_dev,
>> +			       unsigned int timeout)
>> +{
>> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
>> +
>> +	if (watchdog_active(wdt_dev))
>> +		meson_gxbb_wdt_stop(wdt_dev);
>> +
>> +	meson_gxbb_wdt_ping(wdt_dev);
>> +
>> +	writel(timeout*1000, data->reg_base + GXBB_WDT_TCNT_REG);
> 
> nit: spaces around "*"
> 
> [...]
>> +	data->clk = devm_clk_get(&pdev->dev, NULL);
>> +	if (IS_ERR(data->clk))
>> +		return PTR_ERR(data->clk);
>> +
>> +	clk_prepare_enable(data->clk);
> 
> Do we need to merge the clock controller driver before this?

It's not necessary, currently it only selects the xtal source, so it's works with the current upstream architecture.

Neil

> 
> Cheers,
> 



From wxt at rock-chips.com  Fri May 27 01:23:24 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri, 27 May 2016 16:23:24 +0800
Subject: [PATCH v4 0/4] Thermal: Support for hardware-tracked trip points
Message-ID: <1464337408-7123-1-git-send-email-wxt@rock-chips.com>

The history patches come from Mikko and Sascha.
    http://thread.gmane.org/gmane.linux.power-management.general/59451

Now, I pick them up to continue upstream.
Nevermind!

This series history patches:
v3: https://lkml.org/lkml/2016/5/24/797
v2: https://lkml.org/lkml/2016/5/3/220
v1: https://lkml.org/lkml/2016/4/24/227

This series adds support for hardware trip points. It picks up earlier
work from Mikko Perttunen. Mikko implemented hardware trip points as part
of the device tree support. It was suggested back then to move the
functionality to the thermal core instead of putting more code into the
device tree support. This series does exactly that.

This series patches rebase the conflicts.
Note that the hardware-tracked trip points are very well tested currently.

Verified and tested on https://github.com/Caesar-github/rockchip/tree/wip/fixes-thermal-0525
That's based on linux-kernel 20160524.


Changes in v4:
- as the Javi comments, %s/implemnets/implements.

Changes in v3:
- as the Javi comments on https://patchwork.kernel.org/patch/9001311/.
- add the select if they set the option for devicetree.
- Add the peter's ACK.

Changes in v2:
- add the commit in patch[v2 2/5].
- Update the commit for patch[v2 4/5].

Caesar Wang (1):
  thermal: rockchip: add the set_trips function

Sascha Hauer (3):
  thermal: of: implement .set_trips for device tree thermal zones
  thermal: streamline get_trend callbacks
  thermal: bang-bang governor: act on lower trip boundary

 drivers/thermal/gov_bang_bang.c                    |  2 +-
 drivers/thermal/of-thermal.c                       | 30 +++++++++++------
 drivers/thermal/rockchip_thermal.c                 | 39 ++++++++++++++++++++++
 drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 25 +++++---------
 include/linux/thermal.h                            |  6 +++-
 5 files changed, 73 insertions(+), 29 deletions(-)

-- 
1.9.1



From wxt at rock-chips.com  Fri May 27 01:23:28 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri, 27 May 2016 16:23:28 +0800
Subject: [PATCH v4 4/4] thermal: rockchip: add the set_trips function
In-Reply-To: <1464337408-7123-1-git-send-email-wxt@rock-chips.com>
References: <1464337408-7123-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1464337408-7123-5-git-send-email-wxt@rock-chips.com>

Whenever the current temperature is updated, the trip points immediately
below and above the current temperature are found. A sensor driver
callback `set_trips' is then called with the temperatures.
Lastly, The sensor will trigger the hardware high temperature interrupts
to increase the sampleing rate and throttle frequency to limit the
temperature rising When performing passive cooling.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Zhang Rui <rui.zhang at intel.com>
Cc: Eduardo Valentin <edubezval at gmail.com>
Cc: linux-pm at vger.kernel.org

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/thermal/rockchip_thermal.c | 39 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index 86a1ab0..39e2eec 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -96,6 +96,7 @@ struct chip_tsadc_table {
  * @initialize: SoC special initialize tsadc controller method
  * @irq_ack: clear the interrupt
  * @get_temp: get the temperature
+ * @set_alarm_temp: set the high temperature interrupt
  * @set_tshut_temp: set the hardware-controlled shutdown temperature
  * @set_tshut_mode: set the hardware-controlled shutdown mode
  * @table: the chip-specific conversion table
@@ -119,6 +120,8 @@ struct rockchip_tsadc_chip {
 	/* Per-sensor methods */
 	int (*get_temp)(struct chip_tsadc_table table,
 			int chn, void __iomem *reg, int *temp);
+	void (*set_alarm_temp)(struct chip_tsadc_table table,
+			       int chn, void __iomem *reg, int temp);
 	void (*set_tshut_temp)(struct chip_tsadc_table table,
 			       int chn, void __iomem *reg, int temp);
 	void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
@@ -183,6 +186,7 @@ struct rockchip_thermal_data {
 #define TSADCV2_INT_EN				0x08
 #define TSADCV2_INT_PD				0x0c
 #define TSADCV2_DATA(chn)			(0x20 + (chn) * 0x04)
+#define TSADCV2_COMP_INT(chn)		        (0x30 + (chn) * 0x04)
 #define TSADCV2_COMP_SHUT(chn)		        (0x40 + (chn) * 0x04)
 #define TSADCV2_HIGHT_INT_DEBOUNCE		0x60
 #define TSADCV2_HIGHT_TSHUT_DEBOUNCE		0x64
@@ -628,6 +632,20 @@ static int rk_tsadcv2_get_temp(struct chip_tsadc_table table,
 	return rk_tsadcv2_code_to_temp(table, val, temp);
 }
 
+static void rk_tsadcv2_alarm_temp(struct chip_tsadc_table table,
+				  int chn, void __iomem *regs, int temp)
+{
+	u32 alarm_value, int_en;
+
+	alarm_value = rk_tsadcv2_temp_to_code(table, temp);
+	writel_relaxed(alarm_value & table.data_mask,
+		       regs + TSADCV2_COMP_INT(chn));
+
+	int_en = readl_relaxed(regs + TSADCV2_INT_EN);
+	int_en |= TSADCV2_INT_SRC_EN(chn);
+	writel_relaxed(int_en, regs + TSADCV2_INT_EN);
+}
+
 static void rk_tsadcv2_tshut_temp(struct chip_tsadc_table table,
 				  int chn, void __iomem *regs, int temp)
 {
@@ -670,6 +688,7 @@ static const struct rockchip_tsadc_chip rk3228_tsadc_data = {
 	.irq_ack = rk_tsadcv3_irq_ack,
 	.control = rk_tsadcv3_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -694,6 +713,7 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
 	.irq_ack = rk_tsadcv2_irq_ack,
 	.control = rk_tsadcv2_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -718,6 +738,7 @@ static const struct rockchip_tsadc_chip rk3366_tsadc_data = {
 	.irq_ack = rk_tsadcv3_irq_ack,
 	.control = rk_tsadcv3_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -742,6 +763,7 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = {
 	.irq_ack = rk_tsadcv2_irq_ack,
 	.control = rk_tsadcv2_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -766,6 +788,7 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
 	.irq_ack = rk_tsadcv3_irq_ack,
 	.control = rk_tsadcv3_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -826,6 +849,21 @@ static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
+static int rockchip_thermal_set_trips(void *_sensor, int low, int high)
+{
+	struct rockchip_thermal_sensor *sensor = _sensor;
+	struct rockchip_thermal_data *thermal = sensor->thermal;
+	const struct rockchip_tsadc_chip *tsadc = thermal->chip;
+
+	dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n",
+		__func__, sensor->id, low, high);
+
+	tsadc->set_alarm_temp(tsadc->table,
+			      sensor->id, thermal->regs, high);
+
+	return 0;
+}
+
 static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
 {
 	struct rockchip_thermal_sensor *sensor = _sensor;
@@ -843,6 +881,7 @@ static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
 
 static const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = {
 	.get_temp = rockchip_thermal_get_temp,
+	.set_trips = rockchip_thermal_set_trips,
 };
 
 static int rockchip_configure_from_dt(struct device *dev,
-- 
1.9.1



From narmstrong at baylibre.com  Fri May 27 01:25:20 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 27 May 2016 10:25:20 +0200
Subject: [RFC PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <57470026.3000501@roeck-us.net>
References: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
 <1464249112-13658-2-git-send-email-narmstrong@baylibre.com>
 <57470026.3000501@roeck-us.net>
Message-ID: <57480470.4000708@baylibre.com>

On 05/26/2016 03:54 PM, Guenter Roeck wrote:
> On 05/26/2016 12:51 AM, Neil Armstrong wrote:
>> Add watchdog specific driver for Amlogic Meson GXBB SoC.
>>
> 
> Wondering - why RFC ?

For these precious comments !
Thanks Guenter.

> 
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> ---
>>   drivers/watchdog/Makefile         |   1 +
>>   drivers/watchdog/meson_gxbb_wdt.c | 287 ++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 288 insertions(+)
>>   create mode 100644 drivers/watchdog/meson_gxbb_wdt.c
>>
>> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
>> index 9bde095..7679d93 100644
>> --- a/drivers/watchdog/Makefile
>> +++ b/drivers/watchdog/Makefile

[...]

>> +
>> +unsigned int meson_gxbb_wdt_status(struct watchdog_device *wdt_dev)
>> +{
>> +    struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
>> +
>> +    return !!(readl(data->reg_base + GXBB_WDT_CTRL_REG) & GXBB_WDT_CTRL_EN);
> 
> This function is not supposed to return 0/1 but a bit mask with relevant
> WDIOF_bits set. sbsa_gwdt.c is buggy (oops, and I reviewed it ;-), so
> please don't use it as example; it doesn't make much sense to return
> a kernel-only flag to user space.
> 
> Overall I would suggest to not implement the function at all. We'll have
> to revisit it - its current implementation in the watchdog core does not
> make much sense and for the most part only returns 0 to user space.
> The only driver implementing it (sbsa) returns a bad value. It is also
> _not_ supposed to return the "watchdog running" status as currently
> implemented (there is no WDIOF_ flag indicating that the watchdog is
> running).

Ok, will remove it.

>> +}
>> +
>> +int meson_gxbb_wdt_ping(struct watchdog_device *wdt_dev)
>> +{
>> +    struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
>> +
>> +    writel(0, data->reg_base + GXBB_WDT_RSET_REG);
>> +
>> +    return 0;
>> +}
>> +
>> +int meson_gxbb_wdt_set_timeout(struct watchdog_device *wdt_dev,
>> +                   unsigned int timeout)
>> +{
>> +    struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
>> +
>> +    if (watchdog_active(wdt_dev))
>> +        meson_gxbb_wdt_stop(wdt_dev);
>> +
> 
> Is the stop/start sequence mandatory ? It leaves the system unprotected
> for a few cycles, so it is undesirable.

No, it's not mandatory, it's a good point.

>> +
>> +    data->wdt_dev.parent = &pdev->dev;
>> +    data->wdt_dev.info = &meson_gxbb_wdt_info;
>> +    data->wdt_dev.ops = &meson_gxbb_wdt_ops;
>> +    data->wdt_dev.max_hw_heartbeat_ms = GXBB_WDT_TCNT_SETUP_MASK;
>> +    data->wdt_dev.min_hw_heartbeat_ms = 1;
> 
> Does the device require a minimum time between heartbeats ?
> Just asking, because you violate it yourself below.
> 
> If you want to set the minimum timeout, that would be min_timeout.

Ok, these values are not very clear actually.

>> +    data->wdt_dev.timeout = DEFAULT_TIMEOUT;
>> +    watchdog_set_drvdata(&data->wdt_dev, data);
>> +
>> +    watchdog_init_timeout(&data->wdt_dev, DEFAULT_TIMEOUT, &pdev->dev);
>> +
> 
> DEFAULT_TIMEOUT is unnecessary here. Since the default timeout is already set,
> it makes the call useless.
> 
>> +    ret = watchdog_register_device(&data->wdt_dev);
>> +    if (ret)
>> +        return ret;
>> +
>> +    /* Setup with 1ms timebase */
>> +    writel(((clk_get_rate(data->clk) / 1000) & GXBB_WDT_CTRL_DIV_MASK) |
>> +        GXBB_WDT_CTRL_EE_RESET |
>> +        GXBB_WDT_CTRL_CLK_EN |
>> +        GXBB_WDT_CTRL_CLKDIV_EN,
>> +        data->reg_base + GXBB_WDT_CTRL_REG);
>> +    meson_gxbb_wdt_set_timeout(&data->wdt_dev, data->wdt_dev.timeout);
> 
> set_timeout already calls the ping function. Also, the functions should be called
> prior to watchdog registration to avoid race conditions.
> 
>> +    meson_gxbb_wdt_ping(&data->wdt_dev);
> 
> This is unusual. If the watchdog can be already running, it might make sense
> to tell the core about it (set WDOG_HW_RUNNING in the status field), so it
> can send heartbeats until user space opens the device.

Yes, since meson_gxbb_wdt_set_timeout() already ping, this is useless.



From heiko at sntech.de  Fri May 27 01:29:57 2016
From: heiko at sntech.de (Heiko Stuebner)
Date: Fri, 27 May 2016 10:29:57 +0200
Subject: [PATCH 2/6] Documentation: bindings: add dt doc for Rockchip USB
 Type-C PHY
In-Reply-To: <1464328939-8073-3-git-send-email-zyw@rock-chips.com>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
 <1464328939-8073-3-git-send-email-zyw@rock-chips.com>
Message-ID: <2812026.ptEv4ktvbn@phil>

Hi Chris,

Am Freitag, 27. Mai 2016, 14:02:15 schrieb Chris Zhong:
> This patch adds a binding that describes the Rockchip USB Type-C PHY
> for rk3399.
> 
> Signed-off-by: Chris Zhong <zyw at rock-chips.com>
> ---
> 
>  .../devicetree/bindings/phy/phy-rockchip-typec.txt | 55
> ++++++++++++++++++++++ 1 file changed, 55 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
> 
> diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
> b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt new file
> mode 100644
> index 0000000..402f667
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
> @@ -0,0 +1,55 @@
> +ROCKCHIP type-c PHY
> +
> +Required properties:
> + - compatible: should be "rockchip,rk3399-typec-phy"
> + - reg : Address and length of the usb phy control register set
> + - rockchip,grf : phandle to the syscon managing the "general
> +   register files"
> + - clocks : phandle + clock specifier for the phy clocks
> + - clock-names: string, clock name, must be "tcpdcore", "tcpdphy_ref";
> + - resets : a list of phandle + reset specifier pairs
> + - reset-names : string reset name, must be:
> +		 "tcphy_rst", "tcphy_pipe_rst", "uphy_tcphy_rst"
> + - #phy-cells: Must be 0.  See ./phy-bindings.txt for details.
> + - rockchip,usb3phy*: phy registers embed in grf
> +
> +Example:
> +	tcphy0: phy at ff7c0000 {
> +		compatible = "rockchip,rk3399-typec-phy";
> +		reg = <0x0 0xff7c0000 0x0 0x40000>;
> +		#phy-cells = <0>;
> +		rockchip,grf = <&grf>;
> +		clocks = <&cru SCLK_UPHY0_TCPDCORE>,
> +			 <&cru SCLK_UPHY0_TCPDPHY_REF>;
> +		clock-names = "tcpdcore", "tcpdphy_ref";
> +		resets = <&cru SRST_UPHY0>,
> +			 <&cru SRST_UPHY0_PIPE_L00>,
> +			 <&cru SRST_P_UPHY0_TCPHY>;
> +		reset-names = "tcphy_rst", "tcphy_pipe_rst", "uphy_tcphy_rst";
> +		rockchip,usb3phy_con0 = <0x0e580 0 16>;
> +		rockchip,usb3phy_con1 = <0x0e584 0 16>;
> +		rockchip,usb3phy_con2 = <0x0e588 0 16>;
> +		rockchip,usb3phy_status0 = <0x0e5c0 0 13>;
> +		rockchip,usb3phy_status1 = <0x0e5c4 0 12>;

please embedded this register data in the driver instead (not in the 
devicetree), matched against the compatible value.
See Frank's usb2phy driver for reference if needed.


Thanks
Heiko



From arnd at arndb.de  Fri May 27 01:31:55 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 27 May 2016 10:31:55 +0200
Subject: [PATCH v3 4/4] soc: Add SoC driver for Freescale Vybrid platform
In-Reply-To: <20160527063301.GB1554@Sanchayan-Arch.localdomain>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
 <CAL_JsqKCwy=aXveTfnaQuZ5b3Ld9nzABgPfdPm1JX3CBuvzG+Q@mail.gmail.com>
 <20160527063301.GB1554@Sanchayan-Arch.localdomain>
Message-ID: <9495361.v6aft1QR0M@wuerfel>

On Friday, May 27, 2016 12:03:01 PM CEST maitysanchayan at gmail.com wrote:
> 
> So if I understand correctly, the binding at the SoC level is fine.
> Keeping that but removing the additional made-up properties, viz. below
> 
> rom-revision: phandle to the on-chip ROM node
> mscm: phandle to the MSCM CPU configuration node
> nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
> nvmem-cell-names: should contain string names "cfg0" and "cfg1"
> 
> would be fine?
> 
> We would have something similar to here
> http://www.spinics.net/lists/devicetree/msg80655.html
> 
> but now with the DT binding under SoC bus.
> 


You look up the OTP device as a syscon here, which seems odd since there
is already an nvmem driver for it. Shouldn't you use the nvmem API for
that?

	Arnd


From wxt at rock-chips.com  Fri May 27 01:36:48 2016
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri, 27 May 2016 16:36:48 +0800
Subject: [RESEND PATCH v4 5/5] thermal: rockchip: add the set_trips function
In-Reply-To: <1464338208-8105-1-git-send-email-wxt@rock-chips.com>
References: <1464338208-8105-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1464338208-8105-6-git-send-email-wxt@rock-chips.com>

Whenever the current temperature is updated, the trip points immediately
below and above the current temperature are found. A sensor driver
callback `set_trips' is then called with the temperatures.
Lastly, The sensor will trigger the hardware high temperature interrupts
to increase the sampleing rate and throttle frequency to limit the
temperature rising When performing passive cooling.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Cc: Zhang Rui <rui.zhang at intel.com>
Cc: Eduardo Valentin <edubezval at gmail.com>
Cc: linux-pm at vger.kernel.org

---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/thermal/rockchip_thermal.c | 39 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index 86a1ab0..39e2eec 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -96,6 +96,7 @@ struct chip_tsadc_table {
  * @initialize: SoC special initialize tsadc controller method
  * @irq_ack: clear the interrupt
  * @get_temp: get the temperature
+ * @set_alarm_temp: set the high temperature interrupt
  * @set_tshut_temp: set the hardware-controlled shutdown temperature
  * @set_tshut_mode: set the hardware-controlled shutdown mode
  * @table: the chip-specific conversion table
@@ -119,6 +120,8 @@ struct rockchip_tsadc_chip {
 	/* Per-sensor methods */
 	int (*get_temp)(struct chip_tsadc_table table,
 			int chn, void __iomem *reg, int *temp);
+	void (*set_alarm_temp)(struct chip_tsadc_table table,
+			       int chn, void __iomem *reg, int temp);
 	void (*set_tshut_temp)(struct chip_tsadc_table table,
 			       int chn, void __iomem *reg, int temp);
 	void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
@@ -183,6 +186,7 @@ struct rockchip_thermal_data {
 #define TSADCV2_INT_EN				0x08
 #define TSADCV2_INT_PD				0x0c
 #define TSADCV2_DATA(chn)			(0x20 + (chn) * 0x04)
+#define TSADCV2_COMP_INT(chn)		        (0x30 + (chn) * 0x04)
 #define TSADCV2_COMP_SHUT(chn)		        (0x40 + (chn) * 0x04)
 #define TSADCV2_HIGHT_INT_DEBOUNCE		0x60
 #define TSADCV2_HIGHT_TSHUT_DEBOUNCE		0x64
@@ -628,6 +632,20 @@ static int rk_tsadcv2_get_temp(struct chip_tsadc_table table,
 	return rk_tsadcv2_code_to_temp(table, val, temp);
 }
 
+static void rk_tsadcv2_alarm_temp(struct chip_tsadc_table table,
+				  int chn, void __iomem *regs, int temp)
+{
+	u32 alarm_value, int_en;
+
+	alarm_value = rk_tsadcv2_temp_to_code(table, temp);
+	writel_relaxed(alarm_value & table.data_mask,
+		       regs + TSADCV2_COMP_INT(chn));
+
+	int_en = readl_relaxed(regs + TSADCV2_INT_EN);
+	int_en |= TSADCV2_INT_SRC_EN(chn);
+	writel_relaxed(int_en, regs + TSADCV2_INT_EN);
+}
+
 static void rk_tsadcv2_tshut_temp(struct chip_tsadc_table table,
 				  int chn, void __iomem *regs, int temp)
 {
@@ -670,6 +688,7 @@ static const struct rockchip_tsadc_chip rk3228_tsadc_data = {
 	.irq_ack = rk_tsadcv3_irq_ack,
 	.control = rk_tsadcv3_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -694,6 +713,7 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
 	.irq_ack = rk_tsadcv2_irq_ack,
 	.control = rk_tsadcv2_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -718,6 +738,7 @@ static const struct rockchip_tsadc_chip rk3366_tsadc_data = {
 	.irq_ack = rk_tsadcv3_irq_ack,
 	.control = rk_tsadcv3_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -742,6 +763,7 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = {
 	.irq_ack = rk_tsadcv2_irq_ack,
 	.control = rk_tsadcv2_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -766,6 +788,7 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
 	.irq_ack = rk_tsadcv3_irq_ack,
 	.control = rk_tsadcv3_control,
 	.get_temp = rk_tsadcv2_get_temp,
+	.set_alarm_temp = rk_tsadcv2_alarm_temp,
 	.set_tshut_temp = rk_tsadcv2_tshut_temp,
 	.set_tshut_mode = rk_tsadcv2_tshut_mode,
 
@@ -826,6 +849,21 @@ static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
+static int rockchip_thermal_set_trips(void *_sensor, int low, int high)
+{
+	struct rockchip_thermal_sensor *sensor = _sensor;
+	struct rockchip_thermal_data *thermal = sensor->thermal;
+	const struct rockchip_tsadc_chip *tsadc = thermal->chip;
+
+	dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n",
+		__func__, sensor->id, low, high);
+
+	tsadc->set_alarm_temp(tsadc->table,
+			      sensor->id, thermal->regs, high);
+
+	return 0;
+}
+
 static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
 {
 	struct rockchip_thermal_sensor *sensor = _sensor;
@@ -843,6 +881,7 @@ static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
 
 static const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = {
 	.get_temp = rockchip_thermal_get_temp,
+	.set_trips = rockchip_thermal_set_trips,
 };
 
 static int rockchip_configure_from_dt(struct device *dev,
-- 
1.9.1



From caesar.upstream at gmail.com  Fri May 27 01:41:59 2016
From: caesar.upstream at gmail.com (Caesar Wang)
Date: Fri, 27 May 2016 16:41:59 +0800
Subject: [PATCH v4 0/4] Thermal: Support for hardware-tracked trip points
In-Reply-To: <1464337408-7123-1-git-send-email-wxt@rock-chips.com>
References: <1464337408-7123-1-git-send-email-wxt@rock-chips.com>
Message-ID: <57480857.4070904@gmail.com>

Forget to send a patch, sorry for the noise.:-(
Please ignore this series patches [PATCH v4 0/4].

RESEND the new series patches "[RESEND PATCH v4 0/5]".

On 2016?05?27? 16:23, Caesar Wang wrote:
> The history patches come from Mikko and Sascha.
>      http://thread.gmane.org/gmane.linux.power-management.general/59451
>
> Now, I pick them up to continue upstream.
> Nevermind!
>
> This series history patches:
> v3: https://lkml.org/lkml/2016/5/24/797
> v2: https://lkml.org/lkml/2016/5/3/220
> v1: https://lkml.org/lkml/2016/4/24/227
>
> This series adds support for hardware trip points. It picks up earlier
> work from Mikko Perttunen. Mikko implemented hardware trip points as part
> of the device tree support. It was suggested back then to move the
> functionality to the thermal core instead of putting more code into the
> device tree support. This series does exactly that.
>
> This series patches rebase the conflicts.
> Note that the hardware-tracked trip points are very well tested currently.
>
> Verified and tested on https://github.com/Caesar-github/rockchip/tree/wip/fixes-thermal-0525
> That's based on linux-kernel 20160524.
>
>
> Changes in v4:
> - as the Javi comments, %s/implemnets/implements.
>
> Changes in v3:
> - as the Javi comments on https://patchwork.kernel.org/patch/9001311/.
> - add the select if they set the option for devicetree.
> - Add the peter's ACK.
>
> Changes in v2:
> - add the commit in patch[v2 2/5].
> - Update the commit for patch[v2 4/5].
>
> Caesar Wang (1):
>    thermal: rockchip: add the set_trips function
>
> Sascha Hauer (3):
>    thermal: of: implement .set_trips for device tree thermal zones
>    thermal: streamline get_trend callbacks
>    thermal: bang-bang governor: act on lower trip boundary
>
>   drivers/thermal/gov_bang_bang.c                    |  2 +-
>   drivers/thermal/of-thermal.c                       | 30 +++++++++++------
>   drivers/thermal/rockchip_thermal.c                 | 39 ++++++++++++++++++++++
>   drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 25 +++++---------
>   include/linux/thermal.h                            |  6 +++-
>   5 files changed, 73 insertions(+), 29 deletions(-)
>



From k.kozlowski at samsung.com  Fri May 27 01:42:29 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Fri, 27 May 2016 10:42:29 +0200
Subject: [PATCH] pinctrl: samsung: Suppress unbinding to prevent
 theoretical attacks
In-Reply-To: <CACRpkdYdo5XsJvb9GTYph7P=u31treiDX6HZGbG_AGzW5hp1HQ@mail.gmail.com>
References: <1463464926-17482-1-git-send-email-k.kozlowski@samsung.com>
 <CACRpkdYdo5XsJvb9GTYph7P=u31treiDX6HZGbG_AGzW5hp1HQ@mail.gmail.com>
Message-ID: <57480875.2040502@samsung.com>

On 05/26/2016 11:08 AM, Linus Walleij wrote:
> On Tue, May 17, 2016 at 8:02 AM, Krzysztof Kozlowski
> <k.kozlowski at samsung.com> wrote:
> 
>> Although unbinding a pinctrl driver requires root privileges but it
>> still might be used theoretically in certain attacks (by triggering NULL
>> pointer exception or memory corruption).
> 
> Patch applied with Javier's review tag.
> 
> I suspect this kind of patch should be done to a few
> GPIO controller :/

Probably yes... Either the driver properly and safely handles unbind
(remove() callback) or it should be forbidden. In the same time, even if
remove() is implemented, unbinding some of the core SoC drivers is like
shooting self in the foot.

Best regards,
Krzysztof


From arnd at arndb.de  Fri May 27 01:42:59 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 27 May 2016 10:42:59 +0200
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160527060357.GB3820@osiris>
References: <6293194.tGy03QJ9ME@wuerfel> <20160527003753.GA14247@yury-N73SV>
 <20160527060357.GB3820@osiris>
Message-ID: <13240365.okADkKsTBJ@wuerfel>

On Friday, May 27, 2016 8:03:57 AM CEST Heiko Carstens wrote:
> > > > > Cost wise, this seems like it all cancels out in the end, but what
> > > > > do I know?
> > > > 
> > > > I think you know something, and I also think Heiko and other s390 guys
> > > > know something as well. So I'd like to listen their arguments here.
> 
> If it comes to 64 bit arguments for compat system calls: s390 also has an
> x32-like ABI extension which allows user space to use full 64 bit
> registers. As far as I know hardly anybody ever made use of that.
> 
> However even if that would be widely used, to me it wouldn't make sense to
> add new compat system calls which allow 64 bit arguments, simply because
> something like
> 
> c = (u32)a | (u64)b << 32;
> 
> can be done with a single 1-cycle instruction. It's just not worth the
> extra effort to maintain additional system call variants.

For reference, both tile and mips also have separate 32-bit ABIs that are
only used on 64-bit kernels (aside from the normal 32-bit ABI). Tile
does it like s390 and passes 64-bit arguments as pairs, while MIPS
and x86 and pass them as single registers.

Tile is very similar to arm64 because it also uses the generic system
call table, which I think is a good argument to keep them in sync.

	Arnd


From zyw at rock-chips.com  Fri May 27 01:46:07 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 16:46:07 +0800
Subject: [PATCH 2/6] Documentation: bindings: add dt doc for Rockchip USB
 Type-C PHY
In-Reply-To: <2812026.ptEv4ktvbn@phil>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
 <1464328939-8073-3-git-send-email-zyw@rock-chips.com>
 <2812026.ptEv4ktvbn@phil>
Message-ID: <5748094F.6030204@rock-chips.com>

Hi Heiko

On 05/27/2016 04:29 PM, Heiko Stuebner wrote:
> Hi Chris,
>
> Am Freitag, 27. Mai 2016, 14:02:15 schrieb Chris Zhong:
>> This patch adds a binding that describes the Rockchip USB Type-C PHY
>> for rk3399.
>>
>> Signed-off-by: Chris Zhong <zyw at rock-chips.com>
>> ---
>>
>>   .../devicetree/bindings/phy/phy-rockchip-typec.txt | 55
>> ++++++++++++++++++++++ 1 file changed, 55 insertions(+)
>>   create mode 100644
>> Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
>>
>> diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
>> b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt new file
>> mode 100644
>> index 0000000..402f667
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
>> @@ -0,0 +1,55 @@
>> +ROCKCHIP type-c PHY
>> +
>> +Required properties:
>> + - compatible: should be "rockchip,rk3399-typec-phy"
>> + - reg : Address and length of the usb phy control register set
>> + - rockchip,grf : phandle to the syscon managing the "general
>> +   register files"
>> + - clocks : phandle + clock specifier for the phy clocks
>> + - clock-names: string, clock name, must be "tcpdcore", "tcpdphy_ref";
>> + - resets : a list of phandle + reset specifier pairs
>> + - reset-names : string reset name, must be:
>> +		 "tcphy_rst", "tcphy_pipe_rst", "uphy_tcphy_rst"
>> + - #phy-cells: Must be 0.  See ./phy-bindings.txt for details.
>> + - rockchip,usb3phy*: phy registers embed in grf
>> +
>> +Example:
>> +	tcphy0: phy at ff7c0000 {
>> +		compatible = "rockchip,rk3399-typec-phy";
>> +		reg = <0x0 0xff7c0000 0x0 0x40000>;
>> +		#phy-cells = <0>;
>> +		rockchip,grf = <&grf>;
>> +		clocks = <&cru SCLK_UPHY0_TCPDCORE>,
>> +			 <&cru SCLK_UPHY0_TCPDPHY_REF>;
>> +		clock-names = "tcpdcore", "tcpdphy_ref";
>> +		resets = <&cru SRST_UPHY0>,
>> +			 <&cru SRST_UPHY0_PIPE_L00>,
>> +			 <&cru SRST_P_UPHY0_TCPHY>;
>> +		reset-names = "tcphy_rst", "tcphy_pipe_rst", "uphy_tcphy_rst";
>> +		rockchip,usb3phy_con0 = <0x0e580 0 16>;
>> +		rockchip,usb3phy_con1 = <0x0e584 0 16>;
>> +		rockchip,usb3phy_con2 = <0x0e588 0 16>;
>> +		rockchip,usb3phy_status0 = <0x0e5c0 0 13>;
>> +		rockchip,usb3phy_status1 = <0x0e5c4 0 12>;
> please embedded this register data in the driver instead (not in the
> devicetree), matched against the compatible value.
> See Frank's usb2phy driver for reference if needed.
Okay, I will move them to driver file next version, Thanks.
>
> Thanks
> Heiko
>
>
>
>




From honghui.zhang at mediatek.com  Fri May 27 01:56:35 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Fri, 27 May 2016 16:56:35 +0800
Subject: [PATCH v3 0/5] MT2701 iommu support
Message-ID: <1464339400-22559-1-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

  Mediatek's m4u(Multimedia Memory Management Unit) and SMI(Smart
Multimedia Interface)have two generations HW. They basically sharing the
same hardware block diagram, but have some difference as below:

  Generation one m4u only supports one layer, flat pagetable addressing,
and only supports 4K size page mapping. While generation two m4u supports 2
levels of pagetable which uses the ARM short-descriptor translation table
format for address translation.
They have slight different register base and register offset.
They have very different HW ports defines.

  Generaion one SMI has additional "async" clock which transform the smi
clock into emi clock domain, this clock should be prepared and enabled for
SMI generation one HW.
The register which control the iommu need to translation the address or not
for a particular port is located at smi ao base(smi always on register
base) for generation one SMI HW, but located at each larb's register base
for generation two HW.

This patch set add mt2701 iommu support, it's based on 4.6-rc1 and James
Liao's "Add clock support for Mediatek MT2701 v8[1]" and "Mediatek MT2701
SCPSYS power domain support v7[2]" patch.

v3:
-Rebase on "of: Implement iterator for phandles[3]" and take use of
 of_for_each_phandle.
-Forward-declare mtk_iommu_domain and implement the struct separately.
-Free the pagetable memory in mtk_iommu_domain_free
-Roll back the mapping in error case.
-Minor cleanups.

v2: https://lists.linuxfoundation.org/pipermail/iommu/2016-May/017068.html
-Fix syntax errors in dt-bindings.
-Use dma_alloc/free_coherent to allocate pagetable memory and reduce the
 streaming DMA stuff.
-Make the mtk_iommu_ops.pgsize_bitmap as ~0UL << MT2701_IOMMU_PAGE_SHIFT.
-Use macro instead of variable to indicate the pagetable size.
-Change some macro name from MTK_XXX to MT2701_XXX.

v1: http://lists.infradead.org/pipermail/linux-mediatek/2016-May/005301.html
-initial version

[1] http://lists.infradead.org/pipermail/linux-mediatek/2016-May/005439.html
[2] http://lists.infradead.org/pipermail/linux-mediatek/2016-May/005429.html
[3] https://lists.linuxfoundation.org/pipermail/iommu/2016-April/016300.html

Honghui Zhang (5):
  dt-bindings: mediatek: add descriptions for mediatek mt2701 iommu and
    smi
  iommu/mediatek: move the common struct into header file
  memory/mediatek: add support for mt2701
  iommu/mediatek: add support for mtk iommu generation one HW
  ARM: dts: mt2701: add iommu/smi dtsi node for mt2701

 .../devicetree/bindings/iommu/mediatek,iommu.txt   |  13 +-
 .../memory-controllers/mediatek,smi-common.txt     |  21 +-
 .../memory-controllers/mediatek,smi-larb.txt       |   4 +-
 arch/arm/boot/dts/mt2701.dtsi                      |  51 ++
 drivers/iommu/Kconfig                              |  18 +
 drivers/iommu/Makefile                             |   1 +
 drivers/iommu/mtk_iommu.c                          |  48 +-
 drivers/iommu/mtk_iommu.h                          |  77 +++
 drivers/iommu/mtk_iommu_v1.c                       | 728 +++++++++++++++++++++
 drivers/memory/mtk-smi.c                           | 168 ++++-
 include/dt-bindings/memory/mt2701-larb-port.h      |  85 +++
 11 files changed, 1140 insertions(+), 74 deletions(-)
 create mode 100644 drivers/iommu/mtk_iommu.h
 create mode 100644 drivers/iommu/mtk_iommu_v1.c
 create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h

-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Fri May 27 01:56:36 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Fri, 27 May 2016 16:56:36 +0800
Subject: [PATCH v3 1/5] dt-bindings: mediatek: add descriptions for mediatek
 mt2701 iommu and smi
In-Reply-To: <1464339400-22559-1-git-send-email-honghui.zhang@mediatek.com>
References: <1464339400-22559-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1464339400-22559-2-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

This patch defines the local arbitor port IDs for mediatek SoC MT2701 and
add descriptions of binding for mediatek generation one iommu and smi.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/iommu/mediatek,iommu.txt   | 13 +++-
 .../memory-controllers/mediatek,smi-common.txt     | 21 +++++-
 .../memory-controllers/mediatek,smi-larb.txt       |  4 +-
 include/dt-bindings/memory/mt2701-larb-port.h      | 85 ++++++++++++++++++++++
 4 files changed, 115 insertions(+), 8 deletions(-)
 create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h

diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
index cd1b1cd..53c20ca 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
@@ -1,7 +1,9 @@
 * Mediatek IOMMU Architecture Implementation
 
-  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U) which
-uses the ARM Short-Descriptor translation table format for address translation.
+  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U), and
+this M4U have two generations of HW architecture. Generation one uses flat
+pagetable, and only supports 4K size page mapping. Generation two uses the
+ARM Short-Descriptor translation table format for address translation.
 
   About the M4U Hardware Block Diagram, please check below:
 
@@ -36,7 +38,9 @@ in each larb. Take a example, There are many ports like MC, PP, VLD in the
 video decode local arbiter, all these ports are according to the video HW.
 
 Required properties:
-- compatible : must be "mediatek,mt8173-m4u".
+- compatible : must be one of the following string:
+	"mediatek,mt2701-m4u" for mt2701 which uses generation one m4u HW.
+	"mediatek,mt8173-m4u" for mt8173 which uses generation two m4u HW.
 - reg : m4u register base and size.
 - interrupts : the interrupt of m4u.
 - clocks : must contain one entry for each clock-names.
@@ -46,7 +50,8 @@ Required properties:
 	according to the local arbiter index, like larb0, larb1, larb2...
 - iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
 	Specifies the mtk_m4u_id as defined in
-	dt-binding/memory/mt8173-larb-port.h.
+	dt-binding/memory/mt2701-larb-port.h for mt2701 and
+	dt-binding/memory/mt8173-larb-port.h for mt8173
 
 Example:
 	iommu: iommu at 10205000 {
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
index 06a83ce..aa614b2 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
@@ -2,16 +2,31 @@ SMI (Smart Multimedia Interface) Common
 
 The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
 
+Mediatek SMI have two generations of HW architecture, mt8173 uses the second
+generation of SMI HW while mt2701 uses the first generation HW of SMI.
+
+There's slight differences between the two SMI, for generation 2, the
+register which control the iommu port is at each larb's register base. But
+for generation 1, the register is at smi ao base(smi always on register
+base). Besides that, the smi async clock should be prepared and enabled for
+SMI generation 1 to transform the smi clock into emi clock domain, but that is
+not needed for SMI generation 2.
+
 Required properties:
-- compatible : must be "mediatek,mt8173-smi-common"
+- compatible : must be one of :
+	"mediatek,mt2701-smi-common"
+	"mediatek,mt8173-smi-common"
 - reg : the register and size of the SMI block.
 - power-domains : a phandle to the power domain of this local arbiter.
 - clocks : Must contain an entry for each entry in clock-names.
-- clock-names : must contain 2 entries, as follows:
+- clock-names : must contain 3 entries for generation 1 smi HW and 2 entries
+  for generation 2 smi HW as follows:
   - "apb" : Advanced Peripheral Bus clock, It's the clock for setting
 	    the register.
   - "smi" : It's the clock for transfer data and command.
-  They may be the same if both source clocks are the same.
+	    They may be the same if both source clocks are the same.
+  - "async" : asynchronous clock, it help transform the smi clock into the emi
+	      clock domain, this clock is only needed by generation 1 smi HW.
 
 Example:
 	smi_common: smi at 14022000 {
diff --git a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
index 55ff3b7..21277a5 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
@@ -3,7 +3,9 @@ SMI (Smart Multimedia Interface) Local Arbiter
 The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
 
 Required properties:
-- compatible : must be "mediatek,mt8173-smi-larb"
+- compatible : must be one of :
+		"mediatek,mt8173-smi-larb"
+		"mediatek,mt2701-smi-larb"
 - reg : the register and size of this local arbiter.
 - mediatek,smi : a phandle to the smi_common node.
 - power-domains : a phandle to the power domain of this local arbiter.
diff --git a/include/dt-bindings/memory/mt2701-larb-port.h b/include/dt-bindings/memory/mt2701-larb-port.h
new file mode 100644
index 0000000..78f6678
--- /dev/null
+++ b/include/dt-bindings/memory/mt2701-larb-port.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Honghui Zhang <honghui.zhang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MT2701_LARB_PORT_H_
+#define _MT2701_LARB_PORT_H_
+
+/*
+ * Mediatek m4u generation 1 such as mt2701 has flat m4u port numbers,
+ * the first port's id for larb[N] would be the last port's id of larb[N - 1]
+ * plus one while larb[0]'s first port number is 0. The definition of
+ * MT2701_M4U_ID_LARBx is following HW register spec.
+ * But m4u generation 2 like mt8173 have different port number, it use fixed
+ * offset for each larb, the first port's id for larb[N] would be (N * 32).
+ */
+#define LARB0_PORT_OFFSET		0
+#define LARB1_PORT_OFFSET		11
+#define LARB2_PORT_OFFSET		21
+#define LARB3_PORT_OFFSET		43
+
+#define MT2701_M4U_ID_LARB0(port)	((port) + LARB0_PORT_OFFSET)
+#define MT2701_M4U_ID_LARB1(port)	((port) + LARB1_PORT_OFFSET)
+#define MT2701_M4U_ID_LARB2(port)	((port) + LARB2_PORT_OFFSET)
+
+/* Port define for larb0 */
+#define MT2701_M4U_PORT_DISP_OVL_0		MT2701_M4U_ID_LARB0(0)
+#define MT2701_M4U_PORT_DISP_RDMA1		MT2701_M4U_ID_LARB0(1)
+#define MT2701_M4U_PORT_DISP_RDMA		MT2701_M4U_ID_LARB0(2)
+#define MT2701_M4U_PORT_DISP_WDMA		MT2701_M4U_ID_LARB0(3)
+#define MT2701_M4U_PORT_MM_CMDQ			MT2701_M4U_ID_LARB0(4)
+#define MT2701_M4U_PORT_MDP_RDMA		MT2701_M4U_ID_LARB0(5)
+#define MT2701_M4U_PORT_MDP_WDMA		MT2701_M4U_ID_LARB0(6)
+#define MT2701_M4U_PORT_MDP_ROTO		MT2701_M4U_ID_LARB0(7)
+#define MT2701_M4U_PORT_MDP_ROTCO		MT2701_M4U_ID_LARB0(8)
+#define MT2701_M4U_PORT_MDP_ROTVO		MT2701_M4U_ID_LARB0(9)
+#define MT2701_M4U_PORT_MDP_RDMA1		MT2701_M4U_ID_LARB0(10)
+
+/* Port define for larb1 */
+#define MT2701_M4U_PORT_VDEC_MC_EXT		MT2701_M4U_ID_LARB1(0)
+#define MT2701_M4U_PORT_VDEC_PP_EXT		MT2701_M4U_ID_LARB1(1)
+#define MT2701_M4U_PORT_VDEC_PPWRAP_EXT		MT2701_M4U_ID_LARB1(2)
+#define MT2701_M4U_PORT_VDEC_AVC_MV_EXT		MT2701_M4U_ID_LARB1(3)
+#define MT2701_M4U_PORT_VDEC_PRED_RD_EXT	MT2701_M4U_ID_LARB1(4)
+#define MT2701_M4U_PORT_VDEC_PRED_WR_EXT	MT2701_M4U_ID_LARB1(5)
+#define MT2701_M4U_PORT_VDEC_VLD_EXT		MT2701_M4U_ID_LARB1(6)
+#define MT2701_M4U_PORT_VDEC_VLD2_EXT		MT2701_M4U_ID_LARB1(7)
+#define MT2701_M4U_PORT_VDEC_TILE_EXT		MT2701_M4U_ID_LARB1(8)
+#define MT2701_M4U_PORT_VDEC_IMG_RESZ_EXT	MT2701_M4U_ID_LARB1(9)
+
+/* Port define for larb2 */
+#define MT2701_M4U_PORT_VENC_RCPU		MT2701_M4U_ID_LARB2(0)
+#define MT2701_M4U_PORT_VENC_REC_FRM		MT2701_M4U_ID_LARB2(1)
+#define MT2701_M4U_PORT_VENC_BSDMA		MT2701_M4U_ID_LARB2(2)
+#define MT2701_M4U_PORT_JPGENC_RDMA		MT2701_M4U_ID_LARB2(3)
+#define MT2701_M4U_PORT_VENC_LT_RCPU		MT2701_M4U_ID_LARB2(4)
+#define MT2701_M4U_PORT_VENC_LT_REC_FRM		MT2701_M4U_ID_LARB2(5)
+#define MT2701_M4U_PORT_VENC_LT_BSDMA		MT2701_M4U_ID_LARB2(6)
+#define MT2701_M4U_PORT_JPGDEC_BSDMA		MT2701_M4U_ID_LARB2(7)
+#define MT2701_M4U_PORT_VENC_SV_COMV		MT2701_M4U_ID_LARB2(8)
+#define MT2701_M4U_PORT_VENC_RD_COMV		MT2701_M4U_ID_LARB2(9)
+#define MT2701_M4U_PORT_JPGENC_BSDMA		MT2701_M4U_ID_LARB2(10)
+#define MT2701_M4U_PORT_VENC_CUR_LUMA		MT2701_M4U_ID_LARB2(11)
+#define MT2701_M4U_PORT_VENC_CUR_CHROMA		MT2701_M4U_ID_LARB2(12)
+#define MT2701_M4U_PORT_VENC_REF_LUMA		MT2701_M4U_ID_LARB2(13)
+#define MT2701_M4U_PORT_VENC_REF_CHROMA		MT2701_M4U_ID_LARB2(14)
+#define MT2701_M4U_PORT_IMG_RESZ		MT2701_M4U_ID_LARB2(15)
+#define MT2701_M4U_PORT_VENC_LT_SV_COMV		MT2701_M4U_ID_LARB2(16)
+#define MT2701_M4U_PORT_VENC_LT_RD_COMV		MT2701_M4U_ID_LARB2(17)
+#define MT2701_M4U_PORT_VENC_LT_CUR_LUMA	MT2701_M4U_ID_LARB2(18)
+#define MT2701_M4U_PORT_VENC_LT_CUR_CHROMA	MT2701_M4U_ID_LARB2(19)
+#define MT2701_M4U_PORT_VENC_LT_REF_LUMA	MT2701_M4U_ID_LARB2(20)
+#define MT2701_M4U_PORT_VENC_LT_REF_CHROMA	MT2701_M4U_ID_LARB2(21)
+#define MT2701_M4U_PORT_JPGDEC_WDMA		MT2701_M4U_ID_LARB2(22)
+
+#endif
-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Fri May 27 01:56:37 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Fri, 27 May 2016 16:56:37 +0800
Subject: [PATCH v3 2/5] iommu/mediatek: move the common struct into header file
In-Reply-To: <1464339400-22559-1-git-send-email-honghui.zhang@mediatek.com>
References: <1464339400-22559-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1464339400-22559-3-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

Move the struct defines of mtk iommu into a new header files for
common use.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 drivers/iommu/mtk_iommu.c | 48 +----------------------------
 drivers/iommu/mtk_iommu.h | 77 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+), 47 deletions(-)
 create mode 100644 drivers/iommu/mtk_iommu.h

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index db74553..f83c9bc 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -34,7 +34,7 @@
 #include <dt-bindings/memory/mt8173-larb-port.h>
 #include <soc/mediatek/smi.h>
 
-#include "io-pgtable.h"
+#include "mtk_iommu.h"
 
 #define REG_MMU_PT_BASE_ADDR			0x000
 
@@ -93,20 +93,6 @@
 
 #define MTK_PROTECT_PA_ALIGN			128
 
-struct mtk_iommu_suspend_reg {
-	u32				standard_axi_mode;
-	u32				dcm_dis;
-	u32				ctrl_reg;
-	u32				int_control0;
-	u32				int_main_control;
-};
-
-struct mtk_iommu_client_priv {
-	struct list_head		client;
-	unsigned int			mtk_m4u_id;
-	struct device			*m4udev;
-};
-
 struct mtk_iommu_domain {
 	spinlock_t			pgtlock; /* lock for page table */
 
@@ -116,19 +102,6 @@ struct mtk_iommu_domain {
 	struct iommu_domain		domain;
 };
 
-struct mtk_iommu_data {
-	void __iomem			*base;
-	int				irq;
-	struct device			*dev;
-	struct clk			*bclk;
-	phys_addr_t			protect_base; /* protect memory base */
-	struct mtk_iommu_suspend_reg	reg;
-	struct mtk_iommu_domain		*m4u_dom;
-	struct iommu_group		*m4u_group;
-	struct mtk_smi_iommu		smi_imu;      /* SMI larb iommu info */
-	bool                            enable_4GB;
-};
-
 static struct iommu_ops mtk_iommu_ops;
 
 static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
@@ -552,25 +525,6 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
 	return 0;
 }
 
-static int compare_of(struct device *dev, void *data)
-{
-	return dev->of_node == data;
-}
-
-static int mtk_iommu_bind(struct device *dev)
-{
-	struct mtk_iommu_data *data = dev_get_drvdata(dev);
-
-	return component_bind_all(dev, &data->smi_imu);
-}
-
-static void mtk_iommu_unbind(struct device *dev)
-{
-	struct mtk_iommu_data *data = dev_get_drvdata(dev);
-
-	component_unbind_all(dev, &data->smi_imu);
-}
-
 static const struct component_master_ops mtk_iommu_com_ops = {
 	.bind		= mtk_iommu_bind,
 	.unbind		= mtk_iommu_unbind,
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
new file mode 100644
index 0000000..9ed0a84
--- /dev/null
+++ b/drivers/iommu/mtk_iommu.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Honghui Zhang <honghui.zhang at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MTK_IOMMU_H_
+#define _MTK_IOMMU_H_
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/iommu.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <soc/mediatek/smi.h>
+
+#include "io-pgtable.h"
+
+struct mtk_iommu_suspend_reg {
+	u32				standard_axi_mode;
+	u32				dcm_dis;
+	u32				ctrl_reg;
+	u32				int_control0;
+	u32				int_main_control;
+};
+
+struct mtk_iommu_client_priv {
+	struct list_head		client;
+	unsigned int			mtk_m4u_id;
+	struct device			*m4udev;
+};
+
+struct mtk_iommu_domain;
+
+struct mtk_iommu_data {
+	void __iomem			*base;
+	int				irq;
+	struct device			*dev;
+	struct clk			*bclk;
+	phys_addr_t			protect_base; /* protect memory base */
+	struct mtk_iommu_suspend_reg	reg;
+	struct mtk_iommu_domain		*m4u_dom;
+	struct iommu_group		*m4u_group;
+	struct mtk_smi_iommu		smi_imu;      /* SMI larb iommu info */
+	bool                            enable_4GB;
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static int mtk_iommu_bind(struct device *dev)
+{
+	struct mtk_iommu_data *data = dev_get_drvdata(dev);
+
+	return component_bind_all(dev, &data->smi_imu);
+}
+
+static void mtk_iommu_unbind(struct device *dev)
+{
+	struct mtk_iommu_data *data = dev_get_drvdata(dev);
+
+	component_unbind_all(dev, &data->smi_imu);
+}
+
+#endif
-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Fri May 27 01:56:38 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Fri, 27 May 2016 16:56:38 +0800
Subject: [PATCH v3 3/5] memory/mediatek: add support for mt2701
In-Reply-To: <1464339400-22559-1-git-send-email-honghui.zhang@mediatek.com>
References: <1464339400-22559-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1464339400-22559-4-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

Mediatek SMI has two generations of HW architecture, mt8173 uses the
second generation of SMI HW while mt2701 uses the first generation
HW of SMI.

There's slight differences between the two generations, for generation 2,
the register which control the iommu port access PA or IOVA is at each
larb's register base. But for generation 1, the register is at smi ao
base(smi always on register base).
Besides that, the smi async clock should be prepared and enabled for SMI
generation 1 HW to transform the smi clock into emi clock domain, but is
not needed for SMI generation 2.

This patch add SMI driver for mt2701 which use generation 1 SMI HW.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 drivers/memory/mtk-smi.c | 168 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 149 insertions(+), 19 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 089091f..0a47382 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -21,19 +21,50 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <soc/mediatek/smi.h>
+#include <dt-bindings/memory/mt2701-larb-port.h>
 
 #define SMI_LARB_MMU_EN		0xf00
+#define REG_SMI_SECUR_CON_BASE		0x5c0
+
+/* every register control 8 port, register offset 0x4 */
+#define REG_SMI_SECUR_CON_OFFSET(id)	(((id) >> 3) << 2)
+#define REG_SMI_SECUR_CON_ADDR(id)	\
+	(REG_SMI_SECUR_CON_BASE + REG_SMI_SECUR_CON_OFFSET(id))
+
+/*
+ * every port have 4 bit to control, bit[port + 3] control virtual or physical,
+ * bit[port + 2 : port + 1] control the domain, bit[port] control the security
+ * or non-security.
+ */
+#define SMI_SECUR_CON_VAL_MSK(id)	(~(0xf << (((id) & 0x7) << 2)))
+#define SMI_SECUR_CON_VAL_VIRT(id)	BIT((((id) & 0x7) << 2) + 3)
+/* mt2701 domain should be set to 3 */
+#define SMI_SECUR_CON_VAL_DOMAIN(id)	(0x3 << ((((id) & 0x7) << 2) + 1))
+
+struct mtk_smi_larb_gen {
+	int port_in_larb[MTK_LARB_NR_MAX + 1];
+	void (*config_port)(struct device *);
+};
 
 struct mtk_smi {
-	struct device	*dev;
-	struct clk	*clk_apb, *clk_smi;
+	struct device			*dev;
+	struct clk			*clk_apb, *clk_smi;
+	struct clk			*clk_async; /*only needed by mt2701*/
+	void __iomem			*smi_ao_base;
 };
 
 struct mtk_smi_larb { /* larb: local arbiter */
-	struct mtk_smi  smi;
-	void __iomem	*base;
-	struct device	*smi_common_dev;
-	u32		*mmu;
+	struct mtk_smi			smi;
+	void __iomem			*base;
+	struct device			*smi_common_dev;
+	const struct mtk_smi_larb_gen	*larb_gen;
+	int				larbid;
+	u32				*mmu;
+};
+
+enum mtk_smi_gen {
+	MTK_SMI_GEN1,
+	MTK_SMI_GEN2
 };
 
 static int mtk_smi_enable(const struct mtk_smi *smi)
@@ -71,6 +102,7 @@ static void mtk_smi_disable(const struct mtk_smi *smi)
 int mtk_smi_larb_get(struct device *larbdev)
 {
 	struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
+	const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
 	struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
 	int ret;
 
@@ -87,8 +119,7 @@ int mtk_smi_larb_get(struct device *larbdev)
 	}
 
 	/* Configure the iommu info for this larb */
-	writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
-
+	larb_gen->config_port(larbdev);
 	return 0;
 }
 
@@ -124,6 +155,45 @@ mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
 	return -ENODEV;
 }
 
+static void mtk_smi_larb_config_port(struct device *dev)
+{
+	struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+
+	writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
+}
+
+
+static void mtk_smi_larb_config_port_gen1(struct device *dev)
+{
+	struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+	const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
+	struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
+	int i, m4u_port_id, larb_port_num;
+	u32 sec_con_val, reg_val;
+
+	m4u_port_id = larb_gen->port_in_larb[larb->larbid];
+	larb_port_num = larb_gen->port_in_larb[larb->larbid + 1]
+			- larb_gen->port_in_larb[larb->larbid];
+
+	for (i = 0; i < larb_port_num; i++, m4u_port_id++) {
+		if (*larb->mmu & BIT(i)) {
+			/* bit[port + 3] controls the virtual or physical */
+			sec_con_val = SMI_SECUR_CON_VAL_VIRT(m4u_port_id);
+		} else {
+			/* do not need to enable m4u for this port */
+			continue;
+		}
+		reg_val = readl(common->smi_ao_base
+			+ REG_SMI_SECUR_CON_ADDR(m4u_port_id));
+		reg_val &= SMI_SECUR_CON_VAL_MSK(m4u_port_id);
+		reg_val |= sec_con_val;
+		reg_val |= SMI_SECUR_CON_VAL_DOMAIN(m4u_port_id);
+		writel(reg_val,
+			common->smi_ao_base
+			+ REG_SMI_SECUR_CON_ADDR(m4u_port_id));
+	}
+}
+
 static void
 mtk_smi_larb_unbind(struct device *dev, struct device *master, void *data)
 {
@@ -135,6 +205,31 @@ static const struct component_ops mtk_smi_larb_component_ops = {
 	.unbind = mtk_smi_larb_unbind,
 };
 
+static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = {
+	/* mt8173 do not need the port in larb */
+	.config_port = mtk_smi_larb_config_port,
+};
+
+static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
+	.port_in_larb = {
+		LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
+		LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
+	},
+	.config_port = mtk_smi_larb_config_port_gen1,
+};
+
+static const struct of_device_id mtk_smi_larb_of_ids[] = {
+	{
+		.compatible = "mediatek,mt8173-smi-larb",
+		.data = &mtk_smi_larb_mt8173
+	},
+	{
+		.compatible = "mediatek,mt2701-smi-larb",
+		.data = &mtk_smi_larb_mt2701
+	},
+	{}
+};
+
 static int mtk_smi_larb_probe(struct platform_device *pdev)
 {
 	struct mtk_smi_larb *larb;
@@ -142,14 +237,20 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct device_node *smi_node;
 	struct platform_device *smi_pdev;
+	const struct of_device_id *of_id;
 
 	if (!dev->pm_domain)
 		return -EPROBE_DEFER;
 
+	of_id = of_match_node(mtk_smi_larb_of_ids, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
 	larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
 	if (!larb)
 		return -ENOMEM;
 
+	larb->larb_gen = of_id->data;
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	larb->base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(larb->base))
@@ -189,24 +290,34 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id mtk_smi_larb_of_ids[] = {
-	{ .compatible = "mediatek,mt8173-smi-larb",},
-	{}
-};
-
 static struct platform_driver mtk_smi_larb_driver = {
 	.probe	= mtk_smi_larb_probe,
-	.remove = mtk_smi_larb_remove,
+	.remove	= mtk_smi_larb_remove,
 	.driver	= {
 		.name = "mtk-smi-larb",
 		.of_match_table = mtk_smi_larb_of_ids,
 	}
 };
 
+static const struct of_device_id mtk_smi_common_of_ids[] = {
+	{
+		.compatible = "mediatek,mt8173-smi-common",
+		.data = (void *)MTK_SMI_GEN2
+	},
+	{
+		.compatible = "mediatek,mt2701-smi-common",
+		.data = (void *)MTK_SMI_GEN1
+	},
+	{}
+};
+
 static int mtk_smi_common_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct mtk_smi *common;
+	struct resource *res;
+	const struct of_device_id *of_id;
+	enum mtk_smi_gen smi_gen;
 
 	if (!dev->pm_domain)
 		return -EPROBE_DEFER;
@@ -224,6 +335,29 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
 	if (IS_ERR(common->clk_smi))
 		return PTR_ERR(common->clk_smi);
 
+	of_id = of_match_node(mtk_smi_common_of_ids, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
+	/*
+	 * for mtk smi gen 1, we need to get the ao(always on) base to config
+	 * m4u port, and we need to enable the aync clock for transform the smi
+	 * clock into emi clock domain, but for mtk smi gen2, there's no smi ao
+	 * base.
+	 */
+	smi_gen = (enum mtk_smi_gen)of_id->data;
+	if (smi_gen == MTK_SMI_GEN1) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		common->smi_ao_base = devm_ioremap_resource(dev, res);
+		if (IS_ERR(common->smi_ao_base))
+			return PTR_ERR(common->smi_ao_base);
+
+		common->clk_async = devm_clk_get(dev, "async");
+		if (IS_ERR(common->clk_async))
+			return PTR_ERR(common->clk_async);
+
+		clk_prepare_enable(common->clk_async);
+	}
 	pm_runtime_enable(dev);
 	platform_set_drvdata(pdev, common);
 	return 0;
@@ -235,11 +369,6 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id mtk_smi_common_of_ids[] = {
-	{ .compatible = "mediatek,mt8173-smi-common", },
-	{}
-};
-
 static struct platform_driver mtk_smi_common_driver = {
 	.probe	= mtk_smi_common_probe,
 	.remove = mtk_smi_common_remove,
@@ -270,4 +399,5 @@ err_unreg_smi:
 	platform_driver_unregister(&mtk_smi_common_driver);
 	return ret;
 }
+
 subsys_initcall(mtk_smi_init);
-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Fri May 27 01:56:39 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Fri, 27 May 2016 16:56:39 +0800
Subject: [PATCH v3 4/5] iommu/mediatek: add support for mtk iommu generation
 one HW
In-Reply-To: <1464339400-22559-1-git-send-email-honghui.zhang@mediatek.com>
References: <1464339400-22559-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1464339400-22559-5-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

Mediatek SoC's M4U has two generations of HW architcture. Generation one
uses flat, one layer pagetable, and was shipped with ARM architecture, it
only supports 4K size page mapping. MT2701 SoC uses this generation one
m4u HW. Generation two uses the ARM short-descriptor translation table
format for address translation, and was shipped with ARM64 architecture,
MT8173 uses this generation two m4u HW. All the two generation iommu HW
only have one iommu domain, and all its iommu clients share the same
iova address.

These two generation m4u HW have slit different register groups and
register offset, but most register names are the same. This patch add iommu
support for mediatek SoC mt2701.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 drivers/iommu/Kconfig        |  18 ++
 drivers/iommu/Makefile       |   1 +
 drivers/iommu/mtk_iommu_v1.c | 728 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 747 insertions(+)
 create mode 100644 drivers/iommu/mtk_iommu_v1.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index dd1dc39..363c1d8 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -354,4 +354,22 @@ config MTK_IOMMU
 
 	  If unsure, say N here.
 
+config MTK_IOMMU_V1
+	bool "MTK IOMMU Version 1 (M4U gen1) Support"
+	depends on ARM
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	select ARM_DMA_USE_IOMMU
+	select IOMMU_API
+	select MEMORY
+	select MTK_SMI
+	select COMMON_CLK_MT2701_MMSYS
+	select COMMON_CLK_MT2701_IMGSYS
+	select COMMON_CLK_MT2701_VDECSYS
+	help
+	  Support for the M4U on certain Mediatek SoCs. M4U generation 1 HW is
+	  Multimedia Memory Managememt Unit. This option enables remapping of
+	  DMA memory accesses for the multimedia subsystem.
+
+	  if unsure, say N here.
+
 endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index c6edb31..778baf5 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
 obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
 obj-$(CONFIG_MTK_IOMMU) += mtk_iommu.o
+obj-$(CONFIG_MTK_IOMMU_V1) += mtk_iommu_v1.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
 obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
new file mode 100644
index 0000000..a2a2554
--- /dev/null
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -0,0 +1,728 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Honghui Zhang <honghui.zhang at mediatek.com>
+ *
+ * Based on driver/iommu/mtk_iommu.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/bootmem.h>
+#include <linux/bug.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/dma-iommu.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iommu.h>
+#include <linux/iopoll.h>
+#include <linux/kmemleak.h>
+#include <linux/list.h>
+#include <linux/of_address.h>
+#include <linux/of_iommu.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/barrier.h>
+#include <asm/dma-iommu.h>
+#include <linux/module.h>
+#include <dt-bindings/memory/mt2701-larb-port.h>
+#include <soc/mediatek/smi.h>
+#include "mtk_iommu.h"
+
+#define REG_MMU_PT_BASE_ADDR			0x000
+
+#define F_ALL_INVLD				0x2
+#define F_MMU_INV_RANGE				0x1
+#define F_INVLD_EN0				BIT(0)
+#define F_INVLD_EN1				BIT(1)
+
+#define F_MMU_FAULT_VA_MSK			0xfffff000
+#define MTK_PROTECT_PA_ALIGN			128
+
+#define REG_MMU_CTRL_REG			0x210
+#define F_MMU_CTRL_COHERENT_EN			BIT(8)
+#define REG_MMU_IVRP_PADDR			0x214
+#define REG_MMU_INT_CONTROL			0x220
+#define F_INT_TRANSLATION_FAULT			BIT(0)
+#define F_INT_MAIN_MULTI_HIT_FAULT		BIT(1)
+#define F_INT_INVALID_PA_FAULT			BIT(2)
+#define F_INT_ENTRY_REPLACEMENT_FAULT		BIT(3)
+#define F_INT_TABLE_WALK_FAULT			BIT(4)
+#define F_INT_TLB_MISS_FAULT			BIT(5)
+#define F_INT_PFH_DMA_FIFO_OVERFLOW		BIT(6)
+#define F_INT_MISS_DMA_FIFO_OVERFLOW		BIT(7)
+
+#define F_MMU_TF_PROTECT_SEL(prot)		(((prot) & 0x3) << 5)
+#define F_INT_CLR_BIT				BIT(12)
+
+#define REG_MMU_FAULT_ST			0x224
+#define REG_MMU_FAULT_VA			0x228
+#define REG_MMU_INVLD_PA			0x22C
+#define REG_MMU_INT_ID				0x388
+#define REG_MMU_INVALIDATE			0x5c0
+#define REG_MMU_INVLD_START_A			0x5c4
+#define REG_MMU_INVLD_END_A			0x5c8
+
+#define REG_MMU_INV_SEL				0x5d8
+#define REG_MMU_STANDARD_AXI_MODE		0x5e8
+
+#define REG_MMU_DCM				0x5f0
+#define F_MMU_DCM_ON				BIT(1)
+#define REG_MMU_CPE_DONE			0x60c
+#define F_DESC_VALID				0x2
+#define F_DESC_NONSEC				BIT(3)
+#define MT2701_M4U_TF_LARB(TF)			(6 - (((TF) >> 13) & 0x7))
+#define MT2701_M4U_TF_PORT(TF)			(((TF) >> 8) & 0xF)
+/* MTK generation one iommu HW only support 4K size mapping */
+#define MT2701_IOMMU_PAGE_SHIFT			12
+#define MT2701_IOMMU_PAGE_SIZE			(1UL << MT2701_IOMMU_PAGE_SHIFT)
+
+/*
+ * MTK m4u support 4GB iova address space, and only support 4K page
+ * mapping. So the pagetable size should be exactly as 4M.
+ */
+#define M2701_IOMMU_PGT_SIZE			SZ_4M
+
+struct mtk_iommu_domain {
+	spinlock_t			pgtlock; /* lock for page table */
+	struct iommu_domain		domain;
+	u32				*pgt_va;
+	dma_addr_t			pgt_pa;
+	struct mtk_iommu_data		*data;
+};
+
+static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
+{
+	return container_of(dom, struct mtk_iommu_domain, domain);
+}
+
+static const int mt2701_m4u_in_larb[] = {
+	LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
+	LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
+};
+
+static inline int mt2701_m4u_to_larb(int id)
+{
+	int i;
+
+	for (i = ARRAY_SIZE(mt2701_m4u_in_larb) - 1; i >= 0; i--)
+		if ((id) >= mt2701_m4u_in_larb[i])
+			return i;
+
+	return 0;
+}
+
+static inline int mt2701_m4u_to_port(int id)
+{
+	int larb = mt2701_m4u_to_larb(id);
+
+	return id - mt2701_m4u_in_larb[larb];
+}
+
+static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data)
+{
+	writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
+			data->base + REG_MMU_INV_SEL);
+	writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
+	wmb(); /* Make sure the tlb flush all done */
+}
+
+static void mtk_iommu_tlb_flush_range(struct mtk_iommu_data *data,
+				unsigned long iova, size_t size)
+{
+	int ret;
+	u32 tmp;
+
+	writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
+		data->base + REG_MMU_INV_SEL);
+	writel_relaxed(iova & F_MMU_FAULT_VA_MSK,
+		data->base + REG_MMU_INVLD_START_A);
+	writel_relaxed((iova + size - 1) & F_MMU_FAULT_VA_MSK,
+		data->base + REG_MMU_INVLD_END_A);
+	writel_relaxed(F_MMU_INV_RANGE, data->base + REG_MMU_INVALIDATE);
+
+	ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE,
+				tmp, tmp != 0, 10, 100000);
+	if (ret) {
+		dev_warn(data->dev,
+			 "Partial TLB flush timed out, falling back to full flush\n");
+		mtk_iommu_tlb_flush_all(data);
+	}
+	/* Clear the CPE status */
+	writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
+}
+
+static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
+{
+	struct mtk_iommu_data *data = dev_id;
+	struct mtk_iommu_domain *dom = data->m4u_dom;
+	u32 int_state, regval, fault_iova, fault_pa;
+	unsigned int fault_larb, fault_port;
+
+	/* Read error information from registers */
+	int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST);
+	fault_iova = readl_relaxed(data->base + REG_MMU_FAULT_VA);
+
+	fault_iova &= F_MMU_FAULT_VA_MSK;
+	fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
+	regval = readl_relaxed(data->base + REG_MMU_INT_ID);
+	fault_larb = MT2701_M4U_TF_LARB(regval);
+	fault_port = MT2701_M4U_TF_PORT(regval);
+
+	/*
+	 * MTK v1 iommu HW could not determine whether the fault is read or
+	 * write fault, report as read fault.
+	 */
+	if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
+			IOMMU_FAULT_READ))
+		dev_err_ratelimited(data->dev,
+			"fault type=0x%x iova=0x%x pa=0x%x larb=%d port=%d\n",
+			int_state, fault_iova, fault_pa,
+			fault_larb, fault_port);
+
+	/* Interrupt clear */
+	regval = readl_relaxed(data->base + REG_MMU_INT_CONTROL);
+	regval |= F_INT_CLR_BIT;
+	writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL);
+
+	mtk_iommu_tlb_flush_all(data);
+
+	return IRQ_HANDLED;
+}
+
+static void mtk_iommu_config(struct mtk_iommu_data *data,
+			     struct device *dev, bool enable)
+{
+	struct mtk_iommu_client_priv *head, *cur, *next;
+	struct mtk_smi_larb_iommu    *larb_mmu;
+	unsigned int                 larbid, portid;
+
+	head = dev->archdata.iommu;
+	list_for_each_entry_safe(cur, next, &head->client, client) {
+		larbid = mt2701_m4u_to_larb(cur->mtk_m4u_id);
+		portid = mt2701_m4u_to_port(cur->mtk_m4u_id);
+		larb_mmu = &data->smi_imu.larb_imu[larbid];
+
+		dev_dbg(dev, "%s iommu port: %d\n",
+			enable ? "enable" : "disable", portid);
+
+		if (enable)
+			larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
+		else
+			larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
+	}
+}
+
+static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data)
+{
+	struct mtk_iommu_domain *dom = data->m4u_dom;
+
+	spin_lock_init(&dom->pgtlock);
+
+	dom->pgt_va = dma_zalloc_coherent(data->dev,
+				M2701_IOMMU_PGT_SIZE,
+				&dom->pgt_pa, GFP_KERNEL);
+	if (!dom->pgt_va)
+		return -ENOMEM;
+
+	writel(dom->pgt_pa, data->base + REG_MMU_PT_BASE_ADDR);
+
+	dom->data = data;
+
+	return 0;
+}
+
+static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type)
+{
+	struct mtk_iommu_domain *dom;
+
+	if (type != IOMMU_DOMAIN_UNMANAGED)
+		return NULL;
+
+	dom = kzalloc(sizeof(*dom), GFP_KERNEL);
+	if (!dom)
+		return NULL;
+
+	return &dom->domain;
+}
+
+static void mtk_iommu_domain_free(struct iommu_domain *domain)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct mtk_iommu_data *data = dom->data;
+
+	dma_free_coherent(data->dev, M2701_IOMMU_PGT_SIZE,
+			dom->pgt_va, dom->pgt_pa);
+	kfree(to_mtk_domain(domain));
+}
+
+static int mtk_iommu_attach_device(struct iommu_domain *domain,
+				   struct device *dev)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
+	struct mtk_iommu_data *data;
+	int ret;
+
+	if (!priv)
+		return -ENODEV;
+
+	data = dev_get_drvdata(priv->m4udev);
+	if (!data->m4u_dom) {
+		data->m4u_dom = dom;
+		ret = mtk_iommu_domain_finalise(data);
+		if (ret) {
+			data->m4u_dom = NULL;
+			return ret;
+		}
+	}
+
+	mtk_iommu_config(data, dev, true);
+	return 0;
+}
+
+static void mtk_iommu_detach_device(struct iommu_domain *domain,
+				    struct device *dev)
+{
+	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
+	struct mtk_iommu_data *data;
+
+	if (!priv)
+		return;
+
+	data = dev_get_drvdata(priv->m4udev);
+	mtk_iommu_config(data, dev, false);
+}
+
+static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
+			 phys_addr_t paddr, size_t size, int prot)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT;
+	unsigned long flags;
+	unsigned int i;
+	u32 *pgt_base_iova = dom->pgt_va + (iova  >> MT2701_IOMMU_PAGE_SHIFT);
+	u32 pabase = (u32)paddr;
+	int map_size = 0;
+
+	spin_lock_irqsave(&dom->pgtlock, flags);
+	for (i = 0; i < page_num; i++) {
+		if (pgt_base_iova[i]) {
+			memset(pgt_base_iova, 0, i * sizeof(u32));
+			break;
+		}
+		pgt_base_iova[i] = pabase | F_DESC_VALID | F_DESC_NONSEC;
+		pabase += MT2701_IOMMU_PAGE_SIZE;
+		map_size += MT2701_IOMMU_PAGE_SIZE;
+	}
+
+	spin_unlock_irqrestore(&dom->pgtlock, flags);
+
+	mtk_iommu_tlb_flush_range(dom->data, iova, size);
+
+	return map_size == size ? 0 : -EEXIST;
+}
+
+static size_t mtk_iommu_unmap(struct iommu_domain *domain,
+			      unsigned long iova, size_t size)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	unsigned long flags;
+	u32 *pgt_base_iova = dom->pgt_va + (iova  >> MT2701_IOMMU_PAGE_SHIFT);
+	unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT;
+
+	spin_lock_irqsave(&dom->pgtlock, flags);
+	memset(pgt_base_iova, 0, page_num * sizeof(u32));
+	spin_unlock_irqrestore(&dom->pgtlock, flags);
+
+	mtk_iommu_tlb_flush_range(dom->data, iova, size);
+
+	return size;
+}
+
+static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
+					  dma_addr_t iova)
+{
+	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+	unsigned long flags;
+	phys_addr_t pa;
+
+	spin_lock_irqsave(&dom->pgtlock, flags);
+	pa = *(dom->pgt_va + (iova >> MT2701_IOMMU_PAGE_SHIFT));
+	pa = pa & (~(MT2701_IOMMU_PAGE_SIZE - 1));
+	spin_unlock_irqrestore(&dom->pgtlock, flags);
+
+	return pa;
+}
+
+/*
+ * MTK generation one iommu HW only support one iommu domain, and all the client
+ * sharing the same iova address space.
+ */
+static int mtk_iommu_create_mapping(struct device *dev,
+				    struct of_phandle_args *args)
+{
+	struct mtk_iommu_client_priv *head, *priv, *next;
+	struct platform_device *m4updev;
+	struct dma_iommu_mapping *mtk_mapping;
+	struct device *m4udev;
+	int ret;
+
+	if (args->args_count != 1) {
+		dev_err(dev, "invalid #iommu-cells(%d) property for IOMMU\n",
+			args->args_count);
+		return -EINVAL;
+	}
+
+	if (!dev->archdata.iommu) {
+		/* Get the m4u device */
+		m4updev = of_find_device_by_node(args->np);
+		of_node_put(args->np);
+		if (WARN_ON(!m4updev))
+			return -EINVAL;
+
+		head = kzalloc(sizeof(*head), GFP_KERNEL);
+		if (!head)
+			return -ENOMEM;
+
+		dev->archdata.iommu = head;
+		INIT_LIST_HEAD(&head->client);
+		head->m4udev = &m4updev->dev;
+	} else {
+		head = dev->archdata.iommu;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto err_free_mem;
+	}
+	priv->mtk_m4u_id = args->args[0];
+	list_add_tail(&priv->client, &head->client);
+
+	m4udev = head->m4udev;
+	mtk_mapping = m4udev->archdata.iommu;
+	if (!mtk_mapping) {
+		/* MTK iommu support 4GB iova address space. */
+		mtk_mapping = arm_iommu_create_mapping(&platform_bus_type,
+						0, 1ULL << 32);
+		if (IS_ERR(mtk_mapping)) {
+			ret = PTR_ERR(mtk_mapping);
+			goto err_free_mem;
+		}
+		m4udev->archdata.iommu = mtk_mapping;
+	}
+
+	ret = arm_iommu_attach_device(dev, mtk_mapping);
+	if (ret)
+		goto err_release_mapping;
+
+	return 0;
+
+err_release_mapping:
+	arm_iommu_release_mapping(mtk_mapping);
+	m4udev->archdata.iommu = NULL;
+err_free_mem:
+	list_for_each_entry_safe(priv, next, &head->client, client)
+		kfree(priv);
+	kfree(head);
+	dev->archdata.iommu = NULL;
+	return ret;
+}
+
+static int mtk_iommu_add_device(struct device *dev)
+{
+	struct iommu_group *group;
+	struct of_phandle_args iommu_spec;
+	struct of_phandle_iterator it;
+	int err;
+
+	of_for_each_phandle(&it, err, dev->of_node, "iommus",
+			"#iommu-cells", 0) {
+		int count = of_phandle_iterator_args(&it, iommu_spec.args,
+					MAX_PHANDLE_ARGS);
+		iommu_spec.np = of_node_get(it.node);
+		iommu_spec.args_count = count;
+
+		mtk_iommu_create_mapping(dev, &iommu_spec);
+		of_node_put(iommu_spec.np);
+	}
+
+	if (!dev->archdata.iommu) /* Not a iommu client device */
+		return -ENODEV;
+
+	group = iommu_group_get_for_dev(dev);
+	if (IS_ERR(group))
+		return PTR_ERR(group);
+
+	iommu_group_put(group);
+	return 0;
+}
+
+static void mtk_iommu_remove_device(struct device *dev)
+{
+	struct mtk_iommu_client_priv *head, *cur, *next;
+
+	head = dev->archdata.iommu;
+	if (!head)
+		return;
+
+	list_for_each_entry_safe(cur, next, &head->client, client) {
+		list_del(&cur->client);
+		kfree(cur);
+	}
+	kfree(head);
+	dev->archdata.iommu = NULL;
+
+	iommu_group_remove_device(dev);
+}
+
+static struct iommu_group *mtk_iommu_device_group(struct device *dev)
+{
+	struct mtk_iommu_data *data;
+	struct mtk_iommu_client_priv *priv;
+
+	priv = dev->archdata.iommu;
+	if (!priv)
+		return ERR_PTR(-ENODEV);
+
+	/* All the client devices are in the same m4u iommu-group */
+	data = dev_get_drvdata(priv->m4udev);
+	if (!data->m4u_group) {
+		data->m4u_group = iommu_group_alloc();
+		if (IS_ERR(data->m4u_group))
+			dev_err(dev, "Failed to allocate M4U IOMMU group\n");
+	}
+	return data->m4u_group;
+}
+
+static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
+{
+	u32 regval;
+	int ret;
+
+	ret = clk_prepare_enable(data->bclk);
+	if (ret) {
+		dev_err(data->dev, "Failed to enable iommu bclk(%d)\n", ret);
+		return ret;
+	}
+
+	regval = F_MMU_CTRL_COHERENT_EN | F_MMU_TF_PROTECT_SEL(2);
+	writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
+
+	regval = F_INT_TRANSLATION_FAULT |
+		F_INT_MAIN_MULTI_HIT_FAULT |
+		F_INT_INVALID_PA_FAULT |
+		F_INT_ENTRY_REPLACEMENT_FAULT |
+		F_INT_TABLE_WALK_FAULT |
+		F_INT_TLB_MISS_FAULT |
+		F_INT_PFH_DMA_FIFO_OVERFLOW |
+		F_INT_MISS_DMA_FIFO_OVERFLOW;
+	writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL);
+
+	/* protect memory,hw will write here while translation fault */
+	writel_relaxed(data->protect_base,
+			data->base + REG_MMU_IVRP_PADDR);
+
+	writel_relaxed(F_MMU_DCM_ON, data->base + REG_MMU_DCM);
+
+	if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
+			     dev_name(data->dev), (void *)data)) {
+		writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR);
+		clk_disable_unprepare(data->bclk);
+		dev_err(data->dev, "Failed @ IRQ-%d Request\n", data->irq);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static struct iommu_ops mtk_iommu_ops = {
+	.domain_alloc	= mtk_iommu_domain_alloc,
+	.domain_free	= mtk_iommu_domain_free,
+	.attach_dev	= mtk_iommu_attach_device,
+	.detach_dev	= mtk_iommu_detach_device,
+	.map		= mtk_iommu_map,
+	.unmap		= mtk_iommu_unmap,
+	.map_sg		= default_iommu_map_sg,
+	.iova_to_phys	= mtk_iommu_iova_to_phys,
+	.add_device	= mtk_iommu_add_device,
+	.remove_device	= mtk_iommu_remove_device,
+	.device_group	= mtk_iommu_device_group,
+	.pgsize_bitmap	= ~0UL << MT2701_IOMMU_PAGE_SHIFT,
+};
+
+static const struct of_device_id mtk_iommu_of_ids[] = {
+	{ .compatible = "mediatek,mt2701-m4u", },
+	{}
+};
+
+static const struct component_master_ops mtk_iommu_com_ops = {
+	.bind		= mtk_iommu_bind,
+	.unbind		= mtk_iommu_unbind,
+};
+
+static int mtk_iommu_probe(struct platform_device *pdev)
+{
+	struct mtk_iommu_data		*data;
+	struct device			*dev = &pdev->dev;
+	struct resource			*res;
+	struct component_match		*match = NULL;
+	struct of_phandle_args		larb_spec;
+	struct of_phandle_iterator	it;
+	void				*protect;
+	int				larb_nr, ret, err;
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->dev = dev;
+
+	/* Protect memory. HW will access here while translation fault.*/
+	protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2,
+			GFP_KERNEL | GFP_DMA);
+	if (!protect)
+		return -ENOMEM;
+	data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(data->base))
+		return PTR_ERR(data->base);
+
+	data->irq = platform_get_irq(pdev, 0);
+	if (data->irq < 0)
+		return data->irq;
+
+	data->bclk = devm_clk_get(dev, "bclk");
+	if (IS_ERR(data->bclk))
+		return PTR_ERR(data->bclk);
+
+	larb_nr = 0;
+	of_for_each_phandle(&it, err, dev->of_node,
+			"mediatek,larbs", NULL, 0) {
+		struct platform_device *plarbdev;
+		int count = of_phandle_iterator_args(&it, larb_spec.args,
+					MAX_PHANDLE_ARGS);
+
+		if (count)
+			continue;
+
+		larb_spec.np = of_node_get(it.node);
+		if (!of_device_is_available(larb_spec.np))
+			continue;
+
+		plarbdev = of_find_device_by_node(larb_spec.np);
+		of_node_put(larb_spec.np);
+		if (!plarbdev) {
+			plarbdev = of_platform_device_create(
+						larb_spec.np, NULL,
+						platform_bus_type.dev_root);
+			if (!plarbdev)
+				return -EPROBE_DEFER;
+		}
+
+		data->smi_imu.larb_imu[larb_nr].dev = &plarbdev->dev;
+		component_match_add(dev, &match, compare_of, larb_spec.np);
+		larb_nr++;
+	}
+
+	data->smi_imu.larb_nr = larb_nr;
+
+	platform_set_drvdata(pdev, data);
+
+	ret = mtk_iommu_hw_init(data);
+	if (ret)
+		return ret;
+
+	if (!iommu_present(&platform_bus_type))
+		bus_set_iommu(&platform_bus_type,  &mtk_iommu_ops);
+
+	return component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
+}
+
+static int mtk_iommu_remove(struct platform_device *pdev)
+{
+	struct mtk_iommu_data *data = platform_get_drvdata(pdev);
+
+	if (iommu_present(&platform_bus_type))
+		bus_set_iommu(&platform_bus_type, NULL);
+
+	clk_disable_unprepare(data->bclk);
+	devm_free_irq(&pdev->dev, data->irq, data);
+	component_master_del(&pdev->dev, &mtk_iommu_com_ops);
+	return 0;
+}
+
+static int __maybe_unused mtk_iommu_suspend(struct device *dev)
+{
+	struct mtk_iommu_data *data = dev_get_drvdata(dev);
+	struct mtk_iommu_suspend_reg *reg = &data->reg;
+	void __iomem *base = data->base;
+
+	reg->standard_axi_mode = readl_relaxed(base +
+					       REG_MMU_STANDARD_AXI_MODE);
+	reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM);
+	reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG);
+	reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL);
+	return 0;
+}
+
+static int __maybe_unused mtk_iommu_resume(struct device *dev)
+{
+	struct mtk_iommu_data *data = dev_get_drvdata(dev);
+	struct mtk_iommu_suspend_reg *reg = &data->reg;
+	void __iomem *base = data->base;
+
+	writel_relaxed(data->m4u_dom->pgt_pa, base + REG_MMU_PT_BASE_ADDR);
+	writel_relaxed(reg->standard_axi_mode,
+		       base + REG_MMU_STANDARD_AXI_MODE);
+	writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM);
+	writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG);
+	writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL);
+	writel_relaxed(data->protect_base, base + REG_MMU_IVRP_PADDR);
+	return 0;
+}
+
+const struct dev_pm_ops mtk_iommu_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume)
+};
+
+static struct platform_driver mtk_iommu_driver = {
+	.probe	= mtk_iommu_probe,
+	.remove	= mtk_iommu_remove,
+	.driver	= {
+		.name = "mtk-iommu",
+		.of_match_table = mtk_iommu_of_ids,
+		.pm = &mtk_iommu_pm_ops,
+	}
+};
+
+static int __init m4u_init(void)
+{
+	return platform_driver_register(&mtk_iommu_driver);
+}
+
+static void __exit m4u_exit(void)
+{
+	return platform_driver_unregister(&mtk_iommu_driver);
+}
+
+subsys_initcall(m4u_init);
+module_exit(m4u_exit);
+
+MODULE_DESCRIPTION("IOMMU API for MTK architected m4u v1 implementations");
+MODULE_AUTHOR("Honghui Zhang <honghui.zhang at mediatek.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.8.1.1.dirty



From honghui.zhang at mediatek.com  Fri May 27 01:56:40 2016
From: honghui.zhang at mediatek.com (honghui.zhang at mediatek.com)
Date: Fri, 27 May 2016 16:56:40 +0800
Subject: [PATCH v3 5/5] ARM: dts: mt2701: add iommu/smi dtsi node for mt2701
In-Reply-To: <1464339400-22559-1-git-send-email-honghui.zhang@mediatek.com>
References: <1464339400-22559-1-git-send-email-honghui.zhang@mediatek.com>
Message-ID: <1464339400-22559-6-git-send-email-honghui.zhang@mediatek.com>

From: Honghui Zhang <honghui.zhang at mediatek.com>

Add the dtsi node of iommu and smi for mt2701.

Signed-off-by: Honghui Zhang <honghui.zhang at mediatek.com>
---
 arch/arm/boot/dts/mt2701.dtsi | 51 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 42d5a37..363de0d 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -16,6 +16,7 @@
 #include <dt-bindings/power/mt2701-power.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/memory/mt2701-larb-port.h>
 #include "skeleton64.dtsi"
 #include "mt2701-pinfunc.h"
 
@@ -160,6 +161,16 @@
 		clock-names = "system-clk", "rtc-clk";
 	};
 
+	smi_common: smi at 1000c000 {
+		compatible = "mediatek,mt2701-smi-common";
+		reg = <0 0x1000c000 0 0x1000>;
+		clocks = <&infracfg CLK_INFRA_SMI>,
+			 <&mmsys CLK_MM_SMI_COMMON>,
+			 <&infracfg CLK_INFRA_SMI>;
+		clock-names = "apb", "smi", "async";
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
+	};
+
 	sysirq: interrupt-controller at 10200100 {
 		compatible = "mediatek,mt2701-sysirq",
 			     "mediatek,mt6577-sysirq";
@@ -169,6 +180,16 @@
 		reg = <0 0x10200100 0 0x1c>;
 	};
 
+	iommu: mmsys_iommu at 10205000 {
+		compatible = "mediatek,mt2701-m4u";
+		reg = <0 0x10205000 0 0x1000>;
+		interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&infracfg CLK_INFRA_M4U>;
+		clock-names = "bclk";
+		mediatek,larbs = <&larb0 &larb1 &larb2>;
+		#iommu-cells = <1>;
+	};
+
 	apmixedsys: syscon at 10209000 {
 		compatible = "mediatek,mt2701-apmixedsys", "syscon";
 		reg = <0 0x10209000 0 0x1000>;
@@ -234,6 +255,16 @@
 		status = "disabled";
 	};
 
+	larb0: larb at 14010000 {
+		compatible = "mediatek,mt2701-smi-larb";
+		reg = <0 0x14010000 0 0x1000>;
+		mediatek,smi = <&smi_common>;
+		clocks = <&mmsys CLK_MM_SMI_LARB0>,
+			 <&mmsys CLK_MM_SMI_LARB0>;
+		clock-names = "apb", "smi";
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
+	};
+
 	imgsys: syscon at 15000000 {
 		compatible = "mediatek,mt2701-imgsys", "syscon";
 		reg = <0 0x15000000 0 0x1000>;
@@ -241,6 +272,16 @@
 		status = "disabled";
 	};
 
+	larb2: larb at 15001000 {
+		compatible = "mediatek,mt2701-smi-larb";
+		reg = <0 0x15001000 0 0x1000>;
+		mediatek,smi = <&smi_common>;
+		clocks = <&imgsys CLK_IMG_SMI_COMM>,
+			 <&imgsys CLK_IMG_SMI_COMM>;
+		clock-names = "apb", "smi";
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_ISP>;
+	};
+
 	vdecsys: syscon at 16000000 {
 		compatible = "mediatek,mt2701-vdecsys", "syscon";
 		reg = <0 0x16000000 0 0x1000>;
@@ -248,6 +289,16 @@
 		status = "disabled";
 	};
 
+	larb1: larb at 16010000 {
+		compatible = "mediatek,mt2701-smi-larb";
+		reg = <0 0x16010000 0 0x1000>;
+		mediatek,smi = <&smi_common>;
+		clocks = <&vdecsys CLK_VDEC_CKGEN>,
+			 <&vdecsys CLK_VDEC_LARB>;
+		clock-names = "apb", "smi";
+		power-domains = <&scpsys MT2701_POWER_DOMAIN_VDEC>;
+	};
+
 	hifsys: syscon at 1a000000 {
 		compatible = "mediatek,mt2701-hifsys", "syscon";
 		reg = <0 0x1a000000 0 0x1000>;
-- 
1.8.1.1.dirty



From catalin.marinas at arm.com  Fri May 27 02:01:42 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 27 May 2016 10:01:42 +0100
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160527060357.GB3820@osiris>
References: <6293194.tGy03QJ9ME@wuerfel>
 <20160525.135039.244098606649448826.davem@davemloft.net>
 <6407614.fdv5XFSBue@wuerfel>
 <20160525.142821.1719403997976778673.davem@davemloft.net>
 <20160526204819.GA10274@yury-N73SV>
 <20160526222943.GA16729@MBP.local>
 <20160527003753.GA14247@yury-N73SV> <20160527060357.GB3820@osiris>
Message-ID: <20160527090141.GA7865@e104818-lin.cambridge.arm.com>

On Fri, May 27, 2016 at 08:03:57AM +0200, Heiko Carstens wrote:
> > > > The cost is pretty trivial though. See kernel/compat_wrapper.o:
> > > > COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
> > > > 0:   a9bf7bfd        stp     x29, x30, [sp,#-16]!
> > > > 4:   910003fd        mov     x29, sp
> > > > 8:   2a0003e0        mov     w0, w0
> > > > c:   94000000        bl      0 <sys_creat>
> > > > 10:  a8c17bfd        ldp     x29, x30, [sp],#16
> > > > 14:  d65f03c0        ret
> > > 
> > > I would say the above could be more expensive than 8 movs (16 bytes to
> > > write, read, a branch and a ret). You can also add the I-cache locality,
> > > having wrappers for each syscalls instead of a single place for zeroing
> > > the upper half (where no other wrapper is necessary).
> > > 
> > > Can we trick the compiler into doing a tail call optimisation. This
> > > could have simply been:
> > > 
> > > COMPAT_SYSCALL_WRAP2(creat, ...):
> > > 	mov	w0, w0
> > > 	b	<sys_creat>
> > 
> > What you talk about was in my initial version. But Heiko insisted on having all
> > wrappers together.
> > http://www.spinics.net/lists/linux-s390/msg11593.html
> > 
> > Grep your email for discussion.
> 
> I think Catalin's question was more about why there is even a stack frame
> generated. It looks like it is not necessary. I did ask this too a couple
> of months ago, when we discussed this.

Indeed, I was questioning the need for prologue/epilogue, not the use of
COMPAT_SYSCALL_WRAPx(). Maybe something like __naked would do.

> > > > > Cost wise, this seems like it all cancels out in the end, but what
> > > > > do I know?
> > > > 
> > > > I think you know something, and I also think Heiko and other s390 guys
> > > > know something as well. So I'd like to listen their arguments here.
> 
> If it comes to 64 bit arguments for compat system calls: s390 also has an
> x32-like ABI extension which allows user space to use full 64 bit
> registers. As far as I know hardly anybody ever made use of that.
> 
> However even if that would be widely used, to me it wouldn't make sense to
> add new compat system calls which allow 64 bit arguments, simply because
> something like
> 
> c = (u32)a | (u64)b << 32;
> 
> can be done with a single 1-cycle instruction. It's just not worth the
> extra effort to maintain additional system call variants.

If we split 64-bit arguments in two, we can go a step further and avoid
most of the COMPAT_SYSCALL_WRAPx annotations in favour of a common
upper-half zeroing of the argument registers on ILP32 syscall entry.
There would be a few exceptions where we need to re-build 64-bit
arguments on sign-extend.

-- 
Catalin


From emil.l.velikov at gmail.com  Fri May 27 02:24:57 2016
From: emil.l.velikov at gmail.com (Emil Velikov)
Date: Fri, 27 May 2016 10:24:57 +0100
Subject: [RFC v2 3/5] drm/mediatek: add *driver_data for different
 hardware settings
In-Reply-To: <1464334313.31149.16.camel@mtksdaap41>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
 <1463756736-46573-4-git-send-email-yt.shen@mediatek.com>
 <1463996582.30093.5.camel@mtksdaap41>
 <1464334313.31149.16.camel@mtksdaap41>
Message-ID: <CACvgo52xB0KwumC75u2dxfz_yv2PNE0Gem+0t8dqV9qn+pPRLg@mail.gmail.com>

On 27 May 2016 at 08:31, YT Shen <yt.shen at mediatek.com> wrote:
> Hi CK,
>
>
> On Mon, 2016-05-23 at 17:43 +0800, CK Hu wrote:
>> Hi, YT:
>>
>> One comment below.
>>
>> On Fri, 2016-05-20 at 23:05 +0800, yt.shen at mediatek.com wrote:
>> > From: YT Shen <yt.shen at mediatek.com>
>> >
>> > There are some hardware settings changed, between MT8173 & MT2701:
>> > DISP_OVL address offset changed, color format definition changed.
>> > DISP_RDMA fifo size changed.
>> > DISP_COLOR offset changed.
>> >
>> > Signed-off-by: YT Shen <yt.shen at mediatek.com>
>> > ---
>> > +
>> > +static inline struct mtk_ddp_comp_driver_data *mtk_ovl_get_driver_data(
>> > +   struct platform_device *pdev)
>> > +{
>> > +   const struct of_device_id *of_id =
>> > +           of_match_device(mtk_disp_ovl_driver_dt_match, &pdev->dev);
>> > +
>> > +   return (struct mtk_ddp_comp_driver_data *)of_id->data;
>> > +}
>> > +
>> > +static inline struct mtk_ddp_comp_driver_data *mtk_rdma_get_driver_data(
>> > +   struct platform_device *pdev)
>> > +{
>> > +   const struct of_device_id *of_id =
>> > +           of_match_device(mtk_disp_rdma_driver_dt_match, &pdev->dev);
>> > +
>> > +   return (struct mtk_ddp_comp_driver_data *)of_id->data;
>> > +}
>> > +
>> > +static inline struct mtk_ddp_comp_driver_data *mtk_color_get_driver_data(
>> > +   struct device_node *node)
>> > +{
>> > +   const struct of_device_id *of_id =
>> > +           of_match_node(mtk_disp_color_driver_dt_match, node);
>> > +
>> > +   return (struct mtk_ddp_comp_driver_data *)of_id->data;
>> > +}
>> > +
>>
>> These three functions looks the same with different parameter:
>> mtk_disp_ovl_driver_dt_match, mtk_disp_rdma_driver_dt_match, and
>> mtk_disp_color_driver_dt_match. So merge them to prevent duplicated
>> code.
> OK, I'll do this in the next version.

Also preserve the const-ness of the data - don't cast it away on the
return line.
Note that the function return type (and some of the users of said
functions) should be updated as well.

-Emil


From dennis.chen at arm.com  Fri May 27 02:27:24 2016
From: dennis.chen at arm.com (Dennis Chen)
Date: Fri, 27 May 2016 17:27:24 +0800
Subject: [PATCH v2] arm64:efi fix the format of debug message from efi
Message-ID: <1464341244-14152-1-git-send-email-dennis.chen@arm.com>

When enable debug of efi and memblock with 'efi=debug memblock=debug' appended
to the kernel command line, the debug message output for earyly_con looks like:

[    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] memblock_add: [0x00008000000000-0x00008001e7ffff] flags 0x0 early_init_dt_add_memory_arch+0x54/0x5c
[    0.000000] *
...

This patch is trying to fix the above output messed up by memblock_add(), so we can get below debug mesg looks
more formally after applied:

[    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] memblock_add: [0x00008000000000-0x00008001e7ffff] flags 0x0 early_init_dt_add_memory_arch+0x54/0x5c
...

Signed-off-by: Dennis Chen <dennis.chen at arm.com>
Acked-by: Mark Rutland <mark.rutland at arm.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Steve Capper <steve.capper at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org>
Cc: Matt Fleming <matt at codeblueprint.co.uk>
Cc: linux-efi at vger.kernel.org

Since v1[1]:
 According to the suggestion from Mark Rutland, v2 folds the pr_cont("\n") into pr_info.
 [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-May/431233.html
---
 drivers/firmware/efi/arm-init.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index a850cbc..c49d50e 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -174,6 +174,7 @@ static __init void reserve_regions(void)
 {
 	efi_memory_desc_t *md;
 	u64 paddr, npages, size;
+	int resv;
 
 	if (efi_enabled(EFI_DBG))
 		pr_info("Processing EFI memory map:\n");
@@ -190,12 +191,14 @@ static __init void reserve_regions(void)
 		paddr = md->phys_addr;
 		npages = md->num_pages;
 
+		resv = is_reserve_region(md);
 		if (efi_enabled(EFI_DBG)) {
 			char buf[64];
 
-			pr_info("  0x%012llx-0x%012llx %s",
+			pr_info("  0x%012llx-0x%012llx %s%s\n",
 				paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
-				efi_md_typeattr_format(buf, sizeof(buf), md));
+				efi_md_typeattr_format(buf, sizeof(buf), md),
+				resv ? "*" : "");
 		}
 
 		memrange_efi_to_native(&paddr, &npages);
@@ -204,14 +207,9 @@ static __init void reserve_regions(void)
 		if (is_normal_ram(md))
 			early_init_dt_add_memory_arch(paddr, size);
 
-		if (is_reserve_region(md)) {
+		if (resv)
 			memblock_mark_nomap(paddr, size);
-			if (efi_enabled(EFI_DBG))
-				pr_cont("*");
-		}
 
-		if (efi_enabled(EFI_DBG))
-			pr_cont("\n");
 	}
 
 	set_bit(EFI_MEMMAP, &efi.flags);
-- 
2.7.4



From emil.l.velikov at gmail.com  Fri May 27 02:30:34 2016
From: emil.l.velikov at gmail.com (Emil Velikov)
Date: Fri, 27 May 2016 10:30:34 +0100
Subject: [RFC v2 1/5] drm/mediatek: rename macros, add chip suffix
In-Reply-To: <1463756736-46573-2-git-send-email-yt.shen@mediatek.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
 <1463756736-46573-2-git-send-email-yt.shen@mediatek.com>
Message-ID: <CACvgo506uzWug+mEk5OOs-6M9WZnOc-FBChGcf-4DcqqotHpHA@mail.gmail.com>

On 20 May 2016 at 16:05,  <yt.shen at mediatek.com> wrote:
> From: YT Shen <yt.shen at mediatek.com>
>
> Add MT8173 suffix for hardware related macros.
>
Why suffix ? Pretty much everyone else uses prefix.

-Emil


From catalin.marinas at arm.com  Fri May 27 02:30:52 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 27 May 2016 10:30:52 +0100
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <13240365.okADkKsTBJ@wuerfel>
References: <6293194.tGy03QJ9ME@wuerfel> <20160527003753.GA14247@yury-N73SV>
 <20160527060357.GB3820@osiris> <13240365.okADkKsTBJ@wuerfel>
Message-ID: <20160527093052.GB7865@e104818-lin.cambridge.arm.com>

On Fri, May 27, 2016 at 10:42:59AM +0200, Arnd Bergmann wrote:
> On Friday, May 27, 2016 8:03:57 AM CEST Heiko Carstens wrote:
> > > > > > Cost wise, this seems like it all cancels out in the end, but what
> > > > > > do I know?
> > > > > 
> > > > > I think you know something, and I also think Heiko and other s390 guys
> > > > > know something as well. So I'd like to listen their arguments here.
> > 
> > If it comes to 64 bit arguments for compat system calls: s390 also has an
> > x32-like ABI extension which allows user space to use full 64 bit
> > registers. As far as I know hardly anybody ever made use of that.
> > 
> > However even if that would be widely used, to me it wouldn't make sense to
> > add new compat system calls which allow 64 bit arguments, simply because
> > something like
> > 
> > c = (u32)a | (u64)b << 32;
> > 
> > can be done with a single 1-cycle instruction. It's just not worth the
> > extra effort to maintain additional system call variants.
> 
> For reference, both tile and mips also have separate 32-bit ABIs that are
> only used on 64-bit kernels (aside from the normal 32-bit ABI). Tile
> does it like s390 and passes 64-bit arguments as pairs, while MIPS
> and x86 and pass them as single registers.

AFAIK, x32 also requires that the upper half of a 64-bit reg is zeroed
by the user when a 32-bit value is passed. We could require the same on
AArch64/ILP32 but I'm a bit uneasy on trusting a multitude of C
libraries on this.

-- 
Catalin


From emil.l.velikov at gmail.com  Fri May 27 02:35:20 2016
From: emil.l.velikov at gmail.com (Emil Velikov)
Date: Fri, 27 May 2016 10:35:20 +0100
Subject: [RFC v2 2/5] drm/mediatke: add support for Mediatek SoC MT2701
In-Reply-To: <1463756736-46573-3-git-send-email-yt.shen@mediatek.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
 <1463756736-46573-3-git-send-email-yt.shen@mediatek.com>
Message-ID: <CACvgo51gUVtVZtanQh787YeB8F_WHsNx6b1Oi0iBAEYLWZtJMw@mail.gmail.com>

Hi YT Shen,

There's a typo in the commit summary - s/mediatke/mediatek/.

On 20 May 2016 at 16:05,  <yt.shen at mediatek.com> wrote:
> From: YT Shen <yt.shen at mediatek.com>
>
> This patch add support for the Mediatek MT2701 DISP subsystem.
> There is only one OVL engine in MT2701.
>
As is you introduce a broken driver only to fix it up with patches 3/5
and 4/5. You really want to have this patch as 4/5, with the MT2701
hunks from 3/5 merged in here.

Regards,
Emil


From catalin.marinas at arm.com  Fri May 27 03:10:37 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 27 May 2016 11:10:37 +0100
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160526.124344.1660236473079504674.davem@davemloft.net>
References: <6407614.fdv5XFSBue@wuerfel>
 <20160525.142821.1719403997976778673.davem@davemloft.net>
 <20160526142057.GA7456@e104818-lin.cambridge.arm.com>
 <20160526.124344.1660236473079504674.davem@davemloft.net>
Message-ID: <20160527101036.GC7865@e104818-lin.cambridge.arm.com>

On Thu, May 26, 2016 at 12:43:44PM -0700, David Miller wrote:
> From: Catalin Marinas <catalin.marinas at arm.com>
> Date: Thu, 26 May 2016 15:20:58 +0100
> 
> > We can solve (a) by adding more __SC_WRAP annotations in the generic
> > unistd.h.
>  ...
> 
> I really think it's much more robust to clear the tops of the registers
> by default.  Then you won't be auditing constantly and adding more and
> more wrappers.

I think we could avoid adding a new __SC_WRAP by redefining __SYSCALL
for ILP32 to always invoke a wrapper. But given the wrapper overhead,
cache locality, I don't think we would notice any performance difference
in either case.

> You can't even quantify the performance gains for me in any precise
> way.  Whatever you gain by avoiding the 64-bit
> decompostion/reconstitution for those few system calls with 64-bit
> registers, you are losing by calling the wrappers for more common
> system calls, more often.

I hope Yury can provide some numbers. All being equal, I would go for
the lowest code maintenance cost (which is probably less annotations and
wrappers).

> "it's more natural to pass 64-bit values in a register" is not a clear
> justification for this change.

It's more related to how we went about the ILP32 ABI. We initially asked
for a 64-bit native ABI similar to x32 until the libc-alpha community
raised some POSIX compliance issues on time structures. So we decided to
go for a 32-bit-like ABI while keeping the syscall interface close to
the AArch64/ILP32 procedure calling standard (64-bit values passed in a
single register). And now we have this discussion, revisiting this
decision again (which is perfectly fine, we better get it right before
any merging plans; thanks for your input).

-- 
Catalin


From yendapally.reddy at broadcom.com  Fri May 27 03:10:37 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Fri, 27 May 2016 06:10:37 -0400
Subject: [PATCH v2 0/4] hw rng support for NSP SoC
Message-ID: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>

This patchset contains the hw random number generator support for the
Broadcom's NSP SoC. The block is similar to the block available in
bcm2835 with different default interrupt mask value. Due to lack of
documentation, I cannot confirm the interrupt mask register details
in bcm2835. In an effort to not break the existing functionality of
bcm2835, I used a different compatible string to mask the interrupt
for NSP SoC. Please let me know. Also supported providing requested
number of random numbers instead of static size of four bytes.

The first patch contains the documentation changes and the second patch
contains the support for rng available in NSP SoC. The third patch
contains the device tree changes for NSP SoC. The fourth patch contains
the support for reading requested number of random numbers.

This patch set has been tested on NSP bcm958625HR board.
This patch set is based on v4.6.0-rc1 and is available from github
repo: https://github.com/Broadcom/cygnus-linux.git
branch: nsp-rng-v2

Changes since v1

Addressed the review comments from Eric
Added acked by Eric

Yendapally Reddy Dhananjaya Reddy (4):
  dt-bindings: rng: Northstar Plus SoC rng bindings
  hwrng: bcm2835: Support Broadcom NSP SoC rng
  ARM: dts: nsp: Add rng device tree entry
  hwrng: bcm2835: Read as much data as available

 .../devicetree/bindings/rng/brcm,bcm2835.txt       |  7 +++-
 arch/arm/boot/dts/bcm-nsp.dtsi                     |  5 +++
 drivers/char/hw_random/Kconfig                     |  2 +-
 drivers/char/hw_random/bcm2835-rng.c               | 46 +++++++++++++++++++---
 4 files changed, 52 insertions(+), 8 deletions(-)

-- 
2.1.0



From yendapally.reddy at broadcom.com  Fri May 27 03:10:38 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Fri, 27 May 2016 06:10:38 -0400
Subject: [PATCH v2 1/4] dt-bindings: rng: Northstar Plus SoC rng bindings
In-Reply-To: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1464343841-29504-2-git-send-email-yendapally.reddy@broadcom.com>

Document the bindings used by Northstar Plus(NSP) SoC random number
generator.

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
Acked-by: Eric Anholt <eric at anholt.net>
---
 Documentation/devicetree/bindings/rng/brcm,bcm2835.txt | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt b/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt
index 07ccdaa..aa304d4 100644
--- a/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt
+++ b/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt
@@ -2,7 +2,7 @@ BCM2835 Random number generator
 
 Required properties:
 
-- compatible : should be "brcm,bcm2835-rng"
+- compatible : should be "brcm,bcm2835-rng"  or "brcm,bcm-nsp-rng"
 - reg : Specifies base physical address and size of the registers.
 
 Example:
@@ -11,3 +11,8 @@ rng {
         compatible = "brcm,bcm2835-rng";
         reg = <0x7e104000 0x10>;
 };
+
+rng at 18033000 {
+	compatible = "brcm,bcm-nsp-rng";
+	reg = <0x18033000 0x14>;
+};
-- 
2.1.0



From yendapally.reddy at broadcom.com  Fri May 27 03:10:40 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Fri, 27 May 2016 06:10:40 -0400
Subject: [PATCH v2 3/4] ARM: dts: nsp: Add rng device tree entry
In-Reply-To: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1464343841-29504-4-git-send-email-yendapally.reddy@broadcom.com>

Add support for the random number generator to the Northstar Plus
SoC device tree.

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
---
 arch/arm/boot/dts/bcm-nsp.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi
index def9e78..1ed829e 100644
--- a/arch/arm/boot/dts/bcm-nsp.dtsi
+++ b/arch/arm/boot/dts/bcm-nsp.dtsi
@@ -206,6 +206,11 @@
 			brcm,nand-has-wp;
 		};
 
+		rng: rng at 33000 {
+			compatible = "brcm,bcm-nsp-rng";
+			reg = <0x33000 0x14>;
+		};
+
 		ccbtimer0: timer at 34000 {
 			compatible = "arm,sp804";
 			reg = <0x34000 0x1000>;
-- 
2.1.0



From yendapally.reddy at broadcom.com  Fri May 27 03:10:39 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Fri, 27 May 2016 06:10:39 -0400
Subject: [PATCH v2 2/4] hwrng: bcm2835: Support Broadcom NSP SoC rng
In-Reply-To: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1464343841-29504-3-git-send-email-yendapally.reddy@broadcom.com>

This supports the random number generator available in NSP SoC.
Masks the rng interrupt for NSP.

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
Acked-by: Eric Anholt <eric at anholt.net>
---
 drivers/char/hw_random/Kconfig       |  2 +-
 drivers/char/hw_random/bcm2835-rng.c | 34 ++++++++++++++++++++++++++++++----
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 67ee8b0..f8d1a2b 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -90,7 +90,7 @@ config HW_RANDOM_BCM63XX
 
 config HW_RANDOM_BCM2835
 	tristate "Broadcom BCM2835 Random Number Generator support"
-	depends on ARCH_BCM2835
+	depends on ARCH_BCM2835 || ARCH_BCM_NSP
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
index 7192ec2..b1e8b78 100644
--- a/drivers/char/hw_random/bcm2835-rng.c
+++ b/drivers/char/hw_random/bcm2835-rng.c
@@ -19,6 +19,7 @@
 #define RNG_CTRL	0x0
 #define RNG_STATUS	0x4
 #define RNG_DATA	0x8
+#define RNG_INT_MASK	0x10
 
 /* enable rng */
 #define RNG_RBGEN	0x1
@@ -26,6 +27,18 @@
 /* the initial numbers generated are "less random" so will be discarded */
 #define RNG_WARMUP_COUNT 0x40000
 
+#define RNG_INT_OFF	0x1
+
+static void __init nsp_rng_init(void __iomem *base)
+{
+	u32 val;
+
+	/* mask the interrupt */
+	val = readl(base + RNG_INT_MASK);
+	val |= RNG_INT_OFF;
+	writel(val, base + RNG_INT_MASK);
+}
+
 static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
 			       bool wait)
 {
@@ -46,10 +59,18 @@ static struct hwrng bcm2835_rng_ops = {
 	.read	= bcm2835_rng_read,
 };
 
+static const struct of_device_id bcm2835_rng_of_match[] = {
+	{ .compatible = "brcm,bcm2835-rng"},
+	{ .compatible = "brcm,bcm-nsp-rng", .data = nsp_rng_init},
+	{},
+};
+
 static int bcm2835_rng_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
+	void (*rng_setup)(void __iomem *base);
+	const struct of_device_id *rng_id;
 	void __iomem *rng_base;
 	int err;
 
@@ -61,6 +82,15 @@ static int bcm2835_rng_probe(struct platform_device *pdev)
 	}
 	bcm2835_rng_ops.priv = (unsigned long)rng_base;
 
+	rng_id = of_match_node(bcm2835_rng_of_match, np);
+	if (!rng_id)
+		return -EINVAL;
+
+	/* Check for rng init function, execute it */
+	rng_setup = rng_id->data;
+	if (rng_setup)
+		rng_setup(rng_base);
+
 	/* set warm-up count & enable */
 	__raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS);
 	__raw_writel(RNG_RBGEN, rng_base + RNG_CTRL);
@@ -90,10 +120,6 @@ static int bcm2835_rng_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static const struct of_device_id bcm2835_rng_of_match[] = {
-	{ .compatible = "brcm,bcm2835-rng", },
-	{},
-};
 MODULE_DEVICE_TABLE(of, bcm2835_rng_of_match);
 
 static struct platform_driver bcm2835_rng_driver = {
-- 
2.1.0



From yendapally.reddy at broadcom.com  Fri May 27 03:10:41 2016
From: yendapally.reddy at broadcom.com (Yendapally Reddy Dhananjaya Reddy)
Date: Fri, 27 May 2016 06:10:41 -0400
Subject: [PATCH v2 4/4] hwrng: bcm2835: Read as much data as available
In-Reply-To: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <1464343841-29504-5-git-send-email-yendapally.reddy@broadcom.com>

Read the requested number of data from the fifo

Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy at broadcom.com>
Reviewed-by: Eric Anholt <eric at anholt.net>
---
 drivers/char/hw_random/bcm2835-rng.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
index b1e8b78..75ca820 100644
--- a/drivers/char/hw_random/bcm2835-rng.c
+++ b/drivers/char/hw_random/bcm2835-rng.c
@@ -43,6 +43,8 @@ static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
 			       bool wait)
 {
 	void __iomem *rng_base = (void __iomem *)rng->priv;
+	u32 max_words = max / sizeof(u32);
+	u32 num_words, count;
 
 	while ((__raw_readl(rng_base + RNG_STATUS) >> 24) == 0) {
 		if (!wait)
@@ -50,8 +52,14 @@ static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
 		cpu_relax();
 	}
 
-	*(u32 *)buf = __raw_readl(rng_base + RNG_DATA);
-	return sizeof(u32);
+	num_words = readl(rng_base + RNG_STATUS) >> 24;
+	if (num_words > max_words)
+		num_words = max_words;
+
+	for (count = 0; count < num_words; count++)
+		((u32 *)buf)[count] = readl(rng_base + RNG_DATA);
+
+	return num_words * sizeof(u32);
 }
 
 static struct hwrng bcm2835_rng_ops = {
-- 
2.1.0



From maitysanchayan at gmail.com  Fri May 27 03:08:17 2016
From: maitysanchayan at gmail.com (maitysanchayan at gmail.com)
Date: Fri, 27 May 2016 15:38:17 +0530
Subject: [PATCH v3 4/4] soc: Add SoC driver for Freescale Vybrid platform
In-Reply-To: <9495361.v6aft1QR0M@wuerfel>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
 <CAL_JsqKCwy=aXveTfnaQuZ5b3Ld9nzABgPfdPm1JX3CBuvzG+Q@mail.gmail.com>
 <20160527063301.GB1554@Sanchayan-Arch.localdomain>
 <9495361.v6aft1QR0M@wuerfel>
Message-ID: <20160527100817.GA8294@Sanchayan-Arch.localdomain>

On 16-05-27 10:31:55, Arnd Bergmann wrote:
> On Friday, May 27, 2016 12:03:01 PM CEST maitysanchayan at gmail.com wrote:
> > 
> > So if I understand correctly, the binding at the SoC level is fine.
> > Keeping that but removing the additional made-up properties, viz. below
> > 
> > rom-revision: phandle to the on-chip ROM node
> > mscm: phandle to the MSCM CPU configuration node
> > nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
> > nvmem-cell-names: should contain string names "cfg0" and "cfg1"
> > 
> > would be fine?
> > 
> > We would have something similar to here
> > http://www.spinics.net/lists/devicetree/msg80655.html
> > 
> > but now with the DT binding under SoC bus.
> > 
> 
> 
> You look up the OTP device as a syscon here, which seems odd since there
> is already an nvmem driver for it. Shouldn't you use the nvmem API for
> that?
> 
> 	Arnd

I need the following 

nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
nvmem-cell-names: should contain string names "cfg0" and "cfg1"

to be able to use the NVMEM consumer API.

If I can put them at SoC node level then I certainly can use the NVMEM API.

Regards,
Sanchayan.



From riku.voipio at linaro.org  Fri May 27 03:42:27 2016
From: riku.voipio at linaro.org (Riku Voipio)
Date: Fri, 27 May 2016 13:42:27 +0300
Subject: [PATCH] arm64: defconfig: add options for virtualization and
 containers
Message-ID: <1464345747-11729-1-git-send-email-riku.voipio@linaro.org>

Enable options commonly needed by popular virtualization
and container applications. Use modules when possible to
avoid too much overhead for users not interested.

- add namespace and cgroup options needed
- add seccomp - optional, but enhances Qemu etc
- bridge, nat, veth, macvtap and multicast for routing
  guests and containers
- btfrs and overlayfs modules for container COW backends
- while near it, make fuse a module instead of built-in.

Generated with make saveconfig and dropping unrelated spurious
change hunks while commiting. bloat-o-meter old-vmlinux vmlinux:

add/remove: 899/388 grow/shrink: 744/216 up/down: 183556/-94881 (88675)
...
Total: Before=10515333, After=10604008, chg 0.000000%

Signed-off-by: Riku Voipio <riku.voipio at linaro.org>
---
 arch/arm64/configs/defconfig | 53 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index fd2d74d..7db8010 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -15,10 +15,14 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_HUGETLB=y
-# CONFIG_UTS_NS is not set
-# CONFIG_IPC_NS is not set
-# CONFIG_NET_NS is not set
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_USER_NS=y
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
@@ -69,6 +73,7 @@ CONFIG_PREEMPT=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_CMA=y
+CONFIG_SECCOMP=y
 CONFIG_XEN=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
@@ -81,10 +86,37 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
+CONFIG_IPV6=m
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_NAT=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
 CONFIG_BPF_JIT=y
 CONFIG_CFG80211=m
 CONFIG_MAC80211=m
@@ -100,6 +132,7 @@ CONFIG_MTD=y
 CONFIG_MTD_M25P80=y
 CONFIG_MTD_SPI_NOR=y
 CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=m
 CONFIG_VIRTIO_BLK=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
@@ -116,7 +149,10 @@ CONFIG_SATA_SIL24=y
 CONFIG_PATA_PLATFORM=y
 CONFIG_PATA_OF_PLATFORM=y
 CONFIG_NETDEVICES=y
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
 CONFIG_TUN=y
+CONFIG_VETH=m
 CONFIG_VIRTIO_NET=y
 CONFIG_AMD_XGBE=y
 CONFIG_NET_XGENE=y
@@ -144,6 +180,7 @@ CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_AMBAKMI=y
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
 CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
@@ -304,12 +341,16 @@ CONFIG_ARM_SCPI_PROTOCOL=y
 CONFIG_ACPI=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
 CONFIG_FANOTIFY=y
 CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
 CONFIG_QUOTA=y
 CONFIG_AUTOFS4_FS=y
-CONFIG_FUSE_FS=y
-CONFIG_CUSE=y
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+CONFIG_OVERLAY_FS=m
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
-- 
2.1.4



From zyw at rock-chips.com  Fri May 27 03:45:36 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 18:45:36 +0800
Subject: [RESEND PATCH 0/6] Rockchip Type-C and DispplayPort driver
Message-ID: <1464345942-4795-1-git-send-email-zyw@rock-chips.com>

Sorry, forgot a head file in patch 1, so resend.

Hi all

This series patch is for rockchip Type-C phy and DisplayPort controller
driver.

The USB Type-C PHY is designed to support the USB3 and DP applications.
The PHY basically has two main components: USB3 and DisplyPort. USB3
operates in SuperSpeed mode and the DP can operate at RBR, HBR and HBR2
data rates. The Type-C cable orientation detection and Power Delivery
(PD) is accomplished using a PD PHY or a exernal PD chip.

The DP controller is compliant with DisplayPort Specification,
Version 1.3, This IP is compatible with the rockchip type-c PHY IP.
There is a uCPU in DP controller, it need a firmware to work, please
put the firmware file to /lib/firmware/cdn/dptx.bin. The uCPU in charge
of aux communication and link training, the host use mailbox to
communicate with the ucpu.

The PHY driver has register a notification, to get the alt mode from PD,
the PD driver need call the tcphy_notifier_call_chain to notify PHY and
DP controller.

This series is based on Mark Yao's branch:
https://github.com/markyzq/kernel-drm-rockchip/tree/drm-rockchip-next-2016-05-23

I test this patches on the rk3399-evb board, with a fusb302 driver,
this branch has no rk3399.dtsi, so the patch about dts is not included
in this series.



Chris Zhong (6):
  phy: Add USB Type-C PHY driver for rk3399
  Documentation: bindings: add dt doc for Rockchip USB Type-C PHY
  drm/rockchip: vop: add cdn DP support for rk3399
  Documentation: bindings: add dt documentation for cdn DP controller
  ASoC: cdn-dp: Add cdn DP codec driver
  ASoC: rockchip: Add machine driver for cdn dp codec

 .../bindings/display/rockchip/cdn-dp-rockchip.txt  |  57 ++
 .../devicetree/bindings/phy/phy-rockchip-typec.txt |  55 ++
 .../bindings/sound/rockchip-cdn-dp-audio.txt       |  12 +
 drivers/gpu/drm/rockchip/Kconfig                   |   9 +
 drivers/gpu/drm/rockchip/Makefile                  |   1 +
 drivers/gpu/drm/rockchip/cdn-dp-core.c             | 620 ++++++++++++++++
 drivers/gpu/drm/rockchip/cdn-dp-core.h             |  95 +++
 drivers/gpu/drm/rockchip/cdn-dp-reg.c              | 730 ++++++++++++++++++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h              | 404 ++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c        |   9 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h        |   2 +
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c        |   2 +
 drivers/phy/Kconfig                                |   7 +
 drivers/phy/Makefile                               |   1 +
 drivers/phy/phy-rockchip-typec.c                   | 823 +++++++++++++++++++++
 include/linux/phy/phy-rockchip-typec.h             |  72 ++
 include/sound/cdn-dp-audio.h                       |  51 ++
 sound/soc/codecs/Kconfig                           |   3 +
 sound/soc/codecs/Makefile                          |   2 +
 sound/soc/codecs/cdn-dp-audio.c                    | 246 ++++++
 sound/soc/rockchip/Kconfig                         |   9 +
 sound/soc/rockchip/Makefile                        |   2 +
 sound/soc/rockchip/rockchip-cdn-dp-audio.c         | 167 +++++
 23 files changed, 3378 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt
 create mode 100644 Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip-cdn-dp-audio.txt
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-core.c
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-core.h
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-reg.c
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-reg.h
 create mode 100644 drivers/phy/phy-rockchip-typec.c
 create mode 100644 include/linux/phy/phy-rockchip-typec.h
 create mode 100644 include/sound/cdn-dp-audio.h
 create mode 100644 sound/soc/codecs/cdn-dp-audio.c
 create mode 100644 sound/soc/rockchip/rockchip-cdn-dp-audio.c

-- 
2.6.3



From zyw at rock-chips.com  Fri May 27 03:45:37 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 18:45:37 +0800
Subject: [RESEND PATCH 1/6] phy: Add USB Type-C PHY driver for rk3399
In-Reply-To: <1464345942-4795-1-git-send-email-zyw@rock-chips.com>
References: <1464345942-4795-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1464345942-4795-2-git-send-email-zyw@rock-chips.com>

Add a PHY provider driver for the rk3399 SoC Type-c PHY. The USB
Type-C PHY is designed to support the USB3 and DP applications. The
PHY basically has two main components: USB3 and DisplyPort. USB3
operates in SuperSpeed mode and the DP can operate at RBR, HBR and
HBR2 data rates.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
---

 drivers/phy/Kconfig                    |   7 +
 drivers/phy/Makefile                   |   1 +
 drivers/phy/phy-rockchip-typec.c       | 823 +++++++++++++++++++++++++++++++++
 include/linux/phy/phy-rockchip-typec.h |  72 +++
 4 files changed, 903 insertions(+)
 create mode 100644 drivers/phy/phy-rockchip-typec.c
 create mode 100644 include/linux/phy/phy-rockchip-typec.h

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 26566db..dc388a3d 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -351,6 +351,13 @@ config PHY_ROCKCHIP_DP
 	help
 	  Enable this to support the Rockchip Display Port PHY.
 
+config PHY_ROCKCHIP_TYPEC
+	tristate "Rockchip TYPEC PHY Driver"
+	depends on ARCH_ROCKCHIP && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the Rockchip USB TYPEC PHY.
+
 config PHY_ST_SPEAR1310_MIPHY
 	tristate "ST SPEAR1310-MIPHY driver"
 	select GENERIC_PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 24596a9..91fa413 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_PHY_QCOM_APQ8064_SATA)	+= phy-qcom-apq8064-sata.o
 obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
 obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o
 obj-$(CONFIG_PHY_ROCKCHIP_DP)		+= phy-rockchip-dp.o
+obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
 obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)	+= phy-qcom-ipq806x-sata.o
 obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY)	+= phy-spear1310-miphy.o
 obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY)	+= phy-spear1340-miphy.o
diff --git a/drivers/phy/phy-rockchip-typec.c b/drivers/phy/phy-rockchip-typec.c
new file mode 100644
index 0000000..6609cfb
--- /dev/null
+++ b/drivers/phy/phy-rockchip-typec.c
@@ -0,0 +1,823 @@
+/*
+ * Rockchip usb3 PHY driver
+ *
+ * Copyright (C) 2016 Kever Yang <kever.yang at rock-chips.com>
+ *                    Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/delay.h>
+#include <linux/phy/phy-rockchip-typec.h>
+
+#define ADDR_ADJ			2
+#define CMN_SSM_BANDGAP			(0x21 << ADDR_ADJ)
+#define CMN_SSM_BIAS			(0x22 << ADDR_ADJ)
+#define CMN_PLLSM0_PLLEN		(0x29 << ADDR_ADJ)
+#define CMN_PLLSM0_PLLPRE		(0x2a << ADDR_ADJ)
+#define CMN_PLLSM0_PLLVREF		(0x2b << ADDR_ADJ)
+#define CMN_PLLSM0_PLLLOCK		(0x2c << ADDR_ADJ)
+#define CMN_PLLSM1_PLLEN		(0x31 << ADDR_ADJ)
+#define CMN_PLLSM1_PLLPRE		(0x32 << ADDR_ADJ)
+#define CMN_PLLSM1_PLLVREF		(0x33 << ADDR_ADJ)
+#define CMN_PLLSM1_PLLLOCK		(0x34 << ADDR_ADJ)
+#define CMN_PLLSM1_USER_DEF_CTRL	(0x37 << ADDR_ADJ)
+#define CMN_ICAL_OVRD			(0xc1 << ADDR_ADJ)
+#define CMN_PLL0_VCOCAL_OVRD		(0x83 << ADDR_ADJ)
+#define CMN_PLL0_VCOCAL_INIT		(0x84 << ADDR_ADJ)
+#define CMN_PLL0_VCOCAL_ITER		(0x85 << ADDR_ADJ)
+#define CMN_PLL0_LOCK_REFCNT_START	(0x90 << ADDR_ADJ)
+#define CMN_PLL0_LOCK_PLLCNT_START	(0x92 << ADDR_ADJ)
+#define CMN_PLL0_LOCK_PLLCNT_THR	(0x93 << ADDR_ADJ)
+#define CMN_PLL0_INTDIV			(0x94 << ADDR_ADJ)
+#define CMN_PLL0_FRACDIV		(0x95 << ADDR_ADJ)
+#define CMN_PLL0_HIGH_THR		(0x96 << ADDR_ADJ)
+#define CMN_PLL0_DSM_DIAG		(0x97 << ADDR_ADJ)
+#define CMN_PLL0_SS_CTRL1		(0x98 << ADDR_ADJ)
+#define CMN_PLL0_SS_CTRL2		(0x99 << ADDR_ADJ)
+#define CMN_PLL1_VCOCAL_START		(0xa1 << ADDR_ADJ)
+#define CMN_PLL1_VCOCAL_OVRD		(0xa3 << ADDR_ADJ)
+#define CMN_PLL1_VCOCAL_INIT		(0xa4 << ADDR_ADJ)
+#define CMN_PLL1_VCOCAL_ITER		(0xa5 << ADDR_ADJ)
+#define CMN_PLL1_LOCK_REFCNT_START	(0xb0 << ADDR_ADJ)
+#define CMN_PLL1_LOCK_PLLCNT_START	(0xb2 << ADDR_ADJ)
+#define CMN_PLL1_LOCK_PLLCNT_THR	(0xb3 << ADDR_ADJ)
+#define CMN_PLL1_INTDIV			(0xb4 << ADDR_ADJ)
+#define CMN_PLL1_FRACDIV		(0xb5 << ADDR_ADJ)
+#define CMN_PLL1_HIGH_THR		(0xb6 << ADDR_ADJ)
+#define CMN_PLL1_DSM_DIAG		(0xb7 << ADDR_ADJ)
+#define CMN_PLL1_SS_CTRL1		(0xb8 << ADDR_ADJ)
+#define CMN_PLL1_SS_CTRL2		(0xb9 << ADDR_ADJ)
+#define CMN_RXCAL_OVRD			(0xd1 << ADDR_ADJ)
+#define CMN_TXPUCAL_CTRL		(0xe0 << ADDR_ADJ)
+#define CMN_TXPUCAL_OVRD		(0xe1 << ADDR_ADJ)
+#define CMN_TXPDCAL_OVRD		(0xf1 << ADDR_ADJ)
+#define CMN_DIAG_PLL0_FBH_OVRD		(0x1c0 << ADDR_ADJ)
+#define CMN_DIAG_PLL0_FBL_OVRD		(0x1c1 << ADDR_ADJ)
+#define CMN_DIAG_PLL0_OVRD		(0x1c2 << ADDR_ADJ)
+#define CMN_DIAG_PLL0_V2I_TUNE		(0x1c5 << ADDR_ADJ)
+#define CMN_DIAG_PLL0_CP_TUNE		(0x1c6 << ADDR_ADJ)
+#define CMN_DIAG_PLL0_LF_PROG		(0x1c7 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_FBH_OVRD		(0x1d0 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_FBL_OVRD		(0x1d1 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_OVRD		(0x1d2 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_V2I_TUNE		(0x1d5 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_CP_TUNE		(0x1d6 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_LF_PROG		(0x1d7 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_PTATIS_TUNE1	(0x1d8 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_PTATIS_TUNE2	(0x1d9 << ADDR_ADJ)
+#define CMN_DIAG_PLL1_INCLK_CTRL	(0x1da << ADDR_ADJ)
+#define CMN_DIAG_HSCLK_SEL		(0x1e0 << ADDR_ADJ)
+
+#define XCVR_PSM_RCTRL(n)		((0x4001 | (n << 9)) << ADDR_ADJ)
+#define XCVR_PSM_CAL_TMR(n)		((0x4002 | (n << 9)) << ADDR_ADJ)
+#define XCVR_PSM_A0IN_TMR(n)		((0x4003 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_CAL_SCLR_MULT(n)	((0x4047 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_CPOST_MULT_00(n)	((0x404c | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_CPOST_MULT_01(n)	((0x404d | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_CPOST_MULT_10(n)	((0x404e | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_CPOST_MULT_11(n)	((0x404f | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_000(n)	((0x4050 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_001(n)	((0x4051 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_010(n)	((0x4052 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_011(n)	((0x4053 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_100(n)	((0x4054 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_101(n)	((0x4055 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_110(n)	((0x4056 | (n << 9)) << ADDR_ADJ)
+#define TX_TXCC_MGNFS_MULT_111(n)	((0x4057 | (n << 9)) << ADDR_ADJ)
+#define XCVR_DIAG_PLLDRC_CTRL(n)	((0x40e0 | (n << 9)) << ADDR_ADJ)
+#define XCVR_DIAG_BIDI_CTRL(n)		((0x40e8 | (n << 9)) << ADDR_ADJ)
+#define XCVR_DIAG_LANE_FCM_EN_MGN(n)	((0x40f2 | (n << 9)) << ADDR_ADJ)
+#define TX_PSC_A0(n)			((0x4100 | (n << 9)) << ADDR_ADJ)
+#define TX_PSC_A1(n)			((0x4101 | (n << 9)) << ADDR_ADJ)
+#define TX_PSC_A2(n)			((0x4102 | (n << 9)) << ADDR_ADJ)
+#define TX_PSC_A3(n)			((0x4103 | (n << 9)) << ADDR_ADJ)
+#define TX_RCVDET_CTRL(n)		((0x4120 | (n << 9)) << ADDR_ADJ)
+#define TX_RCVDET_EN_TMR(n)		((0x4122 | (n << 9)) << ADDR_ADJ)
+#define TX_RCVDET_ST_TMR(n)		((0x4123 | (n << 9)) << ADDR_ADJ)
+#define TX_DIAG_TX_DRV(n)		((0x41e1 | (n << 9)) << ADDR_ADJ)
+#define TX_DIAG_BGREF_PREDRV_DELAY	(0x41e7 << ADDR_ADJ)
+#define TX_ANA_CTRL_REG_1		(0x5020 << ADDR_ADJ)
+#define TX_ANA_CTRL_REG_2		(0x5021 << ADDR_ADJ)
+#define TXDA_COEFF_CALC_CTRL		(0x5022 << ADDR_ADJ)
+#define TX_DIG_CTRL_REG_2		(0x5024 << ADDR_ADJ)
+#define TXDA_CYA_AUXDA_CYA		(0x5025 << ADDR_ADJ)
+#define TX_ANA_CTRL_REG_3		(0x5026 << ADDR_ADJ)
+#define TX_ANA_CTRL_REG_4		(0x5027 << ADDR_ADJ)
+#define TX_ANA_CTRL_REG_5		(0x5029 << ADDR_ADJ)
+
+#define RX_PSC_A0(n)			((0x8000 | (n << 9)) << ADDR_ADJ)
+#define RX_PSC_A1(n)			((0x8001 | (n << 9)) << ADDR_ADJ)
+#define RX_PSC_A2(n)			((0x8002 | (n << 9)) << ADDR_ADJ)
+#define RX_PSC_A3(n)			((0x8003 | (n << 9)) << ADDR_ADJ)
+#define RX_PSC_CAL(n)			((0x8006 | (n << 9)) << ADDR_ADJ)
+#define RX_PSC_RDY(n)			((0x8007 | (n << 9)) << ADDR_ADJ)
+#define RX_IQPI_ILL_CAL_OVRD		(0x8023 << ADDR_ADJ)
+#define RX_EPI_ILL_CAL_OVRD		(0x8033 << ADDR_ADJ)
+#define RX_SDCAL0_OVRD			(0x8041 << ADDR_ADJ)
+#define RX_SDCAL1_OVRD			(0x8049 << ADDR_ADJ)
+#define RX_SLC_INIT			(0x806d << ADDR_ADJ)
+#define RX_SLC_RUN			(0x806e << ADDR_ADJ)
+#define RX_CDRLF_CNFG2			(0x8081 << ADDR_ADJ)
+#define RX_SIGDET_HL_FILT_TMR(n)	((0x8090 | (n << 9)) << ADDR_ADJ)
+#define RX_SLC_IOP0_OVRD		(0x8101 << ADDR_ADJ)
+#define RX_SLC_IOP1_OVRD		(0x8105 << ADDR_ADJ)
+#define RX_SLC_QOP0_OVRD		(0x8109 << ADDR_ADJ)
+#define RX_SLC_QOP1_OVRD		(0x810d << ADDR_ADJ)
+#define RX_SLC_EOP0_OVRD		(0x8111 << ADDR_ADJ)
+#define RX_SLC_EOP1_OVRD		(0x8115 << ADDR_ADJ)
+#define RX_SLC_ION0_OVRD		(0x8119 << ADDR_ADJ)
+#define RX_SLC_ION1_OVRD		(0x811d << ADDR_ADJ)
+#define RX_SLC_QON0_OVRD		(0x8121 << ADDR_ADJ)
+#define RX_SLC_QON1_OVRD		(0x8125 << ADDR_ADJ)
+#define RX_SLC_EON0_OVRD		(0x8129 << ADDR_ADJ)
+#define RX_SLC_EON1_OVRD		(0x812d << ADDR_ADJ)
+#define RX_SLC_IEP0_OVRD		(0x8131 << ADDR_ADJ)
+#define RX_SLC_IEP1_OVRD		(0x8135 << ADDR_ADJ)
+#define RX_SLC_QEP0_OVRD		(0x8139 << ADDR_ADJ)
+#define RX_SLC_QEP1_OVRD		(0x813d << ADDR_ADJ)
+#define RX_SLC_EEP0_OVRD		(0x8141 << ADDR_ADJ)
+#define RX_SLC_EEP1_OVRD		(0x8145 << ADDR_ADJ)
+#define RX_SLC_IEN0_OVRD		(0x8149 << ADDR_ADJ)
+#define RX_SLC_IEN1_OVRD		(0x814d << ADDR_ADJ)
+#define RX_SLC_QEN0_OVRD		(0x8151 << ADDR_ADJ)
+#define RX_SLC_QEN1_OVRD		(0x8155 << ADDR_ADJ)
+#define RX_SLC_EEN0_OVRD		(0x8159 << ADDR_ADJ)
+#define RX_SLC_EEN1_OVRD		(0x815d << ADDR_ADJ)
+#define RX_DIAG_SIGDET_TUNE(n)		((0x81dc | (n << 9)) << ADDR_ADJ)
+#define RX_DIAG_SC2C_DELAY		(0x81e1 << ADDR_ADJ)
+
+#define PMA_LANE_CFG			(0xc000 << ADDR_ADJ)
+#define PIPE_CMN_CTRL1			(0xc001 << ADDR_ADJ)
+#define PIPE_CMN_CTRL2			(0xc002 << ADDR_ADJ)
+#define PIPE_COM_LOCK_CFG1		(0xc003 << ADDR_ADJ)
+#define PIPE_COM_LOCK_CFG2		(0xc004 << ADDR_ADJ)
+#define PIPE_RCV_DET_INH		(0xc005 << ADDR_ADJ)
+#define DP_MODE_CTL			(0xc008 << ADDR_ADJ)
+#define DP_CLK_CTL			(0xc009 << ADDR_ADJ)
+#define STS				(0xc00F << ADDR_ADJ)
+#define PHY_ISO_CMN_CTRL		(0xc010 << ADDR_ADJ)
+#define PHY_DP_TX_CTL			(0xc408 << ADDR_ADJ)
+#define PMA_CMN_CTRL1			(0xc800 << ADDR_ADJ)
+#define PHY_PMA_ISO_CMN_CTRL		(0xc810 << ADDR_ADJ)
+#define PHY_ISOLATION_CTRL		(0xc81f << ADDR_ADJ)
+#define PHY_PMA_ISO_XCVR_CTRL(n)	((0xcc11 | (n << 6)) << ADDR_ADJ)
+#define PHY_PMA_ISO_LINK_MODE(n)	((0xcc12 | (n << 6)) << ADDR_ADJ)
+#define PHY_PMA_ISO_PWRST_CTRL(n)	((0xcc13 | (n << 6)) << ADDR_ADJ)
+#define PHY_PMA_ISO_TX_DATA_LO(n)	((0xcc14 | (n << 6)) << ADDR_ADJ)
+#define PHY_PMA_ISO_TX_DATA_HI(n)	((0xcc15 | (n << 6)) << ADDR_ADJ)
+#define PHY_PMA_ISO_RX_DATA_LO(n)	((0xcc16 | (n << 6)) << ADDR_ADJ)
+#define PHY_PMA_ISO_RX_DATA_HI(n)	((0xcc17 | (n << 6)) << ADDR_ADJ)
+#define TX_BIST_CTRL(n)			((0x4140 | (n << 9)) << ADDR_ADJ)
+#define TX_BIST_UDDWR(n)		((0x4141 | (n << 9)) << ADDR_ADJ)
+
+#define GRF_SOC_CON26			0x6268
+#define UPHY_DP_SEL			BIT(3)
+#define UPHY_DP_SEL_MASK		BIT(19)
+#define DPTX_HDP_SEL			(3 << 12)
+#define DPTX_HDP_SEL_MASK		(3 << 28)
+
+#define PHY_MODE_SET_TIMEOUT		1000000
+
+#define	MODE_DISCONNECT			1
+#define	MODE_UFP			2
+#define	MODE_DFP_USBONLY		3
+#define	MODE_DFP_DPONLY			4
+#define	MODE_DFP_USB3DP			5
+#define	MODE_DFP_USB2DP			6
+
+#define PARSE_GRF_REG(TYPE) { \
+	if (of_find_property(np, "rockchip,usb3phy_"#TYPE, &len)) { \
+		len /= sizeof(u32);\
+		ret = of_property_read_u32_array(np, "rockchip,usb3phy_" #TYPE,\
+						 array, len); \
+		exregs->usb3phy_##TYPE = array[0]; \
+		exregs->usb3phy_##TYPE##_shift = array[1]; \
+		exregs->usb3phy_##TYPE##_mask = array[2]; \
+		pr_info("%s property found %s, %x, %d, %d\n", __func__, \
+			"rockchip,usb3phy_"#TYPE, \
+			array[0], array[1], array[2]); \
+	} else { \
+		pr_info("%s property not found %s\n", __func__, \
+			"rockchip,usb3phy_" #TYPE); \
+	} \
+}
+
+struct rockchip_typec_phy *rockchip_tcphy;
+
+static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy,
+			  unsigned int num_lanes)
+{
+	unsigned int i;
+
+	writel(0x830, tcphy->base + PMA_CMN_CTRL1);
+	for (i = 0; i < num_lanes; i++) {
+		writel(0x90, tcphy->base + XCVR_DIAG_LANE_FCM_EN_MGN(i));
+		writel(0x960, tcphy->base + TX_RCVDET_EN_TMR(i));
+		writel(0x30, tcphy->base + TX_RCVDET_ST_TMR(i));
+	}
+}
+
+static void tcphy_cfg_usb_pll(struct rockchip_typec_phy *tcphy)
+{
+	unsigned int rdata;
+
+	rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
+	writel(rdata & 0xfffc, tcphy->base + CMN_DIAG_HSCLK_SEL);
+	writel(0xf0, tcphy->base + CMN_PLL0_VCOCAL_INIT);
+	writel(0x18, tcphy->base + CMN_PLL0_VCOCAL_ITER);
+	writel(0xd0, tcphy->base + CMN_PLL0_INTDIV);
+	writel(0x4a4a, tcphy->base + CMN_PLL0_FRACDIV);
+	writel(0x34, tcphy->base + CMN_PLL0_HIGH_THR);
+	writel(0x1ee, tcphy->base + CMN_PLL0_SS_CTRL1);
+	writel(0x7f03, tcphy->base + CMN_PLL0_SS_CTRL2);
+	writel(0x20, tcphy->base + CMN_PLL0_DSM_DIAG);
+	writel(0, tcphy->base + CMN_DIAG_PLL0_OVRD);
+	writel(0, tcphy->base + CMN_DIAG_PLL0_FBH_OVRD);
+	writel(0, tcphy->base + CMN_DIAG_PLL0_FBL_OVRD);
+	writel(0x7, tcphy->base + CMN_DIAG_PLL0_V2I_TUNE);
+	writel(0x45, tcphy->base + CMN_DIAG_PLL0_CP_TUNE);
+	writel(0x8, tcphy->base + CMN_DIAG_PLL0_LF_PROG);
+}
+
+static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy)
+{
+	unsigned int rdata;
+
+	writel(0x2405, tcphy->base + DP_CLK_CTL);
+
+	rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
+	rdata = (rdata & 0xffcf) | 0x30;
+	writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL);
+	writel(0xf0, tcphy->base + CMN_PLL1_VCOCAL_INIT);
+	writel(0x18, tcphy->base + CMN_PLL1_VCOCAL_ITER);
+	writel(0x30b9, tcphy->base + CMN_PLL1_VCOCAL_START);
+	writel(0x21c, tcphy->base + CMN_PLL1_INTDIV);
+	writel(0, tcphy->base + CMN_PLL1_FRACDIV);
+	writel(0x5, tcphy->base + CMN_PLL1_HIGH_THR);
+	writel(0x35, tcphy->base + CMN_PLL1_SS_CTRL1);
+	writel(0x7f1e, tcphy->base + CMN_PLL1_SS_CTRL2);
+	writel(0x20, tcphy->base + CMN_PLL1_DSM_DIAG);
+	writel(0, tcphy->base + CMN_PLLSM1_USER_DEF_CTRL);
+	writel(0, tcphy->base + CMN_DIAG_PLL1_OVRD);
+	writel(0, tcphy->base + CMN_DIAG_PLL1_FBH_OVRD);
+	writel(0, tcphy->base + CMN_DIAG_PLL1_FBL_OVRD);
+	writel(0x6, tcphy->base + CMN_DIAG_PLL1_V2I_TUNE);
+	writel(0x45, tcphy->base + CMN_DIAG_PLL1_CP_TUNE);
+	writel(0x8, tcphy->base + CMN_DIAG_PLL1_LF_PROG);
+	writel(0x100, tcphy->base + CMN_DIAG_PLL1_PTATIS_TUNE1);
+	writel(0x7, tcphy->base + CMN_DIAG_PLL1_PTATIS_TUNE2);
+	writel(0x4, tcphy->base + CMN_DIAG_PLL1_INCLK_CTRL);
+}
+
+static void tcphy_tx_usb_cfg_lane(struct rockchip_typec_phy *tcphy,
+				  unsigned int lane)
+{
+	writel(0x7799, tcphy->base + TX_PSC_A0(lane));
+	writel(0x7798, tcphy->base + TX_PSC_A1(lane));
+	writel(0x5098, tcphy->base + TX_PSC_A2(lane));
+	writel(0x5098, tcphy->base + TX_PSC_A3(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
+	writel(0xbf, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
+}
+
+static void tcphy_rx_usb_cfg_lane(struct rockchip_typec_phy *tcphy,
+				  unsigned int lane)
+{
+	writel(0xa6fd, tcphy->base + RX_PSC_A0(lane));
+	writel(0xa6fd, tcphy->base + RX_PSC_A1(lane));
+	writel(0xa410, tcphy->base + RX_PSC_A2(lane));
+	writel(0x2410, tcphy->base + RX_PSC_A3(lane));
+	writel(0x23ff, tcphy->base + RX_PSC_CAL(lane));
+	writel(0x13, tcphy->base + RX_SIGDET_HL_FILT_TMR(lane));
+	writel(0x1004, tcphy->base + RX_DIAG_SIGDET_TUNE(lane));
+	writel(0x2010, tcphy->base + RX_PSC_RDY(lane));
+	writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
+}
+
+static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy,
+			      unsigned int lane)
+{
+	unsigned int rdata;
+
+	writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
+	writel(0x6799, tcphy->base + TX_PSC_A0(lane));
+	writel(0x6798, tcphy->base + TX_PSC_A1(lane));
+	writel(0x98, tcphy->base + TX_PSC_A2(lane));
+	writel(0x98, tcphy->base + TX_PSC_A3(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane));
+	writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane));
+
+	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane));
+	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane));
+	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
+	writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane));
+
+	writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
+	writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
+
+	rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+	rdata = (rdata & 0x8fff) | 0x6000;
+	writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
+}
+
+static void tcphy_cfg_pin_assign(struct rockchip_typec_phy *tcphy)
+{
+	switch (tcphy->map) {
+	case PIN_MAP_A:
+		writel(0x19d5, tcphy->base + PMA_LANE_CFG);
+		break;
+	case PIN_MAP_B:
+		writel(0x1500, tcphy->base + PMA_LANE_CFG);
+		break;
+	case PIN_MAP_C:
+	case PIN_MAP_E:
+		writel(0x51d9, tcphy->base + PMA_LANE_CFG);
+		break;
+	case PIN_MAP_D:
+	case PIN_MAP_F:
+		writel(0x5100, tcphy->base + PMA_LANE_CFG);
+		break;
+	};
+}
+
+static void tcphy_cfg_lanes(struct rockchip_typec_phy *tcphy,
+			    unsigned int link_cfg)
+{
+	unsigned int i;
+
+	/* PMA lane configuration DP or USB3 */
+	for (i = 0; i < 4; i++) {
+		if ((link_cfg >> i) & 0x1) {
+			tcphy_dp_cfg_lane(tcphy, i);
+		} else {
+			/*
+			 * lan0 TX and lan1 RX for USB3 Normal direction
+			 * lan3 TX and lan2 RX for USB3 Flip direction
+			 */
+			if ((i == 0) | (i == 3))
+				tcphy_tx_usb_cfg_lane(tcphy, i);
+			else
+				tcphy_rx_usb_cfg_lane(tcphy, i);
+		}
+	}
+}
+
+static void tcphy_cfg_flip_set(struct rockchip_typec_phy *tcphy)
+{
+	regmap_write(tcphy->grf_regs,
+		     tcphy->exregs.usb3phy_con0,
+		     tcphy->flip | BIT(16));
+
+	tcphy_cfg_24m(tcphy, 0x4);
+
+	if (tcphy->mode == MODE_UFP ||
+	    tcphy->mode == MODE_DFP_USBONLY ||
+	    tcphy->mode == MODE_DFP_USB3DP)
+		tcphy_cfg_usb_pll(tcphy);
+
+	if (tcphy->mode == MODE_DFP_DPONLY ||
+	    tcphy->mode == MODE_DFP_USB2DP ||
+	    tcphy->mode == MODE_DFP_USB3DP)
+		tcphy_cfg_dp_pll(tcphy);
+
+	if (tcphy->mode == MODE_DFP_DPONLY || tcphy->mode == MODE_DFP_USB2DP)
+		tcphy_cfg_lanes(tcphy, 0xf);
+	else if (tcphy->flip)
+		tcphy_cfg_lanes(tcphy, 0x3);
+	else
+		tcphy_cfg_lanes(tcphy, 0xc);
+}
+
+static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
+{
+	int rdata, rdata2, val;
+
+	rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
+	rdata2 = readl(tcphy->base + CMN_TXPUCAL_CTRL);
+
+	rdata = rdata & 0xdfff;
+	writel(rdata, tcphy->base + TX_ANA_CTRL_REG_1);
+
+	rdata = readl(tcphy->base + TX_DIG_CTRL_REG_2);
+	rdata = rdata & 0xffc0;
+	rdata2 = rdata2 & 0x3f;
+	rdata  = rdata | rdata2;
+	writel(rdata, tcphy->base + TX_DIG_CTRL_REG_2);
+	usleep_range(1000, 2000);
+
+	rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
+	rdata = rdata | 0x2000;
+	writel(rdata, tcphy->base + TX_ANA_CTRL_REG_1);
+
+	usleep_range(150, 200);
+
+	writel(0, tcphy->base + PHY_DP_TX_CTL);
+	writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2);
+	writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2);
+	writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
+	writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1);
+	writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1);
+	writel(0x30C, tcphy->base + TX_ANA_CTRL_REG_2);
+	writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
+	writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4);
+	writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1);
+	writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1);
+	writel(0x30d, tcphy->base + TX_ANA_CTRL_REG_2);
+	writel(0x30f, tcphy->base + TX_ANA_CTRL_REG_2);
+
+	if (tcphy->flip)
+		writel(0xa078, tcphy->base + TX_ANA_CTRL_REG_1);
+	else
+		writel(0xb078, tcphy->base + TX_ANA_CTRL_REG_1);
+
+	writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2);
+	writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
+	writel(0, tcphy->base + TX_ANA_CTRL_REG_4);
+	writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
+	writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL);
+	writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA);
+
+	val = readl(tcphy->base + TX_DIG_CTRL_REG_2);
+	val |= BIT(15);
+	writel(val, tcphy->base + TX_DIG_CTRL_REG_2);
+}
+
+static void tcphy_dp_hpd(struct rockchip_typec_phy *tcphy,
+			 u8 mode)
+{
+	/* force hpd */
+	if (mode)
+		regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
+			     DPTX_HDP_SEL_MASK | DPTX_HDP_SEL);
+	else
+		regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
+			     DPTX_HDP_SEL_MASK);
+}
+
+static int tcphy_usb3_init(struct rockchip_typec_phy *tcphy)
+{
+	int timeout = 0;
+	int ret, val;
+
+	/*wait TCPHY for pipe ready */
+	while (1) {
+		ret = regmap_read(tcphy->grf_regs,
+				  tcphy->exregs.usb3phy_status0, &val);
+		val >>= tcphy->exregs.usb3phy_status0_shift;
+		if ((val & 0x1) == 0)
+			break;
+
+		timeout++;
+		if (timeout > 1000) {
+			pr_warn("%s wait pipe ready timerout!\n", __func__);
+			break;
+		}
+		usleep_range(10, 20);
+	}
+
+	return 0;
+}
+
+static int tcphy_dp_init(struct rockchip_typec_phy *tcphy)
+{
+	int ret, val;
+
+	ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
+				 val, val & BIT(6), 1000, PHY_MODE_SET_TIMEOUT);
+	if (ret < 0) {
+		dev_err(tcphy->dev, "failed to wait TCPHY for DP ready\n");
+		return -EBUSY;
+	}
+
+	tcphy_dp_aux_calibration(tcphy);
+
+	if (tcphy->mode == MODE_DFP_USB3DP)
+		writel(0xc101, tcphy->base + DP_MODE_CTL);
+	else
+		writel(0x0101, tcphy->base + DP_MODE_CTL);
+
+	ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
+				 val, val & BIT(4), 1000, PHY_MODE_SET_TIMEOUT);
+	if (ret < 0) {
+		dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int tcphy_phy_init(struct rockchip_typec_phy *tcphy)
+{
+	int ret;
+	int timeout = 0;
+
+	ret = clk_prepare_enable(tcphy->clk_core);
+	if (ret) {
+		dev_err(tcphy->dev, "Failed to prepare_enable core clock\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(tcphy->clk_ref);
+	if (ret) {
+		dev_err(tcphy->dev, "Failed to prepare_enable ref clock\n");
+		return ret;
+	}
+
+	/* select external psm clock */
+	regmap_write(tcphy->grf_regs, tcphy->exregs.usb3phy_con2,
+		     BIT(14) | BIT(30));
+	regmap_write(tcphy->grf_regs, tcphy->exregs.usb3phy_con0, BIT(19));
+
+	reset_control_assert(tcphy->phy_rst);
+	reset_control_assert(tcphy->pipe_rst);
+	reset_control_assert(tcphy->uphy_rst);
+
+	if (tcphy->num == TYPEC_PHY0)
+		regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
+			     UPHY_DP_SEL_MASK);
+	else
+		regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
+			     UPHY_DP_SEL_MASK | UPHY_DP_SEL);
+
+	reset_control_deassert(tcphy->uphy_rst);
+
+	tcphy_cfg_flip_set(tcphy);
+
+	tcphy_cfg_pin_assign(tcphy);
+
+	if (tcphy->mode == MODE_DFP_USB3DP)
+		writel(0xc104, tcphy->base + DP_MODE_CTL);
+	else if ((tcphy->mode == MODE_DFP_DPONLY) ||
+		 (tcphy->mode == MODE_DFP_USB2DP))
+		writel(0x0104, tcphy->base + DP_MODE_CTL);
+
+	reset_control_deassert(tcphy->phy_rst);
+
+	while (!(readl(tcphy->base + PMA_CMN_CTRL1) & 1)) {
+		timeout++;
+		if (timeout > 1000)
+			break;
+		usleep_range(10, 20);
+	}
+
+	reset_control_deassert(tcphy->pipe_rst);
+
+	return 0;
+}
+
+static int tcphy_phy_deinit(struct rockchip_typec_phy *tcphy)
+{
+	clk_disable_unprepare(tcphy->clk_core);
+	clk_disable_unprepare(tcphy->clk_ref);
+
+	return 0;
+}
+
+int tcphy_register_notifier(struct phy *_phy, struct notifier_block *nb)
+{
+	struct rockchip_typec_phy *tcphy = phy_get_drvdata(_phy);
+
+	return atomic_notifier_chain_register(&tcphy->notifier, nb);
+}
+
+void tcphy_unregister_notifier(struct phy *_phy,
+			       struct notifier_block *nb)
+{
+	struct rockchip_typec_phy *tcphy = phy_get_drvdata(_phy);
+
+	atomic_notifier_chain_unregister(&tcphy->notifier, nb);
+}
+
+void tcphy_notifier_call_chain(struct rockchip_typec_phy *x,
+			       unsigned long val, void *v)
+{
+	atomic_notifier_call_chain(&x->notifier, val, v);
+}
+EXPORT_SYMBOL_GPL(tcphy_notifier_call_chain);
+
+static int tcphy_pd_event(struct notifier_block *nb,
+			  unsigned long event, void *priv)
+{
+	struct rockchip_typec_phy *tcphy;
+	int value = *(int *)priv;
+	u8 is_dp, dfp;
+
+	tcphy = container_of(nb, struct rockchip_typec_phy, event_nb);
+	if (IS_ERR_OR_NULL(tcphy)) {
+		pr_err("initialization issue");
+		return -1;
+	}
+
+	tcphy->flip = GET_FLIP(value);
+	dfp = GET_DFP(value);
+	is_dp = GET_DP(value);
+	tcphy->map = GET_PIN_MAP(value);
+
+	if (event == 0) {
+		if (tcphy->mode == MODE_DISCONNECT)
+			return 0;
+		tcphy->mode = MODE_DISCONNECT;
+	} else if (is_dp) {
+		if (tcphy->map & (PIN_MAP_B | PIN_MAP_D | PIN_MAP_F))
+			tcphy->mode = MODE_DFP_USB3DP;
+		else
+			tcphy->mode = MODE_DFP_DPONLY;
+	} else if (dfp) {
+		tcphy->mode = MODE_DFP_USBONLY;
+	} else {
+		tcphy->mode = MODE_UFP;
+	}
+
+	schedule_delayed_work_on(0, &tcphy->event_wq, 0);
+
+	return 0;
+}
+
+static void tcphy_event_wq(struct work_struct *work)
+{
+	struct rockchip_typec_phy *tcphy;
+
+	tcphy = container_of(work, struct rockchip_typec_phy, event_wq.work);
+	if (IS_ERR_OR_NULL(tcphy)) {
+		pr_err("initialization issue");
+		return;
+	}
+
+	switch (tcphy->mode) {
+	case MODE_DISCONNECT:
+		/* phy enter low power mode */
+		tcphy_phy_deinit(tcphy);
+		tcphy_dp_hpd(tcphy, 0);
+		break;
+	case MODE_UFP:
+		tcphy_phy_init(tcphy);
+		tcphy_usb3_init(tcphy);
+		tcphy_dp_hpd(tcphy, 0);
+		break;
+	case MODE_DFP_USBONLY:
+		tcphy_phy_init(tcphy);
+		tcphy_usb3_init(tcphy);
+		tcphy_dp_hpd(tcphy, 0);
+		break;
+	case MODE_DFP_DPONLY:
+	case MODE_DFP_USB2DP:
+		tcphy_phy_init(tcphy);
+		tcphy_dp_init(tcphy);
+		tcphy_dp_hpd(tcphy, 1);
+		break;
+	case MODE_DFP_USB3DP:
+		tcphy_phy_init(tcphy);
+		tcphy_usb3_init(tcphy);
+		tcphy_dp_init(tcphy);
+		tcphy_dp_hpd(tcphy, 1);
+		break;
+	}
+}
+
+int tcphy_parse_reg(struct rockchip_typec_phy *tcphy, struct device *dev)
+{
+	struct tcphy_grf_reg *exregs = &tcphy->exregs;
+	struct device_node *np = dev->of_node;
+	u32 len = 0, array[3];
+	int ret = 0;
+
+	PARSE_GRF_REG(con0);
+	PARSE_GRF_REG(con1);
+	PARSE_GRF_REG(con2);
+	PARSE_GRF_REG(status0);
+	PARSE_GRF_REG(status1);
+	return ret;
+}
+
+static int rockchip_typec_phy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rockchip_typec_phy *tcphy;
+	struct resource *res;
+	struct phy_provider *phy_provider;
+
+	tcphy = devm_kzalloc(dev, sizeof(*tcphy), GFP_KERNEL);
+	if (!tcphy)
+		return -ENOMEM;
+
+	tcphy->dev = dev;
+	platform_set_drvdata(pdev, tcphy);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	tcphy->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(tcphy->base)) {
+		dev_err(dev, "failed to remap phy regs\n");
+		return PTR_ERR(tcphy->base);
+	}
+	tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node,
+							"rockchip,grf");
+	if (IS_ERR(tcphy->grf_regs)) {
+		dev_err(dev, "%s: could not find grf dt node\n", __func__);
+		return PTR_ERR(tcphy->grf_regs);
+	}
+
+	tcphy->clk_core = of_clk_get_by_name(dev->of_node, "tcpdcore");
+	if (IS_ERR(tcphy->clk_core)) {
+		dev_err(dev, "%s: could not get uphy core clock\n", __func__);
+		tcphy->clk_core = NULL;
+	}
+
+	tcphy->clk_ref = of_clk_get_by_name(dev->of_node, "tcpdphy_ref");
+	if (IS_ERR(tcphy->clk_core)) {
+		dev_err(dev, "%s: could not get uphy ref clock\n", __func__);
+		tcphy->clk_core = NULL;
+	}
+
+	tcphy->phy_rst = devm_reset_control_get(dev, "tcphy_rst");
+	if (IS_ERR(tcphy->phy_rst)) {
+		dev_err(dev, "no phy_rst reset control found\n");
+		return PTR_ERR(tcphy->phy_rst);
+	}
+
+	tcphy->pipe_rst = devm_reset_control_get(dev, "tcphy_pipe_rst");
+	if (IS_ERR(tcphy->pipe_rst)) {
+		dev_err(dev, "no pipe_rst reset control found\n");
+		return PTR_ERR(tcphy->pipe_rst);
+	}
+
+	tcphy->uphy_rst = devm_reset_control_get(dev, "uphy_tcphy_rst");
+	if (IS_ERR(tcphy->uphy_rst)) {
+		dev_err(dev, "no uphy_rst reset control found\n");
+		return PTR_ERR(tcphy->uphy_rst);
+	}
+
+	tcphy_parse_reg(tcphy, dev);
+	tcphy->mode = MODE_DISCONNECT;
+
+	tcphy->phy = devm_phy_create(dev, NULL, NULL);
+
+	phy_set_drvdata(tcphy->phy, tcphy);
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+	/* register notifier for PD event */
+	ATOMIC_INIT_NOTIFIER_HEAD(&tcphy->notifier);
+	tcphy->event_nb.notifier_call = tcphy_pd_event;
+	INIT_DELAYED_WORK(&tcphy->event_wq, tcphy_event_wq);
+	tcphy_register_notifier(tcphy->phy, &tcphy->event_nb);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static int rockchip_typec_phy_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id rockchip_typec_phy_dt_ids[] = {
+	{ .compatible = "rockchip,rk3399-typec-phy", },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, rockchip_typec_phy_dt_ids);
+
+static struct platform_driver rockchip_typec_phy_driver = {
+	.probe		= rockchip_typec_phy_probe,
+	.remove		= rockchip_typec_phy_remove,
+	.driver		= {
+		.name	= "rockchip-typec-phy",
+		.of_match_table = rockchip_typec_phy_dt_ids,
+	},
+};
+
+module_platform_driver(rockchip_typec_phy_driver);
+
+MODULE_AUTHOR("Kever Yang<kever.yang at rock-chips.com>");
+MODULE_AUTHOR("Chris Zhong<zyw at rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip USB TYPE-C PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/phy/phy-rockchip-typec.h b/include/linux/phy/phy-rockchip-typec.h
new file mode 100644
index 0000000..b055297
--- /dev/null
+++ b/include/linux/phy/phy-rockchip-typec.h
@@ -0,0 +1,72 @@
+#ifndef PHY_ROCKCHIP_TYPEC_H_
+#define PHY_ROCKCHIP_TYPEC_H_
+#include <linux/notifier.h>
+
+struct tcphy_grf_reg {
+	u32 usb3phy_con0;
+	u32 usb3phy_con0_shift;
+	u32 usb3phy_con0_mask;
+	u32 usb3phy_con1;
+	u32 usb3phy_con1_shift;
+	u32 usb3phy_con1_mask;
+	u32 usb3phy_con2;
+	u32 usb3phy_con2_shift;
+	u32 usb3phy_con2_mask;
+	u32 usb3phy_status0;
+	u32 usb3phy_status0_shift;
+	u32 usb3phy_status0_mask;
+	u32 usb3phy_status1;
+	u32 usb3phy_status1_shift;
+	u32 usb3phy_status1_mask;
+};
+
+enum phy_num {
+	TYPEC_PHY0,
+	TYPEC_PHY1,
+};
+
+#define	PIN_MAP_A	BIT(0)
+#define	PIN_MAP_B	BIT(1)
+#define	PIN_MAP_C	BIT(2)
+#define	PIN_MAP_D	BIT(3)
+#define	PIN_MAP_E	BIT(4)
+#define	PIN_MAP_F	BIT(5)
+
+#define SET_PIN_MAP(x)	(((x) & 0xff) << 24)
+#define SET_DP(x)	(((x) & 0xff) << 16)
+#define SET_DFP(x)	(((x) & 0xff) << 8)
+#define SET_FLIP(x)	((x) & 0xff)
+#define GET_PIN_MAP(x)	(((x) >> 24) & 0xff)
+#define GET_DP(x)	(((x) >> 16) & 0xff)
+#define GET_DFP(x)	(((x) >> 8) & 0xff)
+#define GET_FLIP(x)	((x) & 0xff)
+
+struct rockchip_typec_phy {
+	struct device *dev;
+	void __iomem *base;
+	struct phy	*phy;
+	struct regmap *grf_regs;
+	struct tcphy_grf_reg exregs;
+	struct clk	*clk_core;
+	struct clk	*clk_ref;
+	struct reset_control *phy_rst;
+	struct reset_control *pipe_rst;
+	struct reset_control *uphy_rst;
+
+	/* to receive notifier from PD */
+	struct atomic_notifier_head     notifier;
+	struct notifier_block	event_nb;
+	struct delayed_work	event_wq;
+
+	bool flip;
+	unsigned int mode;
+	enum phy_num num;
+	int map;
+};
+
+int tcphy_register_notifier(struct phy *_phy, struct notifier_block *nb);
+void tcphy_unregister_notifier(struct phy *_phy, struct notifier_block *nb);
+struct rockchip_typec_phy *get_tcphy(void);
+void tcphy_notifier_call_chain(struct rockchip_typec_phy *x,
+			       unsigned long val, void *v);
+#endif
-- 
2.6.3



From zyw at rock-chips.com  Fri May 27 03:45:38 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 18:45:38 +0800
Subject: [RESEND PATCH 2/6] Documentation: bindings: add dt doc for Rockchip
 USB Type-C PHY
In-Reply-To: <1464345942-4795-1-git-send-email-zyw@rock-chips.com>
References: <1464345942-4795-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1464345942-4795-3-git-send-email-zyw@rock-chips.com>

This patch adds a binding that describes the Rockchip USB Type-C PHY
for rk3399.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
---

 .../devicetree/bindings/phy/phy-rockchip-typec.txt | 55 ++++++++++++++++++++++
 1 file changed, 55 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt

diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
new file mode 100644
index 0000000..402f667
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
@@ -0,0 +1,55 @@
+ROCKCHIP type-c PHY
+
+Required properties:
+ - compatible: should be "rockchip,rk3399-typec-phy"
+ - reg : Address and length of the usb phy control register set
+ - rockchip,grf : phandle to the syscon managing the "general
+   register files"
+ - clocks : phandle + clock specifier for the phy clocks
+ - clock-names: string, clock name, must be "tcpdcore", "tcpdphy_ref";
+ - resets : a list of phandle + reset specifier pairs
+ - reset-names : string reset name, must be:
+		 "tcphy_rst", "tcphy_pipe_rst", "uphy_tcphy_rst"
+ - #phy-cells: Must be 0.  See ./phy-bindings.txt for details.
+ - rockchip,usb3phy*: phy registers embed in grf
+
+Example:
+	tcphy0: phy at ff7c0000 {
+		compatible = "rockchip,rk3399-typec-phy";
+		reg = <0x0 0xff7c0000 0x0 0x40000>;
+		#phy-cells = <0>;
+		rockchip,grf = <&grf>;
+		clocks = <&cru SCLK_UPHY0_TCPDCORE>,
+			 <&cru SCLK_UPHY0_TCPDPHY_REF>;
+		clock-names = "tcpdcore", "tcpdphy_ref";
+		resets = <&cru SRST_UPHY0>,
+			 <&cru SRST_UPHY0_PIPE_L00>,
+			 <&cru SRST_P_UPHY0_TCPHY>;
+		reset-names = "tcphy_rst", "tcphy_pipe_rst", "uphy_tcphy_rst";
+		rockchip,usb3phy_con0 = <0x0e580 0 16>;
+		rockchip,usb3phy_con1 = <0x0e584 0 16>;
+		rockchip,usb3phy_con2 = <0x0e588 0 16>;
+		rockchip,usb3phy_status0 = <0x0e5c0 0 13>;
+		rockchip,usb3phy_status1 = <0x0e5c4 0 12>;
+		status = "disabled";
+	};
+
+	tcphy1: phy at ff800000 {
+		compatible = "rockchip,rk3399-typec-phy";
+		reg = <0x0 0xff800000 0x0 0x40000>;
+		#phy-cells = <0>;
+		rockchip,grf = <&grf>;
+		clocks = <&cru SCLK_UPHY1_TCPDCORE>,
+			 <&cru SCLK_UPHY1_TCPDPHY_REF>;
+		clock-names = "tcpdcore", "tcpdphy_ref";
+		resets = <&cru SRST_UPHY1>,
+		         <&cru SRST_UPHY1_PIPE_L00>,
+			 <&cru SRST_P_UPHY1_TCPHY>;
+		reset-names = "tcphy_rst", "tcphy_pipe_rst", "uphy_tcphy_rst";
+		rockchip,usb3phy_con0 = <0x0e58c 0 16>;
+		rockchip,usb3phy_con1 = <0x0e590 0 16>;
+		rockchip,usb3phy_con2 = <0x0e594 0 16>;
+		rockchip,usb3phy_status0 = <0x0e5c0 16 13>;
+		rockchip,usb3phy_status1 = <0x0e5c4 16 12>;
+		status = "disabled";
+	};
-- 
2.6.3



From zyw at rock-chips.com  Fri May 27 03:45:40 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 18:45:40 +0800
Subject: [RESEND PATCH 4/6] Documentation: bindings: add dt documentation for
 cdn DP controller
In-Reply-To: <1464345942-4795-1-git-send-email-zyw@rock-chips.com>
References: <1464345942-4795-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1464345942-4795-5-git-send-email-zyw@rock-chips.com>

This patch adds a binding that describes the cdn DP controller for
rk3399.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
---

 .../bindings/display/rockchip/cdn-dp-rockchip.txt  | 57 ++++++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt

diff --git a/Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt
new file mode 100644
index 0000000..60795c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt
@@ -0,0 +1,57 @@
+Rockchip RK3399 specific extensions to the cdn Display Port
+================================
+
+Required properties:
+- compatible: "rockchip,cdn-dp"
+
+- reg: physical base address of the controller and length
+
+- clocks: from common clock binding: handle to dp clock.
+
+- clock-names: from common clock binding:
+	       Required elements: "core_clk" "pclk" "spdif"
+
+- rockchip,grf: this soc should set GRF regs, so need get grf here.
+
+- ports: contain a port nodes with endpoint definitions as defined in
+	 Documentation/devicetree/bindings/media/video-interfaces.txt.
+	 contained 2 endpoints, connecting to the output of vop.
+
+- phys: from general PHY binding: the phandle for the PHY device.
+
+-------------------------------------------------------------------------------
+
+Example:
+	cdn_dp: dp at fec00000 {
+		compatible = "rockchip,cdn-dp";
+		reg = <0x0 0xfec00000 0x0 0x100000>;
+		interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_DP_CORE>, <&cru PCLK_DP_CTRL>,
+			 <&cru SCLK_SPDIF_REC_DPTX>;
+		clock-names = "core_clk", "pclk", "spdif";
+		phys = <&tcphy0>;
+		rockchip,grf = <&grf>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			dp_in: port {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				dp_in_vopb: endpoint at 0 {
+					reg = <0>;
+					remote-endpoint = <&vopb_out_dp>;
+				};
+
+				dp_in_vopl: endpoint at 1 {
+					reg = <1>;
+					remote-endpoint = <&vopl_out_dp>;
+				};
+			};
+		};
+	};
-- 
2.6.3



From zyw at rock-chips.com  Fri May 27 03:45:39 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 18:45:39 +0800
Subject: [RESEND PATCH 3/6] drm/rockchip: vop: add cdn DP support for rk3399
In-Reply-To: <1464345942-4795-1-git-send-email-zyw@rock-chips.com>
References: <1464345942-4795-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1464345942-4795-4-git-send-email-zyw@rock-chips.com>

Add support for cdn DP controller which is embedded in the rk3399
SoCs. The DP is compliant with DisplayPort Specification,
Version 1.3, This IP is compatible with the rockchip type-c PHY IP.
There is a uCPU in DP controller, it need a firmware to work,
please put the firmware file to /lib/firmware/cdn/dptx.bin. The
uCPU in charge of aux communication and link training, the host use
mailbox to communicate with the ucpu.
The dclk pin_pol of vop must not be invert for DP.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
---

 drivers/gpu/drm/rockchip/Kconfig            |   9 +
 drivers/gpu/drm/rockchip/Makefile           |   1 +
 drivers/gpu/drm/rockchip/cdn-dp-core.c      | 620 +++++++++++++++++++++++
 drivers/gpu/drm/rockchip/cdn-dp-core.h      |  95 ++++
 drivers/gpu/drm/rockchip/cdn-dp-reg.c       | 730 ++++++++++++++++++++++++++++
 drivers/gpu/drm/rockchip/cdn-dp-reg.h       | 404 +++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |   9 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   2 +
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c |   2 +
 include/sound/cdn-dp-audio.h                |  51 ++
 10 files changed, 1922 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-core.c
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-core.h
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-reg.c
 create mode 100644 drivers/gpu/drm/rockchip/cdn-dp-reg.h
 create mode 100644 include/sound/cdn-dp-audio.h

diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index d30bdc3..20da9a8 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -25,6 +25,15 @@ config ROCKCHIP_ANALOGIX_DP
 	  for the Analogix Core DP driver. If you want to enable DP
 	  on RK3288 based SoC, you should selet this option.
 
+config ROCKCHIP_CDN_DP
+        tristate "Rockchip cdn DP"
+        depends on DRM_ROCKCHIP
+        help
+	  This selects support for Rockchip SoC specific extensions
+	  for the cdn Dp driver. If you want to enable Dp on
+	  RK3399 based SoC, you should selet this
+	  option.
+
 config ROCKCHIP_DW_HDMI
         tristate "Rockchip specific extensions for Synopsys DW HDMI"
         depends on DRM_ROCKCHIP
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index 05d0713..abdecd5 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -7,6 +7,7 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
 obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
+obj-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
 obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
new file mode 100644
index 0000000..fdf99f5
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -0,0 +1,620 @@
+/*
+ * cdn dp controller core driver
+ *
+ * Copyright (C) 2016 Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * 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 <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_of.h>
+
+#include <linux/component.h>
+#include <linux/clk.h>
+#include <linux/firmware.h>
+#include <linux/mfd/syscon.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-rockchip-typec.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#include <sound/cdn-dp-audio.h>
+
+#include "rockchip_drm_vop.h"
+#include "cdn-dp-reg.h"
+#include "cdn-dp-core.h"
+
+#define connector_to_dp(c) \
+		container_of(c, struct cdn_dp_device, connector)
+
+#define encoder_to_dp(c) \
+		container_of(c, struct cdn_dp_device, encoder)
+
+/* dp grf register offset */
+#define DP_VOP_SEL		0x6224
+#define DP_SEL_VOP_LIT		BIT(12)
+
+static int cdn_dp_clk_enable(struct cdn_dp_device *dp)
+{
+	int ret = 0;
+	int clk_rate = 200000000;
+
+	ret = clk_prepare_enable(dp->pclk);
+	if (ret < 0) {
+		dev_err(dp->dev, "cannot enable dp pclk %d\n", ret);
+		goto err_pclk;
+	}
+
+	ret = clk_prepare_enable(dp->core_clk);
+	if (ret < 0) {
+		dev_err(dp->dev, "cannot enable core_clk %d\n", ret);
+		goto err_core_clk;
+	}
+
+	ret = clk_set_rate(dp->core_clk, clk_rate);
+	if (ret < 0) {
+		dev_err(dp->dev, "cannot set dp core clk to %d %d\n",
+			clk_rate, ret);
+		goto err_set_rate;
+	}
+
+	/* notice fw the clk freq value */
+	cdn_dp_set_fw_clk(dp, clk_rate);
+
+	return 0;
+
+err_set_rate:
+	clk_disable_unprepare(dp->core_clk);
+err_core_clk:
+	clk_disable_unprepare(dp->pclk);
+err_pclk:
+	return ret;
+}
+
+static enum drm_connector_status
+cdn_dp_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct cdn_dp_device *dp = connector_to_dp(connector);
+	int ret;
+
+	if (!dp->fw_loaded)
+		return connector_status_unknown;
+
+	ret = cdn_dp_get_hpd_status(dp);
+	if (ret < 0)
+		return connector_status_unknown;
+
+	dp->plugged = ret;
+
+	return ret ? connector_status_connected : connector_status_disconnected;
+}
+
+static void cdn_dp_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static struct drm_connector_funcs cdn_dp_atomic_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.detect = cdn_dp_connector_detect,
+	.destroy = cdn_dp_connector_destroy,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int cdn_dp_connector_get_modes(struct drm_connector *connector)
+{
+	struct cdn_dp_device *dp = connector_to_dp(connector);
+	struct edid *edid;
+	int ret;
+
+	if (!dp->fw_loaded)
+		return 0;
+
+	ret = cdn_dp_set_host_cap(dp);
+	if (ret) {
+		dev_err(dp->dev, "set host capabilities failed:%d\n", ret);
+		return ret;
+	}
+
+	edid = drm_do_get_edid(connector, cdn_dp_get_edid_block, dp);
+	if (edid) {
+		dev_dbg(dp->dev, "got edid: width[%d] x height[%d]\n",
+			edid->width_cm, edid->height_cm);
+
+		dp->sink_has_audio = drm_detect_monitor_audio(edid);
+		drm_mode_connector_update_edid_property(connector, edid);
+		drm_add_edid_modes(connector, edid);
+		/* Store the ELD */
+		drm_edid_to_eld(connector, edid);
+		kfree(edid);
+	} else {
+		dev_dbg(dp->dev, "failed to get edid\n");
+	}
+
+	/*
+	 * put the training process here, since the mode_valid need the
+	 * training result to check if the resolution is support.
+	 */
+	ret = cdn_dp_training_start(dp);
+	if (ret) {
+		dev_err(dp->dev, "hw lt err:%d\n", ret);
+		return ret;
+	}
+
+	ret = cdn_dp_get_lt_status(dp);
+	if (ret) {
+		dev_err(dp->dev, "hw lt get status err:%d\n", ret);
+		return ret;
+	}
+
+	dev_dbg(dp->dev, "rate:%d, lanes:%d\n",
+		dp->link.rate, dp->link.num_lanes);
+	return 0;
+}
+
+static struct drm_encoder *
+	cdn_dp_connector_best_encoder(struct drm_connector *connector)
+{
+	struct cdn_dp_device *dp = connector_to_dp(connector);
+
+	return &dp->encoder;
+}
+
+static int cdn_dp_connector_mode_valid(struct drm_connector *connector,
+				       struct drm_display_mode *mode)
+{
+	struct cdn_dp_device *dp = connector_to_dp(connector);
+	struct drm_display_info *display_info = &dp->connector.display_info;
+	long requested = mode->clock * display_info->bpc * 3 / 1000;
+	long actual, rate;
+
+	rate = drm_dp_bw_code_to_link_rate(dp->link.rate);
+	actual = rate * dp->link.num_lanes / 100;
+
+	/* efficiency is about 0.8 */
+	actual = actual * 8 / 10;
+
+	if (requested > actual) {
+		dev_dbg(dp->dev, "requested=%ld, actual=%ld, clock=%d, bpc= %d\n",
+			requested, actual, mode->clock, display_info->bpc);
+		return MODE_H_ILLEGAL;
+	}
+
+	return MODE_OK;
+}
+
+static struct drm_connector_helper_funcs cdn_dp_connector_helper_funcs = {
+	.get_modes = cdn_dp_connector_get_modes,
+	.best_encoder = cdn_dp_connector_best_encoder,
+	.mode_valid = cdn_dp_connector_mode_valid,
+};
+
+static int cdn_dp_commit(struct drm_encoder *encoder)
+{
+	struct cdn_dp_device *dp = encoder_to_dp(encoder);
+	int ret;
+
+	cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+
+	ret = cdn_dp_config_video(dp);
+	if (ret) {
+		dev_err(dp->dev, "unable to config video\n");
+		return ret;
+	}
+
+	cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID);
+	dp->dpms_mode = DRM_MODE_DPMS_ON;
+
+	return ret;
+}
+
+static void cdn_dp_encoder_mode_set(struct drm_encoder *encoder,
+				    struct drm_display_mode *mode,
+				    struct drm_display_mode *adjusted)
+{
+	struct cdn_dp_device *dp = encoder_to_dp(encoder);
+	struct drm_display_info *display_info = &dp->connector.display_info;
+	struct rockchip_crtc_state *state;
+	struct video_info *video = &dp->video_info;
+	int ret, val;
+
+	switch (display_info->bpc) {
+	case 16:
+	case 12:
+	case 10:
+		video->color_depth = 10;
+		break;
+	case 6:
+		video->color_depth = 6;
+		break;
+	default:
+		video->color_depth = 8;
+		break;
+	}
+
+	video->color_fmt = PXL_RGB;
+
+	video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
+	video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
+
+	ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
+	if (ret < 0)
+		return;
+
+	state = to_rockchip_crtc_state(encoder->crtc->state);
+	if (ret) {
+		val = DP_SEL_VOP_LIT | (DP_SEL_VOP_LIT << 16);
+		state->output_mode = ROCKCHIP_OUT_MODE_P888;
+	} else {
+		val = DP_SEL_VOP_LIT << 16;
+		state->output_mode = ROCKCHIP_OUT_MODE_AAAA;
+	}
+	ret = regmap_write(dp->grf, DP_VOP_SEL, val);
+	if (ret != 0)
+		dev_err(dp->dev, "Could not write to GRF: %d\n", ret);
+
+	memcpy(&dp->mode, adjusted, sizeof(*mode));
+}
+
+static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
+{
+	struct cdn_dp_device *dp = encoder_to_dp(encoder);
+
+	if (dp->dpms_mode == DRM_MODE_DPMS_ON)
+		return;
+
+	cdn_dp_commit(encoder);
+}
+
+static void cdn_dp_encoder_disable(struct drm_encoder *encoder)
+{
+	struct cdn_dp_device *dp = encoder_to_dp(encoder);
+
+	if (dp->dpms_mode != DRM_MODE_DPMS_ON)
+		return;
+
+	cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE);
+
+	dp->dpms_mode = DRM_MODE_DPMS_OFF;
+}
+
+static int
+cdn_dp_encoder_atomic_check(struct drm_encoder *encoder,
+			    struct drm_crtc_state *crtc_state,
+			    struct drm_connector_state *conn_state)
+{
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+
+	s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
+	s->output_type = DRM_MODE_CONNECTOR_DisplayPort;
+
+	return 0;
+}
+
+static struct drm_encoder_helper_funcs cdn_dp_encoder_helper_funcs = {
+	.mode_set = cdn_dp_encoder_mode_set,
+	.enable = cdn_dp_encoder_enable,
+	.disable = cdn_dp_encoder_disable,
+	.atomic_check = cdn_dp_encoder_atomic_check,
+};
+
+static struct drm_encoder_funcs cdn_dp_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int cdn_dp_firmware_init(struct cdn_dp_device *dp)
+{
+	int ret;
+	const u32 *iram_data, *dram_data;
+	const struct firmware *fw;
+	const struct cdn_firmware_header *hdr;
+
+	if (dp->fw_loaded)
+		return 0;
+
+	ret = request_firmware(&fw, "cdn/dptx.bin", dp->dev);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to request firmware %d\n", ret);
+		return ret;
+	}
+
+	hdr = (struct cdn_firmware_header *)fw->data;
+	if (fw->size != le32_to_cpu(hdr->size_bytes))
+		return -EINVAL;
+
+	ret = cdn_dp_clk_enable(dp);
+	if (ret < 0) {
+		dev_err(dp->dev, "cannot enable dp clk %d\n", ret);
+		return ret;
+	}
+
+	dp_clock_reset_seq(dp);
+
+	iram_data = (const u32 *)(fw->data + hdr->header_size);
+	dram_data = (const u32 *)(fw->data + hdr->header_size + hdr->iram_size);
+
+	ret = cdn_dp_load_firmware(dp,
+				   iram_data, hdr->iram_size,
+				   dram_data, hdr->dram_size);
+
+	ret = cdn_dp_active(dp, true);
+	if (ret) {
+		dev_err(dp->dev, "active ucpu failed: %d\n", ret);
+		return ret;
+	}
+
+	cdn_dp_event_config(dp);
+
+	return 0;
+}
+
+static int cdn_dp_init(struct cdn_dp_device *dp)
+{
+	struct device *dev = dp->dev;
+	struct device_node *np = dev->of_node;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct resource *res;
+
+	dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+	if (IS_ERR(dp->grf)) {
+		dev_err(dev, "cdn-dp needs rockchip,grf property\n");
+		return PTR_ERR(dp->grf);
+	}
+
+	dp->irq = platform_get_irq(pdev, 0);
+	if (dp->irq < 0) {
+		dev_err(dev, "cdn-dp can not get irq\n");
+		return dp->irq;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dp->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(dp->regs)) {
+		dev_err(dev, "ioremap reg failed\n");
+		return PTR_ERR(dp->regs);
+	}
+
+	dp->core_clk = devm_clk_get(dev, "core_clk");
+	if (IS_ERR(dp->core_clk)) {
+		dev_err(dev, "cannot get core_clk_dp\n");
+		return PTR_ERR(dp->core_clk);
+	}
+
+	dp->pclk = devm_clk_get(dev, "pclk");
+	if (IS_ERR(dp->pclk)) {
+		dev_err(dev, "cannot get pclk\n");
+		return PTR_ERR(dp->pclk);
+	}
+
+	dp->spdif_clk = devm_clk_get(dev, "spdif");
+	if (IS_ERR(dp->spdif_clk)) {
+		dev_err(dev, "cannot get spdif_clk\n");
+		return PTR_ERR(dp->spdif_clk);
+	}
+
+	dp->dpms_mode = DRM_MODE_DPMS_OFF;
+
+	dev_set_name(dp->dev, "cdn-dp");
+
+	return 0;
+}
+
+static const struct cdn_dp_audio_ops dp_audio_ops = {
+	.audio_startup = cdn_dp_audio_start,
+	.audio_shutdown = cdn_dp_audio_stop,
+	.audio_start = cdn_dp_audio_start,
+	.audio_stop = cdn_dp_audio_stop,
+	.audio_config = cdn_dp_audio_config_set,
+};
+
+static int cdn_dp_pd_event(struct notifier_block *nb,
+			   unsigned long event, void *priv)
+{
+	struct cdn_dp_device *dp;
+	u8 map, is_dp;
+	int value = *(int *)priv;
+
+	dp = container_of(nb, struct cdn_dp_device, event_nb);
+	if (IS_ERR_OR_NULL(dp)) {
+		pr_err("initialization issue");
+		return -1;
+	}
+
+	is_dp = GET_DP(value);
+
+	if (!is_dp)
+		return 0;
+
+	dp->flip = GET_FLIP(value);
+	map = GET_PIN_MAP(value);
+	if (map & (PIN_MAP_B | PIN_MAP_D | PIN_MAP_F))
+		dp->cap_lanes = 2;
+	else
+		dp->cap_lanes = 4;
+
+	schedule_delayed_work_on(0, &dp->event_wq, 100);
+
+	return 0;
+}
+
+static void cdn_dp_pd_event_wq(struct work_struct *work)
+{
+	struct cdn_dp_device *dp;
+
+	dp = container_of(work, struct cdn_dp_device, event_wq.work);
+	if (IS_ERR_OR_NULL(dp)) {
+		pr_err("initialization issue");
+		return;
+	}
+
+	if (cdn_dp_firmware_init(dp))
+		return;
+
+	if ((cdn_dp_get_event(dp) & DPTX_HPD_EVENT) && (dp->drm_dev))
+		drm_helper_hpd_irq_event(dp->drm_dev);
+}
+
+static int cdn_dp_bind(struct device *dev, struct device *master,
+		       void *data)
+{
+	struct cdn_dp_audio_pdata audio_pdata;
+	struct cdn_dp_device *dp = dev_get_drvdata(dev);
+	struct device_node *np = dev->of_node;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	struct drm_device *drm_dev = data;
+	struct phy *phy = devm_of_phy_get_by_index(dev, np, 0);
+	int ret;
+
+	if (IS_ERR(phy))
+		return -EPROBE_DEFER;
+
+	dp->phy = phy;
+
+	ret = cdn_dp_init(dp);
+	if (ret < 0)
+		return ret;
+
+	dp->drm_dev = drm_dev;
+
+	encoder = &dp->encoder;
+
+	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev,
+							     dev->of_node);
+	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
+
+	ret = drm_encoder_init(drm_dev, encoder, &cdn_dp_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS, NULL);
+	if (ret) {
+		DRM_ERROR("failed to initialize encoder with drm\n");
+		return ret;
+	}
+
+	drm_encoder_helper_add(encoder, &cdn_dp_encoder_helper_funcs);
+
+	connector = &dp->connector;
+	connector->polled = DRM_CONNECTOR_POLL_HPD;
+	connector->dpms = DRM_MODE_DPMS_OFF;
+
+	ret = drm_connector_init(drm_dev, connector,
+				 &cdn_dp_atomic_connector_funcs,
+				 DRM_MODE_CONNECTOR_DisplayPort);
+	if (ret) {
+		DRM_ERROR("failed to initialize connector with drm\n");
+		goto err_free_encoder;
+	}
+
+	drm_connector_helper_add(connector, &cdn_dp_connector_helper_funcs);
+
+	ret = drm_mode_connector_attach_encoder(connector, encoder);
+	if (ret) {
+		DRM_ERROR("failed to attach connector and encoder\n");
+		goto err_free_connector;
+	}
+
+	audio_pdata.dev = dev,
+	audio_pdata.ops = &dp_audio_ops,
+	audio_pdata.data = dp;
+
+	dp->audio_pdev = platform_device_register_data(
+		dev, "cdn-dp-audio", PLATFORM_DEVID_NONE,
+		&audio_pdata, sizeof(audio_pdata));
+
+	if (IS_ERR(dp->audio_pdev))
+		return PTR_ERR(dp->audio_pdev);
+
+	dp->event_nb.notifier_call = cdn_dp_pd_event;
+	INIT_DELAYED_WORK(&dp->event_wq, cdn_dp_pd_event_wq);
+	tcphy_register_notifier(phy, &dp->event_nb);
+
+	return 0;
+
+err_free_connector:
+	drm_connector_cleanup(connector);
+err_free_encoder:
+	drm_encoder_cleanup(encoder);
+	return ret;
+}
+
+static void cdn_dp_unbind(struct device *dev, struct device *master, void *data)
+{
+	struct cdn_dp_device *dp = dev_get_drvdata(dev);
+	struct drm_encoder *encoder = &dp->encoder;
+
+	platform_device_unregister(dp->audio_pdev);
+	cdn_dp_encoder_disable(encoder);
+	encoder->funcs->destroy(encoder);
+	drm_connector_unregister(&dp->connector);
+	drm_connector_cleanup(&dp->connector);
+	drm_encoder_cleanup(encoder);
+	tcphy_unregister_notifier(dp->phy, &dp->event_nb);
+}
+
+static const struct component_ops cdn_dp_component_ops = {
+	.bind = cdn_dp_bind,
+	.unbind = cdn_dp_unbind,
+};
+
+static int cdn_dp_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct cdn_dp_device *dp;
+
+	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
+	if (!dp)
+		return -ENOMEM;
+	dp->dev = dev;
+
+	platform_set_drvdata(pdev, dp);
+
+	return component_add(dev, &cdn_dp_component_ops);
+}
+
+static int cdn_dp_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &cdn_dp_component_ops);
+
+	return 0;
+}
+
+static const struct of_device_id cdn_dp_dt_ids[] = {
+	{.compatible = "rockchip,cdn-dp",},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, cdn_dp_dt_ids);
+
+static struct platform_driver cdn_dp_driver = {
+	.probe = cdn_dp_probe,
+	.remove = cdn_dp_remove,
+	.driver = {
+		   .name = "cdn-dp",
+		   .owner = THIS_MODULE,
+		   .of_match_table = of_match_ptr(cdn_dp_dt_ids),
+	},
+};
+
+module_platform_driver(cdn_dp_driver);
+
+MODULE_AUTHOR("Chris Zhong <zyw at rock-chips.com>");
+MODULE_DESCRIPTION("cdn DP Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h
new file mode 100644
index 0000000..99c0123
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ROCKCHIP_EDP_CORE_H
+#define _ROCKCHIP_EDP_CORE_H
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_panel.h>
+#include "rockchip_drm_drv.h"
+#include "cdn-dp-reg.h"
+
+struct video_info {
+	bool h_sync_polarity;
+	bool v_sync_polarity;
+	bool interlaced;
+	int color_depth;
+	enum VIC_PXL_ENCODING_FORMAT color_fmt;
+};
+
+struct cdn_firmware_header {
+	u32 size_bytes; /* size of the entire header+image(s) in bytes */
+	u32 header_size; /* size of just the header in bytes */
+	u32 iram_size; /* size of iram */
+	u32 dram_size; /* size of dram */
+};
+
+struct cdn_dp_device {
+	struct device *dev;
+	struct drm_device *drm_dev;
+	struct drm_connector connector;
+	struct drm_encoder encoder;
+	struct drm_display_mode mode;
+	struct delayed_work hotplug_work;
+	struct platform_device *audio_pdev;
+	bool plugged;
+
+	const struct firmware *fw;	/* cdn dp firmware */
+	unsigned int fw_version;	/* cdn fw version */
+	bool fw_loaded;
+	void __iomem *regs;
+	void __iomem *phy_regs;
+	struct regmap *grf;
+	unsigned int irq;
+	struct clk *core_clk;
+	struct clk *pclk;
+	struct clk *spdif_clk;
+	struct video_info video_info;
+	struct phy *phy;
+	struct notifier_block	event_nb;
+	struct delayed_work	event_wq;
+
+	int cap_lanes;
+	bool flip;
+
+	int dpms_mode;
+	struct drm_dp_link link;
+	bool sink_has_audio;
+};
+
+void dp_clock_reset_seq(struct cdn_dp_device *dp);
+
+void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, int clk);
+int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
+			 u32 i_size, const u32 *d_mem, u32 d_size);
+int cdn_dp_active(struct cdn_dp_device *dp, u8 enable);
+int cdn_dp_set_host_cap(struct cdn_dp_device *dp);
+int cdn_dp_event_config(struct cdn_dp_device *dp);
+int cdn_dp_get_event(struct cdn_dp_device *dp);
+int cdn_dp_get_hpd_status(struct cdn_dp_device *dp);
+int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value);
+int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr);
+int cdn_dp_get_edid_block(void *dp, u8 *edid,
+			  unsigned int block, size_t length);
+int cdn_dp_training_start(struct cdn_dp_device *dp);
+int cdn_dp_get_lt_status(struct cdn_dp_device *dp);
+int cdn_dp_set_video_status(struct cdn_dp_device *dp, int active);
+int cdn_dp_config_video(struct cdn_dp_device *dp);
+int cdn_dp_audio_start(void *dp_dev, struct audio_info *audio);
+int cdn_dp_audio_stop(void *dp_dev, struct audio_info *audio);
+int cdn_dp_audio_config_set(void *dp_dev, struct audio_info *audio);
+
+#endif  /* _ROCKCHIP_EDP_CORE_H */
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
new file mode 100644
index 0000000..d6c9bcb
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -0,0 +1,730 @@
+/*
+ * cdn dp controller register driver
+ *
+ * Copyright (C) 2016 Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/reset.h>
+
+#include <sound/cdn-dp-audio.h>
+
+#include "cdn-dp-core.h"
+#include "cdn-dp-reg.h"
+
+#define FW_ALIVE_TIMEOUT_US		1000000
+#define MAILBOX_TIMEOUT_US		5000000
+
+/* the max size of read buff is 134 */
+static u8 rx_buff[134];
+
+void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, int clk)
+{
+	writel(clk / 1000000, dp->regs + SW_CLK_H);
+}
+
+void dp_clock_reset_seq(struct cdn_dp_device *dp)
+{
+	writel(0xfff, dp->regs + SOURCE_DPTX_CAR);
+	writel(0x7, dp->regs + SOURCE_PHY_CAR);
+	writel(0xf, dp->regs + SOURCE_PKT_CAR);
+	writel(0xff, dp->regs + SOURCE_AIF_CAR);
+	writel(0xf, dp->regs + SOURCE_CIPHER_CAR);
+	writel(0x3, dp->regs + SOURCE_CRYPTO_CAR);
+	writel(0, dp->regs + APB_INT_MASK);
+}
+
+static u8 cdn_dp_mailbox_read(struct cdn_dp_device *dp)
+{
+	int val, ret;
+
+	if (!dp->fw_loaded)
+		return 0;
+
+	ret = readx_poll_timeout(readl, dp->regs + MAILBOX_EMPTY_ADDR,
+				 val, !val, 1000, MAILBOX_TIMEOUT_US);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to wait mailbox response\n");
+		return 0;
+	}
+
+	return readl(dp->regs + MAILBOX0_RD_DATA) & 0xff;
+}
+
+static void cdp_dp_mailbox_write(struct cdn_dp_device *dp, u8 val)
+{
+	int ret, full;
+
+	if (!dp->fw_loaded)
+		return;
+
+	ret = readx_poll_timeout(readl, dp->regs + MAILBOX_FULL_ADDR,
+				 full, !full, 1000, MAILBOX_TIMEOUT_US);
+	if (ret < 0) {
+		dev_err(dp->dev, "mailbox is full\n");
+		return;
+	}
+
+	writel(val, dp->regs + MAILBOX0_WR_DATA);
+}
+
+/* return the size of message */
+int cdn_dp_mailbox_response(struct cdn_dp_device *dp, u8 module_id,
+			    u8 opcode, u8 **message)
+{
+	int size, i = 0;
+
+	memset(rx_buff, 0, 4);
+
+	while (i < sizeof(rx_buff)) {
+		if (i < sizeof(rx_buff))
+			rx_buff[i++] = cdn_dp_mailbox_read(dp);
+
+		size = ((rx_buff[2] << 8) | rx_buff[3]) + 4;
+		if (i >= size)
+			break;
+	}
+
+	if ((opcode != rx_buff[0]) || (module_id != rx_buff[1]))
+		return -EINVAL;
+
+	size = (rx_buff[2] << 8) | rx_buff[3];
+
+	*message = &rx_buff[4];
+
+	return size;
+}
+
+int cdn_dp_mailbox_send(struct cdn_dp_device *dp, u8 module_id, u8 opcode,
+			u16 size, u8 *message)
+{
+	cdp_dp_mailbox_write(dp, opcode);
+	cdp_dp_mailbox_write(dp, module_id);
+	cdp_dp_mailbox_write(dp, size >> 8);
+	cdp_dp_mailbox_write(dp, size & 0xff);
+
+	while (size--)
+		cdp_dp_mailbox_write(dp, *message++);
+
+	return 0;
+}
+
+int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem,
+			 u32 i_size, const u32 *d_mem, u32 d_size)
+{
+	int i, reg, ret;
+
+	/* reset ucpu before load firmware*/
+	writel(APB_IRAM_PATH | APB_DRAM_PATH | APB_XT_RESET,
+	       dp->regs + APB_CTRL);
+
+	for (i = 0; i < i_size; i += 4)
+		writel(*i_mem++, dp->regs + ADDR_IMEM + i);
+
+	for (i = 0; i < d_size; i += 4)
+		writel(*d_mem++, dp->regs + ADDR_DMEM + i);
+
+	/* un-reset ucpu */
+	writel(0, dp->regs + APB_CTRL);
+
+	/* check the keep alive register to make sure fw working */
+	ret = readx_poll_timeout(readl, dp->regs + KEEP_ALIVE,
+				 reg, reg, 2000, FW_ALIVE_TIMEOUT_US);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to loaded the FW reg = %x\n", reg);
+		return -EINVAL;
+	}
+
+	reg = readl(dp->regs + VER_L) & 0xff;
+	dp->fw_version = reg;
+	reg = readl(dp->regs + VER_H) & 0xff;
+	dp->fw_version |= reg << 8;
+	reg = readl(dp->regs + VER_LIB_L_ADDR) & 0xff;
+	dp->fw_version |= reg << 16;
+	reg = readl(dp->regs + VER_LIB_H_ADDR) & 0xff;
+	dp->fw_version |= reg << 24;
+
+	dp->fw_loaded = 1;
+
+	return 0;
+}
+
+int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val)
+{
+	u8 msg[6];
+
+	msg[0] = (addr >> 8) & 0xff;
+	msg[1] = addr & 0xff;
+	msg[2] = (val >> 24) & 0xff;
+	msg[3] = (val >> 16) & 0xff;
+	msg[4] = (val >> 8) & 0xff;
+	msg[5] = val & 0xff;
+	return cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_REGISTER,
+				   ARRAY_SIZE(msg), msg);
+}
+
+int cdn_dp_reg_read(struct cdn_dp_device *dp, u16 addr)
+{
+	u8 msg[2], *reg = NULL;
+	u16 size;
+
+	msg[0] = (addr >> 8) & 0xff;
+	msg[1] = addr & 0xff;
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_READ_REGISTER,
+			    ARRAY_SIZE(msg), msg);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+				       DPTX_READ_REGISTER, &reg);
+	if (size != 6)
+		return -EINVAL;
+
+	if ((msg[0] == reg[0]) && (msg[1] == reg[1]))
+		return (reg[2] << 24) | (reg[3] << 16) | (reg[4] << 8) | reg[5];
+
+	return -EINVAL;
+}
+
+int cdn_dp_reg_write_bit(struct cdn_dp_device *dp, u16 addr, u8 start_bit,
+			 u8 bits_no, u32 val)
+{
+	u8 field[8];
+
+	field[0] = (addr >> 8) & 0xff;
+	field[1] = addr & 0xff;
+	field[2] = start_bit;
+	field[3] = bits_no;
+	field[4] = (val >> 24) & 0xff;
+	field[5] = (val >> 16) & 0xff;
+	field[6] = (val >> 8) & 0xff;
+	field[7] = val & 0xff;
+
+	return cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_FIELD,
+			    sizeof(field), field);
+}
+
+int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value)
+{
+	u8 msg[6], *reg = NULL;
+	u16 size;
+
+	msg[0] = 0;
+	msg[1] = 1;
+	msg[2] = (addr >> 16) & 0xff;
+	msg[3] = (addr >> 8) & 0xff;
+	msg[4] = addr & 0xff;
+	msg[5] = value;
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_DPCD,
+			    ARRAY_SIZE(msg), msg);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+				       DPTX_WRITE_DPCD, &reg);
+	if (size != 5)
+		return -EINVAL;
+
+	if ((msg[2] == reg[2]) && (msg[3] == reg[3]) && (msg[4] == reg[4]))
+		return 0;
+
+	return -EINVAL;
+}
+
+int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr)
+{
+	u8 msg[5], *reg = NULL;
+	u16 size;
+
+	msg[0] = 0;
+	msg[1] = 1;
+	msg[2] = (addr >> 16) & 0xff;
+	msg[3] = (addr >> 8) & 0xff;
+	msg[4] = addr & 0xff;
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_READ_DPCD,
+			    ARRAY_SIZE(msg), msg);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+				       DPTX_READ_DPCD, &reg);
+	if (size != 6)
+		return -EINVAL;
+
+	if ((msg[2] == reg[2]) && (msg[3] == reg[3]) && (msg[4] == reg[4]))
+		return reg[5];
+
+	return -EINVAL;
+}
+
+int cdn_dp_active(struct cdn_dp_device *dp, u8 enable)
+{
+	u8 active = enable ? 1 : 0;
+	u8 *resp = NULL;
+	int size;
+
+	/* set firmware status, 1: avtive; 0: standby */
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_GENERAL, GENERAL_MAIN_CONTROL,
+			    1, &active);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_GENERAL,
+				       GENERAL_MAIN_CONTROL, &resp);
+	if (size != 1)
+		return -EINVAL;
+
+	return *resp ? 0 : -EINVAL;
+}
+
+int cdn_dp_set_host_cap(struct cdn_dp_device *dp)
+{
+	u8 msg[8];
+
+	msg[0] = DP_LINK_BW_5_4;
+	msg[1] = dp->cap_lanes;
+	msg[2] = VOLTAGE_LEVEL_2;
+	msg[3] = PRE_EMPHASIS_LEVEL_3;
+	msg[4] = PRBS7 | D10_2 | TRAINING_PTN1 | TRAINING_PTN2;
+	msg[5] = FAST_LT_NOT_SUPPORT;
+	msg[6] = LANE_MAPPING_NORMAL;
+	msg[7] = ENHANCED;
+
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX,
+			    DPTX_SET_HOST_CAPABILITIES,
+			    ARRAY_SIZE(msg), msg);
+
+	cdn_dp_reg_write(dp, DP_AUX_SWAP_INVERSION_CONTROL, AUX_HOST_INVERT);
+
+	return 0;
+}
+
+int cdn_dp_event_config(struct cdn_dp_device *dp)
+{
+	u8 msg[5];
+
+	msg[0] = DPTX_EVENT_ENABLE_HPD | DPTX_EVENT_ENABLE_TRAINING;
+
+	return cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_ENABLE_EVENT,
+				    ARRAY_SIZE(msg), msg);
+}
+
+int cdn_dp_get_event(struct cdn_dp_device *dp)
+{
+	return readl(dp->regs + SW_EVENTS0);
+}
+
+int cdn_dp_get_hpd_status(struct cdn_dp_device *dp)
+{
+	u8 *status = NULL;
+	int size;
+
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_HPD_STATE,
+			    0, NULL);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+				       DPTX_HPD_STATE, &status);
+	if (size != 1)
+		return -EINVAL;
+
+	return *status;
+}
+
+int cdn_dp_get_edid_block(void *data, u8 *edid,
+			  unsigned int block, size_t length)
+{
+	struct cdn_dp_device *dp = data;
+	int size;
+	u8 msg[2], *reg = NULL;
+
+	if (length != EDID_BLOCK_SIZE)
+		return -EINVAL;
+
+	msg[0] = block / 2;
+	msg[1] = block % 2;
+
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_GET_EDID,
+			    2, msg);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+				       DPTX_GET_EDID, &reg);
+
+	if (size != EDID_DATA + EDID_BLOCK_SIZE) {
+		dev_err(dp->dev, "read edid failed\n");
+		return -EINVAL;
+	}
+
+	if ((reg[EDID_LENGTH_BYTE] != EDID_BLOCK_SIZE) ||
+	    (reg[EDID_SEGMENT_BUMBER] != block / 2)) {
+		dev_err(dp->dev, "edid block size err\n");
+		return -EINVAL;
+	}
+
+	memcpy(edid, &reg[EDID_DATA], EDID_BLOCK_SIZE);
+
+	return 0;
+}
+
+int cdn_dp_training_start(struct cdn_dp_device *dp)
+{
+	int size;
+	u8 msg, *event = NULL;
+	unsigned long timeout;
+
+	msg = LINK_TRAINING_RUN;
+
+	/* start training */
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_TRAINING_CONTROL,
+			    1, &msg);
+
+	/* the whole training should finish in 500ms */
+	timeout = jiffies + msecs_to_jiffies(500);
+	while (1) {
+		msleep(20);
+		cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_READ_EVENT,
+				    0, NULL);
+
+		size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+					       DPTX_READ_EVENT, &event);
+		if (size != 2)
+			return -EINVAL;
+
+		if (event[1] & EQ_PHASE_FINISHED)
+			break;
+
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+int cdn_dp_get_lt_status(struct cdn_dp_device *dp)
+{
+	u8 *status = NULL;
+	int size;
+
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_READ_LINK_STAT,
+			    0, NULL);
+
+	size = cdn_dp_mailbox_response(dp, MB_MODULE_ID_DP_TX,
+				       DPTX_READ_LINK_STAT, &status);
+
+	if (size != 10)
+		return -EINVAL;
+
+	dp->link.rate = status[0];
+	dp->link.num_lanes = status[1];
+
+	return 0;
+}
+
+int cdn_dp_set_video_status(struct cdn_dp_device *dp, int active)
+{
+	u8 msg;
+
+	msg = !!active;
+
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_SET_VIDEO,
+			    1, &msg);
+
+	return 0;
+}
+
+int cdn_dp_set_audio_status(struct cdn_dp_device *dp, int active)
+{
+	u8 msg;
+
+	msg = !!active;
+
+	cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_SET_AUDIO,
+			    1, &msg);
+
+	return 0;
+}
+
+static int cdn_dp_get_msa_misc(struct video_info *video,
+			       struct drm_display_mode *mode)
+{
+	u8 val0, val1;
+	u32 msa_misc;
+
+	switch (video->color_fmt) {
+	case PXL_RGB:
+	case Y_ONLY:
+		val0 = 0;
+		break;
+	case YCBCR_4_4_4:
+		val0 = 6;
+		break;
+	case YCBCR_4_2_2:
+		val0 = 5;
+		break;
+	case YCBCR_4_2_0:
+		val0 = 5;
+		break;
+	};
+
+	switch (video->color_depth) {
+	case 6:
+		val1 = 0;
+		break;
+	case 8:
+		val1 = 1;
+		break;
+	case 10:
+		val1 = 2;
+		break;
+	case 12:
+		val1 = 3;
+		break;
+	case 16:
+		val1 = 4;
+		break;
+	};
+
+	msa_misc = 2 * val0 + 32 * val1 +
+		   ((video->color_fmt == Y_ONLY) ? (1 << 14) : 0);
+
+	return msa_misc;
+}
+
+int cdn_dp_config_video(struct cdn_dp_device *dp)
+{
+	struct video_info *video = &dp->video_info;
+	struct drm_display_mode *mode = &dp->mode;
+	u32 val, link_rate;
+	u8 bit_per_pix;
+
+	bit_per_pix = (video->color_fmt == YCBCR_4_2_2) ?
+		      (video->color_depth * 2) : (video->color_depth * 3);
+
+	val = VIF_BYPASS_INTERLACE;
+
+	cdn_dp_reg_write(dp, BND_HSYNC2VSYNC, val);
+
+	cdn_dp_reg_write(dp, HSYNC2VSYNC_POL_CTRL, 0);
+
+	link_rate = drm_dp_bw_code_to_link_rate(dp->link.rate) / 1000;
+
+	val = TU_SIZE * mode->clock * bit_per_pix;
+	val /= dp->link.num_lanes * link_rate * 8 * 1000;
+	/* FIXME: need add 1 to symbols 4K display */
+	if (mode->clock > 500000)
+		val += 1;
+
+	val += TU_SIZE << 8;
+
+	cdn_dp_reg_write(dp, DP_FRAMER_TU, val);
+
+	switch (video->color_depth) {
+	case 6:
+		val = BCS_6;
+		break;
+	case 8:
+		val = BCS_8;
+		break;
+	case 10:
+		val = BCS_10;
+		break;
+	case 12:
+		val = BCS_12;
+		break;
+	case 16:
+		val = BCS_16;
+		break;
+	};
+
+	val += video->color_fmt << 8;
+	cdn_dp_reg_write(dp, DP_FRAMER_PXL_REPR, val);
+
+	val = video->h_sync_polarity ? DP_FRAMER_SP_HSP : 0;
+	val |= video->v_sync_polarity ? DP_FRAMER_SP_VSP : 0;
+	cdn_dp_reg_write(dp, DP_FRAMER_SP, val);
+
+	val = (mode->hsync_start - mode->hdisplay) << 16;
+	val |= mode->htotal - mode->hsync_end;
+	cdn_dp_reg_write(dp, DP_FRONT_BACK_PORCH, val);
+
+	val = mode->hdisplay * bit_per_pix / 8;
+	cdn_dp_reg_write(dp, DP_BYTE_COUNT, val);
+
+	val = mode->htotal | ((mode->htotal - mode->hsync_start) << 16);
+	cdn_dp_reg_write(dp, MSA_HORIZONTAL_0, val);
+
+	val = mode->hsync_end - mode->hsync_start;
+	val |= (mode->hdisplay << 16) | (video->h_sync_polarity << 15);
+	cdn_dp_reg_write(dp, MSA_HORIZONTAL_1, val);
+
+	val = mode->vtotal;
+	val |= ((mode->vtotal - mode->vsync_start) << 16);
+
+	cdn_dp_reg_write(dp, MSA_VERTICAL_0, val);
+
+	val = mode->vsync_end - mode->vsync_start;
+	val |= mode->vdisplay << 16;
+	val |= (video->v_sync_polarity << 15);
+	cdn_dp_reg_write(dp, MSA_VERTICAL_1, val);
+
+	val = cdn_dp_get_msa_misc(video, mode);
+	cdn_dp_reg_write(dp, MSA_MISC, val);
+
+	cdn_dp_reg_write(dp, STREAM_CONFIG, 1);
+
+	val = mode->hsync_end - mode->hsync_start;
+	val |= (mode->hdisplay << 16);
+	cdn_dp_reg_write(dp, DP_HORIZONTAL, val);
+
+	val = mode->vtotal;
+	val -= (mode->vtotal - mode->vdisplay);
+	val |= (mode->vtotal - mode->vsync_start) << 16;
+
+	cdn_dp_reg_write(dp, DP_VERTICAL_0, val);
+
+	val = mode->vtotal;
+	cdn_dp_reg_write(dp, DP_VERTICAL_1, val);
+
+	val =  0;
+	cdn_dp_reg_write_bit(dp, DP_VB_ID, 2, 1, val);
+
+	return 0;
+}
+
+int cdn_dp_audio_start(void *dp_dev, struct audio_info *audio)
+{
+	struct cdn_dp_device *dp = (struct cdn_dp_device *)dp_dev;
+
+	if (audio->type == TYPE_SPDIF) {
+		clk_prepare_enable(dp->spdif_clk);
+		clk_set_rate(dp->spdif_clk, 400000000);
+	}
+
+	return cdn_dp_reg_write(dp, AUDIO_PACK_CONTROL, AUDIO_PACK_EN(1));
+}
+
+int cdn_dp_audio_stop(void *dp_dev, struct audio_info *audio)
+{
+	struct cdn_dp_device *dp = (struct cdn_dp_device *)dp_dev;
+
+	cdn_dp_reg_write(dp, AUDIO_PACK_CONTROL, AUDIO_PACK_EN(0));
+
+	if (audio->type == TYPE_SPDIF)
+		clk_disable_unprepare(dp->spdif_clk);
+
+	return 0;
+}
+
+int cdn_dp_audio_config_set(void *dp_dev, struct audio_info *audio)
+{
+	struct cdn_dp_device *dp = (struct cdn_dp_device *)dp_dev;
+	int lanes_param, i2s_port_en_val, val, i;
+
+	if ((audio->channels == 2) && (dp->link.num_lanes == 1))
+		lanes_param = 1;
+	else if (audio->channels == 2)
+		lanes_param = 3;
+	else
+		lanes_param = 0;
+
+	if (audio->channels == 2)
+		i2s_port_en_val = 1;
+	else if (audio->channels == 4)
+		i2s_port_en_val = 3;
+	else
+		i2s_port_en_val = 0xf;
+
+	cdn_dp_reg_write(dp, CM_LANE_CTRL, 0x8000);
+
+	cdn_dp_reg_write(dp, CM_CTRL, 0);
+
+	if (audio->type == TYPE_I2S) {
+		writel(0x0, dp->regs + SPDIF_CTRL_ADDR);
+
+		writel(SYNC_WR_TO_CH_ZERO, dp->regs + FIFO_CNTL);
+
+		val = audio->channels - 1;
+		val |= (audio->channels / 2 - 1) << 5;
+		val |= BIT(8);
+		val |= lanes_param << 11;
+		writel(val, dp->regs + SMPL2PKT_CNFG);
+
+		if (audio->word_length == 16)
+			val = 0;
+		else if (audio->word_length == 24)
+			val = 1 << 9;
+		else
+			val = 2 << 9;
+
+		val |= (audio->channels - 1) << 2;
+		val |= i2s_port_en_val << 17;
+		val |= 2 << 11;
+		writel(val, dp->regs + AUDIO_SRC_CNFG);
+
+		for (i = 0; i < (audio->channels + 1) / 2; i++) {
+			if (audio->word_length == 16)
+				val = (0x08 << 8) | (0x08 << 20);
+			else if (audio->word_length == 24)
+				val = (0x0b << 8) | (0x0b << 20);
+
+			val |= ((2 * i) << 4) | ((2 * i + 1) << 16);
+			writel(val, dp->regs + STTS_BIT_CH(i));
+		}
+
+		switch (audio->freq) {
+		case 32000:
+			val = SAMPLING_FREQ(3) |
+			      ORIGINAL_SAMP_FREQ(0xc);
+			break;
+		case 44100:
+			val = SAMPLING_FREQ(0) |
+			      ORIGINAL_SAMP_FREQ(0xf);
+			break;
+		case 48000:
+			val = SAMPLING_FREQ(2) |
+			      ORIGINAL_SAMP_FREQ(0xd);
+			break;
+		case 88200:
+			val = SAMPLING_FREQ(8) |
+			      ORIGINAL_SAMP_FREQ(0x7);
+			break;
+		case 96000:
+			val = SAMPLING_FREQ(0xa) |
+			      ORIGINAL_SAMP_FREQ(5);
+			break;
+		case 176400:
+			val = SAMPLING_FREQ(0xc) |
+			      ORIGINAL_SAMP_FREQ(3);
+			break;
+		case 192000:
+			val = SAMPLING_FREQ(0xe) |
+			      ORIGINAL_SAMP_FREQ(1);
+			break;
+		}
+		val |= 4;
+		writel(val, dp->regs + COM_CH_STTS_BITS);
+
+		writel(2, dp->regs + SMPL2PKT_CNTL);
+		writel(2, dp->regs + AUDIO_SRC_CNTL);
+		cdn_dp_reg_write_bit(dp, DP_VB_ID, 4, 1, 0);
+	} else {
+		val = 0x1F0707;
+		writel(val, dp->regs + SPDIF_CTRL_ADDR);
+
+		writel(SYNC_WR_TO_CH_ZERO, dp->regs + FIFO_CNTL);
+
+		val = 0x101 | (3 << 11);
+		writel(val, dp->regs + SMPL2PKT_CNFG);
+		writel(2, dp->regs + SMPL2PKT_CNTL);
+
+		val = 0x3F0707;
+		writel(val, dp->regs + SPDIF_CTRL_ADDR);
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
new file mode 100644
index 0000000..74fc7f9
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.h
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2016 Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CDN_DP_REG_H
+#define _CDN_DP_REG_H
+
+#include <linux/bitops.h>
+
+#define ADDR_IMEM		0x10000
+#define ADDR_DMEM		0x20000
+
+/* APB CFG addr */
+#define APB_CTRL			0
+#define XT_INT_CTRL			0x04
+#define MAILBOX_FULL_ADDR		0x08
+#define MAILBOX_EMPTY_ADDR		0x0c
+#define MAILBOX0_WR_DATA		0x10
+#define MAILBOX0_RD_DATA		0x14
+#define KEEP_ALIVE			0x18
+#define VER_L				0x1c
+#define VER_H				0x20
+#define VER_LIB_L_ADDR			0x24
+#define VER_LIB_H_ADDR			0x28
+#define SW_DEBUG_L			0x2c
+#define SW_DEBUG_H			0x30
+#define MAILBOX_INT_MASK		0x34
+#define MAILBOX_INT_STATUS		0x38
+#define SW_CLK_L			0x3c
+#define SW_CLK_H			0x40
+#define SW_EVENTS0			0x44
+#define SW_EVENTS1			0x48
+#define SW_EVENTS2			0x4c
+#define SW_EVENTS3			0x50
+#define XT_OCD_CTRL			0x60
+#define APB_INT_MASK			0x6c
+#define APB_STATUS_MASK			0x70
+
+/* audio decoder addr */
+#define AUDIO_SRC_CNTL			0x30000
+#define AUDIO_SRC_CNFG			0x30004
+#define COM_CH_STTS_BITS		0x30008
+#define STTS_BIT_CH(x)			(0x3000c + (x << 2))
+#define SPDIF_CTRL_ADDR			0x3004c
+#define SPDIF_CH1_CS_3100_ADDR		0x30050
+#define SPDIF_CH1_CS_6332_ADDR		0x30054
+#define SPDIF_CH1_CS_9564_ADDR		0x30058
+#define SPDIF_CH1_CS_12796_ADDR		0x3005c
+#define SPDIF_CH1_CS_159128_ADDR	0x30060
+#define SPDIF_CH1_CS_191160_ADDR	0x30064
+#define SPDIF_CH2_CS_3100_ADDR		0x30068
+#define SPDIF_CH2_CS_6332_ADDR		0x3006c
+#define SPDIF_CH2_CS_9564_ADDR		0x30070
+#define SPDIF_CH2_CS_12796_ADDR		0x30074
+#define SPDIF_CH2_CS_159128_ADDR	0x30078
+#define SPDIF_CH2_CS_191160_ADDR	0x3007c
+#define SMPL2PKT_CNTL			0x30080
+#define SMPL2PKT_CNFG			0x30084
+#define FIFO_CNTL			0x30088
+#define FIFO_STTS			0x3008c
+
+/* source pif addr */
+#define SOURCE_PIF_WR_ADDR		0x30800
+#define SOURCE_PIF_WR_REQ		0x30804
+#define SOURCE_PIF_RD_ADDR		0x30808
+#define SOURCE_PIF_RD_REQ		0x3080c
+#define SOURCE_PIF_DATA_WR		0x30810
+#define SOURCE_PIF_DATA_RD		0x30814
+#define SOURCE_PIF_FIFO1_FLUSH		0x30818
+#define SOURCE_PIF_FIFO2_FLUSH		0x3081c
+#define SOURCE_PIF_STATUS		0x30820
+#define SOURCE_PIF_INTERRUPT_SOURCE	0x30824
+#define SOURCE_PIF_INTERRUPT_MASK	0x30828
+#define SOURCE_PIF_PKT_ALLOC_REG	0x3082c
+#define SOURCE_PIF_PKT_ALLOC_WR_EN	0x30830
+#define SOURCE_PIF_SW_RESET		0x30834
+
+/* bellow registers need access by mailbox */
+/* source car addr */
+#define SOURCE_HDTX_CAR			0x0900
+#define SOURCE_DPTX_CAR			0x0904
+#define SOURCE_PHY_CAR			0x0908
+#define SOURCE_CEC_CAR			0x090c
+#define SOURCE_CBUS_CAR			0x0910
+#define SOURCE_PKT_CAR			0x0918
+#define SOURCE_AIF_CAR			0x091c
+#define SOURCE_CIPHER_CAR		0x0920
+#define SOURCE_CRYPTO_CAR		0x0924
+
+/* clock meters addr */
+#define CM_CTRL				0x0a00
+#define CM_I2S_CTRL			0x0a04
+#define CM_SPDIF_CTRL			0x0a08
+#define CM_VID_CTRL			0x0a0c
+#define CM_LANE_CTRL			0x0a10
+#define I2S_NM_STABLE			0x0a14
+#define I2S_NCTS_STABLE			0x0a18
+#define SPDIF_NM_STABLE			0x0a1c
+#define SPDIF_NCTS_STABLE		0x0a20
+#define NMVID_MEAS_STABLE		0x0a24
+#define I2S_MEAS			0x0a40
+#define SPDIF_MEAS			0x0a80
+#define NMVID_MEAS			0x0ac0
+
+/* source vif addr */
+#define BND_HSYNC2VSYNC			0x0b00
+#define HSYNC2VSYNC_F1_L1		0x0b04
+#define HSYNC2VSYNC_F2_L1		0x0b08
+#define HSYNC2VSYNC_STATUS		0x0b0c
+#define HSYNC2VSYNC_POL_CTRL		0x0b10
+
+/* dptx phy addr */
+#define DP_TX_PHY_CONFIG_REG		0x2000
+#define DP_TX_PHY_STATUS_REG		0x2004
+#define DP_TX_PHY_SW_RESET		0x2008
+#define DP_TX_PHY_SCRAMBLER_SEED	0x200c
+#define DP_TX_PHY_TRAINING_01_04	0x2010
+#define DP_TX_PHY_TRAINING_05_08	0x2014
+#define DP_TX_PHY_TRAINING_09_10	0x2018
+#define TEST_COR			0x23fc
+
+/* dptx hpd addr */
+#define HPD_IRQ_DET_MIN_TIMER		0x2100
+#define HPD_IRQ_DET_MAX_TIMER		0x2104
+#define HPD_UNPLGED_DET_MIN_TIMER	0x2108
+#define HPD_STABLE_TIMER		0x210c
+#define HPD_FILTER_TIMER		0x2110
+#define HPD_EVENT_MASK			0x211c
+#define HPD_EVENT_DET			0x2120
+
+/* dpyx framer addr */
+#define DP_FRAMER_GLOBAL_CONFIG		0x2200
+#define DP_SW_RESET			0x2204
+#define DP_FRAMER_TU			0x2208
+#define DP_FRAMER_PXL_REPR		0x220c
+#define DP_FRAMER_SP			0x2210
+#define AUDIO_PACK_CONTROL		0x2214
+#define DP_VC_TABLE(x)			(0x2218 + (x << 2))
+#define DP_VB_ID			0x2258
+#define DP_MTPH_LVP_CONTROL		0x225c
+#define DP_MTPH_SYMBOL_VALUES		0x2260
+#define DP_MTPH_ECF_CONTROL		0x2264
+#define DP_MTPH_ACT_CONTROL		0x2268
+#define DP_MTPH_STATUS			0x226c
+#define DP_INTERRUPT_SOURCE		0x2270
+#define DP_INTERRUPT_MASK		0x2274
+#define DP_FRONT_BACK_PORCH		0x2278
+#define DP_BYTE_COUNT			0x227c
+
+/* dptx stream addr */
+#define MSA_HORIZONTAL_0		0x2280
+#define MSA_HORIZONTAL_1		0x2284
+#define MSA_VERTICAL_0			0x2288
+#define MSA_VERTICAL_1			0x228c
+#define MSA_MISC			0x2290
+#define STREAM_CONFIG			0x2294
+#define AUDIO_PACK_STATUS		0x2298
+#define VIF_STATUS			0x229c
+#define PCK_STUFF_STATUS_0		0x22a0
+#define PCK_STUFF_STATUS_1		0x22a4
+#define INFO_PACK_STATUS		0x22a8
+#define RATE_GOVERNOR_STATUS		0x22ac
+#define DP_HORIZONTAL			0x22b0
+#define DP_VERTICAL_0			0x22b4
+#define DP_VERTICAL_1			0x22b8
+#define DP_BLOCK_SDP			0x22bc
+
+/* dptx glbl addr */
+#define DPTX_LANE_EN			0x2300
+#define DPTX_ENHNCD			0x2304
+#define DPTX_INT_MASK			0x2308
+#define DPTX_INT_STATUS			0x230c
+
+/* dp aux addr */
+#define DP_AUX_HOST_CONTROL		0x2800
+#define DP_AUX_INTERRUPT_SOURCE		0x2804
+#define DP_AUX_INTERRUPT_MASK		0x2808
+#define DP_AUX_SWAP_INVERSION_CONTROL	0x280c
+#define DP_AUX_SEND_NACK_TRANSACTION	0x2810
+#define DP_AUX_CLEAR_RX			0x2814
+#define DP_AUX_CLEAR_TX			0x2818
+#define DP_AUX_TIMER_STOP		0x281c
+#define DP_AUX_TIMER_CLEAR		0x2820
+#define DP_AUX_RESET_SW			0x2824
+#define DP_AUX_DIVIDE_2M		0x2828
+#define DP_AUX_TX_PREACHARGE_LENGTH	0x282c
+#define DP_AUX_FREQUENCY_1M_MAX		0x2830
+#define DP_AUX_FREQUENCY_1M_MIN		0x2834
+#define DP_AUX_RX_PRE_MIN		0x2838
+#define DP_AUX_RX_PRE_MAX		0x283c
+#define DP_AUX_TIMER_PRESET		0x2840
+#define DP_AUX_NACK_FORMAT		0x2844
+#define DP_AUX_TX_DATA			0x2848
+#define DP_AUX_RX_DATA			0x284c
+#define DP_AUX_TX_STATUS		0x2850
+#define DP_AUX_RX_STATUS		0x2854
+#define DP_AUX_RX_CYCLE_COUNTER		0x2858
+#define DP_AUX_MAIN_STATES		0x285c
+#define DP_AUX_MAIN_TIMER		0x2860
+#define DP_AUX_AFE_OUT			0x2864
+
+/* crypto addr */
+#define CRYPTO_HDCP_REVISION		0x5800
+#define HDCP_CRYPTO_CONFIG		0x5804
+#define CRYPTO_INTERRUPT_SOURCE		0x5808
+#define CRYPTO_INTERRUPT_MASK		0x580c
+#define CRYPTO22_CONFIG			0x5818
+#define CRYPTO22_STATUS			0x581c
+#define SHA_256_DATA_IN			0x583c
+#define SHA_256_DATA_OUT_(x)		(0x5850 + (x << 2))
+#define AES_32_KEY_(x)			(0x5870 + (x << 2))
+#define AES_32_DATA_IN			0x5880
+#define AES_32_DATA_OUT_(x)		(0x5884 + (x << 2))
+#define CRYPTO14_CONFIG			0x58a0
+#define CRYPTO14_STATUS			0x58a4
+#define CRYPTO14_PRNM_OUT		0x58a8
+#define CRYPTO14_KM_0			0x58ac
+#define CRYPTO14_KM_1			0x58b0
+#define CRYPTO14_AN_0			0x58b4
+#define CRYPTO14_AN_1			0x58b8
+#define CRYPTO14_YOUR_KSV_0		0x58bc
+#define CRYPTO14_YOUR_KSV_1		0x58c0
+#define CRYPTO14_MI_0			0x58c4
+#define CRYPTO14_MI_1			0x58c8
+#define CRYPTO14_TI_0			0x58cc
+#define CRYPTO14_KI_0			0x58d0
+#define CRYPTO14_KI_1			0x58d4
+#define CRYPTO14_BLOCKS_NUM		0x58d8
+#define CRYPTO14_KEY_MEM_DATA_0		0x58dc
+#define CRYPTO14_KEY_MEM_DATA_1		0x58e0
+#define CRYPTO14_SHA1_MSG_DATA		0x58e4
+#define CRYPTO14_SHA1_V_VALUE_(x)	(0x58e8 + (x << 2))
+#define TRNG_CTRL			0x58fc
+#define TRNG_DATA_RDY			0x5900
+#define TRNG_DATA			0x5904
+
+/* cipher addr */
+#define HDCP_REVISION			0x60000
+#define INTERRUPT_SOURCE		0x60004
+#define INTERRUPT_MASK			0x60008
+#define HDCP_CIPHER_CONFIG		0x6000c
+#define AES_128_KEY_0			0x60010
+#define AES_128_KEY_1			0x60014
+#define AES_128_KEY_2			0x60018
+#define AES_128_KEY_3			0x6001c
+#define AES_128_RANDOM_0		0x60020
+#define AES_128_RANDOM_1		0x60024
+#define CIPHER14_KM_0			0x60028
+#define CIPHER14_KM_1			0x6002c
+#define CIPHER14_STATUS			0x60030
+#define CIPHER14_RI_PJ_STATUS		0x60034
+#define CIPHER_MODE			0x60038
+#define CIPHER14_AN_0			0x6003c
+#define CIPHER14_AN_1			0x60040
+#define CIPHER22_AUTH			0x60044
+#define CIPHER14_R0_DP_STATUS		0x60048
+#define CIPHER14_BOOTSTRAP		0x6004c
+
+#define APB_IRAM_PATH			BIT(2)
+#define APB_DRAM_PATH			BIT(1)
+#define APB_XT_RESET			BIT(0)
+
+/* mailbox */
+#define MB_OPCODE_ID			0
+#define MB_MODULE_ID			1
+#define MB_SIZE_MSB_ID			2
+#define MB_SIZE_LSB_ID			3
+#define MB_DATA_ID			4
+
+#define MB_MODULE_ID_DP_TX		0x01
+#define MB_MODULE_ID_HDCP_TX		0x07
+#define MB_MODULE_ID_HDCP_RX		0x08
+#define MB_MODULE_ID_HDCP_GENERAL	0x09
+#define MB_MODULE_ID_GENERAL		0x0a
+
+/* general opcode */
+#define GENERAL_MAIN_CONTROL            0x01
+#define GENERAL_TEST_ECHO               0x02
+#define GENERAL_BUS_SETTINGS            0x03
+#define GENERAL_TEST_ACCESS             0x04
+
+#define DPTX_SET_POWER_MNG			0x00
+#define DPTX_SET_HOST_CAPABILITIES		0x01
+#define DPTX_GET_EDID				0x02
+#define DPTX_READ_DPCD				0x03
+#define DPTX_WRITE_DPCD				0x04
+#define DPTX_ENABLE_EVENT			0x05
+#define DPTX_WRITE_REGISTER			0x06
+#define DPTX_READ_REGISTER			0x07
+#define DPTX_WRITE_FIELD			0x08
+#define DPTX_TRAINING_CONTROL			0x09
+#define DPTX_READ_EVENT				0x0a
+#define DPTX_READ_LINK_STAT			0x0b
+#define DPTX_SET_VIDEO				0x0c
+#define DPTX_SET_AUDIO				0x0d
+#define DPTX_GET_LAST_AUX_STAUS			0x0e
+#define DPTX_SET_LINK_BREAK_POINT		0x0f
+#define DPTX_FORCE_LANES			0x10
+#define DPTX_HPD_STATE				0x11
+
+#define DPTX_EVENT_ENABLE_HPD			BIT(0)
+#define DPTX_EVENT_ENABLE_TRAINING		BIT(1)
+
+#define LINK_TRAINING_NOT_ACTIVE		0
+#define LINK_TRAINING_RUN			1
+#define LINK_TRAINING_RESTART			2
+
+#define CONTROL_VIDEO_IDLE			0
+#define CONTROL_VIDEO_VALID			1
+
+#define VIF_BYPASS_INTERLACE			BIT(13)
+#define INTERLACE_FMT_DET			BIT(12)
+#define INTERLACE_DTCT_WIN			0x20
+
+#define DP_FRAMER_SP_INTERLACE_EN		BIT(2)
+#define DP_FRAMER_SP_HSP			BIT(1)
+#define DP_FRAMER_SP_VSP			BIT(0)
+
+/* capability */
+#define AUX_HOST_INVERT				3
+#define	FAST_LT_SUPPORT				1
+#define FAST_LT_NOT_SUPPORT			0
+#define LANE_MAPPING_NORMAL			0xe4
+#define LANE_MAPPING_FLIPPED			0x1b
+#define ENHANCED				1
+
+#define	FULL_LT_STARTED				BIT(0)
+#define FASE_LT_STARTED				BIT(1)
+#define CLK_RECOVERY_FINISHED			BIT(2)
+#define EQ_PHASE_FINISHED			BIT(3)
+#define FASE_LT_START_FINISHED			BIT(4)
+#define CLK_RECOVERY_FAILED			BIT(5)
+#define EQ_PHASE_FAILED				BIT(6)
+#define FASE_LT_FAILED				BIT(7)
+
+#define DPTX_HPD_EVENT				BIT(0)
+#define DPTX_TRAINING_EVENT			BIT(1)
+#define HDCP_TX_STATUS_EVENT			BIT(4)
+#define HDCP2_TX_IS_KM_STORED_EVENT		BIT(5)
+#define HDCP2_TX_STORE_KM_EVENT			BIT(6)
+#define HDCP_TX_IS_RECEIVER_ID_VALID_EVENT	BIT(7)
+
+#define EDID_LENGTH_BYTE			0
+#define EDID_SEGMENT_BUMBER			1
+#define EDID_DATA				2
+#define EDID_BLOCK_SIZE				128
+
+#define TU_SIZE					64
+
+/* audio */
+#define AUDIO_PACK_EN(x)			(x << 8)
+#define SAMPLING_FREQ(x)			(x << 16)
+#define ORIGINAL_SAMP_FREQ(x)			(x << 24)
+#define SYNC_WR_TO_CH_ZERO			BIT(1)
+
+enum voltage_swing_level {
+	VOLTAGE_LEVEL_0,
+	VOLTAGE_LEVEL_1,
+	VOLTAGE_LEVEL_2,
+	VOLTAGE_LEVEL_3,
+};
+
+enum pre_emphasis_level {
+	PRE_EMPHASIS_LEVEL_0,
+	PRE_EMPHASIS_LEVEL_1,
+	PRE_EMPHASIS_LEVEL_2,
+	PRE_EMPHASIS_LEVEL_3,
+};
+
+enum pattern_set {
+	PRBS7		= BIT(0),
+	D10_2		= BIT(1),
+	TRAINING_PTN1	= BIT(2),
+	TRAINING_PTN2	= BIT(3),
+	DP_NONE		= BIT(4)
+};
+
+enum VIC_PXL_ENCODING_FORMAT {
+	PXL_RGB = 0x1,
+	YCBCR_4_4_4 = 0x2,
+	YCBCR_4_2_2 = 0x4,
+	YCBCR_4_2_0 = 0x8,
+	Y_ONLY = 0x10,
+};
+
+enum VIC_COLOR_DEPTH {
+	BCS_6 = 0x1,
+	BCS_8 = 0x2,
+	BCS_10 = 0x4,
+	BCS_12 = 0x8,
+	BCS_16 = 0x10,
+};
+
+#endif /* _CDN_DP_REG_H */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index edd7ec2..623d9e3 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -969,7 +969,10 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
 		vop_dsp_hold_valid_irq_disable(vop);
 	}
 
-	pin_pol = 0x8;
+	if (s->output_type != DRM_MODE_CONNECTOR_DisplayPort)
+		pin_pol = 0x8;
+	else
+		pin_pol = 0;
 	pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
 	pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
 	VOP_CTRL_SET(vop, pin_pol, pin_pol);
@@ -991,6 +994,10 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
 		VOP_CTRL_SET(vop, mipi_pin_pol, pin_pol);
 		VOP_CTRL_SET(vop, mipi_en, 1);
 		break;
+	case DRM_MODE_CONNECTOR_DisplayPort:
+		VOP_CTRL_SET(vop, dp_pin_pol, pin_pol);
+		VOP_CTRL_SET(vop, dp_en, 1);
+		break;
 	default:
 		DRM_ERROR("unsupport connector_type[%d]\n", s->output_type);
 	}
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index ff4f52e..50a045c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -45,6 +45,7 @@ struct vop_ctrl {
 	struct vop_reg edp_en;
 	struct vop_reg hdmi_en;
 	struct vop_reg mipi_en;
+	struct vop_reg dp_en;
 	struct vop_reg out_mode;
 	struct vop_reg dither_down;
 	struct vop_reg dither_up;
@@ -53,6 +54,7 @@ struct vop_ctrl {
 	struct vop_reg hdmi_pin_pol;
 	struct vop_reg edp_pin_pol;
 	struct vop_reg mipi_pin_pol;
+	struct vop_reg dp_pin_pol;
 
 	struct vop_reg htotal_pw;
 	struct vop_reg hact_st_end;
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index 5b1ae1f..dcf172e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -281,6 +281,7 @@ static const struct vop_data rk3288_vop = {
 static const struct vop_ctrl rk3399_ctrl_data = {
 	.standby = VOP_REG(RK3399_SYS_CTRL, 0x1, 22),
 	.gate_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 23),
+	.dp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 11),
 	.rgb_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 12),
 	.hdmi_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 13),
 	.edp_en = VOP_REG(RK3399_SYS_CTRL, 0x1, 14),
@@ -290,6 +291,7 @@ static const struct vop_ctrl rk3399_ctrl_data = {
 	.data_blank = VOP_REG(RK3399_DSP_CTRL0, 0x1, 19),
 	.out_mode = VOP_REG(RK3399_DSP_CTRL0, 0xf, 0),
 	.rgb_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16),
+	.dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16),
 	.hdmi_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 20),
 	.edp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 24),
 	.mipi_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 28),
diff --git a/include/sound/cdn-dp-audio.h b/include/sound/cdn-dp-audio.h
new file mode 100644
index 0000000..8c6e55c
--- /dev/null
+++ b/include/sound/cdn-dp-audio.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __CDN_DP_AUDIO_H__
+#define __CDN_DP_AUDIO_H__
+
+#include <linux/platform_device.h>
+
+#define AUDIO_TYPE_I2S			0
+#define AUDIO_TYPE_SPIDIF_INTERNAL	1
+#define AUDIO_TYPE_SPIDIF_EXTERNAL	2
+
+enum AUDIO_TYPE {
+	TYPE_I2S = 0,
+	TYPE_SPDIF = 1,
+};
+
+struct audio_info {
+	enum AUDIO_TYPE type;
+	int freq;
+	int channels;
+	int word_length;
+};
+
+struct cdn_dp_audio_ops {
+	int (*audio_startup)(void *dp_dev, struct audio_info *audio);
+	int (*audio_shutdown)(void *dp_dev, struct audio_info *audio);
+	int (*audio_start)(void *dp_dev, struct audio_info *audio);
+	int (*audio_stop)(void *dp_dev, struct audio_info *audio);
+	int (*audio_config)(void *dp_dev, struct audio_info *audio);
+};
+
+/* DP audio initalization data */
+struct cdn_dp_audio_pdata {
+	struct device *dev;
+	const struct cdn_dp_audio_ops *ops;
+	void *data;
+};
+
+#endif /* __CDN_DP_AUDIO_H__ */
-- 
2.6.3



From zyw at rock-chips.com  Fri May 27 03:45:42 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Fri, 27 May 2016 18:45:42 +0800
Subject: [RESEND PATCH 6/6] ASoC: rockchip: Add machine driver for cdn dp codec
In-Reply-To: <1464345942-4795-1-git-send-email-zyw@rock-chips.com>
References: <1464345942-4795-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1464345942-4795-7-git-send-email-zyw@rock-chips.com>

The driver is used for cdn dp codec embedded in rk3399

Signed-off-by: Chris Zhong <zyw at rock-chips.com>

---

 .../bindings/sound/rockchip-cdn-dp-audio.txt       |  12 ++
 sound/soc/rockchip/Kconfig                         |   9 ++
 sound/soc/rockchip/Makefile                        |   2 +
 sound/soc/rockchip/rockchip-cdn-dp-audio.c         | 167 +++++++++++++++++++++
 4 files changed, 190 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip-cdn-dp-audio.txt
 create mode 100644 sound/soc/rockchip/rockchip-cdn-dp-audio.c

diff --git a/Documentation/devicetree/bindings/sound/rockchip-cdn-dp-audio.txt b/Documentation/devicetree/bindings/sound/rockchip-cdn-dp-audio.txt
new file mode 100644
index 0000000..b7b0898
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip-cdn-dp-audio.txt
@@ -0,0 +1,12 @@
+Rockchip cdn dp audio bindings
+
+Required properties:
+- compatible: platform specific, must be "rockchip,cdn-dp-audio"
+- i2s-controller: the device of i2s controller
+
+Example:
+
+	cdn_dp_audio: cdn-dp_audio {
+		compatible = "rockchip,cdn-dp-audio";
+		i2s-controller = <&i2s2>;
+	};
diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index f1e0c70..7e7d905 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -15,6 +15,15 @@ config SND_SOC_ROCKCHIP_I2S
 	  Rockchip I2S device. The device supports upto maximum of
 	  8 channels each for play and record.
 
+config SND_SOC_ROCKCHIP_CDN_DP_AUDIO
+	tristate "cdn DP audio support"
+	depends on ROCKCHIP_CDN_DP
+	select SND_SOC_ROCKCHIP_I2S
+	select SND_SOC_CDN_DP_AUDIO
+	help
+	  Say Y or M here if you want to add support for SoC audio on Rockchip
+	  boards using the cdn dp codec, such as RK3399.
+
 config SND_SOC_ROCKCHIP_SPDIF
 	tristate "Rockchip SPDIF Device Driver"
 	depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
index c0bf560..9367f55 100644
--- a/sound/soc/rockchip/Makefile
+++ b/sound/soc/rockchip/Makefile
@@ -5,8 +5,10 @@ snd-soc-rockchip-spdif-objs := rockchip_spdif.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-rockchip-i2s.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o
 
+snd-soc-rockchip-cdn-dp-objs := rockchip-cdn-dp-audio.o
 snd-soc-rockchip-max98090-objs := rockchip_max98090.o
 snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o
 
+obj-$(CONFIG_SND_SOC_ROCKCHIP_CDN_DP_AUDIO) += snd-soc-rockchip-cdn-dp.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o
 obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o
diff --git a/sound/soc/rockchip/rockchip-cdn-dp-audio.c b/sound/soc/rockchip/rockchip-cdn-dp-audio.c
new file mode 100644
index 0000000..2bf6649
--- /dev/null
+++ b/sound/soc/rockchip/rockchip-cdn-dp-audio.c
@@ -0,0 +1,167 @@
+/*
+ * rockchip-cdn-dp-card.c
+ *
+ * ROCKCHIP ALSA SoC DAI driver for cdn dp audio on rockchip processors.
+ *
+ * Copyright (C) 2016 Chris Zhong <zyw at rock-chips.com>
+ * Copyright (C) 2016 ROCKCHIP, Inc.
+ *
+ * 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.
+ *
+ * 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/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-cdn-dp-audio"
+
+static int cdn_dp_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_fmt(cpu_dai, dai_fmt);
+	if (ret < 0) {
+		dev_err(cpu_dai->dev, "failed to set cpu_dai fmt.\n");
+		return ret;
+	}
+
+	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 cdn_dp_dai_ops = {
+	.hw_params = cdn_dp_audio_hw_params,
+};
+
+static struct snd_soc_dai_link cdn_dp_dai = {
+	.name = "cdn_dp",
+	.stream_name = "cdn_dp",
+	.codec_name = "cdn-dp-audio",
+	.codec_dai_name = "cdn-dp-hifi",
+	.ops = &cdn_dp_dai_ops,
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBS_CFS,
+};
+
+static struct snd_soc_card cdn_dp_audio_card = {
+	.name = "cdn_dp",
+	.owner = THIS_MODULE,
+	.dai_link = &cdn_dp_dai,
+	.num_links = 1,
+};
+
+static int cdn_dp_audio_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &cdn_dp_audio_card;
+	struct device_node *np = pdev->dev.of_node;
+	int ret;
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+
+	cdn_dp_dai.cpu_of_node = of_parse_phandle(np, "i2s-controller", 0);
+	if (!cdn_dp_dai.cpu_of_node) {
+		dev_err(&pdev->dev, "Property 'i2s-controller' missing !\n");
+		goto free_priv_data;
+	}
+
+	cdn_dp_dai.platform_of_node = cdn_dp_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;
+		goto free_cpu_of_node;
+	}
+
+	dev_info(&pdev->dev, "rockchip cdn dp audio init success.\n");
+
+	return 0;
+
+free_cpu_of_node:
+	cdn_dp_dai.cpu_of_node = NULL;
+	cdn_dp_dai.platform_of_node = NULL;
+free_priv_data:
+	snd_soc_card_set_drvdata(card, NULL);
+	platform_set_drvdata(pdev, NULL);
+	card->dev = NULL;
+
+	return ret;
+}
+
+static int cdn_dp_audio_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+	snd_soc_card_set_drvdata(card, NULL);
+	platform_set_drvdata(pdev, NULL);
+	card->dev = NULL;
+
+	return 0;
+}
+
+static const struct of_device_id cdn_dp_audio_of_match[] = {
+	{ .compatible = "rockchip,cdn-dp-audio", },
+	{},
+};
+
+static struct platform_driver cdn_dp_audio_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+		.of_match_table = cdn_dp_audio_of_match,
+	},
+	.probe = cdn_dp_audio_probe,
+	.remove = cdn_dp_audio_remove,
+};
+module_platform_driver(cdn_dp_audio_driver);
+
+MODULE_AUTHOR("Chris Zhong <zyw at rock-chips.com>");
+MODULE_DESCRIPTION("CDN DP Audio ASoC Interface");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, cdn_dp_audio_of_match);
-- 
2.6.3



From arnd at arndb.de  Fri May 27 03:49:11 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 27 May 2016 12:49:11 +0200
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160527093052.GB7865@e104818-lin.cambridge.arm.com>
References: <6293194.tGy03QJ9ME@wuerfel> <13240365.okADkKsTBJ@wuerfel>
 <20160527093052.GB7865@e104818-lin.cambridge.arm.com>
Message-ID: <5422652.7gdoDlB8u0@wuerfel>

On Friday, May 27, 2016 10:30:52 AM CEST Catalin Marinas wrote:
> On Fri, May 27, 2016 at 10:42:59AM +0200, Arnd Bergmann wrote:
> > On Friday, May 27, 2016 8:03:57 AM CEST Heiko Carstens wrote:
> > > > > > > Cost wise, this seems like it all cancels out in the end, but what
> > > > > > > do I know?
> > > > > > 
> > > > > > I think you know something, and I also think Heiko and other s390 guys
> > > > > > know something as well. So I'd like to listen their arguments here.
> > > 
> > > If it comes to 64 bit arguments for compat system calls: s390 also has an
> > > x32-like ABI extension which allows user space to use full 64 bit
> > > registers. As far as I know hardly anybody ever made use of that.
> > > 
> > > However even if that would be widely used, to me it wouldn't make sense to
> > > add new compat system calls which allow 64 bit arguments, simply because
> > > something like
> > > 
> > > c = (u32)a | (u64)b << 32;
> > > 
> > > can be done with a single 1-cycle instruction. It's just not worth the
> > > extra effort to maintain additional system call variants.
> > 
> > For reference, both tile and mips also have separate 32-bit ABIs that are
> > only used on 64-bit kernels (aside from the normal 32-bit ABI). Tile
> > does it like s390 and passes 64-bit arguments as pairs, while MIPS
> > and x86 and pass them as single registers.
> 
> AFAIK, x32 also requires that the upper half of a 64-bit reg is zeroed
> by the user when a 32-bit value is passed. We could require the same on
> AArch64/ILP32 but I'm a bit uneasy on trusting a multitude of C
> libraries on this.

It's not about trusting a C library, it's about ensuring malicious code
cannot pass argumentst that the kernel code assumes will never happen.

	Arnd


From lorenzo.pieralisi at arm.com  Fri May 27 03:52:38 2016
From: lorenzo.pieralisi at arm.com (Lorenzo Pieralisi)
Date: Fri, 27 May 2016 11:52:38 +0100
Subject: [PATCH] PCI/MSI: pci-xgene-msi: Enable MSI support in ACPI boot
 for X-Gene v1
In-Reply-To: <CADaLNDnf8SRbUkBN9fZMvrvsnTQs+DLyqnZfVpWqVyyY8Hk=1Q@mail.gmail.com>
References: <1455069384-22323-1-git-send-email-dhdang@apm.com>
 <1456330151.5681.46.camel@redhat.com> <56CDD767.6020103@arm.com>
 <CADaLND=mrkxOWOzcEb8os16Rb=SDHfnn_8eSgB4bQYH3UguS3w@mail.gmail.com>
 <20160225173822.GA6349@red-moon>
 <CADaLNDnywVPER9QhmK4C6JyCLhta_M_cVSOuSkEHnmnLPFo3JA@mail.gmail.com>
 <20160526123459.GA23794@red-moon>
 <CADaLNDnf8SRbUkBN9fZMvrvsnTQs+DLyqnZfVpWqVyyY8Hk=1Q@mail.gmail.com>
Message-ID: <20160527105238.GA25842@red-moon>

[+ Rafael]

On Thu, May 26, 2016 at 01:49:23PM -0700, Duc Dang wrote:
> Hi Lorenzo,
> 
> On Thu, May 26, 2016 at 5:34 AM, Lorenzo Pieralisi
> <lorenzo.pieralisi at arm.com> wrote:
> > Hi Duc,
> >
> > On Wed, May 25, 2016 at 04:13:35PM -0700, Duc Dang wrote:
> >> On Thu, Feb 25, 2016 at 9:38 AM, Lorenzo Pieralisi
> >> <lorenzo.pieralisi at arm.com> wrote:
> >> > On Wed, Feb 24, 2016 at 02:28:10PM -0800, Duc Dang wrote:
> >> >> On Wed, Feb 24, 2016 at 8:16 AM, Marc Zyngier <marc.zyngier at arm.com> wrote:
> >> >> > On 24/02/16 16:09, Mark Salter wrote:
> >> >> >> On Tue, 2016-02-09 at 17:56 -0800, Duc Dang wrote:
> >> >> >>> This patch makes pci-xgene-msi driver ACPI-aware and provides
> >> >> >>> MSI capability for X-Gene v1 PCIe controllers in ACPI boot mode.
> >> >> >>>
> >> >> >>> Signed-off-by: Duc Dang <dhdang at apm.com>
> >> >> >>> ---
> >> >> >>>  drivers/pci/host/pci-xgene-msi.c | 35 ++++++++++++++++++++++++++++++++---
> >> >> >>>  1 file changed, 32 insertions(+), 3 deletions(-)
> >> >> >>>
> >> >> >>> diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c
> >> >> >>> index a6456b5..466aa93 100644
> >> >> >>> --- a/drivers/pci/host/pci-xgene-msi.c
> >> >> >>> +++ b/drivers/pci/host/pci-xgene-msi.c
> >> >> >>> @@ -24,6 +24,7 @@
> >> >> >>>  #include <linux/pci.h>
> >> >> >>>  #include <linux/platform_device.h>
> >> >> >>>  #include <linux/of_pci.h>
> >> >> >>> +#include <linux/acpi.h>
> >> >> >>>
> >> >> >>>  #define MSI_IR0                     0x000000
> >> >> >>>  #define MSI_INT0            0x800000
> >> >> >>> @@ -39,7 +40,7 @@ struct xgene_msi_group {
> >> >> >>>  };
> >> >> >>>
> >> >> >>>  struct xgene_msi {
> >> >> >>> -    struct device_node      *node;
> >> >> >>> +    struct fwnode_handle    *fwnode;
> >> >> >>>      struct irq_domain       *inner_domain;
> >> >> >>>      struct irq_domain       *msi_domain;
> >> >> >>>      u64                     msi_addr;
> >> >> >>> @@ -249,6 +250,13 @@ static const struct irq_domain_ops msi_domain_ops = {
> >> >> >>>      .free   = xgene_irq_domain_free,
> >> >> >>>  };
> >> >> >>>
> >> >> >>> +#ifdef CONFIG_ACPI
> >> >> >>> +static struct fwnode_handle *xgene_msi_get_fwnode(struct device *dev)
> >> >> >>> +{
> >> >> >>> +    return xgene_msi_ctrl.fwnode;
> >> >> >>> +}
> >> >> >>> +#endif
> >> >> >>> +
> >> >> >>>  static int xgene_allocate_domains(struct xgene_msi *msi)
> >> >> >>>  {
> >> >> >>>      msi->inner_domain = irq_domain_add_linear(NULL, NR_MSI_VEC,
> >> >> >>> @@ -256,7 +264,7 @@ static int xgene_allocate_domains(struct xgene_msi *msi)
> >> >> >>>      if (!msi->inner_domain)
> >> >> >>>              return -ENOMEM;
> >> >> >>>
> >> >> >>> -    msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(msi->node),
> >> >> >>> +    msi->msi_domain = pci_msi_create_irq_domain(msi->fwnode,
> >> >> >>>                                                  &xgene_msi_domain_info,
> >> >> >>>                                                  msi->inner_domain);
> >> >> >>
> >> >> >> This doesn't work for me (ACPI probing on Mustang) unless I change this
> >> >> >> to be pci_msi_create_default_irq_domain(). The problem seems to be that
> >> >> >> the MSI probe happens after the PCIe RC is probed so there is no MSI domain
> >> >> >> at the time the PCIe root is initialized by ACPI.
> >> >> >
> >> >> > pci_msi_create_default_irq_domain is the wrong thing do use, specially
> >> >> > if you have multiple MSI controllers in the system. I certainly wouldn't
> >> >> > want to see it being used on arm64.
> >> >> >
> >> >> > This is the usual dependency hell. You try moving the probing earlier,
> >> >> > but that may break something else in the process.
> >> >>
> >> >> Hi Mark and Marc,
> >> >>
> >> >> I have modified Tianocore firmware to have MSI node declared before
> >> >> PCIe node in Dsdt table. With this modification, the MSI driver will
> >> >> be loaded before PCIe driver and MSI domain is available at the time
> >> >> PCIe root is initialized.
> >> >
> >> > I am totally against this. We should not hack ACPI tables to make
> >> > the kernel work (on top of that with unwritten ordering rules that may
> >> > well require changes as kernel evolves), we should have a standard set
> >> > of bindings that people use to describe HW in the DSDT and the kernel(s)
> >> > has to cope with that. If there is a dependency problem in the description
> >> > we may solve it at bindings level, but I absolutely do not want to rely
> >> > on DSDT nodes ordering for things to work, that's fragile, no shortcuts
> >> > please.
> >>
> >> Hi Lorenzo, Bjorn,
> >>
> >> (Refresh this thread on this merge cycle)
> >>
> >> I tried to use _DEP method to describe the dependency of PCIe node to
> >> MSI node but it turns out that PCIe driver does not check for the
> >> dependency (only EC (ec.c) and I2C core (i2c-core.c) use
> >> acpi_walk_dep_device_list to check for dependency before loading
> >> dependent drivers)
> >>
> >> Do you have other suggestion/example about how to ensure strict
> >> ordering on driver loading in ACPI boot mode without changing the
> >> order of ACPI nodes in DSDT?
> >
> > Before doing anything else, I would like to ask you to report the code
> > paths leading to failures (what fails actually ?) please, and I want
> > to understand what "this does not work" means.
> >
> > In particular:
> >
> > - Why using pci_msi_create_default_irq_domain() works
> > - Why, if you change the DSDT nodes ordering, things work (please add
> >   some debugging to MSI allocation functions to detect the code paths
> >   leading to correct MSI allocation)
> > - What's the difference wrt the DT probe path
> 
> The MSI allocation happens with following code path (I use PMC pm80xx
> SAS driver as an example (drivers/scsi/pm8001/pm8001_init.c)):
> pci_enable_msix_exact
>     pci_enable_msix_range
>         pci_enable_msix
>             msix_capbility_init
>                 pci_msi_setup_msi_irqs
>                     pci_msi_get_domain
>                         dev_get_msi_domain
>                         arch_get_pci_msi_domain
>                             return pci_msi_default_domain;
> 
> In my failing case: pci_msi_get_domain return NULL, so MSI allocation
> function (pci_enable_msix_exact) fails.
> 
> The expected MSI domain is registered when X-Gene MSI driver is
> initialized and is attached to each PCI bus by calling
> pci_set_bus_msi_domain during PCIe bus-scan:
> pci_scan_root_bus
>     pci_scan_root_bus_msi
>         pci_scan_child_bus
>             pci_scan_bridge
>                 pci_add_new_bus
>                     pci_alloc_child_bus
>                         pci_set_bus_msi_domain
>                             pci_host_bridge_msi_domain
>                                 pci_host_bridge_of_msi_domain
>                                 pci_host_bridge_acpi_msi_domain
> 
> + When booting with DT: X-Gene MSI driver is initialized early
> (subsys_initcall level); X-Gene PCIe driver is initialized later at
> device_initcall level (using module_platform_driver). Because of that
> when PCIe enumeration happens, the X-Gene MSI domain was already
> registered and available. So when the driver of PCIe Endpoint devices
> gets loaded, the call to pci_enable_msix_exact (to allocate MSI)
> succeeds.
> 
> + When booting with ACPI: acpi_scan_init is called at subsys_initcall
> level (the same level with X-Gene MSI driver):
> acpi_init
>     acpi_bus_init (GIC is initialized here)
>         acpi_scan_init
>             acpi_pci_root_init
>             acpi_pci_link_init
>             ...
>             acpi_bus_scan
>                 acpi_bus_check_add
>  ...
> 
> Currently, in DSDT table, X-Gene MSI node is defined right after
> X-Gene PCIe nodes. So PCIe driver initialization and PCIe enumeration
> happens before MSI driver is initialized. During PCIe bus scan, the
> pci_set_bus_msi_domain gets a NULL  irq_domain value from
> pci_host_bridge_msi_domain (as MSI driver is not initialized), so
> there is no MSI support for PCIe bus.
> 
> + Using pci_msi_create_default_irq_domain() helps MSI allocation
> succeed as pci_msi_get_domain (in the code path of
> pci_enable_msix_exact above) can fall back to get a valid domain from
> arch_get_pci_msi_domain (please note that PCIe endpoint driver gets
> called later (at device_initcall level (using module_init)), so at the
> time PCIe endpoint driver probe function executes, the MSI driver
> already register the global MSI domain with
> pci_msi_create_default_irq_domain)
> 
> + If changing DSDT node ordering, to define MSI node before PCIe
> nodes, then X-Gene MSI driver will be loaded before PCIe host driver.
> At the time PCIe enumeration happens, X-Gene MSI driver already
> registered a valid MSI domain (by calling
> pci_msi_register_fwnode_provider to register the fwnode provider
> function), so all the detected PCIe buses (and PCIe endpoint devices)
> will have a valid MSI domain attached to them (as a result of function
> pci_set_bus_msi_domain)

This still works out of sheer luck, given that relying on initcall
ordering at same init level is undefined (ie it works if your msi driver
registration call is executed before acpi_init() is called).

I though about using a scan handler like:

See arch/ia64/hp/common/sba_iommu.c acpi_sba_ioc_handler

but that won't solve your problem either since, given that PNP0A03 (ie
PCI host bridge) is handled through a scan handler too, IIUC you will
still have issues related to namespace device nodes ordering.

I suspect we will have to add a hook walking the ACPI namespace before
acpi_bus_scan() is called in acpi_scan_init() (aka MSI controllers must
be probed before any other device is, that's the gist), I CC'ed Rafael
to see if there is any other suitable way to sort out this issue.

Thanks,
Lorenzo


From aryabinin at virtuozzo.com  Fri May 27 04:02:08 2016
From: aryabinin at virtuozzo.com (Andrey Ryabinin)
Date: Fri, 27 May 2016 14:02:08 +0300
Subject: [PATCH] arm64: kasan: instrument user memory access API
In-Reply-To: <1464288231-11304-1-git-send-email-yang.shi@linaro.org>
References: <1464288231-11304-1-git-send-email-yang.shi@linaro.org>
Message-ID: <57482930.6020608@virtuozzo.com>



On 05/26/2016 09:43 PM, Yang Shi wrote:
> The upstream commit 1771c6e1a567ea0ba2cccc0a4ffe68a1419fd8ef
> ("x86/kasan: instrument user memory access API") added KASAN instrument to
> x86 user memory access API, so added such instrument to ARM64 too.
> 
> Tested by test_kasan module.
> 
> Signed-off-by: Yang Shi <yang.shi at linaro.org>
> ---
>  arch/arm64/include/asm/uaccess.h | 18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)

Please, cover __copy_from_user() and __copy_to_user() too.
Unlike x86, your patch doesn't instrument these two.



From panand at redhat.com  Fri May 27 04:27:08 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 16:57:08 +0530
Subject: [PATCH kexec-tools 17/32] arm: return proper error for missing
 crash kernel
In-Reply-To: <E1axXTL-0004ib-Ho@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXTL-0004ib-Ho@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GuptCq67COZdXN=5QPghXgchpHFgbao0RhNGKobrehvMwQ@mail.gmail.com>

On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Return the proper error code (ENOCRASHKERNEL) for a missing crash
> kernel region in /proc/iomem, so the error handling in kexec.c can
> print the appropriate message.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/kexec-zImage-arm.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kexec/arch/arm/kexec-zImage-arm.c b/kexec/arch/arm/kexec-zImage-arm.c
> index d85ab9b..4755f06 100644
> --- a/kexec/arch/arm/kexec-zImage-arm.c
> +++ b/kexec/arch/arm/kexec-zImage-arm.c
> @@ -451,7 +451,7 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
>                          * No crash kernel memory reserved. We cannot do more
>                          * but just bail out.
>                          */
> -                       return -1;
> +                       return ENOCRASHKERNEL;
>                 }
>                 base = start;
>         } else {
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:27:47 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 16:57:47 +0530
Subject: [PATCH kexec-tools 18/32] arm: report if crash kernel is out of
 bounds
In-Reply-To: <E1axXTQ-0004ih-NN@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXTQ-0004ih-NN@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_Guo-N0Coxj=fHBBM=QULMo6QK3uKbzOh15R6FCihGERjMA@mail.gmail.com>

On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Report an error if the crash kernel memory region is outside of the
> boot-view memory range - this can happen with systems such as
> Keystone 2.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>
> ---
>  kexec/arch/arm/crashdump-arm.c | 11 +++++++++++
>  kexec/arch/arm/crashdump-arm.h |  1 +
>  2 files changed, 12 insertions(+)
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index fcc4d42..739c906 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -365,6 +365,17 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
>         if (get_kernel_page_offset(info, &elf_info))
>                 return -1;
>
> +       /*
> +        * Ensure that the crash kernel memory range is sane. The crash kernel
> +        * must be located within memory which is visible during booting.
> +        */
> +       if (crash_reserved_mem.end > ARM_MAX_VIRTUAL) {
> +               fprintf(stderr,
> +                       "Crash kernel memory [0x%llx-0x%llx] is inaccessible at boot - unable to load crash kernel\n",
> +                       crash_reserved_mem.start, crash_reserved_mem.end);
> +               return -1;
> +       }
> +
>         last_ranges = usablemem_rgns.size - 1;
>         if (last_ranges < 0)
>                 last_ranges = 0;
> diff --git a/kexec/arch/arm/crashdump-arm.h b/kexec/arch/arm/crashdump-arm.h
> index 2dbde04..7314960 100644
> --- a/kexec/arch/arm/crashdump-arm.h
> +++ b/kexec/arch/arm/crashdump-arm.h
> @@ -9,6 +9,7 @@ extern "C" {
>  #define DEFAULT_PAGE_OFFSET            (0xc0000000)
>  #define KVBASE_MASK    (0x1ffffff)
>  #define CRASH_MAX_MEMORY_RANGES        32
> +#define ARM_MAX_VIRTUAL                UINT32_MAX

If I see a kernel code then a virtual address is always defined as
unsigned long. So, shouldn't we use ULONG_MAX instead?

>
>
>  extern struct memory_ranges usablemem_rgns;
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:28:36 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 16:58:36 +0530
Subject: [PATCH kexec-tools 19/32] arm: add memory ranges debug
In-Reply-To: <E1axXTV-0004in-Sw@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXTV-0004in-Sw@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GuqhPgA37LoWn48Oj6vNgQP=enCNUUp-bF1sgk8uHvc-pg@mail.gmail.com>

On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Add the call to dbgprint_mem_range() into the ARM version of
> get_memory_ranges().
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/kexec-arm.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/kexec/arch/arm/kexec-arm.c b/kexec/arch/arm/kexec-arm.c
> index e47fc00..eeb27b4 100644
> --- a/kexec/arch/arm/kexec-arm.c
> +++ b/kexec/arch/arm/kexec-arm.c
> @@ -70,6 +70,9 @@ int get_memory_ranges(struct memory_range **range, int *ranges,
>         fclose(fp);
>         *range = memory_range;
>         *ranges = memory_ranges;
> +
> +       dbgprint_mem_range("MEMORY RANGES", *range, *ranges);
> +
>         return 0;
>  }
>
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:29:08 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 16:59:08 +0530
Subject: [PATCH kexec-tools 20/32] arm: add maximum number of memory ranges
In-Reply-To: <E1axXTb-0004it-43@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXTb-0004it-43@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GuqshsyCJag7XjQVgufkPosEZzBPEhLuiGRYzcW9C++pXw@mail.gmail.com>

On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Add the maximum number of memory ranges to the list of usable memory
> ranges, so that we don't have to carry this around.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/crashdump-arm.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index 739c906..195b43f 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -46,8 +46,8 @@
>   */
>  static struct memory_range crash_memory_ranges[CRASH_MAX_MEMORY_RANGES];
>  struct memory_ranges usablemem_rgns = {
> -    .size = 0,
> -    .ranges = crash_memory_ranges,
> +       .max_size = CRASH_MAX_MEMORY_RANGES,
> +       .ranges = crash_memory_ranges,
>  };
>
>  /* memory range reserved for crashkernel */
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:30:36 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:00:36 +0530
Subject: [PATCH kexec-tools 21/32] arm: parse crash_reserved_mem early
In-Reply-To: <E1axXTg-0004iz-CQ@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXTg-0004iz-CQ@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GupGaahVrx7L9B36V_Ndepo=AstWgdPdcLEZdm-W=fGuYg@mail.gmail.com>

On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> We parse the crash kernel memory region in several locations in the
> kexec tools - once to check that there's a region, another time for
> real when we're locating the memory regions to dump, and another
> while loading the image.
>
> Move the real parsing step to is_crashkernel_mem_reserved(), which
> matches what x86 is doing.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/crashdump-arm.c | 47 +++++++++++++++++++++++++++++++-----------
>  kexec/arch/arm/iomem.h         |  7 +++++++
>  2 files changed, 42 insertions(+), 12 deletions(-)
>  create mode 100644 kexec/arch/arm/iomem.h
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index 195b43f..85afd9f 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -31,6 +31,7 @@
>  #include "../../kexec-elf.h"
>  #include "../../crashdump.h"
>  #include "crashdump-arm.h"
> +#include "iomem.h"
>
>  #if __BYTE_ORDER == __LITTLE_ENDIAN
>  #define ELFDATANATIVE ELFDATA2LSB
> @@ -139,9 +140,8 @@ static int get_kernel_page_offset(struct kexec_info *info,
>   * @length: size of the memory region
>   *
>   * This function is called once for each memory region found in /proc/iomem. It
> - * locates system RAM and crashkernel reserved memory and places these to
> - * variables: @crash_memory_ranges and @crash_reserved_mem. Number of memory
> - * regions is placed in @crash_memory_nr_ranges.
> + * locates system RAM and places these into @crash_memory_ranges. Number of
> + * memory regions is placed in @crash_memory_nr_ranges.
>   */
>  static int crash_range_callback(void *UNUSED(data), int UNUSED(nr),
>                                 char *str, unsigned long long base,
> @@ -159,10 +159,6 @@ static int crash_range_callback(void *UNUSED(data), int UNUSED(nr),
>                 range->end = base + length - 1;
>                 range->type = RANGE_RAM;
>                 usablemem_rgns.size++;
> -       } else if (strncmp(str, "Crash kernel\n", 13) == 0) {
> -               crash_reserved_mem.start = base;
> -               crash_reserved_mem.end = base + length - 1;
> -               crash_reserved_mem.type = RANGE_RAM;
>         }
>
>         return 0;
> @@ -424,12 +420,39 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
>         return 0;
>  }
>
> -int is_crashkernel_mem_reserved(void)
> +/**
> + * iomem_range_callback() - callback called for each iomem region
> + * @data: not used
> + * @nr: not used
> + * @str: name of the memory region (not NULL terminated)
> + * @base: start address of the memory region
> + * @length: size of the memory region
> + *
> + * This function is called for each memory range in /proc/iomem, and stores
> + * the location of the crash kernel range into @crash_reserved_mem.
> + */
> +static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
> +                               char *str, unsigned long long base,
> +                               unsigned long long length)
>  {
> -       uint64_t start, end;
> +       if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) {
> +               crash_reserved_mem.start = base;
> +               crash_reserved_mem.end = base + length - 1;
> +               crash_reserved_mem.type = RANGE_RAM;
> +       }
> +       return 0;
> +}
>
> -       if (parse_iomem_single("Crash kernel\n", &start, &end) == 0)
> -               return start != end;
> +/**
> + * is_crashkernel_mem_reserved() - check for the crashkernel reserved region
> + *
> + * Check for the crashkernel reserved region in /proc/iomem, and return
> + * true if it is present, or false otherwise. We use this to store the
> + * location of this region.
> + */
> +int is_crashkernel_mem_reserved(void)
> +{
> +       kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL);
>
> -       return 0;
> +       return crash_reserved_mem.start != crash_reserved_mem.end;
>  }
> diff --git a/kexec/arch/arm/iomem.h b/kexec/arch/arm/iomem.h
> new file mode 100644
> index 0000000..81c593d
> --- /dev/null
> +++ b/kexec/arch/arm/iomem.h
> @@ -0,0 +1,7 @@
> +#ifndef IOMEM_H
> +#define IOMEM_H
> +
> +#define SYSTEM_RAM             "System RAM\n"
> +#define CRASH_KERNEL           "Crash kernel\n"
> +
> +#endif
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:30:53 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:00:53 +0530
Subject: [PATCH kexec-tools 22/32] arm: use generic mem_region sorting
 implementation
In-Reply-To: <E1axXTl-0004j5-II@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXTl-0004j5-II@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GuowUMo62_AQ2g3FxSW8YZXa4wQgt6oSwJvm_RVtt0+PaQ@mail.gmail.com>

On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Use the generic mem_region sorting implementation.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/crashdump-arm.c | 16 +---------------
>  1 file changed, 1 insertion(+), 15 deletions(-)
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index 85afd9f..d6db566 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -202,19 +202,6 @@ static void crash_exclude_range(void)
>         }
>  }
>
> -static int range_cmp(const void *a1, const void *a2)
> -{
> -       const struct memory_range *r1 = a1;
> -       const struct memory_range *r2 = a2;
> -
> -       if (r1->start > r2->start)
> -               return 1;
> -       if (r1->start < r2->start)
> -               return -1;
> -
> -       return 0;
> -}
> -
>  /**
>   * crash_get_memory_ranges() - read system physical memory
>   *
> @@ -246,8 +233,7 @@ static int crash_get_memory_ranges(void)
>         /*
>          * Make sure that the memory regions are sorted.
>          */
> -       qsort(usablemem_rgns.ranges, usablemem_rgns.size,
> -             sizeof(*usablemem_rgns.ranges), range_cmp);
> +       mem_regions_sort(&usablemem_rgns);
>
>         return 0;
>  }
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:33:46 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:03:46 +0530
Subject: [PATCH kexec-tools 23/32] arm: move crash system RAM parsing
 earlier
In-Reply-To: <E1axXTq-0004jC-OH@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXTq-0004jC-OH@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GuqgsukrjzjuttWVHN=s6vUkynEGAyRp0o7SH8JS40kCaw@mail.gmail.com>

On Tue, May 3, 2016 at 3:53 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/Makefile        |  2 ++
>  kexec/arch/arm/crashdump-arm.c | 51 ++++++++----------------------------------
>  2 files changed, 11 insertions(+), 42 deletions(-)
>
> diff --git a/kexec/arch/arm/Makefile b/kexec/arch/arm/Makefile
> index 60e433a..71db8c3 100644
> --- a/kexec/arch/arm/Makefile
> +++ b/kexec/arch/arm/Makefile
> @@ -7,6 +7,8 @@ arm_FS2DT              = kexec/fs2dt.c
>  arm_FS2DT_INCLUDE      = -include $(srcdir)/kexec/arch/arm/crashdump-arm.h \
>                           -include $(srcdir)/kexec/arch/arm/kexec-arm.h
>
> +arm_MEM_REGIONS        = kexec/mem_regions.c
> +
>  arm_KEXEC_SRCS=  kexec/arch/arm/kexec-elf-rel-arm.c
>  arm_KEXEC_SRCS+= kexec/arch/arm/kexec-zImage-arm.c
>  arm_KEXEC_SRCS+= kexec/arch/arm/kexec-uImage-arm.c
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index d6db566..f2e6a0d 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -30,6 +30,7 @@
>  #include "../../kexec.h"
>  #include "../../kexec-elf.h"
>  #include "../../crashdump.h"
> +#include "../../mem_regions.h"
>  #include "crashdump-arm.h"
>  #include "iomem.h"
>
> @@ -132,39 +133,6 @@ static int get_kernel_page_offset(struct kexec_info *info,
>  }
>
>  /**
> - * crash_range_callback() - callback called for each iomem region
> - * @data: not used
> - * @nr: not used
> - * @str: name of the memory region
> - * @base: start address of the memory region
> - * @length: size of the memory region
> - *
> - * This function is called once for each memory region found in /proc/iomem. It
> - * locates system RAM and places these into @crash_memory_ranges. Number of
> - * memory regions is placed in @crash_memory_nr_ranges.
> - */
> -static int crash_range_callback(void *UNUSED(data), int UNUSED(nr),
> -                               char *str, unsigned long long base,
> -                               unsigned long long length)
> -{
> -       struct memory_range *range;
> -
> -       if (usablemem_rgns.size >= CRASH_MAX_MEMORY_RANGES)
> -               return 1;
> -
> -       range = usablemem_rgns.ranges + usablemem_rgns.size;
> -
> -       if (strncmp(str, "System RAM\n", 11) == 0) {
> -               range->start = base;
> -               range->end = base + length - 1;
> -               range->type = RANGE_RAM;
> -               usablemem_rgns.size++;
> -       }
> -
> -       return 0;
> -}
> -
> -/**
>   * crash_exclude_range() - excludes memory region reserved for crashkernel
>   *
>   * Function locates where crashkernel reserved memory is and removes that region
> @@ -213,12 +181,6 @@ static void crash_exclude_range(void)
>   */
>  static int crash_get_memory_ranges(void)
>  {
> -       /*
> -        * First read all memory regions that can be considered as
> -        * system memory including the crash area.
> -        */
> -       kexec_iomem_for_each_line(NULL, crash_range_callback, NULL);
> -
>         if (usablemem_rgns.size < 1) {
>                 errno = EINVAL;
>                 return -1;
> @@ -414,8 +376,9 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
>   * @base: start address of the memory region
>   * @length: size of the memory region
>   *
> - * This function is called for each memory range in /proc/iomem, and stores
> - * the location of the crash kernel range into @crash_reserved_mem.
> + * This function is called for each memory range in /proc/iomem, stores
> + * the location of the crash kernel range into @crash_reserved_mem, and
> + * stores the system RAM into @usablemem_rgns.
>   */
>  static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
>                                 char *str, unsigned long long base,
> @@ -426,6 +389,10 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
>                 crash_reserved_mem.end = base + length - 1;
>                 crash_reserved_mem.type = RANGE_RAM;
>         }
> +       else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) {
> +               return mem_regions_add(&usablemem_rgns,
> +                                      base, length, RANGE_RAM);
> +       }
>         return 0;
>  }
>
> @@ -434,7 +401,7 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
>   *
>   * Check for the crashkernel reserved region in /proc/iomem, and return
>   * true if it is present, or false otherwise. We use this to store the
> - * location of this region.
> + * location of this region, and system RAM regions.
>   */
>  int is_crashkernel_mem_reserved(void)
>  {
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:34:20 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:04:20 +0530
Subject: [PATCH kexec-tools 24/32] arm: add support for platforms with
 boot memory aliases
In-Reply-To: <E1axXTv-0004jI-UH@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXTv-0004jI-UH@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_Gurpw4QyE73THdM=TWft3xmwDTMJx0Q06rrCxKJwdg4gaw@mail.gmail.com>

On Tue, May 3, 2016 at 3:53 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> The kexec API deals with boot-view addresses, rather than normal system
> view addresses.  This causes problems for platforms such as Keystone 2,
> where the boot view is substantially different from the normal system
> view.
>
> This is because Keystone 2 boots from a memory alias in the lower 4GiB,
> before switching to a high alias at 32GiB.
>
> We handle this in a generic way by introducing boot alias resources in
> /proc/iomem:
>
> 80000000-dfffffff : System RAM (boot alias)
>   9f800000-9fffffff : Crash kernel (boot alias)
> 800000000-85fffffff : System RAM
>   800008000-800790e37 : Kernel code
>   8007ec000-8008b856f : Kernel data
>   81f800000-81fffffff : Crash kernel
>
> To allow kexec to load a kernel, we need to add the boot alias of RAM
> to the memory ranges returned by get_memory_ranges().  Parse the
> system RAM boot alias into the memory ranges.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/iomem.h     | 2 ++
>  kexec/arch/arm/kexec-arm.c | 4 +++-
>  2 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/kexec/arch/arm/iomem.h b/kexec/arch/arm/iomem.h
> index 81c593d..85f958e 100644
> --- a/kexec/arch/arm/iomem.h
> +++ b/kexec/arch/arm/iomem.h
> @@ -2,6 +2,8 @@
>  #define IOMEM_H
>
>  #define SYSTEM_RAM             "System RAM\n"
> +#define SYSTEM_RAM_BOOT                "System RAM (boot alias)\n"
>  #define CRASH_KERNEL           "Crash kernel\n"
> +#define CRASH_KERNEL_BOOT      "Crash kernel (boot alias)\n"
>
>  #endif
> diff --git a/kexec/arch/arm/kexec-arm.c b/kexec/arch/arm/kexec-arm.c
> index eeb27b4..2194b7c 100644
> --- a/kexec/arch/arm/kexec-arm.c
> +++ b/kexec/arch/arm/kexec-arm.c
> @@ -18,6 +18,7 @@
>  #include "kexec-arm.h"
>  #include <arch/options.h>
>  #include "../../fs2dt.h"
> +#include "iomem.h"
>
>  #define MAX_MEMORY_RANGES 64
>  #define MAX_LINE 160
> @@ -52,7 +53,8 @@ int get_memory_ranges(struct memory_range **range, int *ranges,
>                         continue;
>                 str = line + consumed;
>
> -               if (memcmp(str, "System RAM\n", 11) == 0) {
> +               if (memcmp(str, SYSTEM_RAM_BOOT, strlen(SYSTEM_RAM_BOOT)) == 0 ||
> +                   memcmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) {
>                         type = RANGE_RAM;
>                 }
>                 else if (memcmp(str, "reserved\n", 9) == 0) {
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:34:45 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:04:45 +0530
Subject: [PATCH kexec-tools 25/32] arm: crashdump needs boot alias of
 crash kernel region
In-Reply-To: <E1axXU1-0004jO-4q@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXU1-0004jO-4q@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GuqCmBOSQJeQZTCjy4edEe+p5LPvQAVF7gZY+Sc6uZFzuA@mail.gmail.com>

On Tue, May 3, 2016 at 3:53 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> When crashdumping, we need the boot memory alias of the crash kernel
> region rather than the system view.  Arrange to check for the boot
> alias of the crash kernel region first, and if found, use it instead
> of the main alias.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/kexec-zImage-arm.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/kexec/arch/arm/kexec-zImage-arm.c b/kexec/arch/arm/kexec-zImage-arm.c
> index 4755f06..fdd2910 100644
> --- a/kexec/arch/arm/kexec-zImage-arm.c
> +++ b/kexec/arch/arm/kexec-zImage-arm.c
> @@ -20,6 +20,7 @@
>  #include "kexec-arm.h"
>  #include "../../fs2dt.h"
>  #include "crashdump-arm.h"
> +#include "iomem.h"
>
>  #define BOOT_PARAMS_SIZE 1536
>
> @@ -446,7 +447,8 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
>                  * We put the dump capture kernel at the start of crashkernel
>                  * reserved memory.
>                  */
> -               if (parse_iomem_single("Crash kernel\n", &start, &end)) {
> +               if (parse_iomem_single(CRASH_KERNEL_BOOT, &start, &end) &&
> +                   parse_iomem_single(CRASH_KERNEL, &start, &end)) {
>                         /*
>                          * No crash kernel memory reserved. We cannot do more
>                          * but just bail out.
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:35:20 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:05:20 +0530
Subject: [PATCH kexec-tools 29/32] arm: add debug of reserved and coredump
 memory ranges
In-Reply-To: <E1axXUL-0004jm-W0@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXUL-0004jm-W0@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_Guqj8p07CM9mJTHDYDVC2s+6sLQn30JP8qBxOig8rV_RrQ@mail.gmail.com>

On Tue, May 3, 2016 at 3:53 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Add debug of the reserved and coredump memory ranges for validation.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/crashdump-arm.c | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index 25fdbe9..2dc8846 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -158,6 +158,10 @@ static int crash_get_memory_ranges(void)
>                 return -1;
>         }
>
> +       dbgprint_mem_range("Reserved memory ranges",
> +                          crash_reserved_rgns.ranges,
> +                          crash_reserved_rgns.size);
> +
>         /*
>          * Exclude all reserved memory from the usable memory regions.
>          * We want to avoid dumping the crashkernel region itself.  Note
> @@ -179,6 +183,9 @@ static int crash_get_memory_ranges(void)
>          */
>         mem_regions_sort(&usablemem_rgns);
>
> +       dbgprint_mem_range("Coredump memory ranges",
> +                          usablemem_rgns.ranges, usablemem_rgns.size);
> +
>         return 0;
>  }
>
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:36:15 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:06:15 +0530
Subject: [PATCH kexec-tools 26/32] arm: rename crash_reserved_mem to
 crash_kernel_mem
In-Reply-To: <E1axXU6-0004jU-At@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXU6-0004jU-At@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GurX7ZS0PaRaos5VZzndpsL+d+783Jw2Dm0K_h3C0aN3FA@mail.gmail.com>

On Tue, May 3, 2016 at 3:53 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Rename crash_reserved_mem to crash_kernel_mem as we want to support
> multiple reserved memory ranges.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/crashdump-arm.c | 28 ++++++++++++++--------------
>  1 file changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index f2e6a0d..1a6ab88 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -53,7 +53,7 @@ struct memory_ranges usablemem_rgns = {
>  };
>
>  /* memory range reserved for crashkernel */
> -static struct memory_range crash_reserved_mem;
> +static struct memory_range crash_kernel_mem;
>
>  static struct crash_elf_info elf_info = {
>         .class          = ELFCLASS32,
> @@ -140,7 +140,7 @@ static int get_kernel_page_offset(struct kexec_info *info,
>   */
>  static void crash_exclude_range(void)
>  {
> -       const struct memory_range *range = &crash_reserved_mem;
> +       const struct memory_range *range = &crash_kernel_mem;
>         int i;
>
>         for (i = 0; i < usablemem_rgns.size; i++) {
> @@ -262,8 +262,8 @@ static void dump_memory_ranges(void)
>                 return;
>
>         dbgprintf("crashkernel: [%#llx - %#llx] (%ldM)\n",
> -                 crash_reserved_mem.start, crash_reserved_mem.end,
> -                 (unsigned long)range_size(&crash_reserved_mem) >> 20);
> +                 crash_kernel_mem.start, crash_kernel_mem.end,
> +                 (unsigned long)range_size(&crash_kernel_mem) >> 20);
>
>         for (i = 0; i < usablemem_rgns.size; i++) {
>                 struct memory_range *r = usablemem_rgns.ranges + i;
> @@ -313,10 +313,10 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
>          * Ensure that the crash kernel memory range is sane. The crash kernel
>          * must be located within memory which is visible during booting.
>          */
> -       if (crash_reserved_mem.end > ARM_MAX_VIRTUAL) {
> +       if (crash_kernel_mem.end > ARM_MAX_VIRTUAL) {
>                 fprintf(stderr,
>                         "Crash kernel memory [0x%llx-0x%llx] is inaccessible at boot - unable to load crash kernel\n",
> -                       crash_reserved_mem.start, crash_reserved_mem.end);
> +                       crash_kernel_mem.start, crash_kernel_mem.end);
>                 return -1;
>         }
>
> @@ -349,8 +349,8 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
>          * regions to be aligned to SECTION_SIZE.
>          */
>         elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 1 << 20,
> -                                         crash_reserved_mem.start,
> -                                         crash_reserved_mem.end, -1, 0);
> +                                         crash_kernel_mem.start,
> +                                         crash_kernel_mem.end, -1, 0);
>
>         dbgprintf("elfcorehdr: %#lx\n", elfcorehdr);
>         cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
> @@ -360,7 +360,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
>          * prevents the dump capture kernel from using any other memory regions
>          * which belong to the primary kernel.
>          */
> -       cmdline_add_mem(mod_cmdline, elfcorehdr - crash_reserved_mem.start);
> +       cmdline_add_mem(mod_cmdline, elfcorehdr - crash_kernel_mem.start);
>
>         dump_memory_ranges();
>         dbgprintf("kernel command line: \"%s\"\n", mod_cmdline);
> @@ -377,7 +377,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
>   * @length: size of the memory region
>   *
>   * This function is called for each memory range in /proc/iomem, stores
> - * the location of the crash kernel range into @crash_reserved_mem, and
> + * the location of the crash kernel range into @crash_kernel_mem, and
>   * stores the system RAM into @usablemem_rgns.
>   */
>  static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
> @@ -385,9 +385,9 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
>                                 unsigned long long length)
>  {
>         if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) {
> -               crash_reserved_mem.start = base;
> -               crash_reserved_mem.end = base + length - 1;
> -               crash_reserved_mem.type = RANGE_RAM;
> +               crash_kernel_mem.start = base;
> +               crash_kernel_mem.end = base + length - 1;
> +               crash_kernel_mem.type = RANGE_RAM;
>         }
>         else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) {
>                 return mem_regions_add(&usablemem_rgns,
> @@ -407,5 +407,5 @@ int is_crashkernel_mem_reserved(void)
>  {
>         kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL);
>
> -       return crash_reserved_mem.start != crash_reserved_mem.end;
> +       return crash_kernel_mem.start != crash_kernel_mem.end;
>  }
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:37:23 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:07:23 +0530
Subject: [PATCH kexec-tools 27/32] arm: add support for multiple reserved
 regions
In-Reply-To: <E1axXUB-0004ja-JE@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXUB-0004ja-JE@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_Gur-Z8ypohfG7rACR_hvnf_03TqrpJuFtZxAynnmRY6bUQ@mail.gmail.com>

On Tue, May 3, 2016 at 3:53 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Add support for reserving multiple memory regions rather than just a
> single region.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/crashdump-arm.c | 66 ++++++++++++++++--------------------------
>  1 file changed, 25 insertions(+), 41 deletions(-)
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index 1a6ab88..9113f5e 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -55,6 +55,14 @@ struct memory_ranges usablemem_rgns = {
>  /* memory range reserved for crashkernel */
>  static struct memory_range crash_kernel_mem;
>
> +/* reserved regions */
> +#define CRASH_MAX_RESERVED_RANGES 2
> +static struct memory_range crash_reserved_ranges[CRASH_MAX_RESERVED_RANGES];
> +static struct memory_ranges crash_reserved_rgns = {
> +       .max_size = CRASH_MAX_RESERVED_RANGES,
> +       .ranges = crash_reserved_ranges,
> +};
> +
>  static struct crash_elf_info elf_info = {
>         .class          = ELFCLASS32,
>         .data           = ELFDATANATIVE,
> @@ -133,44 +141,6 @@ static int get_kernel_page_offset(struct kexec_info *info,
>  }
>
>  /**
> - * crash_exclude_range() - excludes memory region reserved for crashkernel
> - *
> - * Function locates where crashkernel reserved memory is and removes that region
> - * from the available memory regions.
> - */
> -static void crash_exclude_range(void)
> -{
> -       const struct memory_range *range = &crash_kernel_mem;
> -       int i;
> -
> -       for (i = 0; i < usablemem_rgns.size; i++) {
> -               struct memory_range *r = usablemem_rgns.ranges + i;
> -
> -               /*
> -                * We assume that crash area is fully contained in
> -                * some larger memory area.
> -                */
> -               if (r->start <= range->start && r->end >= range->end) {
> -                       struct memory_range *new;
> -                       /*
> -                        * Let's split this area into 2 smaller ones and
> -                        * remove excluded range from between. First create
> -                        * new entry for the remaining area.
> -                        */
> -                       new = usablemem_rgns.ranges + usablemem_rgns.size;
> -                       new->start = range->end + 1;
> -                       new->end = r->end;
> -                       usablemem_rgns.size++;
> -                       /*
> -                        * Next update this area to end before excluded range.
> -                        */
> -                       r->end = range->start - 1;
> -                       break;
> -               }
> -       }
> -}
> -
> -/**
>   * crash_get_memory_ranges() - read system physical memory
>   *
>   * Function reads through system physical memory and stores found memory regions
> @@ -181,16 +151,28 @@ static void crash_exclude_range(void)
>   */
>  static int crash_get_memory_ranges(void)
>  {
> +       int i;
> +
>         if (usablemem_rgns.size < 1) {
>                 errno = EINVAL;
>                 return -1;
>         }
>
>         /*
> -        * Exclude memory reserved for crashkernel (this may result a split memory
> -        * region).
> +        * Exclude all reserved memory from the usable memory regions.
> +        * We want to avoid dumping the crashkernel region itself.  Note
> +        * that this may result memory regions in usablemem_rgns being
> +        * split.
>          */
> -       crash_exclude_range();
> +       for (i = 0; i < crash_reserved_rgns.size; i++) {
> +               if (mem_regions_exclude(&usablemem_rgns,
> +                                       &crash_reserved_rgns.ranges[i])) {
> +                       fprintf(stderr,
> +                               "Error: Number of crash memory ranges excedeed the max limit\n");
> +                       errno = ENOMEM;
> +                       return -1;
> +               }
> +       }
>
>         /*
>          * Make sure that the memory regions are sorted.
> @@ -388,6 +370,8 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
>                 crash_kernel_mem.start = base;
>                 crash_kernel_mem.end = base + length - 1;
>                 crash_kernel_mem.type = RANGE_RAM;
> +               return mem_regions_add(&crash_reserved_rgns,
> +                                      base, length, RANGE_RAM);
>         }
>         else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) {
>                 return mem_regions_add(&usablemem_rgns,
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:37:46 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:07:46 +0530
Subject: [PATCH kexec-tools 28/32] arm: add support for boot-time crash
 kernel resource
In-Reply-To: <E1axXUG-0004jg-PD@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXUG-0004jg-PD@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GuqYApGpL1v-4mLUJ-iZcs9k-jg8DFedG8_S+Mat4mVoRA@mail.gmail.com>

On Tue, May 3, 2016 at 3:53 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Add support for detecting and using the boot-time crash kernel
> resource, which is needed for systems which have special boot-time
> memory views, such as Keystone 2.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/crashdump-arm.c | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index 9113f5e..25fdbe9 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -52,7 +52,7 @@ struct memory_ranges usablemem_rgns = {
>         .ranges = crash_memory_ranges,
>  };
>
> -/* memory range reserved for crashkernel */
> +/* The boot-time physical memory range reserved for crashkernel region */
>  static struct memory_range crash_kernel_mem;
>
>  /* reserved regions */
> @@ -366,13 +366,22 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
>                                 char *str, unsigned long long base,
>                                 unsigned long long length)
>  {
> -       if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) {
> +       if (strncmp(str, CRASH_KERNEL_BOOT, strlen(CRASH_KERNEL_BOOT)) == 0) {
>                 crash_kernel_mem.start = base;
>                 crash_kernel_mem.end = base + length - 1;
>                 crash_kernel_mem.type = RANGE_RAM;
>                 return mem_regions_add(&crash_reserved_rgns,
>                                        base, length, RANGE_RAM);
>         }
> +       else if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) {
> +               if (crash_kernel_mem.start == crash_kernel_mem.end) {
> +                       crash_kernel_mem.start = base;
> +                       crash_kernel_mem.end = base + length - 1;
> +                       crash_kernel_mem.type = RANGE_RAM;
> +               }
> +               return mem_regions_add(&crash_reserved_rgns,
> +                                      base, length, RANGE_RAM);
> +       }
>         else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) {
>                 return mem_regions_add(&usablemem_rgns,
>                                        base, length, RANGE_RAM);
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:38:21 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:08:21 +0530
Subject: [PATCH kexec-tools 31/32] arm: clean up phys/page offset debug
In-Reply-To: <E1axXUW-0004jy-CS@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXUW-0004jy-CS@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GurTg0R0Ncny452W7c-0MESdDhOMo225goBoNAzzqjmBOQ@mail.gmail.com>

On Tue, May 3, 2016 at 3:53 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Clean up the physical and page offset debug prints.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/crashdump-arm.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index 2589582..3b71267 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -136,7 +136,6 @@ static int get_kernel_page_offset(struct kexec_info *info,
>                                 user_page_offset);
>         }
>         elf_info->page_offset = stext_sym_addr & (~KVBASE_MASK);
> -       dbgprintf("page_offset is set to %llx\n", elf_info->page_offset);
>         return 0;
>  }
>
> @@ -293,11 +292,13 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
>          * region as PHYS_OFFSET.
>          */
>         phys_offset = usablemem_rgns.ranges->start;
> -       dbgprintf("phys_offset: %#llx\n", phys_offset);
>
>         if (get_kernel_page_offset(info, &elf_info))
>                 return -1;
>
> +       dbgprintf("phys offset = %#llx, page offset = %llx\n",
> +                 phys_offset, elf_info.page_offset);
> +
>         /*
>          * Ensure that the crash kernel memory range is sane. The crash kernel
>          * must be located within memory which is visible during booting.
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:38:11 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:08:11 +0530
Subject: [PATCH kexec-tools 30/32] arm: fix type of phys_offset
In-Reply-To: <E1axXUR-0004js-5j@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXUR-0004js-5j@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_Guq+4PQ0o66ypNLQE_y4E1c6=jRO+OwRpmzpE+Z6uDjdmw@mail.gmail.com>

On Tue, May 3, 2016 at 3:53 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Some LPAE systems may have phys_offset above the 4GB mark.  Hence, we
> need phys_offset to be a 64-bit integer.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/crashdump-arm.c | 4 ++--
>  kexec/arch/arm/crashdump-arm.h | 1 -
>  kexec/arch/arm/phys_to_virt.c  | 4 +++-
>  kexec/arch/arm/phys_to_virt.h  | 8 ++++++++
>  4 files changed, 13 insertions(+), 4 deletions(-)
>  create mode 100644 kexec/arch/arm/phys_to_virt.h
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index 2dc8846..2589582 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -33,6 +33,7 @@
>  #include "../../mem_regions.h"
>  #include "crashdump-arm.h"
>  #include "iomem.h"
> +#include "phys_to_virt.h"
>
>  #if __BYTE_ORDER == __LITTLE_ENDIAN
>  #define ELFDATANATIVE ELFDATA2LSB
> @@ -70,7 +71,6 @@ static struct crash_elf_info elf_info = {
>         .page_offset    = DEFAULT_PAGE_OFFSET,
>  };
>
> -unsigned long phys_offset;
>  extern unsigned long long user_page_offset;
>
>  /* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */
> @@ -293,7 +293,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
>          * region as PHYS_OFFSET.
>          */
>         phys_offset = usablemem_rgns.ranges->start;
> -       dbgprintf("phys_offset: %#lx\n", phys_offset);
> +       dbgprintf("phys_offset: %#llx\n", phys_offset);
>
>         if (get_kernel_page_offset(info, &elf_info))
>                 return -1;
> diff --git a/kexec/arch/arm/crashdump-arm.h b/kexec/arch/arm/crashdump-arm.h
> index 7314960..6e87b13 100644
> --- a/kexec/arch/arm/crashdump-arm.h
> +++ b/kexec/arch/arm/crashdump-arm.h
> @@ -16,7 +16,6 @@ extern struct memory_ranges usablemem_rgns;
>
>  struct kexec_info;
>
> -extern unsigned long phys_offset;
>  extern int load_crashdump_segments(struct kexec_info *, char *);
>
>  #ifdef __cplusplus
> diff --git a/kexec/arch/arm/phys_to_virt.c b/kexec/arch/arm/phys_to_virt.c
> index c2fe2ea..46a4f68 100644
> --- a/kexec/arch/arm/phys_to_virt.c
> +++ b/kexec/arch/arm/phys_to_virt.c
> @@ -1,6 +1,8 @@
>  #include "../../kexec.h"
>  #include "../../crashdump.h"
> -#include "crashdump-arm.h"
> +#include "phys_to_virt.h"
> +
> +uint64_t phys_offset;
>
>  /**
>   * phys_to_virt() - translate physical address to virtual address
> diff --git a/kexec/arch/arm/phys_to_virt.h b/kexec/arch/arm/phys_to_virt.h
> new file mode 100644
> index 0000000..b3147dd
> --- /dev/null
> +++ b/kexec/arch/arm/phys_to_virt.h
> @@ -0,0 +1,8 @@
> +#ifndef PHYS_TO_VIRT_H
> +#define PHYS_TO_VIRT_H
> +
> +#include <stdint.h>
> +
> +extern uint64_t phys_offset;
> +
> +#endif
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:38:31 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:08:31 +0530
Subject: [PATCH kexec-tools 32/32] arm: report which ELF core format we
 will use
In-Reply-To: <E1axXUb-0004k4-LW@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXUb-0004k4-LW@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_Guq8Q965VgCzp+Spa2J_u5cUOFifgD45xOYR2uR-P4BxhA@mail.gmail.com>

On Tue, May 3, 2016 at 3:53 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Report which ELF core format will be used to create the template ELF
> core dump in the debug information.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/arch/arm/crashdump-arm.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index 3b71267..4a89b5e 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -315,6 +315,8 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
>                 last_ranges = 0;
>
>         if (crash_memory_ranges[last_ranges].end > UINT32_MAX) {
> +               dbgprintf("Using 64-bit ELF core format\n");
> +
>                 /* for support LPAE enabled kernel*/
>                 elf_info.class = ELFCLASS64;
>
> @@ -323,6 +325,7 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
>                                          usablemem_rgns.size, &buf, &bufsz,
>                                          ELF_CORE_HEADER_ALIGN);
>         } else {
> +               dbgprintf("Using 32-bit ELF core format\n");
>                 err = crash_create_elf32_headers(info, &elf_info,
>                                          usablemem_rgns.ranges,
>                                          usablemem_rgns.size, &buf, &bufsz,
> --
> 1.9.1
>


From panand at redhat.com  Fri May 27 04:43:53 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 17:13:53 +0530
Subject: [PATCH kexec-tools 08/32] kexec: add max_size to memory_ranges
In-Reply-To: <E1axXSa-0004hf-Iz@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSa-0004hf-Iz@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <CAHB_GuruHfjF_YRbP+1wTybGfvX02xQcUefbo0rv4xAtDdhakw@mail.gmail.com>

On Tue, May 3, 2016 at 3:51 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> Many implementations statically allocate the memory range array, which
> therefore will have a maximum allowable size.  Add this information to
> the memory_ranges structure, so we don't have to carry it around.
>
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  kexec/kexec.h | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/kexec/kexec.h b/kexec/kexec.h
> index c02ac8f..9194f1c 100644
> --- a/kexec/kexec.h
> +++ b/kexec/kexec.h
> @@ -142,6 +142,7 @@ struct memory_range {
>
>  struct memory_ranges {
>          unsigned int size;
> +       unsigned int max_size;
>          struct memory_range *ranges;
>  };
>
> --
> 1.9.1
>


From harninder.rai at nxp.com  Fri May 27 04:51:03 2016
From: harninder.rai at nxp.com (Harninder Rai)
Date: Fri, 27 May 2016 11:51:03 +0000
Subject: Help needed with kexec on arm64
References: <CAB5YjtBEO=efjhcFdVOaZqG13qK3uzCbS5SFym5hhw-n+_QLhw@mail.gmail.com>
 <DB5PR04MB1688A6D4385B76DAFF71D364E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org>
 <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160511005334.GA8417@linaro.org>
 <DB5PR04MB1688C3F122091109E6BD9B68E6740@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160519110307.GA4941@linaro.org> 
Message-ID: <DB5PR04MB16887FF10CEA6AA9BF990F0DE6420@DB5PR04MB1688.eurprd04.prod.outlook.com>

Hello Takahiro Akashi,

Please see the following log which I was talking about in my last communication
Any idea as to what could be wrong just when I move from RAM based rootfs to SD based rootfs?

> I did check /proc/iomem and everything looks there. This is very strange
> since if I keep everything same and just move the rootfs from RAM based to
> SD based, I start getting this issue.

root at ls2085ardb:/# kexec -p ./vmlinux.wor --initrd=./initramfs_arm64_busybox1_22_1_with_coremark.cpio.gz --append='console=ttyS1,115200 root=/dev/ram0 earlycon=uart8250,mmio,0x21c0600ramdisk_size=0x2000000 default_hugepagesz=2m hugepagesz=2m hugepages=256 memblock=debug maxcpus=1'
Memory for crashkernel is not reserved
Please reserve memory by passing"crashkernel=X at Y" parameter to kernel
Then try to loading kdump kernel
root at ls2085ardb:/# cat /proc/iomem
02000000-0200ffff : /i2c at 2000000
02140000-0214ffff : mmc0
021c0500-021c05ff : serial
021c0600-021c06ff : serial
03100000-03107fff : /usb3 at 3100000
0310c100-0310ffff : /usb3 at 3100000
03110000-03117fff : /usb3 at 3110000
0311c100-0311ffff : /usb3 at 3110000
05000000-057fffff : /iommu at 5000000
80000000-ffffffff : System RAM
  80080000-80a39333 : Kernel code
  80af5000-80bd4fff : Kernel data
  8c000000-8fffffff : Crash kernel
80c000000-80c00003f : mc_portal

Regards
Harry++


From harninder.rai at nxp.com  Fri May 27 05:03:38 2016
From: harninder.rai at nxp.com (Harninder Rai)
Date: Fri, 27 May 2016 12:03:38 +0000
Subject: kexec: Not able to copy the vmcore file to external device
Message-ID: <DB5PR04MB1688C4D8931ED1F0AB51851BE6420@DB5PR04MB1688.eurprd04.prod.outlook.com>

Hello Takahiro Akashi/Geoff,

When I try a smaller RAM based rootfs to boot the crash kernel, the vmcore file gets generated correctly (it is of 2GB size) 
But I am not able to copy that file completely on my mounted SD card. I get some out of memory errors
Following is the state of my booted crash dump kernel

root at freescale /$ df -h
Filesystem                Size      Used Available Use% Mounted on
shm                      18.2M         0     18.2M   0% /dev/shm
rwfs                    512.0K         0    512.0K   0% /mnt/rwfs
root at freescale /$ ls -ltrh /proc/vmcore
-r--------    1 root     root        1.9G Jan  1 00:00 /proc/vmcore

root at freescale /$ mount /dev/mmcblk0p1 /mnt/
[   64.624900] EXT4-fs (mmcblk0p1): couldn't mount as ext3 due to feature incompatibilities
[   64.641148] EXT4-fs (mmcblk0p1): warning: mounting unchecked fs, running e2fsck is recommended
[   64.655126] EXT4-fs (mmcblk0p1): mounted filesystem without journal. Opts: (null)
root at freescale /$ cp /proc/vmcore /mnt/
[   77.068317] random: nonblocking pool is initialized
[   95.787102] cp invoked oom-killer: gfp_mask=0x26040c0, order=0, oom_score_adj=0
[   95.794531] CPU: 0 PID: 886 Comm: cp Not tainted 4.5.0-rc6-00038-gae2804a-dirty #5
[   95.802125] Hardware name: Freescale Layerscape 2085a RDB Board (DT)
[   95.808499] Call trace:
[   95.810957] [<ffff800000089760>] dump_backtrace+0x0/0x1ac
[   95.816374] [<ffff800000089920>] show_stack+0x14/0x1c
[   95.821442] [<ffff80000032c1d4>] dump_stack+0x8c/0xb0
[   95.826510] [<ffff8000001aebdc>] dump_header.isra.7+0x4c/0x18c
[   95.832362] [<ffff800000152130>] oom_kill_process+0x26c/0x45c
[   95.838126] [<ffff800000152688>] out_of_memory+0x2e0/0x32c
[   95.843628] [<ffff800000156c68>] __alloc_pages_nodemask+0x83c/0x848
[   95.849915] [<ffff80000019a9b8>] cache_alloc_refill+0x38c/0x5fc
[   95.855852] [<ffff80000019acec>] kmem_cache_alloc+0xc4/0x138
[   95.861529] [<ffff800000185118>] alloc_vmap_area.isra.38+0x64/0x2f4
[   95.867815] [<ffff800000185a88>] __get_vm_area_node.isra.39+0xa0/0x15c
[   95.874365] [<ffff800000186084>] get_vm_area_caller+0x34/0x3c
[   95.880129] [<ffff800000097814>] __ioremap_caller+0x6c/0xdc
[   95.885717] [<ffff80000009792c>] ioremap_cache+0x5c/0x68
[   95.891044] [<ffff800000095430>] copy_oldmem_page+0x48/0xe8
[   95.896635] [<ffff80000021c044>] read_from_oldmem.part.3+0xbc/0xfc
[   95.902834] [<ffff80000021c180>] read_vmcore+0xfc/0x228
[   95.908076] [<ffff80000020f654>] proc_reg_read+0x64/0x94
[   95.913403] [<ffff8000001b17b0>] __vfs_read+0x2c/0xd8
[   95.918469] [<ffff8000001b25a0>] vfs_read+0x7c/0x144
[   95.923448] [<ffff8000001b33d0>] SyS_read+0x44/0xa0
[   95.928341] [<ffff800000085d30>] el0_svc_naked+0x24/0x28
[   95.933705] Mem-Info:
[   95.936072] active_anon:46 inactive_anon:0 isolated_anon:0
[   95.936072]  active_file:91 inactive_file:543 isolated_file:0
[   95.936072]  unevictable:2102 dirty:5 writeback:549 unstable:0
[   95.936072]  slab_reclaimable:312 slab_unreclaimable:1301
[   95.936072]  mapped:366 shmem:0 pagetables:12 bounce:0
[   95.936072]  free:3700 free_pcp:0 free_cma:3511
[   95.968438] DMA free:14796kB min:764kB low:952kB high:1144kB active_anon:184kB inactive_anon:0kB active_file:368kB inactive_file:2176kB unevictable:8408kB isolated(anon):0kB isolated(file):0kB present:65536kB managed:37372kB mlocked:0kB dirty:16kB writeback:2188kB mapped:1464kB shmem:0kB slab_reclaimable:1248kB slab_unreclaimable:5204kB kernel_stack:1088kB pagetables:48kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:14040kB writeback_tmp:0kB pages_scanned:15584 all_unreclaimable? yes
[   96.012892] lowmem_reserve[]: 0 0 0
[   96.016412] DMA: 1*4kB (E) 21*8kB (UEC) 12*16kB (UC) 15*32kB (UC) 16*64kB (UC) 9*128kB (C) 12*256kB (C) 5*512kB (C) 4*1024kB (C) 1*2048kB (C) 0*4096kB = 14796kB
[   96.030922] Node 0 hugepages_total=1 hugepages_free=1 hugepages_surp=0 hugepages_size=2048kB
[   96.039390] 2737 total pagecache pages
[   96.043151] 0 pages in swap cache
[   96.046474] Swap cache stats: add 0, delete 0, find 0/0
[   96.051717] Free swap  = 0kB
[   96.054601] Total swap = 0kB
[   96.057491] 16384 pages RAM
[   96.060434] 0 pages HighMem/MovableOnly
[   96.064283] 7041 pages reserved
[   96.067428] 4096 pages cma reserved
[   96.070926] [ pid ]   uid  tgid total_vm      rss nr_ptes nr_pmds swapents oom_score_adj name
[   96.079487] [  877]     0   877      555      353       4       3        0             0 sh
[   96.087870] [  886]     0   886      539        1       4       3        0             0 cp
[   96.096253] Out of memory: Kill process 877 (sh) score 37 or sacrifice child
[   96.103334] Killed process 886 (cp) total-vm:2156kB, anon-rss:4kB, file-rss:0kB, shmem-rss:0kB
Killed
root at freescale /$ ls -ltr /mnt/vmcore
-r--------    1 root     root      65593344 Jan  1 00:01 /mnt/vmcore
root at freescale /$ ls -ltr /mnt/vmcore -h
-r--------    1 root     root       62.6M Jan  1 00:01 /mnt/vmcore

Thanks and Regards
Harry++



From mark.rutland at arm.com  Fri May 27 05:38:10 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Fri, 27 May 2016 13:38:10 +0100
Subject: [PATCH] arm64: kasan: instrument user memory access API
In-Reply-To: <1464288231-11304-1-git-send-email-yang.shi@linaro.org>
References: <1464288231-11304-1-git-send-email-yang.shi@linaro.org>
Message-ID: <20160527123809.GD24469@leverpostej>

Hi,

On Thu, May 26, 2016 at 11:43:51AM -0700, Yang Shi wrote:
> The upstream commit 1771c6e1a567ea0ba2cccc0a4ffe68a1419fd8ef
> ("x86/kasan: instrument user memory access API") added KASAN instrument to
> x86 user memory access API, so added such instrument to ARM64 too.
> 
> Tested by test_kasan module.

I just gave this a go atop of the current HEAD (dc03c0f9d12d8528) on a
Juno R1 board. I hit the expected exceptions when using the test_kasan
module (once I remembered to rebuild it), and things seem to run
smoothly otherwise.

I don't see any built issues when !CONFIG_KASAN, and the patch itself
looks right to me.

So FWIW:

Acked-by: Mark Rutland <mark.rutland at arm.com>
Tested-by: Mark Rutland <mark.rutland at arm.com>

As an aside, it's a shame that each architecture has to duplicate this
logic, rather than having something in the generic code like:

static inline unsigned long __must_check
copy_from_user(void *to, const void __user *from, unsigned long n)
{
	kasan_check_read(from, n);
	arch_copy_from_user(to, from, n);
}

Thanks,
Mark.

> 
> Signed-off-by: Yang Shi <yang.shi at linaro.org>
> ---
>  arch/arm64/include/asm/uaccess.h | 18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
> index 0685d74..ec352fa 100644
> --- a/arch/arm64/include/asm/uaccess.h
> +++ b/arch/arm64/include/asm/uaccess.h
> @@ -23,6 +23,7 @@
>   */
>  #include <linux/string.h>
>  #include <linux/thread_info.h>
> +#include <linux/kasan-checks.h>
>  
>  #include <asm/alternative.h>
>  #include <asm/cpufeature.h>
> @@ -276,6 +277,8 @@ extern unsigned long __must_check __clear_user(void __user *addr, unsigned long
>  
>  static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
>  {
> +	kasan_check_write(to, n);
> +
>  	if (access_ok(VERIFY_READ, from, n))
>  		n = __copy_from_user(to, from, n);
>  	else /* security hole - plug it */
> @@ -285,6 +288,8 @@ static inline unsigned long __must_check copy_from_user(void *to, const void __u
>  
>  static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
>  {
> +	kasan_check_read(from, n);
> +
>  	if (access_ok(VERIFY_WRITE, to, n))
>  		n = __copy_to_user(to, from, n);
>  	return n;
> @@ -297,8 +302,17 @@ static inline unsigned long __must_check copy_in_user(void __user *to, const voi
>  	return n;
>  }
>  
> -#define __copy_to_user_inatomic __copy_to_user
> -#define __copy_from_user_inatomic __copy_from_user
> +static inline unsigned long __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
> +{
> +	kasan_check_read(from, n);
> +	return __copy_to_user(to, from, n);
> +}
> +
> +static inline unsigned long __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
> +{
> +	kasan_check_write(to, n);
> +	return __copy_from_user(to, from, n);
> +}
>  
>  static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
>  {
> -- 
> 2.0.2
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


From catalin.marinas at arm.com  Fri May 27 06:04:47 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 27 May 2016 14:04:47 +0100
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <5422652.7gdoDlB8u0@wuerfel>
References: <6293194.tGy03QJ9ME@wuerfel> <13240365.okADkKsTBJ@wuerfel>
 <20160527093052.GB7865@e104818-lin.cambridge.arm.com>
 <5422652.7gdoDlB8u0@wuerfel>
Message-ID: <20160527130446.GD7865@e104818-lin.cambridge.arm.com>

On Fri, May 27, 2016 at 12:49:11PM +0200, Arnd Bergmann wrote:
> On Friday, May 27, 2016 10:30:52 AM CEST Catalin Marinas wrote:
> > On Fri, May 27, 2016 at 10:42:59AM +0200, Arnd Bergmann wrote:
> > > On Friday, May 27, 2016 8:03:57 AM CEST Heiko Carstens wrote:
> > > > > > > > Cost wise, this seems like it all cancels out in the end, but what
> > > > > > > > do I know?
> > > > > > > 
> > > > > > > I think you know something, and I also think Heiko and other s390 guys
> > > > > > > know something as well. So I'd like to listen their arguments here.
> > > > 
> > > > If it comes to 64 bit arguments for compat system calls: s390 also has an
> > > > x32-like ABI extension which allows user space to use full 64 bit
> > > > registers. As far as I know hardly anybody ever made use of that.
> > > > 
> > > > However even if that would be widely used, to me it wouldn't make sense to
> > > > add new compat system calls which allow 64 bit arguments, simply because
> > > > something like
> > > > 
> > > > c = (u32)a | (u64)b << 32;
> > > > 
> > > > can be done with a single 1-cycle instruction. It's just not worth the
> > > > extra effort to maintain additional system call variants.
> > > 
> > > For reference, both tile and mips also have separate 32-bit ABIs that are
> > > only used on 64-bit kernels (aside from the normal 32-bit ABI). Tile
> > > does it like s390 and passes 64-bit arguments as pairs, while MIPS
> > > and x86 and pass them as single registers.
> > 
> > AFAIK, x32 also requires that the upper half of a 64-bit reg is zeroed
> > by the user when a 32-bit value is passed. We could require the same on
> > AArch64/ILP32 but I'm a bit uneasy on trusting a multitude of C
> > libraries on this.
> 
> It's not about trusting a C library, it's about ensuring malicious code
> cannot pass argumentst that the kernel code assumes will never happen.

At least for pointers and sizes, we have additional checks in place
already, like __access_ok(). Most of the syscalls should be safe since
they either go through some compat functions taking 32-bit arguments or
are routed to native functions which already need to cope with a full
random 64-bit value.

On arm64, I think the only risk comes from syscall handlers expecting
32-bit arguments but using 64-bit types. Apart from pointer types, I
don't expect this to happen but we could enforce it via a
BUILD_BUG_ON(sizeof(t) > 4 && !__TYPE_IS_PTR(t)) in __SC_DELOUSE as per
the s390 implementation. With ILP32 if we go for 64-bit off_t, those
syscalls would be routed directly to the native layer.

-- 
Catalin


From patrice.chotard at st.com  Fri May 27 06:15:19 2016
From: patrice.chotard at st.com (Patrice Chotard)
Date: Fri, 27 May 2016 15:15:19 +0200
Subject: [PATCH v4 01/18] remoteproc: st_xp70_rproc: add a xp70 slimcore
 rproc driver
In-Reply-To: <1464192412-16386-3-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
 <1464192412-16386-3-git-send-email-peter.griffin@linaro.org>
Message-ID: <57484867.6030608@st.com>



On 05/25/2016 06:06 PM, Peter Griffin wrote:
> XP70 slim core is used as a basis for many IPs in the STi
> chipsets such as fdma, display, and demux. To avoid
> duplicating the elf loading code in each device driver
> an xp70 rproc driver has been created.
>
> This driver is designed to be used by other device drivers
> such as fdma, or demux whose IP is based around a xp70 slimcore.
> The device driver can call xp70_rproc_alloc() to allocate
> an xp70 rproc and xp70_rproc_put() when finished.
>
> This driver takes care of ioremapping the xp70
> registers (dmem, imem, slimcore, peripherals), whose offsets
> and sizes can change between IP's. It also obtains and enables
> any clocks used by the device. This approach avoids having
> a double mapping of the registers as xp70_rproc does not register
> its own platform device. It also maps well to device tree
> abstraction as it allows us to have one dt node for the whole
> device.
>
> All of the generic rproc elf loading code can be reused, and
> we provide start() stop() hooks to start and stop the xp70
> core once the firmware has been loaded. This has been tested
> successfully with fdma driver.
>
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
>   drivers/remoteproc/Kconfig               |   8 +
>   drivers/remoteproc/Makefile              |   1 +
>   drivers/remoteproc/st_xp70_rproc.c       | 380 +++++++++++++++++++++++++++++++
>   include/linux/remoteproc/st_xp70_rproc.h |  56 +++++
>   4 files changed, 445 insertions(+)
>   create mode 100644 drivers/remoteproc/st_xp70_rproc.c
>   create mode 100644 include/linux/remoteproc/st_xp70_rproc.h
>
> diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
> index 72e97d7..9e48fd1 100644
> --- a/drivers/remoteproc/Kconfig
> +++ b/drivers/remoteproc/Kconfig
> @@ -86,4 +86,12 @@ config ST_REMOTEPROC
>   	  processor framework.
>   	  This can be either built-in or a loadable module.
>   
> +config ST_XP70_REMOTEPROC
> +	tristate "XP70 slim remoteproc support"
> +	depends on ARCH_STI
> +	select REMOTEPROC
> +	help
> +	  Say y here to support xp70 slim core.
> +	  If unsure say N.
> +
>   endmenu
> diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
> index 279cb2e..b5dab8e 100644
> --- a/drivers/remoteproc/Makefile
> +++ b/drivers/remoteproc/Makefile
> @@ -12,3 +12,4 @@ obj-$(CONFIG_STE_MODEM_RPROC)	 	+= ste_modem_rproc.o
>   obj-$(CONFIG_WKUP_M3_RPROC)		+= wkup_m3_rproc.o
>   obj-$(CONFIG_DA8XX_REMOTEPROC)		+= da8xx_remoteproc.o
>   obj-$(CONFIG_ST_REMOTEPROC)		+= st_remoteproc.o
> +obj-$(CONFIG_ST_XP70_REMOTEPROC)	+= st_xp70_rproc.o
> diff --git a/drivers/remoteproc/st_xp70_rproc.c b/drivers/remoteproc/st_xp70_rproc.c
> new file mode 100644
> index 0000000..6a78e7c
> --- /dev/null
> +++ b/drivers/remoteproc/st_xp70_rproc.c
> @@ -0,0 +1,380 @@
> +/*
> + * st_xp70_rproc.c
> + *
> + * Copyright (C) 2016 STMicroelectronics
> + * Author: Peter Griffin <peter.griffin at st.com>
> + * License terms:  GNU General Public License (GPL), version 2
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/elf.h>
> +#include <linux/err.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/remoteproc.h>
> +#include <linux/remoteproc/st_xp70_rproc.h>
> +#include "remoteproc_internal.h"
> +
> +/* slimcore registers */
> +#define XP70_ID_OFST		0x0
> +#define XP70_VER_OFST		0x4
> +
> +#define XP70_EN_OFST		0x8
> +#define XP70_EN_RUN			BIT(0)
> +
> +#define XP70_CLK_GATE_OFST	0xC
> +#define XP70_CLK_GATE_DIS		BIT(0)
> +#define XP70_CLK_GATE_RESET		BIT(2)
> +
> +#define XP70_SLIM_PC_OFST	0x20
> +
> +/* dmem registers */
> +#define XP70_REV_ID_OFST	0x0
> +#define XP70_REV_ID_MIN_MASK		GENMASK(15, 8)
> +#define XP70_REV_ID_MIN(id)		((id & XP70_REV_ID_MIN_MASK) >> 8)
> +#define XP70_REV_ID_MAJ_MASK		GENMASK(23, 16)
> +#define XP70_REV_ID_MAJ(id)		((id & XP70_REV_ID_MAJ_MASK) >> 16)
> +
> +
> +/* peripherals registers */
> +#define XP70_STBUS_SYNC_OFST	0xF88
> +#define XP70_STBUS_SYNC_DIS		BIT(0)
> +
> +#define XP70_INT_SET_OFST	0xFD4
> +#define XP70_INT_CLR_OFST	0xFD8
> +#define XP70_INT_MASK_OFST	0xFDC
> +
> +#define XP70_CMD_CLR_OFST	0xFC8
> +#define XP70_CMD_MASK_OFST	0xFCC
> +
> +const char *mem_names[XP70_MEM_MAX] = {
> +	[DMEM]		= "dmem",
> +	[IMEM]		= "imem",
> +};
> +
> +static int xp70_clk_get(struct st_xp70_rproc *xp70_rproc, struct device *dev)
> +{
> +	int clk, err = 0;
> +
> +	for (clk = 0; clk < XP70_MAX_CLK; clk++) {
> +		xp70_rproc->clks[clk] = of_clk_get(dev->of_node, clk);
> +		if (IS_ERR(xp70_rproc->clks[clk])) {
> +			err = PTR_ERR(xp70_rproc->clks[clk]);
> +			if (err == -EPROBE_DEFER)
> +				goto err_put_clks;
> +			xp70_rproc->clks[clk] = NULL;
> +			break;
> +		}
> +	}
> +
> +	return 0;
> +
> +err_put_clks:
> +	while (--clk >= 0)
> +		clk_put(xp70_rproc->clks[clk]);
> +
> +	return err;
> +}
> +
> +static void xp70_clk_disable(struct st_xp70_rproc *xp70_rproc)
> +{
> +	int clk;
> +
> +	for (clk = 0; clk < XP70_MAX_CLK && xp70_rproc->clks[clk]; clk++)
> +		clk_disable_unprepare(xp70_rproc->clks[clk]);
> +}
> +
> +static int xp70_clk_enable(struct st_xp70_rproc *xp70_rproc)
> +{
> +	int clk, ret;
> +
> +	for (clk = 0; clk < XP70_MAX_CLK && xp70_rproc->clks[clk]; clk++) {
> +		ret = clk_prepare_enable(xp70_rproc->clks[clk]);
> +		if (ret)
> +			goto err_disable_clks;
> +	}
> +
> +	return 0;
> +
> +err_disable_clks:
> +	while (--clk >= 0)
> +		clk_disable_unprepare(xp70_rproc->clks[clk]);
> +
> +	return ret;
> +}
> +
> +/**
> + * Remoteproc xp70 specific device handlers
> + */
> +static int xp70_rproc_start(struct rproc *rproc)
> +{
> +	struct device *dev = &rproc->dev;
> +	struct st_xp70_rproc *xp70_rproc = rproc->priv;
> +	unsigned long hw_id, hw_ver, fw_rev;
> +	u32 val, ret = 0;
> +
> +	ret = xp70_clk_enable(xp70_rproc);
> +	if (ret) {
> +		dev_err(dev, "Failed to enable clocks\n");
> +		goto err_clk;
> +	}
> +
> +	/* disable CPU pipeline clock & reset cpu pipeline */
> +	val = XP70_CLK_GATE_DIS | XP70_CLK_GATE_RESET;
> +	writel_relaxed(val, xp70_rproc->slimcore + XP70_CLK_GATE_OFST);
> +
> +	/* disable SLIM core STBus sync */
> +	writel_relaxed(XP70_STBUS_SYNC_DIS,
> +		xp70_rproc->peri + XP70_STBUS_SYNC_OFST);
> +
> +	/* enable cpu pipeline clock */
> +	writel_relaxed(!XP70_CLK_GATE_DIS,
> +		xp70_rproc->slimcore + XP70_CLK_GATE_OFST);
> +
> +	/* clear int & cmd mailbox */
> +	writel_relaxed(~0UL, xp70_rproc->peri + XP70_INT_CLR_OFST);
> +	writel_relaxed(~0UL, xp70_rproc->peri + XP70_CMD_CLR_OFST);
> +
> +	/* enable all channels cmd & int */
> +	writel_relaxed(~0UL, xp70_rproc->peri + XP70_INT_MASK_OFST);
> +	writel_relaxed(~0UL, xp70_rproc->peri + XP70_CMD_MASK_OFST);
> +
> +	/* enable cpu */
> +	writel(XP70_EN_RUN, xp70_rproc->slimcore + XP70_EN_OFST);
> +
> +	hw_id = readl_relaxed(xp70_rproc->slimcore + XP70_ID_OFST);
> +	hw_ver = readl_relaxed(xp70_rproc->slimcore + XP70_VER_OFST);
> +
> +	fw_rev = readl_relaxed(xp70_rproc->mem[DMEM].cpu_addr +
> +			XP70_REV_ID_OFST);
> +
> +	dev_info(dev, "fw rev:%ld.%ld on SLIM %ld.%ld\n",
> +		 XP70_REV_ID_MAJ(fw_rev), XP70_REV_ID_MIN(fw_rev),
> +		 hw_id, hw_ver);
> +
> +	dev_dbg(dev, "XP70 started\n");
> +
> +err_clk:
> +	return ret;
> +}
> +
> +static int xp70_rproc_stop(struct rproc *rproc)
> +{
> +	struct st_xp70_rproc *xp70_rproc = rproc->priv;
> +	u32 val;
> +
> +	/* mask all (cmd & int) channels */
> +	writel_relaxed(0UL, xp70_rproc->peri + XP70_INT_MASK_OFST);
> +	writel_relaxed(0UL, xp70_rproc->peri + XP70_CMD_MASK_OFST);
> +
> +	/* disable cpu pipeline clock */
> +	writel_relaxed(XP70_CLK_GATE_DIS
> +		, xp70_rproc->slimcore + XP70_CLK_GATE_OFST);
> +
> +	writel_relaxed(!XP70_EN_RUN, xp70_rproc->slimcore + XP70_EN_OFST);
> +
> +	val = readl_relaxed(xp70_rproc->slimcore + XP70_EN_OFST);
> +	if (val & XP70_EN_RUN)
> +		dev_warn(&rproc->dev, "Failed to disable XP70");
> +
> +	xp70_clk_disable(xp70_rproc);
> +
> +	dev_dbg(&rproc->dev, "xp70 stopped\n");
> +
> +	return 0;
> +}
> +
> +static void *xp70_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
> +{
> +	struct st_xp70_rproc *xp70_rproc = rproc->priv;
> +	void *va = NULL;
> +	int i;
> +
> +	for (i = 0; i < XP70_MEM_MAX; i++) {
> +
> +		if (da != xp70_rproc->mem[i].bus_addr)
> +			continue;
> +
> +		va = xp70_rproc->mem[i].cpu_addr;
> +			break;
> +	}
> +
> +	dev_dbg(&rproc->dev, "%s: da = 0x%llx len = 0x%x va = 0x%p\n"
> +		, __func__, da, len, va);
> +
> +	return va;
> +}
> +
> +static struct rproc_ops xp70_rproc_ops = {
> +	.start		= xp70_rproc_start,
> +	.stop		= xp70_rproc_stop,
> +	.da_to_va       = xp70_rproc_da_to_va,
> +};
> +
> +/**
> + * Firmware handler operations: sanity, boot address, load ...
> + */
> +
> +static struct resource_table empty_rsc_tbl = {
> +	.ver = 1,
> +	.num = 0,
> +};
> +
> +static struct resource_table *xp70_rproc_find_rsc_table(struct rproc *rproc,
> +					       const struct firmware *fw,
> +					       int *tablesz)
> +{
> +	if (!fw)
> +		return NULL;
> +
> +	*tablesz = sizeof(empty_rsc_tbl);
> +	return &empty_rsc_tbl;
> +}
> +
> +static struct resource_table *xp70_rproc_find_loaded_rsc_table(struct rproc *rproc,
> +						      const struct firmware *fw)
> +{
> +	if (!fw)
> +		return NULL;
> +
> +	return &empty_rsc_tbl;
> +}
> +
> +static struct rproc_fw_ops xp70_rproc_fw_ops = {
> +	.find_rsc_table = xp70_rproc_find_rsc_table,
> +	.find_loaded_rsc_table = xp70_rproc_find_loaded_rsc_table,
> +};
> +
> +/**
> +  * xp70_rproc_alloc - allocate and initialise xp70 rproc
> +  * @pdev: Pointer to the platform_device struct
> +  * @fw_name: Name of firmware for rproc to use
> +  *
> +  * Function for allocating and initialising a xp70 rproc for use by
> +  * device drivers whose IP is based around the xp70 slim core. It
> +  * obtains and enables any clocks required by the xp70 core and also
> +  * ioremaps the various IO.
> +  *
> +  * Returns rproc pointer or PTR_ERR() on error.
> +  */
> +
> +struct rproc *xp70_rproc_alloc(struct platform_device *pdev, char *fw_name)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct st_xp70_rproc *xp70_rproc;
> +	struct device_node *np = dev->of_node;
> +	struct rproc *rproc;
> +	struct resource *res;
> +	int err, i;
> +	const struct rproc_fw_ops *elf_ops;
> +
> +	if (!np || !fw_name)
> +		return ERR_PTR(-EINVAL);
> +
> +	if (!of_device_is_compatible(np, "st,xp70-rproc"))
> +		return ERR_PTR(-EINVAL);
> +
> +	rproc = rproc_alloc(dev, np->name, &xp70_rproc_ops,
> +			fw_name, sizeof(*xp70_rproc));
> +	if (!rproc)
> +		return ERR_PTR(-ENOMEM);
> +
> +	rproc->has_iommu = false;
> +
> +	xp70_rproc = rproc->priv;
> +	xp70_rproc->rproc = rproc;
> +
> +	/* Get standard ELF ops */
> +	elf_ops = rproc_get_elf_ops();
> +
> +	/* Use some generic elf ops */
> +	xp70_rproc_fw_ops.load = elf_ops->load;
> +	xp70_rproc_fw_ops.sanity_check = elf_ops->sanity_check;
> +
> +	rproc->fw_ops = &xp70_rproc_fw_ops;
> +
> +	/* get imem and dmem */
> +	for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
> +		res = xp70_rproc->mem[i].io_res;
> +
> +		res = platform_get_resource_byname
> +			(pdev, IORESOURCE_MEM, mem_names[i]);
> +
> +		xp70_rproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res);
> +		if (IS_ERR(xp70_rproc->mem[i].cpu_addr)) {
> +			dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
> +			err = PTR_ERR(xp70_rproc->mem[i].cpu_addr);
> +			goto err;
> +		}
> +		xp70_rproc->mem[i].bus_addr = res->start;
> +		xp70_rproc->mem[i].size = resource_size(res);
> +	}
> +
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "slimcore");
> +
> +	xp70_rproc->slimcore = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(xp70_rproc->slimcore)) {
> +		dev_err(&pdev->dev, "devm_ioremap_resource failed for slimcore\n");
> +		err = PTR_ERR(xp70_rproc->slimcore);
> +		goto err;
> +	}
> +
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "peripherals");
> +
> +	xp70_rproc->peri = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(xp70_rproc->peri)) {
> +		dev_err(&pdev->dev, "devm_ioremap_resource failed for peri\n");
> +		err = PTR_ERR(xp70_rproc->peri);
> +		goto err;
> +	}
> +
> +	err = xp70_clk_get(xp70_rproc, dev);
> +	if (err)
> +		goto err;
> +
> +	/* Register as a remoteproc device */
> +	err = rproc_add(rproc);
> +	if (err) {
> +		dev_err(dev, "registration of xp70 remoteproc failed\n");
> +		goto err;
> +	}
> +
> +	dev_dbg(dev, "XP70 rproc init successful\n");
> +	return rproc;
> +
> +err:
> +	rproc_put(rproc);
> +	return ERR_PTR(err);
> +}
> +EXPORT_SYMBOL(xp70_rproc_alloc);
> +
> +/**
> +  * xp70_rproc_put - put xp70 rproc resources
> +  * @xp70_rproc: Pointer to the st_xp70_rproc struct
> +  *
> +  * Function for calling respective _put() functions on
> +  * xp70_rproc resources.
> +  *
> +  * Returns rproc pointer or PTR_ERR() on error.
> +  */
> +void xp70_rproc_put(struct st_xp70_rproc *xp70_rproc)
> +{
> +	int clk;
> +
> +	if (!xp70_rproc)
> +		return;
> +
> +	rproc_put(xp70_rproc->rproc);
> +
> +	for (clk = 0; clk < XP70_MAX_CLK && xp70_rproc->clks[clk]; clk++)
> +		clk_put(xp70_rproc->clks[clk]);
> +
> +}
> +EXPORT_SYMBOL(xp70_rproc_put);
> +
> +MODULE_AUTHOR("Peter Griffin");
> +MODULE_DESCRIPTION("STMicroelectronics XP70 rproc driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/remoteproc/st_xp70_rproc.h b/include/linux/remoteproc/st_xp70_rproc.h
> new file mode 100644
> index 0000000..3aba2de
> --- /dev/null
> +++ b/include/linux/remoteproc/st_xp70_rproc.h
> @@ -0,0 +1,56 @@
> +/*
> + * st_xp70_rproc.h
> + *
> + * Copyright (C) 2016 STMicroelectronics
> + * Author: Peter Griffin <peter.griffin at linaro.org>
> + * License terms:  GNU General Public License (GPL), version 2
> + */
> +#ifndef _ST_XP70_H
> +#define _ST_XP70_H
> +
> +#define XP70_MEM_MAX 2
> +#define XP70_MAX_CLK 4
> +#define NAME_SZ 10
> +
> +enum {
> +	DMEM,
> +	IMEM,
> +};
> +
> +/**
> + * struct xp70_mem - xp70 internal memory structure
> + * @cpu_addr: MPU virtual address of the memory region
> + * @bus_addr: Bus address used to access the memory region
> + * @dev_addr: Device address from Wakeup M3 view
> + * @size: Size of the memory region
> + */
> +struct xp70_mem {
> +	void __iomem *cpu_addr;
> +	phys_addr_t bus_addr;
> +	u32 dev_addr;
> +	size_t size;
> +	struct resource *io_res;
> +};
> +
> +/**
> + * struct st_xp70_rproc - XP70 slim core
> + * @rproc: rproc handle
> + * @pdev: pointer to platform device
> + * @mem: xp70 memory information
> + * @slimcore: xp70 slimcore regs
> + * @peri: xp70 peripheral regs
> + * @clks: xp70 clocks
> + */
> +struct st_xp70_rproc {
> +	struct rproc *rproc;
> +	struct platform_device *pdev;
> +	struct xp70_mem mem[XP70_MEM_MAX];
> +	void __iomem *slimcore;
> +	void __iomem *peri;
> +	struct clk *clks[XP70_MAX_CLK];
> +};
> +
> +struct rproc *xp70_rproc_alloc(struct platform_device *pdev, char *fw_name);
> +void xp70_rproc_put(struct st_xp70_rproc *xp70_rproc);
> +
> +#endif

Hi Peter

Applying this series on top of v4.6 kernel leads to the following 
compilation error due to patch 01/18 :

drivers/remoteproc/st_xp70_rproc.c: In function 'xp70_rproc_alloc':
drivers/remoteproc/st_xp70_rproc.c:291:2: error: implicit declaration of 
function 'rproc_get_elf_ops' [-Werror=implicit-function-declaration]
   elf_ops = rproc_get_elf_ops();
   ^
   LD [M]  drivers/remoteproc/remoteproc.o


Patrice


From sudipm.mukherjee at gmail.com  Fri May 27 02:00:48 2016
From: sudipm.mukherjee at gmail.com (Sudip Mukherjee)
Date: Fri, 27 May 2016 14:30:48 +0530
Subject: [PATCH] hwrng: stm32 - fix build warning
In-Reply-To: <7211115.EdoBLRGZ1i@wuerfel>
References: <1464007448-25395-1-git-send-email-sudipm.mukherjee@gmail.com>
 <6297051.TAxtzW5OIB@wuerfel> <5745085D.6000104@gmail.com>
 <7211115.EdoBLRGZ1i@wuerfel>
Message-ID: <57480CC0.80500@gmail.com>

On Wednesday 25 May 2016 03:36 PM, Arnd Bergmann wrote:
> On Wednesday, May 25, 2016 7:35:17 AM CEST Sudip Mukherjee wrote:
>> On Tuesday 24 May 2016 02:05 AM, Arnd Bergmann wrote:
>>> On Monday, May 23, 2016 6:14:08 PM CEST Sudip Mukherjee wrote:
>>>> We have been getting build warning about:
>>>> drivers/char/hw_random/stm32-rng.c: In function 'stm32_rng_read':
>>>> drivers/char/hw_random/stm32-rng.c:82:19: warning: 'sr' may be used
>>>>                                       uninitialized in this function
>>>>
>>>> On checking the code it turns out that sr can never be used
>>>> uninitialized as sr is getting initialized in the while loop and while
>>>> loop will always execute as the minimum value of max can be 32.
>>>> So just initialize sr to 0 while declaring it to silence the compiler.
>>>>
>>>> Signed-off-by: Sudip Mukherjee <sudip.mukherjee at codethink.co.uk>
>>>> ---
>>>
>snip>
>
> BTW, regarding your build infrastructure, I'd also recommend building
> with 'make -s' to make the output more compact.

travis is having a timeout and if there is no output from the build 
within a time limit then it will cancel the build. I can use the option 
if i can increase the timeout limit. I will have a look at the options. 
Thanks for the idea.

Regards
Sudip


From linux at armlinux.org.uk  Fri May 27 06:36:25 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Fri, 27 May 2016 14:36:25 +0100
Subject: [PATCH kexec-tools 18/32] arm: report if crash kernel is out of
 bounds
In-Reply-To: <CAHB_Guo-N0Coxj=fHBBM=QULMo6QK3uKbzOh15R6FCihGERjMA@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXTQ-0004ih-NN@e0050434b2927.dyn.arm.linux.org.uk>
 <CAHB_Guo-N0Coxj=fHBBM=QULMo6QK3uKbzOh15R6FCihGERjMA@mail.gmail.com>
Message-ID: <20160527133624.GL19428@n2100.arm.linux.org.uk>

On Fri, May 27, 2016 at 04:57:47PM +0530, Pratyush Anand wrote:
> On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
> > diff --git a/kexec/arch/arm/crashdump-arm.h b/kexec/arch/arm/crashdump-arm.h
> > index 2dbde04..7314960 100644
> > --- a/kexec/arch/arm/crashdump-arm.h
> > +++ b/kexec/arch/arm/crashdump-arm.h
> > @@ -9,6 +9,7 @@ extern "C" {
> >  #define DEFAULT_PAGE_OFFSET            (0xc0000000)
> >  #define KVBASE_MASK    (0x1ffffff)
> >  #define CRASH_MAX_MEMORY_RANGES        32
> > +#define ARM_MAX_VIRTUAL                UINT32_MAX
> 
> If I see a kernel code then a virtual address is always defined as
> unsigned long. So, shouldn't we use ULONG_MAX instead?

What is the definition of ULONG_MAX?  The maximum unsigned value that
can fit in an unsigned long quantity.

While unsigned long _may_ be 32-bit, it's a very round-about way to
say "the maximum virtual address is the maximum unsigned 32-bit value".
Hence why I'm using UINT32_MAX here - it's a tighter and accurate
macro for what we're wanting.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From aleksey.makarov at linaro.org  Fri May 27 06:41:47 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Fri, 27 May 2016 16:41:47 +0300
Subject: [PATCH v8 0/4] ACPI: parse the SPCR table
In-Reply-To: <1463749405-11640-1-git-send-email-aleksey.makarov@linaro.org>
References: <1463749405-11640-1-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <8e18166c-74c0-644c-cbd3-783fc716ab6b@linaro.org>

On 05/20/2016 04:03 PM, Aleksey Makarov wrote:
> 'ARM Server Base Boot Requirements' [1] mentions SPCR (Serial Port Console
> Redirection Table) [2] as a mandatory ACPI table that specifies the
> configuration of serial console.

Hi Russell,

Can you review these patches and consider ACKing the pl011 part [4/4]
please?  It had an ACK from Greg Kroah-Hartman in v7 but since then I
changed it a bit.

Who can I ask to accept the patch set for the upstream tree?

Thank you
Aleksey Makarov

> Move "earlycon" early_param handling to earlycon.c to parse this option once
> 
> Parse SPCR table, setup earlycon and register specified console.
> 
> Enable parsing this table on ARM64.  Earlycon should be set up as early as
> possible.  ACPI boot tables are mapped in
> arch/arm64/kernel/acpi.c:acpi_boot_table_init() called from setup_arch() and
> that's where we parse spcr.  So it has to be opted-in per-arch. When
> ACPI_SPCR_TABLE is defined initialization of DT earlycon is deferred until the
> DT/ACPI decision is done.
> 
> Implement console_match() for pl011.
> 
> Based on the work by Leif Lindholm [3]
> Thanks to Peter Hurley for explaining how this should work.
> 
> Should be applied to next-20160520
> Tested on QEMU and ThunderX.
> SPCR support is included in QEMU's ARM64 mach-virt since 2.4 release.
> 
> v8:
> - rebase to next-20160520
> - remove the patch "ACPICA: Headers: Add new constants for the DBG2 ACPI table"
>   as it have got to linux-next
> - add Acked-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>, Reviewed-by:
>   Peter Hurley <peter at hurleysoftware.com> (but see below)
> - fix the patch "serial: pl011: add console matching function".  The patch by
>   Christopher Covington [4] specifies that SBSA uart does 32-bit access to
>   registers and this breaks the match function.  In this series the function
>   was changed to match when SPCR specifies both mmio32 and mmio access.
>   I removed Acked-by: Greg from this patch because of these changes.
> 
> v7:
> https://lkml.kernel.org/g/1459431629-27934-1-git-send-email-aleksey.makarov at linaro.org
> - add Acked-by: Rob Herring for "of/serial: move earlycon early_param handling
>   to serial"
> - call DT earlycon initialization from the arch ACPI code, not from parse_spcr()
>   (Rafael J. Wysocki)
> - fix a few minor issues (Rafael J. Wysocki)
> 
> v6:
> https://lkml.kernel.org/g/1458823925-19560-1-git-send-email-aleksey.makarov at linaro.org
> - add documentation for parse_spcr() functioin (Yury Norov)
> - don't initialize err variable (Yury Norov)
> - add __initdata for the earlycon_init_is_deferred flag variable
> - rename the function exported in "of/serial: move earlycon early_param handling
>   to serial" to avoid clash with the function from arch/microblaze/kernel/prom.c
> - defer initialization of DT earlycon until DT/ACPI decision is made
>   (Rob Herring, Peter Hurley)
> - use snprintf instead of sprintf (Andy Shevchenko)
> - drop patch that adds EARLYCON_DECLARE for pl011 as EARLYCON_DECLARE is
>   equivalent to OF_EARLYCON_DECLARE for 4.6+ (Peter Hurley).  This means that
>   SPCR earlycon will not work on the kernels before 4.6
> 
> v5:
> https://lkml.kernel.org/g/1458643595-14719-1-git-send-email-aleksey.makarov at linaro.org
> - drop patch "serial: pl011: use ACPI SPCR to setup 32-bit access" because
>   it is ugly. Also because Christopher Covington came with a better solution [4]
> - remove error message when the table is not provided by ACPI (Andy Shevchenko)
> - rewrite spcr.c following the suggestions by Peter Hurley
> - add console_match() for pl011 in a separate patch
> - add EARLYCON_DECLARE for pl011 in a separate patch
> - add patch "of/serial: move earlycon early_param handling to serial" from
>   the GDB2 series
> 
> v4:
> https://lkml.kernel.org/g/1456747355-15692-1-git-send-email-aleksey.makarov at linaro.org
> - drop patch "ACPI: change __init to __ref for early_acpi_os_unmap_memory()"
>   ACPI developers work on a new API and asked not to do that.
>   Instead, use acpi_get_table_with_size()/early_acpi_os_unmap_memory() once
>   and cache the result. (Lv Zheng)
> - fix some style issues (Yury Norov)
> 
> v3:
> https://lkml.kernel.org/g/1455559532-8305-1-git-send-email-aleksey.makarov at linaro.org
> 
> Greg Kroah-Hartman did not like v2 so I have rewritten this patchset:
> 
> - drop acpi_match() member of struct console
> - drop implementations of this member for pl011 and 8250
> - drop the patch that renames some vars in printk.c as it is not needed anymore
> - drop patch that introduces system wide acpi_table_parse2().
>   Instead introduce a custom acpi_table_parse_spcr() in spcr.c
> 
> Instead of introducing a new match_acpi() member of struct console,
> this patchset introduces a new function acpi_console_check().
> This function is called when a new uart is registered at serial_core.c
> the same way OF code checks for console.  If the registered uart is the
> console specified by SPCR table, this function calls add_preferred_console()
> 
> The restrictions of this approach are:
> 
> - only serial consoles can be set up
> - only consoles specified by the memory/io address can be set up
>   (SPCR can specify devices by PCI id/PCI address)
> 
> v2:
> https://lkml.kernel.org/g/1455299022-11641-1-git-send-email-aleksey.makarov at linaro.org
> - don't use SPCR if user specified console in command line
> - fix initialization order of newcon->index = 0
> - rename some variables at printk.c (Joe Perches, Peter Hurley)
> - enable ACPI_SPCR_TABLE in a separate patch (Andy Shevchenko)
> - remove the retry loop for console registering (Peter Hurley).
>   Instead, obtain SPCR with acpi_get_table().  That works after
>   call to acpi_early_init() i. e. in any *_initcall()
> - describe design decision behind introducing acpi_match() (Peter Hurley)
> - fix compilation for x86 + ACPI (Graeme Gregory)
> - introduce DBG2 constants in a separate patch (Andy Shevchenko)
> - fix a typo in DBG2 constants (Andy Shevchenko)
> - add ACPI_DBG2_ARM_SBSA_32BIT constant (Christopher Covington)
> - add support for ACPI_DBG2_ARM_SBSA_* consoles (Christopher Covington)
> - add documentation for functions
> - add a patch that uses SPCR to find if SBSA serial driver should use 32-bit
>   accessor functions (Christopher Covington)
> - change __init to __ref for early_acpi_os_unmap_memory() in a separate patch
> - introduce acpi_table_parse2() in a separate patch
> - fix fetching the SPCR table early (Mark Salter)
> - add a patch from Mark Salter that introduces support for matching 8250-based
>   consoles
> 
> v1:
> https://lkml.kernel.org/g/1453722324-22407-1-git-send-email-aleksey.makarov at linaro.org
> 
> [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0044a/index.html
> [2] https://msdn.microsoft.com/en-us/library/windows/hardware/dn639132(v=vs.85).aspx
> [3] https://lkml.kernel.org/g/1441716217-23786-1-git-send-email-leif.lindholm at linaro.org
> [4] https://lkml.kernel.org/g/1457415800-8799-1-git-send-email-cov at codeaurora.org
> 
> Aleksey Makarov (3):
>   ACPI: parse SPCR and enable matching console
>   ARM64: ACPI: enable ACPI_SPCR_TABLE
>   serial: pl011: add console matching function
> 
> Leif Lindholm (1):
>   of/serial: move earlycon early_param handling to serial
> 
>  arch/arm64/Kconfig              |   1 +
>  arch/arm64/kernel/acpi.c        |  11 +++-
>  drivers/acpi/Kconfig            |   3 ++
>  drivers/acpi/Makefile           |   1 +
>  drivers/acpi/spcr.c             | 111 ++++++++++++++++++++++++++++++++++++++++
>  drivers/of/fdt.c                |  11 +---
>  drivers/tty/serial/amba-pl011.c |  56 ++++++++++++++++++++
>  drivers/tty/serial/earlycon.c   |  19 ++++++-
>  include/linux/acpi.h            |   6 +++
>  include/linux/of_fdt.h          |   2 +
>  include/linux/serial_core.h     |   6 +++
>  11 files changed, 214 insertions(+), 13 deletions(-)
>  create mode 100644 drivers/acpi/spcr.c
> 


From daniel.thompson at linaro.org  Fri May 27 06:46:58 2016
From: daniel.thompson at linaro.org (Daniel Thompson)
Date: Fri, 27 May 2016 14:46:58 +0100
Subject: [PATCH] hwrng: stm32: fix maybe uninitialized variable warning
In-Reply-To: <1464255297-21090-1-git-send-email-mcoquelin.stm32@gmail.com>
References: <1464255297-21090-1-git-send-email-mcoquelin.stm32@gmail.com>
Message-ID: <fc45dc72-6dd9-071c-5bc0-c2ee01b99511@linaro.org>

On 26/05/16 10:34, Maxime Coquelin wrote:
> This patch fixes the following warning:
> drivers/char/hw_random/stm32-rng.c: In function 'stm32_rng_read':
> drivers/char/hw_random/stm32-rng.c:82:19: warning: 'sr' may be used
>                                         uninitialized in this function
>
> Reported-by: Sudip Mukherjee <sudip.mukherjee at codethink.co.uk>
> Suggested-by: Arnd Bergmann <arnd at arndb.de>
> Cc: Daniel Thompson <daniel.thompson at linaro.org>

Reviewed-by: Daniel Thompson <daniel.thompson at linaro.org>


> Signed-off-by: Maxime Coquelin <mcoquelin.stm32 at gmail.com>
> ---
>  drivers/char/hw_random/stm32-rng.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
> index 92a810648bd0..63d84e6f1891 100644
> --- a/drivers/char/hw_random/stm32-rng.c
> +++ b/drivers/char/hw_random/stm32-rng.c
> @@ -69,8 +69,12 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
>  		}
>
>  		/* If error detected or data not ready... */
> -		if (sr != RNG_SR_DRDY)
> +		if (sr != RNG_SR_DRDY) {
> +			if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
> +					"bad RNG status - %x\n", sr))
> +				writel_relaxed(0, priv->base + RNG_SR);
>  			break;
> +		}
>
>  		*(u32 *)data = readl_relaxed(priv->base + RNG_DR);
>
> @@ -79,10 +83,6 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
>  		max -= sizeof(u32);
>  	}
>
> -	if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
> -		      "bad RNG status - %x\n", sr))
> -		writel_relaxed(0, priv->base + RNG_SR);
> -
>  	pm_runtime_mark_last_busy((struct device *) priv->rng.priv);
>  	pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv);
>
>



From aleksey.makarov at linaro.org  Fri May 27 06:46:42 2016
From: aleksey.makarov at linaro.org (Aleksey Makarov)
Date: Fri, 27 May 2016 16:46:42 +0300
Subject: [PATCH v2 0/5] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
In-Reply-To: <CAJZ5v0is7c833aQkRm-D+TwLM+eUYeKEAdLOOdrEdT-hrC_M1A@mail.gmail.com>
References: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
 <CAJZ5v0is7c833aQkRm-D+TwLM+eUYeKEAdLOOdrEdT-hrC_M1A@mail.gmail.com>
Message-ID: <c20f022c-af3e-74be-d78e-e219f14c27a3@linaro.org>



On 05/20/2016 12:22 AM, Rafael J. Wysocki wrote:
> On Thu, May 19, 2016 at 6:15 PM, Aleksey Makarov
> <aleksey.makarov at linaro.org> wrote:
>> This patchset adds support for ACPI_TABLE_UPGRADE for ARM64

Hi Catalin, Will,

Can you review these patches and consider ACKing the ARM64 part [5/5]
please?

Thank you
Aleksey Makarov

>>
>> These patches help with:
>>
>> 1). During development of a platform, it is much easier to debug
>> problems with tables if you can test replacement ones without having to
>> respin the firmware. In the server world, you usually don't have the
>> firmware source code, so to get it respun could be days-weeks even if
>> you are working with the authors closely. We have practically used this
>> feature on a number of platforms already and it will continue.
>>
>> 2). They empower (advanced) users and developers to work around problems
>> that they find on platforms. Sure, we want firmware to always be fixed
>> and working well, but it is better if folks have the tools.
>>
>> It's also required for parity with x86 functionality on servers as Redhat
>> use that method in their tooling.
>>
>> The patchset refactors the code introduced by the patches by Lv Zheng [1],
>> fixes access to the destination of new ACPI tables as suggested
>> by Mark Rutland [2] and enables the feature for ARM64
>>
>> It was first sent by Jon Masters [3] to linaro-acpi in December 2015
>>
>> Tested on QEMU (arm64 and x86) and ThunderX
>> Should be applied to next-20160519
>>
>> v2:
>> - add Acked-by: Lv Zheng <lv.zheng at intel.com>
>> - replace the original patch "ACPI: table upgrade: move early_initrd_acpi_init()
>>   to header file" with the patch "ACPI: table upgrade: refactor function
>>   definitions".  This new patch is just the original one rewritten following the
>>   suggestion by Lv Zheng to use initrd_start, inird_end directly in
>>   acpi_table_initrd_init().  It simplifies things noticeably.
>> - add Jon's explanations to the cover of the patchset and my explanations
>>   to "ACPI: ARM64: support for ACPI_TABLE_UPGRADE"
>> - introduce ARCH_HAS_ACPI_TABLE_UPGRADE in a separate patch (Mark Rutland)
>> - move arch-specific definition to an arch-specific header in a separate patch
>>   (Mark Rutland)
>>
>> v1:
>> https://lkml.kernel.org/g/1463486765-31827-1-git-send-email-aleksey.makarov at linaro.org
>>
>> [1] https://lkml.kernel.org/g/cover.1460340514.git.lv.zheng at intel.com
>> [2] https://lists.linaro.org/pipermail/linaro-acpi/2015-December/006101.html
>> [3] https://lists.linaro.org/pipermail/linaro-acpi/2015-December/006099.html
>>
>> Aleksey Makarov (4):
>>   ACPI: table upgrade: use cacheable map for tables
>>   ACPI: table upgrade: refactor function definitions
>>   ACPI: table upgrade: move arch-specific symbol to asm/acpi.h
>>   ACPI: table upgrade: introduce ARCH_HAS_ACPI_TABLE_UPGRADE
>>
>> Jon Masters (1):
>>   ACPI: ARM64: support for ACPI_TABLE_UPGRADE
>>
>>  arch/arm64/Kconfig            |  1 +
>>  arch/arm64/include/asm/acpi.h |  2 ++
>>  arch/arm64/kernel/setup.c     |  6 ++++--
>>  arch/x86/Kconfig              |  1 +
>>  arch/x86/include/asm/acpi.h   |  2 ++
>>  arch/x86/kernel/setup.c       |  9 +--------
>>  drivers/acpi/Kconfig          |  5 ++++-
>>  drivers/acpi/tables.c         | 23 +++++++++--------------
>>  include/linux/acpi.h          |  8 ++++++--
>>  9 files changed, 30 insertions(+), 27 deletions(-)
> 
> I'm fine with the series.
> 
> I can queue up patches [1-4/5] for 4.8, but I'll need an ACK from the
> ARM64 maintainers for the [5/5].
> 
> Thanks,
> Rafael
> 


From linux at roeck-us.net  Fri May 27 06:48:53 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 27 May 2016 06:48:53 -0700
Subject: [RFC PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <57480470.4000708@baylibre.com>
References: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
 <1464249112-13658-2-git-send-email-narmstrong@baylibre.com>
 <57470026.3000501@roeck-us.net> <57480470.4000708@baylibre.com>
Message-ID: <57485045.70707@roeck-us.net>

On 05/27/2016 01:25 AM, Neil Armstrong wrote:
[ ... ]
>>> +    data->wdt_dev.max_hw_heartbeat_ms = GXBB_WDT_TCNT_SETUP_MASK;
>>> +    data->wdt_dev.min_hw_heartbeat_ms = 1;
>>
>> Does the device require a minimum time between heartbeats ?
>> Just asking, because you violate it yourself below.
>>
>> If you want to set the minimum timeout, that would be min_timeout.
>
> Ok, these values are not very clear actually.
>
Hmmm .. yes, reading the description again, it doesn't really describe well
what it is doing. Essentially, min_hw_heartbeat_ms is enforced by the watchdog
core, and should be used if a watchdog hardware can not tolerate short intervals
between heartbeats. min_timeout is the minimum timeout value configurable from
user space.

>>> +    data->wdt_dev.timeout = DEFAULT_TIMEOUT;
>>> +    watchdog_set_drvdata(&data->wdt_dev, data);
>>> +
>>> +    watchdog_init_timeout(&data->wdt_dev, DEFAULT_TIMEOUT, &pdev->dev);
>>> +
>>
>> DEFAULT_TIMEOUT is unnecessary here. Since the default timeout is already set,
>> it makes the call useless.
>>
>>> +    ret = watchdog_register_device(&data->wdt_dev);
>>> +    if (ret)
>>> +        return ret;
>>> +
>>> +    /* Setup with 1ms timebase */
>>> +    writel(((clk_get_rate(data->clk) / 1000) & GXBB_WDT_CTRL_DIV_MASK) |
>>> +        GXBB_WDT_CTRL_EE_RESET |
>>> +        GXBB_WDT_CTRL_CLK_EN |
>>> +        GXBB_WDT_CTRL_CLKDIV_EN,
>>> +        data->reg_base + GXBB_WDT_CTRL_REG);
>>> +    meson_gxbb_wdt_set_timeout(&data->wdt_dev, data->wdt_dev.timeout);
>>
>> set_timeout already calls the ping function. Also, the functions should be called
>> prior to watchdog registration to avoid race conditions.
>>
>>> +    meson_gxbb_wdt_ping(&data->wdt_dev);
>>
>> This is unusual. If the watchdog can be already running, it might make sense
>> to tell the core about it (set WDOG_HW_RUNNING in the status field), so it
>> can send heartbeats until user space opens the device.
>
> Yes, since meson_gxbb_wdt_set_timeout() already ping, this is useless.
>

Not only that - if the watchdog _is_ already running at boot time, you should
really set WDOG_HW_RUNNING to let the watchdog core know. You status function
would come handy there.

	if (meson_gxbb_wdt_status(data))	// note the changed parameter
		set_bit(WDOG_HW_RUNNING, &data->wdt_dev.status);

Thanks,
Guenter



From linux at armlinux.org.uk  Fri May 27 06:58:20 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Fri, 27 May 2016 14:58:20 +0100
Subject: Help needed with kexec on arm64
In-Reply-To: <DB5PR04MB16887FF10CEA6AA9BF990F0DE6420@DB5PR04MB1688.eurprd04.prod.outlook.com>
References: <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org>
 <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160511005334.GA8417@linaro.org>
 <DB5PR04MB1688C3F122091109E6BD9B68E6740@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160519110307.GA4941@linaro.org>
 <DB5PR04MB16887FF10CEA6AA9BF990F0DE6420@DB5PR04MB1688.eurprd04.prod.outlook.com>
Message-ID: <20160527135820.GM19428@n2100.arm.linux.org.uk>

On Fri, May 27, 2016 at 11:51:03AM +0000, Harninder Rai wrote:
> Hello Takahiro Akashi,
> 
> Please see the following log which I was talking about in my last communication
> Any idea as to what could be wrong just when I move from RAM based rootfs to SD based rootfs?
> 
> > I did check /proc/iomem and everything looks there. This is very strange
> > since if I keep everything same and just move the rootfs from RAM based to
> > SD based, I start getting this issue.

You should be able to get more information by using kexec -d to enable
debug output... if the architecture is usefully printing stuff like
memory layouts etc.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From hdegoede at redhat.com  Fri May 27 06:59:23 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Fri, 27 May 2016 15:59:23 +0200
Subject: [linux-sunxi] Re: [PATCH 1/3] power: axp20x_usb: Add support for
 usb power-supply on axp22x pmics
In-Reply-To: <CAGb2v67N7R5U_+dZ4ZO+VuGKo6wbVALnrMq3=Ceec8J122LiDA@mail.gmail.com>
References: <1463248289-16456-1-git-send-email-hdegoede@redhat.com>
 <CAGb2v67N7R5U_+dZ4ZO+VuGKo6wbVALnrMq3=Ceec8J122LiDA@mail.gmail.com>
Message-ID: <c918e934-17f5-b393-5bee-ac04f838781e@redhat.com>

Hi,

On 16-05-16 09:07, Chen-Yu Tsai wrote:
> Hi,
>
> On Sun, May 15, 2016 at 1:51 AM, Hans de Goede <hdegoede at redhat.com> wrote:
>> The usb power-supply on the axp22x pmics is mostly identical to the
>> one on the axp20x pmics. One significant difference is that it cannot
>> measure / monitor the usb voltage / current.
>>
>> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
>> ---
>>  drivers/power/axp20x_usb_power.c | 99 +++++++++++++++++++++++++++++++---------
>>  1 file changed, 77 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/power/axp20x_usb_power.c b/drivers/power/axp20x_usb_power.c
>> index 421a90b..b3c1d8e 100644
>> --- a/drivers/power/axp20x_usb_power.c
>> +++ b/drivers/power/axp20x_usb_power.c
>> @@ -42,6 +42,7 @@
>>  #define AXP20X_VBUS_MON_VBUS_VALID     BIT(3)
>>
>>  struct axp20x_usb_power {
>> +       struct axp20x_dev *axp20x;
>>         struct regmap *regmap;
>>         struct power_supply *supply;
>>  };
>> @@ -85,7 +86,15 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
>>
>>                 switch (v & AXP20X_VBUS_CLIMIT_MASK) {
>>                 case AXP20X_VBUC_CLIMIT_100mA:
>> -                       val->intval = 100000;
>> +                       switch (power->axp20x->variant) {
>> +                       case AXP202_ID:
>> +                       case AXP209_ID:
>> +                               val->intval = 100000;
>> +                               break;
>> +                       default:
>> +                               val->intval = -1; /* No 100mA limit */
>> +                               break;
>> +                       }
>
> Given this hardware actually has DT bindings, I'd prefer matching against the
> compatible string, and keeping the variant part in axp20x_usb_power. You could
> still use the AXPXXX_ID constants, but just the ones used in the bindings. This
> could potentially make adding support for newer PMICs easier by only needing a
> compatible DT entry.

Fixed for v2 of this patch-set.

>>                         break;
>>                 case AXP20X_VBUC_CLIMIT_500mA:
>>                         val->intval = 500000;
>> @@ -122,16 +131,23 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
>>                         break;
>>                 }
>>
>> -               ret = regmap_read(power->regmap, AXP20X_USB_OTG_STATUS, &v);
>> -               if (ret)
>> -                       return ret;
>> +               val->intval = POWER_SUPPLY_HEALTH_GOOD;
>>
>> -               if (!(v & AXP20X_USB_STATUS_VBUS_VALID)) {
>> -                       val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
>> +               switch (power->axp20x->variant) {
>> +               case AXP202_ID:
>> +               case AXP209_ID:
>> +                       ret = regmap_read(power->regmap,
>> +                                         AXP20X_USB_OTG_STATUS, &v);
>> +                       if (ret)
>> +                               return ret;
>> +
>> +                       if (!(v & AXP20X_USB_STATUS_VBUS_VALID))
>> +                               val->intval =
>> +                                       POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
>> +                       break;
>> +               default:
>
> It seems like you'd return only POWER_SUPPLY_HEALTH_GOOD for AXP22x, even if
> VBUS is actually disconnected.

No, the following sits just above the code in the patch context above:

         case POWER_SUPPLY_PROP_HEALTH:
                 if (!(input & AXP20X_PWR_STATUS_VBUS_PRESENT)) {
                         val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
                         break;
                 }

Actually the break from above is part of the context, but the relevant
bits are missing.



>
>>                         break;
>>                 }
>> -
>> -               val->intval = POWER_SUPPLY_HEALTH_GOOD;
>>                 break;
>>         case POWER_SUPPLY_PROP_PRESENT:
>>                 val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);
>> @@ -156,6 +172,14 @@ static enum power_supply_property axp20x_usb_power_properties[] = {
>>         POWER_SUPPLY_PROP_CURRENT_NOW,
>>  };
>>
>> +static enum power_supply_property axp22x_usb_power_properties[] = {
>> +       POWER_SUPPLY_PROP_HEALTH,
>> +       POWER_SUPPLY_PROP_PRESENT,
>> +       POWER_SUPPLY_PROP_ONLINE,
>> +       POWER_SUPPLY_PROP_VOLTAGE_MIN,
>> +       POWER_SUPPLY_PROP_CURRENT_MAX,
>> +};
>> +
>>  static const struct power_supply_desc axp20x_usb_power_desc = {
>>         .name = "axp20x-usb",
>>         .type = POWER_SUPPLY_TYPE_USB,
>> @@ -164,13 +188,25 @@ static const struct power_supply_desc axp20x_usb_power_desc = {
>>         .get_property = axp20x_usb_power_get_property,
>>  };
>>
>> +static const struct power_supply_desc axp22x_usb_power_desc = {
>> +       .name = "axp20x-usb",
>> +       .type = POWER_SUPPLY_TYPE_USB,
>> +       .properties = axp22x_usb_power_properties,
>> +       .num_properties = ARRAY_SIZE(axp22x_usb_power_properties),
>> +       .get_property = axp20x_usb_power_get_property,
>> +};
>> +
>>  static int axp20x_usb_power_probe(struct platform_device *pdev)
>>  {
>>         struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
>>         struct power_supply_config psy_cfg = {};
>>         struct axp20x_usb_power *power;
>> -       static const char * const irq_names[] = { "VBUS_PLUGIN",
>> -               "VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID" };
>> +       static const char * const axp20x_irq_names[] = { "VBUS_PLUGIN",
>> +               "VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID", NULL };
>> +       static const char * const axp22x_irq_names[] = {
>> +               "VBUS_PLUGIN", "VBUS_REMOVAL", NULL };
>> +       static const char * const *irq_names;
>> +       const struct power_supply_desc *usb_power_desc;
>>         int i, irq, ret;
>>
>>         if (!of_device_is_available(pdev->dev.of_node))
>> @@ -185,31 +221,50 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
>>         if (!power)
>>                 return -ENOMEM;
>>
>> +       power->axp20x = axp20x;
>>         power->regmap = axp20x->regmap;
>>
>> -       /* Enable vbus valid checking */
>> -       ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
>> -                   AXP20X_VBUS_MON_VBUS_VALID, AXP20X_VBUS_MON_VBUS_VALID);
>> -       if (ret)
>> -               return ret;
>> +       switch (power->axp20x->variant) {
>> +       case AXP202_ID:
>> +       case AXP209_ID:
>> +               /* Enable vbus valid checking */
>> +               ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
>> +                                        AXP20X_VBUS_MON_VBUS_VALID,
>> +                                        AXP20X_VBUS_MON_VBUS_VALID);
>> +               if (ret)
>> +                       return ret;
>>
>> -       /* Enable vbus voltage and current measurement */
>> -       ret = regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
>> +               /* Enable vbus voltage and current measurement */
>> +               ret = regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
>>                         AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT,
>>                         AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT);
>> -       if (ret)
>> -               return ret;
>> +               if (ret)
>> +                       return ret;
>> +
>> +               usb_power_desc = &axp20x_usb_power_desc;
>> +               irq_names = axp20x_irq_names;
>> +               break;
>> +       case AXP221_ID:
>> +       case AXP223_ID:
>> +               usb_power_desc = &axp22x_usb_power_desc;
>> +               irq_names = axp22x_irq_names;
>> +               break;
>> +       default:
>> +               dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
>> +                       axp20x->variant);
>> +               return -EINVAL;
>> +       }
>
> As mentioned above, I'd prefer using the compatible string.

Fixed for v2.

Regards,

Hans



>
> Regards
> ChenYu
>
>>
>>         psy_cfg.of_node = pdev->dev.of_node;
>>         psy_cfg.drv_data = power;
>>
>> -       power->supply = devm_power_supply_register(&pdev->dev,
>> -                                       &axp20x_usb_power_desc, &psy_cfg);
>> +       power->supply = devm_power_supply_register(&pdev->dev, usb_power_desc,
>> +                                                  &psy_cfg);
>>         if (IS_ERR(power->supply))
>>                 return PTR_ERR(power->supply);
>>
>>         /* Request irqs after registering, as irqs may trigger immediately */
>> -       for (i = 0; i < ARRAY_SIZE(irq_names); i++) {
>> +       for (i = 0; irq_names[i]; i++) {
>>                 irq = platform_get_irq_byname(pdev, irq_names[i]);
>>                 if (irq < 0) {
>>                         dev_warn(&pdev->dev, "No IRQ for %s: %d\n",
>> --
>> 2.7.4
>>


From grygorii.strashko at ti.com  Fri May 27 07:23:00 2016
From: grygorii.strashko at ti.com (Grygorii Strashko)
Date: Fri, 27 May 2016 17:23:00 +0300
Subject: interrupts properties and API usage with GPIO controllers/Device
 Tree
In-Reply-To: <57461CDC.603@gmail.com>
References: <57461CDC.603@gmail.com>
Message-ID: <57485844.3050807@ti.com>

On 05/26/2016 12:45 AM, Florian Fainelli wrote:
> Hi Linus, Gregory,
> 
> Recently came across an use case that looks like the following:
> 
> gpio0: gpio at deadbeef {
> 	compatible = "brcm,brcmstb-gpio";
> 	#interrrupt-cells = <2>;
> 	#gpio-cells = <2>;
> 	gpio-controller;
> 	interrupt-controller;
> 	...
> };
> 
> test at cafeb00b {
> 	interrupt-parent = <&gpio0>;
> 	interrupts = <99 3>;
> };
> 
> The driver consuming the test node's interrupts property tries to get
> the interrupt by using platform_get_irq() or of_irq_parse_and_map() and
> in the case of the gpio-brcmstb.c, this fails because the interrupt is
> out of range  as flagged by kernel/irq/irqdomain.c::irq_domain_associate.
> 
> Unlike other GPIO provider drivers gpio-brcmstb.c, this driver registers
> one gpiolib irqchip per each of its banks, and still uses the generic
> map/unmap functions for its irq_domain_ops, so there is no way we can
> provide a valid mapping outside of the gpio_to_irq() function
> unfortunately since gpiochip_irq_map() does

And this is not working :( Each irq_domain has to be assigned to separate DT node,
otherwise IRQ mapping will not work (most probably will work, but only for bank 0)

Such kind of GPIO controllers are incompatible with gpiochip_irqchip_add() and required
to have one, common irq_domain for all internal banks.

like 	irq_domain = irq_domain_add_xxx(dev->of_node, ngpio, irq, 0,
							&davinci_gpio_irq_ops,
							chips);

ngpio = 120 in case of bcm7445.dtsi
and custom .map() function need to be implemented 

More or less similar situation is with davinci_gpio.

> 
> So here are a few questions for either of you:
> 
> - is this a valid API and Device Tree use case: call
> of_irq_parse_and_map on an "interrupts" property which has not been
> acquired using the GPIO API and then gpio_to_irq? 

this is valid use case

> While gpio_to_irq()
> works, are not we losing the second specifier in the interrupt cells
> about what kind of interrupt type this is?
> 
> - would it be acceptable to export gpiochip_irq_map and
> gpiochip_irq_export to make them accessible as helpers so we could just
> wrap things a bit around or should I just open code the same things and
> allow gpiochip_irqchip_add to be passed custom irq_domain_ops for instance?
> 

Yah, custom implementation might be needed.

Another interesting, related question (as for me) is "Is there a limitation
 that gpio bank can have only 32 GPIO pins (from gpiolib point of view)?" 

-- 
regards,
-grygorii


From andrew at lunn.ch  Fri May 27 07:40:45 2016
From: andrew at lunn.ch (Andrew Lunn)
Date: Fri, 27 May 2016 16:40:45 +0200
Subject: v7_dma_inv_range performance/high expense
Message-ID: <20160527144045.GB20214@lunn.ch>

Hi folks

I have an imx6q, which is a quad core v7 processor. Attached to it via
pcie i have an intel i210 Ethernet controller.

When the ethernet is transmitting, i can get gigabit line rate, and
use one core to about 35% of one core. When receiving, i get around
700Mbps and ksoftirqd/0 is 98% loading a core.

Using perf to profile the ksoftirqd/0 pid is see:

  46.38%  [kernel]  [k] v7_dma_inv_range
  21.25%  [kernel]  [k] l2c210_inv_range
  10.90%  [kernel]  [k] igb_poll
   1.69%  [kernel]  [k] dma_cache_maint_page
   1.27%  [kernel]  [k] eth_type_trans
   1.20%  [kernel]  [k] skb_add_rx_frag

Digging deeper into v7_dma_inv_range i see:

           801182c0 <v7_dma_inv_range>:
           v7_dma_inv_range():
  0.26       mrc    15, 0, r3, cr0, cr0, {1}
  0.07       lsr    r3, r3, #16
             and    r3, r3, #15
  0.04       mov    r2, #4
             lsl    r2, r2, r3
  0.04       sub    r3, r2, #1
             tst    r0, r3
  0.02       bic    r0, r0, r3
  0.03       dsb    sy
  3.01       mcrne  15, 0, r0, cr7, cr14, {1}
  0.54       tst    r1, r3
             bic    r1, r1, r3
  0.08       mcrne  15, 0, r1, cr7, cr14, {1}
  3.82 34:   mcr    15, 0, r0, cr7, cr6, {1}
 88.32       add    r0, r0, r2
             cmp    r0, r1
  1.97       bcc    34
  0.43       dsb    st
  1.37       bx     lr

I'm assuming perf is off by one here, and the add is not taking 88.32%
of the load, rather it is the mcr instruction before it.

The original code in arch/arm/mm/cache-v7.S  says:

        mcr     p15, 0, r0, c7, c6, 1           @ invalidate D / U line

I don't get why a cache invalidate instruction should be so expensive.
It is just throwing away the contents of the cache line, not flushing
it out to DRAM. Should i trust perf? Is a cache invalidate really so
expensive? Or am i totally missing something here?

Thanks
	Andrew


From linux at armlinux.org.uk  Fri May 27 07:58:11 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Fri, 27 May 2016 15:58:11 +0100
Subject: v7_dma_inv_range performance/high expense
In-Reply-To: <20160527144045.GB20214@lunn.ch>
References: <20160527144045.GB20214@lunn.ch>
Message-ID: <20160527145810.GN19428@n2100.arm.linux.org.uk>

On Fri, May 27, 2016 at 04:40:45PM +0200, Andrew Lunn wrote:
>   0.26       mrc    15, 0, r3, cr0, cr0, {1}
>   0.07       lsr    r3, r3, #16
>              and    r3, r3, #15
>   0.04       mov    r2, #4
>              lsl    r2, r2, r3
>   0.04       sub    r3, r2, #1
>              tst    r0, r3
>   0.02       bic    r0, r0, r3
>   0.03       dsb    sy
>   3.01       mcrne  15, 0, r0, cr7, cr14, {1}
>   0.54       tst    r1, r3
>              bic    r1, r1, r3
>   0.08       mcrne  15, 0, r1, cr7, cr14, {1}
>   3.82 34:   mcr    15, 0, r0, cr7, cr6, {1}
>  88.32       add    r0, r0, r2
>              cmp    r0, r1
>   1.97       bcc    34
>   0.43       dsb    st
>   1.37       bx     lr
> 
> I'm assuming perf is off by one here, and the add is not taking 88.32%
> of the load, rather it is the mcr instruction before it.

Possibly, but I'm not sure that merely subtracting four from the PC (or
two for thumb) would be the correct solution - what if we've branched
to a function and we've taken the exception with the PC pointing at the
very first instruction - we'd wind it back by one place, and it will be
pointing at the instruction before the function (not the previously
executed instruction.)

So, I think folk just have to get used to reading ARM perf traces
differently[*] - the PC points at the _next_ instruction to be executed
after the exception which recorded the event returns.

* - maybe it is the same as x86, I've never looked at an x86 perf trace,
but I don't see that it would be any different.

> The original code in arch/arm/mm/cache-v7.S  says:
> 
>         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D / U line
> 
> I don't get why a cache invalidate instruction should be so expensive.
> It is just throwing away the contents of the cache line, not flushing
> it out to DRAM. Should i trust perf? Is a cache invalidate really so
> expensive? Or am i totally missing something here?

If we're being asked to do a large region, then flushing the cache one
line at a time _is_ expensive.  There's no real getting away from that.
The only thing that saves you from having to do that is having DMA
coherency with the cache, something which I've pointed out in some
meetings I've had with ARM over the years.

The response was along the lines that you'd expect... It's only
relatively recently, with SMP (which needs coherency) that ARM systems
have had a coherent bus, and even systems which have it, there's
relatively few SoCs which make use of it.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From panand at redhat.com  Fri May 27 08:07:41 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 27 May 2016 20:37:41 +0530
Subject: [PATCH kexec-tools 12/32] kexec: add helper to exlude a region
 from a set of memory ranges
In-Reply-To: <20160526085638.GF19428@n2100.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSv-0004i3-Gi@e0050434b2927.dyn.arm.linux.org.uk>
 <CAHB_Guo_ozXhAnkGk_NrdBME2fSYDoKTHwu3kLBvsrmbwxOdww@mail.gmail.com>
 <20160526085638.GF19428@n2100.arm.linux.org.uk>
Message-ID: <CAHB_GuoRuQwhe-bXKAzmjOn=3=7KQ7LtT2JTooO1kjx+V3VgpQ@mail.gmail.com>

On Thu, May 26, 2016 at 2:26 PM, Russell King - ARM Linux
<linux at armlinux.org.uk> wrote:
> On Wed, May 25, 2016 at 01:30:44PM +0530, Pratyush Anand wrote:
>> On Tue, May 3, 2016 at 3:52 PM, Russell King <rmk at arm.linux.org.uk> wrote:
>> > +int mem_regions_exclude(struct memory_ranges *ranges,
>> > +                       const struct memory_range *range)
>> > +{
>> > +       int i;
>> > +
>> > +       for (i = 0; i < ranges->size; i++) {
>> > +               struct memory_range *r = ranges->ranges + i;
>> > +
>> > +               /*
>> > +                * We assume that crash area is fully contained in
>> > +                * some larger memory area.
>> > +                */
>> > +               if (r->start <= range->start && r->end >= range->end) {
>> > +                       if (r->start == range->start) {
>> > +                               /* Shrink the start of this memory range */
>> > +                               r->start = range->end + 1;
>> > +                       } else if (r->end == range->end) {
>> > +                               /* Shrink the end of this memory range */
>> > +                               r->end = range->start - 1;
>>
>> What if r->start == range->start) && (r->end == range->end)?
>
> I suppose that could happen, so what about this patch on top (untested).

I think, it should be fine, except.....

> This isn't something I'd be able to test on real hardware, it needs a
> separate test-suite to be written to do modular testing...
>
>  kexec/mem_regions.c | 94 +++++++++++++++++++++++++++++++----------------------
>  1 file changed, 55 insertions(+), 39 deletions(-)
>
> diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c
> index c6ba942..4e7061b 100644
> --- a/kexec/mem_regions.c
> +++ b/kexec/mem_regions.c
> @@ -29,6 +29,50 @@ void mem_regions_sort(struct memory_ranges *ranges)
>  }
>
>  /**
> + * mem_regions_add() - add a memory region to a set of ranges
> + * @ranges: ranges to add the memory region to
> + * @max: maximum number of entries in memory region
> + * @base: base address of memory region
> + * @length: length of memory region in bytes
> + * @type: type of memory region
> + *
> + * Add the memory region to the set of ranges, and return %0 if successful,
> + * or %-1 if we ran out of space.
> + */
> +int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
> +                    unsigned long long length, int type)
> +{
> +       struct memory_range *range;
> +
> +       if (ranges->size >= ranges->max_size)
> +               return -1;
> +
> +       range = ranges->ranges + ranges->size++;
> +       range->start = base;
> +       range->end = base + length - 1;
> +       range->type = type;
> +
> +       return 0;
> +}
> +
> +static void mem_regions_remove(struct memory_ranges *ranges, int index)
> +{
> +       int tail_entries;
> +
> +       /* we are assured to have at least one entry */
> +       ranges->size -= 1;
> +
> +       /* if we have following entries, shuffle them down one place */
> +       tail_entries = ranges->size - index;
> +       if (tail_entries)
> +               memmove(ranges->ranges + index, ranges->ranges + index + 1,
> +                       tail_entries * sizeof(*ranges->ranges));
> +
> +       /* zero the new tail entry */
> +       memset(ranges->ranges + ranges->size, 0, sizeof(*ranges->ranges));
> +}
> +
> +/**
>   * mem_regions_exclude() - excludes a memory region from a set of memory ranges
>   * @ranges: memory ranges to exclude the region from
>   * @range: memory range to exclude
> @@ -40,7 +84,7 @@ void mem_regions_sort(struct memory_ranges *ranges)
>  int mem_regions_exclude(struct memory_ranges *ranges,
>                         const struct memory_range *range)
>  {
> -       int i;
> +       int i, ret;
>
>         for (i = 0; i < ranges->size; i++) {
>                 struct memory_range *r = ranges->ranges + i;
> @@ -51,25 +95,25 @@ int mem_regions_exclude(struct memory_ranges *ranges,
>                  */
>                 if (r->start <= range->start && r->end >= range->end) {
>                         if (r->start == range->start) {
> -                               /* Shrink the start of this memory range */
> -                               r->start = range->end + 1;
> +                               if (r->end == range->end)
> +                                       /* Remove this entry */
> +                                       mem_regions_remove(ranges, i);
> +                               else
> +                                       /* Shrink the start of this memory range */
> +                                       r->start = range->end + 1;
>                         } else if (r->end == range->end) {
>                                 /* Shrink the end of this memory range */
>                                 r->end = range->start - 1;
>                         } else {
> -                               struct memory_range *new;
> -
>                                 /*
>                                  * Split this area into 2 smaller ones and
>                                  * remove excluded range from between. First
>                                  * create new entry for the remaining area.
>                                  */
> -                               if (ranges->size >= ranges->max_size)
> -                                       return -1;
> -
> -                               new = ranges->ranges + ranges->size++;
> -                               new->start = range->end + 1;
> -                               new->end = r->end;
> +                               ret = mem_regions_add(ranges, range->end + 1,
> +                                                     r->end, 0);

3rd argument should be (r->end - range->end)

> +                               if (ret < 0)
> +                                       return ret;
>
>                                 /*
>                                  * Update this area to end before excluded
> @@ -82,31 +126,3 @@ int mem_regions_exclude(struct memory_ranges *ranges,
>         }
>         return 0;
>  }
> -
> -/**
> - * mem_regions_add() - add a memory region to a set of ranges
> - * @ranges: ranges to add the memory region to
> - * @max: maximum number of entries in memory region
> - * @base: base address of memory region
> - * @length: length of memory region in bytes
> - * @type: type of memory region
> - *
> - * Add the memory region to the set of ranges, and return %0 if successful,
> - * or %-1 if we ran out of space.
> - */
> -int mem_regions_add(struct memory_ranges *ranges, unsigned long long base,
> -                    unsigned long long length, int type)
> -{
> -       struct memory_range *range;
> -
> -       if (ranges->size >= ranges->max_size)
> -               return -1;
> -
> -       range = ranges->ranges + ranges->size++;
> -       range->start = base;
> -       range->end = base + length - 1;
> -       range->type = type;
> -
> -       return 0;
> -}
> -
>
>
> --
> RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.

~Pratyush


From linux at armlinux.org.uk  Fri May 27 08:12:08 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Fri, 27 May 2016 16:12:08 +0100
Subject: [PATCH kexec-tools 12/32] kexec: add helper to exlude a region
 from a set of memory ranges
In-Reply-To: <CAHB_GuoRuQwhe-bXKAzmjOn=3=7KQ7LtT2JTooO1kjx+V3VgpQ@mail.gmail.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSv-0004i3-Gi@e0050434b2927.dyn.arm.linux.org.uk>
 <CAHB_Guo_ozXhAnkGk_NrdBME2fSYDoKTHwu3kLBvsrmbwxOdww@mail.gmail.com>
 <20160526085638.GF19428@n2100.arm.linux.org.uk>
 <CAHB_GuoRuQwhe-bXKAzmjOn=3=7KQ7LtT2JTooO1kjx+V3VgpQ@mail.gmail.com>
Message-ID: <20160527151208.GO19428@n2100.arm.linux.org.uk>

On Fri, May 27, 2016 at 08:37:41PM +0530, Pratyush Anand wrote:
> On Thu, May 26, 2016 at 2:26 PM, Russell King - ARM Linux
> <linux at armlinux.org.uk> wrote:
> > -                               new = ranges->ranges + ranges->size++;
> > -                               new->start = range->end + 1;
> > -                               new->end = r->end;
> > +                               ret = mem_regions_add(ranges, range->end + 1,
> > +                                                     r->end, 0);
> 
> 3rd argument should be (r->end - range->end)

Yes indeed, thanks for pointing that out.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From narmstrong at baylibre.com  Fri May 27 08:17:48 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 27 May 2016 17:17:48 +0200
Subject: [RFC PATCH 0/2] scpi: Add SCPI framework to handle vendors
 variants
In-Reply-To: <574802AF.2080909@baylibre.com>
References: <1464255491-18503-1-git-send-email-narmstrong@baylibre.com>
 <57472450.4000709@arm.com> <574802AF.2080909@baylibre.com>
Message-ID: <5748651C.9060901@baylibre.com>

On 05/27/2016 10:17 AM, Neil Armstrong wrote:
> Hi,
> On 05/26/2016 06:29 PM, Sudeep Holla wrote:
>> Hi Neil,
>>> To keep the spirit of the SCPI interface, add a thin "register" layer to get
>>> the ops from the parent node and switch the drivers using the ops to use
>>> the new of_scpi_ops_get() call.
>>>
>>
>> All I can see is that you share the code to register such drivers which
>> is hardly anything. It's hard to say all drivers use same protocol or
>> interface after this change. I may be missing to see something here so
>> it would be easy to appreciate/review this change with one user of this.
> 
> I'm actually working on a "SCPI" implementation from Amlogic for their arm64 platform,
> and their implementation is slightly different but enough to need a separate driver.
> 
> For instance, the differences are :
> - they do not implement virtual channels
> - they pass the command word by the mailbox interface
> - they use the "sender id" to group the command in a sort of "class"
> - the payload size is shifted by 20 instead of 16
> - the command word is not in the SRAM, so we cannot use a rx command queue, only a single command by channel at a single time
> - the command indexes are slightly shifted
> - in clk_set_value, "rate" is first instead of last entry
> - in sensor_value, they only use a 32bit entry
> - some commands are only accepted on the high priority channel, the others only on the low priority
> - MAX_DVFS_DOMAINS is 3 instead of 8
> - MAX_DVFS_OPPS is 16 instead of 8
> 
> But, It's still a "SCPI" interface by design and usage because :
> - they implement 90% of the same commands, in the same way
> - the usage is exactly the same and architecture is similar
> - they use the same error code scheme
> 
> Finally, it would be stupid to add an exact copy of the scpi-sensors and scpi-clocks !
> The scpi-cpufreq is another story since they only have a single A53 cluster, it's not adapted.
> 
> This is why I wrote a very thin layer, and it can also clean up the arm_scpi and the scpi driver to use a cleaner registry interface.
> It would also be a good point to add a private_data to the ops and pass it to the scpi callbacks, to completely remove the global variables.
> 
> I found an issue with scpi-cpufreq, since the device is created by the scpi-clocks probe, it does not have a proper node and my current of_scpi_ops_get won't work...
> The scpi-cpufreq should have a proper DT node and use the deffered probe to register after the scpi-clocks.

Actually I managed to make the Amlogic SCPI SCPI implementation work using a separate driver and the registry layer just fine.
The cpufreq works, like the scpi-dvfs-clocks and the scpi-hwmon drivers.

You can have a look at my github tree :
https://github.com/superna9999/linux/compare/28165ec7a99be98123aa89540bf2cfc24df19498...superna9999:amlogic/v4.7/scpi+fw-v0

The Amlogic SCPI implementation lies on top of this RFC patchset.
The current patchset need a fix in scpi-hwmon and for scpi-cpufreq but it works like a charm.

Neil



From narmstrong at baylibre.com  Fri May 27 08:24:55 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Fri, 27 May 2016 17:24:55 +0200
Subject: [RFC PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <57485045.70707@roeck-us.net>
References: <1464249112-13658-1-git-send-email-narmstrong@baylibre.com>
 <1464249112-13658-2-git-send-email-narmstrong@baylibre.com>
 <57470026.3000501@roeck-us.net> <57480470.4000708@baylibre.com>
 <57485045.70707@roeck-us.net>
Message-ID: <574866C7.1090201@baylibre.com>

On 05/27/2016 03:48 PM, Guenter Roeck wrote:
> On 05/27/2016 01:25 AM, Neil Armstrong wrote:
> [ ... ]
>>>> +    data->wdt_dev.max_hw_heartbeat_ms = GXBB_WDT_TCNT_SETUP_MASK;
>>>> +    data->wdt_dev.min_hw_heartbeat_ms = 1;
>>>
>>> Does the device require a minimum time between heartbeats ?
>>> Just asking, because you violate it yourself below.
>>>
>>> If you want to set the minimum timeout, that would be min_timeout.
>>
>> Ok, these values are not very clear actually.
>>
> Hmmm .. yes, reading the description again, it doesn't really describe well
> what it is doing. Essentially, min_hw_heartbeat_ms is enforced by the watchdog
> core, and should be used if a watchdog hardware can not tolerate short intervals
> between heartbeats. min_timeout is the minimum timeout value configurable from
> user space.
OK, I'll switch to min_timeout = 1.

> 

[ ... ]

>>>
>>> This is unusual. If the watchdog can be already running, it might make sense
>>> to tell the core about it (set WDOG_HW_RUNNING in the status field), so it
>>> can send heartbeats until user space opens the device.
>>
>> Yes, since meson_gxbb_wdt_set_timeout() already ping, this is useless.
>>
> 
> Not only that - if the watchdog _is_ already running at boot time, you should
> really set WDOG_HW_RUNNING to let the watchdog core know. You status function
> would come handy there.
> 
>     if (meson_gxbb_wdt_status(data))    // note the changed parameter
>         set_bit(WDOG_HW_RUNNING, &data->wdt_dev.status);
Yes, it can be handy.

I will push this feature in a next version, I'll stick to a simpler behavior and check
if it would be running before the kernel starts.

Thanks,
Neil

> 
> Thanks,
> Guenter
> 



From andrew at lunn.ch  Fri May 27 08:38:37 2016
From: andrew at lunn.ch (Andrew Lunn)
Date: Fri, 27 May 2016 17:38:37 +0200
Subject: v7_dma_inv_range performance/high expense
In-Reply-To: <20160527145810.GN19428@n2100.arm.linux.org.uk>
References: <20160527144045.GB20214@lunn.ch>
 <20160527145810.GN19428@n2100.arm.linux.org.uk>
Message-ID: <20160527153837.GE20214@lunn.ch>

> > The original code in arch/arm/mm/cache-v7.S  says:
> > 
> >         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D / U line
> > 
> > I don't get why a cache invalidate instruction should be so expensive.
> > It is just throwing away the contents of the cache line, not flushing
> > it out to DRAM. Should i trust perf? Is a cache invalidate really so
> > expensive? Or am i totally missing something here?
> 
> If we're being asked to do a large region, then flushing the cache one
> line at a time _is_ expensive.

Hi Russell

It is a 2K block, i.e. space for one ethernet frame.

You say flush here. Yet we are not flushing, we are invalidating.

What we logically want to happen is that the DMA engine copies the
packet into DRAM. Once complete we invalidate the cache, and the next
read instruction would cause a cache miss and the ethernet frame is
pulled in.

Looking at these numbers, the invalidate is much more expensive than
the cache miss.

You say one line at a time is expensive. Do you have any idea where
the break even is for invalidating the whole cache? Having said that,
v7_invalidate_l1 seems to be doing it a line at a time as well.

Thanks
	Andrew


From robh at kernel.org  Fri May 27 08:41:59 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 27 May 2016 10:41:59 -0500
Subject: [STLinux Kernel] [PATCH 02/11] drivers: clk: st: Add clock
 propagation for audio clocks
In-Reply-To: <5747F5E8.5030300@st.com>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
 <1463560892-7209-3-git-send-email-gabriel.fernandez@linaro.org>
 <20160525172409.GA27913@rob-hp-laptop>
 <CAG374jDTCJfZB+PuAnggjXhbcd3NjJqrESpe_EnMniCAeoph9A@mail.gmail.com>
 <CAL_JsqLOG4P0H+HkQ3mJhfibatuV2T51KqOn-+U+LK8WUx7QgA@mail.gmail.com>
 <5746F486.602@st.com>
 <CAL_JsqLeD8uTmMYLFZ5Sh9=JV5s1xthvruXL-W=c=zcVS=G-ZA@mail.gmail.com>
 <5747F5E8.5030300@st.com>
Message-ID: <20160527154159.GA17818@rob-hp-laptop>

On Fri, May 27, 2016 at 09:23:20AM +0200, loic pallardy wrote:
> 
> 
> On 05/26/2016 03:20 PM, Rob Herring wrote:
> >On Thu, May 26, 2016 at 8:05 AM, loic pallardy <loic.pallardy at st.com> wrote:
> >>
> >>
> >>On 05/26/2016 02:46 PM, Rob Herring wrote:
> >>>
> >>>On Thu, May 26, 2016 at 4:49 AM, Gabriel Fernandez
> >>><gabriel.fernandez at linaro.org> wrote:
> >>>>
> >>>>On 25 May 2016 at 19:24, Rob Herring <robh at kernel.org> wrote:
> >>>>>
> >>>>>
> >>>>>On Wed, May 18, 2016 at 10:41:23AM +0200, Gabriel Fernandez wrote:
> >>>>>>
> >>>>>>This patch allows fine tuning of the quads FS for audio clocks
> >>>>>>accuracy.
> >>>>>>

> >>>
> >>>That is no different and suffers the same point I raised. It requires
> >>>updating the DT for any clock configuration change or enhancement.
> >>>
> >>Agree with you, DT update is needed as soon as a clock configuration should
> >>be changed. This is due to STiH clock driver design based on DT description
> >>of SoC clock tree.
> >>
> >>This clock driver was accepted 2 years ago. At the time being there was
> >>discussion about clock tree description location: driver or DT.
> >>Bad choice was done for this driver...
> >>
> >>If we decide to redesign STiH clock driver using in-driver clock tree
> >>description, this will modify STiH clock DT nodes description and so break
> >>DT backward compatibility.
> >>
> >>What's from your pov the best option?
> >
> >You can break it once or every time you need a clock change. I'd go
> >with the former. Maybe more specific compatible strings throughout
> >alone would be enough rather than a flag day changing the binding.
> 
> So if I understand you correctly, main issue is d0 and d2 signification.
> d0 and d2 are indeed location of the flexgen in the SoC. But that's right
> flexgen are dedicated to clocks generation for features (system, audio,
> video).
> What about "st,flexgen-audio" and "st,flexgen-video"?

It is not so much the name of these 2, but whether there are other cases 
for different clock nodes that could need the same thing. If so, update 
them all now rather than 1 by 1.

Rob


From robh at kernel.org  Fri May 27 08:44:57 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 27 May 2016 10:44:57 -0500
Subject: [PATCH v4 04/18] dmaengine: st_fdma: Add STMicroelectronics FDMA
 DT binding documentation
In-Reply-To: <1464192412-16386-6-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
 <1464192412-16386-6-git-send-email-peter.griffin@linaro.org>
Message-ID: <20160527154457.GA20370@rob-hp-laptop>

On Wed, May 25, 2016 at 05:06:38PM +0100, Peter Griffin wrote:
> This patch adds the DT binding documentation for the FDMA constroller
> found on STi based chipsets from STMicroelectronics.
> 
> Signed-off-by: Ludovic Barre <ludovic.barre at st.com>
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
>  Documentation/devicetree/bindings/dma/st_fdma.txt | 87 +++++++++++++++++++++++
>  1 file changed, 87 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/dma/st_fdma.txt

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


From robh at kernel.org  Fri May 27 08:47:03 2016
From: robh at kernel.org (Rob Herring)
Date: Fri, 27 May 2016 10:47:03 -0500
Subject: [PATCH v4 10/18] ASoC: sti: Update DT example to match the
 driver code
In-Reply-To: <1464192412-16386-12-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
 <1464192412-16386-12-git-send-email-peter.griffin@linaro.org>
Message-ID: <20160527154703.GA21568@rob-hp-laptop>

On Wed, May 25, 2016 at 05:06:44PM +0100, Peter Griffin wrote:
> uniperiph-id, version and mode are ST specific bindings and
> need the 'st,' prefix. Update the examples, as otherwise copying
> them yields a runtime error parsing the DT node.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> Cc: arnaud.pouliquen at st.com
> Cc: broonie at kernel.org
> ---
>  .../devicetree/bindings/sound/st,sti-asoc-card.txt   | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)

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


From ddaney at caviumnetworks.com  Fri May 27 09:07:02 2016
From: ddaney at caviumnetworks.com (David Daney)
Date: Fri, 27 May 2016 09:07:02 -0700
Subject: [PATCH 2/3] of/numa: fix a memory@ dt node can only contains
 one memory block
In-Reply-To: <5747C0BF.505@huawei.com>
References: <1464230639-9852-1-git-send-email-thunder.leizhen@huawei.com>
 <1464230639-9852-2-git-send-email-thunder.leizhen@huawei.com>
 <20160526131345.GA12024@rob-hp-laptop> <5747C0BF.505@huawei.com>
Message-ID: <574870A6.40003@caviumnetworks.com>

On 05/26/2016 08:36 PM, Leizhen (ThunderTown) wrote:
[...]		continue;
> Hi, everybody:
>      If some "memory" node contains "numa-node-id", but some others missed. Can we simply ignored it?
> I think we should break out too, and faking to only have node0.


I think if some "memory" nodes contain "numa-node-id" and others do not, 
then you have a defective device tree.  In this case I think we must 
continue with the existing behavior, and indicate failure.  This will 
cause the architecture specific NUMA code to disable NUMA and force 
everything onto a singl pseudo-NUMA-node.

I doubt there is anything to be gained by guessing which NUMA node 
orphaned "memory" nodes belong to.

>
>> 		else if (r)
>> 			/* some other error */
>> 			break;
>>
>> 		r = of_address_to_resource(np, 0, &rsrc);
>> 		for (i = 0; !r; i++, r = of_address_to_resource(np, i,
>
> But r(non-zero) is just break this loop, the original is break the outer for (;;) loop
>
> How about as below?
>
> 	for_each_node_by_type(np, "memory") {
> 		... ...
>
> 		for (i = 0; !of_address_to_resource(np, i, &rsrc); i++) {
>                          r = numa_add_memblk(nid, rsrc.start,
>                                              rsrc.end - rsrc.start + 1);
>                          if (r)
>                                  goto finished;
>                  }
>
> 		if (!i)
> 			pr_err("NUMA: bad reg property in memory node\n");
> 	}
>
> finished:
> 	
>
>> &rsrc)) {
>> 			r = numa_add_memblk(nid, rsrc.start,
>> 				    rsrc.end - rsrc.start + 1);
>> 		}
>> 	}
>> 	of_node_put(np);
>>
>> 	return r;
>>
>>
>> Perhaps with a "if (!i && r) pr_err()" for an error message at the end.
>>
>> Rob
>>
>> .
>>
>



From peter.griffin at linaro.org  Fri May 27 09:13:29 2016
From: peter.griffin at linaro.org (Peter Griffin)
Date: Fri, 27 May 2016 17:13:29 +0100
Subject: [PATCH v4 01/18] remoteproc: st_xp70_rproc: add a xp70 slimcore
 rproc driver
In-Reply-To: <57484867.6030608@st.com>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
 <1464192412-16386-3-git-send-email-peter.griffin@linaro.org>
 <57484867.6030608@st.com>
Message-ID: <20160527161329.GA29319@griffinp-ThinkPad-X1-Carbon-2nd>

Hi Patrice,

On Fri, 27 May 2016, Patrice Chotard wrote:
<snip>

> >+struct rproc *xp70_rproc_alloc(struct platform_device *pdev, char *fw_name);
> >+void xp70_rproc_put(struct st_xp70_rproc *xp70_rproc);
> >+
> >+#endif
> 
> Hi Peter
> 
> Applying this series on top of v4.6 kernel leads to the following
> compilation error due to patch 01/18 :
> 
> drivers/remoteproc/st_xp70_rproc.c: In function 'xp70_rproc_alloc':
> drivers/remoteproc/st_xp70_rproc.c:291:2: error: implicit
> declaration of function 'rproc_get_elf_ops'
> [-Werror=implicit-function-declaration]
>   elf_ops = rproc_get_elf_ops();
>   ^
>   LD [M]  drivers/remoteproc/remoteproc.o

Whoops. Looks like I forgot to include the first patch of the series. Doh! I will
include it when I send v5.

The missing patch looks like this. Bjorn do you have any issues with adding this
interface?

regards,

Peter.



>From 4664bb628cb5c99a43976a0b74ae1ee6cb05a68e Mon Sep 17 00:00:00 2001
From: Peter Griffin <peter.griffin at linaro.org>
Date: Wed, 25 May 2016 09:54:02 +0100
Subject: [PATCH 01/19] remoteproc: add a rproc_get_elf_ops interface

This allows us to re-use some of the generic fw_ops such
as rproc_elf_sanity_check() and rproc_elf_load_segments() whilst
overriding some of the others with our own implementation.

Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
---
 drivers/remoteproc/remoteproc_elf_loader.c | 6 ++++++
 include/linux/remoteproc.h                 | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index ce283a5..a3e06df 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -335,3 +335,9 @@ const struct rproc_fw_ops rproc_elf_fw_ops = {
 	.sanity_check = rproc_elf_sanity_check,
 	.get_boot_addr = rproc_elf_get_boot_addr
 };
+
+const struct rproc_fw_ops *rproc_get_elf_ops(void)
+{
+	return &rproc_elf_fw_ops;
+}
+EXPORT_SYMBOL_GPL(rproc_get_elf_ops);
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 9c4e138..b0b06c8 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -495,6 +495,8 @@ int rproc_boot(struct rproc *rproc);
 void rproc_shutdown(struct rproc *rproc);
 void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type);
 
+const struct rproc_fw_ops *rproc_get_elf_ops(void);
+
 static inline struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev)
 {
 	return container_of(vdev, struct rproc_vdev, vdev);
-- 
1.9.1



From mark.rutland at arm.com  Fri May 27 09:14:33 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Fri, 27 May 2016 17:14:33 +0100
Subject: v7_dma_inv_range performance/high expense
In-Reply-To: <20160527144045.GB20214@lunn.ch>
References: <20160527144045.GB20214@lunn.ch>
Message-ID: <20160527161432.GI24469@leverpostej>

On Fri, May 27, 2016 at 04:40:45PM +0200, Andrew Lunn wrote:
> Hi folks
> 
> I have an imx6q, which is a quad core v7 processor. Attached to it via
> pcie i have an intel i210 Ethernet controller.
> 
> When the ethernet is transmitting, i can get gigabit line rate, and
> use one core to about 35% of one core. When receiving, i get around
> 700Mbps and ksoftirqd/0 is 98% loading a core.
> 
> Using perf to profile the ksoftirqd/0 pid is see:
> 
>   46.38%  [kernel]  [k] v7_dma_inv_range
>   21.25%  [kernel]  [k] l2c210_inv_range
>   10.90%  [kernel]  [k] igb_poll
>    1.69%  [kernel]  [k] dma_cache_maint_page
>    1.27%  [kernel]  [k] eth_type_trans
>    1.20%  [kernel]  [k] skb_add_rx_frag
> 
> Digging deeper into v7_dma_inv_range i see:
> 
>            801182c0 <v7_dma_inv_range>:
>            v7_dma_inv_range():
>   0.26       mrc    15, 0, r3, cr0, cr0, {1}
>   0.07       lsr    r3, r3, #16
>              and    r3, r3, #15
>   0.04       mov    r2, #4
>              lsl    r2, r2, r3
>   0.04       sub    r3, r2, #1
>              tst    r0, r3
>   0.02       bic    r0, r0, r3
>   0.03       dsb    sy
>   3.01       mcrne  15, 0, r0, cr7, cr14, {1}
>   0.54       tst    r1, r3
>              bic    r1, r1, r3
>   0.08       mcrne  15, 0, r1, cr7, cr14, {1}
>   3.82 34:   mcr    15, 0, r0, cr7, cr6, {1}
>  88.32       add    r0, r0, r2
>              cmp    r0, r1
>   1.97       bcc    34
>   0.43       dsb    st
>   1.37       bx     lr
> 
> I'm assuming perf is off by one here, and the add is not taking 88.32%
> of the load, rather it is the mcr instruction before it.

The address perf reports is the PC at the moment the PMU overflow
interrupt was architecturally taken by the core. Reporting anything else
would require us to make up bogus PC values (e.g. if a branch was just
taken, you can't reconstruct the previous PC).

If the PMU overflow interrupt comes in (asynchronously) while an
expensive instruction is in progress, the CPU will likely have to wait
for that to complete before it can handle the interrupt.

So yes, the MCR is very likely to be the expensive instruction here.

> The original code in arch/arm/mm/cache-v7.S  says:
> 
>         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D / U line
> 
> I don't get why a cache invalidate instruction should be so expensive.
> It is just throwing away the contents of the cache line, not flushing
> it out to DRAM. 

This really depends on the microarchitecture and integration.

The cache maintenance operations likely have to synchronise with some
logic in other cores to safely invalidate all copies of the line, there
may be some limit on the number of outstanding operations, etc.

> Should i trust perf?

I don't see a reason not to. Nothing above implies that perf is
providing erroneous information.

Thanks,
Mark.


From marcel.ziswiler at toradex.com  Fri May 27 09:27:51 2016
From: marcel.ziswiler at toradex.com (Marcel Ziswiler)
Date: Fri, 27 May 2016 18:27:51 +0200
Subject: [PATCH] arm: tegra124: remove commas from unit addresses
Message-ID: <1464366471-23832-1-git-send-email-marcel.ziswiler@toradex.com>

Remove commas from unit addresses as suggested by Rob Herring upon me
posting initial Apalis TK1 support:

http://article.gmane.org/gmane.linux.ports.tegra/26608

Signed-off-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>

---

 arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi |   6 +-
 arch/arm/boot/dts/tegra124-jetson-tk1.dts      |  72 +++++++--------
 arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi   |   6 +-
 arch/arm/boot/dts/tegra124-nyan-big.dts        |   4 +-
 arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi |   6 +-
 arch/arm/boot/dts/tegra124-nyan-blaze.dts      |   2 +-
 arch/arm/boot/dts/tegra124-nyan.dtsi           |  60 ++++++------
 arch/arm/boot/dts/tegra124-venice2.dts         |  72 +++++++--------
 arch/arm/boot/dts/tegra124.dtsi                | 122 ++++++++++++-------------
 9 files changed, 175 insertions(+), 175 deletions(-)

diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi b/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi
index 2c5cede..accb705 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi
@@ -1,5 +1,5 @@
 / {
-	clock at 0,60006000 {
+	clock at 60006000 {
 		emc-timings-3 {
 			nvidia,ram-code = <3>;
 
@@ -78,7 +78,7 @@
 		};
 	};
 
-	emc at 0,7001b000 {
+	emc at 7001b000 {
 		emc-timings-3 {
 			nvidia,ram-code = <3>;
 
@@ -2101,7 +2101,7 @@
 		};
 	};
 
-	memory-controller at 0,70019000 {
+	memory-controller at 70019000 {
 		emc-timings-3 {
 			nvidia,ram-code = <3>;
 
diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index 941f362..1c1eb18 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -10,8 +10,8 @@
 	compatible = "nvidia,jetson-tk1", "nvidia,tegra124";
 
 	aliases {
-		rtc0 = "/i2c at 0,7000d000/pmic at 40";
-		rtc1 = "/rtc at 0,7000e000";
+		rtc0 = "/i2c at 7000d000/pmic at 40";
+		rtc1 = "/rtc at 7000e000";
 
 		/* This order keeps the mapping DB9 connector <-> ttyS0 */
 		serial0 = &uartd;
@@ -27,7 +27,7 @@
 		reg = <0x0 0x80000000 0x0 0x80000000>;
 	};
 
-	pcie-controller at 0,01003000 {
+	pcie-controller at 01003000 {
 		status = "okay";
 
 		avddio-pex-supply = <&vdd_1v05_run>;
@@ -40,21 +40,21 @@
 
 		/* Mini PCIe */
 		pci at 1,0 {
-			phys = <&{/padctl at 0,7009f000/pads/pcie/lanes/pcie-4}>;
+			phys = <&{/padctl at 7009f000/pads/pcie/lanes/pcie-4}>;
 			phy-names = "pcie-0";
 			status = "okay";
 		};
 
 		/* Gigabit Ethernet */
 		pci at 2,0 {
-			phys = <&{/padctl at 0,7009f000/pads/pcie/lanes/pcie-2}>;
+			phys = <&{/padctl at 7009f000/pads/pcie/lanes/pcie-2}>;
 			phy-names = "pcie-0";
 			status = "okay";
 		};
 	};
 
-	host1x at 0,50000000 {
-		hdmi at 0,54280000 {
+	host1x at 50000000 {
+		hdmi at 54280000 {
 			status = "okay";
 
 			hdmi-supply = <&vdd_5v0_hdmi>;
@@ -67,7 +67,7 @@
 		};
 	};
 
-	gpu at 0,57000000 {
+	gpu at 57000000 {
 		/*
 		 * Node left disabled on purpose - the bootloader will enable
 		 * it after having set the VPR up
@@ -75,7 +75,7 @@
 		vdd-supply = <&vdd_gpu>;
 	};
 
-	pinmux: pinmux at 0,70000868 {
+	pinmux: pinmux at 70000868 {
 		pinctrl-names = "boot";
 		pinctrl-0 = <&state_boot>;
 
@@ -1404,12 +1404,12 @@
 	};
 
 	/* DB9 serial port */
-	serial at 0,70006300 {
+	serial at 70006300 {
 		status = "okay";
 	};
 
 	/* Expansion GEN1_I2C_*, mini-PCIe I2C, on-board components */
-	i2c at 0,7000c000 {
+	i2c at 7000c000 {
 		status = "okay";
 		clock-frequency = <100000>;
 
@@ -1437,25 +1437,25 @@
 	};
 
 	/* Expansion GEN2_I2C_* */
-	i2c at 0,7000c400 {
+	i2c at 7000c400 {
 		status = "okay";
 		clock-frequency = <100000>;
 	};
 
 	/* Expansion CAM_I2C_* */
-	i2c at 0,7000c500 {
+	i2c at 7000c500 {
 		status = "okay";
 		clock-frequency = <100000>;
 	};
 
 	/* HDMI DDC */
-	hdmi_ddc: i2c at 0,7000c700 {
+	hdmi_ddc: i2c at 7000c700 {
 		status = "okay";
 		clock-frequency = <100000>;
 	};
 
 	/* Expansion PWR_I2C_*, on-board components */
-	i2c at 0,7000d000 {
+	i2c at 7000d000 {
 		status = "okay";
 		clock-frequency = <400000>;
 
@@ -1646,12 +1646,12 @@
 	};
 
 	/* Expansion TS_SPI_* */
-	spi at 0,7000d400 {
+	spi at 7000d400 {
 		status = "okay";
 	};
 
 	/* Internal SPI */
-	spi at 0,7000da00 {
+	spi at 7000da00 {
 		status = "okay";
 		spi-max-frequency = <25000000>;
 		spi-flash at 0 {
@@ -1661,7 +1661,7 @@
 		};
 	};
 
-	pmc at 0,7000e400 {
+	pmc at 7000e400 {
 		nvidia,invert-interrupt;
 		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <500>;
@@ -1680,10 +1680,10 @@
 	};
 
 	/* Serial ATA */
-	sata at 0,70020000 {
+	sata at 70020000 {
 		status = "okay";
 
-		phys = <&{/padctl at 0,7009f000/pads/sata/lanes/sata-0}>;
+		phys = <&{/padctl at 7009f000/pads/sata/lanes/sata-0}>;
 		phy-names = "sata-0";
 
 		hvdd-supply = <&vdd_3v3_lp0>;
@@ -1694,15 +1694,15 @@
 		target-12v-supply = <&vdd_12v0_sata>;
 	};
 
-	hda at 0,70030000 {
+	hda at 70030000 {
 		status = "okay";
 	};
 
-	usb at 0,70090000 {
-		phys = <&{/padctl at 0,7009f000/pads/usb2/lanes/usb2-0}>, /* Micro A/B */
-		       <&{/padctl at 0,7009f000/pads/usb2/lanes/usb2-1}>, /* Mini PCIe */
-		       <&{/padctl at 0,7009f000/pads/usb2/lanes/usb2-2}>, /* USB3 */
-		       <&{/padctl at 0,7009f000/pads/pcie/lanes/pcie-0}>; /* USB3 */
+	usb at 70090000 {
+		phys = <&{/padctl at 7009f000/pads/usb2/lanes/usb2-0}>, /* Micro A/B */
+		       <&{/padctl at 7009f000/pads/usb2/lanes/usb2-1}>, /* Mini PCIe */
+		       <&{/padctl at 7009f000/pads/usb2/lanes/usb2-2}>, /* USB3 */
+		       <&{/padctl at 7009f000/pads/pcie/lanes/pcie-0}>; /* USB3 */
 		phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-0";
 
 		avddio-pex-supply = <&vdd_1v05_run>;
@@ -1717,7 +1717,7 @@
 		status = "okay";
 	};
 
-	padctl at 0,7009f000 {
+	padctl at 7009f000 {
 		status = "okay";
 
 		pads {
@@ -1804,7 +1804,7 @@
 	};
 
 	/* SD card */
-	sdhci at 0,700b0400 {
+	sdhci at 700b0400 {
 		status = "okay";
 		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
 		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
@@ -1814,40 +1814,40 @@
 	};
 
 	/* eMMC */
-	sdhci at 0,700b0600 {
+	sdhci at 700b0600 {
 		status = "okay";
 		bus-width = <8>;
 		non-removable;
 	};
 
 	/* CPU DFLL clock */
-	clock at 0,70110000 {
+	clock at 70110000 {
 		status = "okay";
 		vdd-cpu-supply = <&vdd_cpu>;
 		nvidia,i2c-fs-rate = <400000>;
 	};
 
-	ahub at 0,70300000 {
-		i2s at 0,70301100 {
+	ahub at 70300000 {
+		i2s at 70301100 {
 			status = "okay";
 		};
 	};
 
 	/* mini-PCIe USB */
-	usb at 0,7d004000 {
+	usb at 7d004000 {
 		status = "okay";
 	};
 
-	usb-phy at 0,7d004000 {
+	usb-phy at 7d004000 {
 		status = "okay";
 	};
 
 	/* USB A connector */
-	usb at 0,7d008000 {
+	usb at 7d008000 {
 		status = "okay";
 	};
 
-	usb-phy at 0,7d008000 {
+	usb-phy at 7d008000 {
 		status = "okay";
 		vbus-supply = <&vdd_usb3_vbus>;
 	};
diff --git a/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi b/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi
index 1a5748d..4458e86 100644
--- a/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi
+++ b/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi
@@ -1,5 +1,5 @@
 / {
-	clock at 0,60006000 {
+	clock at 60006000 {
 		emc-timings-1 {
 			nvidia,ram-code = <1>;
 
@@ -67,7 +67,7 @@
 		};
 	};
 
-	emc at 0,7001b000 {
+	emc at 7001b000 {
 		emc-timings-1 {
 			nvidia,ram-code = <1>;
 
@@ -1754,7 +1754,7 @@
 		};
 	};
 
-	memory-controller at 0,70019000 {
+	memory-controller at 70019000 {
 		emc-timings-1 {
 			nvidia,ram-code = <1>;
 
diff --git a/arch/arm/boot/dts/tegra124-nyan-big.dts b/arch/arm/boot/dts/tegra124-nyan-big.dts
index 2d21253..67d7cfb 100644
--- a/arch/arm/boot/dts/tegra124-nyan-big.dts
+++ b/arch/arm/boot/dts/tegra124-nyan-big.dts
@@ -15,7 +15,7 @@
 		ddc-i2c-bus = <&dpaux>;
 	};
 
-	sdhci at 0,700b0400 { /* SD Card on this bus */
+	sdhci at 700b0400 { /* SD Card on this bus */
 		wp-gpios = <&gpio TEGRA_GPIO(Q, 4) GPIO_ACTIVE_LOW>;
 	};
 
@@ -26,7 +26,7 @@
 		nvidia,model = "GoogleNyanBig";
 	};
 
-	pinmux at 0,70000868 {
+	pinmux at 70000868 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinmux_default>;
 
diff --git a/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi b/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi
index 9ecd108..4e7b59e 100644
--- a/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi
+++ b/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi
@@ -1,5 +1,5 @@
 / {
-	clock at 0,60006000 {
+	clock at 60006000 {
 		emc-timings-1 {
 			nvidia,ram-code = <1>;
 
@@ -67,7 +67,7 @@
 		};
 	};
 
-	emc at 0,7001b000 {
+	emc at 7001b000 {
 		emc-timings-1 {
 			nvidia,ram-code = <1>;
 
@@ -1754,7 +1754,7 @@
 		};
 	};
 
-	memory-controller at 0,70019000 {
+	memory-controller at 70019000 {
 		emc-timings-1 {
 			nvidia,ram-code = <1>;
 
diff --git a/arch/arm/boot/dts/tegra124-nyan-blaze.dts b/arch/arm/boot/dts/tegra124-nyan-blaze.dts
index 0d30c51..c9582361 100644
--- a/arch/arm/boot/dts/tegra124-nyan-blaze.dts
+++ b/arch/arm/boot/dts/tegra124-nyan-blaze.dts
@@ -22,7 +22,7 @@
 		nvidia,model = "GoogleNyanBlaze";
 	};
 
-	pinmux at 0,70000868 {
+	pinmux at 70000868 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinmux_default>;
 
diff --git a/arch/arm/boot/dts/tegra124-nyan.dtsi b/arch/arm/boot/dts/tegra124-nyan.dtsi
index 0710a60..271505e 100644
--- a/arch/arm/boot/dts/tegra124-nyan.dtsi
+++ b/arch/arm/boot/dts/tegra124-nyan.dtsi
@@ -3,8 +3,8 @@
 
 / {
 	aliases {
-		rtc0 = "/i2c at 0,7000d000/pmic at 40";
-		rtc1 = "/rtc at 0,7000e000";
+		rtc0 = "/i2c at 7000d000/pmic at 40";
+		rtc1 = "/rtc at 7000e000";
 		serial0 = &uarta;
 	};
 
@@ -16,8 +16,8 @@
 		reg = <0x0 0x80000000 0x0 0x80000000>;
 	};
 
-	host1x at 0,50000000 {
-		hdmi at 0,54280000 {
+	host1x at 50000000 {
+		hdmi at 54280000 {
 			status = "okay";
 
 			vdd-supply = <&vdd_3v3_hdmi>;
@@ -29,29 +29,29 @@
 				<&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>;
 		};
 
-		sor at 0,54540000 {
+		sor at 54540000 {
 			status = "okay";
 
 			nvidia,dpaux = <&dpaux>;
 			nvidia,panel = <&panel>;
 		};
 
-		dpaux at 0,545c0000 {
+		dpaux at 545c0000 {
 			vdd-supply = <&vdd_3v3_panel>;
 			status = "okay";
 		};
 	};
 
-	serial at 0,70006000 {
+	serial at 70006000 {
 		/* Debug connector on the bottom of the board near SD card. */
 		status = "okay";
 	};
 
-	pwm at 0,7000a000 {
+	pwm at 7000a000 {
 		status = "okay";
 	};
 
-	i2c at 0,7000c000 {
+	i2c at 7000c000 {
 		status = "okay";
 		clock-frequency = <100000>;
 
@@ -72,7 +72,7 @@
 		};
 	};
 
-	i2c at 0,7000c400 {
+	i2c at 7000c400 {
 		status = "okay";
 		clock-frequency = <100000>;
 
@@ -85,7 +85,7 @@
 		};
 	};
 
-	i2c at 0,7000c500 {
+	i2c at 7000c500 {
 		status = "okay";
 		clock-frequency = <400000>;
 
@@ -95,12 +95,12 @@
 		};
 	};
 
-	hdmi_ddc: i2c at 0,7000c700 {
+	hdmi_ddc: i2c at 7000c700 {
 		status = "okay";
 		clock-frequency = <100000>;
 	};
 
-	i2c at 0,7000d000 {
+	i2c at 7000d000 {
 		status = "okay";
 		clock-frequency = <400000>;
 
@@ -301,7 +301,7 @@
 		};
 	};
 
-	spi at 0,7000d400 {
+	spi at 7000d400 {
 		status = "okay";
 
 		cros_ec: cros-ec at 0 {
@@ -342,7 +342,7 @@
 		};
 	};
 
-	spi at 0,7000da00 {
+	spi at 7000da00 {
 		status = "okay";
 		spi-max-frequency = <25000000>;
 
@@ -353,7 +353,7 @@
 		};
 	};
 
-	pmc at 0,7000e400 {
+	pmc at 7000e400 {
 		nvidia,invert-interrupt;
 		nvidia,suspend-mode = <0>;
 		nvidia,cpu-pwr-good-time = <500>;
@@ -364,16 +364,16 @@
 		nvidia,sys-clock-req-active-high;
 	};
 
-	hda at 0,70030000 {
+	hda at 70030000 {
 		status = "okay";
 	};
 
-	usb at 0,70090000 {
-		phys = <&{/padctl at 0,7009f000/pads/usb2/lanes/usb2-0}>, /* 1st USB A */
-		       <&{/padctl at 0,7009f000/pads/usb2/lanes/usb2-1}>, /* Internal USB */
-		       <&{/padctl at 0,7009f000/pads/usb2/lanes/usb2-2}>, /* 2nd USB A */
-		       <&{/padctl at 0,7009f000/pads/pcie/lanes/pcie-0}>, /* 1st USB A */
-		       <&{/padctl at 0,7009f000/pads/pcie/lanes/pcie-1}>; /* 2nd USB A */
+	usb at 70090000 {
+		phys = <&{/padctl at 7009f000/pads/usb2/lanes/usb2-0}>, /* 1st USB A */
+		       <&{/padctl at 7009f000/pads/usb2/lanes/usb2-1}>, /* Internal USB */
+		       <&{/padctl at 7009f000/pads/usb2/lanes/usb2-2}>, /* 2nd USB A */
+		       <&{/padctl at 7009f000/pads/pcie/lanes/pcie-0}>, /* 1st USB A */
+		       <&{/padctl at 7009f000/pads/pcie/lanes/pcie-1}>; /* 2nd USB A */
 		phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-0", "usb3-1";
 
 		avddio-pex-supply = <&vdd_1v05_run>;
@@ -388,7 +388,7 @@
 		status = "okay";
 	};
 
-	padctl at 0,7009f000 {
+	padctl at 7009f000 {
 		status = "okay";
 
 		pads {
@@ -467,7 +467,7 @@
 		reset-gpios = <&gpio TEGRA_GPIO(X, 7) GPIO_ACTIVE_LOW>;
 	};
 
-	sdhci at 0,700b0000 { /* WiFi/BT on this bus */
+	sdhci at 700b0000 { /* WiFi/BT on this bus */
 		status = "okay";
 		bus-width = <4>;
 		no-1-8-v;
@@ -478,7 +478,7 @@
 		keep-power-in-suspend;
 	};
 
-	sdhci at 0,700b0400 { /* SD Card on this bus */
+	sdhci at 700b0400 { /* SD Card on this bus */
 		status = "okay";
 		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
 		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
@@ -487,7 +487,7 @@
 		vqmmc-supply = <&vddio_sdmmc3>;
 	};
 
-	sdhci at 0,700b0600 { /* eMMC on this bus */
+	sdhci at 700b0600 { /* eMMC on this bus */
 		status = "okay";
 		bus-width = <8>;
 		no-1-8-v;
@@ -495,14 +495,14 @@
 	};
 
 	/* CPU DFLL clock */
-	clock at 0,70110000 {
+	clock at 70110000 {
 		status = "disabled";
 		vdd-cpu-supply = <&vdd_cpu>;
 		nvidia,i2c-fs-rate = <400000>;
 	};
 
-	ahub at 0,70300000 {
-		i2s at 0,70301100 {
+	ahub at 70300000 {
+		i2s at 70301100 {
 			status = "okay";
 		};
 	};
diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts
index 973446d..21f0e5c 100644
--- a/arch/arm/boot/dts/tegra124-venice2.dts
+++ b/arch/arm/boot/dts/tegra124-venice2.dts
@@ -8,8 +8,8 @@
 	compatible = "nvidia,venice2", "nvidia,tegra124";
 
 	aliases {
-		rtc0 = "/i2c at 0,7000d000/pmic at 40";
-		rtc1 = "/rtc at 0,7000e000";
+		rtc0 = "/i2c at 7000d000/pmic at 40";
+		rtc1 = "/rtc at 7000e000";
 		serial0 = &uarta;
 	};
 
@@ -21,8 +21,8 @@
 		reg = <0x0 0x80000000 0x0 0x80000000>;
 	};
 
-	host1x at 0,50000000 {
-		hdmi at 0,54280000 {
+	host1x at 50000000 {
+		hdmi at 54280000 {
 			status = "okay";
 
 			vdd-supply = <&vdd_3v3_hdmi>;
@@ -34,20 +34,20 @@
 				<&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>;
 		};
 
-		sor at 0,54540000 {
+		sor at 54540000 {
 			status = "okay";
 
 			nvidia,dpaux = <&dpaux>;
 			nvidia,panel = <&panel>;
 		};
 
-		dpaux at 0,545c0000 {
+		dpaux at 545c0000 {
 			vdd-supply = <&vdd_3v3_panel>;
 			status = "okay";
 		};
 	};
 
-	gpu at 0,57000000 {
+	gpu at 57000000 {
 		/*
 		 * Node left disabled on purpose - the bootloader will enable
 		 * it after having set the VPR up
@@ -55,7 +55,7 @@
 		vdd-supply = <&vdd_gpu>;
 	};
 
-	pinmux: pinmux at 0,70000868 {
+	pinmux: pinmux at 70000868 {
 		pinctrl-names = "boot";
 		pinctrl-0 = <&pinmux_boot>;
 
@@ -596,15 +596,15 @@
 		};
 	};
 
-	serial at 0,70006000 {
+	serial at 70006000 {
 		status = "okay";
 	};
 
-	pwm at 0,7000a000 {
+	pwm at 7000a000 {
 		status = "okay";
 	};
 
-	i2c at 0,7000c000 {
+	i2c at 7000c000 {
 		status = "okay";
 		clock-frequency = <100000>;
 
@@ -616,7 +616,7 @@
 		};
 	};
 
-	i2c at 0,7000c400 {
+	i2c at 7000c400 {
 		status = "okay";
 		clock-frequency = <100000>;
 
@@ -629,17 +629,17 @@
 		};
 	};
 
-	i2c at 0,7000c500 {
+	i2c at 7000c500 {
 		status = "okay";
 		clock-frequency = <100000>;
 	};
 
-	hdmi_ddc: i2c at 0,7000c700 {
+	hdmi_ddc: i2c at 7000c700 {
 		status = "okay";
 		clock-frequency = <100000>;
 	};
 
-	i2c at 0,7000d000 {
+	i2c at 7000d000 {
 		status = "okay";
 		clock-frequency = <400000>;
 
@@ -834,7 +834,7 @@
 		};
 	};
 
-	spi at 0,7000d400 {
+	spi at 7000d400 {
 		status = "okay";
 
 		cros_ec: cros-ec at 0 {
@@ -874,7 +874,7 @@
 		};
 	};
 
-	spi at 0,7000da00 {
+	spi at 7000da00 {
 		status = "okay";
 		spi-max-frequency = <25000000>;
 		spi-flash at 0 {
@@ -884,7 +884,7 @@
 		};
 	};
 
-	pmc at 0,7000e400 {
+	pmc at 7000e400 {
 		nvidia,invert-interrupt;
 		nvidia,suspend-mode = <1>;
 		nvidia,cpu-pwr-good-time = <500>;
@@ -895,16 +895,16 @@
 		nvidia,sys-clock-req-active-high;
 	};
 
-	hda at 0,70030000 {
+	hda at 70030000 {
 		status = "okay";
 	};
 
-	usb at 0,70090000 {
-		phys = <&{/padctl at 0,7009f000/pads/usb2/lanes/usb2-0}>, /* 1st USB A */
-		       <&{/padctl at 0,7009f000/pads/usb2/lanes/usb2-1}>, /* Internal USB */
-		       <&{/padctl at 0,7009f000/pads/usb2/lanes/usb2-2}>, /* 2nd USB A */
-		       <&{/padctl at 0,7009f000/pads/pcie/lanes/pcie-0}>, /* 1st USB A */
-		       <&{/padctl at 0,7009f000/pads/pcie/lanes/pcie-1}>; /* 2nd USB A */
+	usb at 70090000 {
+		phys = <&{/padctl at 7009f000/pads/usb2/lanes/usb2-0}>, /* 1st USB A */
+		       <&{/padctl at 7009f000/pads/usb2/lanes/usb2-1}>, /* Internal USB */
+		       <&{/padctl at 7009f000/pads/usb2/lanes/usb2-2}>, /* 2nd USB A */
+		       <&{/padctl at 7009f000/pads/pcie/lanes/pcie-0}>, /* 1st USB A */
+		       <&{/padctl at 7009f000/pads/pcie/lanes/pcie-1}>; /* 2nd USB A */
 		phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-0", "usb3-1";
 
 		avddio-pex-supply = <&vdd_1v05_run>;
@@ -919,7 +919,7 @@
 		status = "okay";
 	};
 
-	padctl at 0,7009f000 {
+	padctl at 7009f000 {
 		pads {
 			usb2 {
 				status = "okay";
@@ -998,7 +998,7 @@
 		};
 	};
 
-	sdhci at 0,700b0400 {
+	sdhci at 700b0400 {
 		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
 		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
 		wp-gpios = <&gpio TEGRA_GPIO(Q, 4) GPIO_ACTIVE_LOW>;
@@ -1007,41 +1007,41 @@
 		vqmmc-supply = <&vddio_sdmmc3>;
 	};
 
-	sdhci at 0,700b0600 {
+	sdhci at 700b0600 {
 		status = "okay";
 		bus-width = <8>;
 		non-removable;
 	};
 
-	ahub at 0,70300000 {
-		i2s at 0,70301100 {
+	ahub at 70300000 {
+		i2s at 70301100 {
 			status = "okay";
 		};
 	};
 
-	usb at 0,7d000000 {
+	usb at 7d000000 {
 		status = "okay";
 	};
 
-	usb-phy at 0,7d000000 {
+	usb-phy at 7d000000 {
 		status = "okay";
 		vbus-supply = <&vdd_usb1_vbus>;
 	};
 
-	usb at 0,7d004000 {
+	usb at 7d004000 {
 		status = "okay";
 	};
 
-	usb-phy at 0,7d004000 {
+	usb-phy at 7d004000 {
 		status = "okay";
 		vbus-supply = <&vdd_run_cam>;
 	};
 
-	usb at 0,7d008000 {
+	usb at 7d008000 {
 		status = "okay";
 	};
 
-	usb-phy at 0,7d008000 {
+	usb-phy at 7d008000 {
 		status = "okay";
 		vbus-supply = <&vdd_usb3_vbus>;
 	};
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index ea48118..e0b813e 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -14,7 +14,7 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
-	pcie-controller at 0,01003000 {
+	pcie-controller at 01003000 {
 		compatible = "nvidia,tegra124-pcie";
 		device_type = "pci";
 		reg = <0x0 0x01003000 0x0 0x00000800   /* PADS registers */
@@ -77,7 +77,7 @@
 		};
 	};
 
-	host1x at 0,50000000 {
+	host1x at 50000000 {
 		compatible = "nvidia,tegra124-host1x", "simple-bus";
 		reg = <0x0 0x50000000 0x0 0x00034000>;
 		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, /* syncpt */
@@ -91,7 +91,7 @@
 
 		ranges = <0 0x54000000 0 0x54000000 0 0x01000000>;
 
-		dc at 0,54200000 {
+		dc at 54200000 {
 			compatible = "nvidia,tegra124-dc";
 			reg = <0x0 0x54200000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
@@ -106,7 +106,7 @@
 			nvidia,head = <0>;
 		};
 
-		dc at 0,54240000 {
+		dc at 54240000 {
 			compatible = "nvidia,tegra124-dc";
 			reg = <0x0 0x54240000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
@@ -121,7 +121,7 @@
 			nvidia,head = <1>;
 		};
 
-		hdmi at 0,54280000 {
+		hdmi at 54280000 {
 			compatible = "nvidia,tegra124-hdmi";
 			reg = <0x0 0x54280000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
@@ -133,7 +133,7 @@
 			status = "disabled";
 		};
 
-		sor at 0,54540000 {
+		sor at 54540000 {
 			compatible = "nvidia,tegra124-sor";
 			reg = <0x0 0x54540000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
@@ -147,7 +147,7 @@
 			status = "disabled";
 		};
 
-		dpaux: dpaux at 0,545c0000 {
+		dpaux: dpaux at 545c0000 {
 			compatible = "nvidia,tegra124-dpaux";
 			reg = <0x0 0x545c0000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
@@ -160,7 +160,7 @@
 		};
 	};
 
-	gic: interrupt-controller at 0,50041000 {
+	gic: interrupt-controller at 50041000 {
 		compatible = "arm,cortex-a15-gic";
 		#interrupt-cells = <3>;
 		interrupt-controller;
@@ -173,7 +173,7 @@
 		interrupt-parent = <&gic>;
 	};
 
-	gpu at 0,57000000 {
+	gpu at 57000000 {
 		compatible = "nvidia,gk20a";
 		reg = <0x0 0x57000000 0x0 0x01000000>,
 		      <0x0 0x58000000 0x0 0x01000000>;
@@ -203,7 +203,7 @@
 		interrupt-parent = <&gic>;
 	};
 
-	timer at 0,60005000 {
+	timer at 60005000 {
 		compatible = "nvidia,tegra124-timer", "nvidia,tegra30-timer", "nvidia,tegra20-timer";
 		reg = <0x0 0x60005000 0x0 0x400>;
 		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
@@ -215,7 +215,7 @@
 		clocks = <&tegra_car TEGRA124_CLK_TIMER>;
 	};
 
-	tegra_car: clock at 0,60006000 {
+	tegra_car: clock at 60006000 {
 		compatible = "nvidia,tegra124-car";
 		reg = <0x0 0x60006000 0x0 0x1000>;
 		#clock-cells = <1>;
@@ -223,12 +223,12 @@
 		nvidia,external-memory-controller = <&emc>;
 	};
 
-	flow-controller at 0,60007000 {
+	flow-controller at 60007000 {
 		compatible = "nvidia,tegra124-flowctrl";
 		reg = <0x0 0x60007000 0x0 0x1000>;
 	};
 
-	actmon at 0,6000c800 {
+	actmon at 6000c800 {
 		compatible = "nvidia,tegra124-actmon";
 		reg = <0x0 0x6000c800 0x0 0x400>;
 		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
@@ -239,7 +239,7 @@
 		reset-names = "actmon";
 	};
 
-	gpio: gpio at 0,6000d000 {
+	gpio: gpio at 6000d000 {
 		compatible = "nvidia,tegra124-gpio", "nvidia,tegra30-gpio";
 		reg = <0x0 0x6000d000 0x0 0x1000>;
 		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
@@ -259,7 +259,7 @@
 		*/
 	};
 
-	apbdma: dma at 0,60020000 {
+	apbdma: dma at 60020000 {
 		compatible = "nvidia,tegra124-apbdma", "nvidia,tegra148-apbdma";
 		reg = <0x0 0x60020000 0x0 0x1400>;
 		interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
@@ -300,13 +300,13 @@
 		#dma-cells = <1>;
 	};
 
-	apbmisc at 0,70000800 {
+	apbmisc at 70000800 {
 		compatible = "nvidia,tegra124-apbmisc", "nvidia,tegra20-apbmisc";
 		reg = <0x0 0x70000800 0x0 0x64>,   /* Chip revision */
 		      <0x0 0x7000e864 0x0 0x04>;   /* Strapping options */
 	};
 
-	pinmux: pinmux at 0,70000868 {
+	pinmux: pinmux at 70000868 {
 		compatible = "nvidia,tegra124-pinmux";
 		reg = <0x0 0x70000868 0x0 0x164>, /* Pad control registers */
 		      <0x0 0x70003000 0x0 0x434>, /* Mux registers */
@@ -321,7 +321,7 @@
 	 * the APB DMA based serial driver, the compatible is
 	 * "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart".
 	 */
-	uarta: serial at 0,70006000 {
+	uarta: serial at 70006000 {
 		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x70006000 0x0 0x40>;
 		reg-shift = <2>;
@@ -334,7 +334,7 @@
 		status = "disabled";
 	};
 
-	uartb: serial at 0,70006040 {
+	uartb: serial at 70006040 {
 		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x70006040 0x0 0x40>;
 		reg-shift = <2>;
@@ -347,7 +347,7 @@
 		status = "disabled";
 	};
 
-	uartc: serial at 0,70006200 {
+	uartc: serial at 70006200 {
 		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x70006200 0x0 0x40>;
 		reg-shift = <2>;
@@ -360,7 +360,7 @@
 		status = "disabled";
 	};
 
-	uartd: serial at 0,70006300 {
+	uartd: serial at 70006300 {
 		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x70006300 0x0 0x40>;
 		reg-shift = <2>;
@@ -373,7 +373,7 @@
 		status = "disabled";
 	};
 
-	pwm: pwm at 0,7000a000 {
+	pwm: pwm at 7000a000 {
 		compatible = "nvidia,tegra124-pwm", "nvidia,tegra20-pwm";
 		reg = <0x0 0x7000a000 0x0 0x100>;
 		#pwm-cells = <2>;
@@ -383,7 +383,7 @@
 		status = "disabled";
 	};
 
-	i2c at 0,7000c000 {
+	i2c at 7000c000 {
 		compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000c000 0x0 0x100>;
 		interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
@@ -398,7 +398,7 @@
 		status = "disabled";
 	};
 
-	i2c at 0,7000c400 {
+	i2c at 7000c400 {
 		compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000c400 0x0 0x100>;
 		interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
@@ -413,7 +413,7 @@
 		status = "disabled";
 	};
 
-	i2c at 0,7000c500 {
+	i2c at 7000c500 {
 		compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000c500 0x0 0x100>;
 		interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
@@ -428,7 +428,7 @@
 		status = "disabled";
 	};
 
-	i2c at 0,7000c700 {
+	i2c at 7000c700 {
 		compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000c700 0x0 0x100>;
 		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
@@ -443,7 +443,7 @@
 		status = "disabled";
 	};
 
-	i2c at 0,7000d000 {
+	i2c at 7000d000 {
 		compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000d000 0x0 0x100>;
 		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
@@ -458,7 +458,7 @@
 		status = "disabled";
 	};
 
-	i2c at 0,7000d100 {
+	i2c at 7000d100 {
 		compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000d100 0x0 0x100>;
 		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
@@ -473,7 +473,7 @@
 		status = "disabled";
 	};
 
-	spi at 0,7000d400 {
+	spi at 7000d400 {
 		compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000d400 0x0 0x200>;
 		interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
@@ -488,7 +488,7 @@
 		status = "disabled";
 	};
 
-	spi at 0,7000d600 {
+	spi at 7000d600 {
 		compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000d600 0x0 0x200>;
 		interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
@@ -503,7 +503,7 @@
 		status = "disabled";
 	};
 
-	spi at 0,7000d800 {
+	spi at 7000d800 {
 		compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000d800 0x0 0x200>;
 		interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
@@ -518,7 +518,7 @@
 		status = "disabled";
 	};
 
-	spi at 0,7000da00 {
+	spi at 7000da00 {
 		compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000da00 0x0 0x200>;
 		interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
@@ -533,7 +533,7 @@
 		status = "disabled";
 	};
 
-	spi at 0,7000dc00 {
+	spi at 7000dc00 {
 		compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000dc00 0x0 0x200>;
 		interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
@@ -548,7 +548,7 @@
 		status = "disabled";
 	};
 
-	spi at 0,7000de00 {
+	spi at 7000de00 {
 		compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000de00 0x0 0x200>;
 		interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
@@ -563,21 +563,21 @@
 		status = "disabled";
 	};
 
-	rtc at 0,7000e000 {
+	rtc at 7000e000 {
 		compatible = "nvidia,tegra124-rtc", "nvidia,tegra20-rtc";
 		reg = <0x0 0x7000e000 0x0 0x100>;
 		interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&tegra_car TEGRA124_CLK_RTC>;
 	};
 
-	pmc at 0,7000e400 {
+	pmc at 7000e400 {
 		compatible = "nvidia,tegra124-pmc";
 		reg = <0x0 0x7000e400 0x0 0x400>;
 		clocks = <&tegra_car TEGRA124_CLK_PCLK>, <&clk32k_in>;
 		clock-names = "pclk", "clk32k_in";
 	};
 
-	fuse at 0,7000f800 {
+	fuse at 7000f800 {
 		compatible = "nvidia,tegra124-efuse";
 		reg = <0x0 0x7000f800 0x0 0x400>;
 		clocks = <&tegra_car TEGRA124_CLK_FUSE>;
@@ -586,7 +586,7 @@
 		reset-names = "fuse";
 	};
 
-	mc: memory-controller at 0,70019000 {
+	mc: memory-controller at 70019000 {
 		compatible = "nvidia,tegra124-mc";
 		reg = <0x0 0x70019000 0x0 0x1000>;
 		clocks = <&tegra_car TEGRA124_CLK_MC>;
@@ -597,14 +597,14 @@
 		#iommu-cells = <1>;
 	};
 
-	emc: emc at 0,7001b000 {
+	emc: emc at 7001b000 {
 		compatible = "nvidia,tegra124-emc";
 		reg = <0x0 0x7001b000 0x0 0x1000>;
 
 		nvidia,memory-controller = <&mc>;
 	};
 
-	sata at 0,70020000 {
+	sata at 70020000 {
 		compatible = "nvidia,tegra124-ahci";
 		reg = <0x0 0x70027000 0x0 0x2000>, /* AHCI */
 		      <0x0 0x70020000 0x0 0x7000>; /* SATA */
@@ -621,7 +621,7 @@
 		status = "disabled";
 	};
 
-	hda at 0,70030000 {
+	hda at 70030000 {
 		compatible = "nvidia,tegra124-hda", "nvidia,tegra30-hda";
 		reg = <0x0 0x70030000 0x0 0x10000>;
 		interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
@@ -636,7 +636,7 @@
 		status = "disabled";
 	};
 
-	usb at 0,70090000 {
+	usb at 70090000 {
 		compatible = "nvidia,tegra124-xusb";
 		reg = <0x0 0x70090000 0x0 0x8000>,
 		      <0x0 0x70098000 0x0 0x1000>,
@@ -671,7 +671,7 @@
 		status = "disabled";
 	};
 
-	padctl: padctl at 0,7009f000 {
+	padctl: padctl at 7009f000 {
 		compatible = "nvidia,tegra124-xusb-padctl";
 		reg = <0x0 0x7009f000 0x0 0x1000>;
 		resets = <&tegra_car 142>;
@@ -804,7 +804,7 @@
 		};
 	};
 
-	sdhci at 0,700b0000 {
+	sdhci at 700b0000 {
 		compatible = "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0000 0x0 0x200>;
 		interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
@@ -814,7 +814,7 @@
 		status = "disabled";
 	};
 
-	sdhci at 0,700b0200 {
+	sdhci at 700b0200 {
 		compatible = "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0200 0x0 0x200>;
 		interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
@@ -824,7 +824,7 @@
 		status = "disabled";
 	};
 
-	sdhci at 0,700b0400 {
+	sdhci at 700b0400 {
 		compatible = "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0400 0x0 0x200>;
 		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
@@ -834,7 +834,7 @@
 		status = "disabled";
 	};
 
-	sdhci at 0,700b0600 {
+	sdhci at 700b0600 {
 		compatible = "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0600 0x0 0x200>;
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
@@ -844,7 +844,7 @@
 		status = "disabled";
 	};
 
-	soctherm: thermal-sensor at 0,700e2000 {
+	soctherm: thermal-sensor at 700e2000 {
 		compatible = "nvidia,tegra124-soctherm";
 		reg = <0x0 0x700e2000 0x0 0x1000>;
 		interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
@@ -856,7 +856,7 @@
 		#thermal-sensor-cells = <1>;
 	};
 
-	dfll: clock at 0,70110000 {
+	dfll: clock at 70110000 {
 		compatible = "nvidia,tegra124-dfll";
 		reg = <0 0x70110000 0 0x100>, /* DFLL control */
 		      <0 0x70110000 0 0x100>, /* I2C output control */
@@ -880,7 +880,7 @@
 		status = "disabled";
 	};
 
-	ahub at 0,70300000 {
+	ahub at 70300000 {
 		compatible = "nvidia,tegra124-ahub";
 		reg = <0x0 0x70300000 0x0 0x200>,
 		      <0x0 0x70300800 0x0 0x800>,
@@ -932,7 +932,7 @@
 		#address-cells = <2>;
 		#size-cells = <2>;
 
-		tegra_i2s0: i2s at 0,70301000 {
+		tegra_i2s0: i2s at 70301000 {
 			compatible = "nvidia,tegra124-i2s";
 			reg = <0x0 0x70301000 0x0 0x100>;
 			nvidia,ahub-cif-ids = <4 4>;
@@ -942,7 +942,7 @@
 			status = "disabled";
 		};
 
-		tegra_i2s1: i2s at 0,70301100 {
+		tegra_i2s1: i2s at 70301100 {
 			compatible = "nvidia,tegra124-i2s";
 			reg = <0x0 0x70301100 0x0 0x100>;
 			nvidia,ahub-cif-ids = <5 5>;
@@ -952,7 +952,7 @@
 			status = "disabled";
 		};
 
-		tegra_i2s2: i2s at 0,70301200 {
+		tegra_i2s2: i2s at 70301200 {
 			compatible = "nvidia,tegra124-i2s";
 			reg = <0x0 0x70301200 0x0 0x100>;
 			nvidia,ahub-cif-ids = <6 6>;
@@ -962,7 +962,7 @@
 			status = "disabled";
 		};
 
-		tegra_i2s3: i2s at 0,70301300 {
+		tegra_i2s3: i2s at 70301300 {
 			compatible = "nvidia,tegra124-i2s";
 			reg = <0x0 0x70301300 0x0 0x100>;
 			nvidia,ahub-cif-ids = <7 7>;
@@ -972,7 +972,7 @@
 			status = "disabled";
 		};
 
-		tegra_i2s4: i2s at 0,70301400 {
+		tegra_i2s4: i2s at 70301400 {
 			compatible = "nvidia,tegra124-i2s";
 			reg = <0x0 0x70301400 0x0 0x100>;
 			nvidia,ahub-cif-ids = <8 8>;
@@ -983,7 +983,7 @@
 		};
 	};
 
-	usb at 0,7d000000 {
+	usb at 7d000000 {
 		compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci";
 		reg = <0x0 0x7d000000 0x0 0x4000>;
 		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
@@ -995,7 +995,7 @@
 		status = "disabled";
 	};
 
-	phy1: usb-phy at 0,7d000000 {
+	phy1: usb-phy at 7d000000 {
 		compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy";
 		reg = <0x0 0x7d000000 0x0 0x4000>,
 		      <0x0 0x7d000000 0x0 0x4000>;
@@ -1020,7 +1020,7 @@
 		status = "disabled";
 	};
 
-	usb at 0,7d004000 {
+	usb at 7d004000 {
 		compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci";
 		reg = <0x0 0x7d004000 0x0 0x4000>;
 		interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
@@ -1032,7 +1032,7 @@
 		status = "disabled";
 	};
 
-	phy2: usb-phy at 0,7d004000 {
+	phy2: usb-phy at 7d004000 {
 		compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy";
 		reg = <0x0 0x7d004000 0x0 0x4000>,
 		      <0x0 0x7d000000 0x0 0x4000>;
@@ -1056,7 +1056,7 @@
 		status = "disabled";
 	};
 
-	usb at 0,7d008000 {
+	usb at 7d008000 {
 		compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci";
 		reg = <0x0 0x7d008000 0x0 0x4000>;
 		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
@@ -1068,7 +1068,7 @@
 		status = "disabled";
 	};
 
-	phy3: usb-phy at 0,7d008000 {
+	phy3: usb-phy at 7d008000 {
 		compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy";
 		reg = <0x0 0x7d008000 0x0 0x4000>,
 		      <0x0 0x7d000000 0x0 0x4000>;
-- 
2.5.5



From yang.shi at linaro.org  Fri May 27 09:34:03 2016
From: yang.shi at linaro.org (Shi, Yang)
Date: Fri, 27 May 2016 09:34:03 -0700
Subject: [PATCH] arm64: kasan: instrument user memory access API
In-Reply-To: <57482930.6020608@virtuozzo.com>
References: <1464288231-11304-1-git-send-email-yang.shi@linaro.org>
 <57482930.6020608@virtuozzo.com>
Message-ID: <cea39367-65b6-62df-7e4c-57ae1ce36dcc@linaro.org>

On 5/27/2016 4:02 AM, Andrey Ryabinin wrote:
>
>
> On 05/26/2016 09:43 PM, Yang Shi wrote:
>> The upstream commit 1771c6e1a567ea0ba2cccc0a4ffe68a1419fd8ef
>> ("x86/kasan: instrument user memory access API") added KASAN instrument to
>> x86 user memory access API, so added such instrument to ARM64 too.
>>
>> Tested by test_kasan module.
>>
>> Signed-off-by: Yang Shi <yang.shi at linaro.org>
>> ---
>>  arch/arm64/include/asm/uaccess.h | 18 ++++++++++++++++--
>>  1 file changed, 16 insertions(+), 2 deletions(-)
>
> Please, cover __copy_from_user() and __copy_to_user() too.
> Unlike x86, your patch doesn't instrument these two.

I should elaborated this in my review. Yes, I did think about it, but 
unlike x86, __copy_to/from_user are implemented by asm code on ARM64. If 
I add kasan_check_read/write into them, I have to move the registers 
around to prepare the parameters for kasan calls, then restore them 
after the call, for example the below code for __copy_to_user:

         mov     x9, x0
         mov     x10, x1
         mov     x11, x2
         mov     x0, x10
         mov     x1, x11
         bl      kasan_check_read
         mov     x0, x9
         mov     x1, x10


So, I'm wondering if it is worth or not since __copy_to/from_user are 
just called at a couple of places, i.e. sctp, a couple of drivers, etc 
and not used too much. Actually, I think some of them could be replaced 
by __copy_to/from_user_inatomic.

Any idea is appreciated.

Thanks,
Yang

>



From tony at atomide.com  Fri May 27 09:35:09 2016
From: tony at atomide.com (Tony Lindgren)
Date: Fri, 27 May 2016 09:35:09 -0700
Subject: [PATCH v4 2/7] ARM: dts: omap3: Add clocks to McBSP nodes
In-Reply-To: <1464185756-28401-3-git-send-email-peter.ujfalusi@ti.com>
References: <1464185756-28401-1-git-send-email-peter.ujfalusi@ti.com>
 <1464185756-28401-3-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <20160527163508.GZ5995@atomide.com>

* Peter Ujfalusi <peter.ujfalusi at ti.com> [160525 07:20]:
> Add clock properties to the McBSP nodes. McBSP2 and 3 need to have ick also
> since the Sidetone block of these modules are operating using the McBSP
> interface clock.

Can you please apply this dts patch as the first patch in the
series? That way I can merge it separately into my dts patches.

If no more comments other than the patch ordering change, when
v4.17-rc1 is out, please do an immutable branch against v4.17-rc1
and a pull request for me. Then that branch can be merged into
other trees as needed too.

Regards,

Tony


From linux at armlinux.org.uk  Fri May 27 09:37:15 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Fri, 27 May 2016 17:37:15 +0100
Subject: v7_dma_inv_range performance/high expense
In-Reply-To: <20160527153837.GE20214@lunn.ch>
References: <20160527144045.GB20214@lunn.ch>
 <20160527145810.GN19428@n2100.arm.linux.org.uk>
 <20160527153837.GE20214@lunn.ch>
Message-ID: <20160527163715.GP19428@n2100.arm.linux.org.uk>

On Fri, May 27, 2016 at 05:38:37PM +0200, Andrew Lunn wrote:
> You say flush here. Yet we are not flushing, we are invalidating.

Yes, I meant invalidating, sorry.

> What we logically want to happen is that the DMA engine copies the
> packet into DRAM. Once complete we invalidate the cache, and the next
> read instruction would cause a cache miss and the ethernet frame is
> pulled in.

Yes, so you read the data which was DMAd, rather than any data that may
be in the cache from previous accesses _or_ speculative prefetches.

> Looking at these numbers, the invalidate is much more expensive than
> the cache miss.
> 
> You say one line at a time is expensive. Do you have any idea where
> the break even is for invalidating the whole cache? Having said that,
> v7_invalidate_l1 seems to be doing it a line at a time as well.

Yes, v7_invalidate_l1 also does it one line at a time, but by set/way
instead, and set/way doesn't tell you whether the cache line overlaps
the memory region you're invalidating, so you would end up discarding
dirty data from other memory regions.

The alternative is to flush all cache lines in the cache, 

Even so, for either to be cheaper, you need to be touching less lines
than the present method.  For 2K worth of data, it's unlikely to be
cheaper.

I guess something which may be worth trying is to unroll the loop a
little, and see what effect it has on the perf numbers... if things
like the branch predictor are working correctly, I'd have expected
little difference (except to spread the cost over more of the function.)
It may be worth just proving that point.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From tony at atomide.com  Fri May 27 09:37:29 2016
From: tony at atomide.com (Tony Lindgren)
Date: Fri, 27 May 2016 09:37:29 -0700
Subject: [PATCH v4 2/7] ARM: dts: omap3: Add clocks to McBSP nodes
In-Reply-To: <1464186061-28639-3-git-send-email-peter.ujfalusi@ti.com>
References: <1464186061-28639-1-git-send-email-peter.ujfalusi@ti.com>
 <1464186061-28639-3-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <20160527163728.GA5995@atomide.com>

* Peter Ujfalusi <peter.ujfalusi at ti.com> [160525 07:24]:
> Add clock properties to the McBSP nodes. McBSP2 and 3 need to have ick also
> since the Sidetone block of these modules are operating using the McBSP
> interface clock.

Sorry replied to the earlier thread putting this patch as the first
patch when committing against v4.17-rc1.

Regards,

Tony


From ynorov at caviumnetworks.com  Fri May 27 09:58:06 2016
From: ynorov at caviumnetworks.com (Yury Norov)
Date: Fri, 27 May 2016 19:58:06 +0300
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160527130446.GD7865@e104818-lin.cambridge.arm.com>
References: <6293194.tGy03QJ9ME@wuerfel> <13240365.okADkKsTBJ@wuerfel>
 <20160527093052.GB7865@e104818-lin.cambridge.arm.com>
 <5422652.7gdoDlB8u0@wuerfel>
 <20160527130446.GD7865@e104818-lin.cambridge.arm.com>
Message-ID: <20160527165806.GA20966@yury-N73SV>

On Fri, May 27, 2016 at 02:04:47PM +0100, Catalin Marinas wrote:
> On Fri, May 27, 2016 at 12:49:11PM +0200, Arnd Bergmann wrote:
> > On Friday, May 27, 2016 10:30:52 AM CEST Catalin Marinas wrote:
> > > On Fri, May 27, 2016 at 10:42:59AM +0200, Arnd Bergmann wrote:
> > > > On Friday, May 27, 2016 8:03:57 AM CEST Heiko Carstens wrote:
> > > > > > > > > Cost wise, this seems like it all cancels out in the end, but what
> > > > > > > > > do I know?
> > > > > > > > 
> > > > > > > > I think you know something, and I also think Heiko and other s390 guys
> > > > > > > > know something as well. So I'd like to listen their arguments here.
> > > > > 
> > > > > If it comes to 64 bit arguments for compat system calls: s390 also has an
> > > > > x32-like ABI extension which allows user space to use full 64 bit
> > > > > registers. As far as I know hardly anybody ever made use of that.
> > > > > 
> > > > > However even if that would be widely used, to me it wouldn't make sense to
> > > > > add new compat system calls which allow 64 bit arguments, simply because
> > > > > something like
> > > > > 
> > > > > c = (u32)a | (u64)b << 32;
> > > > > 
> > > > > can be done with a single 1-cycle instruction. It's just not worth the
> > > > > extra effort to maintain additional system call variants.
> > > > 
> > > > For reference, both tile and mips also have separate 32-bit ABIs that are
> > > > only used on 64-bit kernels (aside from the normal 32-bit ABI). Tile
> > > > does it like s390 and passes 64-bit arguments as pairs, while MIPS
> > > > and x86 and pass them as single registers.
> > > 
> > > AFAIK, x32 also requires that the upper half of a 64-bit reg is zeroed
> > > by the user when a 32-bit value is passed. We could require the same on
> > > AArch64/ILP32 but I'm a bit uneasy on trusting a multitude of C
> > > libraries on this.
> > 
> > It's not about trusting a C library, it's about ensuring malicious code
> > cannot pass argumentst that the kernel code assumes will never happen.
> 
> At least for pointers and sizes, we have additional checks in place
> already, like __access_ok(). Most of the syscalls should be safe since
> they either go through some compat functions taking 32-bit arguments or
> are routed to native functions which already need to cope with a full
> random 64-bit value.

It's not a good idea to rely on current implementation. Implementation
may be changed and it's impossible to check each and every patch
against register top-halves correctness.

> 
> On arm64, I think the only risk comes from syscall handlers expecting
> 32-bit arguments but using 64-bit types. Apart from pointer types, I
> don't expect this to happen but we could enforce it via a
> BUILD_BUG_ON(sizeof(t) > 4 && !__TYPE_IS_PTR(t)) in __SC_DELOUSE as per
> the s390 implementation. With ILP32 if we go for 64-bit off_t, those
> syscalls would be routed directly to the native layer.
> 

64-bit off_t doesn't imply we'd rout it directly. At first glance it's
looking reasonable but there are other considerations like simplicity and
unification with aarch32 that may become more important. That's what
David pointed out.

So, we have 3 options for now:
1. Clear top halves in entry.S which means we pass off_t as a pair.
   The cost is performance (didn't measure it yet and doubt about it
   makes serious impact). The advantage is simplicity and unification with
   aarch32, as I mentioned above. And David likes it. And it mininizes
   the amount of changes on glibc side.
2. Clear top halves in in separated file hosted wrappers.
3. Clear top halves in I-cache and tail optimization friendly in-site wrappers.

2 and 3 are the same from ABI point of view.

2 is the worst for me as it is the most complex in implementation and 
I-cache and tail optimization non-friendly. But Heiko likes it.
 
3 is what Catalin is talking about, and it was my initial approach.
Though I didn't made compiler to do tail optimization, I think we can
do it.

But 2 is what we have now. And I'd choose it. We'll never get ilp32 done
if will roll back previously agreed decisions again and again.

Yury.

> -- 
> Catalin


From matthias.bgg at gmail.com  Fri May 27 10:07:04 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Fri, 27 May 2016 19:07:04 +0200
Subject: [PATCH v1 0/6] drivers: net: xgene: Fix 1G hot-plug and module
 support
In-Reply-To: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
References: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
Message-ID: <57487EB8.6040309@gmail.com>

On 27/05/16 09:22, Iyappan Subramanian wrote:
> This patchset addresses the following issues,
>
> 1. hot-plug issue on the SGMII 1G interface
> 	- by adding a driver for MDIO management
> 2. fixes the kernel crash when the driver loaded as an kernel module
> 	- by fixing hardware cleanups and rearrange kernel API calls
>
> Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
> ---

Without this patches we observed problems on some hardware when the 
driver was loaded as modules, as well as the kernel crash when 
unloading/loading the module.

I tested this with an older FW and both issues are fixed, so you can add

Tested-by: Matthias Brugger <mbrugger at suse.com>

But I think the way the series is split in different patches is not 
correct. Patch 1 on its own won't compile and get fixed in patch 2.
Although I think backward compatibility to older firmware should be part 
of the changes which provide support for the new firmware and should not 
be a patch apart. Said this, I'm not sure if just squashing patch 1 and 
patch 2 is the right to do, as to me it seems as if some other fixes 
slipped into the series.

 From my point of view, patch 4 and 5 should be squashed, as xge0clk and 
sge1clk nodes are useless when the mdio nodes are present.

Regards,
Matthias

>
> Iyappan Subramanian (6):
>    drivers: net: xgene: MAC and PHY configuration changes
>    drivers: net: xgene: Backward compatibility with older firmware
>    drivers: net: phy: Add MDIO driver
>    dtb: xgene: Add MDIO node
>    dtb: xgene: Remove clock nodes
>    drivers: net: xgene: Fix module load/unload crash
>
>   arch/arm64/boot/dts/apm/apm-merlin.dts            |  10 +
>   arch/arm64/boot/dts/apm/apm-mustang.dts           |  12 +
>   arch/arm64/boot/dts/apm/apm-shadowcat.dtsi        |  23 +-
>   arch/arm64/boot/dts/apm/apm-storm.dtsi            |  38 +-
>   drivers/net/ethernet/apm/xgene/Kconfig            |   1 +
>   drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    | 241 ++++++----
>   drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    |  18 +-
>   drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 325 ++++++++-----
>   drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |  36 +-
>   drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 191 +++++++-
>   drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h |   8 +
>   drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c |  66 ++-
>   drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h |   4 +
>   drivers/net/phy/Kconfig                           |   7 +
>   drivers/net/phy/Makefile                          |   1 +
>   drivers/net/phy/mdio-xgene.c                      | 531 ++++++++++++++++++++++
>   drivers/net/phy/mdio-xgene.h                      | 140 ++++++
>   17 files changed, 1373 insertions(+), 279 deletions(-)
>   create mode 100644 drivers/net/phy/mdio-xgene.c
>   create mode 100644 drivers/net/phy/mdio-xgene.h
>



From broonie at kernel.org  Fri May 27 10:14:03 2016
From: broonie at kernel.org (Mark Brown)
Date: Fri, 27 May 2016 18:14:03 +0100
Subject: [PATCH v4 10/18] ASoC: sti: Update DT example to match the
 driver code
In-Reply-To: <1464192412-16386-12-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
 <1464192412-16386-12-git-send-email-peter.griffin@linaro.org>
Message-ID: <20160527171403.GN16172@sirena.org.uk>

On Wed, May 25, 2016 at 05:06:44PM +0100, Peter Griffin wrote:
> uniperiph-id, version and mode are ST specific bindings and
> need the 'st,' prefix. Update the examples, as otherwise copying
> them yields a runtime error parsing the DT node.

You've not copied me on the rest of the series so I've no idea what's
going on with dependencies.  When sending a patch series it is important
to ensure that all the various maintainers understand what the
relationship between the patches as the expecation is that there will be
interdependencies.  Either copy everyone on the whole series or at least
copy them on the cover letter and explain what's going on.  If there are
no strong interdependencies then it's generally simplest to just send
the patches separately to avoid any possible confusion.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160527/17a8742a/attachment.sig>

From catalin.marinas at arm.com  Fri May 27 10:14:25 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 27 May 2016 18:14:25 +0100
Subject: [PATCH v2 5/5] ACPI: ARM64: support for ACPI_TABLE_UPGRADE
In-Reply-To: <1463674518-22477-6-git-send-email-aleksey.makarov@linaro.org>
References: <1463674518-22477-1-git-send-email-aleksey.makarov@linaro.org>
 <1463674518-22477-6-git-send-email-aleksey.makarov@linaro.org>
Message-ID: <20160527171424.GG10909@e104818-lin.cambridge.arm.com>

On Thu, May 19, 2016 at 07:15:16PM +0300, Aleksey Makarov wrote:
> diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
> index aee323b..d75f6c7 100644
> --- a/arch/arm64/include/asm/acpi.h
> +++ b/arch/arm64/include/asm/acpi.h
> @@ -113,4 +113,6 @@ static inline const char *acpi_get_enable_method(int cpu)
>  pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr);
>  #endif
>  
> +#define ACPI_TABLE_UPGRADE_MAX_PHYS PFN_PHYS(max_pfn)
> +
>  #endif /*_ASM_ACPI_H*/
> diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
> index feab2ee..4bce811 100644
> --- a/arch/arm64/kernel/setup.c
> +++ b/arch/arm64/kernel/setup.c
> @@ -261,11 +261,13 @@ void __init setup_arch(char **cmdline_p)
>  	efi_init();
>  	arm64_memblock_init();
>  
> +	paging_init();
> +
> +	acpi_table_upgrade();
> +
>  	/* Parse the ACPI tables for possible boot-time configuration */
>  	acpi_boot_table_init();
>  
> -	paging_init();
> -
>  	if (acpi_disabled)
>  		unflatten_device_tree();

So ACPI_TABLE_UPGRADE_MAX_PHYS is defined in terms of max_pfn and
presumably used by acpi_table_upgrade(). max_pfn is only initialised in
the arm64 bootmem_init() called just below the last line of context in
the hunk above.

-- 
Catalin


From matthias.bgg at gmail.com  Fri May 27 10:07:26 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Fri, 27 May 2016 19:07:26 +0200
Subject: [PATCH v1 1/6] drivers: net: xgene: MAC and PHY configuration
 changes
In-Reply-To: <1464333768-26150-2-git-send-email-isubramanian@apm.com>
References: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
 <1464333768-26150-2-git-send-email-isubramanian@apm.com>
Message-ID: <57487ECE.7010309@gmail.com>

On 27/05/16 09:22, Iyappan Subramanian wrote:
> This patch fixes MAC configuration to support 10/100GbE for SGMII and
> link_state call back. It also sets pdata->mdio_driver flag based on
> ethernet mdio subnode and prepare for MDIO driver support.
>
> In summary, following are the changes,
>
> - Added set_speed function pointer in mac_ops
> - Changed link_state to call the set_speed
> - Add 10/100 support for SGMII based 1G
> - Fixed mac_init for 1G
>
> - Call mac_ops rx_enable/disable and tx_enable/disable function pointers

This is just a code clean-up, right? If so, this should be a patch apart.

> - Add acpi_phy_find_device to find PHY using phy-handle reference object
> - Changing phy_start and phy_stop calls based on phy_dev object existence
> - Calling phy_connect based on pdata->mdio_driver flag
>
> Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
> Tested-by: Fushen Chen <fchen at apm.com>
> Tested-by: Toan Le <toanle at apm.com>
> ---
>   drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    | 189 +++++++++++++---------
>   drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    |   4 +
>   drivers/net/ethernet/apm/xgene/xgene_enet_main.c  |  40 +++--
>   drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |   2 +
>   drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 106 +++++++++++-
>   drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h |   8 +
>   drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h |   4 +
>   7 files changed, 256 insertions(+), 97 deletions(-)
>
> diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
> index 2f5638f..6bc8360 100644
> --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
> +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
> @@ -512,14 +512,11 @@ static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata)

[...]

>   static void xgene_sgmac_init(struct xgene_enet_pdata *p)
>   {
>   	u32 data, loop = 10;
> -	u32 offset = p->port_id * 4;
> +	u32 offset = 0;
>   	u32 enet_spare_cfg_reg, rsif_config_reg;
>   	u32 cfg_bypass_reg, rx_dv_gate_reg;
>
>   	xgene_sgmac_reset(p);
>
>   	/* Enable auto-negotiation */
> -	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x1000);
> +	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2,
> +			    0x8000);
> +	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x9000);
>   	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2, 0);
>
>   	while (loop--) {
> @@ -256,16 +343,14 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
>   	if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS))
>   		netdev_err(p->ndev, "Auto-negotiation failed\n");
>
> -	data = xgene_enet_rd_mac(p, MAC_CONFIG_2_ADDR);
> -	ENET_INTERFACE_MODE2_SET(&data, 2);
> -	xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, data | FULL_DUPLEX2);
> -	xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, ENET_GHD_MODE);
> +	xgene_sgmac_set_speed(p);
>
>   	if (p->enet_id == XGENE_ENET1) {
>   		enet_spare_cfg_reg = ENET_SPARE_CFG_REG_ADDR;
>   		rsif_config_reg = RSIF_CONFIG_REG_ADDR;
>   		cfg_bypass_reg = CFG_BYPASS_ADDR;
>   		rx_dv_gate_reg = SG_RX_DV_GATE_REG_0_ADDR;
> +		offset = p->port_id * 4;

At least for me it is not clear where the "4" comes from. Maybe you can 
add a comment or declare a constant for that.
Anyway this looks like it fixes the driver for xgene2-sgnet and therefor 
should go into a separate patch, or am I wrong?

Regards,
Matthias



From stefan at agner.ch  Fri May 27 10:28:45 2016
From: stefan at agner.ch (Stefan Agner)
Date: Fri, 27 May 2016 10:28:45 -0700
Subject: [PATCH v3 4/4] soc: Add SoC driver for Freescale Vybrid platform
In-Reply-To: <20160527100817.GA8294@Sanchayan-Arch.localdomain>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
 <CAL_JsqKCwy=aXveTfnaQuZ5b3Ld9nzABgPfdPm1JX3CBuvzG+Q@mail.gmail.com>
 <20160527063301.GB1554@Sanchayan-Arch.localdomain>
 <9495361.v6aft1QR0M@wuerfel>
 <20160527100817.GA8294@Sanchayan-Arch.localdomain>
Message-ID: <475f53d2bb4c611bfe1c6652215b8626@agner.ch>

On 2016-05-27 03:08, maitysanchayan at gmail.com wrote:
> On 16-05-27 10:31:55, Arnd Bergmann wrote:
>> On Friday, May 27, 2016 12:03:01 PM CEST maitysanchayan at gmail.com wrote:
>> >
>> > So if I understand correctly, the binding at the SoC level is fine.
>> > Keeping that but removing the additional made-up properties, viz. below
>> >
>> > rom-revision: phandle to the on-chip ROM node
>> > mscm: phandle to the MSCM CPU configuration node
>> > nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
>> > nvmem-cell-names: should contain string names "cfg0" and "cfg1"
>> >
>> > would be fine?
>> >
>> > We would have something similar to here
>> > http://www.spinics.net/lists/devicetree/msg80655.html
>> >
>> > but now with the DT binding under SoC bus.
>> >
>>
>>
>> You look up the OTP device as a syscon here, which seems odd since there
>> is already an nvmem driver for it. Shouldn't you use the nvmem API for
>> that?
>>
>> 	Arnd
> 
> I need the following 
> 
> nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
> nvmem-cell-names: should contain string names "cfg0" and "cfg1"
> 
> to be able to use the NVMEM consumer API.

I did not tested it, but it seems the NVMEM consumer API has some kind
of non-DT fallback:
http://lxr.free-electrons.com/source/drivers/nvmem/core.c#L827

Right now, it seems to me that it does not handle the case where we have
a of_node but don't want to use it... You might need to add some extra
handling if there is a of_node without nvmem-cell-names/nvmem-cells, and
fall back to nvmem_cell_get_from_list.

--
Stefan


From catalin.marinas at arm.com  Fri May 27 10:36:53 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Fri, 27 May 2016 18:36:53 +0100
Subject: [PATCH 01/23] all: syscall wrappers: add documentation
In-Reply-To: <20160527165806.GA20966@yury-N73SV>
References: <6293194.tGy03QJ9ME@wuerfel> <13240365.okADkKsTBJ@wuerfel>
 <20160527093052.GB7865@e104818-lin.cambridge.arm.com>
 <5422652.7gdoDlB8u0@wuerfel>
 <20160527130446.GD7865@e104818-lin.cambridge.arm.com>
 <20160527165806.GA20966@yury-N73SV>
Message-ID: <20160527173653.GA19961@e104818-lin.cambridge.arm.com>

On Fri, May 27, 2016 at 07:58:06PM +0300, Yury Norov wrote:
> So, we have 3 options for now:
> 1. Clear top halves in entry.S which means we pass off_t as a pair.
>    The cost is performance (didn't measure it yet and doubt about it
>    makes serious impact). The advantage is simplicity and unification with
>    aarch32, as I mentioned above. And David likes it. And it mininizes
>    the amount of changes on glibc side.
> 2. Clear top halves in in separated file hosted wrappers.
> 3. Clear top halves in I-cache and tail optimization friendly in-site wrappers.
> 
> 2 and 3 are the same from ABI point of view.
> 
> 2 is the worst for me as it is the most complex in implementation and 
> I-cache and tail optimization non-friendly. But Heiko likes it.
>  
> 3 is what Catalin is talking about, and it was my initial approach.
> Though I didn't made compiler to do tail optimization, I think we can
> do it.

I don't fully understand the difference between 2 and 3. My comment was
more around annotating the wrappers in (2) with __naked to no longer
generate function prologue/epilogue. They would still be in a separate
kernel/compat_wrapper.c file.

I can't figure out how you would have in-place wrappers for all
syscalls. You can indeed handle the current COMPAT_SYSCALL_DEFINE via
__SC_DELOUSE (and penalising the AArch32/compat support slightly) but
there is no solution for native SYSCALL_DEFINE functions to do it
in-place.

> But 2 is what we have now. And I'd choose it. We'll never get ilp32 done
> if will roll back previously agreed decisions again and again.

I would rather roll back a decision than going ahead with a wrong one.
Note that this is *ABI*, not a driver that you can fix upstream later.

Since yesterday, I realised that (2) requires further annotations and
wrapping for the native and compat syscalls used by ILP32 just to cope
with pointers. Also given davem's comments, (1) starts to look a bit
more appealing (I don't like reverting such decisions either, I'd have
to review the code again and again).

-- 
Catalin


From mark.rutland at arm.com  Fri May 27 10:46:36 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Fri, 27 May 2016 18:46:36 +0100
Subject: [PATCH] arm64: kasan: instrument user memory access API
In-Reply-To: <cea39367-65b6-62df-7e4c-57ae1ce36dcc@linaro.org>
References: <1464288231-11304-1-git-send-email-yang.shi@linaro.org>
 <57482930.6020608@virtuozzo.com>
 <cea39367-65b6-62df-7e4c-57ae1ce36dcc@linaro.org>
Message-ID: <20160527174635.GL24469@leverpostej>

On Fri, May 27, 2016 at 09:34:03AM -0700, Shi, Yang wrote:
> On 5/27/2016 4:02 AM, Andrey Ryabinin wrote:
> >
> >
> >On 05/26/2016 09:43 PM, Yang Shi wrote:
> >>The upstream commit 1771c6e1a567ea0ba2cccc0a4ffe68a1419fd8ef
> >>("x86/kasan: instrument user memory access API") added KASAN instrument to
> >>x86 user memory access API, so added such instrument to ARM64 too.
> >>
> >>Tested by test_kasan module.
> >>
> >>Signed-off-by: Yang Shi <yang.shi at linaro.org>
> >>---
> >> arch/arm64/include/asm/uaccess.h | 18 ++++++++++++++++--
> >> 1 file changed, 16 insertions(+), 2 deletions(-)
> >
> >Please, cover __copy_from_user() and __copy_to_user() too.
> >Unlike x86, your patch doesn't instrument these two.

Argh, I missed those when reviewing. My bad.

> I should elaborated this in my review. Yes, I did think about it,
> but unlike x86, __copy_to/from_user are implemented by asm code on
> ARM64. If I add kasan_check_read/write into them, I have to move the
> registers around to prepare the parameters for kasan calls, then
> restore them after the call, for example the below code for
> __copy_to_user:
> 
>         mov     x9, x0
>         mov     x10, x1
>         mov     x11, x2
>         mov     x0, x10
>         mov     x1, x11
>         bl      kasan_check_read
>         mov     x0, x9
>         mov     x1, x10

There's no need to alter the assembly.

Rename the functions (e.g. have __arch_raw_copy_from_user), and add
static inline wrappers in uaccess.h that do the kasan calls before
calling the assembly functions.

That gives the compiler the freedom to do the right thing, and avoids
horrible ifdeffery in the assembly code.

> So, I'm wondering if it is worth or not since __copy_to/from_user
> are just called at a couple of places, i.e. sctp, a couple of
> drivers, etc and not used too much.

[mark at leverpostej:~/src/linux]% git grep -w __copy_to_user -- ^arch | wc -l
63
[mark at leverpostej:~/src/linux]% git grep -w __copy_from_user -- ^arch | wc -l
47

That's a reasonable number of callsites.

If we're going to bother adding this, it should be complete. So please
do update __copy_from_user and __copy_to_user.

> Actually, I think some of them
> could be replaced by __copy_to/from_user_inatomic.

Given the number of existing callers outside of arch code, I think we'll
get far more traction reworking the arm64 parts for now.

Thanks,
Mark.


From maitysanchayan at gmail.com  Fri May 27 10:56:41 2016
From: maitysanchayan at gmail.com (maitysanchayan at gmail.com)
Date: Fri, 27 May 2016 23:26:41 +0530
Subject: [PATCH v3 4/4] soc: Add SoC driver for Freescale Vybrid platform
In-Reply-To: <475f53d2bb4c611bfe1c6652215b8626@agner.ch>
References: <cover.1463737502.git.maitysanchayan@gmail.com>
 <CAL_JsqKCwy=aXveTfnaQuZ5b3Ld9nzABgPfdPm1JX3CBuvzG+Q@mail.gmail.com>
 <20160527063301.GB1554@Sanchayan-Arch.localdomain>
 <9495361.v6aft1QR0M@wuerfel>
 <20160527100817.GA8294@Sanchayan-Arch.localdomain>
 <475f53d2bb4c611bfe1c6652215b8626@agner.ch>
Message-ID: <20160527175641.GA10705@Sanchayan-Arch.localdomain>

Hello Stefan,

On 16-05-27 10:28:45, Stefan Agner wrote:
> On 2016-05-27 03:08, maitysanchayan at gmail.com wrote:
> > On 16-05-27 10:31:55, Arnd Bergmann wrote:
> >> On Friday, May 27, 2016 12:03:01 PM CEST maitysanchayan at gmail.com wrote:
> >> >
> >> > So if I understand correctly, the binding at the SoC level is fine.
> >> > Keeping that but removing the additional made-up properties, viz. below
> >> >
> >> > rom-revision: phandle to the on-chip ROM node
> >> > mscm: phandle to the MSCM CPU configuration node
> >> > nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
> >> > nvmem-cell-names: should contain string names "cfg0" and "cfg1"
> >> >
> >> > would be fine?
> >> >
> >> > We would have something similar to here
> >> > http://www.spinics.net/lists/devicetree/msg80655.html
> >> >
> >> > but now with the DT binding under SoC bus.
> >> >
> >>
> >>
> >> You look up the OTP device as a syscon here, which seems odd since there
> >> is already an nvmem driver for it. Shouldn't you use the nvmem API for
> >> that?
> >>
> >> 	Arnd
> > 
> > I need the following 
> > 
> > nvmem-cells: phandles to two OCOTP child nodes ocotp_cfg0 and ocotp_cfg1
> > nvmem-cell-names: should contain string names "cfg0" and "cfg1"
> > 
> > to be able to use the NVMEM consumer API.
> 
> I did not tested it, but it seems the NVMEM consumer API has some kind
> of non-DT fallback:
> http://lxr.free-electrons.com/source/drivers/nvmem/core.c#L827
> 
> Right now, it seems to me that it does not handle the case where we have
> a of_node but don't want to use it... You might need to add some extra
> handling if there is a of_node without nvmem-cell-names/nvmem-cells, and
> fall back to nvmem_cell_get_from_list.
> 

I have already looked at the core nvmem code for options but wanted to avoid
any additons if possible.

However if adding the nvmem properties at the SoC node level is frowned upon
I will make the necessary changes required.

Regards,
Sanchayan.


From yang.shi at linaro.org  Fri May 27 11:05:22 2016
From: yang.shi at linaro.org (Shi, Yang)
Date: Fri, 27 May 2016 11:05:22 -0700
Subject: [PATCH] arm64: kasan: instrument user memory access API
In-Reply-To: <20160527174635.GL24469@leverpostej>
References: <1464288231-11304-1-git-send-email-yang.shi@linaro.org>
 <57482930.6020608@virtuozzo.com>
 <cea39367-65b6-62df-7e4c-57ae1ce36dcc@linaro.org>
 <20160527174635.GL24469@leverpostej>
Message-ID: <9980d1db-abde-8c27-a581-17d72567903f@linaro.org>

On 5/27/2016 10:46 AM, Mark Rutland wrote:
> On Fri, May 27, 2016 at 09:34:03AM -0700, Shi, Yang wrote:
>> On 5/27/2016 4:02 AM, Andrey Ryabinin wrote:
>>>
>>>
>>> On 05/26/2016 09:43 PM, Yang Shi wrote:
>>>> The upstream commit 1771c6e1a567ea0ba2cccc0a4ffe68a1419fd8ef
>>>> ("x86/kasan: instrument user memory access API") added KASAN instrument to
>>>> x86 user memory access API, so added such instrument to ARM64 too.
>>>>
>>>> Tested by test_kasan module.
>>>>
>>>> Signed-off-by: Yang Shi <yang.shi at linaro.org>
>>>> ---
>>>> arch/arm64/include/asm/uaccess.h | 18 ++++++++++++++++--
>>>> 1 file changed, 16 insertions(+), 2 deletions(-)
>>>
>>> Please, cover __copy_from_user() and __copy_to_user() too.
>>> Unlike x86, your patch doesn't instrument these two.
>
> Argh, I missed those when reviewing. My bad.
>
>> I should elaborated this in my review. Yes, I did think about it,
>> but unlike x86, __copy_to/from_user are implemented by asm code on
>> ARM64. If I add kasan_check_read/write into them, I have to move the
>> registers around to prepare the parameters for kasan calls, then
>> restore them after the call, for example the below code for
>> __copy_to_user:
>>
>>         mov     x9, x0
>>         mov     x10, x1
>>         mov     x11, x2
>>         mov     x0, x10
>>         mov     x1, x11
>>         bl      kasan_check_read
>>         mov     x0, x9
>>         mov     x1, x10
>
> There's no need to alter the assembly.
>
> Rename the functions (e.g. have __arch_raw_copy_from_user), and add
> static inline wrappers in uaccess.h that do the kasan calls before
> calling the assembly functions.
>
> That gives the compiler the freedom to do the right thing, and avoids
> horrible ifdeffery in the assembly code.

Thanks for the suggestion, will address in v2.

Yang

>
>> So, I'm wondering if it is worth or not since __copy_to/from_user
>> are just called at a couple of places, i.e. sctp, a couple of
>> drivers, etc and not used too much.
>
> [mark at leverpostej:~/src/linux]% git grep -w __copy_to_user -- ^arch | wc -l
> 63
> [mark at leverpostej:~/src/linux]% git grep -w __copy_from_user -- ^arch | wc -l
> 47
>
> That's a reasonable number of callsites.
>
> If we're going to bother adding this, it should be complete. So please
> do update __copy_from_user and __copy_to_user.
>
>> Actually, I think some of them
>> could be replaced by __copy_to/from_user_inatomic.
>
> Given the number of existing callers outside of arch code, I think we'll
> get far more traction reworking the arm64 parts for now.
>
> Thanks,
> Mark.
>



From swarren at wwwdotorg.org  Fri May 27 11:35:12 2016
From: swarren at wwwdotorg.org (Stephen Warren)
Date: Fri, 27 May 2016 12:35:12 -0600
Subject: [PATCH] arm: tegra124: remove commas from unit addresses
In-Reply-To: <1464366471-23832-1-git-send-email-marcel.ziswiler@toradex.com>
References: <1464366471-23832-1-git-send-email-marcel.ziswiler@toradex.com>
Message-ID: <57489360.1030300@wwwdotorg.org>

On 05/27/2016 10:27 AM, Marcel Ziswiler wrote:
> Remove commas from unit addresses as suggested by Rob Herring upon me
> posting initial Apalis TK1 support:
>
> http://article.gmane.org/gmane.linux.ports.tegra/26608

> diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts

> -	gpu at 0,57000000 {
> +	gpu at 57000000 {
>   		/*
>   		 * Node left disabled on purpose - the bootloader will enable
>   		 * it after having set the VPR up

The last time a similar patch was proposed[1], I pointed out that U-Boot 
uses the node name to enable the node, so this change will break GPU 
functionality on this board. U-Boot has since been updated to find the 
node to enable using compatible value rather than hard-coding the node 
name, but this doesn't help people with existing bootloader binaries; 
kernel changes shouldn't force them to upgrade the bootloader. I think 
the DT node names are part of the ABI and shouldn't be changed. We can 
fix this for completely new SoCs, but not existing SoCs.

[1] http://www.spinics.net/lists/devicetree/msg122164.html "[PATCH] ARM: 
tegra: Remove 0, prefix from unit-addresses".



From geoff at infradead.org  Fri May 27 12:19:45 2016
From: geoff at infradead.org (Geoff Levand)
Date: Fri, 27 May 2016 12:19:45 -0700
Subject: Help needed with kexec on arm64
In-Reply-To: <20160527135820.GM19428@n2100.arm.linux.org.uk>
References: <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org>
 <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160511005334.GA8417@linaro.org>
 <DB5PR04MB1688C3F122091109E6BD9B68E6740@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160519110307.GA4941@linaro.org>
 <DB5PR04MB16887FF10CEA6AA9BF990F0DE6420@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160527135820.GM19428@n2100.arm.linux.org.uk>
Message-ID: <1464376785.12343.3.camel@infradead.org>

On Fri, 2016-05-27 at 14:58 +0100, Russell King - ARM Linux wrote:
> On Fri, May 27, 2016 at 11:51:03AM +0000, Harninder Rai wrote:Hello Takahiro Akashi,
> > 
> > Please see the following log which I was talking about in my last communication
> > Any idea as to what could be wrong just when I move from RAM based rootfs to SD based rootfs?

> debug output... if the architecture is usefully printing stuff like
> memory layouts etc.
You should be able to get more information by using kexec -d to enable

Also, use the latest from here:

  git://git.kernel.org/pub/scm/linux/kernel/git/geoff/kexec-tools.git
  
-Geoff


From fengguang.wu at intel.com  Fri May 27 13:08:51 2016
From: fengguang.wu at intel.com (kbuild test robot)
Date: Sat, 28 May 2016 04:08:51 +0800
Subject: [rjarzmik:work/ac97 4/7] warning: (SND_SOC_WM9713) selects
 AC97_BUS_COMPAT which has unmet direct dependencies (SOUND && ..)
Message-ID: <201605280449.Wn9zuWFS%fengguang.wu@intel.com>

tree:   https://github.com/rjarzmik/linux work/ac97
head:   3350c2230e9e1331442724f919c86542d9668d4b
commit: 8715b68899fdeea2968c7760843a0f908b4def2c [4/7] ASoC: wm9713: add ac97 new bus support
config: sparc64-allyesconfig (attached as .config)
compiler: sparc64-linux-gnu-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        git checkout 8715b68899fdeea2968c7760843a0f908b4def2c
        # save the attached .config to linux build tree
        make.cross ARCH=sparc64 

All warnings (new ones prefixed by >>):

warning: (SND_SOC_WM9713) selects AC97_BUS_COMPAT which has unmet direct dependencies (SOUND && !M68K && !UML && SND && !AC97_BUS)

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 45947 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160528/1f394e09/attachment-0001.obj>

From robert.jarzmik at free.fr  Fri May 27 13:26:58 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Fri, 27 May 2016 22:26:58 +0200
Subject: [RFC PATCH v2 6/7] ARM: pxa: mioa701 convert to the new AC97 bus
In-Reply-To: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
References: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
Message-ID: <1464380819-19075-7-git-send-email-robert.jarzmik@free.fr>

This migration implies :
 - wm9713 device is removed, it will be auto-probed
 - the AC97 bit clock is added as the pxa internally generated 13MHz
   clock

Signed-off-by: Robert Jarzmik <robert.jarzmik at free.fr>
---
 arch/arm/mach-pxa/mioa701.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 38a96a193dc4..e26bace43147 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -19,6 +19,7 @@
  *
  */
 
+#include <linux/clkdev.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -682,7 +683,6 @@ MIO_SIMPLE_DEV(mioa701_led,	  "leds-gpio",	    &gpio_led_info)
 MIO_SIMPLE_DEV(pxa2xx_pcm,	  "pxa2xx-pcm",	    NULL)
 MIO_SIMPLE_DEV(mioa701_sound,	  "mioa701-wm9713", NULL)
 MIO_SIMPLE_DEV(mioa701_board,	  "mioa701-board",  NULL)
-MIO_SIMPLE_DEV(wm9713_acodec,	  "wm9713-codec",   NULL);
 MIO_SIMPLE_DEV(gpio_vbus,	  "gpio-vbus",      &gpio_vbus_data);
 MIO_SIMPLE_DEV(mioa701_camera,	  "soc-camera-pdrv",&iclink);
 
@@ -690,7 +690,6 @@ static struct platform_device *devices[] __initdata = {
 	&mioa701_gpio_keys,
 	&mioa701_backlight,
 	&mioa701_led,
-	&wm9713_acodec,
 	&pxa2xx_pcm,
 	&mioa701_sound,
 	&power_dev,
@@ -742,6 +741,15 @@ static void __init mioa701_machine_init(void)
 	__raw_writel(0x0001c391, MCATT0);
 	__raw_writel(0x0001c391, MCIO0);
 
+	rc = clk_add_alias("ac97_clk", "pxa2xx-ac97:0", "AC97CONFCLK",
+			   &pxa_device_ac97.dev);
+	if (rc)
+		pr_err("PXA2xx AC97 clock1 alias error: %d\n", rc);
+
+	rc = clk_add_alias("ac97_clk", "pxa2xx-ac97:1", "AC97CONFCLK",
+			   &pxa_device_ac97.dev);
+	if (rc)
+		pr_err("PXA2xx AC97 clock2 alias error: %d\n", rc);
 
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(mioa701_pin_config));
 	pxa_set_ffuart_info(NULL);
-- 
2.1.4



From robert.jarzmik at free.fr  Fri May 27 13:26:59 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Fri, 27 May 2016 22:26:59 +0200
Subject: [RFC PATCH v2 7/7] ASoC: mioa701_wm9713: convert to new ac97 bus
In-Reply-To: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
References: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
Message-ID: <1464380819-19075-8-git-send-email-robert.jarzmik@free.fr>

Convert to the new auto-probing ac97 bus, which changes the device name.

Signed-off-by: Robert Jarzmik <robert.jarzmik at free.fr>
---
 sound/soc/pxa/mioa701_wm9713.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
index 5c8f9db50a47..4ed10e6ff5d1 100644
--- a/sound/soc/pxa/mioa701_wm9713.c
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -149,7 +149,7 @@ static struct snd_soc_dai_link mioa701_dai[] = {
 		.stream_name = "AC97 HiFi",
 		.cpu_dai_name = "pxa2xx-ac97",
 		.codec_dai_name = "wm9713-hifi",
-		.codec_name = "wm9713-codec",
+		.codec_name = "pxa2xx-ac97:0",
 		.init = mioa701_wm9713_init,
 		.platform_name = "pxa-pcm-audio",
 		.ops = &mioa701_ops,
@@ -159,7 +159,7 @@ static struct snd_soc_dai_link mioa701_dai[] = {
 		.stream_name = "AC97 Aux",
 		.cpu_dai_name = "pxa2xx-ac97-aux",
 		.codec_dai_name ="wm9713-aux",
-		.codec_name = "wm9713-codec",
+		.codec_name = "pxa2xx-ac97:0",
 		.platform_name = "pxa-pcm-audio",
 		.ops = &mioa701_ops,
 	},
-- 
2.1.4



From robert.jarzmik at free.fr  Fri May 27 13:26:55 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Fri, 27 May 2016 22:26:55 +0200
Subject: [RFC PATCH v2 3/7] ASoC: add new ac97 bus support
In-Reply-To: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
References: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
Message-ID: <1464380819-19075-4-git-send-email-robert.jarzmik@free.fr>

Add the new ac97 bus support, with ac97 bus automatic probing.

Signed-off-by: Robert Jarzmik <robert.jarzmik at free.fr>
---
 sound/Kconfig     | 2 ++
 sound/Makefile    | 1 +
 sound/soc/Kconfig | 4 ++++
 3 files changed, 7 insertions(+)

diff --git a/sound/Kconfig b/sound/Kconfig
index 5a240e050ae6..c7e1cbe84951 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -80,6 +80,8 @@ source "sound/hda/Kconfig"
 
 source "sound/ppc/Kconfig"
 
+source "sound/ac97/Kconfig"
+
 source "sound/aoa/Kconfig"
 
 source "sound/arm/Kconfig"
diff --git a/sound/Makefile b/sound/Makefile
index 77320709fd26..74728aee25d5 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SND_AOA) += aoa/
 
 # This one must be compilable even if sound is configured out
 obj-$(CONFIG_AC97_BUS) += ac97_bus.o
+obj-$(CONFIG_AC97_BUS_NEW) += ac97/
 
 ifeq ($(CONFIG_SND),y)
   obj-y += last.o
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 182d92efc7c8..5ad0a0422054 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -6,6 +6,7 @@ menuconfig SND_SOC
 	tristate "ALSA for SoC audio support"
 	select SND_PCM
 	select AC97_BUS if SND_SOC_AC97_BUS
+	select AC97_BUS_NEW if SND_SOC_AC97_BUS_NEW
 	select SND_JACK
 	select REGMAP_I2C if I2C
 	select REGMAP_SPI if SPI_MASTER
@@ -25,6 +26,9 @@ if SND_SOC
 config SND_SOC_AC97_BUS
 	bool
 
+config SND_SOC_AC97_BUS_NEW
+	bool
+
 config SND_SOC_GENERIC_DMAENGINE_PCM
 	bool
 	select SND_DMAENGINE_PCM
-- 
2.1.4



From robert.jarzmik at free.fr  Fri May 27 13:26:56 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Fri, 27 May 2016 22:26:56 +0200
Subject: [RFC PATCH v2 4/7] ASoC: wm9713: add ac97 new bus support
In-Reply-To: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
References: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
Message-ID: <1464380819-19075-5-git-send-email-robert.jarzmik@free.fr>

Add support for the new ac97 bus model, where devices are automatically
discovered on AC-Links.

Signed-off-by: Robert Jarzmik <robert.jarzmik at free.fr>
---
 sound/soc/codecs/Kconfig  |  1 +
 sound/soc/codecs/wm9713.c | 62 ++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 649e92a252ae..2566962c990e 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -977,6 +977,7 @@ config SND_SOC_WM9712
 config SND_SOC_WM9713
 	tristate
 	select REGMAP_AC97
+	select AC97_BUS_COMPAT
 
 # Amp
 config SND_SOC_LM4857
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 9849643ef809..6cbbf4eda5fc 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -22,7 +22,8 @@
 #include <linux/regmap.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
-#include <sound/ac97_codec.h>
+#include <sound/ac97/codec.h>
+#include <sound/ac97/compat.h>
 #include <sound/initval.h>
 #include <sound/pcm_params.h>
 #include <sound/tlv.h>
@@ -1207,14 +1208,13 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
 	struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
 	struct regmap *regmap;
 
-	wm9713->ac97 = snd_soc_new_ac97_codec(codec, WM9713_VENDOR_ID,
-		WM9713_VENDOR_ID_MASK);
+	wm9713->ac97 = compat_alloc_snd_ac97_codec(codec);
 	if (IS_ERR(wm9713->ac97))
 		return PTR_ERR(wm9713->ac97);
 
 	regmap = regmap_init_ac97(wm9713->ac97, &wm9713_regmap_config);
 	if (IS_ERR(regmap)) {
-		snd_soc_free_ac97_codec(wm9713->ac97);
+		compat_release_snd_ac97_codec(wm9713->ac97);
 		return PTR_ERR(regmap);
 	}
 
@@ -1231,7 +1231,7 @@ static int wm9713_soc_remove(struct snd_soc_codec *codec)
 	struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
 
 	snd_soc_codec_exit_regmap(codec);
-	snd_soc_free_ac97_codec(wm9713->ac97);
+	compat_release_snd_ac97_codec(wm9713->ac97);
 	return 0;
 }
 
@@ -1281,7 +1281,57 @@ static struct platform_driver wm9713_codec_driver = {
 	.remove = wm9713_remove,
 };
 
-module_platform_driver(wm9713_codec_driver);
+static int wm9713_ac97_probe(struct ac97_codec_device *adev)
+{
+	struct wm9713_priv *wm9713;
+
+	wm9713 = devm_kzalloc(ac97_codec_dev2dev(adev),
+			      sizeof(*wm9713), GFP_KERNEL);
+	if (wm9713 == NULL)
+		return -ENOMEM;
+
+	mutex_init(&wm9713->lock);
+
+	ac97_set_drvdata(adev, wm9713);
+
+	return snd_soc_register_codec(ac97_codec_dev2dev(adev),
+				      &soc_codec_dev_wm9713, wm9713_dai,
+				      ARRAY_SIZE(wm9713_dai));
+}
+
+static int wm9713_ac97_remove(struct ac97_codec_device *adev)
+{
+	snd_soc_unregister_codec(ac97_codec_dev2dev(adev));
+	return 0;
+}
+
+static struct ac97_id wm9713_ac97_ids[] = {
+	{ .id = WM9713_VENDOR_ID, .mask = WM9713_VENDOR_ID_MASK },
+	{ }
+};
+
+static struct ac97_codec_driver wm9713_ac97_driver = {
+	.driver = {
+			.name = "wm9713-codec",
+	},
+	.probe		= wm9713_ac97_probe,
+	.remove		= wm9713_ac97_remove,
+	.id_table	= wm9713_ac97_ids,
+};
+
+static int __init wm9713_init(void)
+{
+	snd_ac97_codec_driver_register(&wm9713_ac97_driver);
+	return platform_driver_register(&wm9713_codec_driver);
+}
+module_init(wm9713_init);
+
+static void __exit wm9713_exit(void)
+{
+	snd_ac97_codec_driver_unregister(&wm9713_ac97_driver);
+	return platform_driver_unregister(&wm9713_codec_driver);
+}
+module_exit(wm9713_exit);
 
 MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
 MODULE_AUTHOR("Liam Girdwood");
-- 
2.1.4



From robert.jarzmik at free.fr  Fri May 27 13:26:52 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Fri, 27 May 2016 22:26:52 +0200
Subject: [RFC PATCH v2 0/7] AC97 device/driver model revamp
Message-ID: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>

It all started in the pxa device-tree submission here :
   https://lkml.org/lkml/2016/2/25/965
   
It will be maintained in :
   git fetch https://github.com/rjarzmik/linux.git work/ac97

And now it transformed into this RFC, which would bring a ground for AC'97
devices closer to the linux device/driver model.

The driving ideas are still the same, and I put them in [1] for memory. This is
the second opus of the RFC. I'm intending to stop the RFC cycle here if possible
and have a true PATCH v1 submission after this RFC v2 unless there is a deep
design flaw uncovered.

I took into account Mark's and Takashi's remarks, I hope I forgot none. All the
changes should be documented in the first 2 patches mainly. I also added :
 - the AC97 link clock
   For now, bus code doesn't disable it in suspend and re-enable in resume,
   leaving the controller decide. I'm still pondering if for S2RAM (as opposed
   to runtime suspend), bus code should disable the clock.

 - the .h guards
   I'm not particularly happy with my naming even for v2, feel free to propose
   anything better, the codec.h is particularly ugly.

 - statics and namespace pollution
   I made more functions static, limiting further the namespace pollution.

 - Kconfig/Makefile layout change
   I get the feeling that the KConfig "select" flavor would have better been a
   "depends on" one. And yet I didn't find a good way to enforce it, because of
   the way sound/soc/codecs/Kconfig is designed, and I'm afraid to break the
   structure by doing a "depends on AC97_BUS_NEW" in WM9713 configuration.

Let's have another review cycle, that will let me test this serie more
thoroughly, especially the suspend/resume and the reset in the resume, which
doesn't work, and requires me to test more deeply. I'll also test by removing
the wm9713 change to see how robust the implementation is.

Happy review.

--
Robert

Robert Jarzmik (7):
  ALSA: ac97: split out the generic ac97 registers
  ALSA: ac97: add an ac97 bus
  ASoC: add new ac97 bus support
  ASoC: wm9713: add ac97 new bus support
  ASoC: pxa: switch to new ac97 bus support
  ARM: pxa: mioa701 convert to the new AC97 bus
  ASoC: mioa701_wm9713: convert to new ac97 bus

 arch/arm/mach-pxa/mioa701.c     |  12 +-
 include/sound/ac97/codec.h      | 111 ++++++++++++
 include/sound/ac97/compat.h     |  21 +++
 include/sound/ac97/controller.h |  80 +++++++++
 include/sound/ac97/regs.h       | 262 +++++++++++++++++++++++++++
 include/sound/ac97_codec.h      | 239 +------------------------
 include/sound/pxa2xx-lib.h      |  15 +-
 sound/Kconfig                   |   2 +
 sound/Makefile                  |   1 +
 sound/ac97/Kconfig              |  18 ++
 sound/ac97/Makefile             |   8 +
 sound/ac97/ac97_core.h          |  10 ++
 sound/ac97/bus.c                | 381 ++++++++++++++++++++++++++++++++++++++++
 sound/ac97/codec.c              |  15 ++
 sound/ac97/snd_ac97_compat.c    | 104 +++++++++++
 sound/arm/Kconfig               |   1 -
 sound/arm/pxa2xx-ac97-lib.c     |  39 ++--
 sound/soc/Kconfig               |   4 +
 sound/soc/codecs/Kconfig        |   1 +
 sound/soc/codecs/wm9713.c       |  62 ++++++-
 sound/soc/pxa/Kconfig           |   4 +-
 sound/soc/pxa/mioa701_wm9713.c  |   4 +-
 sound/soc/pxa/pxa2xx-ac97.c     |  20 ++-
 23 files changed, 1132 insertions(+), 282 deletions(-)
 create mode 100644 include/sound/ac97/codec.h
 create mode 100644 include/sound/ac97/compat.h
 create mode 100644 include/sound/ac97/controller.h
 create mode 100644 include/sound/ac97/regs.h
 create mode 100644 sound/ac97/Kconfig
 create mode 100644 sound/ac97/Makefile
 create mode 100644 sound/ac97/ac97_core.h
 create mode 100644 sound/ac97/bus.c
 create mode 100644 sound/ac97/codec.c
 create mode 100644 sound/ac97/snd_ac97_compat.c

-- 
2.1.4

[1] RFC PATCH reminder:

Amongst the driving ideas behind this RFC :
 - use device/driver model for AC'97
   device/driver binding is based on vendor_id{1,2}
 - use auto-probe of the AC'97 bus to enumerate codecs and create devices
 - be compatible with previous platform_data model for codecs
   => this enables a smooth transition, where a codec (here wm9713) can
      be used either through platform_device or automatic discovery
 - struct snd_ac97 is not used
   This structure is really heavy, and doesn't represent an AC97 device, but
   rather an AC'97 codec internals IIUC.
   I think it's right place would be in include/sound/ac97/codec.h.
   This is also a problem for regmap adherence, hence the
   include/sound/ac97/compat.h.
 - a new AC'97 bus Kconfig is created
   This was done for a smooth transition ... let's see if it's a good idea.
 - split the AC'97 into :
   - the codec
   - the digital controller
   - the bus

Amongst the things that are not all touched yet :
 - ac97_codec.c
   The generic AC'97 codec in sound/pci/ac97/ac97_codec.c has really a lot
   features, which are not at all PCI related. They could be transfered to
   sound/ac97, without the pci specific field.
   => this deserves a deep ahead thinking, which I'll do if the current approach
   is accepted by the communauty.

The most important patch is 2/7 "ALSA: ac97: add an ac97 bus". This is the main
evaluation point for the serie, the others are here so that I can test it all.

Well, this is a long term effort, which might need a complete rewrite according
to the comments it'll get. Let's expose it for comments and see how I can
progress with it.


From robert.jarzmik at free.fr  Fri May 27 13:26:57 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Fri, 27 May 2016 22:26:57 +0200
Subject: [RFC PATCH v2 5/7] ASoC: pxa: switch to new ac97 bus support
In-Reply-To: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
References: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
Message-ID: <1464380819-19075-6-git-send-email-robert.jarzmik@free.fr>

Switch to the new ac97 bus support in sound/ac97 instead of the legacy
snd_ac97 one.

Signed-off-by: Robert Jarzmik <robert.jarzmik at free.fr>
---
 include/sound/pxa2xx-lib.h  | 15 +++++++++------
 sound/arm/Kconfig           |  1 -
 sound/arm/pxa2xx-ac97-lib.c | 39 +++++++++++++++++++++++----------------
 sound/soc/pxa/Kconfig       |  4 ++--
 sound/soc/pxa/pxa2xx-ac97.c | 20 +++++++++++---------
 5 files changed, 45 insertions(+), 34 deletions(-)

diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h
index 6ef629bde164..0e2b8ae3e00e 100644
--- a/include/sound/pxa2xx-lib.h
+++ b/include/sound/pxa2xx-lib.h
@@ -2,7 +2,8 @@
 #define PXA2XX_LIB_H
 
 #include <linux/platform_device.h>
-#include <sound/ac97_codec.h>
+#include <sound/ac97/controller.h>
+#include <sound/ac97/compat.h>
 
 /* PCM */
 
@@ -21,12 +22,14 @@ extern void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm);
 
 /* AC97 */
 
-extern unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg);
-extern void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val);
+extern int pxa2xx_ac97_read(struct ac97_controller *adrv, int slot,
+			    unsigned short reg);
+extern int pxa2xx_ac97_write(struct ac97_controller *adrv, int slot,
+			     unsigned short reg, unsigned short val);
 
-extern bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97);
-extern bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97);
-extern void pxa2xx_ac97_finish_reset(struct snd_ac97 *ac97);
+extern bool pxa2xx_ac97_try_warm_reset(struct ac97_controller *adrv);
+extern bool pxa2xx_ac97_try_cold_reset(struct ac97_controller *adrv);
+extern void pxa2xx_ac97_finish_reset(struct ac97_controller *adrv);
 
 extern int pxa2xx_ac97_hw_suspend(void);
 extern int pxa2xx_ac97_hw_resume(void);
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index e0406211716b..94f7539a2c1f 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -11,7 +11,6 @@ menuconfig SND_ARM
 
 config SND_PXA2XX_LIB
 	tristate
-	select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97
 	select SND_DMAENGINE_PCM
 
 config SND_PXA2XX_LIB_AC97
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 39c3969ac1c7..62b31e909d31 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -20,7 +20,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 
-#include <sound/ac97_codec.h>
+#include <sound/ac97/controller.h>
 #include <sound/pxa2xx-lib.h>
 
 #include <mach/irqs.h>
@@ -46,38 +46,41 @@ extern void pxa27x_configure_ac97reset(int reset_gpio, bool to_gpio);
  * 1 jiffy timeout if interrupt never comes).
  */
 
-unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
+int pxa2xx_ac97_read(struct ac97_controller *ac97, int slot, unsigned short reg)
 {
-	unsigned short val = -1;
+	int val = -ENODEV;
 	volatile u32 *reg_addr;
 
+	if (slot > 0)
+		return -ENODEV;
+
 	mutex_lock(&car_mutex);
 
 	/* set up primary or secondary codec space */
 	if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)
-		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
+		reg_addr = slot ? &SMC_REG_BASE : &PMC_REG_BASE;
 	else
-		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
+		reg_addr = slot ? &SAC_REG_BASE : &PAC_REG_BASE;
 	reg_addr += (reg >> 1);
 
 	/* start read access across the ac97 link */
 	GSR = GSR_CDONE | GSR_SDONE;
 	gsr_bits = 0;
-	val = *reg_addr;
+	val = (*reg_addr & 0xffff);
 	if (reg == AC97_GPIO_STATUS)
 		goto out;
 	if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 &&
 	    !((GSR | gsr_bits) & GSR_SDONE)) {
 		printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
 				__func__, reg, GSR | gsr_bits);
-		val = -1;
+		val = -ETIMEDOUT;
 		goto out;
 	}
 
 	/* valid data now */
 	GSR = GSR_CDONE | GSR_SDONE;
 	gsr_bits = 0;
-	val = *reg_addr;
+	val = (*reg_addr & 0xffff);
 	/* but we've just started another cycle... */
 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
 
@@ -86,29 +89,33 @@ out:	mutex_unlock(&car_mutex);
 }
 EXPORT_SYMBOL_GPL(pxa2xx_ac97_read);
 
-void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
-			unsigned short val)
+int pxa2xx_ac97_write(struct ac97_controller *ac97, int slot,
+		      unsigned short reg, unsigned short val)
 {
 	volatile u32 *reg_addr;
+	int ret = 0;
 
 	mutex_lock(&car_mutex);
 
 	/* set up primary or secondary codec space */
 	if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)
-		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
+		reg_addr = slot ? &SMC_REG_BASE : &PMC_REG_BASE;
 	else
-		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
+		reg_addr = slot ? &SAC_REG_BASE : &PAC_REG_BASE;
 	reg_addr += (reg >> 1);
 
 	GSR = GSR_CDONE | GSR_SDONE;
 	gsr_bits = 0;
 	*reg_addr = val;
 	if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 &&
-	    !((GSR | gsr_bits) & GSR_CDONE))
+	    !((GSR | gsr_bits) & GSR_CDONE)) {
 		printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
 				__func__, reg, GSR | gsr_bits);
+		ret = -EIO;
+	}
 
 	mutex_unlock(&car_mutex);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(pxa2xx_ac97_write);
 
@@ -188,7 +195,7 @@ static inline void pxa_ac97_cold_pxa3xx(void)
 }
 #endif
 
-bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
+bool pxa2xx_ac97_try_warm_reset(struct ac97_controller *adrv)
 {
 	unsigned long gsr;
 	unsigned int timeout = 100;
@@ -225,7 +232,7 @@ bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
 }
 EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset);
 
-bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
+bool pxa2xx_ac97_try_cold_reset(struct ac97_controller *adrv)
 {
 	unsigned long gsr;
 	unsigned int timeout = 1000;
@@ -263,7 +270,7 @@ bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
 EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_cold_reset);
 
 
-void pxa2xx_ac97_finish_reset(struct snd_ac97 *ac97)
+void pxa2xx_ac97_finish_reset(struct ac97_controller *adrv)
 {
 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index f2bf8661dd21..784e6dedf5bf 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -23,9 +23,9 @@ config SND_PXA2XX_AC97
 
 config SND_PXA2XX_SOC_AC97
 	tristate
-	select AC97_BUS
+	select AC97_BUS_NEW
 	select SND_PXA2XX_LIB_AC97
-	select SND_SOC_AC97_BUS
+	select SND_SOC_AC97_BUS_NEW
 
 config SND_PXA2XX_SOC_I2S
 	tristate
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index f3de615aacd7..b6551be7c7eb 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -17,6 +17,7 @@
 #include <linux/dmaengine.h>
 #include <linux/dma/pxa-dma.h>
 
+#include <sound/ac97/controller.h>
 #include <sound/core.h>
 #include <sound/ac97_codec.h>
 #include <sound/soc.h>
@@ -29,21 +30,21 @@
 
 #include "pxa2xx-ac97.h"
 
-static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
+static void pxa2xx_ac97_warm_reset(struct ac97_controller *adrv)
 {
-	pxa2xx_ac97_try_warm_reset(ac97);
+	pxa2xx_ac97_try_warm_reset(adrv);
 
-	pxa2xx_ac97_finish_reset(ac97);
+	pxa2xx_ac97_finish_reset(adrv);
 }
 
-static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
+static void pxa2xx_ac97_cold_reset(struct ac97_controller *adrv)
 {
-	pxa2xx_ac97_try_cold_reset(ac97);
+	pxa2xx_ac97_try_cold_reset(adrv);
 
-	pxa2xx_ac97_finish_reset(ac97);
+	pxa2xx_ac97_finish_reset(adrv);
 }
 
-static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
+static struct ac97_controller_ops pxa2xx_ac97_ops = {
 	.read	= pxa2xx_ac97_read,
 	.write	= pxa2xx_ac97_write,
 	.warm_reset	= pxa2xx_ac97_warm_reset,
@@ -236,7 +237,8 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = snd_soc_set_ac97_ops(&pxa2xx_ac97_ops);
+	ret = snd_ac97_controller_register(&pxa2xx_ac97_ops, &pdev->dev,
+					   AC97_SLOTS_AVAILABLE_ALL);
 	if (ret != 0)
 		return ret;
 
@@ -251,7 +253,7 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
 static int pxa2xx_ac97_dev_remove(struct platform_device *pdev)
 {
 	snd_soc_unregister_component(&pdev->dev);
-	snd_soc_set_ac97_ops(NULL);
+	snd_ac97_controller_unregister(&pdev->dev);
 	pxa2xx_ac97_hw_remove(pdev);
 	return 0;
 }
-- 
2.1.4



From robert.jarzmik at free.fr  Fri May 27 13:26:54 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Fri, 27 May 2016 22:26:54 +0200
Subject: [RFC PATCH v2 2/7] ALSA: ac97: add an ac97 bus
In-Reply-To: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
References: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
Message-ID: <1464380819-19075-3-git-send-email-robert.jarzmik@free.fr>

AC97 is a bus for sound usage. It enables for a AC97 AC-Link to link one
controller to 0 to 4 AC97 codecs.

The goal of this new implementation is to implement a device/driver
model for AC97, with an automatic scan of the bus and automatic
discovery of AC97 codec devices.

Signed-off-by: Robert Jarzmik <robert.jarzmik at free.fr>
---
Since v1:
 - Takashi's review
   - changed the codec.h guard ... a better name could be found ...
   - added the AC97_* macros missing parenthesis
   - constantified the id_table in the codec driver structure
   - changed the 4 codecs linked list into an array
   - enabled the ac97 bus to be a module
   - added a slots_available to snd_ac97_controller_register() to have a
     way to prevent scanning and probing of unconnected codecs
   - removed useless ac97 bus index
   - all exported functions begin with snd_ac97_*()
   - change bus operations to controller+slot parameters instead of
     codec device

 - Mark's review
   - changed ac97_digital_controller into ac97_controller
   - rename ac97_digital_controller_*() into ac97_controller_*()
   - add the ac97 ac-link clock to the codec device (ie. the AC'97 BIT_CLK)
---
 include/sound/ac97/codec.h      | 111 ++++++++++++
 include/sound/ac97/compat.h     |  21 +++
 include/sound/ac97/controller.h |  80 +++++++++
 sound/ac97/Kconfig              |  18 ++
 sound/ac97/Makefile             |   8 +
 sound/ac97/ac97_core.h          |  10 ++
 sound/ac97/bus.c                | 381 ++++++++++++++++++++++++++++++++++++++++
 sound/ac97/codec.c              |  15 ++
 sound/ac97/snd_ac97_compat.c    | 104 +++++++++++
 9 files changed, 748 insertions(+)
 create mode 100644 include/sound/ac97/codec.h
 create mode 100644 include/sound/ac97/compat.h
 create mode 100644 include/sound/ac97/controller.h
 create mode 100644 sound/ac97/Kconfig
 create mode 100644 sound/ac97/Makefile
 create mode 100644 sound/ac97/ac97_core.h
 create mode 100644 sound/ac97/bus.c
 create mode 100644 sound/ac97/codec.c
 create mode 100644 sound/ac97/snd_ac97_compat.c

diff --git a/include/sound/ac97/codec.h b/include/sound/ac97/codec.h
new file mode 100644
index 000000000000..a1c9746c987e
--- /dev/null
+++ b/include/sound/ac97/codec.h
@@ -0,0 +1,111 @@
+/*
+ *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
+ *
+ * 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.
+ */
+#ifndef __SOUND_AC97_CODEC2_H
+#define __SOUND_AC97_CODEC2_H
+
+#include <linux/device.h>
+
+#define AC97_ID(vendor_id1, vendor_id2) \
+	((((vendor_id1) & 0xffff) << 16) | ((vendor_id2) & 0xffff))
+#define AC97_DRIVER_ID(vendor_id1, vendor_id2, mask_id1, mask_id2, _data) \
+	{ .id = (((vendor_id1) & 0xffff) << 16) | ((vendor_id2) & 0xffff), \
+	  .mask = (((mask_id1) & 0xffff) << 16) | ((mask_id2) & 0xffff), \
+	  .data = (_data) }
+
+#define to_ac97_device(d) container_of(d, struct ac97_codec_device, dev)
+#define to_ac97_driver(d) container_of(d, struct ac97_codec_driver, driver)
+
+struct ac97_controller;
+struct clk;
+
+/**
+ * struct ac97_id - matches a codec device and driver on an ac97 bus
+ * @id: The significant bits if the codec vendor ID1 and ID2
+ * @mask: Bitmask specifying which bits of the id field are significant when
+ *	  matching. A driver binds to a device when :
+ *        ((vendorID1 << 8 | vendorID2) & (mask_id1 << 8 | mask_id2)) == id.
+ * @data: Private data used by the driver.
+ */
+struct ac97_id {
+	unsigned int		id;
+	unsigned int		mask;
+	void			*data;
+};
+
+/**
+ * ac97_codec_device - a ac97 codec
+ * @dev: the core device
+ * @vendor_id: the vendor_id of the codec, as sensed on the AC-link
+ * @num: the codec number, 0 is primary, 1 is first slave, etc ...
+ * @clk: the clock BIT_CLK provided to the codec
+ * @ac97_ctrl: ac97 digital controller on the same AC-link
+ *
+ * This is the device instanciated for each codec living on a AC-link. There are
+ * normally 0 to 4 codec devices per AC-link, and all of them are controlled by
+ * an AC97 digital controller.
+ */
+struct ac97_codec_device {
+	struct device		dev;
+	unsigned int		vendor_id;
+	unsigned int		num;
+	struct clk		*clk;
+	struct ac97_controller	*ac97_ctrl;
+};
+
+/**
+ * ac97_codec_driver - a ac97 codec driver
+ * @driver: the device driver structure
+ * @probe: the function called when a ac97_codec_device is matched
+ * @remove: the function called when the device is unbound/removed
+ * @suspend: suspend function (might be NULL)
+ * @resume: resume function (might be NULL)
+ * @shutdown: shutdown function (might be NULL)
+ * @id_table: ac97 vendor_id match table, { } member terminated
+ */
+struct ac97_codec_driver {
+	struct device_driver	driver;
+	int			(*probe)(struct ac97_codec_device *);
+	int			(*remove)(struct ac97_codec_device *);
+	int			(*suspend)(struct ac97_codec_device *);
+	int			(*resume)(struct ac97_codec_device *);
+	void			(*shutdown)(struct ac97_codec_device *);
+	const struct ac97_id	*id_table;
+};
+
+#if defined(CONFIG_AC97_BUS_NEW)
+int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv);
+void snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv);
+#else
+static int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv)
+{
+	return 0;
+}
+static void snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv)
+{
+}
+#endif
+
+
+static inline struct device *
+ac97_codec_dev2dev(struct ac97_codec_device *adev)
+{
+	return &adev->dev;
+}
+
+static inline void *ac97_get_drvdata(struct ac97_codec_device *adev)
+{
+	return dev_get_drvdata(ac97_codec_dev2dev(adev));
+}
+
+static inline void ac97_set_drvdata(struct ac97_codec_device *adev,
+				    void *data)
+{
+	dev_set_drvdata(ac97_codec_dev2dev(adev), data);
+}
+
+#endif
diff --git a/include/sound/ac97/compat.h b/include/sound/ac97/compat.h
new file mode 100644
index 000000000000..bf611f572f2d
--- /dev/null
+++ b/include/sound/ac97/compat.h
@@ -0,0 +1,21 @@
+/*
+ *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This file is for backward compatibility with snd_ac97 structure and its
+ * multiple usages, such as the snd_ac97_bus and snd_ac97_build_ops.
+ *
+ */
+#ifndef AC97_COMPAT_H
+#define AC97_COMPAT_H
+
+#include <sound/ac97_codec.h>
+#include <sound/soc.h>
+
+struct snd_ac97 *compat_alloc_snd_ac97_codec(struct snd_soc_codec *codec);
+void compat_release_snd_ac97_codec(struct snd_ac97 *ac97);
+
+#endif
diff --git a/include/sound/ac97/controller.h b/include/sound/ac97/controller.h
new file mode 100644
index 000000000000..7e677f59832a
--- /dev/null
+++ b/include/sound/ac97/controller.h
@@ -0,0 +1,80 @@
+/*
+ *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
+ *
+ * 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.
+ */
+#ifndef AC97_CONTROLLER_H
+#define AC97_CONTROLLER_H
+
+#include <linux/list.h>
+
+#define AC97_BUS_MAX_CODECS 4
+#define AC97_SLOTS_AVAILABLE_ALL 0xf
+
+struct device;
+
+/**
+ * struct ac97_controller - The AC97 controller of the AC-Link
+ * @ops:		the AC97 operations.
+ * @controllers:	linked list of all existing controllers.
+ * @dev:		the device providing the AC97 controller.
+ * @slots_available:	the mask of accessible/scanable codecs.
+ * @codecs:		the 4 possible AC97 codecs (NULL if none found).
+ *
+ * This structure is internal to AC97 bus, and should not be used by the
+ * controllers themselves, excepting for using @dev.
+ */
+struct ac97_controller {
+	const struct ac97_controller_ops *ops;
+	struct list_head controllers;
+	struct device *dev;
+	unsigned short slots_available;
+	struct ac97_codec_device *codecs[AC97_BUS_MAX_CODECS];
+};
+
+/**
+ * struct ac97_controller_ops - The AC97 operations
+ * @reset:	Cold reset of the AC97 AC-Link.
+ * @warm_reset:	Warm reset of the AC97 AC-Link.
+ * @read:	Read of a single AC97 register.
+ *		Returns the register value or a negative error code.
+ * @write:	Write of a single AC97 register.
+ * @wait:	Wait for the current AC97 operation to finish (might be NULL).
+ * @init:	Initialization of the AC97 AC-Link (might be NULL).
+ *
+ * These are the basic operation an AC97 controller must provide for an AC97
+ * access functions. Amongst these, all but the last 2 are mandatory.
+ * The slot number is also known as the AC97 codec number, between 0 and 3.
+ */
+struct ac97_controller_ops {
+	void (*reset)(struct ac97_controller *adrv);
+	void (*warm_reset)(struct ac97_controller *adrv);
+	int (*write)(struct ac97_controller *adrv, int slot,
+		     unsigned short reg, unsigned short val);
+	int (*read)(struct ac97_controller *adrv, int slot, unsigned short reg);
+	void (*wait)(struct ac97_controller *adrv, int slot);
+	void (*init)(struct ac97_controller *adrv, int slot);
+};
+
+#if defined(CONFIG_AC97_BUS_NEW)
+int snd_ac97_controller_register(const struct ac97_controller_ops *ops,
+				 struct device *dev,
+				 unsigned short slots_available);
+int snd_ac97_controller_unregister(const struct device *dev);
+#else
+static int snd_ac97_controller_register(const struct ac97_controller_ops *ops,
+					struct device *dev,
+					unsigned short slots_available)
+{
+	return 0;
+}
+
+static int snd_ac97_controller_unregister(const struct device *dev)
+{
+	return 0;
+}
+#endif
+
+#endif
diff --git a/sound/ac97/Kconfig b/sound/ac97/Kconfig
new file mode 100644
index 000000000000..a99e4dbdf372
--- /dev/null
+++ b/sound/ac97/Kconfig
@@ -0,0 +1,18 @@
+#
+# AC97 configuration
+#
+
+
+config AC97_BUS_NEW
+	tristate
+	select AC97
+	help
+	  This is the new AC97 bus type, successor of AC97_BUS. The ported
+	  drivers which benefit from the AC97 automatic probing should "select"
+	  this instead of the AC97_BUS.
+	  Say Y here if you want to have AC97 devices, which are sound oriented
+	  devices around an AC-Link.
+
+config AC97_BUS_COMPAT
+       bool
+       depends on !AC97_BUS
diff --git a/sound/ac97/Makefile b/sound/ac97/Makefile
new file mode 100644
index 000000000000..f9c2640bfb59
--- /dev/null
+++ b/sound/ac97/Makefile
@@ -0,0 +1,8 @@
+#
+# make for AC97 bus drivers
+#
+
+obj-$(CONFIG_AC97_BUS_NEW)	+= ac97.o
+
+ac97-y				+= bus.o codec.o
+ac97-$(CONFIG_AC97_BUS_COMPAT)	+= snd_ac97_compat.o
diff --git a/sound/ac97/ac97_core.h b/sound/ac97/ac97_core.h
new file mode 100644
index 000000000000..db6e27288357
--- /dev/null
+++ b/sound/ac97/ac97_core.h
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
+ *
+ * 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.
+ */
+
+unsigned int ac97_bus_scan_one(struct ac97_controller *ac97,
+			       int codec_num);
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
new file mode 100644
index 000000000000..6755da79d4b7
--- /dev/null
+++ b/sound/ac97/bus.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
+ *
+ * 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/module.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <sound/ac97/codec.h>
+#include <sound/ac97/controller.h>
+#include <sound/ac97/regs.h>
+
+/*
+ * Protects ac97_controllers and each ac97_controller structure.
+ */
+static DEFINE_MUTEX(ac97_controllers_mutex);
+static LIST_HEAD(ac97_controllers);
+
+static struct bus_type ac97_bus_type;
+
+static struct ac97_codec_device *
+ac97_codec_find(struct ac97_controller *ac97_ctrl, int codec_num)
+{
+	if ((codec_num < 0) || (codec_num >= AC97_BUS_MAX_CODECS))
+		return ERR_PTR(-ERANGE);
+
+	return ac97_ctrl->codecs[codec_num];
+}
+
+static void ac97_codec_release(struct device *dev)
+{
+	struct ac97_codec_device *adev;
+	struct ac97_controller *ac97_ctrl;
+
+	adev = container_of(dev, struct ac97_codec_device, dev);
+	ac97_ctrl = adev->ac97_ctrl;
+	ac97_ctrl->codecs[adev->num] = NULL;
+	kfree(adev);
+}
+
+static int ac97_codec_add(struct ac97_controller *ac97_ctrl, int idx,
+		   unsigned int vendor_id)
+{
+	struct ac97_codec_device *codec;
+	char *codec_name;
+	int ret;
+
+	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
+	if (!codec)
+		return -ENOMEM;
+	ac97_ctrl->codecs[idx] = codec;
+	codec->vendor_id = vendor_id;
+	codec->dev.release = ac97_codec_release;
+	codec->dev.bus = &ac97_bus_type;
+	codec->dev.parent = ac97_ctrl->dev;
+	codec->num = idx;
+	codec->ac97_ctrl = ac97_ctrl;
+
+	codec_name = kasprintf(GFP_KERNEL, "%s:%d", dev_name(ac97_ctrl->dev),
+			       idx);
+	codec->dev.init_name = codec_name;
+
+	ret = device_register(&codec->dev);
+	kfree(codec_name);
+	if (ret) {
+		kfree(codec);
+		ac97_ctrl->codecs[idx] = NULL;
+	}
+
+	return ret;
+}
+
+unsigned int ac97_bus_scan_one(struct ac97_controller *adrv,
+				      int codec_num)
+{
+	unsigned short vid1, vid2;
+	int ret;
+
+	ret = adrv->ops->read(adrv, codec_num, AC97_VENDOR_ID1);
+	vid1 = (ret & 0xffff);
+	if (ret < 0)
+		return 0;
+
+	ret = adrv->ops->read(adrv, codec_num, AC97_VENDOR_ID2);
+	vid2 = (ret & 0xffff);
+	if (ret < 0)
+		return 0;
+
+	dev_dbg(adrv->dev, "%s(codec_num=%d): vendor_id=0x%08x\n",
+		__func__, codec_num, AC97_ID(vid1, vid2));
+	return AC97_ID(vid1, vid2);
+}
+
+static int ac97_bus_scan(struct ac97_controller *ac97_ctrl)
+{
+	int ret, i;
+	unsigned int vendor_id;
+
+	for (i = 0; i < AC97_BUS_MAX_CODECS; i++) {
+		if (ac97_codec_find(ac97_ctrl, i))
+			continue;
+		if (!(ac97_ctrl->slots_available & BIT(i)))
+			continue;
+		vendor_id = ac97_bus_scan_one(ac97_ctrl, i);
+		if (!vendor_id)
+			continue;
+
+		ret = ac97_codec_add(ac97_ctrl, i, vendor_id);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+static void ac97_rescan_all_controllers(void)
+{
+	struct ac97_controller *ac97_ctrl;
+	int ret;
+
+	mutex_lock(&ac97_controllers_mutex);
+	list_for_each_entry(ac97_ctrl, &ac97_controllers, controllers) {
+		ret = ac97_bus_scan(ac97_ctrl);
+		if (ret)
+			dev_warn(ac97_ctrl->dev, "scan failed: %d\n", ret);
+	}
+	mutex_unlock(&ac97_controllers_mutex);
+}
+
+static int ac97_bus_reset(struct ac97_controller *ac97_ctrl)
+{
+	ac97_ctrl->ops->reset(ac97_ctrl);
+
+	return 0;
+}
+
+/**
+ * snd_ac97_codec_driver_register - register an AC97 codec driver
+ * @dev: AC97 driver codec to register
+ *
+ * Register an AC97 codec driver to the ac97 bus driver, aka. the AC97 digital
+ * controller.
+ *
+ * Returns 0 on success or error code
+ */
+int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv)
+{
+	int ret;
+
+	drv->driver.bus = &ac97_bus_type;
+
+	ret = driver_register(&drv->driver);
+	if (!ret)
+		ac97_rescan_all_controllers();
+
+	return ret;
+}
+EXPORT_SYMBOL(snd_ac97_codec_driver_register);
+
+/**
+ * snd_ac97_codec_driver_unregister - unregister an AC97 codec driver
+ * @dev: AC97 codec driver to unregister
+ *
+ * Unregister a previously registered ac97 codec driver.
+ */
+void snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv)
+{
+	driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(snd_ac97_codec_driver_unregister);
+
+static int ac97_ctrl_codecs_unregister(struct ac97_controller *ac97_ctrl)
+{
+	int i;
+
+	for (i = 0; i < AC97_BUS_MAX_CODECS; i++)
+		if (ac97_ctrl->codecs[i])
+			put_device(&ac97_ctrl->codecs[i]->dev);
+
+	return 0;
+}
+
+/**
+ * snd_ac97_controller_register - register an ac97 controller
+ * @ops: the ac97 bus operations
+ * @dev: the device providing the ac97 DC function
+ * @slots_available: mask of the ac97 codecs that can be scanned and probed
+ *                   bit0 => codec 0, bit1 => codec 1 ... bit 3 => codec 3
+ *
+ * Register a digital controller which can control up to 4 ac97 codecs. This is
+ * the controller side of the AC97 AC-link, while the slave side are the codecs.
+ *
+ * Returns 0 upon success, negative value upon error
+ */
+int snd_ac97_controller_register(const struct ac97_controller_ops *ops,
+				 struct device *dev,
+				 unsigned short slots_available)
+{
+	struct ac97_controller *ac97_ctrl;
+
+	ac97_ctrl = kzalloc(sizeof(*ac97_ctrl), GFP_KERNEL);
+	if (!ac97_ctrl)
+		return -ENOMEM;
+
+	mutex_lock(&ac97_controllers_mutex);
+	ac97_ctrl->ops = ops;
+	ac97_ctrl->slots_available = slots_available;
+	ac97_ctrl->dev = dev;
+	list_add(&ac97_ctrl->controllers, &ac97_controllers);
+	mutex_unlock(&ac97_controllers_mutex);
+
+	ac97_bus_reset(ac97_ctrl);
+	ac97_bus_scan(ac97_ctrl);
+
+	return 0;
+}
+EXPORT_SYMBOL(snd_ac97_controller_register);
+
+/**
+ * snd_ac97_controller_unregister - unregister an ac97 controller
+ * @dev: the device previously provided to ac97_controller_register()
+ *
+ * Returns 0 on success, negative upon error
+ */
+int snd_ac97_controller_unregister(const struct device *dev)
+{
+	struct ac97_controller *ac97_ctrl, *tmp;
+	int ret = -ENODEV, i;
+
+	mutex_lock(&ac97_controllers_mutex);
+	list_for_each_entry_safe(ac97_ctrl, tmp, &ac97_controllers,
+				 controllers) {
+		if (ac97_ctrl->dev != dev)
+			continue;
+		ret = 0;
+		for (i = 0; i < AC97_BUS_MAX_CODECS; i++)
+			if (ac97_ctrl->codecs[i] &&
+			    device_is_registered(&ac97_ctrl->codecs[i]->dev))
+				ret = -EBUSY;
+		if (!ret)
+			ret = ac97_ctrl_codecs_unregister(ac97_ctrl);
+		if (!ret)
+			list_del(&ac97_ctrl->controllers);
+	}
+
+	mutex_unlock(&ac97_controllers_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL(snd_ac97_controller_unregister);
+
+static const struct dev_pm_ops ac97_pm = {
+	.suspend	= pm_generic_suspend,
+	.resume		= pm_generic_resume,
+	.freeze		= pm_generic_freeze,
+	.thaw		= pm_generic_thaw,
+	.poweroff	= pm_generic_poweroff,
+	.restore	= pm_generic_restore,
+};
+
+static int ac97_get_enable_clk(struct ac97_codec_device *adev)
+{
+	int ret;
+
+	adev->clk = clk_get(&adev->dev, "ac97_clk");
+	if (IS_ERR(adev->clk))
+		return PTR_ERR(adev->clk);
+
+	ret = clk_prepare_enable(adev->clk);
+	if (ret)
+		clk_put(adev->clk);
+
+	return ret;
+}
+
+static void ac97_put_disable_clk(struct ac97_codec_device *adev)
+{
+	clk_disable_unprepare(adev->clk);
+	clk_put(adev->clk);
+}
+
+static ssize_t vendor_id_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct ac97_codec_device *codec = to_ac97_device(dev);
+
+	return sprintf(buf, "%08x", codec->vendor_id);
+}
+
+static struct device_attribute ac97_dev_attrs[] = {
+	__ATTR_RO(vendor_id),
+	__ATTR_NULL,
+};
+
+static int ac97_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct ac97_codec_device *adev = to_ac97_device(dev);
+	struct ac97_codec_driver *adrv = to_ac97_driver(drv);
+	const struct ac97_id *id = adrv->id_table;
+	int i = 0;
+
+	if (adev->vendor_id == 0x0 || adev->vendor_id == 0xffffffff)
+		return false;
+
+	do {
+		if ((id[i].id & id->mask) == (adev->vendor_id & id[i].mask))
+			return true;
+	} while (id[i++].id);
+
+	return false;
+}
+
+static int ac97_bus_probe(struct device *dev)
+{
+	struct ac97_codec_device *adev = to_ac97_device(dev);
+	struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
+	int ret;
+
+	ret = ac97_get_enable_clk(adev);
+	if (ret)
+		return ret;
+
+	pm_runtime_get_noresume(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	ret = adrv->probe(adev);
+	if (ret == 0)
+		return 0;
+
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
+	ac97_put_disable_clk(adev);
+
+	return ret;
+}
+
+static int ac97_bus_remove(struct device *dev)
+{
+	struct ac97_codec_device *adev = to_ac97_device(dev);
+	struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver);
+	int ret;
+
+	ret = pm_runtime_get_sync(dev);
+	if (ret)
+		return ret;
+
+	ret = adrv->remove(adev);
+	pm_runtime_put_noidle(dev);
+	if (ret == 0)
+		ac97_put_disable_clk(adev);
+
+	return ret;
+}
+
+static struct bus_type ac97_bus_type = {
+	.name		= "ac97",
+	.dev_attrs	= ac97_dev_attrs,
+	.match		= ac97_bus_match,
+	.pm		= &ac97_pm,
+	.probe		= ac97_bus_probe,
+	.remove		= ac97_bus_remove,
+};
+
+static int __init ac97_bus_init(void)
+{
+	return bus_register(&ac97_bus_type);
+}
+subsys_initcall(ac97_bus_init);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik at free.fr>");
diff --git a/sound/ac97/codec.c b/sound/ac97/codec.c
new file mode 100644
index 000000000000..a835f03744bf
--- /dev/null
+++ b/sound/ac97/codec.c
@@ -0,0 +1,15 @@
+/*
+ *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
+ *
+ * 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 <sound/ac97_codec.h>
+#include <sound/ac97/codec.h>
+#include <sound/ac97/controller.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <sound/soc.h>	/* For compat_ac97_* */
+
diff --git a/sound/ac97/snd_ac97_compat.c b/sound/ac97/snd_ac97_compat.c
new file mode 100644
index 000000000000..15ed77c8cf06
--- /dev/null
+++ b/sound/ac97/snd_ac97_compat.c
@@ -0,0 +1,104 @@
+/*
+ *  Copyright (C) 2016 Robert Jarzmik <robert.jarzmik at free.fr>
+ *
+ * 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/list.h>
+#include <linux/slab.h>
+#include <sound/ac97/codec.h>
+#include <sound/ac97/controller.h>
+#include <sound/soc.h>
+
+#include "ac97_core.h"
+
+static void compat_ac97_reset(struct snd_ac97 *ac97)
+{
+	struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
+	struct ac97_controller *actrl = adev->ac97_ctrl;
+
+	if (actrl->ops->reset)
+		actrl->ops->reset(actrl);
+}
+
+static void compat_ac97_warm_reset(struct snd_ac97 *ac97)
+{
+	struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
+	struct ac97_controller *actrl = adev->ac97_ctrl;
+
+	if (actrl->ops->warm_reset)
+		actrl->ops->warm_reset(actrl);
+}
+
+static void compat_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+			      unsigned short val)
+{
+	struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
+	struct ac97_controller *actrl = adev->ac97_ctrl;
+
+	actrl->ops->write(actrl, ac97->num, reg, val);
+}
+
+static unsigned short compat_ac97_read(struct snd_ac97 *ac97,
+				       unsigned short reg)
+{
+	struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
+	struct ac97_controller *actrl = adev->ac97_ctrl;
+
+	return actrl->ops->read(actrl, ac97->num, reg);
+}
+
+static struct snd_ac97_bus_ops compat_snd_ac97_bus_ops = {
+	.reset = compat_ac97_reset,
+	.warm_reset = compat_ac97_warm_reset,
+	.write = compat_ac97_write,
+	.read = compat_ac97_read,
+};
+
+static struct snd_ac97_bus compat_soc_ac97_bus = {
+	.ops = &compat_snd_ac97_bus_ops,
+};
+
+struct snd_ac97 *compat_alloc_snd_ac97_codec(struct snd_soc_codec *codec)
+{
+	struct snd_ac97 *ac97;
+
+	ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
+	if (ac97 == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	ac97->dev = *codec->dev;
+	ac97->private_data = codec->dev;
+	ac97->bus = &compat_soc_ac97_bus;
+	return ac97;
+}
+EXPORT_SYMBOL_GPL(compat_alloc_snd_ac97_codec);
+
+void compat_release_snd_ac97_codec(struct snd_ac97 *ac97)
+{
+	kfree(ac97);
+}
+EXPORT_SYMBOL_GPL(compat_release_snd_ac97_codec);
+
+int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
+	unsigned int id_mask)
+{
+	struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
+	struct ac97_controller *actrl = adev->ac97_ctrl;
+
+	if (try_warm) {
+		compat_ac97_warm_reset(ac97);
+		if (ac97_bus_scan_one(actrl, adev->num) == adev->vendor_id)
+			return 1;
+	}
+
+	compat_ac97_reset(ac97);
+	compat_ac97_warm_reset(ac97);
+	if (ac97_bus_scan_one(actrl, adev->num) == adev->vendor_id)
+		return 0;
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(snd_ac97_reset);
-- 
2.1.4



From robert.jarzmik at free.fr  Fri May 27 13:26:53 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Fri, 27 May 2016 22:26:53 +0200
Subject: [RFC PATCH v2 1/7] ALSA: ac97: split out the generic ac97 registers
In-Reply-To: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
References: <1464380819-19075-1-git-send-email-robert.jarzmik@free.fr>
Message-ID: <1464380819-19075-2-git-send-email-robert.jarzmik@free.fr>

Split out from the ac97_codec.h the ac97 generic registers, which can be
used by a codec, typically a generic ac97 codec, and by the ac97 bus, to
scan an ac97 AC-Link.

This split encompasses all the AC97 standard registers, but not the
codec specific ones.

In order to have a clean split between former ac97 bus implementation
and the new coming one in sound/ac97, it is safer to not include any
former ac97 includes, excepting in sound/ac97/compat.c.

Amongst the thing to isolate :
 - don't have the struct snd_ac97 in sound/ac97/* (except compat.c) to not
   be "fooled" by a definition which would come with ac97_codec.h by
   "chance".
 - don't have to have snd_a97_*() functions, as they rely on struct snd_ac97.
 - don't want the struct snd_ac97_bus_ops, there is a new one

Signed-off-by: Robert Jarzmik <robert.jarzmik at free.fr>
---
Since v1: improve commit message to explain better the rationale
---
 include/sound/ac97/regs.h  | 262 +++++++++++++++++++++++++++++++++++++++++++++
 include/sound/ac97_codec.h | 239 +----------------------------------------
 2 files changed, 263 insertions(+), 238 deletions(-)
 create mode 100644 include/sound/ac97/regs.h

diff --git a/include/sound/ac97/regs.h b/include/sound/ac97/regs.h
new file mode 100644
index 000000000000..4bb86d379bd5
--- /dev/null
+++ b/include/sound/ac97/regs.h
@@ -0,0 +1,262 @@
+/*
+ *  Copyright (c) by Jaroslav Kysela <perex at perex.cz>
+ *  Universal interface for Audio Codec '97
+ *
+ *  For more details look to AC '97 component specification revision 2.1
+ *  by Intel Corporation (http://developer.intel.com).
+ *
+ *
+ *   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.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+/*
+ *  AC'97 codec registers
+ */
+
+#define AC97_RESET		0x00	/* Reset */
+#define AC97_MASTER		0x02	/* Master Volume */
+#define AC97_HEADPHONE		0x04	/* Headphone Volume (optional) */
+#define AC97_MASTER_MONO	0x06	/* Master Volume Mono (optional) */
+#define AC97_MASTER_TONE	0x08	/* Master Tone (Bass & Treble) (optional) */
+#define AC97_PC_BEEP		0x0a	/* PC Beep Volume (optinal) */
+#define AC97_PHONE		0x0c	/* Phone Volume (optional) */
+#define AC97_MIC		0x0e	/* MIC Volume */
+#define AC97_LINE		0x10	/* Line In Volume */
+#define AC97_CD			0x12	/* CD Volume */
+#define AC97_VIDEO		0x14	/* Video Volume (optional) */
+#define AC97_AUX		0x16	/* AUX Volume (optional) */
+#define AC97_PCM		0x18	/* PCM Volume */
+#define AC97_REC_SEL		0x1a	/* Record Select */
+#define AC97_REC_GAIN		0x1c	/* Record Gain */
+#define AC97_REC_GAIN_MIC	0x1e	/* Record Gain MIC (optional) */
+#define AC97_GENERAL_PURPOSE	0x20	/* General Purpose (optional) */
+#define AC97_3D_CONTROL		0x22	/* 3D Control (optional) */
+#define AC97_INT_PAGING		0x24	/* Audio Interrupt & Paging (AC'97 2.3) */
+#define AC97_POWERDOWN		0x26	/* Powerdown control / status */
+/* range 0x28-0x3a - AUDIO AC'97 2.0 extensions */
+#define AC97_EXTENDED_ID	0x28	/* Extended Audio ID */
+#define AC97_EXTENDED_STATUS	0x2a	/* Extended Audio Status and Control */
+#define AC97_PCM_FRONT_DAC_RATE 0x2c	/* PCM Front DAC Rate */
+#define AC97_PCM_SURR_DAC_RATE	0x2e	/* PCM Surround DAC Rate */
+#define AC97_PCM_LFE_DAC_RATE	0x30	/* PCM LFE DAC Rate */
+#define AC97_PCM_LR_ADC_RATE	0x32	/* PCM LR ADC Rate */
+#define AC97_PCM_MIC_ADC_RATE	0x34	/* PCM MIC ADC Rate */
+#define AC97_CENTER_LFE_MASTER	0x36	/* Center + LFE Master Volume */
+#define AC97_SURROUND_MASTER	0x38	/* Surround (Rear) Master Volume */
+#define AC97_SPDIF		0x3a	/* S/PDIF control */
+/* range 0x3c-0x58 - MODEM */
+#define AC97_EXTENDED_MID	0x3c	/* Extended Modem ID */
+#define AC97_EXTENDED_MSTATUS	0x3e	/* Extended Modem Status and Control */
+#define AC97_LINE1_RATE		0x40	/* Line1 DAC/ADC Rate */
+#define AC97_LINE2_RATE		0x42	/* Line2 DAC/ADC Rate */
+#define AC97_HANDSET_RATE	0x44	/* Handset DAC/ADC Rate */
+#define AC97_LINE1_LEVEL	0x46	/* Line1 DAC/ADC Level */
+#define AC97_LINE2_LEVEL	0x48	/* Line2 DAC/ADC Level */
+#define AC97_HANDSET_LEVEL	0x4a	/* Handset DAC/ADC Level */
+#define AC97_GPIO_CFG		0x4c	/* GPIO Configuration */
+#define AC97_GPIO_POLARITY	0x4e	/* GPIO Pin Polarity/Type, 0=low, 1=high active */
+#define AC97_GPIO_STICKY	0x50	/* GPIO Pin Sticky, 0=not, 1=sticky */
+#define AC97_GPIO_WAKEUP	0x52	/* GPIO Pin Wakeup, 0=no int, 1=yes int */
+#define AC97_GPIO_STATUS	0x54	/* GPIO Pin Status, slot 12 */
+#define AC97_MISC_AFE		0x56	/* Miscellaneous Modem AFE Status and Control */
+/* range 0x5a-0x7b - Vendor Specific */
+#define AC97_VENDOR_ID1		0x7c	/* Vendor ID1 */
+#define AC97_VENDOR_ID2		0x7e	/* Vendor ID2 / revision */
+/* range 0x60-0x6f (page 1) - extended codec registers */
+#define AC97_CODEC_CLASS_REV	0x60	/* Codec Class/Revision */
+#define AC97_PCI_SVID		0x62	/* PCI Subsystem Vendor ID */
+#define AC97_PCI_SID		0x64	/* PCI Subsystem ID */
+#define AC97_FUNC_SELECT	0x66	/* Function Select */
+#define AC97_FUNC_INFO		0x68	/* Function Information */
+#define AC97_SENSE_INFO		0x6a	/* Sense Details */
+
+/* volume controls */
+#define AC97_MUTE_MASK_MONO	0x8000
+#define AC97_MUTE_MASK_STEREO	0x8080
+
+/* slot allocation */
+#define AC97_SLOT_TAG		0
+#define AC97_SLOT_CMD_ADDR	1
+#define AC97_SLOT_CMD_DATA	2
+#define AC97_SLOT_PCM_LEFT	3
+#define AC97_SLOT_PCM_RIGHT	4
+#define AC97_SLOT_MODEM_LINE1	5
+#define AC97_SLOT_PCM_CENTER	6
+#define AC97_SLOT_MIC		6	/* input */
+#define AC97_SLOT_SPDIF_LEFT1	6
+#define AC97_SLOT_PCM_SLEFT	7	/* surround left */
+#define AC97_SLOT_PCM_LEFT_0	7	/* double rate operation */
+#define AC97_SLOT_SPDIF_LEFT	7
+#define AC97_SLOT_PCM_SRIGHT	8	/* surround right */
+#define AC97_SLOT_PCM_RIGHT_0	8	/* double rate operation */
+#define AC97_SLOT_SPDIF_RIGHT	8
+#define AC97_SLOT_LFE		9
+#define AC97_SLOT_SPDIF_RIGHT1	9
+#define AC97_SLOT_MODEM_LINE2	10
+#define AC97_SLOT_PCM_LEFT_1	10	/* double rate operation */
+#define AC97_SLOT_SPDIF_LEFT2	10
+#define AC97_SLOT_HANDSET	11	/* output */
+#define AC97_SLOT_PCM_RIGHT_1	11	/* double rate operation */
+#define AC97_SLOT_SPDIF_RIGHT2	11
+#define AC97_SLOT_MODEM_GPIO	12	/* modem GPIO */
+#define AC97_SLOT_PCM_CENTER_1	12	/* double rate operation */
+
+/* basic capabilities (reset register) */
+#define AC97_BC_DEDICATED_MIC	0x0001	/* Dedicated Mic PCM In Channel */
+#define AC97_BC_RESERVED1	0x0002	/* Reserved (was Modem Line Codec support) */
+#define AC97_BC_BASS_TREBLE	0x0004	/* Bass & Treble Control */
+#define AC97_BC_SIM_STEREO	0x0008	/* Simulated stereo */
+#define AC97_BC_HEADPHONE	0x0010	/* Headphone Out Support */
+#define AC97_BC_LOUDNESS	0x0020	/* Loudness (bass boost) Support */
+#define AC97_BC_16BIT_DAC	0x0000	/* 16-bit DAC resolution */
+#define AC97_BC_18BIT_DAC	0x0040	/* 18-bit DAC resolution */
+#define AC97_BC_20BIT_DAC	0x0080	/* 20-bit DAC resolution */
+#define AC97_BC_DAC_MASK	0x00c0
+#define AC97_BC_16BIT_ADC	0x0000	/* 16-bit ADC resolution */
+#define AC97_BC_18BIT_ADC	0x0100	/* 18-bit ADC resolution */
+#define AC97_BC_20BIT_ADC	0x0200	/* 20-bit ADC resolution */
+#define AC97_BC_ADC_MASK	0x0300
+#define AC97_BC_3D_TECH_ID_MASK	0x7c00	/* Per-vendor ID of 3D enhancement */
+
+/* general purpose */
+#define AC97_GP_DRSS_MASK	0x0c00	/* double rate slot select */
+#define AC97_GP_DRSS_1011	0x0000	/* LR(C) 10+11(+12) */
+#define AC97_GP_DRSS_78		0x0400	/* LR 7+8 */
+
+/* powerdown bits */
+#define AC97_PD_ADC_STATUS	0x0001	/* ADC status (RO) */
+#define AC97_PD_DAC_STATUS	0x0002	/* DAC status (RO) */
+#define AC97_PD_MIXER_STATUS	0x0004	/* Analog mixer status (RO) */
+#define AC97_PD_VREF_STATUS	0x0008	/* Vref status (RO) */
+#define AC97_PD_PR0		0x0100	/* Power down PCM ADCs and input MUX */
+#define AC97_PD_PR1		0x0200	/* Power down PCM front DAC */
+#define AC97_PD_PR2		0x0400	/* Power down Mixer (Vref still on) */
+#define AC97_PD_PR3		0x0800	/* Power down Mixer (Vref off) */
+#define AC97_PD_PR4		0x1000	/* Power down AC-Link */
+#define AC97_PD_PR5		0x2000	/* Disable internal clock usage */
+#define AC97_PD_PR6		0x4000	/* Headphone amplifier */
+#define AC97_PD_EAPD		0x8000	/* External Amplifer Power Down (EAPD) */
+
+/* extended audio ID bit defines */
+#define AC97_EI_VRA		0x0001	/* Variable bit rate supported */
+#define AC97_EI_DRA		0x0002	/* Double rate supported */
+#define AC97_EI_SPDIF		0x0004	/* S/PDIF out supported */
+#define AC97_EI_VRM		0x0008	/* Variable bit rate supported for MIC */
+#define AC97_EI_DACS_SLOT_MASK	0x0030	/* DACs slot assignment */
+#define AC97_EI_DACS_SLOT_SHIFT	4
+#define AC97_EI_CDAC		0x0040	/* PCM Center DAC available */
+#define AC97_EI_SDAC		0x0080	/* PCM Surround DACs available */
+#define AC97_EI_LDAC		0x0100	/* PCM LFE DAC available */
+#define AC97_EI_AMAP		0x0200	/* indicates optional slot/DAC mapping based on codec ID */
+#define AC97_EI_REV_MASK	0x0c00	/* AC'97 revision mask */
+#define AC97_EI_REV_22		0x0400	/* AC'97 revision 2.2 */
+#define AC97_EI_REV_23		0x0800	/* AC'97 revision 2.3 */
+#define AC97_EI_REV_SHIFT	10
+#define AC97_EI_ADDR_MASK	0xc000	/* physical codec ID (address) */
+#define AC97_EI_ADDR_SHIFT	14
+
+/* extended audio status and control bit defines */
+#define AC97_EA_VRA		0x0001	/* Variable bit rate enable bit */
+#define AC97_EA_DRA		0x0002	/* Double-rate audio enable bit */
+#define AC97_EA_SPDIF		0x0004	/* S/PDIF out enable bit */
+#define AC97_EA_VRM		0x0008	/* Variable bit rate for MIC enable bit */
+#define AC97_EA_SPSA_SLOT_MASK	0x0030	/* Mask for slot assignment bits */
+#define AC97_EA_SPSA_SLOT_SHIFT 4
+#define AC97_EA_SPSA_3_4	0x0000	/* Slot assigned to 3 & 4 */
+#define AC97_EA_SPSA_7_8	0x0010	/* Slot assigned to 7 & 8 */
+#define AC97_EA_SPSA_6_9	0x0020	/* Slot assigned to 6 & 9 */
+#define AC97_EA_SPSA_10_11	0x0030	/* Slot assigned to 10 & 11 */
+#define AC97_EA_CDAC		0x0040	/* PCM Center DAC is ready (Read only) */
+#define AC97_EA_SDAC		0x0080	/* PCM Surround DACs are ready (Read only) */
+#define AC97_EA_LDAC		0x0100	/* PCM LFE DAC is ready (Read only) */
+#define AC97_EA_MDAC		0x0200	/* MIC ADC is ready (Read only) */
+#define AC97_EA_SPCV		0x0400	/* S/PDIF configuration valid (Read only) */
+#define AC97_EA_PRI		0x0800	/* Turns the PCM Center DAC off */
+#define AC97_EA_PRJ		0x1000	/* Turns the PCM Surround DACs off */
+#define AC97_EA_PRK		0x2000	/* Turns the PCM LFE DAC off */
+#define AC97_EA_PRL		0x4000	/* Turns the MIC ADC off */
+
+/* S/PDIF control bit defines */
+#define AC97_SC_PRO		0x0001	/* Professional status */
+#define AC97_SC_NAUDIO		0x0002	/* Non audio stream */
+#define AC97_SC_COPY		0x0004	/* Copyright status */
+#define AC97_SC_PRE		0x0008	/* Preemphasis status */
+#define AC97_SC_CC_MASK		0x07f0	/* Category Code mask */
+#define AC97_SC_CC_SHIFT	4
+#define AC97_SC_L		0x0800	/* Generation Level status */
+#define AC97_SC_SPSR_MASK	0x3000	/* S/PDIF Sample Rate bits */
+#define AC97_SC_SPSR_SHIFT	12
+#define AC97_SC_SPSR_44K	0x0000	/* Use 44.1kHz Sample rate */
+#define AC97_SC_SPSR_48K	0x2000	/* Use 48kHz Sample rate */
+#define AC97_SC_SPSR_32K	0x3000	/* Use 32kHz Sample rate */
+#define AC97_SC_DRS		0x4000	/* Double Rate S/PDIF */
+#define AC97_SC_V		0x8000	/* Validity status */
+
+/* Interrupt and Paging bit defines (AC'97 2.3) */
+#define AC97_PAGE_MASK		0x000f	/* Page Selector */
+#define AC97_PAGE_VENDOR	0	/* Vendor-specific registers */
+#define AC97_PAGE_1		1	/* Extended Codec Registers page 1 */
+#define AC97_INT_ENABLE		0x0800	/* Interrupt Enable */
+#define AC97_INT_SENSE		0x1000	/* Sense Cycle */
+#define AC97_INT_CAUSE_SENSE	0x2000	/* Sense Cycle Completed (RO) */
+#define AC97_INT_CAUSE_GPIO	0x4000	/* GPIO bits changed (RO) */
+#define AC97_INT_STATUS		0x8000	/* Interrupt Status */
+
+/* extended modem ID bit defines */
+#define AC97_MEI_LINE1		0x0001	/* Line1 present */
+#define AC97_MEI_LINE2		0x0002	/* Line2 present */
+#define AC97_MEI_HANDSET	0x0004	/* Handset present */
+#define AC97_MEI_CID1		0x0008	/* caller ID decode for Line1 is supported */
+#define AC97_MEI_CID2		0x0010	/* caller ID decode for Line2 is supported */
+#define AC97_MEI_ADDR_MASK	0xc000	/* physical codec ID (address) */
+#define AC97_MEI_ADDR_SHIFT	14
+
+/* extended modem status and control bit defines */
+#define AC97_MEA_GPIO		0x0001	/* GPIO is ready (ro) */
+#define AC97_MEA_MREF		0x0002	/* Vref is up to nominal level (ro) */
+#define AC97_MEA_ADC1		0x0004	/* ADC1 operational (ro) */
+#define AC97_MEA_DAC1		0x0008	/* DAC1 operational (ro) */
+#define AC97_MEA_ADC2		0x0010	/* ADC2 operational (ro) */
+#define AC97_MEA_DAC2		0x0020	/* DAC2 operational (ro) */
+#define AC97_MEA_HADC		0x0040	/* HADC operational (ro) */
+#define AC97_MEA_HDAC		0x0080	/* HDAC operational (ro) */
+#define AC97_MEA_PRA		0x0100	/* GPIO power down (high) */
+#define AC97_MEA_PRB		0x0200	/* reserved */
+#define AC97_MEA_PRC		0x0400	/* ADC1 power down (high) */
+#define AC97_MEA_PRD		0x0800	/* DAC1 power down (high) */
+#define AC97_MEA_PRE		0x1000	/* ADC2 power down (high) */
+#define AC97_MEA_PRF		0x2000	/* DAC2 power down (high) */
+#define AC97_MEA_PRG		0x4000	/* HADC power down (high) */
+#define AC97_MEA_PRH		0x8000	/* HDAC power down (high) */
+
+/* modem gpio status defines */
+#define AC97_GPIO_LINE1_OH      0x0001  /* Off Hook Line1 */
+#define AC97_GPIO_LINE1_RI      0x0002  /* Ring Detect Line1 */
+#define AC97_GPIO_LINE1_CID     0x0004  /* Caller ID path enable Line1 */
+#define AC97_GPIO_LINE1_LCS     0x0008  /* Loop Current Sense Line1 */
+#define AC97_GPIO_LINE1_PULSE   0x0010  /* Opt./ Pulse Dial Line1 (out) */
+#define AC97_GPIO_LINE1_HL1R    0x0020  /* Opt./ Handset to Line1 relay control (out) */
+#define AC97_GPIO_LINE1_HOHD    0x0040  /* Opt./ Handset off hook detect Line1 (in) */
+#define AC97_GPIO_LINE12_AC     0x0080  /* Opt./ Int.bit 1 / Line1/2 AC (out) */
+#define AC97_GPIO_LINE12_DC     0x0100  /* Opt./ Int.bit 2 / Line1/2 DC (out) */
+#define AC97_GPIO_LINE12_RS     0x0200  /* Opt./ Int.bit 3 / Line1/2 RS (out) */
+#define AC97_GPIO_LINE2_OH      0x0400  /* Off Hook Line2 */
+#define AC97_GPIO_LINE2_RI      0x0800  /* Ring Detect Line2 */
+#define AC97_GPIO_LINE2_CID     0x1000  /* Caller ID path enable Line2 */
+#define AC97_GPIO_LINE2_LCS     0x2000  /* Loop Current Sense Line2 */
+#define AC97_GPIO_LINE2_PULSE   0x4000  /* Opt./ Pulse Dial Line2 (out) */
+#define AC97_GPIO_LINE2_HL1R    0x8000  /* Opt./ Handset to Line2 relay control (out) */
+
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 15aa5f07c955..89d311a503d3 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -28,6 +28,7 @@
 #include <linux/bitops.h>
 #include <linux/device.h>
 #include <linux/workqueue.h>
+#include <sound/ac97/regs.h>
 #include <sound/pcm.h>
 #include <sound/control.h>
 #include <sound/info.h>
@@ -35,244 +36,6 @@
 /* maximum number of devices on the AC97 bus */
 #define	AC97_BUS_MAX_DEVICES	4
 
-/*
- *  AC'97 codec registers
- */
-
-#define AC97_RESET		0x00	/* Reset */
-#define AC97_MASTER		0x02	/* Master Volume */
-#define AC97_HEADPHONE		0x04	/* Headphone Volume (optional) */
-#define AC97_MASTER_MONO	0x06	/* Master Volume Mono (optional) */
-#define AC97_MASTER_TONE	0x08	/* Master Tone (Bass & Treble) (optional) */
-#define AC97_PC_BEEP		0x0a	/* PC Beep Volume (optinal) */
-#define AC97_PHONE		0x0c	/* Phone Volume (optional) */
-#define AC97_MIC		0x0e	/* MIC Volume */
-#define AC97_LINE		0x10	/* Line In Volume */
-#define AC97_CD			0x12	/* CD Volume */
-#define AC97_VIDEO		0x14	/* Video Volume (optional) */
-#define AC97_AUX		0x16	/* AUX Volume (optional) */
-#define AC97_PCM		0x18	/* PCM Volume */
-#define AC97_REC_SEL		0x1a	/* Record Select */
-#define AC97_REC_GAIN		0x1c	/* Record Gain */
-#define AC97_REC_GAIN_MIC	0x1e	/* Record Gain MIC (optional) */
-#define AC97_GENERAL_PURPOSE	0x20	/* General Purpose (optional) */
-#define AC97_3D_CONTROL		0x22	/* 3D Control (optional) */
-#define AC97_INT_PAGING		0x24	/* Audio Interrupt & Paging (AC'97 2.3) */
-#define AC97_POWERDOWN		0x26	/* Powerdown control / status */
-/* range 0x28-0x3a - AUDIO AC'97 2.0 extensions */
-#define AC97_EXTENDED_ID	0x28	/* Extended Audio ID */
-#define AC97_EXTENDED_STATUS	0x2a	/* Extended Audio Status and Control */
-#define AC97_PCM_FRONT_DAC_RATE 0x2c	/* PCM Front DAC Rate */
-#define AC97_PCM_SURR_DAC_RATE	0x2e	/* PCM Surround DAC Rate */
-#define AC97_PCM_LFE_DAC_RATE	0x30	/* PCM LFE DAC Rate */
-#define AC97_PCM_LR_ADC_RATE	0x32	/* PCM LR ADC Rate */
-#define AC97_PCM_MIC_ADC_RATE	0x34	/* PCM MIC ADC Rate */
-#define AC97_CENTER_LFE_MASTER	0x36	/* Center + LFE Master Volume */
-#define AC97_SURROUND_MASTER	0x38	/* Surround (Rear) Master Volume */
-#define AC97_SPDIF		0x3a	/* S/PDIF control */
-/* range 0x3c-0x58 - MODEM */
-#define AC97_EXTENDED_MID	0x3c	/* Extended Modem ID */
-#define AC97_EXTENDED_MSTATUS	0x3e	/* Extended Modem Status and Control */
-#define AC97_LINE1_RATE		0x40	/* Line1 DAC/ADC Rate */
-#define AC97_LINE2_RATE		0x42	/* Line2 DAC/ADC Rate */
-#define AC97_HANDSET_RATE	0x44	/* Handset DAC/ADC Rate */
-#define AC97_LINE1_LEVEL	0x46	/* Line1 DAC/ADC Level */
-#define AC97_LINE2_LEVEL	0x48	/* Line2 DAC/ADC Level */
-#define AC97_HANDSET_LEVEL	0x4a	/* Handset DAC/ADC Level */
-#define AC97_GPIO_CFG		0x4c	/* GPIO Configuration */
-#define AC97_GPIO_POLARITY	0x4e	/* GPIO Pin Polarity/Type, 0=low, 1=high active */
-#define AC97_GPIO_STICKY	0x50	/* GPIO Pin Sticky, 0=not, 1=sticky */
-#define AC97_GPIO_WAKEUP	0x52	/* GPIO Pin Wakeup, 0=no int, 1=yes int */
-#define AC97_GPIO_STATUS	0x54	/* GPIO Pin Status, slot 12 */
-#define AC97_MISC_AFE		0x56	/* Miscellaneous Modem AFE Status and Control */
-/* range 0x5a-0x7b - Vendor Specific */
-#define AC97_VENDOR_ID1		0x7c	/* Vendor ID1 */
-#define AC97_VENDOR_ID2		0x7e	/* Vendor ID2 / revision */
-/* range 0x60-0x6f (page 1) - extended codec registers */
-#define AC97_CODEC_CLASS_REV	0x60	/* Codec Class/Revision */
-#define AC97_PCI_SVID		0x62	/* PCI Subsystem Vendor ID */
-#define AC97_PCI_SID		0x64	/* PCI Subsystem ID */
-#define AC97_FUNC_SELECT	0x66	/* Function Select */
-#define AC97_FUNC_INFO		0x68	/* Function Information */
-#define AC97_SENSE_INFO		0x6a	/* Sense Details */
-
-/* volume controls */
-#define AC97_MUTE_MASK_MONO	0x8000
-#define AC97_MUTE_MASK_STEREO	0x8080
-
-/* slot allocation */
-#define AC97_SLOT_TAG		0
-#define AC97_SLOT_CMD_ADDR	1
-#define AC97_SLOT_CMD_DATA	2
-#define AC97_SLOT_PCM_LEFT	3
-#define AC97_SLOT_PCM_RIGHT	4
-#define AC97_SLOT_MODEM_LINE1	5
-#define AC97_SLOT_PCM_CENTER	6
-#define AC97_SLOT_MIC		6	/* input */
-#define AC97_SLOT_SPDIF_LEFT1	6
-#define AC97_SLOT_PCM_SLEFT	7	/* surround left */
-#define AC97_SLOT_PCM_LEFT_0	7	/* double rate operation */
-#define AC97_SLOT_SPDIF_LEFT	7
-#define AC97_SLOT_PCM_SRIGHT	8	/* surround right */
-#define AC97_SLOT_PCM_RIGHT_0	8	/* double rate operation */
-#define AC97_SLOT_SPDIF_RIGHT	8
-#define AC97_SLOT_LFE		9
-#define AC97_SLOT_SPDIF_RIGHT1	9
-#define AC97_SLOT_MODEM_LINE2	10
-#define AC97_SLOT_PCM_LEFT_1	10	/* double rate operation */
-#define AC97_SLOT_SPDIF_LEFT2	10
-#define AC97_SLOT_HANDSET	11	/* output */
-#define AC97_SLOT_PCM_RIGHT_1	11	/* double rate operation */
-#define AC97_SLOT_SPDIF_RIGHT2	11
-#define AC97_SLOT_MODEM_GPIO	12	/* modem GPIO */
-#define AC97_SLOT_PCM_CENTER_1	12	/* double rate operation */
-
-/* basic capabilities (reset register) */
-#define AC97_BC_DEDICATED_MIC	0x0001	/* Dedicated Mic PCM In Channel */
-#define AC97_BC_RESERVED1	0x0002	/* Reserved (was Modem Line Codec support) */
-#define AC97_BC_BASS_TREBLE	0x0004	/* Bass & Treble Control */
-#define AC97_BC_SIM_STEREO	0x0008	/* Simulated stereo */
-#define AC97_BC_HEADPHONE	0x0010	/* Headphone Out Support */
-#define AC97_BC_LOUDNESS	0x0020	/* Loudness (bass boost) Support */
-#define AC97_BC_16BIT_DAC	0x0000	/* 16-bit DAC resolution */
-#define AC97_BC_18BIT_DAC	0x0040	/* 18-bit DAC resolution */
-#define AC97_BC_20BIT_DAC	0x0080	/* 20-bit DAC resolution */
-#define AC97_BC_DAC_MASK	0x00c0
-#define AC97_BC_16BIT_ADC	0x0000	/* 16-bit ADC resolution */
-#define AC97_BC_18BIT_ADC	0x0100	/* 18-bit ADC resolution */
-#define AC97_BC_20BIT_ADC	0x0200	/* 20-bit ADC resolution */
-#define AC97_BC_ADC_MASK	0x0300
-#define AC97_BC_3D_TECH_ID_MASK	0x7c00	/* Per-vendor ID of 3D enhancement */
-
-/* general purpose */
-#define AC97_GP_DRSS_MASK	0x0c00	/* double rate slot select */
-#define AC97_GP_DRSS_1011	0x0000	/* LR(C) 10+11(+12) */
-#define AC97_GP_DRSS_78		0x0400	/* LR 7+8 */
-
-/* powerdown bits */
-#define AC97_PD_ADC_STATUS	0x0001	/* ADC status (RO) */
-#define AC97_PD_DAC_STATUS	0x0002	/* DAC status (RO) */
-#define AC97_PD_MIXER_STATUS	0x0004	/* Analog mixer status (RO) */
-#define AC97_PD_VREF_STATUS	0x0008	/* Vref status (RO) */
-#define AC97_PD_PR0		0x0100	/* Power down PCM ADCs and input MUX */
-#define AC97_PD_PR1		0x0200	/* Power down PCM front DAC */
-#define AC97_PD_PR2		0x0400	/* Power down Mixer (Vref still on) */
-#define AC97_PD_PR3		0x0800	/* Power down Mixer (Vref off) */
-#define AC97_PD_PR4		0x1000	/* Power down AC-Link */
-#define AC97_PD_PR5		0x2000	/* Disable internal clock usage */
-#define AC97_PD_PR6		0x4000	/* Headphone amplifier */
-#define AC97_PD_EAPD		0x8000	/* External Amplifer Power Down (EAPD) */
-
-/* extended audio ID bit defines */
-#define AC97_EI_VRA		0x0001	/* Variable bit rate supported */
-#define AC97_EI_DRA		0x0002	/* Double rate supported */
-#define AC97_EI_SPDIF		0x0004	/* S/PDIF out supported */
-#define AC97_EI_VRM		0x0008	/* Variable bit rate supported for MIC */
-#define AC97_EI_DACS_SLOT_MASK	0x0030	/* DACs slot assignment */
-#define AC97_EI_DACS_SLOT_SHIFT	4
-#define AC97_EI_CDAC		0x0040	/* PCM Center DAC available */
-#define AC97_EI_SDAC		0x0080	/* PCM Surround DACs available */
-#define AC97_EI_LDAC		0x0100	/* PCM LFE DAC available */
-#define AC97_EI_AMAP		0x0200	/* indicates optional slot/DAC mapping based on codec ID */
-#define AC97_EI_REV_MASK	0x0c00	/* AC'97 revision mask */
-#define AC97_EI_REV_22		0x0400	/* AC'97 revision 2.2 */
-#define AC97_EI_REV_23		0x0800	/* AC'97 revision 2.3 */
-#define AC97_EI_REV_SHIFT	10
-#define AC97_EI_ADDR_MASK	0xc000	/* physical codec ID (address) */
-#define AC97_EI_ADDR_SHIFT	14
-
-/* extended audio status and control bit defines */
-#define AC97_EA_VRA		0x0001	/* Variable bit rate enable bit */
-#define AC97_EA_DRA		0x0002	/* Double-rate audio enable bit */
-#define AC97_EA_SPDIF		0x0004	/* S/PDIF out enable bit */
-#define AC97_EA_VRM		0x0008	/* Variable bit rate for MIC enable bit */
-#define AC97_EA_SPSA_SLOT_MASK	0x0030	/* Mask for slot assignment bits */
-#define AC97_EA_SPSA_SLOT_SHIFT 4
-#define AC97_EA_SPSA_3_4	0x0000	/* Slot assigned to 3 & 4 */
-#define AC97_EA_SPSA_7_8	0x0010	/* Slot assigned to 7 & 8 */
-#define AC97_EA_SPSA_6_9	0x0020	/* Slot assigned to 6 & 9 */
-#define AC97_EA_SPSA_10_11	0x0030	/* Slot assigned to 10 & 11 */
-#define AC97_EA_CDAC		0x0040	/* PCM Center DAC is ready (Read only) */
-#define AC97_EA_SDAC		0x0080	/* PCM Surround DACs are ready (Read only) */
-#define AC97_EA_LDAC		0x0100	/* PCM LFE DAC is ready (Read only) */
-#define AC97_EA_MDAC		0x0200	/* MIC ADC is ready (Read only) */
-#define AC97_EA_SPCV		0x0400	/* S/PDIF configuration valid (Read only) */
-#define AC97_EA_PRI		0x0800	/* Turns the PCM Center DAC off */
-#define AC97_EA_PRJ		0x1000	/* Turns the PCM Surround DACs off */
-#define AC97_EA_PRK		0x2000	/* Turns the PCM LFE DAC off */
-#define AC97_EA_PRL		0x4000	/* Turns the MIC ADC off */
-
-/* S/PDIF control bit defines */
-#define AC97_SC_PRO		0x0001	/* Professional status */
-#define AC97_SC_NAUDIO		0x0002	/* Non audio stream */
-#define AC97_SC_COPY		0x0004	/* Copyright status */
-#define AC97_SC_PRE		0x0008	/* Preemphasis status */
-#define AC97_SC_CC_MASK		0x07f0	/* Category Code mask */
-#define AC97_SC_CC_SHIFT	4
-#define AC97_SC_L		0x0800	/* Generation Level status */
-#define AC97_SC_SPSR_MASK	0x3000	/* S/PDIF Sample Rate bits */
-#define AC97_SC_SPSR_SHIFT	12
-#define AC97_SC_SPSR_44K	0x0000	/* Use 44.1kHz Sample rate */
-#define AC97_SC_SPSR_48K	0x2000	/* Use 48kHz Sample rate */
-#define AC97_SC_SPSR_32K	0x3000	/* Use 32kHz Sample rate */
-#define AC97_SC_DRS		0x4000	/* Double Rate S/PDIF */
-#define AC97_SC_V		0x8000	/* Validity status */
-
-/* Interrupt and Paging bit defines (AC'97 2.3) */
-#define AC97_PAGE_MASK		0x000f	/* Page Selector */
-#define AC97_PAGE_VENDOR	0	/* Vendor-specific registers */
-#define AC97_PAGE_1		1	/* Extended Codec Registers page 1 */
-#define AC97_INT_ENABLE		0x0800	/* Interrupt Enable */
-#define AC97_INT_SENSE		0x1000	/* Sense Cycle */
-#define AC97_INT_CAUSE_SENSE	0x2000	/* Sense Cycle Completed (RO) */
-#define AC97_INT_CAUSE_GPIO	0x4000	/* GPIO bits changed (RO) */
-#define AC97_INT_STATUS		0x8000	/* Interrupt Status */
-
-/* extended modem ID bit defines */
-#define AC97_MEI_LINE1		0x0001	/* Line1 present */
-#define AC97_MEI_LINE2		0x0002	/* Line2 present */
-#define AC97_MEI_HANDSET	0x0004	/* Handset present */
-#define AC97_MEI_CID1		0x0008	/* caller ID decode for Line1 is supported */
-#define AC97_MEI_CID2		0x0010	/* caller ID decode for Line2 is supported */
-#define AC97_MEI_ADDR_MASK	0xc000	/* physical codec ID (address) */
-#define AC97_MEI_ADDR_SHIFT	14
-
-/* extended modem status and control bit defines */
-#define AC97_MEA_GPIO		0x0001	/* GPIO is ready (ro) */
-#define AC97_MEA_MREF		0x0002	/* Vref is up to nominal level (ro) */
-#define AC97_MEA_ADC1		0x0004	/* ADC1 operational (ro) */
-#define AC97_MEA_DAC1		0x0008	/* DAC1 operational (ro) */
-#define AC97_MEA_ADC2		0x0010	/* ADC2 operational (ro) */
-#define AC97_MEA_DAC2		0x0020	/* DAC2 operational (ro) */
-#define AC97_MEA_HADC		0x0040	/* HADC operational (ro) */
-#define AC97_MEA_HDAC		0x0080	/* HDAC operational (ro) */
-#define AC97_MEA_PRA		0x0100	/* GPIO power down (high) */
-#define AC97_MEA_PRB		0x0200	/* reserved */
-#define AC97_MEA_PRC		0x0400	/* ADC1 power down (high) */
-#define AC97_MEA_PRD		0x0800	/* DAC1 power down (high) */
-#define AC97_MEA_PRE		0x1000	/* ADC2 power down (high) */
-#define AC97_MEA_PRF		0x2000	/* DAC2 power down (high) */
-#define AC97_MEA_PRG		0x4000	/* HADC power down (high) */
-#define AC97_MEA_PRH		0x8000	/* HDAC power down (high) */
-
-/* modem gpio status defines */
-#define AC97_GPIO_LINE1_OH      0x0001  /* Off Hook Line1 */
-#define AC97_GPIO_LINE1_RI      0x0002  /* Ring Detect Line1 */
-#define AC97_GPIO_LINE1_CID     0x0004  /* Caller ID path enable Line1 */
-#define AC97_GPIO_LINE1_LCS     0x0008  /* Loop Current Sense Line1 */
-#define AC97_GPIO_LINE1_PULSE   0x0010  /* Opt./ Pulse Dial Line1 (out) */
-#define AC97_GPIO_LINE1_HL1R    0x0020  /* Opt./ Handset to Line1 relay control (out) */
-#define AC97_GPIO_LINE1_HOHD    0x0040  /* Opt./ Handset off hook detect Line1 (in) */
-#define AC97_GPIO_LINE12_AC     0x0080  /* Opt./ Int.bit 1 / Line1/2 AC (out) */
-#define AC97_GPIO_LINE12_DC     0x0100  /* Opt./ Int.bit 2 / Line1/2 DC (out) */
-#define AC97_GPIO_LINE12_RS     0x0200  /* Opt./ Int.bit 3 / Line1/2 RS (out) */
-#define AC97_GPIO_LINE2_OH      0x0400  /* Off Hook Line2 */
-#define AC97_GPIO_LINE2_RI      0x0800  /* Ring Detect Line2 */
-#define AC97_GPIO_LINE2_CID     0x1000  /* Caller ID path enable Line2 */
-#define AC97_GPIO_LINE2_LCS     0x2000  /* Loop Current Sense Line2 */
-#define AC97_GPIO_LINE2_PULSE   0x4000  /* Opt./ Pulse Dial Line2 (out) */
-#define AC97_GPIO_LINE2_HL1R    0x8000  /* Opt./ Handset to Line2 relay control (out) */
-
 /* specific - SigmaTel */
 #define AC97_SIGMATEL_OUTSEL	0x64	/* Output Select, STAC9758 */
 #define AC97_SIGMATEL_INSEL	0x66	/* Input Select, STAC9758 */
-- 
2.1.4



From linux at roeck-us.net  Fri May 27 13:27:15 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 27 May 2016 13:27:15 -0700
Subject: pxa_defconfig runtime failures due to 'ARM: pxa: activate pinctrl
 for device-tree machines'
Message-ID: <20160527202715.GA4841@roeck-us.net>

Hi,

your mainline commit f806dac5938b ("ARM: pxa: activate pinctrl for device-tree
machines") causes various non-devicetree systems to fail with the following
error messages when running a pxa_defconfig image.

During boot:

Can't request reset_gpio

At reboot:

reboot: Restarting system
------------[ cut here ]------------
kernel BUG at arch/arm/mach-pxa/reset.c:59!
...

Added logging shows that the error seen when trying to request the reset gpio
is -EPROBE_DEFER, and that the pxa gpio driver is not instantiated.

This is seen when attempting to run akita, borzoi, spitz, terrier, or tosa
in qemu with pxa_defconfig. Reverting your patch fixes the problem.

Is this on purpose ? Unless I am missing something, it effectively means that
pxa_defconfig no longer works for pxa3xx systems, since those do not support
devicetree (or at least there is no devicetree file which includes pxa3xx.dtsi).

Thanks,
Guenter


From broonie at kernel.org  Fri May 27 13:31:40 2016
From: broonie at kernel.org (Mark Brown)
Date: Fri, 27 May 2016 21:31:40 +0100
Subject: [PATCH 14/14] ASoC: omap-mcpdm: Add support for pdmclk clock
 handling
In-Reply-To: <1463579196-5484-15-git-send-email-peter.ujfalusi@ti.com>
References: <1463579196-5484-1-git-send-email-peter.ujfalusi@ti.com>
 <1463579196-5484-15-git-send-email-peter.ujfalusi@ti.com>
Message-ID: <20160527203140.GD29837@sirena.org.uk>

On Wed, May 18, 2016 at 04:46:36PM +0300, Peter Ujfalusi wrote:

> +	clk_prepare_enable(mcpdm->pdmclk);

Should really check the return value here.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160527/e9a4f037/attachment.sig>

From pavel at ucw.cz  Fri May 27 13:33:11 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Fri, 27 May 2016 22:33:11 +0200
Subject: [PATCHv4] support for AD5820 camera auto-focus coil
In-Reply-To: <20160525212659.GK26360@valkosipuli.retiisi.org.uk>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com> <20160521105607.GA20071@amd>
 <574049EF.2090208@gmail.com> <20160524090433.GA1277@amd>
 <20160524091746.GA14536@amd>
 <20160525212659.GK26360@valkosipuli.retiisi.org.uk>
Message-ID: <20160527203311.GA13282@amd>

Hi!

> > + * Contact: Tuukka Toivonen
> > + *          Sakari Ailus
> 
> Could you put the e-mail addresses back, please?
> 
> Tuukka's e-mail is tuukkat76 at gmail.com .

Ok.

> > +#include <linux/module.h>
> > +#include <linux/errno.h>
> > +#include <linux/i2c.h>
> > +#include <linux/kernel.h>
> > +#include <linux/regulator/consumer.h>
> 
> Alphabetical order would be nice. The same below.

I was afraid you'd ask. Ok.

> > +/**
> > + * @brief I2C write using i2c_transfer().
> > + * @param coil - the driver data structure
> > + * @param data - register value to be written
> 
> This does not look entirely right. But you could just remove the entire
> comment. It's useless.

Ok.
> > +	int ret = 0;
> > +
> > +	/*
> > +	 * Go to standby first as real power off my be denied by the hardware
> > +	 * (single power line control for both coil and sensor).
> > +	 */
> > +	if (standby) {
> > +		coil->standby = 1;
> > +		ret = ad5820_update_hw(coil);
> > +	}
> > +
> > +	ret |= regulator_disable(coil->vana);
> 
> This is actually an error code and you shouldn't use or to combine two error
> codes. The result will make no sense.
> 
> It might be the driver did this in the past but it should not be done. The
> right thing, as elsewhere, is to assign the value to ret and check it. The
> assigment in declaration may be dropped as well.

Yeah, its broken. Let me fix it. 

> I think this happens in a few places in the driver.

Actually this was the only place left.


> > +	struct ad5820_device *coil = to_ad5820_device(subdev);
> > +	struct i2c_client *client = v4l2_get_subdevdata(subdev);
> > +
> > +	coil->vana = regulator_get(&client->dev, "VANA");
> 
> Is there a reason not to acquire this in probe instead?

Yeah, new version will do that (already done, Dmitry was faster).

> > +	if (IS_ERR(coil->vana)) {
> > +		dev_err(&client->dev, "could not get regulator for vana\n");
> > +		return -ENODEV;
> 
> I wonder if -EPROBE_DEFER might be the right error code here.

..and should handle PROBE_DEFER, too.

> > +static int ad5820_probe(struct i2c_client *client,
> > +			const struct i2c_device_id *devid)
> > +{
> > +	struct ad5820_device *coil;
> > +	int ret = 0;
> 
> No need to assign ret here.

Ok.

> > +
> > +	coil = kzalloc(sizeof(*coil), GFP_KERNEL);
> 
> You could use devm_kzalloc() here and drop kfree() below and in _remove().
> 
> The driver might be actually older than the devm_*() functions. Not sure. At
> least they were not widely used back then. :-)

Already done, Dmitry was faster.

> > +static int __exit ad5820_remove(struct i2c_client *client)
> > +{
> > +	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
> > +	struct ad5820_device *coil = to_ad5820_device(subdev);
> > +
> > +	v4l2_device_unregister_subdev(&coil->subdev);
> > +	v4l2_ctrl_handler_free(&coil->ctrls);
> > +	media_entity_cleanup(&coil->subdev.entity);
> > +	if (coil->vana)
> > +		regulator_put(coil->vana);
> 
> mutex_destroy(&coil->power_lock);
> 
> Here. And in probe() error paths as well.

Ok. Can do, altrough it is pretty much a NOP in the error paths.

Thanks,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From broonie at kernel.org  Fri May 27 13:46:45 2016
From: broonie at kernel.org (Mark Brown)
Date: Fri, 27 May 2016 21:46:45 +0100
Subject: Applied "spi: orion: Add direct access mode" to the spi tree
In-Reply-To: <1463641625-15601-1-git-send-email-sr@denx.de>
Message-ID: <E1b6Oeb-0001m7-Hi@debutante>

The patch

   spi: orion: Add direct access mode

has been applied to the spi tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 90b89a719c773844040822328efe68b17395d63b Mon Sep 17 00:00:00 2001
From: Stefan Roese <sr at denx.de>
Date: Thu, 19 May 2016 09:07:05 +0200
Subject: [PATCH] spi: orion: Add direct access mode

This patch adds support for the direct access mode to the Orion SPI
driver which is used on the Marvell Armada based SoCs. In this direct
mode, all data written to (or read from) a specifically mapped MBus
window (linked to one SPI chip-select on one of the SPI controllers)
will be transferred directly to the SPI bus. Without the need to control
the SPI registers in between. This can improve the SPI transfer rate in
such cases.

Both, direct-read and -write mode are supported. But only the write
mode has been tested. This mode especially benefits from the SPI direct
mode, as the data bytes are written head-to-head to the SPI bus,
without any additional addresses.

One use-case for this direct write mode is, programming a FPGA bitstream
image into the FPGA connected to the SPI bus at maximum speed.

This mode is described in chapter "22.5.2 Direct Write to SPI" in the
Marvell Armada XP Functional Spec Datasheet.

Signed-off-by: Stefan Roese <sr at denx.de>
Acked-by: Arnd Bergmann <arnd at arndb.de>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 .../devicetree/bindings/spi/spi-orion.txt          | 49 +++++++++++-
 drivers/spi/spi-orion.c                            | 88 ++++++++++++++++++++++
 2 files changed, 136 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-orion.txt b/Documentation/devicetree/bindings/spi/spi-orion.txt
index 98bc69815eb3..4f629cc7634a 100644
--- a/Documentation/devicetree/bindings/spi/spi-orion.txt
+++ b/Documentation/devicetree/bindings/spi/spi-orion.txt
@@ -8,7 +8,15 @@ Required properties:
     - "marvell,armada-380-spi", for the Armada 38x SoCs
     - "marvell,armada-390-spi", for the Armada 39x SoCs
     - "marvell,armada-xp-spi", for the Armada XP SoCs
-- reg : offset and length of the register set for the device
+- reg : offset and length of the register set for the device.
+	This property can optionally have additional entries to configure
+	the SPI direct access mode that some of the Marvell SoCs support
+	additionally to the normal indirect access (PIO) mode. The values
+	for the MBus "target" and "attribute" are defined in the Marvell
+	SoC "Functional Specifications" Manual in the chapter "Marvell
+	Core Processor Address Decoding".
+	The eight register sets following the control registers refer to
+	chip-select lines 0 through 7 respectively.
 - cell-index : Which of multiple SPI controllers is this.
 Optional properties:
 - interrupts : Is currently not used.
@@ -23,3 +31,42 @@ Example:
 	       interrupts = <23>;
 	       status = "disabled";
        };
+
+Example with SPI direct mode support (optionally):
+	spi0: spi at 10600 {
+		compatible = "marvell,orion-spi";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cell-index = <0>;
+		reg = <MBUS_ID(0xf0, 0x01) 0x10600 0x28>, /* control */
+		      <MBUS_ID(0x01, 0x1e) 0 0xffffffff>, /* CS0 */
+		      <MBUS_ID(0x01, 0x5e) 0 0xffffffff>, /* CS1 */
+		      <MBUS_ID(0x01, 0x9e) 0 0xffffffff>, /* CS2 */
+		      <MBUS_ID(0x01, 0xde) 0 0xffffffff>, /* CS3 */
+		      <MBUS_ID(0x01, 0x1f) 0 0xffffffff>, /* CS4 */
+		      <MBUS_ID(0x01, 0x5f) 0 0xffffffff>, /* CS5 */
+		      <MBUS_ID(0x01, 0x9f) 0 0xffffffff>, /* CS6 */
+		      <MBUS_ID(0x01, 0xdf) 0 0xffffffff>; /* CS7 */
+		interrupts = <23>;
+		status = "disabled";
+	};
+
+To enable the direct mode, the board specific 'ranges' property in the
+'soc' node needs to add the entries for the desired SPI controllers
+and its chip-selects that are used in the direct mode instead of PIO
+mode. Here an example for this (SPI controller 0, device 1 and SPI
+controller 1, device 2 are used in direct mode. All other SPI device
+are used in the default indirect (PIO) mode):
+	soc {
+		/*
+		 * Enable the SPI direct access by configuring an entry
+		 * here in the board-specific ranges property
+		 */
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000>,	/* internal regs */
+			 <MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>,	/* BootROM       */
+			 <MBUS_ID(0x01, 0x5e) 0 0 0xf1100000 0x10000>,	/* SPI0-DEV1 */
+			 <MBUS_ID(0x01, 0x9a) 0 0 0xf1110000 0x10000>;	/* SPI1-DEV2 */
+
+For further information on the MBus bindings, please see the MBus
+DT documentation:
+Documentation/devicetree/bindings/bus/mvebu-mbus.txt
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index a87cfd4ba17b..d0d9c8682b32 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/clk.h>
 #include <linux/sizes.h>
@@ -43,6 +44,9 @@
 #define ORION_SPI_INT_CAUSE_REG		0x10
 #define ORION_SPI_TIMING_PARAMS_REG	0x18
 
+/* Register for the "Direct Mode" */
+#define SPI_DIRECT_WRITE_CONFIG_REG	0x20
+
 #define ORION_SPI_TMISO_SAMPLE_MASK	(0x3 << 6)
 #define ORION_SPI_TMISO_SAMPLE_1	(1 << 6)
 #define ORION_SPI_TMISO_SAMPLE_2	(2 << 6)
@@ -78,11 +82,18 @@ struct orion_spi_dev {
 	bool			is_errata_50mhz_ac;
 };
 
+struct orion_direct_acc {
+	void __iomem		*vaddr;
+	u32			size;
+};
+
 struct orion_spi {
 	struct spi_master	*master;
 	void __iomem		*base;
 	struct clk              *clk;
 	const struct orion_spi_dev *devdata;
+
+	struct orion_direct_acc	direct_access[ORION_NUM_CHIPSELECTS];
 };
 
 static inline void __iomem *spi_reg(struct orion_spi *orion_spi, u32 reg)
@@ -372,10 +383,39 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer)
 {
 	unsigned int count;
 	int word_len;
+	struct orion_spi *orion_spi;
+	int cs = spi->chip_select;
 
 	word_len = spi->bits_per_word;
 	count = xfer->len;
 
+	orion_spi = spi_master_get_devdata(spi->master);
+
+	/*
+	 * Use SPI direct write mode if base address is available. Otherwise
+	 * fall back to PIO mode for this transfer.
+	 */
+	if ((orion_spi->direct_access[cs].vaddr) && (xfer->tx_buf) &&
+	    (word_len == 8)) {
+		unsigned int cnt = count / 4;
+		unsigned int rem = count % 4;
+
+		/*
+		 * Send the TX-data to the SPI device via the direct
+		 * mapped address window
+		 */
+		iowrite32_rep(orion_spi->direct_access[cs].vaddr,
+			      xfer->tx_buf, cnt);
+		if (rem) {
+			u32 *buf = (u32 *)xfer->tx_buf;
+
+			iowrite8_rep(orion_spi->direct_access[cs].vaddr,
+				     &buf[cnt], rem);
+		}
+
+		return count;
+	}
+
 	if (word_len == 8) {
 		const u8 *tx = xfer->tx_buf;
 		u8 *rx = xfer->rx_buf;
@@ -425,6 +465,10 @@ static int orion_spi_reset(struct orion_spi *orion_spi)
 {
 	/* Verify that the CS is deasserted */
 	orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, 0x1);
+
+	/* Don't deassert CS between the direct mapped SPI transfers */
+	writel(0, spi_reg(orion_spi, SPI_DIRECT_WRITE_CONFIG_REG));
+
 	return 0;
 }
 
@@ -504,6 +548,7 @@ static int orion_spi_probe(struct platform_device *pdev)
 	struct resource *r;
 	unsigned long tclk_hz;
 	int status = 0;
+	struct device_node *np;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(*spi));
 	if (master == NULL) {
@@ -576,6 +621,49 @@ static int orion_spi_probe(struct platform_device *pdev)
 		goto out_rel_clk;
 	}
 
+	/* Scan all SPI devices of this controller for direct mapped devices */
+	for_each_available_child_of_node(pdev->dev.of_node, np) {
+		u32 cs;
+
+		/* Get chip-select number from the "reg" property */
+		status = of_property_read_u32(np, "reg", &cs);
+		if (status) {
+			dev_err(&pdev->dev,
+				"%s has no valid 'reg' property (%d)\n",
+				np->full_name, status);
+			status = 0;
+			continue;
+		}
+
+		/*
+		 * Check if an address is configured for this SPI device. If
+		 * not, the MBus mapping via the 'ranges' property in the 'soc'
+		 * node is not configured and this device should not use the
+		 * direct mode. In this case, just continue with the next
+		 * device.
+		 */
+		status = of_address_to_resource(pdev->dev.of_node, cs + 1, r);
+		if (status)
+			continue;
+
+		/*
+		 * Only map one page for direct access. This is enough for the
+		 * simple TX transfer which only writes to the first word.
+		 * This needs to get extended for the direct SPI-NOR / SPI-NAND
+		 * support, once this gets implemented.
+		 */
+		spi->direct_access[cs].vaddr = devm_ioremap(&pdev->dev,
+							    r->start,
+							    PAGE_SIZE);
+		if (IS_ERR(spi->direct_access[cs].vaddr)) {
+			status = PTR_ERR(spi->direct_access[cs].vaddr);
+			goto out_rel_clk;
+		}
+		spi->direct_access[cs].size = PAGE_SIZE;
+
+		dev_info(&pdev->dev, "CS%d configured for direct access\n", cs);
+	}
+
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
-- 
2.8.1



From pavel at ucw.cz  Fri May 27 13:51:40 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Fri, 27 May 2016 22:51:40 +0200
Subject: [PATCHv5] support for AD5820 camera auto-focus coil
In-Reply-To: <20160525212659.GK26360@valkosipuli.retiisi.org.uk>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com> <20160521105607.GA20071@amd>
 <574049EF.2090208@gmail.com> <20160524090433.GA1277@amd>
 <20160524091746.GA14536@amd>
 <20160525212659.GK26360@valkosipuli.retiisi.org.uk>
Message-ID: <20160527205140.GA26767@amd>


This adds support for AD5820 autofocus coil, found for example in
Nokia N900 smartphone.

Signed-off-by: Pavel Machek <pavel at ucw.cz>

---
v2: simple cleanups, fix error paths, simplify probe
v3: more cleanups, remove printk, add include
v4: remove header file.
v5: switch to devm_ , style cleanups, fixes

diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 993dc50..77313a1 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -279,6 +279,13 @@ config VIDEO_ML86V7667
 	  To compile this driver as a module, choose M here: the
 	  module will be called ml86v7667.
 
+config VIDEO_AD5820
+	tristate "AD5820 lens voice coil support"
+	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+	---help---
+	  This is a driver for the AD5820 camera lens voice coil.
+	  It is used for example in Nokia N900 (RX-51).
+
 config VIDEO_SAA7110
 	tristate "Philips SAA7110 video decoder"
 	depends on VIDEO_V4L2 && I2C
index 94f2c99..34434ae 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -19,6 +20,7 @@ obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
 obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
 obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
+obj-$(CONFIG_VIDEO_AD5820)  += ad5820.o
 obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
 obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
 obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c
new file mode 100644
index 0000000..2efa5dc1
--- /dev/null
+++ b/drivers/media/i2c/ad5820.c
@@ -0,0 +1,428 @@
+/*
+ * drivers/media/i2c/ad5820.c
+ *
+ * AD5820 DAC driver for camera voice coil focus.
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2007 Texas Instruments
+ * Copyright (C) 2016 Pavel Machek <pavel at ucw.cz>
+ *
+ * Contact: Tuukka Toivonen <tuukkat76 at gmail.com>
+ *	    Sakari Ailus <sakari.ailus at iki.fi>
+ *
+ * Based on af_d88.c by Texas Instruments.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#define AD5820_NAME		"ad5820"
+
+/* Register definitions */
+#define AD5820_POWER_DOWN		(1 << 15)
+#define AD5820_DAC_SHIFT		4
+#define AD5820_RAMP_MODE_LINEAR		(0 << 3)
+#define AD5820_RAMP_MODE_64_16		(1 << 3)
+
+#define CODE_TO_RAMP_US(s)	((s) == 0 ? 0 : (1 << ((s) - 1)) * 50)
+#define RAMP_US_TO_CODE(c)	fls(((c) + ((c)>>1)) / 50)
+
+#define to_ad5820_device(sd)	container_of(sd, struct ad5820_device, subdev)
+
+struct ad5820_device {
+	struct v4l2_subdev subdev;
+	struct ad5820_platform_data *platform_data;
+	struct regulator *vana;
+
+	struct v4l2_ctrl_handler ctrls;
+	u32 focus_absolute;
+	u32 focus_ramp_time;
+	u32 focus_ramp_mode;
+
+	struct mutex power_lock;
+	int power_count;
+
+	int standby : 1;
+};
+
+static int ad5820_write(struct ad5820_device *coil, u16 data)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&coil->subdev);
+	struct i2c_msg msg;
+	int r;
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	data = cpu_to_be16(data);
+	msg.addr  = client->addr;
+	msg.flags = 0;
+	msg.len   = 2;
+	msg.buf   = (u8 *)&data;
+
+	r = i2c_transfer(client->adapter, &msg, 1);
+	if (r < 0) {
+		dev_err(&client->dev, "write failed, error %d\n", r);
+		return r;
+	}
+
+	return 0;
+}
+
+/*
+ * Calculate status word and write it to the device based on current
+ * values of V4L2 controls. It is assumed that the stored V4L2 control
+ * values are properly limited and rounded.
+ */
+static int ad5820_update_hw(struct ad5820_device *coil)
+{
+	u16 status;
+
+	status = RAMP_US_TO_CODE(coil->focus_ramp_time);
+	status |= coil->focus_ramp_mode
+		? AD5820_RAMP_MODE_64_16 : AD5820_RAMP_MODE_LINEAR;
+	status |= coil->focus_absolute << AD5820_DAC_SHIFT;
+
+	if (coil->standby)
+		status |= AD5820_POWER_DOWN;
+
+	return ad5820_write(coil, status);
+}
+
+/*
+ * Power handling
+ */
+static int ad5820_power_off(struct ad5820_device *coil, int standby)
+{
+	int ret = 0, ret2;
+
+	/*
+	 * Go to standby first as real power off my be denied by the hardware
+	 * (single power line control for both coil and sensor).
+	 */
+	if (standby) {
+		coil->standby = 1;
+		ret = ad5820_update_hw(coil);
+	}
+
+	ret2 = regulator_disable(coil->vana);
+	if (ret)
+		return ret;
+	return ret2;
+}
+
+static int ad5820_power_on(struct ad5820_device *coil, int restore)
+{
+	int ret;
+
+	ret = regulator_enable(coil->vana);
+	if (ret < 0)
+		return ret;
+
+	if (restore) {
+		/* Restore the hardware settings. */
+		coil->standby = 0;
+		ret = ad5820_update_hw(coil);
+		if (ret)
+			goto fail;
+	}
+	return 0;
+
+fail:
+	coil->standby = 1;
+	regulator_disable(coil->vana);
+
+	return ret;
+}
+
+/*
+ * V4L2 controls
+ */
+static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ad5820_device *coil =
+		container_of(ctrl->handler, struct ad5820_device, ctrls);
+	u32 code;
+
+	switch (ctrl->id) {
+	case V4L2_CID_FOCUS_ABSOLUTE:
+		coil->focus_absolute = ctrl->val;
+		return ad5820_update_hw(coil);
+
+	case V4L2_CID_FOCUS_AD5820_RAMP_TIME:
+		code = RAMP_US_TO_CODE(ctrl->val);
+		ctrl->val = CODE_TO_RAMP_US(code);
+		coil->focus_ramp_time = ctrl->val;
+		break;
+
+	case V4L2_CID_FOCUS_AD5820_RAMP_MODE:
+		coil->focus_ramp_mode = ctrl->val;
+		break;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops ad5820_ctrl_ops = {
+	.s_ctrl = ad5820_set_ctrl,
+};
+
+static const char * const ad5820_focus_menu[] = {
+	"Linear ramp",
+	"64/16 ramp",
+};
+
+static const struct v4l2_ctrl_config ad5820_ctrls[] = {
+	{
+		.ops		= &ad5820_ctrl_ops,
+		.id		= V4L2_CID_FOCUS_AD5820_RAMP_TIME,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Focus ramping time [us]",
+		.min		= 0,
+		.max		= 3200,
+		.step		= 50,
+		.def		= 0,
+		.flags		= 0,
+	},
+	{
+		.ops		= &ad5820_ctrl_ops,
+		.id		= V4L2_CID_FOCUS_AD5820_RAMP_MODE,
+		.type		= V4L2_CTRL_TYPE_MENU,
+		.name		= "Focus ramping mode",
+		.min		= 0,
+		.max		= ARRAY_SIZE(ad5820_focus_menu),
+		.step		= 0,
+		.def		= 0,
+		.flags		= 0,
+		.qmenu		= ad5820_focus_menu,
+	},
+};
+
+
+static int ad5820_init_controls(struct ad5820_device *coil)
+{
+	unsigned int i;
+
+	v4l2_ctrl_handler_init(&coil->ctrls, ARRAY_SIZE(ad5820_ctrls) + 1);
+
+	/*
+	 * V4L2_CID_FOCUS_ABSOLUTE
+	 *
+	 * Minimum current is 0 mA, maximum is 100 mA. Thus, 1 code is
+	 * equivalent to 100/1023 = 0.0978 mA. Nevertheless, we do not use [mA]
+	 * for focus position, because it is meaningless for user. Meaningful
+	 * would be to use focus distance or even its inverse, but since the
+	 * driver doesn't have sufficiently knowledge to do the conversion, we
+	 * will just use abstract codes here. In any case, smaller value = focus
+	 * position farther from camera. The default zero value means focus at
+	 * infinity, and also least current consumption.
+	 */
+	v4l2_ctrl_new_std(&coil->ctrls, &ad5820_ctrl_ops,
+			  V4L2_CID_FOCUS_ABSOLUTE, 0, 1023, 1, 0);
+
+	/* V4L2_CID_TEST_PATTERN and V4L2_CID_MODE_* */
+	for (i = 0; i < ARRAY_SIZE(ad5820_ctrls); ++i)
+		v4l2_ctrl_new_custom(&coil->ctrls, &ad5820_ctrls[i], NULL);
+
+	if (coil->ctrls.error)
+		return coil->ctrls.error;
+
+	coil->focus_absolute = 0;
+	coil->focus_ramp_time = 0;
+	coil->focus_ramp_mode = 0;
+
+	coil->subdev.ctrl_handler = &coil->ctrls;
+
+	return 0;
+}
+
+/*
+ * V4L2 subdev operations
+ */
+static int ad5820_registered(struct v4l2_subdev *subdev)
+{
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	return ad5820_init_controls(coil);
+}
+
+static int
+ad5820_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+	int ret = 0;
+
+	mutex_lock(&coil->power_lock);
+
+	/*
+	 * If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (coil->power_count == !on) {
+		ret = on ? ad5820_power_on(coil, 1) : ad5820_power_off(coil, 1);
+		if (ret < 0)
+			goto done;
+	}
+
+	/* Update the power count. */
+	coil->power_count += on ? 1 : -1;
+	WARN_ON(coil->power_count < 0);
+
+done:
+	mutex_unlock(&coil->power_lock);
+	return ret;
+}
+
+static int ad5820_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return ad5820_set_power(sd, 1);
+}
+
+static int ad5820_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return ad5820_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_core_ops ad5820_core_ops = {
+	.s_power = ad5820_set_power,
+};
+
+static const struct v4l2_subdev_ops ad5820_ops = {
+	.core = &ad5820_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops ad5820_internal_ops = {
+	.registered = ad5820_registered,
+	.open = ad5820_open,
+	.close = ad5820_close,
+};
+
+/*
+ * I2C driver
+ */
+#ifdef CONFIG_PM
+
+static int ad5820_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	if (!coil->power_count)
+		return 0;
+
+	return ad5820_power_off(coil, 0);
+}
+
+static int ad5820_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	if (!coil->power_count)
+		return 0;
+
+	return ad5820_power_on(coil, 1);
+}
+
+#else
+
+#define ad5820_suspend	NULL
+#define ad5820_resume	NULL
+
+#endif /* CONFIG_PM */
+
+static int ad5820_probe(struct i2c_client *client,
+			const struct i2c_device_id *devid)
+{
+	struct ad5820_device *coil;
+	int ret;
+
+	coil = devm_kzalloc(&client->dev, sizeof(*coil), GFP_KERNEL);
+	if (!coil)
+		return -ENOMEM;
+
+	coil->vana = devm_regulator_get(&client->dev, "VANA");
+	if (IS_ERR(coil->vana)) {
+		ret = PTR_ERR(coil->vana);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&client->dev, "could not get regulator for vana\n");
+		return ret;
+	}
+	
+	mutex_init(&coil->power_lock);
+
+	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
+	coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	coil->subdev.internal_ops = &ad5820_internal_ops;
+	strcpy(coil->subdev.name, "ad5820 focus");
+
+	ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
+	if (ret < 0)
+		goto cleanup2;
+
+	ret = v4l2_async_register_subdev(&coil->subdev);
+	if (ret < 0)
+		goto cleanup;
+
+	return ret;
+
+cleanup2:
+	mutex_destroy(&coil->power_lock);
+cleanup:
+	media_entity_cleanup(&coil->subdev.entity);
+	return ret;
+}
+
+static int __exit ad5820_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct ad5820_device *coil = to_ad5820_device(subdev);
+
+	v4l2_device_unregister_subdev(&coil->subdev);
+	v4l2_ctrl_handler_free(&coil->ctrls);
+	media_entity_cleanup(&coil->subdev.entity);
+	mutex_destroy(&coil->power_lock);
+	return 0;
+}
+
+static const struct i2c_device_id ad5820_id_table[] = {
+	{ AD5820_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ad5820_id_table);
+
+static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume);
+
+static struct i2c_driver ad5820_i2c_driver = {
+	.driver		= {
+		.name	= AD5820_NAME,
+		.pm	= &ad5820_pm,
+	},
+	.probe		= ad5820_probe,
+	.remove		= __exit_p(ad5820_remove),
+	.id_table	= ad5820_id_table,
+};
+
+module_i2c_driver(ad5820_i2c_driver);
+
+MODULE_AUTHOR("Tuukka Toivonen");
+MODULE_DESCRIPTION("AD5820 camera lens driver");
+MODULE_LICENSE("GPL");

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From yang.shi at linaro.org  Fri May 27 14:01:03 2016
From: yang.shi at linaro.org (Yang Shi)
Date: Fri, 27 May 2016 14:01:03 -0700
Subject: [v2 PATCH] arm64: kasan: instrument user memory access API
Message-ID: <1464382863-11879-1-git-send-email-yang.shi@linaro.org>

The upstream commit 1771c6e1a567ea0ba2cccc0a4ffe68a1419fd8ef
("x86/kasan: instrument user memory access API") added KASAN instrument to
x86 user memory access API, so added such instrument to ARM64 too.

Define __copy_to/from_user in C in order to add kasan_check_read/write call,
rename assembly implementation to __arch_copy_to/from_user.

Tested by test_kasan module.

Signed-off-by: Yang Shi <yang.shi at linaro.org>
---
v2:
 Adopted the comment from Andrey and Mark to add kasan_check_read/write into
 __copy_to/from_user.

 arch/arm64/include/asm/uaccess.h | 25 +++++++++++++++++++++----
 arch/arm64/kernel/arm64ksyms.c   |  4 ++--
 arch/arm64/lib/copy_from_user.S  |  4 ++--
 arch/arm64/lib/copy_to_user.S    |  4 ++--
 4 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 0685d74..4dc9a8f 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -23,6 +23,7 @@
  */
 #include <linux/string.h>
 #include <linux/thread_info.h>
+#include <linux/kasan-checks.h>
 
 #include <asm/alternative.h>
 #include <asm/cpufeature.h>
@@ -269,15 +270,29 @@ do {									\
 		-EFAULT;						\
 })
 
-extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n);
-extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n);
+extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n);
+extern unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n);
 extern unsigned long __must_check __copy_in_user(void __user *to, const void __user *from, unsigned long n);
 extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
 
+static inline unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	kasan_check_write(to, n);
+	return  __arch_copy_from_user(to, from, n);
+}
+
+static inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	kasan_check_read(from, n);
+	return  __arch_copy_to_user(to, from, n);
+}
+
 static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
 {
+	kasan_check_write(to, n);
+
 	if (access_ok(VERIFY_READ, from, n))
-		n = __copy_from_user(to, from, n);
+		n = __arch_copy_from_user(to, from, n);
 	else /* security hole - plug it */
 		memset(to, 0, n);
 	return n;
@@ -285,8 +300,10 @@ static inline unsigned long __must_check copy_from_user(void *to, const void __u
 
 static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
 {
+	kasan_check_read(from, n);
+
 	if (access_ok(VERIFY_WRITE, to, n))
-		n = __copy_to_user(to, from, n);
+		n = __arch_copy_to_user(to, from, n);
 	return n;
 }
 
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 678f30b0..2dc4440 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -34,8 +34,8 @@ EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(clear_page);
 
 	/* user mem (segment) */
-EXPORT_SYMBOL(__copy_from_user);
-EXPORT_SYMBOL(__copy_to_user);
+EXPORT_SYMBOL(__arch_copy_from_user);
+EXPORT_SYMBOL(__arch_copy_to_user);
 EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(__copy_in_user);
 
diff --git a/arch/arm64/lib/copy_from_user.S b/arch/arm64/lib/copy_from_user.S
index 17e8306..0b90497 100644
--- a/arch/arm64/lib/copy_from_user.S
+++ b/arch/arm64/lib/copy_from_user.S
@@ -66,7 +66,7 @@
 	.endm
 
 end	.req	x5
-ENTRY(__copy_from_user)
+ENTRY(__arch_copy_from_user)
 ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_ALT_PAN_NOT_UAO, \
 	    CONFIG_ARM64_PAN)
 	add	end, x0, x2
@@ -75,7 +75,7 @@ ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \
 	    CONFIG_ARM64_PAN)
 	mov	x0, #0				// Nothing to copy
 	ret
-ENDPROC(__copy_from_user)
+ENDPROC(__arch_copy_from_user)
 
 	.section .fixup,"ax"
 	.align	2
diff --git a/arch/arm64/lib/copy_to_user.S b/arch/arm64/lib/copy_to_user.S
index 21faae6..7a7efe2 100644
--- a/arch/arm64/lib/copy_to_user.S
+++ b/arch/arm64/lib/copy_to_user.S
@@ -65,7 +65,7 @@
 	.endm
 
 end	.req	x5
-ENTRY(__copy_to_user)
+ENTRY(__arch_copy_to_user)
 ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_ALT_PAN_NOT_UAO, \
 	    CONFIG_ARM64_PAN)
 	add	end, x0, x2
@@ -74,7 +74,7 @@ ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \
 	    CONFIG_ARM64_PAN)
 	mov	x0, #0
 	ret
-ENDPROC(__copy_to_user)
+ENDPROC(__arch_copy_to_user)
 
 	.section .fixup,"ax"
 	.align	2
-- 
2.0.2



From alexandre.belloni at free-electrons.com  Fri May 27 15:54:08 2016
From: alexandre.belloni at free-electrons.com (Alexandre Belloni)
Date: Sat, 28 May 2016 00:54:08 +0200
Subject: [PATCH] tty/serial: atmel: fix RS485 half duplex with DMA
Message-ID: <1464389648-4820-1-git-send-email-alexandre.belloni@free-electrons.com>

When using DMA, half duplex doesn't work properly because rx is not stopped
before starting tx. Ensure we call atmel_stop_rx() in the DMA case.

Signed-off-by: Alexandre Belloni <alexandre.belloni at free-electrons.com>
---
 drivers/tty/serial/atmel_serial.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 954941dd8124..f9c798cba83f 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -482,19 +482,21 @@ static void atmel_start_tx(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 
-	if (atmel_use_pdc_tx(port)) {
-		if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
-			/* The transmitter is already running.  Yes, we
-			   really need this.*/
-			return;
+	if (atmel_use_pdc_tx(port) && (atmel_uart_readl(port, ATMEL_PDC_PTSR)
+				       & ATMEL_PDC_TXTEN))
+		/* The transmitter is already running.  Yes, we
+		   really need this.*/
+		return;
 
+	if (atmel_use_pdc_tx(port) || atmel_use_dma_tx(port))
 		if ((port->rs485.flags & SER_RS485_ENABLED) &&
 		    !(port->rs485.flags & SER_RS485_RX_DURING_TX))
 			atmel_stop_rx(port);
 
+	if (atmel_use_pdc_tx(port))
 		/* re-enable PDC transmit */
 		atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
-	}
+
 	/* Enable interrupts */
 	atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
 }
-- 
2.8.1



From hzpeterchen at gmail.com  Fri May 27 20:36:13 2016
From: hzpeterchen at gmail.com (Peter Chen)
Date: Sat, 28 May 2016 11:36:13 +0800
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <CAPDyKFq2=mqujFjvJSYxg2nVmK=OrBKLtFfb-ErNJO3Zr_LMVw@mail.gmail.com>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <20160505224240.GA31429@rob-hp-laptop>
 <CAPDyKFqpoi03Egfuvd8qJXnn_+FBgPXAb7S4UvkxVs8BA+zwnA@mail.gmail.com>
 <20160509181829.GA19687@rob-hp-laptop>
 <CAPDyKFq2=mqujFjvJSYxg2nVmK=OrBKLtFfb-ErNJO3Zr_LMVw@mail.gmail.com>
Message-ID: <20160528033613.GA3291@shlinux2>

On Tue, May 10, 2016 at 01:02:08PM +0200, Ulf Hansson wrote:
> + Arnd
> 
> [...]
> 
> >> >> Solution
> >> >> ========
> >> >> This is very similar to the MMC pwrseq behavior so the idea is to:
> >> >> 1. Move MMC pwrseq drivers to generic place,
> >> >
> >> > You can do that, but I'm going to NAK any use of pwrseq bindings outside
> >> > of MMC. I think it is the wrong way to do things. The DT should describe
> >>
> >> Huh, I didn't know that was your view of the mmc pwrseq bindings. Why
> >> didn't you NAK them before?
> >
> > Unfortunately, either I missed it or it was a time I couldn't spend much
> > time on reviews.
> 
> Okay, I guess it's common issue among maintainers. The problem with DT
> is that it gets really hard to be fixed up later. :-)
> 
> >
> >> > the devices. If they happen to be "simple" then the core can walk the
> >> > tree and do any setup. For example, look for "reset-gpios" and toggle
> >> > that GPIO. There is no need for a special node.
> >> >
> >> >> 2. Extend the pwrseq-simple with regulator toggling,
> >> >> 3. Add support to USB hub and port core for pwrseq,
> >> >
> >> > We discussed this for USB already[1] and is why we defined how to add
> >> > USB child devices. The idea is not to add pwrseq to that.
> >>
> >> I am not familiar with the USB discussion.
> >>
> >> Still, let me give you some more background to the mmc pwrseq. The
> >> idea from the mmc pwrseq bindings comes from the power-domain DT
> >> bindings, as I thought these things were a bit related.
> >> In both cases they are not directly a property of the device, but more
> >> describing a HW dependency to allow the device to work.
> >
> > I could see this as a board level power domain. However the difference
> > is we are not generally exposing internal SOC details the same way as
> > board level components. Perhaps we could extend power domains to board
> > level, but that is not what was done here.
> >
> >> One could probably use a child node instead of a phandle, but that
> >> wasn't chosen back then. Of course you are the DT expert, but could
> >> you perhaps tell me why a child node is better for cases like this?
> >
> > If there is a control path hierarchy, then we try to model that in DT
> > with child nodes. In cases of SDIO and USB, there is a clear hierarchy.
> > Ignoring the discovery ordering problem, we already have defined ways to
> > describe GPIO connections, regulators, etc. to devices. Describing those
> > things separately from the device to solve a particular issue that is
> > really a kernel limitation is what I don't like.
> 
> Okay, I see.
> 
> To move forward in trying to make mmc pwrseq a generic pwrseq, could
> we perhaps allow both cases?
> 
> In the mmc case, there are already deployed bindings so we need to
> cope with these by using the phandle option, but for USB etc we could
> force the child node option.
> As long as we agree that we keep using a compatible string for the
> child node as well, both options should be able to co-exist and we
> should probably be able to managed them both from a common pwrseq
> driver framework.
> 
> Although, I do remember from an older conversations around some of
> mine submission for the mmc pwrseq code, that some people (maybe
> Arnd?) wasn't keen on adding a new framework for this. Perhaps that
> has changed?
> 

All, how we move on for this?

1. Using a generic driver to manage both mmc and USB (and further
subsystem), USB and further subsystem do not use pwrseq node in dts.
2. USB creates the similar driver under drivers/usb for its own use. 

Which one do you prefer, thanks.

-- 

Best Regards,
Peter Chen


From robert.jarzmik at free.fr  Sat May 28 01:24:27 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Sat, 28 May 2016 10:24:27 +0200
Subject: pxa_defconfig runtime failures due to 'ARM: pxa: activate pinctrl
 for device-tree machines'
In-Reply-To: <20160527202715.GA4841@roeck-us.net> (Guenter Roeck's message of
 "Fri, 27 May 2016 13:27:15 -0700")
References: <20160527202715.GA4841@roeck-us.net>
Message-ID: <87a8jah9ok.fsf@belgarion.home>

Guenter Roeck <linux at roeck-us.net> writes:

> Hi,
>
> your mainline commit f806dac5938b ("ARM: pxa: activate pinctrl for device-tree
> machines") causes various non-devicetree systems to fail with the following
> error messages when running a pxa_defconfig image.
Ah yes, you're right.

>
> During boot:
>
> Can't request reset_gpio
>
> At reboot:
>
> reboot: Restarting system
> ------------[ cut here ]------------
> kernel BUG at arch/arm/mach-pxa/reset.c:59!
> ...
>
> Added logging shows that the error seen when trying to request the reset gpio
> is -EPROBE_DEFER, and that the pxa gpio driver is not instantiated.
>
> This is seen when attempting to run akita, borzoi, spitz, terrier, or tosa
> in qemu with pxa_defconfig. Reverting your patch fixes the problem.
>
> Is this on purpose ?
Well no :)
The real reason behind is that gpio handling for pxa in its current state cannot
be built for _both_ a devicetree machine (ie. pxa-dt.c) and a non devicetree
machine (ie. corgi, tosa, ...).

This is turn is because for devicetree a pinctrl is enforced for the machine,
and a pinctrl driver is required. If it's not available, pxa_gpio_request()
fails on pinctrl_request_gpio() and returns -EPROBE_DEFER.

Now the true chicken and egg problem is than machine files,
ie. arch/arm/mach-pxa/xxx.c are using gpio before the drivers are probed, in the
init_machine() function, and that's why pinctrl/gpio for legacy machine files is
a bit difficult.

> Unless I am missing something, it effectively means that
> pxa_defconfig no longer works for pxa3xx systems, since those do not support
> devicetree (or at least there is no devicetree file which includes
> pxa3xx.dtsi).
I'd rather say that pxa_defconfig doesn't work anymore on any legacy system.
Its first purpose was to ensure compilation coverage of all legacy pxa systems.
Its second one was to have a single kernel bootable on all legacy pxa systems.

Therefore, would you tell me if the patch in [1] fixes your issue ?

Cheers.

-- 
Robert

[1] One solution
---8<---
>From d6079c9cce351e217df947b4c5e243d350c39823 Mon Sep 17 00:00:00 2001
From: Robert Jarzmik <robert.jarzmik at free.fr>
Date: Sat, 28 May 2016 10:17:33 +0200
Subject: [PATCH] ARM: pxa: remove devicetree boards from pxa_defconfig

If both legacy and device-tree machines are mixed in the same defconfig,
the legacy boards don't boot up anymore with gpio request deferral
errors.

This is seen when attempting to run akita, borzoi, spitz, terrier, or
tosa in qemu with pxa_defconfig.

The real reason behind is that gpio handling for pxa in its current state cannot
be built for _both_ a devicetree machine (ie. pxa-dt.c) and a non devicetree
machine (ie. corgi, tosa, ...).

This is turn is because for devicetree a pinctrl is enforced for the
machine, and a pinctrl driver is required. If it's not available,
pxa_gpio_request() fails on pinctrl_request_gpio() and returns
-EPROBE_DEFER.  It was introduced by commit :
    f806dac5938b ("ARM: pxa: activate pinctrl for device-tree machines")

Now the true chicken and egg problem is than machine files,
ie. arch/arm/mach-pxa/xxx.c are using gpio before the drivers are probed, in the
init_machine() function, and that's why pinctrl/gpio for legacy machine files is
a bit difficult.

As for now, to keep the compilation coverage and testing of legacy
machines, this patch removes the 2 devicetree machines from pxa_defconfig.

Reported-by: Guenter Roeck <linux at roeck-us.net>
Signed-off-by: Robert Jarzmik <robert.jarzmik at free.fr>
---
 arch/arm/configs/pxa_defconfig | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig
index dc5517eaf09f..a016ecc0084b 100644
--- a/arch/arm/configs/pxa_defconfig
+++ b/arch/arm/configs/pxa_defconfig
@@ -26,8 +26,6 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_LDM_PARTITION=y
 CONFIG_CMDLINE_PARTITION=y
 CONFIG_ARCH_PXA=y
-CONFIG_MACH_PXA27X_DT=y
-CONFIG_MACH_PXA3XX_DT=y
 CONFIG_ARCH_LUBBOCK=y
 CONFIG_MACH_MAINSTONE=y
 CONFIG_MACH_ZYLONITE300=y
-- 
2.1.4



From thunder.leizhen at huawei.com  Sat May 28 02:22:57 2016
From: thunder.leizhen at huawei.com (Zhen Lei)
Date: Sat, 28 May 2016 17:22:57 +0800
Subject: [PATCH v2 5/5] arm64/numa: avoid inconsistent information to be
 printed
In-Reply-To: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
References: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
Message-ID: <1464427377-12712-6-git-send-email-thunder.leizhen@huawei.com>

numa_init(of_numa_init) may returned error because of numa configuration
error. So "No NUMA configuration found" is inaccurate. In fact, specific
configuration error information should be immediately printed by the
testing branch.

Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
---
 arch/arm64/mm/numa.c | 6 +++---
 drivers/of/of_numa.c | 7 +++----
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
index 2601660..1b9622c 100644
--- a/arch/arm64/mm/numa.c
+++ b/arch/arm64/mm/numa.c
@@ -338,8 +338,10 @@ static int __init numa_init(int (*init_func)(void))
 	if (ret < 0)
 		return ret;

-	if (nodes_empty(numa_nodes_parsed))
+	if (nodes_empty(numa_nodes_parsed)) {
+		pr_info("No NUMA configuration found\n");
 		return -EINVAL;
+	}

 	ret = numa_register_nodes();
 	if (ret < 0)
@@ -370,8 +372,6 @@ static int __init dummy_numa_init(void)

 	if (numa_off)
 		pr_info("NUMA disabled\n"); /* Forced off on command line. */
-	else
-		pr_info("No NUMA configuration found\n");
 	pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
 	       0LLU, PFN_PHYS(max_pfn) - 1);

diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
index fb62307..3157130 100644
--- a/drivers/of/of_numa.c
+++ b/drivers/of/of_numa.c
@@ -63,7 +63,7 @@ static int __init of_numa_parse_memory_nodes(void)
 	struct device_node *np = NULL;
 	struct resource rsrc;
 	u32 nid;
-	int i, r = 0;
+	int i, r;

 	for_each_node_by_type(np, "memory") {
 		r = of_property_read_u32(np, "numa-node-id", &nid);
@@ -81,12 +81,11 @@ static int __init of_numa_parse_memory_nodes(void)
 		if (!i || r) {
 			of_node_put(np);
 			pr_err("NUMA: bad property in memory node\n");
-			r = r ? : -EINVAL;
-			break;
+			return r ? : -EINVAL;
 		}
 	}

-	return r;
+	return 0;
 }

 static int __init of_numa_parse_distance_map_v1(struct device_node *map)
--
2.5.0




From thunder.leizhen at huawei.com  Sat May 28 02:22:55 2016
From: thunder.leizhen at huawei.com (Zhen Lei)
Date: Sat, 28 May 2016 17:22:55 +0800
Subject: [PATCH v2 3/5] arm64/numa: add nid check for memory block
In-Reply-To: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
References: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
Message-ID: <1464427377-12712-4-git-send-email-thunder.leizhen@huawei.com>

Use the same tactic to cpu and numa-distance nodes.

Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
---
 arch/arm64/mm/numa.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
index c7fe3ec..2601660 100644
--- a/arch/arm64/mm/numa.c
+++ b/arch/arm64/mm/numa.c
@@ -141,6 +141,11 @@ int __init numa_add_memblk(int nid, u64 start, u64 end)
 {
 	int ret;

+	if (nid >= MAX_NUMNODES) {
+		pr_warn("NUMA: Node id %u exceeds maximum value\n", nid);
+		return -EINVAL;
+	}
+
 	ret = memblock_set_node(start, (end - start), &memblock.memory, nid);
 	if (ret < 0) {
 		pr_err("NUMA: memblock [0x%llx - 0x%llx] failed to add on node %d\n",
--
2.5.0




From thunder.leizhen at huawei.com  Sat May 28 02:22:54 2016
From: thunder.leizhen at huawei.com (Zhen Lei)
Date: Sat, 28 May 2016 17:22:54 +0800
Subject: [PATCH v2 2/5] of/numa: fix a memory@ node can only contains one
 memory block
In-Reply-To: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
References: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
Message-ID: <1464427377-12712-3-git-send-email-thunder.leizhen@huawei.com>

For a normal memory@ devicetree node, its reg property can contains more
memory blocks.

Because we don't known how many memory blocks maybe contained, so we try
from index=0, increase 1 until error returned(the end).

Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
---
 drivers/of/of_numa.c | 26 +++++++++-----------------
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
index fb71b4e..fa85a51 100644
--- a/drivers/of/of_numa.c
+++ b/drivers/of/of_numa.c
@@ -63,13 +63,9 @@ static int __init of_numa_parse_memory_nodes(void)
 	struct device_node *np = NULL;
 	struct resource rsrc;
 	u32 nid;
-	int r = 0;
-
-	for (;;) {
-		np = of_find_node_by_type(np, "memory");
-		if (!np)
-			break;
+	int i, r = 0;

+	for_each_node_by_type(np, "memory") {
 		r = of_property_read_u32(np, "numa-node-id", &nid);
 		if (r == -EINVAL)
 			/*
@@ -78,21 +74,17 @@ static int __init of_numa_parse_memory_nodes(void)
 			 * "numa-node-id" property
 			 */
 			continue;
-		else if (r)
-			/* some other error */
-			break;

-		r = of_address_to_resource(np, 0, &rsrc);
-		if (r) {
-			pr_err("NUMA: bad reg property in memory node\n");
-			break;
-		}
+		for (i = 0; !r && !of_address_to_resource(np, i, &rsrc); i++)
+			r = numa_add_memblk(nid, rsrc.start, rsrc.end + 1);

-		r = numa_add_memblk(nid, rsrc.start, rsrc.end + 1);
-		if (r)
+		if (!i || r) {
+			of_node_put(np);
+			pr_err("NUMA: bad property in memory node\n");
+			r = r ? : -EINVAL;
 			break;
+		}
 	}
-	of_node_put(np);

 	return r;
 }
--
2.5.0




From thunder.leizhen at huawei.com  Sat May 28 02:22:56 2016
From: thunder.leizhen at huawei.com (Zhen Lei)
Date: Sat, 28 May 2016 17:22:56 +0800
Subject: [PATCH v2 4/5] of/numa: remove a duplicated warning
In-Reply-To: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
References: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
Message-ID: <1464427377-12712-5-git-send-email-thunder.leizhen@huawei.com>

This warning has been printed in of_numa_parse_cpu_nodes before.

Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
---
 drivers/of/of_numa.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
index fa85a51..fb62307 100644
--- a/drivers/of/of_numa.c
+++ b/drivers/of/of_numa.c
@@ -175,13 +175,8 @@ int of_node_to_nid(struct device_node *device)
 			np->name);
 	of_node_put(np);

-	if (!r) {
-		if (nid >= MAX_NUMNODES)
-			pr_warn("NUMA: Node id %u exceeds maximum value\n",
-				nid);
-		else
-			return nid;
-	}
+	if (!r)
+		return nid;

 	return NUMA_NO_NODE;
 }
--
2.5.0




From thunder.leizhen at huawei.com  Sat May 28 02:22:53 2016
From: thunder.leizhen at huawei.com (Zhen Lei)
Date: Sat, 28 May 2016 17:22:53 +0800
Subject: [PATCH v2 1/5] of/numa: remove a duplicated pr_debug information
In-Reply-To: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
References: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
Message-ID: <1464427377-12712-2-git-send-email-thunder.leizhen@huawei.com>

This information will be printed in the subfunction numa_add_memblk.
They are not the same, but very similar.

Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
---
 drivers/of/of_numa.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
index ed5a097..fb71b4e 100644
--- a/drivers/of/of_numa.c
+++ b/drivers/of/of_numa.c
@@ -88,10 +88,6 @@ static int __init of_numa_parse_memory_nodes(void)
 			break;
 		}

-		pr_debug("NUMA:  base = %llx len = %llx, node = %u\n",
-			 rsrc.start, rsrc.end - rsrc.start + 1, nid);
-
-
 		r = numa_add_memblk(nid, rsrc.start, rsrc.end + 1);
 		if (r)
 			break;
--
2.5.0




From thunder.leizhen at huawei.com  Sat May 28 02:22:52 2016
From: thunder.leizhen at huawei.com (Zhen Lei)
Date: Sat, 28 May 2016 17:22:52 +0800
Subject: [PATCH v2 0/5] fix some type infos and bugs for arm64/of numa
Message-ID: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>

v1 -> v2:
1. Base on https://lkml.org/lkml/2016/5/24/679
2. Rewrote of_numa_parse_memory_nodes according to Rob Herring's advice. So that it looks more clear.
3. Rewrote patch 5 because some scenes were not considered before.

Zhen Lei (5):
  of/numa: remove a duplicated pr_debug information
  of/numa: fix a memory@ node can only contains one memory block
  arm64/numa: add nid check for memory block
  of/numa: remove a duplicated warning
  arm64/numa: avoid inconsistent information to be printed

 arch/arm64/mm/numa.c | 11 ++++++++---
 drivers/of/of_numa.c | 42 ++++++++++++------------------------------
 2 files changed, 20 insertions(+), 33 deletions(-)

-- 
2.5.0




From wangkefeng.wang at huawei.com  Sat May 28 02:33:50 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Sat, 28 May 2016 17:33:50 +0800
Subject: [PATCH 1/4] clocksource: sp804: cleanup clk_get_sys()
In-Reply-To: <1464428033-52106-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464428033-52106-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464428033-52106-2-git-send-email-wangkefeng.wang@huawei.com>

Move the clk_get_sys() part into sp804_get_clock_rate(), cleanup the same code.

Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/clocksource/timer-sp804.c | 34 +++++++++++-----------------------
 1 file changed, 11 insertions(+), 23 deletions(-)

diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
index 5f45b9a..362e5d0 100644
--- a/drivers/clocksource/timer-sp804.c
+++ b/drivers/clocksource/timer-sp804.c
@@ -34,11 +34,19 @@
 
 #include "timer-sp.h"
 
-static long __init sp804_get_clock_rate(struct clk *clk)
+static long __init sp804_get_clock_rate(struct clk *clk, const char *name)
 {
 	long rate;
 	int err;
 
+	if (!clk) {
+		clk = clk_get_sys("sp804", name);
+		if (IS_ERR(clk)) {
+			pr_err("sp804: clock not found: %ld\n", PTR_ERR(clk));
+			return PTR_ERR(clk);
+		}
+	}
+
 	err = clk_prepare(clk);
 	if (err) {
 		pr_err("sp804: clock failed to prepare: %d\n", err);
@@ -82,18 +90,7 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
 						     struct clk *clk,
 						     int use_sched_clock)
 {
-	long rate;
-
-	if (!clk) {
-		clk = clk_get_sys("sp804", name);
-		if (IS_ERR(clk)) {
-			pr_err("sp804: clock not found: %d\n",
-			       (int)PTR_ERR(clk));
-			return;
-		}
-	}
-
-	rate = sp804_get_clock_rate(clk);
+	long rate = sp804_get_clock_rate(clk, name);
 
 	if (rate < 0)
 		return;
@@ -189,17 +186,8 @@ static struct irqaction sp804_timer_irq = {
 void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name)
 {
 	struct clock_event_device *evt = &sp804_clockevent;
-	long rate;
-
-	if (!clk)
-		clk = clk_get_sys("sp804", name);
-	if (IS_ERR(clk)) {
-		pr_err("sp804: %s clock not found: %d\n", name,
-			(int)PTR_ERR(clk));
-		return;
-	}
+	long rate = sp804_get_clock_rate(clk, name);
 
-	rate = sp804_get_clock_rate(clk);
 	if (rate < 0)
 		return;
 
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Sat May 28 02:33:51 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Sat, 28 May 2016 17:33:51 +0800
Subject: [PATCH 2/4] clocksource: sp804: introduce helper sp804_load_mode_set()
In-Reply-To: <1464428033-52106-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464428033-52106-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464428033-52106-3-git-send-email-wangkefeng.wang@huawei.com>

Introduce helper sp804_load_mode_set(), and use it, prepare for 64bit
mode timer support.

Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/clocksource/timer-sp804.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
index 362e5d0..b8848e5 100644
--- a/drivers/clocksource/timer-sp804.c
+++ b/drivers/clocksource/timer-sp804.c
@@ -73,6 +73,15 @@ static long __init sp804_get_clock_rate(struct clk *clk, const char *name)
 	return rate;
 }
 
+static inline void sp804_load_mode_set(void __iomem *base, unsigned long load, int mode)
+{
+	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
+			     mode | TIMER_CTRL_ENABLE;
+
+	writel(load, base + TIMER_LOAD);
+	writel(ctrl, base + TIMER_CTRL);
+}
+
 static void __iomem *sched_clock_base;
 
 static u64 notrace sp804_read(void)
@@ -97,10 +106,8 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
 
 	/* setup timer 0 as free-running clocksource */
 	writel(0, base + TIMER_CTRL);
-	writel(0xffffffff, base + TIMER_LOAD);
 	writel(0xffffffff, base + TIMER_VALUE);
-	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
-		base + TIMER_CTRL);
+	sp804_load_mode_set(base, 0xffffffff, TIMER_CTRL_PERIODIC & ~TIMER_CTRL_IE);
 
 	clocksource_mmio_init(base + TIMER_VALUE, name,
 		rate, 200, 32, clocksource_mmio_readl_down);
@@ -143,24 +150,16 @@ static int sp804_shutdown(struct clock_event_device *evt)
 
 static int sp804_set_periodic(struct clock_event_device *evt)
 {
-	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
-			     TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
-
 	timer_shutdown(evt);
-	writel(clkevt_reload, clkevt_base + TIMER_LOAD);
-	writel(ctrl, clkevt_base + TIMER_CTRL);
+	sp804_load_mode_set(clkevt_base, clkevt_reload, TIMER_CTRL_PERIODIC);
 	return 0;
 }
 
 static int sp804_set_next_event(unsigned long next,
-	struct clock_event_device *evt)
+				struct clock_event_device *evt)
 {
-	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
-			     TIMER_CTRL_ONESHOT | TIMER_CTRL_ENABLE;
-
-	writel(next, clkevt_base + TIMER_LOAD);
-	writel(ctrl, clkevt_base + TIMER_CTRL);
 
+	sp804_load_mode_set(clkevt_base, next, TIMER_CTRL_ONESHOT);
 	return 0;
 }
 
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Sat May 28 02:33:53 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Sat, 28 May 2016 17:33:53 +0800
Subject: [PATCH 4/4] clocksource: sp804: support 64bit mode for hisilicon
 timer64
In-Reply-To: <1464428033-52106-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464428033-52106-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464428033-52106-5-git-send-email-wangkefeng.wang@huawei.com>

There is a kind of 64bit mode timer in hisilicon soc(like Hip05, Hip06 and
some arm32 soc), it is very similar with ARM sp804 Dual Timers, but TimerX
LOAD/Value/BGLoad are 64bit(two 32bit regs), and reg offset is different.

Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 .../devicetree/bindings/timer/arm,sp804.txt        |  1 +
 drivers/clocksource/timer-sp.h                     |  1 +
 drivers/clocksource/timer-sp804.c                  | 76 ++++++++++++++++++----
 3 files changed, 66 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt b/Documentation/devicetree/bindings/timer/arm,sp804.txt
index 5cd8eee7..d8e8f8f 100644
--- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
+++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
@@ -17,6 +17,7 @@ Optional properties:
 - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line connected, this
 	specifies if the irq connection is for timer 1 or timer 2. A value of 1
 	or 2 should be used.
+- hisilicon,timer64: Support hisilicon 64bit mode timer.
 
 Example:
 
diff --git a/drivers/clocksource/timer-sp.h b/drivers/clocksource/timer-sp.h
index 050d885..adf82f4 100644
--- a/drivers/clocksource/timer-sp.h
+++ b/drivers/clocksource/timer-sp.h
@@ -16,6 +16,7 @@
 #define TIMER_VALUE	0x04			/* ACVR ro */
 #define TIMER_CTRL	0x08			/* ACVR rw */
 #define TIMER_CTRL_ONESHOT	(1 << 0)	/*  CVR */
+/* Used in hisilicon timer64, it means enabling 64bit mode */
 #define TIMER_CTRL_32BIT	(1 << 1)	/*  CVR */
 #define TIMER_CTRL_DIV1		(0 << 2)	/* ACVR */
 #define TIMER_CTRL_DIV16	(1 << 2)	/* ACVR */
diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
index 2ff8777..7f1d947 100644
--- a/drivers/clocksource/timer-sp804.c
+++ b/drivers/clocksource/timer-sp804.c
@@ -34,6 +34,16 @@
 
 #include "timer-sp.h"
 
+#define TIMER64_2_BASE	0x40
+#define TIMER64_LOAD_L	0x00
+#define TIMER64_LOAD_H	0x04
+#define TIMER64_VALUE_L	0x08
+#define TIMER64_VALUE_H	0x0C
+
+#define HISI_OFFSET	0x8
+
+static int timer64_offset;
+
 static long __init sp804_get_clock_rate(struct clk *clk, const char *name)
 {
 	long rate;
@@ -78,8 +88,8 @@ static inline void sp804_load_mode_set(void __iomem *base, unsigned long load, i
 	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
 			     mode | TIMER_CTRL_ENABLE;
 
-	writel(load, base + TIMER_LOAD);
-	writel(ctrl, base + TIMER_CTRL);
+	writel(load, base + TIMER_LOAD); /* equal TIMER64_LOAD_L when timer64*/
+	writel(ctrl, base + TIMER_CTRL + timer64_offset);
 }
 
 static void __iomem *sched_clock_base;
@@ -89,11 +99,37 @@ static u64 notrace sp804_read(void)
 	return ~readl_relaxed(sched_clock_base + TIMER_VALUE);
 }
 
+static u64 notrace hisi_timer64_read(void)
+{
+	u32 val_lo, val_hi, tmp_hi;
+
+	do {
+		val_hi = readl_relaxed(sched_clock_base + TIMER64_VALUE_H);
+		val_lo = readl_relaxed(sched_clock_base + TIMER64_VALUE_L);
+		tmp_hi = readl_relaxed(sched_clock_base + TIMER64_VALUE_H);
+	} while (val_hi != tmp_hi);
+
+	return ((u64) val_hi << 32) | val_lo;
+}
+
 void __init sp804_timer_disable(void __iomem *base)
 {
-	writel(0, base + TIMER_CTRL);
+	writel(0, base + TIMER_CTRL + timer64_offset);
 }
 
+static cycle_t hisi_clocksource_read(struct clocksource *cs)
+{
+	return hisi_timer64_read();
+}
+
+static struct clocksource hisi_clocksource = {
+	.name	= "hisilicon_timer64",
+	.rating	= 200,
+	.read	= hisi_clocksource_read,
+	.mask	= CLOCKSOURCE_MASK(64),
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
 void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
 						     const char *name,
 						     struct clk *clk,
@@ -106,15 +142,25 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
 
 	/* setup timer 0 as free-running clocksource */
 	sp804_timer_disable(base);
-	writel(0xffffffff, base + TIMER_VALUE);
+	writel(0xffffffff, base + TIMER_VALUE); /* equal TIMER64_LOAD_H when tiemr64*/
+	if (timer64_offset) {
+		writel(0xffffffff, base + TIMER64_VALUE_L);
+		writel(0xffffffff, base + TIMER64_VALUE_H);
+	}
 	sp804_load_mode_set(base, 0xffffffff, TIMER_CTRL_PERIODIC & ~TIMER_CTRL_IE);
 
-	clocksource_mmio_init(base + TIMER_VALUE, name,
-		rate, 200, 32, clocksource_mmio_readl_down);
+	if (timer64_offset)
+		clocksource_register_hz(&hisi_clocksource, rate);
+	else
+		clocksource_mmio_init(base + TIMER_VALUE, name, rate, 200, 32,
+				      clocksource_mmio_readl_down);
 
 	if (use_sched_clock) {
 		sched_clock_base = base;
-		sched_clock_register(sp804_read, 32, rate);
+		if (timer64_offset)
+			sched_clock_register(hisi_timer64_read, 64, rate);
+		else
+			sched_clock_register(sp804_read, 32, rate);
 	}
 }
 
@@ -130,7 +176,7 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id)
 	struct clock_event_device *evt = dev_id;
 
 	/* clear the interrupt */
-	writel(1, clkevt_base + TIMER_INTCLR);
+	writel(1, clkevt_base + TIMER_INTCLR + timer64_offset);
 
 	evt->event_handler(evt);
 
@@ -139,7 +185,7 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id)
 
 static inline void timer_shutdown(struct clock_event_device *evt)
 {
-	writel(0, clkevt_base + TIMER_CTRL);
+	writel(0, clkevt_base + TIMER_CTRL + timer64_offset);
 }
 
 static int sp804_shutdown(struct clock_event_device *evt)
@@ -204,6 +250,7 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc
 static void __init sp804_of_init(struct device_node *np)
 {
 	static bool initialized = false;
+	int timer_2_base = TIMER_2_BASE;
 	void __iomem *base;
 	int irq;
 	u32 irq_num = 0;
@@ -214,9 +261,14 @@ static void __init sp804_of_init(struct device_node *np)
 	if (WARN_ON(!base))
 		return;
 
+	if (of_property_read_bool(np, "hisilicon,timer64")) {
+		timer64_offset = HISI_OFFSET;
+		timer_2_base = TIMER64_2_BASE;
+	}
+
 	/* Ensure timers are disabled */
 	sp804_timer_disable(base);
-	sp804_timer_disable(base + TIMER_2_BASE);
+	sp804_timer_disable(base + timer_2_base);
 
 	if (initialized || !of_device_is_available(np))
 		goto err;
@@ -242,11 +294,11 @@ static void __init sp804_of_init(struct device_node *np)
 
 	of_property_read_u32(np, "arm,sp804-has-irq", &irq_num);
 	if (irq_num == 2) {
-		__sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name);
+		__sp804_clockevents_init(base + timer_2_base, irq, clk2, name);
 		__sp804_clocksource_and_sched_clock_init(base, name, clk1, 1);
 	} else {
 		__sp804_clockevents_init(base, irq, clk1 , name);
-		__sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE,
+		__sp804_clocksource_and_sched_clock_init(base + timer_2_base,
 							 name, clk2, 1);
 	}
 	initialized = true;
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Sat May 28 02:33:49 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Sat, 28 May 2016 17:33:49 +0800
Subject: [PATCH 0/4] Support hisilicon 64bit mode timer  
Message-ID: <1464428033-52106-1-git-send-email-wangkefeng.wang@huawei.com>

There is a kind of 64bit mode timer in hisilicon soc(like Hip05, Hip06 and
some arm32 soc), it is very similar with ARM sp804 Dual Timers, but TimerX
LOAD/Value/BGLoad are 64bit(two 32bit regs), and reg offset is different.

This patchset make some cleanup and enable 64bit mode timer for hisilicon.

Kefeng Wang (4):
  clocksource: sp804: cleanup clk_get_sys()
  clocksource: sp804: introduce helper sp804_load_mode_set()
  clocksource: sp804: use sp804_timer_disable() where possible
  clocksource: sp804: support 64bit mode for hisilicon timer64

 .../devicetree/bindings/timer/arm,sp804.txt        |   1 +
 drivers/clocksource/timer-sp.h                     |   1 +
 drivers/clocksource/timer-sp804.c                  | 142 +++++++++++++--------
 3 files changed, 92 insertions(+), 52 deletions(-)

-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Sat May 28 02:33:52 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Sat, 28 May 2016 17:33:52 +0800
Subject: [PATCH 3/4] clocksource: sp804: use sp804_timer_disable() where
 possible
In-Reply-To: <1464428033-52106-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464428033-52106-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464428033-52106-4-git-send-email-wangkefeng.wang@huawei.com>

Use sp804_timer_disable() where possible, prepare for 64bit mode timer support.

Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/clocksource/timer-sp804.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
index b8848e5..2ff8777 100644
--- a/drivers/clocksource/timer-sp804.c
+++ b/drivers/clocksource/timer-sp804.c
@@ -105,7 +105,7 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
 		return;
 
 	/* setup timer 0 as free-running clocksource */
-	writel(0, base + TIMER_CTRL);
+	sp804_timer_disable(base);
 	writel(0xffffffff, base + TIMER_VALUE);
 	sp804_load_mode_set(base, 0xffffffff, TIMER_CTRL_PERIODIC & ~TIMER_CTRL_IE);
 
@@ -196,8 +196,7 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc
 	evt->irq = irq;
 	evt->cpumask = cpu_possible_mask;
 
-	writel(0, base + TIMER_CTRL);
-
+	sp804_timer_disable(base);
 	setup_irq(irq, &sp804_timer_irq);
 	clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
 }
@@ -216,8 +215,8 @@ static void __init sp804_of_init(struct device_node *np)
 		return;
 
 	/* Ensure timers are disabled */
-	writel(0, base + TIMER_CTRL);
-	writel(0, base + TIMER_2_BASE + TIMER_CTRL);
+	sp804_timer_disable(base);
+	sp804_timer_disable(base + TIMER_2_BASE);
 
 	if (initialized || !of_device_is_available(np))
 		goto err;
@@ -274,7 +273,7 @@ static void __init integrator_cp_of_init(struct device_node *np)
 		return;
 
 	/* Ensure timer is disabled */
-	writel(0, base + TIMER_CTRL);
+	sp804_timer_disable(base);
 
 	if (init_count == 2 || !of_device_is_available(np))
 		goto err;
-- 
1.7.12.4



From krzk at kernel.org  Sat May 28 02:54:12 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:12 +0200
Subject: [PATCH v5 01/22] dt-bindings: clock: Add license and reformat
 Exynos5410 clock IDs
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-2-git-send-email-krzk@kernel.org>

Add license and copyrights (file introduced in 2014) to header with
Exynos5410 clock IDs. Additionally reformat it to improve readability.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 include/dt-bindings/clock/exynos5410.h | 54 ++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 9b180f032e2d..213f19e02870 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -1,33 +1,43 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics 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.
+ *
+ * Device Tree binding constants for Exynos5421 clock controller.
+*/
+
 #ifndef _DT_BINDINGS_CLOCK_EXYNOS_5410_H
 #define _DT_BINDINGS_CLOCK_EXYNOS_5410_H
 
 /* core clocks */
-#define CLK_FIN_PLL 1
-#define CLK_FOUT_APLL 2
-#define CLK_FOUT_CPLL 3
-#define CLK_FOUT_MPLL 4
-#define CLK_FOUT_BPLL 5
-#define CLK_FOUT_KPLL 6
+#define CLK_FIN_PLL		1
+#define CLK_FOUT_APLL		2
+#define CLK_FOUT_CPLL		3
+#define CLK_FOUT_MPLL		4
+#define CLK_FOUT_BPLL		5
+#define CLK_FOUT_KPLL		6
 
 /* gate for special clocks (sclk) */
-#define CLK_SCLK_UART0 128
-#define CLK_SCLK_UART1 129
-#define CLK_SCLK_UART2 130
-#define CLK_SCLK_UART3 131
-#define CLK_SCLK_MMC0 132
-#define CLK_SCLK_MMC1 133
-#define CLK_SCLK_MMC2 134
+#define CLK_SCLK_UART0		128
+#define CLK_SCLK_UART1		129
+#define CLK_SCLK_UART2		130
+#define CLK_SCLK_UART3		131
+#define CLK_SCLK_MMC0		132
+#define CLK_SCLK_MMC1		133
+#define CLK_SCLK_MMC2		134
 
 /* gate clocks */
-#define CLK_UART0 257
-#define CLK_UART1 258
-#define CLK_UART2 259
-#define CLK_UART3 260
-#define CLK_MCT 315
-#define CLK_MMC0 351
-#define CLK_MMC1 352
-#define CLK_MMC2 353
+#define CLK_UART0		257
+#define CLK_UART1		258
+#define CLK_UART2		259
+#define CLK_UART3		260
+#define CLK_MCT			315
+#define CLK_MMC0		351
+#define CLK_MMC1		352
+#define CLK_MMC2		353
 
-#define CLK_NR_CLKS 512
+#define CLK_NR_CLKS		512
 
 #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5410_H */
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:11 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:11 +0200
Subject: [PATCH v5 00/22] ARM: dts: exynos: Add initial support for Odroid XU
Message-ID: <1464429273-23457-1-git-send-email-krzk@kernel.org>

Hi,

Patchset adds necessary clocks, reorganizes existing stuff and finally
adds Odroid XU support.


Changes since v4
================
1. Patch 20: Remove the nodes in exynos5420.dtsi (before they were
   actually just copied instead of moving).

Changes since v3
================
1. Get rid of 5 patches changing the fin_pll after talk with Tomasz
   Figa. The existing definition of oscillator in exynos5410.dtsi
   is preferred over solution chosen for Exynos5420.
   This simplifies also the merging strategy.
2. Add tags from Javier (tested and reviewed).

Patchset is available at my private repo @github:
https://github.com/krzk/linux.git for-next/odroid-xu-v4
(I have some more changes coming but I think it is easier for
reviewers if the patchset does not grow infinitely)


Changes since v2
================
1. Got global-ack from Stephen for the clock changes. I think merging
   everything through arm-soc might be the easiest but:
   a. In such case I will prepare a tag with clock changes,
   b. Anyway I will wait for response from Sylwester and Tomasz.
2. Applied comments from Javier and added his Reviewed-by.
3. Patch 22: added ack from Rob.
4. Minor improvements in existing patches.
5. Five new patches at the end: 23-27 (not reviewed yet).
   Some of them could be squashed with existing ones but existing
   changes got reviews. Although the final Odroid XU DTS works fine but
   in general this is still work-in-progress so I suspect it will grow.
   I am releasing it early following Linux concept. :)


Changes since v1
================
1. A lot of new patches.
2. Removed some TODO notes (eMMC 4.5 so no RCLK pin).
3. New clocks, more reorganization.
4. New common DTSI: exynos54xx.dtsi. I know, it is getting more
   and more complicated but this might help removing duplications
   and keeping everything under control.



Merging strategy
================
The clock changes can go to clock tree. ARM changes to samsung-soc tree.
Please provide me a tag with include/dt-bindings/clock commits so I can
merge it.


Best regards,
Krzysztof


Krzysztof Kozlowski (22):
  dt-bindings: clock: Add license and reformat Exynos5410 clock IDs
  dt-bindings: clock: Add PWM and USB clock IDs to Exynos5410
  clk: samsung: exynos5410: Add serial3, USB and PWM clocks
  ARM: dts: exynos: Re-order alphabetically Exynos5420 SD0/SD1 pinctrl
    nodes
  ARM: dts: exynos: Use lowercase for Exynos5410 CPU node labels
  ARM: dts: exynos: Configure Exynos5410 pinctrl for eMMC and SD card
  ARM: dts: exynos: Split Odroid XU3 LEDs to separate DTSI
  ARM: dts: exynos: Move common nodes to exynos5.dtsi
  ARM: dts: exynos: Prepare for inclusion of exynos5.dtsi in
    exynos5410.dtsi
  ARM: dts: exynos: Use phandle to get parent node in exynos5250-snow
  ARM: dts: exynos: Move Exynos5250 and Exynos5420 nodes under soc
  ARM: dts: exynos: Include common exynos5 in exynos5410.dtsi
  ARM: dts: exynos: Enable UART3 on Exynos5410
  ARM: dts: exynos: MCT is not an interrupt controller and extend length
    of iomap
  ARM: dts: exynos: Move common Exynos5410/542x/5800 nodes to new DTSI
  ARM: dts: exynos: Add USB to Exynos5410
  ARM: dts: exynos: Add initial support for Odroid XU board
  dt-bindings: clock: Add I2C, HSI2C and RTC clock IDs to Exynos5410
  clk: samsung: exynos5410: Add I2C, HSI2C and RTC clocks
  ARM: dts: exynos: Move HSI2C nodes to exynos54xx.dtsi
  ARM: dts: exynos: Add I2C, PWM and UART pinctrl to Exynos5410
  ARM: dts: exynos: Add RTC and I2C to Exynos5410

 .../bindings/arm/samsung/samsung-boards.txt        |    1 +
 arch/arm/boot/dts/Makefile                         |    1 +
 arch/arm/boot/dts/exynos5.dtsi                     |  215 ++-
 arch/arm/boot/dts/exynos5250-snow-common.dtsi      |    2 +-
 arch/arm/boot/dts/exynos5250.dtsi                  | 1701 +++++++++--------
 arch/arm/boot/dts/exynos5410-odroidxu.dts          |  121 ++
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi          |  210 +++
 arch/arm/boot/dts/exynos5410-smdk5410.dts          |    6 +-
 arch/arm/boot/dts/exynos5410.dtsi                  |  267 +--
 arch/arm/boot/dts/exynos5420-pinctrl.dtsi          |   12 +-
 arch/arm/boot/dts/exynos5420.dtsi                  | 1939 +++++++++-----------
 arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts    |   35 +-
 arch/arm/boot/dts/exynos5422-odroidxu3.dts         |   35 +-
 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi    |   50 +
 arch/arm/boot/dts/exynos54xx.dtsi                  |  188 ++
 drivers/clk/samsung/clk-exynos5410.c               |   45 +
 include/dt-bindings/clock/exynos5410.h             |   73 +-
 17 files changed, 2681 insertions(+), 2220 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos5410-odroidxu.dts
 create mode 100644 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
 create mode 100644 arch/arm/boot/dts/exynos54xx.dtsi

-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:13 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:13 +0200
Subject: [PATCH v5 02/22] dt-bindings: clock: Add PWM and USB clock IDs to
 Exynos5410
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-3-git-send-email-krzk@kernel.org>

Add IDs for PWM and USB clocks to Exynos5410. Use the same number as for
Exynos5420 just in case in future these drivers were merged.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 include/dt-bindings/clock/exynos5410.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 213f19e02870..34c8e96987a1 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 Krzysztof Kozlowski
  *
  * 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
@@ -27,16 +28,25 @@
 #define CLK_SCLK_MMC0		132
 #define CLK_SCLK_MMC1		133
 #define CLK_SCLK_MMC2		134
+#define CLK_SCLK_USBD300	150
+#define CLK_SCLK_USBD301	151
+#define CLK_SCLK_USBPHY300	152
+#define CLK_SCLK_USBPHY301	153
+#define CLK_SCLK_PWM		155
 
 /* gate clocks */
 #define CLK_UART0		257
 #define CLK_UART1		258
 #define CLK_UART2		259
 #define CLK_UART3		260
+#define CLK_PWM			279
 #define CLK_MCT			315
 #define CLK_MMC0		351
 #define CLK_MMC1		352
 #define CLK_MMC2		353
+#define CLK_USBH20		365
+#define CLK_USBD300		366
+#define CLK_USBD301		367
 
 #define CLK_NR_CLKS		512
 
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:14 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:14 +0200
Subject: [PATCH v5 03/22] clk: samsung: exynos5410: Add serial3,
 USB and PWM clocks
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-4-git-send-email-krzk@kernel.org>

Just like other Exynos5 family SoCs, this one has four UARTs. Add
missing UART3 clocks to the Exynos5410 clock driver.

Add clocks for USB and PWM.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Stephen Boyd <sboyd at codeaurora.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 drivers/clk/samsung/clk-exynos5410.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index d5d5dcabc4a9..5f892128849a 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -33,9 +33,11 @@
 #define SRC_CPERI1		0x4204
 #define DIV_TOP0		0x10510
 #define DIV_TOP1		0x10514
+#define DIV_FSYS0		0x10548
 #define DIV_FSYS1		0x1054c
 #define DIV_FSYS2		0x10550
 #define DIV_PERIC0		0x10558
+#define DIV_PERIC3		0x10564
 #define SRC_TOP0		0x10210
 #define SRC_TOP1		0x10214
 #define SRC_TOP2		0x10218
@@ -44,6 +46,8 @@
 #define SRC_MASK_FSYS		0x10340
 #define SRC_MASK_PERIC0		0x10350
 #define GATE_BUS_FSYS0		0x10740
+#define GATE_TOP_SCLK_FSYS	0x10840
+#define GATE_TOP_SCLK_PERIC	0x10850
 #define GATE_IP_FSYS		0x10944
 #define GATE_IP_PERIC		0x10950
 #define GATE_IP_PERIS		0x10960
@@ -71,6 +75,7 @@ PNAME(mout_kfc_p)	= { "mout_kpll", "sclk_mpll", };
 PNAME(mpll_user_p)	= { "fin_pll", "sclk_mpll", };
 PNAME(bpll_user_p)	= { "fin_pll", "sclk_bpll", };
 PNAME(mpll_bpll_p)	= { "sclk_mpll_muxed", "sclk_bpll_muxed", };
+PNAME(sclk_mpll_bpll_p)	= { "sclk_mpll_bpll", "fin_pll", };
 
 PNAME(group2_p)		= { "fin_pll", "fin_pll", "none", "none",
 			"none", "none", "sclk_mpll_bpll",
@@ -96,10 +101,14 @@ static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
 	MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4),
 	MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4),
 	MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4),
+	MUX(0, "mout_usbd300", sclk_mpll_bpll_p, SRC_FSYS, 28, 1),
+	MUX(0, "mout_usbd301", sclk_mpll_bpll_p, SRC_FSYS, 29, 1),
 
 	MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4),
 	MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4),
 	MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4),
+	MUX(0, "mout_uart3", group2_p, SRC_PERIC0, 12, 4),
+	MUX(0, "mout_pwm", group2_p, SRC_PERIC0, 24, 4),
 
 	MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1),
 	MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1),
@@ -121,6 +130,11 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 	DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3),
 	DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
 
+	DIV(0, "dout_usbphy300", "mout_usbd300", DIV_FSYS0, 16, 4),
+	DIV(0, "dout_usbphy301", "mout_usbd301", DIV_FSYS0, 20, 4),
+	DIV(0, "dout_usbd300", "mout_usbd300", DIV_FSYS0, 24, 4),
+	DIV(0, "dout_usbd301", "mout_usbd301", DIV_FSYS0, 28, 4),
+
 	DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
 	DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
 	DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
@@ -137,6 +151,8 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 	DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
 	DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
 
+	DIV(0, "dout_pwm", "mout_pwm", DIV_PERIC3, 0, 4),
+
 	DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
 	DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3),
 };
@@ -155,9 +171,23 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 	GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0),
 	GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0),
 
+	GATE(CLK_SCLK_USBPHY301, "sclk_usbphy301", "dout_usbphy301",
+	     GATE_TOP_SCLK_FSYS, 7, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_USBPHY300, "sclk_usbphy300", "dout_usbphy300",
+	     GATE_TOP_SCLK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_USBD300, "sclk_usbd300", "dout_usbd300",
+	     GATE_TOP_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_USBD301, "sclk_usbd301", "dout_usbd301",
+	     GATE_TOP_SCLK_FSYS, 10, CLK_SET_RATE_PARENT, 0),
+
+	GATE(CLK_SCLK_PWM, "sclk_pwm", "dout_pwm",
+	     GATE_TOP_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0),
+
 	GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
 	GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
 	GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
+	GATE(CLK_UART3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0),
+	GATE(CLK_PWM, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0),
 
 	GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
 			SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
@@ -165,6 +195,12 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 			SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
 			SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_UART3, "sclk_uart3", "div_uart3",
+			SRC_MASK_PERIC0, 12, CLK_SET_RATE_PARENT, 0),
+
+	GATE(CLK_USBH20, "usbh20", "aclk200_fsys", GATE_IP_FSYS, 18, 0, 0),
+	GATE(CLK_USBD300, "usbd300", "aclk200_fsys", GATE_IP_FSYS, 19, 0, 0),
+	GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_IP_FSYS, 20, 0, 0),
 };
 
 static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:15 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:15 +0200
Subject: [PATCH v5 04/22] ARM: dts: exynos: Re-order alphabetically Exynos5420
 SD0/SD1 pinctrl nodes
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-5-git-send-email-krzk@kernel.org>

The 'sd0_rclk' was put in the middle of SD1 nodes. Remove the confusion.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5420-pinctrl.dtsi | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
index 130563b2ca95..14beb7e07323 100644
--- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi
@@ -193,17 +193,17 @@
 		samsung,pin-drv = <3>;
 	};
 
-	sd1_clk: sd1-clk {
-		samsung,pins = "gpc1-0";
+	sd0_rclk: sd0-rclk {
+		samsung,pins = "gpc0-7";
 		samsung,pin-function = <2>;
-		samsung,pin-pud = <0>;
+		samsung,pin-pud = <1>;
 		samsung,pin-drv = <3>;
 	};
 
-	sd0_rclk: sd0-rclk {
-		samsung,pins = "gpc0-7";
+	sd1_clk: sd1-clk {
+		samsung,pins = "gpc1-0";
 		samsung,pin-function = <2>;
-		samsung,pin-pud = <1>;
+		samsung,pin-pud = <0>;
 		samsung,pin-drv = <3>;
 	};
 
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:16 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:16 +0200
Subject: [PATCH v5 05/22] ARM: dts: exynos: Use lowercase for Exynos5410 CPU
 node labels
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-6-git-send-email-krzk@kernel.org>

For consistency lowercase node labels are used.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 477c6741c6dd..ef60a06211f1 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -35,28 +35,28 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		CPU0: cpu at 0 {
+		cpu0: cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU1: cpu at 1 {
+		cpu1: cpu at 1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x1>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU2: cpu at 2 {
+		cpu2: cpu at 2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x2>;
 			clock-frequency = <1600000000>;
 		};
 
-		CPU3: cpu at 3 {
+		cpu3: cpu at 3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x3>;
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:17 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:17 +0200
Subject: [PATCH v5 06/22] ARM: dts: exynos: Configure Exynos5410 pinctrl for
 eMMC and SD card
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-7-git-send-email-krzk@kernel.org>

Configure the pinctrl for MMC0 (eMMC) and MMC2 (microSD card).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

Important changes since v2:
1. Re-order the eMMC pins by pin-name, not by label.
---
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 77 +++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
index f9aa6bb55464..ddacafa1e907 100644
--- a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
@@ -277,6 +277,83 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
+
+	sd0_clk: sd0-clk {
+		samsung,pins = "gpc0-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cmd: sd0-cmd {
+		samsung,pins = "gpc0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cd: sd0-cd {
+		samsung,pins = "gpc0-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus1: sd0-bus-width1 {
+		samsung,pins = "gpc0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus4: sd0-bus-width4 {
+		samsung,pins = "gpc0-4", "gpc0-5", "gpc0-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_clk: sd2-clk {
+		samsung,pins = "gpc2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cmd: sd2-cmd {
+		samsung,pins = "gpc2-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cd: sd2-cd {
+		samsung,pins = "gpc2-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus1: sd2-bus-width1 {
+		samsung,pins = "gpc2-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus4: sd2-bus-width4 {
+		samsung,pins = "gpc2-4", "gpc2-5", "gpc2-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus8: sd0-bus-width8 {
+		samsung,pins = "gpc3-0", "gpc3-1", "gpc3-2", "gpc3-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
 };
 
 &pinctrl_1 {
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:18 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:18 +0200
Subject: [PATCH v5 07/22] ARM: dts: exynos: Split Odroid XU3 LEDs to separate
 DTSI
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-8-git-send-email-krzk@kernel.org>

The LED nodes can be shared between Odroid XU3, XU3-Lite and XU (not yet
added) thus removing duplication.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts | 35 +----------------
 arch/arm/boot/dts/exynos5422-odroidxu3.dts      | 35 +----------------
 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi | 50 +++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 68 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi

diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
index 2ae1cf41dcb6..03fa88c45426 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
@@ -14,44 +14,11 @@
 /dts-v1/;
 #include "exynos5422-odroidxu3-common.dtsi"
 #include "exynos5422-odroidxu3-audio.dtsi"
+#include "exynos54xx-odroidxu-leds.dtsi"
 
 / {
 	model = "Hardkernel Odroid XU3 Lite";
 	compatible = "hardkernel,odroid-xu3-lite", "samsung,exynos5800", "samsung,exynos5";
-
-	pwmleds {
-		compatible = "pwm-leds";
-
-		greenled {
-			label = "green:mmc0";
-			pwms = <&pwm 1 2000000 0>;
-			pwm-names = "pwm1";
-			/*
-			 * Green LED is much brighter than the others
-			 * so limit its max brightness
-			 */
-			max_brightness = <127>;
-			linux,default-trigger = "mmc0";
-		};
-
-		blueled {
-			label = "blue:heartbeat";
-			pwms = <&pwm 2 2000000 0>;
-			pwm-names = "pwm2";
-			max_brightness = <255>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-
-	gpioleds {
-		compatible = "gpio-leds";
-		redled {
-			label = "red:microSD";
-			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
-			default-state = "off";
-			linux,default-trigger = "mmc1";
-		};
-	};
 };
 
 &pwm {
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
index 432406db85de..9ed6564acfb0 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
@@ -13,44 +13,11 @@
 /dts-v1/;
 #include "exynos5422-odroidxu3-common.dtsi"
 #include "exynos5422-odroidxu3-audio.dtsi"
+#include "exynos54xx-odroidxu-leds.dtsi"
 
 / {
 	model = "Hardkernel Odroid XU3";
 	compatible = "hardkernel,odroid-xu3", "samsung,exynos5800", "samsung,exynos5";
-
-	pwmleds {
-		compatible = "pwm-leds";
-
-		greenled {
-			label = "green:mmc0";
-			pwms = <&pwm 1 2000000 0>;
-			pwm-names = "pwm1";
-			/*
-			 * Green LED is much brighter than the others
-			 * so limit its max brightness
-			 */
-			max_brightness = <127>;
-			linux,default-trigger = "mmc0";
-		};
-
-		blueled {
-			label = "blue:heartbeat";
-			pwms = <&pwm 2 2000000 0>;
-			pwm-names = "pwm2";
-			max_brightness = <255>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-
-	gpioleds {
-		compatible = "gpio-leds";
-		redled {
-			label = "red:microSD";
-			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
-			default-state = "off";
-			linux,default-trigger = "mmc1";
-		};
-	};
 };
 
 &i2c_0 {
diff --git a/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi b/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
new file mode 100644
index 000000000000..0ed30206625c
--- /dev/null
+++ b/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
@@ -0,0 +1,50 @@
+/*
+ * Hardkernel Odroid XU/XU3 LED device tree source
+ *
+ * Copyright (c) 2015,2016 Krzysztof Kozlowski
+ * Copyright (c) 2014 Collabora Ltd.
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	pwmleds {
+		compatible = "pwm-leds";
+
+		greenled {
+			label = "green:mmc0";
+			pwms = <&pwm 1 2000000 0>;
+			pwm-names = "pwm1";
+			/*
+			 * Green LED is much brighter than the others
+			 * so limit its max brightness
+			 */
+			max_brightness = <127>;
+			linux,default-trigger = "mmc0";
+		};
+
+		blueled {
+			label = "blue:heartbeat";
+			pwms = <&pwm 2 2000000 0>;
+			pwm-names = "pwm2";
+			max_brightness = <255>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	gpioleds {
+		compatible = "gpio-leds";
+		redled {
+			label = "red:microSD";
+			gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "mmc1";
+		};
+	};
+};
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:20 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:20 +0200
Subject: [PATCH v5 09/22] ARM: dts: exynos: Prepare for inclusion of
 exynos5.dtsi in exynos5410.dtsi
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-10-git-send-email-krzk@kernel.org>

Add 'sromc' label to SROM memory controller in common exynos5.dtsi so it
can be referenced by inheriting DTSI.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index c5d198c70b86..30a0b63b06c9 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -35,7 +35,7 @@
 		reg = <0x10000000 0x100>;
 	};
 
-	memory-controller at 12250000 {
+	sromc: memory-controller at 12250000 {
 		compatible = "samsung,exynos4210-srom";
 		reg = <0x12250000 0x14>;
 	};
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:19 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:19 +0200
Subject: [PATCH v5 08/22] ARM: dts: exynos: Move common nodes to exynos5.dtsi
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-9-git-send-email-krzk@kernel.org>

Exynos5420 and Exynos5250 share some nodes: the PWM, syscon
(sysreg_system_controller) and first four I2C controllers. Move them to
parent DTSI to avoid duplication.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

Important changes since v2:
1. Move also i2c[0123] to exynos5.dtsi.
---
 arch/arm/boot/dts/exynos5.dtsi    |  56 ++++++++++++++++++++
 arch/arm/boot/dts/exynos5250.dtsi | 108 ++++++++++++--------------------------
 arch/arm/boot/dts/exynos5420.dtsi | 108 ++++++++++++--------------------------
 3 files changed, 124 insertions(+), 148 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index d5c0f18a4223..c5d198c70b86 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -20,6 +20,10 @@
 	interrupt-parent = <&gic>;
 
 	aliases {
+		i2c0 = &i2c_0;
+		i2c1 = &i2c_1;
+		i2c2 = &i2c_2;
+		i2c3 = &i2c_3;
 		serial0 = &serial_0;
 		serial1 = &serial_1;
 		serial2 = &serial_2;
@@ -63,6 +67,11 @@
 		interrupts = <1 9 0xf04>;
 	};
 
+	sysreg_system_controller: syscon at 10050000 {
+		compatible = "samsung,exynos5-sysreg", "syscon";
+		reg = <0x10050000 0x5000>;
+	};
+
 	serial_0: serial at 12C00000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x12C00000 0x100>;
@@ -87,6 +96,53 @@
 		interrupts = <0 54 0>;
 	};
 
+	i2c_0: i2c at 12C60000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C60000 0x100>;
+		interrupts = <0 56 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,sysreg-phandle = <&sysreg_system_controller>;
+		status = "disabled";
+	};
+
+	i2c_1: i2c at 12C70000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C70000 0x100>;
+		interrupts = <0 57 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,sysreg-phandle = <&sysreg_system_controller>;
+		status = "disabled";
+	};
+
+	i2c_2: i2c at 12C80000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C80000 0x100>;
+		interrupts = <0 58 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,sysreg-phandle = <&sysreg_system_controller>;
+		status = "disabled";
+	};
+
+	i2c_3: i2c at 12C90000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C90000 0x100>;
+		interrupts = <0 59 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		samsung,sysreg-phandle = <&sysreg_system_controller>;
+		status = "disabled";
+	};
+
+	pwm: pwm at 12DD0000 {
+		compatible = "samsung,exynos4210-pwm";
+		reg = <0x12DD0000 0x100>;
+		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
+		#pwm-cells = <3>;
+	};
+
 	rtc: rtc at 101E0000 {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x101E0000 0x100>;
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index c7158b2fb213..ae4970d1c74f 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -37,10 +37,6 @@
 		mshc1 = &mmc_1;
 		mshc2 = &mmc_2;
 		mshc3 = &mmc_3;
-		i2c0 = &i2c_0;
-		i2c1 = &i2c_1;
-		i2c2 = &i2c_2;
-		i2c3 = &i2c_3;
 		i2c4 = &i2c_4;
 		i2c5 = &i2c_5;
 		i2c6 = &i2c_6;
@@ -235,11 +231,6 @@
 		interrupt-parent = <&gic>;
 	};
 
-	sysreg_system_controller: syscon at 10050000 {
-		compatible = "samsung,exynos5-sysreg", "syscon";
-		reg = <0x10050000 0x5000>;
-	};
-
 	watchdog at 101D0000 {
 		compatible = "samsung,exynos5250-wdt";
 		reg = <0x101D0000 0x100>;
@@ -328,62 +319,7 @@
 		status = "disabled";
 	};
 
-	i2c_0: i2c at 12C60000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C60000 0x100>;
-		interrupts = <0 56 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C0>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c0_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_1: i2c at 12C70000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C70000 0x100>;
-		interrupts = <0 57 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C1>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c1_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_2: i2c at 12C80000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C80000 0x100>;
-		interrupts = <0 58 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C2>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c2_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_3: i2c at 12C90000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C90000 0x100>;
-		interrupts = <0 59 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C3>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c3_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
+	/* i2c_0-3 are defined in exynos5.dtsi */
 	i2c_4: i2c at 12CA0000 {
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x12CA0000 0x100>;
@@ -662,15 +598,6 @@
 		samsung,pmureg-phandle = <&pmu_system_controller>;
 	};
 
-	pwm: pwm at 12dd0000 {
-		compatible = "samsung,exynos4210-pwm";
-		reg = <0x12dd0000 0x100>;
-		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
-		#pwm-cells = <3>;
-		clocks = <&clock CLK_PWM>;
-		clock-names = "timers";
-	};
-
 	amba {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -1070,6 +997,39 @@
 	iommus = <&sysmmu_fimd1>;
 };
 
+&i2c_0 {
+	clocks = <&clock CLK_I2C0>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_bus>;
+};
+
+&i2c_1 {
+	clocks = <&clock CLK_I2C1>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_bus>;
+};
+
+&i2c_2 {
+	clocks = <&clock CLK_I2C2>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_bus>;
+};
+
+&i2c_3 {
+	clocks = <&clock CLK_I2C3>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_bus>;
+};
+
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
+
 &rtc {
 	clocks = <&clock CLK_RTC>;
 	clock-names = "rtc";
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 549ebf23fee0..f2e8e6482888 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -30,10 +30,6 @@
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
 		pinctrl4 = &pinctrl_4;
-		i2c0 = &i2c_0;
-		i2c1 = &i2c_1;
-		i2c2 = &i2c_2;
-		i2c3 = &i2c_3;
 		i2c4 = &hsi2c_4;
 		i2c5 = &hsi2c_5;
 		i2c6 = &hsi2c_6;
@@ -542,15 +538,6 @@
 		status = "disabled";
 	};
 
-	pwm: pwm at 12dd0000 {
-		compatible = "samsung,exynos4210-pwm";
-		reg = <0x12dd0000 0x100>;
-		samsung,pwm-outputs = <0>, <1>, <2>, <3>;
-		#pwm-cells = <3>;
-		clocks = <&clock CLK_PWM>;
-		clock-names = "timers";
-	};
-
 	dp_phy: dp-video-phy {
 		compatible = "samsung,exynos5420-dp-video-phy";
 		samsung,pmu-syscon = <&pmu_system_controller>;
@@ -588,62 +575,7 @@
 		status = "disabled";
 	};
 
-	i2c_0: i2c at 12C60000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C60000 0x100>;
-		interrupts = <0 56 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C0>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c0_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_1: i2c at 12C70000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C70000 0x100>;
-		interrupts = <0 57 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C1>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c1_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_2: i2c at 12C80000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C80000 0x100>;
-		interrupts = <0 58 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C2>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c2_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
-	i2c_3: i2c at 12C90000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x12C90000 0x100>;
-		interrupts = <0 59 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		clocks = <&clock CLK_I2C3>;
-		clock-names = "i2c";
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c3_bus>;
-		samsung,sysreg-phandle = <&sysreg_system_controller>;
-		status = "disabled";
-	};
-
+	/* i2c_0-3 are defined in exynos5.dtsi */
 	hsi2c_4: i2c at 12CA0000 {
 		compatible = "samsung,exynos5250-hsi2c";
 		reg = <0x12CA0000 0x1000>;
@@ -823,11 +755,6 @@
 		interrupt-parent = <&gic>;
 	};
 
-	sysreg_system_controller: syscon at 10050000 {
-		compatible = "samsung,exynos5-sysreg", "syscon";
-		reg = <0x10050000 0x5000>;
-	};
-
 	tmu_cpu0: tmu at 10060000 {
 		compatible = "samsung,exynos5420-tmu";
 		reg = <0x10060000 0x100>;
@@ -1207,6 +1134,39 @@
 	iommu-names = "m0", "m1";
 };
 
+&i2c_0 {
+	clocks = <&clock CLK_I2C0>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_bus>;
+};
+
+&i2c_1 {
+	clocks = <&clock CLK_I2C1>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_bus>;
+};
+
+&i2c_2 {
+	clocks = <&clock CLK_I2C2>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_bus>;
+};
+
+&i2c_3 {
+	clocks = <&clock CLK_I2C3>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_bus>;
+};
+
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
+
 &rtc {
 	clocks = <&clock CLK_RTC>;
 	clock-names = "rtc";
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:21 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:21 +0200
Subject: [PATCH v5 10/22] ARM: dts: exynos: Use phandle to get parent node in
 exynos5250-snow
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-11-git-send-email-krzk@kernel.org>

The i2c-arbitrator node in exynos5250-snow-common used absolute path to
reference other node (the i2c parent). Use phandle instead, because the
depth of the other node may be changed (like moving it under 'soc'
node).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5250-snow-common.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5250-snow-common.dtsi b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
index ddfe1f558c10..419d59da1751 100644
--- a/arch/arm/boot/dts/exynos5250-snow-common.dtsi
+++ b/arch/arm/boot/dts/exynos5250-snow-common.dtsi
@@ -61,7 +61,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		i2c-parent = <&{/i2c at 12CA0000}>;
+		i2c-parent = <&i2c_4>;
 
 		our-claim-gpio = <&gpf0 3 GPIO_ACTIVE_LOW>;
 		their-claim-gpios = <&gpe0 4 GPIO_ACTIVE_LOW>;
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:23 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:23 +0200
Subject: [PATCH v5 12/22] ARM: dts: exynos: Include common exynos5 in
 exynos5410.dtsi
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-13-git-send-email-krzk@kernel.org>

The exynos5.dtsi is used for common nodes shared between Exynos5250 and
Exynos542x. Since Exynos5410 is very similar to Exynos5420 it can
include the common file as well to remove duplication and make
everything more consistent.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410-smdk5410.dts |   6 +-
 arch/arm/boot/dts/exynos5410.dtsi         | 103 ++++++++++--------------------
 2 files changed, 35 insertions(+), 74 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts
index 0f6429e1b75c..777fcf2edd79 100644
--- a/arch/arm/boot/dts/exynos5410-smdk5410.dts
+++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts
@@ -102,14 +102,14 @@
 	};
 };
 
-&uart0 {
+&serial_0 {
 	status = "okay";
 };
 
-&uart1 {
+&serial_1 {
 	status = "okay";
 };
 
-&uart2 {
+&serial_2 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index ef60a06211f1..0d555c5b7311 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -14,6 +14,7 @@
  */
 
 #include "skeleton.dtsi"
+#include "exynos5.dtsi"
 #include "exynos-syscon-restart.dtsi"
 #include <dt-bindings/clock/exynos5410.h>
 
@@ -26,9 +27,6 @@
 		pinctrl1 = &pinctrl_1;
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
-		serial0 = &uart0;
-		serial1 = &uart1;
-		serial2 = &uart2;
 	};
 
 	cpus {
@@ -70,49 +68,6 @@
 		#size-cells = <1>;
 		ranges;
 
-		combiner: interrupt-controller at 10440000 {
-			compatible = "samsung,exynos4210-combiner";
-			#interrupt-cells = <2>;
-			interrupt-controller;
-			samsung,combiner-nr = <32>;
-			reg = <0x10440000 0x1000>;
-			interrupts =	<0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
-					<0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
-					<0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
-					<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
-					<0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-					<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
-					<0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-					<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
-		};
-
-		gic: interrupt-controller at 10481000 {
-			compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
-			#interrupt-cells = <3>;
-			interrupt-controller;
-			reg =	<0x10481000 0x1000>,
-				<0x10482000 0x1000>,
-				<0x10484000 0x2000>,
-				<0x10486000 0x2000>;
-			interrupts = <1 9 0xf04>;
-		};
-
-		chipid at 10000000 {
-			compatible = "samsung,exynos4210-chipid";
-			reg = <0x10000000 0x100>;
-		};
-
-		sromc: memory-controller at 12250000 {
-			compatible = "samsung,exynos4210-srom";
-			reg = <0x12250000 0x14>;
-			#address-cells = <2>;
-			#size-cells = <1>;
-			ranges = <0 0 0x04000000 0x20000
-				  1 0 0x05000000 0x20000
-				  2 0 0x06000000 0x20000
-				  3 0 0x07000000 0x20000>;
-		};
-
 		pmu_system_controller: system-controller at 10040000 {
 			compatible = "samsung,exynos5410-pmu", "syscon";
 			reg = <0x10040000 0x5000>;
@@ -239,34 +194,40 @@
 			reg = <0x03860000 0x1000>;
 			interrupts = <0 47 0>;
 		};
+	};
+};
 
-		uart0: serial at 12C00000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C00000 0x100>;
-			interrupts = <0 51 0>;
-			clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
+&pwm {
+	clocks = <&clock CLK_PWM>;
+	clock-names = "timers";
+};
 
-		uart1: serial at 12C10000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C10000 0x100>;
-			interrupts = <0 52 0>;
-			clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
+&serial_0 {
+	clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
+	clock-names = "uart", "clk_uart_baud0";
+};
 
-		uart2: serial at 12C20000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x12C20000 0x100>;
-			interrupts = <0 53 0>;
-			clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
-	};
+&serial_1 {
+	clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
+	clock-names = "uart", "clk_uart_baud0";
+};
+
+&serial_2 {
+	clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
+	clock-names = "uart", "clk_uart_baud0";
+};
+
+&serial_3 {
+	status = "disabled";
+};
+
+&sromc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	ranges = <0 0 0x04000000 0x20000
+		  1 0 0x05000000 0x20000
+		  2 0 0x06000000 0x20000
+		  3 0 0x07000000 0x20000>;
 };
 
 #include "exynos5410-pinctrl.dtsi"
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:24 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:24 +0200
Subject: [PATCH v5 13/22] ARM: dts: exynos: Enable UART3 on Exynos5410
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-14-git-send-email-krzk@kernel.org>

Just like other Exynos5 family SoCs, this one has four UARTs. Configure
clocks for UART3 and enable it.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 0d555c5b7311..a81a03408a0a 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -218,7 +218,8 @@
 };
 
 &serial_3 {
-	status = "disabled";
+	clocks = <&clock CLK_UART3>, <&clock CLK_SCLK_UART3>;
+	clock-names = "uart", "clk_uart_baud0";
 };
 
 &sromc {
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:25 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:25 +0200
Subject: [PATCH v5 14/22] ARM: dts: exynos: MCT is not an interrupt controller
 and extend length of iomap
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-15-git-send-email-krzk@kernel.org>

Multi-Core Timer generates interrupts but it is not really an interrupt
controller so remove the "interrupt-controller" and "interrupt-cells"
properties. Additionally extend the length of mapped memory to cover all
registers (last SFR is at 0x0A40).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5420.dtsi | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 4b16a9376a24..872dadf0f2d4 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -263,9 +263,7 @@
 
 		mct: mct at 101C0000 {
 			compatible = "samsung,exynos4210-mct";
-			reg = <0x101C0000 0x800>;
-			interrupt-controller;
-			#interrupt-cells = <1>;
+			reg = <0x101C0000 0xB00>;
 			interrupt-parent = <&mct_map>;
 			interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
 					<8>, <9>, <10>, <11>;
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:26 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:26 +0200
Subject: [PATCH v5 15/22] ARM: dts: exynos: Move common Exynos5410/542x/5800
 nodes to new DTSI
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-16-git-send-email-krzk@kernel.org>

The Exynos5410/542x/5800 are very similar designs. Create a new
DTSI with common nodes to remove DTS duplication. Although currently
only MCT and SysRAM are shared but in future more nodes will be added to
the common file.

The patch should not have functional impact.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 55 ++++---------------------------
 arch/arm/boot/dts/exynos5420.dtsi | 54 ++++---------------------------
 arch/arm/boot/dts/exynos54xx.dtsi | 68 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+), 97 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos54xx.dtsi

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index a81a03408a0a..1354b5bbc14e 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -13,8 +13,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "skeleton.dtsi"
-#include "exynos5.dtsi"
+#include "exynos54xx.dtsi"
 #include "exynos-syscon-restart.dtsi"
 #include <dt-bindings/clock/exynos5410.h>
 
@@ -76,53 +75,6 @@
 			#clock-cells = <1>;
 		};
 
-		mct: mct at 101C0000 {
-			compatible = "samsung,exynos4210-mct";
-			reg = <0x101C0000 0xB00>;
-			interrupt-parent = <&interrupt_map>;
-			interrupts = <0>, <1>, <2>, <3>,
-				<4>, <5>, <6>, <7>,
-				<8>, <9>, <10>, <11>;
-			clocks = <&fin_pll>, <&clock CLK_MCT>;
-			clock-names = "fin_pll", "mct";
-
-			interrupt_map: interrupt-map {
-				#interrupt-cells = <1>;
-				#address-cells = <0>;
-				#size-cells = <0>;
-				interrupt-map = <0 &combiner 23 3>,
-						<1 &combiner 23 4>,
-						<2 &combiner 25 2>,
-						<3 &combiner 25 3>,
-						<4 &gic 0 120 0>,
-						<5 &gic 0 121 0>,
-						<6 &gic 0 122 0>,
-						<7 &gic 0 123 0>,
-						<8 &gic 0 128 0>,
-						<9 &gic 0 129 0>,
-						<10 &gic 0 130 0>,
-						<11 &gic 0 131 0>;
-			};
-		};
-
-		sysram at 02020000 {
-			compatible = "mmio-sram";
-			reg = <0x02020000 0x54000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x02020000 0x54000>;
-
-			smp-sysram at 0 {
-				compatible = "samsung,exynos4210-sysram";
-				reg = <0x0 0x1000>;
-			};
-
-			smp-sysram at 53000 {
-				compatible = "samsung,exynos4210-sysram-ns";
-				reg = <0x53000 0x1000>;
-			};
-		};
-
 		clock: clock-controller at 10010000 {
 			compatible = "samsung,exynos5410-clock";
 			reg = <0x10010000 0x30000>;
@@ -197,6 +149,11 @@
 	};
 };
 
+&mct {
+	clocks = <&fin_pll>, <&clock CLK_MCT>;
+	clock-names = "fin_pll", "mct";
+};
+
 &pwm {
 	clocks = <&clock CLK_PWM>;
 	clock-names = "timers";
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 872dadf0f2d4..ebf2ed3c5ff8 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -13,9 +13,8 @@
  * published by the Free Software Foundation.
  */
 
+#include "exynos54xx.dtsi"
 #include <dt-bindings/clock/exynos5420.h>
-#include "exynos5.dtsi"
-
 #include <dt-bindings/clock/exynos-audss-clk.h>
 
 / {
@@ -181,24 +180,6 @@
 			};
 		};
 
-		sysram at 02020000 {
-			compatible = "mmio-sram";
-			reg = <0x02020000 0x54000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x02020000 0x54000>;
-
-			smp-sysram at 0 {
-				compatible = "samsung,exynos4210-sysram";
-				reg = <0x0 0x1000>;
-			};
-
-			smp-sysram at 53000 {
-				compatible = "samsung,exynos4210-sysram-ns";
-				reg = <0x53000 0x1000>;
-			};
-		};
-
 		clock: clock-controller at 10010000 {
 			compatible = "samsung,exynos5420-clock";
 			reg = <0x10010000 0x30000>;
@@ -261,34 +242,6 @@
 			status = "disabled";
 		};
 
-		mct: mct at 101C0000 {
-			compatible = "samsung,exynos4210-mct";
-			reg = <0x101C0000 0xB00>;
-			interrupt-parent = <&mct_map>;
-			interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
-					<8>, <9>, <10>, <11>;
-			clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
-			clock-names = "fin_pll", "mct";
-
-			mct_map: mct-map {
-				#interrupt-cells = <1>;
-				#address-cells = <0>;
-				#size-cells = <0>;
-				interrupt-map = <0 &combiner 23 3>,
-						<1 &combiner 23 4>,
-						<2 &combiner 25 2>,
-						<3 &combiner 25 3>,
-						<4 &gic 0 120 0>,
-						<5 &gic 0 121 0>,
-						<6 &gic 0 122 0>,
-						<7 &gic 0 123 0>,
-						<8 &gic 0 128 0>,
-						<9 &gic 0 129 0>,
-						<10 &gic 0 130 0>,
-						<11 &gic 0 131 0>;
-			};
-		};
-
 		gsc_pd: power-domain at 10044000 {
 			compatible = "samsung,exynos4210-pd";
 			reg = <0x10044000 0x20>;
@@ -1163,6 +1116,11 @@
 	pinctrl-0 = <&i2c3_bus>;
 };
 
+&mct {
+	clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
+	clock-names = "fin_pll", "mct";
+};
+
 &pwm {
 	clocks = <&clock CLK_PWM>;
 	clock-names = "timers";
diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi
new file mode 100644
index 000000000000..1bcfb7f455c1
--- /dev/null
+++ b/arch/arm/boot/dts/exynos54xx.dtsi
@@ -0,0 +1,68 @@
+/*
+ * Samsung's Exynos54xx SoC series common device tree source
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2016 Krzysztof Kozlowski
+ *
+ * Device nodes common for Samsung Exynos5410/5420/5422/5800. Specific
+ * Exynos 54xx SoCs should include this file and customize it further
+ * (e.g. with clocks).
+ *
+ * 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 "skeleton.dtsi"
+#include "exynos5.dtsi"
+
+/ {
+	compatible = "samsung,exynos5";
+
+	soc: soc {
+		sysram at 02020000 {
+			compatible = "mmio-sram";
+			reg = <0x02020000 0x54000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x02020000 0x54000>;
+
+			smp-sysram at 0 {
+				compatible = "samsung,exynos4210-sysram";
+				reg = <0x0 0x1000>;
+			};
+
+			smp-sysram at 53000 {
+				compatible = "samsung,exynos4210-sysram-ns";
+				reg = <0x53000 0x1000>;
+			};
+		};
+
+		mct: mct at 101c0000 {
+			compatible = "samsung,exynos4210-mct";
+			reg = <0x101c0000 0xb00>;
+			interrupt-parent = <&mct_map>;
+			interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
+					<8>, <9>, <10>, <11>;
+
+			mct_map: mct-map {
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				interrupt-map = <0 &combiner 23 3>,
+						<1 &combiner 23 4>,
+						<2 &combiner 25 2>,
+						<3 &combiner 25 3>,
+						<4 &gic 0 120 0>,
+						<5 &gic 0 121 0>,
+						<6 &gic 0 122 0>,
+						<7 &gic 0 123 0>,
+						<8 &gic 0 128 0>,
+						<9 &gic 0 129 0>,
+						<10 &gic 0 130 0>,
+						<11 &gic 0 131 0>;
+			};
+		};
+	};
+};
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:28 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:28 +0200
Subject: [PATCH v5 17/22] ARM: dts: exynos: Add initial support for Odroid XU
 board
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-18-git-send-email-krzk@kernel.org>

The Hardkernel's Odroid XU board was first design with big.LITTLE SoC
from Samsung: the Exynos5410. Details:
1. Exynos5410 octa-core (A15+A7, however as of now only one cluster is
   enabled),
2. 2 GB DDR3 RAM,
3. PowerVR SGX544MP3 GPU (not enabled in DTS),
4. USB 3.0 Host x 1, USB 3.0 OTG x 1, USB 2.0 Host x 4,
5. HDMI 1.4a, MIPI DSI and Display Port (Display Port not on all of
   revisions though),
6. eMMC 4.5 and microSD slots.

Comparing this board to Odroid XU3 (more popular), the differences are:
1. Exynos5410 instead of 5422,
2. MIPI DSI LCD connector,
3. Main PMIC: Maxim 77802 instead of S2MPS11,
4. USB3503+LAN9730 instead of integrated LAN9514,
5. eMMC 4.5 instead of eMMC 5.0,

This patch adds initial support for the XU board with working basic
functions, eMMC/SD and USB (including attached ethernet adapter).

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Acked-by: Rob Herring <robh at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Link: http://www.hardkernel.com/main/products/prdt_info.php?g_code=G137510300620
---
 .../bindings/arm/samsung/samsung-boards.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/exynos5410-odroidxu.dts          | 121 +++++++++++++++++++++
 3 files changed, 123 insertions(+)
 create mode 100644 arch/arm/boot/dts/exynos5410-odroidxu.dts

diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
index f5deace2b380..0ea7f14ef294 100644
--- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
+++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
@@ -47,6 +47,7 @@ Required root node properties:
 	- "hardkernel,odroid-u3"  - for Exynos4412-based Hardkernel Odroid U3.
 	- "hardkernel,odroid-x"   - for Exynos4412-based Hardkernel Odroid X.
 	- "hardkernel,odroid-x2"  - for Exynos4412-based Hardkernel Odroid X2.
+	- "hardkernel,odroid-xu"  - for Exynos5410-based Hardkernel Odroid XU.
 	- "hardkernel,odroid-xu3" - for Exynos5422-based Hardkernel Odroid XU3.
 	- "hardkernel,odroid-xu3-lite" - for Exynos5422-based Hardkernel
 					 Odroid XU3 Lite board.
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 5aeb10674370..9ed1c7abedb1 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -134,6 +134,7 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \
 	exynos5250-snow-rev5.dtb \
 	exynos5250-spring.dtb \
 	exynos5260-xyref5260.dtb \
+	exynos5410-odroidxu.dtb \
 	exynos5410-smdk5410.dtb \
 	exynos5420-arndale-octa.dtb \
 	exynos5420-peach-pit.dtb \
diff --git a/arch/arm/boot/dts/exynos5410-odroidxu.dts b/arch/arm/boot/dts/exynos5410-odroidxu.dts
new file mode 100644
index 000000000000..9fe04500ecaf
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5410-odroidxu.dts
@@ -0,0 +1,121 @@
+/*
+ * Hardkernel Odroid XU board device tree source
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2016 Krzysztof Kozlowski
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include "exynos5410.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "exynos54xx-odroidxu-leds.dtsi"
+
+/ {
+	model = "Hardkernel Odroid XU";
+	compatible = "hardkernel,odroid-xu", "samsung,exynos5410", "samsung,exynos5";
+
+	memory {
+		reg = <0x40000000 0x7ea00000>;
+	};
+
+	chosen {
+		linux,stdout-path = &serial_2;
+	};
+
+	emmc_pwrseq: pwrseq {
+		pinctrl-0 = <&emmc_nrst_pin>;
+		pinctrl-names = "default";
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpd1 0 GPIO_ACTIVE_LOW>;
+	};
+
+	fan0: pwm-fan {
+		compatible = "pwm-fan";
+		pwms = <&pwm 0 20972 0>;
+		cooling-min-state = <0>;
+		cooling-max-state = <3>;
+		#cooling-cells = <2>;
+		cooling-levels = <0 130 170 230>;
+	};
+
+	fin_pll: xxti {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "fin_pll";
+		#clock-cells = <0>;
+	};
+
+	firmware at 02073000 {
+		compatible = "samsung,secure-firmware";
+		reg = <0x02073000 0x1000>;
+	};
+};
+
+&mmc_0 {
+	status = "okay";
+	mmc-pwrseq = <&emmc_pwrseq>;
+	cd-gpios = <&gpc0 2 GPIO_ACTIVE_LOW>;
+	card-detect-delay = <200>;
+	samsung,dw-mshc-ciu-div = <3>;
+	samsung,dw-mshc-sdr-timing = <0 4>;
+	samsung,dw-mshc-ddr-timing = <0 2>;
+	samsung,dw-mshc-hs400-timing = <0 2>;
+	samsung,read-strobe-delay = <90>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8 &sd0_cd>;
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
+};
+
+&mmc_2 {
+	status = "okay";
+	card-detect-delay = <200>;
+	samsung,dw-mshc-ciu-div = <3>;
+	samsung,dw-mshc-sdr-timing = <0 4>;
+	samsung,dw-mshc-ddr-timing = <0 2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
+	bus-width = <4>;
+	cap-sd-highspeed;
+};
+
+&pinctrl_0 {
+	emmc_nrst_pin: emmc-nrst {
+		samsung,pins = "gpd1-0";
+		samsung,pin-function = <0>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+};
+
+&serial_0 {
+	status = "okay";
+};
+
+&serial_1 {
+	status = "okay";
+};
+
+&serial_2 {
+	status = "okay";
+};
+
+&serial_3 {
+	status = "okay";
+};
+
+&usbdrd_dwc3_0 {
+	dr_mode = "host";
+};
+
+&usbdrd_dwc3_1 {
+	dr_mode = "peripheral";
+};
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:30 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:30 +0200
Subject: [PATCH v5 19/22] clk: samsung: exynos5410: Add I2C,
 HSI2C and RTC clocks
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-20-git-send-email-krzk@kernel.org>

Add clocks for I2C, USI (HSI2C) and RTC to the Exynos5410 clock driver.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 drivers/clk/samsung/clk-exynos5410.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index 5f892128849a..6c2e59c576ee 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -159,6 +159,7 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 
 static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 	GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
+	GATE(CLK_RTC, "rtc", "aclk66", GATE_IP_PERIS, 20, 0, 0),
 
 	GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
 			SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
@@ -187,6 +188,14 @@ static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 	GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
 	GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
 	GATE(CLK_UART3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0),
+	GATE(CLK_I2C0, "i2c0", "aclk66", GATE_IP_PERIC, 6, 0, 0),
+	GATE(CLK_I2C1, "i2c1", "aclk66", GATE_IP_PERIC, 7, 0, 0),
+	GATE(CLK_I2C2, "i2c2", "aclk66", GATE_IP_PERIC, 8, 0, 0),
+	GATE(CLK_I2C3, "i2c3", "aclk66", GATE_IP_PERIC, 9, 0, 0),
+	GATE(CLK_USI0, "usi0", "aclk66", GATE_IP_PERIC, 10, 0, 0),
+	GATE(CLK_USI1, "usi1", "aclk66", GATE_IP_PERIC, 11, 0, 0),
+	GATE(CLK_USI2, "usi2", "aclk66", GATE_IP_PERIC, 12, 0, 0),
+	GATE(CLK_USI3, "usi3", "aclk66", GATE_IP_PERIC, 13, 0, 0),
 	GATE(CLK_PWM, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0),
 
 	GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:29 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:29 +0200
Subject: [PATCH v5 18/22] dt-bindings: clock: Add I2C,
 HSI2C and RTC clock IDs to Exynos5410
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-19-git-send-email-krzk@kernel.org>

Add IDs for I2C, USI (HSI2C) and RTC clocks to Exynos5410. Use the same
number as for Exynos5420 just in case in future these drivers were
merged.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 include/dt-bindings/clock/exynos5410.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index 34c8e96987a1..e94b7bbfd6af 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -38,9 +38,18 @@
 #define CLK_UART0		257
 #define CLK_UART1		258
 #define CLK_UART2		259
+#define CLK_I2C0		261
+#define CLK_I2C1		262
+#define CLK_I2C2		263
+#define CLK_I2C3		264
+#define CLK_USI0		265
+#define CLK_USI1		266
+#define CLK_USI2		267
+#define CLK_USI3		268
 #define CLK_UART3		260
 #define CLK_PWM			279
 #define CLK_MCT			315
+#define CLK_RTC			317
 #define CLK_MMC0		351
 #define CLK_MMC1		352
 #define CLK_MMC2		353
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:27 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:27 +0200
Subject: [PATCH v5 16/22] ARM: dts: exynos: Add USB to Exynos5410
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-17-git-send-email-krzk@kernel.org>

Move USB 3.0 DWC and 2.0 EHCI/OHCI nodes from exynos5420.dtsi to
exynos54xx.dtsi common for entire family. For Exynos542x/5800 this
should not have functional impact but for Exynos5410 this effectively
adds USB support.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi |  39 +++++++++++
 arch/arm/boot/dts/exynos5420.dtsi | 133 +++++++++++---------------------------
 arch/arm/boot/dts/exynos54xx.dtsi |  79 ++++++++++++++++++++++
 3 files changed, 157 insertions(+), 94 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 1354b5bbc14e..6146bf164248 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -188,4 +188,43 @@
 		  3 0 0x07000000 0x20000>;
 };
 
+&usbdrd3_0 {
+	clocks = <&clock CLK_USBD300>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy0 {
+	clocks = <&clock CLK_USBD300>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbdrd3_1 {
+	clocks = <&clock CLK_USBD301>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy1 {
+	clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbhost1 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usbhost2 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usb2_phy {
+	clocks = <&clock CLK_USBH20>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,sysreg-phandle = <&sysreg_system_controller>;
+	samsung,pmureg-phandle = <&pmu_system_controller>;
+};
+
 #include "exynos5410-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index ebf2ed3c5ff8..8fa65eb8027d 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -41,8 +41,6 @@
 		spi0 = &spi_0;
 		spi1 = &spi_1;
 		spi2 = &spi_2;
-		usbdrdphy0 = &usbdrd_phy0;
-		usbdrdphy1 = &usbdrd_phy1;
 	};
 
 	/*
@@ -770,98 +768,6 @@
 			clock-names = "secss";
 		};
 
-		usbdrd3_0: usb3-0 {
-			compatible = "samsung,exynos5250-dwusb3";
-			clocks = <&clock CLK_USBD300>;
-			clock-names = "usbdrd30";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
-
-			usbdrd_dwc3_0: dwc3 at 12000000 {
-				compatible = "snps,dwc3";
-				reg = <0x12000000 0x10000>;
-				interrupts = <0 72 0>;
-				phys = <&usbdrd_phy0 0>, <&usbdrd_phy0 1>;
-				phy-names = "usb2-phy", "usb3-phy";
-			};
-		};
-
-		usbdrd_phy0: phy at 12100000 {
-			compatible = "samsung,exynos5420-usbdrd-phy";
-			reg = <0x12100000 0x100>;
-			clocks = <&clock CLK_USBD300>, <&clock CLK_SCLK_USBPHY300>;
-			clock-names = "phy", "ref";
-			samsung,pmu-syscon = <&pmu_system_controller>;
-			#phy-cells = <1>;
-		};
-
-		usbdrd3_1: usb3-1 {
-			compatible = "samsung,exynos5250-dwusb3";
-			clocks = <&clock CLK_USBD301>;
-			clock-names = "usbdrd30";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
-
-			usbdrd_dwc3_1: dwc3 at 12400000 {
-				compatible = "snps,dwc3";
-				reg = <0x12400000 0x10000>;
-				interrupts = <0 73 0>;
-				phys = <&usbdrd_phy1 0>, <&usbdrd_phy1 1>;
-				phy-names = "usb2-phy", "usb3-phy";
-			};
-		};
-
-		usbdrd_phy1: phy at 12500000 {
-			compatible = "samsung,exynos5420-usbdrd-phy";
-			reg = <0x12500000 0x100>;
-			clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
-			clock-names = "phy", "ref";
-			samsung,pmu-syscon = <&pmu_system_controller>;
-			#phy-cells = <1>;
-		};
-
-		usbhost2: usb at 12110000 {
-			compatible = "samsung,exynos4210-ehci";
-			reg = <0x12110000 0x100>;
-			interrupts = <0 71 0>;
-
-			clocks = <&clock CLK_USBH20>;
-			clock-names = "usbhost";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			port at 0 {
-				reg = <0>;
-				phys = <&usb2_phy 1>;
-			};
-		};
-
-		usbhost1: usb at 12120000 {
-			compatible = "samsung,exynos4210-ohci";
-			reg = <0x12120000 0x100>;
-			interrupts = <0 71 0>;
-
-			clocks = <&clock CLK_USBH20>;
-			clock-names = "usbhost";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			port at 0 {
-				reg = <0>;
-				phys = <&usb2_phy 1>;
-			};
-		};
-
-		usb2_phy: phy at 12130000 {
-			compatible = "samsung,exynos5250-usb2-phy";
-			reg = <0x12130000 0x100>;
-			clocks = <&clock CLK_USBH20>, <&clock CLK_SCLK_USBPHY300>;
-			clock-names = "phy", "ref";
-			#phy-cells = <1>;
-			samsung,sysreg-phandle = <&sysreg_system_controller>;
-			samsung,pmureg-phandle = <&pmu_system_controller>;
-		};
-
 		sysmmu_g2dr: sysmmu at 0x10A60000 {
 			compatible = "samsung,exynos-sysmmu";
 			reg = <0x10A60000 0x1000>;
@@ -1153,4 +1059,43 @@
 	clock-names = "uart", "clk_uart_baud0";
 };
 
+&usbdrd3_0 {
+	clocks = <&clock CLK_USBD300>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy0 {
+	clocks = <&clock CLK_USBD300>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbdrd3_1 {
+	clocks = <&clock CLK_USBD301>;
+	clock-names = "usbdrd30";
+};
+
+&usbdrd_phy1 {
+	clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
+	clock-names = "phy", "ref";
+	samsung,pmu-syscon = <&pmu_system_controller>;
+};
+
+&usbhost1 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usbhost2 {
+	clocks = <&clock CLK_USBH20>;
+	clock-names = "usbhost";
+};
+
+&usb2_phy {
+	clocks = <&clock CLK_USBH20>, <&clock CLK_SCLK_USBPHY300>;
+	clock-names = "phy", "ref";
+	samsung,sysreg-phandle = <&sysreg_system_controller>;
+	samsung,pmureg-phandle = <&pmu_system_controller>;
+};
+
 #include "exynos5420-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi
index 1bcfb7f455c1..e01d068d4c38 100644
--- a/arch/arm/boot/dts/exynos54xx.dtsi
+++ b/arch/arm/boot/dts/exynos54xx.dtsi
@@ -20,6 +20,11 @@
 / {
 	compatible = "samsung,exynos5";
 
+	aliases {
+		usbdrdphy0 = &usbdrd_phy0;
+		usbdrdphy1 = &usbdrd_phy1;
+	};
+
 	soc: soc {
 		sysram at 02020000 {
 			compatible = "mmio-sram";
@@ -64,5 +69,79 @@
 						<11 &gic 0 131 0>;
 			};
 		};
+
+		usbdrd3_0: usb3-0 {
+			compatible = "samsung,exynos5250-dwusb3";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			usbdrd_dwc3_0: dwc3 at 12000000 {
+				compatible = "snps,dwc3";
+				reg = <0x12000000 0x10000>;
+				interrupts = <0 72 0>;
+				phys = <&usbdrd_phy0 0>, <&usbdrd_phy0 1>;
+				phy-names = "usb2-phy", "usb3-phy";
+			};
+		};
+
+		usbdrd_phy0: phy at 12100000 {
+			compatible = "samsung,exynos5420-usbdrd-phy";
+			reg = <0x12100000 0x100>;
+			#phy-cells = <1>;
+		};
+
+		usbdrd3_1: usb3-1 {
+			compatible = "samsung,exynos5250-dwusb3";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			usbdrd_dwc3_1: dwc3 at 12400000 {
+				compatible = "snps,dwc3";
+				reg = <0x12400000 0x10000>;
+				interrupts = <0 73 0>;
+				phys = <&usbdrd_phy1 0>, <&usbdrd_phy1 1>;
+				phy-names = "usb2-phy", "usb3-phy";
+			};
+		};
+
+		usbdrd_phy1: phy at 12500000 {
+			compatible = "samsung,exynos5420-usbdrd-phy";
+			reg = <0x12500000 0x100>;
+			#phy-cells = <1>;
+		};
+
+		usbhost2: usb at 12110000 {
+			compatible = "samsung,exynos4210-ehci";
+			reg = <0x12110000 0x100>;
+			interrupts = <0 71 0>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port at 0 {
+				reg = <0>;
+				phys = <&usb2_phy 1>;
+			};
+		};
+
+		usbhost1: usb at 12120000 {
+			compatible = "samsung,exynos4210-ohci";
+			reg = <0x12120000 0x100>;
+			interrupts = <0 71 0>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port at 0 {
+				reg = <0>;
+				phys = <&usb2_phy 1>;
+			};
+		};
+
+		usb2_phy: phy at 12130000 {
+			compatible = "samsung,exynos5250-usb2-phy";
+			reg = <0x12130000 0x100>;
+			#phy-cells = <1>;
+		};
 	};
 };
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:31 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:31 +0200
Subject: [PATCH v5 20/22] ARM: dts: exynos: Move HSI2C nodes to exynos54xx.dtsi
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-21-git-send-email-krzk@kernel.org>

The USI/HSI2C nodes can be mostly shared between Exynos5420 and
Exynos5410 so move them to common DTSI.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier at osg.samsung.com>

---

Change since v4:
1. Remove the nodes in exynos5420.dtsi (before they were actually just
   copied instead of moving).
2. Use lower-case for hex.
---
 arch/arm/boot/dts/exynos5420.dtsi | 85 +++++++++++++--------------------------
 arch/arm/boot/dts/exynos54xx.dtsi | 41 +++++++++++++++++++
 2 files changed, 69 insertions(+), 57 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 8fa65eb8027d..8b1e706e9250 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -29,10 +29,6 @@
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
 		pinctrl4 = &pinctrl_4;
-		i2c4 = &hsi2c_4;
-		i2c5 = &hsi2c_5;
-		i2c6 = &hsi2c_6;
-		i2c7 = &hsi2c_7;
 		i2c8 = &hsi2c_8;
 		i2c9 = &hsi2c_9;
 		i2c10 = &hsi2c_10;
@@ -526,59 +522,6 @@
 			status = "disabled";
 		};
 
-		/* i2c_0-3 are defined in exynos5.dtsi */
-		hsi2c_4: i2c at 12CA0000 {
-			compatible = "samsung,exynos5250-hsi2c";
-			reg = <0x12CA0000 0x1000>;
-			interrupts = <0 60 0>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c4_hs_bus>;
-			clocks = <&clock CLK_USI0>;
-			clock-names = "hsi2c";
-			status = "disabled";
-		};
-
-		hsi2c_5: i2c at 12CB0000 {
-			compatible = "samsung,exynos5250-hsi2c";
-			reg = <0x12CB0000 0x1000>;
-			interrupts = <0 61 0>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c5_hs_bus>;
-			clocks = <&clock CLK_USI1>;
-			clock-names = "hsi2c";
-			status = "disabled";
-		};
-
-		hsi2c_6: i2c at 12CC0000 {
-			compatible = "samsung,exynos5250-hsi2c";
-			reg = <0x12CC0000 0x1000>;
-			interrupts = <0 62 0>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c6_hs_bus>;
-			clocks = <&clock CLK_USI2>;
-			clock-names = "hsi2c";
-			status = "disabled";
-		};
-
-		hsi2c_7: i2c at 12CD0000 {
-			compatible = "samsung,exynos5250-hsi2c";
-			reg = <0x12CD0000 0x1000>;
-			interrupts = <0 63 0>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c7_hs_bus>;
-			clocks = <&clock CLK_USI3>;
-			clock-names = "hsi2c";
-			status = "disabled";
-		};
-
 		hsi2c_8: i2c at 12E00000 {
 			compatible = "samsung,exynos5250-hsi2c";
 			reg = <0x12E00000 0x1000>;
@@ -1022,6 +965,34 @@
 	pinctrl-0 = <&i2c3_bus>;
 };
 
+&hsi2c_4 {
+	clocks = <&clock CLK_USI0>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_hs_bus>;
+};
+
+&hsi2c_5 {
+	clocks = <&clock CLK_USI1>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c5_hs_bus>;
+};
+
+&hsi2c_6 {
+	clocks = <&clock CLK_USI2>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c6_hs_bus>;
+};
+
+&hsi2c_7 {
+	clocks = <&clock CLK_USI3>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c7_hs_bus>;
+};
+
 &mct {
 	clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MCT>;
 	clock-names = "fin_pll", "mct";
diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi
index e01d068d4c38..44a8391c8524 100644
--- a/arch/arm/boot/dts/exynos54xx.dtsi
+++ b/arch/arm/boot/dts/exynos54xx.dtsi
@@ -21,6 +21,10 @@
 	compatible = "samsung,exynos5";
 
 	aliases {
+		i2c4 = &hsi2c_4;
+		i2c5 = &hsi2c_5;
+		i2c6 = &hsi2c_6;
+		i2c7 = &hsi2c_7;
 		usbdrdphy0 = &usbdrd_phy0;
 		usbdrdphy1 = &usbdrd_phy1;
 	};
@@ -70,6 +74,43 @@
 			};
 		};
 
+		/* i2c_0-3 are defined in exynos5.dtsi */
+		hsi2c_4: i2c at 12ca0000 {
+			compatible = "samsung,exynos5250-hsi2c";
+			reg = <0x12ca0000 0x1000>;
+			interrupts = <0 60 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		hsi2c_5: i2c at 12cb0000 {
+			compatible = "samsung,exynos5250-hsi2c";
+			reg = <0x12cb0000 0x1000>;
+			interrupts = <0 61 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		hsi2c_6: i2c at 12cc0000 {
+			compatible = "samsung,exynos5250-hsi2c";
+			reg = <0x12cc0000 0x1000>;
+			interrupts = <0 62 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		hsi2c_7: i2c at 12cd0000 {
+			compatible = "samsung,exynos5250-hsi2c";
+			reg = <0x12cd0000 0x1000>;
+			interrupts = <0 63 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		usbdrd3_0: usb3-0 {
 			compatible = "samsung,exynos5250-dwusb3";
 			#address-cells = <1>;
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:32 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:32 +0200
Subject: [PATCH v5 21/22] ARM: dts: exynos: Add I2C,
 PWM and UART pinctrl to Exynos5410
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-22-git-send-email-krzk@kernel.org>

Add pincontrol groups for HSI2C (USI), I2C, PWM and UART to Exynos5410.
This allows configuring these pins to specific functions.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410-pinctrl.dtsi | 133 ++++++++++++++++++++++++++++++
 1 file changed, 133 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
index ddacafa1e907..b58a0f29f42c 100644
--- a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
@@ -278,6 +278,139 @@
 		#interrupt-cells = <2>;
 	};
 
+	uart0_data: uart0-data {
+		samsung,pins = "gpa0-0", "gpa0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart0_fctl: uart0-fctl {
+		samsung,pins = "gpa0-2", "gpa0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart1_data: uart1-data {
+		samsung,pins = "gpa0-4", "gpa0-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart1_fctl: uart1-fctl {
+		samsung,pins = "gpa0-6", "gpa0-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c2_bus: i2c2-bus {
+		samsung,pins = "gpa0-6", "gpa0-7";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart2_data: uart2-data {
+		samsung,pins = "gpa1-0", "gpa1-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart2_fctl: uart2-fctl {
+		samsung,pins = "gpa1-2", "gpa1-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c3_bus: i2c3-bus {
+		samsung,pins = "gpa1-2", "gpa1-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart3_data: uart3-data {
+		samsung,pins = "gpa1-4", "gpa1-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c4_hs_bus: i2c4-hs-bus {
+		samsung,pins = "gpa2-0", "gpa2-1";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c5_hs_bus: i2c5-hs-bus {
+		samsung,pins = "gpa2-2", "gpa2-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c6_hs_bus: i2c6-hs-bus {
+		samsung,pins = "gpb1-3", "gpb1-4";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm0_out: pwm0-out {
+		samsung,pins = "gpb2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm1_out: pwm1-out {
+		samsung,pins = "gpb2-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm2_out: pwm2-out {
+		samsung,pins = "gpb2-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm3_out: pwm3-out {
+		samsung,pins = "gpb2-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c7_hs_bus: i2c7-hs-bus {
+		samsung,pins = "gpb2-2", "gpb2-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c0_bus: i2c0-bus {
+		samsung,pins = "gpb3-0", "gpb3-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2c1_bus: i2c1-bus {
+		samsung,pins = "gpb3-2", "gpb3-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
 	sd0_clk: sd0-clk {
 		samsung,pins = "gpc0-0";
 		samsung,pin-function = <2>;
-- 
2.7.4



From krzk at kernel.org  Sat May 28 02:54:33 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 28 May 2016 11:54:33 +0200
Subject: [PATCH v5 22/22] ARM: dts: exynos: Add RTC and I2C to Exynos5410
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <1464429273-23457-23-git-send-email-krzk@kernel.org>

Configure Exynos5410-specific properties of RTC, I2C and HSI2C nodes.
This still does not enable them on the board level though.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>
---
 arch/arm/boot/dts/exynos5410.dtsi | 63 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 6146bf164248..a937d9bdad90 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -149,6 +149,62 @@
 	};
 };
 
+&i2c_0 {
+	clocks = <&clock CLK_I2C0>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_bus>;
+};
+
+&i2c_1 {
+	clocks = <&clock CLK_I2C1>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_bus>;
+};
+
+&i2c_2 {
+	clocks = <&clock CLK_I2C2>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_bus>;
+};
+
+&i2c_3 {
+	clocks = <&clock CLK_I2C3>;
+	clock-names = "i2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_bus>;
+};
+
+&hsi2c_4 {
+	clocks = <&clock CLK_USI0>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_hs_bus>;
+};
+
+&hsi2c_5 {
+	clocks = <&clock CLK_USI1>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c5_hs_bus>;
+};
+
+&hsi2c_6 {
+	clocks = <&clock CLK_USI2>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c6_hs_bus>;
+};
+
+&hsi2c_7 {
+	clocks = <&clock CLK_USI3>;
+	clock-names = "hsi2c";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c7_hs_bus>;
+};
+
 &mct {
 	clocks = <&fin_pll>, <&clock CLK_MCT>;
 	clock-names = "fin_pll", "mct";
@@ -159,6 +215,13 @@
 	clock-names = "timers";
 };
 
+&rtc {
+	clocks = <&clock CLK_RTC>;
+	clock-names = "rtc";
+	interrupt-parent = <&pmu_system_controller>;
+	status = "disabled";
+};
+
 &serial_0 {
 	clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
 	clock-names = "uart", "clk_uart_baud0";
-- 
2.7.4



From fengguang.wu at intel.com  Sat May 28 03:54:06 2016
From: fengguang.wu at intel.com (kbuild test robot)
Date: Sat, 28 May 2016 18:54:06 +0800
Subject: [rjarzmik:work/ac97 4/7] sound/soc/codecs/.tmp_gl_wm9713.o:undefined
 reference to `compat_release_snd_ac97_codec'
Message-ID: <201605281803.w7MfrmbD%fengguang.wu@intel.com>

tree:   https://github.com/rjarzmik/linux work/ac97
head:   3350c2230e9e1331442724f919c86542d9668d4b
commit: 8715b68899fdeea2968c7760843a0f908b4def2c [4/7] ASoC: wm9713: add ac97 new bus support
config: microblaze-allyesconfig (attached as .config)
compiler: microblaze-linux-gcc (GCC) 4.9.0
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        git checkout 8715b68899fdeea2968c7760843a0f908b4def2c
        # save the attached .config to linux build tree
        make.cross ARCH=microblaze 

Note: the rjarzmik/work/ac97 HEAD 3350c2230e9e1331442724f919c86542d9668d4b builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   `.exit.data' referenced in section `.exit.text' of drivers/built-in.o: defined in discarded section `.exit.data' of drivers/built-in.o
   `.exit.data' referenced in section `.exit.text' of drivers/built-in.o: defined in discarded section `.exit.data' of drivers/built-in.o
   sound/built-in.o: In function `wm9713_soc_remove':
>> sound/soc/codecs/.tmp_gl_wm9713.o:(.text+0x921b9c): undefined reference to `compat_release_snd_ac97_codec'
   sound/built-in.o: In function `wm9713_soc_probe':
>> sound/soc/codecs/.tmp_gl_wm9713.o:(.text+0x921c40): undefined reference to `compat_alloc_snd_ac97_codec'
   sound/soc/codecs/.tmp_gl_wm9713.o:(.text+0x921d0c): undefined reference to `compat_release_snd_ac97_codec'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 44817 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160528/c9c4fdc0/attachment-0001.obj>

From pavel at ucw.cz  Sat May 28 04:09:35 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Sat, 28 May 2016 13:09:35 +0200
Subject: Nokia N900 retention mode in v4.6, camera buttons fun
In-Reply-To: <20160502201216.GA19211@earth>
References: <20160411211026.GH5995@atomide.com> <20160412121658.GA32486@amd>
 <20160412123013.GA12296@amd> <20160412163055.GP5995@atomide.com>
 <20160417175539.GA502@amd> <20160421130450.GQ29406@pali>
 <20160429200559.GA16598@earth> <20160501085236.GA14243@amd>
 <20160501154855.GA24970@earth> <20160502201216.GA19211@earth>
Message-ID: <20160528110935.GB21182@amd>

On Mon 2016-05-02 22:12:17, Sebastian Reichel wrote:
> Hi Pavel,
> 
> On Sun, May 01, 2016 at 05:48:56PM +0200, Sebastian Reichel wrote:
> > > I see latest series, and it also talks about frequency scaling.
> > > But I guess it is not going to fix this issue?
> > 
> > No, this is independent of the runtime PM problems. I also worked
> > on runtime PM/idling yesterday and pm_runtime_irq_safe is the main
> > culprit for breaking it (not the only one, though). It's not yet
> > finished though
> 
> I will be on vacation for a week starting tomorrow. If you want to
> play around with my intermediate SSI PM status, you can try this branch:
> 
> https://git.kernel.org/cgit/linux/kernel/git/sre/linux-hsi.git/log/?h=runtime-pm-fixes

Ok, I did:

pavel at amd:/data/l/linux-n900$ git pull
git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-hsi.git
runtime-pm-fixes
remote: Counting objects: 65, done.
remote: Compressing objects: 100% (25/25), done.
remote: Total 65 (delta 51), reused 54 (delta 40)
Unpacking objects: 100% (65/65), done.

And yes, now the LED goes off (so far with modem enabled but not
used). Thanks!

(You can have my Tested-by: when you submit them, or something :-) )

Best regards,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From bhe at redhat.com  Sat May 28 04:28:42 2016
From: bhe at redhat.com (Baoquan He)
Date: Sat, 28 May 2016 19:28:42 +0800
Subject: [PATCH kexec-tools 05/32] arm: fix kdump to work on LPAE systems
In-Reply-To: <E1axXSK-0004hN-V7@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSK-0004hN-V7@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <20160528112842.GA2429@x1.redhat.com>

On 05/03/16 at 11:21am, Russell King wrote:
> We need to use 64-bit file IO when mapping system memory and the core
> dump file as we may be running on a LPAE system, otherwise we risk
> mapping memory we shouldn't, and causing a kernel oops:
> 
> Unhandled fault: asynchronous external abort (0x211) at 0x00000000
> pgd = edd2c740
> [00000000] *pgd=82ec98003, *pmd=82dcd2003, *pte=00000000
> 
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>
> ---
>  kexec/arch/arm/Makefile | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/kexec/arch/arm/Makefile b/kexec/arch/arm/Makefile
> index 38137d7..60e433a 100644
> --- a/kexec/arch/arm/Makefile
> +++ b/kexec/arch/arm/Makefile
> @@ -18,6 +18,9 @@ libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%)
>  
>  arm_CPPFLAGS = -I$(srcdir)/kexec/libfdt
>  
> +# We want 64-bit file IO for kdump to work correctly on LPAE systems
> +arm_CPPFLAGS += -D_FILE_OFFSET_BITS=64
> +

It makes sense in this situation.

In "man 2 stat" and /usr/include/features.h, we can find the relevant
information.

EOVERFLOW
	pathname or fd refers to a file whose size, inode number, or number
	of blocks cannot be represented in, respectively, the types off_t, ino_t,
	or blkcnt_t.  This error can occur when, for example, an  application
	compiled  on  a  32-bit  platform  without -D_FILE_OFFSET_BITS=64 calls
	stat() on a file whose size exceeds (1<<31)-1 bytes.

Ack this patch.

Acked-by: Baoquan He <bhe at redhat.com>

Baoquan
Thanks


From bhe at redhat.com  Sat May 28 04:33:54 2016
From: bhe at redhat.com (Baoquan He)
Date: Sat, 28 May 2016 19:33:54 +0800
Subject: [PATCH kexec-tools 07/32] kexec: fix warnings caused by
 selecting 64-bit file IO on 32-bit platforms
In-Reply-To: <E1axXSV-0004hZ-CH@e0050434b2927.dyn.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSV-0004hZ-CH@e0050434b2927.dyn.arm.linux.org.uk>
Message-ID: <20160528113354.GB2429@x1.redhat.com>

On 05/03/16 at 11:21am, Russell King wrote:
> Fix warnings caused by selecting 64-bit file IO on 32-bit platforms.
> 
> kexec/kexec.c:710:2: warning: format '%lx' expects argument of type 'long unsigned int', but argument 4 has type 'off_t' [-Wformat]
> kexec/zlib.c:63:4: warning: format '%ld' expects argument of type 'long int', but argument 4 has type 'off_t' [-Wformat]
> kexec/kexec-uImage.c:85:3: warning: format '%ld' expects argument of type 'long
> int', but argument 2 has type 'off_t' [-Wformat]
> 
> Signed-off-by: Russell King <rmk at arm.linux.org.uk>
> ---
>  kexec/kexec-uImage.c | 3 ++-
>  kexec/kexec.c        | 4 ++--
>  kexec/zlib.c         | 4 ++--
>  3 files changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/kexec/kexec-uImage.c b/kexec/kexec-uImage.c
> index 9df601b..5e24629 100644
> --- a/kexec/kexec-uImage.c
> +++ b/kexec/kexec-uImage.c
> @@ -82,7 +82,8 @@ int uImage_probe(const unsigned char *buf, off_t len, unsigned int arch)
>  	if (be32_to_cpu(header.ih_size) > len - sizeof(header)) {
>  		printf("uImage header claims that image has %d bytes\n",
>  				be32_to_cpu(header.ih_size));
> -		printf("we read only %ld bytes.\n", len - sizeof(header));
> +		printf("we read only %lld bytes.\n",
> +		       (long long)len - sizeof(header));

With "D_FILE_OFFSET_BITS=64" adding, off_t is identical to off64_t, is
that necessary to still take a type conversion here?

Is that OK to be like this:

		printf("we read only %lld bytes.\n", len - sizeof(header));



From hdegoede at redhat.com  Sat May 28 06:42:24 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Sat, 28 May 2016 15:42:24 +0200
Subject: [linux-sunxi] Re: [PATCH] regulator: axp20x: Add support for the
 (external) drivebus regulator
In-Reply-To: <CAGb2v67iPsUAG=Sgk8z-G3KjVb4WoMUutUPKdQ9s=OOCk_jgqg@mail.gmail.com>
References: <1463248545-16543-1-git-send-email-hdegoede@redhat.com>
 <CAGb2v67iPsUAG=Sgk8z-G3KjVb4WoMUutUPKdQ9s=OOCk_jgqg@mail.gmail.com>
Message-ID: <4fe76e77-6743-fa95-2d19-2625316420bc@redhat.com>

Hi,

On 16-05-16 19:06, Chen-Yu Tsai wrote:
> Hi,
>
> On Sun, May 15, 2016 at 1:55 AM, Hans de Goede <hdegoede at redhat.com> wrote:
>> The axp20x pmics have 2 power inputs, one called ACIN which is intended
>> for to be supplied via a powerbarrel on the board and one called VBUS
>> which is intended to be supplied via an otg connector.
>>
>> In the VBUS case the pmic needs to know if the board is supplying power
>> to the otg connector, because then it should not take any power from
>> its VBUS pin. The axp209 pmic has a N_VBUSEN input pin via which the
>> board can signal to the pmic whether the board is supplying power to the
>> otg connector or not.
>>
>> On the axp221/axp223 this pin can alternatively be used as an output
>> which controls an external regulator which (optionally) supplies
>> power to the otg connector from the board. When the pin is used as
>> output it is called DRIVEBUS in the datasheet.
>
> The datasheet actually calls it DRIVEVBUS. DRIVEBUS seems to be some
> typo Allwinner has in their code.

Fixed for v2.

>> This commit adds support for the DRIVEBUS pin as an extra pmic
>> controlled regulator. Since this is optional a new x-powers,drivebus dt
>> property is added. When this is present the misc-control register is
>> written to change the N_VBUSEN input pin to DRIVEBUS output pin mode and
>> the extra drivebus regulator is registered with the regulator subsystem.
>>
>> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
>> ---
>>  Documentation/devicetree/bindings/mfd/axp20x.txt |  5 ++++
>>  drivers/regulator/axp20x-regulator.c             | 30 ++++++++++++++++++++++++
>>  2 files changed, 35 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
>> index d20b103..7a88479 100644
>> --- a/Documentation/devicetree/bindings/mfd/axp20x.txt
>> +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
>> @@ -22,6 +22,11 @@ Optional properties:
>>                       AXP152/20X: range:  750-1875, Default: 1.5 MHz
>>                       AXP22X/80X: range: 1800-4050, Default: 3   MHz
>>
>> +- x-powers,drivebus: axp221 / axp223 only boolean, set this when the N_VBUSEN
>> +                  pin is used as an output pin to control an external regulator
>> +                  to drive the OTG VBus, rather then as an input pin which
>> +                  signals whether the board is driving OTG VBus or not.
>> +
>
> You should also add it to the regulators table further down in the binding.
> And, as Rob mentioned, x-powers,drive-vbus-en (or drivevbus-en) is better
> for a boolean property.

Both fixed for v2.

>>  - <input>-supply: a phandle to the regulator supply node. May be omitted if
>>                   inputs are unregulated, such as using the IPSOUT output
>>                   from the PMIC.
>> diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
>> index 514a5e8..2422ddd 100644
>> --- a/drivers/regulator/axp20x-regulator.c
>> +++ b/drivers/regulator/axp20x-regulator.c
>> @@ -36,6 +36,8 @@
>>
>>  #define AXP20X_FREQ_DCDC_MASK          0x0f
>>
>> +#define AXP22X_MISC_N_VBUSEN_FUNC      BIT(4)
>> +
>>  #define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,   \
>>                     _vmask, _ereg, _emask, _enable_val, _disable_val)           \
>>         [_family##_##_id] = {                                                   \
>> @@ -230,6 +232,18 @@ static const struct regulator_desc axp22x_regulators[] = {
>>         AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
>>  };
>>
>> +static const struct regulator_desc axp22x_drivebus_regulator = {
>> +       .name           = "drivebus",
>> +       .supply_name    = "ips",
>
> Given that you are approximating a gpio (in this case, the
> N_VBUSEN/DRIVEVBUS pin)
> controlled fixed voltage regulator, it would be better if you could:
>
> a) have some way to specify the output voltage, so it looks like a fixed voltage
>    regulator that can be turned on/off.

This is fixed by your suggestion b) actually, if no get_voltage* ops are specified,
it will inherit the voltage of it supply.

> And
>
> b) have a separate supply name for this so it properly propagates enable/disable
>    calls. It would also pass the upstream voltage, thus behaving like a switch
>    you intended with the axp20x_ops_sw below.

Ack, fixed for v2.

Thanks for the review.

Regards,

Hans


From linux at armlinux.org.uk  Sat May 28 06:53:20 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Sat, 28 May 2016 14:53:20 +0100
Subject: [PATCH kexec-tools 07/32] kexec: fix warnings caused by
 selecting 64-bit file IO on 32-bit platforms
In-Reply-To: <20160528113354.GB2429@x1.redhat.com>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSV-0004hZ-CH@e0050434b2927.dyn.arm.linux.org.uk>
 <20160528113354.GB2429@x1.redhat.com>
Message-ID: <20160528135320.GQ19428@n2100.arm.linux.org.uk>

On Sat, May 28, 2016 at 07:33:54PM +0800, Baoquan He wrote:
> On 05/03/16 at 11:21am, Russell King wrote:
> > diff --git a/kexec/kexec-uImage.c b/kexec/kexec-uImage.c
> > index 9df601b..5e24629 100644
> > --- a/kexec/kexec-uImage.c
> > +++ b/kexec/kexec-uImage.c
> > @@ -82,7 +82,8 @@ int uImage_probe(const unsigned char *buf, off_t len, unsigned int arch)
> >  	if (be32_to_cpu(header.ih_size) > len - sizeof(header)) {
> >  		printf("uImage header claims that image has %d bytes\n",
> >  				be32_to_cpu(header.ih_size));
> > -		printf("we read only %ld bytes.\n", len - sizeof(header));
> > +		printf("we read only %lld bytes.\n",
> > +		       (long long)len - sizeof(header));
> 
> With "D_FILE_OFFSET_BITS=64" adding, off_t is identical to off64_t, is
> that necessary to still take a type conversion here?

The printf format specifies an argument of "long long" type, which is
defined as a data type of at least 64-bits wide.  So, it's more
correct to cast to long long, rather than relying on off64_t being
the same size as long long.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From linux at roeck-us.net  Sat May 28 14:17:05 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Sat, 28 May 2016 14:17:05 -0700
Subject: pxa_defconfig runtime failures due to 'ARM: pxa: activate pinctrl
 for device-tree machines'
In-Reply-To: <87a8jah9ok.fsf@belgarion.home>
References: <20160527202715.GA4841@roeck-us.net>
 <87a8jah9ok.fsf@belgarion.home>
Message-ID: <574A0AD1.9000304@roeck-us.net>

On 05/28/2016 01:24 AM, Robert Jarzmik wrote:
> Guenter Roeck <linux at roeck-us.net> writes:
>
>> Hi,
>>
>> your mainline commit f806dac5938b ("ARM: pxa: activate pinctrl for device-tree
>> machines") causes various non-devicetree systems to fail with the following
>> error messages when running a pxa_defconfig image.
> Ah yes, you're right.
>
>>
>> During boot:
>>
>> Can't request reset_gpio
>>
>> At reboot:
>>
>> reboot: Restarting system
>> ------------[ cut here ]------------
>> kernel BUG at arch/arm/mach-pxa/reset.c:59!
>> ...
>>
>> Added logging shows that the error seen when trying to request the reset gpio
>> is -EPROBE_DEFER, and that the pxa gpio driver is not instantiated.
>>
>> This is seen when attempting to run akita, borzoi, spitz, terrier, or tosa
>> in qemu with pxa_defconfig. Reverting your patch fixes the problem.
>>
>> Is this on purpose ?
> Well no :)
> The real reason behind is that gpio handling for pxa in its current state cannot
> be built for _both_ a devicetree machine (ie. pxa-dt.c) and a non devicetree
> machine (ie. corgi, tosa, ...).
>
> This is turn is because for devicetree a pinctrl is enforced for the machine,
> and a pinctrl driver is required. If it's not available, pxa_gpio_request()
> fails on pinctrl_request_gpio() and returns -EPROBE_DEFER.
>
> Now the true chicken and egg problem is than machine files,
> ie. arch/arm/mach-pxa/xxx.c are using gpio before the drivers are probed, in the
> init_machine() function, and that's why pinctrl/gpio for legacy machine files is
> a bit difficult.
>
>> Unless I am missing something, it effectively means that
>> pxa_defconfig no longer works for pxa3xx systems, since those do not support
>> devicetree (or at least there is no devicetree file which includes
>> pxa3xx.dtsi).
> I'd rather say that pxa_defconfig doesn't work anymore on any legacy system.
> Its first purpose was to ensure compilation coverage of all legacy pxa systems.
> Its second one was to have a single kernel bootable on all legacy pxa systems.
>
> Therefore, would you tell me if the patch in [1] fixes your issue ?
>

Yes, it does. It is actually the workaround I deployed for my test builds,
since I thought that the change was on purpose.

Thanks,
Guenter



From okaya at codeaurora.org  Sat May 28 15:01:11 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sat, 28 May 2016 18:01:11 -0400
Subject: [PATCH V6 1/8] vfio: platform: move reset call to a common function
In-Reply-To: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
References: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1464472878-27176-2-git-send-email-okaya@codeaurora.org>

The reset call sequence seems to replicate itself multiple times
across the file. Grouping them together for maintenance reasons.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 drivers/vfio/platform/vfio_platform_common.c | 30 +++++++++++++---------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 08fd7c2..3e2a7c0 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -134,6 +134,17 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
 	kfree(vdev->regions);
 }
 
+static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
+{
+	if (vdev->of_reset) {
+		dev_info(vdev->device, "reset\n");
+		return vdev->of_reset(vdev);
+	}
+
+	dev_warn(vdev->device, "no reset function found!\n");
+	return -EINVAL;
+}
+
 static void vfio_platform_release(void *device_data)
 {
 	struct vfio_platform_device *vdev = device_data;
@@ -141,12 +152,7 @@ static void vfio_platform_release(void *device_data)
 	mutex_lock(&driver_lock);
 
 	if (!(--vdev->refcnt)) {
-		if (vdev->of_reset) {
-			dev_info(vdev->device, "reset\n");
-			vdev->of_reset(vdev);
-		} else {
-			dev_warn(vdev->device, "no reset function found!\n");
-		}
+		vfio_platform_call_reset(vdev);
 		vfio_platform_regions_cleanup(vdev);
 		vfio_platform_irq_cleanup(vdev);
 	}
@@ -175,12 +181,7 @@ static int vfio_platform_open(void *device_data)
 		if (ret)
 			goto err_irq;
 
-		if (vdev->of_reset) {
-			dev_info(vdev->device, "reset\n");
-			vdev->of_reset(vdev);
-		} else {
-			dev_warn(vdev->device, "no reset function found!\n");
-		}
+		vfio_platform_call_reset(vdev);
 	}
 
 	vdev->refcnt++;
@@ -312,10 +313,7 @@ static long vfio_platform_ioctl(void *device_data,
 		return ret;
 
 	} else if (cmd == VFIO_DEVICE_RESET) {
-		if (vdev->of_reset)
-			return vdev->of_reset(vdev);
-		else
-			return -EINVAL;
+		return vfio_platform_call_reset(vdev);
 	}
 
 	return -ENOTTY;
-- 
1.8.2.1



From okaya at codeaurora.org  Sat May 28 15:01:10 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sat, 28 May 2016 18:01:10 -0400
Subject: [PATCH V6 0/8] vfio, platform: add ACPI support
Message-ID: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>

The device tree code checks for the presence of a reset driver and calls
the of_reset function pointer by looking up the reset driver as a module.

ACPI defines _RST method to perform device level reset. After the _RST
method is executed, the OS can resume using the device.

This patch checks the presence of _RST method and calls the _RST
method when reset is requested.

Changes from V5:
1. Handle reset function call failures in open and release (new patch).
2. Bring out extra debug information when failure happens (new patch).
3. Address review comments from Eric in ACPI _RST patch.

Sinan Kaya (8):
  vfio: platform: move reset call to a common function
  vfio: platform: determine reset capability
  vfio: platform: add support for ACPI probe
  vfio: platform: add extra debug info argument to call reset
  vfio: platform: call _RST method when using ACPI
  vfio, platform: make reset driver a requirement by default
  vfio: platform: check reset call return code during open
  vfio: platform: check reset call return code during release

 drivers/vfio/platform/vfio_amba.c             |   5 +
 drivers/vfio/platform/vfio_platform.c         |   5 +
 drivers/vfio/platform/vfio_platform_common.c  | 169 ++++++++++++++++++++++----
 drivers/vfio/platform/vfio_platform_private.h |   2 +
 4 files changed, 159 insertions(+), 22 deletions(-)

-- 
1.8.2.1



From okaya at codeaurora.org  Sat May 28 15:01:12 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sat, 28 May 2016 18:01:12 -0400
Subject: [PATCH V6 2/8] vfio: platform: determine reset capability
In-Reply-To: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
References: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1464472878-27176-3-git-send-email-okaya@codeaurora.org>

Creating a new function to determine if this driver supports reset
function or not. This is an attempt to abstract device tree calls
from the rest of the code.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 drivers/vfio/platform/vfio_platform_common.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 3e2a7c0..6be92c3 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -49,6 +49,11 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 	return reset_fn;
 }
 
+static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
+{
+	return vdev->of_reset ? true : false;
+}
+
 static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
 	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
@@ -214,7 +219,7 @@ static long vfio_platform_ioctl(void *device_data,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		if (vdev->of_reset)
+		if (vfio_platform_has_reset(vdev))
 			vdev->flags |= VFIO_DEVICE_FLAGS_RESET;
 		info.flags = vdev->flags;
 		info.num_regions = vdev->num_regions;
-- 
1.8.2.1



From okaya at codeaurora.org  Sat May 28 15:01:13 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sat, 28 May 2016 18:01:13 -0400
Subject: [PATCH V6 3/8] vfio: platform: add support for ACPI probe
In-Reply-To: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
References: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1464472878-27176-4-git-send-email-okaya@codeaurora.org>

The code is using the compatible DT string to associate a reset driver
with the actual device itself. The compatible string does not exist on
ACPI based systems. HID is the unique identifier for a device driver
instead.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_platform_common.c  | 57 ++++++++++++++++++++++++---
 drivers/vfio/platform/vfio_platform_private.h |  1 +
 2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 6be92c3..fbf4565 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/acpi.h>
 #include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -49,6 +50,37 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 	return reset_fn;
 }
 
+#ifdef CONFIG_ACPI
+static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
+				    struct device *dev)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	if (!adev) {
+		pr_err("VFIO: ACPI companion device not found for %s\n",
+			vdev->name);
+		return -ENODEV;
+	}
+
+	vdev->acpihid = acpi_device_hid(adev);
+	if (!vdev->acpihid) {
+		pr_err("VFIO: cannot find ACPI HID for %s\n",
+		       vdev->name);
+		return -ENODEV;
+	}
+	return 0;
+}
+#else
+static inline int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
+					   struct device *dev)
+{
+	return -ENOENT;
+}
+#endif
+
 static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
 {
 	return vdev->of_reset ? true : false;
@@ -547,6 +579,20 @@ static const struct vfio_device_ops vfio_platform_ops = {
 	.mmap		= vfio_platform_mmap,
 };
 
+int vfio_platform_of_probe(struct vfio_platform_device *vdev,
+			   struct device *dev)
+{
+	int ret;
+
+	ret = device_property_read_string(dev, "compatible",
+					  &vdev->compat);
+	if (ret)
+		pr_err("VFIO: cannot retrieve compat for %s\n",
+			vdev->name);
+
+	return ret;
+}
+
 int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 			       struct device *dev)
 {
@@ -556,11 +602,12 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 	if (!vdev)
 		return -EINVAL;
 
-	ret = device_property_read_string(dev, "compatible", &vdev->compat);
-	if (ret) {
-		pr_err("VFIO: cannot retrieve compat for %s\n", vdev->name);
-		return -EINVAL;
-	}
+	ret = vfio_platform_acpi_probe(vdev, dev);
+	if (ret)
+		ret = vfio_platform_of_probe(vdev, dev);
+
+	if (ret)
+		return ret;
 
 	vdev->device = dev;
 
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 71ed7d1..ba9e4f8 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -58,6 +58,7 @@ struct vfio_platform_device {
 	struct mutex			igate;
 	struct module			*parent_module;
 	const char			*compat;
+	const char			*acpihid;
 	struct module			*reset_module;
 	struct device			*device;
 
-- 
1.8.2.1



From okaya at codeaurora.org  Sat May 28 15:01:14 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sat, 28 May 2016 18:01:14 -0400
Subject: [PATCH V6 4/8] vfio: platform: add extra debug info argument to call
 reset
In-Reply-To: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
References: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1464472878-27176-5-git-send-email-okaya@codeaurora.org>

Getting ready to bring out extra debug information to the caller
so that more verbose information can be printed when an error is
observed.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_platform_common.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index fbf4565..e7ce2c2 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -171,7 +171,8 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
 	kfree(vdev->regions);
 }
 
-static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
+static int vfio_platform_call_reset(struct vfio_platform_device *vdev,
+				    const char **extra_dbg)
 {
 	if (vdev->of_reset) {
 		dev_info(vdev->device, "reset\n");
@@ -189,7 +190,7 @@ static void vfio_platform_release(void *device_data)
 	mutex_lock(&driver_lock);
 
 	if (!(--vdev->refcnt)) {
-		vfio_platform_call_reset(vdev);
+		vfio_platform_call_reset(vdev, NULL);
 		vfio_platform_regions_cleanup(vdev);
 		vfio_platform_irq_cleanup(vdev);
 	}
@@ -218,7 +219,7 @@ static int vfio_platform_open(void *device_data)
 		if (ret)
 			goto err_irq;
 
-		vfio_platform_call_reset(vdev);
+		vfio_platform_call_reset(vdev, NULL);
 	}
 
 	vdev->refcnt++;
@@ -350,7 +351,7 @@ static long vfio_platform_ioctl(void *device_data,
 		return ret;
 
 	} else if (cmd == VFIO_DEVICE_RESET) {
-		return vfio_platform_call_reset(vdev);
+		return vfio_platform_call_reset(vdev, NULL);
 	}
 
 	return -ENOTTY;
-- 
1.8.2.1



From okaya at codeaurora.org  Sat May 28 15:01:18 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sat, 28 May 2016 18:01:18 -0400
Subject: [PATCH V6 8/8] vfio: platform: check reset call return code during
 release
In-Reply-To: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
References: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1464472878-27176-9-git-send-email-okaya@codeaurora.org>

Release call is ignoring the return code from reset call and can
potentially continue even though reset call failed.

If reset_required module parameter is set, this patch is going
to validate the return code and will cause stack dump with
WARN_ON and warn the user of failure.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_platform_common.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 962cfb1..bb05ca0 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -243,7 +243,15 @@ static void vfio_platform_release(void *device_data)
 	mutex_lock(&driver_lock);
 
 	if (!(--vdev->refcnt)) {
-		vfio_platform_call_reset(vdev, NULL);
+		const char *extra_dbg = NULL;
+		int ret;
+
+		ret = vfio_platform_call_reset(vdev, &extra_dbg);
+		if (ret && vdev->reset_required) {
+			dev_warn(vdev->device, "reset driver is required and reset call failed in release (%d) %s\n",
+				 ret, extra_dbg ? extra_dbg : "");
+			WARN_ON(1);
+		}
 		vfio_platform_regions_cleanup(vdev);
 		vfio_platform_irq_cleanup(vdev);
 	}
-- 
1.8.2.1



From okaya at codeaurora.org  Sat May 28 15:01:16 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sat, 28 May 2016 18:01:16 -0400
Subject: [PATCH V6 6/8] vfio,
 platform: make reset driver a requirement by default
In-Reply-To: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
References: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1464472878-27176-7-git-send-email-okaya@codeaurora.org>

The code was allowing platform devices to be used without a supporting
VFIO reset driver. The hardware can be left in some inconsistent state
after a guest machine abort.

The reset driver will put the hardware back to safe state and disable
interrupts before returning the control back to the host machine.

Adding a new reset_required kernel module option to AMBA and platform
VFIO drivers with a default value of true.

New requirements are:
1. A reset function needs to be implemented by the corresponding driver
via DT/ACPI.
2. The reset function needs to be discovered via DT/ACPI.

The probe of the driver will fail if any of the above conditions are
not satisfied.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_amba.c             |  5 +++++
 drivers/vfio/platform/vfio_platform.c         |  5 +++++
 drivers/vfio/platform/vfio_platform_common.c  | 14 +++++++++++---
 drivers/vfio/platform/vfio_platform_private.h |  1 +
 4 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c
index a66479b..7585902 100644
--- a/drivers/vfio/platform/vfio_amba.c
+++ b/drivers/vfio/platform/vfio_amba.c
@@ -23,6 +23,10 @@
 #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis at virtualopensystems.com>"
 #define DRIVER_DESC     "VFIO for AMBA devices - User Level meta-driver"
 
+static bool reset_required = true;
+module_param(reset_required, bool, 0644);
+MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)");
+
 /* probing devices from the AMBA bus */
 
 static struct resource *get_amba_resource(struct vfio_platform_device *vdev,
@@ -68,6 +72,7 @@ static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
 	vdev->get_resource = get_amba_resource;
 	vdev->get_irq = get_amba_irq;
 	vdev->parent_module = THIS_MODULE;
+	vdev->reset_required = reset_required;
 
 	ret = vfio_platform_probe_common(vdev, &adev->dev);
 	if (ret) {
diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
index b1cc3a7..ef89146 100644
--- a/drivers/vfio/platform/vfio_platform.c
+++ b/drivers/vfio/platform/vfio_platform.c
@@ -23,6 +23,10 @@
 #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis at virtualopensystems.com>"
 #define DRIVER_DESC     "VFIO for platform devices - User Level meta-driver"
 
+static bool reset_required = true;
+module_param(reset_required, bool, 0644);
+MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)");
+
 /* probing devices from the linux platform bus */
 
 static struct resource *get_platform_resource(struct vfio_platform_device *vdev,
@@ -66,6 +70,7 @@ static int vfio_platform_probe(struct platform_device *pdev)
 	vdev->get_resource = get_platform_resource;
 	vdev->get_irq = get_platform_irq;
 	vdev->parent_module = THIS_MODULE;
+	vdev->reset_required = reset_required;
 
 	ret = vfio_platform_probe_common(vdev, &pdev->dev);
 	if (ret)
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 0ea8c26..e87ceab 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -128,10 +128,10 @@ static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
 	return vdev->of_reset ? true : false;
 }
 
-static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
+static int vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
 	if (vdev->acpihid)
-		return;
+		return vfio_platform_acpi_has_reset(vdev) ? 0 : -ENOENT;
 
 	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
 						    &vdev->reset_module);
@@ -140,6 +140,8 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 		vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
 							&vdev->reset_module);
 	}
+
+	return vdev->of_reset ? 0 : -ENOENT;
 }
 
 static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
@@ -675,7 +677,13 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 		return ret;
 	}
 
-	vfio_platform_get_reset(vdev);
+	ret = vfio_platform_get_reset(vdev);
+	if (ret && vdev->reset_required) {
+		pr_err("vfio: no reset function found for device %s\n",
+		       vdev->name);
+		iommu_group_put(group);
+		return ret;
+	}
 
 	mutex_init(&vdev->igate);
 
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index ba9e4f8..68fbc00 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -50,6 +50,7 @@ struct vfio_platform_region {
 };
 
 struct vfio_platform_device {
+	bool				reset_required;
 	struct vfio_platform_region	*regions;
 	u32				num_regions;
 	struct vfio_platform_irq	*irqs;
-- 
1.8.2.1



From okaya at codeaurora.org  Sat May 28 15:01:17 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sat, 28 May 2016 18:01:17 -0400
Subject: [PATCH V6 7/8] vfio: platform: check reset call return code during
 open
In-Reply-To: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
References: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1464472878-27176-8-git-send-email-okaya@codeaurora.org>

Open call is ignoring the return code from reset call and can
potentially continue even though reset call failed.

If reset_required module parameter is set, this patch is going
to validate the return code and will abort open if reset fails.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
---
 drivers/vfio/platform/vfio_platform_common.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index e87ceab..962cfb1 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -264,6 +264,8 @@ static int vfio_platform_open(void *device_data)
 	mutex_lock(&driver_lock);
 
 	if (!vdev->refcnt) {
+		const char *extra_dbg = NULL;
+
 		ret = vfio_platform_regions_init(vdev);
 		if (ret)
 			goto err_reg;
@@ -272,7 +274,12 @@ static int vfio_platform_open(void *device_data)
 		if (ret)
 			goto err_irq;
 
-		vfio_platform_call_reset(vdev, NULL);
+		ret = vfio_platform_call_reset(vdev, &extra_dbg);
+		if (ret && vdev->reset_required) {
+			dev_warn(vdev->device, "reset driver is required and reset call failed in open (%d) %s\n",
+				 ret, extra_dbg ? extra_dbg : "");
+			goto err_irq;
+		}
 	}
 
 	vdev->refcnt++;
-- 
1.8.2.1



From okaya at codeaurora.org  Sat May 28 15:01:15 2016
From: okaya at codeaurora.org (Sinan Kaya)
Date: Sat, 28 May 2016 18:01:15 -0400
Subject: [PATCH V6 5/8] vfio: platform: call _RST method when using ACPI
In-Reply-To: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
References: <1464472878-27176-1-git-send-email-okaya@codeaurora.org>
Message-ID: <1464472878-27176-6-git-send-email-okaya@codeaurora.org>

The device tree code checks for the presence of a reset driver and calls
the of_reset function pointer by looking up the reset driver as a module.

ACPI defines _RST method to perform device level reset. After the _RST
method is executed, the OS can resume using the device. _RST method is
expected to stop DMA transfers and IRQs.

This patch checks the presence of _RST method and calls the _RST
method when reset is requested.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
Reviewed-by: Eric Auger <eric.auger at linaro.org>
---
 drivers/vfio/platform/vfio_platform_common.c | 51 ++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index e7ce2c2..0ea8c26 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -73,21 +73,66 @@ static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
 	}
 	return 0;
 }
+
+static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev,
+					 const char **extra_dbg)
+{
+	struct device *dev = vdev->device;
+	acpi_handle handle = ACPI_HANDLE(dev);
+	acpi_status acpi_ret;
+	unsigned long long val;
+
+	acpi_ret = acpi_evaluate_integer(handle, "_RST", NULL, &val);
+	if (ACPI_FAILURE(acpi_ret)) {
+		if (extra_dbg)
+			*extra_dbg = acpi_format_exception(acpi_ret);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
+{
+	struct device *dev = vdev->device;
+	acpi_handle handle = ACPI_HANDLE(dev);
+
+	return acpi_has_method(handle, "_RST");
+}
 #else
 static inline int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
 					   struct device *dev)
 {
 	return -ENOENT;
 }
+
+static inline
+int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev,
+				  const char **extra_dbg)
+{
+	return -ENOENT;
+}
+
+static inline
+bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
+{
+	return false;
+}
 #endif
 
 static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
 {
+	if (vdev->acpihid)
+		return vfio_platform_acpi_has_reset(vdev);
+
 	return vdev->of_reset ? true : false;
 }
 
 static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
+	if (vdev->acpihid)
+		return;
+
 	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
 						    &vdev->reset_module);
 	if (!vdev->of_reset) {
@@ -99,6 +144,9 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 
 static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
 {
+	if (vdev->acpihid)
+		return;
+
 	if (vdev->of_reset)
 		module_put(vdev->reset_module);
 }
@@ -177,6 +225,9 @@ static int vfio_platform_call_reset(struct vfio_platform_device *vdev,
 	if (vdev->of_reset) {
 		dev_info(vdev->device, "reset\n");
 		return vdev->of_reset(vdev);
+	} else if (vdev->acpihid) {
+		dev_info(vdev->device, "reset\n");
+		return vfio_platform_acpi_call_reset(vdev, extra_dbg);
 	}
 
 	dev_warn(vdev->device, "no reset function found!\n");
-- 
1.8.2.1



From wens at csie.org  Sun May 29 00:04:41 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Sun, 29 May 2016 15:04:41 +0800
Subject: [PATCH 0/3] mmc: sunxi: Fix MMC DDR modes for Allwinner A80
Message-ID: <1464505484-3661-1-git-send-email-wens@csie.org>

Hi everyone,

This series fixes and re-enables eMMC HS-DDR support for Allwinner A80 SoC.
The issue with the original code was the mmc clock timings were incorrect,
and thus we had disabled HS-DDR on A80 for the previous release.

Patch 1 is a fix for mmc core. Arnd's patch to remove IS_ERR_VALUE replaced
it with an incorrect check on return values, thus blocking the code path
for HS-DDR and higher timing modes. This patch instead checks for a positive
return code, which is how mmc_select_bus_width indicates a success.

Patch 2 fixes the HS-DDR clock timings for the A80.

Patch 3 re-enables HS-DDR mode for the A80.


Regards
ChenYu

Chen-Yu Tsai (3):
  mmc: fix mmc mode selection for HS-DDR and higher
  mmc: sunxi: Fix DDR MMC timings for A80
  mmc: sunxi: Re-enable eMMC HS-DDR modes on Allwinner A80

 drivers/mmc/core/mmc.c       | 4 ++--
 drivers/mmc/host/sunxi-mmc.c | 9 ++-------
 2 files changed, 4 insertions(+), 9 deletions(-)

-- 
2.8.1



From wens at csie.org  Sun May 29 00:04:43 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Sun, 29 May 2016 15:04:43 +0800
Subject: [PATCH 2/3] mmc: sunxi: Fix DDR MMC timings for A80
In-Reply-To: <1464505484-3661-1-git-send-email-wens@csie.org>
References: <1464505484-3661-1-git-send-email-wens@csie.org>
Message-ID: <1464505484-3661-3-git-send-email-wens@csie.org>

The MMC clock timings were incorrectly calculated, when the conversion
from delay value to delay phase was done.

The 50M DDR and 50M DDR 8bit timings are off, and make eMMC DDR
unusable. Unfortunately it seems different controllers on the same SoC
have different timings. The new settings are taken from mmc2, which is
commonly used with eMMC.

The settings for the slower timing modes seem to work despite being
wrong, so leave them be.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 drivers/mmc/host/sunxi-mmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 7fc8b7aa83f0..5873dc344ab2 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -970,8 +970,8 @@ static const struct sunxi_mmc_clk_delay sun9i_mmc_clk_delays[] = {
 	[SDXC_CLK_400K]		= { .output = 180, .sample = 180 },
 	[SDXC_CLK_25M]		= { .output = 180, .sample =  75 },
 	[SDXC_CLK_50M]		= { .output = 150, .sample = 120 },
-	[SDXC_CLK_50M_DDR]	= { .output =  90, .sample = 120 },
-	[SDXC_CLK_50M_DDR_8BIT]	= { .output =  90, .sample = 120 },
+	[SDXC_CLK_50M_DDR]	= { .output =  54, .sample =  36 },
+	[SDXC_CLK_50M_DDR_8BIT]	= { .output =  72, .sample =  72 },
 };
 
 static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
-- 
2.8.1



From wens at csie.org  Sun May 29 00:04:42 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Sun, 29 May 2016 15:04:42 +0800
Subject: [PATCH 1/3] mmc: fix mmc mode selection for HS-DDR and higher
In-Reply-To: <1464505484-3661-1-git-send-email-wens@csie.org>
References: <1464505484-3661-1-git-send-email-wens@csie.org>
Message-ID: <1464505484-3661-2-git-send-email-wens@csie.org>

When IS_ERR_VALUE was removed from the mmc core code, it was replaced
with a simple not-zero check. This does not work, as the value checked
is the return value for mmc_select_bus_width, which returns the set
bit width on success. This made eMMC modes higher than HS-DDR unusable.

Fix this by checking for a positive return value instead.

Fixes: 287980e49ffc ("remove lots of IS_ERR_VALUE abuses")
Cc: Arnd Bergmann <arnd at arndb.de>
Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 drivers/mmc/core/mmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index c984321d1881..aafb73d080ca 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1276,7 +1276,7 @@ static int mmc_select_hs200(struct mmc_card *card)
 	 * switch to HS200 mode if bus width is set successfully.
 	 */
 	err = mmc_select_bus_width(card);
-	if (!err) {
+	if (err > 0) {
 		val = EXT_CSD_TIMING_HS200 |
 		      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
 		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1583,7 +1583,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	} else if (mmc_card_hs(card)) {
 		/* Select the desired bus width optionally */
 		err = mmc_select_bus_width(card);
-		if (!err) {
+		if (err > 0) {
 			err = mmc_select_hs_ddr(card);
 			if (err)
 				goto free_card;
-- 
2.8.1



From wens at csie.org  Sun May 29 00:04:44 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Sun, 29 May 2016 15:04:44 +0800
Subject: [PATCH 3/3] mmc: sunxi: Re-enable eMMC HS-DDR modes on Allwinner A80
In-Reply-To: <1464505484-3661-1-git-send-email-wens@csie.org>
References: <1464505484-3661-1-git-send-email-wens@csie.org>
Message-ID: <1464505484-3661-4-git-send-email-wens@csie.org>

Now the the HS-DDR mode clock timings have been corrected, we can
re-enable these modes on the A80.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 drivers/mmc/host/sunxi-mmc.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 5873dc344ab2..2ee4c21ec55e 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -1129,11 +1129,6 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
 				  MMC_CAP_1_8V_DDR |
 				  MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ;
 
-	/* TODO MMC DDR is not working on A80 */
-	if (of_device_is_compatible(pdev->dev.of_node,
-				    "allwinner,sun9i-a80-mmc"))
-		mmc->caps &= ~MMC_CAP_1_8V_DDR;
-
 	ret = mmc_of_parse(mmc);
 	if (ret)
 		goto error_free_dma;
-- 
2.8.1



From grinberg at compulab.co.il  Sun May 29 01:01:39 2016
From: grinberg at compulab.co.il (Igor Grinberg)
Date: Sun, 29 May 2016 11:01:39 +0300
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <CAOMZO5C3_bd-2Nz+G956+VPOcKoFaGGJK7G1p=U0yf5OyWekZA@mail.gmail.com>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
 <CAOMZO5C5goJUdHKB9a=eOv9TKDkJWxnkWWb-G7E5Kvceg6sZVg@mail.gmail.com>
 <a6cc6b85d2fa4994b3cb7e2b047f800d@rwthex-w2-b.rwth-ad.de>
 <9d7793850de942cfb578b0aeb2728f41@rwthex-s1-b.rwth-ad.de>
 <CAOMZO5C3_bd-2Nz+G956+VPOcKoFaGGJK7G1p=U0yf5OyWekZA@mail.gmail.com>
Message-ID: <574AA1E3.4070300@compulab.co.il>

On 05/27/2016 01:20 AM, Fabio Estevam wrote:
> On Thu, May 26, 2016 at 11:26 AM, Christopher Spinrath
> <christopher.spinrath at rwth-aachen.de> wrote:
> 
>> Thanks for joining this discussion. I *guess* the rationale is to share
>> the same device tree with projects that are incompatible with the GPL
>> (e.g. *BSD). Even if there is no support for a particular device/board
>> having all (or most) files dual licensed makes it easier to just pull
>> them all in.
> 
> Yes, that's correct.
> 

Thanks for the explanation.


-- 
Regards,
Igor.


From geert at linux-m68k.org  Sun May 29 02:21:38 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Sun, 29 May 2016 11:21:38 +0200
Subject: [PATCH 05/54] MAINTAINERS: Add file patterns for rockchip device
 tree bindings
In-Reply-To: <1575416.jfSztnP7S8@phil>
References: <1463907991-7916-1-git-send-email-geert@linux-m68k.org>
 <1463907991-7916-6-git-send-email-geert@linux-m68k.org>
 <1575416.jfSztnP7S8@phil>
Message-ID: <CAMuHMdVYd01kWvN5Gv_2RtPXFX2VP0nOx7Ys6=em35rk0HoOmA@mail.gmail.com>

Hi Heiko,

On Sun, May 22, 2016 at 11:27 AM, Heiko Stuebner <heiko at sntech.de> wrote:
> Am Sonntag, 22. Mai 2016, 11:05:42 schrieb Geert Uytterhoeven:
>> Submitters of device tree binding documentation may forget to CC
>> the subsystem maintainer if this is missing.
>
> The "N: rockchip" line at the bottom of the block catches this nicely
> already (also just verified with a get_maintainer.pl -f call), so I don't
> think this new more explicit line is really necessary?

Oh right, thanks! I (my bashery) only looked at direct references to
Documentation/devicetree/bindings. I complely missed the rare users of "N:".

Will drop this patch.

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 zourongrong at gmail.com  Sun May 29 02:40:48 2016
From: zourongrong at gmail.com (Rongrong Zou)
Date: Sun, 29 May 2016 17:40:48 +0800
Subject: [path v2 0/7] Add DRM driver for Hisilicon Hibmc
Message-ID: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>

This patch set adds a new drm driver for Hisilicon Hibmc. Hibmc is a
base board management controller, usually it is used on server for
Out-of-band management purpose. In this patch set, we just support basic
function for Hibmc display subsystem. Hibmc display subsystem is connected
to host CPU by PCIe as blow:

+----------+       +----------+
|          | PCIe  |  Hibmc   |
|host CPU( |<----->| display  |
|arm64,x86)|       |subsystem |
+----------+       +----------+

Hardware Detail for Hibmc display subsystem
-----------

  The display subsystem of Hibmc is show as bellow:
  +----+      +----+      +----+     +--------+
  |    |      |    |      |    |     |        |
  | FB |----->| DE |----->|VDAC|---->|external|
  |    |      |    |      |    |     | VGA    |
  +----+      +----+      +----+     +--------+

  -DE(Display Engine) is the display controller.
  -VDAC(Video Digital-to-Analog converter) converts the RGB diaital data
  stream from DE to VGA analog signals.

Change History
------------

Changes in v2:
  -Remove self-defined macros for bit operations.
  -Remove unused register.
  -Replace those deprecated functions with new version of them.
  -use drm_connector_register_all() to register connector after
   drm_dev_register().

The patch v1 is at
https://lists.freedesktop.org/archives/dri-devel/2016-February/101921.html
Sorry for too late sending.


Rongrong Zou (7):
  idrm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
  drm/hisilicon/hibmc: Add plane for DE
  drm/hisilicon/hibmc: Add crtc for DE
  drm/hisilicon/hibmc: Add encoder for VDAC
  drm/hisilicon/hibmc: Add connector for VDAC
  drm/hisilicon/hibmc: Add support for frame buffer
  drm/hisilicon/hibmc: Add maintainer for Hibmc DRM

 MAINTAINERS                                       |   7 +
 drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
 drivers/gpu/drm/hisilicon/Makefile                |   3 +-
 drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
 drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c    | 477 ++++++++++++++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h    |  29 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 399 ++++++++++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  64 +++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 286 +++++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 ++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c  | 174 ++++++++
 14 files changed, 1789 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c

-- 
1.9.1



From zourongrong at gmail.com  Sun May 29 02:40:49 2016
From: zourongrong at gmail.com (Rongrong Zou)
Date: Sun, 29 May 2016 17:40:49 +0800
Subject: [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master
 driver
In-Reply-To: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
Message-ID: <1464514855-108050-2-git-send-email-zourongrong@gmail.com>

Add DRM master driver for Hisilicon Hibmc SoC which used for
Out-of-band management. Blow is the general hardware connection,
both the Hibmc and the host CPU are on the same mother board.

+----------+       +----------+
|          | PCIe  |  Hibmc   |
|host CPU( |<----->| display  |
|arm64,x86)|       |subsystem |
+----------+       +----------+

Signed-off-by: Rongrong Zou <zourongrong at gmail.com>
Signed-off-by: Jianhua Li <lijianhua at huawei.com>
---
 drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
 drivers/gpu/drm/hisilicon/Makefile                |   3 +-
 drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
 drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 307 ++++++++++++++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  39 +++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 +++++++++++++++
 9 files changed, 699 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h

diff --git a/drivers/gpu/drm/hisilicon/Kconfig b/drivers/gpu/drm/hisilicon/Kconfig
index 558c61b..2fd2724 100644
--- a/drivers/gpu/drm/hisilicon/Kconfig
+++ b/drivers/gpu/drm/hisilicon/Kconfig
@@ -2,4 +2,5 @@
 # hisilicon drm device configuration.
 # Please keep this list sorted alphabetically
 
+source "drivers/gpu/drm/hisilicon/hibmc/Kconfig"
 source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
diff --git a/drivers/gpu/drm/hisilicon/Makefile b/drivers/gpu/drm/hisilicon/Makefile
index e3f6d49..4d7185c 100644
--- a/drivers/gpu/drm/hisilicon/Makefile
+++ b/drivers/gpu/drm/hisilicon/Makefile
@@ -2,4 +2,5 @@
 # Makefile for hisilicon drm drivers.
 # Please keep this list sorted alphabetically
 
-obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
+obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/
+obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
\ No newline at end of file
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
new file mode 100644
index 0000000..1e7810d
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
@@ -0,0 +1,13 @@
+config DRM_HISI_HIBMC
+	tristate "DRM Support for Hisilicon Hibmc"
+	depends on DRM && PCI
+	select DRM_KMS_HELPER
+	select DRM_KMS_FB_HELPER
+	select DRM_GEM_CMA_HELPER
+	select DRM_KMS_CMA_HELPER
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	help
+	  Choose this option if you have a Hisilicon Hibmc soc chipset.
+	  If M is selected the module will be called hibmc-drm.
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
new file mode 100644
index 0000000..533f9ed
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -0,0 +1,4 @@
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
+
+obj-$(CONFIG_DRM_HISI_HIBMC)	+=hibmc-drm.o
+#obj-y	+= hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
new file mode 100644
index 0000000..7eaacd8
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -0,0 +1,307 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong at huawei>
+ *	Rongrong Zou <zourongrong at gmail.com>
+ *	Jianhua Li <lijianhua at huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/console.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drmP.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+#include "hibmc_drm_power.h"
+
+static const struct file_operations hibmc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= drm_compat_ioctl,
+#endif
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+};
+
+static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+	return 0;
+}
+
+static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+}
+
+static struct drm_driver hibmc_driver = {
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET,
+	.fops			= &hibmc_fops,
+	.name			= "hibmc",
+	.desc			= "hibmc drm driver",
+	.major			= 1,
+	.minor			= 0,
+	.get_vblank_counter = drm_vblank_no_hw_counter,
+	.enable_vblank		= hibmc_enable_vblank,
+	.disable_vblank	= hibmc_disable_vblank,
+	.gem_free_object        = drm_gem_cma_free_object,
+	.gem_vm_ops		= &drm_gem_cma_vm_ops,
+	.dumb_create            = drm_gem_cma_dumb_create,
+	.dumb_map_offset        = drm_gem_cma_dumb_map_offset,
+	.dumb_destroy           = drm_gem_dumb_destroy,
+};
+
+static int hibmc_pm_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+
+	drm_kms_helper_poll_disable(drm_dev);
+
+	return 0;
+}
+
+static int hibmc_pm_resume(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+
+	drm_helper_resume_force_mode(drm_dev);
+	drm_kms_helper_poll_enable(drm_dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops hibmc_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
+				hibmc_pm_resume)
+};
+
+static const struct drm_mode_config_funcs mode_config_funcs = {
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+
+static int hibmc_hw_config(struct hibmc_drm_device *hidev)
+{
+	unsigned int reg;
+
+	/* On hardware reset, power mode 0 is default. */
+	hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+	reg |= HIBMC_CURR_GATE_DISPLAY(ON);
+	reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
+
+	hibmc_set_current_gate(hidev, reg);
+
+	/* Reset the memory controller. If the memory controller
+	 * is not reset in chip,the system might hang when sw accesses
+	 * the memory.The memory should be resetted after
+	 * changing the MXCLK.
+	 */
+	reg = readl(hidev->mmio + HIBMC_MISC_CTRL);
+	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
+	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(RESET);
+	writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
+
+	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
+	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(NORMAL);
+
+	writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
+
+	/* We can add more initialization as needed. */
+
+	return 0;
+}
+
+static int hibmc_hw_map(struct hibmc_drm_device *hidev)
+{
+	struct drm_device *dev = hidev->dev;
+	struct pci_dev *pdev = dev->pdev;
+	resource_size_t addr, size, ioaddr, iosize;
+
+	ioaddr = pci_resource_start(pdev, 1);
+	iosize = MB(2);
+
+	hidev->mmio = ioremap_nocache(ioaddr, iosize);
+
+	if (!hidev->mmio) {
+		DRM_ERROR("Cannot map mmio region\n");
+		return -ENOMEM;
+	}
+
+	addr = pci_resource_start(pdev, 0);
+	size = MB(16);
+
+	hidev->fb_map = ioremap(addr, size);
+	if (!hidev->fb_map) {
+		DRM_ERROR("Cannot map framebuffer\n");
+		return -ENOMEM;
+	}
+	hidev->fb_base = addr;
+	hidev->fb_size = size;
+
+	return 0;
+}
+
+static void hibmc_hw_fini(struct hibmc_drm_device *hidev)
+{
+	if (hidev->mmio)
+		iounmap(hidev->mmio);
+	if (hidev->fb_map)
+		iounmap(hidev->fb_map);
+}
+
+static int hibmc_hw_init(struct hibmc_drm_device *hidev)
+{
+	int ret;
+
+	ret = hibmc_hw_map(hidev);
+	if (ret)
+		return ret;
+
+	hibmc_hw_config(hidev);
+
+	return 0;
+}
+
+static int hibmc_unload(struct drm_device *dev)
+{
+	struct hibmc_drm_device *hidev = dev->dev_private;
+
+	hibmc_hw_fini(hidev);
+	dev->dev_private = NULL;
+	return 0;
+}
+
+static int hibmc_load(struct drm_device *dev, unsigned long flags)
+{
+	struct hibmc_drm_device *hidev;
+	int ret;
+
+	hidev = devm_kzalloc(dev->dev, sizeof(*hidev), GFP_KERNEL);
+	if (!hidev)
+		return -ENOMEM;
+	dev->dev_private = hidev;
+	hidev->dev = dev;
+
+	ret = hibmc_hw_init(hidev);
+	if (ret)
+		goto err;
+
+
+	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+	if (ret) {
+		DRM_ERROR("failed to initialize vblank.\n");
+		return ret;
+	}
+	/* reset all the states of crtc/plane/encoder/connector */
+	drm_mode_config_reset(dev);
+
+	return 0;
+
+err:
+	hibmc_unload(dev);
+	DRM_ERROR("failed to initialize drm driver.\n");
+	return ret;
+}
+
+
+static int hibmc_pci_probe(struct pci_dev *pdev,
+			   const struct pci_device_id *ent)
+{
+	struct drm_device *dev;
+	int ret;
+
+	dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->pdev = pdev;
+	pci_set_drvdata(pdev, dev);
+
+	ret = pci_enable_device(pdev);
+	if (ret)
+		goto err_free;
+
+	ret = hibmc_load(dev, 0);
+	if (ret)
+		goto err_disable;
+
+	ret = drm_dev_register(dev, 0);
+	if (ret)
+		goto err_unload;
+
+	return 0;
+
+err_unload:
+	hibmc_unload(dev);
+err_disable:
+	pci_disable_device(pdev);
+err_free:
+	drm_dev_unref(dev);
+
+	return ret;
+}
+
+static void hibmc_pci_remove(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+
+	drm_dev_unregister(dev);
+	hibmc_unload(dev);
+	drm_dev_unref(dev);
+}
+
+static struct pci_device_id hibmc_pci_table[] = {
+	{0x19e5, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
+};
+
+static struct pci_driver hibmc_pci_driver = {
+	.name =		"hibmc-drm",
+	.id_table =	hibmc_pci_table,
+	.probe =	hibmc_pci_probe,
+	.remove =	hibmc_pci_remove,
+	.driver.pm =    &hibmc_pm_ops,
+};
+
+static int __init hibmc_init(void)
+{
+	return pci_register_driver(&hibmc_pci_driver);
+}
+
+static void __exit hibmc_exit(void)
+{
+	return pci_unregister_driver(&hibmc_pci_driver);
+}
+
+module_init(hibmc_init);
+module_exit(hibmc_exit);
+
+MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
+MODULE_AUTHOR("RongrongZou <zourongrong at huawei.com>");
+MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
new file mode 100644
index 0000000..a072ea9
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -0,0 +1,39 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong at huawei>
+ *	Rongrong Zou <zourongrong at gmail.com>
+ *	Jianhua Li <lijianhua at huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef HIBMC_DRM_DRV_H
+#define HIBMC_DRM_DRV_H
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+struct hibmc_drm_device {
+	/* hw */
+	void __iomem   *mmio;
+	void __iomem   *fb_map;
+	unsigned long  fb_base;
+	unsigned long  fb_size;
+
+	/* drm */
+	struct drm_device  *dev;
+	bool mode_config_initialized;
+};
+
+
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
new file mode 100644
index 0000000..673be10
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
@@ -0,0 +1,91 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong at huawei>
+ *	Rongrong Zou <zourongrong at gmail.com>
+ *	Jianhua Li <lijianhua at huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/io.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+/*
+ * It can operate in one of three modes: 0, 1 or Sleep.
+ */
+void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
+				 unsigned int power_mode)
+{
+	unsigned int control_value = 0;
+	void __iomem   *mmio = hidev->mmio;
+
+	if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
+		return;
+
+	control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
+	control_value &= ~HIBMC_PW_MODE_CTL_MODE_MASK;
+
+	control_value |= HIBMC_PW_MODE_CTL_MODE(power_mode) &
+			 HIBMC_PW_MODE_CTL_MODE_MASK;
+
+
+    /* Set up other fields in Power Control Register */
+	if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP) {
+		control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
+		control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(0) &
+				 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
+	} else {
+		control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
+		control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(1) &
+				 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
+
+	}
+    /* Program new power mode. */
+	writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
+}
+
+static unsigned int hibmc_get_power_mode(struct hibmc_drm_device *hidev)
+{
+	void __iomem   *mmio = hidev->mmio;
+
+	return (readl(mmio + HIBMC_POWER_MODE_CTRL)&
+		HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
+}
+
+void hibmc_set_current_gate(struct hibmc_drm_device *hidev, unsigned int gate)
+{
+	unsigned int gate_reg;
+	unsigned int mode;
+	void __iomem   *mmio = hidev->mmio;
+
+	/* Get current power mode. */
+	mode = hibmc_get_power_mode(hidev);
+
+	switch (mode) {
+	case HIBMC_PW_MODE_CTL_MODE_MODE0:
+		gate_reg = HIBMC_MODE0_GATE;
+		break;
+
+	case HIBMC_PW_MODE_CTL_MODE_MODE1:
+		gate_reg = HIBMC_MODE1_GATE;
+		break;
+
+	default:
+		gate_reg = HIBMC_MODE0_GATE;
+		break;
+	}
+	writel(gate, mmio + gate_reg);
+}
+
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
new file mode 100644
index 0000000..39f7a17
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
@@ -0,0 +1,28 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong at huawei>
+ *	Rongrong Zou <zourongrong at gmail.com>
+ *	Jianhua Li <lijianhua at huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef HIBMC_DRM_POWER_H
+#define HIBMC_DRM_POWER_H
+
+#include "hibmc_drm_drv.h"
+
+extern void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
+				 unsigned int power_mode);
+extern void hibmc_set_current_gate(struct hibmc_drm_device *hidev,
+				   unsigned int gate);
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
new file mode 100644
index 0000000..4966c42
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
@@ -0,0 +1,214 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong at huawei>
+ *	Rongrong Zou <zourongrong at gmail.com>
+ *	Jianhua Li <lijianhua at huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef HIBMC_DRM_HW_H
+#define HIBMC_DRM_HW_H
+
+#define OFF 0
+#define ON  1
+#define DISABLE               0
+#define ENABLE                1
+
+
+
+/* register definition */
+#define HIBMC_MISC_CTRL				0x4
+
+#define HIBMC_MSCCTL_LOCALMEM_RESET(x)		((x) << 6)
+#define HIBMC_MSCCTL_LOCALMEM_RESET_MASK	0x40
+
+#define RESET                0
+#define NORMAL               1
+
+#define HIBMC_CURRENT_GATE			0x000040
+#define HIBMC_CURR_GATE_DISPLAY(x)		((x) << 2)
+#define HIBMC_CURR_GATE_DISPLAY_MASK		0x4
+
+#define HIBMC_CURR_GATE_LOCALMEM(x)		((x) << 1)
+#define HIBMC_CURR_GATE_LOCALMEM_MASK		0x2
+
+#define HIBMC_MODE0_GATE			0x000044
+#define HIBMC_MODE1_GATE			0x000048
+#define HIBMC_POWER_MODE_CTRL			0x00004C
+
+#define HIBMC_PW_MODE_CTL_OSC_INPUT(x)		((x) << 3)
+#define HIBMC_PW_MODE_CTL_OSC_INPUT_MASK	0x8
+
+#define HIBMC_PW_MODE_CTL_MODE(x)		((x) << 0)
+#define HIBMC_PW_MODE_CTL_MODE_MASK		0x03
+#define HIBMC_PW_MODE_CTL_MODE_SHIFT		0
+
+
+#define HIBMC_PW_MODE_CTL_MODE_MODE0		0
+#define HIBMC_PW_MODE_CTL_MODE_MODE1		1
+#define HIBMC_PW_MODE_CTL_MODE_SLEEP		2
+
+#define HIBMC_PANEL_PLL_CTRL			0x00005C
+#define HIBMC_CRT_PLL_CTRL			0x000060
+
+#define HIBMC_PLL_CTRL_BYPASS(x)		((x) << 18)
+#define HIBMC_PLL_CTRL_BYPASS_MASK		0x40000
+
+#define HIBMC_PLL_CTRL_POWER(x)			((x) << 17)
+#define HIBMC_PLL_CTRL_POWER_MASK		0x20000
+
+#define HIBMC_PLL_CTRL_INPUT(x)			((x) << 16)
+#define HIBMC_PLL_CTRL_INPUT_MASK		0x10000
+
+#define OSC					0
+#define TESTCLK					1
+
+#define HIBMC_PLL_CTRL_POD(x)			((x) << 14)
+#define HIBMC_PLL_CTRL_POD_MASK			0xC000
+
+#define HIBMC_PLL_CTRL_OD(x)			((x) << 12)
+#define HIBMC_PLL_CTRL_OD_MASK			0x3000
+
+#define HIBMC_PLL_CTRL_N(x)			((x) << 8)
+#define HIBMC_PLL_CTRL_N_MASK			0xF00
+
+#define HIBMC_PLL_CTRL_M(x)			((x) << 0)
+#define HIBMC_PLL_CTRL_M_MASK			0xFF
+
+
+#define HIBMC_CRT_DISP_CTL			0x80200
+
+#define HIBMC_CRT_DISP_CTL_CRTSELECT(x)		((x) << 25)
+#define HIBMC_CRT_DISP_CTL_CRTSELECT_MASK	0x2000000
+
+#define CRTSELECT_VGA                0
+#define CRTSELECT_CRT                1
+
+#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE(x)	((x) << 14)
+#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK	0x4000
+
+#define PHASE_ACTIVE_HIGH      0
+#define PHASE_ACTIVE_LOW       1
+
+#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE(x)	((x) << 13)
+#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK	0x2000
+
+#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE(x)	((x) << 12)
+#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK	0x1000
+
+#define HIBMC_CRT_DISP_CTL_TIMING(x)		((x) << 8)
+#define HIBMC_CRT_DISP_CTL_TIMING_MASK		0x100
+
+
+#define HIBMC_CRT_DISP_CTL_PLANE(x)		((x) << 2)
+#define HIBMC_CRT_DISP_CTL_PLANE_MASK		4
+
+#define HIBMC_CRT_DISP_CTL_FORMAT(x)		((x) << 0)
+#define HIBMC_CRT_DISP_CTL_FORMAT_MASK		0x03
+
+
+
+#define HIBMC_CRT_FB_ADDRESS			0x080204
+
+#define HIBMC_CRT_FB_WIDTH			0x080208
+#define HIBMC_CRT_FB_WIDTH_WIDTH(x)		((x) << 16)
+#define HIBMC_CRT_FB_WIDTH_WIDTH_MASK		0x3FFF0000
+#define HIBMC_CRT_FB_WIDTH_OFFS(x)		((x) << 0)
+#define HIBMC_CRT_FB_WIDTH_OFFS_MASK		0x3FFF
+
+
+#define HIBMC_CRT_HORZ_TOTAL			0x08020C
+#define HIBMC_CRT_HORZ_TOTAL_TOTAL(x)		((x) << 16)
+#define HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK		0xFFF0000
+
+
+#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END(x)	((x) << 0)
+#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END_MASK	0xFFF
+
+#define HIBMC_CRT_HORZ_SYNC			0x080210
+#define HIBMC_CRT_HORZ_SYNC_WIDTH(x)		((x) << 16)
+#define HIBMC_CRT_HORZ_SYNC_WIDTH_MASK		0xFF0000
+
+#define HIBMC_CRT_HORZ_SYNC_START(x)		((x) << 0)
+#define HIBMC_CRT_HORZ_SYNC_START_MASK		0xFFF
+
+#define HIBMC_CRT_VERT_TOTAL			0x080214
+#define HIBMC_CRT_VERT_TOTAL_TOTAL(x)		((x) << 16)
+#define HIBMC_CRT_VERT_TOTAL_TOTAL_MASK		0x7FFF0000
+
+#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END(x)	((x) << 0)
+#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END_MASK	0x7FF
+
+#define HIBMC_CRT_VERT_SYNC			0x080218
+#define HIBMC_CRT_VERT_SYNC_HEIGHT(x)		((x) << 16)
+#define HIBMC_CRT_VERT_SYNC_HEIGHT_MASK		0x3F0000
+
+
+#define HIBMC_CRT_VERT_SYNC_START(x)		((x) << 0)
+#define HIBMC_CRT_VERT_SYNC_START_MASK		0x7FF
+
+/* Auto Centering */
+#define HIBMC_CRT_AUTO_CENTERING_TL		0x080280
+#define HIBMC_CRT_AUTO_CENTERING_TL_TOP(x)	((x) << 16)
+#define HIBMC_CRT_AUTO_CENTERING_TL_TOP_MSK	0x7FF0000
+
+#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT(x)	((x) << 0)
+#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MSK	0x7FF
+
+#define HIBMC_CRT_AUTO_CENTERING_BR		0x080284
+#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(x)	((x) << 16)
+#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK	0x7FF0000
+
+#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x)	((x) << 0)
+#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK	0x7FF
+
+/* register to control panel output */
+#define DISPLAY_CONTROL_HISILE			0x80288
+
+/* register and values for PLL control */
+#define CRT_PLL1_HS				0x802a8
+#define CRT_PLL1_HS_25MHZ			0x23d40f02
+#define CRT_PLL1_HS_40MHZ			0x23940801
+#define CRT_PLL1_HS_65MHZ			0x23940d01
+#define CRT_PLL1_HS_78MHZ			0x23540F82
+#define CRT_PLL1_HS_74MHZ			0x23941dc2
+#define CRT_PLL1_HS_80MHZ			0x23941001
+#define CRT_PLL1_HS_80MHZ_1152			0x23540fc2
+#define CRT_PLL1_HS_108MHZ			0x23b41b01
+#define CRT_PLL1_HS_162MHZ			0x23480681
+#define CRT_PLL1_HS_148MHZ			0x23541dc2
+#define CRT_PLL1_HS_193MHZ			0x234807c1
+
+#define CRT_PLL2_HS				0x802ac
+#define CRT_PLL2_HS_25MHZ			0x206B851E
+#define CRT_PLL2_HS_40MHZ			0x30000000
+#define CRT_PLL2_HS_65MHZ			0x40000000
+#define CRT_PLL2_HS_78MHZ			0x50E147AE
+#define CRT_PLL2_HS_74MHZ			0x602B6AE7
+#define CRT_PLL2_HS_80MHZ			0x70000000
+#define CRT_PLL2_HS_108MHZ			0x80000000
+#define CRT_PLL2_HS_162MHZ			0xA0000000
+#define CRT_PLL2_HS_148MHZ			0xB0CCCCCD
+#define CRT_PLL2_HS_193MHZ			0xC0872B02
+
+/* Global macros */
+#define RGB(r, g, b) \
+( \
+	(unsigned long)(((r) << 16) | ((g) << 8) | (b)) \
+)
+
+#define PADDING(align, data) (((data) + (align) - 1) & (~((align) - 1)))
+
+#define MB(x) ((x) << 20)
+
+#endif
-- 
1.9.1



From zourongrong at gmail.com  Sun May 29 02:40:50 2016
From: zourongrong at gmail.com (Rongrong Zou)
Date: Sun, 29 May 2016 17:40:50 +0800
Subject: [path v2 2/7] drm/hisilicon/hibmc: Add plane for DE
In-Reply-To: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
Message-ID: <1464514855-108050-3-git-send-email-zourongrong@gmail.com>

Add plane funcs and helper funcs for DE.

Signed-off-by: Rongrong Zou <zourongrong at gmail.com>
Signed-off-by: Jianhua Li <lijianhua at huawei.com>
---
 drivers/gpu/drm/hisilicon/hibmc/Makefile        |   2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c  | 170 ++++++++++++++++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c |  41 +++++-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h |   3 +
 4 files changed, 214 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c

diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index 533f9ed..faa7e64 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,4 +1,4 @@
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_power.o
 
 obj-$(CONFIG_DRM_HISI_HIBMC)	+=hibmc-drm.o
 #obj-y	+= hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
new file mode 100644
index 0000000..e8e5853
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -0,0 +1,170 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong at huawei>
+ *	Rongrong Zou <zourongrong at gmail.com>
+ *	Jianhua Li <lijianhua at huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+#include "hibmc_drm_power.h"
+
+/* ---------------------------------------------------------------------- */
+
+static int hibmc_plane_prepare_fb(struct drm_plane *plane,
+		       const struct drm_plane_state *new_state)
+{
+	/* do nothing */
+	return 0;
+}
+
+static void hibmc_plane_cleanup_fb(struct drm_plane *plane,
+				   const struct drm_plane_state *old_state)
+{
+	/* do nothing */
+}
+
+static int hibmc_plane_atomic_check(struct drm_plane *plane,
+				    struct drm_plane_state *state)
+{
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_crtc_state *crtc_state;
+	u32 src_x = state->src_x >> 16;
+	u32 src_y = state->src_y >> 16;
+	u32 src_w = state->src_w >> 16;
+	u32 src_h = state->src_h >> 16;
+	int crtc_x = state->crtc_x;
+	int crtc_y = state->crtc_y;
+	u32 crtc_w = state->crtc_w;
+	u32 crtc_h = state->crtc_h;
+
+	if (!crtc || !fb)
+		return 0;
+
+	crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	if (src_w != crtc_w || src_h != crtc_h) {
+		DRM_ERROR("Scale not support!!!\n");
+		return -EINVAL;
+	}
+
+	if (src_x + src_w > fb->width ||
+	    src_y + src_h > fb->height)
+		return -EINVAL;
+
+	if (crtc_x < 0 || crtc_y < 0)
+		return -EINVAL;
+
+	if (crtc_x + crtc_w > crtc_state->adjusted_mode.hdisplay ||
+	    crtc_y + crtc_h > crtc_state->adjusted_mode.vdisplay)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void hibmc_plane_atomic_update(struct drm_plane *plane,
+				      struct drm_plane_state *old_state)
+{
+	struct drm_plane_state	*state	= plane->state;
+	u32 reg;
+	unsigned int line_l;
+	struct hibmc_drm_device *hidev =
+		(struct hibmc_drm_device *)plane->dev->dev_private;
+
+	/* now just support one plane */
+	writel(0, hidev->mmio + HIBMC_CRT_FB_ADDRESS);
+	reg = state->fb->width * (state->fb->bits_per_pixel >> 3);
+	/* now line_pad is 16 */
+	reg = PADDING(16, reg);
+
+	line_l = state->fb->width * state->fb->bits_per_pixel / 8;
+	line_l = PADDING(16, line_l);
+	writel((HIBMC_CRT_FB_WIDTH_WIDTH(reg) & HIBMC_CRT_FB_WIDTH_WIDTH_MASK) |
+	       (HIBMC_CRT_FB_WIDTH_OFFS(line_l) & HIBMC_CRT_FB_WIDTH_OFFS_MASK),
+	       hidev->mmio + HIBMC_CRT_FB_WIDTH);
+
+	/* SET PIXEL FORMAT */
+	reg = readl(hidev->mmio + HIBMC_CRT_DISP_CTL);
+	reg = reg & ~HIBMC_CRT_DISP_CTL_FORMAT_MASK;
+	reg = reg | (HIBMC_CRT_DISP_CTL_FORMAT(state->fb->bits_per_pixel >> 4) &
+		     HIBMC_CRT_DISP_CTL_FORMAT_MASK);
+	writel(reg, hidev->mmio + HIBMC_CRT_DISP_CTL);
+}
+
+static void hibmc_plane_atomic_disable(struct drm_plane *plane,
+				       struct drm_plane_state *old_state)
+{
+}
+
+static const u32 channel_formats1[] = {
+	DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888, DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888
+};
+
+static struct drm_plane_funcs hibmc_plane_funcs = {
+	.update_plane	= drm_atomic_helper_update_plane,
+	.disable_plane	= drm_atomic_helper_disable_plane,
+	.set_property = drm_atomic_helper_plane_set_property,
+	.destroy = drm_plane_cleanup,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static const struct drm_plane_helper_funcs hibmc_plane_helper_funcs = {
+	.prepare_fb = hibmc_plane_prepare_fb,
+	.cleanup_fb = hibmc_plane_cleanup_fb,
+	.atomic_check = hibmc_plane_atomic_check,
+	.atomic_update = hibmc_plane_atomic_update,
+	.atomic_disable = hibmc_plane_atomic_disable,
+};
+
+int hibmc_plane_init(struct hibmc_drm_device *hidev)
+{
+	struct drm_device *dev = hidev->dev;
+	struct drm_plane *plane = &hidev->plane;
+	int ret = 0;
+
+	/*
+	 * plane init
+	 * TODO: Now only support primary plane, overlay planes
+	 * need to do.
+	 */
+	ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs,
+				       channel_formats1,
+				       ARRAY_SIZE(channel_formats1),
+				       DRM_PLANE_TYPE_PRIMARY,
+				       NULL);
+	if (ret) {
+		DRM_ERROR("fail to init plane!!!\n");
+		return ret;
+	}
+
+	drm_plane_helper_add(plane, &hibmc_plane_helper_funcs);
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 7eaacd8..794250a 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -51,7 +51,8 @@ static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
 }
 
 static struct drm_driver hibmc_driver = {
-	.driver_features	= DRIVER_GEM | DRIVER_MODESET,
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET |
+						DRIVER_ATOMIC,
 	.fops			= &hibmc_fops,
 	.name			= "hibmc",
 	.desc			= "hibmc drm driver",
@@ -98,6 +99,40 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
 	.atomic_commit = drm_atomic_helper_commit,
 };
 
+static int hibmc_kms_init(struct hibmc_drm_device *hidev)
+{
+	int ret;
+
+	drm_mode_config_init(hidev->dev);
+	hidev->mode_config_initialized = true;
+
+	hidev->dev->mode_config.min_width = 0;
+	hidev->dev->mode_config.min_height = 0;
+	hidev->dev->mode_config.max_width = 1920;
+	hidev->dev->mode_config.max_height = 1440;
+
+	hidev->dev->mode_config.fb_base = hidev->fb_base;
+	hidev->dev->mode_config.preferred_depth = 24;
+	hidev->dev->mode_config.prefer_shadow = 0;
+
+	hidev->dev->mode_config.funcs = (void *)&mode_config_funcs;
+
+	ret = hibmc_plane_init(hidev);
+	if (ret) {
+		DRM_ERROR("fail to init plane!!!\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void hibmc_kms_fini(struct hibmc_drm_device *hidev)
+{
+	if (hidev->mode_config_initialized) {
+		drm_mode_config_cleanup(hidev->dev);
+		hidev->mode_config_initialized = false;
+	}
+}
 
 static int hibmc_hw_config(struct hibmc_drm_device *hidev)
 {
@@ -190,6 +225,7 @@ static int hibmc_unload(struct drm_device *dev)
 {
 	struct hibmc_drm_device *hidev = dev->dev_private;
 
+	hibmc_kms_fini(hidev);
 	hibmc_hw_fini(hidev);
 	dev->dev_private = NULL;
 	return 0;
@@ -210,6 +246,9 @@ static int hibmc_load(struct drm_device *dev, unsigned long flags)
 	if (ret)
 		goto err;
 
+	ret = hibmc_kms_init(hidev);
+	if (ret)
+		goto err;
 
 	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
 	if (ret) {
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index a072ea9..6c7985d 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -32,8 +32,11 @@ struct hibmc_drm_device {
 
 	/* drm */
 	struct drm_device  *dev;
+	struct drm_plane plane;
 	bool mode_config_initialized;
 };
 
+int hibmc_plane_init(struct hibmc_drm_device *hidev);
+
 
 #endif
-- 
1.9.1



From zourongrong at gmail.com  Sun May 29 02:40:51 2016
From: zourongrong at gmail.com (Rongrong Zou)
Date: Sun, 29 May 2016 17:40:51 +0800
Subject: [path v2 3/7] drm/hisilicon/hibmc: Add crtc for DE
In-Reply-To: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
Message-ID: <1464514855-108050-4-git-send-email-zourongrong@gmail.com>

Add crtc funcs and helper funcs for DE.

Signed-off-by: Rongrong Zou <zourongrong at gmail.com>
Signed-off-by: Jianhua Li <lijianhua at huawei.com>
---
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c  | 307 ++++++++++++++++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h  |  29 +++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c |   6 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h |   2 +
 4 files changed, 344 insertions(+)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h

diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
index e8e5853..87a7e52 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -26,6 +26,7 @@
 
 #include "hibmc_drm_drv.h"
 #include "hibmc_drm_regs.h"
+#include "hibmc_drm_de.h"
 #include "hibmc_drm_power.h"
 
 /* ---------------------------------------------------------------------- */
@@ -168,3 +169,309 @@ int hibmc_plane_init(struct hibmc_drm_device *hidev)
 	return 0;
 }
 
+static void hibmc_crtc_enable(struct drm_crtc *crtc)
+{
+	unsigned int reg;
+	/* power mode 0 is default. */
+	struct hibmc_drm_device *hidev = crtc->dev->dev_private;
+
+	hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+	reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
+	reg |= HIBMC_CURR_GATE_DISPLAY(ON);
+	hibmc_set_current_gate(hidev, reg);
+}
+
+static void hibmc_crtc_disable(struct drm_crtc *crtc)
+{
+	unsigned int reg;
+	struct hibmc_drm_device *hidev = crtc->dev->dev_private;
+
+	hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_SLEEP);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+	reg |= HIBMC_CURR_GATE_LOCALMEM(OFF);
+	reg |= HIBMC_CURR_GATE_DISPLAY(OFF);
+	hibmc_set_current_gate(hidev, reg);
+}
+
+static int hibmc_crtc_atomic_check(struct drm_crtc *crtc,
+			    struct drm_crtc_state *state)
+{
+	return 0;
+}
+
+static unsigned int format_pll_reg(void)
+{
+	unsigned int pllreg = 0;
+	struct panel_pll pll = {0};
+
+	/* Note that all PLL's have the same format. Here,
+	* we just use Panel PLL parameter to work out the bit
+	* fields in the register.On returning a 32 bit number, the value can
+	* be applied to any PLL in the calling function.
+	*/
+	pllreg |= HIBMC_PLL_CTRL_BYPASS(OFF) & HIBMC_PLL_CTRL_BYPASS_MASK;
+	pllreg |= HIBMC_PLL_CTRL_POWER(ON) & HIBMC_PLL_CTRL_POWER_MASK;
+	pllreg |= HIBMC_PLL_CTRL_INPUT(OSC) & HIBMC_PLL_CTRL_INPUT_MASK;
+	pllreg |= HIBMC_PLL_CTRL_POD(pll.POD) & HIBMC_PLL_CTRL_POD_MASK;
+	pllreg |= HIBMC_PLL_CTRL_OD(pll.OD) & HIBMC_PLL_CTRL_OD_MASK;
+	pllreg |= HIBMC_PLL_CTRL_N(pll.N) & HIBMC_PLL_CTRL_N_MASK;
+	pllreg |= HIBMC_PLL_CTRL_M(pll.M) & HIBMC_PLL_CTRL_M_MASK;
+
+	return pllreg;
+}
+
+static void set_vclock_hisilicon(struct drm_device *dev, unsigned long pll)
+{
+	unsigned long tmp0, tmp1;
+	struct hibmc_drm_device *hidev = dev->dev_private;
+
+    /* 1. outer_bypass_n=0 */
+	tmp0 = readl(hidev->mmio + CRT_PLL1_HS);
+	tmp0 &= 0xBFFFFFFF;
+	writel(tmp0, hidev->mmio + CRT_PLL1_HS);
+
+	/* 2. pll_pd=1?inter_bypass=1 */
+	writel(0x21000000, hidev->mmio + CRT_PLL1_HS);
+
+	/* 3. config pll */
+	writel(pll, hidev->mmio + CRT_PLL1_HS);
+
+	/* 4. delay  */
+	mdelay(1);
+
+	/* 5. pll_pd =0 */
+	tmp1 = pll & ~0x01000000;
+	writel(tmp1, hidev->mmio + CRT_PLL1_HS);
+
+	/* 6. delay  */
+	mdelay(1);
+
+	/* 7. inter_bypass=0 */
+	tmp1 &= ~0x20000000;
+	writel(tmp1, hidev->mmio + CRT_PLL1_HS);
+
+	/* 8. delay  */
+	mdelay(1);
+
+	/* 9. outer_bypass_n=1 */
+	tmp1 |= 0x40000000;
+	writel(tmp1, hidev->mmio + CRT_PLL1_HS);
+}
+
+/* This function takes care the extra registers and bit fields required to
+*setup a mode in board.
+*Explanation about Display Control register:
+*FPGA only supports 7 predefined pixel clocks, and clock select is
+*in bit 4:0 of new register 0x802a8.
+*/
+static unsigned int display_ctrl_adjust(struct drm_device *dev,
+				struct drm_display_mode *mode,
+				unsigned int ctrl)
+{
+	unsigned long x, y;
+	unsigned long pll1; /* bit[31:0] of PLL */
+	unsigned long pll2; /* bit[63:32] of PLL */
+	struct hibmc_drm_device *hidev = dev->dev_private;
+
+	x = mode->hdisplay;
+	y = mode->vdisplay;
+
+	/* Hisilicon has to set up a new register for PLL control
+	 *(CRT_PLL1_HS & CRT_PLL2_HS).
+	 */
+	if (x == 800 && y == 600) {
+		pll1 = CRT_PLL1_HS_40MHZ;
+		pll2 = CRT_PLL2_HS_40MHZ;
+	} else if (x == 1024 && y == 768) {
+		pll1 = CRT_PLL1_HS_65MHZ;
+		pll2 = CRT_PLL2_HS_65MHZ;
+	} else if (x == 1152 && y == 864) {
+		pll1 = CRT_PLL1_HS_80MHZ_1152;
+		pll2 = CRT_PLL2_HS_80MHZ;
+	} else if (x == 1280 && y == 768) {
+		pll1 = CRT_PLL1_HS_80MHZ;
+		pll2 = CRT_PLL2_HS_80MHZ;
+	} else if (x == 1280 && y == 720) {
+		pll1 = CRT_PLL1_HS_74MHZ;
+		pll2 = CRT_PLL2_HS_74MHZ;
+	} else if (x == 1280 && y == 960) {
+		pll1 = CRT_PLL1_HS_108MHZ;
+		pll2 = CRT_PLL2_HS_108MHZ;
+	} else if (x == 1280 && y == 1024) {
+		pll1 = CRT_PLL1_HS_108MHZ;
+		pll2 = CRT_PLL2_HS_108MHZ;
+	} else if (x == 1600 && y == 1200) {
+		pll1 = CRT_PLL1_HS_162MHZ;
+		pll2 = CRT_PLL2_HS_162MHZ;
+	} else if (x == 1920 && y == 1080) {
+		pll1 = CRT_PLL1_HS_148MHZ;
+		pll2 = CRT_PLL2_HS_148MHZ;
+	} else if (x == 1920 && y == 1200) {
+		pll1 = CRT_PLL1_HS_193MHZ;
+		pll2 = CRT_PLL2_HS_193MHZ;
+	} else /* default to VGA clock */ {
+		pll1 = CRT_PLL1_HS_25MHZ;
+		pll2 = CRT_PLL2_HS_25MHZ;
+	}
+
+	writel(pll2, hidev->mmio + CRT_PLL2_HS);
+	set_vclock_hisilicon(dev, pll1);
+
+	/* Hisilicon has to set up the top-left and bottom-right
+	 * registers as well.
+	 * Note that normal chip only use those two register for
+	 * auto-centering mode.
+	 */
+	writel((HIBMC_CRT_AUTO_CENTERING_TL_TOP(0) &
+		HIBMC_CRT_AUTO_CENTERING_TL_TOP_MSK) |
+	       (HIBMC_CRT_AUTO_CENTERING_TL_LEFT(0) &
+		HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MSK),
+	       hidev->mmio + HIBMC_CRT_AUTO_CENTERING_TL);
+
+	writel((HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(y - 1) &
+		HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK) |
+	       (HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x - 1) &
+		HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK),
+		hidev->mmio + HIBMC_CRT_AUTO_CENTERING_BR);
+
+	/* Assume common fields in ctrl have been properly set before
+	 * calling this function.
+	 * This function only sets the extra fields in ctrl.
+	 */
+
+	/* Set bit 25 of display controller: Select CRT or VGA clock */
+	ctrl &= ~HIBMC_CRT_DISP_CTL_CRTSELECT_MASK;
+	ctrl &= ~HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK;
+
+	ctrl |= HIBMC_CRT_DISP_CTL_CRTSELECT(CRTSELECT_CRT);
+
+	/*ctrl = FIELD_SET(ctrl, HIBMC_CRT_DISP_CTL, CRTSELECT, CRT);*/
+
+	/* Set bit 14 of display controller */
+	/*ctrl &= FIELD_CLEAR(HIBMC_CRT_DISP_CTL, CLOCK_PHASE);*/
+
+	/* clock_phase_polarity is 0 */
+	ctrl |= HIBMC_CRT_DISP_CTL_CLOCK_PHASE(PHASE_ACTIVE_HIGH);
+	/*ctrl = FIELD_SET(ctrl, HIBMC_CRT_DISP_CTL,*/
+	/*CLOCK_PHASE, ACTIVE_HIGH);*/
+
+	writel(ctrl, hidev->mmio + HIBMC_CRT_DISP_CTL);
+
+	return ctrl;
+}
+
+static void hibmc_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	unsigned int val;
+	struct drm_display_mode *mode = &crtc->state->mode;
+	struct drm_device *dev = crtc->dev;
+	struct hibmc_drm_device *hidev = dev->dev_private;
+
+	writel(format_pll_reg(), hidev->mmio + HIBMC_CRT_PLL_CTRL);
+	writel((HIBMC_CRT_HORZ_TOTAL_TOTAL(mode->htotal - 1) &
+		HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK) |
+		(HIBMC_CRT_HORZ_TOTAL_DISPLAY_END(mode->hdisplay - 1) &
+		HIBMC_CRT_HORZ_TOTAL_DISPLAY_END_MASK),
+		hidev->mmio + HIBMC_CRT_HORZ_TOTAL);
+
+	writel((HIBMC_CRT_HORZ_SYNC_WIDTH(mode->hsync_end - mode->hsync_start)
+		& HIBMC_CRT_HORZ_SYNC_WIDTH_MASK) |
+		(HIBMC_CRT_HORZ_SYNC_START(mode->hsync_start - 1)
+		& HIBMC_CRT_HORZ_SYNC_START_MASK),
+		hidev->mmio + HIBMC_CRT_HORZ_SYNC);
+
+	writel((HIBMC_CRT_VERT_TOTAL_TOTAL(mode->vtotal - 1) &
+		HIBMC_CRT_VERT_TOTAL_TOTAL_MASK) |
+		(HIBMC_CRT_VERT_TOTAL_DISPLAY_END(mode->vdisplay - 1) &
+		HIBMC_CRT_VERT_TOTAL_DISPLAY_END_MASK),
+		hidev->mmio + HIBMC_CRT_VERT_TOTAL);
+
+	writel((HIBMC_CRT_VERT_SYNC_HEIGHT(mode->vsync_end - mode->vsync_start)
+		& HIBMC_CRT_VERT_SYNC_HEIGHT_MASK) |
+	       (HIBMC_CRT_VERT_SYNC_START(mode->vsync_start - 1) &
+		HIBMC_CRT_VERT_SYNC_START_MASK),
+		hidev->mmio + HIBMC_CRT_VERT_SYNC);
+
+	val = HIBMC_CRT_DISP_CTL_VSYNC_PHASE(0) &
+	      HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK;
+	val |= HIBMC_CRT_DISP_CTL_HSYNC_PHASE(0) &
+	       HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK;
+	val |= HIBMC_CRT_DISP_CTL_TIMING(ENABLE);
+	val |= HIBMC_CRT_DISP_CTL_PLANE(ENABLE);
+
+	display_ctrl_adjust(dev, mode, val);
+}
+
+static void hibmc_crtc_atomic_begin(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_state)
+{
+	unsigned int reg;
+	struct drm_device *dev = crtc->dev;
+	struct hibmc_drm_device *hidev = dev->dev_private;
+
+	hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+	reg |= HIBMC_CURR_GATE_DISPLAY(ON);
+	reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
+	hibmc_set_current_gate(hidev, reg);
+
+	/* We can add more initialization as needed. */
+}
+
+static void hibmc_crtc_atomic_flush(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_state)
+
+{
+}
+
+/* These provide the minimum set of functions required to handle a CRTC */
+static const struct drm_crtc_funcs hibmc_crtc_funcs = {
+	.page_flip = drm_atomic_helper_page_flip,
+	.set_config = drm_atomic_helper_set_config,
+	.destroy = drm_crtc_cleanup,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state =  drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static const struct drm_crtc_helper_funcs hibmc_crtc_helper_funcs = {
+	.enable		= hibmc_crtc_enable,
+	.disable	= hibmc_crtc_disable,
+	.mode_set_nofb	= hibmc_crtc_mode_set_nofb,
+	.atomic_check	= hibmc_crtc_atomic_check,
+	.atomic_begin	= hibmc_crtc_atomic_begin,
+	.atomic_flush	= hibmc_crtc_atomic_flush,
+};
+
+int hibmc_crtc_init(struct hibmc_drm_device *hidev)
+{
+	struct drm_device *dev = hidev->dev;
+	struct drm_crtc *crtc = &hidev->crtc;
+	struct drm_plane *plane = &hidev->plane;
+	int ret;
+
+	ret = drm_crtc_init_with_planes(dev, crtc, plane,
+					NULL, &hibmc_crtc_funcs, NULL);
+	if (ret) {
+		DRM_ERROR("failed to init crtc.\n");
+		return ret;
+	}
+
+	drm_mode_crtc_set_gamma_size(crtc, 256);
+	drm_crtc_helper_add(crtc, &hibmc_crtc_helper_funcs);
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
new file mode 100644
index 0000000..c22f0a4
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
@@ -0,0 +1,29 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong at huawei>
+ *	Rongrong Zou <zourongrong at gmail.com>
+ *	Jianhua Li <lijianhua at huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef HIBMC_DRM_DE_H
+#define HIBMC_DRM_DE_H
+
+struct panel_pll {
+	unsigned long M;
+	unsigned long N;
+	unsigned long OD;
+	unsigned long POD;
+};
+
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 794250a..f7837cc 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -123,6 +123,12 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev)
 		return ret;
 	}
 
+	ret = hibmc_crtc_init(hidev);
+	if (ret) {
+		DRM_ERROR("failed to init crtc.\n");
+		return ret;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index 6c7985d..e64ec8d 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -33,10 +33,12 @@ struct hibmc_drm_device {
 	/* drm */
 	struct drm_device  *dev;
 	struct drm_plane plane;
+	struct drm_crtc crtc;
 	bool mode_config_initialized;
 };
 
 int hibmc_plane_init(struct hibmc_drm_device *hidev);
+int hibmc_crtc_init(struct hibmc_drm_device *hidev);
 
 
 #endif
-- 
1.9.1



From zourongrong at gmail.com  Sun May 29 02:40:52 2016
From: zourongrong at gmail.com (Rongrong Zou)
Date: Sun, 29 May 2016 17:40:52 +0800
Subject: [path v2 4/7] drm/hisilicon/hibmc: Add encoder for VDAC
In-Reply-To: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
Message-ID: <1464514855-108050-5-git-send-email-zourongrong@gmail.com>

Add encoder funcs and helpers for VDAC.

Signed-off-by: Rongrong Zou <zourongrong at gmail.com>
Signed-off-by: Jianhua Li <lijianhua at huawei.com>
---
 drivers/gpu/drm/hisilicon/hibmc/Makefile         |  2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c  |  6 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h  |  2 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 85 ++++++++++++++++++++++++
 4 files changed, 94 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c

diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index faa7e64..4e7797a 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,4 +1,4 @@
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_power.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_power.o
 
 obj-$(CONFIG_DRM_HISI_HIBMC)	+=hibmc-drm.o
 #obj-y	+= hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index f7837cc..962072f 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -129,6 +129,12 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev)
 		return ret;
 	}
 
+	ret = hibmc_encoder_init(hidev);
+	if (ret) {
+		DRM_ERROR("failed to init encoder\n");
+		return ret;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index e64ec8d..d0c5982 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -34,11 +34,13 @@ struct hibmc_drm_device {
 	struct drm_device  *dev;
 	struct drm_plane plane;
 	struct drm_crtc crtc;
+	struct drm_encoder encoder;
 	bool mode_config_initialized;
 };
 
 int hibmc_plane_init(struct hibmc_drm_device *hidev);
 int hibmc_crtc_init(struct hibmc_drm_device *hidev);
+int hibmc_encoder_init(struct hibmc_drm_device *hidev);
 
 
 #endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
new file mode 100644
index 0000000..cb9a130
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -0,0 +1,85 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong at huawei>
+ *	Rongrong Zou <zourongrong at gmail.com>
+ *	Jianhua Li <lijianhua at huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drmP.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+
+static void hibmc_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
+static void hibmc_encoder_enable(struct drm_encoder *encoder)
+{
+}
+
+static void hibmc_encoder_mode_set(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adj_mode)
+{
+	u32 reg;
+	struct drm_device *dev = encoder->dev;
+	struct hibmc_drm_device *hidev = dev->dev_private;
+
+	/* just open DISPLAY_CONTROL_HISILE register bit 3:0*/
+	reg = readl(hidev->mmio + DISPLAY_CONTROL_HISILE);
+	reg |= 0xf;
+	writel(reg, hidev->mmio + DISPLAY_CONTROL_HISILE);
+}
+
+static int hibmc_encoder_atomic_check(struct drm_encoder *encoder,
+				      struct drm_crtc_state *crtc_state,
+				      struct drm_connector_state *conn_state)
+{
+	return 0;
+}
+
+static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = {
+	.mode_set = hibmc_encoder_mode_set,
+	.disable = hibmc_encoder_disable,
+	.enable = hibmc_encoder_enable,
+	.atomic_check = hibmc_encoder_atomic_check,
+};
+
+static const struct drm_encoder_funcs hibmc_encoder_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int hibmc_encoder_init(struct hibmc_drm_device *hidev)
+{
+	struct drm_device *dev = hidev->dev;
+	struct drm_encoder *encoder = &hidev->encoder;
+	int ret;
+
+	encoder->possible_crtcs = 0x1;
+	ret = drm_encoder_init(dev, encoder, &hibmc_encoder_encoder_funcs,
+			       DRM_MODE_ENCODER_DAC, NULL);
+	if (ret) {
+		DRM_ERROR("failed to init encoder\n");
+		return ret;
+	}
+
+	drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
+	return 0;
+}
+
-- 
1.9.1



From zourongrong at gmail.com  Sun May 29 02:40:54 2016
From: zourongrong at gmail.com (Rongrong Zou)
Date: Sun, 29 May 2016 17:40:54 +0800
Subject: [path v2 6/7] drm/hisilicon/hibmc: Add support for frame buffer
In-Reply-To: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
Message-ID: <1464514855-108050-7-git-send-email-zourongrong@gmail.com>

Add support for fbdev.

Signed-off-by: Rongrong Zou <zourongrong at gmail.com>
Signed-off-by: Jianhua Li <lijianhua at huawei.com>
---
 drivers/gpu/drm/hisilicon/hibmc/Makefile          |   2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   |  20 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  17 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 286 ++++++++++++++++++++++
 4 files changed, 324 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c

diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index 4e7797a..92e7b33 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,4 +1,4 @@
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_power.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_fbdev.o hibmc_drm_power.o
 
 obj-$(CONFIG_DRM_HISI_HIBMC)	+=hibmc-drm.o
 #obj-y	+= hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 70d79d2..e36a7ec 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -72,9 +72,16 @@ static int hibmc_pm_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct hibmc_drm_device *hidev = drm_dev->dev_private;
 
 	drm_kms_helper_poll_disable(drm_dev);
 
+	if (hidev->fbdev.initialized) {
+		console_lock();
+		drm_fb_helper_set_suspend(&hidev->fbdev.helper, 1);
+		console_unlock();
+	}
+
 	return 0;
 }
 
@@ -82,8 +89,16 @@ static int hibmc_pm_resume(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct hibmc_drm_device *hidev = drm_dev->dev_private;
 
 	drm_helper_resume_force_mode(drm_dev);
+
+	if (hidev->fbdev.initialized) {
+		console_lock();
+		drm_fb_helper_set_suspend(&hidev->fbdev.helper, 0);
+		console_unlock();
+	}
+
 	drm_kms_helper_poll_enable(drm_dev);
 
 	return 0;
@@ -245,6 +260,7 @@ static int hibmc_unload(struct drm_device *dev)
 {
 	struct hibmc_drm_device *hidev = dev->dev_private;
 
+	hibmc_fbdev_fini(hidev);
 	hibmc_kms_fini(hidev);
 	hibmc_hw_fini(hidev);
 	dev->dev_private = NULL;
@@ -278,6 +294,10 @@ static int hibmc_load(struct drm_device *dev, unsigned long flags)
 	/* reset all the states of crtc/plane/encoder/connector */
 	drm_mode_config_reset(dev);
 
+	ret = hibmc_fbdev_init(hidev);
+	if (ret)
+		goto err;
+
 	return 0;
 
 err:
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index eb5a892..1f32f2e 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -23,6 +23,18 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 
+struct hibmc_framebuffer {
+	struct drm_framebuffer fb;
+	struct drm_gem_cma_object *obj;
+	bool is_fbdev_fb;
+};
+
+struct hibmc_fbdev {
+	struct hibmc_framebuffer fb;
+	struct drm_fb_helper helper;
+	bool initialized;
+};
+
 struct hibmc_drm_device {
 	/* hw */
 	void __iomem   *mmio;
@@ -37,11 +49,16 @@ struct hibmc_drm_device {
 	struct drm_encoder encoder;
 	struct drm_connector connector;
 	bool mode_config_initialized;
+
+	/* fbdev */
+	struct hibmc_fbdev fbdev;
 };
 
 int hibmc_plane_init(struct hibmc_drm_device *hidev);
 int hibmc_crtc_init(struct hibmc_drm_device *hidev);
 int hibmc_encoder_init(struct hibmc_drm_device *hidev);
 int hibmc_connector_init(struct hibmc_drm_device *hidev);
+int hibmc_fbdev_init(struct hibmc_drm_device *hidev);
+void hibmc_fbdev_fini(struct hibmc_drm_device *hidev);
 
 #endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
new file mode 100644
index 0000000..774bfb0
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
@@ -0,0 +1,286 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong at huawei>
+ *	Rongrong Zou <zourongrong at gmail.com>
+ *	Jianhua Li <lijianhua at huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include "hibmc_drm_drv.h"
+
+/* ---------------------------------------------------------------------- */
+
+static void hibmc_drm_fb_destroy(struct drm_framebuffer *fb)
+{
+	struct hibmc_drm_device *hidev =
+		container_of(fb, struct hibmc_drm_device, fbdev.fb.fb);
+	struct drm_gem_object *base = &hidev->fbdev.fb.obj->base;
+
+	if (hidev->fbdev.fb.obj)
+		drm_gem_object_unreference_unlocked(base);
+	drm_framebuffer_cleanup(fb);
+	kfree(fb);
+}
+
+static struct drm_framebuffer_funcs hibmc_drm_fb_funcs = {
+	.destroy	= hibmc_drm_fb_destroy,
+};
+
+static int hibmc_drm_fb_init(struct drm_device *dev,
+		      struct hibmc_framebuffer *gfb,
+		      struct drm_mode_fb_cmd2 *mode_cmd,
+		      struct drm_gem_cma_object *obj)
+{
+	int ret;
+
+	drm_helper_mode_fill_fb_struct(&gfb->fb, mode_cmd);
+	gfb->obj = obj;
+	gfb->is_fbdev_fb = true;
+	ret = drm_framebuffer_init(dev, &gfb->fb, &hibmc_drm_fb_funcs);
+	if (ret) {
+		DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static struct drm_gem_cma_object *hibmc_drm_gem_create_object(
+						struct hibmc_drm_device *hidev,
+						size_t size)
+{
+	struct drm_gem_cma_object *cma_obj;
+	struct drm_gem_object *gem_obj;
+	struct drm_device *drm = hidev->dev;
+	int ret;
+
+	cma_obj = devm_kzalloc(drm->dev, sizeof(*cma_obj), GFP_KERNEL);
+	if (!cma_obj)
+		return ERR_PTR(-ENOMEM);
+
+	gem_obj = &cma_obj->base;
+
+	ret = drm_gem_object_init(drm, gem_obj, size);
+	if (ret)
+		return ERR_PTR(ret);
+
+	cma_obj->vaddr = hidev->fb_map;
+	cma_obj->paddr = hidev->fb_base;
+	return cma_obj;
+}
+
+static void hibmc_drm_gem_free_object(struct drm_gem_object *gem_obj)
+{
+	struct drm_gem_cma_object *cma_obj;
+
+	cma_obj = to_drm_gem_cma_obj(gem_obj);
+	drm_gem_object_release(gem_obj);
+}
+
+static struct fb_ops hibmc_drm_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_fillrect = drm_fb_helper_sys_fillrect,
+	.fb_copyarea = drm_fb_helper_sys_copyarea,
+	.fb_imageblit = drm_fb_helper_sys_imageblit,
+	.fb_pan_display = drm_fb_helper_pan_display,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static int hibmc_drm_fb_probe(struct drm_fb_helper *helper,
+			      struct drm_fb_helper_surface_size *sizes)
+{
+	struct hibmc_drm_device *hidev =
+		container_of(helper, struct hibmc_drm_device, fbdev.helper);
+	struct drm_device *dev = hidev->dev;
+	struct fb_info *info;
+	struct drm_framebuffer *fb;
+	struct drm_mode_fb_cmd2 mode_cmd;
+	struct drm_gem_cma_object *obj = NULL;
+	int ret = 0;
+	size_t size;
+	unsigned int bytes_per_pixel;
+	unsigned long offset;
+
+	DRM_DEBUG_DRIVER("surface width(%d), height(%d) and bpp(%d)\n",
+			 sizes->surface_width, sizes->surface_height,
+			 sizes->surface_bpp);
+	sizes->surface_depth = 32;
+
+	bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+	mode_cmd.pitches[0] = mode_cmd.width * bytes_per_pixel;
+	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+							  sizes->surface_depth);
+
+	size = roundup(mode_cmd.pitches[0] * mode_cmd.height, PAGE_SIZE);
+
+	obj = hibmc_drm_gem_create_object(hidev, size);
+	if (IS_ERR(obj)) {
+		DRM_ERROR("can't allocate gem object\n");
+		return -ENOMEM;
+	}
+
+
+	/* init fb device */
+	/*info = framebuffer_alloc(0, device);*/
+	info = drm_fb_helper_alloc_fbi(helper);
+	if (!info) {
+		DRM_ERROR("can't allocate fb info\n");
+		goto err_drm_gem_cma_free_object;
+	}
+
+	ret = hibmc_drm_fb_init(hidev->dev,
+				&hidev->fbdev.fb, &mode_cmd, obj);
+	if (ret) {
+		DRM_ERROR("framebuffer init error\n");
+		goto err_drm_gem_cma_free_object;
+	}
+
+	/* setup helper */
+	fb = &hidev->fbdev.fb.fb;
+	hidev->fbdev.helper.fb = fb;
+	hidev->fbdev.helper.fbdev = info;
+
+	strcpy(info->fix.id, "hibmcdrmfb");
+	info->par = &hidev->fbdev.helper;
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &hibmc_drm_fb_ops;
+
+	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
+	drm_fb_helper_fill_var(info, &hidev->fbdev.helper, sizes->fb_width,
+			       sizes->fb_height);
+
+	offset = info->var.xoffset * bytes_per_pixel;
+	offset += info->var.yoffset * fb->pitches[0];
+
+	dev->mode_config.fb_base = (resource_size_t)obj->paddr;
+	info->screen_base = obj->vaddr + offset;
+	info->fix.smem_start = (unsigned long)(obj->paddr + offset);
+	info->screen_size = size;
+	info->fix.smem_len = size;
+
+	return 0;
+
+err_drm_gem_cma_free_object:
+	hibmc_drm_gem_free_object(&obj->base);
+	return ret;
+}
+
+static int hibmc_fbdev_destroy(struct hibmc_drm_device *hidev)
+{
+	struct hibmc_framebuffer *gfb = &hidev->fbdev.fb;
+	struct drm_fb_helper *fbh = &hidev->fbdev.helper;
+
+	DRM_DEBUG_DRIVER("hibmc_fbdev_destroy\n");
+
+	drm_fb_helper_unregister_fbi(fbh);
+	drm_fb_helper_release_fbi(fbh);
+
+	drm_framebuffer_unregister_private(&gfb->fb);
+	if (gfb->obj) {
+		drm_gem_object_unreference_unlocked(&gfb->obj->base);
+		gfb->obj = NULL;
+	}
+
+	drm_framebuffer_cleanup(&gfb->fb);
+	drm_fb_helper_fini(&hidev->fbdev.helper);
+
+	return 0;
+}
+
+static const struct drm_fb_helper_funcs hibmc_fbdev_helper_funcs = {
+	.fb_probe = hibmc_drm_fb_probe,
+};
+
+int hibmc_fbdev_init(struct hibmc_drm_device *hidev)
+{
+	int ret;
+	struct fb_var_screeninfo *var;
+	struct fb_fix_screeninfo *fix;
+
+	drm_fb_helper_prepare(hidev->dev, &hidev->fbdev.helper,
+			      &hibmc_fbdev_helper_funcs);
+
+	/* Now just one crtc and one channel */
+	ret = drm_fb_helper_init(hidev->dev,
+				 &hidev->fbdev.helper, 1, 1);
+	if (ret)
+		return ret;
+
+	ret = drm_fb_helper_single_add_all_connectors(&hidev->fbdev.helper);
+	if (ret)
+		goto fini;
+
+	drm_helper_disable_unused_functions(hidev->dev);
+
+	ret = drm_fb_helper_initial_config(&hidev->fbdev.helper, 16);
+	if (ret)
+		goto fini;
+
+	hidev->fbdev.initialized = true;
+
+	var = &hidev->fbdev.helper.fbdev->var;
+	fix = &hidev->fbdev.helper.fbdev->fix;
+
+	DRM_DEBUG("Member of info->var is :\n"
+		 "xres=%d\n"
+		 "yres=%d\n"
+		 "xres_virtual=%d\n"
+		 "yres_virtual=%d\n"
+		 "xoffset=%d\n"
+		 "yoffset=%d\n"
+		 "bits_per_pixel=%d\n"
+		 "...\n", var->xres, var->yres, var->xres_virtual,
+		 var->yres_virtual, var->xoffset, var->yoffset,
+		 var->bits_per_pixel);
+	DRM_DEBUG("Member of info->fix is :\n"
+		 "smem_start=%lx\n"
+		 "smem_len=%d\n"
+		 "type=%d\n"
+		 "type_aux=%d\n"
+		 "visual=%d\n"
+		 "xpanstep=%d\n"
+		 "ypanstep=%d\n"
+		 "ywrapstep=%d\n"
+		 "line_length=%d\n"
+		 "accel=%d\n"
+		 "capabilities=%d\n"
+		 "...\n", fix->smem_start, fix->smem_len, fix->type,
+		 fix->type_aux, fix->visual, fix->xpanstep,
+		 fix->ypanstep, fix->ywrapstep, fix->line_length,
+		 fix->accel, fix->capabilities);
+
+	return 0;
+
+fini:
+	drm_fb_helper_fini(&hidev->fbdev.helper);
+	return ret;
+}
+
+void hibmc_fbdev_fini(struct hibmc_drm_device *hidev)
+{
+	if (!hidev->fbdev.initialized)
+		return;
+
+	hibmc_fbdev_destroy(hidev);
+	hidev->fbdev.initialized = false;
+}
-- 
1.9.1



From zourongrong at gmail.com  Sun May 29 02:40:53 2016
From: zourongrong at gmail.com (Rongrong Zou)
Date: Sun, 29 May 2016 17:40:53 +0800
Subject: [path v2 5/7] drm/hisilicon/hibmc: Add connector for VDAC
In-Reply-To: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
Message-ID: <1464514855-108050-6-git-send-email-zourongrong@gmail.com>

Add connector funcs and helper funcs for VDAC.

Signed-off-by: Rongrong Zou <zourongrong at gmail.com>
Signed-off-by: Jianhua Li <lijianhua at huawei.com>
---
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c  | 21 ++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h  |  3 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 89 ++++++++++++++++++++++++
 3 files changed, 112 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 962072f..70d79d2 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -135,6 +135,14 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev)
 		return ret;
 	}
 
+	ret = hibmc_connector_init(hidev);
+	if (ret) {
+		DRM_ERROR("failed to init connector\n");
+		return ret;
+	}
+
+	drm_mode_connector_attach_encoder(&hidev->connector,
+					  &hidev->encoder);
 	return 0;
 }
 
@@ -278,6 +286,12 @@ err:
 	return ret;
 }
 
+static void hibmc_connector_unplug_all(struct drm_device *dev)
+{
+	mutex_lock(&dev->mode_config.mutex);
+	drm_connector_unregister_all(dev);
+	mutex_unlock(&dev->mode_config.mutex);
+}
 
 static int hibmc_pci_probe(struct pci_dev *pdev,
 			   const struct pci_device_id *ent)
@@ -304,8 +318,14 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
 	if (ret)
 		goto err_unload;
 
+	ret = drm_connector_register_all(dev);
+	if (ret)
+		goto err_unregister;
+
 	return 0;
 
+err_unregister:
+	drm_dev_unregister(dev);
 err_unload:
 	hibmc_unload(dev);
 err_disable:
@@ -320,6 +340,7 @@ static void hibmc_pci_remove(struct pci_dev *pdev)
 {
 	struct drm_device *dev = pci_get_drvdata(pdev);
 
+	hibmc_connector_unplug_all(dev);
 	drm_dev_unregister(dev);
 	hibmc_unload(dev);
 	drm_dev_unref(dev);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index d0c5982..eb5a892 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -35,12 +35,13 @@ struct hibmc_drm_device {
 	struct drm_plane plane;
 	struct drm_crtc crtc;
 	struct drm_encoder encoder;
+	struct drm_connector connector;
 	bool mode_config_initialized;
 };
 
 int hibmc_plane_init(struct hibmc_drm_device *hidev);
 int hibmc_crtc_init(struct hibmc_drm_device *hidev);
 int hibmc_encoder_init(struct hibmc_drm_device *hidev);
-
+int hibmc_connector_init(struct hibmc_drm_device *hidev);
 
 #endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
index cb9a130..b39ec65 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -24,6 +24,13 @@
 #include "hibmc_drm_drv.h"
 #include "hibmc_drm_regs.h"
 
+static int defx = 800;
+static int defy = 600;
+
+module_param(defx, int, 0444);
+module_param(defy, int, 0444);
+MODULE_PARM_DESC(defx, "default x resolution");
+MODULE_PARM_DESC(defy, "default y resolution");
 
 static void hibmc_encoder_disable(struct drm_encoder *encoder)
 {
@@ -83,3 +90,85 @@ int hibmc_encoder_init(struct hibmc_drm_device *hidev)
 	return 0;
 }
 
+static int hibmc_connector_get_modes(struct drm_connector *connector)
+{
+	int count;
+
+	count = drm_add_modes_noedid(connector, 800, 600);
+	drm_set_preferred_mode(connector, defx, defy);
+	return count;
+}
+
+static int hibmc_connector_mode_valid(struct drm_connector *connector,
+				      struct drm_display_mode *mode)
+{
+	struct hibmc_drm_device *hiprivate =
+	 container_of(connector, struct hibmc_drm_device, connector);
+	unsigned long size = mode->hdisplay * mode->vdisplay * 4;
+
+	/*
+	* Make sure we can fit two framebuffers into video memory.
+	* This allows up to 1600x1200 with 16 MB (default size).
+	* If you want more try this:
+	* 'qemu -vga std -global VGA.vgamem_mb=32 $otherargs'
+	*/
+	if (size * 2 > hiprivate->fb_size)
+		return MODE_BAD;
+
+	return MODE_OK;
+}
+
+static struct drm_encoder *
+hibmc_connector_best_encoder(struct drm_connector *connector)
+{
+	int enc_id = connector->encoder_ids[0];
+
+	/* pick the encoder ids */
+	if (enc_id)
+		return drm_encoder_find(connector->dev, enc_id);
+
+	return NULL;
+}
+
+static enum drm_connector_status hibmc_connector_detect(struct drm_connector
+						 *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static const struct drm_connector_helper_funcs
+	hibmc_connector_connector_helper_funcs = {
+	.get_modes = hibmc_connector_get_modes,
+	.mode_valid = hibmc_connector_mode_valid,
+	.best_encoder = hibmc_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs hibmc_connector_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.detect = hibmc_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_connector_cleanup,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+int hibmc_connector_init(struct hibmc_drm_device *hidev)
+{
+	struct drm_device *dev = hidev->dev;
+	struct drm_connector *connector = &hidev->connector;
+	int ret;
+
+	ret = drm_connector_init(dev, connector,
+				 &hibmc_connector_connector_funcs,
+				 DRM_MODE_CONNECTOR_VIRTUAL);
+	if (ret) {
+		DRM_ERROR("failed to init connector\n");
+		return ret;
+	}
+	drm_connector_helper_add(connector,
+				 &hibmc_connector_connector_helper_funcs);
+
+	return 0;
+}
+
-- 
1.9.1



From zourongrong at gmail.com  Sun May 29 02:40:55 2016
From: zourongrong at gmail.com (Rongrong Zou)
Date: Sun, 29 May 2016 17:40:55 +0800
Subject: [path v2 7/7] drm/hisilicon/hibmc: Add maintainer for Hibmc DRM
In-Reply-To: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
Message-ID: <1464514855-108050-8-git-send-email-zourongrong@gmail.com>

Signed-off-by: Rongrong Zou <zourongrong at gmail.com>
Signed-off-by: Jianhua Li <lijianhua at huawei.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index f466673..a8a62e0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3957,6 +3957,13 @@ T:	git git://github.com/patjak/drm-gma500
 S:	Maintained
 F:	drivers/gpu/drm/gma500/
 
+DRM DRIVERS FOR HIBMC
+M:	lijianhua <lijianhua at huawei.com>
+M:	Rongrong Zou <zourongrong at gmail.com>
+L:	dri-devel at lists.freedesktop.org
+S:	Maintained
+F:	drivers/gpu/drm/hisilicon/hibmc
+
 DRM DRIVERS FOR HISILICON
 M:	Xinliang Liu <z.liuxinliang at hisilicon.com>
 R:	Xinwei Kong <kong.kongxinwei at hisilicon.com>
-- 
1.9.1



From carlo at caione.org  Sun May 29 04:12:00 2016
From: carlo at caione.org (Carlo Caione)
Date: Sun, 29 May 2016 13:12:00 +0200
Subject: [PATCH v5 0/3] Add Amlogic secure monitor driver
Message-ID: <1464520323-19531-1-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

In the Amlogic SoCs the secure monitor calls are used for a lot of reasons:
interact with the NVMEM (efuses), check the reboot reason, set USB boot, ...

This driver defines a generic interface towards the secure monitor that can be
used by more specialized drivers to interact with the secure monitor itself
without worrying about bounce buffers managing.

Changelog:

v5:
  * Moved IDs from DT to header file
  * Made read/write bounce buffers not mandatory
  * Introduced helper meson_sm_map_shmem()

v4:
  * Changed patches order
  * Removed now useless PATCH 2/4
  * Changed compatible to be SoC-specific
  * In the DT now we use SoC-agnostic IDs for the SMC functions. These IDs are
    traslated into SoC specific function IDs inside the driver
  * Added error checking on meson_sm_call() to retrieve the base address
  * Improved printing on errors

v3:
  * Moved driver to drivers/firmware
  * Added EXPORT_SYMBOL macros
  * Changed '_' in '-'
  * Introduced 'struct meson_sm_firmware' and 'meson_sm_get_fw()' to be used by
    drivers using the secure-monitor to enforce probe ordering

v2:
  * All the SMC function identifiers are now in a SoC-specific header file to
    be included by the DTS files so the SMC commands are now defined in the DT
    instead to be hardcoded into the driver
  * Patchset is no longer an RFC
  * Better error management and boundary checking
  * s/unsigned int/u32/
  * SMC call not only on CPU 0
  * Fix memory leaking
  * s/amlogic/meson/ in the directory names


Carlo Caione (3):
  firmware: Amlogic: Add secure monitor driver
  documentation: Add secure monitor binding documentation
  ARM64: dts: amlogic: gxbb: Enable secure monitor

 .../bindings/firmware/meson/meson_sm.txt           |  33 +++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   8 +
 drivers/firmware/Kconfig                           |   1 +
 drivers/firmware/Makefile                          |   1 +
 drivers/firmware/meson/Kconfig                     |   8 +
 drivers/firmware/meson/Makefile                    |   1 +
 drivers/firmware/meson/meson_sm.c                  | 223 +++++++++++++++++++++
 include/linux/firmware/meson/meson_sm.h            |  32 +++
 8 files changed, 307 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
 create mode 100644 drivers/firmware/meson/Kconfig
 create mode 100644 drivers/firmware/meson/Makefile
 create mode 100644 drivers/firmware/meson/meson_sm.c
 create mode 100644 include/linux/firmware/meson/meson_sm.h

-- 
2.7.4



From carlo at caione.org  Sun May 29 04:12:02 2016
From: carlo at caione.org (Carlo Caione)
Date: Sun, 29 May 2016 13:12:02 +0200
Subject: [PATCH v5 2/3] documentation: Add secure monitor binding documentation
In-Reply-To: <1464520323-19531-1-git-send-email-carlo@caione.org>
References: <1464520323-19531-1-git-send-email-carlo@caione.org>
Message-ID: <1464520323-19531-3-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add the binding documentation for the Amlogic secure monitor driver.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 .../bindings/firmware/meson/meson_sm.txt           | 33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt

diff --git a/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt b/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
new file mode 100644
index 0000000..6f0b5bc
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
@@ -0,0 +1,33 @@
+* Amlogic Secure Monitor
+
+In the Amlogic SoCs the Secure Monitor code is used to provide access to the
+NVMEM, enable JTAG, set USB boot, etc...
+
+Required properties for the secure monitor node:
+- compatible: Should be "amlogic,meson-gxbb-sm"
+
+Example:
+
+	firmware {
+		compatible = "simple-bus";
+
+		sm: secure-monitor {
+			compatible = "amlogic,meson-gxbb-sm";
+		};
+	};
+
+Example of the node using the secure monitor:
+
+	#include <dt-bindings/firmware/meson-sm.h>
+
+	...
+
+	efuse: efuse {
+		compatible = "amlogic,meson-gxbb-efuse";
+		secure-monitor = <&sm>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		...
+	};
+
-- 
2.7.4



From carlo at caione.org  Sun May 29 04:12:03 2016
From: carlo at caione.org (Carlo Caione)
Date: Sun, 29 May 2016 13:12:03 +0200
Subject: [PATCH v5 3/3] ARM64: dts: amlogic: gxbb: Enable secure monitor
In-Reply-To: <1464520323-19531-1-git-send-email-carlo@caione.org>
References: <1464520323-19531-1-git-send-email-carlo@caione.org>
Message-ID: <1464520323-19531-4-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Add the secure monitor node in the Amlogic Meson GXBB DTSI file to
enable it.

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 76b3b6d..a453bbf 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -98,6 +98,14 @@
 		method = "smc";
 	};
 
+	firmware {
+		compatible = "simple-bus";
+
+		sm: secure-monitor {
+			compatible = "amlogic,meson-gxbb-sm";
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13
-- 
2.7.4



From carlo at caione.org  Sun May 29 04:12:01 2016
From: carlo at caione.org (Carlo Caione)
Date: Sun, 29 May 2016 13:12:01 +0200
Subject: [PATCH v5 1/3] firmware: Amlogic: Add secure monitor driver
In-Reply-To: <1464520323-19531-1-git-send-email-carlo@caione.org>
References: <1464520323-19531-1-git-send-email-carlo@caione.org>
Message-ID: <1464520323-19531-2-git-send-email-carlo@caione.org>

From: Carlo Caione <carlo at endlessm.com>

Introduce a driver to provide calls into secure monitor mode.

In the Amlogic SoCs these calls are used for multiple reasons: access to
NVMEM, set USB boot, enable JTAG, etc...

Signed-off-by: Carlo Caione <carlo at endlessm.com>
---
 drivers/firmware/Kconfig                |   1 +
 drivers/firmware/Makefile               |   1 +
 drivers/firmware/meson/Kconfig          |   8 ++
 drivers/firmware/meson/Makefile         |   1 +
 drivers/firmware/meson/meson_sm.c       | 223 ++++++++++++++++++++++++++++++++
 include/linux/firmware/meson/meson_sm.h |  32 +++++
 6 files changed, 266 insertions(+)
 create mode 100644 drivers/firmware/meson/Kconfig
 create mode 100644 drivers/firmware/meson/Makefile
 create mode 100644 drivers/firmware/meson/meson_sm.c
 create mode 100644 include/linux/firmware/meson/meson_sm.h

diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 6664f11..686e395 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -199,5 +199,6 @@ config HAVE_ARM_SMCCC
 source "drivers/firmware/broadcom/Kconfig"
 source "drivers/firmware/google/Kconfig"
 source "drivers/firmware/efi/Kconfig"
+source "drivers/firmware/meson/Kconfig"
 
 endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 474bada..fc4bb09 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_QCOM_SCM_32)	+= qcom_scm-32.o
 CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
 
 obj-y				+= broadcom/
+obj-y				+= meson/
 obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
 obj-$(CONFIG_EFI)		+= efi/
 obj-$(CONFIG_UEFI_CPER)		+= efi/
diff --git a/drivers/firmware/meson/Kconfig b/drivers/firmware/meson/Kconfig
new file mode 100644
index 0000000..fff11a3
--- /dev/null
+++ b/drivers/firmware/meson/Kconfig
@@ -0,0 +1,8 @@
+#
+# Amlogic Secure Monitor driver
+#
+config MESON_SM
+	bool
+	default ARCH_MESON
+	help
+	  Say y here to enable the Amlogic secure monitor driver
diff --git a/drivers/firmware/meson/Makefile b/drivers/firmware/meson/Makefile
new file mode 100644
index 0000000..9ab3884
--- /dev/null
+++ b/drivers/firmware/meson/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MESON_SM) +=	meson_sm.o
diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
new file mode 100644
index 0000000..e1ce487
--- /dev/null
+++ b/drivers/firmware/meson/meson_sm.c
@@ -0,0 +1,223 @@
+/*
+ * Amlogic Secure Monitor driver
+ *
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <stdarg.h>
+#include <asm/cacheflush.h>
+#include <asm/compiler.h>
+#include <linux/arm-smccc.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/smp.h>
+#include <linux/firmware/meson/meson_sm.h>
+
+struct meson_sm_cmd {
+	unsigned int index;
+	u32 smc_id;
+};
+#define CMD(d, s) { .index = (d), .smc_id = (s), }
+
+struct meson_sm_chip {
+	unsigned int shmem_size;
+	u32 cmd_shmem_in_base;
+	u32 cmd_shmem_out_base;
+	struct meson_sm_cmd cmd[];
+};
+
+struct meson_sm_firmware {
+	struct device *dev;
+	const struct meson_sm_chip *chip;
+	void __iomem *sm_shmem_in_base;
+	void __iomem *sm_shmem_out_base;
+};
+
+struct meson_sm_chip gxbb_chip = {
+	.shmem_size		= 0x1000,
+	.cmd_shmem_in_base	= 0x82000020,
+	.cmd_shmem_out_base	= 0x82000021,
+	.cmd = {
+		CMD(SM_EFUSE_READ,	0x82000030),
+		CMD(SM_EFUSE_WRITE,	0x82000031),
+		CMD(SM_EFUSE_USER_MAX,	0x82000033),
+		{ /* sentinel */ },
+	},
+};
+
+static u32 meson_sm_get_cmd(const struct meson_sm_chip *chip, unsigned int cmd_index)
+{
+	unsigned int i;
+
+	for (i = 0; chip->cmd[i].smc_id; i++)
+		if (chip->cmd[i].index == cmd_index)
+			return chip->cmd[i].smc_id;
+
+	return 0;
+}
+
+static u32 __meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_smc(cmd, arg0, arg1, arg2, arg3, arg4, 0, 0, &res);
+	return res.a0;
+}
+
+u32 meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index,
+		  u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 cmd;
+
+	if (!fw)
+		return -EINVAL;
+
+	cmd = meson_sm_get_cmd(fw->chip, cmd_index);
+	if (!cmd)
+		return -EINVAL;
+
+	return __meson_sm_call(cmd, arg0, arg1, arg2, arg3, arg4);
+}
+EXPORT_SYMBOL(meson_sm_call);
+
+u32 meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
+		       unsigned int cmd_index, u32 arg0, u32 arg1,
+		       u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 size;
+
+	if (!fw->chip->cmd_shmem_out_base)
+		return -EINVAL;
+
+	size = meson_sm_call(fw, cmd_index, arg0, arg1, arg2, arg3, arg4);
+	if (size <= 0 || size > fw->chip->shmem_size)
+		return -EINVAL;
+
+	memcpy(buffer, fw->sm_shmem_out_base, size);
+
+	return size;
+}
+EXPORT_SYMBOL(meson_sm_call_read);
+
+u32 meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
+			unsigned int b_size, unsigned int cmd_index,
+			u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 size;
+
+	if (b_size > fw->chip->shmem_size)
+		return -EINVAL;
+
+	if (!fw->chip->cmd_shmem_in_base)
+		return -EINVAL;
+
+	memcpy(fw->sm_shmem_in_base, buffer, b_size);
+
+	size = meson_sm_call(fw, cmd_index, arg0, arg1, arg2, arg3, arg4);
+	if (size <= 0)
+		return -EINVAL;
+
+	return size;
+}
+EXPORT_SYMBOL(meson_sm_call_write);
+
+static void __iomem *meson_sm_map_shmem(u32 cmd_shmem, unsigned int size)
+{
+	u32 sm_phy_base;
+
+	sm_phy_base = __meson_sm_call(cmd_shmem, 0, 0, 0, 0, 0);
+	if (!sm_phy_base)
+		return 0;
+
+	return ioremap_cache(sm_phy_base, size);
+}
+
+static int meson_sm_probe(struct platform_device *pdev)
+{
+	const struct meson_sm_chip *chip;
+	struct meson_sm_firmware *fw;
+
+	fw = devm_kzalloc(&pdev->dev, sizeof(*fw), GFP_KERNEL);
+	if (!fw)
+		return -ENOMEM;
+
+	fw->dev = &pdev->dev;
+
+	chip = of_device_get_match_data(fw->dev);
+	if (!chip) {
+		dev_err(fw->dev, "Unable to setup secure-monitor data\n");
+		return -ENODEV;
+	}
+
+	if (chip->cmd_shmem_in_base) {
+		fw->sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base,
+							  chip->shmem_size);
+		if (!fw->sm_shmem_in_base)
+			goto out;
+	}
+
+	if (chip->cmd_shmem_out_base) {
+		fw->sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base,
+							   chip->shmem_size);
+		if (!fw->sm_shmem_out_base)
+			goto out;
+	}
+
+	fw->chip = chip;
+	platform_set_drvdata(pdev, fw);
+
+	dev_info(fw->dev, "secure-monitor enabled\n");
+
+	return 0;
+
+out:
+	if (fw->sm_shmem_in_base)
+		iounmap(fw->sm_shmem_in_base);
+
+	return -EINVAL;
+}
+
+struct meson_sm_firmware *meson_sm_get_fw(struct device_node *firmware_node)
+{
+	struct platform_device *pdev = of_find_device_by_node(firmware_node);
+
+	/*
+	 * Returns NULL is the firmware device is not ready.
+	 */
+	if (!pdev)
+		return NULL;
+
+	return platform_get_drvdata(pdev);
+}
+EXPORT_SYMBOL(meson_sm_get_fw);
+
+static const struct of_device_id meson_sm_ids[] = {
+	{ .compatible = "amlogic,meson-gxbb-sm", .data = &gxbb_chip },
+	{ /* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, meson_sm_ids);
+
+static struct platform_driver meson_sm_platform_driver = {
+	.probe	= meson_sm_probe,
+	.driver	= {
+		.name		= "secure-monitor",
+		.of_match_table	= meson_sm_ids,
+	},
+};
+module_platform_driver(meson_sm_platform_driver);
+
+MODULE_AUTHOR("Carlo Caione <carlo at endlessm.com>");
+MODULE_DESCRIPTION("Amlogic secure monitor driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/firmware/meson/meson_sm.h b/include/linux/firmware/meson/meson_sm.h
new file mode 100644
index 0000000..f653916
--- /dev/null
+++ b/include/linux/firmware/meson/meson_sm.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo at endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _MESON_SM_FW_H_
+#define _MESON_SM_FW_H_
+
+#define SM_EFUSE_READ		0
+#define SM_EFUSE_WRITE		1
+#define SM_EFUSE_USER_MAX	2
+
+struct meson_sm_firmware;
+
+u32 meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index,
+		  u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
+u32 meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
+			unsigned int b_size, unsigned int cmd_index,
+			u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
+u32 meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
+		       unsigned int cmd_index, u32 arg0, u32 arg1,
+		       u32 arg2, u32 arg3, u32 arg4);
+struct meson_sm_firmware *meson_sm_get_fw(struct device_node *firmware_node);
+
+#endif /* _MESON_SM_FW_H_ */
-- 
2.7.4



From carlo at caione.org  Sun May 29 04:36:58 2016
From: carlo at caione.org (Carlo Caione)
Date: Sun, 29 May 2016 13:36:58 +0200
Subject: [PATCH v5 1/3] firmware: Amlogic: Add secure monitor driver
In-Reply-To: <CANe6Qb8ECk_1S=pyJBACUwSRyNUi7ROF-GvybcpYLTks4L38fg@mail.gmail.com>
References: <1464520323-19531-1-git-send-email-carlo@caione.org>
 <1464520323-19531-2-git-send-email-carlo@caione.org>
 <CANe6Qb8ECk_1S=pyJBACUwSRyNUi7ROF-GvybcpYLTks4L38fg@mail.gmail.com>
Message-ID: <20160529113658.GA21309@mephisto>

On 29/05/16 12:27, Ben Dooks wrote:

[...]
> > +u32 meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
> > +                      unsigned int cmd_index, u32 arg0, u32 arg1,
> > +                      u32 arg2, u32 arg3, u32 arg4)
> > +{
> > +       u32 size;
> > +
> > +       if (!fw->chip->cmd_shmem_out_base)
> > +               return -EINVAL;
> > +
> > +       size = meson_sm_call(fw, cmd_index, arg0, arg1, arg2, arg3, arg4);
> > +       if (size <= 0 || size > fw->chip->shmem_size)
> > +               return -EINVAL;
> > +
> u32 cannot be less than 0

Ouch. Definitely overlooked that. Fix coming.

[...]
> > +static int meson_sm_probe(struct platform_device *pdev)
> > +{
> > +       const struct meson_sm_chip *chip;
> > +       struct meson_sm_firmware *fw;
> > +
> > +       fw = devm_kzalloc(&pdev->dev, sizeof(*fw), GFP_KERNEL);
> > +       if (!fw)
> > +               return -ENOMEM;
> > +
> > +       fw->dev = &pdev->dev;
> > +
> > +       chip = of_device_get_match_data(fw->dev);
> > +       if (!chip) {
> > +               dev_err(fw->dev, "Unable to setup secure-monitor data\n");
> > +               return -ENODEV;
> > +       }
> -ENODEV not best return here. Return -EINVAL better. -ENODEV won't get
> reported by device layer

Ok

[...]
> > +               if (!fw->sm_shmem_in_base)
> > +                       goto out;
> > +       }
>   Maybe use WarnOn here

Alright.

Cheers,

-- 
Carlo Caione


From bhe at redhat.com  Sun May 29 06:29:10 2016
From: bhe at redhat.com (Baoquan He)
Date: Sun, 29 May 2016 21:29:10 +0800
Subject: [PATCH kexec-tools 07/32] kexec: fix warnings caused by
 selecting 64-bit file IO on 32-bit platforms
In-Reply-To: <20160528135320.GQ19428@n2100.arm.linux.org.uk>
References: <CAHB_GurHc1aVfzJATpNW5yf5s5KkF=t5s09FbWq3+9+ZX39KUg@mail.gmail.com>
 <E1axXSV-0004hZ-CH@e0050434b2927.dyn.arm.linux.org.uk>
 <20160528113354.GB2429@x1.redhat.com>
 <20160528135320.GQ19428@n2100.arm.linux.org.uk>
Message-ID: <20160529132910.GA5752@x1.redhat.com>

On 05/28/16 at 02:53pm, Russell King - ARM Linux wrote:
> On Sat, May 28, 2016 at 07:33:54PM +0800, Baoquan He wrote:
> > On 05/03/16 at 11:21am, Russell King wrote:
> > > diff --git a/kexec/kexec-uImage.c b/kexec/kexec-uImage.c
> > > index 9df601b..5e24629 100644
> > > --- a/kexec/kexec-uImage.c
> > > +++ b/kexec/kexec-uImage.c
> > > @@ -82,7 +82,8 @@ int uImage_probe(const unsigned char *buf, off_t len, unsigned int arch)
> > >  	if (be32_to_cpu(header.ih_size) > len - sizeof(header)) {
> > >  		printf("uImage header claims that image has %d bytes\n",
> > >  				be32_to_cpu(header.ih_size));
> > > -		printf("we read only %ld bytes.\n", len - sizeof(header));
> > > +		printf("we read only %lld bytes.\n",
> > > +		       (long long)len - sizeof(header));
> > 
> > With "D_FILE_OFFSET_BITS=64" adding, off_t is identical to off64_t, is
> > that necessary to still take a type conversion here?
> 
> The printf format specifies an argument of "long long" type, which is
> defined as a data type of at least 64-bits wide.  So, it's more
> correct to cast to long long, rather than relying on off64_t being
> the same size as long long.

Ok, it's fine to have an explict cast here so that people don't need
to consider off_t is long or long long.

Ack this patch.

Acked-by: Baoquan He <bhe at redhat.com>

Thanks
Baoquan



From jinb.park7 at gmail.com  Sun May 29 07:42:21 2016
From: jinb.park7 at gmail.com (Jinbum Park)
Date: Sun, 29 May 2016 23:42:21 +0900
Subject: [PATCH] kprobes: fix a comment typo
Message-ID: <20160529144221.GA14080@pjb1027-Latitude-E5410>

Just fix a typo in the code comment.

Signed-off-by: Jinbum Park <jinb.park7 at gmail.com>
---
 arch/arm/probes/kprobes/opt-arm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c
index bcdecc2..073c0ba 100644
--- a/arch/arm/probes/kprobes/opt-arm.c
+++ b/arch/arm/probes/kprobes/opt-arm.c
@@ -223,7 +223,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *or
 	 *
 	 * So the maximum forward branch should be:
 	 *   (0x007fffff << 2) = 0x01fffffc =  0x1fffffc
-	 * The maximum backword branch should be:
+	 * The maximum backward branch should be:
 	 *   (0xff800000 << 2) = 0xfe000000 = -0x2000000
 	 *
 	 * We can simply check (rel & 0xfe000003):
-- 
1.9.1



From yamada.masahiro at socionext.com  Sun May 29 19:01:23 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Mon, 30 May 2016 11:01:23 +0900
Subject: [PATCH] ARM: avoid duplicating "Kernel: arch/arm/boot/*Image is ready"
Message-ID: <1464573683-30795-1-git-send-email-yamada.masahiro@socionext.com>

Commit 3939f3345050 ("ARM: 8418/1: add boot image dependencies to
not generate invalid images") fixed bad image generation for the
parallel building, but as its side effect, Kbuild now descends into
arch/arm/boot/ again and again, duplicating the log messages.
It looks clumsy, so let's display the same message only once.

This commit moves the log rules from arch/arm/boot/Makefile to
arch/arm/Makefile.  I did not delete them completely because *Image
are the final targets that users are interested in.

Without this commit, the log of incremental build is like follows:

$ make ARCH=arm UIMAGE_LOADADDR=0x80208000 uImage
  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     include/generated/bounds.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  Kernel: arch/arm/boot/Image is ready
  Kernel: arch/arm/boot/Image is ready
  Kernel: arch/arm/boot/zImage is ready
  Kernel: arch/arm/boot/Image is ready
  Kernel: arch/arm/boot/zImage is ready
  Image arch/arm/boot/uImage is ready

With this commit, it will look like follows:

$ make ARCH=arm UIMAGE_LOADADDR=0x80208000 uImage
  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     include/generated/bounds.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  Kernel: arch/arm/boot/Image is ready
  Kernel: arch/arm/boot/zImage is ready
  Kernel: arch/arm/boot/uImage is ready

Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
---
KernelVersion: v4.7-rc1


 arch/arm/Makefile      | 1 +
 arch/arm/boot/Makefile | 6 +-----
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 274e8a6..229afaf 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -327,6 +327,7 @@ zImage: Image
 
 $(BOOT_TARGETS): vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+	@$(kecho) '  Kernel: $(boot)/$@ is ready'
 
 $(INSTALL_TARGETS):
 	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 5be33a2..bdc1d5a 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -31,7 +31,7 @@ ifeq ($(CONFIG_XIP_KERNEL),y)
 
 $(obj)/xipImage: vmlinux FORCE
 	$(call if_changed,objcopy)
-	@$(kecho) '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
+	@$(kecho) '  Physical Address of xipImage: $(CONFIG_XIP_PHYS_ADDR)'
 
 $(obj)/Image $(obj)/zImage: FORCE
 	@echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)'
@@ -46,14 +46,12 @@ $(obj)/xipImage: FORCE
 
 $(obj)/Image: vmlinux FORCE
 	$(call if_changed,objcopy)
-	@$(kecho) '  Kernel: $@ is ready'
 
 $(obj)/compressed/vmlinux: $(obj)/Image FORCE
 	$(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
 $(obj)/zImage:	$(obj)/compressed/vmlinux FORCE
 	$(call if_changed,objcopy)
-	@$(kecho) '  Kernel: $@ is ready'
 
 endif
 
@@ -78,14 +76,12 @@ fi
 $(obj)/uImage:	$(obj)/zImage FORCE
 	@$(check_for_multiple_loadaddr)
 	$(call if_changed,uimage)
-	@$(kecho) '  Image $@ is ready'
 
 $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
 	$(Q)$(MAKE) $(build)=$(obj)/bootp $@
 
 $(obj)/bootpImage: $(obj)/bootp/bootp FORCE
 	$(call if_changed,objcopy)
-	@$(kecho) '  Kernel: $@ is ready'
 
 PHONY += initrd install zinstall uinstall
 initrd:
-- 
1.9.1



From yamada.masahiro at socionext.com  Sun May 29 19:12:33 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Mon, 30 May 2016 11:12:33 +0900
Subject: [PATCH] arm64: dts: drop "arm,
 amba-bus" in favor of "simple-bus" part 2
Message-ID: <1464574353-31477-1-git-send-email-yamada.masahiro@socionext.com>

Tree-wide replacement was done by commit 2ef7d5f342c1 (ARM, ARM64:
dts: drop "arm,amba-bus" in favor of "simple-bus"), but we have some
new users of "arm,amba-bus" at Linux 4.7-rc1.  Eliminate them now.

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

In order to not leave these compatible strings for the release,
is it OK to apply this patch for Linux 4.7 ?



 arch/arm64/boot/dts/lg/lg1312.dtsi       | 2 +-
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/lg/lg1312.dtsi b/arch/arm64/boot/dts/lg/lg1312.dtsi
index 3a4e9a2..fbafa24 100644
--- a/arch/arm64/boot/dts/lg/lg1312.dtsi
+++ b/arch/arm64/boot/dts/lg/lg1312.dtsi
@@ -125,7 +125,7 @@
 		#size-cells = <1>;
 		#interrupts-cells = <3>;
 
-		compatible = "arm,amba-bus";
+		compatible = "simple-bus";
 		interrupt-parent = <&gic>;
 		ranges;
 
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 46f325a..d7f8e06 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -163,7 +163,7 @@
 	};
 
 	amba {
-		compatible = "arm,amba-bus";
+		compatible = "simple-bus";
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
-- 
1.9.1



From shijie.huang at arm.com  Sun May 29 19:12:49 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:12:49 +0800
Subject: [PATCH] arm64: fix the wrong comment
Message-ID: <1464574369-22618-1-git-send-email-shijie.huang@arm.com>

Currently, we use the 48-bit for the kernel and user by default.
The comment becomes stale. This patch fixes the wrong comment.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/mm/proc.S | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index c431787..421386759 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -209,8 +209,8 @@ ENTRY(__cpu_setup)
 	bic	x0, x0, x5			// clear bits
 	orr	x0, x0, x6			// set bits
 	/*
-	 * Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for
-	 * both user and kernel.
+	 * Set/prepare TCR. We use VA_BITS of address range for both
+	 * kernel and user.
 	 */
 	ldr	x10, =TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \
 			TCR_TG_FLAGS | TCR_ASID16 | TCR_TBI0
-- 
2.5.5



From shijie.huang at arm.com  Sun May 29 19:14:26 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:14:26 +0800
Subject: [PATCH 1/3] arm64: move the PTE_VALID to pgtable-hwdef.h
Message-ID: <1464574468-22700-1-git-send-email-shijie.huang@arm.com>

The PTE_VALID is used to check whether the page descriptor is valid.
It's not a software defined PTE bits, such as PTE_WRITE/PTE_DIRTY.

So move it to the proper header file: pgtable-hwdef.h.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/include/asm/pgtable-hwdef.h | 1 +
 arch/arm64/include/asm/pgtable-prot.h  | 1 -
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 2813748..eeb3269 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -154,6 +154,7 @@
 #define PTE_TYPE_MASK		(_AT(pteval_t, 3) << 0)
 #define PTE_TYPE_FAULT		(_AT(pteval_t, 0) << 0)
 #define PTE_TYPE_PAGE		(_AT(pteval_t, 3) << 0)
+#define PTE_VALID		(_AT(pteval_t, 1) << 0)
 #define PTE_TABLE_BIT		(_AT(pteval_t, 1) << 1)
 #define PTE_USER		(_AT(pteval_t, 1) << 6)		/* AP[1] */
 #define PTE_RDONLY		(_AT(pteval_t, 1) << 7)		/* AP[2] */
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index 29fcb33..5ac71f4 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -24,7 +24,6 @@
 /*
  * Software defined PTE bits definition.
  */
-#define PTE_VALID		(_AT(pteval_t, 1) << 0)
 #define PTE_WRITE		(PTE_DBM)		 /* same as DBM (51) */
 #define PTE_DIRTY		(_AT(pteval_t, 1) << 55)
 #define PTE_SPECIAL		(_AT(pteval_t, 1) << 56)
-- 
2.5.5



From shijie.huang at arm.com  Sun May 29 19:14:27 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:14:27 +0800
Subject: [PATCH 2/3] arm64: fix the wrong type
In-Reply-To: <1464574468-22700-1-git-send-email-shijie.huang@arm.com>
References: <1464574468-22700-1-git-send-email-shijie.huang@arm.com>
Message-ID: <1464574468-22700-2-git-send-email-shijie.huang@arm.com>

We should use the pudval_t for the PUD_* macros, not the pgdval_t.
This patch fixes them.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/include/asm/pgtable-hwdef.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index eeb3269..54e2fbf 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -116,9 +116,9 @@
  * Level 1 descriptor (PUD).
  */
 #define PUD_TYPE_TABLE		(_AT(pudval_t, 3) << 0)
-#define PUD_TABLE_BIT		(_AT(pgdval_t, 1) << 1)
-#define PUD_TYPE_MASK		(_AT(pgdval_t, 3) << 0)
-#define PUD_TYPE_SECT		(_AT(pgdval_t, 1) << 0)
+#define PUD_TABLE_BIT		(_AT(pudval_t, 1) << 1)
+#define PUD_TYPE_MASK		(_AT(pudval_t, 3) << 0)
+#define PUD_TYPE_SECT		(_AT(pudval_t, 1) << 0)
 
 /*
  * Level 2 descriptor (PMD).
-- 
2.5.5



From shijie.huang at arm.com  Sun May 29 19:14:28 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:14:28 +0800
Subject: [PATCH 3/3] arm64: add a new macro for the pgd table descriptor
In-Reply-To: <1464574468-22700-1-git-send-email-shijie.huang@arm.com>
References: <1464574468-22700-1-git-send-email-shijie.huang@arm.com>
Message-ID: <1464574468-22700-3-git-send-email-shijie.huang@arm.com>

Add a new macro for the pgd table descriptor to define the "Table"
type, and use it to replace the numerical constant in the pgd_bad().

This patch makes the code more legible.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/include/asm/pgtable-hwdef.h | 5 +++++
 arch/arm64/include/asm/pgtable.h       | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 54e2fbf..f648c28 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -113,6 +113,11 @@
 /*
  * Hardware page table definitions.
  *
+ * Level 0 descriptor (PGD).
+ */
+#define PGD_TABLE_BIT		(_AT(pgdval_t, 1) << 1)
+
+/*
  * Level 1 descriptor (PUD).
  */
 #define PUD_TYPE_TABLE		(_AT(pudval_t, 3) << 0)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 46472a9..bfa0092 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -453,7 +453,7 @@ static inline phys_addr_t pud_page_paddr(pud_t pud)
 #define pud_ERROR(pud)		__pud_error(__FILE__, __LINE__, pud_val(pud))
 
 #define pgd_none(pgd)		(!pgd_val(pgd))
-#define pgd_bad(pgd)		(!(pgd_val(pgd) & 2))
+#define pgd_bad(pgd)		(!(pgd_val(pgd) & PGD_TABLE_BIT))
 #define pgd_present(pgd)	(pgd_val(pgd))
 
 static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
-- 
2.5.5



From xinliang.liu at linaro.org  Sun May 29 19:31:53 2016
From: xinliang.liu at linaro.org (Xinliang Liu)
Date: Mon, 30 May 2016 10:31:53 +0800
Subject: [path v2 7/7] drm/hisilicon/hibmc: Add maintainer for Hibmc DRM
In-Reply-To: <1464514855-108050-8-git-send-email-zourongrong@gmail.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
 <1464514855-108050-8-git-send-email-zourongrong@gmail.com>
Message-ID: <CAGd==07sV0qaDES5D5ozvkC1FDQXZ-Z9_UCNX8vO09HKBktq3w@mail.gmail.com>

On 29 May 2016 at 17:40, Rongrong Zou <zourongrong at gmail.com> wrote:
> Signed-off-by: Rongrong Zou <zourongrong at gmail.com>
> Signed-off-by: Jianhua Li <lijianhua at huawei.com>
> ---
>  MAINTAINERS | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f466673..a8a62e0 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -3957,6 +3957,13 @@ T:       git git://github.com/patjak/drm-gma500
>  S:     Maintained
>  F:     drivers/gpu/drm/gma500/
>
> +DRM DRIVERS FOR HIBMC
> +M:     lijianhua <lijianhua at huawei.com>
> +M:     Rongrong Zou <zourongrong at gmail.com>
> +L:     dri-devel at lists.freedesktop.org
> +S:     Maintained
> +F:     drivers/gpu/drm/hisilicon/hibmc

Please add a "/" ad the end of this line.
And move this part into DRM DRIVERS FOR HISILICON

Thanks,
-xinliang

> +
>  DRM DRIVERS FOR HISILICON
>  M:     Xinliang Liu <z.liuxinliang at hisilicon.com>
>  R:     Xinwei Kong <kong.kongxinwei at hisilicon.com>
> --
> 1.9.1
>


From shijie.huang at arm.com  Sun May 29 19:52:21 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:52:21 +0800
Subject: [PATCH 0/9] arm64: add more accurate code for tracing the hardirq
 flags changes
Message-ID: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>

In the current arm64 code, we trace the hardirq flags change occasionally.
Sometimes, the trace code is buggy, such as the el0_irq.

This patch sets 
   0.) in order to avoid the save/restore registers, add patches to adjust
        the code.
   1.) add the trace code at the entry/exit, 
   2.) add the trace code at the irq macros.
   3.) removes the duplicated trace code.

I tested this patch set with CONFIG_PROVE_LOCKING/CONFIG_LOCKDEP/CONFIG_LOCK_STAT
enabled in the Juno-r1 board.

The whole patch set is based on the patch: 
    http://lists.infradead.org/pipermail/linux-arm-kernel/2016-April/420154.html

Thanks to the code review of Steve/James/Mark, I really appriciate it.

Huang Shijie (9):
  arm64: entry: use the callee-saved registers to save some registers
  arm64: entry: add a new macro to restore the registers for syscall
  arm64: entry: record the hardirq changes on the entry/exit code
  arm64: entry: remove the duplicated code for tracing the IRQ flags
  arm64: entry: only restore the syscall registers once
  arm64: entry: adjust el1_sync so that a function can be called
  arm64: entry: save the x0 back into the stack before disabling the
    interrupt
  arm64: add the hardirq flags trace code for irq macros
  arm64: entry: remove the duplicated hardirq flags trace code

 arch/arm64/include/asm/assembler.h |  9 ++++
 arch/arm64/kernel/entry.S          | 88 ++++++++++++++++++++++----------------
 arch/arm64/kernel/signal.c         |  6 ---
 arch/arm64/mm/fault.c              | 10 -----
 4 files changed, 59 insertions(+), 54 deletions(-)

-- 
2.5.5



From shijie.huang at arm.com  Sun May 29 19:52:25 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:52:25 +0800
Subject: [PATCH 4/9] arm64: entry: remove the duplicated code for tracing the
 IRQ flags
In-Reply-To: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
References: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
Message-ID: <1464576750-25160-5-git-send-email-shijie.huang@arm.com>

We record the hardirq flags changes in the entry/exit code now,
So the code becomes duplicated, just remove it.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/kernel/entry.S | 12 ------------
 arch/arm64/mm/fault.c     | 10 ----------
 2 files changed, 22 deletions(-)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 4c67c56..102fd8b 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -428,9 +428,6 @@ ENDPROC(el1_sync)
 el1_irq:
 	kernel_entry 1
 	enable_dbg
-#ifdef CONFIG_TRACE_IRQFLAGS
-	bl	trace_hardirqs_off
-#endif
 
 	get_thread_info tsk
 	irq_handler
@@ -443,9 +440,6 @@ el1_irq:
 	bl	el1_preempt
 1:
 #endif
-#ifdef CONFIG_TRACE_IRQFLAGS
-	bl	trace_hardirqs_on
-#endif
 	kernel_exit 1
 ENDPROC(el1_irq)
 
@@ -632,16 +626,10 @@ el0_irq:
 	kernel_entry 0
 el0_irq_naked:
 	enable_dbg
-#ifdef CONFIG_TRACE_IRQFLAGS
-	bl	trace_hardirqs_off
-#endif
 
 	ct_user_exit
 	irq_handler
 
-#ifdef CONFIG_TRACE_IRQFLAGS
-	bl	trace_hardirqs_on
-#endif
 	b	ret_to_user
 ENDPROC(el0_irq)
 
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 5954881..f94e598 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -603,13 +603,6 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
 	struct siginfo info;
 	int rv;
 
-	/*
-	 * Tell lockdep we disabled irqs in entry.S. Do nothing if they were
-	 * already disabled to preserve the last enabled/disabled addresses.
-	 */
-	if (interrupts_enabled(regs))
-		trace_hardirqs_off();
-
 	if (!inf->fn(addr, esr, regs)) {
 		rv = 1;
 	} else {
@@ -624,9 +617,6 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
 		rv = 0;
 	}
 
-	if (interrupts_enabled(regs))
-		trace_hardirqs_on();
-
 	return rv;
 }
 
-- 
2.5.5



From shijie.huang at arm.com  Sun May 29 19:52:24 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:52:24 +0800
Subject: [PATCH 3/9] arm64: entry: record the hardirq changes on the
 entry/exit code
In-Reply-To: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
References: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
Message-ID: <1464576750-25160-4-git-send-email-shijie.huang@arm.com>

Just as the arm32 code does, record the hardirq changes at the entry/exit
code.

The trace code may changes some registers, but the syscall path
needs the x0 ~ x7, we restore them in the el0_svc_naked.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/kernel/entry.S | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 21b6068..4c67c56 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -132,6 +132,15 @@
 	mov	scno, x8
 	.endif
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+	/*
+	 * The trace_hardirqs_off may changes some registers, so we should
+	 * restore them back from the stack in the necessary place, such as
+	 * el0_svc_naked.
+	 */
+	bl	trace_hardirqs_off
+#endif
+
 	/*
 	 * Registers that may be useful after this macro is invoked:
 	 *
@@ -142,6 +151,9 @@
 	.endm
 
 	.macro	kernel_exit, el
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_on
+#endif
 	ldp	x21, x22, [sp, #S_PC]		// load ELR, SPSR
 	.if	\el == 0
 	ct_user_enter
@@ -729,6 +741,9 @@ el0_svc:
 	uxtw	scno, w26			// syscall number in w8
 	mov	sc_nr, #__NR_syscalls
 el0_svc_naked:					// compat entry point
+#ifdef CONFIG_TRACE_IRQFLAGS
+	restore_syscall_regs
+#endif
 	stp	x19, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
 	enable_dbg_and_irq
 	ct_user_exit 1
-- 
2.5.5



From shijie.huang at arm.com  Sun May 29 19:52:23 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:52:23 +0800
Subject: [PATCH 2/9] arm64: entry: add a new macro to restore the registers
 for syscall
In-Reply-To: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
References: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
Message-ID: <1464576750-25160-3-git-send-email-shijie.huang@arm.com>

This patch adds restore_syscall_regs to restore the x0~x7 arguments from
the stack.
And this patch also uses this macro to simplify the code.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/kernel/entry.S | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 7dcfd49..21b6068 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -32,6 +32,17 @@
 #include <asm/unistd.h>
 
 /*
+ * Use this macro to restore the syscall arguments from the
+ * values already saved on the stack during kernel_entry.
+ */
+	.macro restore_syscall_regs
+	ldp	x0, x1, [sp]
+	ldp	x2, x3, [sp, #S_X2]
+	ldp	x4, x5, [sp, #S_X4]
+	ldp	x6, x7, [sp, #S_X6]
+	.endm
+
+/*
  * Context tracking subsystem.  Used to instrument transitions
  * between user and kernel mode.
  */
@@ -39,14 +50,7 @@
 #ifdef CONFIG_CONTEXT_TRACKING
 	bl	context_tracking_user_exit
 	.if \syscall == 1
-	/*
-	 * Save/restore needed during syscalls.  Restore syscall arguments from
-	 * the values already saved on stack during kernel_entry.
-	 */
-	ldp	x0, x1, [sp]
-	ldp	x2, x3, [sp, #S_X2]
-	ldp	x4, x5, [sp, #S_X4]
-	ldp	x6, x7, [sp, #S_X6]
+	restore_syscall_regs
 	.endif
 #endif
 	.endm
@@ -761,10 +765,7 @@ __sys_trace:
 	mov	x1, sp				// pointer to regs
 	cmp	scno, sc_nr			// check upper syscall limit
 	b.hs	__ni_sys_trace
-	ldp	x0, x1, [sp]			// restore the syscall args
-	ldp	x2, x3, [sp, #S_X2]
-	ldp	x4, x5, [sp, #S_X4]
-	ldp	x6, x7, [sp, #S_X6]
+	restore_syscall_regs
 	ldr	x16, [stbl, scno, lsl #3]	// address in the syscall table
 	blr	x16				// call sys_* routine
 
-- 
2.5.5



From shijie.huang at arm.com  Sun May 29 19:52:28 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:52:28 +0800
Subject: [PATCH 7/9] arm64: entry: save the x0 back into the stack before
 disabling the interrupt
In-Reply-To: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
References: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
Message-ID: <1464576750-25160-8-git-send-email-shijie.huang@arm.com>

We will add the hardirq flags trace code in the disable_irq, the trace
code may changes the x0, so save the x0 back into the stack before
disabling the interrupt,

This patch makes preparation for the later patch.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/kernel/entry.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 63bf7ad..7005789 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -672,8 +672,8 @@ ENDPROC(cpu_switch_to)
  * and this includes saving x0 back into the kernel stack.
  */
 ret_fast_syscall:
-	disable_irq				// disable interrupts
 	str	x0, [sp, #S_X0]			// returned x0
+	disable_irq				// disable interrupts
 	ldr	x1, [tsk, #TI_FLAGS]		// re-check for syscall tracing
 	and	x2, x1, #_TIF_SYSCALL_WORK
 	cbnz	x2, ret_fast_syscall_trace
-- 
2.5.5



From shijie.huang at arm.com  Sun May 29 19:52:27 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:52:27 +0800
Subject: [PATCH 6/9] arm64: entry: adjust el1_sync so that a function can be
 called
In-Reply-To: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
References: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
Message-ID: <1464576750-25160-7-git-send-email-shijie.huang@arm.com>

To implement the hardirq flag tracing properly on arm64,
the trace_hardirqs_on() should be called before interrupts are turned on.
But the trace_hardirqs_on() may clobber the registers, such as x0 ~ 18.

Just as the el0_sync does, this patch uses the callee-saved registers:
   1.) uses x25 to save the esr_el1,
   2.) uses the x26 to save the far_el1.

And copy x25/x26 back to x1/x0 in the proper places, such as
el1_da/el1_dbg/el1_sp_pc.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/kernel/entry.S | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 98d8dd1..63bf7ad 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -355,8 +355,8 @@ ENDPROC(el1_error_invalid)
 	.align	6
 el1_sync:
 	kernel_entry 1
-	mrs	x1, esr_el1			// read the syndrome register
-	lsr	x24, x1, #ESR_ELx_EC_SHIFT	// exception class
+	mrs	x25, esr_el1			// read the syndrome register
+	lsr	x24, x25, #ESR_ELx_EC_SHIFT	// exception class
 	cmp	x24, #ESR_ELx_EC_DABT_CUR	// data abort in EL1
 	b.eq	el1_da
 	cmp	x24, #ESR_ELx_EC_SYS64		// configurable trap
@@ -374,12 +374,14 @@ el1_da:
 	/*
 	 * Data abort handling
 	 */
-	mrs	x0, far_el1
+	mrs	x26, far_el1
 	enable_dbg
 	// re-enable interrupts if they were enabled in the aborted context
 	tbnz	x23, #7, 1f			// PSR_I_BIT
 	enable_irq
 1:
+	mov	x0, x26
+	mov	x1, x25
 	mov	x2, sp				// struct pt_regs
 	bl	do_mem_abort
 
@@ -392,6 +394,7 @@ el1_sp_pc:
 	 */
 	mrs	x0, far_el1
 	enable_dbg
+	mov	x1, x25
 	mov	x2, sp
 	b	do_sp_pc_abort
 el1_undef:
@@ -409,6 +412,7 @@ el1_dbg:
 	cinc	x24, x24, eq			// set bit '0'
 	tbz	x24, #0, el1_inv		// EL1 only
 	mrs	x0, far_el1
+	mov	x1, x25
 	mov	x2, sp				// struct pt_regs
 	bl	do_debug_exception
 	kernel_exit 1
-- 
2.5.5



From shijie.huang at arm.com  Sun May 29 19:52:26 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:52:26 +0800
Subject: [PATCH 5/9] arm64: entry: only restore the syscall registers once
In-Reply-To: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
References: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
Message-ID: <1464576750-25160-6-git-send-email-shijie.huang@arm.com>

There are two pachs which will restore the syscall registers (x0 - x7)
separately: the hardirq trace code and the context tracking code.

This patch makes the code to restore the syscall registers only once.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/kernel/entry.S | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 102fd8b..98d8dd1 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -46,12 +46,9 @@
  * Context tracking subsystem.  Used to instrument transitions
  * between user and kernel mode.
  */
-	.macro ct_user_exit, syscall = 0
+	.macro ct_user_exit
 #ifdef CONFIG_CONTEXT_TRACKING
 	bl	context_tracking_user_exit
-	.if \syscall == 1
-	restore_syscall_regs
-	.endif
 #endif
 	.endm
 
@@ -729,12 +726,12 @@ el0_svc:
 	uxtw	scno, w26			// syscall number in w8
 	mov	sc_nr, #__NR_syscalls
 el0_svc_naked:					// compat entry point
-#ifdef CONFIG_TRACE_IRQFLAGS
-	restore_syscall_regs
-#endif
 	stp	x19, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
 	enable_dbg_and_irq
-	ct_user_exit 1
+	ct_user_exit
+#if defined(CONFIG_TRACE_IRQFLAGS) || defined(CONFIG_CONTEXT_TRACKING)
+	restore_syscall_regs
+#endif
 
 	ldr	x16, [tsk, #TI_FLAGS]		// check for syscall hooks
 	tst	x16, #_TIF_SYSCALL_WORK
-- 
2.5.5



From shijie.huang at arm.com  Sun May 29 19:52:22 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:52:22 +0800
Subject: [PATCH 1/9] arm64: entry: use the callee-saved registers to save some
 registers
In-Reply-To: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
References: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
Message-ID: <1464576750-25160-2-git-send-email-shijie.huang@arm.com>

This patch uses the callee-saved registers x19/x20/scno to save the
x0/x7/x8 which will be used in the syscall path.

This patch makes preparation for the trace code.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/kernel/entry.S | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index d70a9e4..7dcfd49 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -119,6 +119,16 @@
 	.endif
 
 	/*
+	 * Save the x0/x7/x8 in the Callee-saved registers.
+	 * We will use them in the syscall path.
+	 */
+	.if	\el == 0
+	mov	x19, x0
+	mov	x20, x7
+	mov	scno, x8
+	.endif
+
+	/*
 	 * Registers that may be useful after this macro is invoked:
 	 *
 	 * x21 - aborted SP
@@ -500,7 +510,7 @@ el0_svc_compat:
 	 * AArch32 syscall handling
 	 */
 	adrp	stbl, compat_sys_call_table	// load compat syscall table pointer
-	uxtw	scno, w7			// syscall number in w7 (r7)
+	uxtw	scno, w20			// syscall number in w7 (r7)
 	mov     sc_nr, #__NR_compat_syscalls
 	b	el0_svc_naked
 
@@ -712,10 +722,10 @@ ENDPROC(ret_from_fork)
 	.align	6
 el0_svc:
 	adrp	stbl, sys_call_table		// load syscall table pointer
-	uxtw	scno, w8			// syscall number in w8
+	uxtw	scno, w26			// syscall number in w8
 	mov	sc_nr, #__NR_syscalls
 el0_svc_naked:					// compat entry point
-	stp	x0, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
+	stp	x19, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
 	enable_dbg_and_irq
 	ct_user_exit 1
 
-- 
2.5.5



From shijie.huang at arm.com  Sun May 29 19:52:29 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:52:29 +0800
Subject: [PATCH 8/9] arm64: add the hardirq flags trace code for irq macros
In-Reply-To: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
References: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
Message-ID: <1464576750-25160-9-git-send-email-shijie.huang@arm.com>

This patch adds the hardirq flags trace code for irq macros.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/include/asm/assembler.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 10b017c..0be1d29 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -34,9 +34,15 @@
  */
 	.macro	disable_irq
 	msr	daifset, #2
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_off
+#endif
 	.endm
 
 	.macro	enable_irq
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_on
+#endif
 	msr	daifclr, #2
 	.endm
 
@@ -75,6 +81,9 @@
  * are self-synchronising.
  */
 	.macro	enable_dbg_and_irq
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_on
+#endif
 	msr	daifclr, #(8 | 2)
 	.endm
 
-- 
2.5.5



From shijie.huang at arm.com  Sun May 29 19:52:30 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Mon, 30 May 2016 10:52:30 +0800
Subject: [PATCH 9/9] arm64: entry: remove the duplicated hardirq flags trace
 code
In-Reply-To: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
References: <1464576750-25160-1-git-send-email-shijie.huang@arm.com>
Message-ID: <1464576750-25160-10-git-send-email-shijie.huang@arm.com>

We have added the trace code to the interrupt enable/disable macros,
so the trace code in work_pending and do_notify_resume are
duplicated, just remove them.

Signed-off-by: Huang Shijie <shijie.huang at arm.com>
---
 arch/arm64/kernel/entry.S  | 3 ---
 arch/arm64/kernel/signal.c | 6 ------
 2 files changed, 9 deletions(-)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 7005789..b6edb55 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -691,9 +691,6 @@ ret_fast_syscall_trace:
 work_pending:
 	mov	x0, sp				// 'regs'
 	bl	do_notify_resume
-#ifdef CONFIG_TRACE_IRQFLAGS
-	bl	trace_hardirqs_on		// enabled while in userspace
-#endif
 	ldr	x1, [tsk, #TI_FLAGS]		// re-check for single-step
 	b	finish_ret_to_user
 /*
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 404dd67..56fdcb2 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -402,12 +402,6 @@ static void do_signal(struct pt_regs *regs)
 asmlinkage void do_notify_resume(struct pt_regs *regs,
 				 unsigned int thread_flags)
 {
-	/*
-	 * The assembly code enters us with IRQs off, but it hasn't
-	 * informed the tracing code of that for efficiency reasons.
-	 * Update the trace code with the current status.
-	 */
-	trace_hardirqs_off();
 	do {
 		if (thread_flags & _TIF_NEED_RESCHED) {
 			schedule();
-- 
2.5.5



From xinliang.liu at linaro.org  Sun May 29 20:01:33 2016
From: xinliang.liu at linaro.org (Xinliang Liu)
Date: Mon, 30 May 2016 11:01:33 +0800
Subject: [path v2 0/7] Add DRM driver for Hisilicon Hibmc
In-Reply-To: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
Message-ID: <CAGd==0662wa-mAdX+tUf9_Tw6qQhc0-D5ivSYdRBS=OrqAVYnA@mail.gmail.com>

Hi Rongrong,

It seems that you haven't run the checkpatch script.
Please run this script to check your patches before you send them. Like bellow:
$ cd yourkerneldir
$ ./scripts/checkpatch.pl --strict yourpatches

Thanks,
-xinliang

On 29 May 2016 at 17:40, Rongrong Zou <zourongrong at gmail.com> wrote:
> This patch set adds a new drm driver for Hisilicon Hibmc. Hibmc is a
> base board management controller, usually it is used on server for
> Out-of-band management purpose. In this patch set, we just support basic
> function for Hibmc display subsystem. Hibmc display subsystem is connected
> to host CPU by PCIe as blow:
>
> +----------+       +----------+
> |          | PCIe  |  Hibmc   |
> |host CPU( |<----->| display  |
> |arm64,x86)|       |subsystem |
> +----------+       +----------+
>
> Hardware Detail for Hibmc display subsystem
> -----------
>
>   The display subsystem of Hibmc is show as bellow:
>   +----+      +----+      +----+     +--------+
>   |    |      |    |      |    |     |        |
>   | FB |----->| DE |----->|VDAC|---->|external|
>   |    |      |    |      |    |     | VGA    |
>   +----+      +----+      +----+     +--------+
>
>   -DE(Display Engine) is the display controller.
>   -VDAC(Video Digital-to-Analog converter) converts the RGB diaital data
>   stream from DE to VGA analog signals.
>
> Change History
> ------------
>
> Changes in v2:
>   -Remove self-defined macros for bit operations.
>   -Remove unused register.
>   -Replace those deprecated functions with new version of them.
>   -use drm_connector_register_all() to register connector after
>    drm_dev_register().
>
> The patch v1 is at
> https://lists.freedesktop.org/archives/dri-devel/2016-February/101921.html
> Sorry for too late sending.
>
>
> Rongrong Zou (7):
>   idrm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
>   drm/hisilicon/hibmc: Add plane for DE
>   drm/hisilicon/hibmc: Add crtc for DE
>   drm/hisilicon/hibmc: Add encoder for VDAC
>   drm/hisilicon/hibmc: Add connector for VDAC
>   drm/hisilicon/hibmc: Add support for frame buffer
>   drm/hisilicon/hibmc: Add maintainer for Hibmc DRM
>
>  MAINTAINERS                                       |   7 +
>  drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
>  drivers/gpu/drm/hisilicon/Makefile                |   3 +-
>  drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
>  drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c    | 477 ++++++++++++++++++++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h    |  29 ++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 399 ++++++++++++++++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  64 +++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 286 +++++++++++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 ++++++++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c  | 174 ++++++++
>  14 files changed, 1789 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
>
> --
> 1.9.1
>


From zourongrong at huawei.com  Sun May 29 20:11:38 2016
From: zourongrong at huawei.com (Rongrong Zou)
Date: Mon, 30 May 2016 11:11:38 +0800
Subject: [path v2 0/7] Add DRM driver for Hisilicon Hibmc
In-Reply-To: <CAGd==0662wa-mAdX+tUf9_Tw6qQhc0-D5ivSYdRBS=OrqAVYnA@mail.gmail.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
 <CAGd==0662wa-mAdX+tUf9_Tw6qQhc0-D5ivSYdRBS=OrqAVYnA@mail.gmail.com>
Message-ID: <574BAF6A.9040208@huawei.com>

Hi Xinliang

? 2016/5/30 11:01, Xinliang Liu ??:
> Hi Rongrong,
>
> It seems that you haven't run the checkpatch script.
> Please run this script to check your patches before you send them. Like bellow:
> $ cd yourkerneldir
> $ ./scripts/checkpatch.pl --strict yourpatches

I run checkpatch.pl without "--strict", and i'll check again with
this parameter, thanks!

>
> Thanks,
> -xinliang
>
> On 29 May 2016 at 17:40, Rongrong Zou <zourongrong at gmail.com> wrote:
>> This patch set adds a new drm driver for Hisilicon Hibmc. Hibmc is a
>> base board management controller, usually it is used on server for
>> Out-of-band management purpose. In this patch set, we just support basic
>> function for Hibmc display subsystem. Hibmc display subsystem is connected
>> to host CPU by PCIe as blow:
>>
>> +----------+       +----------+
>> |          | PCIe  |  Hibmc   |
>> |host CPU( |<----->| display  |
>> |arm64,x86)|       |subsystem |
>> +----------+       +----------+
>>
>> Hardware Detail for Hibmc display subsystem
>> -----------
>>
>>    The display subsystem of Hibmc is show as bellow:
>>    +----+      +----+      +----+     +--------+
>>    |    |      |    |      |    |     |        |
>>    | FB |----->| DE |----->|VDAC|---->|external|
>>    |    |      |    |      |    |     | VGA    |
>>    +----+      +----+      +----+     +--------+
>>
>>    -DE(Display Engine) is the display controller.
>>    -VDAC(Video Digital-to-Analog converter) converts the RGB diaital data
>>    stream from DE to VGA analog signals.
>>
>> Change History
>> ------------
>>
>> Changes in v2:
>>    -Remove self-defined macros for bit operations.
>>    -Remove unused register.
>>    -Replace those deprecated functions with new version of them.
>>    -use drm_connector_register_all() to register connector after
>>     drm_dev_register().
>>
>> The patch v1 is at
>> https://lists.freedesktop.org/archives/dri-devel/2016-February/101921.html
>> Sorry for too late sending.
>>
>>
>> Rongrong Zou (7):
>>    idrm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
>>    drm/hisilicon/hibmc: Add plane for DE
>>    drm/hisilicon/hibmc: Add crtc for DE
>>    drm/hisilicon/hibmc: Add encoder for VDAC
>>    drm/hisilicon/hibmc: Add connector for VDAC
>>    drm/hisilicon/hibmc: Add support for frame buffer
>>    drm/hisilicon/hibmc: Add maintainer for Hibmc DRM
>>
>>   MAINTAINERS                                       |   7 +
>>   drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
>>   drivers/gpu/drm/hisilicon/Makefile                |   3 +-
>>   drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
>>   drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c    | 477 ++++++++++++++++++++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h    |  29 ++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 399 ++++++++++++++++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  64 +++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 286 +++++++++++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 ++++++++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c  | 174 ++++++++
>>   14 files changed, 1789 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
>>
>> --
>> 1.9.1
>>
>
> .
>


-- 
Regards,
Rongrong


From hs.liao at mediatek.com  Sun May 29 20:19:54 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Mon, 30 May 2016 11:19:54 +0800
Subject: [PATCH v8 0/3] Mediatek MT8173 CMDQ support
Message-ID: <1464578397-29743-1-git-send-email-hs.liao@mediatek.com>


Hi,

This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used
to help read/write registers with critical time limitation, such as
updating display configuration during the vblank. It controls Global
Command Engine (GCE) hardware to achieve this requirement.

These patches have a build dependency on top of v4.6-rc1.

Changes since v7:
 - fix one v6 bug and one v7 bug, which are due to rewriting for coding style
 - use flushing work queue instead of killing active tasks in suspend and
   merge suspend/resume protection patch into CMDQ driver patch
 - refine some code accroding to comments for v7

Best regards,
HS Liao

HS Liao (3):
  dt-bindings: soc: Add documentation for the MediaTek GCE unit
  CMDQ: Mediatek CMDQ driver
  arm64: dts: mt8173: Add GCE node

 .../devicetree/bindings/soc/mediatek/gce.txt       |  34 +
 arch/arm64/boot/dts/mediatek/mt8173.dtsi           |   8 +
 drivers/soc/mediatek/Kconfig                       |  10 +
 drivers/soc/mediatek/Makefile                      |   1 +
 drivers/soc/mediatek/mtk-cmdq.c                    | 943 +++++++++++++++++++++
 include/soc/mediatek/cmdq.h                        | 197 +++++
 6 files changed, 1193 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/gce.txt
 create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
 create mode 100644 include/soc/mediatek/cmdq.h

-- 
1.9.1



From hs.liao at mediatek.com  Sun May 29 20:19:55 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Mon, 30 May 2016 11:19:55 +0800
Subject: [PATCH v8 1/3] dt-bindings: soc: Add documentation for the MediaTek
 GCE unit
In-Reply-To: <1464578397-29743-1-git-send-email-hs.liao@mediatek.com>
References: <1464578397-29743-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1464578397-29743-2-git-send-email-hs.liao@mediatek.com>

This adds documentation for the MediaTek Global Command Engine (GCE) unit
found in MT8173 SoCs.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/soc/mediatek/gce.txt       | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/mediatek/gce.txt

diff --git a/Documentation/devicetree/bindings/soc/mediatek/gce.txt b/Documentation/devicetree/bindings/soc/mediatek/gce.txt
new file mode 100644
index 0000000..eff07e2
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/mediatek/gce.txt
@@ -0,0 +1,34 @@
+MediaTek GCE
+===============
+
+The Global Command Engine (GCE) is used to help read/write registers with
+critical time limitation, such as updating display configuration during the
+vblank. The GCE can be used to implement the Command Queue (CMDQ) driver.
+
+Required properties:
+- compatible: Must be "mediatek,mt8173-gce"
+- reg: Address range of the GCE unit
+- interrupts: The interrupt signal from the GCE block
+- clock: Clocks according to the common clock binding
+- clock-names: Must be "gce" to stand for GCE clock
+
+Required properties for a client device:
+- mediatek,gce: Should point to the respective GCE block
+
+Example:
+
+	gce: gce at 10212000 {
+		compatible = "mediatek,mt8173-gce";
+		reg = <0 0x10212000 0 0x1000>;
+		interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&infracfg CLK_INFRA_GCE>;
+		clock-names = "gce";
+	};
+
+Example for a client device:
+
+	mmsys: clock-controller at 14000000 {
+		compatible = "mediatek,mt8173-mmsys";
+		mediatek,gce = <&gce>;
+		...
+	};
-- 
1.9.1



From hs.liao at mediatek.com  Sun May 29 20:19:56 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Mon, 30 May 2016 11:19:56 +0800
Subject: [PATCH v8 2/3] CMDQ: Mediatek CMDQ driver
In-Reply-To: <1464578397-29743-1-git-send-email-hs.liao@mediatek.com>
References: <1464578397-29743-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1464578397-29743-3-git-send-email-hs.liao@mediatek.com>

This patch is first version of Mediatek Command Queue(CMDQ) driver. The
CMDQ is used to help read/write registers with critical time limitation,
such as updating display configuration during the vblank. It controls
Global Command Engine (GCE) hardware to achieve this requirement.
Currently, CMDQ only supports display related hardwares, but we expect
it can be extended to other hardwares for future requirements.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
Signed-off-by: CK Hu <ck.hu at mediatek.com>
---
 drivers/soc/mediatek/Kconfig    |  10 +
 drivers/soc/mediatek/Makefile   |   1 +
 drivers/soc/mediatek/mtk-cmdq.c | 943 ++++++++++++++++++++++++++++++++++++++++
 include/soc/mediatek/cmdq.h     | 197 +++++++++
 4 files changed, 1151 insertions(+)
 create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
 create mode 100644 include/soc/mediatek/cmdq.h

diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 0a4ea80..c4ad75c 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -1,6 +1,16 @@
 #
 # MediaTek SoC drivers
 #
+config MTK_CMDQ
+	bool "MediaTek CMDQ Support"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	select MTK_INFRACFG
+	help
+	  Say yes here to add support for the MediaTek Command Queue (CMDQ)
+	  driver. The CMDQ is used to help read/write registers with critical
+	  time limitation, such as updating display configuration during the
+	  vblank.
+
 config MTK_INFRACFG
 	bool "MediaTek INFRACFG Support"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index 12998b0..f7397ef 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq.o
 obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
 obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
 obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
new file mode 100644
index 0000000..e9d6e1c
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-cmdq.c
@@ -0,0 +1,943 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/suspend.h>
+#include <linux/workqueue.h>
+#include <soc/mediatek/cmdq.h>
+
+#define CMDQ_INITIAL_CMD_BLOCK_SIZE	PAGE_SIZE
+#define CMDQ_INST_SIZE			8 /* instruction is 64-bit */
+#define CMDQ_TIMEOUT_MS			1000
+#define CMDQ_IRQ_MASK			0xffff
+#define CMDQ_DRIVER_DEVICE_NAME		"mtk_cmdq"
+#define CMDQ_CLK_NAME			"gce"
+
+#define CMDQ_CURR_IRQ_STATUS		0x010
+#define CMDQ_CURR_LOADED_THR		0x018
+#define CMDQ_THR_SLOT_CYCLES		0x030
+
+#define CMDQ_THR_BASE			0x100
+#define CMDQ_THR_SHIFT			0x080
+#define CMDQ_THR_WARM_RESET		0x00
+#define CMDQ_THR_ENABLE_TASK		0x04
+#define CMDQ_THR_SUSPEND_TASK		0x08
+#define CMDQ_THR_CURR_STATUS		0x0c
+#define CMDQ_THR_IRQ_STATUS		0x10
+#define CMDQ_THR_IRQ_ENABLE		0x14
+#define CMDQ_THR_CURR_ADDR		0x20
+#define CMDQ_THR_END_ADDR		0x24
+#define CMDQ_THR_CFG			0x40
+
+#define CMDQ_THR_ENABLED		0x1
+#define CMDQ_THR_DISABLED		0x0
+#define CMDQ_THR_SUSPEND		0x1
+#define CMDQ_THR_RESUME			0x0
+#define CMDQ_THR_STATUS_SUSPENDED	BIT(1)
+#define CMDQ_THR_DO_WARM_RESET		BIT(0)
+#define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
+#define CMDQ_THR_PRIORITY		3
+#define CMDQ_THR_IRQ_DONE		0x1
+#define CMDQ_THR_IRQ_ERROR		0x12
+#define CMDQ_THR_IRQ_EN			0x13 /* done + error */
+#define CMDQ_THR_IRQ_MASK		0x13
+#define CMDQ_THR_EXECUTING		BIT(31)
+
+#define CMDQ_ARG_A_WRITE_MASK		0xffff
+#define CMDQ_SUBSYS_MASK		0x1f
+#define CMDQ_OP_CODE_MASK		0xff000000
+
+#define CMDQ_OP_CODE_SHIFT		24
+#define CMDQ_SUBSYS_SHIFT		16
+
+#define CMDQ_WRITE_ENABLE_MASK		BIT(0)
+#define CMDQ_JUMP_BY_OFFSET		0x10000000
+#define CMDQ_JUMP_BY_PA			0x10000001
+#define CMDQ_JUMP_PASS			CMDQ_INST_SIZE
+#define CMDQ_WFE_UPDATE			BIT(31)
+#define CMDQ_WFE_WAIT			BIT(15)
+#define CMDQ_WFE_WAIT_VALUE		0x1
+#define CMDQ_EOC_IRQ_EN			BIT(0)
+
+enum cmdq_thread_index {
+	CMDQ_THR_DISP_MAIN_IDX,	/* main */
+	CMDQ_THR_DISP_SUB_IDX,	/* sub */
+	CMDQ_THR_DISP_MISC_IDX,	/* misc */
+	CMDQ_THR_MAX_COUNT,	/* max */
+};
+
+/*
+ * CMDQ_CODE_MOVE:
+ *   move value into internal register as mask
+ *   format: op mask
+ * CMDQ_CODE_WRITE:
+ *   write value into target register
+ *   format: op subsys address value
+ * CMDQ_CODE_JUMP:
+ *   jump by offset
+ *   format: op offset
+ * CMDQ_CODE_WFE:
+ *   wait for event and clear
+ *   it is just clear if no wait
+ *   format: [wait]  op event update:1 to_wait:1 wait:1
+ *           [clear] op event update:1 to_wait:0 wait:0
+ * CMDQ_CODE_EOC:
+ *   end of command
+ *   format: op irq_flag
+ */
+enum cmdq_code {
+	CMDQ_CODE_MOVE = 0x02,
+	CMDQ_CODE_WRITE = 0x04,
+	CMDQ_CODE_JUMP = 0x10,
+	CMDQ_CODE_WFE = 0x20,
+	CMDQ_CODE_EOC = 0x40,
+};
+
+enum cmdq_task_state {
+	TASK_STATE_BUSY, /* running on a GCE thread */
+	TASK_STATE_ERROR,
+	TASK_STATE_DONE,
+};
+
+struct cmdq_task_cb {
+	cmdq_async_flush_cb	cb;
+	void			*data;
+};
+
+struct cmdq_thread {
+	void __iomem		*base;
+	struct list_head	task_busy_list;
+	wait_queue_head_t	wait_task_done;
+};
+
+struct cmdq_task {
+	struct cmdq		*cmdq;
+	struct list_head	list_entry;
+	enum cmdq_task_state	task_state;
+	void			*va_base;
+	dma_addr_t		pa_base;
+	u64			engine_flag;
+	size_t			command_size;
+	u32			num_cmd;
+	struct cmdq_thread	*thread;
+	struct cmdq_task_cb	cb;
+	struct work_struct	release_work;
+};
+
+struct cmdq {
+	struct device		*dev;
+	void __iomem		*base;
+	u32			irq;
+	struct workqueue_struct	*task_release_wq;
+	struct cmdq_thread	thread[CMDQ_THR_MAX_COUNT];
+	struct mutex		task_mutex;	/* for task */
+	spinlock_t		exec_lock;	/* for exec */
+	struct clk		*clock;
+	bool			suspended;
+};
+
+struct cmdq_subsys {
+	u32	base;
+	int	id;
+};
+
+static const struct cmdq_subsys gce_subsys[] = {
+	{0x1400, 1},
+	{0x1401, 2},
+	{0x1402, 3},
+};
+
+static int cmdq_subsys_base_to_id(u32 base)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(gce_subsys); i++)
+		if (gce_subsys[i].base == base)
+			return gce_subsys[i].id;
+	return -EFAULT;
+}
+
+static int cmdq_eng_get_thread(u64 flag)
+{
+	if (flag & BIT_ULL(CMDQ_ENG_DISP_DSI0))
+		return CMDQ_THR_DISP_MAIN_IDX;
+	else if (flag & BIT_ULL(CMDQ_ENG_DISP_DPI0))
+		return CMDQ_THR_DISP_SUB_IDX;
+	else
+		return CMDQ_THR_DISP_MISC_IDX;
+}
+
+static void cmdq_task_release(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+
+	dma_free_coherent(cmdq->dev, task->command_size, task->va_base,
+			  task->pa_base);
+	kfree(task);
+}
+
+static struct cmdq_task *cmdq_task_acquire(struct cmdq_rec *rec,
+					   struct cmdq_task_cb cb)
+{
+	struct cmdq *cmdq = rec->cmdq;
+	struct device *dev = cmdq->dev;
+	struct cmdq_task *task;
+
+	task = kzalloc(sizeof(*task), GFP_KERNEL);
+	INIT_LIST_HEAD(&task->list_entry);
+	task->va_base = dma_alloc_coherent(dev, rec->command_size,
+					   &task->pa_base, GFP_KERNEL);
+	if (!task->va_base) {
+		dev_err(dev, "allocate command buffer failed\n");
+		kfree(task);
+		return NULL;
+	}
+
+	task->cmdq = cmdq;
+	task->command_size = rec->command_size;
+	task->engine_flag = rec->engine_flag;
+	task->task_state = TASK_STATE_BUSY;
+	task->cb = cb;
+	memcpy(task->va_base, rec->buf, rec->command_size);
+	task->num_cmd = task->command_size / CMDQ_INST_SIZE;
+	return task;
+}
+
+static void cmdq_thread_writel(struct cmdq_thread *thread, u32 value,
+			       u32 offset)
+{
+	writel(value, thread->base + offset);
+}
+
+static u32 cmdq_thread_readl(struct cmdq_thread *thread, u32 offset)
+{
+	return readl(thread->base + offset);
+}
+
+static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	u32 status;
+
+	cmdq_thread_writel(thread, CMDQ_THR_SUSPEND, CMDQ_THR_SUSPEND_TASK);
+
+	/* If already disabled, treat as suspended successful. */
+	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
+	      CMDQ_THR_ENABLED))
+		return 0;
+
+	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_CURR_STATUS,
+			status, status & CMDQ_THR_STATUS_SUSPENDED, 0, 10)) {
+		dev_err(cmdq->dev, "suspend GCE thread 0x%x failed\n",
+			(u32)(thread->base - cmdq->base));
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static void cmdq_thread_resume(struct cmdq_thread *thread)
+{
+	cmdq_thread_writel(thread, CMDQ_THR_RESUME, CMDQ_THR_SUSPEND_TASK);
+}
+
+static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	u32 warm_reset;
+
+	cmdq_thread_writel(thread, CMDQ_THR_DO_WARM_RESET, CMDQ_THR_WARM_RESET);
+	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET,
+			warm_reset, !(warm_reset & CMDQ_THR_DO_WARM_RESET),
+			0, 10)) {
+		dev_err(cmdq->dev, "reset GCE thread 0x%x failed\n",
+			(u32)(thread->base - cmdq->base));
+		return -EFAULT;
+	}
+	writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES);
+	return 0;
+}
+
+static void cmdq_thread_disable(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	cmdq_thread_reset(cmdq, thread);
+	cmdq_thread_writel(thread, CMDQ_THR_DISABLED, CMDQ_THR_ENABLE_TASK);
+}
+
+/* notify GCE to re-fetch commands by setting GCE thread PC */
+static void cmdq_thread_invalidate_fetched_data(struct cmdq_thread *thread)
+{
+	cmdq_thread_writel(thread,
+			   cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR),
+			   CMDQ_THR_CURR_ADDR);
+}
+
+static void cmdq_task_insert_into_thread(struct cmdq_task *task)
+{
+	struct cmdq_thread *thread = task->thread;
+	struct cmdq_task *prev_task = list_last_entry(
+			&thread->task_busy_list, typeof(*task), list_entry);
+	u64 *prev_task_base = prev_task->va_base;
+
+	/* let previous task jump to this task */
+	prev_task_base[prev_task->num_cmd - 1] = (u64)CMDQ_JUMP_BY_PA << 32 |
+						 task->pa_base;
+
+	cmdq_thread_invalidate_fetched_data(thread);
+}
+
+/* we assume tasks in the same display GCE thread are waiting the same event. */
+static void cmdq_task_remove_wfe(struct cmdq_task *task)
+{
+	u32 wfe_option = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
+	u32 wfe_op = CMDQ_CODE_WFE << CMDQ_OP_CODE_SHIFT;
+	u32 *base = task->va_base;
+	u32 num_cmd = task->num_cmd << 1;
+	int i;
+
+	for (i = 0; i < num_cmd; i += 2)
+		if (base[i] == wfe_option &&
+		    (base[i + 1] & CMDQ_OP_CODE_MASK) == wfe_op) {
+			base[i] = CMDQ_JUMP_PASS;
+			base[i + 1] = CMDQ_JUMP_BY_OFFSET;
+		}
+}
+
+static void cmdq_task_exec(struct cmdq_task *task, struct cmdq_thread *thread)
+{
+	struct cmdq *cmdq = task->cmdq;
+	unsigned long flags;
+	unsigned long curr_pa, end_pa;
+
+	WARN_ON(clk_prepare_enable(cmdq->clock) < 0);
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+	task->thread = thread;
+	task->task_state = TASK_STATE_BUSY;
+	if (list_empty(&thread->task_busy_list)) {
+		WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
+
+		cmdq_thread_writel(thread, task->pa_base, CMDQ_THR_CURR_ADDR);
+		cmdq_thread_writel(thread, task->pa_base + task->command_size,
+				   CMDQ_THR_END_ADDR);
+		cmdq_thread_writel(thread, CMDQ_THR_PRIORITY, CMDQ_THR_CFG);
+		cmdq_thread_writel(thread, CMDQ_THR_IRQ_EN,
+				   CMDQ_THR_IRQ_ENABLE);
+
+		cmdq_thread_writel(thread, CMDQ_THR_ENABLED,
+				   CMDQ_THR_ENABLE_TASK);
+	} else {
+		WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
+
+		/*
+		 * check boundary condition
+		 * PC = END - 8, EOC is executed
+		 * PC = END, all CMDs are executed
+		 */
+		curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
+		end_pa = cmdq_thread_readl(thread, CMDQ_THR_END_ADDR);
+		if (curr_pa == end_pa - 8 || curr_pa == end_pa) {
+			/* set to this task directly */
+			cmdq_thread_writel(thread, task->pa_base,
+					   CMDQ_THR_CURR_ADDR);
+		} else {
+			cmdq_task_insert_into_thread(task);
+
+			if (thread == &cmdq->thread[CMDQ_THR_DISP_MAIN_IDX] ||
+			    thread == &cmdq->thread[CMDQ_THR_DISP_SUB_IDX])
+				cmdq_task_remove_wfe(task);
+
+			smp_mb(); /* modify jump before enable thread */
+		}
+
+		cmdq_thread_writel(thread, task->pa_base + task->command_size,
+				   CMDQ_THR_END_ADDR);
+		cmdq_thread_resume(thread);
+	}
+	list_move_tail(&task->list_entry, &thread->task_busy_list);
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+}
+
+static void cmdq_handle_error_done(struct cmdq *cmdq,
+				   struct cmdq_thread *thread, u32 irq_flag)
+{
+	struct cmdq_task *task, *tmp, *curr_task = NULL;
+	u32 curr_pa;
+	struct cmdq_cb_data cmdq_cb_data;
+	bool err;
+
+	if (irq_flag & CMDQ_THR_IRQ_ERROR)
+		err = true;
+	else if (irq_flag & CMDQ_THR_IRQ_DONE)
+		err = false;
+	else
+		return;
+
+	curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
+
+	list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
+				 list_entry) {
+		if (curr_pa >= task->pa_base &&
+		    curr_pa < (task->pa_base + task->command_size))
+			curr_task = task;
+		if (task->cb.cb) {
+			cmdq_cb_data.err = curr_task ? err : false;
+			cmdq_cb_data.data = task->cb.data;
+			task->cb.cb(cmdq_cb_data);
+		}
+		task->task_state = (curr_task && err) ? TASK_STATE_ERROR :
+				TASK_STATE_DONE;
+		list_del(&task->list_entry);
+		if (curr_task)
+			break;
+	}
+
+	wake_up(&thread->wait_task_done);
+}
+
+static void cmdq_thread_irq_handler(struct cmdq *cmdq, int tid)
+{
+	struct cmdq_thread *thread = &cmdq->thread[tid];
+	unsigned long flags = 0L;
+	u32 irq_flag;
+
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+
+	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
+	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
+
+	/*
+	 * Another CPU core could run "release task" right before we acquire
+	 * the spin lock, and thus reset / disable this GCE thread, so we
+	 * need to check the enable bit of this GCE thread.
+	 */
+	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
+	      CMDQ_THR_ENABLED))
+		irq_flag = 0;
+
+	cmdq_handle_error_done(cmdq, thread, irq_flag);
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+}
+
+static irqreturn_t cmdq_irq_handler(int irq, void *dev)
+{
+	struct cmdq *cmdq = dev;
+	u32 irq_status;
+	int i;
+
+	irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS);
+	irq_status &= CMDQ_IRQ_MASK;
+	irq_status ^= CMDQ_IRQ_MASK;
+
+	if (!irq_status)
+		return IRQ_NONE;
+
+	while (irq_status) {
+		i = ffs(irq_status) - 1;
+		irq_status &= ~BIT(i);
+		cmdq_thread_irq_handler(cmdq, i);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int cmdq_task_handle_error_result(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+	struct device *dev = cmdq->dev;
+	struct cmdq_thread *thread = task->thread;
+	struct cmdq_task *next_task, *prev_task;
+	u32 irq_flag;
+
+	/* suspend GCE thread to ensure consistency */
+	WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
+
+	/* ISR has handled this error task */
+	if (task->task_state == TASK_STATE_ERROR) {
+		next_task = list_first_entry_or_null(&thread->task_busy_list,
+				struct cmdq_task, list_entry);
+		if (next_task) /* move to next task */
+			cmdq_thread_writel(thread, next_task->pa_base,
+					   CMDQ_THR_CURR_ADDR);
+		cmdq_thread_resume(thread);
+		return -ECANCELED;
+	}
+
+	/*
+	 * Save next_task and prev_task in advance
+	 * since cmdq_handle_error_done will remove list_entry.
+	 */
+	next_task = prev_task = NULL;
+	if (task->list_entry.next != &thread->task_busy_list)
+		next_task = list_next_entry(task, list_entry);
+	if (task->list_entry.prev != &thread->task_busy_list)
+		prev_task = list_prev_entry(task, list_entry);
+
+	/*
+	 * Although IRQ is disabled, GCE continues to execute.
+	 * It may have pending IRQ before GCE thread is suspended,
+	 * so check this condition again.
+	 */
+	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
+	cmdq_handle_error_done(cmdq, thread, irq_flag);
+	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
+
+	if (task->task_state == TASK_STATE_DONE) {
+		cmdq_thread_resume(thread);
+		return 0;
+	}
+
+	if (task->task_state == TASK_STATE_ERROR) {
+		dev_err(dev, "task 0x%p error\n", task);
+		if (next_task) /* move to next task */
+			cmdq_thread_writel(thread, next_task->pa_base,
+					   CMDQ_THR_CURR_ADDR);
+		cmdq_thread_resume(thread);
+		return -ECANCELED;
+	}
+
+	/* Task is running, so we force to remove it. */
+	dev_err(dev, "task 0x%p timeout or killed\n", task);
+	task->task_state = TASK_STATE_ERROR;
+
+	if (prev_task) {
+		u64 *prev_va = prev_task->va_base;
+		u64 *curr_va = task->va_base;
+
+		/* copy JUMP instruction */
+		prev_va[prev_task->num_cmd - 1] = curr_va[task->num_cmd - 1];
+
+		cmdq_thread_invalidate_fetched_data(thread);
+	} else if (next_task) { /* move to next task */
+		cmdq_thread_writel(thread, next_task->pa_base,
+				   CMDQ_THR_CURR_ADDR);
+	}
+
+	list_del(&task->list_entry);
+	cmdq_thread_resume(thread);
+
+	/* call cb here to prevent lock */
+	if (task->cb.cb) {
+		struct cmdq_cb_data cmdq_cb_data;
+
+		cmdq_cb_data.err = true;
+		cmdq_cb_data.data = task->cb.data;
+		task->cb.cb(cmdq_cb_data);
+	}
+
+	return -ECANCELED;
+}
+
+static void cmdq_task_wait_release_work(struct work_struct *work_item)
+{
+	struct cmdq_task *task = container_of(work_item, struct cmdq_task,
+					      release_work);
+	struct cmdq *cmdq = task->cmdq;
+	struct cmdq_thread *thread = task->thread;
+	unsigned long flags;
+
+	wait_event_timeout(thread->wait_task_done,
+			   task->task_state != TASK_STATE_BUSY,
+			   msecs_to_jiffies(CMDQ_TIMEOUT_MS));
+
+	spin_lock_irqsave(&cmdq->exec_lock, flags);
+	if (task->task_state != TASK_STATE_DONE)
+		cmdq_task_handle_error_result(task);
+	if (list_empty(&thread->task_busy_list))
+		cmdq_thread_disable(cmdq, thread);
+	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
+
+	/* release regardless of success or not */
+	clk_disable_unprepare(cmdq->clock);
+	cmdq_task_release(task);
+}
+
+static void cmdq_task_wait_release_schedule(struct cmdq_task *task)
+{
+	struct cmdq *cmdq = task->cmdq;
+
+	INIT_WORK(&task->release_work, cmdq_task_wait_release_work);
+	queue_work(cmdq->task_release_wq, &task->release_work);
+}
+
+static int cmdq_rec_realloc_cmd_buffer(struct cmdq_rec *rec, size_t size)
+{
+	void *new_buf;
+
+	new_buf = krealloc(rec->buf, size, GFP_KERNEL | __GFP_ZERO);
+	if (!new_buf)
+		return -ENOMEM;
+	rec->buf = new_buf;
+	rec->buf_size = size;
+	return 0;
+}
+
+struct cmdq_base *cmdq_register_device(struct device *dev)
+{
+	struct cmdq_base *cmdq_base;
+	struct resource res;
+	int subsys;
+	u32 base;
+
+	if (of_address_to_resource(dev->of_node, 0, &res))
+		return NULL;
+	base = (u32)res.start;
+
+	subsys = cmdq_subsys_base_to_id(base >> 16);
+	if (subsys < 0)
+		return NULL;
+
+	cmdq_base = devm_kmalloc(dev, sizeof(*cmdq_base), GFP_KERNEL);
+	if (!cmdq_base)
+		return NULL;
+	cmdq_base->subsys = subsys;
+	cmdq_base->base = base;
+
+	return cmdq_base;
+}
+EXPORT_SYMBOL(cmdq_register_device);
+
+int cmdq_rec_create(struct device *dev, u64 engine_flag,
+		    struct cmdq_rec **rec_ptr)
+{
+	struct cmdq_rec *rec;
+	int err;
+
+	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
+	if (!rec)
+		return -ENOMEM;
+	rec->cmdq = dev_get_drvdata(dev);
+	rec->engine_flag = engine_flag;
+	err = cmdq_rec_realloc_cmd_buffer(rec, CMDQ_INITIAL_CMD_BLOCK_SIZE);
+	if (err < 0) {
+		kfree(rec);
+		return err;
+	}
+	*rec_ptr = rec;
+	return 0;
+}
+EXPORT_SYMBOL(cmdq_rec_create);
+
+static int cmdq_rec_append_command(struct cmdq_rec *rec, enum cmdq_code code,
+				   u32 arg_a, u32 arg_b)
+{
+	u64 *cmd_ptr;
+	int err;
+
+	if (WARN_ON(rec->finalized))
+		return -EBUSY;
+	if (code < CMDQ_CODE_MOVE || code > CMDQ_CODE_EOC)
+		return -EINVAL;
+	if (unlikely(rec->command_size + CMDQ_INST_SIZE > rec->buf_size)) {
+		err = cmdq_rec_realloc_cmd_buffer(rec, rec->buf_size * 2);
+		if (err < 0)
+			return err;
+	}
+	cmd_ptr = rec->buf + rec->command_size;
+	(*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b;
+	rec->command_size += CMDQ_INST_SIZE;
+	return 0;
+}
+
+int cmdq_rec_write(struct cmdq_rec *rec, u32 value, struct cmdq_base *base,
+		   u32 offset)
+{
+	u32 arg_a = ((base->base + offset) & CMDQ_ARG_A_WRITE_MASK) |
+		    ((base->subsys & CMDQ_SUBSYS_MASK) << CMDQ_SUBSYS_SHIFT);
+	return cmdq_rec_append_command(rec, CMDQ_CODE_WRITE, arg_a, value);
+}
+EXPORT_SYMBOL(cmdq_rec_write);
+
+int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
+			struct cmdq_base *base, u32 offset, u32 mask)
+{
+	u32 offset_mask = offset;
+	int err;
+
+	if (mask != 0xffffffff) {
+		err = cmdq_rec_append_command(rec, CMDQ_CODE_MOVE, 0, ~mask);
+		if (err < 0)
+			return err;
+		offset_mask |= CMDQ_WRITE_ENABLE_MASK;
+	}
+	return cmdq_rec_write(rec, value, base, offset_mask);
+}
+EXPORT_SYMBOL(cmdq_rec_write_mask);
+
+int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event)
+{
+	u32 arg_b;
+
+	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
+		return -EINVAL;
+
+	/*
+	 * bit 0-11: wait value
+	 * bit 15: 1 - wait, 0 - no wait
+	 * bit 16-27: update value
+	 * bit 31: 1 - update, 0 - no update
+	 */
+	arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
+	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event, arg_b);
+}
+EXPORT_SYMBOL(cmdq_rec_wfe);
+
+int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event)
+{
+	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
+		return -EINVAL;
+
+	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event,
+				       CMDQ_WFE_UPDATE);
+}
+EXPORT_SYMBOL(cmdq_rec_clear_event);
+
+static int cmdq_rec_finalize(struct cmdq_rec *rec)
+{
+	int err;
+
+	if (rec->finalized)
+		return 0;
+
+	/* insert EOC and generate IRQ for each command iteration */
+	err = cmdq_rec_append_command(rec, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN);
+	if (err < 0)
+		return err;
+
+	/* JUMP to end */
+	err = cmdq_rec_append_command(rec, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS);
+	if (err < 0)
+		return err;
+
+	rec->finalized = true;
+	return 0;
+}
+
+int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
+			 void *data)
+{
+	struct cmdq *cmdq = rec->cmdq;
+	struct cmdq_task *task;
+	struct cmdq_task_cb task_cb;
+	struct cmdq_thread *thread;
+	int err;
+
+	mutex_lock(&cmdq->task_mutex);
+	if (cmdq->suspended) {
+		dev_err(cmdq->dev, "%s is called after suspended\n", __func__);
+		mutex_unlock(&cmdq->task_mutex);
+		return -EPERM;
+	}
+
+	err = cmdq_rec_finalize(rec);
+	if (err < 0) {
+		mutex_unlock(&cmdq->task_mutex);
+		return err;
+	}
+
+	task_cb.cb = cb;
+	task_cb.data = data;
+	task = cmdq_task_acquire(rec, task_cb);
+	if (!task) {
+		mutex_unlock(&cmdq->task_mutex);
+		return -EFAULT;
+	}
+
+	thread = &cmdq->thread[cmdq_eng_get_thread(task->engine_flag)];
+	cmdq_task_exec(task, thread);
+	cmdq_task_wait_release_schedule(task);
+	mutex_unlock(&cmdq->task_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(cmdq_rec_flush_async);
+
+struct cmdq_flush_completion {
+	struct completion cmplt;
+	bool err;
+};
+
+static int cmdq_rec_flush_cb(struct cmdq_cb_data data)
+{
+	struct cmdq_flush_completion *cmplt = data.data;
+
+	cmplt->err = data.err;
+	complete(&cmplt->cmplt);
+	return 0;
+}
+
+int cmdq_rec_flush(struct cmdq_rec *rec)
+{
+	struct cmdq_flush_completion cmplt;
+	int err;
+
+	init_completion(&cmplt.cmplt);
+	err = cmdq_rec_flush_async(rec, cmdq_rec_flush_cb, &cmplt);
+	if (err < 0)
+		return err;
+	wait_for_completion(&cmplt.cmplt);
+	return cmplt.err ? -EFAULT : 0;
+}
+EXPORT_SYMBOL(cmdq_rec_flush);
+
+void cmdq_rec_destroy(struct cmdq_rec *rec)
+{
+	kfree(rec->buf);
+	kfree(rec);
+}
+EXPORT_SYMBOL(cmdq_rec_destroy);
+
+static bool cmdq_task_is_empty(struct cmdq *cmdq)
+{
+	struct cmdq_thread *thread;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
+		thread = &cmdq->thread[i];
+		if (!list_empty(&thread->task_busy_list))
+			return false;
+	}
+	return true;
+}
+
+static int cmdq_suspend(struct device *dev)
+{
+	struct cmdq *cmdq = dev_get_drvdata(dev);
+	u32 exec_threads;
+
+	mutex_lock(&cmdq->task_mutex);
+	cmdq->suspended = true;
+	mutex_unlock(&cmdq->task_mutex);
+
+	exec_threads = readl(cmdq->base + CMDQ_CURR_LOADED_THR);
+	if ((exec_threads & CMDQ_THR_EXECUTING) && !cmdq_task_is_empty(cmdq)) {
+		dev_err(dev, "wait active tasks timeout.\n");
+		flush_workqueue(cmdq->task_release_wq);
+	}
+	return 0;
+}
+
+static int cmdq_resume(struct device *dev)
+{
+	struct cmdq *cmdq = dev_get_drvdata(dev);
+
+	cmdq->suspended = false;
+	return 0;
+}
+
+static int cmdq_remove(struct platform_device *pdev)
+{
+	struct cmdq *cmdq = platform_get_drvdata(pdev);
+
+	destroy_workqueue(cmdq->task_release_wq);
+	cmdq->task_release_wq = NULL;
+	return 0;
+}
+
+static int cmdq_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct resource *res;
+	struct cmdq *cmdq;
+	int err, i;
+
+	cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
+	if (!cmdq)
+		return -ENOMEM;
+	cmdq->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	cmdq->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(cmdq->base)) {
+		dev_err(dev, "failed to ioremap gce\n");
+		return PTR_ERR(cmdq->base);
+	}
+
+	cmdq->irq = irq_of_parse_and_map(node, 0);
+	if (!cmdq->irq) {
+		dev_err(dev, "failed to get irq\n");
+		return -EINVAL;
+	}
+
+	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
+		dev, cmdq->base, cmdq->irq);
+
+	mutex_init(&cmdq->task_mutex);
+	spin_lock_init(&cmdq->exec_lock);
+	cmdq->task_release_wq = alloc_ordered_workqueue(
+			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI,
+			"cmdq_task_wait_release");
+
+	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
+		cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
+				CMDQ_THR_SHIFT * i;
+		init_waitqueue_head(&cmdq->thread[i].wait_task_done);
+		INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list);
+	}
+
+	platform_set_drvdata(pdev, cmdq);
+
+	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
+			       CMDQ_DRIVER_DEVICE_NAME, cmdq);
+	if (err < 0) {
+		dev_err(dev, "failed to register ISR (%d)\n", err);
+		goto fail;
+	}
+
+	cmdq->clock = devm_clk_get(dev, CMDQ_CLK_NAME);
+	if (IS_ERR(cmdq->clock)) {
+		dev_err(dev, "failed to get clk:%s\n", CMDQ_CLK_NAME);
+		err = PTR_ERR(cmdq->clock);
+		goto fail;
+	}
+	return 0;
+
+fail:
+	cmdq_remove(pdev);
+	return err;
+}
+
+static const struct dev_pm_ops cmdq_pm_ops = {
+	.suspend = cmdq_suspend,
+	.resume = cmdq_resume,
+};
+
+static const struct of_device_id cmdq_of_ids[] = {
+	{.compatible = "mediatek,mt8173-gce",},
+	{}
+};
+
+static struct platform_driver cmdq_drv = {
+	.probe = cmdq_probe,
+	.remove = cmdq_remove,
+	.driver = {
+		.name = CMDQ_DRIVER_DEVICE_NAME,
+		.owner = THIS_MODULE,
+		.pm = &cmdq_pm_ops,
+		.of_match_table = cmdq_of_ids,
+	}
+};
+
+builtin_platform_driver(cmdq_drv);
diff --git a/include/soc/mediatek/cmdq.h b/include/soc/mediatek/cmdq.h
new file mode 100644
index 0000000..60eef3d
--- /dev/null
+++ b/include/soc/mediatek/cmdq.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_CMDQ_H__
+#define __MTK_CMDQ_H__
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+enum cmdq_eng {
+	CMDQ_ENG_DISP_AAL,
+	CMDQ_ENG_DISP_COLOR0,
+	CMDQ_ENG_DISP_COLOR1,
+	CMDQ_ENG_DISP_DPI0,
+	CMDQ_ENG_DISP_DSI0,
+	CMDQ_ENG_DISP_DSI1,
+	CMDQ_ENG_DISP_GAMMA,
+	CMDQ_ENG_DISP_OD,
+	CMDQ_ENG_DISP_OVL0,
+	CMDQ_ENG_DISP_OVL1,
+	CMDQ_ENG_DISP_PWM0,
+	CMDQ_ENG_DISP_PWM1,
+	CMDQ_ENG_DISP_RDMA0,
+	CMDQ_ENG_DISP_RDMA1,
+	CMDQ_ENG_DISP_RDMA2,
+	CMDQ_ENG_DISP_UFOE,
+	CMDQ_ENG_DISP_WDMA0,
+	CMDQ_ENG_DISP_WDMA1,
+	CMDQ_ENG_MAX,
+};
+
+/* events for CMDQ and display */
+enum cmdq_event {
+	/* Display start of frame(SOF) events */
+	CMDQ_EVENT_DISP_OVL0_SOF = 11,
+	CMDQ_EVENT_DISP_OVL1_SOF = 12,
+	CMDQ_EVENT_DISP_RDMA0_SOF = 13,
+	CMDQ_EVENT_DISP_RDMA1_SOF = 14,
+	CMDQ_EVENT_DISP_RDMA2_SOF = 15,
+	CMDQ_EVENT_DISP_WDMA0_SOF = 16,
+	CMDQ_EVENT_DISP_WDMA1_SOF = 17,
+	/* Display end of frame(EOF) events */
+	CMDQ_EVENT_DISP_OVL0_EOF = 39,
+	CMDQ_EVENT_DISP_OVL1_EOF = 40,
+	CMDQ_EVENT_DISP_RDMA0_EOF = 41,
+	CMDQ_EVENT_DISP_RDMA1_EOF = 42,
+	CMDQ_EVENT_DISP_RDMA2_EOF = 43,
+	CMDQ_EVENT_DISP_WDMA0_EOF = 44,
+	CMDQ_EVENT_DISP_WDMA1_EOF = 45,
+	/* Mutex end of frame(EOF) events */
+	CMDQ_EVENT_MUTEX0_STREAM_EOF = 53,
+	CMDQ_EVENT_MUTEX1_STREAM_EOF = 54,
+	CMDQ_EVENT_MUTEX2_STREAM_EOF = 55,
+	CMDQ_EVENT_MUTEX3_STREAM_EOF = 56,
+	CMDQ_EVENT_MUTEX4_STREAM_EOF = 57,
+	/* Display underrun events */
+	CMDQ_EVENT_DISP_RDMA0_UNDERRUN = 63,
+	CMDQ_EVENT_DISP_RDMA1_UNDERRUN = 64,
+	CMDQ_EVENT_DISP_RDMA2_UNDERRUN = 65,
+	/* Keep this at the end of HW events */
+	CMDQ_MAX_HW_EVENT_COUNT = 260,
+};
+
+struct cmdq_cb_data {
+	bool	err;
+	void	*data;
+};
+
+typedef int (*cmdq_async_flush_cb)(struct cmdq_cb_data data);
+
+struct cmdq_task;
+struct cmdq;
+
+struct cmdq_rec {
+	struct cmdq		*cmdq;
+	u64			engine_flag;
+	size_t			command_size;
+	void			*buf;
+	size_t			buf_size;
+	bool			finalized;
+};
+
+struct cmdq_base {
+	int	subsys;
+	u32	base;
+};
+
+/**
+ * cmdq_register_device() - register device which needs CMDQ
+ * @dev:		device
+ *
+ * Return: cmdq_base pointer or NULL for failed
+ */
+struct cmdq_base *cmdq_register_device(struct device *dev);
+
+/**
+ * cmdq_rec_create() - create command queue record
+ * @dev:		device
+ * @engine_flag:	command queue engine flag
+ * @rec_ptr:		command queue record pointer to retrieve cmdq_rec
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_create(struct device *dev, u64 engine_flag,
+		    struct cmdq_rec **rec_ptr);
+
+/**
+ * cmdq_rec_write() - append write command to the command queue record
+ * @rec:	the command queue record
+ * @value:	the specified target register value
+ * @base:	the command queue base
+ * @offset:	register offset from module base
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_write(struct cmdq_rec *rec, u32 value,
+		   struct cmdq_base *base, u32 offset);
+
+/**
+ * cmdq_rec_write_mask() - append write command with mask to the command
+ *			   queue record
+ * @rec:	the command queue record
+ * @value:	the specified target register value
+ * @base:	the command queue base
+ * @offset:	register offset from module base
+ * @mask:	the specified target register mask
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
+			struct cmdq_base *base, u32 offset, u32 mask);
+
+/**
+ * cmdq_rec_wfe() - append wait for event command to the command queue record
+ * @rec:	the command queue record
+ * @event:	the desired event type to "wait and CLEAR"
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event);
+
+/**
+ * cmdq_rec_clear_event() - append clear event command to the command queue
+ *			    record
+ * @rec:	the command queue record
+ * @event:	the desired event to be cleared
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event);
+
+/**
+ * cmdq_rec_flush() - trigger CMDQ to execute the recorded commands
+ * @rec:	the command queue record
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ * Trigger CMDQ to execute the recorded commands. Note that this is a
+ * synchronous flush function. When the function returned, the recorded
+ * commands have been done.
+ */
+int cmdq_rec_flush(struct cmdq_rec *rec);
+
+/**
+ * cmdq_rec_flush_async() - trigger CMDQ to asynchronously execute the recorded
+ *			    commands and call back after ISR is finished
+ * @rec:	the command queue record
+ * @cb:		called in the end of CMDQ ISR
+ * @data:	this data will pass back to cb
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ * Trigger CMDQ to asynchronously execute the recorded commands and call back
+ * after ISR is finished. Note that this is an ASYNC function. When the function
+ * returned, it may or may not be finished. The ISR callback function is called
+ * in the end of ISR.
+ */
+int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
+			 void *data);
+
+/**
+ * cmdq_rec_destroy() - destroy command queue record
+ * @rec:	the command queue record
+ */
+void cmdq_rec_destroy(struct cmdq_rec *rec);
+
+#endif	/* __MTK_CMDQ_H__ */
-- 
1.9.1



From hs.liao at mediatek.com  Sun May 29 20:19:57 2016
From: hs.liao at mediatek.com (HS Liao)
Date: Mon, 30 May 2016 11:19:57 +0800
Subject: [PATCH v8 3/3] arm64: dts: mt8173: Add GCE node
In-Reply-To: <1464578397-29743-1-git-send-email-hs.liao@mediatek.com>
References: <1464578397-29743-1-git-send-email-hs.liao@mediatek.com>
Message-ID: <1464578397-29743-4-git-send-email-hs.liao@mediatek.com>

This patch adds the device node of the GCE hardware for CMDQ module.

Signed-off-by: HS Liao <hs.liao at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index eab7efc..63d1718 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -300,6 +300,14 @@
 			#clock-cells = <1>;
 		};
 
+		gce: gce at 10212000 {
+			compatible = "mediatek,mt8173-gce";
+			reg = <0 0x10212000 0 0x1000>;
+			interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>;
+			clocks = <&infracfg CLK_INFRA_GCE>;
+			clock-names = "gce";
+		};
+
 		gic: interrupt-controller at 10220000 {
 			compatible = "arm,gic-400";
 			#interrupt-cells = <3>;
-- 
1.9.1



From zourongrong at huawei.com  Sun May 29 20:21:54 2016
From: zourongrong at huawei.com (Rongrong Zou)
Date: Mon, 30 May 2016 11:21:54 +0800
Subject: [path v2 7/7] drm/hisilicon/hibmc: Add maintainer for Hibmc DRM
In-Reply-To: <CAGd==07sV0qaDES5D5ozvkC1FDQXZ-Z9_UCNX8vO09HKBktq3w@mail.gmail.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
 <1464514855-108050-8-git-send-email-zourongrong@gmail.com>
 <CAGd==07sV0qaDES5D5ozvkC1FDQXZ-Z9_UCNX8vO09HKBktq3w@mail.gmail.com>
Message-ID: <574BB1D2.9030409@huawei.com>

Hi Xinliang,

? 2016/5/30 10:31, Xinliang Liu ??:
> On 29 May 2016 at 17:40, Rongrong Zou <zourongrong at gmail.com> wrote:
>> Signed-off-by: Rongrong Zou <zourongrong at gmail.com>
>> Signed-off-by: Jianhua Li <lijianhua at huawei.com>
>> ---
>>   MAINTAINERS | 7 +++++++
>>   1 file changed, 7 insertions(+)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index f466673..a8a62e0 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -3957,6 +3957,13 @@ T:       git git://github.com/patjak/drm-gma500
>>   S:     Maintained
>>   F:     drivers/gpu/drm/gma500/
>>
>> +DRM DRIVERS FOR HIBMC
>> +M:     lijianhua <lijianhua at huawei.com>
>> +M:     Rongrong Zou <zourongrong at gmail.com>
>> +L:     dri-devel at lists.freedesktop.org
>> +S:     Maintained
>> +F:     drivers/gpu/drm/hisilicon/hibmc
>
> Please add a "/" ad the end of this line.

OK, thanks!

> And move this part into DRM DRIVERS FOR HISILICON

Can it be placed as below:

DRM DRIVERS FOR HISILICON HIBMC
M:     lijianhua <lijianhua at huawei.com>
M:     Rongrong Zou <zourongrong at gmail.com>
...

DRM DRIVERS FOR HISILICON KIRIN
M:     Xinliang Liu <z.liuxinliang at hisilicon.com>
R:     Xinwei Kong <kong.kongxinwei at hisilicon.com>
...
>
> Thanks,
> -xinliang
>
>> +
>>   DRM DRIVERS FOR HISILICON
>>   M:     Xinliang Liu <z.liuxinliang at hisilicon.com>
>>   R:     Xinwei Kong <kong.kongxinwei at hisilicon.com>
>> --
>> 1.9.1
>>
>
> .
>


-- 
Regards,
Rongrong


From appana.durga.rao at xilinx.com  Sun May 29 21:17:16 2016
From: appana.durga.rao at xilinx.com (Appana Durga Kedareswara Rao)
Date: Mon, 30 May 2016 04:17:16 +0000
Subject: [PATCH v9 2/2] dmaengine: Add Xilinx zynqmp dma engine driver
 support
In-Reply-To: <1463123033-5443-2-git-send-email-appanad@xilinx.com>
References: <1463123033-5443-1-git-send-email-appanad@xilinx.com>
 <1463123033-5443-2-git-send-email-appanad@xilinx.com>
Message-ID: <C246CAC1457055469EF09E3A7AC4E11A4A5B2533@XAP-PVEXMBX01.xlnx.xilinx.com>

Ping!!

> -----Original Message-----
> From: Kedareswara rao Appana [mailto:appana.durga.rao at xilinx.com]
> Sent: Friday, May 13, 2016 12:34 PM
> To: robh+dt at kernel.org; pawel.moll at arm.com; mark.rutland at arm.com;
> ijc+devicetree at hellion.org.uk; galak at codeaurora.org; Michal Simek
> <michals at xilinx.com>; Soren Brinkmann <sorenb at xilinx.com>;
> vinod.koul at intel.com; dan.j.williams at intel.com; Appana Durga Kedareswara
> Rao <appanad at xilinx.com>; moritz.fischer at ettus.com;
> laurent.pinchart at ideasonboard.com; luis at debethencourt.com
> Cc: devicetree at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-
> kernel at vger.kernel.org; dmaengine at vger.kernel.org; Punnaiah Choudary
> Kalluri <punnaia at xilinx.com>
> Subject: [PATCH v9 2/2] dmaengine: Add Xilinx zynqmp dma engine driver
> support
> 
> Added the driver for zynqmp dma engine used in Zynq
> UltraScale+ MPSoC. This dma controller supports memory to memory
> and memory to I/O buffer transfers.
> 
> Signed-off-by: Punnaiah Choudary Kalluri <punnaia at xilinx.com>
> Signed-off-by: Kedareswara rao Appana <appanad at xilinx.com>
> ---
> Changes for v9:
> - Derive the include sg software runtime configuration parameter
>   through config strucutre as suggested by the Lars.
> Changes for v8:
> - Derive the software runtime configuration parameters
>   through config strucutre and configure them during transfer
>   as suggested by the Lars.
> Changes for v7:
> - Fixed kbuild compilation warnings.
> - Fixed {src,dst}_addr_widths are supposed to be a bitmask of
>   supported slave device widths as suggested by Rob.
> Changes in v6:
> - Removed unnecessary axcache properties from the driver
> - Fixed compilation issues
> Changes in v5:
> - Removed in_interrupt check from the tasklet cleanup as
>   suggested by the vinod/lars.
> Changes in v4:
> - Modified the defines to start with ZYNQMP_DMA perfix
> - Changed the zynqmp_dma_alloc_chan_resources to return number of
>   allocated descriptors
> - Changed the zynqmp_dma_device variable name
> - Released the locks before calling user callback
> - freeup irq in zynqmp_dma_chan_remove function.
> Changes in v3:
> - Modified the zynqmp_dma_chan_is_idle function return type to bool Changes
> in v2:
> - Corrected the function header documentation
> - Framework expects bus-width value in bytes. so, fixed it
> - Removed magic numbers for bus-width
> 
>  drivers/dma/Kconfig             |    6 +
>  drivers/dma/xilinx/Makefile     |    1 +
>  drivers/dma/xilinx/zynqmp_dma.c | 1262
> +++++++++++++++++++++++++++++++++++++++
>  include/linux/dma/xilinx_dma.h  |   21 +-
>  4 files changed, 1289 insertions(+), 1 deletion(-)  create mode 100644
> drivers/dma/xilinx/zynqmp_dma.c
> 
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index f843dd5..6758417
> 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -527,6 +527,12 @@ config ZX_DMA
>  	help
>  	  Support the DMA engine for ZTE ZX296702 platform devices.
> 
> +config XILINX_ZYNQMP_DMA
> +	tristate "Xilinx ZynqMP DMA Engine"
> +	depends on (ARCH_ZYNQ || MICROBLAZE || ARM64)
> +	select DMA_ENGINE
> +	help
> +	  Enable support for Xilinx ZynqMP DMA controller.
> 
>  # driver files
>  source "drivers/dma/bestcomm/Kconfig"
> diff --git a/drivers/dma/xilinx/Makefile b/drivers/dma/xilinx/Makefile index
> 3c4e9f2..95469dc 100644
> --- a/drivers/dma/xilinx/Makefile
> +++ b/drivers/dma/xilinx/Makefile
> @@ -1 +1,2 @@
>  obj-$(CONFIG_XILINX_VDMA) += xilinx_vdma.o
> +obj-$(CONFIG_XILINX_ZYNQMP_DMA) += zynqmp_dma.o
> diff --git a/drivers/dma/xilinx/zynqmp_dma.c
> b/drivers/dma/xilinx/zynqmp_dma.c new file mode 100644 index
> 0000000..9964dcb
> --- /dev/null
> +++ b/drivers/dma/xilinx/zynqmp_dma.c
> @@ -0,0 +1,1262 @@
> +/*
> + * DMA driver for Xilinx ZynqMP DMA Engine
> + *
> + * Copyright (C) 2016 Xilinx, Inc. All rights reserved.
> + *
> + * 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.
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/dma/xilinx_dma.h>
> +#include <linux/dmaengine.h>
> +#include <linux/dmapool.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_dma.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_platform.h>
> +#include <linux/slab.h>
> +#include <linux/clk.h>
> +
> +#include "../dmaengine.h"
> +
> +/* Register Offsets */
> +#define ZYNQMP_DMA_ISR			0x100
> +#define ZYNQMP_DMA_IMR			0x104
> +#define ZYNQMP_DMA_IER			0x108
> +#define ZYNQMP_DMA_IDS			0x10C
> +#define ZYNQMP_DMA_CTRL0		0x110
> +#define ZYNQMP_DMA_CTRL1		0x114
> +#define ZYNQMP_DMA_DATA_ATTR		0x120
> +#define ZYNQMP_DMA_DSCR_ATTR		0x124
> +#define ZYNQMP_DMA_SRC_DSCR_WRD0	0x128
> +#define ZYNQMP_DMA_SRC_DSCR_WRD1	0x12C
> +#define ZYNQMP_DMA_SRC_DSCR_WRD2	0x130
> +#define ZYNQMP_DMA_SRC_DSCR_WRD3	0x134
> +#define ZYNQMP_DMA_DST_DSCR_WRD0	0x138
> +#define ZYNQMP_DMA_DST_DSCR_WRD1	0x13C
> +#define ZYNQMP_DMA_DST_DSCR_WRD2	0x140
> +#define ZYNQMP_DMA_DST_DSCR_WRD3	0x144
> +#define ZYNQMP_DMA_SRC_START_LSB	0x158
> +#define ZYNQMP_DMA_SRC_START_MSB	0x15C
> +#define ZYNQMP_DMA_DST_START_LSB	0x160
> +#define ZYNQMP_DMA_DST_START_MSB	0x164
> +#define ZYNQMP_DMA_RATE_CTRL		0x18C
> +#define ZYNQMP_DMA_IRQ_SRC_ACCT		0x190
> +#define ZYNQMP_DMA_IRQ_DST_ACCT		0x194
> +#define ZYNQMP_DMA_CTRL2		0x200
> +
> +/* Interrupt registers bit field definitions */
> +#define ZYNQMP_DMA_DONE			BIT(10)
> +#define ZYNQMP_DMA_AXI_WR_DATA		BIT(9)
> +#define ZYNQMP_DMA_AXI_RD_DATA		BIT(8)
> +#define ZYNQMP_DMA_AXI_RD_DST_DSCR	BIT(7)
> +#define ZYNQMP_DMA_AXI_RD_SRC_DSCR	BIT(6)
> +#define ZYNQMP_DMA_IRQ_DST_ACCT_ERR	BIT(5)
> +#define ZYNQMP_DMA_IRQ_SRC_ACCT_ERR	BIT(4)
> +#define ZYNQMP_DMA_BYTE_CNT_OVRFL	BIT(3)
> +#define ZYNQMP_DMA_DST_DSCR_DONE	BIT(2)
> +#define ZYNQMP_DMA_INV_APB		BIT(0)
> +
> +/* Control 0 register bit field definitions */
> +#define ZYNQMP_DMA_OVR_FETCH		BIT(7)
> +#define ZYNQMP_DMA_POINT_TYPE_SG	BIT(6)
> +#define ZYNQMP_DMA_RATE_CTRL_EN		BIT(3)
> +
> +/* Control 1 register bit field definitions */
> +#define ZYNQMP_DMA_SRC_ISSUE		GENMASK(4, 0)
> +
> +/* Data Attribute register bit field definitions */
> +#define ZYNQMP_DMA_ARBURST		GENMASK(27, 26)
> +#define ZYNQMP_DMA_ARCACHE		GENMASK(25, 22)
> +#define ZYNQMP_DMA_ARCACHE_OFST		22
> +#define ZYNQMP_DMA_ARQOS		GENMASK(21, 18)
> +#define ZYNQMP_DMA_ARQOS_OFST		18
> +#define ZYNQMP_DMA_ARLEN		GENMASK(17, 14)
> +#define ZYNQMP_DMA_ARLEN_OFST		14
> +#define ZYNQMP_DMA_AWBURST		GENMASK(13, 12)
> +#define ZYNQMP_DMA_AWCACHE		GENMASK(11, 8)
> +#define ZYNQMP_DMA_AWCACHE_OFST		8
> +#define ZYNQMP_DMA_AWQOS		GENMASK(7, 4)
> +#define ZYNQMP_DMA_AWQOS_OFST		4
> +#define ZYNQMP_DMA_AWLEN		GENMASK(3, 0)
> +#define ZYNQMP_DMA_AWLEN_OFST		0
> +
> +/* Descriptor Attribute register bit field definitions */
> +#define ZYNQMP_DMA_AXCOHRNT		BIT(8)
> +#define ZYNQMP_DMA_AXCACHE		GENMASK(7, 4)
> +#define ZYNQMP_DMA_AXCACHE_OFST		4
> +#define ZYNQMP_DMA_AXQOS		GENMASK(3, 0)
> +#define ZYNQMP_DMA_AXQOS_OFST		0
> +
> +/* Control register 2 bit field definitions */
> +#define ZYNQMP_DMA_ENABLE		BIT(0)
> +
> +/* Buffer Descriptor definitions */
> +#define ZYNQMP_DMA_DESC_CTRL_STOP	0x10
> +#define ZYNQMP_DMA_DESC_CTRL_COMP_INT	0x4
> +#define ZYNQMP_DMA_DESC_CTRL_SIZE_256	0x2
> +#define ZYNQMP_DMA_DESC_CTRL_COHRNT	0x1
> +
> +/* Interrupt Mask specific definitions */
> +#define ZYNQMP_DMA_INT_ERR	(ZYNQMP_DMA_AXI_RD_DATA | \
> +				ZYNQMP_DMA_AXI_WR_DATA | \
> +				ZYNQMP_DMA_AXI_RD_DST_DSCR | \
> +				ZYNQMP_DMA_AXI_RD_SRC_DSCR | \
> +				ZYNQMP_DMA_INV_APB)
> +#define ZYNQMP_DMA_INT_OVRFL	(ZYNQMP_DMA_BYTE_CNT_OVRFL | \
> +				ZYNQMP_DMA_IRQ_SRC_ACCT_ERR | \
> +				ZYNQMP_DMA_IRQ_DST_ACCT_ERR)
> +#define ZYNQMP_DMA_INT_DONE	(ZYNQMP_DMA_DONE |
> ZYNQMP_DMA_DST_DSCR_DONE)
> +#define ZYNQMP_DMA_INT_EN_DEFAULT_MASK
> 	(ZYNQMP_DMA_INT_DONE | \
> +					ZYNQMP_DMA_INT_ERR | \
> +					ZYNQMP_DMA_INT_OVRFL | \
> +					ZYNQMP_DMA_DST_DSCR_DONE)
> +
> +/* Max number of descriptors per channel */
> +#define ZYNQMP_DMA_NUM_DESCS	32
> +
> +/* Max transfer size per descriptor */
> +#define ZYNQMP_DMA_MAX_TRANS_LEN	0x40000000
> +
> +/* Reset values for data attributes */
> +#define ZYNQMP_DMA_AXCACHE_VAL		0xF
> +#define ZYNQMP_DMA_ARLEN_RST_VAL	0xF
> +#define ZYNQMP_DMA_AWLEN_RST_VAL	0xF
> +
> +#define ZYNQMP_DMA_SRC_ISSUE_RST_VAL	0x1F
> +
> +#define ZYNQMP_DMA_IDS_DEFAULT_MASK	0xFFF
> +
> +/* Bus width in bits */
> +#define ZYNQMP_DMA_BUS_WIDTH_64		64
> +#define ZYNQMP_DMA_BUS_WIDTH_128	128
> +
> +#define ZYNQMP_DMA_DESC_SIZE(chan)	(chan->desc_size)
> +
> +#define to_chan(chan)		container_of(chan, struct zynqmp_dma_chan, \
> +					     common)
> +#define tx_to_desc(tx)		container_of(tx, struct zynqmp_dma_desc_sw,
> \
> +					     async_tx)
> +
> +/**
> + * struct zynqmp_dma_desc_ll - Hw linked list descriptor
> + * @addr: Buffer address
> + * @size: Size of the buffer
> + * @ctrl: Control word
> + * @nxtdscraddr: Next descriptor base address
> + * @rsvd: Reserved field and for Hw internal use.
> + */
> +struct zynqmp_dma_desc_ll {
> +	u64 addr;
> +	u32 size;
> +	u32 ctrl;
> +	u64 nxtdscraddr;
> +	u64 rsvd;
> +}; __aligned(64)
> +
> +/**
> + * struct zynqmp_dma_desc_sw - Per Transaction structure
> + * @src: Source address for simple mode dma
> + * @dst: Destination address for simple mode dma
> + * @len: Transfer length for simple mode dma
> + * @node: Node in the channel descriptor list
> + * @tx_list: List head for the current transfer
> + * @async_tx: Async transaction descriptor
> + * @src_v: Virtual address of the src descriptor
> + * @src_p: Physical address of the src descriptor
> + * @dst_v: Virtual address of the dst descriptor
> + * @dst_p: Physical address of the dst descriptor  */ struct
> +zynqmp_dma_desc_sw {
> +	u64 src;
> +	u64 dst;
> +	u32 len;
> +	struct list_head node;
> +	struct list_head tx_list;
> +	struct dma_async_tx_descriptor async_tx;
> +	struct zynqmp_dma_desc_ll *src_v;
> +	dma_addr_t src_p;
> +	struct zynqmp_dma_desc_ll *dst_v;
> +	dma_addr_t dst_p;
> +};
> +
> +/**
> + * struct zynqmp_dma_chan - Driver specific DMA channel structure
> + * @zdev: Driver specific device structure
> + * @regs: Control registers offset
> + * @lock: Descriptor operation lock
> + * @pending_list: Descriptors waiting
> + * @free_list: Descriptors free
> + * @active_list: Descriptors active
> + * @sw_desc_pool: SW descriptor pool
> + * @done_list: Complete descriptors
> + * @common: DMA common channel
> + * @desc_pool_v: Statically allocated descriptor base
> + * @desc_pool_p: Physical allocated descriptor base
> + * @desc_free_cnt: Descriptor available count
> + * @dev: The dma device
> + * @irq: Channel IRQ
> + * @is_dmacoherent: Tells whether dma operations are coherent or not
> + * @tasklet: Cleanup work after irq
> + * @idle : Channel status;
> + * @desc_size: Size of the low level descriptor
> + * @err: Channel has errors
> + * @bus_width: Bus width
> + * @clk_main: Pointer to main clock
> + * @clk_apb: Pointer to apb clock
> + * @config: Device configuration info
> + */
> +struct zynqmp_dma_chan {
> +	struct zynqmp_dma_device *zdev;
> +	void __iomem *regs;
> +	spinlock_t lock;
> +	struct list_head pending_list;
> +	struct list_head free_list;
> +	struct list_head active_list;
> +	struct zynqmp_dma_desc_sw *sw_desc_pool;
> +	struct list_head done_list;
> +	struct dma_chan common;
> +	void *desc_pool_v;
> +	dma_addr_t desc_pool_p;
> +	u32 desc_free_cnt;
> +	struct device *dev;
> +	int irq;
> +	bool is_dmacoherent;
> +	struct tasklet_struct tasklet;
> +	bool idle;
> +	u32 desc_size;
> +	bool err;
> +	u32 bus_width;
> +	struct clk *clk_main;
> +	struct clk *clk_apb;
> +	struct zynqmp_dma_config config;
> +};
> +
> +/**
> + * struct zynqmp_dma_device - DMA device structure
> + * @dev: Device Structure
> + * @common: DMA device structure
> + * @chan: Driver specific DMA channel
> + */
> +struct zynqmp_dma_device {
> +	struct device *dev;
> +	struct dma_device common;
> +	struct zynqmp_dma_chan *chan;
> +};
> +
> +/**
> + * zynqmp_dma_chan_is_idle - Provides the channel idle status
> + * @chan: ZynqMP DMA DMA channel pointer
> + *
> + * Return: 'true' if the channel is idle otherwise 'false'
> + */
> +static inline bool zynqmp_dma_chan_is_idle(struct zynqmp_dma_chan
> +*chan) {
> +	return chan->idle;
> +
> +}
> +
> +/**
> + * zynqmp_dma_update_desc_to_ctrlr - Updates descriptor to the
> +controller
> + * @chan: ZynqMP DMA DMA channel pointer
> + * @desc: Transaction descriptor pointer  */ static void
> +zynqmp_dma_update_desc_to_ctrlr(struct zynqmp_dma_chan *chan,
> +				      struct zynqmp_dma_desc_sw *desc) {
> +	dma_addr_t addr;
> +
> +	addr = desc->src_p;
> +	writel(addr, chan->regs + ZYNQMP_DMA_SRC_START_LSB);
> +	writel(upper_32_bits(addr), chan->regs +
> ZYNQMP_DMA_SRC_START_MSB);
> +	addr = desc->dst_p;
> +	writel(addr, chan->regs + ZYNQMP_DMA_DST_START_LSB);
> +	writel(upper_32_bits(addr), chan->regs +
> ZYNQMP_DMA_DST_START_MSB); }
> +
> +/**
> + * zynqmp_dma_desc_config_eod - Mark the descriptor as end descriptor
> + * @chan: ZynqMP DMA channel pointer
> + * @desc: Hw descriptor pointer
> + */
> +static void zynqmp_dma_desc_config_eod(struct zynqmp_dma_chan *chan,
> +void *desc) {
> +	struct zynqmp_dma_desc_ll *hw = (struct zynqmp_dma_desc_ll *)desc;
> +
> +	hw->ctrl |= ZYNQMP_DMA_DESC_CTRL_STOP;
> +	hw++;
> +	hw->ctrl |= ZYNQMP_DMA_DESC_CTRL_COMP_INT |
> ZYNQMP_DMA_DESC_CTRL_STOP;
> +}
> +
> +/**
> + * zynqmp_dma_config_simple_desc - Configure the transfer parameters
> + * @chan: ZynqMP DMA channel pointer
> + * @src: Source buffer address
> + * @dst: Destination buffer address
> + * @len: Transfer length
> + */
> +static void zynqmp_dma_config_simple_desc(struct zynqmp_dma_chan *chan,
> +					  dma_addr_t src, dma_addr_t dst,
> +					  size_t len)
> +{
> +	u32 val;
> +
> +	writel(src, chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD0);
> +	writel(upper_32_bits(src), chan->regs +
> ZYNQMP_DMA_SRC_DSCR_WRD1);
> +	writel(len, chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD2);
> +
> +	if (chan->is_dmacoherent)
> +		writel(ZYNQMP_DMA_DESC_CTRL_COHRNT,
> +			chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD3);
> +	else
> +		writel(0, chan->regs + ZYNQMP_DMA_SRC_DSCR_WRD3);
> +
> +	writel(dst, chan->regs + ZYNQMP_DMA_DST_DSCR_WRD0);
> +	writel(upper_32_bits(dst), chan->regs +
> ZYNQMP_DMA_DST_DSCR_WRD1);
> +	writel(len, chan->regs + ZYNQMP_DMA_DST_DSCR_WRD2);
> +
> +	if (chan->is_dmacoherent)
> +		val = ZYNQMP_DMA_DESC_CTRL_COHRNT |
> +				ZYNQMP_DMA_DESC_CTRL_COMP_INT;
> +	else
> +		val = ZYNQMP_DMA_DESC_CTRL_COMP_INT;
> +	writel(val, chan->regs + ZYNQMP_DMA_DST_DSCR_WRD3); }
> +
> +/**
> + * zynqmp_dma_config_sg_ll_desc - Configure the linked list descriptor
> + * @chan: ZynqMP DMA channel pointer
> + * @sdesc: Hw descriptor pointer
> + * @src: Source buffer address
> + * @dst: Destination buffer address
> + * @len: Transfer length
> + * @prev: Previous hw descriptor pointer  */ static void
> +zynqmp_dma_config_sg_ll_desc(struct zynqmp_dma_chan *chan,
> +				   struct zynqmp_dma_desc_ll *sdesc,
> +				   dma_addr_t src, dma_addr_t dst, size_t len,
> +				   struct zynqmp_dma_desc_ll *prev) {
> +	struct zynqmp_dma_desc_ll *ddesc = sdesc + 1;
> +
> +	sdesc->size = ddesc->size = len;
> +	sdesc->addr = src;
> +	ddesc->addr = dst;
> +
> +	sdesc->ctrl = ddesc->ctrl = ZYNQMP_DMA_DESC_CTRL_SIZE_256;
> +	if (chan->is_dmacoherent) {
> +		sdesc->ctrl |= ZYNQMP_DMA_DESC_CTRL_COHRNT;
> +		ddesc->ctrl |= ZYNQMP_DMA_DESC_CTRL_COHRNT;
> +	}
> +
> +	if (prev) {
> +		dma_addr_t addr = chan->desc_pool_p +
> +			    ((dma_addr_t)sdesc - (dma_addr_t)chan-
> >desc_pool_v);
> +		ddesc = prev + 1;
> +		prev->nxtdscraddr = addr;
> +		ddesc->nxtdscraddr = addr + ZYNQMP_DMA_DESC_SIZE(chan);
> +	}
> +}
> +
> +/**
> + * zynqmp_dma_init - Initialize the channel
> + * @chan: ZynqMP DMA channel pointer
> + */
> +static void zynqmp_dma_init(struct zynqmp_dma_chan *chan) {
> +	u32 val;
> +
> +	writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs +
> ZYNQMP_DMA_IDS);
> +	val = readl(chan->regs + ZYNQMP_DMA_ISR);
> +	writel(val, chan->regs + ZYNQMP_DMA_ISR);
> +
> +	val = 0;
> +	if (chan->config.has_sg)
> +		val |= ZYNQMP_DMA_POINT_TYPE_SG;
> +	writel(val, chan->regs + ZYNQMP_DMA_CTRL0);
> +
> +	val = 0;
> +	if (chan->is_dmacoherent) {
> +		val |= ZYNQMP_DMA_AXCOHRNT;
> +		val = (val & ~ZYNQMP_DMA_AXCACHE) |
> +			(ZYNQMP_DMA_AXCACHE_VAL <<
> ZYNQMP_DMA_AXCACHE_OFST);
> +	}
> +	writel(val, chan->regs + ZYNQMP_DMA_DSCR_ATTR);
> +
> +	val = readl(chan->regs + ZYNQMP_DMA_DATA_ATTR);
> +	if (chan->is_dmacoherent) {
> +		val = (val & ~ZYNQMP_DMA_ARCACHE) |
> +			(ZYNQMP_DMA_AXCACHE_VAL <<
> ZYNQMP_DMA_ARCACHE_OFST);
> +		val = (val & ~ZYNQMP_DMA_AWCACHE) |
> +			(ZYNQMP_DMA_AXCACHE_VAL <<
> ZYNQMP_DMA_AWCACHE_OFST);
> +	}
> +	writel(val, chan->regs + ZYNQMP_DMA_DATA_ATTR);
> +
> +	/* Clearing the interrupt account rgisters */
> +	val = readl(chan->regs + ZYNQMP_DMA_IRQ_SRC_ACCT);
> +	val = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
> +
> +	chan->idle = true;
> +}
> +
> +/**
> + * zynqmp_dma_tx_submit - Submit DMA transaction
> + * @tx: Async transaction descriptor pointer
> + *
> + * Return: cookie value
> + */
> +static dma_cookie_t zynqmp_dma_tx_submit(struct dma_async_tx_descriptor
> +*tx) {
> +	struct zynqmp_dma_chan *chan = to_chan(tx->chan);
> +	struct zynqmp_dma_desc_sw *desc, *new;
> +	dma_cookie_t cookie;
> +
> +	new = tx_to_desc(tx);
> +	spin_lock_bh(&chan->lock);
> +	cookie = dma_cookie_assign(tx);
> +
> +	if (!list_empty(&chan->pending_list) && chan->config.has_sg) {
> +		desc = list_last_entry(&chan->pending_list,
> +				     struct zynqmp_dma_desc_sw, node);
> +		if (!list_empty(&desc->tx_list))
> +			desc = list_last_entry(&desc->tx_list,
> +					       struct zynqmp_dma_desc_sw,
> node);
> +		desc->src_v->nxtdscraddr = new->src_p;
> +		desc->src_v->ctrl &= ~ZYNQMP_DMA_DESC_CTRL_STOP;
> +		desc->dst_v->nxtdscraddr = new->dst_p;
> +		desc->dst_v->ctrl &= ~ZYNQMP_DMA_DESC_CTRL_STOP;
> +	}
> +
> +	list_add_tail(&new->node, &chan->pending_list);
> +	spin_unlock_bh(&chan->lock);
> +
> +	return cookie;
> +}
> +
> +/**
> + * zynqmp_dma_get_descriptor - Get the sw descriptor from the pool
> + * @chan: ZynqMP DMA channel pointer
> + *
> + * Return: The sw descriptor
> + */
> +static struct zynqmp_dma_desc_sw *
> +zynqmp_dma_get_descriptor(struct zynqmp_dma_chan *chan) {
> +	struct zynqmp_dma_desc_sw *desc;
> +
> +	spin_lock_bh(&chan->lock);
> +	desc = list_first_entry(&chan->free_list, struct zynqmp_dma_desc_sw,
> +				 node);
> +	list_del(&desc->node);
> +	spin_unlock_bh(&chan->lock);
> +
> +	INIT_LIST_HEAD(&desc->tx_list);
> +	/* Clear the src and dst descriptor memory */
> +	if (chan->config.has_sg) {
> +		memset((void *)desc->src_v, 0,
> ZYNQMP_DMA_DESC_SIZE(chan));
> +		memset((void *)desc->dst_v, 0,
> ZYNQMP_DMA_DESC_SIZE(chan));
> +	}
> +
> +	return desc;
> +}
> +
> +/**
> + * zynqmp_dma_free_descriptor - Issue pending transactions
> + * @chan: ZynqMP DMA channel pointer
> + * @sdesc: Transaction descriptor pointer  */ static void
> +zynqmp_dma_free_descriptor(struct zynqmp_dma_chan *chan,
> +				 struct zynqmp_dma_desc_sw *sdesc)
> +{
> +	struct zynqmp_dma_desc_sw *child, *next;
> +
> +	chan->desc_free_cnt++;
> +	list_add_tail(&sdesc->node, &chan->free_list);
> +	list_for_each_entry_safe(child, next, &sdesc->tx_list, node) {
> +		chan->desc_free_cnt++;
> +		INIT_LIST_HEAD(&child->tx_list);
> +		list_move_tail(&child->node, &chan->free_list);
> +	}
> +	INIT_LIST_HEAD(&sdesc->tx_list);
> +}
> +
> +/**
> + * zynqmp_dma_free_desc_list - Free descriptors list
> + * @chan: ZynqMP DMA channel pointer
> + * @list: List to parse and delete the descriptor  */ static void
> +zynqmp_dma_free_desc_list(struct zynqmp_dma_chan *chan,
> +				      struct list_head *list)
> +{
> +	struct zynqmp_dma_desc_sw *desc, *next;
> +
> +	list_for_each_entry_safe(desc, next, list, node)
> +		zynqmp_dma_free_descriptor(chan, desc); }
> +
> +/**
> + * zynqmp_dma_alloc_chan_resources - Allocate channel resources
> + * @dchan: DMA channel
> + *
> + * Return: Number of descriptors on success and failure value on error
> +*/ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan) {
> +	struct zynqmp_dma_chan *chan = to_chan(dchan);
> +	struct zynqmp_dma_desc_sw *desc;
> +	int i;
> +
> +	chan->sw_desc_pool = kzalloc(sizeof(*desc) *
> ZYNQMP_DMA_NUM_DESCS,
> +				     GFP_KERNEL);
> +	if (!chan->sw_desc_pool)
> +		return -ENOMEM;
> +	chan->idle = true;
> +	chan->desc_free_cnt = ZYNQMP_DMA_NUM_DESCS;
> +
> +	INIT_LIST_HEAD(&chan->free_list);
> +
> +	for (i = 0; i < ZYNQMP_DMA_NUM_DESCS; i++) {
> +		desc = chan->sw_desc_pool + i;
> +		dma_async_tx_descriptor_init(&desc->async_tx, &chan-
> >common);
> +		desc->async_tx.tx_submit = zynqmp_dma_tx_submit;
> +		list_add_tail(&desc->node, &chan->free_list);
> +	}
> +
> +	chan->desc_pool_v = dma_zalloc_coherent(chan->dev,
> +				(2 * chan->desc_size *
> ZYNQMP_DMA_NUM_DESCS),
> +				&chan->desc_pool_p, GFP_KERNEL);
> +	if (!chan->desc_pool_v)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < ZYNQMP_DMA_NUM_DESCS; i++) {
> +		desc = chan->sw_desc_pool + i;
> +		desc->src_v = (struct zynqmp_dma_desc_ll *) (chan-
> >desc_pool_v +
> +					(i * ZYNQMP_DMA_DESC_SIZE(chan) *
> 2));
> +		desc->dst_v = (struct zynqmp_dma_desc_ll *) (desc->src_v + 1);
> +		desc->src_p = chan->desc_pool_p +
> +				(i * ZYNQMP_DMA_DESC_SIZE(chan) * 2);
> +		desc->dst_p = desc->src_p + ZYNQMP_DMA_DESC_SIZE(chan);
> +	}
> +
> +	return ZYNQMP_DMA_NUM_DESCS;
> +}
> +
> +/**
> + * zynqmp_dma_start - Start DMA channel
> + * @chan: ZynqMP DMA channel pointer
> + */
> +static void zynqmp_dma_start(struct zynqmp_dma_chan *chan) {
> +	writel(ZYNQMP_DMA_INT_EN_DEFAULT_MASK, chan->regs +
> ZYNQMP_DMA_IER);
> +	chan->idle = false;
> +	writel(ZYNQMP_DMA_ENABLE, chan->regs + ZYNQMP_DMA_CTRL2); }
> +
> +/**
> + * zynqmp_dma_handle_ovfl_int - Process the overflow interrupt
> + * @chan: ZynqMP DMA channel pointer
> + * @status: Interrupt status value
> + */
> +static void zynqmp_dma_handle_ovfl_int(struct zynqmp_dma_chan *chan,
> +u32 status) {
> +	u32 val;
> +
> +	if (status & ZYNQMP_DMA_IRQ_DST_ACCT_ERR)
> +		val = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
> +	if (status & ZYNQMP_DMA_IRQ_SRC_ACCT_ERR)
> +		val = readl(chan->regs + ZYNQMP_DMA_IRQ_SRC_ACCT); }
> +
> +static void zynqmp_dma_config(struct zynqmp_dma_chan *chan) {
> +	u32 val;
> +
> +	val = readl(chan->regs + ZYNQMP_DMA_CTRL0);
> +	if (chan->config.ovrfetch)
> +		val |= ZYNQMP_DMA_OVR_FETCH;
> +	if (chan->config.ratectrl) {
> +		val |= ZYNQMP_DMA_RATE_CTRL_EN;
> +		writel(chan->config.ratectrl, chan->regs +
> +		       ZYNQMP_DMA_RATE_CTRL);
> +	}
> +	writel(val, chan->regs + ZYNQMP_DMA_CTRL0);
> +
> +	val = readl(chan->regs + ZYNQMP_DMA_CTRL1);
> +	if (chan->config.src_issue)
> +		val = (val & ~ZYNQMP_DMA_SRC_ISSUE) | chan-
> >config.src_issue;
> +	else
> +		val |= ZYNQMP_DMA_SRC_ISSUE_RST_VAL;
> +	writel(val, chan->regs + ZYNQMP_DMA_CTRL1);
> +
> +	val = readl(chan->regs + ZYNQMP_DMA_DATA_ATTR);
> +	if (chan->config.src_burst_len)
> +		val = (val & ~ZYNQMP_DMA_ARLEN) |
> +			(chan->config.src_burst_len <<
> ZYNQMP_DMA_ARLEN_OFST);
> +	else
> +		val |= ZYNQMP_DMA_ARLEN_RST_VAL;
> +
> +	if (chan->config.dst_burst_len)
> +		val = (val & ~ZYNQMP_DMA_AWLEN) |
> +			(chan->config.dst_burst_len <<
> ZYNQMP_DMA_AWLEN_OFST);
> +	else
> +		val |= ZYNQMP_DMA_AWLEN_RST_VAL;
> +	writel(val, chan->regs + ZYNQMP_DMA_DATA_ATTR);
> +
> +}
> +
> +/**
> + * zynqmp_dma_start_transfer - Initiate the new transfer
> + * @chan: ZynqMP DMA channel pointer
> + */
> +static void zynqmp_dma_start_transfer(struct zynqmp_dma_chan *chan) {
> +	struct zynqmp_dma_desc_sw *desc;
> +
> +	if (!zynqmp_dma_chan_is_idle(chan))
> +		return;
> +
> +	zynqmp_dma_config(chan);
> +
> +	desc = list_first_entry_or_null(&chan->pending_list,
> +					struct zynqmp_dma_desc_sw, node);
> +	if (!desc)
> +		return;
> +
> +	if (chan->config.has_sg)
> +		list_splice_tail_init(&chan->pending_list, &chan->active_list);
> +	else
> +		list_move_tail(&desc->node, &chan->active_list);
> +
> +	if (chan->config.has_sg)
> +		zynqmp_dma_update_desc_to_ctrlr(chan, desc);
> +	else
> +		zynqmp_dma_config_simple_desc(chan, desc->src, desc->dst,
> +					      desc->len);
> +
> +	zynqmp_dma_start(chan);
> +}
> +
> +
> +/**
> + * zynqmp_dma_chan_desc_cleanup - Cleanup the completed descriptors
> + * @chan: ZynqMP DMA channel
> + */
> +static void zynqmp_dma_chan_desc_cleanup(struct zynqmp_dma_chan *chan)
> +{
> +	struct zynqmp_dma_desc_sw *desc, *next;
> +
> +	list_for_each_entry_safe(desc, next, &chan->done_list, node) {
> +		dma_async_tx_callback callback;
> +		void *callback_param;
> +
> +		list_del(&desc->node);
> +
> +		callback = desc->async_tx.callback;
> +		callback_param = desc->async_tx.callback_param;
> +		if (callback) {
> +			spin_unlock(&chan->lock);
> +			callback(callback_param);
> +			spin_lock(&chan->lock);
> +		}
> +
> +		/* Run any dependencies, then free the descriptor */
> +		zynqmp_dma_free_descriptor(chan, desc);
> +	}
> +}
> +
> +/**
> + * zynqmp_dma_complete_descriptor - Mark the active descriptor as
> +complete
> + * @chan: ZynqMP DMA channel pointer
> + */
> +static void zynqmp_dma_complete_descriptor(struct zynqmp_dma_chan
> +*chan) {
> +	struct zynqmp_dma_desc_sw *desc;
> +
> +	desc = list_first_entry_or_null(&chan->active_list,
> +					struct zynqmp_dma_desc_sw, node);
> +	if (!desc)
> +		return;
> +	list_del(&desc->node);
> +	dma_cookie_complete(&desc->async_tx);
> +	list_add_tail(&desc->node, &chan->done_list); }
> +
> +/**
> + * zynqmp_dma_issue_pending - Issue pending transactions
> + * @dchan: DMA channel pointer
> + */
> +static void zynqmp_dma_issue_pending(struct dma_chan *dchan) {
> +	struct zynqmp_dma_chan *chan = to_chan(dchan);
> +
> +	spin_lock_bh(&chan->lock);
> +	zynqmp_dma_start_transfer(chan);
> +	spin_unlock_bh(&chan->lock);
> +}
> +
> +/**
> + * zynqmp_dma_free_descriptors - Free channel descriptors
> + * @dchan: DMA channel pointer
> + */
> +static void zynqmp_dma_free_descriptors(struct zynqmp_dma_chan *chan) {
> +	zynqmp_dma_free_desc_list(chan, &chan->active_list);
> +	zynqmp_dma_free_desc_list(chan, &chan->pending_list);
> +	zynqmp_dma_free_desc_list(chan, &chan->done_list); }
> +
> +/**
> + * zynqmp_dma_free_chan_resources - Free channel resources
> + * @dchan: DMA channel pointer
> + */
> +static void zynqmp_dma_free_chan_resources(struct dma_chan *dchan) {
> +	struct zynqmp_dma_chan *chan = to_chan(dchan);
> +
> +	spin_lock_bh(&chan->lock);
> +	zynqmp_dma_free_descriptors(chan);
> +	spin_unlock_bh(&chan->lock);
> +	dma_free_coherent(chan->dev,
> +		(2 * ZYNQMP_DMA_DESC_SIZE(chan) *
> ZYNQMP_DMA_NUM_DESCS),
> +		chan->desc_pool_v, chan->desc_pool_p);
> +	kfree(chan->sw_desc_pool);
> +}
> +
> +/**
> + * zynqmp_dma_tx_status - Get dma transaction status
> + * @dchan: DMA channel pointer
> + * @cookie: Transaction identifier
> + * @txstate: Transaction state
> + *
> + * Return: DMA transaction status
> + */
> +static enum dma_status zynqmp_dma_tx_status(struct dma_chan *dchan,
> +				      dma_cookie_t cookie,
> +				      struct dma_tx_state *txstate) {
> +	return dma_cookie_status(dchan, cookie, txstate); }
> +
> +/**
> + * zynqmp_dma_reset - Reset the channel
> + * @chan: ZynqMP DMA channel pointer
> + */
> +static void zynqmp_dma_reset(struct zynqmp_dma_chan *chan) {
> +	writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs +
> ZYNQMP_DMA_IDS);
> +
> +	zynqmp_dma_complete_descriptor(chan);
> +	zynqmp_dma_chan_desc_cleanup(chan);
> +	zynqmp_dma_free_descriptors(chan);
> +	zynqmp_dma_init(chan);
> +}
> +
> +/**
> + * zynqmp_dma_irq_handler - ZynqMP DMA Interrupt handler
> + * @irq: IRQ number
> + * @data: Pointer to the ZynqMP DMA channel structure
> + *
> + * Return: IRQ_HANDLED/IRQ_NONE
> + */
> +static irqreturn_t zynqmp_dma_irq_handler(int irq, void *data) {
> +	struct zynqmp_dma_chan *chan = (struct zynqmp_dma_chan *)data;
> +	u32 isr, imr, status;
> +	irqreturn_t ret = IRQ_NONE;
> +
> +	isr = readl(chan->regs + ZYNQMP_DMA_ISR);
> +	imr = readl(chan->regs + ZYNQMP_DMA_IMR);
> +	status = isr & ~imr;
> +
> +	writel(isr, chan->regs + ZYNQMP_DMA_ISR);
> +	if (status & ZYNQMP_DMA_INT_DONE) {
> +		tasklet_schedule(&chan->tasklet);
> +		ret = IRQ_HANDLED;
> +	}
> +
> +	if (status & ZYNQMP_DMA_DONE)
> +		chan->idle = true;
> +
> +	if (status & ZYNQMP_DMA_INT_ERR) {
> +		chan->err = true;
> +		tasklet_schedule(&chan->tasklet);
> +		dev_err(chan->dev, "Channel %p has errors\n", chan);
> +		ret = IRQ_HANDLED;
> +	}
> +
> +	if (status & ZYNQMP_DMA_INT_OVRFL) {
> +		zynqmp_dma_handle_ovfl_int(chan, status);
> +		dev_info(chan->dev, "Channel %p overflow interrupt\n", chan);
> +		ret = IRQ_HANDLED;
> +	}
> +
> +	return ret;
> +}
> +
> +/**
> + * zynqmp_dma_do_tasklet - Schedule completion tasklet
> + * @data: Pointer to the ZynqMP DMA channel structure  */ static void
> +zynqmp_dma_do_tasklet(unsigned long data) {
> +	struct zynqmp_dma_chan *chan = (struct zynqmp_dma_chan *)data;
> +	u32 count;
> +
> +	spin_lock(&chan->lock);
> +
> +	if (chan->err) {
> +		zynqmp_dma_reset(chan);
> +		chan->err = false;
> +		goto unlock;
> +	}
> +
> +	count = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT);
> +
> +	while (count) {
> +		zynqmp_dma_complete_descriptor(chan);
> +		zynqmp_dma_chan_desc_cleanup(chan);
> +		count--;
> +	}
> +
> +	if (chan->idle)
> +		zynqmp_dma_start_transfer(chan);
> +
> +unlock:
> +	spin_unlock(&chan->lock);
> +}
> +
> +/**
> + * zynqmp_dma_device_terminate_all - Aborts all transfers on a channel
> + * @dchan: DMA channel pointer
> + *
> + * Return: Always '0'
> + */
> +static int zynqmp_dma_device_terminate_all(struct dma_chan *dchan) {
> +	struct zynqmp_dma_chan *chan = to_chan(dchan);
> +
> +	spin_lock_bh(&chan->lock);
> +	writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs +
> ZYNQMP_DMA_IDS);
> +	zynqmp_dma_free_descriptors(chan);
> +	spin_unlock_bh(&chan->lock);
> +
> +	return 0;
> +}
> +
> +/**
> + * zynqmp_dma_prep_memcpy - prepare descriptors for memcpy transaction
> + * @dchan: DMA channel
> + * @dma_dst: Destination buffer address
> + * @dma_src: Source buffer address
> + * @len: Transfer length
> + * @flags: transfer ack flags
> + *
> + * Return: Async transaction descriptor on success and NULL on failure
> +*/ static struct dma_async_tx_descriptor *zynqmp_dma_prep_memcpy(
> +				struct dma_chan *dchan, dma_addr_t
> dma_dst,
> +				dma_addr_t dma_src, size_t len, ulong flags) {
> +	struct zynqmp_dma_chan *chan;
> +	struct zynqmp_dma_desc_sw *new, *first = NULL;
> +	void *desc = NULL, *prev = NULL;
> +	size_t copy;
> +	u32 desc_cnt;
> +
> +	chan = to_chan(dchan);
> +
> +	if ((len > ZYNQMP_DMA_MAX_TRANS_LEN) && !chan->config.has_sg)
> +		return NULL;
> +
> +	desc_cnt = DIV_ROUND_UP(len, ZYNQMP_DMA_MAX_TRANS_LEN);
> +
> +	spin_lock_bh(&chan->lock);
> +	if ((desc_cnt > chan->desc_free_cnt) && chan->config.has_sg) {
> +		spin_unlock_bh(&chan->lock);
> +		dev_dbg(chan->dev, "chan %p descs are not available\n", chan);
> +		return NULL;
> +	}
> +	chan->desc_free_cnt = chan->desc_free_cnt - desc_cnt;
> +	spin_unlock_bh(&chan->lock);
> +
> +	do {
> +		/* Allocate and populate the descriptor */
> +		new = zynqmp_dma_get_descriptor(chan);
> +
> +		copy = min_t(size_t, len, ZYNQMP_DMA_MAX_TRANS_LEN);
> +		if (chan->config.has_sg) {
> +			desc = (struct zynqmp_dma_desc_ll *)new->src_v;
> +			zynqmp_dma_config_sg_ll_desc(chan, desc, dma_src,
> +						     dma_dst, copy, prev);
> +		} else {
> +			new->src = dma_src;
> +			new->dst = dma_dst;
> +			new->len = len;
> +		}
> +
> +		prev = desc;
> +		len -= copy;
> +		dma_src += copy;
> +		dma_dst += copy;
> +		if (!first)
> +			first = new;
> +		else
> +			list_add_tail(&new->node, &first->tx_list);
> +	} while (len);
> +
> +	if (chan->config.has_sg)
> +		zynqmp_dma_desc_config_eod(chan, desc);
> +
> +	async_tx_ack(&first->async_tx);
> +	first->async_tx.flags = flags;
> +	return &first->async_tx;
> +}
> +
> +/**
> + * zynqmp_dma_prep_slave_sg - prepare descriptors for a memory sg
> +transaction
> + * @dchan: DMA channel
> + * @dst_sg: Destination scatter list
> + * @dst_sg_len: Number of entries in destination scatter list
> + * @src_sg: Source scatter list
> + * @src_sg_len: Number of entries in source scatter list
> + * @flags: transfer ack flags
> + *
> + * Return: Async transaction descriptor on success and NULL on failure
> +*/ static struct dma_async_tx_descriptor *zynqmp_dma_prep_sg(
> +			struct dma_chan *dchan, struct scatterlist *dst_sg,
> +			unsigned int dst_sg_len, struct scatterlist *src_sg,
> +			unsigned int src_sg_len, unsigned long flags) {
> +	struct zynqmp_dma_desc_sw *new, *first = NULL;
> +	struct zynqmp_dma_chan *chan = to_chan(dchan);
> +	void *desc = NULL, *prev = NULL;
> +	size_t len, dst_avail, src_avail;
> +	dma_addr_t dma_dst, dma_src;
> +	u32 desc_cnt = 0, i;
> +	struct scatterlist *sg;
> +
> +	if (!chan->config.has_sg)
> +		return NULL;
> +
> +	for_each_sg(src_sg, sg, src_sg_len, i)
> +		desc_cnt += DIV_ROUND_UP(sg_dma_len(sg),
> +					 ZYNQMP_DMA_MAX_TRANS_LEN);
> +
> +	spin_lock_bh(&chan->lock);
> +	if (desc_cnt > chan->desc_free_cnt) {
> +		spin_unlock_bh(&chan->lock);
> +		dev_dbg(chan->dev, "chan %p descs are not available\n", chan);
> +		return NULL;
> +	}
> +	chan->desc_free_cnt = chan->desc_free_cnt - desc_cnt;
> +	spin_unlock_bh(&chan->lock);
> +
> +	dst_avail = sg_dma_len(dst_sg);
> +	src_avail = sg_dma_len(src_sg);
> +
> +	/* Run until we are out of scatterlist entries */
> +	while (true) {
> +		/* Allocate and populate the descriptor */
> +		new = zynqmp_dma_get_descriptor(chan);
> +		desc = (struct zynqmp_dma_desc_ll *)new->src_v;
> +		len = min_t(size_t, src_avail, dst_avail);
> +		len = min_t(size_t, len, ZYNQMP_DMA_MAX_TRANS_LEN);
> +		if (len == 0)
> +			goto fetch;
> +		dma_dst = sg_dma_address(dst_sg) + sg_dma_len(dst_sg) -
> +			dst_avail;
> +		dma_src = sg_dma_address(src_sg) + sg_dma_len(src_sg) -
> +			src_avail;
> +
> +		zynqmp_dma_config_sg_ll_desc(chan, desc, dma_src, dma_dst,
> +					     len, prev);
> +		prev = desc;
> +		dst_avail -= len;
> +		src_avail -= len;
> +
> +		if (!first)
> +			first = new;
> +		else
> +			list_add_tail(&new->node, &first->tx_list);
> +fetch:
> +		/* Fetch the next dst scatterlist entry */
> +		if (dst_avail == 0) {
> +			if (dst_sg_len == 0)
> +				break;
> +			dst_sg = sg_next(dst_sg);
> +			if (dst_sg == NULL)
> +				break;
> +			dst_sg_len--;
> +			dst_avail = sg_dma_len(dst_sg);
> +		}
> +		/* Fetch the next src scatterlist entry */
> +		if (src_avail == 0) {
> +			if (src_sg_len == 0)
> +				break;
> +			src_sg = sg_next(src_sg);
> +			if (src_sg == NULL)
> +				break;
> +			src_sg_len--;
> +			src_avail = sg_dma_len(src_sg);
> +		}
> +	}
> +
> +	zynqmp_dma_desc_config_eod(chan, desc);
> +	first->async_tx.flags = flags;
> +	return &first->async_tx;
> +}
> +
> +/**
> + * zynqmp_dma_channel_set_config - Configure ZYNQMP DMA channel
> + * @dchan: DMA channel
> + * @cfg: ZYNQMP DMA device configuration pointer
> + *
> + * Return: '0' always
> + */
> +int zynqmp_dma_channel_set_config(struct dma_chan *dchan,
> +				  struct zynqmp_dma_config *cfg)
> +{
> +	struct zynqmp_dma_chan *chan = to_chan(dchan);
> +
> +	chan->config.ovrfetch = cfg->ovrfetch;
> +	chan->config.has_sg = cfg->has_sg;
> +	chan->config.ratectrl = cfg->ratectrl;
> +	chan->config.src_issue = cfg->src_issue;
> +	chan->config.src_burst_len = cfg->src_burst_len;
> +	chan->config.dst_burst_len = cfg->dst_burst_len;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(zynqmp_dma_channel_set_config);
> +
> +/**
> + * zynqmp_dma_chan_remove - Channel remove function
> + * @chan: ZynqMP DMA channel pointer
> + */
> +static void zynqmp_dma_chan_remove(struct zynqmp_dma_chan *chan) {
> +	if (!chan)
> +		return;
> +
> +	devm_free_irq(chan->zdev->dev, chan->irq, chan);
> +	tasklet_kill(&chan->tasklet);
> +	list_del(&chan->common.device_node);
> +	clk_disable_unprepare(chan->clk_apb);
> +	clk_disable_unprepare(chan->clk_main);
> +}
> +
> +/**
> + * zynqmp_dma_chan_probe - Per Channel Probing
> + * @zdev: Driver specific device structure
> + * @pdev: Pointer to the platform_device structure
> + *
> + * Return: '0' on success and failure value on error  */ static int
> +zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev,
> +			   struct platform_device *pdev)
> +{
> +	struct zynqmp_dma_chan *chan;
> +	struct resource *res;
> +	struct device_node *node = pdev->dev.of_node;
> +	int err;
> +
> +	chan = devm_kzalloc(zdev->dev, sizeof(*chan), GFP_KERNEL);
> +	if (!chan)
> +		return -ENOMEM;
> +	chan->dev = zdev->dev;
> +	chan->zdev = zdev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	chan->regs = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(chan->regs))
> +		return PTR_ERR(chan->regs);
> +
> +	chan->bus_width = ZYNQMP_DMA_BUS_WIDTH_64;
> +	chan->config.src_issue = ZYNQMP_DMA_SRC_ISSUE_RST_VAL;
> +	chan->config.dst_burst_len = ZYNQMP_DMA_AWLEN_RST_VAL;
> +	chan->config.src_burst_len = ZYNQMP_DMA_ARLEN_RST_VAL;
> +	err = of_property_read_u32(node, "xlnx,bus-width", &chan-
> >bus_width);
> +	if ((err < 0) && ((chan->bus_width != ZYNQMP_DMA_BUS_WIDTH_64) ||
> +			  (chan->bus_width !=
> ZYNQMP_DMA_BUS_WIDTH_128))) {
> +		dev_err(zdev->dev, "invalid bus-width value");
> +		return err;
> +	}
> +
> +	chan->bus_width = chan->bus_width / 8;
> +	chan->is_dmacoherent =  of_property_read_bool(node, "dma-
> coherent");
> +
> +	zdev->chan = chan;
> +	tasklet_init(&chan->tasklet, zynqmp_dma_do_tasklet, (ulong)chan);
> +	spin_lock_init(&chan->lock);
> +	INIT_LIST_HEAD(&chan->active_list);
> +	INIT_LIST_HEAD(&chan->pending_list);
> +	INIT_LIST_HEAD(&chan->done_list);
> +	INIT_LIST_HEAD(&chan->free_list);
> +
> +	dma_cookie_init(&chan->common);
> +	chan->common.device = &zdev->common;
> +	list_add_tail(&chan->common.device_node, &zdev-
> >common.channels);
> +
> +	zynqmp_dma_init(chan);
> +	chan->irq = platform_get_irq(pdev, 0);
> +	if (chan->irq < 0)
> +		return -ENXIO;
> +	err = devm_request_irq(&pdev->dev, chan->irq,
> zynqmp_dma_irq_handler, 0,
> +			       "zynqmp-dma", chan);
> +	if (err)
> +		return err;
> +	chan->clk_main = devm_clk_get(&pdev->dev, "clk_main");
> +	if (IS_ERR(chan->clk_main)) {
> +		dev_err(&pdev->dev, "main clock not found.\n");
> +		return PTR_ERR(chan->clk_main);
> +	}
> +
> +	chan->clk_apb = devm_clk_get(&pdev->dev, "clk_apb");
> +	if (IS_ERR(chan->clk_apb)) {
> +		dev_err(&pdev->dev, "apb clock not found.\n");
> +		return PTR_ERR(chan->clk_apb);
> +	}
> +
> +	err = clk_prepare_enable(chan->clk_main);
> +	if (err) {
> +		dev_err(&pdev->dev, "Unable to enable main clock.\n");
> +		return err;
> +	}
> +
> +	err = clk_prepare_enable(chan->clk_apb);
> +	if (err) {
> +		clk_disable_unprepare(chan->clk_main);
> +		dev_err(&pdev->dev, "Unable to enable apb clock.\n");
> +		return err;
> +	}
> +
> +	chan->desc_size = sizeof(struct zynqmp_dma_desc_ll);
> +	chan->idle = true;
> +	return 0;
> +}
> +
> +/**
> + * of_zynqmp_dma_xlate - Translation function
> + * @dma_spec: Pointer to DMA specifier as found in the device tree
> + * @ofdma: Pointer to DMA controller data
> + *
> + * Return: DMA channel pointer on success and NULL on error  */ static
> +struct dma_chan *of_zynqmp_dma_xlate(struct of_phandle_args *dma_spec,
> +					    struct of_dma *ofdma)
> +{
> +	struct zynqmp_dma_device *zdev = ofdma->of_dma_data;
> +
> +	return dma_get_slave_channel(&zdev->chan->common);
> +}
> +
> +/**
> + * zynqmp_dma_probe - Driver probe function
> + * @pdev: Pointer to the platform_device structure
> + *
> + * Return: '0' on success and failure value on error  */ static int
> +zynqmp_dma_probe(struct platform_device *pdev) {
> +	struct zynqmp_dma_device *zdev;
> +	struct dma_device *p;
> +	int ret;
> +
> +	zdev = devm_kzalloc(&pdev->dev, sizeof(*zdev), GFP_KERNEL);
> +	if (!zdev)
> +		return -ENOMEM;
> +
> +	zdev->dev = &pdev->dev;
> +	INIT_LIST_HEAD(&zdev->common.channels);
> +
> +	dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
> +	dma_cap_set(DMA_SG, zdev->common.cap_mask);
> +	dma_cap_set(DMA_MEMCPY, zdev->common.cap_mask);
> +
> +	p = &zdev->common;
> +	p->device_prep_dma_sg = zynqmp_dma_prep_sg;
> +	p->device_prep_dma_memcpy = zynqmp_dma_prep_memcpy;
> +	p->device_terminate_all = zynqmp_dma_device_terminate_all;
> +	p->device_issue_pending = zynqmp_dma_issue_pending;
> +	p->device_alloc_chan_resources = zynqmp_dma_alloc_chan_resources;
> +	p->device_free_chan_resources = zynqmp_dma_free_chan_resources;
> +	p->device_tx_status = zynqmp_dma_tx_status;
> +	p->dev = &pdev->dev;
> +
> +	platform_set_drvdata(pdev, zdev);
> +
> +	ret = zynqmp_dma_chan_probe(zdev, pdev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Probing channel failed\n");
> +		goto free_chan_resources;
> +	}
> +
> +	p->dst_addr_widths = BIT(zdev->chan->bus_width);
> +	p->src_addr_widths = BIT(zdev->chan->bus_width);
> +
> +	dma_async_device_register(&zdev->common);
> +
> +	ret = of_dma_controller_register(pdev->dev.of_node,
> +					 of_zynqmp_dma_xlate, zdev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Unable to register DMA to DT\n");
> +		dma_async_device_unregister(&zdev->common);
> +		goto free_chan_resources;
> +	}
> +
> +	dev_info(&pdev->dev, "ZynqMP DMA driver Probe success\n");
> +
> +	return 0;
> +
> +free_chan_resources:
> +	zynqmp_dma_chan_remove(zdev->chan);
> +	return ret;
> +}
> +
> +/**
> + * zynqmp_dma_remove - Driver remove function
> + * @pdev: Pointer to the platform_device structure
> + *
> + * Return: Always '0'
> + */
> +static int zynqmp_dma_remove(struct platform_device *pdev) {
> +	struct zynqmp_dma_device *zdev = platform_get_drvdata(pdev);
> +
> +	of_dma_controller_free(pdev->dev.of_node);
> +	dma_async_device_unregister(&zdev->common);
> +
> +	zynqmp_dma_chan_remove(zdev->chan);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id zynqmp_dma_of_match[] = {
> +	{ .compatible = "xlnx,zynqmp-dma-1.0", },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, zynqmp_dma_of_match);
> +
> +static struct platform_driver zynqmp_dma_driver = {
> +	.driver = {
> +		.name = "xilinx-zynqmp-dma",
> +		.of_match_table = zynqmp_dma_of_match,
> +	},
> +	.probe = zynqmp_dma_probe,
> +	.remove = zynqmp_dma_remove,
> +};
> +
> +module_platform_driver(zynqmp_dma_driver);
> +
> +MODULE_AUTHOR("Xilinx, Inc.");
> +MODULE_DESCRIPTION("Xilinx ZynqMP DMA driver");
> MODULE_LICENSE("GPL");
> diff --git a/include/linux/dma/xilinx_dma.h b/include/linux/dma/xilinx_dma.h
> index 3ae3000..7d7312f 100644
> --- a/include/linux/dma/xilinx_dma.h
> +++ b/include/linux/dma/xilinx_dma.h
> @@ -42,6 +42,24 @@ struct xilinx_vdma_config {  };
> 
>  /**
> + * struct zynqmp_dma_config - ZYNQMP DMA Configuration structure
> + * @ovrfetch: Overfetch status
> + * @has_sg: Support scatter gather transfers
> + * @ratectrl: Rate control value
> + * @src_issue: Out standing transactions on source
> + * @src_burst_len: Source burst length
> + * @dst_burst_len: Dest burst length
> + */
> +struct zynqmp_dma_config {
> +	bool ovrfetch;
> +	bool has_sg;
> +	u32 ratectrl;
> +	u32 src_issue;
> +	u32 src_burst_len;
> +	u32 dst_burst_len;
> +};
> +
> +/**
>   * enum xdma_ip_type: DMA IP type.
>   *
>   * XDMA_TYPE_AXIDMA: Axi dma ip.
> @@ -57,5 +75,6 @@ enum xdma_ip_type {
> 
>  int xilinx_vdma_channel_set_config(struct dma_chan *dchan,
>  					struct xilinx_vdma_config *cfg);
> -
> +int zynqmp_dma_channel_set_config(struct dma_chan *dchan,
> +					struct zynqmp_dma_config *cfg);
>  #endif
> --
> 2.1.1



From vinod.koul at intel.com  Sun May 29 22:18:09 2016
From: vinod.koul at intel.com (Vinod Koul)
Date: Mon, 30 May 2016 10:48:09 +0530
Subject: [PATCH 1/3] dmaengine: at_xdmac: align descriptors on 64 bits
In-Reply-To: <1463064854-6719-1-git-send-email-ludovic.desroches@atmel.com>
References: <1463064854-6719-1-git-send-email-ludovic.desroches@atmel.com>
Message-ID: <20160530051808.GJ16910@localhost>

On Thu, May 12, 2016 at 04:54:08PM +0200, Ludovic Desroches wrote:
> Having descriptors aligned on 64 bits allows update CNDA and CUBC in an
> atomic way.

Applied all, thanks

-- 
~Vinod


From linux at roeck-us.net  Sun May 29 22:25:07 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Sun, 29 May 2016 22:25:07 -0700
Subject: [2/3] hwmon: xgene: Adds hwmon driver
In-Reply-To: <1463415447-29903-3-git-send-email-hotran@apm.com>
References: <1463415447-29903-3-git-send-email-hotran@apm.com>
Message-ID: <20160530052507.GA25641@roeck-us.net>

On Mon, May 16, 2016 at 09:17:26AM -0700, hotran wrote:
> This patch adds hardware temperature and power reading support for
> APM X-Gene SoC's using the mailbox communication interface.
> 
Please drop the "'".

> 
> Signed-off-by: Hoan Tran <hotran at apm.com>
> ---
>  Documentation/hwmon/xgene-hwmon |  32 ++
>  drivers/hwmon/Kconfig           |   7 +
>  drivers/hwmon/Makefile          |   1 +
>  drivers/hwmon/xgene-hwmon.c     | 801 ++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 841 insertions(+)
>  create mode 100644 Documentation/hwmon/xgene-hwmon
>  create mode 100644 drivers/hwmon/xgene-hwmon.c
> 
> diff --git a/Documentation/hwmon/xgene-hwmon b/Documentation/hwmon/xgene-hwmon
> new file mode 100644
> index 0000000..040a7f2
> --- /dev/null
> +++ b/Documentation/hwmon/xgene-hwmon
> @@ -0,0 +1,32 @@
> +Kernel driver xgene-hwmon
> +========================
> +
> +Supported chips:
> + * APM X-Gene SoC
> +
> +Description
> +-----------
> +
> +This driver adds hardware temperature and power reading support for
> +APM X-Gene SoC's using the mailbox communication interface.
> 
No "'".
> 
> +For device tree, it is the standard DT mailbox.
> +For ACPI, it is the PCC mailbox.
> +
> +The following sensors are supported
> +
> +  * Temperature
> +    - SoC on-die temperature in milli-degree
> +    - Alarm when high/over temperature occurs
> +  * Power
> +    - CPU power in uW
> +    - IO power in uW
> +    - CPU and IO power in uW
> +
> +sysfs-Interface
> +---------------
> +
> +temp1_input - SoC on-die temperature (milli-degree C)
> +temp1_critical_alarm - An 1 would indicates on-die temperature exceeded threshold
> +power1_input - CPU power in (uW)
> +power2_input - IO power in (uW)
> +power3_input - CPU and IO power in (uW)
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 5c2d13a..91c3056 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -1776,6 +1776,13 @@ config SENSORS_ULTRA45
>  	  This driver provides support for the Ultra45 workstation environmental
>  	  sensors.
>  
> +config SENSORS_XGENE
> +	tristate "APM X-Gene SoC hardware monitoring driver"
> +	depends on XGENE_SLIMPRO_MBOX || PCC
> +	help
> +	  If you say yes here you get support for the temperature
> +	  and power sensors for APM X-Gene SoC.
> +
>  if ACPI
>  
>  comment "ACPI drivers"
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 58cc3ac..668d0f1 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -161,6 +161,7 @@ obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
>  obj-$(CONFIG_SENSORS_W83L786NG)	+= w83l786ng.o
>  obj-$(CONFIG_SENSORS_WM831X)	+= wm831x-hwmon.o
>  obj-$(CONFIG_SENSORS_WM8350)	+= wm8350-hwmon.o
> +obj-$(CONFIG_SENSORS_XGENE)	+= xgene-hwmon.o
>  
>  obj-$(CONFIG_PMBUS)		+= pmbus/
>  
> diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c
> new file mode 100644
> index 0000000..bc4ad29
> --- /dev/null
> +++ b/drivers/hwmon/xgene-hwmon.c
> @@ -0,0 +1,801 @@
> +/*
> + * APM X-Gene SoC Hardware Monitoring Driver
> + *
> + * Copyright (c) 2016, Applied Micro Circuits Corporation
> + * Author: Loc Ho <lho at apm.com>
> + *         Hoan Tran <hotran at apm.com>
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + *
> + * This driver provides the following features:
> + *  - Retrieve CPU's total power (uW)
> + *  - Retrieve IO's total power (uW)
 
Please drop the "'s".

> + *  - Retrieve SoC total power (uW)
> + *  - Retrieve SoC temperature (milli-degree C) and alarm
> + */
> +#include <linux/acpi.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +#include <linux/kfifo.h>
> +#include <linux/interrupt.h>
> +#include <linux/mailbox_client.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <acpi/cppc_acpi.h>
> +
> +/* SLIMpro message defines */
> +#define SLIMPRO_MSG_TYPE_DBG_ID		0
> +#define SLIMPRO_MSG_TYPE_ERR_ID		7
> +#define SLIMPRO_MSG_TYPE_PWRMGMT_ID	9
> +
> +#define SLIMPRO_MSG_TYPE(v)		(((v) & 0xF0000000) >> 28)
> +#define SLIMPRO_MSG_TYPE_SET(v)		(((v) << 28) & 0xF0000000)
> +#define SLIMPRO_MSG_SUBTYPE(v)		(((v) & 0x0F000000) >> 24)
> +#define SLIMPRO_MSG_SUBTYPE_SET(v)	(((v) << 24) & 0x0F000000)
> +
> +#define SLIMPRO_DBG_SUBTYPE_SENSOR_READ	4
> +#define SLIMPRO_SENSOR_READ_MSG		0x04FFE902
> +#define SLIMPRO_SENSOR_READ_ENCODE_ADDR(a) \
> +	((a) & 0x000FFFFF)
> +#define PMD_PWR_MW_REG			0x26
> +#define SOC_PWR_REG			0x21
> +#define SOC_TEMP_REG			0x10
> +
> +#define SLIMPRO_PWRMGMT_SUBTYPE_TPC	1
> +#define SLIMPRO_TPC_ALARM		2
> +#define SLIMPRO_TPC_GET_ALARM		3
> +#define SLIMPRO_TPC_CMD(v)		(((v) & 0x00FF0000) >> 16)
> +#define SLIMPRO_TPC_CMD_SET(v)		(((v) << 16) & 0x00FF0000)
> +#define SLIMPRO_TPC_ENCODE_MSG(hndl, cmd, type) \
> +	(SLIMPRO_MSG_TYPE_SET(SLIMPRO_MSG_TYPE_PWRMGMT_ID) | \
> +	SLIMPRO_MSG_SUBTYPE_SET(hndl) | \
> +	SLIMPRO_TPC_CMD_SET(cmd) | \
> +	type)
> +

Do you _have_ to use such long defines ? This causes lots of "line too long"
checkpatch warnings, which would really be easy to avoid with shorter defines.

> +/* PCC defines */
> +#define SLIMPRO_MSG_PCC_SUBSPACE	7
> +#define PCC_SIGNATURE_MASK		0x50424300
> +#define PCCC_GENERATE_DB_INT		BIT(15)
> +#define PCCS_CMD_COMPLETE		BIT(0)
> +#define PCCS_SCI_DOORBEL		BIT(1)
> +#define PCCS_PLATFORM_NOTIFICATION	BIT(3)
> +/*
> + * Arbitrary retries in case the remote processor is slow to respond
> + * to PCC commands
> + */
> +#define PCC_NUM_RETRIES			500
> +
> +#define ASYNC_MSG_FIFO_SIZE		16
> +#define MBOX_HWMON_INDEX		0
> +#define MBOX_OP_TIMEOUTMS		1000
> +
> +#define SOC_TEMP			0
> +#define CPU_POWER			0
> +#define IO_POWER			1
> +#define SOC_POWER			2
> +

Are those random defines, to be used for index values ?
If so, how about enums ?

> +#define WATT_TO_mWATT(x)		((x) * 1000)
> +#define mWATT_TO_uWATT(x)		((x) * 1000)
> +#define WATT_TO_uWATT(x)		((x) * 1000000)
> +#define CELSIUS_TO_mCELSIUS(x)		((x) * 1000)
> +
> +#define to_xgene_hwmon_dev(cl)		\
> +	container_of(cl, struct xgene_hwmon_dev, mbox_client)
> +
> +struct slimpro_resp_msg {
> +	u32 msg;
> +	u32 param1;
> +	u32 param2;
> +} __packed;
> +
> +struct xgene_hwmon_dev {
> +	struct device		*dev;
> +	struct mbox_chan	*mbox_chan;
> +	struct mbox_client	mbox_client;
> +
> +	spinlock_t		lock;
> +	struct completion	rd_complete;
> +	int			resp_pending;
> +	struct slimpro_resp_msg sync_msg;
> +
> +	struct work_struct	workq;
> +	struct kfifo_rec_ptr_1	async_msg_fifo;
> +
> +	struct device		*hwmon_dev;
> +	bool			temp_critical_alarm;
> +
> +	phys_addr_t		comm_base_addr;
> +	void			*pcc_comm_addr;
> +	u64			usecs_lat;
> +};
> +
> +/*
> + * This function tests and clears a bitmask then returns its old value
> + */
> +static u16 xgene_word_tst_and_clr(u16 *addr, u16 mask)
> +{
> +	u16 ret, val;
> +
> +	val = readw_relaxed(addr);
> +	ret = val & mask;
> +	val &= ~mask;
> +	writew_relaxed(val, addr);
> +
> +	return ret;
> +}
> +
> +static int xgene_hwmon_pcc_rd(struct xgene_hwmon_dev *ctx, u32 *msg)
> +{
> +	struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr;
> +	void *ptr = generic_comm_base + 1;
> +	unsigned long flags;
> +	u16 val;
> +	int rc;
> +
> +	spin_lock_irqsave(&ctx->lock, flags);
> +	if (ctx->resp_pending) {
> +		spin_unlock_irqrestore(&ctx->lock, flags);
> +		return -EAGAIN;
> +	}
> +
> +	init_completion(&ctx->rd_complete);
> +	ctx->resp_pending = true;
> +
> +	/* Write signature for subspace */
> +	writel_relaxed(PCC_SIGNATURE_MASK | SLIMPRO_MSG_PCC_SUBSPACE,
> +		       &generic_comm_base->signature);
> +
> +	/* Write to the shared command region */
> +	writew_relaxed(SLIMPRO_MSG_TYPE(msg[0]) | PCCC_GENERATE_DB_INT,
> +		       &generic_comm_base->command);
> +
> +	/* Flip CMD COMPLETE bit */
> +	val = readw_relaxed(&generic_comm_base->status);
> +	val &= ~PCCS_CMD_COMPLETE;
> +	writew_relaxed(val, &generic_comm_base->status);
> +
> +	/* Copy the message to the PCC comm space */
> +	memcpy(ptr, msg, sizeof(struct slimpro_resp_msg));
> +
> +	/* Ring the doorbell */
> +	rc = mbox_send_message(ctx->mbox_chan, msg);
> +	if (rc < 0) {
> +		dev_err(ctx->dev, "Mailbox send error %d\n", rc);
> +		goto err;
> +	}
> +	spin_unlock_irqrestore(&ctx->lock, flags);
> +	if (!wait_for_completion_timeout(&ctx->rd_complete,
> +					 usecs_to_jiffies(ctx->usecs_lat))) {
> +		spin_lock_irqsave(&ctx->lock, flags);
> +		dev_err(ctx->dev, "Mailbox operation timed out\n");
> +		rc = -EIO;

	-ETIMEDOUT ?

> +		goto err;
> +	}
> +	spin_lock_irqsave(&ctx->lock, flags);
> +
> +	/* Check for invalid data or no device */
> +	if (SLIMPRO_MSG_TYPE(ctx->sync_msg.msg) == SLIMPRO_MSG_TYPE_ERR_ID ||
> +	    ctx->sync_msg.msg == 0xffffffff) {
> +		rc = -ENODEV;

Two different errors ?

> +		goto err;
> +	}
> +
> +	msg[0] = ctx->sync_msg.msg;
> +	msg[1] = ctx->sync_msg.param1;
> +	msg[2] = ctx->sync_msg.param2;
> +
> +err:
> +	mbox_chan_txdone(ctx->mbox_chan, 0);
> +	ctx->resp_pending = false;
> +	spin_unlock_irqrestore(&ctx->lock, flags);
> +	return rc;
> +}
> +
> +static int xgene_hwmon_rd(struct xgene_hwmon_dev *ctx, u32 *msg)
> +{
> +	unsigned long flags;
> +	int rc;
> +
> +	spin_lock_irqsave(&ctx->lock, flags);
> +	if (ctx->resp_pending) {
> +		spin_unlock_irqrestore(&ctx->lock, flags);
> +		return -EAGAIN;
> +	}
> +
> +	init_completion(&ctx->rd_complete);
> +	ctx->resp_pending = true;
> +	rc = mbox_send_message(ctx->mbox_chan, msg);
> +	if (rc < 0) {
> +		dev_err(ctx->dev, "Mailbox send error %d\n", rc);
> +		goto err;
> +	}
> +	spin_unlock_irqrestore(&ctx->lock, flags);
> +
> +	if (!wait_for_completion_timeout(&ctx->rd_complete,
> +					 msecs_to_jiffies(MBOX_OP_TIMEOUTMS))) {
> +		spin_lock_irqsave(&ctx->lock, flags);
> +		dev_err(ctx->dev, "Mailbox operation timed out\n");
> +		rc = -EIO;

	-ETIMEDOUT ?

> +		goto err;
> +	}
> +	spin_lock_irqsave(&ctx->lock, flags);
> +
> +	/* Check for invalid data or no device */
> +	if (SLIMPRO_MSG_TYPE(ctx->sync_msg.msg) == SLIMPRO_MSG_TYPE_ERR_ID ||
> +	    ctx->sync_msg.msg == 0xffffffff) {
> +		rc = -ENODEV;

Isn't that two different errors ?

> +		goto err;
> +	}
> +
> +	msg[0] = ctx->sync_msg.msg;
> +	msg[1] = ctx->sync_msg.param1;
> +	msg[2] = ctx->sync_msg.param2;
> +
> +err:
> +	ctx->resp_pending = false;
> +	spin_unlock_irqrestore(&ctx->lock, flags);
> +	return rc;
> +}
> +
> +static int xgene_hwmon_reg_map_rd(struct xgene_hwmon_dev *ctx, u32 addr,
> +				  u32 *data)
> +{
> +	u32 msg[3];
> +	int rc;
> +
> +	msg[0] = SLIMPRO_SENSOR_READ_MSG;
> +	msg[1] = SLIMPRO_SENSOR_READ_ENCODE_ADDR(addr);
> +	msg[2] = 0;
> +
Does the msg endianness always match the CPU endianness ?
Probably yes, just want to make sure.

> +	if (ACPI_COMPANION(ctx->dev))
> +		rc = xgene_hwmon_pcc_rd(ctx, msg);
> +	else
> +		rc = xgene_hwmon_rd(ctx, msg);
> +	if (rc < 0) {
> +		/* To support compatibility with firmware, return 0 */
> +		dev_err(ctx->dev, "SLIMpro register 0x%02X read error %d\n",
> +			addr, rc);

Is this error mesage necessary ?

> +		*data = 0;
> +		return rc;
> +	}
> +	*data = msg[1];
> +
> +	return rc;
> +}
> +
> +static int xgene_hwmon_get_notification_msg(struct xgene_hwmon_dev *ctx,
> +					    u32 *amsg)
> +{
> +	u32 msg[3];
> +	int rc;
> +
> +	msg[0] = SLIMPRO_TPC_ENCODE_MSG(SLIMPRO_PWRMGMT_SUBTYPE_TPC,
> +					SLIMPRO_TPC_GET_ALARM, 0);
> +	msg[1] = 0;
> +	msg[2] = 0;
> +
> +	rc = xgene_hwmon_pcc_rd(ctx, msg);
> +	if (rc < 0) {
> +		dev_err(ctx->dev, "PCC Alarm read error %d\n", rc);

Is this error message necessary ?

> +		return rc;
> +	}
> +	amsg[0] = msg[0];
> +	amsg[1] = msg[1];
> +	amsg[2] = msg[2];
> +
> +	return rc;
> +}
> +
> +static int xgene_hwmon_get_cpu_pwr(struct xgene_hwmon_dev *ctx, u32 *val)
> +{
> +	return xgene_hwmon_reg_map_rd(ctx, PMD_PWR_MW_REG, val);
> +}
> +
> +static int xgene_hwmon_get_io_pwr(struct xgene_hwmon_dev *ctx, u32 *val)
> +{
> +	return xgene_hwmon_reg_map_rd(ctx, SOC_PWR_REG, val);
> +}
> +
> +static int xgene_hwmon_get_soc_power(struct xgene_hwmon_dev *ctx, u32 *val)
> +{
> +	u32 pmd_vrm_power;
> +	u32 io_vrm_power;
> +	int rc;
> +
> +	rc = xgene_hwmon_get_cpu_pwr(ctx, &pmd_vrm_power);
> +	if (rc < 0)
> +		return rc;
> +
> +	rc = xgene_hwmon_get_io_pwr(ctx, &io_vrm_power);
> +	if (rc < 0)
> +		return rc;
> +
> +	*val = pmd_vrm_power + WATT_TO_mWATT(io_vrm_power);
> +

So the SoC power is just adding CPU and IO power, ie it reports the sum
of both ?  Please drop. Such calculations should be done in user space
if wanted.

> +	return 0;
> +}
> +
> +static int xgene_hwmon_get_temp(struct xgene_hwmon_dev *ctx, u32 *val)
> +{
> +	return xgene_hwmon_reg_map_rd(ctx, SOC_TEMP_REG, val);
> +}
> +
> +/*
> + * Sensor temperature/power functions
> + */
> +static const char * const sensor_temp_input_names[] = {
> +	[SOC_TEMP] = "SoC Temperature",
> +};
> +
> +static const char * const sensor_pwr_input_names[] = {
> +	[CPU_POWER] = "CPU's power",
> +	[IO_POWER] = "IO's power",

Please drop the "'s".

> +	[SOC_POWER] = "SoC power"
> +};
> +
> +static ssize_t xgene_hwmon_show_name(struct device *dev,
> +				     struct device_attribute *attr, char *buf)
> +{
> +	return snprintf(buf, PAGE_SIZE, "APM X-Gene\n");
> +}
> +
> +static ssize_t xgene_hwmon_show_temp(struct device *dev,
> +				     struct device_attribute *attr,
> +				     char *buf)
> +{
> +	struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
> +	u32 val;
> +	int rc;
> +
> +	rc = xgene_hwmon_get_temp(ctx, &val);
> +	if (rc < 0)
> +		return rc;
> +
> +	val = CELSIUS_TO_mCELSIUS(val);
> +
> +	return snprintf(buf, PAGE_SIZE, "%d\n", val);

val is u32 (is it reported by the chip as unsigned ?)

> +}
> +
> +static ssize_t xgene_hwmon_show_temp_label(struct device *dev,
> +					   struct device_attribute *attr,
> +					   char *buf)
> +{
> +	int channel = to_sensor_dev_attr(attr)->index - 1;
> +
> +	return snprintf(buf, PAGE_SIZE, "%s\n",
> +			sensor_temp_input_names[channel]);
> +}
> +
> +static ssize_t xgene_hwmon_show_temp_critical_alarm(struct device *dev,
> +						    struct device_attribute *devattr,
> +						    char *buf)
> +{
> +	struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
> +
> +	return snprintf(buf, PAGE_SIZE, "%d\n", ctx->temp_critical_alarm);
> +}
> +
> +static ssize_t xgene_hwmon_show_pwr_label(struct device *dev,
> +					  struct device_attribute *attr,
> +					  char *buf)
> +{
> +	int channel = to_sensor_dev_attr(attr)->index - 1;
> +
> +	return snprintf(buf, PAGE_SIZE, "%s\n",
> +			sensor_pwr_input_names[channel]);
> +}
> +
> +static ssize_t xgene_hwmon_show_pwr(struct device *dev,
> +				    struct device_attribute *attr,
> +				    char *buf)
> +{
> +	struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
> +	int channel = to_sensor_dev_attr(attr)->index - 1;
> +	u32 val;
> +	int rc;
> +
> +	switch (channel) {
> +	case CPU_POWER:
> +		rc = xgene_hwmon_get_cpu_pwr(ctx, &val);
> +		break;
> +	case IO_POWER:
> +		rc = xgene_hwmon_get_io_pwr(ctx, &val);
> +		break;
> +	case SOC_POWER:
> +		rc = xgene_hwmon_get_soc_power(ctx, &val);
> +		break;

Those are not the index values specified. Please use those constants
in the attribute declaration.

Overall, it would probably be easier to just have two separate
functions for CPU an IO power.

> +	default:
> +		rc = -EINVAL;
> +		break;
> +	}
> +	if (rc < 0)
> +		return rc;
> +
> +	if (channel == IO_POWER)
> +		val = WATT_TO_uWATT(val);

What is the maximum possible reported IO power ? I understand that
the maximum supported value with the current code is 4,294 kW, but
if the hardware can report more than that it would be prudent to
use an unsigned long for the value.

> +	else
> +		val = mWATT_TO_uWATT(val);
> +
> +	return snprintf(buf, PAGE_SIZE, "%d\n", val);

val is u32.

> +}
> +
> +/* Chip name, required by hwmon */
> +static DEVICE_ATTR(name, S_IRUGO, xgene_hwmon_show_name, NULL);
> +

Unnecesary - see below.

> +#define SENSOR_ATTR_TEMP(index) \
> +	static SENSOR_DEVICE_ATTR(temp##index##_label, S_IRUGO, \
> +				  xgene_hwmon_show_temp_label, NULL, index); \
> +	static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, \
> +				  xgene_hwmon_show_temp, NULL, index); \
> +	static SENSOR_DEVICE_ATTR(temp##index##_critical_alarm, S_IRUGO, \
> +				  xgene_hwmon_show_temp_critical_alarm, NULL, \
> +				  index);
> +#define SENSOR_ATTR_PWR(index) \
> +	static SENSOR_DEVICE_ATTR(power##index##_label, S_IRUGO, \
> +				  xgene_hwmon_show_pwr_label, NULL, index); \
> +	static SENSOR_DEVICE_ATTR(power##index##_input, S_IRUGO, \
> +				  xgene_hwmon_show_pwr, NULL, index);
> +
> +#define APM_TEMP_SENSOR_ATTR(index) \
> +	&sensor_dev_attr_temp##index##_input.dev_attr.attr, \
> +	&sensor_dev_attr_temp##index##_label.dev_attr.attr, \
> +	&sensor_dev_attr_temp##index##_critical_alarm.dev_attr.attr
> +#define APM_PWR_SENSOR_ATTR(index) \
> +	&sensor_dev_attr_power##index##_input.dev_attr.attr, \
> +	&sensor_dev_attr_power##index##_label.dev_attr.attr
> +
> +SENSOR_ATTR_TEMP(1); /* SoC temperature */
> +SENSOR_ATTR_PWR(1);  /* CPU power */
> +SENSOR_ATTR_PWR(2);  /* IO power */
> +SENSOR_ATTR_PWR(3);  /* SoC power */
> +
> +static struct attribute *xgene_hwmon_attributes[] = {
> +	&dev_attr_name.attr,
> +	APM_TEMP_SENSOR_ATTR(1),
> +	APM_PWR_SENSOR_ATTR(1),
> +	APM_PWR_SENSOR_ATTR(2),
> +	APM_PWR_SENSOR_ATTR(3),

Please drop the macros and write explicit code.

'index' values are always accessed with '- 1'. Please start the index with 0
and drop the '- 1'.

> +	NULL,
> +};
> +
> +static const struct attribute_group xgene_hwmon_attr_group = {
> +	.attrs	= xgene_hwmon_attributes,
> +};
> +
> +static int xgene_hwmon_tpc_alarm(struct xgene_hwmon_dev *ctx,
> +				 struct slimpro_resp_msg *amsg)
> +{
> +	char name[40];
> +
> +	ctx->temp_critical_alarm = amsg->param2 ? true : false;
> +	snprintf(name, sizeof(name), "temp%d_critical_alarm", SOC_TEMP + 1);
> +	sysfs_notify(&ctx->dev->kobj, NULL, name);
> +	dev_alert(ctx->dev, "SoC temperature alarm at %d degree\n",
> +		  amsg->param1);

Please drop this message. That is what the notification is for.
User space can then decide if it wants to log or not.

> +	return 0;
> +}
> +
> +static void xgene_hwmon_process_pwrmsg(struct xgene_hwmon_dev *ctx,
> +				       struct slimpro_resp_msg *amsg)
> +{
> +	switch (SLIMPRO_MSG_SUBTYPE(amsg->msg)) {
> +	case SLIMPRO_PWRMGMT_SUBTYPE_TPC:
> +		switch (SLIMPRO_TPC_CMD(amsg->msg)) {
> +		case SLIMPRO_TPC_ALARM:
> +			xgene_hwmon_tpc_alarm(ctx, amsg);
> +			break;
> +		default:
> +			dev_warn(ctx->dev,
> +				 "Un-supported TPC message received 0x%08X\n",
> +				 amsg->msg);
> +			break;
> +		}
> +		break;
> +	default:
> +		dev_warn(ctx->dev, "Un-supported message received 0x%08X\n",
> +			 amsg->msg);

Are those messages necessary ? Can they clog the log ?

> +		break;
> +	}
> +}
> +
> +/*
> + * This function is called to process async work queue
> + */
> +static void xgene_hwmon_evt_work(struct work_struct *work)
> +{
> +	struct slimpro_resp_msg amsg;
> +	struct xgene_hwmon_dev *ctx;
> +	int ret;
> +
> +	ctx = container_of(work, struct xgene_hwmon_dev, workq);
> +	while (kfifo_out_spinlocked(&ctx->async_msg_fifo, &amsg,
> +				    sizeof(struct slimpro_resp_msg),
> +				    &ctx->lock)) {
> +		/*
> +		 * If PCC, send a consumer command to Platform to get info
> +		 * If Slimpro Mailbox, get message from specific FIFO
> +		 */
> +		if (ACPI_COMPANION(ctx->dev)) {
> +			ret = xgene_hwmon_get_notification_msg(ctx,
> +							       (u32 *)&amsg);
> +			if (ret < 0)
> +				continue;
> +		}
> +		switch (SLIMPRO_MSG_TYPE(amsg.msg)) {
> +		case SLIMPRO_MSG_TYPE_PWRMGMT_ID:
> +			xgene_hwmon_process_pwrmsg(ctx, &amsg);
> +			break;
> +		default:
> +			dev_warn(ctx->dev,
> +				 "Invalid mailbox msg received 0x%08X 0x%08X 0x%08X\n",
> +				 amsg.msg, amsg.param1, amsg.param2);

Is this message necessary ? I am concerned about the logging noise it might
create.

> +			break;
> +		}
> +	}
> +}
> +
> +/*
> + * This function is called when the SLIMpro/PCC Mailbox received a message
> + */
> +static void xgene_hwmon_rx_cb(struct mbox_client *cl, void *msg)
> +{
> +	struct xgene_hwmon_dev *ctx = to_xgene_hwmon_dev(cl);
> +	struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr;
> +	struct slimpro_resp_msg amsg;
> +
> +	/* If PCC mailbox controller, get msg from shared memory */
> +	if (ACPI_COMPANION(ctx->dev)) {
> +		msg = generic_comm_base + 1;
> +		/* Check if platform sends interrupt */
> +		if (!xgene_word_tst_and_clr(&generic_comm_base->status,
> +					    PCCS_SCI_DOORBEL))
> +			return;
> +	}
> +
> +	/*
> +	 * Response message format:
> +	 * msg[0] is the return code of the operation
> +	 * msg[1] is the first parameter word
> +	 * msg[2] is the second parameter word
> +	 *
> +	 * As message only supports dword size, just assign it.
> +	 */
> +
> +	/* Check for sync query */
> +	if (ctx->resp_pending &&
> +	    ((SLIMPRO_MSG_TYPE(((u32 *) msg)[0]) == SLIMPRO_MSG_TYPE_ERR_ID) ||
> +	     (SLIMPRO_MSG_TYPE(((u32 *) msg)[0]) == SLIMPRO_MSG_TYPE_DBG_ID &&
> +	      SLIMPRO_MSG_SUBTYPE(((u32 *) msg)[0]) == SLIMPRO_DBG_SUBTYPE_SENSOR_READ) ||
> +	     (SLIMPRO_MSG_TYPE(((u32 *) msg)[0]) == SLIMPRO_MSG_TYPE_PWRMGMT_ID &&
> +	      SLIMPRO_MSG_SUBTYPE(((u32 *) msg)[0]) == SLIMPRO_PWRMGMT_SUBTYPE_TPC &&
> +	      SLIMPRO_TPC_CMD(((u32 *) msg)[0]) == SLIMPRO_TPC_ALARM))) {
> +		if (ACPI_COMPANION(ctx->dev)) {
> +			/* Check if platform completes command */
> +			if (!xgene_word_tst_and_clr(&generic_comm_base->status,
> +						    PCCS_CMD_COMPLETE))
> +				goto notify;

How about reversing the logic here and dropping the goto ?

Overall, I have to say that the code is quite complex due to the repeated
checks for ACPI. I am close to suggest having two separate drivers,
one for ACPI and one for non-ACPI. Any chance to separate ACPI vs. non-ACPI
code a bit better ?

> +		}
> +		ctx->sync_msg.msg = ((u32 *) msg)[0];
> +		ctx->sync_msg.param1 = ((u32 *) msg)[1];
> +		ctx->sync_msg.param2 = ((u32 *) msg)[2];
> +
> +		/* Operation waiting for response */
> +		complete(&ctx->rd_complete);
> +
> +		return;
> +	}
> +
> +	/*
> +	 * If PCC, platform notifies interrupt to OSPM.
> +	 * OPSM schedules a consumer command to get this information
> +	 * in a workqueue. Platform must wait until OSPM has issued
> +	 * a consumer command that serves this notification.
> +	 */
> +notify:
> +	if (ACPI_COMPANION(ctx->dev)) {
> +		/* Check and clear Platform Notification bit */
> +		if (!xgene_word_tst_and_clr(&generic_comm_base->status,
> +					    PCCS_PLATFORM_NOTIFICATION))
> +			return;
> +	} else {
> +		amsg.msg   = ((u32 *) msg)[0];
> +		amsg.param1 = ((u32 *) msg)[1];
> +		amsg.param2 = ((u32 *) msg)[2];
> +	}
> +
> +	/* Enqueue to the FIFO */
> +	kfifo_in_spinlocked(&ctx->async_msg_fifo, &amsg,
> +			    sizeof(struct slimpro_resp_msg), &ctx->lock);
> +	/* Schedule the bottom handler */
> +	schedule_work(&ctx->workq);
> +}
> +
> +static void xgene_hwmon_tx_done(struct mbox_client *cl, void *msg, int ret)
> +{
> +	if (ret) {
> +		dev_dbg(cl->dev, "TX did not complete: CMD sent:%x, ret:%d\n",
> +			*(u16 *) msg, ret);
> +	} else {
> +		dev_dbg(cl->dev, "TX completed. CMD sent:%x, ret:%d\n",
> +			*(u16 *) msg, ret);
> +	}
> +}
> +
> +static int __init xgene_hwmon_probe(struct platform_device *pdev)
> +{
> +	struct xgene_hwmon_dev *ctx;
> +	struct mbox_client *cl;
> +	int rc;
> +
> +	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
> +	if (!ctx)
> +		return -ENOMEM;
> +
> +	ctx->dev = &pdev->dev;
> +	platform_set_drvdata(pdev, ctx);
> +	cl = &ctx->mbox_client;
> +
> +	/* Request mailbox channel */
> +	cl->dev = &pdev->dev;
> +	cl->rx_callback = xgene_hwmon_rx_cb;
> +	cl->tx_done = xgene_hwmon_tx_done;
> +	cl->tx_block = false;
> +	cl->tx_tout = MBOX_OP_TIMEOUTMS;
> +	cl->knows_txdone = false;
> +	if (!ACPI_COMPANION(cl->dev)) {
> +		ctx->mbox_chan = mbox_request_channel(cl, MBOX_HWMON_INDEX);
> +		if (IS_ERR(ctx->mbox_chan)) {
> +			dev_err(&pdev->dev,
> +				"SLIMpro mailbox channel request failed\n");
> +			return PTR_ERR(ctx->mbox_chan);
> +		}
> +	} else {
> +		struct acpi_pcct_hw_reduced *cppc_ss;
> +
> +		ctx->mbox_chan =
> +			pcc_mbox_request_channel(cl, SLIMPRO_MSG_PCC_SUBSPACE);
> +		if (IS_ERR(ctx->mbox_chan)) {
> +			dev_err(&pdev->dev,
> +				"PPC channel request failed\n");
> +			return PTR_ERR(ctx->mbox_chan);
> +		}
> +
> +		/*
> +		 * The PCC mailbox controller driver should
> +		 * have parsed the PCCT (global table of all
> +		 * PCC channels) and stored pointers to the
> +		 * subspace communication region in con_priv.
> +		 */
> +		cppc_ss = ctx->mbox_chan->con_priv;
> +		if (!cppc_ss) {
> +			dev_err(&pdev->dev, "PPC subspace not found\n");
> +			rc = -ENODEV;
> +			goto out_mbox_free;
> +		}
> +
> +		if (!ctx->mbox_chan->mbox->txdone_irq) {
> +			dev_err(&pdev->dev, "PCC IRQ not supported\n");
> +			rc = -ENODEV;
> +			goto out_mbox_free;
> +		}
> +
> +		/*
> +		 * This is the shared communication region
> +		 * for the OS and Platform to communicate over.
> +		 */
> +		ctx->comm_base_addr = cppc_ss->base_address;
> +		if (ctx->comm_base_addr) {
> +			ctx->pcc_comm_addr =
> +					acpi_os_ioremap(ctx->comm_base_addr,
> +							cppc_ss->length);
> +		} else {
> +			dev_err(&pdev->dev, "Failed to get PCC comm region\n");
> +			rc = -ENODEV;
> +			goto out_mbox_free;
> +		}
> +
> +		if (!ctx->pcc_comm_addr) {
> +			dev_err(&pdev->dev,
> +				"Failed to ioremap PCC comm region\n");
> +			rc = -ENOMEM;
> +			goto out_mbox_free;
> +		}
> +
> +		/*
> +		 * cppc_ss->latency is just a Nominal value. In reality
> +		 * the remote processor could be much slower to reply.
> +		 * So add an arbitrary amount of wait on top of Nominal.
> +		 */
> +		ctx->usecs_lat = PCC_NUM_RETRIES * cppc_ss->latency;
> +	}
> +
> +	spin_lock_init(&ctx->lock);
> +
> +	rc = kfifo_alloc(&ctx->async_msg_fifo,
> +			 sizeof(struct slimpro_resp_msg) * ASYNC_MSG_FIFO_SIZE,
> +			 GFP_KERNEL);
> +	if (rc)
> +		goto out_mbox_free;
> +
> +	INIT_WORK(&ctx->workq, xgene_hwmon_evt_work);
> +
> +	/* Hook up sysfs for sensor monitor */
> +	rc = sysfs_create_group(&pdev->dev.kobj, &xgene_hwmon_attr_group);
> +	if (rc) {
> +		dev_err(&pdev->dev, "Fail to create sysfs\n");
> +		goto out_kfifo_free;
> +	}
> +
> +	ctx->hwmon_dev = hwmon_device_register(ctx->dev);
> +	if (IS_ERR(ctx->hwmon_dev)) {
> +		dev_err(&pdev->dev, "Failed to register HW monitor device\n");
> +		rc = PTR_ERR(ctx->hwmon_dev);
> +		goto out;
> +	}

Please use hwmon_device_register_with_groups().

> +
> +	dev_info(&pdev->dev, "APM X-Gene SoC HW monitor driver registered\n");
> +
> +	return rc;
> +
> +out:
> +	sysfs_remove_group(&pdev->dev.kobj, &xgene_hwmon_attr_group);
> +out_kfifo_free:
> +	kfifo_free(&ctx->async_msg_fifo);
> +out_mbox_free:
> +	mbox_free_channel(ctx->mbox_chan);
> +
> +	return rc;
> +}
> +
> +static int xgene_hwmon_remove(struct platform_device *pdev)
> +{
> +	struct xgene_hwmon_dev *ctx = platform_get_drvdata(pdev);
> +
> +	hwmon_device_unregister(ctx->hwmon_dev);
> +	sysfs_remove_group(&pdev->dev.kobj, &xgene_hwmon_attr_group);
> +	kfifo_free(&ctx->async_msg_fifo);
> +	mbox_free_channel(ctx->mbox_chan);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_ACPI
> +static const struct acpi_device_id xgene_hwmon_acpi_match[] = {
> +	{"APMC0D29", 0},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(acpi, xgene_hwmon_acpi_match);
> +#endif
> +
> +static const struct of_device_id xgene_hwmon_of_match[] = {
> +	{.compatible = "apm,xgene-slimpro-hwmon"},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, xgene_hwmon_of_match);
> +
> +static struct platform_driver xgene_hwmon_driver __refdata = {
> +	.probe = xgene_hwmon_probe,
> +	.remove = xgene_hwmon_remove,
> +	.driver = {
> +		.name = "xgene-slimpro-hwmon",
> +		.of_match_table = xgene_hwmon_of_match,
> +		.acpi_match_table = ACPI_PTR(xgene_hwmon_acpi_match),
> +	},
> +};
> +module_platform_driver(xgene_hwmon_driver);
> +
> +MODULE_DESCRIPTION("APM X-Gene SoC hardware monitor");
> +MODULE_LICENSE("GPL");


From nava.manne at xilinx.com  Sun May 29 22:46:21 2016
From: nava.manne at xilinx.com (Nava kishore Manne)
Date: Mon, 30 May 2016 05:46:21 +0000
Subject: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
In-Reply-To: <CAL_Jsq+VL6jjo5QLwnsC8rEfgP4KN5hCSB7QicWWN-uvZU0GHw@mail.gmail.com>
References: <1464067268-35299-1-git-send-email-navam@xilinx.com>
 <C89496FEAE474D468F30D558A9468D9F26CED772@XAP-PVEXMBX01.xlnx.xilinx.com>
 <20160525173419.GA7510@rob-hp-laptop> <5392766.vCAWrASuOA@wuerfel>
 <CAL_Jsq+VL6jjo5QLwnsC8rEfgP4KN5hCSB7QicWWN-uvZU0GHw@mail.gmail.com>
Message-ID: <C89496FEAE474D468F30D558A9468D9F26CEEBAB@XAP-PVEXMBX01.xlnx.xilinx.com>



> -----Original Message-----
> From: Rob Herring [mailto:robh at kernel.org]
> Sent: Thursday, May 26, 2016 12:24 AM
> To: Arnd Bergmann <arnd at arndb.de>
> Cc: Nava kishore Manne <navam at xilinx.com>; pawel.moll at arm.com;
> mark.rutland at arm.com; ijc+devicetree at hellion.org.uk;
> galak at codeaurora.org; Michal Simek <michals at xilinx.com>; Soren
> Brinkmann <sorenb at xilinx.com>; balbi at ti.com;
> gregkh at linuxfoundation.org; Hyun Kwon <hyunk at xilinx.com>; Radhey
> Shyam Pandey <radheys at xilinx.com>; devicetree at vger.kernel.org; linux-
> arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> Subject: Re: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
>
> On Wed, May 25, 2016 at 1:29 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> > On Wednesday, May 25, 2016 12:34:19 PM CEST Rob Herring wrote:
> >> On Tue, May 24, 2016 at 11:47:31AM +0000, Nava kishore Manne wrote:
> >> >
> >> >
> >> > > -----Original Message-----
> >> > > From: Arnd Bergmann [mailto:arnd at arndb.de]
> >> > > Sent: Tuesday, May 24, 2016 2:21 PM
> >> > > To: Nava kishore Manne <navam at xilinx.com>
> >> > > Cc: robh+dt at kernel.org; pawel.moll at arm.com;
> mark.rutland at arm.com;
> >> > > ijc+devicetree at hellion.org.uk; galak at codeaurora.org; Michal Simek
> >> > > <michals at xilinx.com>; Soren Brinkmann <sorenb at xilinx.com>;
> >> > > balbi at ti.com; gregkh at linuxfoundation.org; Hyun Kwon
> >> > > <hyunk at xilinx.com>; Nava kishore Manne <navam at xilinx.com>;
> Radhey
> >> > > Shyam Pandey <radheys at xilinx.com>; devicetree at vger.kernel.org;
> >> > > linux- arm-kernel at lists.infradead.org;
> >> > > linux-kernel at vger.kernel.org
> >> > > Subject: Re: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
> >> > >
> >> > > On Tuesday, May 24, 2016 10:51:08 AM CEST Nava kishore Manne
> wrote:
> >> > > > diff --git
> >> > > > a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> >> > > > b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> >> > > > index 47b4e39..09df757 100644
> >> > > > --- a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> >> > > > +++ b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> >> > > > @@ -1,18 +1,23 @@
> >> > > >  Xilinx USB2 device controller
> >> > > >
> >> > > >  Required properties:
> >> > > > -- compatible             : Should be "xlnx,usb2-device-4.00.a"
> >> > > > +- compatible             : Should be "xlnx,usb2-device-4.00.a" or
> >> > > > +                   "xlnx,usb2-device-5.00"
> >> > > >  - reg                    : Physical base address and size of the USB2
> >> > > >                     device registers map.
> >> > > >  - interrupts             : Should contain single irq line of USB2 device
> >> > > >                     controller
> >> > > >  - xlnx,has-builtin-dma   : if DMA is included
> >> > > > +- dma-ranges             : Should be as the following
> >> > > > +                   <child-bus-address, parent-bus-address,
> >> > > > +length>
> >> > >
> >> > > A USB host should not have any children that are DMA capable, I
> >> > > think, so this property doesn't make sense here. It should be part of
> the parent bus.
> >> > >
> >> > Will send next version (v4) by removing this property from the DT.
> >> >
> >> > > > +- xlnx,addrwidth : Should be the dma addressing size in
> >> > > > +bits(ex: 64
> >> > > bits)
> >> > >
> >> > > I'm still unconvinced about the property definition here. What
> >> > > are the possible options for the IP block? I don't think I ever
> >> > > saw a reply from you to my earlier questions.
> >> > >
> >> >
> >> > Sorry Let me clearly explain
> >> >
> >> > From the IP version 5.0 onwards The IP support both 32-bit and 64-bit
> addressing.
> >> > But the older version of the IP's supports only 32-bit addressing.
> >> >
> >> > This addrwidth property differentiates the address width for the
> >> > new IP (I mean 5.0 version on wards) For older IP it will be always 32-bit.
> >>
> >> Then I think you should have a simple boolean property for 64-bit
> >> configuration.
> >
> > I think matching on the version number is slightly better, as we have
> > the version already and it identifies whether the register exists.
> >
> > Having a boolean property of course works as well, it just duplicates
> > that information.
>
> It doesn't because v5.0 h/w can be configured for either 32 or 64-bit mode.
> Normally, we would encode configuration into the compatible strings, but I
> view FPGA based blocks to be an exception. Of course, since they can just
> "fix the h/w" we could just require h/w version and feature registers. ;)
>
The Axi-usb 5.00 IP is a FPGA based one. This IP needs to support two H/w designs one with 32 bit DMA addressing another one is 64 bit DMA addressing.
And also in the software point for view we don?t have any register to figure out whether it is supporting 32 bit DMA addressing or 64 bit DMA addressing.
To support both the designs I kept addrwidth property in the dt. I think here addrwidth property is make sense to differentiate the h/w configurations.
If you want me to changes it to boolean please let me know I will fix it in the next version.

Regards,
Navakishore.

> Rob


This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.


From shubhrajyoti.datta at gmail.com  Sun May 29 23:17:01 2016
From: shubhrajyoti.datta at gmail.com (Shubhrajyoti Datta)
Date: Mon, 30 May 2016 11:47:01 +0530
Subject: [PATCH v9 2/2] dmaengine: Add Xilinx zynqmp dma engine driver
 support
In-Reply-To: <1463123033-5443-2-git-send-email-appanad@xilinx.com>
References: <1463123033-5443-1-git-send-email-appanad@xilinx.com>
 <1463123033-5443-2-git-send-email-appanad@xilinx.com>
Message-ID: <CAKfKVtE-2rYVmCK1OOzitayH7AzUQHnspoEv6RBLCxUJVnVksg@mail.gmail.com>

> + */
> +static void zynqmp_dma_update_desc_to_ctrlr(struct zynqmp_dma_chan *chan,
> +                                     struct zynqmp_dma_desc_sw *desc)
> +{
> +       dma_addr_t addr;
> +
> +       addr = desc->src_p;
> +       writel(addr, chan->regs + ZYNQMP_DMA_SRC_START_LSB);
> +       writel(upper_32_bits(addr), chan->regs + ZYNQMP_DMA_SRC_START_MSB);
Can we combine the two writes to a 64bit write.
It may be helpful on 64-bit systems.


> +       addr = desc->dst_p;
> +       writel(addr, chan->regs + ZYNQMP_DMA_DST_START_LSB);
> +       writel(upper_32_bits(addr), chan->regs + ZYNQMP_DMA_DST_START_MSB);
> +}


From k.kozlowski at samsung.com  Sun May 29 23:20:48 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 30 May 2016 08:20:48 +0200
Subject: [GIT PULL] ARM: exynos: Fixes for v4.7
Message-ID: <1464589248-31326-1-git-send-email-k.kozlowski@samsung.com>

Hi,

A couple of fixes from Arnd for this release cycle.


Best regards,
Krzysztof


The following changes since commit 2dcd0af568b0cf583645c8a317dd12e344b1c72a:

  Linux 4.6 (2016-05-15 15:43:13 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git tags/samsung-fixes-4.7

for you to fetch changes up to 8a6f71ccb6c39ca5ae442d1478d3a076e2b1361e:

  ARM: exynos: don't select keyboard driver (2016-05-18 16:58:10 +0200)

----------------------------------------------------------------
Two fixes for v4.7 cycle for build issues:
1. Fix samsung-keypad build error if INPUT is selected as module.
   The error though depends on some uncommon build settings so it
   is not as easy to trigger.

2. Get rid of 'samsung_device_dma_mask' defined but not used warning.

----------------------------------------------------------------
Arnd Bergmann (2):
      ARM: samsung: improve static dma_mask definition
      ARM: exynos: don't select keyboard driver

 arch/arm/configs/exynos_defconfig   | 1 +
 arch/arm/configs/multi_v7_defconfig | 1 +
 arch/arm/mach-exynos/Kconfig        | 1 -
 arch/arm/plat-samsung/devs.c        | 2 +-
 4 files changed, 3 insertions(+), 2 deletions(-)


From k.kozlowski at samsung.com  Sun May 29 23:35:55 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 30 May 2016 08:35:55 +0200
Subject: [PATCH] ARM: exynos_defconfig: Disable big.LITTLE switcher
In-Reply-To: <1493315.8NlXQFsEtt@amdc1976>
References: <1493315.8NlXQFsEtt@amdc1976>
Message-ID: <574BDF4B.5020809@samsung.com>

On 04/28/2016 04:44 PM, Bartlomiej Zolnierkiewicz wrote:
> Disable big.LITTLE switcher in order to allow automatic usage of
> cpufreq-dt driver on Exynos542x/Exynos5800 SoCs based boards.
> 
> This change should not cause any problems as arm_big_little[_dt]
> driver (which is using big.LITTLE switcher support to do the "real"
> big.LITTLE switching work) is not used on any Exynos SoC based
> board currently.
> 
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie at samsung.com>
> ---
>  arch/arm/configs/exynos_defconfig | 2 --
>  1 file changed, 2 deletions(-)

Thanks, applied.

Krzysztof



From k.kozlowski at samsung.com  Sun May 29 23:36:19 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 30 May 2016 08:36:19 +0200
Subject: [PATCH 1/2] ARM: exynos_defconfig: Enable MFC driver as module
In-Reply-To: <1462914448-24480-1-git-send-email-javier@osg.samsung.com>
References: <1462914448-24480-1-git-send-email-javier@osg.samsung.com>
Message-ID: <574BDF63.1090407@samsung.com>

On 05/10/2016 11:07 PM, Javier Martinez Canillas wrote:
> Exynos SoCs have a Multi Format Video Hardware Codec (MFC) IP block that
> can be used to {en,de}code video streams by hardware. Enable support for
> its driver as a module so the MFC can be tested.
> 
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
> 
> ---
> 
> This patch depends on https://patchwork.kernel.org/patch/8970731/
> 
>  arch/arm/configs/exynos_defconfig | 1 +
>  1 file changed, 1 insertion(+)

Thanks, applied both.

Krzysztof



From ck.hu at mediatek.com  Sun May 29 23:49:02 2016
From: ck.hu at mediatek.com (CK Hu)
Date: Mon, 30 May 2016 14:49:02 +0800
Subject: [PATCH v8 2/3] CMDQ: Mediatek CMDQ driver
In-Reply-To: <1464578397-29743-3-git-send-email-hs.liao@mediatek.com>
References: <1464578397-29743-1-git-send-email-hs.liao@mediatek.com>
 <1464578397-29743-3-git-send-email-hs.liao@mediatek.com>
Message-ID: <1464590942.20547.22.camel@mtksdaap41>

Hi, HS:

Some comments inline.

On Mon, 2016-05-30 at 11:19 +0800, HS Liao wrote:
> This patch is first version of Mediatek Command Queue(CMDQ) driver. The
> CMDQ is used to help read/write registers with critical time limitation,
> such as updating display configuration during the vblank. It controls
> Global Command Engine (GCE) hardware to achieve this requirement.
> Currently, CMDQ only supports display related hardwares, but we expect
> it can be extended to other hardwares for future requirements.
> 
> Signed-off-by: HS Liao <hs.liao at mediatek.com>
> Signed-off-by: CK Hu <ck.hu at mediatek.com>
> ---
>  drivers/soc/mediatek/Kconfig    |  10 +
>  drivers/soc/mediatek/Makefile   |   1 +
>  drivers/soc/mediatek/mtk-cmdq.c | 943 ++++++++++++++++++++++++++++++++++++++++
>  include/soc/mediatek/cmdq.h     | 197 +++++++++
>  4 files changed, 1151 insertions(+)
>  create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
>  create mode 100644 include/soc/mediatek/cmdq.h
> 
> diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
> index 0a4ea80..c4ad75c 100644
> --- a/drivers/soc/mediatek/Kconfig
> +++ b/drivers/soc/mediatek/Kconfig
> @@ -1,6 +1,16 @@
>  #
>  # MediaTek SoC drivers
>  #
> +config MTK_CMDQ
> +	bool "MediaTek CMDQ Support"
> +	depends on ARCH_MEDIATEK || COMPILE_TEST
> +	select MTK_INFRACFG
> +	help
> +	  Say yes here to add support for the MediaTek Command Queue (CMDQ)
> +	  driver. The CMDQ is used to help read/write registers with critical
> +	  time limitation, such as updating display configuration during the
> +	  vblank.
> +
>  config MTK_INFRACFG
>  	bool "MediaTek INFRACFG Support"
>  	depends on ARCH_MEDIATEK || COMPILE_TEST
> diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
> index 12998b0..f7397ef 100644
> --- a/drivers/soc/mediatek/Makefile
> +++ b/drivers/soc/mediatek/Makefile
> @@ -1,3 +1,4 @@
> +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq.o
>  obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
>  obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
>  obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
> diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
> new file mode 100644
> index 0000000..e9d6e1c
> --- /dev/null
> +++ b/drivers/soc/mediatek/mtk-cmdq.c
> @@ -0,0 +1,943 @@
> +/*
> + * Copyright (c) 2015 MediaTek Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/completion.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/errno.h>
> +#include <linux/interrupt.h>
> +#include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +#include <linux/kthread.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/suspend.h>
> +#include <linux/workqueue.h>
> +#include <soc/mediatek/cmdq.h>
> +
> +#define CMDQ_INITIAL_CMD_BLOCK_SIZE	PAGE_SIZE
> +#define CMDQ_INST_SIZE			8 /* instruction is 64-bit */
> +#define CMDQ_TIMEOUT_MS			1000
> +#define CMDQ_IRQ_MASK			0xffff
> +#define CMDQ_DRIVER_DEVICE_NAME		"mtk_cmdq"
> +#define CMDQ_CLK_NAME			"gce"
> +
> +#define CMDQ_CURR_IRQ_STATUS		0x010
> +#define CMDQ_CURR_LOADED_THR		0x018
> +#define CMDQ_THR_SLOT_CYCLES		0x030
> +
> +#define CMDQ_THR_BASE			0x100
> +#define CMDQ_THR_SHIFT			0x080
> +#define CMDQ_THR_WARM_RESET		0x00
> +#define CMDQ_THR_ENABLE_TASK		0x04
> +#define CMDQ_THR_SUSPEND_TASK		0x08
> +#define CMDQ_THR_CURR_STATUS		0x0c
> +#define CMDQ_THR_IRQ_STATUS		0x10
> +#define CMDQ_THR_IRQ_ENABLE		0x14
> +#define CMDQ_THR_CURR_ADDR		0x20
> +#define CMDQ_THR_END_ADDR		0x24
> +#define CMDQ_THR_CFG			0x40
> +
> +#define CMDQ_THR_ENABLED		0x1
> +#define CMDQ_THR_DISABLED		0x0
> +#define CMDQ_THR_SUSPEND		0x1
> +#define CMDQ_THR_RESUME			0x0
> +#define CMDQ_THR_STATUS_SUSPENDED	BIT(1)
> +#define CMDQ_THR_DO_WARM_RESET		BIT(0)
> +#define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
> +#define CMDQ_THR_PRIORITY		3
> +#define CMDQ_THR_IRQ_DONE		0x1
> +#define CMDQ_THR_IRQ_ERROR		0x12
> +#define CMDQ_THR_IRQ_EN			0x13 /* done + error */
> +#define CMDQ_THR_IRQ_MASK		0x13
> +#define CMDQ_THR_EXECUTING		BIT(31)
> +
> +#define CMDQ_ARG_A_WRITE_MASK		0xffff
> +#define CMDQ_SUBSYS_MASK		0x1f
> +#define CMDQ_OP_CODE_MASK		0xff000000
> +
> +#define CMDQ_OP_CODE_SHIFT		24
> +#define CMDQ_SUBSYS_SHIFT		16
> +
> +#define CMDQ_WRITE_ENABLE_MASK		BIT(0)
> +#define CMDQ_JUMP_BY_OFFSET		0x10000000
> +#define CMDQ_JUMP_BY_PA			0x10000001
> +#define CMDQ_JUMP_PASS			CMDQ_INST_SIZE
> +#define CMDQ_WFE_UPDATE			BIT(31)
> +#define CMDQ_WFE_WAIT			BIT(15)
> +#define CMDQ_WFE_WAIT_VALUE		0x1
> +#define CMDQ_EOC_IRQ_EN			BIT(0)
> +
> +enum cmdq_thread_index {
> +	CMDQ_THR_DISP_MAIN_IDX,	/* main */
> +	CMDQ_THR_DISP_SUB_IDX,	/* sub */
> +	CMDQ_THR_DISP_MISC_IDX,	/* misc */
> +	CMDQ_THR_MAX_COUNT,	/* max */
> +};
> +
> +/*
> + * CMDQ_CODE_MOVE:
> + *   move value into internal register as mask
> + *   format: op mask
> + * CMDQ_CODE_WRITE:
> + *   write value into target register
> + *   format: op subsys address value
> + * CMDQ_CODE_JUMP:
> + *   jump by offset
> + *   format: op offset
> + * CMDQ_CODE_WFE:
> + *   wait for event and clear
> + *   it is just clear if no wait
> + *   format: [wait]  op event update:1 to_wait:1 wait:1
> + *           [clear] op event update:1 to_wait:0 wait:0
> + * CMDQ_CODE_EOC:
> + *   end of command
> + *   format: op irq_flag
> + */
> +enum cmdq_code {
> +	CMDQ_CODE_MOVE = 0x02,
> +	CMDQ_CODE_WRITE = 0x04,
> +	CMDQ_CODE_JUMP = 0x10,
> +	CMDQ_CODE_WFE = 0x20,
> +	CMDQ_CODE_EOC = 0x40,
> +};
> +
> +enum cmdq_task_state {
> +	TASK_STATE_BUSY, /* running on a GCE thread */
> +	TASK_STATE_ERROR,
> +	TASK_STATE_DONE,
> +};
> +
> +struct cmdq_task_cb {
> +	cmdq_async_flush_cb	cb;
> +	void			*data;
> +};
> +
> +struct cmdq_thread {
> +	void __iomem		*base;
> +	struct list_head	task_busy_list;
> +	wait_queue_head_t	wait_task_done;
> +};
> +
> +struct cmdq_task {
> +	struct cmdq		*cmdq;
> +	struct list_head	list_entry;
> +	enum cmdq_task_state	task_state;
> +	void			*va_base;
> +	dma_addr_t		pa_base;
> +	u64			engine_flag;
> +	size_t			command_size;
> +	u32			num_cmd;
> +	struct cmdq_thread	*thread;
> +	struct cmdq_task_cb	cb;
> +	struct work_struct	release_work;
> +};
> +
> +struct cmdq {
> +	struct device		*dev;
> +	void __iomem		*base;
> +	u32			irq;
> +	struct workqueue_struct	*task_release_wq;
> +	struct cmdq_thread	thread[CMDQ_THR_MAX_COUNT];
> +	struct mutex		task_mutex;	/* for task */
> +	spinlock_t		exec_lock;	/* for exec */
> +	struct clk		*clock;
> +	bool			suspended;
> +};
> +
> +struct cmdq_subsys {
> +	u32	base;
> +	int	id;
> +};
> +
> +static const struct cmdq_subsys gce_subsys[] = {
> +	{0x1400, 1},
> +	{0x1401, 2},
> +	{0x1402, 3},
> +};
> +
> +static int cmdq_subsys_base_to_id(u32 base)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(gce_subsys); i++)
> +		if (gce_subsys[i].base == base)
> +			return gce_subsys[i].id;
> +	return -EFAULT;
> +}
> +
> +static int cmdq_eng_get_thread(u64 flag)
> +{
> +	if (flag & BIT_ULL(CMDQ_ENG_DISP_DSI0))
> +		return CMDQ_THR_DISP_MAIN_IDX;
> +	else if (flag & BIT_ULL(CMDQ_ENG_DISP_DPI0))
> +		return CMDQ_THR_DISP_SUB_IDX;
> +	else
> +		return CMDQ_THR_DISP_MISC_IDX;
> +}
> +
> +static void cmdq_task_release(struct cmdq_task *task)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +
> +	dma_free_coherent(cmdq->dev, task->command_size, task->va_base,
> +			  task->pa_base);
> +	kfree(task);
> +}
> +
> +static struct cmdq_task *cmdq_task_acquire(struct cmdq_rec *rec,
> +					   struct cmdq_task_cb cb)
> +{
> +	struct cmdq *cmdq = rec->cmdq;
> +	struct device *dev = cmdq->dev;
> +	struct cmdq_task *task;
> +
> +	task = kzalloc(sizeof(*task), GFP_KERNEL);
> +	INIT_LIST_HEAD(&task->list_entry);
> +	task->va_base = dma_alloc_coherent(dev, rec->command_size,
> +					   &task->pa_base, GFP_KERNEL);
> +	if (!task->va_base) {
> +		dev_err(dev, "allocate command buffer failed\n");
> +		kfree(task);
> +		return NULL;
> +	}
> +
> +	task->cmdq = cmdq;
> +	task->command_size = rec->command_size;
> +	task->engine_flag = rec->engine_flag;
> +	task->task_state = TASK_STATE_BUSY;
> +	task->cb = cb;
> +	memcpy(task->va_base, rec->buf, rec->command_size);
> +	task->num_cmd = task->command_size / CMDQ_INST_SIZE;
> +	return task;
> +}
> +
> +static void cmdq_thread_writel(struct cmdq_thread *thread, u32 value,
> +			       u32 offset)
> +{
> +	writel(value, thread->base + offset);
> +}
> +
> +static u32 cmdq_thread_readl(struct cmdq_thread *thread, u32 offset)
> +{
> +	return readl(thread->base + offset);
> +}
> +
> +static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
> +{
> +	u32 status;
> +
> +	cmdq_thread_writel(thread, CMDQ_THR_SUSPEND, CMDQ_THR_SUSPEND_TASK);
> +
> +	/* If already disabled, treat as suspended successful. */
> +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> +	      CMDQ_THR_ENABLED))
> +		return 0;
> +
> +	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_CURR_STATUS,
> +			status, status & CMDQ_THR_STATUS_SUSPENDED, 0, 10)) {
> +		dev_err(cmdq->dev, "suspend GCE thread 0x%x failed\n",
> +			(u32)(thread->base - cmdq->base));
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static void cmdq_thread_resume(struct cmdq_thread *thread)
> +{
> +	cmdq_thread_writel(thread, CMDQ_THR_RESUME, CMDQ_THR_SUSPEND_TASK);
> +}
> +
> +static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
> +{
> +	u32 warm_reset;
> +
> +	cmdq_thread_writel(thread, CMDQ_THR_DO_WARM_RESET, CMDQ_THR_WARM_RESET);
> +	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET,
> +			warm_reset, !(warm_reset & CMDQ_THR_DO_WARM_RESET),
> +			0, 10)) {
> +		dev_err(cmdq->dev, "reset GCE thread 0x%x failed\n",
> +			(u32)(thread->base - cmdq->base));
> +		return -EFAULT;
> +	}
> +	writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES);
> +	return 0;
> +}
> +
> +static void cmdq_thread_disable(struct cmdq *cmdq, struct cmdq_thread *thread)
> +{
> +	cmdq_thread_reset(cmdq, thread);
> +	cmdq_thread_writel(thread, CMDQ_THR_DISABLED, CMDQ_THR_ENABLE_TASK);
> +}
> +
> +/* notify GCE to re-fetch commands by setting GCE thread PC */
> +static void cmdq_thread_invalidate_fetched_data(struct cmdq_thread *thread)
> +{
> +	cmdq_thread_writel(thread,
> +			   cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR),
> +			   CMDQ_THR_CURR_ADDR);
> +}
> +
> +static void cmdq_task_insert_into_thread(struct cmdq_task *task)
> +{
> +	struct cmdq_thread *thread = task->thread;
> +	struct cmdq_task *prev_task = list_last_entry(
> +			&thread->task_busy_list, typeof(*task), list_entry);
> +	u64 *prev_task_base = prev_task->va_base;
> +
> +	/* let previous task jump to this task */
> +	prev_task_base[prev_task->num_cmd - 1] = (u64)CMDQ_JUMP_BY_PA << 32 |
> +						 task->pa_base;
> +
> +	cmdq_thread_invalidate_fetched_data(thread);
> +}
> +
> +/* we assume tasks in the same display GCE thread are waiting the same event. */
> +static void cmdq_task_remove_wfe(struct cmdq_task *task)
> +{
> +	u32 wfe_option = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
> +	u32 wfe_op = CMDQ_CODE_WFE << CMDQ_OP_CODE_SHIFT;
> +	u32 *base = task->va_base;
> +	u32 num_cmd = task->num_cmd << 1;
> +	int i;
> +
> +	for (i = 0; i < num_cmd; i += 2)
> +		if (base[i] == wfe_option &&
> +		    (base[i + 1] & CMDQ_OP_CODE_MASK) == wfe_op) {
> +			base[i] = CMDQ_JUMP_PASS;
> +			base[i + 1] = CMDQ_JUMP_BY_OFFSET;
> +		}
> +}
> +
> +static void cmdq_task_exec(struct cmdq_task *task, struct cmdq_thread *thread)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +	unsigned long flags;
> +	unsigned long curr_pa, end_pa;
> +
> +	WARN_ON(clk_prepare_enable(cmdq->clock) < 0);
> +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> +	task->thread = thread;
> +	task->task_state = TASK_STATE_BUSY;
> +	if (list_empty(&thread->task_busy_list)) {
> +		WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
> +
> +		cmdq_thread_writel(thread, task->pa_base, CMDQ_THR_CURR_ADDR);
> +		cmdq_thread_writel(thread, task->pa_base + task->command_size,
> +				   CMDQ_THR_END_ADDR);
> +		cmdq_thread_writel(thread, CMDQ_THR_PRIORITY, CMDQ_THR_CFG);
> +		cmdq_thread_writel(thread, CMDQ_THR_IRQ_EN,
> +				   CMDQ_THR_IRQ_ENABLE);
> +
> +		cmdq_thread_writel(thread, CMDQ_THR_ENABLED,
> +				   CMDQ_THR_ENABLE_TASK);
> +	} else {
> +		WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
> +
> +		/*
> +		 * check boundary condition
> +		 * PC = END - 8, EOC is executed
> +		 * PC = END, all CMDs are executed
> +		 */
> +		curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
> +		end_pa = cmdq_thread_readl(thread, CMDQ_THR_END_ADDR);
> +		if (curr_pa == end_pa - 8 || curr_pa == end_pa) {
> +			/* set to this task directly */
> +			cmdq_thread_writel(thread, task->pa_base,
> +					   CMDQ_THR_CURR_ADDR);
> +		} else {
> +			cmdq_task_insert_into_thread(task);
> +
> +			if (thread == &cmdq->thread[CMDQ_THR_DISP_MAIN_IDX] ||
> +			    thread == &cmdq->thread[CMDQ_THR_DISP_SUB_IDX])
> +				cmdq_task_remove_wfe(task);
> +
> +			smp_mb(); /* modify jump before enable thread */
> +		}
> +
> +		cmdq_thread_writel(thread, task->pa_base + task->command_size,
> +				   CMDQ_THR_END_ADDR);
> +		cmdq_thread_resume(thread);
> +	}
> +	list_move_tail(&task->list_entry, &thread->task_busy_list);
> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +}
> +
> +static void cmdq_handle_error_done(struct cmdq *cmdq,
> +				   struct cmdq_thread *thread, u32 irq_flag)
> +{
> +	struct cmdq_task *task, *tmp, *curr_task = NULL;
> +	u32 curr_pa;
> +	struct cmdq_cb_data cmdq_cb_data;
> +	bool err;
> +
> +	if (irq_flag & CMDQ_THR_IRQ_ERROR)
> +		err = true;
> +	else if (irq_flag & CMDQ_THR_IRQ_DONE)
> +		err = false;
> +	else
> +		return;
> +
> +	curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
> +
> +	list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
> +				 list_entry) {
> +		if (curr_pa >= task->pa_base &&
> +		    curr_pa < (task->pa_base + task->command_size))
> +			curr_task = task;
> +		if (task->cb.cb) {
> +			cmdq_cb_data.err = curr_task ? err : false;
> +			cmdq_cb_data.data = task->cb.data;
> +			task->cb.cb(cmdq_cb_data);
> +		}
> +		task->task_state = (curr_task && err) ? TASK_STATE_ERROR :
> +				TASK_STATE_DONE;
> +		list_del(&task->list_entry);
> +		if (curr_task)
> +			break;
> +	}
> +
> +	wake_up(&thread->wait_task_done);
> +}
> +
> +static void cmdq_thread_irq_handler(struct cmdq *cmdq, int tid)
> +{
> +	struct cmdq_thread *thread = &cmdq->thread[tid];
> +	unsigned long flags = 0L;
> +	u32 irq_flag;
> +
> +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> +
> +	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> +	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
> +
> +	/*
> +	 * Another CPU core could run "release task" right before we acquire
> +	 * the spin lock, and thus reset / disable this GCE thread, so we
> +	 * need to check the enable bit of this GCE thread.
> +	 */
> +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> +	      CMDQ_THR_ENABLED))
> +		irq_flag = 0;

These three statement (clear irq flag and detect thread enable) can be
moved into cmdq_handle_error_done() and the duplicated part in
cmdq_task_handle_error_result() can be removed. Even though
cmdq_task_handle_error_result() need not check thread enable, it would
not influence the flow.

> +
> +	cmdq_handle_error_done(cmdq, thread, irq_flag);
> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +}
> +
> +static irqreturn_t cmdq_irq_handler(int irq, void *dev)
> +{
> +	struct cmdq *cmdq = dev;
> +	u32 irq_status;
> +	int i;
> +
> +	irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS);
> +	irq_status &= CMDQ_IRQ_MASK;
> +	irq_status ^= CMDQ_IRQ_MASK;
> +
> +	if (!irq_status)
> +		return IRQ_NONE;
> +
> +	while (irq_status) {
> +		i = ffs(irq_status) - 1;
> +		irq_status &= ~BIT(i);
> +		cmdq_thread_irq_handler(cmdq, i);
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int cmdq_task_handle_error_result(struct cmdq_task *task)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +	struct device *dev = cmdq->dev;
> +	struct cmdq_thread *thread = task->thread;
> +	struct cmdq_task *next_task, *prev_task;
> +	u32 irq_flag;
> +
> +	/* suspend GCE thread to ensure consistency */
> +	WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
> +
> +	/* ISR has handled this error task */
> +	if (task->task_state == TASK_STATE_ERROR) {
> +		next_task = list_first_entry_or_null(&thread->task_busy_list,
> +				struct cmdq_task, list_entry);
> +		if (next_task) /* move to next task */
> +			cmdq_thread_writel(thread, next_task->pa_base,
> +					   CMDQ_THR_CURR_ADDR);
> +		cmdq_thread_resume(thread);
> +		return -ECANCELED;
> +	}
> +
> +	/*
> +	 * Save next_task and prev_task in advance
> +	 * since cmdq_handle_error_done will remove list_entry.
> +	 */
> +	next_task = prev_task = NULL;
> +	if (task->list_entry.next != &thread->task_busy_list)
> +		next_task = list_next_entry(task, list_entry);
> +	if (task->list_entry.prev != &thread->task_busy_list)
> +		prev_task = list_prev_entry(task, list_entry);

I think there is always no previous task because task order in
thread->task_busy_list is the same as in cmdq->task_release_wq. So each
task processed by release work should be the first item in
thread->task_busy_list or be removed from thread->task_busy_list.

> +
> +	/*
> +	 * Although IRQ is disabled, GCE continues to execute.
> +	 * It may have pending IRQ before GCE thread is suspended,
> +	 * so check this condition again.
> +	 */
> +	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> +	cmdq_handle_error_done(cmdq, thread, irq_flag);
> +	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
> +
> +	if (task->task_state == TASK_STATE_DONE) {
> +		cmdq_thread_resume(thread);
> +		return 0;
> +	}
> +
> +	if (task->task_state == TASK_STATE_ERROR) {
> +		dev_err(dev, "task 0x%p error\n", task);
> +		if (next_task) /* move to next task */
> +			cmdq_thread_writel(thread, next_task->pa_base,
> +					   CMDQ_THR_CURR_ADDR);
> +		cmdq_thread_resume(thread);
> +		return -ECANCELED;
> +	}
> +
> +	/* Task is running, so we force to remove it. */
> +	dev_err(dev, "task 0x%p timeout or killed\n", task);

No 'kill' state.

> +	task->task_state = TASK_STATE_ERROR;
> +
> +	if (prev_task) {
> +		u64 *prev_va = prev_task->va_base;
> +		u64 *curr_va = task->va_base;
> +
> +		/* copy JUMP instruction */
> +		prev_va[prev_task->num_cmd - 1] = curr_va[task->num_cmd - 1];
> +
> +		cmdq_thread_invalidate_fetched_data(thread);
> +	} else if (next_task) { /* move to next task */
> +		cmdq_thread_writel(thread, next_task->pa_base,
> +				   CMDQ_THR_CURR_ADDR);
> +	}

Just one statement in 'else if' part. So remove the parentheses.

> +
> +	list_del(&task->list_entry);
> +	cmdq_thread_resume(thread);
> +
> +	/* call cb here to prevent lock */

I think these three statements should be place together and there should
be no this comment.

1. Change task state to DONE or ERROR.
2. Callback
3. Remove task from task_busy_list.

> +	if (task->cb.cb) {
> +		struct cmdq_cb_data cmdq_cb_data;
> +
> +		cmdq_cb_data.err = true;
> +		cmdq_cb_data.data = task->cb.data;
> +		task->cb.cb(cmdq_cb_data);
> +	}
> +
> +	return -ECANCELED;
> +}
> +
> +static void cmdq_task_wait_release_work(struct work_struct *work_item)
> +{
> +	struct cmdq_task *task = container_of(work_item, struct cmdq_task,
> +					      release_work);
> +	struct cmdq *cmdq = task->cmdq;
> +	struct cmdq_thread *thread = task->thread;
> +	unsigned long flags;
> +
> +	wait_event_timeout(thread->wait_task_done,
> +			   task->task_state != TASK_STATE_BUSY,
> +			   msecs_to_jiffies(CMDQ_TIMEOUT_MS));
> +
> +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> +	if (task->task_state != TASK_STATE_DONE)
> +		cmdq_task_handle_error_result(task);
> +	if (list_empty(&thread->task_busy_list))
> +		cmdq_thread_disable(cmdq, thread);
> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +
> +	/* release regardless of success or not */
> +	clk_disable_unprepare(cmdq->clock);
> +	cmdq_task_release(task);
> +}
> +
> +static void cmdq_task_wait_release_schedule(struct cmdq_task *task)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +
> +	INIT_WORK(&task->release_work, cmdq_task_wait_release_work);
> +	queue_work(cmdq->task_release_wq, &task->release_work);
> +}
> +
> +static int cmdq_rec_realloc_cmd_buffer(struct cmdq_rec *rec, size_t size)
> +{
> +	void *new_buf;
> +
> +	new_buf = krealloc(rec->buf, size, GFP_KERNEL | __GFP_ZERO);
> +	if (!new_buf)
> +		return -ENOMEM;
> +	rec->buf = new_buf;
> +	rec->buf_size = size;
> +	return 0;
> +}
> +
> +struct cmdq_base *cmdq_register_device(struct device *dev)
> +{
> +	struct cmdq_base *cmdq_base;
> +	struct resource res;
> +	int subsys;
> +	u32 base;
> +
> +	if (of_address_to_resource(dev->of_node, 0, &res))
> +		return NULL;
> +	base = (u32)res.start;
> +
> +	subsys = cmdq_subsys_base_to_id(base >> 16);
> +	if (subsys < 0)
> +		return NULL;
> +
> +	cmdq_base = devm_kmalloc(dev, sizeof(*cmdq_base), GFP_KERNEL);
> +	if (!cmdq_base)
> +		return NULL;
> +	cmdq_base->subsys = subsys;
> +	cmdq_base->base = base;
> +
> +	return cmdq_base;
> +}
> +EXPORT_SYMBOL(cmdq_register_device);
> +
> +int cmdq_rec_create(struct device *dev, u64 engine_flag,
> +		    struct cmdq_rec **rec_ptr)
> +{
> +	struct cmdq_rec *rec;
> +	int err;
> +
> +	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
> +	if (!rec)
> +		return -ENOMEM;
> +	rec->cmdq = dev_get_drvdata(dev);
> +	rec->engine_flag = engine_flag;
> +	err = cmdq_rec_realloc_cmd_buffer(rec, CMDQ_INITIAL_CMD_BLOCK_SIZE);
> +	if (err < 0) {
> +		kfree(rec);
> +		return err;
> +	}
> +	*rec_ptr = rec;
> +	return 0;
> +}
> +EXPORT_SYMBOL(cmdq_rec_create);
> +
> +static int cmdq_rec_append_command(struct cmdq_rec *rec, enum cmdq_code code,
> +				   u32 arg_a, u32 arg_b)
> +{
> +	u64 *cmd_ptr;
> +	int err;
> +
> +	if (WARN_ON(rec->finalized))
> +		return -EBUSY;
> +	if (code < CMDQ_CODE_MOVE || code > CMDQ_CODE_EOC)
> +		return -EINVAL;
> +	if (unlikely(rec->command_size + CMDQ_INST_SIZE > rec->buf_size)) {
> +		err = cmdq_rec_realloc_cmd_buffer(rec, rec->buf_size * 2);
> +		if (err < 0)
> +			return err;
> +	}
> +	cmd_ptr = rec->buf + rec->command_size;
> +	(*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b;
> +	rec->command_size += CMDQ_INST_SIZE;
> +	return 0;
> +}
> +
> +int cmdq_rec_write(struct cmdq_rec *rec, u32 value, struct cmdq_base *base,
> +		   u32 offset)
> +{
> +	u32 arg_a = ((base->base + offset) & CMDQ_ARG_A_WRITE_MASK) |
> +		    ((base->subsys & CMDQ_SUBSYS_MASK) << CMDQ_SUBSYS_SHIFT);
> +	return cmdq_rec_append_command(rec, CMDQ_CODE_WRITE, arg_a, value);
> +}
> +EXPORT_SYMBOL(cmdq_rec_write);
> +
> +int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
> +			struct cmdq_base *base, u32 offset, u32 mask)
> +{
> +	u32 offset_mask = offset;
> +	int err;
> +
> +	if (mask != 0xffffffff) {
> +		err = cmdq_rec_append_command(rec, CMDQ_CODE_MOVE, 0, ~mask);
> +		if (err < 0)
> +			return err;
> +		offset_mask |= CMDQ_WRITE_ENABLE_MASK;
> +	}
> +	return cmdq_rec_write(rec, value, base, offset_mask);
> +}
> +EXPORT_SYMBOL(cmdq_rec_write_mask);
> +
> +int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event)
> +{
> +	u32 arg_b;
> +
> +	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
> +		return -EINVAL;
> +
> +	/*
> +	 * bit 0-11: wait value
> +	 * bit 15: 1 - wait, 0 - no wait
> +	 * bit 16-27: update value
> +	 * bit 31: 1 - update, 0 - no update
> +	 */
> +	arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
> +	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event, arg_b);
> +}
> +EXPORT_SYMBOL(cmdq_rec_wfe);
> +
> +int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event)
> +{
> +	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
> +		return -EINVAL;
> +
> +	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event,
> +				       CMDQ_WFE_UPDATE);
> +}
> +EXPORT_SYMBOL(cmdq_rec_clear_event);
> +
> +static int cmdq_rec_finalize(struct cmdq_rec *rec)
> +{
> +	int err;
> +
> +	if (rec->finalized)
> +		return 0;
> +
> +	/* insert EOC and generate IRQ for each command iteration */
> +	err = cmdq_rec_append_command(rec, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN);
> +	if (err < 0)
> +		return err;
> +
> +	/* JUMP to end */
> +	err = cmdq_rec_append_command(rec, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS);
> +	if (err < 0)
> +		return err;
> +
> +	rec->finalized = true;
> +	return 0;
> +}
> +
> +int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
> +			 void *data)
> +{
> +	struct cmdq *cmdq = rec->cmdq;
> +	struct cmdq_task *task;
> +	struct cmdq_task_cb task_cb;
> +	struct cmdq_thread *thread;
> +	int err;
> +
> +	mutex_lock(&cmdq->task_mutex);
> +	if (cmdq->suspended) {
> +		dev_err(cmdq->dev, "%s is called after suspended\n", __func__);
> +		mutex_unlock(&cmdq->task_mutex);
> +		return -EPERM;
> +	}
> +
> +	err = cmdq_rec_finalize(rec);
> +	if (err < 0) {
> +		mutex_unlock(&cmdq->task_mutex);
> +		return err;
> +	}
> +
> +	task_cb.cb = cb;
> +	task_cb.data = data;
> +	task = cmdq_task_acquire(rec, task_cb);
> +	if (!task) {
> +		mutex_unlock(&cmdq->task_mutex);
> +		return -EFAULT;
> +	}
> +
> +	thread = &cmdq->thread[cmdq_eng_get_thread(task->engine_flag)];
> +	cmdq_task_exec(task, thread);
> +	cmdq_task_wait_release_schedule(task);
> +	mutex_unlock(&cmdq->task_mutex);
> +	return 0;
> +}
> +EXPORT_SYMBOL(cmdq_rec_flush_async);
> +
> +struct cmdq_flush_completion {
> +	struct completion cmplt;
> +	bool err;
> +};
> +
> +static int cmdq_rec_flush_cb(struct cmdq_cb_data data)
> +{
> +	struct cmdq_flush_completion *cmplt = data.data;
> +
> +	cmplt->err = data.err;
> +	complete(&cmplt->cmplt);
> +	return 0;
> +}
> +
> +int cmdq_rec_flush(struct cmdq_rec *rec)
> +{
> +	struct cmdq_flush_completion cmplt;
> +	int err;
> +
> +	init_completion(&cmplt.cmplt);
> +	err = cmdq_rec_flush_async(rec, cmdq_rec_flush_cb, &cmplt);
> +	if (err < 0)
> +		return err;
> +	wait_for_completion(&cmplt.cmplt);
> +	return cmplt.err ? -EFAULT : 0;
> +}
> +EXPORT_SYMBOL(cmdq_rec_flush);
> +
> +void cmdq_rec_destroy(struct cmdq_rec *rec)
> +{
> +	kfree(rec->buf);
> +	kfree(rec);
> +}
> +EXPORT_SYMBOL(cmdq_rec_destroy);
> +
> +static bool cmdq_task_is_empty(struct cmdq *cmdq)
> +{
> +	struct cmdq_thread *thread;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
> +		thread = &cmdq->thread[i];
> +		if (!list_empty(&thread->task_busy_list))
> +			return false;
> +	}
> +	return true;
> +}
> +
> +static int cmdq_suspend(struct device *dev)
> +{
> +	struct cmdq *cmdq = dev_get_drvdata(dev);
> +	u32 exec_threads;
> +
> +	mutex_lock(&cmdq->task_mutex);
> +	cmdq->suspended = true;
> +	mutex_unlock(&cmdq->task_mutex);
> +
> +	exec_threads = readl(cmdq->base + CMDQ_CURR_LOADED_THR);
> +	if ((exec_threads & CMDQ_THR_EXECUTING) && !cmdq_task_is_empty(cmdq)) {
> +		dev_err(dev, "wait active tasks timeout.\n");
> +		flush_workqueue(cmdq->task_release_wq);
> +	}

Maybe it need not to check exec_threads, it may be written as:

	if (!cmdq_task_is_empty(cmdq))
		dev_err(dev, "wait active tasks timeout.\n");

	flush_workqueue(cmdq->task_release_wq);

Even though task_busy_list is empty, that does not mean every task in
cmdq->task_release_wq is finished. So always do flush
cmdq->task_release_wq.

> +	return 0;
> +}
> +
> +static int cmdq_resume(struct device *dev)
> +{
> +	struct cmdq *cmdq = dev_get_drvdata(dev);
> +
> +	cmdq->suspended = false;
> +	return 0;
> +}
> +
> +static int cmdq_remove(struct platform_device *pdev)
> +{
> +	struct cmdq *cmdq = platform_get_drvdata(pdev);
> +
> +	destroy_workqueue(cmdq->task_release_wq);
> +	cmdq->task_release_wq = NULL;
> +	return 0;
> +}
> +
> +static int cmdq_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *node = dev->of_node;
> +	struct resource *res;
> +	struct cmdq *cmdq;
> +	int err, i;
> +
> +	cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
> +	if (!cmdq)
> +		return -ENOMEM;
> +	cmdq->dev = dev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	cmdq->base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(cmdq->base)) {
> +		dev_err(dev, "failed to ioremap gce\n");
> +		return PTR_ERR(cmdq->base);
> +	}
> +
> +	cmdq->irq = irq_of_parse_and_map(node, 0);
> +	if (!cmdq->irq) {
> +		dev_err(dev, "failed to get irq\n");
> +		return -EINVAL;
> +	}
> +
> +	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
> +		dev, cmdq->base, cmdq->irq);
> +
> +	mutex_init(&cmdq->task_mutex);
> +	spin_lock_init(&cmdq->exec_lock);
> +	cmdq->task_release_wq = alloc_ordered_workqueue(
> +			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI,
> +			"cmdq_task_wait_release");
> +
> +	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
> +		cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
> +				CMDQ_THR_SHIFT * i;
> +		init_waitqueue_head(&cmdq->thread[i].wait_task_done);
> +		INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list);
> +	}
> +
> +	platform_set_drvdata(pdev, cmdq);
> +
> +	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
> +			       CMDQ_DRIVER_DEVICE_NAME, cmdq);
> +	if (err < 0) {
> +		dev_err(dev, "failed to register ISR (%d)\n", err);
> +		goto fail;
> +	}
> +
> +	cmdq->clock = devm_clk_get(dev, CMDQ_CLK_NAME);
> +	if (IS_ERR(cmdq->clock)) {
> +		dev_err(dev, "failed to get clk:%s\n", CMDQ_CLK_NAME);
> +		err = PTR_ERR(cmdq->clock);
> +		goto fail;
> +	}
> +	return 0;
> +
> +fail:
> +	cmdq_remove(pdev);
> +	return err;
> +}
> +
> +static const struct dev_pm_ops cmdq_pm_ops = {
> +	.suspend = cmdq_suspend,
> +	.resume = cmdq_resume,
> +};
> +
> +static const struct of_device_id cmdq_of_ids[] = {
> +	{.compatible = "mediatek,mt8173-gce",},
> +	{}
> +};
> +
> +static struct platform_driver cmdq_drv = {
> +	.probe = cmdq_probe,
> +	.remove = cmdq_remove,
> +	.driver = {
> +		.name = CMDQ_DRIVER_DEVICE_NAME,
> +		.owner = THIS_MODULE,
> +		.pm = &cmdq_pm_ops,
> +		.of_match_table = cmdq_of_ids,
> +	}
> +};
> +
> +builtin_platform_driver(cmdq_drv);
> diff --git a/include/soc/mediatek/cmdq.h b/include/soc/mediatek/cmdq.h
> new file mode 100644
> index 0000000..60eef3d
> --- /dev/null
> +++ b/include/soc/mediatek/cmdq.h
> @@ -0,0 +1,197 @@
> +/*
> + * Copyright (c) 2015 MediaTek Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MTK_CMDQ_H__
> +#define __MTK_CMDQ_H__
> +
> +#include <linux/platform_device.h>
> +#include <linux/types.h>
> +
> +enum cmdq_eng {
> +	CMDQ_ENG_DISP_AAL,
> +	CMDQ_ENG_DISP_COLOR0,
> +	CMDQ_ENG_DISP_COLOR1,
> +	CMDQ_ENG_DISP_DPI0,
> +	CMDQ_ENG_DISP_DSI0,
> +	CMDQ_ENG_DISP_DSI1,
> +	CMDQ_ENG_DISP_GAMMA,
> +	CMDQ_ENG_DISP_OD,
> +	CMDQ_ENG_DISP_OVL0,
> +	CMDQ_ENG_DISP_OVL1,
> +	CMDQ_ENG_DISP_PWM0,
> +	CMDQ_ENG_DISP_PWM1,
> +	CMDQ_ENG_DISP_RDMA0,
> +	CMDQ_ENG_DISP_RDMA1,
> +	CMDQ_ENG_DISP_RDMA2,
> +	CMDQ_ENG_DISP_UFOE,
> +	CMDQ_ENG_DISP_WDMA0,
> +	CMDQ_ENG_DISP_WDMA1,
> +	CMDQ_ENG_MAX,
> +};
> +
> +/* events for CMDQ and display */
> +enum cmdq_event {
> +	/* Display start of frame(SOF) events */
> +	CMDQ_EVENT_DISP_OVL0_SOF = 11,
> +	CMDQ_EVENT_DISP_OVL1_SOF = 12,
> +	CMDQ_EVENT_DISP_RDMA0_SOF = 13,
> +	CMDQ_EVENT_DISP_RDMA1_SOF = 14,
> +	CMDQ_EVENT_DISP_RDMA2_SOF = 15,
> +	CMDQ_EVENT_DISP_WDMA0_SOF = 16,
> +	CMDQ_EVENT_DISP_WDMA1_SOF = 17,
> +	/* Display end of frame(EOF) events */
> +	CMDQ_EVENT_DISP_OVL0_EOF = 39,
> +	CMDQ_EVENT_DISP_OVL1_EOF = 40,
> +	CMDQ_EVENT_DISP_RDMA0_EOF = 41,
> +	CMDQ_EVENT_DISP_RDMA1_EOF = 42,
> +	CMDQ_EVENT_DISP_RDMA2_EOF = 43,
> +	CMDQ_EVENT_DISP_WDMA0_EOF = 44,
> +	CMDQ_EVENT_DISP_WDMA1_EOF = 45,
> +	/* Mutex end of frame(EOF) events */
> +	CMDQ_EVENT_MUTEX0_STREAM_EOF = 53,
> +	CMDQ_EVENT_MUTEX1_STREAM_EOF = 54,
> +	CMDQ_EVENT_MUTEX2_STREAM_EOF = 55,
> +	CMDQ_EVENT_MUTEX3_STREAM_EOF = 56,
> +	CMDQ_EVENT_MUTEX4_STREAM_EOF = 57,
> +	/* Display underrun events */
> +	CMDQ_EVENT_DISP_RDMA0_UNDERRUN = 63,
> +	CMDQ_EVENT_DISP_RDMA1_UNDERRUN = 64,
> +	CMDQ_EVENT_DISP_RDMA2_UNDERRUN = 65,
> +	/* Keep this at the end of HW events */
> +	CMDQ_MAX_HW_EVENT_COUNT = 260,
> +};
> +
> +struct cmdq_cb_data {
> +	bool	err;
> +	void	*data;
> +};
> +
> +typedef int (*cmdq_async_flush_cb)(struct cmdq_cb_data data);
> +
> +struct cmdq_task;
> +struct cmdq;
> +
> +struct cmdq_rec {
> +	struct cmdq		*cmdq;
> +	u64			engine_flag;
> +	size_t			command_size;
> +	void			*buf;
> +	size_t			buf_size;
> +	bool			finalized;
> +};
> +
> +struct cmdq_base {
> +	int	subsys;
> +	u32	base;
> +};
> +
> +/**
> + * cmdq_register_device() - register device which needs CMDQ
> + * @dev:		device
> + *
> + * Return: cmdq_base pointer or NULL for failed
> + */
> +struct cmdq_base *cmdq_register_device(struct device *dev);
> +
> +/**
> + * cmdq_rec_create() - create command queue record
> + * @dev:		device
> + * @engine_flag:	command queue engine flag
> + * @rec_ptr:		command queue record pointer to retrieve cmdq_rec
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_create(struct device *dev, u64 engine_flag,
> +		    struct cmdq_rec **rec_ptr);
> +
> +/**
> + * cmdq_rec_write() - append write command to the command queue record
> + * @rec:	the command queue record
> + * @value:	the specified target register value
> + * @base:	the command queue base
> + * @offset:	register offset from module base
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_write(struct cmdq_rec *rec, u32 value,
> +		   struct cmdq_base *base, u32 offset);
> +
> +/**
> + * cmdq_rec_write_mask() - append write command with mask to the command
> + *			   queue record
> + * @rec:	the command queue record
> + * @value:	the specified target register value
> + * @base:	the command queue base
> + * @offset:	register offset from module base
> + * @mask:	the specified target register mask
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
> +			struct cmdq_base *base, u32 offset, u32 mask);
> +
> +/**
> + * cmdq_rec_wfe() - append wait for event command to the command queue record
> + * @rec:	the command queue record
> + * @event:	the desired event type to "wait and CLEAR"
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event);
> +
> +/**
> + * cmdq_rec_clear_event() - append clear event command to the command queue
> + *			    record
> + * @rec:	the command queue record
> + * @event:	the desired event to be cleared
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event);
> +
> +/**
> + * cmdq_rec_flush() - trigger CMDQ to execute the recorded commands
> + * @rec:	the command queue record
> + *
> + * Return: 0 for success; else the error code is returned
> + *
> + * Trigger CMDQ to execute the recorded commands. Note that this is a
> + * synchronous flush function. When the function returned, the recorded
> + * commands have been done.
> + */
> +int cmdq_rec_flush(struct cmdq_rec *rec);
> +
> +/**
> + * cmdq_rec_flush_async() - trigger CMDQ to asynchronously execute the recorded
> + *			    commands and call back after ISR is finished
> + * @rec:	the command queue record
> + * @cb:		called in the end of CMDQ ISR
> + * @data:	this data will pass back to cb
> + *
> + * Return: 0 for success; else the error code is returned
> + *
> + * Trigger CMDQ to asynchronously execute the recorded commands and call back
> + * after ISR is finished. Note that this is an ASYNC function. When the function
> + * returned, it may or may not be finished. The ISR callback function is called
> + * in the end of ISR.
> + */
> +int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
> +			 void *data);
> +
> +/**
> + * cmdq_rec_destroy() - destroy command queue record
> + * @rec:	the command queue record
> + */
> +void cmdq_rec_destroy(struct cmdq_rec *rec);
> +
> +#endif	/* __MTK_CMDQ_H__ */

Regards,
CK



From pramod.kumar at broadcom.com  Mon May 30 00:10:44 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Mon, 30 May 2016 12:40:44 +0530
Subject: [PATCH 0/7] Add MDIO bus multiplexer support for iProc SoCs
Message-ID: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>

Broadcom iProc based SoCs use a MDIO bus multiplexer where child buses
could be internal as well external to SoCs. These buses could supports
MDIO transaction compatible to C-22/C-45.

Broadcom MDIO bus mulitplexer is an integrated multiplexer where child bus
selection and mdio transaction logic lies inside multiplexer itself.
To accommodate this multiplexer in existing mux framework below changes
were required-

1. Passed MDIO parent bus via mdio_mux_init to MDIO mux framework.

2. Defined one new boolean property named "mdio-integrated-mux". Integrated
   bus Multiplexer node defines this so when parent bus is registered
   by calling "of_mdiobus_register", this api will not scan for child
   nodes. Child node of integrated multiplexer will be muxed nodes not
   PHYs one hence should not be scanned.

This patch set includes MDIO bus multiplexer driver along with above
framework changes. It includes one external bus node having Ethernet PHY
attached and two internal bus node holding PCIe PHYs.

This patch series is based on v4.6.0-rc1 and is available from github-
repo: https://github.com/Broadcom/arm64-linux.git
branch:mdio-mux-v1

Pramod Kumar (7):
  mdio:mux: Enhanced MDIO mux framework for integrated multiplexers
  DT: phy.txt: Add mdio-integrated-mux property
  binding: mdio-mux: Add DT binding doc for Broadcom MDIO bus mutiplexer
  DT:mdio-mux: Add mdio multiplexer driver node
  net:mdio-mux: Add MDIO mux driver for iProc SoCs
  Binding:PHY: Binding doc for NS2 PCIe PHYs.
  phy: Add Northstar2 PCI Phy support

 .../bindings/net/brcm,mdio-mux-iproc.txt           |  64 +++++
 Documentation/devicetree/bindings/net/mdio-mux.txt |   9 +-
 .../bindings/phy/brcm,mdio-mux-bus-pci.txt         |  27 +++
 arch/arm64/boot/dts/broadcom/ns2-svk.dts           |  12 +
 arch/arm64/boot/dts/broadcom/ns2.dtsi              |  32 +++
 drivers/net/phy/Kconfig                            |  11 +
 drivers/net/phy/Makefile                           |   1 +
 drivers/net/phy/mdio-mux-bcm-iproc.c               | 263 +++++++++++++++++++++
 drivers/net/phy/mdio-mux-gpio.c                    |   2 +-
 drivers/net/phy/mdio-mux-mmioreg.c                 |   2 +-
 drivers/net/phy/mdio-mux.c                         |  28 ++-
 drivers/of/of_mdio.c                               |   3 +
 drivers/phy/Kconfig                                |   8 +
 drivers/phy/Makefile                               |   1 +
 drivers/phy/phy-bcm-ns2-pcie.c                     | 115 +++++++++
 include/linux/mdio-mux.h                           |   4 +-
 16 files changed, 568 insertions(+), 14 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
 create mode 100644 Documentation/devicetree/bindings/phy/brcm,mdio-mux-bus-pci.txt
 create mode 100644 drivers/net/phy/mdio-mux-bcm-iproc.c
 create mode 100644 drivers/phy/phy-bcm-ns2-pcie.c

-- 
1.9.1



From pramod.kumar at broadcom.com  Mon May 30 00:10:45 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Mon, 30 May 2016 12:40:45 +0530
Subject: [PATCH 1/7] mdio:mux: Enhanced MDIO mux framework for integrated
 multiplexers
In-Reply-To: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464592251-2688-2-git-send-email-pramod.kumar@broadcom.com>

An integrated multiplexer uses same address space for
"muxed bus selection" and "generation of mdio transaction"
hence its good to register parent bus from mux driver.

Hence added a mechanism where mux driver could register a
parent bus and pass it down to framework via mdio_mux_init api.

Below changes are required to make this happen-

1. When mdio-mux parent bus is registered, mdio framework should not
parse for child as it will be muxed bus node not PHYs.

-created a new property "mdio-mux-bus-parent". if this property is present,
of_mdiobus_register will not scan for phys.

2. Passed down parent bus to mdio mux framework via mdio-mux-init api.

Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 drivers/net/phy/mdio-mux-gpio.c    |  2 +-
 drivers/net/phy/mdio-mux-mmioreg.c |  2 +-
 drivers/net/phy/mdio-mux.c         | 28 ++++++++++++++++++----------
 drivers/of/of_mdio.c               |  3 +++
 include/linux/mdio-mux.h           |  4 +++-
 5 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c
index 7ddb1ab..9199499 100644
--- a/drivers/net/phy/mdio-mux-gpio.c
+++ b/drivers/net/phy/mdio-mux-gpio.c
@@ -55,7 +55,7 @@ static int mdio_mux_gpio_probe(struct platform_device *pdev)
 		return PTR_ERR(s->gpios);
 
 	r = mdio_mux_init(&pdev->dev,
-			  mdio_mux_gpio_switch_fn, &s->mux_handle, s);
+			  mdio_mux_gpio_switch_fn, &s->mux_handle, s, NULL);
 
 	if (r != 0) {
 		gpiod_put_array(s->gpios);
diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c
index 7fde454..d0bed52 100644
--- a/drivers/net/phy/mdio-mux-mmioreg.c
+++ b/drivers/net/phy/mdio-mux-mmioreg.c
@@ -126,7 +126,7 @@ static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
 	}
 
 	ret = mdio_mux_init(&pdev->dev, mdio_mux_mmioreg_switch_fn,
-			    &s->mux_handle, s);
+			    &s->mux_handle, s, NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register mdio-mux bus %s\n",
 			np->full_name);
diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c
index 308ade0..521ab90 100644
--- a/drivers/net/phy/mdio-mux.c
+++ b/drivers/net/phy/mdio-mux.c
@@ -95,7 +95,8 @@ static int parent_count;
 int mdio_mux_init(struct device *dev,
 		  int (*switch_fn)(int cur, int desired, void *data),
 		  void **mux_handle,
-		  void *data)
+		  void *data,
+		  struct mii_bus *mux_bus)
 {
 	struct device_node *parent_bus_node;
 	struct device_node *child_bus_node;
@@ -107,10 +108,21 @@ int mdio_mux_init(struct device *dev,
 	if (!dev->of_node)
 		return -ENODEV;
 
-	parent_bus_node = of_parse_phandle(dev->of_node, "mdio-parent-bus", 0);
+	if (!mux_bus) {
+		parent_bus_node = of_parse_phandle(dev->of_node,
+						   "mdio-parent-bus", 0);
 
-	if (!parent_bus_node)
-		return -ENODEV;
+		if (!parent_bus_node)
+			return -ENODEV;
+
+		parent_bus = of_mdio_find_bus(parent_bus_node);
+		if (!parent_bus) {
+			ret_val = -EPROBE_DEFER;
+			goto err_parent_bus;
+		}
+	} else {
+		parent_bus = mux_bus;
+	}
 
 	pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL);
 	if (pb == NULL) {
@@ -118,11 +130,6 @@ int mdio_mux_init(struct device *dev,
 		goto err_parent_bus;
 	}
 
-	parent_bus = of_mdio_find_bus(parent_bus_node);
-	if (parent_bus == NULL) {
-		ret_val = -EPROBE_DEFER;
-		goto err_parent_bus;
-	}
 
 	pb->switch_data = data;
 	pb->switch_fn = switch_fn;
@@ -183,7 +190,8 @@ int mdio_mux_init(struct device *dev,
 	put_device(&pb->mii_bus->dev);
 
 err_parent_bus:
-	of_node_put(parent_bus_node);
+	if (!mux_bus)
+		of_node_put(parent_bus_node);
 	return ret_val;
 }
 EXPORT_SYMBOL_GPL(mdio_mux_init);
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 8453f08..cf40e7a 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -225,6 +225,9 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 	if (rc)
 		return rc;
 
+	if (of_property_read_bool(np, "mdio-integrated-mux"))
+		return 0;
+
 	/* Loop over the child nodes and register a phy_device for each phy */
 	for_each_available_child_of_node(np, child) {
 		addr = of_mdio_parse_addr(&mdio->dev, child);
diff --git a/include/linux/mdio-mux.h b/include/linux/mdio-mux.h
index a243dbb..61f5b21 100644
--- a/include/linux/mdio-mux.h
+++ b/include/linux/mdio-mux.h
@@ -10,11 +10,13 @@
 #ifndef __LINUX_MDIO_MUX_H
 #define __LINUX_MDIO_MUX_H
 #include <linux/device.h>
+#include <linux/phy.h>
 
 int mdio_mux_init(struct device *dev,
 		  int (*switch_fn) (int cur, int desired, void *data),
 		  void **mux_handle,
-		  void *data);
+		  void *data,
+		  struct mii_bus *mux_bus);
 
 void mdio_mux_uninit(void *mux_handle);
 
-- 
1.9.1



From pramod.kumar at broadcom.com  Mon May 30 00:10:46 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Mon, 30 May 2016 12:40:46 +0530
Subject: [PATCH 2/7] DT: phy.txt: Add mdio-integrated-mux property
In-Reply-To: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464592251-2688-3-git-send-email-pramod.kumar@broadcom.com>

This property is used by integrated MDIO multiplexer
which has bus selection and mdio transaction generation logic,
integrated inside.

Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 Documentation/devicetree/bindings/net/mdio-mux.txt | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/mdio-mux.txt b/Documentation/devicetree/bindings/net/mdio-mux.txt
index 491f5bd..b5ad83e 100644
--- a/Documentation/devicetree/bindings/net/mdio-mux.txt
+++ b/Documentation/devicetree/bindings/net/mdio-mux.txt
@@ -5,13 +5,20 @@ numbered uniquely in a device dependent manner.  The nodes for an MDIO
 bus multiplexer/switch will have one child node for each child bus.
 
 Required properties:
-- mdio-parent-bus : phandle to the parent MDIO bus.
 - #address-cells = <1>;
 - #size-cells = <0>;
 
 Optional properties:
+- mdio-parent-bus : phandle to the parent MDIO bus. Should be used
+		if parent mdio bus is not part of multiplexer.
+- mdio-integrated-mux: boolean property indicateing that the hardware
+		is an integrated multiplex supporting muxed bus selection
+		and MDIO transaction logic generation.
 - Other properties specific to the multiplexer/switch hardware.
 
+Note: one of mdio-parent-bus and mdio-integrated-mux is mandatory to
+get parent bus regsitered.
+
 Required properties for child nodes:
 - #address-cells = <1>;
 - #size-cells = <0>;
-- 
1.9.1



From pramod.kumar at broadcom.com  Mon May 30 00:10:47 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Mon, 30 May 2016 12:40:47 +0530
Subject: [PATCH 3/7] binding: mdio-mux: Add DT binding doc for Broadcom MDIO
 bus mutiplexer
In-Reply-To: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464592251-2688-4-git-send-email-pramod.kumar@broadcom.com>

Add DT binding doc for Broadcom MDIO bus mutiplexer driver.

Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 .../bindings/net/brcm,mdio-mux-iproc.txt           | 64 ++++++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt

diff --git a/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
new file mode 100644
index 0000000..dd74ee0
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
@@ -0,0 +1,64 @@
+Properties for an MDIO bus mutiplexer found in Broadcom iProc based SoCs.
+
+This MDIO bus multiplexer defines buses that could be internal as well as
+external to SoCs and could accept MDIO transaction compatible to C-22 or
+C-45 Clause. When Child bus is selected, one need to select these two
+properties as well to generate desired MDIO trascation on appropriate bus.
+
+Required properties in addition to the generic multiplexer properties:
+
+MDIO multiplexer node:
+- complatible: brcm,mdio-mux-iproc.
+
+Child bus node:
+-brcm,is-c45: Boolean property indicating PHYs attached to this bus supports
+	      C-45 mdio transaction.
+
+Every non-ethernet PHY requires a compatible so that it could be probed based
+on this compatible string.
+
+Additional information regarding generic multiplexer properties could be found
+at- Documentation/devicetree/bindings/net/mdio-mux.txt
+
+
+for example:
+		mdio_mux_iproc: mdio_mux_iproc at 6602023c {
+			compatible = "brcm,mdio-mux-iproc";
+			reg = <0x6602023c 0x14>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			mdio-integrated-mux;
+
+			mdio at 0 {
+				reg = <0x0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pci_phy0: pci-phy at 0 {
+					compatible = "brcm,ns2-pcie-phy";
+					reg = <0x0>;
+					#phy-cells = <0>;
+				};
+			};
+
+			mdio at 7 {
+				reg = <0x7>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pci_phy1: pci-phy at 0 {
+					compatible = "brcm,ns2-pcie-phy";
+					reg = <0x0>;
+					#phy-cells = <0>;
+				};
+			};
+			mdio at 10 {
+				reg = <0x10>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				gphy0: eth-phy at 10 {
+					reg = <0x10>;
+				};
+			};
+		};
-- 
1.9.1



From pramod.kumar at broadcom.com  Mon May 30 00:10:48 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Mon, 30 May 2016 12:40:48 +0530
Subject: [PATCH 4/7] DT:mdio-mux: Add mdio multiplexer driver node
In-Reply-To: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464592251-2688-5-git-send-email-pramod.kumar@broadcom.com>

Add integrated MDIO multiplexer driver node which contains
two mux PCIe bus and one ethernet bus along with phys
lying on these bus.

Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 arch/arm64/boot/dts/broadcom/ns2-svk.dts | 12 ++++++++++++
 arch/arm64/boot/dts/broadcom/ns2.dtsi    | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
index ce0ab84..8f6a6cc 100644
--- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts
+++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
@@ -87,3 +87,15 @@
 		#size-cells = <1>;
 	};
 };
+
+&mdio_mux_iproc {
+	mdio at 10 {
+		reg = <0x10>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gphy0: eth-phy at 10 {
+			reg = <0x10>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi
index 6f81c9d..efc320a 100644
--- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
+++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
@@ -330,6 +330,38 @@
 			      <0x65260000 0x1000>;
 		};
 
+		mdio_mux_iproc: mdio_mux_iproc at 6602023c {
+			compatible = "brcm,mdio-mux-iproc";
+			reg = <0x6602023c 0x14>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			mdio-integrated-mux;
+
+			mdio at 0 {
+				reg = <0x0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pci_phy0: pci-phy at 0 {
+					compatible = "brcm,ns2-pcie-phy";
+					reg = <0x0>;
+					#phy-cells = <0>;
+				};
+			};
+
+			mdio at 7 {
+				reg = <0x7>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pci_phy1: pci-phy at 0 {
+					compatible = "brcm,ns2-pcie-phy";
+					reg = <0x0>;
+					#phy-cells = <0>;
+				};
+			};
+		};
+
 		timer0: timer at 66030000 {
 			compatible = "arm,sp804", "arm,primecell";
 			reg = <0x66030000 0x1000>;
-- 
1.9.1



From pramod.kumar at broadcom.com  Mon May 30 00:10:49 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Mon, 30 May 2016 12:40:49 +0530
Subject: [PATCH 5/7] net:mdio-mux: Add MDIO mux driver for iProc SoCs
In-Reply-To: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464592251-2688-6-git-send-email-pramod.kumar@broadcom.com>

iProc based SoCs supports the integrated mdio multiplexer which
has the bus selection as well as mdio transaction generation logic
inside.

This mutiplexer has child buses for PCIe, SATA, USB and ETH. These
buses could be internal or external to SOC where PHYs are attached.
These buses could use C-45 or C-22 mdio transaction.

Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 drivers/net/phy/Kconfig              |  11 ++
 drivers/net/phy/Makefile             |   1 +
 drivers/net/phy/mdio-mux-bcm-iproc.c | 263 +++++++++++++++++++++++++++++++++++
 3 files changed, 275 insertions(+)
 create mode 100644 drivers/net/phy/mdio-mux-bcm-iproc.c

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 6dad9a9..38faecf 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -254,6 +254,17 @@ config MDIO_BUS_MUX_MMIOREG
 
 	  Currently, only 8-bit registers are supported.
 
+config MDIO_BUS_MUX_BCM_IPROC
+	tristate "Support for iProc based MDIO bus multiplexers"
+	depends on OF && OF_MDIO && (ARCH_BCM_IPROC || COMPILE_TEST)
+	select MDIO_BUS_MUX
+	default ARCH_BCM_IPROC
+	help
+	  This module provides a driver for MDIO bus multiplexers found in
+	  iProc based Broadcom SoCs. This mulitplexer connects one of several
+	  child MDIO bus to a parent bus. Buses could be interal as well as
+	  external and selection logic lies inside the same multiplexer.
+
 config MDIO_BCM_UNIMAC
 	tristate "Broadcom UniMAC MDIO bus controller"
 	depends on HAS_IOMEM
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index fcdbb92..f5951d5a 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_AMD_PHY)		+= amd.o
 obj-$(CONFIG_MDIO_BUS_MUX)	+= mdio-mux.o
 obj-$(CONFIG_MDIO_BUS_MUX_GPIO)	+= mdio-mux-gpio.o
 obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o
+obj-$(CONFIG_MDIO_BUS_MUX_BCM_IPROC)	+= mdio-mux-bcm-iproc.o
 obj-$(CONFIG_MDIO_SUN4I)	+= mdio-sun4i.o
 obj-$(CONFIG_MDIO_MOXART)	+= mdio-moxart.o
 obj-$(CONFIG_MDIO_BCM_UNIMAC)	+= mdio-bcm-unimac.o
diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c
new file mode 100644
index 0000000..40c32ee
--- /dev/null
+++ b/drivers/net/phy/mdio-mux-bcm-iproc.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2016 Broadcom
+ *
+ * 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 (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/of_mdio.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/mdio-mux.h>
+#include <linux/delay.h>
+
+#define MDIO_PARAM_OFFSET		0x00
+#define MDIO_PARAM_MIIM_CYCLE		29
+#define MDIO_PARAM_INTERNAL_SEL		25
+#define MDIO_PARAM_BUS_ID		22
+#define MDIO_PARAM_C45_SEL		21
+#define MDIO_PARAM_PHY_ID		16
+#define MDIO_PARAM_PHY_DATA		0
+
+#define MDIO_READ_OFFSET		0x04
+#define MDIO_READ_DATA_MASK		0xffff
+#define MDIO_ADDR_OFFSET		0x08
+
+#define MDIO_CTRL_OFFSET		0x0C
+#define MDIO_CTRL_WRITE_OP		0x1
+#define MDIO_CTRL_READ_OP		0x2
+
+#define MDIO_STAT_OFFSET		0x10
+#define MDIO_STAT_DONE			1
+
+#define BUS_MAX_ADDR			32
+#define EXT_BUS_START_ADDR		16
+
+struct mdiomux_bus_param {
+	bool is_c45;
+};
+
+struct iproc_mdiomux_desc {
+	void *mux_handle;
+	void __iomem *base;
+	struct device *dev;
+	struct mii_bus *mii_bus;
+	struct mdiomux_bus_param bus_param[BUS_MAX_ADDR];
+};
+
+static int iproc_mdio_wait_for_idle(void __iomem *base, bool result)
+{
+	u32 val;
+	unsigned int timeout = 1000; /* loop for 1s */
+
+	do {
+		val = readl(base + MDIO_STAT_OFFSET);
+		if ((val & MDIO_STAT_DONE) == result)
+			return 0;
+
+		usleep_range(1000, 2000);
+	} while (timeout--);
+
+	return -ETIMEDOUT;
+}
+
+/* start_miim_ops- Program and start MDIO transaction over mdio bus.
+ * @base: Base address
+ * @phyid: phyid of the selected bus.
+ * @reg: register offset to be read/written.
+ * @val :0 if read op else value to be written in @reg;
+ * @op: Operation that need to be carried out.
+ *      MDIO_CTRL_READ_OP: Read transaction.
+ *      MDIO_CTRL_WRITE_OP: Write transaction.
+ *
+ * Return value: Successful Read operation returns read reg values and write
+ *      operation returns 0. Failure operation returns negative error code.
+ */
+static int start_miim_ops(void __iomem *base,
+			  u16 phyid, u32 reg, u16 val, u32 op)
+{
+	int ret;
+	u32 param;
+
+	writel(0, base + MDIO_CTRL_OFFSET);
+	ret = iproc_mdio_wait_for_idle(base, 0);
+	if (ret)
+		goto err;
+
+	param = readl(base + MDIO_PARAM_OFFSET);
+	param |= phyid << MDIO_PARAM_PHY_ID;
+	param |= val << MDIO_PARAM_PHY_DATA;
+
+	writel(param, base + MDIO_PARAM_OFFSET);
+
+	writel(reg, base + MDIO_ADDR_OFFSET);
+
+	writel(op, base + MDIO_CTRL_OFFSET);
+
+	ret = iproc_mdio_wait_for_idle(base, 1);
+	if (ret)
+		goto err;
+
+	if (op == MDIO_CTRL_READ_OP)
+		ret = readl(base + MDIO_READ_OFFSET) & MDIO_READ_DATA_MASK;
+err:
+	return ret;
+}
+
+static int iproc_mdiomux_read(struct mii_bus *bus, int phyid, int reg)
+{
+	int ret;
+	struct iproc_mdiomux_desc *md = bus->priv;
+
+	ret = start_miim_ops(md->base, phyid, reg, 0, MDIO_CTRL_READ_OP);
+	if (ret < 0)
+		dev_err(&bus->dev, "mdiomux read operation failed!!!");
+
+	return ret;
+}
+
+static int iproc_mdiomux_write(struct mii_bus *bus,
+			       int phyid, int reg, u16 val)
+{
+	int ret;
+	struct iproc_mdiomux_desc *md = bus->priv;
+
+	/* Write val at reg offset */
+	ret = start_miim_ops(md->base, phyid, reg, val, MDIO_CTRL_WRITE_OP);
+	if (ret < 0)
+		dev_err(&bus->dev, "mdiomux write operation failed!!!");
+
+	return ret;
+}
+
+static int mdio_mux_iproc_switch_fn(int current_child, int desired_child,
+				    void *data)
+{
+	struct iproc_mdiomux_desc *md = data;
+	struct mdiomux_bus_param *bp = &md->bus_param[desired_child];
+	u32 param, bus_id;
+	bool bus_dir;
+
+	/* select bus and its properties */
+	bus_dir = (desired_child < EXT_BUS_START_ADDR);
+	bus_id = bus_dir ? desired_child : (desired_child - EXT_BUS_START_ADDR);
+
+	param = (bus_dir ? 1 : 0) << MDIO_PARAM_INTERNAL_SEL;
+	param |= (bp->is_c45 ? 1 : 0) << MDIO_PARAM_C45_SEL;
+	param |= (bus_id << MDIO_PARAM_BUS_ID);
+
+	writel(param, md->base + MDIO_PARAM_OFFSET);
+	return 0;
+}
+
+static int mdio_mux_iproc_probe(struct platform_device *pdev)
+{
+	struct iproc_mdiomux_desc *md;
+	struct mii_bus *bus;
+	struct resource *res;
+	struct mdiomux_bus_param *bp;
+	struct device_node *child;
+	int rc;
+	u32 busid;
+
+	md = devm_kzalloc(&pdev->dev, sizeof(*md), GFP_KERNEL);
+	if (!md)
+		return -ENOMEM;
+	md->dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	md->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(md->base)) {
+		dev_err(&pdev->dev, "failed to ioremap register\n");
+		return PTR_ERR(md->base);
+	}
+
+	md->mii_bus = mdiobus_alloc();
+	if (!md->mii_bus) {
+		dev_err(&pdev->dev, "mdiomux bus alloc failed\n");
+		return -ENOMEM;
+	}
+
+	bus = md->mii_bus;
+	bus->priv = md;
+	bus->name = "iProc MDIO mux bus";
+	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", pdev->name, pdev->id);
+	bus->parent = &pdev->dev;
+	bus->read = iproc_mdiomux_read;
+	bus->write = iproc_mdiomux_write;
+
+	rc = of_mdiobus_register(bus, pdev->dev.of_node);
+	if (rc) {
+		dev_err(&pdev->dev, "mdiomux registration failed\n");
+		goto out;
+	}
+
+	platform_set_drvdata(pdev, md);
+
+	for_each_available_child_of_node(md->dev->of_node, child) {
+		rc = of_property_read_u32(child, "reg", &busid);
+		if (rc)
+			continue;
+
+		if (busid >= BUS_MAX_ADDR) {
+			dev_err(md->dev, "invalid mdiomux busid :%d\n", busid);
+			goto out;
+		}
+
+		bp = &md->bus_param[busid];
+		bp->is_c45 = of_property_read_bool(child, "brcm,is-c45");
+	}
+
+	rc = mdio_mux_init(md->dev, mdio_mux_iproc_switch_fn,
+			   &md->mux_handle, md, md->mii_bus);
+	if (!rc) {
+		dev_info(md->dev, "mdiomux registered\n");
+		goto out;
+	}
+
+out:
+	mdiobus_free(bus);
+	return rc;
+}
+
+static int mdio_mux_iproc_remove(struct platform_device *pdev)
+{
+	struct iproc_mdiomux_desc *md = dev_get_platdata(&pdev->dev);
+
+	mdio_mux_uninit(md->mux_handle);
+	return 0;
+}
+
+static const struct of_device_id mdio_mux_iproc_match[] = {
+	{
+		.compatible = "brcm,mdio-mux-iproc",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mdio_mux_iproc_match);
+
+static struct platform_driver mdiomux_iproc_driver = {
+	.driver = {
+		.name		= "mdio-mux-iproc",
+		.of_match_table = mdio_mux_iproc_match,
+	},
+	.probe		= mdio_mux_iproc_probe,
+	.remove		= mdio_mux_iproc_remove,
+};
+
+module_platform_driver(mdiomux_iproc_driver);
+
+MODULE_DESCRIPTION("iProc MDIO Mux Bus Driver");
+MODULE_AUTHOR("Pramod Kumar <pramod.kumar at broadcom.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1



From pramod.kumar at broadcom.com  Mon May 30 00:10:50 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Mon, 30 May 2016 12:40:50 +0530
Subject: [PATCH 6/7] Binding:PHY: Binding doc for NS2 PCIe PHYs.
In-Reply-To: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464592251-2688-7-git-send-email-pramod.kumar@broadcom.com>

Binding doc for NS2 PCIe PHYs.

Signed-off-by: Jon Mason <jonmason at broadcom.com>
Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 .../bindings/phy/brcm,mdio-mux-bus-pci.txt         | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/brcm,mdio-mux-bus-pci.txt

diff --git a/Documentation/devicetree/bindings/phy/brcm,mdio-mux-bus-pci.txt b/Documentation/devicetree/bindings/phy/brcm,mdio-mux-bus-pci.txt
new file mode 100644
index 0000000..5b51007
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/brcm,mdio-mux-bus-pci.txt
@@ -0,0 +1,27 @@
+* Broadcom NS2 PCIe PHY binding document
+
+Required bus properties:
+- reg: MDIO Bus number for the MDIO interface
+- #address-cells: must be 1
+- #size-cells: must be 0
+
+Required PHY properties:
+- compatible: should be "brcm,ns2-pcie-phy"
+- reg: MDIO Phy ID for the MDIO interface
+- #phy-cells: must be 0
+
+This is a child bus node of "brcm,mdio-mux-iproc" node.
+
+Example:
+
+mdio at 0 {
+	reg = <0x0>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	pci_phy0: pci-phy at 0 {
+		compatible = "brcm,ns2-pcie-phy";
+		reg = <0x0>;
+		#phy-cells = <0>;
+	};
+};
-- 
1.9.1



From pramod.kumar at broadcom.com  Mon May 30 00:10:51 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Mon, 30 May 2016 12:40:51 +0530
Subject: [PATCH 7/7] phy: Add Northstar2 PCI Phy support
In-Reply-To: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464592251-2688-8-git-send-email-pramod.kumar@broadcom.com>

Add PCI Phy support for Broadcom Northstar2 SoCs.  This driver uses the
interface from the iproc mdio mux driver to enable the devices
respective phys.

Signed-off-by: Jon Mason <jonmason at broadcom.com>
Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 drivers/phy/Kconfig            |   8 +++
 drivers/phy/Makefile           |   1 +
 drivers/phy/phy-bcm-ns2-pcie.c | 115 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 124 insertions(+)
 create mode 100644 drivers/phy/phy-bcm-ns2-pcie.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 26566db..5ff60b2 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -421,4 +421,12 @@ config PHY_CYGNUS_PCIE
 	  Enable this to support the Broadcom Cygnus PCIe PHY.
 	  If unsure, say N.
 
+config PHY_NS2_PCIE
+	tristate "Broadcom Northstar2 PCIe PHY driver"
+	depends on OF && MDIO_BUS_MUX_BCM_IPROC
+	select GENERIC_PHY
+	default ARCH_BCM_IPROC
+	help
+	  Enable this to support the Broadcom Northstar2 PCIe PHY.
+	  If unsure, say N.
 endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 24596a9..77d51ff 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -52,3 +52,4 @@ obj-$(CONFIG_PHY_TUSB1210)		+= phy-tusb1210.o
 obj-$(CONFIG_PHY_BRCMSTB_SATA)		+= phy-brcmstb-sata.o
 obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
 obj-$(CONFIG_PHY_CYGNUS_PCIE)		+= phy-bcm-cygnus-pcie.o
+obj-$(CONFIG_PHY_NS2_PCIE)		+= phy-bcm-ns2-pcie.o
diff --git a/drivers/phy/phy-bcm-ns2-pcie.c b/drivers/phy/phy-bcm-ns2-pcie.c
new file mode 100644
index 0000000..65c3870
--- /dev/null
+++ b/drivers/phy/phy-bcm-ns2-pcie.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of_mdio.h>
+#include <linux/mdio.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+
+struct ns2_pci_phy {
+	struct mdio_device *mdiodev;
+	struct phy *phy;
+};
+
+#define BLK_ADDR_REG_OFFSET	0x1f
+#define PLL_AFE1_100MHZ_BLK	0x2100
+#define PLL_CLK_AMP_OFFSET	0x03
+#define PLL_CLK_AMP_2P05V	0x2b18
+
+static int ns2_pci_phy_init(struct phy *p)
+{
+	struct ns2_pci_phy *phy = phy_get_drvdata(p);
+	int rc;
+
+	/* select the AFE 100MHz block page */
+	rc = mdiobus_write(phy->mdiodev->bus, phy->mdiodev->addr,
+			   BLK_ADDR_REG_OFFSET, PLL_AFE1_100MHZ_BLK);
+	if (rc)
+		goto err;
+
+	/* set the 100 MHz reference clock amplitude to 2.05 v */
+	rc = mdiobus_write(phy->mdiodev->bus, phy->mdiodev->addr,
+			   PLL_CLK_AMP_OFFSET, PLL_CLK_AMP_2P05V);
+	if (rc)
+		goto err;
+
+	return 0;
+
+err:
+	dev_err(&phy->mdiodev->dev, "Error %d writing to phy\n", rc);
+	return rc;
+}
+
+static struct phy_ops ns2_pci_phy_ops = {
+	.init = ns2_pci_phy_init,
+};
+
+static int ns2_pci_phy_probe(struct mdio_device *mdiodev)
+{
+	struct device *dev = &mdiodev->dev;
+	struct phy_provider *provider;
+	struct ns2_pci_phy *p;
+	struct phy *phy;
+
+	phy = devm_phy_create(dev, dev->of_node, &ns2_pci_phy_ops);
+	if (IS_ERR_OR_NULL(phy)) {
+		dev_err(dev, "failed to create Phy\n");
+		return PTR_ERR(phy);
+	}
+
+	p = devm_kmalloc(dev, sizeof(struct ns2_pci_phy),
+			 GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	p->mdiodev = mdiodev;
+	dev_set_drvdata(dev, p);
+
+	p->phy = phy;
+	phy_set_drvdata(phy, p);
+
+	provider = devm_of_phy_provider_register(&phy->dev,
+						 of_phy_simple_xlate);
+	if (IS_ERR(provider)) {
+		dev_err(dev, "failed to register Phy provider\n");
+		return PTR_ERR(provider);
+	}
+
+	dev_info(dev, "%s PHY registered\n", dev_name(dev));
+
+	return 0;
+}
+
+static const struct of_device_id ns2_pci_phy_of_match[] = {
+	{ .compatible = "brcm,ns2-pcie-phy", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ns2_pci_phy_of_match);
+
+static struct mdio_driver ns2_pci_phy_driver = {
+	.mdiodrv = {
+		.driver = {
+			.name = "phy-bcm-ns2-pci",
+			.of_match_table = ns2_pci_phy_of_match,
+		},
+	},
+	.probe = ns2_pci_phy_probe,
+};
+mdio_module_driver(ns2_pci_phy_driver);
+
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Broadcom Northstar2 PCI Phy driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:phy-bcm-ns2-pci");
-- 
1.9.1



From gabriel.fernandez at linaro.org  Mon May 30 00:30:06 2016
From: gabriel.fernandez at linaro.org (Gabriel Fernandez)
Date: Mon, 30 May 2016 09:30:06 +0200
Subject: [STLinux Kernel] [PATCH 02/11] drivers: clk: st: Add clock
 propagation for audio clocks
In-Reply-To: <20160527154159.GA17818@rob-hp-laptop>
References: <1463560892-7209-1-git-send-email-gabriel.fernandez@linaro.org>
 <1463560892-7209-3-git-send-email-gabriel.fernandez@linaro.org>
 <20160525172409.GA27913@rob-hp-laptop>
 <CAG374jDTCJfZB+PuAnggjXhbcd3NjJqrESpe_EnMniCAeoph9A@mail.gmail.com>
 <CAL_JsqLOG4P0H+HkQ3mJhfibatuV2T51KqOn-+U+LK8WUx7QgA@mail.gmail.com>
 <5746F486.602@st.com>
 <CAL_JsqLeD8uTmMYLFZ5Sh9=JV5s1xthvruXL-W=c=zcVS=G-ZA@mail.gmail.com>
 <5747F5E8.5030300@st.com> <20160527154159.GA17818@rob-hp-laptop>
Message-ID: <CAG374jBTLDiXHQVuxKMA2-xZr1yHUBLmSdT2HAZhp16dTsQDoQ@mail.gmail.com>

On 27 May 2016 at 17:41, Rob Herring <robh at kernel.org> wrote:
> On Fri, May 27, 2016 at 09:23:20AM +0200, loic pallardy wrote:
>>
>>
>> On 05/26/2016 03:20 PM, Rob Herring wrote:
>> >On Thu, May 26, 2016 at 8:05 AM, loic pallardy <loic.pallardy at st.com> wrote:
>> >>
>> >>
>> >>On 05/26/2016 02:46 PM, Rob Herring wrote:
>> >>>
>> >>>On Thu, May 26, 2016 at 4:49 AM, Gabriel Fernandez
>> >>><gabriel.fernandez at linaro.org> wrote:
>> >>>>
>> >>>>On 25 May 2016 at 19:24, Rob Herring <robh at kernel.org> wrote:
>> >>>>>
>> >>>>>
>> >>>>>On Wed, May 18, 2016 at 10:41:23AM +0200, Gabriel Fernandez wrote:
>> >>>>>>
>> >>>>>>This patch allows fine tuning of the quads FS for audio clocks
>> >>>>>>accuracy.
>> >>>>>>
>
>> >>>
>> >>>That is no different and suffers the same point I raised. It requires
>> >>>updating the DT for any clock configuration change or enhancement.
>> >>>
>> >>Agree with you, DT update is needed as soon as a clock configuration should
>> >>be changed. This is due to STiH clock driver design based on DT description
>> >>of SoC clock tree.
>> >>
>> >>This clock driver was accepted 2 years ago. At the time being there was
>> >>discussion about clock tree description location: driver or DT.
>> >>Bad choice was done for this driver...
>> >>
>> >>If we decide to redesign STiH clock driver using in-driver clock tree
>> >>description, this will modify STiH clock DT nodes description and so break
>> >>DT backward compatibility.
>> >>
>> >>What's from your pov the best option?
>> >
>> >You can break it once or every time you need a clock change. I'd go
>> >with the former. Maybe more specific compatible strings throughout
>> >alone would be enough rather than a flag day changing the binding.
>>
>> So if I understand you correctly, main issue is d0 and d2 signification.
>> d0 and d2 are indeed location of the flexgen in the SoC. But that's right
>> flexgen are dedicated to clocks generation for features (system, audio,
>> video).
>> What about "st,flexgen-audio" and "st,flexgen-video"?
>
> It is not so much the name of these 2, but whether there are other cases
> for different clock nodes that could need the same thing. If so, update
> them all now rather than 1 by 1.
>
> Rob

Hi Rob,
Ok i will send a V2 for that.

Mike,
the first patch "drivers: clk: st: Add fs660c32 synthesizer algorithm"  can
be taken into account regardless the remark of Rob. Can you have a look ?

Thanks.
Best Regards

Gabriel


From zhengxing at rock-chips.com  Mon May 30 00:32:45 2016
From: zhengxing at rock-chips.com (Xing Zheng)
Date: Mon, 30 May 2016 15:32:45 +0800
Subject: [PATCH v3] ASoC: rockchip: Add machine driver for
 MAX98357A/RT5514/DA7219
In-Reply-To: <1464267742-15312-1-git-send-email-zhengxing@rock-chips.com>
References: <1464267742-15312-1-git-send-email-zhengxing@rock-chips.com>
Message-ID: <574BEC9D.50007@rock-chips.com>

Hi,
Could any guys help me to review this patch?

Thanks.

On 2016?05?26? 21:02, Xing Zheng wrote:
> There are multi codec devices on the RK3399 platform, we can use
> this patch support and control these codecs.
>
> Signed-off-by: Xing Zheng<zhengxing at rock-chips.com>
> ---
>
> Changes in v3:
> - rename DOC to rockchip,rk3399-max98357a-rt5514-da7219.txt
> - rename compatible to rockchip,rk3399-max98357a-rt5514-da7219
> - rename source code to rk3399_max98357a_rt5514_da7219.c
>
> Changes in v2:
> - use the FS 256 to set mclks of the max98357a and rt5514 danamically
> - add more sample rate for da7219
>
>   .../rockchip,rk3399-max98357a-rt5514-da7219.txt    |   15 +
>   sound/soc/rockchip/Kconfig                         |   11 +
>   sound/soc/rockchip/Makefile                        |    2 +
>   .../soc/rockchip/rk3399_max98357a_rt5514_da7219.c  |  333 ++++++++++++++++++++
>   4 files changed, 361 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3399-max98357a-rt5514-da7219.txt
>   create mode 100644 sound/soc/rockchip/rk3399_max98357a_rt5514_da7219.c
>
> diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3399-max98357a-rt5514-da7219.txt b/Documentation/devicetree/bindings/sound/rockchip,rk3399-max98357a-rt5514-da7219.txt
> new file mode 100644
> index 0000000..3ae603e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/rockchip,rk3399-max98357a-rt5514-da7219.txt
> @@ -0,0 +1,15 @@
> +ROCKCHIP with MAX98357A/RT5514/DA7219 codecs
> +
> +Required properties:
> +- compatible: "rockchip,rk3399-max98357a-rt5514-da7219"
> +- rockchip,cpu: The phandle of the Rockchip I2S controller that's
> +  connected to the codecs
> +- rockchip,codec: The phandle of the MAX98357A/RT5514/DA7219 codecs
> +
> +Example:
> +
> +sound {
> +	compatible = "rockchip,rk3399-max98357a-rt5514-da7219";
> +	rockchip,cpu =<&i2s0&i2s0&i2s1>;
> +	rockchip,codec =<&max98357a&headsetcodec&codec>;
> +};
> diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
> index f1e0c70..e5bd1f9 100644
> --- a/sound/soc/rockchip/Kconfig
> +++ b/sound/soc/rockchip/Kconfig
> @@ -41,3 +41,14 @@ config SND_SOC_ROCKCHIP_RT5645
>   	help
>   	  Say Y or M here if you want to add support for SoC audio on Rockchip
>   	  boards using the RT5645/RT5650 codec, such as Veyron.
> +
> +config SND_SOC_RK3399_MAX98357A_RT5514_DA7219
> +	tristate "ASoC support for Rockchip RK3399 boards using the MAX98357A/RT5514/DA7219"
> +	depends on SND_SOC_ROCKCHIP&&  GPIOLIB
> +	select SND_SOC_ROCKCHIP_I2S
> +	select SND_SOC_MAX98357A
> +	select SND_SOC_RT5514
> +	select SND_SOC_DA7219
> +	help
> +	  Say Y or M here if you want to add support for SoC audio on Rockchip RK3399
> +	  boards using the MAX98357A/RT5514/DA7219.
> diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
> index c0bf560..0d9ca0a 100644
> --- a/sound/soc/rockchip/Makefile
> +++ b/sound/soc/rockchip/Makefile
> @@ -7,6 +7,8 @@ obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o
>
>   snd-soc-rockchip-max98090-objs := rockchip_max98090.o
>   snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o
> +snd-soc-rk3399-max98357a-rt5514-da7219-objs := rk3399_max98357a_rt5514_da7219.o
>
>   obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o
>   obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o
> +obj-$(CONFIG_SND_SOC_RK3399_MAX98357A_RT5514_DA7219) += snd-soc-rk3399-max98357a-rt5514-da7219.o
> diff --git a/sound/soc/rockchip/rk3399_max98357a_rt5514_da7219.c b/sound/soc/rockchip/rk3399_max98357a_rt5514_da7219.c
> new file mode 100644
> index 0000000..ec88600
> --- /dev/null
> +++ b/sound/soc/rockchip/rk3399_max98357a_rt5514_da7219.c
> @@ -0,0 +1,333 @@
> +/*
> + * Rockchip machine ASoC driver for boards using MAX98357A/RT5514/DA7219
> + *
> + * Copyright (c) 2016, ROCKCHIP CORPORATION.  All rights reserved.
> + *
> + * 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<linux/slab.h>
> +#include<linux/gpio.h>
> +#include<linux/of_gpio.h>
> +#include<linux/delay.h>
> +#include<linux/spi/spi.h>
> +#include<sound/core.h>
> +#include<sound/jack.h>
> +#include<sound/pcm.h>
> +#include<sound/pcm_params.h>
> +#include<sound/soc.h>
> +#include "rockchip_i2s.h"
> +#include "../codecs/da7219.h"
> +#include "../codecs/da7219-aad.h"
> +#include "../codecs/rt5514.h"
> +
> +#define DRV_NAME "rk3399-max98357a-rt5514-da7219"
> +
> +#define SOUND_FS	256
> +
> +static struct snd_soc_jack rockchip_sound_jack;
> +
> +static const struct snd_soc_dapm_widget rockchip_dapm_widgets[] = {
> +	SND_SOC_DAPM_HP("Headphones", NULL),
> +	SND_SOC_DAPM_SPK("Speakers", NULL),
> +	SND_SOC_DAPM_MIC("Headset Mic", NULL),
> +	SND_SOC_DAPM_MIC("Int Mic", NULL),
> +};
> +
> +static const struct snd_soc_dapm_route rockchip_dapm_routes[] = {
> +	/* Input Lines */
> +	{"MIC", NULL, "Headset Mic"},
> +	{"DMIC1L", NULL, "Int Mic"},
> +	{"DMIC1R", NULL, "Int Mic"},
> +
> +	/* Output Lines */
> +	{"Headphones", NULL, "HPL"},
> +	{"Headphones", NULL, "HPR"},
> +	{"Speakers", NULL, "Speakers"},
> +};
> +
> +static const struct snd_kcontrol_new rockchip_controls[] = {
> +	SOC_DAPM_PIN_SWITCH("Headphones"),
> +	SOC_DAPM_PIN_SWITCH("Speakers"),
> +	SOC_DAPM_PIN_SWITCH("Headset Mic"),
> +	SOC_DAPM_PIN_SWITCH("Int Mic"),
> +};
> +
> +static int rockchip_sound_max98357a_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_dapm_context *dapm =&rtd->card->dapm;
> +	unsigned int mclk;
> +	int ret;
> +
> +	/* max98357a supports these sample rates */
> +	switch (params_rate(params)) {
> +	case 8000:
> +	case 16000:
> +	case 48000:
> +	case 96000:
> +		mclk = params_rate(params) * SOUND_FS;
> +		break;
> +	default:
> +		dev_err(rtd->card->dev, "%s() doesn't support this sample rate: %d\n",
> +				__func__, params_rate(params));
> +		return -EINVAL;
> +	}
> +
> +	ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, 0);
> +	if (ret) {
> +		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
> +				__func__, mclk, ret);
> +		return ret;
> +	}
> +
> +	snd_soc_dapm_disable_pin(dapm, "Headphones");
> +	snd_soc_dapm_enable_pin(dapm, "Speakers");
> +	snd_soc_dapm_sync(dapm);
> +
> +	return 0;
> +}
> +
> +static int rockchip_sound_rt5514_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;
> +	struct snd_soc_dai *codec_dai = rtd->codec_dai;
> +	unsigned int mclk;
> +	int ret;
> +
> +	mclk = params_rate(params) * SOUND_FS;
> +
> +	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
> +				     SND_SOC_CLOCK_OUT);
> +	if (ret<  0) {
> +		dev_err(rtd->card->dev, "Can't set cpu clock out %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = snd_soc_dai_set_sysclk(codec_dai, RT5514_SCLK_S_MCLK,
> +				     mclk, SND_SOC_CLOCK_IN);
> +	if (ret) {
> +		dev_err(rtd->card->dev, "%s() error setting sysclk to %u: %d\n",
> +				__func__, params_rate(params) * 512, ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rockchip_sound_da7219_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;
> +	struct snd_soc_dai *codec_dai = rtd->codec_dai;
> +	struct snd_soc_dapm_context *dapm =&rtd->card->dapm;
> +	int mclk, ret;
> +
> +	/* in bypass mode, the mclk has to be one of the frequencies below */
> +	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(codec_dai->dev, "Can't set cpu clock out %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
> +				     SND_SOC_CLOCK_IN);
> +	if (ret<  0) {
> +		dev_err(codec_dai->dev, "Can't set codec clock in %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0);
> +	if (ret<  0) {
> +		dev_err(codec_dai->dev, "Can't set pll sysclk mclk %d\n", ret);
> +		return ret;
> +	}
> +
> +	snd_soc_dapm_disable_pin(dapm, "Speakers");
> +	snd_soc_dapm_enable_pin(dapm, "Headphones");
> +	snd_soc_dapm_sync(dapm);
> +
> +	return 0;
> +}
> +
> +static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
> +{
> +	struct snd_soc_codec *codec = rtd->codec_dais[0]->codec;
> +	int ret;
> +
> +	/* Enable Headset and 4 Buttons Jack detection */
> +	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
> +				    SND_JACK_HEADSET |
> +				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
> +				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
> +				&rockchip_sound_jack, NULL, 0);
> +
> +	if (ret) {
> +		dev_err(rtd->card->dev, "New Headset Jack failed! (%d)\n", ret);
> +		return ret;
> +	}
> +
> +	da7219_aad_jack_det(codec,&rockchip_sound_jack);
> +
> +	return 0;
> +}
> +
> +static struct snd_soc_ops rockchip_sound_max98357a_ops = {
> +	.hw_params = rockchip_sound_max98357a_hw_params,
> +};
> +
> +static struct snd_soc_ops rockchip_sound_rt5514_ops = {
> +	.hw_params = rockchip_sound_rt5514_hw_params,
> +};
> +
> +static struct snd_soc_ops rockchip_sound_da7219_ops = {
> +	.hw_params = rockchip_sound_da7219_hw_params,
> +};
> +
> +enum {
> +	DAILINK_MAX98357A,
> +	DAILINK_RT5514,
> +	DAILINK_DA7219,
> +};
> +
> +static struct snd_soc_dai_link rockchip_dailinks[] = {
> +	[DAILINK_MAX98357A] = {
> +		.name = "MAX98357A",
> +		.stream_name = "MAX98357A PCM",
> +		.codec_dai_name = "HiFi",
> +		.ops =&rockchip_sound_max98357a_ops,
> +		/* set max98357a as slave */
> +		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
> +			SND_SOC_DAIFMT_CBS_CFS,
> +	},
> +	[DAILINK_RT5514] = {
> +		.name = "RT5514",
> +		.stream_name = "RT5514 PCM",
> +		.codec_dai_name = "rt5514-aif1",
> +		.ops =&rockchip_sound_rt5514_ops,
> +		/* set rt5514 as slave */
> +		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
> +			SND_SOC_DAIFMT_CBS_CFS,
> +	},
> +	[DAILINK_DA7219] = {
> +		.name = "DA7219",
> +		.stream_name = "DA7219 PCM",
> +		.codec_dai_name = "da7219-hifi",
> +		.init = rockchip_sound_da7219_init,
> +		.ops =&rockchip_sound_da7219_ops,
> +		/* set da7219 as slave */
> +		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
> +			SND_SOC_DAIFMT_CBS_CFS,
> +	},
> +};
> +
> +static struct snd_soc_card rockchip_sound_card = {
> +	.name = "rk3399-max98357a-rt5514-da7219",
> +	.owner = THIS_MODULE,
> +	.dai_link = rockchip_dailinks,
> +	.num_links =  ARRAY_SIZE(rockchip_dailinks),
> +	.dapm_widgets = rockchip_dapm_widgets,
> +	.num_dapm_widgets = ARRAY_SIZE(rockchip_dapm_widgets),
> +	.dapm_routes = rockchip_dapm_routes,
> +	.num_dapm_routes = ARRAY_SIZE(rockchip_dapm_routes),
> +	.controls = rockchip_controls,
> +	.num_controls = ARRAY_SIZE(rockchip_controls),
> +};
> +
> +static int rockchip_sound_probe(struct platform_device *pdev)
> +{
> +	struct snd_soc_card *card =&rockchip_sound_card;
> +	struct device_node *cpu_node;
> +	int i, ret;
> +
> +	for (i = 0; i<  card->num_links; i++) {
> +		cpu_node = of_parse_phandle(pdev->dev.of_node,
> +					 "rockchip,cpu", i);
> +		if (!cpu_node) {
> +			dev_err(&pdev->dev, "Property[%d] 'rockchip,cpu' missing or invalid\n", i);
> +			return -EINVAL;
> +		}
> +
> +		rockchip_dailinks[i].platform_of_node = cpu_node;
> +		rockchip_dailinks[i].cpu_of_node = cpu_node;
> +
> +		rockchip_dailinks[i].codec_of_node =
> +			of_parse_phandle(pdev->dev.of_node, "rockchip,codec", i);
> +		if (!rockchip_dailinks[i].codec_of_node) {
> +			dev_err(&pdev->dev,
> +				"Property[%d] 'rockchip,codec' missing or invalid\n", i);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	card->dev =&pdev->dev;
> +	platform_set_drvdata(pdev, card);
> +
> +	ret = devm_snd_soc_register_card(&pdev->dev, card);
> +	if (ret)
> +		dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
> +			__func__, ret);
> +
> +	return ret;
> +}
> +
> +static const struct of_device_id rockchip_sound_of_match[] = {
> +	{ .compatible = "rockchip,rk3399-max98357a-rt5514-da7219", },
> +	{},
> +};
> +
> +static struct platform_driver rockchip_sound_driver = {
> +	.probe = rockchip_sound_probe,
> +	.driver = {
> +		.name = DRV_NAME,
> +		.of_match_table = rockchip_sound_of_match,
> +#ifdef CONFIG_PM
> +		.pm =&snd_soc_pm_ops,
> +#endif
> +	},
> +};
> +
> +module_platform_driver(rockchip_sound_driver);
> +
> +MODULE_AUTHOR("Xing Zheng<zhengxing at rock-chips.com>");
> +MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:" DRV_NAME);
> +MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);


-- 
- Xing Zheng





From matthias.bgg at gmail.com  Mon May 30 00:34:00 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 30 May 2016 09:34:00 +0200
Subject: [PATCH v1 5/6] dtb: xgene: Remove clock nodes
In-Reply-To: <1464333768-26150-6-git-send-email-isubramanian@apm.com>
References: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
 <1464333768-26150-6-git-send-email-isubramanian@apm.com>
Message-ID: <574BECE8.2050307@gmail.com>



On 27/05/16 09:22, Iyappan Subramanian wrote:
> Since the MDIO will be responsible for clock reset, removing the clock
> nodes from shadowcat xge0 and storm sgenet1.
>
> Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
> Tested-by: Fushen Chen <fchen at apm.com>
> Tested-by: Toan Le <toanle at apm.com>
> ---
>   arch/arm64/boot/dts/apm/apm-shadowcat.dtsi | 12 ------------
>   arch/arm64/boot/dts/apm/apm-storm.dtsi     | 18 ++++--------------
>   2 files changed, 4 insertions(+), 26 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
> index 8106957..f27563d 100644
> --- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
> +++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
> @@ -299,17 +299,6 @@
>   				clock-output-names = "pcie1clk";
>   			};
>
> -			xge0clk: xge0clk at 1f61c000 {
> -				compatible = "apm,xgene-device-clock";
> -				#clock-cells = <1>;
> -				clocks = <&socplldiv2 0>;
> -				reg = <0x0 0x1f61c000 0x0 0x1000>;
> -				reg-names = "csr-reg";
> -				enable-mask = <0x3>;
> -				csr-mask = <0x3>;
> -				clock-output-names = "xge0clk";
> -			};
> -

mdio at 0x1f610000 has xge0clk as input (patch 4), so deleting the node 
here will break the device tree. I suppose the mdio consumes the 
menetclk as in apm-storm.dtsi.

Regards,
Matthias

>   			xge1clk: xge1clk at 1f62c000 {
>   				compatible = "apm,xgene-device-clock";
>   				#clock-cells = <1>;
> @@ -643,7 +632,6 @@
>   			interrupts = <0 96 4>,
>   				     <0 97 4>;
>   			dma-coherent;
> -			clocks = <&xge0clk 0>;
>   			local-mac-address = [00 01 73 00 00 01];
>   			phy-connection-type = "sgmii";
>   			phy-handle = <&sgenet0phy>;
> diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi
> index 18f694ea..f631fe4 100644
> --- a/arch/arm64/boot/dts/apm/apm-storm.dtsi
> +++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi
> @@ -237,20 +237,11 @@
>   				clocks = <&socplldiv2 0>;
>   				reg = <0x0 0x1f21c000 0x0 0x1000>;
>   				reg-names = "csr-reg";
> -				csr-mask = <0x3>;
> +				csr-mask = <0xa>;
> +				enable-mask = <0xf>;
>   				clock-output-names = "sge0clk";
>   			};
>
> -			sge1clk: sge1clk at 1f21c000 {
> -				compatible = "apm,xgene-device-clock";
> -				#clock-cells = <1>;
> -				clocks = <&socplldiv2 0>;
> -				reg = <0x0 0x1f21c000 0x0 0x1000>;
> -				reg-names = "csr-reg";
> -				csr-mask = <0xc>;
> -				clock-output-names = "sge1clk";
> -			};
> -
>   			xge0clk: xge0clk at 1f61c000 {
>   				compatible = "apm,xgene-device-clock";
>   				#clock-cells = <1>;
> @@ -938,9 +929,9 @@
>   			reg-names = "enet_csr", "ring_csr", "ring_cmd";
>   			interrupts = <0x0 0x3c 0x4>;
>   			dma-coherent;
> -			clocks = <&menetclk 0>;
>   			/* mac address will be overwritten by the bootloader */
>   			local-mac-address = [00 00 00 00 00 00];
> +			clocks = <&menetclk 0>;
>   			phy-connection-type = "rgmii";
>   			phy-handle = <&menetphy>;
>   		};
> @@ -955,8 +946,8 @@
>   			interrupts = <0x0 0xA0 0x4>,
>   				     <0x0 0xA1 0x4>;
>   			dma-coherent;
> -			clocks = <&sge0clk 0>;
>   			local-mac-address = [00 00 00 00 00 00];
> +			clocks = <&sge0clk 0>;
>   			phy-connection-type = "sgmii";
>   			phy-handle = <&sgenet0phy>;
>   		};
> @@ -972,7 +963,6 @@
>   				     <0x0 0xAD 0x4>;
>   			port-id = <1>;
>   			dma-coherent;
> -			clocks = <&sge1clk 0>;
>   			local-mac-address = [00 00 00 00 00 00];
>   			phy-connection-type = "sgmii";
>   			phy-handle = <&sgenet1phy>;
>


From wangkefeng.wang at huawei.com  Mon May 30 00:33:52 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Mon, 30 May 2016 15:33:52 +0800
Subject: [Question] Crash when cat /dev/kmem in arm/arm64 but not in x86
Message-ID: <574BECE0.9070105@huawei.com>

Hi all,

When cat /dev/kmem in arm/arm64, it will crash, this is caused by "from = 0"
in copy_to_user(void __user *to, const void *from, unsigned long n),
call trace shows below(eg, arm64)

[    9.913370] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    9.914391] pgd = ffff800008345000
[    9.914976] [00000000] *pgd=00000000482bb003, *pud=00000000f69b4003, *pmd=0000000000000000
[    9.918036] Internal error: Oops: 96000006 [#1] PREEMPT SMP
[    9.918683] Modules linked in:
[    9.919413] CPU: 6 PID: 1021 Comm: cat Not tainted 4.6.0+ #80
[    9.920410] Hardware name: linux,dummy-virt (DT)
[    9.921003] task: ffff8000b6448000 ti: ffff8000083b0000 task.ti: ffff8000083b0000
[    9.922356] PC is at __copy_to_user+0x180/0x280
[    9.922847] LR is at read_kmem+0x200/0x220
[    9.923265] pc : [<ffff000008339500>] lr : [<ffff000008473168>] pstate: 20000145
[    9.923988] sp : ffff8000083b3d60
[    9.924670] x29: ffff8000083b3d60 x28: 0000000000001000
[    9.925420] x27: 0000000000001000 x26: ffff8000083b3ec8
[    9.926039] x25: ffff8000083b0000 x24: ffff000008a20638
[    9.926810] x23: 0000000000001000 x22: 0000ffffe4dac550
[    9.927668] x21: 0000000000000000 x20: 0000000000001000
[    9.928771] x19: 0000000000000000 x18: 0000ffffe4dab240
[    9.929494] x17: 0000000000497458 x16: ffff0000081bc098
[    9.930162] x15: ffffffffffffffff x14: ff00000000000000
[    9.930857] x13: ffffffffffffffff x12: 0000000000000038
[    9.931629] x11: 00000000000000c7 x10: 0000000000000006
[    9.932649] x9 : 0000000000000006 x8 : 207a73202c296c6c
[    9.933356] x7 : 756e282020202020 x6 : 0000ffffe4dab550
[    9.934050] x5 : 0000ffffe4dac550 x4 : 0000000000000000
[    9.934801] x3 : 0000000000000000 x2 : 0000000000000f80
[    9.935601] x1 : 0000000000000000 x0 : 0000ffffe4dab550


but in x86, cat /dev/kmem, will just return "Bad address". After check the x86 code,
copy_to_user ->  _copy_to_user(copy_user_64.S, fixup) -> copy_user_handle_tail (will return len > 0),
then the copy_to_user() will return -EFAULT, the fixup_exception will deal with this situation,
so does the arm/arm64 need the same mechanism to deal with it too?

Thanks
Kefeng



From k.kozlowski at samsung.com  Mon May 30 00:41:20 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 30 May 2016 09:41:20 +0200
Subject: [PATCH 2/2] ARM: dts: Add async-bridge clock to MFC power domain
 for Exynos5420
In-Reply-To: <1464111662-15336-3-git-send-email-javier@osg.samsung.com>
References: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
 <1464111662-15336-3-git-send-email-javier@osg.samsung.com>
Message-ID: <574BEEA0.5020103@samsung.com>

On 05/24/2016 07:41 PM, Javier Martinez Canillas wrote:
> The MFC IP is also inter-connected by an Async-Bridge so the CLK_ACLK333
> has to be ungated during a power domain switch. Trying to do it when the
> clock is gated will fail and lead to an imprecise external abort error
> when the driver tries to access the MFC registers with the PD disabled.
> 
> For example, if the s5p-mfc module is removed and the MFC PD turned off:
> 
> [  186.835606] Power domain power-domain at 10044060 disable failed
> [  186.835671] s5p-mfc 11000000.codec: Removing 11000000.codec
> [  186.837670] Power domain power-domain at 10044060 disable failed
> 
> And when the module is inserted again:
> 
> [ 2395.176956] s5p_mfc_wait_for_done_dev:34: Interrupt (dev->int_type:0, command:12) timed out
> [ 2395.177031] s5p_mfc_init_hw:272: Failed to load firmware
> [ 2395.177384] Unhandled fault: imprecise external abort (0x1406) at 0x00000000
> [ 2395.177441] pgd = ec3b4000
> [ 2395.177467] [00000000] *pgd=00000000
> [ 2395.177507] Internal error: : 1406 [#1] PREEMPT SMP ARM
> [ 2395.177550] Modules linked in: s5p_mfc mwifiex_sdio mwifiex uvcvideo s5p_jpeg v4l2_mem2mem videobuf2_vmalloc videobuf2_dma_contig videobuf2_memops videobuf2_v4l2 videobuf2_core v4l2_common videodev media [last unloaded: s5p_mfc]
> [ 2395.177774] CPU: 1 PID: 2382 Comm: v4l_id Tainted: G        W       4.6.0-rc6-next-20160502-00010-g7730dc64d2c1-dirty #179
> [ 2395.177857] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [ 2395.177906] task: ed275500 ti: e6c8c000 task.ti: e6c8c000
> [ 2395.177996] PC is at s5p_mfc_reset+0x1c4/0x284 [s5p_mfc]
> [ 2395.178057] LR is at s5p_mfc_reset+0x1a4/0x284 [s5p_mfc]
> 
> This patch fixes this issue by adding the CLK_ACLK333 as an Async-Bridge
> clock for the MFC power domain, so the PD configuration works properly.
> 
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
> 
> ---
> 
>  arch/arm/boot/dts/exynos5420.dtsi | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)

Thanks, applied.

Krzysztof




From maxime.ripard at free-electrons.com  Mon May 30 00:57:30 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 30 May 2016 09:57:30 +0200
Subject: [PATCH 14/16] clk: sunxi-ng: Add N-K-M-P factor clock
In-Reply-To: <CAGb2v66b7jXrAs0rBrcHWskQQPqrhRVzY6OmCSoGZg2tfDJrDA@mail.gmail.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-15-git-send-email-maxime.ripard@free-electrons.com>
 <CAGb2v66b7jXrAs0rBrcHWskQQPqrhRVzY6OmCSoGZg2tfDJrDA@mail.gmail.com>
Message-ID: <20160530075730.GB4247@lukather>

Hi Chen-Yu,

On Mon, May 23, 2016 at 10:36:04PM +0800, Chen-Yu Tsai wrote:
> On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
> <maxime.ripard at free-electrons.com> wrote:
> > Introduce support for clocks that use a combination of two linear
> > multipliers (N and K factors), one linear divider (M) and one power of two
> > divider (P).
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> > ---
> >  drivers/clk/sunxi-ng/Makefile   |   1 +
> >  drivers/clk/sunxi-ng/ccu_nkmp.c | 157 ++++++++++++++++++++++++++++++++++++++++
> >  drivers/clk/sunxi-ng/ccu_nkmp.h |  43 +++++++++++
> >  3 files changed, 201 insertions(+)
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_nkmp.c
> >  create mode 100644 drivers/clk/sunxi-ng/ccu_nkmp.h
> >
> > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> > index 2bb8bc22e907..c794f57b6fb1 100644
> > --- a/drivers/clk/sunxi-ng/Makefile
> > +++ b/drivers/clk/sunxi-ng/Makefile
> > @@ -9,6 +9,7 @@ obj-y += ccu_mp.o
> >  obj-y += ccu_mux.o
> >  obj-y += ccu_nk.o
> >  obj-y += ccu_nkm.o
> > +obj-y += ccu_nkmp.o
> >  obj-y += ccu_nm.o
> >  obj-y += ccu_p.o
> >  obj-y += ccu_phase.o
> > diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c
> > new file mode 100644
> > index 000000000000..b7da00773cd6
> > --- /dev/null
> > +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c
> > @@ -0,0 +1,157 @@
> > +/*
> > + * Copyright (C) 2016 Maxime Ripard
> > + * Maxime Ripard <maxime.ripard at free-electrons.com>
> > + *
> > + * 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.
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/rational.h>
> > +
> > +#include "ccu_gate.h"
> > +#include "ccu_nkmp.h"
> > +
> > +void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
> > +                       unsigned long max_n, unsigned long max_k,
> > +                       unsigned long max_m, unsigned long max_p,
> > +                       unsigned long *n, unsigned long *k,
> > +                       unsigned long *m, unsigned long *p)
> 
> We definitely should just pass struct ccu_nkmp* here.

Ok

> > +{
> > +       unsigned long best_rate = 0;
> > +       unsigned long best_n = 0, best_k = 0, best_m = 0, best_p = 0;
> > +       unsigned long _n, _k, _m, _p;
> > +
> > +       for (_k = 1; _k <= max_k; _k++) {
> > +               for (_p = 0; _p <= max_p; _p++) {
> > +                       unsigned long tmp_rate;
> > +
> > +                       rational_best_approximation(rate / _k, parent << _p,
> 
> I think you mean "parent >> _p" ?

Indeed :/

> In general we might lose some precision if parent is too small or _p is
> too large. But the only place we see this type of clock is the CPU PLL,
> and parent (24 MHz) are divisible by all the possible values of P.
> 
> This brings up another issue: P does not go all the way up to (1 << width - 1).
> A register value of 3, or P = 8 is not valid, and it's not restricted in
> the driver. This is not true for all the SoCs though.
> 
> The manual also says P should only be used when rate < 288 MHz. Moving
> P to the outer loop, and maybe adding a short circuit exit when the rate
> matches exactly would help.

This is already something that was already reported by
Jean-Francois. Apart from the P limitation this is the current logic
used in the clock driver. We should probably fix that, but without any
user (ie, cpufreq), it's just wild guesses in the middle of a massive
and very intrusive changes.

So I don't really want to actually try to figure that out for now (and
this is exactly why I don't want to convert the SoCs with a good
support for now, since we'll pretty much uncover a whole lot of bugs
that would turn into regressions).

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/4a242ac9/attachment.sig>

From k.kozlowski at samsung.com  Mon May 30 00:58:02 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 30 May 2016 09:58:02 +0200
Subject: [PATCH] ARM: dts: exynos: Remove unneded always-on for regulators
 on Peach boards
In-Reply-To: <1463694753-7259-1-git-send-email-javier@osg.samsung.com>
References: <1463694753-7259-1-git-send-email-javier@osg.samsung.com>
Message-ID: <574BF28A.5000202@samsung.com>

On 05/19/2016 11:52 PM, Javier Martinez Canillas wrote:
> The regulator always-on property should only be used for regulators
> that either can't be disabled or the drivers for the client devices
> are not enabling the regulator and so being disabled due to unused.
> 
> There are some max77802 regulators in the Peach Pit and Pi boards
> that are always-on but shouldn't since they are enabled by drivers:
> 
> BUCK5 is max77802 inl1 supply
> BUCK7 is max77802 inl{2,10} supply
> BUCK9 is max77802 inl{3,4,5,7} supply
> BUCK10 is mmc1 vqmmc supply
> LDO9 is adc vdd supply
> 
> This patch removes the always-on property for these regulators.
> 
> Some regulators should remain always-on even when they are used as
> input supplies, because these regulators are also used by other
> components that are not described in the DT, for example:
> 
> LDO10 is hdmi vdd_osc supply but it's also used as input supply for
> the Exynos5420 temperature sensor.
> 
> LDO8 is hdmi vdd and vdd_pll supply but it's also used as supply for
> the Exynos5420 Display port.
> 
> BUCK2 and BUCK6 are the vdd supplies for the EAGLE and KFC clusters.
> 
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
> ---
> 
>  arch/arm/boot/dts/exynos5420-peach-pit.dts | 5 -----
>  arch/arm/boot/dts/exynos5800-peach-pi.dts  | 5 -----
>  2 files changed, 10 deletions(-)

Thanks, applied.

Best regards,
Krzysztof



From linux at roeck-us.net  Mon May 30 01:07:59 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Mon, 30 May 2016 01:07:59 -0700
Subject: [PATCH v3 1/2] doc/devicetree: Add Aspeed watchdog timer bindings
In-Reply-To: <1463559661-14170-2-git-send-email-joel@jms.id.au>
References: <1463062631-16432-1-git-send-email-joel@jms.id.au>
 <1463559661-14170-1-git-send-email-joel@jms.id.au>
 <1463559661-14170-2-git-send-email-joel@jms.id.au>
Message-ID: <574BF4DF.6000305@roeck-us.net>

On 05/18/2016 01:20 AM, Joel Stanley wrote:
> Signed-off-by: Joel Stanley <joel at jms.id.au>

Reviewed-by: Guenter Roeck <linux at roeck-us.net>

> ---
>   .../devicetree/bindings/watchdog/aspeed-wdt.txt          | 16 ++++++++++++++++
>   1 file changed, 16 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
>
> diff --git a/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> new file mode 100644
> index 000000000000..c5e74d7b4406
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/watchdog/aspeed-wdt.txt
> @@ -0,0 +1,16 @@
> +Aspeed Watchdog Timer
> +
> +Required properties:
> + - compatible: must be one of:
> +	- "aspeed,ast2400-wdt"
> +	- "aspeed,ast2500-wdt"
> +
> + - reg: physical base address of the controller and length of memory mapped
> +   region
> +
> +Example:
> +
> +	wdt1: watchdog at 1e785000 {
> +		compatible = "aspeed,ast2400-wdt";
> +		reg = <0x1e785000 0x1c>;
> +	};
>



From linux at roeck-us.net  Mon May 30 01:08:46 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Mon, 30 May 2016 01:08:46 -0700
Subject: [PATCH v3 2/2] watchdog: Add Aspeed watchdog driver
In-Reply-To: <1463559661-14170-3-git-send-email-joel@jms.id.au>
References: <1463062631-16432-1-git-send-email-joel@jms.id.au>
 <1463559661-14170-1-git-send-email-joel@jms.id.au>
 <1463559661-14170-3-git-send-email-joel@jms.id.au>
Message-ID: <574BF50E.90406@roeck-us.net>

On 05/18/2016 01:21 AM, Joel Stanley wrote:
> Provides generic watchdog features as well as reboot support for the
> Aspeed SoCs.
>
> Signed-off-by: Joel Stanley <joel at jms.id.au>

Reviewed-by: Guenter Roeck <linux at roeck-us.net>

> ---
>   drivers/watchdog/Kconfig      |  13 +++
>   drivers/watchdog/Makefile     |   1 +
>   drivers/watchdog/aspeed_wdt.c | 212 ++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 226 insertions(+)
>   create mode 100644 drivers/watchdog/aspeed_wdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index fb947655badd..4f0e2ded4785 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -661,6 +661,19 @@ config ATLAS7_WATCHDOG
>   	  To compile this driver as a module, choose M here: the
>   	  module will be called atlas7_wdt.
>
> +config ASPEED_WATCHDOG
> +	tristate "Aspeed 2400 watchdog support"
> +	depends on ARCH_ASPEED || COMPILE_TEST
> +	select WATCHDOG_CORE
> +	help
> +	  Say Y here to include support for the watchdog timer
> +	  in Apseed BMC SoCs.
> +
> +	  This driver is required to reboot the SoC.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called aspeed_wdt.
> +
>   # AVR32 Architecture
>
>   config AT32AP700X_WDT
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index feb6270fdbde..36855375e0ce 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -73,6 +73,7 @@ obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
>   obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
>   obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
>   obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o
> +obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o
>
>   # AVR32 Architecture
>   obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
> diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c
> new file mode 100644
> index 000000000000..f5ad8023c2e6
> --- /dev/null
> +++ b/drivers/watchdog/aspeed_wdt.c
> @@ -0,0 +1,212 @@
> +/*
> + * Copyright 2016 IBM Corporation
> + *
> + * Joel Stanley <joel at jms.id.au>
> + *
> + * 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.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/watchdog.h>
> +
> +struct aspeed_wdt {
> +	struct watchdog_device	wdd;
> +	void __iomem		*base;
> +	u32			ctrl;
> +};
> +
> +static const struct of_device_id aspeed_wdt_of_table[] = {
> +	{ .compatible = "aspeed,ast2400-wdt" },
> +	{ .compatible = "aspeed,ast2500-wdt" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
> +
> +#define WDT_STATUS		0x00
> +#define WDT_RELOAD_VALUE	0x04
> +#define WDT_RESTART		0x08
> +#define WDT_CTRL		0x0C
> +#define   WDT_CTRL_RESET_MODE_SOC	(0x00 << 5)
> +#define   WDT_CTRL_RESET_MODE_FULL_CHIP	(0x01 << 5)
> +#define   WDT_CTRL_1MHZ_CLK		BIT(4)
> +#define   WDT_CTRL_WDT_EXT		BIT(3)
> +#define   WDT_CTRL_WDT_INTR		BIT(2)
> +#define   WDT_CTRL_RESET_SYSTEM		BIT(1)
> +#define   WDT_CTRL_ENABLE		BIT(0)
> +
> +#define WDT_RESTART_MAGIC	0x4755
> +
> +/* 32 bits at 1MHz, in milliseconds */
> +#define WDT_MAX_TIMEOUT_MS	4294967
> +#define WDT_DEFAULT_TIMEOUT	30
> +#define WDT_RATE_1MHZ		1000000
> +
> +static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd)
> +{
> +	return container_of(wdd, struct aspeed_wdt, wdd);
> +}
> +
> +static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
> +{
> +	wdt->ctrl |= WDT_CTRL_ENABLE;
> +
> +	writel(0, wdt->base + WDT_CTRL);
> +	writel(count, wdt->base + WDT_RELOAD_VALUE);
> +	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
> +	writel(wdt->ctrl, wdt->base + WDT_CTRL);
> +}
> +
> +static int aspeed_wdt_start(struct watchdog_device *wdd)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +
> +	aspeed_wdt_enable(wdt, wdd->timeout * WDT_RATE_1MHZ);
> +
> +	return 0;
> +}
> +
> +static int aspeed_wdt_stop(struct watchdog_device *wdd)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +
> +	wdt->ctrl &= ~WDT_CTRL_ENABLE;
> +	writel(wdt->ctrl, wdt->base + WDT_CTRL);
> +
> +	return 0;
> +}
> +
> +static int aspeed_wdt_ping(struct watchdog_device *wdd)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +
> +	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
> +
> +	return 0;
> +}
> +
> +static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
> +				  unsigned int timeout)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +	u32 actual;
> +
> +	wdd->timeout = timeout;
> +
> +	actual = min(timeout, wdd->max_hw_heartbeat_ms * 1000);
> +
> +	writel(actual * WDT_RATE_1MHZ, wdt->base + WDT_RELOAD_VALUE);
> +	writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
> +
> +	return 0;
> +}
> +
> +static int aspeed_wdt_restart(struct watchdog_device *wdd,
> +			      unsigned long action, void *data)
> +{
> +	struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
> +
> +	aspeed_wdt_enable(wdt, 128 * WDT_RATE_1MHZ / 1000);
> +
> +	mdelay(1000);
> +
> +	return 0;
> +}
> +
> +static const struct watchdog_ops aspeed_wdt_ops = {
> +	.start		= aspeed_wdt_start,
> +	.stop		= aspeed_wdt_stop,
> +	.ping		= aspeed_wdt_ping,
> +	.set_timeout	= aspeed_wdt_set_timeout,
> +	.restart	= aspeed_wdt_restart,
> +	.owner		= THIS_MODULE,
> +};
> +
> +static const struct watchdog_info aspeed_wdt_info = {
> +	.options	= WDIOF_KEEPALIVEPING
> +			| WDIOF_MAGICCLOSE
> +			| WDIOF_SETTIMEOUT,
> +	.identity	= KBUILD_MODNAME,
> +};
> +
> +static int aspeed_wdt_remove(struct platform_device *pdev)
> +{
> +	struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
> +
> +	watchdog_unregister_device(&wdt->wdd);
> +
> +	return 0;
> +}
> +
> +static int aspeed_wdt_probe(struct platform_device *pdev)
> +{
> +	struct aspeed_wdt *wdt;
> +	struct resource *res;
> +	int ret;
> +
> +	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
> +	if (!wdt)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	wdt->base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(wdt->base))
> +		return PTR_ERR(wdt->base);
> +
> +	/*
> +	 * The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only
> +	 * runs at 1MHz. We chose to always run at 1MHz, as there's no
> +	 * good reason to have a faster watchdog counter.
> +	 */
> +	wdt->wdd.info = &aspeed_wdt_info;
> +	wdt->wdd.ops = &aspeed_wdt_ops;
> +	wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS;
> +	wdt->wdd.parent = &pdev->dev;
> +
> +	wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT;
> +	watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
> +
> +	/*
> +	 * Control reset on a per-device basis to ensure the
> +	 * host is not affected by a BMC reboot, so only reset
> +	 * the SOC and not the full chip
> +	 */
> +	wdt->ctrl = WDT_CTRL_RESET_MODE_SOC |
> +		WDT_CTRL_1MHZ_CLK |
> +		WDT_CTRL_RESET_SYSTEM;
> +
> +	if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_ENABLE)  {
> +		aspeed_wdt_start(&wdt->wdd);
> +		set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
> +	}
> +
> +	ret = watchdog_register_device(&wdt->wdd);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to register\n");
> +		return ret;
> +	}
> +
> +	platform_set_drvdata(pdev, wdt);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver aspeed_watchdog_driver = {
> +	.probe = aspeed_wdt_probe,
> +	.remove = aspeed_wdt_remove,
> +	.driver = {
> +		.name = KBUILD_MODNAME,
> +		.of_match_table = of_match_ptr(aspeed_wdt_of_table),
> +	},
> +};
> +module_platform_driver(aspeed_watchdog_driver);
> +
> +MODULE_DESCRIPTION("Aspeed Watchdog Driver");
> +MODULE_LICENSE("GPL");
>



From maxime.ripard at free-electrons.com  Mon May 30 01:08:51 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 30 May 2016 10:08:51 +0200
Subject: [PATCH 1/3] ARM: dts: sun5i: a10s: add spi2 pins
In-Reply-To: <908ed06eb46f2162e222258aa14df545d0fa5b48.1464129859.git.hramrach@gmail.com>
References: <908ed06eb46f2162e222258aa14df545d0fa5b48.1464129859.git.hramrach@gmail.com>
Message-ID: <20160530080851.GC4247@lukather>

On Thu, May 26, 2016 at 07:25:22PM -0000, Michal Suchanek wrote:
> Used on A10s Olinuxino.
> 
> Signed-off-by: Michal Suchanek <hramrach at gmail.com>

Applied, thanks!

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/b48ffbe5/attachment.sig>

From maxime.ripard at free-electrons.com  Mon May 30 01:09:40 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 30 May 2016 10:09:40 +0200
Subject: [PATCH 2/3] ARM: dts: sun5i: add spi2 on A10s Olinuxino Micro
In-Reply-To: <602069f7735ad37b1849dac484d2e8e7c9ec08b3.1464129859.git.hramrach@gmail.com>
References: <908ed06eb46f2162e222258aa14df545d0fa5b48.1464129859.git.hramrach@gmail.com>
 <602069f7735ad37b1849dac484d2e8e7c9ec08b3.1464129859.git.hramrach@gmail.com>
Message-ID: <20160530080940.GD4247@lukather>

Hi,

On Thu, May 26, 2016 at 07:25:23PM -0000, Michal Suchanek wrote:
> spi2 is available on the UEXT connector
> 
> Signed-off-by: Michal Suchanek <hramrach at gmail.com>
> ---
>  arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
> index 86d046a..7d2ff60 100644
> --- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
> +++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
> @@ -192,6 +192,13 @@
>  	status = "okay";
>  };
>  
> +&spi2 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&spi2_pins_a>,
> +		    <&spi2_cs0_pins_a>;
> +	status = "okay";
> +};
> +

This should be ordered alphabetically.

Fixed it, and applied.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/c59b2662/attachment.sig>

From arnd at arndb.de  Mon May 30 01:16:43 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 30 May 2016 10:16:43 +0200
Subject: [PATCH v3] Axi-usb: Add support for 64-bit addressing.
In-Reply-To: <C89496FEAE474D468F30D558A9468D9F26CEEBAB@XAP-PVEXMBX01.xlnx.xilinx.com>
References: <1464067268-35299-1-git-send-email-navam@xilinx.com>
 <CAL_Jsq+VL6jjo5QLwnsC8rEfgP4KN5hCSB7QicWWN-uvZU0GHw@mail.gmail.com>
 <C89496FEAE474D468F30D558A9468D9F26CEEBAB@XAP-PVEXMBX01.xlnx.xilinx.com>
Message-ID: <5333252.Un7tdhWc5Q@wuerfel>

On Monday, May 30, 2016 5:46:21 AM CEST Nava kishore Manne wrote:
> >
> The Axi-usb 5.00 IP is a FPGA based one. This IP needs to support two H/w designs one with 32 bit DMA addressing another one is 64 bit DMA addressing.
> And also in the software point for view we don?t have any register to figure out whether it is supporting 32 bit DMA addressing or 64 bit DMA addressing.
> To support both the designs I kept addrwidth property in the dt. I think here addrwidth property is make sense to differentiate the h/w configurations.
> If you want me to changes it to boolean please let me know I will fix it in the next version.

I think boolean would be more logical here, since what is configurable
here is not how many bits are supported, but whether the XUSB_DMA_DSAR_ADDR
register is present or not.

	Arnd


From peter.ujfalusi at ti.com  Mon May 30 01:23:45 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:23:45 +0300
Subject: [PATCH v5 2/7] ARM: OMAP3: hwmod data: Fix McBSP2/3 sidetone data
In-Reply-To: <20160530082350.24285-1-peter.ujfalusi@ti.com>
References: <20160530082350.24285-1-peter.ujfalusi@ti.com>
Message-ID: <20160530082350.24285-3-peter.ujfalusi@ti.com>

The McBSPLP's sidetone main clock is the McBSPLP's ICLK, not FCLK as the
sidetone only receives the ICLK from the main McBSP module.
Since the McBSP and sidetone is using the very same clock from PRCM level
the sidetone must not have the prcm section to check the clock status since
the sidetone is only used when McBSP is already configured.
If two separate hwmods looking at the same bit and they would use
pm_runtime in nested way (as it must happen with McBSP and it's ST module)
the hwmod would warn, because the idlest will not match what it is expected
after enable/disable of the clocks.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 24 ++++--------------------
 1 file changed, 4 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 9869a75c5d96..d72ee6185d5e 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1322,16 +1322,8 @@ static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
 	.name		= "mcbsp2_sidetone",
 	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp2_sidetone_irqs,
-	.main_clk	= "mcbsp2_fck",
-	.prcm		= {
-		.omap2 = {
-			.prcm_reg_id = 1,
-			 .module_bit = OMAP3430_EN_MCBSP2_SHIFT,
-			.module_offs = OMAP3430_PER_MOD,
-			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_MCBSP2_SHIFT,
-		},
-	},
+	.main_clk	= "mcbsp2_ick",
+	.flags		= HWMOD_NO_IDLEST,
 };
 
 /* mcbsp3_sidetone */
@@ -1344,16 +1336,8 @@ static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
 	.name		= "mcbsp3_sidetone",
 	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
 	.mpu_irqs	= omap3xxx_mcbsp3_sidetone_irqs,
-	.main_clk	= "mcbsp3_fck",
-	.prcm		= {
-		.omap2 = {
-			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_MCBSP3_SHIFT,
-			.module_offs = OMAP3430_PER_MOD,
-			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_MCBSP3_SHIFT,
-		},
-	},
+	.main_clk	= "mcbsp3_ick",
+	.flags		= HWMOD_NO_IDLEST,
 };
 
 /* SR common */
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:23:44 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:23:44 +0300
Subject: [PATCH v5 1/7] ARM: dts: omap3: Add clocks to McBSP nodes
In-Reply-To: <20160530082350.24285-1-peter.ujfalusi@ti.com>
References: <20160530082350.24285-1-peter.ujfalusi@ti.com>
Message-ID: <20160530082350.24285-2-peter.ujfalusi@ti.com>

Add clock properties to the McBSP nodes. McBSP2 and 3 need to have ick also
since the Sidetone block of these modules are operating using the McBSP
interface clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap3.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 9fbda38528dc..4c3c471d2a83 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -493,6 +493,8 @@
 			dmas = <&sdma 31>,
 			       <&sdma 32>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp1_fck>;
+			clock-names = "fck";
 			status = "disabled";
 		};
 
@@ -511,6 +513,8 @@
 			dmas = <&sdma 33>,
 			       <&sdma 34>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp2_fck>, <&mcbsp2_ick>;
+			clock-names = "fck", "ick";
 			status = "disabled";
 		};
 
@@ -529,6 +533,8 @@
 			dmas = <&sdma 17>,
 			       <&sdma 18>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp3_fck>, <&mcbsp3_ick>;
+			clock-names = "fck", "ick";
 			status = "disabled";
 		};
 
@@ -545,6 +551,8 @@
 			dmas = <&sdma 19>,
 			       <&sdma 20>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp4_fck>;
+			clock-names = "fck";
 			status = "disabled";
 		};
 
@@ -561,6 +569,8 @@
 			dmas = <&sdma 21>,
 			       <&sdma 22>;
 			dma-names = "tx", "rx";
+			clocks = <&mcbsp5_fck>;
+			clock-names = "fck";
 			status = "disabled";
 		};
 
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:23:43 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:23:43 +0300
Subject: [PATCH v5 0/7] ARM/ASoC: OMAP3: Fix McBSP2/3 sidetone support
Message-ID: <20160530082350.24285-1-peter.ujfalusi@ti.com>

Hi,

Changes since v4:
- Moved DTS patch as the first in the series
- rebased on top of 4.7-rc1

Changes since v3:
- Rebased on next-20160525 [1] to apply cleanly
- Fixed subject line for patch5
- Added Mark's acked-by to the ASoC patches

[1] "ASoC: omap-mcbsp: Enable/disable sidetone block auto clock
gating for omap3" is gone missing from linux-next - it was in next-20160517 and
I'm not sure when it got dropped.

Tony: since Paul did not replied to the series, I'm sending the v4 now, I hope
he will have time to look at this.

Commit message from v3:

Based on the ongoing discussion on v2 (ARM: OMAP3: Fix McBSP2/3 hwmod setup for
sidetone) I have dropped the removal of the sidetone hwmod and only corrected
it. The series now includes all related changes needed to have correct sidetone
support whenever we boot in legacy or in DT mode.

This time the ASoC part have dependency on earlier patches so they can not be
applied separately.

Regards,
Peter
---
Peter Ujfalusi (7):
  ARM: dts: omap3: Add clocks to McBSP nodes
  ARM: OMAP3: hwmod data: Fix McBSP2/3 sidetone data
  ARM: OMAP3: McBSP: New callback for McBSP2/3 ICLK idle configuration
  ARM: OMAP3: pdata-quirks: Add support for McBSP2/3 sidetone handling
  ASoC: omap-mcbsp: Rename omap_mcbsp_sysfs_remove() to
    omap_mcbsp_cleanup()
  ASoC: omap-mcbsp: sidetone: Use the new callback for iclk handling
  ARM: OMAP2+: McBSP: Remove the old iclk allow/deny idle code

 arch/arm/boot/dts/omap3.dtsi                | 10 ++++++++++
 arch/arm/mach-omap2/mcbsp.c                 | 31 ++++++++++++++++-------------
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c  | 24 ++++------------------
 arch/arm/mach-omap2/pdata-quirks.c          | 18 +++++++++++++++++
 include/linux/platform_data/asoc-ti-mcbsp.h |  4 +++-
 sound/soc/omap/mcbsp.c                      | 21 +++++++++++++------
 sound/soc/omap/mcbsp.h                      |  3 ++-
 sound/soc/omap/omap-mcbsp.c                 |  5 ++++-
 8 files changed, 73 insertions(+), 43 deletions(-)

-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:23:46 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:23:46 +0300
Subject: [PATCH v5 3/7] ARM: OMAP3: McBSP: New callback for McBSP2/3 ICLK idle
 configuration
In-Reply-To: <20160530082350.24285-1-peter.ujfalusi@ti.com>
References: <20160530082350.24285-1-peter.ujfalusi@ti.com>
Message-ID: <20160530082350.24285-4-peter.ujfalusi@ti.com>

McBSP2/3 module's sidetone module operates using the module's ICLK clock.
When the Sidetone is in use the interface clock of the module must not
idle. The new callback expects to receive the *clk of the module's ick and
not the id number of the McBSP. This will allow us more cleanups and going
to simplify the ICLK handling.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/mach-omap2/mcbsp.c                 | 12 ++++++++++++
 include/linux/platform_data/asoc-ti-mcbsp.h |  1 +
 2 files changed, 13 insertions(+)

diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index b4ac3af1160c..959cb4cb1062 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -48,6 +48,17 @@ static int omap3_enable_st_clock(unsigned int id, bool enable)
 		return omap2_clk_allow_idle(mcbsp_iclks[id]);
 }
 
+static int omap3_mcbsp_force_ick_on(struct clk *clk, bool force_on)
+{
+	if (!clk)
+		return 0;
+
+	if (force_on)
+		return omap2_clk_deny_idle(clk);
+	else
+		return omap2_clk_allow_idle(clk);
+}
+
 static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 {
 	int id, count = 1;
@@ -97,6 +108,7 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 		oh_device[1] = omap_hwmod_lookup((
 		(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
 		pdata->enable_st_clock = omap3_enable_st_clock;
+		pdata->force_ick_on = omap3_mcbsp_force_ick_on;
 		sprintf(clk_name, "mcbsp%d_ick", id);
 		mcbsp_iclks[id] = clk_get(NULL, clk_name);
 		count++;
diff --git a/include/linux/platform_data/asoc-ti-mcbsp.h b/include/linux/platform_data/asoc-ti-mcbsp.h
index 3c73c045f8da..73e5e832fa23 100644
--- a/include/linux/platform_data/asoc-ti-mcbsp.h
+++ b/include/linux/platform_data/asoc-ti-mcbsp.h
@@ -45,6 +45,7 @@ struct omap_mcbsp_platform_data {
 	bool has_wakeup; /* Wakeup capability */
 	bool has_ccr; /* Transceiver has configuration control registers */
 	int (*enable_st_clock)(unsigned int, bool);
+	int (*force_ick_on)(struct clk *clk, bool force_on);
 };
 
 /**
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:23:47 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:23:47 +0300
Subject: [PATCH v5 4/7] ARM: OMAP3: pdata-quirks: Add support for McBSP2/3
 sidetone handling
In-Reply-To: <20160530082350.24285-1-peter.ujfalusi@ti.com>
References: <20160530082350.24285-1-peter.ujfalusi@ti.com>
Message-ID: <20160530082350.24285-5-peter.ujfalusi@ti.com>

McBSP2/3 module's sidetone module operates using the module's ICLK clock.
When the Sidetone is in use the interface clock of the module must not
idle. To prevent the iclk idling the driver expects to have pdata callback
to call. With this patch the callback is going to be set up for DT boot
also.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/mach-omap2/mcbsp.c                 |  9 +++++++++
 arch/arm/mach-omap2/pdata-quirks.c          | 18 ++++++++++++++++++
 include/linux/platform_data/asoc-ti-mcbsp.h |  2 ++
 3 files changed, 29 insertions(+)

diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index 959cb4cb1062..edf4f41c0135 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -59,6 +59,15 @@ static int omap3_mcbsp_force_ick_on(struct clk *clk, bool force_on)
 		return omap2_clk_allow_idle(clk);
 }
 
+void __init omap3_mcbsp_init_pdata_callback(
+					struct omap_mcbsp_platform_data *pdata)
+{
+	if (!pdata)
+		return;
+
+	pdata->force_ick_on = omap3_mcbsp_force_ick_on;
+}
+
 static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 {
 	int id, count = 1;
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 6571ad959908..ab2b2b2b90e5 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -26,6 +26,7 @@
 #include <linux/platform_data/wkup_m3.h>
 #include <linux/platform_data/pwm_omap_dmtimer.h>
 #include <linux/platform_data/media/ir-rx51.h>
+#include <linux/platform_data/asoc-ti-mcbsp.h>
 #include <plat/dmtimer.h>
 
 #include "common.h"
@@ -505,6 +506,16 @@ static struct platform_device __maybe_unused rx51_lirc_device = {
 	},
 };
 
+#if IS_ENABLED(CONFIG_SND_OMAP_SOC_MCBSP)
+static struct omap_mcbsp_platform_data mcbsp_pdata;
+static void __init omap3_mcbsp_init(void)
+{
+	omap3_mcbsp_init_pdata_callback(&mcbsp_pdata);
+}
+#else
+static void __init omap3_mcbsp_init(void) {}
+#endif
+
 /*
  * Few boards still need auxdata populated before we populate
  * the dev entries in of_platform_populate().
@@ -536,6 +547,11 @@ static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
 	OF_DEV_AUXDATA("ti,am3517-emac", 0x5c000000, "davinci_emac.0",
 		       &am35xx_emac_pdata),
+	/* McBSP modules with sidetone core */
+#if IS_ENABLED(CONFIG_SND_OMAP_SOC_MCBSP)
+	OF_DEV_AUXDATA("ti,omap3-mcbsp", 0x49022000, "49022000.mcbsp", &mcbsp_pdata),
+	OF_DEV_AUXDATA("ti,omap3-mcbsp", 0x49024000, "49024000.mcbsp", &mcbsp_pdata),
+#endif
 #endif
 #ifdef CONFIG_SOC_AM33XX
 	OF_DEV_AUXDATA("ti,am3352-wkup-m3", 0x44d00000, "44d00000.wkup_m3",
@@ -608,6 +624,8 @@ void __init pdata_quirks_init(const struct of_device_id *omap_dt_match_table)
 	    of_machine_is_compatible("ti,omap3"))
 		omap_sdrc_init(NULL, NULL);
 
+	if (of_machine_is_compatible("ti,omap3"))
+		omap3_mcbsp_init();
 	pdata_quirks_check(auxdata_quirks);
 	of_platform_populate(NULL, omap_dt_match_table,
 			     omap_auxdata_lookup, NULL);
diff --git a/include/linux/platform_data/asoc-ti-mcbsp.h b/include/linux/platform_data/asoc-ti-mcbsp.h
index 73e5e832fa23..5530971abf4d 100644
--- a/include/linux/platform_data/asoc-ti-mcbsp.h
+++ b/include/linux/platform_data/asoc-ti-mcbsp.h
@@ -56,4 +56,6 @@ struct omap_mcbsp_dev_attr {
 	const char *sidetone;
 };
 
+void omap3_mcbsp_init_pdata_callback(struct omap_mcbsp_platform_data *pdata);
+
 #endif
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:23:48 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:23:48 +0300
Subject: [PATCH v5 5/7] ASoC: omap-mcbsp: Rename omap_mcbsp_sysfs_remove() to
 omap_mcbsp_cleanup()
In-Reply-To: <20160530082350.24285-1-peter.ujfalusi@ti.com>
References: <20160530082350.24285-1-peter.ujfalusi@ti.com>
Message-ID: <20160530082350.24285-6-peter.ujfalusi@ti.com>

The function will do more then removing the sysfs files in the future.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
Acked-by: Mark Brown <broonie at kernel.org>
---
 sound/soc/omap/mcbsp.c      | 2 +-
 sound/soc/omap/mcbsp.h      | 2 +-
 sound/soc/omap/omap-mcbsp.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
index 4a16e778966b..ace73b97769f 100644
--- a/sound/soc/omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -1088,7 +1088,7 @@ err_thres:
 	return ret;
 }
 
-void omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp)
+void omap_mcbsp_cleanup(struct omap_mcbsp *mcbsp)
 {
 	if (mcbsp->pdata->buffer_size)
 		sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
index 96d1b086bcf8..ce6cbbf923a4 100644
--- a/sound/soc/omap/mcbsp.h
+++ b/sound/soc/omap/mcbsp.h
@@ -349,6 +349,6 @@ int omap_st_disable(struct omap_mcbsp *mcbsp);
 int omap_st_is_enabled(struct omap_mcbsp *mcbsp);
 
 int omap_mcbsp_init(struct platform_device *pdev);
-void omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp);
+void omap_mcbsp_cleanup(struct omap_mcbsp *mcbsp);
 
 #endif /* __ASOC_MCBSP_H */
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index fd99d89de6a8..db07debb4a9c 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -832,7 +832,7 @@ static int asoc_mcbsp_remove(struct platform_device *pdev)
 	if (mcbsp->pdata->ops && mcbsp->pdata->ops->free)
 		mcbsp->pdata->ops->free(mcbsp->id);
 
-	omap_mcbsp_sysfs_remove(mcbsp);
+	omap_mcbsp_cleanup(mcbsp);
 
 	clk_put(mcbsp->fclk);
 
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:23:49 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:23:49 +0300
Subject: [PATCH v5 6/7] ASoC: omap-mcbsp: sidetone: Use the new callback for
 iclk handling
In-Reply-To: <20160530082350.24285-1-peter.ujfalusi@ti.com>
References: <20160530082350.24285-1-peter.ujfalusi@ti.com>
Message-ID: <20160530082350.24285-7-peter.ujfalusi@ti.com>

The McBSP sidetone (in OMAP3 McBSP2 and 3 module) is working with the
module's interface clock. When the sidetone is enabled the iclk must not
idle because it will result in choppy sidetone.
Switch to use the new callback for handling the iclk allow/deny idle
configuration.
For this the driver needs to get the module's ick clock and pass the clk
pointer to the callback.
In DT boot, the pdata-quirk is going to set up the callback for the driver
so save it if it is set in the pdata of the device.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
Acked-by: Mark Brown <broonie at kernel.org>
---
 sound/soc/omap/mcbsp.c      | 19 ++++++++++++++-----
 sound/soc/omap/mcbsp.h      |  1 +
 sound/soc/omap/omap-mcbsp.c |  3 +++
 3 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
index ace73b97769f..76ce33199bf9 100644
--- a/sound/soc/omap/mcbsp.c
+++ b/sound/soc/omap/mcbsp.c
@@ -257,8 +257,8 @@ static void omap_st_on(struct omap_mcbsp *mcbsp)
 {
 	unsigned int w;
 
-	if (mcbsp->pdata->enable_st_clock)
-		mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
+	if (mcbsp->pdata->force_ick_on)
+		mcbsp->pdata->force_ick_on(mcbsp->st_data->mcbsp_iclk, true);
 
 	/* Disable Sidetone clock auto-gating for normal operation */
 	w = MCBSP_ST_READ(mcbsp, SYSCONFIG);
@@ -287,8 +287,8 @@ static void omap_st_off(struct omap_mcbsp *mcbsp)
 	w = MCBSP_ST_READ(mcbsp, SYSCONFIG);
 	MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w | ST_AUTOIDLE);
 
-	if (mcbsp->pdata->enable_st_clock)
-		mcbsp->pdata->enable_st_clock(mcbsp->id, 0);
+	if (mcbsp->pdata->force_ick_on)
+		mcbsp->pdata->force_ick_on(mcbsp->st_data->mcbsp_iclk, false);
 }
 
 static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
@@ -946,6 +946,13 @@ static int omap_st_add(struct omap_mcbsp *mcbsp, struct resource *res)
 	if (!st_data)
 		return -ENOMEM;
 
+	st_data->mcbsp_iclk = clk_get(mcbsp->dev, "ick");
+	if (IS_ERR(st_data->mcbsp_iclk)) {
+		dev_warn(mcbsp->dev,
+			 "Failed to get ick, sidetone might be broken\n");
+		st_data->mcbsp_iclk = NULL;
+	}
+
 	st_data->io_base_st = devm_ioremap(mcbsp->dev, res->start,
 					   resource_size(res));
 	if (!st_data->io_base_st)
@@ -1093,6 +1100,8 @@ void omap_mcbsp_cleanup(struct omap_mcbsp *mcbsp)
 	if (mcbsp->pdata->buffer_size)
 		sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
 
-	if (mcbsp->st_data)
+	if (mcbsp->st_data) {
 		sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
+		clk_put(mcbsp->st_data->mcbsp_iclk);
+	}
 }
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
index ce6cbbf923a4..61e93b1c185d 100644
--- a/sound/soc/omap/mcbsp.h
+++ b/sound/soc/omap/mcbsp.h
@@ -280,6 +280,7 @@ struct omap_mcbsp_reg_cfg {
 
 struct omap_mcbsp_st_data {
 	void __iomem *io_base_st;
+	struct clk *mcbsp_iclk;
 	bool running;
 	bool enabled;
 	s16 taps[128];	/* Sidetone filter coefficients */
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index db07debb4a9c..d018e966e533 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -788,6 +788,7 @@ static int asoc_mcbsp_probe(struct platform_device *pdev)
 	match = of_match_device(omap_mcbsp_of_match, &pdev->dev);
 	if (match) {
 		struct device_node *node = pdev->dev.of_node;
+		struct omap_mcbsp_platform_data *pdata_quirk = pdata;
 		int buffer_size;
 
 		pdata = devm_kzalloc(&pdev->dev,
@@ -799,6 +800,8 @@ static int asoc_mcbsp_probe(struct platform_device *pdev)
 		memcpy(pdata, match->data, sizeof(*pdata));
 		if (!of_property_read_u32(node, "ti,buffer-size", &buffer_size))
 			pdata->buffer_size = buffer_size;
+		if (pdata_quirk)
+			pdata->force_ick_on = pdata_quirk->force_ick_on;
 	} else if (!pdata) {
 		dev_err(&pdev->dev, "missing platform data.\n");
 		return -EINVAL;
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:23:50 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:23:50 +0300
Subject: [PATCH v5 7/7] ARM: OMAP2+: McBSP: Remove the old iclk allow/deny
 idle code
In-Reply-To: <20160530082350.24285-1-peter.ujfalusi@ti.com>
References: <20160530082350.24285-1-peter.ujfalusi@ti.com>
Message-ID: <20160530082350.24285-8-peter.ujfalusi@ti.com>

The new pdata callback (force_ick_on) is now used by the driver and the old
callback related code can be removed.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/mach-omap2/mcbsp.c                 | 18 ------------------
 include/linux/platform_data/asoc-ti-mcbsp.h |  1 -
 2 files changed, 19 deletions(-)

diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index edf4f41c0135..fc04be74e064 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -34,20 +34,6 @@
 #include "cm3xxx.h"
 #include "cm-regbits-34xx.h"
 
-static struct clk *mcbsp_iclks[5];
-
-static int omap3_enable_st_clock(unsigned int id, bool enable)
-{
-	/*
-	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
-	 * are enabled or sidetones start sounding ugly.
-	 */
-	if (enable)
-		return omap2_clk_deny_idle(mcbsp_iclks[id]);
-	else
-		return omap2_clk_allow_idle(mcbsp_iclks[id]);
-}
-
 static int omap3_mcbsp_force_ick_on(struct clk *clk, bool force_on)
 {
 	if (!clk)
@@ -75,7 +61,6 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 	struct omap_hwmod *oh_device[2];
 	struct omap_mcbsp_platform_data *pdata = NULL;
 	struct platform_device *pdev;
-	char clk_name[11];
 
 	sscanf(oh->name, "mcbsp%d", &id);
 
@@ -116,10 +101,7 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 	if (oh->dev_attr) {
 		oh_device[1] = omap_hwmod_lookup((
 		(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
-		pdata->enable_st_clock = omap3_enable_st_clock;
 		pdata->force_ick_on = omap3_mcbsp_force_ick_on;
-		sprintf(clk_name, "mcbsp%d_ick", id);
-		mcbsp_iclks[id] = clk_get(NULL, clk_name);
 		count++;
 	}
 	pdev = omap_device_build_ss(name, id, oh_device, count, pdata,
diff --git a/include/linux/platform_data/asoc-ti-mcbsp.h b/include/linux/platform_data/asoc-ti-mcbsp.h
index 5530971abf4d..e684543254f3 100644
--- a/include/linux/platform_data/asoc-ti-mcbsp.h
+++ b/include/linux/platform_data/asoc-ti-mcbsp.h
@@ -44,7 +44,6 @@ struct omap_mcbsp_platform_data {
 	/* McBSP platform and instance specific features */
 	bool has_wakeup; /* Wakeup capability */
 	bool has_ccr; /* Transceiver has configuration control registers */
-	int (*enable_st_clock)(unsigned int, bool);
 	int (*force_ick_on)(struct clk *clk, bool force_on);
 };
 
-- 
2.8.3



From aryabinin at virtuozzo.com  Mon May 30 01:26:41 2016
From: aryabinin at virtuozzo.com (Andrey Ryabinin)
Date: Mon, 30 May 2016 11:26:41 +0300
Subject: [v2 PATCH] arm64: kasan: instrument user memory access API
In-Reply-To: <1464382863-11879-1-git-send-email-yang.shi@linaro.org>
References: <1464382863-11879-1-git-send-email-yang.shi@linaro.org>
Message-ID: <574BF941.7090906@virtuozzo.com>


On 05/28/2016 12:01 AM, Yang Shi wrote:
> The upstream commit 1771c6e1a567ea0ba2cccc0a4ffe68a1419fd8ef
> ("x86/kasan: instrument user memory access API") added KASAN instrument to
> x86 user memory access API, so added such instrument to ARM64 too.
> 
> Define __copy_to/from_user in C in order to add kasan_check_read/write call,
> rename assembly implementation to __arch_copy_to/from_user.
> 
> Tested by test_kasan module.
> 
> Signed-off-by: Yang Shi <yang.shi at linaro.org>
> 

Acked-by: Andrey Ryabinin <aryabinin at virtuozzo.com>


From maxime.ripard at free-electrons.com  Mon May 30 01:29:38 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 30 May 2016 10:29:38 +0200
Subject: [PATCH 3/3] ARM: dts: sun5i: Add spi2 alias on A10s Olinuxino
In-Reply-To: <df27dbe5931dcb7d8f404759ad42e25b15bcf780.1464129859.git.hramrach@gmail.com>
References: <908ed06eb46f2162e222258aa14df545d0fa5b48.1464129859.git.hramrach@gmail.com>
 <df27dbe5931dcb7d8f404759ad42e25b15bcf780.1464129859.git.hramrach@gmail.com>
Message-ID: <20160530082938.GE4247@lukather>

On Thu, May 26, 2016 at 07:25:24PM -0000, Michal Suchanek wrote:
> spi2 is available on the UEXT connector
> 
> The bus is named spi2 in the A10s manual and Olinuxino manual so it is
> pointless to alias it to something else like spi0.

That's not how aliases work in the DT. It's about indexing the devices
that are enabled on the board, so it should definitely be 0,
especially since it's the only SPI bus usable on that board anyway.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/b64821f6/attachment.sig>

From narmstrong at baylibre.com  Mon May 30 01:30:11 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 30 May 2016 10:30:11 +0200
Subject: [RFC PATCH 0/2] scpi: Add SCPI framework to handle vendors
 variants
In-Reply-To: <574802AF.2080909@baylibre.com>
References: <1464255491-18503-1-git-send-email-narmstrong@baylibre.com>
 <57472450.4000709@arm.com> <574802AF.2080909@baylibre.com>
Message-ID: <574BFA13.40009@baylibre.com>

On 05/27/2016 10:17 AM, Neil Armstrong wrote:
> Hi,
> On 05/26/2016 06:29 PM, Sudeep Holla wrote:
>> Hi Neil,
>>
>> On 26/05/16 10:38, Neil Armstrong wrote:
>>> Since the current SCPI implementation, based on [0]:
>>> - is (at leat) JUNO specific
>>
>> Agreed.
>>
>>> - does not specify a strong "standard"
>>
>> Not exactly, it's extensible. Refer section 3.2.2. Get SCP capability
>> Extended Set Enabled bit.
> 
> Well, I was not thinking about an extension, but this should be upstreamed for sure.
> 
>>
>>> - does not specify a strong MHU interface specification
>>>
>>
>> Not really required, any mailbox must do.
>>
>>> SoC vendors could implement a variant with slight changes in message
>>> indexes,
>>
>> I assume you mean command index here
>>
>>> new messages types,
>>
>> Also fine with extended command set.
>>
>>> different messages data format or
>>
>> you mean the header or payload ? If they don't follow the header, then
>> how can be group them as same protocol ?
>>
>>> different MHU communication scheme.
>>
>> Not a problem as I mentioned above.
>>
>>>
>>> To keep the spirit of the SCPI interface, add a thin "register" layer to get
>>> the ops from the parent node and switch the drivers using the ops to use
>>> the new of_scpi_ops_get() call.
>>>
>>
>> All I can see is that you share the code to register such drivers which
>> is hardly anything. It's hard to say all drivers use same protocol or
>> interface after this change. I may be missing to see something here so
>> it would be easy to appreciate/review this change with one user of this.
> 
> I'm actually working on an "SCPI" implementation from Amlogic for their arm64 plaform,
> and their implementation is slightly different but enough to need a separate driver.
> 
> For instance, the differences are :
> - they do not implement virtual channels
> - they pass the command word by the mailbox interface
> - they use the "sender id" to group the command in a sort of "class"
> - the payload size is shifted by 20 instead of 16
> - the command word is not in the SRAM, so we cannot use a rx command queue, only a single command by channel at a single time
> - the command indexes are slightly shifted
> - in clk_set_value, "rate" is first instead of last entry
> - in sensor_value, they only use a 32bit entry
> - some commands are only accepted on the high priority channel, the others only on the low priority
> - MAX_DVFS_DOMAINS is 3 instead of 8
> - MAX_DVFS_OPPS is 16 instead of 8
> 
> But, It's still a "SCPI" interface by design and usage because :
> - they implement 90% of the same commands, in the same way
> - the usage is exactly the same and architecture is similar
> - they use the same error code scheme
> 
> Finally, it would be stupid to add an exact copy of the scpi-sensors and scpi-clocks !
> The scpi-cpufreq is another story since they only have a single A53 cluster, it's not adapted.
> 
> This is why I wrote a very thin layer, and it can also clean up the arm_scpi and the scpi driver to use a cleaner registry interface.
> It would also be a good point to add a private_data to the ops and pass it to the scpi callbacks, to completely remove the global variables.
> 
> I found an issue with scpi-cpufreq, since the device is created by the scpi-clocks probe, it does not have a proper node and my current of_scpi_ops_get won't work...
> The scpi-cpufreq should have a proper DT node and use the deffered probe to register after the scpi-clocks.
> 
>>
>> My idea of extending this driver if vendor implements extensions based
>> on SCPI specification is something like below:
>>

While looking for other ARMv8 based platform, I found that the RK3368 platform has the same SCPI implementation as Amlogic.

They extended it with DDR, system and thermal commands.

Look at :
https://github.com/geekboxzone/mmallow_kernel/blob/geekbox/drivers/mailbox/scpi_cmd.h
https://github.com/geekboxzone/mmallow_kernel/blob/geekbox/drivers/mailbox/scpi_protocol.c

So the SCPI must have a framework to allow different protocol versions, and must allow command extension.
Grouping Rockchip and Amlogic should be done, thus needing a generic name like vendor_scpi or with a version.

Sudeep, could you somehow find out which version of the protocol AmLogic and Rockchip based their SCPI development ?


Thanks !
Neil

> Neil
> 



From maxime.ripard at free-electrons.com  Mon May 30 01:37:00 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 30 May 2016 10:37:00 +0200
Subject: [PATCH 2/5] spi: sun4i: fix FIFO limit
In-Reply-To: <e315008b5e9dc3f1490507508fd2f6e94767dfbb.1464130597.git.hramrach@gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
 <e315008b5e9dc3f1490507508fd2f6e94767dfbb.1464130597.git.hramrach@gmail.com>
Message-ID: <20160530083700.GF4247@lukather>

Hi,

On Thu, May 26, 2016 at 07:25:24PM -0000, Michal Suchanek wrote:
> When testing SPI without DMA I noticed that filling the FIFO on the
> spi controller causes timeout.
> 
> Always leave room for one byte in the FIFO.
> 
> Signed-off-by: Michal Suchanek <hramrach at gmail.com>

Sending it to stable would be great (with a fixes tag too).

> 
> ---
> v2:
> use EMSGSIZE instead of EINVAL
> ---
>  drivers/spi/spi-sun4i.c | 8 ++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
> index fe63bbd..04f1b77 100644
> --- a/drivers/spi/spi-sun4i.c
> +++ b/drivers/spi/spi-sun4i.c
> @@ -180,7 +180,9 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
>  
>  	/* We don't support transfer larger than the FIFO */
>  	if (tfr->len > SUN4I_FIFO_DEPTH)
> -		return -EINVAL;
> +		return -EMSGSIZE;

One new line here.

> +	if (tfr->tx_buf && tfr->len >= SUN4I_FIFO_DEPTH)
> +		return -EMSGSIZE;
>  
>  	reinit_completion(&sspi->done);
>  	sspi->tx_buf = tfr->tx_buf;
> @@ -271,7 +273,9 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
>  	sun4i_spi_write(sspi, SUN4I_XMIT_CNT_REG, SUN4I_XMIT_CNT(tx_len));
>  
>  	/* Fill the TX FIFO */
> -	sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
> +	/* Filling the FIFO fully causes timeout for some reason
> +	 * at least on spi2 on A10s */

This is not the proper comment style and generate a warning with
checkpatch, please fix that (and merge the comment with the previous
comment).

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/70e12939/attachment.sig>

From maxime.ripard at free-electrons.com  Mon May 30 01:37:45 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 30 May 2016 10:37:45 +0200
Subject: [PATCH 3/5] spi: sunxi: expose maximum transfer size limit
In-Reply-To: <5fffb7eca6f4b70853d92be2403595d6d06bede7.1464130597.git.hramrach@gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
 <5fffb7eca6f4b70853d92be2403595d6d06bede7.1464130597.git.hramrach@gmail.com>
Message-ID: <20160530083745.GG4247@lukather>

On Thu, May 26, 2016 at 07:25:24PM -0000, Michal Suchanek wrote:
> The sun4i spi hardware can trasfer at most 63 bytes of data without DMA
> support so report the limitation. Same on sun6i.

Is it? Is there timeouts on the A31 and later SoCs?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/4739a050/attachment.sig>

From weiqing.kong at mediatek.com  Mon May 30 01:41:49 2016
From: weiqing.kong at mediatek.com (Weiqing Kong)
Date: Mon, 30 May 2016 16:41:49 +0800
Subject: [PATCH RESEND 0/3] Support Mediatek Soc MT2701 disp pwm
Message-ID: <1464597712-5399-1-git-send-email-weiqing.kong@mediatek.com>

Sorry for sending many times, because of company
permission settings, many people and groups can't
receive these patches before.

These series patches modify pwm-mtk-disp.c
and dts/dtsi config to support MT2701 disp pwm.

Weiqing Kong (3):
  dt-bindings: pwm: Add MediaTek display PWM bindings
  pwm: Add MediaTek MT2701 display PWM driver support
  dts: Add disp bls dsti and dts config for MT2701

 .../devicetree/bindings/pwm/pwm-mtk-disp.txt       |  5 +-
 arch/arm/boot/dts/mt2701-evb.dts                   | 29 +++++++
 arch/arm/boot/dts/mt2701.dtsi                      |  9 +++
 drivers/pwm/pwm-mtk-disp.c                         | 89 +++++++++++++++++-----
 4 files changed, 113 insertions(+), 19 deletions(-)

-- 
1.8.1.1.dirty



From weiqing.kong at mediatek.com  Mon May 30 01:41:50 2016
From: weiqing.kong at mediatek.com (Weiqing Kong)
Date: Mon, 30 May 2016 16:41:50 +0800
Subject: [PATCH 1/3] dt-bindings: pwm: Add MediaTek display PWM bindings
In-Reply-To: <1464597712-5399-1-git-send-email-weiqing.kong@mediatek.com>
References: <1464597712-5399-1-git-send-email-weiqing.kong@mediatek.com>
Message-ID: <1464597712-5399-2-git-send-email-weiqing.kong@mediatek.com>

Add MT2701 compatible string.

Signed-off-by: Weiqing Kong <weiqing.kong at mediatek.com>
---
 Documentation/devicetree/bindings/pwm/pwm-mtk-disp.txt | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/pwm/pwm-mtk-disp.txt b/Documentation/devicetree/bindings/pwm/pwm-mtk-disp.txt
index f8f59ba..f2f2fa9 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-mtk-disp.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-mtk-disp.txt
@@ -1,9 +1,10 @@
 MediaTek display PWM controller
 
 Required properties:
- - compatible: should be "mediatek,<name>-disp-pwm":
-   - "mediatek,mt8173-disp-pwm": found on mt8173 SoC.
+ - compatible: should be like these:
+   - "mediatek,mt2701-disp-bls": found on mt2701 SoC.
    - "mediatek,mt6595-disp-pwm": found on mt6595 SoC.
+   - "mediatek,mt8173-disp-pwm": found on mt8173 SoC.
  - reg: physical base address and length of the controller's registers.
  - #pwm-cells: must be 2. See pwm.txt in this directory for a description of
    the cell format.
-- 
1.8.1.1.dirty



From weiqing.kong at mediatek.com  Mon May 30 01:41:51 2016
From: weiqing.kong at mediatek.com (Weiqing Kong)
Date: Mon, 30 May 2016 16:41:51 +0800
Subject: [PATCH 2/3] pwm: Add MediaTek MT2701 display PWM driver support
In-Reply-To: <1464597712-5399-1-git-send-email-weiqing.kong@mediatek.com>
References: <1464597712-5399-1-git-send-email-weiqing.kong@mediatek.com>
Message-ID: <1464597712-5399-3-git-send-email-weiqing.kong@mediatek.com>

Use the mtk_pwm_data struction to define different registers
and add MT2701 specific register operations, such as MT2701
doesn't have commit register, needs to disable double buffer
before writing register, and needs to select manual mode
and use PWM_PERIOD/PWM_HIGH_WIDTH.

Signed-off-by: Weiqing Kong <weiqing.kong at mediatek.com>
---
 drivers/pwm/pwm-mtk-disp.c | 89 +++++++++++++++++++++++++++++++++++++---------
 1 file changed, 72 insertions(+), 17 deletions(-)

diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c
index 0ad3385..03b9c9e 100644
--- a/drivers/pwm/pwm-mtk-disp.c
+++ b/drivers/pwm/pwm-mtk-disp.c
@@ -18,33 +18,44 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pwm.h>
 #include <linux/slab.h>
 
 #define DISP_PWM_EN		0x00
-#define PWM_ENABLE_MASK		BIT(0)
 
 #define DISP_PWM_COMMIT		0x08
 #define PWM_COMMIT_MASK		BIT(0)
 
-#define DISP_PWM_CON_0		0x10
 #define PWM_CLKDIV_SHIFT	16
 #define PWM_CLKDIV_MAX		0x3ff
 #define PWM_CLKDIV_MASK		(PWM_CLKDIV_MAX << PWM_CLKDIV_SHIFT)
 
-#define DISP_PWM_CON_1		0x14
 #define PWM_PERIOD_BIT_WIDTH	12
 #define PWM_PERIOD_MASK		((1 << PWM_PERIOD_BIT_WIDTH) - 1)
 
 #define PWM_HIGH_WIDTH_SHIFT	16
 #define PWM_HIGH_WIDTH_MASK	(0x1fff << PWM_HIGH_WIDTH_SHIFT)
 
+#define MT2701_PWM_MANUAL_SEL_MASK	BIT(1)
+#define MT2701_PWM_BLS_DEBUG		0xb0
+#define MT2701_PWM_BLS_DEBUG_MASK	0x3
+
+struct mtk_pwm_data {
+	unsigned int enable_bit;
+	unsigned int con0;
+	unsigned int con0_sel;
+	unsigned int con1;
+	bool have_commit_reg;
+};
+
 struct mtk_disp_pwm {
 	struct pwm_chip chip;
 	struct clk *clk_main;
 	struct clk *clk_mm;
 	void __iomem *base;
+	const struct mtk_pwm_data *data;
 };
 
 static inline struct mtk_disp_pwm *to_mtk_disp_pwm(struct pwm_chip *chip)
@@ -106,12 +117,18 @@ static int mtk_disp_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 		return err;
 	}
 
-	mtk_disp_pwm_update_bits(mdp, DISP_PWM_CON_0, PWM_CLKDIV_MASK,
+	mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
+				 PWM_CLKDIV_MASK,
 				 clk_div << PWM_CLKDIV_SHIFT);
-	mtk_disp_pwm_update_bits(mdp, DISP_PWM_CON_1,
-				 PWM_PERIOD_MASK | PWM_HIGH_WIDTH_MASK, value);
-	mtk_disp_pwm_update_bits(mdp, DISP_PWM_COMMIT, PWM_COMMIT_MASK, 1);
-	mtk_disp_pwm_update_bits(mdp, DISP_PWM_COMMIT, PWM_COMMIT_MASK, 0);
+	mtk_disp_pwm_update_bits(mdp, mdp->data->con1,
+				 PWM_PERIOD_MASK | PWM_HIGH_WIDTH_MASK,
+				 value);
+	if (mdp->data->have_commit_reg) {
+		mtk_disp_pwm_update_bits(mdp, DISP_PWM_COMMIT,
+					 PWM_COMMIT_MASK, 0x1);
+		mtk_disp_pwm_update_bits(mdp, DISP_PWM_COMMIT,
+					 PWM_COMMIT_MASK, 0x0);
+	}
 
 	clk_disable(mdp->clk_mm);
 	clk_disable(mdp->clk_main);
@@ -134,7 +151,9 @@ static int mtk_disp_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 		return err;
 	}
 
-	mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, PWM_ENABLE_MASK, 1);
+	mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN,
+				 mdp->data->enable_bit,
+				 mdp->data->enable_bit);
 
 	return 0;
 }
@@ -143,7 +162,8 @@ static void mtk_disp_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 	struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
 
-	mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, PWM_ENABLE_MASK, 0);
+	mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN,
+				 mdp->data->enable_bit, 0x0);
 
 	clk_disable(mdp->clk_mm);
 	clk_disable(mdp->clk_main);
@@ -156,12 +176,41 @@ static const struct pwm_ops mtk_disp_pwm_ops = {
 	.owner = THIS_MODULE,
 };
 
+static const struct mtk_pwm_data mt8173_pwm_data = {
+	.enable_bit = BIT(0),
+	.con0 = 0x10,
+	.con0_sel = 0x0,
+	.con1 = 0x14,
+	.have_commit_reg = true,
+};
+
+static const struct mtk_pwm_data mt2701_pwm_data = {
+	.enable_bit = BIT(16),
+	.con0 = 0xa8,
+	.con0_sel = 0x2,
+	.con1 = 0xac,
+	.have_commit_reg = false,
+};
+
+static const struct of_device_id mtk_disp_pwm_of_match[] = {
+	{ .compatible = "mediatek,mt2701-disp-bls", .data = &mt2701_pwm_data},
+	{ .compatible = "mediatek,mt6595-disp-pwm", .data = &mt8173_pwm_data},
+	{ .compatible = "mediatek,mt8173-disp-pwm", .data = &mt8173_pwm_data},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_pwm_of_match);
+
 static int mtk_disp_pwm_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *id;
 	struct mtk_disp_pwm *mdp;
 	struct resource *r;
 	int ret;
 
+	id = of_match_device(mtk_disp_pwm_of_match, &pdev->dev);
+	if (!id)
+		return -EINVAL;
+
 	mdp = devm_kzalloc(&pdev->dev, sizeof(*mdp), GFP_KERNEL);
 	if (!mdp)
 		return -ENOMEM;
@@ -191,6 +240,7 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev)
 	mdp->chip.ops = &mtk_disp_pwm_ops;
 	mdp->chip.base = -1;
 	mdp->chip.npwm = 1;
+	mdp->data = id->data;
 
 	ret = pwmchip_add(&mdp->chip);
 	if (ret < 0) {
@@ -200,6 +250,18 @@ static int mtk_disp_pwm_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, mdp);
 
+	/*
+	 * For MT2701, disable double buffer before writing register
+	 * and select manual mode and use PWM_PERIOD/PWM_HIGH_WIDTH.
+	 */
+	if (!mdp->data->have_commit_reg) {
+		mtk_disp_pwm_update_bits(mdp, MT2701_PWM_BLS_DEBUG,
+					 MT2701_PWM_BLS_DEBUG_MASK, 0x3);
+		mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
+					 MT2701_PWM_MANUAL_SEL_MASK,
+					 mdp->data->con0_sel);
+	}
+
 	return 0;
 
 disable_clk_mm:
@@ -221,13 +283,6 @@ static int mtk_disp_pwm_remove(struct platform_device *pdev)
 	return ret;
 }
 
-static const struct of_device_id mtk_disp_pwm_of_match[] = {
-	{ .compatible = "mediatek,mt8173-disp-pwm" },
-	{ .compatible = "mediatek,mt6595-disp-pwm" },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, mtk_disp_pwm_of_match);
-
 static struct platform_driver mtk_disp_pwm_driver = {
 	.driver = {
 		.name = "mediatek-disp-pwm",
-- 
1.8.1.1.dirty



From weiqing.kong at mediatek.com  Mon May 30 01:41:52 2016
From: weiqing.kong at mediatek.com (Weiqing Kong)
Date: Mon, 30 May 2016 16:41:52 +0800
Subject: [PATCH 3/3] dts: Add disp bls dsti and dts config for MT2701
In-Reply-To: <1464597712-5399-1-git-send-email-weiqing.kong@mediatek.com>
References: <1464597712-5399-1-git-send-email-weiqing.kong@mediatek.com>
Message-ID: <1464597712-5399-4-git-send-email-weiqing.kong@mediatek.com>

Signed-off-by: Weiqing Kong <weiqing.kong at mediatek.com>
---
 arch/arm/boot/dts/mt2701-evb.dts | 29 +++++++++++++++++++++++++++++
 arch/arm/boot/dts/mt2701.dtsi    |  9 +++++++++
 2 files changed, 38 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701-evb.dts b/arch/arm/boot/dts/mt2701-evb.dts
index 082ca88..6d572f4 100644
--- a/arch/arm/boot/dts/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mt2701-evb.dts
@@ -22,6 +22,35 @@
 	memory {
 		reg = <0 0x80000000 0 0x40000000>;
 	};
+
+	backlight_lcd: backlight_lcd {
+		compatible = "pwm-backlight";
+		pwms = <&disp_bls 0 100000>;
+		brightness-levels = <
+			  0  16  32  48  64  80  96 112
+			128 144 160 176 192 208 224 240
+			255
+		>;
+		default-brightness-level = <9>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm_bls_gpio>;
+	};
+};
+
+&disp_bls {
+	status = "okay";
+};
+
+&mmsys {
+	status = "okay";
+};
+
+&pio {
+	pwm_bls_gpio: pwm_bls_gpio {
+		pins_cmd_dat {
+			pinmux = <MT2701_PIN_208_AUD_EXT_CK1__FUNC_DISP_PWM>;
+		};
+	};
 };
 
 &uart0 {
diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 42d5a37..dae55d6 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -234,6 +234,15 @@
 		status = "disabled";
 	};
 
+	disp_bls: dispsys at 1400a000 {
+		compatible = "mediatek,mt2701-disp-bls";
+		reg = <0 0x1400a000 0 0x1000>;
+		#pwm-cells = <2>;
+		clocks = <&mmsys CLK_MM_MDP_BLS_26M>, <&mmsys CLK_MM_DISP_BLS>;
+		clock-names = "main", "mm";
+		status = "disabled";
+	};
+
 	imgsys: syscon at 15000000 {
 		compatible = "mediatek,mt2701-imgsys", "syscon";
 		reg = <0 0x15000000 0 0x1000>;
-- 
1.8.1.1.dirty



From peter.ujfalusi at ti.com  Mon May 30 01:55:08 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:08 +0300
Subject: [PATCH v1 00/14] clk/mfd/ASoC/ARM: OMAP4/5: McPDM/twl6040 pdmclk
 support
Message-ID: <20160530085522.30398-1-peter.ujfalusi@ti.com>

Hi,

Changes since v1:
- Added Rob's Acked-by to patch 5 and 14
- Check the return value of clk_prepare_enable() calls in the last patch

this is something I wanted to do for a long time...

First of all: sorry for the cross domain series. I did tested alone all the
domain patches and they are not causing any regression. When they come together
we will have ability to control the pdmclk needed by McPDM.

CLK patches:
The driver was w/o DT support and needed some cleanup so we can use the driver.
I have also renamed it to twl6040-pdmclk from twl6040-clk to be precise.

MFD patches:
The regmap_sync() was not working since the twl6040 does not support bulk access
and now we are going to create the needed child for the pdmclk.

ARM patches:
Updatding the board DTS files and add the needed lines for the pdmclk.

ASoC patches:
The machine driver needs to select the twl6040-clk driver as it will be used
by the omap-mcpdm.
I needed to do some cleanup and add also suspend/resume support before adding
the code for pdmclk handling since I don't want to keep the twl6040 powered on
when the board is suspended. At the moment it is not possible to do true
dynamic twl6040 power up/down due to pop noises, but I will be looking at that
later.
The driver in the future will fail if it is not able to get the pdmclk to avoid
kernel crash (McPDM registers are not accessible when pdmclk is not available).

I have tested the patches by domain and also in all (I hope) permutation they
could be. I have not experienced any regression.

Regards,
Peter
---
Peter Ujfalusi (14):
  clk: twl6040: Correct clk_ops
  clk: twl6040: Register the clock as of_clk_provider
  clk: twl6040: Rename the driver and use consistent names in the code
  mfd: twl6040: The chip does not support bulk access
  mfd: twl6040: Register child device for twl6040-pdmclk
  ARM: dts: omap5-board-common: Add pdmclk binding for audio
  ARM: dts: omap4-panda-common: Add pdmclk binding for audio
  ARM: dts: omap4-sdp: Add pdmclk binding for audio
  ARM: dts: omap4-var-som-om44: Add pdmclk binding for audio
  ARM: dts: omap4-duovero: Add pdmclk binding for audio
  ASoC: omap: Kconfig: SND_OMAP_SOC_OMAP_ABE_TWL6040 to select
    CLK_TWL6040
  ASoC: omap-mcpdm: Move the WD enable write inside
    omap_mcpdm_open_streams()
  ASoC: omap-mcpdm: Support for suspend resume
  ASoC: omap-mcpdm: Add support for pdmclk clock handling

 Documentation/devicetree/bindings/mfd/twl6040.txt  |  1 +
 .../devicetree/bindings/sound/omap-mcpdm.txt       | 10 +++
 arch/arm/boot/dts/omap4-duovero.dtsi               |  5 ++
 arch/arm/boot/dts/omap4-panda-common.dtsi          |  5 ++
 arch/arm/boot/dts/omap4-sdp.dts                    |  5 ++
 arch/arm/boot/dts/omap4-var-som-om44.dtsi          |  5 ++
 arch/arm/boot/dts/omap5-board-common.dtsi          |  5 ++
 drivers/clk/clk-twl6040.c                          | 80 ++++++++++++---------
 drivers/mfd/twl6040.c                              |  6 ++
 include/linux/mfd/twl6040.h                        |  2 +-
 sound/soc/omap/Kconfig                             |  1 +
 sound/soc/omap/omap-mcpdm.c                        | 84 ++++++++++++++++++++--
 12 files changed, 170 insertions(+), 39 deletions(-)

-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:09 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:09 +0300
Subject: [PATCH v1 01/14] clk: twl6040: Correct clk_ops
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-2-peter.ujfalusi@ti.com>

Since the drover only supports prepare callbacks, the use of is_enabled is
not correct, it should be handling is_prepared.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 drivers/clk/clk-twl6040.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c
index 697c66757400..e167e0bbaff5 100644
--- a/drivers/clk/clk-twl6040.c
+++ b/drivers/clk/clk-twl6040.c
@@ -34,7 +34,7 @@ struct twl6040_clk {
 	int enabled;
 };
 
-static int twl6040_bitclk_is_enabled(struct clk_hw *hw)
+static int twl6040_bitclk_is_prepared(struct clk_hw *hw)
 {
 	struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
 						       mcpdm_fclk);
@@ -66,7 +66,7 @@ static void twl6040_bitclk_unprepare(struct clk_hw *hw)
 }
 
 static const struct clk_ops twl6040_mcpdm_ops = {
-	.is_enabled = twl6040_bitclk_is_enabled,
+	.is_prepared = twl6040_bitclk_is_prepared,
 	.prepare = twl6040_bitclk_prepare,
 	.unprepare = twl6040_bitclk_unprepare,
 };
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:10 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:10 +0300
Subject: [PATCH v1 02/14] clk: twl6040: Register the clock as of_clk_provider
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-3-peter.ujfalusi@ti.com>

In order ot be able to use the pdmclk clock via DT it need to be registered
as of_clk_provide.
Since the twl6040 clock driver does not have it's own DT node, use the
parent's node for registering.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 drivers/clk/clk-twl6040.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c
index e167e0bbaff5..6a2dbe6a1627 100644
--- a/drivers/clk/clk-twl6040.c
+++ b/drivers/clk/clk-twl6040.c
@@ -95,7 +95,8 @@ static int twl6040_clk_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, clkdata);
 
-	return 0;
+	return of_clk_add_provider(pdev->dev.parent->of_node,
+				   of_clk_src_simple_get, clkdata->clk);
 }
 
 static struct platform_driver twl6040_clk_driver = {
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:12 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:12 +0300
Subject: [PATCH v1 04/14] mfd: twl6040: The chip does not support bulk access
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-5-peter.ujfalusi@ti.com>

Bulk access is not working with twl6040, we need to use single register
access. Bulk access would happen when we try to sync the regcache after
power on.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 drivers/mfd/twl6040.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index f3dcf3a85e84..2596546553aa 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -608,6 +608,7 @@ static const struct regmap_config twl6040_regmap_config = {
 	.writeable_reg = twl6040_writeable_reg,
 
 	.cache_type = REGCACHE_RBTREE,
+	.use_single_rw = true,
 };
 
 static const struct regmap_irq twl6040_irqs[] = {
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:13 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:13 +0300
Subject: [PATCH v1 05/14] mfd: twl6040: Register child device for
 twl6040-pdmclk
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-6-peter.ujfalusi@ti.com>

The McPDM in OMAP4/5 is using the pdmclk from twl6040 as functional clock.
The twl6040-pdmclk driver provides a clock which can be used to make sure
that the pdmclk is active when the McPDM is in use.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 Documentation/devicetree/bindings/mfd/twl6040.txt | 1 +
 drivers/mfd/twl6040.c                             | 5 +++++
 include/linux/mfd/twl6040.h                       | 2 +-
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mfd/twl6040.txt b/Documentation/devicetree/bindings/mfd/twl6040.txt
index e6afdfa3543d..9a98ee7c323d 100644
--- a/Documentation/devicetree/bindings/mfd/twl6040.txt
+++ b/Documentation/devicetree/bindings/mfd/twl6040.txt
@@ -12,6 +12,7 @@ Required properties:
 - interrupt-parent: The parent interrupt controller
 - gpio-controller:
 - #gpio-cells = <1>: twl6040 provides GPO lines.
+- #clock-cells = <0>; twl6040 is a provider of pdmclk which is used by McPDM
 - twl6040,audpwron-gpio: Power on GPIO line for the twl6040
 
 - vio-supply: Regulator for the twl6040 VIO supply
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index 2596546553aa..873628a1bd79 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -782,6 +782,11 @@ static int twl6040_probe(struct i2c_client *client,
 	cell->name = "twl6040-gpo";
 	children++;
 
+	/* PDM clock support  */
+	cell = &twl6040->cells[children];
+	cell->name = "twl6040-pdmclk";
+	children++;
+
 	/* The chip is powered down so mark regmap to cache only and dirty */
 	regcache_cache_only(twl6040->regmap, true);
 	regcache_mark_dirty(twl6040->regmap);
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h
index 8015db974157..ef0bb07c3f3d 100644
--- a/include/linux/mfd/twl6040.h
+++ b/include/linux/mfd/twl6040.h
@@ -168,7 +168,7 @@
 #define TWL6040_VIBROCDET		0x20
 #define TWL6040_TSHUTDET                0x40
 
-#define TWL6040_CELLS			3
+#define TWL6040_CELLS			4
 
 #define TWL6040_REV_ES1_0		0x00
 #define TWL6040_REV_ES1_1		0x01 /* Rev ES1.1 and ES1.2 */
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:11 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:11 +0300
Subject: [PATCH v1 03/14] clk: twl6040: Rename the driver and use consistent
 names in the code
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-4-peter.ujfalusi@ti.com>

The driver is to provide the functional clock to OMAP4/5 McPDM. The clock
is named as pdmclk in the documentations so change the function names,
structure names and variables to align with this.
At the same time rename the driver from "twl6040-clk" to "twl6040-pdmclk".
This can be done w/o regression since the clock driver is not in use at
the moment, the MFD core driver is not even registering the device for it.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 drivers/clk/clk-twl6040.c | 77 +++++++++++++++++++++++++++--------------------
 1 file changed, 45 insertions(+), 32 deletions(-)

diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c
index 6a2dbe6a1627..c98b1ec76f54 100644
--- a/drivers/clk/clk-twl6040.c
+++ b/drivers/clk/clk-twl6040.c
@@ -26,60 +26,73 @@
 #include <linux/mfd/twl6040.h>
 #include <linux/clk-provider.h>
 
-struct twl6040_clk {
+struct twl6040_pdmclk {
 	struct twl6040 *twl6040;
 	struct device *dev;
-	struct clk_hw mcpdm_fclk;
+	struct clk_hw pdmclk_hw;
 	struct clk *clk;
 	int enabled;
 };
 
-static int twl6040_bitclk_is_prepared(struct clk_hw *hw)
+static int twl6040_pdmclk_is_prepared(struct clk_hw *hw)
 {
-	struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
-						       mcpdm_fclk);
-	return twl6040_clk->enabled;
+	struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk,
+						     pdmclk_hw);
+
+	return pdmclk->enabled;
 }
 
-static int twl6040_bitclk_prepare(struct clk_hw *hw)
+static int twl6040_pdmclk_prepare(struct clk_hw *hw)
 {
-	struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
-						       mcpdm_fclk);
+	struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk,
+						     pdmclk_hw);
 	int ret;
 
-	ret = twl6040_power(twl6040_clk->twl6040, 1);
+	ret = twl6040_power(pdmclk->twl6040, 1);
 	if (!ret)
-		twl6040_clk->enabled = 1;
+		pdmclk->enabled = 1;
 
 	return ret;
 }
 
-static void twl6040_bitclk_unprepare(struct clk_hw *hw)
+static void twl6040_pdmclk_unprepare(struct clk_hw *hw)
 {
-	struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
-						       mcpdm_fclk);
+	struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk,
+						     pdmclk_hw);
 	int ret;
 
-	ret = twl6040_power(twl6040_clk->twl6040, 0);
+	ret = twl6040_power(pdmclk->twl6040, 0);
 	if (!ret)
-		twl6040_clk->enabled = 0;
+		pdmclk->enabled = 0;
+
+}
+
+static unsigned long twl6040_pdmclk_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk,
+						     pdmclk_hw);
+
+	return twl6040_get_sysclk(pdmclk->twl6040);
 }
 
-static const struct clk_ops twl6040_mcpdm_ops = {
-	.is_prepared = twl6040_bitclk_is_prepared,
-	.prepare = twl6040_bitclk_prepare,
-	.unprepare = twl6040_bitclk_unprepare,
+static const struct clk_ops twl6040_pdmclk_ops = {
+	.is_prepared = twl6040_pdmclk_is_prepared,
+	.prepare = twl6040_pdmclk_prepare,
+	.unprepare = twl6040_pdmclk_unprepare,
+	.recalc_rate = twl6040_pdmclk_recalc_rate,
 };
 
-static struct clk_init_data wm831x_clkout_init = {
-	.name = "mcpdm_fclk",
-	.ops = &twl6040_mcpdm_ops,
+static struct clk_init_data twl6040_pdmclk_init = {
+	.name = "pdmclk",
+	.ops = &twl6040_pdmclk_ops,
+	.flags = CLK_GET_RATE_NOCACHE,
 };
 
-static int twl6040_clk_probe(struct platform_device *pdev)
+static int twl6040_pdmclk_probe(struct platform_device *pdev)
 {
 	struct twl6040 *twl6040 = dev_get_drvdata(pdev->dev.parent);
-	struct twl6040_clk *clkdata;
+	struct twl6040_pdmclk *clkdata;
 
 	clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);
 	if (!clkdata)
@@ -88,8 +101,8 @@ static int twl6040_clk_probe(struct platform_device *pdev)
 	clkdata->dev = &pdev->dev;
 	clkdata->twl6040 = twl6040;
 
-	clkdata->mcpdm_fclk.init = &wm831x_clkout_init;
-	clkdata->clk = devm_clk_register(&pdev->dev, &clkdata->mcpdm_fclk);
+	clkdata->pdmclk_hw.init = &twl6040_pdmclk_init;
+	clkdata->clk = devm_clk_register(&pdev->dev, &clkdata->pdmclk_hw);
 	if (IS_ERR(clkdata->clk))
 		return PTR_ERR(clkdata->clk);
 
@@ -99,16 +112,16 @@ static int twl6040_clk_probe(struct platform_device *pdev)
 				   of_clk_src_simple_get, clkdata->clk);
 }
 
-static struct platform_driver twl6040_clk_driver = {
+static struct platform_driver twl6040_pdmclk_driver = {
 	.driver = {
-		.name = "twl6040-clk",
+		.name = "twl6040-pdmclk",
 	},
-	.probe = twl6040_clk_probe,
+	.probe = twl6040_pdmclk_probe,
 };
 
-module_platform_driver(twl6040_clk_driver);
+module_platform_driver(twl6040_pdmclk_driver);
 
 MODULE_DESCRIPTION("TWL6040 clock driver for McPDM functional clock");
 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi at ti.com>");
-MODULE_ALIAS("platform:twl6040-clk");
+MODULE_ALIAS("platform:twl6040-pdmclk");
 MODULE_LICENSE("GPL");
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:14 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:14 +0300
Subject: [PATCH v1 06/14] ARM: dts: omap5-board-common: Add pdmclk binding for
 audio
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-7-peter.ujfalusi@ti.com>

The twl6040 codec is generating the pdmclk, which is used by the McPDM as
functional clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap5-board-common.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi
index 19efaa079797..63d0352d068d 100644
--- a/arch/arm/boot/dts/omap5-board-common.dtsi
+++ b/arch/arm/boot/dts/omap5-board-common.dtsi
@@ -637,6 +637,7 @@
 
 	twl6040: twl at 4b {
 		compatible = "ti,twl6040";
+		#clock-cells = <0>;
 		reg = <0x4b>;
 
 		pinctrl-names = "default";
@@ -658,6 +659,10 @@
 &mcpdm {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcpdm_pins>;
+
+	clocks = <&twl6040>;
+	clock-names = "pdmclk";
+
 	status = "okay";
 };
 
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:15 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:15 +0300
Subject: [PATCH v1 07/14] ARM: dts: omap4-panda-common: Add pdmclk binding for
 audio
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-8-peter.ujfalusi@ti.com>

The twl6040 codec is generating the pdmclk, which is used by the McPDM as
functional clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap4-panda-common.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi
index df2e356ec089..e1d606f64cb7 100644
--- a/arch/arm/boot/dts/omap4-panda-common.dtsi
+++ b/arch/arm/boot/dts/omap4-panda-common.dtsi
@@ -376,6 +376,7 @@
 
 	twl6040: twl at 4b {
 		compatible = "ti,twl6040";
+		#clock-cells = <0>;
 		reg = <0x4b>;
 
 		pinctrl-names = "default";
@@ -479,6 +480,10 @@
 &mcpdm {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcpdm_pins>;
+
+	clocks = <&twl6040>;
+	clock-names = "pdmclk";
+
 	status = "okay";
 };
 
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:17 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:17 +0300
Subject: [PATCH v1 09/14] ARM: dts: omap4-var-som-om44: Add pdmclk binding for
 audio
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-10-peter.ujfalusi@ti.com>

The twl6040 codec is generating the pdmclk, which is used by the McPDM as
functional clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap4-var-som-om44.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap4-var-som-om44.dtsi b/arch/arm/boot/dts/omap4-var-som-om44.dtsi
index a17997f4e9aa..873cfc87260c 100644
--- a/arch/arm/boot/dts/omap4-var-som-om44.dtsi
+++ b/arch/arm/boot/dts/omap4-var-som-om44.dtsi
@@ -189,6 +189,7 @@
 
 	twl6040: twl at 4b {
 		compatible = "ti,twl6040";
+		#clock-cells = <0>;
 		reg = <0x4b>;
 
 		pinctrl-names = "default";
@@ -252,6 +253,10 @@
 &mcpdm {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcpdm_pins>;
+
+	clocks = <&twl6040>;
+	clock-names = "pdmclk";
+
 	status = "okay";
 };
 
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:16 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:16 +0300
Subject: [PATCH v1 08/14] ARM: dts: omap4-sdp: Add pdmclk binding for audio
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-9-peter.ujfalusi@ti.com>

The twl6040 codec is generating the pdmclk, which is used by the McPDM as
functional clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap4-sdp.dts | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
index aae513265dc2..7e6cd2d8ed5d 100644
--- a/arch/arm/boot/dts/omap4-sdp.dts
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -367,6 +367,7 @@
 
 	twl6040: twl at 4b {
 		compatible = "ti,twl6040";
+		#clock-cells = <0>;
 		reg = <0x4b>;
 
 		pinctrl-names = "default";
@@ -620,6 +621,10 @@
 &mcpdm {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcpdm_pins>;
+
+	clocks = <&twl6040>;
+	clock-names = "pdmclk";
+
 	status = "okay";
 };
 
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:18 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:18 +0300
Subject: [PATCH v1 10/14] ARM: dts: omap4-duovero: Add pdmclk binding for audio
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-11-peter.ujfalusi@ti.com>

The twl6040 codec is generating the pdmclk, which is used by the McPDM as
functional clock.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 arch/arm/boot/dts/omap4-duovero.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/omap4-duovero.dtsi b/arch/arm/boot/dts/omap4-duovero.dtsi
index f2a94fa62552..a90b582e4c3f 100644
--- a/arch/arm/boot/dts/omap4-duovero.dtsi
+++ b/arch/arm/boot/dts/omap4-duovero.dtsi
@@ -177,6 +177,7 @@
 
 	twl6040: twl at 4b {
 		compatible = "ti,twl6040";
+		#clock-cells = <0>;
 		reg = <0x4b>;
 		interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;		/* IRQ_SYS_2N cascaded to gic */
 		ti,audpwron-gpio = <&gpio6 0 GPIO_ACTIVE_HIGH>;		/* gpio_160 */
@@ -207,6 +208,10 @@
 &mcpdm {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcpdm_pins>;
+
+	clocks = <&twl6040>;
+	clock-names = "pdmclk";
+
 	status = "okay";
 };
 
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:19 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:19 +0300
Subject: [PATCH v1 11/14] ASoC: omap: Kconfig: SND_OMAP_SOC_OMAP_ABE_TWL6040
 to select CLK_TWL6040
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-12-peter.ujfalusi@ti.com>

The pdmclk is needed for McPDM. It is generated by twl6040.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 sound/soc/omap/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 5520273724ae..347705c04db1 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -119,6 +119,7 @@ config SND_OMAP_SOC_OMAP_ABE_TWL6040
 	select SND_SOC_TWL6040
 	select SND_SOC_DMIC
 	select COMMON_CLK_PALMAS if (SOC_OMAP5 && MFD_PALMAS)
+	select CLK_TWL6040
 	help
 	  Say Y if you want to add support for SoC audio on OMAP boards using
 	  ABE and twl6040 codec. This driver currently supports:
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:21 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:21 +0300
Subject: [PATCH v1 13/14] ASoC: omap-mcpdm: Support for suspend resume
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-14-peter.ujfalusi@ti.com>

Implement ASoC's suspend and resume callbacks.
Since McPDM does not use pcm_trigger for start and stop of the stream due
to strict sequencing needs with the twl6040, the callbacks will stop and
restart the McPDM in case the board suspended during audio activity.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 sound/soc/omap/omap-mcpdm.c | 46 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 11bd07cdce22..74d6e6fdcfd0 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -66,6 +66,9 @@ struct omap_mcpdm {
 	/* McPDM needs to be restarted due to runtime reconfiguration */
 	bool restart;
 
+	/* pm state for suspend/resume handling */
+	int pm_active_count;
+
 	struct snd_dmaengine_dai_dma_data dma_data[2];
 };
 
@@ -422,12 +425,55 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int omap_mcpdm_suspend(struct snd_soc_dai *dai)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+	if (dai->active) {
+		omap_mcpdm_stop(mcpdm);
+		omap_mcpdm_close_streams(mcpdm);
+	}
+
+	mcpdm->pm_active_count = 0;
+	while (pm_runtime_active(mcpdm->dev)) {
+		pm_runtime_put_sync(mcpdm->dev);
+		mcpdm->pm_active_count++;
+	}
+
+	return 0;
+}
+
+static int omap_mcpdm_resume(struct snd_soc_dai *dai)
+{
+	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+	if (mcpdm->pm_active_count) {
+		while (mcpdm->pm_active_count--)
+			pm_runtime_get_sync(mcpdm->dev);
+
+		if (dai->active) {
+			omap_mcpdm_open_streams(mcpdm);
+			omap_mcpdm_start(mcpdm);
+		}
+	}
+
+
+	return 0;
+}
+#else
+#define omap_mcpdm_suspend NULL
+#define omap_mcpdm_resume NULL
+#endif
+
 #define OMAP_MCPDM_RATES	(SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 #define OMAP_MCPDM_FORMATS	SNDRV_PCM_FMTBIT_S32_LE
 
 static struct snd_soc_dai_driver omap_mcpdm_dai = {
 	.probe = omap_mcpdm_probe,
 	.remove = omap_mcpdm_remove,
+	.suspend = omap_mcpdm_suspend,
+	.resume = omap_mcpdm_resume,
 	.probe_order = SND_SOC_COMP_ORDER_LATE,
 	.remove_order = SND_SOC_COMP_ORDER_EARLY,
 	.playback = {
-- 
2.8.3



From peter.ujfalusi at ti.com  Mon May 30 01:55:20 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:20 +0300
Subject: [PATCH v1 12/14] ASoC: omap-mcpdm: Move the WD enable write inside
 omap_mcpdm_open_streams()
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-13-peter.ujfalusi@ti.com>

The DS4_WD_EN bit is only touched before calling omap_mcpdm_open_streams().
Move it inside of that function for simplicity.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
---
 sound/soc/omap/omap-mcpdm.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index b837265ac3e9..11bd07cdce22 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -173,6 +173,10 @@ static inline int omap_mcpdm_active(struct omap_mcpdm *mcpdm)
  */
 static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm)
 {
+	u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+	omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl | MCPDM_WD_EN);
+
 	omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_SET,
 			MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL |
 			MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
@@ -258,12 +262,9 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
 
 	mutex_lock(&mcpdm->mutex);
 
-	if (!dai->active) {
-		u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
-
-		omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl | MCPDM_WD_EN);
+	if (!dai->active)
 		omap_mcpdm_open_streams(mcpdm);
-	}
+
 	mutex_unlock(&mcpdm->mutex);
 
 	return 0;
-- 
2.8.3



From hramrach at gmail.com  Mon May 30 01:57:10 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: Mon, 30 May 2016 10:57:10 +0200
Subject: [PATCH 3/5] spi: sunxi: expose maximum transfer size limit
In-Reply-To: <20160530083745.GG4247@lukather>
References: <cover.1464130597.git.hramrach@gmail.com>
 <5fffb7eca6f4b70853d92be2403595d6d06bede7.1464130597.git.hramrach@gmail.com>
 <20160530083745.GG4247@lukather>
Message-ID: <CAOMqctQdbipvvTnF253S4jGDos1crYXk9nuzDcRvy4geeS=GrQ@mail.gmail.com>

Hello,

On 30 May 2016 at 10:37, Maxime Ripard <maxime.ripard at free-electrons.com> wrote:
> On Thu, May 26, 2016 at 07:25:24PM -0000, Michal Suchanek wrote:
>> The sun4i spi hardware can trasfer at most 63 bytes of data without DMA
>> support so report the limitation. Same on sun6i.
>
> Is it? Is there timeouts on the A31 and later SoCs?
>

I have no sun6i hardware to test with.

This is an advisory limit you can query and it better be smaller
rather than unreliable. The hard limit in the driver is still
SUN6I_FIFO_DEPTH (which is 128 bytes on sun6i).

You can test his without any actual SPI device. Unused pins you can
multiplex as SPI suffice.

Thanks

Michal


From peter.ujfalusi at ti.com  Mon May 30 01:55:22 2016
From: peter.ujfalusi at ti.com (Peter Ujfalusi)
Date: Mon, 30 May 2016 11:55:22 +0300
Subject: [PATCH v1 14/14] ASoC: omap-mcpdm: Add support for pdmclk clock
 handling
In-Reply-To: <20160530085522.30398-1-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
Message-ID: <20160530085522.30398-15-peter.ujfalusi@ti.com>

McPDM module receives it's functional clock from external source. This
clock is the pdmclk provided by the twl6040 audio IC. If the clock is not
available all register accesses to McPDM fails and the module is not
operational.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/sound/omap-mcpdm.txt       | 10 ++++++++
 sound/soc/omap/omap-mcpdm.c                        | 27 ++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/omap-mcpdm.txt b/Documentation/devicetree/bindings/sound/omap-mcpdm.txt
index 0741dff048dd..6f6c2f8e908d 100644
--- a/Documentation/devicetree/bindings/sound/omap-mcpdm.txt
+++ b/Documentation/devicetree/bindings/sound/omap-mcpdm.txt
@@ -8,6 +8,8 @@ Required properties:
 - interrupts: Interrupt number for McPDM
 - interrupt-parent: The parent interrupt controller
 - ti,hwmods: Name of the hwmod associated to the McPDM
+- clocks:  phandle for the pdmclk provider, likely <&twl6040>
+- clock-names: Must be "pdmclk"
 
 Example:
 
@@ -19,3 +21,11 @@ mcpdm: mcpdm at 40132000 {
 	interrupt-parent = <&gic>;
 	ti,hwmods = "mcpdm";
 };
+
+In board DTS file the pdmclk needs to be added:
+
+&mcpdm {
+	clocks = <&twl6040>;
+	clock-names = "pdmclk";
+	status = "okay";
+};
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 74d6e6fdcfd0..2d2119e7d094 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -31,6 +31,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/of_device.h>
@@ -54,6 +55,7 @@ struct omap_mcpdm {
 	unsigned long phys_base;
 	void __iomem *io_base;
 	int irq;
+	struct clk *pdmclk;
 
 	struct mutex mutex;
 
@@ -388,6 +390,12 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
 	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 	int ret;
 
+	ret = clk_prepare_enable(mcpdm->pdmclk);
+	if (!ret) {
+		dev_err(mcpdm->dev, "Failed to enable PDMCLK: %d\n", ret);
+		return ret;
+	}
+
 	pm_runtime_enable(mcpdm->dev);
 
 	/* Disable lines while request is ongoing */
@@ -422,6 +430,7 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
 
 	pm_runtime_disable(mcpdm->dev);
 
+	clk_disable_unprepare(mcpdm->pdmclk);
 	return 0;
 }
 
@@ -441,12 +450,21 @@ static int omap_mcpdm_suspend(struct snd_soc_dai *dai)
 		mcpdm->pm_active_count++;
 	}
 
+	clk_disable_unprepare(mcpdm->pdmclk);
+
 	return 0;
 }
 
 static int omap_mcpdm_resume(struct snd_soc_dai *dai)
 {
 	struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+	int ret;
+
+	ret = clk_prepare_enable(mcpdm->pdmclk);
+	if (!ret) {
+		dev_err(mcpdm->dev, "Failed to enable PDMCLK: %d\n", ret);
+		return ret;
+	}
 
 	if (mcpdm->pm_active_count) {
 		while (mcpdm->pm_active_count--)
@@ -541,6 +559,15 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
 
 	mcpdm->dev = &pdev->dev;
 
+	mcpdm->pdmclk = devm_clk_get(&pdev->dev, "pdmclk");
+	if (IS_ERR(mcpdm->pdmclk)) {
+		if (PTR_ERR(mcpdm->pdmclk) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		dev_warn(&pdev->dev, "Error getting pdmclk (%ld)!\n",
+			 PTR_ERR(mcpdm->pdmclk));
+		mcpdm->pdmclk = NULL;
+	}
+
 	ret =  devm_snd_soc_register_component(&pdev->dev,
 					       &omap_mcpdm_component,
 					       &omap_mcpdm_dai, 1);
-- 
2.8.3



From daniel at ffwll.ch  Mon May 30 02:03:31 2016
From: daniel at ffwll.ch (Daniel Vetter)
Date: Mon, 30 May 2016 11:03:31 +0200
Subject: [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm
 master driver
In-Reply-To: <1464514855-108050-2-git-send-email-zourongrong@gmail.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
 <1464514855-108050-2-git-send-email-zourongrong@gmail.com>
Message-ID: <20160530090331.GD27098@phenom.ffwll.local>

On Sun, May 29, 2016 at 05:40:49PM +0800, Rongrong Zou wrote:
> Add DRM master driver for Hisilicon Hibmc SoC which used for
> Out-of-band management. Blow is the general hardware connection,
> both the Hibmc and the host CPU are on the same mother board.
> 
> +----------+       +----------+
> |          | PCIe  |  Hibmc   |
> |host CPU( |<----->| display  |
> |arm64,x86)|       |subsystem |
> +----------+       +----------+
> 
> Signed-off-by: Rongrong Zou <zourongrong at gmail.com>
> Signed-off-by: Jianhua Li <lijianhua at huawei.com>
> ---
>  drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
>  drivers/gpu/drm/hisilicon/Makefile                |   3 +-
>  drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
>  drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 307 ++++++++++++++++++++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  39 +++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 +++++++++++++++
>  9 files changed, 699 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
> 
> diff --git a/drivers/gpu/drm/hisilicon/Kconfig b/drivers/gpu/drm/hisilicon/Kconfig
> index 558c61b..2fd2724 100644
> --- a/drivers/gpu/drm/hisilicon/Kconfig
> +++ b/drivers/gpu/drm/hisilicon/Kconfig
> @@ -2,4 +2,5 @@
>  # hisilicon drm device configuration.
>  # Please keep this list sorted alphabetically
>  
> +source "drivers/gpu/drm/hisilicon/hibmc/Kconfig"
>  source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
> diff --git a/drivers/gpu/drm/hisilicon/Makefile b/drivers/gpu/drm/hisilicon/Makefile
> index e3f6d49..4d7185c 100644
> --- a/drivers/gpu/drm/hisilicon/Makefile
> +++ b/drivers/gpu/drm/hisilicon/Makefile
> @@ -2,4 +2,5 @@
>  # Makefile for hisilicon drm drivers.
>  # Please keep this list sorted alphabetically
>  
> -obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
> +obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/
> +obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
> \ No newline at end of file
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
> new file mode 100644
> index 0000000..1e7810d
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
> @@ -0,0 +1,13 @@
> +config DRM_HISI_HIBMC
> +	tristate "DRM Support for Hisilicon Hibmc"
> +	depends on DRM && PCI
> +	select DRM_KMS_HELPER
> +	select DRM_KMS_FB_HELPER
> +	select DRM_GEM_CMA_HELPER
> +	select DRM_KMS_CMA_HELPER
> +	select FB_SYS_FILLRECT
> +	select FB_SYS_COPYAREA
> +	select FB_SYS_IMAGEBLIT
> +	help
> +	  Choose this option if you have a Hisilicon Hibmc soc chipset.
> +	  If M is selected the module will be called hibmc-drm.
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
> new file mode 100644
> index 0000000..533f9ed
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
> @@ -0,0 +1,4 @@
> +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
> +
> +obj-$(CONFIG_DRM_HISI_HIBMC)	+=hibmc-drm.o
> +#obj-y	+= hibmc-drm.o
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
> new file mode 100644
> index 0000000..7eaacd8
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
> @@ -0,0 +1,307 @@
> +/* Hisilicon Hibmc SoC drm driver
> + *
> + * Based on the bochs drm driver.
> + *
> + * Copyright (c) 2016 Huawei Limited.
> + *
> + * Author:
> + *	Rongrong Zou <zourongrong at huawei>
> + *	Rongrong Zou <zourongrong at gmail.com>
> + *	Jianhua Li <lijianhua at huawei.com>
> + *
> + * 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.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/console.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drmP.h>
> +
> +#include "hibmc_drm_drv.h"
> +#include "hibmc_drm_regs.h"
> +#include "hibmc_drm_power.h"
> +
> +static const struct file_operations hibmc_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= drm_open,
> +	.release	= drm_release,
> +	.unlocked_ioctl	= drm_ioctl,
> +#ifdef CONFIG_COMPAT
> +	.compat_ioctl	= drm_compat_ioctl,
> +#endif
> +	.poll		= drm_poll,
> +	.read		= drm_read,
> +	.llseek		= no_llseek,
> +};
> +
> +static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
> +{
> +	return 0;
> +}
> +
> +static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
> +{
> +}
> +
> +static struct drm_driver hibmc_driver = {
> +	.driver_features	= DRIVER_GEM | DRIVER_MODESET,
> +	.fops			= &hibmc_fops,
> +	.name			= "hibmc",
> +	.desc			= "hibmc drm driver",
> +	.major			= 1,
> +	.minor			= 0,
> +	.get_vblank_counter = drm_vblank_no_hw_counter,
> +	.enable_vblank		= hibmc_enable_vblank,
> +	.disable_vblank	= hibmc_disable_vblank,
> +	.gem_free_object        = drm_gem_cma_free_object,

gem_free_object_unlocked pls.

> +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
> +	.dumb_create            = drm_gem_cma_dumb_create,
> +	.dumb_map_offset        = drm_gem_cma_dumb_map_offset,
> +	.dumb_destroy           = drm_gem_dumb_destroy,
> +};
> +
> +static int hibmc_pm_suspend(struct device *dev)
> +{
> +	struct pci_dev *pdev = to_pci_dev(dev);
> +	struct drm_device *drm_dev = pci_get_drvdata(pdev);
> +
> +	drm_kms_helper_poll_disable(drm_dev);
> +
> +	return 0;
> +}
> +
> +static int hibmc_pm_resume(struct device *dev)
> +{
> +	struct pci_dev *pdev = to_pci_dev(dev);
> +	struct drm_device *drm_dev = pci_get_drvdata(pdev);
> +
> +	drm_helper_resume_force_mode(drm_dev);
> +	drm_kms_helper_poll_enable(drm_dev);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops hibmc_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
> +				hibmc_pm_resume)
> +};
> +
> +static const struct drm_mode_config_funcs mode_config_funcs = {
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = drm_atomic_helper_commit,

So how exactly does nonblocking commit work for you? Please run the igt
validation suit on your new driver, a bunch of collabora engineers are
working hard to make it run on non-intel drivers too. Ping Tomeu and
Robert Foss for more info on this please.

Lucky for you I'm working on generic nonblocking support in the atomic
helpers, patches are on the mailing list.

> +};
> +
> +
> +static int hibmc_hw_config(struct hibmc_drm_device *hidev)
> +{
> +	unsigned int reg;
> +
> +	/* On hardware reset, power mode 0 is default. */
> +	hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
> +
> +	/* Enable display power gate & LOCALMEM power gate*/
> +	reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
> +	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
> +	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
> +	reg |= HIBMC_CURR_GATE_DISPLAY(ON);
> +	reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
> +
> +	hibmc_set_current_gate(hidev, reg);
> +
> +	/* Reset the memory controller. If the memory controller
> +	 * is not reset in chip,the system might hang when sw accesses
> +	 * the memory.The memory should be resetted after
> +	 * changing the MXCLK.
> +	 */
> +	reg = readl(hidev->mmio + HIBMC_MISC_CTRL);
> +	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
> +	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(RESET);
> +	writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
> +
> +	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
> +	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(NORMAL);
> +
> +	writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
> +
> +	/* We can add more initialization as needed. */
> +
> +	return 0;
> +}
> +
> +static int hibmc_hw_map(struct hibmc_drm_device *hidev)
> +{
> +	struct drm_device *dev = hidev->dev;
> +	struct pci_dev *pdev = dev->pdev;
> +	resource_size_t addr, size, ioaddr, iosize;
> +
> +	ioaddr = pci_resource_start(pdev, 1);
> +	iosize = MB(2);
> +
> +	hidev->mmio = ioremap_nocache(ioaddr, iosize);
> +
> +	if (!hidev->mmio) {
> +		DRM_ERROR("Cannot map mmio region\n");
> +		return -ENOMEM;
> +	}
> +
> +	addr = pci_resource_start(pdev, 0);
> +	size = MB(16);
> +
> +	hidev->fb_map = ioremap(addr, size);
> +	if (!hidev->fb_map) {
> +		DRM_ERROR("Cannot map framebuffer\n");
> +		return -ENOMEM;
> +	}
> +	hidev->fb_base = addr;
> +	hidev->fb_size = size;
> +
> +	return 0;
> +}
> +
> +static void hibmc_hw_fini(struct hibmc_drm_device *hidev)
> +{
> +	if (hidev->mmio)
> +		iounmap(hidev->mmio);
> +	if (hidev->fb_map)
> +		iounmap(hidev->fb_map);
> +}
> +
> +static int hibmc_hw_init(struct hibmc_drm_device *hidev)
> +{
> +	int ret;
> +
> +	ret = hibmc_hw_map(hidev);
> +	if (ret)
> +		return ret;
> +
> +	hibmc_hw_config(hidev);
> +
> +	return 0;
> +}
> +
> +static int hibmc_unload(struct drm_device *dev)
> +{
> +	struct hibmc_drm_device *hidev = dev->dev_private;
> +
> +	hibmc_hw_fini(hidev);
> +	dev->dev_private = NULL;
> +	return 0;
> +}
> +
> +static int hibmc_load(struct drm_device *dev, unsigned long flags)
> +{
> +	struct hibmc_drm_device *hidev;
> +	int ret;
> +
> +	hidev = devm_kzalloc(dev->dev, sizeof(*hidev), GFP_KERNEL);
> +	if (!hidev)
> +		return -ENOMEM;
> +	dev->dev_private = hidev;
> +	hidev->dev = dev;
> +
> +	ret = hibmc_hw_init(hidev);
> +	if (ret)
> +		goto err;
> +
> +
> +	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
> +	if (ret) {
> +		DRM_ERROR("failed to initialize vblank.\n");
> +		return ret;
> +	}
> +	/* reset all the states of crtc/plane/encoder/connector */
> +	drm_mode_config_reset(dev);
> +
> +	return 0;
> +
> +err:
> +	hibmc_unload(dev);
> +	DRM_ERROR("failed to initialize drm driver.\n");
> +	return ret;
> +}
> +
> +
> +static int hibmc_pci_probe(struct pci_dev *pdev,
> +			   const struct pci_device_id *ent)
> +{
> +	struct drm_device *dev;
> +	int ret;
> +
> +	dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
> +	if (!dev)
> +		return -ENOMEM;
> +
> +	dev->pdev = pdev;
> +	pci_set_drvdata(pdev, dev);
> +
> +	ret = pci_enable_device(pdev);
> +	if (ret)
> +		goto err_free;
> +
> +	ret = hibmc_load(dev, 0);
> +	if (ret)
> +		goto err_disable;
> +
> +	ret = drm_dev_register(dev, 0);
> +	if (ret)
> +		goto err_unload;
> +
> +	return 0;
> +
> +err_unload:
> +	hibmc_unload(dev);
> +err_disable:
> +	pci_disable_device(pdev);
> +err_free:
> +	drm_dev_unref(dev);
> +
> +	return ret;
> +}
> +
> +static void hibmc_pci_remove(struct pci_dev *pdev)
> +{
> +	struct drm_device *dev = pci_get_drvdata(pdev);
> +
> +	drm_dev_unregister(dev);
> +	hibmc_unload(dev);
> +	drm_dev_unref(dev);
> +}
> +
> +static struct pci_device_id hibmc_pci_table[] = {
> +	{0x19e5, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
> +	{0,}
> +};
> +
> +static struct pci_driver hibmc_pci_driver = {
> +	.name =		"hibmc-drm",
> +	.id_table =	hibmc_pci_table,
> +	.probe =	hibmc_pci_probe,
> +	.remove =	hibmc_pci_remove,
> +	.driver.pm =    &hibmc_pm_ops,
> +};
> +
> +static int __init hibmc_init(void)
> +{
> +	return pci_register_driver(&hibmc_pci_driver);
> +}
> +
> +static void __exit hibmc_exit(void)
> +{
> +	return pci_unregister_driver(&hibmc_pci_driver);
> +}
> +
> +module_init(hibmc_init);
> +module_exit(hibmc_exit);
> +
> +MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
> +MODULE_AUTHOR("RongrongZou <zourongrong at huawei.com>");
> +MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
> +MODULE_LICENSE("GPL v2");
> +
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
> new file mode 100644
> index 0000000..a072ea9
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
> @@ -0,0 +1,39 @@
> +/* Hisilicon Hibmc SoC drm driver
> + *
> + * Based on the bochs drm driver.
> + *
> + * Copyright (c) 2016 Huawei Limited.
> + *
> + * Author:
> + *	Rongrong Zou <zourongrong at huawei>
> + *	Rongrong Zou <zourongrong at gmail.com>
> + *	Jianhua Li <lijianhua at huawei.com>
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef HIBMC_DRM_DRV_H
> +#define HIBMC_DRM_DRV_H
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +
> +struct hibmc_drm_device {
> +	/* hw */
> +	void __iomem   *mmio;
> +	void __iomem   *fb_map;
> +	unsigned long  fb_base;
> +	unsigned long  fb_size;
> +
> +	/* drm */
> +	struct drm_device  *dev;
> +	bool mode_config_initialized;
> +};
> +
> +
> +#endif
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
> new file mode 100644
> index 0000000..673be10
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
> @@ -0,0 +1,91 @@
> +/* Hisilicon Hibmc SoC drm driver
> + *
> + * Based on the bochs drm driver.
> + *
> + * Copyright (c) 2016 Huawei Limited.
> + *
> + * Author:
> + *	Rongrong Zou <zourongrong at huawei>
> + *	Rongrong Zou <zourongrong at gmail.com>
> + *	Jianhua Li <lijianhua at huawei.com>
> + *
> + * 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.
> + *
> + */
> +
> +#include <linux/io.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include "hibmc_drm_drv.h"
> +#include "hibmc_drm_regs.h"
> +
> +/*
> + * It can operate in one of three modes: 0, 1 or Sleep.
> + */
> +void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
> +				 unsigned int power_mode)
> +{
> +	unsigned int control_value = 0;
> +	void __iomem   *mmio = hidev->mmio;
> +
> +	if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
> +		return;
> +
> +	control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
> +	control_value &= ~HIBMC_PW_MODE_CTL_MODE_MASK;
> +
> +	control_value |= HIBMC_PW_MODE_CTL_MODE(power_mode) &
> +			 HIBMC_PW_MODE_CTL_MODE_MASK;
> +
> +
> +    /* Set up other fields in Power Control Register */
> +	if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP) {
> +		control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
> +		control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(0) &
> +				 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
> +	} else {
> +		control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
> +		control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(1) &
> +				 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
> +
> +	}
> +    /* Program new power mode. */
> +	writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
> +}
> +
> +static unsigned int hibmc_get_power_mode(struct hibmc_drm_device *hidev)
> +{
> +	void __iomem   *mmio = hidev->mmio;
> +
> +	return (readl(mmio + HIBMC_POWER_MODE_CTRL)&
> +		HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
> +}
> +
> +void hibmc_set_current_gate(struct hibmc_drm_device *hidev, unsigned int gate)
> +{
> +	unsigned int gate_reg;
> +	unsigned int mode;
> +	void __iomem   *mmio = hidev->mmio;
> +
> +	/* Get current power mode. */
> +	mode = hibmc_get_power_mode(hidev);
> +
> +	switch (mode) {
> +	case HIBMC_PW_MODE_CTL_MODE_MODE0:
> +		gate_reg = HIBMC_MODE0_GATE;
> +		break;
> +
> +	case HIBMC_PW_MODE_CTL_MODE_MODE1:
> +		gate_reg = HIBMC_MODE1_GATE;
> +		break;
> +
> +	default:
> +		gate_reg = HIBMC_MODE0_GATE;
> +		break;
> +	}
> +	writel(gate, mmio + gate_reg);
> +}
> +
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
> new file mode 100644
> index 0000000..39f7a17
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
> @@ -0,0 +1,28 @@
> +/* Hisilicon Hibmc SoC drm driver
> + *
> + * Based on the bochs drm driver.
> + *
> + * Copyright (c) 2016 Huawei Limited.
> + *
> + * Author:
> + *	Rongrong Zou <zourongrong at huawei>
> + *	Rongrong Zou <zourongrong at gmail.com>
> + *	Jianhua Li <lijianhua at huawei.com>
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef HIBMC_DRM_POWER_H
> +#define HIBMC_DRM_POWER_H
> +
> +#include "hibmc_drm_drv.h"
> +
> +extern void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
> +				 unsigned int power_mode);
> +extern void hibmc_set_current_gate(struct hibmc_drm_device *hidev,
> +				   unsigned int gate);
> +#endif
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
> new file mode 100644
> index 0000000..4966c42
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
> @@ -0,0 +1,214 @@
> +/* Hisilicon Hibmc SoC drm driver
> + *
> + * Based on the bochs drm driver.
> + *
> + * Copyright (c) 2016 Huawei Limited.
> + *
> + * Author:
> + *	Rongrong Zou <zourongrong at huawei>
> + *	Rongrong Zou <zourongrong at gmail.com>
> + *	Jianhua Li <lijianhua at huawei.com>
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef HIBMC_DRM_HW_H
> +#define HIBMC_DRM_HW_H
> +
> +#define OFF 0
> +#define ON  1
> +#define DISABLE               0
> +#define ENABLE                1
> +
> +
> +
> +/* register definition */
> +#define HIBMC_MISC_CTRL				0x4
> +
> +#define HIBMC_MSCCTL_LOCALMEM_RESET(x)		((x) << 6)
> +#define HIBMC_MSCCTL_LOCALMEM_RESET_MASK	0x40
> +
> +#define RESET                0
> +#define NORMAL               1
> +
> +#define HIBMC_CURRENT_GATE			0x000040
> +#define HIBMC_CURR_GATE_DISPLAY(x)		((x) << 2)
> +#define HIBMC_CURR_GATE_DISPLAY_MASK		0x4
> +
> +#define HIBMC_CURR_GATE_LOCALMEM(x)		((x) << 1)
> +#define HIBMC_CURR_GATE_LOCALMEM_MASK		0x2
> +
> +#define HIBMC_MODE0_GATE			0x000044
> +#define HIBMC_MODE1_GATE			0x000048
> +#define HIBMC_POWER_MODE_CTRL			0x00004C
> +
> +#define HIBMC_PW_MODE_CTL_OSC_INPUT(x)		((x) << 3)
> +#define HIBMC_PW_MODE_CTL_OSC_INPUT_MASK	0x8
> +
> +#define HIBMC_PW_MODE_CTL_MODE(x)		((x) << 0)
> +#define HIBMC_PW_MODE_CTL_MODE_MASK		0x03
> +#define HIBMC_PW_MODE_CTL_MODE_SHIFT		0
> +
> +
> +#define HIBMC_PW_MODE_CTL_MODE_MODE0		0
> +#define HIBMC_PW_MODE_CTL_MODE_MODE1		1
> +#define HIBMC_PW_MODE_CTL_MODE_SLEEP		2
> +
> +#define HIBMC_PANEL_PLL_CTRL			0x00005C
> +#define HIBMC_CRT_PLL_CTRL			0x000060
> +
> +#define HIBMC_PLL_CTRL_BYPASS(x)		((x) << 18)
> +#define HIBMC_PLL_CTRL_BYPASS_MASK		0x40000
> +
> +#define HIBMC_PLL_CTRL_POWER(x)			((x) << 17)
> +#define HIBMC_PLL_CTRL_POWER_MASK		0x20000
> +
> +#define HIBMC_PLL_CTRL_INPUT(x)			((x) << 16)
> +#define HIBMC_PLL_CTRL_INPUT_MASK		0x10000
> +
> +#define OSC					0
> +#define TESTCLK					1
> +
> +#define HIBMC_PLL_CTRL_POD(x)			((x) << 14)
> +#define HIBMC_PLL_CTRL_POD_MASK			0xC000
> +
> +#define HIBMC_PLL_CTRL_OD(x)			((x) << 12)
> +#define HIBMC_PLL_CTRL_OD_MASK			0x3000
> +
> +#define HIBMC_PLL_CTRL_N(x)			((x) << 8)
> +#define HIBMC_PLL_CTRL_N_MASK			0xF00
> +
> +#define HIBMC_PLL_CTRL_M(x)			((x) << 0)
> +#define HIBMC_PLL_CTRL_M_MASK			0xFF
> +
> +
> +#define HIBMC_CRT_DISP_CTL			0x80200
> +
> +#define HIBMC_CRT_DISP_CTL_CRTSELECT(x)		((x) << 25)
> +#define HIBMC_CRT_DISP_CTL_CRTSELECT_MASK	0x2000000
> +
> +#define CRTSELECT_VGA                0
> +#define CRTSELECT_CRT                1
> +
> +#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE(x)	((x) << 14)
> +#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK	0x4000
> +
> +#define PHASE_ACTIVE_HIGH      0
> +#define PHASE_ACTIVE_LOW       1
> +
> +#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE(x)	((x) << 13)
> +#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK	0x2000
> +
> +#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE(x)	((x) << 12)
> +#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK	0x1000
> +
> +#define HIBMC_CRT_DISP_CTL_TIMING(x)		((x) << 8)
> +#define HIBMC_CRT_DISP_CTL_TIMING_MASK		0x100
> +
> +
> +#define HIBMC_CRT_DISP_CTL_PLANE(x)		((x) << 2)
> +#define HIBMC_CRT_DISP_CTL_PLANE_MASK		4
> +
> +#define HIBMC_CRT_DISP_CTL_FORMAT(x)		((x) << 0)
> +#define HIBMC_CRT_DISP_CTL_FORMAT_MASK		0x03
> +
> +
> +
> +#define HIBMC_CRT_FB_ADDRESS			0x080204
> +
> +#define HIBMC_CRT_FB_WIDTH			0x080208
> +#define HIBMC_CRT_FB_WIDTH_WIDTH(x)		((x) << 16)
> +#define HIBMC_CRT_FB_WIDTH_WIDTH_MASK		0x3FFF0000
> +#define HIBMC_CRT_FB_WIDTH_OFFS(x)		((x) << 0)
> +#define HIBMC_CRT_FB_WIDTH_OFFS_MASK		0x3FFF
> +
> +
> +#define HIBMC_CRT_HORZ_TOTAL			0x08020C
> +#define HIBMC_CRT_HORZ_TOTAL_TOTAL(x)		((x) << 16)
> +#define HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK		0xFFF0000
> +
> +
> +#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END(x)	((x) << 0)
> +#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END_MASK	0xFFF
> +
> +#define HIBMC_CRT_HORZ_SYNC			0x080210
> +#define HIBMC_CRT_HORZ_SYNC_WIDTH(x)		((x) << 16)
> +#define HIBMC_CRT_HORZ_SYNC_WIDTH_MASK		0xFF0000
> +
> +#define HIBMC_CRT_HORZ_SYNC_START(x)		((x) << 0)
> +#define HIBMC_CRT_HORZ_SYNC_START_MASK		0xFFF
> +
> +#define HIBMC_CRT_VERT_TOTAL			0x080214
> +#define HIBMC_CRT_VERT_TOTAL_TOTAL(x)		((x) << 16)
> +#define HIBMC_CRT_VERT_TOTAL_TOTAL_MASK		0x7FFF0000
> +
> +#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END(x)	((x) << 0)
> +#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END_MASK	0x7FF
> +
> +#define HIBMC_CRT_VERT_SYNC			0x080218
> +#define HIBMC_CRT_VERT_SYNC_HEIGHT(x)		((x) << 16)
> +#define HIBMC_CRT_VERT_SYNC_HEIGHT_MASK		0x3F0000
> +
> +
> +#define HIBMC_CRT_VERT_SYNC_START(x)		((x) << 0)
> +#define HIBMC_CRT_VERT_SYNC_START_MASK		0x7FF
> +
> +/* Auto Centering */
> +#define HIBMC_CRT_AUTO_CENTERING_TL		0x080280
> +#define HIBMC_CRT_AUTO_CENTERING_TL_TOP(x)	((x) << 16)
> +#define HIBMC_CRT_AUTO_CENTERING_TL_TOP_MSK	0x7FF0000
> +
> +#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT(x)	((x) << 0)
> +#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MSK	0x7FF
> +
> +#define HIBMC_CRT_AUTO_CENTERING_BR		0x080284
> +#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(x)	((x) << 16)
> +#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK	0x7FF0000
> +
> +#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x)	((x) << 0)
> +#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK	0x7FF
> +
> +/* register to control panel output */
> +#define DISPLAY_CONTROL_HISILE			0x80288
> +
> +/* register and values for PLL control */
> +#define CRT_PLL1_HS				0x802a8
> +#define CRT_PLL1_HS_25MHZ			0x23d40f02
> +#define CRT_PLL1_HS_40MHZ			0x23940801
> +#define CRT_PLL1_HS_65MHZ			0x23940d01
> +#define CRT_PLL1_HS_78MHZ			0x23540F82
> +#define CRT_PLL1_HS_74MHZ			0x23941dc2
> +#define CRT_PLL1_HS_80MHZ			0x23941001
> +#define CRT_PLL1_HS_80MHZ_1152			0x23540fc2
> +#define CRT_PLL1_HS_108MHZ			0x23b41b01
> +#define CRT_PLL1_HS_162MHZ			0x23480681
> +#define CRT_PLL1_HS_148MHZ			0x23541dc2
> +#define CRT_PLL1_HS_193MHZ			0x234807c1
> +
> +#define CRT_PLL2_HS				0x802ac
> +#define CRT_PLL2_HS_25MHZ			0x206B851E
> +#define CRT_PLL2_HS_40MHZ			0x30000000
> +#define CRT_PLL2_HS_65MHZ			0x40000000
> +#define CRT_PLL2_HS_78MHZ			0x50E147AE
> +#define CRT_PLL2_HS_74MHZ			0x602B6AE7
> +#define CRT_PLL2_HS_80MHZ			0x70000000
> +#define CRT_PLL2_HS_108MHZ			0x80000000
> +#define CRT_PLL2_HS_162MHZ			0xA0000000
> +#define CRT_PLL2_HS_148MHZ			0xB0CCCCCD
> +#define CRT_PLL2_HS_193MHZ			0xC0872B02
> +
> +/* Global macros */
> +#define RGB(r, g, b) \
> +( \
> +	(unsigned long)(((r) << 16) | ((g) << 8) | (b)) \
> +)
> +
> +#define PADDING(align, data) (((data) + (align) - 1) & (~((align) - 1)))
> +
> +#define MB(x) ((x) << 20)
> +
> +#endif
> -- 
> 1.9.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


From maxime.ripard at free-electrons.com  Mon May 30 02:17:23 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 30 May 2016 11:17:23 +0200
Subject: [PATCH 4/5] spi: sunxi: set maximum and minimum speed of SPI
 master
In-Reply-To: <7292b1fa08de4f453a643beb63e9faa7826726f6.1464130597.git.hramrach@gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
 <7292b1fa08de4f453a643beb63e9faa7826726f6.1464130597.git.hramrach@gmail.com>
Message-ID: <20160530091723.GH4247@lukather>

Hi,

On Thu, May 26, 2016 at 07:25:25PM -0000, Michal Suchanek wrote:
> The maximum speed of SPI master is used when maximum speed of SPI slave
> is not specified. Also the __spi_validate function should check that
> transfer speeds do not exceed the master limits.
> 
> The user manual for A10 and A31 specifies maximum
> speed of the SPI clock as 100MHz and minimum as 3kHz.
> 
> Setting the SPI clock to out-of-spec values can lock up the SoC.
> 
> Signed-off-by: Michal Suchanek <hramrach at gmail.com>
> ---
>  drivers/spi/spi-sun4i.c | 2 ++
>  drivers/spi/spi-sun6i.c | 2 ++
>  2 files changed, 4 insertions(+)
> 
> diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
> index bf52b09..e1a75dd6 100644
> --- a/drivers/spi/spi-sun4i.c
> +++ b/drivers/spi/spi-sun4i.c
> @@ -405,6 +405,8 @@ static int sun4i_spi_probe(struct platform_device *pdev)
>  	}
>  
>  	sspi->master = master;
> +	master->max_speed_hz = 100*1000*1000;

You need spaces around the * operator.

> +	master->min_speed_hz =        3*1000;

And I'm not exactly sure why you have that weird indentation.

The same applies for the sun6i driver

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/2d0eafc9/attachment.sig>

From holgerschurig at gmail.com  Mon May 30 02:36:36 2016
From: holgerschurig at gmail.com (Holger Schurig)
Date: Mon, 30 May 2016 11:36:36 +0200
Subject: [PATCH 2/2] ARM: dts: imx6q: add support for the Utilite Pro
In-Reply-To: <0cf90ebe86e0461f82cb22b2a6b6ea83@rwthex-s1-b.rwth-ad.de>
References: <1463957258-4893-1-git-send-email-christopher.spinrath@rwth-aachen.de>
 <c4ab0387041f42ada68296141befe332@rwthex-s1-b.rwth-ad.de>
 <20abc2f6769b4369ba87ec27274a090e@rwthex-s2-a.rwth-ad.de>
 <644530ff6bb04b5898dc33604dc7a93a@rwthex-s1-b.rwth-ad.de>
 <9b905766c6cc4680be4b33f79a179d5a@rwthex-w1-b.rwth-ad.de>
 <0cf90ebe86e0461f82cb22b2a6b6ea83@rwthex-s1-b.rwth-ad.de>
Message-ID: <87h9df99az.fsf@gmail.com>

> OK, done. Can I always use the default value in this case? If yes, can
> you point me to a proper documentation of these?

Just google for "i.MX6Q Reference Manual", it's chapter 36 ("IOMUXC"),
or to be more specific, it at 36.4.316.



It's nice that Freescale/NXP is way better here than Marvell. You can
download this stuff without any problem.

When Marvell bought the PXA stuff from Intel and put everything under
NDA / download after approvement, I was hugely p.... off. I never
touched any Marvell chip after it :-)


From hs.liao at mediatek.com  Mon May 30 02:38:03 2016
From: hs.liao at mediatek.com (Horng-Shyang Liao)
Date: Mon, 30 May 2016 17:38:03 +0800
Subject: [PATCH v8 2/3] CMDQ: Mediatek CMDQ driver
In-Reply-To: <1464590942.20547.22.camel@mtksdaap41>
References: <1464578397-29743-1-git-send-email-hs.liao@mediatek.com>
 <1464578397-29743-3-git-send-email-hs.liao@mediatek.com>
 <1464590942.20547.22.camel@mtksdaap41>
Message-ID: <1464601083.20071.12.camel@mtksdaap41>

Hi CK,

Reply inline.

On Mon, 2016-05-30 at 14:49 +0800, CK Hu wrote:
> Hi, HS:
> 
> Some comments inline.
> 
> On Mon, 2016-05-30 at 11:19 +0800, HS Liao wrote:
...
> > +static void cmdq_thread_irq_handler(struct cmdq *cmdq, int tid)
> > +{
> > +	struct cmdq_thread *thread = &cmdq->thread[tid];
> > +	unsigned long flags = 0L;
> > +	u32 irq_flag;
> > +
> > +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> > +
> > +	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> > +	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
> > +
> > +	/*
> > +	 * Another CPU core could run "release task" right before we acquire
> > +	 * the spin lock, and thus reset / disable this GCE thread, so we
> > +	 * need to check the enable bit of this GCE thread.
> > +	 */
> > +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> > +	      CMDQ_THR_ENABLED))
> > +		irq_flag = 0;
> 
> These three statement (clear irq flag and detect thread enable) can be
> moved into cmdq_handle_error_done() and the duplicated part in
> cmdq_task_handle_error_result() can be removed. Even though
> cmdq_task_handle_error_result() need not check thread enable, it would
> not influence the flow.

Will do.

> > +
> > +	cmdq_handle_error_done(cmdq, thread, irq_flag);
> > +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > +}
...
> > +static int cmdq_task_handle_error_result(struct cmdq_task *task)
> > +{
> > +	struct cmdq *cmdq = task->cmdq;
> > +	struct device *dev = cmdq->dev;
> > +	struct cmdq_thread *thread = task->thread;
> > +	struct cmdq_task *next_task, *prev_task;
> > +	u32 irq_flag;
> > +
> > +	/* suspend GCE thread to ensure consistency */
> > +	WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
> > +
> > +	/* ISR has handled this error task */
> > +	if (task->task_state == TASK_STATE_ERROR) {
> > +		next_task = list_first_entry_or_null(&thread->task_busy_list,
> > +				struct cmdq_task, list_entry);
> > +		if (next_task) /* move to next task */
> > +			cmdq_thread_writel(thread, next_task->pa_base,
> > +					   CMDQ_THR_CURR_ADDR);
> > +		cmdq_thread_resume(thread);
> > +		return -ECANCELED;
> > +	}
> > +
> > +	/*
> > +	 * Save next_task and prev_task in advance
> > +	 * since cmdq_handle_error_done will remove list_entry.
> > +	 */
> > +	next_task = prev_task = NULL;
> > +	if (task->list_entry.next != &thread->task_busy_list)
> > +		next_task = list_next_entry(task, list_entry);
> > +	if (task->list_entry.prev != &thread->task_busy_list)
> > +		prev_task = list_prev_entry(task, list_entry);
> 
> I think there is always no previous task because task order in
> thread->task_busy_list is the same as in cmdq->task_release_wq. So each
> task processed by release work should be the first item in
> thread->task_busy_list or be removed from thread->task_busy_list.

Will remove previous task.

> > +
> > +	/*
> > +	 * Although IRQ is disabled, GCE continues to execute.
> > +	 * It may have pending IRQ before GCE thread is suspended,
> > +	 * so check this condition again.
> > +	 */
> > +	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> > +	cmdq_handle_error_done(cmdq, thread, irq_flag);
> > +	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
> > +
> > +	if (task->task_state == TASK_STATE_DONE) {
> > +		cmdq_thread_resume(thread);
> > +		return 0;
> > +	}
> > +
> > +	if (task->task_state == TASK_STATE_ERROR) {
> > +		dev_err(dev, "task 0x%p error\n", task);
> > +		if (next_task) /* move to next task */
> > +			cmdq_thread_writel(thread, next_task->pa_base,
> > +					   CMDQ_THR_CURR_ADDR);
> > +		cmdq_thread_resume(thread);
> > +		return -ECANCELED;
> > +	}
> > +
> > +	/* Task is running, so we force to remove it. */
> > +	dev_err(dev, "task 0x%p timeout or killed\n", task);
> 
> No 'kill' state.

>From CMDQ v8, there is no killed task.
I will rewrite output message.

> > +	task->task_state = TASK_STATE_ERROR;
> > +
> > +	if (prev_task) {
> > +		u64 *prev_va = prev_task->va_base;
> > +		u64 *curr_va = task->va_base;
> > +
> > +		/* copy JUMP instruction */
> > +		prev_va[prev_task->num_cmd - 1] = curr_va[task->num_cmd - 1];
> > +
> > +		cmdq_thread_invalidate_fetched_data(thread);
> > +	} else if (next_task) { /* move to next task */
> > +		cmdq_thread_writel(thread, next_task->pa_base,
> > +				   CMDQ_THR_CURR_ADDR);
> > +	}
> 
> Just one statement in 'else if' part. So remove the parentheses.

I think we should keep this parentheses.

Quote from CodingStyle document:

This does not apply if only one branch of a conditional statement is a
single
statement; in the latter case use braces in both branches:

if (condition) {
        do_this();
        do_that();
} else {
        otherwise();
}

> > +
> > +	list_del(&task->list_entry);
> > +	cmdq_thread_resume(thread);
> > +
> > +	/* call cb here to prevent lock */
> 
> I think these three statements should be place together and there should
> be no this comment.
> 
> 1. Change task state to DONE or ERROR.
> 2. Callback
> 3. Remove task from task_busy_list.

I will put these three statements together and wrap up them as a
function.

> > +	if (task->cb.cb) {
> > +		struct cmdq_cb_data cmdq_cb_data;
> > +
> > +		cmdq_cb_data.err = true;
> > +		cmdq_cb_data.data = task->cb.data;
> > +		task->cb.cb(cmdq_cb_data);
> > +	}
> > +
> > +	return -ECANCELED;
> > +}
...
> > +static int cmdq_suspend(struct device *dev)
> > +{
> > +	struct cmdq *cmdq = dev_get_drvdata(dev);
> > +	u32 exec_threads;
> > +
> > +	mutex_lock(&cmdq->task_mutex);
> > +	cmdq->suspended = true;
> > +	mutex_unlock(&cmdq->task_mutex);
> > +
> > +	exec_threads = readl(cmdq->base + CMDQ_CURR_LOADED_THR);
> > +	if ((exec_threads & CMDQ_THR_EXECUTING) && !cmdq_task_is_empty(cmdq)) {
> > +		dev_err(dev, "wait active tasks timeout.\n");
> > +		flush_workqueue(cmdq->task_release_wq);
> > +	}
> 
> Maybe it need not to check exec_threads, it may be written as:
> 
> 	if (!cmdq_task_is_empty(cmdq))
> 		dev_err(dev, "wait active tasks timeout.\n");
> 
> 	flush_workqueue(cmdq->task_release_wq);
> 
> Even though task_busy_list is empty, that does not mean every task in
> cmdq->task_release_wq is finished. So always do flush
> cmdq->task_release_wq.

Will do.

> > +	return 0;
> > +}
> > +
...
> 
> Regards,
> CK
> 

Thanks,
HS



From maxime.ripard at free-electrons.com  Mon May 30 02:44:49 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 30 May 2016 11:44:49 +0200
Subject: [PATCH 1/5] spi: sunxi: fix transfer timeout
In-Reply-To: <cb90b922caa6ac07c1425d726ea19709ee5284f4.1464130597.git.hramrach@gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
 <cb90b922caa6ac07c1425d726ea19709ee5284f4.1464130597.git.hramrach@gmail.com>
Message-ID: <20160530094449.GJ4247@lukather>

On Thu, May 26, 2016 at 07:25:23PM -0000, Michal Suchanek wrote:
> The trasfer timeout is fixed at 1000 ms. Reading a 4Mbyte flash over
> 1MHz SPI bus takes way longer than that. Calculate the timeout from the
> actual time the transfer is supposed to take and multiply by 2 for good
> measure.
> 
> Signed-off-by: Michal Suchanek <hramrach at gmail.com>
> ---
> 
> v2:
> - fix build error
> - use unsigned instead of int in max_t

And this generates warnings in checkpatch. Please make sure that you
run it before submitting any patches.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/6e2521ef/attachment.sig>

From naga.sureshkumar.relli at xilinx.com  Mon May 30 02:46:49 2016
From: naga.sureshkumar.relli at xilinx.com (Naga Sureshkumar Relli)
Date: Mon, 30 May 2016 15:16:49 +0530
Subject: [PATCH v2 1/3] spi: xilinx: Remove bitbang and register with spi core
Message-ID: <1464601609-5095-1-git-send-email-nagasure@xilinx.com>

This patch removes the bitbang layer registration.
it directly register with spi core using spi_register_master and uses
the call backs provided by spi_master struct.

Signed-off-by: Naga Sureshkumar Relli <nagasure at xilinx.com>
---
changes for v2
 - check the return value of of_property_read_u32 for fifo-size
   and return if property is not found, since it is mandatory
---

 drivers/spi/spi-xilinx.c | 733 +++++++++++++++++++++++++++--------------------
 1 file changed, 418 insertions(+), 315 deletions(-)

diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 3009121..d903857 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -18,10 +18,9 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
 #include <linux/spi/xilinx_spi.h>
 #include <linux/io.h>
-
+#include <linux/delay.h>
 #define XILINX_SPI_MAX_CS	32
 
 #define XILINX_SPI_NAME "xilinx_spi"
@@ -29,8 +28,18 @@
 /* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
  * Product Specification", DS464
  */
-#define XSPI_CR_OFFSET		0x60	/* Control Register */
-
+/* Register Offsets */
+#define XSPI_CR_OFFSET		0x60
+#define XSPI_SR_OFFSET		0x64
+#define XSPI_TXD_OFFSET		0x68
+#define XSPI_RXD_OFFSET		0x6c
+#define XSPI_SSR_OFFSET		0x70
+#define XIPIF_V123B_DGIER_OFFSET	0x1c
+#define XIPIF_V123B_IISR_OFFSET		0x20
+#define XIPIF_V123B_IIER_OFFSET		0x28
+#define XIPIF_V123B_RESETR_OFFSET	0x40
+
+/* Register bit masks */
 #define XSPI_CR_LOOP		0x01
 #define XSPI_CR_ENABLE		0x02
 #define XSPI_CR_MASTER_MODE	0x04
@@ -43,133 +52,188 @@
 #define XSPI_CR_MANUAL_SSELECT	0x80
 #define XSPI_CR_TRANS_INHIBIT	0x100
 #define XSPI_CR_LSB_FIRST	0x200
-
-#define XSPI_SR_OFFSET		0x64	/* Status Register */
-
-#define XSPI_SR_RX_EMPTY_MASK	0x01	/* Receive FIFO is empty */
-#define XSPI_SR_RX_FULL_MASK	0x02	/* Receive FIFO is full */
-#define XSPI_SR_TX_EMPTY_MASK	0x04	/* Transmit FIFO is empty */
-#define XSPI_SR_TX_FULL_MASK	0x08	/* Transmit FIFO is full */
-#define XSPI_SR_MODE_FAULT_MASK	0x10	/* Mode fault error */
-
-#define XSPI_TXD_OFFSET		0x68	/* Data Transmit Register */
-#define XSPI_RXD_OFFSET		0x6c	/* Data Receive Register */
-
-#define XSPI_SSR_OFFSET		0x70	/* 32-bit Slave Select Register */
-
-/* Register definitions as per "OPB IPIF (v3.01c) Product Specification", DS414
- * IPIF registers are 32 bit
- */
-#define XIPIF_V123B_DGIER_OFFSET	0x1c	/* IPIF global int enable reg */
+#define XSPI_SR_RX_EMPTY_MASK	0x01
+#define XSPI_SR_RX_FULL_MASK	0x02
+#define XSPI_SR_TX_EMPTY_MASK	0x04
+#define XSPI_SR_TX_FULL_MASK	0x08
+#define XSPI_SR_MODE_FAULT_MASK	0x10
 #define XIPIF_V123B_GINTR_ENABLE	0x80000000
-
-#define XIPIF_V123B_IISR_OFFSET		0x20	/* IPIF interrupt status reg */
-#define XIPIF_V123B_IIER_OFFSET		0x28	/* IPIF interrupt enable reg */
-
-#define XSPI_INTR_MODE_FAULT		0x01	/* Mode fault error */
-#define XSPI_INTR_SLAVE_MODE_FAULT	0x02	/* Selected as slave while
-						 * disabled */
-#define XSPI_INTR_TX_EMPTY		0x04	/* TxFIFO is empty */
-#define XSPI_INTR_TX_UNDERRUN		0x08	/* TxFIFO was underrun */
-#define XSPI_INTR_RX_FULL		0x10	/* RxFIFO is full */
-#define XSPI_INTR_RX_OVERRUN		0x20	/* RxFIFO was overrun */
-#define XSPI_INTR_TX_HALF_EMPTY		0x40	/* TxFIFO is half empty */
-
-#define XIPIF_V123B_RESETR_OFFSET	0x40	/* IPIF reset register */
-#define XIPIF_V123B_RESET_MASK		0x0a	/* the value to write */
-
+#define XSPI_INTR_MODE_FAULT		0x01
+#define XSPI_INTR_SLAVE_MODE_FAULT	0x02
+#define XSPI_INTR_TX_EMPTY		0x04
+#define XSPI_INTR_TX_UNDERRUN		0x08
+#define XSPI_INTR_RX_FULL		0x10
+#define XSPI_INTR_RX_OVERRUN		0x20
+#define XSPI_INTR_TX_HALF_EMPTY		0x40
+#define XIPIF_V123B_RESET_MASK		0x0a
+
+/* Number of bits per word */
+#define XSPI_ONE_BITS_PER_WORD 1
+#define XSPI_TWO_BITS_PER_WORD 2
+#define XSPI_FOUR_BITS_PER_WORD 4
+
+/* Number of data lines used to receive */
+#define XSPI_RX_ONE_WIRE	1
+
+/**
+ * struct xilinx_spi - This definition define spi driver instance
+ * @regs:		virt. address of the control registers
+ * @irq:		IRQ number
+ * @rx_ptr:		Pointer to the RX buffer
+ * @tx_ptr:		Pointer to the TX buffer
+ * @bytes_per_word:	Number of bytes in a word
+ * @buffer_size:	Buffer size in words
+ * @cs_inactive:	Level of the CS pins when inactive
+ * @read_fn:		For reading data from SPI registers
+ * @write_fn:		For writing data to SPI registers
+ * @bytes_to_transfer:	Number of bytes left to transfer
+ * @bytes_to_receive:	Number of bytes left to receive
+ * @rx_bus_width:	Number of wires used to receive data
+ * @tx_fifo:		For writing data to fifo
+ * @rx_fifo:		For reading data from fifo
+ */
 struct xilinx_spi {
-	/* bitbang has to be first */
-	struct spi_bitbang bitbang;
-	struct completion done;
-	void __iomem	*regs;	/* virt. address of the control registers */
-
-	int		irq;
-
-	u8 *rx_ptr;		/* pointer in the Tx buffer */
-	const u8 *tx_ptr;	/* pointer in the Rx buffer */
+	void __iomem *regs;
+	int irq;
+	u8 *rx_ptr;
+	const u8 *tx_ptr;
 	u8 bytes_per_word;
-	int buffer_size;	/* buffer size in words */
-	u32 cs_inactive;	/* Level of the CS pins when inactive*/
+	int buffer_size;
+	u32 cs_inactive;
 	unsigned int (*read_fn)(void __iomem *);
 	void (*write_fn)(u32, void __iomem *);
+	u32 bytes_to_transfer;
+	u32 bytes_to_receive;
+	u32 rx_bus_width;
+	void (*tx_fifo)(struct xilinx_spi *xqspi);
+	void (*rx_fifo)(struct xilinx_spi *xqspi);
 };
 
+/**
+ * XSPI_FIFO_READ - Generate xspi_read_rx_fifo_* functions
+ * @size: bits_per_word that are read from RX FIFO
+ * @type: C type of value argument
+ *
+ * Generates xspi_read_rx_fifo_* functions used to write
+ * data into RX FIFO for different transaction widths.
+ */
+#define XSPI_FIFO_READ(size, type)					\
+static void xspi_read_rx_fifo_##size(struct xilinx_spi *xqspi)		\
+{									\
+	int i;								\
+	int count = (xqspi->bytes_to_receive > xqspi->buffer_size) ?	\
+			xqspi->buffer_size : xqspi->bytes_to_receive;	\
+	u32 data;							\
+	for (i = 0; i < count; i += (size/8)) {				\
+		data = readl_relaxed(xqspi->regs + XSPI_RXD_OFFSET);	\
+		if (xqspi->rx_ptr)					\
+			((type *)xqspi->rx_ptr)[i] = (type)data;	\
+	}								\
+	xqspi->bytes_to_receive -= count;				\
+	if (xqspi->rx_ptr)						\
+		xqspi->rx_ptr += count;					\
+}
+
+/**
+ * XSPI_FIFO_WRITE - Generate xspi_fill_tx_fifo_* functions
+ * @size: bits_per_word that are written into TX FIFO
+ * @type: C type of value argument
+ *
+ * Generates xspi_fill_tx_fifo_* functions used to write
+ * data into TX FIFO for different transaction widths.
+ */
+#define XSPI_FIFO_WRITE(size, type)					\
+static void xspi_fill_tx_fifo_##size(struct xilinx_spi *xqspi)		\
+{									\
+	int i;								\
+	int count = (xqspi->bytes_to_transfer > xqspi->buffer_size) ?	\
+			xqspi->buffer_size : xqspi->bytes_to_transfer;	\
+	u32 data = 0;							\
+	for (i = 0; i < count; i += (size/8)) {				\
+		if (xqspi->tx_ptr)					\
+			data = (type)((u8 *)xqspi->tx_ptr)[i];		\
+		writel_relaxed(data, (xqspi->regs + XSPI_TXD_OFFSET));	\
+	}								\
+	xqspi->bytes_to_transfer -= count;				\
+	if (xqspi->tx_ptr)						\
+		xqspi->tx_ptr += count;					\
+}
+
+XSPI_FIFO_READ(8, u8)
+XSPI_FIFO_READ(16, u16)
+XSPI_FIFO_READ(32, u32)
+XSPI_FIFO_WRITE(8, u8)
+XSPI_FIFO_WRITE(16, u16)
+XSPI_FIFO_WRITE(32, u32)
+
+/**
+ * xspi_write32 - Write a value to the device register little endian
+ * @val:	Value to write at the Register offset
+ * @addr:	Register offset
+ *
+ * Write data to the paricular SPI register
+ */
 static void xspi_write32(u32 val, void __iomem *addr)
 {
 	iowrite32(val, addr);
 }
 
+/**
+ * xspi_read32 - read a value from the device register little endian
+ * @addr:	Register offset
+ *
+ * Read data from the paricular SPI register
+ *
+ * Return:	return value from the SPI register.
+ */
 static unsigned int xspi_read32(void __iomem *addr)
 {
 	return ioread32(addr);
 }
 
+/**
+ * xspi_write32_be - Write a value to the device register big endian
+ * @val:	Value to write at the Register offset
+ * @addr:	Register offset
+ *
+ * Write data to the paricular SPI register
+ */
 static void xspi_write32_be(u32 val, void __iomem *addr)
 {
 	iowrite32be(val, addr);
 }
 
+/**
+ * xspi_read32_be - read a value from the device register big endian
+ * @addr:	Register offset
+ *
+ * Read data from the paricular SPI register
+ *
+ * Return:	return value from the SPI register.
+ */
 static unsigned int xspi_read32_be(void __iomem *addr)
 {
 	return ioread32be(addr);
 }
 
-static void xilinx_spi_tx(struct xilinx_spi *xspi)
-{
-	u32 data = 0;
-
-	if (!xspi->tx_ptr) {
-		xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
-		return;
-	}
-
-	switch (xspi->bytes_per_word) {
-	case 1:
-		data = *(u8 *)(xspi->tx_ptr);
-		break;
-	case 2:
-		data = *(u16 *)(xspi->tx_ptr);
-		break;
-	case 4:
-		data = *(u32 *)(xspi->tx_ptr);
-		break;
-	}
-
-	xspi->write_fn(data, xspi->regs + XSPI_TXD_OFFSET);
-	xspi->tx_ptr += xspi->bytes_per_word;
-}
-
-static void xilinx_spi_rx(struct xilinx_spi *xspi)
-{
-	u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
-
-	if (!xspi->rx_ptr)
-		return;
-
-	switch (xspi->bytes_per_word) {
-	case 1:
-		*(u8 *)(xspi->rx_ptr) = data;
-		break;
-	case 2:
-		*(u16 *)(xspi->rx_ptr) = data;
-		break;
-	case 4:
-		*(u32 *)(xspi->rx_ptr) = data;
-		break;
-	}
-
-	xspi->rx_ptr += xspi->bytes_per_word;
-}
-
+/**
+ * xspi_init_hw - Initialize the hardware
+ * @xspi:	Pointer to the zynqmp_qspi structure
+ *
+ * This function performs the following actions
+ *	- Disable and clear all the interrupts
+ *	- Enable manual slave select
+ *	- Enable the SPI controller
+ */
 static void xspi_init_hw(struct xilinx_spi *xspi)
 {
 	void __iomem *regs_base = xspi->regs;
 
 	/* Reset the SPI device */
 	xspi->write_fn(XIPIF_V123B_RESET_MASK,
-		regs_base + XIPIF_V123B_RESETR_OFFSET);
-	/* Enable the transmit empty interrupt, which we use to determine
+			regs_base + XIPIF_V123B_RESETR_OFFSET);
+	/*
+	 * Enable the transmit empty interrupt, which we use to determine
 	 * progress on the transmission.
 	 */
 	xspi->write_fn(XSPI_INTR_TX_EMPTY,
@@ -178,203 +242,223 @@ static void xspi_init_hw(struct xilinx_spi *xspi)
 	xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
 	/* Deselect the slave on the SPI bus */
 	xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET);
-	/* Disable the transmitter, enable Manual Slave Select Assertion,
+	/*
+	 * Disable the transmitter, enable Manual Slave Select Assertion,
 	 * put SPI controller into master mode, and enable it */
 	xspi->write_fn(XSPI_CR_MANUAL_SSELECT |	XSPI_CR_MASTER_MODE |
 		XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET |	XSPI_CR_RXFIFO_RESET,
 		regs_base + XSPI_CR_OFFSET);
 }
 
-static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
+/**
+ * xspi_chipselect -	Select or deselect the chip select line
+ * @qspi:	Pointer to the spi_device structure
+ * @is_high:	Select(0) or deselect (1) the chip select line
+ *
+ */
+static void xspi_chipselect(struct spi_device *qspi, bool is_high)
 {
-	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
-	u16 cr;
+	struct xilinx_spi *xqspi = spi_master_get_devdata(qspi->master);
 	u32 cs;
 
-	if (is_on == BITBANG_CS_INACTIVE) {
-		/* Deselect the slave on the SPI bus */
-		xspi->write_fn(xspi->cs_inactive, xspi->regs + XSPI_SSR_OFFSET);
-		return;
+	if (is_high) {
+		/* Deselect the slave */
+		xqspi->write_fn(xqspi->cs_inactive,
+			xqspi->regs + XSPI_SSR_OFFSET);
+	} else {
+		cs = xqspi->cs_inactive;
+		cs ^= BIT(qspi->chip_select);
+		/* Activate the chip select */
+		xqspi->write_fn(cs, xqspi->regs + XSPI_SSR_OFFSET);
 	}
+}
 
-	/* Set the SPI clock phase and polarity */
-	cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET)	& ~XSPI_CR_MODE_MASK;
-	if (spi->mode & SPI_CPHA)
-		cr |= XSPI_CR_CPHA;
-	if (spi->mode & SPI_CPOL)
-		cr |= XSPI_CR_CPOL;
-	if (spi->mode & SPI_LSB_FIRST)
-		cr |= XSPI_CR_LSB_FIRST;
-	if (spi->mode & SPI_LOOP)
-		cr |= XSPI_CR_LOOP;
-	xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-
-	/* We do not check spi->max_speed_hz here as the SPI clock
-	 * frequency is not software programmable (the IP block design
-	 * parameter)
-	 */
+/**
+ * xilinx_spi_irq -	Interrupt service routine of the SPI controller
+ * @irq:	IRQ number
+ * @dev_id:	Pointer to the xspi structure
+ *
+ * This function handles TX empty only.
+ * On TX empty interrupt this function reads the received data from RX FIFO
+ * and fills the TX FIFO if there is any data remaining to be transferred.
+ *
+ * Return:	IRQ_HANDLED when interrupt is handled
+ *		IRQ_NONE otherwise.
+ */
+static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
+{
+	struct spi_master *master = dev_id;
+	struct xilinx_spi *xspi = spi_master_get_devdata(dev_id);
+	u32 ipif_isr;
+	int status = IRQ_NONE;
 
-	cs = xspi->cs_inactive;
-	cs ^= BIT(spi->chip_select);
+	/* Get the IPIF interrupts, and clear them immediately */
+	ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
+	xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);
+	if (ipif_isr & XSPI_INTR_TX_EMPTY)  {
+		/* Transmission completed */
+		xspi->rx_fifo(xspi);
+		if (xspi->bytes_to_transfer) {
+			/* There is more data to send */
+			xspi->tx_fifo(xspi);
+		}
+		status = IRQ_HANDLED;
+	}
+
+	if (!xspi->bytes_to_receive && !xspi->bytes_to_transfer) {
+		spi_finalize_current_transfer(master);
+		/* Disable the interrupts here. */
+		xspi->write_fn(0x0, xspi->regs + XIPIF_V123B_DGIER_OFFSET);
+	}
 
-	/* Activate the chip select */
-	xspi->write_fn(cs, xspi->regs + XSPI_SSR_OFFSET);
+	return status;
 }
 
-/* spi_bitbang requires custom setup_transfer() to be defined if there is a
- * custom txrx_bufs().
+/**
+ * xspi_setup_transfer - Configure SPI controller for specified
+ *			 transfer
+ * @qspi:	Pointer to the spi_device structure
+ * @transfer:	Pointer to the spi_transfer structure which provides
+ *		information about next transfer setup parameters
+ *
+ * Sets the operational mode of QSPI controller for the next QSPI
+ * transfer.
+ *
+ * Return:	0 always
  */
-static int xilinx_spi_setup_transfer(struct spi_device *spi,
-		struct spi_transfer *t)
+static int xspi_setup_transfer(struct spi_device *qspi,
+				    struct spi_transfer *transfer)
 {
-	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
-
-	if (spi->mode & SPI_CS_HIGH)
-		xspi->cs_inactive &= ~BIT(spi->chip_select);
+	struct xilinx_spi *xqspi = spi_master_get_devdata(qspi->master);
+	u32 config_reg;
+
+	config_reg = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET);
+	/* Set the QSPI clock phase and clock polarity */
+	config_reg &= ~(XSPI_CR_CPHA | XSPI_CR_CPOL);
+	if (qspi->mode & SPI_CPHA)
+		config_reg |= XSPI_CR_CPHA;
+	if (qspi->mode & SPI_CPOL)
+		config_reg |= XSPI_CR_CPOL;
+	if (qspi->mode & SPI_LSB_FIRST)
+		config_reg |= XSPI_CR_LSB_FIRST;
+	xqspi->write_fn(config_reg, xqspi->regs + XSPI_CR_OFFSET);
+
+	if (qspi->mode & SPI_CS_HIGH)
+		xqspi->cs_inactive &= ~BIT(qspi->chip_select);
 	else
-		xspi->cs_inactive |= BIT(spi->chip_select);
+		xqspi->cs_inactive |= BIT(qspi->chip_select);
 
 	return 0;
 }
 
-static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+/**
+ * xspi_setup -	Configure the SPI controller
+ * @qspi:	Pointer to the spi_device structure
+ *
+ * Sets the operational mode of QSPI controller for the next QSPI
+ * transfer.
+ *
+ * Return:	0 on success; error value otherwise.
+ */
+static int xspi_setup(struct spi_device *qspi)
 {
-	struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
-	int remaining_words;	/* the number of words left to transfer */
-	bool use_irq = false;
-	u16 cr = 0;
-
-	/* We get here with transmitter inhibited */
-
-	xspi->tx_ptr = t->tx_buf;
-	xspi->rx_ptr = t->rx_buf;
-	remaining_words = t->len / xspi->bytes_per_word;
-
-	if (xspi->irq >= 0 &&  remaining_words > xspi->buffer_size) {
-		u32 isr;
-		use_irq = true;
-		/* Inhibit irq to avoid spurious irqs on tx_empty*/
-		cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
-		xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
-			       xspi->regs + XSPI_CR_OFFSET);
-		/* ACK old irqs (if any) */
-		isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
-		if (isr)
-			xspi->write_fn(isr,
-				       xspi->regs + XIPIF_V123B_IISR_OFFSET);
-		/* Enable the global IPIF interrupt */
-		xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
-				xspi->regs + XIPIF_V123B_DGIER_OFFSET);
-		reinit_completion(&xspi->done);
-	}
-
-	while (remaining_words) {
-		int n_words, tx_words, rx_words;
-		u32 sr;
-
-		n_words = min(remaining_words, xspi->buffer_size);
-
-		tx_words = n_words;
-		while (tx_words--)
-			xilinx_spi_tx(xspi);
-
-		/* Start the transfer by not inhibiting the transmitter any
-		 * longer
-		 */
-
-		if (use_irq) {
-			xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-			wait_for_completion(&xspi->done);
-			/* A transmit has just completed. Process received data
-			 * and check for more data to transmit. Always inhibit
-			 * the transmitter while the Isr refills the transmit
-			 * register/FIFO, or make sure it is stopped if we're
-			 * done.
-			 */
-			xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
-				       xspi->regs + XSPI_CR_OFFSET);
-			sr = XSPI_SR_TX_EMPTY_MASK;
-		} else
-			sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
-
-		/* Read out all the data from the Rx FIFO */
-		rx_words = n_words;
-		while (rx_words) {
-			if ((sr & XSPI_SR_TX_EMPTY_MASK) && (rx_words > 1)) {
-				xilinx_spi_rx(xspi);
-				rx_words--;
-				continue;
-			}
-
-			sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
-			if (!(sr & XSPI_SR_RX_EMPTY_MASK)) {
-				xilinx_spi_rx(xspi);
-				rx_words--;
-			}
-		}
+	if (qspi->master->busy)
+		return -EBUSY;
 
-		remaining_words -= n_words;
-	}
+	return xspi_setup_transfer(qspi, NULL);
+}
 
-	if (use_irq) {
-		xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET);
-		xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
-	}
+/**
+ * xspi_start_transfer - Initiates the SPI transfer
+ * @master:	Pointer to the spi_master structure which provides
+ *		information about the controller.
+ * @qspi:	Pointer to the spi_device structure
+ * @transfer:	Pointer to the spi_transfer structure which provide information
+ *		about next transfer parameters
+ *
+ * This function fills the TX FIFO, starts the SPI transfer, and waits for the
+ * transfer to be completed.
+ *
+ * Return:	Number of bytes transferred in the last transfer
+ */
 
-	return t->len;
+static int xspi_start_transfer(struct spi_master *master,
+				    struct spi_device *qspi,
+				    struct spi_transfer *transfer)
+{
+	struct xilinx_spi *xqspi = spi_master_get_devdata(master);
+	u32 cr;
+
+	xqspi->tx_ptr = transfer->tx_buf;
+	xqspi->rx_ptr = transfer->rx_buf;
+	xqspi->bytes_to_transfer = transfer->len;
+	xqspi->bytes_to_receive = transfer->len;
+
+	xspi_setup_transfer(qspi, transfer);
+	cr = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET);
+	/* Enable master transaction inhibit */
+	cr |= XSPI_CR_TRANS_INHIBIT;
+	xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET);
+	xqspi->tx_fifo(xqspi);
+	/* Disable master transaction inhibit */
+	cr &= ~XSPI_CR_TRANS_INHIBIT;
+	xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET);
+	xqspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
+			xqspi->regs + XIPIF_V123B_DGIER_OFFSET);
+
+	return transfer->len;
 }
 
-
-/* This driver supports single master mode only. Hence Tx FIFO Empty
- * is the only interrupt we care about.
- * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode
- * Fault are not to happen.
+/**
+ * xspi_prepare_transfer_hardware -	Prepares hardware for transfer.
+ * @master:	Pointer to the spi_master structure which provides
+ *		information about the controller.
+ *
+ * This function enables SPI master controller.
+ *
+ * Return:	0 on success; error value otherwise
  */
-static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
+static int xspi_prepare_transfer_hardware(struct spi_master *master)
 {
-	struct xilinx_spi *xspi = dev_id;
-	u32 ipif_isr;
+	struct xilinx_spi *xqspi = spi_master_get_devdata(master);
+	u32 cr;
 
-	/* Get the IPIF interrupts, and clear them immediately */
-	ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
-	xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);
+	cr = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET);
+	cr |= XSPI_CR_ENABLE;
+	xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET);
 
-	if (ipif_isr & XSPI_INTR_TX_EMPTY) {	/* Transmission completed */
-		complete(&xspi->done);
-	}
-
-	return IRQ_HANDLED;
+	return 0;
 }
 
-static int xilinx_spi_find_buffer_size(struct xilinx_spi *xspi)
+/**
+ * xspi_unprepare_transfer_hardware -	Relaxes hardware after transfer
+ * @master:	Pointer to the spi_master structure which provides
+ *		information about the controller.
+ *
+ * This function disables the SPI master controller.
+ *
+ * Return:	Always 0
+ */
+static int xspi_unprepare_transfer_hardware(struct spi_master *master)
 {
-	u8 sr;
-	int n_words = 0;
+	struct xilinx_spi *xqspi = spi_master_get_devdata(master);
+	u32 cr;
 
-	/*
-	 * Before the buffer_size detection we reset the core
-	 * to make sure we start with a clean state.
-	 */
-	xspi->write_fn(XIPIF_V123B_RESET_MASK,
-		xspi->regs + XIPIF_V123B_RESETR_OFFSET);
+	cr = xqspi->read_fn(xqspi->regs + XSPI_CR_OFFSET);
+	cr &= ~XSPI_CR_ENABLE;
+	xqspi->write_fn(cr, xqspi->regs + XSPI_CR_OFFSET);
 
-	/* Fill the Tx FIFO with as many words as possible */
-	do {
-		xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
-		sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
-		n_words++;
-	} while (!(sr & XSPI_SR_TX_FULL_MASK));
-
-	return n_words;
+	return 0;
 }
 
-static const struct of_device_id xilinx_spi_of_match[] = {
-	{ .compatible = "xlnx,xps-spi-2.00.a", },
-	{ .compatible = "xlnx,xps-spi-2.00.b", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
-
+/**
+ * xilinx_spi_probe -	Probe method for the SPI driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function initializes the driver data structures and the hardware.
+ *
+ * Return:	0 on success; error value otherwise
+ */
 static int xilinx_spi_probe(struct platform_device *pdev)
 {
 	struct xilinx_spi *xspi;
@@ -382,23 +466,14 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 	struct resource *res;
 	int ret, num_cs = 0, bits_per_word = 8;
 	struct spi_master *master;
-	u32 tmp;
-	u8 i;
+	struct device_node *nc;
+	u32 tmp, rx_bus_width, fifo_size;
 
 	pdata = dev_get_platdata(&pdev->dev);
-	if (pdata) {
-		num_cs = pdata->num_chipselect;
-		bits_per_word = pdata->bits_per_word;
-	} else {
-		of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits",
-					  &num_cs);
-	}
-
-	if (!num_cs) {
-		dev_err(&pdev->dev,
-			"Missing slave select configuration data\n");
-		return -EINVAL;
-	}
+	of_property_read_u32(pdev->dev.of_node, "num-cs",
+				&num_cs);
+	if (!num_cs)
+		num_cs = 1;
 
 	if (num_cs > XILINX_SPI_MAX_CS) {
 		dev_err(&pdev->dev, "Invalid number of spi slaves\n");
@@ -409,18 +484,9 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 	if (!master)
 		return -ENODEV;
 
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP |
-			    SPI_CS_HIGH;
-
 	xspi = spi_master_get_devdata(master);
-	xspi->cs_inactive = 0xffffffff;
-	xspi->bitbang.master = master;
-	xspi->bitbang.chipselect = xilinx_spi_chipselect;
-	xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
-	xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
-	init_completion(&xspi->done);
-
+	master->dev.of_node = pdev->dev.of_node;
+	platform_set_drvdata(pdev, master);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	xspi->regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(xspi->regs)) {
@@ -428,20 +494,28 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 		goto put_master;
 	}
 
-	master->bus_num = pdev->id;
-	master->num_chipselect = num_cs;
-	master->dev.of_node = pdev->dev.of_node;
-
-	/*
-	 * Detect endianess on the IP via loop bit in CR. Detection
-	 * must be done before reset is sent because incorrect reset
-	 * value generates error interrupt.
-	 * Setup little endian helper functions first and try to use them
-	 * and check if bit was correctly setup or not.
-	 */
+	ret = of_property_read_u32(pdev->dev.of_node, "fifo-size",
+				&fifo_size);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Missing fifo size\n");
+		return -EINVAL;
+	}
+	of_property_read_u32(pdev->dev.of_node, "bits-per-word",
+				&bits_per_word);
+
+	xspi->rx_bus_width = XSPI_ONE_BITS_PER_WORD;
+	for_each_available_child_of_node(pdev->dev.of_node, nc) {
+		ret = of_property_read_u32(nc, "spi-rx-bus-width",
+						&rx_bus_width);
+		if (!ret) {
+			xspi->rx_bus_width = rx_bus_width;
+			break;
+		}
+	}
 	xspi->read_fn = xspi_read32;
 	xspi->write_fn = xspi_write32;
-
+	/* Detect endianness on the IP via loop bit in CR register*/
 	xspi->write_fn(XSPI_CR_LOOP, xspi->regs + XSPI_CR_OFFSET);
 	tmp = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
 	tmp &= XSPI_CR_LOOP;
@@ -450,15 +524,12 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 		xspi->write_fn = xspi_write32_be;
 	}
 
-	master->bits_per_word_mask = SPI_BPW_MASK(bits_per_word);
-	xspi->bytes_per_word = bits_per_word / 8;
-	xspi->buffer_size = xilinx_spi_find_buffer_size(xspi);
-
+	xspi->buffer_size = fifo_size;
 	xspi->irq = platform_get_irq(pdev, 0);
 	if (xspi->irq >= 0) {
 		/* Register for SPI Interrupt */
-		ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0,
-				dev_name(&pdev->dev), xspi);
+		ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq,
+					0, dev_name(&pdev->dev), master);
 		if (ret)
 			goto put_master;
 	}
@@ -466,22 +537,39 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 	/* SPI controller initializations */
 	xspi_init_hw(xspi);
 
-	ret = spi_bitbang_start(&xspi->bitbang);
-	if (ret) {
-		dev_err(&pdev->dev, "spi_bitbang_start FAILED\n");
+	master->bus_num = pdev->id;
+	master->num_chipselect = num_cs;
+	master->setup = xspi_setup;
+	master->set_cs = xspi_chipselect;
+	master->transfer_one = xspi_start_transfer;
+	master->prepare_transfer_hardware = xspi_prepare_transfer_hardware;
+	master->unprepare_transfer_hardware = xspi_unprepare_transfer_hardware;
+	master->bits_per_word_mask = SPI_BPW_MASK(8);
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	xspi->bytes_per_word = bits_per_word / 8;
+	xspi->tx_fifo = xspi_fill_tx_fifo_8;
+	xspi->rx_fifo = xspi_read_rx_fifo_8;
+	if (xspi->rx_bus_width == XSPI_RX_ONE_WIRE) {
+		if (xspi->bytes_per_word == XSPI_TWO_BITS_PER_WORD) {
+			xspi->tx_fifo = xspi_fill_tx_fifo_16;
+			xspi->rx_fifo = xspi_read_rx_fifo_16;
+		} else if (xspi->bytes_per_word == XSPI_FOUR_BITS_PER_WORD) {
+			xspi->tx_fifo = xspi_fill_tx_fifo_32;
+			xspi->rx_fifo = xspi_read_rx_fifo_32;
+		}
+	} else {
+		dev_err(&pdev->dev, "Dual/Quad Modes are not supported\n");
 		goto put_master;
 	}
-
-	dev_info(&pdev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n",
-		(unsigned long long)res->start, xspi->regs, xspi->irq);
-
-	if (pdata) {
-		for (i = 0; i < pdata->num_devices; i++)
-			spi_new_device(master, pdata->devices + i);
+	xspi->cs_inactive = 0xffffffff;
+	ret = spi_register_master(master);
+	if (ret) {
+		dev_err(&pdev->dev, "spi_register_master failed\n");
+		goto put_master;
 	}
 
-	platform_set_drvdata(pdev, master);
-	return 0;
+	return ret;
 
 put_master:
 	spi_master_put(master);
@@ -489,20 +577,28 @@ put_master:
 	return ret;
 }
 
+/**
+ * xilinx_spi_remove -	Remove method for the SPI driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function is called if a device is physically removed from the system or
+ * if the driver module is being unloaded. It frees all resources allocated to
+ * the device.
+ *
+ * Return:	0 Always
+ */
 static int xilinx_spi_remove(struct platform_device *pdev)
 {
 	struct spi_master *master = platform_get_drvdata(pdev);
 	struct xilinx_spi *xspi = spi_master_get_devdata(master);
 	void __iomem *regs_base = xspi->regs;
 
-	spi_bitbang_stop(&xspi->bitbang);
-
 	/* Disable all the interrupts just in case */
 	xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET);
 	/* Disable the global IPIF interrupt */
 	xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
 
-	spi_master_put(xspi->bitbang.master);
+	spi_unregister_master(master);
 
 	return 0;
 }
@@ -510,6 +606,13 @@ static int xilinx_spi_remove(struct platform_device *pdev)
 /* work with hotplug and coldplug */
 MODULE_ALIAS("platform:" XILINX_SPI_NAME);
 
+static const struct of_device_id xilinx_spi_of_match[] = {
+	{ .compatible = "xlnx,xps-spi-2.00.a", },
+	{ .compatible = "xlnx,xps-spi-2.00.b", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
+
 static struct platform_driver xilinx_spi_driver = {
 	.probe = xilinx_spi_probe,
 	.remove = xilinx_spi_remove,
-- 
2.1.1



From naga.sureshkumar.relli at xilinx.com  Mon May 30 02:47:01 2016
From: naga.sureshkumar.relli at xilinx.com (Naga Sureshkumar Relli)
Date: Mon, 30 May 2016 15:17:01 +0530
Subject: [PATCH v2 2/3] spi: xilinx: Add QUAD support
Message-ID: <1464601621-5157-1-git-send-email-nagasure@xilinx.com>

This patch adds QUAD mode support to axi spi controller.
updated supported mode bits to SPI_TX_QUAD and SPI_RX_QUAD.

Signed-off-by: Naga Sureshkumar Relli <nagasure at xilinx.com>
---
changes for v2
 - none
---
 drivers/spi/spi-xilinx.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index d903857..4467590 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -74,6 +74,7 @@
 
 /* Number of data lines used to receive */
 #define XSPI_RX_ONE_WIRE	1
+#define XSPI_RX_FOUR_WIRE	4
 
 /**
  * struct xilinx_spi - This definition define spi driver instance
@@ -558,8 +559,10 @@ static int xilinx_spi_probe(struct platform_device *pdev)
 			xspi->tx_fifo = xspi_fill_tx_fifo_32;
 			xspi->rx_fifo = xspi_read_rx_fifo_32;
 		}
+	} else if (xspi->rx_bus_width == XSPI_RX_FOUR_WIRE) {
+		master->mode_bits |= SPI_TX_QUAD | SPI_RX_QUAD;
 	} else {
-		dev_err(&pdev->dev, "Dual/Quad Modes are not supported\n");
+		dev_err(&pdev->dev, "Dual Mode not supported\n");
 		goto put_master;
 	}
 	xspi->cs_inactive = 0xffffffff;
-- 
2.1.1



From naga.sureshkumar.relli at xilinx.com  Mon May 30 02:47:07 2016
From: naga.sureshkumar.relli at xilinx.com (Naga Sureshkumar Relli)
Date: Mon, 30 May 2016 15:17:07 +0530
Subject: [PATCH v2 3/3] spi: xilinx: Update devicetree bindings for spi-xilinx
Message-ID: <1464601627-5246-1-git-send-email-nagasure@xilinx.com>

Update bindings for spi-xilinx.
as per spi-bus.txt rename num-ss-bits to num-cs.
and add fifo-size and bits-per-word properties.

Signed-off-by: Naga Sureshkumar Relli <nagasure at xilinx.com>
---
changes for v2
 - none
---
 Documentation/devicetree/bindings/spi/spi-xilinx.txt | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-xilinx.txt b/Documentation/devicetree/bindings/spi/spi-xilinx.txt
index c7b7856..539bbe9 100644
--- a/Documentation/devicetree/bindings/spi/spi-xilinx.txt
+++ b/Documentation/devicetree/bindings/spi/spi-xilinx.txt
@@ -7,9 +7,11 @@ Required properties:
 - interrupts		: Property with a value describing the interrupt
 			  number.
 - interrupt-parent	: Must be core interrupt controller
+- fifo-size		: Depth of TX/RX Fifos
 
 Optional properties:
-- xlnx,num-ss-bits	: Number of chip selects used.
+- num-cs		: Number of chip selects used.
+- bits-per-word		: Number of bits per word.
 
 Example:
 	axi_quad_spi at 41e00000 {
@@ -17,6 +19,8 @@ Example:
 			interrupt-parent = <&intc>;
 			interrupts = <0 31 1>;
 			reg = <0x41e00000 0x10000>;
-			xlnx,num-ss-bits = <0x1>;
+			num-cs = <0x1>;
+			fifo-size = <256>;
+			bits-per-word = <8>;
 	};
 
-- 
2.1.1



From p.zabel at pengutronix.de  Mon May 30 03:18:40 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Mon, 30 May 2016 12:18:40 +0200
Subject: [PATCH] reset: Put back *_optional variants
In-Reply-To: <dcf6372f-4910-bd03-f1b5-c7e0086fdead@redhat.com>
References: <ca359e013c30f27c825a9580164b01da5ca6476d.1464224883.git.johnyoun@synopsys.com>
 <12e450f0-70ea-29f8-0bf7-8a0697263f2d@redhat.com>
 <57476E48.2060204@synopsys.com>
 <dcf6372f-4910-bd03-f1b5-c7e0086fdead@redhat.com>
Message-ID: <1464603520.3808.34.camel@pengutronix.de>

Hi,

Am Freitag, den 27.05.2016, 09:06 +0200 schrieb Hans de Goede:
[...]
> >> So IMHO the following change would be a better way to fix this:
> >>
> >> --- a/include/linux/reset.h
> >> +++ b/include/linux/reset.h
> >> @@ -65,14 +65,14 @@ static inline struct reset_control *__of_reset_control_get(
> >>                                          struct device_node *node,
> >>                                          const char *id, int index, int shared)
> >>   {
> >> -   return ERR_PTR(-EINVAL);
> >> + return ERR_PTR(-ENOTSUPP);
> >>   }
> >>
> >>   static inline struct reset_control *__devm_reset_control_get(
> >>                                          struct device *dev,
> >>                                          const char *id, int index, int shared)
> >>   {
> >> -   return ERR_PTR(-EINVAL);
> >> + return ERR_PTR(-ENOTSUPP);
> >>   }
> >>
> >>   #endif /* CONFIG_RESET_CONTROLLER */
> >
> >
> > I'm good with this. However, per Philipp on a previous thread, the
> > intended behavior is to return -EINVAL for the non-optional functions.
> >
> > http://marc.info/?l=linux-usb&m=146156945528848&w=2

Adding Dinh to Cc: because he wanted this changed from -EINVAL.
My point then was that WARN_ON + -EINVAL is indented in this case.

Given that the warning backtrace already helps to identify the issue
(CONFIG_RESET_CONTROLLER disabled), and that changing the return value
to -ENOTSUPP improves consistency with the rest of the API and reduces
the amount of inline wrappers, I concur.

> As Philipp rightfully points out, calling the non-optional functions
> without CONFIG_RESET_CONTROLLER is a no-no, so IMHO we should not have to
> care too much about the error code in that case, as long as we return
> an error.
> 
> Also note that even before my patch things were already inconsistent
> with the of_...get... functions already always returning
> -ENOTSUPP when CONFIG_RESET_CONTROLLER was not set, to me it seems
> best and also KISS to just return -ENOTSUPP from all get functions
> when CONFIG_RESET_CONTROLLER is not set.
> 
> Anyways this is Philipp's call, this is all just my 2 cents.

Let the stubs return -ENOTSUPP consistently. A quick grep doesn't show
any driver handling -EINVAL explicitly either.

regards
Philipp



From heiko at sntech.de  Mon May 30 03:19:21 2016
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Mon, 30 May 2016 12:19:21 +0200
Subject: [PATCH] arm64: dts: drop "arm,
 amba-bus" in favor of "simple-bus" part 2
In-Reply-To: <1464574353-31477-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464574353-31477-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <3072536.5uGCiTBfGN@diego>

Am Montag, 30. Mai 2016, 11:12:33 schrieb Masahiro Yamada:
> Tree-wide replacement was done by commit 2ef7d5f342c1 (ARM, ARM64:
> dts: drop "arm,amba-bus" in favor of "simple-bus"), but we have some
> new users of "arm,amba-bus" at Linux 4.7-rc1.  Eliminate them now.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

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

> ---
> 
> In order to not leave these compatible strings for the release,
> is it OK to apply this patch for Linux 4.7 ?
> 
> 
> 
>  arch/arm64/boot/dts/lg/lg1312.dtsi       | 2 +-
>  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/lg/lg1312.dtsi
> b/arch/arm64/boot/dts/lg/lg1312.dtsi index 3a4e9a2..fbafa24 100644
> --- a/arch/arm64/boot/dts/lg/lg1312.dtsi
> +++ b/arch/arm64/boot/dts/lg/lg1312.dtsi
> @@ -125,7 +125,7 @@
>  		#size-cells = <1>;
>  		#interrupts-cells = <3>;
> 
> -		compatible = "arm,amba-bus";
> +		compatible = "simple-bus";
>  		interrupt-parent = <&gic>;
>  		ranges;
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index 46f325a..d7f8e06 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -163,7 +163,7 @@
>  	};
> 
>  	amba {
> -		compatible = "arm,amba-bus";
> +		compatible = "simple-bus";
>  		#address-cells = <2>;
>  		#size-cells = <2>;
>  		ranges;



From arend.vanspriel at broadcom.com  Mon May 30 03:21:33 2016
From: arend.vanspriel at broadcom.com (Arend Van Spriel)
Date: Mon, 30 May 2016 12:21:33 +0200
Subject: building and using modules on arm64 hikey board
Message-ID: <87a3195c-febb-a6c8-a679-272b9f7b59cc@broadcom.com>

I got myself an arm64 HiKey board from LeMaker and build an Android AOSP
image for it (see [1]). For development I would like to use
CONFIG_MODULES. However, when I try to insmod the build module I get:

[  287.903653] module cfg80211: overflow in relocation type 261 val
ffffffbffc006530

Looking AArch64 ELF documentation [2], section 4.6.5, it has:
code|name            |operation |overflow check   |
261 |R_AARCH64_PREL32|S + A - P |-2^31 <= X < 2^32|

So basically the highest 32 bits should all be one and so ffffffbf is
invalid. From what I could find searching internet it could be an issue
with linker options so I build kernel and modules with V=1. Here the
linker invocation for them:

+ aarch64-linux-android-ld -EL -p --no-undefined -X --build-id -o vmlinux \
-T ./arch/arm64/kernel/vmlinux.lds arch/arm64/kernel/head.o
init/built-in.o \
--start-group usr/built-in.o arch/arm64/kernel/built-in.o
arch/arm64/mm/built-in.o \
arch/arm64/net/built-in.o arch/arm64/kvm/built-in.o
arch/arm64/crypto/built-in.o \
./drivers/firmware/efi/libstub/lib.a kernel/built-in.o certs/built-in.o
mm/built-in.o \
fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o
block/built-in.o \
arch/arm64/lib/lib.a lib/lib.a arch/arm64/lib/built-in.o lib/built-in.o
drivers/built-in.o \
sound/built-in.o firmware/built-in.o net/built-in.o virt/built-in.o
--end-group .tmp_kallsyms2.o

  aarch64-linux-android-ld -EL -r  -T ./scripts/module-common.lds
--build-id \
  -o net/wireless/cfg80211.ko net/wireless/cfg80211.o
net/wireless/cfg80211.mod.o

Attached are vmlinux.lds and module-common.lds. I also tried taking
upstream arch/arm64/kernel/module.lds in hikey-linaro tree. If someone
can give a hint or educated guess at what to try it would be appreciated.

Regards,
Arend

[1] https://source.android.com/source/devices.html#building-kernel
[2]
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
-------------- next part --------------
/*
 * Common module linker script, always used when linking a module.
 * Archs are free to supply their own linker scripts.  ld will
 * combine them automatically.
 */
SECTIONS {
	/DISCARD/ : { *(.discard) }

	__ksymtab		0 : { *(SORT(___ksymtab+*)) }
	__ksymtab_gpl		0 : { *(SORT(___ksymtab_gpl+*)) }
	__ksymtab_unused	0 : { *(SORT(___ksymtab_unused+*)) }
	__ksymtab_unused_gpl	0 : { *(SORT(___ksymtab_unused_gpl+*)) }
	__ksymtab_gpl_future	0 : { *(SORT(___ksymtab_gpl_future+*)) }
	__kcrctab		0 : { *(SORT(___kcrctab+*)) }
	__kcrctab_gpl		0 : { *(SORT(___kcrctab_gpl+*)) }
	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }

	. = ALIGN(8);
	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
}
-------------- next part --------------
/*
 *
 * Automatically generated file; DO NOT EDIT.
 * Linux/arm64 4.4.9 Kernel Configuration
 *
 */
/*
 * Helper macros to use CONFIG_ options in C/CPP expressions. Note that
 * these only work with boolean and tristate options.
 */
/*
 * Getting something that works in C and CPP for an arg that may or may
 * not be defined is tricky.  Here, if we have "#define CONFIG_BOOGER 1"
 * we match on the placeholder define, insert the "0," for arg1 and generate
 * the triplet (0, 1, 0).  Then the last step cherry picks the 2nd arg (a one).
 * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
 * the last step cherry picks the 2nd arg, we get a zero.
 */
/*
 * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0
 * otherwise. For boolean options, this is equivalent to
 * IS_ENABLED(CONFIG_FOO).
 */
/*
 * IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0
 * otherwise.
 */
/*
 * IS_REACHABLE(CONFIG_FOO) evaluates to 1 if the currently compiled
 * code can call a function defined in code compiled based on CONFIG_FOO.
 * This is similar to IS_ENABLED(), but returns false when invoked from
 * built-in code when CONFIG_FOO is set to 'm'.
 */
/*
 * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
 * 0 otherwise.
 */
/*
 * ld script to make ARM Linux kernel
 * taken from the i386 version by Russell King
 * Written by Martin Mares <mj at atrey.karlin.mff.cuni.cz>
 */
/*
 * Helper macros to support writing architecture specific
 * linker scripts.
 *
 * A minimal linker scripts has following content:
 * [This is a sample, architectures may have special requiriements]
 *
 * OUTPUT_FORMAT(...)
 * OUTPUT_ARCH(...)
 * ENTRY(...)
 * SECTIONS
 * {
 *	. = START;
 *	__init_begin = .;
 *	HEAD_TEXT_SECTION
 *	INIT_TEXT_SECTION(PAGE_SIZE)
 *	INIT_DATA_SECTION(...)
 *	PERCPU_SECTION(CACHELINE_SIZE)
 *	__init_end = .;
 *
 *	_stext = .;
 *	TEXT_SECTION = 0
 *	_etext = .;
 *
 *      _sdata = .;
 *	RO_DATA_SECTION(PAGE_SIZE)
 *	RW_DATA_SECTION(...)
 *	_edata = .;
 *
 *	EXCEPTION_TABLE(...)
 *	NOTES
 *
 *	BSS_SECTION(0, 0, 0)
 *	_end = .;
 *
 *	STABS_DEBUG
 *	DWARF_DEBUG
 *
 *	DISCARDS		// must be the last
 * }
 *
 * [__init_begin, __init_end] is the init section that may be freed after init
 * 	// __init_begin and __init_end should be page aligned, so that we can
 *	// free the whole .init memory
 * [_stext, _etext] is the text section
 * [_sdata, _edata] is the data section
 *
 * Some of the included output section have their own set of constants.
 * Examples are: [__initramfs_start, __initramfs_end] for initramfs and
 *               [__nosave_begin, __nosave_end] for the nosave data
 */
/*
 * Export symbols from the kernel to modules.  Forked from module.h
 * to reduce the amount of pointless cruft we feed to gcc when only
 * exporting a simple symbol or two.
 *
 * Try not to add #includes here.  It slows compilation and makes kernel
 * hackers place grumpy comments in header files.
 */
/* Some toolchains use a `_' prefix for all user symbols. */
/* Indirect, so macros are expanded before pasting. */
/* Align . to a 8 byte boundary equals to maximum function alignment. */
/*
 * Align to a 32 byte boundary equal to the
 * alignment gcc 4.5 uses for a struct
 */
/* The actual configuration determine if the init/exit sections
 * are handled as text/data or they can be discarded (which
 * often happens at runtime)
 */
/* .data section */
/*
 * Data section helpers
 */
/*
 * Read only Data
 */
/* RODATA & RO_DATA provided for backward compatibility.
 * All archs are supposed to use RO_DATA() */
/* .text section. Map to function alignment to avoid address changes
 * during second ld run in second ld pass when generating System.map */
/* sched.text is aling to function alignment to secure we have same
 * address even at second ld pass when generating System.map */
/* spinlock.text is aling to function alignment to secure we have same
 * address even at second ld pass when generating System.map */
/* Section used for early init (in .S files) */
/*
 * Exception table
 */
/*
 * Init task
 */
/* init and exit section handling */
/*
 * bss (Block Started by Symbol) - uninitialized data
 * zeroed during startup
 */
/*
 * Allow archectures to redefine BSS_FIRST_SECTIONS to add extra
 * sections to the front of bss.
 */
/*
 * DWARF debug sections.
 * Symbols in the DWARF debugging sections are relative to
 * the beginning of the section so we begin them at 0.
 */
  /* Stabs debugging sections.  */
/*
 * Default discarded sections.
 *
 * Some archs want to discard exit text/data at runtime rather than
 * link time due to cross-section references such as alt instructions,
 * bug table, eh_frame, etc.  DISCARDS must be the last of output
 * section definitions so that such archs put those in earlier section
 * definitions.
 */
/**
 * PERCPU_INPUT - the percpu input sections
 * @cacheline: cacheline size
 *
 * The core percpu section names and core symbols which do not rely
 * directly upon load addresses.
 *
 * @cacheline is used to align subsections to avoid false cacheline
 * sharing between subsections for different purposes.
 */
/**
 * PERCPU_VADDR - define output section for percpu area
 * @cacheline: cacheline size
 * @vaddr: explicit base address (optional)
 * @phdr: destination PHDR (optional)
 *
 * Macro which expands to output section for percpu area.
 *
 * @cacheline is used to align subsections to avoid false cacheline
 * sharing between subsections for different purposes.
 *
 * If @vaddr is not blank, it specifies explicit base address and all
 * percpu symbols will be offset from the given address.  If blank,
 * @vaddr always equals @laddr + LOAD_OFFSET.
 *
 * @phdr defines the output PHDR to use if not blank.  Be warned that
 * output PHDR is sticky.  If @phdr is specified, the next output
 * section in the linker script will go there too.  @phdr should have
 * a leading colon.
 *
 * Note that this macros defines __per_cpu_load as an absolute symbol.
 * If there is no need to put the percpu section at a predetermined
 * address, use PERCPU_SECTION.
 */
/**
 * PERCPU_SECTION - define output section for percpu area, simple version
 * @cacheline: cacheline size
 *
 * Align to PAGE_SIZE and outputs output section for percpu area.  This
 * macro doesn't manipulate @vaddr or @phdr and __per_cpu_load and
 * __per_cpu_start will be identical.
 *
 * This macro is equivalent to ALIGN(PAGE_SIZE); PERCPU_VADDR(@cacheline,,)
 * except that __per_cpu_load is defined as a relative symbol against
 * .data..percpu which is required for relocatable x86_32 configuration.
 */
/*
 * Definition of the high level *_SECTION macros
 * They will fit only a subset of the architectures
 */
/*
 * Writeable data.
 * All sections are combined in a single .data section.
 * The sections following CONSTRUCTORS are arranged so their
 * typical alignment matches.
 * A cacheline is typical/always less than a PAGE_SIZE so
 * the sections that has this restriction (or similar)
 * is located before the ones requiring PAGE_SIZE alignment.
 * NOSAVE_DATA starts and ends with a PAGE_SIZE alignment which
 * matches the requirement of PAGE_ALIGNED_DATA.
 *
 * use 0 as page_align if page_aligned data is not used */
/*
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Memory returned by kmalloc() may be used for DMA, so we must make
 * sure that all such allocations are cache aligned. Otherwise,
 * unrelated code may cause parts of the buffer to be read into the
 * cache before the transfer is done, causing old data to be seen by
 * the CPU.
 */
/*
 * Kernel page table mapping
 *
 * Copyright (C) 2015 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * The linear mapping and the start of memory are both 2M aligned (per
 * the arm64 booting.txt requirements). Hence we can use section mapping
 * with 4K (section size = 2M) but not with 16K (section size = 32M) or
 * 64K (section size = 512M).
 */
/*
 * The idmap and swapper page tables need some space reserved in the kernel
 * image. Both require pgd, pud (4 levels only) and pmd tables to (section)
 * map the kernel. With the 64K page configuration, swapper and idmap need to
 * map to pte level. The swapper also maps the FDT (see __create_page_tables
 * for more information). Note that the number of ID map translation levels
 * could be increased on the fly if system RAM is out of reach for the default
 * VA range, so pages required to map highest possible PA are reserved in all
 * cases.
 */
/* Initial memory map size */
/* The size of the initial kernel direct mapping */
/*
 * Initial memory map attributes.
 */
/*
 * Based on arch/arm/include/asm/thread_info.h
 *
 * Copyright (C) 2002 Russell King.
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Allow us to mark functions as 'deprecated' and have gcc emit a nice
 * warning for each use, in hopes of speeding the functions removal.
 * Usage is:
 * 		int __deprecated foo(void)
 */
/*
 * Allow us to avoid 'defined but not used' warnings on functions and data,
 * as well as force them to be emitted to the assembly file.
 *
 * As of gcc 3.4, static functions that are not marked with attribute((used))
 * may be elided from the assembly file.  As of gcc 3.4, static data not so
 * marked will not be elided, but this may change in a future gcc version.
 *
 * NOTE: Because distributions shipped with a backported unit-at-a-time
 * compiler in gcc 3.3, we must define __used to be __attribute__((used))
 * for gcc >=3.3 instead of 3.4.
 *
 * In prior versions of gcc, such functions and data would be emitted, but
 * would be warned about except with attribute((unused)).
 *
 * Mark functions that are referenced only in inline assembly as __used so
 * the code is emitted even though it appears to be unreferenced.
 */
/*
 * Rather then using noinline to prevent stack consumption, use
 * noinline_for_stack instead.  For documentation reasons.
 */
/*
 * From the GCC manual:
 *
 * Many functions do not examine any values except their arguments,
 * and have no effects except the return value.  Basically this is
 * just slightly more strict class than the `pure' attribute above,
 * since function is not allowed to read global memory.
 *
 * Note that a function that has pointer arguments and examines the
 * data pointed to must _not_ be declared `const'.  Likewise, a
 * function that calls a non-`const' function usually must not be
 * `const'.  It does not make sense for a `const' function to return
 * `void'.
 */
/*
 * Tell gcc if a function is cold. The compiler will assume any path
 * directly leading to the call is unlikely.
 */
/* Simple shorthand for a section definition */
/*
 * Assume alignment of return value.
 */
/* Are two types/vars the same type (ignoring qualifiers)? */
/* Is this type a native word size -- useful for atomic operations */
/* Compile time object size, -1 for unknown */
/*
 * Sparse complains of variable sized arrays due to the temporary variable in
 * __compiletime_assert. Unfortunately we can't just expand it out to make
 * sparse see a constant array size without breaking compiletime_assert on old
 * versions of GCC (e.g. 4.2.4), so hide the array from sparse altogether.
 */
/**
 * compiletime_assert - break build and emit msg if condition is false
 * @condition: a compile-time constant condition to check
 * @msg:       a message to emit if condition is false
 *
 * In tradition of POSIX assert, this macro will break the build if the
 * supplied condition is *false*, emitting the supplied error message if the
 * compiler has support to do so.
 */
/*
 * Prevent the compiler from merging or refetching accesses.  The compiler
 * is also forbidden from reordering successive instances of ACCESS_ONCE(),
 * but only when the compiler is aware of some particular ordering.  One way
 * to make the compiler aware of ordering is to put the two invocations of
 * ACCESS_ONCE() in different C statements.
 *
 * ACCESS_ONCE will only work on scalar types. For union types, ACCESS_ONCE
 * on a union member will work as long as the size of the member matches the
 * size of the union and the size is smaller than word size.
 *
 * The major use cases of ACCESS_ONCE used to be (1) Mediating communication
 * between process-level code and irq/NMI handlers, all running on the same CPU,
 * and (2) Ensuring that the compiler does not  fold, spindle, or otherwise
 * mutilate accesses that either do not require ordering or that interact
 * with an explicit memory barrier or atomic instruction that provides the
 * required ordering.
 *
 * If possible use READ_ONCE()/WRITE_ONCE() instead.
 */
/**
 * lockless_dereference() - safely load a pointer for later dereference
 * @p: The pointer to load
 *
 * Similar to rcu_dereference(), but for situations where the pointed-to
 * object's lifetime is managed by something other than RCU.  That
 * "something other" might be reference counting or simple immortality.
 */
/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
/*
 * thread information flags:
 *  TIF_SYSCALL_TRACE	- syscall trace active
 *  TIF_SYSCALL_TRACEPOINT - syscall tracepoint for ftrace
 *  TIF_SYSCALL_AUDIT	- syscall auditing
 *  TIF_SECOMP		- syscall secure computing
 *  TIF_SIGPENDING	- signal pending
 *  TIF_NEED_RESCHED	- rescheduling necessary
 *  TIF_NOTIFY_RESUME	- callback before returning to user
 *  TIF_USEDFPU		- FPU was used by this task this quantum (SMP)
 */
/*
 * Based on arch/arm/include/asm/memory.h
 *
 * Copyright (C) 2000-2002 Russell King
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Note: this file should not be included by non-asm/.h files
 */
/* const.h: Macros for dealing with constants.  */
/* Some constant macros are used in both assembler and
 * C code.  Therefore we cannot annotate them always with
 * 'UL' and other type specifiers unilaterally.  We
 * use the following macros to deal with this.
 *
 * Similarly, _AT() will cast an expression with a type in C, but
 * leave it unchanged in asm.
 */
/*
 * int-ll64 is used everywhere now.
 */
/*
 * asm-generic/int-ll64.h
 *
 * Integer declarations for architectures which use "long long"
 * for 64-bit types.
 */
/*
 * asm-generic/int-ll64.h
 *
 * Integer declarations for architectures which use "long long"
 * for 64-bit types.
 */
/*
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * There seems to be no way of detecting this automatically from user
 * space, so 64 bit architectures should override this in their
 * bitsperlong.h. In particular, an architecture that supports
 * both 32 and 64 bit user space must not rely on CONFIG_64BIT
 * to decide it, but rather check a compiler provided macro.
 */
/*
 * FIXME: The check currently breaks x86-64 build, so it's
 * temporarily disabled. Please fix x86-64 and reenable
 */
/* This is a placeholder, to be removed over time */
/*
 * include/linux/sizes.h
 *
 * 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.
 */
/*
 * Allow for constants defined here to be used from assembly code
 * by prepending the UL suffix only with actual C code compilation.
 */
/*
 * Size of the PCI I/O space. This must remain a power of two so that
 * IO_SPACE_LIMIT acts as a mask for the low bits of I/O addresses.
 */
/*
 * PAGE_OFFSET - the virtual address of the start of the kernel image (top
 *		 (VA_BITS - 1))
 * VA_BITS - the maximum number of bits for virtual addresses.
 * VA_START - the first kernel virtual address.
 * TASK_SIZE - the maximum size of a user space task.
 * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area.
 * The module space lives between the addresses given by TASK_SIZE
 * and PAGE_OFFSET - it must be within 128MB of the kernel text.
 */
/*
 * Physical vs virtual RAM address space conversion.  These are
 * private definitions which should NOT be used outside memory.h
 * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
 */
/*
 * Convert a page to/from a physical address
 */
/*
 * Memory types available.
 */
/*
 * Memory types for Stage-2 translation
 */
/*
 * Based on arch/arm/include/asm/page.h
 *
 * Copyright (C) 1995-2003 Russell King
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/* PAGE_SHIFT determines the page size */
/* CONT_SHIFT determines the number of pages which can be tracked together  */
/*
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Copyright (C) 2015  ARM Limited
 * Author: Dave Martin <Dave.Martin at arm.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * This error code is special: arch syscall entry code will return
 * -ENOSYS if users try to call a syscall that doesn't exist.  To keep
 * failures of syscalls that really do exist distinguishable from
 * failures due to attempts to use a nonexistent syscall, syscall
 * implementations should refrain from returning -ENOSYS.
 */
/* for robust mutexes */
/*
 * These should never be seen by user programs.  To return one of ERESTART*
 * codes, signal_pending() MUST be set.  Note that ptrace can observe these
 * at syscall exit tracing, but they will never be left for the debugged user
 * process to see.
 */
/* Defined for the NFSv3 protocol */
/*
 * Copyright (C) 2013 - ARM Ltd
 * Author: Marc Zyngier <marc.zyngier at arm.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Based on arch/arm/include/asm/memory.h
 *
 * Copyright (C) 2000-2002 Russell King
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Note: this file should not be included by non-asm/.h files
 */
/* Unallocated EC: 0x02 */
/* Unallocated EC: 0x09 - 0x0B */
/* Unallocated EC: 0x0d */
/* Unallocated EC: 0x0F - 0x10 */
/* Unallocated EC: 0x14 */
/* Unallocated EC: 0x19 - 0x1E */
/* Unallocated EC: 0x23 */
/* Unallocated EC: 0x27 */
/* Unallocated EC: 0x29 - 0x2B */
/* Unallocated EC: 0x2D - 0x2E */
/* Unallocated EC: 0x36 - 0x37 */
/* Unallocated EC: 0x39 */
/* Unallocted EC: 0x3B */
/* Unallocated EC: 0x3D - 0x3F */
/* ESR value templates for specific events */
/* BRK instruction trap from AArch64 state */
/*
 * Copyright (C) 2013 Huawei Ltd.
 * Author: Jiang Liu <liuj97 at gmail.com>
 *
 * Copyright (C) 2014 Zi Shen Lim <zlim.lnx at gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/* A64 instructions are always 32 bits. */
/*
 * Based on arch/arm/include/asm/ptrace.h
 *
 * Copyright (C) 1996-2003 Russell King
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Based on arch/arm/include/asm/ptrace.h
 *
 * Copyright (C) 1996-2003 Russell King
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
 */
/*
 * PSR bits
 */
/* AArch32 CPSR bits */
/* AArch64 SPSR bits */
/*
 * Groups of PSR bits
 */
/* Current Exception Level values, as contained in CurrentEL */
/* AArch32-specific ptrace requests */
/* AArch32 CPSR bits */
/*
 * These are 'magic' values for PTRACE_PEEKUSR that return info about where a
 * process is located in memory.
 */
/* Low-level stepping controls. */
/* MDSCR_EL1 enabling bits */
/* AArch64 */
/*
 * Break point instruction encoding
 */
/*
 * #imm16 values used for BRK instruction generation
 * Allowed values for kgbd are 0x400 - 0x7ff
 * 0x100: for triggering a fault on purpose (reserved)
 * 0x400: for dynamic BRK instruction
 * 0x401: for compile time BRK instruction
 * 0x800: kernel-mode BUG() and WARN() traps
 */
/*
 * BRK instruction encoding
 * The #imm16 value should be placed at bits[20:5] within BRK ins
 */
/*
 * BRK instruction for provoking a fault on purpose
 * Unlike kgdb, #imm16 value with unallocated handler is used for faulting.
 */
/* AArch32 */
/*
 * Based on arch/arm/include/asm/proc-fns.h
 *
 * Copyright (C) 1997-1999 Russell King
 * Copyright (C) 2000 Deep Blue Solutions Ltd
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Based on arch/arm/include/asm/memory.h
 *
 * Copyright (C) 2000-2002 Russell King
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Note: this file should not be included by non-asm/.h files
 */
/*
 * Copyright (C) 2012 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Number of page-table levels required to address 'va_bits' wide
 * address, without section mapping. We resolve the top (va_bits - PAGE_SHIFT)
 * bits with (PAGE_SHIFT - 3) bits at each page table level. Hence:
 *
 *  levels = DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - 3))
 *
 * where DIV_ROUND_UP(n, d) => (((n) + (d) - 1) / (d))
 *
 * We cannot include linux/kernel.h which defines DIV_ROUND_UP here
 * due to build issues. So we open code DIV_ROUND_UP here:
 *
 *	((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - 3) - 1) / (PAGE_SHIFT - 3))
 *
 * which gets simplified as :
 */
/*
 * Size mapped by an entry at level n ( 0 <= n <= 3)
 * We map (PAGE_SHIFT - 3) at all translation levels and PAGE_SHIFT bits
 * in the final page. The maximum number of translation levels supported by
 * the architecture is 4. Hence, starting at at level n, we have further
 * ((4 - n) - 1) levels of translation excluding the offset within the page.
 * So, the total number of bits mapped by an entry at level n is :
 *
 *  ((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT
 *
 * Rearranging it a bit we get :
 *   (4 - n) * (PAGE_SHIFT - 3) + 3
 */
/*
 * PMD_SHIFT determines the size a level 2 page table entry can map.
 */
/*
 * PUD_SHIFT determines the size a level 1 page table entry can map.
 */
/*
 * PGDIR_SHIFT determines the size a top-level page table entry can map
 * (depending on the configuration, this level can be 0, 1 or 2).
 */
/*
 * Section address mask and size definitions.
 */
/*
 * Contiguous page definitions.
 */
/* the the numerical offset of the PTE within a range of CONT_PTES */
/*
 * Hardware page table definitions.
 *
 * Level 1 descriptor (PUD).
 */
/*
 * Level 2 descriptor (PMD).
 */
/*
 * Section
 */
/*
 * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
 */
/*
 * Level 3 descriptor (PTE).
 */
/*
 * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
 */
/*
 * 2nd stage PTE definitions
 */
/*
 * Memory Attribute override for Stage-2 (MemAttr[3:0])
 */
/*
 * EL2/HYP PTE/PMD definitions
 */
/*
 * Highest possible physical address supported.
 */
/*
 * TCR flags.
 */
/*
 * Software defined PTE bits definition.
 */
/*
 * VMALLOC and SPARSEMEM_VMEMMAP ranges.
 *
 * VMEMAP_SIZE: allows the whole linear region to be covered by a struct page array
 *	(rounded up to PUD_SIZE).
 * VMALLOC_START: beginning of the kernel VA space
 * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space,
 *	fixed mappings and modules
 */
/*
 * Linker script macros to generate Image header fields.
 *
 * Copyright (C) 2014 ARM 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.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * There aren't any ELF relocations we can use to endian-swap values known only
 * at link time (e.g. the subtraction of two symbol addresses), so we must get
 * the linker to endian-swap certain values before emitting them.
 */
/*
 * These will output as part of the Image header, which should be little-endian
 * regardless of the endianness of the kernel. While constant values could be
 * endian swapped in head.S, all are done here for consistency.
 */
/*
 * The EFI stub has its own symbol namespace prefixed by __efistub_, to
 * isolate it from the kernel proper. The following symbols are legally
 * accessed by the stub, so provide some aliases to make them accessible.
 * Only include data symbols here, or text symbols of functions that are
 * guaranteed to be safe when executed at another offset than they were
 * linked at. The routines below are all implemented in assembler in a
 * position independent manner
 */
__efistub_memcmp = __pi_memcmp;
__efistub_memchr = __pi_memchr;
__efistub_memcpy = __pi_memcpy;
__efistub_memmove = __pi_memmove;
__efistub_memset = __pi_memset;
__efistub_strlen = __pi_strlen;
__efistub_strcmp = __pi_strcmp;
__efistub_strncmp = __pi_strncmp;
__efistub___flush_dcache_area = __pi___flush_dcache_area;
__efistub__text = _text;
__efistub__end = _end;
__efistub__edata = _edata;
/* .exit.text needed in case of alternative patching */
OUTPUT_ARCH(aarch64)
ENTRY(_text)
jiffies = jiffies_64;
/*
 * The size of the PE/COFF section that covers the kernel image, which
 * runs from stext to _edata, must be a round multiple of the PE/COFF
 * FileAlignment, which we set to its minimum value of 0x200. 'stext'
 * itself is 4 KB aligned, so padding out _edata to a 0x200 aligned
 * boundary should be sufficient.
 */
PECOFF_FILE_ALIGNMENT = 0x200;
SECTIONS
{
 /*
	 * XXX: The linker does not define how output sections are
	 * assigned to input sections when there are multiple statements
	 * matching the same input section name.  There is no documented
	 * order of matching.
	 */
 /DISCARD/ : {
 
 
  *(.exitcall.exit)
  *(.discard)
  *(.discard.*)
 }
 . = (0xffffffffffffffff << ((39) - 1)) + 0x00080000;
 .head.text : {
  _text = .;
  *(.head.text)
 }
 . = ALIGN(1<<12);
 .text : { /* Real text segment		*/
  _stext = .; /* Text and read-only data	*/
   __exception_text_start = .;
   *(.exception.text)
   __exception_text_end = .;
   . = ALIGN(8); __irqentry_text_start = .; *(.irqentry.text) __irqentry_text_end = .;
   . = ALIGN(8); *(.text.hot .text .text.fixup .text.unlikely) *(.ref.text)
   . = ALIGN(8); __sched_text_start = .; *(.sched.text) __sched_text_end = .;
   . = ALIGN(8); __lock_text_start = .; *(.spinlock.text) __lock_text_end = .;
   . = ALIGN(0x00001000); __hyp_idmap_text_start = .; *(.hyp.idmap.text) __hyp_idmap_text_end = .; __hyp_text_start = .; *(.hyp.text) __hyp_text_end = .;
   . = ALIGN(0x00001000); __idmap_text_start = .; *(.idmap.text) __idmap_text_end = .;
   *(.fixup)
   *(.gnu.warning)
  . = ALIGN(16);
  *(.got) /* Global offset table		*/
 }
 . = ALIGN(1<<12);
 . = ALIGN(((1 << 12))); .rodata : AT(ADDR(.rodata) - 0) { __start_rodata = .; *(.rodata) *(.rodata.*) *(__vermagic) . = ALIGN(8); __start___tracepoints_ptrs = .; *(__tracepoints_ptrs) __stop___tracepoints_ptrs = .; *(__tracepoints_strings) } .rodata1 : AT(ADDR(.rodata1) - 0) { *(.rodata1) } . = ALIGN(8); __bug_table : AT(ADDR(__bug_table) - 0) { __start___bug_table = .; *(__bug_table) __stop___bug_table = .; } .pci_fixup : AT(ADDR(.pci_fixup) - 0) { __start_pci_fixups_early = .; *(.pci_fixup_early) __end_pci_fixups_early = .; __start_pci_fixups_header = .; *(.pci_fixup_header) __end_pci_fixups_header = .; __start_pci_fixups_final = .; *(.pci_fixup_final) __end_pci_fixups_final = .; __start_pci_fixups_enable = .; *(.pci_fixup_enable) __end_pci_fixups_enable = .; __start_pci_fixups_resume = .; *(.pci_fixup_resume) __end_pci_fixups_resume = .; __start_pci_fixups_resume_early = .; *(.pci_fixup_resume_early) __end_pci_fixups_resume_early = .; __start_pci_fixups_suspend = .; *(.pci_fixup_suspend) __end_pci_fixups_suspend = .; __start_pci_fixups_suspend_late = .; *(.pci_fixup_suspend_late) __end_pci_fixups_suspend_late = .; } .builtin_fw : AT(ADDR(.builtin_fw) - 0) { __start_builtin_fw = .; *(.builtin_fw) __end_builtin_fw = .; } __ksymtab : AT(ADDR(__ksymtab) - 0) { __start___ksymtab = .; *(SORT(___ksymtab+*)) __stop___ksymtab = .; } __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - 0) { __start___ksymtab_gpl = .; *(SORT(___ksymtab_gpl+*)) __stop___ksymtab_gpl = .; } __ksymtab_unused : AT(ADDR(__ksymtab_unused) - 0) { __start___ksymtab_unused = .; *(SORT(___ksymtab_unused+*)) __stop___ksymtab_unused = .; } __ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - 0) { __start___ksymtab_unused_gpl = .; *(SORT(___ksymtab_unused_gpl+*)) __stop___ksymtab_unused_gpl = .; } __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - 0) { __start___ksymtab_gpl_future = .; *(SORT(___ksymtab_gpl_future+*)) __stop___ksymtab_gpl_future = .; } __kcrctab : AT(ADDR(__kcrctab) - 0) { __start___kcrctab = .; *(SORT(___kcrctab+*)) __stop___kcrctab = .; } __kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - 0) { __start___kcrctab_gpl = .; *(SORT(___kcrctab_gpl+*)) __stop___kcrctab_gpl = .; } __kcrctab_unused : AT(ADDR(__kcrctab_unused) - 0) { __start___kcrctab_unused = .; *(SORT(___kcrctab_unused+*)) __stop___kcrctab_unused = .; } __kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - 0) { __start___kcrctab_unused_gpl = .; *(SORT(___kcrctab_unused_gpl+*)) __stop___kcrctab_unused_gpl = .; } __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - 0) { __start___kcrctab_gpl_future = .; *(SORT(___kcrctab_gpl_future+*)) __stop___kcrctab_gpl_future = .; } __ksymtab_strings : AT(ADDR(__ksymtab_strings) - 0) { *(__ksymtab_strings) } __init_rodata : AT(ADDR(__init_rodata) - 0) { *(.ref.rodata) } __param : AT(ADDR(__param) - 0) { __start___param = .; *(__param) __stop___param = .; } __modver : AT(ADDR(__modver) - 0) { __start___modver = .; *(__modver) __stop___modver = .; . = ALIGN(((1 << 12))); __end_rodata = .; } . = ALIGN(((1 << 12)));
 . = ALIGN(8); __ex_table : AT(ADDR(__ex_table) - 0) { __start___ex_table = .; *(__ex_table) __stop___ex_table = .; }
 .notes : AT(ADDR(.notes) - 0) { __start_notes = .; *(.note.*) __stop_notes = .; }
 . = ALIGN(1<<12);
 _etext = .; /* End of text and rodata section */
 . = ALIGN(1<<12);
 __init_begin = .;
 . = ALIGN(8); .init.text : AT(ADDR(.init.text) - 0) { _sinittext = .; *(.init.text) *(.meminit.text) _einittext = .; }
 .exit.text : {
  *(.exit.text) *(.memexit.text)
 }
 . = ALIGN(1<<12);
 .init.data : {
  *(.init.data) *(.meminit.data) . = ALIGN(8); __start_mcount_loc = .; *(__mcount_loc) __stop_mcount_loc = .; *(.init.rodata) . = ALIGN(8); __start_ftrace_events = .; *(_ftrace_events) __stop_ftrace_events = .; __start_ftrace_enum_maps = .; *(_ftrace_enum_map) __stop_ftrace_enum_maps = .; . = ALIGN(8); __start_syscalls_metadata = .; *(__syscalls_metadata) __stop_syscalls_metadata = .; *(.meminit.rodata) . = ALIGN(8); __clk_of_table = .; *(__clk_of_table) *(__clk_of_table_end) . = ALIGN(8); __reservedmem_of_table = .; *(__reservedmem_of_table) *(__reservedmem_of_table_end) . = ALIGN(8); __clksrc_of_table = .; *(__clksrc_of_table) *(__clksrc_of_table_end) . = ALIGN(8); __cpu_method_of_table = .; *(__cpu_method_of_table) *(__cpu_method_of_table_end) . = ALIGN(8); __cpuidle_method_of_table = .; *(__cpuidle_method_of_table) *(__cpuidle_method_of_table_end) . = ALIGN(32); __dtb_start = .; *(.dtb.init.rodata) __dtb_end = .; . = ALIGN(8); __irqchip_of_table = .; *(__irqchip_of_table) *(__irqchip_of_table_end) . = ALIGN(8); __irqchip_acpi_probe_table = .; *(__irqchip_acpi_probe_table) __irqchip_acpi_probe_table_end = .; . = ALIGN(8); __clksrc_acpi_probe_table = .; *(__clksrc_acpi_probe_table) __clksrc_acpi_probe_table_end = .; . = ALIGN(32); __earlycon_table = .; *(__earlycon_table) *(__earlycon_table_end) . = ALIGN(8); __earlycon_of_table = .; *(__earlycon_of_table) *(__earlycon_of_table_end)
  . = ALIGN(16); __setup_start = .; *(.init.setup) __setup_end = .;
  __initcall_start = .; *(.initcallearly.init) __initcall0_start = .; *(.initcall0.init) *(.initcall0s.init) __initcall1_start = .; *(.initcall1.init) *(.initcall1s.init) __initcall2_start = .; *(.initcall2.init) *(.initcall2s.init) __initcall3_start = .; *(.initcall3.init) *(.initcall3s.init) __initcall4_start = .; *(.initcall4.init) *(.initcall4s.init) __initcall5_start = .; *(.initcall5.init) *(.initcall5s.init) __initcallrootfs_start = .; *(.initcallrootfs.init) *(.initcallrootfss.init) __initcall6_start = .; *(.initcall6.init) *(.initcall6s.init) __initcall7_start = .; *(.initcall7.init) *(.initcall7s.init) __initcall_end = .;
  __con_initcall_start = .; *(.con_initcall.init) __con_initcall_end = .;
  __security_initcall_start = .; *(.security_initcall.init) __security_initcall_end = .;
  . = ALIGN(4); __initramfs_start = .; *(.init.ramfs) . = ALIGN(8); *(.init.ramfs.info)
 }
 .exit.data : {
  *(.exit.data) *(.memexit.data) *(.memexit.rodata)
 }
 . = ALIGN((1 << 12)); .data..percpu : AT(ADDR(.data..percpu) - 0) { __per_cpu_load = .; __per_cpu_start = .; *(.data..percpu..first) . = ALIGN((1 << 12)); *(.data..percpu..page_aligned) . = ALIGN((1 << 7)); *(.data..percpu..read_mostly) . = ALIGN((1 << 7)); *(.data..percpu) *(.data..percpu..shared_aligned) __per_cpu_end = .; }
 . = ALIGN((1 << 12));
 __init_end = .;
 . = ALIGN(4);
 .altinstructions : {
  __alt_instructions = .;
  *(.altinstructions)
  __alt_instructions_end = .;
 }
 .altinstr_replacement : {
  *(.altinstr_replacement)
 }
 . = ALIGN((1 << 12));
 _data = .;
 _sdata = .;
 . = ALIGN((1 << 12)); .data : AT(ADDR(.data) - 0) { . = ALIGN(16384); *(.data..init_task) . = ALIGN((1 << 12)); __nosave_begin = .; *(.data..nosave) . = ALIGN((1 << 12)); __nosave_end = .; . = ALIGN((1 << 12)); *(.data..page_aligned) . = ALIGN((1 << 7)); *(.data..cacheline_aligned) . = ALIGN((1 << 7)); *(.data..read_mostly) . = ALIGN((1 << 7)); *(.data) *(.ref.data) *(.data..shared_aligned) *(.data.unlikely) . = ALIGN(32); *(__tracepoints) . = ALIGN(8); __start___jump_table = .; *(__jump_table) __stop___jump_table = .; . = ALIGN(8); __start___verbose = .; *(__verbose) __stop___verbose = .; __start___trace_bprintk_fmt = .; *(__trace_printk_fmt) __stop___trace_bprintk_fmt = .; __start___tracepoint_str = .; *(__tracepoint_str) __stop___tracepoint_str = .; CONSTRUCTORS }
 .pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }
 _edata = .;
 . = ALIGN(0); __bss_start = .; . = ALIGN(0); .sbss : AT(ADDR(.sbss) - 0) { *(.sbss) *(.scommon) } . = ALIGN(0); .bss : AT(ADDR(.bss) - 0) { *(.bss..page_aligned) *(.dynbss) *(.bss) *(COMMON) } . = ALIGN(0); __bss_stop = .;
 . = ALIGN((1 << 12));
 idmap_pg_dir = .;
 . += ((((((48)) - 4) / (12 - 3)) - 1) * (1 << 12));
 swapper_pg_dir = .;
 . += ((3 - 1) * (1 << 12));
 _end = .;
 .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { *(.comment) }
 _kernel_size_le = ((_end - _text) & 0xffffffffffffffff); _kernel_offset_le = ((0x00080000) & 0xffffffffffffffff); _kernel_flags_le = ((((0 << 0) | (((12 - 10) / 2) << 1))) & 0xffffffffffffffff);
}
/*
 * The HYP init code and ID map text can't be longer than a page each,
 * and should not cross a page boundary.
 */
ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & ~(0x00001000 - 1)) <= 0x00001000,
 "HYP init code too big or misaligned")
ASSERT(__idmap_text_end - (__idmap_text_start & ~(0x00001000 - 1)) <= 0x00001000,
 "ID map text too big or misaligned")
/*
 * If padding is applied before .head.text, virt<->phys conversions will fail.
 */
ASSERT(_text == ((0xffffffffffffffff << ((39) - 1)) + 0x00080000), "HEAD is misaligned")

From yt.shen at mediatek.com  Mon May 30 03:23:30 2016
From: yt.shen at mediatek.com (YT Shen)
Date: Mon, 30 May 2016 18:23:30 +0800
Subject: [RFC v2 1/5] drm/mediatek: rename macros, add chip suffix
In-Reply-To: <CACvgo506uzWug+mEk5OOs-6M9WZnOc-FBChGcf-4DcqqotHpHA@mail.gmail.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
 <1463756736-46573-2-git-send-email-yt.shen@mediatek.com>
 <CACvgo506uzWug+mEk5OOs-6M9WZnOc-FBChGcf-4DcqqotHpHA@mail.gmail.com>
Message-ID: <1464603810.21437.17.camel@mtksdaap41>

Hi Emil,

On Fri, 2016-05-27 at 10:30 +0100, Emil Velikov wrote:
> On 20 May 2016 at 16:05,  <yt.shen at mediatek.com> wrote:
> > From: YT Shen <yt.shen at mediatek.com>
> >
> > Add MT8173 suffix for hardware related macros.
> >
> Why suffix ? Pretty much everyone else uses prefix.
No problem, I will use prefix in the future.


> 
> -Emil




From yt.shen at mediatek.com  Mon May 30 03:24:41 2016
From: yt.shen at mediatek.com (YT Shen)
Date: Mon, 30 May 2016 18:24:41 +0800
Subject: [RFC v2 2/5] drm/mediatke: add support for Mediatek SoC MT2701
In-Reply-To: <CACvgo51gUVtVZtanQh787YeB8F_WHsNx6b1Oi0iBAEYLWZtJMw@mail.gmail.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
 <1463756736-46573-3-git-send-email-yt.shen@mediatek.com>
 <CACvgo51gUVtVZtanQh787YeB8F_WHsNx6b1Oi0iBAEYLWZtJMw@mail.gmail.com>
Message-ID: <1464603881.21437.18.camel@mtksdaap41>

Hi Emil,
On Fri, 2016-05-27 at 10:35 +0100, Emil Velikov wrote:
> Hi YT Shen,
> 
> There's a typo in the commit summary - s/mediatke/mediatek/.
Ooops, even I type this word everyday, I still made a mistake...
> 
> On 20 May 2016 at 16:05,  <yt.shen at mediatek.com> wrote:
> > From: YT Shen <yt.shen at mediatek.com>
> >
> > This patch add support for the Mediatek MT2701 DISP subsystem.
> > There is only one OVL engine in MT2701.
> >
> As is you introduce a broken driver only to fix it up with patches 3/5
> and 4/5. You really want to have this patch as 4/5, with the MT2701
> hunks from 3/5 merged in here.
OK, I will reorder the patch series in the next version.
2/5: add *driver_data for hardware specific settings
3/5: add shadow register support
4/5: add support for Mediatek SoC MT2701

> 
> Regards,
> Emil




From yt.shen at mediatek.com  Mon May 30 03:26:44 2016
From: yt.shen at mediatek.com (YT Shen)
Date: Mon, 30 May 2016 18:26:44 +0800
Subject: [RFC v2 3/5] drm/mediatek: add *driver_data for different
 hardware settings
In-Reply-To: <CACvgo52xB0KwumC75u2dxfz_yv2PNE0Gem+0t8dqV9qn+pPRLg@mail.gmail.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
 <1463756736-46573-4-git-send-email-yt.shen@mediatek.com>
 <1463996582.30093.5.camel@mtksdaap41>
 <1464334313.31149.16.camel@mtksdaap41>
 <CACvgo52xB0KwumC75u2dxfz_yv2PNE0Gem+0t8dqV9qn+pPRLg@mail.gmail.com>
Message-ID: <1464604004.21437.19.camel@mtksdaap41>

Hi Emil,

Thanks for your review.

On Fri, 2016-05-27 at 10:24 +0100, Emil Velikov wrote:
> On 27 May 2016 at 08:31, YT Shen <yt.shen at mediatek.com> wrote:
> > Hi CK,
> >
> >
> > On Mon, 2016-05-23 at 17:43 +0800, CK Hu wrote:
> >> Hi, YT:
> >>
> >> One comment below.
> >>
> >> On Fri, 2016-05-20 at 23:05 +0800, yt.shen at mediatek.com wrote:
> >> > From: YT Shen <yt.shen at mediatek.com>
> >> >
> >> > There are some hardware settings changed, between MT8173 & MT2701:
> >> > DISP_OVL address offset changed, color format definition changed.
> >> > DISP_RDMA fifo size changed.
> >> > DISP_COLOR offset changed.
> >> >
> >> > Signed-off-by: YT Shen <yt.shen at mediatek.com>
> >> > ---
> >> > +
> >> > +static inline struct mtk_ddp_comp_driver_data *mtk_ovl_get_driver_data(
> >> > +   struct platform_device *pdev)
> >> > +{
> >> > +   const struct of_device_id *of_id =
> >> > +           of_match_device(mtk_disp_ovl_driver_dt_match, &pdev->dev);
> >> > +
> >> > +   return (struct mtk_ddp_comp_driver_data *)of_id->data;
> >> > +}
> >> > +
> >> > +static inline struct mtk_ddp_comp_driver_data *mtk_rdma_get_driver_data(
> >> > +   struct platform_device *pdev)
> >> > +{
> >> > +   const struct of_device_id *of_id =
> >> > +           of_match_device(mtk_disp_rdma_driver_dt_match, &pdev->dev);
> >> > +
> >> > +   return (struct mtk_ddp_comp_driver_data *)of_id->data;
> >> > +}
> >> > +
> >> > +static inline struct mtk_ddp_comp_driver_data *mtk_color_get_driver_data(
> >> > +   struct device_node *node)
> >> > +{
> >> > +   const struct of_device_id *of_id =
> >> > +           of_match_node(mtk_disp_color_driver_dt_match, node);
> >> > +
> >> > +   return (struct mtk_ddp_comp_driver_data *)of_id->data;
> >> > +}
> >> > +
> >>
> >> These three functions looks the same with different parameter:
> >> mtk_disp_ovl_driver_dt_match, mtk_disp_rdma_driver_dt_match, and
> >> mtk_disp_color_driver_dt_match. So merge them to prevent duplicated
> >> code.
> > OK, I'll do this in the next version.
> 
> Also preserve the const-ness of the data - don't cast it away on the
> return line.
> Note that the function return type (and some of the users of said
> functions) should be updated as well.
OK, I will check this part.

> 
> -Emil




From appana.durga.rao at xilinx.com  Mon May 30 03:38:47 2016
From: appana.durga.rao at xilinx.com (Appana Durga Kedareswara Rao)
Date: Mon, 30 May 2016 10:38:47 +0000
Subject: [PATCH v9 2/2] dmaengine: Add Xilinx zynqmp dma engine driver
 support
In-Reply-To: <CAKfKVtE-2rYVmCK1OOzitayH7AzUQHnspoEv6RBLCxUJVnVksg@mail.gmail.com>
References: <1463123033-5443-1-git-send-email-appanad@xilinx.com>
 <1463123033-5443-2-git-send-email-appanad@xilinx.com>
 <CAKfKVtE-2rYVmCK1OOzitayH7AzUQHnspoEv6RBLCxUJVnVksg@mail.gmail.com>
Message-ID: <C246CAC1457055469EF09E3A7AC4E11A4A5B27B7@XAP-PVEXMBX01.xlnx.xilinx.com>

Hi Shubhrajyoti,

> > + */
> > +static void zynqmp_dma_update_desc_to_ctrlr(struct zynqmp_dma_chan
> *chan,
> > +                                     struct zynqmp_dma_desc_sw *desc)
> > +{
> > +       dma_addr_t addr;
> > +
> > +       addr = desc->src_p;
> > +       writel(addr, chan->regs + ZYNQMP_DMA_SRC_START_LSB);
> > +       writel(upper_32_bits(addr), chan->regs +
> > + ZYNQMP_DMA_SRC_START_MSB);
> Can we combine the two writes to a 64bit write.
> It may be helpful on 64-bit systems.

Ok will fix this in the next version of the patch...

Thanks,
Kedar.


From thierry.reding at gmail.com  Mon May 30 03:41:29 2016
From: thierry.reding at gmail.com (Thierry Reding)
Date: Mon, 30 May 2016 12:41:29 +0200
Subject: [RFC v2 1/5] drm/mediatek: rename macros, add chip suffix
In-Reply-To: <1463756736-46573-2-git-send-email-yt.shen@mediatek.com>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
 <1463756736-46573-2-git-send-email-yt.shen@mediatek.com>
Message-ID: <20160530104129.GA8388@ulmo.ba.sec>

On Fri, May 20, 2016 at 11:05:32PM +0800, yt.shen at mediatek.com wrote:
> From: YT Shen <yt.shen at mediatek.com>
> 
> Add MT8173 suffix for hardware related macros.
> 
> Signed-off-by: YT Shen <yt.shen at mediatek.com>
> ---
>  drivers/gpu/drm/mediatek/mtk_drm_ddp.c |   62 ++++++++++++++++----------------
>  1 file changed, 31 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
> index 17ba935..d6aafd4 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
> @@ -36,21 +36,21 @@
>  #define DISP_REG_MUTEX_MOD(n)	(0x2c + 0x20 * (n))
>  #define DISP_REG_MUTEX_SOF(n)	(0x30 + 0x20 * (n))
>  
> -#define MUTEX_MOD_DISP_OVL0		BIT(11)
> -#define MUTEX_MOD_DISP_OVL1		BIT(12)
> -#define MUTEX_MOD_DISP_RDMA0		BIT(13)
> -#define MUTEX_MOD_DISP_RDMA1		BIT(14)
> -#define MUTEX_MOD_DISP_RDMA2		BIT(15)
> -#define MUTEX_MOD_DISP_WDMA0		BIT(16)
> -#define MUTEX_MOD_DISP_WDMA1		BIT(17)
> -#define MUTEX_MOD_DISP_COLOR0		BIT(18)
> -#define MUTEX_MOD_DISP_COLOR1		BIT(19)
> -#define MUTEX_MOD_DISP_AAL		BIT(20)
> -#define MUTEX_MOD_DISP_GAMMA		BIT(21)
> -#define MUTEX_MOD_DISP_UFOE		BIT(22)
> -#define MUTEX_MOD_DISP_PWM0		BIT(23)
> -#define MUTEX_MOD_DISP_PWM1		BIT(24)
> -#define MUTEX_MOD_DISP_OD		BIT(25)
> +#define MUTEX_MOD_DISP_OVL0_MT8173		BIT(11)
> +#define MUTEX_MOD_DISP_OVL1_MT8173		BIT(12)
> +#define MUTEX_MOD_DISP_RDMA0_MT8173		BIT(13)
> +#define MUTEX_MOD_DISP_RDMA1_MT8173		BIT(14)
> +#define MUTEX_MOD_DISP_RDMA2_MT8173		BIT(15)
> +#define MUTEX_MOD_DISP_WDMA0_MT8173		BIT(16)
> +#define MUTEX_MOD_DISP_WDMA1_MT8173		BIT(17)
> +#define MUTEX_MOD_DISP_COLOR0_MT8173		BIT(18)
> +#define MUTEX_MOD_DISP_COLOR1_MT8173		BIT(19)
> +#define MUTEX_MOD_DISP_AAL_MT8173		BIT(20)
> +#define MUTEX_MOD_DISP_GAMMA_MT8173		BIT(21)
> +#define MUTEX_MOD_DISP_UFOE_MT8173		BIT(22)
> +#define MUTEX_MOD_DISP_PWM0_MT8173		BIT(23)
> +#define MUTEX_MOD_DISP_PWM1_MT8173		BIT(24)
> +#define MUTEX_MOD_DISP_OD_MT8173		BIT(25)

Just a random fly-by comment: this looks like a hardware spinlock, have
you ever considered implementing this as a hwspinlock driver? See the
drivers/hwspinlock subdirectory for existing examples.

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

From thierry.reding at gmail.com  Mon May 30 03:45:53 2016
From: thierry.reding at gmail.com (Thierry Reding)
Date: Mon, 30 May 2016 12:45:53 +0200
Subject: [RFC v2 3/5] drm/mediatek: add *driver_data for different
 hardware settings
In-Reply-To: <1463996582.30093.5.camel@mtksdaap41>
References: <1463756736-46573-1-git-send-email-yt.shen@mediatek.com>
 <1463756736-46573-4-git-send-email-yt.shen@mediatek.com>
 <1463996582.30093.5.camel@mtksdaap41>
Message-ID: <20160530104553.GB8388@ulmo.ba.sec>

On Mon, May 23, 2016 at 05:43:02PM +0800, CK Hu wrote:
> Hi, YT:
> 
> One comment below.
> 
> On Fri, 2016-05-20 at 23:05 +0800, yt.shen at mediatek.com wrote:
> > From: YT Shen <yt.shen at mediatek.com>
> > 
> > There are some hardware settings changed, between MT8173 & MT2701:
> > DISP_OVL address offset changed, color format definition changed.
> > DISP_RDMA fifo size changed.
> > DISP_COLOR offset changed.
> > 
> > Signed-off-by: YT Shen <yt.shen at mediatek.com>
> > ---
> > +
> > +static inline struct mtk_ddp_comp_driver_data *mtk_ovl_get_driver_data(
> > +	struct platform_device *pdev)
> > +{
> > +	const struct of_device_id *of_id =
> > +		of_match_device(mtk_disp_ovl_driver_dt_match, &pdev->dev);
> > +
> > +	return (struct mtk_ddp_comp_driver_data *)of_id->data;
> > +}
> > +
> > +static inline struct mtk_ddp_comp_driver_data *mtk_rdma_get_driver_data(
> > +	struct platform_device *pdev)
> > +{
> > +	const struct of_device_id *of_id =
> > +		of_match_device(mtk_disp_rdma_driver_dt_match, &pdev->dev);
> > +
> > +	return (struct mtk_ddp_comp_driver_data *)of_id->data;
> > +}
> > +
> > +static inline struct mtk_ddp_comp_driver_data *mtk_color_get_driver_data(
> > +	struct device_node *node)
> > +{
> > +	const struct of_device_id *of_id =
> > +		of_match_node(mtk_disp_color_driver_dt_match, node);
> > +
> > +	return (struct mtk_ddp_comp_driver_data *)of_id->data;
> > +}
> > + 
> 
> These three functions looks the same with different parameter:
> mtk_disp_ovl_driver_dt_match, mtk_disp_rdma_driver_dt_match, and
> mtk_disp_color_driver_dt_match. So merge them to prevent duplicated
> code.

I think what you really want is of_device_get_match_data().

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

From harninder.rai at nxp.com  Mon May 30 04:07:41 2016
From: harninder.rai at nxp.com (Harninder Rai)
Date: Mon, 30 May 2016 11:07:41 +0000
Subject: Help needed with kexec on arm64
In-Reply-To: <20160527135820.GM19428@n2100.arm.linux.org.uk>
References: <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org>
 <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160511005334.GA8417@linaro.org>
 <DB5PR04MB1688C3F122091109E6BD9B68E6740@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160519110307.GA4941@linaro.org>
 <DB5PR04MB16887FF10CEA6AA9BF990F0DE6420@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160527135820.GM19428@n2100.arm.linux.org.uk>
Message-ID: <DB5PR04MB1688119765FF39B668E71E9EE6450@DB5PR04MB1688.eurprd04.prod.outlook.com>

> 
> You should be able to get more information by using kexec -d to enable debug
> output... if the architecture is usefully printing stuff like memory layouts
> etc.
Unfortunately, kexec -d didn't give any additional information in this case :(
Any more pointers?

Regards
Harry++


From harninder.rai at nxp.com  Mon May 30 04:10:58 2016
From: harninder.rai at nxp.com (Harninder Rai)
Date: Mon, 30 May 2016 11:10:58 +0000
Subject: Help needed with kexec on arm64
In-Reply-To: <1464376785.12343.3.camel@infradead.org>
References: <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org>
 <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160511005334.GA8417@linaro.org>
 <DB5PR04MB1688C3F122091109E6BD9B68E6740@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160519110307.GA4941@linaro.org>
 <DB5PR04MB16887FF10CEA6AA9BF990F0DE6420@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160527135820.GM19428@n2100.arm.linux.org.uk>
 <1464376785.12343.3.camel@infradead.org>
Message-ID: <DB5PR04MB1688E3A3C72D9173B5DC0DCDE6450@DB5PR04MB1688.eurprd04.prod.outlook.com>

> Also, use the latest from here:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/geoff/kexec-tools.git

I am using kexec -v
kexec version: 16.03.14.10.05-gef652df-dirty
kexec-tools 2.0.12-rc1

Do you think still later version will help in this case?

Regards
Harry++

From broonie at kernel.org  Mon May 30 04:23:50 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 30 May 2016 12:23:50 +0100
Subject: [linux-sunxi] [PATCH 1/5] spi: sunxi: fix transfer timeout
In-Reply-To: <CAGRGNgW=UnmwwiREV+nVcws6sk18-4fKz3qf-WKf4LY9-VqBKg@mail.gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
 <cb90b922caa6ac07c1425d726ea19709ee5284f4.1464130597.git.hramrach@gmail.com>
 <CAGRGNgWDrVHG26umTSHHAxFC3KXjwmpDejBAfKqvuik0_2-Jcw@mail.gmail.com>
 <CAOMqctS0AD6rHGt3wjxxyidee=_5xqby95t5TGuozAA12DdPjQ@mail.gmail.com>
 <CAGRGNgW=UnmwwiREV+nVcws6sk18-4fKz3qf-WKf4LY9-VqBKg@mail.gmail.com>
Message-ID: <20160530112350.GI29837@sirena.org.uk>

On Fri, May 27, 2016 at 03:10:11PM +1000, Julian Calaby wrote:
> On Fri, May 27, 2016 at 3:05 PM, Michal Suchanek <hramrach at gmail.com> wrote:

> >> Also, should the changes for the drivers be in two separate patches also?

> > That's basically the same driver with different constants so I guess not.

> Fair enough, I withdraw my comment then.

If it's the same driver with different constants it should really
actually be the same driver - I did ask this when the drivers were
originally merged...
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/fafb72c7/attachment.sig>

From broonie at kernel.org  Mon May 30 04:26:10 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 30 May 2016 12:26:10 +0100
Subject: [PATCH 5/5] RFC spi: sun4i: add DMA support
In-Reply-To: <ba0d6eb37cc4b0d2c46acbf9fcd7d644b3545ce8.1464130597.git.hramrach@gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
 <ba0d6eb37cc4b0d2c46acbf9fcd7d644b3545ce8.1464130597.git.hramrach@gmail.com>
Message-ID: <20160530112610.GJ29837@sirena.org.uk>

On Thu, May 26, 2016 at 07:25:25PM -0000, Michal Suchanek wrote:

>  - fallback to previous behaviour when DMA initialization fails
> 
>    + this has the problem that when the driver happens to load before the dma
>      driver it will not use dma - can be addressed with a module parameter

No, you should pay attention to the error you are getting and let probe
deferral happen if that's the error you get.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/076d2e84/attachment.sig>

From ard.biesheuvel at linaro.org  Mon May 30 04:30:35 2016
From: ard.biesheuvel at linaro.org (Ard Biesheuvel)
Date: Mon, 30 May 2016 13:30:35 +0200
Subject: building and using modules on arm64 hikey board
In-Reply-To: <87a3195c-febb-a6c8-a679-272b9f7b59cc@broadcom.com>
References: <87a3195c-febb-a6c8-a679-272b9f7b59cc@broadcom.com>
Message-ID: <0240F9F0-0146-4DCC-B512-195415B29B34@linaro.org>

This is likely caused by the fact that the Android AArch64 toolchain uses -fpic by default. Could you try adding -fno-pic to the CFLAGS?


> On 30 mei 2016, at 12:21, Arend Van Spriel <arend.vanspriel at broadcom.com> wrote:
> 
> I got myself an arm64 HiKey board from LeMaker and build an Android AOSP
> image for it (see [1]). For development I would like to use
> CONFIG_MODULES. However, when I try to insmod the build module I get:
> 
> [  287.903653] module cfg80211: overflow in relocation type 261 val
> ffffffbffc006530
> 
> Looking AArch64 ELF documentation [2], section 4.6.5, it has:
> code|name            |operation |overflow check   |
> 261 |R_AARCH64_PREL32|S + A - P |-2^31 <= X < 2^32|
> 
> So basically the highest 32 bits should all be one and so ffffffbf is
> invalid. From what I could find searching internet it could be an issue
> with linker options so I build kernel and modules with V=1. Here the
> linker invocation for them:
> 
> + aarch64-linux-android-ld -EL -p --no-undefined -X --build-id -o vmlinux \
> -T ./arch/arm64/kernel/vmlinux.lds arch/arm64/kernel/head.o
> init/built-in.o \
> --start-group usr/built-in.o arch/arm64/kernel/built-in.o
> arch/arm64/mm/built-in.o \
> arch/arm64/net/built-in.o arch/arm64/kvm/built-in.o
> arch/arm64/crypto/built-in.o \
> ./drivers/firmware/efi/libstub/lib.a kernel/built-in.o certs/built-in.o
> mm/built-in.o \
> fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o
> block/built-in.o \
> arch/arm64/lib/lib.a lib/lib.a arch/arm64/lib/built-in.o lib/built-in.o
> drivers/built-in.o \
> sound/built-in.o firmware/built-in.o net/built-in.o virt/built-in.o
> --end-group .tmp_kallsyms2.o
> 
>  aarch64-linux-android-ld -EL -r  -T ./scripts/module-common.lds
> --build-id \
>  -o net/wireless/cfg80211.ko net/wireless/cfg80211.o
> net/wireless/cfg80211.mod.o
> 
> Attached are vmlinux.lds and module-common.lds. I also tried taking
> upstream arch/arm64/kernel/module.lds in hikey-linaro tree. If someone
> can give a hint or educated guess at what to try it would be appreciated.
> 
> Regards,
> Arend
> 
> [1] https://source.android.com/source/devices.html#building-kernel
> [2]
> http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
> <module-common.lds>
> <vmlinux.lds>


From hdegoede at redhat.com  Mon May 30 04:32:31 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Mon, 30 May 2016 13:32:31 +0200
Subject: [PATCH] reset: Put back *_optional variants
In-Reply-To: <1464603520.3808.34.camel@pengutronix.de>
References: <ca359e013c30f27c825a9580164b01da5ca6476d.1464224883.git.johnyoun@synopsys.com>
 <12e450f0-70ea-29f8-0bf7-8a0697263f2d@redhat.com>
 <57476E48.2060204@synopsys.com>
 <dcf6372f-4910-bd03-f1b5-c7e0086fdead@redhat.com>
 <1464603520.3808.34.camel@pengutronix.de>
Message-ID: <5cf9f346-9b6e-d521-612c-9edd167aa759@redhat.com>

Hi,

On 30-05-16 12:18, Philipp Zabel wrote:
> Hi,
>
> Am Freitag, den 27.05.2016, 09:06 +0200 schrieb Hans de Goede:
> [...]
>>>> So IMHO the following change would be a better way to fix this:
>>>>
>>>> --- a/include/linux/reset.h
>>>> +++ b/include/linux/reset.h
>>>> @@ -65,14 +65,14 @@ static inline struct reset_control *__of_reset_control_get(
>>>>                                          struct device_node *node,
>>>>                                          const char *id, int index, int shared)
>>>>   {
>>>> -   return ERR_PTR(-EINVAL);
>>>> + return ERR_PTR(-ENOTSUPP);
>>>>   }
>>>>
>>>>   static inline struct reset_control *__devm_reset_control_get(
>>>>                                          struct device *dev,
>>>>                                          const char *id, int index, int shared)
>>>>   {
>>>> -   return ERR_PTR(-EINVAL);
>>>> + return ERR_PTR(-ENOTSUPP);
>>>>   }
>>>>
>>>>   #endif /* CONFIG_RESET_CONTROLLER */
>>>
>>>
>>> I'm good with this. However, per Philipp on a previous thread, the
>>> intended behavior is to return -EINVAL for the non-optional functions.
>>>
>>> http://marc.info/?l=linux-usb&m=146156945528848&w=2
>
> Adding Dinh to Cc: because he wanted this changed from -EINVAL.
> My point then was that WARN_ON + -EINVAL is indented in this case.
>
> Given that the warning backtrace already helps to identify the issue
> (CONFIG_RESET_CONTROLLER disabled), and that changing the return value
> to -ENOTSUPP improves consistency with the rest of the API and reduces
> the amount of inline wrappers, I concur.
>
>> As Philipp rightfully points out, calling the non-optional functions
>> without CONFIG_RESET_CONTROLLER is a no-no, so IMHO we should not have to
>> care too much about the error code in that case, as long as we return
>> an error.
>>
>> Also note that even before my patch things were already inconsistent
>> with the of_...get... functions already always returning
>> -ENOTSUPP when CONFIG_RESET_CONTROLLER was not set, to me it seems
>> best and also KISS to just return -ENOTSUPP from all get functions
>> when CONFIG_RESET_CONTROLLER is not set.
>>
>> Anyways this is Philipp's call, this is all just my 2 cents.
>
> Let the stubs return -ENOTSUPP consistently. A quick grep doesn't show
> any driver handling -EINVAL explicitly either.

Great.

John Youn, can you submit a patch changing the return of the stubs
from -EINVAL to -ENOTSUPP please ?

Thanks & Regards,

Hans


From hdegoede at redhat.com  Mon May 30 04:34:42 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Mon, 30 May 2016 13:34:42 +0200
Subject: [PATCH 2/3] mmc: sunxi: Fix DDR MMC timings for A80
In-Reply-To: <1464505484-3661-3-git-send-email-wens@csie.org>
References: <1464505484-3661-1-git-send-email-wens@csie.org>
 <1464505484-3661-3-git-send-email-wens@csie.org>
Message-ID: <99d78ff3-db4d-45cc-024a-d94583b56f35@redhat.com>

Hi,

On 29-05-16 09:04, Chen-Yu Tsai wrote:
> The MMC clock timings were incorrectly calculated, when the conversion
> from delay value to delay phase was done.
>
> The 50M DDR and 50M DDR 8bit timings are off, and make eMMC DDR
> unusable. Unfortunately it seems different controllers on the same SoC
> have different timings. The new settings are taken from mmc2, which is
> commonly used with eMMC.

Hmm, I'm not really all that familiar with mmc, but can't an external
sdcard connected to mmc0 use DDR too ? Assuming the answer is yes, then
we really need to update the driver to use the right per controller
timings.

> The settings for the slower timing modes seem to work despite being
> wrong, so leave them be.

If you're sure the timings are wrong, please fix them. Sometimes wrong
timings do seem to work, but lead to unreliable communication, or turn
out to work on some boards and not on others due to routing differences.

Thanks & Regards,

Hans


>
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
> ---
>  drivers/mmc/host/sunxi-mmc.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
> index 7fc8b7aa83f0..5873dc344ab2 100644
> --- a/drivers/mmc/host/sunxi-mmc.c
> +++ b/drivers/mmc/host/sunxi-mmc.c
> @@ -970,8 +970,8 @@ static const struct sunxi_mmc_clk_delay sun9i_mmc_clk_delays[] = {
>  	[SDXC_CLK_400K]		= { .output = 180, .sample = 180 },
>  	[SDXC_CLK_25M]		= { .output = 180, .sample =  75 },
>  	[SDXC_CLK_50M]		= { .output = 150, .sample = 120 },
> -	[SDXC_CLK_50M_DDR]	= { .output =  90, .sample = 120 },
> -	[SDXC_CLK_50M_DDR_8BIT]	= { .output =  90, .sample = 120 },
> +	[SDXC_CLK_50M_DDR]	= { .output =  54, .sample =  36 },
> +	[SDXC_CLK_50M_DDR_8BIT]	= { .output =  72, .sample =  72 },
>  };
>
>  static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
>


From holgerschurig at gmail.com  Mon May 30 04:35:47 2016
From: holgerschurig at gmail.com (Holger Schurig)
Date: Mon, 30 May 2016 13:35:47 +0200
Subject: Sharing code between Linux and bootloader (U-boot) ?
In-Reply-To: <573F1F07.6040202@laposte.net>
References: <573F1F07.6040202@laposte.net>
Message-ID: <87eg8j93sc.fsf@gmail.com>

Sebastian Frias <sf84 at laposte.net> writes:

Barebox shares a good amount of code. For example, when you look at SPI
at AT24/AT25 you'll see that many things are almost identical.


From k.kozlowski at samsung.com  Mon May 30 04:54:05 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 30 May 2016 13:54:05 +0200
Subject: [RFC v2] Change dma_attrs from bitfield to unsigned long
Message-ID: <1464609246-6948-1-git-send-email-k.kozlowski@samsung.com>

Hi,


This is second attempt to bring some safeness to dma_attrs.
In v1 [0] I added const to data pointed by attrs. However Christoph
Hellwig suggested getting rid of struct dma_attrs in favor of
some simpler data type.


Benefits of unsigned long for dma_attrs:
1. This is just simpler.  Both in terms of reading the code and setting
   attributes.  Instead of initializing local attributes on the stack and
   passing pointer to it to dma_set_attr(), just set the bits.

2. It brings safeness and checking for const correctness because the
   attributes are passed by value.


The problem is that the patch touches the dma-mapping API so all
the users have to be converted (ARM and ARM64 as of now).

Any ideas to split it per smaller patches?

The work is not finished yet, I would rather get some feedback before
progressing further.


Best regards,
Krzysztof


Krzysztof Kozlowski (1):
  dma-mapping: Use unsigned long for dma_attrs

 Documentation/DMA-API.txt                 |   2 +-
 Documentation/DMA-attributes.txt          |   2 +-
 arch/arm/include/asm/dma-mapping.h        |  13 ++--
 arch/arm/include/asm/xen/page-coherent.h  |  16 ++---
 arch/arm/mm/dma-mapping.c                 |  82 +++++++++++------------
 arch/arm/xen/mm.c                         |   4 +-
 arch/arm64/mm/dma-mapping.c               |  57 ++++++++--------
 drivers/gpu/drm/exynos/exynos_drm_fbdev.c |   2 +-
 drivers/gpu/drm/exynos/exynos_drm_g2d.c   |   1 -
 drivers/gpu/drm/exynos/exynos_drm_gem.c   |  20 +++---
 drivers/gpu/drm/exynos/exynos_drm_gem.h   |   2 +-
 drivers/iommu/dma-iommu.c                 |   6 +-
 drivers/xen/swiotlb-xen.c                 |  14 ++--
 include/linux/dma-attrs.h                 |  71 --------------------
 include/linux/dma-iommu.h                 |   6 +-
 include/linux/dma-mapping.h               | 105 +++++++++++++++++-------------
 include/linux/swiotlb.h                   |  10 +--
 include/xen/swiotlb-xen.h                 |  12 ++--
 lib/dma-noop.c                            |   9 +--
 lib/swiotlb.c                             |  13 ++--
 20 files changed, 195 insertions(+), 252 deletions(-)
 delete mode 100644 include/linux/dma-attrs.h

-- 
1.9.1



From k.kozlowski at samsung.com  Mon May 30 04:54:06 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Mon, 30 May 2016 13:54:06 +0200
Subject: [RFC v2] dma-mapping: Use unsigned long for dma_attrs
In-Reply-To: <1464609246-6948-1-git-send-email-k.kozlowski@samsung.com>
References: <1464609246-6948-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1464609246-6948-2-git-send-email-k.kozlowski@samsung.com>

The dma-mapping core and the implementations do not change the
DMA attributes passed by pointer.  Thus the pointer can point to const
data.  However the attributes do not have to be a bitfield. Instead
unsigned long will do fine:

1. This is just simpler.  Both in terms of reading the code and setting
   attributes.  Instead of initializing local attributes on the stack and
   passing pointer to it to dma_set_attr(), just set the bits.

2. It brings safeness and checking for const correctness because the
   attributes are passed by value.

Please have in mind that this is RFC, not finished yet.  Only ARM and
ARM64 are fixed (and not everywhere).
However other API users also have to be converted which is quite
intrusive.  I would rather avoid it until the overall approach is
accepted.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 Documentation/DMA-API.txt                 |   2 +-
 Documentation/DMA-attributes.txt          |   2 +-
 arch/arm/include/asm/dma-mapping.h        |  13 ++--
 arch/arm/include/asm/xen/page-coherent.h  |  16 ++---
 arch/arm/mm/dma-mapping.c                 |  82 +++++++++++------------
 arch/arm/xen/mm.c                         |   4 +-
 arch/arm64/mm/dma-mapping.c               |  57 ++++++++--------
 drivers/gpu/drm/exynos/exynos_drm_fbdev.c |   2 +-
 drivers/gpu/drm/exynos/exynos_drm_g2d.c   |   1 -
 drivers/gpu/drm/exynos/exynos_drm_gem.c   |  20 +++---
 drivers/gpu/drm/exynos/exynos_drm_gem.h   |   2 +-
 drivers/iommu/dma-iommu.c                 |   6 +-
 drivers/xen/swiotlb-xen.c                 |  14 ++--
 include/linux/dma-attrs.h                 |  71 --------------------
 include/linux/dma-iommu.h                 |   6 +-
 include/linux/dma-mapping.h               | 105 +++++++++++++++++-------------
 include/linux/swiotlb.h                   |  10 +--
 include/xen/swiotlb-xen.h                 |  12 ++--
 lib/dma-noop.c                            |   9 +--
 lib/swiotlb.c                             |  13 ++--
 20 files changed, 195 insertions(+), 252 deletions(-)
 delete mode 100644 include/linux/dma-attrs.h

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 45ef3f279c3b..0b55cb7c5aaa 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -391,7 +391,7 @@ without the _attrs suffixes, except that they pass an optional
 struct dma_attrs*.
 
 struct dma_attrs encapsulates a set of "DMA attributes". For the
-definition of struct dma_attrs see linux/dma-attrs.h.
+definition of struct dma_attrs see linux/dma-mapping.h.
 
 The interpretation of DMA attributes is architecture-specific, and
 each attribute should be documented in Documentation/DMA-attributes.txt.
diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
index e8cf9cf873b3..2d455a5cf671 100644
--- a/Documentation/DMA-attributes.txt
+++ b/Documentation/DMA-attributes.txt
@@ -2,7 +2,7 @@
 			==============
 
 This document describes the semantics of the DMA attributes that are
-defined in linux/dma-attrs.h.
+defined in linux/dma-mapping.h.
 
 DMA_ATTR_WRITE_BARRIER
 ----------------------
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index a83570f10124..d009f7911ffc 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -5,7 +5,6 @@
 
 #include <linux/mm_types.h>
 #include <linux/scatterlist.h>
-#include <linux/dma-attrs.h>
 #include <linux/dma-debug.h>
 
 #include <asm/memory.h>
@@ -174,7 +173,7 @@ static inline void dma_mark_clean(void *addr, size_t size) { }
  * to be the device-viewed address.
  */
 extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-			   gfp_t gfp, struct dma_attrs *attrs);
+			   gfp_t gfp, unsigned long attrs);
 
 /**
  * arm_dma_free - free memory allocated by arm_dma_alloc
@@ -191,7 +190,7 @@ extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
  * during and after this call executing are illegal.
  */
 extern void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-			 dma_addr_t handle, struct dma_attrs *attrs);
+			 dma_addr_t handle, unsigned long attrs);
 
 /**
  * arm_dma_mmap - map a coherent DMA allocation into user space
@@ -208,7 +207,7 @@ extern void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
  */
 extern int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 			void *cpu_addr, dma_addr_t dma_addr, size_t size,
-			struct dma_attrs *attrs);
+			unsigned long attrs);
 
 /*
  * This can be called during early boot to increase the size of the atomic
@@ -262,16 +261,16 @@ extern void dmabounce_unregister_dev(struct device *);
  * The scatter list versions of the above methods.
  */
 extern int arm_dma_map_sg(struct device *, struct scatterlist *, int,
-		enum dma_data_direction, struct dma_attrs *attrs);
+		enum dma_data_direction, unsigned long attrs);
 extern void arm_dma_unmap_sg(struct device *, struct scatterlist *, int,
-		enum dma_data_direction, struct dma_attrs *attrs);
+		enum dma_data_direction, unsigned long attrs);
 extern void arm_dma_sync_sg_for_cpu(struct device *, struct scatterlist *, int,
 		enum dma_data_direction);
 extern void arm_dma_sync_sg_for_device(struct device *, struct scatterlist *, int,
 		enum dma_data_direction);
 extern int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
 		void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		struct dma_attrs *attrs);
+		unsigned long attrs);
 
 #endif /* __KERNEL__ */
 #endif
diff --git a/arch/arm/include/asm/xen/page-coherent.h b/arch/arm/include/asm/xen/page-coherent.h
index 9408a994cc91..95ce6ac3a971 100644
--- a/arch/arm/include/asm/xen/page-coherent.h
+++ b/arch/arm/include/asm/xen/page-coherent.h
@@ -2,15 +2,14 @@
 #define _ASM_ARM_XEN_PAGE_COHERENT_H
 
 #include <asm/page.h>
-#include <linux/dma-attrs.h>
 #include <linux/dma-mapping.h>
 
 void __xen_dma_map_page(struct device *hwdev, struct page *page,
 	     dma_addr_t dev_addr, unsigned long offset, size_t size,
-	     enum dma_data_direction dir, struct dma_attrs *attrs);
+	     enum dma_data_direction dir, unsigned long attrs);
 void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir,
-		struct dma_attrs *attrs);
+		unsigned long attrs);
 void __xen_dma_sync_single_for_cpu(struct device *hwdev,
 		dma_addr_t handle, size_t size, enum dma_data_direction dir);
 
@@ -18,22 +17,20 @@ void __xen_dma_sync_single_for_device(struct device *hwdev,
 		dma_addr_t handle, size_t size, enum dma_data_direction dir);
 
 static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
-		dma_addr_t *dma_handle, gfp_t flags,
-		struct dma_attrs *attrs)
+		dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
 {
 	return __generic_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
 }
 
 static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
-		void *cpu_addr, dma_addr_t dma_handle,
-		struct dma_attrs *attrs)
+		void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
 {
 	__generic_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
 }
 
 static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
 	     dma_addr_t dev_addr, unsigned long offset, size_t size,
-	     enum dma_data_direction dir, struct dma_attrs *attrs)
+	     enum dma_data_direction dir, unsigned long attrs)
 {
 	unsigned long page_pfn = page_to_xen_pfn(page);
 	unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
@@ -58,8 +55,7 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
 }
 
 static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
-		size_t size, enum dma_data_direction dir,
-		struct dma_attrs *attrs)
+		size_t size, enum dma_data_direction dir, unsigned long attrs)
 {
 	unsigned long pfn = PFN_DOWN(handle);
 	/*
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index ff7ed5697d3e..fe31fbfd926d 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -124,7 +124,7 @@ static void __dma_page_dev_to_cpu(struct page *, unsigned long,
  */
 static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
 	     unsigned long offset, size_t size, enum dma_data_direction dir,
-	     struct dma_attrs *attrs)
+	     unsigned long attrs)
 {
 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__dma_page_cpu_to_dev(page, offset, size, dir);
@@ -133,7 +133,7 @@ static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
 
 static dma_addr_t arm_coherent_dma_map_page(struct device *dev, struct page *page,
 	     unsigned long offset, size_t size, enum dma_data_direction dir,
-	     struct dma_attrs *attrs)
+	     unsigned long attrs)
 {
 	return pfn_to_dma(dev, page_to_pfn(page)) + offset;
 }
@@ -153,8 +153,7 @@ static dma_addr_t arm_coherent_dma_map_page(struct device *dev, struct page *pag
  * whatever the device wrote there.
  */
 static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
-		size_t size, enum dma_data_direction dir,
-		struct dma_attrs *attrs)
+		size_t size, enum dma_data_direction dir, unsigned long attrs)
 {
 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
@@ -194,12 +193,12 @@ struct dma_map_ops arm_dma_ops = {
 EXPORT_SYMBOL(arm_dma_ops);
 
 static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
-	dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs);
+	dma_addr_t *handle, gfp_t gfp, unsigned long attrs);
 static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
-				  dma_addr_t handle, struct dma_attrs *attrs);
+				  dma_addr_t handle, unsigned long attrs);
 static int arm_coherent_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		 struct dma_attrs *attrs);
+		 unsigned long attrs);
 
 struct dma_map_ops arm_coherent_dma_ops = {
 	.alloc			= arm_coherent_dma_alloc,
@@ -621,7 +620,7 @@ static void __free_from_contiguous(struct device *dev, struct page *page,
 	dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
 }
 
-static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
+static inline pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot)
 {
 	prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
 			    pgprot_writecombine(prot) :
@@ -732,7 +731,7 @@ static struct arm_dma_allocator remap_allocator = {
 
 static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 			 gfp_t gfp, pgprot_t prot, bool is_coherent,
-			 struct dma_attrs *attrs, const void *caller)
+			 unsigned long attrs, const void *caller)
 {
 	u64 mask = get_coherent_dma_mask(dev);
 	struct page *page = NULL;
@@ -814,7 +813,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
  * virtual and bus address for that space.
  */
 void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-		    gfp_t gfp, struct dma_attrs *attrs)
+		    gfp_t gfp, unsigned long attrs)
 {
 	pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
 
@@ -823,7 +822,7 @@ void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 }
 
 static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
-	dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+	dma_addr_t *handle, gfp_t gfp, unsigned long attrs)
 {
 	return __dma_alloc(dev, size, handle, gfp, PAGE_KERNEL, true,
 			   attrs, __builtin_return_address(0));
@@ -831,7 +830,7 @@ static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
 
 static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		 struct dma_attrs *attrs)
+		 unsigned long attrs)
 {
 	int ret = -ENXIO;
 #ifdef CONFIG_MMU
@@ -859,14 +858,14 @@ static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
  */
 static int arm_coherent_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		 struct dma_attrs *attrs)
+		 unsigned long attrs)
 {
 	return __arm_dma_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
 }
 
 int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		 struct dma_attrs *attrs)
+		 unsigned long attrs)
 {
 #ifdef CONFIG_MMU
 	vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
@@ -878,7 +877,7 @@ int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
  * Free a buffer as defined by the above mapping.
  */
 static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-			   dma_addr_t handle, struct dma_attrs *attrs,
+			   dma_addr_t handle, unsigned long attrs,
 			   bool is_coherent)
 {
 	struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
@@ -900,20 +899,20 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
 }
 
 void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-		  dma_addr_t handle, struct dma_attrs *attrs)
+		  dma_addr_t handle, unsigned long attrs)
 {
 	__arm_dma_free(dev, size, cpu_addr, handle, attrs, false);
 }
 
 static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
-				  dma_addr_t handle, struct dma_attrs *attrs)
+				  dma_addr_t handle, unsigned long attrs)
 {
 	__arm_dma_free(dev, size, cpu_addr, handle, attrs, true);
 }
 
 int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
 		 void *cpu_addr, dma_addr_t handle, size_t size,
-		 struct dma_attrs *attrs)
+		 unsigned long attrs)
 {
 	struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
 	int ret;
@@ -1046,7 +1045,7 @@ static void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
  * here.
  */
 int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-		enum dma_data_direction dir, struct dma_attrs *attrs)
+		enum dma_data_direction dir, unsigned long attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	struct scatterlist *s;
@@ -1080,7 +1079,7 @@ int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
  * rules concerning calls here are the same as for dma_unmap_single().
  */
 void arm_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-		enum dma_data_direction dir, struct dma_attrs *attrs)
+		enum dma_data_direction dir, unsigned long attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	struct scatterlist *s;
@@ -1253,7 +1252,7 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping,
 static const int iommu_order_array[] = { 9, 8, 4, 0 };
 
 static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
-					  gfp_t gfp, struct dma_attrs *attrs)
+					  gfp_t gfp, unsigned long attrs)
 {
 	struct page **pages;
 	int count = size >> PAGE_SHIFT;
@@ -1342,7 +1341,7 @@ error:
 }
 
 static int __iommu_free_buffer(struct device *dev, struct page **pages,
-			       size_t size, struct dma_attrs *attrs)
+			       size_t size, unsigned long attrs)
 {
 	int count = size >> PAGE_SHIFT;
 	int i;
@@ -1439,7 +1438,7 @@ static struct page **__atomic_get_pages(void *addr)
 	return (struct page **)page;
 }
 
-static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
+static struct page **__iommu_get_pages(void *cpu_addr, unsigned long attrs)
 {
 	struct vm_struct *area;
 
@@ -1484,7 +1483,7 @@ static void __iommu_free_atomic(struct device *dev, void *cpu_addr,
 }
 
 static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
-	    dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+	    dma_addr_t *handle, gfp_t gfp, unsigned long attrs)
 {
 	pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
 	struct page **pages;
@@ -1532,7 +1531,7 @@ err_buffer:
 
 static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 		    void *cpu_addr, dma_addr_t dma_addr, size_t size,
-		    struct dma_attrs *attrs)
+		    unsigned long attrs)
 {
 	unsigned long uaddr = vma->vm_start;
 	unsigned long usize = vma->vm_end - vma->vm_start;
@@ -1568,7 +1567,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
  * Must not be called with IRQs disabled.
  */
 void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
-			  dma_addr_t handle, struct dma_attrs *attrs)
+			  dma_addr_t handle, unsigned long attrs)
 {
 	struct page **pages;
 	size = PAGE_ALIGN(size);
@@ -1595,7 +1594,7 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
 
 static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
 				 void *cpu_addr, dma_addr_t dma_addr,
-				 size_t size, struct dma_attrs *attrs)
+				 size_t size, unsigned long attrs)
 {
 	unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
 	struct page **pages = __iommu_get_pages(cpu_addr, attrs);
@@ -1633,7 +1632,7 @@ static int __dma_direction_to_prot(enum dma_data_direction dir)
  */
 static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
 			  size_t size, dma_addr_t *handle,
-			  enum dma_data_direction dir, struct dma_attrs *attrs,
+			  enum dma_data_direction dir, unsigned long attrs,
 			  bool is_coherent)
 {
 	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
@@ -1676,7 +1675,7 @@ fail:
 }
 
 static int __iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-		     enum dma_data_direction dir, struct dma_attrs *attrs,
+		     enum dma_data_direction dir, unsigned long attrs,
 		     bool is_coherent)
 {
 	struct scatterlist *s = sg, *dma = sg, *start = sg;
@@ -1734,7 +1733,7 @@ bad_mapping:
  * obtained via sg_dma_{address,length}.
  */
 int arm_coherent_iommu_map_sg(struct device *dev, struct scatterlist *sg,
-		int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+		int nents, enum dma_data_direction dir, unsigned long attrs)
 {
 	return __iommu_map_sg(dev, sg, nents, dir, attrs, true);
 }
@@ -1752,14 +1751,14 @@ int arm_coherent_iommu_map_sg(struct device *dev, struct scatterlist *sg,
  * sg_dma_{address,length}.
  */
 int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg,
-		int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+		int nents, enum dma_data_direction dir, unsigned long attrs)
 {
 	return __iommu_map_sg(dev, sg, nents, dir, attrs, false);
 }
 
 static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
-		int nents, enum dma_data_direction dir, struct dma_attrs *attrs,
-		bool is_coherent)
+		int nents, enum dma_data_direction dir,
+		unsigned long attrs, bool is_coherent)
 {
 	struct scatterlist *s;
 	int i;
@@ -1786,7 +1785,8 @@ static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
  * rules concerning calls here are the same as for dma_unmap_single().
  */
 void arm_coherent_iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
-		int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+		int nents, enum dma_data_direction dir,
+		unsigned long attrs)
 {
 	__iommu_unmap_sg(dev, sg, nents, dir, attrs, true);
 }
@@ -1802,7 +1802,8 @@ void arm_coherent_iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
  * rules concerning calls here are the same as for dma_unmap_single().
  */
 void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-			enum dma_data_direction dir, struct dma_attrs *attrs)
+			enum dma_data_direction dir,
+			unsigned long attrs)
 {
 	__iommu_unmap_sg(dev, sg, nents, dir, attrs, false);
 }
@@ -1855,7 +1856,7 @@ void arm_iommu_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
  */
 static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *page,
 	     unsigned long offset, size_t size, enum dma_data_direction dir,
-	     struct dma_attrs *attrs)
+	     unsigned long attrs)
 {
 	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
 	dma_addr_t dma_addr;
@@ -1889,7 +1890,7 @@ fail:
  */
 static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
 	     unsigned long offset, size_t size, enum dma_data_direction dir,
-	     struct dma_attrs *attrs)
+	     unsigned long attrs)
 {
 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__dma_page_cpu_to_dev(page, offset, size, dir);
@@ -1907,8 +1908,7 @@ static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
  * Coherent IOMMU aware version of arm_dma_unmap_page()
  */
 static void arm_coherent_iommu_unmap_page(struct device *dev, dma_addr_t handle,
-		size_t size, enum dma_data_direction dir,
-		struct dma_attrs *attrs)
+		size_t size, enum dma_data_direction dir, unsigned long attrs)
 {
 	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
 	dma_addr_t iova = handle & PAGE_MASK;
@@ -1932,8 +1932,7 @@ static void arm_coherent_iommu_unmap_page(struct device *dev, dma_addr_t handle,
  * IOMMU aware version of arm_dma_unmap_page()
  */
 static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
-		size_t size, enum dma_data_direction dir,
-		struct dma_attrs *attrs)
+		size_t size, enum dma_data_direction dir, unsigned long attrs)
 {
 	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
 	dma_addr_t iova = handle & PAGE_MASK;
@@ -1944,6 +1943,7 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
 	if (!iova)
 		return;
 
+	// FIXME: replace get with simple check
 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__dma_page_dev_to_cpu(page, offset, size, dir);
 
diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
index c5f9a9e3d1f3..fc67ed236a10 100644
--- a/arch/arm/xen/mm.c
+++ b/arch/arm/xen/mm.c
@@ -98,7 +98,7 @@ static void __xen_dma_page_cpu_to_dev(struct device *hwdev, dma_addr_t handle,
 
 void __xen_dma_map_page(struct device *hwdev, struct page *page,
 	     dma_addr_t dev_addr, unsigned long offset, size_t size,
-	     enum dma_data_direction dir, struct dma_attrs *attrs)
+	     enum dma_data_direction dir, unsigned long attrs)
 {
 	if (is_device_dma_coherent(hwdev))
 		return;
@@ -110,7 +110,7 @@ void __xen_dma_map_page(struct device *hwdev, struct page *page,
 
 void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir,
-		struct dma_attrs *attrs)
+		unsigned long attrs)
 
 {
 	if (is_device_dma_coherent(hwdev))
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index c566ec83719f..a7686028dfeb 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -29,7 +29,7 @@
 
 #include <asm/cacheflush.h>
 
-static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
+static pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot,
 				 bool coherent)
 {
 	if (!coherent || dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs))
@@ -88,7 +88,7 @@ static int __free_from_pool(void *start, size_t size)
 
 static void *__dma_alloc_coherent(struct device *dev, size_t size,
 				  dma_addr_t *dma_handle, gfp_t flags,
-				  struct dma_attrs *attrs)
+				  unsigned long attrs)
 {
 	if (dev == NULL) {
 		WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
@@ -118,7 +118,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
 
 static void __dma_free_coherent(struct device *dev, size_t size,
 				void *vaddr, dma_addr_t dma_handle,
-				struct dma_attrs *attrs)
+				unsigned long attrs)
 {
 	bool freed;
 	phys_addr_t paddr = dma_to_phys(dev, dma_handle);
@@ -137,7 +137,7 @@ static void __dma_free_coherent(struct device *dev, size_t size,
 
 static void *__dma_alloc(struct device *dev, size_t size,
 			 dma_addr_t *dma_handle, gfp_t flags,
-			 struct dma_attrs *attrs)
+			 unsigned long attrs)
 {
 	struct page *page;
 	void *ptr, *coherent_ptr;
@@ -185,7 +185,7 @@ no_mem:
 
 static void __dma_free(struct device *dev, size_t size,
 		       void *vaddr, dma_addr_t dma_handle,
-		       struct dma_attrs *attrs)
+		       unsigned long attrs)
 {
 	void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
 
@@ -202,7 +202,7 @@ static void __dma_free(struct device *dev, size_t size,
 static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
 				     unsigned long offset, size_t size,
 				     enum dma_data_direction dir,
-				     struct dma_attrs *attrs)
+				     unsigned long attrs)
 {
 	dma_addr_t dev_addr;
 
@@ -216,7 +216,7 @@ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
 
 static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
 				 size_t size, enum dma_data_direction dir,
-				 struct dma_attrs *attrs)
+				 unsigned long attrs)
 {
 	if (!is_device_dma_coherent(dev))
 		__dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
@@ -225,7 +225,7 @@ static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
 
 static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
 				  int nelems, enum dma_data_direction dir,
-				  struct dma_attrs *attrs)
+				  unsigned long attrs)
 {
 	struct scatterlist *sg;
 	int i, ret;
@@ -242,7 +242,7 @@ static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
 static void __swiotlb_unmap_sg_attrs(struct device *dev,
 				     struct scatterlist *sgl, int nelems,
 				     enum dma_data_direction dir,
-				     struct dma_attrs *attrs)
+				     unsigned long attrs)
 {
 	struct scatterlist *sg;
 	int i;
@@ -303,7 +303,7 @@ static void __swiotlb_sync_sg_for_device(struct device *dev,
 static int __swiotlb_mmap(struct device *dev,
 			  struct vm_area_struct *vma,
 			  void *cpu_addr, dma_addr_t dma_addr, size_t size,
-			  struct dma_attrs *attrs)
+			  unsigned long attrs)
 {
 	int ret = -ENXIO;
 	unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >>
@@ -330,7 +330,7 @@ static int __swiotlb_mmap(struct device *dev,
 
 static int __swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt,
 				 void *cpu_addr, dma_addr_t handle, size_t size,
-				 struct dma_attrs *attrs)
+				 unsigned long attrs)
 {
 	int ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
 
@@ -425,21 +425,21 @@ out:
 
 static void *__dummy_alloc(struct device *dev, size_t size,
 			   dma_addr_t *dma_handle, gfp_t flags,
-			   struct dma_attrs *attrs)
+			   unsigned long attrs)
 {
 	return NULL;
 }
 
 static void __dummy_free(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle,
-			 struct dma_attrs *attrs)
+			 unsigned long attrs)
 {
 }
 
 static int __dummy_mmap(struct device *dev,
 			struct vm_area_struct *vma,
 			void *cpu_addr, dma_addr_t dma_addr, size_t size,
-			struct dma_attrs *attrs)
+			unsigned long attrs)
 {
 	return -ENXIO;
 }
@@ -447,20 +447,20 @@ static int __dummy_mmap(struct device *dev,
 static dma_addr_t __dummy_map_page(struct device *dev, struct page *page,
 				   unsigned long offset, size_t size,
 				   enum dma_data_direction dir,
-				   struct dma_attrs *attrs)
+				   unsigned long attrs)
 {
 	return DMA_ERROR_CODE;
 }
 
 static void __dummy_unmap_page(struct device *dev, dma_addr_t dev_addr,
 			       size_t size, enum dma_data_direction dir,
-			       struct dma_attrs *attrs)
+			       unsigned long attrs)
 {
 }
 
 static int __dummy_map_sg(struct device *dev, struct scatterlist *sgl,
 			  int nelems, enum dma_data_direction dir,
-			  struct dma_attrs *attrs)
+			  unsigned long attrs)
 {
 	return 0;
 }
@@ -468,7 +468,7 @@ static int __dummy_map_sg(struct device *dev, struct scatterlist *sgl,
 static void __dummy_unmap_sg(struct device *dev,
 			     struct scatterlist *sgl, int nelems,
 			     enum dma_data_direction dir,
-			     struct dma_attrs *attrs)
+			     unsigned long attrs)
 {
 }
 
@@ -540,7 +540,7 @@ static void flush_page(struct device *dev, const void *virt, phys_addr_t phys)
 
 static void *__iommu_alloc_attrs(struct device *dev, size_t size,
 				 dma_addr_t *handle, gfp_t gfp,
-				 struct dma_attrs *attrs)
+				 unsigned long attrs)
 {
 	bool coherent = is_device_dma_coherent(dev);
 	int ioprot = dma_direction_to_prot(DMA_BIDIRECTIONAL, coherent);
@@ -600,7 +600,8 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
 }
 
 static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
-			       dma_addr_t handle, struct dma_attrs *attrs)
+			       dma_addr_t handle,
+			       unsigned long attrs)
 {
 	size_t iosize = size;
 
@@ -616,7 +617,7 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
 	 * Hence how dodgy the below logic looks...
 	 */
 	if (__in_atomic_pool(cpu_addr, size)) {
-		iommu_dma_unmap_page(dev, handle, iosize, 0, NULL);
+		iommu_dma_unmap_page(dev, handle, iosize, 0, 0);
 		__free_from_pool(cpu_addr, size);
 	} else if (is_vmalloc_addr(cpu_addr)){
 		struct vm_struct *area = find_vm_area(cpu_addr);
@@ -626,14 +627,14 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
 		iommu_dma_free(dev, area->pages, iosize, &handle);
 		dma_common_free_remap(cpu_addr, size, VM_USERMAP);
 	} else {
-		iommu_dma_unmap_page(dev, handle, iosize, 0, NULL);
+		iommu_dma_unmap_page(dev, handle, iosize, 0, 0);
 		__free_pages(virt_to_page(cpu_addr), get_order(size));
 	}
 }
 
 static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 			      void *cpu_addr, dma_addr_t dma_addr, size_t size,
-			      struct dma_attrs *attrs)
+			      unsigned long attrs)
 {
 	struct vm_struct *area;
 	int ret;
@@ -653,7 +654,7 @@ static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 
 static int __iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
 			       void *cpu_addr, dma_addr_t dma_addr,
-			       size_t size, struct dma_attrs *attrs)
+			       size_t size, unsigned long attrs)
 {
 	unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
 	struct vm_struct *area = find_vm_area(cpu_addr);
@@ -694,7 +695,7 @@ static void __iommu_sync_single_for_device(struct device *dev,
 static dma_addr_t __iommu_map_page(struct device *dev, struct page *page,
 				   unsigned long offset, size_t size,
 				   enum dma_data_direction dir,
-				   struct dma_attrs *attrs)
+				   unsigned long attrs)
 {
 	bool coherent = is_device_dma_coherent(dev);
 	int prot = dma_direction_to_prot(dir, coherent);
@@ -709,7 +710,7 @@ static dma_addr_t __iommu_map_page(struct device *dev, struct page *page,
 
 static void __iommu_unmap_page(struct device *dev, dma_addr_t dev_addr,
 			       size_t size, enum dma_data_direction dir,
-			       struct dma_attrs *attrs)
+			       unsigned long attrs)
 {
 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__iommu_sync_single_for_cpu(dev, dev_addr, size, dir);
@@ -747,7 +748,7 @@ static void __iommu_sync_sg_for_device(struct device *dev,
 
 static int __iommu_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
 				int nelems, enum dma_data_direction dir,
-				struct dma_attrs *attrs)
+				unsigned long attrs)
 {
 	bool coherent = is_device_dma_coherent(dev);
 
@@ -761,7 +762,7 @@ static int __iommu_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
 static void __iommu_unmap_sg_attrs(struct device *dev,
 				   struct scatterlist *sgl, int nelems,
 				   enum dma_data_direction dir,
-				   struct dma_attrs *attrs)
+				   unsigned long attrs)
 {
 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__iommu_sync_sg_for_cpu(dev, sgl, nelems, dir);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 67dcd6831291..dd091175fc2d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -52,7 +52,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
 
 	ret = dma_mmap_attrs(to_dma_dev(helper->dev), vma, exynos_gem->cookie,
 			     exynos_gem->dma_addr, exynos_gem->size,
-			     &exynos_gem->dma_attrs);
+			     exynos_gem->dma_attrs);
 	if (ret < 0) {
 		DRM_ERROR("failed to mmap.\n");
 		return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 493552368295..f65e6b7ef93b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/dma-mapping.h>
-#include <linux/dma-attrs.h>
 #include <linux/of.h>
 
 #include <drm/drmP.h>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index cdf9f1af4347..f2ae72ba7d5a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -24,7 +24,7 @@
 static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
 {
 	struct drm_device *dev = exynos_gem->base.dev;
-	enum dma_attr attr;
+	unsigned long attr;
 	unsigned int nr_pages;
 	struct sg_table sgt;
 	int ret = -ENOMEM;
@@ -34,7 +34,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
 		return 0;
 	}
 
-	init_dma_attrs(&exynos_gem->dma_attrs);
+	exynos_gem->dma_attrs = 0;
 
 	/*
 	 * if EXYNOS_BO_CONTIG, fully physically contiguous memory
@@ -42,7 +42,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
 	 * as possible.
 	 */
 	if (!(exynos_gem->flags & EXYNOS_BO_NONCONTIG))
-		dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &exynos_gem->dma_attrs);
+		exynos_gem->dma_attrs |= DMA_ATTR_FORCE_CONTIGUOUS;
 
 	/*
 	 * if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping
@@ -54,8 +54,8 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
 	else
 		attr = DMA_ATTR_NON_CONSISTENT;
 
-	dma_set_attr(attr, &exynos_gem->dma_attrs);
-	dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &exynos_gem->dma_attrs);
+	exynos_gem->dma_attrs |= attr;
+	exynos_gem->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
 
 	nr_pages = exynos_gem->size >> PAGE_SHIFT;
 
@@ -67,7 +67,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
 
 	exynos_gem->cookie = dma_alloc_attrs(to_dma_dev(dev), exynos_gem->size,
 					     &exynos_gem->dma_addr, GFP_KERNEL,
-					     &exynos_gem->dma_attrs);
+					     exynos_gem->dma_attrs);
 	if (!exynos_gem->cookie) {
 		DRM_ERROR("failed to allocate buffer.\n");
 		goto err_free;
@@ -75,7 +75,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
 
 	ret = dma_get_sgtable_attrs(to_dma_dev(dev), &sgt, exynos_gem->cookie,
 				    exynos_gem->dma_addr, exynos_gem->size,
-				    &exynos_gem->dma_attrs);
+				    exynos_gem->dma_attrs);
 	if (ret < 0) {
 		DRM_ERROR("failed to get sgtable.\n");
 		goto err_dma_free;
@@ -99,7 +99,7 @@ err_sgt_free:
 	sg_free_table(&sgt);
 err_dma_free:
 	dma_free_attrs(to_dma_dev(dev), exynos_gem->size, exynos_gem->cookie,
-		       exynos_gem->dma_addr, &exynos_gem->dma_attrs);
+		       exynos_gem->dma_addr, exynos_gem->dma_attrs);
 err_free:
 	drm_free_large(exynos_gem->pages);
 
@@ -120,7 +120,7 @@ static void exynos_drm_free_buf(struct exynos_drm_gem *exynos_gem)
 
 	dma_free_attrs(to_dma_dev(dev), exynos_gem->size, exynos_gem->cookie,
 			(dma_addr_t)exynos_gem->dma_addr,
-			&exynos_gem->dma_attrs);
+			exynos_gem->dma_attrs);
 
 	drm_free_large(exynos_gem->pages);
 }
@@ -346,7 +346,7 @@ static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
 
 	ret = dma_mmap_attrs(to_dma_dev(drm_dev), vma, exynos_gem->cookie,
 			     exynos_gem->dma_addr, exynos_gem->size,
-			     &exynos_gem->dma_attrs);
+			     exynos_gem->dma_attrs);
 	if (ret < 0) {
 		DRM_ERROR("failed to mmap.\n");
 		return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index 78100742281d..df7c543d6558 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -50,7 +50,7 @@ struct exynos_drm_gem {
 	void			*cookie;
 	void __iomem		*kvaddr;
 	dma_addr_t		dma_addr;
-	struct dma_attrs	dma_attrs;
+	unsigned long		dma_attrs;
 	struct page		**pages;
 	struct sg_table		*sgt;
 };
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index ea5a9ebf0f78..6c1bda504fb1 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -286,7 +286,7 @@ void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
  *	   or NULL on failure.
  */
 struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
-		struct dma_attrs *attrs, int prot, dma_addr_t *handle,
+		unsigned long attrs, int prot, dma_addr_t *handle,
 		void (*flush_page)(struct device *, const void *, phys_addr_t))
 {
 	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
@@ -400,7 +400,7 @@ dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
 }
 
 void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
-		enum dma_data_direction dir, struct dma_attrs *attrs)
+		enum dma_data_direction dir, unsigned long attrs)
 {
 	__iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
 }
@@ -560,7 +560,7 @@ out_restore_sg:
 }
 
 void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-		enum dma_data_direction dir, struct dma_attrs *attrs)
+		enum dma_data_direction dir, unsigned long attrs)
 {
 	/*
 	 * The scatterlist segments are mapped into a single
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 7399782c0998..87e6035c9e81 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -294,7 +294,7 @@ error:
 void *
 xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 			   dma_addr_t *dma_handle, gfp_t flags,
-			   struct dma_attrs *attrs)
+			   unsigned long attrs)
 {
 	void *ret;
 	int order = get_order(size);
@@ -346,7 +346,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_alloc_coherent);
 
 void
 xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
-			  dma_addr_t dev_addr, struct dma_attrs *attrs)
+			  dma_addr_t dev_addr, unsigned long attrs)
 {
 	int order = get_order(size);
 	phys_addr_t phys;
@@ -378,7 +378,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_free_coherent);
 dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
 				unsigned long offset, size_t size,
 				enum dma_data_direction dir,
-				struct dma_attrs *attrs)
+				unsigned long attrs)
 {
 	phys_addr_t map, phys = page_to_phys(page) + offset;
 	dma_addr_t dev_addr = xen_phys_to_bus(phys);
@@ -434,7 +434,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_map_page);
  */
 static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
 			     size_t size, enum dma_data_direction dir,
-				 struct dma_attrs *attrs)
+			     unsigned long attrs)
 {
 	phys_addr_t paddr = xen_bus_to_phys(dev_addr);
 
@@ -462,7 +462,7 @@ static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
 
 void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
 			    size_t size, enum dma_data_direction dir,
-			    struct dma_attrs *attrs)
+			    unsigned long attrs)
 {
 	xen_unmap_single(hwdev, dev_addr, size, dir, attrs);
 }
@@ -538,7 +538,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_sync_single_for_device);
 int
 xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
 			 int nelems, enum dma_data_direction dir,
-			 struct dma_attrs *attrs)
+			 unsigned long attrs)
 {
 	struct scatterlist *sg;
 	int i;
@@ -599,7 +599,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg_attrs);
 void
 xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
 			   int nelems, enum dma_data_direction dir,
-			   struct dma_attrs *attrs)
+			   unsigned long attrs)
 {
 	struct scatterlist *sg;
 	int i;
diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
deleted file mode 100644
index 5246239a4953..000000000000
--- a/include/linux/dma-attrs.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef _DMA_ATTR_H
-#define _DMA_ATTR_H
-
-#include <linux/bitmap.h>
-#include <linux/bitops.h>
-#include <linux/bug.h>
-
-/**
- * an enum dma_attr represents an attribute associated with a DMA
- * mapping. The semantics of each attribute should be defined in
- * Documentation/DMA-attributes.txt.
- */
-enum dma_attr {
-	DMA_ATTR_WRITE_BARRIER,
-	DMA_ATTR_WEAK_ORDERING,
-	DMA_ATTR_WRITE_COMBINE,
-	DMA_ATTR_NON_CONSISTENT,
-	DMA_ATTR_NO_KERNEL_MAPPING,
-	DMA_ATTR_SKIP_CPU_SYNC,
-	DMA_ATTR_FORCE_CONTIGUOUS,
-	DMA_ATTR_ALLOC_SINGLE_PAGES,
-	DMA_ATTR_MAX,
-};
-
-#define __DMA_ATTRS_LONGS BITS_TO_LONGS(DMA_ATTR_MAX)
-
-/**
- * struct dma_attrs - an opaque container for DMA attributes
- * @flags - bitmask representing a collection of enum dma_attr
- */
-struct dma_attrs {
-	unsigned long flags[__DMA_ATTRS_LONGS];
-};
-
-#define DEFINE_DMA_ATTRS(x) 					\
-	struct dma_attrs x = {					\
-		.flags = { [0 ... __DMA_ATTRS_LONGS-1] = 0 },	\
-	}
-
-static inline void init_dma_attrs(struct dma_attrs *attrs)
-{
-	bitmap_zero(attrs->flags, __DMA_ATTRS_LONGS);
-}
-
-/**
- * dma_set_attr - set a specific attribute
- * @attr: attribute to set
- * @attrs: struct dma_attrs (may be NULL)
- */
-static inline void dma_set_attr(enum dma_attr attr, struct dma_attrs *attrs)
-{
-	if (attrs == NULL)
-		return;
-	BUG_ON(attr >= DMA_ATTR_MAX);
-	__set_bit(attr, attrs->flags);
-}
-
-/**
- * dma_get_attr - check for a specific attribute
- * @attr: attribute to set
- * @attrs: struct dma_attrs (may be NULL)
- */
-static inline int dma_get_attr(enum dma_attr attr, struct dma_attrs *attrs)
-{
-	if (attrs == NULL)
-		return 0;
-	BUG_ON(attr >= DMA_ATTR_MAX);
-	return test_bit(attr, attrs->flags);
-}
-
-#endif /* _DMA_ATTR_H */
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 8443bbb5c071..81c5c8d167ad 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -39,7 +39,7 @@ int dma_direction_to_prot(enum dma_data_direction dir, bool coherent);
  * the arch code to take care of attributes and cache maintenance
  */
 struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
-		struct dma_attrs *attrs, int prot, dma_addr_t *handle,
+		unsigned long attrs, int prot, dma_addr_t *handle,
 		void (*flush_page)(struct device *, const void *, phys_addr_t));
 void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
 		dma_addr_t *handle);
@@ -56,9 +56,9 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
  * directly as DMA mapping callbacks for simplicity
  */
 void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
-		enum dma_data_direction dir, struct dma_attrs *attrs);
+		enum dma_data_direction dir, unsigned long attrs);
 void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-		enum dma_data_direction dir, struct dma_attrs *attrs);
+		enum dma_data_direction dir, unsigned long attrs);
 int iommu_dma_supported(struct device *dev, u64 mask);
 int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
 
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 71c1b215ef66..19e581d5f8b4 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -5,13 +5,25 @@
 #include <linux/string.h>
 #include <linux/device.h>
 #include <linux/err.h>
-#include <linux/dma-attrs.h>
 #include <linux/dma-debug.h>
 #include <linux/dma-direction.h>
 #include <linux/scatterlist.h>
 #include <linux/kmemcheck.h>
 #include <linux/bug.h>
 
+/**
+ * List of possible attributes associated with a DMA mapping. The semantics
+ * of each attribute should be defined in Documentation/DMA-attributes.txt.
+ */
+#define DMA_ATTR_WRITE_BARRIER		BIT(1)
+#define DMA_ATTR_WEAK_ORDERING		BIT(2)
+#define DMA_ATTR_WRITE_COMBINE		BIT(3)
+#define DMA_ATTR_NON_CONSISTENT		BIT(4)
+#define DMA_ATTR_NO_KERNEL_MAPPING	BIT(5)
+#define DMA_ATTR_SKIP_CPU_SYNC		BIT(6)
+#define DMA_ATTR_FORCE_CONTIGUOUS	BIT(7)
+#define DMA_ATTR_ALLOC_SINGLE_PAGES	BIT(8)
+
 /*
  * A dma_addr_t can hold any valid DMA or bus address for the platform.
  * It can be given to a device to use as a DMA source or target.  A CPU cannot
@@ -21,34 +33,35 @@
 struct dma_map_ops {
 	void* (*alloc)(struct device *dev, size_t size,
 				dma_addr_t *dma_handle, gfp_t gfp,
-				struct dma_attrs *attrs);
+				unsigned long attrs);
 	void (*free)(struct device *dev, size_t size,
 			      void *vaddr, dma_addr_t dma_handle,
-			      struct dma_attrs *attrs);
+			      unsigned long attrs);
 	int (*mmap)(struct device *, struct vm_area_struct *,
-			  void *, dma_addr_t, size_t, struct dma_attrs *attrs);
+			  void *, dma_addr_t, size_t,
+			  unsigned long attrs);
 
 	int (*get_sgtable)(struct device *dev, struct sg_table *sgt, void *,
-			   dma_addr_t, size_t, struct dma_attrs *attrs);
+			   dma_addr_t, size_t, unsigned long attrs);
 
 	dma_addr_t (*map_page)(struct device *dev, struct page *page,
 			       unsigned long offset, size_t size,
 			       enum dma_data_direction dir,
-			       struct dma_attrs *attrs);
+			       unsigned long attrs);
 	void (*unmap_page)(struct device *dev, dma_addr_t dma_handle,
 			   size_t size, enum dma_data_direction dir,
-			   struct dma_attrs *attrs);
+			   unsigned long attrs);
 	/*
 	 * map_sg returns 0 on error and a value > 0 on success.
 	 * It should never return a value < 0.
 	 */
 	int (*map_sg)(struct device *dev, struct scatterlist *sg,
 		      int nents, enum dma_data_direction dir,
-		      struct dma_attrs *attrs);
+		      unsigned long attrs);
 	void (*unmap_sg)(struct device *dev,
 			 struct scatterlist *sg, int nents,
 			 enum dma_data_direction dir,
-			 struct dma_attrs *attrs);
+			 unsigned long attrs);
 	void (*sync_single_for_cpu)(struct device *dev,
 				    dma_addr_t dma_handle, size_t size,
 				    enum dma_data_direction dir);
@@ -88,6 +101,16 @@ static inline int is_device_dma_capable(struct device *dev)
 	return dev->dma_mask != NULL && *dev->dma_mask != DMA_MASK_NONE;
 }
 
+/**
+ * dma_get_attr - check for a specific attribute
+ * @attr: attribute to look for
+ * @attrs: attributes to check within
+ */
+static inline bool dma_get_attr(unsigned long attr, unsigned long attrs)
+{
+	return !!(attr & attrs);
+}
+
 #ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
 /*
  * These three functions are only for dma allocator.
@@ -123,7 +146,7 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
 static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
 					      size_t size,
 					      enum dma_data_direction dir,
-					      struct dma_attrs *attrs)
+					      unsigned long attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	dma_addr_t addr;
@@ -142,7 +165,7 @@ static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
 static inline void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr,
 					  size_t size,
 					  enum dma_data_direction dir,
-					  struct dma_attrs *attrs)
+					  unsigned long attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 
@@ -158,7 +181,7 @@ static inline void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr,
  */
 static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
 				   int nents, enum dma_data_direction dir,
-				   struct dma_attrs *attrs)
+				   unsigned long attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	int i, ents;
@@ -176,7 +199,7 @@ static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
 
 static inline void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
 				      int nents, enum dma_data_direction dir,
-				      struct dma_attrs *attrs)
+				      unsigned long attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 
@@ -195,7 +218,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
 
 	kmemcheck_mark_initialized(page_address(page) + offset, size);
 	BUG_ON(!valid_dma_direction(dir));
-	addr = ops->map_page(dev, page, offset, size, dir, NULL);
+	addr = ops->map_page(dev, page, offset, size, dir, 0);
 	debug_dma_map_page(dev, page, offset, size, dir, addr, false);
 
 	return addr;
@@ -208,7 +231,7 @@ static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
 
 	BUG_ON(!valid_dma_direction(dir));
 	if (ops->unmap_page)
-		ops->unmap_page(dev, addr, size, dir, NULL);
+		ops->unmap_page(dev, addr, size, dir, 0);
 	debug_dma_unmap_page(dev, addr, size, dir, false);
 }
 
@@ -289,10 +312,10 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
 
 }
 
-#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL)
-#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, NULL)
-#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL)
-#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL)
+#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, 0)
+#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, 0)
+#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
+#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
 
 extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
 			   void *cpu_addr, dma_addr_t dma_addr, size_t size);
@@ -321,7 +344,7 @@ void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags);
  */
 static inline int
 dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr,
-	       dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
+	       dma_addr_t dma_addr, size_t size, unsigned long attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	BUG_ON(!ops);
@@ -330,7 +353,7 @@ dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr,
 	return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
 }
 
-#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, NULL)
+#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, 0)
 
 int
 dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
@@ -338,7 +361,8 @@ dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
 
 static inline int
 dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr,
-		      dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
+		      dma_addr_t dma_addr, size_t size,
+		      unsigned long attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	BUG_ON(!ops);
@@ -348,7 +372,7 @@ dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr,
 	return dma_common_get_sgtable(dev, sgt, cpu_addr, dma_addr, size);
 }
 
-#define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, NULL)
+#define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, 0)
 
 #ifndef arch_dma_alloc_attrs
 #define arch_dma_alloc_attrs(dev, flag)	(true)
@@ -356,7 +380,7 @@ dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr,
 
 static inline void *dma_alloc_attrs(struct device *dev, size_t size,
 				       dma_addr_t *dma_handle, gfp_t flag,
-				       struct dma_attrs *attrs)
+				       unsigned long attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 	void *cpu_addr;
@@ -378,7 +402,7 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size,
 
 static inline void dma_free_attrs(struct device *dev, size_t size,
 				     void *cpu_addr, dma_addr_t dma_handle,
-				     struct dma_attrs *attrs)
+				     unsigned long attrs)
 {
 	struct dma_map_ops *ops = get_dma_ops(dev);
 
@@ -398,31 +422,27 @@ static inline void dma_free_attrs(struct device *dev, size_t size,
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
 		dma_addr_t *dma_handle, gfp_t flag)
 {
-	return dma_alloc_attrs(dev, size, dma_handle, flag, NULL);
+	return dma_alloc_attrs(dev, size, dma_handle, flag, 0);
 }
 
 static inline void dma_free_coherent(struct device *dev, size_t size,
 		void *cpu_addr, dma_addr_t dma_handle)
 {
-	return dma_free_attrs(dev, size, cpu_addr, dma_handle, NULL);
+	return dma_free_attrs(dev, size, cpu_addr, dma_handle, 0);
 }
 
 static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
 		dma_addr_t *dma_handle, gfp_t gfp)
 {
-	DEFINE_DMA_ATTRS(attrs);
-
-	dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
-	return dma_alloc_attrs(dev, size, dma_handle, gfp, &attrs);
+	return dma_alloc_attrs(dev, size, dma_handle, gfp,
+			       DMA_ATTR_NON_CONSISTENT);
 }
 
 static inline void dma_free_noncoherent(struct device *dev, size_t size,
 		void *cpu_addr, dma_addr_t dma_handle)
 {
-	DEFINE_DMA_ATTRS(attrs);
-
-	dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
-	dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
+	dma_free_attrs(dev, size, cpu_addr, dma_handle,
+		       DMA_ATTR_NON_CONSISTENT);
 }
 
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
@@ -646,9 +666,8 @@ static inline void dmam_release_declared_memory(struct device *dev)
 static inline void *dma_alloc_wc(struct device *dev, size_t size,
 				 dma_addr_t *dma_addr, gfp_t gfp)
 {
-	DEFINE_DMA_ATTRS(attrs);
-	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
-	return dma_alloc_attrs(dev, size, dma_addr, gfp, &attrs);
+	return dma_alloc_attrs(dev, size, dma_addr, gfp,
+			       DMA_ATTR_WRITE_COMBINE);
 }
 #ifndef dma_alloc_writecombine
 #define dma_alloc_writecombine dma_alloc_wc
@@ -657,9 +676,8 @@ static inline void *dma_alloc_wc(struct device *dev, size_t size,
 static inline void dma_free_wc(struct device *dev, size_t size,
 			       void *cpu_addr, dma_addr_t dma_addr)
 {
-	DEFINE_DMA_ATTRS(attrs);
-	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
-	return dma_free_attrs(dev, size, cpu_addr, dma_addr, &attrs);
+	return dma_free_attrs(dev, size, cpu_addr, dma_addr,
+			      DMA_ATTR_WRITE_COMBINE);
 }
 #ifndef dma_free_writecombine
 #define dma_free_writecombine dma_free_wc
@@ -670,9 +688,8 @@ static inline int dma_mmap_wc(struct device *dev,
 			      void *cpu_addr, dma_addr_t dma_addr,
 			      size_t size)
 {
-	DEFINE_DMA_ATTRS(attrs);
-	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
-	return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
+	return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size,
+			      DMA_ATTR_WRITE_COMBINE);
 }
 #ifndef dma_mmap_writecombine
 #define dma_mmap_writecombine dma_mmap_wc
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 017fced60242..5f81f8a187f2 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -6,7 +6,6 @@
 #include <linux/types.h>
 
 struct device;
-struct dma_attrs;
 struct page;
 struct scatterlist;
 
@@ -68,10 +67,10 @@ swiotlb_free_coherent(struct device *hwdev, size_t size,
 extern dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 				   unsigned long offset, size_t size,
 				   enum dma_data_direction dir,
-				   struct dma_attrs *attrs);
+				   unsigned long attrs);
 extern void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
 			       size_t size, enum dma_data_direction dir,
-			       struct dma_attrs *attrs);
+			       unsigned long attrs);
 
 extern int
 swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
@@ -83,12 +82,13 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
 
 extern int
 swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
-		     enum dma_data_direction dir, struct dma_attrs *attrs);
+		     enum dma_data_direction dir,
+		     unsigned long attrs);
 
 extern void
 swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
 		       int nelems, enum dma_data_direction dir,
-		       struct dma_attrs *attrs);
+		       unsigned long attrs);
 
 extern void
 swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h
index 8b2eb93ae8ba..7c35e279d1e3 100644
--- a/include/xen/swiotlb-xen.h
+++ b/include/xen/swiotlb-xen.h
@@ -9,30 +9,30 @@ extern int xen_swiotlb_init(int verbose, bool early);
 extern void
 *xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 			    dma_addr_t *dma_handle, gfp_t flags,
-			    struct dma_attrs *attrs);
+			    unsigned long attrs);
 
 extern void
 xen_swiotlb_free_coherent(struct device *hwdev, size_t size,
 			  void *vaddr, dma_addr_t dma_handle,
-			  struct dma_attrs *attrs);
+			  unsigned long attrs);
 
 extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
 				       unsigned long offset, size_t size,
 				       enum dma_data_direction dir,
-				       struct dma_attrs *attrs);
+				       unsigned long attrs);
 
 extern void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
 				   size_t size, enum dma_data_direction dir,
-				   struct dma_attrs *attrs);
+				   unsigned long attrs);
 extern int
 xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
 			 int nelems, enum dma_data_direction dir,
-			 struct dma_attrs *attrs);
+			 unsigned long attrs);
 
 extern void
 xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
 			   int nelems, enum dma_data_direction dir,
-			   struct dma_attrs *attrs);
+			   unsigned long attrs);
 
 extern void
 xen_swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
diff --git a/lib/dma-noop.c b/lib/dma-noop.c
index 72145646857e..3d766e78fbe2 100644
--- a/lib/dma-noop.c
+++ b/lib/dma-noop.c
@@ -10,7 +10,7 @@
 
 static void *dma_noop_alloc(struct device *dev, size_t size,
 			    dma_addr_t *dma_handle, gfp_t gfp,
-			    struct dma_attrs *attrs)
+			    unsigned long attrs)
 {
 	void *ret;
 
@@ -22,7 +22,7 @@ static void *dma_noop_alloc(struct device *dev, size_t size,
 
 static void dma_noop_free(struct device *dev, size_t size,
 			  void *cpu_addr, dma_addr_t dma_addr,
-			  struct dma_attrs *attrs)
+			  unsigned long attrs)
 {
 	free_pages((unsigned long)cpu_addr, get_order(size));
 }
@@ -30,13 +30,14 @@ static void dma_noop_free(struct device *dev, size_t size,
 static dma_addr_t dma_noop_map_page(struct device *dev, struct page *page,
 				      unsigned long offset, size_t size,
 				      enum dma_data_direction dir,
-				      struct dma_attrs *attrs)
+				      unsigned long attrs)
 {
 	return page_to_phys(page) + offset;
 }
 
 static int dma_noop_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
-			     enum dma_data_direction dir, struct dma_attrs *attrs)
+			     enum dma_data_direction dir,
+			     unsigned long attrs)
 {
 	int i;
 	struct scatterlist *sg;
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 76f29ecba8f4..22e13a0e19d7 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -738,7 +738,7 @@ swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir,
 dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 			    unsigned long offset, size_t size,
 			    enum dma_data_direction dir,
-			    struct dma_attrs *attrs)
+			    unsigned long attrs)
 {
 	phys_addr_t map, phys = page_to_phys(page) + offset;
 	dma_addr_t dev_addr = phys_to_dma(dev, phys);
@@ -807,7 +807,7 @@ static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
 
 void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
 			size_t size, enum dma_data_direction dir,
-			struct dma_attrs *attrs)
+			unsigned long attrs)
 {
 	unmap_single(hwdev, dev_addr, size, dir);
 }
@@ -877,7 +877,7 @@ EXPORT_SYMBOL(swiotlb_sync_single_for_device);
  */
 int
 swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
-		     enum dma_data_direction dir, struct dma_attrs *attrs)
+		     enum dma_data_direction dir, unsigned long attrs)
 {
 	struct scatterlist *sg;
 	int i;
@@ -914,7 +914,7 @@ int
 swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
 	       enum dma_data_direction dir)
 {
-	return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL);
+	return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, 0);
 }
 EXPORT_SYMBOL(swiotlb_map_sg);
 
@@ -924,7 +924,8 @@ EXPORT_SYMBOL(swiotlb_map_sg);
  */
 void
 swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
-		       int nelems, enum dma_data_direction dir, struct dma_attrs *attrs)
+		       int nelems, enum dma_data_direction dir,
+		       unsigned long attrs)
 {
 	struct scatterlist *sg;
 	int i;
@@ -941,7 +942,7 @@ void
 swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
 		 enum dma_data_direction dir)
 {
-	return swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL);
+	return swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, 0);
 }
 EXPORT_SYMBOL(swiotlb_unmap_sg);
 
-- 
1.9.1



From p.zabel at pengutronix.de  Mon May 30 05:11:15 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Mon, 30 May 2016 14:11:15 +0200
Subject: [PATCH] reset: Put back *_optional variants
In-Reply-To: <5cf9f346-9b6e-d521-612c-9edd167aa759@redhat.com>
References: <ca359e013c30f27c825a9580164b01da5ca6476d.1464224883.git.johnyoun@synopsys.com>
 <12e450f0-70ea-29f8-0bf7-8a0697263f2d@redhat.com>
 <57476E48.2060204@synopsys.com>
 <dcf6372f-4910-bd03-f1b5-c7e0086fdead@redhat.com>
 <1464603520.3808.34.camel@pengutronix.de>
 <5cf9f346-9b6e-d521-612c-9edd167aa759@redhat.com>
Message-ID: <1464610275.3808.36.camel@pengutronix.de>

Am Montag, den 30.05.2016, 13:32 +0200 schrieb Hans de Goede:
> Hi,
> 
> On 30-05-16 12:18, Philipp Zabel wrote:
> > Hi,
> >
> > Am Freitag, den 27.05.2016, 09:06 +0200 schrieb Hans de Goede:
> > [...]
> >>>> So IMHO the following change would be a better way to fix this:
> >>>>
> >>>> --- a/include/linux/reset.h
> >>>> +++ b/include/linux/reset.h
> >>>> @@ -65,14 +65,14 @@ static inline struct reset_control *__of_reset_control_get(
> >>>>                                          struct device_node *node,
> >>>>                                          const char *id, int index, int shared)
> >>>>   {
> >>>> -   return ERR_PTR(-EINVAL);
> >>>> + return ERR_PTR(-ENOTSUPP);
> >>>>   }
> >>>>
> >>>>   static inline struct reset_control *__devm_reset_control_get(
> >>>>                                          struct device *dev,
> >>>>                                          const char *id, int index, int shared)
> >>>>   {
> >>>> -   return ERR_PTR(-EINVAL);
> >>>> + return ERR_PTR(-ENOTSUPP);
> >>>>   }
> >>>>
> >>>>   #endif /* CONFIG_RESET_CONTROLLER */
> >>>
> >>>
> >>> I'm good with this. However, per Philipp on a previous thread, the
> >>> intended behavior is to return -EINVAL for the non-optional functions.
> >>>
> >>> http://marc.info/?l=linux-usb&m=146156945528848&w=2
> >
> > Adding Dinh to Cc: because he wanted this changed from -EINVAL.
> > My point then was that WARN_ON + -EINVAL is indented in this case.

No idea how this happened, but I meant "intended", obviously :)

regards
Philipp



From geert at linux-m68k.org  Mon May 30 05:11:51 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 30 May 2016 14:11:51 +0200
Subject: [PATCH 5/5] RFC spi: sun4i: add DMA support
In-Reply-To: <20160530112610.GJ29837@sirena.org.uk>
References: <cover.1464130597.git.hramrach@gmail.com>
 <ba0d6eb37cc4b0d2c46acbf9fcd7d644b3545ce8.1464130597.git.hramrach@gmail.com>
 <20160530112610.GJ29837@sirena.org.uk>
Message-ID: <CAMuHMdVThvtqgFnyqoqypwwf1d81uu9NBo6-heTZBcvBxRevNw@mail.gmail.com>

Hi Mark,

On Mon, May 30, 2016 at 1:26 PM, Mark Brown <broonie at kernel.org> wrote:
> On Thu, May 26, 2016 at 07:25:25PM -0000, Michal Suchanek wrote:
>>  - fallback to previous behaviour when DMA initialization fails
>>
>>    + this has the problem that when the driver happens to load before the dma
>>      driver it will not use dma - can be addressed with a module parameter
>
> No, you should pay attention to the error you are getting and let probe
> deferral happen if that's the error you get.

Unfortunately DMA is an optional feature.

There's no way to distinguish between -EPROBE_DEFER due to the SPI master
driver being probed before the DMA engine driver, and -EPROBE_DEFER due to
support for the DMA engine not having been compiled in.

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 zourongrong at huawei.com  Mon May 30 05:09:14 2016
From: zourongrong at huawei.com (Rongrong Zou)
Date: Mon, 30 May 2016 20:09:14 +0800
Subject: [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master
 driver
In-Reply-To: <20160530090331.GD27098@phenom.ffwll.local>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
 <1464514855-108050-2-git-send-email-zourongrong@gmail.com>
 <20160530090331.GD27098@phenom.ffwll.local>
Message-ID: <574C2D6A.3090508@huawei.com>

Hi Daniel,
Thanks for reveiwing!

? 2016/5/30 17:03, Daniel Vetter ??:
> On Sun, May 29, 2016 at 05:40:49PM +0800, Rongrong Zou wrote:
>> Add DRM master driver for Hisilicon Hibmc SoC which used for
>> Out-of-band management. Blow is the general hardware connection,
>> both the Hibmc and the host CPU are on the same mother board.
>>
>> +----------+       +----------+
>> |          | PCIe  |  Hibmc   |
>> |host CPU( |<----->| display  |
>> |arm64,x86)|       |subsystem |
>> +----------+       +----------+
>>
>> Signed-off-by: Rongrong Zou <zourongrong at gmail.com>
>> Signed-off-by: Jianhua Li <lijianhua at huawei.com>
>> ---
>>   drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
>>   drivers/gpu/drm/hisilicon/Makefile                |   3 +-
>>   drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
>>   drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 307 ++++++++++++++++++++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  39 +++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 +++++++++++++++
>>   9 files changed, 699 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>>
>> diff --git a/drivers/gpu/drm/hisilicon/Kconfig b/drivers/gpu/drm/hisilicon/Kconfig
>> index 558c61b..2fd2724 100644
>> --- a/drivers/gpu/drm/hisilicon/Kconfig
>> +++ b/drivers/gpu/drm/hisilicon/Kconfig
>> @@ -2,4 +2,5 @@
>>   # hisilicon drm device configuration.
>>   # Please keep this list sorted alphabetically
>>
>> +source "drivers/gpu/drm/hisilicon/hibmc/Kconfig"
>>   source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
>> diff --git a/drivers/gpu/drm/hisilicon/Makefile b/drivers/gpu/drm/hisilicon/Makefile
>> index e3f6d49..4d7185c 100644
>> --- a/drivers/gpu/drm/hisilicon/Makefile
>> +++ b/drivers/gpu/drm/hisilicon/Makefile
>> @@ -2,4 +2,5 @@
>>   # Makefile for hisilicon drm drivers.
>>   # Please keep this list sorted alphabetically
>>
>> -obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
>> +obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/
>> +obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
>> \ No newline at end of file
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>> new file mode 100644
>> index 0000000..1e7810d
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>> @@ -0,0 +1,13 @@
>> +config DRM_HISI_HIBMC
>> +	tristate "DRM Support for Hisilicon Hibmc"
>> +	depends on DRM && PCI
>> +	select DRM_KMS_HELPER
>> +	select DRM_KMS_FB_HELPER
>> +	select DRM_GEM_CMA_HELPER
>> +	select DRM_KMS_CMA_HELPER
>> +	select FB_SYS_FILLRECT
>> +	select FB_SYS_COPYAREA
>> +	select FB_SYS_IMAGEBLIT
>> +	help
>> +	  Choose this option if you have a Hisilicon Hibmc soc chipset.
>> +	  If M is selected the module will be called hibmc-drm.
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>> new file mode 100644
>> index 0000000..533f9ed
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>> @@ -0,0 +1,4 @@
>> +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
>> +
>> +obj-$(CONFIG_DRM_HISI_HIBMC)	+=hibmc-drm.o
>> +#obj-y	+= hibmc-drm.o
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>> new file mode 100644
>> index 0000000..7eaacd8
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>> @@ -0,0 +1,307 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + *	Rongrong Zou <zourongrong at huawei>
>> + *	Rongrong Zou <zourongrong at gmail.com>
>> + *	Jianhua Li <lijianhua at huawei.com>
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/console.h>
>> +#include <drm/drm_atomic_helper.h>
>> +#include <drm/drm_crtc_helper.h>
>> +#include <drm/drm_fb_helper.h>
>> +#include <drm/drm_gem_cma_helper.h>
>> +#include <drm/drmP.h>
>> +
>> +#include "hibmc_drm_drv.h"
>> +#include "hibmc_drm_regs.h"
>> +#include "hibmc_drm_power.h"
>> +
>> +static const struct file_operations hibmc_fops = {
>> +	.owner		= THIS_MODULE,
>> +	.open		= drm_open,
>> +	.release	= drm_release,
>> +	.unlocked_ioctl	= drm_ioctl,
>> +#ifdef CONFIG_COMPAT
>> +	.compat_ioctl	= drm_compat_ioctl,
>> +#endif
>> +	.poll		= drm_poll,
>> +	.read		= drm_read,
>> +	.llseek		= no_llseek,
>> +};
>> +
>> +static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
>> +{
>> +	return 0;
>> +}
>> +
>> +static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
>> +{
>> +}
>> +
>> +static struct drm_driver hibmc_driver = {
>> +	.driver_features	= DRIVER_GEM | DRIVER_MODESET,
>> +	.fops			= &hibmc_fops,
>> +	.name			= "hibmc",
>> +	.desc			= "hibmc drm driver",
>> +	.major			= 1,
>> +	.minor			= 0,
>> +	.get_vblank_counter = drm_vblank_no_hw_counter,
>> +	.enable_vblank		= hibmc_enable_vblank,
>> +	.disable_vblank	= hibmc_disable_vblank,
>> +	.gem_free_object        = drm_gem_cma_free_object,
>
> gem_free_object_unlocked pls.

Applied, thanks.

>
>> +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
>> +	.dumb_create            = drm_gem_cma_dumb_create,
>> +	.dumb_map_offset        = drm_gem_cma_dumb_map_offset,
>> +	.dumb_destroy           = drm_gem_dumb_destroy,
>> +};
>> +
>> +static int hibmc_pm_suspend(struct device *dev)
>> +{
>> +	struct pci_dev *pdev = to_pci_dev(dev);
>> +	struct drm_device *drm_dev = pci_get_drvdata(pdev);
>> +
>> +	drm_kms_helper_poll_disable(drm_dev);
>> +
>> +	return 0;
>> +}
>> +
>> +static int hibmc_pm_resume(struct device *dev)
>> +{
>> +	struct pci_dev *pdev = to_pci_dev(dev);
>> +	struct drm_device *drm_dev = pci_get_drvdata(pdev);
>> +
>> +	drm_helper_resume_force_mode(drm_dev);
>> +	drm_kms_helper_poll_enable(drm_dev);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct dev_pm_ops hibmc_pm_ops = {
>> +	SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
>> +				hibmc_pm_resume)
>> +};
>> +
>> +static const struct drm_mode_config_funcs mode_config_funcs = {
>> +	.atomic_check = drm_atomic_helper_check,
>> +	.atomic_commit = drm_atomic_helper_commit,
>
> So how exactly does nonblocking commit work for you? Please run the igt
> validation suit on your new driver, a bunch of collabora engineers are
> working hard to make it run on non-intel drivers too. Ping Tomeu and
> Robert Foss for more info on this please.

OK, I should learn igt validation suit and test the new driver.
I tested the driver with tools such as fbtest before. Thanks.

>
> Lucky for you I'm working on generic nonblocking support in the atomic
> helpers, patches are on the mailing list.
>

It's nice, thanks. :)

>> +};
>> +
>> +
>> +static int hibmc_hw_config(struct hibmc_drm_device *hidev)
>> +{
>> +	unsigned int reg;
>> +
>> +	/* On hardware reset, power mode 0 is default. */
>> +	hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
>> +
>> +	/* Enable display power gate & LOCALMEM power gate*/
>> +	reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
>> +	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
>> +	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
>> +	reg |= HIBMC_CURR_GATE_DISPLAY(ON);
>> +	reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
>> +
>> +	hibmc_set_current_gate(hidev, reg);
>> +
>> +	/* Reset the memory controller. If the memory controller
>> +	 * is not reset in chip,the system might hang when sw accesses
>> +	 * the memory.The memory should be resetted after
>> +	 * changing the MXCLK.
>> +	 */
>> +	reg = readl(hidev->mmio + HIBMC_MISC_CTRL);
>> +	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
>> +	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(RESET);
>> +	writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
>> +
>> +	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
>> +	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(NORMAL);
>> +
>> +	writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
>> +
>> +	/* We can add more initialization as needed. */
>> +
>> +	return 0;
>> +}
>> +
>> +static int hibmc_hw_map(struct hibmc_drm_device *hidev)
>> +{
>> +	struct drm_device *dev = hidev->dev;
>> +	struct pci_dev *pdev = dev->pdev;
>> +	resource_size_t addr, size, ioaddr, iosize;
>> +
>> +	ioaddr = pci_resource_start(pdev, 1);
>> +	iosize = MB(2);
>> +
>> +	hidev->mmio = ioremap_nocache(ioaddr, iosize);
>> +
>> +	if (!hidev->mmio) {
>> +		DRM_ERROR("Cannot map mmio region\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	addr = pci_resource_start(pdev, 0);
>> +	size = MB(16);
>> +
>> +	hidev->fb_map = ioremap(addr, size);
>> +	if (!hidev->fb_map) {
>> +		DRM_ERROR("Cannot map framebuffer\n");
>> +		return -ENOMEM;
>> +	}
>> +	hidev->fb_base = addr;
>> +	hidev->fb_size = size;
>> +
>> +	return 0;
>> +}
>> +
>> +static void hibmc_hw_fini(struct hibmc_drm_device *hidev)
>> +{
>> +	if (hidev->mmio)
>> +		iounmap(hidev->mmio);
>> +	if (hidev->fb_map)
>> +		iounmap(hidev->fb_map);
>> +}
>> +
>> +static int hibmc_hw_init(struct hibmc_drm_device *hidev)
>> +{
>> +	int ret;
>> +
>> +	ret = hibmc_hw_map(hidev);
>> +	if (ret)
>> +		return ret;
>> +
>> +	hibmc_hw_config(hidev);
>> +
>> +	return 0;
>> +}
>> +
>> +static int hibmc_unload(struct drm_device *dev)
>> +{
>> +	struct hibmc_drm_device *hidev = dev->dev_private;
>> +
>> +	hibmc_hw_fini(hidev);
>> +	dev->dev_private = NULL;
>> +	return 0;
>> +}
>> +
>> +static int hibmc_load(struct drm_device *dev, unsigned long flags)
>> +{
>> +	struct hibmc_drm_device *hidev;
>> +	int ret;
>> +
>> +	hidev = devm_kzalloc(dev->dev, sizeof(*hidev), GFP_KERNEL);
>> +	if (!hidev)
>> +		return -ENOMEM;
>> +	dev->dev_private = hidev;
>> +	hidev->dev = dev;
>> +
>> +	ret = hibmc_hw_init(hidev);
>> +	if (ret)
>> +		goto err;
>> +
>> +
>> +	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
>> +	if (ret) {
>> +		DRM_ERROR("failed to initialize vblank.\n");
>> +		return ret;
>> +	}
>> +	/* reset all the states of crtc/plane/encoder/connector */
>> +	drm_mode_config_reset(dev);
>> +
>> +	return 0;
>> +
>> +err:
>> +	hibmc_unload(dev);
>> +	DRM_ERROR("failed to initialize drm driver.\n");
>> +	return ret;
>> +}
>> +
>> +
>> +static int hibmc_pci_probe(struct pci_dev *pdev,
>> +			   const struct pci_device_id *ent)
>> +{
>> +	struct drm_device *dev;
>> +	int ret;
>> +
>> +	dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
>> +	if (!dev)
>> +		return -ENOMEM;
>> +
>> +	dev->pdev = pdev;
>> +	pci_set_drvdata(pdev, dev);
>> +
>> +	ret = pci_enable_device(pdev);
>> +	if (ret)
>> +		goto err_free;
>> +
>> +	ret = hibmc_load(dev, 0);
>> +	if (ret)
>> +		goto err_disable;
>> +
>> +	ret = drm_dev_register(dev, 0);
>> +	if (ret)
>> +		goto err_unload;
>> +
>> +	return 0;
>> +
>> +err_unload:
>> +	hibmc_unload(dev);
>> +err_disable:
>> +	pci_disable_device(pdev);
>> +err_free:
>> +	drm_dev_unref(dev);
>> +
>> +	return ret;
>> +}
>> +
>> +static void hibmc_pci_remove(struct pci_dev *pdev)
>> +{
>> +	struct drm_device *dev = pci_get_drvdata(pdev);
>> +
>> +	drm_dev_unregister(dev);
>> +	hibmc_unload(dev);
>> +	drm_dev_unref(dev);
>> +}
>> +
>> +static struct pci_device_id hibmc_pci_table[] = {
>> +	{0x19e5, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
>> +	{0,}
>> +};
>> +
>> +static struct pci_driver hibmc_pci_driver = {
>> +	.name =		"hibmc-drm",
>> +	.id_table =	hibmc_pci_table,
>> +	.probe =	hibmc_pci_probe,
>> +	.remove =	hibmc_pci_remove,
>> +	.driver.pm =    &hibmc_pm_ops,
>> +};
>> +
>> +static int __init hibmc_init(void)
>> +{
>> +	return pci_register_driver(&hibmc_pci_driver);
>> +}
>> +
>> +static void __exit hibmc_exit(void)
>> +{
>> +	return pci_unregister_driver(&hibmc_pci_driver);
>> +}
>> +
>> +module_init(hibmc_init);
>> +module_exit(hibmc_exit);
>> +
>> +MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
>> +MODULE_AUTHOR("RongrongZou <zourongrong at huawei.com>");
>> +MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
>> +MODULE_LICENSE("GPL v2");
>> +
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>> new file mode 100644
>> index 0000000..a072ea9
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>> @@ -0,0 +1,39 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + *	Rongrong Zou <zourongrong at huawei>
>> + *	Rongrong Zou <zourongrong at gmail.com>
>> + *	Jianhua Li <lijianhua at huawei.com>
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#ifndef HIBMC_DRM_DRV_H
>> +#define HIBMC_DRM_DRV_H
>> +
>> +#include <drm/drmP.h>
>> +#include <drm/drm_fb_helper.h>
>> +#include <drm/drm_gem_cma_helper.h>
>> +
>> +struct hibmc_drm_device {
>> +	/* hw */
>> +	void __iomem   *mmio;
>> +	void __iomem   *fb_map;
>> +	unsigned long  fb_base;
>> +	unsigned long  fb_size;
>> +
>> +	/* drm */
>> +	struct drm_device  *dev;
>> +	bool mode_config_initialized;
>> +};
>> +
>> +
>> +#endif
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>> new file mode 100644
>> index 0000000..673be10
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>> @@ -0,0 +1,91 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + *	Rongrong Zou <zourongrong at huawei>
>> + *	Rongrong Zou <zourongrong at gmail.com>
>> + *	Jianhua Li <lijianhua at huawei.com>
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#include <linux/io.h>
>> +#include <drm/drmP.h>
>> +#include <drm/drm_fb_helper.h>
>> +#include "hibmc_drm_drv.h"
>> +#include "hibmc_drm_regs.h"
>> +
>> +/*
>> + * It can operate in one of three modes: 0, 1 or Sleep.
>> + */
>> +void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
>> +				 unsigned int power_mode)
>> +{
>> +	unsigned int control_value = 0;
>> +	void __iomem   *mmio = hidev->mmio;
>> +
>> +	if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
>> +		return;
>> +
>> +	control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
>> +	control_value &= ~HIBMC_PW_MODE_CTL_MODE_MASK;
>> +
>> +	control_value |= HIBMC_PW_MODE_CTL_MODE(power_mode) &
>> +			 HIBMC_PW_MODE_CTL_MODE_MASK;
>> +
>> +
>> +    /* Set up other fields in Power Control Register */
>> +	if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP) {
>> +		control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>> +		control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(0) &
>> +				 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>> +	} else {
>> +		control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>> +		control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(1) &
>> +				 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>> +
>> +	}
>> +    /* Program new power mode. */
>> +	writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
>> +}
>> +
>> +static unsigned int hibmc_get_power_mode(struct hibmc_drm_device *hidev)
>> +{
>> +	void __iomem   *mmio = hidev->mmio;
>> +
>> +	return (readl(mmio + HIBMC_POWER_MODE_CTRL)&
>> +		HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
>> +}
>> +
>> +void hibmc_set_current_gate(struct hibmc_drm_device *hidev, unsigned int gate)
>> +{
>> +	unsigned int gate_reg;
>> +	unsigned int mode;
>> +	void __iomem   *mmio = hidev->mmio;
>> +
>> +	/* Get current power mode. */
>> +	mode = hibmc_get_power_mode(hidev);
>> +
>> +	switch (mode) {
>> +	case HIBMC_PW_MODE_CTL_MODE_MODE0:
>> +		gate_reg = HIBMC_MODE0_GATE;
>> +		break;
>> +
>> +	case HIBMC_PW_MODE_CTL_MODE_MODE1:
>> +		gate_reg = HIBMC_MODE1_GATE;
>> +		break;
>> +
>> +	default:
>> +		gate_reg = HIBMC_MODE0_GATE;
>> +		break;
>> +	}
>> +	writel(gate, mmio + gate_reg);
>> +}
>> +
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>> new file mode 100644
>> index 0000000..39f7a17
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>> @@ -0,0 +1,28 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + *	Rongrong Zou <zourongrong at huawei>
>> + *	Rongrong Zou <zourongrong at gmail.com>
>> + *	Jianhua Li <lijianhua at huawei.com>
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#ifndef HIBMC_DRM_POWER_H
>> +#define HIBMC_DRM_POWER_H
>> +
>> +#include "hibmc_drm_drv.h"
>> +
>> +extern void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
>> +				 unsigned int power_mode);
>> +extern void hibmc_set_current_gate(struct hibmc_drm_device *hidev,
>> +				   unsigned int gate);
>> +#endif
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>> new file mode 100644
>> index 0000000..4966c42
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>> @@ -0,0 +1,214 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + *	Rongrong Zou <zourongrong at huawei>
>> + *	Rongrong Zou <zourongrong at gmail.com>
>> + *	Jianhua Li <lijianhua at huawei.com>
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#ifndef HIBMC_DRM_HW_H
>> +#define HIBMC_DRM_HW_H
>> +
>> +#define OFF 0
>> +#define ON  1
>> +#define DISABLE               0
>> +#define ENABLE                1
>> +
>> +
>> +
>> +/* register definition */
>> +#define HIBMC_MISC_CTRL				0x4
>> +
>> +#define HIBMC_MSCCTL_LOCALMEM_RESET(x)		((x) << 6)
>> +#define HIBMC_MSCCTL_LOCALMEM_RESET_MASK	0x40
>> +
>> +#define RESET                0
>> +#define NORMAL               1
>> +
>> +#define HIBMC_CURRENT_GATE			0x000040
>> +#define HIBMC_CURR_GATE_DISPLAY(x)		((x) << 2)
>> +#define HIBMC_CURR_GATE_DISPLAY_MASK		0x4
>> +
>> +#define HIBMC_CURR_GATE_LOCALMEM(x)		((x) << 1)
>> +#define HIBMC_CURR_GATE_LOCALMEM_MASK		0x2
>> +
>> +#define HIBMC_MODE0_GATE			0x000044
>> +#define HIBMC_MODE1_GATE			0x000048
>> +#define HIBMC_POWER_MODE_CTRL			0x00004C
>> +
>> +#define HIBMC_PW_MODE_CTL_OSC_INPUT(x)		((x) << 3)
>> +#define HIBMC_PW_MODE_CTL_OSC_INPUT_MASK	0x8
>> +
>> +#define HIBMC_PW_MODE_CTL_MODE(x)		((x) << 0)
>> +#define HIBMC_PW_MODE_CTL_MODE_MASK		0x03
>> +#define HIBMC_PW_MODE_CTL_MODE_SHIFT		0
>> +
>> +
>> +#define HIBMC_PW_MODE_CTL_MODE_MODE0		0
>> +#define HIBMC_PW_MODE_CTL_MODE_MODE1		1
>> +#define HIBMC_PW_MODE_CTL_MODE_SLEEP		2
>> +
>> +#define HIBMC_PANEL_PLL_CTRL			0x00005C
>> +#define HIBMC_CRT_PLL_CTRL			0x000060
>> +
>> +#define HIBMC_PLL_CTRL_BYPASS(x)		((x) << 18)
>> +#define HIBMC_PLL_CTRL_BYPASS_MASK		0x40000
>> +
>> +#define HIBMC_PLL_CTRL_POWER(x)			((x) << 17)
>> +#define HIBMC_PLL_CTRL_POWER_MASK		0x20000
>> +
>> +#define HIBMC_PLL_CTRL_INPUT(x)			((x) << 16)
>> +#define HIBMC_PLL_CTRL_INPUT_MASK		0x10000
>> +
>> +#define OSC					0
>> +#define TESTCLK					1
>> +
>> +#define HIBMC_PLL_CTRL_POD(x)			((x) << 14)
>> +#define HIBMC_PLL_CTRL_POD_MASK			0xC000
>> +
>> +#define HIBMC_PLL_CTRL_OD(x)			((x) << 12)
>> +#define HIBMC_PLL_CTRL_OD_MASK			0x3000
>> +
>> +#define HIBMC_PLL_CTRL_N(x)			((x) << 8)
>> +#define HIBMC_PLL_CTRL_N_MASK			0xF00
>> +
>> +#define HIBMC_PLL_CTRL_M(x)			((x) << 0)
>> +#define HIBMC_PLL_CTRL_M_MASK			0xFF
>> +
>> +
>> +#define HIBMC_CRT_DISP_CTL			0x80200
>> +
>> +#define HIBMC_CRT_DISP_CTL_CRTSELECT(x)		((x) << 25)
>> +#define HIBMC_CRT_DISP_CTL_CRTSELECT_MASK	0x2000000
>> +
>> +#define CRTSELECT_VGA                0
>> +#define CRTSELECT_CRT                1
>> +
>> +#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE(x)	((x) << 14)
>> +#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK	0x4000
>> +
>> +#define PHASE_ACTIVE_HIGH      0
>> +#define PHASE_ACTIVE_LOW       1
>> +
>> +#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE(x)	((x) << 13)
>> +#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK	0x2000
>> +
>> +#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE(x)	((x) << 12)
>> +#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK	0x1000
>> +
>> +#define HIBMC_CRT_DISP_CTL_TIMING(x)		((x) << 8)
>> +#define HIBMC_CRT_DISP_CTL_TIMING_MASK		0x100
>> +
>> +
>> +#define HIBMC_CRT_DISP_CTL_PLANE(x)		((x) << 2)
>> +#define HIBMC_CRT_DISP_CTL_PLANE_MASK		4
>> +
>> +#define HIBMC_CRT_DISP_CTL_FORMAT(x)		((x) << 0)
>> +#define HIBMC_CRT_DISP_CTL_FORMAT_MASK		0x03
>> +
>> +
>> +
>> +#define HIBMC_CRT_FB_ADDRESS			0x080204
>> +
>> +#define HIBMC_CRT_FB_WIDTH			0x080208
>> +#define HIBMC_CRT_FB_WIDTH_WIDTH(x)		((x) << 16)
>> +#define HIBMC_CRT_FB_WIDTH_WIDTH_MASK		0x3FFF0000
>> +#define HIBMC_CRT_FB_WIDTH_OFFS(x)		((x) << 0)
>> +#define HIBMC_CRT_FB_WIDTH_OFFS_MASK		0x3FFF
>> +
>> +
>> +#define HIBMC_CRT_HORZ_TOTAL			0x08020C
>> +#define HIBMC_CRT_HORZ_TOTAL_TOTAL(x)		((x) << 16)
>> +#define HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK		0xFFF0000
>> +
>> +
>> +#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END(x)	((x) << 0)
>> +#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END_MASK	0xFFF
>> +
>> +#define HIBMC_CRT_HORZ_SYNC			0x080210
>> +#define HIBMC_CRT_HORZ_SYNC_WIDTH(x)		((x) << 16)
>> +#define HIBMC_CRT_HORZ_SYNC_WIDTH_MASK		0xFF0000
>> +
>> +#define HIBMC_CRT_HORZ_SYNC_START(x)		((x) << 0)
>> +#define HIBMC_CRT_HORZ_SYNC_START_MASK		0xFFF
>> +
>> +#define HIBMC_CRT_VERT_TOTAL			0x080214
>> +#define HIBMC_CRT_VERT_TOTAL_TOTAL(x)		((x) << 16)
>> +#define HIBMC_CRT_VERT_TOTAL_TOTAL_MASK		0x7FFF0000
>> +
>> +#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END(x)	((x) << 0)
>> +#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END_MASK	0x7FF
>> +
>> +#define HIBMC_CRT_VERT_SYNC			0x080218
>> +#define HIBMC_CRT_VERT_SYNC_HEIGHT(x)		((x) << 16)
>> +#define HIBMC_CRT_VERT_SYNC_HEIGHT_MASK		0x3F0000
>> +
>> +
>> +#define HIBMC_CRT_VERT_SYNC_START(x)		((x) << 0)
>> +#define HIBMC_CRT_VERT_SYNC_START_MASK		0x7FF
>> +
>> +/* Auto Centering */
>> +#define HIBMC_CRT_AUTO_CENTERING_TL		0x080280
>> +#define HIBMC_CRT_AUTO_CENTERING_TL_TOP(x)	((x) << 16)
>> +#define HIBMC_CRT_AUTO_CENTERING_TL_TOP_MSK	0x7FF0000
>> +
>> +#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT(x)	((x) << 0)
>> +#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MSK	0x7FF
>> +
>> +#define HIBMC_CRT_AUTO_CENTERING_BR		0x080284
>> +#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(x)	((x) << 16)
>> +#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK	0x7FF0000
>> +
>> +#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x)	((x) << 0)
>> +#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK	0x7FF
>> +
>> +/* register to control panel output */
>> +#define DISPLAY_CONTROL_HISILE			0x80288
>> +
>> +/* register and values for PLL control */
>> +#define CRT_PLL1_HS				0x802a8
>> +#define CRT_PLL1_HS_25MHZ			0x23d40f02
>> +#define CRT_PLL1_HS_40MHZ			0x23940801
>> +#define CRT_PLL1_HS_65MHZ			0x23940d01
>> +#define CRT_PLL1_HS_78MHZ			0x23540F82
>> +#define CRT_PLL1_HS_74MHZ			0x23941dc2
>> +#define CRT_PLL1_HS_80MHZ			0x23941001
>> +#define CRT_PLL1_HS_80MHZ_1152			0x23540fc2
>> +#define CRT_PLL1_HS_108MHZ			0x23b41b01
>> +#define CRT_PLL1_HS_162MHZ			0x23480681
>> +#define CRT_PLL1_HS_148MHZ			0x23541dc2
>> +#define CRT_PLL1_HS_193MHZ			0x234807c1
>> +
>> +#define CRT_PLL2_HS				0x802ac
>> +#define CRT_PLL2_HS_25MHZ			0x206B851E
>> +#define CRT_PLL2_HS_40MHZ			0x30000000
>> +#define CRT_PLL2_HS_65MHZ			0x40000000
>> +#define CRT_PLL2_HS_78MHZ			0x50E147AE
>> +#define CRT_PLL2_HS_74MHZ			0x602B6AE7
>> +#define CRT_PLL2_HS_80MHZ			0x70000000
>> +#define CRT_PLL2_HS_108MHZ			0x80000000
>> +#define CRT_PLL2_HS_162MHZ			0xA0000000
>> +#define CRT_PLL2_HS_148MHZ			0xB0CCCCCD
>> +#define CRT_PLL2_HS_193MHZ			0xC0872B02
>> +
>> +/* Global macros */
>> +#define RGB(r, g, b) \
>> +( \
>> +	(unsigned long)(((r) << 16) | ((g) << 8) | (b)) \
>> +)
>> +
>> +#define PADDING(align, data) (((data) + (align) - 1) & (~((align) - 1)))
>> +
>> +#define MB(x) ((x) << 20)
>> +
>> +#endif
>> --
>> 1.9.1
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>


-- 
Regards,
Rongrong


From luoyi.ly at gmail.com  Mon May 30 05:30:13 2016
From: luoyi.ly at gmail.com (luoyi.ly at gmail.com)
Date: Mon, 30 May 2016 20:30:13 +0800
Subject: [PATCH] ARM: dts: sun7i: Add dts file for Bananapi M1 Plus board
Message-ID: <20160530123013.11575-1-luoyi.ly@gmail.com>

From: luoyi <luoyi.ly at gmail.com>

Add support for the Bananapi M1 Plus A20 development board from sinovoip.com.cn .
This board features 1G RAM, 2 USB A receptacles, 1 micro USB receptacle for
OTG, 1 micro USB receptacle for power, HDMI, sata, Gbit ethernet, ir receiver,
3.5 mm jack for stero sound out, on board microphone, 40 gpio pins and sdio wifi.

Signed-off-by: Luo Yi <luoyi.ly at gmail.com>
---
 arch/arm/boot/dts/Makefile                       |   1 +
 arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts | 270 +++++++++++++++++++++++
 2 files changed, 271 insertions(+)
 create mode 100644 arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index e06a5ab..fde407f 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -685,6 +685,7 @@ dtb-$(CONFIG_MACH_SUN6I) += \
 	sun6i-a31s-yones-toptech-bs1078-v2.dtb
 dtb-$(CONFIG_MACH_SUN7I) += \
 	sun7i-a20-bananapi.dtb \
+	sun7i-a20-bananapi-m1-plus.dtb \
 	sun7i-a20-bananapro.dtb \
 	sun7i-a20-cubieboard2.dtb \
 	sun7i-a20-cubietruck.dtb \
diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
new file mode 100644
index 0000000..b62fc1d
--- /dev/null
+++ b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2016 Luo Yi <luoyi.ly at gmail.com>
+ * 
+ * Thanks to the original work by Hans de Goede <hdegoede at redhat.com>
+ *
+ * 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 "sun7i-a20.dtsi"
+#include "sunxi-common-regulators.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	model = "Banana Pi BPI-M1-Plus";
+	compatible = "sinovoip,bpi-m1-plus", "allwinner,sun7i-a20";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins_bananapi>;
+
+		red {
+			label = "bananapi:red:usr";
+			gpios = <&pio 7 25 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-on";
+		};
+
+		green {
+			label = "bananapi:green:usr";
+			gpios = <&pio 7 24 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+
+		};
+	};
+
+	reg_gmac_3v3: gmac-3v3 {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gmac_power_pin_bananapi>;
+		regulator-name = "gmac-3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <100000>;
+		enable-active-high;
+		gpio = <&pio 7 23 GPIO_ACTIVE_HIGH>;
+	};
+
+	reg_vmmc3: vmmc3 {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&vmmc3_pin_bananapi>;
+		regulator-name = "vmmc3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+		enable-active-high;
+		gpio = <&pio 7 22 GPIO_ACTIVE_HIGH>;
+	};
+
+};
+
+&ahci {
+	status = "okay";
+};
+
+&codec {
+	status = "okay";
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&gmac {
+	pinctrl-names = "default";
+	pinctrl-0 = <&gmac_pins_rgmii_a>;
+	phy = <&phy1>;
+	phy-mode = "rgmii";
+	phy-supply = <&reg_gmac_3v3>;
+	status = "okay";
+
+	phy1: ethernet-phy at 1 {
+		reg = <1>;
+	};
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins_a>;
+	status = "okay";
+
+	axp209: pmic at 34 {
+		compatible = "x-powers,axp209";
+		reg = <0x34>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		interrupt-controller;
+		#interrupt-cells = <1>;
+	};
+};
+
+&ir0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ir0_rx_pins_a>;
+	status = "okay";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bananapi>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */
+	cd-inverted;
+	status = "okay";
+};
+
+&mmc3 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc3_pins_a>;
+	vmmc-supply = <&reg_vmmc3>;
+	bus-width = <4>;
+	non-removable;
+	enable-sdio-wakeup;
+	status = "okay";
+
+	brcmf: bcrmf at 1 {
+		reg = <1>;
+		compatible = "brcm,bcm4329-fmac";
+		interrupt-parent = <&pio>;
+		interrupts = <7 15 IRQ_TYPE_LEVEL_LOW>; 
+		interrupt-names = "host-wake";
+	};
+
+};
+
+&mmc3_pins_a {
+    /* AP6210 requires pull-up */
+	allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+};
+
+&pio {
+	gmac_power_pin_bananapi: gmac_power_pin at 0 {
+		allwinner,pins = "PH23";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	led_pins_bananapi: led_pins at 0 {
+		allwinner,pins = "PH24", "PG2";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	mmc0_cd_pin_bananapi: mmc0_cd_pin at 0 {
+		allwinner,pins = "PH10";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+	};
+
+	usb1_vbus_pin_bananapi: usb1_vbus_pin at 0 {
+		allwinner,pins = "PH0";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	usb2_vbus_pin_bananapi: usb2_vbus_pin at 0 {
+		allwinner,pins = "PH1";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	vmmc3_pin_bananapi: vmmc3_pin at 0 {
+		allwinner,pins = "PH22";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&reg_usb1_vbus {
+	pinctrl-0 = <&usb1_vbus_pin_bananapi>;
+	gpio = <&pio 7 0 GPIO_ACTIVE_HIGH>; /* PH0 */
+	status = "okay";
+};
+
+&reg_usb2_vbus {
+	pinctrl-0 = <&usb2_vbus_pin_bananapi>;
+	gpio = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins_a>;
+	status = "okay";
+};
+
+&usbphy {
+	usb1_vbus-supply = <&reg_usb1_vbus>;
+	usb2_vbus-supply = <&reg_usb2_vbus>;
+	status = "okay";
+};
-- 
2.8.3



From tiffany.lin at mediatek.com  Mon May 30 05:29:16 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Mon, 30 May 2016 20:29:16 +0800
Subject: [PATCH v3 2/9] v4l: add Mediatek compressed video block format
In-Reply-To: <1464611363-14936-2-git-send-email-tiffany.lin@mediatek.com>
References: <1464611363-14936-1-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-2-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1464611363-14936-3-git-send-email-tiffany.lin@mediatek.com>

Add V4L2_PIX_FMT_MT21 format used on MT8173 driver.
It is compressed format and need MT8173 MDP driver to transfer to other
standard format.

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 include/uapi/linux/videodev2.h |    1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 8f95191..52feea6 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -625,6 +625,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_Y8I      v4l2_fourcc('Y', '8', 'I', ' ') /* Greyscale 8-bit L/R interleaved */
 #define V4L2_PIX_FMT_Y12I     v4l2_fourcc('Y', '1', '2', 'I') /* Greyscale 12-bit L/R interleaved */
 #define V4L2_PIX_FMT_Z16      v4l2_fourcc('Z', '1', '6', ' ') /* Depth data 16-bit */
+#define V4L2_PIX_FMT_MT21     v4l2_fourcc('M', 'T', '2', '1') /* Mediatek compressed block mode  */
 
 /* SDR formats - used only for Software Defined Radio devices */
 #define V4L2_SDR_FMT_CU8          v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Mon May 30 05:29:17 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Mon, 30 May 2016 20:29:17 +0800
Subject: [PATCH v3 3/9] DocBook/v4l: Add compressed video formats used on
 MT8173 codec driver
In-Reply-To: <1464611363-14936-3-git-send-email-tiffany.lin@mediatek.com>
References: <1464611363-14936-1-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-2-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-3-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1464611363-14936-4-git-send-email-tiffany.lin@mediatek.com>

Add V4L2_PIX_FMT_MT21 documentation

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 Documentation/DocBook/media/v4l/pixfmt.xml |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
index 5a08aee..d40e0ce 100644
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt.xml
@@ -1980,6 +1980,12 @@ array. Anything what's in between the UYVY lines is JPEG data and should be
 concatenated to form the JPEG stream. </para>
 </entry>
 	  </row>
+	  <row id="V4L2_PIX_FMT_MT21">
+	    <entry><constant>V4L2_PIX_FMT_MT21</constant></entry>
+	    <entry>'MT21'</entry>
+	    <entry>Compressed two-planar YVU420 format used by Mediatek MT8173
+	    codec driver.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Mon May 30 05:29:15 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Mon, 30 May 2016 20:29:15 +0800
Subject: [PATCH v3 1/9] VPU: mediatek: Add decode support
In-Reply-To: <1464611363-14936-1-git-send-email-tiffany.lin@mediatek.com>
References: <1464611363-14936-1-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1464611363-14936-2-git-send-email-tiffany.lin@mediatek.com>

From: Andrew-CT Chen <andrew-ct.chen at mediatek.com>

VPU driver add decode support

Signed-off-by: Andrew-CT Chen <andrew-ct.chen at mediatek.com>
Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 drivers/media/platform/mtk-vpu/mtk_vpu.c |   12 ++++++++++++
 drivers/media/platform/mtk-vpu/mtk_vpu.h |   27 +++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c
index b60d02c..ca23b1f 100644
--- a/drivers/media/platform/mtk-vpu/mtk_vpu.c
+++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c
@@ -134,6 +134,8 @@ struct vpu_wdt {
  *
  * @signaled:		the signal of vpu initialization completed
  * @fw_ver:		VPU firmware version
+ * @dec_capability:	decoder capability which is not used for now and
+ *			the value is reserved for future use
  * @enc_capability:	encoder capability which is not used for now and
  *			the value is reserved for future use
  * @wq:			wait queue for VPU initialization status
@@ -141,6 +143,7 @@ struct vpu_wdt {
 struct vpu_run {
 	u32 signaled;
 	char fw_ver[VPU_FW_VER_LEN];
+	unsigned int	dec_capability;
 	unsigned int	enc_capability;
 	wait_queue_head_t wq;
 };
@@ -415,6 +418,14 @@ int vpu_wdt_reg_handler(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(vpu_wdt_reg_handler);
 
+unsigned int vpu_get_vdec_hw_capa(struct platform_device *pdev)
+{
+	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
+
+	return vpu->run.dec_capability;
+}
+EXPORT_SYMBOL_GPL(vpu_get_vdec_hw_capa);
+
 unsigned int vpu_get_venc_hw_capa(struct platform_device *pdev)
 {
 	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
@@ -600,6 +611,7 @@ static void vpu_init_ipi_handler(void *data, unsigned int len, void *priv)
 
 	vpu->run.signaled = run->signaled;
 	strncpy(vpu->run.fw_ver, run->fw_ver, VPU_FW_VER_LEN);
+	vpu->run.dec_capability = run->dec_capability;
 	vpu->run.enc_capability = run->enc_capability;
 	wake_up_interruptible(&vpu->run.wq);
 }
diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.h b/drivers/media/platform/mtk-vpu/mtk_vpu.h
index 5ab37f0..f457479 100644
--- a/drivers/media/platform/mtk-vpu/mtk_vpu.h
+++ b/drivers/media/platform/mtk-vpu/mtk_vpu.h
@@ -37,6 +37,18 @@ typedef void (*ipi_handler_t) (void *data,
 			 command to VPU.
 			 For other IPI below, AP should send the request
 			 to VPU to trigger the interrupt.
+ * @IPI_VDEC_H264:	 The interrupt from vpu is to notify kernel to
+			 handle H264 vidoe decoder job, and vice versa.
+			 Decode output format is always MT21 no matter what
+			 the input format is.
+ * @IPI_VDEC_VP8:	 The interrupt from is to notify kernel to
+			 handle VP8 video decoder job, and vice versa.
+			 Decode output format is always MT21 no matter what
+			 the input format is.
+ * @IPI_VDEC_VP9:	 The interrupt from vpu is to notify kernel to
+			 handle VP9 video decoder job, and vice versa.
+			 Decode output format is always MT21 no matter what
+			 the input format is.
  * @IPI_VENC_H264:	 The interrupt from vpu is to notify kernel to
 			 handle H264 video encoder job, and vice versa.
  * @IPI_VENC_VP8:	 The interrupt fro vpu is to notify kernel to
@@ -46,6 +58,9 @@ typedef void (*ipi_handler_t) (void *data,
 
 enum ipi_id {
 	IPI_VPU_INIT = 0,
+	IPI_VDEC_H264,
+	IPI_VDEC_VP8,
+	IPI_VDEC_VP9,
 	IPI_VENC_H264,
 	IPI_VENC_VP8,
 	IPI_MAX,
@@ -55,10 +70,12 @@ enum ipi_id {
  * enum rst_id - reset id to register reset function for VPU watchdog timeout
  *
  * @VPU_RST_ENC: encoder reset id
+ * @VPU_RST_DEC: decoder reset id
  * @VPU_RST_MAX: maximum reset id
  */
 enum rst_id {
 	VPU_RST_ENC,
+	VPU_RST_DEC,
 	VPU_RST_MAX,
 };
 
@@ -125,6 +142,16 @@ struct platform_device *vpu_get_plat_device(struct platform_device *pdev);
 int vpu_wdt_reg_handler(struct platform_device *pdev,
 			void vpu_wdt_reset_func(void *),
 			void *priv, enum rst_id id);
+
+/**
+ * vpu_get_vdec_hw_capa - get video decoder hardware capability
+ *
+ * @pdev:	VPU platform device
+ *
+ * Return: video decoder hardware capability
+ **/
+unsigned int vpu_get_vdec_hw_capa(struct platform_device *pdev);
+
 /**
  * vpu_get_venc_hw_capa - get video encoder hardware capability
  *
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Mon May 30 05:29:23 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Mon, 30 May 2016 20:29:23 +0800
Subject: [PATCH v3 9/9] arm64: dts: mediatek: Add Video Decoder for MT8173
In-Reply-To: <1464611363-14936-9-git-send-email-tiffany.lin@mediatek.com>
References: <1464611363-14936-1-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-2-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-3-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-4-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-5-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-6-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-7-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-8-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-9-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1464611363-14936-10-git-send-email-tiffany.lin@mediatek.com>

Add video decoder node for MT8173

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi |   44 ++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index 348ce0e..4ac06d3 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -691,6 +691,50 @@
 			#clock-cells = <1>;
 		};
 
+		vcodec_dec: vcodec at 16000000 {
+			compatible = "mediatek,mt8173-vcodec-dec";
+			reg = <0 0x16000000 0 0x100>,	/* VDEC_SYS */
+			      <0 0x16020000 0 0x1000>,	/* VDEC_MISC */
+			      <0 0x16021000 0 0x800>,	/* VDEC_LD */
+			      <0 0x16021800 0 0x800>,	/* VDEC_TOP */
+			      <0 0x16022000 0 0x1000>,	/* VDEC_CM */
+			      <0 0x16023000 0 0x1000>,	/* VDEC_AD */
+			      <0 0x16024000 0 0x1000>,	/* VDEC_AV */
+			      <0 0x16025000 0 0x1000>,	/* VDEC_PP */
+			      <0 0x16026800 0 0x800>,	/* VDEC_HWD */
+			      <0 0x16027000 0 0x800>,	/* VDEC_HWQ */
+			      <0 0x16027800 0 0x800>,	/* VDEC_HWB */
+			      <0 0x16028400 0 0x400>;	/* VDEC_HWG */
+			interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_LOW>;
+			mediatek,larb = <&larb1>;
+			iommus = <&iommu M4U_PORT_HW_VDEC_MC_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_PP_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_AVC_MV_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_PRED_RD_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_PRED_WR_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_UFO_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_VLD_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_VLD2_EXT>;
+			mediatek,vpu = <&vpu>;
+			power-domains = <&scpsys MT8173_POWER_DOMAIN_VDEC>;
+			clocks = <&apmixedsys CLK_APMIXED_VCODECPLL>,
+				 <&topckgen CLK_TOP_UNIVPLL_D2>,
+				 <&topckgen CLK_TOP_CCI400_SEL>,
+				 <&topckgen CLK_TOP_VDEC_SEL>,
+				 <&topckgen CLK_TOP_VCODECPLL>,
+				 <&apmixedsys CLK_APMIXED_VENCPLL>,
+				 <&topckgen CLK_TOP_VENC_LT_SEL>,
+				 <&topckgen CLK_TOP_VCODECPLL_370P5>;
+			clock-names = "vcodecpll",
+				      "univpll_d2",
+				      "clk_cci400_sel",
+				      "vdec_sel",
+				      "vdecpll",
+				      "vencpll",
+				      "venc_lt_sel",
+				      "vdec_bus_clk_src";
+		};
+
 		larb1: larb at 16010000 {
 			compatible = "mediatek,mt8173-smi-larb";
 			reg = <0 0x16010000 0 0x1000>;
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Mon May 30 05:29:22 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Mon, 30 May 2016 20:29:22 +0800
Subject: [PATCH v3 8/9] vcodec: mediatek: Add Mediatek VP9 Video Decoder Driver
In-Reply-To: <1464611363-14936-8-git-send-email-tiffany.lin@mediatek.com>
References: <1464611363-14936-1-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-2-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-3-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-4-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-5-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-6-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-7-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-8-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1464611363-14936-9-git-send-email-tiffany.lin@mediatek.com>

Add vp9 decoder driver for MT8173

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 drivers/media/platform/mtk-vcodec/Makefile         |    1 +
 .../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c   |  967 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/vdec_drv_if.c    |    3 +
 3 files changed, 971 insertions(+)
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c

diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
index 7743c81..852d969 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
 
 mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
 		vdec/vdec_vp8_if.o \
+		vdec/vdec_vp9_if.o \
 		mtk_vcodec_dec_drv.o \
 		vdec_drv_if.o \
 		vdec_vpu_if.o \
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
new file mode 100644
index 0000000..650b93a
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
@@ -0,0 +1,967 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Daniel Hsiao <daniel.hsiao at mediatek.com>
+ *	Kai-Sean Yang <kai-sean.yang at mediatek.com>
+ *	Tiffany Lin <tiffany.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+
+#include "../mtk_vcodec_intr.h"
+#include "../vdec_drv_base.h"
+#include "../vdec_vpu_if.h"
+
+#define VP9_SUPER_FRAME_BS_SZ 64
+#define MAX_VP9_DPB_SIZE	9
+
+#define REFS_PER_FRAME 3
+#define MAX_NUM_REF_FRAMES 8
+#define VP9_MAX_FRM_BUF_NUM 9
+#define VP9_MAX_FRM_BUF_NODE_NUM (VP9_MAX_FRM_BUF_NUM * 2)
+
+/**
+ * struct vp9_dram_buf - contains buffer info for vpu
+ * @va : cpu address
+ * @pa : iova address
+ * @sz : buffer size
+ * @padding : for 64 bytes alignment
+ */
+struct vp9_dram_buf {
+	unsigned long va;
+	unsigned long pa;
+	unsigned int sz;
+	unsigned int padding;
+};
+
+/**
+ * struct vp9_fb_info - contains frame buffer info
+ * @fb : frmae buffer
+ * @reserved : reserved field used by vpu
+ */
+struct vp9_fb_info {
+	struct vdec_fb *fb;
+	unsigned int reserved[32];
+};
+
+/**
+ * struct vp9_ref_cnt_buf - contains reference buffer information
+ * @buf : referenced frame buffer
+ * @ref_cnt : referenced frame buffer's reference count.
+ *	When reference count=0, remove it from reference list
+ */
+struct vp9_ref_cnt_buf {
+	struct vp9_fb_info buf;
+	unsigned int ref_cnt;
+};
+
+/**
+ * struct vp9_fb_info - contains current frame's reference buffer information
+ * @buf : reference buffer
+ * @idx : reference buffer index to frm_bufs
+ * @reserved : reserved field used by vpu
+ */
+struct vp9_ref_buf {
+	struct vp9_fb_info *buf;
+	unsigned int idx;
+	unsigned int reserved[6];
+};
+
+/**
+ * struct vp9_fb_info - contains frame buffer info
+ * @fb : super frame reference frame buffer
+ * @used : this reference frame info entry is used
+ * @padding : for 64 bytes size align
+ */
+struct vp9_sf_ref_fb {
+	struct vdec_fb fb;
+	int used;
+	int padding;
+};
+
+/*
+ * struct vdec_vp9_vsi - shared buffer between host and VPU firmware
+ *	AP-W/R : AP is writer/reader on this item
+ *	VPU-W/R: VPU is write/reader on this item
+ * @sf_bs_buf : super frame backup buffer (AP-W, VPU-R)
+ * @sf_ref_fb : record supoer frame reference buffer information
+ *	(AP-R/W, VPU-R/W)
+ * @sf_next_ref_fb_idx : next available super frame (AP-W, VPU-R)
+ * @sf_frm_cnt : super frame count, filled by vpu (AP-R, VPU-W)
+ * @sf_frm_offset : super frame offset, filled by vpu (AP-R, VPU-W)
+ * @sf_frm_sz : super frame size, filled by vpu (AP-R, VPU-W)
+ * @sf_frm_idx : current super frame (AP-R, VPU-W)
+ * @sf_init : inform super frame info already parsed by vpu (AP-R, VPU-W)
+ * @fb : capture buffer (AP-W, VPU-R)
+ * @bs : bs buffer (AP-W, VPU-R)
+ * @cur_fb : current show capture buffer (AP-R/W, VPU-R/W)
+ * @pic_w : picture width (AP-R, VPU-W)
+ * @pic_h : picture height (AP-R, VPU-W)
+ * @buf_w : codec width (AP-R, VPU-W)
+ * @buf_h : coded height (AP-R, VPU-W)
+ * @buf_sz_y_bs : ufo compressed y plane size (AP-R, VPU-W)
+ * @buf_sz_c_bs : ufo compressed cbcr plane size (AP-R, VPU-W)
+ * @buf_len_sz_y : size used to store y plane ufo info (AP-R, VPU-W)
+ * @buf_len_sz_c : size used to store cbcr plane ufo info (AP-R, VPU-W)
+
+ * @profile : profile sparsed from vpu (AP-R, VPU-W)
+ * @show_frame : display this frame or not (AP-R, VPU-W)
+ * @show_existing_frame : inform this frame is show existing frame
+ *	(AP-R, VPU-W)
+ * @frm_to_show_idx : index to show frame (AP-R, VPU-W)
+
+ * @refresh_frm_flags : indicate when frame need to refine reference count
+ *	(AP-R, VPU-W)
+ * @resolution_changed : resolution change in this frame (AP-R, VPU-W)
+
+ * @frm_bufs : maintain reference buffer info (AP-R/W, VPU-R/W)
+ * @ref_frm_map : maintain reference buffer map info (AP-R/W, VPU-R/W)
+ * @new_fb_idx : index to frm_bufs array (AP-R, VPU-W)
+ * @frm_num : decoded frame number, include sub-frame count (AP-R, VPU-W)
+ * @mv_buf : motion vector working buffer (AP-W, VPU-R)
+ * @frm_refs : maintain three reference buffer info (AP-R/W, VPU-R/W)
+ */
+struct vdec_vp9_vsi {
+	unsigned char sf_bs_buf[VP9_SUPER_FRAME_BS_SZ];
+	struct vp9_sf_ref_fb sf_ref_fb[VP9_MAX_FRM_BUF_NUM-1];
+	int sf_next_ref_fb_idx;
+	unsigned int sf_frm_cnt;
+	unsigned int sf_frm_offset[VP9_MAX_FRM_BUF_NUM-1];
+	unsigned int sf_frm_sz[VP9_MAX_FRM_BUF_NUM-1];
+	unsigned int sf_frm_idx;
+	unsigned int sf_init;
+	struct vdec_fb fb;
+	struct mtk_vcodec_mem bs;
+	struct vdec_fb cur_fb;
+	unsigned int pic_w;
+	unsigned int pic_h;
+	unsigned int buf_w;
+	unsigned int buf_h;
+	unsigned int buf_sz_y_bs;
+	unsigned int buf_sz_c_bs;
+	unsigned int buf_len_sz_y;
+	unsigned int buf_len_sz_c;
+	unsigned int profile;
+	unsigned int show_frame;
+	unsigned int show_existing_frame;
+	unsigned int frm_to_show_idx;
+	unsigned int refresh_frm_flags;
+	unsigned int resolution_changed;
+
+	struct vp9_ref_cnt_buf frm_bufs[VP9_MAX_FRM_BUF_NUM];
+	int ref_frm_map[MAX_NUM_REF_FRAMES];
+	unsigned int new_fb_idx;
+	unsigned int frm_num;
+	struct vp9_dram_buf mv_buf;
+
+	struct vp9_ref_buf frm_refs[REFS_PER_FRAME];
+};
+
+/*
+ * struct vdec_vp9_inst - vp9 decode instance
+ * @mv_buf : working buffer for mv
+ * @dec_fb : vdec_fb node to link fb to different fb_xxx_list
+ * @available_fb_node_list : current available vdec_fb node
+ * @fb_use_list : current used or referenced vdec_fb
+ * @fb_free_list : current availabe to free vdec_fb
+ * @fb_disp_list : current availabe to display vdec_fb
+ * @cur_fb : current frame buffer
+ * @ctx : current decode context
+ * @vpu : vpu instance information
+ * @vsi : shared buffer between host and VPU firmware
+ * @total_frm_cnt : total frame count, it do not include sub-frames in super
+ *	    frame
+ * @mem : instance memory information
+ */
+struct vdec_vp9_inst {
+	struct mtk_vcodec_mem mv_buf;
+
+	struct vdec_fb_node dec_fb[VP9_MAX_FRM_BUF_NODE_NUM];
+	struct list_head available_fb_node_list;
+	struct list_head fb_use_list;
+	struct list_head fb_free_list;
+	struct list_head fb_disp_list;
+	struct vdec_fb *cur_fb;
+	struct mtk_vcodec_ctx *ctx;
+	struct vdec_vpu_inst vpu;
+	struct vdec_vp9_vsi *vsi;
+	unsigned int total_frm_cnt;
+	struct mtk_vcodec_mem mem;
+};
+
+static bool vp9_is_sf_ref_fb(struct vdec_vp9_inst *inst, struct vdec_fb *fb)
+{
+	int i;
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+
+	for (i = 0; i < ARRAY_SIZE(vsi->sf_ref_fb); i++) {
+		if (fb == &vsi->sf_ref_fb[i].fb)
+			return true;
+	}
+	return false;
+}
+
+static struct vdec_fb *vp9_rm_from_fb_use_list(struct vdec_vp9_inst
+					*inst, void *addr)
+{
+	struct vdec_fb *fb = NULL;
+	struct vdec_fb_node *node;
+
+	list_for_each_entry(node, &inst->fb_use_list, list) {
+		fb = (struct vdec_fb *)node->fb;
+		if (fb->base_y.va == addr) {
+			list_move_tail(&node->list,
+				       &inst->available_fb_node_list);
+			break;
+		}
+	}
+	return fb;
+}
+
+static void vp9_add_to_fb_free_list(struct vdec_vp9_inst *inst,
+			     struct vdec_fb *fb)
+{
+	struct vdec_fb_node *node;
+
+	if (fb) {
+		node = list_first_entry_or_null(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+
+		if (node) {
+			node->fb = fb;
+			list_move_tail(&node->list, &inst->fb_free_list);
+		}
+	} else {
+		mtk_vcodec_debug(inst, "No free fb node");
+	}
+}
+
+static void vp9_free_sf_ref_fb(struct vdec_fb *fb)
+{
+	struct vp9_sf_ref_fb *sf_ref_fb =
+		container_of(fb, struct vp9_sf_ref_fb, fb);
+
+	sf_ref_fb->used = 0;
+}
+
+static void vp9_ref_cnt_fb(struct vdec_vp9_inst *inst, int *idx,
+			   int new_idx)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	int ref_idx = *idx;
+
+	if (ref_idx >= 0 && vsi->frm_bufs[ref_idx].ref_cnt > 0) {
+		vsi->frm_bufs[ref_idx].ref_cnt--;
+
+		if (vsi->frm_bufs[ref_idx].ref_cnt == 0) {
+			if (!vp9_is_sf_ref_fb(inst,
+					      vsi->frm_bufs[ref_idx].buf.fb)) {
+				struct vdec_fb *fb;
+
+				fb = vp9_rm_from_fb_use_list(inst,
+				     vsi->frm_bufs[ref_idx].buf.fb->base_y.va);
+				vp9_add_to_fb_free_list(inst, fb);
+			} else
+				vp9_free_sf_ref_fb(
+					vsi->frm_bufs[ref_idx].buf.fb);
+		}
+	}
+
+	*idx = new_idx;
+	vsi->frm_bufs[new_idx].ref_cnt++;
+}
+
+static void vp9_free_all_sf_ref_fb(struct vdec_vp9_inst *inst)
+{
+	int i;
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+
+	for (i = 0; i < ARRAY_SIZE(vsi->sf_ref_fb); i++) {
+		if (vsi->sf_ref_fb[i].fb.base_y.va) {
+			mtk_vcodec_mem_free(inst->ctx,
+				&vsi->sf_ref_fb[i].fb.base_y);
+			mtk_vcodec_mem_free(inst->ctx,
+				&vsi->sf_ref_fb[i].fb.base_c);
+			vsi->sf_ref_fb[i].used = 0;
+		}
+	}
+}
+
+/* For each sub-frame except the last one, the driver will dynamically
+ * allocate reference buffer by calling vp9_get_sf_ref_fb()
+ * The last sub-frame will use the original fb provided by the
+ * vp9_dec_decode() interface
+ */
+static int vp9_get_sf_ref_fb(struct vdec_vp9_inst *inst)
+{
+	int idx;
+	struct mtk_vcodec_mem *mem_basy_y;
+	struct mtk_vcodec_mem *mem_basy_c;
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+
+	for (idx = 0;
+		idx < ARRAY_SIZE(vsi->sf_ref_fb);
+		idx++) {
+		if (vsi->sf_ref_fb[idx].fb.base_y.va &&
+		    vsi->sf_ref_fb[idx].used == 0) {
+			return idx;
+		}
+	}
+
+	for (idx = 0;
+		idx < ARRAY_SIZE(vsi->sf_ref_fb);
+		idx++) {
+		if (vsi->sf_ref_fb[idx].fb.base_y.va == NULL)
+			break;
+	}
+
+	if (idx == ARRAY_SIZE(vsi->sf_ref_fb)) {
+		mtk_vcodec_err(inst, "List Full");
+		return -1;
+	}
+
+	mem_basy_y = &vsi->sf_ref_fb[idx].fb.base_y;
+	mem_basy_y->size = vsi->buf_sz_y_bs +
+		vsi->buf_len_sz_y;
+
+	if (mtk_vcodec_mem_alloc(inst->ctx, mem_basy_y)) {
+		mtk_vcodec_err(inst, "Cannot allocate sf_ref_buf y_buf");
+		return -1;
+	}
+
+	mem_basy_c = &vsi->sf_ref_fb[idx].fb.base_c;
+	mem_basy_c->size = vsi->buf_sz_c_bs +
+		vsi->buf_len_sz_c;
+
+	if (mtk_vcodec_mem_alloc(inst->ctx, mem_basy_c)) {
+		mtk_vcodec_err(inst, "Cannot allocate sf_ref_fb c_buf");
+		return -1;
+	}
+	vsi->sf_ref_fb[idx].used = 0;
+
+	return idx;
+}
+
+static bool vp9_alloc_work_buf(struct vdec_vp9_inst *inst)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	int result;
+	struct mtk_vcodec_mem *mem;
+
+	unsigned int max_pic_w;
+	unsigned int max_pic_h;
+
+
+	if (!(inst->ctx->dev->dec_capability &
+		VCODEC_CAPABILITY_4K_DISABLED)) {
+		max_pic_w = VCODEC_DEC_4K_CODED_WIDTH;
+		max_pic_h = VCODEC_DEC_4K_CODED_HEIGHT;
+	} else {
+		max_pic_w = MTK_VDEC_MAX_W;
+		max_pic_h = MTK_VDEC_MAX_H;
+	}
+
+	if ((vsi->pic_w > max_pic_w) ||
+		(vsi->pic_h > max_pic_h)) {
+		mtk_vcodec_err(inst, "Invalid w/h %d/%d",
+				vsi->pic_w, vsi->pic_h);
+		return false;
+	}
+
+	mtk_vcodec_debug(inst, "BUF CHG(%d): w/h/sb_w/sb_h=%d/%d/%d/%d",
+			vsi->resolution_changed,
+			vsi->pic_w,
+			vsi->pic_h,
+			vsi->buf_w,
+			vsi->buf_h);
+
+	mem = &inst->mv_buf;
+
+	if (mem->va)
+		mtk_vcodec_mem_free(inst->ctx, mem);
+
+	mem->size = ((vsi->buf_w / 64) *
+		    (vsi->buf_h / 64) + 2) * 36 * 16;
+
+	result = mtk_vcodec_mem_alloc(inst->ctx, mem);
+	if (result) {
+		mem->size = 0;
+		mtk_vcodec_err(inst, "Cannot allocate mv_buf");
+		return false;
+	}
+	/* Set the va again */
+	vsi->mv_buf.va = (unsigned long)mem->va;
+	vsi->mv_buf.pa = (unsigned long)mem->dma_addr;
+	vsi->mv_buf.sz = (unsigned int)mem->size;
+
+	vp9_free_all_sf_ref_fb(inst);
+	vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
+
+	return true;
+}
+
+static bool vp9_add_to_fb_disp_list(struct vdec_vp9_inst *inst,
+			     struct vdec_fb *fb)
+{
+	struct vdec_fb_node *node;
+
+	if (!fb) {
+		mtk_vcodec_err(inst, "fb == NULL");
+		return false;
+	}
+
+	node = list_first_entry_or_null(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		node->fb = fb;
+		list_move_tail(&node->list, &inst->fb_disp_list);
+	} else {
+		mtk_vcodec_err(inst, "No available fb node");
+		return false;
+	}
+
+	return true;
+}
+
+/* If any buffer updating is signaled it should be done here. */
+static void vp9_swap_frm_bufs(struct vdec_vp9_inst *inst)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	struct vp9_fb_info *frm_to_show;
+	int ref_index = 0, mask;
+
+	for (mask = vsi->refresh_frm_flags; mask; mask >>= 1) {
+		if (mask & 1)
+			vp9_ref_cnt_fb(inst, &vsi->ref_frm_map[ref_index],
+				       vsi->new_fb_idx);
+		++ref_index;
+	}
+
+	frm_to_show = &vsi->frm_bufs[vsi->new_fb_idx].buf;
+	vsi->frm_bufs[vsi->new_fb_idx].ref_cnt--;
+
+	if (frm_to_show->fb != inst->cur_fb) {
+		/* This frame is show exist frame and no decode output
+		 * copy frame data from frm_to_show to current CAPTURE
+		 * buffer
+		 */
+		if ((frm_to_show->fb != NULL) &&
+			(inst->cur_fb->base_y.size >=
+			frm_to_show->fb->base_y.size)) {
+			memcpy((void *)inst->cur_fb->base_y.va,
+				(void *)frm_to_show->fb->base_y.va,
+				vsi->buf_w *
+				vsi->buf_h);
+			memcpy((void *)inst->cur_fb->base_c.va,
+				(void *)frm_to_show->fb->base_c.va,
+				vsi->buf_w *
+				vsi->buf_h / 2);
+		} else {
+			/* After resolution change case, current CAPTURE buffer
+			 * may have less buffer size than frm_to_show buffer
+			 * size
+			 */
+			if (frm_to_show->fb != NULL)
+				mtk_vcodec_err(inst,
+					"inst->cur_fb->base_y.size=%lx, frm_to_show->fb.base_y.size=%lx",
+					inst->cur_fb->base_y.size,
+					frm_to_show->fb->base_y.size);
+		}
+		if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) {
+			if (vsi->show_frame)
+				vp9_add_to_fb_disp_list(inst, inst->cur_fb);
+		}
+	} else {
+		if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) {
+			if (vsi->show_frame)
+				vp9_add_to_fb_disp_list(inst, frm_to_show->fb);
+		}
+	}
+
+	/* when ref_cnt ==0, move this fb to fb_free_list. v4l2 driver will
+	 * clean fb_free_list
+	 */
+	if (vsi->frm_bufs[vsi->new_fb_idx].ref_cnt == 0) {
+		if (!vp9_is_sf_ref_fb(
+			inst, vsi->frm_bufs[vsi->new_fb_idx].buf.fb)) {
+			struct vdec_fb *fb;
+
+			fb = vp9_rm_from_fb_use_list(inst,
+			vsi->frm_bufs[vsi->new_fb_idx].buf.fb->base_y.va);
+
+			vp9_add_to_fb_free_list(inst, fb);
+		} else {
+			vp9_free_sf_ref_fb(
+				vsi->frm_bufs[vsi->new_fb_idx].buf.fb);
+		}
+	}
+
+	/* if this super frame and it is not last sub-frame, get next fb for
+	 * sub-frame decode
+	 */
+	if (vsi->sf_frm_cnt > 0 && vsi->sf_frm_idx != vsi->sf_frm_cnt - 1)
+		vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
+}
+
+static bool vp9_wait_dec_end(struct vdec_vp9_inst *inst)
+{
+	struct mtk_vcodec_ctx *ctx = inst->ctx;
+
+	mtk_vcodec_wait_for_done_ctx(inst->ctx,
+			MTK_INST_IRQ_RECEIVED,
+			WAIT_INTR_TIMEOUT_MS);
+
+	if (ctx->irq_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
+		return true;
+	else
+		return false;
+}
+
+static struct vdec_vp9_inst *vp9_alloc_inst(struct mtk_vcodec_ctx *ctx)
+{
+	int result;
+	struct mtk_vcodec_mem mem;
+	struct vdec_vp9_inst *inst;
+
+	memset(&mem, 0, sizeof(mem));
+	mem.size = sizeof(struct vdec_vp9_inst);
+	result = mtk_vcodec_mem_alloc(ctx, &mem);
+	if (result)
+		return NULL;
+
+	inst = mem.va;
+	inst->mem = mem;
+
+	return inst;
+}
+
+static void vp9_free_inst(struct vdec_vp9_inst *inst)
+{
+	struct mtk_vcodec_mem mem;
+
+	mem = inst->mem;
+	if (mem.va)
+		mtk_vcodec_mem_free(inst->ctx, &mem);
+}
+
+static bool vp9_decode_end_proc(struct vdec_vp9_inst *inst)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	bool ret = false;
+
+	if (!vsi->show_existing_frame) {
+		ret = vp9_wait_dec_end(inst);
+		if (!ret) {
+			mtk_vcodec_err(inst, "Decode failed, Decode Timeout @[%d]",
+				vsi->frm_num);
+			return false;
+		}
+
+		if (vpu_dec_end(&inst->vpu)) {
+			mtk_vcodec_err(inst, "vp9_dec_vpu_end failed");
+			return false;
+		}
+		mtk_vcodec_debug(inst, "Decode Ok @%d (%d/%d)", vsi->frm_num,
+				vsi->pic_w, vsi->pic_h);
+	} else {
+		mtk_vcodec_debug(inst, "Decode Ok @%d (show_existing_frame)",
+				vsi->frm_num);
+	}
+
+	vp9_swap_frm_bufs(inst);
+	vsi->frm_num++;
+	return true;
+}
+
+static bool vp9_is_last_sub_frm(struct vdec_vp9_inst *inst)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+
+	if (vsi->sf_frm_cnt <= 0 || vsi->sf_frm_idx == vsi->sf_frm_cnt)
+		return true;
+
+	return false;
+}
+
+static struct vdec_fb *vp9_rm_from_fb_disp_list(struct vdec_vp9_inst *inst)
+{
+	struct vdec_fb_node *node;
+	struct vdec_fb *fb = NULL;
+
+	node = list_first_entry_or_null(&inst->fb_disp_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		fb = (struct vdec_fb *)node->fb;
+		fb->status |= FB_ST_DISPLAY;
+		list_move_tail(&node->list, &inst->available_fb_node_list);
+		mtk_vcodec_debug(inst, "[FB] get disp fb %p st=%d",
+				 node->fb, fb->status);
+	} else
+		mtk_vcodec_debug(inst, "[FB] there is no disp fb");
+
+	return fb;
+}
+
+static bool vp9_add_to_fb_use_list(struct vdec_vp9_inst *inst,
+			    struct vdec_fb *fb)
+{
+	struct vdec_fb_node *node;
+
+	if (!fb) {
+		mtk_vcodec_debug(inst, "fb == NULL");
+		return false;
+	}
+
+	node = list_first_entry_or_null(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		node->fb = fb;
+		list_move_tail(&node->list, &inst->fb_use_list);
+	} else {
+		mtk_vcodec_err(inst, "No free fb node");
+		return false;
+	}
+	return true;
+}
+
+static void vp9_reset(struct vdec_vp9_inst *inst)
+{
+	struct vdec_fb_node *node, *tmp;
+
+	list_for_each_entry_safe(node, tmp, &inst->fb_use_list, list)
+		list_move_tail(&node->list, &inst->fb_free_list);
+
+	vp9_free_all_sf_ref_fb(inst);
+	inst->vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
+
+	if (vpu_dec_reset(&inst->vpu))
+		mtk_vcodec_err(inst, "vp9_dec_vpu_reset failed");
+
+	/* Set the va again, since vpu_dec_reset will clear mv_buf in vpu */
+	inst->vsi->mv_buf.va = (unsigned long)inst->mv_buf.va;
+	inst->vsi->mv_buf.pa = (unsigned long)inst->mv_buf.dma_addr;
+	inst->vsi->mv_buf.sz = (unsigned long)inst->mv_buf.size;
+}
+
+static void init_all_fb_lists(struct vdec_vp9_inst *inst)
+{
+	int i;
+
+	INIT_LIST_HEAD(&inst->available_fb_node_list);
+	INIT_LIST_HEAD(&inst->fb_use_list);
+	INIT_LIST_HEAD(&inst->fb_free_list);
+	INIT_LIST_HEAD(&inst->fb_disp_list);
+
+	for (i = 0; i < ARRAY_SIZE(inst->dec_fb); i++) {
+		INIT_LIST_HEAD(&inst->dec_fb[i].list);
+		inst->dec_fb[i].fb = NULL;
+		list_add_tail(&inst->dec_fb[i].list,
+			      &inst->available_fb_node_list);
+	}
+}
+
+static void get_pic_info(struct vdec_vp9_inst *inst, struct vdec_pic_info *pic)
+{
+	pic->y_bs_sz = inst->vsi->buf_sz_y_bs;
+	pic->c_bs_sz = inst->vsi->buf_sz_c_bs;
+	pic->y_len_sz = inst->vsi->buf_len_sz_y;
+	pic->c_len_sz = inst->vsi->buf_len_sz_c;
+
+	pic->pic_w = inst->vsi->pic_w;
+	pic->pic_h = inst->vsi->pic_h;
+	pic->buf_w = inst->vsi->buf_w;
+	pic->buf_h = inst->vsi->buf_h;
+
+	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
+		 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
+	mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+		 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_disp_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb)
+{
+
+	*out_fb = vp9_rm_from_fb_disp_list(inst);
+	if (*out_fb)
+		(*out_fb)->status |= FB_ST_DISPLAY;
+}
+
+static void get_free_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb)
+{
+	struct vdec_fb_node *node;
+	struct vdec_fb *fb = NULL;
+
+	node = list_first_entry_or_null(&inst->fb_free_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		list_move_tail(&node->list, &inst->available_fb_node_list);
+		fb = (struct vdec_fb *)node->fb;
+		fb->status |= FB_ST_FREE;
+		mtk_vcodec_debug(inst, "[FB] get free fb %p st=%d",
+				 node->fb, fb->status);
+	} else {
+		mtk_vcodec_debug(inst, "[FB] there is no free fb");
+	}
+
+	*out_fb = fb;
+}
+
+static void vdec_vp9_deinit(unsigned long h_vdec)
+{
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+	struct mtk_vcodec_mem *mem;
+	int ret = 0;
+
+	ret = vpu_dec_deinit(&inst->vpu);
+	if (ret)
+		mtk_vcodec_err(inst, "vpu_dec_deinit failed");
+
+	mem = &inst->mv_buf;
+	if (mem->va)
+		mtk_vcodec_mem_free(inst->ctx, mem);
+
+	vp9_free_all_sf_ref_fb(inst);
+	vp9_free_inst(inst);
+}
+
+static int vdec_vp9_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_vp9_inst *inst;
+
+	inst = vp9_alloc_inst(ctx);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->total_frm_cnt = 0;
+	inst->ctx = ctx;
+
+	inst->vpu.id = IPI_VDEC_VP9;
+	inst->vpu.dev = ctx->dev->vpu_plat_dev;
+	inst->vpu.ctx = ctx;
+	inst->vpu.handler = vpu_dec_ipi_handler;
+
+	if (vpu_dec_init(&inst->vpu)) {
+		mtk_vcodec_err(inst, "vp9_dec_vpu_init failed");
+		goto err_deinit_inst;
+	}
+
+	inst->vsi = (struct vdec_vp9_vsi *)inst->vpu.vsi;
+	init_all_fb_lists(inst);
+
+	(*h_vdec) = (unsigned long)inst;
+	return 0;
+
+err_deinit_inst:
+	vp9_free_inst(inst);
+
+	return -EINVAL;
+}
+
+static int vdec_vp9_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+		   struct vdec_fb *fb, bool *res_chg)
+{
+	int ret = 0;
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	u32 data[3];
+	int i;
+
+	*res_chg = false;
+
+	if ((bs == NULL) && (fb == NULL)) {
+		mtk_vcodec_debug(inst, "[EOS]");
+		vp9_reset(inst);
+		return ret;
+	}
+
+	if (bs == NULL) {
+		mtk_vcodec_err(inst, "bs == NULL");
+		return -EINVAL;
+	}
+
+	mtk_vcodec_debug(inst, "Input BS Size = %ld", bs->size);
+
+	while (1) {
+		struct vdec_fb *cur_fb = NULL;
+
+		data[0] = *((unsigned int *)bs->va);
+		data[1] = *((unsigned int *)(bs->va + 4));
+		data[2] = *((unsigned int *)(bs->va + 8));
+
+		vsi->bs = *bs;
+
+		if (fb)
+			vsi->fb = *fb;
+
+		if (!vsi->sf_init) {
+			unsigned int sf_bs_sz;
+			unsigned int sf_bs_off;
+			unsigned char *sf_bs_src;
+			unsigned char *sf_bs_dst;
+
+			sf_bs_sz = bs->size > VP9_SUPER_FRAME_BS_SZ ?
+					VP9_SUPER_FRAME_BS_SZ : bs->size;
+			sf_bs_off = VP9_SUPER_FRAME_BS_SZ - sf_bs_sz;
+			sf_bs_src = bs->va + bs->size - sf_bs_sz;
+			sf_bs_dst = vsi->sf_bs_buf + sf_bs_off;
+			memcpy(sf_bs_dst, sf_bs_src, sf_bs_sz);
+		} else {
+			if ((vsi->sf_frm_cnt > 0) &&
+				(vsi->sf_frm_idx < vsi->sf_frm_cnt)) {
+				unsigned int idx = vsi->sf_frm_idx;
+
+				memcpy((void *)bs->va,
+					(void *)(bs->va +
+					vsi->sf_frm_offset[idx]),
+					vsi->sf_frm_sz[idx]);
+			}
+		}
+		ret = vpu_dec_start(&inst->vpu, data, 3);
+		if (ret) {
+			mtk_vcodec_err(inst, "vpu_dec_start failed");
+			goto DECODE_ERROR;
+		}
+
+		if (vsi->resolution_changed) {
+			if (!vp9_alloc_work_buf(inst)) {
+				ret = -EINVAL;
+				goto DECODE_ERROR;
+			}
+		}
+
+		if (vsi->sf_frm_cnt > 0) {
+			cur_fb = &vsi->sf_ref_fb[vsi->sf_next_ref_fb_idx].fb;
+
+			if (vsi->sf_frm_idx < vsi->sf_frm_cnt)
+				inst->cur_fb = cur_fb;
+			else
+				inst->cur_fb = fb;
+		} else {
+			inst->cur_fb = fb;
+		}
+
+		vsi->frm_bufs[vsi->new_fb_idx].buf.fb = inst->cur_fb;
+		if (!vp9_is_sf_ref_fb(inst, inst->cur_fb))
+			vp9_add_to_fb_use_list(inst, inst->cur_fb);
+
+		mtk_vcodec_debug(inst, "[#pic %d]", vsi->frm_num);
+
+		if (vsi->show_existing_frame)
+			mtk_vcodec_debug(inst,
+				"drv->new_fb_idx=%d, drv->frm_to_show_idx=%d",
+				vsi->new_fb_idx, vsi->frm_to_show_idx);
+
+		if (vsi->show_existing_frame && (vsi->frm_to_show_idx <
+					VP9_MAX_FRM_BUF_NUM)) {
+			mtk_vcodec_err(inst,
+				"Skip Decode drv->new_fb_idx=%d, drv->frm_to_show_idx=%d",
+				vsi->new_fb_idx, vsi->frm_to_show_idx);
+
+			vp9_ref_cnt_fb(inst, &vsi->new_fb_idx,
+					vsi->frm_to_show_idx);
+			ret = -EINVAL;
+			goto DECODE_ERROR;
+		}
+
+		/* VPU assign the buffer pointer in its address space,
+		 * reassign here
+		 */
+		for (i = 0; i < ARRAY_SIZE(vsi->frm_refs); i++) {
+			unsigned int idx = vsi->frm_refs[i].idx;
+
+			vsi->frm_refs[i].buf = &vsi->frm_bufs[idx].buf;
+		}
+
+		if (vsi->resolution_changed) {
+			*res_chg = true;
+			mtk_vcodec_debug(inst, "VDEC_ST_RESOLUTION_CHANGED");
+
+			ret = 0;
+			goto DECODE_ERROR;
+		}
+
+		if (vp9_decode_end_proc(inst) != true) {
+			mtk_vcodec_err(inst, "vp9_decode_end_proc");
+			ret = -EINVAL;
+			goto DECODE_ERROR;
+		}
+
+		if (vp9_is_last_sub_frm(inst))
+			break;
+
+	}
+	inst->total_frm_cnt++;
+
+DECODE_ERROR:
+	if (ret < 0)
+		vp9_add_to_fb_free_list(inst, fb);
+
+	return ret;
+}
+
+static void get_crop_info(struct vdec_vp9_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = 0;
+	cr->top = 0;
+	cr->width = inst->vsi->pic_w;
+	cr->height = inst->vsi->buf_h;
+	mtk_vcodec_debug(inst, "get crop info l=%d, t=%d, w=%d, h=%d\n",
+			 cr->left, cr->top, cr->width, cr->height);
+}
+
+static int vdec_vp9_get_param(unsigned long h_vdec,
+		enum vdec_get_param_type type, void *out)
+{
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+	int ret = 0;
+
+	switch (type) {
+	case GET_PARAM_DISP_FRAME_BUFFER:
+		get_disp_fb(inst, out);
+		break;
+	case GET_PARAM_FREE_FRAME_BUFFER:
+		get_free_fb(inst, out);
+		break;
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+	case GET_PARAM_DPB_SIZE:
+		*((unsigned int *)out) = MAX_VP9_DPB_SIZE;
+		break;
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+	default:
+		mtk_vcodec_err(inst, "not supported param type %d", type);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static struct vdec_common_if vdec_vp9_if = {
+	vdec_vp9_init,
+	vdec_vp9_decode,
+	vdec_vp9_get_param,
+	vdec_vp9_deinit,
+};
+
+struct vdec_common_if *get_vp9_dec_comm_if(void);
+
+struct vdec_common_if *get_vp9_dec_comm_if(void)
+{
+	return &vdec_vp9_if;
+}
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
index 5338171..3d7aaab 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
@@ -26,6 +26,7 @@
 
 struct vdec_common_if *get_h264_dec_comm_if(void);
 struct vdec_common_if *get_vp8_dec_comm_if(void);
+struct vdec_common_if *get_vp9_dec_comm_if(void);
 
 int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 {
@@ -39,6 +40,8 @@ int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 		ctx->dec_if = get_vp8_dec_comm_if();
 		break;
 	case V4L2_PIX_FMT_VP9:
+		ctx->dec_if = get_vp9_dec_comm_if();
+		break;
 	default:
 		return -EINVAL;
 	}
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Mon May 30 05:29:14 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Mon, 30 May 2016 20:29:14 +0800
Subject: [PATCH v3 0/9] Add MT8173 Video Decoder Driver
Message-ID: <1464611363-14936-1-git-send-email-tiffany.lin@mediatek.com>

==============
 Introduction
==============

The purpose of this series is to add the driver for video codec hw embedded in the Mediatek's MT8173 SoCs.
Mediatek Video Codec is able to handle video decoding of in a range of formats.

This patch series add Mediatek block format V4L2_PIX_FMT_MT21, the decoder driver will decoded bitstream to
V4L2_PIX_FMT_MT21 format.

This patch series rely on MTK VPU driver in patch series "Add MT8173 Video Encoder Driver and VPU Driver"[1]
and patch "CHROMIUM: v4l: Add V4L2_PIX_FMT_VP9 definition"[2] for VP9 support.
Mediatek Video Decoder driver rely on VPU driver to load, communicate with VPU.

Internally the driver uses videobuf2 framework and MTK IOMMU and MTK SMI both have been merged in v4.6-rc1.

[1]https://patchwork.linuxtv.org/patch/33734/
[2]https://chromium-review.googlesource.com/#/c/245241/

==================
 Device interface
==================

In principle the driver bases on v4l2 memory-to-memory framework:
it provides a single video node and each opened file handle gets its own private context with separate
buffer queues. Each context consist of 2 buffer queues: OUTPUT (for source buffers, i.e. bitstream)
and CAPTURE (for destination buffers, i.e. decoded video frames).
OUTPUT and CAPTURE buffer could be MMAP or DMABUF memory type.
VIDIOC_G_CTRL and VIDIOC_G_EXT_CTRLS return V4L2_CID_MIN_BUFFERS_FOR_CAPTURE only when dirver in MTK_STATE_HEADER
state, or it will return EAGAIN.
Driver do not support subscribe event for control 'User Controls' for now.
And it default support export DMABUF for other display drivers.

Change in v3:
1. Refine vdec hw clock setting
2. Refine vp9 codec driver
3. Refine v4l2 codec driver

Change in v2:
1. Add documentation for V4L2_PIX_FMT_MT21
2. Remove DRM_FORMAT_MT21
2. Refine code according to review comments

v4l2-compliance test output:
localhost Encode # ./v4l2-compliance -d /dev/video0
Driver Info:
        Driver name   : mtk-vcodec-dec
        Card type     : platform:mt8173
        Bus info      : platform:mt8173
        Driver version: 4.4.0
        Capabilities  : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps   : 0x04204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format

Compliance test for device /dev/video0 (not using libv4l2):

Required ioctls:
        test VIDIOC_QUERYCAP: OK

Allow for multiple opens:
        test second video open: OK
        test VIDIOC_QUERYCAP: OK
        test VIDIOC_G/S_PRIORITY: OK

Debug ioctls:
        test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
        test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
        test VIDIOC_ENUMAUDIO: OK (Not Supported)
        test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDIO: OK (Not Supported)
        Inputs: 0 Audio Inputs: 0 Tuners: 0

Output ioctls:
        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
        Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
        test VIDIOC_G/S_EDID: OK (Not Supported)

        Control ioctls:
                test VIDIOC_QUERYCTRL/MENU: OK
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-controls.cpp(357): g_ctrl returned an error (11)
                test VIDIOC_G/S_CTRL: FAIL
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-controls.cpp(579): g_ext_ctrls returned an error (11)
                test VIDIOC_G/S/TRY_EXT_CTRLS: FAIL
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-controls.cpp(721): subscribe event for control 'User Controls' failed
                test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: FAIL
                test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
                Standard Controls: 2 Private Controls: 0

        Format ioctls:
                test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
                test VIDIOC_G/S_PARM: OK (Not Supported)
                test VIDIOC_G_FBUF: OK (Not Supported)
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-formats.cpp(405): expected EINVAL, but got 11 when getting format for buftype 9
                test VIDIOC_G_FMT: FAIL
                test VIDIOC_TRY_FMT: OK (Not Supported)
                test VIDIOC_S_FMT: OK (Not Supported)
                test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)

        Codec ioctls:
                test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
                test VIDIOC_G_ENC_INDEX: OK (Not Supported)
                test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)

        Buffer ioctls:
                test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
                fail: ../../../v4l-utils-1.6.0/utils/v4l2-compliance/v4l2-test-buffers.cpp(500): q.has_expbuf(node)
                test VIDIOC_EXPBUF: FAIL


Total: 38, Succeeded: 33, Failed: 5, Warnings: 0


Andrew-CT Chen (1):
  VPU: mediatek: Add decode support

Tiffany Lin (8):
  v4l: add Mediatek compressed video block format
  DocBook/v4l: Add compressed video formats used on MT8173 codec driver
  dt-bindings: Add a binding for Mediatek Video Decoder
  vcodec: mediatek: Add Mediatek V4L2 Video Decoder Driver
  vcodec: mediatek: Add Mediatek H264 Video Decoder Driver
  vcodec: mediatek: Add Mediatek VP8 Video Decoder Driver
  vcodec: mediatek: Add Mediatek VP9 Video Decoder Driver
  arm64: dts: mediatek: Add Video Decoder for MT8173

 Documentation/DocBook/media/v4l/pixfmt.xml         |    6 +
 .../devicetree/bindings/media/mediatek-vcodec.txt  |   57 +-
 arch/arm64/boot/dts/mediatek/mt8173.dtsi           |   44 +
 drivers/media/platform/mtk-vcodec/Makefile         |   15 +-
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 1348 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h |   88 ++
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c |  408 ++++++
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c  |  206 +++
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h  |   28 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h |   88 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_intr.c    |    4 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_intr.h    |    2 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_util.c    |   31 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_util.h    |    7 +-
 .../media/platform/mtk-vcodec/vdec/vdec_h264_if.c  |  503 ++++++++
 .../media/platform/mtk-vcodec/vdec/vdec_vp8_if.c   |  630 +++++++++
 .../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c   |  967 ++++++++++++++
 drivers/media/platform/mtk-vcodec/vdec_drv_base.h  |   56 +
 drivers/media/platform/mtk-vcodec/vdec_drv_if.c    |  117 ++
 drivers/media/platform/mtk-vcodec/vdec_drv_if.h    |  101 ++
 drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h   |  103 ++
 drivers/media/platform/mtk-vcodec/vdec_vpu_if.c    |  168 +++
 drivers/media/platform/mtk-vcodec/vdec_vpu_if.h    |   96 ++
 drivers/media/platform/mtk-vpu/mtk_vpu.c           |   12 +
 drivers/media/platform/mtk-vpu/mtk_vpu.h           |   27 +
 include/uapi/linux/videodev2.h                     |    1 +
 26 files changed, 5090 insertions(+), 23 deletions(-)
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_drv_base.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_drv_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_drv_if.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_vpu_if.h

-- 
1.7.9.5



From tiffany.lin at mediatek.com  Mon May 30 05:29:21 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Mon, 30 May 2016 20:29:21 +0800
Subject: [PATCH v3 7/9] vcodec: mediatek: Add Mediatek VP8 Video Decoder Driver
In-Reply-To: <1464611363-14936-7-git-send-email-tiffany.lin@mediatek.com>
References: <1464611363-14936-1-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-2-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-3-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-4-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-5-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-6-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-7-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1464611363-14936-8-git-send-email-tiffany.lin@mediatek.com>

Add vp8 decoder driver for MT8173

Signed-off-by: PC Chen <pc.chen at mediatek.com>
Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 drivers/media/platform/mtk-vcodec/Makefile         |    1 +
 .../media/platform/mtk-vcodec/vdec/vdec_vp8_if.c   |  630 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/vdec_drv_if.c    |    3 +
 3 files changed, 634 insertions(+)
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c

diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
index 58243ed..7743c81 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
 				       mtk-vcodec-common.o
 
 mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
+		vdec/vdec_vp8_if.o \
 		mtk_vcodec_dec_drv.o \
 		vdec_drv_if.o \
 		vdec_vpu_if.o \
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
new file mode 100644
index 0000000..0c86df0
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
@@ -0,0 +1,630 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Jungchang Tsao <jungchang.tsao at mediatek.com>
+ *	   PC Chen <pc.chen at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "../mtk_vcodec_intr.h"
+#include "../vdec_vpu_if.h"
+#include "../vdec_drv_base.h"
+
+/* Decoding picture buffer size (3 reference frames plus current frame) */
+#define VP8_DPB_SIZE			4
+
+/* HW working buffer size (bytes) */
+#define VP8_WORKING_BUF_SZ		(45 * 4096)
+
+/* HW control register address */
+#define VP8_SEGID_DRAM_ADDR		0x3c
+#define VP8_HW_VLD_ADDR			0x93C
+#define VP8_HW_VLD_VALUE		0x940
+#define VP8_BSASET			0x100
+#define VP8_BSDSET			0x104
+#define VP8_RW_CKEN_SET			0x0
+#define VP8_RW_DCM_CON			0x18
+#define VP8_WO_VLD_SRST			0x108
+#define VP8_RW_MISC_SYS_SEL		0x84
+#define VP8_RW_MISC_SPEC_CON		0xC8
+#define VP8_WO_VLD_SRST			0x108
+#define VP8_RW_VP8_CTRL			0xA4
+#define VP8_RW_MISC_DCM_CON		0xEC
+#define VP8_RW_MISC_SRST		0xF4
+#define VP8_RW_MISC_FUNC_CON		0xCC
+
+#define VP8_MAX_FRM_BUF_NUM		5
+#define VP8_MAX_FRM_BUF_NODE_NUM	(VP8_MAX_FRM_BUF_NUM * 2)
+
+/* required buffer size (bytes) to store decode information */
+#define VP8_HW_SEGMENT_DATA_SZ		272
+#define VP8_HW_SEGMENT_UINT		4
+
+#define VP8_DEC_TABLE_PROC_LOOP		96
+#define VP8_DEC_TABLE_UNIT		3
+#define VP8_DEC_TABLE_SZ		300
+#define VP8_DEC_TABLE_OFFSET		2
+#define VP8_DEC_TABLE_RW_UNIT		4
+
+/**
+ * struct vdec_vp8_dec_info - decode misc information
+ * @working_buf_dma   : working buffer dma address
+ * @prev_y_dma        : previous decoded frame buffer Y plane address
+ * @cur_y_fb_dma      : current plane Y frame buffer dma address
+ * @cur_c_fb_dma      : current plane C frame buffer dma address
+ * @bs_dma	      : bitstream dma address
+ * @bs_sz	      : bitstream size
+ * @resolution_changed: resolution change flag 1 - changed,  0 - not change
+ * @show_frame	      : display this frame or not
+ * @wait_key_frame    : wait key frame coming
+ */
+struct vdec_vp8_dec_info {
+	uint64_t working_buf_dma;
+	uint64_t prev_y_dma;
+	uint64_t cur_y_fb_dma;
+	uint64_t cur_c_fb_dma;
+	uint64_t bs_dma;
+	uint32_t bs_sz;
+	uint32_t resolution_changed;
+	uint32_t show_frame;
+	uint32_t wait_key_frame;
+};
+
+/**
+ * struct vdec_vp8_vsi - VPU shared information
+ * @dec			: decoding information
+ * @pic			: picture information
+ * @dec_table		: decoder coefficient table
+ * @segment_buf		: segmentation buffer
+ * @load_data		: flag to indicate reload decode data
+ */
+struct vdec_vp8_vsi {
+	struct vdec_vp8_dec_info dec;
+	struct vdec_pic_info pic;
+	uint32_t dec_table[VP8_DEC_TABLE_SZ];
+	uint32_t segment_buf[VP8_HW_SEGMENT_DATA_SZ][VP8_HW_SEGMENT_UINT];
+	uint32_t load_data;
+};
+
+/**
+ * struct vdec_vp8_hw_reg_base - HW register base
+ * @sys		: base address for sys
+ * @misc	: base address for misc
+ * @ld		: base address for ld
+ * @top		: base address for top
+ * @cm		: base address for cm
+ * @hwd		: base address for hwd
+ * @hwb		: base address for hwb
+*/
+struct vdec_vp8_hw_reg_base {
+	void __iomem *sys;
+	void __iomem *misc;
+	void __iomem *ld;
+	void __iomem *top;
+	void __iomem *cm;
+	void __iomem *hwd;
+	void __iomem *hwb;
+};
+
+/**
+ * struct vdec_vp8_vpu_inst - VPU instance for VP8 decode
+ * @wq_hd	: Wait queue to wait VPU message ack
+ * @signaled	: 1 - Host has received ack message from VPU, 0 - not recevie
+ * @failure	: VPU execution result status 0 - success, others - fail
+ * @inst_addr	: VPU decoder instance address
+ */
+struct vdec_vp8_vpu_inst {
+	wait_queue_head_t wq_hd;
+	int signaled;
+	int failure;
+	uint32_t inst_addr;
+};
+
+/* frame buffer (fb) list
+ * [available_fb_node_list]  - decode fb are initialized to 0 and populated in
+ * [fb_use_list]  - fb is set after decode and is moved to this list
+ * [fb_free_list] - fb is not needed for reference will be moved from
+ *		     [fb_use_list] to [fb_free_list] and
+ *		     once user remove fb from [fb_free_list],
+ *		     it is circulated back to [available_fb_node_list]
+ * [fb_disp_list] - fb is set after decode and is moved to this list
+ *                   once user remove fb from [fb_disp_list] it is
+ *                   circulated back to [available_fb_node_list]
+ */
+
+/**
+ * struct vdec_vp8_inst - VP8 decoder instance
+ * @cur_fb		   : current frame buffer
+ * @dec_fb		   : decode frame buffer node
+ * @available_fb_node_list : list to store available frame buffer node
+ * @fb_use_list		   : list to store frame buffer in use
+ * @fb_free_list	   : list to store free frame buffer
+ * @fb_disp_list	   : list to store display ready frame buffer
+ * @working_buf		   : HW decoder working buffer
+ * @reg_base		   : HW register base address
+ * @frm_cnt		   : decode frame count
+ * @ctx			   : V4L2 context
+ * @dev			   : platform device
+ * @vpu			   : VPU instance for decoder
+ * @vsi			   : VPU share information
+ */
+struct vdec_vp8_inst {
+	struct vdec_fb *cur_fb;
+	struct vdec_fb_node dec_fb[VP8_MAX_FRM_BUF_NODE_NUM];
+	struct list_head available_fb_node_list;
+	struct list_head fb_use_list;
+	struct list_head fb_free_list;
+	struct list_head fb_disp_list;
+	struct mtk_vcodec_mem working_buf;
+	struct vdec_vp8_hw_reg_base reg_base;
+	unsigned int frm_cnt;
+	struct mtk_vcodec_ctx *ctx;
+	struct vdec_vpu_inst vpu;
+	struct vdec_vp8_vsi *vsi;
+};
+
+static void get_hw_reg_base(struct vdec_vp8_inst *inst)
+{
+	inst->reg_base.top = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_TOP);
+	inst->reg_base.cm = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_CM);
+	inst->reg_base.hwd = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_HWD);
+	inst->reg_base.sys = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_SYS);
+	inst->reg_base.misc = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_MISC);
+	inst->reg_base.ld = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_LD);
+	inst->reg_base.hwb = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_HWB);
+}
+
+static void write_hw_segmentation_data(struct vdec_vp8_inst *inst)
+{
+	int i, j;
+	u32 seg_id_addr;
+	u32 val;
+	void __iomem *cm = inst->reg_base.cm;
+	struct vdec_vp8_vsi *vsi = inst->vsi;
+
+	seg_id_addr = readl(inst->reg_base.top + VP8_SEGID_DRAM_ADDR) >> 4;
+
+	for (i = 0; i < ARRAY_SIZE(vsi->segment_buf); i++) {
+		for (j = ARRAY_SIZE(vsi->segment_buf[i]) - 1; j >= 0; j--) {
+			val = (1 << 16) + ((seg_id_addr + i) << 2) + j;
+			writel(val, cm + VP8_HW_VLD_ADDR);
+
+			val = vsi->segment_buf[i][j];
+			writel(val, cm + VP8_HW_VLD_VALUE);
+		}
+	}
+}
+
+static void read_hw_segmentation_data(struct vdec_vp8_inst *inst)
+{
+	int i, j;
+	u32 seg_id_addr;
+	u32 val;
+	void __iomem *cm = inst->reg_base.cm;
+	struct vdec_vp8_vsi *vsi = inst->vsi;
+
+	seg_id_addr = readl(inst->reg_base.top + VP8_SEGID_DRAM_ADDR) >> 4;
+
+	for (i = 0; i < ARRAY_SIZE(vsi->segment_buf); i++) {
+		for (j = ARRAY_SIZE(vsi->segment_buf[i]) - 1; j >= 0; j--) {
+			val = ((seg_id_addr + i) << 2) + j;
+			writel(val, cm + VP8_HW_VLD_ADDR);
+
+			val = readl(cm + VP8_HW_VLD_VALUE);
+			vsi->segment_buf[i][j] = val;
+		}
+	}
+}
+
+/* reset HW and enable HW read/write data function */
+static void enable_hw_rw_function(struct vdec_vp8_inst *inst)
+{
+	u32 val = 0;
+	void __iomem *sys = inst->reg_base.sys;
+	void __iomem *misc = inst->reg_base.misc;
+	void __iomem *ld = inst->reg_base.ld;
+	void __iomem *hwb = inst->reg_base.hwb;
+	void __iomem *hwd = inst->reg_base.hwd;
+
+	writel(0x1, sys + VP8_RW_CKEN_SET);
+	writel(0x101, ld + VP8_WO_VLD_SRST);
+	writel(0x101, hwb + VP8_WO_VLD_SRST);
+
+	writel(1, sys);
+	val = readl(misc + VP8_RW_MISC_SRST);
+	writel((val & 0xFFFFFFFE), misc + VP8_RW_MISC_SRST);
+
+	writel(0x1, misc + VP8_RW_MISC_SYS_SEL);
+	writel(0x17F, misc + VP8_RW_MISC_SPEC_CON);
+	writel(0x71201100, misc + VP8_RW_MISC_FUNC_CON);
+	writel(0x0, ld + VP8_WO_VLD_SRST);
+	writel(0x0, hwb + VP8_WO_VLD_SRST);
+	writel(0x1, sys + VP8_RW_DCM_CON);
+	writel(0x1, misc + VP8_RW_MISC_DCM_CON);
+	writel(0x1, hwd + VP8_RW_VP8_CTRL);
+}
+
+static void store_dec_table(struct vdec_vp8_inst *inst)
+{
+	int i, j;
+	u32 addr = 0, val = 0;
+	void __iomem *hwd = inst->reg_base.hwd;
+	u32 *p = &inst->vsi->dec_table[VP8_DEC_TABLE_OFFSET];
+
+	for (i = 0; i < VP8_DEC_TABLE_PROC_LOOP; i++) {
+		writel(addr, hwd + VP8_BSASET);
+		for (j = 0; j < VP8_DEC_TABLE_UNIT ; j++) {
+			val = *p++;
+			writel(val, hwd + VP8_BSDSET);
+		}
+		addr += VP8_DEC_TABLE_RW_UNIT;
+	}
+}
+
+static void load_dec_table(struct vdec_vp8_inst *inst)
+{
+	int i;
+	u32 addr = 0;
+	u32 *p = &inst->vsi->dec_table[VP8_DEC_TABLE_OFFSET];
+	void __iomem *hwd = inst->reg_base.hwd;
+
+	for (i = 0; i < VP8_DEC_TABLE_PROC_LOOP; i++) {
+		writel(addr, hwd + VP8_BSASET);
+		/* read total 11 bytes */
+		*p++ = readl(hwd + VP8_BSDSET);
+		*p++ = readl(hwd + VP8_BSDSET);
+		*p++ = readl(hwd + VP8_BSDSET) & 0xFFFFFF;
+		addr += VP8_DEC_TABLE_RW_UNIT;
+	}
+}
+
+static void get_pic_info(struct vdec_vp8_inst *inst, struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+
+	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
+			 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
+	mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+			 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void vp8_dec_finish(struct vdec_vp8_inst *inst)
+{
+	struct vdec_fb_node *node;
+	uint64_t prev_y_dma = inst->vsi->dec.prev_y_dma;
+
+	mtk_vcodec_debug(inst, "prev fb base dma=%llx", prev_y_dma);
+
+	/* put last decode ok frame to fb_free_list */
+	if (prev_y_dma != 0) {
+		list_for_each_entry(node, &inst->fb_use_list, list) {
+			struct vdec_fb *fb = (struct vdec_fb *)node->fb;
+
+			if (prev_y_dma == (uint64_t)fb->base_y.dma_addr) {
+				list_move_tail(&node->list,
+					       &inst->fb_free_list);
+				break;
+			}
+		}
+	}
+
+	/* available_fb_node_list -> fb_use_list */
+	node = list_first_entry(&inst->available_fb_node_list,
+				struct vdec_fb_node, list);
+	node->fb = inst->cur_fb;
+	list_move_tail(&node->list, &inst->fb_use_list);
+
+	/* available_fb_node_list -> fb_disp_list */
+	if (inst->vsi->dec.show_frame) {
+		node = list_first_entry(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+		node->fb = inst->cur_fb;
+		list_move_tail(&node->list, &inst->fb_disp_list);
+	}
+}
+
+static void move_fb_list_use_to_free(struct vdec_vp8_inst *inst)
+{
+	struct vdec_fb_node *node, *tmp;
+
+	list_for_each_entry_safe(node, tmp, &inst->fb_use_list, list)
+		list_move_tail(&node->list, &inst->fb_free_list);
+}
+
+static void init_list(struct vdec_vp8_inst *inst)
+{
+	int i;
+
+	INIT_LIST_HEAD(&inst->available_fb_node_list);
+	INIT_LIST_HEAD(&inst->fb_use_list);
+	INIT_LIST_HEAD(&inst->fb_free_list);
+	INIT_LIST_HEAD(&inst->fb_disp_list);
+
+	for (i = 0; i < ARRAY_SIZE(inst->dec_fb); i++) {
+		INIT_LIST_HEAD(&inst->dec_fb[i].list);
+		inst->dec_fb[i].fb = NULL;
+		list_add_tail(&inst->dec_fb[i].list,
+			      &inst->available_fb_node_list);
+	}
+}
+
+static void add_fb_to_free_list(struct vdec_vp8_inst *inst, void *fb)
+{
+	struct vdec_fb_node *node;
+
+	if (fb) {
+		node = list_first_entry(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+		node->fb = fb;
+		list_move_tail(&node->list, &inst->fb_free_list);
+	}
+}
+
+static int alloc_working_buf(struct vdec_vp8_inst *inst)
+{
+	int err;
+	struct mtk_vcodec_mem *mem = &inst->working_buf;
+
+	mem->size = VP8_WORKING_BUF_SZ;
+	err = mtk_vcodec_mem_alloc(inst->ctx, mem);
+	if (err) {
+		mtk_vcodec_err(inst, "Cannot allocate working buffer");
+		return err;
+	}
+
+	inst->vsi->dec.working_buf_dma = (uint64_t)mem->dma_addr;
+	return 0;
+}
+
+static void free_working_buf(struct vdec_vp8_inst *inst)
+{
+	struct mtk_vcodec_mem *mem = &inst->working_buf;
+
+	if (mem->va)
+		mtk_vcodec_mem_free(inst->ctx, mem);
+
+	inst->vsi->dec.working_buf_dma = 0;
+}
+
+static int vdec_vp8_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_vp8_inst *inst;
+	int err;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return  -ENOMEM;
+
+	inst->ctx = ctx;
+
+	inst->vpu.id = IPI_VDEC_VP8;
+	inst->vpu.dev = ctx->dev->vpu_plat_dev;
+	inst->vpu.ctx = ctx;
+	inst->vpu.handler = vpu_dec_ipi_handler;
+
+	err = vpu_dec_init(&inst->vpu);
+	if (err) {
+		mtk_vcodec_err(inst, "vdec_vp8 init err=%d", err);
+		goto error_free_inst;
+	}
+
+	inst->vsi = (struct vdec_vp8_vsi *)inst->vpu.vsi;
+	init_list(inst);
+	err = alloc_working_buf(inst);
+	if (err)
+		goto error_deinit;
+
+	get_hw_reg_base(inst);
+	mtk_vcodec_debug(inst, "VP8 Instance >> %p", inst);
+
+	*h_vdec = (unsigned long)inst;
+	return 0;
+
+error_deinit:
+	vpu_dec_deinit(&inst->vpu);
+error_free_inst:
+	kfree(inst);
+	return err;
+}
+
+static int vdec_vp8_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+			   struct vdec_fb *fb, bool *res_chg)
+{
+	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
+	struct vdec_vp8_dec_info *dec = &inst->vsi->dec;
+	struct vdec_vpu_inst *vpu = &inst->vpu;
+	unsigned char *bs_va;
+	unsigned int data;
+	int err = 0;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+
+	/* bs NULL means flush decoder */
+	if (bs == NULL) {
+		move_fb_list_use_to_free(inst);
+		return vpu_dec_reset(vpu);
+	}
+
+	y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
+	c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
+
+	mtk_vcodec_debug(inst, "+ [%d] FB y_dma=%llx c_dma=%llx fb=%p",
+			 inst->frm_cnt, y_fb_dma, c_fb_dma, fb);
+
+	inst->cur_fb = fb;
+	dec->bs_dma = (unsigned long)bs->dma_addr;
+	dec->bs_sz = bs->size;
+	dec->cur_y_fb_dma = y_fb_dma;
+	dec->cur_c_fb_dma = c_fb_dma;
+
+	mtk_vcodec_debug(inst, "\n + FRAME[%d] +\n", inst->frm_cnt);
+
+	write_hw_segmentation_data(inst);
+	enable_hw_rw_function(inst);
+	store_dec_table(inst);
+
+	bs_va = (unsigned char *)bs->va;
+
+	/* retrieve width/hight and scale info from header */
+	data = (*(bs_va + 9) << 24) | (*(bs_va + 8) << 16) |
+	       (*(bs_va + 7) << 8) | *(bs_va + 6);
+	err = vpu_dec_start(vpu, &data, 1);
+	if (err) {
+		add_fb_to_free_list(inst, fb);
+		if (dec->wait_key_frame) {
+			mtk_vcodec_debug(inst, "wait key frame !");
+			return 0;
+		}
+
+		goto error;
+	}
+
+	if (dec->resolution_changed) {
+		mtk_vcodec_debug(inst, "- resolution_changed -");
+		*res_chg = true;
+		add_fb_to_free_list(inst, fb);
+		return 0;
+	}
+
+	/* wait decoder done interrupt */
+	mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
+				     WAIT_INTR_TIMEOUT_MS);
+
+	if (inst->vsi->load_data)
+		load_dec_table(inst);
+
+	vp8_dec_finish(inst);
+	read_hw_segmentation_data(inst);
+
+	err = vpu_dec_end(vpu);
+	if (err)
+		goto error;
+
+	mtk_vcodec_debug(inst, "\n - FRAME[%d] - show=%d\n", inst->frm_cnt,
+			 dec->show_frame);
+	inst->frm_cnt++;
+	*res_chg = false;
+	return 0;
+
+error:
+	mtk_vcodec_err(inst, "\n - FRAME[%d] - err=%d\n", inst->frm_cnt, err);
+	return err;
+}
+
+static void get_disp_fb(struct vdec_vp8_inst *inst, struct vdec_fb **out_fb)
+{
+	struct vdec_fb_node *node;
+	struct vdec_fb *fb;
+
+	node = list_first_entry_or_null(&inst->fb_disp_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		list_move_tail(&node->list, &inst->available_fb_node_list);
+		fb = (struct vdec_fb *)node->fb;
+		fb->status |= FB_ST_DISPLAY;
+		mtk_vcodec_debug(inst, "[FB] get disp fb %p st=%d",
+				 node->fb, fb->status);
+	} else {
+		fb = NULL;
+		mtk_vcodec_debug(inst, "[FB] there is no disp fb");
+	}
+
+	*out_fb = fb;
+}
+
+static void get_free_fb(struct vdec_vp8_inst *inst, struct vdec_fb **out_fb)
+{
+	struct vdec_fb_node *node;
+	struct vdec_fb *fb;
+
+	node = list_first_entry_or_null(&inst->fb_free_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		list_move_tail(&node->list, &inst->available_fb_node_list);
+		fb = (struct vdec_fb *)node->fb;
+		fb->status |= FB_ST_FREE;
+		mtk_vcodec_debug(inst, "[FB] get free fb %p st=%d",
+				 node->fb, fb->status);
+	} else {
+		fb = NULL;
+		mtk_vcodec_debug(inst, "[FB] there is no free fb");
+	}
+
+	*out_fb = fb;
+}
+
+static void get_crop_info(struct vdec_vp8_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = 0;
+	cr->top = 0;
+	cr->width = inst->vsi->pic.pic_w;
+	cr->height = inst->vsi->pic.pic_h;
+	mtk_vcodec_debug(inst, "get crop info l=%d, t=%d, w=%d, h=%d",
+			 cr->left, cr->top, cr->width, cr->height);
+}
+
+static int vdec_vp8_get_param(unsigned long h_vdec,
+			      enum vdec_get_param_type type, void *out)
+{
+	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
+
+	switch (type) {
+	case GET_PARAM_DISP_FRAME_BUFFER:
+		get_disp_fb(inst, out);
+		break;
+
+	case GET_PARAM_FREE_FRAME_BUFFER:
+		get_free_fb(inst, out);
+		break;
+
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		*((unsigned int *)out) = VP8_DPB_SIZE;
+		break;
+
+	default:
+		mtk_vcodec_err(inst, "invalid get parameter type=%d", type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void vdec_vp8_deinit(unsigned long h_vdec)
+{
+	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
+
+	mtk_vcodec_debug_enter(inst);
+
+	vpu_dec_deinit(&inst->vpu);
+	free_working_buf(inst);
+	kfree(inst);
+}
+
+static struct vdec_common_if vdec_vp8_if = {
+	vdec_vp8_init,
+	vdec_vp8_decode,
+	vdec_vp8_get_param,
+	vdec_vp8_deinit,
+};
+
+struct vdec_common_if *get_vp8_dec_comm_if(void);
+
+struct vdec_common_if *get_vp8_dec_comm_if(void)
+{
+	return &vdec_vp8_if;
+}
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
index e61f541..5338171 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
@@ -25,6 +25,7 @@
 #include "mtk_vpu.h"
 
 struct vdec_common_if *get_h264_dec_comm_if(void);
+struct vdec_common_if *get_vp8_dec_comm_if(void);
 
 int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 {
@@ -35,6 +36,8 @@ int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 		ctx->dec_if = get_h264_dec_comm_if();
 		break;
 	case V4L2_PIX_FMT_VP8:
+		ctx->dec_if = get_vp8_dec_comm_if();
+		break;
 	case V4L2_PIX_FMT_VP9:
 	default:
 		return -EINVAL;
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Mon May 30 05:29:20 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Mon, 30 May 2016 20:29:20 +0800
Subject: [PATCH v3 6/9] vcodec: mediatek: Add Mediatek H264 Video Decoder
 Driver
In-Reply-To: <1464611363-14936-6-git-send-email-tiffany.lin@mediatek.com>
References: <1464611363-14936-1-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-2-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-3-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-4-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-5-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-6-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1464611363-14936-7-git-send-email-tiffany.lin@mediatek.com>

Add h264 decoder driver for MT8173

Signed-off-by: PC Chen <pc.chen at mediatek.com>
Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 drivers/media/platform/mtk-vcodec/Makefile         |    5 +-
 .../media/platform/mtk-vcodec/vdec/vdec_h264_if.c  |  503 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/vdec_drv_if.c    |    4 +
 drivers/media/platform/mtk-vcodec/vdec_vpu_if.c    |  168 +++++++
 drivers/media/platform/mtk-vcodec/vdec_vpu_if.h    |   96 ++++
 5 files changed, 774 insertions(+), 2 deletions(-)
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_vpu_if.h

diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
index 4c8ed2f..58243ed 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -1,11 +1,12 @@
 
-
 obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
 				       mtk-vcodec-enc.o \
 				       mtk-vcodec-common.o
 
-mtk-vcodec-dec-y := mtk_vcodec_dec_drv.o \
+mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
+		mtk_vcodec_dec_drv.o \
 		vdec_drv_if.o \
+		vdec_vpu_if.o \
 		mtk_vcodec_dec.o \
 		mtk_vcodec_dec_pm.o \
 
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
new file mode 100644
index 0000000..8de0b53
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "../mtk_vcodec_intr.h"
+#include "../vdec_vpu_if.h"
+#include "../vdec_drv_base.h"
+
+#define NAL_NON_IDR_SLICE			0x01
+#define NAL_IDR_SLICE				0x05
+#define NAL_H264_PPS				0x08
+#define NAL_TYPE(value)				((value) & 0x1F)
+
+#define BUF_PREDICTION_SZ			(32 * 1024)
+
+#define MB_UNIT_LEN				16
+
+/* motion vector size (bytes) for every macro block */
+#define HW_MB_STORE_SZ				64
+
+#define H264_MAX_FB_NUM				17
+#define HDR_PARSING_BUF_SZ			1024
+
+/**
+ * struct h264_fb - h264 decode frame buffer information
+ * @vdec_fb_va  : virtual address of struct vdec_fb
+ * @y_fb_dma    : dma address of Y frame buffer (luma)
+ * @c_fb_dma    : dma address of C frame buffer (chroma)
+ * @poc         : picture order count of frame buffer
+ * @reserved    : for 8 bytes alignment
+ */
+struct h264_fb {
+	uint64_t vdec_fb_va;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	int32_t poc;
+	uint32_t reserved;
+};
+
+/**
+ * struct h264_ring_fb_list - ring frame buffer list
+ * @fb_list   : frame buffer arrary
+ * @read_idx  : read index
+ * @write_idx : write index
+ * @count     : buffer count in list
+ */
+struct h264_ring_fb_list {
+	struct h264_fb fb_list[H264_MAX_FB_NUM];
+	unsigned int read_idx;
+	unsigned int write_idx;
+	unsigned int count;
+	unsigned int reserved;
+};
+
+/**
+ * struct vdec_h264_dec_info - decode information
+ * @dpb_sz		: decoding picture buffer size
+ * @resolution_changed  : resoltion change happen
+ * @realloc_mv_buf	: flag to notify driver to re-allocate mv buffer
+ * @reserved		: for 8 bytes alignment
+ * @bs_dma		: Input bit-stream buffer dma address
+ * @y_fb_dma		: Y frame buffer dma address
+ * @c_fb_dma		: C frame buffer dma address
+ * @vdec_fb_va		: VDEC frame buffer struct virtual address
+ */
+struct vdec_h264_dec_info {
+	uint32_t dpb_sz;
+	uint32_t resolution_changed;
+	uint32_t realloc_mv_buf;
+	uint32_t reserved;
+	uint64_t bs_dma;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	uint64_t vdec_fb_va;
+};
+
+/**
+ * struct vdec_h264_vsi - shared memory for decode information exchange
+ *                        between VPU and Host.
+ *                        The memory is allocated by VPU then mapping to Host
+ *                        in vpu_dec_init() and freed in vpu_dec_deinit()
+ *                        by VPU.
+ *                        AP-W/R : AP is writer/reader on this item
+ *                        VPU-W/R: VPU is write/reader on this item
+ * @hdr_buf      : Header parsing buffer (AP-W, VPU-R)
+ * @pred_buf_dma : HW working predication buffer dma address (AP-W, VPU-R)
+ * @mv_buf_dma   : HW working motion vector buffer dma address (AP-W, VPU-R)
+ * @list_free    : free frame buffer ring list (AP-W/R, VPU-W)
+ * @list_disp    : display frame buffer ring list (AP-R, VPU-W)
+ * @dec          : decode information (AP-R, VPU-W)
+ * @pic          : picture information (AP-R, VPU-W)
+ * @crop         : crop information (AP-R, VPU-W)
+ */
+struct vdec_h264_vsi {
+	unsigned char hdr_buf[HDR_PARSING_BUF_SZ];
+	uint64_t pred_buf_dma;
+	uint64_t mv_buf_dma[H264_MAX_FB_NUM];
+	struct h264_ring_fb_list list_free;
+	struct h264_ring_fb_list list_disp;
+	struct vdec_h264_dec_info dec;
+	struct vdec_pic_info pic;
+	struct v4l2_rect crop;
+};
+
+/**
+ * struct vdec_h264_inst - h264 decoder instance
+ * @num_nalu : how many nalus be decoded
+ * @ctx      : point to mtk_vcodec_ctx
+ * @pred_buf : HW working predication buffer
+ * @mv_buf   : HW working motion vector buffer
+ * @vpu      : VPU instance
+ * @vsi      : VPU shared information
+ */
+struct vdec_h264_inst {
+	unsigned int num_nalu;
+	struct mtk_vcodec_ctx *ctx;
+	struct mtk_vcodec_mem pred_buf;
+	struct mtk_vcodec_mem mv_buf[H264_MAX_FB_NUM];
+	struct vdec_vpu_inst vpu;
+	struct vdec_h264_vsi *vsi;
+};
+
+static unsigned int get_mv_buf_size(unsigned int width, unsigned int height)
+{
+	return HW_MB_STORE_SZ * (width/MB_UNIT_LEN) * (height/MB_UNIT_LEN);
+}
+
+static int allocate_predication_buf(struct vdec_h264_inst *inst)
+{
+	int err = 0;
+
+	inst->pred_buf.size = BUF_PREDICTION_SZ;
+	err = mtk_vcodec_mem_alloc(inst->ctx, &inst->pred_buf);
+	if (err) {
+		mtk_vcodec_err(inst, "failed to allocate ppl buf");
+		return err;
+	}
+
+	inst->vsi->pred_buf_dma = inst->pred_buf.dma_addr;
+	return 0;
+}
+
+static void free_predication_buf(struct vdec_h264_inst *inst)
+{
+	struct mtk_vcodec_mem *mem = NULL;
+
+	mtk_vcodec_debug_enter(inst);
+
+	inst->vsi->pred_buf_dma = 0;
+	mem = &inst->pred_buf;
+	if (mem->va)
+		mtk_vcodec_mem_free(inst->ctx, mem);
+}
+
+static int alloc_mv_buf(struct vdec_h264_inst *inst, struct vdec_pic_info *pic)
+{
+	int i;
+	int err;
+	struct mtk_vcodec_mem *mem = NULL;
+	unsigned int buf_sz = get_mv_buf_size(pic->buf_w, pic->buf_h);
+
+	for (i = 0; i < H264_MAX_FB_NUM; i++) {
+		mem = &inst->mv_buf[i];
+		if (mem->va)
+			mtk_vcodec_mem_free(inst->ctx, mem);
+		mem->size = buf_sz;
+		err = mtk_vcodec_mem_alloc(inst->ctx, mem);
+		if (err) {
+			mtk_vcodec_err(inst, "failed to allocate mv buf");
+			return err;
+		}
+		inst->vsi->mv_buf_dma[i] = mem->dma_addr;
+	}
+
+	return 0;
+}
+
+static void free_mv_buf(struct vdec_h264_inst *inst)
+{
+	int i;
+	struct mtk_vcodec_mem *mem = NULL;
+
+	for (i = 0; i < H264_MAX_FB_NUM; i++) {
+		inst->vsi->mv_buf_dma[i] = 0;
+		mem = &inst->mv_buf[i];
+		if (mem->va)
+			mtk_vcodec_mem_free(inst->ctx, mem);
+	}
+}
+
+static int check_list_validity(struct vdec_h264_inst *inst, bool disp_list)
+{
+	struct h264_ring_fb_list *list;
+
+	list = disp_list ? &inst->vsi->list_disp : &inst->vsi->list_free;
+
+	if (list->count > H264_MAX_FB_NUM ||
+	    list->read_idx >= H264_MAX_FB_NUM ||
+	    list->write_idx >= H264_MAX_FB_NUM) {
+		mtk_vcodec_err(inst, "%s list err: cnt=%d r_idx=%d w_idx=%d",
+			       disp_list ? "disp" : "free", list->count,
+			       list->read_idx, list->write_idx);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void put_fb_to_free(struct vdec_h264_inst *inst, struct vdec_fb *fb)
+{
+	struct h264_ring_fb_list *list;
+
+	if (fb) {
+		if (check_list_validity(inst, false))
+			return;
+
+		list = &inst->vsi->list_free;
+		if (list->count == H264_MAX_FB_NUM) {
+			mtk_vcodec_err(inst, "[FB] put fb free_list full");
+			return;
+		}
+
+		mtk_vcodec_debug(inst, "[FB] put fb into free_list @(%p, %llx)",
+				 fb->base_y.va, (u64)fb->base_y.dma_addr);
+
+		list->fb_list[list->write_idx].vdec_fb_va = (u64)fb;
+		list->write_idx = (list->write_idx == H264_MAX_FB_NUM - 1) ?
+				  0 : list->write_idx + 1;
+		list->count++;
+	}
+}
+
+static void get_pic_info(struct vdec_h264_inst *inst,
+			 struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
+			 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
+	mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+			 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = inst->vsi->crop.left;
+	cr->top = inst->vsi->crop.top;
+	cr->width = inst->vsi->crop.width;
+	cr->height = inst->vsi->crop.height;
+
+	mtk_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d",
+			 cr->left, cr->top, cr->width, cr->height);
+}
+
+static void get_dpb_size(struct vdec_h264_inst *inst, unsigned int *dpb_sz)
+{
+	*dpb_sz = inst->vsi->dec.dpb_sz;
+	mtk_vcodec_debug(inst, "sz=%d", *dpb_sz);
+}
+
+static int vdec_h264_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_h264_inst *inst = NULL;
+	int err;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->ctx = ctx;
+
+	inst->vpu.id = IPI_VDEC_H264;
+	inst->vpu.dev = ctx->dev->vpu_plat_dev;
+	inst->vpu.ctx = ctx;
+	inst->vpu.handler = vpu_dec_ipi_handler;
+
+	err = vpu_dec_init(&inst->vpu);
+	if (err) {
+		mtk_vcodec_err(inst, "vdec_h264 init err=%d", err);
+		goto error_free_inst;
+	}
+
+	inst->vsi = (struct vdec_h264_vsi *)inst->vpu.vsi;
+	err = allocate_predication_buf(inst);
+	if (err)
+		goto error_deinit;
+
+	mtk_vcodec_debug(inst, "H264 Instance >> %p", inst);
+
+	*h_vdec = (unsigned long)inst;
+	return 0;
+
+error_deinit:
+	vpu_dec_deinit(&inst->vpu);
+
+error_free_inst:
+	kfree(inst);
+	return err;
+}
+
+static void vdec_h264_deinit(unsigned long h_vdec)
+{
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+
+	mtk_vcodec_debug_enter(inst);
+
+	vpu_dec_deinit(&inst->vpu);
+	free_predication_buf(inst);
+	free_mv_buf(inst);
+
+	kfree(inst);
+}
+
+static int find_start_code(unsigned char *data, unsigned int data_sz)
+{
+	if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1)
+		return 3;
+
+	if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 &&
+	    data[3] == 1)
+		return 4;
+
+	return -1;
+}
+
+static int vdec_h264_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+			    struct vdec_fb *fb, bool *res_chg)
+{
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+	struct vdec_vpu_inst *vpu = &inst->vpu;
+	int nal_start_idx = 0;
+	int err = 0;
+	unsigned int nal_start;
+	unsigned int nal_type;
+	unsigned char *buf;
+	unsigned int buf_sz;
+	unsigned int data[2];
+	uint64_t vdec_fb_va = (u64)fb;
+	uint64_t y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
+	uint64_t c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
+
+	mtk_vcodec_debug(inst, "+ [%d] FB y_dma=%llx c_dma=%llx va=%p",
+			 ++inst->num_nalu, y_fb_dma, c_fb_dma, fb);
+
+	/* bs NULL means flush decoder */
+	if (bs == NULL)
+		return vpu_dec_reset(vpu);
+
+	buf = (unsigned char *)bs->va;
+	buf_sz = bs->size;
+	nal_start_idx = find_start_code(buf, buf_sz);
+	if (nal_start_idx < 0)
+		goto err_free_fb_out;
+
+	nal_start = buf[nal_start_idx];
+	nal_type = NAL_TYPE(buf[nal_start_idx]);
+	mtk_vcodec_debug(inst, "\n + NALU[%d] type %d +\n", inst->num_nalu,
+			 nal_type);
+
+	if (nal_type == NAL_H264_PPS) {
+		buf_sz -= nal_start_idx;
+		if (buf_sz > HDR_PARSING_BUF_SZ) {
+			err = -EILSEQ;
+			goto err_free_fb_out;
+		}
+		memcpy(inst->vsi->hdr_buf, buf + nal_start_idx, buf_sz);
+	}
+
+	inst->vsi->dec.bs_dma = (uint64_t)bs->dma_addr;
+	inst->vsi->dec.y_fb_dma = y_fb_dma;
+	inst->vsi->dec.c_fb_dma = c_fb_dma;
+	inst->vsi->dec.vdec_fb_va = vdec_fb_va;
+
+	data[0] = buf_sz;
+	data[1] = nal_start;
+	err = vpu_dec_start(vpu, data, 2);
+	if (err)
+		goto err_free_fb_out;
+
+	*res_chg = inst->vsi->dec.resolution_changed;
+	if (*res_chg) {
+		struct vdec_pic_info pic;
+
+		mtk_vcodec_debug(inst, "- resolution changed -");
+		get_pic_info(inst, &pic);
+
+		if (inst->vsi->dec.realloc_mv_buf) {
+			err = alloc_mv_buf(inst, &pic);
+			if (err)
+				goto err_free_fb_out;
+		}
+	}
+
+	if (nal_type == NAL_NON_IDR_SLICE || nal_type == NAL_IDR_SLICE) {
+		/* wait decoder done interrupt */
+		err = mtk_vcodec_wait_for_done_ctx(inst->ctx,
+						   MTK_INST_IRQ_RECEIVED,
+						   WAIT_INTR_TIMEOUT_MS);
+		if (err)
+			goto err_free_fb_out;
+
+		vpu_dec_end(vpu);
+	}
+
+	mtk_vcodec_debug(inst, "\n - NALU[%d] type=%d -\n", inst->num_nalu,
+			 nal_type);
+	return 0;
+
+err_free_fb_out:
+	put_fb_to_free(inst, fb);
+	mtk_vcodec_err(inst, "\n - NALU[%d] err=%d -\n", inst->num_nalu, err);
+	return err;
+}
+
+static void vdec_h264_get_fb(struct vdec_h264_inst *inst,
+			     struct h264_ring_fb_list *list,
+			     bool disp_list, struct vdec_fb **out_fb)
+{
+	struct vdec_fb *fb;
+
+	if (check_list_validity(inst, disp_list))
+		return;
+
+	if (list->count == 0) {
+		mtk_vcodec_debug(inst, "[FB] there is no %s fb",
+				 disp_list ? "disp" : "free");
+		*out_fb = NULL;
+		return;
+	}
+
+	fb = (struct vdec_fb *)list->fb_list[list->read_idx].vdec_fb_va;
+	fb->status |= (disp_list ? FB_ST_DISPLAY : FB_ST_FREE);
+
+	*out_fb = fb;
+	mtk_vcodec_debug(inst, "[FB] get %s fb st=%d poc=%d %llx",
+			 disp_list ? "disp" : "free",
+			 fb->status, list->fb_list[list->read_idx].poc,
+			 list->fb_list[list->read_idx].vdec_fb_va);
+
+	list->read_idx = (list->read_idx == H264_MAX_FB_NUM - 1) ?
+			 0 : list->read_idx + 1;
+	list->count--;
+}
+
+static int vdec_h264_get_param(unsigned long h_vdec,
+			       enum vdec_get_param_type type, void *out)
+{
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+
+	switch (type) {
+	case GET_PARAM_DISP_FRAME_BUFFER:
+		vdec_h264_get_fb(inst, &inst->vsi->list_disp, true, out);
+		break;
+
+	case GET_PARAM_FREE_FRAME_BUFFER:
+		vdec_h264_get_fb(inst, &inst->vsi->list_free, false, out);
+		break;
+
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		get_dpb_size(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+
+	default:
+		mtk_vcodec_err(inst, "invalid get parameter type=%d", type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct vdec_common_if vdec_h264_if = {
+	vdec_h264_init,
+	vdec_h264_decode,
+	vdec_h264_get_param,
+	vdec_h264_deinit,
+};
+
+struct vdec_common_if *get_h264_dec_comm_if(void);
+
+struct vdec_common_if *get_h264_dec_comm_if(void)
+{
+	return &vdec_h264_if;
+}
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
index 8202b14..e61f541 100644
--- a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
@@ -24,12 +24,16 @@
 #include "mtk_vcodec_util.h"
 #include "mtk_vpu.h"
 
+struct vdec_common_if *get_h264_dec_comm_if(void);
+
 int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
 {
 	int ret = 0;
 
 	switch (fourcc) {
 	case V4L2_PIX_FMT_H264:
+		ctx->dec_if = get_h264_dec_comm_if();
+		break;
 	case V4L2_PIX_FMT_VP8:
 	case V4L2_PIX_FMT_VP9:
 	default:
diff --git a/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
new file mode 100644
index 0000000..0798a6b
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_util.h"
+#include "vdec_ipi_msg.h"
+#include "vdec_vpu_if.h"
+
+static void handle_init_ack_msg(struct vdec_vpu_ipi_init_ack *msg)
+{
+	struct vdec_vpu_inst *vpu = (struct vdec_vpu_inst *)msg->ap_inst_addr;
+
+	mtk_vcodec_debug(vpu, "+ ap_inst_addr = 0x%llx", msg->ap_inst_addr);
+
+	/* mapping VPU address to kernel virtual address */
+	/* the content in vsi is initialized to 0 in VPU */
+	vpu->vsi = vpu_mapping_dm_addr(vpu->dev, msg->vpu_inst_addr);
+	vpu->inst_addr = msg->vpu_inst_addr;
+
+	mtk_vcodec_debug(vpu, "- vpu_inst_addr = 0x%x", vpu->inst_addr);
+}
+
+/*
+ * This function runs in interrupt context and it means there's an IPI MSG
+ * from VPU.
+ */
+void vpu_dec_ipi_handler(void *data, unsigned int len, void *priv)
+{
+	struct vdec_vpu_ipi_ack *msg = data;
+	struct vdec_vpu_inst *vpu = (struct vdec_vpu_inst *)msg->ap_inst_addr;
+
+	mtk_vcodec_debug(vpu, "+ id=%X", msg->msg_id);
+
+	if (msg->status == 0) {
+		switch (msg->msg_id) {
+		case VPU_IPIMSG_DEC_INIT_ACK:
+			handle_init_ack_msg(data);
+			break;
+
+		case VPU_IPIMSG_DEC_START_ACK:
+		case VPU_IPIMSG_DEC_END_ACK:
+		case VPU_IPIMSG_DEC_DEINIT_ACK:
+		case VPU_IPIMSG_DEC_RESET_ACK:
+			break;
+
+		default:
+			mtk_vcodec_err(vpu, "invalid msg=%X", msg->msg_id);
+			break;
+		}
+	}
+
+	mtk_vcodec_debug(vpu, "- id=%X", msg->msg_id);
+	vpu->failure = msg->status;
+	vpu->signaled = 1;
+}
+
+static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, void *msg, int len)
+{
+	int err;
+	uint32_t msg_id = *(uint32_t *)msg;
+
+	mtk_vcodec_debug(vpu, "id=%X", msg_id);
+
+	vpu->failure = 0;
+	vpu->signaled = 0;
+
+	err = vpu_ipi_send(vpu->dev, vpu->id, msg, len);
+	if (err) {
+		mtk_vcodec_err(vpu, "send fail vpu_id=%d msg_id=%X status=%d",
+			       vpu->id, msg_id, err);
+		return err;
+	}
+
+	return vpu->failure;
+}
+
+static int vcodec_send_ap_ipi(struct vdec_vpu_inst *vpu, unsigned int msg_id)
+{
+	struct vdec_ap_ipi_cmd msg;
+	int err = 0;
+
+	mtk_vcodec_debug(vpu, "+ id=%X", msg_id);
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_id = msg_id;
+	msg.vpu_inst_addr = vpu->inst_addr;
+
+	err = vcodec_vpu_send_msg(vpu, &msg, sizeof(msg));
+	mtk_vcodec_debug(vpu, "- id=%X ret=%d", msg_id, err);
+	return err;
+}
+
+int vpu_dec_init(struct vdec_vpu_inst *vpu)
+{
+	struct vdec_ap_ipi_init msg;
+	int err;
+
+	mtk_vcodec_debug_enter(vpu);
+
+	init_waitqueue_head(&vpu->wq);
+
+	err = vpu_ipi_register(vpu->dev, vpu->id, vpu->handler, "vdec", NULL);
+	if (err != 0) {
+		mtk_vcodec_err(vpu, "vpu_ipi_register fail status=%d", err);
+		return err;
+	}
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_id = AP_IPIMSG_DEC_INIT;
+	msg.ap_inst_addr = (unsigned long)vpu;
+
+	mtk_vcodec_debug(vpu, "vdec_inst=%p", vpu);
+
+	err = vcodec_vpu_send_msg(vpu, (void *)&msg, sizeof(msg));
+	mtk_vcodec_debug(vpu, "- ret=%d", err);
+	return err;
+}
+
+int vpu_dec_start(struct vdec_vpu_inst *vpu, uint32_t *data, unsigned int len)
+{
+	struct vdec_ap_ipi_dec_start msg;
+	int i;
+	int err = 0;
+
+	mtk_vcodec_debug_enter(vpu);
+
+	if (len > ARRAY_SIZE(msg.data)) {
+		mtk_vcodec_err(vpu, "invalid len = %d\n", len);
+		return -EINVAL;
+	}
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_id = AP_IPIMSG_DEC_START;
+	msg.vpu_inst_addr = vpu->inst_addr;
+
+	for (i = 0; i < len; i++)
+		msg.data[i] = data[i];
+
+	err = vcodec_vpu_send_msg(vpu, (void *)&msg, sizeof(msg));
+	mtk_vcodec_debug(vpu, "- ret=%d", err);
+	return err;
+}
+
+int vpu_dec_end(struct vdec_vpu_inst *vpu)
+{
+	return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_END);
+}
+
+int vpu_dec_deinit(struct vdec_vpu_inst *vpu)
+{
+	return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_DEINIT);
+}
+
+int vpu_dec_reset(struct vdec_vpu_inst *vpu)
+{
+	return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_RESET);
+}
diff --git a/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h
new file mode 100644
index 0000000..8dcc1cb
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VDEC_VPU_IF_H_
+#define _VDEC_VPU_IF_H_
+
+#include "mtk_vpu.h"
+
+/**
+ * struct vdec_vpu_inst - VPU instance for video codec
+ * @ipi_id      : ipi id for each decoder
+ * @vsi         : driver structure allocated by VPU side and shared to AP side
+ *                for control and info share
+ * @failure     : VPU execution result status, 0: success, others: fail
+ * @inst_addr	: VPU decoder instance address
+ * @signaled    : 1 - Host has received ack message from VPU, 0 - not received
+ * @ctx         : context for v4l2 layer integration
+ * @dev	        : platform device of VPU
+ * @wq          : wait queue to wait VPU message ack
+ * @handler     : ipi handler for each decoder
+ */
+struct vdec_vpu_inst {
+	enum ipi_id id;
+	void *vsi;
+	int32_t failure;
+	uint32_t inst_addr;
+	unsigned int signaled;
+	struct mtk_vcodec_ctx *ctx;
+	struct platform_device *dev;
+	wait_queue_head_t wq;
+	ipi_handler_t handler;
+};
+
+/**
+ * vpu_dec_init - init decoder instance and allocate required resource in VPU.
+ *
+ * @vpu: instance for vdec_vpu_inst
+ */
+int vpu_dec_init(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_start - start decoding, basically the function will be invoked once
+ *                 every frame.
+ *
+ * @vpu : instance for vdec_vpu_inst
+ * @data: meta data to pass bitstream info to VPU decoder
+ * @len : meta data length
+ */
+int vpu_dec_start(struct vdec_vpu_inst *vpu, uint32_t *data, unsigned int len);
+
+/**
+ * vpu_dec_end - end decoding, basically the function will be invoked once
+ *               when HW decoding done interrupt received successfully. The
+ *               decoder in VPU will continute to do referene frame management
+ *               and check if there is a new decoded frame available to display.
+ *
+ * @vpu : instance for vdec_vpu_inst
+ */
+int vpu_dec_end(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_deinit - deinit decoder instance and resource freed in VPU.
+ *
+ * @vpu: instance for vdec_vpu_inst
+ */
+int vpu_dec_deinit(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_reset - reset decoder, use for flush decoder when end of stream or
+ *                 seek. Remainig non displayed frame will be pushed to display.
+ *
+ * @vpu: instance for vdec_vpu_inst
+ */
+int vpu_dec_reset(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_ipi_handler - Handler for VPU ipi message.
+ *
+ * @data: ipi message
+ * @len : length of ipi message
+ * @priv: callback private data whcih is passed by decoder when register.
+ */
+void vpu_dec_ipi_handler(void *data, unsigned int len, void *priv);
+
+#endif
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Mon May 30 05:29:19 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Mon, 30 May 2016 20:29:19 +0800
Subject: [PATCH v3 5/9] vcodec: mediatek: Add Mediatek V4L2 Video Decoder
 Driver
In-Reply-To: <1464611363-14936-5-git-send-email-tiffany.lin@mediatek.com>
References: <1464611363-14936-1-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-2-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-3-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-4-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-5-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1464611363-14936-6-git-send-email-tiffany.lin@mediatek.com>

Add v4l2 layer decoder driver for MT8173

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
---
 drivers/media/platform/mtk-vcodec/Makefile         |   10 +-
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 1348 ++++++++++++++++++++
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h |   88 ++
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c |  408 ++++++
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c  |  206 +++
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h  |   28 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h |   88 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_intr.c    |    4 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_intr.h    |    2 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_util.c    |   31 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_util.h    |    7 +-
 drivers/media/platform/mtk-vcodec/vdec_drv_base.h  |   56 +
 drivers/media/platform/mtk-vcodec/vdec_drv_if.c    |  107 ++
 drivers/media/platform/mtk-vcodec/vdec_drv_if.h    |  101 ++
 drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h   |  103 ++
 15 files changed, 2569 insertions(+), 18 deletions(-)
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
 create mode 100644 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_drv_base.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_drv_if.c
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_drv_if.h
 create mode 100644 drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h

diff --git a/drivers/media/platform/mtk-vcodec/Makefile b/drivers/media/platform/mtk-vcodec/Makefile
index dc5cb00..4c8ed2f 100644
--- a/drivers/media/platform/mtk-vcodec/Makefile
+++ b/drivers/media/platform/mtk-vcodec/Makefile
@@ -1,7 +1,13 @@
 
 
-obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-enc.o mtk-vcodec-common.o
-
+obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
+				       mtk-vcodec-enc.o \
+				       mtk-vcodec-common.o
+
+mtk-vcodec-dec-y := mtk_vcodec_dec_drv.o \
+		vdec_drv_if.o \
+		mtk_vcodec_dec.o \
+		mtk_vcodec_dec_pm.o \
 
 
 mtk-vcodec-enc-y := venc/venc_vp8_if.o \
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
new file mode 100644
index 0000000..792858a
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
@@ -0,0 +1,1348 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen at mediatek.com>
+*         Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_dec.h"
+#include "mtk_vcodec_intr.h"
+#include "mtk_vcodec_util.h"
+#include "vdec_drv_if.h"
+#include "mtk_vcodec_dec_pm.h"
+
+#define OUT_FMT_IDX	0
+#define CAP_FMT_IDX	3
+
+#define MTK_VDEC_MIN_W	64U
+#define MTK_VDEC_MIN_H	64U
+#define DFT_CFG_WIDTH	MTK_VDEC_MIN_W
+#define DFT_CFG_HEIGHT	MTK_VDEC_MIN_H
+
+static struct mtk_video_fmt mtk_video_formats[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_H264,
+		.type = MTK_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP8,
+		.type = MTK_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP9,
+		.type = MTK_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_MT21,
+		.type = MTK_FMT_FRAME,
+		.num_planes = 2,
+	},
+};
+
+static const struct mtk_codec_framesizes mtk_vdec_framesizes[] = {
+	{
+		.fourcc	= V4L2_PIX_FMT_H264,
+		.stepwise = {  MTK_VDEC_MIN_W, MTK_VDEC_MAX_W, 16,
+				MTK_VDEC_MIN_H, MTK_VDEC_MAX_H, 16 },
+	},
+	{
+		.fourcc	= V4L2_PIX_FMT_VP8,
+		.stepwise = {  MTK_VDEC_MIN_W, MTK_VDEC_MAX_W, 16,
+				MTK_VDEC_MIN_H, MTK_VDEC_MAX_H, 16 },
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP9,
+		.stepwise = {  MTK_VDEC_MIN_W, MTK_VDEC_MAX_W, 16,
+				MTK_VDEC_MIN_H, MTK_VDEC_MAX_H, 16 },
+	},
+};
+
+#define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(mtk_vdec_framesizes)
+#define NUM_FORMATS ARRAY_SIZE(mtk_video_formats)
+
+static struct mtk_video_fmt *mtk_vdec_find_format(struct v4l2_format *f)
+{
+	struct mtk_video_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < NUM_FORMATS; k++) {
+		fmt = &mtk_video_formats[k];
+		if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static struct mtk_q_data *mtk_vdec_get_q_data(struct mtk_vcodec_ctx *ctx,
+					      enum v4l2_buf_type type)
+{
+	if (V4L2_TYPE_IS_OUTPUT(type))
+		return &ctx->q_data[MTK_Q_DATA_SRC];
+
+	return &ctx->q_data[MTK_Q_DATA_DST];
+}
+
+/* This function is try to clean all display buffer, the buffer will return in
+ * display order.
+ * Note the buffer return from codec driver may still in driver's reference
+ * list.
+ */
+static struct vb2_buffer *get_display_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct vdec_fb *disp_frame_buffer = NULL;
+	struct mtk_video_dec_buf *dstbuf;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+	if (vdec_if_get_param(ctx,
+			GET_PARAM_DISP_FRAME_BUFFER,
+			&disp_frame_buffer)) {
+		mtk_v4l2_err("[%d]Cannot get param : GET_PARAM_DISP_FRAME_BUFFER",
+			ctx->id);
+		return NULL;
+	}
+
+	if (disp_frame_buffer == NULL) {
+		mtk_v4l2_debug(3, "No display frame buffer");
+		return NULL;
+	}
+
+	dstbuf = container_of(disp_frame_buffer, struct mtk_video_dec_buf,
+				frame_buffer);
+	mutex_lock(&ctx->lock);
+	if (dstbuf->used) {
+		vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0,
+					ctx->picinfo.y_bs_sz);
+		vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1,
+					ctx->picinfo.c_bs_sz);
+
+		dstbuf->ready_to_display = true;
+
+		mtk_v4l2_debug(2,
+				"[%d]status=%x queue id=%d to done_list %d",
+				ctx->id, disp_frame_buffer->status,
+				dstbuf->vb.vb2_buf.index,
+				dstbuf->queued_in_vb2);
+
+		v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE);
+		ctx->decoded_frame_cnt++;
+	}
+	mutex_unlock(&ctx->lock);
+	return &dstbuf->vb.vb2_buf;
+}
+
+/* This function is try to clean all capture buffers that is not used as
+ * reference buffer by codec driver any more
+ * In this case, we need re-queue buffer to vb2 buffer if user space
+ * already return this buffer to v4l2 or this buffer is just the output of
+ * previous sps/pps/resolution change decode, or do nothing if user
+ * space still own this buffer
+ */
+static struct vb2_buffer *get_free_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct mtk_video_dec_buf *dstbuf;
+	struct vdec_fb *free_frame_buffer = NULL;
+
+	if (vdec_if_get_param(ctx,
+				GET_PARAM_FREE_FRAME_BUFFER,
+				&free_frame_buffer)) {
+		mtk_v4l2_err("[%d] Error!! Cannot get param", ctx->id);
+		return NULL;
+	}
+	if (free_frame_buffer == NULL) {
+		mtk_v4l2_debug(3, " No free frame buffer");
+		return NULL;
+	}
+
+	mtk_v4l2_debug(3, "[%d] tmp_frame_addr = 0x%p",
+			ctx->id, free_frame_buffer);
+
+	dstbuf = container_of(free_frame_buffer, struct mtk_video_dec_buf,
+				frame_buffer);
+
+	mutex_lock(&ctx->lock);
+	if (dstbuf->used) {
+		if ((dstbuf->queued_in_vb2) &&
+		    (dstbuf->queued_in_v4l2) &&
+		    (free_frame_buffer->status == FB_ST_FREE)) {
+			/* After decode sps/pps or non-display buffer, we dont
+			 * need to return capture buffer to user space, but
+			 * just re-queue this capture buffer to vb2 queue.
+			 * This reduce overheads that dq/q unused capture
+			 * buffer We use queued_in_vb2 to mark this buffer
+			 * is from decode output, not q from user space.
+			 */
+			mtk_v4l2_debug(2,
+				"[%d]status=%x queue id=%d to rdy_queue %d",
+				ctx->id, free_frame_buffer->status,
+				dstbuf->vb.vb2_buf.index,
+				dstbuf->queued_in_vb2);
+			v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb);
+		} else if ((dstbuf->queued_in_vb2 == false) &&
+			   (dstbuf->queued_in_v4l2 == true)) {
+			/* If buffer in v4l2 driver but not in vb2 queue yet,
+			 * and we get this buffer from free_list, it means
+			 * that codec driver do not use this buffer as
+			 * reference buffer anymore. We should q buffer to vb2
+			 * queue, so later work thread could get this buffer
+			 * for decode In this sate, queued_in_vb2 = false
+			 * menas this buffer is not from previous decode output
+			 */
+			mtk_v4l2_debug(2,
+					"[%d]status=%x queue id=%d to rdy_queue",
+					ctx->id, free_frame_buffer->status,
+					dstbuf->vb.vb2_buf.index);
+			v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb);
+			dstbuf->queued_in_vb2 = true;
+		} else {
+			/* Codec driver do not need to reference this capture
+			 * buffer and this buffer is not in v4l2 driver.
+			 * Then we dont need to do any thing, just add log when
+			 * we need to debug buffer flow.
+			 * When this buffer q from user space, it could
+			 * directly q to vb2 buffer
+			 */
+			mtk_v4l2_debug(3, "[%d]status=%x err queue id=%d %d %d",
+					ctx->id, free_frame_buffer->status,
+					dstbuf->vb.vb2_buf.index,
+					dstbuf->queued_in_vb2,
+					dstbuf->queued_in_v4l2);
+		}
+		dstbuf->used = false;
+	}
+	mutex_unlock(&ctx->lock);
+	return &dstbuf->vb.vb2_buf;
+}
+
+static void clean_display_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct vb2_buffer *framptr;
+
+	do {
+		framptr = get_display_buffer(ctx);
+	} while (framptr);
+}
+
+static void clean_free_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct vb2_buffer *framptr;
+
+	do {
+		framptr = get_free_buffer(ctx);
+	} while (framptr);
+}
+
+static int mtk_vdec_queue_res_chg_event(struct mtk_vcodec_ctx *ctx)
+{
+	static const struct v4l2_event ev_src_ch = {
+		.type = V4L2_EVENT_SOURCE_CHANGE,
+		.u.src_change.changes =
+		V4L2_EVENT_SRC_CH_RESOLUTION,
+	};
+
+	mtk_v4l2_debug(1, "[%d]", ctx->id);
+	v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
+
+	return 0;
+}
+
+static void mtk_vdec_flush_decoder(struct mtk_vcodec_ctx *ctx)
+{
+	bool res_chg;
+	int ret = 0;
+
+	ret = vdec_if_decode(ctx, NULL, NULL, &res_chg);
+	if (ret)
+		mtk_v4l2_err("DecodeFinal failed, ret=%d", ret);
+
+	clean_display_buffer(ctx);
+	clean_free_buffer(ctx);
+}
+
+static void mtk_vdec_pic_info_update(struct mtk_vcodec_ctx *ctx)
+{
+	unsigned int dpbsize = 0;
+	int ret;
+
+	if (vdec_if_get_param(ctx,
+				GET_PARAM_PIC_INFO,
+				&ctx->last_decoded_picinfo)) {
+		mtk_v4l2_err("[%d]Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR",
+				ctx->id);
+		return;
+	}
+
+	if (ctx->last_decoded_picinfo.pic_w == 0 ||
+		ctx->last_decoded_picinfo.pic_h == 0 ||
+		ctx->last_decoded_picinfo.buf_w == 0 ||
+		ctx->last_decoded_picinfo.buf_h == 0) {
+		mtk_v4l2_err("Cannot get correct pic info");
+		return;
+	}
+
+	if ((ctx->last_decoded_picinfo.pic_w == ctx->picinfo.pic_w) ||
+	    (ctx->last_decoded_picinfo.pic_h == ctx->picinfo.pic_h))
+		return;
+
+	mtk_v4l2_debug(1,
+			"[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)",
+			ctx->id, ctx->last_decoded_picinfo.pic_w,
+			ctx->last_decoded_picinfo.pic_h,
+			ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+			ctx->last_decoded_picinfo.buf_w,
+			ctx->last_decoded_picinfo.buf_h);
+
+	ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize);
+	if (dpbsize == 0)
+		mtk_v4l2_err("Incorrect dpb size, ret=%d", ret);
+
+	ctx->dpb_size = dpbsize;
+}
+
+static void mtk_vdec_worker(struct work_struct *work)
+{
+	struct mtk_vcodec_ctx *ctx = container_of(work, struct mtk_vcodec_ctx,
+				decode_work);
+	struct mtk_vcodec_dev *dev = ctx->dev;
+	struct vb2_buffer *src_buf, *dst_buf;
+	struct mtk_vcodec_mem buf;
+	struct vdec_fb *pfb;
+	bool res_chg = false;
+	int ret;
+	struct mtk_video_dec_buf *dst_buf_info, *src_buf_info;
+	struct vb2_v4l2_buffer *dst_vb2_v4l2, *src_vb2_v4l2;
+
+	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+	if (src_buf == NULL) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_v4l2_debug(1, "[%d] src_buf empty!!", ctx->id);
+		return;
+	}
+
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+	if (dst_buf == NULL) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_v4l2_debug(1, "[%d] dst_buf empty!!", ctx->id);
+		return;
+	}
+
+	src_vb2_v4l2 = container_of(src_buf, struct vb2_v4l2_buffer, vb2_buf);
+	src_buf_info = container_of(src_vb2_v4l2, struct mtk_video_dec_buf, vb);
+
+	dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf);
+	dst_buf_info = container_of(dst_vb2_v4l2, struct mtk_video_dec_buf, vb);
+
+	buf.va = vb2_plane_vaddr(src_buf, 0);
+	buf.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+	buf.size = (size_t)src_buf->planes[0].bytesused;
+	if (!buf.va) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_v4l2_err("[%d] id=%d src_addr is NULL!!",
+				ctx->id, src_buf->index);
+		return;
+	}
+
+	pfb = &dst_buf_info->frame_buffer;
+	pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0);
+	pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+	pfb->base_y.size = ctx->picinfo.y_bs_sz + ctx->picinfo.y_len_sz;
+
+	pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1);
+	pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1);
+	pfb->base_c.size = ctx->picinfo.c_bs_sz + ctx->picinfo.c_len_sz;
+	pfb->status = 0;
+	mtk_v4l2_debug(3, "===>[%d] vdec_if_decode() ===>", ctx->id);
+	mtk_v4l2_debug(3, "[%d] Bitstream VA=%p DMA=%llx Size=0x%lx vb=%p",
+			ctx->id, buf.va, (u64)buf.dma_addr, buf.size, src_buf);
+
+	mtk_v4l2_debug(3,
+			"id=%d Framebuf  pfb=%p VA=%p Y_DMA=%llx C_DMA=%llx Size=0x%lx",
+			dst_buf->index, pfb,
+			pfb->base_y.va, (u64)pfb->base_y.dma_addr,
+			(u64)pfb->base_c.dma_addr, pfb->base_y.size);
+
+	if (src_buf_info->lastframe) {
+		/* update src buf status */
+		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		src_buf_info->lastframe = false;
+		v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE);
+
+		/* update dst buf status */
+		dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+		dst_buf_info->used = false;
+
+		vdec_if_decode(ctx, NULL, NULL, &res_chg);
+		clean_display_buffer(ctx);
+		vb2_set_plane_payload(&dst_buf_info->vb.vb2_buf, 0, 0);
+		vb2_set_plane_payload(&dst_buf_info->vb.vb2_buf, 1, 0);
+		v4l2_m2m_buf_done(&dst_buf_info->vb, VB2_BUF_STATE_DONE);
+		clean_free_buffer(ctx);
+	} else {
+		dst_buf_info->vb.vb2_buf.timestamp
+				= src_buf_info->vb.vb2_buf.timestamp;
+		dst_buf_info->vb.timecode
+				= src_buf_info->vb.timecode;
+		mutex_lock(&ctx->lock);
+		dst_buf_info->used = true;
+		mutex_unlock(&ctx->lock);
+		src_buf_info->used = true;
+
+		ret = vdec_if_decode(ctx, &buf, pfb, &res_chg);
+
+		if (ret) {
+			mtk_v4l2_err(
+				" <===[%d], src_buf[%d]%d sz=0x%zx pts=%llu dst_buf[%d] vdec_if_decode() ret=%d res_chg=%d===>",
+				ctx->id,
+				src_buf->index,
+				src_buf_info->lastframe,
+				buf.size,
+				src_buf_info->vb.vb2_buf.timestamp,
+				dst_buf->index,
+				ret, res_chg);
+			src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+			v4l2_m2m_buf_done(&src_buf_info->vb,
+					VB2_BUF_STATE_ERROR);
+		} else if (res_chg == false) {
+			/* we only return src buffer with VB2_BUF_STATE_DONE
+			  * when decode success without resolution change
+			  */
+			src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+			v4l2_m2m_buf_done(&src_buf_info->vb,
+					VB2_BUF_STATE_DONE);
+		}
+
+		dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+		clean_display_buffer(ctx);
+		clean_free_buffer(ctx);
+
+		if (!ret && res_chg) {
+			mtk_vdec_pic_info_update(ctx);
+			/*
+			 * On encountering a resolution change in the stream.
+			 * The driver must first process and decode all
+			 * remaining buffers from before the resolution change
+			 * point, so call flush decode here
+			 */
+			mtk_vdec_flush_decoder(ctx);
+			/*
+			 * After all buffers containing decoded frames from
+			 * before the resolution change point ready to be
+			 * dequeued on the CAPTURE queue, the driver sends a
+			 * V4L2_EVENT_SOURCE_CHANGE event for source change
+			 * type V4L2_EVENT_SRC_CH_RESOLUTION
+			 */
+			mtk_vdec_queue_res_chg_event(ctx);
+		}
+	}
+
+	v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+}
+
+void mtk_vdec_unlock(struct mtk_vcodec_ctx *ctx)
+{
+	mutex_unlock(&ctx->dev->dec_mutex);
+}
+
+void mtk_vdec_lock(struct mtk_vcodec_ctx *ctx)
+{
+	mutex_lock(&ctx->dev->dec_mutex);
+}
+
+void mtk_vcodec_vdec_release(struct mtk_vcodec_ctx *ctx)
+{
+	vdec_if_deinit(ctx);
+	ctx->state = MTK_STATE_FREE;
+}
+
+void mtk_vcodec_dec_set_default_params(struct mtk_vcodec_ctx *ctx)
+{
+	struct mtk_q_data *q_data;
+
+	ctx->m2m_ctx->q_lock = &ctx->dev->dev_mutex;
+	ctx->fh.m2m_ctx = ctx->m2m_ctx;
+	ctx->fh.ctrl_handler = &ctx->ctrl_hdl;
+	INIT_WORK(&ctx->decode_work, mtk_vdec_worker);
+	ctx->colorspace = V4L2_COLORSPACE_REC709;
+	ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
+	ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+
+	q_data = &ctx->q_data[MTK_Q_DATA_SRC];
+	memset(q_data, 0, sizeof(struct mtk_q_data));
+	q_data->visible_width = DFT_CFG_WIDTH;
+	q_data->visible_height = DFT_CFG_HEIGHT;
+	q_data->fmt = &mtk_video_formats[OUT_FMT_IDX];
+	q_data->field = V4L2_FIELD_NONE;
+
+	ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
+		DFT_CFG_WIDTH * DFT_CFG_HEIGHT;
+	ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] = 0;
+
+	q_data = &ctx->q_data[MTK_Q_DATA_DST];
+	memset(q_data, 0, sizeof(struct mtk_q_data));
+	q_data->visible_width = DFT_CFG_WIDTH;
+	q_data->visible_height = DFT_CFG_HEIGHT;
+	q_data->coded_width = DFT_CFG_WIDTH;
+	q_data->coded_height = DFT_CFG_HEIGHT;
+	q_data->fmt = &mtk_video_formats[CAP_FMT_IDX];
+	q_data->field = V4L2_FIELD_NONE;
+
+	v4l_bound_align_image(&q_data->coded_width,
+				MTK_VDEC_MIN_W,
+				MTK_VDEC_MAX_W, 4,
+				&q_data->coded_height,
+				MTK_VDEC_MIN_H,
+				MTK_VDEC_MAX_H, 5, 6);
+
+	q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height;
+	q_data->bytesperline[0] = q_data->coded_width;
+	q_data->sizeimage[1] = q_data->sizeimage[0] / 2;
+	q_data->bytesperline[1] = q_data->coded_width;
+}
+
+static int vidioc_vdec_qbuf(struct file *file, void *priv,
+			    struct v4l2_buffer *buf)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct vb2_queue *vq;
+	struct vb2_buffer *vb;
+	struct mtk_video_dec_buf *mtkbuf;
+	struct vb2_v4l2_buffer	*vb2_v4l2;
+
+	if (ctx->state == MTK_STATE_ABORT) {
+		mtk_v4l2_err("[%d] Call on QBUF after unrecoverable error",
+				ctx->id);
+		return -EIO;
+	}
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, buf->type);
+	vb = vq->bufs[buf->index];
+	vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
+	mtkbuf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
+
+	if ((buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) &&
+	    (buf->m.planes[0].bytesused == 0)) {
+		mtkbuf->lastframe = true;
+		mtk_v4l2_debug(1, "[%d] (%d) id=%d lastframe=%d (%d,%d, %d) vb=%p",
+			 ctx->id, buf->type, buf->index,
+			 mtkbuf->lastframe, buf->bytesused,
+			 buf->m.planes[0].bytesused, buf->length,
+			 vb);
+	}
+
+	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_vdec_dqbuf(struct file *file, void *priv,
+			     struct v4l2_buffer *buf)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (ctx->state == MTK_STATE_ABORT) {
+		mtk_v4l2_err("[%d] Call on DQBUF after unrecoverable error",
+				ctx->id);
+		return -EIO;
+	}
+
+	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_vdec_querycap(struct file *file, void *priv,
+				struct v4l2_capability *cap)
+{
+	strlcpy(cap->driver, MTK_VCODEC_DEC_NAME, sizeof(cap->driver));
+	strlcpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info));
+	strlcpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card));
+
+	return 0;
+}
+
+static int vidioc_vdec_subscribe_evt(struct v4l2_fh *fh,
+				     const struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_EOS:
+		return v4l2_event_subscribe(fh, sub, 2, NULL);
+	case V4L2_EVENT_SOURCE_CHANGE:
+		return v4l2_src_change_event_subscribe(fh, sub);
+	default:
+		return v4l2_ctrl_subscribe_event(fh, sub);
+	}
+}
+
+static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct mtk_video_fmt *fmt;
+
+	fmt = mtk_vdec_find_format(f);
+	if (!fmt) {
+		f->fmt.pix.pixelformat = mtk_video_formats[CAP_FMT_IDX].fourcc;
+		fmt = mtk_vdec_find_format(f);
+	}
+
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+	struct mtk_video_fmt *fmt;
+
+	fmt = mtk_vdec_find_format(f);
+	if (!fmt) {
+		f->fmt.pix.pixelformat = mtk_video_formats[OUT_FMT_IDX].fourcc;
+		fmt = mtk_vdec_find_format(f);
+	}
+
+	if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) {
+		mtk_v4l2_err("sizeimage of output format must be given");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vidioc_vdec_g_selection(struct file *file, void *priv,
+			struct v4l2_selection *s)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (V4L2_TYPE_IS_OUTPUT(s->type))
+		return -EINVAL;
+
+	if (s->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	if (ctx->state < MTK_STATE_HEADER)
+		return -EINVAL;
+
+	if ((ctx->q_data[MTK_Q_DATA_SRC].fmt->fourcc == V4L2_PIX_FMT_H264) ||
+	    (ctx->q_data[MTK_Q_DATA_SRC].fmt->fourcc == V4L2_PIX_FMT_VP8) ||
+	    (ctx->q_data[MTK_Q_DATA_SRC].fmt->fourcc == V4L2_PIX_FMT_VP9)) {
+
+		if (vdec_if_get_param(ctx, GET_PARAM_CROP_INFO, &(s->r))) {
+			mtk_v4l2_debug(2,
+					"[%d]Error!! Cannot get param : GET_PARAM_CROP_INFO ERR",
+					ctx->id);
+			s->r.left = 0;
+			s->r.top = 0;
+			s->r.width = ctx->picinfo.buf_w;
+			s->r.height = ctx->picinfo.buf_h;
+		}
+		mtk_v4l2_debug(2, "Cropping info: l=%d t=%d w=%d h=%d",
+				s->r.left, s->r.top, s->r.width,
+				s->r.height);
+	} else {
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = ctx->picinfo.pic_w;
+		s->r.height = ctx->picinfo.pic_h;
+		mtk_v4l2_debug(2, "Cropping info: w=%d h=%d fw=%d fh=%d",
+				s->r.width, s->r.height, ctx->picinfo.buf_w,
+				ctx->picinfo.buf_h);
+	}
+	return 0;
+}
+
+static int vidioc_vdec_s_fmt(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct v4l2_pix_format_mplane *pix_mp;
+	struct mtk_q_data *q_data;
+	int ret = 0;
+	struct mtk_video_fmt *fmt;
+	struct vb2_queue *vq;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+
+	fmt = mtk_vdec_find_format(f);
+	if (fmt == NULL) {
+		mtk_v4l2_err("vidioc_vdec_s_fmt fail");
+		return ret;
+	}
+
+	pix_mp = &f->fmt.pix_mp;
+	if ((f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) &&
+	    vb2_is_busy(&ctx->m2m_ctx->out_q_ctx.q)) {
+		mtk_v4l2_err("out_q_ctx buffers already requested");
+		ret = -EBUSY;
+	}
+
+	if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+	    vb2_is_busy(&ctx->m2m_ctx->cap_q_ctx.q)) {
+		mtk_v4l2_err("cap_q_ctx buffers already requested");
+		ret = -EBUSY;
+	}
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+
+	q_data = mtk_vdec_get_q_data(ctx, f->type);
+	if (!q_data)
+		return -EINVAL;
+
+	q_data->fmt = fmt;
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
+		pix_mp->plane_fmt[0].bytesperline = 0;
+		pix_mp->width = 0;
+		pix_mp->height = 0;
+
+		if (ctx->state == MTK_STATE_FREE) {
+			ret = vdec_if_init(ctx, q_data->fmt->fourcc);
+			if (ret) {
+				mtk_v4l2_err("[%d]: vdec_if_init() fail ret=%d",
+					ctx->id, ret);
+				return -EINVAL;
+			}
+			ctx->state = MTK_STATE_INIT;
+		}
+	}
+
+	return 0;
+}
+
+static int vidioc_enum_framesizes(struct file *file, void *priv,
+				struct v4l2_frmsizeenum *fsize)
+{
+	int i = 0;
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (fsize->index != 0)
+		return -EINVAL;
+
+	for (i = 0; i < NUM_SUPPORTED_FRAMESIZE; ++i) {
+		if (fsize->pixel_format != mtk_vdec_framesizes[i].fourcc)
+			continue;
+
+		fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+		fsize->stepwise = mtk_vdec_framesizes[i].stepwise;
+		if (!(ctx->dev->dec_capability &
+				VCODEC_CAPABILITY_4K_DISABLED)) {
+			mtk_v4l2_debug(3, "4K is enabled");
+			fsize->stepwise.max_width =
+					VCODEC_DEC_4K_CODED_WIDTH;
+			fsize->stepwise.max_height =
+					VCODEC_DEC_4K_CODED_HEIGHT;
+		}
+		mtk_v4l2_debug(1, "%x, %d %d %d %d %d %d",
+				ctx->dev->dec_capability,
+				fsize->stepwise.min_width,
+				fsize->stepwise.max_width,
+				fsize->stepwise.step_width,
+				fsize->stepwise.min_height,
+				fsize->stepwise.max_height,
+				fsize->stepwise.step_height);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue)
+{
+	struct mtk_video_fmt *fmt;
+	int i, j = 0;
+
+	for (i = 0; i < NUM_FORMATS; i++) {
+		if (output_queue && (mtk_video_formats[i].type != MTK_FMT_DEC))
+			continue;
+		if (!output_queue &&
+			(mtk_video_formats[i].type != MTK_FMT_FRAME))
+			continue;
+
+		if (j == f->index)
+			break;
+		++j;
+	}
+
+	if (i == NUM_FORMATS)
+		return -EINVAL;
+
+	fmt = &mtk_video_formats[i];
+	f->pixelformat = fmt->fourcc;
+
+	return 0;
+}
+
+static int vidioc_vdec_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
+					       struct v4l2_fmtdesc *f)
+{
+	return vidioc_enum_fmt(f, false);
+}
+
+static int vidioc_vdec_enum_fmt_vid_out_mplane(struct file *file, void *priv,
+					       struct v4l2_fmtdesc *f)
+{
+	return vidioc_enum_fmt(f, true);
+}
+
+static int vidioc_vdec_g_fmt(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct vb2_queue *vq;
+	struct mtk_q_data *q_data;
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+	if (!vq) {
+		mtk_v4l2_err("no vb2 queue for type=%d",
+			f->type);
+		return -EINVAL;
+	}
+
+	q_data = mtk_vdec_get_q_data(ctx, f->type);
+
+	if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+	    (ctx->state >= MTK_STATE_HEADER)) {
+		/* Until STREAMOFF is called on the CAPTURE queue
+		 * (acknowledging the event), the driver operates as if
+		 * the resolution hasn't changed yet.
+		 * So we just return picinfo yet, and update picinfo in
+		 * stop_streaming hook function
+		 */
+		q_data->sizeimage[0] = ctx->picinfo.y_bs_sz +
+					ctx->picinfo.y_len_sz;
+		q_data->sizeimage[1] = ctx->picinfo.c_bs_sz +
+					ctx->picinfo.c_len_sz;
+		q_data->bytesperline[0] = ctx->last_decoded_picinfo.buf_w;
+		q_data->bytesperline[1] = ctx->last_decoded_picinfo.buf_w;
+		q_data->coded_width = ctx->picinfo.buf_w;
+		q_data->coded_height = ctx->picinfo.buf_h;
+
+		/*
+		 * Width and height are set to the dimensions
+		 * of the movie, the buffer is bigger and
+		 * further processing stages should crop to this
+		 * rectangle.
+		 */
+		pix_mp->width = q_data->coded_width;
+		pix_mp->height = q_data->coded_height;
+		pix_mp->field = V4L2_FIELD_NONE;
+
+		/*
+		 * Set pixelformat to the format in which mt vcodec
+		 * outputs the decoded frame
+		 */
+		pix_mp->num_planes = q_data->fmt->num_planes;
+		pix_mp->pixelformat = q_data->fmt->fourcc;
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+		pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1];
+		pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1];
+
+	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		/*
+		 * This is run on OUTPUT
+		 * The buffer contains compressed image
+		 * so width and height have no meaning.
+		 * Assign value here to pass v4l2-compliance test
+		 */
+		pix_mp->width = q_data->visible_width;
+		pix_mp->height = q_data->visible_height;
+		pix_mp->field = V4L2_FIELD_NONE;
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+		pix_mp->pixelformat = q_data->fmt->fourcc;
+		pix_mp->num_planes = q_data->fmt->num_planes;
+	} else {
+		pix_mp->width = q_data->coded_width;
+		pix_mp->height = q_data->coded_height;
+		pix_mp->field = V4L2_FIELD_NONE;
+		pix_mp->num_planes = q_data->fmt->num_planes;
+		pix_mp->pixelformat = q_data->fmt->fourcc;
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+		pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1];
+		pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1];
+
+		mtk_v4l2_debug(1, "[%d] state=%d Format could not be read %d, not ready yet!",
+				ctx->id, ctx->state, f->type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vb2ops_vdec_queue_setup(struct vb2_queue *vq,
+				unsigned int *nbuffers,
+				unsigned int *nplanes,
+				unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vq);
+	struct mtk_q_data *q_data;
+	unsigned int i;
+
+	q_data = mtk_vdec_get_q_data(ctx, vq->type);
+
+	if (q_data == NULL) {
+		mtk_v4l2_err("vq->type=%d err\n", vq->type);
+		return -EINVAL;
+	}
+
+	if (*nplanes) {
+		for (i = 0; i < *nplanes; i++) {
+			if (sizes[i] < q_data->sizeimage[i])
+				return -EINVAL;
+			alloc_ctxs[i] = ctx->dev->alloc_ctx;
+		}
+	} else {
+
+		if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+			if (ctx->state < MTK_STATE_HEADER) {
+				mtk_v4l2_err("State not ready");
+				return -EINVAL;
+			}
+			/*
+			 * Output plane count is 2 - one for Y and one for CbCr
+			 */
+			*nplanes = 2;
+		} else {
+			*nplanes = 1;
+		}
+
+		for (i = 0; i < *nplanes; i++) {
+			sizes[i] = q_data->sizeimage[i];
+			alloc_ctxs[i] = ctx->dev->alloc_ctx;
+		}
+	}
+
+	mtk_v4l2_debug(1,
+			"[%d]\t type = %d, get %d plane(s), %d buffer(s) of size 0x%x 0x%x ",
+			ctx->id, vq->type, *nplanes, *nbuffers,
+			sizes[0], sizes[1]);
+
+	return 0;
+}
+
+static int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct mtk_q_data *q_data;
+	int i;
+
+	mtk_v4l2_debug(3, "[%d] (%d) id=%d",
+			ctx->id, vb->vb2_queue->type, vb->index);
+
+	q_data = mtk_vdec_get_q_data(ctx, vb->vb2_queue->type);
+
+	for (i = 0; i < q_data->fmt->num_planes; i++) {
+		if (vb2_plane_size(vb, i) > q_data->sizeimage[i]) {
+			mtk_v4l2_err("data will not fit into plane %d (%lu < %d)",
+				i, vb2_plane_size(vb, i),
+				q_data->sizeimage[i]);
+		}
+	}
+
+	return 0;
+}
+
+static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb,
+				struct vb2_v4l2_buffer, vb2_buf);
+	struct mtk_video_dec_buf *buf = container_of(vb2_v4l2,
+				struct mtk_video_dec_buf, vb);
+
+	mtk_v4l2_debug(3, "[%d] (%d) id=%d, vb=%p",
+			ctx->id, vb->vb2_queue->type,
+			vb->index, vb);
+	/*
+	 * check if this buffer is ready to be used after decode
+	 */
+	if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		struct vb2_buffer *src_buf;
+		struct mtk_vcodec_mem src_mem;
+		bool res_chg = false;
+		int ret = 0;
+		unsigned int dpbsize = 1;
+
+		v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2);
+
+		if (ctx->state == MTK_STATE_INIT) {
+			src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+			if (!src_buf) {
+				mtk_v4l2_err("No src buffer");
+				return;
+			}
+
+			src_mem.va	= vb2_plane_vaddr(src_buf, 0);
+			src_mem.dma_addr = vb2_dma_contig_plane_dma_addr(
+						src_buf,
+						0);
+			src_mem.size = (size_t)src_buf->planes[0].bytesused;
+			mtk_v4l2_debug(2,
+					"[%d] buf id=%d va=%p dma=%llx size=%zu",
+					ctx->id, src_buf->index,
+					src_mem.va, (u64)src_mem.dma_addr,
+					src_mem.size);
+
+			ret = vdec_if_decode(ctx, &src_mem, NULL, &res_chg);
+			if (ret) {
+				/* fb == NULL menas to parse SPS/PPS header or
+				 * resolution info in src_mem. Decode can fail
+				 * if there is no SPS header or picture info
+				 * in bs
+				 */
+				src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+				v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+						VB2_BUF_STATE_DONE);
+				mtk_v4l2_debug(0, "[%d] vdec_if_decode() src_buf=%d, size=%zu, fail=%d",
+						ctx->id, src_buf->index,
+						src_mem.size, ret);
+				return;
+			}
+
+			if (vdec_if_get_param(ctx,
+						GET_PARAM_PIC_INFO,
+						&ctx->picinfo)) {
+				mtk_v4l2_err("[%d]Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR",
+						ctx->id);
+				return;
+			}
+
+			ctx->last_decoded_picinfo = ctx->picinfo;
+			ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
+						ctx->picinfo.y_bs_sz +
+						ctx->picinfo.y_len_sz;
+			ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] =
+						ctx->picinfo.buf_w;
+			ctx->q_data[MTK_Q_DATA_DST].sizeimage[1] =
+						ctx->picinfo.c_bs_sz +
+						ctx->picinfo.c_len_sz;
+			ctx->q_data[MTK_Q_DATA_DST].bytesperline[1] =
+						ctx->picinfo.buf_w;
+			mtk_v4l2_debug(2, "[%d] vdec_if_init() OK wxh=%dx%d pic wxh=%dx%d sz[0]=0x%x sz[1]=0x%x",
+				ctx->id,
+				ctx->picinfo.buf_w, ctx->picinfo.buf_h,
+				ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+				ctx->q_data[MTK_Q_DATA_DST].sizeimage[0],
+				ctx->q_data[MTK_Q_DATA_DST].sizeimage[1]);
+
+			ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE,
+						&dpbsize);
+			if (dpbsize == 0) {
+				mtk_v4l2_err("[%d] vdec_if_get_param()  GET_PARAM_DPB_SIZE fail=%d",
+						ctx->id, ret);
+			}
+			ctx->dpb_size = dpbsize;
+			ctx->state = MTK_STATE_HEADER;
+			mtk_v4l2_debug(1, "[%d] dpbsize=%d", ctx->id,
+					ctx->dpb_size);
+		} else {
+			mtk_v4l2_debug(3, "[%d] already init driver %d",
+					ctx->id, ctx->state);
+		}
+	} else {
+		mutex_lock(&ctx->lock);
+		if (buf->used == false) {
+			v4l2_m2m_buf_queue(ctx->m2m_ctx,
+					to_vb2_v4l2_buffer(vb));
+			buf->queued_in_vb2 = true;
+			buf->queued_in_v4l2 = true;
+			buf->ready_to_display = false;
+		} else {
+			buf->queued_in_vb2 = false;
+			buf->queued_in_v4l2 = true;
+			buf->ready_to_display = false;
+		}
+		mutex_unlock(&ctx->lock);
+	}
+}
+
+static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+	if (vb->vb2_queue->type ==
+		V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		struct vb2_v4l2_buffer *vb2_v4l2;
+		struct mtk_video_dec_buf *buf;
+
+		vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
+		buf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
+		mutex_lock(&ctx->lock);
+		buf->queued_in_v4l2 = false;
+		buf->queued_in_vb2 = false;
+		mutex_unlock(&ctx->lock);
+	}
+}
+
+static int vb2ops_vdec_buf_init(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb,
+					struct vb2_v4l2_buffer, vb2_buf);
+	struct mtk_video_dec_buf *buf = container_of(vb2_v4l2,
+					struct mtk_video_dec_buf, vb);
+
+	if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		buf->used = false;
+		buf->ready_to_display = false;
+		buf->queued_in_v4l2 = false;
+	} else {
+		buf->lastframe = false;
+	}
+
+	return 0;
+}
+
+static int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q);
+
+	if (ctx->state == MTK_STATE_FLUSH)
+		ctx->state = MTK_STATE_HEADER;
+
+	return 0;
+}
+
+static void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
+{
+	struct vb2_buffer *src_buf = NULL, *dst_buf = NULL;
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q);
+
+	mtk_v4l2_debug(3, "[%d] (%d) state=(%x) ctx->decoded_frame_cnt=%d",
+			ctx->id, q->type, ctx->state, ctx->decoded_frame_cnt);
+
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
+			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+					VB2_BUF_STATE_ERROR);
+
+	} else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		if (ctx->state >= MTK_STATE_HEADER) {
+
+			/* Until STREAMOFF is called on the CAPTURE queue
+			 * (acknowledging the event), the driver operates
+			 * as if the resolution hasn't changed yet, i.e.
+			 * VIDIOC_G_FMT< etc. return previous resolution.
+			 * So we update picinfo here
+			 */
+			ctx->picinfo = ctx->last_decoded_picinfo;
+
+			mtk_v4l2_debug(2,
+				"[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)",
+				ctx->id, ctx->last_decoded_picinfo.pic_w,
+				ctx->last_decoded_picinfo.pic_h,
+				ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+				ctx->last_decoded_picinfo.buf_w,
+				ctx->last_decoded_picinfo.buf_h);
+
+			mtk_vdec_flush_decoder(ctx);
+		}
+		ctx->state = MTK_STATE_FLUSH;
+
+		while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) {
+			vb2_set_plane_payload(dst_buf, 0, 0);
+			vb2_set_plane_payload(dst_buf, 1, 0);
+			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
+					VB2_BUF_STATE_ERROR);
+		}
+	}
+}
+
+static void m2mops_vdec_device_run(void *priv)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+	struct mtk_vcodec_dev *dev = ctx->dev;
+
+	queue_work(dev->decode_workqueue, &ctx->decode_work);
+}
+
+static int m2mops_vdec_job_ready(void *m2m_priv)
+{
+	struct mtk_vcodec_ctx *ctx = m2m_priv;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+
+	if (ctx->state == MTK_STATE_ABORT)
+		return 0;
+
+	if ((ctx->last_decoded_picinfo.pic_w != ctx->picinfo.pic_w) ||
+	    (ctx->last_decoded_picinfo.pic_h != ctx->picinfo.pic_h))
+		return 0;
+
+	if (ctx->state != MTK_STATE_HEADER)
+		return 0;
+
+	return 1;
+}
+
+static void m2mops_vdec_job_abort(void *priv)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+
+	ctx->state = MTK_STATE_ABORT;
+}
+
+static int mtk_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mtk_vcodec_ctx *ctx = ctrl_to_ctx(ctrl);
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+		if (ctx->state >= MTK_STATE_HEADER) {
+			ctrl->val = ctx->dpb_size;
+		} else {
+			mtk_v4l2_err("Seqinfo not ready");
+			ctrl->val = 1;
+			ret = -EAGAIN;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops mtk_vcodec_dec_ctrl_ops = {
+	.g_volatile_ctrl = mtk_vdec_g_v_ctrl,
+};
+
+int mtk_vcodec_dec_ctrls_setup(struct mtk_vcodec_ctx *ctx)
+{
+	struct v4l2_ctrl *ctrl;
+
+	v4l2_ctrl_handler_init(&ctx->ctrl_hdl, 1);
+
+	ctrl = v4l2_ctrl_new_std(&ctx->ctrl_hdl,
+				&mtk_vcodec_dec_ctrl_ops,
+				V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
+				1, 32, 1, 1);
+	ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+	if (ctx->ctrl_hdl.error) {
+		mtk_v4l2_err("Adding control failed %d",
+				ctx->ctrl_hdl.error);
+		return ctx->ctrl_hdl.error;
+	}
+
+	v4l2_ctrl_handler_setup(&ctx->ctrl_hdl);
+	return 0;
+}
+
+static void m2mops_vdec_lock(void *m2m_priv)
+{
+	struct mtk_vcodec_ctx *ctx = m2m_priv;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+	mutex_lock(&ctx->dev->dev_mutex);
+}
+
+static void m2mops_vdec_unlock(void *m2m_priv)
+{
+	struct mtk_vcodec_ctx *ctx = m2m_priv;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+	mutex_unlock(&ctx->dev->dev_mutex);
+}
+
+const struct v4l2_m2m_ops mtk_vdec_m2m_ops = {
+	.device_run	= m2mops_vdec_device_run,
+	.job_ready	= m2mops_vdec_job_ready,
+	.job_abort	= m2mops_vdec_job_abort,
+	.lock		= m2mops_vdec_lock,
+	.unlock		= m2mops_vdec_unlock,
+};
+
+static const struct vb2_ops mtk_vdec_vb2_ops = {
+	.queue_setup	= vb2ops_vdec_queue_setup,
+	.buf_prepare	= vb2ops_vdec_buf_prepare,
+	.buf_queue	= vb2ops_vdec_buf_queue,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
+	.buf_init	= vb2ops_vdec_buf_init,
+	.buf_finish	= vb2ops_vdec_buf_finish,
+	.start_streaming	= vb2ops_vdec_start_streaming,
+	.stop_streaming	= vb2ops_vdec_stop_streaming,
+};
+
+const struct v4l2_ioctl_ops mtk_vdec_ioctl_ops = {
+	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff	= v4l2_m2m_ioctl_streamoff,
+	.vidioc_reqbufs		= v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
+	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
+
+	.vidioc_qbuf		= vidioc_vdec_qbuf,
+	.vidioc_dqbuf		= vidioc_vdec_dqbuf,
+
+	.vidioc_try_fmt_vid_cap_mplane	= vidioc_try_fmt_vid_cap_mplane,
+	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_out_mplane,
+
+	.vidioc_s_fmt_vid_cap_mplane	= vidioc_vdec_s_fmt,
+	.vidioc_s_fmt_vid_out_mplane	= vidioc_vdec_s_fmt,
+	.vidioc_g_fmt_vid_cap_mplane	= vidioc_vdec_g_fmt,
+	.vidioc_g_fmt_vid_out_mplane	= vidioc_vdec_g_fmt,
+
+	.vidioc_enum_fmt_vid_cap_mplane	= vidioc_vdec_enum_fmt_vid_cap_mplane,
+	.vidioc_enum_fmt_vid_out_mplane	= vidioc_vdec_enum_fmt_vid_out_mplane,
+	.vidioc_enum_framesizes	= vidioc_enum_framesizes,
+
+	.vidioc_querycap		= vidioc_vdec_querycap,
+	.vidioc_subscribe_event		= vidioc_vdec_subscribe_evt,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+	.vidioc_g_selection             = vidioc_vdec_g_selection,
+};
+
+int mtk_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
+			   struct vb2_queue *dst_vq)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+	int ret = 0;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+
+	src_vq->type		= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes	= VB2_DMABUF | VB2_MMAP;
+	src_vq->drv_priv	= ctx;
+	src_vq->buf_struct_size = sizeof(struct mtk_video_dec_buf);
+	src_vq->ops		= &mtk_vdec_vb2_ops;
+	src_vq->mem_ops		= &vb2_dma_contig_memops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock		= &ctx->dev->dev_mutex;
+
+	ret = vb2_queue_init(src_vq);
+	if (ret) {
+		mtk_v4l2_err("Failed to initialize videobuf2 queue(output)");
+		return ret;
+	}
+	dst_vq->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes	= VB2_DMABUF | VB2_MMAP;
+	dst_vq->drv_priv	= ctx;
+	dst_vq->buf_struct_size = sizeof(struct mtk_video_dec_buf);
+	dst_vq->ops		= &mtk_vdec_vb2_ops;
+	dst_vq->mem_ops		= &vb2_dma_contig_memops;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock		= &ctx->dev->dev_mutex;
+
+	ret = vb2_queue_init(dst_vq);
+	if (ret) {
+		vb2_queue_release(src_vq);
+		mtk_v4l2_err("Failed to initialize videobuf2 queue(capture)");
+	}
+
+	return ret;
+}
+
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
new file mode 100644
index 0000000..595c244
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
@@ -0,0 +1,88 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen at mediatek.com>
+*         Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MTK_VCODEC_DEC_H_
+#define _MTK_VCODEC_DEC_H_
+
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
+
+#define VCODEC_CAPABILITY_4K_DISABLED	0x10
+#define VCODEC_DEC_4K_CODED_WIDTH	4096U
+#define VCODEC_DEC_4K_CODED_HEIGHT	2304U
+#define MTK_VDEC_MAX_W	2048U
+#define MTK_VDEC_MAX_H	1088U
+
+#define MTK_VDEC_IRQ_STATUS_DEC_SUCCESS        0x10000
+
+/**
+ * struct vdec_fb  - decoder frame buffer
+ * @base_y	: Y plane memory info
+ * @base_c	: C plane memory info
+ * @status      : frame buffer status (vdec_fb_status)
+ */
+struct vdec_fb {
+	struct mtk_vcodec_mem	base_y;
+	struct mtk_vcodec_mem	base_c;
+	unsigned int	status;
+};
+
+/**
+ * struct mtk_video_dec_buf - Private data related to each VB2 buffer.
+ * @b:		VB2 buffer
+ * @list:	link list
+ * @used:	Capture buffer contain decoded frame data and keep in
+ *			codec data structure
+ * @ready_to_display:	Capture buffer not display yet
+ * @queued_in_vb2:	Capture buffer is queue in vb2
+ * @queued_in_v4l2:	Capture buffer is in v4l2 driver, but not in vb2
+ *			queue yet
+ * @lastframe:		Intput buffer is last buffer - EOS
+ * @frame_buffer:	Decode status, and buffer information of Capture buffer
+ *
+ * Note : These status information help us track and debug buffer state
+ */
+struct mtk_video_dec_buf {
+	struct vb2_v4l2_buffer	vb;
+	struct list_head	list;
+
+	bool	used;
+	bool	ready_to_display;
+	bool	queued_in_vb2;
+	bool	queued_in_v4l2;
+	bool	lastframe;
+	struct vdec_fb	frame_buffer;
+};
+
+extern const struct v4l2_ioctl_ops mtk_vdec_ioctl_ops;
+extern const struct v4l2_m2m_ops mtk_vdec_m2m_ops;
+
+
+/*
+ * mtk_vdec_lock/mtk_vdec_unlock are for ctx instance to
+ * get/release lock before/after access decoder hw.
+ * mtk_vdec_lock get decoder hw lock and set curr_ctx
+ * to ctx instance that get lock
+ */
+void mtk_vdec_unlock(struct mtk_vcodec_ctx *ctx);
+void mtk_vdec_lock(struct mtk_vcodec_ctx *ctx);
+int mtk_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
+			   struct vb2_queue *dst_vq);
+void mtk_vcodec_dec_set_default_params(struct mtk_vcodec_ctx *ctx);
+void mtk_vcodec_vdec_release(struct mtk_vcodec_ctx *ctx);
+int mtk_vcodec_dec_ctrls_setup(struct mtk_vcodec_ctx *ctx);
+
+
+#endif /* _MTK_VCODEC_DEC_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
new file mode 100644
index 0000000..725d1e5
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -0,0 +1,408 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: PC Chen <pc.chen at mediatek.com>
+*         Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_dec.h"
+#include "mtk_vcodec_dec_pm.h"
+#include "mtk_vcodec_intr.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
+
+#define VDEC_HW_ACTIVE	0x10
+#define VDEC_IRQ_CFG	0x11
+#define VDEC_IRQ_CLR	0x10
+#define VDEC_IRQ_CFG_REG	0xa4
+
+module_param(mtk_v4l2_dbg_level, int, S_IRUGO | S_IWUSR);
+module_param(mtk_vcodec_dbg, bool, S_IRUGO | S_IWUSR);
+
+/* Wake up context wait_queue */
+static void wake_up_ctx(struct mtk_vcodec_ctx *ctx)
+{
+	ctx->int_cond = 1;
+	wake_up_interruptible(&ctx->queue);
+}
+
+static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void *priv)
+{
+	struct mtk_vcodec_dev *dev = priv;
+	struct mtk_vcodec_ctx *ctx;
+	u32 cg_status = 0;
+	unsigned int dec_done_status = 0;
+	void __iomem *vdec_misc_addr = dev->reg_base[VDEC_MISC] +
+					VDEC_IRQ_CFG_REG;
+
+	ctx = mtk_vcodec_get_curr_ctx(dev);
+
+	/* check if HW active or not */
+	cg_status = readl(dev->reg_base[0]);
+	if ((cg_status & VDEC_HW_ACTIVE) != 0) {
+		mtk_v4l2_err("DEC ISR, VDEC active is not 0x0 (0x%08x)",
+			     cg_status);
+		return IRQ_HANDLED;
+	}
+
+	dec_done_status = readl(vdec_misc_addr);
+	ctx->irq_status = dec_done_status;
+	if ((dec_done_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) !=
+		MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
+		return IRQ_HANDLED;
+
+	/* clear interrupt */
+	writel((readl(vdec_misc_addr) | VDEC_IRQ_CFG),
+		dev->reg_base[VDEC_MISC] + VDEC_IRQ_CFG_REG);
+	writel((readl(vdec_misc_addr) & ~VDEC_IRQ_CLR),
+		dev->reg_base[VDEC_MISC] + VDEC_IRQ_CFG_REG);
+
+	wake_up_ctx(ctx);
+
+	mtk_v4l2_debug(3,
+			"mtk_vcodec_dec_irq_handler :wake up ctx %d, dec_done_status=%x",
+			ctx->id, dec_done_status);
+
+	return IRQ_HANDLED;
+}
+
+static void mtk_vcodec_dec_reset_handler(void *priv)
+{
+	struct mtk_vcodec_dev *dev = priv;
+	struct mtk_vcodec_ctx *ctx;
+
+	mtk_v4l2_err("Watchdog timeout!!");
+
+	mutex_lock(&dev->dev_mutex);
+	list_for_each_entry(ctx, &dev->ctx_list, list) {
+		ctx->state = MTK_STATE_ABORT;
+		mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ERROR",
+				ctx->id);
+	}
+	mutex_unlock(&dev->dev_mutex);
+}
+
+static int fops_vcodec_open(struct file *file)
+{
+	struct mtk_vcodec_dev *dev = video_drvdata(file);
+	struct mtk_vcodec_ctx *ctx = NULL;
+	int ret = 0;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	mutex_lock(&dev->dev_mutex);
+	ctx->id = dev->id_counter++;
+	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	file->private_data = &ctx->fh;
+	v4l2_fh_add(&ctx->fh);
+	INIT_LIST_HEAD(&ctx->list);
+	ctx->dev = dev;
+	init_waitqueue_head(&ctx->queue);
+	mutex_init(&ctx->lock);
+
+	ctx->type = MTK_INST_DECODER;
+	ret = mtk_vcodec_dec_ctrls_setup(ctx);
+	if (ret) {
+		mtk_v4l2_err("Failed to setup mt vcodec controls");
+		goto err_ctrls_setup;
+	}
+	ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx,
+		&mtk_vcodec_dec_queue_init);
+	if (IS_ERR((__force void *)ctx->m2m_ctx)) {
+		ret = PTR_ERR((__force void *)ctx->m2m_ctx);
+		mtk_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)",
+			ret);
+		goto err_m2m_ctx_init;
+	}
+	mtk_vcodec_dec_set_default_params(ctx);
+
+	if (v4l2_fh_is_singular(&ctx->fh)) {
+		mtk_vcodec_dec_pw_on(&dev->pm);
+		/*
+		 * vpu_load_firmware checks if it was loaded already and
+		 * does nothing in that case
+		 */
+		ret = vpu_load_firmware(dev->vpu_plat_dev);
+		if (ret < 0) {
+			/*
+			 * Return 0 if downloading firmware successfully,
+			 * otherwise it is failed
+			 */
+			mtk_v4l2_err("vpu_load_firmware failed!");
+			goto err_load_fw;
+		}
+
+		dev->dec_capability =
+			vpu_get_vdec_hw_capa(dev->vpu_plat_dev);
+		mtk_v4l2_debug(0, "decoder capability %x", dev->dec_capability);
+	}
+
+	dev->num_instances++;
+	list_add(&ctx->list, &dev->ctx_list);
+
+	mutex_unlock(&dev->dev_mutex);
+	mtk_v4l2_debug(0, "%s decoder [%d]", dev_name(&dev->plat_dev->dev),
+			ctx->id);
+	return ret;
+
+	/* Deinit when failure occurred */
+err_load_fw:
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+err_m2m_ctx_init:
+	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+err_ctrls_setup:
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	kfree(ctx);
+	mutex_unlock(&dev->dev_mutex);
+
+	return ret;
+}
+
+static int fops_vcodec_release(struct file *file)
+{
+	struct mtk_vcodec_dev *dev = video_drvdata(file);
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(file->private_data);
+
+	mtk_v4l2_debug(0, "[%d] decoder", ctx->id);
+	mutex_lock(&dev->dev_mutex);
+
+	mtk_vcodec_vdec_release(ctx);
+	if (v4l2_fh_is_singular(&ctx->fh))
+		mtk_vcodec_dec_pw_off(&dev->pm);
+
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+
+	list_del_init(&ctx->list);
+	dev->num_instances--;
+	kfree(ctx);
+	mutex_unlock(&dev->dev_mutex);
+	return 0;
+}
+
+static const struct v4l2_file_operations mtk_vcodec_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fops_vcodec_open,
+	.release	= fops_vcodec_release,
+	.poll		= v4l2_m2m_fop_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= v4l2_m2m_fop_mmap,
+};
+
+static int mtk_vcodec_probe(struct platform_device *pdev)
+{
+	struct mtk_vcodec_dev *dev;
+	struct video_device *vfd_dec;
+	struct resource *res;
+	int i, ret;
+	DEFINE_DMA_ATTRS(attrs);
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&dev->ctx_list);
+	dev->plat_dev = pdev;
+
+	dev->vpu_plat_dev = vpu_get_plat_device(dev->plat_dev);
+	if (dev->vpu_plat_dev == NULL) {
+		mtk_v4l2_err("[VPU] vpu device in not ready");
+		return -EPROBE_DEFER;
+	}
+
+	vpu_wdt_reg_handler(dev->vpu_plat_dev, mtk_vcodec_dec_reset_handler,
+			dev, VPU_RST_DEC);
+
+	ret = mtk_vcodec_init_dec_pm(dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to get mt vcodec clock source");
+		return ret;
+	}
+
+	for (i = 0; i < NUM_MAX_VDEC_REG_BASE; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (res == NULL) {
+			dev_err(&pdev->dev, "get memory resource failed.");
+			ret = -ENXIO;
+			goto err_res;
+		}
+		dev->reg_base[i] = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR((__force void *)dev->reg_base[i])) {
+			dev_err(&pdev->dev,
+				"devm_ioremap_resource %d failed.", i);
+			ret = PTR_ERR((__force void *)dev->reg_base);
+			goto err_res;
+		}
+		mtk_v4l2_debug(2, "reg[%d] base=%p", i, dev->reg_base[i]);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to get irq resource");
+		ret = -ENOENT;
+		goto err_res;
+	}
+
+	dev->dec_irq = platform_get_irq(pdev, 0);
+	ret = devm_request_irq(&pdev->dev, dev->dec_irq,
+			mtk_vcodec_dec_irq_handler, 0, pdev->name, dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to install dev->dec_irq %d (%d)",
+			dev->dec_irq,
+			ret);
+		goto err_res;
+	}
+
+	disable_irq(dev->dec_irq);
+	mutex_init(&dev->dec_mutex);
+	mutex_init(&dev->dev_mutex);
+	spin_lock_init(&dev->irqlock);
+
+	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
+		"[/MTK_V4L2_VDEC]");
+
+	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+	if (ret) {
+		mtk_v4l2_err("v4l2_device_register err=%d", ret);
+		goto err_res;
+	}
+
+	init_waitqueue_head(&dev->queue);
+
+	vfd_dec = video_device_alloc();
+	if (!vfd_dec) {
+		mtk_v4l2_err("Failed to allocate video device");
+		ret = -ENOMEM;
+		goto err_dec_alloc;
+	}
+	vfd_dec->fops		= &mtk_vcodec_fops;
+	vfd_dec->ioctl_ops	= &mtk_vdec_ioctl_ops;
+	vfd_dec->release	= video_device_release;
+	vfd_dec->lock		= &dev->dev_mutex;
+	vfd_dec->v4l2_dev	= &dev->v4l2_dev;
+	vfd_dec->vfl_dir	= VFL_DIR_M2M;
+	vfd_dec->device_caps	= V4L2_CAP_VIDEO_M2M_MPLANE |
+			V4L2_CAP_STREAMING;
+
+	snprintf(vfd_dec->name, sizeof(vfd_dec->name), "%s",
+		MTK_VCODEC_DEC_NAME);
+	video_set_drvdata(vfd_dec, dev);
+	dev->vfd_dec = vfd_dec;
+	platform_set_drvdata(pdev, dev);
+
+	dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	if (IS_ERR((__force void *)dev->alloc_ctx)) {
+		mtk_v4l2_err("Failed to alloc vb2 dma context 0");
+		ret = PTR_ERR((__force void *)dev->alloc_ctx);
+		goto err_vb2_ctx_init;
+	}
+
+	dev->m2m_dev_dec = v4l2_m2m_init(&mtk_vdec_m2m_ops);
+	if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
+		mtk_v4l2_err("Failed to init mem2mem dec device");
+		ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
+		goto err_dec_mem_init;
+	}
+
+	dev->decode_workqueue =
+		alloc_ordered_workqueue(MTK_VCODEC_DEC_NAME,
+			WQ_MEM_RECLAIM | WQ_FREEZABLE);
+	if (!dev->decode_workqueue) {
+		mtk_v4l2_err("Failed to create decode workqueue");
+		ret = -EINVAL;
+		goto err_event_workq;
+	}
+
+	ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 0);
+	if (ret) {
+		mtk_v4l2_err("Failed to register video device");
+		goto err_dec_reg;
+	}
+
+	/* Avoid the iommu eat big hunks */
+	dma_set_attr(DMA_ATTR_ALLOC_SINGLE_PAGES, &attrs);
+
+	mtk_v4l2_debug(0, "decoder registered as /dev/video%d",
+		vfd_dec->num);
+
+	return 0;
+
+err_dec_reg:
+	destroy_workqueue(dev->decode_workqueue);
+err_event_workq:
+	v4l2_m2m_release(dev->m2m_dev_dec);
+err_dec_mem_init:
+	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+err_vb2_ctx_init:
+	video_unregister_device(vfd_dec);
+err_dec_alloc:
+	v4l2_device_unregister(&dev->v4l2_dev);
+err_res:
+	mtk_vcodec_release_dec_pm(dev);
+	return ret;
+}
+
+static const struct of_device_id mtk_vcodec_match[] = {
+	{.compatible = "mediatek,mt8173-vcodec-dec",},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, mtk_vcodec_match);
+
+static int mtk_vcodec_dec_remove(struct platform_device *pdev)
+{
+	struct mtk_vcodec_dev *dev = platform_get_drvdata(pdev);
+
+	flush_workqueue(dev->decode_workqueue);
+	destroy_workqueue(dev->decode_workqueue);
+	if (dev->m2m_dev_dec)
+		v4l2_m2m_release(dev->m2m_dev_dec);
+	if (dev->alloc_ctx)
+		vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+
+	if (dev->vfd_dec)
+		video_unregister_device(dev->vfd_dec);
+
+	v4l2_device_unregister(&dev->v4l2_dev);
+	mtk_vcodec_release_dec_pm(dev);
+	return 0;
+}
+
+static struct platform_driver mtk_vcodec_dec_driver = {
+	.probe	= mtk_vcodec_probe,
+	.remove	= mtk_vcodec_dec_remove,
+	.driver	= {
+		.name	= MTK_VCODEC_DEC_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = mtk_vcodec_match,
+	},
+};
+
+module_platform_driver(mtk_vcodec_dec_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Mediatek video codec V4L2 decoder driver");
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
new file mode 100644
index 0000000..364b756
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -0,0 +1,206 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/clk.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <soc/mediatek/smi.h>
+
+#include "mtk_vcodec_dec_pm.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
+
+int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
+{
+	struct device_node *node;
+	struct platform_device *pdev;
+	struct device *dev;
+	struct mtk_vcodec_pm *pm;
+	int ret = 0;
+
+	pdev = mtkdev->plat_dev;
+	pm = &mtkdev->pm;
+	pm->mtkdev = mtkdev;
+	dev = &pdev->dev;
+	node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
+	if (!node) {
+		mtk_v4l2_err("of_parse_phandle mediatek,larb fail!");
+		return -1;
+	}
+
+	pdev = of_find_device_by_node(node);
+	if (WARN_ON(!pdev)) {
+		of_node_put(node);
+		return -1;
+	}
+	pm->larbvdec = &pdev->dev;
+
+	pdev = mtkdev->plat_dev;
+	pm->dev = &pdev->dev;
+
+	pm->vcodecpll = devm_clk_get(&pdev->dev, "vcodecpll");
+	if (pm->vcodecpll == NULL) {
+		mtk_v4l2_err("devm_clk_get vcodecpll fail");
+		ret = -1;
+	}
+
+	pm->univpll_d2 = devm_clk_get(&pdev->dev, "univpll_d2");
+	if (pm->univpll_d2 == NULL) {
+		mtk_v4l2_err("devm_clk_get univpll_d2 fail");
+		ret = -1;
+	}
+
+	pm->clk_cci400_sel = devm_clk_get(&pdev->dev, "clk_cci400_sel");
+	if (pm->clk_cci400_sel == NULL) {
+		mtk_v4l2_err("devm_clk_get clk_cci400_sel fail");
+		ret = -1;
+	}
+
+	pm->vdec_sel = devm_clk_get(&pdev->dev, "vdec_sel");
+	if (pm->vdec_sel == NULL) {
+		mtk_v4l2_err("devm_clk_get vdec_sel fail");
+		ret = -1;
+	}
+
+	pm->vdecpll = devm_clk_get(&pdev->dev, "vdecpll");
+	if (pm->vdecpll == NULL) {
+		mtk_v4l2_err("devm_clk_get vdecpll fail");
+		ret = -1;
+	}
+
+	pm->vencpll = devm_clk_get(&pdev->dev, "vencpll");
+	if (pm->vencpll == NULL) {
+		mtk_v4l2_err("devm_clk_get vencpll fail");
+		ret = -1;
+	}
+
+	pm->venc_lt_sel = devm_clk_get(&pdev->dev, "venc_lt_sel");
+	if (pm->venc_lt_sel == NULL) {
+		mtk_v4l2_err("devm_clk_get venc_lt_sel fail");
+		ret = -1;
+	}
+
+	pm->vdec_bus_clk_src = devm_clk_get(&pdev->dev, "vdec_bus_clk_src");
+	if (pm->vdec_bus_clk_src == NULL) {
+		mtk_v4l2_err("devm_clk_get vdec_bus_clk_src");
+		ret = -1;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+
+	return ret;
+}
+
+void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
+{
+	pm_runtime_disable(dev->pm.dev);
+}
+
+void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
+{
+	int ret;
+
+	ret = pm_runtime_get_sync(pm->dev);
+	if (ret)
+		mtk_v4l2_err("pm_runtime_get_sync fail %d", ret);
+}
+
+void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm)
+{
+	int ret;
+
+	ret = pm_runtime_put_sync(pm->dev);
+	if (ret)
+		mtk_v4l2_err("pm_runtime_put_sync fail %d", ret);
+}
+
+void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)
+{
+	int ret;
+
+	ret = clk_set_rate(pm->vcodecpll, 1482 * 1000000);
+	if (ret)
+		mtk_v4l2_err("clk_set_rate vcodecpll fail %d", ret);
+
+	ret = clk_set_rate(pm->vencpll, 800 * 1000000);
+	if (ret)
+		mtk_v4l2_err("clk_set_rate vencpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vcodecpll);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vcodecpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vencpll);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vencpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vdec_bus_clk_src);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vdec_bus_clk_src fail %d",
+				ret);
+
+	ret = clk_prepare_enable(pm->venc_lt_sel);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable venc_lt_sel fail %d", ret);
+
+	ret = clk_set_parent(pm->venc_lt_sel, pm->vdec_bus_clk_src);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent venc_lt_sel vdec_bus_clk_src fail %d",
+				ret);
+
+	ret = clk_prepare_enable(pm->univpll_d2);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable univpll_d2 fail %d", ret);
+
+	ret = clk_prepare_enable(pm->clk_cci400_sel);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable clk_cci400_sel fail %d", ret);
+
+	ret = clk_set_parent(pm->clk_cci400_sel, pm->univpll_d2);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent clk_cci400_sel univpll_d2 fail %d",
+				ret);
+
+	ret = clk_prepare_enable(pm->vdecpll);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vdecpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vdec_sel);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vdec_sel fail %d", ret);
+
+	ret = clk_set_parent(pm->vdec_sel, pm->vdecpll);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent vdec_sel vdecpll fail %d", ret);
+
+	ret = mtk_smi_larb_get(pm->larbvdec);
+	if (ret)
+		mtk_v4l2_err("mtk_smi_larb_get larbvdec fail %d", ret);
+
+}
+
+void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm)
+{
+	mtk_smi_larb_put(pm->larbvdec);
+	clk_disable_unprepare(pm->vdec_sel);
+	clk_disable_unprepare(pm->vdecpll);
+	clk_disable_unprepare(pm->univpll_d2);
+	clk_disable_unprepare(pm->clk_cci400_sel);
+	clk_disable_unprepare(pm->venc_lt_sel);
+	clk_disable_unprepare(pm->vdec_bus_clk_src);
+	clk_disable_unprepare(pm->vencpll);
+	clk_disable_unprepare(pm->vcodecpll);
+}
+
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
new file mode 100644
index 0000000..b8bf56f
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2016 MediaTek Inc.
+* Author: Tiffany Lin <tiffany.lin at mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MTK_VCODEC_DEC_PM_H_
+#define _MTK_VCODEC_DEC_PM_H_
+
+#include "mtk_vcodec_drv.h"
+
+int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *dev);
+void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev);
+
+void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm);
+void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm);
+void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm);
+void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm);
+
+#endif /* _MTK_VCODEC_DEC_PM_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
index 78eee50..a11dfec 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
@@ -26,10 +26,10 @@
 #include "mtk_vcodec_util.h"
 
 #define MTK_VCODEC_DRV_NAME	"mtk_vcodec_drv"
+#define MTK_VCODEC_DEC_NAME	"mtk-vcodec-dec"
 #define MTK_VCODEC_ENC_NAME	"mtk-vcodec-enc"
 #define MTK_PLATFORM_STR	"platform:mt8173"
 
-
 #define MTK_VCODEC_MAX_PLANES	3
 #define MTK_V4L2_BENCHMARK	0
 #define WAIT_INTR_TIMEOUT_MS	1000
@@ -180,6 +180,9 @@ struct mtk_enc_params {
  * struct mtk_vcodec_pm - Power management data structure
  */
 struct mtk_vcodec_pm {
+	struct clk	*vdec_bus_clk_src;
+	struct clk	*vencpll;
+
 	struct clk	*vcodecpll;
 	struct clk	*univpll_d2;
 	struct clk	*clk_cci400_sel;
@@ -197,6 +200,32 @@ struct mtk_vcodec_pm {
 };
 
 /**
+ * struct vdec_pic_info  - picture size information
+ * @pic_w: picture width
+ * @pic_h: picture height
+ * @buf_w: picture buffer width (64 aligned up from pic_w)
+ * @buf_h: picture buffer heiht (64 aligned up from pic_h)
+ * @y_bs_sz: Y bitstream size
+ * @c_bs_sz: CbCr bitstream size
+ * @y_len_sz: additional size required to store decompress information for y
+ *		plane
+ * @c_len_sz: additional size required to store decompress information for cbcr
+ *		plane
+ * E.g. suppose picture size is 176x144,
+ *      buffer size will be aligned to 176x160.
+ */
+struct vdec_pic_info {
+	unsigned int pic_w;
+	unsigned int pic_h;
+	unsigned int buf_w;
+	unsigned int buf_h;
+	unsigned int y_bs_sz;
+	unsigned int c_bs_sz;
+	unsigned int y_len_sz;
+	unsigned int c_len_sz;
+};
+
+/**
  * struct mtk_vcodec_ctx - Context (instance) private data.
  *
  * @type: type of the instance - decoder or encoder
@@ -210,9 +239,12 @@ struct mtk_vcodec_pm {
  * @state: state of the context
  * @param_change: indicate encode parameter type
  * @enc_params: encoding parameters
- * @enc_if: hoooked encoder driver interface
+ * @dec_if: hooked decoder driver interface
+ * @enc_if: hooked encoder driver interface
  * @drv_handle: driver handle for specific decode/encode instance
  *
+ * @picinfo: store picture info after header parsing
+ * @dpb_size: store dpb count after header parsing
  * @int_cond: variable used by the waitqueue
  * @int_type: type of the last interrupt
  * @queue: waitqueue that can be used to wait for this context to
@@ -220,12 +252,16 @@ struct mtk_vcodec_pm {
  * @irq_status: irq status
  *
  * @ctrl_hdl: handler for v4l2 framework
+ * @decode_work: worker for the decoding
  * @encode_work: worker for the encoding
+ * @last_decoded_picinfo: pic information get from latest decode
  *
  * @colorspace: enum v4l2_colorspace; supplemental to pixelformat
  * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
  * @quantization: enum v4l2_quantization, colorspace quantization
  * @xfer_func: enum v4l2_xfer_func, colorspace transfer function
+ * @lock: protect variables accessed by V4L2 threads and worker thread such as
+ *	  mtk_video_dec_buf.
  */
 struct mtk_vcodec_ctx {
 	enum mtk_instance_type type;
@@ -240,21 +276,31 @@ struct mtk_vcodec_ctx {
 	enum mtk_encode_param param_change;
 	struct mtk_enc_params enc_params;
 
+	struct vdec_common_if *dec_if;
 	struct venc_common_if *enc_if;
 	unsigned long drv_handle;
 
+	struct vdec_pic_info picinfo;
+	int dpb_size;
+
 	int int_cond;
 	int int_type;
 	wait_queue_head_t queue;
 	unsigned int irq_status;
 
 	struct v4l2_ctrl_handler ctrl_hdl;
+	struct work_struct decode_work;
 	struct work_struct encode_work;
+	struct vdec_pic_info last_decoded_picinfo;
 
 	enum v4l2_colorspace colorspace;
 	enum v4l2_ycbcr_encoding ycbcr_enc;
 	enum v4l2_quantization quantization;
 	enum v4l2_xfer_func xfer_func;
+
+	int decoded_frame_cnt;
+	struct mutex lock;
+
 };
 
 /**
@@ -268,25 +314,48 @@ struct mtk_vcodec_ctx {
  * @alloc_ctx: VB2 allocator context
  *	       (for allocations without kernel mapping).
  * @ctx_list: list of struct mtk_vcodec_ctx
- * @irqlock: protect data access by irq handler and work thread
- * @curr_ctx: The context that is waiting for codec hardware
+ * @irqlock: protect data access by irq handler and work thread -- curr_ctx
+ * @curr_ctx: The context that is waiting for codec hardware. Protected by
+ *		irqlock and dec_mutex or enc_mutex.
  *
  * @reg_base: Mapped address of MTK Vcodec registers.
  *
- * @id_counter: used to identify current opened instance
+ * @id_counter:  An integer id given to the next opened instance
  * @num_instances: counter of active MTK Vcodec instances
  *
  * @encode_workqueue: encode work queue
  *
+ * @v4l2_dev: V4L2 device to register video devices for.
+ * @vfd_dec: Video device for decoder
+ * @vfd_enc: Video device for encoder
+ *
+ * @m2m_dev_dec: m2m device for decoder
+ * @m2m_dev_enc: m2m device for encoder
+ * @plat_dev: platform device
+ * @vpu_plat_dev: mtk vpu platform device
+ * @alloc_ctx:VB2 allocator context
+ *	      (for allocations without kernel mapping).
+ * @ctx_list: list of struct mtk_vcodec_ctx
+ * @irqlock: protect data access by irq handler and work thread
+ * @curr_ctx: The context that is waiting for codec hardware
+ * @reg_base: Mapped address of MTK Vcodec registers.
+ *
+ * @instance_mask: used to mark which index id are used
+ * @num_instances: counter of active MTK Vcodec instances
+ *
+ * @decode_workqueue: decode work queue
+ * @encode_workqueue: encode work queue
  * @int_cond: used to identify interrupt condition happen
  * @int_type: used to identify what kind of interrupt condition happen
  * @dev_mutex: video_device lock
  * @queue: waitqueue for waiting for completion of device commands
  *
+ * @dec_irq: decoder irq resource
  * @enc_irq: h264 encoder irq resource
- * @enc_lt_irq: vp8 encoder irq resource
+ * @enc_lt_irq: vp8 encoder lt irq resource
  *
- * @enc_mutex: encoder hardware lock.
+ * @dec_mutex: decoder hardware lock
+ * @enc_mutex: encoder hardware lock
  *
  * @pm: power management control
  * @dec_capability: used to identify decode capability, ex: 4k
@@ -294,8 +363,10 @@ struct mtk_vcodec_ctx {
  */
 struct mtk_vcodec_dev {
 	struct v4l2_device v4l2_dev;
+	struct video_device *vfd_dec;
 	struct video_device *vfd_enc;
 
+	struct v4l2_m2m_dev *m2m_dev_dec;
 	struct v4l2_m2m_dev *m2m_dev_enc;
 	struct platform_device *plat_dev;
 	struct platform_device *vpu_plat_dev;
@@ -308,6 +379,7 @@ struct mtk_vcodec_dev {
 	unsigned long id_counter;
 	int num_instances;
 
+	struct workqueue_struct *decode_workqueue;
 	struct workqueue_struct *encode_workqueue;
 
 	int int_cond;
@@ -315,9 +387,11 @@ struct mtk_vcodec_dev {
 	struct mutex dev_mutex;
 	wait_queue_head_t queue;
 
+	int dec_irq;
 	int enc_irq;
 	int enc_lt_irq;
 
+	struct mutex dec_mutex;
 	struct mutex enc_mutex;
 
 	struct mtk_vcodec_pm pm;
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c
index 52e7e5c..f0bdb19 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c
@@ -30,8 +30,7 @@ int mtk_vcodec_wait_for_done_ctx(struct mtk_vcodec_ctx  *ctx, int command,
 	timeout_jiff = msecs_to_jiffies(timeout_ms);
 
 	ret = wait_event_interruptible_timeout(*waitqueue,
-				(ctx->int_cond &&
-				(ctx->int_type == command)),
+				ctx->int_cond,
 				timeout_jiff);
 
 	if (!ret) {
@@ -52,3 +51,4 @@ int mtk_vcodec_wait_for_done_ctx(struct mtk_vcodec_ctx  *ctx, int command,
 	return status;
 }
 EXPORT_SYMBOL(mtk_vcodec_wait_for_done_ctx);
+
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h
index 33e890f..fbb8b1e 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.h
@@ -16,7 +16,7 @@
 #define _MTK_VCODEC_INTR_H_
 
 #define MTK_INST_IRQ_RECEIVED		0x1
-#define MTK_INST_WORK_THREAD_ABORT_DONE	0x2
+
 
 struct mtk_vcodec_ctx;
 
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
index 5e36513..7617305 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
@@ -81,14 +81,35 @@ void mtk_vcodec_mem_free(struct mtk_vcodec_ctx *data,
 		return;
 	}
 
-	dma_free_coherent(dev, size, mem->va, mem->dma_addr);
-	mem->va = NULL;
-	mem->dma_addr = 0;
-	mem->size = 0;
-
 	mtk_v4l2_debug(3, "[%d]  - va      = %p", ctx->id, mem->va);
 	mtk_v4l2_debug(3, "[%d]  - dma     = 0x%lx", ctx->id,
 		       (unsigned long)mem->dma_addr);
 	mtk_v4l2_debug(3, "[%d]    size = 0x%lx", ctx->id, size);
+
+	dma_free_coherent(dev, size, mem->va, mem->dma_addr);
+	mem->va = NULL;
+	mem->dma_addr = 0;
+	mem->size = 0;
 }
 EXPORT_SYMBOL(mtk_vcodec_mem_free);
+
+void mtk_vcodec_set_curr_ctx(struct mtk_vcodec_dev *dev,
+	struct mtk_vcodec_ctx *ctx)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+	dev->curr_ctx = ctx;
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+}
+
+struct mtk_vcodec_ctx *mtk_vcodec_get_curr_ctx(struct mtk_vcodec_dev *dev)
+{
+	unsigned long flags;
+	struct mtk_vcodec_ctx *ctx;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+	ctx = dev->curr_ctx;
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+	return ctx;
+}
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
index d6345fc..91a0b1a 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
@@ -1,7 +1,7 @@
 /*
 * Copyright (c) 2016 MediaTek Inc.
 * Author: PC Chen <pc.chen at mediatek.com>
-*	Tiffany Lin <tiffany.lin at mediatek.com>
+*		Tiffany Lin <tiffany.lin at mediatek.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
@@ -26,6 +26,7 @@ struct mtk_vcodec_mem {
 };
 
 struct mtk_vcodec_ctx;
+struct mtk_vcodec_dev;
 
 extern int mtk_v4l2_dbg_level;
 extern bool mtk_vcodec_dbg;
@@ -84,4 +85,8 @@ int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data,
 				struct mtk_vcodec_mem *mem);
 void mtk_vcodec_mem_free(struct mtk_vcodec_ctx *data,
 				struct mtk_vcodec_mem *mem);
+void mtk_vcodec_set_curr_ctx(struct mtk_vcodec_dev *dev,
+	struct mtk_vcodec_ctx *ctx);
+struct mtk_vcodec_ctx *mtk_vcodec_get_curr_ctx(struct mtk_vcodec_dev *dev);
+
 #endif /* _MTK_VCODEC_UTIL_H_ */
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_base.h b/drivers/media/platform/mtk-vcodec/vdec_drv_base.h
new file mode 100644
index 0000000..7e4c1a9
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_base.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VDEC_DRV_BASE_
+#define _VDEC_DRV_BASE_
+
+#include "mtk_vcodec_drv.h"
+
+#include "vdec_drv_if.h"
+
+struct vdec_common_if {
+	/**
+	 * (*init)() - initialize decode driver
+	 * @ctx     : [in] mtk v4l2 context
+	 * @h_vdec  : [out] driver handle
+	 */
+	int (*init)(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec);
+
+	/**
+	 * (*decode)() - trigger decode
+	 * @h_vdec  : [in] driver handle
+	 * @bs      : [in] input bitstream
+	 * @fb      : [in] frame buffer to store decoded frame
+	 * @res_chg : [out] resolution change happen
+	 */
+	int (*decode)(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+		      struct vdec_fb *fb, bool *res_chg);
+
+	/**
+	 * (*get_param)() - get driver's parameter
+	 * @h_vdec : [in] driver handle
+	 * @type   : [in] input parameter type
+	 * @out    : [out] buffer to store query result
+	 */
+	int (*get_param)(unsigned long h_vdec, enum vdec_get_param_type type,
+			 void *out);
+
+	/**
+	 * (*deinit)() - deinitialize driver.
+	 * @h_vdec : [in] driver handle to be deinit
+	 */
+	void (*deinit)(unsigned long h_vdec);
+};
+
+#endif
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_if.c b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
new file mode 100644
index 0000000..8202b14
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *         Tiffany Lin <tiffany.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "vdec_drv_base.h"
+#include "vdec_drv_if.h"
+
+#include "mtk_vcodec_dec_pm.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
+
+int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
+{
+	int ret = 0;
+
+	switch (fourcc) {
+	case V4L2_PIX_FMT_H264:
+	case V4L2_PIX_FMT_VP8:
+	case V4L2_PIX_FMT_VP9:
+	default:
+		return -EINVAL;
+	}
+
+	mtk_vdec_lock(ctx);
+	mtk_vcodec_dec_clock_on(&ctx->dev->pm);
+	ret = ctx->dec_if->init(ctx, &ctx->drv_handle);
+	mtk_vcodec_dec_clock_off(&ctx->dev->pm);
+	mtk_vdec_unlock(ctx);
+
+	return ret;
+}
+
+int vdec_if_decode(struct mtk_vcodec_ctx *ctx, struct mtk_vcodec_mem *bs,
+		   struct vdec_fb *fb, bool *res_chg)
+{
+	int ret = 0;
+
+	if (bs) {
+		if ((bs->dma_addr & 63) != 0) {
+			mtk_v4l2_err("bs dma_addr should 64 byte align");
+			return -EINVAL;
+		}
+	}
+
+	if (fb) {
+		if (((fb->base_y.dma_addr & 511) != 0) ||
+		    ((fb->base_c.dma_addr & 511) != 0)) {
+			mtk_v4l2_err("frame buffer dma_addr should 512 byte align");
+			return -EINVAL;
+		}
+	}
+
+	mtk_vdec_lock(ctx);
+
+	mtk_vcodec_set_curr_ctx(ctx->dev, ctx);
+	mtk_vcodec_dec_clock_on(&ctx->dev->pm);
+	enable_irq(ctx->dev->dec_irq);
+	ret = ctx->dec_if->decode(ctx->drv_handle, bs, fb, res_chg);
+	disable_irq(ctx->dev->dec_irq);
+	mtk_vcodec_dec_clock_off(&ctx->dev->pm);
+	mtk_vcodec_set_curr_ctx(ctx->dev, NULL);
+
+	mtk_vdec_unlock(ctx);
+
+	return ret;
+}
+
+int vdec_if_get_param(struct mtk_vcodec_ctx *ctx, enum vdec_get_param_type type,
+		      void *out)
+{
+	int ret = 0;
+
+	mtk_vdec_lock(ctx);
+	ret = ctx->dec_if->get_param(ctx->drv_handle, type, out);
+	mtk_vdec_unlock(ctx);
+
+	return ret;
+}
+
+void vdec_if_deinit(struct mtk_vcodec_ctx *ctx)
+{
+	if (ctx->drv_handle == 0)
+		return;
+
+	mtk_vdec_lock(ctx);
+	mtk_vcodec_dec_clock_on(&ctx->dev->pm);
+	ctx->dec_if->deinit(ctx->drv_handle);
+	mtk_vcodec_dec_clock_off(&ctx->dev->pm);
+	mtk_vdec_unlock(ctx);
+
+	ctx->drv_handle = 0;
+}
diff --git a/drivers/media/platform/mtk-vcodec/vdec_drv_if.h b/drivers/media/platform/mtk-vcodec/vdec_drv_if.h
new file mode 100644
index 0000000..db6b520
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_drv_if.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *		   Tiffany Lin <tiffany.lin at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VDEC_DRV_IF_H_
+#define _VDEC_DRV_IF_H_
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_dec.h"
+#include "mtk_vcodec_util.h"
+
+
+/**
+ * struct vdec_fb_status  - decoder frame buffer status
+ * @FB_ST_NORMAL	: initial state
+ * @FB_ST_DISPLAY	: frmae buffer is ready to be displayed
+ * @FB_ST_FREE		: frame buffer is not used by decoder any more
+ */
+enum vdec_fb_status {
+	FB_ST_NORMAL		= 0,
+	FB_ST_DISPLAY		= (1 << 0),
+	FB_ST_FREE		= (1 << 1)
+};
+
+/* For GET_PARAM_DISP_FRAME_BUFFER and GET_PARAM_FREE_FRAME_BUFFER,
+ * the caller does not own the returned buffer. The buffer will not be
+ *				released before vdec_if_deinit.
+ * GET_PARAM_DISP_FRAME_BUFFER	: get next displayable frame buffer,
+ *				struct vdec_fb**
+ * GET_PARAM_FREE_FRAME_BUFFER	: get non-referenced framebuffer, vdec_fb**
+ * GET_PARAM_PIC_INFO		: get picture info, struct vdec_pic_info*
+ * GET_PARAM_CROP_INFO		: get crop info, struct v4l2_crop*
+ * GET_PARAM_DPB_SIZE		: get dpb size, unsigned int*
+ */
+enum vdec_get_param_type {
+	GET_PARAM_DISP_FRAME_BUFFER,
+	GET_PARAM_FREE_FRAME_BUFFER,
+	GET_PARAM_PIC_INFO,
+	GET_PARAM_CROP_INFO,
+	GET_PARAM_DPB_SIZE
+};
+
+/**
+ * struct vdec_fb_node  - decoder frame buffer node
+ * @list	: list to hold this node
+ * @fb	: point to frame buffer (vdec_fb), fb could point to frame buffer and
+ *	working buffer this is for maintain buffers in different state
+ */
+struct vdec_fb_node {
+	struct list_head list;
+	struct vdec_fb *fb;
+};
+
+/**
+ * vdec_if_init() - initialize decode driver
+ * @ctx	: [in] v4l2 context
+ * @fourcc	: [in] video format fourcc, V4L2_PIX_FMT_H264/VP8/VP9..
+ */
+int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc);
+
+/**
+ * vdec_if_deinit() - deinitialize decode driver
+ * @ctx	: [in] v4l2 context
+ *
+ */
+void vdec_if_deinit(struct mtk_vcodec_ctx *ctx);
+
+/**
+ * vdec_if_decode() - trigger decode
+ * @ctx	: [in] v4l2 context
+ * @bs	: [in] input bitstream
+ * @fb	: [in] frame buffer to store decoded frame, when null menas parse
+ *	header only
+ * @res_chg	: [out] resolution change happens if current bs have different
+ *	picture width/height
+ * Note: To flush the decoder when reaching EOF, set input bitstream as NULL.
+ */
+int vdec_if_decode(struct mtk_vcodec_ctx *ctx, struct mtk_vcodec_mem *bs,
+		   struct vdec_fb *fb, bool *res_chg);
+
+/**
+ * vdec_if_get_param() - get driver's parameter
+ * @ctx	: [in] v4l2 context
+ * @type	: [in] input parameter type
+ * @out	: [out] buffer to store query result
+ */
+int vdec_if_get_param(struct mtk_vcodec_ctx *ctx, enum vdec_get_param_type type,
+		      void *out);
+
+#endif
diff --git a/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h b/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
new file mode 100644
index 0000000..5a8a629
--- /dev/null
+++ b/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen at mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VDEC_IPI_MSG_H_
+#define _VDEC_IPI_MSG_H_
+
+/**
+ * enum vdec_ipi_msgid - message id between AP and VPU
+ * @AP_IPIMSG_XXX	: AP to VPU cmd message id
+ * @VPU_IPIMSG_XXX_ACK	: VPU ack AP cmd message id
+ */
+enum vdec_ipi_msgid {
+	AP_IPIMSG_DEC_INIT = 0xA000,
+	AP_IPIMSG_DEC_START = 0xA001,
+	AP_IPIMSG_DEC_END = 0xA002,
+	AP_IPIMSG_DEC_DEINIT = 0xA003,
+	AP_IPIMSG_DEC_RESET = 0xA004,
+
+	VPU_IPIMSG_DEC_INIT_ACK = 0xB000,
+	VPU_IPIMSG_DEC_START_ACK = 0xB001,
+	VPU_IPIMSG_DEC_END_ACK = 0xB002,
+	VPU_IPIMSG_DEC_DEINIT_ACK = 0xB003,
+	VPU_IPIMSG_DEC_RESET_ACK = 0xB004,
+};
+
+/**
+ * struct vdec_ap_ipi_cmd - generic AP to VPU ipi command format
+ * @msg_id	: vdec_ipi_msgid
+ * @vpu_inst_addr	: VPU decoder instance address
+ */
+struct vdec_ap_ipi_cmd {
+	uint32_t msg_id;
+	uint32_t vpu_inst_addr;
+};
+
+/**
+ * struct vdec_vpu_ipi_ack - generic VPU to AP ipi command format
+ * @msg_id	: vdec_ipi_msgid
+ * @status	: VPU exeuction result
+ * @ap_inst_addr	: AP video decoder instance address
+ */
+struct vdec_vpu_ipi_ack {
+	uint32_t msg_id;
+	int32_t status;
+	uint64_t ap_inst_addr;
+};
+
+/**
+ * struct vdec_ap_ipi_init - for AP_IPIMSG_DEC_INIT
+ * @msg_id	: AP_IPIMSG_DEC_INIT
+ * @reserved	: Reserved field
+ * @ap_inst_addr	: AP video decoder instance address
+ */
+struct vdec_ap_ipi_init {
+	uint32_t msg_id;
+	uint32_t reserved;
+	uint64_t ap_inst_addr;
+};
+
+/**
+ * struct vdec_ap_ipi_dec_start - for AP_IPIMSG_DEC_START
+ * @msg_id	: AP_IPIMSG_DEC_START
+ * @vpu_inst_addr	: VPU decoder instance address
+ * @data	: Header info
+ *	H264 decoder [0]:buf_sz [1]:nal_start
+ *	VP8 decoder  [0]:width/height
+ *	VP9 decoder  [0]:profile, [1][2] width/height
+ * @reserved	: Reserved field
+ */
+struct vdec_ap_ipi_dec_start {
+	uint32_t msg_id;
+	uint32_t vpu_inst_addr;
+	uint32_t data[3];
+	uint32_t reserved;
+};
+
+/**
+ * struct vdec_vpu_ipi_init_ack - for VPU_IPIMSG_DEC_INIT_ACK
+ * @msg_id	: VPU_IPIMSG_DEC_INIT_ACK
+ * @status	: VPU exeuction result
+ * @ap_inst_addr	: AP vcodec_vpu_inst instance address
+ * @vpu_inst_addr	: VPU decoder instance address
+ */
+struct vdec_vpu_ipi_init_ack {
+	uint32_t msg_id;
+	int32_t status;
+	uint64_t ap_inst_addr;
+	uint32_t vpu_inst_addr;
+};
+
+#endif
-- 
1.7.9.5



From tiffany.lin at mediatek.com  Mon May 30 05:29:18 2016
From: tiffany.lin at mediatek.com (Tiffany Lin)
Date: Mon, 30 May 2016 20:29:18 +0800
Subject: [PATCH v3 4/9] dt-bindings: Add a binding for Mediatek Video Decoder
In-Reply-To: <1464611363-14936-4-git-send-email-tiffany.lin@mediatek.com>
References: <1464611363-14936-1-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-2-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-3-git-send-email-tiffany.lin@mediatek.com>
 <1464611363-14936-4-git-send-email-tiffany.lin@mediatek.com>
Message-ID: <1464611363-14936-5-git-send-email-tiffany.lin@mediatek.com>

Add a DT binding documentation of Video Decoder for the
MT8173 SoC from Mediatek.

Signed-off-by: Tiffany Lin <tiffany.lin at mediatek.com>
Acked-by: Rob Herring <rob at kernel.org>
---
 .../devicetree/bindings/media/mediatek-vcodec.txt  |   57 ++++++++++++++++++--
 1 file changed, 53 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/mediatek-vcodec.txt b/Documentation/devicetree/bindings/media/mediatek-vcodec.txt
index 59a47a5..46c15c5 100644
--- a/Documentation/devicetree/bindings/media/mediatek-vcodec.txt
+++ b/Documentation/devicetree/bindings/media/mediatek-vcodec.txt
@@ -1,25 +1,74 @@
 Mediatek Video Codec
 
 Mediatek Video Codec is the video codec hw present in Mediatek SoCs which
-supports high resolution encoding functionalities.
+supports high resolution encoding and decoding functionalities.
 
 Required properties:
 - compatible : "mediatek,mt8173-vcodec-enc" for encoder
+  "mediatek,mt8173-vcodec-dec" for decoder.
 - reg : Physical base address of the video codec registers and length of
   memory mapped region.
 - interrupts : interrupt number to the cpu.
 - mediatek,larb : must contain the local arbiters in the current Socs.
 - clocks : list of clock specifiers, corresponding to entries in
   the clock-names property.
-- clock-names: encoder must contain "venc_sel_src", "venc_sel",
-- "venc_lt_sel_src", "venc_lt_sel".
+- clock-names: encoder must contain "venc_sel_src", "venc_sel",,
+  "venc_lt_sel_src", "venc_lt_sel", decoder must contain "vcodecpll",
+  "univpll_d2", "clk_cci400_sel", "vdec_sel", "vdecpll", "vencpll",
+  "venc_lt_sel", "vdec_bus_clk_src".
 - iommus : should point to the respective IOMMU block with master port as
   argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
   for details.
 - mediatek,vpu : the node of video processor unit
 
+
 Example:
-vcodec_enc: vcodec at 0x18002000 {
+
+vcodec_dec: vcodec at 16000000 {
+    compatible = "mediatek,mt8173-vcodec-dec";
+    reg = <0 0x16000000 0 0x100>,   /*VDEC_SYS*/
+          <0 0x16020000 0 0x1000>,  /*VDEC_MISC*/
+          <0 0x16021000 0 0x800>,   /*VDEC_LD*/
+          <0 0x16021800 0 0x800>,   /*VDEC_TOP*/
+          <0 0x16022000 0 0x1000>,  /*VDEC_CM*/
+          <0 0x16023000 0 0x1000>,  /*VDEC_AD*/
+          <0 0x16024000 0 0x1000>,  /*VDEC_AV*/
+          <0 0x16025000 0 0x1000>,  /*VDEC_PP*/
+          <0 0x16026800 0 0x800>,   /*VP8_VD*/
+          <0 0x16027000 0 0x800>,   /*VP6_VD*/
+          <0 0x16027800 0 0x800>,   /*VP8_VL*/
+          <0 0x16028400 0 0x400>;   /*VP9_VD*/
+    interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_LOW>;
+    mediatek,larb = <&larb1>;
+    iommus = <&iommu M4U_PORT_HW_VDEC_MC_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_PP_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_AVC_MV_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_PRED_RD_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_PRED_WR_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_UFO_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_VLD_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_VLD2_EXT>;
+    mediatek,vpu = <&vpu>;
+    power-domains = <&scpsys MT8173_POWER_DOMAIN_VDEC>;
+    clocks = <&apmixedsys CLK_APMIXED_VCODECPLL>,
+             <&topckgen CLK_TOP_UNIVPLL_D2>,
+             <&topckgen CLK_TOP_CCI400_SEL>,
+             <&topckgen CLK_TOP_VDEC_SEL>,
+             <&topckgen CLK_TOP_VCODECPLL>,
+             <&apmixedsys CLK_APMIXED_VENCPLL>,
+             <&topckgen CLK_TOP_VENC_LT_SEL>,
+             <&topckgen CLK_TOP_VCODECPLL_370P5>;
+    clock-names = "vcodecpll",
+                  "univpll_d2",
+                  "clk_cci400_sel",
+                  "vdec_sel",
+                  "vdecpll",
+                  "vencpll",
+                  "venc_lt_sel",
+                  "vdec_bus_clk_src";
+  };
+
+  vcodec_enc: vcodec at 0x18002000 {
     compatible = "mediatek,mt8173-vcodec-enc";
     reg = <0 0x18002000 0 0x1000>,    /*VENC_SYS*/
           <0 0x19002000 0 0x1000>;    /*VENC_LT_SYS*/
-- 
1.7.9.5



From s.nawrocki at samsung.com  Mon May 30 05:49:37 2016
From: s.nawrocki at samsung.com (Sylwester Nawrocki)
Date: Mon, 30 May 2016 14:49:37 +0200
Subject: [PATCH 1/2] clk: exynos5420: Set ID for aclk333 gate clock
In-Reply-To: <1464111662-15336-2-git-send-email-javier@osg.samsung.com>
References: <1464111662-15336-1-git-send-email-javier@osg.samsung.com>
 <1464111662-15336-2-git-send-email-javier@osg.samsung.com>
Message-ID: <574C36E1.5000709@samsung.com>

On 05/24/2016 07:41 PM, Javier Martinez Canillas wrote:
> The aclk333 clock needs to be ungated during the MFC power domain switch,
> so set the clock ID to allow the Exynos power domain logic to lookup this
> clock if is defined in the MFC PD device tree node.
> 
> Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>

Thanks, patch applied.



From s.nawrocki at samsung.com  Mon May 30 05:50:32 2016
From: s.nawrocki at samsung.com (Sylwester Nawrocki)
Date: Mon, 30 May 2016 14:50:32 +0200
Subject: [PATCH] clk: samsung: exynos7: Don't gate CMU_{CCORE,
 FSYS0} blocks clock
In-Reply-To: <1460608972-13878-1-git-send-email-alim.akhtar@samsung.com>
References: <1460608972-13878-1-git-send-email-alim.akhtar@samsung.com>
Message-ID: <574C3718.3050301@samsung.com>

On 04/14/2016 06:42 AM, Alim Akhtar wrote:
> This patch adds CLK_IS_CRITICAL flag to ACLK_CCORE_133 and ACLK_FSYS0_200
> clocks. These clocks are critical for accessing CMU_CCORE and CMU_FSYS0
> blocks registers. Let these clocks to be enabled all the time.
> 
> Signed-off-by: Alim Akhtar <alim.akhtar at samsung.com>

Patch applied, thanks.



From zourongrong at huawei.com  Mon May 30 05:51:40 2016
From: zourongrong at huawei.com (Rongrong Zou)
Date: Mon, 30 May 2016 20:51:40 +0800
Subject: [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master
 driver
In-Reply-To: <574C2D6A.3090508@huawei.com>
References: <1464514855-108050-1-git-send-email-zourongrong@gmail.com>
 <1464514855-108050-2-git-send-email-zourongrong@gmail.com>
 <20160530090331.GD27098@phenom.ffwll.local> <574C2D6A.3090508@huawei.com>
Message-ID: <574C375C.5020007@huawei.com>

Sorry, forgot to add daniel at ffwll.ch to sendto list.

? 2016/5/30 20:09, Rongrong Zou ??:
> Hi Daniel,
> Thanks for reveiwing!
>
> ? 2016/5/30 17:03, Daniel Vetter ??:
>> On Sun, May 29, 2016 at 05:40:49PM +0800, Rongrong Zou wrote:
>>> Add DRM master driver for Hisilicon Hibmc SoC which used for
>>> Out-of-band management. Blow is the general hardware connection,
>>> both the Hibmc and the host CPU are on the same mother board.
>>>
>>> +----------+       +----------+
>>> |          | PCIe  |  Hibmc   |
>>> |host CPU( |<----->| display  |
>>> |arm64,x86)|       |subsystem |
>>> +----------+       +----------+
>>>
>>> Signed-off-by: Rongrong Zou <zourongrong at gmail.com>
>>> Signed-off-by: Jianhua Li <lijianhua at huawei.com>
>>> ---
>>>   drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
>>>   drivers/gpu/drm/hisilicon/Makefile                |   3 +-
>>>   drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
>>>   drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
>>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 307 ++++++++++++++++++++++
>>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  39 +++
>>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++++
>>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
>>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 +++++++++++++++
>>>   9 files changed, 699 insertions(+), 1 deletion(-)
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>>>
>>> diff --git a/drivers/gpu/drm/hisilicon/Kconfig b/drivers/gpu/drm/hisilicon/Kconfig
>>> index 558c61b..2fd2724 100644
>>> --- a/drivers/gpu/drm/hisilicon/Kconfig
>>> +++ b/drivers/gpu/drm/hisilicon/Kconfig
>>> @@ -2,4 +2,5 @@
>>>   # hisilicon drm device configuration.
>>>   # Please keep this list sorted alphabetically
>>>
>>> +source "drivers/gpu/drm/hisilicon/hibmc/Kconfig"
>>>   source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
>>> diff --git a/drivers/gpu/drm/hisilicon/Makefile b/drivers/gpu/drm/hisilicon/Makefile
>>> index e3f6d49..4d7185c 100644
>>> --- a/drivers/gpu/drm/hisilicon/Makefile
>>> +++ b/drivers/gpu/drm/hisilicon/Makefile
>>> @@ -2,4 +2,5 @@
>>>   # Makefile for hisilicon drm drivers.
>>>   # Please keep this list sorted alphabetically
>>>
>>> -obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
>>> +obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/
>>> +obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
>>> \ No newline at end of file
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>> new file mode 100644
>>> index 0000000..1e7810d
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>> @@ -0,0 +1,13 @@
>>> +config DRM_HISI_HIBMC
>>> +    tristate "DRM Support for Hisilicon Hibmc"
>>> +    depends on DRM && PCI
>>> +    select DRM_KMS_HELPER
>>> +    select DRM_KMS_FB_HELPER
>>> +    select DRM_GEM_CMA_HELPER
>>> +    select DRM_KMS_CMA_HELPER
>>> +    select FB_SYS_FILLRECT
>>> +    select FB_SYS_COPYAREA
>>> +    select FB_SYS_IMAGEBLIT
>>> +    help
>>> +      Choose this option if you have a Hisilicon Hibmc soc chipset.
>>> +      If M is selected the module will be called hibmc-drm.
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>>> new file mode 100644
>>> index 0000000..533f9ed
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>>> @@ -0,0 +1,4 @@
>>> +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
>>> +
>>> +obj-$(CONFIG_DRM_HISI_HIBMC)    +=hibmc-drm.o
>>> +#obj-y    += hibmc-drm.o
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>> new file mode 100644
>>> index 0000000..7eaacd8
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>> @@ -0,0 +1,307 @@
>>> +/* Hisilicon Hibmc SoC drm driver
>>> + *
>>> + * Based on the bochs drm driver.
>>> + *
>>> + * Copyright (c) 2016 Huawei Limited.
>>> + *
>>> + * Author:
>>> + *    Rongrong Zou <zourongrong at huawei>
>>> + *    Rongrong Zou <zourongrong at gmail.com>
>>> + *    Jianhua Li <lijianhua at huawei.com>
>>> + *
>>> + * 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.
>>> + *
>>> + */
>>> +
>>> +#include <linux/module.h>
>>> +#include <linux/console.h>
>>> +#include <drm/drm_atomic_helper.h>
>>> +#include <drm/drm_crtc_helper.h>
>>> +#include <drm/drm_fb_helper.h>
>>> +#include <drm/drm_gem_cma_helper.h>
>>> +#include <drm/drmP.h>
>>> +
>>> +#include "hibmc_drm_drv.h"
>>> +#include "hibmc_drm_regs.h"
>>> +#include "hibmc_drm_power.h"
>>> +
>>> +static const struct file_operations hibmc_fops = {
>>> +    .owner        = THIS_MODULE,
>>> +    .open        = drm_open,
>>> +    .release    = drm_release,
>>> +    .unlocked_ioctl    = drm_ioctl,
>>> +#ifdef CONFIG_COMPAT
>>> +    .compat_ioctl    = drm_compat_ioctl,
>>> +#endif
>>> +    .poll        = drm_poll,
>>> +    .read        = drm_read,
>>> +    .llseek        = no_llseek,
>>> +};
>>> +
>>> +static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
>>> +{
>>> +    return 0;
>>> +}
>>> +
>>> +static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
>>> +{
>>> +}
>>> +
>>> +static struct drm_driver hibmc_driver = {
>>> +    .driver_features    = DRIVER_GEM | DRIVER_MODESET,
>>> +    .fops            = &hibmc_fops,
>>> +    .name            = "hibmc",
>>> +    .desc            = "hibmc drm driver",
>>> +    .major            = 1,
>>> +    .minor            = 0,
>>> +    .get_vblank_counter = drm_vblank_no_hw_counter,
>>> +    .enable_vblank        = hibmc_enable_vblank,
>>> +    .disable_vblank    = hibmc_disable_vblank,
>>> +    .gem_free_object        = drm_gem_cma_free_object,
>>
>> gem_free_object_unlocked pls.
>
> Applied, thanks.
>
>>
>>> +    .gem_vm_ops        = &drm_gem_cma_vm_ops,
>>> +    .dumb_create            = drm_gem_cma_dumb_create,
>>> +    .dumb_map_offset        = drm_gem_cma_dumb_map_offset,
>>> +    .dumb_destroy           = drm_gem_dumb_destroy,
>>> +};
>>> +
>>> +static int hibmc_pm_suspend(struct device *dev)
>>> +{
>>> +    struct pci_dev *pdev = to_pci_dev(dev);
>>> +    struct drm_device *drm_dev = pci_get_drvdata(pdev);
>>> +
>>> +    drm_kms_helper_poll_disable(drm_dev);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int hibmc_pm_resume(struct device *dev)
>>> +{
>>> +    struct pci_dev *pdev = to_pci_dev(dev);
>>> +    struct drm_device *drm_dev = pci_get_drvdata(pdev);
>>> +
>>> +    drm_helper_resume_force_mode(drm_dev);
>>> +    drm_kms_helper_poll_enable(drm_dev);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static const struct dev_pm_ops hibmc_pm_ops = {
>>> +    SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
>>> +                hibmc_pm_resume)
>>> +};
>>> +
>>> +static const struct drm_mode_config_funcs mode_config_funcs = {
>>> +    .atomic_check = drm_atomic_helper_check,
>>> +    .atomic_commit = drm_atomic_helper_commit,
>>
>> So how exactly does nonblocking commit work for you? Please run the igt
>> validation suit on your new driver, a bunch of collabora engineers are
>> working hard to make it run on non-intel drivers too. Ping Tomeu and
>> Robert Foss for more info on this please.
>
> OK, I should learn igt validation suit and test the new driver.
> I tested the driver with tools such as fbtest before. Thanks.
>
>>
>> Lucky for you I'm working on generic nonblocking support in the atomic
>> helpers, patches are on the mailing list.
>>
>
> It's nice, thanks. :)
>
>>> +};
>>> +
>>> +
>>> +static int hibmc_hw_config(struct hibmc_drm_device *hidev)
>>> +{
>>> +    unsigned int reg;
>>> +
>>> +    /* On hardware reset, power mode 0 is default. */
>>> +    hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
>>> +
>>> +    /* Enable display power gate & LOCALMEM power gate*/
>>> +    reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
>>> +    reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
>>> +    reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
>>> +    reg |= HIBMC_CURR_GATE_DISPLAY(ON);
>>> +    reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
>>> +
>>> +    hibmc_set_current_gate(hidev, reg);
>>> +
>>> +    /* Reset the memory controller. If the memory controller
>>> +     * is not reset in chip,the system might hang when sw accesses
>>> +     * the memory.The memory should be resetted after
>>> +     * changing the MXCLK.
>>> +     */
>>> +    reg = readl(hidev->mmio + HIBMC_MISC_CTRL);
>>> +    reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
>>> +    reg |= HIBMC_MSCCTL_LOCALMEM_RESET(RESET);
>>> +    writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
>>> +
>>> +    reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
>>> +    reg |= HIBMC_MSCCTL_LOCALMEM_RESET(NORMAL);
>>> +
>>> +    writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
>>> +
>>> +    /* We can add more initialization as needed. */
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int hibmc_hw_map(struct hibmc_drm_device *hidev)
>>> +{
>>> +    struct drm_device *dev = hidev->dev;
>>> +    struct pci_dev *pdev = dev->pdev;
>>> +    resource_size_t addr, size, ioaddr, iosize;
>>> +
>>> +    ioaddr = pci_resource_start(pdev, 1);
>>> +    iosize = MB(2);
>>> +
>>> +    hidev->mmio = ioremap_nocache(ioaddr, iosize);
>>> +
>>> +    if (!hidev->mmio) {
>>> +        DRM_ERROR("Cannot map mmio region\n");
>>> +        return -ENOMEM;
>>> +    }
>>> +
>>> +    addr = pci_resource_start(pdev, 0);
>>> +    size = MB(16);
>>> +
>>> +    hidev->fb_map = ioremap(addr, size);
>>> +    if (!hidev->fb_map) {
>>> +        DRM_ERROR("Cannot map framebuffer\n");
>>> +        return -ENOMEM;
>>> +    }
>>> +    hidev->fb_base = addr;
>>> +    hidev->fb_size = size;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static void hibmc_hw_fini(struct hibmc_drm_device *hidev)
>>> +{
>>> +    if (hidev->mmio)
>>> +        iounmap(hidev->mmio);
>>> +    if (hidev->fb_map)
>>> +        iounmap(hidev->fb_map);
>>> +}
>>> +
>>> +static int hibmc_hw_init(struct hibmc_drm_device *hidev)
>>> +{
>>> +    int ret;
>>> +
>>> +    ret = hibmc_hw_map(hidev);
>>> +    if (ret)
>>> +        return ret;
>>> +
>>> +    hibmc_hw_config(hidev);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int hibmc_unload(struct drm_device *dev)
>>> +{
>>> +    struct hibmc_drm_device *hidev = dev->dev_private;
>>> +
>>> +    hibmc_hw_fini(hidev);
>>> +    dev->dev_private = NULL;
>>> +    return 0;
>>> +}
>>> +
>>> +static int hibmc_load(struct drm_device *dev, unsigned long flags)
>>> +{
>>> +    struct hibmc_drm_device *hidev;
>>> +    int ret;
>>> +
>>> +    hidev = devm_kzalloc(dev->dev, sizeof(*hidev), GFP_KERNEL);
>>> +    if (!hidev)
>>> +        return -ENOMEM;
>>> +    dev->dev_private = hidev;
>>> +    hidev->dev = dev;
>>> +
>>> +    ret = hibmc_hw_init(hidev);
>>> +    if (ret)
>>> +        goto err;
>>> +
>>> +
>>> +    ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
>>> +    if (ret) {
>>> +        DRM_ERROR("failed to initialize vblank.\n");
>>> +        return ret;
>>> +    }
>>> +    /* reset all the states of crtc/plane/encoder/connector */
>>> +    drm_mode_config_reset(dev);
>>> +
>>> +    return 0;
>>> +
>>> +err:
>>> +    hibmc_unload(dev);
>>> +    DRM_ERROR("failed to initialize drm driver.\n");
>>> +    return ret;
>>> +}
>>> +
>>> +
>>> +static int hibmc_pci_probe(struct pci_dev *pdev,
>>> +               const struct pci_device_id *ent)
>>> +{
>>> +    struct drm_device *dev;
>>> +    int ret;
>>> +
>>> +    dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
>>> +    if (!dev)
>>> +        return -ENOMEM;
>>> +
>>> +    dev->pdev = pdev;
>>> +    pci_set_drvdata(pdev, dev);
>>> +
>>> +    ret = pci_enable_device(pdev);
>>> +    if (ret)
>>> +        goto err_free;
>>> +
>>> +    ret = hibmc_load(dev, 0);
>>> +    if (ret)
>>> +        goto err_disable;
>>> +
>>> +    ret = drm_dev_register(dev, 0);
>>> +    if (ret)
>>> +        goto err_unload;
>>> +
>>> +    return 0;
>>> +
>>> +err_unload:
>>> +    hibmc_unload(dev);
>>> +err_disable:
>>> +    pci_disable_device(pdev);
>>> +err_free:
>>> +    drm_dev_unref(dev);
>>> +
>>> +    return ret;
>>> +}
>>> +
>>> +static void hibmc_pci_remove(struct pci_dev *pdev)
>>> +{
>>> +    struct drm_device *dev = pci_get_drvdata(pdev);
>>> +
>>> +    drm_dev_unregister(dev);
>>> +    hibmc_unload(dev);
>>> +    drm_dev_unref(dev);
>>> +}
>>> +
>>> +static struct pci_device_id hibmc_pci_table[] = {
>>> +    {0x19e5, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
>>> +    {0,}
>>> +};
>>> +
>>> +static struct pci_driver hibmc_pci_driver = {
>>> +    .name =        "hibmc-drm",
>>> +    .id_table =    hibmc_pci_table,
>>> +    .probe =    hibmc_pci_probe,
>>> +    .remove =    hibmc_pci_remove,
>>> +    .driver.pm =    &hibmc_pm_ops,
>>> +};
>>> +
>>> +static int __init hibmc_init(void)
>>> +{
>>> +    return pci_register_driver(&hibmc_pci_driver);
>>> +}
>>> +
>>> +static void __exit hibmc_exit(void)
>>> +{
>>> +    return pci_unregister_driver(&hibmc_pci_driver);
>>> +}
>>> +
>>> +module_init(hibmc_init);
>>> +module_exit(hibmc_exit);
>>> +
>>> +MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
>>> +MODULE_AUTHOR("RongrongZou <zourongrong at huawei.com>");
>>> +MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
>>> +MODULE_LICENSE("GPL v2");
>>> +
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>> new file mode 100644
>>> index 0000000..a072ea9
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>> @@ -0,0 +1,39 @@
>>> +/* Hisilicon Hibmc SoC drm driver
>>> + *
>>> + * Based on the bochs drm driver.
>>> + *
>>> + * Copyright (c) 2016 Huawei Limited.
>>> + *
>>> + * Author:
>>> + *    Rongrong Zou <zourongrong at huawei>
>>> + *    Rongrong Zou <zourongrong at gmail.com>
>>> + *    Jianhua Li <lijianhua at huawei.com>
>>> + *
>>> + * 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.
>>> + *
>>> + */
>>> +
>>> +#ifndef HIBMC_DRM_DRV_H
>>> +#define HIBMC_DRM_DRV_H
>>> +
>>> +#include <drm/drmP.h>
>>> +#include <drm/drm_fb_helper.h>
>>> +#include <drm/drm_gem_cma_helper.h>
>>> +
>>> +struct hibmc_drm_device {
>>> +    /* hw */
>>> +    void __iomem   *mmio;
>>> +    void __iomem   *fb_map;
>>> +    unsigned long  fb_base;
>>> +    unsigned long  fb_size;
>>> +
>>> +    /* drm */
>>> +    struct drm_device  *dev;
>>> +    bool mode_config_initialized;
>>> +};
>>> +
>>> +
>>> +#endif
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>>> new file mode 100644
>>> index 0000000..673be10
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>>> @@ -0,0 +1,91 @@
>>> +/* Hisilicon Hibmc SoC drm driver
>>> + *
>>> + * Based on the bochs drm driver.
>>> + *
>>> + * Copyright (c) 2016 Huawei Limited.
>>> + *
>>> + * Author:
>>> + *    Rongrong Zou <zourongrong at huawei>
>>> + *    Rongrong Zou <zourongrong at gmail.com>
>>> + *    Jianhua Li <lijianhua at huawei.com>
>>> + *
>>> + * 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.
>>> + *
>>> + */
>>> +
>>> +#include <linux/io.h>
>>> +#include <drm/drmP.h>
>>> +#include <drm/drm_fb_helper.h>
>>> +#include "hibmc_drm_drv.h"
>>> +#include "hibmc_drm_regs.h"
>>> +
>>> +/*
>>> + * It can operate in one of three modes: 0, 1 or Sleep.
>>> + */
>>> +void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
>>> +                 unsigned int power_mode)
>>> +{
>>> +    unsigned int control_value = 0;
>>> +    void __iomem   *mmio = hidev->mmio;
>>> +
>>> +    if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
>>> +        return;
>>> +
>>> +    control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
>>> +    control_value &= ~HIBMC_PW_MODE_CTL_MODE_MASK;
>>> +
>>> +    control_value |= HIBMC_PW_MODE_CTL_MODE(power_mode) &
>>> +             HIBMC_PW_MODE_CTL_MODE_MASK;
>>> +
>>> +
>>> +    /* Set up other fields in Power Control Register */
>>> +    if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP) {
>>> +        control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>>> +        control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(0) &
>>> +                 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>>> +    } else {
>>> +        control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>>> +        control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(1) &
>>> +                 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>>> +
>>> +    }
>>> +    /* Program new power mode. */
>>> +    writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
>>> +}
>>> +
>>> +static unsigned int hibmc_get_power_mode(struct hibmc_drm_device *hidev)
>>> +{
>>> +    void __iomem   *mmio = hidev->mmio;
>>> +
>>> +    return (readl(mmio + HIBMC_POWER_MODE_CTRL)&
>>> +        HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
>>> +}
>>> +
>>> +void hibmc_set_current_gate(struct hibmc_drm_device *hidev, unsigned int gate)
>>> +{
>>> +    unsigned int gate_reg;
>>> +    unsigned int mode;
>>> +    void __iomem   *mmio = hidev->mmio;
>>> +
>>> +    /* Get current power mode. */
>>> +    mode = hibmc_get_power_mode(hidev);
>>> +
>>> +    switch (mode) {
>>> +    case HIBMC_PW_MODE_CTL_MODE_MODE0:
>>> +        gate_reg = HIBMC_MODE0_GATE;
>>> +        break;
>>> +
>>> +    case HIBMC_PW_MODE_CTL_MODE_MODE1:
>>> +        gate_reg = HIBMC_MODE1_GATE;
>>> +        break;
>>> +
>>> +    default:
>>> +        gate_reg = HIBMC_MODE0_GATE;
>>> +        break;
>>> +    }
>>> +    writel(gate, mmio + gate_reg);
>>> +}
>>> +
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>>> new file mode 100644
>>> index 0000000..39f7a17
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>>> @@ -0,0 +1,28 @@
>>> +/* Hisilicon Hibmc SoC drm driver
>>> + *
>>> + * Based on the bochs drm driver.
>>> + *
>>> + * Copyright (c) 2016 Huawei Limited.
>>> + *
>>> + * Author:
>>> + *    Rongrong Zou <zourongrong at huawei>
>>> + *    Rongrong Zou <zourongrong at gmail.com>
>>> + *    Jianhua Li <lijianhua at huawei.com>
>>> + *
>>> + * 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.
>>> + *
>>> + */
>>> +
>>> +#ifndef HIBMC_DRM_POWER_H
>>> +#define HIBMC_DRM_POWER_H
>>> +
>>> +#include "hibmc_drm_drv.h"
>>> +
>>> +extern void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
>>> +                 unsigned int power_mode);
>>> +extern void hibmc_set_current_gate(struct hibmc_drm_device *hidev,
>>> +                   unsigned int gate);
>>> +#endif
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>>> new file mode 100644
>>> index 0000000..4966c42
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>>> @@ -0,0 +1,214 @@
>>> +/* Hisilicon Hibmc SoC drm driver
>>> + *
>>> + * Based on the bochs drm driver.
>>> + *
>>> + * Copyright (c) 2016 Huawei Limited.
>>> + *
>>> + * Author:
>>> + *    Rongrong Zou <zourongrong at huawei>
>>> + *    Rongrong Zou <zourongrong at gmail.com>
>>> + *    Jianhua Li <lijianhua at huawei.com>
>>> + *
>>> + * 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.
>>> + *
>>> + */
>>> +
>>> +#ifndef HIBMC_DRM_HW_H
>>> +#define HIBMC_DRM_HW_H
>>> +
>>> +#define OFF 0
>>> +#define ON  1
>>> +#define DISABLE               0
>>> +#define ENABLE                1
>>> +
>>> +
>>> +
>>> +/* register definition */
>>> +#define HIBMC_MISC_CTRL                0x4
>>> +
>>> +#define HIBMC_MSCCTL_LOCALMEM_RESET(x)        ((x) << 6)
>>> +#define HIBMC_MSCCTL_LOCALMEM_RESET_MASK    0x40
>>> +
>>> +#define RESET                0
>>> +#define NORMAL               1
>>> +
>>> +#define HIBMC_CURRENT_GATE            0x000040
>>> +#define HIBMC_CURR_GATE_DISPLAY(x)        ((x) << 2)
>>> +#define HIBMC_CURR_GATE_DISPLAY_MASK        0x4
>>> +
>>> +#define HIBMC_CURR_GATE_LOCALMEM(x)        ((x) << 1)
>>> +#define HIBMC_CURR_GATE_LOCALMEM_MASK        0x2
>>> +
>>> +#define HIBMC_MODE0_GATE            0x000044
>>> +#define HIBMC_MODE1_GATE            0x000048
>>> +#define HIBMC_POWER_MODE_CTRL            0x00004C
>>> +
>>> +#define HIBMC_PW_MODE_CTL_OSC_INPUT(x)        ((x) << 3)
>>> +#define HIBMC_PW_MODE_CTL_OSC_INPUT_MASK    0x8
>>> +
>>> +#define HIBMC_PW_MODE_CTL_MODE(x)        ((x) << 0)
>>> +#define HIBMC_PW_MODE_CTL_MODE_MASK        0x03
>>> +#define HIBMC_PW_MODE_CTL_MODE_SHIFT        0
>>> +
>>> +
>>> +#define HIBMC_PW_MODE_CTL_MODE_MODE0        0
>>> +#define HIBMC_PW_MODE_CTL_MODE_MODE1        1
>>> +#define HIBMC_PW_MODE_CTL_MODE_SLEEP        2
>>> +
>>> +#define HIBMC_PANEL_PLL_CTRL            0x00005C
>>> +#define HIBMC_CRT_PLL_CTRL            0x000060
>>> +
>>> +#define HIBMC_PLL_CTRL_BYPASS(x)        ((x) << 18)
>>> +#define HIBMC_PLL_CTRL_BYPASS_MASK        0x40000
>>> +
>>> +#define HIBMC_PLL_CTRL_POWER(x)            ((x) << 17)
>>> +#define HIBMC_PLL_CTRL_POWER_MASK        0x20000
>>> +
>>> +#define HIBMC_PLL_CTRL_INPUT(x)            ((x) << 16)
>>> +#define HIBMC_PLL_CTRL_INPUT_MASK        0x10000
>>> +
>>> +#define OSC                    0
>>> +#define TESTCLK                    1
>>> +
>>> +#define HIBMC_PLL_CTRL_POD(x)            ((x) << 14)
>>> +#define HIBMC_PLL_CTRL_POD_MASK            0xC000
>>> +
>>> +#define HIBMC_PLL_CTRL_OD(x)            ((x) << 12)
>>> +#define HIBMC_PLL_CTRL_OD_MASK            0x3000
>>> +
>>> +#define HIBMC_PLL_CTRL_N(x)            ((x) << 8)
>>> +#define HIBMC_PLL_CTRL_N_MASK            0xF00
>>> +
>>> +#define HIBMC_PLL_CTRL_M(x)            ((x) << 0)
>>> +#define HIBMC_PLL_CTRL_M_MASK            0xFF
>>> +
>>> +
>>> +#define HIBMC_CRT_DISP_CTL            0x80200
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_CRTSELECT(x)        ((x) << 25)
>>> +#define HIBMC_CRT_DISP_CTL_CRTSELECT_MASK    0x2000000
>>> +
>>> +#define CRTSELECT_VGA                0
>>> +#define CRTSELECT_CRT                1
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE(x)    ((x) << 14)
>>> +#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK    0x4000
>>> +
>>> +#define PHASE_ACTIVE_HIGH      0
>>> +#define PHASE_ACTIVE_LOW       1
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE(x)    ((x) << 13)
>>> +#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK    0x2000
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE(x)    ((x) << 12)
>>> +#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK    0x1000
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_TIMING(x)        ((x) << 8)
>>> +#define HIBMC_CRT_DISP_CTL_TIMING_MASK        0x100
>>> +
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_PLANE(x)        ((x) << 2)
>>> +#define HIBMC_CRT_DISP_CTL_PLANE_MASK        4
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_FORMAT(x)        ((x) << 0)
>>> +#define HIBMC_CRT_DISP_CTL_FORMAT_MASK        0x03
>>> +
>>> +
>>> +
>>> +#define HIBMC_CRT_FB_ADDRESS            0x080204
>>> +
>>> +#define HIBMC_CRT_FB_WIDTH            0x080208
>>> +#define HIBMC_CRT_FB_WIDTH_WIDTH(x)        ((x) << 16)
>>> +#define HIBMC_CRT_FB_WIDTH_WIDTH_MASK        0x3FFF0000
>>> +#define HIBMC_CRT_FB_WIDTH_OFFS(x)        ((x) << 0)
>>> +#define HIBMC_CRT_FB_WIDTH_OFFS_MASK        0x3FFF
>>> +
>>> +
>>> +#define HIBMC_CRT_HORZ_TOTAL            0x08020C
>>> +#define HIBMC_CRT_HORZ_TOTAL_TOTAL(x)        ((x) << 16)
>>> +#define HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK        0xFFF0000
>>> +
>>> +
>>> +#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END(x)    ((x) << 0)
>>> +#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END_MASK    0xFFF
>>> +
>>> +#define HIBMC_CRT_HORZ_SYNC            0x080210
>>> +#define HIBMC_CRT_HORZ_SYNC_WIDTH(x)        ((x) << 16)
>>> +#define HIBMC_CRT_HORZ_SYNC_WIDTH_MASK        0xFF0000
>>> +
>>> +#define HIBMC_CRT_HORZ_SYNC_START(x)        ((x) << 0)
>>> +#define HIBMC_CRT_HORZ_SYNC_START_MASK        0xFFF
>>> +
>>> +#define HIBMC_CRT_VERT_TOTAL            0x080214
>>> +#define HIBMC_CRT_VERT_TOTAL_TOTAL(x)        ((x) << 16)
>>> +#define HIBMC_CRT_VERT_TOTAL_TOTAL_MASK        0x7FFF0000
>>> +
>>> +#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END(x)    ((x) << 0)
>>> +#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END_MASK    0x7FF
>>> +
>>> +#define HIBMC_CRT_VERT_SYNC            0x080218
>>> +#define HIBMC_CRT_VERT_SYNC_HEIGHT(x)        ((x) << 16)
>>> +#define HIBMC_CRT_VERT_SYNC_HEIGHT_MASK        0x3F0000
>>> +
>>> +
>>> +#define HIBMC_CRT_VERT_SYNC_START(x)        ((x) << 0)
>>> +#define HIBMC_CRT_VERT_SYNC_START_MASK        0x7FF
>>> +
>>> +/* Auto Centering */
>>> +#define HIBMC_CRT_AUTO_CENTERING_TL        0x080280
>>> +#define HIBMC_CRT_AUTO_CENTERING_TL_TOP(x)    ((x) << 16)
>>> +#define HIBMC_CRT_AUTO_CENTERING_TL_TOP_MSK    0x7FF0000
>>> +
>>> +#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT(x)    ((x) << 0)
>>> +#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MSK    0x7FF
>>> +
>>> +#define HIBMC_CRT_AUTO_CENTERING_BR        0x080284
>>> +#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(x)    ((x) << 16)
>>> +#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK    0x7FF0000
>>> +
>>> +#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x)    ((x) << 0)
>>> +#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK    0x7FF
>>> +
>>> +/* register to control panel output */
>>> +#define DISPLAY_CONTROL_HISILE            0x80288
>>> +
>>> +/* register and values for PLL control */
>>> +#define CRT_PLL1_HS                0x802a8
>>> +#define CRT_PLL1_HS_25MHZ            0x23d40f02
>>> +#define CRT_PLL1_HS_40MHZ            0x23940801
>>> +#define CRT_PLL1_HS_65MHZ            0x23940d01
>>> +#define CRT_PLL1_HS_78MHZ            0x23540F82
>>> +#define CRT_PLL1_HS_74MHZ            0x23941dc2
>>> +#define CRT_PLL1_HS_80MHZ            0x23941001
>>> +#define CRT_PLL1_HS_80MHZ_1152            0x23540fc2
>>> +#define CRT_PLL1_HS_108MHZ            0x23b41b01
>>> +#define CRT_PLL1_HS_162MHZ            0x23480681
>>> +#define CRT_PLL1_HS_148MHZ            0x23541dc2
>>> +#define CRT_PLL1_HS_193MHZ            0x234807c1
>>> +
>>> +#define CRT_PLL2_HS                0x802ac
>>> +#define CRT_PLL2_HS_25MHZ            0x206B851E
>>> +#define CRT_PLL2_HS_40MHZ            0x30000000
>>> +#define CRT_PLL2_HS_65MHZ            0x40000000
>>> +#define CRT_PLL2_HS_78MHZ            0x50E147AE
>>> +#define CRT_PLL2_HS_74MHZ            0x602B6AE7
>>> +#define CRT_PLL2_HS_80MHZ            0x70000000
>>> +#define CRT_PLL2_HS_108MHZ            0x80000000
>>> +#define CRT_PLL2_HS_162MHZ            0xA0000000
>>> +#define CRT_PLL2_HS_148MHZ            0xB0CCCCCD
>>> +#define CRT_PLL2_HS_193MHZ            0xC0872B02
>>> +
>>> +/* Global macros */
>>> +#define RGB(r, g, b) \
>>> +( \
>>> +    (unsigned long)(((r) << 16) | ((g) << 8) | (b)) \
>>> +)
>>> +
>>> +#define PADDING(align, data) (((data) + (align) - 1) & (~((align) - 1)))
>>> +
>>> +#define MB(x) ((x) << 20)
>>> +
>>> +#endif
>>> --
>>> 1.9.1
>>>
>>> _______________________________________________
>>> dri-devel mailing list
>>> dri-devel at lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>>
>
>


-- 
Regards,
Rongrong


From wens at csie.org  Mon May 30 05:59:57 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 30 May 2016 20:59:57 +0800
Subject: [PATCH 2/3] mmc: sunxi: Fix DDR MMC timings for A80
In-Reply-To: <99d78ff3-db4d-45cc-024a-d94583b56f35@redhat.com>
References: <1464505484-3661-1-git-send-email-wens@csie.org>
 <1464505484-3661-3-git-send-email-wens@csie.org>
 <99d78ff3-db4d-45cc-024a-d94583b56f35@redhat.com>
Message-ID: <CAGb2v65=ZM+deSmTmMnT6XFJv8PuY+Kba3kJGKrk_46hxxRyHA@mail.gmail.com>

On Mon, May 30, 2016 at 7:34 PM, Hans de Goede <hdegoede at redhat.com> wrote:
> Hi,
>
> On 29-05-16 09:04, Chen-Yu Tsai wrote:
>>
>> The MMC clock timings were incorrectly calculated, when the conversion
>> from delay value to delay phase was done.
>>
>> The 50M DDR and 50M DDR 8bit timings are off, and make eMMC DDR
>> unusable. Unfortunately it seems different controllers on the same SoC
>> have different timings. The new settings are taken from mmc2, which is
>> commonly used with eMMC.
>
>
> Hmm, I'm not really all that familiar with mmc, but can't an external
> sdcard connected to mmc0 use DDR too ? Assuming the answer is yes, then
> we really need to update the driver to use the right per controller
> timings.

I would very much like that to happen. However, SD card UHS-1 DDR modes
require 1.8V signaling, which is unavailable on _all_ sunxi boards.
This seems like a limit of most of the SoCs not having a separate IO
voltage rail for mmc pins.

Until then, I wouldn't worry that much.

>> The settings for the slower timing modes seem to work despite being
>> wrong, so leave them be.
>
>
> If you're sure the timings are wrong, please fix them. Sometimes wrong
> timings do seem to work, but lead to unreliable communication, or turn
> out to work on some boards and not on others due to routing differences.

Unfortunately I did try putting in the correct numbers for them, and my
eMMC then failed to probe. It seems the core switches up from 400kHz to
50MHz then to 50MHz DDR, and it fails somewhere in there, maybe at 50MHz.

I'm not sure if we need to add DT bindings to specify different delays
for different controllers, though. Seems like we'll never actually use
it.

Hope this answers your questions.

Regards
ChenYu

> Thanks & Regards,
>
> Hans
>
>
>
>>
>> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
>> ---
>>  drivers/mmc/host/sunxi-mmc.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
>> index 7fc8b7aa83f0..5873dc344ab2 100644
>> --- a/drivers/mmc/host/sunxi-mmc.c
>> +++ b/drivers/mmc/host/sunxi-mmc.c
>> @@ -970,8 +970,8 @@ static const struct sunxi_mmc_clk_delay
>> sun9i_mmc_clk_delays[] = {
>>         [SDXC_CLK_400K]         = { .output = 180, .sample = 180 },
>>         [SDXC_CLK_25M]          = { .output = 180, .sample =  75 },
>>         [SDXC_CLK_50M]          = { .output = 150, .sample = 120 },
>> -       [SDXC_CLK_50M_DDR]      = { .output =  90, .sample = 120 },
>> -       [SDXC_CLK_50M_DDR_8BIT] = { .output =  90, .sample = 120 },
>> +       [SDXC_CLK_50M_DDR]      = { .output =  54, .sample =  36 },
>> +       [SDXC_CLK_50M_DDR_8BIT] = { .output =  72, .sample =  72 },
>>  };
>>
>>  static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
>>
>


From arnd at arndb.de  Mon May 30 06:13:39 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 30 May 2016 15:13:39 +0200
Subject: [v10,
 7/7] mmc: sdhci-of-esdhc: fix host version for T4240-R1.0-R2.0
In-Reply-To: <CAPDyKFqx2JMLzXoDxGCKFYMFV47+SegnkuWFXKvsQHK7L5w-1g@mail.gmail.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <HE1PR04MB0889852B7809A1CCFF8922ACF8410@HE1PR04MB0889.eurprd04.prod.outlook.com>
 <CAPDyKFqx2JMLzXoDxGCKFYMFV47+SegnkuWFXKvsQHK7L5w-1g@mail.gmail.com>
Message-ID: <11214004.Ypipe5qZMl@wuerfel>

On Thursday, May 26, 2016 9:44:10 AM CEST Ulf Hansson wrote:
> On 26 May 2016 at 06:05, Yangbo Lu <yangbo.lu at nxp.com> wrote:
> > Hi Uffe,
> >
> > Could we merge this patchset? ...
> > It has been a long time to wait for Arnd's response...
> >
> > Thanks a lot.
> >
> >
> 
> As we are still in the merge window I won't queue anything but fixes.
> Let's give Arnd another week or so to respond.

I've got a patch series now that implements a method for matching
the soc ID, see the following emails.

	Arnd



From arnd at arndb.de  Mon May 30 06:14:38 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 30 May 2016 15:14:38 +0200
Subject: [PATCH 1/4]  base: soc: introduce soc_device_match() interface
In-Reply-To: <CAPDyKFqx2JMLzXoDxGCKFYMFV47+SegnkuWFXKvsQHK7L5w-1g@mail.gmail.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <HE1PR04MB0889852B7809A1CCFF8922ACF8410@HE1PR04MB0889.eurprd04.prod.outlook.com>
 <CAPDyKFqx2JMLzXoDxGCKFYMFV47+SegnkuWFXKvsQHK7L5w-1g@mail.gmail.com>
Message-ID: <6032641.cjSseEG2PF@wuerfel>

We keep running into cases where device drivers want to know the exact
version of the SoC a they are currently running on. In the past, this
has usually been done through a vendor specific API that can be called
by a driver, or by directly accessing some kind of version register
that is not part of the device itself but that belongs to a global
register area of the chip.

Common reasons for doing this include:

- A machine is not using devicetree or similar for passing data
  about on-chip devices, but just announces their presence using
  boot-time platform devices, and the machine code itself does
  not care about the revision.

- There is existing firmware or boot loaders with existing DT
  binaries with generic compatible strings that do not identify
  the particular revision of each device, but the driver knows
  which SoC revisions include which part

- A prerelease version of a chip has some quirks and we are
  using the same version of the bootloader and the DT blob
  on both the prerelease and the final version. An update of
  the DT binding seems inappropriate because that would involve
  maintaining multiple copies of the dts and/or bootloader.

This introduces the soc_device_match() interface that is meant
to work like of_match_node() but instead of identifying the
version of a device, it identifies the SoC itself using a
vendor-agnostic interface.

Unlike soc_device_match(), we do not do an exact string compare
but instead use glob_match() to allow wildcards in strings.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>

diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 246acdafedb6..fc7613cc7fd5 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -225,6 +225,7 @@ config GENERIC_CPU_AUTOPROBE
 
 config SOC_BUS
 	bool
+	select GLOB
 
 source "drivers/base/regmap/Kconfig"
 
diff --git a/drivers/base/soc.c b/drivers/base/soc.c
index 75b98aad6faf..e9623c6674a5 100644
--- a/drivers/base/soc.c
+++ b/drivers/base/soc.c
@@ -14,6 +14,7 @@
 #include <linux/spinlock.h>
 #include <linux/sys_soc.h>
 #include <linux/err.h>
+#include <linux/glob.h>
 
 static DEFINE_IDA(soc_ida);
 
@@ -168,3 +169,60 @@ static void __exit soc_bus_unregister(void)
 	bus_unregister(&soc_bus_type);
 }
 module_exit(soc_bus_unregister);
+
+static int soc_device_match_one(struct device *dev, void *arg)
+{
+	struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
+	struct soc_device_attribute *match = arg;
+
+	if (match->machine && !glob_match(match->machine, soc_dev->attr->machine))
+		return 0;
+
+	if (match->family && !glob_match(match->family, soc_dev->attr->family))
+		return 0;
+
+	if (match->revision && !glob_match(match->revision, soc_dev->attr->revision))
+		return 0;
+
+	if (match->soc_id && !glob_match(match->soc_id, soc_dev->attr->revision))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * soc_device_match - identify the SoC in the machine
+ * @matches: zero-terminated array of possible matches
+ *
+ * returns the first matching entry of the argument array, or NULL
+ * if none of them match.
+ *
+ * This function is meant as a helper in place of of_match_node()
+ * in cases where either no device tree is available or the information
+ * in a device node is insufficient to identify a particular variant
+ * by its compatible strings or other properties. For new devices,
+ * the DT binding should always provide unique compatible strings
+ * that allow the use of of_match_node() instead.
+ *
+ * The calling function can use the .data entry of the
+ * soc_device_attribute to pass a structure or function pointer for
+ * each entry.
+ */
+struct soc_device_attribute *soc_device_match(struct soc_device_attribute *matches)
+{
+	struct device *dev;
+	int ret;
+
+	for (ret = 0; ret == 0; matches++) {
+		if (matches->machine || matches->family ||
+		    matches->revision || matches->soc_id)
+			return NULL;
+
+		dev = NULL;
+		ret = bus_for_each_dev(&soc_bus_type, dev, matches,
+					 soc_device_match_one);
+	}
+
+	return matches;
+}
+EXPORT_SYMBOL_GPL(soc_device_match);
diff --git a/include/linux/sys_soc.h b/include/linux/sys_soc.h
index 2739ccb69571..02c48c76052b 100644
--- a/include/linux/sys_soc.h
+++ b/include/linux/sys_soc.h
@@ -13,6 +13,8 @@ struct soc_device_attribute {
 	const char *family;
 	const char *revision;
 	const char *soc_id;
+
+	const void *data;
 };
 
 /**
@@ -34,4 +36,6 @@ void soc_device_unregister(struct soc_device *soc_dev);
  */
 struct device *soc_device_to_device(struct soc_device *soc);
 
+struct soc_device_attribute *soc_device_match(struct soc_device_attribute *matches);
+
 #endif /* __SOC_BUS_H */



From arnd at arndb.de  Mon May 30 06:15:25 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 30 May 2016 15:15:25 +0200
Subject: [PATCH 2/4] soc: fsl: add GUTS driver for QorIQ platforms
In-Reply-To: <CAPDyKFqx2JMLzXoDxGCKFYMFV47+SegnkuWFXKvsQHK7L5w-1g@mail.gmail.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <HE1PR04MB0889852B7809A1CCFF8922ACF8410@HE1PR04MB0889.eurprd04.prod.outlook.com>
 <CAPDyKFqx2JMLzXoDxGCKFYMFV47+SegnkuWFXKvsQHK7L5w-1g@mail.gmail.com>
Message-ID: <5339448.D8rpq4ofAC@wuerfel>

From: Yangbo Lu <yangbo.lu at nxp.com>

The global utilities block controls power management, I/O device
enabling, power-onreset(POR) configuration monitoring, alternate
function selection for multiplexed signals,and clock control.

This patch adds GUTS driver to manage and access global utilities
block.

[arnd turned this into a platform_driver registering a soc_device
 rather than providing an ad-hoc interface for soc-id]

Signed-off-by: Yangbo Lu <yangbo.lu at nxp.com>
Signed-off-by: Arnd Bergmann <arnd at arndb.de>

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cb58ef0d9b2c..7106463f118e 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -2,7 +2,7 @@ menu "SOC (System On Chip) specific Drivers"
 
 source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/brcmstb/Kconfig"
-source "drivers/soc/fsl/qe/Kconfig"
+source "drivers/soc/fsl/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/rockchip/Kconfig"
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
new file mode 100644
index 000000000000..33d331cac8d6
--- /dev/null
+++ b/drivers/soc/fsl/Kconfig
@@ -0,0 +1,15 @@
+#
+# Freescale SOC drivers
+#
+
+source "drivers/soc/fsl/qe/Kconfig"
+
+config FSL_GUTS
+	bool "NXP Layerscale SoC identification"
+	depends on PPC_FSL || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST
+	default PPC_FSL || SOC_LS1021A || ARCH_LAYERSCAPE
+	select SOC_BUS
+	help
+	  This registers a SoC device for NXP (formerly Freescale)
+	  Layerscape devices, making information about the system
+	  available in /sys/devices/soc/
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index 203307fd92c1..02afb7f980f6 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_QUICC_ENGINE)		+= qe/
 obj-$(CONFIG_CPM)			+= qe/
+obj-$(CONFIG_FSL_GUTS)			+= guts.o
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
new file mode 100644
index 000000000000..2f30698f5bcf
--- /dev/null
+++ b/drivers/soc/fsl/guts.c
@@ -0,0 +1,130 @@
+/*
+ * Freescale QorIQ Platforms GUTS Driver
+ *
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/sys_soc.h>
+
+#define GUTS_PVR	0x0a0
+#define GUTS_SVR	0x0a4
+
+struct guts {
+	void __iomem *regs;
+	bool little_endian;
+	struct soc_device_attribute soc;
+};
+
+static u32 fsl_guts_get_svr(struct guts *guts)
+{
+	if (guts->little_endian)
+		return ioread32(guts->regs + GUTS_SVR);
+	else
+		return ioread32be(guts->regs + GUTS_SVR);
+}
+
+static u32 fsl_guts_get_pvr(struct guts *guts)
+{
+	if (guts->little_endian)
+		return ioread32(guts->regs + GUTS_PVR);
+	else
+		return ioread32be(guts->regs + GUTS_PVR);
+}
+
+/*
+ * Table for matching compatible strings, for device tree
+ * guts node, for Freescale QorIQ SOCs.
+ */
+static const struct of_device_id fsl_guts_of_match[] = {
+	/* For T4 & B4 Series SOCs */
+	{ .compatible = "fsl,qoriq-device-config-1.0", .data = "T4/B4 series" },
+	/* For P Series SOCs */
+	{ .compatible = "fsl,p1010-guts", .data = "P1010/P1014" },
+	{ .compatible = "fsl,p1020-guts", .data = "P1020/P1011" },
+	{ .compatible = "fsl,p1021-guts", .data = "P1021/P1012" },
+	{ .compatible = "fsl,p1022-guts", .data = "P1022/P1013" },
+	{ .compatible = "fsl,p1023-guts", .data = "P1013/P1017" },
+	{ .compatible = "fsl,p2020-guts", .data = "P2010/P2020" },
+	{ .compatible = "fsl,qoriq-device-config-2.0", .data = "P series" },
+	/* For BSC Series SOCs */
+	{ .compatible = "fsl,bsc9131-guts", .data = "BSC9131 Qonverge" },
+	{ .compatible = "fsl,bsc9132-guts", .data = "BSC9132 Qonverge" },
+	/* For MPC85xx Series SOCs */
+	{ .compatible = "fsl,mpc8536-guts", .data = "PowerPC MPC8536" },
+	{ .compatible = "fsl,mpc8544-guts", .data = "PowerPC MPC8544" },
+	{ .compatible = "fsl,mpc8548-guts", .data = "PowerPC MPC8548" },
+	{ .compatible = "fsl,mpc8568-guts", .data = "PowerPC MPC8568" },
+	{ .compatible = "fsl,mpc8569-guts", .data = "PowerPC MPC8569" },
+	{ .compatible = "fsl,mpc8572-guts", .data = "PowerPC MPC8572" },
+	/* For Layerscape Series SOCs */
+	{ .compatible = "fsl,ls1021a-dcfg", .data = "Layerscape LS1021A" },
+	{ .compatible = "fsl,ls1043a-dcfg", .data = "Layerscape LS1043A" },
+	{ .compatible = "fsl,ls2080a-dcfg", .data = "Layerscape LS2080A" },
+	{}
+};
+
+static void fsl_guts_init(struct device *dev, struct guts *guts)
+{
+	const struct of_device_id *id;
+	u32 svr = fsl_guts_get_svr(guts);
+
+	guts->soc.family = "NXP QorIQ";
+	id = of_match_node(fsl_guts_of_match, dev->of_node);
+	guts->soc.soc_id = devm_kasprintf(dev, "%s (ver 0x%06x)" id->data,
+					  svr >> 8;
+	guts->soc.revision = devm_kasprintf(dev, GFP_KERNEL, "0x%02x",
+					    svr & 0xff);
+}
+
+static int fsl_guts_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct guts *guts;
+	int ret;
+
+	guts = devm_kzalloc(dev, sizeof(*guts), GFP_KERNEL);
+	if (!guts) {
+		ret = -ENOMEM;
+		goto out;
+
+	}
+
+	/*
+	 * syscon devices default to little-endian, but on powerpc we have
+	 * existing device trees with big-endian maps and an absent endianess
+	 * "big-property"
+	 */
+	if (!IS_ENABLED(CONFIG_POWERPC) &&
+	    !of_property_read_bool(dev->of_node, "big-endian"))
+		guts->little_endian = true;
+
+	guts->regs = devm_ioremap_resource(dev, 0);
+	if (!guts->regs) {
+		ret = -ENOMEM;
+		kfree(guts);
+		goto out;
+	}
+
+	fsl_guts_init(dev, guts);
+	ret = 0;
+out:
+	return ret;
+}
+
+static struct platform_driver fsl_soc_guts = {
+	.probe = fsl_guts_probe,
+	.driver.of_match_table = fsl_guts_of_match,
+};
+
+module_platform_driver(fsl_soc_guts);



From arnd at arndb.de  Mon May 30 06:16:03 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 30 May 2016 15:16:03 +0200
Subject: [PATCH 3/4] mmc: sdhci-of-esdhc: fix host version for T4240-R1.0-R2.0
In-Reply-To: <CAPDyKFqx2JMLzXoDxGCKFYMFV47+SegnkuWFXKvsQHK7L5w-1g@mail.gmail.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <HE1PR04MB0889852B7809A1CCFF8922ACF8410@HE1PR04MB0889.eurprd04.prod.outlook.com>
 <CAPDyKFqx2JMLzXoDxGCKFYMFV47+SegnkuWFXKvsQHK7L5w-1g@mail.gmail.com>
Message-ID: <6110875.0k1HlSKhzn@wuerfel>

This is a rewrite of an earlier patch from Yangbo Lu, adding a quirk
for the NXP QorIQ T4240 in the detection of the host device version.

Unfortunately, this device cannot be detected using the compatible
string, as we have to support existing DTS files that use the generic
"fsl,t4240-esdhc" identifier but that have other host versions that
are correctly detected.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>

diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 3f34d354f1fc..1d4814fe4cb2 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -73,14 +73,16 @@ static u32 esdhc_readl_fixup(struct sdhci_host *host,
 static u16 esdhc_readw_fixup(struct sdhci_host *host,
 				     int spec_reg, u32 value)
 {
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
 	u16 ret;
 	int shift = (spec_reg & 0x2) * 8;
 
 	if (spec_reg == SDHCI_HOST_VERSION)
-		ret = value & 0xffff;
-	else
-		ret = (value >> shift) & 0xffff;
-	return ret;
+		return esdhc->vendor_ver << SDHCI_VENDOR_VER_SHIFT |
+		       esdhc->spec_ver;
+
+	return (value >> shift) & 0xffff;
 }
 
 static u8 esdhc_readb_fixup(struct sdhci_host *host,
@@ -562,16 +564,32 @@ static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = {
 	.ops = &sdhci_esdhc_le_ops,
 };
 
+#define T4240_HOST_VER ((VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200)
+static const struct soc_device_attribute esdhc_t4240_quirk = {
+	/* T4240 revision < 0x20 uses vendor version 23, SDHCI version 200 */
+	{ .soc_id = "T4*(0x824000)", .revision = "0x[01]?",
+	  .data = (void *)(uintptr_t)(T4240_HOST_VER) },
+	{ },
+};
+
 static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_esdhc *esdhc;
-	u16 host_ver;
 
 	pltfm_host = sdhci_priv(host);
 	esdhc = sdhci_pltfm_priv(pltfm_host);
 
 	host_ver = sdhci_readw(host, SDHCI_HOST_VERSION);
+
+	if (of_device_is_compatible(pdev->dev.of_node, "fsl,t4240-esdhc")) {
+		struct soc_device_attribute *match;
+
+		match = soc_device_match(&esdhc_t4240_quirk);
+		if (match)
+			host_ver = (uintptr_t)match->data;
+	}
+
 	esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >>
 			     SDHCI_VENDOR_VER_SHIFT;
 	esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK;



From arnd at arndb.de  Mon May 30 06:18:43 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 30 May 2016 15:18:43 +0200
Subject: [PATCH 4/4] Revert "powerpc/fsl: Move fsl_guts.h out of arch/powerpc"
In-Reply-To: <CAPDyKFqx2JMLzXoDxGCKFYMFV47+SegnkuWFXKvsQHK7L5w-1g@mail.gmail.com>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <HE1PR04MB0889852B7809A1CCFF8922ACF8410@HE1PR04MB0889.eurprd04.prod.outlook.com>
 <CAPDyKFqx2JMLzXoDxGCKFYMFV47+SegnkuWFXKvsQHK7L5w-1g@mail.gmail.com>
Message-ID: <5513501.AmZs7h1vI2@wuerfel>

All users of this driver are PowerPC specific and the header file
has no business in the global include/linux/ hierarchy, so move
it back before anyone starts using it on ARM.

This reverts commit 948486544713492f00ac8a9572909101ea892cb0.

Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
This part of the series is not required for the eSDHC quirk,
but it restores the asm/fsl_guts.h header so it doesn't accidentally
get abused for this in the future. I found two drivers outside of
arch/powerpc that already accessed the registers directly, but the
functions look fairly contained, and can be easily hidden in an
#ifdef CONFIG_PPC

diff --git a/include/linux/fsl/guts.h b/arch/powerpc/include/asm/fsl_guts.h
similarity index 99%
rename from include/linux/fsl/guts.h
rename to arch/powerpc/include/asm/fsl_guts.h
index 649e9171a9b3..a67413c52701 100644
--- a/include/linux/fsl/guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -12,10 +12,9 @@
  * option) any later version.
  */
 
-#ifndef __FSL_GUTS_H__
-#define __FSL_GUTS_H__
-
-#include <linux/types.h>
+#ifndef __ASM_POWERPC_FSL_GUTS_H__
+#define __ASM_POWERPC_FSL_GUTS_H__
+#ifdef __KERNEL__
 
 /**
  * Global Utility Registers.
@@ -295,3 +294,4 @@ struct ccsr_rcpm_v2 {
 };
 
 #endif
+#endif
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index f61cbe235581..00f052e9f2a2 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -34,7 +34,6 @@
 #include <linux/of_device.h>
 #include <linux/phy.h>
 #include <linux/memblock.h>
-#include <linux/fsl/guts.h>
 
 #include <linux/atomic.h>
 #include <asm/time.h>
@@ -52,6 +51,7 @@
 #include <soc/fsl/qe/qe_ic.h>
 #include <asm/mpic.h>
 #include <asm/swiotlb.h>
+#include <asm/fsl_guts.h>
 #include "smp.h"
 
 #include "mpc85xx.h"
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c
index f05325f0cc03..a812c0511252 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c
@@ -14,8 +14,8 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/fsl/guts.h>
 
+#include <asm/fsl_guts.h>
 #include <asm/io.h>
 #include <asm/fsl_pm.h>
 
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 3f4dad133338..453ddda00fce 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -17,7 +17,6 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
-#include <linux/fsl/guts.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -28,6 +27,7 @@
 #include <asm/mpic.h>
 #include <soc/fsl/qe/qe.h>
 #include <soc/fsl/qe/qe_ic.h>
+#include <asm/fsl_guts.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 371df822e88e..6ac986d3f8a3 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -16,7 +16,6 @@
  * kind, whether express or implied.
  */
 
-#include <linux/fsl/guts.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 #include <asm/div64.h>
@@ -26,6 +25,7 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 #include <asm/udbg.h>
+#include <asm/fsl_guts.h>
 #include <asm/fsl_lbc.h>
 #include "smp.h"
 
diff --git a/arch/powerpc/platforms/85xx/p1022_rdk.c b/arch/powerpc/platforms/85xx/p1022_rdk.c
index 5087becaa8bc..680232d6ba48 100644
--- a/arch/powerpc/platforms/85xx/p1022_rdk.c
+++ b/arch/powerpc/platforms/85xx/p1022_rdk.c
@@ -12,7 +12,6 @@
  * kind, whether express or implied.
  */
 
-#include <linux/fsl/guts.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 #include <asm/div64.h>
@@ -22,6 +21,7 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 #include <asm/udbg.h>
+#include <asm/fsl_guts.h>
 #include "smp.h"
 
 #include "mpc85xx.h"
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index fe9f19e5e935..6bd3a292e790 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -18,7 +18,6 @@
 #include <linux/kexec.h>
 #include <linux/highmem.h>
 #include <linux/cpu.h>
-#include <linux/fsl/guts.h>
 
 #include <asm/machdep.h>
 #include <asm/pgtable.h>
@@ -26,6 +25,7 @@
 #include <asm/mpic.h>
 #include <asm/cacheflush.h>
 #include <asm/dbell.h>
+#include <asm/fsl_guts.h>
 #include <asm/code-patching.h>
 #include <asm/cputhreads.h>
 #include <asm/fsl_pm.h>
diff --git a/arch/powerpc/platforms/85xx/twr_p102x.c b/arch/powerpc/platforms/85xx/twr_p102x.c
index 71bc255b4324..2cac45f72d24 100644
--- a/arch/powerpc/platforms/85xx/twr_p102x.c
+++ b/arch/powerpc/platforms/85xx/twr_p102x.c
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/errno.h>
-#include <linux/fsl/guts.h>
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 
@@ -24,6 +23,7 @@
 #include <asm/mpic.h>
 #include <soc/fsl/qe/qe.h>
 #include <soc/fsl/qe/qe_ic.h>
+#include <asm/fsl_guts.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 957473e5c8e5..761c81476957 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -24,7 +24,6 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/of.h>
-#include <linux/fsl/guts.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -39,6 +38,7 @@
 #include <sysdev/fsl_pci.h>
 #include <sysdev/fsl_soc.h>
 #include <sysdev/simple_gpio.h>
+#include <asm/fsl_guts.h>
 
 #include "mpc86xx.h"
 
diff --git a/arch/powerpc/sysdev/fsl_rcpm.c b/arch/powerpc/sysdev/fsl_rcpm.c
index 9259a94f70e1..8af22187cb25 100644
--- a/arch/powerpc/sysdev/fsl_rcpm.c
+++ b/arch/powerpc/sysdev/fsl_rcpm.c
@@ -19,7 +19,7 @@
 #include <linux/export.h>
 
 #include <asm/io.h>
-#include <linux/fsl/guts.h>
+#include <asm/fsl_guts.h>
 #include <asm/cputhreads.h>
 #include <asm/fsl_pm.h>
 #include <asm/smp.h>
diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 58566a17944a..f311bd399672 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -12,7 +12,6 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
-#include <linux/fsl/guts.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -21,6 +20,10 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 
+#ifdef CONFIG_PPC
+#include <asm/fsl_guts.h>
+#endif
+
 #define PLL_DIV1	0
 #define PLL_DIV2	1
 #define PLL_DIV3	2
@@ -341,6 +344,8 @@ static const struct clockgen_muxinfo t4240_hwa5 = {
 	},
 };
 
+#ifdef CONFIG_PPC
+
 #define RCWSR7_FM1_CLK_SEL	0x40000000
 #define RCWSR7_FM2_CLK_SEL	0x20000000
 #define RCWSR7_HWA_ASYNC_DIV	0x04000000
@@ -408,6 +413,7 @@ static void __init p5040_init_periph(struct clockgen *cg)
 	else
 		cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
 }
+#endif
 
 static void __init t1023_init_periph(struct clockgen *cg)
 {
@@ -499,6 +505,7 @@ static const struct clockgen_chipinfo chipinfo[] = {
 		.pll_mask = 0x37,
 		.flags = CG_VER3 | CG_LITTLE_ENDIAN,
 	},
+#ifdef CONFIG_PPC
 	{
 		.compat = "fsl,p2041-clockgen",
 		.guts_compat = "fsl,qoriq-device-config-1.0",
@@ -559,6 +566,7 @@ static const struct clockgen_chipinfo chipinfo[] = {
 		},
 		.pll_mask = 0x0f,
 	},
+#endif
 	{
 		.compat = "fsl,t1023-clockgen",
 		.guts_compat = "fsl,t1023-device-config",
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index a34355fca37a..2570f2a25dc4 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -20,11 +20,11 @@
 
 #include "fsl_pamu.h"
 
-#include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/genalloc.h>
 
 #include <asm/mpc85xx.h>
+#include <asm/fsl_guts.h>
 
 /* define indexes for each operation mapping scenario */
 #define OMI_QMAN        0x00
diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c
index 1de2e1e51c2b..dabee93fcadd 100644
--- a/drivers/net/ethernet/freescale/fman/fman.c
+++ b/drivers/net/ethernet/freescale/fman/fman.c
@@ -35,7 +35,6 @@
 #include "fman.h"
 #include "fman_muram.h"
 
-#include <linux/fsl/guts.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/module.h>
@@ -46,6 +45,10 @@
 #include <linux/interrupt.h>
 #include <linux/libfdt_env.h>
 
+#ifdef CONFIG_PPC
+#include <asm/fsl_guts.h>
+#endif
+
 /* General defines */
 #define FMAN_LIODN_TBL			64	/* size of LIODN table */
 #define MAX_NUM_OF_MACS			10
@@ -1889,7 +1892,9 @@ static int fman_reset(struct fman *fman)
 			err = -EBUSY;
 
 		goto _return;
-	} else {
+	}
+#ifdef CONFIG_PPC
+	else {
 		struct device_node *guts_node;
 		struct ccsr_guts __iomem *guts_regs;
 		u32 devdisr2, reg;
@@ -1952,6 +1957,7 @@ guts_node:
 		dev_dbg(fman->dev, "%s: Didn't perform FManV3 reset due to Errata A007273!\n",
 			__func__);
 	}
+#endif
 _return:
 	return err;
 }
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index ddf49f30b23f..73b2b89d4a3e 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -12,11 +12,11 @@
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/fsl/guts.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
+#include <asm/fsl_guts.h>
 
 #include "fsl_dma.h"
 #include "fsl_ssi.h"
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index a1f780ecadf5..a24e04919f71 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -11,12 +11,12 @@
  */
 
 #include <linux/module.h>
-#include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
+#include <asm/fsl_guts.h>
 
 #include "fsl_dma.h"
 #include "fsl_ssi.h"
diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c
index d4d88a8cb9c0..d8448887bfda 100644
--- a/sound/soc/fsl/p1022_rdk.c
+++ b/sound/soc/fsl/p1022_rdk.c
@@ -18,12 +18,12 @@
  */
 
 #include <linux/module.h>
-#include <linux/fsl/guts.h>
 #include <linux/interrupt.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
+#include <asm/fsl_guts.h>
 
 #include "fsl_dma.h"
 #include "fsl_ssi.h"



From pramod.gurav at linaro.org  Mon May 30 06:20:47 2016
From: pramod.gurav at linaro.org (Pramod Gurav)
Date: Mon, 30 May 2016 18:50:47 +0530
Subject: [PATCH] usb: echi-hcd: Add ehci_setup check before echi_shutdown
In-Reply-To: <1463652776-30456-1-git-send-email-srinivas.kandagatla@linaro.org>
References: <1463652776-30456-1-git-send-email-srinivas.kandagatla@linaro.org>
Message-ID: <CANYu_0vK8-oEL-QrHH196DnEy+5qSYEqm1s1P4FXkDUJWOJH0Q@mail.gmail.com>

On 19 May 2016 at 15:42, Srinivas Kandagatla
<srinivas.kandagatla at linaro.org> wrote:

<snip>

> Fixes 4bb3cad7125b ("usb: host: ehci-msm: Register usb shutdown function")
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>

Was seeing this crash while doing a reboot on db410c which is fixed
with this patch:

Tested-by: Pramod Gurav <pramod.gurav at linaro.org>


From narmstrong at baylibre.com  Mon May 30 06:27:14 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 30 May 2016 15:27:14 +0200
Subject: [PATCH v3 0/4] Amlogic: Meson: Add reset controller
Message-ID: <1464614838-28107-1-git-send-email-narmstrong@baylibre.com>

Patchset to add and enable the reset controller driver on Meson SoCs platforms.

This reset controller has up to 256 reset lines with reset pulse generation only,
so the assert and deassert calls are not available.

Depends on the patch :
 - "reset: add devm_reset_controller_register API" [1]

Changes since v2 at http://lkml.kernel.org/r/1464169758-26975-1-git-send-email-narmstrong at baylibre.com :
- Get back __iomem in _reset() callback
- Get rid of MODULE_ALIAS

Changes since v1 at http://lkml.kernel.org/r/1463732875-23141-1-git-send-email-narmstrong at baylibre.com :
- Remove _gxbb_ in names
- Depends build on ARCH_MESON only
- Add meson8b compatible and bindings
- Re-indent dt-bindings headers
- Switch to devm_ reset controller register
- Remove platform "remove" callback
- Update Dual BSD/GPL file headers

Changes since the RFC at http://lkml.kernel.org/r/1463148012-25988-1-git-send-email-narmstrong at baylibre.com :
- Fix register mapping and bit defines in bindings header
- Remove assert and unassert calls
- Fix missing __iomem

[1] https://patchwork.kernel.org/patch/8988471/

Neil Armstrong (4):
  reset: Add support for the Amlogic Meson SoC Reset Controller
  dt-bindings: reset: Add bindings for the Meson SoC Reset Controller
  ARM64: dts: amlogic: Enable Reset Controller on GXBB-based platforms
  ARM: dts: amlogic: Enable Reset Controller on Meson8b platforms

 .../bindings/reset/amlogic,meson-reset.txt         |  18 ++
 arch/arm/boot/dts/meson8b.dtsi                     |   7 +
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   7 +
 drivers/reset/Makefile                             |   1 +
 drivers/reset/reset-meson.c                        | 136 +++++++++++++
 .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 210 +++++++++++++++++++++
 include/dt-bindings/reset/amlogic,meson8b-reset.h  | 175 +++++++++++++++++
 7 files changed, 554 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt
 create mode 100644 drivers/reset/reset-meson.c
 create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
 create mode 100644 include/dt-bindings/reset/amlogic,meson8b-reset.h

-- 
2.7.0



From narmstrong at baylibre.com  Mon May 30 06:27:15 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 30 May 2016 15:27:15 +0200
Subject: [PATCH v3 1/4] reset: Add support for the Amlogic Meson SoC Reset
 Controller
In-Reply-To: <1464614838-28107-1-git-send-email-narmstrong@baylibre.com>
References: <1464614838-28107-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464614838-28107-2-git-send-email-narmstrong@baylibre.com>

This patch adds the platform driver for the Amlogic Meson SoC Reset
Controller.

The Meson8b and GXBB SoCs are supported.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/reset/Makefile      |   1 +
 drivers/reset/reset-meson.c | 136 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 137 insertions(+)
 create mode 100644 drivers/reset/reset-meson.c

diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index f173fc3..03dc1bb 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
 obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
 obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
 obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o
+obj-$(CONFIG_ARCH_MESON) += reset-meson.o
 obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_HISI) += hisilicon/
diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
new file mode 100644
index 0000000..c32f11a
--- /dev/null
+++ b/drivers/reset/reset-meson.c
@@ -0,0 +1,136 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define REG_COUNT	8
+#define BITS_PER_REG	32
+
+struct meson_reset {
+	void __iomem *reg_base;
+	struct reset_controller_dev rcdev;
+};
+
+static int meson_reset_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct meson_reset *data =
+		container_of(rcdev, struct meson_reset, rcdev);
+	unsigned int bank = id / BITS_PER_REG;
+	unsigned int offset = id % BITS_PER_REG;
+	void __iomem *reg_addr = data->reg_base + (bank << 2);
+
+	if (bank >= REG_COUNT)
+		return -EINVAL;
+
+	writel(BIT(offset), reg_addr);
+
+	return 0;
+}
+
+static const struct reset_control_ops meson_reset_ops = {
+	.reset		= meson_reset_reset,
+};
+
+static const struct of_device_id meson_reset_dt_ids[] = {
+	 { .compatible = "amlogic,meson8b-reset", },
+	 { .compatible = "amlogic,meson-gxbb-reset", },
+	 { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
+
+static int meson_reset_probe(struct platform_device *pdev)
+{
+	struct meson_reset *data;
+	struct resource *res;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(data->reg_base))
+		return PTR_ERR(data->reg_base);
+
+	platform_set_drvdata(pdev, data);
+
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = REG_COUNT * BITS_PER_REG;
+	data->rcdev.ops = &meson_reset_ops;
+	data->rcdev.of_node = pdev->dev.of_node;
+
+	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
+}
+
+static struct platform_driver meson_reset_driver = {
+	.probe	= meson_reset_probe,
+	.driver = {
+		.name		= "meson_reset",
+		.of_match_table	= meson_reset_dt_ids,
+	},
+};
+
+module_platform_driver(meson_reset_driver);
+
+MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
+MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver");
+MODULE_LICENSE("Dual BSD/GPL");
-- 
2.7.0



From narmstrong at baylibre.com  Mon May 30 06:27:16 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 30 May 2016 15:27:16 +0200
Subject: [PATCH v3 2/4] dt-bindings: reset: Add bindings for the Meson SoC
 Reset Controller
In-Reply-To: <1464614838-28107-1-git-send-email-narmstrong@baylibre.com>
References: <1464614838-28107-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464614838-28107-3-git-send-email-narmstrong@baylibre.com>

Add DT bindings for the Meson SoC Reset Controller documentation and the
associated include file.

Acked-by: Rob Herring <robh at kernel.org>
Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 .../bindings/reset/amlogic,meson-reset.txt         |  18 ++
 .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 210 +++++++++++++++++++++
 include/dt-bindings/reset/amlogic,meson8b-reset.h  | 175 +++++++++++++++++
 3 files changed, 403 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt
 create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
 create mode 100644 include/dt-bindings/reset/amlogic,meson8b-reset.h

diff --git a/Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt
new file mode 100644
index 0000000..e746b63
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt
@@ -0,0 +1,18 @@
+Amlogic Meson SoC Reset Controller
+=======================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "amlogic,meson8b-reset" or "amlogic,meson-gxbb-reset"
+- reg: should contain the register address base
+- #reset-cells: 1, see below
+
+example:
+
+reset: reset-controller {
+	compatible = "amlogic,meson-gxbb-reset";
+	reg = <0x0 0x04404 0x0 0x20>;
+	#reset-cells = <1>;
+};
diff --git a/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
new file mode 100644
index 0000000..524d607
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
@@ -0,0 +1,210 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON_GXBB_RESET_H
+
+/*	RESET0					*/
+#define RESET_HIU			0
+/*					1	*/
+#define RESET_DOS_RESET			2
+#define RESET_DDR_TOP			3
+#define RESET_DCU_RESET			4
+#define RESET_VIU			5
+#define RESET_AIU			6
+#define RESET_VID_PLL_DIV		7
+/*					8	*/
+#define RESET_PMUX			9
+#define RESET_VENC			10
+#define RESET_ASSIST			11
+#define RESET_AFIFO2			12
+#define RESET_VCBUS			13
+/*					14	*/
+/*					15	*/
+#define RESET_GIC			16
+#define RESET_CAPB3_DECODE		17
+#define RESET_NAND_CAPB3		18
+#define RESET_HDMITX_CAPB3		19
+#define RESET_MALI_CAPB3		20
+#define RESET_DOS_CAPB3			21
+#define RESET_SYS_CPU_CAPB3		22
+#define RESET_CBUS_CAPB3		23
+#define RESET_AHB_CNTL			24
+#define RESET_AHB_DATA			25
+#define RESET_VCBUS_CLK81		26
+#define RESET_MMC			27
+#define RESET_MIPI_0			28
+#define RESET_MIPI_1			29
+#define RESET_MIPI_2			30
+#define RESET_MIPI_3			31
+/*	RESET1					*/
+#define RESET_CPPM			32
+#define RESET_DEMUX			33
+#define RESET_USB_OTG			34
+#define RESET_DDR			35
+#define RESET_AO_RESET			36
+#define RESET_BT656			37
+#define RESET_AHB_SRAM			38
+/*					39	*/
+#define RESET_PARSER			40
+#define RESET_BLKMV			41
+#define RESET_ISA			42
+#define RESET_ETHERNET			43
+#define RESET_SD_EMMC_A			44
+#define RESET_SD_EMMC_B			45
+#define RESET_SD_EMMC_C			46
+#define RESET_ROM_BOOT			47
+#define RESET_SYS_CPU_0			48
+#define RESET_SYS_CPU_1			49
+#define RESET_SYS_CPU_2			50
+#define RESET_SYS_CPU_3			51
+#define RESET_SYS_CPU_CORE_0		52
+#define RESET_SYS_CPU_CORE_1		53
+#define RESET_SYS_CPU_CORE_2		54
+#define RESET_SYS_CPU_CORE_3		55
+#define RESET_SYS_PLL_DIV		56
+#define RESET_SYS_CPU_AXI		57
+#define RESET_SYS_CPU_L2		58
+#define RESET_SYS_CPU_P			59
+#define RESET_SYS_CPU_MBIST		60
+/*					61	*/
+/*					62	*/
+/*					63	*/
+/*	RESET2					*/
+#define RESET_VD_RMEM			64
+#define RESET_AUDIN			65
+#define RESET_HDMI_TX			66
+/*					67	*/
+/*					68	*/
+/*					69	*/
+#define RESET_GE2D			70
+#define RESET_PARSER_REG		71
+#define RESET_PARSER_FETCH		72
+#define RESET_PARSER_CTL		73
+#define RESET_PARSER_TOP		74
+/*					75	*/
+/*					76	*/
+#define RESET_AO_CPU_RESET		77
+#define RESET_MALI			78
+#define RESET_HDMI_SYSTEM_RESET		79
+/*					80-95	*/
+/*	RESET3					*/
+#define RESET_RING_OSCILLATOR		96
+#define RESET_SYS_CPU			97
+#define RESET_EFUSE			98
+#define RESET_SYS_CPU_BVCI		99
+#define RESET_AIFIFO			100
+#define RESET_TVFE			101
+#define RESET_AHB_BRIDGE_CNTL		102
+/*					103	*/
+#define RESET_AUDIO_DAC			104
+#define RESET_DEMUX_TOP			105
+#define RESET_DEMUX_DES			106
+#define RESET_DEMUX_S2P_0		107
+#define RESET_DEMUX_S2P_1		108
+#define RESET_DEMUX_RESET_0		109
+#define RESET_DEMUX_RESET_1		110
+#define RESET_DEMUX_RESET_2		111
+/*					112-127	*/
+/*	RESET4					*/
+/*					128	*/
+/*					129	*/
+/*					130	*/
+/*					131	*/
+#define RESET_DVIN_RESET		132
+#define RESET_RDMA			133
+#define RESET_VENCI			134
+#define RESET_VENCP			135
+/*					136	*/
+#define RESET_VDAC			137
+#define RESET_RTC			138
+/*					139	*/
+#define RESET_VDI6			140
+#define RESET_VENCL			141
+#define RESET_I2C_MASTER_2		142
+#define RESET_I2C_MASTER_1		143
+/*					144-159	*/
+/*	RESET5					*/
+/*					160-191	*/
+/*	RESET6					*/
+#define RESET_PERIPHS_GENERAL		192
+#define RESET_PERIPHS_SPICC		193
+#define RESET_PERIPHS_SMART_CARD	194
+#define RESET_PERIPHS_SAR_ADC		195
+#define RESET_PERIPHS_I2C_MASTER_0	196
+#define RESET_SANA			197
+/*					198	*/
+#define RESET_PERIPHS_STREAM_INTERFACE	199
+#define RESET_PERIPHS_SDIO		200
+#define RESET_PERIPHS_UART_0		201
+#define RESET_PERIPHS_UART_1_2		202
+#define RESET_PERIPHS_ASYNC_0		203
+#define RESET_PERIPHS_ASYNC_1		204
+#define RESET_PERIPHS_SPI_0		205
+#define RESET_PERIPHS_SDHC		206
+#define RESET_UART_SLIP			207
+/*					208-223	*/
+/*	RESET7					*/
+#define RESET_USB_DDR_0			224
+#define RESET_USB_DDR_1			225
+#define RESET_USB_DDR_2			226
+#define RESET_USB_DDR_3			227
+/*					228	*/
+#define RESET_DEVICE_MMC_ARB		229
+/*					230	*/
+#define RESET_VID_LOCK			231
+#define RESET_A9_DMC_PIPEL		232
+/*					233-255	*/
+
+#endif
diff --git a/include/dt-bindings/reset/amlogic,meson8b-reset.h b/include/dt-bindings/reset/amlogic,meson8b-reset.h
new file mode 100644
index 0000000..614aff2
--- /dev/null
+++ b/include/dt-bindings/reset/amlogic,meson8b-reset.h
@@ -0,0 +1,175 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _DT_BINDINGS_AMLOGIC_MESON8B_RESET_H
+#define _DT_BINDINGS_AMLOGIC_MESON8B_RESET_H
+
+/*	RESET0					*/
+#define RESET_HIU			0
+#define RESET_VLD			1
+#define RESET_IQIDCT			2
+#define RESET_MC			3
+/*					8	*/
+#define RESET_VIU			5
+#define RESET_AIU			6
+#define RESET_MCPU			7
+#define RESET_CCPU			8
+#define RESET_PMUX			9
+#define RESET_VENC			10
+#define RESET_ASSIST			11
+#define RESET_AFIFO2			12
+#define RESET_MDEC			13
+#define RESET_VLD_PART			14
+#define RESET_VIFIFO			15
+/*					16-31	*/
+/*	RESET1					*/
+/*					32	*/
+#define RESET_DEMUX			33
+#define RESET_USB_OTG			34
+#define RESET_DDR			35
+#define RESET_VDAC_1			36
+#define RESET_BT656			37
+#define RESET_AHB_SRAM			38
+#define RESET_AHB_BRIDGE		39
+#define RESET_PARSER			40
+#define RESET_BLKMV			41
+#define RESET_ISA			42
+#define RESET_ETHERNET			43
+#define RESET_ABUF			44
+#define RESET_AHB_DATA			45
+#define RESET_AHB_CNTL			46
+#define RESET_ROM_BOOT			47
+/*					48-63	*/
+/*	RESET2					*/
+#define RESET_VD_RMEM			64
+#define RESET_AUDIN			65
+#define RESET_DBLK			66
+#define RESET_PIC_DC			66
+#define RESET_PSC			66
+#define RESET_NAND			66
+#define RESET_GE2D			70
+#define RESET_PARSER_REG		71
+#define RESET_PARSER_FETCH		72
+#define RESET_PARSER_CTL		73
+#define RESET_PARSER_TOP		74
+#define RESET_HDMI_APB			75
+#define RESET_AUDIO_APB			76
+#define RESET_MEDIA_CPU			77
+#define RESET_MALI			78
+#define RESET_HDMI_SYSTEM_RESET		79
+/*					80-95	*/
+/*	RESET3					*/
+#define RESET_RING_OSCILLATOR		96
+#define RESET_SYS_CPU_0			97
+#define RESET_EFUSE			98
+#define RESET_SYS_CPU_BVCI		99
+#define RESET_AIFIFO			100
+#define RESET_AUDIO_PLL_MODULATOR	101
+#define RESET_AHB_BRIDGE_CNTL		102
+#define RESET_SYS_CPU_1			103
+#define RESET_AUDIO_DAC			104
+#define RESET_DEMUX_TOP			105
+#define RESET_DEMUX_DES			106
+#define RESET_DEMUX_S2P_0		107
+#define RESET_DEMUX_S2P_1		108
+#define RESET_DEMUX_RESET_0		109
+#define RESET_DEMUX_RESET_1		110
+#define RESET_DEMUX_RESET_2		111
+/*					112-127	*/
+/*	RESET4					*/
+#define RESET_PL310			128
+#define RESET_A5_APB			129
+#define RESET_A5_AXI			130
+#define RESET_A5			131
+#define RESET_DVIN			132
+#define RESET_RDMA			133
+#define RESET_VENCI			134
+#define RESET_VENCP			135
+#define RESET_VENCT			136
+#define RESET_VDAC_4			137
+#define RESET_RTC			138
+#define RESET_A5_DEBUG			139
+#define RESET_VDI6			140
+#define RESET_VENCL			141
+/*					142-159	*/
+/*	RESET5					*/
+#define RESET_DDR_PLL			160
+#define RESET_MISC_PLL			161
+#define RESET_SYS_PLL			162
+#define RESET_HPLL_PLL			163
+#define RESET_AUDIO_PLL			164
+#define RESET_VID2_PLL			165
+/*					166-191	*/
+/*	RESET6					*/
+#define RESET_PERIPHS_GENERAL		192
+#define RESET_PERIPHS_IR_REMOTE		193
+#define RESET_PERIPHS_SMART_CARD	194
+#define RESET_PERIPHS_SAR_ADC		195
+#define RESET_PERIPHS_I2C_MASTER_0	196
+#define RESET_PERIPHS_I2C_MASTER_1	197
+#define RESET_PERIPHS_I2C_SLAVE		198
+#define RESET_PERIPHS_STREAM_INTERFACE	199
+#define RESET_PERIPHS_SDIO		200
+#define RESET_PERIPHS_UART_0		201
+#define RESET_PERIPHS_UART_1		202
+#define RESET_PERIPHS_ASYNC_0		203
+#define RESET_PERIPHS_ASYNC_1		204
+#define RESET_PERIPHS_SPI_0		205
+#define RESET_PERIPHS_SPI_1		206
+#define RESET_PERIPHS_LED_PWM		207
+/*					208-223	*/
+/*	RESET7					*/
+/*					224-255	*/
+
+#endif
-- 
2.7.0



From narmstrong at baylibre.com  Mon May 30 06:27:18 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 30 May 2016 15:27:18 +0200
Subject: [PATCH v3 4/4] ARM: dts: amlogic: Enable Reset Controller on Meson8b
 platforms
In-Reply-To: <1464614838-28107-1-git-send-email-narmstrong@baylibre.com>
References: <1464614838-28107-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464614838-28107-5-git-send-email-narmstrong@baylibre.com>

Update DTSI file to add the reset controller node.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm/boot/dts/meson8b.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index 2bfe401..fc4080d 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -46,6 +46,7 @@
 
 #include <dt-bindings/clock/meson8b-clkc.h>
 #include <dt-bindings/gpio/meson8b-gpio.h>
+#include <dt-bindings/reset/amlogic,meson8b-reset.h>
 #include "skeleton.dtsi"
 
 / {
@@ -105,6 +106,12 @@
 			#interrupt-cells = <3>;
 		};
 
+		reset: reset-controller at c1104404 {
+			compatible = "amlogic,meson8b-reset";
+			reg = <0xc1104404 0x20>;
+			#reset-cells = <1>;
+		};
+
 		wdt: watchdog at c1109900 {
 			compatible = "amlogic,meson8b-wdt";
 			reg = <0xc1109900 0x8>;
-- 
2.7.0



From narmstrong at baylibre.com  Mon May 30 06:27:17 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 30 May 2016 15:27:17 +0200
Subject: [PATCH v3 3/4] ARM64: dts: amlogic: Enable Reset Controller on
 GXBB-based platforms
In-Reply-To: <1464614838-28107-1-git-send-email-narmstrong@baylibre.com>
References: <1464614838-28107-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464614838-28107-4-git-send-email-narmstrong@baylibre.com>

Update DTSI file to add the reset controller node.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 832815d..45e9c55 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -43,6 +43,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
 
 / {
 	compatible = "amlogic,meson-gxbb";
@@ -129,6 +130,12 @@
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
 
+			reset: reset-controller at 4404 {
+				compatible = "amlogic,meson-gxbb-reset";
+				reg = <0x0 0x04404 0x0 0x20>;
+				#reset-cells = <1>;
+			};
+
 			uart_A: serial at 84c0 {
 				compatible = "amlogic,meson-uart";
 				reg = <0x0 0x084c0 0x0 0x14>;
-- 
2.7.0



From narmstrong at baylibre.com  Mon May 30 06:28:13 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 30 May 2016 15:28:13 +0200
Subject: [PATCH v3 0/4] Amlogic: Meson: Add reset controller
Message-ID: <1464614897-28173-1-git-send-email-narmstrong@baylibre.com>

Patchset to add and enable the reset controller driver on Meson SoCs platforms.

This reset controller has up to 256 reset lines with reset pulse generation only,
so the assert and deassert calls are not available.

Depends on the patch :
 - "reset: add devm_reset_controller_register API" [1]

Changes since v2 at http://lkml.kernel.org/r/1464169758-26975-1-git-send-email-narmstrong at baylibre.com :
- Get back __iomem in _reset() callback
- Get rid of MODULE_ALIAS

Changes since v1 at http://lkml.kernel.org/r/1463732875-23141-1-git-send-email-narmstrong at baylibre.com :
- Remove _gxbb_ in names
- Depends build on ARCH_MESON only
- Add meson8b compatible and bindings
- Re-indent dt-bindings headers
- Switch to devm_ reset controller register
- Remove platform "remove" callback
- Update Dual BSD/GPL file headers

Changes since the RFC at http://lkml.kernel.org/r/1463148012-25988-1-git-send-email-narmstrong at baylibre.com :
- Fix register mapping and bit defines in bindings header
- Remove assert and unassert calls
- Fix missing __iomem

[1] https://patchwork.kernel.org/patch/8988471/

Neil Armstrong (4):
  reset: Add support for the Amlogic Meson SoC Reset Controller
  dt-bindings: reset: Add bindings for the Meson SoC Reset Controller
  ARM64: dts: amlogic: Enable Reset Controller on GXBB-based platforms
  ARM: dts: amlogic: Enable Reset Controller on Meson8b platforms

 .../bindings/reset/amlogic,meson-reset.txt         |  18 ++
 arch/arm/boot/dts/meson8b.dtsi                     |   7 +
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   7 +
 drivers/reset/Makefile                             |   1 +
 drivers/reset/reset-meson.c                        | 136 +++++++++++++
 .../dt-bindings/reset/amlogic,meson-gxbb-reset.h   | 210 +++++++++++++++++++++
 include/dt-bindings/reset/amlogic,meson8b-reset.h  | 175 +++++++++++++++++
 7 files changed, 554 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/amlogic,meson-reset.txt
 create mode 100644 drivers/reset/reset-meson.c
 create mode 100644 include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
 create mode 100644 include/dt-bindings/reset/amlogic,meson8b-reset.h

-- 
2.7.0



From narmstrong at baylibre.com  Mon May 30 06:29:05 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 30 May 2016 15:29:05 +0200
Subject: [PATCH 0/3] watchdog: Add Amlogic Meson GXBB Watchdog Timer driver
Message-ID: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>

Adds support for the Amlogic Meson GXBB SoC Watchdog Timer.
It differs from the meson6/meson8b HW, so need for a separate driver.
The HW provides a divider capable of having a 1ms timebase thus simplifying
the counter update.
The restart call is not provided even if the HW is capable of triggering a
system reset immediately because of the PSCI firmare having such functionnality.
The watchdog is not expected to be running at boot time since there is a separate
system-level watchdog running from the SCPI co-processor, but this case would be
handle in a next driver update.

Changes since RFC version at http://lkml.kernel.org/r/1464249112-13658-1-git-send-email-narmstrong at baylibre.com :
- Remove status callback, will re-introduce it later to managed the already-running use case
- Fix registers defines indentation
- Fix space between operators
- Make all callbacks static functions
- Fix bindings with missing clocks attribute
- Do not stop/start watchdog on a timeout setup
- Fix probe device configuration

Neil Armstrong (3):
  watchdog: Add Meson GXBB Watchdog Driver
  dt-bindings: watchdog: Add Meson GXBB Watchdog bindings
  ARM64: dts: amlogic: meson-gxbb: Add watchdog node

 .../bindings/watchdog/meson-gxbb-wdt.txt           |  16 ++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |   6 +
 drivers/watchdog/Makefile                          |   1 +
 drivers/watchdog/meson_gxbb_wdt.c                  | 277 +++++++++++++++++++++
 4 files changed, 300 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt
 create mode 100644 drivers/watchdog/meson_gxbb_wdt.c

-- 
2.7.0



From narmstrong at baylibre.com  Mon May 30 06:29:06 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 30 May 2016 15:29:06 +0200
Subject: [PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
References: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464614948-28247-2-git-send-email-narmstrong@baylibre.com>

Add watchdog specific driver for Amlogic Meson GXBB SoC.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/watchdog/Makefile         |   1 +
 drivers/watchdog/meson_gxbb_wdt.c | 277 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 278 insertions(+)
 create mode 100644 drivers/watchdog/meson_gxbb_wdt.c

diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 9bde095..7679d93 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
 obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
 obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
 obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
+obj-$(CONFIG_MESON_WATCHDOG) += meson_gxbb_wdt.o
 obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
 obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
 obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
diff --git a/drivers/watchdog/meson_gxbb_wdt.c b/drivers/watchdog/meson_gxbb_wdt.c
new file mode 100644
index 0000000..9619c5e
--- /dev/null
+++ b/drivers/watchdog/meson_gxbb_wdt.c
@@ -0,0 +1,277 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * BSD LICENSE
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong at baylibre.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *   * Neither the name of Intel Corporation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+#define DEFAULT_TIMEOUT	10	/* seconds */
+
+#define GXBB_WDT_CTRL_REG			0x0
+#define GXBB_WDT_CTRL1_REG			0x4
+#define GXBB_WDT_TCNT_REG			0x8
+#define GXBB_WDT_RSET_REG			0xc
+
+#define GXBB_WDT_CTRL_EE_RESET_NOW		BIT(26)
+
+#define GXBB_WDT_CTRL_CLKDIV_EN			BIT(25)
+#define GXBB_WDT_CTRL_CLK_EN			BIT(24)
+#define GXBB_WDT_CTRL_IRQ_EN			BIT(23)
+#define GXBB_WDT_CTRL_EE_RESET			BIT(21)
+#define GXBB_WDT_CTRL_XTAL_SEL			(0)
+#define GXBB_WDT_CTRL_CLK81_SEL			BIT(19)
+#define GXBB_WDT_CTRL_EN			BIT(18)
+#define GXBB_WDT_CTRL_DIV_MASK			(BIT(18) - 1)
+
+#define GXBB_WDT_CTRL1_GPIO_PULSE		BIT(17)
+#define GXBB_WDT_CTRL1_GPIO_POL_RESET_0		BIT(16)
+#define GXBB_WDT_CTRL1_GPIO_POL_RESET_1		(0)
+#define GXBB_WDT_CTRL1_GPIO_PULSE_CNT		(BIT(16) - 1)
+
+#define GXBB_WDT_TCNT_SETUP_MASK		(BIT(16) - 1)
+#define GXBB_WDT_TCNT_CNT_SHIFT			16
+
+struct meson_gxbb_wdt {
+	void __iomem *reg_base;
+	struct watchdog_device wdt_dev;
+	struct clk *clk;
+};
+
+static int meson_gxbb_wdt_start(struct watchdog_device *wdt_dev)
+{
+	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
+
+	writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) | GXBB_WDT_CTRL_EN,
+		data->reg_base + GXBB_WDT_CTRL_REG);
+
+	return 0;
+}
+
+static int meson_gxbb_wdt_stop(struct watchdog_device *wdt_dev)
+{
+	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
+
+	writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) & ~GXBB_WDT_CTRL_EN,
+		data->reg_base + GXBB_WDT_CTRL_REG);
+
+	return 0;
+}
+
+static int meson_gxbb_wdt_ping(struct watchdog_device *wdt_dev)
+{
+	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
+
+	writel(0, data->reg_base + GXBB_WDT_RSET_REG);
+
+	return 0;
+}
+
+static int meson_gxbb_wdt_get_timeout(struct meson_gxbb_wdt *data)
+{
+	return (readl(data->reg_base + GXBB_WDT_TCNT_REG) &
+			GXBB_WDT_TCNT_SETUP_MASK) / 1000;
+}
+
+static int meson_gxbb_wdt_set_timeout(struct watchdog_device *wdt_dev,
+				      unsigned int timeout)
+{
+	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
+
+	meson_gxbb_wdt_ping(wdt_dev);
+
+	writel(timeout * 1000, data->reg_base + GXBB_WDT_TCNT_REG);
+
+	return 0;
+}
+
+static unsigned int meson_gxbb_wdt_get_timeleft(struct watchdog_device *wdt_dev)
+{
+	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
+	unsigned long reg;
+
+	reg = readl(data->reg_base + GXBB_WDT_TCNT_REG);
+
+	return ((reg >> GXBB_WDT_TCNT_CNT_SHIFT)-
+			(reg & GXBB_WDT_TCNT_SETUP_MASK)) / 1000;
+}
+
+static const struct watchdog_ops meson_gxbb_wdt_ops = {
+	.start = meson_gxbb_wdt_start,
+	.stop = meson_gxbb_wdt_stop,
+	.ping = meson_gxbb_wdt_ping,
+	.set_timeout = meson_gxbb_wdt_set_timeout,
+	.get_timeleft = meson_gxbb_wdt_get_timeleft,
+};
+
+static const struct watchdog_info meson_gxbb_wdt_info = {
+	.identity = "meson-gxbb-wdt",
+	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+};
+
+static int __maybe_unused meson_gxbb_wdt_resume(struct device *dev)
+{
+	struct meson_gxbb_wdt *data = dev_get_drvdata(dev);
+
+	if (watchdog_active(&data->wdt_dev))
+		meson_gxbb_wdt_start(&data->wdt_dev);
+
+	return 0;
+}
+
+static int __maybe_unused meson_gxbb_wdt_suspend(struct device *dev)
+{
+	struct meson_gxbb_wdt *data = dev_get_drvdata(dev);
+
+	if (watchdog_active(&data->wdt_dev))
+		meson_gxbb_wdt_stop(&data->wdt_dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops meson_gxbb_wdt_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(meson_gxbb_wdt_suspend, meson_gxbb_wdt_resume)
+};
+
+static const struct of_device_id meson_gxbb_wdt_dt_ids[] = {
+	 { .compatible = "amlogic,meson-gxbb-wdt", },
+	 { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, meson_gxbb_wdt_dt_ids);
+
+static int meson_gxbb_wdt_probe(struct platform_device *pdev)
+{
+	struct meson_gxbb_wdt *data;
+	struct resource *res;
+	int ret;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(data->reg_base))
+		return PTR_ERR(data->reg_base);
+
+	data->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(data->clk))
+		return PTR_ERR(data->clk);
+
+	clk_prepare_enable(data->clk);
+
+	platform_set_drvdata(pdev, data);
+
+	data->wdt_dev.parent = &pdev->dev;
+	data->wdt_dev.info = &meson_gxbb_wdt_info;
+	data->wdt_dev.ops = &meson_gxbb_wdt_ops;
+	data->wdt_dev.max_hw_heartbeat_ms = GXBB_WDT_TCNT_SETUP_MASK;
+	data->wdt_dev.min_timeout = 1;
+	data->wdt_dev.timeout = DEFAULT_TIMEOUT;
+	watchdog_set_drvdata(&data->wdt_dev, data);
+
+	/* Setup with 1ms timebase */
+	writel(((clk_get_rate(data->clk) / 1000) & GXBB_WDT_CTRL_DIV_MASK) |
+		GXBB_WDT_CTRL_EE_RESET |
+		GXBB_WDT_CTRL_CLK_EN |
+		GXBB_WDT_CTRL_CLKDIV_EN,
+		data->reg_base + GXBB_WDT_CTRL_REG);
+
+	meson_gxbb_wdt_set_timeout(&data->wdt_dev, data->wdt_dev.timeout);
+
+	ret = watchdog_register_device(&data->wdt_dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int meson_gxbb_wdt_remove(struct platform_device *pdev)
+{
+	struct meson_gxbb_wdt *data = platform_get_drvdata(pdev);
+
+	watchdog_unregister_device(&data->wdt_dev);
+
+	return 0;
+}
+
+static void meson_gxbb_wdt_shutdown(struct platform_device *pdev)
+{
+	struct meson_gxbb_wdt *data = platform_get_drvdata(pdev);
+
+	meson_gxbb_wdt_stop(&data->wdt_dev);
+}
+
+static struct platform_driver meson_gxbb_wdt_driver = {
+	.probe	= meson_gxbb_wdt_probe,
+	.remove	= meson_gxbb_wdt_remove,
+	.shutdown = meson_gxbb_wdt_shutdown,
+	.driver = {
+		.name = "meson-gxbb-wdt",
+		.pm = &meson_gxbb_wdt_pm_ops,
+		.of_match_table	= meson_gxbb_wdt_dt_ids,
+	},
+};
+
+module_platform_driver(meson_gxbb_wdt_driver);
+
+MODULE_ALIAS("platform:meson-gxbb-wdt");
+MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
+MODULE_DESCRIPTION("Amlogic Meson GXBB Watchdog timer driver");
+MODULE_LICENSE("Dual BSD/GPL");
-- 
2.7.0



From narmstrong at baylibre.com  Mon May 30 06:29:08 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 30 May 2016 15:29:08 +0200
Subject: [PATCH 3/3] ARM64: dts: amlogic: meson-gxbb: Add watchdog node
In-Reply-To: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
References: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464614948-28247-4-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 832815d..bcca82f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -136,6 +136,12 @@
 				clocks = <&xtal>;
 				status = "disabled";
 			};
+
+			watchdog at 98d0 {
+				compatible = "amlogic,meson-gxbb-wdt";
+				reg = <0x0 0x098d0 0x0 0x10>;
+				clocks = <&xtal>;
+			};
 		};
 
 		gic: interrupt-controller at c4301000 {
-- 
2.7.0



From andrew at lunn.ch  Mon May 30 06:34:42 2016
From: andrew at lunn.ch (Andrew Lunn)
Date: Mon, 30 May 2016 15:34:42 +0200
Subject: [PATCH 5/7] net:mdio-mux: Add MDIO mux driver for iProc SoCs
In-Reply-To: <1464592251-2688-6-git-send-email-pramod.kumar@broadcom.com>
References: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
 <1464592251-2688-6-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <20160530133442.GK6027@lunn.ch>

On Mon, May 30, 2016 at 12:40:49PM +0530, Pramod Kumar wrote:
> iProc based SoCs supports the integrated mdio multiplexer which
> has the bus selection as well as mdio transaction generation logic
> inside.

Hi Pramod

Great to see you using the existing MDIO framework. Thanks.

> +static int mdio_mux_iproc_switch_fn(int current_child, int desired_child,
> +				    void *data)
> +{
> +	struct iproc_mdiomux_desc *md = data;
> +	struct mdiomux_bus_param *bp = &md->bus_param[desired_child];
> +	u32 param, bus_id;
> +	bool bus_dir;
> +
> +	/* select bus and its properties */
> +	bus_dir = (desired_child < EXT_BUS_START_ADDR);
> +	bus_id = bus_dir ? desired_child : (desired_child - EXT_BUS_START_ADDR);
> +
> +	param = (bus_dir ? 1 : 0) << MDIO_PARAM_INTERNAL_SEL;
> +	param |= (bp->is_c45 ? 1 : 0) << MDIO_PARAM_C45_SEL;
> +	param |= (bus_id << MDIO_PARAM_BUS_ID);
> +
> +	writel(param, md->base + MDIO_PARAM_OFFSET);
> +	return 0;
> +}

What i don't yet see is why you went for the concept of an integrated
MDIO and MUX. This function above is the mux function, and it looks
like it could be used to implement a standard mdio-mux driver.

Thanks
     Andrew


From carlo at caione.org  Mon May 30 06:45:37 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 30 May 2016 15:45:37 +0200
Subject: [PATCH 0/3] watchdog: Add Amlogic Meson GXBB Watchdog Timer driver
In-Reply-To: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
References: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160530134537.GA16188@mephisto>

On 30/05/16 15:29, Neil Armstrong wrote:
> Adds support for the Amlogic Meson GXBB SoC Watchdog Timer.
> It differs from the meson6/meson8b HW, so need for a separate driver.
> The HW provides a divider capable of having a 1ms timebase thus simplifying
> the counter update.
> The restart call is not provided even if the HW is capable of triggering a
> system reset immediately because of the PSCI firmare having such functionnality.
> The watchdog is not expected to be running at boot time since there is a separate
> system-level watchdog running from the SCPI co-processor, but this case would be
> handle in a next driver update.
> 
> Changes since RFC version at http://lkml.kernel.org/r/1464249112-13658-1-git-send-email-narmstrong at baylibre.com :
> - Remove status callback, will re-introduce it later to managed the already-running use case
> - Fix registers defines indentation
> - Fix space between operators
> - Make all callbacks static functions
> - Fix bindings with missing clocks attribute
> - Do not stop/start watchdog on a timeout setup
> - Fix probe device configuration
> 
> Neil Armstrong (3):
>   watchdog: Add Meson GXBB Watchdog Driver
>   dt-bindings: watchdog: Add Meson GXBB Watchdog bindings
>   ARM64: dts: amlogic: meson-gxbb: Add watchdog node

I'm missing [PATCH 2/3]

-- 
Carlo Caione


From carlo at caione.org  Mon May 30 06:51:25 2016
From: carlo at caione.org (Carlo Caione)
Date: Mon, 30 May 2016 15:51:25 +0200
Subject: [PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <1464614948-28247-2-git-send-email-narmstrong@baylibre.com>
References: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
 <1464614948-28247-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <20160530135125.GB16188@mephisto>

On 30/05/16 15:29, Neil Armstrong wrote:
> Add watchdog specific driver for Amlogic Meson GXBB SoC.
> 
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> +

> +#define GXBB_WDT_CTRL1_REG			0x4
...
> +#define GXBB_WDT_CTRL_EE_RESET_NOW		BIT(26)
...
> +#define GXBB_WDT_CTRL_IRQ_EN			BIT(23)
...
> +#define GXBB_WDT_CTRL_XTAL_SEL			(0)
...
> +#define GXBB_WDT_CTRL_CLK81_SEL			BIT(19)
...
> +#define GXBB_WDT_CTRL1_GPIO_PULSE		BIT(17)
...
> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_0		BIT(16)
> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_1		(0)
> +#define GXBB_WDT_CTRL1_GPIO_PULSE_CNT		(BIT(16) - 1)

nit: all these defines are not used at all in the driver. You can remove them

Thanks!


-- 
Carlo Caione


From narmstrong at baylibre.com  Mon May 30 07:12:06 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 30 May 2016 16:12:06 +0200
Subject: [PATCH 2/3] dt-bindings: watchdog: Add Meson GXBB Watchdog bindings
In-Reply-To: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
References: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464617526-29140-1-git-send-email-narmstrong@baylibre.com>

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 .../devicetree/bindings/watchdog/meson-gxbb-wdt.txt      | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt b/Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt
new file mode 100644
index 0000000..c7fe36f
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/meson-gxbb-wdt.txt
@@ -0,0 +1,16 @@
+Meson GXBB SoCs Watchdog timer
+
+Required properties:
+
+- compatible : should be "amlogic,meson-gxbb-wdt"
+- reg : Specifies base physical address and size of the registers.
+- clocks : Should be a phandle to the Watchdog clock source, for GXBB the xtal
+	   is the default clock source.
+
+Example:
+
+wdt: watchdog at 98d0 {
+	compatible = "amlogic,meson-gxbb-wdt";
+	reg = <0 0x98d0 0x0 0x10>;
+	clocks = <&xtal>;
+};
-- 
2.7.0



From narmstrong at baylibre.com  Mon May 30 07:13:10 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Mon, 30 May 2016 16:13:10 +0200
Subject: [PATCH 0/3] watchdog: Add Amlogic Meson GXBB Watchdog Timer driver
In-Reply-To: <20160530134537.GA16188@mephisto>
References: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
 <20160530134537.GA16188@mephisto>
Message-ID: <574C4A76.10807@baylibre.com>

On 05/30/2016 03:45 PM, Carlo Caione wrote:
> On 30/05/16 15:29, Neil Armstrong wrote:
>> Adds support for the Amlogic Meson GXBB SoC Watchdog Timer.
>> It differs from the meson6/meson8b HW, so need for a separate driver.
>> The HW provides a divider capable of having a 1ms timebase thus simplifying
>> the counter update.
>> The restart call is not provided even if the HW is capable of triggering a
>> system reset immediately because of the PSCI firmare having such functionnality.
>> The watchdog is not expected to be running at boot time since there is a separate
>> system-level watchdog running from the SCPI co-processor, but this case would be
>> handle in a next driver update.
>>
>> Changes since RFC version at http://lkml.kernel.org/r/1464249112-13658-1-git-send-email-narmstrong at baylibre.com :
>> - Remove status callback, will re-introduce it later to managed the already-running use case
>> - Fix registers defines indentation
>> - Fix space between operators
>> - Make all callbacks static functions
>> - Fix bindings with missing clocks attribute
>> - Do not stop/start watchdog on a timeout setup
>> - Fix probe device configuration
>>
>> Neil Armstrong (3):
>>   watchdog: Add Meson GXBB Watchdog Driver
>>   dt-bindings: watchdog: Add Meson GXBB Watchdog bindings
>>   ARM64: dts: amlogic: meson-gxbb: Add watchdog node
> 
> I'm missing [PATCH 2/3]
> 
Sorry, fixed here :


From bogdan.purcareata at nxp.com  Mon May 30 07:15:42 2016
From: bogdan.purcareata at nxp.com (Bogdan Purcareata)
Date: Mon, 30 May 2016 14:15:42 +0000
Subject: [PATCH] iommu/arm-smmu: Properly initialize CBAR MemAttr
Message-ID: <1464617742-5493-1-git-send-email-bogdan.purcareata@nxp.com>

Currently, when initializing the CBAR memattr attributes to the weakest
values, it is expected that the final ones will be declared in the TTBCR
register (SMMU_CBn_TCR).

This is not required when CBAR type consists of a stage 1 translation
followed by a stage 2 bypass. This is the case when assigning a VFIO PCI
device to a KVM guest. Overriding the default transaction attributes to
writeback cacheable results in the device no longer working in the guest
(the adapter requires explicit flushes on the descriptor rings memory).

Update the context init routine to initialize the CBAR MemAttr field only
if there's a stage 1 followed by a stage 2 translation.

Signed-off-by: Bogdan Purcareata <bogdan.purcareata at nxp.com>
---
 drivers/iommu/arm-smmu.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index ff7a392..1400ec9 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -765,13 +765,14 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
 {
 	u32 reg;
 	u64 reg64;
-	bool stage1;
+	bool stage1, stage1_stage2;
 	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
 	struct arm_smmu_device *smmu = smmu_domain->smmu;
 	void __iomem *cb_base, *gr1_base;
 
 	gr1_base = ARM_SMMU_GR1(smmu);
 	stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
+	stage1_stage2 = cfg->cbar == CBAR_TYPE_S1_TRANS_S2_TRANS;
 	cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
 
 	if (smmu->version > ARM_SMMU_V1) {
@@ -793,15 +794,19 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
 
 	/*
 	 * Use the weakest shareability/memory types, so they are
-	 * overridden by the ttbcr/pte.
+	 * overridden by the ttbcr/pte. This happens only if the stage
+	 * 1 is followed by a stage 2 translation.
 	 */
-	if (stage1) {
+	if (stage1_stage2) {
 		reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
 			(CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
-	} else if (!(smmu->features & ARM_SMMU_FEAT_VMID16)) {
+	}
+
+	if (!stage1 && !(smmu->features & ARM_SMMU_FEAT_VMID16)) {
 		/* 8-bit VMIDs live in CBAR */
 		reg |= ARM_SMMU_CB_VMID(smmu, cfg) << CBAR_VMID_SHIFT;
 	}
+
 	writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx));
 
 	/* TTBRs */
-- 
1.9.1



From pramod.kumar at broadcom.com  Mon May 30 07:39:08 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Mon, 30 May 2016 20:09:08 +0530
Subject: [PATCH 5/7] net:mdio-mux: Add MDIO mux driver for iProc SoCs
In-Reply-To: <20160530133442.GK6027@lunn.ch>
References: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
 <1464592251-2688-6-git-send-email-pramod.kumar@broadcom.com>
 <20160530133442.GK6027@lunn.ch>
Message-ID: <c26a73e6243f0cf11b7745ac5bcc8a4b@mail.gmail.com>

Hi Andrew,

Thanks for reviewing. Please see my comment inline.

> -----Original Message-----
> From: Andrew Lunn [mailto:andrew at lunn.ch]
> Sent: 30 May 2016 19:05
> To: Pramod Kumar
> Cc: Rob Herring; Pawel Moll; Mark Rutland; Ian Campbell; Kumar Gala;
Catalin
> Marinas; Will Deacon; Kishon Vijay Abraham I; David S. Miller;
> devicetree at vger.kernel.org; netdev at vger.kernel.org; linux-
> kernel at vger.kernel.org; bcm-kernel-feedback-list at broadcom.com;
linux-arm-
> kernel at lists.infradead.org
> Subject: Re: [PATCH 5/7] net:mdio-mux: Add MDIO mux driver for iProc
SoCs
>
> On Mon, May 30, 2016 at 12:40:49PM +0530, Pramod Kumar wrote:
> > iProc based SoCs supports the integrated mdio multiplexer which has
> > the bus selection as well as mdio transaction generation logic inside.
>
> Hi Pramod
>
> Great to see you using the existing MDIO framework. Thanks.
>
> > +static int mdio_mux_iproc_switch_fn(int current_child, int
desired_child,
> > +				    void *data)
> > +{
> > +	struct iproc_mdiomux_desc *md = data;
> > +	struct mdiomux_bus_param *bp = &md->bus_param[desired_child];
> > +	u32 param, bus_id;
> > +	bool bus_dir;
> > +
> > +	/* select bus and its properties */
> > +	bus_dir = (desired_child < EXT_BUS_START_ADDR);
> > +	bus_id = bus_dir ? desired_child : (desired_child -
> > +EXT_BUS_START_ADDR);
> > +
> > +	param = (bus_dir ? 1 : 0) << MDIO_PARAM_INTERNAL_SEL;
> > +	param |= (bp->is_c45 ? 1 : 0) << MDIO_PARAM_C45_SEL;
> > +	param |= (bus_id << MDIO_PARAM_BUS_ID);
> > +
> > +	writel(param, md->base + MDIO_PARAM_OFFSET);
> > +	return 0;
> > +}
>
> What i don't yet see is why you went for the concept of an integrated
MDIO and
> MUX. This function above is the mux function, and it looks like it could
be used
> to implement a standard mdio-mux driver.
>

iProc based SoCs Integrated MDIO Multiplexer has both logic in a hardware.
MDIO transaction and Child bus selection logic share the same address
space.
For ex-

In above mux function- Register-MDIO_PARAM_OFFSET is used for bus,
direction and transaction type. Same register
Is used for programming the PHY Ids and write data values in MDIO parent
bus transaction.

Writing MDIO bus driver and mux driver separately gives a notion of being
two separate device/address space, obviously it is not our use case.
Even if we used syscon for accessing the shared register, this does not
appears good for writing separate drivers for a single device.


> Thanks
>      Andrew

Regards,
Pramod


From linux at roeck-us.net  Mon May 30 07:44:17 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Mon, 30 May 2016 07:44:17 -0700
Subject: [PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <1464614948-28247-2-git-send-email-narmstrong@baylibre.com>
References: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
 <1464614948-28247-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <574C51C1.1060609@roeck-us.net>

On 05/30/2016 06:29 AM, Neil Armstrong wrote:
> Add watchdog specific driver for Amlogic Meson GXBB SoC.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>   drivers/watchdog/Makefile         |   1 +
>   drivers/watchdog/meson_gxbb_wdt.c | 277 ++++++++++++++++++++++++++++++++++++++
>   2 files changed, 278 insertions(+)
>   create mode 100644 drivers/watchdog/meson_gxbb_wdt.c
>
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index 9bde095..7679d93 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -68,6 +68,7 @@ obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
>   obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
>   obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
>   obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
> +obj-$(CONFIG_MESON_WATCHDOG) += meson_gxbb_wdt.o

No extra Kconfig entry ? Why ?



From arnd at arndb.de  Mon May 30 07:57:55 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 30 May 2016 16:57:55 +0200
Subject: [PATCH 1/4]  base: soc: introduce soc_device_match() interface
In-Reply-To: <6032641.cjSseEG2PF@wuerfel>
References: <1462417950-46796-1-git-send-email-yangbo.lu@nxp.com>
 <CAPDyKFqx2JMLzXoDxGCKFYMFV47+SegnkuWFXKvsQHK7L5w-1g@mail.gmail.com>
 <6032641.cjSseEG2PF@wuerfel>
Message-ID: <4811326.1KLIei2jcl@wuerfel>

On Monday, May 30, 2016 3:14:38 PM CEST Arnd Bergmann wrote:
> We keep running into cases where device drivers want to know the exact
> version of the SoC a they are currently running on. In the past, this
> has usually been done through a vendor specific API that can be called
> by a driver, or by directly accessing some kind of version register
> that is not part of the device itself but that belongs to a global
> register area of the chip.
> 
> Common reasons for doing this include:
> 
> - A machine is not using devicetree or similar for passing data
>   about on-chip devices, but just announces their presence using
>   boot-time platform devices, and the machine code itself does
>   not care about the revision.
> 
> - There is existing firmware or boot loaders with existing DT
>   binaries with generic compatible strings that do not identify
>   the particular revision of each device, but the driver knows
>   which SoC revisions include which part
> 
> - A prerelease version of a chip has some quirks and we are
>   using the same version of the bootloader and the DT blob
>   on both the prerelease and the final version. An update of
>   the DT binding seems inappropriate because that would involve
>   maintaining multiple copies of the dts and/or bootloader.
> 
> This introduces the soc_device_match() interface that is meant
> to work like of_match_node() but instead of identifying the
> version of a device, it identifies the SoC itself using a
> vendor-agnostic interface.
> 
> Unlike soc_device_match(), we do not do an exact string compare
> but instead use glob_match() to allow wildcards in strings.

I'm sorry the series introduced build failures (I had done some changes
after testing), here is a quick fixup. I'll resend the whole thing
after someone has looked at it as none of the changes below should
have any influence on the review.

	Arnd

diff --git a/drivers/base/soc.c b/drivers/base/soc.c
index e9623c6674a5..c38573249777 100644
--- a/drivers/base/soc.c
+++ b/drivers/base/soc.c
@@ -173,7 +173,7 @@ module_exit(soc_bus_unregister);
 static int soc_device_match_one(struct device *dev, void *arg)
 {
 	struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
-	struct soc_device_attribute *match = arg;
+	const struct soc_device_attribute *match = arg;
 
 	if (match->machine && !glob_match(match->machine, soc_dev->attr->machine))
 		return 0;
@@ -208,7 +208,7 @@ static int soc_device_match_one(struct device *dev, void *arg)
  * soc_device_attribute to pass a structure or function pointer for
  * each entry.
  */
-struct soc_device_attribute *soc_device_match(struct soc_device_attribute *matches)
+const struct soc_device_attribute *soc_device_match(const struct soc_device_attribute *matches)
 {
 	struct device *dev;
 	int ret;
@@ -219,7 +219,7 @@ struct soc_device_attribute *soc_device_match(struct soc_device_attribute *match
 			return NULL;
 
 		dev = NULL;
-		ret = bus_for_each_dev(&soc_bus_type, dev, matches,
+		ret = bus_for_each_dev(&soc_bus_type, dev, (void *)matches,
 					 soc_device_match_one);
 	}
 
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 1d4814fe4cb2..a7b8b05a13e8 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -19,6 +19,8 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/mmc/host.h>
+#include <linux/sys_soc.h>
+
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
 
@@ -75,7 +77,6 @@ static u16 esdhc_readw_fixup(struct sdhci_host *host,
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
-	u16 ret;
 	int shift = (spec_reg & 0x2) * 8;
 
 	if (spec_reg == SDHCI_HOST_VERSION)
@@ -565,7 +566,7 @@ static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = {
 };
 
 #define T4240_HOST_VER ((VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200)
-static const struct soc_device_attribute esdhc_t4240_quirk = {
+static const struct soc_device_attribute esdhc_t4240_quirk[] = {
 	/* T4240 revision < 0x20 uses vendor version 23, SDHCI version 200 */
 	{ .soc_id = "T4*(0x824000)", .revision = "0x[01]?",
 	  .data = (void *)(uintptr_t)(T4240_HOST_VER) },
@@ -576,6 +577,7 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_esdhc *esdhc;
+	u32 host_ver;
 
 	pltfm_host = sdhci_priv(host);
 	esdhc = sdhci_pltfm_priv(pltfm_host);
@@ -583,9 +585,9 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
 	host_ver = sdhci_readw(host, SDHCI_HOST_VERSION);
 
 	if (of_device_is_compatible(pdev->dev.of_node, "fsl,t4240-esdhc")) {
-		struct soc_device_attribute *match;
+		const struct soc_device_attribute *match;
 
-		match = soc_device_match(&esdhc_t4240_quirk);
+		match = soc_device_match(esdhc_t4240_quirk);
 		if (match)
 			host_ver = (uintptr_t)match->data;
 	}
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
index 2f30698f5bcf..476969644bed 100644
--- a/drivers/soc/fsl/guts.c
+++ b/drivers/soc/fsl/guts.c
@@ -34,14 +34,6 @@ static u32 fsl_guts_get_svr(struct guts *guts)
 		return ioread32be(guts->regs + GUTS_SVR);
 }
 
-static u32 fsl_guts_get_pvr(struct guts *guts)
-{
-	if (guts->little_endian)
-		return ioread32(guts->regs + GUTS_PVR);
-	else
-		return ioread32be(guts->regs + GUTS_PVR);
-}
-
 /*
  * Table for matching compatible strings, for device tree
  * guts node, for Freescale QorIQ SOCs.
@@ -76,13 +68,15 @@ static const struct of_device_id fsl_guts_of_match[] = {
 
 static void fsl_guts_init(struct device *dev, struct guts *guts)
 {
-	const struct of_device_id *id;
 	u32 svr = fsl_guts_get_svr(guts);
+	const struct of_device_id *id;
+	const char *socname;
 
 	guts->soc.family = "NXP QorIQ";
 	id = of_match_node(fsl_guts_of_match, dev->of_node);
-	guts->soc.soc_id = devm_kasprintf(dev, "%s (ver 0x%06x)" id->data,
-					  svr >> 8;
+	socname = id->data;
+	guts->soc.soc_id = devm_kasprintf(dev, GFP_KERNEL, "%s (ver 0x%06x)",
+					  socname, svr >> 8);
 	guts->soc.revision = devm_kasprintf(dev, GFP_KERNEL, "0x%02x",
 					    svr & 0xff);
 }
diff --git a/include/linux/sys_soc.h b/include/linux/sys_soc.h
index 02c48c76052b..3dfc8714a88c 100644
--- a/include/linux/sys_soc.h
+++ b/include/linux/sys_soc.h
@@ -36,6 +36,6 @@ void soc_device_unregister(struct soc_device *soc_dev);
  */
 struct device *soc_device_to_device(struct soc_device *soc);
 
-struct soc_device_attribute *soc_device_match(struct soc_device_attribute *matches);
+const struct soc_device_attribute *soc_device_match(const struct soc_device_attribute *matches);
 
 #endif /* __SOC_BUS_H */



From broonie at kernel.org  Mon May 30 08:03:43 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 30 May 2016 16:03:43 +0100
Subject: [PATCH 5/5] RFC spi: sun4i: add DMA support
In-Reply-To: <CAMuHMdVThvtqgFnyqoqypwwf1d81uu9NBo6-heTZBcvBxRevNw@mail.gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
 <ba0d6eb37cc4b0d2c46acbf9fcd7d644b3545ce8.1464130597.git.hramrach@gmail.com>
 <20160530112610.GJ29837@sirena.org.uk>
 <CAMuHMdVThvtqgFnyqoqypwwf1d81uu9NBo6-heTZBcvBxRevNw@mail.gmail.com>
Message-ID: <20160530150343.GL29837@sirena.org.uk>

On Mon, May 30, 2016 at 02:11:51PM +0200, Geert Uytterhoeven wrote:
> On Mon, May 30, 2016 at 1:26 PM, Mark Brown <broonie at kernel.org> wrote:
> > On Thu, May 26, 2016 at 07:25:25PM -0000, Michal Suchanek wrote:
> >>  - fallback to previous behaviour when DMA initialization fails
> >>
> >>    + this has the problem that when the driver happens to load before the dma
> >>      driver it will not use dma - can be addressed with a module parameter

> > No, you should pay attention to the error you are getting and let probe
> > deferral happen if that's the error you get.

> Unfortunately DMA is an optional feature.

> There's no way to distinguish between -EPROBE_DEFER due to the SPI master
> driver being probed before the DMA engine driver, and -EPROBE_DEFER due to
> support for the DMA engine not having been compiled in.

I really don't think it's worth caring too much about cases where the
DMA driver hasn't been compiled in, it's not like SPI is the only thing
that's going to be using it.  I really think it's better to defer the
problem - not getting DMA (or worse, only getting DMA on some boots) is
not great and if people are optimising on that level my feeling is that
they're probably going to be OK with customizing DT to match.  Ideally
we would have something a bit nicer than deferred probe but right now
this seems the more helpful option.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/7e494196/attachment.sig>

From daniel.lezcano at linaro.org  Mon May 30 08:07:16 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Mon, 30 May 2016 17:07:16 +0200
Subject: [PATCH v5 2/6] clocksource/drivers/arm_arch_timer: Add a new enum
 for spi type
In-Reply-To: <1464096633-9309-3-git-send-email-fu.wei@linaro.org>
References: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
 <1464096633-9309-3-git-send-email-fu.wei@linaro.org>
Message-ID: <574C5724.30200@linaro.org>

On 05/24/2016 03:30 PM, fu.wei at linaro.org wrote:
> From: Fu Wei <fu.wei at linaro.org>
>
> This patch add a new enum "spi_nr" and use it in the driver.
> Just for code's readability, no functional change.
>
> Signed-off-by: Fu Wei <fu.wei at linaro.org>
> ---
>   drivers/clocksource/arm_arch_timer.c | 4 ++--
>   include/clocksource/arm_arch_timer.h | 6 ++++++
>   2 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> index 5d7272e..966c574 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -826,9 +826,9 @@ static void __init arch_timer_mem_init(struct device_node *np)
>   	}
>
>   	if (arch_timer_mem_use_virtual)
> -		irq = irq_of_parse_and_map(best_frame, 1);
> +		irq = irq_of_parse_and_map(best_frame, VIRT_SPI);
>   	else
> -		irq = irq_of_parse_and_map(best_frame, 0);
> +		irq = irq_of_parse_and_map(best_frame, PHYS_SPI);
>
>   	if (!irq) {
>   		pr_err("arch_timer: Frame missing %s irq",
> diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
> index 6f06481..16dcd10 100644
> --- a/include/clocksource/arm_arch_timer.h
> +++ b/include/clocksource/arm_arch_timer.h
> @@ -45,6 +45,12 @@ enum ppi_nr {
>   	MAX_TIMER_PPI
>   };
>
> +enum spi_nr {
> +	PHYS_SPI,
> +	VIRT_SPI,
> +	MAX_TIMER_SPI
> +};

Wouldn't make sense to use the constant below instead of defining new ones ?

>   #define ARCH_TIMER_PHYS_ACCESS		0
>   #define ARCH_TIMER_VIRT_ACCESS		1
>   #define ARCH_TIMER_MEM_PHYS_ACCESS	2
>


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

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



From tn at semihalf.com  Mon May 30 08:14:13 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 30 May 2016 17:14:13 +0200
Subject: [PATCH V8 0/9] Support for ARM64 ACPI based PCI host controller
Message-ID: <1464621262-26770-1-git-send-email-tn@semihalf.com>

>From the functionality point of view this series may be split into the
following logic parts:
1. Export ECAM API and add parent device to pci_config_window
2. Add IO resources handling to PCI core code
3. Support for generic domain assignment based on ACPI
4. New MCFG driver
5. Implement ARM64 ACPI based PCI host controller driver under arch/arm64/

Patches has been built on top of 4.7-rc1 and can be found here:
git at github.com:semihalf-nowicki-tomasz/linux.git (pci-acpi-v8)

This has been tested on Cavium ThunderX server. Any help in reviewing and
testing is very appreciated.

v7 -> v8
- move code from drivers/acpi/pci_root_generic.c to arch/arm64/kernel/pci.c
- minor changes around domain assignment
- pci_mcfg.c improvements for parsing MCFG tables and lookup its entries

v6 -> v7
- drop quirks handling
- changes for ACPI companion and domain number assignment approach
- implement arch pcibios_{add|remove}_bus and call acpi_pci_{add|remove}_bus from there
- cleanups around nomenclature
- use resources oriented API for ECAM
- fix for based address calculation before mapping ECAM region
- remove useless lock for MCFG lookup
- move MCFG stuff to separated file pci_mcfg.c
- drop MCFG entries caching
- rebase against 4.6-rc7

v5 -> v6
- drop idea of x86 MMCONFIG code refactoring
- integrate JC's patches which introduce new ECAM API:
  https://lkml.org/lkml/2016/4/11/907
  git: https://github.com/jchandra-brcm/linux/ (arm64-acpi-pci-v3)
- integrate Sinan's fix for releasing IO resources, see patch [06/13]
- added ACPI support for ThunderX ECAM and PEM drivers
- rebase against 4.6-rc2

v4 -> v5
- drop MCFG refactoring group patches 1-6 from series v4 and integrate Jayachandran's patch
  https://patchwork.ozlabs.org/patch/575525/
- rewrite PCI legacy IRQs allocation
- squash two patches 11 and 12 from series v4, fixed bisection issue
- changelog improvements
- rebase against 4.5-rc3

v3 -> v4
- drop Jiang's fix http://lkml.iu.edu/hypermail/linux/kernel/1601.1/04318.html
- add Lorenzo's fix patch 19/24
- ACPI PCI bus domain number assigning cleanup
- change resource management, we now claim and reassign resources
- improvements for applying quirks
- drop Matthew's http://www.spinics.net/lists/linux-pci/msg45950.html dependency
- rebase against 4.5-rc1

v2 -> v3
- fix legacy IRQ assigning and IO ports registration
- remove reference to arch specific companion device for ia64
- move ACPI PCI host controller driver to pci_root.c
- drop generic domain assignment for x86 and ia64 as I am not
  able to run all necessary test variants
- drop patch which cleaned legacy IRQ assignment since it belongs to
  Mathew's series:
  https://patchwork.ozlabs.org/patch/557504/
- extend MCFG quirk code
- rebase against 4.4

v1 -> v2
- move non-arch specific piece of code to dirver/acpi/ directory
- fix IO resource handling
- introduce PCI config accessors quirks matching
- moved ACPI_COMPANION_SET to generic code

v1 - https://lkml.org/lkml/2015/10/27/504
v2 - https://lkml.org/lkml/2015/12/16/246
v3 - http://lkml.iu.edu/hypermail/linux/kernel/1601.1/04308.html
v4 - https://lkml.org/lkml/2016/2/4/646
v5 - https://lkml.org/lkml/2016/2/16/426
v6 - https://lkml.org/lkml/2016/4/15/594

Jayachandran C (2):
  PCI: ecam: move ecam.h to linux/include/pci-ecam.h
  PCI: ecam: Add parent device field to pci_config_window

Tomasz Nowicki (7):
  pci: Add new function to unmap IO resources.
  acpi, pci: Support IO resources when parsing PCI host bridge
    resources.
  pci, acpi: add acpi hook to assign domain number.
  arm64, pci, acpi: ACPI support for legacy IRQs parsing and
    consolidation with DT code.
  acpi: Add generic MCFG table handling
  arm64, pci, acpi: Provide ACPI-specific prerequisites for PCI bus
    enumeration.
  pci, acpi: ARM64 support for ACPI based generic PCI host controller

 arch/arm64/Kconfig                  |   2 +
 arch/arm64/kernel/pci.c             | 143 ++++++++++++++++++++++++++++++++++--
 drivers/acpi/Kconfig                |   3 +
 drivers/acpi/Makefile               |   1 +
 drivers/acpi/pci_mcfg.c             |  94 ++++++++++++++++++++++++
 drivers/acpi/pci_root.c             |  39 ++++++++++
 drivers/pci/ecam.c                  |   6 +-
 drivers/pci/ecam.h                  |  67 -----------------
 drivers/pci/host/pci-host-common.c  |   3 +-
 drivers/pci/host/pci-host-generic.c |   3 +-
 drivers/pci/host/pci-thunder-ecam.c |   3 +-
 drivers/pci/host/pci-thunder-pem.c  |   6 +-
 drivers/pci/pci.c                   |  29 +++++++-
 include/linux/pci-acpi.h            |   2 +
 include/linux/pci-ecam.h            |  67 +++++++++++++++++
 include/linux/pci.h                 |   9 ++-
 16 files changed, 387 insertions(+), 90 deletions(-)
 create mode 100644 drivers/acpi/pci_mcfg.c
 delete mode 100644 drivers/pci/ecam.h
 create mode 100644 include/linux/pci-ecam.h

-- 
1.9.1



From tn at semihalf.com  Mon May 30 08:14:14 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 30 May 2016 17:14:14 +0200
Subject: [PATCH V8 1/9] PCI: ecam: move ecam.h to linux/include/pci-ecam.h
In-Reply-To: <1464621262-26770-1-git-send-email-tn@semihalf.com>
References: <1464621262-26770-1-git-send-email-tn@semihalf.com>
Message-ID: <1464621262-26770-2-git-send-email-tn@semihalf.com>

From: Jayachandran C <jchandra at broadcom.com>

This header will be used from arch/arm64 for ACPI PCI implementation
so it needs to be moved out of drivers/pci.

Update users of the header file to use the new name. No functional
changes.

Signed-off-by: Jayachandran C <jchandra at broadcom.com>
---
 drivers/pci/ecam.c                  |  3 +-
 drivers/pci/ecam.h                  | 67 -------------------------------------
 drivers/pci/host/pci-host-common.c  |  3 +-
 drivers/pci/host/pci-host-generic.c |  3 +-
 drivers/pci/host/pci-thunder-ecam.c |  3 +-
 drivers/pci/host/pci-thunder-pem.c  |  3 +-
 include/linux/pci-ecam.h            | 67 +++++++++++++++++++++++++++++++++++++
 7 files changed, 72 insertions(+), 77 deletions(-)
 delete mode 100644 drivers/pci/ecam.h
 create mode 100644 include/linux/pci-ecam.h

diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
index f9832ad..820e26b 100644
--- a/drivers/pci/ecam.c
+++ b/drivers/pci/ecam.c
@@ -19,10 +19,9 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/pci-ecam.h>
 #include <linux/slab.h>
 
-#include "ecam.h"
-
 /*
  * On 64-bit systems, we do a single ioremap for the whole config space
  * since we have enough virtual address range available.  On 32-bit, we
diff --git a/drivers/pci/ecam.h b/drivers/pci/ecam.h
deleted file mode 100644
index 9878beb..0000000
--- a/drivers/pci/ecam.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2016 Broadcom
- *
- * 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 (the "GPL").
- *
- * 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 version 2 (GPLv2) for more details.
- *
- * You should have received a copy of the GNU General Public License
- * version 2 (GPLv2) along with this source code.
- */
-#ifndef DRIVERS_PCI_ECAM_H
-#define DRIVERS_PCI_ECAM_H
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-/*
- * struct to hold pci ops and bus shift of the config window
- * for a PCI controller.
- */
-struct pci_config_window;
-struct pci_ecam_ops {
-	unsigned int			bus_shift;
-	struct pci_ops			pci_ops;
-	int				(*init)(struct device *,
-						struct pci_config_window *);
-};
-
-/*
- * struct to hold the mappings of a config space window. This
- * is expected to be used as sysdata for PCI controllers that
- * use ECAM.
- */
-struct pci_config_window {
-	struct resource			res;
-	struct resource			busr;
-	void				*priv;
-	struct pci_ecam_ops		*ops;
-	union {
-		void __iomem		*win;	/* 64-bit single mapping */
-		void __iomem		**winp; /* 32-bit per-bus mapping */
-	};
-};
-
-/* create and free pci_config_window */
-struct pci_config_window *pci_ecam_create(struct device *dev,
-		struct resource *cfgres, struct resource *busr,
-		struct pci_ecam_ops *ops);
-void pci_ecam_free(struct pci_config_window *cfg);
-
-/* map_bus when ->sysdata is an instance of pci_config_window */
-void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
-			       int where);
-/* default ECAM ops */
-extern struct pci_ecam_ops pci_generic_ecam_ops;
-
-#ifdef CONFIG_PCI_HOST_GENERIC
-/* for DT-based PCI controllers that support ECAM */
-int pci_host_common_probe(struct platform_device *pdev,
-			  struct pci_ecam_ops *ops);
-#endif
-#endif
diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c
index 8cba7ab..c18b9e3 100644
--- a/drivers/pci/host/pci-host-common.c
+++ b/drivers/pci/host/pci-host-common.c
@@ -20,10 +20,9 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
+#include <linux/pci-ecam.h>
 #include <linux/platform_device.h>
 
-#include "../ecam.h"
-
 static int gen_pci_parse_request_of_pci_ranges(struct device *dev,
 		       struct list_head *resources, struct resource **bus_range)
 {
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c
index 6eaceab..f0ca6de 100644
--- a/drivers/pci/host/pci-host-generic.c
+++ b/drivers/pci/host/pci-host-generic.c
@@ -23,10 +23,9 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
+#include <linux/pci-ecam.h>
 #include <linux/platform_device.h>
 
-#include "../ecam.h"
-
 static struct pci_ecam_ops gen_pci_cfg_cam_bus_ops = {
 	.bus_shift	= 16,
 	.pci_ops	= {
diff --git a/drivers/pci/host/pci-thunder-ecam.c b/drivers/pci/host/pci-thunder-ecam.c
index 540d030..a9fc1c9 100644
--- a/drivers/pci/host/pci-thunder-ecam.c
+++ b/drivers/pci/host/pci-thunder-ecam.c
@@ -11,10 +11,9 @@
 #include <linux/ioport.h>
 #include <linux/of_pci.h>
 #include <linux/of.h>
+#include <linux/pci-ecam.h>
 #include <linux/platform_device.h>
 
-#include "../ecam.h"
-
 static void set_val(u32 v, int where, int size, u32 *val)
 {
 	int shift = (where & 3) * 8;
diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
index 9b8ab94..5020d3d 100644
--- a/drivers/pci/host/pci-thunder-pem.c
+++ b/drivers/pci/host/pci-thunder-pem.c
@@ -18,10 +18,9 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
+#include <linux/pci-ecam.h>
 #include <linux/platform_device.h>
 
-#include "../ecam.h"
-
 #define PEM_CFG_WR 0x28
 #define PEM_CFG_RD 0x30
 
diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
new file mode 100644
index 0000000..9878beb
--- /dev/null
+++ b/include/linux/pci-ecam.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016 Broadcom
+ *
+ * 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 (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+#ifndef DRIVERS_PCI_ECAM_H
+#define DRIVERS_PCI_ECAM_H
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+/*
+ * struct to hold pci ops and bus shift of the config window
+ * for a PCI controller.
+ */
+struct pci_config_window;
+struct pci_ecam_ops {
+	unsigned int			bus_shift;
+	struct pci_ops			pci_ops;
+	int				(*init)(struct device *,
+						struct pci_config_window *);
+};
+
+/*
+ * struct to hold the mappings of a config space window. This
+ * is expected to be used as sysdata for PCI controllers that
+ * use ECAM.
+ */
+struct pci_config_window {
+	struct resource			res;
+	struct resource			busr;
+	void				*priv;
+	struct pci_ecam_ops		*ops;
+	union {
+		void __iomem		*win;	/* 64-bit single mapping */
+		void __iomem		**winp; /* 32-bit per-bus mapping */
+	};
+};
+
+/* create and free pci_config_window */
+struct pci_config_window *pci_ecam_create(struct device *dev,
+		struct resource *cfgres, struct resource *busr,
+		struct pci_ecam_ops *ops);
+void pci_ecam_free(struct pci_config_window *cfg);
+
+/* map_bus when ->sysdata is an instance of pci_config_window */
+void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
+			       int where);
+/* default ECAM ops */
+extern struct pci_ecam_ops pci_generic_ecam_ops;
+
+#ifdef CONFIG_PCI_HOST_GENERIC
+/* for DT-based PCI controllers that support ECAM */
+int pci_host_common_probe(struct platform_device *pdev,
+			  struct pci_ecam_ops *ops);
+#endif
+#endif
-- 
1.9.1



From tn at semihalf.com  Mon May 30 08:14:15 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 30 May 2016 17:14:15 +0200
Subject: [PATCH V8 2/9] PCI: ecam: Add parent device field to pci_config_window
In-Reply-To: <1464621262-26770-1-git-send-email-tn@semihalf.com>
References: <1464621262-26770-1-git-send-email-tn@semihalf.com>
Message-ID: <1464621262-26770-3-git-send-email-tn@semihalf.com>

From: Jayachandran C <jchandra at broadcom.com>

Add a parent device field to struct pci_config_window. The parent
is not saved now, but will be useful to save it in some cases.
Specifically in case of ACPI for ARM64, it can be used to setup
ACPI companion and domain.

Since the parent dev is in struct pci_config_window now, we need
not pass it to he init function as a separate argument.

Signed-off-by: Jayachandran C <jchandra at broadcom.com>
---
 drivers/pci/ecam.c                 | 3 ++-
 drivers/pci/host/pci-thunder-pem.c | 3 ++-
 include/linux/pci-ecam.h           | 4 ++--
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
index 820e26b..66e0d71 100644
--- a/drivers/pci/ecam.c
+++ b/drivers/pci/ecam.c
@@ -51,6 +51,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
 	if (!cfg)
 		return ERR_PTR(-ENOMEM);
 
+	cfg->parent = dev;
 	cfg->ops = ops;
 	cfg->busr.start = busr->start;
 	cfg->busr.end = busr->end;
@@ -94,7 +95,7 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
 	}
 
 	if (ops->init) {
-		err = ops->init(dev, cfg);
+		err = ops->init(cfg);
 		if (err)
 			goto err_exit;
 	}
diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
index 5020d3d..91f6fc6 100644
--- a/drivers/pci/host/pci-thunder-pem.c
+++ b/drivers/pci/host/pci-thunder-pem.c
@@ -284,8 +284,9 @@ static int thunder_pem_config_write(struct pci_bus *bus, unsigned int devfn,
 	return pci_generic_config_write(bus, devfn, where, size, val);
 }
 
-static int thunder_pem_init(struct device *dev, struct pci_config_window *cfg)
+static int thunder_pem_init(struct pci_config_window *cfg)
 {
+	struct device *dev = cfg->parent;
 	resource_size_t bar4_start;
 	struct resource *res_pem;
 	struct thunder_pem_pci *pem_pci;
diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
index 9878beb..7adad20 100644
--- a/include/linux/pci-ecam.h
+++ b/include/linux/pci-ecam.h
@@ -27,8 +27,7 @@ struct pci_config_window;
 struct pci_ecam_ops {
 	unsigned int			bus_shift;
 	struct pci_ops			pci_ops;
-	int				(*init)(struct device *,
-						struct pci_config_window *);
+	int				(*init)(struct pci_config_window *);
 };
 
 /*
@@ -45,6 +44,7 @@ struct pci_config_window {
 		void __iomem		*win;	/* 64-bit single mapping */
 		void __iomem		**winp; /* 32-bit per-bus mapping */
 	};
+	struct device			*parent;/* ECAM res was from this dev */
 };
 
 /* create and free pci_config_window */
-- 
1.9.1



From tn at semihalf.com  Mon May 30 08:14:16 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 30 May 2016 17:14:16 +0200
Subject: [PATCH V8 3/9] pci: Add new function to unmap IO resources.
In-Reply-To: <1464621262-26770-1-git-send-email-tn@semihalf.com>
References: <1464621262-26770-1-git-send-email-tn@semihalf.com>
Message-ID: <1464621262-26770-4-git-send-email-tn@semihalf.com>

We need to release I/O resources so that the same I/O resources
can be allocated again (pci_remap_iospace), like in PCI hotplug removal
scenario. Therefore this patch implements new pci_unmap_iospace call which
unmaps I/O space as the symmetry to pci_remap_iospace.

Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 drivers/pci/pci.c   | 18 ++++++++++++++++++
 include/linux/pci.h |  1 +
 2 files changed, 19 insertions(+)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index c8b4dbd..eb431b5 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -25,6 +25,7 @@
 #include <linux/device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pci_hotplug.h>
+#include <linux/vmalloc.h>
 #include <asm/setup.h>
 #include <linux/aer.h>
 #include "pci.h"
@@ -3165,6 +3166,23 @@ int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
 #endif
 }
 
+/**
+ *	pci_unmap_iospace - Unmap the memory mapped I/O space
+ *	@res: resource to be unmapped
+ *
+ *	Unmap the CPU virtual address @res from virtual address space.
+ *	Only architectures that have memory mapped IO functions defined
+ *	(and the PCI_IOBASE value defined) should call this function.
+ */
+void pci_unmap_iospace(struct resource *res)
+{
+#if defined(PCI_IOBASE) && defined(CONFIG_MMU)
+	unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start;
+
+	unmap_kernel_range(vaddr, resource_size(res));
+#endif
+}
+
 static void __pci_set_master(struct pci_dev *dev, bool enable)
 {
 	u16 old_cmd, cmd;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index b67e4df..12349de 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1167,6 +1167,7 @@ int pci_register_io_range(phys_addr_t addr, resource_size_t size);
 unsigned long pci_address_to_pio(phys_addr_t addr);
 phys_addr_t pci_pio_to_address(unsigned long pio);
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
+void pci_unmap_iospace(struct resource *res);
 
 static inline pci_bus_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
 {
-- 
1.9.1



From tn at semihalf.com  Mon May 30 08:14:17 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 30 May 2016 17:14:17 +0200
Subject: [PATCH V8 4/9] acpi,
 pci: Support IO resources when parsing PCI host bridge resources.
In-Reply-To: <1464621262-26770-1-git-send-email-tn@semihalf.com>
References: <1464621262-26770-1-git-send-email-tn@semihalf.com>
Message-ID: <1464621262-26770-5-git-send-email-tn@semihalf.com>

Platforms that have memory mapped IO port (such as ARM64) need special
handling for PCI I/O resources. For host bridge's resource probing case
these resources need to be fixed up with pci_register_io_range/pci_remap_iospace etc.

The same I/O resources need to be released after hotplug
removal so that it can be re-added back by the pci_remap_iospace
function during insertion. As a consequence we unmap I/O resources
with pci_unmap_iospace when we release host bridge resources.

Signed-off-by: Jayachandran C <jchandra at broadcom.com>
Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 drivers/acpi/pci_root.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index ae3fe4e..ee3b728 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -720,6 +720,40 @@ next:
 	}
 }
 
+#ifdef PCI_IOBASE
+static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
+{
+	struct resource *res = entry->res;
+	resource_size_t cpu_addr = res->start;
+	resource_size_t pci_addr = cpu_addr - entry->offset;
+	resource_size_t length = resource_size(res);
+	unsigned long port;
+
+	if (pci_register_io_range(cpu_addr, length))
+		goto err;
+
+	port = pci_address_to_pio(cpu_addr);
+	if (port == (unsigned long)-1)
+		goto err;
+
+	res->start = port;
+	res->end = port + length - 1;
+	entry->offset = port - pci_addr;
+
+	if (pci_remap_iospace(res, cpu_addr) < 0)
+		goto err;
+
+	pr_info("Remapped I/O %pa to %pR\n", &cpu_addr, res);
+	return;
+err:
+	res->flags |= IORESOURCE_DISABLED;
+}
+#else
+static void acpi_pci_root_remap_iospace(struct resource_entry *entry)
+{
+}
+#endif
+
 int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
 {
 	int ret;
@@ -740,6 +774,9 @@ int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
 			"no IO and memory resources present in _CRS\n");
 	else {
 		resource_list_for_each_entry_safe(entry, tmp, list) {
+			if (entry->res->flags & IORESOURCE_IO)
+				acpi_pci_root_remap_iospace(entry);
+
 			if (entry->res->flags & IORESOURCE_DISABLED)
 				resource_list_destroy_entry(entry);
 			else
@@ -811,6 +848,8 @@ static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
 
 	resource_list_for_each_entry(entry, &bridge->windows) {
 		res = entry->res;
+		if (res->flags & IORESOURCE_IO)
+			pci_unmap_iospace(res);
 		if (res->parent &&
 		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
 			release_resource(res);
-- 
1.9.1



From tn at semihalf.com  Mon May 30 08:14:21 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 30 May 2016 17:14:21 +0200
Subject: [PATCH V8 8/9] arm64, pci,
 acpi: Provide ACPI-specific prerequisites for PCI bus enumeration.
In-Reply-To: <1464621262-26770-1-git-send-email-tn@semihalf.com>
References: <1464621262-26770-1-git-send-email-tn@semihalf.com>
Message-ID: <1464621262-26770-9-git-send-email-tn@semihalf.com>

ACPI requires to run acpi_pci_{add|remove}_bus while new PCI bus is created.
This allows to do some ACPI-specific additional configuration, like
PCI hotplug slot enumeration. In order to fulfill these requirements,
we implement arch-specific pcibios_{add|remove}_bus calls
and call acpi_pci_{add|remove}_bus from there.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 arch/arm64/kernel/pci.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
index 336deef..3663be1 100644
--- a/arch/arm64/kernel/pci.c
+++ b/arch/arm64/kernel/pci.c
@@ -17,6 +17,7 @@
 #include <linux/mm.h>
 #include <linux/of_pci.h>
 #include <linux/of_platform.h>
+#include <linux/pci-acpi.h>
 #include <linux/slab.h>
 
 /*
@@ -96,4 +97,15 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 	/* TODO: Should be revisited when implementing PCI on ACPI */
 	return NULL;
 }
+
+void pcibios_add_bus(struct pci_bus *bus)
+{
+	acpi_pci_add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+	acpi_pci_remove_bus(bus);
+}
+
 #endif
-- 
1.9.1



From tn at semihalf.com  Mon May 30 08:14:22 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 30 May 2016 17:14:22 +0200
Subject: [PATCH V8 9/9] pci,
 acpi: ARM64 support for ACPI based generic PCI host controller
In-Reply-To: <1464621262-26770-1-git-send-email-tn@semihalf.com>
References: <1464621262-26770-1-git-send-email-tn@semihalf.com>
Message-ID: <1464621262-26770-10-git-send-email-tn@semihalf.com>

This patch implements pci_acpi_scan_root call so that ARM64 can start
using ACPI to setup and enumerate PCI buses.

The implementation of pci_acpi_scan_root() looks up config space regions
through MCFG interface. Then ECAM library is doing a new mapping
and attach generic ECAM ops which are used for accessing config space.

On ARM64, ACPI and DT can be enabled together, and in that case
we need to use generic domains. In order to do that we implement
ARM64 specific way of retrieving domain number from pci_config_window
structure.

Since we enable PCI for ACPI we need to implement raw_pci_{read|write}
at the same time. ARM64 provides RAW accessors as long as there is
correlated valid pci_bus structure, but not before.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
Signed-off-by: Jayachandran C <jchandra at broadcom.com>
---
 arch/arm64/Kconfig      |   2 +
 arch/arm64/kernel/pci.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/pci.h     |   5 ++
 3 files changed, 122 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 76747d9..87c48ad 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -3,6 +3,7 @@ config ARM64
 	select ACPI_CCA_REQUIRED if ACPI
 	select ACPI_GENERIC_GSI if ACPI
 	select ACPI_REDUCED_HARDWARE_ONLY if ACPI
+	select ACPI_MCFG if ACPI
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select ARCH_HAS_ELF_RANDOMIZE
@@ -96,6 +97,7 @@ config ARM64
 	select OF_EARLY_FLATTREE
 	select OF_NUMA if NUMA && OF
 	select OF_RESERVED_MEM
+	select PCI_ECAM if ACPI
 	select PERF_USE_VMALLOC
 	select POWER_RESET
 	select POWER_SUPPLY
diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
index 3663be1..39f2a40 100644
--- a/arch/arm64/kernel/pci.c
+++ b/arch/arm64/kernel/pci.c
@@ -17,7 +17,9 @@
 #include <linux/mm.h>
 #include <linux/of_pci.h>
 #include <linux/of_platform.h>
+#include <linux/pci.h>
 #include <linux/pci-acpi.h>
+#include <linux/pci-ecam.h>
 #include <linux/slab.h>
 
 /*
@@ -71,13 +73,21 @@ int pcibios_alloc_irq(struct pci_dev *dev)
 int raw_pci_read(unsigned int domain, unsigned int bus,
 		  unsigned int devfn, int reg, int len, u32 *val)
 {
-	return -ENXIO;
+	struct pci_bus *b = pci_find_bus(domain, bus);
+
+	if (!b)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	return b->ops->read(b, devfn, reg, len, val);
 }
 
 int raw_pci_write(unsigned int domain, unsigned int bus,
 		unsigned int devfn, int reg, int len, u32 val)
 {
-	return -ENXIO;
+	struct pci_bus *b = pci_find_bus(domain, bus);
+
+	if (!b)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	return b->ops->write(b, devfn, reg, len, val);
 }
 
 #ifdef CONFIG_NUMA
@@ -91,11 +101,111 @@ EXPORT_SYMBOL(pcibus_to_node);
 #endif
 
 #ifdef CONFIG_ACPI
-/* Root bridge scanning */
+
+struct acpi_pci_generic_root_info {
+	struct acpi_pci_root_info	common;
+	struct pci_config_window	*cfg;	/* config space mapping */
+};
+
+int acpi_pci_bus_domain_nr(struct pci_bus *bus)
+{
+	struct pci_config_window *cfg = bus->sysdata;
+	struct acpi_device *adev = to_acpi_device(cfg->parent);
+	struct acpi_pci_root *root = acpi_driver_data(adev);
+
+	return root->segment;
+}
+
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	if (!acpi_disabled) {
+		struct pci_config_window *cfg = bridge->bus->sysdata;
+		struct acpi_device *adev = to_acpi_device(cfg->parent);
+		ACPI_COMPANION_SET(&bridge->dev, adev);
+	}
+
+	return 0;
+}
+
+/*
+ * Lookup the bus range for the domain in MCFG, and set up config space
+ * mapping.
+ */
+static int pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root,
+				       struct acpi_pci_generic_root_info *ri)
+{
+	struct resource *bus_res = &root->secondary;
+	u16 seg = root->segment;
+	struct pci_config_window *cfg;
+	struct resource cfgres;
+	unsigned int bsz;
+	int err;
+
+	err = pci_mcfg_lookup(root);
+	if (err) {
+		pr_err("%04x:%pR MCFG region not found\n", seg, bus_res);
+		return err;
+	}
+
+	bsz = 1 << pci_generic_ecam_ops.bus_shift;
+	cfgres.start = root->mcfg_addr + bus_res->start * bsz;
+	cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
+	cfgres.flags = IORESOURCE_MEM;
+	cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
+			      &pci_generic_ecam_ops);
+	if (IS_ERR(cfg)) {
+		pr_err("%04x:%pR error %ld mapping CAM\n", seg, bus_res,
+		       PTR_ERR(cfg));
+		return PTR_ERR(cfg);
+	}
+
+	ri->cfg = cfg;
+	return 0;
+}
+
+/* release_info: free resrouces allocated by init_info */
+static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci)
+{
+	struct acpi_pci_generic_root_info *ri;
+
+	ri = container_of(ci, struct acpi_pci_generic_root_info, common);
+	pci_ecam_free(ri->cfg);
+	kfree(ri);
+}
+
+static struct acpi_pci_root_ops acpi_pci_root_ops = {
+	.release_info = pci_acpi_generic_release_info,
+};
+
+/* Interface called from ACPI code to setup PCI host controller */
 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 {
-	/* TODO: Should be revisited when implementing PCI on ACPI */
-	return NULL;
+	int node = acpi_get_node(root->device->handle);
+	struct acpi_pci_generic_root_info *ri;
+	struct pci_bus *bus, *child;
+	int err;
+
+	ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node);
+	if (!ri)
+		return NULL;
+
+	err = pci_acpi_setup_ecam_mapping(root, ri);
+	if (err)
+		return NULL;
+
+	acpi_pci_root_ops.pci_ops = &ri->cfg->ops->pci_ops;
+	bus = acpi_pci_root_create(root, &acpi_pci_root_ops, &ri->common,
+				   ri->cfg);
+	if (!bus)
+		return NULL;
+
+	pci_bus_size_bridges(bus);
+	pci_bus_assign_resources(bus);
+
+	list_for_each_entry(child, &bus->children, node)
+		pcie_bus_configure_settings(child);
+
+	return bus;
 }
 
 void pcibios_add_bus(struct pci_bus *bus)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9661c85..f66d188 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1390,7 +1390,12 @@ static inline int pci_domain_nr(struct pci_bus *bus)
 {
 	return bus->domain_nr;
 }
+/* Arch specific ACPI hook to set-up domain number */
+#ifdef CONFIG_ACPI
+int acpi_pci_bus_domain_nr(struct pci_bus *bus);
+#else
 static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus) { return -1; }
+#endif
 void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
 #else
 static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
-- 
1.9.1



From tn at semihalf.com  Mon May 30 08:14:18 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 30 May 2016 17:14:18 +0200
Subject: [PATCH V8 5/9] pci, acpi: add acpi hook to assign domain number.
In-Reply-To: <1464621262-26770-1-git-send-email-tn@semihalf.com>
References: <1464621262-26770-1-git-send-email-tn@semihalf.com>
Message-ID: <1464621262-26770-6-git-send-email-tn@semihalf.com>

PCI core code provides a config option (CONFIG_PCI_DOMAINS_GENERIC)
that allows assigning the PCI bus domain number generically by
relying on device tree bindings, and falling back to a simple counter
when the respective DT properties (ie "linux,pci-domain") are not
specified in the host bridge device tree node.

In a similar way, when a system is booted through ACPI, architectures
that are selecting CONFIG_PCI_DOMAINS_GENERIC (ie ARM64) require kernel
hooks to retrieve the domain number so that the PCI bus domain number
set-up can be handled seamlessly with DT and ACPI in generic core code
when CONFIG_PCI_DOMAINS_GENERIC is selected.

Since currently it is not possible to retrieve a pointer to the PCI
host bridge ACPI device backing the host bridge from core PCI code
(which would allow retrieving the domain number in an arch agnostic
way through the ACPI _SEG method), an arch specific ACPI hook has to
be declared and implemented by all arches that rely on
CONFIG_PCI_DOMAINS_GENERIC to retrieve the domain number and set it
up in core PCI code.

For the aforementioned reasons, this patch introduces a dummy
acpi_pci_bus_domain_nr() hook in preparation for per-arch implementation
of the same to retrieve the domain number on a per-arch basis when
the system boots through ACPI.

For the sake of code clarity the current code implementing generic
domain number assignment (ie pci_bus_assign_domain_nr(), selected by
CONFIG_PCI_DOMAINS_GENERIC) is reshuffled so that the code implementing
the DT domain assignment function is stubbed out into a corresponding
helper, so that DT and ACPI functions are clearly separated in
preparation for arches acpi_pci_bus_domain_nr() implementations.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
---
 drivers/pci/pci.c   | 11 +++++++++--
 include/linux/pci.h |  1 +
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index eb431b5..2b52178 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -7,6 +7,7 @@
  *	Copyright 1997 -- 2000 Martin Mares <mj at ucw.cz>
  */
 
+#include <linux/acpi.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -4941,7 +4942,7 @@ int pci_get_new_domain_nr(void)
 }
 
 #ifdef CONFIG_PCI_DOMAINS_GENERIC
-void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+static int of_pci_bus_domain_nr(struct device *parent)
 {
 	static int use_dt_domains = -1;
 	int domain = -1;
@@ -4985,7 +4986,13 @@ void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
 		domain = -1;
 	}
 
-	bus->domain_nr = domain;
+	return domain;
+}
+
+void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
+{
+	bus->domain_nr = acpi_disabled ? of_pci_bus_domain_nr(parent) :
+					 acpi_pci_bus_domain_nr(bus);
 }
 #endif
 #endif
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 12349de..bba4053 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1390,6 +1390,7 @@ static inline int pci_domain_nr(struct pci_bus *bus)
 {
 	return bus->domain_nr;
 }
+static inline int acpi_pci_bus_domain_nr(struct pci_bus *bus) { return -1; }
 void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent);
 #else
 static inline void pci_bus_assign_domain_nr(struct pci_bus *bus,
-- 
1.9.1



From tn at semihalf.com  Mon May 30 08:14:19 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 30 May 2016 17:14:19 +0200
Subject: [PATCH V8 6/9] arm64, pci,
 acpi: ACPI support for legacy IRQs parsing and consolidation with DT
 code.
In-Reply-To: <1464621262-26770-1-git-send-email-tn@semihalf.com>
References: <1464621262-26770-1-git-send-email-tn@semihalf.com>
Message-ID: <1464621262-26770-7-git-send-email-tn@semihalf.com>

To enable PCI legacy IRQs on platforms booting with ACPI, arch code
should include ACPI specific callbacks that parse and set-up the
device IRQ number, equivalent to the DT boot path. Owing to the current
ACPI core scan handlers implementation, ACPI PCI legacy IRQs bindings
cannot be parsed at device add time, since that would trigger ACPI scan
handlers ordering issues depending on how the ACPI tables are defined.

To solve this problem and consolidate FW PCI legacy IRQs parsing in
one single pcibios callback (pending final removal), this patch moves
DT PCI IRQ parsing to the pcibios_alloc_irq() callback (called by
PCI core code at device probe time) and adds ACPI PCI legacy IRQs
parsing to the same callback too, so that FW PCI legacy IRQs parsing
is confined in one single arch callback that can be easily removed
when code parsing PCI legacy IRQs is consolidated and moved to core
PCI code.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
Suggested-by: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
---
 arch/arm64/kernel/pci.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
index 3c4e308..336deef 100644
--- a/arch/arm64/kernel/pci.c
+++ b/arch/arm64/kernel/pci.c
@@ -50,11 +50,16 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 }
 
 /*
- * Try to assign the IRQ number from DT when adding a new device
+ * Try to assign the IRQ number when probing a new device
  */
-int pcibios_add_device(struct pci_dev *dev)
+int pcibios_alloc_irq(struct pci_dev *dev)
 {
-	dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
+	if (acpi_disabled)
+		dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
+#ifdef CONFIG_ACPI
+	else
+		return acpi_pci_irq_enable(dev);
+#endif
 
 	return 0;
 }
-- 
1.9.1



From tn at semihalf.com  Mon May 30 08:14:20 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Mon, 30 May 2016 17:14:20 +0200
Subject: [PATCH V8 7/9] acpi: Add generic MCFG table handling
In-Reply-To: <1464621262-26770-1-git-send-email-tn@semihalf.com>
References: <1464621262-26770-1-git-send-email-tn@semihalf.com>
Message-ID: <1464621262-26770-8-git-send-email-tn@semihalf.com>

In order to handle PCI config space regions properly in ACPI, new MCFG
interface is defined which does sanity checks on MCFG table and keeps its
root pointer. The user is able to lookup MCFG regions based on
host bridge root structure and domain:bus_start:bus_end touple.
Use pci_mmcfg_late_init old prototype to avoid another function name.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
Signed-off-by: Jayachandran C <jchandra at broadcom.com>
---
 drivers/acpi/Kconfig     |  3 ++
 drivers/acpi/Makefile    |  1 +
 drivers/acpi/pci_mcfg.c  | 94 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/pci-acpi.h |  2 ++
 include/linux/pci.h      |  2 +-
 5 files changed, 101 insertions(+), 1 deletion(-)
 create mode 100644 drivers/acpi/pci_mcfg.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index b7e2e77..f98c328 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -217,6 +217,9 @@ config ACPI_PROCESSOR_IDLE
 	bool
 	select CPU_IDLE
 
+config ACPI_MCFG
+	bool
+
 config ACPI_CPPC_LIB
 	bool
 	depends on ACPI_PROCESSOR
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 251ce85..632e81f 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -40,6 +40,7 @@ acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o
 acpi-y				+= ec.o
 acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
 acpi-y				+= pci_root.o pci_link.o pci_irq.o
+obj-$(CONFIG_ACPI_MCFG)		+= pci_mcfg.o
 acpi-y				+= acpi_lpss.o acpi_apd.o
 acpi-y				+= acpi_platform.o
 acpi-y				+= acpi_pnp.o
diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
new file mode 100644
index 0000000..1847f74
--- /dev/null
+++ b/drivers/acpi/pci_mcfg.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *	Author: Jayachandran C <jchandra at broadcom.com>
+ * Copyright (C) 2016 Semihalf
+ * 	Author: Tomasz Nowicki <tn at semihalf.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+
+#define pr_fmt(fmt) "ACPI: " fmt
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pci-acpi.h>
+
+/* Root pointer to the mapped MCFG table */
+static struct acpi_table_mcfg *mcfg_table;
+static int mcfg_entries;
+
+int pci_mcfg_lookup(struct acpi_pci_root *root)
+{
+	struct acpi_mcfg_allocation *mptr, *entry = NULL;
+	struct resource *bus_res = &root->secondary;
+	int i;
+
+	if (mcfg_table) {
+		mptr = (struct acpi_mcfg_allocation *) &mcfg_table[1];
+		for (i = 0; i < mcfg_entries && !entry; i++, mptr++)
+			if (mptr->pci_segment == root->segment &&
+			    mptr->start_bus_number == bus_res->start)
+				entry = mptr;
+	}
+
+	/* not found, use _CBA if available, else error */
+	if (!entry) {
+		if (root->mcfg_addr)
+			return root->mcfg_addr;
+		pr_err("%04x:%pR MCFG lookup failed\n", root->segment, bus_res);
+		return -ENOENT;
+	} else if (root->mcfg_addr && entry->address != root->mcfg_addr) {
+		pr_warn("%04x:%pR CBA %pa != MCFG %lx, using CBA\n",
+			root->segment, bus_res, &root->mcfg_addr,
+			(unsigned long)entry->address);
+		return 0;
+	}
+
+	/* found matching entry, bus range check */
+	if (entry->end_bus_number != bus_res->end) {
+		resource_size_t bus_end = min_t(resource_size_t,
+					entry->end_bus_number, bus_res->end);
+		pr_warn("%04x:%pR bus end mismatch, using %02lx\n",
+			root->segment, bus_res, (unsigned long)bus_end);
+		bus_res->end = bus_end;
+	}
+
+	if (!root->mcfg_addr)
+		root->mcfg_addr = entry->address;
+	return 0;
+}
+
+static __init int pci_mcfg_parse(struct acpi_table_header *header)
+{
+	if (header->length < sizeof(struct acpi_table_mcfg))
+		return -EINVAL;
+
+	mcfg_entries = (header->length - sizeof(struct acpi_table_mcfg)) /
+					sizeof(struct acpi_mcfg_allocation);
+	if (mcfg_entries == 0) {
+		pr_err("MCFG has no entries\n");
+		return -EINVAL;
+	}
+
+	mcfg_table = (struct acpi_table_mcfg *)header;
+	pr_info("MCFG table detected, %d entries\n", mcfg_entries);
+	return 0;
+}
+
+/* Interface called by ACPI - parse and save MCFG table */
+void __init pci_mmcfg_late_init(void)
+{
+	int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse);
+	if (err)
+		pr_err("Failed to parse MCFG (%d)\n", err);
+}
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 89ab057..e0e6dfc 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -24,6 +24,8 @@ static inline acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
 }
 extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
 
+extern int pci_mcfg_lookup(struct acpi_pci_root *root);
+
 static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
 {
 	struct pci_bus *pbus = pdev->bus;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index bba4053..9661c85 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1724,7 +1724,7 @@ void pcibios_free_irq(struct pci_dev *dev);
 extern struct dev_pm_ops pcibios_pm_ops;
 #endif
 
-#ifdef CONFIG_PCI_MMCONFIG
+#if defined(CONFIG_PCI_MMCONFIG) || defined(CONFIG_ACPI_MCFG)
 void __init pci_mmcfg_early_init(void);
 void __init pci_mmcfg_late_init(void);
 #else
-- 
1.9.1



From andrew at lunn.ch  Mon May 30 08:24:26 2016
From: andrew at lunn.ch (Andrew Lunn)
Date: Mon, 30 May 2016 17:24:26 +0200
Subject: [PATCH 3/7] binding: mdio-mux: Add DT binding doc for Broadcom
 MDIO bus mutiplexer
In-Reply-To: <1464592251-2688-4-git-send-email-pramod.kumar@broadcom.com>
References: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
 <1464592251-2688-4-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <20160530152426.GM6027@lunn.ch>

On Mon, May 30, 2016 at 12:40:47PM +0530, Pramod Kumar wrote:
> Add DT binding doc for Broadcom MDIO bus mutiplexer driver.
> 
> Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
> ---
>  .../bindings/net/brcm,mdio-mux-iproc.txt           | 64 ++++++++++++++++++++++
>  1 file changed, 64 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
> 
> diff --git a/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
> new file mode 100644
> index 0000000..dd74ee0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
> @@ -0,0 +1,64 @@
> +Properties for an MDIO bus mutiplexer found in Broadcom iProc based SoCs.
> +
> +This MDIO bus multiplexer defines buses that could be internal as well as
> +external to SoCs and could accept MDIO transaction compatible to C-22 or
> +C-45 Clause. When Child bus is selected, one need to select these two
> +properties as well to generate desired MDIO trascation on appropriate bus.
> +
> +Required properties in addition to the generic multiplexer properties:
> +
> +MDIO multiplexer node:
> +- complatible: brcm,mdio-mux-iproc.
> +
> +Child bus node:
> +-brcm,is-c45: Boolean property indicating PHYs attached to this bus supports
> +	      C-45 mdio transaction.

This is-c45 seems to be at the wrong level. As far as i know, you can
mix C22 and C45 devices on a bus. It is a property of the individual
MDIO device if it uses C45 or not.

I would expect your MDIO device PHY drivers to logically OR
MII_ADDR_C45 into the address when doing an MDIO read/write using C45.

	     Andrew


From s.nawrocki at samsung.com  Mon May 30 08:27:14 2016
From: s.nawrocki at samsung.com (Sylwester Nawrocki)
Date: Mon, 30 May 2016 17:27:14 +0200
Subject: [PATCH v5 00/22] ARM: dts: exynos: Add initial support for Odroid
 XU
In-Reply-To: <1464429273-23457-1-git-send-email-krzk@kernel.org>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
Message-ID: <574C5BD2.60008@samsung.com>

On 05/28/2016 11:54 AM, Krzysztof Kozlowski wrote:
>
> The clock changes can go to clock tree. ARM changes to samsung-soc tree.
> Please provide me a tag with include/dt-bindings/clock commits so I can
> merge it.

I applied the clock tree patches and here is the tag for the three
include/dt-bindings patches:

The following changes since commit 1a695a905c18548062509178b98bc91e67510864:

  Linux 4.7-rc1 (2016-05-29 09:29:24 -0700)

are available in the git repository at:

  git://linuxtv.org/snawrocki/samsung.git tags/clk-v4.8-exynos5410-dt

for you to fetch changes up to ed1e1505db0c116affdfab01e650c44a9c459c65:

  dt-bindings: clock: Add I2C, HSI2C and RTC clock IDs to Exynos5410
(2016-05-30 16:00:11 +0200)

----------------------------------------------------------------
Adition of missing clock index definitions for exynos5410 SoC
PWM, USB, I2C, and RTC device related clocks.

----------------------------------------------------------------
Krzysztof Kozlowski (3):
      dt-bindings: clock: Add license and reformat Exynos5410 clock IDs
      dt-bindings: clock: Add PWM and USB clock IDs to Exynos5410
      dt-bindings: clock: Add I2C, HSI2C and RTC clock IDs to Exynos5410

 include/dt-bindings/clock/exynos5410.h | 73
+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 51 insertions(+), 22 deletions(-)


--
Thanks,
Sylwester


From hramrach at gmail.com  Mon May 30 08:28:10 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: Mon, 30 May 2016 17:28:10 +0200
Subject: [PATCH 5/5] RFC spi: sun4i: add DMA support
In-Reply-To: <20160530150343.GL29837@sirena.org.uk>
References: <cover.1464130597.git.hramrach@gmail.com>
 <ba0d6eb37cc4b0d2c46acbf9fcd7d644b3545ce8.1464130597.git.hramrach@gmail.com>
 <20160530112610.GJ29837@sirena.org.uk>
 <CAMuHMdVThvtqgFnyqoqypwwf1d81uu9NBo6-heTZBcvBxRevNw@mail.gmail.com>
 <20160530150343.GL29837@sirena.org.uk>
Message-ID: <CAOMqctQb-YYprA7H5qCcYo2hxXiUhjW2z3JbZ3-FhbfcjFzBpw@mail.gmail.com>

Hello,

On 30 May 2016 at 17:03, Mark Brown <broonie at kernel.org> wrote:
> On Mon, May 30, 2016 at 02:11:51PM +0200, Geert Uytterhoeven wrote:
>> On Mon, May 30, 2016 at 1:26 PM, Mark Brown <broonie at kernel.org> wrote:
>> > On Thu, May 26, 2016 at 07:25:25PM -0000, Michal Suchanek wrote:
>> >>  - fallback to previous behaviour when DMA initialization fails
>> >>
>> >>    + this has the problem that when the driver happens to load before the dma
>> >>      driver it will not use dma - can be addressed with a module parameter
>
>> > No, you should pay attention to the error you are getting and let probe
>> > deferral happen if that's the error you get.
>
>> Unfortunately DMA is an optional feature.
>
>> There's no way to distinguish between -EPROBE_DEFER due to the SPI master
>> driver being probed before the DMA engine driver, and -EPROBE_DEFER due to
>> support for the DMA engine not having been compiled in.
>
> I really don't think it's worth caring too much about cases where the
> DMA driver hasn't been compiled in, it's not like SPI is the only thing
> that's going to be using it.  I really think it's better to defer the
> problem - not getting DMA (or worse, only getting DMA on some boots) is
> not great and if people are optimising on that level my feeling is that
> they're probably going to be OK with customizing DT to match.  Ideally
> we would have something a bit nicer than deferred probe but right now
> this seems the more helpful option.

It's what the driver did to start with and it was requested to fall
back to non-DMA in the case DMA is not available.

We get to the much discussed problem that it's never possible to tell
if a driver is available or not.

It's possible to add a parameter like require_dma which could be used
to load the driver without dma if unset. If it was set by default then
driver ordering is not important so long as dma driver is loaded
eventually. Also an informative print that such parameter exists when
probing the driver is deferred would be helpful. It would probably
create quite a bit of log spam, however. The driver can be deferred
several times during boot.

Thanks

Michal


From matthias.bgg at gmail.com  Mon May 30 08:31:11 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Mon, 30 May 2016 17:31:11 +0200
Subject: [PATCH v8 2/3] CMDQ: Mediatek CMDQ driver
In-Reply-To: <1464578397-29743-3-git-send-email-hs.liao@mediatek.com>
References: <1464578397-29743-1-git-send-email-hs.liao@mediatek.com>
 <1464578397-29743-3-git-send-email-hs.liao@mediatek.com>
Message-ID: <574C5CBF.7060002@gmail.com>



On 30/05/16 05:19, HS Liao wrote:
> This patch is first version of Mediatek Command Queue(CMDQ) driver. The
> CMDQ is used to help read/write registers with critical time limitation,
> such as updating display configuration during the vblank. It controls
> Global Command Engine (GCE) hardware to achieve this requirement.
> Currently, CMDQ only supports display related hardwares, but we expect
> it can be extended to other hardwares for future requirements.
>
> Signed-off-by: HS Liao <hs.liao at mediatek.com>
> Signed-off-by: CK Hu <ck.hu at mediatek.com>
> ---
>   drivers/soc/mediatek/Kconfig    |  10 +
>   drivers/soc/mediatek/Makefile   |   1 +
>   drivers/soc/mediatek/mtk-cmdq.c | 943 ++++++++++++++++++++++++++++++++++++++++
>   include/soc/mediatek/cmdq.h     | 197 +++++++++
>   4 files changed, 1151 insertions(+)
>   create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
>   create mode 100644 include/soc/mediatek/cmdq.h
>
> diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
> index 0a4ea80..c4ad75c 100644
> --- a/drivers/soc/mediatek/Kconfig
> +++ b/drivers/soc/mediatek/Kconfig
> @@ -1,6 +1,16 @@
>   #
>   # MediaTek SoC drivers
>   #
> +config MTK_CMDQ
> +	bool "MediaTek CMDQ Support"
> +	depends on ARCH_MEDIATEK || COMPILE_TEST
> +	select MTK_INFRACFG
> +	help
> +	  Say yes here to add support for the MediaTek Command Queue (CMDQ)
> +	  driver. The CMDQ is used to help read/write registers with critical
> +	  time limitation, such as updating display configuration during the
> +	  vblank.
> +
>   config MTK_INFRACFG
>   	bool "MediaTek INFRACFG Support"
>   	depends on ARCH_MEDIATEK || COMPILE_TEST
> diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
> index 12998b0..f7397ef 100644
> --- a/drivers/soc/mediatek/Makefile
> +++ b/drivers/soc/mediatek/Makefile
> @@ -1,3 +1,4 @@
> +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq.o
>   obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
>   obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
>   obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
> diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
> new file mode 100644
> index 0000000..e9d6e1c
> --- /dev/null
> +++ b/drivers/soc/mediatek/mtk-cmdq.c
> @@ -0,0 +1,943 @@
> +/*
> + * Copyright (c) 2015 MediaTek Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/completion.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/errno.h>
> +#include <linux/interrupt.h>
> +#include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +#include <linux/kthread.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/suspend.h>
> +#include <linux/workqueue.h>
> +#include <soc/mediatek/cmdq.h>
> +
> +#define CMDQ_INITIAL_CMD_BLOCK_SIZE	PAGE_SIZE
> +#define CMDQ_INST_SIZE			8 /* instruction is 64-bit */
> +#define CMDQ_TIMEOUT_MS			1000
> +#define CMDQ_IRQ_MASK			0xffff
> +#define CMDQ_DRIVER_DEVICE_NAME		"mtk_cmdq"
> +#define CMDQ_CLK_NAME			"gce"

We can put the names in directly to un-bloat the defines.

> +
> +#define CMDQ_CURR_IRQ_STATUS		0x010
> +#define CMDQ_CURR_LOADED_THR		0x018
> +#define CMDQ_THR_SLOT_CYCLES		0x030
> +
> +#define CMDQ_THR_BASE			0x100
> +#define CMDQ_THR_SHIFT			0x080

Wouldn't be CMDQ_THR_SIZE more accurate?

> +#define CMDQ_THR_WARM_RESET		0x00
> +#define CMDQ_THR_ENABLE_TASK		0x04
> +#define CMDQ_THR_SUSPEND_TASK		0x08
> +#define CMDQ_THR_CURR_STATUS		0x0c
> +#define CMDQ_THR_IRQ_STATUS		0x10
> +#define CMDQ_THR_IRQ_ENABLE		0x14
> +#define CMDQ_THR_CURR_ADDR		0x20
> +#define CMDQ_THR_END_ADDR		0x24
> +#define CMDQ_THR_CFG			0x40
> +
> +#define CMDQ_THR_ENABLED		0x1
> +#define CMDQ_THR_DISABLED		0x0
> +#define CMDQ_THR_SUSPEND		0x1
> +#define CMDQ_THR_RESUME			0x0
> +#define CMDQ_THR_STATUS_SUSPENDED	BIT(1)
> +#define CMDQ_THR_DO_WARM_RESET		BIT(0)
> +#define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
> +#define CMDQ_THR_PRIORITY		3
> +#define CMDQ_THR_IRQ_DONE		0x1
> +#define CMDQ_THR_IRQ_ERROR		0x12
> +#define CMDQ_THR_IRQ_EN			0x13 /* done + error */

#define CMDQ_THR_IRQ_EN (CMDQ_THR_IRQ_ERROR | CMDQ_THR_IRQ_DONE)

> +#define CMDQ_THR_IRQ_MASK		0x13

never used.

> +#define CMDQ_THR_EXECUTING		BIT(31)
> +
> +#define CMDQ_ARG_A_WRITE_MASK		0xffff
> +#define CMDQ_SUBSYS_MASK		0x1f
> +#define CMDQ_OP_CODE_MASK		0xff000000
> +
> +#define CMDQ_OP_CODE_SHIFT		24

Couldn't we connect the mask with the shift, or aren't they related?

#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT)

> +#define CMDQ_SUBSYS_SHIFT		16
> +
> +#define CMDQ_WRITE_ENABLE_MASK		BIT(0)
> +#define CMDQ_JUMP_BY_OFFSET		0x10000000
> +#define CMDQ_JUMP_BY_PA			0x10000001
> +#define CMDQ_JUMP_PASS			CMDQ_INST_SIZE
> +#define CMDQ_WFE_UPDATE			BIT(31)
> +#define CMDQ_WFE_WAIT			BIT(15)
> +#define CMDQ_WFE_WAIT_VALUE		0x1
> +#define CMDQ_EOC_IRQ_EN			BIT(0)
> +
> +enum cmdq_thread_index {
> +	CMDQ_THR_DISP_MAIN_IDX,	/* main */
> +	CMDQ_THR_DISP_SUB_IDX,	/* sub */
> +	CMDQ_THR_DISP_MISC_IDX,	/* misc */
> +	CMDQ_THR_MAX_COUNT,	/* max */
> +};
> +
> +/*
> + * CMDQ_CODE_MOVE:
> + *   move value into internal register as mask
> + *   format: op mask
> + * CMDQ_CODE_WRITE:
> + *   write value into target register
> + *   format: op subsys address value
> + * CMDQ_CODE_JUMP:
> + *   jump by offset
> + *   format: op offset
> + * CMDQ_CODE_WFE:
> + *   wait for event and clear
> + *   it is just clear if no wait
> + *   format: [wait]  op event update:1 to_wait:1 wait:1
> + *           [clear] op event update:1 to_wait:0 wait:0
> + * CMDQ_CODE_EOC:
> + *   end of command
> + *   format: op irq_flag
> + */

I think we need more documentation of how this command queue engine is 
working. If not, I think it will be really complicated to understand how 
to use this.

> +enum cmdq_code {
> +	CMDQ_CODE_MOVE = 0x02,
> +	CMDQ_CODE_WRITE = 0x04,
> +	CMDQ_CODE_JUMP = 0x10,
> +	CMDQ_CODE_WFE = 0x20,
> +	CMDQ_CODE_EOC = 0x40,
> +};
> +
> +enum cmdq_task_state {
> +	TASK_STATE_BUSY, /* running on a GCE thread */
> +	TASK_STATE_ERROR,
> +	TASK_STATE_DONE,
> +};
> +
> +struct cmdq_task_cb {
> +	cmdq_async_flush_cb	cb;
> +	void			*data;
> +};
> +
> +struct cmdq_thread {
> +	void __iomem		*base;
> +	struct list_head	task_busy_list;
> +	wait_queue_head_t	wait_task_done;
> +};
> +
> +struct cmdq_task {
> +	struct cmdq		*cmdq;
> +	struct list_head	list_entry;
> +	enum cmdq_task_state	task_state;
> +	void			*va_base;
> +	dma_addr_t		pa_base;
> +	u64			engine_flag;
> +	size_t			command_size;
> +	u32			num_cmd;

num_cmd is directly connected to command_size. I prefer to just keep 
num_cmd and calculate the command_size where necessary.

> +	struct cmdq_thread	*thread;
> +	struct cmdq_task_cb	cb;
> +	struct work_struct	release_work;
> +};
> +
> +struct cmdq {
> +	struct device		*dev;
> +	void __iomem		*base;
> +	u32			irq;
> +	struct workqueue_struct	*task_release_wq;
> +	struct cmdq_thread	thread[CMDQ_THR_MAX_COUNT];
> +	struct mutex		task_mutex;	/* for task */
> +	spinlock_t		exec_lock;	/* for exec */
> +	struct clk		*clock;
> +	bool			suspended;
> +};
> +
> +struct cmdq_subsys {
> +	u32	base;
> +	int	id;
> +};
> +
> +static const struct cmdq_subsys gce_subsys[] = {
> +	{0x1400, 1},
> +	{0x1401, 2},
> +	{0x1402, 3},
> +};
> +
> +static int cmdq_subsys_base_to_id(u32 base)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(gce_subsys); i++)
> +		if (gce_subsys[i].base == base)
> +			return gce_subsys[i].id;
> +	return -EFAULT;
> +}
> +
> +static int cmdq_eng_get_thread(u64 flag)
> +{
> +	if (flag & BIT_ULL(CMDQ_ENG_DISP_DSI0))
> +		return CMDQ_THR_DISP_MAIN_IDX;
> +	else if (flag & BIT_ULL(CMDQ_ENG_DISP_DPI0))
> +		return CMDQ_THR_DISP_SUB_IDX;
> +	else
> +		return CMDQ_THR_DISP_MISC_IDX;
> +}
> +
> +static void cmdq_task_release(struct cmdq_task *task)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +
> +	dma_free_coherent(cmdq->dev, task->command_size, task->va_base,
> +			  task->pa_base);
> +	kfree(task);
> +}
> +
> +static struct cmdq_task *cmdq_task_acquire(struct cmdq_rec *rec,
> +					   struct cmdq_task_cb cb)
> +{
> +	struct cmdq *cmdq = rec->cmdq;
> +	struct device *dev = cmdq->dev;
> +	struct cmdq_task *task;
> +
> +	task = kzalloc(sizeof(*task), GFP_KERNEL);
> +	INIT_LIST_HEAD(&task->list_entry);
> +	task->va_base = dma_alloc_coherent(dev, rec->command_size,
> +					   &task->pa_base, GFP_KERNEL);
> +	if (!task->va_base) {
> +		dev_err(dev, "allocate command buffer failed\n");
> +		kfree(task);
> +		return NULL;
> +	}
> +
> +	task->cmdq = cmdq;
> +	task->command_size = rec->command_size;
> +	task->engine_flag = rec->engine_flag;
> +	task->task_state = TASK_STATE_BUSY;
> +	task->cb = cb;
> +	memcpy(task->va_base, rec->buf, rec->command_size);
> +	task->num_cmd = task->command_size / CMDQ_INST_SIZE;
> +	return task;
> +}
> +
> +static void cmdq_thread_writel(struct cmdq_thread *thread, u32 value,
> +			       u32 offset)
> +{
> +	writel(value, thread->base + offset);
> +}
> +
> +static u32 cmdq_thread_readl(struct cmdq_thread *thread, u32 offset)
> +{
> +	return readl(thread->base + offset);
> +}

We can get rid of cmdq_thread_readl/writel.

> +
> +static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
> +{
> +	u32 status;
> +
> +	cmdq_thread_writel(thread, CMDQ_THR_SUSPEND, CMDQ_THR_SUSPEND_TASK);
> +
> +	/* If already disabled, treat as suspended successful. */
> +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> +	      CMDQ_THR_ENABLED))
> +		return 0;
> +
> +	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_CURR_STATUS,
> +			status, status & CMDQ_THR_STATUS_SUSPENDED, 0, 10)) {
> +		dev_err(cmdq->dev, "suspend GCE thread 0x%x failed\n",
> +			(u32)(thread->base - cmdq->base));
> +		return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
> +static void cmdq_thread_resume(struct cmdq_thread *thread)
> +{
> +	cmdq_thread_writel(thread, CMDQ_THR_RESUME, CMDQ_THR_SUSPEND_TASK);
> +}
> +
> +static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
> +{
> +	u32 warm_reset;
> +
> +	cmdq_thread_writel(thread, CMDQ_THR_DO_WARM_RESET, CMDQ_THR_WARM_RESET);
> +	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET,
> +			warm_reset, !(warm_reset & CMDQ_THR_DO_WARM_RESET),
> +			0, 10)) {
> +		dev_err(cmdq->dev, "reset GCE thread 0x%x failed\n",
> +			(u32)(thread->base - cmdq->base));
> +		return -EFAULT;
> +	}
> +	writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES);
> +	return 0;
> +}
> +
> +static void cmdq_thread_disable(struct cmdq *cmdq, struct cmdq_thread *thread)
> +{
> +	cmdq_thread_reset(cmdq, thread);
> +	cmdq_thread_writel(thread, CMDQ_THR_DISABLED, CMDQ_THR_ENABLE_TASK);
> +}
> +
> +/* notify GCE to re-fetch commands by setting GCE thread PC */
> +static void cmdq_thread_invalidate_fetched_data(struct cmdq_thread *thread)
> +{
> +	cmdq_thread_writel(thread,
> +			   cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR),
> +			   CMDQ_THR_CURR_ADDR);
> +}
> +
> +static void cmdq_task_insert_into_thread(struct cmdq_task *task)
> +{
> +	struct cmdq_thread *thread = task->thread;
> +	struct cmdq_task *prev_task = list_last_entry(
> +			&thread->task_busy_list, typeof(*task), list_entry);
> +	u64 *prev_task_base = prev_task->va_base;
> +
> +	/* let previous task jump to this task */
> +	prev_task_base[prev_task->num_cmd - 1] = (u64)CMDQ_JUMP_BY_PA << 32 |
> +						 task->pa_base;
> +
> +	cmdq_thread_invalidate_fetched_data(thread);
> +}
> +
> +/* we assume tasks in the same display GCE thread are waiting the same event. */
> +static void cmdq_task_remove_wfe(struct cmdq_task *task)
> +{
> +	u32 wfe_option = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
> +	u32 wfe_op = CMDQ_CODE_WFE << CMDQ_OP_CODE_SHIFT;
> +	u32 *base = task->va_base;
> +	u32 num_cmd = task->num_cmd << 1;
> +	int i;
> +
> +	for (i = 0; i < num_cmd; i += 2)
> +		if (base[i] == wfe_option &&
> +		    (base[i + 1] & CMDQ_OP_CODE_MASK) == wfe_op) {
> +			base[i] = CMDQ_JUMP_PASS;
> +			base[i + 1] = CMDQ_JUMP_BY_OFFSET;
> +		}

After using the command buffer as a void pointer a u64 pointer, we now 
reference to it as u32. I would prefer to explain here, how the command 
looks like we are searching for and use a for loop passing task->num_cmd 
instead.

> +}
> +
> +static void cmdq_task_exec(struct cmdq_task *task, struct cmdq_thread *thread)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +	unsigned long flags;
> +	unsigned long curr_pa, end_pa;
> +
> +	WARN_ON(clk_prepare_enable(cmdq->clock) < 0);
> +	spin_lock_irqsave(&cmdq->exec_lock, flags);

cmdq_task_exec is called with cmdq->task_mutex held, so why do we need 
the spin_lock here? Can't we just use one of the two?

> +	task->thread = thread;
> +	task->task_state = TASK_STATE_BUSY;

That was already set in cmdq_task_acquire, why do we need to set it here 
again?

> +	if (list_empty(&thread->task_busy_list)) {
> +		WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
> +
> +		cmdq_thread_writel(thread, task->pa_base, CMDQ_THR_CURR_ADDR);
> +		cmdq_thread_writel(thread, task->pa_base + task->command_size,
> +				   CMDQ_THR_END_ADDR);
> +		cmdq_thread_writel(thread, CMDQ_THR_PRIORITY, CMDQ_THR_CFG);
> +		cmdq_thread_writel(thread, CMDQ_THR_IRQ_EN,
> +				   CMDQ_THR_IRQ_ENABLE);
> +
> +		cmdq_thread_writel(thread, CMDQ_THR_ENABLED,
> +				   CMDQ_THR_ENABLE_TASK);
> +	} else {
> +		WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
> +
> +		/*
> +		 * check boundary condition
> +		 * PC = END - 8, EOC is executed
> +		 * PC = END, all CMDs are executed
> +		 */
> +		curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
> +		end_pa = cmdq_thread_readl(thread, CMDQ_THR_END_ADDR);
> +		if (curr_pa == end_pa - 8 || curr_pa == end_pa) {

8 refers to CMDQ_INST_SIZE, right?

> +			/* set to this task directly */
> +			cmdq_thread_writel(thread, task->pa_base,
> +					   CMDQ_THR_CURR_ADDR);
> +		} else {
> +			cmdq_task_insert_into_thread(task);
> +
> +			if (thread == &cmdq->thread[CMDQ_THR_DISP_MAIN_IDX] ||
> +			    thread == &cmdq->thread[CMDQ_THR_DISP_SUB_IDX])
> +				cmdq_task_remove_wfe(task);

We could do this check using the task->engine_flag, I suppose that's 
easier to undestand then.

> +
> +			smp_mb(); /* modify jump before enable thread */
> +		}
> +
> +		cmdq_thread_writel(thread, task->pa_base + task->command_size,
> +				   CMDQ_THR_END_ADDR);
> +		cmdq_thread_resume(thread);
> +	}
> +	list_move_tail(&task->list_entry, &thread->task_busy_list);
> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +}
> +
> +static void cmdq_handle_error_done(struct cmdq *cmdq,
> +				   struct cmdq_thread *thread, u32 irq_flag)
> +{
> +	struct cmdq_task *task, *tmp, *curr_task = NULL;
> +	u32 curr_pa;
> +	struct cmdq_cb_data cmdq_cb_data;
> +	bool err;
> +
> +	if (irq_flag & CMDQ_THR_IRQ_ERROR)
> +		err = true;
> +	else if (irq_flag & CMDQ_THR_IRQ_DONE)
> +		err = false;
> +	else
> +		return;
> +
> +	curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
> +
> +	list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
> +				 list_entry) {
> +		if (curr_pa >= task->pa_base &&
> +		    curr_pa < (task->pa_base + task->command_size))

What are you checking here? It seems as if you make some implcit 
assumptions about pa_base and the order of execution of commands in the 
thread. Is it save to do so? Does dma_alloc_coherent give any guarantees 
about dma_handle?

> +			curr_task = task;
> +		if (task->cb.cb) {
> +			cmdq_cb_data.err = curr_task ? err : false;
> +			cmdq_cb_data.data = task->cb.data;
> +			task->cb.cb(cmdq_cb_data);
> +		}
> +		task->task_state = (curr_task && err) ? TASK_STATE_ERROR :
> +				TASK_STATE_DONE;
> +		list_del(&task->list_entry);
> +		if (curr_task)
> +			break;
> +	}
> +
> +	wake_up(&thread->wait_task_done);
> +}
> +
> +static void cmdq_thread_irq_handler(struct cmdq *cmdq, int tid)
> +{
> +	struct cmdq_thread *thread = &cmdq->thread[tid];
> +	unsigned long flags = 0L;
> +	u32 irq_flag;
> +
> +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> +
> +	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> +	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
> +
> +	/*
> +	 * Another CPU core could run "release task" right before we acquire
> +	 * the spin lock, and thus reset / disable this GCE thread, so we
> +	 * need to check the enable bit of this GCE thread.
> +	 */
> +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> +	      CMDQ_THR_ENABLED))
> +		irq_flag = 0;

cmdq_handle_error_done just retuns in this case. Programming this way 
just makes things confusing. What about:

if (cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
	      CMDQ_THR_ENABLED)
	cmdq_handle_error_done(cmdq, thread, irq_flag);
else
		irq_flag = 0;

spin_unlock_irqrestore(&cmdq->exec_lock, flags);

> +
> +	cmdq_handle_error_done(cmdq, thread, irq_flag);
> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +}
> +
> +static irqreturn_t cmdq_irq_handler(int irq, void *dev)
> +{
> +	struct cmdq *cmdq = dev;
> +	u32 irq_status;
> +	int i;
> +
> +	irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS);
> +	irq_status &= CMDQ_IRQ_MASK;
> +	irq_status ^= CMDQ_IRQ_MASK;

irq_status can be much bigger then 3, which is the number of threads in 
the system (CMDQ_THR_MAX_COUNT). So why we use this mask here isn't 
clear to me.

> +
> +	if (!irq_status)
> +		return IRQ_NONE;
> +
> +	while (irq_status) {
> +		i = ffs(irq_status) - 1;
> +		irq_status &= ~BIT(i);
> +		cmdq_thread_irq_handler(cmdq, i);
> +	}

Can you explain how the irq status register looks like, that would it 
make much easier to understand what happens here.

> +
> +	return IRQ_HANDLED;	
> +}
> +
> +static int cmdq_task_handle_error_result(struct cmdq_task *task)

We never check the return values, why do we have them?

> +{
> +	struct cmdq *cmdq = task->cmdq;
> +	struct device *dev = cmdq->dev;
> +	struct cmdq_thread *thread = task->thread;
> +	struct cmdq_task *next_task, *prev_task;
> +	u32 irq_flag;
> +
> +	/* suspend GCE thread to ensure consistency */
> +	WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
> +
> +	/* ISR has handled this error task */
> +	if (task->task_state == TASK_STATE_ERROR) {
> +		next_task = list_first_entry_or_null(&thread->task_busy_list,
> +				struct cmdq_task, list_entry);
> +		if (next_task) /* move to next task */
> +			cmdq_thread_writel(thread, next_task->pa_base,
> +					   CMDQ_THR_CURR_ADDR);

We have to do this, as we suppose that the thread did not reach the jump 
instruction we put into it's command queue, right?

> +		cmdq_thread_resume(thread);
> +		return -ECANCELED;
> +	}
> +

if task_state != ERROR and != DONE. This means that the timeout of 
task_release_wq has timed out, right?

> +	/*
> +	 * Save next_task and prev_task in advance
> +	 * since cmdq_handle_error_done will remove list_entry.
> +	 */
> +	next_task = prev_task = NULL;
> +	if (task->list_entry.next != &thread->task_busy_list)
> +		next_task = list_next_entry(task, list_entry);
> +	if (task->list_entry.prev != &thread->task_busy_list)
> +		prev_task = list_prev_entry(task, list_entry);
> +
> +	/*
> +	 * Although IRQ is disabled, GCE continues to execute.
> +	 * It may have pending IRQ before GCE thread is suspended,
> +	 * so check this condition again.
> +	 */

The first thing we did in this function was suspending the thread. Why 
do we need this then?
To be honest this whole functions looks really like a design error. We 
have to sperate the states much clearer so that it is possible to 
understand what is happening in the GCE. Isn't it for example posible to 
have worker queues for timed out tasks and tasks with an error? I'm not 
sure how to do this, actually I'm not sure if I really understood how 
this is supposed to work.

How much do we win, when we patch the thread command queue for every 
task we add, instead of just taking one task after another from the 
task_busy_list?

> +	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> +	cmdq_handle_error_done(cmdq, thread, irq_flag);
> +	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
> +
> +	if (task->task_state == TASK_STATE_DONE) {
> +		cmdq_thread_resume(thread);
> +		return 0;
> +	}
> +
> +	if (task->task_state == TASK_STATE_ERROR) {
> +		dev_err(dev, "task 0x%p error\n", task);
> +		if (next_task) /* move to next task */
> +			cmdq_thread_writel(thread, next_task->pa_base,
> +					   CMDQ_THR_CURR_ADDR);
> +		cmdq_thread_resume(thread);
> +		return -ECANCELED;
> +	}
> +
> +	/* Task is running, so we force to remove it. */
> +	dev_err(dev, "task 0x%p timeout or killed\n", task);
> +	task->task_state = TASK_STATE_ERROR;
> +
> +	if (prev_task) {
> +		u64 *prev_va = prev_task->va_base;
> +		u64 *curr_va = task->va_base;
> +
> +		/* copy JUMP instruction */
> +		prev_va[prev_task->num_cmd - 1] = curr_va[task->num_cmd - 1];
> +
> +		cmdq_thread_invalidate_fetched_data(thread);
> +	} else if (next_task) { /* move to next task */
> +		cmdq_thread_writel(thread, next_task->pa_base,
> +				   CMDQ_THR_CURR_ADDR);
> +	}
> +
> +	list_del(&task->list_entry);
> +	cmdq_thread_resume(thread);
> +
> +	/* call cb here to prevent lock */
> +	if (task->cb.cb) {
> +		struct cmdq_cb_data cmdq_cb_data;
> +
> +		cmdq_cb_data.err = true;
> +		cmdq_cb_data.data = task->cb.data;
> +		task->cb.cb(cmdq_cb_data);
> +	}
> +
> +	return -ECANCELED;
> +}
> +
> +static void cmdq_task_wait_release_work(struct work_struct *work_item)
> +{
> +	struct cmdq_task *task = container_of(work_item, struct cmdq_task,
> +					      release_work);
> +	struct cmdq *cmdq = task->cmdq;
> +	struct cmdq_thread *thread = task->thread;
> +	unsigned long flags;
> +
> +	wait_event_timeout(thread->wait_task_done,
> +			   task->task_state != TASK_STATE_BUSY,
> +			   msecs_to_jiffies(CMDQ_TIMEOUT_MS));
> +
> +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> +	if (task->task_state != TASK_STATE_DONE)
> +		cmdq_task_handle_error_result(task);
> +	if (list_empty(&thread->task_busy_list))
> +		cmdq_thread_disable(cmdq, thread);
> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> +
> +	/* release regardless of success or not */
> +	clk_disable_unprepare(cmdq->clock);
> +	cmdq_task_release(task);
> +}
> +
> +static void cmdq_task_wait_release_schedule(struct cmdq_task *task)
> +{
> +	struct cmdq *cmdq = task->cmdq;
> +
> +	INIT_WORK(&task->release_work, cmdq_task_wait_release_work);
> +	queue_work(cmdq->task_release_wq, &task->release_work);
> +}
> +
> +static int cmdq_rec_realloc_cmd_buffer(struct cmdq_rec *rec, size_t size)
> +{
> +	void *new_buf;
> +
> +	new_buf = krealloc(rec->buf, size, GFP_KERNEL | __GFP_ZERO);
> +	if (!new_buf)
> +		return -ENOMEM;
> +	rec->buf = new_buf;
> +	rec->buf_size = size;
> +	return 0;
> +}
> +
> +struct cmdq_base *cmdq_register_device(struct device *dev)
> +{
> +	struct cmdq_base *cmdq_base;
> +	struct resource res;
> +	int subsys;
> +	u32 base;
> +
> +	if (of_address_to_resource(dev->of_node, 0, &res))
> +		return NULL;
> +	base = (u32)res.start;
> +
> +	subsys = cmdq_subsys_base_to_id(base >> 16);
> +	if (subsys < 0)
> +		return NULL;
> +
> +	cmdq_base = devm_kmalloc(dev, sizeof(*cmdq_base), GFP_KERNEL);
> +	if (!cmdq_base)
> +		return NULL;
> +	cmdq_base->subsys = subsys;
> +	cmdq_base->base = base;
> +
> +	return cmdq_base;
> +}
> +EXPORT_SYMBOL(cmdq_register_device);
> +
> +int cmdq_rec_create(struct device *dev, u64 engine_flag,
> +		    struct cmdq_rec **rec_ptr)
> +{
> +	struct cmdq_rec *rec;
> +	int err;
> +
> +	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
> +	if (!rec)
> +		return -ENOMEM;
> +	rec->cmdq = dev_get_drvdata(dev);
> +	rec->engine_flag = engine_flag;
> +	err = cmdq_rec_realloc_cmd_buffer(rec, CMDQ_INITIAL_CMD_BLOCK_SIZE);

Just pass PAGE_SIZE here, no need for CMDQ_INITIAL_CMD_BLOCK_SIZE.

> +	if (err < 0) {
> +		kfree(rec);
> +		return err;
> +	}
> +	*rec_ptr = rec;
> +	return 0;
> +}
> +EXPORT_SYMBOL(cmdq_rec_create);
> +
> +static int cmdq_rec_append_command(struct cmdq_rec *rec, enum cmdq_code code,
> +				   u32 arg_a, u32 arg_b)
> +{
> +	u64 *cmd_ptr;
> +	int err;
> +
> +	if (WARN_ON(rec->finalized))
> +		return -EBUSY;
> +	if (code < CMDQ_CODE_MOVE || code > CMDQ_CODE_EOC)
> +		return -EINVAL;

cmdq_rec_append_command is just called from inside this driver and code 
is a enum. We can expect it to be correct, no need for this check.

> +	if (unlikely(rec->command_size + CMDQ_INST_SIZE > rec->buf_size)) {

command_size is the offset into the buffer to which a new command is 
written, so this name is highly confusing. I wonder if this would be 
easier to understand if we redefine command_size to something like the 
number of commands and divide/multiply CMDQ_INST_SIZE where this is needed.

> +		err = cmdq_rec_realloc_cmd_buffer(rec, rec->buf_size * 2);
> +		if (err < 0)
> +			return err;
> +	}
> +	cmd_ptr = rec->buf + rec->command_size;
> +	(*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b;
> +	rec->command_size += CMDQ_INST_SIZE;
> +	return 0;
> +}
> +
> +int cmdq_rec_write(struct cmdq_rec *rec, u32 value, struct cmdq_base *base,
> +		   u32 offset)
> +{
> +	u32 arg_a = ((base->base + offset) & CMDQ_ARG_A_WRITE_MASK) |
> +		    ((base->subsys & CMDQ_SUBSYS_MASK) << CMDQ_SUBSYS_SHIFT);

base->subsys is the id from gce_sybsys, so we can expect it to be 
correct, no need to mask with CMDQ_SUBSYS_MASK.

> +	return cmdq_rec_append_command(rec, CMDQ_CODE_WRITE, arg_a, value);
> +}
> +EXPORT_SYMBOL(cmdq_rec_write);
> +
> +int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
> +			struct cmdq_base *base, u32 offset, u32 mask)
> +{
> +	u32 offset_mask = offset;
> +	int err;
> +
> +	if (mask != 0xffffffff) {
> +		err = cmdq_rec_append_command(rec, CMDQ_CODE_MOVE, 0, ~mask);
> +		if (err < 0)
> +			return err;
> +		offset_mask |= CMDQ_WRITE_ENABLE_MASK;
> +	}
> +	return cmdq_rec_write(rec, value, base, offset_mask);
> +}
> +EXPORT_SYMBOL(cmdq_rec_write_mask);
> +
> +int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event)
> +{
> +	u32 arg_b;
> +
> +	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
> +		return -EINVAL;
> +
> +	/*
> +	 * bit 0-11: wait value
> +	 * bit 15: 1 - wait, 0 - no wait
> +	 * bit 16-27: update value
> +	 * bit 31: 1 - update, 0 - no update
> +	 */

I don't understand this comments. What are they for?

> +	arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
> +	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event, arg_b);
> +}
> +EXPORT_SYMBOL(cmdq_rec_wfe);
> +
> +int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event)
> +{
> +	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
> +		return -EINVAL;
> +
> +	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event,
> +				       CMDQ_WFE_UPDATE);
> +}
> +EXPORT_SYMBOL(cmdq_rec_clear_event);
> +
> +static int cmdq_rec_finalize(struct cmdq_rec *rec)
> +{
> +	int err;
> +
> +	if (rec->finalized)
> +		return 0;
> +
> +	/* insert EOC and generate IRQ for each command iteration */
> +	err = cmdq_rec_append_command(rec, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN);
> +	if (err < 0)
> +		return err;
> +
> +	/* JUMP to end */
> +	err = cmdq_rec_append_command(rec, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS);
> +	if (err < 0)
> +		return err;
> +

Does this need to be atomic?
What happens if after CODE_EOC and before CODE_JUMP some 
write/read/event gets added?
What happens if more commands get added to the queue after CODE_JUMP, 
but before finalized is set to true. Why don't you use atomic functions 
to access finalized?

> +	rec->finalized = true;
> +	return 0;
> +}
> +
> +int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
> +			 void *data)
> +{
> +	struct cmdq *cmdq = rec->cmdq;
> +	struct cmdq_task *task;
> +	struct cmdq_task_cb task_cb;
> +	struct cmdq_thread *thread;
> +	int err;
> +
> +	mutex_lock(&cmdq->task_mutex);
> +	if (cmdq->suspended) {
> +		dev_err(cmdq->dev, "%s is called after suspended\n", __func__);
> +		mutex_unlock(&cmdq->task_mutex);
> +		return -EPERM;
> +	}
> +
> +	err = cmdq_rec_finalize(rec);
> +	if (err < 0) {
> +		mutex_unlock(&cmdq->task_mutex);
> +		return err;
> +	}
> +
> +	task_cb.cb = cb;
> +	task_cb.data = data;
> +	task = cmdq_task_acquire(rec, task_cb);
> +	if (!task) {
> +		mutex_unlock(&cmdq->task_mutex);
> +		return -EFAULT;
> +	}
> +
> +	thread = &cmdq->thread[cmdq_eng_get_thread(task->engine_flag)];
> +	cmdq_task_exec(task, thread);
> +	cmdq_task_wait_release_schedule(task);
> +	mutex_unlock(&cmdq->task_mutex);
> +	return 0;
> +}
> +EXPORT_SYMBOL(cmdq_rec_flush_async);
> +
> +struct cmdq_flush_completion {
> +	struct completion cmplt;
> +	bool err;
> +};
> +
> +static int cmdq_rec_flush_cb(struct cmdq_cb_data data)
> +{
> +	struct cmdq_flush_completion *cmplt = data.data;
> +
> +	cmplt->err = data.err;
> +	complete(&cmplt->cmplt);
> +	return 0;
> +}
> +
> +int cmdq_rec_flush(struct cmdq_rec *rec)
> +{
> +	struct cmdq_flush_completion cmplt;
> +	int err;
> +
> +	init_completion(&cmplt.cmplt);
> +	err = cmdq_rec_flush_async(rec, cmdq_rec_flush_cb, &cmplt);
> +	if (err < 0)
> +		return err;
> +	wait_for_completion(&cmplt.cmplt);
> +	return cmplt.err ? -EFAULT : 0;
> +}
> +EXPORT_SYMBOL(cmdq_rec_flush);
> +
> +void cmdq_rec_destroy(struct cmdq_rec *rec)
> +{
> +	kfree(rec->buf);
> +	kfree(rec);
> +}
> +EXPORT_SYMBOL(cmdq_rec_destroy);
> +
> +static bool cmdq_task_is_empty(struct cmdq *cmdq)
> +{
> +	struct cmdq_thread *thread;
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
> +		thread = &cmdq->thread[i];
> +		if (!list_empty(&thread->task_busy_list))
> +			return false;
> +	}
> +	return true;
> +}
> +
> +static int cmdq_suspend(struct device *dev)
> +{
> +	struct cmdq *cmdq = dev_get_drvdata(dev);
> +	u32 exec_threads;
> +
> +	mutex_lock(&cmdq->task_mutex);
> +	cmdq->suspended = true;
> +	mutex_unlock(&cmdq->task_mutex);
> +
> +	exec_threads = readl(cmdq->base + CMDQ_CURR_LOADED_THR);
> +	if ((exec_threads & CMDQ_THR_EXECUTING) && !cmdq_task_is_empty(cmdq)) {
> +		dev_err(dev, "wait active tasks timeout.\n");
> +		flush_workqueue(cmdq->task_release_wq);
> +	}
> +	return 0;
> +}
> +
> +static int cmdq_resume(struct device *dev)
> +{
> +	struct cmdq *cmdq = dev_get_drvdata(dev);
> +
> +	cmdq->suspended = false;
> +	return 0;
> +}
> +
> +static int cmdq_remove(struct platform_device *pdev)
> +{
> +	struct cmdq *cmdq = platform_get_drvdata(pdev);
> +
> +	destroy_workqueue(cmdq->task_release_wq);
> +	cmdq->task_release_wq = NULL;
> +	return 0;
> +}
> +
> +static int cmdq_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *node = dev->of_node;
> +	struct resource *res;
> +	struct cmdq *cmdq;
> +	int err, i;
> +
> +	cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
> +	if (!cmdq)
> +		return -ENOMEM;
> +	cmdq->dev = dev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	cmdq->base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(cmdq->base)) {
> +		dev_err(dev, "failed to ioremap gce\n");
> +		return PTR_ERR(cmdq->base);
> +	}
> +
> +	cmdq->irq = irq_of_parse_and_map(node, 0);
> +	if (!cmdq->irq) {
> +		dev_err(dev, "failed to get irq\n");
> +		return -EINVAL;
> +	}
> +
> +	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
> +		dev, cmdq->base, cmdq->irq);
> +
> +	mutex_init(&cmdq->task_mutex);
> +	spin_lock_init(&cmdq->exec_lock);
> +	cmdq->task_release_wq = alloc_ordered_workqueue(
> +			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI,
> +			"cmdq_task_wait_release");
> +
> +	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
> +		cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
> +				CMDQ_THR_SHIFT * i;
> +		init_waitqueue_head(&cmdq->thread[i].wait_task_done);
> +		INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list);
> +	}
> +
> +	platform_set_drvdata(pdev, cmdq);
> +
> +	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
> +			       CMDQ_DRIVER_DEVICE_NAME, cmdq);
> +	if (err < 0) {
> +		dev_err(dev, "failed to register ISR (%d)\n", err);
> +		goto fail;
> +	}
> +
> +	cmdq->clock = devm_clk_get(dev, CMDQ_CLK_NAME);
> +	if (IS_ERR(cmdq->clock)) {
> +		dev_err(dev, "failed to get clk:%s\n", CMDQ_CLK_NAME);
> +		err = PTR_ERR(cmdq->clock);
> +		goto fail;
> +	}
> +	return 0;
> +
> +fail:
> +	cmdq_remove(pdev);
> +	return err;
> +}
> +
> +static const struct dev_pm_ops cmdq_pm_ops = {
> +	.suspend = cmdq_suspend,
> +	.resume = cmdq_resume,
> +};
> +
> +static const struct of_device_id cmdq_of_ids[] = {
> +	{.compatible = "mediatek,mt8173-gce",},
> +	{}
> +};
> +
> +static struct platform_driver cmdq_drv = {
> +	.probe = cmdq_probe,
> +	.remove = cmdq_remove,
> +	.driver = {
> +		.name = CMDQ_DRIVER_DEVICE_NAME,
> +		.owner = THIS_MODULE,
> +		.pm = &cmdq_pm_ops,
> +		.of_match_table = cmdq_of_ids,
> +	}
> +};
> +
> +builtin_platform_driver(cmdq_drv);
> diff --git a/include/soc/mediatek/cmdq.h b/include/soc/mediatek/cmdq.h
> new file mode 100644
> index 0000000..60eef3d
> --- /dev/null
> +++ b/include/soc/mediatek/cmdq.h
> @@ -0,0 +1,197 @@
> +/*
> + * Copyright (c) 2015 MediaTek Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __MTK_CMDQ_H__
> +#define __MTK_CMDQ_H__
> +
> +#include <linux/platform_device.h>
> +#include <linux/types.h>
> +
> +enum cmdq_eng {
> +	CMDQ_ENG_DISP_AAL,
> +	CMDQ_ENG_DISP_COLOR0,
> +	CMDQ_ENG_DISP_COLOR1,
> +	CMDQ_ENG_DISP_DPI0,
> +	CMDQ_ENG_DISP_DSI0,
> +	CMDQ_ENG_DISP_DSI1,
> +	CMDQ_ENG_DISP_GAMMA,
> +	CMDQ_ENG_DISP_OD,
> +	CMDQ_ENG_DISP_OVL0,
> +	CMDQ_ENG_DISP_OVL1,
> +	CMDQ_ENG_DISP_PWM0,
> +	CMDQ_ENG_DISP_PWM1,
> +	CMDQ_ENG_DISP_RDMA0,
> +	CMDQ_ENG_DISP_RDMA1,
> +	CMDQ_ENG_DISP_RDMA2,
> +	CMDQ_ENG_DISP_UFOE,
> +	CMDQ_ENG_DISP_WDMA0,
> +	CMDQ_ENG_DISP_WDMA1,
> +	CMDQ_ENG_MAX,
> +};
> +
> +/* events for CMDQ and display */
> +enum cmdq_event {
> +	/* Display start of frame(SOF) events */
> +	CMDQ_EVENT_DISP_OVL0_SOF = 11,
> +	CMDQ_EVENT_DISP_OVL1_SOF = 12,
> +	CMDQ_EVENT_DISP_RDMA0_SOF = 13,
> +	CMDQ_EVENT_DISP_RDMA1_SOF = 14,
> +	CMDQ_EVENT_DISP_RDMA2_SOF = 15,
> +	CMDQ_EVENT_DISP_WDMA0_SOF = 16,
> +	CMDQ_EVENT_DISP_WDMA1_SOF = 17,
> +	/* Display end of frame(EOF) events */
> +	CMDQ_EVENT_DISP_OVL0_EOF = 39,
> +	CMDQ_EVENT_DISP_OVL1_EOF = 40,
> +	CMDQ_EVENT_DISP_RDMA0_EOF = 41,
> +	CMDQ_EVENT_DISP_RDMA1_EOF = 42,
> +	CMDQ_EVENT_DISP_RDMA2_EOF = 43,
> +	CMDQ_EVENT_DISP_WDMA0_EOF = 44,
> +	CMDQ_EVENT_DISP_WDMA1_EOF = 45,
> +	/* Mutex end of frame(EOF) events */
> +	CMDQ_EVENT_MUTEX0_STREAM_EOF = 53,
> +	CMDQ_EVENT_MUTEX1_STREAM_EOF = 54,
> +	CMDQ_EVENT_MUTEX2_STREAM_EOF = 55,
> +	CMDQ_EVENT_MUTEX3_STREAM_EOF = 56,
> +	CMDQ_EVENT_MUTEX4_STREAM_EOF = 57,
> +	/* Display underrun events */
> +	CMDQ_EVENT_DISP_RDMA0_UNDERRUN = 63,
> +	CMDQ_EVENT_DISP_RDMA1_UNDERRUN = 64,
> +	CMDQ_EVENT_DISP_RDMA2_UNDERRUN = 65,
> +	/* Keep this at the end of HW events */
> +	CMDQ_MAX_HW_EVENT_COUNT = 260,
> +};
> +
> +struct cmdq_cb_data {
> +	bool	err;
> +	void	*data;
> +};
> +
> +typedef int (*cmdq_async_flush_cb)(struct cmdq_cb_data data);
> +
> +struct cmdq_task;
> +struct cmdq;
> +
> +struct cmdq_rec {
> +	struct cmdq		*cmdq;
> +	u64			engine_flag;
> +	size_t			command_size;
> +	void			*buf;
> +	size_t			buf_size;
> +	bool			finalized;
> +};
> +
> +struct cmdq_base {
> +	int	subsys;
> +	u32	base;

subsys can always be calculated via cmdq_subsys_base_to_id(base >> 16) 
so we can get rid of the struct, right?

> +};
> +
> +/**
> + * cmdq_register_device() - register device which needs CMDQ
> + * @dev:		device
> + *
> + * Return: cmdq_base pointer or NULL for failed
> + */
> +struct cmdq_base *cmdq_register_device(struct device *dev);
> +
> +/**
> + * cmdq_rec_create() - create command queue record
> + * @dev:		device
> + * @engine_flag:	command queue engine flag
> + * @rec_ptr:		command queue record pointer to retrieve cmdq_rec
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_create(struct device *dev, u64 engine_flag,
> +		    struct cmdq_rec **rec_ptr);
> +
> +/**
> + * cmdq_rec_write() - append write command to the command queue record
> + * @rec:	the command queue record
> + * @value:	the specified target register value
> + * @base:	the command queue base
> + * @offset:	register offset from module base
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_write(struct cmdq_rec *rec, u32 value,
> +		   struct cmdq_base *base, u32 offset);
> +
> +/**
> + * cmdq_rec_write_mask() - append write command with mask to the command
> + *			   queue record
> + * @rec:	the command queue record
> + * @value:	the specified target register value
> + * @base:	the command queue base
> + * @offset:	register offset from module base
> + * @mask:	the specified target register mask
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
> +			struct cmdq_base *base, u32 offset, u32 mask);
> +
> +/**
> + * cmdq_rec_wfe() - append wait for event command to the command queue reco	rd

reco rd -> record

Regards,
Matthias

> + * @rec:	the command queue record
> + * @event:	the desired event type to "wait and CLEAR"
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event);
> +
> +/**
> + * cmdq_rec_clear_event() - append clear event command to the command queue
> + *			    record
> + * @rec:	the command queue record
> + * @event:	the desired event to be cleared
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event);
> +
> +/**
> + * cmdq_rec_flush() - trigger CMDQ to execute the recorded commands
> + * @rec:	the command queue record
> + *
> + * Return: 0 for success; else the error code is returned
> + *
> + * Trigger CMDQ to execute the recorded commands. Note that this is a
> + * synchronous flush function. When the function returned, the recorded
> + * commands have been done.
> + */
> +int cmdq_rec_flush(struct cmdq_rec *rec);
> +
> +/**
> + * cmdq_rec_flush_async() - trigger CMDQ to asynchronously execute the recorded
> + *			    commands and call back after ISR is finished
> + * @rec:	the command queue record
> + * @cb:		called in the end of CMDQ ISR
> + * @data:	this data will pass back to cb
> + *
> + * Return: 0 for success; else the error code is returned
> + *
> + * Trigger CMDQ to asynchronously execute the recorded commands and call back
> + * after ISR is finished. Note that this is an ASYNC function. When the function
> + * returned, it may or may not be finished. The ISR callback function is called
> + * in the end of ISR.
> + */
> +int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
> +			 void *data);
> +
> +/**
> + * cmdq_rec_destroy() - destroy command queue record
> + * @rec:	the command queue record
> + */
> +void cmdq_rec_destroy(struct cmdq_rec *rec);
> +
> +#endif	/* __MTK_CMDQ_H__ */
>


From arnd at arndb.de  Mon May 30 08:38:13 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Mon, 30 May 2016 17:38:13 +0200
Subject: [PATCH V8 9/9] pci,
 acpi: ARM64 support for ACPI based generic PCI host controller
In-Reply-To: <1464621262-26770-10-git-send-email-tn@semihalf.com>
References: <1464621262-26770-1-git-send-email-tn@semihalf.com>
 <1464621262-26770-10-git-send-email-tn@semihalf.com>
Message-ID: <8385994.W7ve9PrvHG@wuerfel>

On Monday, May 30, 2016 5:14:22 PM CEST Tomasz Nowicki wrote:
> +       bsz = 1 << pci_generic_ecam_ops.bus_shift;
> +       cfgres.start = root->mcfg_addr + bus_res->start * bsz;
> +       cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
> +       cfgres.flags = IORESOURCE_MEM;
> +       cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
> +                             &pci_generic_ecam_ops);
> +       if (IS_ERR(cfg)) {
> +               pr_err("%04x:%pR error %ld mapping CAM\n", seg, bus_res,
> +                      PTR_ERR(cfg));
> +               return PTR_ERR(cfg);
> +       }
> +
> +       ri->cfg = cfg;
> +       return 0;
> +}

I wonder if we could do this a little simpler and just put a pointer
to the mmconfig space into struct pci_host_bridge, and then have a trivial
map_bus function alongside pci_generic_config_read/pci_generic_config_write.

As this code is specific to arch/arm64, we don't need any of the complexity
of drivers/pci/ecam.c, which basically only exists to work around the
limited virtual address space of 32-bit machines.

	Arnd


From wens at csie.org  Mon May 30 08:38:37 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Mon, 30 May 2016 23:38:37 +0800
Subject: [PATCH 2/3] mmc: sunxi: Fix DDR MMC timings for A80
In-Reply-To: <CAGb2v65=ZM+deSmTmMnT6XFJv8PuY+Kba3kJGKrk_46hxxRyHA@mail.gmail.com>
References: <1464505484-3661-1-git-send-email-wens@csie.org>
 <1464505484-3661-3-git-send-email-wens@csie.org>
 <99d78ff3-db4d-45cc-024a-d94583b56f35@redhat.com>
 <CAGb2v65=ZM+deSmTmMnT6XFJv8PuY+Kba3kJGKrk_46hxxRyHA@mail.gmail.com>
Message-ID: <CAGb2v64qo=kY=ekhbzJUWM_6p9oUupsE+YASD6g9beZS7eg9NQ@mail.gmail.com>

On Mon, May 30, 2016 at 8:59 PM, Chen-Yu Tsai <wens at csie.org> wrote:
> On Mon, May 30, 2016 at 7:34 PM, Hans de Goede <hdegoede at redhat.com> wrote:
>> Hi,
>>
>> On 29-05-16 09:04, Chen-Yu Tsai wrote:
>>>
>>> The MMC clock timings were incorrectly calculated, when the conversion
>>> from delay value to delay phase was done.
>>>
>>> The 50M DDR and 50M DDR 8bit timings are off, and make eMMC DDR
>>> unusable. Unfortunately it seems different controllers on the same SoC
>>> have different timings. The new settings are taken from mmc2, which is
>>> commonly used with eMMC.
>>
>>
>> Hmm, I'm not really all that familiar with mmc, but can't an external
>> sdcard connected to mmc0 use DDR too ? Assuming the answer is yes, then
>> we really need to update the driver to use the right per controller
>> timings.
>
> I would very much like that to happen. However, SD card UHS-1 DDR modes
> require 1.8V signaling, which is unavailable on _all_ sunxi boards.
> This seems like a limit of most of the SoCs not having a separate IO
> voltage rail for mmc pins.
>
> Until then, I wouldn't worry that much.

P.S. I also tried the settings from mmc0 in Allwinner sources. They gave
horrible results ( < 5 MB/s read ) on my CC-A80, while my Optimus wasn't
really affected. I wonder if there's some kind of auto-retry mechanism
in the MMC controller, or driver?

ChenYu

>>> The settings for the slower timing modes seem to work despite being
>>> wrong, so leave them be.
>>
>>
>> If you're sure the timings are wrong, please fix them. Sometimes wrong
>> timings do seem to work, but lead to unreliable communication, or turn
>> out to work on some boards and not on others due to routing differences.
>
> Unfortunately I did try putting in the correct numbers for them, and my
> eMMC then failed to probe. It seems the core switches up from 400kHz to
> 50MHz then to 50MHz DDR, and it fails somewhere in there, maybe at 50MHz.
>
> I'm not sure if we need to add DT bindings to specify different delays
> for different controllers, though. Seems like we'll never actually use
> it.
>
> Hope this answers your questions.
>
> Regards
> ChenYu
>
>> Thanks & Regards,
>>
>> Hans
>>
>>
>>
>>>
>>> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
>>> ---
>>>  drivers/mmc/host/sunxi-mmc.c | 4 ++--
>>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
>>> index 7fc8b7aa83f0..5873dc344ab2 100644
>>> --- a/drivers/mmc/host/sunxi-mmc.c
>>> +++ b/drivers/mmc/host/sunxi-mmc.c
>>> @@ -970,8 +970,8 @@ static const struct sunxi_mmc_clk_delay
>>> sun9i_mmc_clk_delays[] = {
>>>         [SDXC_CLK_400K]         = { .output = 180, .sample = 180 },
>>>         [SDXC_CLK_25M]          = { .output = 180, .sample =  75 },
>>>         [SDXC_CLK_50M]          = { .output = 150, .sample = 120 },
>>> -       [SDXC_CLK_50M_DDR]      = { .output =  90, .sample = 120 },
>>> -       [SDXC_CLK_50M_DDR_8BIT] = { .output =  90, .sample = 120 },
>>> +       [SDXC_CLK_50M_DDR]      = { .output =  54, .sample =  36 },
>>> +       [SDXC_CLK_50M_DDR_8BIT] = { .output =  72, .sample =  72 },
>>>  };
>>>
>>>  static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
>>>
>>


From broonie at kernel.org  Mon May 30 08:50:16 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 30 May 2016 16:50:16 +0100
Subject: [PATCH 5/5] RFC spi: sun4i: add DMA support
In-Reply-To: <CAOMqctQb-YYprA7H5qCcYo2hxXiUhjW2z3JbZ3-FhbfcjFzBpw@mail.gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
 <ba0d6eb37cc4b0d2c46acbf9fcd7d644b3545ce8.1464130597.git.hramrach@gmail.com>
 <20160530112610.GJ29837@sirena.org.uk>
 <CAMuHMdVThvtqgFnyqoqypwwf1d81uu9NBo6-heTZBcvBxRevNw@mail.gmail.com>
 <20160530150343.GL29837@sirena.org.uk>
 <CAOMqctQb-YYprA7H5qCcYo2hxXiUhjW2z3JbZ3-FhbfcjFzBpw@mail.gmail.com>
Message-ID: <20160530155016.GO29837@sirena.org.uk>

On Mon, May 30, 2016 at 05:28:10PM +0200, Michal Suchanek wrote:
> On 30 May 2016 at 17:03, Mark Brown <broonie at kernel.org> wrote:

> > I really don't think it's worth caring too much about cases where the
> > DMA driver hasn't been compiled in, it's not like SPI is the only thing

> It's what the driver did to start with and it was requested to fall
> back to non-DMA in the case DMA is not available.

Why?  I really can't see any sensible use case for this that doesn't
have a better solution available.

> It's possible to add a parameter like require_dma which could be used
> to load the driver without dma if unset. If it was set by default then
> driver ordering is not important so long as dma driver is loaded
> eventually. Also an informative print that such parameter exists when
> probing the driver is deferred would be helpful. It would probably
> create quite a bit of log spam, however. The driver can be deferred
> several times during boot.

That seems fairly hacky, if we were going to do anything like that it
should be the other way around so that we default to trying to use
resources and even then it seems like something that should be handled
at a framework level rather than having random options in individual
drivers to ignore things.  Having things behave inconsistently between
different drivers is going to lead to a worse user experience and if
this is a good idea for one driver it seems like it'd be a good idea for
all of them.

But really 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/4ad69a21/attachment.sig>

From broonie at kernel.org  Mon May 30 09:03:57 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 30 May 2016 17:03:57 +0100
Subject: [PATCH v3] ASoC: rockchip: Add machine driver for
 MAX98357A/RT5514/DA7219
In-Reply-To: <574BEC9D.50007@rock-chips.com>
References: <1464267742-15312-1-git-send-email-zhengxing@rock-chips.com>
 <574BEC9D.50007@rock-chips.com>
Message-ID: <20160530160357.GQ29837@sirena.org.uk>

On Mon, May 30, 2016 at 03:32:45PM +0800, Xing Zheng wrote:
> Hi,
> Could any guys help me to review this patch?

Please don't send content free pings and please allow a reasonable time
for review.  People get busy, go on holiday, attend conferences and so 
on so unless there is some reason for urgency (like critical bug fixes)
please allow at least a couple of weeks for review.  If there have been
review comments then people may be waiting for those to be addressed.
Sending content free pings just adds to the mail volume (if they are
seen at all) and if something has gone wrong you'll have to resend the
patches anyway.

Please don't top post, reply in line with needed context.  This allows
readers to readily follow the flow of conversation and understand what
you are talking about and also helps ensure that everything in the
discussion is being addressed.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/5e060bd5/attachment.sig>

From p.zabel at pengutronix.de  Mon May 30 09:14:22 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Mon, 30 May 2016 18:14:22 +0200
Subject: [PATCH v2 1/4] reset: Add support for the Amlogic Meson SoC
 Reset Controller
In-Reply-To: <m28tywhda8.fsf@baylibre.com>
References: <1464169758-26975-1-git-send-email-narmstrong@baylibre.com>
 <1464169758-26975-2-git-send-email-narmstrong@baylibre.com>
 <m2iny1h74c.fsf@baylibre.com> <1464260562.4109.77.camel@pengutronix.de>
 <m28tywhda8.fsf@baylibre.com>
Message-ID: <1464624862.3808.106.camel@pengutronix.de>

Hi Kevin,

Am Donnerstag, den 26.05.2016, 11:42 -0700 schrieb Kevin Hilman:
[...]
> > Personally, I'd prefer if the driver could switch to only using
> > 	reset_control_reset(rstc);
> 
> Then what would happen if that same driver is used on platforms that
> have ->assert and ->deassert but no -reset?

If the implementer of the reset controller driver doesn't have enough
information about all connected devices to implement ->reset, then
_reset() has to return -ENOTSUPP, so this is not an option in the
general case.

> The bind I'm in is that I'm using an exsting network driver
> (stmicro/stmmac) which is used on a bunch of platforms and I dont' know
> what all those reset controllers are actually doing, so going and
> changing the driver seems problematic.

I see. It's all the more important that the API clearly states the
intended effects.

> > or, if the reset line needs to stay asserted during powerdown where the
> > reset controller supports it, but doesn't matter whert not, use:
> > 	ret = reset_control_deassert(rstc);
> > 	if (ret == -ENOTSUPP)
> > 		ret = reset_control_reset(rstc);
> >
> > We could add a helper reset_control_deassert_or_reset() for that.
> 
> IMO, that would be a useful helper function, but I still think that
> should be the default behavior of _deassert, otherwise it will still
> require changing all the drivers.

"All the drivers" makes me reconsider. If all drivers eventually,
reasonably could be changed to use reset_control_deassert_or_reset()
instead of reset_control_deassert(), there would be no reason not to
make _deassert() behave like you expect (well, except for the naming
issue).

One thing that has to be considered is that in the case of synchronous
resets there may be a significant difference in the behaviour of ->reset
and ->deassert: With ->deassert you could prime the reset line before
enabling clocks and letting the reset signal propagate. This is not
possible with ->reset, which could hang or have no effect at all with
the relevant clocks disabled. So it should be clearly documented that
anybody intending to make use of this must call reset_control_assert()
first and back off if that returns -ENOTSUPP.

regards
Philipp



From jchandra at broadcom.com  Mon May 30 09:13:58 2016
From: jchandra at broadcom.com (Jayachandran C)
Date: Mon, 30 May 2016 21:43:58 +0530
Subject: [PATCH V8 9/9] pci, acpi: ARM64 support for ACPI based generic
 PCI host controller
In-Reply-To: <8385994.W7ve9PrvHG@wuerfel>
References: <1464621262-26770-1-git-send-email-tn@semihalf.com>
 <1464621262-26770-10-git-send-email-tn@semihalf.com>
 <8385994.W7ve9PrvHG@wuerfel>
Message-ID: <CAKc_7PW3Hdk9zTZ53yhGVdeeFVGFaFExZEvp456s16DnnMMjWg@mail.gmail.com>

On Mon, May 30, 2016 at 9:08 PM, Arnd Bergmann <arnd at arndb.de> wrote:
> On Monday, May 30, 2016 5:14:22 PM CEST Tomasz Nowicki wrote:
>> +       bsz = 1 << pci_generic_ecam_ops.bus_shift;
>> +       cfgres.start = root->mcfg_addr + bus_res->start * bsz;
>> +       cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
>> +       cfgres.flags = IORESOURCE_MEM;
>> +       cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
>> +                             &pci_generic_ecam_ops);
>> +       if (IS_ERR(cfg)) {
>> +               pr_err("%04x:%pR error %ld mapping CAM\n", seg, bus_res,
>> +                      PTR_ERR(cfg));
>> +               return PTR_ERR(cfg);
>> +       }
>> +
>> +       ri->cfg = cfg;
>> +       return 0;
>> +}
>
> I wonder if we could do this a little simpler and just put a pointer
> to the mmconfig space into struct pci_host_bridge, and then have a trivial
> map_bus function alongside pci_generic_config_read/pci_generic_config_write.
>
> As this code is specific to arch/arm64, we don't need any of the complexity
> of drivers/pci/ecam.c, which basically only exists to work around the
> limited virtual address space of 32-bit machines.

The map_bus provided by pci-ecam.h is already trivial in 64bit case,
it was written so that it could be optimized at compile time. The
pci_ecam_create is a useful to have here instead of redoing the
request_resource/ioremap sequence.

The struct pci_config_window can be moved into struct
pci_host_bridge (or a wrapper of pci_host_bridge) when we have
the setup to point bus->sysdata to something like that. The ECAM
API can be fixed up to handle that case as well. I did not make
any changes since the pci_host_bridge discussion is still going on.

JC.


From broonie at kernel.org  Mon May 30 09:15:04 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 30 May 2016 17:15:04 +0100
Subject: [PATCH v1 11/14] ASoC: omap: Kconfig:
 SND_OMAP_SOC_OMAP_ABE_TWL6040 to select CLK_TWL6040
In-Reply-To: <20160530085522.30398-12-peter.ujfalusi@ti.com>
References: <20160530085522.30398-1-peter.ujfalusi@ti.com>
 <20160530085522.30398-12-peter.ujfalusi@ti.com>
Message-ID: <20160530161504.GS29837@sirena.org.uk>

On Mon, May 30, 2016 at 11:55:19AM +0300, Peter Ujfalusi wrote:
> The pdmclk is needed for McPDM. It is generated by twl6040.

Please don't resubmit already applied patches.  If any incremental
updates are needed please send them as such.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/b562c972/attachment.sig>

From wens at csie.org  Mon May 30 09:15:28 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 31 May 2016 00:15:28 +0800
Subject: [PATCH 15/16] clk: sunxi-ng: Add H3 clocks
In-Reply-To: <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
References: <1462737711-10017-1-git-send-email-maxime.ripard@free-electrons.com>
 <1462737711-10017-16-git-send-email-maxime.ripard@free-electrons.com>
Message-ID: <CAGb2v67RUCZfFaXnM2LxomV5DBSVApXHHs0noiNEbReOh_3W9w@mail.gmail.com>

On Mon, May 9, 2016 at 4:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Add the list of clocks and resets found in the H3 CCU.
>
> Signed-off-by: Maxime Ripard <maxime.ripard at free-electrons.com>
> ---
>  drivers/clk/sunxi-ng/Makefile        |   2 +
>  drivers/clk/sunxi-ng/ccu-sun8i-h3.c  | 757 +++++++++++++++++++++++++++++++++++
>  include/dt-bindings/clock/sun8i-h3.h | 162 ++++++++
>  include/dt-bindings/reset/sun8i-h3.h | 103 +++++
>  4 files changed, 1024 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.c
>  create mode 100644 include/dt-bindings/clock/sun8i-h3.h
>  create mode 100644 include/dt-bindings/reset/sun8i-h3.h
>
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index c794f57b6fb1..67ff6a92f124 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -13,3 +13,5 @@ obj-y += ccu_nkmp.o
>  obj-y += ccu_nm.o
>  obj-y += ccu_p.o
>  obj-y += ccu_phase.o
> +
> +obj-y += ccu-sun8i-h3.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> new file mode 100644
> index 000000000000..5ce699e95c32
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> @@ -0,0 +1,757 @@
> +/*
> + * Copyright (c) 2016 Maxime Ripard. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk-provider.h>
> +
> +#include <dt-bindings/clock/sun8i-h3.h>
> +#include <dt-bindings/reset/sun8i-h3.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_reset.h"
> +
> +#include "ccu_div_table.h"
> +#include "ccu_factor.h"
> +#include "ccu_fixed_factor.h"
> +#include "ccu_gate.h"
> +#include "ccu_m.h"
> +#include "ccu_mp.h"
> +#include "ccu_nk.h"
> +#include "ccu_nkm.h"
> +#include "ccu_nkmp.h"
> +#include "ccu_nm.h"
> +#include "ccu_p.h"
> +#include "ccu_phase.h"
> +
> +static struct ccu_nkmp pll_cpux_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +
> +       .m              = SUNXI_CLK_FACTOR(0, 2),
> +       .k              = SUNXI_CLK_FACTOR(4, 2),
> +       .n              = SUNXI_CLK_FACTOR(8, 5),
> +       .p              = SUNXI_CLK_FACTOR(16, 2),

We should find a way to specify a table for p.

> +
> +       .common         = {
> +               .reg            = 0x000,
> +               .features       = CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> +               .hw.init        = SUNXI_HW_INIT("pll-cpux",
> +                                               "osc24M",

osc24M is an outside reference. Shouldn't we use put it in a "clocks"
property in the DT, and use of_clk_get_parent_name()?

osc24M can be controlled from the PRCM on other chips. I suspect the
same with the H3. osc32k might also be from the PRCM.

> +                                               &ccu_nkmp_ops,
> +                                               0),
> +       },
> +};
> +
> +static struct ccu_nm pll_audio_base_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +
> +       .m              = SUNXI_CLK_FACTOR(0, 5),
> +       .n              = SUNXI_CLK_FACTOR(8, 7),
> +
> +       .common         = {
> +               .reg            = 0x008,
> +               .features       = CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> +               .hw.init        = SUNXI_HW_INIT("pll-audio-base",
> +                                               "osc24M",
> +                                               &ccu_nm_ops,
> +                                               0),
> +       },
> +};
> +
> +static SUNXI_CCU_M(pll_audio_clk, "pll-audio", "pll-audio-base",
> +                  0x008, 16, 4, 0);
> +
> +static SUNXI_CCU_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
> +                             "pll-audio-base", 2, 1, 0);
> +static SUNXI_CCU_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
> +                             "pll-audio-base", 1, 1, 0);
> +static SUNXI_CCU_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
> +                             "pll-audio-base", 1, 2, 0);
> +
> +static struct ccu_nm pll_video_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +
> +       .m              = SUNXI_CLK_FACTOR(0, 4),
> +       .n              = SUNXI_CLK_FACTOR(8, 7),
> +
> +       .common         = {
> +               .reg            = 0x010,
> +               .features       = CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> +               .hw.init        = SUNXI_HW_INIT("pll-video",
> +                                               "osc24M",
> +                                               &ccu_nm_ops,
> +                                               0),
> +       },
> +};
> +
> +static struct ccu_nm pll_ve_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +
> +       .m              = SUNXI_CLK_FACTOR(0, 4),
> +       .n              = SUNXI_CLK_FACTOR(8, 7),
> +
> +       .common         = {
> +               .reg            = 0x018,
> +               .features       = CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> +               .hw.init        = SUNXI_HW_INIT("pll-ve",
> +                                               "osc24M",
> +                                               &ccu_nm_ops,
> +                                               0),
> +       },
> +};
> +
> +static struct ccu_nkm pll_ddr_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +
> +       .n              = SUNXI_CLK_FACTOR(8, 5),
> +       .k              = SUNXI_CLK_FACTOR(4, 2),
> +       .m              = SUNXI_CLK_FACTOR(0, 2),

We need a special "update" bit (bit 20) for this clock, otherwise changes
don't really take effect.

> +
> +       .common         = {
> +               .reg            = 0x020,
> +               .features       = CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> +               .hw.init        = SUNXI_HW_INIT("pll-ddr",
> +                                               "osc24M",
> +                                               &ccu_nkm_ops,
> +                                               0),
> +       },
> +};
> +
> +static struct ccu_nk pll_periph0_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +
> +       .k              = SUNXI_CLK_FACTOR(4, 2),
> +       .n              = SUNXI_CLK_FACTOR(8, 5),
> +       .fixed_post_div = 2,
> +
> +       .common         = {
> +               .reg            = 0x028,
> +               .features       = (CCU_FEATURE_GATE |
> +                                  CCU_FEATURE_LOCK |
> +                                  CCU_FEATURE_FIXED_POSTDIV),
> +               .hw.init        = SUNXI_HW_INIT("pll-periph0",
> +                                               "osc24M",
> +                                               &ccu_nk_ops,
> +                                               0),
> +       },
> +};
> +
> +static SUNXI_CCU_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
> +                             "pll-periph0", 1, 2, 0);
> +
> +static struct ccu_nm pll_gpu_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +
> +       .m              = SUNXI_CLK_FACTOR(0, 4),
> +       .n              = SUNXI_CLK_FACTOR(8, 7),
> +
> +       .common         = {
> +               .reg            = 0x038,
> +               .features       = CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> +               .hw.init        = SUNXI_HW_INIT("pll-gpu",
> +                                               "osc24M",
> +                                               &ccu_nm_ops,
> +                                               0),
> +       },
> +};
> +
> +static struct ccu_nk pll_periph1_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +
> +       .k              = SUNXI_CLK_FACTOR(4, 2),
> +       .n              = SUNXI_CLK_FACTOR(8, 5),
> +       .fixed_post_div = 2,
> +
> +       .common         = {
> +               .reg            = 0x044,
> +               .features       = (CCU_FEATURE_GATE |
> +                                  CCU_FEATURE_LOCK |
> +                                  CCU_FEATURE_FIXED_POSTDIV),
> +               .hw.init        = SUNXI_HW_INIT("pll-periph1",
> +                                               "osc24M",
> +                                               &ccu_nk_ops,
> +                                               0),
> +       },
> +};
> +
> +static struct ccu_nm pll_de_clk = {
> +       .enable         = BIT(31),
> +       .lock           = BIT(28),
> +
> +       .m              = SUNXI_CLK_FACTOR(0, 4),
> +       .n              = SUNXI_CLK_FACTOR(8, 7),
> +
> +       .common         = {
> +               .reg            = 0x048,
> +               .features       = CCU_FEATURE_GATE | CCU_FEATURE_LOCK,
> +               .hw.init        = SUNXI_HW_INIT("pll-de",
> +                                               "osc24M",
> +                                               &ccu_nm_ops,
> +                                               0),
> +       },
> +};
> +
> +static const char * const cpux_parents[] = { "osc32k", "osc24M", "pll-cpux" , "pll-cpux" };
> +static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
> +                    0x050, 16, 2, CLK_IS_CRITICAL);

Nit: Is it necessary to split this line?

> +
> +static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);

This register also has a "System APB" clock. Any idea what that is?

> +
> +static const char * const ahb1_parents[] = { "osc32k", "osc24M", "axi" , "pll-periph0" };
> +static struct ccu_p ahb1_clk = {
> +       .p              = SUNXI_CLK_FACTOR(4, 2),
> +
> +       .mux            = {
> +               .shift  = 12,
> +               .width  = 2,
> +
> +               .variable_prediv        = {
> +                       .index  = 3,
> +                       .shift  = 6,
> +                       .width  = 2,
> +               },
> +       },
> +
> +       .common         = {
> +               .reg            = 0x054,
> +               .features       = CCU_FEATURE_VARIABLE_PREDIV,
> +               .hw.init        = SUNXI_HW_INIT_PARENTS("ahb1",
> +                                                       ahb1_parents,
> +                                                       &ccu_p_ops,
> +                                                       0),
> +       },
> +};
> +
> +static u8 apb1_div_table [] = { 2, 2, 4, 8 };
> +static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1",
> +                          0x054, 8, 2, apb1_div_table, 0);
> +
> +static const char * const apb2_parents[] = { "osc32k", "osc24M",
> +                                            "pll-periph0" , "pll-periph0" };
> +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058,
> +                            0, 5,      /* M */
> +                            16, 2,     /* P */
> +                            24, 2,     /* mux */
> +                            0);
> +
> +static const char * const ahb2_parents[] = { "ahb1" , "pll-periph0" };
> +static struct ccu_mux ahb2_clk = {
> +       .mux            = {
> +               .shift  = 0,
> +               .width  = 1,
> +
> +               .fixed_prediv   = {
> +                       .index  = 1,
> +                       .div    = 2,
> +               },
> +       },
> +
> +       .common         = {
> +               .reg            = 0x05c,
> +               .features       = CCU_FEATURE_FIXED_PREDIV,
> +               .hw.init        = SUNXI_HW_INIT_PARENTS("ahb2",
> +                                                       ahb2_parents,
> +                                                       &ccu_mux_ops,
> +                                                       0),
> +       },
> +};
> +
> +static SUNXI_CCU_GATE(bus_ce_clk,      "bus-ce",       "ahb1",
> +                     0x060, BIT(5), 0);
> +static SUNXI_CCU_GATE(bus_dma_clk,     "bus-dma",      "ahb1",
> +                     0x060, BIT(6), 0);
> +static SUNXI_CCU_GATE(bus_mmc0_clk,    "bus-mmc0",     "ahb1",
> +                     0x060, BIT(8), 0);
> +static SUNXI_CCU_GATE(bus_mmc1_clk,    "bus-mmc1",     "ahb1",
> +                     0x060, BIT(9), 0);
> +static SUNXI_CCU_GATE(bus_mmc2_clk,    "bus-mmc2",     "ahb1",
> +                     0x060, BIT(10), 0);
> +static SUNXI_CCU_GATE(bus_nand_clk,    "bus-nand",     "ahb1",
> +                     0x060, BIT(13), 0);
> +static SUNXI_CCU_GATE(bus_dram_clk,    "bus-dram",     "ahb1",
> +                     0x060, BIT(14), 0);
> +static SUNXI_CCU_GATE(bus_emac_clk,    "bus-emac",     "ahb2",
> +                     0x060, BIT(17), 0);
> +static SUNXI_CCU_GATE(bus_ts_clk,      "bus-ts",       "ahb1",
> +                     0x060, BIT(18), 0);
> +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer",  "ahb1",
> +                     0x060, BIT(19), 0);
> +static SUNXI_CCU_GATE(bus_spi0_clk,    "bus-spi0",     "ahb1",
> +                     0x060, BIT(20), 0);
> +static SUNXI_CCU_GATE(bus_spi1_clk,    "bus-spi1",     "ahb1",
> +                     0x060, BIT(21), 0);
> +static SUNXI_CCU_GATE(bus_otg_clk,     "bus-otg",      "ahb1",
> +                     0x060, BIT(23), 0);
> +static SUNXI_CCU_GATE(bus_ehci0_clk,   "bus-ehci0",    "ahb2",

Clock diagram says ?HCI 1/2/3 are on ahb2, while otg (I assume it includes
both the OTG controller and the associated ?HCI) is on ahb1.

> +                     0x060, BIT(24), 0);
> +static SUNXI_CCU_GATE(bus_ehci1_clk,   "bus-ehci1",    "ahb2",
> +                     0x060, BIT(25), 0);
> +static SUNXI_CCU_GATE(bus_ehci2_clk,   "bus-ehci2",    "ahb2",
> +                     0x060, BIT(26), 0);
> +static SUNXI_CCU_GATE(bus_ehci3_clk,   "bus-ehci3",    "ahb2",
> +                     0x060, BIT(27), 0);
> +static SUNXI_CCU_GATE(bus_ohci0_clk,   "bus-ohci0",    "ahb2",
> +                     0x060, BIT(28), 0);
> +static SUNXI_CCU_GATE(bus_ohci1_clk,   "bus-ohci1",    "ahb2",
> +                     0x060, BIT(29), 0);
> +static SUNXI_CCU_GATE(bus_ohci2_clk,   "bus-ohci2",    "ahb2",
> +                     0x060, BIT(30), 0);
> +static SUNXI_CCU_GATE(bus_ohci3_clk,   "bus-ohci3",    "ahb2",
> +                     0x060, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE(bus_ve_clk,      "bus-ve",       "ahb1",
> +                     0x064, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_tcon0_clk,   "bus-tcon0",    "ahb1",
> +                     0x064, BIT(3), 0);
> +static SUNXI_CCU_GATE(bus_tcon1_clk,   "bus-tcon1",    "ahb1",
> +                     0x064, BIT(4), 0);
> +static SUNXI_CCU_GATE(bus_deinterlace_clk,     "bus-deinterlace",      "ahb1",
> +                     0x064, BIT(5), 0);
> +static SUNXI_CCU_GATE(bus_csi_clk,     "bus-csi",      "ahb1",
> +                     0x064, BIT(8), 0);
> +static SUNXI_CCU_GATE(bus_tve_clk,     "bus-tve",      "ahb1",
> +                     0x064, BIT(9), 0);
> +static SUNXI_CCU_GATE(bus_hdmi_clk,    "bus-hdmi",     "ahb1",
> +                     0x064, BIT(11), 0);
> +static SUNXI_CCU_GATE(bus_de_clk,      "bus-de",       "ahb1",
> +                     0x064, BIT(12), 0);
> +static SUNXI_CCU_GATE(bus_gpu_clk,     "bus-gpu",      "ahb1",
> +                     0x064, BIT(20), 0);
> +static SUNXI_CCU_GATE(bus_msgbox_clk,  "bus-msgbox",   "ahb1",
> +                     0x064, BIT(21), 0);
> +static SUNXI_CCU_GATE(bus_spinlock_clk,        "bus-spinlock", "ahb1",
> +                     0x064, BIT(22), 0);
> +
> +static SUNXI_CCU_GATE(bus_codec_clk,   "bus-codec",    "apb1",
> +                     0x068, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_spdif_clk,   "bus-spdif",    "apb1",
> +                     0x068, BIT(1), 0);
> +static SUNXI_CCU_GATE(bus_pio_clk,     "bus-pio",      "apb1",
> +                     0x068, BIT(5), 0);
> +static SUNXI_CCU_GATE(bus_ths_clk,     "bus-ths",      "apb1",
> +                     0x068, BIT(8), 0);
> +static SUNXI_CCU_GATE(bus_i2s0_clk,    "bus-i2s0",     "apb1",
> +                     0x068, BIT(12), 0);
> +static SUNXI_CCU_GATE(bus_i2s1_clk,    "bus-i2s1",     "apb1",
> +                     0x068, BIT(13), 0);
> +static SUNXI_CCU_GATE(bus_i2s2_clk,    "bus-i2s2",     "apb1",
> +                     0x068, BIT(14), 0);
> +
> +static SUNXI_CCU_GATE(bus_i2c0_clk,    "bus-i2c0",     "apb2",
> +                     0x06c, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_i2c1_clk,    "bus-i2c1",     "apb2",
> +                     0x06c, BIT(1), 0);
> +static SUNXI_CCU_GATE(bus_i2c2_clk,    "bus-i2c2",     "apb2",
> +                     0x06c, BIT(2), 0);
> +static SUNXI_CCU_GATE(bus_uart0_clk,   "bus-uart0",    "apb2",
> +                     0x06c, BIT(16), 0);
> +static SUNXI_CCU_GATE(bus_uart1_clk,   "bus-uart1",    "apb2",
> +                     0x06c, BIT(17), 0);
> +static SUNXI_CCU_GATE(bus_uart2_clk,   "bus-uart2",    "apb2",
> +                     0x06c, BIT(18), 0);
> +static SUNXI_CCU_GATE(bus_uart3_clk,   "bus-uart3",    "apb2",
> +                     0x06c, BIT(19), 0);
> +static SUNXI_CCU_GATE(bus_scr_clk,     "bus-scr",      "apb2",
> +                     0x06c, BIT(20), 0);
> +
> +static SUNXI_CCU_GATE(bus_ephy_clk,    "bus-ephy",     "ahb1",
> +                     0x070, BIT(0), 0);
> +static SUNXI_CCU_GATE(bus_dbg_clk,     "bus-dbg",      "ahb1",
> +                     0x070, BIT(7), 0);

Maybe not split these lines? IMHO it's easier to read as table.

> +
> +static u8 ths_div_table [] = { 1, 2, 4, 6 };
> +static SUNXI_CCU_DIV_TABLE_WITH_GATE(ths_clk, "ths", "osc24M",
> +                                    0x074, 0, 2, ths_div_table, BIT(31), 0);

The clock actually has a mux, which has only one valid parent.
Should we include it?

> +
> +static const char * const nand_parents[] = { "osc24M", "pll-periph0",
> +                                            "pll-periph1" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", nand_parents, 0x080,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static const char * const mmc0_parents[] = { "osc24M", "pll-periph0",
> +                                            "pll-periph1" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_parents, 0x088,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0",
> +                      0x088, 20, 3, 0);
> +static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0",
> +                      0x088, 8, 3, 0);
> +
> +static const char * const mmc1_parents[] = { "osc24M", "pll-periph0",
> +                                            "pll-periph1" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc1_parents, 0x08c,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1",
> +                      0x08c, 20, 3, 0);
> +static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1",
> +                      0x08c, 8, 3, 0);
> +
> +static const char * const mmc2_parents[] = { "osc24M", "pll-periph0",
> +                                            "pll-periph1" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc2_parents, 0x090,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2_sample", "mmc2",
> +                      0x090, 20, 3, 0);
> +static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2_output", "mmc2",
> +                      0x090, 8, 3, 0);
> +
> +static const char * const ts_parents[] = { "osc24M", "pll-periph0", };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 1,        /* mux */

The mux is 4 bits wide with only 2 valid parents.

> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static const char * const ce_parents[] = { "osc24M", "pll-periph0",
> +                                          "pll-periph1" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x09c,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static const char * const spi0_parents[] = { "osc24M", "pll-periph0",
> +                                            "pll-periph1" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", spi0_parents, 0x0a0,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static const char * const spi1_parents[] = { "osc24M", "pll-periph0",
> +                                            "pll-periph1" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", spi1_parents, 0x0a4,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static const char * const i2s0_parents[] = { "pll-audio-8x", "pll-audio-4x",
> +                                            "pll-audio-2x" , "pll-audio" };
> +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s0_parents,
> +                              0x0b0, 16, 2, BIT(31), 0);
> +
> +static const char * const i2s1_parents[] = { "pll-audio-8x", "pll-audio-4x",
> +                                            "pll-audio-2x" , "pll-audio" };
> +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s1_parents,
> +                              0x0b4, 16, 2, BIT(31), 0);
> +
> +static const char * const i2s2_parents[] = { "pll-audio-8x", "pll-audio-4x",
> +                                            "pll-audio-2x" , "pll-audio" };
> +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s2_parents,
> +                              0x0b8, 16, 2, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
> +                            0x0c0, 0, 4, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE(usb_phy0_clk,    "usb-phy0",     "osc24M",
> +                     0x0cc, BIT(8), 0);
> +static SUNXI_CCU_GATE(usb_phy1_clk,    "usb-phy1",     "osc24M",
> +                     0x0cc, BIT(9), 0);
> +static SUNXI_CCU_GATE(usb_phy2_clk,    "usb-phy2",     "osc24M",
> +                     0x0cc, BIT(10), 0);
> +static SUNXI_CCU_GATE(usb_phy3_clk,    "usb-phy3",     "osc24M",
> +                     0x0cc, BIT(11), 0);
> +static SUNXI_CCU_GATE(usb_ohci0_clk,   "usb-ohci0",    "osc24M",
> +                     0x0cc, BIT(16), 0);
> +static SUNXI_CCU_GATE(usb_ohci1_clk,   "usb-ohci1",    "osc24M",
> +                     0x0cc, BIT(17), 0);
> +static SUNXI_CCU_GATE(usb_ohci2_clk,   "usb-ohci2",    "osc24M",
> +                     0x0cc, BIT(18), 0);
> +static SUNXI_CCU_GATE(usb_ohci3_clk,   "usb-ohci3",    "osc24M",
> +                     0x0cc, BIT(19), 0);
> +
> +static const char * const dram_parents[] = { "pll-ddr", "pll-periph0-2x" };
> +static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents,
> +                           0x0f4, 0, 4, 20, 1, 0);

Mux is 2 bits wide. Also need an update bit setting for this clock.
(or mark it read-only?)

> +
> +static SUNXI_CCU_GATE(dram_ve_clk,     "dram-ve",      "dram",
> +                     0x100, BIT(0), 0);
> +static SUNXI_CCU_GATE(dram_csi_clk,    "dram-csi",     "dram",
> +                     0x100, BIT(1), 0);
> +static SUNXI_CCU_GATE(dram_deinterlace_clk,    "dram-deinterlace",     "dram",
> +                     0x100, BIT(2), 0);
> +static SUNXI_CCU_GATE(dram_ts_clk,     "dram-ts",      "dram",
> +                     0x100, BIT(3), 0);
> +
> +static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
> +                                0x104, 0, 4, 24, 1, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_GATE(tcon_clk, "tcon", "pll-video",
> +                            0x118, 0, 4, BIT(31), 0);
> +
> +static const char * const tve_parents[] = { "pll-de", "pll-periph1" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(tve_clk, "tve", tve_parents,
> +                                0x120, 0, 4, 24, 1, BIT(31), 0);
> +
> +static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents,
> +                                0x124, 0, 4, 24, 1, BIT(31), 0);

Mux is 3 bits wide for DE, TCON, TVE, and DEINTERLACE clocks.

> +
> +static SUNXI_CCU_GATE(csi_misc_clk,    "csi-misc",     "osc24M",
> +                     0x130, BIT(31), 0);
> +
> +static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents,
> +                                0x134, 16, 4, 24, 1, BIT(31), 0);

Mux is 3 bits wide.

> +
> +static const char * const csi_mclk_parents[] = { "osc24M", "pll-video", "pll-periph0" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents,
> +                                0x134, 0, 5, 8, 2, BIT(15), 0);

Same here.

> +
> +static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve",
> +                            0x13c, 16, 3, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE(ac_dig_clk,      "ac-dig",       "pll-audio",
> +                     0x140, BIT(31), 0);
> +static SUNXI_CCU_GATE(avs_clk,         "avs",          "osc24M",
> +                     0x144, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_GATE(hdmi_clk, "hdmi", "pll-video",
> +                            0x150, 0, 4, BIT(31), 0);

2 bit mux?

> +
> +static SUNXI_CCU_GATE(hdmi_ddc_clk,    "hdmi-ddc",     "osc24M",
> +                     0x154, BIT(31), 0);
> +
> +static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x", "pll-ddr" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
> +                                0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL);
> +
> +static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu",
> +                            0x1a0, 0, 3, BIT(31), 0);
> +
> +static struct ccu_common *sun8i_h3_ccu_clks[] = {
> +       [CLK_PLL_CPUX]          = &pll_cpux_clk.common,
> +       [CLK_PLL_AUDIO_BASE]    = &pll_audio_base_clk.common,
> +       [CLK_PLL_AUDIO]         = &pll_audio_clk.common,
> +       [CLK_PLL_AUDIO_2X]      = &pll_audio_2x_clk.common,
> +       [CLK_PLL_AUDIO_4X]      = &pll_audio_4x_clk.common,
> +       [CLK_PLL_AUDIO_8X]      = &pll_audio_8x_clk.common,
> +       [CLK_PLL_VIDEO]         = &pll_video_clk.common,
> +       [CLK_PLL_VE]            = &pll_ve_clk.common,
> +       [CLK_PLL_DDR]           = &pll_ddr_clk.common,
> +       [CLK_PLL_PERIPH0]       = &pll_periph0_clk.common,
> +       [CLK_PLL_PERIPH0_2X]    = &pll_periph0_2x_clk.common,
> +       [CLK_PLL_GPU]           = &pll_gpu_clk.common,
> +       [CLK_PLL_PERIPH1]       = &pll_periph1_clk.common,
> +       [CLK_PLL_DE]            = &pll_de_clk.common,
> +       [CLK_CPUX]              = &cpux_clk.common,
> +       [CLK_AXI]               = &axi_clk.common,
> +       [CLK_AHB1]              = &ahb1_clk.common,
> +       [CLK_APB1]              = &apb1_clk.common,
> +       [CLK_APB2]              = &apb2_clk.common,
> +       [CLK_AHB2]              = &ahb2_clk.common,
> +       [CLK_BUS_CE]            = &bus_ce_clk.common,
> +       [CLK_BUS_DMA]           = &bus_dma_clk.common,
> +       [CLK_BUS_MMC0]          = &bus_mmc0_clk.common,
> +       [CLK_BUS_MMC1]          = &bus_mmc1_clk.common,
> +       [CLK_BUS_MMC2]          = &bus_mmc2_clk.common,
> +       [CLK_BUS_NAND]          = &bus_nand_clk.common,
> +       [CLK_BUS_DRAM]          = &bus_dram_clk.common,
> +       [CLK_BUS_EMAC]          = &bus_emac_clk.common,
> +       [CLK_BUS_TS]            = &bus_ts_clk.common,
> +       [CLK_BUS_HSTIMER]       = &bus_hstimer_clk.common,
> +       [CLK_BUS_SPI0]          = &bus_spi0_clk.common,
> +       [CLK_BUS_SPI1]          = &bus_spi1_clk.common,
> +       [CLK_BUS_OTG]           = &bus_otg_clk.common,
> +       [CLK_BUS_EHCI0]         = &bus_ehci0_clk.common,
> +       [CLK_BUS_EHCI1]         = &bus_ehci1_clk.common,
> +       [CLK_BUS_EHCI2]         = &bus_ehci2_clk.common,
> +       [CLK_BUS_EHCI3]         = &bus_ehci3_clk.common,
> +       [CLK_BUS_OHCI0]         = &bus_ohci0_clk.common,
> +       [CLK_BUS_OHCI1]         = &bus_ohci1_clk.common,
> +       [CLK_BUS_OHCI2]         = &bus_ohci2_clk.common,
> +       [CLK_BUS_OHCI3]         = &bus_ohci3_clk.common,
> +       [CLK_BUS_VE]            = &bus_ve_clk.common,
> +       [CLK_BUS_TCON0]         = &bus_tcon0_clk.common,
> +       [CLK_BUS_TCON1]         = &bus_tcon1_clk.common,
> +       [CLK_BUS_DEINTERLACE]   = &bus_deinterlace_clk.common,
> +       [CLK_BUS_CSI]           = &bus_csi_clk.common,
> +       [CLK_BUS_TVE]           = &bus_tve_clk.common,
> +       [CLK_BUS_HDMI]          = &bus_hdmi_clk.common,
> +       [CLK_BUS_DE]            = &bus_de_clk.common,
> +       [CLK_BUS_GPU]           = &bus_gpu_clk.common,
> +       [CLK_BUS_MSGBOX]        = &bus_msgbox_clk.common,
> +       [CLK_BUS_SPINLOCK]      = &bus_spinlock_clk.common,
> +       [CLK_BUS_CODEC]         = &bus_codec_clk.common,
> +       [CLK_BUS_SPDIF]         = &bus_spdif_clk.common,
> +       [CLK_BUS_PIO]           = &bus_pio_clk.common,
> +       [CLK_BUS_THS]           = &bus_ths_clk.common,
> +       [CLK_BUS_I2S0]          = &bus_i2s0_clk.common,
> +       [CLK_BUS_I2S1]          = &bus_i2s1_clk.common,
> +       [CLK_BUS_I2S2]          = &bus_i2s2_clk.common,
> +       [CLK_BUS_I2C0]          = &bus_i2c0_clk.common,
> +       [CLK_BUS_I2C1]          = &bus_i2c1_clk.common,
> +       [CLK_BUS_I2C2]          = &bus_i2c2_clk.common,
> +       [CLK_BUS_UART0]         = &bus_uart0_clk.common,
> +       [CLK_BUS_UART1]         = &bus_uart1_clk.common,
> +       [CLK_BUS_UART2]         = &bus_uart2_clk.common,
> +       [CLK_BUS_UART3]         = &bus_uart3_clk.common,
> +       [CLK_BUS_SCR]           = &bus_scr_clk.common,
> +       [CLK_BUS_EPHY]          = &bus_ephy_clk.common,
> +       [CLK_BUS_DBG]           = &bus_dbg_clk.common,
> +       [CLK_THS]               = &ths_clk.common,
> +       [CLK_NAND]              = &nand_clk.common,
> +       [CLK_MMC0]              = &mmc0_clk.common,
> +       [CLK_MMC0_SAMPLE]       = &mmc0_sample_clk.common,
> +       [CLK_MMC0_OUTPUT]       = &mmc0_output_clk.common,
> +       [CLK_MMC1]              = &mmc1_clk.common,
> +       [CLK_MMC1_SAMPLE]       = &mmc1_sample_clk.common,
> +       [CLK_MMC1_OUTPUT]       = &mmc1_output_clk.common,
> +       [CLK_MMC2]              = &mmc2_clk.common,
> +       [CLK_MMC2_SAMPLE]       = &mmc2_sample_clk.common,
> +       [CLK_MMC2_OUTPUT]       = &mmc2_output_clk.common,
> +       [CLK_TS]                = &ts_clk.common,
> +       [CLK_CE]                = &ce_clk.common,
> +       [CLK_SPI0]              = &spi0_clk.common,
> +       [CLK_SPI1]              = &spi1_clk.common,
> +       [CLK_I2S0]              = &i2s0_clk.common,
> +       [CLK_I2S1]              = &i2s1_clk.common,
> +       [CLK_I2S2]              = &i2s2_clk.common,
> +       [CLK_SPDIF]             = &spdif_clk.common,
> +       [CLK_USB_PHY0]          = &usb_phy0_clk.common,
> +       [CLK_USB_PHY1]          = &usb_phy1_clk.common,
> +       [CLK_USB_PHY2]          = &usb_phy2_clk.common,
> +       [CLK_USB_PHY3]          = &usb_phy3_clk.common,
> +       [CLK_USB_OHCI0]         = &usb_ohci0_clk.common,
> +       [CLK_USB_OHCI1]         = &usb_ohci1_clk.common,
> +       [CLK_USB_OHCI2]         = &usb_ohci2_clk.common,
> +       [CLK_USB_OHCI3]         = &usb_ohci3_clk.common,
> +       [CLK_DRAM]              = &dram_clk.common,
> +       [CLK_DRAM_VE]           = &dram_ve_clk.common,
> +       [CLK_DRAM_CSI]          = &dram_csi_clk.common,
> +       [CLK_DRAM_DEINTERLACE]  = &dram_deinterlace_clk.common,
> +       [CLK_DRAM_TS]           = &dram_ts_clk.common,
> +       [CLK_DE]                = &de_clk.common,
> +       [CLK_TCON0]             = &tcon_clk.common,
> +       [CLK_TVE]               = &tve_clk.common,
> +       [CLK_DEINTERLACE]       = &deinterlace_clk.common,
> +       [CLK_CSI_MISC]          = &csi_misc_clk.common,
> +       [CLK_CSI_SCLK]          = &csi_sclk_clk.common,
> +       [CLK_CSI_MCLK]          = &csi_mclk_clk.common,
> +       [CLK_VE]                = &ve_clk.common,
> +       [CLK_AC_DIG]            = &ac_dig_clk.common,
> +       [CLK_AVS]               = &avs_clk.common,
> +       [CLK_HDMI]              = &hdmi_clk.common,
> +       [CLK_HDMI_DDC]          = &hdmi_ddc_clk.common,
> +       [CLK_MBUS]              = &mbus_clk.common,
> +       [CLK_GPU]               = &gpu_clk.common,
> +};
> +
> +static struct ccu_reset_map sun8i_h3_ccu_resets[] = {
> +       [RST_USB_PHY0]          =  { 0x0cc, BIT(0) },
> +       [RST_USB_PHY1]          =  { 0x0cc, BIT(1) },
> +       [RST_USB_PHY2]          =  { 0x0cc, BIT(2) },
> +       [RST_USB_PHY3]          =  { 0x0cc, BIT(3) },
> +
> +       [RST_MBUS]              =  { 0x0fc, BIT(31) },
> +
> +       [RST_BUS_CE]            =  { 0x2c0, BIT(5) },
> +       [RST_BUS_DMA]           =  { 0x2c0, BIT(6) },
> +       [RST_BUS_MMC0]          =  { 0x2c0, BIT(8) },
> +       [RST_BUS_MMC1]          =  { 0x2c0, BIT(9) },
> +       [RST_BUS_MMC2]          =  { 0x2c0, BIT(10) },
> +       [RST_BUS_NAND]          =  { 0x2c0, BIT(13) },
> +       [RST_BUS_DRAM]          =  { 0x2c0, BIT(14) },
> +       [RST_BUS_EMAC]          =  { 0x2c0, BIT(17) },
> +       [RST_BUS_TS]            =  { 0x2c0, BIT(18) },
> +       [RST_BUS_HSTIMER]       =  { 0x2c0, BIT(19) },
> +       [RST_BUS_SPI0]          =  { 0x2c0, BIT(20) },
> +       [RST_BUS_SPI1]          =  { 0x2c0, BIT(21) },
> +       [RST_BUS_OTG]           =  { 0x2c0, BIT(23) },
> +       [RST_BUS_EHCI0]         =  { 0x2c0, BIT(24) },
> +       [RST_BUS_EHCI1]         =  { 0x2c0, BIT(25) },
> +       [RST_BUS_EHCI2]         =  { 0x2c0, BIT(26) },
> +       [RST_BUS_EHCI3]         =  { 0x2c0, BIT(27) },
> +       [RST_BUS_OHCI0]         =  { 0x2c0, BIT(28) },
> +       [RST_BUS_OHCI1]         =  { 0x2c0, BIT(29) },
> +       [RST_BUS_OHCI2]         =  { 0x2c0, BIT(30) },
> +       [RST_BUS_OHCI3]         =  { 0x2c0, BIT(31) },
> +
> +       [RST_BUS_VE]            =  { 0x2c4, BIT(0) },
> +       [RST_BUS_TCON0]         =  { 0x2c4, BIT(3) },
> +       [RST_BUS_TCON1]         =  { 0x2c4, BIT(4) },
> +       [RST_BUS_DEINTERLACE]   =  { 0x2c4, BIT(5) },
> +       [RST_BUS_CSI]           =  { 0x2c4, BIT(8) },
> +       [RST_BUS_TVE]           =  { 0x2c4, BIT(9) },
> +       [RST_BUS_HDMI0]         =  { 0x2c4, BIT(10) },
> +       [RST_BUS_HDMI1]         =  { 0x2c4, BIT(11) },
> +       [RST_BUS_DE]            =  { 0x2c4, BIT(12) },
> +       [RST_BUS_GPU]           =  { 0x2c4, BIT(20) },
> +       [RST_BUS_MSGBOX]        =  { 0x2c4, BIT(21) },
> +       [RST_BUS_SPINLOCK]      =  { 0x2c4, BIT(22) },
> +       [RST_BUS_DBG]           =  { 0x2c4, BIT(31) },
> +
> +       [RST_BUS_EPHY]          =  { 0x2c8, BIT(2) },
> +
> +       [RST_BUS_CODEC]         =  { 0x2d0, BIT(0) },
> +       [RST_BUS_SPDIF]         =  { 0x2d0, BIT(1) },
> +       [RST_BUS_THS]           =  { 0x2d0, BIT(8) },
> +       [RST_BUS_I2S0]          =  { 0x2d0, BIT(12) },
> +       [RST_BUS_I2S1]          =  { 0x2d0, BIT(13) },
> +       [RST_BUS_I2S2]          =  { 0x2d0, BIT(14) },
> +
> +       [RST_BUS_I2C0]          =  { 0x2d4, BIT(0) },
> +       [RST_BUS_I2C1]          =  { 0x2d4, BIT(1) },
> +       [RST_BUS_I2C2]          =  { 0x2d4, BIT(2) },
> +       [RST_BUS_UART0]         =  { 0x2d4, BIT(16) },
> +       [RST_BUS_UART1]         =  { 0x2d4, BIT(17) },
> +       [RST_BUS_UART2]         =  { 0x2d4, BIT(18) },
> +       [RST_BUS_UART3]         =  { 0x2d4, BIT(19) },
> +       [RST_BUS_SCR]           =  { 0x2d4, BIT(20) },
> +};
> +
> +static const struct sunxi_ccu_desc sun8i_h3_ccu_desc = {
> +       .clks           = sun8i_h3_ccu_clks,
> +       .num_clks       = ARRAY_SIZE(sun8i_h3_ccu_clks),
> +
> +       .resets         = sun8i_h3_ccu_resets,
> +       .num_resets     = ARRAY_SIZE(sun8i_h3_ccu_resets),
> +};
> +
> +static void __init sun8i_h3_ccu_setup(struct device_node *node)
> +{
> +       sunxi_ccu_probe(node, &sun8i_h3_ccu_desc);
> +}
> +CLK_OF_DECLARE(sun8i_h3_ccu, "allwinner,sun8i-h3-ccu",
> +              sun8i_h3_ccu_setup);
> diff --git a/include/dt-bindings/clock/sun8i-h3.h b/include/dt-bindings/clock/sun8i-h3.h
> new file mode 100644
> index 000000000000..96eced56e7a2
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun8i-h3.h
> @@ -0,0 +1,162 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + *  a) This file is free software; you can redistribute it and/or
> + *     modify it under the terms of the GNU General Public License as
> + *     published by the Free Software Foundation; either version 2 of the
> + *     License, or (at your option) any later version.
> + *
> + *     This file is distributed in the hope that it will be useful,
> + *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *     GNU General Public License for more details.
> + *
> + * Or, alternatively,
> + *
> + *  b) Permission is hereby granted, free of charge, to any person
> + *     obtaining a copy of this software and associated documentation
> + *     files (the "Software"), to deal in the Software without
> + *     restriction, including without limitation the rights to use,
> + *     copy, modify, merge, publish, distribute, sublicense, and/or
> + *     sell copies of the Software, and to permit persons to whom the
> + *     Software is furnished to do so, subject to the following
> + *     conditions:
> + *
> + *     The above copyright notice and this permission notice shall be
> + *     included in all copies or substantial portions of the Software.
> + *
> + *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + *     OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_SUN8I_H3_H_
> +#define _DT_BINDINGS_CLK_SUN8I_H3_H_
> +
> +#define CLK_PLL_CPUX           0
> +#define CLK_PLL_AUDIO_BASE     1
> +#define CLK_PLL_AUDIO          2
> +#define CLK_PLL_AUDIO_2X       3
> +#define CLK_PLL_AUDIO_4X       4
> +#define CLK_PLL_AUDIO_8X       5
> +#define CLK_PLL_VIDEO          6
> +#define CLK_PLL_VE             7
> +#define CLK_PLL_DDR            8
> +#define CLK_PLL_PERIPH0                9
> +#define CLK_PLL_PERIPH0_2X     10
> +#define CLK_PLL_GPU            11
> +#define CLK_PLL_PERIPH1                12
> +#define CLK_PLL_DE             13
> +#define CLK_CPUX               14
> +#define CLK_AXI                        15
> +#define CLK_AHB1               16
> +#define CLK_APB1               17
> +#define CLK_APB2               18
> +#define CLK_AHB2               19
> +#define CLK_BUS_CE             20
> +#define CLK_BUS_DMA            21
> +#define CLK_BUS_MMC0           22
> +#define CLK_BUS_MMC1           23
> +#define CLK_BUS_MMC2           24
> +#define CLK_BUS_NAND           25
> +#define CLK_BUS_DRAM           26
> +#define CLK_BUS_EMAC           27
> +#define CLK_BUS_TS             28
> +#define CLK_BUS_HSTIMER                29
> +#define CLK_BUS_SPI0           30
> +#define CLK_BUS_SPI1           31
> +#define CLK_BUS_OTG            32
> +#define CLK_BUS_EHCI0          33
> +#define CLK_BUS_EHCI1          34
> +#define CLK_BUS_EHCI2          35
> +#define CLK_BUS_EHCI3          36
> +#define CLK_BUS_OHCI0          37
> +#define CLK_BUS_OHCI1          38
> +#define CLK_BUS_OHCI2          39
> +#define CLK_BUS_OHCI3          40
> +#define CLK_BUS_VE             41
> +#define CLK_BUS_TCON0          42
> +#define CLK_BUS_TCON1          43
> +#define CLK_BUS_DEINTERLACE    44
> +#define CLK_BUS_CSI            45
> +#define CLK_BUS_TVE            46
> +#define CLK_BUS_HDMI           47
> +#define CLK_BUS_DE             48
> +#define CLK_BUS_GPU            49
> +#define CLK_BUS_MSGBOX         50
> +#define CLK_BUS_SPINLOCK       51
> +#define CLK_BUS_CODEC          52
> +#define CLK_BUS_SPDIF          53
> +#define CLK_BUS_PIO            54
> +#define CLK_BUS_THS            55
> +#define CLK_BUS_I2S0           56
> +#define CLK_BUS_I2S1           57
> +#define CLK_BUS_I2S2           58
> +#define CLK_BUS_I2C0           59
> +#define CLK_BUS_I2C1           60
> +#define CLK_BUS_I2C2           61
> +#define CLK_BUS_UART0          62
> +#define CLK_BUS_UART1          63
> +#define CLK_BUS_UART2          64
> +#define CLK_BUS_UART3          65
> +#define CLK_BUS_SCR            66
> +#define CLK_BUS_EPHY           67
> +#define CLK_BUS_DBG            68
> +#define CLK_THS                        69
> +#define CLK_NAND               70
> +#define CLK_MMC0               71
> +#define CLK_MMC0_SAMPLE                72
> +#define CLK_MMC0_OUTPUT                73
> +#define CLK_MMC1               74
> +#define CLK_MMC1_SAMPLE                75
> +#define CLK_MMC1_OUTPUT                76
> +#define CLK_MMC2               77
> +#define CLK_MMC2_SAMPLE                78
> +#define CLK_MMC2_OUTPUT                79
> +#define CLK_TS                 80
> +#define CLK_CE                 81
> +#define CLK_SPI0               82
> +#define CLK_SPI1               83
> +#define CLK_I2S0               84
> +#define CLK_I2S1               85
> +#define CLK_I2S2               86
> +#define CLK_SPDIF              87
> +#define CLK_USB_PHY0           88
> +#define CLK_USB_PHY1           89
> +#define CLK_USB_PHY2           90
> +#define CLK_USB_PHY3           91
> +#define CLK_USB_OHCI0          92
> +#define CLK_USB_OHCI1          93
> +#define CLK_USB_OHCI2          94
> +#define CLK_USB_OHCI3          95
> +#define CLK_DRAM               96
> +#define CLK_DRAM_VE            97
> +#define CLK_DRAM_CSI           98
> +#define CLK_DRAM_DEINTERLACE   99
> +#define CLK_DRAM_TS            100
> +#define CLK_DE                 101
> +#define CLK_TCON0              102
> +#define CLK_TVE                        103
> +#define CLK_DEINTERLACE                104
> +#define CLK_CSI_MISC           105
> +#define CLK_CSI_SCLK           106
> +#define CLK_CSI_MCLK           107
> +#define CLK_VE                 108
> +#define CLK_AC_DIG             109
> +#define CLK_AVS                        110
> +#define CLK_HDMI               111
> +#define CLK_HDMI_DDC           112
> +#define CLK_MBUS               113
> +#define CLK_GPU                        114
> +
> +#endif /* _DT_BINDINGS_CLK_SUN8I_H3_H_ */
> diff --git a/include/dt-bindings/reset/sun8i-h3.h b/include/dt-bindings/reset/sun8i-h3.h
> new file mode 100644
> index 000000000000..6b7af80c26ec
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun8i-h3.h
> @@ -0,0 +1,103 @@
> +/*
> + * Copyright (C) 2016 Maxime Ripard <maxime.ripard at free-electrons.com>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + *  a) This file is free software; you can redistribute it and/or
> + *     modify it under the terms of the GNU General Public License as
> + *     published by the Free Software Foundation; either version 2 of the
> + *     License, or (at your option) any later version.
> + *
> + *     This file is distributed in the hope that it will be useful,
> + *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *     GNU General Public License for more details.
> + *
> + * Or, alternatively,
> + *
> + *  b) Permission is hereby granted, free of charge, to any person
> + *     obtaining a copy of this software and associated documentation
> + *     files (the "Software"), to deal in the Software without
> + *     restriction, including without limitation the rights to use,
> + *     copy, modify, merge, publish, distribute, sublicense, and/or
> + *     sell copies of the Software, and to permit persons to whom the
> + *     Software is furnished to do so, subject to the following
> + *     conditions:
> + *
> + *     The above copyright notice and this permission notice shall be
> + *     included in all copies or substantial portions of the Software.
> + *
> + *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + *     OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef _DT_BINDINGS_RST_SUN8I_H3_H_
> +#define _DT_BINDINGS_RST_SUN8I_H3_H_
> +
> +#define RST_USB_PHY0           0
> +#define RST_USB_PHY1           1
> +#define RST_USB_PHY2           2
> +#define RST_USB_PHY3           3
> +
> +#define RST_MBUS               4
> +
> +#define RST_BUS_CE             5
> +#define RST_BUS_DMA            6
> +#define RST_BUS_MMC0           7
> +#define RST_BUS_MMC1           8
> +#define RST_BUS_MMC2           9
> +#define RST_BUS_NAND           10
> +#define RST_BUS_DRAM           11
> +#define RST_BUS_EMAC           12
> +#define RST_BUS_TS             13
> +#define RST_BUS_HSTIMER                14
> +#define RST_BUS_SPI0           15
> +#define RST_BUS_SPI1           16
> +#define RST_BUS_OTG            17
> +#define RST_BUS_EHCI0          18
> +#define RST_BUS_EHCI1          19
> +#define RST_BUS_EHCI2          20
> +#define RST_BUS_EHCI3          21
> +#define RST_BUS_OHCI0          22
> +#define RST_BUS_OHCI1          23
> +#define RST_BUS_OHCI2          24
> +#define RST_BUS_OHCI3          25
> +#define RST_BUS_VE             26
> +#define RST_BUS_TCON0          27
> +#define RST_BUS_TCON1          28
> +#define RST_BUS_DEINTERLACE    29
> +#define RST_BUS_CSI            30
> +#define RST_BUS_TVE            31
> +#define RST_BUS_HDMI0          32
> +#define RST_BUS_HDMI1          33
> +#define RST_BUS_DE             34
> +#define RST_BUS_GPU            35
> +#define RST_BUS_MSGBOX         36
> +#define RST_BUS_SPINLOCK       37
> +#define RST_BUS_DBG            38
> +#define RST_BUS_EPHY           39
> +#define RST_BUS_CODEC          40
> +#define RST_BUS_SPDIF          41
> +#define RST_BUS_THS            42
> +#define RST_BUS_I2S0           43
> +#define RST_BUS_I2S1           44
> +#define RST_BUS_I2S2           45
> +#define RST_BUS_I2C0           46
> +#define RST_BUS_I2C1           47
> +#define RST_BUS_I2C2           48
> +#define RST_BUS_UART0          49
> +#define RST_BUS_UART1          50
> +#define RST_BUS_UART2          51
> +#define RST_BUS_UART3          52
> +#define RST_BUS_SCR            53
> +
> +#endif /* _DT_BINDINGS_RST_SUN8I_H3_H_ */
> --
> 2.8.2
>

The rest looks good. Sorry it took so long.

About the mux widths, I prefer to have the full width, even if only the first
few values are valid. It would prevent someone playing with the registers (or
bad code) and the values sticking, before the kernel loads. Then the kernel
won't think that it set a valid parent, but the high bit was not cleared, and
whatever peripheral ended up not working.


Regards
ChenYu


From peter.senna at collabora.com  Mon May 30 09:39:42 2016
From: peter.senna at collabora.com (Peter Senna Tschudin)
Date: Mon, 30 May 2016 18:39:42 +0200
Subject: [PATCH 2/5] arm/dts/imx6q-b850v3: Configure IPU assignment order
In-Reply-To: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
References: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
Message-ID: <1464626385-19253-3-git-send-email-peter.senna@collabora.com>

Configure the IPU assignment order to assign one IPU per external
display. A single IPU can drive multiple external displays but there are
resolution restrictions. After this patch the GPU is capalbe of driving two
Full-HD monitors.

Signed-off-by: Peter Senna Tschudin <peter.senna at collabora.com>
---
 arch/arm/boot/dts/imx6q-b850v3.dts | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/imx6q-b850v3.dts b/arch/arm/boot/dts/imx6q-b850v3.dts
index 167f744..88a70de 100644
--- a/arch/arm/boot/dts/imx6q-b850v3.dts
+++ b/arch/arm/boot/dts/imx6q-b850v3.dts
@@ -51,6 +51,11 @@
 	chosen {
 		stdout-path = &uart3;
 	};
+
+	display-subsystem {
+		compatible = "fsl,imx-display-subsystem";
+		ports = <&ipu1_di0>, <&ipu2_di0>, <&ipu1_di1>, <&ipu2_di1>;
+	};
 };
 
 &clks {
-- 
2.5.5



From peter.senna at collabora.com  Mon May 30 09:39:41 2016
From: peter.senna at collabora.com (Peter Senna Tschudin)
Date: Mon, 30 May 2016 18:39:41 +0200
Subject: [PATCH 1/5] drm/imx-ldb: Add support to drm-bridge
In-Reply-To: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
References: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
Message-ID: <1464626385-19253-2-git-send-email-peter.senna@collabora.com>

Add support to attach a drm_bridge to imx-ldb in addition to
existing support to attach a LVDS panel.

Signed-off-by: Peter Senna Tschudin <peter.senna at collabora.com>
---
 drivers/gpu/drm/imx/imx-ldb.c | 75 +++++++++++++++++++++++++++++++------------
 1 file changed, 54 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index a58eee5..7233a81 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -57,7 +57,11 @@ struct imx_ldb_channel {
 	struct imx_ldb *ldb;
 	struct drm_connector connector;
 	struct drm_encoder encoder;
+
+	/* Defines what is connected to the ldb, only one at a time */
 	struct drm_panel *panel;
+	struct drm_bridge *ext_bridge;
+
 	struct device_node *child;
 	int chno;
 	void *edid;
@@ -295,6 +299,10 @@ static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
 	}
 }
 
+static void imx_ldb_encoder_enable(struct drm_encoder *encoder)
+{
+}
+
 static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
 {
 	struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
@@ -373,6 +381,7 @@ static const struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = {
 	.prepare = imx_ldb_encoder_prepare,
 	.commit = imx_ldb_encoder_commit,
 	.mode_set = imx_ldb_encoder_mode_set,
+	.enable = imx_ldb_encoder_enable,
 	.disable = imx_ldb_encoder_disable,
 };
 
@@ -417,16 +426,28 @@ static int imx_ldb_register(struct drm_device *drm,
 	drm_encoder_init(drm, &imx_ldb_ch->encoder, &imx_ldb_encoder_funcs,
 			 DRM_MODE_ENCODER_LVDS, NULL);
 
-	drm_connector_helper_add(&imx_ldb_ch->connector,
-			&imx_ldb_connector_helper_funcs);
-	drm_connector_init(drm, &imx_ldb_ch->connector,
-			   &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
-
-	if (imx_ldb_ch->panel)
+	if (imx_ldb_ch->panel) {
+		drm_connector_helper_add(&imx_ldb_ch->connector,
+				&imx_ldb_connector_helper_funcs);
+		drm_connector_init(drm, &imx_ldb_ch->connector,
+				&imx_ldb_connector_funcs,
+				DRM_MODE_CONNECTOR_LVDS);
 		drm_panel_attach(imx_ldb_ch->panel, &imx_ldb_ch->connector);
 
-	drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
-			&imx_ldb_ch->encoder);
+		drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
+				&imx_ldb_ch->encoder);
+	}
+
+	if (imx_ldb_ch->ext_bridge) {
+		imx_ldb_ch->ext_bridge->encoder = &imx_ldb_ch->encoder;
+
+		imx_ldb_ch->encoder.bridge = imx_ldb_ch->ext_bridge;
+		ret = drm_bridge_attach(drm, imx_ldb_ch->ext_bridge);
+		if (ret) {
+			DRM_ERROR("Failed to initialize bridge with drm\n");
+			return ret;
+		}
+	}
 
 	return 0;
 }
@@ -583,23 +604,35 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 			endpoint = of_get_child_by_name(port, "endpoint");
 			if (endpoint) {
 				remote = of_graph_get_remote_port_parent(endpoint);
-				if (remote)
-					channel->panel = of_drm_find_panel(remote);
-				else
-					return -EPROBE_DEFER;
-				if (!channel->panel) {
-					dev_err(dev, "panel not found: %s\n",
-						remote->full_name);
-					return -EPROBE_DEFER;
+				if (remote) {
+					/* Only one of these two will succeed */
+					channel->panel =
+						of_drm_find_panel(remote);
+
+					channel->ext_bridge =
+						of_drm_find_bridge(remote);
+
+					/*
+					 * If the bridge is compiled as a
+					 * module, it may take some time until
+					 * the bridge driver is available.
+					 * Defer until the bridge driver is
+					 * ready.
+					 */
+					if (!channel->panel &&
+							!channel->ext_bridge)
+						return -EPROBE_DEFER;
 				}
 			}
 		}
 
-		edidp = of_get_property(child, "edid", &channel->edid_len);
-		if (edidp) {
-			channel->edid = kmemdup(edidp, channel->edid_len,
-						GFP_KERNEL);
-		} else if (!channel->panel) {
+		if (channel->panel) {
+			edidp = of_get_property(child, "edid",
+					&channel->edid_len);
+			if (edidp)
+				channel->edid = kmemdup(edidp,
+						channel->edid_len, GFP_KERNEL);
+		} else {
 			ret = of_get_drm_display_mode(child, &channel->mode, 0);
 			if (!ret)
 				channel->mode_valid = 1;
-- 
2.5.5



From peter.senna at collabora.com  Mon May 30 09:39:43 2016
From: peter.senna at collabora.com (Peter Senna Tschudin)
Date: Mon, 30 May 2016 18:39:43 +0200
Subject: [PATCH 3/5] Documentation/devicetree/bindings: Add b850v3_lvds_dp
In-Reply-To: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
References: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
Message-ID: <1464626385-19253-4-git-send-email-peter.senna@collabora.com>

Devicetree bindings documentation for the GE B850v3 LVDS/DP++
display bridge.

Signed-off-by: Peter Senna Tschudin <peter.senna at collabora.com>
---
 .../devicetree/bindings/ge/b850v3_lvds_dp.txt      | 38 ++++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/ge/b850v3_lvds_dp.txt

diff --git a/Documentation/devicetree/bindings/ge/b850v3_lvds_dp.txt b/Documentation/devicetree/bindings/ge/b850v3_lvds_dp.txt
new file mode 100644
index 0000000..32e123a
--- /dev/null
+++ b/Documentation/devicetree/bindings/ge/b850v3_lvds_dp.txt
@@ -0,0 +1,38 @@
+Driver for GE B850v3 LVDS/DP++ display bridge
+
+Required properties:
+  - compatible : should be "ge,b850v3_lvds_dp".
+  - reg : should contain the address used to ack the interrupts.
+  - interrupt-parent : should link to the gpio used as interrupt
+    source on the host.
+  - interrupts : one interrupt should be described here, as in
+    <0 IRQ_TYPE_LEVEL_HIGH>.
+  - edid-reg : should contain the address used to read edid information
+  - port : should describe the vide signal connection between the host
+    and the bridge.
+
+Example:
+
+&mux2_i2c2 {
+	status = "okay";
+	clock-frequency = <100000>;
+
+	b850v3_dp_bridge {
+		compatible = "ge,b850v3_lvds_dp";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg = <0x73>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+
+		edid-reg = <0x72>;
+
+		port at 0 {
+			reg = <0>;
+			b850v3_dp_bridge_in: endpoint {
+				remote-endpoint = <&lvds0_out>;
+			};
+		};
+	};
+};
-- 
2.5.5



From peter.senna at collabora.com  Mon May 30 09:39:40 2016
From: peter.senna at collabora.com (Peter Senna Tschudin)
Date: Mon, 30 May 2016 18:39:40 +0200
Subject: [PATCH 0/5] Add driver for GE B850v3 LVDS/DP++ Bridge
Message-ID: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>

The series adds a driver that creates a drm_bridge and a drm_connector for the
LVDS to DP++ display bridge of the GE B850v3. There are two physical bridges on
the video signal pipeline: a STDP4028(LVDS to DP) and a STDP2690(DP to DP++).
However the physical bridges are automatically configured by the input video
signal, and the driver has no access to the video processing pipeline. The
driver is only needed to read EDID from the STDP2690 and to handle HPD events
from the STDP4028. The driver communicates with both bridges over i2c. The
video signal pipeline is as follows:

  Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output

The patches from the series:
 [1/5] Change the imx-ldb driver to allow attaching a bridge and not only a LVDS
       panel.

 [2/5] Configure the mapping between IPUs and external displays on the dts file
       of the B850v3. Needed so the GPU can drive two Full-HD monitors.

 [3/5] Devicetree documentation for the GE B850v3 LVDS/DP++ Bridge

 [4/5] Add the driver, make changes to MAINTAINERS, Kconfig and Makefile

 [5/5] Make the changes to the B850v3 dts file to enalbe the GE B850v3
       LVDS/DP++ Bridge.

Peter Senna Tschudin (5):
  drm/imx-ldb: Add support to drm-bridge
  dts/imx6q-b850v3: Configure IPU assignment order
  Documentation/devicetree/bindings: b850v3_lvds_dp
  drm/bridge: Add driver for GE B850v3 LVDS/DP++ Bridge
  dts/imx6q-b850v3: Use GE B850v3 LVDS/DP++ Bridge

 .../devicetree/bindings/ge/b850v3_lvds_dp.txt      |  38 ++
 MAINTAINERS                                        |   8 +
 arch/arm/boot/dts/imx6q-b850v3.dts                 |  36 ++
 drivers/gpu/drm/bridge/Kconfig                     |   8 +
 drivers/gpu/drm/bridge/Makefile                    |   1 +
 drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c         | 397 +++++++++++++++++++++
 drivers/gpu/drm/imx/imx-ldb.c                      |  75 ++--
 7 files changed, 542 insertions(+), 21 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/ge/b850v3_lvds_dp.txt
 create mode 100644 drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c

-- 
2.5.5



From peter.senna at collabora.com  Mon May 30 09:39:44 2016
From: peter.senna at collabora.com (Peter Senna Tschudin)
Date: Mon, 30 May 2016 18:39:44 +0200
Subject: [PATCH 4/5] drm/bridge: Add driver for GE B850v3 LVDS/DP++ Bridge
In-Reply-To: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
References: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
Message-ID: <1464626385-19253-5-git-send-email-peter.senna@collabora.com>

This driver creates a drm_bridge and a drm_connector for the LVDS to DP++
display bridge of the GE B850v3(imx6q-b850v3.dts). There are two physical
bridges on the video signal pipeline: a STDP4028(LVDS to DP) and a
STDP2690(DP to DP++). However the physical bridges are automatically
configured by the input video signal, and the driver has no access to
the video processing pipeline. The driver is only needed to read EDID
from the STDP2690 and to handle HPD events from the STDP4028. The driver
communicates with both bridges over i2c. The video signal pipeline is as
follows:

  Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output

Signed-off-by: Peter Senna Tschudin <peter.senna at collabora.com>
---
 MAINTAINERS                                |   8 +
 drivers/gpu/drm/bridge/Kconfig             |   8 +
 drivers/gpu/drm/bridge/Makefile            |   1 +
 drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c | 397 +++++++++++++++++++++++++++++
 4 files changed, 414 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 3273ffa..7bb5e89 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5009,6 +5009,14 @@ W:	https://linuxtv.org
 S:	Maintained
 F:	drivers/media/radio/radio-gemtek*
 
+GENERAL ELECTRIC B850V3 LVDS/DP++ BRIDGE
+M:	Martin Donnelly <martin.donnelly at ge.com>
+M:	Peter Senna Tschudin <peter.senna at collabora.com>
+M:	Martyn Welch <martyn.welch at collabora.co.uk>
+S:	Maintained
+F:	drivers/gpu/drm/bridge/ge_b850v3_dp2.c
+F:	Documentation/devicetree/bindings/ge/b850v3_dp2_bridge.txt
+
 GENERIC GPIO I2C DRIVER
 M:	Haavard Skinnemoen <hskinnemoen at gmail.com>
 S:	Supported
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 8f7423f..e9c32fc 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -52,4 +52,12 @@ config DRM_PARADE_PS8622
 
 source "drivers/gpu/drm/bridge/analogix/Kconfig"
 
+config DRM_GE_B850V3_LVDS_DP
+	tristate "LVDS/DP bridge"
+	depends on OF
+	select DRM_KMS_HELPER
+	select DRM_PANEL
+	---help---
+	  Driver for GE B850v3 DP2 LVDS to DP+ Bridge
+
 endmenu
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 96b13b3..ba2e355 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
 obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
+obj-$(CONFIG_DRM_GE_B850V3_LVDS_DP) += ge_b850v3_lvds_dp.o
diff --git a/drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c b/drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c
new file mode 100644
index 0000000..37a4e7a
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c
@@ -0,0 +1,397 @@
+/*
+ * Driver for GE B850v3 DP display bridge
+
+ * Copyright (c) 2016, Collabora Ltd.
+ * Copyright (c) 2016, General Electric Company
+
+ * 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/>.
+
+ * This driver creates a drm_bridge and a drm_connector for the LVDS to DP++
+ * display bridge of the GE B850v3. There are two physical bridges on the video
+ * signal pipeline: a STDP4028(LVDS to DP) and a STDP2690(DP to DP++). However
+ * the physical bridges are automatically configured by the input video signal,
+ * and the driver has no access to the video processing pipeline. The driver is
+ * only needed to read EDID from the STDP2690 and to handle HPD events from the
+ * STDP4028. The driver communicates with both bridges over i2c. The video
+ * signal pipeline is as follows:
+ *
+ *   Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
+
+ *
+ */
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+#include "drm_edid.h"
+#include "drmP.h"
+
+#define EDID_EXT_BLOCK_CNT 0x7E
+
+#define STDP4028_IRQ_OUT_CONF_REG 0x02
+#define STDP4028_DPTX_IRQ_EN_REG 0x3C
+#define STDP4028_DPTX_IRQ_STS_REG 0x3D
+#define STDP4028_DPTX_STS_REG 0x3E
+
+#define STDP4028_DPTX_DP_IRQ_EN 0x1000
+
+#define STDP4028_DPTX_HOTPLUG_IRQ_EN 0x0400
+#define STDP4028_DPTX_LINK_CH_IRQ_EN 0x2000
+#define STDP4028_DPTX_IRQ_CONFIG \
+		(STDP4028_DPTX_LINK_CH_IRQ_EN | STDP4028_DPTX_HOTPLUG_IRQ_EN)
+
+#define STDP4028_DPTX_HOTPLUG_STS 0x0200
+#define STDP4028_DPTX_LINK_STS 0x1000
+#define STDP4028_CON_STATE_CONNECTED \
+		(STDP4028_DPTX_HOTPLUG_STS | STDP4028_DPTX_LINK_STS)
+
+#define STDP4028_DPTX_HOTPLUG_CH_STS 0x0400
+#define STDP4028_DPTX_LINK_CH_STS 0x2000
+#define STDP4028_DPTX_IRQ_CLEAR \
+		(STDP4028_DPTX_LINK_CH_STS | STDP4028_DPTX_HOTPLUG_CH_STS)
+
+struct ge_b850v3_lvds_dp {
+	struct drm_connector connector;
+	struct drm_bridge bridge;
+	struct i2c_client *ge_b850v3_lvds_dp_i2c;
+	struct i2c_client *edid_i2c;
+	struct edid *edid;
+};
+
+static inline struct ge_b850v3_lvds_dp *
+		bridge_to_ge_b850v3_lvds_dp(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct ge_b850v3_lvds_dp, bridge);
+}
+
+static inline struct ge_b850v3_lvds_dp *
+		connector_to_ge_b850v3_lvds_dp(struct drm_connector *connector)
+{
+	return container_of(connector, struct ge_b850v3_lvds_dp, connector);
+}
+
+static void ge_b850v3_lvds_dp_pre_enable(struct drm_bridge *bridge)
+{
+}
+
+static void ge_b850v3_lvds_dp_enable(struct drm_bridge *bridge)
+{
+}
+
+static void ge_b850v3_lvds_dp_disable(struct drm_bridge *bridge)
+{
+}
+
+static void ge_b850v3_lvds_dp_post_disable(struct drm_bridge *bridge)
+{
+}
+
+u8 *stdp2690_get_edid(struct i2c_client *client)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	unsigned char start = 0x00;
+	unsigned int total_size;
+	u8 *block = kmalloc(EDID_LENGTH, GFP_KERNEL);
+
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= &start,
+		}, {
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= EDID_LENGTH,
+			.buf	= block,
+		}
+	};
+
+	if (!block)
+		return NULL;
+
+	if (i2c_transfer(adapter, msgs, 2) != 2) {
+		DRM_ERROR("Unable to read EDID.\n");
+		goto err;
+	}
+
+	if (!drm_edid_block_valid(block, 0, false, NULL)) {
+		DRM_ERROR("Invalid EDID block\n");
+		goto err;
+	}
+
+	total_size = (block[EDID_EXT_BLOCK_CNT] + 1) * EDID_LENGTH;
+	if (total_size > EDID_LENGTH) {
+		kfree(block);
+		block = kmalloc(total_size, GFP_KERNEL);
+		if (!block)
+			return NULL;
+
+		/* Yes, read the entire buffer, and do not skip the first
+		 * EDID_LENGTH bytes.
+		 */
+		start = 0x00;
+		msgs[1].len = total_size;
+		msgs[1].buf = block;
+
+		if (i2c_transfer(adapter, msgs, 2) != 2) {
+			DRM_ERROR("Unable to read EDID extension blocks.\n");
+			goto err;
+		}
+	}
+
+	return block;
+
+err:
+	kfree(block);
+	return NULL;
+}
+
+static int ge_b850v3_lvds_dp_get_modes(struct drm_connector *connector)
+{
+	struct ge_b850v3_lvds_dp *ptn_bridge;
+	struct i2c_client *client;
+	u8 *block;
+	int num_modes;
+
+	ptn_bridge = connector_to_ge_b850v3_lvds_dp(connector);
+	client = ptn_bridge->edid_i2c;
+
+	block = stdp2690_get_edid(client);
+	ptn_bridge->edid = (struct edid *) block;
+
+	drm_mode_connector_update_edid_property(connector, ptn_bridge->edid);
+	num_modes = drm_add_edid_modes(connector, ptn_bridge->edid);
+
+	return num_modes;
+}
+
+static struct drm_encoder
+*ge_b850v3_lvds_dp_best_encoder(struct drm_connector *connector)
+{
+	struct ge_b850v3_lvds_dp *ptn_bridge =
+		connector_to_ge_b850v3_lvds_dp(connector);
+
+	return ptn_bridge->bridge.encoder;
+}
+
+static const struct
+drm_connector_helper_funcs ge_b850v3_lvds_dp_connector_helper_funcs = {
+	.get_modes = ge_b850v3_lvds_dp_get_modes,
+	.best_encoder = ge_b850v3_lvds_dp_best_encoder,
+};
+
+static enum drm_connector_status ge_b850v3_lvds_dp_detect(
+		struct drm_connector *connector, bool force)
+{
+	struct ge_b850v3_lvds_dp *ptn_bridge =
+			connector_to_ge_b850v3_lvds_dp(connector);
+	struct i2c_client *ge_b850v3_lvds_dp_i2c =
+			ptn_bridge->ge_b850v3_lvds_dp_i2c;
+	s32 link_state;
+
+	link_state = i2c_smbus_read_word_data(ge_b850v3_lvds_dp_i2c,
+			STDP4028_DPTX_STS_REG);
+
+	if (link_state == STDP4028_CON_STATE_CONNECTED)
+		return connector_status_connected;
+
+	if (link_state == 0)
+		return connector_status_disconnected;
+
+	return connector_status_unknown;
+}
+
+static void ge_b850v3_lvds_dp_connector_force(struct drm_connector *connector)
+{
+}
+
+static void ge_b850v3_lvds_dp_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs ge_b850v3_lvds_dp_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = ge_b850v3_lvds_dp_detect,
+	.destroy = ge_b850v3_lvds_dp_connector_destroy,
+	.force = ge_b850v3_lvds_dp_connector_force,
+};
+
+static irqreturn_t ge_b850v3_lvds_dp_irq_handler(int irq, void *dev_id)
+{
+	struct ge_b850v3_lvds_dp *ptn_bridge = dev_id;
+	struct i2c_client *ge_b850v3_lvds_dp_i2c
+			= ptn_bridge->ge_b850v3_lvds_dp_i2c;
+
+	i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
+			STDP4028_DPTX_IRQ_STS_REG, STDP4028_DPTX_IRQ_CLEAR);
+
+	if (ptn_bridge->connector.dev)
+		drm_kms_helper_hotplug_event(ptn_bridge->connector.dev);
+
+	return IRQ_HANDLED;
+
+}
+
+static int ge_b850v3_lvds_dp_attach(struct drm_bridge *bridge)
+{
+	struct ge_b850v3_lvds_dp *ptn_bridge
+			= bridge_to_ge_b850v3_lvds_dp(bridge);
+	struct drm_connector *connector = &ptn_bridge->connector;
+	struct i2c_client *ge_b850v3_lvds_dp_i2c
+			= ptn_bridge->ge_b850v3_lvds_dp_i2c;
+	int ret;
+
+	if (!bridge->encoder) {
+		DRM_ERROR("Parent encoder object not found");
+		return -ENODEV;
+	}
+
+	connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+	drm_connector_helper_add(connector,
+			&ge_b850v3_lvds_dp_connector_helper_funcs);
+
+	ret = drm_connector_init(bridge->dev, connector,
+			&ge_b850v3_lvds_dp_connector_funcs,
+			DRM_MODE_CONNECTOR_DisplayPort);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector with drm\n");
+		return ret;
+	}
+
+	ret = drm_mode_connector_attach_encoder(connector, bridge->encoder);
+	if (ret)
+		return ret;
+
+	drm_bridge_enable(bridge);
+	if (ge_b850v3_lvds_dp_i2c->irq) {
+		drm_helper_hpd_irq_event(connector->dev);
+
+		ret = devm_request_threaded_irq(&ge_b850v3_lvds_dp_i2c->dev,
+				ge_b850v3_lvds_dp_i2c->irq, NULL,
+				ge_b850v3_lvds_dp_irq_handler,
+				IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				"ge_b850v3_lvds_dp", ptn_bridge);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct drm_bridge_funcs ge_b850v3_lvds_dp_funcs = {
+	.pre_enable = ge_b850v3_lvds_dp_pre_enable,
+	.enable = ge_b850v3_lvds_dp_enable,
+	.disable = ge_b850v3_lvds_dp_disable,
+	.post_disable = ge_b850v3_lvds_dp_post_disable,
+	.attach = ge_b850v3_lvds_dp_attach,
+};
+
+static int ge_b850v3_lvds_dp_probe(struct i2c_client *ge_b850v3_lvds_dp_i2c,
+				const struct i2c_device_id *id)
+{
+	struct device *dev = &ge_b850v3_lvds_dp_i2c->dev;
+	struct ge_b850v3_lvds_dp *ptn_bridge;
+
+	int ret;
+	u32 edid_i2c_reg;
+
+	ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL);
+	if (!ptn_bridge)
+		return -ENOMEM;
+
+	ptn_bridge->ge_b850v3_lvds_dp_i2c = ge_b850v3_lvds_dp_i2c;
+	ptn_bridge->bridge.driver_private = ptn_bridge;
+	i2c_set_clientdata(ge_b850v3_lvds_dp_i2c, ptn_bridge);
+
+	ret = of_property_read_u32(dev->of_node, "edid-reg", &edid_i2c_reg);
+	if (ret) {
+		dev_err(dev, "edid-reg not specified, aborting...\n");
+		return -ENODEV;
+	}
+
+	ptn_bridge->edid_i2c = devm_kzalloc(dev,
+			sizeof(struct i2c_client), GFP_KERNEL);
+
+	if (!ptn_bridge->edid_i2c)
+		return -ENOMEM;
+
+	memcpy(ptn_bridge->edid_i2c, ge_b850v3_lvds_dp_i2c,
+			sizeof(struct i2c_client));
+
+	ptn_bridge->edid_i2c->addr = (unsigned short) edid_i2c_reg;
+
+
+	/* Configures the bridge to re-enable interrupts after each ack */
+	i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
+			STDP4028_IRQ_OUT_CONF_REG, STDP4028_DPTX_DP_IRQ_EN);
+	i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
+			STDP4028_DPTX_IRQ_EN_REG, STDP4028_DPTX_IRQ_CONFIG);
+
+	/* Clear pending interrupts since power up. */
+	i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
+			STDP4028_DPTX_IRQ_STS_REG, STDP4028_DPTX_IRQ_CLEAR);
+
+	ptn_bridge->bridge.funcs = &ge_b850v3_lvds_dp_funcs;
+	ptn_bridge->bridge.of_node = dev->of_node;
+	ret = drm_bridge_add(&ptn_bridge->bridge);
+	if (ret) {
+		DRM_ERROR("Failed to add bridge\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ge_b850v3_lvds_dp_remove(struct i2c_client *ge_b850v3_lvds_dp_i2c)
+{
+	struct ge_b850v3_lvds_dp *ptn_bridge =
+		i2c_get_clientdata(ge_b850v3_lvds_dp_i2c);
+
+	drm_bridge_remove(&ptn_bridge->bridge);
+
+	return 0;
+}
+
+static const struct i2c_device_id ge_b850v3_lvds_dp_i2c_table[] = {
+	{"b850v3_lvds_dp", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, ge_b850v3_lvds_dp_i2c_table);
+
+static const struct of_device_id ge_b850v3_lvds_dp_match[] = {
+	{ .compatible = "ge,b850v3_lvds_dp" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ge_b850v3_lvds_dp_match);
+
+static struct i2c_driver ge_b850v3_lvds_dp_driver = {
+	.id_table	= ge_b850v3_lvds_dp_i2c_table,
+	.probe		= ge_b850v3_lvds_dp_probe,
+	.remove		= ge_b850v3_lvds_dp_remove,
+	.driver		= {
+		.name		= "ge,b850v3_lvds_dp",
+		.of_match_table = ge_b850v3_lvds_dp_match,
+	},
+};
+module_i2c_driver(ge_b850v3_lvds_dp_driver);
+
+MODULE_AUTHOR("Peter Senna Tschudin <peter.senna at collabora.com>");
+MODULE_AUTHOR("Martyn Welch <martyn.welch at collabora.co.uk>");
+MODULE_DESCRIPTION("GE LVDS to DP++ bridge)");
+MODULE_LICENSE("GPL v2");
-- 
2.5.5



From peter.senna at collabora.com  Mon May 30 09:39:45 2016
From: peter.senna at collabora.com (Peter Senna Tschudin)
Date: Mon, 30 May 2016 18:39:45 +0200
Subject: [PATCH 5/5] arm/dts/imx6q-b850v3: Use GE B850v3 LVDS/DP++ Bridge
In-Reply-To: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
References: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
Message-ID: <1464626385-19253-6-git-send-email-peter.senna@collabora.com>

Configure the GE B850v3 to use the LVDS/DP++ bridge.

Signed-off-by: Peter Senna Tschudin <peter.senna at collabora.com>
---
 arch/arm/boot/dts/imx6q-b850v3.dts | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm/boot/dts/imx6q-b850v3.dts b/arch/arm/boot/dts/imx6q-b850v3.dts
index 88a70de..d366384 100644
--- a/arch/arm/boot/dts/imx6q-b850v3.dts
+++ b/arch/arm/boot/dts/imx6q-b850v3.dts
@@ -77,6 +77,13 @@
 		fsl,data-mapping = "spwg";
 		fsl,data-width = <24>;
 		status = "okay";
+
+		port at 4 {
+			reg = <4>;
+			lvds0_out: endpoint {
+				remote-endpoint = <&b850v3_lvds_dp_bridge_in>;
+			};
+		};
 	};
 };
 
@@ -147,3 +154,27 @@
 		reg = <0x4a>;
 	};
 };
+
+&mux2_i2c2 {
+	status = "okay";
+	clock-frequency = <100000>;
+
+	b850v3_lvds_dp_bridge {
+		compatible = "ge,b850v3_lvds_dp";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg = <0x73>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+
+		edid-reg = <0x72>;
+
+		port at 0 {
+			reg = <0>;
+			b850v3_lvds_dp_bridge_in: endpoint {
+				remote-endpoint = <&lvds0_out>;
+			};
+		};
+	};
+};
-- 
2.5.5



From nava.manne at xilinx.com  Mon May 30 09:46:38 2016
From: nava.manne at xilinx.com (Nava kishore Manne)
Date: Mon, 30 May 2016 22:16:38 +0530
Subject: [PATCH v4] Axi-usb: Add support for 64-bit addressing.
Message-ID: <1464626798-1334-1-git-send-email-navam@xilinx.com>

This patch updates the driver to support 64-bit DMA addressing.

Signed-off-by: Nava kishore Manne <navam at xilinx.com>
---
Changes for v4:
		-Used boolen property insted of addrwith property in the DT
		 as suggested by Arnd Bergmann.
		-Adopt the DT relevant changes into the driver.

Changes for v3:
                -Added new compatable string for 5.00 IP version as suggested by
                 Arnd Bergmann.
                -Used write_fn() insted of lo_hi_writeq() as suggested by
                 Arnd Bergmann.

Changes for v2:
                -Added dma-ranges property in device tree as suggested by Arnd Bergmann.
                -Modified the driver code based on the xlnx,addrwidth.

 .../devicetree/bindings/usb/udc-xilinx.txt         |  5 ++-
 drivers/usb/gadget/udc/udc-xilinx.c                | 52 +++++++++++++++++++++-
 2 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/udc-xilinx.txt b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
index 47b4e39..d08d972 100644
--- a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
+++ b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
@@ -1,12 +1,14 @@
 Xilinx USB2 device controller
 
 Required properties:
-- compatible		: Should be "xlnx,usb2-device-4.00.a"
+- compatible		: Should be "xlnx,usb2-device-4.00.a" or
+			  "xlnx,usb2-device-5.00"
 - reg			: Physical base address and size of the USB2
 			  device registers map.
 - interrupts		: Should contain single irq line of USB2 device
 			  controller
 - xlnx,has-builtin-dma	: if DMA is included
+- xlnx,has-64bit-dma	: if DMA is included 64-bit addressing support.
 
 Example:
  		axi-usb2-device at 42e00000 {
@@ -14,5 +16,6 @@ Example:
                         interrupts = <0x0 0x39 0x1>;
                         reg = <0x42e00000 0x10000>;
                         xlnx,has-builtin-dma;
+			xlnx,has-64bit-dma;
                 };
 
diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c
index 1cbb0ac..6fb80c6 100644
--- a/drivers/usb/gadget/udc/udc-xilinx.c
+++ b/drivers/usb/gadget/udc/udc-xilinx.c
@@ -47,6 +47,15 @@
 #define XUSB_DMA_LENGTH_OFFSET		0x0210	/* DMA Length Register */
 #define XUSB_DMA_STATUS_OFFSET		0x0214	/* DMA Status Register */
 
+/* DMA source Address Reg for LSB */
+#define XUSB_DMA_DSAR_ADDR_OFFSET_LSB   0x0308
+/* DMA source Address Reg for MSB */
+#define XUSB_DMA_DSAR_ADDR_OFFSET_MSB   0x030C
+/* DMA destination Addr Reg LSB */
+#define XUSB_DMA_DDAR_ADDR_OFFSET_LSB   0x0310
+/* DMA destination Addr Reg MSB */
+#define XUSB_DMA_DDAR_ADDR_OFFSET_MSB   0x0314
+
 /* Endpoint Configuration Space offsets */
 #define XUSB_EP_CFGSTATUS_OFFSET	0x00	/* Endpoint Config Status  */
 #define XUSB_EP_BUF0COUNT_OFFSET	0x08	/* Buffer 0 Count */
@@ -169,6 +178,7 @@ struct xusb_ep {
  * @setup: usb_ctrlrequest structure for control requests
  * @req: pointer to dummy request for get status command
  * @dev: pointer to device structure in gadget
+ * @is_extend_dma: flag indiacting whether the dma is 64-bit support or not.
  * @usb_state: device in suspended state or not
  * @remote_wkp: remote wakeup enabled by host
  * @setupseqtx: tx status
@@ -186,6 +196,7 @@ struct xusb_udc {
 	struct usb_ctrlrequest setup;
 	struct xusb_req *req;
 	struct device *dev;
+	bool is_extend_dma;
 	u32 usb_state;
 	u32 remote_wkp;
 	u32 setupseqtx;
@@ -215,6 +226,20 @@ static const struct usb_endpoint_descriptor config_bulk_out_desc = {
 };
 
 /**
+ * xudc_write64 - write 64bit value to device registers
+ * @ep: pointer to the usb device endpoint structure.
+ * @offset: register offset
+ * @val: data to be written
+ **/
+static void xudc_write64(struct xusb_ep *ep, u32 offset, u64 val)
+{
+	struct xusb_udc *udc = ep->udc;
+
+	udc->write_fn(udc->addr, offset, lower_32_bits(val));
+	udc->write_fn(udc->addr, offset+0x04, upper_32_bits(val));
+}
+
+/**
  * xudc_write32 - little endian write to device registers
  * @addr: base addr of device registers
  * @offset: register offset
@@ -330,8 +355,13 @@ static int xudc_start_dma(struct xusb_ep *ep, dma_addr_t src,
 	 * destination registers and then set the length
 	 * into the DMA length register.
 	 */
-	udc->write_fn(udc->addr, XUSB_DMA_DSAR_ADDR_OFFSET, src);
-	udc->write_fn(udc->addr, XUSB_DMA_DDAR_ADDR_OFFSET, dst);
+	if (udc->is_extend_dma) {
+		xudc_write64(ep, XUSB_DMA_DSAR_ADDR_OFFSET_LSB, src);
+		xudc_write64(ep, XUSB_DMA_DDAR_ADDR_OFFSET_LSB, dst);
+	} else {
+		udc->write_fn(udc->addr, XUSB_DMA_DSAR_ADDR_OFFSET, src);
+		udc->write_fn(udc->addr, XUSB_DMA_DDAR_ADDR_OFFSET, dst);
+	}
 	udc->write_fn(udc->addr, XUSB_DMA_LENGTH_OFFSET, length);
 
 	/*
@@ -2097,6 +2127,23 @@ static int xudc_probe(struct platform_device *pdev)
 
 	udc->dma_enabled = of_property_read_bool(np, "xlnx,has-builtin-dma");
 
+	udc->is_extend_dma = false;
+
+	if (of_device_is_compatible(np, "xlnx,usb2-device-5.00"))
+		udc->is_extend_dma = of_property_read_bool(np,
+						"xlnx,has-64bit-dma");
+
+	/* Set the dma mask bits */
+	if (udc->is_extend_dma)
+		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+	else
+		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+
+	if (ret < 0) {
+		dev_dbg(&pdev->dev, "no usable DMA configuration");
+		goto fail;
+	}
+
 	/* Setup gadget structure */
 	udc->gadget.ops = &xusb_udc_ops;
 	udc->gadget.max_speed = USB_SPEED_HIGH;
@@ -2168,6 +2215,7 @@ static int xudc_remove(struct platform_device *pdev)
 /* Match table for of_platform binding */
 static const struct of_device_id usb_of_match[] = {
 	{ .compatible = "xlnx,usb2-device-4.00.a", },
+	{ .compatible = "xlnx,usb2-device-5.00", },
 	{ /* end of list */ },
 };
 MODULE_DEVICE_TABLE(of, usb_of_match);
-- 
2.1.1



From festevam at gmail.com  Mon May 30 09:49:09 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 30 May 2016 13:49:09 -0300
Subject: [PATCH 2/5] arm/dts/imx6q-b850v3: Configure IPU assignment order
In-Reply-To: <1464626385-19253-3-git-send-email-peter.senna@collabora.com>
References: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
 <1464626385-19253-3-git-send-email-peter.senna@collabora.com>
Message-ID: <CAOMZO5Cek0nNXPCQxE-gXQqX83MAyPy56nmktETDxX3Ls2XZMA@mail.gmail.com>

On Mon, May 30, 2016 at 1:39 PM, Peter Senna Tschudin
<peter.senna at collabora.com> wrote:
> Configure the IPU assignment order to assign one IPU per external
> display. A single IPU can drive multiple external displays but there are
> resolution restrictions. After this patch the GPU is capalbe of driving two

I think you meant "the IPU is capable"


From linux at roeck-us.net  Mon May 30 09:50:34 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Mon, 30 May 2016 09:50:34 -0700
Subject: [PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <1464614948-28247-2-git-send-email-narmstrong@baylibre.com>
References: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
 <1464614948-28247-2-git-send-email-narmstrong@baylibre.com>
Message-ID: <574C6F5A.1010109@roeck-us.net>

On 05/30/2016 06:29 AM, Neil Armstrong wrote:
> Add watchdog specific driver for Amlogic Meson GXBB SoC.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
>   drivers/watchdog/Makefile         |   1 +
>   drivers/watchdog/meson_gxbb_wdt.c | 277 ++++++++++++++++++++++++++++++++++++++
>   2 files changed, 278 insertions(+)
>   create mode 100644 drivers/watchdog/meson_gxbb_wdt.c
>
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index 9bde095..7679d93 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -68,6 +68,7 @@ obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
>   obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
>   obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
>   obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
> +obj-$(CONFIG_MESON_WATCHDOG) += meson_gxbb_wdt.o

I would really prefer a separate configuration option.

>   obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
>   obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
>   obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
> diff --git a/drivers/watchdog/meson_gxbb_wdt.c b/drivers/watchdog/meson_gxbb_wdt.c
> new file mode 100644
> index 0000000..9619c5e
> --- /dev/null
> +++ b/drivers/watchdog/meson_gxbb_wdt.c
> @@ -0,0 +1,277 @@
> +/*
> + * This file is provided under a dual BSD/GPLv2 license.  When using or
> + * redistributing this file, you may do so under either license.
> + *
> + * GPL LICENSE SUMMARY
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Neil Armstrong <narmstrong at baylibre.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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + * The full GNU General Public License is included in this distribution
> + * in the file called COPYING.
> + *
> + * BSD LICENSE
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Neil Armstrong <narmstrong at baylibre.com>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + *   * Redistributions of source code must retain the above copyright
> + *     notice, this list of conditions and the following disclaimer.
> + *   * Redistributions in binary form must reproduce the above copyright
> + *     notice, this list of conditions and the following disclaimer in
> + *     the documentation and/or other materials provided with the
> + *     distribution.
> + *   * Neither the name of Intel Corporation nor the names of its
> + *     contributors may be used to endorse or promote products derived
> + *     from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +#include <linux/err.h>
> +#include <linux/module.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/clk.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <linux/watchdog.h>

Please order include files alphabetically; that simplifies later changes
and helps finding duplicates.

> +
> +#define DEFAULT_TIMEOUT	10	/* seconds */
> +

Sure you want the default timeout to be that low ?

> +#define GXBB_WDT_CTRL_REG			0x0
> +#define GXBB_WDT_CTRL1_REG			0x4
> +#define GXBB_WDT_TCNT_REG			0x8
> +#define GXBB_WDT_RSET_REG			0xc
> +
> +#define GXBB_WDT_CTRL_EE_RESET_NOW		BIT(26)
> +
> +#define GXBB_WDT_CTRL_CLKDIV_EN			BIT(25)
> +#define GXBB_WDT_CTRL_CLK_EN			BIT(24)
> +#define GXBB_WDT_CTRL_IRQ_EN			BIT(23)
> +#define GXBB_WDT_CTRL_EE_RESET			BIT(21)
> +#define GXBB_WDT_CTRL_XTAL_SEL			(0)
> +#define GXBB_WDT_CTRL_CLK81_SEL			BIT(19)
> +#define GXBB_WDT_CTRL_EN			BIT(18)
> +#define GXBB_WDT_CTRL_DIV_MASK			(BIT(18) - 1)
> +
> +#define GXBB_WDT_CTRL1_GPIO_PULSE		BIT(17)
> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_0		BIT(16)
> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_1		(0)
> +#define GXBB_WDT_CTRL1_GPIO_PULSE_CNT		(BIT(16) - 1)
> +
> +#define GXBB_WDT_TCNT_SETUP_MASK		(BIT(16) - 1)
> +#define GXBB_WDT_TCNT_CNT_SHIFT			16
> +
> +struct meson_gxbb_wdt {
> +	void __iomem *reg_base;
> +	struct watchdog_device wdt_dev;
> +	struct clk *clk;
> +};
> +
> +static int meson_gxbb_wdt_start(struct watchdog_device *wdt_dev)
> +{
> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> +
> +	writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) | GXBB_WDT_CTRL_EN,
> +		data->reg_base + GXBB_WDT_CTRL_REG);
> +
> +	return 0;
> +}
> +
> +static int meson_gxbb_wdt_stop(struct watchdog_device *wdt_dev)
> +{
> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> +
> +	writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) & ~GXBB_WDT_CTRL_EN,
> +		data->reg_base + GXBB_WDT_CTRL_REG);

Please align continuation lines with '('.

> +
> +	return 0;
> +}
> +
> +static int meson_gxbb_wdt_ping(struct watchdog_device *wdt_dev)
> +{
> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> +
> +	writel(0, data->reg_base + GXBB_WDT_RSET_REG);
> +
> +	return 0;
> +}
> +
> +static int meson_gxbb_wdt_get_timeout(struct meson_gxbb_wdt *data)
> +{
> +	return (readl(data->reg_base + GXBB_WDT_TCNT_REG) &
> +			GXBB_WDT_TCNT_SETUP_MASK) / 1000;
> +}
> +
Unused function ?

> +static int meson_gxbb_wdt_set_timeout(struct watchdog_device *wdt_dev,
> +				      unsigned int timeout)
> +{
> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> +
> +	meson_gxbb_wdt_ping(wdt_dev);

Is this necessary ? The infrastructure calls it after calling this function.

> +
> +	writel(timeout * 1000, data->reg_base + GXBB_WDT_TCNT_REG);

	wdt_dev->timeout = timeout;

Also, timeout may be larger than the maximum supported by the hardware,
so you need to ensure that the value your write is not larger than
GXBB_WDT_TCNT_SETUP_MASK.

> +
> +	return 0;
> +}
> +
> +static unsigned int meson_gxbb_wdt_get_timeleft(struct watchdog_device *wdt_dev)
> +{
> +	struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> +	unsigned long reg;
> +
> +	reg = readl(data->reg_base + GXBB_WDT_TCNT_REG);
> +
> +	return ((reg >> GXBB_WDT_TCNT_CNT_SHIFT)-

Space between operators, please.

> +			(reg & GXBB_WDT_TCNT_SETUP_MASK)) / 1000;
> +}
> +
> +static const struct watchdog_ops meson_gxbb_wdt_ops = {
> +	.start = meson_gxbb_wdt_start,
> +	.stop = meson_gxbb_wdt_stop,
> +	.ping = meson_gxbb_wdt_ping,
> +	.set_timeout = meson_gxbb_wdt_set_timeout,
> +	.get_timeleft = meson_gxbb_wdt_get_timeleft,
> +};
> +
> +static const struct watchdog_info meson_gxbb_wdt_info = {
> +	.identity = "meson-gxbb-wdt",

It is common here to provide a user readable string, which would be something
like "Meson GXBB Watchdog".

> +	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
> +};
> +
> +static int __maybe_unused meson_gxbb_wdt_resume(struct device *dev)
> +{
> +	struct meson_gxbb_wdt *data = dev_get_drvdata(dev);
> +
> +	if (watchdog_active(&data->wdt_dev))
> +		meson_gxbb_wdt_start(&data->wdt_dev);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused meson_gxbb_wdt_suspend(struct device *dev)
> +{
> +	struct meson_gxbb_wdt *data = dev_get_drvdata(dev);
> +
> +	if (watchdog_active(&data->wdt_dev))
> +		meson_gxbb_wdt_stop(&data->wdt_dev);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops meson_gxbb_wdt_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(meson_gxbb_wdt_suspend, meson_gxbb_wdt_resume)
> +};
> +
> +static const struct of_device_id meson_gxbb_wdt_dt_ids[] = {
> +	 { .compatible = "amlogic,meson-gxbb-wdt", },
> +	 { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, meson_gxbb_wdt_dt_ids);
> +
> +static int meson_gxbb_wdt_probe(struct platform_device *pdev)
> +{
> +	struct meson_gxbb_wdt *data;
> +	struct resource *res;
> +	int ret;
> +
> +	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	data->reg_base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(data->reg_base))
> +		return PTR_ERR(data->reg_base);
> +
> +	data->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(data->clk))
> +		return PTR_ERR(data->clk);
> +
> +	clk_prepare_enable(data->clk);
> +
> +	platform_set_drvdata(pdev, data);
> +
> +	data->wdt_dev.parent = &pdev->dev;
> +	data->wdt_dev.info = &meson_gxbb_wdt_info;
> +	data->wdt_dev.ops = &meson_gxbb_wdt_ops;
> +	data->wdt_dev.max_hw_heartbeat_ms = GXBB_WDT_TCNT_SETUP_MASK;
> +	data->wdt_dev.min_timeout = 1;
> +	data->wdt_dev.timeout = DEFAULT_TIMEOUT;
> +	watchdog_set_drvdata(&data->wdt_dev, data);
> +
> +	/* Setup with 1ms timebase */
> +	writel(((clk_get_rate(data->clk) / 1000) & GXBB_WDT_CTRL_DIV_MASK) |
> +		GXBB_WDT_CTRL_EE_RESET |
> +		GXBB_WDT_CTRL_CLK_EN |
> +		GXBB_WDT_CTRL_CLKDIV_EN,
> +		data->reg_base + GXBB_WDT_CTRL_REG);
> +
> +	meson_gxbb_wdt_set_timeout(&data->wdt_dev, data->wdt_dev.timeout);
> +
> +	ret = watchdog_register_device(&data->wdt_dev);
> +	if (ret)
> +		return ret;

clk_disable_unprepare() ?

> +
> +	return 0;
> +}
> +
> +static int meson_gxbb_wdt_remove(struct platform_device *pdev)
> +{
> +	struct meson_gxbb_wdt *data = platform_get_drvdata(pdev);
> +
> +	watchdog_unregister_device(&data->wdt_dev);
> +

clk_disable_unprepare() ?

> +	return 0;
> +}
> +
> +static void meson_gxbb_wdt_shutdown(struct platform_device *pdev)
> +{
> +	struct meson_gxbb_wdt *data = platform_get_drvdata(pdev);
> +
> +	meson_gxbb_wdt_stop(&data->wdt_dev);
> +}
> +
> +static struct platform_driver meson_gxbb_wdt_driver = {
> +	.probe	= meson_gxbb_wdt_probe,
> +	.remove	= meson_gxbb_wdt_remove,
> +	.shutdown = meson_gxbb_wdt_shutdown,
> +	.driver = {
> +		.name = "meson-gxbb-wdt",
> +		.pm = &meson_gxbb_wdt_pm_ops,
> +		.of_match_table	= meson_gxbb_wdt_dt_ids,
> +	},
> +};
> +
> +module_platform_driver(meson_gxbb_wdt_driver);
> +
> +MODULE_ALIAS("platform:meson-gxbb-wdt");
> +MODULE_AUTHOR("Neil Armstrong <narmstrong at baylibre.com>");
> +MODULE_DESCRIPTION("Amlogic Meson GXBB Watchdog timer driver");
> +MODULE_LICENSE("Dual BSD/GPL");
>



From festevam at gmail.com  Mon May 30 09:54:43 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 30 May 2016 13:54:43 -0300
Subject: [PATCH 5/5] arm/dts/imx6q-b850v3: Use GE B850v3 LVDS/DP++ Bridge
In-Reply-To: <1464626385-19253-6-git-send-email-peter.senna@collabora.com>
References: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
 <1464626385-19253-6-git-send-email-peter.senna@collabora.com>
Message-ID: <CAOMZO5CigjkoKoHdWROYwz=76OjbA8bTsrgG4VVQymKPZeUtUw@mail.gmail.com>

On Mon, May 30, 2016 at 1:39 PM, Peter Senna Tschudin
<peter.senna at collabora.com> wrote:

> +&mux2_i2c2 {
> +       status = "okay";
> +       clock-frequency = <100000>;
> +
> +       b850v3_lvds_dp_bridge {
> +               compatible = "ge,b850v3_lvds_dp";
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +               reg = <0x73>;

You use 'reg = <0x73>' here, but no @73.


From broonie at kernel.org  Mon May 30 10:35:57 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 30 May 2016 18:35:57 +0100
Subject: [PATCH v2 1/3] spi: xilinx: Remove bitbang and register with spi
 core
In-Reply-To: <1464601609-5095-1-git-send-email-nagasure@xilinx.com>
References: <1464601609-5095-1-git-send-email-nagasure@xilinx.com>
Message-ID: <20160530173557.GZ29837@sirena.org.uk>

On Mon, May 30, 2016 at 03:16:49PM +0530, Naga Sureshkumar Relli wrote:
> This patch removes the bitbang layer registration.
> it directly register with spi core using spi_register_master and uses
> the call backs provided by spi_master struct.

This is doing a whole bunch of other stuff as well.  

> +/* Register Offsets */
> +#define XSPI_CR_OFFSET		0x60
> +#define XSPI_SR_OFFSET		0x64
> +#define XSPI_TXD_OFFSET		0x68
> +#define XSPI_RXD_OFFSET		0x6c
> +#define XSPI_SSR_OFFSET		0x70
> +#define XIPIF_V123B_DGIER_OFFSET	0x1c
> +#define XIPIF_V123B_IISR_OFFSET		0x20
> +#define XIPIF_V123B_IIER_OFFSET		0x28
> +#define XIPIF_V123B_RESETR_OFFSET	0x40

> -#define XSPI_SR_RX_EMPTY_MASK	0x01	/* Receive FIFO is empty */
> -#define XSPI_SR_RX_FULL_MASK	0x02	/* Receive FIFO is full */
> -#define XSPI_SR_TX_EMPTY_MASK	0x04	/* Transmit FIFO is empty */
> -#define XSPI_SR_TX_FULL_MASK	0x08	/* Transmit FIFO is full */
> -#define XSPI_SR_MODE_FAULT_MASK	0x10	/* Mode fault error */
> -
> -#define XSPI_TXD_OFFSET		0x68	/* Data Transmit Register */
> -#define XSPI_RXD_OFFSET		0x6c	/* Data Receive Register */
> -
> -#define XSPI_SSR_OFFSET		0x70	/* 32-bit Slave Select Register */

There's unrelated code motion stuff here.

> +/**
> + * xspi_write32 - Write a value to the device register little endian
> + * @val:	Value to write at the Register offset
> + * @addr:	Register offset
> + *
> + * Write data to the paricular SPI register
> + */
>  static void xspi_write32(u32 val, void __iomem *addr)

There's adding some new documentation.

> -static void xilinx_spi_tx(struct xilinx_spi *xspi)
> -{
> -	u32 data = 0;

And what looks like a total rewrite of even the FIFO stuffing code
rather than the refactoring to go into the new framework that I'd
expect.  As a result of all this it's very hard to review this change,
welcome though it is.  Can you please split this out into a patch series
with smaller changes in each patch rather than one big rewrite
everything patch?

> -	if (!xspi->tx_ptr) {
> -		xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
> -		return;
> -	}
> -
> -	switch (xspi->bytes_per_word) {
> -	case 1:
> -		data = *(u8 *)(xspi->tx_ptr);
> -		break;
> -	case 2:
> -		data = *(u16 *)(xspi->tx_ptr);
> -		break;
> -	case 4:
> -		data = *(u32 *)(xspi->tx_ptr);
> -		break;
> -	}
> -
> -	xspi->write_fn(data, xspi->regs + XSPI_TXD_OFFSET);
> -	xspi->tx_ptr += xspi->bytes_per_word;
> -}

For example this refactoring of the FIFO stuffing looks good but ought
to be a separate patch.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/29369a1b/attachment.sig>

From broonie at kernel.org  Mon May 30 10:38:39 2016
From: broonie at kernel.org (Mark Brown)
Date: Mon, 30 May 2016 18:38:39 +0100
Subject: [PATCH v2 3/3] spi: xilinx: Update devicetree bindings for
 spi-xilinx
In-Reply-To: <1464601627-5246-1-git-send-email-nagasure@xilinx.com>
References: <1464601627-5246-1-git-send-email-nagasure@xilinx.com>
Message-ID: <20160530173839.GA29837@sirena.org.uk>

On Mon, May 30, 2016 at 03:17:07PM +0530, Naga Sureshkumar Relli wrote:

> Update bindings for spi-xilinx.
> as per spi-bus.txt rename num-ss-bits to num-cs.
> and add fifo-size and bits-per-word properties.

This makes the new bindings backwards incompatible breaking existing
machine descriptions.  It's fine to add new options but the driver
should accept the old options.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/fb69d58a/attachment.sig>

From festevam at gmail.com  Mon May 30 10:41:37 2016
From: festevam at gmail.com (Fabio Estevam)
Date: Mon, 30 May 2016 14:41:37 -0300
Subject: [PATCH] ARM: dts: imx6ul-14x14-evk: Add LCD and backlight support
Message-ID: <1464630097-23992-1-git-send-email-festevam@gmail.com>

From: Fabio Estevam <fabio.estevam at nxp.com>

Add support for the LCD8000-43T display and for the backlight
controlled via PWM1.

Signed-off-by: Fabio Estevam <fabio.estevam at nxp.com>
---
 arch/arm/boot/dts/imx6ul-14x14-evk.dts | 48 ++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dts b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
index 668a729..df19391 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk.dts
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
@@ -22,6 +22,14 @@
 		reg = <0x80000000 0x20000000>;
 	};
 
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+		status = "okay";
+	};
+
 	regulators {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -125,6 +133,46 @@
 	};
 };
 
+
+&lcdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_lcdif_dat
+		     &pinctrl_lcdif_ctrl>;
+	display = <&display0>;
+	status = "okay";
+
+	display0: display {
+		bits-per-pixel = <16>;
+		bus-width = <24>;
+
+		display-timings {
+			native-mode = <&timing0>;
+
+			timing0: timing0 {
+				clock-frequency = <9200000>;
+				hactive = <480>;
+				vactive = <272>;
+				hfront-porch = <8>;
+				hback-porch = <4>;
+				hsync-len = <41>;
+				vback-porch = <2>;
+				vfront-porch = <4>;
+				vsync-len = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
 &qspi {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_qspi>;
-- 
1.9.1



From simon.marchi at ericsson.com  Mon May 30 10:48:11 2016
From: simon.marchi at ericsson.com (Simon Marchi)
Date: Mon, 30 May 2016 13:48:11 -0400
Subject: Possible race between PTRACE_SETVFPREGS and PTRACE_CONT on ARM?
Message-ID: <574C7CDB.7050103@ericsson.com>

Hello knowledgeable ARM people!

(Background: https://sourceware.org/ml/gdb/2016-05/msg00020.html )

Debugging a flaky GDB test case on ARM lead me to think there might
be race between PTRACE_SETVFPREGS and PTRACE_CONT on ARM
(PTRACE_SETVFPREGS is ARM-specific anyway).  The test case (and the
reproducer below) changes the value of a VFP register (let's say d0)
using PTRACE_SETVFPREGS and resumes the thread with PTRACE_CONT.  It
happens intermittently that the thread resumes execution with the
old value in d0 instead of the new one.

Here is a minimal reproducing example.

test.S:

  .global _start
  _start:
      vldr.64 d0, constant
      vldr.64 d1, constant

  break_here:
      vcmp.f64 d0, d1
      vmrs APSR_nzcv, fpscr

      # Exit code
      moveq r0, #1
      movne r0, #0

      # Exit syscall
      mov r7, #1
      svc 0

  .align 8
  constant:
  .word 0xc8b43958
  .word 0x40594676

Built with:

  $ gcc -g3 -O0 -o test test.S -nostdlib

And the gdb script, test.gdb:

  file test
  b break_here
  run
  p $d0 = 4.0
  c

The test is ran with

  $ ./gdb -nx -x test.gdb -batch

The test loads the same constant in d0 and d1.  It then does a comparison between
them and exits with 1 (failure) if they are the same, 0 (success) if they are different.
The GDB script breaks at "break_here", tries to change the value of d0 to some other
constant (4.0) and lets the program continue and exit.  If our register write succeeded,
the program should exit with 0 (values are different).  If our register write failed, the
program will exit with 1 (values are still the same).

The result is that I randomly see both cases, hinting to a race between the register write
and the time where the kernel restores the thread's vfp registers.  Note that when GDB's
affinity is pinned to a single core, I do not see the failure.  Also, note that when I
remove the vldr.64 instructions, I can't seem to reproduce the problem, so it looks
like they are somehow important.

I see this behavior on 3 different boards:

- ODroid XU-4, kernel 3.10.96
- Firefly RK3288, kernel 3.10.0
- Raspberry Pi 2, kernel 4.4.8

Any ideas about this problem?

Thanks,

Simon


From hdegoede at redhat.com  Mon May 30 11:05:29 2016
From: hdegoede at redhat.com (Hans de Goede)
Date: Mon, 30 May 2016 20:05:29 +0200
Subject: [PATCH 2/3] mmc: sunxi: Fix DDR MMC timings for A80
In-Reply-To: <CAGb2v65=ZM+deSmTmMnT6XFJv8PuY+Kba3kJGKrk_46hxxRyHA@mail.gmail.com>
References: <1464505484-3661-1-git-send-email-wens@csie.org>
 <1464505484-3661-3-git-send-email-wens@csie.org>
 <99d78ff3-db4d-45cc-024a-d94583b56f35@redhat.com>
 <CAGb2v65=ZM+deSmTmMnT6XFJv8PuY+Kba3kJGKrk_46hxxRyHA@mail.gmail.com>
Message-ID: <822dc3f1-9afe-f356-e0e7-89073586d401@redhat.com>

Hi,

On 30-05-16 14:59, Chen-Yu Tsai wrote:
> On Mon, May 30, 2016 at 7:34 PM, Hans de Goede <hdegoede at redhat.com> wrote:
>> Hi,
>>
>> On 29-05-16 09:04, Chen-Yu Tsai wrote:
>>>
>>> The MMC clock timings were incorrectly calculated, when the conversion
>>> from delay value to delay phase was done.
>>>
>>> The 50M DDR and 50M DDR 8bit timings are off, and make eMMC DDR
>>> unusable. Unfortunately it seems different controllers on the same SoC
>>> have different timings. The new settings are taken from mmc2, which is
>>> commonly used with eMMC.
>>
>>
>> Hmm, I'm not really all that familiar with mmc, but can't an external
>> sdcard connected to mmc0 use DDR too ? Assuming the answer is yes, then
>> we really need to update the driver to use the right per controller
>> timings.
>
> I would very much like that to happen. However, SD card UHS-1 DDR modes
> require 1.8V signaling, which is unavailable on _all_ sunxi boards.
> This seems like a limit of most of the SoCs not having a separate IO
> voltage rail for mmc pins.
>
> Until then, I wouldn't worry that much.
>
>>> The settings for the slower timing modes seem to work despite being
>>> wrong, so leave them be.
>>
>>
>> If you're sure the timings are wrong, please fix them. Sometimes wrong
>> timings do seem to work, but lead to unreliable communication, or turn
>> out to work on some boards and not on others due to routing differences.
>
> Unfortunately I did try putting in the correct numbers for them, and my
> eMMC then failed to probe. It seems the core switches up from 400kHz to
> 50MHz then to 50MHz DDR, and it fails somewhere in there, maybe at 50MHz.
>
> I'm not sure if we need to add DT bindings to specify different delays
> for different controllers, though. Seems like we'll never actually use
> it.
>
> Hope this answers your questions.

Yes that answers my questions, and with my questions answered, this series is:

Acked-by: Hans de Goede <hdegoede at redhat.com>

Regards,

Hans



From maxime.ripard at free-electrons.com  Mon May 30 11:45:32 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 30 May 2016 20:45:32 +0200
Subject: [PATCH v2] clk: sunxi: predivider handling for factors clock
In-Reply-To: <CAEzqOZvnKKNs_sXUJrwTykA5mzwKMg+HpaFcKgBTFr+utT4qQg@mail.gmail.com>
References: <1461084466-20889-1-git-send-email-vishnupatekar0510@gmail.com>
 <1461084466-20889-2-git-send-email-vishnupatekar0510@gmail.com>
 <20160502111337.GR17159@lukather>
 <CAEzqOZvnKKNs_sXUJrwTykA5mzwKMg+HpaFcKgBTFr+utT4qQg@mail.gmail.com>
Message-ID: <20160530184532.GD4908@lukather>

Hi Vishnu,

On Mon, May 16, 2016 at 07:28:42AM +0800, Vishnu Patekar wrote:
> > > @@ -307,7 +305,7 @@ static void sun6i_get_ahb1_factors(struct factors_request *req)
> > >       div = DIV_ROUND_UP(req->parent_rate, req->rate);
> > >
> > >       /* calculate pre-divider if parent is pll6 */
> > > -     if (req->parent_index == SUN6I_AHB1_PARENT_PLL6) {
> > > +     if (req->prediv_width) {
> > >               if (div < 4)
> > >                       calcp = 0;
> > >               else if (div / 2 < 4)
> >
> > You should also remove that code from that function. Now that the core
> > can tell the pre-divider configuration, it can adjust the parent rate
> > so that you don't have to care anymore.
>
> We still need to get m factor when it's called from set_rate and
> determine_rate.
> 
> Sorry, I did not your "that code from that function" meaning. I assumed
> you're talking about m factor in sun6i_get_ahb1_factors.

Sorry for the late answer.

I don't know if you've seen it, but I have been working on a new clock
framework.

I went over all the A83T clocks, and most of them could be
covered. The issue only lies in the PLLs and their additional 1-bit
dividers.

If we just choos to ignore (one of) them, it should be pretty trivial
to implement with the current clock classes we have.

There's also the current assumption that there's a single parent that
has a pre-divider, but that can easily be fixed by setting up an
array.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/d2c5751b/attachment.sig>

From arend.vanspriel at broadcom.com  Mon May 30 11:54:33 2016
From: arend.vanspriel at broadcom.com (Arend van Spriel)
Date: Mon, 30 May 2016 20:54:33 +0200
Subject: building and using modules on arm64 hikey board
In-Reply-To: <0240F9F0-0146-4DCC-B512-195415B29B34@linaro.org>
References: <87a3195c-febb-a6c8-a679-272b9f7b59cc@broadcom.com>
 <0240F9F0-0146-4DCC-B512-195415B29B34@linaro.org>
Message-ID: <574C8C69.6020501@broadcom.com>



On 30-05-16 13:30, Ard Biesheuvel wrote:
> This is likely caused by the fact that the Android AArch64 toolchain uses -fpic by default. Could you try adding -fno-pic to the CFLAGS?

I did only to notice with 'make V=1 ...' that it was already used hence
showing up in the compile command line twice. To no avail so that ain't
working.

Regards,
Arend

>> On 30 mei 2016, at 12:21, Arend Van Spriel <arend.vanspriel at broadcom.com> wrote:
>>
>> I got myself an arm64 HiKey board from LeMaker and build an Android AOSP
>> image for it (see [1]). For development I would like to use
>> CONFIG_MODULES. However, when I try to insmod the build module I get:
>>
>> [  287.903653] module cfg80211: overflow in relocation type 261 val
>> ffffffbffc006530
>>
>> Looking AArch64 ELF documentation [2], section 4.6.5, it has:
>> code|name            |operation |overflow check   |
>> 261 |R_AARCH64_PREL32|S + A - P |-2^31 <= X < 2^32|
>>
>> So basically the highest 32 bits should all be one and so ffffffbf is
>> invalid. From what I could find searching internet it could be an issue
>> with linker options so I build kernel and modules with V=1. Here the
>> linker invocation for them:
>>
>> + aarch64-linux-android-ld -EL -p --no-undefined -X --build-id -o vmlinux \
>> -T ./arch/arm64/kernel/vmlinux.lds arch/arm64/kernel/head.o
>> init/built-in.o \
>> --start-group usr/built-in.o arch/arm64/kernel/built-in.o
>> arch/arm64/mm/built-in.o \
>> arch/arm64/net/built-in.o arch/arm64/kvm/built-in.o
>> arch/arm64/crypto/built-in.o \
>> ./drivers/firmware/efi/libstub/lib.a kernel/built-in.o certs/built-in.o
>> mm/built-in.o \
>> fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o
>> block/built-in.o \
>> arch/arm64/lib/lib.a lib/lib.a arch/arm64/lib/built-in.o lib/built-in.o
>> drivers/built-in.o \
>> sound/built-in.o firmware/built-in.o net/built-in.o virt/built-in.o
>> --end-group .tmp_kallsyms2.o
>>
>>  aarch64-linux-android-ld -EL -r  -T ./scripts/module-common.lds
>> --build-id \
>>  -o net/wireless/cfg80211.ko net/wireless/cfg80211.o
>> net/wireless/cfg80211.mod.o
>>
>> Attached are vmlinux.lds and module-common.lds. I also tried taking
>> upstream arch/arm64/kernel/module.lds in hikey-linaro tree. If someone
>> can give a hint or educated guess at what to try it would be appreciated.
>>
>> Regards,
>> Arend
>>
>> [1] https://source.android.com/source/devices.html#building-kernel
>> [2]
>> http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
>> <module-common.lds>
>> <vmlinux.lds>


From maxime.ripard at free-electrons.com  Mon May 30 12:43:40 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Mon, 30 May 2016 21:43:40 +0200
Subject: [PATCH] ARM: dts: sun7i: Add dts file for Bananapi M1 Plus board
In-Reply-To: <20160530123013.11575-1-luoyi.ly@gmail.com>
References: <20160530123013.11575-1-luoyi.ly@gmail.com>
Message-ID: <20160530194340.GE4908@lukather>

Hi,

On Mon, May 30, 2016 at 08:30:13PM +0800, luoyi.ly at gmail.com wrote:
> From: luoyi <luoyi.ly at gmail.com>
> 
> Add support for the Bananapi M1 Plus A20 development board from sinovoip.com.cn .
> This board features 1G RAM, 2 USB A receptacles, 1 micro USB receptacle for
> OTG, 1 micro USB receptacle for power, HDMI, sata, Gbit ethernet, ir receiver,
> 3.5 mm jack for stero sound out, on board microphone, 40 gpio pins and sdio wifi.

What is the difference between the M1+ and the M1?

> 
> Signed-off-by: Luo Yi <luoyi.ly at gmail.com>
> ---
>  arch/arm/boot/dts/Makefile                       |   1 +
>  arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts | 270 +++++++++++++++++++++++
>  2 files changed, 271 insertions(+)
>  create mode 100644 arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
> 
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index e06a5ab..fde407f 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -685,6 +685,7 @@ dtb-$(CONFIG_MACH_SUN6I) += \
>  	sun6i-a31s-yones-toptech-bs1078-v2.dtb
>  dtb-$(CONFIG_MACH_SUN7I) += \
>  	sun7i-a20-bananapi.dtb \
> +	sun7i-a20-bananapi-m1-plus.dtb \
>  	sun7i-a20-bananapro.dtb \
>  	sun7i-a20-cubieboard2.dtb \
>  	sun7i-a20-cubietruck.dtb \
> diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
> new file mode 100644
> index 0000000..b62fc1d
> --- /dev/null
> +++ b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
> @@ -0,0 +1,270 @@
> +/*
> + * Copyright 2016 Luo Yi <luoyi.ly at gmail.com>
> + * 
> + * Thanks to the original work by Hans de Goede <hdegoede at redhat.com>
> + *
> + * 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 "sun7i-a20.dtsi"
> +#include "sunxi-common-regulators.dtsi"
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +/ {
> +	model = "Banana Pi BPI-M1-Plus";
> +	compatible = "sinovoip,bpi-m1-plus", "allwinner,sun7i-a20";
> +
> +	aliases {
> +		serial0 = &uart0;
> +	};
> +
> +	chosen {
> +		stdout-path = "serial0:115200n8";
> +	};
> +
> +	leds {
> +		compatible = "gpio-leds";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&led_pins_bananapi>;
> +
> +		red {
> +			label = "bananapi:red:usr";

The first part the label is the board name, in that case that would be
bananapi-m1-plus.

> +			gpios = <&pio 7 25 GPIO_ACTIVE_HIGH>;
> +			linux,default-trigger = "default-on";

So that's the power led?

> +		};
> +
> +		green {
> +			label = "bananapi:green:usr";
> +			gpios = <&pio 7 24 GPIO_ACTIVE_HIGH>;
> +			linux,default-trigger = "heartbeat";

We don't enforce any trigger by default.

> +
> +		};
> +	};
> +
> +	reg_gmac_3v3: gmac-3v3 {
> +		compatible = "regulator-fixed";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&gmac_power_pin_bananapi>;
> +		regulator-name = "gmac-3v3";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		startup-delay-us = <100000>;
> +		enable-active-high;
> +		gpio = <&pio 7 23 GPIO_ACTIVE_HIGH>;
> +	};
> +
> +	reg_vmmc3: vmmc3 {
> +		compatible = "regulator-fixed";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&vmmc3_pin_bananapi>;
> +		regulator-name = "vmmc3";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		regulator-always-on;
> +		regulator-boot-on;
> +		enable-active-high;
> +		gpio = <&pio 7 22 GPIO_ACTIVE_HIGH>;
> +	};

You can use reg_vcc3v3 from sunxi-common-regulators.dtsi.

> +
> +};
> +
> +&ahci {
> +	status = "okay";
> +};
> +
> +&codec {
> +	status = "okay";
> +};
> +
> +&ehci0 {
> +	status = "okay";
> +};
> +
> +&ehci1 {
> +	status = "okay";
> +};
> +
> +&ohci0 {
> +	status = "okay";
> +};
> +
> +&ohci1 {
> +	status = "okay";
> +};

Please order your nodes alphabetically.

> +
> +&gmac {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&gmac_pins_rgmii_a>;
> +	phy = <&phy1>;
> +	phy-mode = "rgmii";
> +	phy-supply = <&reg_gmac_3v3>;
> +	status = "okay";
> +
> +	phy1: ethernet-phy at 1 {
> +		reg = <1>;
> +	};
> +};
> +
> +&i2c0 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&i2c0_pins_a>;
> +	status = "okay";
> +
> +	axp209: pmic at 34 {
> +		compatible = "x-powers,axp209";
> +		reg = <0x34>;
> +		interrupt-parent = <&nmi_intc>;
> +		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
> +
> +		interrupt-controller;
> +		#interrupt-cells = <1>;
> +	};
> +};
> +
> +&ir0 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&ir0_rx_pins_a>;
> +	status = "okay";
> +};
> +
> +&mmc0 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bananapi>;
> +	vmmc-supply = <&reg_vcc3v3>;
> +	bus-width = <4>;
> +	cd-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */
> +	cd-inverted;
> +	status = "okay";
> +};
> +
> +&mmc3 {
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&mmc3_pins_a>;
> +	vmmc-supply = <&reg_vmmc3>;
> +	bus-width = <4>;
> +	non-removable;
> +	enable-sdio-wakeup;
> +	status = "okay";
> +
> +	brcmf: bcrmf at 1 {
> +		reg = <1>;
> +		compatible = "brcm,bcm4329-fmac";
> +		interrupt-parent = <&pio>;
> +		interrupts = <7 15 IRQ_TYPE_LEVEL_LOW>; 
> +		interrupt-names = "host-wake";
> +	};
> +
> +};
> +
> +&mmc3_pins_a {
> +    /* AP6210 requires pull-up */
> +	allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
> +};
> +
> +&pio {
> +	gmac_power_pin_bananapi: gmac_power_pin at 0 {
> +		allwinner,pins = "PH23";
> +		allwinner,function = "gpio_out";
> +		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
> +		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
> +	};
> +
> +	led_pins_bananapi: led_pins at 0 {
> +		allwinner,pins = "PH24", "PG2";
> +		allwinner,function = "gpio_out";
> +		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
> +		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
> +	};
> +
> +	mmc0_cd_pin_bananapi: mmc0_cd_pin at 0 {
> +		allwinner,pins = "PH10";
> +		allwinner,function = "gpio_in";
> +		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
> +		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
> +	};
> +
> +	usb1_vbus_pin_bananapi: usb1_vbus_pin at 0 {
> +		allwinner,pins = "PH0";
> +		allwinner,function = "gpio_out";
> +		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
> +		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
> +	};
> +
> +	usb2_vbus_pin_bananapi: usb2_vbus_pin at 0 {
> +		allwinner,pins = "PH1";
> +		allwinner,function = "gpio_out";
> +		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
> +		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
> +	};
> +
> +	vmmc3_pin_bananapi: vmmc3_pin at 0 {
> +		allwinner,pins = "PH22";
> +		allwinner,function = "gpio_out";
> +		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
> +		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
> +	};
> +};
> +
> +&reg_usb1_vbus {
> +	pinctrl-0 = <&usb1_vbus_pin_bananapi>;
> +	gpio = <&pio 7 0 GPIO_ACTIVE_HIGH>; /* PH0 */
> +	status = "okay";
> +};
> +
> +&reg_usb2_vbus {
> +	pinctrl-0 = <&usb2_vbus_pin_bananapi>;
> +	gpio = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
> +	status = "okay";
> +};
> +
> +&uart0 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&uart0_pins_a>;
> +	status = "okay";
> +};
> +
> +&usbphy {
> +	usb1_vbus-supply = <&reg_usb1_vbus>;
> +	usb2_vbus-supply = <&reg_usb2_vbus>;
> +	status = "okay";
> +};
> -- 
> 2.8.3
>

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160530/da12d889/attachment.sig>

From bernhard.nortmann at web.de  Mon May 30 13:26:21 2016
From: bernhard.nortmann at web.de (Bernhard Nortmann)
Date: Mon, 30 May 2016 22:26:21 +0200
Subject: [linux-sunxi] Re: [PATCH] ARM: dts: sun7i: Add dts file for
 Bananapi M1 Plus board
In-Reply-To: <20160530194340.GE4908@lukather>
References: <20160530123013.11575-1-luoyi.ly@gmail.com>
 <20160530194340.GE4908@lukather>
Message-ID: <574CA1ED.8050007@web.de>

Am 30.05.2016 um 21:43 schrieb Maxime Ripard:
> Hi,
>
> On Mon, May 30, 2016 at 08:30:13PM +0800, luoyi.ly at gmail.com wrote:
>> From: luoyi <luoyi.ly at gmail.com>
>>
>> Add support for the Bananapi M1 Plus A20 development board from sinovoip.com.cn .
>> This board features 1G RAM, 2 USB A receptacles, 1 micro USB receptacle for
>> OTG, 1 micro USB receptacle for power, HDMI, sata, Gbit ethernet, ir receiver,
>> 3.5 mm jack for stero sound out, on board microphone, 40 gpio pins and sdio wifi.
> What is the difference between the M1+ and the M1?

The M1+ is an updated version of the original Banana Pi. If you're 
interested
in the details, have a look at http://linux-sunxi.org/Banana_Pi#Variants .
"BPi-M1+" is SinoVoip's counterpart of LeMaker's "Banana Pro", for which 
a .dts
already exists. Judging from .fex files, only a single pin assignment 
seems to
differ between the two (audio_pa_ctrl, PH26 vs. PH15).

Regards, B. Nortmann


From thommyj at gmail.com  Mon May 30 13:40:04 2016
From: thommyj at gmail.com (Thommy Jakobsson)
Date: Mon, 30 May 2016 22:40:04 +0200
Subject: [PATCH 0/2] arm-smmu: add master mask
Message-ID: <1464640806-3942-1-git-send-email-thommyj@gmail.com>

This patchset makes it possible to manually set a mask for a master.
Default behaviour when not specifying a mask is to keep current behaviour.
If masks are specified for a master, all of its stream IDs needs to have a
mask.

Platforms with a large number of IDs per master starts to show up. Its
impractical to specify all available IDs in some cases. Specific example
is the ZynqMPSoC, where the streamid have 6 bits from the AXI ID. So 2^6
IDs for each PL port, which there are 6 of.

Thommy Jakobsson (2):
  arm-smmu: doc: add binding for stream ID mask
  arm-smmu: Add possibillity to mask streamIDs

 .../devicetree/bindings/iommu/arm,smmu.txt         | 15 +++++++-
 drivers/iommu/arm-smmu.c                           | 43 +++++++++++++++++++++-
 2 files changed, 55 insertions(+), 3 deletions(-)

-- 
1.9.1



From thommyj at gmail.com  Mon May 30 13:40:05 2016
From: thommyj at gmail.com (Thommy Jakobsson)
Date: Mon, 30 May 2016 22:40:05 +0200
Subject: [PATCH 1/2] arm-smmu: doc: add binding for stream ID mask
In-Reply-To: <1464640806-3942-1-git-send-email-thommyj@gmail.com>
References: <1464640806-3942-1-git-send-email-thommyj@gmail.com>
Message-ID: <1464640806-3942-2-git-send-email-thommyj@gmail.com>

Add documentation for new device tree binding, mmu-masters-mask.

Signed-off-by: Thommy Jakobsson <thommyj at gmail.com>
---
 Documentation/devicetree/bindings/iommu/arm,smmu.txt | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index 19fe6f2..cabd1dc 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -56,6 +56,13 @@ conditions.
                   aliases of secure registers have to be used during
                   SMMU configuration.
 
+- mmu-masters-mask : An optional list that specifies a mask per StreamID.
+                  A master included in this liss, have to specify masks
+                  for all of its StreamIDs. A master not included in the
+                  list will default to mask 0 (i.e entire ID is used).
+                  This can for example be used in systems where parts of
+                  the StreamID is dynamic.
+
 Example:
 
         smmu {
@@ -70,9 +77,13 @@ Example:
                              <0 37 4>;
 
                 /*
-                 * Two DMA controllers, the first with two StreamIDs (0xd01d
+                 * Three DMA controllers, the first with two StreamIDs (0xd01d
                  * and 0xd01e) and the second with only one (0xd11c).
+                 * The third uses a mask to use all StreamIDs that starts with
+                 * 0xd8
                  */
                 mmu-masters = <&dma0 0xd01d 0xd01e>,
-                              <&dma1 0xd11c>;
+                              <&dma1 0xd11c>,
+                              <&dma2 0xd800>;
+                mmu-masters-mask = <&dma2 0x07FF>
         };
-- 
1.9.1



From thommyj at gmail.com  Mon May 30 13:40:06 2016
From: thommyj at gmail.com (Thommy Jakobsson)
Date: Mon, 30 May 2016 22:40:06 +0200
Subject: [PATCH 2/2] arm-smmu: Add possibillity to mask streamIDs
In-Reply-To: <1464640806-3942-1-git-send-email-thommyj@gmail.com>
References: <1464640806-3942-1-git-send-email-thommyj@gmail.com>
Message-ID: <1464640806-3942-3-git-send-email-thommyj@gmail.com>

Use DT bindings to allow masks to be added for a masters streamIDs. This
is necessary for devices that have multiple IDs, or use dynamic signals to
build up the ID. For example the ZynqMPSoC that mirrors 6bits from the
AXI ID into the streamid.

Signed-off-by: Thommy Jakobsson <thommyj at gmail.com>
---
 drivers/iommu/arm-smmu.c | 46 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 9345a3f..14438f8 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -305,6 +305,7 @@ struct arm_smmu_smr {
 struct arm_smmu_master_cfg {
 	int				num_streamids;
 	u16				streamids[MAX_MASTER_STREAMIDS];
+	u16				streammasks[MAX_MASTER_STREAMIDS];
 	struct arm_smmu_smr		*smrs;
 };
 
@@ -554,6 +555,38 @@ static int register_smmu_master(struct arm_smmu_device *smmu,
 	return insert_smmu_master(smmu, master);
 }
 
+static int register_smmu_master_mask(struct arm_smmu_device *smmu,
+				     struct device *dev,
+				     struct of_phandle_args *masterspec)
+{
+	int i;
+	struct arm_smmu_master *master;
+
+	master = find_smmu_master(smmu, masterspec->np);
+	if (!master) {
+		dev_err(dev,
+			"mask phandle to %s, but no ID registred\n",
+			masterspec->np->name);
+		return -EINVAL;
+	}
+
+	if (masterspec->args_count != master->cfg.num_streamids) {
+		dev_err(dev,
+			"Different number of ids %d and masks %d not supported for master device %s\n",
+			master->cfg.num_streamids,
+			masterspec->args_count,
+			masterspec->np->name);
+		return -ENOSPC;
+	}
+
+	for (i = 0; i < master->cfg.num_streamids; ++i) {
+		u16 streammask = masterspec->args[i];
+
+		master->cfg.streamids[i] = streammask;
+	}
+	return 0;
+}
+
 static struct arm_smmu_device *find_smmu_for_device(struct device *dev)
 {
 	struct arm_smmu_device *smmu;
@@ -1106,7 +1139,7 @@ static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
 
 		smrs[i] = (struct arm_smmu_smr) {
 			.idx	= idx,
-			.mask	= 0, /* We don't currently share SMRs */
+			.mask	= cfg->streammasks[i],
 			.id	= cfg->streamids[i],
 		};
 	}
@@ -1972,6 +2005,17 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
 
 	dev_notice(dev, "registered %d master devices\n", i);
 
+	while (!of_parse_phandle_with_args(dev->of_node, "mmu-masters-mask",
+					   "#stream-id-cells", i,
+					   &masterspec)) {
+		err = register_smmu_master_mask(smmu, dev, &masterspec);
+		if (err) {
+			dev_err(dev, "failed to add mask for%s\n",
+				masterspec.np->name);
+			goto out_put_masters;
+		}
+
+	}
 	kfree(masterspec);
 
 	parse_driver_options(smmu);
-- 
1.9.1



From matt at codeblueprint.co.uk  Mon May 30 14:12:12 2016
From: matt at codeblueprint.co.uk (Matt Fleming)
Date: Mon, 30 May 2016 22:12:12 +0100
Subject: [PATCH] arm64/efi: remove spurious WARN_ON for !4K kernels
In-Reply-To: <1464189116-30898-1-git-send-email-mark.rutland@arm.com>
References: <1464189116-30898-1-git-send-email-mark.rutland@arm.com>
Message-ID: <20160530211212.GG2984@codeblueprint.co.uk>

On Wed, 25 May, at 04:11:56PM, Mark Rutland wrote:
> 
> No further restriction on alignment is provided in the UEFI
> specification, neither generically nor in a rule specific to AArch64.
 
This surprises me. I could have sworn the intention was to add this
restriction to the spec when the strict permissions were being
discussed in the UEFI working groups.

Am I reinventing history?

As an aside, Mark, Jeremy, which machines did you see this warning
triggered on? Preproduction/development boards or also in the wild?


From linux at armlinux.org.uk  Mon May 30 14:35:29 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Mon, 30 May 2016 22:35:29 +0100
Subject: Possible race between PTRACE_SETVFPREGS and PTRACE_CONT on ARM?
In-Reply-To: <574C7CDB.7050103@ericsson.com>
References: <574C7CDB.7050103@ericsson.com>
Message-ID: <20160530213529.GS19428@n2100.arm.linux.org.uk>

On Mon, May 30, 2016 at 01:48:11PM -0400, Simon Marchi wrote:
> Hello knowledgeable ARM people!
> 
> (Background: https://sourceware.org/ml/gdb/2016-05/msg00020.html )
> 
> Debugging a flaky GDB test case on ARM lead me to think there might
> be race between PTRACE_SETVFPREGS and PTRACE_CONT on ARM
> (PTRACE_SETVFPREGS is ARM-specific anyway).  The test case (and the
> reproducer below) changes the value of a VFP register (let's say d0)
> using PTRACE_SETVFPREGS and resumes the thread with PTRACE_CONT.  It
> happens intermittently that the thread resumes execution with the
> old value in d0 instead of the new one.

So, I thought I'd look into this, and what I see here on my systems
(whether it be Marvell Dove or iMX6) is that the program always exits
with a return code of 1.

Investigation on the Marvell Dove platform leads me to conclude that
Ubuntu 14.04 gdb (7.7.1-0ubuntu5~14.04.2) is built without support for
VFP - if I add an "info float" into the gdb script, I get:

Breakpoint 1, break_here () at test.S:8
8             vmrs APSR_nzcv, fpscr
No floating-point info available for this processor.

which is incredibly annoying, because it means that your "p $d0 = 4.0"
line has no effect on the VFP state - hence why its always exiting with
1.

However, if we look closer, we see that gdb has decided to put the
breakpoint _after_ the comparison instruction, as confirmed by the
disassembly after the breakpoint is hit:

   0x00008108 <+0>:     vcmp.f64        d0, d1
=> 0x0000810c <+4>:     vmrs    APSR_nzcv, fpscr
   0x00008110 <+8>:     moveq   r0, #1

On iMX6, where I have Ubuntu 12.04 gdb (7.4-2012.04-0ubuntu2.1), "info
float" works as one expects, but we still end up with the program
exiting with a code of 1 - every time - because again, the breakpoint
is misplaced.

So, the gdb verisons I have here seem to be particularly poor - but with
some modifications, I can test out on iMX6 by forcing gdb to do the right
thing - by inserting a couple of "mov r0, r0" instructions after the
"break_here" label.

With that, on a single CPU, it seems to work correctly every time, but
if I bring up a secondary CPU I start seeing the same problems you've
reported - which seems to need the following patch to solve.  Please can
you check whether this resolves your problem?

Thanks.

 arch/arm/kernel/ptrace.c | 2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index ef9119f7462e..4d9375814b53 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -733,8 +733,8 @@ static int vfp_set(struct task_struct *target,
 	if (ret)
 		return ret;
 
-	vfp_flush_hwstate(thread);
 	thread->vfpstate.hard = new_vfp;
+	vfp_flush_hwstate(thread);
 
 	return 0;
 }


-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From matt at codeblueprint.co.uk  Mon May 30 14:53:21 2016
From: matt at codeblueprint.co.uk (Matt Fleming)
Date: Mon, 30 May 2016 22:53:21 +0100
Subject: [PATCH v2] arm64:efi fix the format of debug message from efi
In-Reply-To: <1464341244-14152-1-git-send-email-dennis.chen@arm.com>
References: <1464341244-14152-1-git-send-email-dennis.chen@arm.com>
Message-ID: <20160530215321.GI2984@codeblueprint.co.uk>

On Fri, 27 May, at 05:27:24PM, Dennis Chen wrote:
> When enable debug of efi and memblock with 'efi=debug memblock=debug' appended
> to the kernel command line, the debug message output for earyly_con looks like:
> 
> [    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]
> [    0.000000] memblock_add: [0x00008000000000-0x00008001e7ffff] flags 0x0 early_init_dt_add_memory_arch+0x54/0x5c
> [    0.000000] *
> ...
> 
> This patch is trying to fix the above output messed up by memblock_add(), so we can get below debug mesg looks
> more formally after applied:
> 
> [    0.000000] efi:   0x0000e1050000-0x0000e105ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x0000e1300000-0x0000e1300fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x0000e8200000-0x0000e827ffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
> [    0.000000] efi:   0x008000000000-0x008001e7ffff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
> [    0.000000] memblock_add: [0x00008000000000-0x00008001e7ffff] flags 0x0 early_init_dt_add_memory_arch+0x54/0x5c
> ...
> 
> Signed-off-by: Dennis Chen <dennis.chen at arm.com>
> Acked-by: Mark Rutland <mark.rutland at arm.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Steve Capper <steve.capper at arm.com>
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: Mark Rutland <mark.rutland at arm.com>
> Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> Cc: Matt Fleming <matt at codeblueprint.co.uk>
> Cc: linux-efi at vger.kernel.org
> 
> Since v1[1]:
>  According to the suggestion from Mark Rutland, v2 folds the pr_cont("\n") into pr_info.
>  [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-May/431233.html
> ---
>  drivers/firmware/efi/arm-init.c | 14 ++++++--------
>  1 file changed, 6 insertions(+), 8 deletions(-)

Thanks, applied.


From linux at armlinux.org.uk  Mon May 30 15:40:28 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Mon, 30 May 2016 23:40:28 +0100
Subject: Possible race between PTRACE_SETVFPREGS and PTRACE_CONT on ARM?
In-Reply-To: <20160530213529.GS19428@n2100.arm.linux.org.uk>
References: <574C7CDB.7050103@ericsson.com>
 <20160530213529.GS19428@n2100.arm.linux.org.uk>
Message-ID: <20160530224028.GT19428@n2100.arm.linux.org.uk>

On Mon, May 30, 2016 at 10:35:29PM +0100, Russell King - ARM Linux wrote:
> With that, on a single CPU, it seems to work correctly every time, but
> if I bring up a secondary CPU I start seeing the same problems you've
> reported - which seems to need the following patch to solve.  Please can
> you check whether this resolves your problem?

More background behind this patch... I think that commit 8130b9d7b9d8
("ARM: 7308/1: vfp: flush thread hwstate before copying ptrace registers")
was wrong.

Let's look at what's happening.  The above commit had the following effect:

	vfp_sync_hwstate();
	new_vfp = thread->vfpstate.hard;
	modify new_vfp (but not new_vfp.cpu)
+	vfp_flush_hwstate(thread);
	thread->vfpstate.hard = new_vfp;
-	vfp_flush_hwstate(thread);

Now, the commit above claims that a context switch mid-copy of new_vfp
into thread->vfpstate.hard may result in corrupted state.

I'm not quite sure how we could get to that point: the only thread which
is allowed to touch the traced child's state is the ptracing parent, and
the ptracing parent can't do anything until after vfp_set() has returned.
Even if the traced child gets a fatal signal, the point at which the
signal is delivered to the child is when returning to userspace, which
means the child must be runnable.  That in turn means that we are not
in the middle of changing the register state.

So, I'm not sure where Will got the idea that the partially copied state
would be visible: it shouldn't ever be visible.  If it is visible, then
we've got problems even with Will's patch applied, because a partial
copy whenever it happens would be visible.

In any case, the above change is wrong: vfp_flush_hwstate() sets
thread->vfpstate.hard.cpu to an invalid CPU number.  Switching the order
as Will has done _undoes_ the effect of vfp_flush_hwstate(), which leads
to the bug you are seeing.

So, I think the correct approach is to revert it.

If the partially copied state _is_ visible somehow, that needs to be
better documented - the original commit fails to indicate how the
partially copied state becomes visible as a result of a context switch.

> 
> Thanks.
> 
>  arch/arm/kernel/ptrace.c | 2 +-
>  1 files changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
> index ef9119f7462e..4d9375814b53 100644
> --- a/arch/arm/kernel/ptrace.c
> +++ b/arch/arm/kernel/ptrace.c
> @@ -733,8 +733,8 @@ static int vfp_set(struct task_struct *target,
>  	if (ret)
>  		return ret;
>  
> -	vfp_flush_hwstate(thread);
>  	thread->vfpstate.hard = new_vfp;
> +	vfp_flush_hwstate(thread);
>  
>  	return 0;
>  }
> 
> 
> -- 
> RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From daniel.lezcano at linaro.org  Mon May 30 15:56:36 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 31 May 2016 00:56:36 +0200
Subject: [PATCH v5 4/6] acpi: Add GTDT table parse driver into ACPI driver
In-Reply-To: <1464096633-9309-5-git-send-email-fu.wei@linaro.org>
References: <1464096633-9309-1-git-send-email-fu.wei@linaro.org>
 <1464096633-9309-5-git-send-email-fu.wei@linaro.org>
Message-ID: <574CC524.5090601@linaro.org>

On 05/24/2016 03:30 PM, fu.wei at linaro.org wrote:
> From: Fu Wei <fu.wei at linaro.org>
>
> This driver adds support for parsing all kinds of timer in GTDT:
> (1)arch timer: provide a kernel API to parse all the PPIs and
> always-on info in GTDT and export them by filling the structs
> which provided by parameters(pointer of them).
>
> (2)memory-mapped timer: provide a kernel APIs to parse
> GT Block Structure in GTDT, export all the timer info by filling
> the struct which provided by parameter(pointer of the struct).
>
> (3)SBSA Generic Watchdog: parse all info in SBSA Generic Watchdog
> Structure in GTDT, and creating a platform device with that
> information. This allows the operating system to obtain device
> data from the resource of platform device.
> The platform device named "sbsa-gwdt" can be used by the ARM SBSA
> Generic Watchdog driver.
>
> By this driver, we can simplify all the relevant drivers, and
> separate all the ACPI GTDT knowledge from them.
>
> Signed-off-by: Fu Wei <fu.wei at linaro.org>
> Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>

Hi Fu Wei,

the code is better than the previous version but it is still confusing. 
There are global variables accessed several times by different functions 
and modified. This is an encapsulation issue.

This code is a bit hard to follow.

Please split it out into 4 patches:

1. Create a clean base with helper functions and proper encapsulation 
for gtdt.

2. Add gtdt timer based code

3. Add gtdt mem timer based code

4. Add gtdt watchdog based code

Comments below.

Thanks !

   -- Daniel

> ---
>   drivers/acpi/Kconfig                 |   9 +
>   drivers/acpi/Makefile                |   1 +
>   drivers/acpi/acpi_gtdt.c             | 309 +++++++++++++++++++++++++++++++++++
>   include/clocksource/arm_arch_timer.h |  16 ++
>   include/linux/acpi.h                 |   6 +
>   5 files changed, 341 insertions(+)
>
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index b7e2e77..27a5cf9 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -521,4 +521,13 @@ config XPOWER_PMIC_OPREGION
>
>   endif
>
> +config ACPI_GTDT
> +	bool "ACPI GTDT Support"
> +	depends on ARM64
> +	help
> +	  GTDT (Generic Timer Description Table) provides information
> +	  for per-processor timers and Platform (memory-mapped) timers
> +	  for ARM platforms. Select this option to provide information
> +	  needed for the timers init.

Why not ARM64's Kconfig select ACPI_GTDT ?

This config option assumes an user will manually select this option 
which I believe it makes sense to have always on when ARM64=y. So why 
not create a silent option and select it directly from the ARM64 
platform Kconfig ?

>   endif	# ACPI
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 251ce85..848aa8a 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -99,5 +99,6 @@ obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
>   obj-$(CONFIG_PMIC_OPREGION)	+= pmic/intel_pmic.o
>   obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o
>   obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o
> +obj-$(CONFIG_ACPI_GTDT)		+= acpi_gtdt.o
>
>   video-objs			+= acpi_video.o video_detect.o
> diff --git a/drivers/acpi/acpi_gtdt.c b/drivers/acpi/acpi_gtdt.c
> new file mode 100644
> index 0000000..e54fadf
> --- /dev/null
> +++ b/drivers/acpi/acpi_gtdt.c
> @@ -0,0 +1,309 @@
> +/*
> + * ARM Specific GTDT table Support
> + *
> + * Copyright (C) 2015, Linaro Ltd.
> + * Author: Fu Wei <fu.wei at linaro.org>
> + *         Hanjun Guo <hanjun.guo at linaro.org>
> + *
> + * 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/acpi.h>
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#include <clocksource/arm_arch_timer.h>
> +
> +#undef pr_fmt
> +#define pr_fmt(fmt) "GTDT: " fmt
> +
> +typedef int (*platform_timer_handler)(void *platform_timer, int index,
> +				      void *data);
> +
> +static void *platform_timer_struct __initdata;
> +static u32 platform_timer_count __initdata;
> +static void *gtdt_end __initdata;

I am pretty sure you can get ride of these global variables with a 
little effort.

> +static int __init for_platform_timer(enum acpi_gtdt_type type,
> +				     platform_timer_handler handler, void *data)

For the clarity of the code, I suggest to use a macro with a name 
similar to what we find in the kernel:

#define gtdt_for_each(type, ...) ...
#define gtdt_for_each_timer gtdt_for_each(ACPI_GTDT_TYPE_TIMER_BLOCK)
#define gtdt_for_each_wd    gtdt_for_each(ACPI_GTDT_TYPE_WATCHDOG)

... and rework this function to clarify its purpose.

What is for ? Count the number of 'type' which succeed to call the handler ?

> +{
> +	struct acpi_gtdt_header *header;
> +	int i, index, ret;
> +	void *platform_timer = platform_timer_struct;
> +
> +	for (i = 0, index = 0; i < platform_timer_count; i++) {
> +		if (platform_timer > gtdt_end) {
> +			pr_err(FW_BUG "subtable pointer overflows.\n");
> +			platform_timer_count = i;

Fix firmware bug in the kernel ? No. Up to the firmware to fix it, "no 
handy, no candy".

> +			break;
> +		}
> +		header = (struct acpi_gtdt_header *)platform_timer;
> +		if (header->type == type) {
> +			ret = handler(platform_timer, index, data);
> +			if (ret)
> +				pr_err("failed to handler subtable %d.\n", i);
> +			else
> +				index++;
> +		}
> +		platform_timer += header->length;

That is not correct. This function is setting the platform_timer pointer 
to the end. Even if that works, it violates the encapsulation paradigm. 
Regarding how are used those global variables, please kill them and use 
proper parameter and structure encapsulation.

> +	}
> +
> +	return index;
> +}
> +
> +/*
> + * Get some basic info from GTDT table, and init the global variables above
> + * for all timers initialization of Generic Timer.
> + * This function does some validation on GTDT table, and will be run only once.
> + */
> +static void __init platform_timer_init(struct acpi_table_header *table,
> +				       struct acpi_table_gtdt *gtdt)
> +{
> +	gtdt_end = (void *)table + table->length;
> +
> +	if (table->revision < 2) {
> +		pr_info("Revision:%d doesn't support Platform Timers.\n",
> +			table->revision);
> +		return;
> +	}

This check should be called much sooner, before entering the gtdt 
subsystems. It is too late here.

> +	platform_timer_count = gtdt->platform_timer_count;
> +	if (!platform_timer_count) {
> +		pr_info("No Platform Timer structures.\n");
> +		return;
> +	}
> +
> +	platform_timer_struct = (void *)gtdt + gtdt->platform_timer_offset;
> +	if (platform_timer_struct < (void *)table +
> +				    sizeof(struct acpi_table_gtdt)) {
> +		pr_err(FW_BUG "Platform Timer pointer error.\n");
> +		platform_timer_struct = NULL;
> +		platform_timer_count = 0;
> +	}

Why this check ?

> +}
> +
> +static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
> +{
> +	int trigger, polarity;
> +
> +	if (!interrupt)
> +		return 0;
> +
> +	trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
> +			: ACPI_LEVEL_SENSITIVE;
> +
> +	polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
> +			: ACPI_ACTIVE_HIGH;
> +
> +	return acpi_register_gsi(NULL, interrupt, trigger, polarity);
> +}
> +
> +/*
> + * Get the necessary info of arch_timer from GTDT table.
> + */
> +int __init gtdt_arch_timer_init(struct acpi_table_header *table, int *ppi,
> +				bool *c3stop, u32 *timer_count)
> +{
> +	struct acpi_table_gtdt *gtdt;

This API is not correctly separating both subsystems. Moving the code 
from the arch_arm_timer init function here is not the solution.

I suggest the following:

1. Change CLOCKSOURCE_ACPI_DECLARE to pass the init function as:

int __init gtdt_init(struct acpi_table_gtdt *gtdt);

2. Add helpers:

	int gtdt_map_irq(struct acpi_table_gtdt *gtdt, int flags);

	int gtdt_c3stop(struct acpi_table_gtdt *gtdt);

3. Export these helpers

arch_arm_timer.c should see nothing more than:

struct acpi_table_gtdt;

4. Use these helpers in the arch_arm_timer.c

static int __init arch_timer_acpi_init(struct acpi_table_gtdt *gtdt)
{
	arch_timer_ppi[PHYS_SECURE_PPI]    = gtdt_map_irq(gtdt, flags);
	arch_timer_ppi[PHYS_NONSECURE_PPI] = gtdt_map_irq(gtdt, flags);
	arch_timer_ppi[VIRT_PPI]           = gtdt_map_irq(gtdt, flags);
	arch_timer_ppi[HYP_PPI]            = gtdt_map_irq(gtdt, flags);
	arch_timer_c3stop                  = gtdt_c3stop(gtdt);

	arch_timer_init();

	return 0;
}

> +	if (acpi_disabled || !table || !ppi || !c3stop)
> +		return -EINVAL;

Why acpi_disabled is an error here but ok for gtdt_sbsa_gwdt_init() ?

> +	gtdt = container_of(table, struct acpi_table_gtdt, header);
> +	if (!gtdt) {
> +		pr_err("table pointer error.\n");
> +		return -EINVAL;
> +	}
> +
> +	ppi[PHYS_SECURE_PPI] =
> +		map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
> +					    gtdt->secure_el1_flags);
> +
> +	ppi[PHYS_NONSECURE_PPI] =
> +		map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
> +					    gtdt->non_secure_el1_flags);
> +
> +	ppi[VIRT_PPI] =
> +		map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
> +					    gtdt->virtual_timer_flags);
> +
> +	ppi[HYP_PPI] =
> +		map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
> +					    gtdt->non_secure_el2_flags);
> +
> +	*c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
> +
> +	platform_timer_init(table, gtdt);
> +	if (timer_count)
> +		*timer_count = platform_timer_count;

come on !

> +
> +	return 0;
> +}
> +
> +/*
> + * Helper function for getting the pointer of a timer frame in GT block.
> + */
> +static void __init *gtdt_gt_timer_frame(struct acpi_gtdt_timer_block *gt_block,
> +					int index)
> +{
> +	void *timer_frame = (void *)gt_block + gt_block->timer_offset +
> +			    sizeof(struct acpi_gtdt_timer_entry) * index;
> +
> +	if (timer_frame <= (void *)gt_block + gt_block->header.length -
> +			   sizeof(struct acpi_gtdt_timer_entry))
> +		return timer_frame;
> +
> +	return NULL;
> +}
> +
> +static int __init gtdt_parse_gt_block(void *platform_timer, int index,
> +				      void *data)
> +{
> +	struct acpi_gtdt_timer_block *block;
> +	struct acpi_gtdt_timer_entry *frame;
> +	struct gt_block_data *block_data;
> +	int i, j;
> +
> +	if (!platform_timer || !data)
> +		return -EINVAL;
> +
> +	block = platform_timer;
> +	block_data = data + sizeof(struct gt_block_data) * index;
> +
> +	if (!block->block_address || !block->timer_count) {
> +		pr_err(FW_BUG "invalid GT Block data.\n");
> +		return -EINVAL;
> +	}
> +	block_data->cntctlbase_phy = (phys_addr_t)block->block_address;
> +	block_data->timer_count = block->timer_count;
> +
> +	/*
> +	 * Get the GT timer Frame data for every GT Block Timer
> +	 */
> +	for (i = 0, j = 0; i < block->timer_count; i++) {
> +		frame = gtdt_gt_timer_frame(block, i);
> +		if (!frame || !frame->base_address || !frame->timer_interrupt) {
> +			pr_err(FW_BUG "invalid GT Block Timer data, skip.\n");
> +			continue;
> +		}
> +		block_data->timer[j].frame_nr = frame->frame_number;
> +		block_data->timer[j].cntbase_phy = frame->base_address;
> +		block_data->timer[j].irq = map_generic_timer_interrupt(
> +						   frame->timer_interrupt,
> +						   frame->timer_flags);
> +		if (frame->virtual_timer_interrupt)
> +			block_data->timer[j].virt_irq =
> +				map_generic_timer_interrupt(
> +					frame->virtual_timer_interrupt,
> +					frame->virtual_timer_flags);
> +		j++;
> +	}
> +
> +	if (j)
> +		return 0;
> +
> +	block_data->cntctlbase_phy = (phys_addr_t)NULL;
> +	block_data->timer_count = 0;
> +
> +	return -EINVAL;
> +}
> +
> +/*
> + * Get the GT block info for memory-mapped timer from GTDT table.
> + * Please make sure we have called gtdt_arch_timer_init, because it helps to
> + * init the global variables.
> + */
> +int __init gtdt_arch_timer_mem_init(struct gt_block_data *data)
> +{
> +	int ret = for_platform_timer(ACPI_GTDT_TYPE_TIMER_BLOCK,
> +				     gtdt_parse_gt_block, (void *)data);

(void *) explicit cast is not needed.

> +	pr_info("found %d memory-mapped timer block.\n", ret);
> +
> +	return ret;
> +}
> +
> +/*
> + * Initialize a SBSA generic Watchdog platform device info from GTDT
> + */
> +static int __init gtdt_import_sbsa_gwdt(void *platform_timer,
> +					int index, void *data)
> +{
> +	struct platform_device *pdev;
> +	struct acpi_gtdt_watchdog *wd = platform_timer;
> +	int irq = map_generic_timer_interrupt(wd->timer_interrupt,
> +					      wd->timer_flags);
> +	int no_irq = 1;
> +
> +	/*
> +	 * According to SBSA specification the size of refresh and control
> +	 * frames of SBSA Generic Watchdog is SZ_4K(Offset 0x000 ? 0xFFF).
> +	 */
> +	struct resource res[] = {
> +		DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
> +		DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
> +		DEFINE_RES_IRQ(irq),
> +	};
> +
> +	pr_debug("a Watchdog GT(0x%llx/0x%llx gsi:%u flags:0x%x).\n",
> +		 wd->refresh_frame_address, wd->control_frame_address,
> +		 wd->timer_interrupt, wd->timer_flags);
> +
> +	if (!(wd->refresh_frame_address && wd->control_frame_address)) {
> +		pr_err(FW_BUG "failed getting the Watchdog GT frame addr.\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!wd->timer_interrupt)
> +		pr_warn(FW_BUG "failed getting the Watchdog GT GSIV.\n");
> +	else if (irq <= 0)
> +		pr_warn("failed to map the Watchdog GT GSIV.\n");
> +	else
> +		no_irq = 0;
> +
> +	/*
> +	 * Add a platform device named "sbsa-gwdt" to match the platform driver.
> +	 * "sbsa-gwdt": SBSA(Server Base System Architecture) Generic Watchdog
> +	 * The platform driver (like drivers/watchdog/sbsa_gwdt.c)can get device
> +	 * info below by matching this name.
> +	 */
> +	pdev = platform_device_register_simple("sbsa-gwdt", index, res,
> +					       ARRAY_SIZE(res) - no_irq);
> +	if (IS_ERR(pdev)) {
> +		acpi_unregister_gsi(wd->timer_interrupt);
> +		return PTR_ERR(pdev);
> +	}
> +
> +	return 0;
> +}
> +
> +static int __init gtdt_sbsa_gwdt_init(void)
> +{
> +	struct acpi_table_header *table;
> +	struct acpi_table_gtdt *gtdt;
> +	int ret;
> +
> +	if (acpi_disabled)
> +		return 0;
> +
> +	if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_GTDT, 0, &table)))
> +		return -EINVAL;
> +
> +	/* global variables initialization */
> +	gtdt_end = (void *)table + table->length;

That is prone to bug. The end of the table is computed here and stored 
in the global variable and then computed again in platform_timer_init 
and also stored in the global variable.

Kill this global variable.

> +	gtdt = container_of(table, struct acpi_table_gtdt, header);
> +	platform_timer_struct = (void *)gtdt + gtdt->platform_timer_offset;
> +
> +	ret = for_platform_timer(ACPI_GTDT_TYPE_WATCHDOG,
> +				 gtdt_import_sbsa_gwdt, NULL);
> +	pr_info("found %d SBSA generic Watchdog.\n", ret);
> +
> +	return 0;
> +}
> +
> +device_initcall(gtdt_sbsa_gwdt_init);

Do you really have to call device_initcall ?


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

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



From daniel.lezcano at linaro.org  Mon May 30 16:09:45 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 31 May 2016 01:09:45 +0200
Subject: [PATCH 2/5] clocksource: rockchip: remove unnecessary clear irq
 before request_irq
In-Reply-To: <1464169802-6033-3-git-send-email-wxt@rock-chips.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
 <1464169802-6033-3-git-send-email-wxt@rock-chips.com>
Message-ID: <574CC839.60608@linaro.org>

On 05/25/2016 11:49 AM, Caesar Wang wrote:
> From: Huang Tao <huangtao at rock-chips.com>
>
> rk_timer_interrupt_clear and rk_timer_disable is unnecessary before
> request_irq. Timer should keep disabled before booting Linux.

That's true in the perfect world :/ Some version has u-boot letting the 
timer with irq enabled, therefore as soon as request_irq is done, an irq 
fires and leads to a kernel panic.

On the other side, this timer is not used on the other rockchip version 
than rk3399 because of no need of a broadcast timer, so removing these 
two lines may be acceptable.

Can try the changes with another board, eg rk3288 (and forcing to use 
this timer). Can you do the test and confirm it does not break with 
different version of u-boot ?

Thanks!

   -- Daniel

> Signed-off-by: Huang Tao <huangtao at rock-chips.com>
> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
> Cc: Thomas Gleixner <tglx at linutronix.de>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Tested-by: Jianqun Xu <jay.xu at rock-chips.com>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> ---
>
>   drivers/clocksource/rockchip_timer.c | 3 ---
>   1 file changed, 3 deletions(-)
>
> diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c
> index b991b28..b93fed6 100644
> --- a/drivers/clocksource/rockchip_timer.c
> +++ b/drivers/clocksource/rockchip_timer.c
> @@ -158,9 +158,6 @@ static void __init rk_timer_init(struct device_node *np)
>   	ce->cpumask = cpumask_of(0);
>   	ce->rating = 250;
>
> -	rk_timer_interrupt_clear(ce);
> -	rk_timer_disable(ce);
> -
>   	ret = request_irq(irq, rk_timer_interrupt, IRQF_TIMER, TIMER_NAME, ce);
>   	if (ret) {
>   		pr_err("Failed to initialize '%s': %d\n", TIMER_NAME, ret);
>


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

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



From daniel.lezcano at linaro.org  Mon May 30 16:16:46 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 31 May 2016 01:16:46 +0200
Subject: [PATCH 3/5] clocksource: rockchip: add dynamic irq flag to the
 timer
In-Reply-To: <1464169802-6033-4-git-send-email-wxt@rock-chips.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
 <1464169802-6033-4-git-send-email-wxt@rock-chips.com>
Message-ID: <574CC9DE.1050501@linaro.org>

On 05/25/2016 11:50 AM, Caesar Wang wrote:
> From: Huang Tao <huangtao at rock-chips.com>
>
> The rockchip timer is broadcast timer. Add CLOCK_EVT_FEAT_DYNIRQ
> flag and set cpumask to all cpu to save power by avoid unnecessary
> wakeups and IPIs.
>
> Signed-off-by: Huang Tao <huangtao at rock-chips.com>
> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
> Cc: Thomas Gleixner <tglx at linutronix.de>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Tested-by: Jianqun Xu <jay.xu at rock-chips.com>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> ---
>
>   drivers/clocksource/rockchip_timer.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c
> index b93fed6..f3dfb1a 100644
> --- a/drivers/clocksource/rockchip_timer.c
> +++ b/drivers/clocksource/rockchip_timer.c
> @@ -150,12 +150,13 @@ static void __init rk_timer_init(struct device_node *np)
>   	}
>
>   	ce->name = TIMER_NAME;
> -	ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
> +	ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
> +		       CLOCK_EVT_FEAT_DYNIRQ;
>   	ce->set_next_event = rk_timer_set_next_event;
>   	ce->set_state_shutdown = rk_timer_shutdown;
>   	ce->set_state_periodic = rk_timer_set_periodic;
>   	ce->irq = irq;
> -	ce->cpumask = cpumask_of(0);
> +	ce->cpumask = cpu_all_mask;

s/cpu_all_mask/cpu_possible_mask/

>   	ce->rating = 250;
>
>   	ret = request_irq(irq, rk_timer_interrupt, IRQF_TIMER, TIMER_NAME, ce);
>


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

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



From chanho.min at lge.com  Mon May 30 16:25:27 2016
From: chanho.min at lge.com (Chanho Min)
Date: Tue, 31 May 2016 08:25:27 +0900
Subject: [PATCH] arm64: dts: drop "arm,
 amba-bus" in favor of "simple-bus" part 2
In-Reply-To: <1464574353-31477-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464574353-31477-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <021901d1baca$8ddf8050$a99e80f0$@lge.com>

> Subject: [PATCH] arm64: dts: drop "arm,amba-bus" in favor of "simple-bus" part
> 2
> 
> Tree-wide replacement was done by commit 2ef7d5f342c1 (ARM, ARM64:
> dts: drop "arm,amba-bus" in favor of "simple-bus"), but we have some
> new users of "arm,amba-bus" at Linux 4.7-rc1.  Eliminate them now.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> ---
> 
> In order to not leave these compatible strings for the release,
> is it OK to apply this patch for Linux 4.7 ?
> 
> 
> 
>  arch/arm64/boot/dts/lg/lg1312.dtsi       | 2 +-
>  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 

> diff --git a/arch/arm64/boot/dts/lg/lg1312.dtsi
> b/arch/arm64/boot/dts/lg/lg1312.dtsi
> index 3a4e9a2..fbafa24 100644
> --- a/arch/arm64/boot/dts/lg/lg1312.dtsi
> +++ b/arch/arm64/boot/dts/lg/lg1312.dtsi
> @@ -125,7 +125,7 @@
>  		#size-cells = <1>;
>  		#interrupts-cells = <3>;
> 
> -		compatible = "arm,amba-bus";
> +		compatible = "simple-bus";
>  		interrupt-parent = <&gic>;
>  		ranges;
> 

Acked-by: Chanho Min <chanho.min at lge.com>

> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> index 46f325a..d7f8e06 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -163,7 +163,7 @@
>  	};
> 
>  	amba {
> -		compatible = "arm,amba-bus";
> +		compatible = "simple-bus";
>  		#address-cells = <2>;
>  		#size-cells = <2>;
>  		ranges;
> --
> 1.9.1



From daniel.lezcano at linaro.org  Mon May 30 16:28:52 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 31 May 2016 01:28:52 +0200
Subject: [PATCH 4/5] clocksource: rockchip: add support for rk3399 SoC
In-Reply-To: <1464169802-6033-5-git-send-email-wxt@rock-chips.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
 <1464169802-6033-5-git-send-email-wxt@rock-chips.com>
Message-ID: <574CCCB4.1030001@linaro.org>

On 05/25/2016 11:50 AM, Caesar Wang wrote:
> From: Huang Tao <huangtao at rock-chips.com>
>
> The CONTROL register offset is different from old SoCs.
> For Linux driver, there are not functional changes at all.
> Let's call it v2.
>
> Signed-off-by: Huang Tao <huangtao at rock-chips.com>
> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
> Cc: Thomas Gleixner <tglx at linutronix.de>
> Cc: Heiko Stuebner <heiko at sntech.de>
> Tested-by: Jianqun Xu <jay.xu at rock-chips.com>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> ---

That's hackish.

Please consider something like:

diff --git a/drivers/clocksource/rockchip_timer.c 
b/drivers/clocksource/rockchip_timer.c
index b991b28..b6ba6f9 100644
--- a/drivers/clocksource/rockchip_timer.c
+++ b/drivers/clocksource/rockchip_timer.c
@@ -19,7 +19,8 @@

  #define TIMER_LOAD_COUNT0	0x00
  #define TIMER_LOAD_COUNT1	0x04
-#define TIMER_CONTROL_REG	0x10
+#define TIMER_CONTROL_REG3288	0x10
+#define TIMER_CONTROL_REG3399	0x1C
  #define TIMER_INT_STATUS	0x18

  #define TIMER_DISABLE		0x0
@@ -31,6 +32,7 @@
  struct bc_timer {
  	struct clock_event_device ce;
  	void __iomem *base;
+	void __iomem *ctrl;
  	u32 freq;
  };

@@ -46,15 +48,20 @@ static inline void __iomem *rk_base(struct 
clock_event_device *ce)
  	return rk_timer(ce)->base;
  }

+static inline void __iomem *rk_ctrl(struct clock_event_device *ce)
+{
+        return rk_timer(ce)->ctrl;
+}
+
  static inline void rk_timer_disable(struct clock_event_device *ce)
  {
-	writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_CONTROL_REG);
+	writel_relaxed(TIMER_DISABLE, rk_ctrl(ce));
  }

  static inline void rk_timer_enable(struct clock_event_device *ce, u32 
flags)
  {
  	writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags,
-		       rk_base(ce) + TIMER_CONTROL_REG);
+		       rk_ctrl(ce));
  }

  static void rk_timer_update_counter(unsigned long cycles,
@@ -179,4 +186,18 @@ out_unmap:
  	iounmap(bc_timer.base);
  }

-CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init);
+static void __init rk3288_timer_init(struct device_node *np)
+{
+	bc_timer.ctrl = TIMER_CONTROL_REG3288;
+	rk_timer_init(np);
+}
+
+static void __init rk3399_timer_init(struct device_node *np)
+{
+        bc_timer.ctrl = TIMER_CONTROL_REG3399;
+	rk_timer_init(np);
+}
+
+
+CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", 
rk3288_timer_init);
+CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3399-timer", 
rk3399_timer_init);




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

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



From javier at osg.samsung.com  Mon May 30 17:20:22 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Mon, 30 May 2016 20:20:22 -0400
Subject: [PATCH] drm/exynos: fimd: don't set .has_hw_trigger in s3c6400 driver
 data
Message-ID: <1464654022-344-1-git-send-email-javier@osg.samsung.com>

The field value is only checked in fimd_setup_trigger() if .trg_type is
I80_HW_TRG so there's no point in setting this field for the s3c6400 if
is never going to be used since .trg_type is not set.

Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
---

 drivers/gpu/drm/exynos/exynos_drm_fimd.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 3efe1aa89416..1c23a8ff5e83 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -120,7 +120,6 @@ static struct fimd_driver_data s3c64xx_fimd_driver_data = {
 	.timing_base = 0x0,
 	.has_clksel = 1,
 	.has_limited_fmt = 1,
-	.has_hw_trigger = 1,
 };
 
 static struct fimd_driver_data exynos3_fimd_driver_data = {
-- 
2.5.5



From takahiro.akashi at linaro.org  Mon May 30 17:34:27 2016
From: takahiro.akashi at linaro.org (AKASHI Takahiro)
Date: Tue, 31 May 2016 09:34:27 +0900
Subject: Help needed with kexec on arm64
In-Reply-To: <DB5PR04MB16887FF10CEA6AA9BF990F0DE6420@DB5PR04MB1688.eurprd04.prod.outlook.com>
References: <CAB5YjtBEO=efjhcFdVOaZqG13qK3uzCbS5SFym5hhw-n+_QLhw@mail.gmail.com>
 <DB5PR04MB1688A6D4385B76DAFF71D364E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtAqjL8LMvNPbxwVWe+Zhi5rFkz_X7rti9wSrXQ7Y_2kOA@mail.gmail.com>
 <DB5PR04MB16880834700413C3B80194B5E68C0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <CAB5YjtCP6M9=ESJhfxyyYKSGTg8s3Y83qp8RS_oyYkUqcqYcCw@mail.gmail.com>
 <DB5PR04MB168874758924173BBD5CC037E69D0@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160405052341.GA19476@linaro.org>
 <DB5PR04MB1688F09062B2A5ECACCA4D80E6710@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160511005334.GA8417@linaro.org>
 <DB5PR04MB1688C3F122091109E6BD9B68E6740@DB5PR04MB1688.eurprd04.prod.outlook.com>
 <20160519110307.GA4941@linaro.org>
 <DB5PR04MB16887FF10CEA6AA9BF990F0DE6420@DB5PR04MB1688.eurprd04.prod.outlook.com>
Message-ID: <574CDC13.9090709@linaro.org>

On 05/27/2016 08:51 PM, Harninder Rai wrote:
> Hello Takahiro Akashi,
>
> Please see the following log which I was talking about in my last communication
> Any idea as to what could be wrong just when I move from RAM based rootfs to SD based rootfs?
>
>> I did check /proc/iomem and everything looks there. This is very strange
>> since if I keep everything same and just move the rootfs from RAM based to
>> SD based, I start getting this issue.
>
> root at ls2085ardb:/# kexec -p ./vmlinux.wor --initrd=./initramfs_arm64_busybox1_22_1_with_coremark.cpio.gz --append='console=ttyS1,115200 root=/dev/ram0 earlycon=uart8250,mmio,0x21c0600ramdisk_size=0x2000000 default_hugepagesz=2m hugepagesz=2m hugepages=256 memblock=debug maxcpus=1'
> Memory for crashkernel is not reserved
> Please reserve memory by passing"crashkernel=X at Y" parameter to kernel
> Then try to loading kdump kernel
> root at ls2085ardb:/# cat /proc/iomem
> 02000000-0200ffff : /i2c at 2000000
> 02140000-0214ffff : mmc0
> 021c0500-021c05ff : serial
> 021c0600-021c06ff : serial
> 03100000-03107fff : /usb3 at 3100000
> 0310c100-0310ffff : /usb3 at 3100000
> 03110000-03117fff : /usb3 at 3110000
> 0311c100-0311ffff : /usb3 at 3110000
> 05000000-057fffff : /iommu at 5000000
> 80000000-ffffffff : System RAM
>    80080000-80a39333 : Kernel code
>    80af5000-80bd4fff : Kernel data
>    8c000000-8fffffff : Crash kernel
> 80c000000-80c00003f : mc_portal


Please trace is_crashkernel_mem_reserved() and kexec_iomem_for_each_line().

-Takahiro AKASHI

> Regards
> Harry++
>


From hzpeterchen at gmail.com  Mon May 30 17:58:08 2016
From: hzpeterchen at gmail.com (Peter Chen)
Date: Tue, 31 May 2016 08:58:08 +0800
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <20160528033613.GA3291@shlinux2>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <20160505224240.GA31429@rob-hp-laptop>
 <CAPDyKFqpoi03Egfuvd8qJXnn_+FBgPXAb7S4UvkxVs8BA+zwnA@mail.gmail.com>
 <20160509181829.GA19687@rob-hp-laptop>
 <CAPDyKFq2=mqujFjvJSYxg2nVmK=OrBKLtFfb-ErNJO3Zr_LMVw@mail.gmail.com>
 <20160528033613.GA3291@shlinux2>
Message-ID: <20160531005808.GA7913@shlinux2>

On Sat, May 28, 2016 at 11:36:13AM +0800, Peter Chen wrote:
> On Tue, May 10, 2016 at 01:02:08PM +0200, Ulf Hansson wrote:
> > + Arnd
> > 
> > [...]
> > 
> > >> >> Solution
> > >> >> ========
> > >> >> This is very similar to the MMC pwrseq behavior so the idea is to:
> > >> >> 1. Move MMC pwrseq drivers to generic place,
> > >> >
> > >> > You can do that, but I'm going to NAK any use of pwrseq bindings outside
> > >> > of MMC. I think it is the wrong way to do things. The DT should describe
> > >>
> > >> Huh, I didn't know that was your view of the mmc pwrseq bindings. Why
> > >> didn't you NAK them before?
> > >
> > > Unfortunately, either I missed it or it was a time I couldn't spend much
> > > time on reviews.
> > 
> > Okay, I guess it's common issue among maintainers. The problem with DT
> > is that it gets really hard to be fixed up later. :-)
> > 
> > >
> > >> > the devices. If they happen to be "simple" then the core can walk the
> > >> > tree and do any setup. For example, look for "reset-gpios" and toggle
> > >> > that GPIO. There is no need for a special node.
> > >> >
> > >> >> 2. Extend the pwrseq-simple with regulator toggling,
> > >> >> 3. Add support to USB hub and port core for pwrseq,
> > >> >
> > >> > We discussed this for USB already[1] and is why we defined how to add
> > >> > USB child devices. The idea is not to add pwrseq to that.
> > >>
> > >> I am not familiar with the USB discussion.
> > >>
> > >> Still, let me give you some more background to the mmc pwrseq. The
> > >> idea from the mmc pwrseq bindings comes from the power-domain DT
> > >> bindings, as I thought these things were a bit related.
> > >> In both cases they are not directly a property of the device, but more
> > >> describing a HW dependency to allow the device to work.
> > >
> > > I could see this as a board level power domain. However the difference
> > > is we are not generally exposing internal SOC details the same way as
> > > board level components. Perhaps we could extend power domains to board
> > > level, but that is not what was done here.
> > >
> > >> One could probably use a child node instead of a phandle, but that
> > >> wasn't chosen back then. Of course you are the DT expert, but could
> > >> you perhaps tell me why a child node is better for cases like this?
> > >
> > > If there is a control path hierarchy, then we try to model that in DT
> > > with child nodes. In cases of SDIO and USB, there is a clear hierarchy.
> > > Ignoring the discovery ordering problem, we already have defined ways to
> > > describe GPIO connections, regulators, etc. to devices. Describing those
> > > things separately from the device to solve a particular issue that is
> > > really a kernel limitation is what I don't like.
> > 
> > Okay, I see.
> > 
> > To move forward in trying to make mmc pwrseq a generic pwrseq, could
> > we perhaps allow both cases?
> > 
> > In the mmc case, there are already deployed bindings so we need to
> > cope with these by using the phandle option, but for USB etc we could
> > force the child node option.
> > As long as we agree that we keep using a compatible string for the
> > child node as well, both options should be able to co-exist and we
> > should probably be able to managed them both from a common pwrseq
> > driver framework.
> > 
> > Although, I do remember from an older conversations around some of
> > mine submission for the mmc pwrseq code, that some people (maybe
> > Arnd?) wasn't keen on adding a new framework for this. Perhaps that
> > has changed?
> > 
> 
> All, how we move on for this?
> 
> 1. Using a generic driver to manage both mmc and USB (and further
> subsystem), USB and further subsystem do not use pwrseq node in dts.
> 2. USB creates the similar driver under drivers/usb for its own use. 
> 
> Which one do you prefer, thanks.
> 

Hi Krzysztof Kozlowski,

I think option 1 may be better according to Rob and Ulf's comment.
Would you like going on your patch set? You can work on generic pwrseq
driver, I will do USB stuffs based on generic pwrseq driver?

-- 

Best Regards,
Peter Chen


From jszhang at marvell.com  Mon May 30 18:53:57 2016
From: jszhang at marvell.com (Jisheng Zhang)
Date: Tue, 31 May 2016 09:53:57 +0800
Subject: building and using modules on arm64 hikey board
In-Reply-To: <574C8C69.6020501@broadcom.com>
References: <87a3195c-febb-a6c8-a679-272b9f7b59cc@broadcom.com>
 <0240F9F0-0146-4DCC-B512-195415B29B34@linaro.org>
 <574C8C69.6020501@broadcom.com>
Message-ID: <20160531095357.3eb6548c@xhacker>

On Mon, 30 May 2016 20:54:33 +0200
Arend van Spriel <arend.vanspriel at broadcom.com> wrote:

> On 30-05-16 13:30, Ard Biesheuvel wrote:
> > This is likely caused by the fact that the Android AArch64 toolchain uses -fpic by default. Could you try adding -fno-pic to the CFLAGS?  
> 
> I did only to notice with 'make V=1 ...' that it was already used hence
> showing up in the compile command line twice. To no avail so that ain't
> working.

Per my experience, the default ld in android toolchain is gold, can you plz try
to use ld.bfd instead?

> 
> Regards,
> Arend
> 
> >> On 30 mei 2016, at 12:21, Arend Van Spriel <arend.vanspriel at broadcom.com> wrote:
> >>
> >> I got myself an arm64 HiKey board from LeMaker and build an Android AOSP
> >> image for it (see [1]). For development I would like to use
> >> CONFIG_MODULES. However, when I try to insmod the build module I get:
> >>
> >> [  287.903653] module cfg80211: overflow in relocation type 261 val
> >> ffffffbffc006530
> >>
> >> Looking AArch64 ELF documentation [2], section 4.6.5, it has:
> >> code|name            |operation |overflow check   |
> >> 261 |R_AARCH64_PREL32|S + A - P |-2^31 <= X < 2^32|
> >>
> >> So basically the highest 32 bits should all be one and so ffffffbf is
> >> invalid. From what I could find searching internet it could be an issue
> >> with linker options so I build kernel and modules with V=1. Here the
> >> linker invocation for them:
> >>
> >> + aarch64-linux-android-ld -EL -p --no-undefined -X --build-id -o vmlinux \
> >> -T ./arch/arm64/kernel/vmlinux.lds arch/arm64/kernel/head.o
> >> init/built-in.o \
> >> --start-group usr/built-in.o arch/arm64/kernel/built-in.o
> >> arch/arm64/mm/built-in.o \
> >> arch/arm64/net/built-in.o arch/arm64/kvm/built-in.o
> >> arch/arm64/crypto/built-in.o \
> >> ./drivers/firmware/efi/libstub/lib.a kernel/built-in.o certs/built-in.o
> >> mm/built-in.o \
> >> fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o
> >> block/built-in.o \
> >> arch/arm64/lib/lib.a lib/lib.a arch/arm64/lib/built-in.o lib/built-in.o
> >> drivers/built-in.o \
> >> sound/built-in.o firmware/built-in.o net/built-in.o virt/built-in.o
> >> --end-group .tmp_kallsyms2.o
> >>
> >>  aarch64-linux-android-ld -EL -r  -T ./scripts/module-common.lds
> >> --build-id \
> >>  -o net/wireless/cfg80211.ko net/wireless/cfg80211.o
> >> net/wireless/cfg80211.mod.o
> >>
> >> Attached are vmlinux.lds and module-common.lds. I also tried taking
> >> upstream arch/arm64/kernel/module.lds in hikey-linaro tree. If someone
> >> can give a hint or educated guess at what to try it would be appreciated.
> >>
> >> Regards,
> >> Arend
> >>
> >> [1] https://source.android.com/source/devices.html#building-kernel
> >> [2]
> >> http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
> >> <module-common.lds>
> >> <vmlinux.lds>  
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



From shubhrajyoti.datta at gmail.com  Mon May 30 19:29:01 2016
From: shubhrajyoti.datta at gmail.com (Shubhrajyoti Datta)
Date: Tue, 31 May 2016 07:59:01 +0530
Subject: [PATCH v4] Axi-usb: Add support for 64-bit addressing.
In-Reply-To: <1464626798-1334-1-git-send-email-navam@xilinx.com>
References: <1464626798-1334-1-git-send-email-navam@xilinx.com>
Message-ID: <CAKfKVtF1hOn9QwiqtjqqPYtUz5PscTBs4kBC1zRH6FY-4vVoUA@mail.gmail.com>

On Mon, May 30, 2016 at 10:16 PM, Nava kishore Manne
<nava.manne at xilinx.com> wrote:
> This patch updates the driver to support 64-bit DMA addressing.
>
> Signed-off-by: Nava kishore Manne <navam at xilinx.com>
> ---
> Changes for v4:
>                 -Used boolen property insted of addrwith property in the DT
>                  as suggested by Arnd Bergmann.
>                 -Adopt the DT relevant changes into the driver.
>
> Changes for v3:
>                 -Added new compatable string for 5.00 IP version as suggested by
>                  Arnd Bergmann.
>                 -Used write_fn() insted of lo_hi_writeq() as suggested by
>                  Arnd Bergmann.
>
> Changes for v2:
>                 -Added dma-ranges property in device tree as suggested by Arnd Bergmann.
>                 -Modified the driver code based on the xlnx,addrwidth.
>
>  .../devicetree/bindings/usb/udc-xilinx.txt         |  5 ++-
>  drivers/usb/gadget/udc/udc-xilinx.c                | 52 +++++++++++++++++++++-
>  2 files changed, 54 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/usb/udc-xilinx.txt b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> index 47b4e39..d08d972 100644
> --- a/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> +++ b/Documentation/devicetree/bindings/usb/udc-xilinx.txt
> @@ -1,12 +1,14 @@
>  Xilinx USB2 device controller
>
>  Required properties:
> -- compatible           : Should be "xlnx,usb2-device-4.00.a"
> +- compatible           : Should be "xlnx,usb2-device-4.00.a" or
> +                         "xlnx,usb2-device-5.00"
>  - reg                  : Physical base address and size of the USB2
>                           device registers map.
>  - interrupts           : Should contain single irq line of USB2 device
>                           controller
>  - xlnx,has-builtin-dma : if DMA is included
> +- xlnx,has-64bit-dma   : if DMA is included 64-bit addressing support.
>
>  Example:
>                 axi-usb2-device at 42e00000 {
> @@ -14,5 +16,6 @@ Example:
>                          interrupts = <0x0 0x39 0x1>;
>                          reg = <0x42e00000 0x10000>;
>                          xlnx,has-builtin-dma;
> +                       xlnx,has-64bit-dma;
>                  };
>
> diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c
> index 1cbb0ac..6fb80c6 100644
> --- a/drivers/usb/gadget/udc/udc-xilinx.c
> +++ b/drivers/usb/gadget/udc/udc-xilinx.c
> @@ -47,6 +47,15 @@
>  #define XUSB_DMA_LENGTH_OFFSET         0x0210  /* DMA Length Register */
>  #define XUSB_DMA_STATUS_OFFSET         0x0214  /* DMA Status Register */
>
> +/* DMA source Address Reg for LSB */
> +#define XUSB_DMA_DSAR_ADDR_OFFSET_LSB   0x0308
> +/* DMA source Address Reg for MSB */
> +#define XUSB_DMA_DSAR_ADDR_OFFSET_MSB   0x030C
> +/* DMA destination Addr Reg LSB */
> +#define XUSB_DMA_DDAR_ADDR_OFFSET_LSB   0x0310
> +/* DMA destination Addr Reg MSB */
> +#define XUSB_DMA_DDAR_ADDR_OFFSET_MSB   0x0314
> +
>  /* Endpoint Configuration Space offsets */
>  #define XUSB_EP_CFGSTATUS_OFFSET       0x00    /* Endpoint Config Status  */
>  #define XUSB_EP_BUF0COUNT_OFFSET       0x08    /* Buffer 0 Count */
> @@ -169,6 +178,7 @@ struct xusb_ep {
>   * @setup: usb_ctrlrequest structure for control requests
>   * @req: pointer to dummy request for get status command
>   * @dev: pointer to device structure in gadget
> + * @is_extend_dma: flag indiacting whether the dma is 64-bit support or not.
>   * @usb_state: device in suspended state or not
>   * @remote_wkp: remote wakeup enabled by host
>   * @setupseqtx: tx status
> @@ -186,6 +196,7 @@ struct xusb_udc {
>         struct usb_ctrlrequest setup;
>         struct xusb_req *req;
>         struct device *dev;
> +       bool is_extend_dma;
>         u32 usb_state;
>         u32 remote_wkp;
>         u32 setupseqtx;
> @@ -215,6 +226,20 @@ static const struct usb_endpoint_descriptor config_bulk_out_desc = {
>  };
>
>  /**
> + * xudc_write64 - write 64bit value to device registers
> + * @ep: pointer to the usb device endpoint structure.
> + * @offset: register offset
> + * @val: data to be written
> + **/
> +static void xudc_write64(struct xusb_ep *ep, u32 offset, u64 val)
> +{
> +       struct xusb_udc *udc = ep->udc;
> +
> +       udc->write_fn(udc->addr, offset, lower_32_bits(val));
> +       udc->write_fn(udc->addr, offset+0x04, upper_32_bits(val));

can we move this to a single 64 bit write?
> +}
> +
> +/**


From mw at semihalf.com  Mon May 30 20:02:50 2016
From: mw at semihalf.com (Marcin Wojtas)
Date: Tue, 31 May 2016 05:02:50 +0200
Subject: [BUG] Page allocation failures with newest kernels
Message-ID: <CAPv3WKcVsWBgHHC3UPNcbka2JUmN4CTw1Ym4BR1=1V9=B9av5Q@mail.gmail.com>

Hi,

After rebasing platform support of two different ARMv8 SoC's from v4.1
baseline to v4.4 it occurred that stressed systems tend to have page
allocation problems, related to creating new slabs:

http://pastebin.com/FhRW5DsF

Steps to reproduce:
- use SATA drive (on-board or over PCIe) with 2 btrfs 50G partitions
- run a couple of loops of following script:
mount /dev/sd${1}1 /mnt
mount /dev/sd${1}2 /mnt2
i=0
while [[ $i -lt ${2} ]]
do
echo -e "i = ${i}\n"
dd if=/dev/zero of=/mnt/3g bs=3M count=1024 &
dd if=/dev/zero of=/mnt/2g bs=2M count=1024 &
dd if=/dev/zero of=/mnt/1g bs=1M count=1024 &
dd if=/dev/zero of=/mnt2/2g bs=2M count=1024 &
dd if=/dev/zero of=/mnt2/1g bs=1M count=1024 &
dd if=/dev/zero of=/mnt2/3g bs=3M count=1024
let "i++"
done

The issue also reproduced on v4.6. Usually problems occur within first
iteration and then the rest is done without errors, also kernel remain
stable. I got an information, that page alloc problem were observed
also on Marvell ARMv7 platfrom (Armada38x).

About the debug itself - after adding simplest possible trace in
trace/events/kmem.h (single argument u64 for counter or whatever kind
of number), it was shown both on v4.1 and v4.4 following condition is
achieved multiple times during test:
In __alloc_pages_nodemask(), during the test kernel jumps huge amount
of times (~250k times in v4.1 and ~570k in v4.4 per one script loop)
into following 'unlikely' condition:
page = get_page_from_freelist(alloc_mask, order, alloc_flags, &ac);
if (unlikely(!page)) {
    [...]
    page = __alloc_pages_slowpath(alloc_mask, order, &ac);
}

The further difference is seen in __alloc_pages_slowpath().
warn_alloc_page() (routine responsible for printing page alloc failure
message) is reached via following condition:
if (!can_direct_reclaim) {
    [...]
    goto nopage;
}
In v4.1 ~5 times and in v4.4 ~40 times per one script loop.

Printing message however can be blocked by following condition in
warn_alloc_fail():
if ((gfp_mask & _GFP_NOWARN) || !_ratelimit(&nopage_rs) ||
    debug_guardpage_minorder() > 0)
        return;
Only first two are relevant. As ratelimit is derived directly from
CONFIG_HZ and this parameter differ between v4.1 and v4.4 (100 vs 250,
also CONFIG_SCHED_HRTICK is enabled only in v4.4) the configs were
swapped, but no change in behavior.

Also within 'faulty' revision there is a difference, depending on
filesystem used - with buildroot the dumps occur, but with same test
under ubuntu - it's impossible see the failure output (and it's not a
question of dmesg level:)). Comparing /proc/sys/vm contents didn't
show anything meaningful.

I tried to analyze changes around mm/ folder between v4.1 and v4.4
that may cause such difference, but wasn't able to find out what may
be causing the issue. Have anyone encountered such problems in recent
revisions? I would be very grateful for any hint or comment. Also if
any other data can be captured, please let know.

Best regards,
Marcin Wojtas


From wens at csie.org  Mon May 30 20:03:51 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Tue, 31 May 2016 11:03:51 +0800
Subject: [PATCH] ARM: dts: sun7i: Add dts file for Bananapi M1 Plus board
In-Reply-To: <20160530194340.GE4908@lukather>
References: <20160530123013.11575-1-luoyi.ly@gmail.com>
 <20160530194340.GE4908@lukather>
Message-ID: <CAGb2v66ojJfSoCQ13rGyfi4XjbzkZfMn=gfPFN+mQmv8NoBqfA@mail.gmail.com>

Hi,

On Tue, May 31, 2016 at 3:43 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Hi,
>
> On Mon, May 30, 2016 at 08:30:13PM +0800, luoyi.ly at gmail.com wrote:
>> From: luoyi <luoyi.ly at gmail.com>
>>
>> Add support for the Bananapi M1 Plus A20 development board from sinovoip.com.cn .
>> This board features 1G RAM, 2 USB A receptacles, 1 micro USB receptacle for
>> OTG, 1 micro USB receptacle for power, HDMI, sata, Gbit ethernet, ir receiver,
>> 3.5 mm jack for stero sound out, on board microphone, 40 gpio pins and sdio wifi.
>
> What is the difference between the M1+ and the M1?
>
>>
>> Signed-off-by: Luo Yi <luoyi.ly at gmail.com>
>> ---
>>  arch/arm/boot/dts/Makefile                       |   1 +
>>  arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts | 270 +++++++++++++++++++++++
>>  2 files changed, 271 insertions(+)
>>  create mode 100644 arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
>>
>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>> index e06a5ab..fde407f 100644
>> --- a/arch/arm/boot/dts/Makefile
>> +++ b/arch/arm/boot/dts/Makefile
>> @@ -685,6 +685,7 @@ dtb-$(CONFIG_MACH_SUN6I) += \
>>       sun6i-a31s-yones-toptech-bs1078-v2.dtb
>>  dtb-$(CONFIG_MACH_SUN7I) += \
>>       sun7i-a20-bananapi.dtb \
>> +     sun7i-a20-bananapi-m1-plus.dtb \
>>       sun7i-a20-bananapro.dtb \
>>       sun7i-a20-cubieboard2.dtb \
>>       sun7i-a20-cubietruck.dtb \
>> diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
>> new file mode 100644
>> index 0000000..b62fc1d
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
>> @@ -0,0 +1,270 @@
>> +/*
>> + * Copyright 2016 Luo Yi <luoyi.ly at gmail.com>
>> + *
>> + * Thanks to the original work by Hans de Goede <hdegoede at redhat.com>
>> + *
>> + * 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 "sun7i-a20.dtsi"
>> +#include "sunxi-common-regulators.dtsi"
>> +#include <dt-bindings/gpio/gpio.h>
>> +#include <dt-bindings/interrupt-controller/arm-gic.h>
>> +
>> +/ {
>> +     model = "Banana Pi BPI-M1-Plus";
>> +     compatible = "sinovoip,bpi-m1-plus", "allwinner,sun7i-a20";
>> +
>> +     aliases {
>> +             serial0 = &uart0;
>> +     };
>> +
>> +     chosen {
>> +             stdout-path = "serial0:115200n8";
>> +     };
>> +
>> +     leds {
>> +             compatible = "gpio-leds";
>> +             pinctrl-names = "default";
>> +             pinctrl-0 = <&led_pins_bananapi>;
>> +
>> +             red {
>> +                     label = "bananapi:red:usr";
>
> The first part the label is the board name, in that case that would be
> bananapi-m1-plus.
>
>> +                     gpios = <&pio 7 25 GPIO_ACTIVE_HIGH>;
>> +                     linux,default-trigger = "default-on";
>
> So that's the power led?
>
>> +             };
>> +
>> +             green {
>> +                     label = "bananapi:green:usr";
>> +                     gpios = <&pio 7 24 GPIO_ACTIVE_HIGH>;
>> +                     linux,default-trigger = "heartbeat";
>
> We don't enforce any trigger by default.
>
>> +
>> +             };
>> +     };
>> +
>> +     reg_gmac_3v3: gmac-3v3 {
>> +             compatible = "regulator-fixed";
>> +             pinctrl-names = "default";
>> +             pinctrl-0 = <&gmac_power_pin_bananapi>;
>> +             regulator-name = "gmac-3v3";
>> +             regulator-min-microvolt = <3300000>;
>> +             regulator-max-microvolt = <3300000>;
>> +             startup-delay-us = <100000>;
>> +             enable-active-high;
>> +             gpio = <&pio 7 23 GPIO_ACTIVE_HIGH>;
>> +     };
>> +
>> +     reg_vmmc3: vmmc3 {
>> +             compatible = "regulator-fixed";
>> +             pinctrl-names = "default";
>> +             pinctrl-0 = <&vmmc3_pin_bananapi>;
>> +             regulator-name = "vmmc3";
>> +             regulator-min-microvolt = <3300000>;
>> +             regulator-max-microvolt = <3300000>;
>> +             regulator-always-on;
>> +             regulator-boot-on;
>> +             enable-active-high;
>> +             gpio = <&pio 7 22 GPIO_ACTIVE_HIGH>;
>> +     };
>
> You can use reg_vcc3v3 from sunxi-common-regulators.dtsi.

This is a GPIO controlled one, not just a fixed regulator.

However, this is a misrepresentation of what is on the board.

PH22 here is connected to the REG_ON pin on the WiFi chip.
So either you represent this as a GPIO toggled fixed
regulator with a source from reg_vcc3v3, and use this as
vmmc on mmc3. Or you use the pwrseq_simple bindings for
this.


ChenYu

>
>> +
>> +};
>> +
>> +&ahci {
>> +     status = "okay";
>> +};
>> +
>> +&codec {
>> +     status = "okay";
>> +};
>> +
>> +&ehci0 {
>> +     status = "okay";
>> +};
>> +
>> +&ehci1 {
>> +     status = "okay";
>> +};
>> +
>> +&ohci0 {
>> +     status = "okay";
>> +};
>> +
>> +&ohci1 {
>> +     status = "okay";
>> +};
>
> Please order your nodes alphabetically.
>
>> +
>> +&gmac {
>> +     pinctrl-names = "default";
>> +     pinctrl-0 = <&gmac_pins_rgmii_a>;
>> +     phy = <&phy1>;
>> +     phy-mode = "rgmii";
>> +     phy-supply = <&reg_gmac_3v3>;
>> +     status = "okay";
>> +
>> +     phy1: ethernet-phy at 1 {
>> +             reg = <1>;
>> +     };
>> +};
>> +
>> +&i2c0 {
>> +     pinctrl-names = "default";
>> +     pinctrl-0 = <&i2c0_pins_a>;
>> +     status = "okay";
>> +
>> +     axp209: pmic at 34 {
>> +             compatible = "x-powers,axp209";
>> +             reg = <0x34>;
>> +             interrupt-parent = <&nmi_intc>;
>> +             interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
>> +
>> +             interrupt-controller;
>> +             #interrupt-cells = <1>;
>> +     };
>> +};
>> +
>> +&ir0 {
>> +     pinctrl-names = "default";
>> +     pinctrl-0 = <&ir0_rx_pins_a>;
>> +     status = "okay";
>> +};
>> +
>> +&mmc0 {
>> +     pinctrl-names = "default";
>> +     pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bananapi>;
>> +     vmmc-supply = <&reg_vcc3v3>;
>> +     bus-width = <4>;
>> +     cd-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */
>> +     cd-inverted;
>> +     status = "okay";
>> +};
>> +
>> +&mmc3 {
>> +     #address-cells = <1>;
>> +     #size-cells = <0>;
>> +     pinctrl-names = "default";
>> +     pinctrl-0 = <&mmc3_pins_a>;
>> +     vmmc-supply = <&reg_vmmc3>;
>> +     bus-width = <4>;
>> +     non-removable;
>> +     enable-sdio-wakeup;
>> +     status = "okay";
>> +
>> +     brcmf: bcrmf at 1 {
>> +             reg = <1>;
>> +             compatible = "brcm,bcm4329-fmac";
>> +             interrupt-parent = <&pio>;
>> +             interrupts = <7 15 IRQ_TYPE_LEVEL_LOW>;
>> +             interrupt-names = "host-wake";
>> +     };
>> +
>> +};
>> +
>> +&mmc3_pins_a {
>> +    /* AP6210 requires pull-up */
>> +     allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
>> +};
>> +
>> +&pio {
>> +     gmac_power_pin_bananapi: gmac_power_pin at 0 {
>> +             allwinner,pins = "PH23";
>> +             allwinner,function = "gpio_out";
>> +             allwinner,drive = <SUN4I_PINCTRL_10_MA>;
>> +             allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
>> +     };
>> +
>> +     led_pins_bananapi: led_pins at 0 {
>> +             allwinner,pins = "PH24", "PG2";
>> +             allwinner,function = "gpio_out";
>> +             allwinner,drive = <SUN4I_PINCTRL_10_MA>;
>> +             allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
>> +     };
>> +
>> +     mmc0_cd_pin_bananapi: mmc0_cd_pin at 0 {
>> +             allwinner,pins = "PH10";
>> +             allwinner,function = "gpio_in";
>> +             allwinner,drive = <SUN4I_PINCTRL_10_MA>;
>> +             allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
>> +     };
>> +
>> +     usb1_vbus_pin_bananapi: usb1_vbus_pin at 0 {
>> +             allwinner,pins = "PH0";
>> +             allwinner,function = "gpio_out";
>> +             allwinner,drive = <SUN4I_PINCTRL_10_MA>;
>> +             allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
>> +     };
>> +
>> +     usb2_vbus_pin_bananapi: usb2_vbus_pin at 0 {
>> +             allwinner,pins = "PH1";
>> +             allwinner,function = "gpio_out";
>> +             allwinner,drive = <SUN4I_PINCTRL_10_MA>;
>> +             allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
>> +     };
>> +
>> +     vmmc3_pin_bananapi: vmmc3_pin at 0 {
>> +             allwinner,pins = "PH22";
>> +             allwinner,function = "gpio_out";
>> +             allwinner,drive = <SUN4I_PINCTRL_10_MA>;
>> +             allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
>> +     };
>> +};
>> +
>> +&reg_usb1_vbus {
>> +     pinctrl-0 = <&usb1_vbus_pin_bananapi>;
>> +     gpio = <&pio 7 0 GPIO_ACTIVE_HIGH>; /* PH0 */
>> +     status = "okay";
>> +};
>> +
>> +&reg_usb2_vbus {
>> +     pinctrl-0 = <&usb2_vbus_pin_bananapi>;
>> +     gpio = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
>> +     status = "okay";
>> +};
>> +
>> +&uart0 {
>> +     pinctrl-names = "default";
>> +     pinctrl-0 = <&uart0_pins_a>;
>> +     status = "okay";
>> +};
>> +
>> +&usbphy {
>> +     usb1_vbus-supply = <&reg_usb1_vbus>;
>> +     usb2_vbus-supply = <&reg_usb2_vbus>;
>> +     status = "okay";
>> +};
>> --
>> 2.8.3
>>
>
> Thanks!
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com


From horms+renesas at verge.net.au  Mon May 30 20:32:04 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Tue, 31 May 2016 12:32:04 +0900
Subject: [RFC 0/4] ARM: dts: r8a7790: lager: use demuxer for I2C
Message-ID: <1464665528-11398-1-git-send-email-horms+renesas@verge.net.au>

Hi,

the intention of this series is to extend use of the demuxer for I2C
on the lager/r8a7790 to cover all I2C IP blocks.

This is based on work by Wolfram Sang.

I have not included GPIO in the demux configuration. This is in keeping
with the existing usage for IIC0/I2C0.

Any advice or assistance in testing would be gratefully received.

For reference a boot log is provided below.

This series is based on renesas-devel-20160530-v4.7-rc1.

To aid review it is provided in git at:

git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git topic/i2c-demux

I also intend to add demux for I2C to other R-Car Gen2 boards as a follow-up.


Simon Horman (4):
  ARM: dts: r8a7790: lager: rename i2cexio as i2cexio0
  ARM: dts: r8a7790: lager: use demuxer for IIC1/I2C1
  ARM: dts: r8a7790: lager: use demuxer for IIC2/I2C2
  ARM: dts: r8a7790: lager: use demuxer for IIC3/I2C3

 arch/arm/boot/dts/r8a7790-lager.dts | 241 ++++++++++++++++++++++--------------
 1 file changed, 151 insertions(+), 90 deletions(-)

--- Boot log ---

Lager booted with kernel using shmobile_defconfig.

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.7.0-rc1-11566-g37773b1e292b (horms at ayumi.isobedori.kobe.vergenet.net) (gcc version 4.6.3 (GCC) ) #621 SMP Tue May 31 12:07:50 JST 2016
[    0.000000] CPU: ARMv7 Processor [413fc0f2] revision 2 (ARMv7), cr=10c5387d
[    0.000000] CPU: div instructions available: patching division code
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache
[    0.000000] Machine model: Lager
[    0.000000] Ignoring memory block 0x140000000 - 0x200000000
[    0.000000] debug: ignoring loglevel setting.
[    0.000000] Memory policy: Data cache writealloc
[    0.000000] On node 0 totalpages: 262144
[    0.000000] free_area_init_node: node 0, pgdat c0a3d680, node_mem_map ef7f9000
[    0.000000]   Normal zone: 1536 pages used for memmap
[    0.000000]   Normal zone: 0 pages reserved
[    0.000000]   Normal zone: 196608 pages, LIFO batch:31
[    0.000000]   HighMem zone: 65536 pages, LIFO batch:15
[    0.000000] percpu: Embedded 11 pages/cpu @ef77b000 s22720 r0 d22336 u45056
[    0.000000] pcpu-alloc: s22720 r0 d22336 u45056 alloc=11*4096
[    0.000000] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3 [0] 4 [0] 5 [0] 6 [0] 7 
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 260608
[    0.000000] Kernel command line: ignore_loglevel rw root=/dev/nfs ip=dhcp
[    0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
[    0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
[    0.000000] Memory: 1029228K/1048576K available (6148K kernel code, 251K rwdata, 1480K rodata, 1024K init, 292K bss, 19348K reserved, 0K cma-reserved, 262144K highmem)
[    0.000000] Virtual kernel memory layout:
[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
[    0.000000]     vmalloc : 0xf0800000 - 0xff800000   ( 240 MB)
[    0.000000]     lowmem  : 0xc0000000 - 0xf0000000   ( 768 MB)
[    0.000000]     pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
[    0.000000]       .text : 0xc0008000 - 0xc087307c   (8621 kB)
[    0.000000]       .init : 0xc0900000 - 0xc0a00000   (1024 kB)
[    0.000000]       .data : 0xc0a00000 - 0xc0a3ef80   ( 252 kB)
[    0.000000]        .bss : 0xc0a40000 - 0xc0a8919c   ( 293 kB)
[    0.000000] Hierarchical RCU implementation.
[    0.000000]  Build-time adjustment of leaf fanout to 32.
[    0.000000] NR_IRQS:16 nr_irqs:16 16
[    0.000000] Architected cp15 timer(s) running at 10.00MHz (virt).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x24e6a1710, max_idle_ns: 440795202120 ns
[    0.000004] sched_clock: 56 bits at 10MHz, resolution 100ns, wraps every 4398046511100ns
[    0.000014] Switching to timer-based delay loop, resolution 100ns
[    0.000525] Console: colour dummy device 80x30
[    0.000812] console [tty0] enabled
[    0.000837] Calibrating delay loop (skipped), value calculated using timer frequency.. 20.00 BogoMIPS (lpj=100000)
[    0.000862] pid_max: default: 32768 minimum: 301
[    0.000987] Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
[    0.001004] Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes)
[    0.001448] CPU: Testing write buffer coherency: ok
[    0.001708] CPU0: update cpu_capacity 1535
[    0.001725] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
[    0.003528] Setting up static identity map for 0x40100000 - 0x40100058
[    0.006976] CPU1: update cpu_capacity 1535
[    0.006982] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
[    0.007849] CPU2: update cpu_capacity 1535
[    0.007856] CPU2: thread -1, cpu 2, socket 0, mpidr 80000002
[    0.008731] CPU3: update cpu_capacity 1535
[    0.008737] CPU3: thread -1, cpu 3, socket 0, mpidr 80000003
[    0.009384] CPU4: failed to boot: -22
[    0.010088] CPU5: failed to boot: -22
[    0.010715] CPU6: failed to boot: -22
[    0.011335] CPU7: failed to boot: -22
[    0.011423] Brought up 4 CPUs
[    0.011437] SMP: Total of 4 processors activated (80.00 BogoMIPS).
[    0.011450] CPU: All CPU(s) started in SVC mode.
[    0.060700] devtmpfs: initialized
[    0.070169] VFP support v0.3: implementor 41 architecture 4 part 30 variant f rev 0
[    0.070566] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.127064] pinctrl core: initialized pinctrl subsystem
[    0.268112] NET: Registered protocol family 16
[    0.268305] DMA: preallocated 256 KiB pool for atomic coherent allocations
[    0.271065] renesas_irqc e61c0000.interrupt-controller: driving 4 irqs
[    0.274207] sh-pfc e6060000.pfc: r8a77900_pfc support registered
[    0.279976] No ATAGs?
[    0.280000] hw-breakpoint: found 5 (+1 reserved) breakpoint and 4 watchpoint registers.
[    0.280025] hw-breakpoint: maximum watchpoint size is 8 bytes.
[    0.280067] IRQ2 is asserted, installing da9063/da9210 regulator quirk
[    0.791592] vgaarb: loaded
[    0.880763] SCSI subsystem initialized
[    0.880929] libata version 3.00 loaded.
[    0.881158] usbcore: registered new interface driver usbfs
[    0.881216] usbcore: registered new interface driver hub
[    0.881318] usbcore: registered new device driver usb
[    0.881857] media: Linux media interface: v0.10
[    0.881915] Linux video capture interface: v2.00
[    0.882284] sh_cmt ffca0000.timer: ch0: used for clock events
[    0.882308] sh_cmt ffca0000.timer: ch1: used as clock source
[    0.882326] clocksource: ffca0000.timer: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275000000 ns
[    0.882978] Advanced Linux Sound Architecture Driver Initialized.
[    0.883681] clocksource: Switched to clocksource arch_sys_counter
[    1.233687] NET: Registered protocol family 2
[    1.353767] TCP established hash table entries: 8192 (order: 3, 32768 bytes)
[    1.353836] TCP bind hash table entries: 8192 (order: 4, 65536 bytes)
[    1.353939] TCP: Hash tables configured (established 8192 bind 8192)
[    1.353991] UDP hash table entries: 512 (order: 2, 16384 bytes)
[    1.354023] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
[    1.473682] NET: Registered protocol family 1
[    1.533688] RPC: Registered named UNIX socket transport module.
[    1.533704] RPC: Registered udp transport module.
[    1.533716] RPC: Registered tcp transport module.
[    1.533728] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    1.533744] PCI: CLS 0 bytes, default 64
[    1.594689] futex hash table entries: 2048 (order: 5, 131072 bytes)
[    1.595243] workingset: timestamp_bits=28 max_order=18 bucket_order=0
[    1.833703] NFS: Registering the id_resolver key type
[    1.833741] Key type id_resolver registered
[    1.833754] Key type id_legacy registered
[    1.833775] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
[    1.833790] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
[    1.835424] bounce: pool size: 64 pages
[    1.903719] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 249)
[    1.903741] io scheduler noop registered
[    1.903754] io scheduler deadline registered
[    1.903775] io scheduler cfq registered (default)
[    1.905105] gpio_rcar e6050000.gpio: driving 32 GPIOs
[    1.905547] gpio_rcar e6051000.gpio: driving 30 GPIOs
[    1.905973] gpio_rcar e6052000.gpio: driving 30 GPIOs
[    1.906416] gpio_rcar e6053000.gpio: driving 32 GPIOs
[    1.906843] gpio_rcar e6054000.gpio: driving 32 GPIOs
[    1.907281] gpio_rcar e6055000.gpio: driving 32 GPIOs
[    1.907986] pci-rcar-gen2 ee090000.pci: PCI: bus0 revision 11
[    1.908152] pci-rcar-gen2 ee090000.pci: PCI host bridge to bus 0000:00
[    1.908173] pci_bus 0000:00: root bus resource [io  0xee080000-0xee0810ff]
[    1.908189] pci_bus 0000:00: root bus resource [mem 0xee080000-0xee0810ff]
[    1.908205] pci_bus 0000:00: No busn resource found for root bus, will use [bus 00-ff]
[    1.908248] pci 0000:00:00.0: [1033:0000] type 00 class 0x060000
[    1.908277] pci 0000:00:00.0: reg 0x10: [mem 0xee090800-0xee090bff]
[    1.908297] pci 0000:00:00.0: reg 0x14: [mem 0x40000000-0x7fffffff pref]
[    1.908517] pci 0000:00:01.0: [1033:0035] type 00 class 0x0c0310
[    1.908547] pci 0000:00:01.0: reg 0x10: [mem 0x00000000-0x00000fff]
[    1.908627] pci 0000:00:01.0: supports D1 D2
[    1.908643] pci 0000:00:01.0: PME# supported from D0 D1 D2 D3hot
[    1.908857] pci 0000:00:02.0: [1033:00e0] type 00 class 0x0c0320
[    1.908887] pci 0000:00:02.0: reg 0x10: [mem 0x00000000-0x000000ff]
[    1.908967] pci 0000:00:02.0: supports D1 D2
[    1.908981] pci 0000:00:02.0: PME# supported from D0 D1 D2 D3hot
[    1.909199] PCI: bus0: Fast back to back transfers disabled
[    1.909219] pci_bus 0000:00: busn_res: [bus 00-ff] end is updated to 00
[    1.909309] pci 0000:00:01.0: BAR 0: assigned [mem 0xee080000-0xee080fff]
[    1.909330] pci 0000:00:02.0: BAR 0: assigned [mem 0xee081000-0xee0810ff]
[    1.909378] pci 0000:00:01.0: enabling device (0140 -> 0142)
[    1.909422] pci 0000:00:02.0: enabling device (0140 -> 0142)
[    1.909666] pci-rcar-gen2 ee0b0000.pci: PCI: bus0 revision 11
[    1.909819] pci-rcar-gen2 ee0b0000.pci: PCI host bridge to bus 0001:01
[    1.909836] pci_bus 0001:01: root bus resource [io  0xee0a0000-0xee0a10ff]
[    1.909852] pci_bus 0001:01: root bus resource [mem 0xee0a0000-0xee0a10ff]
[    1.909867] pci_bus 0001:01: No busn resource found for root bus, will use [bus 01-ff]
[    1.909902] pci 0001:01:00.0: [1033:0000] type 00 class 0x060000
[    1.909928] pci 0001:01:00.0: reg 0x10: [mem 0xee0b0800-0xee0b0bff]
[    1.909947] pci 0001:01:00.0: reg 0x14: [mem 0x40000000-0x7fffffff pref]
[    1.910152] pci 0001:01:01.0: [1033:0035] type 00 class 0x0c0310
[    1.910182] pci 0001:01:01.0: reg 0x10: [mem 0x00000000-0x00000fff]
[    1.910263] pci 0001:01:01.0: supports D1 D2
[    1.910278] pci 0001:01:01.0: PME# supported from D0 D1 D2 D3hot
[    1.910486] pci 0001:01:02.0: [1033:00e0] type 00 class 0x0c0320
[    1.910516] pci 0001:01:02.0: reg 0x10: [mem 0x00000000-0x000000ff]
[    1.910595] pci 0001:01:02.0: supports D1 D2
[    1.910610] pci 0001:01:02.0: PME# supported from D0 D1 D2 D3hot
[    1.910818] PCI: bus1: Fast back to back transfers disabled
[    1.910836] pci_bus 0001:01: busn_res: [bus 01-ff] end is updated to 01
[    1.910968] pci 0001:01:01.0: BAR 0: assigned [mem 0xee0a0000-0xee0a0fff]
[    1.910988] pci 0001:01:02.0: BAR 0: assigned [mem 0xee0a1000-0xee0a10ff]
[    1.911024] pci 0001:01:01.0: enabling device (0140 -> 0142)
[    1.911066] pci 0001:01:02.0: enabling device (0140 -> 0142)
[    1.911241] pci-rcar-gen2 ee0d0000.pci: PCI: bus0 revision 11
[    1.911400] pci-rcar-gen2 ee0d0000.pci: PCI host bridge to bus 0002:02
[    1.911418] pci_bus 0002:02: root bus resource [io  0xee0c0000-0xee0c10ff]
[    1.911433] pci_bus 0002:02: root bus resource [mem 0xee0c0000-0xee0c10ff]
[    1.911448] pci_bus 0002:02: No busn resource found for root bus, will use [bus 02-ff]
[    1.911485] pci 0002:02:00.0: [1033:0000] type 00 class 0x060000
[    1.911509] pci 0002:02:00.0: reg 0x10: [mem 0xee0d0800-0xee0d0bff]
[    1.911528] pci 0002:02:00.0: reg 0x14: [mem 0x40000000-0x7fffffff pref]
[    1.911732] pci 0002:02:01.0: [1033:0035] type 00 class 0x0c0310
[    1.911761] pci 0002:02:01.0: reg 0x10: [mem 0x00000000-0x00000fff]
[    1.911840] pci 0002:02:01.0: supports D1 D2
[    1.911855] pci 0002:02:01.0: PME# supported from D0 D1 D2 D3hot
[    1.912067] pci 0002:02:02.0: [1033:00e0] type 00 class 0x0c0320
[    1.912096] pci 0002:02:02.0: reg 0x10: [mem 0x00000000-0x000000ff]
[    1.912176] pci 0002:02:02.0: supports D1 D2
[    1.912190] pci 0002:02:02.0: PME# supported from D0 D1 D2 D3hot
[    1.912408] PCI: bus2: Fast back to back transfers disabled
[    1.912426] pci_bus 0002:02: busn_res: [bus 02-ff] end is updated to 02
[    1.912612] pci 0002:02:01.0: BAR 0: assigned [mem 0xee0c0000-0xee0c0fff]
[    1.912633] pci 0002:02:02.0: BAR 0: assigned [mem 0xee0c1000-0xee0c10ff]
[    1.912669] pci 0002:02:01.0: enabling device (0140 -> 0142)
[    1.912709] pci 0002:02:02.0: enabling device (0140 -> 0142)
[    1.924475] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[    1.925658] SuperH (H)SCI(F) driver initialized
[    1.926117] e6c50000.serial: ttySC1 at MMIO 0xe6c50000 (irq = 99, base_baud = 0) is a scifa
[    1.926642] e6e60000.serial: ttySC0 at MMIO 0xe6e60000 (irq = 100, base_baud = 0) is a scif
[    3.034029] console [ttySC0] enabled
[    3.038133] [drm] Initialized drm 1.1.0 20060810
[    3.043595] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[    3.050230] [drm] No driver support for vblank timestamp query.
[    3.056800] rcar-du feb00000.display: failed to initialize DRM/KMS (-517)
[    3.065038] scsi host0: sata_rcar
[    3.068573] ata1: SATA max UDMA/133 irq 102
[    3.073495] renesas_spi e6b10000.spi: DMA available
[    3.079099] m25p80 spi0.0: s25fl512s (65536 Kbytes)
[    3.084040] 3 ofpart partitions found on MTD device spi0.0
[    3.089530] Creating 3 MTD partitions on "spi0.0":
[    3.094340] 0x000000000000-0x000000040000 : "loader"
[    3.100176] 0x000000040000-0x000000440000 : "user"
[    3.105794] 0x000000440000-0x000004000000 : "flash"
[    3.111484] renesas_spi e6b10000.spi: probed
[    3.116579] spi_sh_msiof e6e10000.spi: DMA available
[    3.122717] CAN device driver interface
[    3.127403] libphy: sh_mii: probed
[    3.131875] sh-eth ee700000.ethernet eth0: Base address at 0xee700000, 2e:09:0a:00:6e:71, IRQ 101.
[    3.141156] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    3.147703] ehci-pci: EHCI PCI platform driver
[    3.152278] ehci-pci 0000:00:02.0: EHCI Host Controller
[    3.157536] ehci-pci 0000:00:02.0: new USB bus registered, assigned bus number 1
[    3.165054] ehci-pci 0000:00:02.0: irq 116, io mem 0xee081000
[    3.183686] ehci-pci 0000:00:02.0: USB 2.0 started, EHCI 1.00
[    3.190140] hub 1-0:1.0: USB hub found
[    3.193942] hub 1-0:1.0: 1 port detected
[    3.198274] ehci-pci 0001:01:02.0: EHCI Host Controller
[    3.203520] ehci-pci 0001:01:02.0: new USB bus registered, assigned bus number 2
[    3.211029] ehci-pci 0001:01:02.0: irq 117, io mem 0xee0a1000
[    3.233685] ehci-pci 0001:01:02.0: USB 2.0 started, EHCI 1.00
[    3.240066] hub 2-0:1.0: USB hub found
[    3.243862] hub 2-0:1.0: 1 port detected
[    3.248185] ehci-pci 0002:02:02.0: EHCI Host Controller
[    3.253429] ehci-pci 0002:02:02.0: new USB bus registered, assigned bus number 3
[    3.260933] ehci-pci 0002:02:02.0: irq 118, io mem 0xee0c1000
[    3.283685] ehci-pci 0002:02:02.0: USB 2.0 started, EHCI 1.00
[    3.290051] hub 3-0:1.0: USB hub found
[    3.293853] hub 3-0:1.0: 1 port detected
[    3.298131] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    3.304340] ohci-pci: OHCI PCI platform driver
[    3.308853] ohci-pci 0000:00:01.0: OHCI PCI host controller
[    3.314457] ohci-pci 0000:00:01.0: new USB bus registered, assigned bus number 4
[    3.321895] ohci-pci 0000:00:01.0: irq 116, io mem 0xee080000
[    3.414324] hub 4-0:1.0: USB hub found
[    3.418107] hub 4-0:1.0: 1 port detected
[    3.422384] ohci-pci 0001:01:01.0: OHCI PCI host controller
[    3.427989] ohci-pci 0001:01:01.0: new USB bus registered, assigned bus number 5
[    3.435433] ohci-pci 0001:01:01.0: irq 117, io mem 0xee0a0000
[    3.493688] ata1: link resume succeeded after 1 retries
[    3.524349] hub 5-0:1.0: USB hub found
[    3.528132] hub 5-0:1.0: 1 port detected
[    3.532425] ohci-pci 0002:02:01.0: OHCI PCI host controller
[    3.538041] ohci-pci 0002:02:01.0: new USB bus registered, assigned bus number 6
[    3.545491] ohci-pci 0002:02:01.0: irq 118, io mem 0xee0c0000
[    3.603701] ata1: SATA link down (SStatus 0 SControl 300)
[    3.634334] hub 6-0:1.0: USB hub found
[    3.638120] hub 6-0:1.0: 1 port detected
[    3.642710] sh-pfc e6060000.pfc: pin GP_5_19 already requested by ee090000.pci; cannot claim for e6590000.usb
[    3.652649] sh-pfc e6060000.pfc: pin-179 (e6590000.usb) status -22
[    3.658844] sh-pfc e6060000.pfc: could not request pin 179 (GP_5_19) from group usb0_ovc_vbus  on device sh-pfc
[    3.668949] renesas_usbhs e6590000.usb: Error applying setting, reverse things back
[    3.676844] renesas_usbhs e6590000.usb: transceiver found
[    3.682404] renesas_usbhs e6590000.usb: gadget probed
[    3.687558] phy phy-e6590100.usb-phy.1: phy init failed --> -16
[    3.693486] renesas_usbhs e6590000.usb: probed
[    3.698157] using random self ethernet address
[    3.702609] using random host ethernet address
[    3.707486] usb0: HOST MAC a2:bd:c8:b5:c1:92
[    3.711778] usb0: MAC d2:33:7b:bb:af:f1
[    3.715639] using random self ethernet address
[    3.720087] using random host ethernet address
[    3.724590] g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
[    3.731208] g_ether gadget: g_ether ready
[    3.735412] mousedev: PS/2 mouse device common for all mice
[    3.741394] i2c /dev entries driver
[    3.746291] i2c-sh_mobile e6500000.i2c: I2C adapter 4, bus speed 100000 Hz
[    3.754293] i2c-sh_mobile e6510000.i2c: I2C adapter 5, bus speed 100000 Hz
[    3.762237] i2c-sh_mobile e6520000.i2c: I2C adapter 6, bus speed 100000 Hz
[    3.777719] i2c-sh_mobile e60b0000.i2c: I2C adapter 7, bus speed 100000 Hz
[    3.785054] i2c 11-0058: Masking da9063 interrupt sources
[    3.796955] da9063 11-0058: Device detected (chip-ID: 0x61, var-ID: 0x30)
[    3.834992] da9063-rtc da9063-rtc: rtc core: registered da9063-rtc as rtc0
[    3.848136] i2c 11-0068: Masking da9210 interrupt sources
[    3.857027] i2c 11-0068: IRQ2 is not asserted, removing quirk
[    3.864260] DA9210: Bringing 1080000uV into 1000000-1000000uV
[    3.875154] adv7180 10-0020: chip found @ 0x20 (i2c-demux (master i2c-6))
[    3.895816] soc-camera-pdrv soc-camera-pdrv.0: Probing soc-camera-pdrv.0
[    3.903400] rcar_jpu fe980000.jpeg-codec: encoder device registered as /dev/video1
[    3.910998] rcar_jpu fe980000.jpeg-codec: decoder device registered as /dev/video2
[    3.920291] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 bru was not initialized!
[    3.928847] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 hsi was not initialized!
[    3.937395] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 hst was not initialized!
[    3.945939] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 rpf.0 was not initialized!
[    3.954657] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 rpf.1 was not initialized!
[    3.963366] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 rpf.2 was not initialized!
[    3.972084] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 rpf.3 was not initialized!
[    3.980801] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 rpf.4 was not initialized!
[    3.989518] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 sru was not initialized!
[    3.998062] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 uds.0 was not initialized!
[    4.006778] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 wpf.0 was not initialized!
[    4.015495] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 wpf.1 was not initialized!
[    4.024212] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 wpf.2 was not initialized!
[    4.032921] vsp1 fe920000.vsp1: Entity type for entity fe920000.vsp1 wpf.3 was not initialized!
[    4.045012] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 bru was not initialized!
[    4.053558] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 hsi was not initialized!
[    4.062108] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 hst was not initialized!
[    4.070653] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 lut was not initialized!
[    4.079197] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 rpf.0 was not initialized!
[    4.087914] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 rpf.1 was not initialized!
[    4.096631] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 rpf.2 was not initialized!
[    4.105349] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 rpf.3 was not initialized!
[    4.114065] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 rpf.4 was not initialized!
[    4.122774] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 sru was not initialized!
[    4.131317] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 uds.0 was not initialized!
[    4.140037] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 uds.1 was not initialized!
[    4.148754] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 uds.2 was not initialized!
[    4.157471] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 wpf.0 was not initialized!
[    4.166187] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 wpf.1 was not initialized!
[    4.174904] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 wpf.2 was not initialized!
[    4.183613] vsp1 fe928000.vsp1: Entity type for entity fe928000.vsp1 wpf.3 was not initialized!
[    4.195933] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 bru was not initialized!
[    4.204493] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 hsi was not initialized!
[    4.213029] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 hst was not initialized!
[    4.221572] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 lif was not initialized!
[    4.230116] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 lut was not initialized!
[    4.238659] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 rpf.0 was not initialized!
[    4.247375] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 rpf.1 was not initialized!
[    4.256092] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 rpf.2 was not initialized!
[    4.264808] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 rpf.3 was not initialized!
[    4.273517] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 uds.0 was not initialized!
[    4.282232] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 wpf.0 was not initialized!
[    4.290949] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 wpf.1 was not initialized!
[    4.299665] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 wpf.2 was not initialized!
[    4.308382] vsp1 fe930000.vsp1: Entity type for entity fe930000.vsp1 wpf.3 was not initialized!
[    4.320287] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 bru was not initialized!
[    4.328847] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 hsi was not initialized!
[    4.337393] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 hst was not initialized!
[    4.345937] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 lif was not initialized!
[    4.354480] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 lut was not initialized!
[    4.363016] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 rpf.0 was not initialized!
[    4.371733] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 rpf.1 was not initialized!
[    4.380449] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 rpf.2 was not initialized!
[    4.389165] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 rpf.3 was not initialized!
[    4.397887] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 uds.0 was not initialized!
[    4.406604] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 wpf.0 was not initialized!
[    4.415320] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 wpf.1 was not initialized!
[    4.424037] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 wpf.2 was not initialized!
[    4.432746] vsp1 fe938000.vsp1: Entity type for entity fe938000.vsp1 wpf.3 was not initialized!
[    4.445893] rcar_thermal e61f0000.thermal: 1 sensor probed
[    4.457775] sh_mobile_sdhi ee100000.sd: Got CD GPIO
[    4.463122] sh_mobile_sdhi ee140000.sd: Got CD GPIO
[    4.503711] sh_mmcif ee220000.mmc: Chip version 0x0003, clock rate 12MHz
[    4.511151] usbcore: registered new interface driver usbhid
[    4.516743] usbhid: USB HID core driver
[    4.526878] rcar_sound ec500000.sound: probed
[    4.901310] mmc0: new high speed MMC card at address 0001
[    4.907087] mmcblk0: mmc0:0001 MMC08G 7.33 GiB 
[    4.911791] mmcblk0boot0: mmc0:0001 MMC08G partition 1 2.00 MiB
[    4.913698] NET: Registered protocol family 10
[    4.914406] sit: IPv6 over IPv4 tunneling driver
[    4.914978] NET: Registered protocol family 17
[    4.914989] can: controller area network core (rev 20120528 abi 9)
[    4.915038] NET: Registered protocol family 29
[    4.915043] can: raw protocol (rev 20120528)
[    4.915047] can: broadcast manager protocol (rev 20120528 t)
[    4.915054] can: netlink gateway (rev 20130117) max_hops=1
[    4.957494] mmcblk0boot1: mmc0:0001 MMC08G partition 2 2.00 MiB
[    4.965208]  mmcblk0: p1
[    5.013753] Key type dns_resolver registered
[    5.018099] Registering SWP/SWPB emulation handler
[    5.025432] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[    5.032054] [drm] No driver support for vblank timestamp query.
[    5.067400] Console: switching to colour frame buffer device 128x48
[    5.082885] rcar-du feb00000.display: fb0:  frame buffer device
[    5.089384] [drm] Device feb00000.display probed
[    5.094664] sh_mobile_sdhi ee100000.sd: Got CD GPIO
[    5.233861] sh_mobile_sdhi ee100000.sd: mmc1 base at 0xee100000 max clock rate 195 MHz
[    5.242410] sh_mobile_sdhi ee140000.sd: Got CD GPIO
[    5.383844] sh_mobile_sdhi ee140000.sd: mmc2 base at 0xee140000 max clock rate 97 MHz
[    5.393429] asoc-simple-card sound: ak4642-hifi <-> ec500000.sound mapping ok
[    5.402269] input: keyboard as /devices/platform/keyboard/input/input0
[    5.410872] da9063-rtc da9063-rtc: setting system clock to 2000-01-01 00:00:01 UTC (946684801)
[    5.495935] Micrel KSZ8041RNLI ee700000.etherne:01: attached PHY driver [Micrel KSZ8041RNLI] (mii_bus:phy_addr=ee700000.etherne:01, irq=307)
[    5.508852] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
[    5.514872] IPv6: ADDRCONF(NETDEV_UP): usb0: link is not ready
[    5.633835] mmc1: new ultra high speed SDR50 SDHC card at address 0001
[    5.640811] mmcblk1: mmc1:0001 00000 29.8 GiB 
[    5.648918]  mmcblk1: p1
[    8.411027] sh-eth ee700000.ethernet eth0: Link is Up - 100Mbps/Full - flow control off
[    8.413703] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[    8.433686] Sending DHCP requests ., OK
[    8.613682] IP-Config: Got DHCP answer from 10.3.3.2, my address is 10.3.3.167
[    8.625312] IP-Config: Complete:
[    8.632542]      device=eth0, hwaddr=2e:09:0a:00:6e:71, ipaddr=10.3.3.167, mask=255.255.255.0, gw=10.3.3.2
[    8.646341]      host=10.3.3.167, domain=isobedori.kobe.vergenet.net kanocho.kobe.vergenet.net vergenet., nis-domain=(none)
[    8.661696]      bootserver=10.3.3.135, rootserver=10.3.3.135, rootpath=/srv/nfs/lager-armhf,rsize=1024,wsize=1024     nameserver0=10.3.3.2, nameserver1=8.8.8.8
[    8.684784] SDHI2 Vcc: disabling
[    8.692313] SDHI2 VccQ: disabling
[    8.700112] ALSA device list:
[    8.707304]   #0: rsnd-dai.0-ak4642-hifi
[    8.720578] VFS: Mounted root (nfs filesystem) on device 0:14.
[    8.731125] devtmpfs: mounted
[    8.739080] Freeing unused kernel memory: 1024K (c0900000 - c0a00000)
INIT: version 2.88 booting
Using makefile-style concurrent boot in runlevel S.
Starting the hotplug events dispatcher: udevd[    9.646302] udevd[1089]: starting version 175
.
Synthesizing the initial hotplug events...done.
[    9.781824] random: nonblocking pool is initialized
Waiting for /dev to be fully populated...done.
Activating swap...done.
Activating lvm and md swap...done.
Checking file systems...fsck from util-linux 2.20.1
done.
Mounting local filesystems...done.
Activating swapfile swap...done.
Cleaning up temporary files....
Cleaning up ifupdown....
Setting up networking....
Configuring network interfaces...Internet Systems Consortium DHCP Client 4.2.2
Copyright 2004-2011 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/

Listening on LPF/eth0/2e:09:0a:00:6e:71
Sending on   LPF/eth0/2e:09:0a:00:6e:71
Sending on   Socket/fallback
DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 6
DHCPREQUEST on eth0 to 255.255.255.255 port 67
DHCPOFFER from 10.3.3.2
DHCPACK from 10.3.3.2
RTNETLINK answers: File exists
bound to 10.3.3.167 -- renewal in 269 seconds.
done.
Cleaning up temporary files....
Setting up ALSA...warning: 'alsactl restore' failed with error message 'Found hardware: "rsnd-dai_0-ak46" "" "" "" ""
Hardware is initialized using a generic method'...done.
Setting kernel variables ...done.
INIT: Entering runlevel: 2
Using makefile-style concurrent boot in runlevel 2.
Starting enhanced syslogd: rsyslogd.
Starting periodic command scheduler: cron.
Starting system message bus: dbus.
Starting OpenBSD Secure Shell server: sshd.

Debian GNU/Linux wheezy/sid debian ttySC0

debian login: root
Password: 
Last login: Thu Jan  1 00:00:21 UTC 1970 on ttySC0
Linux debian 4.7.0-rc1-11566-g37773b1e292b #621 SMP Tue May 31 12:07:50 JST 2016 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root at debian:~# cat /proc/interrupts 
           CPU0       CPU1       CPU2       CPU3       
 19:       5428       4738       2964       2784     GIC-0  27 Edge      arch_timer
 21:          0          0          0          0     GIC-0  36 Level     e6050000.gpio
 22:          0          0          0          0     GIC-0  37 Level     e6051000.gpio
 23:          0          0          0          0     GIC-0  38 Level     e6052000.gpio
 24:          0          0          0          0     GIC-0  39 Level     e6053000.gpio
 25:          0          0          0          0     GIC-0  40 Level     e6054000.gpio
 26:          0          0          0          0     GIC-0  41 Level     e6055000.gpio
 27:          0          0          0          0     GIC-0 101 Level     e61f0000.thermal
 28:          0          0          0          0     GIC-0 174 Level     ffca0000.timer
 30:          1          0          0          0     GIC-0  32 Level     e61c0000.interrupt-controller
 31:          0          0          0          0     GIC-0  33 Level     e61c0000.interrupt-controller
 32:          6          0          0          0     GIC-0  34 Level     e61c0000.interrupt-controller
 33:          0          0          0          0     GIC-0  35 Level     e61c0000.interrupt-controller
 34:          0          0          0          0     GIC-0 229 Level     e6700000.dma-controller:error
 35:          0          0          0          0     GIC-0 232 Level     e6700000.dma-controller:0
 36:          0          0          0          0     GIC-0 233 Level     e6700000.dma-controller:1
 37:          0          0          0          0     GIC-0 234 Level     e6700000.dma-controller:2
 38:          0          0          0          0     GIC-0 235 Level     e6700000.dma-controller:3
 39:          0          0          0          0     GIC-0 236 Level     e6700000.dma-controller:4
 40:          0          0          0          0     GIC-0 237 Level     e6700000.dma-controller:5
 41:          0          0          0          0     GIC-0 238 Level     e6700000.dma-controller:6
 42:          0          0          0          0     GIC-0 239 Level     e6700000.dma-controller:7
 43:          0          0          0          0     GIC-0 240 Level     e6700000.dma-controller:8
 44:          0          0          0          0     GIC-0 241 Level     e6700000.dma-controller:9
 45:          0          0          0          0     GIC-0 242 Level     e6700000.dma-controller:10
 46:          0          0          0          0     GIC-0 243 Level     e6700000.dma-controller:11
 47:          0          0          0          0     GIC-0 244 Level     e6700000.dma-controller:12
 48:          0          0          0          0     GIC-0 245 Level     e6700000.dma-controller:13
 49:          0          0          0          0     GIC-0 246 Level     e6700000.dma-controller:14
 50:          0          0          0          0     GIC-0 252 Level     e6720000.dma-controller:error
 51:          0          0          0          0     GIC-0 248 Level     e6720000.dma-controller:0
 52:          0          0          0          0     GIC-0 249 Level     e6720000.dma-controller:1
 53:          0          0          0          0     GIC-0 250 Level     e6720000.dma-controller:2
 54:        203          0          0          0     GIC-0 251 Level     e6720000.dma-controller:3
 55:          0          0          0          0     GIC-0 340 Level     e6720000.dma-controller:4
 56:        171          0          0          0     GIC-0 341 Level     e6720000.dma-controller:5
 57:          0          0          0          0     GIC-0 342 Level     e6720000.dma-controller:6
 58:          0          0          0          0     GIC-0 343 Level     e6720000.dma-controller:7
 59:          0          0          0          0     GIC-0 344 Level     e6720000.dma-controller:8
 60:          0          0          0          0     GIC-0 345 Level     e6720000.dma-controller:9
 61:          0          0          0          0     GIC-0 346 Level     e6720000.dma-controller:10
 62:          0          0          0          0     GIC-0 347 Level     e6720000.dma-controller:11
 63:          0          0          0          0     GIC-0 348 Level     e6720000.dma-controller:12
 64:          0          0          0          0     GIC-0 349 Level     e6720000.dma-controller:13
 65:          0          0          0          0     GIC-0 350 Level     e6720000.dma-controller:14
 66:          0          0          0          0     GIC-0 378 Level     ec700000.dma-controller:error
 67:          0          0          0          0     GIC-0 352 Level     ec700000.dma-controller:0
 68:          0          0          0          0     GIC-0 353 Level     ec700000.dma-controller:1
 69:          0          0          0          0     GIC-0 354 Level     ec700000.dma-controller:2
 70:          0          0          0          0     GIC-0 355 Level     ec700000.dma-controller:3
 71:          0          0          0          0     GIC-0 356 Level     ec700000.dma-controller:4
 72:          0          0          0          0     GIC-0 357 Level     ec700000.dma-controller:5
 73:          0          0          0          0     GIC-0 358 Level     ec700000.dma-controller:6
 74:          0          0          0          0     GIC-0 359 Level     ec700000.dma-controller:7
 75:          0          0          0          0     GIC-0 360 Level     ec700000.dma-controller:8
 76:          0          0          0          0     GIC-0 361 Level     ec700000.dma-controller:9
 77:          0          0          0          0     GIC-0 362 Level     ec700000.dma-controller:10
 78:          0          0          0          0     GIC-0 363 Level     ec700000.dma-controller:11
 79:          0          0          0          0     GIC-0 364 Level     ec700000.dma-controller:12
 80:          0          0          0          0     GIC-0 379 Level     ec720000.dma-controller:error
 81:          0          0          0          0     GIC-0 365 Level     ec720000.dma-controller:0
 82:          0          0          0          0     GIC-0 366 Level     ec720000.dma-controller:1
 83:          0          0          0          0     GIC-0 367 Level     ec720000.dma-controller:2
 84:          0          0          0          0     GIC-0 368 Level     ec720000.dma-controller:3
 85:          0          0          0          0     GIC-0 369 Level     ec720000.dma-controller:4
 86:          0          0          0          0     GIC-0 370 Level     ec720000.dma-controller:5
 87:          0          0          0          0     GIC-0 371 Level     ec720000.dma-controller:6
 88:          0          0          0          0     GIC-0 372 Level     ec720000.dma-controller:7
 89:          0          0          0          0     GIC-0 373 Level     ec720000.dma-controller:8
 90:          0          0          0          0     GIC-0 374 Level     ec720000.dma-controller:9
 91:          0          0          0          0     GIC-0 375 Level     ec720000.dma-controller:10
 92:          0          0          0          0     GIC-0 376 Level     ec720000.dma-controller:11
 93:          0          0          0          0     GIC-0 377 Level     ec720000.dma-controller:12
 94:          0          0          0          0     GIC-0 141 Level     e65a0000.dma-controller:0, e65a0000.dma-controller:1
 95:          0          0          0          0     GIC-0 142 Level     e65b0000.dma-controller:0, e65b0000.dma-controller:1
 96:        546          0          0          0     GIC-0 202 Level     ee220000.mmc
 97:        385          0          0          0     GIC-0 197 Level     ee100000.sd
 98:          0          0          0          0     GIC-0 199 Level     ee140000.sd
100:        387          0          0          0     GIC-0 184 Level     e6e60000.serial:mux
101:      34376          0          0          0     GIC-0 194 Level     eth0
102:          0          0          0          0     GIC-0 138 Level     sata_rcar[ee500000.sata]
103:          0          0          0          0     GIC-0 139 Level     e6590000.usb
104:          0          0          0          0     GIC-0 221 Level     e6ef1000.video
105:          0          0          0          0     GIC-0 298 Level     fe920000.vsp1
106:          0          0          0          0     GIC-0 299 Level     fe928000.vsp1
107:          0          0          0          0     GIC-0 278 Level     fe930000.vsp1
108:          0          0          0          0     GIC-0 279 Level     fe938000.vsp1
109:        301          0          0          0     GIC-0 288 Level     feb00000.display
110:          0          0          0          0     GIC-0 300 Level     feb00000.display
111:          0          0          0          0     GIC-0 301 Level     feb00000.display
112:          0          0          0          0     GIC-0 304 Level     fe980000.jpeg-codec
113:         13          0          0          0     GIC-0 216 Level     e6b10000.spi:mux
114:          0          0          0          0     GIC-0 189 Level     e6e10000.spi
116:          0          0          0          0     GIC-0 140 Level     ehci_hcd:usb1, ohci_hcd:usb4
117:          0          0          0          0     GIC-0 144 Level     ehci_hcd:usb2, ohci_hcd:usb5
118:          0          0          0          0     GIC-0 145 Level     ehci_hcd:usb3, ohci_hcd:usb6
165:          0          0          0          0  e6051000.gpio  14 Edge      SW2-1
166:          0          0          0          0  e6051000.gpio  15 Level     10-0039
175:          0          0          0          0  e6051000.gpio  24 Edge      SW2-2
177:          0          0          0          0  e6051000.gpio  26 Edge      SW2-3
179:          0          0          0          0  e6051000.gpio  28 Edge      SW2-4
217:          0          0          0          0  e6053000.gpio   6 Edge      ee100000.sd cd
233:          0          0          0          0  e6053000.gpio  22 Edge      ee140000.sd cd
307:          1          0          0          0  e61c0000.interrupt-controller   0 Level     phy_interrupt
308:          0          0          0          0     GIC-0 206 Level     e6500000.i2c
309:          0          0          0          0     GIC-0 207 Level     e6510000.i2c
310:        205          0          0          0     GIC-0 208 Level     e6520000.i2c
311:        703          0          0          0     GIC-0 205 Level     e60b0000.i2c
312:          6          0          0          0  e61c0000.interrupt-controller   2 Level     da9063-irq, da9210
314:          0          0          0          0  da9063-irq   1 Level     ALARM
342:          0          0          0          0     GIC-0 402 Level     ec500000.sound
343:          0          0          0          0     GIC-0 403 Level     ec500000.sound
354:          0          0          0          0     GIC-0 386 Level     ec500000.sound
355:          0          0          0          0     GIC-0 387 Level     ec500000.sound
IPI0:          0          0          0          0  CPU wakeup interrupts
IPI1:          0          0          0          0  Timer broadcast interrupts
IPI2:       1474       4093       5034       3458  Rescheduling interrupts
IPI3:         28         32         17         35  Function call interrupts
IPI4:          0          0          0          0  CPU stop interrupts
IPI5:          0          0          0          0  IRQ work interrupts
IPI6:          0          0          0          0  completion interrupts
Err:          0
root at debian:~# dmesg | grep -A 2 i[2i]c
[    3.741394] i2c /dev entries driver
[    3.746291] i2c-sh_mobile e6500000.i2c: I2C adapter 4, bus speed 100000 Hz
[    3.754293] i2c-sh_mobile e6510000.i2c: I2C adapter 5, bus speed 100000 Hz
[    3.762237] i2c-sh_mobile e6520000.i2c: I2C adapter 6, bus speed 100000 Hz
[    3.777719] i2c-sh_mobile e60b0000.i2c: I2C adapter 7, bus speed 100000 Hz
[    3.785054] i2c 11-0058: Masking da9063 interrupt sources
[    3.796955] da9063 11-0058: Device detected (chip-ID: 0x61, var-ID: 0x30)
[    3.834992] da9063-rtc da9063-rtc: rtc core: registered da9063-rtc as rtc0
[    3.848136] i2c 11-0068: Masking da9210 interrupt sources
[    3.857027] i2c 11-0068: IRQ2 is not asserted, removing quirk
[    3.864260] DA9210: Bringing 1080000uV into 1000000-1000000uV
[    3.875154] adv7180 10-0020: chip found @ 0x20 (i2c-demux (master i2c-6))
[    3.895816] soc-camera-pdrv soc-camera-pdrv.0: Probing soc-camera-pdrv.0
[    3.903400] rcar_jpu fe980000.jpeg-codec: encoder device registered as /dev/video1


From horms+renesas at verge.net.au  Mon May 30 20:32:05 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Tue, 31 May 2016 12:32:05 +0900
Subject: [RFC 1/4] ARM: dts: r8a7790: lager: rename i2cexio as i2cexio0
In-Reply-To: <1464665528-11398-1-git-send-email-horms+renesas@verge.net.au>
References: <1464665528-11398-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1464665528-11398-2-git-send-email-horms+renesas@verge.net.au>

This is in preparation for adding i2cexio1 which will use the
dmuxer for IIC1/I2C0.

Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
---
 arch/arm/boot/dts/r8a7790-lager.dts | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index 9d20ace33b01..71d62ca282ea 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -50,7 +50,7 @@
 	aliases {
 		serial0 = &scif0;
 		serial1 = &scifa1;
-		i2c8 = "i2cexio";
+		i2c8 = "i2cexio0";
 	};
 
 	chosen {
@@ -263,10 +263,10 @@
 	 * instantiate the slave device at runtime according to the documentation.
 	 * You can then communicate with the slave via IIC3.
 	 */
-	i2cexio: i2c-8 {
+	i2cexio0: i2c-8 {
 		compatible = "i2c-demux-pinctrl";
 		i2c-parent = <&iic0>, <&i2c0>;
-		i2c-bus-name = "i2c-exio";
+		i2c-bus-name = "i2c-exio0";
 		#address-cells = <1>;
 		#size-cells = <0>;
 	};
@@ -580,12 +580,12 @@
 
 &i2c0	{
 	pinctrl-0 = <&i2c0_pins>;
-	pinctrl-names = "i2c-exio";
+	pinctrl-names = "i2c-exio0";
 };
 
 &iic0	{
 	pinctrl-0 = <&iic0_pins>;
-	pinctrl-names = "i2c-exio";
+	pinctrl-names = "i2c-exio0";
 };
 
 &iic1	{
-- 
2.1.4



From horms+renesas at verge.net.au  Mon May 30 20:32:06 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Tue, 31 May 2016 12:32:06 +0900
Subject: [RFC 2/4] ARM: dts: r8a7790: lager: use demuxer for IIC1/I2C1
In-Reply-To: <1464665528-11398-1-git-send-email-horms+renesas@verge.net.au>
References: <1464665528-11398-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1464665528-11398-3-git-send-email-horms+renesas@verge.net.au>

Make it possible to select which I2C1 IP core you want to run on the
EXIO-A connector.

This is based on reference work for the I2C0 core of the lager by Wolfram Sang.

Cc: Wolfram Sang <wsa+renesas at sang-engineering.com>
Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
---
 arch/arm/boot/dts/r8a7790-lager.dts | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index 71d62ca282ea..2e671aeafbef 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -51,6 +51,7 @@
 		serial0 = &scif0;
 		serial1 = &scifa1;
 		i2c8 = "i2cexio0";
+		i2c9 = "i2cexio1";
 	};
 
 	chosen {
@@ -270,6 +271,19 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 	};
+
+	/*
+	 * IIC1/I2C1 is routed to EXIO connector A, pins 78 (SCL) + 80 (SDA).
+	 * For further notes see i2cexio0.
+	 */
+
+	i2cexio1: i2c-9 {
+		compatible = "i2c-demux-pinctrl";
+		i2c-parent = <&iic1>, <&i2c1>;
+		i2c-bus-name = "i2c-exio1";
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
 };
 
 &du {
@@ -392,6 +406,11 @@
 		function = "iic0";
 	};
 
+	i2c1_pins: i2c1 {
+		groups = "i2c1";
+		function = "i2c1";
+	};
+
 	iic1_pins: iic1 {
 		groups = "iic1";
 		function = "iic1";
@@ -588,10 +607,14 @@
 	pinctrl-names = "i2c-exio0";
 };
 
+&i2c1	{
+	pinctrl-0 = <&i2c1_pins>;
+	pinctrl-names = "i2c-exio1";
+};
+
 &iic1	{
-	status = "okay";
 	pinctrl-0 = <&iic1_pins>;
-	pinctrl-names = "default";
+	pinctrl-names = "i2c-exio1";
 };
 
 &iic2	{
-- 
2.1.4



From horms+renesas at verge.net.au  Mon May 30 20:32:07 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Tue, 31 May 2016 12:32:07 +0900
Subject: [RFC 3/4] ARM: dts: r8a7790: lager: use demuxer for IIC2/I2C2
In-Reply-To: <1464665528-11398-1-git-send-email-horms+renesas@verge.net.au>
References: <1464665528-11398-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1464665528-11398-4-git-send-email-horms+renesas@verge.net.au>

Create a seperate bus for HDMI related I2C slaves.

Based on work by Wolfram Sang.

Cc: Wolfram Sang <wsa+renesas at sang-engineering.com>
Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
---
 arch/arm/boot/dts/r8a7790-lager.dts | 126 +++++++++++++++++++++---------------
 1 file changed, 73 insertions(+), 53 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index 2e671aeafbef..aa316bc358e1 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -52,6 +52,7 @@
 		serial1 = &scifa1;
 		i2c8 = "i2cexio0";
 		i2c9 = "i2cexio1";
+		i2c10 = "i2chdmi";
 	};
 
 	chosen {
@@ -284,6 +285,65 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 	};
+
+	i2chdmi: i2c-10 {
+		compatible = "i2c-demux-pinctrl";
+		i2c-parent = <&iic2>, <&i2c2>;
+		i2c-bus-name = "i2c-hdmi";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ak4643: codec at 12 {
+			compatible = "asahi-kasei,ak4643";
+			#sound-dai-cells = <0>;
+			reg = <0x12>;
+		};
+
+		composite-in at 20 {
+			compatible = "adi,adv7180";
+			reg = <0x20>;
+			remote = <&vin1>;
+
+			port {
+				adv7180: endpoint {
+					bus-width = <8>;
+					remote-endpoint = <&vin1ep0>;
+				};
+			};
+		};
+
+		hdmi at 39 {
+			compatible = "adi,adv7511w";
+			reg = <0x39>;
+			interrupt-parent = <&gpio1>;
+			interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+
+			adi,input-depth = <8>;
+			adi,input-colorspace = "rgb";
+			adi,input-clock = "1x";
+			adi,input-style = <1>;
+			adi,input-justification = "evenly";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port at 0 {
+					reg = <0>;
+					adv7511_in: endpoint {
+						remote-endpoint = <&du_out_lvds0>;
+					};
+				};
+
+				port at 1 {
+					reg = <1>;
+					adv7511_out: endpoint {
+						remote-endpoint = <&hdmi_con>;
+					};
+				};
+			};
+		};
+	};
 };
 
 &du {
@@ -416,6 +476,11 @@
 		function = "iic1";
 	};
 
+	i2c2_pins: i2c2 {
+		groups = "i2c2";
+		function = "i2c2";
+	};
+
 	iic2_pins: iic2 {
 		groups = "iic2";
 		function = "iic2";
@@ -617,63 +682,18 @@
 	pinctrl-names = "i2c-exio1";
 };
 
-&iic2	{
-	status = "okay";
-	pinctrl-0 = <&iic2_pins>;
-	pinctrl-names = "default";
+&i2c2	{
+	pinctrl-0 = <&i2c2_pins>;
+	pinctrl-names = "i2c-hdmi";
 
 	clock-frequency = <100000>;
+};
 
-	ak4643: codec at 12 {
-		compatible = "asahi-kasei,ak4643";
-		#sound-dai-cells = <0>;
-		reg = <0x12>;
-	};
-
-	composite-in at 20 {
-		compatible = "adi,adv7180";
-		reg = <0x20>;
-		remote = <&vin1>;
-
-		port {
-			adv7180: endpoint {
-				bus-width = <8>;
-				remote-endpoint = <&vin1ep0>;
-			};
-		};
-	};
-
-	hdmi at 39 {
-		compatible = "adi,adv7511w";
-		reg = <0x39>;
-		interrupt-parent = <&gpio1>;
-		interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
-
-		adi,input-depth = <8>;
-		adi,input-colorspace = "rgb";
-		adi,input-clock = "1x";
-		adi,input-style = <1>;
-		adi,input-justification = "evenly";
-
-		ports {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			port at 0 {
-				reg = <0>;
-				adv7511_in: endpoint {
-					remote-endpoint = <&du_out_lvds0>;
-				};
-			};
+&iic2	{
+	pinctrl-0 = <&iic2_pins>;
+	pinctrl-names = "i2c-hdmi";
 
-			port at 1 {
-				reg = <1>;
-				adv7511_out: endpoint {
-					remote-endpoint = <&hdmi_con>;
-				};
-			};
-		};
-	};
+	clock-frequency = <100000>;
 };
 
 &iic3 {
-- 
2.1.4



From horms+renesas at verge.net.au  Mon May 30 20:32:08 2016
From: horms+renesas at verge.net.au (Simon Horman)
Date: Tue, 31 May 2016 12:32:08 +0900
Subject: [RFC 4/4] ARM: dts: r8a7790: lager: use demuxer for IIC3/I2C3
In-Reply-To: <1464665528-11398-1-git-send-email-horms+renesas@verge.net.au>
References: <1464665528-11398-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <1464665528-11398-5-git-send-email-horms+renesas@verge.net.au>

Create a separate bus for dla98063 PMIC and da9210 regulator
related I2C slaves.

Based on similar work for HDMI by Wolfram Sang.

Cc: Wolfram Sang <wsa+renesas at sang-engineering.com>
Signed-off-by: Simon Horman <horms+renesas at verge.net.au>
---
 arch/arm/boot/dts/r8a7790-lager.dts | 80 +++++++++++++++++++++++--------------
 1 file changed, 49 insertions(+), 31 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index aa316bc358e1..d5fafdf3bcbd 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -53,6 +53,7 @@
 		i2c8 = "i2cexio0";
 		i2c9 = "i2cexio1";
 		i2c10 = "i2chdmi";
+		i2c11 = "i2cpwr";
 	};
 
 	chosen {
@@ -344,6 +345,42 @@
 			};
 		};
 	};
+
+	i2cpwr: i2c-11 {
+		compatible = "i2c-demux-pinctrl";
+		i2c-parent = <&iic3>, <&i2c3>;
+		i2c-bus-name = "i2c-pwr";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pmic at 58 {
+			compatible = "dlg,da9063";
+			reg = <0x58>;
+			interrupt-parent = <&irqc0>;
+			interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+			interrupt-controller;
+
+			rtc {
+				compatible = "dlg,da9063-rtc";
+			};
+
+			wdt {
+				compatible = "dlg,da9063-watchdog";
+			};
+		};
+
+		vdd_dvfs: regulator at 68 {
+			compatible = "dlg,da9210";
+			reg = <0x68>;
+			interrupt-parent = <&irqc0>;
+			interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+	};
 };
 
 &du {
@@ -486,6 +523,11 @@
 		function = "iic2";
 	};
 
+	i2c3_pins: i2c3 {
+		groups = "i2c3";
+		function = "i2c3";
+	};
+
 	iic3_pins: iic3 {
 		groups = "iic3";
 		function = "iic3";
@@ -696,38 +738,14 @@
 	clock-frequency = <100000>;
 };
 
-&iic3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&iic3_pins>;
-	status = "okay";
-
-	pmic at 58 {
-		compatible = "dlg,da9063";
-		reg = <0x58>;
-		interrupt-parent = <&irqc0>;
-		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
-		interrupt-controller;
-
-		rtc {
-			compatible = "dlg,da9063-rtc";
-		};
-
-		wdt {
-			compatible = "dlg,da9063-watchdog";
-		};
-	};
-
-	vdd_dvfs: regulator at 68 {
-		compatible = "dlg,da9210";
-		reg = <0x68>;
-		interrupt-parent = <&irqc0>;
-		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+&i2c3	{
+	pinctrl-0 = <&i2c3_pins>;
+	pinctrl-names = "i2c-pwr";
+};
 
-		regulator-min-microvolt = <1000000>;
-		regulator-max-microvolt = <1000000>;
-		regulator-boot-on;
-		regulator-always-on;
-	};
+&iic3	{
+	pinctrl-0 = <&iic3_pins>;
+	pinctrl-names = "i2c-pwr";
 };
 
 &pci0 {
-- 
2.1.4



From vikas.cha.sajjan at hpe.com  Mon May 30 21:57:13 2016
From: vikas.cha.sajjan at hpe.com (Sajjan, Vikas C)
Date: Tue, 31 May 2016 04:57:13 +0000
Subject: [PATCH] Add support to parse RASF Table
In-Reply-To: <TU4PR84MB0079FF2412932840DBE794C0C2770@TU4PR84MB0079.NAMPRD84.PROD.OUTLOOK.COM>
References: <1462796276-3987-1-git-send-email-nagendra.k-v@hpe.com>
 <TU4PR84MB0079FF2412932840DBE794C0C2770@TU4PR84MB0079.NAMPRD84.PROD.OUTLOOK.COM>
Message-ID: <TU4PR84MB004598D95417F3C00FC6BFC7D9460@TU4PR84MB0045.NAMPRD84.PROD.OUTLOOK.COM>

Hi Bob,

Any thoughts on this patch

Regards
Vikas Sajjan

-----Original Message-----
From: K V, Nagendra 
Sent: Monday, May 16, 2016 2:05 PM
To: robert.moore at intel.com
Cc: Sajjan, Vikas C <vikas.cha.sajjan at hpe.com>; Lakshminarasimha, Sunil Vishwanathpur <sunil.vl at hpe.com>; devel at acpica.org; linux-acpi at vger.kernel.org
Subject: RE: [PATCH] Add support to parse RASF Table

Bob,

Did you get chance to look into this?

Regards
Nagendra

-----Original Message-----
From: K V, Nagendra 
Sent: Monday, May 09, 2016 5:48 PM
To: robert.moore at intel.com
Cc: Sajjan, Vikas C <vikas.cha.sajjan at hpe.com>; Lakshminarasimha, Sunil Vishwanathpur <sunil.vl at hpe.com>; devel at acpica.org; K V, Nagendra <nagendra.k-v at hpe.com>
Subject: [PATCH] Add support to parse RASF Table

This patch adds support to parse RASF table. Currently RASF table is not being recognized.
---
 source/common/ahtable.c      |  1 +
 source/common/dmtable.c      |  7 +++++++
 source/common/dmtbinfo.c     | 13 +++++++++++++
 source/compiler/dtcompiler.h |  1 +
 source/compiler/dttemplate.h | 11 +++++++++++
 source/compiler/dtutils.c    |  5 +++++
 source/include/acdisasm.h    |  2 ++
 7 files changed, 40 insertions(+)

diff --git a/source/common/ahtable.c b/source/common/ahtable.c index 021ae33..59ddc83 100644
--- a/source/common/ahtable.c
+++ b/source/common/ahtable.c
@@ -196,6 +196,7 @@ const AH_TABLE      AcpiSupportedTables[] =
     {ACPI_SIG_NFIT, "NVDIMM Firmware Interface Table"},
     {ACPI_SIG_PCCT, "Platform Communications Channel Table"},
     {ACPI_SIG_PMTT, "Platform Memory Topology Table"},
+    {ACPI_SIG_RASF, "RAS Features Table"},
     {ACPI_RSDP_NAME,"Root System Description Pointer"},
     {ACPI_SIG_RSDT, "Root System Description Table"},
     {ACPI_SIG_S3PT, "S3 Performance Table"}, diff --git a/source/common/dmtable.c b/source/common/dmtable.c index 51d91f8..321407c 100644
--- a/source/common/dmtable.c
+++ b/source/common/dmtable.c
@@ -430,6 +430,7 @@ const ACPI_DMTABLE_DATA     AcpiDmTableData[] =
     {ACPI_SIG_NFIT, AcpiDmTableInfoNfit,    AcpiDmDumpNfit, DtCompileNfit,  TemplateNfit},
     {ACPI_SIG_PCCT, AcpiDmTableInfoPcct,    AcpiDmDumpPcct, DtCompilePcct,  TemplatePcct},
     {ACPI_SIG_PMTT, NULL,                   AcpiDmDumpPmtt, DtCompilePmtt,  TemplatePmtt},
+    {ACPI_SIG_RASF, AcpiDmTableInfoRasf,    NULL,           NULL,           TemplateRasf},
     {ACPI_SIG_RSDT, NULL,                   AcpiDmDumpRsdt, DtCompileRsdt,  TemplateRsdt},
     {ACPI_SIG_S3PT, NULL,                   NULL,           NULL,           TemplateS3pt},
     {ACPI_SIG_SBST, AcpiDmTableInfoSbst,    NULL,           NULL,           TemplateSbst},
@@ -916,6 +917,11 @@ AcpiDmDumpTable (
             ByteLength = 10;
             break;
 
+        case ACPI_DMT_RASF:
+
+            ByteLength = 12;
+            break;
+
         case ACPI_DMT_BUF16:
         case ACPI_DMT_UUID:
 
@@ -1048,6 +1054,7 @@ AcpiDmDumpTable (
 
         /* Integer Data Types */
 
+        case ACPI_DMT_RASF:
         case ACPI_DMT_UINT8:
         case ACPI_DMT_UINT16:
         case ACPI_DMT_UINT24:
diff --git a/source/common/dmtbinfo.c b/source/common/dmtbinfo.c index 5520da2..3896b69 100644
--- a/source/common/dmtbinfo.c
+++ b/source/common/dmtbinfo.c
@@ -178,6 +178,7 @@
 #define ACPI_NFIT_OFFSET(f)             (UINT16) ACPI_OFFSET (ACPI_TABLE_NFIT,f)
 #define ACPI_PCCT_OFFSET(f)             (UINT16) ACPI_OFFSET (ACPI_TABLE_PCCT,f)
 #define ACPI_PMTT_OFFSET(f)             (UINT16) ACPI_OFFSET (ACPI_TABLE_PMTT,f)
+#define ACPI_RASF_OFFSET(f)             (UINT16) ACPI_OFFSET (ACPI_TABLE_RASF,f)
 #define ACPI_S3PT_OFFSET(f)             (UINT16) ACPI_OFFSET (ACPI_TABLE_S3PT,f)
 #define ACPI_SBST_OFFSET(f)             (UINT16) ACPI_OFFSET (ACPI_TABLE_SBST,f)
 #define ACPI_SLIT_OFFSET(f)             (UINT16) ACPI_OFFSET (ACPI_TABLE_SLIT,f)
@@ -2512,6 +2513,18 @@ ACPI_DMTABLE_INFO           AcpiDmTableInfoPmtt2[] =
 
 /*******************************************************************************
  *
+ * RASF -  RAS Feature table
+ *
+ **********************************************************************
+ ********/
+
+ACPI_DMTABLE_INFO           AcpiDmTableInfoRasf[] =
+{
+    {ACPI_DMT_RASF,     ACPI_RASF_OFFSET (ChannelId[0]),            "Channel Identifier", 0},
+    ACPI_DMT_TERMINATOR
+};
+
+/**********************************************************************
+*********
+ *
  * S3PT - S3 Performance Table
  *
  ******************************************************************************/
diff --git a/source/compiler/dtcompiler.h b/source/compiler/dtcompiler.h index eb85ddc..1072f52 100644
--- a/source/compiler/dtcompiler.h
+++ b/source/compiler/dtcompiler.h
@@ -681,6 +681,7 @@ extern const unsigned char  TemplateMtmr[];  extern const unsigned char  TemplateNfit[];  extern const unsigned char  TemplatePcct[];  extern const unsigned char  TemplatePmtt[];
+extern const unsigned char  TemplateRasf[];
 extern const unsigned char  TemplateRsdt[];  extern const unsigned char  TemplateS3pt[];  extern const unsigned char  TemplateSbst[]; diff --git a/source/compiler/dttemplate.h b/source/compiler/dttemplate.h index e420ec4..d17b2af 100644
--- a/source/compiler/dttemplate.h
+++ b/source/compiler/dttemplate.h
@@ -978,6 +978,17 @@ const unsigned char TemplatePmtt[] =
     0x00,0x00,0x00,0x00                       /* 000000B0    "...."     */
 };
 
+const unsigned char TemplateRasf[] =
+{
+    0x42,0x45,0x52,0x54,0x30,0x00,0x00,0x00,  /* 00000000    "RASF0..." */
+    0x01,0x15,0x49,0x4E,0x54,0x45,0x4C,0x20,  /* 00000008    "..INTEL " */
+    0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45,  /* 00000010    "TEMPLATE" */
+    0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL" */
+    0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00,  /* 00000020    "(.. ...." */
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000028    "........" */
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00   /* 00000030    "........" */
+};
+
 const unsigned char TemplateRsdp[] =
 {
     0x52,0x53,0x44,0x20,0x50,0x54,0x52,0x20,  /* 00000000    "RSD PTR " */
diff --git a/source/compiler/dtutils.c b/source/compiler/dtutils.c index 6ca418c..774db8b 100644
--- a/source/compiler/dtutils.c
+++ b/source/compiler/dtutils.c
@@ -688,6 +688,11 @@ DtGetFieldLength (
         ByteLength = 10;
         break;
 
+    case ACPI_DMT_RASF:
+
+        ByteLength = 12;
+        break;
+
     case ACPI_DMT_BUF16:
     case ACPI_DMT_UUID:
 
diff --git a/source/include/acdisasm.h b/source/include/acdisasm.h index ba8f274..d59e4d9 100644
--- a/source/include/acdisasm.h
+++ b/source/include/acdisasm.h
@@ -227,6 +227,7 @@ typedef enum
     ACPI_DMT_NFIT,
     ACPI_DMT_PCCT,
     ACPI_DMT_PMTT,
+    ACPI_DMT_RASF,
     ACPI_DMT_SLIC,
     ACPI_DMT_SRAT,
 
@@ -458,6 +459,7 @@ extern ACPI_DMTABLE_INFO        AcpiDmTableInfoPcctHdr[];
 extern ACPI_DMTABLE_INFO        AcpiDmTableInfoPcct0[];
 extern ACPI_DMTABLE_INFO        AcpiDmTableInfoPcct1[];
 extern ACPI_DMTABLE_INFO        AcpiDmTableInfoPcct2[];
+extern ACPI_DMTABLE_INFO        AcpiDmTableInfoRasf[];
 extern ACPI_DMTABLE_INFO        AcpiDmTableInfoRsdp1[];
 extern ACPI_DMTABLE_INFO        AcpiDmTableInfoRsdp2[];
 extern ACPI_DMTABLE_INFO        AcpiDmTableInfoS3pt[];
--
2.5.0



From nava.manne at xilinx.com  Mon May 30 22:15:10 2016
From: nava.manne at xilinx.com (Nava kishore Manne)
Date: Tue, 31 May 2016 05:15:10 +0000
Subject: [PATCH v4] Axi-usb: Add support for 64-bit addressing.
In-Reply-To: <CAKfKVtF1hOn9QwiqtjqqPYtUz5PscTBs4kBC1zRH6FY-4vVoUA@mail.gmail.com>
References: <1464626798-1334-1-git-send-email-navam@xilinx.com>
 <CAKfKVtF1hOn9QwiqtjqqPYtUz5PscTBs4kBC1zRH6FY-4vVoUA@mail.gmail.com>
Message-ID: <C89496FEAE474D468F30D558A9468D9F26CEF0EF@XAP-PVEXMBX01.xlnx.xilinx.com>

Hi Shubhrajyoti,

	
	Thanks for the review...

> >  /**
> > + * xudc_write64 - write 64bit value to device registers
> > + * @ep: pointer to the usb device endpoint structure.
> > + * @offset: register offset
> > + * @val: data to be written
> > + **/
> > +static void xudc_write64(struct xusb_ep *ep, u32 offset, u64 val) {
> > +       struct xusb_udc *udc = ep->udc;
> > +
> > +       udc->write_fn(udc->addr, offset, lower_32_bits(val));
> > +       udc->write_fn(udc->addr, offset+0x04, upper_32_bits(val));
> 
> can we move this to a single 64 bit write?

Initially I sent the patches with writeq() ,lo_hi_writeq()  later we decided to replace with write_fun().
The reason for this is lo_hi_writeq() always assumes a little-endian register, so it's broken if anyone builds this device with big-endian registers.
So replaced the 64bit calls with write_fun() as suggested by Arnd Bergmann. Hope it clears your query.
Please refer to the below thread

	http://lkml.iu.edu/hypermail/linux/kernel/1604.2/02046.html 


Regards,
Navakishore.


From chunfeng.yun at mediatek.com  Mon May 30 22:52:39 2016
From: chunfeng.yun at mediatek.com (Chunfeng Yun)
Date: Tue, 31 May 2016 13:52:39 +0800
Subject: [PATCH v2,2/5] usb: xhci-mtk: make IPPC register optional
In-Reply-To: <1464673962-11506-1-git-send-email-chunfeng.yun@mediatek.com>
References: <1464673962-11506-1-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <1464673962-11506-3-git-send-email-chunfeng.yun@mediatek.com>

Make IPPC register optional to support host side of dual-role mode,
due to it is moved into common glue layer for simplification.

Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
---
 drivers/usb/host/xhci-mtk.c |   32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 79959f1..dc86832 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -94,6 +94,9 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk)
 	int ret;
 	int i;
 
+	if (ippc == NULL)
+		return 0;
+
 	/* power on host ip */
 	value = readl(&ippc->ip_pw_ctr1);
 	value &= ~CTRL1_IP_HOST_PDN;
@@ -139,6 +142,9 @@ static int xhci_mtk_host_disable(struct xhci_hcd_mtk *mtk)
 	int ret;
 	int i;
 
+	if (ippc == NULL)
+		return 0;
+
 	/* power down all u3 ports */
 	for (i = 0; i < mtk->num_u3_ports; i++) {
 		value = readl(&ippc->u3_ctrl_p[i]);
@@ -173,6 +179,9 @@ static int xhci_mtk_ssusb_config(struct xhci_hcd_mtk *mtk)
 	struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs;
 	u32 value;
 
+	if (ippc == NULL)
+		return 0;
+
 	/* reset whole ip */
 	value = readl(&ippc->ip_pw_ctr0);
 	value |= CTRL0_IP_SW_RST;
@@ -475,6 +484,7 @@ static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci)
 /* called during probe() after chip reset completes */
 static int xhci_mtk_setup(struct usb_hcd *hcd)
 {
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 	struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
 	int ret;
 
@@ -482,12 +492,21 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
 		ret = xhci_mtk_ssusb_config(mtk);
 		if (ret)
 			return ret;
+	}
+
+	ret = xhci_gen_setup(hcd, xhci_mtk_quirks);
+	if (ret)
+		return ret;
+
+	if (usb_hcd_is_primary_hcd(hcd)) {
+		mtk->num_u3_ports = xhci->num_usb3_ports;
+		mtk->num_u2_ports = xhci->num_usb2_ports;
 		ret = xhci_mtk_sch_init(mtk);
 		if (ret)
 			return ret;
 	}
 
-	return xhci_gen_setup(hcd, xhci_mtk_quirks);
+	return ret;
 }
 
 static int xhci_mtk_probe(struct platform_device *pdev)
@@ -595,11 +614,14 @@ static int xhci_mtk_probe(struct platform_device *pdev)
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_len = resource_size(res);
 
+	mtk->ippc_regs = NULL;
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	mtk->ippc_regs = devm_ioremap_resource(dev, res);
-	if (IS_ERR(mtk->ippc_regs)) {
-		ret = PTR_ERR(mtk->ippc_regs);
-		goto put_usb2_hcd;
+	if (res) {	/* ippc register is optional */
+		mtk->ippc_regs = devm_ioremap_resource(dev, res);
+		if (IS_ERR(mtk->ippc_regs)) {
+			ret = PTR_ERR(mtk->ippc_regs);
+			goto put_usb2_hcd;
+		}
 	}
 
 	for (phy_num = 0; phy_num < mtk->num_phys; phy_num++) {
-- 
1.7.9.5



From chunfeng.yun at mediatek.com  Mon May 30 22:52:42 2016
From: chunfeng.yun at mediatek.com (Chunfeng Yun)
Date: Tue, 31 May 2016 13:52:42 +0800
Subject: [PATCH v2,5/5] arm64: dts: mediatek: add USB3 DRD driver
In-Reply-To: <1464673962-11506-1-git-send-email-chunfeng.yun@mediatek.com>
References: <1464673962-11506-1-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <1464673962-11506-6-git-send-email-chunfeng.yun@mediatek.com>

USB3 DRD driver is added for MT8173-EVB, and xHCI driver
becomes its subnode

Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8173-evb.dts |   46 +++++++++++++++++++++++++--
 arch/arm64/boot/dts/mediatek/mt8173.dtsi    |   28 ++++++++++++----
 2 files changed, 65 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
index 7453a47..682dfd7 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
@@ -34,6 +34,11 @@
 
 	chosen { };
 
+	extcon_usb: extcon_iddig {
+		compatible = "linux,extcon-usb-gpio";
+		id-gpio = <&pio 16 GPIO_ACTIVE_HIGH>;
+	};
+
 	usb_p1_vbus: regulator at 0 {
 		compatible = "regulator-fixed";
 		regulator-name = "usb_vbus";
@@ -42,6 +47,16 @@
 		gpio = <&pio 130 GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 	};
+
+	usb_p0_vbus: regulator at 1 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&pio 9 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
 };
 
 &i2c1 {
@@ -205,6 +220,20 @@
 			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
 		};
 	};
+
+	usb_id_pins_float: usb_iddig_pull_up {
+		pins_iddig {
+			pinmux = <MT8173_PIN_16_IDDIG__FUNC_IDDIG>;
+			bias-pull-up;
+		};
+	};
+
+	usb_id_pins_ground: usb_iddig_pull_down {
+		pins_iddig {
+			pinmux = <MT8173_PIN_16_IDDIG__FUNC_IDDIG>;
+			bias-pull-down;
+		};
+	};
 };
 
 &pwm0 {
@@ -431,12 +460,25 @@
 	status = "okay";
 };
 
+&ssusb {
+	vusb33-supply = <&mt6397_vusb_reg>;
+	vbus-supply = <&usb_p0_vbus>;
+	extcon = <&extcon_usb>;
+	dr_mode = "otg";
+	mediatek,enable-wakeup;
+	pinctrl-names = "default", "id_float", "id_ground";
+	pinctrl-0 = <&usb_id_pins_float>;
+	pinctrl-1 = <&usb_id_pins_float>;
+	pinctrl-2 = <&usb_id_pins_ground>;
+	status = "okay";
+};
+
 &uart0 {
 	status = "okay";
 };
 
-&usb30 {
+&usb_host {
 	vusb33-supply = <&mt6397_vusb_reg>;
 	vbus-supply = <&usb_p1_vbus>;
-	mediatek,wakeup-src = <1>;
+	status = "okay";
 };
diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index 05f89c4..723ab6e 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -608,11 +608,14 @@
 			status = "disabled";
 		};
 
-		usb30: usb at 11270000 {
-			compatible = "mediatek,mt8173-xhci";
-			reg = <0 0x11270000 0 0x1000>,
+		ssusb: usb at 11271000 {
+			compatible = "mediatek,mt8173-mtu3";
+			reg = <0 0x11271000 0 0x3000>,
 			      <0 0x11280700 0 0x0100>;
-			interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
+			reg-names = "mac", "ippc";
+			interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>;
+			phys = <&phy_port0 PHY_TYPE_USB3>,
+			       <&phy_port1 PHY_TYPE_USB2>;
 			power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
 			clocks = <&topckgen CLK_TOP_USB30_SEL>,
 				 <&pericfg CLK_PERI_USB0>,
@@ -620,10 +623,21 @@
 			clock-names = "sys_ck",
 				      "wakeup_deb_p0",
 				      "wakeup_deb_p1";
-			phys = <&phy_port0 PHY_TYPE_USB3>,
-			       <&phy_port1 PHY_TYPE_USB2>;
 			mediatek,syscon-wakeup = <&pericfg>;
-			status = "okay";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+			status = "disabled";
+
+			usb_host: xhci at 11270000 {
+				compatible = "mediatek,mt8173-xhci";
+				reg = <0 0x11270000 0 0x1000>;
+				interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
+				power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
+				clocks = <&topckgen CLK_TOP_USB30_SEL>;
+				clock-names = "sys_ck";
+				status = "disabled";
+			};
 		};
 
 		u3phy: usb-phy at 11290000 {
-- 
1.7.9.5



From chunfeng.yun at mediatek.com  Mon May 30 22:52:40 2016
From: chunfeng.yun at mediatek.com (Chunfeng Yun)
Date: Tue, 31 May 2016 13:52:40 +0800
Subject: [PATCH v2,3/5] dt-bindings: mtu3: add devicetree bindings
In-Reply-To: <1464673962-11506-1-git-send-email-chunfeng.yun@mediatek.com>
References: <1464673962-11506-1-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <1464673962-11506-4-git-send-email-chunfeng.yun@mediatek.com>

add a DT binding doc for MediaTek USB3 DRD driver

Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
---
 Documentation/devicetree/bindings/usb/mtu3.txt |   85 ++++++++++++++++++++++++
 1 file changed, 85 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/mtu3.txt

diff --git a/Documentation/devicetree/bindings/usb/mtu3.txt b/Documentation/devicetree/bindings/usb/mtu3.txt
new file mode 100644
index 0000000..571ae8b
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/mtu3.txt
@@ -0,0 +1,85 @@
+The device node for Mediatek USB3.0 DRD controller
+
+Required properties:
+ - compatible : should be "mediatek,mt8173-mtu3"
+ - reg : specifies physical base address and size of the registers
+ - reg-names: should be "mac" for device IP and "ippc" for IP port control
+ - interrupts : interrupt used by the device IP
+ - power-domains : a phandle to USB power domain node to control USB's
+	mtcmos
+ - vusb33-supply : regulator of USB avdd3.3v
+ - clocks : a list of phandle + clock-specifier pairs, one for each
+	entry in clock-names
+ - clock-names : must contain "sys_ck" for clock of controller;
+	"wakeup_deb_p0" and "wakeup_deb_p1" are optional, they are
+	depends on "mediatek,enable-wakeup"
+ - phys : a list of phandle + phy specifier pairs
+ - dr_mode : should be one of "host", "peripheral" or "otg",
+	refer to usb/generic.txt
+
+Optional properties:
+ - #address-cells, #size-cells : should be '2' if the device has sub-nodes
+	with 'reg' property
+ - ranges : allows valid 1:1 translation between child's address space and
+	parent's address space
+ - extcon : external connector for vbus and idpin changes detection, needed
+	when supports dual-role mode.
+ - vbus-supply : reference to the VBUS regulator, needed when supports
+	dual-role mode.
+ - pinctl-names : a pinctrl state named "default" must be defined,
+	"id_float" and "id_ground" are optinal which depends on
+	"mediatek,enable-manual-drd"
+ - pinctrl-0 : pin control group
+	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+
+ - maximum-speed : valid arguments are "super-speed", "high-speed" and
+	"full-speed"; refer to usb/generic.txt
+ - enable-manual-drd : supports manual dual-role switch via sysfs; only used
+	when receptacle is TYPE-A and also wants to support dual-role mode.
+ - mediatek,enable-wakeup : supports ip sleep wakeup used by host mode
+ - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup
+	control register, it depends on "mediatek,enable-wakeup".
+
+Sub-nodes:
+The xhci should be added as subnode to mtu3 as shown in the following example
+if host mode is enabled. The DT binding details of xhci can be found in:
+Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+
+Example:
+ssusb: usb at 11271000 {
+	compatible = "mediatek,mt8173-mtu3";
+	reg = <0 0x11271000 0 0x3000>,
+	      <0 0x11280700 0 0x0100>;
+	reg-names = "mac", "ippc";
+	interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>;
+	phys = <&phy_port0 PHY_TYPE_USB3>,
+	       <&phy_port1 PHY_TYPE_USB2>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
+	clocks = <&topckgen CLK_TOP_USB30_SEL>,
+		 <&pericfg CLK_PERI_USB0>,
+		 <&pericfg CLK_PERI_USB1>;
+	clock-names = "sys_ck",
+		      "wakeup_deb_p0",
+		      "wakeup_deb_p1";
+	vusb33-supply = <&mt6397_vusb_reg>;
+	vbus-supply = <&usb_p0_vbus>;
+	extcon = <&extcon_usb>;
+	dr_mode = "otg";
+	mediatek,enable-wakeup;
+	mediatek,syscon-wakeup = <&pericfg>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+	ranges;
+	status = "disabled";
+
+	usb_host: xhci at 11270000 {
+		compatible = "mediatek,mt8173-xhci";
+		reg = <0 0x11270000 0 0x1000>;
+		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
+		power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
+		clocks = <&topckgen CLK_TOP_USB30_SEL>;
+		clock-names = "sys_ck";
+		vusb33-supply = <&mt6397_vusb_reg>;
+		status = "disabled";
+	};
+};
-- 
1.7.9.5



From chunfeng.yun at mediatek.com  Mon May 30 22:52:37 2016
From: chunfeng.yun at mediatek.com (Chunfeng Yun)
Date: Tue, 31 May 2016 13:52:37 +0800
Subject: Add MediaTek USB3 DRD Driver
Message-ID: <1464673962-11506-1-git-send-email-chunfeng.yun@mediatek.com>

>From f2b6744b1ed13636db8690dd3e8d65ad7f3fb7ce Mon Sep 17 00:00:00 2001
From: Chunfeng Yun <chunfeng.yun at mediatek.com>
Date: Tue, 31 May 2016 10:52:46 +0800
Subject: [PATCH 0/5] Add MediaTek USB3 DRD Driver

These patches introduce the MediaTek USB3 dual-role controller
driver.

The driver can be configured as Dual-Role Device (DRD),
Peripheral Only and Host Only (xHCI) modes. It works well
with Mass Storage, RNDIS and g_zero on FS/HS and SS. And it is
tested on MT8173 platform which only contains USB2.0 device IP,
and on MT6290 platform which contains USB3.0 device IP.

Change in v2:
1. modify binding docs according to suggestions 
2. modify some comments and remove some dummy blank lines
3. fix memory leakage

Chunfeng Yun (5):
  dt-bindings: mt8173-xhci: support host side of dual-role mode
  usb: xhci-mtk: make IPPC register optional
  dt-bindings: mtu3: add devicetree bindings
  usb: Add MediaTek USB3 DRD Driver
  arm64: dts: mediatek: add USB3 DRD driver

 .../devicetree/bindings/usb/mt8173-xhci.txt        |   48 ++
 Documentation/devicetree/bindings/usb/mtu3.txt     |   85 ++
 arch/arm64/boot/dts/mediatek/mt8173-evb.dts        |   46 +-
 arch/arm64/boot/dts/mediatek/mt8173.dtsi           |   28 +-
 drivers/usb/Kconfig                                |    2 +
 drivers/usb/Makefile                               |    1 +
 drivers/usb/host/xhci-mtk.c                        |   32 +-
 drivers/usb/mtu3/Kconfig                           |   47 ++
 drivers/usb/mtu3/Makefile                          |   20 +
 drivers/usb/mtu3/mtu3.h                            |  422 ++++++++++
 drivers/usb/mtu3/mtu3_core.c                       |  879 ++++++++++++++++++++
 drivers/usb/mtu3/mtu3_dr.c                         |  348 ++++++++
 drivers/usb/mtu3/mtu3_dr.h                         |  108 +++
 drivers/usb/mtu3/mtu3_gadget.c                     |  731 ++++++++++++++++
 drivers/usb/mtu3/mtu3_gadget_ep0.c                 |  879 ++++++++++++++++++++
 drivers/usb/mtu3/mtu3_host.c                       |  294 +++++++
 drivers/usb/mtu3/mtu3_hw_regs.h                    |  474 +++++++++++
 drivers/usb/mtu3/mtu3_plat.c                       |  490 +++++++++++
 drivers/usb/mtu3/mtu3_qmu.c                        |  599 +++++++++++++
 drivers/usb/mtu3/mtu3_qmu.h                        |   43 +
 20 files changed, 5562 insertions(+), 14 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/mtu3.txt
 create mode 100644 drivers/usb/mtu3/Kconfig
 create mode 100644 drivers/usb/mtu3/Makefile
 create mode 100644 drivers/usb/mtu3/mtu3.h
 create mode 100644 drivers/usb/mtu3/mtu3_core.c
 create mode 100644 drivers/usb/mtu3/mtu3_dr.c
 create mode 100644 drivers/usb/mtu3/mtu3_dr.h
 create mode 100644 drivers/usb/mtu3/mtu3_gadget.c
 create mode 100644 drivers/usb/mtu3/mtu3_gadget_ep0.c
 create mode 100644 drivers/usb/mtu3/mtu3_host.c
 create mode 100644 drivers/usb/mtu3/mtu3_hw_regs.h
 create mode 100644 drivers/usb/mtu3/mtu3_plat.c
 create mode 100644 drivers/usb/mtu3/mtu3_qmu.c
 create mode 100644 drivers/usb/mtu3/mtu3_qmu.h

-- 
1.7.9.5



From John.Youn at synopsys.com  Mon May 30 22:53:18 2016
From: John.Youn at synopsys.com (John Youn)
Date: Mon, 30 May 2016 22:53:18 -0700
Subject: [PATCH] reset: Put back *_optional variants
In-Reply-To: <5cf9f346-9b6e-d521-612c-9edd167aa759@redhat.com>
References: <ca359e013c30f27c825a9580164b01da5ca6476d.1464224883.git.johnyoun@synopsys.com>
 <12e450f0-70ea-29f8-0bf7-8a0697263f2d@redhat.com>
 <57476E48.2060204@synopsys.com>
 <dcf6372f-4910-bd03-f1b5-c7e0086fdead@redhat.com>
 <1464603520.3808.34.camel@pengutronix.de>
 <5cf9f346-9b6e-d521-612c-9edd167aa759@redhat.com>
Message-ID: <da7e41b2-de80-c692-e7ec-ba8231dadb0a@synopsys.com>

On 5/30/2016 4:32 AM, Hans de Goede wrote:
> Hi,
> 
> On 30-05-16 12:18, Philipp Zabel wrote:
>> Hi,
>>
>> Am Freitag, den 27.05.2016, 09:06 +0200 schrieb Hans de Goede:
>> [...]
>>>>> So IMHO the following change would be a better way to fix this:
>>>>>
>>>>> --- a/include/linux/reset.h
>>>>> +++ b/include/linux/reset.h
>>>>> @@ -65,14 +65,14 @@ static inline struct reset_control *__of_reset_control_get(
>>>>>                                          struct device_node *node,
>>>>>                                          const char *id, int index, int shared)
>>>>>   {
>>>>> -   return ERR_PTR(-EINVAL);
>>>>> + return ERR_PTR(-ENOTSUPP);
>>>>>   }
>>>>>
>>>>>   static inline struct reset_control *__devm_reset_control_get(
>>>>>                                          struct device *dev,
>>>>>                                          const char *id, int index, int shared)
>>>>>   {
>>>>> -   return ERR_PTR(-EINVAL);
>>>>> + return ERR_PTR(-ENOTSUPP);
>>>>>   }
>>>>>
>>>>>   #endif /* CONFIG_RESET_CONTROLLER */
>>>>
>>>>
>>>> I'm good with this. However, per Philipp on a previous thread, the
>>>> intended behavior is to return -EINVAL for the non-optional functions.
>>>>
>>>> http://marc.info/?l=linux-usb&m=146156945528848&w=2
>>
>> Adding Dinh to Cc: because he wanted this changed from -EINVAL.
>> My point then was that WARN_ON + -EINVAL is indented in this case.
>>
>> Given that the warning backtrace already helps to identify the issue
>> (CONFIG_RESET_CONTROLLER disabled), and that changing the return value
>> to -ENOTSUPP improves consistency with the rest of the API and reduces
>> the amount of inline wrappers, I concur.
>>
>>> As Philipp rightfully points out, calling the non-optional functions
>>> without CONFIG_RESET_CONTROLLER is a no-no, so IMHO we should not have to
>>> care too much about the error code in that case, as long as we return
>>> an error.
>>>
>>> Also note that even before my patch things were already inconsistent
>>> with the of_...get... functions already always returning
>>> -ENOTSUPP when CONFIG_RESET_CONTROLLER was not set, to me it seems
>>> best and also KISS to just return -ENOTSUPP from all get functions
>>> when CONFIG_RESET_CONTROLLER is not set.
>>>
>>> Anyways this is Philipp's call, this is all just my 2 cents.
>>
>> Let the stubs return -ENOTSUPP consistently. A quick grep doesn't show
>> any driver handling -EINVAL explicitly either.
> 
> Great.
> 
> John Youn, can you submit a patch changing the return of the stubs
> from -EINVAL to -ENOTSUPP please ?
> 

Sure. I'll send a patch tomorrow.

Regards,
John




From chunfeng.yun at mediatek.com  Mon May 30 22:52:38 2016
From: chunfeng.yun at mediatek.com (Chunfeng Yun)
Date: Tue, 31 May 2016 13:52:38 +0800
Subject: [PATCH v2,
 1/5] dt-bindings: mt8173-xhci: support host side of dual-role mode
In-Reply-To: <1464673962-11506-1-git-send-email-chunfeng.yun@mediatek.com>
References: <1464673962-11506-1-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <1464673962-11506-2-git-send-email-chunfeng.yun@mediatek.com>

Some resources, such as IPPC register etc, shared with device
driver are moved into common glue layer when xHCI driver is the
host side of dual-role mode and they should be changed as optional
properties if they are required ones before. For clarity, add
a new part of binding to support host side of dual-role mode.

Additionally add optional properties of pinctrl for host only mode

Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
---
 .../devicetree/bindings/usb/mt8173-xhci.txt        |   48 ++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
index b3a7ffa..542e3fa 100644
--- a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
@@ -2,6 +2,14 @@ MT8173 xHCI
 
 The device node for Mediatek SOC USB3.0 host controller
 
+There are two scenarios: the first one only supports xHCI driver;
+the second one supports dual-role mode, and the host is based on xHCI
+driver. Take account of backward compatibility, we divide bindings
+into two parts.
+
+1st: only supports xHCI driver
+------------------------------------------------------------------------
+
 Required properties:
  - compatible : should contain "mediatek,mt8173-xhci"
  - reg : specifies physical base address and size of the registers,
@@ -27,6 +35,9 @@ Optional properties:
 	control register, it depends on "mediatek,wakeup-src".
  - vbus-supply : reference to the VBUS regulator;
  - usb3-lpm-capable : supports USB3.0 LPM
+ - pinctl-names : a pinctrl state named "default" must be defined
+ - pinctrl-0 : pin control group
+	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
 
 Example:
 usb30: usb at 11270000 {
@@ -49,3 +60,40 @@ usb30: usb at 11270000 {
 	mediatek,syscon-wakeup = <&pericfg>;
 	mediatek,wakeup-src = <1>;
 };
+
+2nd: dual-role mode with xHCI driver
+------------------------------------------------------------------------
+
+In the case, xhci is added as subnode to mtu3. An example and the DT binding
+details of mtu3 can be found in:
+Documentation/devicetree/bindings/usb/mtu3.txt
+
+Required properties:
+ - compatible : should contain "mediatek,mt8173-xhci"
+ - reg : specifies physical base address and size of the registers,
+	should be only for xHCI IP registers
+ - interrupts : interrupt used by the host controller
+ - power-domains : a phandle to USB power domain node to control USB's
+	mtcmos
+ - vusb33-supply : regulator of USB avdd3.3v
+
+ - clocks : a list of phandle + clock-specifier pairs, one for each
+	entry in clock-names
+ - clock-names : must be
+	"sys_ck": for clock of xHCI MAC
+
+Optional properties:
+ - vbus-supply : reference to the VBUS regulator;
+ - usb3-lpm-capable : supports USB3.0 LPM
+
+Example:
+usb30: usb at 11270000 {
+	compatible = "mediatek,mt8173-xhci";
+	reg = <0 0x11270000 0 0x1000>;
+	interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
+	clocks = <&topckgen CLK_TOP_USB30_SEL>;
+	clock-names = "sys_ck";
+	vusb33-supply = <&mt6397_vusb_reg>;
+	usb3-lpm-capable;
+};
-- 
1.7.9.5



From fu.wei at linaro.org  Mon May 30 23:08:07 2016
From: fu.wei at linaro.org (fu.wei at linaro.org)
Date: Tue, 31 May 2016 14:08:07 +0800
Subject: [PATCH 0/3] watchdog,
 sbsa_gwdt: Update SBSA watchdog with the new infrastructure of
 watchdog.
Message-ID: <1464674890-10512-1-git-send-email-fu.wei@linaro.org>

From: Fu Wei <fu.wei at linaro.org>

This patchset:
    (1)Try to fix an issue about min and max timeout validity check:
    when max_hw_heartbeat_ms is defined, this check should be skipped.

    (2)Use max_hw_heartbeat_ms instead of max_timeout in SBSA watchdog.

    (3)Set WDOG_HW_RUNNING, when SBSA watchdog is already running before
    it's initialized.

Changelog:
v1: The first formal upstreaming version

RFC: https://lkml.org/lkml/2016/5/3/145

Pratyush Anand (3):
  watchdog: skip min and max timeout validity check when
    max_hw_heartbeat_ms is defined
  sbsa_gwdt: Use max_hw_heartbeat_ms instead of max_timeout
  sbsa_gwdt: Set WDOG_HW_RUNNING, when watchdog is already running.

 drivers/watchdog/sbsa_gwdt.c     | 6 ++++--
 drivers/watchdog/watchdog_core.c | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

-- 
2.5.5



From fu.wei at linaro.org  Mon May 30 23:08:08 2016
From: fu.wei at linaro.org (fu.wei at linaro.org)
Date: Tue, 31 May 2016 14:08:08 +0800
Subject: [PATCH 1/3] watchdog: skip min and max timeout validity check when
 max_hw_heartbeat_ms is defined
In-Reply-To: <1464674890-10512-1-git-send-email-fu.wei@linaro.org>
References: <1464674890-10512-1-git-send-email-fu.wei@linaro.org>
Message-ID: <1464674890-10512-2-git-send-email-fu.wei@linaro.org>

From: Pratyush Anand <panand at redhat.com>

When max_hw_heartbeat_ms has a none zero value, max_timeout is not used.
So it's value can be 0. In such case if a driver uses min_timeout
functionality, then check will always fail.

This patch fixes above issue.

Signed-off-by: Pratyush Anand <panand at redhat.com>
Signed-off-by: Fu Wei <fu.wei at linaro.org>
---
 drivers/watchdog/watchdog_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 7c3ba58..65e62d1 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -88,7 +88,7 @@ static void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
 	 * Check that we have valid min and max timeout values, if
 	 * not reset them both to 0 (=not used or unknown)
 	 */
-	if (wdd->min_timeout > wdd->max_timeout) {
+	if (!wdd->max_hw_heartbeat_ms && wdd->min_timeout > wdd->max_timeout) {
 		pr_info("Invalid min and max timeout values, resetting to 0!\n");
 		wdd->min_timeout = 0;
 		wdd->max_timeout = 0;
-- 
2.5.5



From fu.wei at linaro.org  Mon May 30 23:08:09 2016
From: fu.wei at linaro.org (fu.wei at linaro.org)
Date: Tue, 31 May 2016 14:08:09 +0800
Subject: [PATCH 2/3] sbsa_gwdt: Use max_hw_heartbeat_ms instead of max_timeout
In-Reply-To: <1464674890-10512-1-git-send-email-fu.wei@linaro.org>
References: <1464674890-10512-1-git-send-email-fu.wei@linaro.org>
Message-ID: <1464674890-10512-3-git-send-email-fu.wei@linaro.org>

From: Pratyush Anand <panand at redhat.com>

Using max_hw_heartbeat_ms instead of max_timeout gives the flexibility to
achieve higher user "timeout". Therefore, use this new infrastructure.

Signed-off-by: Pratyush Anand <panand at redhat.com>
Signed-off-by: Fu Wei <fu.wei at linaro.org>
---
 drivers/watchdog/sbsa_gwdt.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
index ad383f6..6af71e0 100644
--- a/drivers/watchdog/sbsa_gwdt.c
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -273,7 +273,7 @@ static int sbsa_gwdt_probe(struct platform_device *pdev)
 	wdd->info = &sbsa_gwdt_info;
 	wdd->ops = &sbsa_gwdt_ops;
 	wdd->min_timeout = 1;
-	wdd->max_timeout = U32_MAX / gwdt->clk;
+	wdd->max_hw_heartbeat_ms = U32_MAX / gwdt->clk * 1000;
 	wdd->timeout = DEFAULT_TIMEOUT;
 	watchdog_set_drvdata(wdd, gwdt);
 	watchdog_set_nowayout(wdd, nowayout);
@@ -310,7 +310,7 @@ static int sbsa_gwdt_probe(struct platform_device *pdev)
 	 * the timeout is (WOR * 2), so the maximum timeout should be doubled.
 	 */
 	if (!action)
-		wdd->max_timeout *= 2;
+		wdd->max_hw_heartbeat_ms *= 2;
 
 	watchdog_init_timeout(wdd, timeout, dev);
 	/*
-- 
2.5.5



From fu.wei at linaro.org  Mon May 30 23:08:10 2016
From: fu.wei at linaro.org (fu.wei at linaro.org)
Date: Tue, 31 May 2016 14:08:10 +0800
Subject: [PATCH 3/3] sbsa_gwdt: Set WDOG_HW_RUNNING,
 when watchdog is already running.
In-Reply-To: <1464674890-10512-1-git-send-email-fu.wei@linaro.org>
References: <1464674890-10512-1-git-send-email-fu.wei@linaro.org>
Message-ID: <1464674890-10512-4-git-send-email-fu.wei@linaro.org>

From: Pratyush Anand <panand at redhat.com>

This patch uses the new flag WDOG_HW_RUNNING in driver.
According to the definition of this flag, it should be set,
if watchdog is running after booting, before it's opened.

Signed-off-by: Pratyush Anand <panand at redhat.com>
Signed-off-by: Fu Wei <fu.wei at linaro.org>
---
 drivers/watchdog/sbsa_gwdt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
index 6af71e0..cc885f1 100644
--- a/drivers/watchdog/sbsa_gwdt.c
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -283,6 +283,8 @@ static int sbsa_gwdt_probe(struct platform_device *pdev)
 		dev_warn(dev, "System reset by WDT.\n");
 		wdd->bootstatus |= WDIOF_CARDRESET;
 	}
+	if (status & SBSA_GWDT_WCS_EN)
+		set_bit(WDOG_HW_RUNNING, &wdd->status);
 
 	if (action) {
 		irq = platform_get_irq(pdev, 0);
-- 
2.5.5



From robert.jarzmik at free.fr  Mon May 30 23:27:15 2016
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Tue, 31 May 2016 08:27:15 +0200
Subject: pxa_defconfig runtime failures due to 'ARM: pxa: activate pinctrl
 for device-tree machines'
In-Reply-To: <574A0AD1.9000304@roeck-us.net> (Guenter Roeck's message of "Sat, 
 28 May 2016 14:17:05 -0700")
References: <20160527202715.GA4841@roeck-us.net>
 <87a8jah9ok.fsf@belgarion.home> <574A0AD1.9000304@roeck-us.net>
Message-ID: <87vb1ueo8s.fsf@belgarion.home>

Guenter Roeck <linux at roeck-us.net> writes:

> On 05/28/2016 01:24 AM, Robert Jarzmik wrote:
>> Guenter Roeck <linux at roeck-us.net> writes:
>>
>>> Hi,
>> I'd rather say that pxa_defconfig doesn't work anymore on any legacy system.
>> Its first purpose was to ensure compilation coverage of all legacy pxa systems.
>> Its second one was to have a single kernel bootable on all legacy pxa systems.
>>
>> Therefore, would you tell me if the patch in [1] fixes your issue ?
>>
>
> Yes, it does. It is actually the workaround I deployed for my test builds,
> since I thought that the change was on purpose.

Good. Can I take that as a Tested-by ?

Cheers.

-- 
Robert


From yamada.masahiro at socionext.com  Mon May 30 23:30:10 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 15:30:10 +0900
Subject: [PATCH] pinctrl: uniphier: fix .pin_dbg_show() callback
Message-ID: <1464676210-16508-1-git-send-email-yamada.masahiro@socionext.com>

Without this, reading the "pins" in the debugfs causes kernel BUG.

Fixes: 6e9088920258 ("pinctrl: UniPhier: add UniPhier pinctrl core support")
Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
---

Hi Linus,
I hope this will be applied as a bug-fix patch for Linux 4.7 .

 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 9674009..5d08de0 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -73,6 +73,12 @@ static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
 	case UNIPHIER_PIN_PULL_DOWN:
 		pull_dir = "DOWN";
 		break;
+	case UNIPHIER_PIN_PULL_UP_FIXED:
+		pull_dir = "UP(FIXED)";
+		break;
+	case UNIPHIER_PIN_PULL_DOWN_FIXED:
+		pull_dir = "DOWN(FIXED)";
+		break;
 	case UNIPHIER_PIN_PULL_NONE:
 		pull_dir = "NONE";
 		break;
-- 
1.9.1



From marek.belisko at gmail.com  Mon May 30 23:48:44 2016
From: marek.belisko at gmail.com (Belisko Marek)
Date: Tue, 31 May 2016 08:48:44 +0200
Subject: [PATCH 0/5] ARM: dts: omap3-gta04: Various updates
In-Reply-To: <1463514531-7235-1-git-send-email-marek@goldelico.com>
References: <1463514531-7235-1-git-send-email-marek@goldelico.com>
Message-ID: <CAAfyv37NE1eogrSRCuRY-9V30FtD3u7oeFWMJk=xNX1hFJ9O-w@mail.gmail.com>

Ping? Any objections? Thanks.

On Tue, May 17, 2016 at 9:48 PM, Marek Belisko <marek at goldelico.com> wrote:
> Add various improvements for gta04 device (wifi, backlight, irq lines for sensors)
>
> H. Nikolaus Schaller (4):
>   ARM: dts: omap3-gta04: Define and use bma180 irq pin
>   ARM: dta: omap3-gta04: Define and use itg3200  irq pin
>   ARM: dta: omap3-gta04: Define and use hmc5843 irq pin
>   ARM: dts: omap3-gat04: Fix wifi handling
>
> Marek Belisko (1):
>   ARM: dts: omap3-gta04: Add backlight support
>
>  arch/arm/boot/dts/omap3-gta04.dtsi | 60 ++++++++++++++++++++++++++++++++++++--
>  1 file changed, 57 insertions(+), 3 deletions(-)
>
> --
> 2.5.0
>

Marek

-- 
as simple and primitive as possible
-------------------------------------------------
Marek Belisko - OPEN-NANDRA
Freelance Developer

Ruska Nova Ves 219 | Presov, 08005 Slovak Republic
Tel: +421 915 052 184
skype: marekwhite
twitter: #opennandra
web: http://open-nandra.com


From songjun.wu at atmel.com  Mon May 30 23:58:21 2016
From: songjun.wu at atmel.com (Songjun Wu)
Date: Tue, 31 May 2016 14:58:21 +0800
Subject: [PATCH v3 0/2] [media] atmel-isc: add driver for Atmel ISC
Message-ID: <1464677903-28412-1-git-send-email-songjun.wu@atmel.com>

The Image Sensor Controller driver includes two parts.
1) Driver code to implement the ISC function.
2) Device tree binding documentation, it describes how
   to add the ISC in device tree.

Changes in v3:
- Add pm runtime feature.
- Modify the isc clock code since the dt is changed.
- Remove the 'atmel,sensor-preferred'.
- Modify the isc clock node according to the Rob's remarks.

Changes in v2:
- Add "depends on COMMON_CLK" and "VIDEO_V4L2_SUBDEV_API"
  in Kconfig file.
- Correct typos and coding style according to Laurent's remarks.
- Delete the loop while in 'isc_clk_enable' function.
- Replace 'hsync_active', 'vsync_active' and 'pclk_sample'
  with 'pfe_cfg0' in struct isc_subdev_entity.
- Add the code to support VIDIOC_CREATE_BUFS in
  'isc_queue_setup' function.
- Invoke isc_config to configure register in
  'isc_start_streaming' function.
- Add the struct completion 'comp' to synchronize with
  the frame end interrupt in 'isc_stop_streaming' function.
- Check the return value of the clk_prepare_enable
  in 'isc_open' function.
- Set the default format in 'isc_open' function.
- Add an exit condition in the loop while in 'isc_config'.
- Delete the hardware setup operation in 'isc_set_format'.
- Refuse format modification during streaming
  in 'isc_s_fmt_vid_cap' function.
- Invoke v4l2_subdev_alloc_pad_config to allocate and
  initialize the pad config in 'isc_async_complete' function.
- Remove the '.owner  = THIS_MODULE,' in atmel_isc_driver.
- Replace the module_platform_driver_probe() with
  module_platform_driver().
- Remove the unit address of the endpoint.
- Add the unit address to the clock node.
- Avoid using underscores in node names.
- Drop the "0x" in the unit address of the i2c node.
- Modify the description of 'atmel,sensor-preferred'.
- Add the description for the ISC internal clock.

Songjun Wu (2):
  [media] atmel-isc: add the Image Sensor Controller code
  [media] atmel-isc: DT binding for Image Sensor Controller driver

 .../devicetree/bindings/media/atmel-isc.txt        |   88 ++
 drivers/media/platform/Kconfig                     |    1 +
 drivers/media/platform/Makefile                    |    2 +
 drivers/media/platform/atmel/Kconfig               |    9 +
 drivers/media/platform/atmel/Makefile              |    1 +
 drivers/media/platform/atmel/atmel-isc-regs.h      |  276 ++++
 drivers/media/platform/atmel/atmel-isc.c           | 1610 ++++++++++++++++++++
 7 files changed, 1987 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/atmel-isc.txt
 create mode 100644 drivers/media/platform/atmel/Kconfig
 create mode 100644 drivers/media/platform/atmel/Makefile
 create mode 100644 drivers/media/platform/atmel/atmel-isc-regs.h
 create mode 100644 drivers/media/platform/atmel/atmel-isc.c

-- 
2.7.4



From songjun.wu at atmel.com  Mon May 30 23:58:22 2016
From: songjun.wu at atmel.com (Songjun Wu)
Date: Tue, 31 May 2016 14:58:22 +0800
Subject: [PATCH v3 1/2] [media] atmel-isc: add the Image Sensor Controller code
In-Reply-To: <1464677903-28412-1-git-send-email-songjun.wu@atmel.com>
References: <1464677903-28412-1-git-send-email-songjun.wu@atmel.com>
Message-ID: <1464677903-28412-2-git-send-email-songjun.wu@atmel.com>

Add driver for the Image Sensor Controller. It manages
incoming data from a parallel based CMOS/CCD sensor.
It has an internal image processor, also integrates a
triple channel direct memory access controller master
interface.

Signed-off-by: Songjun Wu <songjun.wu at atmel.com>
---

Changes in v3:
- Add pm runtime feature.
- Modify the isc clock code since the dt is changed.

Changes in v2:
- Add "depends on COMMON_CLK" and "VIDEO_V4L2_SUBDEV_API"
  in Kconfig file.
- Correct typos and coding style according to Laurent's remarks.
- Delete the loop while in 'isc_clk_enable' function.
- Replace 'hsync_active', 'vsync_active' and 'pclk_sample'
  with 'pfe_cfg0' in struct isc_subdev_entity.
- Add the code to support VIDIOC_CREATE_BUFS in
  'isc_queue_setup' function.
- Invoke isc_config to configure register in
  'isc_start_streaming' function.
- Add the struct completion 'comp' to synchronize with
  the frame end interrupt in 'isc_stop_streaming' function.
- Check the return value of the clk_prepare_enable
  in 'isc_open' function.
- Set the default format in 'isc_open' function.
- Add an exit condition in the loop while in 'isc_config'.
- Delete the hardware setup operation in 'isc_set_format'.
- Refuse format modification during streaming
  in 'isc_s_fmt_vid_cap' function.
- Invoke v4l2_subdev_alloc_pad_config to allocate and
  initialize the pad config in 'isc_async_complete' function.
- Remove the '.owner  = THIS_MODULE,' in atmel_isc_driver.
- Replace the module_platform_driver_probe() with
  module_platform_driver().

 drivers/media/platform/Kconfig                |    1 +
 drivers/media/platform/Makefile               |    2 +
 drivers/media/platform/atmel/Kconfig          |    9 +
 drivers/media/platform/atmel/Makefile         |    1 +
 drivers/media/platform/atmel/atmel-isc-regs.h |  276 +++++
 drivers/media/platform/atmel/atmel-isc.c      | 1610 +++++++++++++++++++++++++
 6 files changed, 1899 insertions(+)
 create mode 100644 drivers/media/platform/atmel/Kconfig
 create mode 100644 drivers/media/platform/atmel/Makefile
 create mode 100644 drivers/media/platform/atmel/atmel-isc-regs.h
 create mode 100644 drivers/media/platform/atmel/atmel-isc.c

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 84e041c..91d7aea 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -110,6 +110,7 @@ source "drivers/media/platform/exynos4-is/Kconfig"
 source "drivers/media/platform/s5p-tv/Kconfig"
 source "drivers/media/platform/am437x/Kconfig"
 source "drivers/media/platform/xilinx/Kconfig"
+source "drivers/media/platform/atmel/Kconfig"
 
 config VIDEO_TI_CAL
 	tristate "TI CAL (Camera Adaptation Layer) driver"
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index bbb7bd1..ad8f471 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -55,4 +55,6 @@ obj-$(CONFIG_VIDEO_AM437X_VPFE)		+= am437x/
 
 obj-$(CONFIG_VIDEO_XILINX)		+= xilinx/
 
+obj-$(CONFIG_VIDEO_ATMEL_ISC)		+= atmel/
+
 ccflags-y += -I$(srctree)/drivers/media/i2c
diff --git a/drivers/media/platform/atmel/Kconfig b/drivers/media/platform/atmel/Kconfig
new file mode 100644
index 0000000..867dca2
--- /dev/null
+++ b/drivers/media/platform/atmel/Kconfig
@@ -0,0 +1,9 @@
+config VIDEO_ATMEL_ISC
+	tristate "ATMEL Image Sensor Controller (ISC) support"
+	depends on VIDEO_V4L2 && COMMON_CLK && VIDEO_V4L2_SUBDEV_API && HAS_DMA
+	depends on ARCH_AT91 || COMPILE_TEST
+	select VIDEOBUF2_DMA_CONTIG
+	select REGMAP_MMIO
+	help
+	   This module makes the ATMEL Image Sensor Controller available
+	   as a v4l2 device.
\ No newline at end of file
diff --git a/drivers/media/platform/atmel/Makefile b/drivers/media/platform/atmel/Makefile
new file mode 100644
index 0000000..9d7c999
--- /dev/null
+++ b/drivers/media/platform/atmel/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_VIDEO_ATMEL_ISC) += atmel-isc.o
diff --git a/drivers/media/platform/atmel/atmel-isc-regs.h b/drivers/media/platform/atmel/atmel-isc-regs.h
new file mode 100644
index 0000000..dda9396
--- /dev/null
+++ b/drivers/media/platform/atmel/atmel-isc-regs.h
@@ -0,0 +1,276 @@
+#ifndef __ATMEL_ISC_REGS_H
+#define __ATMEL_ISC_REGS_H
+
+#include <linux/bitops.h>
+
+/* ISC Control Enable Register 0 */
+#define ISC_CTRLEN      0x00000000
+
+#define ISC_CTRLEN_CAPTURE              BIT(0)
+#define ISC_CTRLEN_CAPTURE_MASK         BIT(0)
+
+#define ISC_CTRLEN_UPPRO                BIT(1)
+#define ISC_CTRLEN_UPPRO_MASK           BIT(1)
+
+#define ISC_CTRLEN_HISREQ               BIT(2)
+#define ISC_CTRLEN_HISREQ_MASK          BIT(2)
+
+#define ISC_CTRLEN_HISCLR               BIT(3)
+#define ISC_CTRLEN_HISCLR_MASK          BIT(3)
+
+/* ISC Control Disable Register 0 */
+#define ISC_CTRLDIS     0x00000004
+
+#define ISC_CTRLDIS_DISABLE             BIT(0)
+#define ISC_CTRLDIS_DISABLE_MASK        BIT(0)
+
+#define ISC_CTRLDIS_SWRST               BIT(8)
+#define ISC_CTRLDIS_SWRST_MASK          BIT(8)
+
+/* ISC Control Status Register 0 */
+#define ISC_CTRLSR      0x00000008
+
+#define ISC_CTRLSR_CAPTURE      BIT(0)
+#define ISC_CTRLSR_UPPRO        BIT(1)
+#define ISC_CTRLSR_HISREQ       BIT(2)
+#define ISC_CTRLSR_FIELD        BIT(4)
+#define ISC_CTRLSR_SIP          BIT(31)
+
+/* ISC Parallel Front End Configuration 0 Register */
+#define ISC_PFE_CFG0    0x0000000c
+
+#define ISC_PFE_CFG0_HPOL_LOW   BIT(0)
+#define ISC_PFE_CFG0_HPOL_HIGH  0x0
+#define ISC_PFE_CFG0_HPOL_MASK  BIT(0)
+
+#define ISC_PFE_CFG0_VPOL_LOW   BIT(1)
+#define ISC_PFE_CFG0_VPOL_HIGH  0x0
+#define ISC_PFE_CFG0_VPOL_MASK  BIT(1)
+
+#define ISC_PFE_CFG0_PPOL_LOW   BIT(2)
+#define ISC_PFE_CFG0_PPOL_HIGH  0x0
+#define ISC_PFE_CFG0_PPOL_MASK  BIT(2)
+
+#define ISC_PFE_CFG0_MODE_PROGRESSIVE   0x0
+#define ISC_PFE_CFG0_MODE_MASK          GENMASK(6, 4)
+
+#define ISC_PFE_CFG0_BPS_EIGHT  (0x4 << 28)
+#define ISC_PFG_CFG0_BPS_NINE   (0x3 << 28)
+#define ISC_PFG_CFG0_BPS_TEN    (0x2 << 28)
+#define ISC_PFG_CFG0_BPS_ELEVEN (0x1 << 28)
+#define ISC_PFG_CFG0_BPS_TWELVE 0x0
+#define ISC_PFE_CFG0_BPS_MASK   GENMASK(30, 28)
+
+/* ISC Clock Enable Register */
+#define ISC_CLKEN               0x00000018
+#define ISC_CLKEN_EN            0x1
+#define ISC_CLKEN_EN_SHIFT(n)   (n)
+#define ISC_CLKEN_EN_MASK(n)    BIT(n)
+
+/* ISC Clock Disable Register */
+#define ISC_CLKDIS              0x0000001c
+#define ISC_CLKDIS_DIS          0x1
+#define ISC_CLKDIS_DIS_SHIFT(n) (n)
+#define ISC_CLKDIS_DIS_MASK(n)  BIT(n)
+
+/* ISC Clock Status Register */
+#define ISC_CLKSR               0x00000020
+#define ISC_CLKSR_CLK_MASK(n)   BIT(n)
+#define ISC_CLKSR_SIP_PROGRESS  BIT(31)
+
+/* ISC Clock Configuration Register */
+#define ISC_CLKCFG              0x00000024
+#define ISC_CLKCFG_DIV_SHIFT(n) ((n)*16)
+#define ISC_CLKCFG_DIV_MASK(n)  GENMASK(((n)*16 + 7), (n)*16)
+#define ISC_CLKCFG_SEL_SHIFT(n) ((n)*16 + 8)
+#define ISC_CLKCFG_SEL_MASK(n)  GENMASK(((n)*17 + 8), ((n)*16 + 8))
+
+/* ISC Interrupt Enable Register */
+#define ISC_INTEN       0x00000028
+
+#define ISC_INTEN_DDONE         BIT(8)
+#define ISC_INTEN_DDONE_MASK    BIT(8)
+
+/* ISC Interrupt Disable Register */
+#define ISC_INTDIS      0x0000002c
+
+#define ISC_INTDIS_DDONE        BIT(8)
+#define ISC_INTDIS_DDONE_MASK   BIT(8)
+
+/* ISC Interrupt Mask Register */
+#define ISC_INTMASK     0x00000030
+
+/* ISC Interrupt Status Register */
+#define ISC_INTSR       0x00000034
+
+#define ISC_INTSR_DDONE         BIT(8)
+
+/* ISC White Balance Control Register */
+#define ISC_WB_CTRL     0x00000058
+
+#define ISC_WB_CTRL_EN          BIT(0)
+#define ISC_WB_CTRL_DIS         0x0
+#define ISC_WB_CTRL_MASK        BIT(0)
+
+/* ISC White Balance Configuration Register */
+#define ISC_WB_CFG      0x0000005c
+
+#define ISC_WB_CFG_BAYCFG_GRGR  0x0
+#define ISC_WB_CFG_BAYCFG_RGRG  0x1
+#define ISC_WB_CFG_BAYCFG_GBGB  0x2
+#define ISC_WB_CFG_BAYCFG_BGBG  0x3
+#define ISC_WB_CFG_BAYCFG_MASK  GENMASK(1, 0)
+
+/* ISC Color Filter Array Control Register */
+#define ISC_CFA_CTRL    0x00000070
+
+#define ISC_CFA_CTRL_EN         BIT(0)
+#define ISC_CFA_CTRL_DIS        0x0
+#define ISC_CFA_CTRL_MASK       BIT(0)
+
+/* ISC Color Filter Array Configuration Register */
+#define ISC_CFA_CFG     0x00000074
+
+#define ISC_CFA_CFG_BAY_GRGR    0x0
+#define ISC_CFA_CFG_BAY_RGRG    0x1
+#define ISC_CFA_CFG_BAY_GBGB    0x2
+#define ISC_CFA_CFG_BAY_BGBG    0x3
+#define ISC_CFA_CFG_BAY_MASK    GENMASK(1, 0)
+
+/* ISC Color Correction Control Register */
+#define ISC_CC_CTRL     0x00000078
+
+#define ISC_CC_CTRL_EN          BIT(0)
+#define ISC_CC_CTRL_DIS         0x0
+#define ISC_CC_CTRL_MASK        BIT(0)
+
+/* ISC Gamma Correction Control Register */
+#define ISC_GAM_CTRL    0x00000094
+
+#define ISC_GAM_CTRL_EN         BIT(0)
+#define ISC_GAM_CTRL_DIS        0x0
+#define ISC_GAM_CTRL_MASK       BIT(0)
+
+#define ISC_GAM_CTRL_B_EN       BIT(1)
+#define ISC_GAM_CTRL_B_DIS      0x0
+#define ISC_GAM_CTRL_B_MASK     BIT(1)
+
+#define ISC_GAM_CTRL_G_EN       BIT(2)
+#define ISC_GAM_CTRL_G_DIS      0x0
+#define ISC_GAM_CTRL_G_MASK     BIT(2)
+
+#define ISC_GAM_CTRL_R_EN       BIT(3)
+#define ISC_GAM_CTRL_R_DIS      0x0
+#define ISC_GAM_CTRL_R_MASK     BIT(3)
+
+#define ISC_GAM_CTRL_ALL_CHAN_MASK (ISC_GAM_CTRL_B_MASK | \
+				    ISC_GAM_CTRL_G_MASK | \
+				    ISC_GAM_CTRL_R_MASK)
+
+/* Color Space Conversion Control Register */
+#define ISC_CSC_CTRL    0x00000398
+
+#define ISC_CSC_CTRL_EN         BIT(0)
+#define ISC_CSC_CTRL_DIS        0x0
+#define ISC_CSC_CTRL_MASK       BIT(0)
+
+/* Contrast And Brightness Control Register */
+#define ISC_CBC_CTRL    0x000003b4
+
+#define ISC_CBC_CTRL_EN         BIT(0)
+#define ISC_CBC_CTRL_DIS        0x0
+#define ISC_CBC_CTRL_MASK       BIT(0)
+
+/* Subsampling 4:4:4 to 4:2:2 Control Register */
+#define ISC_SUB422_CTRL 0x000003c4
+
+#define ISC_SUB422_CTRL_EN      BIT(0)
+#define ISC_SUB422_CTRL_DIS     0x0
+#define ISC_SUB422_CTRL_MASK    BIT(0)
+
+/* Subsampling 4:2:2 to 4:2:0 Control Register */
+#define ISC_SUB420_CTRL 0x000003cc
+
+#define ISC_SUB420_CTRL_EN      BIT(0)
+#define ISC_SUB420_CTRL_DIS     0x0
+#define ISC_SUB420_CTRL_MASK    BIT(0)
+
+#define ISC_SUB420_CTRL_FILTER_PROG     0x0
+#define ISC_SUB420_CTRL_FILTER_INTER    BIT(4)
+#define ISC_SUB420_CTRL_FILTER_MASK     BIT(4)
+
+/* Rounding, Limiting and Packing Configuration Register */
+#define ISC_RLP_CFG     0x000003d0
+
+#define ISC_RLP_CFG_MODE_DAT8           0x0
+#define ISC_RLP_CFG_MODE_DAT9           0x1
+#define ISC_RLP_CFG_MODE_DAT10          0x2
+#define ISC_RLP_CFG_MODE_DAT11          0x3
+#define ISC_RLP_CFG_MODE_DAT12          0x4
+#define ISC_RLP_CFG_MODE_DATY8          0x5
+#define ISC_RLP_CFG_MODE_DATY10         0x6
+#define ISC_RLP_CFG_MODE_ARGB444        0x7
+#define ISC_RLP_CFG_MODE_ARGB555        0x8
+#define ISC_RLP_CFG_MODE_RGB565         0x9
+#define ISC_RLP_CFG_MODE_ARGB32         0xa
+#define ISC_RLP_CFG_MODE_YYCC           0xb
+#define ISC_RLP_CFG_MODE_YYCC_LIMITED   0xc
+#define ISC_RLP_CFG_MODE_MASK           GENMASK(3, 0)
+
+/* DMA Configuration Register */
+#define ISC_DCFG        0x000003e0
+#define ISC_DCFG_IMODE_PACKED8          0x0
+#define ISC_DCFG_IMODE_PACKED16         0x1
+#define ISC_DCFG_IMODE_PACKED32         0x2
+#define ISC_DCFG_IMODE_YC422SP          0x3
+#define ISC_DCFG_IMODE_YC422P           0x4
+#define ISC_DCFG_IMODE_YC420SP          0x5
+#define ISC_DCFG_IMODE_YC420P           0x6
+#define ISC_DCFG_IMODE_MASK             GENMASK(2, 0)
+
+#define ISC_DCFG_YMBSIZE_SINGLE         0x0
+#define ISC_DCFG_YMBSIZE_BEATS4         (0x1 << 4)
+#define ISC_DCFG_YMBSIZE_BEATS8         (0x2 << 4)
+#define ISC_DCFG_YMBSIZE_BEATS16        (0x3 << 4)
+#define ISC_DCFG_YMBSIZE_MASK           GENMASK(5, 4)
+
+#define ISC_DCFG_CMBSIZE_SINGLE         0x0
+#define ISC_DCFG_CMBSIZE_BEATS4         (0x1 << 8)
+#define ISC_DCFG_CMBSIZE_BEATS8         (0x2 << 8)
+#define ISC_DCFG_CMBSIZE_BEATS16        (0x3 << 8)
+#define ISC_DCFG_CMBSIZE_MASK           GENMASK(9, 8)
+
+/* DMA Control Register */
+#define ISC_DCTRL       0x000003e4
+
+#define ISC_DCTRL_DE_EN         BIT(0)
+#define ISC_DCTRL_DE_DIS        0x0
+#define ISC_DCTRL_DE_MASK       BIT(0)
+
+#define ISC_DCTRL_DVIEW_PACKED          0x0
+#define ISC_DCTRL_DVIEW_SEMIPLANAR      (0x1 << 1)
+#define ISC_DCTRL_DVIEW_PLANAR          (0x2 << 1)
+#define ISC_DCTRL_DVIEW_MASK            GENMASK(2, 1)
+
+#define ISC_DCTRL_IE_IS         0x0
+#define ISC_DCTRL_IE_NOT        BIT(4)
+#define ISC_DCTRL_IE_MASK       BIT(4)
+
+#define ISC_DCTRL_WB_EN         BIT(5)
+#define ISC_DCTRL_WB_DIS        0x0
+#define ISC_DCTRL_WB_MASK       BIT(5)
+
+#define ISC_DCTRL_DESC_IS_DONE  BIT(7)
+#define ISC_DCTRL_DESC_NOT_DONE 0x0
+#define ISC_DCTRL_DESC_MASK     BIT(7)
+
+/* DMA Descriptor Address Register */
+#define ISC_DNDA        0x000003e8
+
+/* DMA Address 0 Register */
+#define ISC_DAD0        0x000003ec
+
+/* DMA Stride 0 Register */
+#define ISC_DST0        0x000003f0
+
+#endif
diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c
new file mode 100644
index 0000000..148b9e8
--- /dev/null
+++ b/drivers/media/platform/atmel/atmel-isc.c
@@ -0,0 +1,1610 @@
+/*
+ * Atmel Image Sensor Controller (ISC) driver
+ *
+ * Copyright (C) 2016 Atmel
+ *
+ * Author: Songjun Wu <songjun.wu at atmel.com>
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * Sensor-->PFE-->WB-->CFA-->CC-->GAM-->CSC-->CBC-->SUB-->RLP-->DMA
+ *
+ * ISC video pipeline integrates the following submodules:
+ * PFE: Parallel Front End to sample the camera sensor input stream
+ *  WB: Programmable white balance in the Bayer domain
+ * CFA: Color filter array interpolation module
+ *  CC: Programmable color correction
+ * GAM: Gamma correction
+ * CSC: Programmable color space conversion
+ * CBC: Contrast and Brightness control
+ * SUB: This module performs YCbCr444 to YCbCr420 chrominance subsampling
+ * RLP: This module performs rounding, range limiting
+ *      and packing of the incoming data
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-image-sizes.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-of.h>
+#include <media/v4l2-subdev.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "atmel-isc-regs.h"
+
+#define ATMEL_ISC_NAME		"atmel_isc"
+
+#define ISC_MAX_SUPPORT_WIDTH   2592
+#define ISC_MAX_SUPPORT_HEIGHT  1944
+
+#define ISC_CLK_MAX_DIV		255
+
+struct isc_clk_pdata {
+	u8 clk_id;
+	u8 max_num_parents;
+};
+
+struct isc_clk {
+	struct clk_hw   hw;
+	struct clk      *clk;
+	struct regmap   *regmap;
+	spinlock_t      *lock;
+	u8		id;
+	u8		parent_id;
+	u32		div;
+
+	struct isc_device *isc;
+};
+
+#define to_isc_clk(hw) container_of(hw, struct isc_clk, hw)
+
+struct isc_buffer {
+	struct vb2_v4l2_buffer  vb;
+	struct list_head	list;
+};
+
+struct isc_subdev_entity {
+	struct v4l2_subdev		*sd;
+	struct v4l2_async_subdev	*asd;
+	struct v4l2_async_notifier      notifier;
+	struct v4l2_subdev_pad_config	*config;
+
+	u32 pfe_cfg0;
+
+	struct list_head list;
+};
+
+/*
+ * struct isc_format - ISC media bus format information
+ * @fourcc:		Fourcc code for this format
+ * @isc_mbus_code:      V4L2 media bus format code if ISC is preferred
+ * @sd_mbus_code:       V4L2 media bus format code if subdev is preferred
+ * @bpp:		Bytes per pixel (when stored in memory)
+ * @reg_sd_bps:		reg value for bits per sample if subdev is preferred
+ *			(when transferred over a bus)
+ * @reg_isc_bps:	reg value for bits per sample if ISC is preferred
+ *			(when transferred over a bus)
+ * @pipeline:		pipeline switch if ISC is preferred
+ * @isc_support:	ISC can convert raw format to this format
+ * @sd_support:		Subdev supports this format
+ */
+struct isc_format {
+	u32	fourcc;
+	u32	isc_mbus_code;
+	u32	sd_mbus_code;
+
+	u8	bpp;
+
+	u32	reg_sd_bps;
+	u32	reg_isc_bps;
+
+	u32	reg_wb_cfg;
+	u32	reg_cfa_cfg;
+	u32	reg_rlp_mode;
+	u32	reg_dcfg_imode;
+	u32	reg_dctrl_dview;
+
+	u32	pipeline;
+
+	bool	isc_support;
+	bool	sd_support;
+};
+
+struct isc_device {
+	struct regmap		*regmap;
+	struct clk		*hclock;
+	struct clk		*ispck;
+	struct isc_clk		isc_clks[2];
+	spinlock_t		clk_lock;
+
+	struct device		*dev;
+	struct v4l2_device	v4l2_dev;
+	struct video_device	video_dev;
+
+	struct vb2_queue	vb2_vidq;
+	struct vb2_alloc_ctx	*alloc_ctx;
+
+	spinlock_t		dma_queue_lock;
+	struct list_head	dma_queue;
+	struct isc_buffer	*cur_frm;
+	unsigned int		sequence;
+	bool			stop;
+	struct completion	comp;
+
+	struct v4l2_format	fmt;
+
+	struct isc_format	**user_formats;
+	unsigned int		num_user_formats;
+	const struct isc_format	*current_fmt;
+
+	struct mutex		lock;
+
+	struct isc_subdev_entity	*current_subdev;
+	struct list_head		subdev_entities;
+};
+
+struct reg_mask {
+	u32 reg;
+	u32 mask;
+};
+
+static unsigned int sensor_preferred = 1;
+module_param(sensor_preferred, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(sensor_preferred,
+"Sensor is preferred to output the specified format (1-on 0-off) default 1");
+
+/* WB-->CFA-->CC-->GAM-->CSC-->CBC-->SUB422-->SUB420 */
+const struct reg_mask pipeline_regs[] = {
+	{ ISC_WB_CTRL,  ISC_WB_CTRL_MASK },
+	{ ISC_CFA_CTRL, ISC_CFA_CTRL_MASK },
+	{ ISC_CC_CTRL,  ISC_CC_CTRL_MASK },
+	{ ISC_GAM_CTRL, ISC_GAM_CTRL_MASK | ISC_GAM_CTRL_ALL_CHAN_MASK },
+	{ ISC_CSC_CTRL, ISC_CSC_CTRL_MASK },
+	{ ISC_CBC_CTRL, ISC_CBC_CTRL_MASK },
+	{ ISC_SUB422_CTRL, ISC_SUB422_CTRL_MASK },
+	{ ISC_SUB420_CTRL, ISC_SUB420_CTRL_MASK }
+};
+
+#define RAW_FMT_INDEX_START	0
+#define RAW_FMT_INDEX_END	11
+#define ISC_FMT_INDEX_START	12
+#define ISC_FMT_INDEX_END	12
+
+/*
+ * index(0~11):  raw formats.
+ * index(12~12): the formats which can be converted from raw format by ISC.
+ * index():      the formats which can only be provided by subdev.
+ */
+static struct isc_format isc_formats[] = {
+{V4L2_PIX_FMT_SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8,
+1, ISC_PFE_CFG0_BPS_EIGHT, ISC_PFE_CFG0_BPS_EIGHT, ISC_WB_CFG_BAYCFG_BGBG,
+ISC_CFA_CFG_BAY_BGBG, ISC_RLP_CFG_MODE_DAT8, ISC_DCFG_IMODE_PACKED8,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8,
+1, ISC_PFE_CFG0_BPS_EIGHT, ISC_PFE_CFG0_BPS_EIGHT, ISC_WB_CFG_BAYCFG_GBGB,
+ISC_CFA_CFG_BAY_GBGB, ISC_RLP_CFG_MODE_DAT8, ISC_DCFG_IMODE_PACKED8,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8,
+1, ISC_PFE_CFG0_BPS_EIGHT, ISC_PFE_CFG0_BPS_EIGHT, ISC_WB_CFG_BAYCFG_GRGR,
+ISC_CFA_CFG_BAY_GRGR, ISC_RLP_CFG_MODE_DAT8, ISC_DCFG_IMODE_PACKED8,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8,
+1, ISC_PFE_CFG0_BPS_EIGHT, ISC_PFE_CFG0_BPS_EIGHT, ISC_WB_CFG_BAYCFG_RGRG,
+ISC_CFA_CFG_BAY_RGRG, ISC_RLP_CFG_MODE_DAT8, ISC_DCFG_IMODE_PACKED8,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+
+{V4L2_PIX_FMT_SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10,
+2, ISC_PFG_CFG0_BPS_TEN, ISC_PFG_CFG0_BPS_TEN, ISC_WB_CFG_BAYCFG_BGBG,
+ISC_CFA_CFG_BAY_BGBG, ISC_RLP_CFG_MODE_DAT10, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10,
+2, ISC_PFG_CFG0_BPS_TEN, ISC_PFG_CFG0_BPS_TEN, ISC_WB_CFG_BAYCFG_GBGB,
+ISC_CFA_CFG_BAY_GBGB, ISC_RLP_CFG_MODE_DAT10, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SGRBG10, MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10,
+2, ISC_PFG_CFG0_BPS_TEN, ISC_PFG_CFG0_BPS_TEN, ISC_WB_CFG_BAYCFG_GRGR,
+ISC_CFA_CFG_BAY_GRGR, ISC_RLP_CFG_MODE_DAT10, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SRGGB10, MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10,
+2, ISC_PFG_CFG0_BPS_TEN, ISC_PFG_CFG0_BPS_TEN, ISC_WB_CFG_BAYCFG_RGRG,
+ISC_CFA_CFG_BAY_RGRG, ISC_RLP_CFG_MODE_DAT10, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+
+{V4L2_PIX_FMT_SBGGR12, MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR12_1X12,
+2, ISC_PFG_CFG0_BPS_TWELVE, ISC_PFG_CFG0_BPS_TWELVE, ISC_WB_CFG_BAYCFG_BGBG,
+ISC_CFA_CFG_BAY_BGBG, ISC_RLP_CFG_MODE_DAT12, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SGBRG12, MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG12_1X12,
+2, ISC_PFG_CFG0_BPS_TWELVE, ISC_PFG_CFG0_BPS_TWELVE, ISC_WB_CFG_BAYCFG_GBGB,
+ISC_CFA_CFG_BAY_GBGB, ISC_RLP_CFG_MODE_DAT12, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SGRBG12, MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG12_1X12,
+2, ISC_PFG_CFG0_BPS_TWELVE, ISC_PFG_CFG0_BPS_TWELVE, ISC_WB_CFG_BAYCFG_GRGR,
+ISC_CFA_CFG_BAY_GRGR, ISC_RLP_CFG_MODE_DAT12, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+{V4L2_PIX_FMT_SRGGB12, MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB12_1X12,
+2, ISC_PFG_CFG0_BPS_TWELVE, ISC_PFG_CFG0_BPS_TWELVE, ISC_WB_CFG_BAYCFG_RGRG,
+ISC_CFA_CFG_BAY_RGRG, ISC_RLP_CFG_MODE_DAT12, ISC_DCFG_IMODE_PACKED16,
+ISC_DCTRL_DVIEW_PACKED, 0x0, false, false},
+
+{V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_YUYV8_2X8,
+2, ISC_PFE_CFG0_BPS_EIGHT, ISC_PFE_CFG0_BPS_EIGHT, ISC_WB_CFG_BAYCFG_BGBG,
+ISC_CFA_CFG_BAY_BGBG, ISC_RLP_CFG_MODE_DAT8, ISC_DCFG_IMODE_PACKED8,
+ISC_DCTRL_DVIEW_PACKED, 0x7f, false, false},
+};
+
+static int isc_clk_enable(struct clk_hw *hw)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+	u32 id = isc_clk->id;
+	struct regmap *regmap = isc_clk->regmap;
+	unsigned long flags;
+
+	dev_dbg(isc_clk->isc->dev, "ISC CLK: %s, div = %d, parent id = %d\n",
+		__func__, isc_clk->div, isc_clk->parent_id);
+
+	spin_lock_irqsave(isc_clk->lock, flags);
+
+	regmap_update_bits(regmap, ISC_CLKCFG,
+			   ISC_CLKCFG_DIV_MASK(id) | ISC_CLKCFG_SEL_MASK(id),
+			   (isc_clk->div << ISC_CLKCFG_DIV_SHIFT(id)) |
+			   (isc_clk->parent_id << ISC_CLKCFG_SEL_SHIFT(id)));
+
+	regmap_update_bits(regmap, ISC_CLKEN,
+			   ISC_CLKEN_EN_MASK(id),
+			   ISC_CLKEN_EN << ISC_CLKEN_EN_SHIFT(id));
+
+	spin_unlock_irqrestore(isc_clk->lock, flags);
+
+	return 0;
+}
+
+static void isc_clk_disable(struct clk_hw *hw)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+	u32 id = isc_clk->id;
+	unsigned long flags;
+
+	spin_lock_irqsave(isc_clk->lock, flags);
+
+	regmap_update_bits(isc_clk->regmap, ISC_CLKDIS,
+			   ISC_CLKDIS_DIS_MASK(id),
+			   ISC_CLKDIS_DIS << ISC_CLKDIS_DIS_SHIFT(id));
+
+	spin_unlock_irqrestore(isc_clk->lock, flags);
+}
+
+static int isc_clk_is_enabled(struct clk_hw *hw)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+	unsigned long flags;
+	u32 status;
+
+	spin_lock_irqsave(isc_clk->lock, flags);
+	regmap_read(isc_clk->regmap, ISC_CLKSR, &status);
+	spin_unlock_irqrestore(isc_clk->lock, flags);
+
+	return status & ISC_CLKSR_CLK_MASK(isc_clk->id) ? 1 : 0;
+}
+
+static unsigned long
+isc_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+
+	return DIV_ROUND_CLOSEST(parent_rate, isc_clk->div + 1);
+}
+
+static int isc_clk_determine_rate(struct clk_hw *hw,
+				  struct clk_rate_request *req)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+	long best_rate = -EINVAL;
+	int best_diff = -1;
+	unsigned int i, div;
+
+	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+		struct clk_hw *parent;
+		unsigned long parent_rate;
+
+		parent = clk_hw_get_parent_by_index(hw, i);
+		if (!parent)
+			continue;
+
+		parent_rate = clk_hw_get_rate(parent);
+		if (!parent_rate)
+			continue;
+
+		for (div = 1; div < ISC_CLK_MAX_DIV + 2; div++) {
+			unsigned long rate;
+			int diff;
+
+			rate = DIV_ROUND_CLOSEST(parent_rate, div);
+			diff = abs(req->rate - rate);
+
+			if (best_diff < 0 || best_diff > diff) {
+				best_rate = rate;
+				best_diff = diff;
+				req->best_parent_rate = parent_rate;
+				req->best_parent_hw = parent;
+			}
+
+			if (!best_diff || rate < req->rate)
+				break;
+		}
+
+		if (!best_diff)
+			break;
+	}
+
+	dev_dbg(isc_clk->isc->dev,
+		"ISC CLK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
+		__func__, best_rate,
+		__clk_get_name((req->best_parent_hw)->clk),
+		req->best_parent_rate);
+
+	if (best_rate < 0)
+		return best_rate;
+
+	req->rate = best_rate;
+
+	return 0;
+}
+
+static int isc_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+
+	if (index >= clk_hw_get_num_parents(hw))
+		return -EINVAL;
+
+	isc_clk->parent_id = index;
+
+	return 0;
+}
+
+static u8 isc_clk_get_parent(struct clk_hw *hw)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+
+	return isc_clk->parent_id;
+}
+
+static int isc_clk_set_rate(struct clk_hw *hw,
+			    unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct isc_clk *isc_clk = to_isc_clk(hw);
+	u32 div;
+
+	if (!rate)
+		return -EINVAL;
+
+	div = DIV_ROUND_CLOSEST(parent_rate, rate);
+	if ((div > (ISC_CLK_MAX_DIV + 1)) || !div)
+		return -EINVAL;
+
+	isc_clk->div = div - 1;
+
+	return 0;
+}
+
+static const struct clk_ops isc_clk_ops = {
+	.enable		= isc_clk_enable,
+	.disable	= isc_clk_disable,
+	.is_enabled	= isc_clk_is_enabled,
+	.recalc_rate	= isc_clk_recalc_rate,
+	.determine_rate	= isc_clk_determine_rate,
+	.set_parent	= isc_clk_set_parent,
+	.get_parent	= isc_clk_get_parent,
+	.set_rate	= isc_clk_set_rate,
+};
+
+static int isc_clk_register(struct isc_device *isc,
+		    const struct isc_clk_pdata *pdata, struct device_node *np)
+{
+	struct regmap *regmap = isc->regmap;
+	struct isc_clk *isc_clk;
+	struct clk_init_data init;
+	const char *clk_name = np->name;
+	const char **parent_names;
+	int num_parents, ret = 0;
+	u8 id = pdata->clk_id;
+
+	num_parents = of_clk_get_parent_count(np);
+	if (num_parents < 1 || num_parents > pdata->max_num_parents)
+		return -EINVAL;
+
+	parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
+	if (!parent_names)
+		return -ENOMEM;
+
+	of_clk_parent_fill(np, parent_names, num_parents);
+
+	init.parent_names	= parent_names;
+	init.num_parents	= num_parents;
+	init.name		= clk_name;
+	init.ops		= &isc_clk_ops;
+	init.flags		= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+
+	isc_clk = &isc->isc_clks[id];
+	isc_clk->hw.init	= &init;
+	isc_clk->regmap		= regmap;
+	isc_clk->lock		= &isc->clk_lock;
+	isc_clk->id		= id;
+	isc_clk->isc		= isc;
+
+	isc_clk->clk = clk_register(NULL, &isc_clk->hw);
+	if (!IS_ERR(isc_clk->clk))
+		of_clk_add_provider(np, of_clk_src_simple_get, isc_clk->clk);
+	else {
+		dev_err(isc->dev, "%s: clock register fail\n", clk_name);
+		ret = PTR_ERR(isc_clk->clk);
+		goto free_parent_names;
+	}
+
+free_parent_names:
+	kfree(parent_names);
+	return ret;
+}
+
+static const struct isc_clk_pdata isc_ispck_pdata = {
+	.clk_id = 0,
+	.max_num_parents = 2,
+};
+
+static const struct isc_clk_pdata isc_mck_pdata = {
+	.clk_id = 1,
+	.max_num_parents = 3,
+};
+
+static const struct of_device_id isc_clk_ids[] = {
+	{ .compatible = "atmel,sama5d2-isc-ispck", .data = &isc_ispck_pdata, },
+	{ .compatible = "atmel,sama5d2-isc-mck", .data = &isc_mck_pdata, },
+	{ /*sentinel*/ }
+};
+
+static int isc_clk_init(struct isc_device *isc)
+{
+	struct device_node *np = isc->dev->of_node;
+	struct device_node *childnp;
+	const struct of_device_id *clk_id;
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < ARRAY_SIZE(isc->isc_clks); i++)
+		isc->isc_clks[i].clk = ERR_PTR(-EINVAL);
+
+	spin_lock_init(&isc->clk_lock);
+	for_each_child_of_node(np, childnp) {
+		clk_id = of_match_node(isc_clk_ids, childnp);
+		if (!clk_id)
+			continue;
+
+		ret = isc_clk_register(isc, clk_id->data, childnp);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void isc_clk_cleanup(struct isc_device *isc)
+{
+	struct device_node *np = isc->dev->of_node;
+	struct device_node *childnp;
+	const struct of_device_id *clk_id;
+	unsigned int i;
+
+	for_each_child_of_node(np, childnp) {
+		clk_id = of_match_node(isc_clk_ids, childnp);
+		if (!clk_id)
+			continue;
+
+		of_clk_del_provider(childnp);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(isc->isc_clks); i++) {
+		struct isc_clk *isc_clk = &isc->isc_clks[i];
+
+		if (!IS_ERR(isc_clk->clk))
+			clk_unregister(isc_clk->clk);
+	}
+}
+
+static int isc_queue_setup(struct vb2_queue *vq,
+			   unsigned int *nbuffers, unsigned int *nplanes,
+			   unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct isc_device *isc = vb2_get_drv_priv(vq);
+	unsigned int size = isc->fmt.fmt.pix.sizeimage;
+
+	alloc_ctxs[0] = isc->alloc_ctx;
+
+	if (*nplanes)
+		return sizes[0] < size ? -EINVAL : 0;
+
+	*nplanes = 1;
+	sizes[0] = size;
+
+	return 0;
+}
+
+static int isc_buffer_prepare(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct isc_device *isc = vb2_get_drv_priv(vb->vb2_queue);
+	unsigned long size = isc->fmt.fmt.pix.sizeimage;
+
+	if (vb2_plane_size(vb, 0) < size) {
+		v4l2_err(&isc->v4l2_dev, "buffer too small (%lu < %lu)\n",
+			 vb2_plane_size(vb, 0), size);
+		return -EINVAL;
+	}
+
+	vb2_set_plane_payload(vb, 0, size);
+
+	vbuf->field = isc->fmt.fmt.pix.field;
+
+	return 0;
+}
+
+static inline void isc_start_dma(struct regmap *regmap,
+				 struct isc_buffer *frm, u32 dview)
+{
+	dma_addr_t addr;
+
+	addr = vb2_dma_contig_plane_dma_addr(&frm->vb.vb2_buf, 0);
+
+	regmap_write(regmap, ISC_DCTRL, dview | ISC_DCTRL_IE_IS);
+	regmap_write(regmap, ISC_DAD0, addr);
+	regmap_update_bits(regmap, ISC_CTRLEN,
+			   ISC_CTRLEN_CAPTURE_MASK, ISC_CTRLEN_CAPTURE);
+}
+
+static inline bool sensor_is_preferred(const struct isc_format *isc_fmt)
+{
+	if ((sensor_preferred && isc_fmt->sd_support) ||
+	    !isc_fmt->isc_support)
+		return true;
+	else
+		return false;
+}
+
+static void isc_set_pipeline(struct regmap *regmap, u32 pipeline)
+{
+	const struct reg_mask *reg = &pipeline_regs[0];
+	u32 val;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(pipeline_regs); i++) {
+		if (pipeline & BIT(i))
+			val = reg->mask;
+		else
+			val = 0;
+
+		regmap_update_bits(regmap, reg->reg, reg->mask, val);
+
+		reg++;
+	}
+}
+
+static int isc_configure(struct isc_device *isc)
+{
+	struct regmap *regmap = isc->regmap;
+	const struct isc_format *current_fmt = isc->current_fmt;
+	struct isc_subdev_entity *subdev = isc->current_subdev;
+	u32 pipeline, val, mask;
+	int counter = 10;
+
+	if (sensor_is_preferred(current_fmt)) {
+		val = current_fmt->reg_sd_bps;
+		pipeline = 0x0;
+	} else {
+		val = current_fmt->reg_isc_bps;
+		pipeline = current_fmt->pipeline;
+
+		regmap_update_bits(regmap, ISC_WB_CFG, ISC_WB_CFG_BAYCFG_MASK,
+				   current_fmt->reg_wb_cfg);
+		regmap_update_bits(regmap, ISC_CFA_CFG, ISC_CFA_CFG_BAY_MASK,
+				   current_fmt->reg_cfa_cfg);
+	}
+
+	val |= subdev->pfe_cfg0 | ISC_PFE_CFG0_MODE_PROGRESSIVE;
+	mask = ISC_PFE_CFG0_BPS_MASK | ISC_PFE_CFG0_HPOL_MASK |
+	       ISC_PFE_CFG0_VPOL_MASK | ISC_PFE_CFG0_PPOL_MASK |
+	       ISC_PFE_CFG0_MODE_MASK;
+
+	regmap_update_bits(regmap, ISC_PFE_CFG0, mask, val);
+
+	regmap_update_bits(regmap, ISC_RLP_CFG, ISC_RLP_CFG_MODE_MASK,
+			   current_fmt->reg_rlp_mode);
+
+	regmap_update_bits(regmap, ISC_DCFG, ISC_DCFG_IMODE_MASK,
+			   current_fmt->reg_dcfg_imode);
+
+	isc_set_pipeline(regmap, pipeline);
+
+	/* Update profile */
+	regmap_update_bits(regmap, ISC_CTRLEN,
+			   ISC_CTRLEN_UPPRO_MASK, ISC_CTRLEN_UPPRO);
+
+	regmap_read(regmap, ISC_CTRLSR, &val);
+	while ((val & ISC_CTRLSR_UPPRO) && counter--) {
+		usleep_range(1000, 2000);
+		regmap_read(regmap, ISC_CTRLSR, &val);
+	}
+
+	if (counter < 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int isc_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct isc_device *isc = vb2_get_drv_priv(vq);
+	struct regmap *regmap = isc->regmap;
+	struct isc_buffer *buf;
+	unsigned long flags;
+	int ret;
+	u32 val;
+
+	/* Enable stream on the sub device */
+	ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 1);
+	if (ret && ret != -ENOIOCTLCMD) {
+		v4l2_err(&isc->v4l2_dev, "stream on failed in subdev\n");
+		goto err;
+	}
+
+	pm_runtime_get_sync(isc->dev);
+
+	/* Disable all the interrupts */
+	regmap_write(isc->regmap, ISC_INTDIS, (u32)~0UL);
+
+	/* Clean the interrupt status register */
+	regmap_read(regmap, ISC_INTSR, &val);
+
+	ret = isc_configure(isc);
+	if (unlikely(ret))
+		goto err;
+
+	/* Enable DMA interrupt */
+	regmap_update_bits(regmap, ISC_INTEN,
+			   ISC_INTEN_DDONE_MASK, ISC_INTEN_DDONE);
+
+	spin_lock_irqsave(&isc->dma_queue_lock, flags);
+
+	isc->sequence = 0;
+	isc->stop = false;
+	reinit_completion(&isc->comp);
+
+	isc->cur_frm = list_first_entry(&isc->dma_queue,
+					struct isc_buffer, list);
+	list_del(&isc->cur_frm->list);
+
+	isc_start_dma(regmap, isc->cur_frm, isc->current_fmt->reg_dctrl_dview);
+
+	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
+
+	return 0;
+
+err:
+	pm_runtime_put_sync(isc->dev);
+
+	spin_lock_irqsave(&isc->dma_queue_lock, flags);
+	list_for_each_entry(buf, &isc->dma_queue, list)
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
+	INIT_LIST_HEAD(&isc->dma_queue);
+	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
+
+	return ret;
+}
+
+static void isc_stop_streaming(struct vb2_queue *vq)
+{
+	struct isc_device *isc = vb2_get_drv_priv(vq);
+	unsigned long flags;
+	struct isc_buffer *buf;
+	int ret;
+
+	isc->stop = true;
+
+	/* Wait until the end of the current frame */
+	if (isc->cur_frm && !wait_for_completion_timeout(&isc->comp, 5 * HZ))
+		v4l2_err(&isc->v4l2_dev,
+			 "Timeout waiting for end of the capture\n");
+
+	/* Disable DMA interrupt */
+	regmap_update_bits(isc->regmap, ISC_INTDIS,
+			   ISC_INTDIS_DDONE_MASK, ISC_INTDIS_DDONE);
+
+	pm_runtime_put_sync(isc->dev);
+
+	/* Disable stream on the sub device */
+	ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 0);
+	if (ret && ret != -ENOIOCTLCMD)
+		v4l2_err(&isc->v4l2_dev, "stream off failed in subdev\n");
+
+	/* Release all active buffers */
+	spin_lock_irqsave(&isc->dma_queue_lock, flags);
+	if (unlikely(isc->cur_frm)) {
+		vb2_buffer_done(&isc->cur_frm->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
+		isc->cur_frm = NULL;
+	}
+	list_for_each_entry(buf, &isc->dma_queue, list)
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+	INIT_LIST_HEAD(&isc->dma_queue);
+	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
+}
+
+static void isc_buffer_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct isc_buffer *buf = container_of(vbuf, struct isc_buffer, vb);
+	struct isc_device *isc = vb2_get_drv_priv(vb->vb2_queue);
+	unsigned long flags;
+
+	spin_lock_irqsave(&isc->dma_queue_lock, flags);
+	list_add_tail(&buf->list, &isc->dma_queue);
+	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
+}
+
+static struct vb2_ops isc_vb2_ops = {
+	.queue_setup		= isc_queue_setup,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
+	.buf_prepare		= isc_buffer_prepare,
+	.start_streaming	= isc_start_streaming,
+	.stop_streaming		= isc_stop_streaming,
+	.buf_queue		= isc_buffer_queue,
+};
+
+static int isc_querycap(struct file *file, void *priv,
+			struct v4l2_capability *cap)
+{
+	struct isc_device *isc = video_drvdata(file);
+
+	strcpy(cap->driver, ATMEL_ISC_NAME);
+	strcpy(cap->card, "Atmel Image Sensor Controller");
+	snprintf(cap->bus_info, sizeof(cap->bus_info),
+		 "platform:%s", isc->v4l2_dev.name);
+
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+	return 0;
+}
+
+static int isc_enum_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_fmtdesc *f)
+{
+	struct isc_device *isc = video_drvdata(file);
+	u32 index = f->index;
+
+	if (index >= isc->num_user_formats)
+		return -EINVAL;
+
+	f->pixelformat = isc->user_formats[index]->fourcc;
+
+	return 0;
+}
+
+static int isc_g_fmt_vid_cap(struct file *file, void *priv,
+			     struct v4l2_format *fmt)
+{
+	struct isc_device *isc = video_drvdata(file);
+
+	*fmt = isc->fmt;
+
+	return 0;
+}
+
+static struct isc_format *find_format_by_fourcc(struct isc_device *isc,
+						unsigned int fourcc)
+{
+	unsigned int num_formats = isc->num_user_formats;
+	struct isc_format *fmt;
+	unsigned int i;
+
+	for (i = 0; i < num_formats; i++) {
+		fmt = isc->user_formats[i];
+		if (fmt->fourcc == fourcc)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f,
+		       struct isc_format **current_fmt, u32 *code)
+{
+	struct isc_format *isc_fmt;
+	struct v4l2_pix_format *pixfmt = &f->fmt.pix;
+	struct v4l2_subdev_format format = {
+		.which = V4L2_SUBDEV_FORMAT_TRY,
+	};
+	u32 mbus_code;
+	int ret;
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	isc_fmt = find_format_by_fourcc(isc, pixfmt->pixelformat);
+	if (!isc_fmt) {
+		v4l2_warn(&isc->v4l2_dev, "Format 0x%x not found\n",
+			  pixfmt->pixelformat);
+		return -EINVAL;
+	}
+
+	/* Limit to Atmel ISC hardware capabilities */
+	if (pixfmt->width > ISC_MAX_SUPPORT_WIDTH)
+		pixfmt->width = ISC_MAX_SUPPORT_WIDTH;
+	if (pixfmt->height > ISC_MAX_SUPPORT_HEIGHT)
+		pixfmt->height = ISC_MAX_SUPPORT_HEIGHT;
+
+	if (sensor_is_preferred(isc_fmt))
+		mbus_code = isc_fmt->sd_mbus_code;
+	else
+		mbus_code = isc_fmt->isc_mbus_code;
+
+	v4l2_fill_mbus_format(&format.format, pixfmt, mbus_code);
+	ret = v4l2_subdev_call(isc->current_subdev->sd, pad, set_fmt,
+			       isc->current_subdev->config, &format);
+	if (ret < 0)
+		return ret;
+
+	v4l2_fill_pix_format(pixfmt, &format.format);
+
+	switch (pixfmt->field) {
+	case V4L2_FIELD_ANY:
+	case V4L2_FIELD_NONE:
+		break;
+	default:
+		v4l2_err(&isc->v4l2_dev, "Field type %d unsupported.\n",
+			 pixfmt->field);
+		return -EINVAL;
+	}
+
+	pixfmt->bytesperline = pixfmt->width * isc_fmt->bpp;
+	pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
+
+	if (current_fmt)
+		*current_fmt = isc_fmt;
+
+	if (code)
+		*code = mbus_code;
+
+	return 0;
+}
+
+static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f)
+{
+	struct v4l2_subdev_format format = {
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+	};
+	struct isc_format *current_fmt;
+	int ret;
+	u32 mbus_code;
+
+	ret = isc_try_fmt(isc, f, &current_fmt, &mbus_code);
+	if (ret)
+		return ret;
+
+	v4l2_fill_mbus_format(&format.format, &f->fmt.pix, mbus_code);
+	ret = v4l2_subdev_call(isc->current_subdev->sd, pad,
+			       set_fmt, NULL, &format);
+	if (ret < 0)
+		return ret;
+
+	isc->fmt = *f;
+	isc->current_fmt = current_fmt;
+
+	return 0;
+}
+
+static int isc_s_fmt_vid_cap(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct isc_device *isc = video_drvdata(file);
+
+	if (vb2_is_streaming(&isc->vb2_vidq))
+		return -EBUSY;
+
+	return isc_set_fmt(isc, f);
+}
+
+static int isc_try_fmt_vid_cap(struct file *file, void *priv,
+			       struct v4l2_format *f)
+{
+	struct isc_device *isc = video_drvdata(file);
+
+	return isc_try_fmt(isc, f, NULL, NULL);
+}
+
+static int isc_enum_input(struct file *file, void *priv,
+			  struct v4l2_input *inp)
+{
+	if (inp->index != 0)
+		return -EINVAL;
+
+	inp->type = V4L2_INPUT_TYPE_CAMERA;
+	inp->std = 0;
+	strcpy(inp->name, "Camera");
+
+	return 0;
+}
+
+static int isc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	*i = 0;
+
+	return 0;
+}
+
+static int isc_s_input(struct file *file, void *priv, unsigned int i)
+{
+	if (i > 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int isc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct isc_device *isc = video_drvdata(file);
+	int ret;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	ret = v4l2_subdev_call(isc->current_subdev->sd, video, g_parm, a);
+	if (ret == -ENOIOCTLCMD)
+		ret = 0;
+
+	return ret;
+}
+
+static int isc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct isc_device *isc = video_drvdata(file);
+	int ret;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_parm, a);
+	if (ret == -ENOIOCTLCMD)
+		ret = 0;
+
+	return ret;
+}
+
+static const struct v4l2_ioctl_ops isc_ioctl_ops = {
+	.vidioc_querycap		= isc_querycap,
+	.vidioc_enum_fmt_vid_cap	= isc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap		= isc_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap		= isc_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap		= isc_try_fmt_vid_cap,
+
+	.vidioc_enum_input		= isc_enum_input,
+	.vidioc_g_input			= isc_g_input,
+	.vidioc_s_input			= isc_s_input,
+
+	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
+	.vidioc_querybuf		= vb2_ioctl_querybuf,
+	.vidioc_qbuf			= vb2_ioctl_qbuf,
+	.vidioc_expbuf			= vb2_ioctl_expbuf,
+	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
+	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
+	.vidioc_streamon		= vb2_ioctl_streamon,
+	.vidioc_streamoff		= vb2_ioctl_streamoff,
+
+	.vidioc_g_parm			= isc_g_parm,
+	.vidioc_s_parm			= isc_s_parm,
+};
+
+static int isc_set_default_fmt(struct isc_device *isc)
+{
+	u32 index = isc->num_user_formats - 1;
+	struct v4l2_format f = {
+		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+		.fmt.pix = {
+			.width		= VGA_WIDTH,
+			.height		= VGA_HEIGHT,
+			.field		= V4L2_FIELD_ANY,
+			.pixelformat	= isc->user_formats[index]->fourcc,
+		},
+	};
+
+	return isc_set_fmt(isc, &f);
+}
+
+static int isc_open(struct file *file)
+{
+	struct isc_device *isc = video_drvdata(file);
+	struct v4l2_subdev *sd = isc->current_subdev->sd;
+	int ret;
+
+	if (mutex_lock_interruptible(&isc->lock))
+		return -ERESTARTSYS;
+
+	ret = v4l2_fh_open(file);
+	if (ret < 0)
+		goto unlock;
+
+	ret = v4l2_subdev_call(sd, core, s_power, 1);
+	if (ret < 0 && ret != -ENOIOCTLCMD)
+		goto unlock;
+
+	ret = isc_set_default_fmt(isc);
+	if (ret)
+		goto unlock;
+
+unlock:
+	mutex_unlock(&isc->lock);
+	return ret;
+}
+
+static int isc_release(struct file *file)
+{
+	struct isc_device *isc = video_drvdata(file);
+	struct v4l2_subdev *sd = isc->current_subdev->sd;
+	int ret;
+
+	mutex_lock(&isc->lock);
+
+	ret = _vb2_fop_release(file, NULL);
+
+	v4l2_subdev_call(sd, core, s_power, 0);
+
+	mutex_unlock(&isc->lock);
+
+	return ret;
+}
+
+static const struct v4l2_file_operations isc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= isc_open,
+	.release	= isc_release,
+	.unlocked_ioctl	= video_ioctl2,
+	.read		= vb2_fop_read,
+	.mmap		= vb2_fop_mmap,
+	.poll		= vb2_fop_poll,
+};
+
+static irqreturn_t isc_interrupt(int irq, void *dev_id)
+{
+	struct isc_device *isc = (struct isc_device *)dev_id;
+	struct regmap *regmap = isc->regmap;
+	u32 isc_intsr, isc_intmask, pending;
+	irqreturn_t ret = IRQ_NONE;
+
+	spin_lock(&isc->dma_queue_lock);
+
+	regmap_read(regmap, ISC_INTSR, &isc_intsr);
+	regmap_read(regmap, ISC_INTMASK, &isc_intmask);
+
+	pending = isc_intsr & isc_intmask;
+
+	if (likely(pending & ISC_INTSR_DDONE)) {
+		if (isc->cur_frm) {
+			struct vb2_v4l2_buffer *vbuf = &isc->cur_frm->vb;
+			struct vb2_buffer *vb = &vbuf->vb2_buf;
+
+			vb->timestamp = ktime_get_ns();
+			vbuf->sequence = isc->sequence++;
+			vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+			isc->cur_frm = NULL;
+		}
+
+		if (!list_empty(&isc->dma_queue) && !isc->stop) {
+			isc->cur_frm = list_first_entry(&isc->dma_queue,
+						     struct isc_buffer, list);
+			list_del(&isc->cur_frm->list);
+
+			isc_start_dma(regmap, isc->cur_frm,
+				      isc->current_fmt->reg_dctrl_dview);
+		}
+
+		if (isc->stop)
+			complete(&isc->comp);
+
+		ret = IRQ_HANDLED;
+	}
+
+	spin_unlock(&isc->dma_queue_lock);
+
+	return ret;
+}
+
+static int isc_async_bound(struct v4l2_async_notifier *notifier,
+			   struct v4l2_subdev *subdev,
+			   struct v4l2_async_subdev *asd)
+{
+	struct isc_device *isc = container_of(notifier->v4l2_dev,
+					      struct isc_device, v4l2_dev);
+	struct isc_subdev_entity *subdev_entity =
+		container_of(notifier, struct isc_subdev_entity, notifier);
+
+	if (video_is_registered(&isc->video_dev)) {
+		v4l2_err(&isc->v4l2_dev, "only supports one sub-device.\n");
+		return -EBUSY;
+	}
+
+	subdev_entity->sd = subdev;
+
+	return 0;
+}
+
+static void isc_async_unbind(struct v4l2_async_notifier *notifier,
+			     struct v4l2_subdev *subdev,
+			     struct v4l2_async_subdev *asd)
+{
+	struct isc_device *isc = container_of(notifier->v4l2_dev,
+					      struct isc_device, v4l2_dev);
+
+	video_unregister_device(&isc->video_dev);
+	vb2_dma_contig_cleanup_ctx(isc->alloc_ctx);
+	isc->alloc_ctx = NULL;
+	if (isc->current_subdev->config)
+		v4l2_subdev_free_pad_config(isc->current_subdev->config);
+}
+
+static struct isc_format *find_format_by_code(unsigned int code, int *index)
+{
+	struct isc_format *fmt = &isc_formats[0];
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(isc_formats); i++) {
+		if (fmt->sd_mbus_code == code) {
+			*index = i;
+			return fmt;
+		}
+
+		fmt++;
+	}
+
+	return NULL;
+}
+
+static int isc_formats_init(struct isc_device *isc)
+{
+	struct isc_format *fmt;
+	struct v4l2_subdev *subdev = isc->current_subdev->sd;
+	int num_fmts, i, j;
+	struct v4l2_subdev_mbus_code_enum mbus_code = {
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+	};
+
+	fmt = &isc_formats[0];
+	for (i = 0; i < ARRAY_SIZE(isc_formats); i++) {
+		fmt->isc_support = false;
+		fmt->sd_support = false;
+
+		fmt++;
+	}
+
+	while (!v4l2_subdev_call(subdev, pad, enum_mbus_code,
+	       NULL, &mbus_code)) {
+		mbus_code.index++;
+		fmt = find_format_by_code(mbus_code.code, &i);
+		if (!fmt)
+			continue;
+
+		fmt->sd_support = true;
+
+		if (i <= RAW_FMT_INDEX_END) {
+			for (j = ISC_FMT_INDEX_START;
+			     j <= ISC_FMT_INDEX_END; j++) {
+				isc_formats[j].isc_support = true;
+				isc_formats[j].isc_mbus_code = mbus_code.code;
+				isc_formats[j].reg_isc_bps = fmt->reg_sd_bps;
+				isc_formats[j].reg_wb_cfg = fmt->reg_wb_cfg;
+				isc_formats[j].reg_cfa_cfg = fmt->reg_cfa_cfg;
+			}
+		}
+	}
+
+	fmt = &isc_formats[0];
+	for (i = 0, num_fmts = 0; i < ARRAY_SIZE(isc_formats); i++) {
+		if (fmt->isc_support || fmt->sd_support)
+			num_fmts++;
+
+		fmt++;
+	}
+
+	if (!num_fmts)
+		return -ENXIO;
+
+	isc->num_user_formats = num_fmts;
+	isc->user_formats = devm_kcalloc(isc->dev,
+					 num_fmts, sizeof(struct isc_format *),
+					 GFP_KERNEL);
+	if (!isc->user_formats) {
+		v4l2_err(&isc->v4l2_dev, "could not allocate memory\n");
+		return -ENOMEM;
+	}
+
+	fmt = &isc_formats[0];
+	for (i = 0, j = 0; i < ARRAY_SIZE(isc_formats); i++) {
+		if (fmt->isc_support || fmt->sd_support)
+			isc->user_formats[j++] = fmt;
+
+		fmt++;
+	}
+
+	return 0;
+}
+
+static int isc_async_complete(struct v4l2_async_notifier *notifier)
+{
+	struct isc_device *isc = container_of(notifier->v4l2_dev,
+					      struct isc_device, v4l2_dev);
+	struct isc_subdev_entity *sd_entity;
+	struct video_device *vdev = &isc->video_dev;
+	struct vb2_queue *q = &isc->vb2_vidq;
+	int ret;
+
+	isc->current_subdev = container_of(notifier,
+					   struct isc_subdev_entity, notifier);
+	sd_entity = isc->current_subdev;
+
+	mutex_init(&isc->lock);
+	init_completion(&isc->comp);
+
+	/* Initialize videobuf2 queue */
+	isc->alloc_ctx = vb2_dma_contig_init_ctx(isc->dev);
+	if (IS_ERR(isc->alloc_ctx)) {
+		ret = PTR_ERR(isc->alloc_ctx);
+		v4l2_err(&isc->v4l2_dev,
+			 "Failed to get the context: %d\n", ret);
+		return ret;
+	}
+
+	q->type			= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes		= VB2_MMAP;
+	q->drv_priv		= isc;
+	q->buf_struct_size	= sizeof(struct isc_buffer);
+	q->ops			= &isc_vb2_ops;
+	q->mem_ops		= &vb2_dma_contig_memops;
+	q->timestamp_flags	= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->lock			= &isc->lock;
+	q->min_buffers_needed	= 1;
+
+	ret = vb2_queue_init(q);
+	if (ret < 0) {
+		v4l2_err(&isc->v4l2_dev,
+			 "vb2_queue_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	/* Init video dma queues */
+	INIT_LIST_HEAD(&isc->dma_queue);
+	spin_lock_init(&isc->dma_queue_lock);
+
+	/* Register video device */
+	strlcpy(vdev->name, ATMEL_ISC_NAME, sizeof(vdev->name));
+	vdev->release		= video_device_release_empty;
+	vdev->fops		= &isc_fops;
+	vdev->ioctl_ops		= &isc_ioctl_ops;
+	vdev->v4l2_dev		= &isc->v4l2_dev;
+	vdev->vfl_dir		= VFL_DIR_RX;
+	vdev->queue		= q;
+	vdev->lock		= &isc->lock;
+	vdev->ctrl_handler	= isc->current_subdev->sd->ctrl_handler;
+	video_set_drvdata(vdev, isc);
+
+	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	if (ret < 0) {
+		v4l2_err(&isc->v4l2_dev,
+			 "video_register_device failed: %d\n", ret);
+		return ret;
+	}
+
+	sd_entity->config = v4l2_subdev_alloc_pad_config(sd_entity->sd);
+	if (sd_entity->config == NULL)
+		return -ENOMEM;
+
+	ret = isc_formats_init(isc);
+	if (ret < 0) {
+		v4l2_err(&isc->v4l2_dev,
+			 "Init format failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void isc_subdev_cleanup(struct isc_device *isc)
+{
+	struct isc_subdev_entity *subdev_entity;
+
+	list_for_each_entry(subdev_entity, &isc->subdev_entities, list)
+		v4l2_async_notifier_unregister(&subdev_entity->notifier);
+
+	INIT_LIST_HEAD(&isc->subdev_entities);
+}
+
+static int isc_parse_dt(struct device *dev, struct isc_device *isc)
+{
+	struct device_node *np = dev->of_node;
+	struct device_node *epn = NULL, *rem;
+	struct v4l2_of_endpoint v4l2_epn;
+	struct isc_subdev_entity *subdev_entity;
+	unsigned int flags;
+	int ret;
+
+	INIT_LIST_HEAD(&isc->subdev_entities);
+
+	for (; ;) {
+		epn = of_graph_get_next_endpoint(np, epn);
+		if (!epn)
+			break;
+
+		rem = of_graph_get_remote_port_parent(epn);
+		if (!rem) {
+			dev_notice(dev, "Remote device at %s not found\n",
+				   of_node_full_name(epn));
+			continue;
+		}
+
+		ret = v4l2_of_parse_endpoint(epn, &v4l2_epn);
+		if (ret) {
+			of_node_put(rem);
+			ret = -EINVAL;
+			dev_err(dev, "Could not parse the endpoint\n");
+			break;
+		}
+
+		subdev_entity = devm_kzalloc(dev,
+					  sizeof(*subdev_entity), GFP_KERNEL);
+		if (subdev_entity == NULL) {
+			of_node_put(rem);
+			ret = -ENOMEM;
+			break;
+		}
+
+		subdev_entity->asd = devm_kzalloc(dev,
+				     sizeof(*subdev_entity->asd), GFP_KERNEL);
+		if (subdev_entity->asd == NULL) {
+			of_node_put(rem);
+			ret = -ENOMEM;
+			break;
+		}
+
+		flags = v4l2_epn.bus.parallel.flags;
+
+		if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+			subdev_entity->pfe_cfg0 = ISC_PFE_CFG0_HPOL_LOW;
+		else
+			subdev_entity->pfe_cfg0 = ISC_PFE_CFG0_HPOL_HIGH;
+
+		if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_VPOL_LOW;
+		else
+			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_VPOL_HIGH;
+
+		if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW;
+		else
+			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_HIGH;
+
+		subdev_entity->asd->match_type = V4L2_ASYNC_MATCH_OF;
+		subdev_entity->asd->match.of.node = rem;
+		list_add_tail(&subdev_entity->list, &isc->subdev_entities);
+	}
+
+	of_node_put(epn);
+	return ret;
+}
+
+/* regmap configuration */
+#define ATMEL_ISC_REG_MAX    0xbfc
+static const struct regmap_config isc_regmap_config = {
+	.reg_bits       = 32,
+	.reg_stride     = 4,
+	.val_bits       = 32,
+	.max_register	= ATMEL_ISC_REG_MAX,
+};
+
+static int atmel_isc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct isc_device *isc;
+	struct resource *res;
+	void __iomem *io_base;
+	struct isc_subdev_entity *subdev_entity;
+	int irq;
+	int ret;
+
+	isc = devm_kzalloc(dev, sizeof(*isc), GFP_KERNEL);
+	if (!isc)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, isc);
+	isc->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	io_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(io_base))
+		return PTR_ERR(io_base);
+
+	isc->regmap = devm_regmap_init_mmio(dev, io_base, &isc_regmap_config);
+	if (IS_ERR(isc->regmap)) {
+		ret = PTR_ERR(isc->regmap);
+		dev_err(dev, "failed to init register map: %d\n", ret);
+		return ret;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (IS_ERR_VALUE(irq)) {
+		ret = irq;
+		dev_err(dev, "failed to get irq: %d\n", ret);
+		return ret;
+	}
+
+	ret = devm_request_irq(dev, irq, isc_interrupt, 0,
+			       ATMEL_ISC_NAME, isc);
+	if (ret < 0) {
+		dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
+			irq, ret);
+		return ret;
+	}
+
+	isc->hclock = devm_clk_get(dev, "hclock");
+	if (IS_ERR(isc->hclock)) {
+		ret = PTR_ERR(isc->hclock);
+		dev_err(dev, "failed to get hclock: %d\n", ret);
+		return ret;
+	}
+
+	ret = isc_clk_init(isc);
+	if (ret) {
+		dev_err(dev, "failed to init isc clock: %d\n", ret);
+		goto clean_isc_clk;
+	}
+
+	isc->ispck = devm_clk_get(dev, "ispck");
+	if (IS_ERR(isc->ispck)) {
+		ret = PTR_ERR(isc->ispck);
+		dev_err(dev, "failed to get isc_ispck: %d\n", ret);
+		goto clean_isc_clk;
+	}
+
+	/* ispck should be greater or equal to hclock */
+	ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock));
+	if (ret) {
+		dev_err(dev, "failed to set ispck rate: %d\n", ret);
+		goto clean_isc_clk;
+	}
+
+	ret = v4l2_device_register(dev, &isc->v4l2_dev);
+	if (ret) {
+		dev_err(dev, "unable to register v4l2 device.\n");
+		goto clean_isc_clk;
+	}
+
+	ret = isc_parse_dt(dev, isc);
+	if (ret) {
+		dev_err(dev, "fail to parse device tree\n");
+		goto unregister_v4l2_device;
+	}
+
+	if (list_empty(&isc->subdev_entities)) {
+		dev_err(dev, "no subdev found\n");
+		goto unregister_v4l2_device;
+	}
+
+	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
+		subdev_entity->notifier.subdevs = &subdev_entity->asd;
+		subdev_entity->notifier.num_subdevs = 1;
+		subdev_entity->notifier.bound = isc_async_bound;
+		subdev_entity->notifier.unbind = isc_async_unbind;
+		subdev_entity->notifier.complete = isc_async_complete;
+
+		ret = v4l2_async_notifier_register(&isc->v4l2_dev,
+						   &subdev_entity->notifier);
+		if (ret) {
+			dev_err(dev, "fail to register async notifier\n");
+			goto cleanup_subdev;
+		}
+
+		if (video_is_registered(&isc->video_dev))
+			break;
+	}
+
+	pm_runtime_enable(dev);
+
+	return 0;
+
+cleanup_subdev:
+	isc_subdev_cleanup(isc);
+
+unregister_v4l2_device:
+	v4l2_device_unregister(&isc->v4l2_dev);
+
+clean_isc_clk:
+	isc_clk_cleanup(isc);
+
+	return ret;
+}
+
+static int atmel_isc_remove(struct platform_device *pdev)
+{
+	struct isc_device *isc = platform_get_drvdata(pdev);
+
+	pm_runtime_disable(&pdev->dev);
+
+	isc_subdev_cleanup(isc);
+
+	v4l2_device_unregister(&isc->v4l2_dev);
+
+	isc_clk_cleanup(isc);
+
+	return 0;
+}
+
+static int isc_runtime_suspend(struct device *dev)
+{
+	struct isc_device *isc = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(isc->ispck);
+	clk_disable_unprepare(isc->hclock);
+
+	return 0;
+}
+
+static int isc_runtime_resume(struct device *dev)
+{
+	struct isc_device *isc = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(isc->hclock);
+	if (ret)
+		return ret;
+
+	return clk_prepare_enable(isc->ispck);
+}
+
+static const struct dev_pm_ops atmel_isc_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(isc_runtime_suspend, isc_runtime_resume, NULL)
+};
+
+static const struct of_device_id atmel_isc_of_match[] = {
+	{ .compatible = "atmel,sama5d2-isc" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, atmel_isc_of_match);
+
+static struct platform_driver atmel_isc_driver = {
+	.probe	= atmel_isc_probe,
+	.remove	= atmel_isc_remove,
+	.driver	= {
+		.name		= ATMEL_ISC_NAME,
+		.pm		= &atmel_isc_dev_pm_ops,
+		.of_match_table = of_match_ptr(atmel_isc_of_match),
+	},
+};
+
+module_platform_driver(atmel_isc_driver);
+
+MODULE_AUTHOR("Songjun Wu <songjun.wu at atmel.com>");
+MODULE_DESCRIPTION("The V4L2 driver for Atmel-ISC");
+MODULE_LICENSE("GPL v2");
+MODULE_SUPPORTED_DEVICE("video");
-- 
2.7.4



From songjun.wu at atmel.com  Mon May 30 23:58:23 2016
From: songjun.wu at atmel.com (Songjun Wu)
Date: Tue, 31 May 2016 14:58:23 +0800
Subject: [PATCH v3 2/2] [media] atmel-isc: DT binding for Image Sensor
 Controller driver
In-Reply-To: <1464677903-28412-1-git-send-email-songjun.wu@atmel.com>
References: <1464677903-28412-1-git-send-email-songjun.wu@atmel.com>
Message-ID: <1464677903-28412-3-git-send-email-songjun.wu@atmel.com>

DT binding documentation for ISC driver.

Signed-off-by: Songjun Wu <songjun.wu at atmel.com>
---

Changes in v3:
- Remove the 'atmel,sensor-preferred'.
- Modify the isc clock node according to the Rob's remarks.

Changes in v2:
- Remove the unit address of the endpoint.
- Add the unit address to the clock node.
- Avoid using underscores in node names.
- Drop the "0x" in the unit address of the i2c node.
- Modify the description of 'atmel,sensor-preferred'.
- Add the description for the ISC internal clock.

 .../devicetree/bindings/media/atmel-isc.txt        | 88 ++++++++++++++++++++++
 1 file changed, 88 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/atmel-isc.txt

diff --git a/Documentation/devicetree/bindings/media/atmel-isc.txt b/Documentation/devicetree/bindings/media/atmel-isc.txt
new file mode 100644
index 0000000..2ae1d60
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/atmel-isc.txt
@@ -0,0 +1,88 @@
+Atmel Image Sensor Controller (ISC)
+----------------------------------------------
+
+Required properties for ISC:
+- compatible
+	Must be "atmel,sama5d2-isc"
+- reg
+	Physical base address and length of the registers set for the device;
+- interrupts
+	Should contain IRQ line for the ISI;
+- clocks
+	List of clock specifiers, corresponding to entries in
+	the clock-names property;
+	Please refer to clock-bindings.txt.
+- clock-names
+	Required elements: "hclock", "ispck".
+- pinctrl-names, pinctrl-0
+	Please refer to pinctrl-bindings.txt.
+- isc-ispck
+	The clock for the ISC digital pipeline.
+	- compatible
+		Must be "atmel,sama5d2-isc-ispck".
+	- clock-cells
+		From common clock binding; should be set to 0.
+	- clocks
+		The clock source phandles.
+- isc-mck
+	The clock for the image sensor.
+	- compatible
+		Must be "atmel,sama5d2-isc-mck".
+	- clock-cells
+		From common clock binding; should be set to 0.
+	- clocks
+		The clock source phandles.
+
+ISC supports a single port node with parallel bus. It should contain one
+'port' child node with child 'endpoint' node. Please refer to the bindings
+defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+isc: isc at f0008000 {
+	compatible = "atmel,sama5d2-isc";
+	reg = <0xf0008000 0x4000>;
+	interrupts = <46 IRQ_TYPE_LEVEL_HIGH 5>;
+	clocks = <&isc_clk>, <&isc_ispck>;
+	clock-names = "hclock", "ispck";
+
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		isc_0: endpoint {
+			remote-endpoint = <&ov7740_0>;
+			hsync-active = <1>;
+			vsync-active = <0>;
+			pclk-sample = <1>;
+		};
+	};
+
+	isc_ispck: isc-ispck at 0 {
+		compatible = "atmel,sama5d2-isc-ispck";
+		#clock-cells = <0>;
+		clocks = <&isc_clk>, <&iscck>;
+	};
+
+	isc_mck: isc-mck at 1 {
+		compatible = "atmel,sama5d2-isc-mck";
+		#clock-cells = <0>;
+		clocks = <&isc_clk>, <&iscck>, <&isc_gclk>;
+	};
+};
+
+i2c1: i2c at fc028000 {
+	ov7740: camera at 21 {
+	compatible = "ovti,ov7740";
+	reg = <0x21>;
+
+	clocks = <&isc_mck>;
+	clock-names = "xvclk";
+	assigned-clocks = <&isc_mck>;
+	assigned-clock-rates = <24000000>;
+
+	port {
+		ov7740_0: endpoint {
+			remote-endpoint = <&isc_0>;
+		};
+	};
+};
-- 
2.7.4



From geert at linux-m68k.org  Tue May 31 00:17:09 2016
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Tue, 31 May 2016 09:17:09 +0200
Subject: [PATCH v3 0/2] [media] atmel-isc: add driver for Atmel ISC
In-Reply-To: <1464677903-28412-1-git-send-email-songjun.wu@atmel.com>
References: <1464677903-28412-1-git-send-email-songjun.wu@atmel.com>
Message-ID: <CAMuHMdV5pqAEea7v7WbQ2FSSve92avte4B=j53-12s842D-Xdg@mail.gmail.com>

Hi Songjun,

On Tue, May 31, 2016 at 8:58 AM, Songjun Wu <songjun.wu at atmel.com> wrote:
> The Image Sensor Controller driver includes two parts.
> 1) Driver code to implement the ISC function.
> 2) Device tree binding documentation, it describes how
>    to add the ISC in device tree.

Please reduce the CC list. Not everyone who ever touched a line in the
files you modified is working on media or atmel devices.

get_maintainer.pl gives hints, not exact lists of people.

Thanks!

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 raashidmuhammed at zilogic.com  Tue May 31 00:17:31 2016
From: raashidmuhammed at zilogic.com (Raashid Muhammed)
Date: Tue, 31 May 2016 12:47:31 +0530
Subject: [PATCH v2 2/2] ARM: at91: Add DT support for Olimex SAM9-L9260 board.
In-Reply-To: <1464679051-5263-1-git-send-email-raashidmuhammed@zilogic.com>
References: <1464679051-5263-1-git-send-email-raashidmuhammed@zilogic.com>
Message-ID: <1464679051-5263-2-git-send-email-raashidmuhammed@zilogic.com>

From: Raashid Muhammed <raashidmuhammed at zilogic.com>

sam9-l9260 is a low cost board designed by Olimex.

More information is available at:
https://www.olimex.com/Products/ARM/Atmel/SAM9-L9260/

Signed-off-by: Raashid Muhammed <raashidmuhammed at zilogic.com>
Reviewed-by: Vijay Kumar B. <vijaykumar at bravegnu.org>
---
 Documentation/devicetree/bindings/arm/olimex.txt |   8 +-
 arch/arm/boot/dts/Makefile                       |   1 +
 arch/arm/boot/dts/at91-sam9_l9260.dts            | 115 +++++++++++++++++++++++
 3 files changed, 122 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/boot/dts/at91-sam9_l9260.dts

diff --git a/Documentation/devicetree/bindings/arm/olimex.txt b/Documentation/devicetree/bindings/arm/olimex.txt
index 007fb5c..d726aec 100644
--- a/Documentation/devicetree/bindings/arm/olimex.txt
+++ b/Documentation/devicetree/bindings/arm/olimex.txt
@@ -1,5 +1,9 @@
-Olimex i.MX Platforms Device Tree Bindings
-------------------------------------------
+Olimex Device Tree Bindings
+---------------------------
+
+SAM9-L9260 Board
+Required root node properties:
+    - compatible = "olimex,sam9-l9260", "atmel,at91sam9260";
 
 i.MX23 Olinuxino Low Cost Board
 Required root node properties:
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 0f89d87..d27f09d 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -19,6 +19,7 @@ dtb-$(CONFIG_SOC_SAM_V4_V5) += \
 	usb_a9260.dtb \
 	at91sam9261ek.dtb \
 	at91sam9263ek.dtb \
+	at91-sam9_l9260.dtb \
 	tny_a9263.dtb \
 	usb_a9263.dtb \
 	at91-foxg20.dtb \
diff --git a/arch/arm/boot/dts/at91-sam9_l9260.dts b/arch/arm/boot/dts/at91-sam9_l9260.dts
new file mode 100644
index 0000000..b3d738b
--- /dev/null
+++ b/arch/arm/boot/dts/at91-sam9_l9260.dts
@@ -0,0 +1,115 @@
+/*
+ * at91-sam9_l9260.dts - Device Tree file for Olimex SAM9-L9260 board
+ *
+ *  Copyright (C) 2016 Raashid Muhammed <raashidmuhammed at zilogic.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+#include "at91sam9260.dtsi"
+
+/ {
+	model = "Olimex sam9-l9260";
+	compatible = "olimex,sam9-l9260", "atmel,at91sam9260", "atmel,at91sam9";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		reg = <0x20000000 0x4000000>;
+	};
+
+	clocks {
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <18432000>;
+		};
+	};
+
+	ahb {
+		apb {
+			mmc0: mmc at fffa8000 {
+				pinctrl-0 = <
+					&pinctrl_board_mmc0
+					&pinctrl_mmc0_clk
+					&pinctrl_mmc0_slot1_cmd_dat0
+					&pinctrl_mmc0_slot1_dat1_3>;
+				status = "okay";
+
+				slot at 1 {
+					reg = <1>;
+					bus-width = <4>;
+					cd-gpios = <&pioC 8 GPIO_ACTIVE_HIGH>;
+					wp-gpios = <&pioC 4 GPIO_ACTIVE_HIGH>;
+				};
+			};
+
+			macb0: ethernet at fffc4000 {
+				phy-mode = "mii";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "okay";
+
+				ethernet-phy at 1 {
+					reg = <0x1>;
+				};
+			};
+
+			spi0: spi at fffc8000 {
+				cs-gpios = <&pioC 11 0>, <0>, <0>, <0>;
+				status = "okay";
+
+				mtd_dataflash at 0 {
+					compatible = "atmel,at45", "atmel,dataflash";
+					spi-max-frequency = <15000000>;
+					reg = <0>;
+				};
+			};
+
+			dbgu: serial at fffff200 {
+				status = "okay";
+			};
+
+			pinctrl at fffff400 {
+				mmc0 {
+					pinctrl_board_mmc0: mmc0-board {
+						atmel,pins =
+							<AT91_PIOC 8 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH	/* CD pin */
+							 AT91_PIOC 4 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP>;	/* WP pin */
+					};
+				};
+			};
+		};
+
+		nand0: nand at 40000000 {
+			nand-bus-width = <8>;
+			nand-ecc-mode = "soft";
+			nand-on-flash-bbt = <1>;
+			status = "okay";
+		};
+
+		usb0: ohci at 500000 {
+			status = "okay";
+		};
+
+	};
+
+	i2c at 0 {
+		status = "okay";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		b0 {
+			label = "b0";
+			gpios = <&pioA 6 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+
+	};
+};
-- 
2.1.4



From raashidmuhammed at zilogic.com  Tue May 31 00:17:30 2016
From: raashidmuhammed at zilogic.com (Raashid Muhammed)
Date: Tue, 31 May 2016 12:47:30 +0530
Subject: [PATCH v2 1/2] ARM: at91/dt: at91sam9260: Remove leading zeros in
 OHCI node.
Message-ID: <1464679051-5263-1-git-send-email-raashidmuhammed@zilogic.com>

From: Raashid Muhammed <raashidmuhammed at zilogic.com>

Remove leading zeros in OHCI node for at91sam9260 based boards.

Signed-off-by: Raashid Muhammed <raashidmuhammed at zilogic.com>
Reviewed-by: Vijay Kumar B. <vijaykumar at bravegnu.org>
---
 arch/arm/boot/dts/aks-cdu.dts               | 2 +-
 arch/arm/boot/dts/animeo_ip.dts             | 2 +-
 arch/arm/boot/dts/at91-foxg20.dts           | 2 +-
 arch/arm/boot/dts/at91-kizbox.dts           | 2 +-
 arch/arm/boot/dts/at91-qil_a9260.dts        | 2 +-
 arch/arm/boot/dts/at91sam9260.dtsi          | 2 +-
 arch/arm/boot/dts/at91sam9g20ek_common.dtsi | 2 +-
 arch/arm/boot/dts/ethernut5.dts             | 2 +-
 arch/arm/boot/dts/evk-pro3.dts              | 2 +-
 arch/arm/boot/dts/usb_a9260_common.dtsi     | 2 +-
 10 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/arm/boot/dts/aks-cdu.dts b/arch/arm/boot/dts/aks-cdu.dts
index d9c50fb..5b1bf92 100644
--- a/arch/arm/boot/dts/aks-cdu.dts
+++ b/arch/arm/boot/dts/aks-cdu.dts
@@ -57,7 +57,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/animeo_ip.dts b/arch/arm/boot/dts/animeo_ip.dts
index 0962f2f..8bcbad3 100644
--- a/arch/arm/boot/dts/animeo_ip.dts
+++ b/arch/arm/boot/dts/animeo_ip.dts
@@ -114,7 +114,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			atmel,vbus-gpio = <&pioB 15 GPIO_ACTIVE_LOW>;
 			status = "okay";
diff --git a/arch/arm/boot/dts/at91-foxg20.dts b/arch/arm/boot/dts/at91-foxg20.dts
index 6bf873e..42a535d 100644
--- a/arch/arm/boot/dts/at91-foxg20.dts
+++ b/arch/arm/boot/dts/at91-foxg20.dts
@@ -128,7 +128,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/at91-kizbox.dts b/arch/arm/boot/dts/at91-kizbox.dts
index 229e989..0e3f34e 100644
--- a/arch/arm/boot/dts/at91-kizbox.dts
+++ b/arch/arm/boot/dts/at91-kizbox.dts
@@ -54,7 +54,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <1>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/at91-qil_a9260.dts b/arch/arm/boot/dts/at91-qil_a9260.dts
index 4f2eebf..5309e19 100644
--- a/arch/arm/boot/dts/at91-qil_a9260.dts
+++ b/arch/arm/boot/dts/at91-qil_a9260.dts
@@ -111,7 +111,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index d4884dd..af5ba31 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -1007,7 +1007,7 @@
 			status = "disabled";
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			compatible = "atmel,at91rm9200-ohci", "usb-ohci";
 			reg = <0x00500000 0x100000>;
 			interrupts = <20 IRQ_TYPE_LEVEL_HIGH 2>;
diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
index e9cc99b..1395b30 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -170,7 +170,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/ethernut5.dts b/arch/arm/boot/dts/ethernut5.dts
index 2430443..298ee2f 100644
--- a/arch/arm/boot/dts/ethernut5.dts
+++ b/arch/arm/boot/dts/ethernut5.dts
@@ -77,7 +77,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/evk-pro3.dts b/arch/arm/boot/dts/evk-pro3.dts
index f72969e..312d3e8 100644
--- a/arch/arm/boot/dts/evk-pro3.dts
+++ b/arch/arm/boot/dts/evk-pro3.dts
@@ -46,7 +46,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/usb_a9260_common.dtsi b/arch/arm/boot/dts/usb_a9260_common.dtsi
index 9beea89..12119b5 100644
--- a/arch/arm/boot/dts/usb_a9260_common.dtsi
+++ b/arch/arm/boot/dts/usb_a9260_common.dtsi
@@ -90,7 +90,7 @@
 			};
 		};
 
-		usb0: ohci at 00500000 {
+		usb0: ohci at 500000 {
 			num-ports = <2>;
 			status = "okay";
 		};
-- 
2.1.4



From dongas86 at gmail.com  Tue May 31 00:18:37 2016
From: dongas86 at gmail.com (Dong Aisheng)
Date: Tue, 31 May 2016 15:18:37 +0800
Subject: [PATCH 13/23] mmc: sdhci-esdhc-imx: restore watermark level
 setting after resume
In-Reply-To: <5731AA28.9030304@intel.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-14-git-send-email-aisheng.dong@nxp.com>
 <5731AA28.9030304@intel.com>
Message-ID: <20160531071837.GA4096@shlinux2>

On Tue, May 10, 2016 at 12:30:16PM +0300, Adrian Hunter wrote:
> On 15/04/16 20:29, Dong Aisheng wrote:
> > Currently, we config the watermark_level register only in probe.
> > This will cause the mmc write operation timeout issue after system
> > resume back in LPSR mode. Because in LPSR mode, after system resume
> > back, the watermark_level register(0x44) changes to 0x08000880, which
> > set the write watermark level as 0, and set the read watermark level
> > as 128. This value is incorrect.
> > 
> > This patch restores the setting of watermark level register after
> > system resume back.
> 
> In sdhci_esdhc_imx_probe() the watermark setting is conditional on
> esdhc_is_usdhc(imx_data), but in the resume it is not.  Is that intended?
> If so, maybe explain that in the commit message.
> 

Good catch!
I think we'd probably better keep that condition check.
Will update it in V2.


> Might be worth pulling out the constant 0x10401040 and #defining it since it
> is used in more than one place too.
> 

Good point!
Will do it.

Regards
Dong Aisheng

> > 
> > Signed-off-by: Dong Aisheng <aisheng.dong at nxp.com>
> > ---
> >  drivers/mmc/host/sdhci-esdhc-imx.c | 5 +++++
> >  1 file changed, 5 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 6fef6bc..4c28fbb 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -1261,6 +1261,11 @@ static int sdhci_esdhc_suspend(struct device *dev)
> >  
> >  static int sdhci_esdhc_resume(struct device *dev)
> >  {
> > +	struct sdhci_host *host = dev_get_drvdata(dev);
> > +
> > +	/* restore watermark setting in case it's lost in low power mode */
> > +	writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
> > +
> >  	return sdhci_pltfm_resume(dev);
> >  }
> >  
> > 
> 


From holgerschurig at gmail.com  Tue May 31 00:40:29 2016
From: holgerschurig at gmail.com (Holger Schurig)
Date: Tue, 31 May 2016 09:40:29 +0200
Subject: [BUG] CONFIG_UNINLINE_SPIN_UNLOCK important for Cortex-A9
Message-ID: <874m9eoetu.fsf@gmail.com>

I chased a bug in the recent weeks that seems to be related to spinlocks.



Hardware & Kernel config
------------------------
I have an i.MX6Q device. I don't use "make imx_v6_v7_defconfig", but
selected only what I need. As such, I only have CONFIG_ARCH_MXC and
CONFIG_SOC_IMX6Q enabled.

As a result, in my kernel CONFIG_UNINLINE_SPIN_UNLOCK was *not* defined.

In a kernel configured with "make imx_v6_v7_defconfig" this is
configured. And so people (e.g. the Freescale/NPX people) that normally
use this defconfig will never see the issue.



Reproduction
------------
There is a test tool called "stress-ng" in Debian, already compiled for
armhf.

If you run "stress-ng --sock 5 --timeout 999999" then you'll get weird
errors within 1 ... 30 hours. It's always some kernel OOPS, and
differing. Usually it's in the network stack, but not always. At it's
core the skb's seem to be inconsistent. I can submit oops logs if you
want.

This stress-ng starts 5 unix domain listeners, and 5 unix domain senders
(and one manager process). They send and receive at full speed. If you
run top, you see that on a 4 core system they eat 79% of system time on
each processor.

My assumption is that those processes fight over the list head of the
skb list and use therefore heavily spinlocks.



Cure
----
When I turned on CONFIG_PROVE_RCU the issue stopped. This option does
"select UNINLINE_SPIN_UNLOCK", and this uninline option is also selected
with the imx_v6_v7_defconfig. I actually don't care if RCUs are proven
or not, this just turns on the uninlining as a side-effect.



Question
--------
I don't have the slightest idea what produces the error and why
uninlining helps (I'm not deep in such internals), so I wonder how to
proceed.

Should I simply send in a patch that "select UNINLINE_SPIN_UNLOCK" on
i.MX6Q ???


From eballetbo at gmail.com  Tue May 31 00:48:32 2016
From: eballetbo at gmail.com (Enric Balletbo Serra)
Date: Tue, 31 May 2016 09:48:32 +0200
Subject: [PATCH 4/5] drm/bridge: Add driver for GE B850v3 LVDS/DP++ Bridge
In-Reply-To: <1464626385-19253-5-git-send-email-peter.senna@collabora.com>
References: <1464626385-19253-1-git-send-email-peter.senna@collabora.com>
 <1464626385-19253-5-git-send-email-peter.senna@collabora.com>
Message-ID: <CAFqH_52S99QNFc5EOrKRRbTPPoimTQTgQ81a-HV4=Pm+HSW1yg@mail.gmail.com>

Hi Peter,

Just some comments that I received when I submitted my bridge patches
and that I think can help you ...

2016-05-30 18:39 GMT+02:00 Peter Senna Tschudin <peter.senna at collabora.com>:
> This driver creates a drm_bridge and a drm_connector for the LVDS to DP++
> display bridge of the GE B850v3(imx6q-b850v3.dts). There are two physical
> bridges on the video signal pipeline: a STDP4028(LVDS to DP) and a
> STDP2690(DP to DP++). However the physical bridges are automatically
> configured by the input video signal, and the driver has no access to
> the video processing pipeline. The driver is only needed to read EDID
> from the STDP2690 and to handle HPD events from the STDP4028. The driver
> communicates with both bridges over i2c. The video signal pipeline is as
> follows:
>
>   Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
>
> Signed-off-by: Peter Senna Tschudin <peter.senna at collabora.com>
> ---
>  MAINTAINERS                                |   8 +
>  drivers/gpu/drm/bridge/Kconfig             |   8 +
>  drivers/gpu/drm/bridge/Makefile            |   1 +
>  drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c | 397 +++++++++++++++++++++++++++++
>  4 files changed, 414 insertions(+)
>  create mode 100644 drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 3273ffa..7bb5e89 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5009,6 +5009,14 @@ W:       https://linuxtv.org
>  S:     Maintained
>  F:     drivers/media/radio/radio-gemtek*
>
> +GENERAL ELECTRIC B850V3 LVDS/DP++ BRIDGE
> +M:     Martin Donnelly <martin.donnelly at ge.com>
> +M:     Peter Senna Tschudin <peter.senna at collabora.com>
> +M:     Martyn Welch <martyn.welch at collabora.co.uk>
> +S:     Maintained
> +F:     drivers/gpu/drm/bridge/ge_b850v3_dp2.c
> +F:     Documentation/devicetree/bindings/ge/b850v3_dp2_bridge.txt
> +
>  GENERIC GPIO I2C DRIVER
>  M:     Haavard Skinnemoen <hskinnemoen at gmail.com>
>  S:     Supported
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index 8f7423f..e9c32fc 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -52,4 +52,12 @@ config DRM_PARADE_PS8622
>
>  source "drivers/gpu/drm/bridge/analogix/Kconfig"
>
> +config DRM_GE_B850V3_LVDS_DP
> +       tristate "LVDS/DP bridge"
> +       depends on OF
> +       select DRM_KMS_HELPER
> +       select DRM_PANEL
> +       ---help---
> +         Driver for GE B850v3 DP2 LVDS to DP+ Bridge
> +

I think the maintainer prefers the entries ordered alphabetically (by
vendor, then name), so your config should go before "config
DRM_NXP_PTN3460"

>  endmenu
> diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
> index 96b13b3..ba2e355 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -6,3 +6,4 @@ obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
>  obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
>  obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
>  obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
> +obj-$(CONFIG_DRM_GE_B850V3_LVDS_DP) += ge_b850v3_lvds_dp.o

Same here,  this needs to be sorted by vendor, then name as well. Also
I think is preferred use hyphens like the others drivers.

Hmm, I see now that CONFIG_DRM_ANALOGIX_DP is not sorted, but I guess
the preferred is be sorted.

> diff --git a/drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c b/drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c
> new file mode 100644
> index 0000000..37a4e7a
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c
> @@ -0,0 +1,397 @@
> +/*
> + * Driver for GE B850v3 DP display bridge
> +
> + * Copyright (c) 2016, Collabora Ltd.
> + * Copyright (c) 2016, General Electric Company
> +
> + * 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/>.
> +
> + * This driver creates a drm_bridge and a drm_connector for the LVDS to DP++
> + * display bridge of the GE B850v3. There are two physical bridges on the video
> + * signal pipeline: a STDP4028(LVDS to DP) and a STDP2690(DP to DP++). However
> + * the physical bridges are automatically configured by the input video signal,
> + * and the driver has no access to the video processing pipeline. The driver is
> + * only needed to read EDID from the STDP2690 and to handle HPD events from the
> + * STDP4028. The driver communicates with both bridges over i2c. The video
> + * signal pipeline is as follows:
> + *
> + *   Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
> +
> + *
> + */
> +#include <linux/gpio.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include "drm_crtc.h"
> +#include "drm_crtc_helper.h"
> +#include "drm_edid.h"
> +#include "drmP.h"
> +
> +#define EDID_EXT_BLOCK_CNT 0x7E
> +
> +#define STDP4028_IRQ_OUT_CONF_REG 0x02
> +#define STDP4028_DPTX_IRQ_EN_REG 0x3C
> +#define STDP4028_DPTX_IRQ_STS_REG 0x3D
> +#define STDP4028_DPTX_STS_REG 0x3E
> +
> +#define STDP4028_DPTX_DP_IRQ_EN 0x1000
> +
> +#define STDP4028_DPTX_HOTPLUG_IRQ_EN 0x0400
> +#define STDP4028_DPTX_LINK_CH_IRQ_EN 0x2000
> +#define STDP4028_DPTX_IRQ_CONFIG \
> +               (STDP4028_DPTX_LINK_CH_IRQ_EN | STDP4028_DPTX_HOTPLUG_IRQ_EN)
> +
> +#define STDP4028_DPTX_HOTPLUG_STS 0x0200
> +#define STDP4028_DPTX_LINK_STS 0x1000
> +#define STDP4028_CON_STATE_CONNECTED \
> +               (STDP4028_DPTX_HOTPLUG_STS | STDP4028_DPTX_LINK_STS)
> +
> +#define STDP4028_DPTX_HOTPLUG_CH_STS 0x0400
> +#define STDP4028_DPTX_LINK_CH_STS 0x2000
> +#define STDP4028_DPTX_IRQ_CLEAR \
> +               (STDP4028_DPTX_LINK_CH_STS | STDP4028_DPTX_HOTPLUG_CH_STS)
> +
> +struct ge_b850v3_lvds_dp {
> +       struct drm_connector connector;
> +       struct drm_bridge bridge;
> +       struct i2c_client *ge_b850v3_lvds_dp_i2c;
> +       struct i2c_client *edid_i2c;
> +       struct edid *edid;
> +};
> +
> +static inline struct ge_b850v3_lvds_dp *
> +               bridge_to_ge_b850v3_lvds_dp(struct drm_bridge *bridge)
> +{
> +       return container_of(bridge, struct ge_b850v3_lvds_dp, bridge);
> +}
> +
> +static inline struct ge_b850v3_lvds_dp *
> +               connector_to_ge_b850v3_lvds_dp(struct drm_connector *connector)
> +{
> +       return container_of(connector, struct ge_b850v3_lvds_dp, connector);
> +}
> +
> +static void ge_b850v3_lvds_dp_pre_enable(struct drm_bridge *bridge)
> +{
> +}
> +

You don't need to keep empty callbacks for the (pre/post)
enable/disable drm_bridge ops anymore so you can remove this function
and the below.

> +static void ge_b850v3_lvds_dp_enable(struct drm_bridge *bridge)
> +{
> +}
> +
> +static void ge_b850v3_lvds_dp_disable(struct drm_bridge *bridge)
> +{
> +}
> +
> +static void ge_b850v3_lvds_dp_post_disable(struct drm_bridge *bridge)
> +{
> +}
> +
> +u8 *stdp2690_get_edid(struct i2c_client *client)
> +{
> +       struct i2c_adapter *adapter = client->adapter;
> +       unsigned char start = 0x00;
> +       unsigned int total_size;
> +       u8 *block = kmalloc(EDID_LENGTH, GFP_KERNEL);
> +
> +       struct i2c_msg msgs[] = {
> +               {
> +                       .addr   = client->addr,
> +                       .flags  = 0,
> +                       .len    = 1,
> +                       .buf    = &start,
> +               }, {
> +                       .addr   = client->addr,
> +                       .flags  = I2C_M_RD,
> +                       .len    = EDID_LENGTH,
> +                       .buf    = block,
> +               }
> +       };
> +
> +       if (!block)
> +               return NULL;
> +
> +       if (i2c_transfer(adapter, msgs, 2) != 2) {
> +               DRM_ERROR("Unable to read EDID.\n");
> +               goto err;
> +       }
> +
> +       if (!drm_edid_block_valid(block, 0, false, NULL)) {
> +               DRM_ERROR("Invalid EDID block\n");
> +               goto err;
> +       }
> +
> +       total_size = (block[EDID_EXT_BLOCK_CNT] + 1) * EDID_LENGTH;
> +       if (total_size > EDID_LENGTH) {
> +               kfree(block);
> +               block = kmalloc(total_size, GFP_KERNEL);
> +               if (!block)
> +                       return NULL;
> +
> +               /* Yes, read the entire buffer, and do not skip the first
> +                * EDID_LENGTH bytes.
> +                */
> +               start = 0x00;
> +               msgs[1].len = total_size;
> +               msgs[1].buf = block;
> +
> +               if (i2c_transfer(adapter, msgs, 2) != 2) {
> +                       DRM_ERROR("Unable to read EDID extension blocks.\n");
> +                       goto err;
> +               }
> +       }
> +
> +       return block;
> +
> +err:
> +       kfree(block);
> +       return NULL;
> +}
> +
> +static int ge_b850v3_lvds_dp_get_modes(struct drm_connector *connector)
> +{
> +       struct ge_b850v3_lvds_dp *ptn_bridge;
> +       struct i2c_client *client;
> +       u8 *block;
> +       int num_modes;
> +
> +       ptn_bridge = connector_to_ge_b850v3_lvds_dp(connector);

Move this assignation to ptn_bridge declaration

> +       client = ptn_bridge->edid_i2c;
> +
> +       block = stdp2690_get_edid(client);

I think you can remove the client variable and pass
ptn_bridge->edid_i2c directly to the stdp2690_get_edid function.

Note that get_modes is called several times and can be called from
userspace, you are allocating memory on every call to get_modes that I
think is not released or I'm missing something?

> +       ptn_bridge->edid = (struct edid *) block;
> +

What if block is NULL here ?

> +       drm_mode_connector_update_edid_property(connector, ptn_bridge->edid);
> +       num_modes = drm_add_edid_modes(connector, ptn_bridge->edid);
> +
> +       return num_modes;

nit: return drm_add_edid_modes(connector, ptn_bridge->edid); ? And
remove num_modes ?

> +}
> +
> +static struct drm_encoder
> +*ge_b850v3_lvds_dp_best_encoder(struct drm_connector *connector)
> +{
> +       struct ge_b850v3_lvds_dp *ptn_bridge =
> +               connector_to_ge_b850v3_lvds_dp(connector);
> +
> +       return ptn_bridge->bridge.encoder;
> +}
> +
> +static const struct
> +drm_connector_helper_funcs ge_b850v3_lvds_dp_connector_helper_funcs = {
> +       .get_modes = ge_b850v3_lvds_dp_get_modes,
> +       .best_encoder = ge_b850v3_lvds_dp_best_encoder,
> +};
> +
> +static enum drm_connector_status ge_b850v3_lvds_dp_detect(
> +               struct drm_connector *connector, bool force)
> +{
> +       struct ge_b850v3_lvds_dp *ptn_bridge =
> +                       connector_to_ge_b850v3_lvds_dp(connector);
> +       struct i2c_client *ge_b850v3_lvds_dp_i2c =
> +                       ptn_bridge->ge_b850v3_lvds_dp_i2c;
> +       s32 link_state;
> +
> +       link_state = i2c_smbus_read_word_data(ge_b850v3_lvds_dp_i2c,
> +                       STDP4028_DPTX_STS_REG);
> +
> +       if (link_state == STDP4028_CON_STATE_CONNECTED)
> +               return connector_status_connected;
> +
> +       if (link_state == 0)
> +               return connector_status_disconnected;
> +
> +       return connector_status_unknown;
> +}
> +
> +static void ge_b850v3_lvds_dp_connector_force(struct drm_connector *connector)
> +{
> +}
> +

Guess you can remove this empty callback.

> +static void ge_b850v3_lvds_dp_connector_destroy(struct drm_connector *connector)
> +{
> +       drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_funcs ge_b850v3_lvds_dp_connector_funcs = {
> +       .dpms = drm_helper_connector_dpms,
> +       .fill_modes = drm_helper_probe_single_connector_modes,
> +       .detect = ge_b850v3_lvds_dp_detect,
> +       .destroy = ge_b850v3_lvds_dp_connector_destroy,
> +       .force = ge_b850v3_lvds_dp_connector_force,

Remove .force

> +};
> +
> +static irqreturn_t ge_b850v3_lvds_dp_irq_handler(int irq, void *dev_id)
> +{
> +       struct ge_b850v3_lvds_dp *ptn_bridge = dev_id;
> +       struct i2c_client *ge_b850v3_lvds_dp_i2c
> +                       = ptn_bridge->ge_b850v3_lvds_dp_i2c;
> +
> +       i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> +                       STDP4028_DPTX_IRQ_STS_REG, STDP4028_DPTX_IRQ_CLEAR);
> +
> +       if (ptn_bridge->connector.dev)
> +               drm_kms_helper_hotplug_event(ptn_bridge->connector.dev);
> +
> +       return IRQ_HANDLED;
> +

Remove the empty line.

> +}
> +
> +static int ge_b850v3_lvds_dp_attach(struct drm_bridge *bridge)
> +{
> +       struct ge_b850v3_lvds_dp *ptn_bridge
> +                       = bridge_to_ge_b850v3_lvds_dp(bridge);
> +       struct drm_connector *connector = &ptn_bridge->connector;
> +       struct i2c_client *ge_b850v3_lvds_dp_i2c
> +                       = ptn_bridge->ge_b850v3_lvds_dp_i2c;
> +       int ret;
> +
> +       if (!bridge->encoder) {
> +               DRM_ERROR("Parent encoder object not found");
> +               return -ENODEV;
> +       }
> +
> +       connector->polled = DRM_CONNECTOR_POLL_HPD;
> +
> +       drm_connector_helper_add(connector,
> +                       &ge_b850v3_lvds_dp_connector_helper_funcs);
> +
> +       ret = drm_connector_init(bridge->dev, connector,
> +                       &ge_b850v3_lvds_dp_connector_funcs,
> +                       DRM_MODE_CONNECTOR_DisplayPort);
> +       if (ret) {
> +               DRM_ERROR("Failed to initialize connector with drm\n");
> +               return ret;
> +       }
> +
> +       ret = drm_mode_connector_attach_encoder(connector, bridge->encoder);
> +       if (ret)
> +               return ret;
> +
> +       drm_bridge_enable(bridge);
> +       if (ge_b850v3_lvds_dp_i2c->irq) {
> +               drm_helper_hpd_irq_event(connector->dev);
> +
> +               ret = devm_request_threaded_irq(&ge_b850v3_lvds_dp_i2c->dev,
> +                               ge_b850v3_lvds_dp_i2c->irq, NULL,
> +                               ge_b850v3_lvds_dp_irq_handler,
> +                               IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
> +                               "ge_b850v3_lvds_dp", ptn_bridge);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct drm_bridge_funcs ge_b850v3_lvds_dp_funcs = {
> +       .pre_enable = ge_b850v3_lvds_dp_pre_enable,
> +       .enable = ge_b850v3_lvds_dp_enable,
> +       .disable = ge_b850v3_lvds_dp_disable,
> +       .post_disable = ge_b850v3_lvds_dp_post_disable,

Remove the above empty callbacks.

> +       .attach = ge_b850v3_lvds_dp_attach,
> +};
> +
> +static int ge_b850v3_lvds_dp_probe(struct i2c_client *ge_b850v3_lvds_dp_i2c,
> +                               const struct i2c_device_id *id)
> +{
> +       struct device *dev = &ge_b850v3_lvds_dp_i2c->dev;
> +       struct ge_b850v3_lvds_dp *ptn_bridge;
> +

Remove this empty line between these two blocks.

> +       int ret;
> +       u32 edid_i2c_reg;
> +
> +       ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL);
> +       if (!ptn_bridge)
> +               return -ENOMEM;
> +
> +       ptn_bridge->ge_b850v3_lvds_dp_i2c = ge_b850v3_lvds_dp_i2c;
> +       ptn_bridge->bridge.driver_private = ptn_bridge;
> +       i2c_set_clientdata(ge_b850v3_lvds_dp_i2c, ptn_bridge);
> +
> +       ret = of_property_read_u32(dev->of_node, "edid-reg", &edid_i2c_reg);
> +       if (ret) {
> +               dev_err(dev, "edid-reg not specified, aborting...\n");

Use DRM_ERROR?

> +               return -ENODEV;
> +       }
> +
> +       ptn_bridge->edid_i2c = devm_kzalloc(dev,
> +                       sizeof(struct i2c_client), GFP_KERNEL);
> +
> +       if (!ptn_bridge->edid_i2c)
> +               return -ENOMEM;
> +
> +       memcpy(ptn_bridge->edid_i2c, ge_b850v3_lvds_dp_i2c,
> +                       sizeof(struct i2c_client));
> +
> +       ptn_bridge->edid_i2c->addr = (unsigned short) edid_i2c_reg;
> +

Remove empty line.

> +
> +       /* Configures the bridge to re-enable interrupts after each ack */
> +       i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> +                       STDP4028_IRQ_OUT_CONF_REG, STDP4028_DPTX_DP_IRQ_EN);
> +       i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> +                       STDP4028_DPTX_IRQ_EN_REG, STDP4028_DPTX_IRQ_CONFIG);
> +
> +       /* Clear pending interrupts since power up. */
> +       i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> +                       STDP4028_DPTX_IRQ_STS_REG, STDP4028_DPTX_IRQ_CLEAR);
> +
> +       ptn_bridge->bridge.funcs = &ge_b850v3_lvds_dp_funcs;
> +       ptn_bridge->bridge.of_node = dev->of_node;
> +       ret = drm_bridge_add(&ptn_bridge->bridge);
> +       if (ret) {
> +               DRM_ERROR("Failed to add bridge\n");
> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static int ge_b850v3_lvds_dp_remove(struct i2c_client *ge_b850v3_lvds_dp_i2c)
> +{
> +       struct ge_b850v3_lvds_dp *ptn_bridge =
> +               i2c_get_clientdata(ge_b850v3_lvds_dp_i2c);
> +
> +       drm_bridge_remove(&ptn_bridge->bridge);
> +
> +       return 0;
> +}
> +
> +static const struct i2c_device_id ge_b850v3_lvds_dp_i2c_table[] = {
> +       {"b850v3_lvds_dp", 0},
> +       {},
> +};
> +MODULE_DEVICE_TABLE(i2c, ge_b850v3_lvds_dp_i2c_table);
> +
> +static const struct of_device_id ge_b850v3_lvds_dp_match[] = {
> +       { .compatible = "ge,b850v3_lvds_dp" },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, ge_b850v3_lvds_dp_match);
> +
> +static struct i2c_driver ge_b850v3_lvds_dp_driver = {
> +       .id_table       = ge_b850v3_lvds_dp_i2c_table,
> +       .probe          = ge_b850v3_lvds_dp_probe,
> +       .remove         = ge_b850v3_lvds_dp_remove,
> +       .driver         = {
> +               .name           = "ge,b850v3_lvds_dp",
> +               .of_match_table = ge_b850v3_lvds_dp_match,
> +       },
> +};
> +module_i2c_driver(ge_b850v3_lvds_dp_driver);
> +
> +MODULE_AUTHOR("Peter Senna Tschudin <peter.senna at collabora.com>");
> +MODULE_AUTHOR("Martyn Welch <martyn.welch at collabora.co.uk>");
> +MODULE_DESCRIPTION("GE LVDS to DP++ bridge)");
> +MODULE_LICENSE("GPL v2");
> --
> 2.5.5
>

Best regards,
   Enric


From linus.walleij at linaro.org  Tue May 31 01:06:54 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 10:06:54 +0200
Subject: [PATCH v2] pinctrl: stm32: factorize
 stm32_pconf_input/output_get()
In-Reply-To: <1464091063-22341-2-git-send-email-patrice.chotard@st.com>
References: <1464091063-22341-1-git-send-email-patrice.chotard@st.com>
 <1464091063-22341-2-git-send-email-patrice.chotard@st.com>
Message-ID: <CACRpkdY0Z7J347u1UkdYKpbKCga_JiJ+bKmULXAv2rWyb24cmA@mail.gmail.com>

On Tue, May 24, 2016 at 1:57 PM,  <patrice.chotard at st.com> wrote:

> From: Patrice Chotard <patrice.chotard at st.com>
>
> As these 2 functions code are 95% similar, factorize them.
>
> Signed-off-by: Patrice Chotard <patrice.chotard at st.com>

Patch applied with Maxime's ACK.

Yours,
Linus Walleij


From yamada.masahiro at socionext.com  Tue May 31 01:05:16 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:16 +0900
Subject: [PATCH 10/17] pinctrl: uniphier: introduce capability flag
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-11-git-send-email-yamada.masahiro@socionext.com>

The core part of the UniPhier pinctrl driver needs to support a new
capability for upcoming UniPhier ARMv8 SoCs.  This sometimes happens
because pinctrl drivers include really SoC-specific stuff.

This commit intends to tidy up SoC-specific parameters of the existing
drivers before adding the new one.  Having just one flag would be
better than adding a new struct member every time a new SoC-specific
capability comes up.

At this time, there is one flag, UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE.
This capability (I'd say rather quirk) was added for PH1-Pro4 and
PH1-Pro5 as requirement from a customer.  For those SoCs, one pin-mux
setting is controlled by the combination of two separate registers; the
LSB bits at register offset (8 * N) and the MSB bits at (8 * N + 4).
Because it is impossible to update two separate registers atomically,
the LOAD_PINCTRL register should be set in order to make the pin-mux
settings really effective.

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 35 +++++++++++++++++-------
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c  |  4 +--
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c |  4 +--
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c |  4 +--
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c |  4 +--
 drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c |  4 +--
 drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c |  4 +--
 drivers/pinctrl/uniphier/pinctrl-uniphier.h      |  6 ++--
 8 files changed, 34 insertions(+), 31 deletions(-)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 39e3375..ca2562a 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -552,9 +552,8 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
 				    unsigned muxval)
 {
 	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
-	unsigned mux_bits = priv->socdata->mux_bits;
-	unsigned reg_stride = priv->socdata->reg_stride;
-	unsigned reg, reg_end, shift, mask;
+	unsigned int mux_bits, reg_stride, reg, reg_end, shift, mask;
+	bool load_pinctrl;
 	int ret;
 
 	/* some pins need input-enabling */
@@ -563,6 +562,26 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
 	if (ret)
 		return ret;
 
+	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
+		/*
+		 *  Mode     reg_offset     bit_position
+		 *  Normal    4 * n        shift+3:shift
+		 *  Debug     4 * n        shift+7:shift+4
+		 */
+		mux_bits = 4;
+		reg_stride = 8;
+		load_pinctrl = true;
+	} else {
+		/*
+		 *  Mode     reg_offset     bit_position
+		 *  Normal    8 * n        shift+3:shift
+		 *  Debug     8 * n + 4    shift+3:shift
+		 */
+		mux_bits = 8;
+		reg_stride = 4;
+		load_pinctrl = false;
+	}
+
 	reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
 	reg_end = reg + reg_stride;
 	shift = pin * mux_bits % 32;
@@ -580,7 +599,7 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
 		muxval >>= mux_bits;
 	}
 
-	if (priv->socdata->load_pinctrl) {
+	if (load_pinctrl) {
 		ret = regmap_write(priv->regmap,
 				   UNIPHIER_PINCTRL_LOAD_PINMUX, 1);
 		if (ret)
@@ -658,12 +677,8 @@ int uniphier_pinctrl_probe(struct platform_device *pdev,
 
 	if (!socdata ||
 	    !socdata->pins || !socdata->npins ||
-	    !socdata->groups ||
-	    !socdata->groups_count ||
-	    !socdata->functions ||
-	    !socdata->functions_count ||
-	    !socdata->mux_bits ||
-	    !socdata->reg_stride) {
+	    !socdata->groups || !socdata->groups_count ||
+	    !socdata->functions || !socdata->functions_count) {
 		dev_err(dev, "pinctrl socdata lacks necessary members\n");
 		return -EINVAL;
 	}
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
index 4ada574..edea90d 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
@@ -852,9 +852,7 @@ static struct uniphier_pinctrl_socdata uniphier_ld4_pindata = {
 	.groups_count = ARRAY_SIZE(uniphier_ld4_groups),
 	.functions = uniphier_ld4_functions,
 	.functions_count = ARRAY_SIZE(uniphier_ld4_functions),
-	.mux_bits = 8,
-	.reg_stride = 4,
-	.load_pinctrl = false,
+	.caps = 0,
 };
 
 static int uniphier_ld4_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
index 7ae42a4..2c9747b 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
@@ -1240,9 +1240,7 @@ static struct uniphier_pinctrl_socdata uniphier_ld6b_pindata = {
 	.groups_count = ARRAY_SIZE(uniphier_ld6b_groups),
 	.functions = uniphier_ld6b_functions,
 	.functions_count = ARRAY_SIZE(uniphier_ld6b_functions),
-	.mux_bits = 8,
-	.reg_stride = 4,
-	.load_pinctrl = false,
+	.caps = 0,
 };
 
 static int uniphier_ld6b_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
index 3735eb7..547359e 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
@@ -1526,9 +1526,7 @@ static struct uniphier_pinctrl_socdata uniphier_pro4_pindata = {
 	.groups_count = ARRAY_SIZE(uniphier_pro4_groups),
 	.functions = uniphier_pro4_functions,
 	.functions_count = ARRAY_SIZE(uniphier_pro4_functions),
-	.mux_bits = 4,
-	.reg_stride = 8,
-	.load_pinctrl = true,
+	.caps = UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE,
 };
 
 static int uniphier_pro4_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index 7a883161..080332d 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -1317,9 +1317,7 @@ static struct uniphier_pinctrl_socdata uniphier_pro5_pindata = {
 	.groups_count = ARRAY_SIZE(uniphier_pro5_groups),
 	.functions = uniphier_pro5_functions,
 	.functions_count = ARRAY_SIZE(uniphier_pro5_functions),
-	.mux_bits = 4,
-	.reg_stride = 8,
-	.load_pinctrl = true,
+	.caps = UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE,
 };
 
 static int uniphier_pro5_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
index d8190e8..a2bf3f7 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
@@ -1235,9 +1235,7 @@ static struct uniphier_pinctrl_socdata uniphier_pxs2_pindata = {
 	.groups_count = ARRAY_SIZE(uniphier_pxs2_groups),
 	.functions = uniphier_pxs2_functions,
 	.functions_count = ARRAY_SIZE(uniphier_pxs2_functions),
-	.mux_bits = 8,
-	.reg_stride = 4,
-	.load_pinctrl = false,
+	.caps = 0,
 };
 
 static int uniphier_pxs2_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
index d2c4d90..ef86693 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
@@ -760,9 +760,7 @@ static struct uniphier_pinctrl_socdata uniphier_sld8_pindata = {
 	.groups_count = ARRAY_SIZE(uniphier_sld8_groups),
 	.functions = uniphier_sld8_functions,
 	.functions_count = ARRAY_SIZE(uniphier_sld8_functions),
-	.mux_bits = 8,
-	.reg_stride = 4,
-	.load_pinctrl = false,
+	.caps = 0,
 };
 
 static int uniphier_sld8_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
index eca379a..3fd5020 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
@@ -15,6 +15,7 @@
 #ifndef __PINCTRL_UNIPHIER_H__
 #define __PINCTRL_UNIPHIER_H__
 
+#include <linux/bitops.h>
 #include <linux/bug.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -164,9 +165,8 @@ struct uniphier_pinctrl_socdata {
 	int groups_count;
 	const struct uniphier_pinmux_function *functions;
 	int functions_count;
-	unsigned mux_bits;
-	unsigned reg_stride;
-	bool load_pinctrl;
+	unsigned int caps;
+#define UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE	BIT(0)
 };
 
 #define UNIPHIER_PINCTRL_PIN(a, b, c, d, e, f, g)			\
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:14 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:14 +0900
Subject: [PATCH 08/17] pinctrl: uniphier: support 3-bit drive strength control
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-9-git-send-email-yamada.masahiro@socionext.com>

The new ARMv8 SoC, PH1-LD20, supports more fine-grained drive
strength control.  Drive strength of some pins are controlled by
3-bit width registers (8-level granularity).

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 25 ++++++++++++++++++------
 drivers/pinctrl/uniphier/pinctrl-uniphier.h      |  2 ++
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 7f7274e..017b84f 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -94,6 +94,9 @@ static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
 	case UNIPHIER_PIN_DRV_2BIT:
 		drv_type = "8/12/16/20(mA)";
 		break;
+	case UNIPHIER_PIN_DRV_3BIT:
+		drv_type = "4/5/7/9/11/12/14/16(mA)";
+		break;
 	case UNIPHIER_PIN_DRV_FIXED4:
 		drv_type = "4(mA)";
 		break;
@@ -184,6 +187,7 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
 				uniphier_pin_get_drv_type(pin->drv_data);
 	const unsigned int strength_1bit[] = {4, 8};
 	const unsigned int strength_2bit[] = {8, 12, 16, 20};
+	const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12, 14, 16};
 	const unsigned int *supported_strength;
 	unsigned int drvctrl, reg, shift, mask, width, val;
 	int ret;
@@ -191,12 +195,19 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
 	switch (type) {
 	case UNIPHIER_PIN_DRV_1BIT:
 		supported_strength = strength_1bit;
+		reg = UNIPHIER_PINCTRL_DRVCTRL_BASE;
 		width = 1;
 		break;
 	case UNIPHIER_PIN_DRV_2BIT:
 		supported_strength = strength_2bit;
+		reg = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
 		width = 2;
 		break;
+	case UNIPHIER_PIN_DRV_3BIT:
+		supported_strength = strength_3bit;
+		reg = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
+		width = 4;
+		break;
 	case UNIPHIER_PIN_DRV_FIXED4:
 		*strength = 4;
 		return 0;
@@ -214,9 +225,6 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
 	drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
 	drvctrl *= width;
 
-	reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE :
-			     UNIPHIER_PINCTRL_DRVCTRL_BASE;
-
 	reg += drvctrl / 32 * 4;
 	shift = drvctrl % 32;
 	mask = (1U << width) - 1;
@@ -368,18 +376,26 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
 				uniphier_pin_get_drv_type(pin->drv_data);
 	const unsigned int strength_1bit[] = {4, 8, -1};
 	const unsigned int strength_2bit[] = {8, 12, 16, 20, -1};
+	const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12, 14, 16, -1};
 	const unsigned int *supported_strength;
 	unsigned int drvctrl, reg, shift, mask, width, val;
 
 	switch (type) {
 	case UNIPHIER_PIN_DRV_1BIT:
 		supported_strength = strength_1bit;
+		reg = UNIPHIER_PINCTRL_DRVCTRL_BASE;
 		width = 1;
 		break;
 	case UNIPHIER_PIN_DRV_2BIT:
 		supported_strength = strength_2bit;
+		reg = UNIPHIER_PINCTRL_DRV2CTRL_BASE;
 		width = 2;
 		break;
+	case UNIPHIER_PIN_DRV_3BIT:
+		supported_strength = strength_3bit;
+		reg = UNIPHIER_PINCTRL_DRV3CTRL_BASE;
+		width = 4;
+		break;
 	default:
 		dev_err(pctldev->dev,
 			"cannot change drive strength for pin %u (%s)\n",
@@ -404,9 +420,6 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
 	drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
 	drvctrl *= width;
 
-	reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE :
-			     UNIPHIER_PINCTRL_DRVCTRL_BASE;
-
 	reg += drvctrl / 32 * 4;
 	shift = drvctrl % 32;
 	mask = (1U << width) - 1;
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
index 7f3e7ff..eca379a 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
@@ -25,6 +25,7 @@ struct platform_device;
 #define UNIPHIER_PINCTRL_LOAD_PINMUX	0x700
 #define UNIPHIER_PINCTRL_DRVCTRL_BASE	0x800
 #define UNIPHIER_PINCTRL_DRV2CTRL_BASE	0x900
+#define UNIPHIER_PINCTRL_DRV3CTRL_BASE	0x980
 #define UNIPHIER_PINCTRL_PUPDCTRL_BASE	0xa00
 #define UNIPHIER_PINCTRL_IECTRL		0xd00
 
@@ -72,6 +73,7 @@ struct platform_device;
 enum uniphier_pin_drv_type {
 	UNIPHIER_PIN_DRV_1BIT,		/* 2 level control: 4/8 mA */
 	UNIPHIER_PIN_DRV_2BIT,		/* 4 level control: 8/12/16/20 mA */
+	UNIPHIER_PIN_DRV_3BIT,		/* 8 level control: 4/5/7/9/11/12/14/16 mA */
 	UNIPHIER_PIN_DRV_FIXED4,	/* fixed to 4mA */
 	UNIPHIER_PIN_DRV_FIXED5,	/* fixed to 5mA */
 	UNIPHIER_PIN_DRV_FIXED8,	/* fixed to 8mA */
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:10 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:10 +0900
Subject: [PATCH 04/17] pinctrl: uniphier: set pinctrl_desc owner in common
 probe function
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-5-git-send-email-yamada.masahiro@socionext.com>

The owner of the struct pinctrl_desc matches that of platform_driver.
Set it in the common probe function.

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 1 +
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c  | 1 -
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c | 1 -
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c | 1 -
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c | 1 -
 drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c | 1 -
 drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c | 1 -
 7 files changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 5d08de0..ab89efb 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -670,6 +670,7 @@ int uniphier_pinctrl_probe(struct platform_device *pdev,
 	desc->pctlops = &uniphier_pctlops;
 	desc->pmxops = &uniphier_pmxops;
 	desc->confops = &uniphier_confops;
+	desc->owner = dev->driver->owner;
 
 	priv->pctldev = devm_pinctrl_register(dev, desc, priv);
 	if (IS_ERR(priv->pctldev)) {
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
index ad193c7..5353ce4 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
@@ -861,7 +861,6 @@ static struct pinctrl_desc uniphier_ld4_pinctrl_desc = {
 	.name = DRIVER_NAME,
 	.pins = uniphier_ld4_pins,
 	.npins = ARRAY_SIZE(uniphier_ld4_pins),
-	.owner = THIS_MODULE,
 };
 
 static int uniphier_ld4_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
index 0782a6d..c405960 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
@@ -1249,7 +1249,6 @@ static struct pinctrl_desc uniphier_ld6b_pinctrl_desc = {
 	.name = DRIVER_NAME,
 	.pins = uniphier_ld6b_pins,
 	.npins = ARRAY_SIZE(uniphier_ld6b_pins),
-	.owner = THIS_MODULE,
 };
 
 static int uniphier_ld6b_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
index 2d45307..54b08d5 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
@@ -1535,7 +1535,6 @@ static struct pinctrl_desc uniphier_pro4_pinctrl_desc = {
 	.name = DRIVER_NAME,
 	.pins = uniphier_pro4_pins,
 	.npins = ARRAY_SIZE(uniphier_pro4_pins),
-	.owner = THIS_MODULE,
 };
 
 static int uniphier_pro4_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index 8452dad..19b15db 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -1326,7 +1326,6 @@ static struct pinctrl_desc uniphier_pro5_pinctrl_desc = {
 	.name = DRIVER_NAME,
 	.pins = uniphier_pro5_pins,
 	.npins = ARRAY_SIZE(uniphier_pro5_pins),
-	.owner = THIS_MODULE,
 };
 
 static int uniphier_pro5_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
index 89d3fdb..762de0e 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
@@ -1244,7 +1244,6 @@ static struct pinctrl_desc uniphier_pxs2_pinctrl_desc = {
 	.name = DRIVER_NAME,
 	.pins = uniphier_pxs2_pins,
 	.npins = ARRAY_SIZE(uniphier_pxs2_pins),
-	.owner = THIS_MODULE,
 };
 
 static int uniphier_pxs2_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
index ab635f2..9fe8762 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
@@ -769,7 +769,6 @@ static struct pinctrl_desc uniphier_sld8_pinctrl_desc = {
 	.name = DRIVER_NAME,
 	.pins = uniphier_sld8_pins,
 	.npins = ARRAY_SIZE(uniphier_sld8_pins),
-	.owner = THIS_MODULE,
 };
 
 static int uniphier_sld8_pinctrl_probe(struct platform_device *pdev)
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:21 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:21 +0900
Subject: [PATCH 15/17] pinctrl: uniphier: allow to have pinctrl node under
 syscon node
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-16-git-send-email-yamada.masahiro@socionext.com>

Currently, the UniPhier pinctrl driver itself is a syscon, but it
turned out much more reasonable to make it a child node of a syscon
because our syscon node consists of a bunch of system configuration
registers, not only pinctrl, but also phy, and misc registers.
It is difficult to split the node.

To allow to migrate to the new DT structure, this commit adds new
compatible strings to not disturb the existing DT.  After a while,
the old binding will be removed.

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 38 ++++++++++++++++++------
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c  |  1 +
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c |  1 +
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c |  1 +
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c |  1 +
 drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c |  1 +
 drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c |  1 +
 7 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 5bfcfa8..9b2ee71 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -14,6 +14,7 @@
 
 #include <linux/export.h>
 #include <linux/mfd/syscon.h>
+#include <linux/of.h>
 #include <linux/pinctrl/pinconf.h>
 #include <linux/pinctrl/pinconf-generic.h>
 #include <linux/pinctrl/pinctrl.h>
@@ -29,6 +30,7 @@ struct uniphier_pinctrl_priv {
 	struct pinctrl_desc pctldesc;
 	struct pinctrl_dev *pctldev;
 	struct regmap *regmap;
+	unsigned int regbase;
 	struct uniphier_pinctrl_socdata *socdata;
 };
 
@@ -169,7 +171,7 @@ static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
 	reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
 	shift = pupdctrl % 32;
 
-	ret = regmap_read(priv->regmap, reg, &val);
+	ret = regmap_read(priv->regmap, priv->regbase + reg, &val);
 	if (ret)
 		return ret;
 
@@ -229,7 +231,7 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
 	shift = drvctrl % 32;
 	mask = (1U << width) - 1;
 
-	ret = regmap_read(priv->regmap, reg, &val);
+	ret = regmap_read(priv->regmap, priv->regbase + reg, &val);
 	if (ret)
 		return ret;
 
@@ -250,7 +252,8 @@ static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev *pctldev,
 		/* This pin is always input-enabled. */
 		return 0;
 
-	ret = regmap_read(priv->regmap, UNIPHIER_PINCTRL_IECTRL, &val);
+	ret = regmap_read(priv->regmap,
+			  priv->regbase + UNIPHIER_PINCTRL_IECTRL, &val);
 	if (ret)
 		return ret;
 
@@ -363,7 +366,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
 	reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
 	shift = pupdctrl % 32;
 
-	return regmap_update_bits(priv->regmap, reg, 1 << shift, val << shift);
+	return regmap_update_bits(priv->regmap, priv->regbase + reg,
+				  1 << shift, val << shift);
 }
 
 static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
@@ -423,7 +427,7 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
 	shift = drvctrl % 32;
 	mask = (1U << width) - 1;
 
-	return regmap_update_bits(priv->regmap, reg,
+	return regmap_update_bits(priv->regmap, priv->regbase + reg,
 				  mask << shift, val << shift);
 }
 
@@ -447,7 +451,7 @@ static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev,
 	if (iectrl == UNIPHIER_PIN_IECTRL_NONE)
 		return enable ? 0 : -EINVAL;
 
-	reg = UNIPHIER_PINCTRL_IECTRL + iectrl / 32 * 4;
+	reg = priv->regbase + UNIPHIER_PINCTRL_IECTRL + iectrl / 32 * 4;
 	mask = BIT(iectrl % 32);
 
 	return regmap_update_bits(priv->regmap, reg, mask, enable ? mask : 0);
@@ -597,7 +601,7 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
 	 * stored in the offset+4.
 	 */
 	for (; reg < reg_end; reg += 4) {
-		ret = regmap_update_bits(priv->regmap, reg,
+		ret = regmap_update_bits(priv->regmap, priv->regbase + reg,
 					 mask << shift, muxval << shift);
 		if (ret)
 			return ret;
@@ -606,7 +610,8 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
 
 	if (load_pinctrl) {
 		ret = regmap_write(priv->regmap,
-				   UNIPHIER_PINCTRL_LOAD_PINMUX, 1);
+				   priv->regbase + UNIPHIER_PINCTRL_LOAD_PINMUX,
+				   1);
 		if (ret)
 			return ret;
 	}
@@ -679,6 +684,7 @@ int uniphier_pinctrl_probe(struct platform_device *pdev,
 {
 	struct device *dev = &pdev->dev;
 	struct uniphier_pinctrl_priv *priv;
+	struct device_node *parent;
 
 	if (!socdata ||
 	    !socdata->pins || !socdata->npins ||
@@ -692,7 +698,21 @@ int uniphier_pinctrl_probe(struct platform_device *pdev,
 	if (!priv)
 		return -ENOMEM;
 
-	priv->regmap = syscon_node_to_regmap(dev->of_node);
+	if (of_device_is_compatible(dev->of_node, "socionext,ph1-ld4-pinctrl") ||
+	    of_device_is_compatible(dev->of_node, "socionext,ph1-pro4-pinctrl") ||
+	    of_device_is_compatible(dev->of_node, "socionext,ph1-sld8-pinctrl") ||
+	    of_device_is_compatible(dev->of_node, "socionext,ph1-pro5-pinctrl") ||
+	    of_device_is_compatible(dev->of_node, "socionext,proxstream2-pinctrl") ||
+	    of_device_is_compatible(dev->of_node, "socionext,ph1-ld6b-pinctrl")) {
+		/* old binding */
+		priv->regmap = syscon_node_to_regmap(dev->of_node);
+	} else {
+		priv->regbase = 0x1000;
+		parent = of_get_parent(dev->of_node);
+		priv->regmap = syscon_node_to_regmap(parent);
+		of_node_put(parent);
+	}
+
 	if (IS_ERR(priv->regmap)) {
 		dev_err(dev, "failed to get regmap\n");
 		return PTR_ERR(priv->regmap);
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
index 7437483..98044bc 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
@@ -914,6 +914,7 @@ static int uniphier_ld4_pinctrl_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id uniphier_ld4_pinctrl_match[] = {
+	{ .compatible = "socionext,uniphier-ld4-pinctrl" },
 	{ .compatible = "socionext,ph1-ld4-pinctrl" },
 	{ /* sentinel */ }
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
index d575194..6c0d66c 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
@@ -1275,6 +1275,7 @@ static int uniphier_ld6b_pinctrl_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id uniphier_ld6b_pinctrl_match[] = {
+	{ .compatible = "socionext,uniphier-ld6b-pinctrl" },
 	{ .compatible = "socionext,ph1-ld6b-pinctrl" },
 	{ /* sentinel */ }
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
index 35c5c51..8c61493 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
@@ -1573,6 +1573,7 @@ static int uniphier_pro4_pinctrl_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id uniphier_pro4_pinctrl_match[] = {
+	{ .compatible = "socionext,uniphier-pro4-pinctrl" },
 	{ .compatible = "socionext,ph1-pro4-pinctrl" },
 	{ /* sentinel */ }
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index f94eb42..55d4a12 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -1364,6 +1364,7 @@ static int uniphier_pro5_pinctrl_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id uniphier_pro5_pinctrl_match[] = {
+	{ .compatible = "socionext,uniphier-pro5-pinctrl" },
 	{ .compatible = "socionext,ph1-pro5-pinctrl" },
 	{ /* sentinel */ }
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
index c879be3..8e1d73e 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
@@ -1254,6 +1254,7 @@ static int uniphier_pxs2_pinctrl_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id uniphier_pxs2_pinctrl_match[] = {
+	{ .compatible = "socionext,uniphier-pxs2-pinctrl" },
 	{ .compatible = "socionext,proxstream2-pinctrl" },
 	{ /* sentinel */ }
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
index 096a460..8ea740d 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
@@ -841,6 +841,7 @@ static int uniphier_sld8_pinctrl_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id uniphier_sld8_pinctrl_match[] = {
+	{ .compatible = "socionext,uniphier-sld8-pinctrl" },
 	{ .compatible = "socionext,ph1-sld8-pinctrl" },
 	{ /* sentinel */ }
 };
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:12 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:12 +0900
Subject: [PATCH 06/17] pinctrl: uniphier: allocate struct pinctrl_desc in
 probe function
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-7-git-send-email-yamada.masahiro@socionext.com>

Currently, every SoC driver defines struct pinctrl_desc statically,
i.e. it consumes memory footprint even if it is not probed.

In multi-platform, many pinctrl drivers are linked (generally as
built-in objects), although only one of them is actually used.
So, it is reasonable to allocate memory dynamically where possible.

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 19 +++++++++++--------
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c  | 10 +++-------
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c | 10 +++-------
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c | 10 +++-------
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c | 10 +++-------
 drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c | 10 +++-------
 drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c | 10 +++-------
 drivers/pinctrl/uniphier/pinctrl-uniphier.h      |  8 ++++----
 8 files changed, 33 insertions(+), 54 deletions(-)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 4aa67c6..953b13a 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -26,6 +26,7 @@
 #include "pinctrl-uniphier.h"
 
 struct uniphier_pinctrl_priv {
+	struct pinctrl_desc pctldesc;
 	struct pinctrl_dev *pctldev;
 	struct regmap *regmap;
 	struct uniphier_pinctrl_socdata *socdata;
@@ -639,13 +640,13 @@ static const struct pinmux_ops uniphier_pmxops = {
 };
 
 int uniphier_pinctrl_probe(struct platform_device *pdev,
-			   struct pinctrl_desc *desc,
 			   struct uniphier_pinctrl_socdata *socdata)
 {
 	struct device *dev = &pdev->dev;
 	struct uniphier_pinctrl_priv *priv;
 
 	if (!socdata ||
+	    !socdata->pins || !socdata->npins ||
 	    !socdata->groups ||
 	    !socdata->groups_count ||
 	    !socdata->functions ||
@@ -667,13 +668,15 @@ int uniphier_pinctrl_probe(struct platform_device *pdev,
 	}
 
 	priv->socdata = socdata;
-	desc->name = dev->driver->name;
-	desc->pctlops = &uniphier_pctlops;
-	desc->pmxops = &uniphier_pmxops;
-	desc->confops = &uniphier_confops;
-	desc->owner = dev->driver->owner;
-
-	priv->pctldev = devm_pinctrl_register(dev, desc, priv);
+	priv->pctldesc.name = dev->driver->name;
+	priv->pctldesc.pins = socdata->pins;
+	priv->pctldesc.npins = socdata->npins;
+	priv->pctldesc.pctlops = &uniphier_pctlops;
+	priv->pctldesc.pmxops = &uniphier_pmxops;
+	priv->pctldesc.confops = &uniphier_confops;
+	priv->pctldesc.owner = dev->driver->owner;
+
+	priv->pctldev = devm_pinctrl_register(dev, &priv->pctldesc, priv);
 	if (IS_ERR(priv->pctldev)) {
 		dev_err(dev, "failed to register UniPhier pinctrl driver\n");
 		return PTR_ERR(priv->pctldev);
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
index 1e7bacd..7b8cf31 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
@@ -846,6 +846,8 @@ static const struct uniphier_pinmux_function uniphier_ld4_functions[] = {
 };
 
 static struct uniphier_pinctrl_socdata uniphier_ld4_pindata = {
+	.pins = uniphier_ld4_pins,
+	.npins = ARRAY_SIZE(uniphier_ld4_pins),
 	.groups = uniphier_ld4_groups,
 	.groups_count = ARRAY_SIZE(uniphier_ld4_groups),
 	.functions = uniphier_ld4_functions,
@@ -855,15 +857,9 @@ static struct uniphier_pinctrl_socdata uniphier_ld4_pindata = {
 	.load_pinctrl = false,
 };
 
-static struct pinctrl_desc uniphier_ld4_pinctrl_desc = {
-	.pins = uniphier_ld4_pins,
-	.npins = ARRAY_SIZE(uniphier_ld4_pins),
-};
-
 static int uniphier_ld4_pinctrl_probe(struct platform_device *pdev)
 {
-	return uniphier_pinctrl_probe(pdev, &uniphier_ld4_pinctrl_desc,
-				      &uniphier_ld4_pindata);
+	return uniphier_pinctrl_probe(pdev, &uniphier_ld4_pindata);
 }
 
 static const struct of_device_id uniphier_ld4_pinctrl_match[] = {
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
index 458c8a4..b8d1df9 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
@@ -1234,6 +1234,8 @@ static const struct uniphier_pinmux_function uniphier_ld6b_functions[] = {
 };
 
 static struct uniphier_pinctrl_socdata uniphier_ld6b_pindata = {
+	.pins = uniphier_ld6b_pins,
+	.npins = ARRAY_SIZE(uniphier_ld6b_pins),
 	.groups = uniphier_ld6b_groups,
 	.groups_count = ARRAY_SIZE(uniphier_ld6b_groups),
 	.functions = uniphier_ld6b_functions,
@@ -1243,15 +1245,9 @@ static struct uniphier_pinctrl_socdata uniphier_ld6b_pindata = {
 	.load_pinctrl = false,
 };
 
-static struct pinctrl_desc uniphier_ld6b_pinctrl_desc = {
-	.pins = uniphier_ld6b_pins,
-	.npins = ARRAY_SIZE(uniphier_ld6b_pins),
-};
-
 static int uniphier_ld6b_pinctrl_probe(struct platform_device *pdev)
 {
-	return uniphier_pinctrl_probe(pdev, &uniphier_ld6b_pinctrl_desc,
-				      &uniphier_ld6b_pindata);
+	return uniphier_pinctrl_probe(pdev, &uniphier_ld6b_pindata);
 }
 
 static const struct of_device_id uniphier_ld6b_pinctrl_match[] = {
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
index 7fcaeb5..d88b351 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
@@ -1520,6 +1520,8 @@ static const struct uniphier_pinmux_function uniphier_pro4_functions[] = {
 };
 
 static struct uniphier_pinctrl_socdata uniphier_pro4_pindata = {
+	.pins = uniphier_pro4_pins,
+	.npins = ARRAY_SIZE(uniphier_pro4_pins),
 	.groups = uniphier_pro4_groups,
 	.groups_count = ARRAY_SIZE(uniphier_pro4_groups),
 	.functions = uniphier_pro4_functions,
@@ -1529,15 +1531,9 @@ static struct uniphier_pinctrl_socdata uniphier_pro4_pindata = {
 	.load_pinctrl = true,
 };
 
-static struct pinctrl_desc uniphier_pro4_pinctrl_desc = {
-	.pins = uniphier_pro4_pins,
-	.npins = ARRAY_SIZE(uniphier_pro4_pins),
-};
-
 static int uniphier_pro4_pinctrl_probe(struct platform_device *pdev)
 {
-	return uniphier_pinctrl_probe(pdev, &uniphier_pro4_pinctrl_desc,
-				      &uniphier_pro4_pindata);
+	return uniphier_pinctrl_probe(pdev, &uniphier_pro4_pindata);
 }
 
 static const struct of_device_id uniphier_pro4_pinctrl_match[] = {
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index 47fa57e..6282ace 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -1311,6 +1311,8 @@ static const struct uniphier_pinmux_function uniphier_pro5_functions[] = {
 };
 
 static struct uniphier_pinctrl_socdata uniphier_pro5_pindata = {
+	.pins = uniphier_pro5_pins,
+	.npins = ARRAY_SIZE(uniphier_pro5_pins),
 	.groups = uniphier_pro5_groups,
 	.groups_count = ARRAY_SIZE(uniphier_pro5_groups),
 	.functions = uniphier_pro5_functions,
@@ -1320,15 +1322,9 @@ static struct uniphier_pinctrl_socdata uniphier_pro5_pindata = {
 	.load_pinctrl = true,
 };
 
-static struct pinctrl_desc uniphier_pro5_pinctrl_desc = {
-	.pins = uniphier_pro5_pins,
-	.npins = ARRAY_SIZE(uniphier_pro5_pins),
-};
-
 static int uniphier_pro5_pinctrl_probe(struct platform_device *pdev)
 {
-	return uniphier_pinctrl_probe(pdev, &uniphier_pro5_pinctrl_desc,
-				      &uniphier_pro5_pindata);
+	return uniphier_pinctrl_probe(pdev, &uniphier_pro5_pindata);
 }
 
 static const struct of_device_id uniphier_pro5_pinctrl_match[] = {
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
index 246e2be..8c48f31 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
@@ -1229,6 +1229,8 @@ static const struct uniphier_pinmux_function uniphier_pxs2_functions[] = {
 };
 
 static struct uniphier_pinctrl_socdata uniphier_pxs2_pindata = {
+	.pins = uniphier_pxs2_pins,
+	.npins = ARRAY_SIZE(uniphier_pxs2_pins),
 	.groups = uniphier_pxs2_groups,
 	.groups_count = ARRAY_SIZE(uniphier_pxs2_groups),
 	.functions = uniphier_pxs2_functions,
@@ -1238,15 +1240,9 @@ static struct uniphier_pinctrl_socdata uniphier_pxs2_pindata = {
 	.load_pinctrl = false,
 };
 
-static struct pinctrl_desc uniphier_pxs2_pinctrl_desc = {
-	.pins = uniphier_pxs2_pins,
-	.npins = ARRAY_SIZE(uniphier_pxs2_pins),
-};
-
 static int uniphier_pxs2_pinctrl_probe(struct platform_device *pdev)
 {
-	return uniphier_pinctrl_probe(pdev, &uniphier_pxs2_pinctrl_desc,
-				      &uniphier_pxs2_pindata);
+	return uniphier_pinctrl_probe(pdev, &uniphier_pxs2_pindata);
 }
 
 static const struct of_device_id uniphier_pxs2_pinctrl_match[] = {
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
index 915259f..caf5380 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
@@ -754,6 +754,8 @@ static const struct uniphier_pinmux_function uniphier_sld8_functions[] = {
 };
 
 static struct uniphier_pinctrl_socdata uniphier_sld8_pindata = {
+	.pins = uniphier_sld8_pins,
+	.npins = ARRAY_SIZE(uniphier_sld8_pins),
 	.groups = uniphier_sld8_groups,
 	.groups_count = ARRAY_SIZE(uniphier_sld8_groups),
 	.functions = uniphier_sld8_functions,
@@ -763,15 +765,9 @@ static struct uniphier_pinctrl_socdata uniphier_sld8_pindata = {
 	.load_pinctrl = false,
 };
 
-static struct pinctrl_desc uniphier_sld8_pinctrl_desc = {
-	.pins = uniphier_sld8_pins,
-	.npins = ARRAY_SIZE(uniphier_sld8_pins),
-};
-
 static int uniphier_sld8_pinctrl_probe(struct platform_device *pdev)
 {
-	return uniphier_pinctrl_probe(pdev, &uniphier_sld8_pinctrl_desc,
-				      &uniphier_sld8_pindata);
+	return uniphier_pinctrl_probe(pdev, &uniphier_sld8_pindata);
 }
 
 static const struct of_device_id uniphier_sld8_pinctrl_match[] = {
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
index a21154f..0322413 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
@@ -19,6 +19,8 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 
+struct platform_device;
+
 #define UNIPHIER_PINCTRL_PINMUX_BASE	0x0
 #define UNIPHIER_PINCTRL_LOAD_PINMUX	0x700
 #define UNIPHIER_PINCTRL_DRVCTRL_BASE	0x800
@@ -154,6 +156,8 @@ struct uniphier_pinmux_function {
 };
 
 struct uniphier_pinctrl_socdata {
+	const struct pinctrl_pin_desc *pins;
+	unsigned int npins;
 	const struct uniphier_pinctrl_group *groups;
 	int groups_count;
 	const struct uniphier_pinmux_function *functions;
@@ -205,11 +209,7 @@ struct uniphier_pinctrl_socdata {
 		.num_groups = ARRAY_SIZE(func##_groups),		\
 	}
 
-struct platform_device;
-struct pinctrl_desc;
-
 int uniphier_pinctrl_probe(struct platform_device *pdev,
-			   struct pinctrl_desc *desc,
 			   struct uniphier_pinctrl_socdata *socdata);
 
 #endif /* __PINCTRL_UNIPHIER_H__ */
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:11 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:11 +0900
Subject: [PATCH 05/17] pinctrl: uniphier: set pinctrl_desc name in common
 probe function
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-6-git-send-email-yamada.masahiro@socionext.com>

Every SoC driver sets the same name for struct pinctrl_desc and
platform_driver.  The common probe function can set desc->name
instead of duplicating strings in each SoC driver.

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 1 +
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c  | 5 +----
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c | 5 +----
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c | 5 +----
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c | 5 +----
 drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c | 5 +----
 drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c | 5 +----
 7 files changed, 7 insertions(+), 24 deletions(-)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index ab89efb..4aa67c6 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -667,6 +667,7 @@ int uniphier_pinctrl_probe(struct platform_device *pdev,
 	}
 
 	priv->socdata = socdata;
+	desc->name = dev->driver->name;
 	desc->pctlops = &uniphier_pctlops;
 	desc->pmxops = &uniphier_pmxops;
 	desc->confops = &uniphier_confops;
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
index 5353ce4..1e7bacd 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
@@ -19,8 +19,6 @@
 
 #include "pinctrl-uniphier.h"
 
-#define DRIVER_NAME "uniphier-ld4-pinctrl"
-
 static const struct pinctrl_pin_desc uniphier_ld4_pins[] = {
 	UNIPHIER_PINCTRL_PIN(0, "EA1", UNIPHIER_PIN_IECTRL_NONE,
 			     8, UNIPHIER_PIN_DRV_4_8,
@@ -858,7 +856,6 @@ static struct uniphier_pinctrl_socdata uniphier_ld4_pindata = {
 };
 
 static struct pinctrl_desc uniphier_ld4_pinctrl_desc = {
-	.name = DRIVER_NAME,
 	.pins = uniphier_ld4_pins,
 	.npins = ARRAY_SIZE(uniphier_ld4_pins),
 };
@@ -878,7 +875,7 @@ MODULE_DEVICE_TABLE(of, uniphier_ld4_pinctrl_match);
 static struct platform_driver uniphier_ld4_pinctrl_driver = {
 	.probe = uniphier_ld4_pinctrl_probe,
 	.driver = {
-		.name = DRIVER_NAME,
+		.name = "uniphier-ld4-pinctrl",
 		.of_match_table = uniphier_ld4_pinctrl_match,
 	},
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
index c405960..458c8a4 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
@@ -19,8 +19,6 @@
 
 #include "pinctrl-uniphier.h"
 
-#define DRIVER_NAME "uniphier-ld6b-pinctrl"
-
 static const struct pinctrl_pin_desc uniphier_ld6b_pins[] = {
 	UNIPHIER_PINCTRL_PIN(0, "ED0", UNIPHIER_PIN_IECTRL_NONE,
 			     0, UNIPHIER_PIN_DRV_4_8,
@@ -1246,7 +1244,6 @@ static struct uniphier_pinctrl_socdata uniphier_ld6b_pindata = {
 };
 
 static struct pinctrl_desc uniphier_ld6b_pinctrl_desc = {
-	.name = DRIVER_NAME,
 	.pins = uniphier_ld6b_pins,
 	.npins = ARRAY_SIZE(uniphier_ld6b_pins),
 };
@@ -1266,7 +1263,7 @@ MODULE_DEVICE_TABLE(of, uniphier_ld6b_pinctrl_match);
 static struct platform_driver uniphier_ld6b_pinctrl_driver = {
 	.probe = uniphier_ld6b_pinctrl_probe,
 	.driver = {
-		.name = DRIVER_NAME,
+		.name = "uniphier-ld6b-pinctrl",
 		.of_match_table = uniphier_ld6b_pinctrl_match,
 	},
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
index 54b08d5..7fcaeb5 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
@@ -19,8 +19,6 @@
 
 #include "pinctrl-uniphier.h"
 
-#define DRIVER_NAME "uniphier-pro4-pinctrl"
-
 static const struct pinctrl_pin_desc uniphier_pro4_pins[] = {
 	UNIPHIER_PINCTRL_PIN(0, "CK24O", UNIPHIER_PIN_IECTRL_NONE,
 			     0, UNIPHIER_PIN_DRV_4_8,
@@ -1532,7 +1530,6 @@ static struct uniphier_pinctrl_socdata uniphier_pro4_pindata = {
 };
 
 static struct pinctrl_desc uniphier_pro4_pinctrl_desc = {
-	.name = DRIVER_NAME,
 	.pins = uniphier_pro4_pins,
 	.npins = ARRAY_SIZE(uniphier_pro4_pins),
 };
@@ -1552,7 +1549,7 @@ MODULE_DEVICE_TABLE(of, uniphier_pro4_pinctrl_match);
 static struct platform_driver uniphier_pro4_pinctrl_driver = {
 	.probe = uniphier_pro4_pinctrl_probe,
 	.driver = {
-		.name = DRIVER_NAME,
+		.name = "uniphier-pro4-pinctrl",
 		.of_match_table = uniphier_pro4_pinctrl_match,
 	},
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index 19b15db..47fa57e 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -19,8 +19,6 @@
 
 #include "pinctrl-uniphier.h"
 
-#define DRIVER_NAME "uniphier-pro5-pinctrl"
-
 static const struct pinctrl_pin_desc uniphier_pro5_pins[] = {
 	UNIPHIER_PINCTRL_PIN(0, "AEXCKA1", 0,
 			     0, UNIPHIER_PIN_DRV_4_8,
@@ -1323,7 +1321,6 @@ static struct uniphier_pinctrl_socdata uniphier_pro5_pindata = {
 };
 
 static struct pinctrl_desc uniphier_pro5_pinctrl_desc = {
-	.name = DRIVER_NAME,
 	.pins = uniphier_pro5_pins,
 	.npins = ARRAY_SIZE(uniphier_pro5_pins),
 };
@@ -1343,7 +1340,7 @@ MODULE_DEVICE_TABLE(of, uniphier_pro5_pinctrl_match);
 static struct platform_driver uniphier_pro5_pinctrl_driver = {
 	.probe = uniphier_pro5_pinctrl_probe,
 	.driver = {
-		.name = DRIVER_NAME,
+		.name = "uniphier-pro5-pinctrl",
 		.of_match_table = uniphier_pro5_pinctrl_match,
 	},
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
index 762de0e..246e2be 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
@@ -19,8 +19,6 @@
 
 #include "pinctrl-uniphier.h"
 
-#define DRIVER_NAME "uniphier-pxs2-pinctrl"
-
 static const struct pinctrl_pin_desc uniphier_pxs2_pins[] = {
 	UNIPHIER_PINCTRL_PIN(0, "ED0", UNIPHIER_PIN_IECTRL_NONE,
 			     0, UNIPHIER_PIN_DRV_4_8,
@@ -1241,7 +1239,6 @@ static struct uniphier_pinctrl_socdata uniphier_pxs2_pindata = {
 };
 
 static struct pinctrl_desc uniphier_pxs2_pinctrl_desc = {
-	.name = DRIVER_NAME,
 	.pins = uniphier_pxs2_pins,
 	.npins = ARRAY_SIZE(uniphier_pxs2_pins),
 };
@@ -1261,7 +1258,7 @@ MODULE_DEVICE_TABLE(of, uniphier_pxs2_pinctrl_match);
 static struct platform_driver uniphier_pxs2_pinctrl_driver = {
 	.probe = uniphier_pxs2_pinctrl_probe,
 	.driver = {
-		.name = DRIVER_NAME,
+		.name = "uniphier-pxs2-pinctrl",
 		.of_match_table = uniphier_pxs2_pinctrl_match,
 	},
 };
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
index 9fe8762..915259f 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
@@ -19,8 +19,6 @@
 
 #include "pinctrl-uniphier.h"
 
-#define DRIVER_NAME "uniphier-sld8-pinctrl"
-
 static const struct pinctrl_pin_desc uniphier_sld8_pins[] = {
 	UNIPHIER_PINCTRL_PIN(0, "PCA00", 0,
 			     15, UNIPHIER_PIN_DRV_4_8,
@@ -766,7 +764,6 @@ static struct uniphier_pinctrl_socdata uniphier_sld8_pindata = {
 };
 
 static struct pinctrl_desc uniphier_sld8_pinctrl_desc = {
-	.name = DRIVER_NAME,
 	.pins = uniphier_sld8_pins,
 	.npins = ARRAY_SIZE(uniphier_sld8_pins),
 };
@@ -786,7 +783,7 @@ MODULE_DEVICE_TABLE(of, uniphier_sld8_pinctrl_match);
 static struct platform_driver uniphier_sld8_pinctrl_driver = {
 	.probe = uniphier_sld8_pinctrl_probe,
 	.driver = {
-		.name = DRIVER_NAME,
+		.name = "uniphier-sld8-pinctrl",
 		.of_match_table = uniphier_sld8_pinctrl_match,
 	},
 };
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:22 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:22 +0900
Subject: [PATCH 16/17] pinctrl: uniphier: add UniPhier PH1-LD11 pinctrl driver
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-17-git-send-email-yamada.masahiro@socionext.com>

Add pin configuration and pinmux support for UniPhier PH1-LD11 SoC.

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

 drivers/pinctrl/uniphier/Kconfig                 |  16 +-
 drivers/pinctrl/uniphier/Makefile                |   1 +
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c | 956 +++++++++++++++++++++++
 3 files changed, 967 insertions(+), 6 deletions(-)
 create mode 100644 drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c

diff --git a/drivers/pinctrl/uniphier/Kconfig b/drivers/pinctrl/uniphier/Kconfig
index 0b40ded..395d42f 100644
--- a/drivers/pinctrl/uniphier/Kconfig
+++ b/drivers/pinctrl/uniphier/Kconfig
@@ -10,26 +10,30 @@ if PINCTRL_UNIPHIER
 
 config PINCTRL_UNIPHIER_LD4
 	tristate "UniPhier PH1-LD4 SoC pinctrl driver"
-	default y
+	default ARM
 
 config PINCTRL_UNIPHIER_PRO4
 	tristate "UniPhier PH1-Pro4 SoC pinctrl driver"
-	default y
+	default ARM
 
 config PINCTRL_UNIPHIER_SLD8
 	tristate "UniPhier PH1-sLD8 SoC pinctrl driver"
-	default y
+	default ARM
 
 config PINCTRL_UNIPHIER_PRO5
 	tristate "UniPhier PH1-Pro5 SoC pinctrl driver"
-	default y
+	default ARM
 
 config PINCTRL_UNIPHIER_PXS2
 	tristate "UniPhier ProXstream2 SoC pinctrl driver"
-	default y
+	default ARM
 
 config PINCTRL_UNIPHIER_LD6B
 	tristate "UniPhier PH1-LD6b SoC pinctrl driver"
-	default y
+	default ARM
+
+config PINCTRL_UNIPHIER_LD11
+	tristate "UniPhier PH1-LD11 SoC pinctrl driver"
+	default ARM64
 
 endif
diff --git a/drivers/pinctrl/uniphier/Makefile b/drivers/pinctrl/uniphier/Makefile
index 3b8f9ee..883c1076 100644
--- a/drivers/pinctrl/uniphier/Makefile
+++ b/drivers/pinctrl/uniphier/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_PINCTRL_UNIPHIER_SLD8)	+= pinctrl-uniphier-sld8.o
 obj-$(CONFIG_PINCTRL_UNIPHIER_PRO5)	+= pinctrl-uniphier-pro5.o
 obj-$(CONFIG_PINCTRL_UNIPHIER_PXS2)	+= pinctrl-uniphier-pxs2.o
 obj-$(CONFIG_PINCTRL_UNIPHIER_LD6B)	+= pinctrl-uniphier-ld6b.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_LD11)	+= pinctrl-uniphier-ld11.o
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
new file mode 100644
index 0000000..418ccd6
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
@@ -0,0 +1,956 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-uniphier.h"
+
+static const struct pinctrl_pin_desc uniphier_ld11_pins[] = {
+	UNIPHIER_PINCTRL_PIN(0, "XECS1", 0,
+			     0, UNIPHIER_PIN_DRV_1BIT,
+			     0, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(1, "ERXW", UNIPHIER_PIN_IECTRL_NONE,
+			     1, UNIPHIER_PIN_DRV_1BIT,
+			     1, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(2, "XERWE1", UNIPHIER_PIN_IECTRL_NONE,
+			     2, UNIPHIER_PIN_DRV_1BIT,
+			     2, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(3, "XNFWP", 3,
+			     3, UNIPHIER_PIN_DRV_1BIT,
+			     3, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(4, "XNFCE0", 4,
+			     4, UNIPHIER_PIN_DRV_1BIT,
+			     4, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(5, "NFRYBY0", 5,
+			     5, UNIPHIER_PIN_DRV_1BIT,
+			     5, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(6, "XNFRE", UNIPHIER_PIN_IECTRL_NONE,
+			     6, UNIPHIER_PIN_DRV_1BIT,
+			     6, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(7, "XNFWE", UNIPHIER_PIN_IECTRL_NONE,
+			     7, UNIPHIER_PIN_DRV_1BIT,
+			     7, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(8, "NFALE", UNIPHIER_PIN_IECTRL_NONE,
+			     8, UNIPHIER_PIN_DRV_1BIT,
+			     8, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(9, "NFCLE", UNIPHIER_PIN_IECTRL_NONE,
+			     9, UNIPHIER_PIN_DRV_1BIT,
+			     9, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(10, "NFD0", 10,
+			     10, UNIPHIER_PIN_DRV_1BIT,
+			     10, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(11, "NFD1", 11,
+			     11, UNIPHIER_PIN_DRV_1BIT,
+			     11, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(12, "NFD2", 12,
+			     12, UNIPHIER_PIN_DRV_1BIT,
+			     12, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(13, "NFD3", 13,
+			     13, UNIPHIER_PIN_DRV_1BIT,
+			     13, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(14, "NFD4", 14,
+			     14, UNIPHIER_PIN_DRV_1BIT,
+			     14, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(15, "NFD5", 15,
+			     15, UNIPHIER_PIN_DRV_1BIT,
+			     15, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(16, "NFD6", 16,
+			     16, UNIPHIER_PIN_DRV_1BIT,
+			     16, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(17, "NFD7", 17,
+			     17, UNIPHIER_PIN_DRV_1BIT,
+			     17, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(18, "XERST", 18,
+			     0, UNIPHIER_PIN_DRV_2BIT,
+			     18, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(19, "MMCCLK", 19,
+			     1, UNIPHIER_PIN_DRV_2BIT,
+			     19, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(20, "MMCCMD", 20,
+			     2, UNIPHIER_PIN_DRV_2BIT,
+			     20, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(21, "MMCDS", 21,
+			     3, UNIPHIER_PIN_DRV_2BIT,
+			     21, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(22, "MMCDAT0", 22,
+			     4, UNIPHIER_PIN_DRV_2BIT,
+			     22, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(23, "MMCDAT1", 23,
+			     5, UNIPHIER_PIN_DRV_2BIT,
+			     23, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(24, "MMCDAT2", 24,
+			     6, UNIPHIER_PIN_DRV_2BIT,
+			     24, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(25, "MMCDAT3", 25,
+			     7, UNIPHIER_PIN_DRV_2BIT,
+			     25, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(26, "MMCDAT4", 26,
+			     8, UNIPHIER_PIN_DRV_2BIT,
+			     26, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(27, "MMCDAT5", 27,
+			     9, UNIPHIER_PIN_DRV_2BIT,
+			     27, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(28, "MMCDAT6", 28,
+			     10, UNIPHIER_PIN_DRV_2BIT,
+			     28, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(29, "MMCDAT7", 29,
+			     11, UNIPHIER_PIN_DRV_2BIT,
+			     29, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(46, "USB0VBUS", 46,
+			     46, UNIPHIER_PIN_DRV_1BIT,
+			     46, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(47, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
+			     47, UNIPHIER_PIN_DRV_1BIT,
+			     47, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(48, "USB1VBUS", 48,
+			     48, UNIPHIER_PIN_DRV_1BIT,
+			     48, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(49, "USB1OD", 49,
+			     49, UNIPHIER_PIN_DRV_1BIT,
+			     49, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(50, "USB2VBUS", 50,
+			     50, UNIPHIER_PIN_DRV_1BIT,
+			     50, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(51, "USB2OD", 51,
+			     51, UNIPHIER_PIN_DRV_1BIT,
+			     51, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(54, "TXD0", 54,
+			     54, UNIPHIER_PIN_DRV_1BIT,
+			     54, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(55, "RXD0", 55,
+			     55, UNIPHIER_PIN_DRV_1BIT,
+			     55, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(56, "SPISYNC0", 56,
+			     56, UNIPHIER_PIN_DRV_1BIT,
+			     56, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(57, "SPISCLK0", 57,
+			     57, UNIPHIER_PIN_DRV_1BIT,
+			     57, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(58, "SPITXD0", 58,
+			     58, UNIPHIER_PIN_DRV_1BIT,
+			     58, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(59, "SPIRXD0", 59,
+			     59, UNIPHIER_PIN_DRV_1BIT,
+			     59, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(60, "AGCI", 60,
+			     60, UNIPHIER_PIN_DRV_1BIT,
+			     60, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(61, "DMDSDA0", 61,
+			     61, UNIPHIER_PIN_DRV_1BIT,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(62, "DMDSCL0", 62,
+			     62, UNIPHIER_PIN_DRV_1BIT,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(63, "SDA0", 63,
+			     63, UNIPHIER_PIN_DRV_1BIT,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(64, "SCL0", 64,
+			     64, UNIPHIER_PIN_DRV_1BIT,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(65, "SDA1", 65,
+			     65, UNIPHIER_PIN_DRV_1BIT,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(66, "SCL1", 66,
+			     66, UNIPHIER_PIN_DRV_1BIT,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(67, "HIN", 67,
+			     -1, UNIPHIER_PIN_DRV_FIXED5,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(68, "VIN", 68,
+			     -1, UNIPHIER_PIN_DRV_FIXED5,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(69, "PCA00", 69,
+			     69, UNIPHIER_PIN_DRV_1BIT,
+			     69, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(70, "PCA01", 70,
+			     70, UNIPHIER_PIN_DRV_1BIT,
+			     70, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(71, "PCA02", 71,
+			     71, UNIPHIER_PIN_DRV_1BIT,
+			     71, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(72, "PCA03", 72,
+			     72, UNIPHIER_PIN_DRV_1BIT,
+			     72, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(73, "PCA04", 73,
+			     73, UNIPHIER_PIN_DRV_1BIT,
+			     73, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(74, "PCA05", 74,
+			     74, UNIPHIER_PIN_DRV_1BIT,
+			     74, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(75, "PCA06", 75,
+			     75, UNIPHIER_PIN_DRV_1BIT,
+			     75, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(76, "PCA07", 76,
+			     76, UNIPHIER_PIN_DRV_1BIT,
+			     76, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(77, "PCA08", 77,
+			     77, UNIPHIER_PIN_DRV_1BIT,
+			     77, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(78, "PCA09", 78,
+			     78, UNIPHIER_PIN_DRV_1BIT,
+			     78, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(79, "PCA10", 79,
+			     79, UNIPHIER_PIN_DRV_1BIT,
+			     79, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(80, "PCA11", 80,
+			     80, UNIPHIER_PIN_DRV_1BIT,
+			     80, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(81, "PCA12", 81,
+			     81, UNIPHIER_PIN_DRV_1BIT,
+			     81, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(82, "PCA13", 82,
+			     82, UNIPHIER_PIN_DRV_1BIT,
+			     82, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(83, "PCA14", 83,
+			     83, UNIPHIER_PIN_DRV_1BIT,
+			     83, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(84, "PC0READY", 84,
+			     84, UNIPHIER_PIN_DRV_1BIT,
+			     84, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(85, "PC0CD1", 85,
+			     85, UNIPHIER_PIN_DRV_1BIT,
+			     85, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(86, "PC0CD2", 86,
+			     86, UNIPHIER_PIN_DRV_1BIT,
+			     86, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(87, "PC0WAIT", 87,
+			     87, UNIPHIER_PIN_DRV_1BIT,
+			     87, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(88, "PC0RESET", 88,
+			     88, UNIPHIER_PIN_DRV_1BIT,
+			     88, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(89, "PC0CE1", 89,
+			     89, UNIPHIER_PIN_DRV_1BIT,
+			     89, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(90, "PC0WE", 90,
+			     90, UNIPHIER_PIN_DRV_1BIT,
+			     90, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(91, "PC0OE", 91,
+			     91, UNIPHIER_PIN_DRV_1BIT,
+			     91, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(92, "PC0IOWR", 92,
+			     92, UNIPHIER_PIN_DRV_1BIT,
+			     92, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(93, "PC0IORD", 93,
+			     93, UNIPHIER_PIN_DRV_1BIT,
+			     93, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(94, "PCD00", 94,
+			     94, UNIPHIER_PIN_DRV_1BIT,
+			     94, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(95, "PCD01", 95,
+			     95, UNIPHIER_PIN_DRV_1BIT,
+			     95, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(96, "PCD02", 96,
+			     96, UNIPHIER_PIN_DRV_1BIT,
+			     96, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(97, "PCD03", 97,
+			     97, UNIPHIER_PIN_DRV_1BIT,
+			     97, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(98, "PCD04", 98,
+			     98, UNIPHIER_PIN_DRV_1BIT,
+			     98, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(99, "PCD05", 99,
+			     99, UNIPHIER_PIN_DRV_1BIT,
+			     99, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(100, "PCD06", 100,
+			     100, UNIPHIER_PIN_DRV_1BIT,
+			     100, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(101, "PCD07", 101,
+			     101, UNIPHIER_PIN_DRV_1BIT,
+			     101, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(102, "HS0BCLKIN", 102,
+			     102, UNIPHIER_PIN_DRV_1BIT,
+			     102, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(103, "HS0SYNCIN", 103,
+			     103, UNIPHIER_PIN_DRV_1BIT,
+			     103, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(104, "HS0VALIN", 104,
+			     104, UNIPHIER_PIN_DRV_1BIT,
+			     104, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(105, "HS0DIN0", 105,
+			     105, UNIPHIER_PIN_DRV_1BIT,
+			     105, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(106, "HS0DIN1", 106,
+			     106, UNIPHIER_PIN_DRV_1BIT,
+			     106, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(107, "HS0DIN2", 107,
+			     107, UNIPHIER_PIN_DRV_1BIT,
+			     107, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(108, "HS0DIN3", 108,
+			     108, UNIPHIER_PIN_DRV_1BIT,
+			     108, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(109, "HS0DIN4", 109,
+			     109, UNIPHIER_PIN_DRV_1BIT,
+			     109, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(110, "HS0DIN5", 110,
+			     110, UNIPHIER_PIN_DRV_1BIT,
+			     110, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(111, "HS0DIN6", 111,
+			     111, UNIPHIER_PIN_DRV_1BIT,
+			     111, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(112, "HS0DIN7", 112,
+			     112, UNIPHIER_PIN_DRV_1BIT,
+			     112, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(113, "HS0BCLKOUT", 113,
+			     113, UNIPHIER_PIN_DRV_1BIT,
+			     113, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(114, "HS0SYNCOUT", 114,
+			     114, UNIPHIER_PIN_DRV_1BIT,
+			     114, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(115, "HS0VALOUT", 115,
+			     115, UNIPHIER_PIN_DRV_1BIT,
+			     115, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(116, "HS0DOUT0", 116,
+			     116, UNIPHIER_PIN_DRV_1BIT,
+			     116, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(117, "HS0DOUT1", 117,
+			     117, UNIPHIER_PIN_DRV_1BIT,
+			     117, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(118, "HS0DOUT2", 118,
+			     118, UNIPHIER_PIN_DRV_1BIT,
+			     118, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(119, "HS0DOUT3", 119,
+			     119, UNIPHIER_PIN_DRV_1BIT,
+			     119, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(120, "HS0DOUT4", 120,
+			     120, UNIPHIER_PIN_DRV_1BIT,
+			     120, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(121, "HS0DOUT5", 121,
+			     121, UNIPHIER_PIN_DRV_1BIT,
+			     121, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(122, "HS0DOUT6", 122,
+			     122, UNIPHIER_PIN_DRV_1BIT,
+			     122, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(123, "HS0DOUT7", 123,
+			     123, UNIPHIER_PIN_DRV_1BIT,
+			     123, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(124, "HS1BCLKIN", 124,
+			     124, UNIPHIER_PIN_DRV_1BIT,
+			     124, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(125, "HS1SYNCIN", 125,
+			     125, UNIPHIER_PIN_DRV_1BIT,
+			     125, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(126, "HS1VALIN", 126,
+			     126, UNIPHIER_PIN_DRV_1BIT,
+			     126, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(127, "HS1DIN0", 127,
+			     127, UNIPHIER_PIN_DRV_1BIT,
+			     127, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(128, "HS1DIN1", 128,
+			     128, UNIPHIER_PIN_DRV_1BIT,
+			     128, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(129, "HS1DIN2", 129,
+			     129, UNIPHIER_PIN_DRV_1BIT,
+			     129, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(130, "HS1DIN3", 130,
+			     130, UNIPHIER_PIN_DRV_1BIT,
+			     130, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(131, "HS1DIN4", 131,
+			     131, UNIPHIER_PIN_DRV_1BIT,
+			     131, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(132, "HS1DIN5", 132,
+			     132, UNIPHIER_PIN_DRV_1BIT,
+			     132, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(133, "HS1DIN6", 133,
+			     133, UNIPHIER_PIN_DRV_1BIT,
+			     133, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(134, "HS1DIN7", 134,
+			     134, UNIPHIER_PIN_DRV_1BIT,
+			     134, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(135, "AO1IEC", 135,
+			     135, UNIPHIER_PIN_DRV_1BIT,
+			     135, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(136, "AO1ARC", 136,
+			     136, UNIPHIER_PIN_DRV_1BIT,
+			     136, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(137, "AO1DACCK", 137,
+			     137, UNIPHIER_PIN_DRV_1BIT,
+			     137, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(138, "AO1BCK", 138,
+			     138, UNIPHIER_PIN_DRV_1BIT,
+			     138, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(139, "AO1LRCK", 139,
+			     139, UNIPHIER_PIN_DRV_1BIT,
+			     139, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(140, "AO1D0", 140,
+			     140, UNIPHIER_PIN_DRV_1BIT,
+			     140, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(141, "TCON0", 141,
+			     141, UNIPHIER_PIN_DRV_1BIT,
+			     141, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(142, "TCON1", 142,
+			     142, UNIPHIER_PIN_DRV_1BIT,
+			     142, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(143, "TCON2", 143,
+			     143, UNIPHIER_PIN_DRV_1BIT,
+			     143, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(144, "TCON3", 144,
+			     144, UNIPHIER_PIN_DRV_1BIT,
+			     144, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(145, "TCON4", 145,
+			     145, UNIPHIER_PIN_DRV_1BIT,
+			     145, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(146, "TCON5", 146,
+			     146, UNIPHIER_PIN_DRV_1BIT,
+			     146, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(147, "PWMA", 147,
+			     147, UNIPHIER_PIN_DRV_1BIT,
+			     147, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(148, "LR_GOUT", 148,
+			     148, UNIPHIER_PIN_DRV_1BIT,
+			     148, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(149, "XIRQ0", 149,
+			     149, UNIPHIER_PIN_DRV_1BIT,
+			     149, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(150, "XIRQ1", 150,
+			     150, UNIPHIER_PIN_DRV_1BIT,
+			     150, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(151, "XIRQ2", 151,
+			     151, UNIPHIER_PIN_DRV_1BIT,
+			     151, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(152, "XIRQ3", 152,
+			     152, UNIPHIER_PIN_DRV_1BIT,
+			     152, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(153, "XIRQ4", 153,
+			     153, UNIPHIER_PIN_DRV_1BIT,
+			     153, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(154, "XIRQ5", 154,
+			     154, UNIPHIER_PIN_DRV_1BIT,
+			     154, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(155, "XIRQ6", 155,
+			     155, UNIPHIER_PIN_DRV_1BIT,
+			     155, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(156, "XIRQ7", 156,
+			     156, UNIPHIER_PIN_DRV_1BIT,
+			     156, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(157, "XIRQ8", 157,
+			     157, UNIPHIER_PIN_DRV_1BIT,
+			     157, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(158, "AGCBS", 158,
+			     158, UNIPHIER_PIN_DRV_1BIT,
+			     158, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(159, "XIRQ21", 159,
+			     159, UNIPHIER_PIN_DRV_1BIT,
+			     159, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(160, "XIRQ22", 160,
+			     160, UNIPHIER_PIN_DRV_1BIT,
+			     160, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(161, "XIRQ23", 161,
+			     161, UNIPHIER_PIN_DRV_1BIT,
+			     161, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(162, "CH2CLK", 162,
+			     162, UNIPHIER_PIN_DRV_1BIT,
+			     162, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(163, "CH2PSYNC", 163,
+			     163, UNIPHIER_PIN_DRV_1BIT,
+			     163, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(164, "CH2VAL", 164,
+			     164, UNIPHIER_PIN_DRV_1BIT,
+			     164, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(165, "CH2DATA", 165,
+			     165, UNIPHIER_PIN_DRV_1BIT,
+			     165, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(166, "CK25O", 166,
+			     166, UNIPHIER_PIN_DRV_1BIT,
+			     166, UNIPHIER_PIN_PULL_DOWN),
+};
+
+static const unsigned emmc_pins[] = {18, 19, 20, 21, 22, 23, 24, 25};
+static const int emmc_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned emmc_dat8_pins[] = {26, 27, 28, 29};
+static const int emmc_dat8_muxvals[] = {0, 0, 0, 0};
+static const unsigned i2c0_pins[] = {63, 64};
+static const int i2c0_muxvals[] = {0, 0};
+static const unsigned i2c1_pins[] = {65, 66};
+static const int i2c1_muxvals[] = {0, 0};
+static const unsigned i2c3_pins[] = {67, 68};
+static const int i2c3_muxvals[] = {1, 1};
+static const unsigned i2c4_pins[] = {61, 62};
+static const int i2c4_muxvals[] = {1, 1};
+static const unsigned nand_pins[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+				     15, 16, 17};
+static const int nand_muxvals[] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
+static const unsigned sd_pins[] = {10, 11, 12, 13, 14, 15, 16, 17};
+static const int sd_muxvals[] = {3, 3, 3, 3, 3, 3, 3, 3};  /* No SDVOLC */
+static const unsigned system_bus_pins[] = {1, 2, 6, 7, 8, 9, 10, 11, 12, 13,
+					   14, 15, 16, 17};
+static const int system_bus_muxvals[] = {0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+					 2};
+static const unsigned system_bus_cs1_pins[] = {0};
+static const int system_bus_cs1_muxvals[] = {0};
+static const unsigned uart0_pins[] = {54, 55};
+static const int uart0_muxvals[] = {0, 0};
+static const unsigned uart1_pins[] = {58, 59};
+static const int uart1_muxvals[] = {1, 1};
+static const unsigned uart2_pins[] = {90, 91};
+static const int uart2_muxvals[] = {1, 1};
+static const unsigned uart3_pins[] = {94, 95};
+static const int uart3_muxvals[] = {1, 1};
+static const unsigned usb0_pins[] = {46, 47};
+static const int usb0_muxvals[] = {0, 0};
+static const unsigned usb1_pins[] = {48, 49};
+static const int usb1_muxvals[] = {0, 0};
+static const unsigned usb2_pins[] = {50, 51};
+static const int usb2_muxvals[] = {0, 0};
+static const unsigned usb3_pins[] = {52, 53};
+static const int usb3_muxvals[] = {0, 0};
+static const unsigned port_range_pins[] = {
+	159, 160, 161, 162, 163, 164, 165, 166,		/* PORT0x */
+	0, 1, 2, 3, 4, 5, 6, 7,				/* PORT1x */
+	8, 9, 10, 11, 12, 13, 14, 15,			/* PORT2x */
+	16, 17, 18, -1, -1, -1, -1, -1,			/* PORT3x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT4x */
+	-1, -1, -1, 46, 47, 48, 49, 50,			/* PORT5x */
+	51, -1, -1, 54, 55, 56, 57, 58,			/* PORT6x */
+	59, 60, 69, 70, 71, 72, 73, 74,			/* PORT7x */
+	75, 76, 77, 78, 79, 80, 81, 82,			/* PORT8x */
+	83, 84, 85, 86, 87, 88, 89, 90,			/* PORT9x */
+	91, 92, 93, 94, 95, 96, 97, 98,			/* PORT10x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT11x */
+	99, 100, 101, 102, 103, 104, 105, 106,		/* PORT12x */
+	107, 108, 109, 110, 111, 112, 113, 114,		/* PORT13x */
+	115, 116, 117, 118, 119, 120, 121, 122,		/* PORT14x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT15x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT16x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT17x */
+	61, 62, 63, 64, 65, 66, 67, 68,			/* PORT18x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT19x */
+	123, 124, 125, 126, 127, 128, 129, 130,		/* PORT20x */
+	131, 132, 133, 134, 135, 136, 137, 138,		/* PORT21x */
+	139, 140, 141, 142, -1, -1, -1, -1,		/* PORT22x */
+	147, 148, 149, 150, 151, 152, 153, 154,		/* PORT23x */
+	155, 156, 157, 143, 144, 145, 146, 158,		/* PORT24x */
+};
+static const int port_range_muxvals[] = {
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT0x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT1x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT2x */
+	15, 15, 15, -1, -1, -1, -1, -1,			/* PORT3x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT4x */
+	-1, -1, -1, 15, 15, 15, 15, 15,			/* PORT5x */
+	15, -1, -1, 15, 15, 15, 15, 15,			/* PORT6x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT7x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT8x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT9x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT10x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT11x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT12x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT13x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT14x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT15x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT16x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT17x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT18x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT19x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT20x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT21x */
+	15, 15, 15, 15, -1, -1, -1, -1,			/* PORT22x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT23x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT24x */
+};
+static const unsigned xirq_pins[] = {
+	149, 150, 151, 152, 153, 154, 155, 156,		/* XIRQ0-7 */
+	157, 143, 144, 145, 85, 146, 158, 84,		/* XIRQ8-15 */
+	141, 142, 148, 50, 51, 159, 160, 161,		/* XIRQ16-23 */
+};
+static const int xirq_muxvals[] = {
+	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ0-7 */
+	14, 14, 14, 14, 13, 14, 14, 13,			/* XIRQ8-15 */
+	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ16-23 */
+};
+static const unsigned xirq_alternatives_pins[] = {
+	94, 95, 96, 97, 98, 99, 100, 101,		/* XIRQ0-7 */
+	102, 103, 104, 105, 106, 107,			/* XIRQ8-11,13,14 */
+	108, 109, 110, 111, 112, 113, 114, 115,		/* XIRQ16-23 */
+	9, 10, 11, 12, 13, 14, 15, 16,			/* XIRQ4-11 */
+	17, 0, 1, 2, 3, 4, 5, 6, 7, 8,			/* XIRQ13,14,16-23 */
+	139, 140, 135, 147,				/* XIRQ17,18,21,22 */
+};
+static const int xirq_alternatives_muxvals[] = {
+	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ0-7 */
+	14, 14, 14, 14, 14, 14,				/* XIRQ8-11,13,14 */
+	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ16-23 */
+	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ4-11 */
+	14, 14, 14, 14, 14, 14, 14, 14, 14, 14,		/* XIRQ13,14,16-23 */
+	14, 14, 14, 14,					/* XIRQ17,18,21,22 */
+};
+
+static const struct uniphier_pinctrl_group uniphier_ld11_groups[] = {
+	UNIPHIER_PINCTRL_GROUP(emmc),
+	UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+	UNIPHIER_PINCTRL_GROUP(i2c0),
+	UNIPHIER_PINCTRL_GROUP(i2c1),
+	UNIPHIER_PINCTRL_GROUP(i2c3),
+	UNIPHIER_PINCTRL_GROUP(i2c4),
+	UNIPHIER_PINCTRL_GROUP(nand),
+	UNIPHIER_PINCTRL_GROUP(sd),
+	UNIPHIER_PINCTRL_GROUP(system_bus),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs1),
+	UNIPHIER_PINCTRL_GROUP(uart0),
+	UNIPHIER_PINCTRL_GROUP(uart1),
+	UNIPHIER_PINCTRL_GROUP(uart2),
+	UNIPHIER_PINCTRL_GROUP(uart3),
+	UNIPHIER_PINCTRL_GROUP(usb0),
+	UNIPHIER_PINCTRL_GROUP(usb1),
+	UNIPHIER_PINCTRL_GROUP(usb2),
+	UNIPHIER_PINCTRL_GROUP(usb3),
+	UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range),
+	UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq),
+	UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_alternatives),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range, 0),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range, 1),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range, 2),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range, 3),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range, 4),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range, 5),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range, 6),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range, 7),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range, 8),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range, 9),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range, 10),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range, 11),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range, 12),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range, 13),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range, 14),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range, 15),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range, 16),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range, 17),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range, 18),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range, 19),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range, 20),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range, 21),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range, 22),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range, 23),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range, 24),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range, 25),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range, 26),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range, 43),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range, 44),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range, 45),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range, 46),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range, 47),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range, 48),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range, 51),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range, 52),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range, 53),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range, 54),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range, 55),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range, 56),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range, 57),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range, 58),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range, 59),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range, 60),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range, 61),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range, 62),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range, 63),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range, 64),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range, 65),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range, 66),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range, 67),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range, 68),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range, 69),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range, 70),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range, 71),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range, 72),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range, 73),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range, 74),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range, 75),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range, 76),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range, 77),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range, 78),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range, 79),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range, 80),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range, 81),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range, 82),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range, 83),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range, 84),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range, 85),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range, 86),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range, 87),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range, 96),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range, 97),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range, 98),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range, 99),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range, 100),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range, 101),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range, 102),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range, 103),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range, 104),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range, 105),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range, 106),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range, 107),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range, 108),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range, 109),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range, 110),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range, 111),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range, 112),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range, 113),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range, 114),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range, 115),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range, 116),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range, 117),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range, 118),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range, 119),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port180, port_range, 144),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port181, port_range, 145),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port182, port_range, 146),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port183, port_range, 147),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port184, port_range, 148),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port185, port_range, 149),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port186, port_range, 150),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port187, port_range, 151),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port200, port_range, 160),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port201, port_range, 161),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port202, port_range, 162),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port203, port_range, 163),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port204, port_range, 164),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port205, port_range, 165),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port206, port_range, 166),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port207, port_range, 167),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port210, port_range, 168),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port211, port_range, 169),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port212, port_range, 170),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port213, port_range, 171),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port214, port_range, 172),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port215, port_range, 173),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port216, port_range, 174),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port217, port_range, 175),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port220, port_range, 176),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port221, port_range, 177),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port222, port_range, 178),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port223, port_range, 179),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port230, port_range, 184),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port231, port_range, 185),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port232, port_range, 186),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port233, port_range, 187),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port234, port_range, 188),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port235, port_range, 189),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port236, port_range, 190),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port237, port_range, 191),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port240, port_range, 192),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port241, port_range, 193),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port242, port_range, 194),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port243, port_range, 195),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port244, port_range, 196),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port245, port_range, 197),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port246, port_range, 198),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port247, port_range, 199),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq, 0),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq, 1),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq, 2),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq, 3),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq, 4),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq, 5),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq, 6),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq, 7),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq, 8),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq, 9),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq, 10),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq, 11),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq, 12),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13, xirq, 13),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq, 14),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq, 15),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16, xirq, 16),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17, xirq, 17),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18, xirq, 18),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19, xirq, 19),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20, xirq, 20),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq21, xirq, 21),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq22, xirq, 22),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq23, xirq, 23),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0b, xirq_alternatives, 0),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1b, xirq_alternatives, 1),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2b, xirq_alternatives, 2),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3b, xirq_alternatives, 3),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4b, xirq_alternatives, 4),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5b, xirq_alternatives, 5),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6b, xirq_alternatives, 6),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7b, xirq_alternatives, 7),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8b, xirq_alternatives, 8),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9b, xirq_alternatives, 9),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10b, xirq_alternatives, 10),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11b, xirq_alternatives, 11),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13b, xirq_alternatives, 12),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14b, xirq_alternatives, 13),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16b, xirq_alternatives, 14),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17b, xirq_alternatives, 15),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18b, xirq_alternatives, 16),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19b, xirq_alternatives, 17),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20b, xirq_alternatives, 18),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq21b, xirq_alternatives, 19),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq22b, xirq_alternatives, 20),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq23b, xirq_alternatives, 21),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4c, xirq_alternatives, 22),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5c, xirq_alternatives, 23),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6c, xirq_alternatives, 24),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7c, xirq_alternatives, 25),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8c, xirq_alternatives, 26),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9c, xirq_alternatives, 27),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10c, xirq_alternatives, 28),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11c, xirq_alternatives, 29),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13c, xirq_alternatives, 30),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14c, xirq_alternatives, 31),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16c, xirq_alternatives, 32),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17c, xirq_alternatives, 33),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18c, xirq_alternatives, 34),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19c, xirq_alternatives, 35),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20c, xirq_alternatives, 36),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq21c, xirq_alternatives, 37),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq22c, xirq_alternatives, 38),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq23c, xirq_alternatives, 39),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17d, xirq_alternatives, 40),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18d, xirq_alternatives, 41),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq21d, xirq_alternatives, 42),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq22d, xirq_alternatives, 43),
+};
+
+static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
+static const char * const i2c0_groups[] = {"i2c0"};
+static const char * const i2c1_groups[] = {"i2c1"};
+static const char * const i2c3_groups[] = {"i2c3"};
+static const char * const i2c4_groups[] = {"i2c4"};
+static const char * const nand_groups[] = {"nand"};
+static const char * const sd_groups[] = {"sd"};
+static const char * const system_bus_groups[] = {"system_bus",
+						 "system_bus_cs1"};
+static const char * const uart0_groups[] = {"uart0"};
+static const char * const uart1_groups[] = {"uart1"};
+static const char * const uart2_groups[] = {"uart2"};
+static const char * const uart3_groups[] = {"uart3"};
+static const char * const usb0_groups[] = {"usb0"};
+static const char * const usb1_groups[] = {"usb1"};
+static const char * const usb2_groups[] = {"usb2"};
+static const char * const usb3_groups[] = {"usb3"};
+static const char * const port_groups[] = {
+	"port00",  "port01",  "port02",  "port03",
+	"port04",  "port05",  "port06",  "port07",
+	"port10",  "port11",  "port12",  "port13",
+	"port14",  "port15",  "port16",  "port17",
+	"port20",  "port21",  "port22",  "port23",
+	"port24",  "port25",  "port26",  "port27",
+	"port30",  "port31",  "port32",
+	/* port33-52 missing */          "port53",
+	"port54",  "port55",  "port56",  "port57",
+	"port60", /* port61-62 missing*/ "port63",
+	"port64",  "port65",  "port66",  "port67",
+	"port70",  "port71",  "port72",  "port73",
+	"port74",  "port75",  "port76",  "port77",
+	"port80",  "port81",  "port82",  "port83",
+	"port84",  "port85",  "port86",  "port87",
+	"port90",  "port91",  "port92",  "port93",
+	"port94",  "port95",  "port96",  "port97",
+	"port100", "port101", "port102", "port103",
+	"port104", "port105", "port106", "port107",
+	/* port110-117 missing */
+	"port120", "port121", "port122", "port123",
+	"port124", "port125", "port126", "port127",
+	"port130", "port131", "port132", "port133",
+	"port134", "port135", "port136", "port137",
+	"port140", "port141", "port142", "port143",
+	"port144", "port145", "port146", "port147",
+	/* port150-177 missing */
+	"port180", "port181", "port182", "port183",
+	"port184", "port185", "port186", "port187",
+	/* port190-197 missing */
+	"port200", "port201", "port202", "port203",
+	"port204", "port205", "port206", "port207",
+	"port210", "port211", "port212", "port213",
+	"port214", "port215", "port216", "port217",
+	"port220", "port221", "port222", "port223",
+	/* port224-227 missing */
+	"port230", "port231", "port232", "port233",
+	"port234", "port235", "port236", "port237",
+	"port240", "port241", "port242", "port243",
+	"port244", "port245", "port246", "port247",
+};
+static const char * const xirq_groups[] = {
+	"xirq0",  "xirq1",  "xirq2",  "xirq3",
+	"xirq4",  "xirq5",  "xirq6",  "xirq7",
+	"xirq8",  "xirq9",  "xirq10", "xirq11",
+	"xirq12", "xirq13", "xirq14", "xirq15",
+	"xirq16", "xirq17", "xirq18", "xirq19",
+	"xirq20", "xirq21", "xirq22", "xirq23",
+	"xirq0b",  "xirq1b",  "xirq2b",  "xirq3b",
+	"xirq4b",  "xirq5b",  "xirq6b",  "xirq7b",
+	"xirq8b",  "xirq9b",  "xirq10b", "xirq11b",
+	/* none */ "xirq13b", "xirq14b", /* none */
+	"xirq16b", "xirq17b", "xirq18b", "xirq19b",
+	"xirq20b", "xirq21b", "xirq22b", "xirq23b",
+	"xirq4c",  "xirq5c",  "xirq6c",  "xirq7c",
+	"xirq8c",  "xirq9c",  "xirq10c", "xirq11c",
+	/* none */ "xirq13c", "xirq14c", /* none */
+	"xirq16c", "xirq17c", "xirq18c", "xirq19c",
+	"xirq20c", "xirq21c", "xirq22c", "xirq23c",
+	"xirq17d", "xirq18d", "xirq21d", "xirq22d",
+};
+
+static const struct uniphier_pinmux_function uniphier_ld11_functions[] = {
+	UNIPHIER_PINMUX_FUNCTION(emmc),
+	UNIPHIER_PINMUX_FUNCTION(i2c0),
+	UNIPHIER_PINMUX_FUNCTION(i2c1),
+	UNIPHIER_PINMUX_FUNCTION(i2c3),
+	UNIPHIER_PINMUX_FUNCTION(i2c4),
+	UNIPHIER_PINMUX_FUNCTION(nand),
+	UNIPHIER_PINMUX_FUNCTION(sd),
+	UNIPHIER_PINMUX_FUNCTION(system_bus),
+	UNIPHIER_PINMUX_FUNCTION(uart0),
+	UNIPHIER_PINMUX_FUNCTION(uart1),
+	UNIPHIER_PINMUX_FUNCTION(uart2),
+	UNIPHIER_PINMUX_FUNCTION(uart3),
+	UNIPHIER_PINMUX_FUNCTION(usb0),
+	UNIPHIER_PINMUX_FUNCTION(usb1),
+	UNIPHIER_PINMUX_FUNCTION(usb2),
+	UNIPHIER_PINMUX_FUNCTION(usb3),
+	UNIPHIER_PINMUX_FUNCTION(port),
+	UNIPHIER_PINMUX_FUNCTION(xirq),
+};
+
+static struct uniphier_pinctrl_socdata uniphier_ld11_pindata = {
+	.pins = uniphier_ld11_pins,
+	.npins = ARRAY_SIZE(uniphier_ld11_pins),
+	.groups = uniphier_ld11_groups,
+	.groups_count = ARRAY_SIZE(uniphier_ld11_groups),
+	.functions = uniphier_ld11_functions,
+	.functions_count = ARRAY_SIZE(uniphier_ld11_functions),
+	.caps = UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL,
+};
+
+static int uniphier_ld11_pinctrl_probe(struct platform_device *pdev)
+{
+	return uniphier_pinctrl_probe(pdev, &uniphier_ld11_pindata);
+}
+
+static const struct of_device_id uniphier_ld11_pinctrl_match[] = {
+	{ .compatible = "socionext,uniphier-ld11-pinctrl" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, uniphier_ld11_pinctrl_match);
+
+static struct platform_driver uniphier_ld11_pinctrl_driver = {
+	.probe = uniphier_ld11_pinctrl_probe,
+	.driver = {
+		.name = "uniphier-ld11-pinctrl",
+		.of_match_table = uniphier_ld11_pinctrl_match,
+	},
+};
+module_platform_driver(uniphier_ld11_pinctrl_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-LD11 pinctrl driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:18 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:18 +0900
Subject: [PATCH 12/17] pinctrl: uniphier: support pin configuration for
 dedicated pins
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-13-git-send-email-yamada.masahiro@socionext.com>

PH1-LD4 and PH1-sLD8 SoCs have pins that support pin configuration
(pin biasing, drive strength control), but not pin-muxing.

Allow to fill the mux value table with -1 for those pins; pins with
mux value -1 will be skipped in the pin-mux set function.  The mux
value type should be changed from "unsigned" to "int" in order to
accommodate -1 as a special case.

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c |  5 ++-
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c  | 45 ++++++++++-----------
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c | 47 +++++++++++-----------
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c | 47 +++++++++++-----------
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c | 51 ++++++++++++------------
 drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c | 49 +++++++++++------------
 drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c | 45 ++++++++++-----------
 drivers/pinctrl/uniphier/pinctrl-uniphier.h      |  2 +-
 8 files changed, 144 insertions(+), 147 deletions(-)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index d774a8e..5bfcfa8 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -551,7 +551,7 @@ static int uniphier_pmx_get_function_groups(struct pinctrl_dev *pctldev,
 }
 
 static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
-				    unsigned muxval)
+				    int muxval)
 {
 	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
 	unsigned int mux_bits, reg_stride, reg, reg_end, shift, mask;
@@ -564,6 +564,9 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
 	if (ret)
 		return ret;
 
+	if (muxval < 0)
+		return 0;	/* dedicated pin; nothing to do for pin-mux */
+
 	if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
 		/*
 		 *  Mode     reg_offset     bit_position
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
index edea90d..9b59f8d 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
@@ -518,43 +518,42 @@ static const struct pinctrl_pin_desc uniphier_ld4_pins[] = {
 };
 
 static const unsigned emmc_pins[] = {21, 22, 23, 24, 25, 26, 27};
-static const unsigned emmc_muxvals[] = {0, 1, 1, 1, 1, 1, 1};
+static const int emmc_muxvals[] = {0, 1, 1, 1, 1, 1, 1};
 static const unsigned emmc_dat8_pins[] = {28, 29, 30, 31};
-static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
+static const int emmc_dat8_muxvals[] = {1, 1, 1, 1};
 static const unsigned i2c0_pins[] = {102, 103};
-static const unsigned i2c0_muxvals[] = {0, 0};
+static const int i2c0_muxvals[] = {0, 0};
 static const unsigned i2c1_pins[] = {104, 105};
-static const unsigned i2c1_muxvals[] = {0, 0};
+static const int i2c1_muxvals[] = {0, 0};
 static const unsigned i2c2_pins[] = {108, 109};
-static const unsigned i2c2_muxvals[] = {2, 2};
+static const int i2c2_muxvals[] = {2, 2};
 static const unsigned i2c3_pins[] = {108, 109};
-static const unsigned i2c3_muxvals[] = {3, 3};
+static const int i2c3_muxvals[] = {3, 3};
 static const unsigned nand_pins[] = {24, 25, 26, 27, 28, 29, 30, 31, 158, 159,
 				     160, 161, 162, 163, 164};
-static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-					0, 0};
+static const int nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned nand_cs1_pins[] = {22, 23};
-static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const int nand_cs1_muxvals[] = {0, 0};
 static const unsigned sd_pins[] = {44, 45, 46, 47, 48, 49, 50, 51, 52};
-static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const int sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned uart0_pins[] = {85, 88};
-static const unsigned uart0_muxvals[] = {1, 1};
+static const int uart0_muxvals[] = {1, 1};
 static const unsigned uart1_pins[] = {155, 156};
-static const unsigned uart1_muxvals[] = {13, 13};
+static const int uart1_muxvals[] = {13, 13};
 static const unsigned uart1b_pins[] = {69, 70};
-static const unsigned uart1b_muxvals[] = {23, 23};
+static const int uart1b_muxvals[] = {23, 23};
 static const unsigned uart2_pins[] = {128, 129};
-static const unsigned uart2_muxvals[] = {13, 13};
+static const int uart2_muxvals[] = {13, 13};
 static const unsigned uart3_pins[] = {110, 111};
-static const unsigned uart3_muxvals[] = {1, 1};
+static const int uart3_muxvals[] = {1, 1};
 static const unsigned usb0_pins[] = {53, 54};
-static const unsigned usb0_muxvals[] = {0, 0};
+static const int usb0_muxvals[] = {0, 0};
 static const unsigned usb1_pins[] = {55, 56};
-static const unsigned usb1_muxvals[] = {0, 0};
+static const int usb1_muxvals[] = {0, 0};
 static const unsigned usb2_pins[] = {155, 156};
-static const unsigned usb2_muxvals[] = {4, 4};
+static const int usb2_muxvals[] = {4, 4};
 static const unsigned usb2b_pins[] = {67, 68};
-static const unsigned usb2b_muxvals[] = {23, 23};
+static const int usb2b_muxvals[] = {23, 23};
 static const unsigned port_range0_pins[] = {
 	135, 136, 137, 138, 139, 140, 141, 142,		/* PORT0x */
 	143, 144, 145, 146, 147, 148, 149, 150,		/* PORT1x */
@@ -572,7 +571,7 @@ static const unsigned port_range0_pins[] = {
 	98, 99, 100, 6, 101, 114, 115, 116,		/* PORT13x */
 	103, 108, 21, 22, 23, 117, 118, 119,		/* PORT14x */
 };
-static const unsigned port_range0_muxvals[] = {
+static const int port_range0_muxvals[] = {
 	0, 0, 0, 0, 0, 0, 0, 0,				/* PORT0x */
 	0, 0, 0, 0, 0, 0, 0, 0,				/* PORT1x */
 	0, 0, 0, 0, 0, 0, 0, 15,			/* PORT2x */
@@ -592,21 +591,21 @@ static const unsigned port_range0_muxvals[] = {
 static const unsigned port_range1_pins[] = {
 	7,						/* PORT166 */
 };
-static const unsigned port_range1_muxvals[] = {
+static const int port_range1_muxvals[] = {
 	15,						/* PORT166 */
 };
 static const unsigned xirq_range0_pins[] = {
 	151, 123, 124, 125, 126, 127, 128, 129,		/* XIRQ0-7 */
 	130, 131, 132, 133, 62,				/* XIRQ8-12 */
 };
-static const unsigned xirq_range0_muxvals[] = {
+static const int xirq_range0_muxvals[] = {
 	14, 0, 0, 0, 0, 0, 0, 0,			/* XIRQ0-7 */
 	0, 0, 0, 0, 14,					/* XIRQ8-12 */
 };
 static const unsigned xirq_range1_pins[] = {
 	134, 63,					/* XIRQ14-15 */
 };
-static const unsigned xirq_range1_muxvals[] = {
+static const int xirq_range1_muxvals[] = {
 	0, 14,						/* XIRQ14-15 */
 };
 
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
index 2c9747b..638b342e 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
@@ -735,52 +735,51 @@ static const unsigned adinter_pins[] = {
 	215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
 	229, 230, 231, 232, 233, 234,
 };
-static const unsigned adinter_muxvals[] = {
+static const int adinter_muxvals[] = {
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0,
 };
 static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
-static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
+static const int emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
 static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
-static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
+static const int emmc_dat8_muxvals[] = {1, 1, 1, 1};
 static const unsigned i2c0_pins[] = {109, 110};
-static const unsigned i2c0_muxvals[] = {0, 0};
+static const int i2c0_muxvals[] = {0, 0};
 static const unsigned i2c1_pins[] = {111, 112};
-static const unsigned i2c1_muxvals[] = {0, 0};
+static const int i2c1_muxvals[] = {0, 0};
 static const unsigned i2c2_pins[] = {115, 116};
-static const unsigned i2c2_muxvals[] = {1, 1};
+static const int i2c2_muxvals[] = {1, 1};
 static const unsigned i2c3_pins[] = {118, 119};
-static const unsigned i2c3_muxvals[] = {1, 1};
+static const int i2c3_muxvals[] = {1, 1};
 static const unsigned nand_pins[] = {30, 31, 32, 33, 34, 35, 36, 39, 40, 41,
 				     42, 43, 44, 45, 46};
-static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-					0, 0};
+static const int nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned nand_cs1_pins[] = {37, 38};
-static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const int nand_cs1_muxvals[] = {0, 0};
 static const unsigned sd_pins[] = {47, 48, 49, 50, 51, 52, 53, 54, 55};
-static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const int sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned uart0_pins[] = {135, 136};
-static const unsigned uart0_muxvals[] = {3, 3};
+static const int uart0_muxvals[] = {3, 3};
 static const unsigned uart0b_pins[] = {11, 12};
-static const unsigned uart0b_muxvals[] = {2, 2};
+static const int uart0b_muxvals[] = {2, 2};
 static const unsigned uart1_pins[] = {115, 116};
-static const unsigned uart1_muxvals[] = {0, 0};
+static const int uart1_muxvals[] = {0, 0};
 static const unsigned uart1b_pins[] = {113, 114};
-static const unsigned uart1b_muxvals[] = {1, 1};
+static const int uart1b_muxvals[] = {1, 1};
 static const unsigned uart2_pins[] = {113, 114};
-static const unsigned uart2_muxvals[] = {2, 2};
+static const int uart2_muxvals[] = {2, 2};
 static const unsigned uart2b_pins[] = {86, 87};
-static const unsigned uart2b_muxvals[] = {1, 1};
+static const int uart2b_muxvals[] = {1, 1};
 static const unsigned usb0_pins[] = {56, 57};
-static const unsigned usb0_muxvals[] = {0, 0};
+static const int usb0_muxvals[] = {0, 0};
 static const unsigned usb1_pins[] = {58, 59};
-static const unsigned usb1_muxvals[] = {0, 0};
+static const int usb1_muxvals[] = {0, 0};
 static const unsigned usb2_pins[] = {60, 61};
-static const unsigned usb2_muxvals[] = {0, 0};
+static const int usb2_muxvals[] = {0, 0};
 static const unsigned usb3_pins[] = {62, 63};
-static const unsigned usb3_muxvals[] = {0, 0};
+static const int usb3_muxvals[] = {0, 0};
 static const unsigned port_range0_pins[] = {
 	127, 128, 129, 130, 131, 132, 133, 134,		/* PORT0x */
 	135, 136, 137, 138, 139, 140, 141, 142,		/* PORT1x */
@@ -794,7 +793,7 @@ static const unsigned port_range0_pins[] = {
 	61, 62, 63, 64, 65, 66, 67, 68,			/* PORT9x */
 	69, 70, 71, 76, 77, 78, 79, 80,			/* PORT10x */
 };
-static const unsigned port_range0_muxvals[] = {
+static const int port_range0_muxvals[] = {
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT0x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT1x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT2x */
@@ -826,7 +825,7 @@ static const unsigned port_range1_pins[] = {
 	218, 219, 220, 221, 223, 224, 225, 226,		/* PORT27x */
 	227, 228, 229, 230, 231, 232, 233, 234,		/* PORT28x */
 };
-static const unsigned port_range1_muxvals[] = {
+static const int port_range1_muxvals[] = {
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT12x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT13x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT14x */
@@ -850,7 +849,7 @@ static const unsigned xirq_pins[] = {
 	126, 72, 73, 92, 177, 93, 94, 176,		/* XIRQ8-15 */
 	74, 91, 27, 28, 29, 75, 20, 26,			/* XIRQ16-23 */
 };
-static const unsigned xirq_muxvals[] = {
+static const int xirq_muxvals[] = {
 	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ0-7 */
 	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ8-15 */
 	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ16-23 */
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
index 547359e..e973dd8 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
@@ -1010,46 +1010,45 @@ static const struct pinctrl_pin_desc uniphier_pro4_pins[] = {
 };
 
 static const unsigned emmc_pins[] = {40, 41, 42, 43, 51, 52, 53};
-static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
+static const int emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
 static const unsigned emmc_dat8_pins[] = {44, 45, 46, 47};
-static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
+static const int emmc_dat8_muxvals[] = {1, 1, 1, 1};
 static const unsigned i2c0_pins[] = {142, 143};
-static const unsigned i2c0_muxvals[] = {0, 0};
+static const int i2c0_muxvals[] = {0, 0};
 static const unsigned i2c1_pins[] = {144, 145};
-static const unsigned i2c1_muxvals[] = {0, 0};
+static const int i2c1_muxvals[] = {0, 0};
 static const unsigned i2c2_pins[] = {146, 147};
-static const unsigned i2c2_muxvals[] = {0, 0};
+static const int i2c2_muxvals[] = {0, 0};
 static const unsigned i2c3_pins[] = {148, 149};
-static const unsigned i2c3_muxvals[] = {0, 0};
+static const int i2c3_muxvals[] = {0, 0};
 static const unsigned i2c6_pins[] = {308, 309};
-static const unsigned i2c6_muxvals[] = {6, 6};
+static const int i2c6_muxvals[] = {6, 6};
 static const unsigned nand_pins[] = {40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
 				     50, 51, 52, 53, 54};
-static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-					0, 0};
+static const int nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned nand_cs1_pins[] = {131, 132};
-static const unsigned nand_cs1_muxvals[] = {1, 1};
+static const int nand_cs1_muxvals[] = {1, 1};
 static const unsigned sd_pins[] = {150, 151, 152, 153, 154, 155, 156, 157, 158};
-static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const int sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned sd1_pins[] = {319, 320, 321, 322, 323, 324, 325, 326,
 				    327};
-static const unsigned sd1_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const int sd1_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned uart0_pins[] = {127, 128};
-static const unsigned uart0_muxvals[] = {0, 0};
+static const int uart0_muxvals[] = {0, 0};
 static const unsigned uart1_pins[] = {129, 130};
-static const unsigned uart1_muxvals[] = {0, 0};
+static const int uart1_muxvals[] = {0, 0};
 static const unsigned uart2_pins[] = {131, 132};
-static const unsigned uart2_muxvals[] = {0, 0};
+static const int uart2_muxvals[] = {0, 0};
 static const unsigned uart3_pins[] = {88, 89};
-static const unsigned uart3_muxvals[] = {2, 2};
+static const int uart3_muxvals[] = {2, 2};
 static const unsigned usb0_pins[] = {180, 181};
-static const unsigned usb0_muxvals[] = {0, 0};
+static const int usb0_muxvals[] = {0, 0};
 static const unsigned usb1_pins[] = {182, 183};
-static const unsigned usb1_muxvals[] = {0, 0};
+static const int usb1_muxvals[] = {0, 0};
 static const unsigned usb2_pins[] = {184, 185};
-static const unsigned usb2_muxvals[] = {0, 0};
+static const int usb2_muxvals[] = {0, 0};
 static const unsigned usb3_pins[] = {186, 187};
-static const unsigned usb3_muxvals[] = {0, 0};
+static const int usb3_muxvals[] = {0, 0};
 static const unsigned port_range0_pins[] = {
 	300, 301, 302, 303, 304, 305, 306, 307,		/* PORT0x */
 	308, 309, 310, 311, 312, 313, 314, 315,		/* PORT1x */
@@ -1067,7 +1066,7 @@ static const unsigned port_range0_pins[] = {
 	76, 77, 78, 79, 80, 81, 82, 83,			/* PORT13x */
 	84, 85, 86, 87, 88, 89, 90, 91,			/* PORT14x */
 };
-static const unsigned port_range0_muxvals[] = {
+static const int port_range0_muxvals[] = {
 	7, 7, 7, 7, 7, 7, 7, 7,				/* PORT0x */
 	7, 7, 7, 7, 7, 7, 7, 7,				/* PORT1x */
 	7, 7, 7, 7, 7, 7, 7, 7,				/* PORT2x */
@@ -1100,7 +1099,7 @@ static const unsigned port_range1_pins[] = {
 	251, 252, 261, 262, 263, 264, 273, 274,		/* PORT29x */
 	31, 32, 33, 34, 35, 36, 37, 38,			/* PORT30x */
 };
-static const unsigned port_range1_muxvals[] = {
+static const int port_range1_muxvals[] = {
 	7, 7, 7,					/* PORT175-177 */
 	7, 7, 7, 7, 7, 7, 7, 7,				/* PORT18x */
 	7, 7, 7, 7, 7, 7, 7, 7,				/* PORT19x */
@@ -1121,7 +1120,7 @@ static const unsigned xirq_pins[] = {
 	234, 186, 99, 100, 101, 102, 184, 301,		/* XIRQ8-15 */
 	302, 303, 304, 305, 306,			/* XIRQ16-20 */
 };
-static const unsigned xirq_muxvals[] = {
+static const int xirq_muxvals[] = {
 	7, 7, 7, 7, 7, 7, 7, 7,				/* XIRQ0-7 */
 	7, 7, 7, 7, 7, 7, 2, 2,				/* XIRQ8-15 */
 	2, 2, 2, 2, 2,					/* XIRQ16-20 */
@@ -1129,7 +1128,7 @@ static const unsigned xirq_muxvals[] = {
 static const unsigned xirq_alternatives_pins[] = {
 	184, 310, 316,
 };
-static const unsigned xirq_alternatives_muxvals[] = {
+static const int xirq_alternatives_muxvals[] = {
 	2, 2, 2,
 };
 
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index 080332d..191c200 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -791,49 +791,48 @@ static const struct pinctrl_pin_desc uniphier_pro5_pins[] = {
 };
 
 static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
-static const unsigned emmc_muxvals[] = {0, 0, 0, 0, 0, 0, 0};
+static const int emmc_muxvals[] = {0, 0, 0, 0, 0, 0, 0};
 static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
-static const unsigned emmc_dat8_muxvals[] = {0, 0, 0, 0};
+static const int emmc_dat8_muxvals[] = {0, 0, 0, 0};
 static const unsigned i2c0_pins[] = {112, 113};
-static const unsigned i2c0_muxvals[] = {0, 0};
+static const int i2c0_muxvals[] = {0, 0};
 static const unsigned i2c1_pins[] = {114, 115};
-static const unsigned i2c1_muxvals[] = {0, 0};
+static const int i2c1_muxvals[] = {0, 0};
 static const unsigned i2c2_pins[] = {116, 117};
-static const unsigned i2c2_muxvals[] = {0, 0};
+static const int i2c2_muxvals[] = {0, 0};
 static const unsigned i2c3_pins[] = {118, 119};
-static const unsigned i2c3_muxvals[] = {0, 0};
+static const int i2c3_muxvals[] = {0, 0};
 static const unsigned i2c5_pins[] = {87, 88};
-static const unsigned i2c5_muxvals[] = {2, 2};
+static const int i2c5_muxvals[] = {2, 2};
 static const unsigned i2c5b_pins[] = {196, 197};
-static const unsigned i2c5b_muxvals[] = {2, 2};
+static const int i2c5b_muxvals[] = {2, 2};
 static const unsigned i2c5c_pins[] = {215, 216};
-static const unsigned i2c5c_muxvals[] = {2, 2};
+static const int i2c5c_muxvals[] = {2, 2};
 static const unsigned i2c6_pins[] = {101, 102};
-static const unsigned i2c6_muxvals[] = {2, 2};
+static const int i2c6_muxvals[] = {2, 2};
 static const unsigned nand_pins[] = {19, 20, 21, 22, 23, 24, 25, 28, 29, 30,
 				     31, 32, 33, 34, 35};
-static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-					0, 0};
+static const int nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned nand_cs1_pins[] = {26, 27};
-static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const int nand_cs1_muxvals[] = {0, 0};
 static const unsigned sd_pins[] = {250, 251, 252, 253, 254, 255, 256, 257, 258};
-static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const int sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned uart0_pins[] = {47, 48};
-static const unsigned uart0_muxvals[] = {0, 0};
+static const int uart0_muxvals[] = {0, 0};
 static const unsigned uart0b_pins[] = {227, 228};
-static const unsigned uart0b_muxvals[] = {3, 3};
+static const int uart0b_muxvals[] = {3, 3};
 static const unsigned uart1_pins[] = {49, 50};
-static const unsigned uart1_muxvals[] = {0, 0};
+static const int uart1_muxvals[] = {0, 0};
 static const unsigned uart2_pins[] = {51, 52};
-static const unsigned uart2_muxvals[] = {0, 0};
+static const int uart2_muxvals[] = {0, 0};
 static const unsigned uart3_pins[] = {53, 54};
-static const unsigned uart3_muxvals[] = {0, 0};
+static const int uart3_muxvals[] = {0, 0};
 static const unsigned usb0_pins[] = {124, 125};
-static const unsigned usb0_muxvals[] = {0, 0};
+static const int usb0_muxvals[] = {0, 0};
 static const unsigned usb1_pins[] = {126, 127};
-static const unsigned usb1_muxvals[] = {0, 0};
+static const int usb1_muxvals[] = {0, 0};
 static const unsigned usb2_pins[] = {128, 129};
-static const unsigned usb2_muxvals[] = {0, 0};
+static const int usb2_muxvals[] = {0, 0};
 static const unsigned port_range0_pins[] = {
 	89, 90, 91, 92, 93, 94, 95, 96,			/* PORT0x */
 	97, 98, 99, 100, 101, 102, 103, 104,		/* PORT1x */
@@ -851,7 +850,7 @@ static const unsigned port_range0_pins[] = {
 	179, 180, 181, 182, 186, 187, 188, 189,		/* PORT13x */
 	4, 5, 6, 7, 8, 9, 10, 11,			/* PORT14x */
 };
-static const unsigned port_range0_muxvals[] = {
+static const int port_range0_muxvals[] = {
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT0x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT1x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT2x */
@@ -884,7 +883,7 @@ static const unsigned port_range1_pins[] = {
 	105, 106, 18, 27, 36, 128, 132, 137,		/* PORT29x */
 	183, 184, 185, 84, 47, 48, 51, 52,		/* PORT30x */
 };
-static const unsigned port_range1_muxvals[] = {
+static const int port_range1_muxvals[] = {
 	15, 15, 15,					/* PORT175-177 */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT18x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT19x */
@@ -905,7 +904,7 @@ static const unsigned xirq_pins[] = {
 	76, 77, 78, 79, 80, 81, 82, 83,			/* XIRQ8-15 */
 	84, 85, 86, 87, 88,				/* XIRQ16-20 */
 };
-static const unsigned xirq_muxvals[] = {
+static const int xirq_muxvals[] = {
 	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ0-7 */
 	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ8-15 */
 	14, 14, 14, 14, 14,				/* XIRQ16-20 */
@@ -913,7 +912,7 @@ static const unsigned xirq_muxvals[] = {
 static const unsigned xirq_alternatives_pins[] = {
 	91, 92, 239, 144, 240, 156, 241, 106, 128,
 };
-static const unsigned xirq_alternatives_muxvals[] = {
+static const int xirq_alternatives_muxvals[] = {
 	14, 14, 14, 14, 14, 14, 14, 14, 14,
 };
 
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
index a2bf3f7..4349e99ff 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
@@ -728,49 +728,48 @@ static const struct pinctrl_pin_desc uniphier_pxs2_pins[] = {
 };
 
 static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
-static const unsigned emmc_muxvals[] = {9, 9, 9, 9, 9, 9, 9};
+static const int emmc_muxvals[] = {9, 9, 9, 9, 9, 9, 9};
 static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
-static const unsigned emmc_dat8_muxvals[] = {9, 9, 9, 9};
+static const int emmc_dat8_muxvals[] = {9, 9, 9, 9};
 static const unsigned i2c0_pins[] = {109, 110};
-static const unsigned i2c0_muxvals[] = {8, 8};
+static const int i2c0_muxvals[] = {8, 8};
 static const unsigned i2c1_pins[] = {111, 112};
-static const unsigned i2c1_muxvals[] = {8, 8};
+static const int i2c1_muxvals[] = {8, 8};
 static const unsigned i2c2_pins[] = {171, 172};
-static const unsigned i2c2_muxvals[] = {8, 8};
+static const int i2c2_muxvals[] = {8, 8};
 static const unsigned i2c3_pins[] = {159, 160};
-static const unsigned i2c3_muxvals[] = {8, 8};
+static const int i2c3_muxvals[] = {8, 8};
 static const unsigned i2c5_pins[] = {183, 184};
-static const unsigned i2c5_muxvals[] = {11, 11};
+static const int i2c5_muxvals[] = {11, 11};
 static const unsigned i2c6_pins[] = {185, 186};
-static const unsigned i2c6_muxvals[] = {11, 11};
+static const int i2c6_muxvals[] = {11, 11};
 static const unsigned nand_pins[] = {30, 31, 32, 33, 34, 35, 36, 39, 40, 41,
 				     42, 43, 44, 45, 46};
-static const unsigned nand_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-					8, 8};
+static const int nand_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
 static const unsigned nand_cs1_pins[] = {37, 38};
-static const unsigned nand_cs1_muxvals[] = {8, 8};
+static const int nand_cs1_muxvals[] = {8, 8};
 static const unsigned sd_pins[] = {47, 48, 49, 50, 51, 52, 53, 54, 55};
-static const unsigned sd_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8};
+static const int sd_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8};
 static const unsigned uart0_pins[] = {217, 218};
-static const unsigned uart0_muxvals[] = {8, 8};
+static const int uart0_muxvals[] = {8, 8};
 static const unsigned uart0b_pins[] = {179, 180};
-static const unsigned uart0b_muxvals[] = {10, 10};
+static const int uart0b_muxvals[] = {10, 10};
 static const unsigned uart1_pins[] = {115, 116};
-static const unsigned uart1_muxvals[] = {8, 8};
+static const int uart1_muxvals[] = {8, 8};
 static const unsigned uart2_pins[] = {113, 114};
-static const unsigned uart2_muxvals[] = {8, 8};
+static const int uart2_muxvals[] = {8, 8};
 static const unsigned uart3_pins[] = {219, 220};
-static const unsigned uart3_muxvals[] = {8, 8};
+static const int uart3_muxvals[] = {8, 8};
 static const unsigned uart3b_pins[] = {181, 182};
-static const unsigned uart3b_muxvals[] = {10, 10};
+static const int uart3b_muxvals[] = {10, 10};
 static const unsigned usb0_pins[] = {56, 57};
-static const unsigned usb0_muxvals[] = {8, 8};
+static const int usb0_muxvals[] = {8, 8};
 static const unsigned usb1_pins[] = {58, 59};
-static const unsigned usb1_muxvals[] = {8, 8};
+static const int usb1_muxvals[] = {8, 8};
 static const unsigned usb2_pins[] = {60, 61};
-static const unsigned usb2_muxvals[] = {8, 8};
+static const int usb2_muxvals[] = {8, 8};
 static const unsigned usb3_pins[] = {62, 63};
-static const unsigned usb3_muxvals[] = {8, 8};
+static const int usb3_muxvals[] = {8, 8};
 static const unsigned port_range0_pins[] = {
 	127, 128, 129, 130, 131, 132, 133, 134,		/* PORT0x */
 	135, 136, 137, 138, 139, 140, 141, 142,		/* PORT1x */
@@ -784,7 +783,7 @@ static const unsigned port_range0_pins[] = {
 	61, 62, 63, 64, 65, 66, 67, 68,			/* PORT9x */
 	69, 70, 71, 76, 77, 78, 79, 80,			/* PORT10x */
 };
-static const unsigned port_range0_muxvals[] = {
+static const int port_range0_muxvals[] = {
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT0x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT1x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT2x */
@@ -816,7 +815,7 @@ static const unsigned port_range1_pins[] = {
 	218, 219, 220, 221, 223, 224, 225, 226,		/* PORT27x */
 	227, 228, 229, 230, 231, 232, 233, 234,		/* PORT28x */
 };
-static const unsigned port_range1_muxvals[] = {
+static const int port_range1_muxvals[] = {
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT12x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT13x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT14x */
@@ -840,7 +839,7 @@ static const unsigned xirq_pins[] = {
 	126, 72, 73, 92, 177, 93, 94, 176,		/* XIRQ8-15 */
 	74, 91, 27, 28, 29, 75, 20, 26,			/* XIRQ16-23 */
 };
-static const unsigned xirq_muxvals[] = {
+static const int xirq_muxvals[] = {
 	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ0-7 */
 	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ8-15 */
 	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ16-23 */
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
index ef86693..d8b3655 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
@@ -431,39 +431,38 @@ static const struct pinctrl_pin_desc uniphier_sld8_pins[] = {
 };
 
 static const unsigned emmc_pins[] = {21, 22, 23, 24, 25, 26, 27};
-static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
+static const int emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
 static const unsigned emmc_dat8_pins[] = {28, 29, 30, 31};
-static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
+static const int emmc_dat8_muxvals[] = {1, 1, 1, 1};
 static const unsigned i2c0_pins[] = {102, 103};
-static const unsigned i2c0_muxvals[] = {0, 0};
+static const int i2c0_muxvals[] = {0, 0};
 static const unsigned i2c1_pins[] = {104, 105};
-static const unsigned i2c1_muxvals[] = {0, 0};
+static const int i2c1_muxvals[] = {0, 0};
 static const unsigned i2c2_pins[] = {108, 109};
-static const unsigned i2c2_muxvals[] = {2, 2};
+static const int i2c2_muxvals[] = {2, 2};
 static const unsigned i2c3_pins[] = {108, 109};
-static const unsigned i2c3_muxvals[] = {3, 3};
+static const int i2c3_muxvals[] = {3, 3};
 static const unsigned nand_pins[] = {15, 16, 17, 18, 19, 20, 21, 24, 25, 26,
 				     27, 28, 29, 30, 31};
-static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-					0, 0};
+static const int nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned nand_cs1_pins[] = {22, 23};
-static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const int nand_cs1_muxvals[] = {0, 0};
 static const unsigned sd_pins[] = {32, 33, 34, 35, 36, 37, 38, 39, 40};
-static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const int sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned uart0_pins[] = {70, 71};
-static const unsigned uart0_muxvals[] = {3, 3};
+static const int uart0_muxvals[] = {3, 3};
 static const unsigned uart1_pins[] = {114, 115};
-static const unsigned uart1_muxvals[] = {0, 0};
+static const int uart1_muxvals[] = {0, 0};
 static const unsigned uart2_pins[] = {112, 113};
-static const unsigned uart2_muxvals[] = {1, 1};
+static const int uart2_muxvals[] = {1, 1};
 static const unsigned uart3_pins[] = {110, 111};
-static const unsigned uart3_muxvals[] = {1, 1};
+static const int uart3_muxvals[] = {1, 1};
 static const unsigned usb0_pins[] = {41, 42};
-static const unsigned usb0_muxvals[] = {0, 0};
+static const int usb0_muxvals[] = {0, 0};
 static const unsigned usb1_pins[] = {43, 44};
-static const unsigned usb1_muxvals[] = {0, 0};
+static const int usb1_muxvals[] = {0, 0};
 static const unsigned usb2_pins[] = {114, 115};
-static const unsigned usb2_muxvals[] = {1, 1};
+static const int usb2_muxvals[] = {1, 1};
 static const unsigned port_range0_pins[] = {
 	0, 1, 2, 3, 4, 5, 6, 7,				/* PORT0x */
 	8, 9, 10, 11, 12, 13, 14, 15,			/* PORT1x */
@@ -479,7 +478,7 @@ static const unsigned port_range0_pins[] = {
 	48, 49, 46, 45, 123, 124, 125, 126,		/* PORT11x */
 	47, 127, 20, 56, 22,				/* PORT120-124 */
 };
-static const unsigned port_range0_muxvals[] = {
+static const int port_range0_muxvals[] = {
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT0x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT1x */
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT2x */
@@ -497,33 +496,33 @@ static const unsigned port_range0_muxvals[] = {
 static const unsigned port_range1_pins[] = {
 	116, 117,					/* PORT130-131 */
 };
-static const unsigned port_range1_muxvals[] = {
+static const int port_range1_muxvals[] = {
 	15, 15,						/* PORT130-131 */
 };
 static const unsigned port_range2_pins[] = {
 	102, 103, 104, 105, 106, 107, 108, 109,		/* PORT14x */
 };
-static const unsigned port_range2_muxvals[] = {
+static const int port_range2_muxvals[] = {
 	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT14x */
 };
 static const unsigned port_range3_pins[] = {
 	23,						/* PORT166 */
 };
-static const unsigned port_range3_muxvals[] = {
+static const int port_range3_muxvals[] = {
 	15,						/* PORT166 */
 };
 static const unsigned xirq_range0_pins[] = {
 	128, 129, 130, 131, 132, 133, 134, 135,		/* XIRQ0-7 */
 	82, 87, 88, 50, 51,				/* XIRQ8-12 */
 };
-static const unsigned xirq_range0_muxvals[] = {
+static const int xirq_range0_muxvals[] = {
 	0, 0, 0, 0, 0, 0, 0, 0,				/* XIRQ0-7 */
 	14, 14, 14, 14, 14,				/* XIRQ8-12 */
 };
 static const unsigned xirq_range1_pins[] = {
 	52, 58,						/* XIRQ14-15 */
 };
-static const unsigned xirq_range1_muxvals[] = {
+static const int xirq_range1_muxvals[] = {
 	14, 14,						/* XIRQ14-15 */
 };
 
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
index 9941a4c..923f36c 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
@@ -148,7 +148,7 @@ struct uniphier_pinctrl_group {
 	const char *name;
 	const unsigned *pins;
 	unsigned num_pins;
-	const unsigned *muxvals;
+	const int *muxvals;
 	enum uniphier_pinmux_gpio_range_type range_type;
 };
 
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:06 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:06 +0900
Subject: [PATCH 00/17] pinctrl: uniphier: many clean-ups and support new
 pinctrl drivers
Message-ID: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>


Here is a bunch of updates of UniPhier pinctrl drivers
(hopefully, for Linux 4.8-rc1).

Socionext Inc. developed two new ARMv8 SoCs this year.

New pinctrl driver support will be added by 16/17, 17/17.

But, before doing new development, it is usually nice
to clean the existing code.  So, this series also includes
several clean-up patches.

The new SoCs added some new SoC-specific features
(more fine-grained drive control, sparse pin space,
per-pin input enable gating, etc.), so I needed to update
the core support code for Uniphier pinctrl.

1/17 touches the core of pinctrl frame work, but
I included it in this series because it is a prerequisite
for 9/17.



Masahiro Yamada (17):
  pinctrl: copy per-pin driver private data to struct pin_desc
  pinctrl: uniphier: rename function and variable names
  pinctrl: uniphier: fix register offsets for drive strength control
  pinctrl: uniphier: set pinctrl_desc owner in common probe function
  pinctrl: uniphier: set pinctrl_desc name in common probe function
  pinctrl: uniphier: allocate struct pinctrl_desc in probe function
  pinctrl: uniphier: rename macros for drive strength control
  pinctrl: uniphier: support 3-bit drive strength control
  pinctrl: uniphier: support pin configuration in sparse pin space
  pinctrl: uniphier: introduce capability flag
  pinctrl: uniphier: support per-pin input enable for new SoCs
  pinctrl: uniphier: support pin configuration for dedicated pins
  pinctrl: uniphier: add dedicated pins to pin tables of PH1-LD4/sLD8
  pinctrl: uniphier: add System Bus pin-mux settings
  pinctrl: uniphier: allow to have pinctrl node under syscon node
  pinctrl: uniphier: add UniPhier PH1-LD11 pinctrl driver
  pinctrl: uniphier: add UniPhier PH1-LD20 pinctrl driver

 drivers/pinctrl/core.c                           |   22 +-
 drivers/pinctrl/core.h                           |    2 +
 drivers/pinctrl/uniphier/Kconfig                 |   20 +-
 drivers/pinctrl/uniphier/Makefile                |    2 +
 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c |  292 +++---
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c |  956 ++++++++++++++++++++
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c | 1037 ++++++++++++++++++++++
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c  |  480 +++++-----
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c |  595 +++++++------
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c |  787 ++++++++--------
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c |  653 +++++++-------
 drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c |  581 ++++++------
 drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c |  441 +++++----
 drivers/pinctrl/uniphier/pinctrl-uniphier.h      |   59 +-
 14 files changed, 4088 insertions(+), 1839 deletions(-)
 create mode 100644 drivers/pinctrl/uniphier/pinctrl-uniphier-ld11.c
 create mode 100644 drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c

-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:15 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:15 +0900
Subject: [PATCH 09/17] pinctrl: uniphier: support pin configuration in sparse
 pin space
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-10-git-send-email-yamada.masahiro@socionext.com>

Unfortunately, the pin number of the new SoC, PH1-LD11, is not
contiguous.  The base frame work must be adjusted to support the new
SoC pinctrl driver.  The pin_desc_get() exploits radix-tree for pin
look-up, so it works more efficiently with sparse pin space.

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 86 ++++++++++++------------
 1 file changed, 42 insertions(+), 44 deletions(-)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index 017b84f..39e3375 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -64,10 +64,10 @@ static int uniphier_pctl_get_group_pins(struct pinctrl_dev *pctldev,
 static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
 				       struct seq_file *s, unsigned offset)
 {
-	const struct pinctrl_pin_desc *pin = &pctldev->desc->pins[offset];
+	const struct pin_desc *desc = pin_desc_get(pctldev, offset);
 	const char *pull_dir, *drv_type;
 
-	switch (uniphier_pin_get_pull_dir(pin->drv_data)) {
+	switch (uniphier_pin_get_pull_dir(desc->drv_data)) {
 	case UNIPHIER_PIN_PULL_UP:
 		pull_dir = "UP";
 		break;
@@ -87,7 +87,7 @@ static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
 		BUG();
 	}
 
-	switch (uniphier_pin_get_drv_type(pin->drv_data)) {
+	switch (uniphier_pin_get_drv_type(desc->drv_data)) {
 	case UNIPHIER_PIN_DRV_1BIT:
 		drv_type = "4/8(mA)";
 		break;
@@ -129,12 +129,12 @@ static const struct pinctrl_ops uniphier_pctlops = {
 };
 
 static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
-				      const struct pinctrl_pin_desc *pin,
+				      const struct pin_desc *desc,
 				      enum pin_config_param param)
 {
 	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
 	enum uniphier_pin_pull_dir pull_dir =
-				uniphier_pin_get_pull_dir(pin->drv_data);
+				uniphier_pin_get_pull_dir(desc->drv_data);
 	unsigned int pupdctrl, reg, shift, val;
 	unsigned int expected = 1;
 	int ret;
@@ -164,7 +164,7 @@ static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
 		BUG();
 	}
 
-	pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data);
+	pupdctrl = uniphier_pin_get_pupdctrl(desc->drv_data);
 
 	reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
 	shift = pupdctrl % 32;
@@ -179,12 +179,12 @@ static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
 }
 
 static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
-				       const struct pinctrl_pin_desc *pin,
+				       const struct pin_desc *desc,
 				       u16 *strength)
 {
 	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
 	enum uniphier_pin_drv_type type =
-				uniphier_pin_get_drv_type(pin->drv_data);
+				uniphier_pin_get_drv_type(desc->drv_data);
 	const unsigned int strength_1bit[] = {4, 8};
 	const unsigned int strength_2bit[] = {8, 12, 16, 20};
 	const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12, 14, 16};
@@ -222,7 +222,7 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
 		return -EINVAL;
 	}
 
-	drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
+	drvctrl = uniphier_pin_get_drvctrl(desc->drv_data);
 	drvctrl *= width;
 
 	reg += drvctrl / 32 * 4;
@@ -239,10 +239,10 @@ static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
 }
 
 static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev *pctldev,
-					const struct pinctrl_pin_desc *pin)
+					      const struct pin_desc *desc)
 {
 	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
-	unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data);
+	unsigned int iectrl = uniphier_pin_get_iectrl(desc->drv_data);
 	unsigned int val;
 	int ret;
 
@@ -261,7 +261,7 @@ static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
 					unsigned pin,
 					unsigned long *configs)
 {
-	const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin];
+	const struct pin_desc *desc = pin_desc_get(pctldev, pin);
 	enum pin_config_param param = pinconf_to_config_param(*configs);
 	bool has_arg = false;
 	u16 arg;
@@ -271,14 +271,14 @@ static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
 	case PIN_CONFIG_BIAS_DISABLE:
 	case PIN_CONFIG_BIAS_PULL_UP:
 	case PIN_CONFIG_BIAS_PULL_DOWN:
-		ret = uniphier_conf_pin_bias_get(pctldev, pin_desc, param);
+		ret = uniphier_conf_pin_bias_get(pctldev, desc, param);
 		break;
 	case PIN_CONFIG_DRIVE_STRENGTH:
-		ret = uniphier_conf_pin_drive_get(pctldev, pin_desc, &arg);
+		ret = uniphier_conf_pin_drive_get(pctldev, desc, &arg);
 		has_arg = true;
 		break;
 	case PIN_CONFIG_INPUT_ENABLE:
-		ret = uniphier_conf_pin_input_enable_get(pctldev, pin_desc);
+		ret = uniphier_conf_pin_input_enable_get(pctldev, desc);
 		break;
 	default:
 		/* unsupported parameter */
@@ -293,13 +293,12 @@ static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
 }
 
 static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
-				      const struct pinctrl_pin_desc *pin,
-				      enum pin_config_param param,
-				      u16 arg)
+				      const struct pin_desc *desc,
+				      enum pin_config_param param, u16 arg)
 {
 	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
 	enum uniphier_pin_pull_dir pull_dir =
-				uniphier_pin_get_pull_dir(pin->drv_data);
+				uniphier_pin_get_pull_dir(desc->drv_data);
 	unsigned int pupdctrl, reg, shift;
 	unsigned int val = 1;
 
@@ -310,8 +309,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
 		if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||
 		    pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED) {
 			dev_err(pctldev->dev,
-				"can not disable pull register for pin %u (%s)\n",
-				pin->number, pin->name);
+				"can not disable pull register for pin %s\n",
+				desc->name);
 			return -EINVAL;
 		}
 		val = 0;
@@ -321,8 +320,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
 			return 0;
 		if (pull_dir != UNIPHIER_PIN_PULL_UP) {
 			dev_err(pctldev->dev,
-				"pull-up is unsupported for pin %u (%s)\n",
-				pin->number, pin->name);
+				"pull-up is unsupported for pin %s\n",
+				desc->name);
 			return -EINVAL;
 		}
 		if (arg == 0) {
@@ -335,8 +334,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
 			return 0;
 		if (pull_dir != UNIPHIER_PIN_PULL_DOWN) {
 			dev_err(pctldev->dev,
-				"pull-down is unsupported for pin %u (%s)\n",
-				pin->number, pin->name);
+				"pull-down is unsupported for pin %s\n",
+				desc->name);
 			return -EINVAL;
 		}
 		if (arg == 0) {
@@ -347,8 +346,8 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
 	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
 		if (pull_dir == UNIPHIER_PIN_PULL_NONE) {
 			dev_err(pctldev->dev,
-				"pull-up/down is unsupported for pin %u (%s)\n",
-				pin->number, pin->name);
+				"pull-up/down is unsupported for pin %s\n",
+				desc->name);
 			return -EINVAL;
 		}
 
@@ -359,7 +358,7 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
 		BUG();
 	}
 
-	pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data);
+	pupdctrl = uniphier_pin_get_pupdctrl(desc->drv_data);
 
 	reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
 	shift = pupdctrl % 32;
@@ -368,12 +367,12 @@ static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
 }
 
 static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
-				       const struct pinctrl_pin_desc *pin,
+				       const struct pin_desc *desc,
 				       u16 strength)
 {
 	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
 	enum uniphier_pin_drv_type type =
-				uniphier_pin_get_drv_type(pin->drv_data);
+				uniphier_pin_get_drv_type(desc->drv_data);
 	const unsigned int strength_1bit[] = {4, 8, -1};
 	const unsigned int strength_2bit[] = {8, 12, 16, 20, -1};
 	const unsigned int strength_3bit[] = {4, 5, 7, 9, 11, 12, 14, 16, -1};
@@ -398,8 +397,8 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
 		break;
 	default:
 		dev_err(pctldev->dev,
-			"cannot change drive strength for pin %u (%s)\n",
-			pin->number, pin->name);
+			"cannot change drive strength for pin %s\n",
+			desc->name);
 		return -EINVAL;
 	}
 
@@ -410,14 +409,14 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
 
 	if (val == 0) {
 		dev_err(pctldev->dev,
-			"unsupported drive strength %u mA for pin %u (%s)\n",
-			strength, pin->number, pin->name);
+			"unsupported drive strength %u mA for pin %s\n",
+			strength, desc->name);
 		return -EINVAL;
 	}
 
 	val--;
 
-	drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
+	drvctrl = uniphier_pin_get_drvctrl(desc->drv_data);
 	drvctrl *= width;
 
 	reg += drvctrl / 32 * 4;
@@ -429,11 +428,11 @@ static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
 }
 
 static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev,
-					  const struct pinctrl_pin_desc *pin,
+					  const struct pin_desc *desc,
 					  u16 enable)
 {
 	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
-	unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data);
+	unsigned int iectrl = uniphier_pin_get_iectrl(desc->drv_data);
 
 	if (enable == 0) {
 		/*
@@ -457,7 +456,7 @@ static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,
 					unsigned long *configs,
 					unsigned num_configs)
 {
-	const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin];
+	const struct pin_desc *desc = pin_desc_get(pctldev, pin);
 	int i, ret;
 
 	for (i = 0; i < num_configs; i++) {
@@ -470,16 +469,15 @@ static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,
 		case PIN_CONFIG_BIAS_PULL_UP:
 		case PIN_CONFIG_BIAS_PULL_DOWN:
 		case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
-			ret = uniphier_conf_pin_bias_set(pctldev, pin_desc,
+			ret = uniphier_conf_pin_bias_set(pctldev, desc,
 							 param, arg);
 			break;
 		case PIN_CONFIG_DRIVE_STRENGTH:
-			ret = uniphier_conf_pin_drive_set(pctldev, pin_desc,
-							  arg);
+			ret = uniphier_conf_pin_drive_set(pctldev, desc, arg);
 			break;
 		case PIN_CONFIG_INPUT_ENABLE:
-			ret = uniphier_conf_pin_input_enable(pctldev,
-							     pin_desc, arg);
+			ret = uniphier_conf_pin_input_enable(pctldev, desc,
+							     arg);
 			break;
 		default:
 			dev_err(pctldev->dev,
@@ -561,7 +559,7 @@ static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
 
 	/* some pins need input-enabling */
 	ret = uniphier_conf_pin_input_enable(pctldev,
-					     &pctldev->desc->pins[pin], 1);
+					     pin_desc_get(pctldev, pin), 1);
 	if (ret)
 		return ret;
 
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:08 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:08 +0900
Subject: [PATCH 02/17] pinctrl: uniphier: rename function and variable names
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-3-git-send-email-yamada.masahiro@socionext.com>

Make function/variable names match the file names for consistency.

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c  | 42 ++++++++++++------------
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c | 42 ++++++++++++------------
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c | 42 ++++++++++++------------
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c | 42 ++++++++++++------------
 drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c | 42 ++++++++++++------------
 drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c | 42 ++++++++++++------------
 6 files changed, 126 insertions(+), 126 deletions(-)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
index 4a0439c..fdcdc91 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
@@ -19,9 +19,9 @@
 
 #include "pinctrl-uniphier.h"
 
-#define DRIVER_NAME "ph1-ld4-pinctrl"
+#define DRIVER_NAME "uniphier-ld4-pinctrl"
 
-static const struct pinctrl_pin_desc ph1_ld4_pins[] = {
+static const struct pinctrl_pin_desc uniphier_ld4_pins[] = {
 	UNIPHIER_PINCTRL_PIN(0, "EA1", UNIPHIER_PIN_IECTRL_NONE,
 			     8, UNIPHIER_PIN_DRV_4_8,
 			     8, UNIPHIER_PIN_PULL_DOWN),
@@ -612,7 +612,7 @@ static const unsigned xirq_range1_muxvals[] = {
 	0, 14,						/* XIRQ14-15 */
 };
 
-static const struct uniphier_pinctrl_group ph1_ld4_groups[] = {
+static const struct uniphier_pinctrl_group uniphier_ld4_groups[] = {
 	UNIPHIER_PINCTRL_GROUP(emmc),
 	UNIPHIER_PINCTRL_GROUP(emmc_dat8),
 	UNIPHIER_PINCTRL_GROUP(i2c0),
@@ -828,7 +828,7 @@ static const char * const xirq_groups[] = {
 	"xirq12", /* none*/ "xirq14", "xirq15",
 };
 
-static const struct uniphier_pinmux_function ph1_ld4_functions[] = {
+static const struct uniphier_pinmux_function uniphier_ld4_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(emmc),
 	UNIPHIER_PINMUX_FUNCTION(i2c0),
 	UNIPHIER_PINMUX_FUNCTION(i2c1),
@@ -847,43 +847,43 @@ static const struct uniphier_pinmux_function ph1_ld4_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(xirq),
 };
 
-static struct uniphier_pinctrl_socdata ph1_ld4_pindata = {
-	.groups = ph1_ld4_groups,
-	.groups_count = ARRAY_SIZE(ph1_ld4_groups),
-	.functions = ph1_ld4_functions,
-	.functions_count = ARRAY_SIZE(ph1_ld4_functions),
+static struct uniphier_pinctrl_socdata uniphier_ld4_pindata = {
+	.groups = uniphier_ld4_groups,
+	.groups_count = ARRAY_SIZE(uniphier_ld4_groups),
+	.functions = uniphier_ld4_functions,
+	.functions_count = ARRAY_SIZE(uniphier_ld4_functions),
 	.mux_bits = 8,
 	.reg_stride = 4,
 	.load_pinctrl = false,
 };
 
-static struct pinctrl_desc ph1_ld4_pinctrl_desc = {
+static struct pinctrl_desc uniphier_ld4_pinctrl_desc = {
 	.name = DRIVER_NAME,
-	.pins = ph1_ld4_pins,
-	.npins = ARRAY_SIZE(ph1_ld4_pins),
+	.pins = uniphier_ld4_pins,
+	.npins = ARRAY_SIZE(uniphier_ld4_pins),
 	.owner = THIS_MODULE,
 };
 
-static int ph1_ld4_pinctrl_probe(struct platform_device *pdev)
+static int uniphier_ld4_pinctrl_probe(struct platform_device *pdev)
 {
-	return uniphier_pinctrl_probe(pdev, &ph1_ld4_pinctrl_desc,
-				      &ph1_ld4_pindata);
+	return uniphier_pinctrl_probe(pdev, &uniphier_ld4_pinctrl_desc,
+				      &uniphier_ld4_pindata);
 }
 
-static const struct of_device_id ph1_ld4_pinctrl_match[] = {
+static const struct of_device_id uniphier_ld4_pinctrl_match[] = {
 	{ .compatible = "socionext,ph1-ld4-pinctrl" },
 	{ /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, ph1_ld4_pinctrl_match);
+MODULE_DEVICE_TABLE(of, uniphier_ld4_pinctrl_match);
 
-static struct platform_driver ph1_ld4_pinctrl_driver = {
-	.probe = ph1_ld4_pinctrl_probe,
+static struct platform_driver uniphier_ld4_pinctrl_driver = {
+	.probe = uniphier_ld4_pinctrl_probe,
 	.driver = {
 		.name = DRIVER_NAME,
-		.of_match_table = ph1_ld4_pinctrl_match,
+		.of_match_table = uniphier_ld4_pinctrl_match,
 	},
 };
-module_platform_driver(ph1_ld4_pinctrl_driver);
+module_platform_driver(uniphier_ld4_pinctrl_driver);
 
 MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
 MODULE_DESCRIPTION("UniPhier PH1-LD4 pinctrl driver");
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
index 150d339..99a3e1a 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
@@ -19,9 +19,9 @@
 
 #include "pinctrl-uniphier.h"
 
-#define DRIVER_NAME "ph1-ld6b-pinctrl"
+#define DRIVER_NAME "uniphier-ld6b-pinctrl"
 
-static const struct pinctrl_pin_desc ph1_ld6b_pins[] = {
+static const struct pinctrl_pin_desc uniphier_ld6b_pins[] = {
 	UNIPHIER_PINCTRL_PIN(0, "ED0", UNIPHIER_PIN_IECTRL_NONE,
 			     0, UNIPHIER_PIN_DRV_4_8,
 			     0, UNIPHIER_PIN_PULL_DOWN),
@@ -858,7 +858,7 @@ static const unsigned xirq_muxvals[] = {
 	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ16-23 */
 };
 
-static const struct uniphier_pinctrl_group ph1_ld6b_groups[] = {
+static const struct uniphier_pinctrl_group uniphier_ld6b_groups[] = {
 	UNIPHIER_PINCTRL_GROUP(adinter),
 	UNIPHIER_PINCTRL_GROUP(emmc),
 	UNIPHIER_PINCTRL_GROUP(emmc_dat8),
@@ -1215,7 +1215,7 @@ static const char * const xirq_groups[] = {
 	"xirq20", "xirq21", "xirq22", "xirq23",
 };
 
-static const struct uniphier_pinmux_function ph1_ld6b_functions[] = {
+static const struct uniphier_pinmux_function uniphier_ld6b_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(adinter), /* Achip-Dchip interconnect */
 	UNIPHIER_PINMUX_FUNCTION(emmc),
 	UNIPHIER_PINMUX_FUNCTION(i2c0),
@@ -1235,43 +1235,43 @@ static const struct uniphier_pinmux_function ph1_ld6b_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(xirq),
 };
 
-static struct uniphier_pinctrl_socdata ph1_ld6b_pindata = {
-	.groups = ph1_ld6b_groups,
-	.groups_count = ARRAY_SIZE(ph1_ld6b_groups),
-	.functions = ph1_ld6b_functions,
-	.functions_count = ARRAY_SIZE(ph1_ld6b_functions),
+static struct uniphier_pinctrl_socdata uniphier_ld6b_pindata = {
+	.groups = uniphier_ld6b_groups,
+	.groups_count = ARRAY_SIZE(uniphier_ld6b_groups),
+	.functions = uniphier_ld6b_functions,
+	.functions_count = ARRAY_SIZE(uniphier_ld6b_functions),
 	.mux_bits = 8,
 	.reg_stride = 4,
 	.load_pinctrl = false,
 };
 
-static struct pinctrl_desc ph1_ld6b_pinctrl_desc = {
+static struct pinctrl_desc uniphier_ld6b_pinctrl_desc = {
 	.name = DRIVER_NAME,
-	.pins = ph1_ld6b_pins,
-	.npins = ARRAY_SIZE(ph1_ld6b_pins),
+	.pins = uniphier_ld6b_pins,
+	.npins = ARRAY_SIZE(uniphier_ld6b_pins),
 	.owner = THIS_MODULE,
 };
 
-static int ph1_ld6b_pinctrl_probe(struct platform_device *pdev)
+static int uniphier_ld6b_pinctrl_probe(struct platform_device *pdev)
 {
-	return uniphier_pinctrl_probe(pdev, &ph1_ld6b_pinctrl_desc,
-				      &ph1_ld6b_pindata);
+	return uniphier_pinctrl_probe(pdev, &uniphier_ld6b_pinctrl_desc,
+				      &uniphier_ld6b_pindata);
 }
 
-static const struct of_device_id ph1_ld6b_pinctrl_match[] = {
+static const struct of_device_id uniphier_ld6b_pinctrl_match[] = {
 	{ .compatible = "socionext,ph1-ld6b-pinctrl" },
 	{ /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, ph1_ld6b_pinctrl_match);
+MODULE_DEVICE_TABLE(of, uniphier_ld6b_pinctrl_match);
 
-static struct platform_driver ph1_ld6b_pinctrl_driver = {
-	.probe = ph1_ld6b_pinctrl_probe,
+static struct platform_driver uniphier_ld6b_pinctrl_driver = {
+	.probe = uniphier_ld6b_pinctrl_probe,
 	.driver = {
 		.name = DRIVER_NAME,
-		.of_match_table = ph1_ld6b_pinctrl_match,
+		.of_match_table = uniphier_ld6b_pinctrl_match,
 	},
 };
-module_platform_driver(ph1_ld6b_pinctrl_driver);
+module_platform_driver(uniphier_ld6b_pinctrl_driver);
 
 MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
 MODULE_DESCRIPTION("UniPhier PH1-LD6b pinctrl driver");
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
index b1f09e6..2d45307 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
@@ -19,9 +19,9 @@
 
 #include "pinctrl-uniphier.h"
 
-#define DRIVER_NAME "ph1-pro4-pinctrl"
+#define DRIVER_NAME "uniphier-pro4-pinctrl"
 
-static const struct pinctrl_pin_desc ph1_pro4_pins[] = {
+static const struct pinctrl_pin_desc uniphier_pro4_pins[] = {
 	UNIPHIER_PINCTRL_PIN(0, "CK24O", UNIPHIER_PIN_IECTRL_NONE,
 			     0, UNIPHIER_PIN_DRV_4_8,
 			     0, UNIPHIER_PIN_PULL_DOWN),
@@ -1135,7 +1135,7 @@ static const unsigned xirq_alternatives_muxvals[] = {
 	2, 2, 2,
 };
 
-static const struct uniphier_pinctrl_group ph1_pro4_groups[] = {
+static const struct uniphier_pinctrl_group uniphier_pro4_groups[] = {
 	UNIPHIER_PINCTRL_GROUP(emmc),
 	UNIPHIER_PINCTRL_GROUP(emmc_dat8),
 	UNIPHIER_PINCTRL_GROUP(i2c0),
@@ -1499,7 +1499,7 @@ static const char * const xirq_groups[] = {
 	"xirq14b", "xirq17b", "xirq18b",
 };
 
-static const struct uniphier_pinmux_function ph1_pro4_functions[] = {
+static const struct uniphier_pinmux_function uniphier_pro4_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(emmc),
 	UNIPHIER_PINMUX_FUNCTION(i2c0),
 	UNIPHIER_PINMUX_FUNCTION(i2c1),
@@ -1521,43 +1521,43 @@ static const struct uniphier_pinmux_function ph1_pro4_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(xirq),
 };
 
-static struct uniphier_pinctrl_socdata ph1_pro4_pindata = {
-	.groups = ph1_pro4_groups,
-	.groups_count = ARRAY_SIZE(ph1_pro4_groups),
-	.functions = ph1_pro4_functions,
-	.functions_count = ARRAY_SIZE(ph1_pro4_functions),
+static struct uniphier_pinctrl_socdata uniphier_pro4_pindata = {
+	.groups = uniphier_pro4_groups,
+	.groups_count = ARRAY_SIZE(uniphier_pro4_groups),
+	.functions = uniphier_pro4_functions,
+	.functions_count = ARRAY_SIZE(uniphier_pro4_functions),
 	.mux_bits = 4,
 	.reg_stride = 8,
 	.load_pinctrl = true,
 };
 
-static struct pinctrl_desc ph1_pro4_pinctrl_desc = {
+static struct pinctrl_desc uniphier_pro4_pinctrl_desc = {
 	.name = DRIVER_NAME,
-	.pins = ph1_pro4_pins,
-	.npins = ARRAY_SIZE(ph1_pro4_pins),
+	.pins = uniphier_pro4_pins,
+	.npins = ARRAY_SIZE(uniphier_pro4_pins),
 	.owner = THIS_MODULE,
 };
 
-static int ph1_pro4_pinctrl_probe(struct platform_device *pdev)
+static int uniphier_pro4_pinctrl_probe(struct platform_device *pdev)
 {
-	return uniphier_pinctrl_probe(pdev, &ph1_pro4_pinctrl_desc,
-				      &ph1_pro4_pindata);
+	return uniphier_pinctrl_probe(pdev, &uniphier_pro4_pinctrl_desc,
+				      &uniphier_pro4_pindata);
 }
 
-static const struct of_device_id ph1_pro4_pinctrl_match[] = {
+static const struct of_device_id uniphier_pro4_pinctrl_match[] = {
 	{ .compatible = "socionext,ph1-pro4-pinctrl" },
 	{ /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, ph1_pro4_pinctrl_match);
+MODULE_DEVICE_TABLE(of, uniphier_pro4_pinctrl_match);
 
-static struct platform_driver ph1_pro4_pinctrl_driver = {
-	.probe = ph1_pro4_pinctrl_probe,
+static struct platform_driver uniphier_pro4_pinctrl_driver = {
+	.probe = uniphier_pro4_pinctrl_probe,
 	.driver = {
 		.name = DRIVER_NAME,
-		.of_match_table = ph1_pro4_pinctrl_match,
+		.of_match_table = uniphier_pro4_pinctrl_match,
 	},
 };
-module_platform_driver(ph1_pro4_pinctrl_driver);
+module_platform_driver(uniphier_pro4_pinctrl_driver);
 
 MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
 MODULE_DESCRIPTION("UniPhier PH1-Pro4 pinctrl driver");
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index 3087f76..a96559c 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -19,9 +19,9 @@
 
 #include "pinctrl-uniphier.h"
 
-#define DRIVER_NAME "ph1-pro5-pinctrl"
+#define DRIVER_NAME "uniphier-pro5-pinctrl"
 
-static const struct pinctrl_pin_desc ph1_pro5_pins[] = {
+static const struct pinctrl_pin_desc uniphier_pro5_pins[] = {
 	UNIPHIER_PINCTRL_PIN(0, "AEXCKA1", 0,
 			     0, UNIPHIER_PIN_DRV_4_8,
 			     0, UNIPHIER_PIN_PULL_DOWN),
@@ -919,7 +919,7 @@ static const unsigned xirq_alternatives_muxvals[] = {
 	14, 14, 14, 14, 14, 14, 14, 14, 14,
 };
 
-static const struct uniphier_pinctrl_group ph1_pro5_groups[] = {
+static const struct uniphier_pinctrl_group uniphier_pro5_groups[] = {
 	UNIPHIER_PINCTRL_GROUP(nand),
 	UNIPHIER_PINCTRL_GROUP(nand_cs1),
 	UNIPHIER_PINCTRL_GROUP(emmc),
@@ -1291,7 +1291,7 @@ static const char * const xirq_groups[] = {
 	"xirq18b", "xirq18c", "xirq19b", "xirq20b",
 };
 
-static const struct uniphier_pinmux_function ph1_pro5_functions[] = {
+static const struct uniphier_pinmux_function uniphier_pro5_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(emmc),
 	UNIPHIER_PINMUX_FUNCTION(i2c0),
 	UNIPHIER_PINMUX_FUNCTION(i2c1),
@@ -1312,43 +1312,43 @@ static const struct uniphier_pinmux_function ph1_pro5_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(xirq),
 };
 
-static struct uniphier_pinctrl_socdata ph1_pro5_pindata = {
-	.groups = ph1_pro5_groups,
-	.groups_count = ARRAY_SIZE(ph1_pro5_groups),
-	.functions = ph1_pro5_functions,
-	.functions_count = ARRAY_SIZE(ph1_pro5_functions),
+static struct uniphier_pinctrl_socdata uniphier_pro5_pindata = {
+	.groups = uniphier_pro5_groups,
+	.groups_count = ARRAY_SIZE(uniphier_pro5_groups),
+	.functions = uniphier_pro5_functions,
+	.functions_count = ARRAY_SIZE(uniphier_pro5_functions),
 	.mux_bits = 4,
 	.reg_stride = 8,
 	.load_pinctrl = true,
 };
 
-static struct pinctrl_desc ph1_pro5_pinctrl_desc = {
+static struct pinctrl_desc uniphier_pro5_pinctrl_desc = {
 	.name = DRIVER_NAME,
-	.pins = ph1_pro5_pins,
-	.npins = ARRAY_SIZE(ph1_pro5_pins),
+	.pins = uniphier_pro5_pins,
+	.npins = ARRAY_SIZE(uniphier_pro5_pins),
 	.owner = THIS_MODULE,
 };
 
-static int ph1_pro5_pinctrl_probe(struct platform_device *pdev)
+static int uniphier_pro5_pinctrl_probe(struct platform_device *pdev)
 {
-	return uniphier_pinctrl_probe(pdev, &ph1_pro5_pinctrl_desc,
-				      &ph1_pro5_pindata);
+	return uniphier_pinctrl_probe(pdev, &uniphier_pro5_pinctrl_desc,
+				      &uniphier_pro5_pindata);
 }
 
-static const struct of_device_id ph1_pro5_pinctrl_match[] = {
+static const struct of_device_id uniphier_pro5_pinctrl_match[] = {
 	{ .compatible = "socionext,ph1-pro5-pinctrl" },
 	{ /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, ph1_pro5_pinctrl_match);
+MODULE_DEVICE_TABLE(of, uniphier_pro5_pinctrl_match);
 
-static struct platform_driver ph1_pro5_pinctrl_driver = {
-	.probe = ph1_pro5_pinctrl_probe,
+static struct platform_driver uniphier_pro5_pinctrl_driver = {
+	.probe = uniphier_pro5_pinctrl_probe,
 	.driver = {
 		.name = DRIVER_NAME,
-		.of_match_table = ph1_pro5_pinctrl_match,
+		.of_match_table = uniphier_pro5_pinctrl_match,
 	},
 };
-module_platform_driver(ph1_pro5_pinctrl_driver);
+module_platform_driver(uniphier_pro5_pinctrl_driver);
 
 MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
 MODULE_DESCRIPTION("UniPhier PH1-Pro5 pinctrl driver");
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
index e868030..8074460e 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
@@ -19,9 +19,9 @@
 
 #include "pinctrl-uniphier.h"
 
-#define DRIVER_NAME "proxstream2-pinctrl"
+#define DRIVER_NAME "uniphier-pxs2-pinctrl"
 
-static const struct pinctrl_pin_desc proxstream2_pins[] = {
+static const struct pinctrl_pin_desc uniphier_pxs2_pins[] = {
 	UNIPHIER_PINCTRL_PIN(0, "ED0", UNIPHIER_PIN_IECTRL_NONE,
 			     0, UNIPHIER_PIN_DRV_4_8,
 			     0, UNIPHIER_PIN_PULL_DOWN),
@@ -848,7 +848,7 @@ static const unsigned xirq_muxvals[] = {
 	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ16-23 */
 };
 
-static const struct uniphier_pinctrl_group proxstream2_groups[] = {
+static const struct uniphier_pinctrl_group uniphier_pxs2_groups[] = {
 	UNIPHIER_PINCTRL_GROUP(emmc),
 	UNIPHIER_PINCTRL_GROUP(emmc_dat8),
 	UNIPHIER_PINCTRL_GROUP(i2c0),
@@ -1208,7 +1208,7 @@ static const char * const xirq_groups[] = {
 	"xirq20", "xirq21", "xirq22", "xirq23",
 };
 
-static const struct uniphier_pinmux_function proxstream2_functions[] = {
+static const struct uniphier_pinmux_function uniphier_pxs2_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(emmc),
 	UNIPHIER_PINMUX_FUNCTION(i2c0),
 	UNIPHIER_PINMUX_FUNCTION(i2c1),
@@ -1230,43 +1230,43 @@ static const struct uniphier_pinmux_function proxstream2_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(xirq),
 };
 
-static struct uniphier_pinctrl_socdata proxstream2_pindata = {
-	.groups = proxstream2_groups,
-	.groups_count = ARRAY_SIZE(proxstream2_groups),
-	.functions = proxstream2_functions,
-	.functions_count = ARRAY_SIZE(proxstream2_functions),
+static struct uniphier_pinctrl_socdata uniphier_pxs2_pindata = {
+	.groups = uniphier_pxs2_groups,
+	.groups_count = ARRAY_SIZE(uniphier_pxs2_groups),
+	.functions = uniphier_pxs2_functions,
+	.functions_count = ARRAY_SIZE(uniphier_pxs2_functions),
 	.mux_bits = 8,
 	.reg_stride = 4,
 	.load_pinctrl = false,
 };
 
-static struct pinctrl_desc proxstream2_pinctrl_desc = {
+static struct pinctrl_desc uniphier_pxs2_pinctrl_desc = {
 	.name = DRIVER_NAME,
-	.pins = proxstream2_pins,
-	.npins = ARRAY_SIZE(proxstream2_pins),
+	.pins = uniphier_pxs2_pins,
+	.npins = ARRAY_SIZE(uniphier_pxs2_pins),
 	.owner = THIS_MODULE,
 };
 
-static int proxstream2_pinctrl_probe(struct platform_device *pdev)
+static int uniphier_pxs2_pinctrl_probe(struct platform_device *pdev)
 {
-	return uniphier_pinctrl_probe(pdev, &proxstream2_pinctrl_desc,
-				      &proxstream2_pindata);
+	return uniphier_pinctrl_probe(pdev, &uniphier_pxs2_pinctrl_desc,
+				      &uniphier_pxs2_pindata);
 }
 
-static const struct of_device_id proxstream2_pinctrl_match[] = {
+static const struct of_device_id uniphier_pxs2_pinctrl_match[] = {
 	{ .compatible = "socionext,proxstream2-pinctrl" },
 	{ /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, proxstream2_pinctrl_match);
+MODULE_DEVICE_TABLE(of, uniphier_pxs2_pinctrl_match);
 
-static struct platform_driver proxstream2_pinctrl_driver = {
-	.probe = proxstream2_pinctrl_probe,
+static struct platform_driver uniphier_pxs2_pinctrl_driver = {
+	.probe = uniphier_pxs2_pinctrl_probe,
 	.driver = {
 		.name = DRIVER_NAME,
-		.of_match_table = proxstream2_pinctrl_match,
+		.of_match_table = uniphier_pxs2_pinctrl_match,
 	},
 };
-module_platform_driver(proxstream2_pinctrl_driver);
+module_platform_driver(uniphier_pxs2_pinctrl_driver);
 
 MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
 MODULE_DESCRIPTION("UniPhier ProXstream2 pinctrl driver");
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
index ceb7a98..1e26b96 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
@@ -19,9 +19,9 @@
 
 #include "pinctrl-uniphier.h"
 
-#define DRIVER_NAME "ph1-sld8-pinctrl"
+#define DRIVER_NAME "uniphier-sld8-pinctrl"
 
-static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
+static const struct pinctrl_pin_desc uniphier_sld8_pins[] = {
 	UNIPHIER_PINCTRL_PIN(0, "PCA00", 0,
 			     15, UNIPHIER_PIN_DRV_4_8,
 			     15, UNIPHIER_PIN_PULL_DOWN),
@@ -529,7 +529,7 @@ static const unsigned xirq_range1_muxvals[] = {
 	14, 14,						/* XIRQ14-15 */
 };
 
-static const struct uniphier_pinctrl_group ph1_sld8_groups[] = {
+static const struct uniphier_pinctrl_group uniphier_sld8_groups[] = {
 	UNIPHIER_PINCTRL_GROUP(emmc),
 	UNIPHIER_PINCTRL_GROUP(emmc_dat8),
 	UNIPHIER_PINCTRL_GROUP(i2c0),
@@ -736,7 +736,7 @@ static const char * const xirq_groups[] = {
 	"xirq12", /* none*/ "xirq14", "xirq15",
 };
 
-static const struct uniphier_pinmux_function ph1_sld8_functions[] = {
+static const struct uniphier_pinmux_function uniphier_sld8_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(emmc),
 	UNIPHIER_PINMUX_FUNCTION(i2c0),
 	UNIPHIER_PINMUX_FUNCTION(i2c1),
@@ -755,43 +755,43 @@ static const struct uniphier_pinmux_function ph1_sld8_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(xirq),
 };
 
-static struct uniphier_pinctrl_socdata ph1_sld8_pindata = {
-	.groups = ph1_sld8_groups,
-	.groups_count = ARRAY_SIZE(ph1_sld8_groups),
-	.functions = ph1_sld8_functions,
-	.functions_count = ARRAY_SIZE(ph1_sld8_functions),
+static struct uniphier_pinctrl_socdata uniphier_sld8_pindata = {
+	.groups = uniphier_sld8_groups,
+	.groups_count = ARRAY_SIZE(uniphier_sld8_groups),
+	.functions = uniphier_sld8_functions,
+	.functions_count = ARRAY_SIZE(uniphier_sld8_functions),
 	.mux_bits = 8,
 	.reg_stride = 4,
 	.load_pinctrl = false,
 };
 
-static struct pinctrl_desc ph1_sld8_pinctrl_desc = {
+static struct pinctrl_desc uniphier_sld8_pinctrl_desc = {
 	.name = DRIVER_NAME,
-	.pins = ph1_sld8_pins,
-	.npins = ARRAY_SIZE(ph1_sld8_pins),
+	.pins = uniphier_sld8_pins,
+	.npins = ARRAY_SIZE(uniphier_sld8_pins),
 	.owner = THIS_MODULE,
 };
 
-static int ph1_sld8_pinctrl_probe(struct platform_device *pdev)
+static int uniphier_sld8_pinctrl_probe(struct platform_device *pdev)
 {
-	return uniphier_pinctrl_probe(pdev, &ph1_sld8_pinctrl_desc,
-				      &ph1_sld8_pindata);
+	return uniphier_pinctrl_probe(pdev, &uniphier_sld8_pinctrl_desc,
+				      &uniphier_sld8_pindata);
 }
 
-static const struct of_device_id ph1_sld8_pinctrl_match[] = {
+static const struct of_device_id uniphier_sld8_pinctrl_match[] = {
 	{ .compatible = "socionext,ph1-sld8-pinctrl" },
 	{ /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, ph1_sld8_pinctrl_match);
+MODULE_DEVICE_TABLE(of, uniphier_sld8_pinctrl_match);
 
-static struct platform_driver ph1_sld8_pinctrl_driver = {
-	.probe = ph1_sld8_pinctrl_probe,
+static struct platform_driver uniphier_sld8_pinctrl_driver = {
+	.probe = uniphier_sld8_pinctrl_probe,
 	.driver = {
 		.name = DRIVER_NAME,
-		.of_match_table = ph1_sld8_pinctrl_match,
+		.of_match_table = uniphier_sld8_pinctrl_match,
 	},
 };
-module_platform_driver(ph1_sld8_pinctrl_driver);
+module_platform_driver(uniphier_sld8_pinctrl_driver);
 
 MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
 MODULE_DESCRIPTION("UniPhier PH1-sLD8 pinctrl driver");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:20 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:20 +0900
Subject: [PATCH 14/17] pinctrl: uniphier: add System Bus pin-mux settings
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-15-git-send-email-yamada.masahiro@socionext.com>

This is needed to get access to UniPhier System Bus (external bus).

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c  | 23 ++++++++++++++
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c | 27 ++++++++++++++++
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c | 39 ++++++++++++++++++++++++
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c | 39 ++++++++++++++++++++++++
 drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c | 11 +++++++
 drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c | 27 ++++++++++++++++
 6 files changed, 166 insertions(+)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
index 6692e80..7437483 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
@@ -567,6 +567,18 @@ static const unsigned nand_cs1_pins[] = {22, 23};
 static const int nand_cs1_muxvals[] = {0, 0};
 static const unsigned sd_pins[] = {44, 45, 46, 47, 48, 49, 50, 51, 52};
 static const int sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned system_bus_pins[] = {16, 17, 18, 19, 20, 165, 166, 167,
+					   168, 169, 170, 171, 172, 173};
+static const int system_bus_muxvals[] = {0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1,
+					 -1, -1, -1};
+static const unsigned system_bus_cs0_pins[] = {155};
+static const int system_bus_cs0_muxvals[] = {1};
+static const unsigned system_bus_cs1_pins[] = {174};
+static const int system_bus_cs1_muxvals[] = {-1};
+static const unsigned system_bus_cs2_pins[] = {64};
+static const int system_bus_cs2_muxvals[] = {1};
+static const unsigned system_bus_cs3_pins[] = {156};
+static const int system_bus_cs3_muxvals[] = {1};
 static const unsigned uart0_pins[] = {85, 88};
 static const int uart0_muxvals[] = {1, 1};
 static const unsigned uart1_pins[] = {155, 156};
@@ -650,6 +662,11 @@ static const struct uniphier_pinctrl_group uniphier_ld4_groups[] = {
 	UNIPHIER_PINCTRL_GROUP(nand),
 	UNIPHIER_PINCTRL_GROUP(nand_cs1),
 	UNIPHIER_PINCTRL_GROUP(sd),
+	UNIPHIER_PINCTRL_GROUP(system_bus),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs0),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs1),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs2),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs3),
 	UNIPHIER_PINCTRL_GROUP(uart0),
 	UNIPHIER_PINCTRL_GROUP(uart1),
 	UNIPHIER_PINCTRL_GROUP(uart1b),
@@ -808,6 +825,11 @@ static const char * const i2c2_groups[] = {"i2c2"};
 static const char * const i2c3_groups[] = {"i2c3"};
 static const char * const nand_groups[] = {"nand", "nand_cs1"};
 static const char * const sd_groups[] = {"sd"};
+static const char * const system_bus_groups[] = {"system_bus",
+						 "system_bus_cs0",
+						 "system_bus_cs1",
+						 "system_bus_cs2",
+						 "system_bus_cs3"};
 static const char * const uart0_groups[] = {"uart0"};
 static const char * const uart1_groups[] = {"uart1", "uart1b"};
 static const char * const uart2_groups[] = {"uart2"};
@@ -864,6 +886,7 @@ static const struct uniphier_pinmux_function uniphier_ld4_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(i2c3),
 	UNIPHIER_PINMUX_FUNCTION(nand),
 	UNIPHIER_PINMUX_FUNCTION(sd),
+	UNIPHIER_PINMUX_FUNCTION(system_bus),
 	UNIPHIER_PINMUX_FUNCTION(uart0),
 	UNIPHIER_PINMUX_FUNCTION(uart1),
 	UNIPHIER_PINMUX_FUNCTION(uart2),
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
index 638b342e..d575194 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
@@ -760,6 +760,20 @@ static const unsigned nand_cs1_pins[] = {37, 38};
 static const int nand_cs1_muxvals[] = {0, 0};
 static const unsigned sd_pins[] = {47, 48, 49, 50, 51, 52, 53, 54, 55};
 static const int sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned system_bus_pins[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+					   11, 12, 13};
+static const int system_bus_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+					 0};
+static const unsigned system_bus_cs1_pins[] = {14};
+static const int system_bus_cs1_muxvals[] = {0};
+static const unsigned system_bus_cs2_pins[] = {37};
+static const int system_bus_cs2_muxvals[] = {6};
+static const unsigned system_bus_cs3_pins[] = {38};
+static const int system_bus_cs3_muxvals[] = {6};
+static const unsigned system_bus_cs4_pins[] = {115};
+static const int system_bus_cs4_muxvals[] = {6};
+static const unsigned system_bus_cs5_pins[] = {55};
+static const int system_bus_cs5_muxvals[] = {6};
 static const unsigned uart0_pins[] = {135, 136};
 static const int uart0_muxvals[] = {3, 3};
 static const unsigned uart0b_pins[] = {11, 12};
@@ -866,6 +880,12 @@ static const struct uniphier_pinctrl_group uniphier_ld6b_groups[] = {
 	UNIPHIER_PINCTRL_GROUP(nand),
 	UNIPHIER_PINCTRL_GROUP(nand_cs1),
 	UNIPHIER_PINCTRL_GROUP(sd),
+	UNIPHIER_PINCTRL_GROUP(system_bus),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs1),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs2),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs3),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs4),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs5),
 	UNIPHIER_PINCTRL_GROUP(uart0),
 	UNIPHIER_PINCTRL_GROUP(uart0b),
 	UNIPHIER_PINCTRL_GROUP(uart1),
@@ -1137,6 +1157,12 @@ static const char * const i2c2_groups[] = {"i2c2"};
 static const char * const i2c3_groups[] = {"i2c3"};
 static const char * const nand_groups[] = {"nand", "nand_cs1"};
 static const char * const sd_groups[] = {"sd"};
+static const char * const system_bus_groups[] = {"system_bus",
+						 "system_bus_cs1",
+						 "system_bus_cs2",
+						 "system_bus_cs3",
+						 "system_bus_cs4",
+						 "system_bus_cs5"};
 static const char * const uart0_groups[] = {"uart0", "uart0b"};
 static const char * const uart1_groups[] = {"uart1", "uart1b"};
 static const char * const uart2_groups[] = {"uart2", "uart2b"};
@@ -1221,6 +1247,7 @@ static const struct uniphier_pinmux_function uniphier_ld6b_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(i2c3),
 	UNIPHIER_PINMUX_FUNCTION(nand),
 	UNIPHIER_PINMUX_FUNCTION(sd),
+	UNIPHIER_PINMUX_FUNCTION(system_bus),
 	UNIPHIER_PINMUX_FUNCTION(uart0),
 	UNIPHIER_PINMUX_FUNCTION(uart1),
 	UNIPHIER_PINMUX_FUNCTION(uart2),
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
index e973dd8..35c5c51 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
@@ -1033,6 +1033,26 @@ static const int sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
 static const unsigned sd1_pins[] = {319, 320, 321, 322, 323, 324, 325, 326,
 				    327};
 static const int sd1_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned system_bus_pins[] = {25, 26, 27, 28, 29, 30, 31, 32, 33,
+					   34, 35, 36, 37, 38};
+static const int system_bus_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+					 0};
+static const unsigned system_bus_cs0_pins[] = {318};
+static const int system_bus_cs0_muxvals[] = {5};
+static const unsigned system_bus_cs1_pins[] = {24};
+static const int system_bus_cs1_muxvals[] = {0};
+static const unsigned system_bus_cs2_pins[] = {315};
+static const int system_bus_cs2_muxvals[] = {5};
+static const unsigned system_bus_cs3_pins[] = {313};
+static const int system_bus_cs3_muxvals[] = {5};
+static const unsigned system_bus_cs4_pins[] = {305};
+static const int system_bus_cs4_muxvals[] = {5};
+static const unsigned system_bus_cs5_pins[] = {303};
+static const int system_bus_cs5_muxvals[] = {6};
+static const unsigned system_bus_cs6_pins[] = {307};
+static const int system_bus_cs6_muxvals[] = {6};
+static const unsigned system_bus_cs7_pins[] = {312};
+static const int system_bus_cs7_muxvals[] = {6};
 static const unsigned uart0_pins[] = {127, 128};
 static const int uart0_muxvals[] = {0, 0};
 static const unsigned uart1_pins[] = {129, 130};
@@ -1144,6 +1164,15 @@ static const struct uniphier_pinctrl_group uniphier_pro4_groups[] = {
 	UNIPHIER_PINCTRL_GROUP(nand_cs1),
 	UNIPHIER_PINCTRL_GROUP(sd),
 	UNIPHIER_PINCTRL_GROUP(sd1),
+	UNIPHIER_PINCTRL_GROUP(system_bus),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs0),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs1),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs2),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs3),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs4),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs5),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs6),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs7),
 	UNIPHIER_PINCTRL_GROUP(uart0),
 	UNIPHIER_PINCTRL_GROUP(uart1),
 	UNIPHIER_PINCTRL_GROUP(uart2),
@@ -1418,6 +1447,15 @@ static const char * const i2c6_groups[] = {"i2c6"};
 static const char * const nand_groups[] = {"nand", "nand_cs1"};
 static const char * const sd_groups[] = {"sd"};
 static const char * const sd1_groups[] = {"sd1"};
+static const char * const system_bus_groups[] = {"system_bus",
+						 "system_bus_cs0",
+						 "system_bus_cs1",
+						 "system_bus_cs2",
+						 "system_bus_cs3",
+						 "system_bus_cs4",
+						 "system_bus_cs5",
+						 "system_bus_cs6",
+						 "system_bus_cs7"};
 static const char * const uart0_groups[] = {"uart0"};
 static const char * const uart1_groups[] = {"uart1"};
 static const char * const uart2_groups[] = {"uart2"};
@@ -1506,6 +1544,7 @@ static const struct uniphier_pinmux_function uniphier_pro4_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(nand),
 	UNIPHIER_PINMUX_FUNCTION(sd),
 	UNIPHIER_PINMUX_FUNCTION(sd1),
+	UNIPHIER_PINMUX_FUNCTION(system_bus),
 	UNIPHIER_PINMUX_FUNCTION(uart0),
 	UNIPHIER_PINMUX_FUNCTION(uart1),
 	UNIPHIER_PINMUX_FUNCTION(uart2),
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index 191c200..f94eb42 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -817,6 +817,26 @@ static const unsigned nand_cs1_pins[] = {26, 27};
 static const int nand_cs1_muxvals[] = {0, 0};
 static const unsigned sd_pins[] = {250, 251, 252, 253, 254, 255, 256, 257, 258};
 static const int sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned system_bus_pins[] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+					   14, 15, 16, 17};
+static const int system_bus_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+					 0};
+static const unsigned system_bus_cs0_pins[] = {105};
+static const int system_bus_cs0_muxvals[] = {1};
+static const unsigned system_bus_cs1_pins[] = {18};
+static const int system_bus_cs1_muxvals[] = {0};
+static const unsigned system_bus_cs2_pins[] = {106};
+static const int system_bus_cs2_muxvals[] = {1};
+static const unsigned system_bus_cs3_pins[] = {100};
+static const int system_bus_cs3_muxvals[] = {1};
+static const unsigned system_bus_cs4_pins[] = {101};
+static const int system_bus_cs4_muxvals[] = {1};
+static const unsigned system_bus_cs5_pins[] = {102};
+static const int system_bus_cs5_muxvals[] = {1};
+static const unsigned system_bus_cs6_pins[] = {69};
+static const int system_bus_cs6_muxvals[] = {5};
+static const unsigned system_bus_cs7_pins[] = {70};
+static const int system_bus_cs7_muxvals[] = {5};
 static const unsigned uart0_pins[] = {47, 48};
 static const int uart0_muxvals[] = {0, 0};
 static const unsigned uart0b_pins[] = {227, 228};
@@ -930,6 +950,15 @@ static const struct uniphier_pinctrl_group uniphier_pro5_groups[] = {
 	UNIPHIER_PINCTRL_GROUP(i2c5c),
 	UNIPHIER_PINCTRL_GROUP(i2c6),
 	UNIPHIER_PINCTRL_GROUP(sd),
+	UNIPHIER_PINCTRL_GROUP(system_bus),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs0),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs1),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs2),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs3),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs4),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs5),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs6),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs7),
 	UNIPHIER_PINCTRL_GROUP(uart0),
 	UNIPHIER_PINCTRL_GROUP(uart0b),
 	UNIPHIER_PINCTRL_GROUP(uart1),
@@ -1210,6 +1239,15 @@ static const char * const i2c5_groups[] = {"i2c5", "i2c5b", "i2c5c"};
 static const char * const i2c6_groups[] = {"i2c6"};
 static const char * const nand_groups[] = {"nand", "nand_cs1"};
 static const char * const sd_groups[] = {"sd"};
+static const char * const system_bus_groups[] = {"system_bus",
+						 "system_bus_cs0",
+						 "system_bus_cs1",
+						 "system_bus_cs2",
+						 "system_bus_cs3",
+						 "system_bus_cs4",
+						 "system_bus_cs5",
+						 "system_bus_cs6",
+						 "system_bus_cs7"};
 static const char * const uart0_groups[] = {"uart0", "uart0b"};
 static const char * const uart1_groups[] = {"uart1"};
 static const char * const uart2_groups[] = {"uart2"};
@@ -1298,6 +1336,7 @@ static const struct uniphier_pinmux_function uniphier_pro5_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(i2c6),
 	UNIPHIER_PINMUX_FUNCTION(nand),
 	UNIPHIER_PINMUX_FUNCTION(sd),
+	UNIPHIER_PINMUX_FUNCTION(system_bus),
 	UNIPHIER_PINMUX_FUNCTION(uart0),
 	UNIPHIER_PINMUX_FUNCTION(uart1),
 	UNIPHIER_PINMUX_FUNCTION(uart2),
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
index 4349e99ff..c879be3 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
@@ -750,6 +750,12 @@ static const unsigned nand_cs1_pins[] = {37, 38};
 static const int nand_cs1_muxvals[] = {8, 8};
 static const unsigned sd_pins[] = {47, 48, 49, 50, 51, 52, 53, 54, 55};
 static const int sd_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8};
+static const unsigned system_bus_pins[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+					   11, 12, 13};
+static const int system_bus_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+					 8};
+static const unsigned system_bus_cs1_pins[] = {14};
+static const int system_bus_cs1_muxvals[] = {8};
 static const unsigned uart0_pins[] = {217, 218};
 static const int uart0_muxvals[] = {8, 8};
 static const unsigned uart0b_pins[] = {179, 180};
@@ -857,6 +863,8 @@ static const struct uniphier_pinctrl_group uniphier_pxs2_groups[] = {
 	UNIPHIER_PINCTRL_GROUP(nand),
 	UNIPHIER_PINCTRL_GROUP(nand_cs1),
 	UNIPHIER_PINCTRL_GROUP(sd),
+	UNIPHIER_PINCTRL_GROUP(system_bus),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs1),
 	UNIPHIER_PINCTRL_GROUP(uart0),
 	UNIPHIER_PINCTRL_GROUP(uart0b),
 	UNIPHIER_PINCTRL_GROUP(uart1),
@@ -1129,6 +1137,8 @@ static const char * const i2c5_groups[] = {"i2c5"};
 static const char * const i2c6_groups[] = {"i2c6"};
 static const char * const nand_groups[] = {"nand", "nand_cs1"};
 static const char * const sd_groups[] = {"sd"};
+static const char * const system_bus_groups[] = {"system_bus",
+						 "system_bus_cs1"};
 static const char * const uart0_groups[] = {"uart0", "uart0b"};
 static const char * const uart1_groups[] = {"uart1"};
 static const char * const uart2_groups[] = {"uart2"};
@@ -1215,6 +1225,7 @@ static const struct uniphier_pinmux_function uniphier_pxs2_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(i2c6),
 	UNIPHIER_PINMUX_FUNCTION(nand),
 	UNIPHIER_PINMUX_FUNCTION(sd),
+	UNIPHIER_PINMUX_FUNCTION(system_bus),
 	UNIPHIER_PINMUX_FUNCTION(uart0),
 	UNIPHIER_PINMUX_FUNCTION(uart1),
 	UNIPHIER_PINMUX_FUNCTION(uart2),
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
index 1bda223..096a460 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
@@ -495,6 +495,20 @@ static const unsigned nand_cs1_pins[] = {22, 23};
 static const int nand_cs1_muxvals[] = {0, 0};
 static const unsigned sd_pins[] = {32, 33, 34, 35, 36, 37, 38, 39, 40};
 static const int sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned system_bus_pins[] = {136, 137, 138, 139, 140, 141, 142,
+					   143, 144, 145, 146, 147, 148, 149};
+static const int system_bus_muxvals[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+					 -1, -1, -1, -1, -1};
+static const unsigned system_bus_cs1_pins[] = {150};
+static const int system_bus_cs1_muxvals[] = {-1};
+static const unsigned system_bus_cs2_pins[] = {10};
+static const int system_bus_cs2_muxvals[] = {1};
+static const unsigned system_bus_cs3_pins[] = {11};
+static const int system_bus_cs3_muxvals[] = {1};
+static const unsigned system_bus_cs4_pins[] = {12};
+static const int system_bus_cs4_muxvals[] = {1};
+static const unsigned system_bus_cs5_pins[] = {13};
+static const int system_bus_cs5_muxvals[] = {1};
 static const unsigned uart0_pins[] = {70, 71};
 static const int uart0_muxvals[] = {3, 3};
 static const unsigned uart1_pins[] = {114, 115};
@@ -582,6 +596,12 @@ static const struct uniphier_pinctrl_group uniphier_sld8_groups[] = {
 	UNIPHIER_PINCTRL_GROUP(nand),
 	UNIPHIER_PINCTRL_GROUP(nand_cs1),
 	UNIPHIER_PINCTRL_GROUP(sd),
+	UNIPHIER_PINCTRL_GROUP(system_bus),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs1),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs2),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs3),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs4),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs5),
 	UNIPHIER_PINCTRL_GROUP(uart0),
 	UNIPHIER_PINCTRL_GROUP(uart1),
 	UNIPHIER_PINCTRL_GROUP(uart2),
@@ -731,6 +751,12 @@ static const char * const i2c2_groups[] = {"i2c2"};
 static const char * const i2c3_groups[] = {"i2c3"};
 static const char * const nand_groups[] = {"nand", "nand_cs1"};
 static const char * const sd_groups[] = {"sd"};
+static const char * const system_bus_groups[] = {"system_bus",
+						 "system_bus_cs1",
+						 "system_bus_cs2",
+						 "system_bus_cs3",
+						 "system_bus_cs4",
+						 "system_bus_cs5"};
 static const char * const uart0_groups[] = {"uart0"};
 static const char * const uart1_groups[] = {"uart1"};
 static const char * const uart2_groups[] = {"uart2"};
@@ -787,6 +813,7 @@ static const struct uniphier_pinmux_function uniphier_sld8_functions[] = {
 	UNIPHIER_PINMUX_FUNCTION(i2c3),
 	UNIPHIER_PINMUX_FUNCTION(nand),
 	UNIPHIER_PINMUX_FUNCTION(sd),
+	UNIPHIER_PINMUX_FUNCTION(system_bus),
 	UNIPHIER_PINMUX_FUNCTION(uart0),
 	UNIPHIER_PINMUX_FUNCTION(uart1),
 	UNIPHIER_PINMUX_FUNCTION(uart2),
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:17 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:17 +0900
Subject: [PATCH 11/17] pinctrl: uniphier: support per-pin input enable for new
 SoCs
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-12-git-send-email-yamada.masahiro@socionext.com>

Upcoming new pinctrl drivers for PH1-LD11 and PH-LD20 support input
signal gating for each pin.  (While, existing ones only support it
per pin-group.)  This commit updates the core part for that.

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-core.c | 24 +++++++++++++-----------
 drivers/pinctrl/uniphier/pinctrl-uniphier.h      |  1 +
 2 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
index ca2562a..d774a8e 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
@@ -433,22 +433,24 @@ static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev,
 {
 	struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
 	unsigned int iectrl = uniphier_pin_get_iectrl(desc->drv_data);
+	unsigned int reg, mask;
 
-	if (enable == 0) {
-		/*
-		 * Multiple pins share one input enable, so per-pin disabling
-		 * is impossible.
-		 */
-		dev_err(pctldev->dev, "unable to disable input\n");
+	/*
+	 * Multiple pins share one input enable, per-pin disabling is
+	 * impossible.
+	 */
+	if (!(priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL) &&
+	    !enable)
 		return -EINVAL;
-	}
 
+	/* UNIPHIER_PIN_IECTRL_NONE means the pin is always input-enabled */
 	if (iectrl == UNIPHIER_PIN_IECTRL_NONE)
-		/* This pin is always input-enabled. nothing to do. */
-		return 0;
+		return enable ? 0 : -EINVAL;
+
+	reg = UNIPHIER_PINCTRL_IECTRL + iectrl / 32 * 4;
+	mask = BIT(iectrl % 32);
 
-	return regmap_update_bits(priv->regmap, UNIPHIER_PINCTRL_IECTRL,
-				  BIT(iectrl), BIT(iectrl));
+	return regmap_update_bits(priv->regmap, reg, mask, enable ? mask : 0);
 }
 
 static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier.h b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
index 3fd5020..9941a4c 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier.h
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier.h
@@ -166,6 +166,7 @@ struct uniphier_pinctrl_socdata {
 	const struct uniphier_pinmux_function *functions;
 	int functions_count;
 	unsigned int caps;
+#define UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL	BIT(1)
 #define UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE	BIT(0)
 };
 
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:09 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:09 +0900
Subject: [PATCH 03/17] pinctrl: uniphier: fix register offsets for drive
 strength control
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-4-git-send-email-yamada.masahiro@socionext.com>

These pin tables were generated by parsing hardware documents with
a script, but the script had a bug.  Fix the register offsets.

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c  | 30 ++++++++++++------------
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c | 10 ++++----
 drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c | 12 +++++-----
 drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c | 10 ++++----
 drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c | 30 ++++++++++++------------
 5 files changed, 46 insertions(+), 46 deletions(-)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
index fdcdc91..ad193c7 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
@@ -92,31 +92,31 @@ static const struct pinctrl_pin_desc uniphier_ld4_pins[] = {
 			     0, UNIPHIER_PIN_DRV_8_12_16_20,
 			     146, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(23, "MMCCMD", UNIPHIER_PIN_IECTRL_NONE,
-			     4, UNIPHIER_PIN_DRV_8_12_16_20,
+			     1, UNIPHIER_PIN_DRV_8_12_16_20,
 			     147, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(24, "MMCDAT0", UNIPHIER_PIN_IECTRL_NONE,
-			     8, UNIPHIER_PIN_DRV_8_12_16_20,
+			     2, UNIPHIER_PIN_DRV_8_12_16_20,
 			     148, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(25, "MMCDAT1", UNIPHIER_PIN_IECTRL_NONE,
-			     12, UNIPHIER_PIN_DRV_8_12_16_20,
+			     3, UNIPHIER_PIN_DRV_8_12_16_20,
 			     149, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(26, "MMCDAT2", UNIPHIER_PIN_IECTRL_NONE,
-			     16, UNIPHIER_PIN_DRV_8_12_16_20,
+			     4, UNIPHIER_PIN_DRV_8_12_16_20,
 			     150, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(27, "MMCDAT3", UNIPHIER_PIN_IECTRL_NONE,
-			     20, UNIPHIER_PIN_DRV_8_12_16_20,
+			     5, UNIPHIER_PIN_DRV_8_12_16_20,
 			     151, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(28, "MMCDAT4", UNIPHIER_PIN_IECTRL_NONE,
-			     24, UNIPHIER_PIN_DRV_8_12_16_20,
+			     6, UNIPHIER_PIN_DRV_8_12_16_20,
 			     152, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(29, "MMCDAT5", UNIPHIER_PIN_IECTRL_NONE,
-			     28, UNIPHIER_PIN_DRV_8_12_16_20,
+			     7, UNIPHIER_PIN_DRV_8_12_16_20,
 			     153, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(30, "MMCDAT6", UNIPHIER_PIN_IECTRL_NONE,
-			     32, UNIPHIER_PIN_DRV_8_12_16_20,
+			     8, UNIPHIER_PIN_DRV_8_12_16_20,
 			     154, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(31, "MMCDAT7", UNIPHIER_PIN_IECTRL_NONE,
-			     36, UNIPHIER_PIN_DRV_8_12_16_20,
+			     9, UNIPHIER_PIN_DRV_8_12_16_20,
 			     155, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(32, "RMII_RXD0", 6,
 			     39, UNIPHIER_PIN_DRV_4_8,
@@ -155,22 +155,22 @@ static const struct pinctrl_pin_desc uniphier_ld4_pins[] = {
 			     50, UNIPHIER_PIN_DRV_4_8,
 			     50, UNIPHIER_PIN_PULL_DOWN),
 	UNIPHIER_PINCTRL_PIN(44, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
-			     40, UNIPHIER_PIN_DRV_8_12_16_20,
+			     10, UNIPHIER_PIN_DRV_8_12_16_20,
 			     156, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(45, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
-			     44, UNIPHIER_PIN_DRV_8_12_16_20,
+			     11, UNIPHIER_PIN_DRV_8_12_16_20,
 			     157, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(46, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
-			     48, UNIPHIER_PIN_DRV_8_12_16_20,
+			     12, UNIPHIER_PIN_DRV_8_12_16_20,
 			     158, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(47, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
-			     52, UNIPHIER_PIN_DRV_8_12_16_20,
+			     13, UNIPHIER_PIN_DRV_8_12_16_20,
 			     159, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(48, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
-			     56, UNIPHIER_PIN_DRV_8_12_16_20,
+			     14, UNIPHIER_PIN_DRV_8_12_16_20,
 			     160, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(49, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
-			     60, UNIPHIER_PIN_DRV_8_12_16_20,
+			     15, UNIPHIER_PIN_DRV_8_12_16_20,
 			     161, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(50, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
 			     51, UNIPHIER_PIN_DRV_4_8,
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
index 99a3e1a..0782a6d 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
@@ -167,19 +167,19 @@ static const struct pinctrl_pin_desc uniphier_ld6b_pins[] = {
 			     0, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(48, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
-			     4, UNIPHIER_PIN_DRV_8_12_16_20,
+			     1, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(49, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
-			     8, UNIPHIER_PIN_DRV_8_12_16_20,
+			     2, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(50, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
-			     12, UNIPHIER_PIN_DRV_8_12_16_20,
+			     3, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(51, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
-			     16, UNIPHIER_PIN_DRV_8_12_16_20,
+			     4, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(52, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
-			     20, UNIPHIER_PIN_DRV_8_12_16_20,
+			     5, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(53, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
 			     -1, UNIPHIER_PIN_DRV_FIXED_8,
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
index a96559c..8452dad 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
@@ -773,22 +773,22 @@ static const struct pinctrl_pin_desc uniphier_pro5_pins[] = {
 			     -1, UNIPHIER_PIN_DRV_FIXED_8,
 			     249, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(250, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
-			     40, UNIPHIER_PIN_DRV_8_12_16_20,
+			     10, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(251, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
-			     44, UNIPHIER_PIN_DRV_8_12_16_20,
+			     11, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(252, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
-			     48, UNIPHIER_PIN_DRV_8_12_16_20,
+			     12, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(253, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
-			     52, UNIPHIER_PIN_DRV_8_12_16_20,
+			     13, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(254, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
-			     56, UNIPHIER_PIN_DRV_8_12_16_20,
+			     14, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(255, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
-			     60, UNIPHIER_PIN_DRV_8_12_16_20,
+			     15, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 };
 
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
index 8074460e..89d3fdb 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
@@ -167,19 +167,19 @@ static const struct pinctrl_pin_desc uniphier_pxs2_pins[] = {
 			     0, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(48, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
-			     4, UNIPHIER_PIN_DRV_8_12_16_20,
+			     1, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(49, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
-			     8, UNIPHIER_PIN_DRV_8_12_16_20,
+			     2, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(50, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
-			     12, UNIPHIER_PIN_DRV_8_12_16_20,
+			     3, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(51, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
-			     16, UNIPHIER_PIN_DRV_8_12_16_20,
+			     4, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(52, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
-			     20, UNIPHIER_PIN_DRV_8_12_16_20,
+			     5, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_UP_FIXED),
 	UNIPHIER_PINCTRL_PIN(53, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
 			     -1, UNIPHIER_PIN_DRV_FIXED_8,
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
index 1e26b96..ab635f2 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
@@ -92,49 +92,49 @@ static const struct pinctrl_pin_desc uniphier_sld8_pins[] = {
 			     0, UNIPHIER_PIN_DRV_8_12_16_20,
 			     119, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(23, "NANDRYBY1_GB", UNIPHIER_PIN_IECTRL_NONE,
-			     4, UNIPHIER_PIN_DRV_8_12_16_20,
+			     1, UNIPHIER_PIN_DRV_8_12_16_20,
 			     120, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(24, "NFD0_GB", UNIPHIER_PIN_IECTRL_NONE,
-			     8, UNIPHIER_PIN_DRV_8_12_16_20,
+			     2, UNIPHIER_PIN_DRV_8_12_16_20,
 			     121, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(25, "NFD1_GB", UNIPHIER_PIN_IECTRL_NONE,
-			     12, UNIPHIER_PIN_DRV_8_12_16_20,
+			     3, UNIPHIER_PIN_DRV_8_12_16_20,
 			     122, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(26, "NFD2_GB", UNIPHIER_PIN_IECTRL_NONE,
-			     16, UNIPHIER_PIN_DRV_8_12_16_20,
+			     4, UNIPHIER_PIN_DRV_8_12_16_20,
 			     123, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(27, "NFD3_GB", UNIPHIER_PIN_IECTRL_NONE,
-			     20, UNIPHIER_PIN_DRV_8_12_16_20,
+			     5, UNIPHIER_PIN_DRV_8_12_16_20,
 			     124, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(28, "NFD4_GB", UNIPHIER_PIN_IECTRL_NONE,
-			     24, UNIPHIER_PIN_DRV_8_12_16_20,
+			     6, UNIPHIER_PIN_DRV_8_12_16_20,
 			     125, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(29, "NFD5_GB", UNIPHIER_PIN_IECTRL_NONE,
-			     28, UNIPHIER_PIN_DRV_8_12_16_20,
+			     7, UNIPHIER_PIN_DRV_8_12_16_20,
 			     126, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(30, "NFD6_GB", UNIPHIER_PIN_IECTRL_NONE,
-			     32, UNIPHIER_PIN_DRV_8_12_16_20,
+			     8, UNIPHIER_PIN_DRV_8_12_16_20,
 			     127, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(31, "NFD7_GB", UNIPHIER_PIN_IECTRL_NONE,
-			     36, UNIPHIER_PIN_DRV_8_12_16_20,
+			     9, UNIPHIER_PIN_DRV_8_12_16_20,
 			     128, UNIPHIER_PIN_PULL_UP),
 	UNIPHIER_PINCTRL_PIN(32, "SDCLK", 8,
-			     40, UNIPHIER_PIN_DRV_8_12_16_20,
+			     10, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_NONE),
 	UNIPHIER_PINCTRL_PIN(33, "SDCMD", 8,
-			     44, UNIPHIER_PIN_DRV_8_12_16_20,
+			     11, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_NONE),
 	UNIPHIER_PINCTRL_PIN(34, "SDDAT0", 8,
-			     48, UNIPHIER_PIN_DRV_8_12_16_20,
+			     12, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_NONE),
 	UNIPHIER_PINCTRL_PIN(35, "SDDAT1", 8,
-			     52, UNIPHIER_PIN_DRV_8_12_16_20,
+			     13, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_NONE),
 	UNIPHIER_PINCTRL_PIN(36, "SDDAT2", 8,
-			     56, UNIPHIER_PIN_DRV_8_12_16_20,
+			     14, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_NONE),
 	UNIPHIER_PINCTRL_PIN(37, "SDDAT3", 8,
-			     60, UNIPHIER_PIN_DRV_8_12_16_20,
+			     15, UNIPHIER_PIN_DRV_8_12_16_20,
 			     -1, UNIPHIER_PIN_PULL_NONE),
 	UNIPHIER_PINCTRL_PIN(38, "SDCD", 8,
 			     -1, UNIPHIER_PIN_DRV_FIXED_4,
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:23 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:23 +0900
Subject: [PATCH 17/17] pinctrl: uniphier: add UniPhier PH1-LD20 pinctrl driver
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-18-git-send-email-yamada.masahiro@socionext.com>

Add pin configuration and pinmux support for UniPhier PH1-LD20 SoC.

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

 drivers/pinctrl/uniphier/Kconfig                 |    4 +
 drivers/pinctrl/uniphier/Makefile                |    1 +
 drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c | 1037 ++++++++++++++++++++++
 3 files changed, 1042 insertions(+)
 create mode 100644 drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c

diff --git a/drivers/pinctrl/uniphier/Kconfig b/drivers/pinctrl/uniphier/Kconfig
index 395d42f..e077a9e 100644
--- a/drivers/pinctrl/uniphier/Kconfig
+++ b/drivers/pinctrl/uniphier/Kconfig
@@ -36,4 +36,8 @@ config PINCTRL_UNIPHIER_LD11
 	tristate "UniPhier PH1-LD11 SoC pinctrl driver"
 	default ARM64
 
+config PINCTRL_UNIPHIER_LD20
+	tristate "UniPhier PH1-LD20 SoC pinctrl driver"
+	default ARM64
+
 endif
diff --git a/drivers/pinctrl/uniphier/Makefile b/drivers/pinctrl/uniphier/Makefile
index 883c1076..9f4bc8a 100644
--- a/drivers/pinctrl/uniphier/Makefile
+++ b/drivers/pinctrl/uniphier/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_PINCTRL_UNIPHIER_PRO5)	+= pinctrl-uniphier-pro5.o
 obj-$(CONFIG_PINCTRL_UNIPHIER_PXS2)	+= pinctrl-uniphier-pxs2.o
 obj-$(CONFIG_PINCTRL_UNIPHIER_LD6B)	+= pinctrl-uniphier-ld6b.o
 obj-$(CONFIG_PINCTRL_UNIPHIER_LD11)	+= pinctrl-uniphier-ld11.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_LD20)	+= pinctrl-uniphier-ld20.o
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
new file mode 100644
index 0000000..2cb26b7
--- /dev/null
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
@@ -0,0 +1,1037 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro at socionext.com>
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-uniphier.h"
+
+static const struct pinctrl_pin_desc uniphier_ld20_pins[] = {
+	UNIPHIER_PINCTRL_PIN(0, "XECS1", 0,
+			     0, UNIPHIER_PIN_DRV_3BIT,
+			     0, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(1, "ERXW", 1,
+			     1, UNIPHIER_PIN_DRV_3BIT,
+			     1, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(2, "XERWE1", 2,
+			     2, UNIPHIER_PIN_DRV_3BIT,
+			     2, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(3, "XNFWP", 3,
+			     3, UNIPHIER_PIN_DRV_3BIT,
+			     3, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(4, "XNFCE0", 4,
+			     4, UNIPHIER_PIN_DRV_3BIT,
+			     4, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(5, "NFRYBY0", 5,
+			     5, UNIPHIER_PIN_DRV_3BIT,
+			     5, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(6, "XNFRE", 6,
+			     6, UNIPHIER_PIN_DRV_3BIT,
+			     6, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(7, "XNFWE", 7,
+			     7, UNIPHIER_PIN_DRV_3BIT,
+			     7, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(8, "NFALE", 8,
+			     8, UNIPHIER_PIN_DRV_3BIT,
+			     8, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(9, "NFCLE", 9,
+			     9, UNIPHIER_PIN_DRV_3BIT,
+			     9, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(10, "NFD0", 10,
+			     10, UNIPHIER_PIN_DRV_3BIT,
+			     10, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(11, "NFD1", 11,
+			     11, UNIPHIER_PIN_DRV_3BIT,
+			     11, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(12, "NFD2", 12,
+			     12, UNIPHIER_PIN_DRV_3BIT,
+			     12, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(13, "NFD3", 13,
+			     13, UNIPHIER_PIN_DRV_3BIT,
+			     13, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(14, "NFD4", 14,
+			     14, UNIPHIER_PIN_DRV_3BIT,
+			     14, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(15, "NFD5", 15,
+			     15, UNIPHIER_PIN_DRV_3BIT,
+			     15, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(16, "NFD6", 16,
+			     16, UNIPHIER_PIN_DRV_3BIT,
+			     16, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(17, "NFD7", 17,
+			     17, UNIPHIER_PIN_DRV_3BIT,
+			     17, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(18, "XERST", 18,
+			     0, UNIPHIER_PIN_DRV_2BIT,
+			     18, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(19, "MMCCLK", 19,
+			     1, UNIPHIER_PIN_DRV_2BIT,
+			     19, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(20, "MMCCMD", 20,
+			     2, UNIPHIER_PIN_DRV_2BIT,
+			     20, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(21, "MMCDS", 21,
+			     3, UNIPHIER_PIN_DRV_2BIT,
+			     21, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(22, "MMCDAT0", 22,
+			     4, UNIPHIER_PIN_DRV_2BIT,
+			     22, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(23, "MMCDAT1", 23,
+			     5, UNIPHIER_PIN_DRV_2BIT,
+			     23, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(24, "MMCDAT2", 24,
+			     6, UNIPHIER_PIN_DRV_2BIT,
+			     24, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(25, "MMCDAT3", 25,
+			     7, UNIPHIER_PIN_DRV_2BIT,
+			     25, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(26, "MMCDAT4", 26,
+			     8, UNIPHIER_PIN_DRV_2BIT,
+			     26, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(27, "MMCDAT5", 27,
+			     9, UNIPHIER_PIN_DRV_2BIT,
+			     27, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(28, "MMCDAT6", 28,
+			     10, UNIPHIER_PIN_DRV_2BIT,
+			     28, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(29, "MMCDAT7", 29,
+			     11, UNIPHIER_PIN_DRV_2BIT,
+			     29, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(30, "MDC", 30,
+			     18, UNIPHIER_PIN_DRV_3BIT,
+			     30, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(31, "MDIO", 31,
+			     19, UNIPHIER_PIN_DRV_3BIT,
+			     31, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(32, "MDIO_INTL", 32,
+			     20, UNIPHIER_PIN_DRV_3BIT,
+			     32, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(33, "PHYRSTL", 33,
+			     21, UNIPHIER_PIN_DRV_3BIT,
+			     33, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(34, "RGMII_RXCLK", 34,
+			     22, UNIPHIER_PIN_DRV_3BIT,
+			     34, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(35, "RGMII_RXD0", 35,
+			     23, UNIPHIER_PIN_DRV_3BIT,
+			     35, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(36, "RGMII_RXD1", 36,
+			     24, UNIPHIER_PIN_DRV_3BIT,
+			     36, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(37, "RGMII_RXD2", 37,
+			     25, UNIPHIER_PIN_DRV_3BIT,
+			     37, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(38, "RGMII_RXD3", 38,
+			     26, UNIPHIER_PIN_DRV_3BIT,
+			     38, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(39, "RGMII_RXCTL", 39,
+			     27, UNIPHIER_PIN_DRV_3BIT,
+			     39, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(40, "RGMII_TXCLK", 40,
+			     28, UNIPHIER_PIN_DRV_3BIT,
+			     40, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(41, "RGMII_TXD0", 41,
+			     29, UNIPHIER_PIN_DRV_3BIT,
+			     41, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(42, "RGMII_TXD1", 42,
+			     30, UNIPHIER_PIN_DRV_3BIT,
+			     42, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(43, "RGMII_TXD2", 43,
+			     31, UNIPHIER_PIN_DRV_3BIT,
+			     43, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(44, "RGMII_TXD3", 44,
+			     32, UNIPHIER_PIN_DRV_3BIT,
+			     44, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(45, "RGMII_TXCTL", 45,
+			     33, UNIPHIER_PIN_DRV_3BIT,
+			     45, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(46, "USB0VBUS", 46,
+			     34, UNIPHIER_PIN_DRV_3BIT,
+			     46, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(47, "USB0OD", 47,
+			     35, UNIPHIER_PIN_DRV_3BIT,
+			     47, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(48, "USB1VBUS", 48,
+			     36, UNIPHIER_PIN_DRV_3BIT,
+			     48, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(49, "USB1OD", 49,
+			     37, UNIPHIER_PIN_DRV_3BIT,
+			     49, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(50, "USB2VBUS", 50,
+			     38, UNIPHIER_PIN_DRV_3BIT,
+			     50, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(51, "USB2OD", 51,
+			     39, UNIPHIER_PIN_DRV_3BIT,
+			     51, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(52, "USB3VBUS", 52,
+			     40, UNIPHIER_PIN_DRV_3BIT,
+			     52, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(53, "USB3OD", 53,
+			     41, UNIPHIER_PIN_DRV_3BIT,
+			     53, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(54, "TXD0", 54,
+			     42, UNIPHIER_PIN_DRV_3BIT,
+			     54, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(55, "RXD0", 55,
+			     43, UNIPHIER_PIN_DRV_3BIT,
+			     55, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(56, "SPISYNC0", 56,
+			     44, UNIPHIER_PIN_DRV_3BIT,
+			     56, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(57, "SPISCLK0", 57,
+			     45, UNIPHIER_PIN_DRV_3BIT,
+			     57, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(58, "SPITXD0", 58,
+			     46, UNIPHIER_PIN_DRV_3BIT,
+			     58, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(59, "SPIRXD0", 59,
+			     47, UNIPHIER_PIN_DRV_3BIT,
+			     59, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(60, "AGCI", 60,
+			     48, UNIPHIER_PIN_DRV_3BIT,
+			     60, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(61, "DMDSDA0", 61,
+			     -1, UNIPHIER_PIN_DRV_FIXED4,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(62, "DMDSCL0", 62,
+			     -1, UNIPHIER_PIN_DRV_FIXED4,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(63, "SDA0", 63,
+			     -1, UNIPHIER_PIN_DRV_FIXED4,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(64, "SCL0", 64,
+			     -1, UNIPHIER_PIN_DRV_FIXED4,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(65, "SDA1", 65,
+			     -1, UNIPHIER_PIN_DRV_FIXED4,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(66, "SCL1", 66,
+			     -1, UNIPHIER_PIN_DRV_FIXED4,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(67, "HIN", 67,
+			     -1, UNIPHIER_PIN_DRV_FIXED4,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(68, "VIN", 68,
+			     -1, UNIPHIER_PIN_DRV_FIXED4,
+			     -1, UNIPHIER_PIN_PULL_NONE),
+	UNIPHIER_PINCTRL_PIN(69, "PCA00", 69,
+			     49, UNIPHIER_PIN_DRV_3BIT,
+			     69, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(70, "PCA01", 70,
+			     50, UNIPHIER_PIN_DRV_3BIT,
+			     70, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(71, "PCA02", 71,
+			     51, UNIPHIER_PIN_DRV_3BIT,
+			     71, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(72, "PCA03", 72,
+			     52, UNIPHIER_PIN_DRV_3BIT,
+			     72, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(73, "PCA04", 73,
+			     53, UNIPHIER_PIN_DRV_3BIT,
+			     73, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(74, "PCA05", 74,
+			     54, UNIPHIER_PIN_DRV_3BIT,
+			     74, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(75, "PCA06", 75,
+			     55, UNIPHIER_PIN_DRV_3BIT,
+			     75, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(76, "PCA07", 76,
+			     56, UNIPHIER_PIN_DRV_3BIT,
+			     76, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(77, "PCA08", 77,
+			     57, UNIPHIER_PIN_DRV_3BIT,
+			     77, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(78, "PCA09", 78,
+			     58, UNIPHIER_PIN_DRV_3BIT,
+			     78, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(79, "PCA10", 79,
+			     59, UNIPHIER_PIN_DRV_3BIT,
+			     79, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(80, "PCA11", 80,
+			     60, UNIPHIER_PIN_DRV_3BIT,
+			     80, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(81, "PCA12", 81,
+			     61, UNIPHIER_PIN_DRV_3BIT,
+			     81, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(82, "PCA13", 82,
+			     62, UNIPHIER_PIN_DRV_3BIT,
+			     82, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(83, "PCA14", 83,
+			     63, UNIPHIER_PIN_DRV_3BIT,
+			     83, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(84, "PC0READY", 84,
+			     0, UNIPHIER_PIN_DRV_1BIT,
+			     84, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(85, "PC0CD1", 85,
+			     1, UNIPHIER_PIN_DRV_1BIT,
+			     85, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(86, "PC0CD2", 86,
+			     2, UNIPHIER_PIN_DRV_1BIT,
+			     86, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(87, "PC0WAIT", 87,
+			     3, UNIPHIER_PIN_DRV_1BIT,
+			     87, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(88, "PC0RESET", 88,
+			     4, UNIPHIER_PIN_DRV_1BIT,
+			     88, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(89, "PC0CE1", 89,
+			     5, UNIPHIER_PIN_DRV_1BIT,
+			     89, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(90, "PC0WE", 90,
+			     6, UNIPHIER_PIN_DRV_1BIT,
+			     90, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(91, "PC0OE", 91,
+			     7, UNIPHIER_PIN_DRV_1BIT,
+			     91, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(92, "PC0IOWR", 92,
+			     8, UNIPHIER_PIN_DRV_1BIT,
+			     92, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(93, "PC0IORD", 93,
+			     9, UNIPHIER_PIN_DRV_1BIT,
+			     93, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(94, "PCD00", 94,
+			     10, UNIPHIER_PIN_DRV_1BIT,
+			     94, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(95, "PCD01", 95,
+			     11, UNIPHIER_PIN_DRV_1BIT,
+			     95, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(96, "PCD02", 96,
+			     12, UNIPHIER_PIN_DRV_1BIT,
+			     96, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(97, "PCD03", 97,
+			     13, UNIPHIER_PIN_DRV_1BIT,
+			     97, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(98, "PCD04", 98,
+			     14, UNIPHIER_PIN_DRV_1BIT,
+			     98, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(99, "PCD05", 99,
+			     15, UNIPHIER_PIN_DRV_1BIT,
+			     99, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(100, "PCD06", 100,
+			     16, UNIPHIER_PIN_DRV_1BIT,
+			     100, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(101, "PCD07", 101,
+			     17, UNIPHIER_PIN_DRV_1BIT,
+			     101, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(102, "HS0BCLKIN", 102,
+			     18, UNIPHIER_PIN_DRV_1BIT,
+			     102, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(103, "HS0SYNCIN", 103,
+			     19, UNIPHIER_PIN_DRV_1BIT,
+			     103, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(104, "HS0VALIN", 104,
+			     20, UNIPHIER_PIN_DRV_1BIT,
+			     104, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(105, "HS0DIN0", 105,
+			     21, UNIPHIER_PIN_DRV_1BIT,
+			     105, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(106, "HS0DIN1", 106,
+			     22, UNIPHIER_PIN_DRV_1BIT,
+			     106, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(107, "HS0DIN2", 107,
+			     23, UNIPHIER_PIN_DRV_1BIT,
+			     107, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(108, "HS0DIN3", 108,
+			     24, UNIPHIER_PIN_DRV_1BIT,
+			     108, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(109, "HS0DIN4", 109,
+			     25, UNIPHIER_PIN_DRV_1BIT,
+			     109, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(110, "HS0DIN5", 110,
+			     26, UNIPHIER_PIN_DRV_1BIT,
+			     110, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(111, "HS0DIN6", 111,
+			     27, UNIPHIER_PIN_DRV_1BIT,
+			     111, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(112, "HS0DIN7", 112,
+			     28, UNIPHIER_PIN_DRV_1BIT,
+			     112, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(113, "HS0BCLKOUT", 113,
+			     64, UNIPHIER_PIN_DRV_3BIT,
+			     113, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(114, "HS0SYNCOUT", 114,
+			     65, UNIPHIER_PIN_DRV_3BIT,
+			     114, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(115, "HS0VALOUT", 115,
+			     66, UNIPHIER_PIN_DRV_3BIT,
+			     115, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(116, "HS0DOUT0", 116,
+			     67, UNIPHIER_PIN_DRV_3BIT,
+			     116, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(117, "HS0DOUT1", 117,
+			     68, UNIPHIER_PIN_DRV_3BIT,
+			     117, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(118, "HS0DOUT2", 118,
+			     69, UNIPHIER_PIN_DRV_3BIT,
+			     118, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(119, "HS0DOUT3", 119,
+			     70, UNIPHIER_PIN_DRV_3BIT,
+			     119, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(120, "HS0DOUT4", 120,
+			     71, UNIPHIER_PIN_DRV_3BIT,
+			     120, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(121, "HS0DOUT5", 121,
+			     72, UNIPHIER_PIN_DRV_3BIT,
+			     121, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(122, "HS0DOUT6", 122,
+			     73, UNIPHIER_PIN_DRV_3BIT,
+			     122, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(123, "HS0DOUT7", 123,
+			     74, UNIPHIER_PIN_DRV_3BIT,
+			     123, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(124, "HS1BCLKIN", 124,
+			     75, UNIPHIER_PIN_DRV_3BIT,
+			     124, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(125, "HS1SYNCIN", 125,
+			     76, UNIPHIER_PIN_DRV_3BIT,
+			     125, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(126, "HS1VALIN", 126,
+			     77, UNIPHIER_PIN_DRV_3BIT,
+			     126, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(127, "HS1DIN0", 127,
+			     78, UNIPHIER_PIN_DRV_3BIT,
+			     127, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(128, "HS1DIN1", 128,
+			     79, UNIPHIER_PIN_DRV_3BIT,
+			     128, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(129, "HS1DIN2", 129,
+			     80, UNIPHIER_PIN_DRV_3BIT,
+			     129, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(130, "HS1DIN3", 130,
+			     81, UNIPHIER_PIN_DRV_3BIT,
+			     130, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(131, "HS1DIN4", 131,
+			     82, UNIPHIER_PIN_DRV_3BIT,
+			     131, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(132, "HS1DIN5", 132,
+			     83, UNIPHIER_PIN_DRV_3BIT,
+			     132, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(133, "HS1DIN6", 133,
+			     84, UNIPHIER_PIN_DRV_3BIT,
+			     133, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(134, "HS1DIN7", 134,
+			     85, UNIPHIER_PIN_DRV_3BIT,
+			     134, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(135, "AO1IEC", 135,
+			     86, UNIPHIER_PIN_DRV_3BIT,
+			     135, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(136, "AO1ARC", 136,
+			     87, UNIPHIER_PIN_DRV_3BIT,
+			     136, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(137, "AO1DACCK", 137,
+			     88, UNIPHIER_PIN_DRV_3BIT,
+			     137, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(138, "AO1BCK", 138,
+			     89, UNIPHIER_PIN_DRV_3BIT,
+			     138, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(139, "AO1LRCK", 139,
+			     90, UNIPHIER_PIN_DRV_3BIT,
+			     139, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(140, "AO1D0", 140,
+			     91, UNIPHIER_PIN_DRV_3BIT,
+			     140, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(141, "AO1D1", 141,
+			     92, UNIPHIER_PIN_DRV_3BIT,
+			     141, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(142, "AO1D2", 142,
+			     93, UNIPHIER_PIN_DRV_3BIT,
+			     142, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(143, "HTPDN0", 143,
+			     94, UNIPHIER_PIN_DRV_3BIT,
+			     143, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(144, "LOCKN0", 144,
+			     95, UNIPHIER_PIN_DRV_3BIT,
+			     144, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(145, "HTPDN1", 145,
+			     96, UNIPHIER_PIN_DRV_3BIT,
+			     145, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(146, "LOCKN1", 146,
+			     97, UNIPHIER_PIN_DRV_3BIT,
+			     146, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(147, "PWMA", 147,
+			     98, UNIPHIER_PIN_DRV_3BIT,
+			     147, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(148, "LR_GOUT", 148,
+			     99, UNIPHIER_PIN_DRV_3BIT,
+			     148, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(149, "XIRQ0", 149,
+			     100, UNIPHIER_PIN_DRV_3BIT,
+			     149, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(150, "XIRQ1", 150,
+			     101, UNIPHIER_PIN_DRV_3BIT,
+			     150, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(151, "XIRQ2", 151,
+			     102, UNIPHIER_PIN_DRV_3BIT,
+			     151, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(152, "XIRQ3", 152,
+			     103, UNIPHIER_PIN_DRV_3BIT,
+			     152, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(153, "XIRQ4", 153,
+			     104, UNIPHIER_PIN_DRV_3BIT,
+			     153, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(154, "XIRQ5", 154,
+			     105, UNIPHIER_PIN_DRV_3BIT,
+			     154, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(155, "XIRQ6", 155,
+			     106, UNIPHIER_PIN_DRV_3BIT,
+			     155, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(156, "XIRQ7", 156,
+			     107, UNIPHIER_PIN_DRV_3BIT,
+			     156, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(157, "XIRQ8", 157,
+			     108, UNIPHIER_PIN_DRV_3BIT,
+			     157, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(158, "XIRQ9", 158,
+			     109, UNIPHIER_PIN_DRV_3BIT,
+			     158, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(159, "XIRQ10", 159,
+			     110, UNIPHIER_PIN_DRV_3BIT,
+			     159, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(160, "XIRQ11", 160,
+			     111, UNIPHIER_PIN_DRV_3BIT,
+			     160, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(161, "XIRQ13", 161,
+			     112, UNIPHIER_PIN_DRV_3BIT,
+			     161, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(162, "XIRQ14", 162,
+			     113, UNIPHIER_PIN_DRV_3BIT,
+			     162, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(163, "XIRQ16", 163,
+			     114, UNIPHIER_PIN_DRV_3BIT,
+			     163, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(164, "XIRQ17", 164,
+			     115, UNIPHIER_PIN_DRV_3BIT,
+			     164, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(165, "XIRQ18", 165,
+			     116, UNIPHIER_PIN_DRV_3BIT,
+			     165, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(166, "XIRQ19", 166,
+			     117, UNIPHIER_PIN_DRV_3BIT,
+			     166, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(167, "XIRQ20", 167,
+			     118, UNIPHIER_PIN_DRV_3BIT,
+			     167, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(168, "PORT00", 168,
+			     119, UNIPHIER_PIN_DRV_3BIT,
+			     168, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(169, "PORT01", 169,
+			     120, UNIPHIER_PIN_DRV_3BIT,
+			     169, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(170, "PORT02", 170,
+			     121, UNIPHIER_PIN_DRV_3BIT,
+			     170, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(171, "PORT03", 171,
+			     122, UNIPHIER_PIN_DRV_3BIT,
+			     171, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(172, "PORT04", 172,
+			     123, UNIPHIER_PIN_DRV_3BIT,
+			     172, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(173, "CK27FO", 173,
+			     124, UNIPHIER_PIN_DRV_3BIT,
+			     173, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(174, "PHSYNCO", 174,
+			     125, UNIPHIER_PIN_DRV_3BIT,
+			     174, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(175, "PVSYNCO", 175,
+			     126, UNIPHIER_PIN_DRV_3BIT,
+			     175, UNIPHIER_PIN_PULL_DOWN),
+};
+
+static const unsigned emmc_pins[] = {18, 19, 20, 21, 22, 23, 24, 25};
+static const int emmc_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned emmc_dat8_pins[] = {26, 27, 28, 29};
+static const int emmc_dat8_muxvals[] = {0, 0, 0, 0};
+static const unsigned i2c0_pins[] = {63, 64};
+static const int i2c0_muxvals[] = {0, 0};
+static const unsigned i2c1_pins[] = {65, 66};
+static const int i2c1_muxvals[] = {0, 0};
+static const unsigned i2c3_pins[] = {67, 68};
+static const int i2c3_muxvals[] = {1, 1};
+static const unsigned i2c4_pins[] = {61, 62};
+static const int i2c4_muxvals[] = {1, 1};
+static const unsigned nand_pins[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+				     15, 16, 17};
+static const int nand_muxvals[] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
+static const unsigned sd_pins[] = {10, 11, 12, 13, 14, 15, 16, 17};
+static const int sd_muxvals[] = {3, 3, 3, 3, 3, 3, 3, 3};  /* No SDVOLC */
+static const unsigned system_bus_pins[] = {1, 2, 6, 7, 8, 9, 10, 11, 12, 13,
+					   14, 15, 16, 17};
+static const int system_bus_muxvals[] = {0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+					 2};
+static const unsigned system_bus_cs1_pins[] = {0};
+static const int system_bus_cs1_muxvals[] = {0};
+static const unsigned uart0_pins[] = {54, 55};
+static const int uart0_muxvals[] = {0, 0};
+static const unsigned uart1_pins[] = {58, 59};
+static const int uart1_muxvals[] = {1, 1};
+static const unsigned uart2_pins[] = {90, 91};
+static const int uart2_muxvals[] = {1, 1};
+static const unsigned uart3_pins[] = {94, 95};
+static const int uart3_muxvals[] = {1, 1};
+static const unsigned usb0_pins[] = {46, 47};
+static const int usb0_muxvals[] = {0, 0};
+static const unsigned usb1_pins[] = {48, 49};
+static const int usb1_muxvals[] = {0, 0};
+static const unsigned usb2_pins[] = {50, 51};
+static const int usb2_muxvals[] = {0, 0};
+static const unsigned usb3_pins[] = {52, 53};
+static const int usb3_muxvals[] = {0, 0};
+static const unsigned port_range_pins[] = {
+	168, 169, 170, 171, 172, 173, 174, 175,		/* PORT0x */
+	0, 1, 2, 3, 4, 5, 6, 7,				/* PORT1x */
+	8, 9, 10, 11, 12, 13, 14, 15,			/* PORT2x */
+	16, 17, 18, 30, 31, 32, 33, 34,			/* PORT3x */
+	35, 36, 37, 38, 39, 40, 41, 42,			/* PORT4x */
+	43, 44, 45, 46, 47, 48, 49, 50,			/* PORT5x */
+	51, 52, 53, 54, 55, 56, 57, 58,			/* PORT6x */
+	59, 60, 69, 70, 71, 72, 73, 74,			/* PORT7x */
+	75, 76, 77, 78, 79, 80, 81, 82,			/* PORT8x */
+	83, 84, 85, 86, 87, 88, 89, 90,			/* PORT9x */
+	91, 92, 93, 94, 95, 96, 97, 98,			/* PORT10x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT11x */
+	99, 100, 101, 102, 103, 104, 105, 106,		/* PORT12x */
+	107, 108, 109, 110, 111, 112, 113, 114,		/* PORT13x */
+	115, 116, 117, 118, 119, 120, 121, 122,		/* PORT14x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT15x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT16x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT17x */
+	61, 62, 63, 64, 65, 66, 67, 68,			/* PORT18x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT19x */
+	123, 124, 125, 126, 127, 128, 129, 130,		/* PORT20x */
+	131, 132, 133, 134, 135, 136, 137, 138,		/* PORT21x */
+	139, 140, 141, 142, 143, 144, 145, 146,		/* PORT22x */
+	147, 148, 149, 150, 151, 152, 153, 154,		/* PORT23x */
+	155, 156, 157, 158, 159, 160, 161, 162,		/* PORT24x */
+	163, 164, 165, 166, 167,			/* PORT25x */
+};
+static const int port_range_muxvals[] = {
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT0x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT1x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT2x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT3x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT4x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT5x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT6x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT7x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT8x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT9x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT10x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT11x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT12x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT13x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT14x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT15x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT16x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT17x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT18x */
+	-1, -1, -1, -1, -1, -1, -1, -1,			/* PORT19x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT20x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT21x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT22x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT23x */
+	15, 15, 15, 15, 15, 15, 15, 15,			/* PORT24x */
+	15, 15, 15, 15, 15,				/* PORT25x */
+};
+static const unsigned xirq_pins[] = {
+	149, 150, 151, 152, 153, 154, 155, 156,		/* XIRQ0-7 */
+	157, 158, 159, 160, 85, 161, 162, 84,		/* XIRQ8-15 */
+	163, 164, 165, 166, 167, 146, 52, 53,		/* XIRQ16-23 */
+};
+static const int xirq_muxvals[] = {
+	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ0-7 */
+	14, 14, 14, 14, 13, 14, 14, 13,			/* XIRQ8-15 */
+	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ16-23 */
+};
+static const unsigned xirq_alternatives_pins[] = {
+	94, 95, 96, 97, 98, 99, 100, 101,		/* XIRQ0-7 */
+	102, 103, 104, 105, 106, 107,			/* XIRQ8-11,13,14 */
+	108, 109, 110, 111, 112, 147, 141, 142,		/* XIRQ16-23 */
+};
+static const int xirq_alternatives_muxvals[] = {
+	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ0-7 */
+	14, 14, 14, 14, 14, 14,				/* XIRQ8-11,13,14 */
+	14, 14, 14, 14, 14, 14, 14, 14,			/* XIRQ16-23 */
+};
+
+static const struct uniphier_pinctrl_group uniphier_ld20_groups[] = {
+	UNIPHIER_PINCTRL_GROUP(emmc),
+	UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+	UNIPHIER_PINCTRL_GROUP(i2c0),
+	UNIPHIER_PINCTRL_GROUP(i2c1),
+	UNIPHIER_PINCTRL_GROUP(i2c3),
+	UNIPHIER_PINCTRL_GROUP(i2c4),
+	UNIPHIER_PINCTRL_GROUP(nand),
+	UNIPHIER_PINCTRL_GROUP(sd),
+	UNIPHIER_PINCTRL_GROUP(system_bus),
+	UNIPHIER_PINCTRL_GROUP(system_bus_cs1),
+	UNIPHIER_PINCTRL_GROUP(uart0),
+	UNIPHIER_PINCTRL_GROUP(uart1),
+	UNIPHIER_PINCTRL_GROUP(uart2),
+	UNIPHIER_PINCTRL_GROUP(uart3),
+	UNIPHIER_PINCTRL_GROUP(usb0),
+	UNIPHIER_PINCTRL_GROUP(usb1),
+	UNIPHIER_PINCTRL_GROUP(usb2),
+	UNIPHIER_PINCTRL_GROUP(usb3),
+	UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range),
+	UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq),
+	UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_alternatives),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range, 0),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range, 1),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range, 2),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range, 3),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range, 4),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range, 5),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range, 6),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range, 7),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range, 8),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range, 9),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range, 10),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range, 11),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range, 12),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range, 13),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range, 14),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range, 15),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range, 16),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range, 17),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range, 18),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range, 19),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range, 20),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range, 21),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range, 22),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range, 23),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range, 24),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range, 25),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range, 26),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range, 27),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range, 28),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range, 29),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range, 30),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range, 31),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range, 32),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range, 33),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range, 34),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range, 35),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range, 36),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range, 37),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range, 38),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range, 39),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range, 40),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range, 41),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range, 42),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range, 43),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range, 44),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range, 45),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range, 46),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range, 47),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range, 48),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range, 49),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range, 50),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range, 51),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range, 52),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range, 53),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range, 54),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range, 55),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range, 56),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range, 57),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range, 58),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range, 59),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range, 60),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range, 61),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range, 62),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range, 63),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range, 64),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range, 65),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range, 66),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range, 67),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range, 68),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range, 69),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range, 70),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range, 71),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range, 72),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range, 73),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range, 74),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range, 75),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range, 76),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range, 77),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range, 78),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range, 79),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range, 80),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range, 81),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range, 82),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range, 83),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range, 84),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range, 85),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range, 86),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range, 87),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range, 96),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range, 97),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range, 98),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range, 99),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range, 100),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range, 101),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range, 102),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range, 103),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range, 104),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range, 105),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range, 106),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range, 107),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range, 108),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range, 109),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range, 110),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range, 111),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range, 112),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range, 113),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range, 114),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range, 115),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range, 116),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range, 117),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range, 118),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range, 119),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port180, port_range, 144),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port181, port_range, 145),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port182, port_range, 146),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port183, port_range, 147),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port184, port_range, 148),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port185, port_range, 149),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port186, port_range, 150),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port187, port_range, 151),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port200, port_range, 160),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port201, port_range, 161),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port202, port_range, 162),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port203, port_range, 163),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port204, port_range, 164),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port205, port_range, 165),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port206, port_range, 166),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port207, port_range, 167),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port210, port_range, 168),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port211, port_range, 169),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port212, port_range, 170),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port213, port_range, 171),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port214, port_range, 172),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port215, port_range, 173),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port216, port_range, 174),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port217, port_range, 175),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port220, port_range, 176),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port221, port_range, 177),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port222, port_range, 178),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port223, port_range, 179),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port224, port_range, 180),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port225, port_range, 181),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port226, port_range, 182),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port227, port_range, 183),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port230, port_range, 184),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port231, port_range, 185),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port232, port_range, 186),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port233, port_range, 187),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port234, port_range, 188),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port235, port_range, 189),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port236, port_range, 190),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port237, port_range, 191),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port240, port_range, 192),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port241, port_range, 193),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port242, port_range, 194),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port243, port_range, 195),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port244, port_range, 196),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port245, port_range, 197),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port246, port_range, 198),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port247, port_range, 199),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port250, port_range, 200),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port251, port_range, 201),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port252, port_range, 202),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port253, port_range, 203),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(port254, port_range, 204),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq, 0),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq, 1),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq, 2),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq, 3),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq, 4),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq, 5),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq, 6),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq, 7),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq, 8),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq, 9),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq, 10),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq, 11),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq, 12),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13, xirq, 13),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq, 14),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq, 15),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16, xirq, 16),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17, xirq, 17),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18, xirq, 18),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19, xirq, 19),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20, xirq, 20),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq21, xirq, 21),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq22, xirq, 22),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq23, xirq, 23),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0b, xirq_alternatives, 0),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1b, xirq_alternatives, 1),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2b, xirq_alternatives, 2),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3b, xirq_alternatives, 3),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4b, xirq_alternatives, 4),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5b, xirq_alternatives, 5),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6b, xirq_alternatives, 6),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7b, xirq_alternatives, 7),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8b, xirq_alternatives, 8),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9b, xirq_alternatives, 9),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10b, xirq_alternatives, 10),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11b, xirq_alternatives, 11),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13b, xirq_alternatives, 12),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14b, xirq_alternatives, 13),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16b, xirq_alternatives, 14),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17b, xirq_alternatives, 15),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18b, xirq_alternatives, 16),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19b, xirq_alternatives, 17),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20b, xirq_alternatives, 18),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq21b, xirq_alternatives, 19),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq22b, xirq_alternatives, 20),
+	UNIPHIER_PINCTRL_GROUP_SINGLE(xirq23b, xirq_alternatives, 21),
+};
+
+static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
+static const char * const i2c0_groups[] = {"i2c0"};
+static const char * const i2c1_groups[] = {"i2c1"};
+static const char * const i2c3_groups[] = {"i2c3"};
+static const char * const i2c4_groups[] = {"i2c4"};
+static const char * const nand_groups[] = {"nand"};
+static const char * const sd_groups[] = {"sd"};
+static const char * const system_bus_groups[] = {"system_bus",
+						 "system_bus_cs1"};
+static const char * const uart0_groups[] = {"uart0"};
+static const char * const uart1_groups[] = {"uart1"};
+static const char * const uart2_groups[] = {"uart2"};
+static const char * const uart3_groups[] = {"uart3"};
+static const char * const usb0_groups[] = {"usb0"};
+static const char * const usb1_groups[] = {"usb1"};
+static const char * const usb2_groups[] = {"usb2"};
+static const char * const usb3_groups[] = {"usb3"};
+static const char * const port_groups[] = {
+	"port00", "port01", "port02", "port03",
+	"port04", "port05", "port06", "port07",
+	"port10", "port11", "port12", "port13",
+	"port14", "port15", "port16", "port17",
+	"port20", "port21", "port22", "port23",
+	"port24", "port25", "port26", "port27",
+	"port30", "port31", "port32", "port33",
+	"port34", "port35", "port36", "port37",
+	"port40", "port41", "port42", "port43",
+	"port44", "port45", "port46", "port47",
+	"port50", "port51", "port52", "port53",
+	"port54", "port55", "port56", "port57",
+	"port60", "port61", "port62", "port63",
+	"port64", "port65", "port66", "port67",
+	"port70", "port71", "port72", "port73",
+	"port74", "port75", "port76", "port77",
+	"port80", "port81", "port82", "port83",
+	"port84", "port85", "port86", "port87",
+	"port90", "port91", "port92", "port93",
+	"port94", "port95", "port96", "port97",
+	"port100", "port101", "port102", "port103",
+	"port104", "port105", "port106", "port107",
+	/* port110-117 missing */
+	"port120", "port121", "port122", "port123",
+	"port124", "port125", "port126", "port127",
+	"port130", "port131", "port132", "port133",
+	"port134", "port135", "port136", "port137",
+	"port140", "port141", "port142", "port143",
+	"port144", "port145", "port146", "port147",
+	/* port150-177 missing */
+	"port180", "port181", "port182", "port183",
+	"port184", "port185", "port186", "port187",
+	/* port190-197 missing */
+	"port200", "port201", "port202", "port203",
+	"port204", "port205", "port206", "port207",
+	"port210", "port211", "port212", "port213",
+	"port214", "port215", "port216", "port217",
+	"port220", "port221", "port222", "port223",
+	"port224", "port225", "port226", "port227",
+	"port230", "port231", "port232", "port233",
+	"port234", "port235", "port236", "port237",
+	"port240", "port241", "port242", "port243",
+	"port244", "port245", "port246", "port247",
+	"port250", "port251", "port252", "port253",
+	"port254",
+};
+static const char * const xirq_groups[] = {
+	"xirq0",  "xirq1",  "xirq2",  "xirq3",
+	"xirq4",  "xirq5",  "xirq6",  "xirq7",
+	"xirq8",  "xirq9",  "xirq10", "xirq11",
+	"xirq12", "xirq13", "xirq14", "xirq15",
+	"xirq16", "xirq17", "xirq18", "xirq19",
+	"xirq20", "xirq21", "xirq22", "xirq23",
+	"xirq0b",  "xirq1b",  "xirq2b",  "xirq3b",
+	"xirq4b",  "xirq5b",  "xirq6b",  "xirq7b",
+	"xirq8b",  "xirq9b",  "xirq10b", "xirq11b",
+	/* none */ "xirq13b", "xirq14b", /* none */
+	"xirq16b", "xirq17b", "xirq18b", "xirq19b",
+	"xirq20b", "xirq21b", "xirq22b", "xirq23b",
+};
+
+static const struct uniphier_pinmux_function uniphier_ld20_functions[] = {
+	UNIPHIER_PINMUX_FUNCTION(emmc),
+	UNIPHIER_PINMUX_FUNCTION(i2c0),
+	UNIPHIER_PINMUX_FUNCTION(i2c1),
+	UNIPHIER_PINMUX_FUNCTION(i2c3),
+	UNIPHIER_PINMUX_FUNCTION(i2c4),
+	UNIPHIER_PINMUX_FUNCTION(nand),
+	UNIPHIER_PINMUX_FUNCTION(sd),
+	UNIPHIER_PINMUX_FUNCTION(system_bus),
+	UNIPHIER_PINMUX_FUNCTION(uart0),
+	UNIPHIER_PINMUX_FUNCTION(uart1),
+	UNIPHIER_PINMUX_FUNCTION(uart2),
+	UNIPHIER_PINMUX_FUNCTION(uart3),
+	UNIPHIER_PINMUX_FUNCTION(usb0),
+	UNIPHIER_PINMUX_FUNCTION(usb1),
+	UNIPHIER_PINMUX_FUNCTION(usb2),
+	UNIPHIER_PINMUX_FUNCTION(usb3),
+	UNIPHIER_PINMUX_FUNCTION(port),
+	UNIPHIER_PINMUX_FUNCTION(xirq),
+};
+
+static struct uniphier_pinctrl_socdata uniphier_ld20_pindata = {
+	.pins = uniphier_ld20_pins,
+	.npins = ARRAY_SIZE(uniphier_ld20_pins),
+	.groups = uniphier_ld20_groups,
+	.groups_count = ARRAY_SIZE(uniphier_ld20_groups),
+	.functions = uniphier_ld20_functions,
+	.functions_count = ARRAY_SIZE(uniphier_ld20_functions),
+	.caps = UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL,
+};
+
+static int uniphier_ld20_pinctrl_probe(struct platform_device *pdev)
+{
+	return uniphier_pinctrl_probe(pdev, &uniphier_ld20_pindata);
+}
+
+static const struct of_device_id uniphier_ld20_pinctrl_match[] = {
+	{ .compatible = "socionext,uniphier-ld20-pinctrl" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, uniphier_ld20_pinctrl_match);
+
+static struct platform_driver uniphier_ld20_pinctrl_driver = {
+	.probe = uniphier_ld20_pinctrl_probe,
+	.driver = {
+		.name = "uniphier-ld20-pinctrl",
+		.of_match_table = uniphier_ld20_pinctrl_match,
+	},
+};
+module_platform_driver(uniphier_ld20_pinctrl_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro at socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-LD20 pinctrl driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1



From yamada.masahiro at socionext.com  Tue May 31 01:05:19 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:05:19 +0900
Subject: [PATCH 13/17] pinctrl: uniphier: add dedicated pins to pin tables of
 PH1-LD4/sLD8
In-Reply-To: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1464681923-7469-14-git-send-email-yamada.masahiro@socionext.com>

These pins do not support pin-muxing, but it is useful to support
pin configuration for them.

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

 drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c  | 31 ++++++++++++++++
 drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c | 46 ++++++++++++++++++++++++
 2 files changed, 77 insertions(+)

diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
index 9b59f8d..6692e80 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
@@ -515,6 +515,37 @@ static const struct pinctrl_pin_desc uniphier_ld4_pins[] = {
 	UNIPHIER_PINCTRL_PIN(164, "NANDRYBY0", UNIPHIER_PIN_IECTRL_NONE,
 			     37, UNIPHIER_PIN_DRV_1BIT,
 			     37, UNIPHIER_PIN_PULL_UP),
+	/* dedicated pins */
+	UNIPHIER_PINCTRL_PIN(165, "ED0", -1,
+			     0, UNIPHIER_PIN_DRV_1BIT,
+			     0, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(166, "ED1", -1,
+			     1, UNIPHIER_PIN_DRV_1BIT,
+			     1, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(167, "ED2", -1,
+			     2, UNIPHIER_PIN_DRV_1BIT,
+			     2, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(168, "ED3", -1,
+			     3, UNIPHIER_PIN_DRV_1BIT,
+			     3, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(169, "ED4", -1,
+			     4, UNIPHIER_PIN_DRV_1BIT,
+			     4, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(170, "ED5", -1,
+			     5, UNIPHIER_PIN_DRV_1BIT,
+			     5, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(171, "ED6", -1,
+			     6, UNIPHIER_PIN_DRV_1BIT,
+			     6, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(172, "ED7", -1,
+			     7, UNIPHIER_PIN_DRV_1BIT,
+			     7, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(173, "ERXW", -1,
+			     26, UNIPHIER_PIN_DRV_1BIT,
+			     26, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(174, "XECS1", -1,
+			     30, UNIPHIER_PIN_DRV_1BIT,
+			     30, UNIPHIER_PIN_PULL_UP),
 };
 
 static const unsigned emmc_pins[] = {21, 22, 23, 24, 25, 26, 27};
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
index d8b3655..1bda223 100644
--- a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
+++ b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
@@ -428,6 +428,52 @@ static const struct pinctrl_pin_desc uniphier_sld8_pins[] = {
 	UNIPHIER_PINCTRL_PIN(135, "XIRQ7", 0,
 			     118, UNIPHIER_PIN_DRV_1BIT,
 			     118, UNIPHIER_PIN_PULL_DOWN),
+	/* dedicated pins */
+	UNIPHIER_PINCTRL_PIN(136, "ED0", -1,
+			     0, UNIPHIER_PIN_DRV_1BIT,
+			     0, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(137, "ED1", -1,
+			     1, UNIPHIER_PIN_DRV_1BIT,
+			     1, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(138, "ED2", -1,
+			     2, UNIPHIER_PIN_DRV_1BIT,
+			     2, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(139, "ED3", -1,
+			     3, UNIPHIER_PIN_DRV_1BIT,
+			     3, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(140, "ED4", -1,
+			     4, UNIPHIER_PIN_DRV_1BIT,
+			     4, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(141, "ED5", -1,
+			     5, UNIPHIER_PIN_DRV_1BIT,
+			     5, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(142, "ED6", -1,
+			     6, UNIPHIER_PIN_DRV_1BIT,
+			     6, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(143, "ED7", -1,
+			     7, UNIPHIER_PIN_DRV_1BIT,
+			     7, UNIPHIER_PIN_PULL_DOWN),
+	UNIPHIER_PINCTRL_PIN(144, "XERWE0", -1,
+			     8, UNIPHIER_PIN_DRV_1BIT,
+			     8, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(145, "XERWE1", -1,
+			     9, UNIPHIER_PIN_DRV_1BIT,
+			     9, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(146, "ERXW", -1,
+			     10, UNIPHIER_PIN_DRV_1BIT,
+			     10, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(147, "ES0", -1,
+			     11, UNIPHIER_PIN_DRV_1BIT,
+			     11, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(148, "ES1", -1,
+			     12, UNIPHIER_PIN_DRV_1BIT,
+			     12, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(149, "ES2", -1,
+			     13, UNIPHIER_PIN_DRV_1BIT,
+			     13, UNIPHIER_PIN_PULL_UP),
+	UNIPHIER_PINCTRL_PIN(150, "XECS1", -1,
+			     14, UNIPHIER_PIN_DRV_1BIT,
+			     14, UNIPHIER_PIN_PULL_DOWN),
 };
 
 static const unsigned emmc_pins[] = {21, 22, 23, 24, 25, 26, 27};
-- 
1.9.1



From linus.walleij at linaro.org  Tue May 31 01:13:35 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 10:13:35 +0200
Subject: [PATCH] pinctrl: mediatek: fix dual-edge code defect
In-Reply-To: <1463815419-11719-1-git-send-email-hongkun.cao@mediatek.com>
References: <1463815419-11719-1-git-send-email-hongkun.cao@mediatek.com>
Message-ID: <CACRpkdYWEpVetL=YXs-FjaHUob6U6WjJspmiJYaGR8NPMjh6zA@mail.gmail.com>

On Sat, May 21, 2016 at 9:23 AM,  <hongkun.cao at mediatek.com> wrote:

> From: "hongkun.cao" <hongkun.cao at mediatek.com>
>
> When a dual-edge irq is triggered, an incorrect irq will be reported on
> condition that the external signal is not stable and this incorrect irq
> has been registered.
> Correct the register offset.
>
> Signed-off-by: hongkun.cao <hongkun.cao at mediatek.com>

Patch applied for fixes with Matthias' review tag.

Yours,
Linus Walleij


From yamada.masahiro at socionext.com  Tue May 31 01:17:08 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue, 31 May 2016 17:17:08 +0900
Subject: [PATCH] ARM: uniphier: drop code for old DT binding
Message-ID: <1464682628-12163-1-git-send-email-yamada.masahiro@socionext.com>

Commit 307d40c56b0c ("ARM: uniphier: rework SMP code to support new
System Bus binding") added a new DT binding for SMP code, but still
kept old code for the backward compatibility.

Linux 4.6 was out with both bindings supported, so it should not
hurt to drop the old code now.

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

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

diff --git a/arch/arm/mach-uniphier/platsmp.c b/arch/arm/mach-uniphier/platsmp.c
index e802ca8..9978c41 100644
--- a/arch/arm/mach-uniphier/platsmp.c
+++ b/arch/arm/mach-uniphier/platsmp.c
@@ -101,21 +101,13 @@ static int __init uniphier_smp_prepare_trampoline(unsigned int max_cpus)
 	np = of_find_compatible_node(NULL, NULL, "socionext,uniphier-smpctrl");
 	ret = of_address_to_resource(np, 0, &res);
 	of_node_put(np);
-	if (!ret) {
-		rom_rsv2_phys = res.start + UNIPHIER_SMPCTRL_ROM_RSV2;
-	} else {
-		/* try old binding too */
-		np = of_find_compatible_node(NULL, NULL,
-					     "socionext,uniphier-system-bus-controller");
-		ret = of_address_to_resource(np, 1, &res);
-		of_node_put(np);
-		if (ret) {
-			pr_err("failed to get resource of SMP control\n");
-			return ret;
-		}
-		rom_rsv2_phys = res.start + 0x1000 + UNIPHIER_SMPCTRL_ROM_RSV2;
+	if (ret) {
+		pr_err("failed to get resource of SMP control\n");
+		return ret;
 	}
 
+	rom_rsv2_phys = res.start + UNIPHIER_SMPCTRL_ROM_RSV2;
+
 	ret = uniphier_smp_copy_trampoline(rom_rsv2_phys);
 	if (ret)
 		return ret;
-- 
1.9.1



From fan.chen at mediatek.com  Tue May 31 01:20:35 2016
From: fan.chen at mediatek.com (Fan Chen)
Date: Tue, 31 May 2016 16:20:35 +0800
Subject: [PATCH v2 1/3] regulator: DT: Add DT property for operation
 mode configuration
In-Reply-To: <20160523112856.GR8206@sirena.org.uk>
References: <1463987611-32139-1-git-send-email-henryc.chen@mediatek.com>
 <1463987611-32139-2-git-send-email-henryc.chen@mediatek.com>
 <20160523104703.GB26992@leverpostej> <20160523112856.GR8206@sirena.org.uk>
Message-ID: <1464682835.25847.3.camel@mtksdaap41>

Hi Mark,

On Mon, 2016-05-23 at 12:28 +0100, Mark Brown wrote:
> On Mon, May 23, 2016 at 11:47:04AM +0100, Mark Rutland wrote:
> 
> > > +/* Regulator operating modes */
> > > +#define REGULATOR_OPERATION_MODE_FAST			0x0
> > > +#define REGULATOR_OPERATION_MODE_NORMAL			0x1
> > > +#define REGULATOR_OPERATION_MODE_IDLE			0x2
> > > +#define REGULATOR_OPERATION_MODE_STANDBY		0x3
> 
> > These sound like they're tied to linux internal details (e.g. the
> > implementation of idle and/or suspend).
> 
> > What do each of these actually mean?
> 
> They are not really at all general and I'm fairly sure I've provided the
> same feedback repeatedly on earlier versions of the patch set.  They are
> not entirely based on Linux internal details (or at least the Linux
> internal details tend to flow from the hardware) - broadly fast is
> forced PWM, normal is default, idle is LDO mode and standby is a lower
> quality LDO mode - but how this translates into anything that a consumer
> could actually use is unclear since the supported output loads and
> quality of regulation can vary wildy.  It's also somewhat implementation
> dependent what a given regulator does (and it's always possible that
> some regulators may have more modes to control or differing definitions
> in the hardware).
> 
> Henry, *please* look at how the existing mode support in the bindings is
> done and consider how a consumer would use this given that it doesn't
> know anything about the regulator...

Hi Mark,

Thanks for your review and patiently explain your thought to us.

In the case of svs[1], which Henry mentioned in cover letter, it can be
regarded as a special consumer who requires very accurate voltage for
calibration the hardware in its initialization stage. So, this kinds of
consumers know their regulator very well and only need to switch to the
modes they want in the particular conditions.
However, IIUC, you want a proposal to provide a sort of QoS framework
which can cover most of use cases who care about the regular quality in
runtime, is that correct?

IMHO, some quality index can be considered, for example:
Minimum Current Requirement (mA): If a user specified this constraint in
runtime, it means that he cares more about the supplying quality like
transient voltage drop, ripple above certain load.
Maximum Current Requirement (mA): If a user specified this constraint in
runtime, it means that he cares more about the power consumption under
certain load.
It could be a flexible way instead to tie the operation modes directly.

BTW, we should encourage people here to share more use cases related to
regulator quality issues, especially in runtime, so we can evaluate the
most suitable index to fit the requirements.

What do you think?


[1] http://www.spinics.net/lists/devicetree/msg111208.html


Best regards,
Fan

> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek




From daniel.lezcano at linaro.org  Tue May 31 01:24:02 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 31 May 2016 10:24:02 +0200
Subject: [PATCH 2/4] clocksource: sp804: introduce helper
 sp804_load_mode_set()
In-Reply-To: <1464428033-52106-3-git-send-email-wangkefeng.wang@huawei.com>
References: <1464428033-52106-1-git-send-email-wangkefeng.wang@huawei.com>
 <1464428033-52106-3-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <574D4A22.703@linaro.org>

On 05/28/2016 11:33 AM, Kefeng Wang wrote:
> Introduce helper sp804_load_mode_set(), and use it, prepare for 64bit
> mode timer support.

More verbose please.

> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> ---
>   drivers/clocksource/timer-sp804.c | 27 +++++++++++++--------------
>   1 file changed, 13 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
> index 362e5d0..b8848e5 100644
> --- a/drivers/clocksource/timer-sp804.c
> +++ b/drivers/clocksource/timer-sp804.c
> @@ -73,6 +73,15 @@ static long __init sp804_get_clock_rate(struct clk *clk, const char *name)
>   	return rate;
>   }
>
> +static inline void sp804_load_mode_set(void __iomem *base, unsigned long load, int mode)
> +{
> +	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
> +			     mode | TIMER_CTRL_ENABLE;
> +
> +	writel(load, base + TIMER_LOAD);
> +	writel(ctrl, base + TIMER_CTRL);
> +}
> +
>   static void __iomem *sched_clock_base;
>
>   static u64 notrace sp804_read(void)
> @@ -97,10 +106,8 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
>
>   	/* setup timer 0 as free-running clocksource */
>   	writel(0, base + TIMER_CTRL);
> -	writel(0xffffffff, base + TIMER_LOAD);
>   	writel(0xffffffff, base + TIMER_VALUE);
> -	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
> -		base + TIMER_CTRL);
> +	sp804_load_mode_set(base, 0xffffffff, TIMER_CTRL_PERIODIC & ~TIMER_CTRL_IE);

Can you explain this change ?

>   	clocksource_mmio_init(base + TIMER_VALUE, name,
>   		rate, 200, 32, clocksource_mmio_readl_down);
> @@ -143,24 +150,16 @@ static int sp804_shutdown(struct clock_event_device *evt)
>
>   static int sp804_set_periodic(struct clock_event_device *evt)
>   {
> -	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
> -			     TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
> -
>   	timer_shutdown(evt);
> -	writel(clkevt_reload, clkevt_base + TIMER_LOAD);
> -	writel(ctrl, clkevt_base + TIMER_CTRL);
> +	sp804_load_mode_set(clkevt_base, clkevt_reload, TIMER_CTRL_PERIODIC);
>   	return 0;
>   }
>
>   static int sp804_set_next_event(unsigned long next,
> -	struct clock_event_device *evt)
> +				struct clock_event_device *evt)
>   {
> -	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
> -			     TIMER_CTRL_ONESHOT | TIMER_CTRL_ENABLE;
> -
> -	writel(next, clkevt_base + TIMER_LOAD);
> -	writel(ctrl, clkevt_base + TIMER_CTRL);
>
> +	sp804_load_mode_set(clkevt_base, next, TIMER_CTRL_ONESHOT);
>   	return 0;
>   }
>
>


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

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



From daniel.lezcano at linaro.org  Tue May 31 01:25:34 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 31 May 2016 10:25:34 +0200
Subject: [PATCH 3/4] clocksource: sp804: use sp804_timer_disable() where
 possible
In-Reply-To: <1464428033-52106-4-git-send-email-wangkefeng.wang@huawei.com>
References: <1464428033-52106-1-git-send-email-wangkefeng.wang@huawei.com>
 <1464428033-52106-4-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <574D4A7E.7000301@linaro.org>

On 05/28/2016 11:33 AM, Kefeng Wang wrote:
> Use sp804_timer_disable() where possible, prepare for 64bit mode timer support.

Explain this change please.

> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> ---
>   drivers/clocksource/timer-sp804.c | 11 +++++------
>   1 file changed, 5 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
> index b8848e5..2ff8777 100644
> --- a/drivers/clocksource/timer-sp804.c
> +++ b/drivers/clocksource/timer-sp804.c
> @@ -105,7 +105,7 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
>   		return;
>
>   	/* setup timer 0 as free-running clocksource */
> -	writel(0, base + TIMER_CTRL);
> +	sp804_timer_disable(base);
>   	writel(0xffffffff, base + TIMER_VALUE);
>   	sp804_load_mode_set(base, 0xffffffff, TIMER_CTRL_PERIODIC & ~TIMER_CTRL_IE);
>
> @@ -196,8 +196,7 @@ void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struc
>   	evt->irq = irq;
>   	evt->cpumask = cpu_possible_mask;
>
> -	writel(0, base + TIMER_CTRL);
> -
> +	sp804_timer_disable(base);
>   	setup_irq(irq, &sp804_timer_irq);
>   	clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
>   }
> @@ -216,8 +215,8 @@ static void __init sp804_of_init(struct device_node *np)
>   		return;
>
>   	/* Ensure timers are disabled */
> -	writel(0, base + TIMER_CTRL);
> -	writel(0, base + TIMER_2_BASE + TIMER_CTRL);
> +	sp804_timer_disable(base);
> +	sp804_timer_disable(base + TIMER_2_BASE);
>
>   	if (initialized || !of_device_is_available(np))
>   		goto err;
> @@ -274,7 +273,7 @@ static void __init integrator_cp_of_init(struct device_node *np)
>   		return;
>
>   	/* Ensure timer is disabled */
> -	writel(0, base + TIMER_CTRL);
> +	sp804_timer_disable(base);
>
>   	if (init_count == 2 || !of_device_is_available(np))
>   		goto err;
>


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

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



From linus.walleij at linaro.org  Tue May 31 01:31:16 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 10:31:16 +0200
Subject: [PATCH] pinctrl: digicolor: add missing platform_set_drvdata()
 call
In-Reply-To: <1464155932-25344-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464155932-25344-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdZMZvV6fYsr0Dx8Fiu-W8uYrqK92tzHkMG4BOECRbbHkA@mail.gmail.com>

On Wed, May 25, 2016 at 7:58 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> gc_pinctrl_remove() calls platform_get_drvdata(), but I see neither
> platform_set_drvdata() nor dev_set_drvdata() anywhere in this driver.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied with Baruch's ACK.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 01:35:08 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 10:35:08 +0200
Subject: [PATCH v2 1/4] pinctrl: amlogic: gxbb: add UART_AO_B, I2C
In-Reply-To: <1464297865-8965-2-git-send-email-khilman@baylibre.com>
References: <1464297865-8965-1-git-send-email-khilman@baylibre.com>
 <1464297865-8965-2-git-send-email-khilman@baylibre.com>
Message-ID: <CACRpkdZSXtuHxpxxQB3JEOQPYHuWzQrDt5=F627ujNMFnBnKog@mail.gmail.com>

On Thu, May 26, 2016 at 11:24 PM, Kevin Hilman <khilman at baylibre.com> wrote:

> Add pins for some more AO domain devices: UART_AO_B and I2C master &
> slave.
>
> Acked-by: Carlo Caione <carlo at endlessm.com>
> Signed-off-by: Kevin Hilman <khilman at baylibre.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 01:35:54 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 10:35:54 +0200
Subject: [PATCH v2 2/4] pinctrl: amlogic: gxbb: add EMMC and SD pins
In-Reply-To: <1464297865-8965-3-git-send-email-khilman@baylibre.com>
References: <1464297865-8965-1-git-send-email-khilman@baylibre.com>
 <1464297865-8965-3-git-send-email-khilman@baylibre.com>
Message-ID: <CACRpkdaBdYuXgybtLJy7F2JDmGqdkCrNqeddQTtiePf9tdik9w@mail.gmail.com>

On Thu, May 26, 2016 at 11:24 PM, Kevin Hilman <khilman at baylibre.com> wrote:

> Add EE domain pins for eMMC and SD card.
>
> Acked-by: Carlo Caione <carlo at endlessm.com>
> Signed-off-by: Kevin Hilman <khilman at baylibre.com>

Patch applied.

Yours,
Linus Walleij


From hs.liao at mediatek.com  Tue May 31 01:36:02 2016
From: hs.liao at mediatek.com (Horng-Shyang Liao)
Date: Tue, 31 May 2016 16:36:02 +0800
Subject: [PATCH v8 2/3] CMDQ: Mediatek CMDQ driver
In-Reply-To: <574C5CBF.7060002@gmail.com>
References: <1464578397-29743-1-git-send-email-hs.liao@mediatek.com>
 <1464578397-29743-3-git-send-email-hs.liao@mediatek.com>
 <574C5CBF.7060002@gmail.com>
Message-ID: <1464683762.14604.59.camel@mtksdaap41>

Hi Mathias,

Please see my inline reply.

On Mon, 2016-05-30 at 17:31 +0200, Matthias Brugger wrote:
> 
> On 30/05/16 05:19, HS Liao wrote:
> > This patch is first version of Mediatek Command Queue(CMDQ) driver. The
> > CMDQ is used to help read/write registers with critical time limitation,
> > such as updating display configuration during the vblank. It controls
> > Global Command Engine (GCE) hardware to achieve this requirement.
> > Currently, CMDQ only supports display related hardwares, but we expect
> > it can be extended to other hardwares for future requirements.
> >
> > Signed-off-by: HS Liao <hs.liao at mediatek.com>
> > Signed-off-by: CK Hu <ck.hu at mediatek.com>
> > ---
> >   drivers/soc/mediatek/Kconfig    |  10 +
> >   drivers/soc/mediatek/Makefile   |   1 +
> >   drivers/soc/mediatek/mtk-cmdq.c | 943 ++++++++++++++++++++++++++++++++++++++++
> >   include/soc/mediatek/cmdq.h     | 197 +++++++++
> >   4 files changed, 1151 insertions(+)
> >   create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
> >   create mode 100644 include/soc/mediatek/cmdq.h
> >
> > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
> > index 0a4ea80..c4ad75c 100644
> > --- a/drivers/soc/mediatek/Kconfig
> > +++ b/drivers/soc/mediatek/Kconfig
> > @@ -1,6 +1,16 @@
> >   #
> >   # MediaTek SoC drivers
> >   #
> > +config MTK_CMDQ
> > +	bool "MediaTek CMDQ Support"
> > +	depends on ARCH_MEDIATEK || COMPILE_TEST
> > +	select MTK_INFRACFG
> > +	help
> > +	  Say yes here to add support for the MediaTek Command Queue (CMDQ)
> > +	  driver. The CMDQ is used to help read/write registers with critical
> > +	  time limitation, such as updating display configuration during the
> > +	  vblank.
> > +
> >   config MTK_INFRACFG
> >   	bool "MediaTek INFRACFG Support"
> >   	depends on ARCH_MEDIATEK || COMPILE_TEST
> > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
> > index 12998b0..f7397ef 100644
> > --- a/drivers/soc/mediatek/Makefile
> > +++ b/drivers/soc/mediatek/Makefile
> > @@ -1,3 +1,4 @@
> > +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq.o
> >   obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
> >   obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
> >   obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
> > diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
> > new file mode 100644
> > index 0000000..e9d6e1c
> > --- /dev/null
> > +++ b/drivers/soc/mediatek/mtk-cmdq.c
> > @@ -0,0 +1,943 @@
> > +/*
> > + * Copyright (c) 2015 MediaTek Inc.
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/clk-provider.h>
> > +#include <linux/completion.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/errno.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/kernel.h>
> > +#include <linux/kthread.h>
> > +#include <linux/module.h>
> > +#include <linux/mutex.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/slab.h>
> > +#include <linux/spinlock.h>
> > +#include <linux/suspend.h>
> > +#include <linux/workqueue.h>
> > +#include <soc/mediatek/cmdq.h>
> > +
> > +#define CMDQ_INITIAL_CMD_BLOCK_SIZE	PAGE_SIZE
> > +#define CMDQ_INST_SIZE			8 /* instruction is 64-bit */
> > +#define CMDQ_TIMEOUT_MS			1000
> > +#define CMDQ_IRQ_MASK			0xffff
> > +#define CMDQ_DRIVER_DEVICE_NAME		"mtk_cmdq"
> > +#define CMDQ_CLK_NAME			"gce"
> 
> We can put the names in directly to un-bloat the defines.

I will use the names directly and remove defines.

> > +
> > +#define CMDQ_CURR_IRQ_STATUS		0x010
> > +#define CMDQ_CURR_LOADED_THR		0x018
> > +#define CMDQ_THR_SLOT_CYCLES		0x030
> > +
> > +#define CMDQ_THR_BASE			0x100
> > +#define CMDQ_THR_SHIFT			0x080
> 
> Wouldn't be CMDQ_THR_SIZE more accurate?

Will rename it.

> > +#define CMDQ_THR_WARM_RESET		0x00
> > +#define CMDQ_THR_ENABLE_TASK		0x04
> > +#define CMDQ_THR_SUSPEND_TASK		0x08
> > +#define CMDQ_THR_CURR_STATUS		0x0c
> > +#define CMDQ_THR_IRQ_STATUS		0x10
> > +#define CMDQ_THR_IRQ_ENABLE		0x14
> > +#define CMDQ_THR_CURR_ADDR		0x20
> > +#define CMDQ_THR_END_ADDR		0x24
> > +#define CMDQ_THR_CFG			0x40
> > +
> > +#define CMDQ_THR_ENABLED		0x1
> > +#define CMDQ_THR_DISABLED		0x0
> > +#define CMDQ_THR_SUSPEND		0x1
> > +#define CMDQ_THR_RESUME			0x0
> > +#define CMDQ_THR_STATUS_SUSPENDED	BIT(1)
> > +#define CMDQ_THR_DO_WARM_RESET		BIT(0)
> > +#define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
> > +#define CMDQ_THR_PRIORITY		3
> > +#define CMDQ_THR_IRQ_DONE		0x1
> > +#define CMDQ_THR_IRQ_ERROR		0x12
> > +#define CMDQ_THR_IRQ_EN			0x13 /* done + error */
> 
> #define CMDQ_THR_IRQ_EN (CMDQ_THR_IRQ_ERROR | CMDQ_THR_IRQ_DONE)

Will do.

> > +#define CMDQ_THR_IRQ_MASK		0x13
> 
> never used.

Will remove.

> > +#define CMDQ_THR_EXECUTING		BIT(31)
> > +
> > +#define CMDQ_ARG_A_WRITE_MASK		0xffff
> > +#define CMDQ_SUBSYS_MASK		0x1f
> > +#define CMDQ_OP_CODE_MASK		0xff000000
> > +
> > +#define CMDQ_OP_CODE_SHIFT		24
> 
> Couldn't we connect the mask with the shift, or aren't they related?
> 
> #define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT)

Will do.

> > +#define CMDQ_SUBSYS_SHIFT		16
> > +
> > +#define CMDQ_WRITE_ENABLE_MASK		BIT(0)
> > +#define CMDQ_JUMP_BY_OFFSET		0x10000000
> > +#define CMDQ_JUMP_BY_PA			0x10000001
> > +#define CMDQ_JUMP_PASS			CMDQ_INST_SIZE
> > +#define CMDQ_WFE_UPDATE			BIT(31)
> > +#define CMDQ_WFE_WAIT			BIT(15)
> > +#define CMDQ_WFE_WAIT_VALUE		0x1
> > +#define CMDQ_EOC_IRQ_EN			BIT(0)
> > +
> > +enum cmdq_thread_index {
> > +	CMDQ_THR_DISP_MAIN_IDX,	/* main */
> > +	CMDQ_THR_DISP_SUB_IDX,	/* sub */
> > +	CMDQ_THR_DISP_MISC_IDX,	/* misc */
> > +	CMDQ_THR_MAX_COUNT,	/* max */
> > +};
> > +
> > +/*
> > + * CMDQ_CODE_MOVE:
> > + *   move value into internal register as mask
> > + *   format: op mask
> > + * CMDQ_CODE_WRITE:
> > + *   write value into target register
> > + *   format: op subsys address value
> > + * CMDQ_CODE_JUMP:
> > + *   jump by offset
> > + *   format: op offset
> > + * CMDQ_CODE_WFE:
> > + *   wait for event and clear
> > + *   it is just clear if no wait
> > + *   format: [wait]  op event update:1 to_wait:1 wait:1
> > + *           [clear] op event update:1 to_wait:0 wait:0
> > + * CMDQ_CODE_EOC:
> > + *   end of command
> > + *   format: op irq_flag
> > + */
> 
> I think we need more documentation of how this command queue engine is 
> working. If not, I think it will be really complicated to understand how 
> to use this.
> 
> > +enum cmdq_code {
> > +	CMDQ_CODE_MOVE = 0x02,
> > +	CMDQ_CODE_WRITE = 0x04,
> > +	CMDQ_CODE_JUMP = 0x10,
> > +	CMDQ_CODE_WFE = 0x20,
> > +	CMDQ_CODE_EOC = 0x40,
> > +};
> > +
> > +enum cmdq_task_state {
> > +	TASK_STATE_BUSY, /* running on a GCE thread */
> > +	TASK_STATE_ERROR,
> > +	TASK_STATE_DONE,
> > +};
> > +
> > +struct cmdq_task_cb {
> > +	cmdq_async_flush_cb	cb;
> > +	void			*data;
> > +};
> > +
> > +struct cmdq_thread {
> > +	void __iomem		*base;
> > +	struct list_head	task_busy_list;
> > +	wait_queue_head_t	wait_task_done;
> > +};
> > +
> > +struct cmdq_task {
> > +	struct cmdq		*cmdq;
> > +	struct list_head	list_entry;
> > +	enum cmdq_task_state	task_state;
> > +	void			*va_base;
> > +	dma_addr_t		pa_base;
> > +	u64			engine_flag;
> > +	size_t			command_size;
> > +	u32			num_cmd;
> 
> num_cmd is directly connected to command_size. I prefer to just keep 
> num_cmd and calculate the command_size where necessary.

After I trace code, I prefer to keep command_size and calculate num_cmd
where necessary. What do you think?

> > +	struct cmdq_thread	*thread;
> > +	struct cmdq_task_cb	cb;
> > +	struct work_struct	release_work;
> > +};
> > +
> > +struct cmdq {
> > +	struct device		*dev;
> > +	void __iomem		*base;
> > +	u32			irq;
> > +	struct workqueue_struct	*task_release_wq;
> > +	struct cmdq_thread	thread[CMDQ_THR_MAX_COUNT];
> > +	struct mutex		task_mutex;	/* for task */
> > +	spinlock_t		exec_lock;	/* for exec */
> > +	struct clk		*clock;
> > +	bool			suspended;
> > +};
> > +
> > +struct cmdq_subsys {
> > +	u32	base;
> > +	int	id;
> > +};
> > +
> > +static const struct cmdq_subsys gce_subsys[] = {
> > +	{0x1400, 1},
> > +	{0x1401, 2},
> > +	{0x1402, 3},
> > +};
> > +
> > +static int cmdq_subsys_base_to_id(u32 base)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(gce_subsys); i++)
> > +		if (gce_subsys[i].base == base)
> > +			return gce_subsys[i].id;
> > +	return -EFAULT;
> > +}
> > +
> > +static int cmdq_eng_get_thread(u64 flag)
> > +{
> > +	if (flag & BIT_ULL(CMDQ_ENG_DISP_DSI0))
> > +		return CMDQ_THR_DISP_MAIN_IDX;
> > +	else if (flag & BIT_ULL(CMDQ_ENG_DISP_DPI0))
> > +		return CMDQ_THR_DISP_SUB_IDX;
> > +	else
> > +		return CMDQ_THR_DISP_MISC_IDX;
> > +}
> > +
> > +static void cmdq_task_release(struct cmdq_task *task)
> > +{
> > +	struct cmdq *cmdq = task->cmdq;
> > +
> > +	dma_free_coherent(cmdq->dev, task->command_size, task->va_base,
> > +			  task->pa_base);
> > +	kfree(task);
> > +}
> > +
> > +static struct cmdq_task *cmdq_task_acquire(struct cmdq_rec *rec,
> > +					   struct cmdq_task_cb cb)
> > +{
> > +	struct cmdq *cmdq = rec->cmdq;
> > +	struct device *dev = cmdq->dev;
> > +	struct cmdq_task *task;
> > +
> > +	task = kzalloc(sizeof(*task), GFP_KERNEL);
> > +	INIT_LIST_HEAD(&task->list_entry);
> > +	task->va_base = dma_alloc_coherent(dev, rec->command_size,
> > +					   &task->pa_base, GFP_KERNEL);
> > +	if (!task->va_base) {
> > +		dev_err(dev, "allocate command buffer failed\n");
> > +		kfree(task);
> > +		return NULL;
> > +	}
> > +
> > +	task->cmdq = cmdq;
> > +	task->command_size = rec->command_size;
> > +	task->engine_flag = rec->engine_flag;
> > +	task->task_state = TASK_STATE_BUSY;
> > +	task->cb = cb;
> > +	memcpy(task->va_base, rec->buf, rec->command_size);
> > +	task->num_cmd = task->command_size / CMDQ_INST_SIZE;
> > +	return task;
> > +}
> > +
> > +static void cmdq_thread_writel(struct cmdq_thread *thread, u32 value,
> > +			       u32 offset)
> > +{
> > +	writel(value, thread->base + offset);
> > +}
> > +
> > +static u32 cmdq_thread_readl(struct cmdq_thread *thread, u32 offset)
> > +{
> > +	return readl(thread->base + offset);
> > +}
> 
> We can get rid of cmdq_thread_readl/writel.

Will do.

> > +
> > +static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
> > +{
> > +	u32 status;
> > +
> > +	cmdq_thread_writel(thread, CMDQ_THR_SUSPEND, CMDQ_THR_SUSPEND_TASK);
> > +
> > +	/* If already disabled, treat as suspended successful. */
> > +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> > +	      CMDQ_THR_ENABLED))
> > +		return 0;
> > +
> > +	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_CURR_STATUS,
> > +			status, status & CMDQ_THR_STATUS_SUSPENDED, 0, 10)) {
> > +		dev_err(cmdq->dev, "suspend GCE thread 0x%x failed\n",
> > +			(u32)(thread->base - cmdq->base));
> > +		return -EFAULT;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void cmdq_thread_resume(struct cmdq_thread *thread)
> > +{
> > +	cmdq_thread_writel(thread, CMDQ_THR_RESUME, CMDQ_THR_SUSPEND_TASK);
> > +}
> > +
> > +static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
> > +{
> > +	u32 warm_reset;
> > +
> > +	cmdq_thread_writel(thread, CMDQ_THR_DO_WARM_RESET, CMDQ_THR_WARM_RESET);
> > +	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET,
> > +			warm_reset, !(warm_reset & CMDQ_THR_DO_WARM_RESET),
> > +			0, 10)) {
> > +		dev_err(cmdq->dev, "reset GCE thread 0x%x failed\n",
> > +			(u32)(thread->base - cmdq->base));
> > +		return -EFAULT;
> > +	}
> > +	writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES);
> > +	return 0;
> > +}
> > +
> > +static void cmdq_thread_disable(struct cmdq *cmdq, struct cmdq_thread *thread)
> > +{
> > +	cmdq_thread_reset(cmdq, thread);
> > +	cmdq_thread_writel(thread, CMDQ_THR_DISABLED, CMDQ_THR_ENABLE_TASK);
> > +}
> > +
> > +/* notify GCE to re-fetch commands by setting GCE thread PC */
> > +static void cmdq_thread_invalidate_fetched_data(struct cmdq_thread *thread)
> > +{
> > +	cmdq_thread_writel(thread,
> > +			   cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR),
> > +			   CMDQ_THR_CURR_ADDR);
> > +}
> > +
> > +static void cmdq_task_insert_into_thread(struct cmdq_task *task)
> > +{
> > +	struct cmdq_thread *thread = task->thread;
> > +	struct cmdq_task *prev_task = list_last_entry(
> > +			&thread->task_busy_list, typeof(*task), list_entry);
> > +	u64 *prev_task_base = prev_task->va_base;
> > +
> > +	/* let previous task jump to this task */
> > +	prev_task_base[prev_task->num_cmd - 1] = (u64)CMDQ_JUMP_BY_PA << 32 |
> > +						 task->pa_base;
> > +
> > +	cmdq_thread_invalidate_fetched_data(thread);
> > +}
> > +
> > +/* we assume tasks in the same display GCE thread are waiting the same event. */
> > +static void cmdq_task_remove_wfe(struct cmdq_task *task)
> > +{
> > +	u32 wfe_option = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
> > +	u32 wfe_op = CMDQ_CODE_WFE << CMDQ_OP_CODE_SHIFT;
> > +	u32 *base = task->va_base;
> > +	u32 num_cmd = task->num_cmd << 1;
> > +	int i;
> > +
> > +	for (i = 0; i < num_cmd; i += 2)
> > +		if (base[i] == wfe_option &&
> > +		    (base[i + 1] & CMDQ_OP_CODE_MASK) == wfe_op) {
> > +			base[i] = CMDQ_JUMP_PASS;
> > +			base[i + 1] = CMDQ_JUMP_BY_OFFSET;
> > +		}
> 
> After using the command buffer as a void pointer a u64 pointer, we now 
> reference to it as u32. I would prefer to explain here, how the command 
> looks like we are searching for and use a for loop passing task->num_cmd 
> instead.

Will use u64* to rewrite the above code.

> > +}
> > +
> > +static void cmdq_task_exec(struct cmdq_task *task, struct cmdq_thread *thread)
> > +{
> > +	struct cmdq *cmdq = task->cmdq;
> > +	unsigned long flags;
> > +	unsigned long curr_pa, end_pa;
> > +
> > +	WARN_ON(clk_prepare_enable(cmdq->clock) < 0);
> > +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> 
> cmdq_task_exec is called with cmdq->task_mutex held, so why do we need 
> the spin_lock here? Can't we just use one of the two?

We can drop task_mutex, but we will get some side effects.
1. exec_lock needs to include more code, but I think it is not good for
   spinlock.
2. In cmdq_rec_flush_async(), task_mutex needs to protect
   (1) cmdq->suspended, (2) cmdq_task_exec(), and
   (3) cmdq_task_wait_release_schedule().
   If we drop task_mutex, we have to put cmdq->suspended if condition
   just before cmdq_task_exec() and inside exec_lock, and we have to
   release task and its command buffer if error. This will let flow
   become more complex and enlarge code size.

What do you think?

> > +	task->thread = thread;
> > +	task->task_state = TASK_STATE_BUSY;
> 
> That was already set in cmdq_task_acquire, why do we need to set it here 
> again?

Will drop it.

> > +	if (list_empty(&thread->task_busy_list)) {
> > +		WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
> > +
> > +		cmdq_thread_writel(thread, task->pa_base, CMDQ_THR_CURR_ADDR);
> > +		cmdq_thread_writel(thread, task->pa_base + task->command_size,
> > +				   CMDQ_THR_END_ADDR);
> > +		cmdq_thread_writel(thread, CMDQ_THR_PRIORITY, CMDQ_THR_CFG);
> > +		cmdq_thread_writel(thread, CMDQ_THR_IRQ_EN,
> > +				   CMDQ_THR_IRQ_ENABLE);
> > +
> > +		cmdq_thread_writel(thread, CMDQ_THR_ENABLED,
> > +				   CMDQ_THR_ENABLE_TASK);
> > +	} else {
> > +		WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
> > +
> > +		/*
> > +		 * check boundary condition
> > +		 * PC = END - 8, EOC is executed
> > +		 * PC = END, all CMDs are executed
> > +		 */
> > +		curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
> > +		end_pa = cmdq_thread_readl(thread, CMDQ_THR_END_ADDR);
> > +		if (curr_pa == end_pa - 8 || curr_pa == end_pa) {
> 
> 8 refers to CMDQ_INST_SIZE, right?

Yes, I will use CMDQ_INST_SIZE.

> > +			/* set to this task directly */
> > +			cmdq_thread_writel(thread, task->pa_base,
> > +					   CMDQ_THR_CURR_ADDR);
> > +		} else {
> > +			cmdq_task_insert_into_thread(task);
> > +
> > +			if (thread == &cmdq->thread[CMDQ_THR_DISP_MAIN_IDX] ||
> > +			    thread == &cmdq->thread[CMDQ_THR_DISP_SUB_IDX])
> > +				cmdq_task_remove_wfe(task);
> 
> We could do this check using the task->engine_flag, I suppose that's 
> easier to undestand then.

Will use task->engine_flag.

> > +
> > +			smp_mb(); /* modify jump before enable thread */
> > +		}
> > +
> > +		cmdq_thread_writel(thread, task->pa_base + task->command_size,
> > +				   CMDQ_THR_END_ADDR);
> > +		cmdq_thread_resume(thread);
> > +	}
> > +	list_move_tail(&task->list_entry, &thread->task_busy_list);
> > +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > +}
> > +
> > +static void cmdq_handle_error_done(struct cmdq *cmdq,
> > +				   struct cmdq_thread *thread, u32 irq_flag)
> > +{
> > +	struct cmdq_task *task, *tmp, *curr_task = NULL;
> > +	u32 curr_pa;
> > +	struct cmdq_cb_data cmdq_cb_data;
> > +	bool err;
> > +
> > +	if (irq_flag & CMDQ_THR_IRQ_ERROR)
> > +		err = true;
> > +	else if (irq_flag & CMDQ_THR_IRQ_DONE)
> > +		err = false;
> > +	else
> > +		return;
> > +
> > +	curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
> > +
> > +	list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
> > +				 list_entry) {
> > +		if (curr_pa >= task->pa_base &&
> > +		    curr_pa < (task->pa_base + task->command_size))
> 
> What are you checking here? It seems as if you make some implcit 
> assumptions about pa_base and the order of execution of commands in the 
> thread. Is it save to do so? Does dma_alloc_coherent give any guarantees 
> about dma_handle?

1. Check what is the current running task in this GCE thread.
2. Yes.
3. Yes, CMDQ doesn't use iommu, so physical address is continuous.

> > +			curr_task = task;
> > +		if (task->cb.cb) {
> > +			cmdq_cb_data.err = curr_task ? err : false;
> > +			cmdq_cb_data.data = task->cb.data;
> > +			task->cb.cb(cmdq_cb_data);
> > +		}
> > +		task->task_state = (curr_task && err) ? TASK_STATE_ERROR :
> > +				TASK_STATE_DONE;
> > +		list_del(&task->list_entry);
> > +		if (curr_task)
> > +			break;
> > +	}
> > +
> > +	wake_up(&thread->wait_task_done);
> > +}
> > +
> > +static void cmdq_thread_irq_handler(struct cmdq *cmdq, int tid)
> > +{
> > +	struct cmdq_thread *thread = &cmdq->thread[tid];
> > +	unsigned long flags = 0L;
> > +	u32 irq_flag;
> > +
> > +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> > +
> > +	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> > +	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
> > +
> > +	/*
> > +	 * Another CPU core could run "release task" right before we acquire
> > +	 * the spin lock, and thus reset / disable this GCE thread, so we
> > +	 * need to check the enable bit of this GCE thread.
> > +	 */
> > +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> > +	      CMDQ_THR_ENABLED))
> > +		irq_flag = 0;
> 
> cmdq_handle_error_done just retuns in this case. Programming this way 
> just makes things confusing. What about:
> 
> if (cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> 	      CMDQ_THR_ENABLED)
> 	cmdq_handle_error_done(cmdq, thread, irq_flag);
> else
> 		irq_flag = 0;
> 
> spin_unlock_irqrestore(&cmdq->exec_lock, flags);

We still need to clear irq_flag if GCE thread is disabled.
So, I think we can just return here.

	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
	      CMDQ_THR_ENABLED))
		return;
 
What do you think?

> > +
> > +	cmdq_handle_error_done(cmdq, thread, irq_flag);
> > +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > +}
> > +
> > +static irqreturn_t cmdq_irq_handler(int irq, void *dev)
> > +{
> > +	struct cmdq *cmdq = dev;
> > +	u32 irq_status;
> > +	int i;
> > +
> > +	irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS);
> > +	irq_status &= CMDQ_IRQ_MASK;
> > +	irq_status ^= CMDQ_IRQ_MASK;
> 
> irq_status can be much bigger then 3, which is the number of threads in 
> the system (CMDQ_THR_MAX_COUNT). So why we use this mask here isn't 
> clear to me.

Our GCE hardware has 16 threads, but we only use 3 threads currently.

> > +
> > +	if (!irq_status)
> > +		return IRQ_NONE;
> > +
> > +	while (irq_status) {
> > +		i = ffs(irq_status) - 1;
> > +		irq_status &= ~BIT(i);
> > +		cmdq_thread_irq_handler(cmdq, i);
> > +	}
> 
> Can you explain how the irq status register looks like, that would it 
> make much easier to understand what happens here.

Bit 0 ~ 15 of irq status register represents GCE thread 0 ~ 15
interrupt. 0 means asserting interrupt; 1 means no interrupt.

> > +
> > +	return IRQ_HANDLED;	
> > +}
> > +
> > +static int cmdq_task_handle_error_result(struct cmdq_task *task)
> 
> We never check the return values, why do we have them?

Will drop return value.

> > +{
> > +	struct cmdq *cmdq = task->cmdq;
> > +	struct device *dev = cmdq->dev;
> > +	struct cmdq_thread *thread = task->thread;
> > +	struct cmdq_task *next_task, *prev_task;
> > +	u32 irq_flag;
> > +
> > +	/* suspend GCE thread to ensure consistency */
> > +	WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
> > +
> > +	/* ISR has handled this error task */
> > +	if (task->task_state == TASK_STATE_ERROR) {
> > +		next_task = list_first_entry_or_null(&thread->task_busy_list,
> > +				struct cmdq_task, list_entry);
> > +		if (next_task) /* move to next task */
> > +			cmdq_thread_writel(thread, next_task->pa_base,
> > +					   CMDQ_THR_CURR_ADDR);
> 
> We have to do this, as we suppose that the thread did not reach the jump 
> instruction we put into it's command queue, right?

Yes.

> > +		cmdq_thread_resume(thread);
> > +		return -ECANCELED;
> > +	}
> > +
> 
> if task_state != ERROR and != DONE. This means that the timeout of 
> task_release_wq has timed out, right?

Yes.

> > +	/*
> > +	 * Save next_task and prev_task in advance
> > +	 * since cmdq_handle_error_done will remove list_entry.
> > +	 */
> > +	next_task = prev_task = NULL;
> > +	if (task->list_entry.next != &thread->task_busy_list)
> > +		next_task = list_next_entry(task, list_entry);
> > +	if (task->list_entry.prev != &thread->task_busy_list)
> > +		prev_task = list_prev_entry(task, list_entry);
> > +
> > +	/*
> > +	 * Although IRQ is disabled, GCE continues to execute.
> > +	 * It may have pending IRQ before GCE thread is suspended,
> > +	 * so check this condition again.
> > +	 */
> 
> The first thing we did in this function was suspending the thread. Why 
> do we need this then?

Because timeout is CPU timeout not GCE timeout, GCE could just finish
this task before the GCE thread is suspended.

> To be honest this whole functions looks really like a design error. We 
> have to sperate the states much clearer so that it is possible to 
> understand what is happening in the GCE. Isn't it for example posible to 
> have worker queues for timed out tasks and tasks with an error? I'm not 
> sure how to do this, actually I'm not sure if I really understood how 
> this is supposed to work.

GCE doesn't have timeout. The timeout is decided and controlled by CPU,
so we check timeout in release work.
For error and done, they are easy to check by register, and we have
already created release work for timeout. So, I don't think we need to
create work queue for each case.

What do you think?

> How much do we win, when we patch the thread command queue for every 
> task we add, instead of just taking one task after another from the 
> task_busy_list?

GCE is used to help read/write registers with critical time limitation.
Sometimes, client may ask to process multiple tasks in a short period
of time, e.g. display flush multiple tasks for next vblank. So, CMDQ
shouldn't limit to process one task after another from the
task_busy_list. Currently, when interrupt or timeout, we will check
how many tasks are done, and which one is error or timeout.

> > +	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
> > +	cmdq_handle_error_done(cmdq, thread, irq_flag);
> > +	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
> > +
> > +	if (task->task_state == TASK_STATE_DONE) {
> > +		cmdq_thread_resume(thread);
> > +		return 0;
> > +	}
> > +
> > +	if (task->task_state == TASK_STATE_ERROR) {
> > +		dev_err(dev, "task 0x%p error\n", task);
> > +		if (next_task) /* move to next task */
> > +			cmdq_thread_writel(thread, next_task->pa_base,
> > +					   CMDQ_THR_CURR_ADDR);
> > +		cmdq_thread_resume(thread);
> > +		return -ECANCELED;
> > +	}
> > +
> > +	/* Task is running, so we force to remove it. */
> > +	dev_err(dev, "task 0x%p timeout or killed\n", task);
> > +	task->task_state = TASK_STATE_ERROR;
> > +
> > +	if (prev_task) {
> > +		u64 *prev_va = prev_task->va_base;
> > +		u64 *curr_va = task->va_base;
> > +
> > +		/* copy JUMP instruction */
> > +		prev_va[prev_task->num_cmd - 1] = curr_va[task->num_cmd - 1];
> > +
> > +		cmdq_thread_invalidate_fetched_data(thread);
> > +	} else if (next_task) { /* move to next task */
> > +		cmdq_thread_writel(thread, next_task->pa_base,
> > +				   CMDQ_THR_CURR_ADDR);
> > +	}
> > +
> > +	list_del(&task->list_entry);
> > +	cmdq_thread_resume(thread);
> > +
> > +	/* call cb here to prevent lock */
> > +	if (task->cb.cb) {
> > +		struct cmdq_cb_data cmdq_cb_data;
> > +
> > +		cmdq_cb_data.err = true;
> > +		cmdq_cb_data.data = task->cb.data;
> > +		task->cb.cb(cmdq_cb_data);
> > +	}
> > +
> > +	return -ECANCELED;
> > +}
> > +
> > +static void cmdq_task_wait_release_work(struct work_struct *work_item)
> > +{
> > +	struct cmdq_task *task = container_of(work_item, struct cmdq_task,
> > +					      release_work);
> > +	struct cmdq *cmdq = task->cmdq;
> > +	struct cmdq_thread *thread = task->thread;
> > +	unsigned long flags;
> > +
> > +	wait_event_timeout(thread->wait_task_done,
> > +			   task->task_state != TASK_STATE_BUSY,
> > +			   msecs_to_jiffies(CMDQ_TIMEOUT_MS));
> > +
> > +	spin_lock_irqsave(&cmdq->exec_lock, flags);
> > +	if (task->task_state != TASK_STATE_DONE)
> > +		cmdq_task_handle_error_result(task);
> > +	if (list_empty(&thread->task_busy_list))
> > +		cmdq_thread_disable(cmdq, thread);
> > +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
> > +
> > +	/* release regardless of success or not */
> > +	clk_disable_unprepare(cmdq->clock);
> > +	cmdq_task_release(task);
> > +}
> > +
> > +static void cmdq_task_wait_release_schedule(struct cmdq_task *task)
> > +{
> > +	struct cmdq *cmdq = task->cmdq;
> > +
> > +	INIT_WORK(&task->release_work, cmdq_task_wait_release_work);
> > +	queue_work(cmdq->task_release_wq, &task->release_work);
> > +}
> > +
> > +static int cmdq_rec_realloc_cmd_buffer(struct cmdq_rec *rec, size_t size)
> > +{
> > +	void *new_buf;
> > +
> > +	new_buf = krealloc(rec->buf, size, GFP_KERNEL | __GFP_ZERO);
> > +	if (!new_buf)
> > +		return -ENOMEM;
> > +	rec->buf = new_buf;
> > +	rec->buf_size = size;
> > +	return 0;
> > +}
> > +
> > +struct cmdq_base *cmdq_register_device(struct device *dev)
> > +{
> > +	struct cmdq_base *cmdq_base;
> > +	struct resource res;
> > +	int subsys;
> > +	u32 base;
> > +
> > +	if (of_address_to_resource(dev->of_node, 0, &res))
> > +		return NULL;
> > +	base = (u32)res.start;
> > +
> > +	subsys = cmdq_subsys_base_to_id(base >> 16);
> > +	if (subsys < 0)
> > +		return NULL;
> > +
> > +	cmdq_base = devm_kmalloc(dev, sizeof(*cmdq_base), GFP_KERNEL);
> > +	if (!cmdq_base)
> > +		return NULL;
> > +	cmdq_base->subsys = subsys;
> > +	cmdq_base->base = base;
> > +
> > +	return cmdq_base;
> > +}
> > +EXPORT_SYMBOL(cmdq_register_device);
> > +
> > +int cmdq_rec_create(struct device *dev, u64 engine_flag,
> > +		    struct cmdq_rec **rec_ptr)
> > +{
> > +	struct cmdq_rec *rec;
> > +	int err;
> > +
> > +	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
> > +	if (!rec)
> > +		return -ENOMEM;
> > +	rec->cmdq = dev_get_drvdata(dev);
> > +	rec->engine_flag = engine_flag;
> > +	err = cmdq_rec_realloc_cmd_buffer(rec, CMDQ_INITIAL_CMD_BLOCK_SIZE);
> 
> Just pass PAGE_SIZE here, no need for CMDQ_INITIAL_CMD_BLOCK_SIZE.

Will do.

> > +	if (err < 0) {
> > +		kfree(rec);
> > +		return err;
> > +	}
> > +	*rec_ptr = rec;
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(cmdq_rec_create);
> > +
> > +static int cmdq_rec_append_command(struct cmdq_rec *rec, enum cmdq_code code,
> > +				   u32 arg_a, u32 arg_b)
> > +{
> > +	u64 *cmd_ptr;
> > +	int err;
> > +
> > +	if (WARN_ON(rec->finalized))
> > +		return -EBUSY;
> > +	if (code < CMDQ_CODE_MOVE || code > CMDQ_CODE_EOC)
> > +		return -EINVAL;
> 
> cmdq_rec_append_command is just called from inside this driver and code 
> is a enum. We can expect it to be correct, no need for this check.

Will drop this check.

> > +	if (unlikely(rec->command_size + CMDQ_INST_SIZE > rec->buf_size)) {
> 
> command_size is the offset into the buffer to which a new command is 
> written, so this name is highly confusing. I wonder if this would be 
> easier to understand if we redefine command_size to something like the 
> number of commands and divide/multiply CMDQ_INST_SIZE where this is needed.

I can rename command_size to cmd_buf_size and calculate num_cmd by
dividing CMDQ_INST_SIZE.
What do you think?

> > +		err = cmdq_rec_realloc_cmd_buffer(rec, rec->buf_size * 2);
> > +		if (err < 0)
> > +			return err;
> > +	}
> > +	cmd_ptr = rec->buf + rec->command_size;
> > +	(*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b;
> > +	rec->command_size += CMDQ_INST_SIZE;
> > +	return 0;
> > +}
> > +
> > +int cmdq_rec_write(struct cmdq_rec *rec, u32 value, struct cmdq_base *base,
> > +		   u32 offset)
> > +{
> > +	u32 arg_a = ((base->base + offset) & CMDQ_ARG_A_WRITE_MASK) |
> > +		    ((base->subsys & CMDQ_SUBSYS_MASK) << CMDQ_SUBSYS_SHIFT);
> 
> base->subsys is the id from gce_sybsys, so we can expect it to be 
> correct, no need to mask with CMDQ_SUBSYS_MASK.

Will drop it.

> > +	return cmdq_rec_append_command(rec, CMDQ_CODE_WRITE, arg_a, value);
> > +}
> > +EXPORT_SYMBOL(cmdq_rec_write);
> > +
> > +int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
> > +			struct cmdq_base *base, u32 offset, u32 mask)
> > +{
> > +	u32 offset_mask = offset;
> > +	int err;
> > +
> > +	if (mask != 0xffffffff) {
> > +		err = cmdq_rec_append_command(rec, CMDQ_CODE_MOVE, 0, ~mask);
> > +		if (err < 0)
> > +			return err;
> > +		offset_mask |= CMDQ_WRITE_ENABLE_MASK;
> > +	}
> > +	return cmdq_rec_write(rec, value, base, offset_mask);
> > +}
> > +EXPORT_SYMBOL(cmdq_rec_write_mask);
> > +
> > +int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event)
> > +{
> > +	u32 arg_b;
> > +
> > +	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
> > +		return -EINVAL;
> > +
> > +	/*
> > +	 * bit 0-11: wait value
> > +	 * bit 15: 1 - wait, 0 - no wait
> > +	 * bit 16-27: update value
> > +	 * bit 31: 1 - update, 0 - no update
> > +	 */
> 
> I don't understand this comments. What are they for?

This is for WFE command. I will comment it.

> > +	arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
> > +	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event, arg_b);
> > +}
> > +EXPORT_SYMBOL(cmdq_rec_wfe);
> > +
> > +int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event)
> > +{
> > +	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
> > +		return -EINVAL;
> > +
> > +	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event,
> > +				       CMDQ_WFE_UPDATE);
> > +}
> > +EXPORT_SYMBOL(cmdq_rec_clear_event);
> > +
> > +static int cmdq_rec_finalize(struct cmdq_rec *rec)
> > +{
> > +	int err;
> > +
> > +	if (rec->finalized)
> > +		return 0;
> > +
> > +	/* insert EOC and generate IRQ for each command iteration */
> > +	err = cmdq_rec_append_command(rec, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN);
> > +	if (err < 0)
> > +		return err;
> > +
> > +	/* JUMP to end */
> > +	err = cmdq_rec_append_command(rec, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS);
> > +	if (err < 0)
> > +		return err;
> > +
> 
> Does this need to be atomic?
> What happens if after CODE_EOC and before CODE_JUMP some 
> write/read/event gets added?
> What happens if more commands get added to the queue after CODE_JUMP, 
> but before finalized is set to true. Why don't you use atomic functions 
> to access finalized?

Since cmdq_rec doesn't guarantee thread safe, mutex is needed when
client uses cmdq_rec.

> > +	rec->finalized = true;
> > +	return 0;
> > +}
> > +
> > +int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
> > +			 void *data)
> > +{
> > +	struct cmdq *cmdq = rec->cmdq;
> > +	struct cmdq_task *task;
> > +	struct cmdq_task_cb task_cb;
> > +	struct cmdq_thread *thread;
> > +	int err;
> > +
> > +	mutex_lock(&cmdq->task_mutex);
> > +	if (cmdq->suspended) {
> > +		dev_err(cmdq->dev, "%s is called after suspended\n", __func__);
> > +		mutex_unlock(&cmdq->task_mutex);
> > +		return -EPERM;
> > +	}
> > +
> > +	err = cmdq_rec_finalize(rec);
> > +	if (err < 0) {
> > +		mutex_unlock(&cmdq->task_mutex);
> > +		return err;
> > +	}
> > +
> > +	task_cb.cb = cb;
> > +	task_cb.data = data;
> > +	task = cmdq_task_acquire(rec, task_cb);
> > +	if (!task) {
> > +		mutex_unlock(&cmdq->task_mutex);
> > +		return -EFAULT;
> > +	}
> > +
> > +	thread = &cmdq->thread[cmdq_eng_get_thread(task->engine_flag)];
> > +	cmdq_task_exec(task, thread);
> > +	cmdq_task_wait_release_schedule(task);
> > +	mutex_unlock(&cmdq->task_mutex);
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(cmdq_rec_flush_async);
> > +
> > +struct cmdq_flush_completion {
> > +	struct completion cmplt;
> > +	bool err;
> > +};
> > +
> > +static int cmdq_rec_flush_cb(struct cmdq_cb_data data)
> > +{
> > +	struct cmdq_flush_completion *cmplt = data.data;
> > +
> > +	cmplt->err = data.err;
> > +	complete(&cmplt->cmplt);
> > +	return 0;
> > +}
> > +
> > +int cmdq_rec_flush(struct cmdq_rec *rec)
> > +{
> > +	struct cmdq_flush_completion cmplt;
> > +	int err;
> > +
> > +	init_completion(&cmplt.cmplt);
> > +	err = cmdq_rec_flush_async(rec, cmdq_rec_flush_cb, &cmplt);
> > +	if (err < 0)
> > +		return err;
> > +	wait_for_completion(&cmplt.cmplt);
> > +	return cmplt.err ? -EFAULT : 0;
> > +}
> > +EXPORT_SYMBOL(cmdq_rec_flush);
> > +
> > +void cmdq_rec_destroy(struct cmdq_rec *rec)
> > +{
> > +	kfree(rec->buf);
> > +	kfree(rec);
> > +}
> > +EXPORT_SYMBOL(cmdq_rec_destroy);
> > +
> > +static bool cmdq_task_is_empty(struct cmdq *cmdq)
> > +{
> > +	struct cmdq_thread *thread;
> > +	int i;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
> > +		thread = &cmdq->thread[i];
> > +		if (!list_empty(&thread->task_busy_list))
> > +			return false;
> > +	}
> > +	return true;
> > +}
> > +
> > +static int cmdq_suspend(struct device *dev)
> > +{
> > +	struct cmdq *cmdq = dev_get_drvdata(dev);
> > +	u32 exec_threads;
> > +
> > +	mutex_lock(&cmdq->task_mutex);
> > +	cmdq->suspended = true;
> > +	mutex_unlock(&cmdq->task_mutex);
> > +
> > +	exec_threads = readl(cmdq->base + CMDQ_CURR_LOADED_THR);
> > +	if ((exec_threads & CMDQ_THR_EXECUTING) && !cmdq_task_is_empty(cmdq)) {
> > +		dev_err(dev, "wait active tasks timeout.\n");
> > +		flush_workqueue(cmdq->task_release_wq);
> > +	}
> > +	return 0;
> > +}
> > +
> > +static int cmdq_resume(struct device *dev)
> > +{
> > +	struct cmdq *cmdq = dev_get_drvdata(dev);
> > +
> > +	cmdq->suspended = false;
> > +	return 0;
> > +}
> > +
> > +static int cmdq_remove(struct platform_device *pdev)
> > +{
> > +	struct cmdq *cmdq = platform_get_drvdata(pdev);
> > +
> > +	destroy_workqueue(cmdq->task_release_wq);
> > +	cmdq->task_release_wq = NULL;
> > +	return 0;
> > +}
> > +
> > +static int cmdq_probe(struct platform_device *pdev)
> > +{
> > +	struct device *dev = &pdev->dev;
> > +	struct device_node *node = dev->of_node;
> > +	struct resource *res;
> > +	struct cmdq *cmdq;
> > +	int err, i;
> > +
> > +	cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
> > +	if (!cmdq)
> > +		return -ENOMEM;
> > +	cmdq->dev = dev;
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	cmdq->base = devm_ioremap_resource(dev, res);
> > +	if (IS_ERR(cmdq->base)) {
> > +		dev_err(dev, "failed to ioremap gce\n");
> > +		return PTR_ERR(cmdq->base);
> > +	}
> > +
> > +	cmdq->irq = irq_of_parse_and_map(node, 0);
> > +	if (!cmdq->irq) {
> > +		dev_err(dev, "failed to get irq\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
> > +		dev, cmdq->base, cmdq->irq);
> > +
> > +	mutex_init(&cmdq->task_mutex);
> > +	spin_lock_init(&cmdq->exec_lock);
> > +	cmdq->task_release_wq = alloc_ordered_workqueue(
> > +			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI,
> > +			"cmdq_task_wait_release");
> > +
> > +	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
> > +		cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
> > +				CMDQ_THR_SHIFT * i;
> > +		init_waitqueue_head(&cmdq->thread[i].wait_task_done);
> > +		INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list);
> > +	}
> > +
> > +	platform_set_drvdata(pdev, cmdq);
> > +
> > +	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
> > +			       CMDQ_DRIVER_DEVICE_NAME, cmdq);
> > +	if (err < 0) {
> > +		dev_err(dev, "failed to register ISR (%d)\n", err);
> > +		goto fail;
> > +	}
> > +
> > +	cmdq->clock = devm_clk_get(dev, CMDQ_CLK_NAME);
> > +	if (IS_ERR(cmdq->clock)) {
> > +		dev_err(dev, "failed to get clk:%s\n", CMDQ_CLK_NAME);
> > +		err = PTR_ERR(cmdq->clock);
> > +		goto fail;
> > +	}
> > +	return 0;
> > +
> > +fail:
> > +	cmdq_remove(pdev);
> > +	return err;
> > +}
> > +
> > +static const struct dev_pm_ops cmdq_pm_ops = {
> > +	.suspend = cmdq_suspend,
> > +	.resume = cmdq_resume,
> > +};
> > +
> > +static const struct of_device_id cmdq_of_ids[] = {
> > +	{.compatible = "mediatek,mt8173-gce",},
> > +	{}
> > +};
> > +
> > +static struct platform_driver cmdq_drv = {
> > +	.probe = cmdq_probe,
> > +	.remove = cmdq_remove,
> > +	.driver = {
> > +		.name = CMDQ_DRIVER_DEVICE_NAME,
> > +		.owner = THIS_MODULE,
> > +		.pm = &cmdq_pm_ops,
> > +		.of_match_table = cmdq_of_ids,
> > +	}
> > +};
> > +
> > +builtin_platform_driver(cmdq_drv);
> > diff --git a/include/soc/mediatek/cmdq.h b/include/soc/mediatek/cmdq.h
> > new file mode 100644
> > index 0000000..60eef3d
> > --- /dev/null
> > +++ b/include/soc/mediatek/cmdq.h
> > @@ -0,0 +1,197 @@
> > +/*
> > + * Copyright (c) 2015 MediaTek Inc.
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef __MTK_CMDQ_H__
> > +#define __MTK_CMDQ_H__
> > +
> > +#include <linux/platform_device.h>
> > +#include <linux/types.h>
> > +
> > +enum cmdq_eng {
> > +	CMDQ_ENG_DISP_AAL,
> > +	CMDQ_ENG_DISP_COLOR0,
> > +	CMDQ_ENG_DISP_COLOR1,
> > +	CMDQ_ENG_DISP_DPI0,
> > +	CMDQ_ENG_DISP_DSI0,
> > +	CMDQ_ENG_DISP_DSI1,
> > +	CMDQ_ENG_DISP_GAMMA,
> > +	CMDQ_ENG_DISP_OD,
> > +	CMDQ_ENG_DISP_OVL0,
> > +	CMDQ_ENG_DISP_OVL1,
> > +	CMDQ_ENG_DISP_PWM0,
> > +	CMDQ_ENG_DISP_PWM1,
> > +	CMDQ_ENG_DISP_RDMA0,
> > +	CMDQ_ENG_DISP_RDMA1,
> > +	CMDQ_ENG_DISP_RDMA2,
> > +	CMDQ_ENG_DISP_UFOE,
> > +	CMDQ_ENG_DISP_WDMA0,
> > +	CMDQ_ENG_DISP_WDMA1,
> > +	CMDQ_ENG_MAX,
> > +};
> > +
> > +/* events for CMDQ and display */
> > +enum cmdq_event {
> > +	/* Display start of frame(SOF) events */
> > +	CMDQ_EVENT_DISP_OVL0_SOF = 11,
> > +	CMDQ_EVENT_DISP_OVL1_SOF = 12,
> > +	CMDQ_EVENT_DISP_RDMA0_SOF = 13,
> > +	CMDQ_EVENT_DISP_RDMA1_SOF = 14,
> > +	CMDQ_EVENT_DISP_RDMA2_SOF = 15,
> > +	CMDQ_EVENT_DISP_WDMA0_SOF = 16,
> > +	CMDQ_EVENT_DISP_WDMA1_SOF = 17,
> > +	/* Display end of frame(EOF) events */
> > +	CMDQ_EVENT_DISP_OVL0_EOF = 39,
> > +	CMDQ_EVENT_DISP_OVL1_EOF = 40,
> > +	CMDQ_EVENT_DISP_RDMA0_EOF = 41,
> > +	CMDQ_EVENT_DISP_RDMA1_EOF = 42,
> > +	CMDQ_EVENT_DISP_RDMA2_EOF = 43,
> > +	CMDQ_EVENT_DISP_WDMA0_EOF = 44,
> > +	CMDQ_EVENT_DISP_WDMA1_EOF = 45,
> > +	/* Mutex end of frame(EOF) events */
> > +	CMDQ_EVENT_MUTEX0_STREAM_EOF = 53,
> > +	CMDQ_EVENT_MUTEX1_STREAM_EOF = 54,
> > +	CMDQ_EVENT_MUTEX2_STREAM_EOF = 55,
> > +	CMDQ_EVENT_MUTEX3_STREAM_EOF = 56,
> > +	CMDQ_EVENT_MUTEX4_STREAM_EOF = 57,
> > +	/* Display underrun events */
> > +	CMDQ_EVENT_DISP_RDMA0_UNDERRUN = 63,
> > +	CMDQ_EVENT_DISP_RDMA1_UNDERRUN = 64,
> > +	CMDQ_EVENT_DISP_RDMA2_UNDERRUN = 65,
> > +	/* Keep this at the end of HW events */
> > +	CMDQ_MAX_HW_EVENT_COUNT = 260,
> > +};
> > +
> > +struct cmdq_cb_data {
> > +	bool	err;
> > +	void	*data;
> > +};
> > +
> > +typedef int (*cmdq_async_flush_cb)(struct cmdq_cb_data data);
> > +
> > +struct cmdq_task;
> > +struct cmdq;
> > +
> > +struct cmdq_rec {
> > +	struct cmdq		*cmdq;
> > +	u64			engine_flag;
> > +	size_t			command_size;
> > +	void			*buf;
> > +	size_t			buf_size;
> > +	bool			finalized;
> > +};
> > +
> > +struct cmdq_base {
> > +	int	subsys;
> > +	u32	base;
> 
> subsys can always be calculated via cmdq_subsys_base_to_id(base >> 16) 
> so we can get rid of the struct, right?

Current subsys method is based on previous comment from Daniel Kurtz.
Please take a look of our previous discussion.
http://lists.infradead.org/pipermail/linux-mediatek/2016-February/004483.html
Thanks.

> > +};
> > +
> > +/**
> > + * cmdq_register_device() - register device which needs CMDQ
> > + * @dev:		device
> > + *
> > + * Return: cmdq_base pointer or NULL for failed
> > + */
> > +struct cmdq_base *cmdq_register_device(struct device *dev);
> > +
> > +/**
> > + * cmdq_rec_create() - create command queue record
> > + * @dev:		device
> > + * @engine_flag:	command queue engine flag
> > + * @rec_ptr:		command queue record pointer to retrieve cmdq_rec
> > + *
> > + * Return: 0 for success; else the error code is returned
> > + */
> > +int cmdq_rec_create(struct device *dev, u64 engine_flag,
> > +		    struct cmdq_rec **rec_ptr);
> > +
> > +/**
> > + * cmdq_rec_write() - append write command to the command queue record
> > + * @rec:	the command queue record
> > + * @value:	the specified target register value
> > + * @base:	the command queue base
> > + * @offset:	register offset from module base
> > + *
> > + * Return: 0 for success; else the error code is returned
> > + */
> > +int cmdq_rec_write(struct cmdq_rec *rec, u32 value,
> > +		   struct cmdq_base *base, u32 offset);
> > +
> > +/**
> > + * cmdq_rec_write_mask() - append write command with mask to the command
> > + *			   queue record
> > + * @rec:	the command queue record
> > + * @value:	the specified target register value
> > + * @base:	the command queue base
> > + * @offset:	register offset from module base
> > + * @mask:	the specified target register mask
> > + *
> > + * Return: 0 for success; else the error code is returned
> > + */
> > +int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
> > +			struct cmdq_base *base, u32 offset, u32 mask);
> > +
> > +/**
> > + * cmdq_rec_wfe() - append wait for event command to the command queue reco	rd
> 
> reco rd -> record

Will fix it.

> Regards,
> Matthias
> 
> > + * @rec:	the command queue record
> > + * @event:	the desired event type to "wait and CLEAR"
> > + *
> > + * Return: 0 for success; else the error code is returned
> > + */
> > +int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event);
> > +
> > +/**
> > + * cmdq_rec_clear_event() - append clear event command to the command queue
> > + *			    record
> > + * @rec:	the command queue record
> > + * @event:	the desired event to be cleared
> > + *
> > + * Return: 0 for success; else the error code is returned
> > + */
> > +int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event);
> > +
> > +/**
> > + * cmdq_rec_flush() - trigger CMDQ to execute the recorded commands
> > + * @rec:	the command queue record
> > + *
> > + * Return: 0 for success; else the error code is returned
> > + *
> > + * Trigger CMDQ to execute the recorded commands. Note that this is a
> > + * synchronous flush function. When the function returned, the recorded
> > + * commands have been done.
> > + */
> > +int cmdq_rec_flush(struct cmdq_rec *rec);
> > +
> > +/**
> > + * cmdq_rec_flush_async() - trigger CMDQ to asynchronously execute the recorded
> > + *			    commands and call back after ISR is finished
> > + * @rec:	the command queue record
> > + * @cb:		called in the end of CMDQ ISR
> > + * @data:	this data will pass back to cb
> > + *
> > + * Return: 0 for success; else the error code is returned
> > + *
> > + * Trigger CMDQ to asynchronously execute the recorded commands and call back
> > + * after ISR is finished. Note that this is an ASYNC function. When the function
> > + * returned, it may or may not be finished. The ISR callback function is called
> > + * in the end of ISR.
> > + */
> > +int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
> > +			 void *data);
> > +
> > +/**
> > + * cmdq_rec_destroy() - destroy command queue record
> > + * @rec:	the command queue record
> > + */
> > +void cmdq_rec_destroy(struct cmdq_rec *rec);
> > +
> > +#endif	/* __MTK_CMDQ_H__ */
> >

Thanks,
HS



From linus.walleij at linaro.org  Tue May 31 01:36:42 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 10:36:42 +0200
Subject: [PATCH v2 3/4] pinctrl: amlogic: gxbb: add more UART pins
In-Reply-To: <1464297865-8965-4-git-send-email-khilman@baylibre.com>
References: <1464297865-8965-1-git-send-email-khilman@baylibre.com>
 <1464297865-8965-4-git-send-email-khilman@baylibre.com>
Message-ID: <CACRpkdYX9+r51bD42z7kWvxuh4-4xWf1Uaqi7sy7vRsRpz5Nmg@mail.gmail.com>

On Thu, May 26, 2016 at 11:24 PM, Kevin Hilman <khilman at baylibre.com> wrote:

> Add EE domain pins for UART A, B & C.
>
> Acked-by: Carlo Caione <carlo at endlessm.com>
> Signed-off-by: Kevin Hilman <khilman at baylibre.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 01:37:33 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 10:37:33 +0200
Subject: [PATCH v2 4/4] pinctrl: amlogic: gxbb: add ethernet pins
In-Reply-To: <1464297865-8965-5-git-send-email-khilman@baylibre.com>
References: <1464297865-8965-1-git-send-email-khilman@baylibre.com>
 <1464297865-8965-5-git-send-email-khilman@baylibre.com>
Message-ID: <CACRpkdb=p4ALi7DqUu7o8iEZajUX0Nb8nfwp8_-c5CCJUV_pag@mail.gmail.com>

On Thu, May 26, 2016 at 11:24 PM, Kevin Hilman <khilman at baylibre.com> wrote:

> Add EE domain pins for ethernet interface.
>
> Acked-by: Carlo Caione <carlo at endlessm.com>
> Signed-off-by: Kevin Hilman <khilman at baylibre.com>

Patch applied.

Yours,
Linus Walleij


From moinejf at free.fr  Tue May 31 01:39:05 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Tue, 31 May 2016 10:39:05 +0200
Subject: [PATCH v2] clk: sunxi: predivider handling for factors clock
In-Reply-To: <20160530184532.GD4908@lukather>
References: <1461084466-20889-1-git-send-email-vishnupatekar0510@gmail.com>
 <1461084466-20889-2-git-send-email-vishnupatekar0510@gmail.com>
 <20160502111337.GR17159@lukather>
 <CAEzqOZvnKKNs_sXUJrwTykA5mzwKMg+HpaFcKgBTFr+utT4qQg@mail.gmail.com>
 <20160530184532.GD4908@lukather>
Message-ID: <20160531103905.faf5e2b80d60d46c8757ad1c@free.fr>

On Mon, 30 May 2016 20:45:32 +0200
Maxime Ripard <maxime.ripard at free-electrons.com> wrote:

> I went over all the A83T clocks, and most of them could be
> covered. The issue only lies in the PLLs and their additional 1-bit
> dividers.
> 
> If we just choos to ignore (one of) them, it should be pretty trivial
> to implement with the current clock classes we have.

Hi Maxime,

I already did the job for all the A83T clocks.
It is not fully tested yet, but, to be sure we are on the same way,
I am sending a RFC series.

-- 
Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
Jef		|		http://moinejf.free.fr/


From moinejf at free.fr  Tue May 31 00:47:45 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Tue, 31 May 2016 09:47:45 +0200
Subject: [PATCH RFC 0/2] clk: sunxi-ng: Add the A83T clocks
Message-ID: <cover.1464680865.git.moinejf@free.fr>

This patch series is a proposal to add the clocks of the sunxi A83T
in the "modern" clock framework proposed by Maxime Ripard.
It is currently being tested on a Banana Pi M3.

Jean-Francois Moine (2):
  clk: sunxi: Add the PLL clocks of the A83T and A80 SoCs
  clk: sunxi-ng: Add the A83T clocks

 drivers/clk/sunxi-ng/ccu-sun8i-a83t.c  | 755 +++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_ndmp.c        | 247 +++++++++++
 drivers/clk/sunxi-ng/ccu_ndmp.h        |  45 ++
 include/dt-bindings/clock/sun8i-a83t.h | 150 +++++++
 include/dt-bindings/reset/sun8i-a83t.h |  96 +++++
 5 files changed, 1293 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_ndmp.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_ndmp.h
 create mode 100644 include/dt-bindings/clock/sun8i-a83t.h
 create mode 100644 include/dt-bindings/reset/sun8i-a83t.h

-- 
2.8.3



From moinejf at free.fr  Tue May 31 00:32:41 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Tue, 31 May 2016 09:32:41 +0200
Subject: [PATCH RFC 2/2] clk: sunxi-ng: Add the A83T clocks
In-Reply-To: <cover.1464680865.git.moinejf@free.fr>
References: <cover.1464680865.git.moinejf@free.fr>
Message-ID: <8c3b58f5a6119c7f1114b35ad53151bb0a5f6c19.1464680865.git.moinejf@free.fr>

Add the clocks and resets found in the A83T CCU.

Signed-off-by: Jean-Francois Moine <moinejf at free.fr>
---
 drivers/clk/sunxi-ng/ccu-sun8i-a83t.c  | 755 +++++++++++++++++++++++++++++++++
 include/dt-bindings/clock/sun8i-a83t.h | 150 +++++++
 include/dt-bindings/reset/sun8i-a83t.h |  96 +++++
 3 files changed, 1001 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
 create mode 100644 include/dt-bindings/clock/sun8i-a83t.h
 create mode 100644 include/dt-bindings/reset/sun8i-a83t.h

diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
new file mode 100644
index 0000000..96178b5
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
@@ -0,0 +1,753 @@
+/*
+ * Copyright (c) 2016 Jean-Francois Moine <moinejf at free.fr>
+ * Based on the H3 version from
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/rational.h>
+
+#include <dt-bindings/clock/sun8i-a83t.h>
+#include <dt-bindings/reset/sun8i-a83t.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_factor.h"
+#include "ccu_fixed_factor.h"
+#include "ccu_gate.h"
+#include "ccu_m.h"
+#include "ccu_mp.h"
+#include "ccu_ndmp.h"
+#include "ccu_p.h"
+#include "ccu_phase.h"
+
+/* 2 * cpux */
+/*	rate = 24MHz * n */
+static struct ccu_ndmp pll_c0cpux_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(0),
+	.reg_lock	= 0x20c,
+
+	.n		= SUNXI_CLK_FACTOR(8, 7),
+
+	.common		= {
+		.reg		= 0x000,
+		.features	= CCU_FEATURE_N0,
+		.hw.init	= SUNXI_HW_INIT("pll-cpux",
+						"osc24M",
+						&ccu_ndmp_ops,
+						0),
+	},
+};
+
+static struct ccu_ndmp pll_c1cpux_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(1),
+	.reg_lock	= 0x20c,
+
+	.n		= SUNXI_CLK_FACTOR(8, 7),
+
+	.common		= {
+		.reg		= 0x004,
+		.features	= CCU_FEATURE_N0,
+		.hw.init	= SUNXI_HW_INIT("pll-cpux",
+						"osc24M",
+						&ccu_ndmp_ops,
+						0),
+	},
+};
+
+/* audio */
+/*	rate = 24MHz * n / (d1 + 1) / (d2 + 1) / (p + 1) */
+static struct ccu_ndmp pll_audio_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(2),
+	.reg_lock	= 0x20c,
+
+	.n		= SUNXI_CLK_FACTOR(8, 8),
+	.d1		= SUNXI_CLK_FACTOR(16, 1),
+	.d2		= SUNXI_CLK_FACTOR(18, 1),
+	.m		= SUNXI_CLK_FACTOR(0, 6),	/* (p) post div */
+
+	.common		= {
+		.reg		= 0x008,
+		.features	= CCU_FEATURE_N0,
+		.hw.init	= SUNXI_HW_INIT("pll-audio",
+						"osc24M",
+						&ccu_ndmp_ops,
+						0),
+	},
+};
+
+/* video 0 */
+/*	rate = 24MHz * n / (d1 + 1) >> p */
+static struct ccu_ndmp pll_video0_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(3),
+	.reg_lock	= 0x20c,
+
+	.n		= SUNXI_CLK_FACTOR(8, 7),
+	.d1		= SUNXI_CLK_FACTOR(16, 1),
+	.p		= SUNXI_CLK_FACTOR(0, 2),
+
+	.common		= {
+		.reg		= 0x010,
+		.features	= CCU_FEATURE_N0,
+		.hw.init	= SUNXI_HW_INIT("pll-video0",
+						"osc24M",
+						&ccu_ndmp_ops,
+						0),
+	},
+};
+
+/* video engine */
+/*	rate = 24MHz * n / (d1 + 1) / (d2 + 1) */
+static struct ccu_ndmp pll_ve_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(4),
+	.reg_lock	= 0x20c,
+
+	.n		= SUNXI_CLK_FACTOR(8, 8),
+	.d1		= SUNXI_CLK_FACTOR(16, 1),
+	.d2		= SUNXI_CLK_FACTOR(18, 1),
+
+	.common		= {
+		.reg		= 0x018,
+		.features	= CCU_FEATURE_N0,
+		.hw.init	= SUNXI_HW_INIT("pll-ve",
+						"osc24M",
+						&ccu_ndmp_ops,
+						0),
+	},
+};
+
+/* ddr */
+/*	rate = 24MHz * (n + 1) / (d1 + 1) / (d2 + 1)
+ *	bit 21: DDR_CLOCK = PLL_DDR / PLL_PERIPH (default DDR)
+ *	bit 22: to be set after rate is changed */
+static struct ccu_ndmp pll_ddr_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(5),
+	.reg_lock	= 0x20c,
+
+	.n		= SUNXI_CLK_FACTOR(8, 6),
+	.d1		= SUNXI_CLK_FACTOR(16, 1),
+	.d2		= SUNXI_CLK_FACTOR(18, 1),
+
+	.common		= {
+		.reg		= 0x020,
+		.hw.init	= SUNXI_HW_INIT("pll-ddr",
+						"osc24M",
+						&ccu_ndmp_ops,
+						0),
+	},
+};
+
+/* periph - must be 600MHz (n=25, d1=d2=0) */
+/*	rate = 24MHz * n / (d1 + 1) / (d2 + 1) */
+static struct ccu_ndmp pll_periph_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(6),
+	.reg_lock	= 0x20c,
+
+	.n		= SUNXI_CLK_FACTOR(8, 8),
+	.d1		= SUNXI_CLK_FACTOR(16, 1),
+	.d2		= SUNXI_CLK_FACTOR(18, 1),
+
+	.common		= {
+		.reg		= 0x028,
+		.features	= CCU_FEATURE_N0,
+		.hw.init	= SUNXI_HW_INIT("pll-periph",
+						"osc24M",
+						&ccu_ndmp_ops,
+						0),
+	},
+};
+
+/* gpu */
+/*	rate = 24MHz * n / (d1 + 1) / (d2 + 1) */
+static struct ccu_ndmp pll_gpu_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(7),
+	.reg_lock	= 0x20c,
+
+	.n		= SUNXI_CLK_FACTOR(8, 8),
+	.d1		= SUNXI_CLK_FACTOR(16, 1),
+	.d2		= SUNXI_CLK_FACTOR(18, 1),
+
+	.common		= {
+		.reg		= 0x038,
+		.features	= CCU_FEATURE_N0,
+		.hw.init	= SUNXI_HW_INIT("pll-gpu",
+						"osc24M",
+						&ccu_ndmp_ops,
+						0),
+	},
+};
+
+/* hsic */
+/*	rate = 24MHz * n / (d1 + 1) / (d2 + 1) */
+static struct ccu_ndmp pll_hsic_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(8),
+	.reg_lock	= 0x20c,
+
+	.n		= SUNXI_CLK_FACTOR(8, 7),
+	.d1		= SUNXI_CLK_FACTOR(16, 1),
+	.d2		= SUNXI_CLK_FACTOR(18, 1),
+
+	.common		= {
+		.reg		= 0x044,
+		.features	= CCU_FEATURE_N0,
+		.hw.init	= SUNXI_HW_INIT("pll-hsic",
+						"osc24M",
+						&ccu_ndmp_ops,
+						0),
+	},
+};
+
+/* display engine */
+/*	rate = 24MHz * n / (d1 + 1) / (d2 + 1) */
+static struct ccu_ndmp pll_de_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(9),
+	.reg_lock	= 0x20c,
+
+	.n		= SUNXI_CLK_FACTOR(8, 7),
+	.d1		= SUNXI_CLK_FACTOR(16, 1),
+	.d2		= SUNXI_CLK_FACTOR(18, 1),
+
+	.common		= {
+		.reg		= 0x048,
+		.features	= CCU_FEATURE_N0,
+		.hw.init	= SUNXI_HW_INIT("pll-de",
+						"osc24M",
+						&ccu_ndmp_ops,
+						0),
+	},
+};
+
+/* video 1 */
+/*	rate = 24MHz * n / (d1 + 1) >> p */
+static struct ccu_ndmp pll_video1_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(10),
+	.reg_lock	= 0x20c,
+
+	.n		= SUNXI_CLK_FACTOR(8, 7),
+	.d1		= SUNXI_CLK_FACTOR(16, 1),
+	.p		= SUNXI_CLK_FACTOR(0, 2),
+
+	.common		= {
+		.reg		= 0x04c,
+		.features	= CCU_FEATURE_N0,
+		.hw.init	= SUNXI_HW_INIT("pll-video1",
+						"osc24M",
+						&ccu_ndmp_ops,
+						0),
+	},
+};
+
+static const char * const c0cpux_parents[] = { "osc24M", "pll-c0cpux" };
+static SUNXI_CCU_MUX(c0cpux_clk, "c0cpux", c0cpux_parents,
+		     0x050, 12, 1, CLK_IS_CRITICAL);
+
+static SUNXI_CCU_M(axi0_clk, "axi0", "c0cpux", 0x050, 0, 2, 0);
+
+static const char * const c1cpux_parents[] = { "osc24M", "pll-c1cpux" };
+static SUNXI_CCU_MUX(c1cpux_clk, "c1cpux", c1cpux_parents,
+		     0x050, 28, 1, CLK_IS_CRITICAL);
+
+static SUNXI_CCU_M(axi1_clk, "axi1", "c1cpux", 0x050, 16, 2, 0);
+
+static const char * const ahb1_parents[] = { "osc32k", "osc24M", "pll-periph" };
+static struct ccu_p ahb1_clk = {
+	.p		= SUNXI_CLK_FACTOR(4, 2),
+
+	.mux		= {
+		.shift	= 12,
+		.width	= 2,
+
+		.variable_prediv	= {
+			.index	= 2,
+			.shift	= 6,
+			.width	= 2,
+		},
+	},
+
+	.common		= {
+		.reg		= 0x054,
+		.features	= CCU_FEATURE_VARIABLE_PREDIV,
+		.hw.init	= SUNXI_HW_INIT_PARENTS("ahb1",
+							ahb1_parents,
+							&ccu_p_ops,
+							0),
+	},
+};
+
+static SUNXI_CCU_M(apb1_clk, "apb1", "ahb1", 0x054, 8, 2, 0);
+
+static const char * const apb2_parents[] = { "osc32k", "osc24M",
+					     "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058,
+			     0, 5,	/* M */
+			     16, 2,	/* P */
+			     24, 2,	/* mux */
+			     0);
+
+static const char * const ahb2_parents[] = { "ahb1" , "pll-periph" };
+static struct ccu_mux ahb2_clk = {
+	.mux		= {
+		.shift	= 0,
+		.width	= 2,
+
+		.fixed_prediv	= {
+			.index	= 1,
+			.div	= 2,
+		},
+	},
+
+	.common		= {
+		.reg		= 0x05c,
+		.features	= CCU_FEATURE_FIXED_PREDIV,
+		.hw.init	= SUNXI_HW_INIT_PARENTS("ahb2",
+							ahb2_parents,
+							&ccu_mux_ops,
+							0),
+	},
+};
+
+static SUNXI_CCU_GATE(bus_mipidsi_clk,	"bus-mipidsi",	"ahb1",
+		      0x060, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_ss_clk,	"bus-ss",	"ahb1",
+		      0x060, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_dma_clk,	"bus-dma",	"ahb1",
+		      0x060, BIT(6), 0);
+static SUNXI_CCU_GATE(bus_mmc0_clk,	"bus-mmc0",	"ahb1",
+		      0x060, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_mmc1_clk,	"bus-mmc1",	"ahb1",
+		      0x060, BIT(9), 0);
+static SUNXI_CCU_GATE(bus_mmc2_clk,	"bus-mmc2",	"ahb1",
+		      0x060, BIT(10), 0);
+static SUNXI_CCU_GATE(bus_nand_clk,	"bus-nand",	"ahb1",
+		      0x060, BIT(13), 0);
+static SUNXI_CCU_GATE(bus_dram_clk,	"bus-dram",	"ahb1",
+		      0x060, BIT(14), 0);
+static SUNXI_CCU_GATE(bus_emac_clk,	"bus-emac",	"ahb2",
+		      0x060, BIT(17), 0);
+static SUNXI_CCU_GATE(bus_hstimer_clk,	"bus-hstimer",	"ahb1",
+		      0x060, BIT(19), 0);
+static SUNXI_CCU_GATE(bus_spi0_clk,	"bus-spi0",	"ahb1",
+		      0x060, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_spi1_clk,	"bus-spi1",	"ahb1",
+		      0x060, BIT(21), 0);
+static SUNXI_CCU_GATE(bus_usbdrd_clk,	"bus-usbdrd",	"ahb2",
+		      0x060, BIT(24), 0);
+static SUNXI_CCU_GATE(bus_ehci0_clk,	"bus-ehci0",	"ahb2",
+		      0x060, BIT(26), 0);
+static SUNXI_CCU_GATE(bus_ehci1_clk,	"bus-ehci1",	"ahb2",
+		      0x060, BIT(27), 0);
+static SUNXI_CCU_GATE(bus_ohci0_clk,	"bus-ohci0",	"ahb2",
+		      0x060, BIT(29), 0);
+
+static SUNXI_CCU_GATE(bus_ve_clk,	"bus-ve",	"ahb1",
+		      0x064, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_tcon0_clk,	"bus-tcon0",	"ahb1",
+		      0x064, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_tcon1_clk,	"bus-tcon1",	"ahb1",
+		      0x064, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_csi_clk,	"bus-csi",	"ahb1",
+		      0x064, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_hdmi_clk,	"bus-hdmi",	"ahb1",
+		      0x064, BIT(11), 0);
+static SUNXI_CCU_GATE(bus_de_clk,	"bus-de",	"ahb1",
+		      0x064, BIT(12), 0);
+static SUNXI_CCU_GATE(bus_gpu_clk,	"bus-gpu",	"ahb1",
+		      0x064, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_msgbox_clk,	"bus-msgbox",	"ahb1",
+		      0x064, BIT(21), 0);
+static SUNXI_CCU_GATE(bus_spinlock_clk,	"bus-spinlock",	"ahb1",
+		      0x064, BIT(22), 0);
+
+static SUNXI_CCU_GATE(bus_spdif_clk,	"bus-spdif",	"apb1",
+		      0x068, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_pio_clk,	"bus-pio",	"apb1",
+		      0x068, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_daudio0_clk,	"bus-daudio0",	"apb1",
+		      0x068, BIT(12), 0);
+static SUNXI_CCU_GATE(bus_daudio1_clk,	"bus-daudio1",	"apb1",
+		      0x068, BIT(13), 0);
+static SUNXI_CCU_GATE(bus_daudio2_clk,	"bus-daudio2",	"apb1",
+		      0x068, BIT(14), 0);
+static SUNXI_CCU_GATE(bus_tdm_clk,	"bus-tdm",	"apb1",
+		      0x068, BIT(15), 0);
+
+static SUNXI_CCU_GATE(bus_i2c0_clk,	"bus-i2c0",	"apb2",
+		      0x06c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c1_clk,	"bus-i2c1",	"apb2",
+		      0x06c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_i2c2_clk,	"bus-i2c2",	"apb2",
+		      0x06c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_uart0_clk,	"bus-uart0",	"apb2",
+		      0x06c, BIT(16), 0);
+static SUNXI_CCU_GATE(bus_uart1_clk,	"bus-uart1",	"apb2",
+		      0x06c, BIT(17), 0);
+static SUNXI_CCU_GATE(bus_uart2_clk,	"bus-uart2",	"apb2",
+		      0x06c, BIT(18), 0);
+static SUNXI_CCU_GATE(bus_uart3_clk,	"bus-uart3",	"apb2",
+		      0x06c, BIT(19), 0);
+static SUNXI_CCU_GATE(bus_uart4_clk,	"bus-uart4",	"apb2",
+		      0x06c, BIT(20), 0);
+
+static const char * const cci400_parents[] = { "ocs24M", "pll-periph",
+					"pll_hsic" };
+static SUNXI_CCU_M_WITH_MUX(cci400_clk, "cci400", cci400_parents,
+			    0x078, 0, 2, 24, 2, 0);
+
+static const char * const nand_parents[] = { "osc24M", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", nand_parents, 0x080,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const char * const mmc0_parents[] = { "osc24M", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_parents, 0x088,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0",
+		       0x088, 20, 3, 0);
+static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0",
+		       0x088, 8, 3, 0);
+
+static const char * const mmc1_parents[] = { "osc24M", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc1_parents, 0x08c,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1",
+		       0x08c, 20, 3, 0);
+static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1",
+		       0x08c, 8, 3, 0);
+
+static const char * const mmc2_parents[] = { "osc24M", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc2_parents, 0x090,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2_sample", "mmc2",
+		       0x090, 20, 3, 0);
+static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2_output", "mmc2",
+		       0x090, 8, 3, 0);
+
+static const char * const ss_parents[] = { "osc24M", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ss_clk, "ss", ss_parents, 0x09c,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const char * const spi0_parents[] = { "osc24M", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", spi0_parents, 0x0a0,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const char * const spi1_parents[] = { "osc24M", "pll-periph" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", spi1_parents, 0x0a4,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_M(daudio0_clk, "daudio0", "pll-audio",
+				0x0b0, 0, 4, 0);
+
+static SUNXI_CCU_M(daudio1_clk, "daudio1", "pll-audio",
+				0x0b4, 0, 4, 0);
+
+static SUNXI_CCU_M(daudio2_clk, "daudio2", "pll-audio",
+				0x0b8, 0, 4, 0);
+
+static SUNXI_CCU_M(tdm_clk, "tdm", "pll-audio",
+				0x0bc, 0, 4, 0);
+
+static SUNXI_CCU_M(spdif_clk, "spdif", "pll-audio",
+				0x0c0, 0, 4, 0);
+
+static SUNXI_CCU_GATE(usb_phy0_clk,	"usb-phy0",	"osc24M",
+		      0x0cc, BIT(8), 0);
+static SUNXI_CCU_GATE(usb_phy1_clk,	"usb-phy1",	"osc24M",
+		      0x0cc, BIT(9), 0);
+static SUNXI_CCU_GATE(hsic_clk,		"hsic",		"pll-hsic",
+		      0x0cc, BIT(10), 0);
+static SUNXI_CCU_GATE(osc12m_clk,	"osc12M",	"osc24M",
+		      0x0cc, BIT(11), 0);
+static SUNXI_CCU_GATE(ohci0_clk,	"ohci0",	"osc24M",
+		      0x0cc, BIT(16), 0);
+
+static SUNXI_CCU_M(dram_clk, "dram", "pll-ddr",
+			    0x0f4, 0, 4, 0);
+/* bit 16 SDRCLK_UPD (configuration update) */
+
+/* pll_ddr config not done */
+
+static SUNXI_CCU_GATE(dram_ve_clk,	"dram-ve",	"dram",
+		      0x100, BIT(0), 0);
+static SUNXI_CCU_GATE(dram_csi_clk,	"dram-csi",	"dram",
+		      0x100, BIT(1), 0);
+
+static SUNXI_CCU_GATE(tcon0_clk, "tcon0", "pll-video0",
+			     0x118, BIT(31), 0);
+
+static SUNXI_CCU_M_WITH_GATE(tcon1_clk, "tcon1", "pll-video1",
+			     0x11c, 0, 4, BIT(31), 0);
+
+static SUNXI_CCU_GATE(csi_misc_clk,	"csi-misc",	"osc24M",
+		      0x130, BIT(16), 0);
+
+static SUNXI_CCU_GATE(mipi_csi_clk,	"mipi-csi",	"osc24M",
+		      0x130, BIT(31), 0);
+
+static const char * const csi_sclk_parents[] = { "pll-periph",
+				NULL, NULL, NULL, NULL, "pll-ve" };
+static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents,
+				 0x134, 16, 4, 24, 3, BIT(31), 0);
+
+static const char * const csi_mclk_parents[] = { NULL, NULL, NULL, "pll-periph",
+				NULL, "osc24M"};
+static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents,
+				 0x134, 0, 5, 8, 3, BIT(15), 0);
+
+static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve",
+			     0x13c, 16, 3, BIT(31), 0);
+
+static SUNXI_CCU_GATE(avs_clk,		"avs",		"osc24M",
+		      0x144, BIT(31), 0);
+
+static SUNXI_CCU_M_WITH_GATE(hdmi_clk, "hdmi", "pll-video",
+			     0x150, 0, 4, BIT(31), 0);
+
+static SUNXI_CCU_GATE(hdmi_ddc_clk,	"hdmi-ddc",	"osc24M",
+		      0x154, BIT(31), 0);
+
+static const char * const mbus_parents[] = { "osc24M", "pll-periph", "pll-ddr" };
+static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
+				 0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL);
+
+static SUNXI_CCU_M_WITH_GATE(mipi_dsi0_clk, "mipi-dsi0", "pll-video0",
+			     0x168, 0, 4, BIT(31), 0);
+
+static const char * const mipi_dsi1_parents[] = { "osc24M",
+				NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+				NULL, "pll-video0" };
+static SUNXI_CCU_M_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1", mipi_dsi1_parents,
+				 0x16c, 0, 4, 24, 4, BIT(31), 0);
+
+static SUNXI_CCU_M_WITH_GATE(gpu_core_clk, "gpu-core", "pll-gpu",
+			     0x1a0, 0, 3, BIT(31), 0);
+
+static const char * const gpu_mem_parents[] = { "pll-gpu", "pll-periph" };
+static SUNXI_CCU_M_WITH_MUX_GATE(gpu_mem_clk, "gpu-mem", gpu_mem_parents,
+				 0x1a4, 0, 3, 24, 1, BIT(31), 0);
+
+static SUNXI_CCU_M_WITH_GATE(gpu_hyd_clk, "gpu-hyd", "pll-gpu",
+			     0x1a8, 0, 3, BIT(31), 0);
+
+static struct ccu_common *sun8i_a83t_ccu_clks[] = {
+	[CLK_PLL_C0CPUX]	= &pll_c0cpux_clk.common,
+	[CLK_PLL_C1CPUX]	= &pll_c1cpux_clk.common,
+	[CLK_PLL_AUDIO]		= &pll_audio_clk.common,
+	[CLK_PLL_VIDEO0]	= &pll_video0_clk.common,
+	[CLK_PLL_VE]		= &pll_ve_clk.common,
+	[CLK_PLL_DDR]		= &pll_ddr_clk.common,
+	[CLK_PLL_PERIPH]	= &pll_periph_clk.common,
+	[CLK_PLL_GPU]		= &pll_gpu_clk.common,
+	[CLK_PLL_HSIC]		= &pll_hsic_clk.common,
+	[CLK_PLL_DE]		= &pll_de_clk.common,
+	[CLK_PLL_VIDEO1]	= &pll_video1_clk.common,
+	[CLK_C0CPUX]		= &c0cpux_clk.common,
+	[CLK_AXI0]		= &axi0_clk.common,
+	[CLK_C1CPUX]		= &c1cpux_clk.common,
+	[CLK_AXI1]		= &axi1_clk.common,
+	[CLK_AHB1]		= &ahb1_clk.common,
+	[CLK_APB1]		= &apb1_clk.common,
+	[CLK_APB2]		= &apb2_clk.common,
+	[CLK_AHB2]		= &ahb2_clk.common,
+	[CLK_BUS_MIPIDSI]	= &bus_mipidsi_clk.common,
+	[CLK_BUS_SS]		= &bus_ss_clk.common,
+	[CLK_BUS_DMA]		= &bus_dma_clk.common,
+	[CLK_BUS_MMC0]		= &bus_mmc0_clk.common,
+	[CLK_BUS_MMC1]		= &bus_mmc1_clk.common,
+	[CLK_BUS_MMC2]		= &bus_mmc2_clk.common,
+	[CLK_BUS_NAND]		= &bus_nand_clk.common,
+	[CLK_BUS_DRAM]		= &bus_dram_clk.common,
+	[CLK_BUS_EMAC]		= &bus_emac_clk.common,
+	[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common,
+	[CLK_BUS_SPI0]		= &bus_spi0_clk.common,
+	[CLK_BUS_SPI1]		= &bus_spi1_clk.common,
+	[CLK_BUS_USBDRD]	= &bus_usbdrd_clk.common,
+	[CLK_BUS_EHCI0]		= &bus_ehci0_clk.common,
+	[CLK_BUS_EHCI1]		= &bus_ehci1_clk.common,
+	[CLK_BUS_OHCI0]		= &bus_ohci0_clk.common,
+	[CLK_BUS_VE]		= &bus_ve_clk.common,
+	[CLK_BUS_TCON0]		= &bus_tcon0_clk.common,
+	[CLK_BUS_TCON1]		= &bus_tcon1_clk.common,
+	[CLK_BUS_CSI]		= &bus_csi_clk.common,
+	[CLK_BUS_HDMI]		= &bus_hdmi_clk.common,
+	[CLK_BUS_DE]		= &bus_de_clk.common,
+	[CLK_BUS_GPU]		= &bus_gpu_clk.common,
+	[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common,
+	[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common,
+	[CLK_BUS_SPDIF]		= &bus_spdif_clk.common,
+	[CLK_BUS_PIO]		= &bus_pio_clk.common,
+	[CLK_BUS_DAUDIO0]	= &bus_daudio0_clk.common,
+	[CLK_BUS_DAUDIO1]	= &bus_daudio1_clk.common,
+	[CLK_BUS_DAUDIO2]	= &bus_daudio2_clk.common,
+	[CLK_BUS_TDM]		= &bus_tdm_clk.common,
+	[CLK_BUS_I2C0]		= &bus_i2c0_clk.common,
+	[CLK_BUS_I2C1]		= &bus_i2c1_clk.common,
+	[CLK_BUS_I2C2]		= &bus_i2c2_clk.common,
+	[CLK_BUS_UART0]		= &bus_uart0_clk.common,
+	[CLK_BUS_UART1]		= &bus_uart1_clk.common,
+	[CLK_BUS_UART2]		= &bus_uart2_clk.common,
+	[CLK_BUS_UART3]		= &bus_uart3_clk.common,
+	[CLK_BUS_UART4]		= &bus_uart4_clk.common,
+	[CLK_CCI400]		= &cci400_clk.common,
+	[CLK_NAND]		= &nand_clk.common,
+	[CLK_MMC0]		= &mmc0_clk.common,
+	[CLK_MMC0_SAMPLE]	= &mmc0_sample_clk.common,
+	[CLK_MMC0_OUTPUT]	= &mmc0_output_clk.common,
+	[CLK_MMC1]		= &mmc1_clk.common,
+	[CLK_MMC1_SAMPLE]	= &mmc1_sample_clk.common,
+	[CLK_MMC1_OUTPUT]	= &mmc1_output_clk.common,
+	[CLK_MMC2]		= &mmc2_clk.common,
+	[CLK_MMC2_SAMPLE]	= &mmc2_sample_clk.common,
+	[CLK_MMC2_OUTPUT]	= &mmc2_output_clk.common,
+	[CLK_SS]		= &ss_clk.common,
+	[CLK_SPI0]		= &spi0_clk.common,
+	[CLK_SPI1]		= &spi1_clk.common,
+	[CLK_DAUDIO0]		= &daudio0_clk.common,
+	[CLK_DAUDIO1]		= &daudio1_clk.common,
+	[CLK_DAUDIO2]		= &daudio2_clk.common,
+	[CLK_TDM]		= &tdm_clk.common,
+	[CLK_SPDIF]		= &spdif_clk.common,
+	[CLK_USB_PHY0]		= &usb_phy0_clk.common,
+	[CLK_USB_PHY1]		= &usb_phy1_clk.common,
+	[CLK_HSIC]		= &hsic_clk.common,
+	[CLK_OSC12M]		= &osc12m_clk.common,
+	[CLK_OHCI0]		= &ohci0_clk.common,
+	[CLK_DRAM]		= &dram_clk.common,
+	[CLK_DRAM_VE]		= &dram_ve_clk.common,
+	[CLK_DRAM_CSI]		= &dram_csi_clk.common,
+	[CLK_TCON0]		= &tcon0_clk.common,
+	[CLK_TCON1]		= &tcon1_clk.common,
+	[CLK_CSI_MISC]		= &csi_misc_clk.common,
+	[CLK_MIPI_CSI]		= &mipi_csi_clk.common,
+	[CLK_CSI_SCLK]		= &csi_sclk_clk.common,
+	[CLK_CSI_MCLK]		= &csi_mclk_clk.common,
+	[CLK_VE]		= &ve_clk.common,
+	[CLK_AVS]		= &avs_clk.common,
+	[CLK_HDMI]		= &hdmi_clk.common,
+	[CLK_HDMI_DDC]		= &hdmi_ddc_clk.common,
+	[CLK_MBUS]		= &mbus_clk.common,
+	[CLK_MIPI_DSI0]		= &mipi_dsi0_clk.common,
+	[CLK_MIPI_DSI1]		= &mipi_dsi1_clk.common,
+	[CLK_GPU_CORE]		= &gpu_core_clk.common,
+	[CLK_GPU_MEM]		= &gpu_mem_clk.common,
+	[CLK_GPU_HYD]		= &gpu_hyd_clk.common,
+};
+
+static struct ccu_reset_map sun8i_a83t_ccu_resets[] = {
+	[RST_USB_PHY0]		=  { 0x0cc, BIT(0) },
+	[RST_USB_PHY1]		=  { 0x0cc, BIT(1) },
+	[RST_USB_HSIC]		=  { 0x0cc, BIT(2) },
+
+	[RST_DRAM]		=  { 0x0f4, BIT(31) },
+	[RST_MBUS]		=  { 0x0fc, BIT(31) },
+
+	[RST_BUS_MIPIDSI]	=  { 0x2c0, BIT(1) },
+	[RST_BUS_CE]		=  { 0x2c0, BIT(5) },
+	[RST_BUS_DMA]		=  { 0x2c0, BIT(6) },
+	[RST_BUS_MMC0]		=  { 0x2c0, BIT(8) },
+	[RST_BUS_MMC1]		=  { 0x2c0, BIT(9) },
+	[RST_BUS_MMC2]		=  { 0x2c0, BIT(10) },
+	[RST_BUS_NAND]		=  { 0x2c0, BIT(13) },
+	[RST_BUS_DRAM]		=  { 0x2c0, BIT(14) },
+	[RST_BUS_EMAC]		=  { 0x2c0, BIT(17) },
+	[RST_BUS_HSTIMER]	=  { 0x2c0, BIT(19) },
+	[RST_BUS_SPI0]		=  { 0x2c0, BIT(20) },
+	[RST_BUS_SPI1]		=  { 0x2c0, BIT(21) },
+	[RST_BUS_USBDRD]	=  { 0x2c0, BIT(24) },
+	[RST_BUS_EHCI0]		=  { 0x2c0, BIT(26) },
+	[RST_BUS_EHCI1]		=  { 0x2c0, BIT(27) },
+	[RST_BUS_OHCI0]		=  { 0x2c0, BIT(29) },
+
+	[RST_BUS_VE]		=  { 0x2c4, BIT(0) },
+	[RST_BUS_TCON0]		=  { 0x2c4, BIT(4) },
+	[RST_BUS_TCON1]		=  { 0x2c4, BIT(5) },
+	[RST_BUS_CSI]		=  { 0x2c4, BIT(8) },
+	[RST_BUS_HDMI0]		=  { 0x2c4, BIT(10) },
+	[RST_BUS_HDMI1]		=  { 0x2c4, BIT(11) },
+	[RST_BUS_DE]		=  { 0x2c4, BIT(12) },
+	[RST_BUS_GPU]		=  { 0x2c4, BIT(20) },
+	[RST_BUS_MSGBOX]	=  { 0x2c4, BIT(21) },
+	[RST_BUS_SPINLOCK]	=  { 0x2c4, BIT(22) },
+
+	[RST_BUS_LVDS]		=  { 0x2c8, BIT(0) },
+
+	[RST_BUS_SPDIF]		=  { 0x2d0, BIT(1) },
+	[RST_BUS_DAUDIO0]	=  { 0x2d0, BIT(12) },
+	[RST_BUS_DAUDIO1]	=  { 0x2d0, BIT(13) },
+	[RST_BUS_DAUDIO2]	=  { 0x2d0, BIT(14) },
+	[RST_BUS_TDM]		=  { 0x2d0, BIT(15) },
+
+	[RST_BUS_I2C0]		=  { 0x2d8, BIT(0) },
+	[RST_BUS_I2C1]		=  { 0x2d8, BIT(1) },
+	[RST_BUS_I2C2]		=  { 0x2d8, BIT(2) },
+	[RST_BUS_UART0]		=  { 0x2d8, BIT(16) },
+	[RST_BUS_UART1]		=  { 0x2d8, BIT(17) },
+	[RST_BUS_UART2]		=  { 0x2d8, BIT(18) },
+	[RST_BUS_UART3]		=  { 0x2d8, BIT(19) },
+	[RST_BUS_UART4]		=  { 0x2d8, BIT(20) },
+};
+
+static const struct sunxi_ccu_desc sun8i_a83t_ccu_desc = {
+	.clks		= sun8i_a83t_ccu_clks,
+	.num_clks	= ARRAY_SIZE(sun8i_a83t_ccu_clks),
+
+	.resets		= sun8i_a83t_ccu_resets,
+	.num_resets	= ARRAY_SIZE(sun8i_a83t_ccu_resets),
+};
+
+static void __init sun8i_a83t_ccu_setup(struct device_node *node)
+{
+	sunxi_ccu_probe(node, &sun8i_a83t_ccu_desc);
+}
+CLK_OF_DECLARE(sun8i_a83t_ccu, "allwinner,sun8i-a83t-ccu",
+	       sun8i_a83t_ccu_setup);
diff --git a/include/dt-bindings/clock/sun8i-a83t.h b/include/dt-bindings/clock/sun8i-a83t.h
new file mode 100644
index 0000000..f194e89
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-a83t.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf at free.fr>
+ * Based on the H3 version from
+ * Copyright (C) 2016 Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN8I_A83T_H_
+#define _DT_BINDINGS_CLK_SUN8I_A83T_H_
+
+#define CLK_PLL_C0CPUX		0
+#define CLK_PLL_C1CPUX		1
+#define CLK_PLL_AUDIO		2
+#define CLK_PLL_VIDEO0		3
+#define CLK_PLL_VE		4
+#define CLK_PLL_DDR		5
+#define CLK_PLL_PERIPH		6
+#define CLK_PLL_GPU		7
+#define CLK_PLL_HSIC		8
+#define CLK_PLL_DE		9
+#define CLK_PLL_VIDEO1		10
+#define CLK_C0CPUX		11
+#define CLK_AXI0		12
+#define CLK_C1CPUX		13
+#define CLK_AXI1		14
+#define CLK_AHB1		15
+#define CLK_APB1		16
+#define CLK_APB2		17
+#define CLK_AHB2		18
+#define CLK_BUS_MIPIDSI		19
+#define CLK_BUS_SS		20
+#define CLK_BUS_DMA		21
+#define CLK_BUS_MMC0		22
+#define CLK_BUS_MMC1		23
+#define CLK_BUS_MMC2		24
+#define CLK_BUS_NAND		25
+#define CLK_BUS_DRAM		26
+#define CLK_BUS_EMAC		27
+#define CLK_BUS_HSTIMER		28
+#define CLK_BUS_SPI0		29
+#define CLK_BUS_SPI1		30
+#define CLK_BUS_USBDRD		31
+#define CLK_BUS_EHCI0		32
+#define CLK_BUS_EHCI1		33
+#define CLK_BUS_OHCI0		34
+#define CLK_BUS_VE		35
+#define CLK_BUS_TCON0		36
+#define CLK_BUS_TCON1		37
+#define CLK_BUS_CSI		38
+#define CLK_BUS_HDMI		39
+#define CLK_BUS_DE		40
+#define CLK_BUS_GPU		41
+#define CLK_BUS_MSGBOX		42
+#define CLK_BUS_SPINLOCK	43
+#define CLK_BUS_SPDIF		44
+#define CLK_BUS_PIO		45
+#define CLK_BUS_DAUDIO0		46
+#define CLK_BUS_DAUDIO1		47
+#define CLK_BUS_DAUDIO2		48
+#define CLK_BUS_TDM		49
+#define CLK_BUS_I2C0		50
+#define CLK_BUS_I2C1		51
+#define CLK_BUS_I2C2		52
+#define CLK_BUS_UART0		53
+#define CLK_BUS_UART1		54
+#define CLK_BUS_UART2		55
+#define CLK_BUS_UART3		56
+#define CLK_BUS_UART4		57
+#define CLK_CCI400		58
+#define CLK_NAND		59
+#define CLK_MMC0		60
+#define CLK_MMC0_SAMPLE		61
+#define CLK_MMC0_OUTPUT		62
+#define CLK_MMC1		63
+#define CLK_MMC1_SAMPLE		64
+#define CLK_MMC1_OUTPUT		65
+#define CLK_MMC2		66
+#define CLK_MMC2_SAMPLE		67
+#define CLK_MMC2_OUTPUT		68
+#define CLK_SS			69
+#define CLK_SPI0		70
+#define CLK_SPI1		71
+#define CLK_DAUDIO0		72
+#define CLK_DAUDIO1		73
+#define CLK_DAUDIO2		74
+#define CLK_TDM			75
+#define CLK_SPDIF		76
+#define CLK_USB_PHY0		77
+#define CLK_USB_PHY1		78
+#define CLK_HSIC		79
+#define CLK_OSC12M		80
+#define CLK_OHCI0		81
+#define CLK_DRAM		82
+#define CLK_DRAM_VE		83
+#define CLK_DRAM_CSI		84
+#define CLK_TCON0		85
+#define CLK_TCON1		86
+#define CLK_CSI_MISC		87
+#define CLK_MIPI_CSI		88
+#define CLK_CSI_SCLK		89
+#define CLK_CSI_MCLK		90
+#define CLK_VE			91
+#define CLK_AVS			92
+#define CLK_HDMI		93
+#define CLK_HDMI_DDC		94
+#define CLK_MBUS		95
+#define CLK_MIPI_DSI0		96
+#define CLK_MIPI_DSI1		97
+#define CLK_GPU_CORE		98
+#define CLK_GPU_MEM		99
+#define CLK_GPU_HYD		100
+
+#endif /* _DT_BINDINGS_CLK_SUN8I_A83T_H_ */
diff --git a/include/dt-bindings/reset/sun8i-a83t.h b/include/dt-bindings/reset/sun8i-a83t.h
new file mode 100644
index 0000000..86facc6
--- /dev/null
+++ b/include/dt-bindings/reset/sun8i-a83t.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016 Jean-Francois Moine <moinejf at free.fr>
+ * Based on the H3 version from
+ * Copyright (C) 2016 Maxime Ripard <maxime.ripard at free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN8I_A83T_H_
+#define _DT_BINDINGS_RST_SUN8I_A83T_H_
+
+#define RST_USB_PHY0		0
+#define RST_USB_PHY1		1
+#define RST_USB_HSIC		2
+
+#define RST_DRAM		3
+#define RST_MBUS		4
+
+#define RST_BUS_MIPIDSI		5
+#define RST_BUS_CE		6
+#define RST_BUS_DMA		7
+#define RST_BUS_MMC0		8
+#define RST_BUS_MMC1		9
+#define RST_BUS_MMC2		10
+#define RST_BUS_NAND		11
+#define RST_BUS_DRAM		12
+#define RST_BUS_EMAC		13
+#define RST_BUS_HSTIMER		14
+#define RST_BUS_SPI0		15
+#define RST_BUS_SPI1		16
+#define RST_BUS_USBDRD		17
+#define RST_BUS_EHCI0		18
+#define RST_BUS_EHCI1		19
+#define RST_BUS_OHCI0		20
+#define RST_BUS_VE		21
+#define RST_BUS_TCON0		22
+#define RST_BUS_TCON1		23
+#define RST_BUS_CSI		24
+#define RST_BUS_HDMI0		25
+#define RST_BUS_HDMI1		26
+#define RST_BUS_DE		27
+#define RST_BUS_GPU		28
+#define RST_BUS_MSGBOX		29
+#define RST_BUS_SPINLOCK	30
+#define RST_BUS_LVDS		31
+#define RST_BUS_SPDIF		32
+#define RST_BUS_DAUDIO0		33
+#define RST_BUS_DAUDIO1		34
+#define RST_BUS_DAUDIO2		35
+#define RST_BUS_TDM		36
+#define RST_BUS_I2C0		37
+#define RST_BUS_I2C1		38
+#define RST_BUS_I2C2		39
+#define RST_BUS_UART0		40
+#define RST_BUS_UART1		41
+#define RST_BUS_UART2		42
+#define RST_BUS_UART3		43
+#define RST_BUS_UART4		44
+
+#endif /* _DT_BINDINGS_RST_SUN8I_A83T_H_ */
-- 
2.8.3



From moinejf at free.fr  Tue May 31 00:26:38 2016
From: moinejf at free.fr (Jean-Francois Moine)
Date: Tue, 31 May 2016 09:26:38 +0200
Subject: [PATCH RFC 1/2] clk: sunxi-ng: Add the A83T and A80 PLL clocks
In-Reply-To: <cover.1464680865.git.moinejf@free.fr>
References: <cover.1464680865.git.moinejf@free.fr>
Message-ID: <bbf3cefa47323660ead5ebdafe63f382fea06f39.1464680865.git.moinejf@free.fr>

The A83T and A80 SoCs have unique settings of their PLL clocks.

Signed-off-by: Jean-Francois Moine <moinejf at free.fr>
---
 drivers/clk/sunxi-ng/ccu_ndmp.c | 247 ++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_ndmp.h |  45 ++++++++
 2 files changed, 292 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu_ndmp.c
 create mode 100644 drivers/clk/sunxi-ng/ccu_ndmp.h

diff --git a/drivers/clk/sunxi-ng/ccu_ndmp.c b/drivers/clk/sunxi-ng/ccu_ndmp.c
new file mode 100644
index 0000000..079b155
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_ndmp.c
@@ -0,0 +1,247 @@
+/*
+ * PLL clocks of sun8iw6 (A83T) and sun9iw1 (A80)
+ *
+ * Copyright (c) 2016 Jean-Francois Moine <moinejf at free.fr>
+ *
+ * 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.
+ *
+ * The clock rates are computed as:
+ *	rate = parent_rate / d1 * n / d2 / m >> p
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/rational.h>
+#include <linux/iopoll.h>
+
+#include "ccu_gate.h"
+#include "ccu_ndmp.h"
+
+static void ccu_ndmp_disable(struct clk_hw *hw)
+{
+	struct ccu_ndmp *ndmp = hw_to_ccu_ndmp(hw);
+
+	return ccu_gate_helper_disable(&ndmp->common, ndmp->enable);
+}
+
+static int ccu_ndmp_enable(struct clk_hw *hw)
+{
+	struct ccu_ndmp *ndmp = hw_to_ccu_ndmp(hw);
+
+	return ccu_gate_helper_enable(&ndmp->common, ndmp->enable);
+}
+
+static int ccu_ndmp_is_enabled(struct clk_hw *hw)
+{
+	struct ccu_ndmp *ndmp = hw_to_ccu_ndmp(hw);
+
+	return ccu_gate_helper_is_enabled(&ndmp->common, ndmp->enable);
+}
+
+static unsigned long ccu_ndmp_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct ccu_ndmp *ndmp = hw_to_ccu_ndmp(hw);
+	int n, d1, d2, m, p;
+	unsigned long rate;
+	u32 reg;
+
+	reg = readl(ndmp->common.base + ndmp->common.reg);
+
+	rate = parent_rate;
+
+	if (ndmp->d1.shift) {
+		d1 = reg >> ndmp->d1.shift;
+		d1 &= (1 << ndmp->d1.width) - 1;
+		rate /= (d1 + 1);
+	}
+
+	n = reg >> ndmp->n.shift;
+	n &= (1 << ndmp->n.width) - 1;
+	if (!(ndmp->common.features & CCU_FEATURE_N0))
+		n++;
+	rate *= n;
+
+	if (ndmp->d2.shift) {
+		d2 = reg >> ndmp->d2.shift;
+		d2 &= (1 << ndmp->d2.width) - 1;
+		rate /= (d2 + 1);
+	}
+
+	if (ndmp->m.shift) {
+		m = reg >> ndmp->m.shift;
+		m &= (1 << ndmp->m.width) - 1;
+		rate /= (m + 1);
+	}
+
+	if (ndmp->p.shift) {
+		p = reg >> ndmp->p.shift;
+		p &= (1 << ndmp->p.width) - 1;
+		rate >>= p;
+	}
+
+	return rate;
+}
+
+/* d1 and d2 may be only 1 or 2 */
+static int ccu_ndmp_get_fact(struct ccu_ndmp *ndmp,
+			unsigned long rate, unsigned long prate,
+			int *p_n, int *p_d1, int *p_d2, int *p_m, int *p_p)
+{
+	int n, d1, d2, m, p, d;
+	unsigned long t;
+
+	/* m implies only n, d1, d2 and m (pll-audio) */
+	/* Setting d1=1 and d2=2 keeps n and m small enough
+	 *	with error < 5/10000 */
+	/* As only 2 rates are used, this could be simplified:
+	 *	22579200Hz => n = 32, m = 17
+	 *	24576000Hz => n = 43, m = 21
+	 */
+	if (ndmp->m.shift) {
+		long unsigned int lun, lum;
+
+		d1 = 0 + 1;
+		d2 = 1 + 1;
+		t = prate / 2;
+		rational_best_approximation(rate, t,
+					1 << ndmp->n.width,
+					1 << ndmp->m.width,
+					&lun, &lum);
+		if (lum == 0)
+			return -EINVAL;
+		n = lun;
+		m = lum;
+		p = 0;
+
+	/* no d1 implies n alone (pll-cxcpux) */
+	} else if (!ndmp->d1.shift) {
+		d1 = d2 = 0 + 1;
+		n = rate / prate;
+		m = 1;
+		p = 0;
+
+	/* p implies only n, d1 and p (pll-videox) */
+	} else if (ndmp->m.shift) {
+		d2 = 0 + 1;
+		d = 2 + ndmp->p.width;
+		n = rate / (prate / (1 << d));
+		if (n < 12) {
+			n *= 2;
+			d++;
+		}
+		while (n >= 12 * 2 && !(n & 1)) {
+			n /= 2;
+			if (--d == 0)
+				break;
+		}
+		if (d <= 1) {
+			d1 = d + 1;
+			p = 0;
+		} else {
+			d1 = 1 + 1;
+			p = d - 1;
+		}
+		m = 1;
+
+	/* only n, d1 and d2 (other plls) */
+	} else {
+		t = prate / 4;
+		n = rate / t;
+		if (n < 12) {
+			n *= 4;
+			d1 = d2 = 0 + 1;
+		} else if (n >= 12 * 2 && !(n & 1)) {
+			if (n >= 12 * 4 && !(n % 4)) {
+				n /= 4;
+				d1 = d2 = 0 + 1;
+			} else {
+				n /= 2;
+				d1 = 0 + 1;
+				d2 = 1 + 1;
+			}
+		} else {
+			d1 = d2 = 1 + 1;
+		}
+		if (n > (1 << ndmp->n.width))
+			return -EINVAL;
+		m = 1;
+		p = 0;
+	}
+
+	if (n < 12 || n > (1 << ndmp->n.width))
+		return -EINVAL;
+
+	*p_n = n;
+	*p_d1 = d1;
+	*p_d2 = d2;
+	*p_m = m;
+	*p_p = p;
+
+	return 0;
+}
+
+static long ccu_ndmp_round_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long *parent_rate)
+{
+	struct ccu_ndmp *ndmp = hw_to_ccu_ndmp(hw);
+	int n, d1, d2, m, p, ret;
+
+	ret = ccu_ndmp_get_fact(ndmp, rate, *parent_rate,
+				&n, &d1, &d2, &m, &p);
+	if (!ret)
+		return 0;
+
+	return *parent_rate / d1 * n / d2 / m >> p;
+}
+
+static int ccu_ndmp_set_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long parent_rate)
+{
+	struct ccu_ndmp *ndmp = hw_to_ccu_ndmp(hw);
+	unsigned long flags;
+	int n, d1, d2, m, p, ret;
+	u32 reg;
+
+	ret = ccu_ndmp_get_fact(ndmp, rate, parent_rate,
+				&n, &d1, &d2, &m, &p);
+	if (!ret)
+		return ret;
+	if (!(ndmp->common.features & CCU_FEATURE_N0))
+		n--;
+
+	spin_lock_irqsave(ndmp->common.lock, flags);
+
+	reg = readl(ndmp->common.base + ndmp->common.reg) &
+		~((((1 << ndmp->n.width) - 1) << ndmp->n.shift) |
+		  (((1 << ndmp->d1.width) - 1) << ndmp->d1.shift) |
+		  (((1 << ndmp->d2.width) - 1) << ndmp->d2.shift) |
+		  (((1 << ndmp->m.width) - 1) << ndmp->m.shift) |
+		  (((1 << ndmp->p.width) - 1) << ndmp->p.shift));
+
+	writel(reg | (n << ndmp->n.shift) |
+			((d1 - 1) << ndmp->d1.shift) |
+			((d2 - 1) << ndmp->d2.shift) |
+			((m - 1) << ndmp->m.shift) |
+			(p << ndmp->p.shift),
+	       ndmp->common.base + ndmp->common.reg);
+
+	spin_unlock_irqrestore(ndmp->common.lock, flags);
+
+	WARN_ON(readl_relaxed_poll_timeout(ndmp->common.base + ndmp->reg_lock,
+					   reg, !(reg & ndmp->lock), 50, 500));
+
+	return 0;
+}
+
+const struct clk_ops ccu_ndmp_ops = {
+	.disable	= ccu_ndmp_disable,
+	.enable		= ccu_ndmp_enable,
+	.is_enabled	= ccu_ndmp_is_enabled,
+
+	.recalc_rate	= ccu_ndmp_recalc_rate,
+	.round_rate	= ccu_ndmp_round_rate,
+	.set_rate	= ccu_ndmp_set_rate,
+};
diff --git a/drivers/clk/sunxi-ng/ccu_ndmp.h b/drivers/clk/sunxi-ng/ccu_ndmp.h
new file mode 100644
index 0000000..bb47127
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu_ndmp.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016 Jean-Francois Moine <moinejf at free.fr>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_NDMP_H_
+#define _CCU_NDMP_H_
+
+#include <linux/clk-provider.h>
+
+#include "ccu_factor.h"
+#include "ccu_common.h"
+
+struct ccu_ndmp {
+	u32			enable;
+	u32			lock;
+	int			reg_lock;
+
+	struct ccu_factor	n;
+	struct ccu_factor	d1;
+	struct ccu_factor	d2;
+	struct ccu_factor	m;
+	struct ccu_factor	p;
+
+	struct ccu_common	common;
+};
+
+static inline struct ccu_ndmp *hw_to_ccu_ndmp(struct clk_hw *hw)
+{
+	struct ccu_common *common = hw_to_ccu_common(hw);
+
+	return container_of(common, struct ccu_ndmp, common);
+}
+
+extern const struct clk_ops ccu_ndmp_ops;
+
+#endif /* _CCU_NDMP_H_ */
-- 
2.8.3



From linus.walleij at linaro.org  Tue May 31 01:48:53 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 10:48:53 +0200
Subject: interrupts properties and API usage with GPIO controllers/Device
 Tree
In-Reply-To: <57461CDC.603@gmail.com>
References: <57461CDC.603@gmail.com>
Message-ID: <CACRpkdbys9JDCdwxpFuYFd_c=i2KaoTTf0WWX+J4qbiubSJNWA@mail.gmail.com>

On Wed, May 25, 2016 at 11:45 PM, Florian Fainelli <f.fainelli at gmail.com> wrote:

> - is this a valid API and Device Tree use case: call
> of_irq_parse_and_map on an "interrupts" property which has not been
> acquired using the GPIO API and then gpio_to_irq?

Yes. See Documentation/gpio/driver.txt:

-------

It is legal for any IRQ consumer to request an IRQ from any irqchip no matter
if that is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and
irq_chip are orthogonal, and offering their services independent of each
other.

gpiod_to_irq() is just a convenience function to figure out the IRQ for a
certain GPIO line and should not be relied upon to have been called before
the IRQ is used.

So always prepare the hardware and make it ready for action in respective
callbacks from the GPIO and irqchip APIs. Do not rely on gpiod_to_irq() having
been called first.

This orthogonality leads to ambiguities that we need to solve: if there is
competition inside the subsystem which side is using the resource (a certain
GPIO line and register for example) it needs to deny certain operations and
keep track of usage inside of the gpiolib subsystem. This is why the API
below exists.

-----

> While gpio_to_irq()
> works, are not we losing the second specifier in the interrupt cells
> about what kind of interrupt type this is?

Yeah and .set_type() needs to work. See other drivers for inspiration...

> - would it be acceptable to export gpiochip_irq_map and
> gpiochip_irq_export to make them accessible as helpers so we could just
> wrap things a bit around or should I just open code the same things and
> allow gpiochip_irqchip_add to be passed custom irq_domain_ops for instance?

Rather than poke around in gpiolib internals, make a separate
implementation for corner cases unless you can make it really
clean and nice for all consumers.

Yours,
Linus Walleij


From matthias.bgg at gmail.com  Tue May 31 01:49:11 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Tue, 31 May 2016 10:49:11 +0200
Subject: [PATCH 03/54] MAINTAINERS: Add file patterns for mediatek device
 tree bindings
In-Reply-To: <1463907991-7916-4-git-send-email-geert@linux-m68k.org>
References: <1463907991-7916-1-git-send-email-geert@linux-m68k.org>
 <1463907991-7916-4-git-send-email-geert@linux-m68k.org>
Message-ID: <574D5007.6070003@gmail.com>



On 22/05/16 11:05, Geert Uytterhoeven wrote:
> Submitters of device tree binding documentation may forget to CC
> the subsystem maintainer if this is missing.
>
> Signed-off-by: Geert Uytterhoeven <geert at linux-m68k.org>
> Cc: Matthias Brugger <matthias.bgg at gmail.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-mediatek at lists.infradead.org
> ---

Reviewed-by: Matthias Brugger <matthias.bgg at gmail.com

> Please apply this patch directly if you want to be involved in device
> tree binding documentation for your subsystem.
> ---
>   MAINTAINERS | 1 +
>   1 file changed, 1 insertion(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e1bf10e4ad021483..80d97eebcccec449 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1424,6 +1424,7 @@ M:	Matthias Brugger <matthias.bgg at gmail.com>
>   L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
>   L:	linux-mediatek at lists.infradead.org (moderated for non-subscribers)
>   S:	Maintained
> +F:	Documentation/devicetree/bindings/soc/mediatek/
>   F:	arch/arm/boot/dts/mt6*
>   F:	arch/arm/boot/dts/mt8*
>   F:	arch/arm/mach-mediatek/
>


From linus.walleij at linaro.org  Tue May 31 01:49:55 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 10:49:55 +0200
Subject: interrupts properties and API usage with GPIO controllers/Device
 Tree
In-Reply-To: <57485844.3050807@ti.com>
References: <57461CDC.603@gmail.com>
	<57485844.3050807@ti.com>
Message-ID: <CACRpkdYULz6fgw8N_yLCGYzqV7DjeJGmh1b0e9coxpGqSgZf+A@mail.gmail.com>

On Fri, May 27, 2016 at 4:23 PM, Grygorii Strashko
<grygorii.strashko at ti.com> wrote:

> Another interesting, related question (as for me) is "Is there a limitation
>  that gpio bank can have only 32 GPIO pins (from gpiolib point of view)?"

Do you mean for this driver or in general?

The gpio MMIO driver has this limitation, but not the subsystem
and gpiolib as far as I know.

Yours,
Linus Walleij


From arnaud.pouliquen at st.com  Tue May 31 01:55:20 2016
From: arnaud.pouliquen at st.com (Arnaud Pouliquen)
Date: Tue, 31 May 2016 10:55:20 +0200
Subject: [PATCH v4 11/18] ARM: multi_v7_defconfig: Enable STi and
 simple-card drivers.
In-Reply-To: <1464192412-16386-13-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
 <1464192412-16386-13-git-send-email-peter.griffin@linaro.org>
Message-ID: <574D5178.5030200@st.com>

Hi Peter,

On 05/25/2016 06:06 PM, Peter Griffin wrote:
> This patch enables the STi ALSA drivers found on STi platforms
> as well as the simple-card driver which is a dependency to have
> working sound.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> Cc: arnaud.pouliquen at st.com
> Cc: broonie at kernel.org
> ---
>  arch/arm/configs/multi_v7_defconfig | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> index 5eee45b..0ced665 100644
> --- a/arch/arm/configs/multi_v7_defconfig
> +++ b/arch/arm/configs/multi_v7_defconfig
> @@ -589,6 +589,9 @@ CONFIG_SND_SOC_AK4642=m
>  CONFIG_SND_SOC_SGTL5000=m
>  CONFIG_SND_SOC_SPDIF=m
>  CONFIG_SND_SOC_WM8978=m
> +CONFIG_SND_SOC_STI=m
> +CONFIG_SND_SOC_STI_SAS=m
> +CONFIG_SND_SIMPLE_CARD=m
Simple card config seems enabled by default, at least on 4.7 rc1.

Regards,
Arnaud
>  CONFIG_USB=y
>  CONFIG_USB_XHCI_HCD=y
>  CONFIG_USB_XHCI_MVEBU=y
> 


From linus.walleij at linaro.org  Tue May 31 01:56:46 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 10:56:46 +0200
Subject: [PATCH] pinctrl: uniphier: fix .pin_dbg_show() callback
In-Reply-To: <1464676210-16508-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464676210-16508-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdbwD5Kb+HG+T2Geo4fN272CD2iAgDH4qSkgo8HgA4U3SQ@mail.gmail.com>

On Tue, May 31, 2016 at 8:30 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> Without this, reading the "pins" in the debugfs causes kernel BUG.
>
> Fixes: 6e9088920258 ("pinctrl: UniPhier: add UniPhier pinctrl core support")
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From maxime.ripard at free-electrons.com  Tue May 31 01:59:15 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Tue, 31 May 2016 10:59:15 +0200
Subject: [PATCH v2] clk: sunxi: predivider handling for factors clock
In-Reply-To: <20160531103905.faf5e2b80d60d46c8757ad1c@free.fr>
References: <1461084466-20889-1-git-send-email-vishnupatekar0510@gmail.com>
 <1461084466-20889-2-git-send-email-vishnupatekar0510@gmail.com>
 <20160502111337.GR17159@lukather>
 <CAEzqOZvnKKNs_sXUJrwTykA5mzwKMg+HpaFcKgBTFr+utT4qQg@mail.gmail.com>
 <20160530184532.GD4908@lukather>
 <20160531103905.faf5e2b80d60d46c8757ad1c@free.fr>
Message-ID: <20160531085915.GK4908@lukather>

On Tue, May 31, 2016 at 10:39:05AM +0200, Jean-Francois Moine wrote:
> On Mon, 30 May 2016 20:45:32 +0200
> Maxime Ripard <maxime.ripard at free-electrons.com> wrote:
> 
> > I went over all the A83T clocks, and most of them could be
> > covered. The issue only lies in the PLLs and their additional 1-bit
> > dividers.
> > 
> > If we just choos to ignore (one of) them, it should be pretty trivial
> > to implement with the current clock classes we have.
> 
> Hi Maxime,
> 
> I already did the job for all the A83T clocks.
> It is not fully tested yet, but, to be sure we are on the same way,
> I am sending a RFC series.

Awesome, thanks!

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160531/72963101/attachment.sig>

From arnaud.pouliquen at st.com  Tue May 31 02:05:43 2016
From: arnaud.pouliquen at st.com (Arnaud Pouliquen)
Date: Tue, 31 May 2016 11:05:43 +0200
Subject: [PATCH v4 15/18] ARM: STi: DT: STiH407: Add sti-sasg-codec dt node
In-Reply-To: <1464192412-16386-17-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
 <1464192412-16386-17-git-send-email-peter.griffin@linaro.org>
Message-ID: <574D53E7.40008@st.com>



On 05/25/2016 06:06 PM, Peter Griffin wrote:
> This patch adds the dt node for the internal audio
> codec IP.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
>  arch/arm/boot/dts/stih407-family.dtsi | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
> index b423836..60f95b6 100644
> --- a/arch/arm/boot/dts/stih407-family.dtsi
> +++ b/arch/arm/boot/dts/stih407-family.dtsi
> @@ -746,5 +746,14 @@
>  				<&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
>  				<&clk_s_c0_flexgen CLK_EXT2F_A9>;
>  		};
> +
> +		sti_sasg_codec: sti-sasg-codec {
> +			compatible = "st,stih407-sas-codec";
> +			#sound-dai-cells = <1>;
> +			status = "okay";
Should be set to disable in family and enabled it depending on boards
(stihxxx-b2120.dtsi)
> +			st,syscfg = <&syscfg_core>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&pinctrl_spdif_out >;
Declare pinctrl use in stihxxx-b2120.dtsi, should be set only if SPDIF used.

Regards
Arnaud
> +		};
>  	};
>  };
> 


From mbrugger at suse.com  Tue May 31 02:07:06 2016
From: mbrugger at suse.com (Matthias Brugger)
Date: Tue, 31 May 2016 11:07:06 +0200
Subject: [PATCH v2 5/5] arm64/numa: avoid inconsistent information to be
 printed
In-Reply-To: <1464427377-12712-6-git-send-email-thunder.leizhen@huawei.com>
References: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
 <1464427377-12712-6-git-send-email-thunder.leizhen@huawei.com>
Message-ID: <574D543A.2090406@suse.com>



On 28/05/16 11:22, Zhen Lei wrote:
> numa_init(of_numa_init) may returned error because of numa configuration
> error. So "No NUMA configuration found" is inaccurate. In fact, specific
> configuration error information should be immediately printed by the
> testing branch.
>
> Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
> ---

Which kernel version is this patch based on?

Regards,
Matthias

>   arch/arm64/mm/numa.c | 6 +++---
>   drivers/of/of_numa.c | 7 +++----
>   2 files changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
> index 2601660..1b9622c 100644
> --- a/arch/arm64/mm/numa.c
> +++ b/arch/arm64/mm/numa.c
> @@ -338,8 +338,10 @@ static int __init numa_init(int (*init_func)(void))
>   	if (ret < 0)
>   		return ret;
>
> -	if (nodes_empty(numa_nodes_parsed))
> +	if (nodes_empty(numa_nodes_parsed)) {
> +		pr_info("No NUMA configuration found\n");
>   		return -EINVAL;
> +	}
>
>   	ret = numa_register_nodes();
>   	if (ret < 0)
> @@ -370,8 +372,6 @@ static int __init dummy_numa_init(void)
>
>   	if (numa_off)
>   		pr_info("NUMA disabled\n"); /* Forced off on command line. */
> -	else
> -		pr_info("No NUMA configuration found\n");
>   	pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
>   	       0LLU, PFN_PHYS(max_pfn) - 1);
>
> diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
> index fb62307..3157130 100644
> --- a/drivers/of/of_numa.c
> +++ b/drivers/of/of_numa.c
> @@ -63,7 +63,7 @@ static int __init of_numa_parse_memory_nodes(void)
>   	struct device_node *np = NULL;
>   	struct resource rsrc;
>   	u32 nid;
> -	int i, r = 0;
> +	int i, r;
>
>   	for_each_node_by_type(np, "memory") {
>   		r = of_property_read_u32(np, "numa-node-id", &nid);
> @@ -81,12 +81,11 @@ static int __init of_numa_parse_memory_nodes(void)
>   		if (!i || r) {
>   			of_node_put(np);
>   			pr_err("NUMA: bad property in memory node\n");
> -			r = r ? : -EINVAL;
> -			break;
> +			return r ? : -EINVAL;
>   		}
>   	}
>
> -	return r;
> +	return 0;
>   }
>

Well this is fixing changes you introduced in this patch-set. Any reason 
this is not part of patch 2?

>   static int __init of_numa_parse_distance_map_v1(struct device_node *map)
> --
> 2.5.0
>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>


From k.kozlowski at samsung.com  Tue May 31 02:12:31 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 11:12:31 +0200
Subject: [PATCH v5 00/22] ARM: dts: exynos: Add initial support for Odroid
 XU
In-Reply-To: <574C5BD2.60008@samsung.com>
References: <1464429273-23457-1-git-send-email-krzk@kernel.org>
 <574C5BD2.60008@samsung.com>
Message-ID: <574D557F.70209@samsung.com>

On 05/30/2016 05:27 PM, Sylwester Nawrocki wrote:
> On 05/28/2016 11:54 AM, Krzysztof Kozlowski wrote:
>>
>> The clock changes can go to clock tree. ARM changes to samsung-soc tree.
>> Please provide me a tag with include/dt-bindings/clock commits so I can
>> merge it.
> 
> I applied the clock tree patches and here is the tag for the three
> include/dt-bindings patches:

Thanks mate!
Pulled.

Best regards,
Krzysztof

> 
> The following changes since commit 1a695a905c18548062509178b98bc91e67510864:
> 
>   Linux 4.7-rc1 (2016-05-29 09:29:24 -0700)
> 
> are available in the git repository at:
> 
>   git://linuxtv.org/snawrocki/samsung.git tags/clk-v4.8-exynos5410-dt
> 
> for you to fetch changes up to ed1e1505db0c116affdfab01e650c44a9c459c65:
> 
>   dt-bindings: clock: Add I2C, HSI2C and RTC clock IDs to Exynos5410
> (2016-05-30 16:00:11 +0200)
> 
> ----------------------------------------------------------------
> Adition of missing clock index definitions for exynos5410 SoC
> PWM, USB, I2C, and RTC device related clocks.
> 
> ----------------------------------------------------------------
> Krzysztof Kozlowski (3):
>       dt-bindings: clock: Add license and reformat Exynos5410 clock IDs
>       dt-bindings: clock: Add PWM and USB clock IDs to Exynos5410
>       dt-bindings: clock: Add I2C, HSI2C and RTC clock IDs to Exynos5410
> 
>  include/dt-bindings/clock/exynos5410.h | 73
> +++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
>  1 file changed, 51 insertions(+), 22 deletions(-)
> 
> 
> --
> Thanks,
> Sylwester
> 



From arnaud.pouliquen at st.com  Tue May 31 02:14:48 2016
From: arnaud.pouliquen at st.com (Arnaud Pouliquen)
Date: Tue, 31 May 2016 11:14:48 +0200
Subject: [PATCH v4 16/18] ARM: STi: DT: STiH407: Add uniperif player dt
 nodes
In-Reply-To: <1464192412-16386-18-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
 <1464192412-16386-18-git-send-email-peter.griffin@linaro.org>
Message-ID: <574D5608.3080800@st.com>



On 05/25/2016 06:06 PM, Peter Griffin wrote:
> This patch adds the DT nodes for the uniperif player
> IP blocks found on STiH407 family silicon.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
>  arch/arm/boot/dts/stih407-family.dtsi | 76 +++++++++++++++++++++++++++++++++++
>  1 file changed, 76 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
> index 60f95b6..7ca149b 100644
> --- a/arch/arm/boot/dts/stih407-family.dtsi
> +++ b/arch/arm/boot/dts/stih407-family.dtsi
> @@ -755,5 +755,81 @@
>  			pinctrl-names = "default";
>  			pinctrl-0 = <&pinctrl_spdif_out >;
>  		};
> +
> +		sti_uni_player0: sti-uni-player at 0 {
> +			compatible = "st,sti-uni-player";
> +			status = "disabled";
> +			#sound-dai-cells = <0>;
> +			st,syscfg = <&syscfg_core>;
> +			clocks = <&clk_s_d0_flexgen CLK_PCM_0>;
> +			assigned-clocks = <&clk_s_d0_flexgen CLK_PCM_0>;
> +			assigned-clock-parents = <&clk_s_d0_quadfs 0>;
This does not work properly. You need to declare parent like this:
assigned-clocks = <&clk_s_d0_quadfs 0>, <&clk_s_d0_flexgen CLK_PCM_0>;
assigned-clock-parents = <0>, <&clk_s_d0_quadfs 0>;

> +			assigned-clock-rates = <50000000>;
> +			reg = <0x8D80000 0x158>;
> +			interrupts = <GIC_SPI 84 IRQ_TYPE_NONE>;
> +			dmas = <&fdma0 2 0 1>;
> +			dai-name = "Uni Player #0 (HDMI)";
> +			dma-names = "tx";
> +			st,uniperiph-id = <0>;
> +			st,version = <5>;
> +			st,mode = "HDMI";
> +		};
> +
> +		sti_uni_player1: sti-uni-player at 1 {
> +			compatible = "st,sti-uni-player";
> +			status = "disabled";
> +			#sound-dai-cells = <0>;
> +			st,syscfg = <&syscfg_core>;
> +			clocks = <&clk_s_d0_flexgen CLK_PCM_1>;
> +			assigned-clocks = <&clk_s_d0_flexgen CLK_PCM_1>;
> +			assigned-clock-parents = <&clk_s_d0_quadfs 1>;
assigned-clocks = <&clk_s_d0_quadfs 1>, <&clk_s_d0_flexgen CLK_PCM_1>;
assigned-clock-parents = <0>, <&clk_s_d0_quadfs 1>;

> +			assigned-clock-rates = <50000000>;
> +			reg = <0x8D81000 0x158>;
> +			interrupts = <GIC_SPI 85 IRQ_TYPE_NONE>;
> +			dmas = <&fdma0 3 0 1>;
> +			dai-name = "Uni Player #1 (PIO)";
> +			dma-names = "tx";
> +			st,uniperiph-id = <1>;
> +			st,version = <5>;
> +			st,mode = "PCM";
> +		};
> +
> +		sti_uni_player2: sti-uni-player at 2 {
> +			compatible = "st,sti-uni-player";
> +			status = "disabled";
> +			#sound-dai-cells = <0>;
> +			st,syscfg = <&syscfg_core>;
> +			clocks = <&clk_s_d0_flexgen CLK_PCM_2>;
> +			assigned-clocks = <&clk_s_d0_flexgen CLK_PCM_2>;
> +			assigned-clock-parents = <&clk_s_d0_quadfs 2>;
assigned-clocks = <&clk_s_d0_quadfs 2>, <&clk_s_d0_flexgen CLK_PCM_2>;
assigned-clock-parents = <0>, <&clk_s_d0_quadfs 2>;
> +			assigned-clock-rates = <50000000>;
> +			reg = <0x8D82000 0x158>;
> +			interrupts = <GIC_SPI 86 IRQ_TYPE_NONE>;
> +			dmas = <&fdma0 4 0 1>;
> +			dai-name = "Uni Player #1 (DAC)";
> +			dma-names = "tx";
> +			st,uniperiph-id = <2>;
> +			st,version = <5>;
> +			st,mode = "PCM";
> +		};
> +
> +		sti_uni_player3: sti-uni-player at 3 {
> +			compatible = "st,sti-uni-player";
> +			status = "disabled";
> +			#sound-dai-cells = <0>;
> +			st,syscfg = <&syscfg_core>;
> +			clocks = <&clk_s_d0_flexgen CLK_SPDIFF>;
> +			assigned-clocks = <&clk_s_d0_flexgen CLK_SPDIFF>;
> +			assigned-clock-parents = <&clk_s_d0_quadfs 3>;
> +			assigned-clock-rates = <50000000>;
assigned-clocks = <&clk_s_d0_quadfs 3>, <&clk_s_d0_flexgen CLK_SPDIFF>;
assigned-clock-parents = <0>, <&clk_s_d0_quadfs 3>;

Regards,
Arnaud
> +			reg = <0x8D85000 0x158>;
> +			interrupts = <GIC_SPI 89 IRQ_TYPE_NONE>;
> +			dmas = <&fdma0 7 0 1>;
> +			dma-names = "tx";
> +			dai-name = "Uni Player #1 (PIO)";
> +			st,uniperiph-id = <3>;
> +			st,version = <5>;
> +			st,mode = "SPDIF";
> +		};
>  	};
>  };
> 


From arnaud.pouliquen at st.com  Tue May 31 02:18:06 2016
From: arnaud.pouliquen at st.com (Arnaud Pouliquen)
Date: Tue, 31 May 2016 11:18:06 +0200
Subject: [PATCH v4 17/18] ARM: STi: DT: STiH407: Add uniperif reader dt
 nodes
In-Reply-To: <1464192412-16386-19-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
 <1464192412-16386-19-git-send-email-peter.griffin@linaro.org>
Message-ID: <574D56CE.5020802@st.com>



On 05/25/2016 06:06 PM, Peter Griffin wrote:
> This patch adds the DT node for the uniperif reader
> IP block found on STiH407 family silicon.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
>  arch/arm/boot/dts/stih407-family.dtsi | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
> index 7ca149b..fb6363e1 100644
> --- a/arch/arm/boot/dts/stih407-family.dtsi
> +++ b/arch/arm/boot/dts/stih407-family.dtsi
> @@ -831,5 +831,33 @@
>  			st,version = <5>;
>  			st,mode = "SPDIF";
>  		};
> +
> +		sti_uni_reader0: sti-uni-reader at 0 {
> +			compatible = "st,sti-uni-reader";
> +			status = "disabled";
> +			#sound-dai-cells = <0>;
> +			st,syscfg = <&syscfg_core>;
> +			reg = <0x8D83000 0x158>;
> +			interrupts = <GIC_SPI 87 IRQ_TYPE_NONE>;
> +			dmas = <&fdma0 5 0 1>;
> +			dma-names = "rx";
> +			dai-name = "Uni Reader #0 (PCM IN)";
> +			st,version = <3>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&pinctrl_i2s_8ch_in>;
suppress pinctrl declaration
> +		};
> +
> +		sti_uni_reader1: sti-uni-reader at 1 {
> +			compatible = "st,sti-uni-reader";
> +			status = "disabled";
> +			#sound-dai-cells = <0>;
> +			st,syscfg = <&syscfg_core>;
> +			reg = <0x8D84000 0x158>;
> +			interrupts = <GIC_SPI 88 IRQ_TYPE_NONE>;
> +			dmas = <&fdma0 6 0 1>;
> +			dma-names = "rx";
> +			dai-name = "Uni Reader #1 (HDMI RX)";
> +			st,version = <3>;
> +		};
>  	};
>  };
> 


From arnd at arndb.de  Tue May 31 02:21:37 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 31 May 2016 11:21:37 +0200
Subject: [PATCH] ARM: uniphier: drop code for old DT binding
In-Reply-To: <1464682628-12163-1-git-send-email-yamada.masahiro@socionext.com>
References: <1464682628-12163-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <4992506.m4GEHIOqdc@wuerfel>

On Tuesday, May 31, 2016 5:17:08 PM CEST Masahiro Yamada wrote:
> Commit 307d40c56b0c ("ARM: uniphier: rework SMP code to support new
> System Bus binding") added a new DT binding for SMP code, but still
> kept old code for the backward compatibility.
> 
> Linux 4.6 was out with both bindings supported, so it should not
> hurt to drop the old code now.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> 

That explanation is in general not sufficient. Are you sure that
nobody is shipping a machine with their own dts file that is not
merged upstream, and that there are no bootloaders that have a
hardcoded dtb file that we need to support indefinitely?

	Arnd


From k.kozlowski at samsung.com  Tue May 31 02:30:34 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 11:30:34 +0200
Subject: [PATCH 1/3] mmc: fix mmc mode selection for HS-DDR and higher
In-Reply-To: <1464505484-3661-2-git-send-email-wens@csie.org>
References: <1464505484-3661-1-git-send-email-wens@csie.org>
 <1464505484-3661-2-git-send-email-wens@csie.org>
Message-ID: <CAJKOXPcGCXJb5j2ShwL15GzKUXqR=z8p7TApORoHm9t-z1i6kA@mail.gmail.com>

On Sun, May 29, 2016 at 9:04 AM, Chen-Yu Tsai <wens at csie.org> wrote:
> When IS_ERR_VALUE was removed from the mmc core code, it was replaced
> with a simple not-zero check. This does not work, as the value checked
> is the return value for mmc_select_bus_width, which returns the set
> bit width on success. This made eMMC modes higher than HS-DDR unusable.
>
> Fix this by checking for a positive return value instead.
>
> Fixes: 287980e49ffc ("remove lots of IS_ERR_VALUE abuses")
> Cc: Arnd Bergmann <arnd at arndb.de>
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
> ---
>  drivers/mmc/core/mmc.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>

Reviewed-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

Could you be so kind and pick it up as fast as possible for current
RC? Half of my boards fail (because they work on eMMC) so testing
patches before applying is limited.

Best regards,
Krzysztof


From arnd at arndb.de  Tue May 31 02:35:08 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 31 May 2016 11:35:08 +0200
Subject: [BUG] CONFIG_UNINLINE_SPIN_UNLOCK important for Cortex-A9
In-Reply-To: <874m9eoetu.fsf@gmail.com>
References: <874m9eoetu.fsf@gmail.com>
Message-ID: <4854518.jvbplH0SM0@wuerfel>

On Tuesday, May 31, 2016 9:40:29 AM CEST Holger Schurig wrote:
> I chased a bug in the recent weeks that seems to be related to spinlocks.
> 
> 
> 
> Hardware & Kernel config
> ------------------------
> I have an i.MX6Q device. I don't use "make imx_v6_v7_defconfig", but
> selected only what I need. As such, I only have CONFIG_ARCH_MXC and
> CONFIG_SOC_IMX6Q enabled.
> 
> As a result, in my kernel CONFIG_UNINLINE_SPIN_UNLOCK was *not* defined.
> 
> In a kernel configured with "make imx_v6_v7_defconfig" this is
> configured. And so people (e.g. the Freescale/NPX people) that normally
> use this defconfig will never see the issue.

Have you tried multi_v7_defconfig? That also does not set 
CONFIG_UNINLINE_SPIN_UNLOCK, but it is generally assumed to work.

> Cure
> ----
> When I turned on CONFIG_PROVE_RCU the issue stopped. This option does
> "select UNINLINE_SPIN_UNLOCK", and this uninline option is also selected
> with the imx_v6_v7_defconfig. I actually don't care if RCUs are proven
> or not, this just turns on the uninlining as a side-effect.

Just to be sure: If you just enable UNINLINE_SPIN_UNLOCK (e.g. using
a 'select' from arch/arm/mach-imx/Kconfig) without selecting PROVE_RCU,
you say the bug is gone too?

> Question
> --------
> I don't have the slightest idea what produces the error and why
> uninlining helps (I'm not deep in such internals), so I wonder how to
> proceed.
>
> Should I simply send in a patch that "select UNINLINE_SPIN_UNLOCK" on
> i.MX6Q ???

I think we really need to get to the bottom of this, as there are tons
of possible reasons for the behavior, and selecting it for i.MX6Q.

Please provide a few more details about your environment:

- Specific kernel version, and full list of patches applied (if any).
  Have you reproduced this with a plain unpatched linux-4.6 kernel?

- Specific gcc version you used for building the kernel. Does this
  happen with both old and new compilers, e.g. 4.7 and 6.1?

- If it happens with an unpatched linux-4.6 and all gcc versions
  with multi_v7_defconfig, we should try reproducing it on some
  other quad-core Cortex-A9 (non-imx) platform with the same kernel
  binary.

	Arnd


From narmstrong at baylibre.com  Tue May 31 02:36:15 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 31 May 2016 11:36:15 +0200
Subject: [PATCH] pinctrl: oxnas: Rename pinctrl_utils_dt_free_map to
 pinctrl_utils_free_map
Message-ID: <1464687375-1370-1-git-send-email-narmstrong@baylibre.com>

Rename pinctrl_utils_dt_free_map to pinctrl_utils_free_map, introduced in
d32f7fd3bbc3 ("pinctrl: Rename pinctrl_utils_dt_free_map to pinctrl_utils_free_map")
but not reported into oxnas driver.

Fixes: 611dac1e48a4 ("pinctrl: Add Oxford Semiconductor OXNAS pinctrl and gpio driver")
Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/pinctrl/pinctrl-oxnas.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c
index 2c6abef..917a7d2 100644
--- a/drivers/pinctrl/pinctrl-oxnas.c
+++ b/drivers/pinctrl/pinctrl-oxnas.c
@@ -321,7 +321,7 @@ static const struct pinctrl_ops oxnas_pinctrl_ops = {
 	.get_group_name = oxnas_pinctrl_get_group_name,
 	.get_group_pins = oxnas_pinctrl_get_group_pins,
 	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
-	.dt_free_map = pinctrl_utils_dt_free_map,
+	.dt_free_map = pinctrl_utils_free_map,
 };
 
 static int oxnas_pinmux_get_functions_count(struct pinctrl_dev *pctldev)
-- 
1.9.1



From daniel.lezcano at linaro.org  Tue May 31 02:44:29 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 31 May 2016 11:44:29 +0200
Subject: [PATCH 4/4] clocksource: sp804: support 64bit mode for hisilicon
 timer64
In-Reply-To: <1464428033-52106-5-git-send-email-wangkefeng.wang@huawei.com>
References: <1464428033-52106-1-git-send-email-wangkefeng.wang@huawei.com>
 <1464428033-52106-5-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <574D5CFD.1010305@linaro.org>

On 05/28/2016 11:33 AM, Kefeng Wang wrote:
> There is a kind of 64bit mode timer in hisilicon soc(like Hip05, Hip06 and
> some arm32 soc), it is very similar with ARM sp804 Dual Timers, but TimerX
> LOAD/Value/BGLoad are 64bit(two 32bit regs), and reg offset is different.

"A kind of 64bit mode timer" is very vague. Please describe more the 
timer you want to support in this driver and split dt-bindings, so Rob 
can ack it independently.

Especially, explain why 64bits is needed here, when the clocksource 
wraps up, etc ...

> Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> ---
>   .../devicetree/bindings/timer/arm,sp804.txt        |  1 +
>   drivers/clocksource/timer-sp.h                     |  1 +
>   drivers/clocksource/timer-sp804.c                  | 76 ++++++++++++++++++----
>   3 files changed, 66 insertions(+), 12 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/timer/arm,sp804.txt b/Documentation/devicetree/bindings/timer/arm,sp804.txt
> index 5cd8eee7..d8e8f8f 100644
> --- a/Documentation/devicetree/bindings/timer/arm,sp804.txt
> +++ b/Documentation/devicetree/bindings/timer/arm,sp804.txt
> @@ -17,6 +17,7 @@ Optional properties:
>   - arm,sp804-has-irq = <#>: In the case of only 1 timer irq line connected, this
>   	specifies if the irq connection is for timer 1 or timer 2. A value of 1
>   	or 2 should be used.
> +- hisilicon,timer64: Support hisilicon 64bit mode timer.
>
>   Example:
>
> diff --git a/drivers/clocksource/timer-sp.h b/drivers/clocksource/timer-sp.h
> index 050d885..adf82f4 100644
> --- a/drivers/clocksource/timer-sp.h
> +++ b/drivers/clocksource/timer-sp.h
> @@ -16,6 +16,7 @@
>   #define TIMER_VALUE	0x04			/* ACVR ro */
>   #define TIMER_CTRL	0x08			/* ACVR rw */
>   #define TIMER_CTRL_ONESHOT	(1 << 0)	/*  CVR */
> +/* Used in hisilicon timer64, it means enabling 64bit mode */
>   #define TIMER_CTRL_32BIT	(1 << 1)	/*  CVR */
>   #define TIMER_CTRL_DIV1		(0 << 2)	/* ACVR */
>   #define TIMER_CTRL_DIV16	(1 << 2)	/* ACVR */
> diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
> index 2ff8777..7f1d947 100644
> --- a/drivers/clocksource/timer-sp804.c
> +++ b/drivers/clocksource/timer-sp804.c
> @@ -34,6 +34,16 @@
>
>   #include "timer-sp.h"
>
> +#define TIMER64_2_BASE	0x40
> +#define TIMER64_LOAD_L	0x00
> +#define TIMER64_LOAD_H	0x04
> +#define TIMER64_VALUE_L	0x08
> +#define TIMER64_VALUE_H	0x0C
> +
> +#define HISI_OFFSET	0x8
> +
> +static int timer64_offset;
> +
>   static long __init sp804_get_clock_rate(struct clk *clk, const char *name)
>   {
>   	long rate;
> @@ -78,8 +88,8 @@ static inline void sp804_load_mode_set(void __iomem *base, unsigned long load, i
>   	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
>   			     mode | TIMER_CTRL_ENABLE;
>
> -	writel(load, base + TIMER_LOAD);
> -	writel(ctrl, base + TIMER_CTRL);
> +	writel(load, base + TIMER_LOAD); /* equal TIMER64_LOAD_L when timer64*/
> +	writel(ctrl, base + TIMER_CTRL + timer64_offset);
>   }
>
>   static void __iomem *sched_clock_base;
> @@ -89,11 +99,37 @@ static u64 notrace sp804_read(void)
>   	return ~readl_relaxed(sched_clock_base + TIMER_VALUE);
>   }
>
> +static u64 notrace hisi_timer64_read(void)
> +{
> +	u32 val_lo, val_hi, tmp_hi;
> +
> +	do {
> +		val_hi = readl_relaxed(sched_clock_base + TIMER64_VALUE_H);
> +		val_lo = readl_relaxed(sched_clock_base + TIMER64_VALUE_L);
> +		tmp_hi = readl_relaxed(sched_clock_base + TIMER64_VALUE_H);
> +	} while (val_hi != tmp_hi);
> +
> +	return ((u64) val_hi << 32) | val_lo;
> +}

64bits is not free. Is it really needed ? How long before it wraps up in 
32bits ?

> +
>   void __init sp804_timer_disable(void __iomem *base)
>   {
> -	writel(0, base + TIMER_CTRL);
> +	writel(0, base + TIMER_CTRL + timer64_offset);
>   }

Nope, sp804_timer_disable() should be called with the right parameter.

Ok, so before going further, do the following:

1. Create a structure:

struct sp804_clockevent {
	struct clockevent clkevt;
	void __iomem *base;
	void __iomem *ctrl;
	int width;
};

2. Add a function to return the sp804_clockevent from a clkevt

struct sp804_clockevent sp804_timer(struct clockevent *clkevt)
{
	return container_of(clkevt, struct sp804_clockevent, clkevt);
}

3. Change the different function to use:
	struct sp804_clockevent -> base | ctrl
	
4. And then at init time, fill the structure with the right info.

5. Make sure, 64bits clocksource is really needed and if it is possible 
to share a common timer_read()

Thanks !
   -- Daniel

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

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



From narmstrong at baylibre.com  Tue May 31 02:49:56 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 31 May 2016 11:49:56 +0200
Subject: [PATCH 0/2] clocksource: Add support for Oxford Semiconductor RPS
 Dual Timer
Message-ID: <1464688198-9655-1-git-send-email-narmstrong@baylibre.com>

Adds driver for the Oxford Semiconductor RPS Dual Timer as base of the OX810SE
clock tick event and sched clock source.

This driver was posted with the initial OX810SE platform patchset at :
http://lkml.kernel.org/r/1457005210-18485-5-git-send-email-narmstrong at baylibre.com
and
http://lkml.kernel.org/r/1457005210-18485-6-git-send-email-narmstrong at baylibre.com

But since the SP804 was very similar, I decided to adapt it for OX810SE usage.
For some reasons, the SP804 has a lot of legacy code for non-dt, non-multiarch
platforms and needs a complete rewrite.
For now, this adds a dedicated driver with the same bindings as intended for SP804.

Neil Armstrong (2):
  clocksource: Add Oxford Semiconductor RPS Dual Timer
  dt-bindings: clocksource: Add Add Oxford Semiconductor RPS Timer
    bindings

 .../devicetree/bindings/timer/oxsemi,rps-timer.txt |  17 ++
 drivers/clocksource/Kconfig                        |   6 +
 drivers/clocksource/Makefile                       |   1 +
 drivers/clocksource/timer-oxnas-rps.c              | 273 +++++++++++++++++++++
 4 files changed, 297 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/oxsemi,rps-timer.txt
 create mode 100644 drivers/clocksource/timer-oxnas-rps.c

-- 
1.9.1



From narmstrong at baylibre.com  Tue May 31 02:49:58 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 31 May 2016 11:49:58 +0200
Subject: [PATCH 2/2] dt-bindings: clocksource: Add Add Oxford Semiconductor
 RPS Timer bindings
In-Reply-To: <1464688198-9655-1-git-send-email-narmstrong@baylibre.com>
References: <1464688198-9655-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464688198-9655-3-git-send-email-narmstrong@baylibre.com>

Add DT bindings for the Oxford Semiconductor RPS dual Timer.

Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 .../devicetree/bindings/timer/oxsemi,rps-timer.txt      | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/oxsemi,rps-timer.txt

diff --git a/Documentation/devicetree/bindings/timer/oxsemi,rps-timer.txt b/Documentation/devicetree/bindings/timer/oxsemi,rps-timer.txt
new file mode 100644
index 0000000..3ca89cd
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/oxsemi,rps-timer.txt
@@ -0,0 +1,17 @@
+Oxford Semiconductor OXNAS SoCs Family RPS Timer
+================================================
+
+Required properties:
+- compatible: Should be "oxsemi,ox810se-rps-timer"
+- reg : Specifies base physical address and size of the registers.
+- interrupts : The interrupts of the two timers
+- clocks : The phandle of the timer clock source
+
+example:
+
+timer0: timer at 200 {
+	compatible = "oxsemi,ox810se-rps-timer";
+	reg = <0x200 0x40>;
+	clocks = <&rpsclk>;
+	interrupts = <4 5>;
+};
-- 
1.9.1



From narmstrong at baylibre.com  Tue May 31 02:49:57 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 31 May 2016 11:49:57 +0200
Subject: [PATCH 1/2] clocksource: Add Oxford Semiconductor RPS Dual Timer
In-Reply-To: <1464688198-9655-1-git-send-email-narmstrong@baylibre.com>
References: <1464688198-9655-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <1464688198-9655-2-git-send-email-narmstrong@baylibre.com>

Add clocksource and clockevent driver from dual RPS timer.
The HW provides a dual one-shot or periodic 24bit timers,
the drivers set the first one as tick event source and the
second as a continuous scheduler clock source.
The timer can use 1, 16 or 256 as pre-dividers, thus the
clocksource uses 16 by default.

CC: Ma Haijun <mahaijuns at gmail.com>
Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
---
 drivers/clocksource/Kconfig           |   6 +
 drivers/clocksource/Makefile          |   1 +
 drivers/clocksource/timer-oxnas-rps.c | 273 ++++++++++++++++++++++++++++++++++
 3 files changed, 280 insertions(+)
 create mode 100644 drivers/clocksource/timer-oxnas-rps.c

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 47352d2..7e382c5 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -293,6 +293,12 @@ config VF_PIT_TIMER
 	help
 	  Support for Period Interrupt Timer on Freescale Vybrid Family SoCs.
 
+config OXNAS_RPS_TIMER
+	bool
+	select CLKSRC_MMIO
+	help
+	  This enables support for the Oxford Semiconductor OXNAS RPS timers.
+
 config SYS_SUPPORTS_SH_CMT
         bool
 
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 473974f..bc66981 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
 obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o
 obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o
 obj-$(CONFIG_CLKSRC_NPS)	+= timer-nps.o
+obj-$(CONFIG_OXNAS_RPS_TIMER)	+= timer-oxnas-rps.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
diff --git a/drivers/clocksource/timer-oxnas-rps.c b/drivers/clocksource/timer-oxnas-rps.c
new file mode 100644
index 0000000..f42f73d
--- /dev/null
+++ b/drivers/clocksource/timer-oxnas-rps.c
@@ -0,0 +1,273 @@
+/*
+ * drivers/clocksource/timer-oxnas-rps.c
+ *
+ * Copyright (C) 2009 Oxford Semiconductor Ltd
+ * Copyright (C) 2013 Ma Haijun <mahaijuns at gmail.com>
+ * Copyright (C) 2016 Neil Armstrong <narmstrong at baylibre.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/>.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/clockchips.h>
+#include <linux/sched_clock.h>
+
+/* TIMER1 used as tick
+ * TIMER2 used as clocksource
+ */
+
+/* Registers definitions */
+
+#define TIMER_LOAD_REG		0x0
+#define TIMER_CURR_REG		0x4
+#define TIMER_CTRL_REG		0x8
+#define TIMER_CLRINT_REG	0xC
+
+#define TIMER_BITS		24
+
+#define TIMER_MAX_VAL		(BIT(TIMER_BITS) - 1)
+
+#define TIMER_PERIODIC		BIT(6)
+#define TIMER_ENABLE		BIT(7)
+
+#define TIMER_DIV1		(0)
+#define TIMER_DIV16		(1 << 2)
+#define TIMER_DIV256		(2 << 2)
+
+#define TIMER1_REG_OFFSET	0
+#define TIMER2_REG_OFFSET	0x20
+
+/* Clockevent & Clocksource data */
+
+struct oxnas_rps_timer {
+	struct clock_event_device clkevent;
+	void __iomem *clksrc_base;
+	void __iomem *clkevt_base;
+	unsigned long timer_period;
+	unsigned int timer_prescaler;
+	struct clk *clk;
+	int irq;
+};
+
+static irqreturn_t oxnas_rps_timer_irq(int irq, void *dev_id)
+{
+	struct oxnas_rps_timer *rps = dev_id;
+
+	writel_relaxed(0, rps->clkevt_base + TIMER_CLRINT_REG);
+
+	rps->clkevent.event_handler(&rps->clkevent);
+
+	return IRQ_HANDLED;
+}
+
+static void oxnas_rps_timer_config(struct oxnas_rps_timer *rps,
+				   unsigned long period,
+				   unsigned int periodic)
+{
+	uint32_t cfg = rps->timer_prescaler;
+
+	if (period)
+		cfg |= TIMER_ENABLE;
+
+	if (periodic)
+		cfg |= TIMER_PERIODIC;
+
+	writel_relaxed(period, rps->clkevt_base + TIMER_LOAD_REG);
+	writel_relaxed(cfg, rps->clkevt_base + TIMER_CTRL_REG);
+}
+
+static int oxnas_rps_timer_shutdown(struct clock_event_device *evt)
+{
+	struct oxnas_rps_timer *rps =
+		container_of(evt, struct oxnas_rps_timer, clkevent);
+
+	if (!clockevent_state_periodic(evt))
+		return 0;
+
+	oxnas_rps_timer_config(rps, 0, 0);
+
+	return 0;
+}
+
+static int oxnas_rps_timer_set_periodic(struct clock_event_device *evt)
+{
+	struct oxnas_rps_timer *rps =
+		container_of(evt, struct oxnas_rps_timer, clkevent);
+
+	oxnas_rps_timer_config(rps, rps->timer_period, 1);
+
+	return 0;
+}
+
+static int oxnas_rps_timer_set_oneshot(struct clock_event_device *evt)
+{
+	struct oxnas_rps_timer *rps =
+		container_of(evt, struct oxnas_rps_timer, clkevent);
+
+	oxnas_rps_timer_config(rps, rps->timer_period, 0);
+
+	return 0;
+}
+
+static int oxnas_rps_timer_next_event(unsigned long delta,
+				struct clock_event_device *evt)
+{
+	struct oxnas_rps_timer *rps =
+		container_of(evt, struct oxnas_rps_timer, clkevent);
+
+	oxnas_rps_timer_config(rps, delta, 0);
+
+	return 0;
+}
+
+static void __init oxnas_rps_clockevent_init(struct oxnas_rps_timer *rps)
+{
+	ulong clk_rate = clk_get_rate(rps->clk);
+	ulong timer_rate;
+
+	/* Start with prescaler 1 */
+	rps->timer_prescaler = TIMER_DIV1;
+	rps->timer_period = DIV_ROUND_UP(clk_rate, HZ);
+	timer_rate = clk_rate;
+
+	if (rps->timer_period > TIMER_MAX_VAL) {
+		rps->timer_prescaler = TIMER_DIV16;
+		rps->timer_period = DIV_ROUND_UP(clk_rate / 16, HZ);
+		timer_rate = clk_rate / 16;
+	}
+	if (rps->timer_period > TIMER_MAX_VAL) {
+		rps->timer_prescaler = TIMER_DIV256;
+		rps->timer_period = DIV_ROUND_UP(clk_rate / 256, HZ);
+		timer_rate = clk_rate / 256;
+	}
+
+	rps->clkevent.name = "oxnas-rps";
+	rps->clkevent.features = CLOCK_EVT_FEAT_PERIODIC |
+				 CLOCK_EVT_FEAT_ONESHOT |
+				 CLOCK_EVT_FEAT_DYNIRQ;
+	rps->clkevent.tick_resume = oxnas_rps_timer_shutdown;
+	rps->clkevent.set_state_shutdown = oxnas_rps_timer_shutdown;
+	rps->clkevent.set_state_periodic = oxnas_rps_timer_set_periodic;
+	rps->clkevent.set_state_oneshot = oxnas_rps_timer_set_oneshot;
+	rps->clkevent.set_next_event = oxnas_rps_timer_next_event;
+	rps->clkevent.rating = 200;
+	rps->clkevent.cpumask = cpu_possible_mask;
+	rps->clkevent.irq = rps->irq;
+	clockevents_config_and_register(&rps->clkevent,
+					timer_rate,
+					1,
+					TIMER_MAX_VAL);
+
+	pr_info("Registered clock event rate %luHz prescaler %d period %lu\n",
+			clk_rate,
+			rps->timer_prescaler,
+			rps->timer_period);
+}
+
+/* Clocksource */
+
+static void __iomem *timer_sched_base;
+
+static u64 notrace oxnas_rps_read_sched_clock(void)
+{
+	return ~readl_relaxed(timer_sched_base);
+}
+
+static void __init oxnas_rps_clocksource_init(struct oxnas_rps_timer *rps)
+{
+	ulong clk_rate = clk_get_rate(rps->clk);
+	int ret;
+
+	/* use prescale 16 */
+	clk_rate = clk_rate / 16;
+
+	writel_relaxed(TIMER_MAX_VAL, rps->clksrc_base + TIMER_LOAD_REG);
+	writel_relaxed(TIMER_PERIODIC | TIMER_ENABLE | TIMER_DIV16,
+			rps->clksrc_base + TIMER_CTRL_REG);
+
+	timer_sched_base = rps->clksrc_base + TIMER_CURR_REG;
+	sched_clock_register(oxnas_rps_read_sched_clock,
+			     TIMER_BITS, clk_rate);
+	ret = clocksource_mmio_init(timer_sched_base,
+				    "oxnas_rps_clocksource_timer",
+				    clk_rate, 250, TIMER_BITS,
+				    clocksource_mmio_readl_down);
+	if (WARN_ON(ret))
+		pr_err("can't register clocksource\n");
+
+	pr_info("Registered clocksource rate %luHz\n", clk_rate);
+}
+
+static void __init oxnas_rps_timer_init(struct device_node *np)
+{
+	struct oxnas_rps_timer *rps;
+	void __iomem *base;
+	int ret;
+
+	rps = kzalloc(sizeof(*rps), GFP_KERNEL);
+	if (WARN_ON(!rps))
+		return;
+
+	rps->clk = of_clk_get(np, 0);
+	if (WARN_ON(IS_ERR(rps->clk)))
+		return;
+
+	if (WARN_ON(clk_prepare_enable(rps->clk)))
+		goto err;
+
+	base = of_iomap(np, 0);
+	if (WARN_ON(!base))
+		goto err;
+
+
+	rps->irq = irq_of_parse_and_map(np, 0);
+	if (WARN_ON(rps->irq < 0))
+		goto err;
+
+	rps->clkevt_base = base + TIMER1_REG_OFFSET;
+	rps->clksrc_base = base + TIMER2_REG_OFFSET;
+
+	/* Disable timers */
+	writel_relaxed(0, rps->clkevt_base + TIMER_CTRL_REG);
+	writel_relaxed(0, rps->clksrc_base + TIMER_CTRL_REG);
+	writel_relaxed(0, rps->clkevt_base + TIMER_LOAD_REG);
+	writel_relaxed(0, rps->clksrc_base + TIMER_LOAD_REG);
+	writel_relaxed(0, rps->clkevt_base + TIMER_CLRINT_REG);
+	writel_relaxed(0, rps->clksrc_base + TIMER_CLRINT_REG);
+
+	ret = request_irq(rps->irq, oxnas_rps_timer_irq,
+			  IRQF_TIMER | IRQF_IRQPOLL,
+			  "rps-timer", rps);
+	if (WARN_ON(ret))
+		goto err;
+
+	oxnas_rps_clockevent_init(rps);
+	oxnas_rps_clocksource_init(rps);
+
+	return;
+err:
+	clk_put(rps->clk);
+	kfree(rps);
+}
+
+CLOCKSOURCE_OF_DECLARE(ox810se_rps,
+		       "oxsemi,ox810se-rps-timer", oxnas_rps_timer_init);
-- 
1.9.1



From grygorii.strashko at ti.com  Tue May 31 02:51:05 2016
From: grygorii.strashko at ti.com (Grygorii Strashko)
Date: Tue, 31 May 2016 12:51:05 +0300
Subject: interrupts properties and API usage with GPIO controllers/Device
 Tree
In-Reply-To: <CACRpkdYULz6fgw8N_yLCGYzqV7DjeJGmh1b0e9coxpGqSgZf+A@mail.gmail.com>
References: <57461CDC.603@gmail.com> <57485844.3050807@ti.com>
 <CACRpkdYULz6fgw8N_yLCGYzqV7DjeJGmh1b0e9coxpGqSgZf+A@mail.gmail.com>
Message-ID: <574D5E89.10906@ti.com>

On 05/31/2016 11:49 AM, Linus Walleij wrote:
> On Fri, May 27, 2016 at 4:23 PM, Grygorii Strashko
> <grygorii.strashko at ti.com> wrote:
>
>> Another interesting, related question (as for me) is "Is there a limitation
>>   that gpio bank can have only 32 GPIO pins (from gpiolib point of view)?"
>
> Do you mean for this driver or in general?

In general.

>
> The gpio MMIO driver has this limitation, but not the subsystem
> and gpiolib as far as I know.

Thanks.

-- 
regards,
-grygorii


From robin.murphy at arm.com  Tue May 31 02:51:59 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 31 May 2016 10:51:59 +0100
Subject: [PATCH] iommu/arm-smmu: Properly initialize CBAR MemAttr
In-Reply-To: <1464617742-5493-1-git-send-email-bogdan.purcareata@nxp.com>
References: <1464617742-5493-1-git-send-email-bogdan.purcareata@nxp.com>
Message-ID: <574D5EBF.8010707@arm.com>

On 30/05/16 15:15, Bogdan Purcareata wrote:
> Currently, when initializing the CBAR memattr attributes to the weakest
> values, it is expected that the final ones will be declared in the TTBCR
> register (SMMU_CBn_TCR).

You mean the stage 1 PTE, right? TTBCR only controls the attributes for 
table walks.

> This is not required when CBAR type consists of a stage 1 translation
> followed by a stage 2 bypass.

On the contrary, this is _only_ required for stage 1 translation with 
stage 2 bypass - CBAR.MemAttr gives the _stage 2_ memory type (see 
section 2.4 "Memory type and shareability attribute determination" in 
the SMMU spec). For nested translation the stage 2 attributes come from 
the stage 2 context itself.

>                               This is the case when assigning a VFIO PCI
> device to a KVM guest. Overriding the default transaction attributes to
> writeback cacheable results in the device no longer working in the guest
> (the adapter requires explicit flushes on the descriptor rings memory).

 From that, the real problem is almost certainly that you're erroneously 
describing the device as coherent or non-coherent (whichever it actually 
isn't) somewhere.

> Update the context init routine to initialize the CBAR MemAttr field only
> if there's a stage 1 followed by a stage 2 translation.

The CBAR.MemAttr field doesn't even exist in that format - it's a good 
thing that we don't actually implement nested translation (we currently 
just use a stage 2 context instead), because this would end up 
corrupting CBAR.CBNDX (i.e. the stage 2 context bank index). Now that I 
should probably fix...

> Signed-off-by: Bogdan Purcareata <bogdan.purcareata at nxp.com>
> ---
>   drivers/iommu/arm-smmu.c | 13 +++++++++----
>   1 file changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index ff7a392..1400ec9 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -765,13 +765,14 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
>   {
>   	u32 reg;
>   	u64 reg64;
> -	bool stage1;
> +	bool stage1, stage1_stage2;
>   	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
>   	struct arm_smmu_device *smmu = smmu_domain->smmu;
>   	void __iomem *cb_base, *gr1_base;
>
>   	gr1_base = ARM_SMMU_GR1(smmu);
>   	stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
> +	stage1_stage2 = cfg->cbar == CBAR_TYPE_S1_TRANS_S2_TRANS;
>   	cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
>
>   	if (smmu->version > ARM_SMMU_V1) {
> @@ -793,15 +794,19 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
>
>   	/*
>   	 * Use the weakest shareability/memory types, so they are
> -	 * overridden by the ttbcr/pte.
> +	 * overridden by the ttbcr/pte. This happens only if the stage
> +	 * 1 is followed by a stage 2 translation.
>   	 */
> -	if (stage1) {
> +	if (stage1_stage2) {
>   		reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
>   			(CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
> -	} else if (!(smmu->features & ARM_SMMU_FEAT_VMID16)) {

Since MemAttr is initially zero, the net result of this is that *all* 
stage 1 transactions will now get overridden to Strongly-Ordered. That 
may hide your problem, but it's definitely not the correct thing to do.

Robin.

> +	}
> +
> +	if (!stage1 && !(smmu->features & ARM_SMMU_FEAT_VMID16)) {
>   		/* 8-bit VMIDs live in CBAR */
>   		reg |= ARM_SMMU_CB_VMID(smmu, cfg) << CBAR_VMID_SHIFT;
>   	}
> +
>   	writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx));
>
>   	/* TTBRs */
>



From narmstrong at baylibre.com  Tue May 31 02:57:03 2016
From: narmstrong at baylibre.com (Neil Armstrong)
Date: Tue, 31 May 2016 11:57:03 +0200
Subject: [PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <574C6F5A.1010109@roeck-us.net>
References: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
 <1464614948-28247-2-git-send-email-narmstrong@baylibre.com>
 <574C6F5A.1010109@roeck-us.net>
Message-ID: <574D5FEF.7050308@baylibre.com>


Hi Guenter,
On 05/30/2016 06:50 PM, Guenter Roeck wrote:
> On 05/30/2016 06:29 AM, Neil Armstrong wrote:
>> Add watchdog specific driver for Amlogic Meson GXBB SoC.
>>
>> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
>> ---
>>   drivers/watchdog/Makefile         |   1 +
>>   drivers/watchdog/meson_gxbb_wdt.c | 277 ++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 278 insertions(+)
>>   create mode 100644 drivers/watchdog/meson_gxbb_wdt.c
>>
>> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
>> index 9bde095..7679d93 100644
>> --- a/drivers/watchdog/Makefile
>> +++ b/drivers/watchdog/Makefile
>> @@ -68,6 +68,7 @@ obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
>>   obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
>>   obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
>>   obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
>> +obj-$(CONFIG_MESON_WATCHDOG) += meson_gxbb_wdt.o
> 
> I would really prefer a separate configuration option.

OK

> 
>>   obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
>>   obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
>>   obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
>> diff --git a/drivers/watchdog/meson_gxbb_wdt.c b/drivers/watchdog/meson_gxbb_wdt.c
>> new file mode 100644
>> index 0000000..9619c5e
>> --- /dev/null
>> +++ b/drivers/watchdog/meson_gxbb_wdt.c
>> @@ -0,0 +1,277 @@
>> +/*
>> + * This file is provided under a dual BSD/GPLv2 license.  When using or
>> + * redistributing this file, you may do so under either license.
>> + *
>> + * GPL LICENSE SUMMARY
>> + *
>> + * Copyright (c) 2016 BayLibre, SAS.
>> + * Author: Neil Armstrong <narmstrong at baylibre.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.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
>> + * The full GNU General Public License is included in this distribution
>> + * in the file called COPYING.
>> + *
>> + * BSD LICENSE
>> + *
>> + * Copyright (c) 2016 BayLibre, SAS.
>> + * Author: Neil Armstrong <narmstrong at baylibre.com>
>> + *
>> + * Redistribution and use in source and binary forms, with or without
>> + * modification, are permitted provided that the following conditions
>> + * are met:
>> + *
>> + *   * Redistributions of source code must retain the above copyright
>> + *     notice, this list of conditions and the following disclaimer.
>> + *   * Redistributions in binary form must reproduce the above copyright
>> + *     notice, this list of conditions and the following disclaimer in
>> + *     the documentation and/or other materials provided with the
>> + *     distribution.
>> + *   * Neither the name of Intel Corporation nor the names of its
>> + *     contributors may be used to endorse or promote products derived
>> + *     from this software without specific prior written permission.
>> + *
>> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
>> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
>> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
>> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
>> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
>> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
>> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
>> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
>> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>> + */
>> +#include <linux/err.h>
>> +#include <linux/module.h>
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/clk.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +#include <linux/types.h>
>> +#include <linux/watchdog.h>
> 
> Please order include files alphabetically; that simplifies later changes
> and helps finding duplicates.
> 
>> +
>> +#define DEFAULT_TIMEOUT    10    /* seconds */
>> +
> 
> Sure you want the default timeout to be that low ?

I'm not sure of anything actually, what is generally set ?

> 
>> +#define GXBB_WDT_CTRL_REG            0x0
>> +#define GXBB_WDT_CTRL1_REG            0x4
>> +#define GXBB_WDT_TCNT_REG            0x8
>> +#define GXBB_WDT_RSET_REG            0xc
>> +
>> +#define GXBB_WDT_CTRL_EE_RESET_NOW        BIT(26)
>> +
>> +#define GXBB_WDT_CTRL_CLKDIV_EN            BIT(25)
>> +#define GXBB_WDT_CTRL_CLK_EN            BIT(24)
>> +#define GXBB_WDT_CTRL_IRQ_EN            BIT(23)
>> +#define GXBB_WDT_CTRL_EE_RESET            BIT(21)
>> +#define GXBB_WDT_CTRL_XTAL_SEL            (0)
>> +#define GXBB_WDT_CTRL_CLK81_SEL            BIT(19)
>> +#define GXBB_WDT_CTRL_EN            BIT(18)
>> +#define GXBB_WDT_CTRL_DIV_MASK            (BIT(18) - 1)
>> +
>> +#define GXBB_WDT_CTRL1_GPIO_PULSE        BIT(17)
>> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_0        BIT(16)
>> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_1        (0)
>> +#define GXBB_WDT_CTRL1_GPIO_PULSE_CNT        (BIT(16) - 1)
>> +
>> +#define GXBB_WDT_TCNT_SETUP_MASK        (BIT(16) - 1)
>> +#define GXBB_WDT_TCNT_CNT_SHIFT            16
>> +
>> +struct meson_gxbb_wdt {
>> +    void __iomem *reg_base;
>> +    struct watchdog_device wdt_dev;
>> +    struct clk *clk;
>> +};
>> +
>> +static int meson_gxbb_wdt_start(struct watchdog_device *wdt_dev)
>> +{
>> +    struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
>> +
>> +    writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) | GXBB_WDT_CTRL_EN,
>> +        data->reg_base + GXBB_WDT_CTRL_REG);
>> +
>> +    return 0;
>> +}
>> +
>> +static int meson_gxbb_wdt_stop(struct watchdog_device *wdt_dev)
>> +{
>> +    struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
>> +
>> +    writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) & ~GXBB_WDT_CTRL_EN,
>> +        data->reg_base + GXBB_WDT_CTRL_REG);
> 
> Please align continuation lines with '('.
> 
>> +
>> +    return 0;
>> +}
>> +
>> +static int meson_gxbb_wdt_ping(struct watchdog_device *wdt_dev)
>> +{
>> +    struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
>> +
>> +    writel(0, data->reg_base + GXBB_WDT_RSET_REG);
>> +
>> +    return 0;
>> +}
>> +
>> +static int meson_gxbb_wdt_get_timeout(struct meson_gxbb_wdt *data)
>> +{
>> +    return (readl(data->reg_base + GXBB_WDT_TCNT_REG) &
>> +            GXBB_WDT_TCNT_SETUP_MASK) / 1000;
>> +}
>> +
> Unused function ?
Crap, forgot to remove this.

> 
>> +static int meson_gxbb_wdt_set_timeout(struct watchdog_device *wdt_dev,
>> +                      unsigned int timeout)
>> +{
>> +    struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
>> +
>> +    meson_gxbb_wdt_ping(wdt_dev);
> 
> Is this necessary ? The infrastructure calls it after calling this function.

Is it really safe to change the timeout value before calling ping ?

On the HW, there is a running counter that is reset to 0 when writing any value to the RSET register.
A comparator triggers a reset when the counter is >= the timeout value.

If somehow we change to a lower value but the counter is > the new timeout value, it will reset the system.
Calling ping right before would keep this safe.

> 
>> +
>> +    writel(timeout * 1000, data->reg_base + GXBB_WDT_TCNT_REG);
> 
>     wdt_dev->timeout = timeout;
> 
> Also, timeout may be larger than the maximum supported by the hardware,
> so you need to ensure that the value your write is not larger than
> GXBB_WDT_TCNT_SETUP_MASK.

Isn't already checked by the watchdog-core ?

> 
>> +
>> +    return 0;
>> +}
>> +
>> +static unsigned int meson_gxbb_wdt_get_timeleft(struct watchdog_device *wdt_dev)
>> +{
>> +    struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
>> +    unsigned long reg;
>> +
>> +    reg = readl(data->reg_base + GXBB_WDT_TCNT_REG);
>> +
>> +    return ((reg >> GXBB_WDT_TCNT_CNT_SHIFT)-
> 
> Space between operators, please.
> 
>> +            (reg & GXBB_WDT_TCNT_SETUP_MASK)) / 1000;
>> +}
>> +
>> +static const struct watchdog_ops meson_gxbb_wdt_ops = {
>> +    .start = meson_gxbb_wdt_start,
>> +    .stop = meson_gxbb_wdt_stop,
>> +    .ping = meson_gxbb_wdt_ping,
>> +    .set_timeout = meson_gxbb_wdt_set_timeout,
>> +    .get_timeleft = meson_gxbb_wdt_get_timeleft,
>> +};
>> +
>> +static const struct watchdog_info meson_gxbb_wdt_info = {
>> +    .identity = "meson-gxbb-wdt",
> 
> It is common here to provide a user readable string, which would be something
> like "Meson GXBB Watchdog".
> 
Why not.

[...]

>> +
>> +static int meson_gxbb_wdt_probe(struct platform_device *pdev)
>> +{
>> +    struct meson_gxbb_wdt *data;
>> +    struct resource *res;
>> +    int ret;
>> +
>> +    data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
>> +    if (!data)
>> +        return -ENOMEM;
>> +
>> +    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +    data->reg_base = devm_ioremap_resource(&pdev->dev, res);
>> +    if (IS_ERR(data->reg_base))
>> +        return PTR_ERR(data->reg_base);
>> +
>> +    data->clk = devm_clk_get(&pdev->dev, NULL);
>> +    if (IS_ERR(data->clk))
>> +        return PTR_ERR(data->clk);
>> +
>> +    clk_prepare_enable(data->clk);
>> +
>> +    platform_set_drvdata(pdev, data);
>> +
>> +    data->wdt_dev.parent = &pdev->dev;
>> +    data->wdt_dev.info = &meson_gxbb_wdt_info;
>> +    data->wdt_dev.ops = &meson_gxbb_wdt_ops;
>> +    data->wdt_dev.max_hw_heartbeat_ms = GXBB_WDT_TCNT_SETUP_MASK;
>> +    data->wdt_dev.min_timeout = 1;
>> +    data->wdt_dev.timeout = DEFAULT_TIMEOUT;
>> +    watchdog_set_drvdata(&data->wdt_dev, data);
>> +
>> +    /* Setup with 1ms timebase */
>> +    writel(((clk_get_rate(data->clk) / 1000) & GXBB_WDT_CTRL_DIV_MASK) |
>> +        GXBB_WDT_CTRL_EE_RESET |
>> +        GXBB_WDT_CTRL_CLK_EN |
>> +        GXBB_WDT_CTRL_CLKDIV_EN,
>> +        data->reg_base + GXBB_WDT_CTRL_REG);
>> +
>> +    meson_gxbb_wdt_set_timeout(&data->wdt_dev, data->wdt_dev.timeout);
>> +
>> +    ret = watchdog_register_device(&data->wdt_dev);
>> +    if (ret)
>> +        return ret;
> 
> clk_disable_unprepare() ?

Sure.

> 
>> +
>> +    return 0;
>> +}
>> +
>> +static int meson_gxbb_wdt_remove(struct platform_device *pdev)
>> +{
>> +    struct meson_gxbb_wdt *data = platform_get_drvdata(pdev);
>> +
>> +    watchdog_unregister_device(&data->wdt_dev);
>> +
> 
> clk_disable_unprepare() ?
Same.

Thanks,
Neil



From arnaud.pouliquen at st.com  Tue May 31 03:16:19 2016
From: arnaud.pouliquen at st.com (Arnaud Pouliquen)
Date: Tue, 31 May 2016 12:16:19 +0200
Subject: [PATCH v4 18/18] ARM: DT: STi: stihxxx-b2120: Add DT nodes for
 STi audio card
In-Reply-To: <1464192412-16386-20-git-send-email-peter.griffin@linaro.org>
References: <1464192412-16386-1-git-send-email-peter.griffin@linaro.org>
 <1464192412-16386-20-git-send-email-peter.griffin@linaro.org>
Message-ID: <574D6473.7050902@st.com>



On 05/25/2016 06:06 PM, Peter Griffin wrote:
> This patch enables the uniperif players 2 & 3 for b2120 boards
> and also adds the "simple-audio-card" device node to interconnect
> the SoC sound device and the codec.
> 
> Signed-off-by: Peter Griffin <peter.griffin at linaro.org>
> ---
>  arch/arm/boot/dts/stihxxx-b2120.dtsi | 40 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi b/arch/arm/boot/dts/stihxxx-b2120.dtsi
> index 722c63f..5297f21 100644
> --- a/arch/arm/boot/dts/stihxxx-b2120.dtsi
> +++ b/arch/arm/boot/dts/stihxxx-b2120.dtsi
> @@ -131,5 +131,45 @@
>  				dvb-card	= <STV0367_TDA18212_NIMA_1>;
>  			};
>  		};
> +
> +		sti_uni_player2: sti-uni-player at 2 {
> +			status = "okay";
> +		};
> +
> +		sti_uni_player3: sti-uni-player at 3 {
> +			status = "okay";
> +		};
enable sti-sasg-codec with spdif pinctrl
> +
> +		sound {
> +			compatible = "simple-audio-card";
> +			simple-audio-card,name = "sti audio card";
> +			status = "okay";
> +
> +			simple-audio-card,dai-link at 0 {
> +				/* DAC */
> +				format = "i2s";
> +				dai-tdm-slot-width = <32>;
clean dai-tdm-slot-width, not used.

Regards,
Arnaud
> +				mclk-fs = <256>;
> +				cpu {
> +					sound-dai = <&sti_uni_player2>;
> +				};
> +
> +				codec {
> +					sound-dai = <&sti_sasg_codec 1>;
> +				};
> +			};
> +			simple-audio-card,dai-link at 1 {
> +				/* SPDIF */
> +				format = "left_j";
> +				mclk-fs = <128>;
> +				cpu {
> +					sound-dai = <&sti_uni_player3>;
> +				};
> +
> +				codec {
> +					sound-dai = <&sti_sasg_codec 0>;
> +				};
> +			};
> +		};
>  	};
>  };
> 


From robin.murphy at arm.com  Tue May 31 03:17:04 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 31 May 2016 11:17:04 +0100
Subject: [BUG] Page allocation failures with newest kernels
In-Reply-To: <CAPv3WKcVsWBgHHC3UPNcbka2JUmN4CTw1Ym4BR1=1V9=B9av5Q@mail.gmail.com>
References: <CAPv3WKcVsWBgHHC3UPNcbka2JUmN4CTw1Ym4BR1=1V9=B9av5Q@mail.gmail.com>
Message-ID: <574D64A0.2070207@arm.com>

On 31/05/16 04:02, Marcin Wojtas wrote:
> Hi,
>
> After rebasing platform support of two different ARMv8 SoC's from v4.1
> baseline to v4.4 it occurred that stressed systems tend to have page
> allocation problems, related to creating new slabs:
>
> http://pastebin.com/FhRW5DsF
>
> Steps to reproduce:
> - use SATA drive (on-board or over PCIe) with 2 btrfs 50G partitions
> - run a couple of loops of following script:
> mount /dev/sd${1}1 /mnt
> mount /dev/sd${1}2 /mnt2
> i=0
> while [[ $i -lt ${2} ]]
> do
> echo -e "i = ${i}\n"
> dd if=/dev/zero of=/mnt/3g bs=3M count=1024 &
> dd if=/dev/zero of=/mnt/2g bs=2M count=1024 &
> dd if=/dev/zero of=/mnt/1g bs=1M count=1024 &
> dd if=/dev/zero of=/mnt2/2g bs=2M count=1024 &
> dd if=/dev/zero of=/mnt2/1g bs=1M count=1024 &
> dd if=/dev/zero of=/mnt2/3g bs=3M count=1024
> let "i++"
> done
>
> The issue also reproduced on v4.6. Usually problems occur within first
> iteration and then the rest is done without errors, also kernel remain
> stable. I got an information, that page alloc problem were observed
> also on Marvell ARMv7 platfrom (Armada38x).

I remember there were some issues around 4.2 with the revision of the 
arm64 atomic implementations affecting the cmpxchg_double() in SLUB, but 
those should all be fixed (and the symptoms tended to be considerably 
more fatal). A stronger candidate would be 97303480753e (which landed in 
4.4), which has various knock-on effects on the layout of SLUB internals 
- does fiddling with L1_CACHE_SHIFT make any difference?

Robin.

> About the debug itself - after adding simplest possible trace in
> trace/events/kmem.h (single argument u64 for counter or whatever kind
> of number), it was shown both on v4.1 and v4.4 following condition is
> achieved multiple times during test:
> In __alloc_pages_nodemask(), during the test kernel jumps huge amount
> of times (~250k times in v4.1 and ~570k in v4.4 per one script loop)
> into following 'unlikely' condition:
> page = get_page_from_freelist(alloc_mask, order, alloc_flags, &ac);
> if (unlikely(!page)) {
>      [...]
>      page = __alloc_pages_slowpath(alloc_mask, order, &ac);
> }
>
> The further difference is seen in __alloc_pages_slowpath().
> warn_alloc_page() (routine responsible for printing page alloc failure
> message) is reached via following condition:
> if (!can_direct_reclaim) {
>      [...]
>      goto nopage;
> }
> In v4.1 ~5 times and in v4.4 ~40 times per one script loop.
>
> Printing message however can be blocked by following condition in
> warn_alloc_fail():
> if ((gfp_mask & _GFP_NOWARN) || !_ratelimit(&nopage_rs) ||
>      debug_guardpage_minorder() > 0)
>          return;
> Only first two are relevant. As ratelimit is derived directly from
> CONFIG_HZ and this parameter differ between v4.1 and v4.4 (100 vs 250,
> also CONFIG_SCHED_HRTICK is enabled only in v4.4) the configs were
> swapped, but no change in behavior.
>
> Also within 'faulty' revision there is a difference, depending on
> filesystem used - with buildroot the dumps occur, but with same test
> under ubuntu - it's impossible see the failure output (and it's not a
> question of dmesg level:)). Comparing /proc/sys/vm contents didn't
> show anything meaningful.
>
> I tried to analyze changes around mm/ folder between v4.1 and v4.4
> that may cause such difference, but wasn't able to find out what may
> be causing the issue. Have anyone encountered such problems in recent
> revisions? I would be very grateful for any hint or comment. Also if
> any other data can be captured, please let know.
>
> Best regards,
> Marcin Wojtas
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>



From herbert at gondor.apana.org.au  Tue May 31 03:18:00 2016
From: herbert at gondor.apana.org.au (Herbert Xu)
Date: Tue, 31 May 2016 18:18:00 +0800
Subject: [PATCH] hwrng: stm32: fix maybe uninitialized variable warning
In-Reply-To: <1464255297-21090-1-git-send-email-mcoquelin.stm32@gmail.com>
References: <1464255297-21090-1-git-send-email-mcoquelin.stm32@gmail.com>
Message-ID: <20160531101800.GI15376@gondor.apana.org.au>

On Thu, May 26, 2016 at 11:34:57AM +0200, Maxime Coquelin wrote:
> This patch fixes the following warning:
> drivers/char/hw_random/stm32-rng.c: In function 'stm32_rng_read':
> drivers/char/hw_random/stm32-rng.c:82:19: warning: 'sr' may be used
>                                         uninitialized in this function
> 
> Reported-by: Sudip Mukherjee <sudip.mukherjee at codethink.co.uk>
> Suggested-by: Arnd Bergmann <arnd at arndb.de>
> Cc: Daniel Thompson <daniel.thompson at linaro.org>
> Signed-off-by: Maxime Coquelin <mcoquelin.stm32 at gmail.com>

Applied.
-- 
Email: Herbert Xu <herbert at gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt


From herbert at gondor.apana.org.au  Tue May 31 03:19:34 2016
From: herbert at gondor.apana.org.au (Herbert Xu)
Date: Tue, 31 May 2016 18:19:34 +0800
Subject: [PATCH v2 0/4] hw rng support for NSP SoC
In-Reply-To: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>
References: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>
Message-ID: <20160531101934.GM15376@gondor.apana.org.au>

On Fri, May 27, 2016 at 06:10:37AM -0400, Yendapally Reddy Dhananjaya Reddy wrote:
> This patchset contains the hw random number generator support for the
> Broadcom's NSP SoC. The block is similar to the block available in
> bcm2835 with different default interrupt mask value. Due to lack of
> documentation, I cannot confirm the interrupt mask register details
> in bcm2835. In an effort to not break the existing functionality of
> bcm2835, I used a different compatible string to mask the interrupt
> for NSP SoC. Please let me know. Also supported providing requested
> number of random numbers instead of static size of four bytes.
> 
> The first patch contains the documentation changes and the second patch
> contains the support for rng available in NSP SoC. The third patch
> contains the device tree changes for NSP SoC. The fourth patch contains
> the support for reading requested number of random numbers.
> 
> This patch set has been tested on NSP bcm958625HR board.
> This patch set is based on v4.6.0-rc1 and is available from github
> repo: https://github.com/Broadcom/cygnus-linux.git
> branch: nsp-rng-v2
> 
> Changes since v1

All applied.
-- 
Email: Herbert Xu <herbert at gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt


From dongas86 at gmail.com  Tue May 31 03:18:23 2016
From: dongas86 at gmail.com (Dong Aisheng)
Date: Tue, 31 May 2016 18:18:23 +0800
Subject: [PATCH 10/23] mmc: core: disable auto retune during card
 detection process
In-Reply-To: <573185FC.5060506@intel.com>
References: <1460741387-23815-1-git-send-email-aisheng.dong@nxp.com>
 <1460741387-23815-11-git-send-email-aisheng.dong@nxp.com>
 <571A1D85.3020200@intel.com>
 <CAA+hA=R9JfV4ScuM=OZ3VHdSiQiMO9io8mQQDNXfkTwNv7RVvg@mail.gmail.com>
 <5721B602.6010306@intel.com>
 <20160428132249.GB27560@shlinux2.ap.freescale.net>
 <57230515.9030602@intel.com>
 <20160429074258.GA28427@shlinux2.ap.freescale.net>
 <573185FC.5060506@intel.com>
Message-ID: <20160531101823.GB4096@shlinux2>

On Tue, May 10, 2016 at 09:55:56AM +0300, Adrian Hunter wrote:
> On 29/04/16 10:42, Dong Aisheng wrote:
> > And IMX6DL ARD is even worser due to it's using common
> > mmc_send_tuning() function.
> > root at imx6qdlsolo:~# 
> > root at imx6qdlsolo:~# [  129.462564] sysrq: SysRq : Changing Loglevel
> > [  129.466902] sysrq: Loglevel set to 8
> > [  131.616078] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
> > [  131.625311] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
> > [  131.632133] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
> > [  131.642121] mmc0: starting CMD13 arg 59b40000 flags 00000195
> > [  131.648925] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x0 ESDHC_TUNE_CTRL_STATUS 0x0
> > [  131.657818] mmc0: starting CMD19 arg 00000000 flags 00000035
> > [  131.663518] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
> > [  131.670835] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
> 
> You should stop here because -123 is -ENOMEDIUM
> 

Hi Adrian,

This is the last issue before V2.
I just tried the way you proposed (see detailed log below).

A few questions if we decide to let tuning routine to handle
the card remove case:
1) we may have to fix it for all platforms tuning code.

Below is the example i did for IMX uSDHC and common SDHCI.
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -757,7 +757,11 @@ static void esdhc_post_tuning(struct sdhci_host *host)
 
 static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
 {
-       int min, max, avg, ret;
+       int min, max, avg, ret, present;
+
+       present = host->mmc->ops->get_cd(host->mmc);
+       if (!present)
+               return -ENOMEDIUM;
 
        /* find the mininum delay first which can pass tuning */
        min = ESDHC_TUNE_CTRL_MIN;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0027b8707ebd..7b7545dd1a4b 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1767,6 +1767,11 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
        unsigned long flags;
        unsigned int tuning_count = 0;
        bool hs400_tuning;
+       int present;
+
+       present = mmc->ops->get_cd(mmc);
+       if (!present)
+               return -ENOMEDIUM;

And if we need fix all platforms, do you think we should
do it in MMC core mmc_execute_tuning()?

If yes, then we probably could move all the normal host CD check
before sending CMD in MMC core (__mmc_start_request()) as well?

2) MMC core will print out tuning error for card remove case
which is not before.
e.g
[   98.730597] mmc0: tuning execution failed: -123
We probably may need make it debug level since it's meaningless
for card removed case.

Detailed log below:
After the fix, card remove with calling mmc_send_tuning():
root at imx6qdlsolo:~# [   98.664049] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   98.673280] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
[   98.680102] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[   98.689560] mmc0: starting CMD13 arg aaaa0000 flags 00000195
[   98.696336] sdhci-esdhc-imx 2198000.usdhc: tunning with delay 0x0 ESDHC_TUNE_CTRL_STATUS 0x0
[   98.705407] mmc0: starting CMD19 arg 00000000 flags 00000035
[   98.711121] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 150 ms nsac 0
[   98.718144] mmc0: req done (CMD19): -123: 00000000 00000000 00000000 00000000
[   98.725351] mmc0:     0 bytes transferred: 0
[   98.730597] mmc0: tuning execution failed: -123
[   98.735255] mmc0: req failed (CMD13): -123, retrying...
[   98.740921] mmc0: req failed (CMD13): -123, retrying...
[   98.746344] mmc0: req failed (CMD13): -123, retrying...
[   98.751909] mmc0: req done (CMD13): -123: 00000000 00000000 00000000 00000000
[   98.759206] mmc0: card remove detected
[   98.763514] mmc0: card aaaa removed
[   98.780475] mmc0: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 1 timing 0
[   98.787730] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 0
[   99.028432] FAT-fs (mmcblk0p1): FAT read failed (blocknr 32)q


card remove with calling standard sdhci_execute_tuning():
root at imx6qdlsolo:~# [  210.555330] sysrq: SysRq : Changing Loglevel
[  210.559665] sysrq: Loglevel set to 8
[  212.244148] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[  212.253376] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 6
[  212.260199] sdhci-esdhc-imx 2198000.usdhc: desired SD clock: 198000000, actual: 198000000
[  212.269637] mmc0: starting CMD13 arg aaaa0000 flags 00000195
[  212.275399] mmc0: tuning execution failed: -123
[  212.280601] mmc0: req failed (CMD13): -123, retrying...
[  212.286094] mmc0: req failed (CMD13): -123, retrying...
[  212.291763] mmc0: req failed (CMD13): -123, retrying...
[  212.297226] mmc0: req done (CMD13): -123: 00000000 00000000 00000000 00000000
[  212.304899] mmc0: card remove detected
[  212.308948] mmc0: card aaaa removed
[  212.318162] mmc0: clock 0Hz busmode 2 powermode 0 cs 0 Vdd 0 width 1 timing 0
[  212.325415] sdhci-esdhc-imx 2198000.usdhc: change pinctrl state for uhs 0
[  212.580621] FAT-fs (mmcblk0p1): FAT read failed (blocknr 32)

Regards
Dong Aisheng



From mw at semihalf.com  Tue May 31 03:29:51 2016
From: mw at semihalf.com (Marcin Wojtas)
Date: Tue, 31 May 2016 12:29:51 +0200
Subject: [BUG] Page allocation failures with newest kernels
In-Reply-To: <574D64A0.2070207@arm.com>
References: <CAPv3WKcVsWBgHHC3UPNcbka2JUmN4CTw1Ym4BR1=1V9=B9av5Q@mail.gmail.com>
 <574D64A0.2070207@arm.com>
Message-ID: <CAPv3WKdYdwpi3k5eY86qibfprMFwkYOkDwHOsNydp=0sTV3mgg@mail.gmail.com>

Hi Robin,

>
> I remember there were some issues around 4.2 with the revision of the arm64
> atomic implementations affecting the cmpxchg_double() in SLUB, but those
> should all be fixed (and the symptoms tended to be considerably more fatal).
> A stronger candidate would be 97303480753e (which landed in 4.4), which has
> various knock-on effects on the layout of SLUB internals - does fiddling
> with L1_CACHE_SHIFT make any difference?
>

I'll check the commits, thanks. I forgot to add L1_CACHE_SHIFT was my
first suspect - I had spent a long time debugging network controller,
which stopped working because of this change - L1_CACHE_BYTES (and
hence NET_SKB_PAD) not fitting HW constraints. Anyway reverting it
didn't help at all for page alloc issue.

Best regards,
Marcin


From linus.walleij at linaro.org  Tue May 31 03:36:53 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:36:53 +0200
Subject: [PATCH 02/17] pinctrl: uniphier: rename function and variable
 names
In-Reply-To: <1464681923-7469-3-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-3-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdbbU4JicsL=sHpWW_gtHdQ7v+AAoMusLRTq_-JghL18hg@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> Make function/variable names match the file names for consistency.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:38:01 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:38:01 +0200
Subject: [PATCH 03/17] pinctrl: uniphier: fix register offsets for drive
 strength control
In-Reply-To: <1464681923-7469-4-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-4-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdZA5ETunZQPALebPajhvEs9X-NeyWV0xGYmr2GiTkkshg@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> These pin tables were generated by parsing hardware documents with
> a script, but the script had a bug.  Fix the register offsets.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:38:56 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:38:56 +0200
Subject: [PATCH 04/17] pinctrl: uniphier: set pinctrl_desc owner in common
 probe function
In-Reply-To: <1464681923-7469-5-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-5-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdbBE09Y6tDyx9VEwSxJF=4b1501ZZ49R=ia-HpZsjwj2w@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> The owner of the struct pinctrl_desc matches that of platform_driver.
> Set it in the common probe function.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:40:11 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:40:11 +0200
Subject: [PATCH 05/17] pinctrl: uniphier: set pinctrl_desc name in common
 probe function
In-Reply-To: <1464681923-7469-6-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-6-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdYNrKSULcoos3owH76+Bx0Kgi3mFh1YrESFZZhrwWF+wQ@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> Every SoC driver sets the same name for struct pinctrl_desc and
> platform_driver.  The common probe function can set desc->name
> instead of duplicating strings in each SoC driver.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:41:22 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:41:22 +0200
Subject: [PATCH 06/17] pinctrl: uniphier: allocate struct pinctrl_desc in
 probe function
In-Reply-To: <1464681923-7469-7-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-7-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdbGiH1+ShZ53CMJkuR7n0MANcdKhgAEYFua_TUbmS-_Yw@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> Currently, every SoC driver defines struct pinctrl_desc statically,
> i.e. it consumes memory footprint even if it is not probed.
>
> In multi-platform, many pinctrl drivers are linked (generally as
> built-in objects), although only one of them is actually used.
> So, it is reasonable to allocate memory dynamically where possible.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From hramrach at gmail.com  Tue May 31 03:44:54 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: Tue, 31 May 2016 12:44:54 +0200
Subject: [PATCH 5/5] RFC spi: sun4i: add DMA support
In-Reply-To: <20160530155016.GO29837@sirena.org.uk>
References: <cover.1464130597.git.hramrach@gmail.com>
 <ba0d6eb37cc4b0d2c46acbf9fcd7d644b3545ce8.1464130597.git.hramrach@gmail.com>
 <20160530112610.GJ29837@sirena.org.uk>
 <CAMuHMdVThvtqgFnyqoqypwwf1d81uu9NBo6-heTZBcvBxRevNw@mail.gmail.com>
 <20160530150343.GL29837@sirena.org.uk>
 <CAOMqctQb-YYprA7H5qCcYo2hxXiUhjW2z3JbZ3-FhbfcjFzBpw@mail.gmail.com>
 <20160530155016.GO29837@sirena.org.uk>
Message-ID: <CAOMqctQijjO2amwSmSMGp96KBRGrLb0fvXRwnybOEqvV3-HZ0g@mail.gmail.com>

On 30 May 2016 at 17:50, Mark Brown <broonie at kernel.org> wrote:
> On Mon, May 30, 2016 at 05:28:10PM +0200, Michal Suchanek wrote:
>> On 30 May 2016 at 17:03, Mark Brown <broonie at kernel.org> wrote:
>
>> > I really don't think it's worth caring too much about cases where the
>> > DMA driver hasn't been compiled in, it's not like SPI is the only thing
>
>> It's what the driver did to start with and it was requested to fall
>> back to non-DMA in the case DMA is not available.
>
> Why?  I really can't see any sensible use case for this that doesn't
> have a better solution available.

Of course, the solution is to compile in the DMA driver.

It's been argued that some drivers which use only short transfers will
just work.

>
>> It's possible to add a parameter like require_dma which could be used
>> to load the driver without dma if unset. If it was set by default then
>> driver ordering is not important so long as dma driver is loaded
>> eventually. Also an informative print that such parameter exists when
>> probing the driver is deferred would be helpful. It would probably
>> create quite a bit of log spam, however. The driver can be deferred
>> several times during boot.
>
> That seems fairly hacky, if we were going to do anything like that it
> should be the other way around so that we default to trying to use
> resources and even then it seems like something that should be handled
> at a framework level rather than having random options in individual
> drivers to ignore things.  Having things behave inconsistently between
> different drivers is going to lead to a worse user experience and if
> this is a good idea for one driver it seems like it'd be a good idea for
> all of them.

Hacky but doable if desirable. It's awesome for testing SPI transfer
fragmentation with different drivers ;-)

The previous discussion of this driver is here
http://thread.gmane.org/gmane.linux.kernel/2162327

Thanks

Michal


From linus.walleij at linaro.org  Tue May 31 03:45:44 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:45:44 +0200
Subject: [PATCH 07/17] pinctrl: uniphier: rename macros for drive strength
 control
In-Reply-To: <1464681923-7469-8-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-8-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdZGNU_fu+66tEheuE_bY0nW+M18BsQNQAsL2Qs7=g4S_g@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> The new ARMv8 SoC, PH1-LD20, supports more fine-grained drive
> strength control.  Some of the configuration registers on it have
> 3-bit width.
>
> The feature will be supported in the next commit, but a problem is
> that macro names are getting longer and longer in the current naming
> scheme.
>
> Before moving forward, this commit renames macros as follows:
>
>   UNIPHIER_PIN_DRV_4_8        -> UNIPHIER_PIN_DRV_1BIT
>   UNIPHIER_PIN_DRV_8_12_16_20 -> UNIPHIER_PIN_DRV_2BIT
>   UNIPHIER_PIN_DRV_FIXED_4    -> UNIPHIER_PIN_DRV_FIXED4
>   UNIPHIER_PIN_DRV_FIXED_5    -> UNIPHIER_PIN_DRV_FIXED5
>   UNIPHIER_PIN_DRV_FIXED_8    -> UNIPHIER_PIN_DRV_FIXED8
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:46:46 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:46:46 +0200
Subject: [PATCH 08/17] pinctrl: uniphier: support 3-bit drive strength
 control
In-Reply-To: <1464681923-7469-9-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-9-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdaDReMSb6uBi2ono_m-fnMoh9-p=Wj=XB5nF72FEmXmyA@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> The new ARMv8 SoC, PH1-LD20, supports more fine-grained drive
> strength control.  Drive strength of some pins are controlled by
> 3-bit width registers (8-level granularity).
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:47:58 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:47:58 +0200
Subject: [PATCH 09/17] pinctrl: uniphier: support pin configuration in
 sparse pin space
In-Reply-To: <1464681923-7469-10-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-10-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdYw=YCT6xtEdxXfxfSX-OWoGfzv2vbY5_+gKQ_uoDsjFA@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> Unfortunately, the pin number of the new SoC, PH1-LD11, is not
> contiguous.  The base frame work must be adjusted to support the new
> SoC pinctrl driver.  The pin_desc_get() exploits radix-tree for pin
> look-up, so it works more efficiently with sparse pin space.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:49:16 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:49:16 +0200
Subject: [PATCH 10/17] pinctrl: uniphier: introduce capability flag
In-Reply-To: <1464681923-7469-11-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-11-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdaGqCfNYcqNbWwLzcBngqrPX23JDOyQfeeBO+5ngxd1gQ@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> The core part of the UniPhier pinctrl driver needs to support a new
> capability for upcoming UniPhier ARMv8 SoCs.  This sometimes happens
> because pinctrl drivers include really SoC-specific stuff.
>
> This commit intends to tidy up SoC-specific parameters of the existing
> drivers before adding the new one.  Having just one flag would be
> better than adding a new struct member every time a new SoC-specific
> capability comes up.
>
> At this time, there is one flag, UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE.
> This capability (I'd say rather quirk) was added for PH1-Pro4 and
> PH1-Pro5 as requirement from a customer.  For those SoCs, one pin-mux
> setting is controlled by the combination of two separate registers; the
> LSB bits at register offset (8 * N) and the MSB bits at (8 * N + 4).
> Because it is impossible to update two separate registers atomically,
> the LOAD_PINCTRL register should be set in order to make the pin-mux
> settings really effective.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:50:22 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:50:22 +0200
Subject: [PATCH 11/17] pinctrl: uniphier: support per-pin input enable for
 new SoCs
In-Reply-To: <1464681923-7469-12-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-12-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdYUusdcLR2Q-KCwyg=_PDbLkrn22gvDx27nb9YhSdQnRw@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> Upcoming new pinctrl drivers for PH1-LD11 and PH-LD20 support input
> signal gating for each pin.  (While, existing ones only support it
> per pin-group.)  This commit updates the core part for that.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From holgerschurig at gmail.com  Tue May 31 03:51:03 2016
From: holgerschurig at gmail.com (Holger Schurig)
Date: Tue, 31 May 2016 12:51:03 +0200
Subject: [BUG] CONFIG_UNINLINE_SPIN_UNLOCK important for Cortex-A9
In-Reply-To: <4854518.jvbplH0SM0@wuerfel>
References: <874m9eoetu.fsf@gmail.com> <4854518.jvbplH0SM0@wuerfel>
Message-ID: <871t4io608.fsf@gmail.com>

> Have you tried multi_v7_defconfig? That also does not set 
> CONFIG_UNINLINE_SPIN_UNLOCK, but it is generally assumed to work.

Not yet, will try this (see below).



> Just to be sure: If you just enable UNINLINE_SPIN_UNLOCK (e.g. using
> a 'select' from arch/arm/mach-imx/Kconfig) without selecting PROVE_RCU,
> you say the bug is gone too?

Currently I select it indirectly. One person that tried to help me
turned on 29 different kernel debug options and the bug was gone. Then I
reduced this step by step to find out which of them was needed
minimally.

Still I don't think that it's an RCU issue. But it could of course be a
"Heisenbug".



> - Specific kernel version, and full list of patches applied (if any).
>   Have you reproduced this with a plain unpatched linux-4.6 kernel?

I'm not in love with vendor-kernels, so I use kernels from kernel.org.
When I started to chase the oops happened in 4.4.4, but the behavior was
also present in 4.5, 4.5.1 ... 4.5.4 and 4.6.

I have some patches applied, e.g. aufs4, one patch in the i.MX6Q FEC
ethernet driver and stuff to program the eMMC firmware. Nothing that
plays with rcu, spinlocks etc, e.g. no preempt or Linux-RT patches.

However, a vanilla kernel boots on my device (isn't device tree
nice?!?!?) and here I had the same behavior. I think that vanilla kernel
was 4.5.3, but I'm unsure.



> - Specific gcc version you used for building the kernel. Does this
>   happen with both old and new compilers, e.g. 4.7 and 6.1?

I don't have yet a gcc 6.1 armhf cross compiler.

My gcc used to be
http://releases.linaro.org/14.04/components/toolchain/binaries/gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux.tar.xz
but during the bug chase I switched to Debian's cross-gcc. It says it is
"arm-linux-gnueabihf-gcc ( 4.9.2-10) 4.9.2".

A kernel compiled by someone else with some "gcc-4.8
4.8.4-2ubuntu1~14.04" also had the same oopsing-behavior.



> - If it happens with an unpatched linux-4.6 and all gcc versions
>   with multi_v7_defconfig, we should try reproducing it on some
>   other quad-core Cortex-A9 (non-imx) platform with the same kernel
>   binary.

I will try to reproduce it, as said it can take between 3 to 24 hours.

I'll be using

- vanilla 4.6 without any patch
- ... and without any device-specific kernel module
- multi_v7_defconfig
- Debian 4.9.2 cross-compiler







BTW, here is one of the older oopses:

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.5.4 (linux at localhost) (gcc version 4.9.2 (Debian 4.9.2-10) ) #1 SMP Fri May 20 14:08:13 CEST 2016
[    0.000000] CPU: ARMv7 Processor [412fc09a] revision 10 (ARMv7), cr=10c5387d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] Machine model: PTX-C
[    0.000000] Memory policy: Data cache writealloc
[    0.000000] PERCPU: Embedded 12 pages/cpu @ef7aa000 s17024 r8192 d23936 u49152
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 260608
[    0.000000] Kernel command line:  console=ttymxc0,115200n8 skb_cpu=-1 printk.time=1  root=/dev/sdblk0p1 rootwait ro
[    0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
[    0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
[    0.000000] Memory: 1032768K/1048576K available (4451K kernel code, 140K rwdata, 1336K rodata, 228K init, 256K bss, 15808K reserved, 0K cma-reserved, 262144K highmem)
[    0.000000] Virtual kernel memory layout:
[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
[    0.000000]     vmalloc : 0xf0800000 - 0xff800000   ( 240 MB)
[    0.000000]     lowmem  : 0xc0000000 - 0xf0000000   ( 768 MB)
[    0.000000]     pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
[    0.000000]     modules : 0xbf000000 - 0xbfe00000   (  14 MB)
[    0.000000]       .text : 0xc0008000 - 0xc05aefbc   (5788 kB)
[    0.000000]       .init : 0xc05af000 - 0xc05e8000   ( 228 kB)
[    0.000000]       .data : 0xc05e8000 - 0xc060b340   ( 141 kB)
[    0.000000]        .bss : 0xc060e000 - 0xc064e364   ( 257 kB)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
[    0.000000] Hierarchical RCU implementation.
[    0.000000] Build-time adjustment of leaf fanout to 32.
[    0.000000] NR_IRQS:16 nr_irqs:16 16
[    0.000000] L2C-310 erratum 769419 enabled
[    0.000000] L2C-310 enabling early BRESP for Cortex-A9
[    0.000000] L2C-310 full line of zeros enabled for Cortex-A9
[    0.000000] L2C-310 ID prefetch enabled, offset 16 lines
[    0.000000] L2C-310 dynamic clock gating enabled, standby mode enabled
[    0.000000] L2C-310 cache controller enabled, 16 ways, 1024 kB
[    0.000000] L2C-310: CACHE_ID 0x410000c7, AUX_CTRL 0x76470001
[    0.000000] Switching to timer-based delay loop, resolution 333ns
[    0.000007] sched_clock: 32 bits at 3000kHz, resolution 333ns, wraps every 715827882841ns
[    0.000023] clocksource: mxc_timer1: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 637086815595 ns
[    0.000981] Console: colour dummy device 80x30
[    0.001000] Calibrating delay loop (skipped), value calculated using timer frequency.. 6.00 BogoMIPS (lpj=30000)
[    0.001014] pid_max: default: 32768 minimum: 301
[    0.001102] Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
[    0.001113] Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes)
[    0.001667] CPU: Testing write buffer coherency: ok
[    0.001920] Setting up static identity map for 0x10008200 - 0x10008258
[    0.004711] Brought up 4 CPUs
[    0.004723] SMP: Total of 4 processors activated (24.00 BogoMIPS).
[    0.004731] CPU: All CPU(s) started in SVC mode.
[    0.005185] devtmpfs: initialized
[    0.012919] VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 4
[    0.013222] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.013385] pinctrl core: initialized pinctrl subsystem
[    0.014308] NET: Registered protocol family 16
[    0.016024] DMA: preallocated 256 KiB pool for atomic coherent allocations
[    0.016712] CPU identified as i.MX6Q, silicon rev 1.5
[    0.036432] imx6q-pinctrl 20e0000.iomuxc: initialized IMX pinctrl driver
[    0.071626] SCSI subsystem initialized
[    0.071885] usbcore: registered new interface driver usbfs
[    0.071949] usbcore: registered new interface driver hub
[    0.072052] usbcore: registered new device driver usb
[    0.072859] i2c i2c-0: IMX I2C adapter registered
[    0.072877] i2c i2c-0: can't use DMA, using PIO instead.
[    0.073678] i2c i2c-2: IMX I2C adapter registered
[    0.073696] i2c i2c-2: can't use DMA, using PIO instead.
[    0.073848] pps_core: LinuxPPS API ver. 1 registered
[    0.073857] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti at linux.it>
[    0.073894] PTP clock support registered
[    0.074897] clocksource: Switched to clocksource mxc_timer1
[    0.085009] NET: Registered protocol family 2
[    0.085568] TCP established hash table entries: 8192 (order: 3, 32768 bytes)
[    0.085662] TCP bind hash table entries: 8192 (order: 4, 65536 bytes)
[    0.085808] TCP: Hash tables configured (established 8192 bind 8192)
[    0.085969] UDP hash table entries: 512 (order: 2, 16384 bytes)
[    0.086014] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
[    0.086214] NET: Registered protocol family 1
[    0.086560] RPC: Registered named UNIX socket transport module.
[    0.086571] RPC: Registered udp transport module.
[    0.086578] RPC: Registered tcp transport module.
[    0.086585] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.087730] futex hash table entries: 1024 (order: 4, 65536 bytes)
[    0.095320] aufs 4.x-rcN-20160301
[    0.096395] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 249)
[    0.096415] io scheduler noop registered (default)
[    0.096845] imx-weim 21b8000.weim: Driver registered.
[    0.098054] 2020000.serial: ttymxc0 at MMIO 0x2020000 (irq = 24, base_baud = 5000000) is a IMX
[    0.610190] console [ttymxc0] enabled
[    0.614540] 21e8000.serial: ttymxc1 at MMIO 0x21e8000 (irq = 293, base_baud = 5000000) is a IMX
[    0.623709] 21ec000.serial: ttymxc2 at MMIO 0x21ec000 (irq = 294, base_baud = 5000000) is a IMX
[    0.632917] 21f0000.serial: ttymxc3 at MMIO 0x21f0000 (irq = 295, base_baud = 5000000) is a IMX
[    0.642143] 21f4000.serial: ttymxc4 at MMIO 0x21f4000 (irq = 296, base_baud = 5000000) is a IMX
[    0.651203] [drm] Initialized drm 1.1.0 20060810
[    0.657567] imx-ipuv3 2400000.ipu: IPUv3H probed
[    0.663542] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[    0.670190] [drm] No driver support for vblank timestamp query.
[    0.676227] imx-drm display-subsystem: bound imx-ipuv3-crtc.2 (ops ipu_crtc_ops)
[    0.683689] imx-drm display-subsystem: bound imx-ipuv3-crtc.3 (ops ipu_crtc_ops)
[    0.691191] imx-drm display-subsystem: bound imx-ipuv3-crtc.6 (ops ipu_crtc_ops)
[    0.698682] imx-drm display-subsystem: bound imx-ipuv3-crtc.7 (ops ipu_crtc_ops)
[    0.706398] imx-drm display-subsystem: bound 2000000.aips-bus:ldb at 020e0008 (ops imx_ldb_ops)
[    0.725252] Console: switching to colour frame buffer device 100x37
[    0.734687] imx-drm display-subsystem: fb0:  frame buffer device
[    0.764913] [drm] Initialized imx-drm 1.0.0 20120507 on minor 0
[    0.770853] imx-ipuv3 2800000.ipu: IPUv3H probed
[    0.777626] loop: module loaded
[    0.780892] at24 2-0050: 256 byte 24c02 EEPROM, writable, 16 bytes/write
[    0.789037] CAN device driver interface
[    0.805354] pps pps0: new PPS source ptp0
[    0.813339] libphy: fec_enet_mii_bus: probed
[    0.818188] fec 2188000.ethernet eth0: registered PHC device 0
[    0.824239] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    0.830800] ehci-mxc: Freescale On-Chip EHCI Host driver
[    0.836311] usbcore: registered new interface driver usb-storage
[    0.847175] ci_hdrc ci_hdrc.0: EHCI Host Controller
[    0.852084] ci_hdrc ci_hdrc.0: new USB bus registered, assigned bus number 1
[    0.874919] ci_hdrc ci_hdrc.0: USB 2.0 started, EHCI 1.00
[    0.880486] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
[    0.887310] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    0.894551] usb usb1: Product: EHCI Host Controller
[    0.899454] usb usb1: Manufacturer: Linux 4.5.4 ehci_hcd
[    0.904783] usb usb1: SerialNumber: ci_hdrc.0
[    0.909733] hub 1-0:1.0: USB hub found
[    0.913519] hub 1-0:1.0: 1 port detected
[    0.921374] ci_hdrc ci_hdrc.1: EHCI Host Controller
[    0.926301] ci_hdrc ci_hdrc.1: new USB bus registered, assigned bus number 2
[    0.944924] ci_hdrc ci_hdrc.1: USB 2.0 started, EHCI 1.00
[    0.950482] usb usb2: New USB device found, idVendor=1d6b, idProduct=0002
[    0.957300] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    0.964542] usb usb2: Product: EHCI Host Controller
[    0.969439] usb usb2: Manufacturer: Linux 4.5.4 ehci_hcd
[    0.974768] usb usb2: SerialNumber: ci_hdrc.1
[    0.979653] hub 2-0:1.0: USB hub found
[    0.983438] hub 2-0:1.0: 1 port detected
[    0.992564] rtc-ds1307 2-0068: rtc core: registered ds1337 as rtc0
[    0.998843] i2c /dev entries driver
[    1.003552] imx2-wdt 20bc000.wdog: timeout 60 sec (nowayout=0)
[    1.009662] sdhci: Secure Digital Host Controller Interface driver
[    1.015886] sdhci: Copyright(c) Pierre Ossman
[    1.021215] sdhci-pltfm: SDHCI platform and OF driver helper
[    1.027564] /soc/aips-bus at 02100000/usdhc at 02194000: voltage-ranges unspecified
[    1.034728] sdhci-esdhc-imx 2194000.usdhc: Got CD GPIO
[    1.039901] sdhci-esdhc-imx 2194000.usdhc: Got WP GPIO
[    1.085110] mmc0: SDHCI controller on 2194000.usdhc [2194000.usdhc] using ADMA
[    1.095006] /soc/aips-bus at 02100000/usdhc at 0219c000: voltage-ranges unspecified
[    1.144917] mmc1: SDHCI controller on 219c000.usdhc [219c000.usdhc] using ADMA
[    1.163030] Netfilter messages via NETLINK v0.30.
[    1.170075] NET: Registered protocol family 17
[    1.176638] can: controller area network core (rev 20120528 abi 9)
[    1.184998] NET: Registered protocol family 29
[    1.189463] can: raw protocol (rev 20120528)
[    1.193744] can: broadcast manager protocol (rev 20120528 t)
[    1.199437] can: netlink gateway (rev 20130117) max_hops=1
[    1.207433] mmc0: new high speed SD card at address 0007
[    1.207453] Registering SWP/SWPB emulation handler
[    1.215948] imx_thermal 2000000.aips-bus:tempmon: Automotive CPU temperature grade - max:125C critical:120C passive:115C
[    1.229447] rtc-ds1307 2-0068: setting system clock to 2014-06-07 10:17:52 UTC (1402136272)
[    1.238198] sdblk0: mmc0:0007 SD01G 972 MiB 
[    1.244374]  sdblk0: p1 p4
[    1.255477] EXT4-fs (sdblk0p1): mounted filesystem with ordered data mode. Opts: (null)
[    1.263514] VFS: Mounted root (ext4 filesystem) readonly on device 179:1.
[    1.274643] devtmpfs: mounted
[    1.286615] Freeing unused kernel memory: 228K (c05af000 - c05e8000)
[    1.300598] mmc1: MAN_BKOPS_EN bit is not set
[    1.305029] usb 2-1: new high-speed USB device number 2 using ci_hdrc
[    1.325380] mmc1: new DDR MMC card at address 0001
[    1.330726] mmcblk0: mmc1:0001 W11016 7.13 GiB 
[    1.335546] mmcblk0boot0: mmc1:0001 W11016 partition 1 4.00 MiB
[    1.341690] mmcblk0boot1: mmc1:0001 W11016 partition 2 4.00 MiB
[    1.347877] mmcblk0rpmb: mmc1:0001 W11016 partition 3 4.00 MiB
[    1.355422]  mmcblk0: p1 p2 p3 p4
[    1.455412] usb 2-1: New USB device found, idVendor=0424, idProduct=2514
[    1.462162] usb 2-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[    1.470008] hub 2-1:1.0: USB hub found
[    1.473895] hub 2-1:1.0: 3 ports detected
[    1.519832] random: systemd urandom read with 10 bits of entropy available
[    1.531714] systemd[1]: systemd 217 running in system mode. (+PAM -AUDIT -SELINUX -IMA -APPARMOR -SMACK -SYSVINIT -UTMP -LIBCRYPTSETUP -GCRYPT -GNUTLS +ACL -XZ -LZ4 -SECCOMP +BLKID -ELFUTILS +KMOD -IDN )
[    1.550031] systemd[1]: Detected architecture 'arm'.
[    1.565955] systemd[1]: Set hostname to <ptxc>.
[    1.579164] systemd[1]: Initializing machine ID from random generator.
[    1.754933] usb 2-1.1: new full-speed USB device number 3 using ci_hdrc
[    1.810850] systemd[1]: Expecting device dev-ttymxc0.device...
[    1.816795] systemd[1]: Starting Forward Password Requests to Wall Directory Watch.
[    1.824757] systemd[1]: Started Forward Password Requests to Wall Directory Watch.
[    1.832482] systemd[1]: Starting Network.
[    1.836681] systemd[1]: Reached target Network.
[    1.841283] systemd[1]: Starting Dispatch Password Requests to Console Directory Watch.
[    1.849524] systemd[1]: Started Dispatch Password Requests to Console Directory Watch.
[    1.857523] systemd[1]: Starting -Paths.
[    1.861473] systemd[1]: Reached target -Paths.
[    1.865998] systemd[1]: Starting -Swap.
[    1.869870] systemd[1]: Reached target -Swap.
[    1.874281] systemd[1]: Starting Root Slice.
[    1.878694] systemd[1]: Created slice Root Slice.
[    1.883458] systemd[1]: Starting User and Session Slice.
[    1.888980] systemd[1]: Created slice User and Session Slice.
[    1.894769] systemd[1]: Starting Delayed Shutdown Socket.
[    1.900323] systemd[1]: Listening on Delayed Shutdown Socket.
[    1.902531] usb 2-1.1: New USB device found, idVendor=0a12, idProduct=0001
[    1.902539] usb 2-1.1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[    1.902544] usb 2-1.1: Product: CSR8510 A10
[    1.924561] systemd[1]: Starting /dev/initctl Compatibility Named Pipe.
[    1.931393] systemd[1]: Listening on /dev/initctl Compatibility Named Pipe.
[    1.938415] systemd[1]: Starting Journal Socket (/dev/log).
[    1.944144] systemd[1]: Listening on Journal Socket (/dev/log).
[    1.950171] systemd[1]: Starting udev Control Socket.
[    1.955390] systemd[1]: Listening on udev Control Socket.
[    1.960870] systemd[1]: Starting udev Kernel Socket.
[    1.965927] systemd[1]: Listening on udev Kernel Socket.
[    1.971295] systemd[1]: Starting Journal Socket.
[    1.976079] systemd[1]: Listening on Journal Socket.
[    1.981132] systemd[1]: Starting System Slice.
[    1.985766] systemd[1]: Created slice System Slice.
[    1.994921] usb 2-1.2: new high-speed USB device number 4 using ci_hdrc
[    2.001678] systemd[1]: Starting loadkeys...
[    2.035385] systemd[1]: Starting system-getty.slice.
[    2.040626] systemd[1]: Created slice system-getty.slice.
[    2.046165] systemd[1]: Starting system-serial\x2dgetty.slice.
[    2.052301] systemd[1]: Created slice system-serial\x2dgetty.slice.
[    2.058937] systemd[1]: Starting Remount /media/realroot writable...
[    2.067349] systemd[1]: Mounting Debug File System...
[    2.088733] systemd[1]: Starting Load Kernel Modules...
[    2.095797] systemd[1]: Mounted POSIX Message Queue File System.
[    2.102065] systemd[1]: Starting udev Coldplug all Devices...
[    2.110104] systemd[1]: Starting Create list of required static device nodes for the current kernel...
[    2.121877] systemd[1]: Mounted Huge Pages File System.
[    2.130883] systemd[1]: Starting Journal Service...
[    2.135409] usb 2-1.2: New USB device found, idVendor=0424, idProduct=9e00
[    2.135416] usb 2-1.2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[    2.151838] systemd[1]: Started Journal Service.
[    2.155238] input: beep as /devices/virtual/input/input0
[    2.161069] EXT4-fs (sdblk0p1): re-mounted. Opts: data=ordered
[    2.472678] systemd-journald[80]: Received request to flush runtime journal from PID 1
[    2.565712] smsc95xx v1.0.4
[    2.642784] smsc95xx 2-1.2:1.0 eth1: register 'smsc95xx' at usb-ci_hdrc.1-1.2, smsc95xx USB 2.0 Ethernet, 00:80:07:00:d6:aa
[    2.655791] usbcore: registered new interface driver smsc95xx
[    2.692008] flexcan 2090000.flexcan: device registered (reg_base=f0ba0000, irq=29)
[    2.708295] flexcan 2094000.flexcan: device registered (reg_base=f0bb0000, irq=30)
[    2.824757] Bluetooth: Core ver 2.21
[    2.828589] NET: Registered protocol family 31
[    2.833073] Bluetooth: HCI device and connection manager initialized
[    2.839512] Bluetooth: HCI socket layer initialized
[    2.844408] Bluetooth: L2CAP socket layer initialized
[    2.849514] Bluetooth: SCO socket layer initialized
[    2.895099] usbcore: registered new interface driver btusb
[    3.257897] SMSC LAN8710/LAN8720 2188000.ethernet:00: attached PHY driver [SMSC LAN8710/LAN8720] (mii_bus:phy_addr=2188000.ethernet:00, irq=-1)
[17827.758966] Unable to handle kernel paging request at virtual address 00001014
[17827.766279] pgd = ee09c000
[17827.769003] [00001014] *pgd=3eba3831, *pte=00000000, *ppte=00000000
[17827.775383] Internal error: Oops: 17 [#1] SMP ARM
[17827.780108] Modules linked in: usbhid btusb btrtl btbcm btintel bluetooth flexcan smsc95xx usbnet mii ptxc(O)
[17827.790242] CPU: 1 PID: 372 Comm: stress-ng-socke Tainted: G           O    4.5.4 #1
[17827.797995] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[17827.804536] task: ed614780 ti: eebba000 task.ti: eebba000
[17827.809977] PC is at __netif_receive_skb_core+0x328/0xa9c
[17827.815390] LR is at __netif_receive_skb+0x30/0x8c
[17827.820190] pc : [<c03a7634>]    lr : [<c03a9b60>]    psr: 60030013
[17827.820190] sp : eebbba10  ip : 00001014  fp : eebbba84
[17827.831672] r10: 00001000  r9 : c05eac94  r8 : c05eac8c
[17827.836900] r7 : 00000001  r6 : ef7b9840  r5 : ef7ba148  r4 : ee05ba30
[17827.843432] r3 : ef7b9894  r2 : 00001000  r1 : 2f1d4000  r0 : 00000001
[17827.849964] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
[17827.857101] Control: 10c5387d  Table: 3e09c04a  DAC: 00000055
[17827.862857] Process stress-ng-socke (pid: 372, stack limit = 0xeebba210)
[17827.869561] Stack: (0xeebbba10 to 0xeebbc000)
[17827.873923] ba00:                                     eebbba44 eebbba20 c0606280 00000000
[17827.882107] ba20: ee164780 ef7b9840 a0030193 ee05ba30 f4000100 f4001100 eebbba5c eebbba48
[17827.890291] ba40: c003fa50 c003f8d4 00000000 ef7b9840 c05e5840 c05ea5d4 eebbba7c ef7ba1b8
[17827.898475] ba60: ef7ba148 00000040 ef7ba1a4 ef7ba1b0 00000000 00000001 eebbba9c eebbba88
[17827.906658] ba80: c03a9b60 c03a7318 ef7ba148 ef7ba1b8 eebbbacc eebbbaa0 c03aaac4 c03a9b3c
[17827.914840] baa0: eebbbaf0 ef7ba1b8 c03aaa30 001abec9 0000012c c05ea100 00000040 eebbbaf0
[17827.923023] bac0: eebbbb2c eebbbad0 c03aa2cc c03aaa3c c05e9640 c057d614 c05eac8c c05eac8c
[17827.931206] bae0: c060b2e5 2f1d4000 c05e6140 ef7ba140 eebbbaf0 eebbbaf0 eebbbaf8 eebbbaf8
[17827.939391] bb00: 00000000 00000000 00000003 c05ea08c eebba000 00000101 40000003 c05ea080
[17827.947573] bb20: eebbbb8c eebbbb30 c0022444 c03aa0dc c03ac244 c03abeb0 00400040 c05ea100
[17827.955758] bb40: 001abec8 c0460bb8 0000000a c060e980 c05e2250 c05ea080 eebbbb30 eebba030
[17827.963941] bb60: c03acb9c 60030013 ee05ba30 eeb1c200 00000000 0000000e ef06a800 00000006
[17827.972124] bb80: eebbbba4 eebbbb90 c0022624 c002231c 00000008 00000200 eebbbbbc eebbbba8
[17827.980308] bba0: c00226e8 c00225c8 00000000 ee05ba30 eebbbbec eebbbbc0 c03e0360 c0022638
[17827.988492] bbc0: ee164780 0100007f a0030193 ee05ba30 0000ffff c0606280 ee2d2c00 ee2d2c00
[17827.996676] bbe0: eebbbc24 eebbbbf0 c03e1ed4 c03e01b8 c05e5840 c05ea5d4 eebbbc1c ee05ba30
[17828.004861] bc00: c0606280 0971f1b9 00000000 ee2d2c00 ef06a800 00000006 eebbbc74 eebbbc28
[17828.013043] bc20: c03e2a34 c03e1d94 c03e2060 c03e014c eebbbc5c eebbbc40 c0014c34 c0041be8
[17828.021225] bc40: c05f6fb0 c05ea740 f400010c eebbbc88 ee05ba30 ee2d2c00 c0606280 00000000
[17828.029407] bc60: ee3e5000 0000ab00 eebbbc94 eebbbc78 c03e2110 c03e291c 00000000 ee05ba30
[17828.037588] bc80: ee2d2c00 ee2d2e20 eebbbcd4 eebbbc98 c03e23fc c03e20dc eebbbcbc eebbbca8
[17828.045770] bca0: c03980bc c0397f94 ee2d2c00 ee2d2c00 ee05ba30 00000000 00000000 0000ab00
[17828.053953] bcc0: 0000ab00 00000006 eebbbd1c eebbbcd8 c03f9d08 c03e22cc 00000002 00000000
[17828.062134] bce0: 00000000 001abec7 001abec7 00000000 00000015 ee05b980 ee2d2c00 00040000
[17828.070317] bd00: 00000000 0000ffcb 000014b0 c05ec068 eebbbd84 eebbbd20 c03fa354 c03f9908
[17828.078500] bd20: c0013740 c00093b4 ed6b10a0 bebf9d4c 00000090 000346db c05ea100 00000000
[17828.086683] bd40: 00000002 ee2d2f94 00000005 00000000 00000000 0000ffcb 024000c0 ee2d2c00
[17828.094865] bd60: ee05b980 0000ffcb 00000000 9274572f eebbbe84 00000000 eebbbda4 eebbbd88
[17828.103047] bd80: c03fb2a4 c03fa168 02080020 ed6b0000 00000e50 ee2d2c00 eebbbdcc eebbbda8
[17828.111229] bda0: c03ea2e8 c03fb274 ee2d2c00 00000e50 000014b0 ee2d2c00 00000e50 0000ffcb
[17828.119413] bdc0: eebbbe4c eebbbdd0 c03edd44 c03ea1e4 0000ffcb c003ced8 00000002 00000660
[17828.127595] bde0: 00000000 eebbbe8c c05eac4c eebba000 00000001 00000000 ed614cb4 00000000
[17828.135777] be00: 00000000 ee2d2cb8 0000ffcb 000014b0 eebbbe8c 0000ffcb 7fffffff c0204128
[17828.143957] be20: c0046e40 ee2d2c00 00000000 00000000 00000000 eeb31840 eebba000 00000000
[17828.152138] be40: eebbbe6c eebbbe50 c0414204 c03ed628 d93a496c 00001036 eebbbeec 00000000
[17828.160321] be60: eebbbe7c eebbbe70 c0391600 c041417c eebbbed4 eebbbe80 c039169c c03915f0
[17828.168504] be80: eebbbf34 00000000 00000000 00000001 00000000 00000000 eebbbeec 00000000
[17828.176686] bea0: 00000000 00000000 00000000 eebbbf00 00000000 eeb31840 eebbbf80 00000000
[17828.184870] bec0: 00000000 c000f9c4 eebbbf3c eebbbed8 c00cc698 c039161c 000014b0 00000004
[17828.193052] bee0: eebda018 bebf89ac 000014b0 00000001 00000000 000014b0 eebbbee4 00000001
[17828.201237] bf00: eeb31840 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[17828.209420] bf20: eeb31840 000014b0 bebf89ac eebbbf80 eebbbf4c eebbbf40 c00cc6f0 c00cc61c
[17828.217603] bf40: eebbbf7c eebbbf50 c00cd3a0 c00cc6c8 c000f9c4 eebbbfb0 eebbbf7c eeb31840
[17828.225786] bf60: eeb31840 000014b0 bebf89ac c000f9c4 eebbbfa4 eebbbf80 c00cdea8 c00cd314
[17828.233968] bf80: 00000000 00000000 00000004 0002a1e8 b6fd2140 00000004 00000000 eebbbfa8
[17828.242150] bfa0: c000f820 c00cde68 00000004 0002a1e8 00000004 bebf89ac 000014b0 bebfa9ac
[17828.250332] bfc0: 00000004 0002a1e8 b6fd2140 00000004 000014b0 00000177 0002a1f0 00000003
[17828.258514] bfe0: 00000000 bebf88e4 00014a57 b6f0d4d6 40030030 00000004 80488d08 2125c40e
[17828.266690] Backtrace: 
[17828.269173] [<c03a730c>] (__netif_receive_skb_core) from [<c03a9b60>] (__netif_receive_skb+0x30/0x8c)
[17828.278397]  r10:00000001 r9:00000000 r8:ef7ba1b0 r7:ef7ba1a4 r6:00000040 r5:ef7ba148
[17828.286301]  r4:ef7ba1b8
[17828.288863] [<c03a9b30>] (__netif_receive_skb) from [<c03aaac4>] (process_backlog+0x94/0x140)
[17828.297390]  r4:ef7ba1b8 r3:ef7ba148
[17828.301008] [<c03aaa30>] (process_backlog) from [<c03aa2cc>] (net_rx_action+0x1fc/0x2f0)
[17828.309101]  r10:eebbbaf0 r9:00000040 r8:c05ea100 r7:0000012c r6:001abec9 r5:c03aaa30
[17828.317014]  r4:ef7ba1b8 r3:eebbbaf0
[17828.320637] [<c03aa0d0>] (net_rx_action) from [<c0022444>] (__do_softirq+0x134/0x254)
[17828.328470]  r10:c05ea080 r9:40000003 r8:00000101 r7:eebba000 r6:c05ea08c r5:00000003
[17828.336381]  r4:00000000
[17828.338937] [<c0022310>] (__do_softirq) from [<c0022624>] (do_softirq+0x68/0x70)
[17828.346334]  r10:00000006 r9:ef06a800 r8:0000000e r7:00000000 r6:eeb1c200 r5:ee05ba30
[17828.354238]  r4:60030013
[17828.356797] [<c00225bc>] (do_softirq) from [<c00226e8>] (__local_bh_enable_ip+0xbc/0xd0)
[17828.364890]  r4:00000200 r3:00000008
[17828.368520] [<c002262c>] (__local_bh_enable_ip) from [<c03e0360>] (ip_finish_output2+0x1b4/0x3b8)
[17828.377395]  r5:ee05ba30 r4:00000000
[17828.381005] [<c03e01ac>] (ip_finish_output2) from [<c03e1ed4>] (ip_finish_output+0x14c/0x20c)
[17828.389531]  r8:ee2d2c00 r7:ee2d2c00 r6:c0606280 r5:0000ffff r4:ee05ba30
[17828.396321] [<c03e1d88>] (ip_finish_output) from [<c03e2a34>] (ip_output+0x124/0x130)
[17828.404153]  r10:00000006 r9:ef06a800 r8:ee2d2c00 r7:00000000 r6:0971f1b9 r5:c0606280
[17828.412061]  r4:ee05ba30
[17828.414617] [<c03e2910>] (ip_output) from [<c03e2110>] (ip_local_out+0x40/0x44)
[17828.421927]  r9:0000ab00 r8:ee3e5000 r7:00000000 r6:c0606280 r5:ee2d2c00 r4:ee05ba30
[17828.429753] [<c03e20d0>] (ip_local_out) from [<c03e23fc>] (ip_queue_xmit+0x13c/0x3a4)
[17828.437586]  r6:ee2d2e20 r5:ee2d2c00 r4:ee05ba30 r3:00000000
[17828.443317] [<c03e22c0>] (ip_queue_xmit) from [<c03f9d08>] (tcp_transmit_skb+0x40c/0x860)
[17828.451496]  r10:00000006 r9:0000ab00 r8:0000ab00 r7:00000000 r6:00000000 r5:ee05ba30
[17828.459412]  r4:ee2d2c00
[17828.461965] [<c03f98fc>] (tcp_transmit_skb) from [<c03fa354>] (tcp_write_xmit+0x1f8/0xe80)
[17828.470231]  r10:c05ec068 r9:000014b0 r8:0000ffcb r7:00000000 r6:00040000 r5:ee2d2c00
[17828.478131]  r4:ee05b980
[17828.480686] [<c03fa15c>] (tcp_write_xmit) from [<c03fb2a4>] (__tcp_push_pending_frames+0x3c/0xa4)
[17828.489559]  r10:00000000 r9:eebbbe84 r8:9274572f r7:00000000 r6:0000ffcb r5:ee05b980
[17828.497464]  r4:ee2d2c00
[17828.500027] [<c03fb268>] (__tcp_push_pending_frames) from [<c03ea2e8>] (tcp_push+0x110/0x134)
[17828.508552]  r4:ee2d2c00
[17828.511114] [<c03ea1d8>] (tcp_push) from [<c03edd44>] (tcp_sendmsg+0x728/0xa7c)
[17828.518425]  r7:0000ffcb r6:00000e50 r5:ee2d2c00 r4:000014b0
[17828.524157] [<c03ed61c>] (tcp_sendmsg) from [<c0414204>] (inet_sendmsg+0x94/0xc8)
[17828.531640]  r10:00000000 r9:eebba000 r8:eeb31840 r7:00000000 r6:00000000 r5:00000000
[17828.539540]  r4:ee2d2c00
[17828.542117] [<c0414170>] (inet_sendmsg) from [<c0391600>] (sock_sendmsg+0x1c/0x2c)
[17828.549688]  r5:00000000 r4:eebbbeec
[17828.553299] [<c03915e4>] (sock_sendmsg) from [<c039169c>] (sock_write_iter+0x8c/0xc0)
[17828.561164] [<c0391610>] (sock_write_iter) from [<c00cc698>] (new_sync_write+0x88/0xac)
[17828.569169]  r8:c000f9c4 r7:00000000 r6:00000000 r5:eebbbf80 r4:eeb31840
[17828.575947] [<c00cc610>] (new_sync_write) from [<c00cc6f0>] (__vfs_write+0x34/0x40)
[17828.583605]  r7:eebbbf80 r6:bebf89ac r5:000014b0 r4:eeb31840
[17828.589335] [<c00cc6bc>] (__vfs_write) from [<c00cd3a0>] (vfs_write+0x98/0x16c)
[17828.596652] [<c00cd308>] (vfs_write) from [<c00cdea8>] (SyS_write+0x4c/0xa8)
[17828.603702]  r8:c000f9c4 r7:bebf89ac r6:000014b0 r5:eeb31840 r4:eeb31840
[17828.610494] [<c00cde5c>] (SyS_write) from [<c000f820>] (ret_fast_syscall+0x0/0x34)
[17828.618064]  r7:00000004 r6:b6fd2140 r5:0002a1e8 r4:00000004
[17828.623787] Code: e1a03006 e12fff3c e51b4058 e1a0200a (e59a3014) 
[17828.633464] ---[ end trace 292e54b4b334809b ]---
[17828.638144] Kernel panic - not syncing: Fatal exception in interrupt
[17828.644528] CPU0: stopping
[17828.647267] CPU: 0 PID: 380 Comm: stress-ng-socke Tainted: G      D    O    4.5.4 #1
[17828.655012] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[17828.661542] Backtrace: 
[17828.664032] [<c0012a24>] (dump_backtrace) from [<c0012c20>] (show_stack+0x18/0x1c)
[17828.671604]  r6:60030193 r5:c05f6f00 r4:00000000 r3:00000000
[17828.677331] [<c0012c08>] (show_stack) from [<c01fe6ac>] (dump_stack+0x9c/0xb0)
[17828.684561] [<c01fe610>] (dump_stack) from [<c0014c80>] (handle_IPI+0x170/0x190)
[17828.691957]  r6:00000000 r5:00000000 r4:c060e2d8 r3:c05e2da4
[17828.697678] [<c0014b10>] (handle_IPI) from [<c0009434>] (gic_handle_irq+0x8c/0x90)
[17828.705248]  r7:eebd5cf8 r6:f400010c r5:c05ea740 r4:c05f6fb0
[17828.710969] [<c00093a8>] (gic_handle_irq) from [<c0013740>] (__irq_svc+0x40/0x54)
[17828.718454] Exception stack(0xeebd5cf8 to 0xeebd5d40)
[17828.723508] 5ce0:                                                       bebf992c ed69bc50
[17828.731689] 5d00: 00001000 43434343 43434343 43434343 43434343 43434343 43434343 ed69b310
[17828.739870] 5d20: bebf900c eebd5dac 43434343 eebd5d4c 43434343 c01fb6d0 20030013 ffffffff
[17828.748047]  r9:ed69b310 r8:43434343 r7:eebd5d2c r6:ffffffff r5:20030013 r4:c01fb6d0
[17828.755883] [<c020ff58>] (copy_page_to_iter) from [<c039e984>] (skb_copy_datagram_iter+0xdc/0x1b8)
[17828.764842]  r10:eea24e30 r9:00000001 r8:00000660 r7:00000660 r6:00005350 r5:000019a0
[17828.772743]  r4:000019a0
[17828.775304] [<c039e8a8>] (skb_copy_datagram_iter) from [<c03eb0fc>] (tcp_recvmsg+0x518/0x9d4)
[17828.783828]  r10:00000000 r9:ee2d6bd8 r8:00000000 r7:ee2d6880 r6:00002000 r5:00000000
[17828.791729]  r4:eea24e30
[17828.794286] [<c03eabe4>] (tcp_recvmsg) from [<c0413b78>] (inet_recvmsg+0x9c/0xb0)
[17828.801768]  r10:00000000 r9:eebd4000 r8:c000f9c4 r7:ec909480 r6:eebd5f00 r5:00000000
[17828.809669]  r4:eebd5e8c
[17828.812227] [<c0413adc>] (inet_recvmsg) from [<c0390458>] (sock_read_iter+0x94/0xc0)
[17828.819971]  r6:eebd5f00 r5:00000000 r4:eebd5eec
[17828.824644] [<c03903c4>] (sock_read_iter) from [<c00cc5b0>] (new_sync_read+0x88/0xa8)
[17828.832474]  r7:00000000 r6:00000000 r5:eebd5f80 r4:ec909480
[17828.838196] [<c00cc528>] (new_sync_read) from [<c00cc604>] (__vfs_read+0x34/0x40)
[17828.845679]  r7:bebf89ac r6:eebd5f80 r5:ec909480 r4:bebf89ac
[17828.851401] [<c00cc5d0>] (__vfs_read) from [<c00cd280>] (vfs_read+0x84/0x10c)
[17828.858541] [<c00cd1fc>] (vfs_read) from [<c00cde00>] (SyS_read+0x4c/0xa8)
[17828.865417]  r9:eebd4000 r8:c000f9c4 r7:bebf89ac r6:00002000 r5:ec909480 r4:ec909480
[17828.873238] [<c00cddb4>] (SyS_read) from [<c000f820>] (ret_fast_syscall+0x0/0x34)
[17828.880721]  r7:00000003 r6:00000003 r5:00000065 r4:bebf8920
[17828.886441] CPU3: stopping
[17828.889157] CPU: 3 PID: 378 Comm: stress-ng-socke Tainted: G      D    O    4.5.4 #1
[17828.896903] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[17828.903431] Backtrace: 
[17828.905902] [<c0012a24>] (dump_backtrace) from [<c0012c20>] (show_stack+0x18/0x1c)
[17828.913472]  r6:60030193 r5:c05f6f00 r4:00000000 r3:00000000
[17828.919195] [<c0012c08>] (show_stack) from [<c01fe6ac>] (dump_stack+0x9c/0xb0)
[17828.926424] [<c01fe610>] (dump_stack) from [<c0014c80>] (handle_IPI+0x170/0x190)
[17828.933820]  r6:00000000 r5:00000003 r4:c060e2d8 r3:c05e2da4
[17828.939539] [<c0014b10>] (handle_IPI) from [<c0009434>] (gic_handle_irq+0x8c/0x90)
[17828.947109]  r7:eea2dd60 r6:f400010c r5:c05ea740 r4:c05f6fb0
[17828.952829] [<c00093a8>] (gic_handle_irq) from [<c0013740>] (__irq_svc+0x40/0x54)
[17828.960314] Exception stack(0xeea2dd60 to 0xeea2dda8)
[17828.965370] dd60: ee2d0b00 eea24300 00000000 00000000 ee2d0b00 eea24300 00001700 0000ffcb
[17828.973552] dd80: 61cc4f57 eea2de84 00000000 eea2ddcc eea2ddd0 eea2ddb0 c03edfac c03ea444
[17828.981730] dda0: 60030013 ffffffff
[17828.985220]  r9:eea2de84 r8:61cc4f57 r7:eea2dd94 r6:ffffffff r5:60030013 r4:c03ea444
[17828.993044] [<c03ea424>] (tcp_tx_timestamp) from [<c03edfac>] (tcp_sendmsg+0x990/0xa7c)
[17829.001048]  r6:00001700 r5:ee2d0b00 r4:00001d60 r3:00001d60
[17829.006769] [<c03ed61c>] (tcp_sendmsg) from [<c0414204>] (inet_sendmsg+0x94/0xc8)
[17829.014252]  r10:00000000 r9:eea2c000 r8:ed6469c0 r7:00000000 r6:00000000 r5:00000000
[17829.022154]  r4:ee2d0b00
[17829.024709] [<c0414170>] (inet_sendmsg) from [<c0391600>] (sock_sendmsg+0x1c/0x2c)
[17829.032278]  r5:00000000 r4:eea2deec
[17829.035888] [<c03915e4>] (sock_sendmsg) from [<c039169c>] (sock_write_iter+0x8c/0xc0)
[17829.043727] [<c0391610>] (sock_write_iter) from [<c00cc698>] (new_sync_write+0x88/0xac)
[17829.051730]  r8:c000f9c4 r7:00000000 r6:00000000 r5:eea2df80 r4:ed6469c0
[17829.058509] [<c00cc610>] (new_sync_write) from [<c00cc6f0>] (__vfs_write+0x34/0x40)
[17829.066165]  r7:eea2df80 r6:bebf89ac r5:00001d60 r4:ed6469c0
[17829.071885] [<c00cc6bc>] (__vfs_write) from [<c00cd3a0>] (vfs_write+0x98/0x16c)
[17829.079199] [<c00cd308>] (vfs_write) from [<c00cdea8>] (SyS_write+0x4c/0xa8)
[17829.086247]  r8:c000f9c4 r7:bebf89ac r6:00001d60 r5:ed6469c0 r4:ed6469c0
[17829.093023] [<c00cde5c>] (SyS_write) from [<c000f820>] (ret_fast_syscall+0x0/0x34)
[17829.100593]  r7:00000004 r6:b6fd2160 r5:0002a1e8 r4:00000004
[17829.106311] CPU2: stopping
[17829.109027] CPU: 2 PID: 376 Comm: stress-ng-socke Tainted: G      D    O    4.5.4 #1
[17829.116772] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[17829.123300] Backtrace: 
[17829.125772] [<c0012a24>] (dump_backtrace) from [<c0012c20>] (show_stack+0x18/0x1c)
[17829.133342]  r6:60030193 r5:c05f6f00 r4:00000000 r3:00000000
[17829.139065] [<c0012c08>] (show_stack) from [<c01fe6ac>] (dump_stack+0x9c/0xb0)
[17829.146293] [<c01fe610>] (dump_stack) from [<c0014c80>] (handle_IPI+0x170/0x190)
[17829.153689]  r6:00000000 r5:00000002 r4:c060e2d8 r3:c05e2da4
[17829.159409] [<c0014b10>] (handle_IPI) from [<c0009434>] (gic_handle_irq+0x8c/0x90)
[17829.166979]  r7:ee3ddd28 r6:f400010c r5:c05ea740 r4:c05f6fb0
[17829.172699] [<c00093a8>] (gic_handle_irq) from [<c0013740>] (__irq_svc+0x40/0x54)
[17829.180183] Exception stack(0xee3ddd28 to 0xee3ddd70)
[17829.185240] dd20:                   ecac7cd0 bebf976c 00000030 5a5a5a5a 5a5a5a5a 5a5a5a5a
[17829.193422] dd40: 5a5a5a5a 5a5a5a5a 5a5a5a5a ecac7d80 00000000 ee3dddcc 5a5a5a5a ee3ddd7c
[17829.201601] dd60: 5a5a5a5a c01fb2c0 20030013 ffffffff
[17829.206653]  r9:ecac7d80 r8:5a5a5a5a r7:ee3ddd5c r6:ffffffff r5:20030013 r4:c01fb2c0
[17829.214477] [<c020e03c>] (copy_from_iter) from [<c03ede00>] (tcp_sendmsg+0x7e4/0xa7c)
[17829.222307]  r10:00000000 r9:ee3dde84 r8:00006f30 r7:00005580 r6:00000e50 r5:ee36ac00
[17829.230209]  r4:ee2d9680 r3:00000000
[17829.233819] [<c03ed61c>] (tcp_sendmsg) from [<c0414204>] (inet_sendmsg+0x94/0xc8)
[17829.241302]  r10:00000000 r9:ee3dc000 r8:ee9b6c00 r7:00000000 r6:00000000 r5:00000000
[17829.249204]  r4:ee36ac00
[17829.251759] [<c0414170>] (inet_sendmsg) from [<c0391600>] (sock_sendmsg+0x1c/0x2c)
[17829.259328]  r5:00000000 r4:ee3ddeec
[17829.262939] [<c03915e4>] (sock_sendmsg) from [<c039169c>] (sock_write_iter+0x8c/0xc0)
[17829.270778] [<c0391610>] (sock_write_iter) from [<c00cc698>] (new_sync_write+0x88/0xac)
[17829.278781]  r8:c000f9c4 r7:00000000 r6:00000000 r5:ee3ddf80 r4:ee9b6c00
[17829.285559] [<c00cc610>] (new_sync_write) from [<c00cc6f0>] (__vfs_write+0x34/0x40)
[17829.293216]  r7:ee3ddf80 r6:bebf89ac r5:00001c80 r4:ee9b6c00
[17829.298936] [<c00cc6bc>] (__vfs_write) from [<c00cd3a0>] (vfs_write+0x98/0x16c)
[17829.306250] [<c00cd308>] (vfs_write) from [<c00cdea8>] (SyS_write+0x4c/0xa8)
[17829.313299]  r8:c000f9c4 r7:bebf89ac r6:00001c80 r5:ee9b6c00 r4:ee9b6c00
[17829.320077] [<c00cde5c>] (SyS_write) from [<c000f820>] (ret_fast_syscall+0x0/0x34)
[17829.327646]  r7:00000004 r6:b6fd2158 r5:0002a1e8 r4:00000004
[17829.333369] ---[ end Kernel panic - not syncing: Fatal exception in interrupt


From linus.walleij at linaro.org  Tue May 31 03:51:39 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:51:39 +0200
Subject: [PATCH 12/17] pinctrl: uniphier: support pin configuration for
 dedicated pins
In-Reply-To: <1464681923-7469-13-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-13-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdY9wRMJddR+yEqqCRwjvgnXtkiVb9bkvv1+-ugq1V7-Xw@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> PH1-LD4 and PH1-sLD8 SoCs have pins that support pin configuration
> (pin biasing, drive strength control), but not pin-muxing.
>
> Allow to fill the mux value table with -1 for those pins; pins with
> mux value -1 will be skipped in the pin-mux set function.  The mux
> value type should be changed from "unsigned" to "int" in order to
> accommodate -1 as a special case.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:52:36 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:52:36 +0200
Subject: [PATCH 13/17] pinctrl: uniphier: add dedicated pins to pin tables
 of PH1-LD4/sLD8
In-Reply-To: <1464681923-7469-14-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-14-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdaFsLD6+8sv4N5O7i1td4YeDS38aVb4SjmHi+QwfkQgsQ@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> These pins do not support pin-muxing, but it is useful to support
> pin configuration for them.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:53:40 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:53:40 +0200
Subject: [PATCH 14/17] pinctrl: uniphier: add System Bus pin-mux settings
In-Reply-To: <1464681923-7469-15-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-15-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdauPKZJFkVHx4S8M1ze8jXDYN17sqG68H4hK-WyZNZU4w@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> This is needed to get access to UniPhier System Bus (external bus).
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:55:24 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:55:24 +0200
Subject: [PATCH 15/17] pinctrl: uniphier: allow to have pinctrl node under
 syscon node
In-Reply-To: <1464681923-7469-16-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-16-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdZ3tLp3LeR6Q1YvgvKN8B0NuRzfcg_K+smo3_-TGCvr8Q@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> Currently, the UniPhier pinctrl driver itself is a syscon, but it
> turned out much more reasonable to make it a child node of a syscon
> because our syscon node consists of a bunch of system configuration
> registers, not only pinctrl, but also phy, and misc registers.
> It is difficult to split the node.
>
> To allow to migrate to the new DT structure, this commit adds new
> compatible strings to not disturb the existing DT.  After a while,
> the old binding will be removed.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied, I guess if there is too much fuzz about the DT
bindings getting incompatible I would have to revert it.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:57:18 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:57:18 +0200
Subject: [PATCH 16/17] pinctrl: uniphier: add UniPhier PH1-LD11 pinctrl
 driver
In-Reply-To: <1464681923-7469-17-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-17-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkda5K=FCqcMk4p91C54Hx=XEL3wEmsHtnAJipSeZqW_Pvg@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> Add pin configuration and pinmux support for UniPhier PH1-LD11 SoC.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:58:46 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:58:46 +0200
Subject: [PATCH 17/17] pinctrl: uniphier: add UniPhier PH1-LD20 pinctrl
 driver
In-Reply-To: <1464681923-7469-18-git-send-email-yamada.masahiro@socionext.com>
References: <1464681923-7469-1-git-send-email-yamada.masahiro@socionext.com>
 <1464681923-7469-18-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdbAP3RLUSd=NqEzOVk2fib4UOM1NBj7X_jdj4a+8cYjDg@mail.gmail.com>

On Tue, May 31, 2016 at 10:05 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> Add pin configuration and pinmux support for UniPhier PH1-LD20 SoC.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Tue May 31 03:59:51 2016
From: linus.walleij at linaro.org (Linus Walleij)
Date: Tue, 31 May 2016 12:59:51 +0200
Subject: [PATCH] pinctrl: oxnas: Rename pinctrl_utils_dt_free_map to
 pinctrl_utils_free_map
In-Reply-To: <1464687375-1370-1-git-send-email-narmstrong@baylibre.com>
References: <1464687375-1370-1-git-send-email-narmstrong@baylibre.com>
Message-ID: <CACRpkdb0yrqbyk8k38DpZ1KP1WvPv6qxsDNgXm9XHCsiJRgmmg@mail.gmail.com>

On Tue, May 31, 2016 at 11:36 AM, Neil Armstrong
<narmstrong at baylibre.com> wrote:

> Rename pinctrl_utils_dt_free_map to pinctrl_utils_free_map, introduced in
> d32f7fd3bbc3 ("pinctrl: Rename pinctrl_utils_dt_free_map to pinctrl_utils_free_map")
> but not reported into oxnas driver.
>
> Fixes: 611dac1e48a4 ("pinctrl: Add Oxford Semiconductor OXNAS pinctrl and gpio driver")
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>

Patch applied.

Yours,
Linus Walleij


From sergei.shtylyov at cogentembedded.com  Tue May 31 04:07:48 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Tue, 31 May 2016 14:07:48 +0300
Subject: [PATCH v2,1/5] dt-bindings: mt8173-xhci: support host side of
 dual-role mode
In-Reply-To: <1464673962-11506-2-git-send-email-chunfeng.yun@mediatek.com>
References: <1464673962-11506-1-git-send-email-chunfeng.yun@mediatek.com>
 <1464673962-11506-2-git-send-email-chunfeng.yun@mediatek.com>
Message-ID: <7828750b-f5ac-6fa0-ee6e-d4775c227e1a@cogentembedded.com>

Hello.

On 5/31/2016 8:52 AM, Chunfeng Yun wrote:

> Some resources, such as IPPC register etc, shared with device
> driver are moved into common glue layer when xHCI driver is the
> host side of dual-role mode and they should be changed as optional
> properties if they are required ones before. For clarity, add
> a new part of binding to support host side of dual-role mode.
>
> Additionally add optional properties of pinctrl for host only mode
>
> Signed-off-by: Chunfeng Yun <chunfeng.yun at mediatek.com>
> ---
>  .../devicetree/bindings/usb/mt8173-xhci.txt        |   48 ++++++++++++++++++++
>  1 file changed, 48 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
> index b3a7ffa..542e3fa 100644
> --- a/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
> +++ b/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
> @@ -2,6 +2,14 @@ MT8173 xHCI
>
>  The device node for Mediatek SOC USB3.0 host controller
>
> +There are two scenarios: the first one only supports xHCI driver;
> +the second one supports dual-role mode, and the host is based on xHCI
> +driver. Take account of backward compatibility, we divide bindings
> +into two parts.
> +
> +1st: only supports xHCI driver
> +------------------------------------------------------------------------
> +
>  Required properties:
>   - compatible : should contain "mediatek,mt8173-xhci"
>   - reg : specifies physical base address and size of the registers,
> @@ -27,6 +35,9 @@ Optional properties:
>  	control register, it depends on "mediatek,wakeup-src".
>   - vbus-supply : reference to the VBUS regulator;
>   - usb3-lpm-capable : supports USB3.0 LPM
> + - pinctl-names : a pinctrl state named "default" must be defined

    pinctrl-names.

> + - pinctrl-0 : pin control group
> +	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
>
>  Example:
>  usb30: usb at 11270000 {
[...]

MBR, Sergei



From mark.rutland at arm.com  Tue May 31 04:07:47 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 12:07:47 +0100
Subject: [PATCH] arm64: report CPU number in bad_mode
Message-ID: <1464692867-339-1-git-send-email-mark.rutland@arm.com>

If we take an exception we don't expect (e.g. SError), we report this in
the bad_mode handler with pr_crit. Depending on the configured log
level, we may or may not log additional information in functions called
subsequently. Notably, the messages in dump_stack (including the CPU
number) are printed with KERN_DEFAULT and may not appear.

Some exceptions have an IMPLEMENTATION DEFINED ESR_ELx.ISS encoding, and
knowing the CPU number is crucial to correctly decode them. To ensure
that this is always possible, we should log the CPU number along with
the ESR_ELx value, so we are not reliant on subsequent logs or
additional printk configuration options.

This patch logs the CPU number in bad_mode such that it is possible for
a developer to decode these exceptions, provided access to sufficient
documentation.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reported-by: Al Grant <Al.Grant at arm.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Dave Martin <dave.martin at arm.com>
Cc: Robin Murphy <robin.murphy at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
---
 arch/arm64/kernel/traps.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index c539208..f7cf463 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -477,8 +477,9 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
 	void __user *pc = (void __user *)instruction_pointer(regs);
 	console_verbose();
 
-	pr_crit("Bad mode in %s handler detected, code 0x%08x -- %s\n",
-		handler[reason], esr, esr_get_class_string(esr));
+	pr_crit("Bad mode in %s handler detected on CPU%d, code 0x%08x -- %s\n",
+		handler[reason], smp_processor_id(), esr,
+		esr_get_class_string(esr));
 	__show_regs(regs);
 
 	info.si_signo = SIGILL;
-- 
1.9.1



From tn at semihalf.com  Tue May 31 04:19:37 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 31 May 2016 13:19:37 +0200
Subject: [PATCH V5 0/7] Introduce ACPI world to ITS irqchip
Message-ID: <1464693584-22343-1-git-send-email-tn@semihalf.com>

Patches can be found:
https://github.com/semihalf-nowicki-tomasz/linux.git (its-acpi-v5)

Since this series depends on pending ARM64 ACPI PCI support, please pull:
https://github.com/semihalf-nowicki-tomasz/linux.git (its-pci-acpi-v5)
The its-pci-acpi-v5 git branch contains submitted patches along with
the useful PCI patches from the test point of view.

Series has been tested on Cavium ThunderX server.

v4 -> v5
- rebased against v4.7-rc1
- drop generic layer and call IORT functions directly
- improve resource abstraction and string formatting

v3 -> v4
- rebased against v4.5
- add ACPI support for IRQ domain handling on a per-device basis
- reorder domain setup step
- improve error handling
- code style improvements

v2 -> v3
- rebased on top of 4.4
- fixes and improvements for redistributor init via GICC structures
- fixes as per kbuild reports

v1 -> v2
- rebased on top of 4.4-rc4
- use pci_msi_domain_get_msi_rid for requester ID to device ID translation


Tomasz Nowicki (7):
  ARM64, ACPI, PCI: I/O Remapping Table (IORT) initial support.
  acpi, pci: Setup MSI domain on a per-devices basis.
  irqchip, GICv3, ITS: Cleanup for ITS domain initialization.
  irqchip, GICv3, ITS: Refator ITS DT init code to prepare for ACPI.
  irqchip, gicv3, its: Probe ITS in the ACPI way.
  its, pci, msi: Factor out code that might be reused for ACPI.
  acpi, gicv3, its: Use MADT ITS subtable to do PCI/MSI domain
    initialization.

 drivers/acpi/Kconfig                     |   3 +
 drivers/acpi/Makefile                    |   1 +
 drivers/acpi/iort.c                      | 344 +++++++++++++++++++++++++++++++
 drivers/irqchip/Kconfig                  |   1 +
 drivers/irqchip/irq-gic-v3-its-pci-msi.c |  84 ++++++--
 drivers/irqchip/irq-gic-v3-its.c         | 184 ++++++++++++-----
 drivers/irqchip/irq-gic-v3.c             |   7 +-
 drivers/pci/msi.c                        |  11 +-
 include/linux/iort.h                     |  38 ++++
 include/linux/irqchip/arm-gic-v3.h       |   4 +-
 10 files changed, 600 insertions(+), 77 deletions(-)
 create mode 100644 drivers/acpi/iort.c
 create mode 100644 include/linux/iort.h

-- 
1.9.1



From tn at semihalf.com  Tue May 31 04:19:38 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 31 May 2016 13:19:38 +0200
Subject: [PATCH V5 1/7] ARM64, ACPI,
 PCI: I/O Remapping Table (IORT) initial support.
In-Reply-To: <1464693584-22343-1-git-send-email-tn@semihalf.com>
References: <1464693584-22343-1-git-send-email-tn@semihalf.com>
Message-ID: <1464693584-22343-2-git-send-email-tn@semihalf.com>

IORT shows representation of IO topology for ARM based systems.
It describes how various components are connected together on
parent-child basis e.g. PCI RC -> SMMU -> ITS. Also see IORT spec.

Initial support allows to:
- register ITS MSI chip along with ITS translation ID and domain token
- deregister ITS MSI chip based on ITS translation ID
- find registered domain token based on ITS translation ID
- map MSI RID based on PCI device and requester ID
- find domain token based on PCI device and requester ID

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 drivers/acpi/Kconfig  |   3 +
 drivers/acpi/Makefile |   1 +
 drivers/acpi/iort.c   | 344 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/iort.h  |  38 ++++++
 4 files changed, 386 insertions(+)
 create mode 100644 drivers/acpi/iort.c
 create mode 100644 include/linux/iort.h

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index b7e2e77..848471f 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -57,6 +57,9 @@ config ACPI_SYSTEM_POWER_STATES_SUPPORT
 config ACPI_CCA_REQUIRED
 	bool
 
+config IORT_TABLE
+	bool
+
 config ACPI_DEBUGGER
 	bool "AML debugger interface"
 	select ACPI_DEBUG
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 251ce85..c7c9b29 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
 obj-$(CONFIG_ACPI_BGRT)		+= bgrt.o
 obj-$(CONFIG_ACPI_CPPC_LIB)	+= cppc_acpi.o
 obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o
+obj-$(CONFIG_IORT_TABLE) 	+= iort.o
 
 # processor has its own "processor." module_param namespace
 processor-y			:= processor_driver.o
diff --git a/drivers/acpi/iort.c b/drivers/acpi/iort.c
new file mode 100644
index 0000000..226eb6d
--- /dev/null
+++ b/drivers/acpi/iort.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2016, Semihalf
+ *	Author: Tomasz Nowicki <tn at semihalf.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.
+ *
+ * This file implements early detection/parsing of I/O mapping
+ * reported to OS through firmware via I/O Remapping Table (IORT)
+ * IORT document number: ARM DEN 0049A
+ */
+
+#define pr_fmt(fmt)	"ACPI: IORT: " fmt
+
+#include <linux/export.h>
+#include <linux/iort.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+struct iort_its_msi_chip {
+	struct list_head	list;
+	struct fwnode_handle	*fw_node;
+	u32			translation_id;
+};
+
+typedef acpi_status (*iort_find_node_callback)
+	(struct acpi_iort_node *node, void *context);
+
+/* Root pointer to the mapped IORT table */
+static struct acpi_table_header *iort_table;
+
+static LIST_HEAD(iort_msi_chip_list);
+
+/**
+ * iort_register_domain_token() - register domain token and related ITS ID
+ * 				  to the list from where we can get it back
+ * 				  later on.
+ * @translation_id: ITS ID
+ * @token: domain token
+ *
+ * Returns: 0 on success, -ENOMEM if not memory when allocating list element.
+ */
+int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node)
+{
+	struct iort_its_msi_chip *its_msi_chip;
+
+	its_msi_chip = kzalloc(sizeof(*its_msi_chip), GFP_KERNEL);
+	if (!its_msi_chip)
+		return -ENOMEM;
+
+	its_msi_chip->fw_node = fw_node;
+	its_msi_chip->translation_id = trans_id;
+
+	list_add(&its_msi_chip->list, &iort_msi_chip_list);
+	return 0;
+}
+
+/**
+ * iort_unregister_domain_token() - unregister domain token based on ITS ID.
+ * @translation_id: ITS ID
+ *
+ * Returns: none.
+ */
+void iort_deregister_domain_token(int trans_id)
+{
+	struct iort_its_msi_chip *its_msi_chip, *t;
+
+	list_for_each_entry_safe(its_msi_chip, t, &iort_msi_chip_list, list) {
+		if (its_msi_chip->translation_id == trans_id) {
+			list_del(&its_msi_chip->list);
+			kfree(its_msi_chip);
+			break;
+		}
+	}
+}
+
+/**
+ * iort_find_its_domain_token() - find domain token based on given ITS ID.
+ * @translation_id: ITS ID
+ *
+ * Returns: domain token when find on the list, NULL otherwise.
+ */
+struct fwnode_handle *iort_its_find_domain_token(int trans_id)
+{
+	struct iort_its_msi_chip *its_msi_chip;
+
+	list_for_each_entry(its_msi_chip, &iort_msi_chip_list, list) {
+		if (its_msi_chip->translation_id == trans_id)
+			return its_msi_chip->fw_node;
+	}
+
+	return NULL;
+}
+
+static struct acpi_iort_node *
+iort_scan_node(enum acpi_iort_node_type type,
+	       iort_find_node_callback callback, void *context)
+{
+	struct acpi_iort_node *iort_node, *iort_end;
+	struct acpi_table_iort *iort;
+	int i;
+
+	if (!iort_table)
+		return NULL;
+
+	/*
+	 * iort_table and iort both point to the start of IORT table, but
+	 * have different struct types
+	 */
+	iort = (struct acpi_table_iort *)iort_table;
+
+	/* Get the first IORT node */
+	iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+				 iort->node_offset);
+	iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort_table,
+				iort_table->length);
+
+	for (i = 0; i < iort->node_count; i++) {
+		if (iort_node >= iort_end) {
+			pr_err("iort node pointer overflows, bad table\n");
+			return NULL;
+		}
+
+		if (iort_node->type == type) {
+			if (ACPI_SUCCESS(callback(iort_node, context)))
+				return iort_node;
+		}
+
+		iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
+					 iort_node->length);
+	}
+
+	return NULL;
+}
+
+static acpi_status
+iort_find_dev_callback(struct acpi_iort_node *node, void *context)
+{
+	struct acpi_iort_root_complex *pci_rc;
+	struct device *dev = context;
+	struct pci_bus *bus;
+
+	switch (node->type) {
+	case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
+		bus = to_pci_bus(dev);
+		pci_rc = (struct acpi_iort_root_complex *)node->node_data;
+
+		/*
+		 * It is assumed that PCI segment numbers maps one-to-one
+		 * with root complexes. Each segment number can represent only
+		 * one root complex.
+		 */
+		if (pci_rc->pci_segment_number == pci_domain_nr(bus))
+			return AE_OK;
+
+		break;
+	}
+
+	return AE_NOT_FOUND;
+}
+
+static struct acpi_iort_node *
+iort_dev_map_rid(struct acpi_iort_node *node, u32 rid_in,
+			    u32 *rid_out)
+{
+
+	if (!node)
+		goto out;
+
+	/* Go upstream */
+	while (node->type != ACPI_IORT_NODE_ITS_GROUP) {
+		struct acpi_iort_id_mapping *id;
+		int i, found = 0;
+
+		/* Exit when no mapping array */
+		if (!node->mapping_offset || !node->mapping_count)
+			return NULL;
+
+		id = ACPI_ADD_PTR(struct acpi_iort_id_mapping, node,
+				  node->mapping_offset);
+
+		for (i = 0, found = 0; i < node->mapping_count; i++, id++) {
+			/*
+			 * Single mapping is not translation rule,
+			 * lets move on for this case
+			 */
+			if (id->flags & ACPI_IORT_ID_SINGLE_MAPPING) {
+				if (node->type != ACPI_IORT_NODE_SMMU) {
+					rid_in = id->output_base;
+					found = 1;
+					break;
+				}
+
+				pr_warn(FW_BUG "[node %p type %d] SINGLE MAPPING flag not allowed for SMMU node, skipping ID map\n",
+					node, node->type);
+				continue;
+			}
+
+			if (rid_in < id->input_base ||
+			    (rid_in > id->input_base + id->id_count))
+				continue;
+
+			rid_in = id->output_base + (rid_in - id->input_base);
+			found = 1;
+			break;
+		}
+
+		if (!found)
+			return NULL;
+
+		/* Firmware bug! */
+		if (!id->output_reference) {
+			pr_err(FW_BUG "[node %p type %d] ID map has NULL parent reference\n",
+			       node, node->type);
+			return NULL;
+		}
+
+		node = ACPI_ADD_PTR(struct acpi_iort_node, iort_table,
+				    id->output_reference);
+	}
+
+out:
+	if (rid_out)
+		*rid_out = rid_in;
+	return node;
+}
+
+static struct acpi_iort_node *
+iort_its_find_node_and_map_rid(struct pci_dev *pdev, u32 req_id, u32 *dev_id)
+{
+	struct pci_bus *pbus = pdev->bus;
+	struct acpi_iort_node *node;
+
+	/* Find a PCI root bus */
+	while (!pci_is_root_bus(pbus))
+		pbus = pbus->parent;
+
+
+	node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
+			      iort_find_dev_callback, &pbus->dev);
+	if (!node) {
+		dev_err(&pdev->dev, "can't find related IORT node\n");
+		return NULL;
+	}
+
+	return iort_dev_map_rid(node, req_id, dev_id);
+}
+
+/**
+ * iort_pci_domain_get_msi_rid() - find MSI RID based on PCI device ID
+ * @pdev: The PCI device
+ * @req_id: The PCI device requester ID
+ *
+ * Returns: MSI RID on success, input requester ID otherwise
+ */
+u32 iort_pci_get_msi_rid(struct pci_dev *pdev, u32 req_id)
+{
+	u32 dev_id;
+
+	if (!iort_its_find_node_and_map_rid(pdev, req_id, &dev_id))
+		return req_id;
+
+	return dev_id;
+}
+
+/**
+ * iort_pci_find_its_id() - find the ITS identifier based on specified device.
+ * @pdev: The PCI device
+ * @idx: Index of the ITS identifier list
+ * @its_id: ITS identifier
+ *
+ * Returns: 0 on success, appropriate error value otherwise
+ */
+static int
+iort_pci_find_its_id(struct pci_dev *pdev, u32 req_id, unsigned int idx,
+		     int *its_id)
+{
+	struct acpi_iort_its_group *its;
+	struct acpi_iort_node *node;
+
+	node = iort_its_find_node_and_map_rid(pdev, req_id, NULL);
+	if (!node)
+		return -ENXIO;
+
+	/* Move to ITS specific data */
+	its = (struct acpi_iort_its_group *)node->node_data;
+	if (idx > its->its_count) {
+		dev_err(&pdev->dev, "requested ITS ID index [%d] is greater than available[%d]\n",
+			idx, its->its_count);
+		return -ENXIO;
+	}
+
+	*its_id = its->identifiers[idx];
+	return 0;
+}
+
+/**
+ * iort_pci_get_msi_domain_handle() - find registered domain token related to
+ *                                    PCI device
+ * @pdev:    The PCI device
+ * @req_id:  The PCI device requester ID
+ *
+ * Returns: the MSI domain for this device, NULL otherwise
+ */
+struct irq_domain *
+iort_pci_get_domain(struct pci_dev *pdev, u32 req_id)
+{
+	static struct fwnode_handle *handle;
+	int its_id;
+
+	if (iort_pci_find_its_id(pdev, req_id, 0, &its_id))
+		return NULL;
+
+	handle = iort_its_find_domain_token(its_id);
+	if (!handle)
+		return NULL;
+
+	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
+}
+
+static int __init iort_table_detect(void)
+{
+	acpi_status status;
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	status = acpi_get_table(ACPI_SIG_IORT, 0, &iort_table);
+	if (ACPI_FAILURE(status)) {
+		const char *msg = acpi_format_exception(status);
+		pr_err("Failed to get table, %s\n", msg);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+arch_initcall(iort_table_detect);
diff --git a/include/linux/iort.h b/include/linux/iort.h
new file mode 100644
index 0000000..490ff4d
--- /dev/null
+++ b/include/linux/iort.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016, Semihalf
+ *	Author: Tomasz Nowicki <tn at semihalf.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, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef __IORT_H__
+#define __IORT_H__
+
+#include <linux/acpi.h>
+
+struct fwnode_handle;
+int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
+void iort_deregister_domain_token(int trans_id);
+struct fwnode_handle *iort_its_find_domain_token(int trans_id);
+#ifdef CONFIG_IORT_TABLE
+u32 iort_pci_get_msi_rid(struct pci_dev *pdev, u32 req_id);
+struct irq_domain *iort_pci_get_domain(struct pci_dev *pdev, u32 req_id);
+#else
+static inline u32 iort_pci_get_msi_rid(struct pci_dev *pdev, u32 req_id)
+{ return req_id; }
+static inline struct irq_domain *
+iort_pci_get_domain(struct pci_dev *pdev, u32 req_id) { return NULL; }
+#endif
+
+#endif /* __IORT_H__ */
-- 
1.9.1



From tn at semihalf.com  Tue May 31 04:19:39 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 31 May 2016 13:19:39 +0200
Subject: [PATCH V5 2/7] acpi, pci: Setup MSI domain on a per-devices basis.
In-Reply-To: <1464693584-22343-1-git-send-email-tn@semihalf.com>
References: <1464693584-22343-1-git-send-email-tn@semihalf.com>
Message-ID: <1464693584-22343-3-git-send-email-tn@semihalf.com>

It is possible to provide information about which MSI controller to
use on a per-device basis for DT. This patch supply this with ACPI support.

Currently, IORT is the only one ACPI table which can provide such mapping.
In order to plug IORT into MSI infrastructure we are adding ACPI
equivalents for finding PCI device domain and its RID translation
(pci_msi_domain_get_msi_rid and pci_msi_domain_get_msi_rid calls).

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 drivers/pci/msi.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index a080f44..ba49df7 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -18,6 +18,7 @@
 #include <linux/smp.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/iort.h>
 #include <linux/slab.h>
 #include <linux/irqdomain.h>
 #include <linux/of_irq.h>
@@ -1364,8 +1365,8 @@ u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev)
 	pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
 
 	of_node = irq_domain_get_of_node(domain);
-	if (of_node)
-		rid = of_msi_map_rid(&pdev->dev, of_node, rid);
+	rid = of_node ? of_msi_map_rid(&pdev->dev, of_node, rid) :
+			iort_pci_get_msi_rid(pdev, rid);
 
 	return rid;
 }
@@ -1381,9 +1382,13 @@ u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev)
  */
 struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev)
 {
+	struct irq_domain *dom;
 	u32 rid = 0;
 
 	pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
-	return of_msi_map_get_device_domain(&pdev->dev, rid);
+	dom = of_msi_map_get_device_domain(&pdev->dev, rid);
+	if (!dom)
+		dom = iort_pci_get_domain(pdev, rid);
+	return dom;
 }
 #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */
-- 
1.9.1



From tn at semihalf.com  Tue May 31 04:19:40 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 31 May 2016 13:19:40 +0200
Subject: [PATCH V5 3/7] irqchip, GICv3,
 ITS: Cleanup for ITS domain initialization.
In-Reply-To: <1464693584-22343-1-git-send-email-tn@semihalf.com>
References: <1464693584-22343-1-git-send-email-tn@semihalf.com>
Message-ID: <1464693584-22343-4-git-send-email-tn@semihalf.com>

There is no point to initialize ITS without having msi-controller
property in corresponding DT node. However, its_probe is checking
msi-controller presence at the end, so we can save our time and do that
check prior to its_probe call. Also, for the code clarity purpose,
we put domain initialization to separate function.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 57 ++++++++++++++++++++++++----------------
 1 file changed, 34 insertions(+), 23 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 6bd881b..cb33c92 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1463,13 +1463,37 @@ static void its_enable_quirks(struct its_node *its)
 	gic_enable_quirks(iidr, its_quirks, its);
 }
 
+static int its_init_domain(struct device_node *node, struct its_node *its,
+			   struct irq_domain *parent)
+{
+	struct irq_domain *inner_domain;
+	struct msi_domain_info *info;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	inner_domain = irq_domain_add_tree(node, &its_domain_ops, its);
+	if (!inner_domain) {
+		kfree(info);
+		return -ENOMEM;
+	}
+
+	inner_domain->parent = parent;
+	inner_domain->bus_token = DOMAIN_BUS_NEXUS;
+	info->ops = &its_msi_domain_ops;
+	info->data = its;
+	inner_domain->host_data = info;
+
+	return 0;
+}
+
 static int __init its_probe(struct device_node *node,
 			    struct irq_domain *parent)
 {
 	struct resource res;
 	struct its_node *its;
 	void __iomem *its_base;
-	struct irq_domain *inner_domain;
 	u32 val;
 	u64 baser, tmp;
 	int err;
@@ -1560,28 +1584,9 @@ static int __init its_probe(struct device_node *node,
 	writeq_relaxed(0, its->base + GITS_CWRITER);
 	writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);
 
-	if (of_property_read_bool(node, "msi-controller")) {
-		struct msi_domain_info *info;
-
-		info = kzalloc(sizeof(*info), GFP_KERNEL);
-		if (!info) {
-			err = -ENOMEM;
-			goto out_free_tables;
-		}
-
-		inner_domain = irq_domain_add_tree(node, &its_domain_ops, its);
-		if (!inner_domain) {
-			err = -ENOMEM;
-			kfree(info);
-			goto out_free_tables;
-		}
-
-		inner_domain->parent = parent;
-		inner_domain->bus_token = DOMAIN_BUS_NEXUS;
-		info->ops = &its_msi_domain_ops;
-		info->data = its;
-		inner_domain->host_data = info;
-	}
+	err = its_init_domain(node, its, parent);
+	if (err)
+		goto out_free_tables;
 
 	spin_lock(&its_lock);
 	list_add(&its->entry, &its_nodes);
@@ -1632,6 +1637,12 @@ int __init its_init(struct device_node *node, struct rdists *rdists,
 
 	for (np = of_find_matching_node(node, its_device_id); np;
 	     np = of_find_matching_node(np, its_device_id)) {
+		if (!of_property_read_bool(np, "msi-controller")) {
+			pr_warn("%s: no msi-controller property, ITS ignored\n",
+				np->full_name);
+			continue;
+		}
+
 		its_probe(np, parent_domain);
 	}
 
-- 
1.9.1



From tn at semihalf.com  Tue May 31 04:19:42 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 31 May 2016 13:19:42 +0200
Subject: [PATCH V5 5/7] irqchip, gicv3, its: Probe ITS in the ACPI way.
In-Reply-To: <1464693584-22343-1-git-send-email-tn@semihalf.com>
References: <1464693584-22343-1-git-send-email-tn@semihalf.com>
Message-ID: <1464693584-22343-6-git-send-email-tn@semihalf.com>

ITS is prepared for being initialized different than DT,
therefore we can initialize it in ACPI way. We collect register base
address from MADT table and pass mandatory info to firmware-agnostic
ITS init call.

Note that we are using here IORT lib to register ITS domain which
then can be found and used on to build another PCI MSI domain
in hierarchical stack domain.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 drivers/irqchip/Kconfig          |  1 +
 drivers/irqchip/irq-gic-v3-its.c | 60 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index fa33c50..c6e652f 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -32,6 +32,7 @@ config ARM_GIC_V3
 config ARM_GIC_V3_ITS
 	bool
 	select PCI_MSI_IRQ_DOMAIN
+	select IORT_TABLE if ACPI
 
 config ARM_NVIC
 	bool
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 6a97ee5..c8f36a5 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -15,10 +15,13 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/bitmap.h>
 #include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/iort.h>
 #include <linux/log2.h>
 #include <linux/mm.h>
 #include <linux/msi.h>
@@ -1312,6 +1315,11 @@ static int its_irq_gic_domain_alloc(struct irq_domain *domain,
 		fwspec.param[0] = GIC_IRQ_TYPE_LPI;
 		fwspec.param[1] = hwirq;
 		fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+	} else if (is_fwnode_irqchip(domain->parent->fwnode)) {
+		fwspec.fwnode = domain->parent->fwnode;
+		fwspec.param_count = 2;
+		fwspec.param[0] = hwirq;
+		fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
 	} else {
 		return -EINVAL;
 	}
@@ -1645,6 +1653,56 @@ static int __init its_of_probe(struct device_node *node)
 	return 0;
 }
 
+#ifdef CONFIG_ACPI
+
+#define ACPI_GICV3_ITS_MEM_SIZE (2 * SZ_64K)
+
+static int __init gic_acpi_parse_madt_its(struct acpi_subtable_header *header,
+					  const unsigned long end)
+{
+	struct acpi_madt_generic_translator *its_entry;
+	struct fwnode_handle *dom_handle;
+	struct resource res;
+	int err;
+
+	its_entry = (struct acpi_madt_generic_translator *)header;
+	res.start = its_entry->base_address;
+	res.end = its_entry->base_address + ACPI_GICV3_ITS_MEM_SIZE - 1;
+
+	dom_handle = irq_domain_alloc_fwnode((void *)its_entry->base_address);
+	if (!dom_handle) {
+		pr_err("ITS@%pa: Unable to allocate GICv3 ITS domain token\n",
+		       &res.start);
+		return -ENOMEM;
+	}
+
+	err = iort_register_domain_token(its_entry->translation_id, dom_handle);
+	if (err) {
+		pr_err("ITS@%pa: Unable to register GICv3 ITS domain token (ITS ID %d) to IORT\n",
+		       &res.start, its_entry->translation_id);
+		goto dom_err;
+	}
+
+	err = its_probe_one(&res, dom_handle);
+	if (!err)
+		return 0;
+
+	iort_deregister_domain_token(its_entry->translation_id);
+dom_err:
+	irq_domain_free_fwnode(dom_handle);
+	return err;
+}
+
+void __init its_acpi_probe(void)
+{
+	if (acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
+				  gic_acpi_parse_madt_its, 0) <= 0)
+		pr_info("No valid GIC ITS entries exist\n");
+}
+#else
+static inline void __init its_acpi_probe(struct irq_domain *parent_domain) { }
+#endif
+
 int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
 		    struct irq_domain *parent_domain)
 {
@@ -1654,6 +1712,8 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
 	of_node = to_of_node(handle);
 	if (of_node)
 		its_of_probe(of_node);
+	else
+		its_acpi_probe();
 
 	if (list_empty(&its_nodes)) {
 		pr_warn("ITS: No ITS available, not enabling LPIs\n");
-- 
1.9.1



From tn at semihalf.com  Tue May 31 04:19:43 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 31 May 2016 13:19:43 +0200
Subject: [PATCH V5 6/7] its, pci,
 msi: Factor out code that might be reused for ACPI.
In-Reply-To: <1464693584-22343-1-git-send-email-tn@semihalf.com>
References: <1464693584-22343-1-git-send-email-tn@semihalf.com>
Message-ID: <1464693584-22343-7-git-send-email-tn@semihalf.com>

Firmware agnostic code lands in common functions which do necessary
domain initialization based on unique domain handler. DT specific
code goes to DT specific init call.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 drivers/irqchip/irq-gic-v3-its-pci-msi.c | 44 +++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 15 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index aee60ed..23679ae 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -106,34 +106,48 @@ static struct of_device_id its_device_id[] = {
 	{},
 };
 
-static int __init its_pci_msi_init(void)
+static int __init its_pci_msi_init_one(struct fwnode_handle *handle,
+				       const char *name)
 {
-	struct device_node *np;
 	struct irq_domain *parent;
 
+	parent = irq_find_matching_fwnode(handle, DOMAIN_BUS_NEXUS);
+	if (!parent || !msi_get_domain_info(parent)) {
+		pr_err("%s: Unable to locate ITS domain\n", name);
+		return -ENXIO;
+	}
+
+	if (!pci_msi_create_irq_domain(handle, &its_pci_msi_domain_info,
+				       parent)) {
+		pr_err("%s: Unable to create PCI domain\n", name);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int __init its_pci_of_msi_init(void)
+{
+	struct device_node *np;
+
 	for (np = of_find_matching_node(NULL, its_device_id); np;
 	     np = of_find_matching_node(np, its_device_id)) {
 		if (!of_property_read_bool(np, "msi-controller"))
 			continue;
 
-		parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS);
-		if (!parent || !msi_get_domain_info(parent)) {
-			pr_err("%s: unable to locate ITS domain\n",
-			       np->full_name);
+		if (its_pci_msi_init_one(of_node_to_fwnode(np), np->full_name))
 			continue;
-		}
-
-		if (!pci_msi_create_irq_domain(of_node_to_fwnode(np),
-					       &its_pci_msi_domain_info,
-					       parent)) {
-			pr_err("%s: unable to create PCI domain\n",
-			       np->full_name);
-			continue;
-		}
 
 		pr_info("PCI/MSI: %s domain created\n", np->full_name);
 	}
 
 	return 0;
 }
+
+static int __init its_pci_msi_init(void)
+{
+	its_pci_of_msi_init();
+	return 0;
+}
+
 early_initcall(its_pci_msi_init);
-- 
1.9.1



From tn at semihalf.com  Tue May 31 04:19:41 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 31 May 2016 13:19:41 +0200
Subject: [PATCH V5 4/7] irqchip, GICv3,
 ITS: Refator ITS DT init code to prepare for ACPI.
In-Reply-To: <1464693584-22343-1-git-send-email-tn@semihalf.com>
References: <1464693584-22343-1-git-send-email-tn@semihalf.com>
Message-ID: <1464693584-22343-5-git-send-email-tn@semihalf.com>

In order to add ACPI support we need to isolate ACPI&DT common code and
move DT logic to corresponding functions. To achieve this we are using
firmware agnostic handle which can be unpacked to either DT or ACPI node.

No functional changes other than a very minor one:
1. Fix ITS base register address type (from 'unsigned long' to 'phys_addr_t'),
as a bonus we get nice string formatting.
2. Since there is only one of ITS parent domain convert it to static global
variable and drop the parameter from its_probe_one. Users can refer to it
in more convenient way then.

Signed-off-by: Hanjun Guo <hanjun.guo at linaro.org>
Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 drivers/irqchip/irq-gic-v3-its.c   | 77 +++++++++++++++++++++-----------------
 drivers/irqchip/irq-gic-v3.c       |  6 +--
 include/linux/irqchip/arm-gic-v3.h |  4 +-
 3 files changed, 47 insertions(+), 40 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index cb33c92..6a97ee5 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -73,7 +73,7 @@ struct its_node {
 	raw_spinlock_t		lock;
 	struct list_head	entry;
 	void __iomem		*base;
-	unsigned long		phys_base;
+	phys_addr_t		phys_base;
 	struct its_cmd_block	*cmd_base;
 	struct its_cmd_block	*cmd_write;
 	struct its_baser	tables[GITS_BASER_NR_REGS];
@@ -112,6 +112,7 @@ struct its_device {
 static LIST_HEAD(its_nodes);
 static DEFINE_SPINLOCK(its_lock);
 static struct rdists *gic_rdists;
+static struct irq_domain *its_parent;
 
 #define gic_data_rdist()		(raw_cpu_ptr(gic_rdists->rdist))
 #define gic_data_rdist_rd_base()	(gic_data_rdist()->rd_base)
@@ -823,7 +824,7 @@ static void its_free_tables(struct its_node *its)
 	}
 }
 
-static int its_alloc_tables(const char *node_name, struct its_node *its)
+static int its_alloc_tables(struct its_node *its)
 {
 	int err;
 	int i;
@@ -879,8 +880,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
 				    order);
 			if (order >= MAX_ORDER) {
 				order = MAX_ORDER - 1;
-				pr_warn("%s: Device Table too large, reduce its page order to %u\n",
-					node_name, order);
+				pr_warn("ITS@%pa: Device Table too large, reduce its page order to %u\n",
+					&its->phys_base, order);
 			}
 		}
 
@@ -889,8 +890,8 @@ retry_alloc_baser:
 		if (alloc_pages > GITS_BASER_PAGES_MAX) {
 			alloc_pages = GITS_BASER_PAGES_MAX;
 			order = get_order(GITS_BASER_PAGES_MAX * psz);
-			pr_warn("%s: Device Table too large, reduce its page order to %u (%u pages)\n",
-				node_name, order, alloc_pages);
+			pr_warn("ITS@%pa: Device Table too large, reduce its page order to %u (%u pages)\n",
+				&its->phys_base, order, alloc_pages);
 		}
 
 		base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
@@ -964,8 +965,8 @@ retry_baser:
 		}
 
 		if (val != tmp) {
-			pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n",
-			       node_name, i,
+			pr_err("ITS@%pa: GITS_BASER%d doesn't stick: %lx %lx\n",
+			       &its->phys_base, i,
 			       (unsigned long) val, (unsigned long) tmp);
 			err = -ENXIO;
 			goto out_free;
@@ -1463,8 +1464,7 @@ static void its_enable_quirks(struct its_node *its)
 	gic_enable_quirks(iidr, its_quirks, its);
 }
 
-static int its_init_domain(struct device_node *node, struct its_node *its,
-			   struct irq_domain *parent)
+static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
 {
 	struct irq_domain *inner_domain;
 	struct msi_domain_info *info;
@@ -1473,13 +1473,13 @@ static int its_init_domain(struct device_node *node, struct its_node *its,
 	if (!info)
 		return -ENOMEM;
 
-	inner_domain = irq_domain_add_tree(node, &its_domain_ops, its);
+	inner_domain = irq_domain_create_tree(handle, &its_domain_ops, its);
 	if (!inner_domain) {
 		kfree(info);
 		return -ENOMEM;
 	}
 
-	inner_domain->parent = parent;
+	inner_domain->parent = its_parent;
 	inner_domain->bus_token = DOMAIN_BUS_NEXUS;
 	info->ops = &its_msi_domain_ops;
 	info->data = its;
@@ -1488,43 +1488,35 @@ static int its_init_domain(struct device_node *node, struct its_node *its,
 	return 0;
 }
 
-static int __init its_probe(struct device_node *node,
-			    struct irq_domain *parent)
+static int __init its_probe_one(struct resource *res,
+				struct fwnode_handle *handle)
 {
-	struct resource res;
 	struct its_node *its;
 	void __iomem *its_base;
 	u32 val;
 	u64 baser, tmp;
 	int err;
 
-	err = of_address_to_resource(node, 0, &res);
-	if (err) {
-		pr_warn("%s: no regs?\n", node->full_name);
-		return -ENXIO;
-	}
-
-	its_base = ioremap(res.start, resource_size(&res));
+	its_base = ioremap(res->start, resource_size(res));
 	if (!its_base) {
-		pr_warn("%s: unable to map registers\n", node->full_name);
+		pr_warn("ITS@%pa: Unable to map ITS registers\n", &res->start);
 		return -ENOMEM;
 	}
 
 	val = readl_relaxed(its_base + GITS_PIDR2) & GIC_PIDR2_ARCH_MASK;
 	if (val != 0x30 && val != 0x40) {
-		pr_warn("%s: no ITS detected, giving up\n", node->full_name);
+		pr_warn("ITS@%pa: No ITS detected, giving up\n", &res->start);
 		err = -ENODEV;
 		goto out_unmap;
 	}
 
 	err = its_force_quiescent(its_base);
 	if (err) {
-		pr_warn("%s: failed to quiesce, giving up\n",
-			node->full_name);
+		pr_warn("ITS@%pa: Failed to quiesce, giving up\n", &res->start);
 		goto out_unmap;
 	}
 
-	pr_info("ITS: %s\n", node->full_name);
+	pr_info("ITS@%pa\n", &res->start);
 
 	its = kzalloc(sizeof(*its), GFP_KERNEL);
 	if (!its) {
@@ -1536,7 +1528,7 @@ static int __init its_probe(struct device_node *node,
 	INIT_LIST_HEAD(&its->entry);
 	INIT_LIST_HEAD(&its->its_device_list);
 	its->base = its_base;
-	its->phys_base = res.start;
+	its->phys_base = res->start;
 	its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
 
 	its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
@@ -1548,7 +1540,7 @@ static int __init its_probe(struct device_node *node,
 
 	its_enable_quirks(its);
 
-	err = its_alloc_tables(node->full_name, its);
+	err = its_alloc_tables(its);
 	if (err)
 		goto out_free_cmd;
 
@@ -1584,7 +1576,7 @@ static int __init its_probe(struct device_node *node,
 	writeq_relaxed(0, its->base + GITS_CWRITER);
 	writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);
 
-	err = its_init_domain(node, its, parent);
+	err = its_init_domain(handle, its);
 	if (err)
 		goto out_free_tables;
 
@@ -1602,7 +1594,7 @@ out_free_its:
 	kfree(its);
 out_unmap:
 	iounmap(its_base);
-	pr_err("ITS: failed probing %s (%d)\n", node->full_name, err);
+	pr_err("ITS@%pa: failed probing (%d)\n", &res->start, err);
 	return err;
 }
 
@@ -1630,10 +1622,10 @@ static struct of_device_id its_device_id[] = {
 	{},
 };
 
-int __init its_init(struct device_node *node, struct rdists *rdists,
-	     struct irq_domain *parent_domain)
+static int __init its_of_probe(struct device_node *node)
 {
 	struct device_node *np;
+	struct resource res;
 
 	for (np = of_find_matching_node(node, its_device_id); np;
 	     np = of_find_matching_node(np, its_device_id)) {
@@ -1643,8 +1635,25 @@ int __init its_init(struct device_node *node, struct rdists *rdists,
 			continue;
 		}
 
-		its_probe(np, parent_domain);
+		if (of_address_to_resource(np, 0, &res)) {
+			pr_warn("%s: no regs?\n", np->full_name);
+			continue;
+		}
+
+		its_probe_one(&res, &np->fwnode);
 	}
+	return 0;
+}
+
+int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
+		    struct irq_domain *parent_domain)
+{
+	struct device_node *of_node;
+
+	its_parent = parent_domain;
+	of_node = to_of_node(handle);
+	if (of_node)
+		its_of_probe(of_node);
 
 	if (list_empty(&its_nodes)) {
 		pr_warn("ITS: No ITS available, not enabling LPIs\n");
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index fb042ba..cee8296 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -911,7 +911,6 @@ static int __init gic_init_bases(void __iomem *dist_base,
 				 u64 redist_stride,
 				 struct fwnode_handle *handle)
 {
-	struct device_node *node;
 	u32 typer;
 	int gic_irqs;
 	int err;
@@ -952,10 +951,9 @@ static int __init gic_init_bases(void __iomem *dist_base,
 
 	set_handle_irq(gic_handle_irq);
 
-	node = to_of_node(handle);
 	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis() &&
-	    node) /* Temp hack to prevent ITS init for ACPI */
-		its_init(node, &gic_data.rdists, gic_data.domain);
+	    to_of_node(handle)) /* Temp hack to prevent ITS init for ACPI */
+		its_init(handle, &gic_data.rdists, gic_data.domain);
 
 	gic_smp_init();
 	gic_dist_init();
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index bfbd707..0e75cb7 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -334,9 +334,9 @@ struct rdists {
 };
 
 struct irq_domain;
-struct device_node;
+struct fwnode_handle;
 int its_cpu_init(void);
-int its_init(struct device_node *node, struct rdists *rdists,
+int its_init(struct fwnode_handle *handle, struct rdists *rdists,
 	     struct irq_domain *domain);
 
 static inline bool gic_enable_sre(void)
-- 
1.9.1



From tn at semihalf.com  Tue May 31 04:19:44 2016
From: tn at semihalf.com (Tomasz Nowicki)
Date: Tue, 31 May 2016 13:19:44 +0200
Subject: [PATCH V5 7/7] acpi, gicv3,
 its: Use MADT ITS subtable to do PCI/MSI domain initialization.
In-Reply-To: <1464693584-22343-1-git-send-email-tn@semihalf.com>
References: <1464693584-22343-1-git-send-email-tn@semihalf.com>
Message-ID: <1464693584-22343-8-git-send-email-tn@semihalf.com>

Let ACPI build ITS PCI MSI domain. ACPI is responsible for retrieving
inner domain token and passing it on to its_pci_msi_init_one generic
init call.

We have now full PCI MSI domain stack, thus we can enable ITS initialization
from GICv3 core driver for ACPI scenario.

Signed-off-by: Tomasz Nowicki <tn at semihalf.com>
---
 drivers/irqchip/irq-gic-v3-its-pci-msi.c | 42 +++++++++++++++++++++++++++++++-
 drivers/irqchip/irq-gic-v3.c             |  3 +--
 2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
index 23679ae..985f5d9 100644
--- a/drivers/irqchip/irq-gic-v3-its-pci-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/iort.h>
 #include <linux/msi.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
@@ -144,10 +145,49 @@ static int __init its_pci_of_msi_init(void)
 	return 0;
 }
 
+#ifdef CONFIG_ACPI
+
+static int __init
+its_pci_msi_parse_madt(struct acpi_subtable_header *header,
+		       const unsigned long end)
+{
+	struct acpi_madt_generic_translator *its_entry;
+	struct fwnode_handle *dom_handle;
+	char node_name[6 + 16 + 1]; // ITS identification name
+
+	its_entry = (struct acpi_madt_generic_translator *)header;
+	snprintf(node_name, 23, "ITS at 0x%lx", (long)its_entry->base_address);
+	dom_handle = iort_its_find_domain_token(its_entry->translation_id);
+	if (!dom_handle) {
+		pr_err("%s: Unable to locate ITS domain handle\n", node_name);
+		return 0;
+	}
+
+	if (its_pci_msi_init_one(dom_handle, node_name))
+		return 0;
+
+	pr_info("PCI/MSI: %s domain created\n", node_name);
+	return 0;
+}
+
+static int __init its_pci_acpi_msi_init(void)
+{
+	acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
+			      its_pci_msi_parse_madt, 0);
+	return 0;
+}
+#else
+inline static int __init its_pci_acpi_msi_init(void)
+{
+	return 0;
+}
+#endif
+
 static int __init its_pci_msi_init(void)
 {
 	its_pci_of_msi_init();
+	its_pci_acpi_msi_init();
+
 	return 0;
 }
-
 early_initcall(its_pci_msi_init);
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index cee8296..41c1cda 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -951,8 +951,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
 
 	set_handle_irq(gic_handle_irq);
 
-	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis() &&
-	    to_of_node(handle)) /* Temp hack to prevent ITS init for ACPI */
+	if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
 		its_init(handle, &gic_data.rdists, gic_data.domain);
 
 	gic_smp_init();
-- 
1.9.1



From robin.murphy at arm.com  Tue May 31 04:22:33 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 31 May 2016 12:22:33 +0100
Subject: [PATCH v2] arm64: Implement optimised IP checksum helpers
Message-ID: <ba9cf5bf84b8adc766f7f7511dda8cb501cd4101.1464693619.git.robin.murphy@arm.com>

AArch64 is capable of 128-bit memory accesses without alignment
restrictions, which makes it both possible and highly practical to slurp
up a typical 20-byte IP header in just 2 loads. Implement our own
version of ip_fast_checksum() to take advantage of that, resulting in
considerably fewer instructions and memory accesses than the generic
version. We can also get more optimal code generation for csum_fold() by
defining it a slightly different way round from the generic version, so
throw that into the mix too.

Suggested-by: Luke Starrett <luke.starrett at broadcom.com>
Acked-by: Luke Starrett <luke.starrett at broadcom.com>
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---

Minor changes: include types.h for correctness, add Luke's ack.

 arch/arm64/include/asm/checksum.h | 51 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)
 create mode 100644 arch/arm64/include/asm/checksum.h

diff --git a/arch/arm64/include/asm/checksum.h b/arch/arm64/include/asm/checksum.h
new file mode 100644
index 000000000000..09f65339d66d
--- /dev/null
+++ b/arch/arm64/include/asm/checksum.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_CHECKSUM_H
+#define __ASM_CHECKSUM_H
+
+#include <linux/types.h>
+
+static inline __sum16 csum_fold(__wsum csum)
+{
+	u32 sum = (__force u32)csum;
+	sum += (sum >> 16) | (sum << 16);
+	return ~(__force __sum16)(sum >> 16);
+}
+#define csum_fold csum_fold
+
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	__uint128_t tmp;
+	u64 sum;
+
+	tmp = *(const __uint128_t *)iph;
+	iph += 16;
+	ihl -= 4;
+	tmp += ((tmp >> 64) | (tmp << 64));
+	sum = tmp >> 64;
+	do {
+		sum += *(const u32 *)iph;
+		iph += 4;
+	} while (--ihl);
+
+	sum += ((sum >> 32) | (sum << 32));
+	return csum_fold(sum >> 32);
+}
+#define ip_fast_csum ip_fast_csum
+
+#include <asm-generic/checksum.h>
+
+#endif	/* __ASM_CHECKSUM_H */
-- 
2.8.1.dirty



From thunder.leizhen at huawei.com  Tue May 31 04:27:25 2016
From: thunder.leizhen at huawei.com (Leizhen (ThunderTown))
Date: Tue, 31 May 2016 19:27:25 +0800
Subject: [PATCH v2 5/5] arm64/numa: avoid inconsistent information to be
 printed
In-Reply-To: <574D543A.2090406@suse.com>
References: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
 <1464427377-12712-6-git-send-email-thunder.leizhen@huawei.com>
 <574D543A.2090406@suse.com>
Message-ID: <574D751D.9020901@huawei.com>



On 2016/5/31 17:07, Matthias Brugger wrote:
> 
> 
> On 28/05/16 11:22, Zhen Lei wrote:
>> numa_init(of_numa_init) may returned error because of numa configuration
>> error. So "No NUMA configuration found" is inaccurate. In fact, specific
>> configuration error information should be immediately printed by the
>> testing branch.
>>
>> Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
>> ---
> 
> Which kernel version is this patch based on?

Base on mainline(git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git), I git pulled about 3-5 days ago, the last commit-id is dc03c0f.

And thess patches base on https://lkml.org/lkml/2016/5/24/679 series(acpi numa) as David Daney's requirement.

> 
> Regards,
> Matthias
> 
>>   arch/arm64/mm/numa.c | 6 +++---
>>   drivers/of/of_numa.c | 7 +++----
>>   2 files changed, 6 insertions(+), 7 deletions(-)
>>
>> diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
>> index 2601660..1b9622c 100644
>> --- a/arch/arm64/mm/numa.c
>> +++ b/arch/arm64/mm/numa.c
>> @@ -338,8 +338,10 @@ static int __init numa_init(int (*init_func)(void))
>>       if (ret < 0)
>>           return ret;
>>
>> -    if (nodes_empty(numa_nodes_parsed))
>> +    if (nodes_empty(numa_nodes_parsed)) {
>> +        pr_info("No NUMA configuration found\n");
>>           return -EINVAL;
>> +    }
>>
>>       ret = numa_register_nodes();
>>       if (ret < 0)
>> @@ -370,8 +372,6 @@ static int __init dummy_numa_init(void)
>>
>>       if (numa_off)
>>           pr_info("NUMA disabled\n"); /* Forced off on command line. */
>> -    else
>> -        pr_info("No NUMA configuration found\n");
>>       pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
>>              0LLU, PFN_PHYS(max_pfn) - 1);
>>
>> diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
>> index fb62307..3157130 100644
>> --- a/drivers/of/of_numa.c
>> +++ b/drivers/of/of_numa.c
>> @@ -63,7 +63,7 @@ static int __init of_numa_parse_memory_nodes(void)
>>       struct device_node *np = NULL;
>>       struct resource rsrc;
>>       u32 nid;
>> -    int i, r = 0;
>> +    int i, r;
>>
>>       for_each_node_by_type(np, "memory") {
>>           r = of_property_read_u32(np, "numa-node-id", &nid);
>> @@ -81,12 +81,11 @@ static int __init of_numa_parse_memory_nodes(void)
>>           if (!i || r) {
>>               of_node_put(np);
>>               pr_err("NUMA: bad property in memory node\n");
>> -            r = r ? : -EINVAL;
>> -            break;
>> +            return r ? : -EINVAL;
>>           }
>>       }
>>
>> -    return r;
>> +    return 0;
>>   }
>>
> 
> Well this is fixing changes you introduced in this patch-set. Any reason this is not part of patch 2?

Because they fixed two different problems.

> 
>>   static int __init of_numa_parse_distance_map_v1(struct device_node *map)
>> -- 
>> 2.5.0
>>
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
> 
> .
> 



From mark.rutland at arm.com  Tue May 31 04:33:00 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 12:33:00 +0100
Subject: [PATCH 0/3] arm64: Kill ESR_LNX_EXEC
Message-ID: <1464694383-31700-1-git-send-email-mark.rutland@arm.com>

Currently we (ab)use a reserved bit in ESR_ELx for our own purposes as
ESR_LNX_EXEC, which isn't ideal, especially as we're inconsistent with our
mnemonic usage. This series removes ESR_LNX_EXEC entirely, avoiding (ab)use of
reserved ESR_ELx bits, and makes things a little more consistent.

I've extracted this from my entry-deasm branch [1], and rebased to v4.7-rc1.
I've split the KVM changes as the KVM code is undergoing rapid change these
days, and it should be possible to take those as a subsequent cleanup rather
than forcing a painful merging process.

Thanks,
Mark.

[1] https://git.kernel.org/cgit/linux/kernel/git/mark/linux.git/log/?h=arm64/entry-deasm


Mark Rutland (3):
  arm64: add macro to extract ESR_ELx.EC
  arm64/kvm: use ESR_ELx_EC to extract EC
  arm64: kill ESR_LNX_EXEC

 arch/arm64/include/asm/esr.h         |  1 +
 arch/arm64/include/asm/kvm_emulate.h |  2 +-
 arch/arm64/kernel/entry.S            |  2 +-
 arch/arm64/kernel/traps.c            |  2 +-
 arch/arm64/kvm/handle_exit.c         |  4 ++--
 arch/arm64/kvm/hyp/switch.c          |  2 +-
 arch/arm64/mm/fault.c                | 15 +++++++++------
 7 files changed, 16 insertions(+), 12 deletions(-)

-- 
1.9.1



From mark.rutland at arm.com  Tue May 31 04:33:01 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 12:33:01 +0100
Subject: [PATCH 1/3] arm64: add macro to extract ESR_ELx.EC
In-Reply-To: <1464694383-31700-1-git-send-email-mark.rutland@arm.com>
References: <1464694383-31700-1-git-send-email-mark.rutland@arm.com>
Message-ID: <1464694383-31700-2-git-send-email-mark.rutland@arm.com>

Several places open-code extraction of the EC field from an ESR_ELx
value, in subtly different ways. This is unfortunate duplication and
variation, and the precise logic used to extract the field is a
distraction.

This patch adds a new macro, ESR_ELx_EC(), to extract the EC field from
an ESR_ELx value in a consistent fashion.

Existing open-coded extractions in core arm64 code are moved over to the
new helper. KVM code is left as-is for the moment.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Tested-by: Huang Shijie <shijie.huang at arm.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Dave P Martin <dave.martin at arm.com>
Cc: James Morse <james.morse at arm.com>
Cc: Marc Zyngier <marc.zyngier at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
---
 arch/arm64/include/asm/esr.h | 1 +
 arch/arm64/kernel/traps.c    | 2 +-
 arch/arm64/mm/fault.c        | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index 77eeb2c..f772e15 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -74,6 +74,7 @@
 
 #define ESR_ELx_EC_SHIFT	(26)
 #define ESR_ELx_EC_MASK		(UL(0x3F) << ESR_ELx_EC_SHIFT)
+#define ESR_ELx_EC(esr)		(((esr) & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT)
 
 #define ESR_ELx_IL		(UL(1) << 25)
 #define ESR_ELx_ISS_MASK	(ESR_ELx_IL - 1)
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index c539208..673d8d7 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -465,7 +465,7 @@ static const char *esr_class_str[] = {
 
 const char *esr_get_class_string(u32 esr)
 {
-	return esr_class_str[esr >> ESR_ELx_EC_SHIFT];
+	return esr_class_str[ESR_ELx_EC(esr)];
 }
 
 /*
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 5954881..6b6f5ec 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -244,7 +244,7 @@ out:
 
 static inline int permission_fault(unsigned int esr)
 {
-	unsigned int ec       = (esr & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT;
+	unsigned int ec       = ESR_ELx_EC(esr);
 	unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE;
 
 	return (ec == ESR_ELx_EC_DABT_CUR && fsc_type == ESR_ELx_FSC_PERM);
-- 
1.9.1



From mark.rutland at arm.com  Tue May 31 04:33:03 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 12:33:03 +0100
Subject: [PATCH 3/3] arm64: kill ESR_LNX_EXEC
In-Reply-To: <1464694383-31700-1-git-send-email-mark.rutland@arm.com>
References: <1464694383-31700-1-git-send-email-mark.rutland@arm.com>
Message-ID: <1464694383-31700-4-git-send-email-mark.rutland@arm.com>

Currently we treat ESR_EL1 bit 24 as software-defined for distinguishing
instruction aborts from data aborts, but this bit is architecturally
RES0 for instruction aborts, and could be allocated for an arbitrary
purpose in future. Additionally, we hard-code the value in entry.S
without the mnemonic, making the code difficult to understand.

Instead, remove ESR_LNX_EXEC, and distinguish aborts based on the esr,
which we already pass to the sole use of ESR_LNX_EXEC. A new helper,
is_el0_instruction_abort() is added to make the logic clear. Any
instruction aborts taken from EL1 will already have been handled by
bad_mode, so we need not handle that case in the helper.

For consistency, the existing permission_fault helper is renamed to
is_permission_fault, and the return type is changed to bool. There
should be no functional changes as the return value was a boolean
expression, and the result is only used in another boolean expression.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Dave P Martin <dave.martin at arm.com>
Cc: Huang Shijie <shijie.huang at arm.com>
Cc: James Morse <james.morse at arm.com>
Cc: Marc Zyngier <marc.zyngier at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
---
 arch/arm64/kernel/entry.S |  2 +-
 arch/arm64/mm/fault.c     | 13 ++++++++-----
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 12e8d2b..eefffa8 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -532,7 +532,7 @@ el0_ia:
 	enable_dbg_and_irq
 	ct_user_exit
 	mov	x0, x26
-	orr	x1, x25, #1 << 24		// use reserved ISS bit for instruction aborts
+	mov	x1, x25
 	mov	x2, sp
 	bl	do_mem_abort
 	b	ret_to_user
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 6b6f5ec..5af5f7f 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -202,8 +202,6 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
 #define VM_FAULT_BADMAP		0x010000
 #define VM_FAULT_BADACCESS	0x020000
 
-#define ESR_LNX_EXEC		(1 << 24)
-
 static int __do_page_fault(struct mm_struct *mm, unsigned long addr,
 			   unsigned int mm_flags, unsigned long vm_flags,
 			   struct task_struct *tsk)
@@ -242,7 +240,7 @@ out:
 	return fault;
 }
 
-static inline int permission_fault(unsigned int esr)
+static inline bool is_permission_fault(unsigned int esr)
 {
 	unsigned int ec       = ESR_ELx_EC(esr);
 	unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE;
@@ -250,6 +248,11 @@ static inline int permission_fault(unsigned int esr)
 	return (ec == ESR_ELx_EC_DABT_CUR && fsc_type == ESR_ELx_FSC_PERM);
 }
 
+static bool is_el0_instruction_abort(unsigned int esr)
+{
+	return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_LOW;
+}
+
 static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 				   struct pt_regs *regs)
 {
@@ -272,14 +275,14 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 	if (user_mode(regs))
 		mm_flags |= FAULT_FLAG_USER;
 
-	if (esr & ESR_LNX_EXEC) {
+	if (is_el0_instruction_abort(esr)) {
 		vm_flags = VM_EXEC;
 	} else if ((esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM)) {
 		vm_flags = VM_WRITE;
 		mm_flags |= FAULT_FLAG_WRITE;
 	}
 
-	if (permission_fault(esr) && (addr < USER_DS)) {
+	if (is_permission_fault(esr) && (addr < USER_DS)) {
 		if (get_fs() == KERNEL_DS)
 			die("Accessing user space memory with fs=KERNEL_DS", regs, esr);
 
-- 
1.9.1



From mark.rutland at arm.com  Tue May 31 04:33:02 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 12:33:02 +0100
Subject: [PATCH 2/3] arm64/kvm: use ESR_ELx_EC to extract EC
In-Reply-To: <1464694383-31700-1-git-send-email-mark.rutland@arm.com>
References: <1464694383-31700-1-git-send-email-mark.rutland@arm.com>
Message-ID: <1464694383-31700-3-git-send-email-mark.rutland@arm.com>

Now that we have a helper to extract the EC from an ESR_ELx value, make
use of this in the arm64 KVM code for simplicity and consistency. There
should be no functional changes as a result of this patch.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Christoffer Dall <christoffer.dall at linaro.org>
Cc: Dave P Martin <dave.martin at arm.com>
Cc: Huang Shijie <shijie.huang at arm.com>
Cc: James Morse <james.morse at arm.com>
Cc: Marc Zyngier <marc.zyngier at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
Cc: kvmarm at lists.cs.columbia.edu
---
 arch/arm64/include/asm/kvm_emulate.h | 2 +-
 arch/arm64/kvm/handle_exit.c         | 4 ++--
 arch/arm64/kvm/hyp/switch.c          | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index 40bc168..4cdeae3 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -210,7 +210,7 @@ static inline bool kvm_vcpu_trap_il_is32bit(const struct kvm_vcpu *vcpu)
 
 static inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu)
 {
-	return kvm_vcpu_get_hsr(vcpu) >> ESR_ELx_EC_SHIFT;
+	return ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu));
 }
 
 static inline bool kvm_vcpu_trap_is_iabt(const struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 3246c4a..fa96fe2 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -106,7 +106,7 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, struct kvm_run *run)
 	run->exit_reason = KVM_EXIT_DEBUG;
 	run->debug.arch.hsr = hsr;
 
-	switch (hsr >> ESR_ELx_EC_SHIFT) {
+	switch (ESR_ELx_EC(hsr)) {
 	case ESR_ELx_EC_WATCHPT_LOW:
 		run->debug.arch.far = vcpu->arch.fault.far_el2;
 		/* fall through */
@@ -149,7 +149,7 @@ static exit_handle_fn arm_exit_handlers[] = {
 static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
 {
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
-	u8 hsr_ec = hsr >> ESR_ELx_EC_SHIFT;
+	u8 hsr_ec = ESR_ELx_EC(hsr);
 
 	if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers) ||
 	    !arm_exit_handlers[hsr_ec]) {
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 437cfad..4373997 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -198,7 +198,7 @@ static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar)
 static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
 {
 	u64 esr = read_sysreg_el2(esr);
-	u8 ec = esr >> ESR_ELx_EC_SHIFT;
+	u8 ec = ESR_ELx_EC(esr);
 	u64 hpfar, far;
 
 	vcpu->arch.fault.esr_el2 = esr;
-- 
1.9.1



From julien.grall at arm.com  Tue May 31 04:41:23 2016
From: julien.grall at arm.com (Julien Grall)
Date: Tue, 31 May 2016 12:41:23 +0100
Subject: [PATCH 3/3] drivers/perf: arm_pmu: Avoid leaking pmu->irq_affinity on
 error
In-Reply-To: <1464694883-26298-1-git-send-email-julien.grall@arm.com>
References: <1464694883-26298-1-git-send-email-julien.grall@arm.com>
Message-ID: <1464694883-26298-4-git-send-email-julien.grall@arm.com>

pmu->irq_affinity will not be freed if an error occurred within
arm_pmu_device_probe after of_pmu_irq_cfg has been called.

Note that in the case of_pmu_irq_cfg is returning an error,
pmu->irq_affinity will not be set, but it should be NULL as pmu was
kzalloc'd. Therefore the result kfree(NULL) is benign.

Signed-off-by: Julien Grall <julien.grall at arm.com>
Acked-by: Mark Rutland <mark.rutland at arm.com>
---
 drivers/perf/arm_pmu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 95614d2..1b8304e 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -1040,6 +1040,7 @@ out_destroy:
 out_free:
 	pr_info("%s: failed to register PMU devices!\n",
 		of_node_full_name(node));
+	kfree(pmu->irq_affinity);
 	kfree(pmu);
 	return ret;
 }
-- 
1.9.1



From julien.grall at arm.com  Tue May 31 04:41:20 2016
From: julien.grall at arm.com (Julien Grall)
Date: Tue, 31 May 2016 12:41:20 +0100
Subject: [PATCH 0/3] drivers/perf: arm_pmu: Small bug fixes in the driver
Message-ID: <1464694883-26298-1-git-send-email-julien.grall@arm.com>

Hello all,

This patch series contains a series of small bug fixes for the arm_pmu
drivers.

I think all the patch should be backported to stable but I have not figured
out up to which version.

Julien Grall (3):
  drivers/perf: arm_pmu: Fix reference count of a device_node in
    of_pmu_irq_cfg
  drivers/perf: arm_pmu: Defer the setting of __oprofile_cpu_pmu
  drivers/perf: arm_pmu: Avoid leaking pmu->irq_affinity on error

 drivers/perf/arm_pmu.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

-- 
1.9.1



From julien.grall at arm.com  Tue May 31 04:41:21 2016
From: julien.grall at arm.com (Julien Grall)
Date: Tue, 31 May 2016 12:41:21 +0100
Subject: [PATCH 1/3] drivers/perf: arm_pmu: Fix reference count of a
 device_node in of_pmu_irq_cfg
In-Reply-To: <1464694883-26298-1-git-send-email-julien.grall@arm.com>
References: <1464694883-26298-1-git-send-email-julien.grall@arm.com>
Message-ID: <1464694883-26298-2-git-send-email-julien.grall@arm.com>

The only function called by of_pmu_irq_cfg that will increment the
reference count on dn is of_parse_phandle.

Each time we successfully parse a possible CPU from an
interrupt-affinity property, we increment the refcount of that CPU node
once via of_parse_handle. After validating the CPU is possible, we
decrement the refcount once. Subsequently, we decrement the refcount
again, either as part of an early break if we don't have a matching SPI,
or as part of the end of the loop body.

This will lead to decrementing twice the refcounnt.
Remove the second pairs of call to of_node_put as nobody is using dn
between the first and second call to of_node_put.

Signed-off-by: Julien Grall <julien.grall at arm.com>
Acked-by: Mark Rutland <mark.rutland at arm.com>
---
 drivers/perf/arm_pmu.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index f2d01d4..6401f0c 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -950,17 +950,14 @@ static int of_pmu_irq_cfg(struct arm_pmu *pmu)
 
 		/* For SPIs, we need to track the affinity per IRQ */
 		if (using_spi) {
-			if (i >= pdev->num_resources) {
-				of_node_put(dn);
+			if (i >= pdev->num_resources)
 				break;
-			}
 
 			irqs[i] = cpu;
 		}
 
 		/* Keep track of the CPUs containing this PMU type */
 		cpumask_set_cpu(cpu, &pmu->supported_cpus);
-		of_node_put(dn);
 		i++;
 	} while (1);
 
-- 
1.9.1



From julien.grall at arm.com  Tue May 31 04:41:22 2016
From: julien.grall at arm.com (Julien Grall)
Date: Tue, 31 May 2016 12:41:22 +0100
Subject: [PATCH 2/3] drivers/perf: arm_pmu: Defer the setting of
 __oprofile_cpu_pmu
In-Reply-To: <1464694883-26298-1-git-send-email-julien.grall@arm.com>
References: <1464694883-26298-1-git-send-email-julien.grall@arm.com>
Message-ID: <1464694883-26298-3-git-send-email-julien.grall@arm.com>

The global variable __oprofile_cpu_pmu is set before the PMU is fully
initialized. If an error occurs before the end of the initialization,
the PMU will be freed and the variable will contain an invalid pointer.

This will result in a kernel crash when perf will be used.

Fix it by moving the setting of __oprofile_cpu_pmu when the PMU is fully
initialized (i.e when it is no longer possible to fail).

Signed-off-by: Julien Grall <julien.grall at arm.com>
Acked-by: Mark Rutland <mark.rutland at arm.com>
---
 drivers/perf/arm_pmu.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 6401f0c..95614d2 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -992,9 +992,6 @@ int arm_pmu_device_probe(struct platform_device *pdev,
 
 	armpmu_init(pmu);
 
-	if (!__oprofile_cpu_pmu)
-		__oprofile_cpu_pmu = pmu;
-
 	pmu->plat_device = pdev;
 
 	if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) {
@@ -1030,6 +1027,9 @@ int arm_pmu_device_probe(struct platform_device *pdev,
 	if (ret)
 		goto out_destroy;
 
+	if (!__oprofile_cpu_pmu)
+		__oprofile_cpu_pmu = pmu;
+
 	pr_info("enabled with %s PMU driver, %d counters available\n",
 			pmu->name, pmu->num_events);
 
-- 
1.9.1



From arnd at arndb.de  Tue May 31 04:43:43 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 31 May 2016 13:43:43 +0200
Subject: [BUG] CONFIG_UNINLINE_SPIN_UNLOCK important for Cortex-A9
In-Reply-To: <871t4io608.fsf@gmail.com>
References: <874m9eoetu.fsf@gmail.com> <4854518.jvbplH0SM0@wuerfel>
 <871t4io608.fsf@gmail.com>
Message-ID: <6689734.3ffZe38SoY@wuerfel>

On Tuesday, May 31, 2016 12:51:03 PM CEST Holger Schurig wrote:
> > Have you tried multi_v7_defconfig? That also does not set 
> > CONFIG_UNINLINE_SPIN_UNLOCK, but it is generally assumed to work.
> 
> Not yet, will try this (see below).

Ok

> > Just to be sure: If you just enable UNINLINE_SPIN_UNLOCK (e.g. using
> > a 'select' from arch/arm/mach-imx/Kconfig) without selecting PROVE_RCU,
> > you say the bug is gone too?
> 
> Currently I select it indirectly. One person that tried to help me
> turned on 29 different kernel debug options and the bug was gone. Then I
> reduced this step by step to find out which of them was needed
> minimally.
> 
> Still I don't think that it's an RCU issue. But it could of course be a
> "Heisenbug".

I would also not guess RCU as the first possibility. I was first guessing
that something might be wrong with arch_spin_unlock(), but it's actually
a really trivial function:

static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
       smp_mb();
       lock->tickets.owner++;
       dsb_sev();
}

so there is really not much that can go wrong, and if there is,
then presumably either smp_mb() or dsb_sev() is not as strong
a barrier here as it should be, and that seems very unlikely.

The last change to the function was a while ago, but you could
try reverting this commit if nothing else helps:

commit 20e260b6f4f717c100620122f626a2c06a4cfd72
Author: Will Deacon <will.deacon at arm.com>
Date:   Thu Jan 24 14:47:38 2013 +0100

    ARM: 7632/1: spinlock: avoid exclusive accesses on unlock() path
    
    When unlocking a spinlock, all we need to do is increment the owner
    field of the lock. Since only one CPU can be performing an unlock()
    operation for a given lock, this doesn't need to be exclusive.
    
    This patch simplifies arch_spin_unlock to use non-exclusive accesses
    when updating the owner field of the lock.
    
    Signed-off-by: Will Deacon <will.deacon at arm.com>
    Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>

diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h
index b4ca707d0a69..6220e9fdf4c7 100644
--- a/arch/arm/include/asm/spinlock.h
+++ b/arch/arm/include/asm/spinlock.h
@@ -119,22 +119,8 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock)
 
 static inline void arch_spin_unlock(arch_spinlock_t *lock)
 {
-	unsigned long tmp;
-	u32 slock;
-
 	smp_mb();
-
-	__asm__ __volatile__(
-"	mov	%1, #1\n"
-"1:	ldrex	%0, [%2]\n"
-"	uadd16	%0, %0, %1\n"
-"	strex	%1, %0, [%2]\n"
-"	teq	%1, #0\n"
-"	bne	1b"
-	: "=&r" (slock), "=&r" (tmp)
-	: "r" (&lock->slock)
-	: "cc");
-
+	lock->tickets.owner++;
 	dsb_sev();
 }

> > - Specific kernel version, and full list of patches applied (if any).
> >   Have you reproduced this with a plain unpatched linux-4.6 kernel?
> 
> I'm not in love with vendor-kernels, so I use kernels from kernel.org.
> When I started to chase the oops happened in 4.4.4, but the behavior was
> also present in 4.5, 4.5.1 ... 4.5.4 and 4.6.
> 
> I have some patches applied, e.g. aufs4, one patch in the i.MX6Q FEC
> ethernet driver and stuff to program the eMMC firmware. Nothing that
> plays with rcu, spinlocks etc, e.g. no preempt or Linux-RT patches.
> 
> However, a vanilla kernel boots on my device (isn't device tree
> nice?!?!?) and here I had the same behavior. I think that vanilla kernel
> was 4.5.3, but I'm unsure.

Ok, good, that should make it easy to reproduce.

> 
> > - Specific gcc version you used for building the kernel. Does this
> >   happen with both old and new compilers, e.g. 4.7 and 6.1?
> 
> I don't have yet a gcc 6.1 armhf cross compiler.

It's fairly straightforward to build gcc binaries for testing kernels
using Segher's "buildall" script from 
git://git.infradead.org/users/segher/buildall.git

I use that for testing out lots of gcc versions across architectures
when I run into a bug that is version specific.

> My gcc used to be
> http://releases.linaro.org/14.04/components/toolchain/binaries/gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux.tar.xz
> but during the bug chase I switched to Debian's cross-gcc. It says it is
> "arm-linux-gnueabihf-gcc ( 4.9.2-10) 4.9.2".
> 
> A kernel compiled by someone else with some "gcc-4.8
> 4.8.4-2ubuntu1~14.04" also had the same oopsing-behavior.

ok. Both of them are a few years old, so it would be interesting to
try a new version, probably not so interesting to try anything older.

If you like, I can also send you a tarball with gcc-6 binaries

> > - If it happens with an unpatched linux-4.6 and all gcc versions
> >   with multi_v7_defconfig, we should try reproducing it on some
> >   other quad-core Cortex-A9 (non-imx) platform with the same kernel
> >   binary.
> 
> I will try to reproduce it, as said it can take between 3 to 24 hours.
> 
> I'll be using
> 
> - vanilla 4.6 without any patch
> - ... and without any device-specific kernel module
> - multi_v7_defconfig
> - Debian 4.9.2 cross-compiler

awesome.

> [    2.844408] Bluetooth: L2CAP socket layer initialized
> [    2.849514] Bluetooth: SCO socket layer initialized
> [    2.895099] usbcore: registered new interface driver btusb
> [    3.257897] SMSC LAN8710/LAN8720 2188000.ethernet:00: attached PHY driver [SMSC LAN8710/LAN8720] (mii_bus:phy_addr=2188000.ethernet:00, irq=-1)
> [17827.758966] Unable to handle kernel paging request at virtual address 00001014

0x1014 is a rather long offset, but still a plausible NULL pointer. The r10 register
contains 0x1000, so this is probably an incorrect value and is being used as a pointer
with offset 0x14 added in. With an objdump of your net/core/dev.o, we could
see which pointer that was, to maybe figure out which lock is supposed to protect
it and where that lock gets released.

> [17827.766279] pgd = ee09c000
> [17827.769003] [00001014] *pgd=3eba3831, *pte=00000000, *ppte=00000000
> [17827.775383] Internal error: Oops: 17 [#1] SMP ARM
> [17827.780108] Modules linked in: usbhid btusb btrtl btbcm btintel bluetooth flexcan smsc95xx usbnet mii ptxc(O)
> [17827.790242] CPU: 1 PID: 372 Comm: stress-ng-socke Tainted: G           O    4.5.4 #1
> [17827.797995] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
> [17827.804536] task: ed614780 ti: eebba000 task.ti: eebba000
> [17827.809977] PC is at __netif_receive_skb_core+0x328/0xa9c

Unfortunately in the middle of a rather long function, and I don't
see a spin_unlock in this function, in fact it's not even called
with a spinlock held, so it must be something more indirect.

> [17828.297390]  r4:ef7ba1b8 r3:ef7ba148
> [17828.301008] [<c03aaa30>] (process_backlog) from [<c03aa2cc>] (net_rx_action+0x1fc/0x2f0)
> [17828.309101]  r10:eebbbaf0 r9:00000040 r8:c05ea100 r7:0000012c r6:001abec9 r5:c03aaa30
> [17828.317014]  r4:ef7ba1b8 r3:eebbbaf0
> [17828.320637] [<c03aa0d0>] (net_rx_action) from [<c0022444>] (__do_softirq+0x134/0x254)
> [17828.328470]  r10:c05ea080 r9:40000003 r8:00000101 r7:eebba000 r6:c05ea08c r5:00000003
> [17828.336381]  r4:00000000
> [17828.338937] [<c0022310>] (__do_softirq) from [<c0022624>] (do_softirq+0x68/0x70)
> [17828.346334]  r10:00000006 r9:ef06a800 r8:0000000e r7:00000000 r6:eeb1c200 r5:ee05ba30
> [17828.354238]  r4:60030013
> [17828.356797] [<c00225bc>] (do_softirq) from [<c00226e8>] (__local_bh_enable_ip+0xbc/0xd0)
> [17828.364890]  r4:00000200 r3:00000008
> [17828.368520] [<c002262c>] (__local_bh_enable_ip) from [<c03e0360>] (ip_finish_output2+0x1b4/0x3b8)
> [17828.377395]  r5:ee05ba30 r4:00000000
> [17828.381005] [<c03e01ac>] (ip_finish_output2) from [<c03e1ed4>] (ip_finish_output+0x14c/0x20c)
> [17828.389531]  r8:ee2d2c00 r7:ee2d2c00 r6:c0606280 r5:0000ffff r4:ee05ba30
> [17828.396321] [<c03e1d88>] (ip_finish_output) from [<c03e2a34>] (ip_output+0x124/0x130)
> [17828.404153]  r10:00000006 r9:ef06a800 r8:ee2d2c00 r7:00000000 r6:0971f1b9 r5:c0606280
> [17828.412061]  r4:ee05ba30

This might be the smoking gun: We are in the middle of do_softirq() as triggered
from a __local_bh_enable_ip. This is often called from __raw_spin_unlock_bh(),
though I don't see that call in ip_finish_output2.

http://lwn.net/Articles/687617/ has some explanation about how this mechanism
works, and what some recent plans to change that are. I don't immediately see
anything that could lead to your bug there, but it's a start.

	Arnd


From hramrach at gmail.com  Tue May 31 04:52:20 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: Tue, 31 May 2016 13:52:20 +0200
Subject: [linux-sunxi] [PATCH 1/5] spi: sunxi: fix transfer timeout
In-Reply-To: <20160530112350.GI29837@sirena.org.uk>
References: <cover.1464130597.git.hramrach@gmail.com>
 <cb90b922caa6ac07c1425d726ea19709ee5284f4.1464130597.git.hramrach@gmail.com>
 <CAGRGNgWDrVHG26umTSHHAxFC3KXjwmpDejBAfKqvuik0_2-Jcw@mail.gmail.com>
 <CAOMqctS0AD6rHGt3wjxxyidee=_5xqby95t5TGuozAA12DdPjQ@mail.gmail.com>
 <CAGRGNgW=UnmwwiREV+nVcws6sk18-4fKz3qf-WKf4LY9-VqBKg@mail.gmail.com>
 <20160530112350.GI29837@sirena.org.uk>
Message-ID: <CAOMqctQqJaKBA++yiniroEcTjWCMD5WT7CpVjTYBmLzGcB2vYw@mail.gmail.com>

Hello

On 30 May 2016 at 13:23, Mark Brown <broonie at kernel.org> wrote:
> On Fri, May 27, 2016 at 03:10:11PM +1000, Julian Calaby wrote:
>> On Fri, May 27, 2016 at 3:05 PM, Michal Suchanek <hramrach at gmail.com> wrote:
>
>> >> Also, should the changes for the drivers be in two separate patches also?
>
>> > That's basically the same driver with different constants so I guess not.
>
>> Fair enough, I withdraw my comment then.
>
> If it's the same driver with different constants it should really
> actually be the same driver - I did ask this when the drivers were
> originally merged...

There are some slight differences and the constants really are
different for each driver.

You would need a register remap adaptation layer and a few qirks for
each revision of the driver.

It's certainly possible to merge them but I am not sure if that gives
easier to maintain code.

On the other hand, comparing the drivers there is different comment
anout clock calculation arithmetic and the code is the same :S

Thanks

Michal

--- spi-sun4i.c    2016-05-31 13:19:27.076510421 +0200
+++ spi-sun6i.c    2016-05-31 13:26:58.123580382 +0200
@@ -19,65 +19,72 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/reset.h>

 #include <linux/spi/spi.h>

-#define SUNXI_FIFO_DEPTH            64
+#define SUNXI_FIFO_DEPTH            128

-#define SUNXI_RXDATA_REG            0x00
+#define SUNXI_TXDATA_REG            0x200

-#define SUNXI_TXDATA_REG            0x04
+#define SUNXI_RXDATA_REG            0x300

 #define SUNXI_TFR_CTL_REG            0x08
-#define SUNXI_TFR_CTL_ENABLE            BIT(0)
-#define SUNXI_TFR_CTL_MASTER            BIT(1)
-#define SUNXI_TFR_CTL_CPHA            BIT(2)
-#define SUNXI_TFR_CTL_CPOL            BIT(3)
-#define SUNXI_TFR_CTL_CS_ACTIVE_LOW        BIT(4)
-#define SUNXI_TFR_CTL_LMTF            BIT(6)
-#define SUNXI_TFR_CTL_TF_RST            BIT(8)
-#define SUNXI_TFR_CTL_RF_RST            BIT(9)
-#define SUNXI_TFR_CTL_XCH            BIT(10)
-#define SUNXI_TFR_CTL_CS_MASK            0x3000
-#define SUNXI_TFR_CTL_CS(cs)            (((cs) << 12) & SUNXI_TFR_CTL_CS_MASK)
-#define SUNXI_TFR_CTL_DHB            BIT(15)
-#define SUNXI_TFR_CTL_CS_MANUAL            BIT(16)
-#define SUNXI_TFR_CTL_CS_LEVEL            BIT(17)
-#define SUNXI_TFR_CTL_TP            BIT(18)
+#define SUNXI_TFR_CTL_CPHA            BIT(0)
+#define SUNXI_TFR_CTL_CPOL            BIT(1)
+#define SUNXI_TFR_CTL_SPOL            BIT(2)
+#define SUNXI_TFR_CTL_CS_MASK            0x30
+#define SUNXI_TFR_CTL_CS(cs)            (((cs) << 4) & SUNXI_TFR_CTL_CS_MASK)
+#define SUNXI_TFR_CTL_CS_MANUAL            BIT(6)
+#define SUNXI_TFR_CTL_CS_LEVEL            BIT(7)
+#define SUNXI_TFR_CTL_DHB            BIT(8)
+#define SUNXI_TFR_CTL_FBS            BIT(12)
+#define SUNXI_TFR_CTL_XCH            BIT(31)

-#define SUNXI_INT_CTL_REG            0x0c
-#define SUNXI_INT_CTL_TC            BIT(16)
+#define SUNXI_INT_CTL_REG            0x10
+#define SUNXI_INT_CTL_RF_OVF            BIT(8)
+#define SUNXI_INT_CTL_TC            BIT(12)

-#define SUNXI_INT_STA_REG            0x10
+#define SUNXI_INT_STA_REG            0x14

-#define SUNXI_DMA_CTL_REG            0x14
+#define SUNXI_FIFO_CTL_REG            0x18
+#define SUNXI_FIFO_CTL_RF_RST            BIT(15)
+#define SUNXI_FIFO_CTL_TF_RST            BIT(31)

-#define SUNXI_CLK_CTL_REG            0x1c
+#define SUNXI_CLK_CTL_REG            0x24
 #define SUNXI_CLK_CTL_CDR2_MASK            0xff
 #define SUNXI_CLK_CTL_CDR2(div)            (((div) &
SUNXI_CLK_CTL_CDR2_MASK) << 0)
 #define SUNXI_CLK_CTL_CDR1_MASK            0xf
 #define SUNXI_CLK_CTL_CDR1(div)            (((div) &
SUNXI_CLK_CTL_CDR1_MASK) << 8)
 #define SUNXI_CLK_CTL_DRS            BIT(12)

-#define SUNXI_BURST_CNT_REG            0x20
+#define SUNXI_BURST_CNT_REG            0x30
 #define SUNXI_BURST_CNT(cnt)            ((cnt) & 0xffffff)

-#define SUNXI_XMIT_CNT_REG            0x24
+#define SUNXI_XMIT_CNT_REG            0x34
 #define SUNXI_XMIT_CNT(cnt)            ((cnt) & 0xffffff)

-#define SUNXI_FIFO_STA_REG            0x28
+#define SUNXI_FIFO_STA_REG            0x1c
 #define SUNXI_FIFO_STA_RF_CNT_MASK        0x7f
 #define SUNXI_FIFO_STA_RF_CNT_BITS        0
 #define SUNXI_FIFO_STA_TF_CNT_MASK        0x7f
 #define SUNXI_FIFO_STA_TF_CNT_BITS        16

-#define SUNXI_WAIT_REG                0x18
+#define SUNXI_BURST_CTL_CNT_REG            0x38
+#define SUNXI_BURST_CTL_CNT_STC(cnt)        ((cnt) & 0xffffff)
+
+#define SUNXI_GBL_CTL_REG            0x04
+#define SUNXI_GBL_CTL_BUS_ENABLE        BIT(0)
+#define SUNXI_GBL_CTL_MASTER            BIT(1)
+#define SUNXI_GBL_CTL_TP            BIT(7)
+#define SUNXI_GBL_CTL_RST            BIT(31)

 struct sunxi_spi {
     struct spi_master    *master;
     void __iomem        *base_addr;
     struct clk        *hclk;
     struct clk        *mclk;
+    struct reset_control    *rstc;

     struct completion    done;

@@ -136,37 +143,18 @@
     u32 reg;

     reg = sunxi_spi_read(sspi, SUNXI_TFR_CTL_REG);
-
     reg &= ~SUNXI_TFR_CTL_CS_MASK;
     reg |= SUNXI_TFR_CTL_CS(spi->chip_select);

-    /* We want to control the chip select manually */
-    reg |= SUNXI_TFR_CTL_CS_MANUAL;
-
     if (enable)
         reg |= SUNXI_TFR_CTL_CS_LEVEL;
     else
         reg &= ~SUNXI_TFR_CTL_CS_LEVEL;

-    /*
-     * Even though this looks irrelevant since we are supposed to
-     * be controlling the chip select manually, this bit also
-     * controls the levels of the chip select for inactive
-     * devices.
-     *
-     * If we don't set it, the chip select level will go low by
-     * default when the device is idle, which is not really
-     * expected in the common case where the chip select is active
-     * low.
-     */
-    if (spi->mode & SPI_CS_HIGH)
-        reg &= ~SUNXI_TFR_CTL_CS_ACTIVE_LOW;
-    else
-        reg |= SUNXI_TFR_CTL_CS_ACTIVE_LOW;
-
     sunxi_spi_write(sspi, SUNXI_TFR_CTL_REG, reg);
 }

+
 static int sunxi_spi_transfer_one(struct spi_master *master,
                   struct spi_device *spi,
                   struct spi_transfer *tfr)
@@ -189,17 +177,16 @@
     /* Clear pending interrupts */
     sunxi_spi_write(sspi, SUNXI_INT_STA_REG, ~0);

-
-    reg = sunxi_spi_read(sspi, SUNXI_TFR_CTL_REG);
-
     /* Reset FIFOs */
-    sunxi_spi_write(sspi, SUNXI_TFR_CTL_REG,
-            reg | SUNXI_TFR_CTL_RF_RST | SUNXI_TFR_CTL_TF_RST);
+    sunxi_spi_write(sspi, SUNXI_FIFO_CTL_REG,
+            SUNXI_FIFO_CTL_RF_RST | SUNXI_FIFO_CTL_TF_RST);

     /*
      * Setup the transfer control register: Chip Select,
      * polarities, etc.
      */
+    reg = sunxi_spi_read(sspi, SUNXI_TFR_CTL_REG);
+
     if (spi->mode & SPI_CPOL)
         reg |= SUNXI_TFR_CTL_CPOL;
     else
@@ -211,10 +198,9 @@
         reg &= ~SUNXI_TFR_CTL_CPHA;

     if (spi->mode & SPI_LSB_FIRST)
-        reg |= SUNXI_TFR_CTL_LMTF;
+        reg |= SUNXI_TFR_CTL_FBS;
     else
-        reg &= ~SUNXI_TFR_CTL_LMTF;
-
+        reg &= ~SUNXI_TFR_CTL_FBS;

     /*
      * If it's a TX only transfer, we don't want to fill the RX
@@ -225,6 +211,9 @@
     else
         reg |= SUNXI_TFR_CTL_DHB;

+    /* We want to control the chip select manually */
+    reg |= SUNXI_TFR_CTL_CS_MANUAL;
+
     sunxi_spi_write(sspi, SUNXI_TFR_CTL_REG, reg);

     /* Ensure that we have a parent clock fast enough */
@@ -239,7 +228,7 @@
      *
      * We have two choices there. Either we can use the clock
      * divide rate 1, which is calculated thanks to this formula:
-     * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))
+     * SPI_CLK = MOD_CLK / (2 ^ cdr)
      * Or we can use CDR2, which is calculated with the formula:
      * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
      * Wether we use the former or the latter is set through the
@@ -268,6 +257,8 @@
     /* Setup the counters */
     sunxi_spi_write(sspi, SUNXI_BURST_CNT_REG, SUNXI_BURST_CNT(tfr->len));
     sunxi_spi_write(sspi, SUNXI_XMIT_CNT_REG, SUNXI_XMIT_CNT(tx_len));
+    sunxi_spi_write(sspi, SUNXI_BURST_CTL_CNT_REG,
+            SUNXI_BURST_CTL_CNT_STC(tx_len));

     /* Fill the TX FIFO */
     sunxi_spi_fill_fifo(sspi, SUNXI_FIFO_DEPTH);
@@ -327,11 +318,19 @@
         goto err;
     }

-    sunxi_spi_write(sspi, SUNXI_TFR_CTL_REG,
-            SUNXI_TFR_CTL_ENABLE | SUNXI_TFR_CTL_MASTER | SUNXI_TFR_CTL_TP);
+    ret = reset_control_deassert(sspi->rstc);
+    if (ret) {
+        dev_err(dev, "Couldn't deassert the device from reset\n");
+        goto err2;
+    }
+
+    sunxi_spi_write(sspi, SUNXI_GBL_CTL_REG,
+            SUNXI_GBL_CTL_BUS_ENABLE | SUNXI_GBL_CTL_MASTER |
SUNXI_GBL_CTL_TP);

     return 0;

+err2:
+    clk_disable_unprepare(sspi->mclk);
 err:
     clk_disable_unprepare(sspi->hclk);
 out:
@@ -343,6 +342,7 @@
     struct spi_master *master = dev_get_drvdata(dev);
     struct sunxi_spi *sspi = spi_master_get_devdata(master);

+    reset_control_assert(sspi->rstc);
     clk_disable_unprepare(sspi->mclk);
     clk_disable_unprepare(sspi->hclk);

@@ -411,6 +411,13 @@

     init_completion(&sspi->done);

+    sspi->rstc = devm_reset_control_get(&pdev->dev, NULL);
+    if (IS_ERR(sspi->rstc)) {
+        dev_err(&pdev->dev, "Couldn't get reset controller\n");
+        ret = PTR_ERR(sspi->rstc);
+        goto err_free_master;
+    }
+
     /*
      * This wake-up/shutdown pattern is to be able to have the
      * device woken up, even if runtime_pm is disabled
@@ -449,7 +456,7 @@
 }

 static const struct of_device_id sunxi_spi_match[] = {
-    { .compatible = "allwinner,sun4i-a10-spi", },
+    { .compatible = "allwinner,sun6i-a31-spi", },
     {}
 };
 MODULE_DEVICE_TABLE(of, sunxi_spi_match);
@@ -472,5 +479,5 @@

 MODULE_AUTHOR("Pan Nan <pannan at allwinnertech.com>");
 MODULE_AUTHOR("Maxime Ripard <maxime.ripard at free-electrons.com>");
-MODULE_DESCRIPTION("Allwinner A1X/A20 SPI controller driver");
+MODULE_DESCRIPTION("Allwinner A31 SPI controller driver");
 MODULE_LICENSE("GPL");


From k.kozlowski at samsung.com  Tue May 31 04:54:31 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 13:54:31 +0200
Subject: [RFC v2 00/13] usb/mmc/power: Fix USB/LAN when TFTP booting
In-Reply-To: <20160531005808.GA7913@shlinux2>
References: <1462451666-17945-1-git-send-email-k.kozlowski@samsung.com>
 <20160505224240.GA31429@rob-hp-laptop>
 <CAPDyKFqpoi03Egfuvd8qJXnn_+FBgPXAb7S4UvkxVs8BA+zwnA@mail.gmail.com>
 <20160509181829.GA19687@rob-hp-laptop>
 <CAPDyKFq2=mqujFjvJSYxg2nVmK=OrBKLtFfb-ErNJO3Zr_LMVw@mail.gmail.com>
 <20160528033613.GA3291@shlinux2> <20160531005808.GA7913@shlinux2>
Message-ID: <574D7B77.4000606@samsung.com>

On 05/31/2016 02:58 AM, Peter Chen wrote:
> On Sat, May 28, 2016 at 11:36:13AM +0800, Peter Chen wrote:
>> All, how we move on for this?
>>
>> 1. Using a generic driver to manage both mmc and USB (and further
>> subsystem), USB and further subsystem do not use pwrseq node in dts.
>> 2. USB creates the similar driver under drivers/usb for its own use. 
>>
>> Which one do you prefer, thanks.
>>
> 
> Hi Krzysztof Kozlowski,
> 
> I think option 1 may be better according to Rob and Ulf's comment.

Hi,

I like the option #1 as well. The generic driver should rely and parse
existing bindings like 'reset-gpios'. Still additional property (e.g.
"do-the-power-sequence") seems needed as we do not want to play with all
reset-gpios in DTB.

> Would you like going on your patch set? You can work on generic pwrseq
> driver, I will do USB stuffs based on generic pwrseq driver?

Great, that sounds good! I'll start the work.

Best regards,
Krzysztof



From suzuki.poulose at arm.com  Tue May 31 04:57:35 2016
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 31 May 2016 12:57:35 +0100
Subject: [PATCH 2/5] coresight: etmv4: Fix ETMv4x peripheral ID table
In-Reply-To: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
References: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
Message-ID: <1464695858-29284-3-git-send-email-suzuki.poulose@arm.com>

This patch cleans up the peripheral id table for different ETMv4
implementations.

As per Cortex-A53 TRM, the ETM has following id values:

Peripheral ID0	0x5D	0xFE0
Peripheral ID1	0xB9	0xFE4
Peripheral ID2	0x4B	0xFE8
Peripheral ID3	0x00	0xFEC

where, PID2: has the following format:

[7:4]   Revision
[3]     JEDEC   0b1     res1. Indicates a JEP106 identity code is used
[2:0]   DES_1   0b011   ARM Limited. This is bits[6:4] of JEP106 ID code

The existing table entry checks only the bits [1:0], which is not
sufficient enough. Fix it to match bits [3:0], just like the other
entries do. While at it, correct the comment for A57 and the A53 entry.

Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-etm4x.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index 462f0dc..88947f3 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -815,12 +815,12 @@ err_arch_supported:
 }
 
 static struct amba_id etm4_ids[] = {
-	{       /* ETM 4.0 - Qualcomm */
-		.id	= 0x0003b95d,
-		.mask	= 0x0003ffff,
+	{       /* ETM 4.0 - Cortex-A53  */
+		.id	= 0x000bb95d,
+		.mask	= 0x000fffff,
 		.data	= "ETM 4.0",
 	},
-	{       /* ETM 4.0 - Juno board */
+	{       /* ETM 4.0 - Cortex-A57 */
 		.id	= 0x000bb95e,
 		.mask	= 0x000fffff,
 		.data	= "ETM 4.0",
-- 
1.9.1



From suzuki.poulose at arm.com  Tue May 31 04:57:33 2016
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 31 May 2016 12:57:33 +0100
Subject: [PATCH 0/5] coresight: Miscellaneous fixes
Message-ID: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>

This is a collection fixes / cleanups for the coresight driver.

Patches 1,2 are proper fixes and would be good to have it fixed for 4.7.
Patches 3-5 are cleanups.

Suzuki K Poulose (5):
  coresight: Fix NULL pointer dereference in _coresight_build_path
  coresight: etmv4: Fix ETMv4x peripheral ID table
  coresight: Fix csdev connections initialisation
  coresight: Add better messages for coresight_timeout
  coresight: Cleanup TMC status check

 drivers/hwtracing/coresight/coresight-etb10.c   |  6 ++--
 drivers/hwtracing/coresight/coresight-etm4x.c   | 14 ++++----
 drivers/hwtracing/coresight/coresight-tmc-etr.c |  2 +-
 drivers/hwtracing/coresight/coresight-tmc.c     |  6 ++--
 drivers/hwtracing/coresight/coresight.c         | 48 ++++++++++++++-----------
 5 files changed, 38 insertions(+), 38 deletions(-)

-- 
1.9.1



From suzuki.poulose at arm.com  Tue May 31 04:57:37 2016
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 31 May 2016 12:57:37 +0100
Subject: [PATCH 4/5] coresight: Add better messages for coresight_timeout
In-Reply-To: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
References: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
Message-ID: <1464695858-29284-5-git-send-email-suzuki.poulose@arm.com>

When we encounter a timeout waiting for a status change via
coresight_timeout, the caller always print the offset which
was tried. This is pretty much useless as it doesn't specify
the bit position we wait for. Also, one needs to lookup the
TRM to figure out, what was wrong. This patch changes all
such error messages to print something more meaningful.

Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-etb10.c | 6 ++----
 drivers/hwtracing/coresight/coresight-etm4x.c | 6 ++----
 drivers/hwtracing/coresight/coresight-tmc.c   | 6 ++----
 3 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 4d20b0b..6bd4b93 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -184,8 +184,7 @@ static void etb_disable_hw(struct etb_drvdata *drvdata)
 
 	if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) {
 		dev_err(drvdata->dev,
-			"timeout observed when probing at offset %#x\n",
-			ETB_FFCR);
+			"timeout while waiting for completion of Manual Flush\n");
 	}
 
 	/* disable trace capture */
@@ -193,8 +192,7 @@ static void etb_disable_hw(struct etb_drvdata *drvdata)
 
 	if (coresight_timeout(drvdata->base, ETB_FFSR, ETB_FFSR_BIT, 1)) {
 		dev_err(drvdata->dev,
-			"timeout observed when probing at offset %#x\n",
-			ETB_FFCR);
+			"timeout while waiting for Formatter to Stop\n");
 	}
 
 	CS_LOCK(drvdata->base);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index 88947f3..e494042 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -111,8 +111,7 @@ static void etm4_enable_hw(void *info)
 	/* wait for TRCSTATR.IDLE to go up */
 	if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
 		dev_err(drvdata->dev,
-			"timeout observed when probing at offset %#x\n",
-			TRCSTATR);
+			"timeout when waiting for Idle Trace Status\n");
 
 	writel_relaxed(config->pe_sel, drvdata->base + TRCPROCSELR);
 	writel_relaxed(config->cfg, drvdata->base + TRCCONFIGR);
@@ -184,8 +183,7 @@ static void etm4_enable_hw(void *info)
 	/* wait for TRCSTATR.IDLE to go back down to '0' */
 	if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
 		dev_err(drvdata->dev,
-			"timeout observed when probing at offset %#x\n",
-			TRCSTATR);
+			"timeout when waiting for Idle Trace Status\n");
 
 	CS_LOCK(drvdata->base);
 
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 9e02ac9..c7d8ba6 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -38,8 +38,7 @@ void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
 	if (coresight_timeout(drvdata->base,
 			      TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
 		dev_err(drvdata->dev,
-			"timeout observed when probing at offset %#x\n",
-			TMC_STS);
+			"timeout observed when waiting for TMC to be Ready\n");
 	}
 }
 
@@ -56,8 +55,7 @@ void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
 	if (coresight_timeout(drvdata->base,
 			      TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
 		dev_err(drvdata->dev,
-			"timeout observed when probing at offset %#x\n",
-			TMC_FFCR);
+			"timeout observed while waiting for completion of Manual Flush\n");
 	}
 
 	tmc_wait_for_tmcready(drvdata);
-- 
1.9.1



From suzuki.poulose at arm.com  Tue May 31 04:57:36 2016
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 31 May 2016 12:57:36 +0100
Subject: [PATCH 3/5] coresight: Fix csdev connections initialisation
In-Reply-To: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
References: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
Message-ID: <1464695858-29284-4-git-send-email-suzuki.poulose@arm.com>

This is a cleanup patch.

coresight_device->conns holds an array to point to the devices
connected to the OUT ports of a component. Sinks, e.g ETR, do not
have an OUT port (nr_outport = 0), as it streams the trace to
memory via AXI.

At coresight_register() we do :

	conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL);
	if (!conns) {
		ret = -ENOMEM;
		goto err_kzalloc_conns;
	}

For ETR, since the total size requested for kcalloc is zero, the return value is,
ZERO_SIZE_PTR ( != NULL). Hence, csdev->conns = ZERO_SIZE_PTR which cannot be
verified later to contain a valid pointer. The code which accesses the csdev->conns
is bounded by the csdev->nr_outport check, hence we don't try to dereference the
ZERO_SIZE_PTR. This patch cleans up the csdev->conns and csdev->refcnt, initialisation
to make sure we initialise it properly(i.e, either NULL or valid conns array).

Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight.c | 42 +++++++++++++++++++--------------
 1 file changed, 24 insertions(+), 18 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 0fdaaf4..8410420 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -890,7 +890,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
 	int nr_refcnts = 1;
 	atomic_t *refcnts = NULL;
 	struct coresight_device *csdev;
-	struct coresight_connection *conns;
+	struct coresight_connection *conns = NULL;
 
 	csdev = kzalloc(sizeof(*csdev), GFP_KERNEL);
 	if (!csdev) {
@@ -908,29 +908,35 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
 			nr_refcnts = desc->pdata->nr_outport;
 	}
 
-	refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
-	if (!refcnts) {
-		ret = -ENOMEM;
-		goto err_kzalloc_refcnts;
-	}
+	if (nr_refcnts) {
+		refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
+		if (!refcnts) {
+			ret = -ENOMEM;
+			goto err_kzalloc_refcnts;
+		}
 
-	csdev->refcnt = refcnts;
+		csdev->refcnt = refcnts;
+	}
 
 	csdev->nr_inport = desc->pdata->nr_inport;
 	csdev->nr_outport = desc->pdata->nr_outport;
-	conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL);
-	if (!conns) {
-		ret = -ENOMEM;
-		goto err_kzalloc_conns;
-	}
 
-	for (i = 0; i < csdev->nr_outport; i++) {
-		conns[i].outport = desc->pdata->outports[i];
-		conns[i].child_name = desc->pdata->child_names[i];
-		conns[i].child_port = desc->pdata->child_ports[i];
-	}
+	/* Initialise connections if there is at least one outport for this component */
+	if (csdev->nr_outport) {
+		conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL);
+		if (!conns) {
+			ret = -ENOMEM;
+			goto err_kzalloc_conns;
+		}
 
-	csdev->conns = conns;
+		for (i = 0; i < csdev->nr_outport; i++) {
+			conns[i].outport = desc->pdata->outports[i];
+			conns[i].child_name = desc->pdata->child_names[i];
+			conns[i].child_port = desc->pdata->child_ports[i];
+		}
+
+		csdev->conns = conns;
+	}
 
 	csdev->type = desc->type;
 	csdev->subtype = desc->subtype;
-- 
1.9.1



From suzuki.poulose at arm.com  Tue May 31 04:57:34 2016
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 31 May 2016 12:57:34 +0100
Subject: [PATCH 1/5] coresight: Fix NULL pointer dereference in
 _coresight_build_path
In-Reply-To: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
References: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
Message-ID: <1464695858-29284-2-git-send-email-suzuki.poulose@arm.com>

_coresight_build_path assumes that all the connections of a csdev
has the child_dev initialised. This may not be true if the particular
component is not supported by the kernel config(e.g TPIU) but is
present in the DT. In which case, building a path can cause a crash like this :

  Unable to handle kernel NULL pointer dereference at virtual address 00000010
  pgd = ffffffc9750dd000
  [00000010] *pgd=00000009f5e90003, *pud=00000009f5e90003, *pmd=0000000000000000
  Internal error: Oops: 96000006 [#1] PREEMPT SMP
  Modules linked in:
  CPU: 4 PID: 1348 Comm: bash Not tainted 4.6.0-next-20160517 #1646
  Hardware name: ARM Juno development board (r0) (DT)
  task: ffffffc97517a280 ti: ffffffc9762c4000 task.ti: ffffffc9762c4000
  PC is at _coresight_build_path+0x18/0xe4
  LR is at _coresight_build_path+0xc0/0xe4
  pc : [<ffffff80083d5130>] lr : [<ffffff80083d51d8>] pstate: 20000145
  sp : ffffffc9762c7ba0

  [<ffffff80083d5130>] _coresight_build_path+0x18/0xe4
  [<ffffff80083d51d8>] _coresight_build_path+0xc0/0xe4
  [<ffffff80083d51d8>] _coresight_build_path+0xc0/0xe4
  [<ffffff80083d51d8>] _coresight_build_path+0xc0/0xe4
  [<ffffff80083d51d8>] _coresight_build_path+0xc0/0xe4
  [<ffffff80083d51d8>] _coresight_build_path+0xc0/0xe4
  [<ffffff80083d5cdc>] coresight_build_path+0x40/0x68
  [<ffffff80083d5e14>] coresight_enable+0x74/0x1bc
  [<ffffff80083d60a0>] enable_source_store+0x3c/0x6c
  [<ffffff800830b17c>] dev_attr_store+0x18/0x28
  [<ffffff80081ca9c4>] sysfs_kf_write+0x40/0x50
  [<ffffff80081c9e38>] kernfs_fop_write+0x140/0x1cc
  [<ffffff8008163ec8>] __vfs_write+0x28/0x110
  [<ffffff8008164bf0>] vfs_write+0xa0/0x174
  [<ffffff8008165d18>] SyS_write+0x44/0xa0
  [<ffffff8008084e70>] el0_svc_naked+0x24/0x28

Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 5443d03..0fdaaf4 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -385,7 +385,6 @@ static int _coresight_build_path(struct coresight_device *csdev,
 	int i;
 	bool found = false;
 	struct coresight_node *node;
-	struct coresight_connection *conn;
 
 	/* An activated sink has been found.  Enqueue the element */
 	if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
@@ -394,8 +393,9 @@ static int _coresight_build_path(struct coresight_device *csdev,
 
 	/* Not a sink - recursively explore each port found on this element */
 	for (i = 0; i < csdev->nr_outport; i++) {
-		conn = &csdev->conns[i];
-		if (_coresight_build_path(conn->child_dev, path) == 0) {
+		struct coresight_device *child_dev = csdev->conns[i].child_dev;
+
+		if (child_dev && _coresight_build_path(child_dev, path) == 0) {
 			found = true;
 			break;
 		}
-- 
1.9.1



From suzuki.poulose at arm.com  Tue May 31 04:57:38 2016
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 31 May 2016 12:57:38 +0100
Subject: [PATCH 5/5] coresight: Cleanup TMC status check
In-Reply-To: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
References: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
Message-ID: <1464695858-29284-6-git-send-email-suzuki.poulose@arm.com>

Use the defined symbol rather than hardcoding the value to
check whether the TMC buffer is full.

Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc-etr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 847d1b5..b0dce93 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -65,7 +65,7 @@ static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
 	val = readl_relaxed(drvdata->base + TMC_STS);
 
 	/* How much memory do we still have */
-	if (val & BIT(0))
+	if (val & TMC_STS_FULL)
 		drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
 	else
 		drvdata->buf = drvdata->vaddr;
-- 
1.9.1



From pramod.kumar at broadcom.com  Tue May 31 05:04:13 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Tue, 31 May 2016 17:34:13 +0530
Subject: [PATCH 3/7] binding: mdio-mux: Add DT binding doc for Broadcom
 MDIO bus mutiplexer
In-Reply-To: <20160530152426.GM6027@lunn.ch>
References: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
 <1464592251-2688-4-git-send-email-pramod.kumar@broadcom.com>
 <20160530152426.GM6027@lunn.ch>
Message-ID: <e002ac1b95d8ee4725f7315427f65fbf@mail.gmail.com>

Hi Andrew,

> -----Original Message-----
> From: Andrew Lunn [mailto:andrew at lunn.ch]
> Sent: 30 May 2016 20:54
> To: Pramod Kumar
> Cc: Rob Herring; Pawel Moll; Mark Rutland; Ian Campbell; Kumar Gala;
Catalin
> Marinas; Will Deacon; Kishon Vijay Abraham I; David S. Miller;
> devicetree at vger.kernel.org; netdev at vger.kernel.org; linux-
> kernel at vger.kernel.org; bcm-kernel-feedback-list at broadcom.com;
linux-arm-
> kernel at lists.infradead.org
> Subject: Re: [PATCH 3/7] binding: mdio-mux: Add DT binding doc for
Broadcom
> MDIO bus mutiplexer
>
> On Mon, May 30, 2016 at 12:40:47PM +0530, Pramod Kumar wrote:
> > Add DT binding doc for Broadcom MDIO bus mutiplexer driver.
> >
> > Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
> > ---
> >  .../bindings/net/brcm,mdio-mux-iproc.txt           | 64
> ++++++++++++++++++++++
> >  1 file changed, 64 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
> >
> > diff --git
> > a/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
> > b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
> > new file mode 100644
> > index 0000000..dd74ee0
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
> > @@ -0,0 +1,64 @@
> > +Properties for an MDIO bus mutiplexer found in Broadcom iProc based
SoCs.
> > +
> > +This MDIO bus multiplexer defines buses that could be internal as
> > +well as external to SoCs and could accept MDIO transaction compatible
> > +to C-22 or
> > +C-45 Clause. When Child bus is selected, one need to select these two
> > +properties as well to generate desired MDIO trascation on appropriate
bus.
> > +
> > +Required properties in addition to the generic multiplexer
properties:
> > +
> > +MDIO multiplexer node:
> > +- complatible: brcm,mdio-mux-iproc.
> > +
> > +Child bus node:
> > +-brcm,is-c45: Boolean property indicating PHYs attached to this bus
supports
> > +	      C-45 mdio transaction.
>
> This is-c45 seems to be at the wrong level. As far as i know, you can
mix C22 and
> C45 devices on a bus. It is a property of the individual MDIO device if
it uses C45
> or not.
>
> I would expect your MDIO device PHY drivers to logically OR
> MII_ADDR_C45 into the address when doing an MDIO read/write using C45.
>

Yes. I agree. We will logical OR MII_ADDR_C45 into the address from PHY
drivers. Is there any standard property exist for non-ethernet-phy DRIVERS
to decide the whether PHY node support C45 or C22?

Or shall I define a new one like "mdio-device-c45" or something similar
name in PHY DT NODE.


> 	     Andrew

Regards,
Pramod


From linux at armlinux.org.uk  Tue May 31 05:16:40 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Tue, 31 May 2016 13:16:40 +0100
Subject: [BUG] CONFIG_UNINLINE_SPIN_UNLOCK important for Cortex-A9
In-Reply-To: <6689734.3ffZe38SoY@wuerfel>
References: <874m9eoetu.fsf@gmail.com> <4854518.jvbplH0SM0@wuerfel>
 <871t4io608.fsf@gmail.com> <6689734.3ffZe38SoY@wuerfel>
Message-ID: <20160531121640.GU19428@n2100.arm.linux.org.uk>

On Tue, May 31, 2016 at 01:43:43PM +0200, Arnd Bergmann wrote:
> > [17827.758966] Unable to handle kernel paging request at virtual address 00001014
> 
> 0x1014 is a rather long offset, but still a plausible NULL pointer. The
> r10 register contains 0x1000, so this is probably an incorrect value and
> is being used as a pointer with offset 0x14 added in. With an objdump of
> your net/core/dev.o, we could see which pointer that was, to maybe figure
> out which lock is supposed to protect it and where that lock gets released.

Or maybe disassemble the code line.

   0:   e1a03006        mov     r3, r6
   4:   e12fff3c        blx     ip
   8:   e51b4058        ldr     r4, [fp, #-88]  ; 0xffffffa8
   c:   e1a0200a        mov     r2, sl
  10:   e59a3014        ldr     r3, [sl, #20]

So yes, sl (r10) is the base register, with an offset of 0x14.

> > [17827.766279] pgd = ee09c000
> > [17827.769003] [00001014] *pgd=3eba3831, *pte=00000000, *ppte=00000000
> > [17827.775383] Internal error: Oops: 17 [#1] SMP ARM
> > [17827.780108] Modules linked in: usbhid btusb btrtl btbcm btintel bluetooth flexcan smsc95xx usbnet mii ptxc(O)
> > [17827.790242] CPU: 1 PID: 372 Comm: stress-ng-socke Tainted: G           O    4.5.4 #1
> > [17827.797995] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
> > [17827.804536] task: ed614780 ti: eebba000 task.ti: eebba000
> > [17827.809977] PC is at __netif_receive_skb_core+0x328/0xa9c
> 
> Unfortunately in the middle of a rather long function, and I don't
> see a spin_unlock in this function, in fact it's not even called
> with a spinlock held, so it must be something more indirect.

On a kernel here, I have:

    1290:       e51b4058        ldr     r4, [fp, #-88]  ; 0xffffffa8
...
    12b0:       e5943014        ldr     r3, [r4, #20]
    12b4:       e5b37054        ldr     r7, [r3, #84]!  ; 0x54
    12b8:       e1570003        cmp     r7, r3
    12bc:       e2477014        sub     r7, r7, #20
    12c0:       0a00001f        beq     1344 <__netif_receive_skb_core+0x3c0>
...
    1314:       e1a0300a        mov     r3, sl
    1318:       e12fff3c        blx     ip
    131c:       e51b4058        ldr     r4, [fp, #-88]  ; 0xffffffa8
    1320:       e1a02007        mov     r2, r7
    1324:       e5971014        ldr     r1, [r7, #20]

So it's a list of some sort.  fp, #-88 is the first arg, so that's
the struct sk_buff pointer.

Adding debug info to the build, reveals that it's this:

        list_for_each_entry_rcu(ptype, &skb->dev->ptype_all, list) {
                if (pt_prev)
                        ret = deliver_skb(skb, pt_prev, orig_dev);
                pt_prev = ptype;
        }

specifically, the load is for __read_once_size() inside
list_for_each_entry_rcu().

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From andrew at lunn.ch  Tue May 31 05:27:57 2016
From: andrew at lunn.ch (Andrew Lunn)
Date: Tue, 31 May 2016 14:27:57 +0200
Subject: [PATCH 3/7] binding: mdio-mux: Add DT binding doc for Broadcom
 MDIO bus mutiplexer
In-Reply-To: <e002ac1b95d8ee4725f7315427f65fbf@mail.gmail.com>
References: <1464592251-2688-1-git-send-email-pramod.kumar@broadcom.com>
 <1464592251-2688-4-git-send-email-pramod.kumar@broadcom.com>
 <20160530152426.GM6027@lunn.ch>
 <e002ac1b95d8ee4725f7315427f65fbf@mail.gmail.com>
Message-ID: <20160531122757.GD24402@lunn.ch>

> Yes. I agree. We will logical OR MII_ADDR_C45 into the address from PHY
> drivers. Is there any standard property exist for non-ethernet-phy DRIVERS
> to decide the whether PHY node support C45 or C22?

Why do you even need this in the device tree? If the driver needs to
access a register > 31, it knows it must use C45. If it is less than
32, it can use either C22 or C45.

    Andrew


From hanjun.guo at linaro.org  Tue May 31 05:28:26 2016
From: hanjun.guo at linaro.org (Hanjun Guo)
Date: Tue, 31 May 2016 20:28:26 +0800
Subject: [PATCH v7 07/15] arm64, numa: Cleanup NUMA disabled messages.
In-Reply-To: <1464129345-18985-8-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
 <1464129345-18985-8-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <574D836A.2090905@linaro.org>

On 2016/5/25 6:35, David Daney wrote:
> From: David Daney <david.daney at cavium.com>
>
> As noted by Dennis Chen, we don't want to print "No NUMA configuration
> found" if NUMA was forced off from the command line.
>
> Change the type of numa_off to bool, and clean up printing code.
> Print "NUMA disabled" if forced off on command line and "No NUMA
> configuration found" if there was no firmware NUMA information.
>
> Signed-off-by: David Daney <david.daney at cavium.com>
> Acked-by: Catalin Marinas <catalin.marinas at arm.com>
> ---
>   arch/arm64/mm/numa.c | 11 +++++++----
>   1 file changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
> index 6cb03f9..1def1de 100644
> --- a/arch/arm64/mm/numa.c
> +++ b/arch/arm64/mm/numa.c
> @@ -29,7 +29,7 @@ static int cpu_to_node_map[NR_CPUS] = { [0 ... NR_CPUS-1] = NUMA_NO_NODE };
>
>   static int numa_distance_cnt;
>   static u8 *numa_distance;
> -static int numa_off;
> +static bool numa_off;
>
>   static __init int numa_parse_early_param(char *opt)
>   {
> @@ -37,7 +37,7 @@ static __init int numa_parse_early_param(char *opt)
>   		return -EINVAL;
>   	if (!strncmp(opt, "off", 3)) {
>   		pr_info("%s\n", "NUMA turned off");
> -		numa_off = 1;
> +		numa_off = true;
>   	}
>   	return 0;
>   }
> @@ -362,7 +362,10 @@ static int __init dummy_numa_init(void)
>   	int ret;
>   	struct memblock_region *mblk;
>
> -	pr_info("%s\n", "No NUMA configuration found");
> +	if (numa_off)
> +		pr_info("NUMA disabled\n"); /* Forced off on command line. */
> +	else
> +		pr_info("No NUMA configuration found\n");
>   	pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
>   	       0LLU, PFN_PHYS(max_pfn) - 1);
>
> @@ -375,7 +378,7 @@ static int __init dummy_numa_init(void)
>   		return ret;
>   	}
>
> -	numa_off = 1;
> +	numa_off = true;
>   	return 0;
>   }

Reviewed-by: Hanjun Guo <hanjun.guo at linaro.org>

>
>


From will.deacon at arm.com  Tue May 31 05:38:27 2016
From: will.deacon at arm.com (Will Deacon)
Date: Tue, 31 May 2016 13:38:27 +0100
Subject: Support for unaligned watchpoints in arm/arm64
In-Reply-To: <CAJt8pk8FBbTVMMM45SaEs86MZOp0o6xChAsMT1sO+_Xy-GENyw@mail.gmail.com>
References: <CAJt8pk8FBbTVMMM45SaEs86MZOp0o6xChAsMT1sO+_Xy-GENyw@mail.gmail.com>
Message-ID: <20160531123827.GF24936@arm.com>

On Thu, May 26, 2016 at 05:04:46PM +0100, Pavel Labath wrote:
> Hello all,

Hi Pavel,

> I've been wondering if there are any plans about adding support for
> unaligned watchpoints to the kernel. It seems quite a shame that
> applications are not able not use them, even though the hardware
> should support that feature.

I'm actually coming round to the idea of ditching the perf hw_breakpoint
mechanism entirely and simply writing a ptrace back-end that can expose
the hardware features directly to userspace. The two issues with this
are:

  (1) It's a fair amount of work
  (2) We might already have users of the perf interface (including compat)

I'm really not happy with the way hw_breakpoint worked out :(

Will


From robin.murphy at arm.com  Tue May 31 05:52:45 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 31 May 2016 13:52:45 +0100
Subject: [PATCH] drivers: char: mem: Check {read,write}_kmem() addresses
Message-ID: <5e293c103f0a86f512d71f17091a55e9746e711f.1464698496.git.robin.murphy@arm.com>

Arriving at read_kmem() with an offset representing a bogus kernel
address (e.g. 0 from a simple "cat /dev/kmem") leads to copy_to_user
faulting on the kernel-space read.

x86_64 happens to get away with this since the optimised implementation
uses "rep movs*", thus the user write (which is allowed to fault) and
the kernel read are the same instruction, the kernel-side fault falls
into the userspace fixup handler and a chain of events transpires
leading to returning the expected -EFAULT. On other architectures,
though, the read is not covered by the fixup entry for the write, and we
get a straightforward "Unable to hande kernel paging request..." dump.

The more typical use-case of mmap_kmem() already validates the address
with pfn_valid() as one might expect, so let's make that consistent
across {read,write}_kem() too.

Reported-by: Kefeng Wang <wangkefeng.wang at huawei.com>
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---

I'm not sure if this warrants going to stable or not, as it's really
just making an existing failure case more graceful and less confusing.

 drivers/char/mem.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 71025c2f6bbb..64c766023b15 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -384,6 +384,9 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
 	char *kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
 	int err = 0;
 
+	if (!pfn_valid(PFN_DOWN(p)))
+		return -EFAULT;
+
 	read = 0;
 	if (p < (unsigned long) high_memory) {
 		low_count = count;
@@ -512,6 +515,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf,
 	char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
 	int err = 0;
 
+	if (!pfn_valid(PFN_DOWN(p)))
+		return -EFAULT;
+
 	if (p < (unsigned long) high_memory) {
 		unsigned long to_write = min_t(unsigned long, count,
 					       (unsigned long)high_memory - p);
-- 
2.8.1.dirty



From hanjun.guo at linaro.org  Tue May 31 06:05:13 2016
From: hanjun.guo at linaro.org (Hanjun Guo)
Date: Tue, 31 May 2016 21:05:13 +0800
Subject: [PATCH v7 13/15] ACPI / processor: Add acpi_map_madt_entry().
In-Reply-To: <1464129345-18985-14-git-send-email-ddaney.cavm@gmail.com>
References: <1464129345-18985-1-git-send-email-ddaney.cavm@gmail.com>
 <1464129345-18985-14-git-send-email-ddaney.cavm@gmail.com>
Message-ID: <574D8C09.3030608@linaro.org>

On 2016/5/25 6:35, David Daney wrote:
> From: David Daney <david.daney at cavium.com>
>
> Follow-on arm64 ACPI/NUMA patches need to map MADT entries very early
> (before kmalloc is usable).
>
> Add acpi_map_madt_entry() which, indirectly, uses
> early_memremap()/early_memunmap() to access the table and parse out
> the mpidr.  The existing implementation of map_madt_entry() is
> modified to take a pointer to the MADT as a parameter and the callers
> adjusted.
>
> Signed-off-by: David Daney <david.daney at cavium.com>
> ---
>   drivers/acpi/processor_core.c | 26 ++++++++++++++++++++++----
>   include/acpi/processor.h      |  1 +
>   2 files changed, 23 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
> index 33a38d6..9125d7d 100644
> --- a/drivers/acpi/processor_core.c
> +++ b/drivers/acpi/processor_core.c
> @@ -108,13 +108,12 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry,
>   	return -EINVAL;
>   }
>
> -static phys_cpuid_t map_madt_entry(int type, u32 acpi_id)
> +static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
> +				   int type, u32 acpi_id)
>   {
>   	unsigned long madt_end, entry;
>   	phys_cpuid_t phys_id = PHYS_CPUID_INVALID;	/* CPU hardware ID */
> -	struct acpi_table_madt *madt;
>
> -	madt = get_madt_table();
>   	if (!madt)
>   		return phys_id;
>
> @@ -145,6 +144,25 @@ static phys_cpuid_t map_madt_entry(int type, u32 acpi_id)
>   	return phys_id;
>   }
>
> +phys_cpuid_t __init acpi_map_madt_entry(u32 acpi_id)
> +{
> +	struct acpi_table_madt *madt = NULL;
> +	acpi_size tbl_size;
> +	phys_cpuid_t rv;
> +
> +	acpi_get_table_with_size(ACPI_SIG_MADT, 0,
> +				 (struct acpi_table_header **)&madt,
> +				 &tbl_size);
> +	if (!madt)
> +		return PHYS_CPUID_INVALID;
> +
> +	rv = map_madt_entry(madt, 1, acpi_id);

Just nit-pick, pass 1 here means we need to define an acpi processor
device object in DSDT (see function map_gicc_mpidr(),
device_declaration), it would be fine for x2apic and gic mode,
but not for lapic mode, since the function name is acpi_map_madt_entry
which is general for all architecture, it will confuse people I think.

How about rename acpi_map_madt_entry() to acpi_map_madt_gicc_entry()?
It's only used for AMR64 to get mpidrs from GICC entries using acpi_id,
other than that, it's good to me.

Thanks
Hanjun


From christoffer.dall at linaro.org  Tue May 31 06:05:59 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 31 May 2016 15:05:59 +0200
Subject: [PATCH v4 01/12] KVM: extend struct kvm_msi to hold a 32-bit
 device ID
In-Reply-To: <5745CFF6.6070001@arm.com>
References: <1458958450-19662-1-git-send-email-andre.przywara@arm.com>
 <1458958450-19662-2-git-send-email-andre.przywara@arm.com>
 <20160403091508.GA5261@cbox>
 <e520a5a8-b259-27f3-f33c-f87e008f1c6f@arm.com>
 <5745CFF6.6070001@arm.com>
Message-ID: <20160531130559.GA12568@cbox>

On Wed, May 25, 2016 at 05:16:54PM +0100, Marc Zyngier wrote:
> On 25/05/16 16:55, Andre Przywara wrote:
> > Hi Christoffer,
> > 
> > On 03/04/16 10:15, Christoffer Dall wrote:
> >> On Sat, Mar 26, 2016 at 02:13:59AM +0000, Andre Przywara wrote:
> >>> The ARM GICv3 ITS MSI controller requires a device ID to be able to
> >>> assign the proper interrupt vector. On real hardware, this ID is
> >>> sampled from the bus. To be able to emulate an ITS controller, extend
> >>> the KVM MSI interface to let userspace provide such a device ID. For
> >>> PCI devices, the device ID is simply the 16-bit bus-device-function
> >>> triplet, which should be easily available to the userland tool.
> >>>
> >>> Also there is a new KVM capability which advertises whether the
> >>> current VM requires a device ID to be set along with the MSI data.
> >>> This flag is still reported as not available everywhere, later we will
> >>> enable it when ITS emulation is used.
> >>>
> >>> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> >>> Reviewed-by: Eric Auger <eric.auger at linaro.org>
> >>> ---
> >>>  Documentation/virtual/kvm/api.txt | 12 ++++++++++--
> >>>  include/uapi/linux/kvm.h          |  5 ++++-
> >>>  2 files changed, 14 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> >>> index cb2ef0b..8f7351d 100644
> >>> --- a/Documentation/virtual/kvm/api.txt
> >>> +++ b/Documentation/virtual/kvm/api.txt
> >>> @@ -2163,10 +2163,18 @@ struct kvm_msi {
> >>>  	__u32 address_hi;
> >>>  	__u32 data;
> >>>  	__u32 flags;
> >>> -	__u8  pad[16];
> >>> +	__u32 devid;
> >>
> >> Are we imposing any unfortunate restrictions for other architectures by
> >> using a u32 over a u64 for the device ID?
> > 
> > Mmmh, good point. I guess not only for other architectures, but also for
> > the future in general.
> > 
> > Are there any objections against increasing this to a u64?
> 
> I'm not sure this is really necessary. A PCI RID is 16bit, and expanding
> it to 32bit is already making quite a bit of space for further extension.
> 
> Also, some architecture might be unhappy of having a 64bit quantity that
> is not 64bit aligned...
> 
ok, thanks for the explanation.

-Christoffer


From linux at armlinux.org.uk  Tue May 31 06:08:21 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Tue, 31 May 2016 14:08:21 +0100
Subject: [PATCH] drivers: char: mem: Check {read,write}_kmem() addresses
In-Reply-To: <5e293c103f0a86f512d71f17091a55e9746e711f.1464698496.git.robin.murphy@arm.com>
References: <5e293c103f0a86f512d71f17091a55e9746e711f.1464698496.git.robin.murphy@arm.com>
Message-ID: <20160531130821.GV19428@n2100.arm.linux.org.uk>

On Tue, May 31, 2016 at 01:52:45PM +0100, Robin Murphy wrote:
> Arriving at read_kmem() with an offset representing a bogus kernel
> address (e.g. 0 from a simple "cat /dev/kmem") leads to copy_to_user
> faulting on the kernel-space read.
> 
> x86_64 happens to get away with this since the optimised implementation
> uses "rep movs*", thus the user write (which is allowed to fault) and
> the kernel read are the same instruction, the kernel-side fault falls
> into the userspace fixup handler and a chain of events transpires
> leading to returning the expected -EFAULT. On other architectures,
> though, the read is not covered by the fixup entry for the write, and we
> get a straightforward "Unable to hande kernel paging request..." dump.
> 
> The more typical use-case of mmap_kmem() already validates the address
> with pfn_valid() as one might expect, so let's make that consistent
> across {read,write}_kem() too.
> 
> Reported-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
> 
> I'm not sure if this warrants going to stable or not, as it's really
> just making an existing failure case more graceful and less confusing.

Returning -EFAULT because the kernel-side address (iow, file offset) is
invalid is not particularly nice:

NAME
       read - read from a file descriptor

ERRORS
       EFAULT buf is outside your accessible address space.

Latest POSIX has:

ENXIO
	A request was made of a nonexistent device, or the
	request was outside the capabilities of the device.

which to me looks like a better error code to return, as file offsets
which are not valid can be interpreted as being "outside the
capabilities of the device".  EFAULT has always on Linux meant that
the user passed an invalid userspace buffer.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From bogdan.purcareata at nxp.com  Tue May 31 06:09:23 2016
From: bogdan.purcareata at nxp.com (Bogdan Purcareata)
Date: Tue, 31 May 2016 13:09:23 +0000
Subject: [PATCH] iommu/arm-smmu: Properly initialize CBAR MemAttr
In-Reply-To: <574D5EBF.8010707@arm.com>
References: <1464617742-5493-1-git-send-email-bogdan.purcareata@nxp.com>
 <574D5EBF.8010707@arm.com>
Message-ID: <574D8D01.7090500@nxp.com>

On 31.05.2016 12:51, Robin Murphy wrote:
> On 30/05/16 15:15, Bogdan Purcareata wrote:
>> Currently, when initializing the CBAR memattr attributes to the weakest
>> values, it is expected that the final ones will be declared in the TTBCR
>> register (SMMU_CBn_TCR).
>
> You mean the stage 1 PTE, right? TTBCR only controls the attributes for
> table walks.

I got lost in the SMMU spec. I couldn't find the direct correlation between CBAR 
and TTBCR. Thanks for the clarification.

>> This is not required when CBAR type consists of a stage 1 translation
>> followed by a stage 2 bypass.
>
> On the contrary, this is _only_ required for stage 1 translation with
> stage 2 bypass - CBAR.MemAttr gives the _stage 2_ memory type (see
> section 2.4 "Memory type and shareability attribute determination" in
> the SMMU spec). For nested translation the stage 2 attributes come from
> the stage 2 context itself.

Yes. In the previous "this", I was referring to the TTBCR configurations, not 
CBAR itself.

>>                                This is the case when assigning a VFIO PCI
>> device to a KVM guest. Overriding the default transaction attributes to
>> writeback cacheable results in the device no longer working in the guest
>> (the adapter requires explicit flushes on the descriptor rings memory).
>
>   From that, the real problem is almost certainly that you're erroneously
> describing the device as coherent or non-coherent (whichever it actually
> isn't) somewhere.

And that was the issue, indeed. The PCIe controller was not described as 
dma-coherent in the device tree, when in fact it was, thus wreaking all this havoc.

Thank you for the valuable insight and please discard the patch.

Bogdan P.

>> Update the context init routine to initialize the CBAR MemAttr field only
>> if there's a stage 1 followed by a stage 2 translation.
>
> The CBAR.MemAttr field doesn't even exist in that format - it's a good
> thing that we don't actually implement nested translation (we currently
> just use a stage 2 context instead), because this would end up
> corrupting CBAR.CBNDX (i.e. the stage 2 context bank index). Now that I
> should probably fix...
>
>> Signed-off-by: Bogdan Purcareata <bogdan.purcareata at nxp.com>
>> ---
>>    drivers/iommu/arm-smmu.c | 13 +++++++++----
>>    1 file changed, 9 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
>> index ff7a392..1400ec9 100644
>> --- a/drivers/iommu/arm-smmu.c
>> +++ b/drivers/iommu/arm-smmu.c
>> @@ -765,13 +765,14 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
>>    {
>>    	u32 reg;
>>    	u64 reg64;
>> -	bool stage1;
>> +	bool stage1, stage1_stage2;
>>    	struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
>>    	struct arm_smmu_device *smmu = smmu_domain->smmu;
>>    	void __iomem *cb_base, *gr1_base;
>>
>>    	gr1_base = ARM_SMMU_GR1(smmu);
>>    	stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
>> +	stage1_stage2 = cfg->cbar == CBAR_TYPE_S1_TRANS_S2_TRANS;
>>    	cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
>>
>>    	if (smmu->version > ARM_SMMU_V1) {
>> @@ -793,15 +794,19 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
>>
>>    	/*
>>    	 * Use the weakest shareability/memory types, so they are
>> -	 * overridden by the ttbcr/pte.
>> +	 * overridden by the ttbcr/pte. This happens only if the stage
>> +	 * 1 is followed by a stage 2 translation.
>>    	 */
>> -	if (stage1) {
>> +	if (stage1_stage2) {
>>    		reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) |
>>    			(CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
>> -	} else if (!(smmu->features & ARM_SMMU_FEAT_VMID16)) {
>
> Since MemAttr is initially zero, the net result of this is that *all*
> stage 1 transactions will now get overridden to Strongly-Ordered. That
> may hide your problem, but it's definitely not the correct thing to do.
>
> Robin.
>
>> +	}
>> +
>> +	if (!stage1 && !(smmu->features & ARM_SMMU_FEAT_VMID16)) {
>>    		/* 8-bit VMIDs live in CBAR */
>>    		reg |= ARM_SMMU_CB_VMID(smmu, cfg) << CBAR_VMID_SHIFT;
>>    	}
>> +
>>    	writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx));
>>
>>    	/* TTBRs */
>>
>

From yehuday at marvell.com  Tue May 31 06:10:44 2016
From: yehuday at marvell.com (Yehuda Yitschak)
Date: Tue, 31 May 2016 13:10:44 +0000
Subject: [BUG] Page allocation failures with newest kernels
In-Reply-To: <CAPv3WKdYdwpi3k5eY86qibfprMFwkYOkDwHOsNydp=0sTV3mgg@mail.gmail.com>
References: <CAPv3WKcVsWBgHHC3UPNcbka2JUmN4CTw1Ym4BR1=1V9=B9av5Q@mail.gmail.com>
 <574D64A0.2070207@arm.com>
 <CAPv3WKdYdwpi3k5eY86qibfprMFwkYOkDwHOsNydp=0sTV3mgg@mail.gmail.com>
Message-ID: <60e8df74202e40b28a4d53dbc7fd0b22@IL-EXCH02.marvell.com>

Hi Robin 

During some of the stress tests we also came across a different warning from the arm64  page management code
It looks like a race is detected between HW and SW marking a bit in the PTE

Not sure it's really related but I thought it might give a clue on the issue
http://pastebin.com/ASv19vZP

Thanks

Yehuda 


> -----Original Message-----
> From: Marcin Wojtas [mailto:mw at semihalf.com]
> Sent: Tuesday, May 31, 2016 13:30
> To: Robin Murphy
> Cc: linux-mm at kvack.org; linux-kernel at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; Lior Amsalem; Thomas Petazzoni; Yehuda
> Yitschak; Catalin Marinas; Arnd Bergmann; Grzegorz Jaszczyk; Will Deacon;
> Nadav Haklai; Tomasz Nowicki; Gregory Cl?ment
> Subject: Re: [BUG] Page allocation failures with newest kernels
> 
> Hi Robin,
> 
> >
> > I remember there were some issues around 4.2 with the revision of the
> > arm64 atomic implementations affecting the cmpxchg_double() in SLUB,
> > but those should all be fixed (and the symptoms tended to be
> considerably more fatal).
> > A stronger candidate would be 97303480753e (which landed in 4.4),
> > which has various knock-on effects on the layout of SLUB internals -
> > does fiddling with L1_CACHE_SHIFT make any difference?
> >
> 
> I'll check the commits, thanks. I forgot to add L1_CACHE_SHIFT was my first
> suspect - I had spent a long time debugging network controller, which
> stopped working because of this change - L1_CACHE_BYTES (and hence
> NET_SKB_PAD) not fitting HW constraints. Anyway reverting it didn't help at
> all for page alloc issue.
> 
> Best regards,
> Marcin

From arnd at arndb.de  Tue May 31 06:12:30 2016
From: arnd at arndb.de (Arnd Bergmann)
Date: Tue, 31 May 2016 15:12:30 +0200
Subject: [BUG] CONFIG_UNINLINE_SPIN_UNLOCK important for Cortex-A9
In-Reply-To: <20160531121640.GU19428@n2100.arm.linux.org.uk>
References: <874m9eoetu.fsf@gmail.com> <6689734.3ffZe38SoY@wuerfel>
 <20160531121640.GU19428@n2100.arm.linux.org.uk>
Message-ID: <11929103.x2FTA7ihIh@wuerfel>

On Tuesday, May 31, 2016 1:16:40 PM CEST Russell King - ARM Linux wrote:
> 
> > > [17827.766279] pgd = ee09c000
> > > [17827.769003] [00001014] *pgd=3eba3831, *pte=00000000, *ppte=00000000
> > > [17827.775383] Internal error: Oops: 17 [#1] SMP ARM
> > > [17827.780108] Modules linked in: usbhid btusb btrtl btbcm btintel bluetooth flexcan smsc95xx usbnet mii ptxc(O)
> > > [17827.790242] CPU: 1 PID: 372 Comm: stress-ng-socke Tainted: G           O    4.5.4 #1
> > > [17827.797995] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
> > > [17827.804536] task: ed614780 ti: eebba000 task.ti: eebba000
> > > [17827.809977] PC is at __netif_receive_skb_core+0x328/0xa9c
> > 
> > Unfortunately in the middle of a rather long function, and I don't
> > see a spin_unlock in this function, in fact it's not even called
> > with a spinlock held, so it must be something more indirect.
> 
> On a kernel here, I have:
> 
>     1290:       e51b4058        ldr     r4, [fp, #-88]  ; 0xffffffa8
> ...
>     12b0:       e5943014        ldr     r3, [r4, #20]
>     12b4:       e5b37054        ldr     r7, [r3, #84]!  ; 0x54
>     12b8:       e1570003        cmp     r7, r3
>     12bc:       e2477014        sub     r7, r7, #20
>     12c0:       0a00001f        beq     1344 <__netif_receive_skb_core+0x3c0>
> ...
>     1314:       e1a0300a        mov     r3, sl
>     1318:       e12fff3c        blx     ip
>     131c:       e51b4058        ldr     r4, [fp, #-88]  ; 0xffffffa8
>     1320:       e1a02007        mov     r2, r7
>     1324:       e5971014        ldr     r1, [r7, #20]
> 
> So it's a list of some sort.  fp, #-88 is the first arg, so that's
> the struct sk_buff pointer.
> 
> Adding debug info to the build, reveals that it's this:
> 
>         list_for_each_entry_rcu(ptype, &skb->dev->ptype_all, list) {
>                 if (pt_prev)
>                         ret = deliver_skb(skb, pt_prev, orig_dev);
>                 pt_prev = ptype;
>         }
> 
> specifically, the load is for __read_once_size() inside
> list_for_each_entry_rcu().

Ok, so this is an rcu protected list that gets written to using the function

void dev_add_pack(struct packet_type *pt)
{
        struct list_head *head = ptype_head(pt);

        spin_lock(&ptype_lock);
        list_add_rcu(&pt->list, head);
        spin_unlock(&ptype_lock);
}
EXPORT_SYMBOL(dev_add_pack);

and the respective __dev_remove_pack taking the same lock. These get called
once for each network protocol (which basically should never change) and
also for af_packet.c when registering a new listener.

Somehow we managed to get an invalid entry in the list, which could
be related to lots of af_packet registering/unregistering.

Does the stress-ng test case do that?

Do the other oops output logs have any relation to the above?

	Arnd


From will.deacon at arm.com  Tue May 31 06:15:20 2016
From: will.deacon at arm.com (Will Deacon)
Date: Tue, 31 May 2016 14:15:20 +0100
Subject: [BUG] Page allocation failures with newest kernels
In-Reply-To: <60e8df74202e40b28a4d53dbc7fd0b22@IL-EXCH02.marvell.com>
References: <CAPv3WKcVsWBgHHC3UPNcbka2JUmN4CTw1Ym4BR1=1V9=B9av5Q@mail.gmail.com>
 <574D64A0.2070207@arm.com>
 <CAPv3WKdYdwpi3k5eY86qibfprMFwkYOkDwHOsNydp=0sTV3mgg@mail.gmail.com>
 <60e8df74202e40b28a4d53dbc7fd0b22@IL-EXCH02.marvell.com>
Message-ID: <20160531131520.GI24936@arm.com>

On Tue, May 31, 2016 at 01:10:44PM +0000, Yehuda Yitschak wrote:
> During some of the stress tests we also came across a different warning
> from the arm64  page management code
> It looks like a race is detected between HW and SW marking a bit in the PTE

A72 (which I believe is the CPU in that SoC) is a v8.0 CPU and therefore
doesn't have hardware DBM.

> Not sure it's really related but I thought it might give a clue on the issue
> http://pastebin.com/ASv19vZP

There have been a few patches from Catalin to fix up the hardware DBM
patches, so it might be worth trying to reproduce this failure with a
more recent kernel. I doubt this is related to the allocation failures,
however.

Will


From will.deacon at arm.com  Tue May 31 06:25:08 2016
From: will.deacon at arm.com (Will Deacon)
Date: Tue, 31 May 2016 14:25:08 +0100
Subject: [PATCH v2 4/6] arm64: mm: dump: make page table dumping reusable
In-Reply-To: <20160513125606.GB4088@leverpostej>
References: <1461343688-8552-1-git-send-email-ard.biesheuvel@linaro.org>
 <1461343688-8552-5-git-send-email-ard.biesheuvel@linaro.org>
 <20160425110757.GI16065@arm.com>
 <20160513125606.GB4088@leverpostej>
Message-ID: <20160531132508.GJ24936@arm.com>

On Fri, May 13, 2016 at 01:56:07PM +0100, Mark Rutland wrote:
> On Mon, Apr 25, 2016 at 12:07:57PM +0100, Will Deacon wrote:
> > Hi Ard, Mark,
> > 
> > On Fri, Apr 22, 2016 at 06:48:06PM +0200, Ard Biesheuvel wrote:
> > > From: Mark Rutland <mark.rutland at arm.com>
> > > 
> > > For debugging purposes, it would be nice if we could export page tables
> > > other than the swapper_pg_dir to userspace. To enable this, this patch
> > > refactors the arm64 page table dumping code such that multiple tables
> > > may be registered with the framework, and exported under debugfs.
> > > 
> > > Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> > > Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> > > ---
> > >  arch/arm64/include/asm/ptdump.h | 44 ++++++++++++++++++++
> > >  arch/arm64/mm/dump.c            | 32 ++++++++------
> > >  2 files changed, 64 insertions(+), 12 deletions(-)
> > 
> > Could you reorder this with patch 3, please? I'm unsure about the benefit
> > of the very specific string literal changes, but the ptdump stuff here
> > certainly looks beneficial.
> 
> I'm sure this is far too late, but for posterity I've rebased patch 4
> below atop of pathes 1 & 2 as queued in the arm64 for-next/core branch,
> without patch 3. It builds cleanly, and I've given it a spin on
> Juno.
> 
> Will, I guess I should rebase and resend this after we hit v4.7-rc1?

Yes, please.

Will


From broonie at kernel.org  Tue May 31 06:27:07 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 31 May 2016 14:27:07 +0100
Subject: [PATCH 5/5] RFC spi: sun4i: add DMA support
In-Reply-To: <CAOMqctQijjO2amwSmSMGp96KBRGrLb0fvXRwnybOEqvV3-HZ0g@mail.gmail.com>
References: <cover.1464130597.git.hramrach@gmail.com>
 <ba0d6eb37cc4b0d2c46acbf9fcd7d644b3545ce8.1464130597.git.hramrach@gmail.com>
 <20160530112610.GJ29837@sirena.org.uk>
 <CAMuHMdVThvtqgFnyqoqypwwf1d81uu9NBo6-heTZBcvBxRevNw@mail.gmail.com>
 <20160530150343.GL29837@sirena.org.uk>
 <CAOMqctQb-YYprA7H5qCcYo2hxXiUhjW2z3JbZ3-FhbfcjFzBpw@mail.gmail.com>
 <20160530155016.GO29837@sirena.org.uk>
 <CAOMqctQijjO2amwSmSMGp96KBRGrLb0fvXRwnybOEqvV3-HZ0g@mail.gmail.com>
Message-ID: <20160531132706.GC29837@sirena.org.uk>

On Tue, May 31, 2016 at 12:44:54PM +0200, Michal Suchanek wrote:
> On 30 May 2016 at 17:50, Mark Brown <broonie at kernel.org> wrote:
> > On Mon, May 30, 2016 at 05:28:10PM +0200, Michal Suchanek wrote:

> >> It's what the driver did to start with and it was requested to fall
> >> back to non-DMA in the case DMA is not available.

> > Why?  I really can't see any sensible use case for this that doesn't
> > have a better solution available.

> Of course, the solution is to compile in the DMA driver.

> It's been argued that some drivers which use only short transfers will
> just work.

With nothing else in the system that needs DMA?  It's making the
performance of the system less reliable for the benefit of a very narrow
use case.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160531/f521afd4/attachment.sig>

From pramod.kumar at broadcom.com  Tue May 31 06:36:34 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Tue, 31 May 2016 19:06:34 +0530
Subject: [PATCH v2 0/7] Add MDIO bus multiplexer support for iProc SoCs
Message-ID: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>

Broadcom iProc based SoCs use a MDIO bus multiplexer where child buses
could be internal as well external to SoCs. These buses could supports
MDIO transaction compatible to C-22/C-45.

Broadcom MDIO bus mulitplexer is an integrated multiplexer where child bus
selection and mdio transaction logic lies inside multiplexer itself.
To accommodate this multiplexer in existing mux framework below changes
were required-

1. Passed MDIO parent bus via mdio_mux_init to MDIO mux framework.

2. Defined one new boolean property named "mdio-integrated-mux". Integrated
   bus Multiplexer node defines this so when parent bus is registered
   by calling "of_mdiobus_register", this api will not scan for child
   nodes. Child node of integrated multiplexer will be muxed nodes not
   PHYs one hence should not be scanned.

This patch set includes MDIO bus multiplexer driver along with above
framework changes. It includes one external bus node having Ethernet PHY
attached and two internal bus node holding PCIe PHYs.

This patch series is based on v4.6.0-rc1 and is available from github-
repo: https://github.com/Broadcom/arm64-linux.git
branch:mdio-mux-v2

Changes from v1:
- stop using "brcm,is_c45" from bus node as suggested by Andrew. MDIO
PHY driver will logically OR MII_ADDR_C45 into the address when issues
any C45 MDIO read/write transaction.

Pramod Kumar (7):
  mdio:mux: Enhanced MDIO mux framework for integrated multiplexers
  DT: phy.txt: Add mdio-integrated-mux property
  binding: mdio-mux: Add DT binding doc for Broadcom MDIO bus mutiplexer
  DT:mdio-mux: Add mdio multiplexer driver node
  net:mdio-mux: Add MDIO mux driver for iProc SoCs
  Binding:PHY: Binding doc for NS2 PCIe PHYs.
  phy: Add Northstar2 PCI Phy support

 .../bindings/net/brcm,mdio-mux-iproc.txt           |  60 +++++
 Documentation/devicetree/bindings/net/mdio-mux.txt |   9 +-
 .../bindings/phy/brcm,mdio-mux-bus-pci.txt         |  27 +++
 arch/arm64/boot/dts/broadcom/ns2-svk.dts           |  12 +
 arch/arm64/boot/dts/broadcom/ns2.dtsi              |  32 +++
 drivers/net/phy/Kconfig                            |  11 +
 drivers/net/phy/Makefile                           |   1 +
 drivers/net/phy/mdio-mux-bcm-iproc.c               | 243 +++++++++++++++++++++
 drivers/net/phy/mdio-mux-gpio.c                    |   2 +-
 drivers/net/phy/mdio-mux-mmioreg.c                 |   2 +-
 drivers/net/phy/mdio-mux.c                         |  28 ++-
 drivers/of/of_mdio.c                               |   3 +
 drivers/phy/Kconfig                                |   8 +
 drivers/phy/Makefile                               |   1 +
 drivers/phy/phy-bcm-ns2-pcie.c                     | 115 ++++++++++
 include/linux/mdio-mux.h                           |   4 +-
 16 files changed, 544 insertions(+), 14 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
 create mode 100644 Documentation/devicetree/bindings/phy/brcm,mdio-mux-bus-pci.txt
 create mode 100644 drivers/net/phy/mdio-mux-bcm-iproc.c
 create mode 100644 drivers/phy/phy-bcm-ns2-pcie.c

-- 
1.9.1



From pramod.kumar at broadcom.com  Tue May 31 06:36:35 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Tue, 31 May 2016 19:06:35 +0530
Subject: [PATCH v2 1/7] mdio:mux: Enhanced MDIO mux framework for integrated
 multiplexers
In-Reply-To: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464701801-17243-2-git-send-email-pramod.kumar@broadcom.com>

An integrated multiplexer uses same address space for
"muxed bus selection" and "generation of mdio transaction"
hence its good to register parent bus from mux driver.

Hence added a mechanism where mux driver could register a
parent bus and pass it down to framework via mdio_mux_init api.

Below changes are required to make this happen-

1. When mdio-mux parent bus is registered, mdio framework should not
parse for child as it will be muxed bus node not PHYs.

-created a new property "mdio-mux-bus-parent". if this property is present,
of_mdiobus_register will not scan for phys.

2. Passed down parent bus to mdio mux framework via mdio-mux-init api.

Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 drivers/net/phy/mdio-mux-gpio.c    |  2 +-
 drivers/net/phy/mdio-mux-mmioreg.c |  2 +-
 drivers/net/phy/mdio-mux.c         | 28 ++++++++++++++++++----------
 drivers/of/of_mdio.c               |  3 +++
 include/linux/mdio-mux.h           |  4 +++-
 5 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c
index 7ddb1ab..9199499 100644
--- a/drivers/net/phy/mdio-mux-gpio.c
+++ b/drivers/net/phy/mdio-mux-gpio.c
@@ -55,7 +55,7 @@ static int mdio_mux_gpio_probe(struct platform_device *pdev)
 		return PTR_ERR(s->gpios);
 
 	r = mdio_mux_init(&pdev->dev,
-			  mdio_mux_gpio_switch_fn, &s->mux_handle, s);
+			  mdio_mux_gpio_switch_fn, &s->mux_handle, s, NULL);
 
 	if (r != 0) {
 		gpiod_put_array(s->gpios);
diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c
index 7fde454..d0bed52 100644
--- a/drivers/net/phy/mdio-mux-mmioreg.c
+++ b/drivers/net/phy/mdio-mux-mmioreg.c
@@ -126,7 +126,7 @@ static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
 	}
 
 	ret = mdio_mux_init(&pdev->dev, mdio_mux_mmioreg_switch_fn,
-			    &s->mux_handle, s);
+			    &s->mux_handle, s, NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register mdio-mux bus %s\n",
 			np->full_name);
diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c
index 308ade0..521ab90 100644
--- a/drivers/net/phy/mdio-mux.c
+++ b/drivers/net/phy/mdio-mux.c
@@ -95,7 +95,8 @@ static int parent_count;
 int mdio_mux_init(struct device *dev,
 		  int (*switch_fn)(int cur, int desired, void *data),
 		  void **mux_handle,
-		  void *data)
+		  void *data,
+		  struct mii_bus *mux_bus)
 {
 	struct device_node *parent_bus_node;
 	struct device_node *child_bus_node;
@@ -107,10 +108,21 @@ int mdio_mux_init(struct device *dev,
 	if (!dev->of_node)
 		return -ENODEV;
 
-	parent_bus_node = of_parse_phandle(dev->of_node, "mdio-parent-bus", 0);
+	if (!mux_bus) {
+		parent_bus_node = of_parse_phandle(dev->of_node,
+						   "mdio-parent-bus", 0);
 
-	if (!parent_bus_node)
-		return -ENODEV;
+		if (!parent_bus_node)
+			return -ENODEV;
+
+		parent_bus = of_mdio_find_bus(parent_bus_node);
+		if (!parent_bus) {
+			ret_val = -EPROBE_DEFER;
+			goto err_parent_bus;
+		}
+	} else {
+		parent_bus = mux_bus;
+	}
 
 	pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL);
 	if (pb == NULL) {
@@ -118,11 +130,6 @@ int mdio_mux_init(struct device *dev,
 		goto err_parent_bus;
 	}
 
-	parent_bus = of_mdio_find_bus(parent_bus_node);
-	if (parent_bus == NULL) {
-		ret_val = -EPROBE_DEFER;
-		goto err_parent_bus;
-	}
 
 	pb->switch_data = data;
 	pb->switch_fn = switch_fn;
@@ -183,7 +190,8 @@ int mdio_mux_init(struct device *dev,
 	put_device(&pb->mii_bus->dev);
 
 err_parent_bus:
-	of_node_put(parent_bus_node);
+	if (!mux_bus)
+		of_node_put(parent_bus_node);
 	return ret_val;
 }
 EXPORT_SYMBOL_GPL(mdio_mux_init);
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 8453f08..cf40e7a 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -225,6 +225,9 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 	if (rc)
 		return rc;
 
+	if (of_property_read_bool(np, "mdio-integrated-mux"))
+		return 0;
+
 	/* Loop over the child nodes and register a phy_device for each phy */
 	for_each_available_child_of_node(np, child) {
 		addr = of_mdio_parse_addr(&mdio->dev, child);
diff --git a/include/linux/mdio-mux.h b/include/linux/mdio-mux.h
index a243dbb..61f5b21 100644
--- a/include/linux/mdio-mux.h
+++ b/include/linux/mdio-mux.h
@@ -10,11 +10,13 @@
 #ifndef __LINUX_MDIO_MUX_H
 #define __LINUX_MDIO_MUX_H
 #include <linux/device.h>
+#include <linux/phy.h>
 
 int mdio_mux_init(struct device *dev,
 		  int (*switch_fn) (int cur, int desired, void *data),
 		  void **mux_handle,
-		  void *data);
+		  void *data,
+		  struct mii_bus *mux_bus);
 
 void mdio_mux_uninit(void *mux_handle);
 
-- 
1.9.1



From pramod.kumar at broadcom.com  Tue May 31 06:36:36 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Tue, 31 May 2016 19:06:36 +0530
Subject: [PATCH v2 2/7] DT: phy.txt: Add mdio-integrated-mux property
In-Reply-To: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464701801-17243-3-git-send-email-pramod.kumar@broadcom.com>

This property is used by integrated MDIO multiplexer
which has bus selection and mdio transaction generation logic,
integrated inside.

Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 Documentation/devicetree/bindings/net/mdio-mux.txt | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/mdio-mux.txt b/Documentation/devicetree/bindings/net/mdio-mux.txt
index 491f5bd..b5ad83e 100644
--- a/Documentation/devicetree/bindings/net/mdio-mux.txt
+++ b/Documentation/devicetree/bindings/net/mdio-mux.txt
@@ -5,13 +5,20 @@ numbered uniquely in a device dependent manner.  The nodes for an MDIO
 bus multiplexer/switch will have one child node for each child bus.
 
 Required properties:
-- mdio-parent-bus : phandle to the parent MDIO bus.
 - #address-cells = <1>;
 - #size-cells = <0>;
 
 Optional properties:
+- mdio-parent-bus : phandle to the parent MDIO bus. Should be used
+		if parent mdio bus is not part of multiplexer.
+- mdio-integrated-mux: boolean property indicateing that the hardware
+		is an integrated multiplex supporting muxed bus selection
+		and MDIO transaction logic generation.
 - Other properties specific to the multiplexer/switch hardware.
 
+Note: one of mdio-parent-bus and mdio-integrated-mux is mandatory to
+get parent bus regsitered.
+
 Required properties for child nodes:
 - #address-cells = <1>;
 - #size-cells = <0>;
-- 
1.9.1



From pramod.kumar at broadcom.com  Tue May 31 06:36:38 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Tue, 31 May 2016 19:06:38 +0530
Subject: [PATCH v2 4/7] DT:mdio-mux: Add mdio multiplexer driver node
In-Reply-To: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464701801-17243-5-git-send-email-pramod.kumar@broadcom.com>

Add integrated MDIO multiplexer driver node which contains
two mux PCIe bus and one ethernet bus along with phys
lying on these bus.

Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 arch/arm64/boot/dts/broadcom/ns2-svk.dts | 12 ++++++++++++
 arch/arm64/boot/dts/broadcom/ns2.dtsi    | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/arch/arm64/boot/dts/broadcom/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
index ce0ab84..8f6a6cc 100644
--- a/arch/arm64/boot/dts/broadcom/ns2-svk.dts
+++ b/arch/arm64/boot/dts/broadcom/ns2-svk.dts
@@ -87,3 +87,15 @@
 		#size-cells = <1>;
 	};
 };
+
+&mdio_mux_iproc {
+	mdio at 10 {
+		reg = <0x10>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gphy0: eth-phy at 10 {
+			reg = <0x10>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi
index 6f81c9d..efc320a 100644
--- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
+++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
@@ -330,6 +330,38 @@
 			      <0x65260000 0x1000>;
 		};
 
+		mdio_mux_iproc: mdio_mux_iproc at 6602023c {
+			compatible = "brcm,mdio-mux-iproc";
+			reg = <0x6602023c 0x14>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			mdio-integrated-mux;
+
+			mdio at 0 {
+				reg = <0x0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pci_phy0: pci-phy at 0 {
+					compatible = "brcm,ns2-pcie-phy";
+					reg = <0x0>;
+					#phy-cells = <0>;
+				};
+			};
+
+			mdio at 7 {
+				reg = <0x7>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pci_phy1: pci-phy at 0 {
+					compatible = "brcm,ns2-pcie-phy";
+					reg = <0x0>;
+					#phy-cells = <0>;
+				};
+			};
+		};
+
 		timer0: timer at 66030000 {
 			compatible = "arm,sp804", "arm,primecell";
 			reg = <0x66030000 0x1000>;
-- 
1.9.1



From pramod.kumar at broadcom.com  Tue May 31 06:36:37 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Tue, 31 May 2016 19:06:37 +0530
Subject: [PATCH v2 3/7] binding: mdio-mux: Add DT binding doc for Broadcom
 MDIO bus mutiplexer
In-Reply-To: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464701801-17243-4-git-send-email-pramod.kumar@broadcom.com>

Add DT binding doc for Broadcom MDIO bus mutiplexer driver.

Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 .../bindings/net/brcm,mdio-mux-iproc.txt           | 60 ++++++++++++++++++++++
 1 file changed, 60 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt

diff --git a/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
new file mode 100644
index 0000000..f270b41
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.txt
@@ -0,0 +1,60 @@
+Properties for an MDIO bus mutiplexer found in Broadcom iProc based SoCs.
+
+This MDIO bus multiplexer defines buses that could be internal as well as
+external to SoCs and could accept MDIO transaction compatible to C-22 or
+C-45 Clause. When Child bus is selected, one need to select these two
+properties as well to generate desired MDIO trascation on appropriate bus.
+
+Required properties in addition to the generic multiplexer properties:
+
+MDIO multiplexer node:
+- complatible: brcm,mdio-mux-iproc.
+
+Every non-ethernet PHY requires a compatible so that it could be probed based
+on this compatible string.
+
+Additional information regarding generic multiplexer properties could be found
+at- Documentation/devicetree/bindings/net/mdio-mux.txt
+
+
+for example:
+		mdio_mux_iproc: mdio_mux_iproc at 6602023c {
+			compatible = "brcm,mdio-mux-iproc";
+			reg = <0x6602023c 0x14>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			mdio-integrated-mux;
+
+			mdio at 0 {
+				reg = <0x0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pci_phy0: pci-phy at 0 {
+					compatible = "brcm,ns2-pcie-phy";
+					reg = <0x0>;
+					#phy-cells = <0>;
+				};
+			};
+
+			mdio at 7 {
+				reg = <0x7>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pci_phy1: pci-phy at 0 {
+					compatible = "brcm,ns2-pcie-phy";
+					reg = <0x0>;
+					#phy-cells = <0>;
+				};
+			};
+			mdio at 10 {
+				reg = <0x10>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				gphy0: eth-phy at 10 {
+					reg = <0x10>;
+				};
+			};
+		};
-- 
1.9.1



From pramod.kumar at broadcom.com  Tue May 31 06:36:39 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Tue, 31 May 2016 19:06:39 +0530
Subject: [PATCH v2 5/7] net:mdio-mux: Add MDIO mux driver for iProc SoCs
In-Reply-To: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464701801-17243-6-git-send-email-pramod.kumar@broadcom.com>

iProc based SoCs supports the integrated mdio multiplexer which
has the bus selection as well as mdio transaction generation logic
inside.

This mutiplexer has child buses for PCIe, SATA, USB and ETH. These
buses could be internal or external to SOC where PHYs are attached.
These buses could use C-45 or C-22 mdio transaction.

Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 drivers/net/phy/Kconfig              |  11 ++
 drivers/net/phy/Makefile             |   1 +
 drivers/net/phy/mdio-mux-bcm-iproc.c | 243 +++++++++++++++++++++++++++++++++++
 3 files changed, 255 insertions(+)
 create mode 100644 drivers/net/phy/mdio-mux-bcm-iproc.c

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 6dad9a9..38faecf 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -254,6 +254,17 @@ config MDIO_BUS_MUX_MMIOREG
 
 	  Currently, only 8-bit registers are supported.
 
+config MDIO_BUS_MUX_BCM_IPROC
+	tristate "Support for iProc based MDIO bus multiplexers"
+	depends on OF && OF_MDIO && (ARCH_BCM_IPROC || COMPILE_TEST)
+	select MDIO_BUS_MUX
+	default ARCH_BCM_IPROC
+	help
+	  This module provides a driver for MDIO bus multiplexers found in
+	  iProc based Broadcom SoCs. This mulitplexer connects one of several
+	  child MDIO bus to a parent bus. Buses could be interal as well as
+	  external and selection logic lies inside the same multiplexer.
+
 config MDIO_BCM_UNIMAC
 	tristate "Broadcom UniMAC MDIO bus controller"
 	depends on HAS_IOMEM
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index fcdbb92..f5951d5a 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_AMD_PHY)		+= amd.o
 obj-$(CONFIG_MDIO_BUS_MUX)	+= mdio-mux.o
 obj-$(CONFIG_MDIO_BUS_MUX_GPIO)	+= mdio-mux-gpio.o
 obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o
+obj-$(CONFIG_MDIO_BUS_MUX_BCM_IPROC)	+= mdio-mux-bcm-iproc.o
 obj-$(CONFIG_MDIO_SUN4I)	+= mdio-sun4i.o
 obj-$(CONFIG_MDIO_MOXART)	+= mdio-moxart.o
 obj-$(CONFIG_MDIO_BCM_UNIMAC)	+= mdio-bcm-unimac.o
diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c
new file mode 100644
index 0000000..f047be6
--- /dev/null
+++ b/drivers/net/phy/mdio-mux-bcm-iproc.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2016 Broadcom
+ *
+ * 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 (the "GPL").
+ *
+ * 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 version 2 (GPLv2) for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 (GPLv2) along with this source code.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/of_mdio.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/mdio-mux.h>
+#include <linux/delay.h>
+
+#define MDIO_PARAM_OFFSET		0x00
+#define MDIO_PARAM_MIIM_CYCLE		29
+#define MDIO_PARAM_INTERNAL_SEL		25
+#define MDIO_PARAM_BUS_ID		22
+#define MDIO_PARAM_C45_SEL		21
+#define MDIO_PARAM_PHY_ID		16
+#define MDIO_PARAM_PHY_DATA		0
+
+#define MDIO_READ_OFFSET		0x04
+#define MDIO_READ_DATA_MASK		0xffff
+#define MDIO_ADDR_OFFSET		0x08
+
+#define MDIO_CTRL_OFFSET		0x0C
+#define MDIO_CTRL_WRITE_OP		0x1
+#define MDIO_CTRL_READ_OP		0x2
+
+#define MDIO_STAT_OFFSET		0x10
+#define MDIO_STAT_DONE			1
+
+#define BUS_MAX_ADDR			32
+#define EXT_BUS_START_ADDR		16
+
+struct iproc_mdiomux_desc {
+	void *mux_handle;
+	void __iomem *base;
+	struct device *dev;
+	struct mii_bus *mii_bus;
+};
+
+static int iproc_mdio_wait_for_idle(void __iomem *base, bool result)
+{
+	u32 val;
+	unsigned int timeout = 1000; /* loop for 1s */
+
+	do {
+		val = readl(base + MDIO_STAT_OFFSET);
+		if ((val & MDIO_STAT_DONE) == result)
+			return 0;
+
+		usleep_range(1000, 2000);
+	} while (timeout--);
+
+	return -ETIMEDOUT;
+}
+
+/* start_miim_ops- Program and start MDIO transaction over mdio bus.
+ * @base: Base address
+ * @phyid: phyid of the selected bus.
+ * @reg: register offset to be read/written.
+ * @val :0 if read op else value to be written in @reg;
+ * @op: Operation that need to be carried out.
+ *      MDIO_CTRL_READ_OP: Read transaction.
+ *      MDIO_CTRL_WRITE_OP: Write transaction.
+ *
+ * Return value: Successful Read operation returns read reg values and write
+ *      operation returns 0. Failure operation returns negative error code.
+ */
+static int start_miim_ops(void __iomem *base,
+			  u16 phyid, u32 reg, u16 val, u32 op)
+{
+	int ret;
+	u32 param;
+
+	writel(0, base + MDIO_CTRL_OFFSET);
+	ret = iproc_mdio_wait_for_idle(base, 0);
+	if (ret)
+		goto err;
+
+	param = readl(base + MDIO_PARAM_OFFSET);
+	param |= phyid << MDIO_PARAM_PHY_ID;
+	param |= val << MDIO_PARAM_PHY_DATA;
+	if (reg & MII_ADDR_C45)
+		param |= (1 << MDIO_PARAM_C45_SEL);
+
+	writel(param, base + MDIO_PARAM_OFFSET);
+
+	writel(reg, base + MDIO_ADDR_OFFSET);
+
+	writel(op, base + MDIO_CTRL_OFFSET);
+
+	ret = iproc_mdio_wait_for_idle(base, 1);
+	if (ret)
+		goto err;
+
+	if (op == MDIO_CTRL_READ_OP)
+		ret = readl(base + MDIO_READ_OFFSET) & MDIO_READ_DATA_MASK;
+err:
+	return ret;
+}
+
+static int iproc_mdiomux_read(struct mii_bus *bus, int phyid, int reg)
+{
+	int ret;
+	struct iproc_mdiomux_desc *md = bus->priv;
+
+	ret = start_miim_ops(md->base, phyid, reg, 0, MDIO_CTRL_READ_OP);
+	if (ret < 0)
+		dev_err(&bus->dev, "mdiomux read operation failed!!!");
+
+	return ret;
+}
+
+static int iproc_mdiomux_write(struct mii_bus *bus,
+			       int phyid, int reg, u16 val)
+{
+	int ret;
+	struct iproc_mdiomux_desc *md = bus->priv;
+
+	/* Write val at reg offset */
+	ret = start_miim_ops(md->base, phyid, reg, val, MDIO_CTRL_WRITE_OP);
+	if (ret < 0)
+		dev_err(&bus->dev, "mdiomux write operation failed!!!");
+
+	return ret;
+}
+
+static int mdio_mux_iproc_switch_fn(int current_child, int desired_child,
+				    void *data)
+{
+	struct iproc_mdiomux_desc *md = data;
+	u32 param, bus_id;
+	bool bus_dir;
+
+	/* select bus and its properties */
+	bus_dir = (desired_child < EXT_BUS_START_ADDR);
+	bus_id = bus_dir ? desired_child : (desired_child - EXT_BUS_START_ADDR);
+
+	param = (bus_dir ? 1 : 0) << MDIO_PARAM_INTERNAL_SEL;
+	param |= (bus_id << MDIO_PARAM_BUS_ID);
+
+	writel(param, md->base + MDIO_PARAM_OFFSET);
+	return 0;
+}
+
+static int mdio_mux_iproc_probe(struct platform_device *pdev)
+{
+	struct iproc_mdiomux_desc *md;
+	struct mii_bus *bus;
+	struct resource *res;
+	int rc;
+
+	md = devm_kzalloc(&pdev->dev, sizeof(*md), GFP_KERNEL);
+	if (!md)
+		return -ENOMEM;
+	md->dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	md->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(md->base)) {
+		dev_err(&pdev->dev, "failed to ioremap register\n");
+		return PTR_ERR(md->base);
+	}
+
+	md->mii_bus = mdiobus_alloc();
+	if (!md->mii_bus) {
+		dev_err(&pdev->dev, "mdiomux bus alloc failed\n");
+		return -ENOMEM;
+	}
+
+	bus = md->mii_bus;
+	bus->priv = md;
+	bus->name = "iProc MDIO mux bus";
+	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", pdev->name, pdev->id);
+	bus->parent = &pdev->dev;
+	bus->read = iproc_mdiomux_read;
+	bus->write = iproc_mdiomux_write;
+
+	rc = of_mdiobus_register(bus, pdev->dev.of_node);
+	if (rc) {
+		dev_err(&pdev->dev, "mdiomux registration failed\n");
+		goto out;
+	}
+
+	platform_set_drvdata(pdev, md);
+
+	rc = mdio_mux_init(md->dev, mdio_mux_iproc_switch_fn,
+			   &md->mux_handle, md, md->mii_bus);
+	if (rc) {
+		dev_info(md->dev, "mdiomux initialization failed\n");
+		goto out;
+	}
+
+	dev_info(md->dev, "iProc mdiomux registered\n");
+	return 0;
+out:
+	mdiobus_free(bus);
+	return rc;
+}
+
+static int mdio_mux_iproc_remove(struct platform_device *pdev)
+{
+	struct iproc_mdiomux_desc *md = dev_get_platdata(&pdev->dev);
+
+	mdio_mux_uninit(md->mux_handle);
+	return 0;
+}
+
+static const struct of_device_id mdio_mux_iproc_match[] = {
+	{
+		.compatible = "brcm,mdio-mux-iproc",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mdio_mux_iproc_match);
+
+static struct platform_driver mdiomux_iproc_driver = {
+	.driver = {
+		.name		= "mdio-mux-iproc",
+		.of_match_table = mdio_mux_iproc_match,
+	},
+	.probe		= mdio_mux_iproc_probe,
+	.remove		= mdio_mux_iproc_remove,
+};
+
+module_platform_driver(mdiomux_iproc_driver);
+
+MODULE_DESCRIPTION("iProc MDIO Mux Bus Driver");
+MODULE_AUTHOR("Pramod Kumar <pramod.kumar at broadcom.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1



From pramod.kumar at broadcom.com  Tue May 31 06:36:40 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Tue, 31 May 2016 19:06:40 +0530
Subject: [PATCH v2 6/7] Binding:PHY: Binding doc for NS2 PCIe PHYs.
In-Reply-To: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464701801-17243-7-git-send-email-pramod.kumar@broadcom.com>

Binding doc for NS2 PCIe PHYs.

Signed-off-by: Jon Mason <jonmason at broadcom.com>
Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 .../bindings/phy/brcm,mdio-mux-bus-pci.txt         | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/brcm,mdio-mux-bus-pci.txt

diff --git a/Documentation/devicetree/bindings/phy/brcm,mdio-mux-bus-pci.txt b/Documentation/devicetree/bindings/phy/brcm,mdio-mux-bus-pci.txt
new file mode 100644
index 0000000..5b51007
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/brcm,mdio-mux-bus-pci.txt
@@ -0,0 +1,27 @@
+* Broadcom NS2 PCIe PHY binding document
+
+Required bus properties:
+- reg: MDIO Bus number for the MDIO interface
+- #address-cells: must be 1
+- #size-cells: must be 0
+
+Required PHY properties:
+- compatible: should be "brcm,ns2-pcie-phy"
+- reg: MDIO Phy ID for the MDIO interface
+- #phy-cells: must be 0
+
+This is a child bus node of "brcm,mdio-mux-iproc" node.
+
+Example:
+
+mdio at 0 {
+	reg = <0x0>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	pci_phy0: pci-phy at 0 {
+		compatible = "brcm,ns2-pcie-phy";
+		reg = <0x0>;
+		#phy-cells = <0>;
+	};
+};
-- 
1.9.1



From pramod.kumar at broadcom.com  Tue May 31 06:36:41 2016
From: pramod.kumar at broadcom.com (Pramod Kumar)
Date: Tue, 31 May 2016 19:06:41 +0530
Subject: [PATCH v2 7/7] phy: Add Northstar2 PCI Phy support
In-Reply-To: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
References: <1464701801-17243-1-git-send-email-pramod.kumar@broadcom.com>
Message-ID: <1464701801-17243-8-git-send-email-pramod.kumar@broadcom.com>

Add PCI Phy support for Broadcom Northstar2 SoCs.  This driver uses the
interface from the iproc mdio mux driver to enable the devices
respective phys.

Signed-off-by: Jon Mason <jonmason at broadcom.com>
Signed-off-by: Pramod Kumar <pramod.kumar at broadcom.com>
---
 drivers/phy/Kconfig            |   8 +++
 drivers/phy/Makefile           |   1 +
 drivers/phy/phy-bcm-ns2-pcie.c | 115 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 124 insertions(+)
 create mode 100644 drivers/phy/phy-bcm-ns2-pcie.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 26566db..5ff60b2 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -421,4 +421,12 @@ config PHY_CYGNUS_PCIE
 	  Enable this to support the Broadcom Cygnus PCIe PHY.
 	  If unsure, say N.
 
+config PHY_NS2_PCIE
+	tristate "Broadcom Northstar2 PCIe PHY driver"
+	depends on OF && MDIO_BUS_MUX_BCM_IPROC
+	select GENERIC_PHY
+	default ARCH_BCM_IPROC
+	help
+	  Enable this to support the Broadcom Northstar2 PCIe PHY.
+	  If unsure, say N.
 endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 24596a9..77d51ff 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -52,3 +52,4 @@ obj-$(CONFIG_PHY_TUSB1210)		+= phy-tusb1210.o
 obj-$(CONFIG_PHY_BRCMSTB_SATA)		+= phy-brcmstb-sata.o
 obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
 obj-$(CONFIG_PHY_CYGNUS_PCIE)		+= phy-bcm-cygnus-pcie.o
+obj-$(CONFIG_PHY_NS2_PCIE)		+= phy-bcm-ns2-pcie.o
diff --git a/drivers/phy/phy-bcm-ns2-pcie.c b/drivers/phy/phy-bcm-ns2-pcie.c
new file mode 100644
index 0000000..65c3870
--- /dev/null
+++ b/drivers/phy/phy-bcm-ns2-pcie.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of_mdio.h>
+#include <linux/mdio.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+
+struct ns2_pci_phy {
+	struct mdio_device *mdiodev;
+	struct phy *phy;
+};
+
+#define BLK_ADDR_REG_OFFSET	0x1f
+#define PLL_AFE1_100MHZ_BLK	0x2100
+#define PLL_CLK_AMP_OFFSET	0x03
+#define PLL_CLK_AMP_2P05V	0x2b18
+
+static int ns2_pci_phy_init(struct phy *p)
+{
+	struct ns2_pci_phy *phy = phy_get_drvdata(p);
+	int rc;
+
+	/* select the AFE 100MHz block page */
+	rc = mdiobus_write(phy->mdiodev->bus, phy->mdiodev->addr,
+			   BLK_ADDR_REG_OFFSET, PLL_AFE1_100MHZ_BLK);
+	if (rc)
+		goto err;
+
+	/* set the 100 MHz reference clock amplitude to 2.05 v */
+	rc = mdiobus_write(phy->mdiodev->bus, phy->mdiodev->addr,
+			   PLL_CLK_AMP_OFFSET, PLL_CLK_AMP_2P05V);
+	if (rc)
+		goto err;
+
+	return 0;
+
+err:
+	dev_err(&phy->mdiodev->dev, "Error %d writing to phy\n", rc);
+	return rc;
+}
+
+static struct phy_ops ns2_pci_phy_ops = {
+	.init = ns2_pci_phy_init,
+};
+
+static int ns2_pci_phy_probe(struct mdio_device *mdiodev)
+{
+	struct device *dev = &mdiodev->dev;
+	struct phy_provider *provider;
+	struct ns2_pci_phy *p;
+	struct phy *phy;
+
+	phy = devm_phy_create(dev, dev->of_node, &ns2_pci_phy_ops);
+	if (IS_ERR_OR_NULL(phy)) {
+		dev_err(dev, "failed to create Phy\n");
+		return PTR_ERR(phy);
+	}
+
+	p = devm_kmalloc(dev, sizeof(struct ns2_pci_phy),
+			 GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	p->mdiodev = mdiodev;
+	dev_set_drvdata(dev, p);
+
+	p->phy = phy;
+	phy_set_drvdata(phy, p);
+
+	provider = devm_of_phy_provider_register(&phy->dev,
+						 of_phy_simple_xlate);
+	if (IS_ERR(provider)) {
+		dev_err(dev, "failed to register Phy provider\n");
+		return PTR_ERR(provider);
+	}
+
+	dev_info(dev, "%s PHY registered\n", dev_name(dev));
+
+	return 0;
+}
+
+static const struct of_device_id ns2_pci_phy_of_match[] = {
+	{ .compatible = "brcm,ns2-pcie-phy", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ns2_pci_phy_of_match);
+
+static struct mdio_driver ns2_pci_phy_driver = {
+	.mdiodrv = {
+		.driver = {
+			.name = "phy-bcm-ns2-pci",
+			.of_match_table = ns2_pci_phy_of_match,
+		},
+	},
+	.probe = ns2_pci_phy_probe,
+};
+mdio_module_driver(ns2_pci_phy_driver);
+
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Broadcom Northstar2 PCI Phy driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:phy-bcm-ns2-pci");
-- 
1.9.1



From robin.murphy at arm.com  Tue May 31 06:40:24 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 31 May 2016 14:40:24 +0100
Subject: [PATCH] drivers: char: mem: Check {read,write}_kmem() addresses
In-Reply-To: <20160531130821.GV19428@n2100.arm.linux.org.uk>
References: <5e293c103f0a86f512d71f17091a55e9746e711f.1464698496.git.robin.murphy@arm.com>
 <20160531130821.GV19428@n2100.arm.linux.org.uk>
Message-ID: <574D9448.7080206@arm.com>

On 31/05/16 14:08, Russell King - ARM Linux wrote:
> On Tue, May 31, 2016 at 01:52:45PM +0100, Robin Murphy wrote:
>> Arriving at read_kmem() with an offset representing a bogus kernel
>> address (e.g. 0 from a simple "cat /dev/kmem") leads to copy_to_user
>> faulting on the kernel-space read.
>>
>> x86_64 happens to get away with this since the optimised implementation
>> uses "rep movs*", thus the user write (which is allowed to fault) and
>> the kernel read are the same instruction, the kernel-side fault falls
>> into the userspace fixup handler and a chain of events transpires
>> leading to returning the expected -EFAULT. On other architectures,
>> though, the read is not covered by the fixup entry for the write, and we
>> get a straightforward "Unable to hande kernel paging request..." dump.
>>
>> The more typical use-case of mmap_kmem() already validates the address
>> with pfn_valid() as one might expect, so let's make that consistent
>> across {read,write}_kem() too.
>>
>> Reported-by: Kefeng Wang <wangkefeng.wang at huawei.com>
>> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
>> ---
>>
>> I'm not sure if this warrants going to stable or not, as it's really
>> just making an existing failure case more graceful and less confusing.
>
> Returning -EFAULT because the kernel-side address (iow, file offset) is
> invalid is not particularly nice:
>
> NAME
>         read - read from a file descriptor
>
> ERRORS
>         EFAULT buf is outside your accessible address space.
>
> Latest POSIX has:
>
> ENXIO
> 	A request was made of a nonexistent device, or the
> 	request was outside the capabilities of the device.
>
> which to me looks like a better error code to return, as file offsets
> which are not valid can be interpreted as being "outside the
> capabilities of the device".  EFAULT has always on Linux meant that
> the user passed an invalid userspace buffer.

Good point - seems I failed to twig that the error code in the x86 case 
is still effectively falling out of the "fault with the user address" 
path. ENXIO indeed sounds more reasonable, thanks.

Robin.


From huangtao at rock-chips.com  Tue May 31 06:45:51 2016
From: huangtao at rock-chips.com (Huang, Tao)
Date: Tue, 31 May 2016 21:45:51 +0800
Subject: [PATCH 3/5] clocksource: rockchip: add dynamic irq flag to the
 timer
In-Reply-To: <574CC9DE.1050501@linaro.org>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
 <1464169802-6033-4-git-send-email-wxt@rock-chips.com>
 <574CC9DE.1050501@linaro.org>
Message-ID: <574D958F.9010707@rock-chips.com>

Hi Daniel:
On 2016?05?31? 07:16, Daniel Lezcano wrote:
> On 05/25/2016 11:50 AM, Caesar Wang wrote:
>> From: Huang Tao <huangtao at rock-chips.com>
>>
>> The rockchip timer is broadcast timer. Add CLOCK_EVT_FEAT_DYNIRQ
>> flag and set cpumask to all cpu to save power by avoid unnecessary
>> wakeups and IPIs.
>>
>> Signed-off-by: Huang Tao <huangtao at rock-chips.com>
>> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
>> Cc: Thomas Gleixner <tglx at linutronix.de>
>> Cc: Heiko Stuebner <heiko at sntech.de>
>> Tested-by: Jianqun Xu <jay.xu at rock-chips.com>
>> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>> ---
>>
>>   drivers/clocksource/rockchip_timer.c | 5 +++--
>>   1 file changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c
>> index b93fed6..f3dfb1a 100644
>> --- a/drivers/clocksource/rockchip_timer.c
>> +++ b/drivers/clocksource/rockchip_timer.c
>> @@ -150,12 +150,13 @@ static void __init rk_timer_init(struct device_node *np)
>>   	}
>>
>>   	ce->name = TIMER_NAME;
>> -	ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
>> +	ce->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
>> +		       CLOCK_EVT_FEAT_DYNIRQ;
>>   	ce->set_next_event = rk_timer_set_next_event;
>>   	ce->set_state_shutdown = rk_timer_shutdown;
>>   	ce->set_state_periodic = rk_timer_set_periodic;
>>   	ce->irq = irq;
>> -	ce->cpumask = cpumask_of(0);
>> +	ce->cpumask = cpu_all_mask;
> 
> s/cpu_all_mask/cpu_possible_mask/

Okay for me.
It seems drivers in drivers/clocksource are very confusing about use
cpu_all_mask or cpu_possible_mask. For example arm_arch_timer.c use
cpu_all_mask, while mtk_timer.c use cpu_possible_mask. I think all just
work.

Thanks,
Huang, Tao



From catalin.marinas at arm.com  Tue May 31 06:46:17 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 14:46:17 +0100
Subject: [PATCH] drivers: char: mem: Check {read,write}_kmem() addresses
In-Reply-To: <5e293c103f0a86f512d71f17091a55e9746e711f.1464698496.git.robin.murphy@arm.com>
References: <5e293c103f0a86f512d71f17091a55e9746e711f.1464698496.git.robin.murphy@arm.com>
Message-ID: <20160531134617.GA11321@e104818-lin.cambridge.arm.com>

On Tue, May 31, 2016 at 01:52:45PM +0100, Robin Murphy wrote:
> Arriving at read_kmem() with an offset representing a bogus kernel
> address (e.g. 0 from a simple "cat /dev/kmem") leads to copy_to_user
> faulting on the kernel-space read.
> 
> x86_64 happens to get away with this since the optimised implementation
> uses "rep movs*", thus the user write (which is allowed to fault) and
> the kernel read are the same instruction, the kernel-side fault falls
> into the userspace fixup handler and a chain of events transpires
> leading to returning the expected -EFAULT. On other architectures,
> though, the read is not covered by the fixup entry for the write, and we
> get a straightforward "Unable to hande kernel paging request..." dump.
> 
> The more typical use-case of mmap_kmem() already validates the address
> with pfn_valid() as one might expect, so let's make that consistent
> across {read,write}_kem() too.
> 
> Reported-by: Kefeng Wang <wangkefeng.wang at huawei.com>
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
> 
> I'm not sure if this warrants going to stable or not, as it's really
> just making an existing failure case more graceful and less confusing.
> 
>  drivers/char/mem.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/char/mem.c b/drivers/char/mem.c
> index 71025c2f6bbb..64c766023b15 100644
> --- a/drivers/char/mem.c
> +++ b/drivers/char/mem.c
> @@ -384,6 +384,9 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
>  	char *kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
>  	int err = 0;
>  
> +	if (!pfn_valid(PFN_DOWN(p)))
> +		return -EFAULT;
> +
>  	read = 0;
>  	if (p < (unsigned long) high_memory) {
>  		low_count = count;
> @@ -512,6 +515,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf,
>  	char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
>  	int err = 0;
>  
> +	if (!pfn_valid(PFN_DOWN(p)))
> +		return -EFAULT;

Since the /dev/kmem interface is about kernel virtual address rather
than physical (like /dev/mem), the pfn may not always be mapped. I think
a better check would be to use kern_addr_valid(kaddr) just before
copy_(to|from)_user (a similar approach is taken by read_kcore()). The
downside is that it breaks a couple of configurations where
kern_addr_valid() is 0:

- x86_32 with !CONFIG_FLATMEM
- alpha with CONFIG_DISCONTIGMEM

-- 
Catalin


From huangtao at rock-chips.com  Tue May 31 06:46:23 2016
From: huangtao at rock-chips.com (Huang, Tao)
Date: Tue, 31 May 2016 21:46:23 +0800
Subject: [PATCH 4/5] clocksource: rockchip: add support for rk3399 SoC
In-Reply-To: <574CCCB4.1030001@linaro.org>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
 <1464169802-6033-5-git-send-email-wxt@rock-chips.com>
 <574CCCB4.1030001@linaro.org>
Message-ID: <574D95AF.2020905@rock-chips.com>

Hi Daniel:
On 2016?05?31? 07:28, Daniel Lezcano wrote:
> On 05/25/2016 11:50 AM, Caesar Wang wrote:
>> From: Huang Tao <huangtao at rock-chips.com>
>>
>> The CONTROL register offset is different from old SoCs.
>> For Linux driver, there are not functional changes at all.
>> Let's call it v2.
>>
>> Signed-off-by: Huang Tao <huangtao at rock-chips.com>
>> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
>> Cc: Thomas Gleixner <tglx at linutronix.de>
>> Cc: Heiko Stuebner <heiko at sntech.de>
>> Tested-by: Jianqun Xu <jay.xu at rock-chips.com>
>> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>> ---
> 
> That's hackish.
Yes:( I blamed our IC guy.
> 
> Please consider something like:
> 
> diff --git a/drivers/clocksource/rockchip_timer.c 
> b/drivers/clocksource/rockchip_timer.c
> index b991b28..b6ba6f9 100644
> --- a/drivers/clocksource/rockchip_timer.c
> +++ b/drivers/clocksource/rockchip_timer.c
> @@ -19,7 +19,8 @@
> 
>   #define TIMER_LOAD_COUNT0	0x00
>   #define TIMER_LOAD_COUNT1	0x04
> -#define TIMER_CONTROL_REG	0x10
> +#define TIMER_CONTROL_REG3288	0x10
> +#define TIMER_CONTROL_REG3399	0x1C
>   #define TIMER_INT_STATUS	0x18
> 
>   #define TIMER_DISABLE		0x0
> @@ -31,6 +32,7 @@
>   struct bc_timer {
>   	struct clock_event_device ce;
>   	void __iomem *base;
> +	void __iomem *ctrl;
>   	u32 freq;
>   };
> 
> @@ -46,15 +48,20 @@ static inline void __iomem *rk_base(struct 
> clock_event_device *ce)
>   	return rk_timer(ce)->base;
>   }
> 
> +static inline void __iomem *rk_ctrl(struct clock_event_device *ce)
> +{
> +        return rk_timer(ce)->ctrl;
> +}
> +
>   static inline void rk_timer_disable(struct clock_event_device *ce)
>   {
> -	writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_CONTROL_REG);
> +	writel_relaxed(TIMER_DISABLE, rk_ctrl(ce));
>   }
> 
>   static inline void rk_timer_enable(struct clock_event_device *ce, u32 
> flags)
>   {
>   	writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags,
> -		       rk_base(ce) + TIMER_CONTROL_REG);
> +		       rk_ctrl(ce));
>   }
> 
>   static void rk_timer_update_counter(unsigned long cycles,
> @@ -179,4 +186,18 @@ out_unmap:
>   	iounmap(bc_timer.base);
>   }
> 
> -CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init);
> +static void __init rk3288_timer_init(struct device_node *np)
> +{
> +	bc_timer.ctrl = TIMER_CONTROL_REG3288;
> +	rk_timer_init(np);
> +}
> +
> +static void __init rk3399_timer_init(struct device_node *np)
> +{
> +        bc_timer.ctrl = TIMER_CONTROL_REG3399;
> +	rk_timer_init(np);
> +}
> +
> +
> +CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", 
> rk3288_timer_init);
> +CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3399-timer", 
> rk3399_timer_init);
> 
> 

I think you mean this patch otherwise compile will fail:
@@ -19,7 +19,8 @@

 #define TIMER_LOAD_COUNT0	0x00
 #define TIMER_LOAD_COUNT1	0x04
-#define TIMER_CONTROL_REG	0x10
+#define TIMER_CONTROL_REG3288	0x10
+#define TIMER_CONTROL_REG3399	0x1C
 #define TIMER_INT_STATUS	0x18

 #define TIMER_DISABLE		0x0
@@ -31,6 +32,7 @@
 struct bc_timer {
 	struct clock_event_device ce;
 	void __iomem *base;
+	u32 ctrl;
 	u32 freq;
 };

@@ -46,15 +48,20 @@ static inline void __iomem *rk_base(struct
clock_event_device *ce)
 	return rk_timer(ce)->base;
 }

+static inline void __iomem *rk_ctrl(struct clock_event_device *ce)
+{
+	return rk_timer(ce)->base + rk_timer(ce)->ctrl;
+}
+
 static inline void rk_timer_disable(struct clock_event_device *ce)
 {
-	writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_CONTROL_REG);
+	writel_relaxed(TIMER_DISABLE, rk_ctrl(ce));
 }

 static inline void rk_timer_enable(struct clock_event_device *ce, u32
flags)
 {
 	writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags,
-		       rk_base(ce) + TIMER_CONTROL_REG);
+		       rk_ctrl(ce));
 }

 static void rk_timer_update_counter(unsigned long cycles,
@@ -179,4 +186,19 @@ out_unmap:
 	iounmap(bc_timer.base);
 }

-CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init);
+static void __init rk3288_timer_init(struct device_node *np)
+{
+	bc_timer.ctrl = TIMER_CONTROL_REG3288;
+	rk_timer_init(np);
+}
+
+static void __init rk3399_timer_init(struct device_node *np)
+{
+	bc_timer.ctrl = TIMER_CONTROL_REG3399;
+	rk_timer_init(np);
+}
+
+CLOCKSOURCE_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer",
+		       rk3288_timer_init);
+CLOCKSOURCE_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer",
+		       rk3399_timer_init);

This patch will give us a little lager text size. If we do disassemble,
we can see additional LDR is called. I can accept this performance drop.
So we will send new patches.
BTW, the patch "clocksource: rockchip: remove unnecessary clear irq
before request_irq" can drop if we use this patch.

Thanks,
Huang, Tao



From mark.rutland at arm.com  Tue May 31 06:49:00 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 14:49:00 +0100
Subject: [PATCH 0/2] arm64: mm: dump: rework and fix
Message-ID: <1464702542-24394-1-git-send-email-mark.rutland@arm.com>

Hi Will,

Here are a couple of patches for the arm64 pagetable dump code.

The first patch is the final reusable ptdump patch, rebased to v4.7-rc1, as per
your request [1]. Other than the rebase, I have made no changes.

The second patch addresses an ambiguity in the dump output, in that we cannot
determine whether a span of block entries exists at the PGD, PUD, or PMD level.
It's logically unrelated to patch 1, and the two should apply independently,
but I've put them in a series so that I can call that out, and to avoid the
inevitable confusion with patches that appear to intersect.

I've given them both a spin on Juno R1 with v4.7-rc1 defconfig, fiddling with
the page size and number of levels. So far everything seems to work as
expected.

Thanks,
Mark.

[1] http://lkml.kernel.org/r/20160531132508.GJ24936 at arm.com

Mark Rutland (2):
  arm64: mm: dump: make page table dumping reusable
  arm64: mm: dump: log span level

 arch/arm64/include/asm/ptdump.h | 44 +++++++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/dump.c            | 40 +++++++++++++++++++++++++------------
 2 files changed, 71 insertions(+), 13 deletions(-)
 create mode 100644 arch/arm64/include/asm/ptdump.h

-- 
1.9.1



From mark.rutland at arm.com  Tue May 31 06:49:02 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 14:49:02 +0100
Subject: [PATCH 2/2] arm64: mm: dump: log span level
In-Reply-To: <1464702542-24394-1-git-send-email-mark.rutland@arm.com>
References: <1464702542-24394-1-git-send-email-mark.rutland@arm.com>
Message-ID: <1464702542-24394-3-git-send-email-mark.rutland@arm.com>

The page table dump code logs spans of entries at the same level
(pgd/pud/pmd/pte) which have the same attributes. While we log the
(decoded) attributes, we don't log the level, which leaves the output
ambiguous and/or confusing in some cases.

For example:

0xffff800800000000-0xffff800980000000           6G       RW NX SHD AF        BLK UXN MEM/NORMAL

If using 4K pages, this may describe a span of 6 1G block entries at the
PGD/PUD level, or 3072 2M block entries at the PMD level.

This patch adds the page table level to each output line, removing this
ambiguity. For the example above, this will produce:

0xffffffc800000000-0xffffffc980000000           6G PUD       RW NX SHD AF        BLK UXN MEM/NORMAL

When 3 level tables are in use, and we use the asm-generic/nopud.h
definitions, the dump code treats each entry in the PGD as a 1 element
table at the PUD level, and logs spans as being PUDs, which can be
confusing. To counteract this, the "PUD" mnemonic is replaced with "PGD"
when CONFIG_PGTABLE_LEVELS <= 3. Likewise for "PMD" when
CONFIG_PGTABLE_LEVELS <= 2.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Huang Shijie <shijie.huang at arm.com>
Cc: Laura Abbott <labbott at fedoraproject.org>
Cc: Steve Capper <steve.capper at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
---
 arch/arm64/mm/dump.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
index a56a7ad..f94b80e 100644
--- a/arch/arm64/mm/dump.c
+++ b/arch/arm64/mm/dump.c
@@ -146,6 +146,7 @@ static const struct prot_bits pte_bits[] = {
 
 struct pg_level {
 	const struct prot_bits *bits;
+	const char *name;
 	size_t num;
 	u64 mask;
 };
@@ -153,15 +154,19 @@ struct pg_level {
 static struct pg_level pg_level[] = {
 	{
 	}, { /* pgd */
+		.name	= "PGD",
 		.bits	= pte_bits,
 		.num	= ARRAY_SIZE(pte_bits),
 	}, { /* pud */
+		.name	= (CONFIG_PGTABLE_LEVELS > 3) ? "PUD" : "PGD",
 		.bits	= pte_bits,
 		.num	= ARRAY_SIZE(pte_bits),
 	}, { /* pmd */
+		.name	= (CONFIG_PGTABLE_LEVELS > 2) ? "PMD" : "PGD",
 		.bits	= pte_bits,
 		.num	= ARRAY_SIZE(pte_bits),
 	}, { /* pte */
+		.name	= "PTE",
 		.bits	= pte_bits,
 		.num	= ARRAY_SIZE(pte_bits),
 	},
@@ -210,7 +215,8 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
 				delta >>= 10;
 				unit++;
 			}
-			seq_printf(st->seq, "%9lu%c", delta, *unit);
+			seq_printf(st->seq, "%9lu%c %s", delta, *unit,
+				   pg_level[st->level].name);
 			if (pg_level[st->level].bits)
 				dump_prot(st, pg_level[st->level].bits,
 					  pg_level[st->level].num);
-- 
1.9.1



From mark.rutland at arm.com  Tue May 31 06:49:01 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 14:49:01 +0100
Subject: [PATCH 1/2] arm64: mm: dump: make page table dumping reusable
In-Reply-To: <1464702542-24394-1-git-send-email-mark.rutland@arm.com>
References: <1464702542-24394-1-git-send-email-mark.rutland@arm.com>
Message-ID: <1464702542-24394-2-git-send-email-mark.rutland@arm.com>

For debugging purposes, it would be nice if we could export page tables
other than the swapper_pg_dir to userspace. To enable this, this patch
refactors the arm64 page table dumping code such that multiple tables
may be registered with the framework, and exported under debugfs.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Laura Abbott <labbott at fedoraproject.org>
Cc: Will Deacon <will.deacon at arm.com>
---
 arch/arm64/include/asm/ptdump.h | 44 +++++++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/dump.c            | 32 +++++++++++++++++++-----------
 2 files changed, 64 insertions(+), 12 deletions(-)
 create mode 100644 arch/arm64/include/asm/ptdump.h

diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
new file mode 100644
index 0000000..07b8ed0
--- /dev/null
+++ b/arch/arm64/include/asm/ptdump.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PTDUMP_H
+#define __ASM_PTDUMP_H
+
+#ifdef CONFIG_ARM64_PTDUMP
+
+#include <linux/mm_types.h>
+
+struct addr_marker {
+	unsigned long start_address;
+	char *name;
+};
+
+struct ptdump_info {
+	struct mm_struct		*mm;
+	const struct addr_marker	*markers;
+	unsigned long			base_addr;
+	unsigned long			max_addr;
+};
+
+int ptdump_register(struct ptdump_info *info, const char *name);
+
+#else
+static inline int ptdump_register(struct ptdump_info *info, const char *name)
+{
+	return 0;
+}
+#endif /* CONFIG_ARM64_PTDUMP */
+
+#endif /* __ASM_PTDUMP_H */
diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
index 8404190..a56a7ad 100644
--- a/arch/arm64/mm/dump.c
+++ b/arch/arm64/mm/dump.c
@@ -27,11 +27,7 @@
 #include <asm/memory.h>
 #include <asm/pgtable.h>
 #include <asm/pgtable-hwdef.h>
-
-struct addr_marker {
-	unsigned long start_address;
-	const char *name;
-};
+#include <asm/ptdump.h>
 
 static const struct addr_marker address_markers[] = {
 #ifdef CONFIG_KASAN
@@ -284,7 +280,8 @@ static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
 	}
 }
 
-static void walk_pgd(struct pg_state *st, struct mm_struct *mm, unsigned long start)
+static void walk_pgd(struct pg_state *st, struct mm_struct *mm,
+		     unsigned long start)
 {
 	pgd_t *pgd = pgd_offset(mm, 0UL);
 	unsigned i;
@@ -303,12 +300,13 @@ static void walk_pgd(struct pg_state *st, struct mm_struct *mm, unsigned long st
 
 static int ptdump_show(struct seq_file *m, void *v)
 {
+	struct ptdump_info *info = m->private;
 	struct pg_state st = {
 		.seq = m,
-		.marker = address_markers,
+		.marker = info->markers,
 	};
 
-	walk_pgd(&st, &init_mm, VA_START);
+	walk_pgd(&st, info->mm, info->base_addr);
 
 	note_page(&st, 0, 0, 0);
 	return 0;
@@ -316,7 +314,7 @@ static int ptdump_show(struct seq_file *m, void *v)
 
 static int ptdump_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ptdump_show, NULL);
+	return single_open(file, ptdump_show, inode->i_private);
 }
 
 static const struct file_operations ptdump_fops = {
@@ -326,7 +324,7 @@ static const struct file_operations ptdump_fops = {
 	.release	= single_release,
 };
 
-static int ptdump_init(void)
+int ptdump_register(struct ptdump_info *info, const char *name)
 {
 	struct dentry *pe;
 	unsigned i, j;
@@ -336,8 +334,18 @@ static int ptdump_init(void)
 			for (j = 0; j < pg_level[i].num; j++)
 				pg_level[i].mask |= pg_level[i].bits[j].mask;
 
-	pe = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL,
-				 &ptdump_fops);
+	pe = debugfs_create_file(name, 0400, NULL, info, &ptdump_fops);
 	return pe ? 0 : -ENOMEM;
 }
+
+static struct ptdump_info kernel_ptdump_info = {
+	.mm		= &init_mm,
+	.markers	= address_markers,
+	.base_addr	= VA_START,
+};
+
+static int ptdump_init(void)
+{
+	return ptdump_register(&kernel_ptdump_info, "kernel_page_tables");
+}
 device_initcall(ptdump_init);
-- 
1.9.1



From will.deacon at arm.com  Tue May 31 06:52:52 2016
From: will.deacon at arm.com (Will Deacon)
Date: Tue, 31 May 2016 14:52:52 +0100
Subject: Possible race between PTRACE_SETVFPREGS and PTRACE_CONT on ARM?
In-Reply-To: <20160530224028.GT19428@n2100.arm.linux.org.uk>
References: <574C7CDB.7050103@ericsson.com>
 <20160530213529.GS19428@n2100.arm.linux.org.uk>
 <20160530224028.GT19428@n2100.arm.linux.org.uk>
Message-ID: <20160531135251.GK24936@arm.com>

On Mon, May 30, 2016 at 11:40:28PM +0100, Russell King - ARM Linux wrote:
> On Mon, May 30, 2016 at 10:35:29PM +0100, Russell King - ARM Linux wrote:
> > With that, on a single CPU, it seems to work correctly every time, but
> > if I bring up a secondary CPU I start seeing the same problems you've
> > reported - which seems to need the following patch to solve.  Please can
> > you check whether this resolves your problem?
> 
> More background behind this patch... I think that commit 8130b9d7b9d8
> ("ARM: 7308/1: vfp: flush thread hwstate before copying ptrace registers")
> was wrong.
> 
> Let's look at what's happening.  The above commit had the following effect:
> 
> 	vfp_sync_hwstate();
> 	new_vfp = thread->vfpstate.hard;
> 	modify new_vfp (but not new_vfp.cpu)
> +	vfp_flush_hwstate(thread);
> 	thread->vfpstate.hard = new_vfp;
> -	vfp_flush_hwstate(thread);
> 
> Now, the commit above claims that a context switch mid-copy of new_vfp
> into thread->vfpstate.hard may result in corrupted state.
> 
> I'm not quite sure how we could get to that point: the only thread which
> is allowed to touch the traced child's state is the ptracing parent, and
> the ptracing parent can't do anything until after vfp_set() has returned.
> Even if the traced child gets a fatal signal, the point at which the
> signal is delivered to the child is when returning to userspace, which
> means the child must be runnable.  That in turn means that we are not
> in the middle of changing the register state.
> 
> So, I'm not sure where Will got the idea that the partially copied state
> would be visible: it shouldn't ever be visible.  If it is visible, then
> we've got problems even with Will's patch applied, because a partial
> copy whenever it happens would be visible.
> 
> In any case, the above change is wrong: vfp_flush_hwstate() sets
> thread->vfpstate.hard.cpu to an invalid CPU number.  Switching the order
> as Will has done _undoes_ the effect of vfp_flush_hwstate(), which leads
> to the bug you are seeing.
> 
> So, I think the correct approach is to revert it.

Yes, it looks like I was over-zealous in fixing all users of
vfp_flush_hwstate after I fixed the signal handling code. Given that the
child isn't runnable until the parent has finished poking at the register
state, the original code looks fine.

The only thing I'm uncertain of is whether or not PTRACE_SEIZE/PTRACE_LISTEN
allow switching to the child (but even then, how is the parent doing
to issue such a request?).

Will


From will.deacon at arm.com  Tue May 31 06:57:41 2016
From: will.deacon at arm.com (Will Deacon)
Date: Tue, 31 May 2016 14:57:41 +0100
Subject: [PATCH] arm64: defconfig: add options for virtualization and
 containers
In-Reply-To: <1464345747-11729-1-git-send-email-riku.voipio@linaro.org>
References: <1464345747-11729-1-git-send-email-riku.voipio@linaro.org>
Message-ID: <20160531135740.GL24936@arm.com>

On Fri, May 27, 2016 at 01:42:27PM +0300, Riku Voipio wrote:
> Enable options commonly needed by popular virtualization
> and container applications. Use modules when possible to
> avoid too much overhead for users not interested.
> 
> - add namespace and cgroup options needed
> - add seccomp - optional, but enhances Qemu etc
> - bridge, nat, veth, macvtap and multicast for routing
>   guests and containers
> - btfrs and overlayfs modules for container COW backends
> - while near it, make fuse a module instead of built-in.
> 
> Generated with make saveconfig and dropping unrelated spurious
> change hunks while commiting. bloat-o-meter old-vmlinux vmlinux:
> 
> add/remove: 899/388 grow/shrink: 744/216 up/down: 183556/-94881 (88675)
> ...
> Total: Before=10515333, After=10604008, chg 0.000000%
> 
> Signed-off-by: Riku Voipio <riku.voipio at linaro.org>
> ---
>  arch/arm64/configs/defconfig | 53 +++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 47 insertions(+), 6 deletions(-)

I'm fine with adding stuff to defconfig if it's useful to people (and it
looks like this is), but it's probably about time we figured out what to
do about '=y' vs '=m'. Until recently (i.e. this merge window), the arm64
defconfig didn't build any modules. Obviously this only scales so far,
since the Image tends to get rather huge, but it would be good to try and
establish a rule-of-thumb as to whether we treat something as a module
or a built-in. We could even consider retrospectively applying the rule
if its straightforward enough.

One easy way to do it would be: if you need the option to boot, then
it's a built-in, but that brings up questions around "boot a full android
system" vs "boot to a point where you could load an initrd".

Any ideas? Am I mad trying to put method into madness?

Will


From daniel.lezcano at linaro.org  Tue May 31 07:06:30 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Tue, 31 May 2016 16:06:30 +0200
Subject: [PATCH 4/5] clocksource: rockchip: add support for rk3399 SoC
In-Reply-To: <574D95AF.2020905@rock-chips.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
 <1464169802-6033-5-git-send-email-wxt@rock-chips.com>
 <574CCCB4.1030001@linaro.org> <574D95AF.2020905@rock-chips.com>
Message-ID: <574D9A66.4090209@linaro.org>

On 05/31/2016 03:46 PM, Huang, Tao wrote:
> Hi Daniel:
> On 2016?05?31? 07:28, Daniel Lezcano wrote:
>> On 05/25/2016 11:50 AM, Caesar Wang wrote:
>>> From: Huang Tao <huangtao at rock-chips.com>
>>>
>>> The CONTROL register offset is different from old SoCs.
>>> For Linux driver, there are not functional changes at all.
>>> Let's call it v2.
>>>
>>> Signed-off-by: Huang Tao <huangtao at rock-chips.com>
>>> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
>>> Cc: Thomas Gleixner <tglx at linutronix.de>
>>> Cc: Heiko Stuebner <heiko at sntech.de>
>>> Tested-by: Jianqun Xu <jay.xu at rock-chips.com>
>>> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>>> ---
>>
>> That's hackish.
> Yes:( I blamed our IC guy.
>>
>> Please consider something like:
>>
>> diff --git a/drivers/clocksource/rockchip_timer.c
>> b/drivers/clocksource/rockchip_timer.c
>> index b991b28..b6ba6f9 100644
>> --- a/drivers/clocksource/rockchip_timer.c
>> +++ b/drivers/clocksource/rockchip_timer.c
>> @@ -19,7 +19,8 @@
>>
>>    #define TIMER_LOAD_COUNT0	0x00
>>    #define TIMER_LOAD_COUNT1	0x04
>> -#define TIMER_CONTROL_REG	0x10
>> +#define TIMER_CONTROL_REG3288	0x10
>> +#define TIMER_CONTROL_REG3399	0x1C
>>    #define TIMER_INT_STATUS	0x18
>>
>>    #define TIMER_DISABLE		0x0
>> @@ -31,6 +32,7 @@
>>    struct bc_timer {
>>    	struct clock_event_device ce;
>>    	void __iomem *base;
>> +	void __iomem *ctrl;
>>    	u32 freq;
>>    };
>>
>> @@ -46,15 +48,20 @@ static inline void __iomem *rk_base(struct
>> clock_event_device *ce)
>>    	return rk_timer(ce)->base;
>>    }
>>
>> +static inline void __iomem *rk_ctrl(struct clock_event_device *ce)
>> +{
>> +        return rk_timer(ce)->ctrl;
>> +}
>> +
>>    static inline void rk_timer_disable(struct clock_event_device *ce)
>>    {
>> -	writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_CONTROL_REG);
>> +	writel_relaxed(TIMER_DISABLE, rk_ctrl(ce));
>>    }
>>
>>    static inline void rk_timer_enable(struct clock_event_device *ce, u32
>> flags)
>>    {
>>    	writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags,
>> -		       rk_base(ce) + TIMER_CONTROL_REG);
>> +		       rk_ctrl(ce));
>>    }
>>
>>    static void rk_timer_update_counter(unsigned long cycles,
>> @@ -179,4 +186,18 @@ out_unmap:
>>    	iounmap(bc_timer.base);
>>    }
>>
>> -CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init);
>> +static void __init rk3288_timer_init(struct device_node *np)
>> +{
>> +	bc_timer.ctrl = TIMER_CONTROL_REG3288;
>> +	rk_timer_init(np);
>> +}
>> +
>> +static void __init rk3399_timer_init(struct device_node *np)
>> +{
>> +        bc_timer.ctrl = TIMER_CONTROL_REG3399;
>> +	rk_timer_init(np);
>> +}
>> +
>> +
>> +CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer",
>> rk3288_timer_init);
>> +CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3399-timer",
>> rk3399_timer_init);
>>
>>
>
> I think you mean this patch otherwise compile will fail:
> @@ -19,7 +19,8 @@
>
>   #define TIMER_LOAD_COUNT0	0x00
>   #define TIMER_LOAD_COUNT1	0x04
> -#define TIMER_CONTROL_REG	0x10
> +#define TIMER_CONTROL_REG3288	0x10
> +#define TIMER_CONTROL_REG3399	0x1C
>   #define TIMER_INT_STATUS	0x18
>
>   #define TIMER_DISABLE		0x0
> @@ -31,6 +32,7 @@
>   struct bc_timer {
>   	struct clock_event_device ce;
>   	void __iomem *base;
> +	u32 ctrl;
>   	u32 freq;
>   };
>
> @@ -46,15 +48,20 @@ static inline void __iomem *rk_base(struct
> clock_event_device *ce)
>   	return rk_timer(ce)->base;
>   }
>
> +static inline void __iomem *rk_ctrl(struct clock_event_device *ce)
> +{
> +	return rk_timer(ce)->base + rk_timer(ce)->ctrl;

You can do a small optimization by pre-computing 'ctrl' at init time, so 
no need to do this addition each time.

> +}
> +
>   static inline void rk_timer_disable(struct clock_event_device *ce)
>   {
> -	writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_CONTROL_REG);
> +	writel_relaxed(TIMER_DISABLE, rk_ctrl(ce));
>   }
>
>   static inline void rk_timer_enable(struct clock_event_device *ce, u32
> flags)
>   {
>   	writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags,
> -		       rk_base(ce) + TIMER_CONTROL_REG);
> +		       rk_ctrl(ce));
>   }
>
>   static void rk_timer_update_counter(unsigned long cycles,
> @@ -179,4 +186,19 @@ out_unmap:
>   	iounmap(bc_timer.base);
>   }
>
> -CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init);
> +static void __init rk3288_timer_init(struct device_node *np)
> +{
> +	bc_timer.ctrl = TIMER_CONTROL_REG3288;
> +	rk_timer_init(np);

	rk_timer_init(np);
	bc_timer.ctrl = bc_timer.base + TIMER_CONTROL_REG3288;

> +}
> +
> +static void __init rk3399_timer_init(struct device_node *np)
> +{
> +	bc_timer.ctrl = TIMER_CONTROL_REG3399;
> +	rk_timer_init(np);

	rk_timer_init(np);
	bc_timer.ctrl = bc_timer.base + TIMER_CONTROL_REG3399;

> +}
> +
> +CLOCKSOURCE_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer",
> +		       rk3288_timer_init);
> +CLOCKSOURCE_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer",
> +		       rk3399_timer_init);
>
> This patch will give us a little lager text size. If we do disassemble,
> we can see additional LDR is called. I can accept this performance drop.
> So we will send new patches.
> BTW, the patch "clocksource: rockchip: remove unnecessary clear irq
> before request_irq" can drop if we use this patch.


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

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



From christoffer.dall at linaro.org  Tue May 31 07:14:14 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 31 May 2016 16:14:14 +0200
Subject: [PATCH v2 0/7] vgic fixes for 4.7-rc1
In-Reply-To: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
References: <1464186399-16604-1-git-send-email-marc.zyngier@arm.com>
Message-ID: <20160531141414.GB12568@cbox>

On Wed, May 25, 2016 at 03:26:32PM +0100, Marc Zyngier wrote:
> The dust has not yet settled on the new vgic, but here's the first
> batch of fixes anyway!
> 
> The first two patches are courtesy of Christoffer, who noticed that we
> fail to clear LRs that generate a maintenance interrupt, leading to
> potential screaming interrupts. This bug already exists in the current
> mainline (cc stable?)
> 
> The next two address a bug where we fail to properly resample the line
> level on exit, which could result in spurious interrupts being
> injected. This is specific to the new vgic implementation.
> 
> The following two patches tighten our GICv3 emulation by preventing
> the guest from changing the SRE setting. This bug already exists in
> mainline, though it is hardly critical.
> 
> The last patch is actually a performance optimization: if the guest is
> using GICv3, we can drop a number of barriers (since we don't need to
> change SRE, and there is no memory-mapped view to synchronize
> with). This results in a world switch that is 2.5% faster on my LS2085
> box when running GICv3 guests. I suspect that the bigger the box, the
> bigger this impact this change will have (system-wide DSBs don't really
> come cheap).
> 
> These patches have been tested on top of the kvmarm/next branch.
> 

Thanks, applied to queue (with cc stable for v4.6+ as I only think this
applies post our optimizations that went in for v4.6)

-Christoffer


From robert.moore at intel.com  Tue May 31 07:16:07 2016
From: robert.moore at intel.com (Moore, Robert)
Date: Tue, 31 May 2016 14:16:07 +0000
Subject: [PATCH] Add support to parse RASF Table
In-Reply-To: <TU4PR84MB004598D95417F3C00FC6BFC7D9460@TU4PR84MB0045.NAMPRD84.PROD.OUTLOOK.COM>
References: <1462796276-3987-1-git-send-email-nagendra.k-v@hpe.com>
 <TU4PR84MB0079FF2412932840DBE794C0C2770@TU4PR84MB0079.NAMPRD84.PROD.OUTLOOK.COM>
 <TU4PR84MB004598D95417F3C00FC6BFC7D9460@TU4PR84MB0045.NAMPRD84.PROD.OUTLOOK.COM>
Message-ID: <94F2FBAB4432B54E8AACC7DFDE6C92E37E488955@ORSMSX110.amr.corp.intel.com>

Sorry for the delay.
Yes, this looks like we can take this.
Bob


> -----Original Message-----
> From: Sajjan, Vikas C [mailto:vikas.cha.sajjan at hpe.com]
> Sent: Monday, May 30, 2016 9:57 PM
> To: Moore, Robert
> Cc: Lakshminarasimha, Sunil Vishwanathpur; rjw at rjwysocki.net;
> devel at acpica.org; linux-acpi at vger.kernel.org; K V, Nagendra; linaro-
> acpi at lists.linaro.org; linux-arm-kernel at lists.infradead.org
> Subject: RE: [PATCH] Add support to parse RASF Table
> 
> Hi Bob,
> 
> Any thoughts on this patch
> 
> Regards
> Vikas Sajjan
> 
> -----Original Message-----
> From: K V, Nagendra
> Sent: Monday, May 16, 2016 2:05 PM
> To: robert.moore at intel.com
> Cc: Sajjan, Vikas C <vikas.cha.sajjan at hpe.com>; Lakshminarasimha, Sunil
> Vishwanathpur <sunil.vl at hpe.com>; devel at acpica.org; linux-
> acpi at vger.kernel.org
> Subject: RE: [PATCH] Add support to parse RASF Table
> 
> Bob,
> 
> Did you get chance to look into this?
> 
> Regards
> Nagendra
> 
> -----Original Message-----
> From: K V, Nagendra
> Sent: Monday, May 09, 2016 5:48 PM
> To: robert.moore at intel.com
> Cc: Sajjan, Vikas C <vikas.cha.sajjan at hpe.com>; Lakshminarasimha, Sunil
> Vishwanathpur <sunil.vl at hpe.com>; devel at acpica.org; K V, Nagendra
> <nagendra.k-v at hpe.com>
> Subject: [PATCH] Add support to parse RASF Table
> 
> This patch adds support to parse RASF table. Currently RASF table is not
> being recognized.
> ---
>  source/common/ahtable.c      |  1 +
>  source/common/dmtable.c      |  7 +++++++
>  source/common/dmtbinfo.c     | 13 +++++++++++++
>  source/compiler/dtcompiler.h |  1 +
>  source/compiler/dttemplate.h | 11 +++++++++++
>  source/compiler/dtutils.c    |  5 +++++
>  source/include/acdisasm.h    |  2 ++
>  7 files changed, 40 insertions(+)
> 
> diff --git a/source/common/ahtable.c b/source/common/ahtable.c index
> 021ae33..59ddc83 100644
> --- a/source/common/ahtable.c
> +++ b/source/common/ahtable.c
> @@ -196,6 +196,7 @@ const AH_TABLE      AcpiSupportedTables[] =
>      {ACPI_SIG_NFIT, "NVDIMM Firmware Interface Table"},
>      {ACPI_SIG_PCCT, "Platform Communications Channel Table"},
>      {ACPI_SIG_PMTT, "Platform Memory Topology Table"},
> +    {ACPI_SIG_RASF, "RAS Features Table"},
>      {ACPI_RSDP_NAME,"Root System Description Pointer"},
>      {ACPI_SIG_RSDT, "Root System Description Table"},
>      {ACPI_SIG_S3PT, "S3 Performance Table"}, diff --git
> a/source/common/dmtable.c b/source/common/dmtable.c index 51d91f8..321407c
> 100644
> --- a/source/common/dmtable.c
> +++ b/source/common/dmtable.c
> @@ -430,6 +430,7 @@ const ACPI_DMTABLE_DATA     AcpiDmTableData[] =
>      {ACPI_SIG_NFIT, AcpiDmTableInfoNfit,    AcpiDmDumpNfit,
> DtCompileNfit,  TemplateNfit},
>      {ACPI_SIG_PCCT, AcpiDmTableInfoPcct,    AcpiDmDumpPcct,
> DtCompilePcct,  TemplatePcct},
>      {ACPI_SIG_PMTT, NULL,                   AcpiDmDumpPmtt,
> DtCompilePmtt,  TemplatePmtt},
> +    {ACPI_SIG_RASF, AcpiDmTableInfoRasf,    NULL,           NULL,
> TemplateRasf},
>      {ACPI_SIG_RSDT, NULL,                   AcpiDmDumpRsdt,
> DtCompileRsdt,  TemplateRsdt},
>      {ACPI_SIG_S3PT, NULL,                   NULL,           NULL,
> TemplateS3pt},
>      {ACPI_SIG_SBST, AcpiDmTableInfoSbst,    NULL,           NULL,
> TemplateSbst},
> @@ -916,6 +917,11 @@ AcpiDmDumpTable (
>              ByteLength = 10;
>              break;
> 
> +        case ACPI_DMT_RASF:
> +
> +            ByteLength = 12;
> +            break;
> +
>          case ACPI_DMT_BUF16:
>          case ACPI_DMT_UUID:
> 
> @@ -1048,6 +1054,7 @@ AcpiDmDumpTable (
> 
>          /* Integer Data Types */
> 
> +        case ACPI_DMT_RASF:
>          case ACPI_DMT_UINT8:
>          case ACPI_DMT_UINT16:
>          case ACPI_DMT_UINT24:
> diff --git a/source/common/dmtbinfo.c b/source/common/dmtbinfo.c index
> 5520da2..3896b69 100644
> --- a/source/common/dmtbinfo.c
> +++ b/source/common/dmtbinfo.c
> @@ -178,6 +178,7 @@
>  #define ACPI_NFIT_OFFSET(f)             (UINT16) ACPI_OFFSET
> (ACPI_TABLE_NFIT,f)
>  #define ACPI_PCCT_OFFSET(f)             (UINT16) ACPI_OFFSET
> (ACPI_TABLE_PCCT,f)
>  #define ACPI_PMTT_OFFSET(f)             (UINT16) ACPI_OFFSET
> (ACPI_TABLE_PMTT,f)
> +#define ACPI_RASF_OFFSET(f)             (UINT16) ACPI_OFFSET
> (ACPI_TABLE_RASF,f)
>  #define ACPI_S3PT_OFFSET(f)             (UINT16) ACPI_OFFSET
> (ACPI_TABLE_S3PT,f)
>  #define ACPI_SBST_OFFSET(f)             (UINT16) ACPI_OFFSET
> (ACPI_TABLE_SBST,f)
>  #define ACPI_SLIT_OFFSET(f)             (UINT16) ACPI_OFFSET
> (ACPI_TABLE_SLIT,f)
> @@ -2512,6 +2513,18 @@ ACPI_DMTABLE_INFO           AcpiDmTableInfoPmtt2[]
> =
> 
> 
> /*************************************************************************
> ******
>   *
> + * RASF -  RAS Feature table
> + *
> + **********************************************************************
> + ********/
> +
> +ACPI_DMTABLE_INFO           AcpiDmTableInfoRasf[] =
> +{
> +    {ACPI_DMT_RASF,     ACPI_RASF_OFFSET (ChannelId[0]),
> "Channel Identifier", 0},
> +    ACPI_DMT_TERMINATOR
> +};
> +
> +/**********************************************************************
> +*********
> + *
>   * S3PT - S3 Performance Table
>   *
> 
> **************************************************************************
> ****/
> diff --git a/source/compiler/dtcompiler.h b/source/compiler/dtcompiler.h
> index eb85ddc..1072f52 100644
> --- a/source/compiler/dtcompiler.h
> +++ b/source/compiler/dtcompiler.h
> @@ -681,6 +681,7 @@ extern const unsigned char  TemplateMtmr[];  extern
> const unsigned char  TemplateNfit[];  extern const unsigned char
> TemplatePcct[];  extern const unsigned char  TemplatePmtt[];
> +extern const unsigned char  TemplateRasf[];
>  extern const unsigned char  TemplateRsdt[];  extern const unsigned char
> TemplateS3pt[];  extern const unsigned char  TemplateSbst[]; diff --git
> a/source/compiler/dttemplate.h b/source/compiler/dttemplate.h index
> e420ec4..d17b2af 100644
> --- a/source/compiler/dttemplate.h
> +++ b/source/compiler/dttemplate.h
> @@ -978,6 +978,17 @@ const unsigned char TemplatePmtt[] =
>      0x00,0x00,0x00,0x00                       /* 000000B0    "...."
> */
>  };
> 
> +const unsigned char TemplateRasf[] =
> +{
> +    0x42,0x45,0x52,0x54,0x30,0x00,0x00,0x00,  /* 00000000    "RASF0..."
> */
> +    0x01,0x15,0x49,0x4E,0x54,0x45,0x4C,0x20,  /* 00000008    "..INTEL "
> */
> +    0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45,  /* 00000010    "TEMPLATE"
> */
> +    0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL"
> */
> +    0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00,  /* 00000020    "(.. ...."
> */
> +    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000028    "........"
> */
> +    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00   /* 00000030    "........"
> */
> +};
> +
>  const unsigned char TemplateRsdp[] =
>  {
>      0x52,0x53,0x44,0x20,0x50,0x54,0x52,0x20,  /* 00000000    "RSD PTR "
> */
> diff --git a/source/compiler/dtutils.c b/source/compiler/dtutils.c index
> 6ca418c..774db8b 100644
> --- a/source/compiler/dtutils.c
> +++ b/source/compiler/dtutils.c
> @@ -688,6 +688,11 @@ DtGetFieldLength (
>          ByteLength = 10;
>          break;
> 
> +    case ACPI_DMT_RASF:
> +
> +        ByteLength = 12;
> +        break;
> +
>      case ACPI_DMT_BUF16:
>      case ACPI_DMT_UUID:
> 
> diff --git a/source/include/acdisasm.h b/source/include/acdisasm.h index
> ba8f274..d59e4d9 100644
> --- a/source/include/acdisasm.h
> +++ b/source/include/acdisasm.h
> @@ -227,6 +227,7 @@ typedef enum
>      ACPI_DMT_NFIT,
>      ACPI_DMT_PCCT,
>      ACPI_DMT_PMTT,
> +    ACPI_DMT_RASF,
>      ACPI_DMT_SLIC,
>      ACPI_DMT_SRAT,
> 
> @@ -458,6 +459,7 @@ extern ACPI_DMTABLE_INFO
> AcpiDmTableInfoPcctHdr[];
>  extern ACPI_DMTABLE_INFO        AcpiDmTableInfoPcct0[];
>  extern ACPI_DMTABLE_INFO        AcpiDmTableInfoPcct1[];
>  extern ACPI_DMTABLE_INFO        AcpiDmTableInfoPcct2[];
> +extern ACPI_DMTABLE_INFO        AcpiDmTableInfoRasf[];
>  extern ACPI_DMTABLE_INFO        AcpiDmTableInfoRsdp1[];
>  extern ACPI_DMTABLE_INFO        AcpiDmTableInfoRsdp2[];
>  extern ACPI_DMTABLE_INFO        AcpiDmTableInfoS3pt[];
> --
> 2.5.0
> 



From linux at armlinux.org.uk  Tue May 31 07:18:17 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Tue, 31 May 2016 15:18:17 +0100
Subject: Possible race between PTRACE_SETVFPREGS and PTRACE_CONT on ARM?
In-Reply-To: <20160531135251.GK24936@arm.com>
References: <574C7CDB.7050103@ericsson.com>
 <20160530213529.GS19428@n2100.arm.linux.org.uk>
 <20160530224028.GT19428@n2100.arm.linux.org.uk>
 <20160531135251.GK24936@arm.com>
Message-ID: <20160531141817.GW19428@n2100.arm.linux.org.uk>

On Tue, May 31, 2016 at 02:52:52PM +0100, Will Deacon wrote:
> The only thing I'm uncertain of is whether or not PTRACE_SEIZE/PTRACE_LISTEN
> allow switching to the child (but even then, how is the parent doing
> to issue such a request?).

I can't see how that would be possible - the parent needs to finish
the vfp_set() call before it can issue any others - and there can
only be one tracer.  IOW, if we're in vfp_set(), the thread must
have attached to the child, at which point PTRACE_SEIZE will be
rejected.

PTRACE_LISTEN also requires the child to be in STOP state as well, and
again, can only be issued from the current tracer.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From k.kozlowski at samsung.com  Tue May 31 07:19:32 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 16:19:32 +0200
Subject: [RFT PATCH 2/2] serial: pnx8xxx: Fix coding style
In-Reply-To: <1464704372-17668-1-git-send-email-k.kozlowski@samsung.com>
References: <1464704372-17668-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <1464704372-17668-2-git-send-email-k.kozlowski@samsung.com>

Definition of function should start from new line.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
---
 drivers/tty/serial/pnx8xxx_uart.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/pnx8xxx_uart.c b/drivers/tty/serial/pnx8xxx_uart.c
index 84c4efdde8dc..9eaedd6a049e 100644
--- a/drivers/tty/serial/pnx8xxx_uart.c
+++ b/drivers/tty/serial/pnx8xxx_uart.c
@@ -690,7 +690,8 @@ static void pnx8xxx_console_putchar(struct uart_port *port, int ch)
 
 /*
  * Interrupts are disabled on entering
- */static void
+ */
+static void
 pnx8xxx_console_write(struct console *co, const char *s, unsigned int count)
 {
 	struct pnx8xxx_port *sport = &pnx8xxx_ports[co->index];
-- 
1.9.1



From k.kozlowski at samsung.com  Tue May 31 07:19:31 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 16:19:31 +0200
Subject: [RFT PATCH 1/2] serial: Fix console setup section mismatch
Message-ID: <1464704372-17668-1-git-send-email-k.kozlowski@samsung.com>

Remove __init annotation from all of console->setup implementations
because:
1. The pointer to it is stored in a struct console which is not
   marked with __initdata.
2. It is referenced by register_console() from kernel which is not
   marked with __init.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>

---

Drivers only build tested (and maybe some of them not built at all).
---
 drivers/tty/serial/21285.c           |  7 +++----
 drivers/tty/serial/altera_jtaguart.c |  2 +-
 drivers/tty/serial/altera_uart.c     |  2 +-
 drivers/tty/serial/amba-pl010.c      |  7 +++----
 drivers/tty/serial/amba-pl011.c      |  7 +++----
 drivers/tty/serial/apbuart.c         |  7 +++----
 drivers/tty/serial/atmel_serial.c    |  4 ++--
 drivers/tty/serial/bfin_sport_uart.c |  3 +--
 drivers/tty/serial/bfin_uart.c       |  8 +++-----
 drivers/tty/serial/dz.c              |  2 +-
 drivers/tty/serial/etraxfs-uart.c    |  3 +--
 drivers/tty/serial/fsl_lpuart.c      | 12 +++++-------
 drivers/tty/serial/imx.c             |  8 +++-----
 drivers/tty/serial/ip22zilog.c       |  2 +-
 drivers/tty/serial/lantiq.c          |  3 +--
 drivers/tty/serial/lpc32xx_hs.c      |  4 ++--
 drivers/tty/serial/m32r_sio.c        |  2 +-
 drivers/tty/serial/mcf.c             |  2 +-
 drivers/tty/serial/mpc52xx_uart.c    |  8 +++-----
 drivers/tty/serial/mpsc.c            |  2 +-
 drivers/tty/serial/msm_serial.c      |  2 +-
 drivers/tty/serial/mxs-auart.c       |  8 +++-----
 drivers/tty/serial/netx-serial.c     |  8 +++-----
 drivers/tty/serial/omap-serial.c     |  3 +--
 drivers/tty/serial/pch_uart.c        |  2 +-
 drivers/tty/serial/pmac_zilog.c      |  2 +-
 drivers/tty/serial/pnx8xxx_uart.c    |  3 +--
 drivers/tty/serial/pxa.c             |  3 +--
 drivers/tty/serial/sa1100.c          |  8 +++-----
 drivers/tty/serial/samsung.c         |  8 +++-----
 drivers/tty/serial/sb1250-duart.c    |  2 +-
 drivers/tty/serial/serial_ks8695.c   |  5 +++--
 drivers/tty/serial/serial_txx9.c     |  2 +-
 drivers/tty/serial/sirfsoc_uart.c    |  3 +--
 drivers/tty/serial/sprd_serial.c     |  2 +-
 drivers/tty/serial/sunsu.c           |  2 +-
 drivers/tty/serial/sunzilog.c        |  2 +-
 drivers/tty/serial/vr41xx_siu.c      |  2 +-
 drivers/tty/serial/vt8500_serial.c   |  2 +-
 drivers/tty/serial/xilinx_uartps.c   |  2 +-
 drivers/tty/serial/zs.c              |  2 +-
 41 files changed, 71 insertions(+), 97 deletions(-)

diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c
index 9b208bd686e6..8af51a451c5e 100644
--- a/drivers/tty/serial/21285.c
+++ b/drivers/tty/serial/21285.c
@@ -381,9 +381,8 @@ serial21285_console_write(struct console *co, const char *s,
 	uart_console_write(&serial21285_port, s, count, serial21285_console_putchar);
 }
 
-static void __init
-serial21285_get_options(struct uart_port *port, int *baud,
-			int *parity, int *bits)
+static void serial21285_get_options(struct uart_port *port, int *baud,
+				    int *parity, int *bits)
 {
 	if (*CSR_UARTCON == 1) {
 		unsigned int tmp;
@@ -417,7 +416,7 @@ serial21285_get_options(struct uart_port *port, int *baud,
 	}
 }
 
-static int __init serial21285_console_setup(struct console *co, char *options)
+static int serial21285_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port = &serial21285_port;
 	int baud = 9600;
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index 32df2a0cb060..a13457a85043 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -348,7 +348,7 @@ static void altera_jtaguart_console_write(struct console *co, const char *s,
 	uart_console_write(port, s, count, altera_jtaguart_console_putc);
 }
 
-static int __init altera_jtaguart_console_setup(struct console *co,
+static int altera_jtaguart_console_setup(struct console *co,
 						char *options)
 {
 	struct uart_port *port;
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 61b607f2488e..64255c4878ed 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -447,7 +447,7 @@ static void altera_uart_console_write(struct console *co, const char *s,
 	uart_console_write(port, s, count, altera_uart_console_putc);
 }
 
-static int __init altera_uart_console_setup(struct console *co, char *options)
+static int altera_uart_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = CONFIG_SERIAL_ALTERA_UART_BAUDRATE;
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index 5d41d5b92619..6e54fb819855 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -620,9 +620,8 @@ pl010_console_write(struct console *co, const char *s, unsigned int count)
 	clk_disable(uap->clk);
 }
 
-static void __init
-pl010_console_get_options(struct uart_amba_port *uap, int *baud,
-			     int *parity, int *bits)
+static void pl010_console_get_options(struct uart_amba_port *uap, int *baud,
+				      int *parity, int *bits)
 {
 	if (readb(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, quot;
@@ -647,7 +646,7 @@ pl010_console_get_options(struct uart_amba_port *uap, int *baud,
 	}
 }
 
-static int __init pl010_console_setup(struct console *co, char *options)
+static int pl010_console_setup(struct console *co, char *options)
 {
 	struct uart_amba_port *uap;
 	int baud = 38400;
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 1b7331e40d79..3aee1bffbbdf 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2203,9 +2203,8 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
 	clk_disable(uap->clk);
 }
 
-static void __init
-pl011_console_get_options(struct uart_amba_port *uap, int *baud,
-			     int *parity, int *bits)
+static void pl011_console_get_options(struct uart_amba_port *uap, int *baud,
+				      int *parity, int *bits)
 {
 	if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) {
 		unsigned int lcr_h, ibrd, fbrd;
@@ -2238,7 +2237,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 	}
 }
 
-static int __init pl011_console_setup(struct console *co, char *options)
+static int pl011_console_setup(struct console *co, char *options)
 {
 	struct uart_amba_port *uap;
 	int baud = 38400;
diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c
index 75eb083b3361..77b7881a8931 100644
--- a/drivers/tty/serial/apbuart.c
+++ b/drivers/tty/serial/apbuart.c
@@ -450,9 +450,8 @@ apbuart_console_write(struct console *co, const char *s, unsigned int count)
 	UART_PUT_CTRL(port, old_cr);
 }
 
-static void __init
-apbuart_console_get_options(struct uart_port *port, int *baud,
-			    int *parity, int *bits)
+static void apbuart_console_get_options(struct uart_port *port, int *baud,
+					int *parity, int *bits)
 {
 	if (UART_GET_CTRL(port) & (UART_CTRL_RE | UART_CTRL_TE)) {
 
@@ -473,7 +472,7 @@ apbuart_console_get_options(struct uart_port *port, int *baud,
 	}
 }
 
-static int __init apbuart_console_setup(struct console *co, char *options)
+static int apbuart_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = 38400;
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 954941dd8124..fa71aac07a8c 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -2410,7 +2410,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
  * If the port was already initialised (eg, by a boot loader),
  * try to determine the current setup.
  */
-static void __init atmel_console_get_options(struct uart_port *port, int *baud,
+static void atmel_console_get_options(struct uart_port *port, int *baud,
 					     int *parity, int *bits)
 {
 	unsigned int mr, quot;
@@ -2444,7 +2444,7 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud,
 	*baud = port->uartclk / (16 * (quot - 1));
 }
 
-static int __init atmel_console_setup(struct console *co, char *options)
+static int atmel_console_setup(struct console *co, char *options)
 {
 	int ret;
 	struct uart_port *port = &atmel_ports[co->index].uart;
diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c
index 984e1c050096..b0407c1bc31d 100644
--- a/drivers/tty/serial/bfin_sport_uart.c
+++ b/drivers/tty/serial/bfin_sport_uart.c
@@ -609,8 +609,7 @@ static struct sport_uart_port *bfin_sport_uart_ports[BFIN_SPORT_UART_MAX_PORTS];
 #ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
 #define CLASS_BFIN_SPORT_CONSOLE	"bfin-sport-console"
 
-static int __init
-sport_uart_console_setup(struct console *co, char *options)
+static int sport_uart_console_setup(struct console *co, char *options)
 {
 	struct sport_uart_port *up;
 	int baud = 57600;
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index 293ecbb00684..42f2dc66adda 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -1035,9 +1035,8 @@ static struct uart_ops bfin_serial_pops = {
  * If the port was already initialised (eg, by a boot loader),
  * try to determine the current setup.
  */
-static void __init
-bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
-			   int *parity, int *bits)
+static void bfin_serial_console_get_options(struct bfin_serial_port *uart,
+					    int *baud, int *parity, int *bits)
 {
 	unsigned int status;
 
@@ -1100,8 +1099,7 @@ bfin_serial_console_write(struct console *co, const char *s, unsigned int count)
 
 }
 
-static int __init
-bfin_serial_console_setup(struct console *co, char *options)
+static int bfin_serial_console_setup(struct console *co, char *options)
 {
 	struct bfin_serial_port *uart;
 	int baud = 57600;
diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c
index c121f16a973f..5d8e67b137ed 100644
--- a/drivers/tty/serial/dz.c
+++ b/drivers/tty/serial/dz.c
@@ -860,7 +860,7 @@ static void dz_console_print(struct console *co,
 	uart_console_write(&dport->port, str, count, dz_console_putchar);
 }
 
-static int __init dz_console_setup(struct console *co, char *options)
+static int dz_console_setup(struct console *co, char *options)
 {
 	struct dz_port *dport = &dz_mux.dport[co->index];
 	struct uart_port *uport = &dport->port;
diff --git a/drivers/tty/serial/etraxfs-uart.c b/drivers/tty/serial/etraxfs-uart.c
index 2f80bc7e44fb..a7eefb3c0a88 100644
--- a/drivers/tty/serial/etraxfs-uart.c
+++ b/drivers/tty/serial/etraxfs-uart.c
@@ -86,8 +86,7 @@ cris_console_write(struct console *co, const char *s, unsigned int count)
 		REG_WR(ser, up->regi_ser, rw_tr_dma_en, old);
 }
 
-static int __init
-cris_console_setup(struct console *co, char *options)
+static int cris_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = 115200;
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 3d790033744e..ce6030dca617 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1597,9 +1597,8 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count)
  * if the port was already initialised (eg, by a boot loader),
  * try to determine the current setup.
  */
-static void __init
-lpuart_console_get_options(struct lpuart_port *sport, int *baud,
-			   int *parity, int *bits)
+static void lpuart_console_get_options(struct lpuart_port *sport, int *baud,
+				       int *parity, int *bits)
 {
 	unsigned char cr, bdh, bdl, brfa;
 	unsigned int sbr, uartclk, baud_raw;
@@ -1646,9 +1645,8 @@ lpuart_console_get_options(struct lpuart_port *sport, int *baud,
 				"from %d to %d\n", baud_raw, *baud);
 }
 
-static void __init
-lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
-			   int *parity, int *bits)
+static void lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
+					 int *parity, int *bits)
 {
 	unsigned long cr, bd;
 	unsigned int sbr, uartclk, baud_raw;
@@ -1689,7 +1687,7 @@ lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
 				"from %d to %d\n", baud_raw, *baud);
 }
 
-static int __init lpuart_console_setup(struct console *co, char *options)
+static int lpuart_console_setup(struct console *co, char *options)
 {
 	struct lpuart_port *sport;
 	int baud = 115200;
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 0df2b1c091ae..0734330ff9c5 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1791,9 +1791,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
  * If the port was already initialised (eg, by a boot loader),
  * try to determine the current setup.
  */
-static void __init
-imx_console_get_options(struct imx_port *sport, int *baud,
-			   int *parity, int *bits)
+static void imx_console_get_options(struct imx_port *sport, int *baud,
+				    int *parity, int *bits)
 {
 
 	if (readl(sport->port.membase + UCR1) & UCR1_UARTEN) {
@@ -1850,8 +1849,7 @@ imx_console_get_options(struct imx_port *sport, int *baud,
 	}
 }
 
-static int __init
-imx_console_setup(struct console *co, char *options)
+static int imx_console_setup(struct console *co, char *options)
 {
 	struct imx_port *sport;
 	int baud = 9600;
diff --git a/drivers/tty/serial/ip22zilog.c b/drivers/tty/serial/ip22zilog.c
index 991e6dce916e..f57c09e9569d 100644
--- a/drivers/tty/serial/ip22zilog.c
+++ b/drivers/tty/serial/ip22zilog.c
@@ -1027,7 +1027,7 @@ ip22zilog_console_write(struct console *con, const char *s, unsigned int count)
 	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
-static int __init ip22zilog_console_setup(struct console *con, char *options)
+static int ip22zilog_console_setup(struct console *con, char *options)
 {
 	struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index];
 	unsigned long flags;
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index b88832e8ee82..2a73fca6a767 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -612,8 +612,7 @@ lqasc_console_write(struct console *co, const char *s, u_int count)
 	spin_unlock_irqrestore(&ltq_asc_lock, flags);
 }
 
-static int __init
-lqasc_console_setup(struct console *co, char *options)
+static int lqasc_console_setup(struct console *co, char *options)
 {
 	struct ltq_uart_port *ltq_port;
 	struct uart_port *port;
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index 7eb04ae71cc8..eea59136b92d 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -160,8 +160,8 @@ static void lpc32xx_hsuart_console_write(struct console *co, const char *s,
 	local_irq_restore(flags);
 }
 
-static int __init lpc32xx_hsuart_console_setup(struct console *co,
-					       char *options)
+static int lpc32xx_hsuart_console_setup(struct console *co,
+					char *options)
 {
 	struct uart_port *port;
 	int baud = 115200;
diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c
index 68765f7c2645..600fbfaf9c18 100644
--- a/drivers/tty/serial/m32r_sio.c
+++ b/drivers/tty/serial/m32r_sio.c
@@ -981,7 +981,7 @@ static void m32r_sio_console_write(struct console *co, const char *s,
 	sio_out(up, SIOTRCR, ier);
 }
 
-static int __init m32r_sio_console_setup(struct console *co, char *options)
+static int m32r_sio_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = 9600;
diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c
index 02eb32217685..cf28c2ff6d1a 100644
--- a/drivers/tty/serial/mcf.c
+++ b/drivers/tty/serial/mcf.c
@@ -546,7 +546,7 @@ static void mcf_console_write(struct console *co, const char *s, unsigned int co
 
 /****************************************************************************/
 
-static int __init mcf_console_setup(struct console *co, char *options)
+static int mcf_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = CONFIG_SERIAL_MCF_BAUDRATE;
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 3970d6a9aaca..9ebdb7ab1786 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1537,9 +1537,8 @@ mpc52xx_uart_int(int irq, void *dev_id)
 
 #ifdef CONFIG_SERIAL_MPC52xx_CONSOLE
 
-static void __init
-mpc52xx_console_get_options(struct uart_port *port,
-			    int *baud, int *parity, int *bits, int *flow)
+static void mpc52xx_console_get_options(struct uart_port *port, int *baud,
+					int *parity, int *bits, int *flow)
 {
 	unsigned char mr1;
 
@@ -1607,8 +1606,7 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
 }
 
 
-static int __init
-mpc52xx_console_setup(struct console *co, char *options)
+static int mpc52xx_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port = &mpc52xx_uart_ports[co->index];
 	struct device_node *np = mpc52xx_uart_nodes[co->index];
diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c
index 4a3021bcc859..09de17f50dbd 100644
--- a/drivers/tty/serial/mpsc.c
+++ b/drivers/tty/serial/mpsc.c
@@ -1762,7 +1762,7 @@ static void mpsc_console_write(struct console *co, const char *s, uint count)
 	spin_unlock_irqrestore(&pi->tx_lock, iflags);
 }
 
-static int __init mpsc_console_setup(struct console *co, char *options)
+static int mpsc_console_setup(struct console *co, char *options)
 {
 	struct mpsc_port_info *pi;
 	int baud, bits, parity, flow;
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index b7d80bd57db9..cb93e43e1537 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -1468,7 +1468,7 @@ static void msm_console_write(struct console *co, const char *s,
 	__msm_console_write(port, s, count, msm_port->is_uartdm);
 }
 
-static int __init msm_console_setup(struct console *co, char *options)
+static int msm_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = 115200;
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index eb54e5c77ead..ec9a52c32f47 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1400,9 +1400,8 @@ auart_console_write(struct console *co, const char *str, unsigned int count)
 	clk_disable(s->clk);
 }
 
-static void __init
-auart_console_get_options(struct mxs_auart_port *s, int *baud,
-			  int *parity, int *bits)
+static void auart_console_get_options(struct mxs_auart_port *s, int *baud,
+				      int *parity, int *bits)
 {
 	struct uart_port *port = &s->port;
 	unsigned int lcr_h, quot;
@@ -1435,8 +1434,7 @@ auart_console_get_options(struct mxs_auart_port *s, int *baud,
 	*baud = (port->uartclk << 2) / quot;
 }
 
-static int __init
-auart_console_setup(struct console *co, char *options)
+static int auart_console_setup(struct console *co, char *options)
 {
 	struct mxs_auart_port *s;
 	int baud = 9600;
diff --git a/drivers/tty/serial/netx-serial.c b/drivers/tty/serial/netx-serial.c
index 207a0a032ed1..78ded531ce75 100644
--- a/drivers/tty/serial/netx-serial.c
+++ b/drivers/tty/serial/netx-serial.c
@@ -547,9 +547,8 @@ netx_console_write(struct console *co, const char *s, unsigned int count)
 	writel(cr_save, port->membase + UART_CR);
 }
 
-static void __init
-netx_console_get_options(struct uart_port *port, int *baud,
-			int *parity, int *bits, int *flow)
+static void netx_console_get_options(struct uart_port *port, int *baud,
+				     int *parity, int *bits, int *flow)
 {
 	unsigned char line_cr;
 
@@ -589,8 +588,7 @@ netx_console_get_options(struct uart_port *port, int *baud,
 		*flow = 'r';
 }
 
-static int __init
-netx_console_setup(struct console *co, char *options)
+static int netx_console_setup(struct console *co, char *options)
 {
 	struct netx_port *sport;
 	int baud = 9600;
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index a2a529994ba5..4aea63b20780 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1296,8 +1296,7 @@ serial_omap_console_write(struct console *co, const char *s,
 	local_irq_restore(flags);
 }
 
-static int __init
-serial_omap_console_setup(struct console *co, char *options)
+static int serial_omap_console_setup(struct console *co, char *options)
 {
 	struct uart_omap_port *up;
 	int baud = 115200;
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index ea4ffc2ebb2f..61b3c28e83aa 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -1694,7 +1694,7 @@ pch_console_write(struct console *co, const char *s, unsigned int count)
 	local_irq_restore(flags);
 }
 
-static int __init pch_console_setup(struct console *co, char *options)
+static int pch_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = default_baud;
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index e156e39d620c..1292c6c9b9c5 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -1991,7 +1991,7 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c
 /*
  * Setup the serial console
  */
-static int __init pmz_console_setup(struct console *co, char *options)
+static int pmz_console_setup(struct console *co, char *options)
 {
 	struct uart_pmac_port *uap;
 	struct uart_port *port;
diff --git a/drivers/tty/serial/pnx8xxx_uart.c b/drivers/tty/serial/pnx8xxx_uart.c
index 7a3bb9cf1f2e..84c4efdde8dc 100644
--- a/drivers/tty/serial/pnx8xxx_uart.c
+++ b/drivers/tty/serial/pnx8xxx_uart.c
@@ -721,8 +721,7 @@ pnx8xxx_console_write(struct console *co, const char *s, unsigned int count)
 	serial_out(sport, PNX8XXX_IEN, old_ien);
 }
 
-static int __init
-pnx8xxx_console_setup(struct console *co, char *options)
+static int pnx8xxx_console_setup(struct console *co, char *options)
 {
 	struct pnx8xxx_port *sport;
 	int baud = 38400;
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c
index 41eab75ba2af..215a1ba687a7 100644
--- a/drivers/tty/serial/pxa.c
+++ b/drivers/tty/serial/pxa.c
@@ -727,8 +727,7 @@ static void serial_pxa_put_poll_char(struct uart_port *port,
 
 #endif /* CONFIG_CONSOLE_POLL */
 
-static int __init
-serial_pxa_console_setup(struct console *co, char *options)
+static int serial_pxa_console_setup(struct console *co, char *options)
 {
 	struct uart_pxa_port *up;
 	int baud = 9600;
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
index fd3d1329d48c..2ad0bf2af484 100644
--- a/drivers/tty/serial/sa1100.c
+++ b/drivers/tty/serial/sa1100.c
@@ -745,9 +745,8 @@ sa1100_console_write(struct console *co, const char *s, unsigned int count)
  * If the port was already initialised (eg, by a boot loader),
  * try to determine the current setup.
  */
-static void __init
-sa1100_console_get_options(struct sa1100_port *sport, int *baud,
-			   int *parity, int *bits)
+static void sa1100_console_get_options(struct sa1100_port *sport, int *baud,
+				       int *parity, int *bits)
 {
 	unsigned int utcr3;
 
@@ -777,8 +776,7 @@ sa1100_console_get_options(struct sa1100_port *sport, int *baud,
 	}
 }
 
-static int __init
-sa1100_console_setup(struct console *co, char *options)
+static int sa1100_console_setup(struct console *co, char *options)
 {
 	struct sa1100_port *sport;
 	int baud = 9600;
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 4d2924f61e0b..2fa86e01bd94 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -2041,9 +2041,8 @@ s3c24xx_serial_console_write(struct console *co, const char *s,
 	uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
 }
 
-static void __init
-s3c24xx_serial_get_options(struct uart_port *port, int *baud,
-			   int *parity, int *bits)
+static void s3c24xx_serial_get_options(struct uart_port *port, int *baud,
+				       int *parity, int *bits)
 {
 	struct clk *clk;
 	unsigned int ulcon;
@@ -2109,8 +2108,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
 
 }
 
-static int __init
-s3c24xx_serial_console_setup(struct console *co, char *options)
+static int s3c24xx_serial_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = 9600;
diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c
index 771f361c47ea..826c87c1d0c3 100644
--- a/drivers/tty/serial/sb1250-duart.c
+++ b/drivers/tty/serial/sb1250-duart.c
@@ -869,7 +869,7 @@ static void sbd_console_write(struct console *co, const char *s,
 	spin_unlock_irqrestore(&uport->lock, flags);
 }
 
-static int __init sbd_console_setup(struct console *co, char *options)
+static int sbd_console_setup(struct console *co, char *options)
 {
 	int chip = co->index / DUART_MAX_SIDE;
 	int side = co->index % DUART_MAX_SIDE;
diff --git a/drivers/tty/serial/serial_ks8695.c b/drivers/tty/serial/serial_ks8695.c
index 57f152394af5..97c3aa5a27e6 100644
--- a/drivers/tty/serial/serial_ks8695.c
+++ b/drivers/tty/serial/serial_ks8695.c
@@ -575,7 +575,8 @@ static void ks8695_console_write(struct console *co, const char *s, u_int count)
 	uart_console_write(port, s, count, ks8695_console_putchar);
 }
 
-static void __init ks8695_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
+static void ks8695_console_get_options(struct uart_port *port, int *baud,
+				       int *parity, int *bits)
 {
 	unsigned int lcr;
 
@@ -611,7 +612,7 @@ static void __init ks8695_console_get_options(struct uart_port *port, int *baud,
 	*baud &= 0xFFFFFFF0;
 }
 
-static int __init ks8695_console_setup(struct console *co, char *options)
+static int ks8695_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = 115200;
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index f80312eed4fd..90593c77fe73 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -930,7 +930,7 @@ serial_txx9_console_write(struct console *co, const char *s, unsigned int count)
 	sio_out(up, TXX9_SIDICR, ier);
 }
 
-static int __init serial_txx9_console_setup(struct console *co, char *options)
+static int serial_txx9_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	struct uart_txx9_port *up;
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
index b186c9c4f850..ffab1e8fb090 100644
--- a/drivers/tty/serial/sirfsoc_uart.c
+++ b/drivers/tty/serial/sirfsoc_uart.c
@@ -1081,8 +1081,7 @@ static struct uart_ops sirfsoc_uart_ops = {
 };
 
 #ifdef CONFIG_SERIAL_SIRFSOC_CONSOLE
-static int __init
-sirfsoc_uart_console_setup(struct console *co, char *options)
+static int sirfsoc_uart_console_setup(struct console *co, char *options)
 {
 	unsigned int baud = 115200;
 	unsigned int bits = 8;
diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
index 699447aa8b43..922ca6ed8dca 100644
--- a/drivers/tty/serial/sprd_serial.c
+++ b/drivers/tty/serial/sprd_serial.c
@@ -559,7 +559,7 @@ static void sprd_console_write(struct console *co, const char *s,
 		spin_unlock_irqrestore(&port->lock, flags);
 }
 
-static int __init sprd_console_setup(struct console *co, char *options)
+static int sprd_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
 	int baud = 115200;
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 9ad98eaa35bf..ffedbc152aa5 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -1338,7 +1338,7 @@ static void sunsu_console_write(struct console *co, const char *s,
  *	- initialize the serial port
  *	Return non-zero if we didn't find a serial port.
  */
-static int __init sunsu_console_setup(struct console *co, char *options)
+static int sunsu_console_setup(struct console *co, char *options)
 {
 	static struct ktermios dummy;
 	struct ktermios termios;
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
index 8b6ace341029..450ae95f9962 100644
--- a/drivers/tty/serial/sunzilog.c
+++ b/drivers/tty/serial/sunzilog.c
@@ -1217,7 +1217,7 @@ sunzilog_console_write(struct console *con, const char *s, unsigned int count)
 		spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
-static int __init sunzilog_console_setup(struct console *con, char *options)
+static int sunzilog_console_setup(struct console *con, char *options)
 {
 	struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
 	unsigned long flags;
diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c
index 485de53c5d75..306c59aa8687 100644
--- a/drivers/tty/serial/vr41xx_siu.c
+++ b/drivers/tty/serial/vr41xx_siu.c
@@ -782,7 +782,7 @@ static void siu_console_write(struct console *con, const char *s, unsigned count
 	siu_write(port, UART_IER, ier);
 }
 
-static int __init siu_console_setup(struct console *con, char *options)
+static int siu_console_setup(struct console *con, char *options)
 {
 	struct uart_port *port;
 	int baud = 9600;
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index b384060e3b1f..855e612c2bcd 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -527,7 +527,7 @@ static void vt8500_console_write(struct console *co, const char *s,
 	vt8500_write(&vt8500_port->uart, VT8500_URIER, ier);
 }
 
-static int __init vt8500_console_setup(struct console *co, char *options)
+static int vt8500_console_setup(struct console *co, char *options)
 {
 	struct vt8500_port *vt8500_port;
 	int baud = 9600;
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index cd46e64c4255..1d3908628896 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -1134,7 +1134,7 @@ static void cdns_uart_console_write(struct console *co, const char *s,
  *
  * Return: 0 on success, negative errno otherwise.
  */
-static int __init cdns_uart_console_setup(struct console *co, char *options)
+static int cdns_uart_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port = &cdns_uart_port[co->index];
 	int baud = 9600;
diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c
index eeefd76a30da..80066ae8cadf 100644
--- a/drivers/tty/serial/zs.c
+++ b/drivers/tty/serial/zs.c
@@ -1195,7 +1195,7 @@ static void zs_console_write(struct console *co, const char *s,
  * - initialise the serial port
  * Return non-zero if we didn't find a serial port.
  */
-static int __init zs_console_setup(struct console *co, char *options)
+static int zs_console_setup(struct console *co, char *options)
 {
 	int chip = co->index / ZS_NUM_CHAN, side = co->index % ZS_NUM_CHAN;
 	struct zs_port *zport = &zs_sccs[chip].zport[side];
-- 
1.9.1



From hramrach at gmail.com  Tue May 31 07:19:28 2016
From: hramrach at gmail.com (Michal Suchanek)
Date: Tue, 31 May 2016 16:19:28 +0200
Subject: [PATCH 5/5] RFC spi: sun4i: add DMA support
In-Reply-To: <20160531132706.GC29837@sirena.org.uk>
References: <cover.1464130597.git.hramrach@gmail.com>
 <ba0d6eb37cc4b0d2c46acbf9fcd7d644b3545ce8.1464130597.git.hramrach@gmail.com>
 <20160530112610.GJ29837@sirena.org.uk>
 <CAMuHMdVThvtqgFnyqoqypwwf1d81uu9NBo6-heTZBcvBxRevNw@mail.gmail.com>
 <20160530150343.GL29837@sirena.org.uk>
 <CAOMqctQb-YYprA7H5qCcYo2hxXiUhjW2z3JbZ3-FhbfcjFzBpw@mail.gmail.com>
 <20160530155016.GO29837@sirena.org.uk>
 <CAOMqctQijjO2amwSmSMGp96KBRGrLb0fvXRwnybOEqvV3-HZ0g@mail.gmail.com>
 <20160531132706.GC29837@sirena.org.uk>
Message-ID: <CAOMqctSWnbUaOveMUhz+yOJqTOK4EhDd5jUqKoHCohfndNAjWA@mail.gmail.com>

On 31 May 2016 at 15:27, Mark Brown <broonie at kernel.org> wrote:
> On Tue, May 31, 2016 at 12:44:54PM +0200, Michal Suchanek wrote:
>> On 30 May 2016 at 17:50, Mark Brown <broonie at kernel.org> wrote:
>> > On Mon, May 30, 2016 at 05:28:10PM +0200, Michal Suchanek wrote:
>
>> >> It's what the driver did to start with and it was requested to fall
>> >> back to non-DMA in the case DMA is not available.
>
>> > Why?  I really can't see any sensible use case for this that doesn't
>> > have a better solution available.
>
>> Of course, the solution is to compile in the DMA driver.
>
>> It's been argued that some drivers which use only short transfers will
>> just work.
>
> With nothing else in the system that needs DMA?  It's making the
> performance of the system less reliable for the benefit of a very narrow
> use case.

Some of the platform devices have dedicated DMA *controller* built
into the device IP so the DMA engine really is optional on many sunxi
devices. Besides SPI you definitely need the DMA engine for audio. You
probably don't need it for storage and graphics. I don't have any idea
if it's used for USB and Ethernet.

Thanks

Michal


From linux at armlinux.org.uk  Tue May 31 07:21:42 2016
From: linux at armlinux.org.uk (Russell King - ARM Linux)
Date: Tue, 31 May 2016 15:21:42 +0100
Subject: [RFT PATCH 1/2] serial: Fix console setup section mismatch
In-Reply-To: <1464704372-17668-1-git-send-email-k.kozlowski@samsung.com>
References: <1464704372-17668-1-git-send-email-k.kozlowski@samsung.com>
Message-ID: <20160531142142.GX19428@n2100.arm.linux.org.uk>

On Tue, May 31, 2016 at 04:19:31PM +0200, Krzysztof Kozlowski wrote:
> Remove __init annotation from all of console->setup implementations
> because:
> 1. The pointer to it is stored in a struct console which is not
>    marked with __initdata.
> 2. It is referenced by register_console() from kernel which is not
>    marked with __init.

However, many of these drivers, the console can only be used when the
driver is built-in, and register_console() is only called early in
initialisation.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


From catalin.marinas at arm.com  Tue May 31 07:23:21 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 15:23:21 +0100
Subject: [PATCH] arm64: defconfig: add options for virtualization and
 containers
In-Reply-To: <20160531135740.GL24936@arm.com>
References: <1464345747-11729-1-git-send-email-riku.voipio@linaro.org>
 <20160531135740.GL24936@arm.com>
Message-ID: <20160531142321.GB11321@e104818-lin.cambridge.arm.com>

On Tue, May 31, 2016 at 02:57:41PM +0100, Will Deacon wrote:
> On Fri, May 27, 2016 at 01:42:27PM +0300, Riku Voipio wrote:
> > Enable options commonly needed by popular virtualization
> > and container applications. Use modules when possible to
> > avoid too much overhead for users not interested.
> > 
> > - add namespace and cgroup options needed
> > - add seccomp - optional, but enhances Qemu etc
> > - bridge, nat, veth, macvtap and multicast for routing
> >   guests and containers
> > - btfrs and overlayfs modules for container COW backends
> > - while near it, make fuse a module instead of built-in.
> > 
> > Generated with make saveconfig and dropping unrelated spurious
> > change hunks while commiting. bloat-o-meter old-vmlinux vmlinux:
> > 
> > add/remove: 899/388 grow/shrink: 744/216 up/down: 183556/-94881 (88675)
> > ...
> > Total: Before=10515333, After=10604008, chg 0.000000%
> > 
> > Signed-off-by: Riku Voipio <riku.voipio at linaro.org>
> > ---
> >  arch/arm64/configs/defconfig | 53 +++++++++++++++++++++++++++++++++++++++-----
> >  1 file changed, 47 insertions(+), 6 deletions(-)
> 
> I'm fine with adding stuff to defconfig if it's useful to people (and it
> looks like this is), but it's probably about time we figured out what to
> do about '=y' vs '=m'. Until recently (i.e. this merge window), the arm64
> defconfig didn't build any modules. Obviously this only scales so far,
> since the Image tends to get rather huge, but it would be good to try and
> establish a rule-of-thumb as to whether we treat something as a module
> or a built-in. We could even consider retrospectively applying the rule
> if its straightforward enough.
> 
> One easy way to do it would be: if you need the option to boot, then
> it's a built-in, but that brings up questions around "boot a full android
> system" vs "boot to a point where you could load an initrd".

For the time being, I would say defconfig should cover "boot to a login
prompt" where this may imply NFS + network driver built in for the
supported SoCs, couple of commonly used filesystems (ext4, btrfs). The
rest can be enabled as modules.

As the image continues to grow over years, we will have to revisit this
and possibly separate the mobile from the server SoC defconfig. For the
former, we can probably keep the same "boot to a login prompt" approach.
For the latter, especially if you install it under a distro (e.g. you do
make deb-pkg or rpm-pkg), we can aim for "boot to initramfs". That said,
I'd like to see most of the SoC drivers stuff built as modules (whatever
is not essential for booting to initramfs and comes in at
device_initcall level).

-- 
Catalin


From james.morse at arm.com  Tue May 31 07:24:15 2016
From: james.morse at arm.com (James Morse)
Date: Tue, 31 May 2016 15:24:15 +0100
Subject: [PATCH v2] arm64: Implement optimised IP checksum helpers
In-Reply-To: <ba9cf5bf84b8adc766f7f7511dda8cb501cd4101.1464693619.git.robin.murphy@arm.com>
References: <ba9cf5bf84b8adc766f7f7511dda8cb501cd4101.1464693619.git.robin.murphy@arm.com>
Message-ID: <574D9E8F.7080509@arm.com>

Hi Robin,

On 31/05/16 12:22, Robin Murphy wrote:
> AArch64 is capable of 128-bit memory accesses without alignment
> restrictions, which makes it both possible and highly practical to slurp
> up a typical 20-byte IP header in just 2 loads. Implement our own
> version of ip_fast_checksum() to take advantage of that, resulting in
> considerably fewer instructions and memory accesses than the generic
> version. We can also get more optimal code generation for csum_fold() by
> defining it a slightly different way round from the generic version, so
> throw that into the mix too.
> 
> Suggested-by: Luke Starrett <luke.starrett at broadcom.com>
> Acked-by: Luke Starrett <luke.starrett at broadcom.com>
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
> 
> Minor changes: include types.h for correctness, add Luke's ack.
> 
>  arch/arm64/include/asm/checksum.h | 51 +++++++++++++++++++++++++++++++++++++++

Maybe a nit, don't you need to remove the 'generic-y += checksum.h' line from
arch/arm64/include/asm/Kbuild to avoid the generated version being created too? [0]

The compiler on my box picks your header in preference to the generated one, but
[1] suggests it isn't to be trusted!


Thanks,

James

[0] d8ecc5cd8e22 ("kbuild: asm-generic support")
[1] https://lkml.org/lkml/2016/5/23/78


From mark.rutland at arm.com  Tue May 31 07:30:29 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 15:30:29 +0100
Subject: [PATCHv2] arm64: enable CONFIG_SET_MODULE_RONX by default
Message-ID: <1464705029-23868-1-git-send-email-mark.rutland@arm.com>

The SET_MODULE_RONX protections are effectively the same as the
DEBUG_RODATA protections we enabled by default back in commit
57efac2f7108e325 ("arm64: enable CONFIG_DEBUG_RODATA by default"). It
seems unusual to have one but not the other.

As evidenced by the help text, the rationale appears to be that
SET_MODULE_RONX interacts poorly with tracing and patching, but both of
these make use of the insn framework, which takes SET_MODULE_RONX into
account. Any remaining issues are bugs which should be fixed regardless
of the default state of the option.

This patch enables DEBUG_SET_MODULE_RONX by default, and replaces the
help text with a new wording derived from the DEBUG_RODATA help text,
which better describes the functionality. Previously, the DEBUG_RODATA
entry was inconsistently indented with spaces, which are replaced with
tabs as with the other Kconfig entries.

Additionally, the wording of recommended defaults is made consistent for
all options. These are placed in a new paragraph, unquoted, as a full
sentence (with a period/full stop) as this appears to be the most common
form per $(git grep 'in doubt').

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
Acked-by: Kees Cook <keescook at chromium.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Laura Abbott <labbott at fedoraproject.org>
Cc: Will Deacon <will.deacon at arm.com>
---
 arch/arm64/Kconfig.debug | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

I'm resending this with acks accumulated since we've hit v4.7-rc1. I've also
given this a spin loading and unloading modules, without incident.

Since v1 [1]:
* Accumulate acks
* Trivial v4.7-rc1 rebase

Mark.

[1] lkml.kernel.org/r/1463138436-5073-1-git-send-email-mark.rutland at arm.com

diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
index 710fde4..0cc758c 100644
--- a/arch/arm64/Kconfig.debug
+++ b/arch/arm64/Kconfig.debug
@@ -12,7 +12,8 @@ config ARM64_PTDUMP
 	  who are working in architecture specific areas of the kernel.
 	  It is probably not a good idea to enable this feature in a production
 	  kernel.
-	  If in doubt, say "N"
+
+	  If in doubt, say N.
 
 config PID_IN_CONTEXTIDR
 	bool "Write the current PID to the CONTEXTIDR register"
@@ -38,15 +39,15 @@ config ARM64_RANDOMIZE_TEXT_OFFSET
 	  value.
 
 config DEBUG_SET_MODULE_RONX
-        bool "Set loadable kernel module data as NX and text as RO"
-        depends on MODULES
-        help
-          This option helps catch unintended modifications to loadable
-          kernel module's text and read-only data. It also prevents execution
-          of module data. Such protection may interfere with run-time code
-          patching and dynamic kernel tracing - and they might also protect
-          against certain classes of kernel exploits.
-          If in doubt, say "N".
+	bool "Set loadable kernel module data as NX and text as RO"
+	depends on MODULES
+	default y
+	help
+	  Is this is set, kernel module text and rodata will be made read-only.
+	  This is to help catch accidental or malicious attempts to change the
+	  kernel's executable code.
+
+	  If in doubt, say Y.
 
 config DEBUG_RODATA
 	bool "Make kernel text and rodata read-only"
@@ -56,7 +57,7 @@ config DEBUG_RODATA
 	  is to help catch accidental or malicious attempts to change the
 	  kernel's executable code.
 
-	  If in doubt, say Y
+	  If in doubt, say Y.
 
 config DEBUG_ALIGN_RODATA
 	depends on DEBUG_RODATA
@@ -69,7 +70,7 @@ config DEBUG_ALIGN_RODATA
 	  alignment and potentially wasted space. Turn on this option if
 	  performance is more important than memory pressure.
 
-	  If in doubt, say N
+	  If in doubt, say N.
 
 source "drivers/hwtracing/coresight/Kconfig"
 
-- 
1.9.1



From geert+renesas at glider.be  Tue May 31 07:31:50 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Tue, 31 May 2016 16:31:50 +0200
Subject: [PATCH 1/3] ARM: dts: imx28: Use generic uart-has-rtscts DT property
In-Reply-To: <1464705112-21609-1-git-send-email-geert+renesas@glider.be>
References: <1464705112-21609-1-git-send-email-geert+renesas@glider.be>
Message-ID: <1464705112-21609-2-git-send-email-geert+renesas@glider.be>

As of commit 182cdcb8bb16e687 ("serial: mxs-auart: Use generic
uart-has-rtscts DT property"), the Freescale MXS AUART driver recognizes
the generic "uart-has-rtscts" DT property, deprecating the
vendor-specific "fsl,uart-has-rtscts" DT property. Hence replace the
latter by the former in all DTS files.

Signed-off-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
 arch/arm/boot/dts/imx28-apf28dev.dts | 2 +-
 arch/arm/boot/dts/imx28-evk.dts      | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/imx28-apf28dev.dts b/arch/arm/boot/dts/imx28-apf28dev.dts
index 1eaa131e2d1809fb..c4fadbc1b40040f4 100644
--- a/arch/arm/boot/dts/imx28-apf28dev.dts
+++ b/arch/arm/boot/dts/imx28-apf28dev.dts
@@ -140,7 +140,7 @@
 			auart0: serial at 8006a000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&auart0_pins_a>;
-				fsl,uart-has-rtscts;
+				uart-has-rtscts;
 				status = "okay";
 			};
 
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index e3ef94ac159f75b2..a5ba669b4eaa4ce3 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -224,7 +224,7 @@
 			auart0: serial at 8006a000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&auart0_pins_a>;
-				fsl,uart-has-rtscts;
+				uart-has-rtscts;
 				status = "okay";
 			};
 
-- 
1.9.1



From geert+renesas at glider.be  Tue May 31 07:31:49 2016
From: geert+renesas at glider.be (Geert Uytterhoeven)
Date: Tue, 31 May 2016 16:31:49 +0200
Subject: [PATCH 0/3] ARM: dts: Use generic uart-has-rtscts DT property
Message-ID: <1464705112-21609-1-git-send-email-geert+renesas@glider.be>

	Hi Shawn, Sascha, Barry,

As of v4.7-rc1, the Freescale MXS AUART and IMX UART drivers, and the
SiRF UART driver, recognize the generic "uart-has-rtscts" DT property,
deprecating the vendor-specific "<vendor>,uart-has-rtscts" DT
properties.  This series updates all DTS files to replace the latter by
the former.

Thanks for applying!

Geert Uytterhoeven (3):
  ARM: dts: imx28: Use generic uart-has-rtscts DT property
  ARM: dts: imx: Use generic uart-has-rtscts DT property
  ARM: dts: atlas7: Use generic uart-has-rtscts DT property

 arch/arm/boot/dts/atlas7-evb.dts                       | 2 +-
 arch/arm/boot/dts/imx1-ads.dts                         | 4 ++--
 arch/arm/boot/dts/imx1-apf9328.dts                     | 4 ++--
 arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts | 4 ++--
 arch/arm/boot/dts/imx25-pdk.dts                        | 2 +-
 arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi           | 2 +-
 arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts | 6 +++---
 arch/arm/boot/dts/imx27-pdk.dts                        | 2 +-
 arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts       | 6 +++---
 arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts         | 4 ++--
 arch/arm/boot/dts/imx28-apf28dev.dts                   | 2 +-
 arch/arm/boot/dts/imx28-evk.dts                        | 2 +-
 arch/arm/boot/dts/imx31-bug.dts                        | 2 +-
 arch/arm/boot/dts/imx35-eukrea-mbimxsd35-baseboard.dts | 4 ++--
 arch/arm/boot/dts/imx35-pdk.dts                        | 2 +-
 arch/arm/boot/dts/imx51-babbage.dts                    | 4 ++--
 arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts | 4 ++--
 arch/arm/boot/dts/imx53-smd.dts                        | 2 +-
 arch/arm/boot/dts/imx53-tqma53.dtsi                    | 2 +-
 arch/arm/boot/dts/imx53-tx53.dtsi                      | 6 +++---
 arch/arm/boot/dts/imx6q-arm2.dts                       | 2 +-
 arch/arm/boot/dts/imx6q-ba16.dtsi                      | 2 +-
 arch/arm/boot/dts/imx6qdl-apalis.dtsi                  | 4 ++--
 arch/arm/boot/dts/imx6qdl-apf6dev.dtsi                 | 2 +-
 arch/arm/boot/dts/imx6qdl-aristainetos.dtsi            | 4 ++--
 arch/arm/boot/dts/imx6qdl-aristainetos2.dtsi           | 4 ++--
 arch/arm/boot/dts/imx6qdl-microsom.dtsi                | 2 +-
 arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi               | 2 +-
 arch/arm/boot/dts/imx6qdl-tx6.dtsi                     | 6 +++---
 arch/arm/boot/dts/imx6qdl-wandboard.dtsi               | 2 +-
 arch/arm/boot/dts/imx6sl-warp.dts                      | 2 +-
 arch/arm/boot/dts/imx6sx-nitrogen6sx.dts               | 2 +-
 arch/arm/boot/dts/imx6sx-sdb.dtsi                      | 2 +-
 arch/arm/boot/dts/imx6ul-14x14-evk.dts                 | 2 +-
 arch/arm/boot/dts/imx6ul-pico-hobbit.dts               | 2 +-
 arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts           | 4 ++--
 arch/arm/boot/dts/imx6ul-tx6ul.dtsi                    | 6 +++---
 arch/arm/boot/dts/imx7d-nitrogen7.dts                  | 2 +-
 38 files changed, 59 insertions(+), 59 deletions(-)

-- 
1.9.1

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 k.kozlowski at samsung.com  Tue May 31 07:34:47 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 16:34:47 +0200
Subject: [RFT PATCH 1/2] serial: Fix console setup section mismatch
In-Reply-To: <20160531142142.GX19428@n2100.arm.linux.org.uk>
References: <1464704372-17668-1-git-send-email-k.kozlowski@samsung.com>
 <20160531142142.GX19428@n2100.arm.linux.org.uk>
Message-ID: <574DA107.8050002@samsung.com>

On 05/31/2016 04:21 PM, Russell King - ARM Linux wrote:
> On Tue, May 31, 2016 at 04:19:31PM +0200, Krzysztof Kozlowski wrote:
>> Remove __init annotation from all of console->setup implementations
>> because:
>> 1. The pointer to it is stored in a struct console which is not
>>    marked with __initdata.
>> 2. It is referenced by register_console() from kernel which is not
>>    marked with __init.
> 
> However, many of these drivers, the console can only be used when the
> driver is built-in, and register_console() is only called early in
> initialisation.

Indeed so maybe the word "fix" in commit subject is not proper because
there might be no error at all. My point is that current solution is a
little bit non-obvious and an error might happen. If we were sure that
register_console() is called only from other __init functions, then it
should be made also __init.

Best regards,
Krzysztof



From christoffer.dall at linaro.org  Tue May 31 07:35:28 2016
From: christoffer.dall at linaro.org (Christoffer Dall)
Date: Tue, 31 May 2016 16:35:28 +0200
Subject: [PATCH 2/3] arm64/kvm: use ESR_ELx_EC to extract EC
In-Reply-To: <1464694383-31700-3-git-send-email-mark.rutland@arm.com>
References: <1464694383-31700-1-git-send-email-mark.rutland@arm.com>
 <1464694383-31700-3-git-send-email-mark.rutland@arm.com>
Message-ID: <20160531143528.GC12568@cbox>

On Tue, May 31, 2016 at 12:33:02PM +0100, Mark Rutland wrote:
> Now that we have a helper to extract the EC from an ESR_ELx value, make
> use of this in the arm64 KVM code for simplicity and consistency. There
> should be no functional changes as a result of this patch.
> 
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Christoffer Dall <christoffer.dall at linaro.org>
> Cc: Dave P Martin <dave.martin at arm.com>
> Cc: Huang Shijie <shijie.huang at arm.com>
> Cc: James Morse <james.morse at arm.com>
> Cc: Marc Zyngier <marc.zyngier at arm.com>
> Cc: Will Deacon <will.deacon at arm.com>
> Cc: kvmarm at lists.cs.columbia.edu

Acked-by: Christoffer Dall <christoffer.dall at linaro.org>

> ---
>  arch/arm64/include/asm/kvm_emulate.h | 2 +-
>  arch/arm64/kvm/handle_exit.c         | 4 ++--
>  arch/arm64/kvm/hyp/switch.c          | 2 +-
>  3 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
> index 40bc168..4cdeae3 100644
> --- a/arch/arm64/include/asm/kvm_emulate.h
> +++ b/arch/arm64/include/asm/kvm_emulate.h
> @@ -210,7 +210,7 @@ static inline bool kvm_vcpu_trap_il_is32bit(const struct kvm_vcpu *vcpu)
>  
>  static inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu)
>  {
> -	return kvm_vcpu_get_hsr(vcpu) >> ESR_ELx_EC_SHIFT;
> +	return ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu));
>  }
>  
>  static inline bool kvm_vcpu_trap_is_iabt(const struct kvm_vcpu *vcpu)
> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> index 3246c4a..fa96fe2 100644
> --- a/arch/arm64/kvm/handle_exit.c
> +++ b/arch/arm64/kvm/handle_exit.c
> @@ -106,7 +106,7 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, struct kvm_run *run)
>  	run->exit_reason = KVM_EXIT_DEBUG;
>  	run->debug.arch.hsr = hsr;
>  
> -	switch (hsr >> ESR_ELx_EC_SHIFT) {
> +	switch (ESR_ELx_EC(hsr)) {
>  	case ESR_ELx_EC_WATCHPT_LOW:
>  		run->debug.arch.far = vcpu->arch.fault.far_el2;
>  		/* fall through */
> @@ -149,7 +149,7 @@ static exit_handle_fn arm_exit_handlers[] = {
>  static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
>  {
>  	u32 hsr = kvm_vcpu_get_hsr(vcpu);
> -	u8 hsr_ec = hsr >> ESR_ELx_EC_SHIFT;
> +	u8 hsr_ec = ESR_ELx_EC(hsr);
>  
>  	if (hsr_ec >= ARRAY_SIZE(arm_exit_handlers) ||
>  	    !arm_exit_handlers[hsr_ec]) {
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index 437cfad..4373997 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -198,7 +198,7 @@ static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar)
>  static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
>  {
>  	u64 esr = read_sysreg_el2(esr);
> -	u8 ec = esr >> ESR_ELx_EC_SHIFT;
> +	u8 ec = ESR_ELx_EC(esr);
>  	u64 hpfar, far;
>  
>  	vcpu->arch.fault.esr_el2 = esr;
> -- 
> 1.9.1
> 


From robin.murphy at arm.com  Tue May 31 07:39:06 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 31 May 2016 15:39:06 +0100
Subject: [PATCH v2] arm64: Implement optimised IP checksum helpers
In-Reply-To: <574D9E8F.7080509@arm.com>
References: <ba9cf5bf84b8adc766f7f7511dda8cb501cd4101.1464693619.git.robin.murphy@arm.com>
 <574D9E8F.7080509@arm.com>
Message-ID: <574DA20A.4070302@arm.com>

Hi James,

On 31/05/16 15:24, James Morse wrote:
> Hi Robin,
>
> On 31/05/16 12:22, Robin Murphy wrote:
>> AArch64 is capable of 128-bit memory accesses without alignment
>> restrictions, which makes it both possible and highly practical to slurp
>> up a typical 20-byte IP header in just 2 loads. Implement our own
>> version of ip_fast_checksum() to take advantage of that, resulting in
>> considerably fewer instructions and memory accesses than the generic
>> version. We can also get more optimal code generation for csum_fold() by
>> defining it a slightly different way round from the generic version, so
>> throw that into the mix too.
>>
>> Suggested-by: Luke Starrett <luke.starrett at broadcom.com>
>> Acked-by: Luke Starrett <luke.starrett at broadcom.com>
>> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
>> ---
>>
>> Minor changes: include types.h for correctness, add Luke's ack.
>>
>>   arch/arm64/include/asm/checksum.h | 51 +++++++++++++++++++++++++++++++++++++++
>
> Maybe a nit, don't you need to remove the 'generic-y += checksum.h' line from
> arch/arm64/include/asm/Kbuild to avoid the generated version being created too? [0]

I guess you skimmed the very end of the patch ;)

+#include <asm-generic/checksum.h>

> The compiler on my box picks your header in preference to the generated one, but
> [1] suggests it isn't to be trusted!

We only cherry-pick a couple of functions to optimise, so not building 
the generic file would necessitate copy-pasting the rest of it. I'd hope 
this pattern is sufficiently robust, since it's already in use on a 
number of other architectures! AFAICS [1] only applies when the generic 
file shouldn't be built at all, so cross fingers we're probably OK.

Robin.

> Thanks,
>
> James
>
> [0] d8ecc5cd8e22 ("kbuild: asm-generic support")
> [1] https://lkml.org/lkml/2016/5/23/78
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>



From l.stach at pengutronix.de  Tue May 31 07:43:22 2016
From: l.stach at pengutronix.de (Lucas Stach)
Date: Tue, 31 May 2016 16:43:22 +0200
Subject: [PATCH] l2c: warn about misconfigured PL310 shared-override
Message-ID: <1464705802-11787-1-git-send-email-l.stach@pengutronix.de>

If the shared override enable bit in the PL310 aux ctrl register is
not set the L2 cache controller will render the system non-compliant
to the rules regarding mismatched memory aliases as specified in the
ARMv7 ARM RevC.

As this may lead to subtle corruptions when reading from a bufferable
alias, make sure to warn about this in the kernel log.

Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
---
 arch/arm/mm/cache-l2x0.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index c61996c256cc..d2690f0d3cd0 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -815,6 +815,11 @@ static int __init __l2c_init(const struct l2c_init_data *data,
 		pr_warn("L2C: DT/platform modifies aux control register: 0x%08x -> 0x%08x\n",
 		        old_aux, aux);
 
+	if (((cache_id & L2X0_CACHE_ID_PART_MASK) == L2X0_CACHE_ID_PART_L310) &&
+	    !(aux & L2C_AUX_CTRL_SHARED_OVERRIDE))
+		pr_warn("L2C-310 shared attribute override enable not set, "
+			"system is non-compliant to ARM specified memory aliasing rules\n");
+
 	/* Determine the number of ways */
 	switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
 	case L2X0_CACHE_ID_PART_L310:
-- 
2.8.1



From robin.murphy at arm.com  Tue May 31 07:43:39 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 31 May 2016 15:43:39 +0100
Subject: [PATCH v2] arm64: Implement optimised IP checksum helpers
In-Reply-To: <574DA20A.4070302@arm.com>
References: <ba9cf5bf84b8adc766f7f7511dda8cb501cd4101.1464693619.git.robin.murphy@arm.com>
 <574D9E8F.7080509@arm.com> <574DA20A.4070302@arm.com>
Message-ID: <574DA31B.3080309@arm.com>

On 31/05/16 15:39, Robin Murphy wrote:
> Hi James,
>
> On 31/05/16 15:24, James Morse wrote:
>> Hi Robin,
>>
>> On 31/05/16 12:22, Robin Murphy wrote:
>>> AArch64 is capable of 128-bit memory accesses without alignment
>>> restrictions, which makes it both possible and highly practical to slurp
>>> up a typical 20-byte IP header in just 2 loads. Implement our own
>>> version of ip_fast_checksum() to take advantage of that, resulting in
>>> considerably fewer instructions and memory accesses than the generic
>>> version. We can also get more optimal code generation for csum_fold() by
>>> defining it a slightly different way round from the generic version, so
>>> throw that into the mix too.
>>>
>>> Suggested-by: Luke Starrett <luke.starrett at broadcom.com>
>>> Acked-by: Luke Starrett <luke.starrett at broadcom.com>
>>> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
>>> ---
>>>
>>> Minor changes: include types.h for correctness, add Luke's ack.
>>>
>>>   arch/arm64/include/asm/checksum.h | 51
>>> +++++++++++++++++++++++++++++++++++++++
>>
>> Maybe a nit, don't you need to remove the 'generic-y += checksum.h'
>> line from
>> arch/arm64/include/asm/Kbuild to avoid the generated version being
>> created too? [0]
>
> I guess you skimmed the very end of the patch ;)
>
> +#include <asm-generic/checksum.h>

Oh wait, I'm being a massive idiot - include/asm-generic is not the same 
thing as arch/arm/include/generated/asm, is it? I see what you mean now, 
and yes it probably does want fixing...

Sorry!
Robin.

>> The compiler on my box picks your header in preference to the
>> generated one, but
>> [1] suggests it isn't to be trusted!
>
> We only cherry-pick a couple of functions to optimise, so not building
> the generic file would necessitate copy-pasting the rest of it. I'd hope
> this pattern is sufficiently robust, since it's already in use on a
> number of other architectures! AFAICS [1] only applies when the generic
> file shouldn't be built at all, so cross fingers we're probably OK.
>
> Robin.
>
>> Thanks,
>>
>> James
>>
>> [0] d8ecc5cd8e22 ("kbuild: asm-generic support")
>> [1] https://lkml.org/lkml/2016/5/23/78
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



From l.stach at pengutronix.de  Tue May 31 07:49:37 2016
From: l.stach at pengutronix.de (Lucas Stach)
Date: Tue, 31 May 2016 16:49:37 +0200
Subject: [PATCH] ARM: dts: imx6: fix IPU1 DI1 node name
Message-ID: <1464706177-30330-1-git-send-email-l.stach@pengutronix.de>

From: Juergen Borleis <jbe at pengutronix.de>

This node describes the DI1 port of IPU, fix the node name to reflect this.
There's currently no user of this node in mainline, so this change should
not break any supported platforms.

Signed-off-by: Juergen Borleis <jbe at pengutronix.de>
Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
---
 arch/arm/boot/dts/imx6q-apalis-ixora.dts | 4 ++--
 arch/arm/boot/dts/imx6qdl.dtsi           | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora.dts b/arch/arm/boot/dts/imx6q-apalis-ixora.dts
index 8e67ca27ad79..207b85b91ada 100644
--- a/arch/arm/boot/dts/imx6q-apalis-ixora.dts
+++ b/arch/arm/boot/dts/imx6q-apalis-ixora.dts
@@ -93,7 +93,7 @@
 			reg = <0>;
 
 			lcd_display_in: endpoint {
-				remote-endpoint = <&ipu1_di0_disp1>;
+				remote-endpoint = <&ipu1_di1_disp1>;
 			};
 		};
 
@@ -210,7 +210,7 @@
 	};
 };
 
-&ipu1_di0_disp1 {
+&ipu1_di1_disp1 {
 	remote-endpoint = <&lcd_display_in>;
 };
 
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index ed613ebe0812..c270dc2c629f 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -1255,7 +1255,7 @@
 				#size-cells = <0>;
 				reg = <3>;
 
-				ipu1_di0_disp1: disp1-endpoint {
+				ipu1_di1_disp1: disp1-endpoint {
 				};
 
 				ipu1_di1_hdmi: hdmi-endpoint {
-- 
2.8.1



From linux at roeck-us.net  Tue May 31 07:53:18 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 31 May 2016 07:53:18 -0700
Subject: pxa_defconfig runtime failures due to 'ARM: pxa: activate pinctrl
 for device-tree machines'
In-Reply-To: <87vb1ueo8s.fsf@belgarion.home>
References: <20160527202715.GA4841@roeck-us.net>
 <87a8jah9ok.fsf@belgarion.home> <574A0AD1.9000304@roeck-us.net>
 <87vb1ueo8s.fsf@belgarion.home>
Message-ID: <574DA55E.7070109@roeck-us.net>

On 05/30/2016 11:27 PM, Robert Jarzmik wrote:
> Guenter Roeck <linux at roeck-us.net> writes:
>
>> On 05/28/2016 01:24 AM, Robert Jarzmik wrote:
>>> Guenter Roeck <linux at roeck-us.net> writes:
>>>
>>>> Hi,
>>> I'd rather say that pxa_defconfig doesn't work anymore on any legacy system.
>>> Its first purpose was to ensure compilation coverage of all legacy pxa systems.
>>> Its second one was to have a single kernel bootable on all legacy pxa systems.
>>>
>>> Therefore, would you tell me if the patch in [1] fixes your issue ?
>>>
>>
>> Yes, it does. It is actually the workaround I deployed for my test builds,
>> since I thought that the change was on purpose.
>
> Good. Can I take that as a Tested-by ?
>
Yes.

Guenter



From catalin.marinas at arm.com  Tue May 31 07:55:04 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 15:55:04 +0100
Subject: [PATCH 2/2] arm64: Always provide compat /proc/cpuinfo for 32-bit
 tasks
In-Reply-To: <1464706504-25224-1-git-send-email-catalin.marinas@arm.com>
References: <1464706504-25224-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <1464706504-25224-3-git-send-email-catalin.marinas@arm.com>

Currently, the compat /proc/cpuinfo is provided only if a task has the
PER_LINUX32 personality, either by setting it explicitly or by
inheriting it from the parent task. This is in line with the "uname -m"
behaviour.

However, there are 32-bit user applications making use of the
/proc/cpuinfo and unaware of a need to set the personality. This patch
changes the arm64 /proc/cpuinfo logic to provide the compat information
if the task is 32-bit _or_ the PER_LINUX32 personality is set.

Cc: <stable at vger.kernel.org>
Cc: Arnd Bergmann <arnd at arndb.de>
Cc: Will Deacon <will.deacon at arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---
 arch/arm64/kernel/cpuinfo.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index c173d329397f..bd6a122ea856 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -106,7 +106,8 @@ static const char *const compat_hwcap2_str[] = {
 static int c_show(struct seq_file *m, void *v)
 {
 	int i, j;
-	bool compat = personality(current->personality) == PER_LINUX32;
+	bool compat = is_compat_task() ||
+		personality(current->personality) == PER_LINUX32;
 
 	for_each_online_cpu(i) {
 		struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);


From catalin.marinas at arm.com  Tue May 31 07:55:03 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 15:55:03 +0100
Subject: [PATCH 1/2] arm64: Provide "model name" in /proc/cpuinfo for
 PER_LINUX32 tasks
In-Reply-To: <1464706504-25224-1-git-send-email-catalin.marinas@arm.com>
References: <1464706504-25224-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <1464706504-25224-2-git-send-email-catalin.marinas@arm.com>

This patch brings the PER_LINUX32 /proc/cpuinfo format more in line with
the 32-bit ARM one by providing an additional line:

model name      : ARMv8 Processor rev X (v8l)

Cc: <stable at vger.kernel.org>
Cc: Will Deacon <will.deacon at arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---
 arch/arm64/include/asm/elf.h | 4 ++--
 arch/arm64/kernel/cpuinfo.c  | 8 +++++++-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 7a09c48c0475..579b6e654f2d 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -160,14 +160,14 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 #define STACK_RND_MASK			(0x3ffff >> (PAGE_SHIFT - 12))
 #endif
 
-#ifdef CONFIG_COMPAT
-
 #ifdef __AARCH64EB__
 #define COMPAT_ELF_PLATFORM		("v8b")
 #else
 #define COMPAT_ELF_PLATFORM		("v8l")
 #endif
 
+#ifdef CONFIG_COMPAT
+
 #define COMPAT_ELF_ET_DYN_BASE		(2 * TASK_SIZE_32 / 3)
 
 /* AArch32 registers. */
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 3808470486f3..c173d329397f 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -22,6 +22,8 @@
 
 #include <linux/bitops.h>
 #include <linux/bug.h>
+#include <linux/compat.h>
+#include <linux/elf.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/personality.h>
@@ -104,6 +106,7 @@ static const char *const compat_hwcap2_str[] = {
 static int c_show(struct seq_file *m, void *v)
 {
 	int i, j;
+	bool compat = personality(current->personality) == PER_LINUX32;
 
 	for_each_online_cpu(i) {
 		struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
@@ -115,6 +118,9 @@ static int c_show(struct seq_file *m, void *v)
 		 * "processor".  Give glibc what it expects.
 		 */
 		seq_printf(m, "processor\t: %d\n", i);
+		if (compat)
+			seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
+				   MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
 
 		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
 			   loops_per_jiffy / (500000UL/HZ),
@@ -127,7 +133,7 @@ static int c_show(struct seq_file *m, void *v)
 		 * software which does already (at least for 32-bit).
 		 */
 		seq_puts(m, "Features\t:");
-		if (personality(current->personality) == PER_LINUX32) {
+		if (compat) {
 #ifdef CONFIG_COMPAT
 			for (j = 0; compat_hwcap_str[j]; j++)
 				if (compat_elf_hwcap & (1 << j))


From catalin.marinas at arm.com  Tue May 31 07:55:02 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 15:55:02 +0100
Subject: [PATCH 0/2] arm64: /proc/cpuinfo updates for compat tasks
Message-ID: <1464706504-25224-1-git-send-email-catalin.marinas@arm.com>

The first patch is relatively simple, adding the "model name" line which
is present in the arm32 /proc/cpuinfo.

The second patch is up for discussion. When arm64 support was merged, we
concluded that "uname -m" should report "aarch64" even for compat tasks.
The only way to change the output to "armv8l" was to set the PER_LINUX32
personality (and I think this is in line with x86).

We followed a similar personality approach for /proc/cpuinfo where the
compat one is only exposed if the task sets/inherits PER_LINUX32. The
downside is that apparently some 32-bit applications started making use
of the 64-bit /proc/cpuinfo format. To prevent further spread, I'm
proposing the second patch in this series to force compat /proc/cpuinfo
for 32-bit tasks. This is a departure from the "uname -m" behaviour but
maybe they don't need to be coupled anyway.

Thoughts?

Catalin Marinas (2):
  arm64: Provide "model name" in /proc/cpuinfo for PER_LINUX32 tasks
  arm64: Always provide compat /proc/cpuinfo for 32-bit tasks

 arch/arm64/include/asm/elf.h | 4 ++--
 arch/arm64/kernel/cpuinfo.c  | 9 ++++++++-
 2 files changed, 10 insertions(+), 3 deletions(-)



From mark.rutland at arm.com  Tue May 31 07:57:58 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 15:57:58 +0100
Subject: [PATCH 0/2] arm64: Fix RANDOMIZE_TEXT_OFFSET for !4K kernels
Message-ID: <1464706680-15713-1-git-send-email-mark.rutland@arm.com>

Recently we inadvertently broke RANDOMIZE_TEXT_OFFSET for !4K page
kernels, as we changed the way we map the kernel image. Now, when
TEXT_OFFSET is not a multiple of the kernel page size, we may attempt to
create (block) entries for misaligned addresses, leading to failures at
pagetable creation time.

To avoid this issue, these patches ensure that the TEXT_OFFSET value is
always a multiple of the kernel page size. Doing this requires factoring
PAGE_SHIFT out into Kconfig such that it is available to the awk code
that generates TEXT_OFFSET.

Thanks,
Mark.

Mark Rutland (2):
  arm64: move {PAGE,CONT}_SHIFT into Kconfig
  arm64: fix alignment when RANDOMIZE_TEXT_OFFSET is enabled

 arch/arm64/Kconfig            | 12 ++++++++++++
 arch/arm64/Makefile           |  4 +++-
 arch/arm64/include/asm/page.h | 12 ++----------
 3 files changed, 17 insertions(+), 11 deletions(-)

-- 
1.9.1



From mark.rutland at arm.com  Tue May 31 07:57:59 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 15:57:59 +0100
Subject: [PATCH 1/2] arm64: move {PAGE,CONT}_SHIFT into Kconfig
In-Reply-To: <1464706680-15713-1-git-send-email-mark.rutland@arm.com>
References: <1464706680-15713-1-git-send-email-mark.rutland@arm.com>
Message-ID: <1464706680-15713-2-git-send-email-mark.rutland@arm.com>

In some cases (e.g. the awk for CONFIG_RANDOMIZE_TEXT_OFFSET) we would
like to make use of PAGE_SHIFT outside of code that can include the
usual header files.

Add a new CONFIG_ARM64_PAGE_SHIFT for this, likewise with
ARM64_CONT_SHIFT for consistency.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Sudeep Holla <sudeep.holla at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
---
 arch/arm64/Kconfig            | 12 ++++++++++++
 arch/arm64/include/asm/page.h | 12 ++----------
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 76747d9..5fe3208 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -113,6 +113,18 @@ config ARCH_PHYS_ADDR_T_64BIT
 config MMU
 	def_bool y
 
+config ARM64_PAGE_SHIFT
+	int
+	default 16 if ARM64_64K_PAGES
+	default 14 if ARM64_16K_PAGES
+	default 12
+
+config ARM64_CONT_SHIFT
+	int
+	default 5 if ARM64_64K_PAGES
+	default 7 if ARM64_16K_PAGES
+	default 4
+
 config ARCH_MMAP_RND_BITS_MIN
        default 14 if ARM64_64K_PAGES
        default 16 if ARM64_16K_PAGES
diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h
index 17b45f7..8472c6d 100644
--- a/arch/arm64/include/asm/page.h
+++ b/arch/arm64/include/asm/page.h
@@ -23,16 +23,8 @@
 
 /* PAGE_SHIFT determines the page size */
 /* CONT_SHIFT determines the number of pages which can be tracked together  */
-#ifdef CONFIG_ARM64_64K_PAGES
-#define PAGE_SHIFT		16
-#define CONT_SHIFT		5
-#elif defined(CONFIG_ARM64_16K_PAGES)
-#define PAGE_SHIFT		14
-#define CONT_SHIFT		7
-#else
-#define PAGE_SHIFT		12
-#define CONT_SHIFT		4
-#endif
+#define PAGE_SHIFT		CONFIG_ARM64_PAGE_SHIFT
+#define CONT_SHIFT		CONFIG_ARM64_CONT_SHIFT
 #define PAGE_SIZE		(_AC(1, UL) << PAGE_SHIFT)
 #define PAGE_MASK		(~(PAGE_SIZE-1))
 
-- 
1.9.1



From mark.rutland at arm.com  Tue May 31 07:58:00 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 15:58:00 +0100
Subject: [PATCH 2/2] arm64: fix alignment when RANDOMIZE_TEXT_OFFSET is enabled
In-Reply-To: <1464706680-15713-1-git-send-email-mark.rutland@arm.com>
References: <1464706680-15713-1-git-send-email-mark.rutland@arm.com>
Message-ID: <1464706680-15713-3-git-send-email-mark.rutland@arm.com>

With ARM64_64K_PAGES and RANDOMIZE_TEXT_OFFSET enabled, we hit the
following issue on the boot:

kernel BUG at arch/arm64/mm/mmu.c:480!
Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
Modules linked in:
CPU: 0 PID: 0 Comm: swapper Not tainted 4.6.0 #310
Hardware name: ARM Juno development board (r2) (DT)
task: ffff000008d58a80 ti: ffff000008d30000 task.ti: ffff000008d30000
PC is at map_kernel_segment+0x44/0xb0
LR is at paging_init+0x84/0x5b0
pc : [<ffff000008c450b4>] lr : [<ffff000008c451a4>] pstate: 600002c5

Call trace:
[<ffff000008c450b4>] map_kernel_segment+0x44/0xb0
[<ffff000008c451a4>] paging_init+0x84/0x5b0
[<ffff000008c42728>] setup_arch+0x198/0x534
[<ffff000008c40848>] start_kernel+0x70/0x388
[<ffff000008c401bc>] __primary_switched+0x30/0x74

Commit 7eb90f2ff7e3 ("arm64: cover the .head.text section in the .text
segment mapping") removed the alignment between the .head.text and .text
sections, and used the _text rather than the _stext interval for mapping
the .text segment.

Prior to this commit _stext was always section aligned and didn't cause
any issue even when RANDOMIZE_TEXT_OFFSET was enabled. Since that
alignment has been removed and _text is used to map the .text segment,
we need ensure _text is always page aligned when RANDOMIZE_TEXT_OFFSET
is enabled.

This patch adds logic to TEXT_OFFSET fuzzing to ensure that the offset
is always aligned to the kernel page size. To ensure this, we rely on
the PAGE_SHIFT being available via Kconfig.

Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Reported-by: Sudeep Holla <sudeep.holla at arm.com>
Cc: Ard Biesheuvel <ard.biesheuvel at linaro.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
Fixes: 7eb90f2ff7e3 ("arm64: cover the .head.text section in the .text segment mapping")
---
 arch/arm64/Makefile | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 354d754..7085e32 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -60,7 +60,9 @@ head-y		:= arch/arm64/kernel/head.o
 
 # The byte offset of the kernel image in RAM from the start of RAM.
 ifeq ($(CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET), y)
-TEXT_OFFSET := $(shell awk 'BEGIN {srand(); printf "0x%03x000\n", int(512 * rand())}')
+TEXT_OFFSET := $(shell awk "BEGIN {srand(); printf \"0x%06x\n\", \
+		 int(2 * 1024 * 1024 / (2 ^ $(CONFIG_ARM64_PAGE_SHIFT)) * \
+		 rand()) * (2 ^ $(CONFIG_ARM64_PAGE_SHIFT))}")
 else
 TEXT_OFFSET := 0x00080000
 endif
-- 
1.9.1



From catalin.marinas at arm.com  Tue May 31 08:14:30 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 16:14:30 +0100
Subject: [PATCH 1/3] efi: Introduce *_continue efi_memory_desc iterators
In-Reply-To: <1464707672-21882-1-git-send-email-catalin.marinas@arm.com>
References: <1464707672-21882-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <1464707672-21882-2-git-send-email-catalin.marinas@arm.com>

The for_each_efi_memory_desc_continue() macro and corresponding
"_in_map" allow iterating over an efi_memory_map from a given position.
For code reuse between the existing iterator and the _continue variant,
this patch also introduces efi_memory_desc_next_entry_map().

Cc: Matt Fleming <matt at codeblueprint.co.uk>
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---
 include/linux/efi.h | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/include/linux/efi.h b/include/linux/efi.h
index c2db3ca22217..4b0d880f1cd7 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1002,11 +1002,16 @@ extern int efi_memattr_init(void);
 extern int efi_memattr_apply_permissions(struct mm_struct *mm,
 					 efi_memattr_perm_setter fn);
 
+/* Find next entry in an efi_memory_map or NULL if md is last */
+#define efi_memory_desc_next_entry_map(m, md)				   \
+	((md) == (efi_memory_desc_t *)((m)->map_end - (m)->desc_size)	   \
+	 ? NULL : (void *)(md) + (m)->desc_size)
+
 /* Iterate through an efi_memory_map */
 #define for_each_efi_memory_desc_in_map(m, md)				   \
 	for ((md) = (m)->map;						   \
-	     (md) <= (efi_memory_desc_t *)((m)->map_end - (m)->desc_size); \
-	     (md) = (void *)(md) + (m)->desc_size)
+	     (md);							   \
+	     (md) = efi_memory_desc_next_entry_map(m, md))
 
 /**
  * for_each_efi_memory_desc - iterate over descriptors in efi.memmap
@@ -1017,6 +1022,16 @@ extern int efi_memattr_apply_permissions(struct mm_struct *mm,
 #define for_each_efi_memory_desc(md) \
 	for_each_efi_memory_desc_in_map(&efi.memmap, md)
 
+/* Continue iterating through an efi_memory_map */
+#define for_each_efi_memory_desc_in_map_continue(m, md)			   \
+	for ((md) = efi_memory_desc_next_entry_map(m, md);		   \
+	     (md);							   \
+	     (md) = efi_memory_desc_next_entry_map(m, md))
+
+/* Continue iterating through efi.memmap */
+#define for_each_efi_memory_desc_continue(md) \
+	for_each_efi_memory_desc_in_map_continue(&efi.memmap, md)
+
 /*
  * Format an EFI memory descriptor's type and attributes to a user-provided
  * character buffer, as per snprintf(), and return the buffer.


From catalin.marinas at arm.com  Tue May 31 08:14:32 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 16:14:32 +0100
Subject: [PATCH 3/3] arm64: mm: Remove split_p*d() functions
In-Reply-To: <1464707672-21882-1-git-send-email-catalin.marinas@arm.com>
References: <1464707672-21882-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <1464707672-21882-4-git-send-email-catalin.marinas@arm.com>

Since the efi_create_mapping() no longer generates overlapping regions
and being the last user of the split_p*d code, remove these functions
and the corresponding TLBI.

Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---
 arch/arm64/mm/mmu.c | 47 ++++-------------------------------------------
 1 file changed, 4 insertions(+), 43 deletions(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index c31f796f33ac..00a9e3f64ea9 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -134,24 +134,6 @@ void __strict_break_before_make(pte_t old_pte, pte_t new_pte, const char *info)
 }
 #endif
 
-/*
- * remap a PMD into pages
- */
-static void split_pmd(pmd_t *pmd, pte_t *pte)
-{
-	unsigned long pfn = pmd_pfn(*pmd);
-	int i = 0;
-
-	do {
-		/*
-		 * Need to have the least restrictive permissions available
-		 * permissions will be fixed up later
-		 */
-		set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
-		pfn++;
-	} while (pte++, i++, i < PTRS_PER_PTE);
-}
-
 static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
 				  unsigned long end, unsigned long pfn,
 				  pgprot_t prot,
@@ -159,15 +141,13 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
 {
 	pte_t *pte;
 
-	if (pmd_none(*pmd) || pmd_sect(*pmd)) {
+	BUG_ON(pmd_sect(*pmd));
+	if (pmd_none(*pmd)) {
 		phys_addr_t pte_phys;
 		BUG_ON(!pgtable_alloc);
 		pte_phys = pgtable_alloc();
 		pte = pte_set_fixmap(pte_phys);
-		if (pmd_sect(*pmd))
-			split_pmd(pmd, pte);
 		__pmd_populate(pmd, pte_phys, PMD_TYPE_TABLE);
-		flush_tlb_all();
 		pte_clear_fixmap();
 	}
 	BUG_ON(pmd_bad(*pmd));
@@ -181,18 +161,6 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
 	pte_clear_fixmap();
 }
 
-static void split_pud(pud_t *old_pud, pmd_t *pmd)
-{
-	unsigned long addr = pud_pfn(*old_pud) << PAGE_SHIFT;
-	pgprot_t prot = __pgprot(pud_val(*old_pud) ^ addr);
-	int i = 0;
-
-	do {
-		set_pmd(pmd, __pmd(addr | pgprot_val(prot)));
-		addr += PMD_SIZE;
-	} while (pmd++, i++, i < PTRS_PER_PMD);
-}
-
 #ifdef CONFIG_DEBUG_PAGEALLOC
 static bool block_mappings_allowed(phys_addr_t (*pgtable_alloc)(void))
 {
@@ -223,20 +191,13 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
 	/*
 	 * Check for initial section mappings in the pgd/pud and remove them.
 	 */
-	if (pud_none(*pud) || pud_sect(*pud)) {
+	BUG_ON(pud_sect(*pud));
+	if (pud_none(*pud)) {
 		phys_addr_t pmd_phys;
 		BUG_ON(!pgtable_alloc);
 		pmd_phys = pgtable_alloc();
 		pmd = pmd_set_fixmap(pmd_phys);
-		if (pud_sect(*pud)) {
-			/*
-			 * need to have the 1G of mappings continue to be
-			 * present
-			 */
-			split_pud(pud, pmd);
-		}
 		__pud_populate(pud, pmd_phys, PUD_TYPE_TABLE);
-		flush_tlb_all();
 		pmd_clear_fixmap();
 	}
 	BUG_ON(pud_bad(*pud));


From catalin.marinas at arm.com  Tue May 31 08:14:29 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 16:14:29 +0100
Subject: [PATCH 0/3] arm64: Avoid overlapping EFI regions
Message-ID: <1464707672-21882-1-git-send-email-catalin.marinas@arm.com>

The aim of this series is to avoid the pud/pmd splitting in the arm64
create_pgd_mapping() code. AFAICT, efi_create_mapping() was the last
user to generate overlapping mappings. If I'm mistaken and this is not
the last user, we have to fix the rest as well.

The EFI memory map on my Juno looks like this:

[    0.000000] efi: Processing EFI memory map:
[    0.000000] efi:   0x000008000000-0x00000bffffff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x00001c170000-0x00001c170fff [Memory Mapped I/O  |RUN|  |  |  |  |  |  |   |  |  |  |UC]
[    0.000000] efi:   0x000080000000-0x00008007ffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x000080080000-0x000080d8ffff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x000080d90000-0x00009fdfffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x00009fe00000-0x00009fe0ffff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x00009fe10000-0x0000dfffffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0000e00f0000-0x0000febd5fff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0000febd6000-0x0000febd9fff [ACPI Reclaim Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0000febda000-0x0000febdafff [ACPI Memory NVS    |   |  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0000febdb000-0x0000febdcfff [ACPI Reclaim Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0000febdd000-0x0000feffffff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x000880000000-0x0009f9644fff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009f9645000-0x0009f9646fff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009f9647000-0x0009fa356fff [Loader Code        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009fa357000-0x0009faf6efff [Boot Code          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009faf6f000-0x0009fafa9fff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0009fafaa000-0x0009ff2b1fff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009ff2b2000-0x0009ffb70fff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009ffb71000-0x0009ffb89fff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009ffb8a000-0x0009ffb8dfff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009ffb8e000-0x0009ffb8efff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009ffb8f000-0x0009ffdddfff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009ffdde000-0x0009ffe5ffff [Conventional Memory|   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009ffe60000-0x0009ffe76fff [Loader Data        |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009ffe77000-0x0009fff6dfff [Boot Code          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]
[    0.000000] efi:   0x0009fff6e000-0x0009fffaefff [Runtime Code       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0009fffaf000-0x0009ffffefff [Runtime Data       |RUN|  |  |  |  |  |  |   |WB|WT|WC|UC]*
[    0.000000] efi:   0x0009fffff000-0x0009ffffffff [Boot Data          |   |  |  |  |  |  |  |   |WB|WT|WC|UC]

Catalin Marinas (3):
  efi: Introduce *_continue efi_memory_desc iterators
  arm64: efi: Ensure efi_create_mapping() does not map overlapping
    regions
  arm64: mm: Remove split_p*d() functions

 arch/arm64/kernel/efi.c | 22 +++++++++++++++++++---
 arch/arm64/mm/mmu.c     | 47 ++++-------------------------------------------
 include/linux/efi.h     | 19 +++++++++++++++++--
 3 files changed, 40 insertions(+), 48 deletions(-)



From catalin.marinas at arm.com  Tue May 31 08:14:31 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 16:14:31 +0100
Subject: [PATCH 2/3] arm64: efi: Ensure efi_create_mapping() does not map
 overlapping regions
In-Reply-To: <1464707672-21882-1-git-send-email-catalin.marinas@arm.com>
References: <1464707672-21882-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <1464707672-21882-3-git-send-email-catalin.marinas@arm.com>

Since the EFI page size is 4KB, it is possible for a !4KB page kernel to
align an EFI runtime map boundaries in a way that they can overlap
within the same page. This requires the current create_pgd_mapping()
code to be able to split existing larger mappings when an overlapping
region needs to be mapped.

With this patch, efi_create_mapping() scans the EFI memory map for
overlapping regions and trims the length of the current map to avoid a
large block mapping and subsequent split.

Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---
 arch/arm64/kernel/efi.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 78f52488f9ff..0d5753c31c7f 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -62,10 +62,26 @@ struct screen_info screen_info __section(.data);
 int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
 {
 	pteval_t prot_val = create_mapping_protection(md);
+	phys_addr_t length = md->num_pages << EFI_PAGE_SHIFT;
+	efi_memory_desc_t *next = md;
 
-	create_pgd_mapping(mm, md->phys_addr, md->virt_addr,
-			   md->num_pages << EFI_PAGE_SHIFT,
-			   __pgprot(prot_val | PTE_NG));
+	/*
+	 * Search for the next EFI runtime map and check for any overlap with
+	 * the current map when aligned to PAGE_SIZE. In such case, defer
+	 * mapping the end of the current range until the next
+	 * efi_create_mapping() call.
+	 */
+	for_each_efi_memory_desc_continue(next) {
+		if (!(next->attribute & EFI_MEMORY_RUNTIME))
+			continue;
+		if (next->phys_addr < PAGE_ALIGN(md->phys_addr + length))
+			length -= (md->phys_addr + length) & ~PAGE_MASK;
+		break;
+	}
+
+	if (length)
+		create_pgd_mapping(mm, md->phys_addr, md->virt_addr, length,
+				   __pgprot(prot_val | PTE_NG));
 	return 0;
 }
 


From dinguyen at opensource.altera.com  Tue May 31 09:03:02 2016
From: dinguyen at opensource.altera.com (Dinh Nguyen)
Date: Tue, 31 May 2016 11:03:02 -0500
Subject: [PATCH] ARM: dts: socfpga: Add missing PHY phandle
In-Reply-To: <1464216042-6477-1-git-send-email-marex@denx.de>
References: <1464216042-6477-1-git-send-email-marex@denx.de>
Message-ID: <alpine.DEB.2.02.1605311102320.17588@linux-builds1>

On Wed, 25 May 2016, Marek Vasut wrote:

> Add missing PHY phandle into the DT, otherwise the stmmac code won't
> detect the PHY correctly anymore.
> 
> Signed-off-by: Marek Vasut <marex at denx.de>
> Cc: Dinh Nguyen <dinguyen at opensource.altera.com>
> ---

Applied!

Thanks,
Dinh


From will.deacon at arm.com  Tue May 31 09:16:09 2016
From: will.deacon at arm.com (Will Deacon)
Date: Tue, 31 May 2016 17:16:09 +0100
Subject: [PATCH 1/2] arm64: Provide "model name" in /proc/cpuinfo for
 PER_LINUX32 tasks
In-Reply-To: <1464706504-25224-2-git-send-email-catalin.marinas@arm.com>
References: <1464706504-25224-1-git-send-email-catalin.marinas@arm.com>
 <1464706504-25224-2-git-send-email-catalin.marinas@arm.com>
Message-ID: <20160531161609.GM24936@arm.com>

On Tue, May 31, 2016 at 03:55:03PM +0100, Catalin Marinas wrote:
> This patch brings the PER_LINUX32 /proc/cpuinfo format more in line with
> the 32-bit ARM one by providing an additional line:
> 
> model name      : ARMv8 Processor rev X (v8l)
> 
> Cc: <stable at vger.kernel.org>
> Cc: Will Deacon <will.deacon at arm.com>
> Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
> ---
>  arch/arm64/include/asm/elf.h | 4 ++--
>  arch/arm64/kernel/cpuinfo.c  | 8 +++++++-
>  2 files changed, 9 insertions(+), 3 deletions(-)

Looks good to me:

Acked-by: Will Deacon <will.deacon at arm.com>

Will


From will.deacon at arm.com  Tue May 31 09:18:27 2016
From: will.deacon at arm.com (Will Deacon)
Date: Tue, 31 May 2016 17:18:27 +0100
Subject: [PATCH 2/2] arm64: Always provide compat /proc/cpuinfo for
 32-bit tasks
In-Reply-To: <1464706504-25224-3-git-send-email-catalin.marinas@arm.com>
References: <1464706504-25224-1-git-send-email-catalin.marinas@arm.com>
 <1464706504-25224-3-git-send-email-catalin.marinas@arm.com>
Message-ID: <20160531161827.GN24936@arm.com>

On Tue, May 31, 2016 at 03:55:04PM +0100, Catalin Marinas wrote:
> Currently, the compat /proc/cpuinfo is provided only if a task has the
> PER_LINUX32 personality, either by setting it explicitly or by
> inheriting it from the parent task. This is in line with the "uname -m"
> behaviour.
> 
> However, there are 32-bit user applications making use of the
> /proc/cpuinfo and unaware of a need to set the personality. This patch
> changes the arm64 /proc/cpuinfo logic to provide the compat information
> if the task is 32-bit _or_ the PER_LINUX32 personality is set.
> 
> Cc: <stable at vger.kernel.org>
> Cc: Arnd Bergmann <arnd at arndb.de>
> Cc: Will Deacon <will.deacon at arm.com>
> Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
> ---
>  arch/arm64/kernel/cpuinfo.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
> index c173d329397f..bd6a122ea856 100644
> --- a/arch/arm64/kernel/cpuinfo.c
> +++ b/arch/arm64/kernel/cpuinfo.c
> @@ -106,7 +106,8 @@ static const char *const compat_hwcap2_str[] = {
>  static int c_show(struct seq_file *m, void *v)
>  {
>  	int i, j;
> -	bool compat = personality(current->personality) == PER_LINUX32;
> +	bool compat = is_compat_task() ||
> +		personality(current->personality) == PER_LINUX32;

Hmm, I'm uneasy about this. It feels like an inconsistency with other
things like uname, where we require the personality to be changed explicitly
in order to get the AArch32 interface.

I'd rather go back to changing personality automatically based on the elf
machine, or continue to require that applications be run with the correct
personality (e.g. via linux32). This half way house is just confusing.

Arnd might have more thoughts...

Will


From wens at csie.org  Tue May 31 09:23:18 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed,  1 Jun 2016 00:23:18 +0800
Subject: [PATCH resend v2 0/6] regulator: axp20x: Add support for AXP809 PMIC
Message-ID: <1464711804-19256-1-git-send-email-wens@csie.org>

Hi everyone,

These are the remaining patches of my AXP809 PMIC support series. The
mfd parts and regulator fixes were merged in v4.7-rc1. What's left are
the AXP809 regulator driver and dts changes.

Patch 1 adds AXP809 support to the axp20x regulator driver. This patch
depends on patch 3, and patches already in regulator/topic/axp20x.

Patch 2 adds a dtsi file for AXP809.

Patch 3 enables AXP809 support on the A80 Optimus board.

Patch 4 enables AXP809 support on the Cubieboard 4.

Patch 5 disables the dummy regulators from sunxi-common-regulators.dtsi
on the A80 Optimus board. These aren't used in the board DTS anymore.

Patch 6 disables the dummy regulators from sunxi-common-regulators.dtsi,
on the Cubieboard4. These aren't used in the board DTS anymore.


Chen-Yu Tsai (6):
  regulator: axp20x: support AXP809 variant
  ARM: dts: sunxi: Add dtsi file for AXP809 PMIC
  ARM: dts: sun9i: a80-optimus: Add AXP809 PMIC device node and
    regulators
  ARM: dts: sun9i: cubieboard4: Add AXP809 PMIC device node and
    regulators
  ARM: dts: sun9i: a80-optimus: Disable dummy regulators vcc3v0, vcc3v3,
    vcc5v0
  ARM: dts: sun9i: cubieboard4: Disable dummy regulators vcc3v0, vcc3v3,
    vcc5v0

 .../dts/{sun9i-a80-cubieboard4.dts => axp809.dtsi} |  98 ++------------
 arch/arm/boot/dts/sun9i-a80-cubieboard4.dts        | 143 ++++++++++++++++++++-
 arch/arm/boot/dts/sun9i-a80-optimus.dts            | 143 ++++++++++++++++++++-
 drivers/regulator/axp20x-regulator.c               | 119 ++++++++++++-----
 4 files changed, 380 insertions(+), 123 deletions(-)
 copy arch/arm/boot/dts/{sun9i-a80-cubieboard4.dts => axp809.dtsi} (52%)

-- 
2.8.1



From wens at csie.org  Tue May 31 09:23:20 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed,  1 Jun 2016 00:23:20 +0800
Subject: [PATCH resend v2 2/6] ARM: dts: sunxi: Add dtsi file for AXP809 PMIC
In-Reply-To: <1464711804-19256-1-git-send-email-wens@csie.org>
References: <1464711804-19256-1-git-send-email-wens@csie.org>
Message-ID: <1464711804-19256-3-git-send-email-wens@csie.org>

The AXP809 PMIC is used with the Allwinner A80 SoC, along with
an AXP806 PMIC as a slave.

This patch adds a dtsi file for all the common bindings and default
values unrelated to board design. Currently this is just listing all
the regulator nodes. The regulators are initialized based on their
device node names.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 arch/arm/boot/dts/axp809.dtsi | 53 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 arch/arm/boot/dts/axp809.dtsi

diff --git a/arch/arm/boot/dts/axp809.dtsi b/arch/arm/boot/dts/axp809.dtsi
new file mode 100644
index 000000000000..ab8e5f2d9246
--- /dev/null
+++ b/arch/arm/boot/dts/axp809.dtsi
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2015 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens at csie.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * AXP809 Integrated Power Management Chip
+ */
+
+&axp809 {
+	compatible = "x-powers,axp809";
+	interrupt-controller;
+	#interrupt-cells = <1>;
+};
-- 
2.8.1



From wens at csie.org  Tue May 31 09:23:21 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed,  1 Jun 2016 00:23:21 +0800
Subject: [PATCH resend v2 3/6] ARM: dts: sun9i: a80-optimus: Add AXP809 PMIC
 device node and regulators
In-Reply-To: <1464711804-19256-1-git-send-email-wens@csie.org>
References: <1464711804-19256-1-git-send-email-wens@csie.org>
Message-ID: <1464711804-19256-4-git-send-email-wens@csie.org>

The AXP809 PMIC is the primary PMIC. It provides various supply voltages
for the SoC and other peripherals. The PMIC's interrupt line is
connected to NMI pin of the SoC.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 arch/arm/boot/dts/sun9i-a80-optimus.dts | 131 +++++++++++++++++++++++++++++++-
 1 file changed, 129 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts
index d7a20d92b114..6cfc02194035 100644
--- a/arch/arm/boot/dts/sun9i-a80-optimus.dts
+++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts
@@ -150,7 +150,7 @@
 &mmc0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc0_pins>, <&mmc0_cd_pin_optimus>;
-	vmmc-supply = <&reg_vcc3v0>;
+	vmmc-supply = <&reg_dcdc1>;
 	bus-width = <4>;
 	cd-gpios = <&pio 7 18 GPIO_ACTIVE_HIGH>; /* PH8 */
 	cd-inverted;
@@ -160,7 +160,7 @@
 &mmc2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc2_8bit_pins>;
-	vmmc-supply = <&reg_vcc3v0>;
+	vmmc-supply = <&reg_dcdc1>;
 	bus-width = <8>;
 	non-removable;
 	cap-mmc-hw-reset;
@@ -193,8 +193,135 @@
 
 &r_rsb {
 	status = "okay";
+
+	axp809: pmic at 3a3 {
+		reg = <0x3a3>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		regulators {
+			reg_aldo1: aldo1 {
+				/*
+				 * TODO: This should be handled by the
+				 * USB PHY driver.
+				 */
+				regulator-always-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-name = "vcc33-usbh";
+			};
+
+			reg_aldo2: aldo2 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pb-io-cam";
+			};
+
+			aldo3 {
+				/* unused */
+			};
+
+			reg_dc5ldo: dc5ldo {
+				regulator-always-on;
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-name = "vdd-cpus-09-usbh";
+			};
+
+			reg_dcdc1: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-name = "vcc-3v";
+			};
+
+			reg_dcdc2: dcdc2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-name = "vdd-gpu";
+			};
+
+			reg_dcdc3: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-name = "vdd-cpua";
+			};
+
+			reg_dcdc4: dcdc4 {
+				regulator-always-on;
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-name = "vdd-sys-usb0-hdmi";
+			};
+
+			reg_dcdc5: dcdc5 {
+				regulator-always-on;
+				regulator-min-microvolt = <1425000>;
+				regulator-max-microvolt = <1575000>;
+				regulator-name = "vcc-dram";
+			};
+
+			reg_dldo1: dldo1 {
+				/*
+				 * The WiFi chip supports a wide range
+				 * (3.0 ~ 4.8V) of voltages, and so does
+				 * this regulator (3.0 ~ 4.2V), but
+				 * Allwinner SDK always sets it to 3.3V.
+				 */
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-wifi";
+			};
+
+			reg_dldo2: dldo2 {
+				regulator-always-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-name = "vcc-pl";
+			};
+
+			reg_eldo1: eldo1 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-name = "vcc-dvdd-cam";
+			};
+
+			reg_eldo2: eldo2 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pe";
+			};
+
+			reg_eldo3: eldo3 {
+				regulator-always-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-name = "vcc-pm-codec-io1";
+			};
+
+			reg_ldo_io0: ldo_io0 {
+				regulator-always-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-name = "vcc-pg";
+			};
+
+			reg_ldo_io1: ldo_io1 {
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <2500000>;
+				regulator-name = "vcc-pa-gmac-2v5";
+			};
+
+			reg_rtc_ldo: rtc_ldo {
+				regulator-name = "vcc-rtc-vdd1v8-io";
+			};
+		};
+	};
 };
 
+#include "axp809.dtsi"
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
-- 
2.8.1



From wens at csie.org  Tue May 31 09:23:22 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed,  1 Jun 2016 00:23:22 +0800
Subject: [PATCH resend v2 4/6] ARM: dts: sun9i: cubieboard4: Add AXP809 PMIC
 device node and regulators
In-Reply-To: <1464711804-19256-1-git-send-email-wens@csie.org>
References: <1464711804-19256-1-git-send-email-wens@csie.org>
Message-ID: <1464711804-19256-5-git-send-email-wens@csie.org>

The AXP809 PMIC is the primary PMIC. It provides various supply voltages
for the SoC and other peripherals. The PMIC's interrupt line is connected
to NMI pin of the SoC.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 arch/arm/boot/dts/sun9i-a80-cubieboard4.dts | 131 +++++++++++++++++++++++++++-
 1 file changed, 129 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
index eb2ccd0a3bd5..8d8af1189d87 100644
--- a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
+++ b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
@@ -98,7 +98,7 @@
 &mmc0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc0_pins>, <&mmc0_cd_pin_cubieboard4>;
-	vmmc-supply = <&reg_vcc3v0>;
+	vmmc-supply = <&reg_dcdc1>;
 	bus-width = <4>;
 	cd-gpios = <&pio 7 18 GPIO_ACTIVE_HIGH>; /* PH18 */
 	cd-inverted;
@@ -108,7 +108,7 @@
 &mmc2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc2_8bit_pins>;
-	vmmc-supply = <&reg_vcc3v0>;
+	vmmc-supply = <&reg_dcdc1>;
 	bus-width = <8>;
 	non-removable;
 	cap-mmc-hw-reset;
@@ -126,8 +126,135 @@
 
 &r_rsb {
 	status = "okay";
+
+	axp809: pmic at 3a3 {
+		reg = <0x3a3>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+		regulators {
+			reg_aldo1: aldo1 {
+				/*
+				 * TODO: This should be handled by the
+				 * USB PHY driver.
+				 */
+				regulator-always-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-name = "vcc33-usbh";
+			};
+
+			reg_aldo2: aldo2 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pb-io-cam";
+			};
+
+			aldo3 {
+				/* unused */
+			};
+
+			reg_dc5ldo: dc5ldo {
+				regulator-always-on;
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-name = "vdd-cpus-09-usbh";
+			};
+
+			reg_dcdc1: dcdc1 {
+				regulator-always-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-name = "vcc-3v";
+			};
+
+			reg_dcdc2: dcdc2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-name = "vdd-gpu";
+			};
+
+			reg_dcdc3: dcdc3 {
+				regulator-always-on;
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-name = "vdd-cpua";
+			};
+
+			reg_dcdc4: dcdc4 {
+				regulator-always-on;
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-name = "vdd-sys-usb0-hdmi";
+			};
+
+			reg_dcdc5: dcdc5 {
+				regulator-always-on;
+				regulator-min-microvolt = <1425000>;
+				regulator-max-microvolt = <1575000>;
+				regulator-name = "vcc-dram";
+			};
+
+			reg_dldo1: dldo1 {
+				/*
+				 * The WiFi chip supports a wide range
+				 * (3.0 ~ 4.8V) of voltages, and so does
+				 * this regulator (3.0 ~ 4.2V), but
+				 * Allwinner SDK always sets it to 3.3V.
+				 */
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc-wifi";
+			};
+
+			reg_dldo2: dldo2 {
+				regulator-always-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-name = "vcc-pl";
+			};
+
+			reg_eldo1: eldo1 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-name = "vcc-dvdd-cam";
+			};
+
+			reg_eldo2: eldo2 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc-pe";
+			};
+
+			reg_eldo3: eldo3 {
+				regulator-always-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-name = "vcc-pm-codec-io1";
+			};
+
+			reg_ldo_io0: ldo_io0 {
+				regulator-always-on;
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-name = "vcc-pg";
+			};
+
+			reg_ldo_io1: ldo_io1 {
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <2500000>;
+				regulator-name = "vcc-pa-gmac-2v5";
+			};
+
+			reg_rtc_ldo: rtc_ldo {
+				regulator-name = "vcc-rtc-vdd1v8-io";
+			};
+		};
+	};
 };
 
+#include "axp809.dtsi"
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
-- 
2.8.1



From wens at csie.org  Tue May 31 09:23:19 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed,  1 Jun 2016 00:23:19 +0800
Subject: [PATCH resend v2 1/6] regulator: axp20x: support AXP809 variant
In-Reply-To: <1464711804-19256-1-git-send-email-wens@csie.org>
References: <1464711804-19256-1-git-send-email-wens@csie.org>
Message-ID: <1464711804-19256-2-git-send-email-wens@csie.org>

The X-Powers AXP809 PMIC has a similar set of regulators as the AXP221,
though a few LDOs were removed, and a new switch output added. Like the
AXP221, AXP809 also has DC1SW and DC5LDO, which are internally chained
to DCDC1 and DCDC5, respectively.

Add support for this new variant. Also remove the "axp22x_" prefix from
DC1SW/DC5LDO supply handling code, as the AXP809 uses it as well.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 drivers/regulator/axp20x-regulator.c | 119 ++++++++++++++++++++++++++---------
 1 file changed, 90 insertions(+), 29 deletions(-)

diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 514a5e8fdbab..728be64e817a 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -230,6 +230,61 @@ static const struct regulator_desc axp22x_regulators[] = {
 	AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
 };
 
+static const struct regulator_linear_range axp809_dcdc4_ranges[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2f, 20000),
+	REGULATOR_LINEAR_RANGE(1800000, 0x30, 0x38, 100000),
+};
+
+static const struct regulator_linear_range axp809_dldo1_ranges[] = {
+	REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
+	REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
+};
+
+static const struct regulator_desc axp809_regulators[] = {
+	AXP_DESC(AXP809, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
+		 AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)),
+	AXP_DESC(AXP809, DCDC2, "dcdc2", "vin2", 600, 1540, 20,
+		 AXP22X_DCDC2_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(2)),
+	AXP_DESC(AXP809, DCDC3, "dcdc3", "vin3", 600, 1860, 20,
+		 AXP22X_DCDC3_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(3)),
+	AXP_DESC_RANGES(AXP809, DCDC4, "dcdc4", "vin4", axp809_dcdc4_ranges,
+			57, AXP22X_DCDC4_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1,
+			BIT(4)),
+	AXP_DESC(AXP809, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
+		 AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
+	/* secondary switchable output of DCDC1 */
+	AXP_DESC_SW(AXP809, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
+		    BIT(7)),
+	/* LDO regulator internally chained to DCDC5 */
+	AXP_DESC(AXP809, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
+		 AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
+	AXP_DESC(AXP809, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(6)),
+	AXP_DESC(AXP809, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
+	AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
+	AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp809_dldo1_ranges,
+			32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
+			BIT(3)),
+	AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(4)),
+	AXP_DESC(AXP809, ELDO1, "eldo1", "eldoin", 700, 3300, 100,
+		 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+	AXP_DESC(AXP809, ELDO2, "eldo2", "eldoin", 700, 3300, 100,
+		 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+	AXP_DESC(AXP809, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
+		 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+	AXP_DESC_IO(AXP809, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_IO(AXP809, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_FIXED(AXP809, RTC_LDO, "rtc_ldo", "ips", 1800),
+	AXP_DESC_SW(AXP809, SW, "sw", "swin", AXP22X_PWR_OUT_CTRL2, BIT(6)),
+};
+
 static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
 {
 	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
@@ -245,6 +300,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
 		break;
 	case AXP221_ID:
 	case AXP223_ID:
+	case AXP809_ID:
 		min = 1800;
 		max = 4050;
 		def = 3000;
@@ -324,6 +380,7 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
 
 	case AXP221_ID:
 	case AXP223_ID:
+	case AXP809_ID:
 		if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
 			return -EINVAL;
 
@@ -352,8 +409,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 	};
 	int ret, i, nregulators;
 	u32 workmode;
-	const char *axp22x_dc1_name = axp22x_regulators[AXP22X_DCDC1].name;
-	const char *axp22x_dc5_name = axp22x_regulators[AXP22X_DCDC5].name;
+	const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name;
+	const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name;
 
 	switch (axp20x->variant) {
 	case AXP202_ID:
@@ -366,6 +423,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		regulators = axp22x_regulators;
 		nregulators = AXP22X_REG_ID_MAX;
 		break;
+	case AXP809_ID:
+		regulators = axp809_regulators;
+		nregulators = AXP809_REG_ID_MAX;
+		break;
 	default:
 		dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
 			axp20x->variant);
@@ -388,22 +449,22 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		 * part of this loop to see where we save the DT defined
 		 * name.
 		 */
-		if (regulators == axp22x_regulators) {
-			if (i == AXP22X_DC1SW) {
-				new_desc = devm_kzalloc(&pdev->dev,
-							sizeof(*desc),
-							GFP_KERNEL);
-				*new_desc = regulators[i];
-				new_desc->supply_name = axp22x_dc1_name;
-				desc = new_desc;
-			} else if (i == AXP22X_DC5LDO) {
-				new_desc = devm_kzalloc(&pdev->dev,
-							sizeof(*desc),
-							GFP_KERNEL);
-				*new_desc = regulators[i];
-				new_desc->supply_name = axp22x_dc5_name;
-				desc = new_desc;
-			}
+		if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) ||
+		    (regulators == axp809_regulators && i == AXP809_DC1SW)) {
+			new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
+						GFP_KERNEL);
+			*new_desc = regulators[i];
+			new_desc->supply_name = dcdc1_name;
+			desc = new_desc;
+		}
+
+		if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) ||
+		    (regulators == axp809_regulators && i == AXP809_DC5LDO)) {
+			new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
+						GFP_KERNEL);
+			*new_desc = regulators[i];
+			new_desc->supply_name = dcdc5_name;
+			desc = new_desc;
 		}
 
 		rdev = devm_regulator_register(&pdev->dev, desc, &config);
@@ -426,17 +487,17 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		/*
 		 * Save AXP22X DCDC1 / DCDC5 regulator names for later.
 		 */
-		if (regulators == axp22x_regulators) {
-			/* Can we use rdev->constraints->name instead? */
-			if (i == AXP22X_DCDC1)
-				of_property_read_string(rdev->dev.of_node,
-							"regulator-name",
-							&axp22x_dc1_name);
-			else if (i == AXP22X_DCDC5)
-				of_property_read_string(rdev->dev.of_node,
-							"regulator-name",
-							&axp22x_dc5_name);
-		}
+		if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) ||
+		    (regulators == axp809_regulators && i == AXP809_DCDC1))
+			of_property_read_string(rdev->dev.of_node,
+						"regulator-name",
+						&dcdc1_name);
+
+		if ((regulators == axp22x_regulators && i == AXP22X_DCDC5) ||
+		    (regulators == axp809_regulators && i == AXP809_DCDC5))
+			of_property_read_string(rdev->dev.of_node,
+						"regulator-name",
+						&dcdc5_name);
 	}
 
 	return 0;
-- 
2.8.1



From wens at csie.org  Tue May 31 09:23:23 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed,  1 Jun 2016 00:23:23 +0800
Subject: [PATCH resend v2 5/6] ARM: dts: sun9i: a80-optimus: Disable dummy
 regulators vcc3v0, vcc3v3, vcc5v0
In-Reply-To: <1464711804-19256-1-git-send-email-wens@csie.org>
References: <1464711804-19256-1-git-send-email-wens@csie.org>
Message-ID: <1464711804-19256-6-git-send-email-wens@csie.org>

These 3 regulators are provided in sunxi-common-regulators.dtsi.
3.0V/3.3V and 5.0V are commonly used voltages in Allwinner devices.
These dummy regulators provide a stand-in when bindings that require
one, but the real regulator is not supported yet.

Since these are no longer needed, we can disable them.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 arch/arm/boot/dts/sun9i-a80-optimus.dts | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts
index 6cfc02194035..991337d1d6f1 100644
--- a/arch/arm/boot/dts/sun9i-a80-optimus.dts
+++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts
@@ -322,6 +322,18 @@
 
 #include "axp809.dtsi"
 
+&reg_vcc3v0 {
+	status = "disabled";
+};
+
+&reg_vcc3v3 {
+	status = "disabled";
+};
+
+&reg_vcc5v0 {
+	status = "disabled";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
-- 
2.8.1



From wens at csie.org  Tue May 31 09:23:24 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed,  1 Jun 2016 00:23:24 +0800
Subject: [PATCH resend v2 6/6] ARM: dts: sun9i: cubieboard4: Disable dummy
 regulators vcc3v0, vcc3v3, vcc5v0
In-Reply-To: <1464711804-19256-1-git-send-email-wens@csie.org>
References: <1464711804-19256-1-git-send-email-wens@csie.org>
Message-ID: <1464711804-19256-7-git-send-email-wens@csie.org>

These 3 regulators are provided in sunxi-common-regulators.dtsi.
3.0V/3.3V and 5.0V are commonly used voltages in Allwinner devices.
These dummy regulators provide a stand-in when bindings that require
one, but the real regulator is not supported yet.

Since these are no longer needed, we can disable them.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
---
 arch/arm/boot/dts/sun9i-a80-cubieboard4.dts | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
index 8d8af1189d87..84a12fef5768 100644
--- a/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
+++ b/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
@@ -255,6 +255,18 @@
 
 #include "axp809.dtsi"
 
+&reg_vcc3v0 {
+	status = "disabled";
+};
+
+&reg_vcc3v3 {
+	status = "disabled";
+};
+
+&reg_vcc5v0 {
+	status = "disabled";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
-- 
2.8.1



From will.deacon at arm.com  Tue May 31 09:25:56 2016
From: will.deacon at arm.com (Will Deacon)
Date: Tue, 31 May 2016 17:25:56 +0100
Subject: [PATCH v2 2/4] Documentation: Add documentation for APM X-Gene
 SoC PMU DTS binding
In-Reply-To: <CACgAJHz8bRb6E1xNFwhKpHDGxPhEsQ3J=H_u3woVLgzK0j==Bg@mail.gmail.com>
References: <1460510547-17611-1-git-send-email-ttnguyen@apm.com>
 <1460510547-17611-3-git-send-email-ttnguyen@apm.com>
 <20160418170009.GA15338@rob-hp-laptop>
 <CACgAJHyBbO_LXwtfNVK1f=dY3v1Jfxwxq1dw98EZ0aYdhjPpAg@mail.gmail.com>
 <20160420113121.GE2514@arm.com>
 <20160502205648.GA7374@rob-hp-laptop>
 <CACgAJHyT31DuVNoyRQZVKjv=zM5Fc-EY0gy=y=pHHrBTT+1Xow@mail.gmail.com>
 <CACgAJHyHEOe70pOG2yi-XUQS3BYdGmfYD-yTE0wFM9knDtHOiQ@mail.gmail.com>
 <CACgAJHz8bRb6E1xNFwhKpHDGxPhEsQ3J=H_u3woVLgzK0j==Bg@mail.gmail.com>
Message-ID: <20160531162555.GQ24936@arm.com>

On Tue, May 24, 2016 at 02:12:19PM -0700, Tai Tri Nguyen wrote:
> It's been weeks.
> I just want to ping again if you have any more comments on this patch set?

We seem to have reached a stalemate whereby:

  - The devicetree maintainers don't agree with your binding
  - You don't agree with them
  - I won't merge the patch without their ack

so I guess you either need to try harder to convince them about the
index-based binding, or bite the bullet and fix it to make them happy.

Will


From will.deacon at arm.com  Tue May 31 09:28:34 2016
From: will.deacon at arm.com (Will Deacon)
Date: Tue, 31 May 2016 17:28:34 +0100
Subject: [PATCH 2/3] drivers/perf: arm_pmu: Defer the setting of
 __oprofile_cpu_pmu
In-Reply-To: <1464694883-26298-3-git-send-email-julien.grall@arm.com>
References: <1464694883-26298-1-git-send-email-julien.grall@arm.com>
 <1464694883-26298-3-git-send-email-julien.grall@arm.com>
Message-ID: <20160531162834.GR24936@arm.com>

On Tue, May 31, 2016 at 12:41:22PM +0100, Julien Grall wrote:
> The global variable __oprofile_cpu_pmu is set before the PMU is fully
> initialized. If an error occurs before the end of the initialization,
> the PMU will be freed and the variable will contain an invalid pointer.
> 
> This will result in a kernel crash when perf will be used.
> 
> Fix it by moving the setting of __oprofile_cpu_pmu when the PMU is fully
> initialized (i.e when it is no longer possible to fail).
> 
> Signed-off-by: Julien Grall <julien.grall at arm.com>
> Acked-by: Mark Rutland <mark.rutland at arm.com>
> ---
>  drivers/perf/arm_pmu.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

Should this one go to -stable too?

Will

> diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
> index 6401f0c..95614d2 100644
> --- a/drivers/perf/arm_pmu.c
> +++ b/drivers/perf/arm_pmu.c
> @@ -992,9 +992,6 @@ int arm_pmu_device_probe(struct platform_device *pdev,
>  
>  	armpmu_init(pmu);
>  
> -	if (!__oprofile_cpu_pmu)
> -		__oprofile_cpu_pmu = pmu;
> -
>  	pmu->plat_device = pdev;
>  
>  	if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) {
> @@ -1030,6 +1027,9 @@ int arm_pmu_device_probe(struct platform_device *pdev,
>  	if (ret)
>  		goto out_destroy;
>  
> +	if (!__oprofile_cpu_pmu)
> +		__oprofile_cpu_pmu = pmu;
> +
>  	pr_info("enabled with %s PMU driver, %d counters available\n",
>  			pmu->name, pmu->num_events);
>  
> -- 
> 1.9.1
> 


From catalin.marinas at arm.com  Tue May 31 09:37:40 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 17:37:40 +0100
Subject: [PATCH 2/2] ARM: mm: Fix definition of pmd_mknotpresent
In-Reply-To: <1464712660-25177-1-git-send-email-catalin.marinas@arm.com>
References: <1464712660-25177-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <1464712660-25177-3-git-send-email-catalin.marinas@arm.com>

From: Steve Capper <steve.capper at arm.com>

Currently pmd_mknotpresent will use a zero entry to respresent an
invalidated pmd.

Unfortunately this definition clashes with pmd_none, thus it is
possible for a race condition to occur if zap_pmd_range sees pmd_none
whilst __split_huge_pmd_locked is running too with pmdp_invalidate
just called.

This patch fixes the race condition by modifying pmd_mknotpresent to
create non-zero faulting entries (as is done in other architectures),
removing the ambiguity with pmd_none.

Fixes: 8d9625070073 ("ARM: mm: Transparent huge page support for LPAE systems.")
Cc: <stable at vger.kernel.org> # 3.11+
Reported-by: Kirill A. Shutemov <kirill.shutemov at linux.intel.com>
Acked-by: Will Deacon <will.deacon at arm.com>
Cc: Russell King <linux at armlinux.org.uk>
Signed-off-by: Steve Capper <steve.capper at arm.com>
[catalin.marinas at arm.com: using L_PMD_SECT_VALID instead of PMD_TYPE_SECT]
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---
 arch/arm/include/asm/pgtable-3level.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index 4dce1580bc15..2a029bceaf2f 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -250,10 +250,10 @@ PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
 #define pfn_pmd(pfn,prot)	(__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
 #define mk_pmd(page,prot)	pfn_pmd(page_to_pfn(page),prot)
 
-/* represent a notpresent pmd by zero, this is used by pmdp_invalidate */
+/* represent a notpresent pmd by faulting entry, this is used by pmdp_invalidate */
 static inline pmd_t pmd_mknotpresent(pmd_t pmd)
 {
-	return __pmd(0);
+	return __pmd(pmd_val(pmd) & ~L_PMD_SECT_VALID);
 }
 
 static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)


From catalin.marinas at arm.com  Tue May 31 09:37:38 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 17:37:38 +0100
Subject: [PATCH 0/2] ARM: fix the pmd_mknotpresent definition
Message-ID: <1464712660-25177-1-git-send-email-catalin.marinas@arm.com>

Following discussions on the LKML few months ago:

http://lkml.iu.edu/hypermail/linux/kernel/1602.3/01844.html

we need to adjust the LPAE pmd_mknotpresent() so that it does not clash
with the pmd_none() definition (IOW, we should allow !pmd_none() &&
!pmd_present() after pmd_mknotpresent()). This requires that
pmd_present() checks the L_PMD_SECT_VALID bit instead of a non-zero
value (similar commit for arm64: 5bb1cc0ff9a6 "arm64: Ensure
pmd_present() returns false after pmd_mknotpresent()")

Steve Capper (1):
  ARM: mm: Fix definition of pmd_mknotpresent

Will Deacon (1):
  ARM: mm: ensure pmd_present only checks the valid bit

 arch/arm/include/asm/pgtable-2level.h | 1 +
 arch/arm/include/asm/pgtable-3level.h | 5 +++--
 arch/arm/include/asm/pgtable.h        | 1 -
 3 files changed, 4 insertions(+), 3 deletions(-)



From catalin.marinas at arm.com  Tue May 31 09:37:39 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 17:37:39 +0100
Subject: [PATCH 1/2] ARM: mm: ensure pmd_present only checks the valid bit
In-Reply-To: <1464712660-25177-1-git-send-email-catalin.marinas@arm.com>
References: <1464712660-25177-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <1464712660-25177-2-git-send-email-catalin.marinas@arm.com>

From: Will Deacon <will.deacon at arm.com>

In a subsequent patch, pmd_mknotpresent will clear the valid bit of the
pmd entry, resulting in a not-present entry from the hardware's
perspective. Unfortunately, pmd_present simply checks for a non-zero pmd
value and will therefore continue to return true even after a
pmd_mknotpresent operation. Since pmd_mknotpresent is only used for
managing huge entries, this is only an issue for the 3-level case.

This patch fixes the 3-level pmd_present implementation to take into
account the valid bit. For bisectability, the change is made before the
fix to pmd_mknotpresent.

Fixes: 8d9625070073 ("ARM: mm: Transparent huge page support for LPAE systems.")
Cc: <stable at vger.kernel.org> # 3.11+
Cc: Russell King <linux at armlinux.org.uk>
Cc: Steve Capper <Steve.Capper at arm.com>
Signed-off-by: Will Deacon <will.deacon at arm.com>
[catalin.marinas at arm.com: comment update regarding pmd_mknotpresent patch]
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---
 arch/arm/include/asm/pgtable-2level.h | 1 +
 arch/arm/include/asm/pgtable-3level.h | 1 +
 arch/arm/include/asm/pgtable.h        | 1 -
 3 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h
index aeddd28b3595..92fd2c8a9af0 100644
--- a/arch/arm/include/asm/pgtable-2level.h
+++ b/arch/arm/include/asm/pgtable-2level.h
@@ -193,6 +193,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 
 #define pmd_large(pmd)		(pmd_val(pmd) & 2)
 #define pmd_bad(pmd)		(pmd_val(pmd) & 2)
+#define pmd_present(pmd)	(pmd_val(pmd))
 
 #define copy_pmd(pmdpd,pmdps)		\
 	do {				\
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index fa70db7c714b..4dce1580bc15 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -211,6 +211,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 						: !!(pmd_val(pmd) & (val)))
 #define pmd_isclear(pmd, val)	(!(pmd_val(pmd) & (val)))
 
+#define pmd_present(pmd)	(pmd_isset((pmd), L_PMD_SECT_VALID))
 #define pmd_young(pmd)		(pmd_isset((pmd), PMD_SECT_AF))
 #define pte_special(pte)	(pte_isset((pte), L_PTE_SPECIAL))
 static inline pte_t pte_mkspecial(pte_t pte)
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 348caabb7625..d62204060cbe 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -182,7 +182,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 #define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
 
 #define pmd_none(pmd)		(!pmd_val(pmd))
-#define pmd_present(pmd)	(pmd_val(pmd))
 
 static inline pte_t *pmd_page_vaddr(pmd_t pmd)
 {


From catalin.marinas at arm.com  Tue May 31 09:42:40 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 17:42:40 +0100
Subject: [PATCH 1/2] arm64: Provide "model name" in /proc/cpuinfo for
 PER_LINUX32 tasks
In-Reply-To: <20160531161609.GM24936@arm.com>
References: <1464706504-25224-1-git-send-email-catalin.marinas@arm.com>
 <1464706504-25224-2-git-send-email-catalin.marinas@arm.com>
 <20160531161609.GM24936@arm.com>
Message-ID: <20160531164239.GC11321@e104818-lin.cambridge.arm.com>

On Tue, May 31, 2016 at 05:16:09PM +0100, Will Deacon wrote:
> On Tue, May 31, 2016 at 03:55:03PM +0100, Catalin Marinas wrote:
> > This patch brings the PER_LINUX32 /proc/cpuinfo format more in line with
> > the 32-bit ARM one by providing an additional line:
> > 
> > model name      : ARMv8 Processor rev X (v8l)
> > 
> > Cc: <stable at vger.kernel.org>
> > Cc: Will Deacon <will.deacon at arm.com>
> > Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
> > ---
> >  arch/arm64/include/asm/elf.h | 4 ++--
> >  arch/arm64/kernel/cpuinfo.c  | 8 +++++++-
> >  2 files changed, 9 insertions(+), 3 deletions(-)
> 
> Looks good to me:
> 
> Acked-by: Will Deacon <will.deacon at arm.com>

I guess you can take it as a fix for 4.7.

-- 
Catalin


From robin.murphy at arm.com  Tue May 31 09:45:14 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 31 May 2016 17:45:14 +0100
Subject: [PATCH] drivers: char: mem: Check {read,write}_kmem() addresses
In-Reply-To: <20160531134617.GA11321@e104818-lin.cambridge.arm.com>
References: <5e293c103f0a86f512d71f17091a55e9746e711f.1464698496.git.robin.murphy@arm.com>
 <20160531134617.GA11321@e104818-lin.cambridge.arm.com>
Message-ID: <574DBF9A.3030403@arm.com>

On 31/05/16 14:46, Catalin Marinas wrote:
> On Tue, May 31, 2016 at 01:52:45PM +0100, Robin Murphy wrote:
>> Arriving at read_kmem() with an offset representing a bogus kernel
>> address (e.g. 0 from a simple "cat /dev/kmem") leads to copy_to_user
>> faulting on the kernel-space read.
>>
>> x86_64 happens to get away with this since the optimised implementation
>> uses "rep movs*", thus the user write (which is allowed to fault) and
>> the kernel read are the same instruction, the kernel-side fault falls
>> into the userspace fixup handler and a chain of events transpires
>> leading to returning the expected -EFAULT. On other architectures,
>> though, the read is not covered by the fixup entry for the write, and we
>> get a straightforward "Unable to hande kernel paging request..." dump.
>>
>> The more typical use-case of mmap_kmem() already validates the address
>> with pfn_valid() as one might expect, so let's make that consistent
>> across {read,write}_kem() too.
>>
>> Reported-by: Kefeng Wang <wangkefeng.wang at huawei.com>
>> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
>> ---
>>
>> I'm not sure if this warrants going to stable or not, as it's really
>> just making an existing failure case more graceful and less confusing.
>>
>>   drivers/char/mem.c | 6 ++++++
>>   1 file changed, 6 insertions(+)
>>
>> diff --git a/drivers/char/mem.c b/drivers/char/mem.c
>> index 71025c2f6bbb..64c766023b15 100644
>> --- a/drivers/char/mem.c
>> +++ b/drivers/char/mem.c
>> @@ -384,6 +384,9 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
>>   	char *kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
>>   	int err = 0;
>>
>> +	if (!pfn_valid(PFN_DOWN(p)))
>> +		return -EFAULT;
>> +
>>   	read = 0;
>>   	if (p < (unsigned long) high_memory) {
>>   		low_count = count;
>> @@ -512,6 +515,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf,
>>   	char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
>>   	int err = 0;
>>
>> +	if (!pfn_valid(PFN_DOWN(p)))
>> +		return -EFAULT;
>
> Since the /dev/kmem interface is about kernel virtual address rather
> than physical (like /dev/mem), the pfn may not always be mapped. I think
> a better check would be to use kern_addr_valid(kaddr) just before
> copy_(to|from)_user (a similar approach is taken by read_kcore()). The
> downside is that it breaks a couple of configurations where
> kern_addr_valid() is 0:

Well, the mmap() case, which is arguably the "normal" access method, 
looks to have been enforcing pfn_valid since pretty much forever[1] so I 
struggle to imagine how much anyone will actually care. In my view it's 
more just that "do a silly thing and get an error" seems preferable to 
"do a silly thing and get a scary backtrace".

Robin.

[1]:http://lwn.net/Articles/147901/ - I particularly enjoyed 
"[...]chances are that /dev/kmem will not survive into 2.6.14"

>
> - x86_32 with !CONFIG_FLATMEM
> - alpha with CONFIG_DISCONTIGMEM
>



From catalin.marinas at arm.com  Tue May 31 09:53:11 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Tue, 31 May 2016 17:53:11 +0100
Subject: [PATCH 0/3] arm64: Kill ESR_LNX_EXEC
In-Reply-To: <1464694383-31700-1-git-send-email-mark.rutland@arm.com>
References: <1464694383-31700-1-git-send-email-mark.rutland@arm.com>
Message-ID: <20160531165311.GD11321@e104818-lin.cambridge.arm.com>

On Tue, May 31, 2016 at 12:33:00PM +0100, Mark Rutland wrote:
> Mark Rutland (3):
>   arm64: add macro to extract ESR_ELx.EC
>   arm64/kvm: use ESR_ELx_EC to extract EC
>   arm64: kill ESR_LNX_EXEC

For the series:

Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>


From mark.rutland at arm.com  Tue May 31 09:56:30 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 17:56:30 +0100
Subject: [PATCH v2 2/4] Documentation: Add documentation for APM X-Gene
 SoC PMU DTS binding
In-Reply-To: <CACgAJHyT31DuVNoyRQZVKjv=zM5Fc-EY0gy=y=pHHrBTT+1Xow@mail.gmail.com>
References: <1460510547-17611-1-git-send-email-ttnguyen@apm.com>
 <1460510547-17611-3-git-send-email-ttnguyen@apm.com>
 <20160418170009.GA15338@rob-hp-laptop>
 <CACgAJHyBbO_LXwtfNVK1f=dY3v1Jfxwxq1dw98EZ0aYdhjPpAg@mail.gmail.com>
 <20160420113121.GE2514@arm.com>
 <20160502205648.GA7374@rob-hp-laptop>
 <CACgAJHyT31DuVNoyRQZVKjv=zM5Fc-EY0gy=y=pHHrBTT+1Xow@mail.gmail.com>
Message-ID: <20160531165630.GE4254@leverpostej>

On Mon, May 02, 2016 at 02:46:05PM -0700, Tai Tri Nguyen wrote:
> Hi Rob,
> 
> On Mon, May 2, 2016 at 1:56 PM, Rob Herring <robh at kernel.org> wrote:
> > On Wed, Apr 20, 2016 at 12:31:22PM +0100, Will Deacon wrote:
> >> On Mon, Apr 18, 2016 at 01:04:53PM -0700, Tai Tri Nguyen wrote:
> >> > >> +Required properties for MCB subnode:
> >> > >> +- compatible         : Shall be "apm,xgene-pmu-mcb".
> >> > >> +- reg                        : First resource shall be the MCB PMU resource.
> >> > >> +- index                      : Instance number of the MCB PMU.
> >> > >> +
> >> > >> +Required properties for MC subnode:
> >> > >> +- compatible         : Shall be "apm,xgene-pmu-mc".
> >> > >> +- reg                        : First resource shall be the MC PMU resource.
> >> > >> +- index                      : Instance number of the MC PMU.
> >> > >
> >> > > Don't use indexes. You probably need phandles to the nodes these are
> >> > > related to.
> >> > >
> >> > > How many variations of child nodes do you expect to have? 2, 10, 50? You
> >> > > might want to just collapse all this down to a single node and put this
> >> > > information in the driver if it is fixed for each SoC and there's only a
> >> > > handful.
> >> > >
> >> >
> >> > For each kind of PMU, for example memory controller PMU, I expect to
> >> > have the number of instances up to 8.
> >> > They are actually all independent PMU nodes and have their own CSR memory bases.
> >> > The indexes are used for exposing the devices to perf user only. It
> >> > doesn't have an impact on the programming model.
> >> > Mark also had the same concern.
> >>
> >> Regardless, I'll need an ack from Rob or Mark before I can merge this.
> >
> > I still have a concern with this. Needing an index to expose to the user
> > is generally not a valid reason. That's OS specific and therefore
> > doesn't belong in DT.
> >
> > Rob
> 
> I can use device name here. However, the perf event names will be
> different between DT and ACPI which I want to avoid.
> And the names don't look good at all.
> Also, specifically for MC and MCB PMUs, the indexes are compared
> against the active MC/MCB mask to find out whether they are populated
> or not.
> Without using the index property, I will also need a mapping function
> of physical device addresses and their physical ids.

What's wrong with using ${device}.{physical_address} as the PMU name?
That would be unique and consistent regardless of the firmware, no
mapping nor index property necessary.

That's sufficient for any user already familiar with the topology, a
familiarity you seem to be assuming regardless by not explicitly
describing the topology in the DT.

Thanks,
Mark.


From dianders at chromium.org  Tue May 31 10:03:37 2016
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 31 May 2016 10:03:37 -0700
Subject: [PATCH 2/5] clocksource: rockchip: remove unnecessary clear irq
 before request_irq
In-Reply-To: <574CC839.60608@linaro.org>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
 <1464169802-6033-3-git-send-email-wxt@rock-chips.com>
 <574CC839.60608@linaro.org>
Message-ID: <CAD=FV=U5zqU0CMeg1dDTYHrRqWAxTQO_xk2T7p09GJuj-Fn9Gw@mail.gmail.com>

Hi,

On Mon, May 30, 2016 at 4:09 PM, Daniel Lezcano
<daniel.lezcano at linaro.org> wrote:
> On 05/25/2016 11:49 AM, Caesar Wang wrote:
>>
>> From: Huang Tao <huangtao at rock-chips.com>
>>
>> rk_timer_interrupt_clear and rk_timer_disable is unnecessary before
>> request_irq. Timer should keep disabled before booting Linux.
>
>
> That's true in the perfect world :/ Some version has u-boot letting the
> timer with irq enabled, therefore as soon as request_irq is done, an irq
> fires and leads to a kernel panic.
>
> On the other side, this timer is not used on the other rockchip version than
> rk3399 because of no need of a broadcast timer, so removing these two lines
> may be acceptable.
>
> Can try the changes with another board, eg rk3288 (and forcing to use this
> timer). Can you do the test and confirm it does not break with different
> version of u-boot ?

Actually, I'm not even sure that's true in a perfect world.  ;)  There
are two main problems that might be lurking here:

1. On exynos5 devices I've worked with, the private timer (MCT)
actually shared the same physical counter with the ARM Architected
Timer.  IIRC stopping or resetting the MCT had the effect of stopping
/ resetting the Arch Timer.  Is it the same for you?  As I understand
it the Arch Timer isn't supposed to ever be stopped or reset.  If
firmware left the timer stopped and the kernel happened to be compiled
without support for the Rockchip timer (but had the Arch Timers) then
things would be very broken.  Also the early kernel boot might be
broken if the Arch Timer inits before the Rockchip timer.

NOTE: If your timer and the Arch Timer are totally separate then point
#1 is not important.


2. Historically in Chrome OS there's been an unofficial agreement that
the firmware would start its high speed timer as soon as possible at
bootup and that this could be used to (roughly) measure the time
between the start of firmware and the start of the kernel.  That means
that the kernel was expecting the timer to actually be running when it
started up.  Yup, this is a bit of a hack and I'm not sure it's
terribly well documented, but it does provide a reason that firmware
might have left the timer running.


-Doug


From hch at infradead.org  Tue May 31 10:04:20 2016
From: hch at infradead.org (Christoph Hellwig)
Date: Tue, 31 May 2016 10:04:20 -0700
Subject: [RFC v2] dma-mapping: Use unsigned long for dma_attrs
In-Reply-To: <1464609246-6948-2-git-send-email-k.kozlowski@samsung.com>
References: <1464609246-6948-1-git-send-email-k.kozlowski@samsung.com>
 <1464609246-6948-2-git-send-email-k.kozlowski@samsung.com>
Message-ID: <20160531170420.GB25366@infradead.org>

On Mon, May 30, 2016 at 01:54:06PM +0200, Krzysztof Kozlowski wrote:
> The dma-mapping core and the implementations do not change the
> DMA attributes passed by pointer.  Thus the pointer can point to const
> data.  However the attributes do not have to be a bitfield. Instead
> unsigned long will do fine:
> 
> 1. This is just simpler.  Both in terms of reading the code and setting
>    attributes.  Instead of initializing local attributes on the stack and
>    passing pointer to it to dma_set_attr(), just set the bits.
> 
> 2. It brings safeness and checking for const correctness because the
>    attributes are passed by value.
> 
> Please have in mind that this is RFC, not finished yet.  Only ARM and
> ARM64 are fixed (and not everywhere).
> However other API users also have to be converted which is quite
> intrusive.  I would rather avoid it until the overall approach is
> accepted.

This looks great!  Please continue doing the full conversion.

> +/**
> + * List of possible attributes associated with a DMA mapping. The semantics
> + * of each attribute should be defined in Documentation/DMA-attributes.txt.
> + */
> +#define DMA_ATTR_WRITE_BARRIER		BIT(1)
> +#define DMA_ATTR_WEAK_ORDERING		BIT(2)
> +#define DMA_ATTR_WRITE_COMBINE		BIT(3)
> +#define DMA_ATTR_NON_CONSISTENT		BIT(4)
> +#define DMA_ATTR_NO_KERNEL_MAPPING	BIT(5)
> +#define DMA_ATTR_SKIP_CPU_SYNC		BIT(6)
> +#define DMA_ATTR_FORCE_CONTIGUOUS	BIT(7)
> +#define DMA_ATTR_ALLOC_SINGLE_PAGES	BIT(8)

No really for this patch, but I would much prefer to document them next
to the code in the long run.  Also I really think these BIT() macros
are a distraction compared to the (1 << N) notation.

> +/**
> + * dma_get_attr - check for a specific attribute
> + * @attr: attribute to look for
> + * @attrs: attributes to check within
> + */
> +static inline bool dma_get_attr(unsigned long attr, unsigned long attrs)
> +{
> +	return !!(attr & attrs);
> +}

I'd just kill this helper, much easier to simply open code it in the
caller.


From robin.murphy at arm.com  Tue May 31 10:04:40 2016
From: robin.murphy at arm.com (Robin Murphy)
Date: Tue, 31 May 2016 18:04:40 +0100
Subject: [PATCH v3] arm64: Implement optimised IP checksum helpers
In-Reply-To: <ba9cf5bf84b8adc766f7f7511dda8cb501cd4101.1464693619.git.robin.murphy@arm.com>
References: <ba9cf5bf84b8adc766f7f7511dda8cb501cd4101.1464693619.git.robin.murphy@arm.com>
Message-ID: <4cef631ae5ff455d080cb17c8e0fa918c9a5c067.1464714040.git.robin.murphy@arm.com>

AArch64 is capable of 128-bit memory accesses without alignment
restrictions, which makes it both possible and highly practical to slurp
up a typical 20-byte IP header in just 2 loads. Implement our own
version of ip_fast_checksum() to take advantage of that, resulting in
considerably fewer instructions and memory accesses than the generic
version. We can also get more optimal code generation for csum_fold() by
defining it a slightly different way round from the generic version, so
throw that into the mix too.

Suggested-by: Luke Starrett <luke.starrett at broadcom.com>
Acked-by: Luke Starrett <luke.starrett at broadcom.com>
Signed-off-by: Robin Murphy <robin.murphy at arm.com>
---

v3: Don't generate generic header [James]
v2: Include types.h, add Luke's ack

 arch/arm64/include/asm/Kbuild     |  1 -
 arch/arm64/include/asm/checksum.h | 51 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/checksum.h

diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index cff532a6744e..f43d2c44c765 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -1,6 +1,5 @@
 generic-y += bug.h
 generic-y += bugs.h
-generic-y += checksum.h
 generic-y += clkdev.h
 generic-y += cputime.h
 generic-y += current.h
diff --git a/arch/arm64/include/asm/checksum.h b/arch/arm64/include/asm/checksum.h
new file mode 100644
index 000000000000..09f65339d66d
--- /dev/null
+++ b/arch/arm64/include/asm/checksum.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 ARM 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_CHECKSUM_H
+#define __ASM_CHECKSUM_H
+
+#include <linux/types.h>
+
+static inline __sum16 csum_fold(__wsum csum)
+{
+	u32 sum = (__force u32)csum;
+	sum += (sum >> 16) | (sum << 16);
+	return ~(__force __sum16)(sum >> 16);
+}
+#define csum_fold csum_fold
+
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	__uint128_t tmp;
+	u64 sum;
+
+	tmp = *(const __uint128_t *)iph;
+	iph += 16;
+	ihl -= 4;
+	tmp += ((tmp >> 64) | (tmp << 64));
+	sum = tmp >> 64;
+	do {
+		sum += *(const u32 *)iph;
+		iph += 4;
+	} while (--ihl);
+
+	sum += ((sum >> 32) | (sum << 32));
+	return csum_fold(sum >> 32);
+}
+#define ip_fast_csum ip_fast_csum
+
+#include <asm-generic/checksum.h>
+
+#endif	/* __ASM_CHECKSUM_H */
-- 
2.8.1.dirty



From f.fainelli at gmail.com  Tue May 31 10:09:39 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Tue, 31 May 2016 10:09:39 -0700
Subject: [PATCH v2 0/4] hw rng support for NSP SoC
In-Reply-To: <20160531101934.GM15376@gondor.apana.org.au>
References: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>
 <20160531101934.GM15376@gondor.apana.org.au>
Message-ID: <574DC553.4030009@gmail.com>

On 05/31/2016 03:19 AM, Herbert Xu wrote:
> On Fri, May 27, 2016 at 06:10:37AM -0400, Yendapally Reddy Dhananjaya Reddy wrote:
>> This patchset contains the hw random number generator support for the
>> Broadcom's NSP SoC. The block is similar to the block available in
>> bcm2835 with different default interrupt mask value. Due to lack of
>> documentation, I cannot confirm the interrupt mask register details
>> in bcm2835. In an effort to not break the existing functionality of
>> bcm2835, I used a different compatible string to mask the interrupt
>> for NSP SoC. Please let me know. Also supported providing requested
>> number of random numbers instead of static size of four bytes.
>>
>> The first patch contains the documentation changes and the second patch
>> contains the support for rng available in NSP SoC. The third patch
>> contains the device tree changes for NSP SoC. The fourth patch contains
>> the support for reading requested number of random numbers.
>>
>> This patch set has been tested on NSP bcm958625HR board.
>> This patch set is based on v4.6.0-rc1 and is available from github
>> repo: https://github.com/Broadcom/cygnus-linux.git
>> branch: nsp-rng-v2
>>
>> Changes since v1
> 
> All applied.

FYI, ARM Device Tree patches usually go via ARM SoC pull requests, so it
is best if this is planned in advance. Can you make sure you document
that there could be a merge conflict in your pull request to Linus?

Thanks
-- 
Florian


From maxime.ripard at free-electrons.com  Tue May 31 10:09:57 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Tue, 31 May 2016 19:09:57 +0200
Subject: [linux-sunxi] Re: [PATCH] ARM: dts: sun7i: Add dts file for
 Bananapi M1 Plus board
In-Reply-To: <574CA1ED.8050007@web.de>
References: <20160530123013.11575-1-luoyi.ly@gmail.com>
 <20160530194340.GE4908@lukather> <574CA1ED.8050007@web.de>
Message-ID: <20160531170957.GM4908@lukather>

On Mon, May 30, 2016 at 10:26:21PM +0200, Bernhard Nortmann wrote:
> Am 30.05.2016 um 21:43 schrieb Maxime Ripard:
> >Hi,
> >
> >On Mon, May 30, 2016 at 08:30:13PM +0800, luoyi.ly at gmail.com wrote:
> >>From: luoyi <luoyi.ly at gmail.com>
> >>
> >>Add support for the Bananapi M1 Plus A20 development board from sinovoip.com.cn .
> >>This board features 1G RAM, 2 USB A receptacles, 1 micro USB receptacle for
> >>OTG, 1 micro USB receptacle for power, HDMI, sata, Gbit ethernet, ir receiver,
> >>3.5 mm jack for stero sound out, on board microphone, 40 gpio pins and sdio wifi.
> >What is the difference between the M1+ and the M1?
> 
> The M1+ is an updated version of the original Banana Pi. If you're
> interested in the details, have a look at
> http://linux-sunxi.org/Banana_Pi#Variants .  "BPi-M1+" is SinoVoip's
> counterpart of LeMaker's "Banana Pro", for which a .dts already
> exists. Judging from .fex files, only a single pin assignment seems
> to differ between the two (audio_pa_ctrl, PH26 vs. PH15).

Gee, that's confusing :)

I guess we should just include the banana pro DTB and change that pin
(and the i2s pins Luo was mentionning).

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160531/eba0f737/attachment.sig>

From mathieu.poirier at linaro.org  Tue May 31 10:10:32 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue, 31 May 2016 11:10:32 -0600
Subject: [PATCH 1/2] perf tools: making coresight PMU listable
In-Reply-To: <1464714633-16697-1-git-send-email-mathieu.poirier@linaro.org>
References: <1464714633-16697-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1464714633-16697-2-git-send-email-mathieu.poirier@linaro.org>

Adding the required mechanic allowing 'perf list pmu' to
discover coresight ETM/PTM tracers.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
---
 MAINTAINERS                    |  1 +
 tools/perf/MANIFEST            |  1 +
 tools/perf/arch/arm/util/Build |  2 ++
 tools/perf/arch/arm/util/pmu.c | 34 ++++++++++++++++++++++++++++++++++
 tools/perf/config/Makefile     | 11 ++++++++---
 5 files changed, 46 insertions(+), 3 deletions(-)
 create mode 100644 tools/perf/arch/arm/util/pmu.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7304d2e37a98..d3451007718b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1085,6 +1085,7 @@ F:	drivers/hwtracing/coresight/*
 F:	Documentation/trace/coresight.txt
 F:	Documentation/devicetree/bindings/arm/coresight.txt
 F:	Documentation/ABI/testing/sysfs-bus-coresight-devices-*
+F:	tools/perf/arch/arm/util/pmu.c
 
 ARM/CORGI MACHINE SUPPORT
 M:	Richard Purdie <rpurdie at rpsys.net>
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 8c8c6b9ce915..c6683e60e603 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -64,6 +64,7 @@ include/asm-generic/bitops/const_hweight.h
 include/asm-generic/bitops/fls64.h
 include/asm-generic/bitops/__fls.h
 include/asm-generic/bitops/fls.h
+include/linux/coresight-pmu.h
 include/linux/perf_event.h
 include/linux/list.h
 include/linux/hash.h
diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build
index d22e3d07de3d..66ab0b05549c 100644
--- a/tools/perf/arch/arm/util/Build
+++ b/tools/perf/arch/arm/util/Build
@@ -2,3 +2,5 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o
 
 libperf-$(CONFIG_LIBUNWIND)          += unwind-libunwind.o
 libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
+
+libperf-$(CONFIG_AUXTRACE) += pmu.o
diff --git a/tools/perf/arch/arm/util/pmu.c b/tools/perf/arch/arm/util/pmu.c
new file mode 100644
index 000000000000..af9fb666b44f
--- /dev/null
+++ b/tools/perf/arch/arm/util/pmu.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier at linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * 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 <string.h>
+#include <linux/coresight-pmu.h>
+#include <linux/perf_event.h>
+
+#include "../../util/pmu.h"
+
+struct perf_event_attr
+*perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
+{
+#ifdef HAVE_AUXTRACE_SUPPORT
+	if (!strcmp(pmu->name, CORESIGHT_ETM_PMU_NAME)) {
+		/* add ETM default config here */
+		pmu->selectable = true;
+	}
+#endif
+	return NULL;
+}
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 5ad0255f8756..494a672aa11d 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -681,9 +681,14 @@ ifdef LIBBABELTRACE
 endif
 
 ifndef NO_AUXTRACE
-  ifeq ($(feature-get_cpuid), 0)
-    msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc);
-    NO_AUXTRACE := 1
+  ifeq ($(ARCH),x86)
+    ifeq ($(feature-get_cpuid), 0)
+      msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc);
+      NO_AUXTRACE := 1
+    else
+      $(call detected,CONFIG_AUXTRACE)
+      CFLAGS += -DHAVE_AUXTRACE_SUPPORT
+    endif
   else
     $(call detected,CONFIG_AUXTRACE)
     CFLAGS += -DHAVE_AUXTRACE_SUPPORT
-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May 31 10:10:31 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue, 31 May 2016 11:10:31 -0600
Subject: [PATCH 0/2] perf tools: coresight PMU recording capabilities 
Message-ID: <1464714633-16697-1-git-send-email-mathieu.poirier@linaro.org>

Good day Arnaldo,

If you recal we had a discussion about the code submitted in this set back in
February[1].  At the time we agreed it would be better to wait until the 
decoding library is available, allowing people to test the solution.  

That library is now out and accessible by anyone[2] - branch "opencsd-0v002"
is stable and the one we advise to use.  Part of that branch is a "HOWTO.md"
that describes how to perform on-target trace acquisition, along with how to
setup the library and perf tools for off system trace decoding. 

The patches in this set can also be found on gitHub[2], branch
"perf-opencsd-4.7-rc1".  Available there are many more patches that will be
submitted for review incrementally.

Everything works on mainline v4.7-rc1.  I will be happy to change the baseline
should this prove to be easier for your to review.  Note that 2/2 has already
been acked by Adrian Hunter but submitted here without the usual mention since
the code has change a little.

To conclude, here are a couple of pastebins for you to look at if you don't want
to go through the whole process of setting up the solution:

$ perf report --stdio -D [3]
$ perf report --stdio [4] 

And a snippet of the output from the "cs-etm-disasem.py" script, also included
on branch "perf-opencsd-4.7-rc1":

FILE: /lib/aarch64-linux-gnu/ld-2.21.so CPU: 3
          7fab57fd80:   910003e0        mov     x0, sp
          7fab57fd84:   94000d53        bl      7fab5832d0 <free at plt+0x3790>
FILE: /lib/aarch64-linux-gnu/ld-2.21.so CPU: 3
          7fab5832d0:   d11203ff        sub     sp, sp, #0x480
FILE: /lib/aarch64-linux-gnu/ld-2.21.so CPU: 3
          7fab5832d4:   a9ba7bfd        stp     x29, x30, [sp,#-96]!
          7fab5832d8:   910003fd        mov     x29, sp
          7fab5832dc:   a90363f7        stp     x23, x24, [sp,#48]
          7fab5832e0:   9101e3b7        add     x23, x29, #0x78
          7fab5832e4:   a90573fb        stp     x27, x28, [sp,#80]
          7fab5832e8:   a90153f3        stp     x19, x20, [sp,#16]
          7fab5832ec:   aa0003fb        mov     x27, x0
          7fab5832f0:   910a82e1        add     x1, x23, #0x2a0
          7fab5832f4:   a9025bf5        stp     x21, x22, [sp,#32]
          7fab5832f8:   a9046bf9        stp     x25, x26, [sp,#64]
          7fab5832fc:   910102e0        add     x0, x23, #0x40
          7fab583300:   f800841f        str     xzr, [x0],#8
          7fab583304:   eb01001f        cmp     x0, x1
          7fab583308:   54ffffc1        b.ne    7fab583300 <free at plt+0x37c0>
FILE: /lib/aarch64-linux-gnu/ld-2.21.so CPU: 3
          7fab583300:   f800841f        str     xzr, [x0],#8
          7fab583304:   eb01001f        cmp     x0, x1
          7fab583308:   54ffffc1        b.ne    7fab583300 <free at plt+0x37c0>
FILE: /lib/aarch64-linux-gnu/ld-2.21.so CPU: 3
          7fab583300:   f800841f        str     xzr, [x0],#8
          7fab583304:   eb01001f        cmp     x0, x1
          7fab583308:   54ffffc1        b.ne    7fab583300 <free at plt+0x37c0>
...
...

Regards,
Mathieu

[1]. http://lists.infradead.org/pipermail/linux-arm-kernel/2016-February/404232.html
[2]. https://github.com/Linaro/OpenCSD/ 
[3]. http://pastebin.com/u9tgdwjF
[4]. http://pastebin.com/V9N3bnEq

Mathieu Poirier (2):
  perf tools: making coresight PMU listable
  perf tools: adding coresight etm PMU record capabilities

 MAINTAINERS                         |   4 +
 tools/perf/MANIFEST                 |   1 +
 tools/perf/arch/arm/util/Build      |   2 +
 tools/perf/arch/arm/util/auxtrace.c |  54 ++++
 tools/perf/arch/arm/util/cs-etm.c   | 559 ++++++++++++++++++++++++++++++++++++
 tools/perf/arch/arm/util/cs-etm.h   |  23 ++
 tools/perf/arch/arm/util/pmu.c      |  34 +++
 tools/perf/arch/arm64/util/Build    |   4 +
 tools/perf/config/Makefile          |  11 +-
 tools/perf/util/auxtrace.c          |   1 +
 tools/perf/util/auxtrace.h          |   1 +
 tools/perf/util/cs-etm.h            |  74 +++++
 12 files changed, 765 insertions(+), 3 deletions(-)
 create mode 100644 tools/perf/arch/arm/util/auxtrace.c
 create mode 100644 tools/perf/arch/arm/util/cs-etm.c
 create mode 100644 tools/perf/arch/arm/util/cs-etm.h
 create mode 100644 tools/perf/arch/arm/util/pmu.c
 create mode 100644 tools/perf/util/cs-etm.h

-- 
2.5.0



From mathieu.poirier at linaro.org  Tue May 31 10:10:33 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue, 31 May 2016 11:10:33 -0600
Subject: [PATCH 2/2] perf tools: adding coresight etm PMU record capabilities
In-Reply-To: <1464714633-16697-1-git-send-email-mathieu.poirier@linaro.org>
References: <1464714633-16697-1-git-send-email-mathieu.poirier@linaro.org>
Message-ID: <1464714633-16697-3-git-send-email-mathieu.poirier@linaro.org>

Coresight ETMs are IP blocks used to perform HW assisted tracing
on a CPU core.  This patch introduce the required auxiliary API
functions allowing the perf core to interact with a tracer.

Signed-off-by: Mathieu Poirier <mathieu.poirier at linaro.org>
---
 MAINTAINERS                         |   3 +
 tools/perf/arch/arm/util/Build      |   2 +-
 tools/perf/arch/arm/util/auxtrace.c |  54 ++++
 tools/perf/arch/arm/util/cs-etm.c   | 559 ++++++++++++++++++++++++++++++++++++
 tools/perf/arch/arm/util/cs-etm.h   |  23 ++
 tools/perf/arch/arm64/util/Build    |   4 +
 tools/perf/util/auxtrace.c          |   1 +
 tools/perf/util/auxtrace.h          |   1 +
 tools/perf/util/cs-etm.h            |  74 +++++
 9 files changed, 720 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/arch/arm/util/auxtrace.c
 create mode 100644 tools/perf/arch/arm/util/cs-etm.c
 create mode 100644 tools/perf/arch/arm/util/cs-etm.h
 create mode 100644 tools/perf/util/cs-etm.h

diff --git a/MAINTAINERS b/MAINTAINERS
index d3451007718b..4fa03b03bfc5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1086,6 +1086,9 @@ F:	Documentation/trace/coresight.txt
 F:	Documentation/devicetree/bindings/arm/coresight.txt
 F:	Documentation/ABI/testing/sysfs-bus-coresight-devices-*
 F:	tools/perf/arch/arm/util/pmu.c
+F:	tools/perf/arch/arm/util/auxtrace.c
+F:	tools/perf/arch/arm/util/cs_etm.c
+F:	tools/perf/arch/arm/util/cs_etm.h
 
 ARM/CORGI MACHINE SUPPORT
 M:	Richard Purdie <rpurdie at rpsys.net>
diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build
index 66ab0b05549c..71de3fc40502 100644
--- a/tools/perf/arch/arm/util/Build
+++ b/tools/perf/arch/arm/util/Build
@@ -3,4 +3,4 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o
 libperf-$(CONFIG_LIBUNWIND)          += unwind-libunwind.o
 libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
 
-libperf-$(CONFIG_AUXTRACE) += pmu.o
+libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs-etm.o
diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c
new file mode 100644
index 000000000000..95c38b683159
--- /dev/null
+++ b/tools/perf/arch/arm/util/auxtrace.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier at linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * 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 <stdbool.h>
+#include <linux/coresight-pmu.h>
+
+#include "../../util/auxtrace.h"
+#include "../../util/evlist.h"
+#include "../../util/pmu.h"
+#include "cs-etm.h"
+
+struct auxtrace_record
+*auxtrace_record__init(struct perf_evlist *evlist, int *err)
+{
+	struct perf_pmu	*cs_etm_pmu;
+	struct perf_evsel *evsel;
+	bool found_etm = false;
+
+	cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME);
+
+	if (evlist) {
+		evlist__for_each(evlist, evsel) {
+			if (cs_etm_pmu &&
+			    evsel->attr.type == cs_etm_pmu->type)
+				found_etm = true;
+		}
+	}
+
+	if (found_etm)
+		return cs_etm_record_init(err);
+
+	/*
+	 * Clear 'err' even if we haven't found a cs_etm event - that way perf
+	 * record can still be used even if tracers aren't present.  The NULL
+	 * return value will take care of telling the infrastructure HW tracing
+	 * isn't available.
+	 */
+	*err = 0;
+	return NULL;
+}
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
new file mode 100644
index 000000000000..57f488f59438
--- /dev/null
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier at linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * 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 <api/fs/fs.h>
+#include <linux/bitops.h>
+#include <linux/coresight-pmu.h>
+#include <linux/kernel.h>
+#include <linux/log2.h>
+#include <linux/types.h>
+
+#include "cs-etm.h"
+#include "../../perf.h"
+#include "../../util/auxtrace.h"
+#include "../../util/cpumap.h"
+#include "../../util/evlist.h"
+#include "../../util/pmu.h"
+#include "../../util/thread_map.h"
+#include "../../util/cs-etm.h"
+
+#include <stdlib.h>
+
+struct cs_etm_recording {
+	struct auxtrace_record	itr;
+	struct perf_pmu		*cs_etm_pmu;
+	struct perf_evlist	*evlist;
+	bool			snapshot_mode;
+	size_t			snapshot_size;
+};
+
+static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu);
+
+static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr,
+					 struct record_opts *opts,
+					 const char *str)
+{
+	struct cs_etm_recording *ptr =
+				container_of(itr, struct cs_etm_recording, itr);
+	unsigned long long snapshot_size = 0;
+	char *endptr;
+
+	if (str) {
+		snapshot_size = strtoull(str, &endptr, 0);
+		if (*endptr || snapshot_size > SIZE_MAX)
+			return -1;
+	}
+
+	opts->auxtrace_snapshot_mode = true;
+	opts->auxtrace_snapshot_size = snapshot_size;
+	ptr->snapshot_size = snapshot_size;
+
+	return 0;
+}
+
+static int cs_etm_recording_options(struct auxtrace_record *itr,
+				    struct perf_evlist *evlist,
+				    struct record_opts *opts)
+{
+	struct cs_etm_recording *ptr =
+				container_of(itr, struct cs_etm_recording, itr);
+	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
+	struct perf_evsel *evsel, *cs_etm_evsel = NULL;
+	const struct cpu_map *cpus = evlist->cpus;
+	bool privileged = (geteuid() == 0 || perf_event_paranoid() < 0);
+
+	ptr->evlist = evlist;
+	ptr->snapshot_mode = opts->auxtrace_snapshot_mode;
+
+	evlist__for_each(evlist, evsel) {
+		if (evsel->attr.type == cs_etm_pmu->type) {
+			if (cs_etm_evsel) {
+				pr_err("There may be only one %s event\n",
+				       CORESIGHT_ETM_PMU_NAME);
+				return -EINVAL;
+			}
+			evsel->attr.freq = 0;
+			evsel->attr.sample_period = 1;
+			cs_etm_evsel = evsel;
+			opts->full_auxtrace = true;
+		}
+	}
+
+	/* no need to continue if at least one event of interest was found */
+	if (!cs_etm_evsel)
+		return 0;
+
+	if (opts->use_clockid) {
+		pr_err("Cannot use clockid (-k option) with %s\n",
+		       CORESIGHT_ETM_PMU_NAME);
+		return -EINVAL;
+	}
+
+	/* we are in snapshot mode */
+	if (opts->auxtrace_snapshot_mode) {
+		/*
+		 * No size were given to '-S' or '-m,', so go with
+		 * the default
+		 */
+		if (!opts->auxtrace_snapshot_size &&
+		    !opts->auxtrace_mmap_pages) {
+			if (privileged) {
+				opts->auxtrace_mmap_pages = MiB(4) / page_size;
+			} else {
+				opts->auxtrace_mmap_pages =
+							KiB(128) / page_size;
+				if (opts->mmap_pages == UINT_MAX)
+					opts->mmap_pages = KiB(256) / page_size;
+			}
+		} else if (!opts->auxtrace_mmap_pages && !privileged &&
+						opts->mmap_pages == UINT_MAX) {
+			opts->mmap_pages = KiB(256) / page_size;
+		}
+
+		/*
+		 * '-m,xyz' was specified but no snapshot size, so make the
+		 * snapshot size as big as the auxtrace mmap area.
+		 */
+		if (!opts->auxtrace_snapshot_size) {
+			opts->auxtrace_snapshot_size =
+				opts->auxtrace_mmap_pages * (size_t)page_size;
+		}
+
+		/*
+		 * -Sxyz was specified but no auxtrace mmap area, so make the
+		 * auxtrace mmap area big enough to fit the requested snapshot
+		 * size.
+		 */
+		if (!opts->auxtrace_mmap_pages) {
+			size_t sz = opts->auxtrace_snapshot_size;
+
+			sz = round_up(sz, page_size) / page_size;
+			opts->auxtrace_mmap_pages = roundup_pow_of_two(sz);
+		}
+
+		/* Snapshost size can't be bigger than the auxtrace area */
+		if (opts->auxtrace_snapshot_size >
+				opts->auxtrace_mmap_pages * (size_t)page_size) {
+			pr_err("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n",
+			       opts->auxtrace_snapshot_size,
+			       opts->auxtrace_mmap_pages * (size_t)page_size);
+			return -EINVAL;
+		}
+
+		/* Something went wrong somewhere - this shouldn't happen */
+		if (!opts->auxtrace_snapshot_size ||
+		    !opts->auxtrace_mmap_pages) {
+			pr_err("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n");
+			return -EINVAL;
+		}
+	}
+
+	/* We are in full trace mode but '-m,xyz' wasn't specified */
+	if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) {
+		if (privileged) {
+			opts->auxtrace_mmap_pages = MiB(4) / page_size;
+		} else {
+			opts->auxtrace_mmap_pages = KiB(128) / page_size;
+			if (opts->mmap_pages == UINT_MAX)
+				opts->mmap_pages = KiB(256) / page_size;
+		}
+
+	}
+
+	/* Validate auxtrace_mmap_pages provided by user */
+	if (opts->auxtrace_mmap_pages) {
+		unsigned int max_page = (KiB(128) / page_size);
+		size_t sz = opts->auxtrace_mmap_pages * (size_t)page_size;
+
+		if (!privileged &&
+		    opts->auxtrace_mmap_pages > max_page) {
+			opts->auxtrace_mmap_pages = max_page;
+			pr_err("auxtrace too big, truncating to %d\n",
+			       max_page);
+		}
+
+		if (!is_power_of_2(sz)) {
+			pr_err("Invalid mmap size for %s: must be a power of 2\n",
+			       CORESIGHT_ETM_PMU_NAME);
+			return -EINVAL;
+		}
+	}
+
+	if (opts->auxtrace_snapshot_mode)
+		pr_debug2("%s snapshot size: %zu\n", CORESIGHT_ETM_PMU_NAME,
+			  opts->auxtrace_snapshot_size);
+
+	if (cs_etm_evsel) {
+		/*
+		 * To obtain the auxtrace buffer file descriptor, the auxtrace
+		 * event must come first.
+		 */
+		perf_evlist__to_front(evlist, cs_etm_evsel);
+		/*
+		 * In the case of per-cpu mmaps, we need the CPU on the
+		 * AUX event.
+		 */
+		if (!cpu_map__empty(cpus))
+			perf_evsel__set_sample_bit(cs_etm_evsel, CPU);
+	}
+
+	/* Add dummy event to keep tracking */
+	if (opts->full_auxtrace) {
+		struct perf_evsel *tracking_evsel;
+		int err;
+
+		err = parse_events(evlist, "dummy:u", NULL);
+		if (err)
+			return err;
+
+		tracking_evsel = perf_evlist__last(evlist);
+		perf_evlist__set_tracking_event(evlist, tracking_evsel);
+
+		tracking_evsel->attr.freq = 0;
+		tracking_evsel->attr.sample_period = 1;
+
+		/* In per-cpu case, always need the time of mmap events etc */
+		if (!cpu_map__empty(cpus))
+			perf_evsel__set_sample_bit(tracking_evsel, TIME);
+	}
+
+	return 0;
+}
+
+static u64 cs_etm_get_config(struct auxtrace_record *itr)
+{
+	u64 config = 0;
+	struct cs_etm_recording *ptr =
+			container_of(itr, struct cs_etm_recording, itr);
+	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
+	struct perf_evlist *evlist = ptr->evlist;
+	struct perf_evsel *evsel;
+
+	evlist__for_each(evlist, evsel) {
+		if (evsel->attr.type == cs_etm_pmu->type) {
+			/*
+			 * Variable perf_event_attr::config is assigned to
+			 * ETMv3/PTM.  The bit fields have been made to match
+			 * the ETMv3.5 ETRMCR register specification.  See the
+			 * PMU_FORMAT_ATTR() declarations in
+			 * drivers/hwtracing/coresight/coresight-perf.c for
+			 * details.
+			 */
+			config = evsel->attr.config;
+			break;
+		}
+	}
+
+	return config;
+}
+
+static size_t
+cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
+		      struct perf_evlist *evlist __maybe_unused)
+{
+	int i;
+	int etmv3 = 0, etmv4 = 0;
+	const struct cpu_map *cpus = evlist->cpus;
+
+	/* cpu map is not empty, we have specific CPUs to work with */
+	if (!cpu_map__empty(cpus)) {
+		for (i = 0; i < cpu_map__nr(cpus); i++) {
+			if (cs_etm_is_etmv4(itr, cpus->map[i]))
+				etmv4++;
+			else
+				etmv3++;
+		}
+	} else {
+		/* get configuration for all CPUs in the system */
+		for (i = 0; i < cpu__max_cpu(); i++) {
+			if (cs_etm_is_etmv4(itr, i))
+				etmv4++;
+			else
+				etmv3++;
+		}
+	}
+
+	return (CS_ETM_HEADER_SIZE +
+	       (etmv4 * CS_ETMV4_PRIV_SIZE) +
+	       (etmv3 * CS_ETMV3_PRIV_SIZE));
+}
+
+static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX] = {
+	[CS_ETM_ETMCCER]	= "mgmt/etmccer",
+	[CS_ETM_ETMIDR]		= "mgmt/etmidr",
+};
+
+static const char *metadata_etmv4_ro[CS_ETMV4_PRIV_MAX] = {
+	[CS_ETMV4_TRCIDR0]		= "trcidr/trcidr0",
+	[CS_ETMV4_TRCIDR1]		= "trcidr/trcidr1",
+	[CS_ETMV4_TRCIDR2]		= "trcidr/trcidr2",
+	[CS_ETMV4_TRCIDR8]		= "trcidr/trcidr8",
+	[CS_ETMV4_TRCAUTHSTATUS]	= "mgmt/trcauthstatus",
+};
+
+static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu)
+{
+	bool ret = false;
+	char path[PATH_MAX];
+	int scan;
+	unsigned int val;
+	struct cs_etm_recording *ptr =
+			container_of(itr, struct cs_etm_recording, itr);
+	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
+
+	/* Take any of the RO files for ETMv4 and see if it present */
+	snprintf(path, PATH_MAX, "cpu%d/%s",
+		 cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
+	scan = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
+
+	/* The file was read successfully, we have a winner */
+	if (scan == 1)
+		ret = true;
+
+	return ret;
+}
+
+static int cs_etm_get_ro(struct perf_pmu *pmu, int cpu, const char *path)
+{
+	char pmu_path[PATH_MAX];
+	int scan;
+	unsigned int val = 0;
+
+	/* Get RO metadata from sysfs */
+	snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu, path);
+
+	scan = perf_pmu__scan_file(pmu, pmu_path, "%x", &val);
+	if (scan != 1)
+		pr_err("%s: error reading: %s\n", __func__, pmu_path);
+
+	return val;
+}
+
+static void cs_etm_get_metadata(int cpu, u32 *offset,
+				struct auxtrace_record *itr,
+				struct auxtrace_info_event *info)
+{
+	u32 increment;
+	u64 magic;
+	struct cs_etm_recording *ptr =
+			container_of(itr, struct cs_etm_recording, itr);
+	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
+
+	/* first see what kind of tracer this cpu is affined to */
+	if (cs_etm_is_etmv4(itr, cpu)) {
+		magic = __perf_cs_etmv4_magic;
+		/* Get trace configuration register */
+		info->priv[*offset + CS_ETMV4_TRCCONFIGR] =
+						cs_etm_get_config(itr);
+		/* Get traceID from the framework */
+		info->priv[*offset + CS_ETMV4_TRCTRACEIDR] =
+						coresight_get_trace_id(cpu);
+		/* Get read-only information from sysFS */
+		info->priv[*offset + CS_ETMV4_TRCIDR0] =
+			cs_etm_get_ro(cs_etm_pmu, cpu,
+				      metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
+		info->priv[*offset + CS_ETMV4_TRCIDR1] =
+			cs_etm_get_ro(cs_etm_pmu, cpu,
+				      metadata_etmv4_ro[CS_ETMV4_TRCIDR1]);
+		info->priv[*offset + CS_ETMV4_TRCIDR2] =
+			cs_etm_get_ro(cs_etm_pmu, cpu,
+				      metadata_etmv4_ro[CS_ETMV4_TRCIDR2]);
+		info->priv[*offset + CS_ETMV4_TRCIDR8] =
+			cs_etm_get_ro(cs_etm_pmu, cpu,
+				      metadata_etmv4_ro[CS_ETMV4_TRCIDR8]);
+		info->priv[*offset + CS_ETMV4_TRCAUTHSTATUS] =
+			cs_etm_get_ro(cs_etm_pmu, cpu,
+				      metadata_etmv4_ro
+				      [CS_ETMV4_TRCAUTHSTATUS]);
+
+		/* How much space was used */
+		increment = CS_ETMV4_PRIV_MAX;
+	} else {
+		magic = __perf_cs_etmv3_magic;
+		/* Get configuration register */
+		info->priv[*offset + CS_ETM_ETMCR] = cs_etm_get_config(itr);
+		/* Get traceID from the framework */
+		info->priv[*offset + CS_ETM_ETMTRACEIDR] =
+						coresight_get_trace_id(cpu);
+		/* Get read-only information from sysFS */
+		info->priv[*offset + CS_ETM_ETMCCER] =
+			cs_etm_get_ro(cs_etm_pmu, cpu,
+				      metadata_etmv3_ro[CS_ETM_ETMCCER]);
+		info->priv[*offset + CS_ETM_ETMIDR] =
+			cs_etm_get_ro(cs_etm_pmu, cpu,
+				      metadata_etmv3_ro[CS_ETM_ETMIDR]);
+
+		/* How much space was used */
+		increment = CS_ETM_PRIV_MAX;
+	}
+
+	/* Build generic header portion */
+	info->priv[*offset + CS_ETM_MAGIC] = magic;
+	info->priv[*offset + CS_ETM_CPU] = cpu;
+	/* Where the next CPU entry should start from */
+	*offset += increment;
+}
+
+static int cs_etm_info_fill(struct auxtrace_record *itr,
+			    struct perf_session *session,
+			    struct auxtrace_info_event *info,
+			    size_t priv_size)
+{
+	int i;
+	u32 offset;
+	u64 nr_cpu, type;
+	const struct cpu_map *cpus = session->evlist->cpus;
+	struct cs_etm_recording *ptr =
+			container_of(itr, struct cs_etm_recording, itr);
+	struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
+
+	if (priv_size != cs_etm_info_priv_size(itr, session->evlist))
+		return -EINVAL;
+
+	if (!session->evlist->nr_mmaps)
+		return -EINVAL;
+
+	/* If the cpu_map is empty all CPUs are involved */
+	nr_cpu = cpu_map__empty(cpus) ? cpu__max_cpu() : cpu_map__nr(cpus);
+	/* Get PMU type as dynamically assigned by the core */
+	type = cs_etm_pmu->type;
+
+	/* First fill out the session header */
+	info->type = PERF_AUXTRACE_CS_ETM;
+	info->priv[CS_HEADER_VERSION_0] = 0;
+	info->priv[CS_PMU_TYPE_CPUS] = type << 32;
+	info->priv[CS_PMU_TYPE_CPUS] |= nr_cpu;
+	info->priv[CS_ETM_SNAPSHOT] = ptr->snapshot_mode;
+
+	offset = CS_ETM_SNAPSHOT + 1;
+
+	/* cpu map is not empty, we have specific CPUs to work with */
+	if (!cpu_map__empty(cpus)) {
+		for (i = 0; i < cpu_map__nr(cpus) && offset < priv_size; i++)
+			cs_etm_get_metadata(cpus->map[i], &offset, itr, info);
+	} else {
+		/* get configuration for all CPUs in the system */
+		for (i = 0; i < cpu__max_cpu(); i++)
+			cs_etm_get_metadata(i, &offset, itr, info);
+	}
+
+	return 0;
+}
+
+static int cs_etm_find_snapshot(struct auxtrace_record *itr __maybe_unused,
+				int idx, struct auxtrace_mmap *mm,
+				unsigned char *data __maybe_unused,
+				u64 *head, u64 *old)
+{
+	pr_debug3("%s: mmap index %d old head %zu new head %zu size %zu\n",
+		  __func__, idx, (size_t)*old, (size_t)*head, mm->len);
+
+	*old = *head;
+	*head += mm->len;
+
+	return 0;
+}
+
+static int cs_etm_snapshot_start(struct auxtrace_record *itr)
+{
+	struct cs_etm_recording *ptr =
+			container_of(itr, struct cs_etm_recording, itr);
+	struct perf_evsel *evsel;
+
+	evlist__for_each(ptr->evlist, evsel) {
+		if (evsel->attr.type == ptr->cs_etm_pmu->type)
+			return perf_evsel__disable(evsel);
+	}
+	return -EINVAL;
+}
+
+static int cs_etm_snapshot_finish(struct auxtrace_record *itr)
+{
+	struct cs_etm_recording *ptr =
+			container_of(itr, struct cs_etm_recording, itr);
+	struct perf_evsel *evsel;
+
+	evlist__for_each(ptr->evlist, evsel) {
+		if (evsel->attr.type == ptr->cs_etm_pmu->type)
+			return perf_evsel__enable(evsel);
+	}
+	return -EINVAL;
+}
+
+static u64 cs_etm_reference(struct auxtrace_record *itr __maybe_unused)
+{
+	return (((u64) rand() <<  0) & 0x00000000FFFFFFFFull) |
+		(((u64) rand() << 32) & 0xFFFFFFFF00000000ull);
+}
+
+static void cs_etm_recording_free(struct auxtrace_record *itr)
+{
+	struct cs_etm_recording *ptr =
+			container_of(itr, struct cs_etm_recording, itr);
+	free(ptr);
+}
+
+static int cs_etm_read_finish(struct auxtrace_record *itr, int idx)
+{
+	struct cs_etm_recording *ptr =
+			container_of(itr, struct cs_etm_recording, itr);
+	struct perf_evsel *evsel;
+
+	evlist__for_each(ptr->evlist, evsel) {
+		if (evsel->attr.type == ptr->cs_etm_pmu->type)
+			return perf_evlist__enable_event_idx(ptr->evlist,
+							     evsel, idx);
+	}
+
+	return -EINVAL;
+}
+
+struct auxtrace_record *cs_etm_record_init(int *err)
+{
+	struct perf_pmu *cs_etm_pmu;
+	struct cs_etm_recording *ptr;
+
+	cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME);
+
+	if (!cs_etm_pmu) {
+		*err = -EINVAL;
+		goto out;
+	}
+
+	ptr = zalloc(sizeof(struct cs_etm_recording));
+	if (!ptr) {
+		*err = -ENOMEM;
+		goto out;
+	}
+
+	ptr->cs_etm_pmu			= cs_etm_pmu;
+	ptr->itr.parse_snapshot_options	= cs_etm_parse_snapshot_options;
+	ptr->itr.recording_options	= cs_etm_recording_options;
+	ptr->itr.info_priv_size		= cs_etm_info_priv_size;
+	ptr->itr.info_fill		= cs_etm_info_fill;
+	ptr->itr.find_snapshot		= cs_etm_find_snapshot;
+	ptr->itr.snapshot_start		= cs_etm_snapshot_start;
+	ptr->itr.snapshot_finish	= cs_etm_snapshot_finish;
+	ptr->itr.reference		= cs_etm_reference;
+	ptr->itr.free			= cs_etm_recording_free;
+	ptr->itr.read_finish		= cs_etm_read_finish;
+
+	*err = 0;
+	return &ptr->itr;
+out:
+	return NULL;
+}
diff --git a/tools/perf/arch/arm/util/cs-etm.h b/tools/perf/arch/arm/util/cs-etm.h
new file mode 100644
index 000000000000..909f486d02d1
--- /dev/null
+++ b/tools/perf/arch/arm/util/cs-etm.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier at linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDE__PERF_CS_ETM_H__
+#define INCLUDE__PERF_CS_ETM_H__
+
+struct auxtrace_record *cs_etm_record_init(int *err);
+
+#endif
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
index e58123a8912b..f92918154fec 100644
--- a/tools/perf/arch/arm64/util/Build
+++ b/tools/perf/arch/arm64/util/Build
@@ -1,2 +1,6 @@
 libperf-$(CONFIG_DWARF)     += dwarf-regs.o
 libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
+
+libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
+			      ../../arm/util/auxtrace.o \
+			      ../../arm/util/cs-etm.o
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c9169011e55e..c0aba8e839aa 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -892,6 +892,7 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
 		return intel_pt_process_auxtrace_info(event, session);
 	case PERF_AUXTRACE_INTEL_BTS:
 		return intel_bts_process_auxtrace_info(event, session);
+	case PERF_AUXTRACE_CS_ETM:
 	case PERF_AUXTRACE_UNKNOWN:
 	default:
 		return -EINVAL;
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 767989e0e312..d62ec4b262b0 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -41,6 +41,7 @@ enum auxtrace_type {
 	PERF_AUXTRACE_UNKNOWN,
 	PERF_AUXTRACE_INTEL_PT,
 	PERF_AUXTRACE_INTEL_BTS,
+	PERF_AUXTRACE_CS_ETM,
 };
 
 enum itrace_period_type {
diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h
new file mode 100644
index 000000000000..3cc6bc3263fe
--- /dev/null
+++ b/tools/perf/util/cs-etm.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier at linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDE__UTIL_PERF_CS_ETM_H__
+#define INCLUDE__UTIL_PERF_CS_ETM_H__
+
+/* Versionning header in case things need tro change in the future.  That way
+ * decoding of old snapshot is still possible.
+ */
+enum {
+	/* Starting with 0x0 */
+	CS_HEADER_VERSION_0,
+	/* PMU->type (32 bit), total # of CPUs (32 bit) */
+	CS_PMU_TYPE_CPUS,
+	CS_ETM_SNAPSHOT,
+	CS_HEADER_VERSION_0_MAX,
+};
+
+/* Beginning of header common to both ETMv3 and V4 */
+enum {
+	CS_ETM_MAGIC,
+	CS_ETM_CPU,
+};
+
+/* ETMv3/PTM metadata */
+enum {
+	/* Dynamic, configurable parameters */
+	CS_ETM_ETMCR = CS_ETM_CPU + 1,
+	CS_ETM_ETMTRACEIDR,
+	/* RO, taken from sysFS */
+	CS_ETM_ETMCCER,
+	CS_ETM_ETMIDR,
+	CS_ETM_PRIV_MAX,
+};
+
+/* ETMv4 metadata */
+enum {
+	/* Dynamic, configurable parameters */
+	CS_ETMV4_TRCCONFIGR = CS_ETM_CPU + 1,
+	CS_ETMV4_TRCTRACEIDR,
+	/* RO, taken from sysFS */
+	CS_ETMV4_TRCIDR0,
+	CS_ETMV4_TRCIDR1,
+	CS_ETMV4_TRCIDR2,
+	CS_ETMV4_TRCIDR8,
+	CS_ETMV4_TRCAUTHSTATUS,
+	CS_ETMV4_PRIV_MAX,
+};
+
+#define KiB(x) ((x) * 1024)
+#define MiB(x) ((x) * 1024 * 1024)
+
+#define CS_ETM_HEADER_SIZE (CS_HEADER_VERSION_0_MAX * sizeof(u64))
+
+static const u64 __perf_cs_etmv3_magic   = 0x3030303030303030ULL;
+static const u64 __perf_cs_etmv4_magic   = 0x4040404040404040ULL;
+#define CS_ETMV3_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64))
+#define CS_ETMV4_PRIV_SIZE (CS_ETMV4_PRIV_MAX * sizeof(u64))
+
+#endif
-- 
2.5.0



From ttnguyen at apm.com  Tue May 31 10:17:31 2016
From: ttnguyen at apm.com (Tai Tri Nguyen)
Date: Tue, 31 May 2016 10:17:31 -0700
Subject: [PATCH v2 2/4] Documentation: Add documentation for APM X-Gene
 SoC PMU DTS binding
In-Reply-To: <20160531165630.GE4254@leverpostej>
References: <1460510547-17611-1-git-send-email-ttnguyen@apm.com>
 <1460510547-17611-3-git-send-email-ttnguyen@apm.com>
 <20160418170009.GA15338@rob-hp-laptop>
 <CACgAJHyBbO_LXwtfNVK1f=dY3v1Jfxwxq1dw98EZ0aYdhjPpAg@mail.gmail.com>
 <20160420113121.GE2514@arm.com>
 <20160502205648.GA7374@rob-hp-laptop>
 <CACgAJHyT31DuVNoyRQZVKjv=zM5Fc-EY0gy=y=pHHrBTT+1Xow@mail.gmail.com>
 <20160531165630.GE4254@leverpostej>
Message-ID: <CACgAJHwtb0hNs0JWOrpyF=_fRVvUi2QG4q7qohgCw4SjxqtX6A@mail.gmail.com>

Hi Mark,

On Tue, May 31, 2016 at 9:56 AM, Mark Rutland <mark.rutland at arm.com> wrote:
> On Mon, May 02, 2016 at 02:46:05PM -0700, Tai Tri Nguyen wrote:
>> Hi Rob,
>>
>> On Mon, May 2, 2016 at 1:56 PM, Rob Herring <robh at kernel.org> wrote:
>> > On Wed, Apr 20, 2016 at 12:31:22PM +0100, Will Deacon wrote:
>> >> On Mon, Apr 18, 2016 at 01:04:53PM -0700, Tai Tri Nguyen wrote:
>> >> > >> +Required properties for MCB subnode:
>> >> > >> +- compatible         : Shall be "apm,xgene-pmu-mcb".
>> >> > >> +- reg                        : First resource shall be the MCB PMU resource.
>> >> > >> +- index                      : Instance number of the MCB PMU.
>> >> > >> +
>> >> > >> +Required properties for MC subnode:
>> >> > >> +- compatible         : Shall be "apm,xgene-pmu-mc".
>> >> > >> +- reg                        : First resource shall be the MC PMU resource.
>> >> > >> +- index                      : Instance number of the MC PMU.
>> >> > >
>> >> > > Don't use indexes. You probably need phandles to the nodes these are
>> >> > > related to.
>> >> > >
>> >> > > How many variations of child nodes do you expect to have? 2, 10, 50? You
>> >> > > might want to just collapse all this down to a single node and put this
>> >> > > information in the driver if it is fixed for each SoC and there's only a
>> >> > > handful.
>> >> > >
>> >> >
>> >> > For each kind of PMU, for example memory controller PMU, I expect to
>> >> > have the number of instances up to 8.
>> >> > They are actually all independent PMU nodes and have their own CSR memory bases.
>> >> > The indexes are used for exposing the devices to perf user only. It
>> >> > doesn't have an impact on the programming model.
>> >> > Mark also had the same concern.
>> >>
>> >> Regardless, I'll need an ack from Rob or Mark before I can merge this.
>> >
>> > I still have a concern with this. Needing an index to expose to the user
>> > is generally not a valid reason. That's OS specific and therefore
>> > doesn't belong in DT.
>> >
>> > Rob
>>
>> I can use device name here. However, the perf event names will be
>> different between DT and ACPI which I want to avoid.
>> And the names don't look good at all.
>> Also, specifically for MC and MCB PMUs, the indexes are compared
>> against the active MC/MCB mask to find out whether they are populated
>> or not.
>> Without using the index property, I will also need a mapping function
>> of physical device addresses and their physical ids.
>
> What's wrong with using ${device}.{physical_address} as the PMU name?
> That would be unique and consistent regardless of the firmware, no
> mapping nor index property necessary.
>
> That's sufficient for any user already familiar with the topology, a
> familiarity you seem to be assuming regardless by not explicitly
> describing the topology in the DT.
>
> Thanks,
> Mark.

Okay. I'll do fix it for the next patches.

Thanks,
-- 
Tai


From ttnguyen at apm.com  Tue May 31 10:18:18 2016
From: ttnguyen at apm.com (Tai Tri Nguyen)
Date: Tue, 31 May 2016 10:18:18 -0700
Subject: [PATCH v2 2/4] Documentation: Add documentation for APM X-Gene
 SoC PMU DTS binding
In-Reply-To: <20160531162555.GQ24936@arm.com>
References: <1460510547-17611-1-git-send-email-ttnguyen@apm.com>
 <1460510547-17611-3-git-send-email-ttnguyen@apm.com>
 <20160418170009.GA15338@rob-hp-laptop>
 <CACgAJHyBbO_LXwtfNVK1f=dY3v1Jfxwxq1dw98EZ0aYdhjPpAg@mail.gmail.com>
 <20160420113121.GE2514@arm.com>
 <20160502205648.GA7374@rob-hp-laptop>
 <CACgAJHyT31DuVNoyRQZVKjv=zM5Fc-EY0gy=y=pHHrBTT+1Xow@mail.gmail.com>
 <CACgAJHyHEOe70pOG2yi-XUQS3BYdGmfYD-yTE0wFM9knDtHOiQ@mail.gmail.com>
 <CACgAJHz8bRb6E1xNFwhKpHDGxPhEsQ3J=H_u3woVLgzK0j==Bg@mail.gmail.com>
 <20160531162555.GQ24936@arm.com>
Message-ID: <CACgAJHz63k_eB1qK5rD0bK2qeYiLMYnWgdL+eJD7rnF_Dn03gg@mail.gmail.com>

Hi Will,

On Tue, May 31, 2016 at 9:25 AM, Will Deacon <will.deacon at arm.com> wrote:
> On Tue, May 24, 2016 at 02:12:19PM -0700, Tai Tri Nguyen wrote:
>> It's been weeks.
>> I just want to ping again if you have any more comments on this patch set?
>
> We seem to have reached a stalemate whereby:
>
>   - The devicetree maintainers don't agree with your binding
>   - You don't agree with them
>   - I won't merge the patch without their ack
>
> so I guess you either need to try harder to convince them about the
> index-based binding, or bite the bullet and fix it to make them happy.
>
> Will

Thanks. Yes, I will fix it.

Regards,
-- 
Tai


From mark.rutland at arm.com  Tue May 31 10:29:38 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 31 May 2016 18:29:38 +0100
Subject: [PATCH 2/3] drivers/perf: arm_pmu: Defer the setting of
 __oprofile_cpu_pmu
In-Reply-To: <20160531162834.GR24936@arm.com>
References: <1464694883-26298-1-git-send-email-julien.grall@arm.com>
 <1464694883-26298-3-git-send-email-julien.grall@arm.com>
 <20160531162834.GR24936@arm.com>
Message-ID: <20160531172937.GG4254@leverpostej>

On Tue, May 31, 2016 at 05:28:34PM +0100, Will Deacon wrote:
> On Tue, May 31, 2016 at 12:41:22PM +0100, Julien Grall wrote:
> > The global variable __oprofile_cpu_pmu is set before the PMU is fully
> > initialized. If an error occurs before the end of the initialization,
> > the PMU will be freed and the variable will contain an invalid pointer.
> > 
> > This will result in a kernel crash when perf will be used.
> > 
> > Fix it by moving the setting of __oprofile_cpu_pmu when the PMU is fully
> > initialized (i.e when it is no longer possible to fail).
> > 
> > Signed-off-by: Julien Grall <julien.grall at arm.com>
> > Acked-by: Mark Rutland <mark.rutland at arm.com>
> > ---
> >  drivers/perf/arm_pmu.c | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> Should this one go to -stable too?

I think so.

The bug has been there at least since 76b8a0e4c8bda5f0 ("ARM: perf:
handle armpmu_register failing"), in v3.8...

Prior to that we wouldn't free the PMU, but it might not have been
initialised correctly.

Thanks,
Mark.
 
> Will
> 
> > diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
> > index 6401f0c..95614d2 100644
> > --- a/drivers/perf/arm_pmu.c
> > +++ b/drivers/perf/arm_pmu.c
> > @@ -992,9 +992,6 @@ int arm_pmu_device_probe(struct platform_device *pdev,
> >  
> >  	armpmu_init(pmu);
> >  
> > -	if (!__oprofile_cpu_pmu)
> > -		__oprofile_cpu_pmu = pmu;
> > -
> >  	pmu->plat_device = pdev;
> >  
> >  	if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) {
> > @@ -1030,6 +1027,9 @@ int arm_pmu_device_probe(struct platform_device *pdev,
> >  	if (ret)
> >  		goto out_destroy;
> >  
> > +	if (!__oprofile_cpu_pmu)
> > +		__oprofile_cpu_pmu = pmu;
> > +
> >  	pr_info("enabled with %s PMU driver, %d counters available\n",
> >  			pmu->name, pmu->num_events);
> >  
> > -- 
> > 1.9.1
> > 
> 


From linux at roeck-us.net  Tue May 31 10:31:52 2016
From: linux at roeck-us.net (Guenter Roeck)
Date: Tue, 31 May 2016 10:31:52 -0700
Subject: [PATCH 1/3] watchdog: Add Meson GXBB Watchdog Driver
In-Reply-To: <574D5FEF.7050308@baylibre.com>
References: <1464614948-28247-1-git-send-email-narmstrong@baylibre.com>
 <1464614948-28247-2-git-send-email-narmstrong@baylibre.com>
 <574C6F5A.1010109@roeck-us.net> <574D5FEF.7050308@baylibre.com>
Message-ID: <20160531173152.GD14007@roeck-us.net>

On Tue, May 31, 2016 at 11:57:03AM +0200, Neil Armstrong wrote:
> 
> Hi Guenter,
> On 05/30/2016 06:50 PM, Guenter Roeck wrote:
> > On 05/30/2016 06:29 AM, Neil Armstrong wrote:
> >> Add watchdog specific driver for Amlogic Meson GXBB SoC.
> >>
> >> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> >> ---
> >>   drivers/watchdog/Makefile         |   1 +
> >>   drivers/watchdog/meson_gxbb_wdt.c | 277 ++++++++++++++++++++++++++++++++++++++
> >>   2 files changed, 278 insertions(+)
> >>   create mode 100644 drivers/watchdog/meson_gxbb_wdt.c
> >>
> >> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> >> index 9bde095..7679d93 100644
> >> --- a/drivers/watchdog/Makefile
> >> +++ b/drivers/watchdog/Makefile
> >> @@ -68,6 +68,7 @@ obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
> >>   obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
> >>   obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
> >>   obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
> >> +obj-$(CONFIG_MESON_WATCHDOG) += meson_gxbb_wdt.o
> > 
> > I would really prefer a separate configuration option.
> 
> OK
> 
> > 
> >>   obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
> >>   obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
> >>   obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
> >> diff --git a/drivers/watchdog/meson_gxbb_wdt.c b/drivers/watchdog/meson_gxbb_wdt.c
> >> new file mode 100644
> >> index 0000000..9619c5e
> >> --- /dev/null
> >> +++ b/drivers/watchdog/meson_gxbb_wdt.c
> >> @@ -0,0 +1,277 @@
> >> +/*
> >> + * This file is provided under a dual BSD/GPLv2 license.  When using or
> >> + * redistributing this file, you may do so under either license.
> >> + *
> >> + * GPL LICENSE SUMMARY
> >> + *
> >> + * Copyright (c) 2016 BayLibre, SAS.
> >> + * Author: Neil Armstrong <narmstrong at baylibre.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.
> >> + *
> >> + * You should have received a copy of the GNU General Public License
> >> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> >> + * The full GNU General Public License is included in this distribution
> >> + * in the file called COPYING.
> >> + *
> >> + * BSD LICENSE
> >> + *
> >> + * Copyright (c) 2016 BayLibre, SAS.
> >> + * Author: Neil Armstrong <narmstrong at baylibre.com>
> >> + *
> >> + * Redistribution and use in source and binary forms, with or without
> >> + * modification, are permitted provided that the following conditions
> >> + * are met:
> >> + *
> >> + *   * Redistributions of source code must retain the above copyright
> >> + *     notice, this list of conditions and the following disclaimer.
> >> + *   * Redistributions in binary form must reproduce the above copyright
> >> + *     notice, this list of conditions and the following disclaimer in
> >> + *     the documentation and/or other materials provided with the
> >> + *     distribution.
> >> + *   * Neither the name of Intel Corporation nor the names of its
> >> + *     contributors may be used to endorse or promote products derived
> >> + *     from this software without specific prior written permission.
> >> + *
> >> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> >> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> >> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> >> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> >> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> >> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> >> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> >> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> >> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> >> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> >> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> >> + */
> >> +#include <linux/err.h>
> >> +#include <linux/module.h>
> >> +#include <linux/io.h>
> >> +#include <linux/of.h>
> >> +#include <linux/clk.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/slab.h>
> >> +#include <linux/types.h>
> >> +#include <linux/watchdog.h>
> > 
> > Please order include files alphabetically; that simplifies later changes
> > and helps finding duplicates.
> > 
> >> +
> >> +#define DEFAULT_TIMEOUT    10    /* seconds */
> >> +
> > 
> > Sure you want the default timeout to be that low ?
> 
> I'm not sure of anything actually, what is generally set ?
> 

30 seconds is quite common. I don't really mind 10 seconds, if that makes
sense for this platform, but in some cases it is a bit low.


> > 
> >> +#define GXBB_WDT_CTRL_REG            0x0
> >> +#define GXBB_WDT_CTRL1_REG            0x4
> >> +#define GXBB_WDT_TCNT_REG            0x8
> >> +#define GXBB_WDT_RSET_REG            0xc
> >> +
> >> +#define GXBB_WDT_CTRL_EE_RESET_NOW        BIT(26)
> >> +
> >> +#define GXBB_WDT_CTRL_CLKDIV_EN            BIT(25)
> >> +#define GXBB_WDT_CTRL_CLK_EN            BIT(24)
> >> +#define GXBB_WDT_CTRL_IRQ_EN            BIT(23)
> >> +#define GXBB_WDT_CTRL_EE_RESET            BIT(21)
> >> +#define GXBB_WDT_CTRL_XTAL_SEL            (0)
> >> +#define GXBB_WDT_CTRL_CLK81_SEL            BIT(19)
> >> +#define GXBB_WDT_CTRL_EN            BIT(18)
> >> +#define GXBB_WDT_CTRL_DIV_MASK            (BIT(18) - 1)
> >> +
> >> +#define GXBB_WDT_CTRL1_GPIO_PULSE        BIT(17)
> >> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_0        BIT(16)
> >> +#define GXBB_WDT_CTRL1_GPIO_POL_RESET_1        (0)
> >> +#define GXBB_WDT_CTRL1_GPIO_PULSE_CNT        (BIT(16) - 1)
> >> +
> >> +#define GXBB_WDT_TCNT_SETUP_MASK        (BIT(16) - 1)
> >> +#define GXBB_WDT_TCNT_CNT_SHIFT            16
> >> +
> >> +struct meson_gxbb_wdt {
> >> +    void __iomem *reg_base;
> >> +    struct watchdog_device wdt_dev;
> >> +    struct clk *clk;
> >> +};
> >> +
> >> +static int meson_gxbb_wdt_start(struct watchdog_device *wdt_dev)
> >> +{
> >> +    struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> >> +
> >> +    writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) | GXBB_WDT_CTRL_EN,
> >> +        data->reg_base + GXBB_WDT_CTRL_REG);
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static int meson_gxbb_wdt_stop(struct watchdog_device *wdt_dev)
> >> +{
> >> +    struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> >> +
> >> +    writel(readl(data->reg_base + GXBB_WDT_CTRL_REG) & ~GXBB_WDT_CTRL_EN,
> >> +        data->reg_base + GXBB_WDT_CTRL_REG);
> > 
> > Please align continuation lines with '('.
> > 
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static int meson_gxbb_wdt_ping(struct watchdog_device *wdt_dev)
> >> +{
> >> +    struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> >> +
> >> +    writel(0, data->reg_base + GXBB_WDT_RSET_REG);
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static int meson_gxbb_wdt_get_timeout(struct meson_gxbb_wdt *data)
> >> +{
> >> +    return (readl(data->reg_base + GXBB_WDT_TCNT_REG) &
> >> +            GXBB_WDT_TCNT_SETUP_MASK) / 1000;
> >> +}
> >> +
> > Unused function ?
> Crap, forgot to remove this.
> 
> > 
> >> +static int meson_gxbb_wdt_set_timeout(struct watchdog_device *wdt_dev,
> >> +                      unsigned int timeout)
> >> +{
> >> +    struct meson_gxbb_wdt *data = watchdog_get_drvdata(wdt_dev);
> >> +
> >> +    meson_gxbb_wdt_ping(wdt_dev);
> > 
> > Is this necessary ? The infrastructure calls it after calling this function.
> 
> Is it really safe to change the timeout value before calling ping ?
> 
> On the HW, there is a running counter that is reset to 0 when writing any value to the RSET register.
> A comparator triggers a reset when the counter is >= the timeout value.
> 
> If somehow we change to a lower value but the counter is > the new timeout value, it will reset the system.
> Calling ping right before would keep this safe.
> 
Ok.

> > 
> >> +
> >> +    writel(timeout * 1000, data->reg_base + GXBB_WDT_TCNT_REG);
> > 
> >     wdt_dev->timeout = timeout;
> > 
> > Also, timeout may be larger than the maximum supported by the hardware,
> > so you need to ensure that the value your write is not larger than
> > GXBB_WDT_TCNT_SETUP_MASK.
> 
> Isn't already checked by the watchdog-core ?
> 

Not anymore if the maximum hardware timeout is specified.

The difficulty in this case is that 'timeout' no longer reflects
the hardware timeout, but the logical timeout set from user space.
Maybe we can come up with a better mechanism (maybe two separate variables),
but for now drivers which set the maximum HW timeout have to check the
value range.

Thanks,
Guenter


From broonie at kernel.org  Tue May 31 10:36:47 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 31 May 2016 18:36:47 +0100
Subject: [PATCH resend v2 1/6] regulator: axp20x: support AXP809 variant
In-Reply-To: <1464711804-19256-2-git-send-email-wens@csie.org>
References: <1464711804-19256-1-git-send-email-wens@csie.org>
 <1464711804-19256-2-git-send-email-wens@csie.org>
Message-ID: <20160531173647.GJ29837@sirena.org.uk>

On Wed, Jun 01, 2016 at 12:23:19AM +0800, Chen-Yu Tsai wrote:
> The X-Powers AXP809 PMIC has a similar set of regulators as the AXP221,
> though a few LDOs were removed, and a new switch output added. Like the
> AXP221, AXP809 also has DC1SW and DC5LDO, which are internally chained
> to DCDC1 and DCDC5, respectively.
> 
> Add support for this new variant. Also remove the "axp22x_" prefix from
> DC1SW/DC5LDO supply handling code, as the AXP809 uses it as well.
> 
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
> ---

Please preserve tags when people review things.  Why wasn't this applied
when I originally reviewed it?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160531/14c3e9fd/attachment-0001.sig>

From mathieu.poirier at linaro.org  Tue May 31 10:39:00 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue, 31 May 2016 11:39:00 -0600
Subject: [PATCH 1/5] coresight: Fix NULL pointer dereference in
 _coresight_build_path
In-Reply-To: <1464695858-29284-2-git-send-email-suzuki.poulose@arm.com>
References: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
 <1464695858-29284-2-git-send-email-suzuki.poulose@arm.com>
Message-ID: <CANLsYkwgdSF9CA+fZFg_SFN2xg4LW7eqZ0=-v8yaM4wdgwMPjA@mail.gmail.com>

On 31 May 2016 at 05:57, Suzuki K Poulose <suzuki.poulose at arm.com> wrote:
> _coresight_build_path assumes that all the connections of a csdev
> has the child_dev initialised. This may not be true if the particular
> component is not supported by the kernel config(e.g TPIU) but is
> present in the DT. In which case, building a path can cause a crash like this :
>
>   Unable to handle kernel NULL pointer dereference at virtual address 00000010
>   pgd = ffffffc9750dd000
>   [00000010] *pgd=00000009f5e90003, *pud=00000009f5e90003, *pmd=0000000000000000
>   Internal error: Oops: 96000006 [#1] PREEMPT SMP
>   Modules linked in:
>   CPU: 4 PID: 1348 Comm: bash Not tainted 4.6.0-next-20160517 #1646
>   Hardware name: ARM Juno development board (r0) (DT)
>   task: ffffffc97517a280 ti: ffffffc9762c4000 task.ti: ffffffc9762c4000
>   PC is at _coresight_build_path+0x18/0xe4
>   LR is at _coresight_build_path+0xc0/0xe4
>   pc : [<ffffff80083d5130>] lr : [<ffffff80083d51d8>] pstate: 20000145
>   sp : ffffffc9762c7ba0
>
>   [<ffffff80083d5130>] _coresight_build_path+0x18/0xe4
>   [<ffffff80083d51d8>] _coresight_build_path+0xc0/0xe4
>   [<ffffff80083d51d8>] _coresight_build_path+0xc0/0xe4
>   [<ffffff80083d51d8>] _coresight_build_path+0xc0/0xe4
>   [<ffffff80083d51d8>] _coresight_build_path+0xc0/0xe4
>   [<ffffff80083d51d8>] _coresight_build_path+0xc0/0xe4
>   [<ffffff80083d5cdc>] coresight_build_path+0x40/0x68
>   [<ffffff80083d5e14>] coresight_enable+0x74/0x1bc
>   [<ffffff80083d60a0>] enable_source_store+0x3c/0x6c
>   [<ffffff800830b17c>] dev_attr_store+0x18/0x28
>   [<ffffff80081ca9c4>] sysfs_kf_write+0x40/0x50
>   [<ffffff80081c9e38>] kernfs_fop_write+0x140/0x1cc
>   [<ffffff8008163ec8>] __vfs_write+0x28/0x110
>   [<ffffff8008164bf0>] vfs_write+0xa0/0x174
>   [<ffffff8008165d18>] SyS_write+0x44/0xa0
>   [<ffffff8008084e70>] el0_svc_naked+0x24/0x28
>
> Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> ---
>  drivers/hwtracing/coresight/coresight.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
> index 5443d03..0fdaaf4 100644
> --- a/drivers/hwtracing/coresight/coresight.c
> +++ b/drivers/hwtracing/coresight/coresight.c
> @@ -385,7 +385,6 @@ static int _coresight_build_path(struct coresight_device *csdev,
>         int i;
>         bool found = false;
>         struct coresight_node *node;
> -       struct coresight_connection *conn;
>
>         /* An activated sink has been found.  Enqueue the element */
>         if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
> @@ -394,8 +393,9 @@ static int _coresight_build_path(struct coresight_device *csdev,
>
>         /* Not a sink - recursively explore each port found on this element */
>         for (i = 0; i < csdev->nr_outport; i++) {
> -               conn = &csdev->conns[i];
> -               if (_coresight_build_path(conn->child_dev, path) == 0) {
> +               struct coresight_device *child_dev = csdev->conns[i].child_dev;
> +
> +               if (child_dev && _coresight_build_path(child_dev, path) == 0) {
>                         found = true;
>                         break;
>                 }
> --
> 1.9.1
>

Acked-by: Mathieu Poirier <mathieu.poirier at linaro.org>

Greg, since this is a bug fix can we add it to 4.7-rc2?

Thanks,
Mathieu


From mathieu.poirier at linaro.org  Tue May 31 10:45:38 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue, 31 May 2016 11:45:38 -0600
Subject: [PATCH 2/5] coresight: etmv4: Fix ETMv4x peripheral ID table
In-Reply-To: <1464695858-29284-3-git-send-email-suzuki.poulose@arm.com>
References: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
 <1464695858-29284-3-git-send-email-suzuki.poulose@arm.com>
Message-ID: <CANLsYkzzogTMRdhuSc6AtFUjM7BM3xgMHqth4sJeYn=dA1=qNg@mail.gmail.com>

On 31 May 2016 at 05:57, Suzuki K Poulose <suzuki.poulose at arm.com> wrote:
> This patch cleans up the peripheral id table for different ETMv4
> implementations.
>
> As per Cortex-A53 TRM, the ETM has following id values:
>
> Peripheral ID0  0x5D    0xFE0
> Peripheral ID1  0xB9    0xFE4
> Peripheral ID2  0x4B    0xFE8
> Peripheral ID3  0x00    0xFEC
>
> where, PID2: has the following format:
>
> [7:4]   Revision
> [3]     JEDEC   0b1     res1. Indicates a JEP106 identity code is used
> [2:0]   DES_1   0b011   ARM Limited. This is bits[6:4] of JEP106 ID code
>
> The existing table entry checks only the bits [1:0], which is not
> sufficient enough. Fix it to match bits [3:0], just like the other
> entries do. While at it, correct the comment for A57 and the A53 entry.
>
> Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> ---
>  drivers/hwtracing/coresight/coresight-etm4x.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
> index 462f0dc..88947f3 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.c
> @@ -815,12 +815,12 @@ err_arch_supported:
>  }
>
>  static struct amba_id etm4_ids[] = {
> -       {       /* ETM 4.0 - Qualcomm */
> -               .id     = 0x0003b95d,
> -               .mask   = 0x0003ffff,
> +       {       /* ETM 4.0 - Cortex-A53  */
> +               .id     = 0x000bb95d,
> +               .mask   = 0x000fffff,
>                 .data   = "ETM 4.0",
>         },
> -       {       /* ETM 4.0 - Juno board */
> +       {       /* ETM 4.0 - Cortex-A57 */
>                 .id     = 0x000bb95e,
>                 .mask   = 0x000fffff,
>                 .data   = "ETM 4.0",
> --
> 1.9.1
>

I'll apply this to my next tree but since it doesn't cause a core dump
or prevent the kernel from booting, I don't think it deserves to be in
-rc2.

Thanks,
Mathieu


From broonie at kernel.org  Tue May 31 10:45:51 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 31 May 2016 18:45:51 +0100
Subject: Applied "ASoC: cygnus: Add Cygnus audio DMA driver" to the asoc tree
In-Reply-To: <1459277192-10942-4-git-send-email-simran.rai@broadcom.com>
Message-ID: <E1b7njj-00060p-RB@debutante>

The patch

   ASoC: cygnus: Add Cygnus audio DMA driver

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 1200a7d9b2c65ffb2dd673add65cd5dc95671489 Mon Sep 17 00:00:00 2001
From: Simran Rai <ssimran at broadcom.com>
Date: Tue, 17 May 2016 17:01:09 -0700
Subject: [PATCH] ASoC: cygnus: Add Cygnus audio DMA driver

This patch adds Cygnus audio DMA driver. It supports playback
and capture modes and uses ringbuffers for data transfer.

Signed-off-by: Lori Hikichi <lhikichi at broadcom.com>
Signed-off-by: Simran Rai <ssimran at broadcom.com>
Reviewed-by: Ray Jui <rjui at broadcom.com>
Reviewed-by: Arun Parameswaran <arunp at broadcom.com>
Reviewed-by: Scott Branden <sbranden at broadcom.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 sound/soc/bcm/Kconfig      |   9 +
 sound/soc/bcm/Makefile     |   5 +
 sound/soc/bcm/cygnus-pcm.c | 861 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 875 insertions(+)
 create mode 100644 sound/soc/bcm/cygnus-pcm.c

diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig
index 6a834e109f1d..d528aaceaad9 100644
--- a/sound/soc/bcm/Kconfig
+++ b/sound/soc/bcm/Kconfig
@@ -7,3 +7,12 @@ config SND_BCM2835_SOC_I2S
 	  Say Y or M if you want to add support for codecs attached to
 	  the BCM2835 I2S interface. You will also need
 	  to select the audio interfaces to support below.
+
+config SND_SOC_CYGNUS
+	tristate "SoC platform audio for Broadcom Cygnus chips"
+	depends on ARCH_BCM_CYGNUS || COMPILE_TEST
+	help
+	  Say Y if you want to add support for ASoC audio on Broadcom
+	  Cygnus chips (bcm958300, bcm958305, bcm911360)
+
+	  If you don't know what to do here, say N.
\ No newline at end of file
diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile
index bc816b71e5a4..fc739d007884 100644
--- a/sound/soc/bcm/Makefile
+++ b/sound/soc/bcm/Makefile
@@ -3,3 +3,8 @@ snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o
 
 obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o
 
+# CYGNUS Platform Support
+snd-soc-cygnus-objs := cygnus-pcm.o cygnus-ssp.o
+
+obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o
+
diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c
new file mode 100644
index 000000000000..d616e096462e
--- /dev/null
+++ b/sound/soc/bcm/cygnus-pcm.c
@@ -0,0 +1,861 @@
+/*
+ * Copyright (C) 2014-2015 Broadcom Corporation
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/debugfs.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+
+#include "cygnus-ssp.h"
+
+/* Register offset needed for ASoC PCM module */
+
+#define INTH_R5F_STATUS_OFFSET     0x040
+#define INTH_R5F_CLEAR_OFFSET      0x048
+#define INTH_R5F_MASK_SET_OFFSET   0x050
+#define INTH_R5F_MASK_CLEAR_OFFSET 0x054
+
+#define BF_REARM_FREE_MARK_OFFSET 0x344
+#define BF_REARM_FULL_MARK_OFFSET 0x348
+
+/* Ring Buffer Ctrl Regs --- Start */
+/* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_RDADDR_REG_BASE */
+#define SRC_RBUF_0_RDADDR_OFFSET 0x500
+#define SRC_RBUF_1_RDADDR_OFFSET 0x518
+#define SRC_RBUF_2_RDADDR_OFFSET 0x530
+#define SRC_RBUF_3_RDADDR_OFFSET 0x548
+#define SRC_RBUF_4_RDADDR_OFFSET 0x560
+#define SRC_RBUF_5_RDADDR_OFFSET 0x578
+#define SRC_RBUF_6_RDADDR_OFFSET 0x590
+
+/* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_WRADDR_REG_BASE */
+#define SRC_RBUF_0_WRADDR_OFFSET 0x504
+#define SRC_RBUF_1_WRADDR_OFFSET 0x51c
+#define SRC_RBUF_2_WRADDR_OFFSET 0x534
+#define SRC_RBUF_3_WRADDR_OFFSET 0x54c
+#define SRC_RBUF_4_WRADDR_OFFSET 0x564
+#define SRC_RBUF_5_WRADDR_OFFSET 0x57c
+#define SRC_RBUF_6_WRADDR_OFFSET 0x594
+
+/* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_BASEADDR_REG_BASE */
+#define SRC_RBUF_0_BASEADDR_OFFSET 0x508
+#define SRC_RBUF_1_BASEADDR_OFFSET 0x520
+#define SRC_RBUF_2_BASEADDR_OFFSET 0x538
+#define SRC_RBUF_3_BASEADDR_OFFSET 0x550
+#define SRC_RBUF_4_BASEADDR_OFFSET 0x568
+#define SRC_RBUF_5_BASEADDR_OFFSET 0x580
+#define SRC_RBUF_6_BASEADDR_OFFSET 0x598
+
+/* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_ENDADDR_REG_BASE */
+#define SRC_RBUF_0_ENDADDR_OFFSET 0x50c
+#define SRC_RBUF_1_ENDADDR_OFFSET 0x524
+#define SRC_RBUF_2_ENDADDR_OFFSET 0x53c
+#define SRC_RBUF_3_ENDADDR_OFFSET 0x554
+#define SRC_RBUF_4_ENDADDR_OFFSET 0x56c
+#define SRC_RBUF_5_ENDADDR_OFFSET 0x584
+#define SRC_RBUF_6_ENDADDR_OFFSET 0x59c
+
+/* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_FREE_MARK_REG_BASE */
+#define SRC_RBUF_0_FREE_MARK_OFFSET 0x510
+#define SRC_RBUF_1_FREE_MARK_OFFSET 0x528
+#define SRC_RBUF_2_FREE_MARK_OFFSET 0x540
+#define SRC_RBUF_3_FREE_MARK_OFFSET 0x558
+#define SRC_RBUF_4_FREE_MARK_OFFSET 0x570
+#define SRC_RBUF_5_FREE_MARK_OFFSET 0x588
+#define SRC_RBUF_6_FREE_MARK_OFFSET 0x5a0
+
+/* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_RDADDR_REG_BASE */
+#define DST_RBUF_0_RDADDR_OFFSET 0x5c0
+#define DST_RBUF_1_RDADDR_OFFSET 0x5d8
+#define DST_RBUF_2_RDADDR_OFFSET 0x5f0
+#define DST_RBUF_3_RDADDR_OFFSET 0x608
+#define DST_RBUF_4_RDADDR_OFFSET 0x620
+#define DST_RBUF_5_RDADDR_OFFSET 0x638
+
+/* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_WRADDR_REG_BASE */
+#define DST_RBUF_0_WRADDR_OFFSET 0x5c4
+#define DST_RBUF_1_WRADDR_OFFSET 0x5dc
+#define DST_RBUF_2_WRADDR_OFFSET 0x5f4
+#define DST_RBUF_3_WRADDR_OFFSET 0x60c
+#define DST_RBUF_4_WRADDR_OFFSET 0x624
+#define DST_RBUF_5_WRADDR_OFFSET 0x63c
+
+/* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_BASEADDR_REG_BASE */
+#define DST_RBUF_0_BASEADDR_OFFSET 0x5c8
+#define DST_RBUF_1_BASEADDR_OFFSET 0x5e0
+#define DST_RBUF_2_BASEADDR_OFFSET 0x5f8
+#define DST_RBUF_3_BASEADDR_OFFSET 0x610
+#define DST_RBUF_4_BASEADDR_OFFSET 0x628
+#define DST_RBUF_5_BASEADDR_OFFSET 0x640
+
+/* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_ENDADDR_REG_BASE */
+#define DST_RBUF_0_ENDADDR_OFFSET 0x5cc
+#define DST_RBUF_1_ENDADDR_OFFSET 0x5e4
+#define DST_RBUF_2_ENDADDR_OFFSET 0x5fc
+#define DST_RBUF_3_ENDADDR_OFFSET 0x614
+#define DST_RBUF_4_ENDADDR_OFFSET 0x62c
+#define DST_RBUF_5_ENDADDR_OFFSET 0x644
+
+/* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_FULL_MARK_REG_BASE */
+#define DST_RBUF_0_FULL_MARK_OFFSET 0x5d0
+#define DST_RBUF_1_FULL_MARK_OFFSET 0x5e8
+#define DST_RBUF_2_FULL_MARK_OFFSET 0x600
+#define DST_RBUF_3_FULL_MARK_OFFSET 0x618
+#define DST_RBUF_4_FULL_MARK_OFFSET 0x630
+#define DST_RBUF_5_FULL_MARK_OFFSET 0x648
+/* Ring Buffer Ctrl Regs --- End */
+
+/* Error Status Regs --- Start */
+/* AUD_FMM_BF_ESR_ESRX_STATUS_REG_BASE */
+#define ESR0_STATUS_OFFSET 0x900
+#define ESR1_STATUS_OFFSET 0x918
+#define ESR2_STATUS_OFFSET 0x930
+#define ESR3_STATUS_OFFSET 0x948
+#define ESR4_STATUS_OFFSET 0x960
+
+/* AUD_FMM_BF_ESR_ESRX_STATUS_CLEAR_REG_BASE */
+#define ESR0_STATUS_CLR_OFFSET 0x908
+#define ESR1_STATUS_CLR_OFFSET 0x920
+#define ESR2_STATUS_CLR_OFFSET 0x938
+#define ESR3_STATUS_CLR_OFFSET 0x950
+#define ESR4_STATUS_CLR_OFFSET 0x968
+
+/* AUD_FMM_BF_ESR_ESRX_MASK_REG_BASE */
+#define ESR0_MASK_STATUS_OFFSET 0x90c
+#define ESR1_MASK_STATUS_OFFSET 0x924
+#define ESR2_MASK_STATUS_OFFSET 0x93c
+#define ESR3_MASK_STATUS_OFFSET 0x954
+#define ESR4_MASK_STATUS_OFFSET 0x96c
+
+/* AUD_FMM_BF_ESR_ESRX_MASK_SET_REG_BASE */
+#define ESR0_MASK_SET_OFFSET 0x910
+#define ESR1_MASK_SET_OFFSET 0x928
+#define ESR2_MASK_SET_OFFSET 0x940
+#define ESR3_MASK_SET_OFFSET 0x958
+#define ESR4_MASK_SET_OFFSET 0x970
+
+/* AUD_FMM_BF_ESR_ESRX_MASK_CLEAR_REG_BASE */
+#define ESR0_MASK_CLR_OFFSET 0x914
+#define ESR1_MASK_CLR_OFFSET 0x92c
+#define ESR2_MASK_CLR_OFFSET 0x944
+#define ESR3_MASK_CLR_OFFSET 0x95c
+#define ESR4_MASK_CLR_OFFSET 0x974
+/* Error Status Regs --- End */
+
+#define R5F_ESR0_SHIFT  0    /* esr0 = fifo underflow */
+#define R5F_ESR1_SHIFT  1    /* esr1 = ringbuf underflow */
+#define R5F_ESR2_SHIFT  2    /* esr2 = ringbuf overflow */
+#define R5F_ESR3_SHIFT  3    /* esr3 = freemark */
+#define R5F_ESR4_SHIFT  4    /* esr4 = fullmark */
+
+
+/* Mask for R5F register.  Set all relevant interrupt for playback handler */
+#define ANY_PLAYBACK_IRQ  (BIT(R5F_ESR0_SHIFT) | \
+			   BIT(R5F_ESR1_SHIFT) | \
+			   BIT(R5F_ESR3_SHIFT))
+
+/* Mask for R5F register.  Set all relevant interrupt for capture handler */
+#define ANY_CAPTURE_IRQ   (BIT(R5F_ESR2_SHIFT) | BIT(R5F_ESR4_SHIFT))
+
+/*
+ * PERIOD_BYTES_MIN is the number of bytes to at which the interrupt will tick.
+ * This number should be a multiple of 256. Minimum value is 256
+ */
+#define PERIOD_BYTES_MIN 0x100
+
+static const struct snd_pcm_hardware cygnus_pcm_hw = {
+	.info = SNDRV_PCM_INFO_MMAP |
+			SNDRV_PCM_INFO_MMAP_VALID |
+			SNDRV_PCM_INFO_INTERLEAVED,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE |
+			SNDRV_PCM_FMTBIT_S32_LE,
+
+	/* A period is basically an interrupt */
+	.period_bytes_min = PERIOD_BYTES_MIN,
+	.period_bytes_max = 0x10000,
+
+	/* period_min/max gives range of approx interrupts per buffer */
+	.periods_min = 2,
+	.periods_max = 8,
+
+	/*
+	 * maximum buffer size in bytes = period_bytes_max * periods_max
+	 * We allocate this amount of data for each enabled channel
+	 */
+	.buffer_bytes_max = 4 * 0x8000,
+};
+
+static u64 cygnus_dma_dmamask = DMA_BIT_MASK(32);
+
+static struct cygnus_aio_port *cygnus_dai_get_dma_data(
+				struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+
+	return snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
+}
+
+static void ringbuf_set_initial(void __iomem *audio_io,
+		struct ringbuf_regs *p_rbuf,
+		bool is_playback,
+		u32 start,
+		u32 periodsize,
+		u32 bufsize)
+{
+	u32 initial_rd;
+	u32 initial_wr;
+	u32 end;
+	u32 fmark_val; /* free or full mark */
+
+	p_rbuf->period_bytes = periodsize;
+	p_rbuf->buf_size = bufsize;
+
+	if (is_playback) {
+		/* Set the pointers to indicate full (flip uppermost bit) */
+		initial_rd = start;
+		initial_wr = initial_rd ^ BIT(31);
+	} else {
+		/* Set the pointers to indicate empty */
+		initial_wr = start;
+		initial_rd = initial_wr;
+	}
+
+	end = start + bufsize - 1;
+
+	/*
+	 * The interrupt will fire when free/full mark is *exceeded*
+	 * The fmark value must be multiple of PERIOD_BYTES_MIN so set fmark
+	 * to be PERIOD_BYTES_MIN less than the period size.
+	 */
+	fmark_val = periodsize - PERIOD_BYTES_MIN;
+
+	writel(start, audio_io + p_rbuf->baseaddr);
+	writel(end, audio_io + p_rbuf->endaddr);
+	writel(fmark_val, audio_io + p_rbuf->fmark);
+	writel(initial_rd, audio_io + p_rbuf->rdaddr);
+	writel(initial_wr, audio_io + p_rbuf->wraddr);
+}
+
+static int configure_ringbuf_regs(struct snd_pcm_substream *substream)
+{
+	struct cygnus_aio_port *aio;
+	struct ringbuf_regs *p_rbuf;
+	int status = 0;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	/* Map the ssp portnum to a set of ring buffers. */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		p_rbuf = &aio->play_rb_regs;
+
+		switch (aio->portnum) {
+		case 0:
+			*p_rbuf = RINGBUF_REG_PLAYBACK(0);
+			break;
+		case 1:
+			*p_rbuf = RINGBUF_REG_PLAYBACK(2);
+			break;
+		case 2:
+			*p_rbuf = RINGBUF_REG_PLAYBACK(4);
+			break;
+		case 3: /* SPDIF */
+			*p_rbuf = RINGBUF_REG_PLAYBACK(6);
+			break;
+		default:
+			status = -EINVAL;
+		}
+	} else {
+		p_rbuf = &aio->capture_rb_regs;
+
+		switch (aio->portnum) {
+		case 0:
+			*p_rbuf = RINGBUF_REG_CAPTURE(0);
+			break;
+		case 1:
+			*p_rbuf = RINGBUF_REG_CAPTURE(2);
+			break;
+		case 2:
+			*p_rbuf = RINGBUF_REG_CAPTURE(4);
+			break;
+		default:
+			status = -EINVAL;
+		}
+	}
+
+	return status;
+}
+
+static struct ringbuf_regs *get_ringbuf(struct snd_pcm_substream *substream)
+{
+	struct cygnus_aio_port *aio;
+	struct ringbuf_regs *p_rbuf = NULL;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		p_rbuf = &aio->play_rb_regs;
+	else
+		p_rbuf = &aio->capture_rb_regs;
+
+	return p_rbuf;
+}
+
+static void enable_intr(struct snd_pcm_substream *substream)
+{
+	struct cygnus_aio_port *aio;
+	u32 clear_mask;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	/* The port number maps to the bit position to be cleared */
+	clear_mask = BIT(aio->portnum);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* Clear interrupt status before enabling them */
+		writel(clear_mask, aio->cygaud->audio + ESR0_STATUS_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR1_STATUS_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR3_STATUS_CLR_OFFSET);
+		/* Unmask the interrupts of the given port*/
+		writel(clear_mask, aio->cygaud->audio + ESR0_MASK_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR1_MASK_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR3_MASK_CLR_OFFSET);
+
+		writel(ANY_PLAYBACK_IRQ,
+			aio->cygaud->audio + INTH_R5F_MASK_CLEAR_OFFSET);
+	} else {
+		writel(clear_mask, aio->cygaud->audio + ESR2_STATUS_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR4_STATUS_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR2_MASK_CLR_OFFSET);
+		writel(clear_mask, aio->cygaud->audio + ESR4_MASK_CLR_OFFSET);
+
+		writel(ANY_CAPTURE_IRQ,
+			aio->cygaud->audio + INTH_R5F_MASK_CLEAR_OFFSET);
+	}
+
+}
+
+static void disable_intr(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct cygnus_aio_port *aio;
+	u32 set_mask;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	dev_dbg(rtd->cpu_dai->dev, "%s on port %d\n", __func__, aio->portnum);
+
+	/* The port number maps to the bit position to be set */
+	set_mask = BIT(aio->portnum);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* Mask the interrupts of the given port*/
+		writel(set_mask, aio->cygaud->audio + ESR0_MASK_SET_OFFSET);
+		writel(set_mask, aio->cygaud->audio + ESR1_MASK_SET_OFFSET);
+		writel(set_mask, aio->cygaud->audio + ESR3_MASK_SET_OFFSET);
+	} else {
+		writel(set_mask, aio->cygaud->audio + ESR2_MASK_SET_OFFSET);
+		writel(set_mask, aio->cygaud->audio + ESR4_MASK_SET_OFFSET);
+	}
+
+}
+
+static int cygnus_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		enable_intr(substream);
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		disable_intr(substream);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void cygnus_pcm_period_elapsed(struct snd_pcm_substream *substream)
+{
+	struct cygnus_aio_port *aio;
+	struct ringbuf_regs *p_rbuf = NULL;
+	u32 regval;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	p_rbuf = get_ringbuf(substream);
+
+	/*
+	 * If free/full mark interrupt occurs, provide timestamp
+	 * to ALSA and update appropriate idx by period_bytes
+	 */
+	snd_pcm_period_elapsed(substream);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* Set the ring buffer to full */
+		regval = readl(aio->cygaud->audio + p_rbuf->rdaddr);
+		regval = regval ^ BIT(31);
+		writel(regval, aio->cygaud->audio + p_rbuf->wraddr);
+	} else {
+		/* Set the ring buffer to empty */
+		regval = readl(aio->cygaud->audio + p_rbuf->wraddr);
+		writel(regval, aio->cygaud->audio + p_rbuf->rdaddr);
+	}
+}
+
+/*
+ * ESR0/1/3 status  Description
+ *  0x1	I2S0_out port caused interrupt
+ *  0x2	I2S1_out port caused interrupt
+ *  0x4	I2S2_out port caused interrupt
+ *  0x8	SPDIF_out port caused interrupt
+ */
+static void handle_playback_irq(struct cygnus_audio *cygaud)
+{
+	void __iomem *audio_io;
+	u32 port;
+	u32 esr_status0, esr_status1, esr_status3;
+
+	audio_io = cygaud->audio;
+
+	/*
+	 * ESR status gets updates with/without interrupts enabled.
+	 * So, check the ESR mask, which provides interrupt enable/
+	 * disable status and use it to determine which ESR status
+	 * should be serviced.
+	 */
+	esr_status0 = readl(audio_io + ESR0_STATUS_OFFSET);
+	esr_status0 &= ~readl(audio_io + ESR0_MASK_STATUS_OFFSET);
+	esr_status1 = readl(audio_io + ESR1_STATUS_OFFSET);
+	esr_status1 &= ~readl(audio_io + ESR1_MASK_STATUS_OFFSET);
+	esr_status3 = readl(audio_io + ESR3_STATUS_OFFSET);
+	esr_status3 &= ~readl(audio_io + ESR3_MASK_STATUS_OFFSET);
+
+	for (port = 0; port < CYGNUS_MAX_PLAYBACK_PORTS; port++) {
+		u32 esrmask = BIT(port);
+
+		/*
+		 * Ringbuffer or FIFO underflow
+		 * If we get this interrupt then, it is also true that we have
+		 * not yet responded to the freemark interrupt.
+		 * Log a debug message.  The freemark handler below will
+		 * handle getting everything going again.
+		 */
+		if ((esrmask & esr_status1) || (esrmask & esr_status0)) {
+			dev_dbg(cygaud->dev,
+				"Underrun: esr0=0x%x, esr1=0x%x esr3=0x%x\n",
+				esr_status0, esr_status1, esr_status3);
+		}
+
+		/*
+		 * Freemark is hit. This is the normal interrupt.
+		 * In typical operation the read and write regs will be equal
+		 */
+		if (esrmask & esr_status3) {
+			struct snd_pcm_substream *playstr;
+
+			playstr = cygaud->portinfo[port].play_stream;
+			cygnus_pcm_period_elapsed(playstr);
+		}
+	}
+
+	/* Clear ESR interrupt */
+	writel(esr_status0, audio_io + ESR0_STATUS_CLR_OFFSET);
+	writel(esr_status1, audio_io + ESR1_STATUS_CLR_OFFSET);
+	writel(esr_status3, audio_io + ESR3_STATUS_CLR_OFFSET);
+	/* Rearm freemark logic by writing 1 to the correct bit */
+	writel(esr_status3, audio_io + BF_REARM_FREE_MARK_OFFSET);
+}
+
+/*
+ * ESR2/4 status  Description
+ *  0x1	I2S0_in port caused interrupt
+ *  0x2	I2S1_in port caused interrupt
+ *  0x4	I2S2_in port caused interrupt
+ */
+static void handle_capture_irq(struct cygnus_audio *cygaud)
+{
+	void __iomem *audio_io;
+	u32 port;
+	u32 esr_status2, esr_status4;
+
+	audio_io = cygaud->audio;
+
+	/*
+	 * ESR status gets updates with/without interrupts enabled.
+	 * So, check the ESR mask, which provides interrupt enable/
+	 * disable status and use it to determine which ESR status
+	 * should be serviced.
+	 */
+	esr_status2 = readl(audio_io + ESR2_STATUS_OFFSET);
+	esr_status2 &= ~readl(audio_io + ESR2_MASK_STATUS_OFFSET);
+	esr_status4 = readl(audio_io + ESR4_STATUS_OFFSET);
+	esr_status4 &= ~readl(audio_io + ESR4_MASK_STATUS_OFFSET);
+
+	for (port = 0; port < CYGNUS_MAX_CAPTURE_PORTS; port++) {
+		u32 esrmask = BIT(port);
+
+		/*
+		 * Ringbuffer or FIFO overflow
+		 * If we get this interrupt then, it is also true that we have
+		 * not yet responded to the fullmark interrupt.
+		 * Log a debug message.  The fullmark handler below will
+		 * handle getting everything going again.
+		 */
+		if (esrmask & esr_status2)
+			dev_dbg(cygaud->dev,
+				"Overflow: esr2=0x%x\n", esr_status2);
+
+		if (esrmask & esr_status4) {
+			struct snd_pcm_substream *capstr;
+
+			capstr = cygaud->portinfo[port].capture_stream;
+			cygnus_pcm_period_elapsed(capstr);
+		}
+	}
+
+	writel(esr_status2, audio_io + ESR2_STATUS_CLR_OFFSET);
+	writel(esr_status4, audio_io + ESR4_STATUS_CLR_OFFSET);
+	/* Rearm fullmark logic by writing 1 to the correct bit */
+	writel(esr_status4, audio_io + BF_REARM_FULL_MARK_OFFSET);
+}
+
+static irqreturn_t cygnus_dma_irq(int irq, void *data)
+{
+	u32 r5_status;
+	struct cygnus_audio *cygaud = data;
+
+	/*
+	 * R5 status bits	Description
+	 *  0		ESR0 (playback FIFO interrupt)
+	 *  1		ESR1 (playback rbuf interrupt)
+	 *  2		ESR2 (capture rbuf interrupt)
+	 *  3		ESR3 (Freemark play. interrupt)
+	 *  4		ESR4 (Fullmark capt. interrupt)
+	 */
+	r5_status = readl(cygaud->audio + INTH_R5F_STATUS_OFFSET);
+
+	if (!(r5_status & (ANY_PLAYBACK_IRQ | ANY_CAPTURE_IRQ)))
+		return IRQ_NONE;
+
+	/* If playback interrupt happened */
+	if (ANY_PLAYBACK_IRQ & r5_status) {
+		handle_playback_irq(cygaud);
+		writel(ANY_PLAYBACK_IRQ & r5_status,
+			cygaud->audio + INTH_R5F_CLEAR_OFFSET);
+	}
+
+	/* If  capture interrupt happened */
+	if (ANY_CAPTURE_IRQ & r5_status) {
+		handle_capture_irq(cygaud);
+		writel(ANY_CAPTURE_IRQ & r5_status,
+			cygaud->audio + INTH_R5F_CLEAR_OFFSET);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int cygnus_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct cygnus_aio_port *aio;
+	int ret;
+
+	aio = cygnus_dai_get_dma_data(substream);
+	if (!aio)
+		return -ENODEV;
+
+	dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum);
+
+	snd_soc_set_runtime_hwparams(substream, &cygnus_pcm_hw);
+
+	ret = snd_pcm_hw_constraint_step(runtime, 0,
+		SNDRV_PCM_HW_PARAM_PERIOD_BYTES, PERIOD_BYTES_MIN);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_pcm_hw_constraint_step(runtime, 0,
+		SNDRV_PCM_HW_PARAM_BUFFER_BYTES, PERIOD_BYTES_MIN);
+	if (ret < 0)
+		return ret;
+	/*
+	 * Keep track of which substream belongs to which port.
+	 * This info is needed by snd_pcm_period_elapsed() in irq_handler
+	 */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		aio->play_stream = substream;
+	else
+		aio->capture_stream = substream;
+
+	return 0;
+}
+
+static int cygnus_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct cygnus_aio_port *aio;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	dev_dbg(rtd->cpu_dai->dev, "%s  port %d\n", __func__, aio->portnum);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		aio->play_stream = NULL;
+	else
+		aio->capture_stream = NULL;
+
+	if (!aio->play_stream && !aio->capture_stream)
+		dev_dbg(rtd->cpu_dai->dev, "freed  port %d\n", aio->portnum);
+
+	return 0;
+}
+
+static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct cygnus_aio_port *aio;
+	int ret = 0;
+
+	aio = cygnus_dai_get_dma_data(substream);
+	dev_dbg(rtd->cpu_dai->dev, "%s  port %d\n", __func__, aio->portnum);
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+	runtime->dma_bytes = params_buffer_bytes(params);
+
+	return ret;
+}
+
+static int cygnus_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct cygnus_aio_port *aio;
+
+	aio = cygnus_dai_get_dma_data(substream);
+	dev_dbg(rtd->cpu_dai->dev, "%s  port %d\n", __func__, aio->portnum);
+
+	snd_pcm_set_runtime_buffer(substream, NULL);
+	return 0;
+}
+
+static int cygnus_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct cygnus_aio_port *aio;
+	unsigned long bufsize, periodsize;
+	int ret = 0;
+	bool is_play;
+	u32 start;
+	struct ringbuf_regs *p_rbuf = NULL;
+
+	aio = cygnus_dai_get_dma_data(substream);
+	dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum);
+
+	bufsize = snd_pcm_lib_buffer_bytes(substream);
+	periodsize = snd_pcm_lib_period_bytes(substream);
+
+	dev_dbg(rtd->cpu_dai->dev, "%s (buf_size %lu) (period_size %lu)\n",
+			__func__, bufsize, periodsize);
+
+	configure_ringbuf_regs(substream);
+
+	p_rbuf = get_ringbuf(substream);
+
+	start = runtime->dma_addr;
+
+	is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 1 : 0;
+
+	ringbuf_set_initial(aio->cygaud->audio, p_rbuf, is_play, start,
+				periodsize, bufsize);
+
+	return ret;
+}
+
+static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct cygnus_aio_port *aio;
+	unsigned int res = 0, cur = 0, base = 0;
+	struct ringbuf_regs *p_rbuf = NULL;
+
+	aio = cygnus_dai_get_dma_data(substream);
+
+	/*
+	 * Get the offset of the current read (for playack) or write
+	 * index (for capture).  Report this value back to the asoc framework.
+	 */
+	p_rbuf = get_ringbuf(substream);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		cur = readl(aio->cygaud->audio + p_rbuf->rdaddr);
+	else
+		cur = readl(aio->cygaud->audio + p_rbuf->wraddr);
+
+	base = readl(aio->cygaud->audio + p_rbuf->baseaddr);
+
+	/*
+	 * Mask off the MSB of the rdaddr,wraddr and baseaddr
+	 * since MSB is not part of the address
+	 */
+	res = (cur & 0x7fffffff) - (base & 0x7fffffff);
+
+	return bytes_to_frames(substream->runtime, res);
+}
+
+static int cygnus_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	size_t size;
+
+	size = cygnus_pcm_hw.buffer_bytes_max;
+
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+	buf->area = dma_alloc_coherent(pcm->card->dev, size,
+			&buf->addr, GFP_KERNEL);
+
+	dev_dbg(rtd->cpu_dai->dev, "%s: size 0x%zx @ %pK\n",
+				__func__, size, buf->area);
+
+	if (!buf->area) {
+		dev_err(rtd->cpu_dai->dev, "%s: dma_alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	buf->bytes = size;
+
+	return 0;
+}
+
+
+static const struct snd_pcm_ops cygnus_pcm_ops = {
+	.open		= cygnus_pcm_open,
+	.close		= cygnus_pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= cygnus_pcm_hw_params,
+	.hw_free	= cygnus_pcm_hw_free,
+	.prepare	= cygnus_pcm_prepare,
+	.trigger	= cygnus_pcm_trigger,
+	.pointer	= cygnus_pcm_pointer,
+};
+
+static void cygnus_dma_free_dma_buffers(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_dma_buffer *buf;
+
+	substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	if (substream) {
+		buf = &substream->dma_buffer;
+		if (buf->area) {
+			dma_free_coherent(pcm->card->dev, buf->bytes,
+				buf->area, buf->addr);
+			buf->area = NULL;
+		}
+	}
+
+	substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+	if (substream) {
+		buf = &substream->dma_buffer;
+		if (buf->area) {
+			dma_free_coherent(pcm->card->dev, buf->bytes,
+				buf->area, buf->addr);
+			buf->area = NULL;
+		}
+	}
+}
+
+static int cygnus_dma_new(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_card *card = rtd->card->snd_card;
+	struct snd_pcm *pcm = rtd->pcm;
+	int ret;
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &cygnus_dma_dmamask;
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+		ret = cygnus_pcm_preallocate_dma_buffer(pcm,
+				SNDRV_PCM_STREAM_PLAYBACK);
+		if (ret)
+			return ret;
+	}
+
+	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+		ret = cygnus_pcm_preallocate_dma_buffer(pcm,
+				SNDRV_PCM_STREAM_CAPTURE);
+		if (ret) {
+			cygnus_dma_free_dma_buffers(pcm);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static struct snd_soc_platform_driver cygnus_soc_platform = {
+	.ops		= &cygnus_pcm_ops,
+	.pcm_new	= cygnus_dma_new,
+	.pcm_free	= cygnus_dma_free_dma_buffers,
+};
+
+int cygnus_soc_platform_register(struct device *dev,
+				 struct cygnus_audio *cygaud)
+{
+	int rc = 0;
+
+	dev_dbg(dev, "%s Enter\n", __func__);
+
+	rc = devm_request_irq(dev, cygaud->irq_num, cygnus_dma_irq,
+				IRQF_SHARED, "cygnus-audio", cygaud);
+	if (rc) {
+		dev_err(dev, "%s request_irq error %d\n", __func__, rc);
+		return rc;
+	}
+
+	rc = snd_soc_register_platform(dev, &cygnus_soc_platform);
+	if (rc) {
+		dev_err(dev, "%s failed\n", __func__);
+		return rc;
+	}
+
+	return 0;
+}
+
+int cygnus_soc_platform_unregister(struct device *dev)
+{
+	snd_soc_unregister_platform(dev);
+
+	return 0;
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Cygnus ASoC PCM module");
-- 
2.8.1



From broonie at kernel.org  Tue May 31 10:45:55 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 31 May 2016 18:45:55 +0100
Subject: Applied "ASoC: cygnus: Add Cygnus audio DAI driver" to the asoc tree
In-Reply-To: <1459383886-20317-3-git-send-email-simran.rai@broadcom.com>
Message-ID: <E1b7njn-00062D-KV@debutante>

The patch

   ASoC: cygnus: Add Cygnus audio DAI driver

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From a6ee05d94e8fca0c9eed71669a32c8f1fd0f24e7 Mon Sep 17 00:00:00 2001
From: Simran Rai <simran.rai at broadcom.com>
Date: Tue, 17 May 2016 17:01:08 -0700
Subject: [PATCH] ASoC: cygnus: Add Cygnus audio DAI driver

This patch adds Cygnus audio DAI driver. It supports I2S, TDM
and SPDIF modes and uses three clocks derived from PLL.

This patchset has been tested on Cygnus wireless audio
bcm958305K board.

Signed-off-by: Lori Hikichi <lhikichi at broadcom.com>
Signed-off-by: Simran Rai <ssimran at broadcom.com>
Reviewed-by: Ray Jui <rjui at broadcom.com>
Reviewed-by: Arun Parameswaran <arunp at broadcom.com>
Reviewed-by: Scott Branden <sbranden at broadcom.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 sound/soc/bcm/cygnus-ssp.c | 1529 ++++++++++++++++++++++++++++++++++++++++++++
 sound/soc/bcm/cygnus-ssp.h |  139 ++++
 2 files changed, 1668 insertions(+)
 create mode 100644 sound/soc/bcm/cygnus-ssp.c
 create mode 100644 sound/soc/bcm/cygnus-ssp.h

diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c
new file mode 100644
index 000000000000..e710bb0c5637
--- /dev/null
+++ b/sound/soc/bcm/cygnus-ssp.c
@@ -0,0 +1,1529 @@
+/*
+ * Copyright (C) 2014-2015 Broadcom Corporation
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+
+#include "cygnus-ssp.h"
+
+#define DEFAULT_VCO    1354750204
+
+#define CYGNUS_TDM_RATE \
+		(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
+		SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050 | \
+		SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+		SNDRV_PCM_RATE_48000)
+
+#define CAPTURE_FCI_ID_BASE 0x180
+#define CYGNUS_SSP_TRISTATE_MASK 0x001fff
+#define CYGNUS_PLLCLKSEL_MASK 0xf
+
+/* Used with stream_on field to indicate which streams are active */
+#define  PLAYBACK_STREAM_MASK   BIT(0)
+#define  CAPTURE_STREAM_MASK    BIT(1)
+
+#define I2S_STREAM_CFG_MASK      0xff003ff
+#define I2S_CAP_STREAM_CFG_MASK  0xf0
+#define SPDIF_STREAM_CFG_MASK    0x3ff
+#define CH_GRP_STEREO            0x1
+
+/* Begin register offset defines */
+#define AUD_MISC_SEROUT_OE_REG_BASE  0x01c
+#define AUD_MISC_SEROUT_SPDIF_OE  12
+#define AUD_MISC_SEROUT_MCLK_OE   3
+#define AUD_MISC_SEROUT_LRCK_OE   2
+#define AUD_MISC_SEROUT_SCLK_OE   1
+#define AUD_MISC_SEROUT_SDAT_OE   0
+
+/* AUD_FMM_BF_CTRL_xxx regs */
+#define BF_DST_CFG0_OFFSET  0x100
+#define BF_DST_CFG1_OFFSET  0x104
+#define BF_DST_CFG2_OFFSET  0x108
+
+#define BF_DST_CTRL0_OFFSET 0x130
+#define BF_DST_CTRL1_OFFSET 0x134
+#define BF_DST_CTRL2_OFFSET 0x138
+
+#define BF_SRC_CFG0_OFFSET  0x148
+#define BF_SRC_CFG1_OFFSET  0x14c
+#define BF_SRC_CFG2_OFFSET  0x150
+#define BF_SRC_CFG3_OFFSET  0x154
+
+#define BF_SRC_CTRL0_OFFSET 0x1c0
+#define BF_SRC_CTRL1_OFFSET 0x1c4
+#define BF_SRC_CTRL2_OFFSET 0x1c8
+#define BF_SRC_CTRL3_OFFSET 0x1cc
+
+#define BF_SRC_GRP0_OFFSET  0x1fc
+#define BF_SRC_GRP1_OFFSET  0x200
+#define BF_SRC_GRP2_OFFSET  0x204
+#define BF_SRC_GRP3_OFFSET  0x208
+
+#define BF_SRC_GRP_EN_OFFSET        0x320
+#define BF_SRC_GRP_FLOWON_OFFSET    0x324
+#define BF_SRC_GRP_SYNC_DIS_OFFSET  0x328
+
+/* AUD_FMM_IOP_OUT_I2S_xxx regs */
+#define OUT_I2S_0_STREAM_CFG_OFFSET 0xa00
+#define OUT_I2S_0_CFG_OFFSET        0xa04
+#define OUT_I2S_0_MCLK_CFG_OFFSET   0xa0c
+
+#define OUT_I2S_1_STREAM_CFG_OFFSET 0xa40
+#define OUT_I2S_1_CFG_OFFSET        0xa44
+#define OUT_I2S_1_MCLK_CFG_OFFSET   0xa4c
+
+#define OUT_I2S_2_STREAM_CFG_OFFSET 0xa80
+#define OUT_I2S_2_CFG_OFFSET        0xa84
+#define OUT_I2S_2_MCLK_CFG_OFFSET   0xa8c
+
+/* AUD_FMM_IOP_OUT_SPDIF_xxx regs */
+#define SPDIF_STREAM_CFG_OFFSET  0xac0
+#define SPDIF_CTRL_OFFSET        0xac4
+#define SPDIF_FORMAT_CFG_OFFSET  0xad8
+#define SPDIF_MCLK_CFG_OFFSET    0xadc
+
+/* AUD_FMM_IOP_PLL_0_xxx regs */
+#define IOP_PLL_0_MACRO_OFFSET    0xb00
+#define IOP_PLL_0_MDIV_Ch0_OFFSET 0xb14
+#define IOP_PLL_0_MDIV_Ch1_OFFSET 0xb18
+#define IOP_PLL_0_MDIV_Ch2_OFFSET 0xb1c
+
+#define IOP_PLL_0_ACTIVE_MDIV_Ch0_OFFSET 0xb30
+#define IOP_PLL_0_ACTIVE_MDIV_Ch1_OFFSET 0xb34
+#define IOP_PLL_0_ACTIVE_MDIV_Ch2_OFFSET 0xb38
+
+/* AUD_FMM_IOP_xxx regs */
+#define IOP_PLL_0_CONTROL_OFFSET     0xb04
+#define IOP_PLL_0_USER_NDIV_OFFSET   0xb08
+#define IOP_PLL_0_ACTIVE_NDIV_OFFSET 0xb20
+#define IOP_PLL_0_RESET_OFFSET       0xb5c
+
+/* AUD_FMM_IOP_IN_I2S_xxx regs */
+#define IN_I2S_0_STREAM_CFG_OFFSET 0x00
+#define IN_I2S_0_CFG_OFFSET        0x04
+#define IN_I2S_1_STREAM_CFG_OFFSET 0x40
+#define IN_I2S_1_CFG_OFFSET        0x44
+#define IN_I2S_2_STREAM_CFG_OFFSET 0x80
+#define IN_I2S_2_CFG_OFFSET        0x84
+
+/* AUD_FMM_IOP_MISC_xxx regs */
+#define IOP_SW_INIT_LOGIC          0x1c0
+
+/* End register offset defines */
+
+
+/* AUD_FMM_IOP_OUT_I2S_x_MCLK_CFG_0_REG */
+#define I2S_OUT_MCLKRATE_SHIFT 16
+
+/* AUD_FMM_IOP_OUT_I2S_x_MCLK_CFG_REG */
+#define I2S_OUT_PLLCLKSEL_SHIFT  0
+
+/* AUD_FMM_IOP_OUT_I2S_x_STREAM_CFG */
+#define I2S_OUT_STREAM_ENA  31
+#define I2S_OUT_STREAM_CFG_GROUP_ID  20
+#define I2S_OUT_STREAM_CFG_CHANNEL_GROUPING  24
+
+/* AUD_FMM_IOP_IN_I2S_x_CAP */
+#define I2S_IN_STREAM_CFG_CAP_ENA   31
+#define I2S_IN_STREAM_CFG_0_GROUP_ID 4
+
+/* AUD_FMM_IOP_OUT_I2S_x_I2S_CFG_REG */
+#define I2S_OUT_CFGX_CLK_ENA         0
+#define I2S_OUT_CFGX_DATA_ENABLE     1
+#define I2S_OUT_CFGX_DATA_ALIGNMENT  6
+#define I2S_OUT_CFGX_BITS_PER_SLOT  13
+#define I2S_OUT_CFGX_VALID_SLOT     14
+#define I2S_OUT_CFGX_FSYNC_WIDTH    18
+#define I2S_OUT_CFGX_SCLKS_PER_1FS_DIV32 26
+#define I2S_OUT_CFGX_SLAVE_MODE     30
+#define I2S_OUT_CFGX_TDM_MODE       31
+
+/* AUD_FMM_BF_CTRL_SOURCECH_CFGx_REG */
+#define BF_SRC_CFGX_SFIFO_ENA              0
+#define BF_SRC_CFGX_BUFFER_PAIR_ENABLE     1
+#define BF_SRC_CFGX_SAMPLE_CH_MODE         2
+#define BF_SRC_CFGX_SFIFO_SZ_DOUBLE        5
+#define BF_SRC_CFGX_NOT_PAUSE_WHEN_EMPTY  10
+#define BF_SRC_CFGX_BIT_RES               20
+#define BF_SRC_CFGX_PROCESS_SEQ_ID_VALID  31
+
+/* AUD_FMM_BF_CTRL_DESTCH_CFGx_REG */
+#define BF_DST_CFGX_CAP_ENA              0
+#define BF_DST_CFGX_BUFFER_PAIR_ENABLE   1
+#define BF_DST_CFGX_DFIFO_SZ_DOUBLE      2
+#define BF_DST_CFGX_NOT_PAUSE_WHEN_FULL 11
+#define BF_DST_CFGX_FCI_ID              12
+#define BF_DST_CFGX_CAP_MODE            24
+#define BF_DST_CFGX_PROC_SEQ_ID_VALID   31
+
+/* AUD_FMM_IOP_OUT_SPDIF_xxx */
+#define SPDIF_0_OUT_DITHER_ENA     3
+#define SPDIF_0_OUT_STREAM_ENA    31
+
+/* AUD_FMM_IOP_PLL_0_USER */
+#define IOP_PLL_0_USER_NDIV_FRAC   10
+
+/* AUD_FMM_IOP_PLL_0_ACTIVE */
+#define IOP_PLL_0_ACTIVE_NDIV_FRAC 10
+
+
+#define INIT_SSP_REGS(num) (struct cygnus_ssp_regs){ \
+		.i2s_stream_cfg = OUT_I2S_ ##num## _STREAM_CFG_OFFSET, \
+		.i2s_cap_stream_cfg = IN_I2S_ ##num## _STREAM_CFG_OFFSET, \
+		.i2s_cfg = OUT_I2S_ ##num## _CFG_OFFSET, \
+		.i2s_cap_cfg = IN_I2S_ ##num## _CFG_OFFSET, \
+		.i2s_mclk_cfg = OUT_I2S_ ##num## _MCLK_CFG_OFFSET, \
+		.bf_destch_ctrl = BF_DST_CTRL ##num## _OFFSET, \
+		.bf_destch_cfg = BF_DST_CFG ##num## _OFFSET, \
+		.bf_sourcech_ctrl = BF_SRC_CTRL ##num## _OFFSET, \
+		.bf_sourcech_cfg = BF_SRC_CFG ##num## _OFFSET, \
+		.bf_sourcech_grp = BF_SRC_GRP ##num## _OFFSET \
+}
+
+struct pll_macro_entry {
+	u32 mclk;
+	u32 pll_ch_num;
+};
+
+/*
+ * PLL has 3 output channels (1x, 2x, and 4x). Below are
+ * the common MCLK frequencies used by audio driver
+ */
+static const struct pll_macro_entry pll_predef_mclk[] = {
+	{ 4096000, 0},
+	{ 8192000, 1},
+	{16384000, 2},
+
+	{ 5644800, 0},
+	{11289600, 1},
+	{22579200, 2},
+
+	{ 6144000, 0},
+	{12288000, 1},
+	{24576000, 2},
+
+	{12288000, 0},
+	{24576000, 1},
+	{49152000, 2},
+
+	{22579200, 0},
+	{45158400, 1},
+	{90316800, 2},
+
+	{24576000, 0},
+	{49152000, 1},
+	{98304000, 2},
+};
+
+/* List of valid frame sizes for tdm mode */
+static const int ssp_valid_tdm_framesize[] = {32, 64, 128, 256, 512};
+
+/*
+ * Use this relationship to derive the sampling rate (lrclk)
+ * lrclk = (mclk) / ((2*mclk_to_sclk_ratio) * (32 * SCLK))).
+ *
+ * Use mclk and pll_ch from the table above
+ *
+ * Valid SCLK = 0/1/2/4/8/12
+ *
+ * mclk_to_sclk_ratio = number of MCLK per SCLK. Division is twice the
+ * value programmed in this field.
+ * Valid mclk_to_sclk_ratio = 1 through to 15
+ *
+ * eg: To set lrclk = 48khz, set mclk = 12288000, mclk_to_sclk_ratio = 2,
+ * SCLK = 64
+ */
+struct _ssp_clk_coeff {
+	u32 mclk;
+	u32 sclk_rate;
+	u32 rate;
+	u32 mclk_rate;
+};
+
+static const struct _ssp_clk_coeff ssp_clk_coeff[] = {
+	{ 4096000,  32,  16000, 4},
+	{ 4096000,  32,  32000, 2},
+	{ 4096000,  64,   8000, 4},
+	{ 4096000,  64,  16000, 2},
+	{ 4096000,  64,  32000, 1},
+	{ 4096000, 128,   8000, 2},
+	{ 4096000, 128,  16000, 1},
+	{ 4096000, 256,   8000, 1},
+
+	{ 6144000,  32,  16000, 6},
+	{ 6144000,  32,  32000, 3},
+	{ 6144000,  32,  48000, 2},
+	{ 6144000,  32,  96000, 1},
+	{ 6144000,  64,   8000, 6},
+	{ 6144000,  64,  16000, 3},
+	{ 6144000,  64,  48000, 1},
+	{ 6144000, 128,   8000, 3},
+
+	{ 8192000,  32,  32000, 4},
+	{ 8192000,  64,  16000, 4},
+	{ 8192000,  64,  32000, 2},
+	{ 8192000, 128,   8000, 4},
+	{ 8192000, 128,  16000, 2},
+	{ 8192000, 128,  32000, 1},
+	{ 8192000, 256,   8000, 2},
+	{ 8192000, 256,  16000, 1},
+	{ 8192000, 512,   8000, 1},
+
+	{12288000,  32,  32000, 6},
+	{12288000,  32,  48000, 4},
+	{12288000,  32,  96000, 2},
+	{12288000,  32, 192000, 1},
+	{12288000,  64,  16000, 6},
+	{12288000,  64,  32000, 3},
+	{12288000,  64,  48000, 2},
+	{12288000,  64,  96000, 1},
+	{12288000, 128,   8000, 6},
+	{12288000, 128,  16000, 3},
+	{12288000, 128,  48000, 1},
+	{12288000, 256,   8000, 3},
+
+	{16384000,  64,  32000, 4},
+	{16384000, 128,  16000, 4},
+	{16384000, 128,  32000, 2},
+	{16384000, 256,   8000, 4},
+	{16384000, 256,  16000, 2},
+	{16384000, 256,  32000, 1},
+	{16384000, 512,   8000, 2},
+	{16384000, 512,  16000, 1},
+
+	{24576000,  32,  96000, 4},
+	{24576000,  32, 192000, 2},
+	{24576000,  64,  32000, 6},
+	{24576000,  64,  48000, 4},
+	{24576000,  64,  96000, 2},
+	{24576000,  64, 192000, 1},
+	{24576000, 128,  16000, 6},
+	{24576000, 128,  32000, 3},
+	{24576000, 128,  48000, 2},
+	{24576000, 256,   8000, 6},
+	{24576000, 256,  16000, 3},
+	{24576000, 256,  48000, 1},
+	{24576000, 512,   8000, 3},
+
+	{49152000,  32, 192000, 4},
+	{49152000,  64,  96000, 4},
+	{49152000,  64, 192000, 2},
+	{49152000, 128,  32000, 6},
+	{49152000, 128,  48000, 4},
+	{49152000, 128,  96000, 2},
+	{49152000, 128, 192000, 1},
+	{49152000, 256,  16000, 6},
+	{49152000, 256,  32000, 3},
+	{49152000, 256,  48000, 2},
+	{49152000, 256,  96000, 1},
+	{49152000, 512,   8000, 6},
+	{49152000, 512,  16000, 3},
+	{49152000, 512,  48000, 1},
+
+	{ 5644800,  32,  22050, 4},
+	{ 5644800,  32,  44100, 2},
+	{ 5644800,  32,  88200, 1},
+	{ 5644800,  64,  11025, 4},
+	{ 5644800,  64,  22050, 2},
+	{ 5644800,  64,  44100, 1},
+
+	{11289600,  32,  44100, 4},
+	{11289600,  32,  88200, 2},
+	{11289600,  32, 176400, 1},
+	{11289600,  64,  22050, 4},
+	{11289600,  64,  44100, 2},
+	{11289600,  64,  88200, 1},
+	{11289600, 128,  11025, 4},
+	{11289600, 128,  22050, 2},
+	{11289600, 128,  44100, 1},
+
+	{22579200,  32,  88200, 4},
+	{22579200,  32, 176400, 2},
+	{22579200,  64,  44100, 4},
+	{22579200,  64,  88200, 2},
+	{22579200,  64, 176400, 1},
+	{22579200, 128,  22050, 4},
+	{22579200, 128,  44100, 2},
+	{22579200, 128,  88200, 1},
+	{22579200, 256,  11025, 4},
+	{22579200, 256,  22050, 2},
+	{22579200, 256,  44100, 1},
+
+	{45158400,  32, 176400, 4},
+	{45158400,  64,  88200, 4},
+	{45158400,  64, 176400, 2},
+	{45158400, 128,  44100, 4},
+	{45158400, 128,  88200, 2},
+	{45158400, 128, 176400, 1},
+	{45158400, 256,  22050, 4},
+	{45158400, 256,  44100, 2},
+	{45158400, 256,  88200, 1},
+	{45158400, 512,  11025, 4},
+	{45158400, 512,  22050, 2},
+	{45158400, 512,  44100, 1},
+};
+
+static struct cygnus_aio_port *cygnus_dai_get_portinfo(struct snd_soc_dai *dai)
+{
+	struct cygnus_audio *cygaud = snd_soc_dai_get_drvdata(dai);
+
+	return &cygaud->portinfo[dai->id];
+}
+
+static int audio_ssp_init_portregs(struct cygnus_aio_port *aio)
+{
+	u32 value, fci_id;
+	int status = 0;
+
+	switch (aio->port_type) {
+	case PORT_TDM:
+		value = readl(aio->cygaud->audio + aio->regs.i2s_stream_cfg);
+		value &= ~I2S_STREAM_CFG_MASK;
+
+		/* Set Group ID */
+		writel(aio->portnum,
+			aio->cygaud->audio + aio->regs.bf_sourcech_grp);
+
+		/* Configure the AUD_FMM_IOP_OUT_I2S_x_STREAM_CFG reg */
+		value |= aio->portnum << I2S_OUT_STREAM_CFG_GROUP_ID;
+		value |= aio->portnum; /* FCI ID is the port num */
+		value |= CH_GRP_STEREO << I2S_OUT_STREAM_CFG_CHANNEL_GROUPING;
+		writel(value, aio->cygaud->audio + aio->regs.i2s_stream_cfg);
+
+		/* Configure the AUD_FMM_BF_CTRL_SOURCECH_CFGX reg */
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value &= ~BIT(BF_SRC_CFGX_NOT_PAUSE_WHEN_EMPTY);
+		value |= BIT(BF_SRC_CFGX_SFIFO_SZ_DOUBLE);
+		value |= BIT(BF_SRC_CFGX_PROCESS_SEQ_ID_VALID);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+
+		/* Configure the AUD_FMM_IOP_IN_I2S_x_CAP_STREAM_CFG_0 reg */
+		value = readl(aio->cygaud->i2s_in +
+			aio->regs.i2s_cap_stream_cfg);
+		value &= ~I2S_CAP_STREAM_CFG_MASK;
+		value |= aio->portnum << I2S_IN_STREAM_CFG_0_GROUP_ID;
+		writel(value, aio->cygaud->i2s_in +
+			aio->regs.i2s_cap_stream_cfg);
+
+		/* Configure the AUD_FMM_BF_CTRL_DESTCH_CFGX_REG_BASE reg */
+		fci_id = CAPTURE_FCI_ID_BASE + aio->portnum;
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_destch_cfg);
+		value |= BIT(BF_DST_CFGX_DFIFO_SZ_DOUBLE);
+		value &= ~BIT(BF_DST_CFGX_NOT_PAUSE_WHEN_FULL);
+		value |= (fci_id << BF_DST_CFGX_FCI_ID);
+		value |= BIT(BF_DST_CFGX_PROC_SEQ_ID_VALID);
+		writel(value, aio->cygaud->audio + aio->regs.bf_destch_cfg);
+
+		/* Enable the transmit pin for this port */
+		value = readl(aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+		value &= ~BIT((aio->portnum * 4) + AUD_MISC_SEROUT_SDAT_OE);
+		writel(value, aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+		break;
+	case PORT_SPDIF:
+		writel(aio->portnum, aio->cygaud->audio + BF_SRC_GRP3_OFFSET);
+
+		value = readl(aio->cygaud->audio + SPDIF_CTRL_OFFSET);
+		value |= BIT(SPDIF_0_OUT_DITHER_ENA);
+		writel(value, aio->cygaud->audio + SPDIF_CTRL_OFFSET);
+
+		/* Enable and set the FCI ID for the SPDIF channel */
+		value = readl(aio->cygaud->audio + SPDIF_STREAM_CFG_OFFSET);
+		value &= ~SPDIF_STREAM_CFG_MASK;
+		value |= aio->portnum; /* FCI ID is the port num */
+		value |= BIT(SPDIF_0_OUT_STREAM_ENA);
+		writel(value, aio->cygaud->audio + SPDIF_STREAM_CFG_OFFSET);
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value &= ~BIT(BF_SRC_CFGX_NOT_PAUSE_WHEN_EMPTY);
+		value |= BIT(BF_SRC_CFGX_SFIFO_SZ_DOUBLE);
+		value |= BIT(BF_SRC_CFGX_PROCESS_SEQ_ID_VALID);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+
+		/* Enable the spdif output pin */
+		value = readl(aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+		value &= ~BIT(AUD_MISC_SEROUT_SPDIF_OE);
+		writel(value, aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+		break;
+	default:
+		dev_err(aio->cygaud->dev, "Port not supported\n");
+		status = -EINVAL;
+	}
+
+	return status;
+}
+
+static void audio_ssp_in_enable(struct cygnus_aio_port *aio)
+{
+	u32 value;
+
+	value = readl(aio->cygaud->audio + aio->regs.bf_destch_cfg);
+	value |= BIT(BF_DST_CFGX_CAP_ENA);
+	writel(value, aio->cygaud->audio + aio->regs.bf_destch_cfg);
+
+	writel(0x1, aio->cygaud->audio + aio->regs.bf_destch_ctrl);
+
+	value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+	value |= BIT(I2S_OUT_CFGX_CLK_ENA);
+	value |= BIT(I2S_OUT_CFGX_DATA_ENABLE);
+	writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
+
+	value = readl(aio->cygaud->i2s_in + aio->regs.i2s_cap_stream_cfg);
+	value |= BIT(I2S_IN_STREAM_CFG_CAP_ENA);
+	writel(value, aio->cygaud->i2s_in + aio->regs.i2s_cap_stream_cfg);
+
+	aio->streams_on |= CAPTURE_STREAM_MASK;
+}
+
+static void audio_ssp_in_disable(struct cygnus_aio_port *aio)
+{
+	u32 value;
+
+	value = readl(aio->cygaud->i2s_in + aio->regs.i2s_cap_stream_cfg);
+	value &= ~BIT(I2S_IN_STREAM_CFG_CAP_ENA);
+	writel(value, aio->cygaud->i2s_in + aio->regs.i2s_cap_stream_cfg);
+
+	aio->streams_on &= ~CAPTURE_STREAM_MASK;
+
+	/* If both playback and capture are off */
+	if (!aio->streams_on) {
+		value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+		value &= ~BIT(I2S_OUT_CFGX_CLK_ENA);
+		value &= ~BIT(I2S_OUT_CFGX_DATA_ENABLE);
+		writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
+	}
+
+	writel(0x0, aio->cygaud->audio + aio->regs.bf_destch_ctrl);
+
+	value = readl(aio->cygaud->audio + aio->regs.bf_destch_cfg);
+	value &= ~BIT(BF_DST_CFGX_CAP_ENA);
+	writel(value, aio->cygaud->audio + aio->regs.bf_destch_cfg);
+}
+
+static int audio_ssp_out_enable(struct cygnus_aio_port *aio)
+{
+	u32 value;
+	int status = 0;
+
+	switch (aio->port_type) {
+	case PORT_TDM:
+		value = readl(aio->cygaud->audio + aio->regs.i2s_stream_cfg);
+		value |= BIT(I2S_OUT_STREAM_ENA);
+		writel(value, aio->cygaud->audio + aio->regs.i2s_stream_cfg);
+
+		writel(1, aio->cygaud->audio + aio->regs.bf_sourcech_ctrl);
+
+		value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+		value |= BIT(I2S_OUT_CFGX_CLK_ENA);
+		value |= BIT(I2S_OUT_CFGX_DATA_ENABLE);
+		writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value |= BIT(BF_SRC_CFGX_SFIFO_ENA);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+
+		aio->streams_on |= PLAYBACK_STREAM_MASK;
+		break;
+	case PORT_SPDIF:
+		value = readl(aio->cygaud->audio + SPDIF_FORMAT_CFG_OFFSET);
+		value |= 0x3;
+		writel(value, aio->cygaud->audio + SPDIF_FORMAT_CFG_OFFSET);
+
+		writel(1, aio->cygaud->audio + aio->regs.bf_sourcech_ctrl);
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value |= BIT(BF_SRC_CFGX_SFIFO_ENA);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		break;
+	default:
+		dev_err(aio->cygaud->dev,
+			"Port not supported %d\n", aio->portnum);
+		status = -EINVAL;
+	}
+
+	return status;
+}
+
+static int audio_ssp_out_disable(struct cygnus_aio_port *aio)
+{
+	u32 value;
+	int status = 0;
+
+	switch (aio->port_type) {
+	case PORT_TDM:
+		aio->streams_on &= ~PLAYBACK_STREAM_MASK;
+
+		/* If both playback and capture are off */
+		if (!aio->streams_on) {
+			value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+			value &= ~BIT(I2S_OUT_CFGX_CLK_ENA);
+			value &= ~BIT(I2S_OUT_CFGX_DATA_ENABLE);
+			writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
+		}
+
+		/* set group_sync_dis = 1 */
+		value = readl(aio->cygaud->audio + BF_SRC_GRP_SYNC_DIS_OFFSET);
+		value |= BIT(aio->portnum);
+		writel(value, aio->cygaud->audio + BF_SRC_GRP_SYNC_DIS_OFFSET);
+
+		writel(0, aio->cygaud->audio + aio->regs.bf_sourcech_ctrl);
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value &= ~BIT(BF_SRC_CFGX_SFIFO_ENA);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+
+		/* set group_sync_dis = 0 */
+		value = readl(aio->cygaud->audio + BF_SRC_GRP_SYNC_DIS_OFFSET);
+		value &= ~BIT(aio->portnum);
+		writel(value, aio->cygaud->audio + BF_SRC_GRP_SYNC_DIS_OFFSET);
+
+		value = readl(aio->cygaud->audio + aio->regs.i2s_stream_cfg);
+		value &= ~BIT(I2S_OUT_STREAM_ENA);
+		writel(value, aio->cygaud->audio + aio->regs.i2s_stream_cfg);
+
+		/* IOP SW INIT on OUT_I2S_x */
+		value = readl(aio->cygaud->i2s_in + IOP_SW_INIT_LOGIC);
+		value |= BIT(aio->portnum);
+		writel(value, aio->cygaud->i2s_in + IOP_SW_INIT_LOGIC);
+		value &= ~BIT(aio->portnum);
+		writel(value, aio->cygaud->i2s_in + IOP_SW_INIT_LOGIC);
+		break;
+	case PORT_SPDIF:
+		value = readl(aio->cygaud->audio + SPDIF_FORMAT_CFG_OFFSET);
+		value &= ~0x3;
+		writel(value, aio->cygaud->audio + SPDIF_FORMAT_CFG_OFFSET);
+		writel(0, aio->cygaud->audio + aio->regs.bf_sourcech_ctrl);
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value &= ~BIT(BF_SRC_CFGX_SFIFO_ENA);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		break;
+	default:
+		dev_err(aio->cygaud->dev,
+			"Port not supported %d\n", aio->portnum);
+		status = -EINVAL;
+	}
+
+	return status;
+}
+
+static int pll_configure_mclk(struct cygnus_audio *cygaud, u32 mclk,
+	struct cygnus_aio_port *aio)
+{
+	int i = 0, error;
+	bool found = false;
+	const struct pll_macro_entry *p_entry;
+	struct clk *ch_clk;
+
+	for (i = 0; i < ARRAY_SIZE(pll_predef_mclk); i++) {
+		p_entry = &pll_predef_mclk[i];
+		if (p_entry->mclk == mclk) {
+			found = true;
+			break;
+		}
+	}
+	if (!found) {
+		dev_err(cygaud->dev,
+			"%s No valid mclk freq (%u) found!\n", __func__, mclk);
+		return -EINVAL;
+	}
+
+	ch_clk = cygaud->audio_clk[p_entry->pll_ch_num];
+
+	if ((aio->clk_trace.cap_en) && (!aio->clk_trace.cap_clk_en)) {
+		error = clk_prepare_enable(ch_clk);
+		if (error) {
+			dev_err(cygaud->dev, "%s clk_prepare_enable failed %d\n",
+				__func__, error);
+			return error;
+		}
+		aio->clk_trace.cap_clk_en = true;
+	}
+
+	if ((aio->clk_trace.play_en) && (!aio->clk_trace.play_clk_en)) {
+		error = clk_prepare_enable(ch_clk);
+		if (error) {
+			dev_err(cygaud->dev, "%s clk_prepare_enable failed %d\n",
+				__func__, error);
+			return error;
+		}
+		aio->clk_trace.play_clk_en = true;
+	}
+
+	error = clk_set_rate(ch_clk, mclk);
+	if (error) {
+		dev_err(cygaud->dev, "%s Set MCLK rate failed: %d\n",
+			__func__, error);
+		return error;
+	}
+
+	return p_entry->pll_ch_num;
+}
+
+static int cygnus_ssp_set_clocks(struct cygnus_aio_port *aio,
+			struct cygnus_audio *cygaud)
+{
+	u32 value, i = 0;
+	u32 mask = 0xf;
+	u32 sclk;
+	bool found = false;
+	const struct _ssp_clk_coeff *p_entry = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(ssp_clk_coeff); i++) {
+		p_entry = &ssp_clk_coeff[i];
+		if ((p_entry->rate == aio->lrclk) &&
+		    (p_entry->sclk_rate == aio->bit_per_frame) &&
+		    (p_entry->mclk == aio->mclk)) {
+			found = true;
+			break;
+		}
+	}
+	if (!found) {
+		dev_err(aio->cygaud->dev,
+			"No valid match found in ssp_clk_coeff array\n");
+		dev_err(aio->cygaud->dev, "lrclk = %u, bits/frame = %u, mclk = %u\n",
+			aio->lrclk, aio->bit_per_frame, aio->mclk);
+		return -EINVAL;
+	}
+
+	sclk = aio->bit_per_frame;
+	if (sclk == 512)
+		sclk = 0;
+	/* sclks_per_1fs_div = sclk cycles/32 */
+	sclk /= 32;
+	/* Set sclk rate */
+	switch (aio->port_type) {
+	case PORT_TDM:
+		/* Set number of bitclks per frame */
+		value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+		value &= ~(mask << I2S_OUT_CFGX_SCLKS_PER_1FS_DIV32);
+		value |= sclk << I2S_OUT_CFGX_SCLKS_PER_1FS_DIV32;
+		writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
+		dev_dbg(aio->cygaud->dev,
+			"SCLKS_PER_1FS_DIV32 = 0x%x\n", value);
+		break;
+	case PORT_SPDIF:
+		break;
+	default:
+		dev_err(aio->cygaud->dev, "Unknown port type\n");
+		return -EINVAL;
+	}
+
+	/* Set MCLK_RATE ssp port (spdif and ssp are the same) */
+	value = readl(aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
+	value &= ~(0xf << I2S_OUT_MCLKRATE_SHIFT);
+	value |= (p_entry->mclk_rate << I2S_OUT_MCLKRATE_SHIFT);
+	writel(value, aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
+
+	dev_dbg(aio->cygaud->dev, "mclk cfg reg = 0x%x\n", value);
+	dev_dbg(aio->cygaud->dev, "bits per frame = %u, mclk = %u Hz, lrclk = %u Hz\n",
+			aio->bit_per_frame, aio->mclk, aio->lrclk);
+	return 0;
+}
+
+static int cygnus_ssp_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *params,
+				 struct snd_soc_dai *dai)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
+	struct cygnus_audio *cygaud = snd_soc_dai_get_drvdata(dai);
+	int rate, bitres;
+	u32 value;
+	u32 mask = 0x1f;
+	int ret = 0;
+
+	dev_dbg(aio->cygaud->dev, "%s port = %d\n", __func__, aio->portnum);
+	dev_dbg(aio->cygaud->dev, "params_channels %d\n",
+			params_channels(params));
+	dev_dbg(aio->cygaud->dev, "rate %d\n", params_rate(params));
+	dev_dbg(aio->cygaud->dev, "format %d\n", params_format(params));
+
+	rate = params_rate(params);
+
+	switch (aio->mode) {
+	case CYGNUS_SSPMODE_TDM:
+		if ((rate == 192000) && (params_channels(params) > 4)) {
+			dev_err(aio->cygaud->dev, "Cannot run %d channels at %dHz\n",
+				params_channels(params), rate);
+			return -EINVAL;
+		}
+		break;
+	case CYGNUS_SSPMODE_I2S:
+		aio->bit_per_frame = 64; /* I2S must be 64 bit per frame */
+		break;
+	default:
+		dev_err(aio->cygaud->dev,
+			"%s port running in unknown mode\n", __func__);
+		return -EINVAL;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value &= ~BIT(BF_SRC_CFGX_BUFFER_PAIR_ENABLE);
+		/* Configure channels as mono or stereo/TDM */
+		if (params_channels(params) == 1)
+			value |= BIT(BF_SRC_CFGX_SAMPLE_CH_MODE);
+		else
+			value &= ~BIT(BF_SRC_CFGX_SAMPLE_CH_MODE);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+
+		switch (params_format(params)) {
+		case SNDRV_PCM_FORMAT_S8:
+			if (aio->port_type == PORT_SPDIF) {
+				dev_err(aio->cygaud->dev,
+				"SPDIF does not support 8bit format\n");
+				return -EINVAL;
+			}
+			bitres = 8;
+			break;
+
+		case SNDRV_PCM_FORMAT_S16_LE:
+			bitres = 16;
+			break;
+
+		case SNDRV_PCM_FORMAT_S32_LE:
+			/* 32 bit mode is coded as 0 */
+			bitres = 0;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+		value &= ~(mask << BF_SRC_CFGX_BIT_RES);
+		value |= (bitres << BF_SRC_CFGX_BIT_RES);
+		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
+
+	} else {
+
+		switch (params_format(params)) {
+		case SNDRV_PCM_FORMAT_S16_LE:
+			value = readl(aio->cygaud->audio +
+					aio->regs.bf_destch_cfg);
+			value |= BIT(BF_DST_CFGX_CAP_MODE);
+			writel(value, aio->cygaud->audio +
+					aio->regs.bf_destch_cfg);
+			break;
+
+		case SNDRV_PCM_FORMAT_S32_LE:
+			value = readl(aio->cygaud->audio +
+					aio->regs.bf_destch_cfg);
+			value &= ~BIT(BF_DST_CFGX_CAP_MODE);
+			writel(value, aio->cygaud->audio +
+					aio->regs.bf_destch_cfg);
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+
+	aio->lrclk = rate;
+
+	if (!aio->is_slave)
+		ret = cygnus_ssp_set_clocks(aio, cygaud);
+
+	return ret;
+}
+
+/*
+ * This function sets the mclk frequency for pll clock
+ */
+static int cygnus_ssp_set_sysclk(struct snd_soc_dai *dai,
+			int clk_id, unsigned int freq, int dir)
+{
+	int sel;
+	u32 value;
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
+	struct cygnus_audio *cygaud = snd_soc_dai_get_drvdata(dai);
+
+	dev_dbg(aio->cygaud->dev,
+		"%s Enter port = %d\n", __func__, aio->portnum);
+	sel = pll_configure_mclk(cygaud, freq, aio);
+	if (sel < 0) {
+		dev_err(aio->cygaud->dev,
+			"%s Setting mclk failed.\n", __func__);
+		return -EINVAL;
+	}
+
+	aio->mclk = freq;
+
+	dev_dbg(aio->cygaud->dev, "%s Setting MCLKSEL to %d\n", __func__, sel);
+	value = readl(aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
+	value &= ~(0xf << I2S_OUT_PLLCLKSEL_SHIFT);
+	value |= (sel << I2S_OUT_PLLCLKSEL_SHIFT);
+	writel(value, aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
+
+	return 0;
+}
+
+static int cygnus_ssp_startup(struct snd_pcm_substream *substream,
+			       struct snd_soc_dai *dai)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
+
+	snd_soc_dai_set_dma_data(dai, substream, aio);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		aio->clk_trace.play_en = true;
+	else
+		aio->clk_trace.cap_en = true;
+
+	return 0;
+}
+
+static void cygnus_ssp_shutdown(struct snd_pcm_substream *substream,
+			       struct snd_soc_dai *dai)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		aio->clk_trace.play_en = false;
+	else
+		aio->clk_trace.cap_en = false;
+
+	if (!aio->is_slave) {
+		u32 val;
+
+		val = readl(aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
+		val &= CYGNUS_PLLCLKSEL_MASK;
+		if (val >= ARRAY_SIZE(aio->cygaud->audio_clk)) {
+			dev_err(aio->cygaud->dev, "Clk index %u is out of bounds\n",
+				val);
+			return;
+		}
+
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			if (aio->clk_trace.play_clk_en) {
+				clk_disable_unprepare(aio->cygaud->
+						audio_clk[val]);
+				aio->clk_trace.play_clk_en = false;
+			}
+		} else {
+			if (aio->clk_trace.cap_clk_en) {
+				clk_disable_unprepare(aio->cygaud->
+						audio_clk[val]);
+				aio->clk_trace.cap_clk_en = false;
+			}
+		}
+	}
+}
+
+/*
+ * Bit    Update  Notes
+ * 31     Yes     TDM Mode        (1 = TDM, 0 = i2s)
+ * 30     Yes     Slave Mode	  (1 = Slave, 0 = Master)
+ * 29:26  No      Sclks per frame
+ * 25:18  Yes     FS Width
+ * 17:14  No      Valid Slots
+ * 13     No      Bits		  (1 = 16 bits, 0 = 32 bits)
+ * 12:08  No     Bits per samp
+ * 07     Yes     Justifcation    (1 = LSB, 0 = MSB)
+ * 06     Yes     Alignment       (1 = Delay 1 clk, 0 = no delay
+ * 05     Yes     SCLK polarity   (1 = Rising, 0 = Falling)
+ * 04     Yes     LRCLK Polarity  (1 = High for left, 0 = Low for left)
+ * 03:02  Yes     Reserved - write as zero
+ * 01     No      Data Enable
+ * 00     No      CLK Enable
+ */
+#define I2S_OUT_CFG_REG_UPDATE_MASK   0x3C03FF03
+
+/* Input cfg is same as output, but the FS width is not a valid field */
+#define I2S_IN_CFG_REG_UPDATE_MASK  (I2S_OUT_CFG_REG_UPDATE_MASK | 0x03FC0000)
+
+int cygnus_ssp_set_custom_fsync_width(struct snd_soc_dai *cpu_dai, int len)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
+
+	if ((len > 0) && (len < 256)) {
+		aio->fsync_width = len;
+		return 0;
+	} else {
+		return -EINVAL;
+	}
+}
+
+static int cygnus_ssp_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
+	u32 ssp_curcfg;
+	u32 ssp_newcfg;
+	u32 ssp_outcfg;
+	u32 ssp_incfg;
+	u32 val;
+	u32 mask;
+
+	dev_dbg(aio->cygaud->dev, "%s Enter  fmt: %x\n", __func__, fmt);
+
+	if (aio->port_type == PORT_SPDIF)
+		return -EINVAL;
+
+	ssp_newcfg = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		ssp_newcfg |= BIT(I2S_OUT_CFGX_SLAVE_MODE);
+		aio->is_slave = 1;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		ssp_newcfg &= ~BIT(I2S_OUT_CFGX_SLAVE_MODE);
+		aio->is_slave = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		ssp_newcfg |= BIT(I2S_OUT_CFGX_DATA_ALIGNMENT);
+		ssp_newcfg |= BIT(I2S_OUT_CFGX_FSYNC_WIDTH);
+		aio->mode = CYGNUS_SSPMODE_I2S;
+		break;
+
+	case SND_SOC_DAIFMT_DSP_A:
+	case SND_SOC_DAIFMT_DSP_B:
+		ssp_newcfg |= BIT(I2S_OUT_CFGX_TDM_MODE);
+
+		/* DSP_A = data after FS, DSP_B = data during FS */
+		if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A)
+			ssp_newcfg |= BIT(I2S_OUT_CFGX_DATA_ALIGNMENT);
+
+		if ((aio->fsync_width > 0) && (aio->fsync_width < 256))
+			ssp_newcfg |=
+				(aio->fsync_width << I2S_OUT_CFGX_FSYNC_WIDTH);
+		else
+			ssp_newcfg |= BIT(I2S_OUT_CFGX_FSYNC_WIDTH);
+
+		aio->mode = CYGNUS_SSPMODE_TDM;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * SSP out cfg.
+	 * Retain bits we do not want to update, then OR in new bits
+	 */
+	ssp_curcfg = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+	ssp_outcfg = (ssp_curcfg & I2S_OUT_CFG_REG_UPDATE_MASK) | ssp_newcfg;
+	writel(ssp_outcfg, aio->cygaud->audio + aio->regs.i2s_cfg);
+
+	/*
+	 * SSP in cfg.
+	 * Retain bits we do not want to update, then OR in new bits
+	 */
+	ssp_curcfg = readl(aio->cygaud->i2s_in + aio->regs.i2s_cap_cfg);
+	ssp_incfg = (ssp_curcfg & I2S_IN_CFG_REG_UPDATE_MASK) | ssp_newcfg;
+	writel(ssp_incfg, aio->cygaud->i2s_in + aio->regs.i2s_cap_cfg);
+
+	val = readl(aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+
+	/*
+	 * Configure the word clk and bit clk as output or tristate
+	 * Each port has 4 bits for controlling its pins.
+	 * Shift the mask based upon port number.
+	 */
+	mask = BIT(AUD_MISC_SEROUT_LRCK_OE)
+			| BIT(AUD_MISC_SEROUT_SCLK_OE)
+			| BIT(AUD_MISC_SEROUT_MCLK_OE);
+	mask = mask << (aio->portnum * 4);
+	if (aio->is_slave)
+		/* Set bit for tri-state */
+		val |= mask;
+	else
+		/* Clear bit for drive */
+		val &= ~mask;
+
+	dev_dbg(aio->cygaud->dev, "%s  Set OE bits 0x%x\n", __func__, val);
+	writel(val, aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+
+	return 0;
+}
+
+static int cygnus_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
+			       struct snd_soc_dai *dai)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
+	struct cygnus_audio *cygaud = snd_soc_dai_get_drvdata(dai);
+
+	dev_dbg(aio->cygaud->dev,
+		"%s cmd %d at port = %d\n", __func__, cmd, aio->portnum);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			audio_ssp_out_enable(aio);
+		else
+			audio_ssp_in_enable(aio);
+		cygaud->active_ports++;
+
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			audio_ssp_out_disable(aio);
+		else
+			audio_ssp_in_disable(aio);
+		cygaud->active_ports--;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int cygnus_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
+	unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
+	u32 value;
+	int bits_per_slot = 0;     /* default to 32-bits per slot */
+	int frame_bits;
+	unsigned int active_slots;
+	bool found = false;
+	int i;
+
+	if (tx_mask != rx_mask) {
+		dev_err(aio->cygaud->dev,
+			"%s tx_mask must equal rx_mask\n", __func__);
+		return -EINVAL;
+	}
+
+	active_slots = hweight32(tx_mask);
+
+	if ((active_slots < 0) || (active_slots > 16))
+		return -EINVAL;
+
+	/* Slot value must be even */
+	if (active_slots % 2)
+		return -EINVAL;
+
+	/* We encode 16 slots as 0 in the reg */
+	if (active_slots == 16)
+		active_slots = 0;
+
+	/* Slot Width is either 16 or 32 */
+	switch (slot_width) {
+	case 16:
+		bits_per_slot = 1;
+		break;
+	case 32:
+		bits_per_slot = 0;
+		break;
+	default:
+		bits_per_slot = 0;
+		dev_warn(aio->cygaud->dev,
+			"%s Defaulting Slot Width to 32\n", __func__);
+	}
+
+	frame_bits = slots * slot_width;
+
+	for (i = 0; i < ARRAY_SIZE(ssp_valid_tdm_framesize); i++) {
+		if (ssp_valid_tdm_framesize[i] == frame_bits) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		dev_err(aio->cygaud->dev,
+			"%s In TDM mode, frame bits INVALID (%d)\n",
+			__func__, frame_bits);
+		return -EINVAL;
+	}
+
+	aio->bit_per_frame = frame_bits;
+
+	dev_dbg(aio->cygaud->dev, "%s active_slots %u, bits per frame %d\n",
+			__func__, active_slots, frame_bits);
+
+	/* Set capture side of ssp port */
+	value = readl(aio->cygaud->i2s_in + aio->regs.i2s_cap_cfg);
+	value &= ~(0xf << I2S_OUT_CFGX_VALID_SLOT);
+	value |= (active_slots << I2S_OUT_CFGX_VALID_SLOT);
+	value &= ~BIT(I2S_OUT_CFGX_BITS_PER_SLOT);
+	value |= (bits_per_slot << I2S_OUT_CFGX_BITS_PER_SLOT);
+	writel(value, aio->cygaud->i2s_in + aio->regs.i2s_cap_cfg);
+
+	/* Set playback side of ssp port */
+	value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
+	value &= ~(0xf << I2S_OUT_CFGX_VALID_SLOT);
+	value |= (active_slots << I2S_OUT_CFGX_VALID_SLOT);
+	value &= ~BIT(I2S_OUT_CFGX_BITS_PER_SLOT);
+	value |= (bits_per_slot << I2S_OUT_CFGX_BITS_PER_SLOT);
+	writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int cygnus_ssp_suspend(struct snd_soc_dai *cpu_dai)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
+
+	if (!aio->is_slave) {
+		u32 val;
+
+		val = readl(aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
+		val &= CYGNUS_PLLCLKSEL_MASK;
+		if (val >= ARRAY_SIZE(aio->cygaud->audio_clk)) {
+			dev_err(aio->cygaud->dev, "Clk index %u is out of bounds\n",
+				val);
+			return -EINVAL;
+		}
+
+		if (aio->clk_trace.cap_clk_en)
+			clk_disable_unprepare(aio->cygaud->audio_clk[val]);
+		if (aio->clk_trace.play_clk_en)
+			clk_disable_unprepare(aio->cygaud->audio_clk[val]);
+
+		aio->pll_clk_num = val;
+	}
+
+	return 0;
+}
+
+static int cygnus_ssp_resume(struct snd_soc_dai *cpu_dai)
+{
+	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
+	int error;
+
+	if (!aio->is_slave) {
+		if (aio->clk_trace.cap_clk_en) {
+			error = clk_prepare_enable(aio->cygaud->
+					audio_clk[aio->pll_clk_num]);
+			if (error) {
+				dev_err(aio->cygaud->dev, "%s clk_prepare_enable failed\n",
+					__func__);
+				return -EINVAL;
+			}
+		}
+		if (aio->clk_trace.play_clk_en) {
+			error = clk_prepare_enable(aio->cygaud->
+					audio_clk[aio->pll_clk_num]);
+			if (error) {
+				if (aio->clk_trace.cap_clk_en)
+					clk_disable_unprepare(aio->cygaud->
+						audio_clk[aio->pll_clk_num]);
+				dev_err(aio->cygaud->dev, "%s clk_prepare_enable failed\n",
+					__func__);
+				return -EINVAL;
+			}
+		}
+	}
+
+	return 0;
+}
+#else
+#define cygnus_ssp_suspend NULL
+#define cygnus_ssp_resume  NULL
+#endif
+
+static const struct snd_soc_dai_ops cygnus_ssp_dai_ops = {
+	.startup	= cygnus_ssp_startup,
+	.shutdown	= cygnus_ssp_shutdown,
+	.trigger	= cygnus_ssp_trigger,
+	.hw_params	= cygnus_ssp_hw_params,
+	.set_fmt	= cygnus_ssp_set_fmt,
+	.set_sysclk	= cygnus_ssp_set_sysclk,
+	.set_tdm_slot	= cygnus_set_dai_tdm_slot,
+};
+
+
+#define INIT_CPU_DAI(num) { \
+	.name = "cygnus-ssp" #num, \
+	.playback = { \
+		.channels_min = 1, \
+		.channels_max = 16, \
+		.rates = CYGNUS_TDM_RATE | SNDRV_PCM_RATE_88200 | \
+			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \
+			SNDRV_PCM_RATE_192000, \
+		.formats = SNDRV_PCM_FMTBIT_S8 | \
+				SNDRV_PCM_FMTBIT_S16_LE | \
+				SNDRV_PCM_FMTBIT_S32_LE, \
+	}, \
+	.capture = { \
+		.channels_min = 2, \
+		.channels_max = 16, \
+		.rates = CYGNUS_TDM_RATE | 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_S32_LE, \
+	}, \
+	.ops = &cygnus_ssp_dai_ops, \
+	.suspend = cygnus_ssp_suspend, \
+	.resume = cygnus_ssp_resume, \
+}
+
+static const struct snd_soc_dai_driver cygnus_ssp_dai_info[] = {
+	INIT_CPU_DAI(0),
+	INIT_CPU_DAI(1),
+	INIT_CPU_DAI(2),
+};
+
+static struct snd_soc_dai_driver cygnus_spdif_dai_info = {
+	.name = "cygnus-spdif",
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = CYGNUS_TDM_RATE | 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_S32_LE,
+	},
+	.ops = &cygnus_ssp_dai_ops,
+	.suspend = cygnus_ssp_suspend,
+	.resume = cygnus_ssp_resume,
+};
+
+static struct snd_soc_dai_driver cygnus_ssp_dai[CYGNUS_MAX_PORTS];
+
+static const struct snd_soc_component_driver cygnus_ssp_component = {
+	.name		= "cygnus-audio",
+};
+
+/*
+ * Return < 0 if error
+ * Return 0 if disabled
+ * Return 1 if enabled and node is parsed successfully
+ */
+static int parse_ssp_child_node(struct platform_device *pdev,
+				struct device_node *dn,
+				struct cygnus_audio *cygaud,
+				struct snd_soc_dai_driver *p_dai)
+{
+	struct cygnus_aio_port *aio;
+	struct cygnus_ssp_regs ssp_regs[3];
+	u32 rawval;
+	int portnum = -1;
+	enum cygnus_audio_port_type port_type;
+
+	if (of_property_read_u32(dn, "reg", &rawval)) {
+		dev_err(&pdev->dev, "Missing reg property\n");
+		return -EINVAL;
+	}
+
+	portnum = rawval;
+	switch (rawval) {
+	case 0:
+		ssp_regs[0] = INIT_SSP_REGS(0);
+		port_type = PORT_TDM;
+		break;
+	case 1:
+		ssp_regs[1] = INIT_SSP_REGS(1);
+		port_type = PORT_TDM;
+		break;
+	case 2:
+		ssp_regs[2] = INIT_SSP_REGS(2);
+		port_type = PORT_TDM;
+		break;
+	case 3:
+		port_type = PORT_SPDIF;
+		break;
+	default:
+		dev_err(&pdev->dev, "Bad value for reg %u\n", rawval);
+		return -EINVAL;
+	}
+
+	aio = &cygaud->portinfo[portnum];
+	aio->cygaud = cygaud;
+	aio->portnum = portnum;
+	aio->port_type = port_type;
+	aio->fsync_width = -1;
+
+	switch (port_type) {
+	case PORT_TDM:
+		aio->regs = ssp_regs[portnum];
+		*p_dai = cygnus_ssp_dai_info[portnum];
+		aio->mode = CYGNUS_SSPMODE_UNKNOWN;
+		break;
+
+	case PORT_SPDIF:
+		aio->regs.bf_sourcech_cfg = BF_SRC_CFG3_OFFSET;
+		aio->regs.bf_sourcech_ctrl = BF_SRC_CTRL3_OFFSET;
+		aio->regs.i2s_mclk_cfg = SPDIF_MCLK_CFG_OFFSET;
+		aio->regs.i2s_stream_cfg = SPDIF_STREAM_CFG_OFFSET;
+		*p_dai = cygnus_spdif_dai_info;
+
+		/* For the purposes of this code SPDIF can be I2S mode */
+		aio->mode = CYGNUS_SSPMODE_I2S;
+		break;
+	default:
+		dev_err(&pdev->dev, "Bad value for port_type %d\n", port_type);
+		return -EINVAL;
+	}
+
+	dev_dbg(&pdev->dev, "%s portnum = %d\n", __func__, aio->portnum);
+	aio->streams_on = 0;
+	aio->cygaud->dev = &pdev->dev;
+	aio->clk_trace.play_en = false;
+	aio->clk_trace.cap_en = false;
+
+	audio_ssp_init_portregs(aio);
+	return 0;
+}
+
+static int audio_clk_init(struct platform_device *pdev,
+						struct cygnus_audio *cygaud)
+{
+	int i;
+	char clk_name[PROP_LEN_MAX];
+
+	for (i = 0; i < ARRAY_SIZE(cygaud->audio_clk); i++) {
+		snprintf(clk_name, PROP_LEN_MAX, "ch%d_audio", i);
+
+		cygaud->audio_clk[i] = devm_clk_get(&pdev->dev, clk_name);
+		if (IS_ERR(cygaud->audio_clk[i]))
+			return PTR_ERR(cygaud->audio_clk[i]);
+	}
+
+	return 0;
+}
+
+static int cygnus_ssp_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *child_node;
+	struct resource *res = pdev->resource;
+	struct cygnus_audio *cygaud;
+	int err = -EINVAL;
+	int node_count;
+	int active_port_count;
+
+	cygaud = devm_kzalloc(dev, sizeof(struct cygnus_audio), GFP_KERNEL);
+	if (!cygaud)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, cygaud);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aud");
+	cygaud->audio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(cygaud->audio))
+		return PTR_ERR(cygaud->audio);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "i2s_in");
+	cygaud->i2s_in = devm_ioremap_resource(dev, res);
+	if (IS_ERR(cygaud->i2s_in))
+		return PTR_ERR(cygaud->i2s_in);
+
+	/* Tri-state all controlable pins until we know that we need them */
+	writel(CYGNUS_SSP_TRISTATE_MASK,
+			cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
+
+	node_count = of_get_child_count(pdev->dev.of_node);
+	if ((node_count < 1) || (node_count > CYGNUS_MAX_PORTS)) {
+		dev_err(dev, "child nodes is %d.  Must be between 1 and %d\n",
+			node_count, CYGNUS_MAX_PORTS);
+		return -EINVAL;
+	}
+
+	active_port_count = 0;
+
+	for_each_available_child_of_node(pdev->dev.of_node, child_node) {
+		err = parse_ssp_child_node(pdev, child_node, cygaud,
+					&cygnus_ssp_dai[active_port_count]);
+
+		/* negative is err, 0 is active and good, 1 is disabled */
+		if (err < 0)
+			return err;
+		else if (!err) {
+			dev_dbg(dev, "Activating DAI: %s\n",
+				cygnus_ssp_dai[active_port_count].name);
+			active_port_count++;
+		}
+	}
+
+	cygaud->dev = dev;
+	cygaud->active_ports = 0;
+
+	dev_dbg(dev, "Registering %d DAIs\n", active_port_count);
+	err = snd_soc_register_component(dev, &cygnus_ssp_component,
+				cygnus_ssp_dai, active_port_count);
+	if (err) {
+		dev_err(dev, "snd_soc_register_dai failed\n");
+		return err;
+	}
+
+	cygaud->irq_num = platform_get_irq(pdev, 0);
+	if (cygaud->irq_num <= 0) {
+		dev_err(dev, "platform_get_irq failed\n");
+		err = cygaud->irq_num;
+		goto err_irq;
+	}
+
+	err = audio_clk_init(pdev, cygaud);
+	if (err) {
+		dev_err(dev, "audio clock initialization failed\n");
+		goto err_irq;
+	}
+
+	err = cygnus_soc_platform_register(dev, cygaud);
+	if (err) {
+		dev_err(dev, "platform reg error %d\n", err);
+		goto err_irq;
+	}
+
+	return 0;
+
+err_irq:
+	snd_soc_unregister_component(dev);
+	return err;
+}
+
+static int cygnus_ssp_remove(struct platform_device *pdev)
+{
+	cygnus_soc_platform_unregister(&pdev->dev);
+	snd_soc_unregister_component(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id cygnus_ssp_of_match[] = {
+	{ .compatible = "brcm,cygnus-audio" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, cygnus_ssp_of_match);
+
+static struct platform_driver cygnus_ssp_driver = {
+	.probe		= cygnus_ssp_probe,
+	.remove		= cygnus_ssp_remove,
+	.driver		= {
+		.name	= "cygnus-ssp",
+		.of_match_table = cygnus_ssp_of_match,
+	},
+};
+
+module_platform_driver(cygnus_ssp_driver);
+
+MODULE_ALIAS("platform:cygnus-ssp");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Cygnus ASoC SSP Interface");
diff --git a/sound/soc/bcm/cygnus-ssp.h b/sound/soc/bcm/cygnus-ssp.h
new file mode 100644
index 000000000000..33dd34305928
--- /dev/null
+++ b/sound/soc/bcm/cygnus-ssp.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2014-2015 Broadcom Corporation
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __CYGNUS_SSP_H__
+#define __CYGNUS_SSP_H__
+
+#define CYGNUS_TDM_DAI_MAX_SLOTS 16
+
+#define CYGNUS_MAX_PLAYBACK_PORTS 4
+#define CYGNUS_MAX_CAPTURE_PORTS 3
+#define CYGNUS_MAX_I2S_PORTS 3
+#define CYGNUS_MAX_PORTS  CYGNUS_MAX_PLAYBACK_PORTS
+#define CYGNUS_AUIDO_MAX_NUM_CLKS 3
+
+#define CYGNUS_SSP_FRAMEBITS_DIV 1
+
+#define CYGNUS_SSPMODE_I2S 0
+#define CYGNUS_SSPMODE_TDM 1
+#define CYGNUS_SSPMODE_UNKNOWN -1
+
+#define CYGNUS_SSP_CLKSRC_PLL      0
+
+/* Max string length of our dt property names */
+#define PROP_LEN_MAX 40
+
+struct ringbuf_regs {
+	unsigned rdaddr;
+	unsigned wraddr;
+	unsigned baseaddr;
+	unsigned endaddr;
+	unsigned fmark;   /* freemark for play, fullmark for caputure */
+	unsigned period_bytes;
+	unsigned buf_size;
+};
+
+#define RINGBUF_REG_PLAYBACK(num) ((struct ringbuf_regs) { \
+	.rdaddr = SRC_RBUF_ ##num## _RDADDR_OFFSET, \
+	.wraddr = SRC_RBUF_ ##num## _WRADDR_OFFSET, \
+	.baseaddr = SRC_RBUF_ ##num## _BASEADDR_OFFSET, \
+	.endaddr = SRC_RBUF_ ##num## _ENDADDR_OFFSET, \
+	.fmark = SRC_RBUF_ ##num## _FREE_MARK_OFFSET, \
+	.period_bytes = 0, \
+	.buf_size = 0, \
+})
+
+#define RINGBUF_REG_CAPTURE(num) ((struct ringbuf_regs)  { \
+	.rdaddr = DST_RBUF_ ##num## _RDADDR_OFFSET, \
+	.wraddr = DST_RBUF_ ##num## _WRADDR_OFFSET, \
+	.baseaddr = DST_RBUF_ ##num## _BASEADDR_OFFSET, \
+	.endaddr = DST_RBUF_ ##num## _ENDADDR_OFFSET, \
+	.fmark = DST_RBUF_ ##num## _FULL_MARK_OFFSET, \
+	.period_bytes = 0, \
+	.buf_size = 0, \
+})
+
+enum cygnus_audio_port_type {
+	PORT_TDM,
+	PORT_SPDIF,
+};
+
+struct cygnus_ssp_regs {
+	u32 i2s_stream_cfg;
+	u32 i2s_cfg;
+	u32 i2s_cap_stream_cfg;
+	u32 i2s_cap_cfg;
+	u32 i2s_mclk_cfg;
+
+	u32 bf_destch_ctrl;
+	u32 bf_destch_cfg;
+	u32 bf_sourcech_ctrl;
+	u32 bf_sourcech_cfg;
+	u32 bf_sourcech_grp;
+};
+
+struct cygnus_track_clk {
+	bool cap_en;
+	bool play_en;
+	bool cap_clk_en;
+	bool play_clk_en;
+};
+
+struct cygnus_aio_port {
+	int portnum;
+	int mode;
+	bool is_slave;
+	int streams_on;   /* will be 0 if both capture and play are off */
+	int fsync_width;
+	int port_type;
+
+	u32 mclk;
+	u32 lrclk;
+	u32 bit_per_frame;
+	u32 pll_clk_num;
+
+	struct cygnus_audio *cygaud;
+	struct cygnus_ssp_regs regs;
+
+	struct ringbuf_regs play_rb_regs;
+	struct ringbuf_regs capture_rb_regs;
+
+	struct snd_pcm_substream *play_stream;
+	struct snd_pcm_substream *capture_stream;
+
+	struct cygnus_track_clk clk_trace;
+};
+
+
+struct cygnus_audio {
+	struct cygnus_aio_port  portinfo[CYGNUS_MAX_PORTS];
+
+	int irq_num;
+	void __iomem *audio;
+	struct device *dev;
+	void __iomem *i2s_in;
+
+	struct clk *audio_clk[CYGNUS_AUIDO_MAX_NUM_CLKS];
+	int active_ports;
+	unsigned long vco_rate;
+};
+
+extern int cygnus_ssp_get_mode(struct snd_soc_dai *cpu_dai);
+extern int cygnus_ssp_add_pll_tweak_controls(struct snd_soc_pcm_runtime *rtd);
+extern int cygnus_ssp_set_custom_fsync_width(struct snd_soc_dai *cpu_dai,
+						int len);
+extern int cygnus_soc_platform_register(struct device *dev,
+					struct cygnus_audio *cygaud);
+extern int cygnus_soc_platform_unregister(struct device *dev);
+extern int cygnus_ssp_set_custom_fsync_width(struct snd_soc_dai *cpu_dai,
+	int len);
+#endif
-- 
2.8.1



From broonie at kernel.org  Tue May 31 10:45:58 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 31 May 2016 18:45:58 +0100
Subject: Applied "ASoC: cygnus: Add DT bindings for Broadcom Cygnus audio" to
 the asoc tree
In-Reply-To: <1459277192-10942-2-git-send-email-simran.rai@broadcom.com>
Message-ID: <E1b7njq-00063a-OB@debutante>

The patch

   ASoC: cygnus: Add DT bindings for Broadcom Cygnus audio

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 36e5ecc2986f4712d8fdfc05ed1e5d39dda7096d Mon Sep 17 00:00:00 2001
From: Simran Rai <ssimran at broadcom.com>
Date: Tue, 17 May 2016 17:01:07 -0700
Subject: [PATCH] ASoC: cygnus: Add DT bindings for Broadcom Cygnus audio

Add bindings for audio driver in Broadcom Cygnus.

Signed-off-by: Lori Hikichi <lhikichi at broadcom.com>
Signed-off-by: Simran Rai <ssimran at broadcom.com>
Reviewed-by: Ray Jui <rjui at broadcom.com>
Reviewed-by: Scott Branden <sbranden at broadcom.com>
Acked-by: Rob Herring <robh at kernel.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 .../bindings/sound/brcm,cygnus-audio.txt           | 67 ++++++++++++++++++++++
 1 file changed, 67 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/brcm,cygnus-audio.txt

diff --git a/Documentation/devicetree/bindings/sound/brcm,cygnus-audio.txt b/Documentation/devicetree/bindings/sound/brcm,cygnus-audio.txt
new file mode 100644
index 000000000000..b139e66d2a11
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/brcm,cygnus-audio.txt
@@ -0,0 +1,67 @@
+BROADCOM Cygnus Audio I2S/TDM/SPDIF controller
+
+Required properties:
+	- compatible : "brcm,cygnus-audio"
+	- #address-cells: 32bit valued, 1 cell.
+	- #size-cells:  32bit valued, 0 cell.
+	- reg : Should contain audio registers location and length
+	- reg-names: names of the registers listed in "reg" property
+		Valid names are "aud" and "i2s_in". "aud" contains a
+		set of DMA, I2S_OUT and SPDIF registers. "i2s_in" contains
+		a set of I2S_IN registers.
+	- clocks: PLL and leaf clocks used by audio ports
+	- assigned-clocks: PLL and leaf clocks
+	- assigned-clock-parents: parent clocks of the assigned clocks
+		(usually the PLL)
+	- assigned-clock-rates: List of clock frequencies of the
+		assigned clocks
+	- clock-names: names of 3 leaf clocks used by audio ports
+		Valid names are "ch0_audio", "ch1_audio", "ch2_audio"
+	- interrupts: audio DMA interrupt number
+
+SSP Subnode properties:
+- reg: The index of ssp port interface to use
+	Valid value are 0, 1, 2, or 3 (for spdif)
+
+Example:
+	cygnus_audio: audio at 180ae000 {
+		compatible = "brcm,cygnus-audio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x180ae000 0xafd>, <0x180aec00 0x1f8>;
+		reg-names = "aud", "i2s_in";
+		clocks = <&audiopll BCM_CYGNUS_AUDIOPLL_CH0>,
+				<&audiopll BCM_CYGNUS_AUDIOPLL_CH1>,
+				<&audiopll BCM_CYGNUS_AUDIOPLL_CH2>;
+		assigned-clocks = <&audiopll BCM_CYGNUS_AUDIOPLL>,
+							<&audiopll BCM_CYGNUS_AUDIOPLL_CH0>,
+							<&audiopll BCM_CYGNUS_AUDIOPLL_CH1>,
+							<&audiopll BCM_CYGNUS_AUDIOPLL_CH2>;
+		assigned-clock-parents = <&audiopll BCM_CYGNUS_AUDIOPLL>;
+		assigned-clock-rates = <1769470191>,
+								<0>,
+								<0>,
+								<0>;
+		clock-names = "ch0_audio", "ch1_audio", "ch2_audio";
+		interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+
+		ssp0: ssp_port at 0 {
+			reg = <0>;
+			status = "okay";
+		};
+
+		ssp1: ssp_port at 1 {
+			reg = <1>;
+			status = "disabled";
+		};
+
+		ssp2: ssp_port at 2 {
+			reg = <2>;
+			status = "disabled";
+		};
+
+		spdif: spdif_port at 3 {
+			reg = <3>;
+			status = "disabled";
+		};
+	};
-- 
2.8.1



From broonie at kernel.org  Tue May 31 10:46:18 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 31 May 2016 18:46:18 +0100
Subject: Applied "regulator: axp20x: support AXP809 variant" to the regulator
 tree
In-Reply-To: <1454408864-24112-7-git-send-email-wens@csie.org>
Message-ID: <E1b7nkA-00068u-78@debutante>

The patch

   regulator: axp20x: support AXP809 variant

has been applied to the regulator tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From a51f9f4622a34eb19b5658c08b083345d763657b Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens at csie.org>
Date: Wed, 1 Jun 2016 00:23:19 +0800
Subject: [PATCH] regulator: axp20x: support AXP809 variant

The X-Powers AXP809 PMIC has a similar set of regulators as the AXP221,
though a few LDOs were removed, and a new switch output added. Like the
AXP221, AXP809 also has DC1SW and DC5LDO, which are internally chained
to DCDC1 and DCDC5, respectively.

Add support for this new variant. Also remove the "axp22x_" prefix from
DC1SW/DC5LDO supply handling code, as the AXP809 uses it as well.

Signed-off-by: Chen-Yu Tsai <wens at csie.org>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 drivers/regulator/axp20x-regulator.c | 119 ++++++++++++++++++++++++++---------
 1 file changed, 90 insertions(+), 29 deletions(-)

diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 514a5e8fdbab..728be64e817a 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -230,6 +230,61 @@ static const struct regulator_desc axp22x_regulators[] = {
 	AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
 };
 
+static const struct regulator_linear_range axp809_dcdc4_ranges[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2f, 20000),
+	REGULATOR_LINEAR_RANGE(1800000, 0x30, 0x38, 100000),
+};
+
+static const struct regulator_linear_range axp809_dldo1_ranges[] = {
+	REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
+	REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
+};
+
+static const struct regulator_desc axp809_regulators[] = {
+	AXP_DESC(AXP809, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
+		 AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)),
+	AXP_DESC(AXP809, DCDC2, "dcdc2", "vin2", 600, 1540, 20,
+		 AXP22X_DCDC2_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(2)),
+	AXP_DESC(AXP809, DCDC3, "dcdc3", "vin3", 600, 1860, 20,
+		 AXP22X_DCDC3_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(3)),
+	AXP_DESC_RANGES(AXP809, DCDC4, "dcdc4", "vin4", axp809_dcdc4_ranges,
+			57, AXP22X_DCDC4_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1,
+			BIT(4)),
+	AXP_DESC(AXP809, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
+		 AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
+	/* secondary switchable output of DCDC1 */
+	AXP_DESC_SW(AXP809, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
+		    BIT(7)),
+	/* LDO regulator internally chained to DCDC5 */
+	AXP_DESC(AXP809, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
+		 AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
+	AXP_DESC(AXP809, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(6)),
+	AXP_DESC(AXP809, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
+	AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
+		 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
+	AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp809_dldo1_ranges,
+			32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
+			BIT(3)),
+	AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
+		 AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(4)),
+	AXP_DESC(AXP809, ELDO1, "eldo1", "eldoin", 700, 3300, 100,
+		 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
+	AXP_DESC(AXP809, ELDO2, "eldo2", "eldoin", 700, 3300, 100,
+		 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
+	AXP_DESC(AXP809, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
+		 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
+	AXP_DESC_IO(AXP809, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_IO(AXP809, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
+		    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
+		    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
+	AXP_DESC_FIXED(AXP809, RTC_LDO, "rtc_ldo", "ips", 1800),
+	AXP_DESC_SW(AXP809, SW, "sw", "swin", AXP22X_PWR_OUT_CTRL2, BIT(6)),
+};
+
 static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
 {
 	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
@@ -245,6 +300,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
 		break;
 	case AXP221_ID:
 	case AXP223_ID:
+	case AXP809_ID:
 		min = 1800;
 		max = 4050;
 		def = 3000;
@@ -324,6 +380,7 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
 
 	case AXP221_ID:
 	case AXP223_ID:
+	case AXP809_ID:
 		if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
 			return -EINVAL;
 
@@ -352,8 +409,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 	};
 	int ret, i, nregulators;
 	u32 workmode;
-	const char *axp22x_dc1_name = axp22x_regulators[AXP22X_DCDC1].name;
-	const char *axp22x_dc5_name = axp22x_regulators[AXP22X_DCDC5].name;
+	const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name;
+	const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name;
 
 	switch (axp20x->variant) {
 	case AXP202_ID:
@@ -366,6 +423,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		regulators = axp22x_regulators;
 		nregulators = AXP22X_REG_ID_MAX;
 		break;
+	case AXP809_ID:
+		regulators = axp809_regulators;
+		nregulators = AXP809_REG_ID_MAX;
+		break;
 	default:
 		dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
 			axp20x->variant);
@@ -388,22 +449,22 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		 * part of this loop to see where we save the DT defined
 		 * name.
 		 */
-		if (regulators == axp22x_regulators) {
-			if (i == AXP22X_DC1SW) {
-				new_desc = devm_kzalloc(&pdev->dev,
-							sizeof(*desc),
-							GFP_KERNEL);
-				*new_desc = regulators[i];
-				new_desc->supply_name = axp22x_dc1_name;
-				desc = new_desc;
-			} else if (i == AXP22X_DC5LDO) {
-				new_desc = devm_kzalloc(&pdev->dev,
-							sizeof(*desc),
-							GFP_KERNEL);
-				*new_desc = regulators[i];
-				new_desc->supply_name = axp22x_dc5_name;
-				desc = new_desc;
-			}
+		if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) ||
+		    (regulators == axp809_regulators && i == AXP809_DC1SW)) {
+			new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
+						GFP_KERNEL);
+			*new_desc = regulators[i];
+			new_desc->supply_name = dcdc1_name;
+			desc = new_desc;
+		}
+
+		if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) ||
+		    (regulators == axp809_regulators && i == AXP809_DC5LDO)) {
+			new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
+						GFP_KERNEL);
+			*new_desc = regulators[i];
+			new_desc->supply_name = dcdc5_name;
+			desc = new_desc;
 		}
 
 		rdev = devm_regulator_register(&pdev->dev, desc, &config);
@@ -426,17 +487,17 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
 		/*
 		 * Save AXP22X DCDC1 / DCDC5 regulator names for later.
 		 */
-		if (regulators == axp22x_regulators) {
-			/* Can we use rdev->constraints->name instead? */
-			if (i == AXP22X_DCDC1)
-				of_property_read_string(rdev->dev.of_node,
-							"regulator-name",
-							&axp22x_dc1_name);
-			else if (i == AXP22X_DCDC5)
-				of_property_read_string(rdev->dev.of_node,
-							"regulator-name",
-							&axp22x_dc5_name);
-		}
+		if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) ||
+		    (regulators == axp809_regulators && i == AXP809_DCDC1))
+			of_property_read_string(rdev->dev.of_node,
+						"regulator-name",
+						&dcdc1_name);
+
+		if ((regulators == axp22x_regulators && i == AXP22X_DCDC5) ||
+		    (regulators == axp809_regulators && i == AXP809_DCDC5))
+			of_property_read_string(rdev->dev.of_node,
+						"regulator-name",
+						&dcdc5_name);
 	}
 
 	return 0;
-- 
2.8.1



From broonie at kernel.org  Tue May 31 10:46:29 2016
From: broonie at kernel.org (Mark Brown)
Date: Tue, 31 May 2016 18:46:29 +0100
Subject: Applied "spi/rockchip: add the rk3036/rk3228/rk3368 to match for
 driver" to the spi tree
In-Reply-To: <1463672824-15367-2-git-send-email-wxt@rock-chips.com>
Message-ID: <E1b7nkL-0006By-NN@debutante>

The patch

   spi/rockchip: add the rk3036/rk3228/rk3368 to match for driver

has been applied to the spi tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From aa29ea3df27dbba19ef59023d0f7330f2fdc58ae Mon Sep 17 00:00:00 2001
From: Caesar Wang <wxt at rock-chips.com>
Date: Fri, 20 May 2016 07:56:21 +0800
Subject: [PATCH] spi/rockchip: add the rk3036/rk3228/rk3368 to match for
 driver

In gerenal, the "rockchip,rockchip-spi" string will match the dts
that's great in spi driver. After all the most of rockchip SoCs ar
same spi controller.

Then, we should keep the old style to match the dts various.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 drivers/spi/spi-rockchip.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index cd89682065b9..bead5bfcbb0c 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -892,9 +892,12 @@ static const struct dev_pm_ops rockchip_spi_pm = {
 };
 
 static const struct of_device_id rockchip_spi_dt_match[] = {
+	{ .compatible = "rockchip,rk3036-spi", },
 	{ .compatible = "rockchip,rk3066-spi", },
 	{ .compatible = "rockchip,rk3188-spi", },
+	{ .compatible = "rockchip,rk3228-spi", },
 	{ .compatible = "rockchip,rk3288-spi", },
+	{ .compatible = "rockchip,rk3368-spi", },
 	{ .compatible = "rockchip,rk3399-spi", },
 	{ },
 };
-- 
2.8.1



From suzuki.poulose at arm.com  Tue May 31 10:47:29 2016
From: suzuki.poulose at arm.com (Suzuki K Poulose)
Date: Tue, 31 May 2016 18:47:29 +0100
Subject: [PATCH] coresight: Remove erroneous dma_free_coherent in tmc_probe
Message-ID: <1464716849-32066-1-git-send-email-suzuki.poulose@arm.com>

commit de5461970b3e9e194 ("coresight: tmc: allocating memory when needed")
removed the static allocation of buffer for the trace data in ETR mode in
tmc_probe. However it failed to remove the "devm_free_coherent" in tmc_probe
when the probe fails due to other reasons. This patch gets rid of the
incorrect dma_free_coherent() call. Also consolidates the error return
paths.

Fixes: commit de5461970b3e9e194 ("coresight: tmc: allocating memory when needed")
Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
---
 drivers/hwtracing/coresight/coresight-tmc.c | 32 ++++++++++++++---------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index c7d8ba6..ca38144 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -307,22 +307,31 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 
 	if (np) {
 		pdata = of_get_coresight_platform_data(dev, np);
-		if (IS_ERR(pdata))
-			return PTR_ERR(pdata);
+		if (IS_ERR(pdata)) {
+			ret = PTR_ERR(pdata);
+			goto out;
+		}
 		adev->dev.platform_data = pdata;
 	}
 
+	ret = -ENOMEM;
 	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
 	if (!drvdata)
-		return -ENOMEM;
+		goto out;
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		goto out;
 
 	drvdata->dev = &adev->dev;
 	dev_set_drvdata(dev, drvdata);
 
 	/* Validity for the resource is already checked by the AMBA core */
 	base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
+	if (IS_ERR(base)) {
+		ret = PTR_ERR(base);
+		goto out;
+	}
 
 	drvdata->base = base;
 
@@ -345,12 +354,6 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 
 	pm_runtime_put(&adev->dev);
 
-	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
-	if (!desc) {
-		ret = -ENOMEM;
-		goto err_devm_kzalloc;
-	}
-
 	desc->pdata = pdata;
 	desc->dev = dev;
 	desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
@@ -371,7 +374,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 	drvdata->csdev = coresight_register(desc);
 	if (IS_ERR(drvdata->csdev)) {
 		ret = PTR_ERR(drvdata->csdev);
-		goto err_devm_kzalloc;
+		goto out;
 	}
 
 	drvdata->miscdev.name = pdata->name;
@@ -385,10 +388,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 
 err_misc_register:
 	coresight_unregister(drvdata->csdev);
-err_devm_kzalloc:
-	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
-		dma_free_coherent(dev, drvdata->size,
-				drvdata->vaddr, drvdata->paddr);
+out:
 	return ret;
 }
 
-- 
1.9.1



From mathieu.poirier at linaro.org  Tue May 31 10:55:36 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue, 31 May 2016 11:55:36 -0600
Subject: [PATCH 3/5] coresight: Fix csdev connections initialisation
In-Reply-To: <1464695858-29284-4-git-send-email-suzuki.poulose@arm.com>
References: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
 <1464695858-29284-4-git-send-email-suzuki.poulose@arm.com>
Message-ID: <CANLsYkzQJVY3CDC7D9_Miw3Lu7iqV-6ABsVbTUCpivc-R0WB+Q@mail.gmail.com>

On 31 May 2016 at 05:57, Suzuki K Poulose <suzuki.poulose at arm.com> wrote:
> This is a cleanup patch.
>
> coresight_device->conns holds an array to point to the devices
> connected to the OUT ports of a component. Sinks, e.g ETR, do not
> have an OUT port (nr_outport = 0), as it streams the trace to
> memory via AXI.
>
> At coresight_register() we do :
>
>         conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL);
>         if (!conns) {
>                 ret = -ENOMEM;
>                 goto err_kzalloc_conns;
>         }
>
> For ETR, since the total size requested for kcalloc is zero, the return value is,
> ZERO_SIZE_PTR ( != NULL). Hence, csdev->conns = ZERO_SIZE_PTR which cannot be
> verified later to contain a valid pointer. The code which accesses the csdev->conns
> is bounded by the csdev->nr_outport check, hence we don't try to dereference the
> ZERO_SIZE_PTR. This patch cleans up the csdev->conns and csdev->refcnt, initialisation
> to make sure we initialise it properly(i.e, either NULL or valid conns array).
>
> Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> ---
>  drivers/hwtracing/coresight/coresight.c | 42 +++++++++++++++++++--------------
>  1 file changed, 24 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
> index 0fdaaf4..8410420 100644
> --- a/drivers/hwtracing/coresight/coresight.c
> +++ b/drivers/hwtracing/coresight/coresight.c
> @@ -890,7 +890,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
>         int nr_refcnts = 1;
>         atomic_t *refcnts = NULL;
>         struct coresight_device *csdev;
> -       struct coresight_connection *conns;
> +       struct coresight_connection *conns = NULL;
>
>         csdev = kzalloc(sizeof(*csdev), GFP_KERNEL);
>         if (!csdev) {
> @@ -908,29 +908,35 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
>                         nr_refcnts = desc->pdata->nr_outport;
>         }
>
> -       refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
> -       if (!refcnts) {
> -               ret = -ENOMEM;
> -               goto err_kzalloc_refcnts;
> -       }
> +       if (nr_refcnts) {

Did you manage to find a usecase where "nr_refcnts == 0" ?  Since
components have at least one port this condition will always be true.

> +               refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
> +               if (!refcnts) {
> +                       ret = -ENOMEM;
> +                       goto err_kzalloc_refcnts;
> +               }
>
> -       csdev->refcnt = refcnts;
> +               csdev->refcnt = refcnts;
> +       }
>
>         csdev->nr_inport = desc->pdata->nr_inport;
>         csdev->nr_outport = desc->pdata->nr_outport;
> -       conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL);
> -       if (!conns) {
> -               ret = -ENOMEM;
> -               goto err_kzalloc_conns;
> -       }
>
> -       for (i = 0; i < csdev->nr_outport; i++) {
> -               conns[i].outport = desc->pdata->outports[i];
> -               conns[i].child_name = desc->pdata->child_names[i];
> -               conns[i].child_port = desc->pdata->child_ports[i];
> -       }
> +       /* Initialise connections if there is at least one outport for this component */
> +       if (csdev->nr_outport) {
> +               conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL);
> +               if (!conns) {
> +                       ret = -ENOMEM;
> +                       goto err_kzalloc_conns;
> +               }
>
> -       csdev->conns = conns;
> +               for (i = 0; i < csdev->nr_outport; i++) {
> +                       conns[i].outport = desc->pdata->outports[i];
> +                       conns[i].child_name = desc->pdata->child_names[i];
> +                       conns[i].child_port = desc->pdata->child_ports[i];
> +               }
> +
> +               csdev->conns = conns;

The purpose of your patch is to correctly initialise csdev->conns to
NULL if there is no output port to speak of.  As such shouldn't the
above statement be out of the if (csdev->nr_outport) {} ?.

I'm also getting a couple of checkpatch.pl warnings on this patch.

> +       }
>
>         csdev->type = desc->type;
>         csdev->subtype = desc->subtype;
> --
> 1.9.1
>


From mathieu.poirier at linaro.org  Tue May 31 10:57:58 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue, 31 May 2016 11:57:58 -0600
Subject: [PATCH 4/5] coresight: Add better messages for coresight_timeout
In-Reply-To: <1464695858-29284-5-git-send-email-suzuki.poulose@arm.com>
References: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
 <1464695858-29284-5-git-send-email-suzuki.poulose@arm.com>
Message-ID: <CANLsYkyef0Zkvrt+7a9N2YD3z8vPSoR_m1pq5nBRRKn1Ns1LOw@mail.gmail.com>

On 31 May 2016 at 05:57, Suzuki K Poulose <suzuki.poulose at arm.com> wrote:
> When we encounter a timeout waiting for a status change via
> coresight_timeout, the caller always print the offset which
> was tried. This is pretty much useless as it doesn't specify
> the bit position we wait for. Also, one needs to lookup the
> TRM to figure out, what was wrong. This patch changes all
> such error messages to print something more meaningful.
>
> Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> ---
>  drivers/hwtracing/coresight/coresight-etb10.c | 6 ++----
>  drivers/hwtracing/coresight/coresight-etm4x.c | 6 ++----
>  drivers/hwtracing/coresight/coresight-tmc.c   | 6 ++----
>  3 files changed, 6 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
> index 4d20b0b..6bd4b93 100644
> --- a/drivers/hwtracing/coresight/coresight-etb10.c
> +++ b/drivers/hwtracing/coresight/coresight-etb10.c
> @@ -184,8 +184,7 @@ static void etb_disable_hw(struct etb_drvdata *drvdata)
>
>         if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) {
>                 dev_err(drvdata->dev,
> -                       "timeout observed when probing at offset %#x\n",
> -                       ETB_FFCR);
> +                       "timeout while waiting for completion of Manual Flush\n");
>         }
>
>         /* disable trace capture */
> @@ -193,8 +192,7 @@ static void etb_disable_hw(struct etb_drvdata *drvdata)
>
>         if (coresight_timeout(drvdata->base, ETB_FFSR, ETB_FFSR_BIT, 1)) {
>                 dev_err(drvdata->dev,
> -                       "timeout observed when probing at offset %#x\n",
> -                       ETB_FFCR);
> +                       "timeout while waiting for Formatter to Stop\n");
>         }
>
>         CS_LOCK(drvdata->base);
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
> index 88947f3..e494042 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.c
> @@ -111,8 +111,7 @@ static void etm4_enable_hw(void *info)
>         /* wait for TRCSTATR.IDLE to go up */
>         if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
>                 dev_err(drvdata->dev,
> -                       "timeout observed when probing at offset %#x\n",
> -                       TRCSTATR);
> +                       "timeout when waiting for Idle Trace Status\n");
>
>         writel_relaxed(config->pe_sel, drvdata->base + TRCPROCSELR);
>         writel_relaxed(config->cfg, drvdata->base + TRCCONFIGR);
> @@ -184,8 +183,7 @@ static void etm4_enable_hw(void *info)
>         /* wait for TRCSTATR.IDLE to go back down to '0' */
>         if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
>                 dev_err(drvdata->dev,
> -                       "timeout observed when probing at offset %#x\n",
> -                       TRCSTATR);
> +                       "timeout when waiting for Idle Trace Status\n");
>
>         CS_LOCK(drvdata->base);
>
> diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
> index 9e02ac9..c7d8ba6 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc.c
> @@ -38,8 +38,7 @@ void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
>         if (coresight_timeout(drvdata->base,
>                               TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
>                 dev_err(drvdata->dev,
> -                       "timeout observed when probing at offset %#x\n",
> -                       TMC_STS);
> +                       "timeout observed when waiting for TMC to be Ready\n");
>         }
>  }
>
> @@ -56,8 +55,7 @@ void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
>         if (coresight_timeout(drvdata->base,
>                               TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
>                 dev_err(drvdata->dev,
> -                       "timeout observed when probing at offset %#x\n",
> -                       TMC_FFCR);
> +                       "timeout observed while waiting for completion of Manual Flush\n");
>         }
>
>         tmc_wait_for_tmcready(drvdata);
> --
> 1.9.1
>

I'm fine with this change but in all 3 files the beginning of the new
error message is different.  Please select one and use it throughout.

Thanks,
Mathieu


From joe at perches.com  Tue May 31 10:58:57 2016
From: joe at perches.com (Joe Perches)
Date: Tue, 31 May 2016 10:58:57 -0700
Subject: [PATCH 4/5] coresight: Add better messages for coresight_timeout
In-Reply-To: <1464695858-29284-5-git-send-email-suzuki.poulose@arm.com>
References: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
 <1464695858-29284-5-git-send-email-suzuki.poulose@arm.com>
Message-ID: <1464717537.14627.39.camel@perches.com>

On Tue, 2016-05-31 at 12:57 +0100, Suzuki K Poulose wrote:
> When we encounter a timeout waiting for a status change via
> coresight_timeout, the caller always print the offset which
> was tried. This is pretty much useless as it doesn't specify
> the bit position we wait for. Also, one needs to lookup the
> TRM to figure out, what was wrong. This patch changes all
> such error messages to print something more meaningful.

trivia:

Perhaps consistently using
	dev_err(dev, "timeout while waiting for %s\n", "<foo>");
could make the object code a bit smaller.

> diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
[]
> @@ -184,8 +184,7 @@ static void etb_disable_hw(struct etb_drvdata *drvdata)
> ?
> ?	if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) {
> ?		dev_err(drvdata->dev,
> -			"timeout observed when probing at offset %#x\n",
> -			ETB_FFCR);
> +			"timeout while waiting for completion of Manual Flush\n");

ie:
		dev_err(drvdata->dev,
			"timeout while waiting for %s\n",
			"completion of Manual Flush");

but that depends on how many of these coresight
files are compiled and linked.

There is a while/when usage difference in some of
the output messages.


From mathieu.poirier at linaro.org  Tue May 31 11:01:23 2016
From: mathieu.poirier at linaro.org (Mathieu Poirier)
Date: Tue, 31 May 2016 12:01:23 -0600
Subject: [PATCH 5/5] coresight: Cleanup TMC status check
In-Reply-To: <1464695858-29284-6-git-send-email-suzuki.poulose@arm.com>
References: <1464695858-29284-1-git-send-email-suzuki.poulose@arm.com>
 <1464695858-29284-6-git-send-email-suzuki.poulose@arm.com>
Message-ID: <CANLsYkzcHxQ7k_iwwW0XDE5MutkpaCz63T1bkrcp7Kp9t0QSLA@mail.gmail.com>

On 31 May 2016 at 05:57, Suzuki K Poulose <suzuki.poulose at arm.com> wrote:
> Use the defined symbol rather than hardcoding the value to
> check whether the TMC buffer is full.
>
> Cc: Mathieu Poirier <mathieu.poirier at linaro.org>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
> ---
>  drivers/hwtracing/coresight/coresight-tmc-etr.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index 847d1b5..b0dce93 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -65,7 +65,7 @@ static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
>         val = readl_relaxed(drvdata->base + TMC_STS);
>
>         /* How much memory do we still have */
> -       if (val & BIT(0))
> +       if (val & TMC_STS_FULL)
>                 drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
>         else
>                 drvdata->buf = drvdata->vaddr;
> --
> 1.9.1
>

Applied - thanks.
Mathieu


From f.fainelli at gmail.com  Tue May 31 11:04:00 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Tue, 31 May 2016 11:04:00 -0700
Subject: [PATCH 0/7] ARM: multi_v7_defconfig: Add more Broadcom SoCs
In-Reply-To: <573F755D.3070203@broadcom.com>
References: <1463771252-12805-1-git-send-email-f.fainelli@gmail.com>
 <573F755D.3070203@broadcom.com>
Message-ID: <574DD210.5020300@gmail.com>

On 05/20/2016 01:36 PM, Scott Branden wrote:
> Hi Florian,
> 
> On 16-05-20 12:07 PM, Florian Fainelli wrote:
>> This patch series enables more fundamental drivers which are useful for
>> Broadcom BCM63xx and BCM7xxx SoCs.
>>
>> The last patch remove bcm_defconfig which is causing a whole lot of
>> confusiong
>> at best and is completely out of sync now.
>>
>> Florian Fainelli (7):
>>    ARM: multi_v7_defconfig: Enable BCM63xx
>>    ARM: multi_v7_defconfig: Enable BRCMSTB networking
>>    ARM: multi_v7_defconfig: Enable BRCMSTB AHCI
>>    ARM: multi_v7_defconfig: Enable BCM7038 Watchdog
>>    ARM: multi_v7_defconfig: Enable Broadcom STB PWM
>>    ARM: multi_v7_defconfig: Enable Broadcom Kona watchdog
>>    ARM: Remove bcm_defconfig
> 
> Patch series looks good.  Given we can't upstream a defconfig per SoC
> family, bcm_defconfig is quite useless and can be removed.
> 
> Acked-by: Scott Branden <scott.branden at broadcom.com>

Series applied, thanks!
-- 
Florian


From f.fainelli at gmail.com  Tue May 31 11:07:13 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Tue, 31 May 2016 11:07:13 -0700
Subject: [PATCH] soc: Move brcmstb to bcm/brcmstb
In-Reply-To: <573F75A0.5090206@broadcom.com>
References: <1463769495-10072-1-git-send-email-f.fainelli@gmail.com>
 <573F75A0.5090206@broadcom.com>
Message-ID: <574DD2D1.7010204@gmail.com>

On 05/20/2016 01:37 PM, Scott Branden wrote:
> Hi Florian,
> 
> Looks good.
> 
> On 16-05-20 11:38 AM, Florian Fainelli wrote:
>> Unify the different Broadcom SoCs directory and have everybody live
>> under drivers/soc/bcm/*.
>>
>> Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
> Acked-by: Scott Branden <scott.branden at broadcom.com>

Applied to drivers/next, thanks
-- 
Florian


From rmk+kernel at armlinux.org.uk  Tue May 31 11:15:03 2016
From: rmk+kernel at armlinux.org.uk (Russell King)
Date: Tue, 31 May 2016 19:15:03 +0100
Subject: [PATCH] ARM: fix PTRACE_SETVFPREGS on SMP systems
Message-ID: <E1b7oBz-0005wE-1t@rmk-PC.armlinux.org.uk>

PTRACE_SETVFPREGS fails to properly mark the VFP register set to be
reloaded, because it undoes one of the effects of vfp_flush_hwstate().

Specifically vfp_flush_hwstate() sets thread->vfpstate.hard.cpu to
an invalid CPU number, but vfp_set() overwrites this with the original
CPU number, thereby rendering the hardware state as apparently "valid",
even though the software state is more recent.

Fix this by reverting the previous change.

Cc: <stable at vger.kernel.org>
Fixes: 8130b9d7b9d8 ("ARM: 7308/1: vfp: flush thread hwstate before copying ptrace registers")
Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
---
Will, please ack this.

 arch/arm/kernel/ptrace.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index ef9119f7462e..4d9375814b53 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -733,8 +733,8 @@ static int vfp_set(struct task_struct *target,
 	if (ret)
 		return ret;
 
-	vfp_flush_hwstate(thread);
 	thread->vfpstate.hard = new_vfp;
+	vfp_flush_hwstate(thread);
 
 	return 0;
 }
-- 
2.1.0



From konrad.wilk at oracle.com  Tue May 31 11:15:33 2016
From: konrad.wilk at oracle.com (Konrad Rzeszutek Wilk)
Date: Tue, 31 May 2016 14:15:33 -0400
Subject: [RFC v2] dma-mapping: Use unsigned long for dma_attrs
In-Reply-To: <1464609246-6948-2-git-send-email-k.kozlowski@samsung.com>
References: <1464609246-6948-1-git-send-email-k.kozlowski@samsung.com>
 <1464609246-6948-2-git-send-email-k.kozlowski@samsung.com>
Message-ID: <20160531181533.GD11300@char.us.oracle.com>

On Mon, May 30, 2016 at 01:54:06PM +0200, Krzysztof Kozlowski wrote:
> The dma-mapping core and the implementations do not change the
> DMA attributes passed by pointer.  Thus the pointer can point to const
> data.  However the attributes do not have to be a bitfield. Instead
> unsigned long will do fine:
> 
> 1. This is just simpler.  Both in terms of reading the code and setting
>    attributes.  Instead of initializing local attributes on the stack and
>    passing pointer to it to dma_set_attr(), just set the bits.
> 
> 2. It brings safeness and checking for const correctness because the
>    attributes are passed by value.


.. why not go the next step a do an enum? Perhaps that should be mentioned
as part of the description?

Thanks.
> 
> Please have in mind that this is RFC, not finished yet.  Only ARM and
> ARM64 are fixed (and not everywhere).
> However other API users also have to be converted which is quite
> intrusive.  I would rather avoid it until the overall approach is
> accepted.
> 
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski at samsung.com>
> ---
>  Documentation/DMA-API.txt                 |   2 +-
>  Documentation/DMA-attributes.txt          |   2 +-
>  arch/arm/include/asm/dma-mapping.h        |  13 ++--
>  arch/arm/include/asm/xen/page-coherent.h  |  16 ++---
>  arch/arm/mm/dma-mapping.c                 |  82 +++++++++++------------
>  arch/arm/xen/mm.c                         |   4 +-
>  arch/arm64/mm/dma-mapping.c               |  57 ++++++++--------
>  drivers/gpu/drm/exynos/exynos_drm_fbdev.c |   2 +-
>  drivers/gpu/drm/exynos/exynos_drm_g2d.c   |   1 -
>  drivers/gpu/drm/exynos/exynos_drm_gem.c   |  20 +++---
>  drivers/gpu/drm/exynos/exynos_drm_gem.h   |   2 +-
>  drivers/iommu/dma-iommu.c                 |   6 +-
>  drivers/xen/swiotlb-xen.c                 |  14 ++--
>  include/linux/dma-attrs.h                 |  71 --------------------
>  include/linux/dma-iommu.h                 |   6 +-
>  include/linux/dma-mapping.h               | 105 +++++++++++++++++-------------
>  include/linux/swiotlb.h                   |  10 +--
>  include/xen/swiotlb-xen.h                 |  12 ++--
>  lib/dma-noop.c                            |   9 +--
>  lib/swiotlb.c                             |  13 ++--
>  20 files changed, 195 insertions(+), 252 deletions(-)
>  delete mode 100644 include/linux/dma-attrs.h
> 
> diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
> index 45ef3f279c3b..0b55cb7c5aaa 100644
> --- a/Documentation/DMA-API.txt
> +++ b/Documentation/DMA-API.txt
> @@ -391,7 +391,7 @@ without the _attrs suffixes, except that they pass an optional
>  struct dma_attrs*.
>  
>  struct dma_attrs encapsulates a set of "DMA attributes". For the
> -definition of struct dma_attrs see linux/dma-attrs.h.
> +definition of struct dma_attrs see linux/dma-mapping.h.
>  
>  The interpretation of DMA attributes is architecture-specific, and
>  each attribute should be documented in Documentation/DMA-attributes.txt.
> diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
> index e8cf9cf873b3..2d455a5cf671 100644
> --- a/Documentation/DMA-attributes.txt
> +++ b/Documentation/DMA-attributes.txt
> @@ -2,7 +2,7 @@
>  			==============
>  
>  This document describes the semantics of the DMA attributes that are
> -defined in linux/dma-attrs.h.
> +defined in linux/dma-mapping.h.
>  
>  DMA_ATTR_WRITE_BARRIER
>  ----------------------
> diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
> index a83570f10124..d009f7911ffc 100644
> --- a/arch/arm/include/asm/dma-mapping.h
> +++ b/arch/arm/include/asm/dma-mapping.h
> @@ -5,7 +5,6 @@
>  
>  #include <linux/mm_types.h>
>  #include <linux/scatterlist.h>
> -#include <linux/dma-attrs.h>
>  #include <linux/dma-debug.h>
>  
>  #include <asm/memory.h>
> @@ -174,7 +173,7 @@ static inline void dma_mark_clean(void *addr, size_t size) { }
>   * to be the device-viewed address.
>   */
>  extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
> -			   gfp_t gfp, struct dma_attrs *attrs);
> +			   gfp_t gfp, unsigned long attrs);
>  
>  /**
>   * arm_dma_free - free memory allocated by arm_dma_alloc
> @@ -191,7 +190,7 @@ extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
>   * during and after this call executing are illegal.
>   */
>  extern void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
> -			 dma_addr_t handle, struct dma_attrs *attrs);
> +			 dma_addr_t handle, unsigned long attrs);
>  
>  /**
>   * arm_dma_mmap - map a coherent DMA allocation into user space
> @@ -208,7 +207,7 @@ extern void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
>   */
>  extern int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
>  			void *cpu_addr, dma_addr_t dma_addr, size_t size,
> -			struct dma_attrs *attrs);
> +			unsigned long attrs);
>  
>  /*
>   * This can be called during early boot to increase the size of the atomic
> @@ -262,16 +261,16 @@ extern void dmabounce_unregister_dev(struct device *);
>   * The scatter list versions of the above methods.
>   */
>  extern int arm_dma_map_sg(struct device *, struct scatterlist *, int,
> -		enum dma_data_direction, struct dma_attrs *attrs);
> +		enum dma_data_direction, unsigned long attrs);
>  extern void arm_dma_unmap_sg(struct device *, struct scatterlist *, int,
> -		enum dma_data_direction, struct dma_attrs *attrs);
> +		enum dma_data_direction, unsigned long attrs);
>  extern void arm_dma_sync_sg_for_cpu(struct device *, struct scatterlist *, int,
>  		enum dma_data_direction);
>  extern void arm_dma_sync_sg_for_device(struct device *, struct scatterlist *, int,
>  		enum dma_data_direction);
>  extern int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
>  		void *cpu_addr, dma_addr_t dma_addr, size_t size,
> -		struct dma_attrs *attrs);
> +		unsigned long attrs);
>  
>  #endif /* __KERNEL__ */
>  #endif
> diff --git a/arch/arm/include/asm/xen/page-coherent.h b/arch/arm/include/asm/xen/page-coherent.h
> index 9408a994cc91..95ce6ac3a971 100644
> --- a/arch/arm/include/asm/xen/page-coherent.h
> +++ b/arch/arm/include/asm/xen/page-coherent.h
> @@ -2,15 +2,14 @@
>  #define _ASM_ARM_XEN_PAGE_COHERENT_H
>  
>  #include <asm/page.h>
> -#include <linux/dma-attrs.h>
>  #include <linux/dma-mapping.h>
>  
>  void __xen_dma_map_page(struct device *hwdev, struct page *page,
>  	     dma_addr_t dev_addr, unsigned long offset, size_t size,
> -	     enum dma_data_direction dir, struct dma_attrs *attrs);
> +	     enum dma_data_direction dir, unsigned long attrs);
>  void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
>  		size_t size, enum dma_data_direction dir,
> -		struct dma_attrs *attrs);
> +		unsigned long attrs);
>  void __xen_dma_sync_single_for_cpu(struct device *hwdev,
>  		dma_addr_t handle, size_t size, enum dma_data_direction dir);
>  
> @@ -18,22 +17,20 @@ void __xen_dma_sync_single_for_device(struct device *hwdev,
>  		dma_addr_t handle, size_t size, enum dma_data_direction dir);
>  
>  static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
> -		dma_addr_t *dma_handle, gfp_t flags,
> -		struct dma_attrs *attrs)
> +		dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
>  {
>  	return __generic_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
>  }
>  
>  static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
> -		void *cpu_addr, dma_addr_t dma_handle,
> -		struct dma_attrs *attrs)
> +		void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
>  {
>  	__generic_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
>  }
>  
>  static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
>  	     dma_addr_t dev_addr, unsigned long offset, size_t size,
> -	     enum dma_data_direction dir, struct dma_attrs *attrs)
> +	     enum dma_data_direction dir, unsigned long attrs)
>  {
>  	unsigned long page_pfn = page_to_xen_pfn(page);
>  	unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
> @@ -58,8 +55,7 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
>  }
>  
>  static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
> -		size_t size, enum dma_data_direction dir,
> -		struct dma_attrs *attrs)
> +		size_t size, enum dma_data_direction dir, unsigned long attrs)
>  {
>  	unsigned long pfn = PFN_DOWN(handle);
>  	/*
> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> index ff7ed5697d3e..fe31fbfd926d 100644
> --- a/arch/arm/mm/dma-mapping.c
> +++ b/arch/arm/mm/dma-mapping.c
> @@ -124,7 +124,7 @@ static void __dma_page_dev_to_cpu(struct page *, unsigned long,
>   */
>  static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
>  	     unsigned long offset, size_t size, enum dma_data_direction dir,
> -	     struct dma_attrs *attrs)
> +	     unsigned long attrs)
>  {
>  	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
>  		__dma_page_cpu_to_dev(page, offset, size, dir);
> @@ -133,7 +133,7 @@ static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
>  
>  static dma_addr_t arm_coherent_dma_map_page(struct device *dev, struct page *page,
>  	     unsigned long offset, size_t size, enum dma_data_direction dir,
> -	     struct dma_attrs *attrs)
> +	     unsigned long attrs)
>  {
>  	return pfn_to_dma(dev, page_to_pfn(page)) + offset;
>  }
> @@ -153,8 +153,7 @@ static dma_addr_t arm_coherent_dma_map_page(struct device *dev, struct page *pag
>   * whatever the device wrote there.
>   */
>  static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
> -		size_t size, enum dma_data_direction dir,
> -		struct dma_attrs *attrs)
> +		size_t size, enum dma_data_direction dir, unsigned long attrs)
>  {
>  	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
>  		__dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
> @@ -194,12 +193,12 @@ struct dma_map_ops arm_dma_ops = {
>  EXPORT_SYMBOL(arm_dma_ops);
>  
>  static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
> -	dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs);
> +	dma_addr_t *handle, gfp_t gfp, unsigned long attrs);
>  static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
> -				  dma_addr_t handle, struct dma_attrs *attrs);
> +				  dma_addr_t handle, unsigned long attrs);
>  static int arm_coherent_dma_mmap(struct device *dev, struct vm_area_struct *vma,
>  		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
> -		 struct dma_attrs *attrs);
> +		 unsigned long attrs);
>  
>  struct dma_map_ops arm_coherent_dma_ops = {
>  	.alloc			= arm_coherent_dma_alloc,
> @@ -621,7 +620,7 @@ static void __free_from_contiguous(struct device *dev, struct page *page,
>  	dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
>  }
>  
> -static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
> +static inline pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot)
>  {
>  	prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
>  			    pgprot_writecombine(prot) :
> @@ -732,7 +731,7 @@ static struct arm_dma_allocator remap_allocator = {
>  
>  static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
>  			 gfp_t gfp, pgprot_t prot, bool is_coherent,
> -			 struct dma_attrs *attrs, const void *caller)
> +			 unsigned long attrs, const void *caller)
>  {
>  	u64 mask = get_coherent_dma_mask(dev);
>  	struct page *page = NULL;
> @@ -814,7 +813,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
>   * virtual and bus address for that space.
>   */
>  void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
> -		    gfp_t gfp, struct dma_attrs *attrs)
> +		    gfp_t gfp, unsigned long attrs)
>  {
>  	pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
>  
> @@ -823,7 +822,7 @@ void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
>  }
>  
>  static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
> -	dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
> +	dma_addr_t *handle, gfp_t gfp, unsigned long attrs)
>  {
>  	return __dma_alloc(dev, size, handle, gfp, PAGE_KERNEL, true,
>  			   attrs, __builtin_return_address(0));
> @@ -831,7 +830,7 @@ static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
>  
>  static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
>  		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
> -		 struct dma_attrs *attrs)
> +		 unsigned long attrs)
>  {
>  	int ret = -ENXIO;
>  #ifdef CONFIG_MMU
> @@ -859,14 +858,14 @@ static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
>   */
>  static int arm_coherent_dma_mmap(struct device *dev, struct vm_area_struct *vma,
>  		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
> -		 struct dma_attrs *attrs)
> +		 unsigned long attrs)
>  {
>  	return __arm_dma_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
>  }
>  
>  int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
>  		 void *cpu_addr, dma_addr_t dma_addr, size_t size,
> -		 struct dma_attrs *attrs)
> +		 unsigned long attrs)
>  {
>  #ifdef CONFIG_MMU
>  	vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
> @@ -878,7 +877,7 @@ int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
>   * Free a buffer as defined by the above mapping.
>   */
>  static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
> -			   dma_addr_t handle, struct dma_attrs *attrs,
> +			   dma_addr_t handle, unsigned long attrs,
>  			   bool is_coherent)
>  {
>  	struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
> @@ -900,20 +899,20 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
>  }
>  
>  void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
> -		  dma_addr_t handle, struct dma_attrs *attrs)
> +		  dma_addr_t handle, unsigned long attrs)
>  {
>  	__arm_dma_free(dev, size, cpu_addr, handle, attrs, false);
>  }
>  
>  static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
> -				  dma_addr_t handle, struct dma_attrs *attrs)
> +				  dma_addr_t handle, unsigned long attrs)
>  {
>  	__arm_dma_free(dev, size, cpu_addr, handle, attrs, true);
>  }
>  
>  int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
>  		 void *cpu_addr, dma_addr_t handle, size_t size,
> -		 struct dma_attrs *attrs)
> +		 unsigned long attrs)
>  {
>  	struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
>  	int ret;
> @@ -1046,7 +1045,7 @@ static void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
>   * here.
>   */
>  int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
> -		enum dma_data_direction dir, struct dma_attrs *attrs)
> +		enum dma_data_direction dir, unsigned long attrs)
>  {
>  	struct dma_map_ops *ops = get_dma_ops(dev);
>  	struct scatterlist *s;
> @@ -1080,7 +1079,7 @@ int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
>   * rules concerning calls here are the same as for dma_unmap_single().
>   */
>  void arm_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
> -		enum dma_data_direction dir, struct dma_attrs *attrs)
> +		enum dma_data_direction dir, unsigned long attrs)
>  {
>  	struct dma_map_ops *ops = get_dma_ops(dev);
>  	struct scatterlist *s;
> @@ -1253,7 +1252,7 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping,
>  static const int iommu_order_array[] = { 9, 8, 4, 0 };
>  
>  static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
> -					  gfp_t gfp, struct dma_attrs *attrs)
> +					  gfp_t gfp, unsigned long attrs)
>  {
>  	struct page **pages;
>  	int count = size >> PAGE_SHIFT;
> @@ -1342,7 +1341,7 @@ error:
>  }
>  
>  static int __iommu_free_buffer(struct device *dev, struct page **pages,
> -			       size_t size, struct dma_attrs *attrs)
> +			       size_t size, unsigned long attrs)
>  {
>  	int count = size >> PAGE_SHIFT;
>  	int i;
> @@ -1439,7 +1438,7 @@ static struct page **__atomic_get_pages(void *addr)
>  	return (struct page **)page;
>  }
>  
> -static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
> +static struct page **__iommu_get_pages(void *cpu_addr, unsigned long attrs)
>  {
>  	struct vm_struct *area;
>  
> @@ -1484,7 +1483,7 @@ static void __iommu_free_atomic(struct device *dev, void *cpu_addr,
>  }
>  
>  static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
> -	    dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
> +	    dma_addr_t *handle, gfp_t gfp, unsigned long attrs)
>  {
>  	pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
>  	struct page **pages;
> @@ -1532,7 +1531,7 @@ err_buffer:
>  
>  static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
>  		    void *cpu_addr, dma_addr_t dma_addr, size_t size,
> -		    struct dma_attrs *attrs)
> +		    unsigned long attrs)
>  {
>  	unsigned long uaddr = vma->vm_start;
>  	unsigned long usize = vma->vm_end - vma->vm_start;
> @@ -1568,7 +1567,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
>   * Must not be called with IRQs disabled.
>   */
>  void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
> -			  dma_addr_t handle, struct dma_attrs *attrs)
> +			  dma_addr_t handle, unsigned long attrs)
>  {
>  	struct page **pages;
>  	size = PAGE_ALIGN(size);
> @@ -1595,7 +1594,7 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
>  
>  static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
>  				 void *cpu_addr, dma_addr_t dma_addr,
> -				 size_t size, struct dma_attrs *attrs)
> +				 size_t size, unsigned long attrs)
>  {
>  	unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
>  	struct page **pages = __iommu_get_pages(cpu_addr, attrs);
> @@ -1633,7 +1632,7 @@ static int __dma_direction_to_prot(enum dma_data_direction dir)
>   */
>  static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
>  			  size_t size, dma_addr_t *handle,
> -			  enum dma_data_direction dir, struct dma_attrs *attrs,
> +			  enum dma_data_direction dir, unsigned long attrs,
>  			  bool is_coherent)
>  {
>  	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
> @@ -1676,7 +1675,7 @@ fail:
>  }
>  
>  static int __iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
> -		     enum dma_data_direction dir, struct dma_attrs *attrs,
> +		     enum dma_data_direction dir, unsigned long attrs,
>  		     bool is_coherent)
>  {
>  	struct scatterlist *s = sg, *dma = sg, *start = sg;
> @@ -1734,7 +1733,7 @@ bad_mapping:
>   * obtained via sg_dma_{address,length}.
>   */
>  int arm_coherent_iommu_map_sg(struct device *dev, struct scatterlist *sg,
> -		int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
> +		int nents, enum dma_data_direction dir, unsigned long attrs)
>  {
>  	return __iommu_map_sg(dev, sg, nents, dir, attrs, true);
>  }
> @@ -1752,14 +1751,14 @@ int arm_coherent_iommu_map_sg(struct device *dev, struct scatterlist *sg,
>   * sg_dma_{address,length}.
>   */
>  int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg,
> -		int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
> +		int nents, enum dma_data_direction dir, unsigned long attrs)
>  {
>  	return __iommu_map_sg(dev, sg, nents, dir, attrs, false);
>  }
>  
>  static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
> -		int nents, enum dma_data_direction dir, struct dma_attrs *attrs,
> -		bool is_coherent)
> +		int nents, enum dma_data_direction dir,
> +		unsigned long attrs, bool is_coherent)
>  {
>  	struct scatterlist *s;
>  	int i;
> @@ -1786,7 +1785,8 @@ static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
>   * rules concerning calls here are the same as for dma_unmap_single().
>   */
>  void arm_coherent_iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
> -		int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
> +		int nents, enum dma_data_direction dir,
> +		unsigned long attrs)
>  {
>  	__iommu_unmap_sg(dev, sg, nents, dir, attrs, true);
>  }
> @@ -1802,7 +1802,8 @@ void arm_coherent_iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
>   * rules concerning calls here are the same as for dma_unmap_single().
>   */
>  void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
> -			enum dma_data_direction dir, struct dma_attrs *attrs)
> +			enum dma_data_direction dir,
> +			unsigned long attrs)
>  {
>  	__iommu_unmap_sg(dev, sg, nents, dir, attrs, false);
>  }
> @@ -1855,7 +1856,7 @@ void arm_iommu_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
>   */
>  static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *page,
>  	     unsigned long offset, size_t size, enum dma_data_direction dir,
> -	     struct dma_attrs *attrs)
> +	     unsigned long attrs)
>  {
>  	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
>  	dma_addr_t dma_addr;
> @@ -1889,7 +1890,7 @@ fail:
>   */
>  static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
>  	     unsigned long offset, size_t size, enum dma_data_direction dir,
> -	     struct dma_attrs *attrs)
> +	     unsigned long attrs)
>  {
>  	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
>  		__dma_page_cpu_to_dev(page, offset, size, dir);
> @@ -1907,8 +1908,7 @@ static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
>   * Coherent IOMMU aware version of arm_dma_unmap_page()
>   */
>  static void arm_coherent_iommu_unmap_page(struct device *dev, dma_addr_t handle,
> -		size_t size, enum dma_data_direction dir,
> -		struct dma_attrs *attrs)
> +		size_t size, enum dma_data_direction dir, unsigned long attrs)
>  {
>  	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
>  	dma_addr_t iova = handle & PAGE_MASK;
> @@ -1932,8 +1932,7 @@ static void arm_coherent_iommu_unmap_page(struct device *dev, dma_addr_t handle,
>   * IOMMU aware version of arm_dma_unmap_page()
>   */
>  static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
> -		size_t size, enum dma_data_direction dir,
> -		struct dma_attrs *attrs)
> +		size_t size, enum dma_data_direction dir, unsigned long attrs)
>  {
>  	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
>  	dma_addr_t iova = handle & PAGE_MASK;
> @@ -1944,6 +1943,7 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
>  	if (!iova)
>  		return;
>  
> +	// FIXME: replace get with simple check
>  	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
>  		__dma_page_dev_to_cpu(page, offset, size, dir);
>  
> diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
> index c5f9a9e3d1f3..fc67ed236a10 100644
> --- a/arch/arm/xen/mm.c
> +++ b/arch/arm/xen/mm.c
> @@ -98,7 +98,7 @@ static void __xen_dma_page_cpu_to_dev(struct device *hwdev, dma_addr_t handle,
>  
>  void __xen_dma_map_page(struct device *hwdev, struct page *page,
>  	     dma_addr_t dev_addr, unsigned long offset, size_t size,
> -	     enum dma_data_direction dir, struct dma_attrs *attrs)
> +	     enum dma_data_direction dir, unsigned long attrs)
>  {
>  	if (is_device_dma_coherent(hwdev))
>  		return;
> @@ -110,7 +110,7 @@ void __xen_dma_map_page(struct device *hwdev, struct page *page,
>  
>  void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
>  		size_t size, enum dma_data_direction dir,
> -		struct dma_attrs *attrs)
> +		unsigned long attrs)
>  
>  {
>  	if (is_device_dma_coherent(hwdev))
> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> index c566ec83719f..a7686028dfeb 100644
> --- a/arch/arm64/mm/dma-mapping.c
> +++ b/arch/arm64/mm/dma-mapping.c
> @@ -29,7 +29,7 @@
>  
>  #include <asm/cacheflush.h>
>  
> -static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
> +static pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot,
>  				 bool coherent)
>  {
>  	if (!coherent || dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs))
> @@ -88,7 +88,7 @@ static int __free_from_pool(void *start, size_t size)
>  
>  static void *__dma_alloc_coherent(struct device *dev, size_t size,
>  				  dma_addr_t *dma_handle, gfp_t flags,
> -				  struct dma_attrs *attrs)
> +				  unsigned long attrs)
>  {
>  	if (dev == NULL) {
>  		WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
> @@ -118,7 +118,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
>  
>  static void __dma_free_coherent(struct device *dev, size_t size,
>  				void *vaddr, dma_addr_t dma_handle,
> -				struct dma_attrs *attrs)
> +				unsigned long attrs)
>  {
>  	bool freed;
>  	phys_addr_t paddr = dma_to_phys(dev, dma_handle);
> @@ -137,7 +137,7 @@ static void __dma_free_coherent(struct device *dev, size_t size,
>  
>  static void *__dma_alloc(struct device *dev, size_t size,
>  			 dma_addr_t *dma_handle, gfp_t flags,
> -			 struct dma_attrs *attrs)
> +			 unsigned long attrs)
>  {
>  	struct page *page;
>  	void *ptr, *coherent_ptr;
> @@ -185,7 +185,7 @@ no_mem:
>  
>  static void __dma_free(struct device *dev, size_t size,
>  		       void *vaddr, dma_addr_t dma_handle,
> -		       struct dma_attrs *attrs)
> +		       unsigned long attrs)
>  {
>  	void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
>  
> @@ -202,7 +202,7 @@ static void __dma_free(struct device *dev, size_t size,
>  static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
>  				     unsigned long offset, size_t size,
>  				     enum dma_data_direction dir,
> -				     struct dma_attrs *attrs)
> +				     unsigned long attrs)
>  {
>  	dma_addr_t dev_addr;
>  
> @@ -216,7 +216,7 @@ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
>  
>  static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
>  				 size_t size, enum dma_data_direction dir,
> -				 struct dma_attrs *attrs)
> +				 unsigned long attrs)
>  {
>  	if (!is_device_dma_coherent(dev))
>  		__dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
> @@ -225,7 +225,7 @@ static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
>  
>  static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
>  				  int nelems, enum dma_data_direction dir,
> -				  struct dma_attrs *attrs)
> +				  unsigned long attrs)
>  {
>  	struct scatterlist *sg;
>  	int i, ret;
> @@ -242,7 +242,7 @@ static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
>  static void __swiotlb_unmap_sg_attrs(struct device *dev,
>  				     struct scatterlist *sgl, int nelems,
>  				     enum dma_data_direction dir,
> -				     struct dma_attrs *attrs)
> +				     unsigned long attrs)
>  {
>  	struct scatterlist *sg;
>  	int i;
> @@ -303,7 +303,7 @@ static void __swiotlb_sync_sg_for_device(struct device *dev,
>  static int __swiotlb_mmap(struct device *dev,
>  			  struct vm_area_struct *vma,
>  			  void *cpu_addr, dma_addr_t dma_addr, size_t size,
> -			  struct dma_attrs *attrs)
> +			  unsigned long attrs)
>  {
>  	int ret = -ENXIO;
>  	unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >>
> @@ -330,7 +330,7 @@ static int __swiotlb_mmap(struct device *dev,
>  
>  static int __swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt,
>  				 void *cpu_addr, dma_addr_t handle, size_t size,
> -				 struct dma_attrs *attrs)
> +				 unsigned long attrs)
>  {
>  	int ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
>  
> @@ -425,21 +425,21 @@ out:
>  
>  static void *__dummy_alloc(struct device *dev, size_t size,
>  			   dma_addr_t *dma_handle, gfp_t flags,
> -			   struct dma_attrs *attrs)
> +			   unsigned long attrs)
>  {
>  	return NULL;
>  }
>  
>  static void __dummy_free(struct device *dev, size_t size,
>  			 void *vaddr, dma_addr_t dma_handle,
> -			 struct dma_attrs *attrs)
> +			 unsigned long attrs)
>  {
>  }
>  
>  static int __dummy_mmap(struct device *dev,
>  			struct vm_area_struct *vma,
>  			void *cpu_addr, dma_addr_t dma_addr, size_t size,
> -			struct dma_attrs *attrs)
> +			unsigned long attrs)
>  {
>  	return -ENXIO;
>  }
> @@ -447,20 +447,20 @@ static int __dummy_mmap(struct device *dev,
>  static dma_addr_t __dummy_map_page(struct device *dev, struct page *page,
>  				   unsigned long offset, size_t size,
>  				   enum dma_data_direction dir,
> -				   struct dma_attrs *attrs)
> +				   unsigned long attrs)
>  {
>  	return DMA_ERROR_CODE;
>  }
>  
>  static void __dummy_unmap_page(struct device *dev, dma_addr_t dev_addr,
>  			       size_t size, enum dma_data_direction dir,
> -			       struct dma_attrs *attrs)
> +			       unsigned long attrs)
>  {
>  }
>  
>  static int __dummy_map_sg(struct device *dev, struct scatterlist *sgl,
>  			  int nelems, enum dma_data_direction dir,
> -			  struct dma_attrs *attrs)
> +			  unsigned long attrs)
>  {
>  	return 0;
>  }
> @@ -468,7 +468,7 @@ static int __dummy_map_sg(struct device *dev, struct scatterlist *sgl,
>  static void __dummy_unmap_sg(struct device *dev,
>  			     struct scatterlist *sgl, int nelems,
>  			     enum dma_data_direction dir,
> -			     struct dma_attrs *attrs)
> +			     unsigned long attrs)
>  {
>  }
>  
> @@ -540,7 +540,7 @@ static void flush_page(struct device *dev, const void *virt, phys_addr_t phys)
>  
>  static void *__iommu_alloc_attrs(struct device *dev, size_t size,
>  				 dma_addr_t *handle, gfp_t gfp,
> -				 struct dma_attrs *attrs)
> +				 unsigned long attrs)
>  {
>  	bool coherent = is_device_dma_coherent(dev);
>  	int ioprot = dma_direction_to_prot(DMA_BIDIRECTIONAL, coherent);
> @@ -600,7 +600,8 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
>  }
>  
>  static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
> -			       dma_addr_t handle, struct dma_attrs *attrs)
> +			       dma_addr_t handle,
> +			       unsigned long attrs)
>  {
>  	size_t iosize = size;
>  
> @@ -616,7 +617,7 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
>  	 * Hence how dodgy the below logic looks...
>  	 */
>  	if (__in_atomic_pool(cpu_addr, size)) {
> -		iommu_dma_unmap_page(dev, handle, iosize, 0, NULL);
> +		iommu_dma_unmap_page(dev, handle, iosize, 0, 0);
>  		__free_from_pool(cpu_addr, size);
>  	} else if (is_vmalloc_addr(cpu_addr)){
>  		struct vm_struct *area = find_vm_area(cpu_addr);
> @@ -626,14 +627,14 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
>  		iommu_dma_free(dev, area->pages, iosize, &handle);
>  		dma_common_free_remap(cpu_addr, size, VM_USERMAP);
>  	} else {
> -		iommu_dma_unmap_page(dev, handle, iosize, 0, NULL);
> +		iommu_dma_unmap_page(dev, handle, iosize, 0, 0);
>  		__free_pages(virt_to_page(cpu_addr), get_order(size));
>  	}
>  }
>  
>  static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
>  			      void *cpu_addr, dma_addr_t dma_addr, size_t size,
> -			      struct dma_attrs *attrs)
> +			      unsigned long attrs)
>  {
>  	struct vm_struct *area;
>  	int ret;
> @@ -653,7 +654,7 @@ static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
>  
>  static int __iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
>  			       void *cpu_addr, dma_addr_t dma_addr,
> -			       size_t size, struct dma_attrs *attrs)
> +			       size_t size, unsigned long attrs)
>  {
>  	unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
>  	struct vm_struct *area = find_vm_area(cpu_addr);
> @@ -694,7 +695,7 @@ static void __iommu_sync_single_for_device(struct device *dev,
>  static dma_addr_t __iommu_map_page(struct device *dev, struct page *page,
>  				   unsigned long offset, size_t size,
>  				   enum dma_data_direction dir,
> -				   struct dma_attrs *attrs)
> +				   unsigned long attrs)
>  {
>  	bool coherent = is_device_dma_coherent(dev);
>  	int prot = dma_direction_to_prot(dir, coherent);
> @@ -709,7 +710,7 @@ static dma_addr_t __iommu_map_page(struct device *dev, struct page *page,
>  
>  static void __iommu_unmap_page(struct device *dev, dma_addr_t dev_addr,
>  			       size_t size, enum dma_data_direction dir,
> -			       struct dma_attrs *attrs)
> +			       unsigned long attrs)
>  {
>  	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
>  		__iommu_sync_single_for_cpu(dev, dev_addr, size, dir);
> @@ -747,7 +748,7 @@ static void __iommu_sync_sg_for_device(struct device *dev,
>  
>  static int __iommu_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
>  				int nelems, enum dma_data_direction dir,
> -				struct dma_attrs *attrs)
> +				unsigned long attrs)
>  {
>  	bool coherent = is_device_dma_coherent(dev);
>  
> @@ -761,7 +762,7 @@ static int __iommu_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
>  static void __iommu_unmap_sg_attrs(struct device *dev,
>  				   struct scatterlist *sgl, int nelems,
>  				   enum dma_data_direction dir,
> -				   struct dma_attrs *attrs)
> +				   unsigned long attrs)
>  {
>  	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
>  		__iommu_sync_sg_for_cpu(dev, sgl, nelems, dir);
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
> index 67dcd6831291..dd091175fc2d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
> @@ -52,7 +52,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
>  
>  	ret = dma_mmap_attrs(to_dma_dev(helper->dev), vma, exynos_gem->cookie,
>  			     exynos_gem->dma_addr, exynos_gem->size,
> -			     &exynos_gem->dma_attrs);
> +			     exynos_gem->dma_attrs);
>  	if (ret < 0) {
>  		DRM_ERROR("failed to mmap.\n");
>  		return ret;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> index 493552368295..f65e6b7ef93b 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
> @@ -17,7 +17,6 @@
>  #include <linux/slab.h>
>  #include <linux/workqueue.h>
>  #include <linux/dma-mapping.h>
> -#include <linux/dma-attrs.h>
>  #include <linux/of.h>
>  
>  #include <drm/drmP.h>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
> index cdf9f1af4347..f2ae72ba7d5a 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
> @@ -24,7 +24,7 @@
>  static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
>  {
>  	struct drm_device *dev = exynos_gem->base.dev;
> -	enum dma_attr attr;
> +	unsigned long attr;
>  	unsigned int nr_pages;
>  	struct sg_table sgt;
>  	int ret = -ENOMEM;
> @@ -34,7 +34,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
>  		return 0;
>  	}
>  
> -	init_dma_attrs(&exynos_gem->dma_attrs);
> +	exynos_gem->dma_attrs = 0;
>  
>  	/*
>  	 * if EXYNOS_BO_CONTIG, fully physically contiguous memory
> @@ -42,7 +42,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
>  	 * as possible.
>  	 */
>  	if (!(exynos_gem->flags & EXYNOS_BO_NONCONTIG))
> -		dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &exynos_gem->dma_attrs);
> +		exynos_gem->dma_attrs |= DMA_ATTR_FORCE_CONTIGUOUS;
>  
>  	/*
>  	 * if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping
> @@ -54,8 +54,8 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
>  	else
>  		attr = DMA_ATTR_NON_CONSISTENT;
>  
> -	dma_set_attr(attr, &exynos_gem->dma_attrs);
> -	dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &exynos_gem->dma_attrs);
> +	exynos_gem->dma_attrs |= attr;
> +	exynos_gem->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
>  
>  	nr_pages = exynos_gem->size >> PAGE_SHIFT;
>  
> @@ -67,7 +67,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
>  
>  	exynos_gem->cookie = dma_alloc_attrs(to_dma_dev(dev), exynos_gem->size,
>  					     &exynos_gem->dma_addr, GFP_KERNEL,
> -					     &exynos_gem->dma_attrs);
> +					     exynos_gem->dma_attrs);
>  	if (!exynos_gem->cookie) {
>  		DRM_ERROR("failed to allocate buffer.\n");
>  		goto err_free;
> @@ -75,7 +75,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
>  
>  	ret = dma_get_sgtable_attrs(to_dma_dev(dev), &sgt, exynos_gem->cookie,
>  				    exynos_gem->dma_addr, exynos_gem->size,
> -				    &exynos_gem->dma_attrs);
> +				    exynos_gem->dma_attrs);
>  	if (ret < 0) {
>  		DRM_ERROR("failed to get sgtable.\n");
>  		goto err_dma_free;
> @@ -99,7 +99,7 @@ err_sgt_free:
>  	sg_free_table(&sgt);
>  err_dma_free:
>  	dma_free_attrs(to_dma_dev(dev), exynos_gem->size, exynos_gem->cookie,
> -		       exynos_gem->dma_addr, &exynos_gem->dma_attrs);
> +		       exynos_gem->dma_addr, exynos_gem->dma_attrs);
>  err_free:
>  	drm_free_large(exynos_gem->pages);
>  
> @@ -120,7 +120,7 @@ static void exynos_drm_free_buf(struct exynos_drm_gem *exynos_gem)
>  
>  	dma_free_attrs(to_dma_dev(dev), exynos_gem->size, exynos_gem->cookie,
>  			(dma_addr_t)exynos_gem->dma_addr,
> -			&exynos_gem->dma_attrs);
> +			exynos_gem->dma_attrs);
>  
>  	drm_free_large(exynos_gem->pages);
>  }
> @@ -346,7 +346,7 @@ static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
>  
>  	ret = dma_mmap_attrs(to_dma_dev(drm_dev), vma, exynos_gem->cookie,
>  			     exynos_gem->dma_addr, exynos_gem->size,
> -			     &exynos_gem->dma_attrs);
> +			     exynos_gem->dma_attrs);
>  	if (ret < 0) {
>  		DRM_ERROR("failed to mmap.\n");
>  		return ret;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
> index 78100742281d..df7c543d6558 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
> +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
> @@ -50,7 +50,7 @@ struct exynos_drm_gem {
>  	void			*cookie;
>  	void __iomem		*kvaddr;
>  	dma_addr_t		dma_addr;
> -	struct dma_attrs	dma_attrs;
> +	unsigned long		dma_attrs;
>  	struct page		**pages;
>  	struct sg_table		*sgt;
>  };
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index ea5a9ebf0f78..6c1bda504fb1 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -286,7 +286,7 @@ void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
>   *	   or NULL on failure.
>   */
>  struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
> -		struct dma_attrs *attrs, int prot, dma_addr_t *handle,
> +		unsigned long attrs, int prot, dma_addr_t *handle,
>  		void (*flush_page)(struct device *, const void *, phys_addr_t))
>  {
>  	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
> @@ -400,7 +400,7 @@ dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
>  }
>  
>  void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
> -		enum dma_data_direction dir, struct dma_attrs *attrs)
> +		enum dma_data_direction dir, unsigned long attrs)
>  {
>  	__iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
>  }
> @@ -560,7 +560,7 @@ out_restore_sg:
>  }
>  
>  void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
> -		enum dma_data_direction dir, struct dma_attrs *attrs)
> +		enum dma_data_direction dir, unsigned long attrs)
>  {
>  	/*
>  	 * The scatterlist segments are mapped into a single
> diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
> index 7399782c0998..87e6035c9e81 100644
> --- a/drivers/xen/swiotlb-xen.c
> +++ b/drivers/xen/swiotlb-xen.c
> @@ -294,7 +294,7 @@ error:
>  void *
>  xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
>  			   dma_addr_t *dma_handle, gfp_t flags,
> -			   struct dma_attrs *attrs)
> +			   unsigned long attrs)
>  {
>  	void *ret;
>  	int order = get_order(size);
> @@ -346,7 +346,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_alloc_coherent);
>  
>  void
>  xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
> -			  dma_addr_t dev_addr, struct dma_attrs *attrs)
> +			  dma_addr_t dev_addr, unsigned long attrs)
>  {
>  	int order = get_order(size);
>  	phys_addr_t phys;
> @@ -378,7 +378,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_free_coherent);
>  dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
>  				unsigned long offset, size_t size,
>  				enum dma_data_direction dir,
> -				struct dma_attrs *attrs)
> +				unsigned long attrs)
>  {
>  	phys_addr_t map, phys = page_to_phys(page) + offset;
>  	dma_addr_t dev_addr = xen_phys_to_bus(phys);
> @@ -434,7 +434,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_map_page);
>   */
>  static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
>  			     size_t size, enum dma_data_direction dir,
> -				 struct dma_attrs *attrs)
> +			     unsigned long attrs)
>  {
>  	phys_addr_t paddr = xen_bus_to_phys(dev_addr);
>  
> @@ -462,7 +462,7 @@ static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
>  
>  void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
>  			    size_t size, enum dma_data_direction dir,
> -			    struct dma_attrs *attrs)
> +			    unsigned long attrs)
>  {
>  	xen_unmap_single(hwdev, dev_addr, size, dir, attrs);
>  }
> @@ -538,7 +538,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_sync_single_for_device);
>  int
>  xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
>  			 int nelems, enum dma_data_direction dir,
> -			 struct dma_attrs *attrs)
> +			 unsigned long attrs)
>  {
>  	struct scatterlist *sg;
>  	int i;
> @@ -599,7 +599,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg_attrs);
>  void
>  xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
>  			   int nelems, enum dma_data_direction dir,
> -			   struct dma_attrs *attrs)
> +			   unsigned long attrs)
>  {
>  	struct scatterlist *sg;
>  	int i;
> diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
> deleted file mode 100644
> index 5246239a4953..000000000000
> --- a/include/linux/dma-attrs.h
> +++ /dev/null
> @@ -1,71 +0,0 @@
> -#ifndef _DMA_ATTR_H
> -#define _DMA_ATTR_H
> -
> -#include <linux/bitmap.h>
> -#include <linux/bitops.h>
> -#include <linux/bug.h>
> -
> -/**
> - * an enum dma_attr represents an attribute associated with a DMA
> - * mapping. The semantics of each attribute should be defined in
> - * Documentation/DMA-attributes.txt.
> - */
> -enum dma_attr {
> -	DMA_ATTR_WRITE_BARRIER,
> -	DMA_ATTR_WEAK_ORDERING,
> -	DMA_ATTR_WRITE_COMBINE,
> -	DMA_ATTR_NON_CONSISTENT,
> -	DMA_ATTR_NO_KERNEL_MAPPING,
> -	DMA_ATTR_SKIP_CPU_SYNC,
> -	DMA_ATTR_FORCE_CONTIGUOUS,
> -	DMA_ATTR_ALLOC_SINGLE_PAGES,
> -	DMA_ATTR_MAX,
> -};
> -
> -#define __DMA_ATTRS_LONGS BITS_TO_LONGS(DMA_ATTR_MAX)
> -
> -/**
> - * struct dma_attrs - an opaque container for DMA attributes
> - * @flags - bitmask representing a collection of enum dma_attr
> - */
> -struct dma_attrs {
> -	unsigned long flags[__DMA_ATTRS_LONGS];
> -};
> -
> -#define DEFINE_DMA_ATTRS(x) 					\
> -	struct dma_attrs x = {					\
> -		.flags = { [0 ... __DMA_ATTRS_LONGS-1] = 0 },	\
> -	}
> -
> -static inline void init_dma_attrs(struct dma_attrs *attrs)
> -{
> -	bitmap_zero(attrs->flags, __DMA_ATTRS_LONGS);
> -}
> -
> -/**
> - * dma_set_attr - set a specific attribute
> - * @attr: attribute to set
> - * @attrs: struct dma_attrs (may be NULL)
> - */
> -static inline void dma_set_attr(enum dma_attr attr, struct dma_attrs *attrs)
> -{
> -	if (attrs == NULL)
> -		return;
> -	BUG_ON(attr >= DMA_ATTR_MAX);
> -	__set_bit(attr, attrs->flags);
> -}
> -
> -/**
> - * dma_get_attr - check for a specific attribute
> - * @attr: attribute to set
> - * @attrs: struct dma_attrs (may be NULL)
> - */
> -static inline int dma_get_attr(enum dma_attr attr, struct dma_attrs *attrs)
> -{
> -	if (attrs == NULL)
> -		return 0;
> -	BUG_ON(attr >= DMA_ATTR_MAX);
> -	return test_bit(attr, attrs->flags);
> -}
> -
> -#endif /* _DMA_ATTR_H */
> diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
> index 8443bbb5c071..81c5c8d167ad 100644
> --- a/include/linux/dma-iommu.h
> +++ b/include/linux/dma-iommu.h
> @@ -39,7 +39,7 @@ int dma_direction_to_prot(enum dma_data_direction dir, bool coherent);
>   * the arch code to take care of attributes and cache maintenance
>   */
>  struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
> -		struct dma_attrs *attrs, int prot, dma_addr_t *handle,
> +		unsigned long attrs, int prot, dma_addr_t *handle,
>  		void (*flush_page)(struct device *, const void *, phys_addr_t));
>  void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
>  		dma_addr_t *handle);
> @@ -56,9 +56,9 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
>   * directly as DMA mapping callbacks for simplicity
>   */
>  void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
> -		enum dma_data_direction dir, struct dma_attrs *attrs);
> +		enum dma_data_direction dir, unsigned long attrs);
>  void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
> -		enum dma_data_direction dir, struct dma_attrs *attrs);
> +		enum dma_data_direction dir, unsigned long attrs);
>  int iommu_dma_supported(struct device *dev, u64 mask);
>  int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
>  
> diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
> index 71c1b215ef66..19e581d5f8b4 100644
> --- a/include/linux/dma-mapping.h
> +++ b/include/linux/dma-mapping.h
> @@ -5,13 +5,25 @@
>  #include <linux/string.h>
>  #include <linux/device.h>
>  #include <linux/err.h>
> -#include <linux/dma-attrs.h>
>  #include <linux/dma-debug.h>
>  #include <linux/dma-direction.h>
>  #include <linux/scatterlist.h>
>  #include <linux/kmemcheck.h>
>  #include <linux/bug.h>
>  
> +/**
> + * List of possible attributes associated with a DMA mapping. The semantics
> + * of each attribute should be defined in Documentation/DMA-attributes.txt.
> + */
> +#define DMA_ATTR_WRITE_BARRIER		BIT(1)
> +#define DMA_ATTR_WEAK_ORDERING		BIT(2)
> +#define DMA_ATTR_WRITE_COMBINE		BIT(3)
> +#define DMA_ATTR_NON_CONSISTENT		BIT(4)
> +#define DMA_ATTR_NO_KERNEL_MAPPING	BIT(5)
> +#define DMA_ATTR_SKIP_CPU_SYNC		BIT(6)
> +#define DMA_ATTR_FORCE_CONTIGUOUS	BIT(7)
> +#define DMA_ATTR_ALLOC_SINGLE_PAGES	BIT(8)
> +
>  /*
>   * A dma_addr_t can hold any valid DMA or bus address for the platform.
>   * It can be given to a device to use as a DMA source or target.  A CPU cannot
> @@ -21,34 +33,35 @@
>  struct dma_map_ops {
>  	void* (*alloc)(struct device *dev, size_t size,
>  				dma_addr_t *dma_handle, gfp_t gfp,
> -				struct dma_attrs *attrs);
> +				unsigned long attrs);
>  	void (*free)(struct device *dev, size_t size,
>  			      void *vaddr, dma_addr_t dma_handle,
> -			      struct dma_attrs *attrs);
> +			      unsigned long attrs);
>  	int (*mmap)(struct device *, struct vm_area_struct *,
> -			  void *, dma_addr_t, size_t, struct dma_attrs *attrs);
> +			  void *, dma_addr_t, size_t,
> +			  unsigned long attrs);
>  
>  	int (*get_sgtable)(struct device *dev, struct sg_table *sgt, void *,
> -			   dma_addr_t, size_t, struct dma_attrs *attrs);
> +			   dma_addr_t, size_t, unsigned long attrs);
>  
>  	dma_addr_t (*map_page)(struct device *dev, struct page *page,
>  			       unsigned long offset, size_t size,
>  			       enum dma_data_direction dir,
> -			       struct dma_attrs *attrs);
> +			       unsigned long attrs);
>  	void (*unmap_page)(struct device *dev, dma_addr_t dma_handle,
>  			   size_t size, enum dma_data_direction dir,
> -			   struct dma_attrs *attrs);
> +			   unsigned long attrs);
>  	/*
>  	 * map_sg returns 0 on error and a value > 0 on success.
>  	 * It should never return a value < 0.
>  	 */
>  	int (*map_sg)(struct device *dev, struct scatterlist *sg,
>  		      int nents, enum dma_data_direction dir,
> -		      struct dma_attrs *attrs);
> +		      unsigned long attrs);
>  	void (*unmap_sg)(struct device *dev,
>  			 struct scatterlist *sg, int nents,
>  			 enum dma_data_direction dir,
> -			 struct dma_attrs *attrs);
> +			 unsigned long attrs);
>  	void (*sync_single_for_cpu)(struct device *dev,
>  				    dma_addr_t dma_handle, size_t size,
>  				    enum dma_data_direction dir);
> @@ -88,6 +101,16 @@ static inline int is_device_dma_capable(struct device *dev)
>  	return dev->dma_mask != NULL && *dev->dma_mask != DMA_MASK_NONE;
>  }
>  
> +/**
> + * dma_get_attr - check for a specific attribute
> + * @attr: attribute to look for
> + * @attrs: attributes to check within
> + */
> +static inline bool dma_get_attr(unsigned long attr, unsigned long attrs)
> +{
> +	return !!(attr & attrs);
> +}
> +
>  #ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
>  /*
>   * These three functions are only for dma allocator.
> @@ -123,7 +146,7 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
>  static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
>  					      size_t size,
>  					      enum dma_data_direction dir,
> -					      struct dma_attrs *attrs)
> +					      unsigned long attrs)
>  {
>  	struct dma_map_ops *ops = get_dma_ops(dev);
>  	dma_addr_t addr;
> @@ -142,7 +165,7 @@ static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
>  static inline void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr,
>  					  size_t size,
>  					  enum dma_data_direction dir,
> -					  struct dma_attrs *attrs)
> +					  unsigned long attrs)
>  {
>  	struct dma_map_ops *ops = get_dma_ops(dev);
>  
> @@ -158,7 +181,7 @@ static inline void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr,
>   */
>  static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
>  				   int nents, enum dma_data_direction dir,
> -				   struct dma_attrs *attrs)
> +				   unsigned long attrs)
>  {
>  	struct dma_map_ops *ops = get_dma_ops(dev);
>  	int i, ents;
> @@ -176,7 +199,7 @@ static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
>  
>  static inline void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
>  				      int nents, enum dma_data_direction dir,
> -				      struct dma_attrs *attrs)
> +				      unsigned long attrs)
>  {
>  	struct dma_map_ops *ops = get_dma_ops(dev);
>  
> @@ -195,7 +218,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
>  
>  	kmemcheck_mark_initialized(page_address(page) + offset, size);
>  	BUG_ON(!valid_dma_direction(dir));
> -	addr = ops->map_page(dev, page, offset, size, dir, NULL);
> +	addr = ops->map_page(dev, page, offset, size, dir, 0);
>  	debug_dma_map_page(dev, page, offset, size, dir, addr, false);
>  
>  	return addr;
> @@ -208,7 +231,7 @@ static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
>  
>  	BUG_ON(!valid_dma_direction(dir));
>  	if (ops->unmap_page)
> -		ops->unmap_page(dev, addr, size, dir, NULL);
> +		ops->unmap_page(dev, addr, size, dir, 0);
>  	debug_dma_unmap_page(dev, addr, size, dir, false);
>  }
>  
> @@ -289,10 +312,10 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
>  
>  }
>  
> -#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL)
> -#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, NULL)
> -#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL)
> -#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL)
> +#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, 0)
> +#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, 0)
> +#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
> +#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
>  
>  extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
>  			   void *cpu_addr, dma_addr_t dma_addr, size_t size);
> @@ -321,7 +344,7 @@ void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags);
>   */
>  static inline int
>  dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr,
> -	       dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
> +	       dma_addr_t dma_addr, size_t size, unsigned long attrs)
>  {
>  	struct dma_map_ops *ops = get_dma_ops(dev);
>  	BUG_ON(!ops);
> @@ -330,7 +353,7 @@ dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr,
>  	return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
>  }
>  
> -#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, NULL)
> +#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, 0)
>  
>  int
>  dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
> @@ -338,7 +361,8 @@ dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
>  
>  static inline int
>  dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr,
> -		      dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
> +		      dma_addr_t dma_addr, size_t size,
> +		      unsigned long attrs)
>  {
>  	struct dma_map_ops *ops = get_dma_ops(dev);
>  	BUG_ON(!ops);
> @@ -348,7 +372,7 @@ dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr,
>  	return dma_common_get_sgtable(dev, sgt, cpu_addr, dma_addr, size);
>  }
>  
> -#define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, NULL)
> +#define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, 0)
>  
>  #ifndef arch_dma_alloc_attrs
>  #define arch_dma_alloc_attrs(dev, flag)	(true)
> @@ -356,7 +380,7 @@ dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr,
>  
>  static inline void *dma_alloc_attrs(struct device *dev, size_t size,
>  				       dma_addr_t *dma_handle, gfp_t flag,
> -				       struct dma_attrs *attrs)
> +				       unsigned long attrs)
>  {
>  	struct dma_map_ops *ops = get_dma_ops(dev);
>  	void *cpu_addr;
> @@ -378,7 +402,7 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size,
>  
>  static inline void dma_free_attrs(struct device *dev, size_t size,
>  				     void *cpu_addr, dma_addr_t dma_handle,
> -				     struct dma_attrs *attrs)
> +				     unsigned long attrs)
>  {
>  	struct dma_map_ops *ops = get_dma_ops(dev);
>  
> @@ -398,31 +422,27 @@ static inline void dma_free_attrs(struct device *dev, size_t size,
>  static inline void *dma_alloc_coherent(struct device *dev, size_t size,
>  		dma_addr_t *dma_handle, gfp_t flag)
>  {
> -	return dma_alloc_attrs(dev, size, dma_handle, flag, NULL);
> +	return dma_alloc_attrs(dev, size, dma_handle, flag, 0);
>  }
>  
>  static inline void dma_free_coherent(struct device *dev, size_t size,
>  		void *cpu_addr, dma_addr_t dma_handle)
>  {
> -	return dma_free_attrs(dev, size, cpu_addr, dma_handle, NULL);
> +	return dma_free_attrs(dev, size, cpu_addr, dma_handle, 0);
>  }
>  
>  static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
>  		dma_addr_t *dma_handle, gfp_t gfp)
>  {
> -	DEFINE_DMA_ATTRS(attrs);
> -
> -	dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
> -	return dma_alloc_attrs(dev, size, dma_handle, gfp, &attrs);
> +	return dma_alloc_attrs(dev, size, dma_handle, gfp,
> +			       DMA_ATTR_NON_CONSISTENT);
>  }
>  
>  static inline void dma_free_noncoherent(struct device *dev, size_t size,
>  		void *cpu_addr, dma_addr_t dma_handle)
>  {
> -	DEFINE_DMA_ATTRS(attrs);
> -
> -	dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
> -	dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
> +	dma_free_attrs(dev, size, cpu_addr, dma_handle,
> +		       DMA_ATTR_NON_CONSISTENT);
>  }
>  
>  static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
> @@ -646,9 +666,8 @@ static inline void dmam_release_declared_memory(struct device *dev)
>  static inline void *dma_alloc_wc(struct device *dev, size_t size,
>  				 dma_addr_t *dma_addr, gfp_t gfp)
>  {
> -	DEFINE_DMA_ATTRS(attrs);
> -	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
> -	return dma_alloc_attrs(dev, size, dma_addr, gfp, &attrs);
> +	return dma_alloc_attrs(dev, size, dma_addr, gfp,
> +			       DMA_ATTR_WRITE_COMBINE);
>  }
>  #ifndef dma_alloc_writecombine
>  #define dma_alloc_writecombine dma_alloc_wc
> @@ -657,9 +676,8 @@ static inline void *dma_alloc_wc(struct device *dev, size_t size,
>  static inline void dma_free_wc(struct device *dev, size_t size,
>  			       void *cpu_addr, dma_addr_t dma_addr)
>  {
> -	DEFINE_DMA_ATTRS(attrs);
> -	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
> -	return dma_free_attrs(dev, size, cpu_addr, dma_addr, &attrs);
> +	return dma_free_attrs(dev, size, cpu_addr, dma_addr,
> +			      DMA_ATTR_WRITE_COMBINE);
>  }
>  #ifndef dma_free_writecombine
>  #define dma_free_writecombine dma_free_wc
> @@ -670,9 +688,8 @@ static inline int dma_mmap_wc(struct device *dev,
>  			      void *cpu_addr, dma_addr_t dma_addr,
>  			      size_t size)
>  {
> -	DEFINE_DMA_ATTRS(attrs);
> -	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
> -	return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
> +	return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size,
> +			      DMA_ATTR_WRITE_COMBINE);
>  }
>  #ifndef dma_mmap_writecombine
>  #define dma_mmap_writecombine dma_mmap_wc
> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> index 017fced60242..5f81f8a187f2 100644
> --- a/include/linux/swiotlb.h
> +++ b/include/linux/swiotlb.h
> @@ -6,7 +6,6 @@
>  #include <linux/types.h>
>  
>  struct device;
> -struct dma_attrs;
>  struct page;
>  struct scatterlist;
>  
> @@ -68,10 +67,10 @@ swiotlb_free_coherent(struct device *hwdev, size_t size,
>  extern dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
>  				   unsigned long offset, size_t size,
>  				   enum dma_data_direction dir,
> -				   struct dma_attrs *attrs);
> +				   unsigned long attrs);
>  extern void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
>  			       size_t size, enum dma_data_direction dir,
> -			       struct dma_attrs *attrs);
> +			       unsigned long attrs);
>  
>  extern int
>  swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
> @@ -83,12 +82,13 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
>  
>  extern int
>  swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
> -		     enum dma_data_direction dir, struct dma_attrs *attrs);
> +		     enum dma_data_direction dir,
> +		     unsigned long attrs);
>  
>  extern void
>  swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
>  		       int nelems, enum dma_data_direction dir,
> -		       struct dma_attrs *attrs);
> +		       unsigned long attrs);
>  
>  extern void
>  swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
> diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h
> index 8b2eb93ae8ba..7c35e279d1e3 100644
> --- a/include/xen/swiotlb-xen.h
> +++ b/include/xen/swiotlb-xen.h
> @@ -9,30 +9,30 @@ extern int xen_swiotlb_init(int verbose, bool early);
>  extern void
>  *xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
>  			    dma_addr_t *dma_handle, gfp_t flags,
> -			    struct dma_attrs *attrs);
> +			    unsigned long attrs);
>  
>  extern void
>  xen_swiotlb_free_coherent(struct device *hwdev, size_t size,
>  			  void *vaddr, dma_addr_t dma_handle,
> -			  struct dma_attrs *attrs);
> +			  unsigned long attrs);
>  
>  extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
>  				       unsigned long offset, size_t size,
>  				       enum dma_data_direction dir,
> -				       struct dma_attrs *attrs);
> +				       unsigned long attrs);
>  
>  extern void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
>  				   size_t size, enum dma_data_direction dir,
> -				   struct dma_attrs *attrs);
> +				   unsigned long attrs);
>  extern int
>  xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
>  			 int nelems, enum dma_data_direction dir,
> -			 struct dma_attrs *attrs);
> +			 unsigned long attrs);
>  
>  extern void
>  xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
>  			   int nelems, enum dma_data_direction dir,
> -			   struct dma_attrs *attrs);
> +			   unsigned long attrs);
>  
>  extern void
>  xen_swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
> diff --git a/lib/dma-noop.c b/lib/dma-noop.c
> index 72145646857e..3d766e78fbe2 100644
> --- a/lib/dma-noop.c
> +++ b/lib/dma-noop.c
> @@ -10,7 +10,7 @@
>  
>  static void *dma_noop_alloc(struct device *dev, size_t size,
>  			    dma_addr_t *dma_handle, gfp_t gfp,
> -			    struct dma_attrs *attrs)
> +			    unsigned long attrs)
>  {
>  	void *ret;
>  
> @@ -22,7 +22,7 @@ static void *dma_noop_alloc(struct device *dev, size_t size,
>  
>  static void dma_noop_free(struct device *dev, size_t size,
>  			  void *cpu_addr, dma_addr_t dma_addr,
> -			  struct dma_attrs *attrs)
> +			  unsigned long attrs)
>  {
>  	free_pages((unsigned long)cpu_addr, get_order(size));
>  }
> @@ -30,13 +30,14 @@ static void dma_noop_free(struct device *dev, size_t size,
>  static dma_addr_t dma_noop_map_page(struct device *dev, struct page *page,
>  				      unsigned long offset, size_t size,
>  				      enum dma_data_direction dir,
> -				      struct dma_attrs *attrs)
> +				      unsigned long attrs)
>  {
>  	return page_to_phys(page) + offset;
>  }
>  
>  static int dma_noop_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
> -			     enum dma_data_direction dir, struct dma_attrs *attrs)
> +			     enum dma_data_direction dir,
> +			     unsigned long attrs)
>  {
>  	int i;
>  	struct scatterlist *sg;
> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
> index 76f29ecba8f4..22e13a0e19d7 100644
> --- a/lib/swiotlb.c
> +++ b/lib/swiotlb.c
> @@ -738,7 +738,7 @@ swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir,
>  dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
>  			    unsigned long offset, size_t size,
>  			    enum dma_data_direction dir,
> -			    struct dma_attrs *attrs)
> +			    unsigned long attrs)
>  {
>  	phys_addr_t map, phys = page_to_phys(page) + offset;
>  	dma_addr_t dev_addr = phys_to_dma(dev, phys);
> @@ -807,7 +807,7 @@ static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
>  
>  void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
>  			size_t size, enum dma_data_direction dir,
> -			struct dma_attrs *attrs)
> +			unsigned long attrs)
>  {
>  	unmap_single(hwdev, dev_addr, size, dir);
>  }
> @@ -877,7 +877,7 @@ EXPORT_SYMBOL(swiotlb_sync_single_for_device);
>   */
>  int
>  swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
> -		     enum dma_data_direction dir, struct dma_attrs *attrs)
> +		     enum dma_data_direction dir, unsigned long attrs)
>  {
>  	struct scatterlist *sg;
>  	int i;
> @@ -914,7 +914,7 @@ int
>  swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
>  	       enum dma_data_direction dir)
>  {
> -	return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL);
> +	return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, 0);
>  }
>  EXPORT_SYMBOL(swiotlb_map_sg);
>  
> @@ -924,7 +924,8 @@ EXPORT_SYMBOL(swiotlb_map_sg);
>   */
>  void
>  swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
> -		       int nelems, enum dma_data_direction dir, struct dma_attrs *attrs)
> +		       int nelems, enum dma_data_direction dir,
> +		       unsigned long attrs)
>  {
>  	struct scatterlist *sg;
>  	int i;
> @@ -941,7 +942,7 @@ void
>  swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
>  		 enum dma_data_direction dir)
>  {
> -	return swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL);
> +	return swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, 0);
>  }
>  EXPORT_SYMBOL(swiotlb_unmap_sg);
>  
> -- 
> 1.9.1
> 
> _______________________________________________
> iommu mailing list
> iommu at lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/iommu


From tony at atomide.com  Tue May 31 11:19:04 2016
From: tony at atomide.com (Tony Lindgren)
Date: Tue, 31 May 2016 11:19:04 -0700
Subject: [PATCH 0/5] ARM: dts: omap3-gta04: Various updates
In-Reply-To: <CAAfyv37NE1eogrSRCuRY-9V30FtD3u7oeFWMJk=xNX1hFJ9O-w@mail.gmail.com>
References: <1463514531-7235-1-git-send-email-marek@goldelico.com>
 <CAAfyv37NE1eogrSRCuRY-9V30FtD3u7oeFWMJk=xNX1hFJ9O-w@mail.gmail.com>
Message-ID: <20160531181903.GB5995@atomide.com>

* Belisko Marek <marek.belisko at gmail.com> [160530 23:50]:
> Ping? Any objections? Thanks.

Looks OK to me, with v4.7-rc1 out I'll start applying patches
again once the pending fixes are out of the way. So it will be
few more days, probably around -rc2 time.

Regards,

Tony


From will.deacon at arm.com  Tue May 31 11:20:46 2016
From: will.deacon at arm.com (Will Deacon)
Date: Tue, 31 May 2016 19:20:46 +0100
Subject: [PATCH] ARM: fix PTRACE_SETVFPREGS on SMP systems
In-Reply-To: <E1b7oBz-0005wE-1t@rmk-PC.armlinux.org.uk>
References: <E1b7oBz-0005wE-1t@rmk-PC.armlinux.org.uk>
Message-ID: <20160531182045.GZ24936@arm.com>

On Tue, May 31, 2016 at 07:15:03PM +0100, Russell King wrote:
> PTRACE_SETVFPREGS fails to properly mark the VFP register set to be
> reloaded, because it undoes one of the effects of vfp_flush_hwstate().
> 
> Specifically vfp_flush_hwstate() sets thread->vfpstate.hard.cpu to
> an invalid CPU number, but vfp_set() overwrites this with the original
> CPU number, thereby rendering the hardware state as apparently "valid",
> even though the software state is more recent.
> 
> Fix this by reverting the previous change.
> 
> Cc: <stable at vger.kernel.org>
> Fixes: 8130b9d7b9d8 ("ARM: 7308/1: vfp: flush thread hwstate before copying ptrace registers")
> Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
> ---
> Will, please ack this.

Acked-by: Will Deacon <will.deacon at arm.com>

Will

> 
>  arch/arm/kernel/ptrace.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
> index ef9119f7462e..4d9375814b53 100644
> --- a/arch/arm/kernel/ptrace.c
> +++ b/arch/arm/kernel/ptrace.c
> @@ -733,8 +733,8 @@ static int vfp_set(struct task_struct *target,
>  	if (ret)
>  		return ret;
>  
> -	vfp_flush_hwstate(thread);
>  	thread->vfpstate.hard = new_vfp;
> +	vfp_flush_hwstate(thread);
>  
>  	return 0;
>  }
> -- 
> 2.1.0
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


From krzk at kernel.org  Tue May 31 11:39:00 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 20:39:00 +0200
Subject: [PATCH 1/6] dt-bindings: clock: Add TMU clock ID to Exynos5410
Message-ID: <1464719945-3417-1-git-send-email-krzk@kernel.org>

Add ID for TMU clock to Exynos5410. Use the same number as for
Exynos5420 just in case in future these drivers were merged.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 include/dt-bindings/clock/exynos5410.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
index e94b7bbfd6af..705b2aa84317 100644
--- a/include/dt-bindings/clock/exynos5410.h
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -50,6 +50,7 @@
 #define CLK_PWM			279
 #define CLK_MCT			315
 #define CLK_RTC			317
+#define CLK_TMU			318
 #define CLK_MMC0		351
 #define CLK_MMC1		352
 #define CLK_MMC2		353
-- 
2.7.4



From krzk at kernel.org  Tue May 31 11:39:01 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 20:39:01 +0200
Subject: [PATCH 2/6] clk: samsung: exynos5410: Add TMU clock
In-Reply-To: <1464719945-3417-1-git-send-email-krzk@kernel.org>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
Message-ID: <1464719945-3417-2-git-send-email-krzk@kernel.org>

Add clock for TMU to the Exynos5410 clock driver.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 drivers/clk/samsung/clk-exynos5410.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
index 6c2e59c576ee..db9978dc6e83 100644
--- a/drivers/clk/samsung/clk-exynos5410.c
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -160,6 +160,7 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
 static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
 	GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
 	GATE(CLK_RTC, "rtc", "aclk66", GATE_IP_PERIS, 20, 0, 0),
+	GATE(CLK_TMU, "tmu", "aclk66", GATE_IP_PERIS, 21, 0, 0),
 
 	GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
 			SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
-- 
2.7.4



From krzk at kernel.org  Tue May 31 11:39:02 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 20:39:02 +0200
Subject: [PATCH 3/6] ARM: dts: exynos: Interrupt for USB DWC3-1 differs
 between Exynos5420 and 5410
In-Reply-To: <1464719945-3417-1-git-send-email-krzk@kernel.org>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
Message-ID: <1464719945-3417-3-git-send-email-krzk@kernel.org>

On Exynos5410 the SPI interrupt for second USB DWC3 (called DRD: Dual
Role Device) is different - 200 instead of 73.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410.dtsi | 4 ++++
 arch/arm/boot/dts/exynos5420.dtsi | 4 ++++
 arch/arm/boot/dts/exynos54xx.dtsi | 1 -
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index a937d9bdad90..994d16a44fe4 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -267,6 +267,10 @@
 	clock-names = "usbdrd30";
 };
 
+&usbdrd_dwc3_1 {
+	interrupts = <0 200 0>;
+};
+
 &usbdrd_phy1 {
 	clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
 	clock-names = "phy", "ref";
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 8b1e706e9250..265747bb19d1 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -1046,6 +1046,10 @@
 	clock-names = "usbdrd30";
 };
 
+&usbdrd_dwc3_1 {
+	interrupts = <0 73 0>;
+};
+
 &usbdrd_phy1 {
 	clocks = <&clock CLK_USBD301>, <&clock CLK_SCLK_USBPHY301>;
 	clock-names = "phy", "ref";
diff --git a/arch/arm/boot/dts/exynos54xx.dtsi b/arch/arm/boot/dts/exynos54xx.dtsi
index 44a8391c8524..0eb8aa31b7d9 100644
--- a/arch/arm/boot/dts/exynos54xx.dtsi
+++ b/arch/arm/boot/dts/exynos54xx.dtsi
@@ -141,7 +141,6 @@
 			usbdrd_dwc3_1: dwc3 at 12400000 {
 				compatible = "snps,dwc3";
 				reg = <0x12400000 0x10000>;
-				interrupts = <0 73 0>;
 				phys = <&usbdrd_phy1 0>, <&usbdrd_phy1 1>;
 				phy-names = "usb2-phy", "usb3-phy";
 			};
-- 
2.7.4



From krzk at kernel.org  Tue May 31 11:39:03 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 20:39:03 +0200
Subject: [PATCH 4/6] ARM: dts: exynos: Add Thermal Management Unit to
 Exynos5410
In-Reply-To: <1464719945-3417-1-git-send-email-krzk@kernel.org>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
Message-ID: <1464719945-3417-4-git-send-email-krzk@kernel.org>

Add nodes for Thermal Management Unit to exynos5410.dtsi. Use the same
compatible as for Exynos5420 however without second base for TRIMINFO
register.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5410.dtsi | 55 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 994d16a44fe4..f1effd3f03c4 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -81,6 +81,42 @@
 			#clock-cells = <1>;
 		};
 
+		tmu_cpu0: tmu at 10060000 {
+			compatible = "samsung,exynos5420-tmu";
+			reg = <0x10060000 0x100>;
+			interrupts = <0 65 0>;
+			clocks = <&clock CLK_TMU>;
+			clock-names = "tmu_apbif";
+			#include "exynos4412-tmu-sensor-conf.dtsi"
+		};
+
+		tmu_cpu1: tmu at 10064000 {
+			compatible = "samsung,exynos5420-tmu";
+			reg = <0x10064000 0x100>;
+			interrupts = <0 183 0>;
+			clocks = <&clock CLK_TMU>;
+			clock-names = "tmu_apbif";
+			#include "exynos4412-tmu-sensor-conf.dtsi"
+		};
+
+		tmu_cpu2: tmu at 10068000 {
+			compatible = "samsung,exynos5420-tmu";
+			reg = <0x10068000 0x100>;
+			interrupts = <0 184 0>;
+			clocks = <&clock CLK_TMU>;
+			clock-names = "tmu_apbif";
+			#include "exynos4412-tmu-sensor-conf.dtsi"
+		};
+
+		tmu_cpu3: tmu at 1006c000 {
+			compatible = "samsung,exynos5420-tmu";
+			reg = <0x1006c000 0x100>;
+			interrupts = <0 185 0>;
+			clocks = <&clock CLK_TMU>;
+			clock-names = "tmu_apbif";
+			#include "exynos4412-tmu-sensor-conf.dtsi"
+		};
+
 		mmc_0: mmc at 12200000 {
 			compatible = "samsung,exynos5250-dw-mshc";
 			reg = <0x12200000 0x1000>;
@@ -147,6 +183,25 @@
 			interrupts = <0 47 0>;
 		};
 	};
+
+	thermal-zones {
+		cpu0_thermal: cpu0-thermal {
+			thermal-sensors = <&tmu_cpu0>;
+			#include "exynos5420-trip-points.dtsi"
+		};
+		cpu1_thermal: cpu1-thermal {
+		       thermal-sensors = <&tmu_cpu1>;
+		       #include "exynos5420-trip-points.dtsi"
+		};
+		cpu2_thermal: cpu2-thermal {
+		       thermal-sensors = <&tmu_cpu2>;
+		       #include "exynos5420-trip-points.dtsi"
+		};
+		cpu3_thermal: cpu3-thermal {
+		       thermal-sensors = <&tmu_cpu3>;
+		       #include "exynos5420-trip-points.dtsi"
+		};
+	};
 };
 
 &i2c_0 {
-- 
2.7.4



From krzk at kernel.org  Tue May 31 11:39:04 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 20:39:04 +0200
Subject: [PATCH 5/6] ARM: dts: exynos: Configure PWM, usb3503,
 PMIC and thermal on Odroid XU board
In-Reply-To: <1464719945-3417-1-git-send-email-krzk@kernel.org>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
Message-ID: <1464719945-3417-5-git-send-email-krzk@kernel.org>

Extend the DTS for Exynos5410-based Odroid XU board with:
1. Proper PWM outputs,
2. usb3503 USB HUB (with integrated LAN9730 ethernet adapter (smsc95xx)),
3. Maxim 77802 PMIC (regulators, 32 kHz clocks, RTC),
4. CPU thermal (trip points are the same as in Odroid XU3/XU4 but
   cooling maps are different as there is no CPU freq and only one
   cluster available for now),
5. Regulator supplies for USB 3.0.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>

---

Sources:
1. XU schematics
2. Hardkernel kernel tree:
   https://github.com/hardkernel/linux.git
   branch: odroidxu-3.4.y
   file: arch/arm/mach-exynos/board-odroidxu-power.c

Still USB over-current is reported:
[    2.115186] usb usb3-port1: over-current condition
[    2.118555] usb usb4-port1: over-current condition
---
 arch/arm/boot/dts/exynos5410-odroidxu.dts | 461 +++++++++++++++++++++++++++++-
 1 file changed, 460 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5410-odroidxu.dts b/arch/arm/boot/dts/exynos5410-odroidxu.dts
index 9fe04500ecaf..d9499310a301 100644
--- a/arch/arm/boot/dts/exynos5410-odroidxu.dts
+++ b/arch/arm/boot/dts/exynos5410-odroidxu.dts
@@ -12,6 +12,7 @@
 
 /dts-v1/;
 #include "exynos5410.dtsi"
+#include <dt-bindings/clock/maxim,max77802.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include "exynos54xx-odroidxu-leds.dtsi"
@@ -57,6 +58,387 @@
 	};
 };
 
+&cpu0_thermal {
+	thermal-sensors = <&tmu_cpu0 0>;
+	polling-delay-passive = <0>;
+	polling-delay = <0>;
+
+	trips {
+		cpu_alert0: cpu-alert-0 {
+			temperature = <50000>; /* millicelsius */
+			hysteresis = <5000>; /* millicelsius */
+			type = "active";
+		};
+		cpu_alert1: cpu-alert-1 {
+			temperature = <60000>; /* millicelsius */
+			hysteresis = <5000>; /* millicelsius */
+			type = "active";
+		};
+		cpu_alert2: cpu-alert-2 {
+			temperature = <70000>; /* millicelsius */
+			hysteresis = <5000>; /* millicelsius */
+			type = "active";
+		};
+		cpu_crit0: cpu-crit-0 {
+			temperature = <120000>; /* millicelsius */
+			hysteresis = <0>; /* millicelsius */
+			type = "critical";
+		};
+	};
+
+	cooling-maps {
+		map0 {
+			trip = <&cpu_alert0>;
+			cooling-device = <&fan0 0 1>;
+		};
+		map1 {
+			trip = <&cpu_alert1>;
+			cooling-device = <&fan0 1 2>;
+		};
+		map2 {
+			trip = <&cpu_alert2>;
+			cooling-device = <&fan0 2 3>;
+		};
+	};
+};
+
+&hsi2c_4 {
+	samsung,i2c-sda-delay = <100>;
+	samsung,i2c-max-bus-freq = <400000>;
+	status = "okay";
+
+	usb3503: usb-hub at 08 {
+		compatible = "smsc,usb3503";
+		reg = <0x08>;
+
+		intn-gpios = <&gpx0 7 GPIO_ACTIVE_HIGH>;
+		connect-gpios = <&gpx0 6 GPIO_ACTIVE_HIGH>;
+		reset-gpios = <&gpx1 4 GPIO_ACTIVE_HIGH>;
+		initial-mode = <1>;
+
+		clock-names = "refclk";
+		clocks = <&pmu_system_controller 0>;
+		refclk-frequency = <24000000>;
+	};
+
+	max77802: pmic at 09 {
+		compatible = "maxim,max77802";
+		reg = <0x9>;
+		interrupt-parent = <&gpx0>;
+		interrupts = <4 IRQ_TYPE_NONE>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&max77802_irq>, <&pmic_dvs_1>, <&pmic_dvs_2>,
+			    <&pmic_dvs_3>;
+		#clock-cells = <1>;
+
+		inl1-supply = <&buck5_reg>;
+		inl2-supply = <&buck7_reg>;
+		inl3-supply = <&buck9_reg>;
+		inl4-supply = <&buck9_reg>;
+		inl5-supply = <&buck9_reg>;
+		inl6-supply = <&buck10_reg>;
+		inl7-supply = <&buck9_reg>;
+		/* inl9 supply is BOOST, not configured here */
+		inl10-supply = <&buck7_reg>;
+
+		regulators {
+			buck1_reg: BUCK1 {
+				regulator-name = "vdd_mif";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck2_reg: BUCK2 {
+				regulator-name = "vdd_arm";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck3_reg: BUCK3 {
+				regulator-name = "vdd_int";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck4_reg: BUCK4 {
+				regulator-name = "vdd_g3d";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck5_reg: BUCK5 {
+				regulator-name = "vdd_mem";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck6_reg: BUCK6 {
+				regulator-name = "vdd_kfc";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck7_reg: BUCK7 {
+				regulator-name = "buck7";
+				regulator-min-microvolt = <1300000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck8_reg: BUCK8 {
+				/* vdd_mmc0 */
+				regulator-name = "vddf_2v85";
+				regulator-min-microvolt = <2850000>;
+				regulator-max-microvolt = <2850000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck9_reg: BUCK9 {
+				regulator-name = "buck9";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buck10_reg: BUCK10 {
+				regulator-name = "buck10";
+				regulator-min-microvolt = <2950000>;
+				regulator-max-microvolt = <2950000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			ldo1_reg: LDO1 {
+				regulator-name = "vdd_alive";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			ldo2_reg: LDO2 {
+				regulator-name = "vddq_m1_m2";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			ldo3_reg: LDO3 {
+				regulator-name = "vddq_gpio";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo4_reg: LDO4 {
+				regulator-name = "vddq_mmc2";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3000000>;
+				/* Having it off prevents reboot */
+				regulator-always-on;
+			};
+
+			ldo5_reg: LDO5 {
+				regulator-name = "vdd18_hsic";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo6_reg: LDO6 {
+				regulator-name = "vdd18_bpll";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo7_reg: LDO7 {
+				regulator-name = "vddq_lcd";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo8_reg: LDO8 {
+				regulator-name = "vdd10_hdmi";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			ldo9_reg: LDO9 {
+				regulator-name = "ldo9";
+			};
+
+			ldo10_reg: LDO10 {
+				regulator-name = "vdd18_mipi";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo11_reg: LDO11 {
+				regulator-name = "vddq_mmc01";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				/*
+				 * Having it off prevents accessing MMC after
+				 * reboot with error:
+				 * MMC Device 1: Clock OFF has been failed.
+				 */
+				regulator-always-on;
+			};
+
+			ldo12_reg: LDO12 {
+				regulator-name = "vdd33_usb3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			ldo13_reg: LDO13 {
+				regulator-name = "vddq_abbg0";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo14_reg: LDO14 {
+				regulator-name = "vddq_abbg1";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo15_reg: LDO15 {
+				regulator-name = "vdd10_usb3";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			ldo16_reg: LDO16 {
+				regulator-name = "ldo16";
+			};
+
+			ldo17_reg: LDO17 {
+				regulator-name = "cam_sensor_core";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+			};
+
+			ldo18_reg: LDO18 {
+				regulator-name = "ldo18";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo19_reg: LDO19 {
+				regulator-name = "ldo19";
+			};
+
+			ldo20_reg: LDO20 {
+				regulator-name = "vdd_mmc0";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo21_reg: LDO21 {
+				/* vdd_mmc2 */
+				regulator-name = "vddf_2v8";
+				regulator-min-microvolt = <2850000>;
+				regulator-max-microvolt = <2850000>;
+			};
+
+			ldo22_reg: LDO22 {
+				regulator-name = "ldo22";
+			};
+
+			ldo23_reg: LDO23 {
+				regulator-name = "dp_p3v3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			ldo24_reg: LDO24 {
+				regulator-name = "cam_af";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+			};
+
+			ldo25_reg: LDO25 {
+				regulator-name = "eth_p3v3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			ldo26_reg: LDO26 {
+				regulator-name = "usb30_extclk";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			ldo27_reg: LDO27 {
+				regulator-name = "ldo27";
+			};
+
+			ldo28_reg: LDO28 {
+				regulator-name = "ldo28";
+			};
+
+			ldo29_reg: LDO29 {
+				regulator-name = "ldo29";
+			};
+
+			ldo30_reg: LDO30 {
+				regulator-name = "vddq_e1_e2";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			ldo31_reg: LDO31 {
+				regulator-name = "ldo31";
+			};
+
+			/* On revisions with ti,ina231 this is sensor VS */
+			ldo32_reg: LDO32 {
+				regulator-name = "vs_power_meter";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			ldo33_reg: LDO33 {
+				regulator-name = "ldo33";
+			};
+
+			ldo34_reg: LDO34 {
+				regulator-name = "ldo34";
+			};
+
+			ldo35_reg: LDO35 {
+				regulator-name = "ldo35";
+			};
+		};
+	};
+};
+
 &mmc_0 {
 	status = "okay";
 	mmc-pwrseq = <&emmc_pwrseq>;
@@ -73,6 +455,8 @@
 	cap-mmc-highspeed;
 	mmc-hs200-1_8v;
 	mmc-hs400-1_8v;
+	vmmc-supply = <&ldo20_reg>;
+	vqmmc-supply = <&ldo11_reg>;
 };
 
 &mmc_2 {
@@ -85,17 +469,66 @@
 	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
 	bus-width = <4>;
 	cap-sd-highspeed;
+	vmmc-supply = <&ldo21_reg>;
+	vqmmc-supply = <&ldo4_reg>;
 };
 
 &pinctrl_0 {
 	emmc_nrst_pin: emmc-nrst {
 		samsung,pins = "gpd1-0";
-		samsung,pin-function = <0>;
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pmic_dvs_3: pmic-dvs-3 {
+		samsung,pins = "gpx0-0";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pmic_dvs_2: pmic-dvs-2 {
+		samsung,pins = "gpx0-1";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pmic_dvs_1: pmic-dvs-1 {
+		samsung,pins = "gpx0-2";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+		samsung,pin-val = <1>;
+	};
+
+	max77802_irq: max77802-irq {
+		samsung,pins = "gpx0-4";
+		samsung,pin-function = <0xf>;
 		samsung,pin-pud = <0>;
 		samsung,pin-drv = <0>;
 	};
 };
 
+&pwm {
+	/*
+	 * PWM 0 -- fan
+	 * PWM 1 -- Green LED
+	 * PWM 2 -- Blue LED
+	 * PWM 3 -- on MIPI connector for backlight
+	 */
+	pinctrl-0 = <&pwm0_out &pwm1_out &pwm2_out &pwm3_out>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&rtc {
+	status = "okay";
+	clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
+	clock-names = "rtc", "rtc_src";
+};
+
 &serial_0 {
 	status = "okay";
 };
@@ -112,6 +545,22 @@
 	status = "okay";
 };
 
+&tmu_cpu0 {
+	vtmu-supply = <&ldo10_reg>;
+};
+
+&tmu_cpu1 {
+	vtmu-supply = <&ldo10_reg>;
+};
+
+&tmu_cpu2 {
+	vtmu-supply = <&ldo10_reg>;
+};
+
+&tmu_cpu3 {
+	vtmu-supply = <&ldo10_reg>;
+};
+
 &usbdrd_dwc3_0 {
 	dr_mode = "host";
 };
@@ -119,3 +568,13 @@
 &usbdrd_dwc3_1 {
 	dr_mode = "peripheral";
 };
+
+&usbdrd3_0 {
+	vdd33-supply = <&ldo12_reg>;
+	vdd10-supply = <&ldo15_reg>;
+};
+
+&usbdrd3_1 {
+	vdd33-supply = <&ldo12_reg>;
+	vdd10-supply = <&ldo15_reg>;
+};
-- 
2.7.4



From krzk at kernel.org  Tue May 31 11:39:05 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 20:39:05 +0200
Subject: [PATCH 6/6] ARM: dts: exynos: No need to enable TMU nodes on Odroid
 XU3 family
In-Reply-To: <1464719945-3417-1-git-send-email-krzk@kernel.org>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
Message-ID: <1464719945-3417-6-git-send-email-krzk@kernel.org>

The thermal nodes are not disabled in exynos5420.dtsi so there is no
need to manually enable them on Odroid XU3/XU3-Lite/XU4 boards.

Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
---
 arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
index 20fa7612080d..c08392b9e0dd 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
@@ -388,27 +388,22 @@
 
 &tmu_cpu0 {
 	vtmu-supply = <&ldo7_reg>;
-	status = "okay";
 };
 
 &tmu_cpu1 {
 	vtmu-supply = <&ldo7_reg>;
-	status = "okay";
 };
 
 &tmu_cpu2 {
 	vtmu-supply = <&ldo7_reg>;
-	status = "okay";
 };
 
 &tmu_cpu3 {
 	vtmu-supply = <&ldo7_reg>;
-	status = "okay";
 };
 
 &tmu_gpu {
 	vtmu-supply = <&ldo7_reg>;
-	status = "okay";
 };
 
 &rtc {
-- 
2.7.4



From javier at osg.samsung.com  Tue May 31 11:53:13 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 31 May 2016 14:53:13 -0400
Subject: [PATCH 1/6] dt-bindings: clock: Add TMU clock ID to Exynos5410
In-Reply-To: <1464719945-3417-1-git-send-email-krzk@kernel.org>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
Message-ID: <6ee898e7-3dcd-bdd8-0929-b196e6c80b77@osg.samsung.com>

Hello Krzysztof,

On 05/31/2016 02:39 PM, Krzysztof Kozlowski wrote:
> Add ID for TMU clock to Exynos5410. Use the same number as for
> Exynos5420 just in case in future these drivers were merged.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Tue May 31 11:56:03 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 31 May 2016 14:56:03 -0400
Subject: [PATCH 2/6] clk: samsung: exynos5410: Add TMU clock
In-Reply-To: <1464719945-3417-2-git-send-email-krzk@kernel.org>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
 <1464719945-3417-2-git-send-email-krzk@kernel.org>
Message-ID: <8281b473-22c8-f87d-4282-45f93f61b937@osg.samsung.com>

Hello Krzysztof,

On 05/31/2016 02:39 PM, Krzysztof Kozlowski wrote:
> Add clock for TMU to the Exynos5410 clock driver.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---
>  drivers/clk/samsung/clk-exynos5410.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
> index 6c2e59c576ee..db9978dc6e83 100644
> --- a/drivers/clk/samsung/clk-exynos5410.c
> +++ b/drivers/clk/samsung/clk-exynos5410.c
> @@ -160,6 +160,7 @@ static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
>  static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
>  	GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
>  	GATE(CLK_RTC, "rtc", "aclk66", GATE_IP_PERIS, 20, 0, 0),
> +	GATE(CLK_TMU, "tmu", "aclk66", GATE_IP_PERIS, 21, 0, 0),
>  
>  	GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
>  			SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
> 

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From maxime.ripard at free-electrons.com  Tue May 31 12:01:13 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Tue, 31 May 2016 21:01:13 +0200
Subject: [PATCH resend v2 5/6] ARM: dts: sun9i: a80-optimus: Disable
 dummy regulators vcc3v0, vcc3v3, vcc5v0
In-Reply-To: <1464711804-19256-6-git-send-email-wens@csie.org>
References: <1464711804-19256-1-git-send-email-wens@csie.org>
 <1464711804-19256-6-git-send-email-wens@csie.org>
Message-ID: <20160531190113.GO4908@lukather>

Hi,

On Wed, Jun 01, 2016 at 12:23:23AM +0800, Chen-Yu Tsai wrote:
> These 3 regulators are provided in sunxi-common-regulators.dtsi.
> 3.0V/3.3V and 5.0V are commonly used voltages in Allwinner devices.
> These dummy regulators provide a stand-in when bindings that require
> one, but the real regulator is not supported yet.
> 
> Since these are no longer needed, we can disable them.
> 
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
> ---
>  arch/arm/boot/dts/sun9i-a80-optimus.dts | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts
> index 6cfc02194035..991337d1d6f1 100644
> --- a/arch/arm/boot/dts/sun9i-a80-optimus.dts
> +++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts
> @@ -322,6 +322,18 @@
>  
>  #include "axp809.dtsi"
>  
> +&reg_vcc3v0 {
> +	status = "disabled";
> +};
> +
> +&reg_vcc3v3 {
> +	status = "disabled";
> +};
> +
> +&reg_vcc5v0 {
> +	status = "disabled";
> +};
> +

Why not remove the include entirely?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160531/ea5464ad/attachment.sig>

From javier at osg.samsung.com  Tue May 31 12:01:24 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 31 May 2016 15:01:24 -0400
Subject: [PATCH 3/6] ARM: dts: exynos: Interrupt for USB DWC3-1 differs
 between Exynos5420 and 5410
In-Reply-To: <1464719945-3417-3-git-send-email-krzk@kernel.org>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
 <1464719945-3417-3-git-send-email-krzk@kernel.org>
Message-ID: <fca224e1-af8c-5540-d47a-9f05e494b2c4@osg.samsung.com>

Hello Krzysztof,

On 05/31/2016 02:39 PM, Krzysztof Kozlowski wrote:
> On Exynos5410 the SPI interrupt for second USB DWC3 (called DRD: Dual
> Role Device) is different - 200 instead of 73.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---
>  arch/arm/boot/dts/exynos5410.dtsi | 4 ++++
>  arch/arm/boot/dts/exynos5420.dtsi | 4 ++++
>  arch/arm/boot/dts/exynos54xx.dtsi | 1 -
>  3 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
> index a937d9bdad90..994d16a44fe4 100644
> --- a/arch/arm/boot/dts/exynos5410.dtsi
> +++ b/arch/arm/boot/dts/exynos5410.dtsi
> @@ -267,6 +267,10 @@
>  	clock-names = "usbdrd30";
>  };
>  
> +&usbdrd_dwc3_1 {
> +	interrupts = <0 200 0>;

Please use GIC_SPI from <dt-bindings/interrupt-controller/arm-gic.h> instead 0.

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From maxime.ripard at free-electrons.com  Tue May 31 12:02:07 2016
From: maxime.ripard at free-electrons.com (Maxime Ripard)
Date: Tue, 31 May 2016 21:02:07 +0200
Subject: [PATCH resend v2 0/6] regulator: axp20x: Add support for AXP809
 PMIC
In-Reply-To: <1464711804-19256-1-git-send-email-wens@csie.org>
References: <1464711804-19256-1-git-send-email-wens@csie.org>
Message-ID: <20160531190207.GP4908@lukather>

On Wed, Jun 01, 2016 at 12:23:18AM +0800, Chen-Yu Tsai wrote:
> Hi everyone,
> 
> These are the remaining patches of my AXP809 PMIC support series. The
> mfd parts and regulator fixes were merged in v4.7-rc1. What's left are
> the AXP809 regulator driver and dts changes.
> 
> Patch 1 adds AXP809 support to the axp20x regulator driver. This patch
> depends on patch 3, and patches already in regulator/topic/axp20x.
> 
> Patch 2 adds a dtsi file for AXP809.
> 
> Patch 3 enables AXP809 support on the A80 Optimus board.
> 
> Patch 4 enables AXP809 support on the Cubieboard 4.

Merged the last 3

> 
> Patch 5 disables the dummy regulators from sunxi-common-regulators.dtsi
> on the A80 Optimus board. These aren't used in the board DTS anymore.
> 
> Patch 6 disables the dummy regulators from sunxi-common-regulators.dtsi,
> on the Cubieboard4. These aren't used in the board DTS anymore.

And we should just remove the include on his one.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160531/a71a6c72/attachment.sig>

From javier at osg.samsung.com  Tue May 31 12:21:06 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 31 May 2016 15:21:06 -0400
Subject: [PATCH 4/6] ARM: dts: exynos: Add Thermal Management Unit to
 Exynos5410
In-Reply-To: <1464719945-3417-4-git-send-email-krzk@kernel.org>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
 <1464719945-3417-4-git-send-email-krzk@kernel.org>
Message-ID: <25549eaa-a286-7579-8407-411f0c1834ae@osg.samsung.com>

Hello Krzysztof,

On 05/31/2016 02:39 PM, Krzysztof Kozlowski wrote:
> Add nodes for Thermal Management Unit to exynos5410.dtsi. Use the same
> compatible as for Exynos5420 however without second base for TRIMINFO
> register.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---
>  arch/arm/boot/dts/exynos5410.dtsi | 55 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 55 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
> index 994d16a44fe4..f1effd3f03c4 100644
> --- a/arch/arm/boot/dts/exynos5410.dtsi
> +++ b/arch/arm/boot/dts/exynos5410.dtsi
> @@ -81,6 +81,42 @@
>  			#clock-cells = <1>;
>  		};
>  
> +		tmu_cpu0: tmu at 10060000 {
> +			compatible = "samsung,exynos5420-tmu";
> +			reg = <0x10060000 0x100>;
> +			interrupts = <0 65 0>;

Please use GIC_SPI instead of 0 on these.

> +			clocks = <&clock CLK_TMU>;
> +			clock-names = "tmu_apbif";
> +			#include "exynos4412-tmu-sensor-conf.dtsi"
> +		};
> +
> +		tmu_cpu1: tmu at 10064000 {
> +			compatible = "samsung,exynos5420-tmu";
> +			reg = <0x10064000 0x100>;
> +			interrupts = <0 183 0>;
> +			clocks = <&clock CLK_TMU>;
> +			clock-names = "tmu_apbif";
> +			#include "exynos4412-tmu-sensor-conf.dtsi"
> +		};
> +
> +		tmu_cpu2: tmu at 10068000 {
> +			compatible = "samsung,exynos5420-tmu";
> +			reg = <0x10068000 0x100>;
> +			interrupts = <0 184 0>;
> +			clocks = <&clock CLK_TMU>;
> +			clock-names = "tmu_apbif";
> +			#include "exynos4412-tmu-sensor-conf.dtsi"
> +		};
> +
> +		tmu_cpu3: tmu at 1006c000 {
> +			compatible = "samsung,exynos5420-tmu";
> +			reg = <0x1006c000 0x100>;
> +			interrupts = <0 185 0>;
> +			clocks = <&clock CLK_TMU>;
> +			clock-names = "tmu_apbif";
> +			#include "exynos4412-tmu-sensor-conf.dtsi"
> +		};
> +

Exynos5420 has 5 TMU channels and you are adding only 4 so I guess this
is another difference with Exynos5410 besides the TRIMINFO register not
being misplaced? Probably is worth to mention it in the commit message.

Anyway, the patch looks good to me.

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From krzk at kernel.org  Tue May 31 12:26:43 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 21:26:43 +0200
Subject: [PATCH 3/6] ARM: dts: exynos: Interrupt for USB DWC3-1 differs
 between Exynos5420 and 5410
In-Reply-To: <fca224e1-af8c-5540-d47a-9f05e494b2c4@osg.samsung.com>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
 <1464719945-3417-3-git-send-email-krzk@kernel.org>
 <fca224e1-af8c-5540-d47a-9f05e494b2c4@osg.samsung.com>
Message-ID: <CAJKOXPf204zCUaWm48TbGhPiehpxjQ6F-F-tc+ZtYOesmoaPww@mail.gmail.com>

On Tue, May 31, 2016 at 9:01 PM, Javier Martinez Canillas
<javier at osg.samsung.com> wrote:
> Hello Krzysztof,
>
> On 05/31/2016 02:39 PM, Krzysztof Kozlowski wrote:
>> On Exynos5410 the SPI interrupt for second USB DWC3 (called DRD: Dual
>> Role Device) is different - 200 instead of 73.
>>
>> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
>> ---
>>  arch/arm/boot/dts/exynos5410.dtsi | 4 ++++
>>  arch/arm/boot/dts/exynos5420.dtsi | 4 ++++
>>  arch/arm/boot/dts/exynos54xx.dtsi | 1 -
>>  3 files changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
>> index a937d9bdad90..994d16a44fe4 100644
>> --- a/arch/arm/boot/dts/exynos5410.dtsi
>> +++ b/arch/arm/boot/dts/exynos5410.dtsi
>> @@ -267,6 +267,10 @@
>>       clock-names = "usbdrd30";
>>  };
>>
>> +&usbdrd_dwc3_1 {
>> +     interrupts = <0 200 0>;
>
> Please use GIC_SPI from <dt-bindings/interrupt-controller/arm-gic.h> instead 0.
>
> Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Sure, thanks for feedback.

Krzysztof


From krzk at kernel.org  Tue May 31 12:28:18 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 21:28:18 +0200
Subject: [PATCH 4/6] ARM: dts: exynos: Add Thermal Management Unit to
 Exynos5410
In-Reply-To: <25549eaa-a286-7579-8407-411f0c1834ae@osg.samsung.com>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
 <1464719945-3417-4-git-send-email-krzk@kernel.org>
 <25549eaa-a286-7579-8407-411f0c1834ae@osg.samsung.com>
Message-ID: <CAJKOXPeDw4BQm8HU0Pe1f1=5C8kHa_ZXGbYZR=o7Ah0mZX1H=Q@mail.gmail.com>

On Tue, May 31, 2016 at 9:21 PM, Javier Martinez Canillas
<javier at osg.samsung.com> wrote:
> Hello Krzysztof,
>
> On 05/31/2016 02:39 PM, Krzysztof Kozlowski wrote:
>> Add nodes for Thermal Management Unit to exynos5410.dtsi. Use the same
>> compatible as for Exynos5420 however without second base for TRIMINFO
>> register.
>>
>> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
>> ---
>>  arch/arm/boot/dts/exynos5410.dtsi | 55 +++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 55 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
>> index 994d16a44fe4..f1effd3f03c4 100644
>> --- a/arch/arm/boot/dts/exynos5410.dtsi
>> +++ b/arch/arm/boot/dts/exynos5410.dtsi
>> @@ -81,6 +81,42 @@
>>                       #clock-cells = <1>;
>>               };
>>
>> +             tmu_cpu0: tmu at 10060000 {
>> +                     compatible = "samsung,exynos5420-tmu";
>> +                     reg = <0x10060000 0x100>;
>> +                     interrupts = <0 65 0>;
>
> Please use GIC_SPI instead of 0 on these.

ok

>
>> +                     clocks = <&clock CLK_TMU>;
>> +                     clock-names = "tmu_apbif";
>> +                     #include "exynos4412-tmu-sensor-conf.dtsi"
>> +             };
>> +
>> +             tmu_cpu1: tmu at 10064000 {
>> +                     compatible = "samsung,exynos5420-tmu";
>> +                     reg = <0x10064000 0x100>;
>> +                     interrupts = <0 183 0>;
>> +                     clocks = <&clock CLK_TMU>;
>> +                     clock-names = "tmu_apbif";
>> +                     #include "exynos4412-tmu-sensor-conf.dtsi"
>> +             };
>> +
>> +             tmu_cpu2: tmu at 10068000 {
>> +                     compatible = "samsung,exynos5420-tmu";
>> +                     reg = <0x10068000 0x100>;
>> +                     interrupts = <0 184 0>;
>> +                     clocks = <&clock CLK_TMU>;
>> +                     clock-names = "tmu_apbif";
>> +                     #include "exynos4412-tmu-sensor-conf.dtsi"
>> +             };
>> +
>> +             tmu_cpu3: tmu at 1006c000 {
>> +                     compatible = "samsung,exynos5420-tmu";
>> +                     reg = <0x1006c000 0x100>;
>> +                     interrupts = <0 185 0>;
>> +                     clocks = <&clock CLK_TMU>;
>> +                     clock-names = "tmu_apbif";
>> +                     #include "exynos4412-tmu-sensor-conf.dtsi"
>> +             };
>> +
>
> Exynos5420 has 5 TMU channels and you are adding only 4 so I guess this
> is another difference with Exynos5410 besides the TRIMINFO register not
> being misplaced? Probably is worth to mention it in the commit message.


Yes, indeed there is no GPU thermal zone. I'll mention it.

Best regards,
Krzysztof


From javier at osg.samsung.com  Tue May 31 12:36:04 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 31 May 2016 15:36:04 -0400
Subject: [PATCH 5/6] ARM: dts: exynos: Configure PWM, usb3503, PMIC and
 thermal on Odroid XU board
In-Reply-To: <1464719945-3417-5-git-send-email-krzk@kernel.org>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
 <1464719945-3417-5-git-send-email-krzk@kernel.org>
Message-ID: <1ec0f7fc-f6e0-e4d6-e424-43289bf31b16@osg.samsung.com>

Hello Krzysztof,

On 05/31/2016 02:39 PM, Krzysztof Kozlowski wrote:
> Extend the DTS for Exynos5410-based Odroid XU board with:
> 1. Proper PWM outputs,
> 2. usb3503 USB HUB (with integrated LAN9730 ethernet adapter (smsc95xx)),
> 3. Maxim 77802 PMIC (regulators, 32 kHz clocks, RTC),
> 4. CPU thermal (trip points are the same as in Odroid XU3/XU4 but
>    cooling maps are different as there is no CPU freq and only one
>    cluster available for now),
> 5. Regulator supplies for USB 3.0.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> 
> ---
> 

[snip]

> +
> +			ldo10_reg: LDO10 {
> +				regulator-name = "vdd18_mipi";
> +				regulator-min-microvolt = <1800000>;
> +				regulator-max-microvolt = <1800000>;
> +				regulator-always-on;
> +			};
> +

[snip]

> +
> +			ldo12_reg: LDO12 {
> +				regulator-name = "vdd33_usb3";
> +				regulator-min-microvolt = <3300000>;
> +				regulator-max-microvolt = <3300000>;
> +				regulator-always-on;
> +			};
> +

[snip]

> +
> +			ldo15_reg: LDO15 {
> +				regulator-name = "vdd10_usb3";
> +				regulator-min-microvolt = <1000000>;
> +				regulator-max-microvolt = <1000000>;
> +				regulator-always-on;
> +			};
> +

I see that LDO 10, 12 and 15 are used by still marked as always-on. Did
you try not marking as always-on those or that also causes issues like
in the other regulators were you added comments about being always-on?

Besides that, patch looks good to me.

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From javier at osg.samsung.com  Tue May 31 12:37:28 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 31 May 2016 15:37:28 -0400
Subject: [PATCH 6/6] ARM: dts: exynos: No need to enable TMU nodes on
 Odroid XU3 family
In-Reply-To: <1464719945-3417-6-git-send-email-krzk@kernel.org>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
 <1464719945-3417-6-git-send-email-krzk@kernel.org>
Message-ID: <c3222e0a-51a9-a93f-97e4-9a12e17167de@osg.samsung.com>

Hello Krzysztof,

On 05/31/2016 02:39 PM, Krzysztof Kozlowski wrote:
> The thermal nodes are not disabled in exynos5420.dtsi so there is no
> need to manually enable them on Odroid XU3/XU3-Lite/XU4 boards.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
> ---

Reviewed-by: Javier Martinez Canillas <javier at osg.samsung.com>

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From eric at anholt.net  Tue May 31 12:52:22 2016
From: eric at anholt.net (Eric Anholt)
Date: Tue, 31 May 2016 12:52:22 -0700
Subject: [PATCH V3 2/5] thermal: bcm2835: add thermal driver for bcm2835
 soc
In-Reply-To: <1463495753-967-3-git-send-email-kernel@martin.sperl.org>
References: <1463495753-967-1-git-send-email-kernel@martin.sperl.org>
 <1463495753-967-3-git-send-email-kernel@martin.sperl.org>
Message-ID: <87mvn6qa2x.fsf@eliezer.anholt.net>

kernel at martin.sperl.org writes:

> From: Martin Sperl <kernel at martin.sperl.org>
>
> Add basic thermal driver for bcm2835 SOC.
>
> This driver currently relies on the firmware setting up the
> tsense HW block and does not set it up itself.
>
> Signed-off-by: Martin Sperl <kernel at martin.sperl.org>
>
> ChangeLog:
>  V1 -> V2: added specific settings depending on compatiblity
> 	   added trip point based on register
> 	   setting up ctrl-register if HW is not enabled by firmware
> 	     as per recommendation of Eric (untested)
> 	   check that clock frequency is in range
> 	     (1.9 - 5MHz - as per comment in clk-bcm2835.c)
> ---

> diff --git a/drivers/thermal/bcm/Makefile b/drivers/thermal/bcm/Makefile
> new file mode 100644
> index 0000000..13456d2
> --- /dev/null
> +++ b/drivers/thermal/bcm/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_BCM2835_THERMAL)		:= bcm2835_thermal.o
> diff --git a/drivers/thermal/bcm/bcm2835_thermal.c b/drivers/thermal/bcm/bcm2835_thermal.c
> new file mode 100644
> index 0000000..73138cb
> --- /dev/null
> +++ b/drivers/thermal/bcm/bcm2835_thermal.c

> +static const struct of_device_id bcm2835_thermal_of_match_table[];
> +static int bcm2835_thermal_probe(struct platform_device *pdev)
> +{

> +	/* enable clock and check rate */
> +	clk_prepare_enable(data->clk);
> +	rate = clk_get_rate(data->clk);
> +	if ((rate < 1920000) || (rate > 5000000)) {
> +		dev_warn(&pdev->dev,
> +			 "Clock %pCn is running at %pCr Hz, which is outside the recommended range of 1.9 to 5.0 MHz\n",
> +			 data->clk, data->clk);
> +	}
> +
> +	/* register it */
> +	tz = thermal_zone_device_register("bcm2835_thermal",
> +					  1, 0, data,
> +					  &bcm2835_thermal_ops,
> +					  NULL, 0, 0);

I notice that the polling_delay is set to 0, but we're not using
interrupts to trigger the trip.  Is it valid to expose a trip without a
polling_delay or interrupts?  Should passive_delay be set as well?

This is up to the thermal maintainers.  As far as I'm concerned, it's:

Acked-by: Eric Anholt <eric at anholt.net>

One it lands I'll pull the defconfig and DT bits.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160531/fdfb9eec/attachment.sig>

From dianders at chromium.org  Tue May 31 12:57:17 2016
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 31 May 2016 12:57:17 -0700
Subject: [PATCH 2/6] Documentation: bindings: add dt doc for Rockchip USB
 Type-C PHY
In-Reply-To: <5748094F.6030204@rock-chips.com>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
 <1464328939-8073-3-git-send-email-zyw@rock-chips.com>
 <2812026.ptEv4ktvbn@phil> <5748094F.6030204@rock-chips.com>
Message-ID: <CAD=FV=W9iFXX_BfORP-9=8tnu9Ea_f2k1wK_T2j=ZAVA9cFSwg@mail.gmail.com>

Chris,

On Fri, May 27, 2016 at 1:46 AM, Chris Zhong <zyw at rock-chips.com> wrote:
> Hi Heiko
>
>
> On 05/27/2016 04:29 PM, Heiko Stuebner wrote:
>>
>> Hi Chris,
>>
>> Am Freitag, 27. Mai 2016, 14:02:15 schrieb Chris Zhong:
>>>
>>> This patch adds a binding that describes the Rockchip USB Type-C PHY
>>> for rk3399.
>>>
>>> Signed-off-by: Chris Zhong <zyw at rock-chips.com>
>>> ---
>>>
>>>   .../devicetree/bindings/phy/phy-rockchip-typec.txt | 55
>>> ++++++++++++++++++++++ 1 file changed, 55 insertions(+)
>>>   create mode 100644
>>> Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
>>>
>>> diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
>>> b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt new file
>>> mode 100644
>>> index 0000000..402f667
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
>>> @@ -0,0 +1,55 @@
>>> +ROCKCHIP type-c PHY
>>> +
>>> +Required properties:
>>> + - compatible: should be "rockchip,rk3399-typec-phy"
>>> + - reg : Address and length of the usb phy control register set
>>> + - rockchip,grf : phandle to the syscon managing the "general
>>> +   register files"
>>> + - clocks : phandle + clock specifier for the phy clocks
>>> + - clock-names: string, clock name, must be "tcpdcore", "tcpdphy_ref";
>>> + - resets : a list of phandle + reset specifier pairs
>>> + - reset-names : string reset name, must be:
>>> +                "tcphy_rst", "tcphy_pipe_rst", "uphy_tcphy_rst"

In other contexts I believe Heiko has requested that a suffix like
"_rst" not be present in the names of reset signals.  We already know
that this is a list of reset names so the "_rst" is redundant.

>>> + - #phy-cells: Must be 0.  See ./phy-bindings.txt for details.
>>> + - rockchip,usb3phy*: phy registers embed in grf
>>> +
>>> +Example:
>>> +       tcphy0: phy at ff7c0000 {
>>> +               compatible = "rockchip,rk3399-typec-phy";
>>> +               reg = <0x0 0xff7c0000 0x0 0x40000>;
>>> +               #phy-cells = <0>;
>>> +               rockchip,grf = <&grf>;
>>> +               clocks = <&cru SCLK_UPHY0_TCPDCORE>,
>>> +                        <&cru SCLK_UPHY0_TCPDPHY_REF>;
>>> +               clock-names = "tcpdcore", "tcpdphy_ref";
>>> +               resets = <&cru SRST_UPHY0>,
>>> +                        <&cru SRST_UPHY0_PIPE_L00>,
>>> +                        <&cru SRST_P_UPHY0_TCPHY>;
>>> +               reset-names = "tcphy_rst", "tcphy_pipe_rst",
>>> "uphy_tcphy_rst";
>>> +               rockchip,usb3phy_con0 = <0x0e580 0 16>;
>>> +               rockchip,usb3phy_con1 = <0x0e584 0 16>;
>>> +               rockchip,usb3phy_con2 = <0x0e588 0 16>;
>>> +               rockchip,usb3phy_status0 = <0x0e5c0 0 13>;
>>> +               rockchip,usb3phy_status1 = <0x0e5c4 0 12>;
>>
>> please embedded this register data in the driver instead (not in the
>> devicetree), matched against the compatible value.
>> See Frank's usb2phy driver for reference if needed.
>
> Okay, I will move them to driver file next version, Thanks.

Just making sure: I saw a RESEND of your original version get posted,
but nothing that addresses Heiko's comments, right?

Also: note that bindings should be sent in the patch _before_ the
code.  So instead of:
  [1] phy: Add USB Type-C PHY driver for rk3399
  [2] Documentation: bindings: add dt doc for Rockchip USB Type-C PHY
  [3] drm/rockchip: vop: add cdn DP support for rk3399
  [4] Documentation: bindings: add dt documentation for cdn DP controller

You should have:
  [1] Documentation: bindings: add dt doc for Rockchip USB Type-C PHY
  [2] phy: Add USB Type-C PHY driver for rk3399
  [3] Documentation: bindings: add dt documentation for cdn DP controller
  [4] drm/rockchip: vop: add cdn DP support for rk3399


-Doug


From matthias.bgg at gmail.com  Tue May 31 13:04:16 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Tue, 31 May 2016 22:04:16 +0200
Subject: [PATCH v8 2/3] CMDQ: Mediatek CMDQ driver
In-Reply-To: <1464683762.14604.59.camel@mtksdaap41>
References: <1464578397-29743-1-git-send-email-hs.liao@mediatek.com>
 <1464578397-29743-3-git-send-email-hs.liao@mediatek.com>
 <574C5CBF.7060002@gmail.com> <1464683762.14604.59.camel@mtksdaap41>
Message-ID: <574DEE40.9010008@gmail.com>



On 31/05/16 10:36, Horng-Shyang Liao wrote:
> Hi Mathias,
>
> Please see my inline reply.
>
> On Mon, 2016-05-30 at 17:31 +0200, Matthias Brugger wrote:
>>
>> On 30/05/16 05:19, HS Liao wrote:
>>> This patch is first version of Mediatek Command Queue(CMDQ) driver. The
>>> CMDQ is used to help read/write registers with critical time limitation,
>>> such as updating display configuration during the vblank. It controls
>>> Global Command Engine (GCE) hardware to achieve this requirement.
>>> Currently, CMDQ only supports display related hardwares, but we expect
>>> it can be extended to other hardwares for future requirements.
>>>
>>> Signed-off-by: HS Liao <hs.liao at mediatek.com>
>>> Signed-off-by: CK Hu <ck.hu at mediatek.com>
>>> ---
>>>    drivers/soc/mediatek/Kconfig    |  10 +
>>>    drivers/soc/mediatek/Makefile   |   1 +
>>>    drivers/soc/mediatek/mtk-cmdq.c | 943 ++++++++++++++++++++++++++++++++++++++++
>>>    include/soc/mediatek/cmdq.h     | 197 +++++++++
>>>    4 files changed, 1151 insertions(+)
>>>    create mode 100644 drivers/soc/mediatek/mtk-cmdq.c
>>>    create mode 100644 include/soc/mediatek/cmdq.h
>>>
>>> diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
>>> index 0a4ea80..c4ad75c 100644
>>> --- a/drivers/soc/mediatek/Kconfig
>>> +++ b/drivers/soc/mediatek/Kconfig
>>> @@ -1,6 +1,16 @@
>>>    #
>>>    # MediaTek SoC drivers
>>>    #
>>> +config MTK_CMDQ
>>> +	bool "MediaTek CMDQ Support"
>>> +	depends on ARCH_MEDIATEK || COMPILE_TEST

depends on ARM64 ?

>>> +	select MTK_INFRACFG
>>> +	help
>>> +	  Say yes here to add support for the MediaTek Command Queue (CMDQ)
>>> +	  driver. The CMDQ is used to help read/write registers with critical
>>> +	  time limitation, such as updating display configuration during the
>>> +	  vblank.
>>> +
>>>    config MTK_INFRACFG
>>>    	bool "MediaTek INFRACFG Support"
>>>    	depends on ARCH_MEDIATEK || COMPILE_TEST
>>> diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
>>> index 12998b0..f7397ef 100644
>>> --- a/drivers/soc/mediatek/Makefile
>>> +++ b/drivers/soc/mediatek/Makefile
>>> @@ -1,3 +1,4 @@
>>> +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq.o
>>>    obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
>>>    obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
>>>    obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
>>> diff --git a/drivers/soc/mediatek/mtk-cmdq.c b/drivers/soc/mediatek/mtk-cmdq.c
>>> new file mode 100644
>>> index 0000000..e9d6e1c
>>> --- /dev/null
>>> +++ b/drivers/soc/mediatek/mtk-cmdq.c
>>> @@ -0,0 +1,943 @@
>>> +/*
>>> + * Copyright (c) 2015 MediaTek Inc.
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + */
>>> +
>>> +#include <linux/clk.h>
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/completion.h>
>>> +#include <linux/dma-mapping.h>
>>> +#include <linux/errno.h>
>>> +#include <linux/interrupt.h>
>>> +#include <linux/iopoll.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/kthread.h>
>>> +#include <linux/module.h>
>>> +#include <linux/mutex.h>
>>> +#include <linux/of_address.h>
>>> +#include <linux/of_irq.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/spinlock.h>
>>> +#include <linux/suspend.h>
>>> +#include <linux/workqueue.h>
>>> +#include <soc/mediatek/cmdq.h>
>>> +
>>> +#define CMDQ_INITIAL_CMD_BLOCK_SIZE	PAGE_SIZE
>>> +#define CMDQ_INST_SIZE			8 /* instruction is 64-bit */
>>> +#define CMDQ_TIMEOUT_MS			1000
>>> +#define CMDQ_IRQ_MASK			0xffff
>>> +#define CMDQ_DRIVER_DEVICE_NAME		"mtk_cmdq"
>>> +#define CMDQ_CLK_NAME			"gce"
>>
>> We can put the names in directly to un-bloat the defines.
>
> I will use the names directly and remove defines.
>
>>> +
>>> +#define CMDQ_CURR_IRQ_STATUS		0x010
>>> +#define CMDQ_CURR_LOADED_THR		0x018
>>> +#define CMDQ_THR_SLOT_CYCLES		0x030
>>> +
>>> +#define CMDQ_THR_BASE			0x100
>>> +#define CMDQ_THR_SHIFT			0x080
>>
>> Wouldn't be CMDQ_THR_SIZE more accurate?
>
> Will rename it.
>
>>> +#define CMDQ_THR_WARM_RESET		0x00
>>> +#define CMDQ_THR_ENABLE_TASK		0x04
>>> +#define CMDQ_THR_SUSPEND_TASK		0x08
>>> +#define CMDQ_THR_CURR_STATUS		0x0c
>>> +#define CMDQ_THR_IRQ_STATUS		0x10
>>> +#define CMDQ_THR_IRQ_ENABLE		0x14
>>> +#define CMDQ_THR_CURR_ADDR		0x20
>>> +#define CMDQ_THR_END_ADDR		0x24
>>> +#define CMDQ_THR_CFG			0x40
>>> +
>>> +#define CMDQ_THR_ENABLED		0x1
>>> +#define CMDQ_THR_DISABLED		0x0
>>> +#define CMDQ_THR_SUSPEND		0x1
>>> +#define CMDQ_THR_RESUME			0x0
>>> +#define CMDQ_THR_STATUS_SUSPENDED	BIT(1)
>>> +#define CMDQ_THR_DO_WARM_RESET		BIT(0)
>>> +#define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
>>> +#define CMDQ_THR_PRIORITY		3
>>> +#define CMDQ_THR_IRQ_DONE		0x1
>>> +#define CMDQ_THR_IRQ_ERROR		0x12
>>> +#define CMDQ_THR_IRQ_EN			0x13 /* done + error */
>>
>> #define CMDQ_THR_IRQ_EN (CMDQ_THR_IRQ_ERROR | CMDQ_THR_IRQ_DONE)
>
> Will do.
>
>>> +#define CMDQ_THR_IRQ_MASK		0x13
>>
>> never used.
>
> Will remove.
>
>>> +#define CMDQ_THR_EXECUTING		BIT(31)
>>> +
>>> +#define CMDQ_ARG_A_WRITE_MASK		0xffff
>>> +#define CMDQ_SUBSYS_MASK		0x1f
>>> +#define CMDQ_OP_CODE_MASK		0xff000000
>>> +
>>> +#define CMDQ_OP_CODE_SHIFT		24
>>
>> Couldn't we connect the mask with the shift, or aren't they related?
>>
>> #define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT)
>
> Will do.
>
>>> +#define CMDQ_SUBSYS_SHIFT		16
>>> +
>>> +#define CMDQ_WRITE_ENABLE_MASK		BIT(0)
>>> +#define CMDQ_JUMP_BY_OFFSET		0x10000000
>>> +#define CMDQ_JUMP_BY_PA			0x10000001
>>> +#define CMDQ_JUMP_PASS			CMDQ_INST_SIZE
>>> +#define CMDQ_WFE_UPDATE			BIT(31)
>>> +#define CMDQ_WFE_WAIT			BIT(15)
>>> +#define CMDQ_WFE_WAIT_VALUE		0x1
>>> +#define CMDQ_EOC_IRQ_EN			BIT(0)
>>> +
>>> +enum cmdq_thread_index {
>>> +	CMDQ_THR_DISP_MAIN_IDX,	/* main */
>>> +	CMDQ_THR_DISP_SUB_IDX,	/* sub */
>>> +	CMDQ_THR_DISP_MISC_IDX,	/* misc */
>>> +	CMDQ_THR_MAX_COUNT,	/* max */
>>> +};
>>> +
>>> +/*
>>> + * CMDQ_CODE_MOVE:
>>> + *   move value into internal register as mask
>>> + *   format: op mask
>>> + * CMDQ_CODE_WRITE:
>>> + *   write value into target register
>>> + *   format: op subsys address value
>>> + * CMDQ_CODE_JUMP:
>>> + *   jump by offset
>>> + *   format: op offset
>>> + * CMDQ_CODE_WFE:
>>> + *   wait for event and clear
>>> + *   it is just clear if no wait
>>> + *   format: [wait]  op event update:1 to_wait:1 wait:1
>>> + *           [clear] op event update:1 to_wait:0 wait:0
>>> + * CMDQ_CODE_EOC:
>>> + *   end of command
>>> + *   format: op irq_flag
>>> + */
>>
>> I think we need more documentation of how this command queue engine is
>> working. If not, I think it will be really complicated to understand how
>> to use this.
>>
>>> +enum cmdq_code {
>>> +	CMDQ_CODE_MOVE = 0x02,
>>> +	CMDQ_CODE_WRITE = 0x04,
>>> +	CMDQ_CODE_JUMP = 0x10,
>>> +	CMDQ_CODE_WFE = 0x20,
>>> +	CMDQ_CODE_EOC = 0x40,
>>> +};
>>> +
>>> +enum cmdq_task_state {
>>> +	TASK_STATE_BUSY, /* running on a GCE thread */
>>> +	TASK_STATE_ERROR,
>>> +	TASK_STATE_DONE,
>>> +};
>>> +
>>> +struct cmdq_task_cb {
>>> +	cmdq_async_flush_cb	cb;
>>> +	void			*data;
>>> +};
>>> +
>>> +struct cmdq_thread {
>>> +	void __iomem		*base;
>>> +	struct list_head	task_busy_list;
>>> +	wait_queue_head_t	wait_task_done;
>>> +};
>>> +
>>> +struct cmdq_task {
>>> +	struct cmdq		*cmdq;
>>> +	struct list_head	list_entry;
>>> +	enum cmdq_task_state	task_state;
>>> +	void			*va_base;
>>> +	dma_addr_t		pa_base;
>>> +	u64			engine_flag;
>>> +	size_t			command_size;
>>> +	u32			num_cmd;
>>
>> num_cmd is directly connected to command_size. I prefer to just keep
>> num_cmd and calculate the command_size where necessary.
>
> After I trace code, I prefer to keep command_size and calculate num_cmd
> where necessary. What do you think?
>

I suppose you prefer this, as you are writing to the GCE depending on 
the command_size. I think it is worth to create a macro for the 
calculation of the number of commands, to make the code more readable.
Would be nice if you would just pass cmdq_task to it and it would return 
the number. Just as an idea.

>>> +	struct cmdq_thread	*thread;
>>> +	struct cmdq_task_cb	cb;
>>> +	struct work_struct	release_work;
>>> +};
>>> +
>>> +struct cmdq {
>>> +	struct device		*dev;
>>> +	void __iomem		*base;
>>> +	u32			irq;
>>> +	struct workqueue_struct	*task_release_wq;
>>> +	struct cmdq_thread	thread[CMDQ_THR_MAX_COUNT];
>>> +	struct mutex		task_mutex;	/* for task */
>>> +	spinlock_t		exec_lock;	/* for exec */
>>> +	struct clk		*clock;
>>> +	bool			suspended;
>>> +};
>>> +
>>> +struct cmdq_subsys {
>>> +	u32	base;
>>> +	int	id;
>>> +};
>>> +
>>> +static const struct cmdq_subsys gce_subsys[] = {
>>> +	{0x1400, 1},
>>> +	{0x1401, 2},
>>> +	{0x1402, 3},
>>> +};
>>> +
>>> +static int cmdq_subsys_base_to_id(u32 base)
>>> +{
>>> +	int i;
>>> +
>>> +	for (i = 0; i < ARRAY_SIZE(gce_subsys); i++)
>>> +		if (gce_subsys[i].base == base)
>>> +			return gce_subsys[i].id;
>>> +	return -EFAULT;
>>> +}
>>> +
>>> +static int cmdq_eng_get_thread(u64 flag)
>>> +{
>>> +	if (flag & BIT_ULL(CMDQ_ENG_DISP_DSI0))
>>> +		return CMDQ_THR_DISP_MAIN_IDX;
>>> +	else if (flag & BIT_ULL(CMDQ_ENG_DISP_DPI0))
>>> +		return CMDQ_THR_DISP_SUB_IDX;
>>> +	else
>>> +		return CMDQ_THR_DISP_MISC_IDX;
>>> +}
>>> +
>>> +static void cmdq_task_release(struct cmdq_task *task)
>>> +{
>>> +	struct cmdq *cmdq = task->cmdq;
>>> +
>>> +	dma_free_coherent(cmdq->dev, task->command_size, task->va_base,
>>> +			  task->pa_base);
>>> +	kfree(task);
>>> +}
>>> +
>>> +static struct cmdq_task *cmdq_task_acquire(struct cmdq_rec *rec,
>>> +					   struct cmdq_task_cb cb)
>>> +{
>>> +	struct cmdq *cmdq = rec->cmdq;
>>> +	struct device *dev = cmdq->dev;
>>> +	struct cmdq_task *task;
>>> +
>>> +	task = kzalloc(sizeof(*task), GFP_KERNEL);
>>> +	INIT_LIST_HEAD(&task->list_entry);
>>> +	task->va_base = dma_alloc_coherent(dev, rec->command_size,
>>> +					   &task->pa_base, GFP_KERNEL);
>>> +	if (!task->va_base) {
>>> +		dev_err(dev, "allocate command buffer failed\n");
>>> +		kfree(task);
>>> +		return NULL;
>>> +	}
>>> +
>>> +	task->cmdq = cmdq;
>>> +	task->command_size = rec->command_size;
>>> +	task->engine_flag = rec->engine_flag;
>>> +	task->task_state = TASK_STATE_BUSY;
>>> +	task->cb = cb;
>>> +	memcpy(task->va_base, rec->buf, rec->command_size);
>>> +	task->num_cmd = task->command_size / CMDQ_INST_SIZE;
>>> +	return task;
>>> +}
>>> +
>>> +static void cmdq_thread_writel(struct cmdq_thread *thread, u32 value,
>>> +			       u32 offset)
>>> +{
>>> +	writel(value, thread->base + offset);
>>> +}
>>> +
>>> +static u32 cmdq_thread_readl(struct cmdq_thread *thread, u32 offset)
>>> +{
>>> +	return readl(thread->base + offset);
>>> +}
>>
>> We can get rid of cmdq_thread_readl/writel.
>
> Will do.
>
>>> +
>>> +static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
>>> +{
>>> +	u32 status;
>>> +
>>> +	cmdq_thread_writel(thread, CMDQ_THR_SUSPEND, CMDQ_THR_SUSPEND_TASK);
>>> +
>>> +	/* If already disabled, treat as suspended successful. */
>>> +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
>>> +	      CMDQ_THR_ENABLED))
>>> +		return 0;
>>> +
>>> +	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_CURR_STATUS,
>>> +			status, status & CMDQ_THR_STATUS_SUSPENDED, 0, 10)) {
>>> +		dev_err(cmdq->dev, "suspend GCE thread 0x%x failed\n",
>>> +			(u32)(thread->base - cmdq->base));
>>> +		return -EFAULT;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static void cmdq_thread_resume(struct cmdq_thread *thread)
>>> +{
>>> +	cmdq_thread_writel(thread, CMDQ_THR_RESUME, CMDQ_THR_SUSPEND_TASK);
>>> +}
>>> +
>>> +static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
>>> +{
>>> +	u32 warm_reset;
>>> +
>>> +	cmdq_thread_writel(thread, CMDQ_THR_DO_WARM_RESET, CMDQ_THR_WARM_RESET);
>>> +	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET,
>>> +			warm_reset, !(warm_reset & CMDQ_THR_DO_WARM_RESET),
>>> +			0, 10)) {
>>> +		dev_err(cmdq->dev, "reset GCE thread 0x%x failed\n",
>>> +			(u32)(thread->base - cmdq->base));
>>> +		return -EFAULT;
>>> +	}
>>> +	writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES);
>>> +	return 0;
>>> +}
>>> +
>>> +static void cmdq_thread_disable(struct cmdq *cmdq, struct cmdq_thread *thread)
>>> +{
>>> +	cmdq_thread_reset(cmdq, thread);
>>> +	cmdq_thread_writel(thread, CMDQ_THR_DISABLED, CMDQ_THR_ENABLE_TASK);
>>> +}
>>> +
>>> +/* notify GCE to re-fetch commands by setting GCE thread PC */
>>> +static void cmdq_thread_invalidate_fetched_data(struct cmdq_thread *thread)
>>> +{
>>> +	cmdq_thread_writel(thread,
>>> +			   cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR),
>>> +			   CMDQ_THR_CURR_ADDR);
>>> +}
>>> +
>>> +static void cmdq_task_insert_into_thread(struct cmdq_task *task)
>>> +{
>>> +	struct cmdq_thread *thread = task->thread;
>>> +	struct cmdq_task *prev_task = list_last_entry(
>>> +			&thread->task_busy_list, typeof(*task), list_entry);
>>> +	u64 *prev_task_base = prev_task->va_base;
>>> +
>>> +	/* let previous task jump to this task */
>>> +	prev_task_base[prev_task->num_cmd - 1] = (u64)CMDQ_JUMP_BY_PA << 32 |
>>> +						 task->pa_base;
>>> +
>>> +	cmdq_thread_invalidate_fetched_data(thread);
>>> +}
>>> +
>>> +/* we assume tasks in the same display GCE thread are waiting the same event. */
>>> +static void cmdq_task_remove_wfe(struct cmdq_task *task)
>>> +{
>>> +	u32 wfe_option = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
>>> +	u32 wfe_op = CMDQ_CODE_WFE << CMDQ_OP_CODE_SHIFT;
>>> +	u32 *base = task->va_base;
>>> +	u32 num_cmd = task->num_cmd << 1;
>>> +	int i;
>>> +
>>> +	for (i = 0; i < num_cmd; i += 2)
>>> +		if (base[i] == wfe_option &&
>>> +		    (base[i + 1] & CMDQ_OP_CODE_MASK) == wfe_op) {
>>> +			base[i] = CMDQ_JUMP_PASS;
>>> +			base[i + 1] = CMDQ_JUMP_BY_OFFSET;
>>> +		}
>>
>> After using the command buffer as a void pointer a u64 pointer, we now
>> reference to it as u32. I would prefer to explain here, how the command
>> looks like we are searching for and use a for loop passing task->num_cmd
>> instead.
>
> Will use u64* to rewrite the above code.
>
>>> +}
>>> +
>>> +static void cmdq_task_exec(struct cmdq_task *task, struct cmdq_thread *thread)
>>> +{
>>> +	struct cmdq *cmdq = task->cmdq;
>>> +	unsigned long flags;
>>> +	unsigned long curr_pa, end_pa;
>>> +
>>> +	WARN_ON(clk_prepare_enable(cmdq->clock) < 0);
>>> +	spin_lock_irqsave(&cmdq->exec_lock, flags);
>>
>> cmdq_task_exec is called with cmdq->task_mutex held, so why do we need
>> the spin_lock here? Can't we just use one of the two?
>
> We can drop task_mutex, but we will get some side effects.
> 1. exec_lock needs to include more code, but I think it is not good for
>     spinlock.
> 2. In cmdq_rec_flush_async(), task_mutex needs to protect
>     (1) cmdq->suspended, (2) cmdq_task_exec(), and
>     (3) cmdq_task_wait_release_schedule().
>     If we drop task_mutex, we have to put cmdq->suspended if condition
>     just before cmdq_task_exec() and inside exec_lock, and we have to
>     release task and its command buffer if error. This will let flow
>     become more complex and enlarge code size.
>
> What do you think?

Why do you need to protect cmdq_task_wait_release_schedule? We don't 
care about the order of the workqueue elements, do we?

As far as I understand you would need to protect cmdq_task_acquire as 
well, to "ensure" continously growing pa_base. More on that below.

>
>>> +	task->thread = thread;
>>> +	task->task_state = TASK_STATE_BUSY;
>>
>> That was already set in cmdq_task_acquire, why do we need to set it here
>> again?
>
> Will drop it.
>

Yeah, but I think it makes more sense to drop it in cmdq_task_acquire 
instead.

>>> +	if (list_empty(&thread->task_busy_list)) {
>>> +		WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
>>> +
>>> +		cmdq_thread_writel(thread, task->pa_base, CMDQ_THR_CURR_ADDR);
>>> +		cmdq_thread_writel(thread, task->pa_base + task->command_size,
>>> +				   CMDQ_THR_END_ADDR);
>>> +		cmdq_thread_writel(thread, CMDQ_THR_PRIORITY, CMDQ_THR_CFG);
>>> +		cmdq_thread_writel(thread, CMDQ_THR_IRQ_EN,
>>> +				   CMDQ_THR_IRQ_ENABLE);
>>> +
>>> +		cmdq_thread_writel(thread, CMDQ_THR_ENABLED,
>>> +				   CMDQ_THR_ENABLE_TASK);
>>> +	} else {
>>> +		WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
>>> +
>>> +		/*
>>> +		 * check boundary condition
>>> +		 * PC = END - 8, EOC is executed
>>> +		 * PC = END, all CMDs are executed
>>> +		 */
>>> +		curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
>>> +		end_pa = cmdq_thread_readl(thread, CMDQ_THR_END_ADDR);
>>> +		if (curr_pa == end_pa - 8 || curr_pa == end_pa) {
>>
>> 8 refers to CMDQ_INST_SIZE, right?
>
> Yes, I will use CMDQ_INST_SIZE.
>
>>> +			/* set to this task directly */
>>> +			cmdq_thread_writel(thread, task->pa_base,
>>> +					   CMDQ_THR_CURR_ADDR);
>>> +		} else {
>>> +			cmdq_task_insert_into_thread(task);
>>> +
>>> +			if (thread == &cmdq->thread[CMDQ_THR_DISP_MAIN_IDX] ||
>>> +			    thread == &cmdq->thread[CMDQ_THR_DISP_SUB_IDX])
>>> +				cmdq_task_remove_wfe(task);
>>
>> We could do this check using the task->engine_flag, I suppose that's
>> easier to undestand then.
>
> Will use task->engine_flag.
>
>>> +
>>> +			smp_mb(); /* modify jump before enable thread */
>>> +		}
>>> +
>>> +		cmdq_thread_writel(thread, task->pa_base + task->command_size,
>>> +				   CMDQ_THR_END_ADDR);
>>> +		cmdq_thread_resume(thread);
>>> +	}
>>> +	list_move_tail(&task->list_entry, &thread->task_busy_list);
>>> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
>>> +}
>>> +
>>> +static void cmdq_handle_error_done(struct cmdq *cmdq,
>>> +				   struct cmdq_thread *thread, u32 irq_flag)
>>> +{
>>> +	struct cmdq_task *task, *tmp, *curr_task = NULL;
>>> +	u32 curr_pa;
>>> +	struct cmdq_cb_data cmdq_cb_data;
>>> +	bool err;
>>> +
>>> +	if (irq_flag & CMDQ_THR_IRQ_ERROR)
>>> +		err = true;
>>> +	else if (irq_flag & CMDQ_THR_IRQ_DONE)
>>> +		err = false;
>>> +	else
>>> +		return;
>>> +
>>> +	curr_pa = cmdq_thread_readl(thread, CMDQ_THR_CURR_ADDR);
>>> +
>>> +	list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
>>> +				 list_entry) {
>>> +		if (curr_pa >= task->pa_base &&
>>> +		    curr_pa < (task->pa_base + task->command_size))
>>
>> What are you checking here? It seems as if you make some implcit
>> assumptions about pa_base and the order of execution of commands in the
>> thread. Is it save to do so? Does dma_alloc_coherent give any guarantees
>> about dma_handle?
>
> 1. Check what is the current running task in this GCE thread.
> 2. Yes.
> 3. Yes, CMDQ doesn't use iommu, so physical address is continuous.
>

Yes, physical addresses might be continous, but AFAIK there is no 
guarantee that the dma_handle address is steadily growing, when calling 
dma_alloc_coherent. And if I understand the code correctly, you use this 
assumption to decide if the task picked from task_busy_list is currently 
executing. So I think this mecanism is not working.

In which cases does the HW thread raise an interrupt.
In case of error. When does CMDQ_THR_IRQ_DONE get raised?

>>> +			curr_task = task;
>>> +		if (task->cb.cb) {
>>> +			cmdq_cb_data.err = curr_task ? err : false;
>>> +			cmdq_cb_data.data = task->cb.data;
>>> +			task->cb.cb(cmdq_cb_data);
>>> +		}
>>> +		task->task_state = (curr_task && err) ? TASK_STATE_ERROR :
>>> +				TASK_STATE_DONE;
>>> +		list_del(&task->list_entry);
>>> +		if (curr_task)
>>> +			break;
>>> +	}
>>> +
>>> +	wake_up(&thread->wait_task_done);
>>> +}
>>> +
>>> +static void cmdq_thread_irq_handler(struct cmdq *cmdq, int tid)
>>> +{
>>> +	struct cmdq_thread *thread = &cmdq->thread[tid];
>>> +	unsigned long flags = 0L;
>>> +	u32 irq_flag;
>>> +
>>> +	spin_lock_irqsave(&cmdq->exec_lock, flags);
>>> +
>>> +	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
>>> +	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
>>> +
>>> +	/*
>>> +	 * Another CPU core could run "release task" right before we acquire
>>> +	 * the spin lock, and thus reset / disable this GCE thread, so we
>>> +	 * need to check the enable bit of this GCE thread.
>>> +	 */
>>> +	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
>>> +	      CMDQ_THR_ENABLED))
>>> +		irq_flag = 0;
>>
>> cmdq_handle_error_done just retuns in this case. Programming this way
>> just makes things confusing. What about:
>>
>> if (cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
>> 	      CMDQ_THR_ENABLED)
>> 	cmdq_handle_error_done(cmdq, thread, irq_flag);
>> else
>> 		irq_flag = 0;
>>
>> spin_unlock_irqrestore(&cmdq->exec_lock, flags);
>
> We still need to clear irq_flag if GCE thread is disabled.
> So, I think we can just return here.
>
> 	if (!(cmdq_thread_readl(thread, CMDQ_THR_ENABLE_TASK) &
> 	      CMDQ_THR_ENABLED))
> 		return;
>
> What do you think?
>

No, you can't just return, you need to unlock the spinlock.
Anyway I would prefer it the other way round, as I put it in my last 
mail. Just delete the else branch, we don't need to set irq_flag to zero.

>>> +
>>> +	cmdq_handle_error_done(cmdq, thread, irq_flag);
>>> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
>>> +}
>>> +
>>> +static irqreturn_t cmdq_irq_handler(int irq, void *dev)
>>> +{
>>> +	struct cmdq *cmdq = dev;
>>> +	u32 irq_status;
>>> +	int i;
>>> +
>>> +	irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS);
>>> +	irq_status &= CMDQ_IRQ_MASK;
>>> +	irq_status ^= CMDQ_IRQ_MASK;
>>
>> irq_status can be much bigger then 3, which is the number of threads in
>> the system (CMDQ_THR_MAX_COUNT). So why we use this mask here isn't
>> clear to me.
>
> Our GCE hardware has 16 threads, but we only use 3 threads currently.
>

Ok, but please use bitops here.

>>> +
>>> +	if (!irq_status)
>>> +		return IRQ_NONE;
>>> +
>>> +	while (irq_status) {
>>> +		i = ffs(irq_status) - 1;
>>> +		irq_status &= ~BIT(i);
>>> +		cmdq_thread_irq_handler(cmdq, i);
>>> +	}
>>
>> Can you explain how the irq status register looks like, that would it
>> make much easier to understand what happens here.
>
> Bit 0 ~ 15 of irq status register represents GCE thread 0 ~ 15
> interrupt. 0 means asserting interrupt; 1 means no interrupt.
>

Thanks, that helped. :)

>>> +
>>> +	return IRQ_HANDLED;	
>>> +}
>>> +
>>> +static int cmdq_task_handle_error_result(struct cmdq_task *task)
>>
>> We never check the return values, why do we have them?
>
> Will drop return value.
>
>>> +{
>>> +	struct cmdq *cmdq = task->cmdq;
>>> +	struct device *dev = cmdq->dev;
>>> +	struct cmdq_thread *thread = task->thread;
>>> +	struct cmdq_task *next_task, *prev_task;
>>> +	u32 irq_flag;
>>> +
>>> +	/* suspend GCE thread to ensure consistency */
>>> +	WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
>>> +
>>> +	/* ISR has handled this error task */
>>> +	if (task->task_state == TASK_STATE_ERROR) {
>>> +		next_task = list_first_entry_or_null(&thread->task_busy_list,
>>> +				struct cmdq_task, list_entry);
>>> +		if (next_task) /* move to next task */
>>> +			cmdq_thread_writel(thread, next_task->pa_base,
>>> +					   CMDQ_THR_CURR_ADDR);
>>
>> We have to do this, as we suppose that the thread did not reach the jump
>> instruction we put into it's command queue, right?
>
> Yes.
>

So this should then go into it's own function. In wait_release_work, 
something like this:

if(task->task_state == TASK_STATE_ERROR)
      cmdq_task_handle_error(task)

>>> +		cmdq_thread_resume(thread);
>>> +		return -ECANCELED;
>>> +	}
>>> +
>>
>> if task_state != ERROR and != DONE. This means that the timeout of
>> task_release_wq has timed out, right?
>
> Yes.
>
>>> +	/*
>>> +	 * Save next_task and prev_task in advance
>>> +	 * since cmdq_handle_error_done will remove list_entry.
>>> +	 */
>>> +	next_task = prev_task = NULL;
>>> +	if (task->list_entry.next != &thread->task_busy_list)
>>> +		next_task = list_next_entry(task, list_entry);
>>> +	if (task->list_entry.prev != &thread->task_busy_list)
>>> +		prev_task = list_prev_entry(task, list_entry);
>>> +
>>> +	/*
>>> +	 * Although IRQ is disabled, GCE continues to execute.
>>> +	 * It may have pending IRQ before GCE thread is suspended,
>>> +	 * so check this condition again.
>>> +	 */
>>
>> The first thing we did in this function was suspending the thread. Why
>> do we need this then?
>
> Because timeout is CPU timeout not GCE timeout, GCE could just finish
> this task before the GCE thread is suspended.
>

What are the reasons for a timeout? An error has happend, or the task is 
still executing.

>> To be honest this whole functions looks really like a design error. We
>> have to sperate the states much clearer so that it is possible to
>> understand what is happening in the GCE. Isn't it for example posible to
>> have worker queues for timed out tasks and tasks with an error? I'm not
>> sure how to do this, actually I'm not sure if I really understood how
>> this is supposed to work.
>
> GCE doesn't have timeout. The timeout is decided and controlled by CPU,
> so we check timeout in release work.
> For error and done, they are easy to check by register, and we have
> already created release work for timeout. So, I don't think we need to
> create work queue for each case.
>
> What do you think?
>

I think, if we find in here, that the irq_flag is set, then the the 
interrupt handler was triggered and is spinning the spinlock. If this is 
not the case, we have a timeout and we handle this.

>> How much do we win, when we patch the thread command queue for every
>> task we add, instead of just taking one task after another from the
>> task_busy_list?
>
> GCE is used to help read/write registers with critical time limitation.
> Sometimes, client may ask to process multiple tasks in a short period
> of time, e.g. display flush multiple tasks for next vblank. So, CMDQ
> shouldn't limit to process one task after another from the
> task_busy_list. Currently, when interrupt or timeout, we will check
> how many tasks are done, and which one is error or timeout.
>

So I suppose the device driver who use this are interested in throughput 
and not in latency. The callback of every

>>> +	irq_flag = cmdq_thread_readl(thread, CMDQ_THR_IRQ_STATUS);
>>> +	cmdq_handle_error_done(cmdq, thread, irq_flag);
>>> +	cmdq_thread_writel(thread, ~irq_flag, CMDQ_THR_IRQ_STATUS);
>>> +
>>> +	if (task->task_state == TASK_STATE_DONE) {
>>> +		cmdq_thread_resume(thread);
>>> +		return 0;
>>> +	}
>>> +
>>> +	if (task->task_state == TASK_STATE_ERROR) {
>>> +		dev_err(dev, "task 0x%p error\n", task);
>>> +		if (next_task) /* move to next task */
>>> +			cmdq_thread_writel(thread, next_task->pa_base,
>>> +					   CMDQ_THR_CURR_ADDR);
>>> +		cmdq_thread_resume(thread);
>>> +		return -ECANCELED;
>>> +	}
>>> +
>>> +	/* Task is running, so we force to remove it. */
>>> +	dev_err(dev, "task 0x%p timeout or killed\n", task);
>>> +	task->task_state = TASK_STATE_ERROR;
>>> +
>>> +	if (prev_task) {
>>> +		u64 *prev_va = prev_task->va_base;
>>> +		u64 *curr_va = task->va_base;
>>> +
>>> +		/* copy JUMP instruction */
>>> +		prev_va[prev_task->num_cmd - 1] = curr_va[task->num_cmd - 1];
>>> +
>>> +		cmdq_thread_invalidate_fetched_data(thread);
>>> +	} else if (next_task) { /* move to next task */
>>> +		cmdq_thread_writel(thread, next_task->pa_base,
>>> +				   CMDQ_THR_CURR_ADDR);
>>> +	}
>>> +
>>> +	list_del(&task->list_entry);
>>> +	cmdq_thread_resume(thread);
>>> +
>>> +	/* call cb here to prevent lock */
>>> +	if (task->cb.cb) {
>>> +		struct cmdq_cb_data cmdq_cb_data;
>>> +
>>> +		cmdq_cb_data.err = true;
>>> +		cmdq_cb_data.data = task->cb.data;
>>> +		task->cb.cb(cmdq_cb_data);
>>> +	}
>>> +
>>> +	return -ECANCELED;
>>> +}
>>> +
>>> +static void cmdq_task_wait_release_work(struct work_struct *work_item)
>>> +{
>>> +	struct cmdq_task *task = container_of(work_item, struct cmdq_task,
>>> +					      release_work);
>>> +	struct cmdq *cmdq = task->cmdq;
>>> +	struct cmdq_thread *thread = task->thread;
>>> +	unsigned long flags;
>>> +
>>> +	wait_event_timeout(thread->wait_task_done,
>>> +			   task->task_state != TASK_STATE_BUSY,
>>> +			   msecs_to_jiffies(CMDQ_TIMEOUT_MS));
>>> +
>>> +	spin_lock_irqsave(&cmdq->exec_lock, flags);
>>> +	if (task->task_state != TASK_STATE_DONE)
>>> +		cmdq_task_handle_error_result(task);
>>> +	if (list_empty(&thread->task_busy_list))
>>> +		cmdq_thread_disable(cmdq, thread);
>>> +	spin_unlock_irqrestore(&cmdq->exec_lock, flags);
>>> +
>>> +	/* release regardless of success or not */
>>> +	clk_disable_unprepare(cmdq->clock);
>>> +	cmdq_task_release(task);
>>> +}
>>> +
>>> +static void cmdq_task_wait_release_schedule(struct cmdq_task *task)
>>> +{
>>> +	struct cmdq *cmdq = task->cmdq;
>>> +
>>> +	INIT_WORK(&task->release_work, cmdq_task_wait_release_work);
>>> +	queue_work(cmdq->task_release_wq, &task->release_work);
>>> +}
>>> +
>>> +static int cmdq_rec_realloc_cmd_buffer(struct cmdq_rec *rec, size_t size)
>>> +{
>>> +	void *new_buf;
>>> +
>>> +	new_buf = krealloc(rec->buf, size, GFP_KERNEL | __GFP_ZERO);
>>> +	if (!new_buf)
>>> +		return -ENOMEM;
>>> +	rec->buf = new_buf;
>>> +	rec->buf_size = size;
>>> +	return 0;
>>> +}
>>> +
>>> +struct cmdq_base *cmdq_register_device(struct device *dev)
>>> +{
>>> +	struct cmdq_base *cmdq_base;
>>> +	struct resource res;
>>> +	int subsys;
>>> +	u32 base;
>>> +
>>> +	if (of_address_to_resource(dev->of_node, 0, &res))
>>> +		return NULL;
>>> +	base = (u32)res.start;
>>> +
>>> +	subsys = cmdq_subsys_base_to_id(base >> 16);
>>> +	if (subsys < 0)
>>> +		return NULL;
>>> +
>>> +	cmdq_base = devm_kmalloc(dev, sizeof(*cmdq_base), GFP_KERNEL);
>>> +	if (!cmdq_base)
>>> +		return NULL;
>>> +	cmdq_base->subsys = subsys;
>>> +	cmdq_base->base = base;
>>> +
>>> +	return cmdq_base;
>>> +}
>>> +EXPORT_SYMBOL(cmdq_register_device);
>>> +
>>> +int cmdq_rec_create(struct device *dev, u64 engine_flag,
>>> +		    struct cmdq_rec **rec_ptr)
>>> +{
>>> +	struct cmdq_rec *rec;
>>> +	int err;
>>> +
>>> +	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
>>> +	if (!rec)
>>> +		return -ENOMEM;
>>> +	rec->cmdq = dev_get_drvdata(dev);
>>> +	rec->engine_flag = engine_flag;
>>> +	err = cmdq_rec_realloc_cmd_buffer(rec, CMDQ_INITIAL_CMD_BLOCK_SIZE);
>>
>> Just pass PAGE_SIZE here, no need for CMDQ_INITIAL_CMD_BLOCK_SIZE.
>
> Will do.
>
>>> +	if (err < 0) {
>>> +		kfree(rec);
>>> +		return err;
>>> +	}
>>> +	*rec_ptr = rec;
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL(cmdq_rec_create);
>>> +
>>> +static int cmdq_rec_append_command(struct cmdq_rec *rec, enum cmdq_code code,
>>> +				   u32 arg_a, u32 arg_b)
>>> +{
>>> +	u64 *cmd_ptr;
>>> +	int err;
>>> +
>>> +	if (WARN_ON(rec->finalized))
>>> +		return -EBUSY;
>>> +	if (code < CMDQ_CODE_MOVE || code > CMDQ_CODE_EOC)
>>> +		return -EINVAL;
>>
>> cmdq_rec_append_command is just called from inside this driver and code
>> is a enum. We can expect it to be correct, no need for this check.
>
> Will drop this check.
>
>>> +	if (unlikely(rec->command_size + CMDQ_INST_SIZE > rec->buf_size)) {
>>
>> command_size is the offset into the buffer to which a new command is
>> written, so this name is highly confusing. I wonder if this would be
>> easier to understand if we redefine command_size to something like the
>> number of commands and divide/multiply CMDQ_INST_SIZE where this is needed.
>
> I can rename command_size to cmd_buf_size and calculate num_cmd by
> dividing CMDQ_INST_SIZE.
> What do you think?
>
>>> +		err = cmdq_rec_realloc_cmd_buffer(rec, rec->buf_size * 2);
>>> +		if (err < 0)
>>> +			return err;
>>> +	}
>>> +	cmd_ptr = rec->buf + rec->command_size;
>>> +	(*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b;
>>> +	rec->command_size += CMDQ_INST_SIZE;
>>> +	return 0;
>>> +}
>>> +
>>> +int cmdq_rec_write(struct cmdq_rec *rec, u32 value, struct cmdq_base *base,
>>> +		   u32 offset)
>>> +{
>>> +	u32 arg_a = ((base->base + offset) & CMDQ_ARG_A_WRITE_MASK) |
>>> +		    ((base->subsys & CMDQ_SUBSYS_MASK) << CMDQ_SUBSYS_SHIFT);
>>
>> base->subsys is the id from gce_sybsys, so we can expect it to be
>> correct, no need to mask with CMDQ_SUBSYS_MASK.
>
> Will drop it.
>
>>> +	return cmdq_rec_append_command(rec, CMDQ_CODE_WRITE, arg_a, value);
>>> +}
>>> +EXPORT_SYMBOL(cmdq_rec_write);
>>> +
>>> +int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
>>> +			struct cmdq_base *base, u32 offset, u32 mask)
>>> +{
>>> +	u32 offset_mask = offset;
>>> +	int err;
>>> +
>>> +	if (mask != 0xffffffff) {
>>> +		err = cmdq_rec_append_command(rec, CMDQ_CODE_MOVE, 0, ~mask);
>>> +		if (err < 0)
>>> +			return err;
>>> +		offset_mask |= CMDQ_WRITE_ENABLE_MASK;
>>> +	}
>>> +	return cmdq_rec_write(rec, value, base, offset_mask);
>>> +}
>>> +EXPORT_SYMBOL(cmdq_rec_write_mask);
>>> +
>>> +int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event)
>>> +{
>>> +	u32 arg_b;
>>> +
>>> +	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
>>> +		return -EINVAL;
>>> +
>>> +	/*
>>> +	 * bit 0-11: wait value
>>> +	 * bit 15: 1 - wait, 0 - no wait
>>> +	 * bit 16-27: update value
>>> +	 * bit 31: 1 - update, 0 - no update
>>> +	 */
>>
>> I don't understand this comments. What are they for?
>
> This is for WFE command. I will comment it.
>
>>> +	arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
>>> +	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event, arg_b);
>>> +}
>>> +EXPORT_SYMBOL(cmdq_rec_wfe);
>>> +
>>> +int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event)
>>> +{
>>> +	if (event >= CMDQ_MAX_HW_EVENT_COUNT || event < 0)
>>> +		return -EINVAL;
>>> +
>>> +	return cmdq_rec_append_command(rec, CMDQ_CODE_WFE, event,
>>> +				       CMDQ_WFE_UPDATE);
>>> +}
>>> +EXPORT_SYMBOL(cmdq_rec_clear_event);
>>> +
>>> +static int cmdq_rec_finalize(struct cmdq_rec *rec)
>>> +{
>>> +	int err;
>>> +
>>> +	if (rec->finalized)
>>> +		return 0;
>>> +
>>> +	/* insert EOC and generate IRQ for each command iteration */
>>> +	err = cmdq_rec_append_command(rec, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN);
>>> +	if (err < 0)
>>> +		return err;
>>> +
>>> +	/* JUMP to end */
>>> +	err = cmdq_rec_append_command(rec, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS);
>>> +	if (err < 0)
>>> +		return err;
>>> +
>>
>> Does this need to be atomic?
>> What happens if after CODE_EOC and before CODE_JUMP some
>> write/read/event gets added?
>> What happens if more commands get added to the queue after CODE_JUMP,
>> but before finalized is set to true. Why don't you use atomic functions
>> to access finalized?
>
> Since cmdq_rec doesn't guarantee thread safe, mutex is needed when
> client uses cmdq_rec.
>

Well I think that rec->finalized tries to implement this, but might 
fail, if two kernel threads work on the same cmdq_rec.

>>> +	rec->finalized = true;
>>> +	return 0;
>>> +}
>>> +
>>> +int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
>>> +			 void *data)
>>> +{
>>> +	struct cmdq *cmdq = rec->cmdq;
>>> +	struct cmdq_task *task;
>>> +	struct cmdq_task_cb task_cb;
>>> +	struct cmdq_thread *thread;
>>> +	int err;
>>> +
>>> +	mutex_lock(&cmdq->task_mutex);
>>> +	if (cmdq->suspended) {
>>> +		dev_err(cmdq->dev, "%s is called after suspended\n", __func__);
>>> +		mutex_unlock(&cmdq->task_mutex);
>>> +		return -EPERM;
>>> +	}
>>> +
>>> +	err = cmdq_rec_finalize(rec);
>>> +	if (err < 0) {
>>> +		mutex_unlock(&cmdq->task_mutex);
>>> +		return err;
>>> +	}
>>> +
>>> +	task_cb.cb = cb;
>>> +	task_cb.data = data;
>>> +	task = cmdq_task_acquire(rec, task_cb);
>>> +	if (!task) {
>>> +		mutex_unlock(&cmdq->task_mutex);
>>> +		return -EFAULT;
>>> +	}
>>> +
>>> +	thread = &cmdq->thread[cmdq_eng_get_thread(task->engine_flag)];
>>> +	cmdq_task_exec(task, thread);
>>> +	cmdq_task_wait_release_schedule(task);
>>> +	mutex_unlock(&cmdq->task_mutex);
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL(cmdq_rec_flush_async);
>>> +
>>> +struct cmdq_flush_completion {
>>> +	struct completion cmplt;
>>> +	bool err;
>>> +};
>>> +
>>> +static int cmdq_rec_flush_cb(struct cmdq_cb_data data)
>>> +{
>>> +	struct cmdq_flush_completion *cmplt = data.data;
>>> +
>>> +	cmplt->err = data.err;
>>> +	complete(&cmplt->cmplt);
>>> +	return 0;
>>> +}
>>> +
>>> +int cmdq_rec_flush(struct cmdq_rec *rec)
>>> +{
>>> +	struct cmdq_flush_completion cmplt;
>>> +	int err;
>>> +
>>> +	init_completion(&cmplt.cmplt);
>>> +	err = cmdq_rec_flush_async(rec, cmdq_rec_flush_cb, &cmplt);
>>> +	if (err < 0)
>>> +		return err;
>>> +	wait_for_completion(&cmplt.cmplt);
>>> +	return cmplt.err ? -EFAULT : 0;
>>> +}
>>> +EXPORT_SYMBOL(cmdq_rec_flush);
>>> +
>>> +void cmdq_rec_destroy(struct cmdq_rec *rec)
>>> +{
>>> +	kfree(rec->buf);
>>> +	kfree(rec);
>>> +}
>>> +EXPORT_SYMBOL(cmdq_rec_destroy);
>>> +
>>> +static bool cmdq_task_is_empty(struct cmdq *cmdq)
>>> +{
>>> +	struct cmdq_thread *thread;
>>> +	int i;
>>> +
>>> +	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
>>> +		thread = &cmdq->thread[i];
>>> +		if (!list_empty(&thread->task_busy_list))
>>> +			return false;
>>> +	}
>>> +	return true;
>>> +}
>>> +
>>> +static int cmdq_suspend(struct device *dev)
>>> +{
>>> +	struct cmdq *cmdq = dev_get_drvdata(dev);
>>> +	u32 exec_threads;
>>> +
>>> +	mutex_lock(&cmdq->task_mutex);
>>> +	cmdq->suspended = true;
>>> +	mutex_unlock(&cmdq->task_mutex);
>>> +
>>> +	exec_threads = readl(cmdq->base + CMDQ_CURR_LOADED_THR);
>>> +	if ((exec_threads & CMDQ_THR_EXECUTING) && !cmdq_task_is_empty(cmdq)) {
>>> +		dev_err(dev, "wait active tasks timeout.\n");
>>> +		flush_workqueue(cmdq->task_release_wq);
>>> +	}
>>> +	return 0;
>>> +}
>>> +
>>> +static int cmdq_resume(struct device *dev)
>>> +{
>>> +	struct cmdq *cmdq = dev_get_drvdata(dev);
>>> +
>>> +	cmdq->suspended = false;
>>> +	return 0;
>>> +}
>>> +
>>> +static int cmdq_remove(struct platform_device *pdev)
>>> +{
>>> +	struct cmdq *cmdq = platform_get_drvdata(pdev);
>>> +
>>> +	destroy_workqueue(cmdq->task_release_wq);
>>> +	cmdq->task_release_wq = NULL;
>>> +	return 0;
>>> +}
>>> +
>>> +static int cmdq_probe(struct platform_device *pdev)
>>> +{
>>> +	struct device *dev = &pdev->dev;
>>> +	struct device_node *node = dev->of_node;
>>> +	struct resource *res;
>>> +	struct cmdq *cmdq;
>>> +	int err, i;
>>> +
>>> +	cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
>>> +	if (!cmdq)
>>> +		return -ENOMEM;
>>> +	cmdq->dev = dev;
>>> +
>>> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> +	cmdq->base = devm_ioremap_resource(dev, res);
>>> +	if (IS_ERR(cmdq->base)) {
>>> +		dev_err(dev, "failed to ioremap gce\n");
>>> +		return PTR_ERR(cmdq->base);
>>> +	}
>>> +
>>> +	cmdq->irq = irq_of_parse_and_map(node, 0);
>>> +	if (!cmdq->irq) {
>>> +		dev_err(dev, "failed to get irq\n");
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
>>> +		dev, cmdq->base, cmdq->irq);
>>> +
>>> +	mutex_init(&cmdq->task_mutex);
>>> +	spin_lock_init(&cmdq->exec_lock);
>>> +	cmdq->task_release_wq = alloc_ordered_workqueue(
>>> +			"%s", WQ_MEM_RECLAIM | WQ_HIGHPRI,
>>> +			"cmdq_task_wait_release");
>>> +
>>> +	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
>>> +		cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
>>> +				CMDQ_THR_SHIFT * i;
>>> +		init_waitqueue_head(&cmdq->thread[i].wait_task_done);
>>> +		INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list);
>>> +	}
>>> +
>>> +	platform_set_drvdata(pdev, cmdq);
>>> +
>>> +	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
>>> +			       CMDQ_DRIVER_DEVICE_NAME, cmdq);
>>> +	if (err < 0) {
>>> +		dev_err(dev, "failed to register ISR (%d)\n", err);
>>> +		goto fail;
>>> +	}
>>> +
>>> +	cmdq->clock = devm_clk_get(dev, CMDQ_CLK_NAME);
>>> +	if (IS_ERR(cmdq->clock)) {
>>> +		dev_err(dev, "failed to get clk:%s\n", CMDQ_CLK_NAME);
>>> +		err = PTR_ERR(cmdq->clock);
>>> +		goto fail;
>>> +	}
>>> +	return 0;
>>> +
>>> +fail:
>>> +	cmdq_remove(pdev);
>>> +	return err;
>>> +}
>>> +
>>> +static const struct dev_pm_ops cmdq_pm_ops = {
>>> +	.suspend = cmdq_suspend,
>>> +	.resume = cmdq_resume,
>>> +};
>>> +
>>> +static const struct of_device_id cmdq_of_ids[] = {
>>> +	{.compatible = "mediatek,mt8173-gce",},
>>> +	{}
>>> +};
>>> +
>>> +static struct platform_driver cmdq_drv = {
>>> +	.probe = cmdq_probe,
>>> +	.remove = cmdq_remove,
>>> +	.driver = {
>>> +		.name = CMDQ_DRIVER_DEVICE_NAME,
>>> +		.owner = THIS_MODULE,
>>> +		.pm = &cmdq_pm_ops,
>>> +		.of_match_table = cmdq_of_ids,
>>> +	}
>>> +};
>>> +
>>> +builtin_platform_driver(cmdq_drv);
>>> diff --git a/include/soc/mediatek/cmdq.h b/include/soc/mediatek/cmdq.h
>>> new file mode 100644
>>> index 0000000..60eef3d
>>> --- /dev/null
>>> +++ b/include/soc/mediatek/cmdq.h
>>> @@ -0,0 +1,197 @@
>>> +/*
>>> + * Copyright (c) 2015 MediaTek Inc.
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + */
>>> +
>>> +#ifndef __MTK_CMDQ_H__
>>> +#define __MTK_CMDQ_H__
>>> +
>>> +#include <linux/platform_device.h>
>>> +#include <linux/types.h>
>>> +
>>> +enum cmdq_eng {
>>> +	CMDQ_ENG_DISP_AAL,
>>> +	CMDQ_ENG_DISP_COLOR0,
>>> +	CMDQ_ENG_DISP_COLOR1,
>>> +	CMDQ_ENG_DISP_DPI0,
>>> +	CMDQ_ENG_DISP_DSI0,
>>> +	CMDQ_ENG_DISP_DSI1,
>>> +	CMDQ_ENG_DISP_GAMMA,
>>> +	CMDQ_ENG_DISP_OD,
>>> +	CMDQ_ENG_DISP_OVL0,
>>> +	CMDQ_ENG_DISP_OVL1,
>>> +	CMDQ_ENG_DISP_PWM0,
>>> +	CMDQ_ENG_DISP_PWM1,
>>> +	CMDQ_ENG_DISP_RDMA0,
>>> +	CMDQ_ENG_DISP_RDMA1,
>>> +	CMDQ_ENG_DISP_RDMA2,
>>> +	CMDQ_ENG_DISP_UFOE,
>>> +	CMDQ_ENG_DISP_WDMA0,
>>> +	CMDQ_ENG_DISP_WDMA1,
>>> +	CMDQ_ENG_MAX,
>>> +};
>>> +
>>> +/* events for CMDQ and display */
>>> +enum cmdq_event {
>>> +	/* Display start of frame(SOF) events */
>>> +	CMDQ_EVENT_DISP_OVL0_SOF = 11,
>>> +	CMDQ_EVENT_DISP_OVL1_SOF = 12,
>>> +	CMDQ_EVENT_DISP_RDMA0_SOF = 13,
>>> +	CMDQ_EVENT_DISP_RDMA1_SOF = 14,
>>> +	CMDQ_EVENT_DISP_RDMA2_SOF = 15,
>>> +	CMDQ_EVENT_DISP_WDMA0_SOF = 16,
>>> +	CMDQ_EVENT_DISP_WDMA1_SOF = 17,
>>> +	/* Display end of frame(EOF) events */
>>> +	CMDQ_EVENT_DISP_OVL0_EOF = 39,
>>> +	CMDQ_EVENT_DISP_OVL1_EOF = 40,
>>> +	CMDQ_EVENT_DISP_RDMA0_EOF = 41,
>>> +	CMDQ_EVENT_DISP_RDMA1_EOF = 42,
>>> +	CMDQ_EVENT_DISP_RDMA2_EOF = 43,
>>> +	CMDQ_EVENT_DISP_WDMA0_EOF = 44,
>>> +	CMDQ_EVENT_DISP_WDMA1_EOF = 45,
>>> +	/* Mutex end of frame(EOF) events */
>>> +	CMDQ_EVENT_MUTEX0_STREAM_EOF = 53,
>>> +	CMDQ_EVENT_MUTEX1_STREAM_EOF = 54,
>>> +	CMDQ_EVENT_MUTEX2_STREAM_EOF = 55,
>>> +	CMDQ_EVENT_MUTEX3_STREAM_EOF = 56,
>>> +	CMDQ_EVENT_MUTEX4_STREAM_EOF = 57,
>>> +	/* Display underrun events */
>>> +	CMDQ_EVENT_DISP_RDMA0_UNDERRUN = 63,
>>> +	CMDQ_EVENT_DISP_RDMA1_UNDERRUN = 64,
>>> +	CMDQ_EVENT_DISP_RDMA2_UNDERRUN = 65,
>>> +	/* Keep this at the end of HW events */
>>> +	CMDQ_MAX_HW_EVENT_COUNT = 260,
>>> +};
>>> +
>>> +struct cmdq_cb_data {
>>> +	bool	err;
>>> +	void	*data;
>>> +};
>>> +
>>> +typedef int (*cmdq_async_flush_cb)(struct cmdq_cb_data data);
>>> +
>>> +struct cmdq_task;
>>> +struct cmdq;
>>> +
>>> +struct cmdq_rec {
>>> +	struct cmdq		*cmdq;
>>> +	u64			engine_flag;
>>> +	size_t			command_size;
>>> +	void			*buf;
>>> +	size_t			buf_size;
>>> +	bool			finalized;
>>> +};

Why do we need cmdq_rec at all? Can't we just use the cmdq_task for that 
and this way make the driver less complex?

>>> +
>>> +struct cmdq_base {
>>> +	int	subsys;
>>> +	u32	base;
>>
>> subsys can always be calculated via cmdq_subsys_base_to_id(base >> 16)
>> so we can get rid of the struct, right?
>
> Current subsys method is based on previous comment from Daniel Kurtz.
> Please take a look of our previous discussion.
> http://lists.infradead.org/pipermail/linux-mediatek/2016-February/004483.html
> Thanks.
>

I have to look deeper into this, but from what I read, the proposal from 
Daniel [1] seems good to me.

[1] https://patchwork.kernel.org/patch/8068311/

>>> +};
>>> +
>>> +/**
>>> + * cmdq_register_device() - register device which needs CMDQ
>>> + * @dev:		device
>>> + *
>>> + * Return: cmdq_base pointer or NULL for failed
>>> + */
>>> +struct cmdq_base *cmdq_register_device(struct device *dev);
>>> +
>>> +/**
>>> + * cmdq_rec_create() - create command queue record
>>> + * @dev:		device
>>> + * @engine_flag:	command queue engine flag
>>> + * @rec_ptr:		command queue record pointer to retrieve cmdq_rec
>>> + *
>>> + * Return: 0 for success; else the error code is returned
>>> + */
>>> +int cmdq_rec_create(struct device *dev, u64 engine_flag,
>>> +		    struct cmdq_rec **rec_ptr);
>>> +
>>> +/**
>>> + * cmdq_rec_write() - append write command to the command queue record
>>> + * @rec:	the command queue record
>>> + * @value:	the specified target register value
>>> + * @base:	the command queue base
>>> + * @offset:	register offset from module base
>>> + *
>>> + * Return: 0 for success; else the error code is returned
>>> + */
>>> +int cmdq_rec_write(struct cmdq_rec *rec, u32 value,
>>> +		   struct cmdq_base *base, u32 offset);
>>> +
>>> +/**
>>> + * cmdq_rec_write_mask() - append write command with mask to the command
>>> + *			   queue record
>>> + * @rec:	the command queue record
>>> + * @value:	the specified target register value
>>> + * @base:	the command queue base
>>> + * @offset:	register offset from module base
>>> + * @mask:	the specified target register mask
>>> + *
>>> + * Return: 0 for success; else the error code is returned
>>> + */
>>> +int cmdq_rec_write_mask(struct cmdq_rec *rec, u32 value,
>>> +			struct cmdq_base *base, u32 offset, u32 mask);
>>> +
>>> +/**
>>> + * cmdq_rec_wfe() - append wait for event command to the command queue reco	rd
>>
>> reco rd -> record
>
> Will fix it.
>
>> Regards,
>> Matthias
>>
>>> + * @rec:	the command queue record
>>> + * @event:	the desired event type to "wait and CLEAR"
>>> + *
>>> + * Return: 0 for success; else the error code is returned
>>> + */
>>> +int cmdq_rec_wfe(struct cmdq_rec *rec, enum cmdq_event event);
>>> +
>>> +/**
>>> + * cmdq_rec_clear_event() - append clear event command to the command queue
>>> + *			    record
>>> + * @rec:	the command queue record
>>> + * @event:	the desired event to be cleared
>>> + *
>>> + * Return: 0 for success; else the error code is returned
>>> + */
>>> +int cmdq_rec_clear_event(struct cmdq_rec *rec, enum cmdq_event event);
>>> +
>>> +/**
>>> + * cmdq_rec_flush() - trigger CMDQ to execute the recorded commands
>>> + * @rec:	the command queue record
>>> + *
>>> + * Return: 0 for success; else the error code is returned
>>> + *
>>> + * Trigger CMDQ to execute the recorded commands. Note that this is a
>>> + * synchronous flush function. When the function returned, the recorded
>>> + * commands have been done.
>>> + */
>>> +int cmdq_rec_flush(struct cmdq_rec *rec);
>>> +
>>> +/**
>>> + * cmdq_rec_flush_async() - trigger CMDQ to asynchronously execute the recorded
>>> + *			    commands and call back after ISR is finished
>>> + * @rec:	the command queue record
>>> + * @cb:		called in the end of CMDQ ISR
>>> + * @data:	this data will pass back to cb
>>> + *
>>> + * Return: 0 for success; else the error code is returned
>>> + *
>>> + * Trigger CMDQ to asynchronously execute the recorded commands and call back
>>> + * after ISR is finished. Note that this is an ASYNC function. When the function
>>> + * returned, it may or may not be finished. The ISR callback function is called
>>> + * in the end of ISR.

"The callback is called from the ISR."

Regards,
Matthias

>>> + */
>>> +int cmdq_rec_flush_async(struct cmdq_rec *rec, cmdq_async_flush_cb cb,
>>> +			 void *data);
>>> +
>>> +/**
>>> + * cmdq_rec_destroy() - destroy command queue record
>>> + * @rec:	the command queue record
>>> + */
>>> +void cmdq_rec_destroy(struct cmdq_rec *rec);
>>> +
>>> +#endif	/* __MTK_CMDQ_H__ */
>>>
>
> Thanks,
> HS
>


From krzk at kernel.org  Tue May 31 13:05:06 2016
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 31 May 2016 22:05:06 +0200
Subject: [PATCH 5/6] ARM: dts: exynos: Configure PWM, usb3503, PMIC and
 thermal on Odroid XU board
In-Reply-To: <1ec0f7fc-f6e0-e4d6-e424-43289bf31b16@osg.samsung.com>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
 <1464719945-3417-5-git-send-email-krzk@kernel.org>
 <1ec0f7fc-f6e0-e4d6-e424-43289bf31b16@osg.samsung.com>
Message-ID: <CAJKOXPfDtp1GLCkQQSKmzRLs4qqwY9Y019rXpUXSeoYQny-sfA@mail.gmail.com>

On Tue, May 31, 2016 at 9:36 PM, Javier Martinez Canillas
<javier at osg.samsung.com> wrote:
> Hello Krzysztof,
>
> On 05/31/2016 02:39 PM, Krzysztof Kozlowski wrote:
>> Extend the DTS for Exynos5410-based Odroid XU board with:
>> 1. Proper PWM outputs,
>> 2. usb3503 USB HUB (with integrated LAN9730 ethernet adapter (smsc95xx)),
>> 3. Maxim 77802 PMIC (regulators, 32 kHz clocks, RTC),
>> 4. CPU thermal (trip points are the same as in Odroid XU3/XU4 but
>>    cooling maps are different as there is no CPU freq and only one
>>    cluster available for now),
>> 5. Regulator supplies for USB 3.0.
>>
>> Signed-off-by: Krzysztof Kozlowski <krzk at kernel.org>
>>
>> ---
>>
>
> [snip]
>
>> +
>> +                     ldo10_reg: LDO10 {
>> +                             regulator-name = "vdd18_mipi";
>> +                             regulator-min-microvolt = <1800000>;
>> +                             regulator-max-microvolt = <1800000>;
>> +                             regulator-always-on;
>> +                     };
>> +
>
> [snip]
>
>> +
>> +                     ldo12_reg: LDO12 {
>> +                             regulator-name = "vdd33_usb3";
>> +                             regulator-min-microvolt = <3300000>;
>> +                             regulator-max-microvolt = <3300000>;
>> +                             regulator-always-on;
>> +                     };
>> +
>
> [snip]
>
>> +
>> +                     ldo15_reg: LDO15 {
>> +                             regulator-name = "vdd10_usb3";
>> +                             regulator-min-microvolt = <1000000>;
>> +                             regulator-max-microvolt = <1000000>;
>> +                             regulator-always-on;
>> +                     };
>> +
>
> I see that LDO 10, 12 and 15 are used by still marked as always-on. Did
> you try not marking as always-on those or that also causes issues like
> in the other regulators were you added comments about being always-on?
>
> Besides that, patch looks good to me.

The LDO10 is supplying few more elements (MIPI, HDMI, ADC and
something called EFNAND). Having it non-always-on still works but
maybe because I did not test these elements.

LDO12 and LDO15 supply also VDD10_HSIC and UHOST (used by USB2.0 ports
and attached on board: usb3503 and lan9730) so if it is not enabled by
USB 3.0, then they won't work. I guess the usb 2.0 driver should also
take regulators.

So overall the board works after removing always-on but it is not
properly described in DT so I prefer to leave them.

Best regards,
Krzysztof


From javier at osg.samsung.com  Tue May 31 13:10:09 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 31 May 2016 16:10:09 -0400
Subject: [PATCH 5/6] ARM: dts: exynos: Configure PWM, usb3503, PMIC and
 thermal on Odroid XU board
In-Reply-To: <CAJKOXPfDtp1GLCkQQSKmzRLs4qqwY9Y019rXpUXSeoYQny-sfA@mail.gmail.com>
References: <1464719945-3417-1-git-send-email-krzk@kernel.org>
 <1464719945-3417-5-git-send-email-krzk@kernel.org>
 <1ec0f7fc-f6e0-e4d6-e424-43289bf31b16@osg.samsung.com>
 <CAJKOXPfDtp1GLCkQQSKmzRLs4qqwY9Y019rXpUXSeoYQny-sfA@mail.gmail.com>
Message-ID: <372c8249-b19e-2488-beef-50a0423da757@osg.samsung.com>

Hello Krzysztof,

On 05/31/2016 04:05 PM, Krzysztof Kozlowski wrote:
> On Tue, May 31, 2016 at 9:36 PM, Javier Martinez Canillas

[snip]

>>
>> I see that LDO 10, 12 and 15 are used by still marked as always-on. Did
>> you try not marking as always-on those or that also causes issues like
>> in the other regulators were you added comments about being always-on?
>>
>> Besides that, patch looks good to me.
> 
> The LDO10 is supplying few more elements (MIPI, HDMI, ADC and
> something called EFNAND). Having it non-always-on still works but
> maybe because I did not test these elements.
> 
> LDO12 and LDO15 supply also VDD10_HSIC and UHOST (used by USB2.0 ports
> and attached on board: usb3503 and lan9730) so if it is not enabled by
> USB 3.0, then they won't work. I guess the usb 2.0 driver should also
> take regulators.
> 
> So overall the board works after removing always-on but it is not
> properly described in DT so I prefer to leave them.
> 

Agreed, thanks a lot for your explanations.

> Best regards,
> Krzysztof

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America


From dimitrysh at google.com  Tue May 31 13:24:59 2016
From: dimitrysh at google.com (Dmitry Shmidt)
Date: Tue, 31 May 2016 13:24:59 -0700
Subject: building and using modules on arm64 hikey board
In-Reply-To: <0240F9F0-0146-4DCC-B512-195415B29B34@linaro.org>
References: <87a3195c-febb-a6c8-a679-272b9f7b59cc@broadcom.com>
 <0240F9F0-0146-4DCC-B512-195415B29B34@linaro.org>
Message-ID: <CAH7ZN-xMfE-+RiXfdvzEHtOVARy--yAV+fbjS+wsbujrkZgm0A@mail.gmail.com>

On Mon, May 30, 2016 at 4:30 AM, Ard Biesheuvel
<ard.biesheuvel at linaro.org> wrote:
> This is likely caused by the fact that the Android AArch64 toolchain uses -fpic by default. Could you try adding -fno-pic to the CFLAGS?

Actually Arend is using 4.4, and we need to pull your fix, Ard:

commit 80a2d83376001f6a1993f2e925670ab0e4cdb76d
Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
Date:   Tue Jan 5 10:18:52 2016 +0100

    arm64: module: avoid undefined shift behavior in reloc_data()


>> On 30 mei 2016, at 12:21, Arend Van Spriel <arend.vanspriel at broadcom.com> wrote:
>>
>> I got myself an arm64 HiKey board from LeMaker and build an Android AOSP
>> image for it (see [1]). For development I would like to use
>> CONFIG_MODULES. However, when I try to insmod the build module I get:
>>
>> [  287.903653] module cfg80211: overflow in relocation type 261 val
>> ffffffbffc006530
>>
>> Looking AArch64 ELF documentation [2], section 4.6.5, it has:
>> code|name            |operation |overflow check   |
>> 261 |R_AARCH64_PREL32|S + A - P |-2^31 <= X < 2^32|
>>
>> So basically the highest 32 bits should all be one and so ffffffbf is
>> invalid. From what I could find searching internet it could be an issue
>> with linker options so I build kernel and modules with V=1. Here the
>> linker invocation for them:
>>
>> + aarch64-linux-android-ld -EL -p --no-undefined -X --build-id -o vmlinux \
>> -T ./arch/arm64/kernel/vmlinux.lds arch/arm64/kernel/head.o
>> init/built-in.o \
>> --start-group usr/built-in.o arch/arm64/kernel/built-in.o
>> arch/arm64/mm/built-in.o \
>> arch/arm64/net/built-in.o arch/arm64/kvm/built-in.o
>> arch/arm64/crypto/built-in.o \
>> ./drivers/firmware/efi/libstub/lib.a kernel/built-in.o certs/built-in.o
>> mm/built-in.o \
>> fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o
>> block/built-in.o \
>> arch/arm64/lib/lib.a lib/lib.a arch/arm64/lib/built-in.o lib/built-in.o
>> drivers/built-in.o \
>> sound/built-in.o firmware/built-in.o net/built-in.o virt/built-in.o
>> --end-group .tmp_kallsyms2.o
>>
>>  aarch64-linux-android-ld -EL -r  -T ./scripts/module-common.lds
>> --build-id \
>>  -o net/wireless/cfg80211.ko net/wireless/cfg80211.o
>> net/wireless/cfg80211.mod.o
>>
>> Attached are vmlinux.lds and module-common.lds. I also tried taking
>> upstream arch/arm64/kernel/module.lds in hikey-linaro tree. If someone
>> can give a hint or educated guess at what to try it would be appreciated.
>>
>> Regards,
>> Arend
>>
>> [1] https://source.android.com/source/devices.html#building-kernel
>> [2]
>> http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
>> <module-common.lds>
>> <vmlinux.lds>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From ard.biesheuvel at linaro.org  Tue May 31 13:58:59 2016
From: ard.biesheuvel at linaro.org (Ard Biesheuvel)
Date: Tue, 31 May 2016 22:58:59 +0200
Subject: building and using modules on arm64 hikey board
In-Reply-To: <CAH7ZN-xMfE-+RiXfdvzEHtOVARy--yAV+fbjS+wsbujrkZgm0A@mail.gmail.com>
References: <87a3195c-febb-a6c8-a679-272b9f7b59cc@broadcom.com>
 <0240F9F0-0146-4DCC-B512-195415B29B34@linaro.org>
 <CAH7ZN-xMfE-+RiXfdvzEHtOVARy--yAV+fbjS+wsbujrkZgm0A@mail.gmail.com>
Message-ID: <CAKv+Gu_=SCHwi8nBXGQ6wux4T59BGAU_H-942+QnSL0KO=zp4w@mail.gmail.com>

On 31 May 2016 at 22:24, Dmitry Shmidt <dimitrysh at google.com> wrote:
> On Mon, May 30, 2016 at 4:30 AM, Ard Biesheuvel
> <ard.biesheuvel at linaro.org> wrote:
>> This is likely caused by the fact that the Android AArch64 toolchain uses -fpic by default. Could you try adding -fno-pic to the CFLAGS?
>
> Actually Arend is using 4.4, and we need to pull your fix, Ard:
>
> commit 80a2d83376001f6a1993f2e925670ab0e4cdb76d
> Author: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> Date:   Tue Jan 5 10:18:52 2016 +0100
>
>     arm64: module: avoid undefined shift behavior in reloc_data()
>

OK, that was going to be my next question to Arend, i.e., to check
whether he has all the recent fixes we did for the module loader.

But I'd also like to understand how we ended up with PREL32
relocations in the first place, since those are quite unusual in
object code generated from generic C source code when using the
non-pic small model, which is normally GCC's default. Are there any
other code generation defaults for the Android  AArch64 GCC toolchain
that you are aware of?

>>> On 30 mei 2016, at 12:21, Arend Van Spriel <arend.vanspriel at broadcom.com> wrote:
>>>
>>> I got myself an arm64 HiKey board from LeMaker and build an Android AOSP
>>> image for it (see [1]). For development I would like to use
>>> CONFIG_MODULES. However, when I try to insmod the build module I get:
>>>
>>> [  287.903653] module cfg80211: overflow in relocation type 261 val
>>> ffffffbffc006530
>>>
>>> Looking AArch64 ELF documentation [2], section 4.6.5, it has:
>>> code|name            |operation |overflow check   |
>>> 261 |R_AARCH64_PREL32|S + A - P |-2^31 <= X < 2^32|
>>>
>>> So basically the highest 32 bits should all be one and so ffffffbf is
>>> invalid. From what I could find searching internet it could be an issue
>>> with linker options so I build kernel and modules with V=1. Here the
>>> linker invocation for them:
>>>
>>> + aarch64-linux-android-ld -EL -p --no-undefined -X --build-id -o vmlinux \
>>> -T ./arch/arm64/kernel/vmlinux.lds arch/arm64/kernel/head.o
>>> init/built-in.o \
>>> --start-group usr/built-in.o arch/arm64/kernel/built-in.o
>>> arch/arm64/mm/built-in.o \
>>> arch/arm64/net/built-in.o arch/arm64/kvm/built-in.o
>>> arch/arm64/crypto/built-in.o \
>>> ./drivers/firmware/efi/libstub/lib.a kernel/built-in.o certs/built-in.o
>>> mm/built-in.o \
>>> fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o
>>> block/built-in.o \
>>> arch/arm64/lib/lib.a lib/lib.a arch/arm64/lib/built-in.o lib/built-in.o
>>> drivers/built-in.o \
>>> sound/built-in.o firmware/built-in.o net/built-in.o virt/built-in.o
>>> --end-group .tmp_kallsyms2.o
>>>
>>>  aarch64-linux-android-ld -EL -r  -T ./scripts/module-common.lds
>>> --build-id \
>>>  -o net/wireless/cfg80211.ko net/wireless/cfg80211.o
>>> net/wireless/cfg80211.mod.o
>>>
>>> Attached are vmlinux.lds and module-common.lds. I also tried taking
>>> upstream arch/arm64/kernel/module.lds in hikey-linaro tree. If someone
>>> can give a hint or educated guess at what to try it would be appreciated.
>>>
>>> Regards,
>>> Arend
>>>
>>> [1] https://source.android.com/source/devices.html#building-kernel
>>> [2]
>>> http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
>>> <module-common.lds>
>>> <vmlinux.lds>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From eric at anholt.net  Tue May 31 14:05:27 2016
From: eric at anholt.net (Eric Anholt)
Date: Tue, 31 May 2016 14:05:27 -0700
Subject: [PATCH v2 RESEND] irqchip: bcm2835: Avoid arch/arm-specific handle_IRQ
Message-ID: <1464728727-16300-1-git-send-email-eric@anholt.net>

This is equivalent and works for arm64 as well.

Signed-off-by: Eric Anholt <eric at anholt.net>
Acked-by: Stephen Warren <swarren at wwwdotorg.org>
---

Patch 1 of the arm64 series was left out of the 4.7 pull request.
Would it be possible to merge this through the SOC tree?  Otherwise I
would need a stable branch to merge from you, so that I can land the
Makefile changes to start building it.

 drivers/irqchip/irq-bcm2835.c | 3 +--
 drivers/irqchip/irq-bcm2836.c | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c
index bf9cc5f2e839..44d7c38dde47 100644
--- a/drivers/irqchip/irq-bcm2835.c
+++ b/drivers/irqchip/irq-bcm2835.c
@@ -52,7 +52,6 @@
 #include <linux/irqdomain.h>
 
 #include <asm/exception.h>
-#include <asm/mach/irq.h>
 
 /* Put the bank and irq (32 bits) into the hwirq */
 #define MAKE_HWIRQ(b, n)	((b << 5) | (n))
@@ -242,7 +241,7 @@ static void __exception_irq_entry bcm2835_handle_irq(
 	u32 hwirq;
 
 	while ((hwirq = get_next_armctrl_hwirq()) != ~0)
-		handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
+		handle_domain_irq(intc.domain, hwirq, regs);
 }
 
 static void bcm2836_chained_handle_irq(struct irq_desc *desc)
diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c
index 72ff1d5c5de6..27875982657e 100644
--- a/drivers/irqchip/irq-bcm2836.c
+++ b/drivers/irqchip/irq-bcm2836.c
@@ -180,7 +180,7 @@ __exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
 	} else if (stat) {
 		u32 hwirq = ffs(stat) - 1;
 
-		handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
+		handle_domain_irq(intc.domain, hwirq, regs);
 	}
 }
 
-- 
2.8.0.rc3



From sakari.ailus at iki.fi  Tue May 31 14:22:22 2016
From: sakari.ailus at iki.fi (Sakari Ailus)
Date: Wed, 1 Jun 2016 00:22:22 +0300
Subject: [PATCHv5] support for AD5820 camera auto-focus coil
In-Reply-To: <20160527205140.GA26767@amd>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com> <20160521105607.GA20071@amd>
 <574049EF.2090208@gmail.com> <20160524090433.GA1277@amd>
 <20160524091746.GA14536@amd>
 <20160525212659.GK26360@valkosipuli.retiisi.org.uk>
 <20160527205140.GA26767@amd>
Message-ID: <20160531212222.GP26360@valkosipuli.retiisi.org.uk>

Hi Pavel,

On Fri, May 27, 2016 at 10:51:40PM +0200, Pavel Machek wrote:
> 
> This adds support for AD5820 autofocus coil, found for example in
> Nokia N900 smartphone.
> 
> Signed-off-by: Pavel Machek <pavel at ucw.cz>

The patch looks good to me but then I came to think of a question I've
missed so far: is there DT documentation somewhere for the properties used
by the driver? I might put that to a separate patch, and cc the relevant
list.

Whether we decide to have the module in DT or not is orthogonal to this.

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus at iki.fi	XMPP: sailus at retiisi.org.uk


From pavel at ucw.cz  Tue May 31 14:34:37 2016
From: pavel at ucw.cz (Pavel Machek)
Date: Tue, 31 May 2016 23:34:37 +0200
Subject: [PATCHv5] support for AD5820 camera auto-focus coil
In-Reply-To: <20160531212222.GP26360@valkosipuli.retiisi.org.uk>
References: <20160517181927.GA28741@amd> <20160521054336.GA27123@amd>
 <573FFF51.1000004@gmail.com> <20160521105607.GA20071@amd>
 <574049EF.2090208@gmail.com> <20160524090433.GA1277@amd>
 <20160524091746.GA14536@amd>
 <20160525212659.GK26360@valkosipuli.retiisi.org.uk>
 <20160527205140.GA26767@amd>
 <20160531212222.GP26360@valkosipuli.retiisi.org.uk>
Message-ID: <20160531213437.GA28397@amd>

On Wed 2016-06-01 00:22:22, Sakari Ailus wrote:
> Hi Pavel,
> 
> On Fri, May 27, 2016 at 10:51:40PM +0200, Pavel Machek wrote:
> > 
> > This adds support for AD5820 autofocus coil, found for example in
> > Nokia N900 smartphone.
> > 
> > Signed-off-by: Pavel Machek <pavel at ucw.cz>
> 
> The patch looks good to me but then I came to think of a question I've
> missed so far: is there DT documentation somewhere for the properties used
> by the driver? I might put that to a separate patch, and cc the relevant
> list.

Well, it does not use any dt properties. So there's not really much to
discuss with dt people...

Maybe "ad5820" needs to go to list of simple i2c drivers somewhere,
but...

Best regards,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


From dianders at chromium.org  Tue May 31 14:35:39 2016
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 31 May 2016 14:35:39 -0700
Subject: [PATCH 1/6] phy: Add USB Type-C PHY driver for rk3399
In-Reply-To: <1464328939-8073-2-git-send-email-zyw@rock-chips.com>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
 <1464328939-8073-2-git-send-email-zyw@rock-chips.com>
Message-ID: <CAD=FV=V1qX_YTTygsz=v+p6BdG8VZcu8np2nDvm1NiJHDnf==g@mail.gmail.com>

Chris,

On Thu, May 26, 2016 at 11:02 PM, Chris Zhong <zyw at rock-chips.com> wrote:
> Add a PHY provider driver for the rk3399 SoC Type-c PHY. The USB
> Type-C PHY is designed to support the USB3 and DP applications. The
> PHY basically has two main components: USB3 and DisplyPort. USB3
> operates in SuperSpeed mode and the DP can operate at RBR, HBR and
> HBR2 data rates.
>
> Signed-off-by: Chris Zhong <zyw at rock-chips.com>
> ---
>
>  drivers/phy/Kconfig              |   7 +
>  drivers/phy/Makefile             |   1 +
>  drivers/phy/phy-rockchip-typec.c | 823 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 831 insertions(+)

This is a bit of a superficial review.  Hopefully we can find someone
to do something more thorough.


>  create mode 100644 drivers/phy/phy-rockchip-typec.c
>
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 26566db..dc388a3d 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -351,6 +351,13 @@ config PHY_ROCKCHIP_DP
>         help
>           Enable this to support the Rockchip Display Port PHY.
>
> +config PHY_ROCKCHIP_TYPEC
> +       tristate "Rockchip TYPEC PHY Driver"
> +       depends on ARCH_ROCKCHIP && OF
> +       select GENERIC_PHY
> +       help
> +         Enable this to support the Rockchip USB TYPEC PHY.
> +
>  config PHY_ST_SPEAR1310_MIPHY
>         tristate "ST SPEAR1310-MIPHY driver"
>         select GENERIC_PHY
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index 24596a9..91fa413 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -39,6 +39,7 @@ obj-$(CONFIG_PHY_QCOM_APQ8064_SATA)   += phy-qcom-apq8064-sata.o
>  obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
>  obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o
>  obj-$(CONFIG_PHY_ROCKCHIP_DP)          += phy-rockchip-dp.o
> +obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
>  obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)    += phy-qcom-ipq806x-sata.o
>  obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY)   += phy-spear1310-miphy.o
>  obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY)   += phy-spear1340-miphy.o
> diff --git a/drivers/phy/phy-rockchip-typec.c b/drivers/phy/phy-rockchip-typec.c
> new file mode 100644
> index 0000000..6609cfb
> --- /dev/null
> +++ b/drivers/phy/phy-rockchip-typec.c
> @@ -0,0 +1,823 @@
> +/*
> + * Rockchip usb3 PHY driver
> + *
> + * Copyright (C) 2016 Kever Yang <kever.yang at rock-chips.com>
> + *                    Chris Zhong <zyw at rock-chips.com>
> + * Copyright (C) 2016 ROCKCHIP, Inc.
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>p
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/regmap.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/delay.h>
> +#include <linux/phy/phy-rockchip-typec.h>
> +
> +#define ADDR_ADJ                       2
> +#define CMN_SSM_BANDGAP                        (0x21 << ADDR_ADJ)
> +#define CMN_SSM_BIAS                   (0x22 << ADDR_ADJ)
> +#define CMN_PLLSM0_PLLEN               (0x29 << ADDR_ADJ)
> +#define CMN_PLLSM0_PLLPRE              (0x2a << ADDR_ADJ)
> +#define CMN_PLLSM0_PLLVREF             (0x2b << ADDR_ADJ)
> +#define CMN_PLLSM0_PLLLOCK             (0x2c << ADDR_ADJ)
> +#define CMN_PLLSM1_PLLEN               (0x31 << ADDR_ADJ)
> +#define CMN_PLLSM1_PLLPRE              (0x32 << ADDR_ADJ)
> +#define CMN_PLLSM1_PLLVREF             (0x33 << ADDR_ADJ)
> +#define CMN_PLLSM1_PLLLOCK             (0x34 << ADDR_ADJ)
> +#define CMN_PLLSM1_USER_DEF_CTRL       (0x37 << ADDR_ADJ)
> +#define CMN_ICAL_OVRD                  (0xc1 << ADDR_ADJ)
> +#define CMN_PLL0_VCOCAL_OVRD           (0x83 << ADDR_ADJ)
> +#define CMN_PLL0_VCOCAL_INIT           (0x84 << ADDR_ADJ)
> +#define CMN_PLL0_VCOCAL_ITER           (0x85 << ADDR_ADJ)
> +#define CMN_PLL0_LOCK_REFCNT_START     (0x90 << ADDR_ADJ)
> +#define CMN_PLL0_LOCK_PLLCNT_START     (0x92 << ADDR_ADJ)
> +#define CMN_PLL0_LOCK_PLLCNT_THR       (0x93 << ADDR_ADJ)
> +#define CMN_PLL0_INTDIV                        (0x94 << ADDR_ADJ)
> +#define CMN_PLL0_FRACDIV               (0x95 << ADDR_ADJ)
> +#define CMN_PLL0_HIGH_THR              (0x96 << ADDR_ADJ)
> +#define CMN_PLL0_DSM_DIAG              (0x97 << ADDR_ADJ)
> +#define CMN_PLL0_SS_CTRL1              (0x98 << ADDR_ADJ)
> +#define CMN_PLL0_SS_CTRL2              (0x99 << ADDR_ADJ)
> +#define CMN_PLL1_VCOCAL_START          (0xa1 << ADDR_ADJ)
> +#define CMN_PLL1_VCOCAL_OVRD           (0xa3 << ADDR_ADJ)
> +#define CMN_PLL1_VCOCAL_INIT           (0xa4 << ADDR_ADJ)
> +#define CMN_PLL1_VCOCAL_ITER           (0xa5 << ADDR_ADJ)
> +#define CMN_PLL1_LOCK_REFCNT_START     (0xb0 << ADDR_ADJ)
> +#define CMN_PLL1_LOCK_PLLCNT_START     (0xb2 << ADDR_ADJ)
> +#define CMN_PLL1_LOCK_PLLCNT_THR       (0xb3 << ADDR_ADJ)
> +#define CMN_PLL1_INTDIV                        (0xb4 << ADDR_ADJ)
> +#define CMN_PLL1_FRACDIV               (0xb5 << ADDR_ADJ)
> +#define CMN_PLL1_HIGH_THR              (0xb6 << ADDR_ADJ)
> +#define CMN_PLL1_DSM_DIAG              (0xb7 << ADDR_ADJ)
> +#define CMN_PLL1_SS_CTRL1              (0xb8 << ADDR_ADJ)
> +#define CMN_PLL1_SS_CTRL2              (0xb9 << ADDR_ADJ)
> +#define CMN_RXCAL_OVRD                 (0xd1 << ADDR_ADJ)
> +#define CMN_TXPUCAL_CTRL               (0xe0 << ADDR_ADJ)
> +#define CMN_TXPUCAL_OVRD               (0xe1 << ADDR_ADJ)
> +#define CMN_TXPDCAL_OVRD               (0xf1 << ADDR_ADJ)
> +#define CMN_DIAG_PLL0_FBH_OVRD         (0x1c0 << ADDR_ADJ)
> +#define CMN_DIAG_PLL0_FBL_OVRD         (0x1c1 << ADDR_ADJ)
> +#define CMN_DIAG_PLL0_OVRD             (0x1c2 << ADDR_ADJ)
> +#define CMN_DIAG_PLL0_V2I_TUNE         (0x1c5 << ADDR_ADJ)
> +#define CMN_DIAG_PLL0_CP_TUNE          (0x1c6 << ADDR_ADJ)
> +#define CMN_DIAG_PLL0_LF_PROG          (0x1c7 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_FBH_OVRD         (0x1d0 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_FBL_OVRD         (0x1d1 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_OVRD             (0x1d2 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_V2I_TUNE         (0x1d5 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_CP_TUNE          (0x1d6 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_LF_PROG          (0x1d7 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_PTATIS_TUNE1     (0x1d8 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_PTATIS_TUNE2     (0x1d9 << ADDR_ADJ)
> +#define CMN_DIAG_PLL1_INCLK_CTRL       (0x1da << ADDR_ADJ)
> +#define CMN_DIAG_HSCLK_SEL             (0x1e0 << ADDR_ADJ)
> +
> +#define XCVR_PSM_RCTRL(n)              ((0x4001 | (n << 9)) << ADDR_ADJ)
> +#define XCVR_PSM_CAL_TMR(n)            ((0x4002 | (n << 9)) << ADDR_ADJ)
> +#define XCVR_PSM_A0IN_TMR(n)           ((0x4003 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_CAL_SCLR_MULT(n)       ((0x4047 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_CPOST_MULT_00(n)       ((0x404c | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_CPOST_MULT_01(n)       ((0x404d | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_CPOST_MULT_10(n)       ((0x404e | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_CPOST_MULT_11(n)       ((0x404f | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_000(n)      ((0x4050 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_001(n)      ((0x4051 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_010(n)      ((0x4052 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_011(n)      ((0x4053 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_100(n)      ((0x4054 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_101(n)      ((0x4055 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_110(n)      ((0x4056 | (n << 9)) << ADDR_ADJ)
> +#define TX_TXCC_MGNFS_MULT_111(n)      ((0x4057 | (n << 9)) << ADDR_ADJ)
> +#define XCVR_DIAG_PLLDRC_CTRL(n)       ((0x40e0 | (n << 9)) << ADDR_ADJ)
> +#define XCVR_DIAG_BIDI_CTRL(n)         ((0x40e8 | (n << 9)) << ADDR_ADJ)
> +#define XCVR_DIAG_LANE_FCM_EN_MGN(n)   ((0x40f2 | (n << 9)) << ADDR_ADJ)
> +#define TX_PSC_A0(n)                   ((0x4100 | (n << 9)) << ADDR_ADJ)
> +#define TX_PSC_A1(n)                   ((0x4101 | (n << 9)) << ADDR_ADJ)
> +#define TX_PSC_A2(n)                   ((0x4102 | (n << 9)) << ADDR_ADJ)
> +#define TX_PSC_A3(n)                   ((0x4103 | (n << 9)) << ADDR_ADJ)
> +#define TX_RCVDET_CTRL(n)              ((0x4120 | (n << 9)) << ADDR_ADJ)
> +#define TX_RCVDET_EN_TMR(n)            ((0x4122 | (n << 9)) << ADDR_ADJ)
> +#define TX_RCVDET_ST_TMR(n)            ((0x4123 | (n << 9)) << ADDR_ADJ)
> +#define TX_DIAG_TX_DRV(n)              ((0x41e1 | (n << 9)) << ADDR_ADJ)
> +#define TX_DIAG_BGREF_PREDRV_DELAY     (0x41e7 << ADDR_ADJ)
> +#define TX_ANA_CTRL_REG_1              (0x5020 << ADDR_ADJ)
> +#define TX_ANA_CTRL_REG_2              (0x5021 << ADDR_ADJ)
> +#define TXDA_COEFF_CALC_CTRL           (0x5022 << ADDR_ADJ)
> +#define TX_DIG_CTRL_REG_2              (0x5024 << ADDR_ADJ)
> +#define TXDA_CYA_AUXDA_CYA             (0x5025 << ADDR_ADJ)
> +#define TX_ANA_CTRL_REG_3              (0x5026 << ADDR_ADJ)
> +#define TX_ANA_CTRL_REG_4              (0x5027 << ADDR_ADJ)
> +#define TX_ANA_CTRL_REG_5              (0x5029 << ADDR_ADJ)
> +
> +#define RX_PSC_A0(n)                   ((0x8000 | (n << 9)) << ADDR_ADJ)
> +#define RX_PSC_A1(n)                   ((0x8001 | (n << 9)) << ADDR_ADJ)
> +#define RX_PSC_A2(n)                   ((0x8002 | (n << 9)) << ADDR_ADJ)
> +#define RX_PSC_A3(n)                   ((0x8003 | (n << 9)) << ADDR_ADJ)
> +#define RX_PSC_CAL(n)                  ((0x8006 | (n << 9)) << ADDR_ADJ)
> +#define RX_PSC_RDY(n)                  ((0x8007 | (n << 9)) << ADDR_ADJ)
> +#define RX_IQPI_ILL_CAL_OVRD           (0x8023 << ADDR_ADJ)
> +#define RX_EPI_ILL_CAL_OVRD            (0x8033 << ADDR_ADJ)
> +#define RX_SDCAL0_OVRD                 (0x8041 << ADDR_ADJ)
> +#define RX_SDCAL1_OVRD                 (0x8049 << ADDR_ADJ)
> +#define RX_SLC_INIT                    (0x806d << ADDR_ADJ)
> +#define RX_SLC_RUN                     (0x806e << ADDR_ADJ)
> +#define RX_CDRLF_CNFG2                 (0x8081 << ADDR_ADJ)
> +#define RX_SIGDET_HL_FILT_TMR(n)       ((0x8090 | (n << 9)) << ADDR_ADJ)
> +#define RX_SLC_IOP0_OVRD               (0x8101 << ADDR_ADJ)
> +#define RX_SLC_IOP1_OVRD               (0x8105 << ADDR_ADJ)
> +#define RX_SLC_QOP0_OVRD               (0x8109 << ADDR_ADJ)
> +#define RX_SLC_QOP1_OVRD               (0x810d << ADDR_ADJ)
> +#define RX_SLC_EOP0_OVRD               (0x8111 << ADDR_ADJ)
> +#define RX_SLC_EOP1_OVRD               (0x8115 << ADDR_ADJ)
> +#define RX_SLC_ION0_OVRD               (0x8119 << ADDR_ADJ)
> +#define RX_SLC_ION1_OVRD               (0x811d << ADDR_ADJ)
> +#define RX_SLC_QON0_OVRD               (0x8121 << ADDR_ADJ)
> +#define RX_SLC_QON1_OVRD               (0x8125 << ADDR_ADJ)
> +#define RX_SLC_EON0_OVRD               (0x8129 << ADDR_ADJ)
> +#define RX_SLC_EON1_OVRD               (0x812d << ADDR_ADJ)
> +#define RX_SLC_IEP0_OVRD               (0x8131 << ADDR_ADJ)
> +#define RX_SLC_IEP1_OVRD               (0x8135 << ADDR_ADJ)
> +#define RX_SLC_QEP0_OVRD               (0x8139 << ADDR_ADJ)
> +#define RX_SLC_QEP1_OVRD               (0x813d << ADDR_ADJ)
> +#define RX_SLC_EEP0_OVRD               (0x8141 << ADDR_ADJ)
> +#define RX_SLC_EEP1_OVRD               (0x8145 << ADDR_ADJ)
> +#define RX_SLC_IEN0_OVRD               (0x8149 << ADDR_ADJ)
> +#define RX_SLC_IEN1_OVRD               (0x814d << ADDR_ADJ)
> +#define RX_SLC_QEN0_OVRD               (0x8151 << ADDR_ADJ)
> +#define RX_SLC_QEN1_OVRD               (0x8155 << ADDR_ADJ)
> +#define RX_SLC_EEN0_OVRD               (0x8159 << ADDR_ADJ)
> +#define RX_SLC_EEN1_OVRD               (0x815d << ADDR_ADJ)
> +#define RX_DIAG_SIGDET_TUNE(n)         ((0x81dc | (n << 9)) << ADDR_ADJ)
> +#define RX_DIAG_SC2C_DELAY             (0x81e1 << ADDR_ADJ)
> +
> +#define PMA_LANE_CFG                   (0xc000 << ADDR_ADJ)
> +#define PIPE_CMN_CTRL1                 (0xc001 << ADDR_ADJ)
> +#define PIPE_CMN_CTRL2                 (0xc002 << ADDR_ADJ)
> +#define PIPE_COM_LOCK_CFG1             (0xc003 << ADDR_ADJ)
> +#define PIPE_COM_LOCK_CFG2             (0xc004 << ADDR_ADJ)
> +#define PIPE_RCV_DET_INH               (0xc005 << ADDR_ADJ)
> +#define DP_MODE_CTL                    (0xc008 << ADDR_ADJ)
> +#define DP_CLK_CTL                     (0xc009 << ADDR_ADJ)
> +#define STS                            (0xc00F << ADDR_ADJ)
> +#define PHY_ISO_CMN_CTRL               (0xc010 << ADDR_ADJ)
> +#define PHY_DP_TX_CTL                  (0xc408 << ADDR_ADJ)
> +#define PMA_CMN_CTRL1                  (0xc800 << ADDR_ADJ)
> +#define PHY_PMA_ISO_CMN_CTRL           (0xc810 << ADDR_ADJ)
> +#define PHY_ISOLATION_CTRL             (0xc81f << ADDR_ADJ)
> +#define PHY_PMA_ISO_XCVR_CTRL(n)       ((0xcc11 | (n << 6)) << ADDR_ADJ)
> +#define PHY_PMA_ISO_LINK_MODE(n)       ((0xcc12 | (n << 6)) << ADDR_ADJ)
> +#define PHY_PMA_ISO_PWRST_CTRL(n)      ((0xcc13 | (n << 6)) << ADDR_ADJ)
> +#define PHY_PMA_ISO_TX_DATA_LO(n)      ((0xcc14 | (n << 6)) << ADDR_ADJ)
> +#define PHY_PMA_ISO_TX_DATA_HI(n)      ((0xcc15 | (n << 6)) << ADDR_ADJ)
> +#define PHY_PMA_ISO_RX_DATA_LO(n)      ((0xcc16 | (n << 6)) << ADDR_ADJ)
> +#define PHY_PMA_ISO_RX_DATA_HI(n)      ((0xcc17 | (n << 6)) << ADDR_ADJ)
> +#define TX_BIST_CTRL(n)                        ((0x4140 | (n << 9)) << ADDR_ADJ)
> +#define TX_BIST_UDDWR(n)               ((0x4141 | (n << 9)) << ADDR_ADJ)
> +
> +#define GRF_SOC_CON26                  0x6268
> +#define UPHY_DP_SEL                    BIT(3)
> +#define UPHY_DP_SEL_MASK               BIT(19)
> +#define DPTX_HDP_SEL                   (3 << 12)
> +#define DPTX_HDP_SEL_MASK              (3 << 28)
> +
> +#define PHY_MODE_SET_TIMEOUT           1000000
> +
> +#define        MODE_DISCONNECT                 1
> +#define        MODE_UFP                        2
> +#define        MODE_DFP_USBONLY                3
> +#define        MODE_DFP_DPONLY                 4
> +#define        MODE_DFP_USB3DP                 5
> +#define        MODE_DFP_USB2DP                 6
> +
> +#define PARSE_GRF_REG(TYPE) { \
> +       if (of_find_property(np, "rockchip,usb3phy_"#TYPE, &len)) { \
> +               len /= sizeof(u32);\
> +               ret = of_property_read_u32_array(np, "rockchip,usb3phy_" #TYPE,\
> +                                                array, len); \
> +               exregs->usb3phy_##TYPE = array[0]; \
> +               exregs->usb3phy_##TYPE##_shift = array[1]; \
> +               exregs->usb3phy_##TYPE##_mask = array[2]; \
> +               pr_info("%s property found %s, %x, %d, %d\n", __func__, \
> +                       "rockchip,usb3phy_"#TYPE, \
> +                       array[0], array[1], array[2]); \
> +       } else { \
> +               pr_info("%s property not found %s\n", __func__, \
> +                       "rockchip,usb3phy_" #TYPE); \
> +       } \
> +}
> +
> +struct rockchip_typec_phy *rockchip_tcphy;

Unused global?

> +
> +static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy,
> +                         unsigned int num_lanes)
> +{
> +       unsigned int i;()?
> +
> +       writel(0x830, tcphy->base + PMA_CMN_CTRL1);
> +       for (i = 0; i < num_lanes; i++) {
> +               writel(0x90, tcphy->base + XCVR_DIAG_LANE_FCM_EN_MGN(i));
> +               writel(0x960, tcphy->base + TX_RCVDET_EN_TMR(i));
> +               writel(0x30, tcphy->base + TX_RCVDET_ST_TMR(i));

Would it be too much to ask to get more details about all these magic values?

> +       }
> +}
> +
> +static void tcphy_cfg_usb_pll(struct rockchip_typec_phy *tcphy)
> +{
> +       unsigned int rdata;
> +
> +       rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
> +       writel(rdata & 0xfffc, tcphy->base + CMN_DIAG_HSCLK_SEL);
> +       writel(0xf0, tcphy->base + CMN_PLL0_VCOCAL_INIT);
> +       writel(0x18, tcphy->base + CMN_PLL0_VCOCAL_ITER);
> +       writel(0xd0, tcphy->base + CMN_PLL0_INTDIV);
> +       writel(0x4a4a, tcphy->base + CMN_PLL0_FRACDIV);
> +       writel(0x34, tcphy->base + CMN_PLL0_HIGH_THR);
> +       writel(0x1ee, tcphy->base + CMN_PLL0_SS_CTRL1);
> +       writel(0x7f03, tcphy->base + CMN_PLL0_SS_CTRL2);
> +       writel(0x20, tcphy->base + CMN_PLL0_DSM_DIAG);
> +       writel(0, tcphy->base + CMN_DIAG_PLL0_OVRD);
> +       writel(0, tcphy->base + CMN_DIAG_PLL0_FBH_OVRD);
> +       writel(0, tcphy->base + CMN_DIAG_PLL0_FBL_OVRD);
> +       writel(0x7, tcphy->base + CMN_DIAG_PLL0_V2I_TUNE);
> +       writel(0x45, tcphy->base + CMN_DIAG_PLL0_CP_TUNE);
> +       writel(0x8, tcphy->base + CMN_DIAG_PLL0_LF_PROG);
> +}
> +
> +static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy)
> +{
> +       unsigned int rdata;
> +
> +       writel(0x2405, tcphy->base + DP_CLK_CTL);
> +
> +       rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
> +       rdata = (rdata & 0xffcf) | 0x30;
> +       writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL);
> +       writel(0xf0, tcphy->base + CMN_PLL1_VCOCAL_INIT);
> +       writel(0x18, tcphy->base + CMN_PLL1_VCOCAL_ITER);
> +       writel(0x30b9, tcphy->base + CMN_PLL1_VCOCAL_START);
> +       writel(0x21c, tcphy->base + CMN_PLL1_INTDIV);
> +       writel(0, tcphy->base + CMN_PLL1_FRACDIV);
> +       writel(0x5, tcphy->base + CMN_PLL1_HIGH_THR);
> +       writel(0x35, tcphy->base + CMN_PLL1_SS_CTRL1);
> +       writel(0x7f1e, tcphy->base + CMN_PLL1_SS_CTRL2);
> +       writel(0x20, tcphy->base + CMN_PLL1_DSM_DIAG);
> +       writel(0, tcphy->base + CMN_PLLSM1_USER_DEF_CTRL);
> +       writel(0, tcphy->base + CMN_DIAG_PLL1_OVRD);
> +       writel(0, tcphy->base + CMN_DIAG_PLL1_FBH_OVRD);
> +       writel(0, tcphy->base + CMN_DIAG_PLL1_FBL_OVRD);
> +       writel(0x6, tcphy->base + CMN_DIAG_PLL1_V2I_TUNE);
> +       writel(0x45, tcphy->base + CMN_DIAG_PLL1_CP_TUNE);
> +       writel(0x8, tcphy->base + CMN_DIAG_PLL1_LF_PROG);
> +       writel(0x100, tcphy->base + CMN_DIAG_PLL1_PTATIS_TUNE1);
> +       writel(0x7, tcphy->base + CMN_DIAG_PLL1_PTATIS_TUNE2);
> +       writel(0x4, tcphy->base + CMN_DIAG_PLL1_INCLK_CTRL);
> +}
> +
> +static void tcphy_tx_usb_cfg_lane(struct rockchip_typec_phy *tcphy,
> +                                 unsigned int lane)
> +{
> +       writel(0x7799, tcphy->base + TX_PSC_A0(lane));
> +       writel(0x7798, tcphy->base + TX_PSC_A1(lane));
> +       writel(0x5098, tcphy->base + TX_PSC_A2(lane));
> +       writel(0x5098, tcphy->base + TX_PSC_A3(lane));
> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
> +       writel(0xbf, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
> +}
> +
> +static void tcphy_rx_usb_cfg_lane(struct rockchip_typec_phy *tcphy,
> +                                 unsigned int lane)
> +{
> +       writel(0xa6fd, tcphy->base + RX_PSC_A0(lane));
> +       writel(0xa6fd, tcphy->base + RX_PSC_A1(lane));
> +       writel(0xa410, tcphy->base + RX_PSC_A2(lane));
> +       writel(0x2410, tcphy->base + RX_PSC_A3(lane));
> +       writel(0x23ff, tcphy->base + RX_PSC_CAL(lane));
> +       writel(0x13, tcphy->base + RX_SIGDET_HL_FILT_TMR(lane));
> +       writel(0x1004, tcphy->base + RX_DIAG_SIGDET_TUNE(lane));
> +       writel(0x2010, tcphy->base + RX_PSC_RDY(lane));
> +       writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
> +}
> +
> +static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy,
> +                             unsigned int lane)
> +{
> +       unsigned int rdata;
> +
> +       writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
> +       writel(0x6799, tcphy->base + TX_PSC_A0(lane));
> +       writel(0x6798, tcphy->base + TX_PSC_A1(lane));
> +       writel(0x98, tcphy->base + TX_PSC_A2(lane));
> +       writel(0x98, tcphy->base + TX_PSC_A3(lane));
> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane));
> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane));
> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane));
> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane));
> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane));
> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane));
> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane));
> +
> +       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane));
> +       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane));
> +       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
> +       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane));
> +
> +       writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
> +       writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
> +
> +       rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
> +       rdata = (rdata & 0x8fff) | 0x6000;
> +       writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
> +}
> +
> +static void tcphy_cfg_pin_assign(struct rockchip_typec_phy *tcphy)
> +{
> +       switch (tcphy->map) {
> +       case PIN_MAP_A:
> +               writel(0x19d5, tcphy->base + PMA_LANE_CFG);
> +               break;
> +       case PIN_MAP_B:
> +               writel(0x1500, tcphy->base + PMA_LANE_CFG);
> +               break;
> +       case PIN_MAP_C:
> +       case PIN_MAP_E:
> +               writel(0x51d9, tcphy->base + PMA_LANE_CFG);
> +               break;
> +       case PIN_MAP_D:
> +       case PIN_MAP_F:
> +               writel(0x5100, tcphy->base + PMA_LANE_CFG);
> +               break;
> +       };
> +}
> +
> +static void tcphy_cfg_lanes(struct rockchip_typec_phy *tcphy,
> +                           unsigned int link_cfg)
> +{
> +       unsigned int i;
> +
> +       /* PMA lane configuration DP or USB3 */
> +       for (i = 0; i < 4; i++) {
> +               if ((link_cfg >> i) & 0x1) {
> +                       tcphy_dp_cfg_lane(tcphy, i);
> +               } else {
> +                       /*
> +                        * lan0 TX and lan1 RX for USB3 Normal direction
> +                        * lan3 TX and lan2 RX for USB3 Flip direction
> +                        */
> +                       if ((i == 0) | (i == 3))
> +                               tcphy_tx_usb_cfg_lane(tcphy, i);
> +                       else
> +                               tcphy_rx_usb_cfg_lane(tcphy, i);
> +               }
> +       }
> +}
> +
> +static void tcphy_cfg_flip_set(struct rockchip_typec_phy *tcphy)
> +{
> +       regmap_write(tcphy->grf_regs,
> +                    tcphy->exregs.usb3phy_con0,
> +                    tcphy->flip | BIT(16));
> +
> +       tcphy_cfg_24m(tcphy, 0x4);
> +
> +       if (tcphy->mode == MODE_UFP ||
> +           tcphy->mode == MODE_DFP_USBONLY ||
> +           tcphy->mode == MODE_DFP_USB3DP)
> +               tcphy_cfg_usb_pll(tcphy);
> +
> +       if (tcphy->mode == MODE_DFP_DPONLY ||
> +           tcphy->mode == MODE_DFP_USB2DP ||
> +           tcphy->mode == MODE_DFP_USB3DP)
> +               tcphy_cfg_dp_pll(tcphy);
> +
> +       if (tcphy->mode == MODE_DFP_DPONLY || tcphy->mode == MODE_DFP_USB2DP)
> +               tcphy_cfg_lanes(tcphy, 0xf);
> +       else if (tcphy->flip)
> +               tcphy_cfg_lanes(tcphy, 0x3);
> +       else
> +               tcphy_cfg_lanes(tcphy, 0xc);
> +}
> +
> +static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
> +{
> +       int rdata, rdata2, val;
> +
> +       rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
> +       rdata2 = readl(tcphy->base + CMN_TXPUCAL_CTRL);
> +
> +       rdata = rdata & 0xdfff;
> +       writel(rdata, tcphy->base + TX_ANA_CTRL_REG_1);
> +
> +       rdata = readl(tcphy->base + TX_DIG_CTRL_REG_2);
> +       rdata = rdata & 0xffc0;
> +       rdata2 = rdata2 & 0x3f;
> +       rdata  = rdata | rdata2;
> +       writel(rdata, tcphy->base + TX_DIG_CTRL_REG_2);
> +       usleep_range(1000, 2000);

nit: this is at init time and will be run once.  Power savings of
trying to group wakeups will be minimal or none.  Last I looked
usleep_range() nearly always takes the longer of the two times unless
it happens to wake up anyway.  Make the range smaller and boot time
will be 1ms faster.  Try usleep_range(1000, 1050).

> +
> +       rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
> +       rdata = rdata | 0x2000;
> +       writel(rdata, tcphy->base + TX_ANA_CTRL_REG_1);
> +
> +       usleep_range(150, 200);
> +
> +       writel(0, tcphy->base + PHY_DP_TX_CTL);
> +       writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2);
> +       writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2);
> +       writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
> +       writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1);
> +       writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1);
> +       writel(0x30C, tcphy->base + TX_ANA_CTRL_REG_2);
> +       writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
> +       writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4);
> +       writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1);
> +       writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1);
> +       writel(0x30d, tcphy->base + TX_ANA_CTRL_REG_2);
> +       writel(0x30f, tcphy->base + TX_ANA_CTRL_REG_2);
> +
> +       if (tcphy->flip)
> +               writel(0xa078, tcphy->base + TX_ANA_CTRL_REG_1);
> +       else
> +               writel(0xb078, tcphy->base + TX_ANA_CTRL_REG_1);
> +
> +       writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2);
> +       writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
> +       writel(0, tcphy->base + TX_ANA_CTRL_REG_4);
> +       writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
> +       writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL);
> +       writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA);
> +
> +       val = readl(tcphy->base + TX_DIG_CTRL_REG_2);
> +       val |= BIT(15);
> +       writel(val, tcphy->base + TX_DIG_CTRL_REG_2);
> +}
> +
> +static void tcphy_dp_hpd(struct rockchip_typec_phy *tcphy,
> +                        u8 mode)
> +{
> +       /* force hpd */
> +       if (mode)
> +               regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
> +                            DPTX_HDP_SEL_MASK | DPTX_HDP_SEL);
> +       else
> +               regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
> +                            DPTX_HDP_SEL_MASK);
> +}
> +
> +static int tcphy_usb3_init(struct rockchip_typec_phy *tcphy)
> +{
> +       int timeout = 0;
> +       int ret, val;
> +
> +       /*wait TCPHY for pipe ready */
> +       while (1) {
> +               ret = regmap_read(tcphy->grf_regs,
> +                                 tcphy->exregs.usb3phy_status0, &val);
> +               val >>= tcphy->exregs.usb3phy_status0_shift;
> +               if ((val & 0x1) == 0)
> +                       break;
> +
> +               timeout++;
> +               if (timeout > 1000) {
> +                       pr_warn("%s wait pipe ready timerout!\n", __func__);
> +                       break;
> +               }
> +               usleep_range(10, 20);
> +       }
> +
> +       return 0;
> +}
> +
> +static int tcphy_dp_init(struct rockchip_typec_phy *tcphy)
> +{
> +       int ret, val;
> +
> +       ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
> +                                val, val & BIT(6), 1000, PHY_MODE_SET_TIMEOUT);
> +       if (ret < 0) {
> +               dev_err(tcphy->dev, "failed to wait TCPHY for DP ready\n");
> +               return -EBUSY;
> +       }
> +
> +       tcphy_dp_aux_calibration(tcphy);
> +
> +       if (tcphy->mode == MODE_DFP_USB3DP)
> +               writel(0xc101, tcphy->base + DP_MODE_CTL);
> +       else
> +               writel(0x0101, tcphy->base + DP_MODE_CTL);
> +
> +       ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
> +                                val, val & BIT(4), 1000, PHY_MODE_SET_TIMEOUT);
> +       if (ret < 0) {
> +               dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
> +               return -EBUSY;
> +       }
> +
> +       return 0;
> +}
> +
> +static int tcphy_phy_init(struct rockchip_typec_phy *tcphy)
> +{
> +       int ret;
> +       int timeout = 0;
> +
> +       ret = clk_prepare_enable(tcphy->clk_core);
> +       if (ret) {
> +               dev_err(tcphy->dev, "Failed to prepare_enable core clock\n");
> +               return ret;
> +       }
> +
> +       ret = clk_prepare_enable(tcphy->clk_ref);
> +       if (ret) {
> +               dev_err(tcphy->dev, "Failed to prepare_enable ref clock\n");
> +               return ret;
> +       }
> +
> +       /* select external psm clock */
> +       regmap_write(tcphy->grf_regs, tcphy->exregs.usb3phy_con2,
> +                    BIT(14) | BIT(30));
> +       regmap_write(tcphy->grf_regs, tcphy->exregs.usb3phy_con0, BIT(19));
> +
> +       reset_control_assert(tcphy->phy_rst);
> +       reset_control_assert(tcphy->pipe_rst);
> +       reset_control_assert(tcphy->uphy_rst);
> +
> +       if (tcphy->num == TYPEC_PHY0)
> +               regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
> +                            UPHY_DP_SEL_MASK);
> +       else
> +               regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
> +                            UPHY_DP_SEL_MASK | UPHY_DP_SEL);
> +
> +       reset_control_deassert(tcphy->uphy_rst);
> +
> +       tcphy_cfg_flip_set(tcphy);
> +
> +       tcphy_cfg_pin_assign(tcphy);
> +
> +       if (tcphy->mode == MODE_DFP_USB3DP)
> +               writel(0xc104, tcphy->base + DP_MODE_CTL);
> +       else if ((tcphy->mode == MODE_DFP_DPONLY) ||
> +                (tcphy->mode == MODE_DFP_USB2DP))
> +               writel(0x0104, tcphy->base + DP_MODE_CTL);
> +
> +       reset_control_deassert(tcphy->phy_rst);
> +
> +       while (!(readl(tcphy->base + PMA_CMN_CTRL1) & 1)) {
> +               timeout++;
> +               if (timeout > 1000)
> +                       break;
> +               usleep_range(10, 20);
> +       }
> +
> +       reset_control_deassert(tcphy->pipe_rst);
> +
> +       return 0;
> +}
> +
> +static int tcphy_phy_deinit(struct rockchip_typec_phy *tcphy)
> +{
> +       clk_disable_unprepare(tcphy->clk_core);
> +       clk_disable_unprepare(tcphy->clk_ref);
> +
> +       return 0;
> +}
> +
> +int tcphy_register_notifier(struct phy *_phy, struct notifier_block *nb)

Is there a reason this isn't static?

> +{
> +       struct rockchip_typec_phy *tcphy = phy_get_drvdata(_phy);
> +
> +       return atomic_notifier_chain_register(&tcphy->notifier, nb);
> +}
> +
> +void tcphy_unregister_notifier(struct phy *_phy,
> +                              struct notifier_block *nb)

Is there a reason this isn't static?

> +{
> +       struct rockchip_typec_phy *tcphy = phy_get_drvdata(_phy);
> +
> +       atomic_notifier_chain_unregister(&tcphy->notifier, nb);
> +}
> +
> +void tcphy_notifier_call_chain(struct rockchip_typec_phy *x,
> +                              unsigned long val, void *v)
> +{
> +       atomic_notifier_call_chain(&x->notifier, val, v);
> +}
> +EXPORT_SYMBOL_GPL(tcphy_notifier_call_chain);
> +
> +static int tcphy_pd_event(struct notifier_block *nb,
> +                         unsigned long event, void *priv)
> +{
> +       struct rockchip_typec_phy *tcphy;
> +       int value = *(int *)priv;
> +       u8 is_dp, dfp;
> +
> +       tcphy = container_of(nb, struct rockchip_typec_phy, event_nb);
> +       if (IS_ERR_OR_NULL(tcphy)) {
> +               pr_err("initialization issue");
> +               return -1;
> +       }
> +
> +       tcphy->flip = GET_FLIP(value);
> +       dfp = GET_DFP(value);
> +       is_dp = GET_DP(value);
> +       tcphy->map = GET_PIN_MAP(value);
> +
> +       if (event == 0) {
> +               if (tcphy->mode == MODE_DISCONNECT)
> +                       return 0;
> +               tcphy->mode = MODE_DISCONNECT;
> +       } else if (is_dp) {
> +               if (tcphy->map & (PIN_MAP_B | PIN_MAP_D | PIN_MAP_F))
> +                       tcphy->mode = MODE_DFP_USB3DP;
> +               else
> +                       tcphy->mode = MODE_DFP_DPONLY;
> +       } else if (dfp) {
> +               tcphy->mode = MODE_DFP_USBONLY;
> +       } else {
> +               tcphy->mode = MODE_UFP;
> +       }
> +
> +       schedule_delayed_work_on(0, &tcphy->event_wq, 0);
> +
> +       return 0;
> +}
> +
> +static void tcphy_event_wq(struct work_struct *work)
> +{
> +       struct rockchip_typec_phy *tcphy;
> +
> +       tcphy = container_of(work, struct rockchip_typec_phy, event_wq.work);
> +       if (IS_ERR_OR_NULL(tcphy)) {
> +               pr_err("initialization issue");
> +               return;
> +       }
> +
> +       switch (tcphy->mode) {
> +       case MODE_DISCONNECT:
> +               /* phy enter low power mode */
> +               tcphy_phy_deinit(tcphy);
> +               tcphy_dp_hpd(tcphy, 0);
> +               break;
> +       case MODE_UFP:
> +               tcphy_phy_init(tcphy);
> +               tcphy_usb3_init(tcphy);
> +               tcphy_dp_hpd(tcphy, 0);
> +               break;
> +       case MODE_DFP_USBONLY:
> +               tcphy_phy_init(tcphy);
> +               tcphy_usb3_init(tcphy);
> +               tcphy_dp_hpd(tcphy, 0);
> +               break;
> +       case MODE_DFP_DPONLY:
> +       case MODE_DFP_USB2DP:
> +               tcphy_phy_init(tcphy);
> +               tcphy_dp_init(tcphy);
> +               tcphy_dp_hpd(tcphy, 1);
> +               break;
> +       case MODE_DFP_USB3DP:
> +               tcphy_phy_init(tcphy);
> +               tcphy_usb3_init(tcphy);
> +               tcphy_dp_init(tcphy);
> +               tcphy_dp_hpd(tcphy, 1);
> +               break;
> +       }
> +}
> +
> +int tcphy_parse_reg(struct rockchip_typec_phy *tcphy, struct device *dev)
> +{
> +       struct tcphy_grf_reg *exregs = &tcphy->exregs;
> +       struct device_node *np = dev->of_node;
> +       u32 len = 0, array[3];
> +       int ret = 0;
> +
> +       PARSE_GRF_REG(con0);
> +       PARSE_GRF_REG(con1);
> +       PARSE_GRF_REG(con2);
> +       PARSE_GRF_REG(status0);
> +       PARSE_GRF_REG(status1);
> +       return ret;
> +}
> +
> +static int rockchip_typec_phy_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct rockchip_typec_phy *tcphy;
> +       struct resource *res;
> +       struct phy_provider *phy_provider;
> +
> +       tcphy = devm_kzalloc(dev, sizeof(*tcphy), GFP_KERNEL);
> +       if (!tcphy)
> +               return -ENOMEM;
> +
> +       tcphy->dev = dev;
> +       platform_set_drvdata(pdev, tcphy);
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       tcphy->base = devm_ioremap_resource(dev, res);
> +       if (IS_ERR(tcphy->base)) {
> +               dev_err(dev, "failed to remap phy regs\n");
> +               return PTR_ERR(tcphy->base);
> +       }
> +       tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node,
> +                                                       "rockchip,grf");
> +       if (IS_ERR(tcphy->grf_regs)) {
> +               dev_err(dev, "%s: could not find grf dt node\n", __func__);
> +               return PTR_ERR(tcphy->grf_regs);
> +       }
> +
> +       tcphy->clk_core = of_clk_get_by_name(dev->of_node, "tcpdcore");
> +       if (IS_ERR(tcphy->clk_core)) {
> +               dev_err(dev, "%s: could not get uphy core clock\n", __func__);

nit: No real need for __func__.  That's useful to add in when you
don't have a "dev" pointer and need a "pr_err" to show something that
will help the user find the right line of code.

> +               tcphy->clk_core = NULL;

So is tcpdcore optional or required?  Bindings doc says "required" and
the "dev_err" above implies required.  ...but then you don't return an
error code.  That makes it optional.  ...but then you use it
unconditional elsewhere in this file.  That makes it required.

Summary: return an error here, don't just set to NULL.

> +       }
> +
> +       tcphy->clk_ref = of_clk_get_by_name(dev->of_node, "tcpdphy_ref");
> +       if (IS_ERR(tcphy->clk_core)) {
> +               dev_err(dev, "%s: could not get uphy ref clock\n", __func__);
> +               tcphy->clk_core = NULL;

"if" test and NULL assignment are for wrong variables.

> +       }
> +
> +       tcphy->phy_rst = devm_reset_control_get(dev, "tcphy_rst");
> +       if (IS_ERR(tcphy->phy_rst)) {
> +               dev_err(dev, "no phy_rst reset control found\n");
> +               return PTR_ERR(tcphy->phy_rst);
> +       }
> +
> +       tcphy->pipe_rst = devm_reset_control_get(dev, "tcphy_pipe_rst");
> +       if (IS_ERR(tcphy->pipe_rst)) {
> +               dev_err(dev, "no pipe_rst reset control found\n");
> +               return PTR_ERR(tcphy->pipe_rst);
> +       }
> +
> +       tcphy->uphy_rst = devm_reset_control_get(dev, "uphy_tcphy_rst");
> +       if (IS_ERR(tcphy->uphy_rst)) {
> +               dev_err(dev, "no uphy_rst reset control found\n");
> +               return PTR_ERR(tcphy->uphy_rst);
> +       }
> +
> +       tcphy_parse_reg(tcphy, dev);
> +       tcphy->mode = MODE_DISCONNECT;
> +
> +       tcphy->phy = devm_phy_create(dev, NULL, NULL);
> +
> +       phy_set_drvdata(tcphy->phy, tcphy);
> +
> +       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> +       /* register notifier for PD event */
> +       ATOMIC_INIT_NOTIFIER_HEAD(&tcphy->notifier);
> +       tcphy->event_nb.notifier_call = tcphy_pd_event;
> +       INIT_DELAYED_WORK(&tcphy->event_wq, tcphy_event_wq);
> +       tcphy_register_notifier(tcphy->phy, &tcphy->event_nb);
> +
> +       return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static int rockchip_typec_phy_remove(struct platform_device *pdev)
> +{
> +       return 0;
> +}

I believe that if you've got an empty remove function you can just remove it.

...but doesn't remove need to call tcphy_unregister_notifier?


> +
> +static const struct of_device_id rockchip_typec_phy_dt_ids[] = {
> +       { .compatible = "rockchip,rk3399-typec-phy", },
> +       {}
> +};
> +
> +MODULE_DEVICE_TABLE(of, rockchip_typec_phy_dt_ids);
> +
> +static struct platform_driver rockchip_typec_phy_driver = {
> +       .probe          = rockchip_typec_phy_probe,
> +       .remove         = rockchip_typec_phy_remove,
> +       .driver         = {
> +               .name   = "rockchip-typec-phy",
> +               .of_match_table = rockchip_typec_phy_dt_ids,
> +       },
> +};
> +
> +module_platform_driver(rockchip_typec_phy_driver);
> +
> +MODULE_AUTHOR("Kever Yang<kever.yang at rock-chips.com>");

nit: space before "<"

> +MODULE_AUTHOR("Chris Zhong<zyw at rock-chips.com>");
> +MODULE_DESCRIPTION("Rockchip USB TYPE-C PHY driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.6.3
>


From javier at osg.samsung.com  Tue May 31 14:48:00 2016
From: javier at osg.samsung.com (Javier Martinez Canillas)
Date: Tue, 31 May 2016 17:48:00 -0400
Subject: [PATCH] ARM: dts: exynos: Add TMU nodes regulator supply for Peach
 boards
Message-ID: <1464731280-24588-1-git-send-email-javier@osg.samsung.com>

The Exynos5800 Peach Pi and Exynos5420 Peach Pit Chromebooks have the
LDO10 1.8V output connected to the VDD18_TS{01,23,4} Exynos SoC pins.

Add this regulator as the input supply of the Thermal Management Unit
channels and also remove the always-on property since all the devices
using LDO10 as input supply are now defined.

Signed-off-by: Javier Martinez Canillas <javier at osg.samsung.com>
---

 arch/arm/boot/dts/exynos5420-peach-pit.dts | 21 ++++++++++++++++++++-
 arch/arm/boot/dts/exynos5800-peach-pi.dts  | 21 ++++++++++++++++++++-
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
index c1247402cb17..a55760b5fa82 100644
--- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
@@ -425,7 +425,6 @@
 				regulator-name = "vdd_ldo10";
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <1800000>;
-				regulator-always-on;
 				regulator-state-mem {
 					regulator-off-in-suspend;
 				};
@@ -924,6 +923,26 @@
 	assigned-clock-parents = <&clock CLK_FIN_PLL>;
 };
 
+&tmu_cpu0 {
+	vtmu-supply = <&ldo10_reg>;
+};
+
+&tmu_cpu1 {
+	vtmu-supply = <&ldo10_reg>;
+};
+
+&tmu_cpu2 {
+	vtmu-supply = <&ldo10_reg>;
+};
+
+&tmu_cpu3 {
+	vtmu-supply = <&ldo10_reg>;
+};
+
+&tmu_gpu {
+	vtmu-supply = <&ldo10_reg>;
+};
+
 &rtc {
 	status = "okay";
 	clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index af1c9b9a63f9..34cc6cee0cdb 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -425,7 +425,6 @@
 				regulator-name = "vdd_ldo10";
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <1800000>;
-				regulator-always-on;
 				regulator-state-mem {
 					regulator-off-in-suspend;
 				};
@@ -900,6 +899,26 @@
 	assigned-clock-parents = <&clock CLK_FIN_PLL>;
 };
 
+&tmu_cpu0 {
+	vtmu-supply = <&ldo10_reg>;
+};
+
+&tmu_cpu1 {
+	vtmu-supply = <&ldo10_reg>;
+};
+
+&tmu_cpu2 {
+	vtmu-supply = <&ldo10_reg>;
+};
+
+&tmu_cpu3 {
+	vtmu-supply = <&ldo10_reg>;
+};
+
+&tmu_gpu {
+	vtmu-supply = <&ldo10_reg>;
+};
+
 &rtc {
 	status = "okay";
 	clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
-- 
2.5.5



From helgaas at kernel.org  Tue May 31 15:02:24 2016
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Tue, 31 May 2016 17:02:24 -0500
Subject: [PATCH] Revert "ARM: cns3xxx: pci: avoid potential stack overflow"
In-Reply-To: <20160531215802.30590.97398.stgit@bhelgaas-glaptop2.roam.corp.google.com>
References: <20160531215802.30590.97398.stgit@bhelgaas-glaptop2.roam.corp.google.com>
Message-ID: <20160531220224.GA30841@localhost>

[+cc Russell, linux-arm-kernel]

On Tue, May 31, 2016 at 04:58:02PM -0500, Bjorn Helgaas wrote:
> This reverts commit 498a92d42596a7a32c042319eb62a4c3d8081cf1.
> 
> Krzysztof reported that this change broke Cavium CNS3xxx, ARMv6 (Laguna
> GW-2388) because the MRRS setting is never written to the hardware.

Krzysztof, can you test this and see whether it fixes the problem for
you?

> Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
> CC: Arnd Bergmann <arnd at arndb.de>
> CC: Krzysztof Ha?asa <khalasa at piap.pl>
> ---
>  arch/arm/mach-cns3xxx/pcie.c |   71 ++++++++++++++++++++++++------------------
>  1 file changed, 41 insertions(+), 30 deletions(-)
> 
> diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
> index 318394e..c622c30 100644
> --- a/arch/arm/mach-cns3xxx/pcie.c
> +++ b/arch/arm/mach-cns3xxx/pcie.c
> @@ -65,9 +65,8 @@ static void __iomem *cns3xxx_pci_map_bus(struct pci_bus *bus,
>  
>  	/*
>  	 * The CNS PCI bridge doesn't fit into the PCI hierarchy, though
> -	 * we still want to access it.
> -	 * We place the host bridge on bus 0, and the directly connected
> -	 * device on bus 1, slot 0.
> +	 * we still want to access it. For this to work, we must place
> +	 * the first device on the same bus as the CNS PCI bridge.
>  	 */
>  	if (busno == 0) { /* internal PCIe bus, host bridge device */
>  		if (devfn == 0) /* device# and function# are ignored by hw */
> @@ -212,46 +211,58 @@ static void __init cns3xxx_pcie_check_link(struct cns3xxx_pcie *cnspci)
>  	}
>  }
>  
> -static void cns3xxx_write_config(struct cns3xxx_pcie *cnspci,
> -					 int where, int size, u32 val)
> -{
> -	void __iomem *base = cnspci->host_regs + (where & 0xffc);
> -	u32 v;
> -	u32 mask = (0x1ull << (size * 8)) - 1;
> -	int shift = (where % 4) * 8;
> -
> -	v = readl_relaxed(base);
> -
> -	v &= ~(mask << shift);
> -	v |= (val & mask) << shift;
> -
> -	writel_relaxed(v, base);
> -	readl_relaxed(base);
> -}
> -
>  static void __init cns3xxx_pcie_hw_init(struct cns3xxx_pcie *cnspci)
>  {
> +	int port = cnspci->port;
> +	struct pci_sys_data sd = {
> +		.private_data = cnspci,
> +	};
> +	struct pci_bus bus = {
> +		.number = 0,
> +		.ops = &cns3xxx_pcie_ops,
> +		.sysdata = &sd,
> +	};
>  	u16 mem_base  = cnspci->res_mem.start >> 16;
>  	u16 mem_limit = cnspci->res_mem.end   >> 16;
>  	u16 io_base   = cnspci->res_io.start  >> 16;
>  	u16 io_limit  = cnspci->res_io.end    >> 16;
> +	u32 devfn = 0;
> +	u8 tmp8;
> +	u16 pos;
> +	u16 dc;
> +
> +	pci_bus_write_config_byte(&bus, devfn, PCI_PRIMARY_BUS, 0);
> +	pci_bus_write_config_byte(&bus, devfn, PCI_SECONDARY_BUS, 1);
> +	pci_bus_write_config_byte(&bus, devfn, PCI_SUBORDINATE_BUS, 1);
>  
> -	cns3xxx_write_config(cnspci, PCI_PRIMARY_BUS, 1, 0);
> -	cns3xxx_write_config(cnspci, PCI_SECONDARY_BUS, 1, 1);
> -	cns3xxx_write_config(cnspci, PCI_SUBORDINATE_BUS, 1, 1);
> -	cns3xxx_write_config(cnspci, PCI_MEMORY_BASE, 2, mem_base);
> -	cns3xxx_write_config(cnspci, PCI_MEMORY_LIMIT, 2, mem_limit);
> -	cns3xxx_write_config(cnspci, PCI_IO_BASE_UPPER16, 2, io_base);
> -	cns3xxx_write_config(cnspci, PCI_IO_LIMIT_UPPER16, 2, io_limit);
> +	pci_bus_read_config_byte(&bus, devfn, PCI_PRIMARY_BUS, &tmp8);
> +	pci_bus_read_config_byte(&bus, devfn, PCI_SECONDARY_BUS, &tmp8);
> +	pci_bus_read_config_byte(&bus, devfn, PCI_SUBORDINATE_BUS, &tmp8);
> +
> +	pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_BASE, mem_base);
> +	pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_LIMIT, mem_limit);
> +	pci_bus_write_config_word(&bus, devfn, PCI_IO_BASE_UPPER16, io_base);
> +	pci_bus_write_config_word(&bus, devfn, PCI_IO_LIMIT_UPPER16, io_limit);
>  
>  	if (!cnspci->linked)
>  		return;
>  
>  	/* Set Device Max_Read_Request_Size to 128 byte */
> -	pcie_bus_config = PCIE_BUS_PEER2PEER;
> -
> +	bus.number = 1; /* directly connected PCIe device */
> +	devfn = PCI_DEVFN(0, 0);
> +	pos = pci_bus_find_capability(&bus, devfn, PCI_CAP_ID_EXP);
> +	pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc);
> +	if (dc & PCI_EXP_DEVCTL_READRQ) {
> +		dc &= ~PCI_EXP_DEVCTL_READRQ;
> +		pci_bus_write_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, dc);
> +		pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc);
> +		if (dc & PCI_EXP_DEVCTL_READRQ)
> +			pr_warn("PCIe: Unable to set device Max_Read_Request_Size\n");
> +		else
> +			pr_info("PCIe: Max_Read_Request_Size set to 128 bytes\n");
> +	}
>  	/* Disable PCIe0 Interrupt Mask INTA to INTD */
> -	__raw_writel(~0x3FFF, MISC_PCIE_INT_MASK(cnspci->port));
> +	__raw_writel(~0x3FFF, MISC_PCIE_INT_MASK(port));
>  }
>  
>  static int cns3xxx_pcie_abort_handler(unsigned long addr, unsigned int fsr,
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From sergei.shtylyov at cogentembedded.com  Tue May 31 15:06:37 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Wed, 01 Jun 2016 01:06:37 +0300
Subject: [PATCH 00/13] Add R8A7794/SILK board eMMC DT support
Message-ID: <13205049.n7pM8utpHF@wasted.cogentembedded.com>

Hello.

   Here's the set of 13 patches against Simon Horman's 'renesas.git' repo,
'renesas-devel-20160530-v4.7-rc1' tag. We add the device tree support for
the R8A7792-based Blanche board. The R-Car 'clk' driver patch was posted last
week separately...

[01/13] ARM: shmobile: r8a7792: add clock index macros
[02/13] ARM: shmobile: r8a7792: add power domain index macros
[03/13] soc: renesas: rcar-sysc: add R8A7792 support
[04/13] ARM: shmobile: r8a7792: basic SoC support
[05/13] DT: clock: rcar-gen2-cpg-clocks: document R8A7792 support
[06/13] DT: clock: cpg-mstp-clocks: document-R8A7792-support
[07/13] ARM: dts: r8a7792: initial SoC device tree
[08/13] ARM: dts: r8a7792: add SYS-DMAC support
[09/13] ARM: dts: r8a7792: add [H]SCIF support
[10/13] ARM dts: r8a7792: add IRQC support
[11/13] DT: arm: shmobile: document Blanche board
[12/13] ARM: dts: blanche: initial device tree
[13/13] ARM: dts: blanche: add Ethernet support

WBR, Sergei



From sergei.shtylyov at cogentembedded.com  Tue May 31 15:18:22 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Wed, 01 Jun 2016 01:18:22 +0300
Subject: [PATCH 04/13] ARM: shmobile: r8a7792: basic SoC support
In-Reply-To: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
Message-ID: <2352834.cNFKgiQiVO@wasted.cogentembedded.com>

Add minimal support for the R-Car V2H (R8A7792) SoC.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
 arch/arm/mach-shmobile/Kconfig         |    5 ++++
 arch/arm/mach-shmobile/Makefile        |    1 
 arch/arm/mach-shmobile/setup-r8a7792.c |   34 +++++++++++++++++++++++++++++++++
 3 files changed, 40 insertions(+)

Index: renesas/arch/arm/mach-shmobile/Kconfig
===================================================================
--- renesas.orig/arch/arm/mach-shmobile/Kconfig
+++ renesas/arch/arm/mach-shmobile/Kconfig
@@ -86,6 +86,11 @@ config ARCH_R8A7791
 	select ARCH_RCAR_GEN2
 	select I2C
 
+config ARCH_R8A7792
+	bool "R-Car V2H (R8A77920)"
+	select ARCH_RCAR_GEN2
+	select I2C
+
 config ARCH_R8A7793
 	bool "R-Car M2-N (R8A7793)"
 	select ARCH_RCAR_GEN2
Index: renesas/arch/arm/mach-shmobile/Makefile
===================================================================
--- renesas.orig/arch/arm/mach-shmobile/Makefile
+++ renesas/arch/arm/mach-shmobile/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_R8A7778)	+= setup-r8a7
 obj-$(CONFIG_ARCH_R8A7779)	+= setup-r8a7779.o pm-r8a7779.o
 obj-$(CONFIG_ARCH_R8A7790)	+= setup-r8a7790.o
 obj-$(CONFIG_ARCH_R8A7791)	+= setup-r8a7791.o
+obj-$(CONFIG_ARCH_R8A7792)	+= setup-r8a7792.o
 obj-$(CONFIG_ARCH_R8A7793)	+= setup-r8a7793.o
 obj-$(CONFIG_ARCH_R8A7794)	+= setup-r8a7794.o
 obj-$(CONFIG_ARCH_EMEV2)	+= setup-emev2.o
Index: renesas/arch/arm/mach-shmobile/setup-r8a7792.c
===================================================================
--- /dev/null
+++ renesas/arch/arm/mach-shmobile/setup-r8a7792.c
@@ -0,0 +1,34 @@
+/*
+ * r8a7792 processor support
+ *
+ * Copyright (C) 2014  Renesas Electronics Corporation
+ *
+ * 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; version 2 of the License.
+ *
+ * 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/of_platform.h>
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+#include "rcar-gen2.h"
+
+static const char * const r8a7792_boards_compat_dt[] __initconst = {
+	"renesas,r8a7792",
+	NULL,
+};
+
+DT_MACHINE_START(R8A7792_DT, "Generic R8A7792 (Flattened Device Tree)")
+	.init_early	= shmobile_init_delay,
+	.init_late	= shmobile_init_late,
+	.init_time	= rcar_gen2_timer_init,
+	.reserve	= rcar_gen2_reserve,
+	.dt_compat	= r8a7792_boards_compat_dt,
+MACHINE_END



From sergei.shtylyov at cogentembedded.com  Tue May 31 15:24:21 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Wed, 01 Jun 2016 01:24:21 +0300
Subject: [PATCH 07/13] ARM: dts: r8a7792: initial SoC device tree
In-Reply-To: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
Message-ID: <2539026.OyU5nvpxa6@wasted.cogentembedded.com>

The initial R8A7792 SoC device tree including 2 CPU cores, GIC, timer, SYSC,
and the required  clock descriptions.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
 arch/arm/boot/dts/r8a7792.dtsi |  423 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 423 insertions(+)

Index: renesas/arch/arm/boot/dts/r8a7792.dtsi
===================================================================
--- /dev/null
+++ renesas/arch/arm/boot/dts/r8a7792.dtsi
@@ -0,0 +1,423 @@
+/*
+ * Device Tree Source for the r8a7792 SoC
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/clock/r8a7792-clock.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/r8a7792-sysc.h>
+
+/ {
+	compatible = "renesas,r8a7792";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+			clock-frequency = <1000000000>;
+			clocks = <&cpg_clocks R8A7792_CLK_Z>;
+			power-domains = <&sysc R8A7792_PD_CA15_CPU0>;
+			next-level-cache = <&L2_CA15>;
+		};
+
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <1>;
+			clock-frequency = <1000000000>;
+			power-domains = <&sysc R8A7792_PD_CA15_CPU1>;
+			next-level-cache = <&L2_CA15>;
+		};
+
+		L2_CA15: cache-controller at 0 {
+			compatible = "cache";
+			reg = <0>;
+			cache-unified;
+			cache-level = <2>;
+			power-domains = <&sysc R8A7792_PD_CA15_SCU>;
+		};
+	};
+
+	gic: interrupt-controller at f1001000 {
+		compatible = "arm,gic-400";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0 0xf1001000 0 0x1000>,
+		      <0 0xf1002000 0 0x1000>,
+		      <0 0xf1004000 0 0x2000>,
+		      <0 0xf1006000 0 0x2000>;
+		interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) |
+			      IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <GIC_PPI 13
+			      (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14
+			      (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11
+			      (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10
+			      (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	sysc: system-controller at e6180000 {
+		compatible = "renesas,r8a7792-sysc";
+		reg = <0 0xe6180000 0 0x0200>;
+		#power-domain-cells = <1>;
+	};
+
+	clocks {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* External root clock */
+		extal_clk: extal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			/* This value must be overridden by the board. */
+			clock-frequency = <0>;
+		};
+
+		/* External PCIe clock - can be overridden by the board */
+		pcie_bus_clk: pcie_bus {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+
+		/* External SCIF clock */
+		scif_clk: scif {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			/* This value must be overridden by the board. */
+			clock-frequency = <0>;
+		};
+
+		/*
+		 * The external audio clocks are configured as 0 Hz fixed
+		 * frequency clocks by default.  Boards that provide audio
+		 * clocks should override them.
+		 */
+		audio_clka: audio_clka {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+		audio_clkb: audio_clkb {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+		audio_clkc: audio_clkc {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+		};
+
+		/* Special CPG clocks */
+		cpg_clocks: cpg_clocks at e6150000 {
+			compatible = "renesas,r8a7792-cpg-clocks",
+				     "renesas,rcar-gen2-cpg-clocks";
+			reg = <0 0xe6150000 0 0x1000>;
+			clocks = <&extal_clk>;
+			#clock-cells = <1>;
+			clock-output-names = "main", "pll0", "pll1", "pll3",
+					     "lb", "qspi", "sdh", "sd0", "sd1",
+					     "z";
+			#power-domain-cells = <0>;
+		};
+
+		/* Fixed factor clocks */
+		pll1_div2_clk: pll1_div2 {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		z2_clk: z2 {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		zg_clk: zg {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <3>;
+			clock-mult = <1>;
+		};
+		zx_clk: zx {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <3>;
+			clock-mult = <1>;
+		};
+		zs_clk: zs {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <6>;
+			clock-mult = <1>;
+		};
+		hp_clk: hp {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <12>;
+			clock-mult = <1>;
+		};
+		i_clk: i {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+		b_clk: b {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <12>;
+			clock-mult = <1>;
+		};
+		p_clk: p {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <24>;
+			clock-mult = <1>;
+		};
+		cl_clk: cl {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <48>;
+			clock-mult = <1>;
+		};
+		m2_clk: m2 {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <8>;
+			clock-mult = <1>;
+		};
+		rclk_clk: rclk {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <(48 * 1024)>;
+			clock-mult = <1>;
+		};
+		oscclk_clk: oscclk {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <(12 * 1024)>;
+			clock-mult = <1>;
+		};
+		zb3_clk: zb3 {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL3>;
+			#clock-cells = <0>;
+			clock-div = <4>;
+			clock-mult = <1>;
+		};
+		zb3d2_clk: zb3d2 {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL3>;
+			#clock-cells = <0>;
+			clock-div = <8>;
+			clock-mult = <1>;
+		};
+		ddr_clk: ddr {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks R8A7792_CLK_PLL3>;
+			#clock-cells = <0>;
+			clock-div = <8>;
+			clock-mult = <1>;
+		};
+		mp_clk: mp {
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-div = <15>;
+			clock-mult = <1>;
+		};
+		cp_clk: cp {
+			compatible = "fixed-factor-clock";
+			clocks = <&extal_clk>;
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+		};
+
+		/* Gate clocks */
+		mstp0_clks: mstp0_clks at e6150130 {
+			compatible = "renesas,r8a7792-mstp-clocks",
+				     "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150130 0 4>, <0 0xe6150030 0 4>;
+			clocks = <&mp_clk>;
+			#clock-cells = <1>;
+			clock-indices = <R8A7792_CLK_MSIOF0>;
+			clock-output-names = "msiof0";
+		};
+		mstp1_clks: mstp1_clks at e6150134 {
+			compatible = "renesas,r8a7792-mstp-clocks",
+				     "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150134 0 4>, <0 0xe6150038 0 4>;
+			clocks = <&p_clk>, <&p_clk>, <&p_clk>, <&rclk_clk>,
+				 <&cp_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>;
+			#clock-cells = <1>;
+			clock-indices = <
+				R8A7792_CLK_TMU1 R8A7792_CLK_TMU3
+				R8A7792_CLK_TMU2 R8A7792_CLK_CMT0
+				R8A7792_CLK_TMU0 R8A7792_CLK_VSP1DU1
+				R8A7792_CLK_VSP1DU0 R8A7792_CLK_VSP1_SY
+			>;
+			clock-output-names = "tmu1", "tmu3", "tmu2", "cmt0",
+					     "tmu0", "vsp1du1", "vsp1du0",
+					     "vsp1-sy";
+		};
+		mstp2_clks: mstp2_clks at e6150138 {
+			compatible = "renesas,r8a7792-mstp-clocks",
+				     "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150138 0 4>, <0 0xe6150040 0 4>;
+			clocks = <&mp_clk>, <&zs_clk>, <&zs_clk>;
+			#clock-cells = <1>;
+			clock-indices = <
+				R8A7792_CLK_MSIOF1
+				R8A7792_CLK_SYS_DMAC0 R8A7792_CLK_SYS_DMAC1
+			>;
+			clock-output-names = "msiof1", "sys-dmac0", "sys-dmac1";
+		};
+		mstp3_clks: mstp3_clks at e615013c {
+			compatible = "renesas,r8a7792-mstp-clocks",
+				     "renesas,cpg-mstp-clocks";
+			reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
+			clocks = <&cp_clk>, <&cpg_clocks R8A7792_CLK_SD0>,
+				 <&rclk_clk>;
+			#clock-cells = <1>;
+			clock-indices = <
+				R8A7792_CLK_TPU0 R8A7792_CLK_SDHI0
+				R8A7792_CLK_CMT1
+			>;
+			clock-output-names = "tpu0", "sdhi0", "cmt1";
+		};
+		mstp4_clks: mstp4_clks at e6150140 {
+			compatible = "renesas,r8a7792-mstp-clocks",
+				     "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150140 0 4>, <0 0xe615004c 0 4>;
+			clocks = <&cp_clk>;
+			#clock-cells = <1>;
+			clock-indices = <R8A7792_CLK_IRQC>;
+			clock-output-names = "irqc";
+		};
+		mstp5_clks: mstp5_clks at e6150144 {
+			compatible = "renesas,r8a7792-mstp-clocks",
+				     "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>;
+			clocks = <&hp_clk>, <&extal_clk>, <&p_clk>;
+			#clock-cells = <1>;
+			clock-indices = <
+				R8A7792_CLK_AUDIO_DMAC0
+				R8A7792_CLK_THERMAL R8A7792_CLK_PWM
+			>;
+			clock-output-names = "thermal", "pwm", "audmac0";
+		};
+		mstp7_clks: mstp7_clks at e615014c {
+			compatible = "renesas,r8a7792-mstp-clocks",
+				     "renesas,cpg-mstp-clocks";
+			reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>;
+			clocks = <&zs_clk>, <&zs_clk>, <&p_clk>, <&p_clk>,
+				 <&p_clk>, <&p_clk>, <&zx_clk>, <&zx_clk>;
+			#clock-cells = <1>;
+			clock-indices = <
+				R8A7792_CLK_HSCIF1 R8A7792_CLK_HSCIF0
+				R8A7792_CLK_SCIF3 R8A7792_CLK_SCIF2
+				R8A7792_CLK_SCIF1 R8A7792_CLK_SCIF0
+				R8A7792_CLK_DU1 R8A7792_CLK_DU0
+			>;
+			clock-output-names = "hscif1", "hscif0", "scif3",
+					     "scif2", "scif1", "scif0",
+					     "du1", "du0";
+		};
+		mstp8_clks: mstp8_clks at e6150990 {
+			compatible = "renesas,r8a7792-mstp-clocks",
+				     "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>;
+			clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>,
+				 <&zg_clk>, <&zg_clk>, <&hp_clk>;
+			#clock-cells = <1>;
+			clock-indices = <
+				R8A7792_CLK_VIN5 R8A7792_CLK_VIN4
+				R8A7792_CLK_VIN3 R8A7792_CLK_VIN2
+				R8A7792_CLK_VIN1 R8A7792_CLK_VIN0
+				R8A7792_CLK_ETHERAVB
+			>;
+			clock-output-names = "vin5", "vin4", "vin3", "vin2",
+					     "vin1", "vin0", "etheravb";
+		};
+		mstp9_clks: mstp9_clks at e6150994 {
+			compatible = "renesas,r8a7792-mstp-clocks",
+				     "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>;
+			clocks = <&cp_clk>, <&cp_clk>, <&cp_clk>, <&cp_clk>,
+				 <&cp_clk>, <&cp_clk>, <&cp_clk>, <&cp_clk>,
+				 <&cp_clk>, <&cp_clk>, <&p_clk>, <&p_clk>,
+				 <&cpg_clocks R8A7792_CLK_QSPI>, <&cp_clk>,
+				 <&cp_clk>, <&hp_clk>, <&cp_clk>, <&hp_clk>,
+				 <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>;
+			#clock-cells = <1>;
+			clock-indices = <
+				R8A7792_CLK_GPIO7 R8A7792_CLK_GPIO6
+				R8A7792_CLK_GPIO5 R8A7792_CLK_GPIO4
+				R8A7792_CLK_GPIO3 R8A7792_CLK_GPIO2
+				R8A7792_CLK_GPIO1 R8A7792_CLK_GPIO0
+				R8A7792_CLK_GPIO11 R8A7792_CLK_GPIO10
+				R8A7792_CLK_CAN1 R8A7792_CLK_CAN0
+				R8A7792_CLK_QSPI_MOD R8A7792_CLK_GPIO9
+				R8A7792_CLK_GPIO8 R8A7792_CLK_I2C5
+				R8A7792_CLK_IICDVFS R8A7792_CLK_I2C4
+				R8A7792_CLK_I2C3 R8A7792_CLK_I2C2
+				R8A7792_CLK_I2C1 R8A7792_CLK_I2C0
+			>;
+			clock-output-names = "gpio7", "gpio6", "gpio5", "gpio4",
+					     "gpio3", "gpio2", "gpio1", "gpio0",
+					     "gpio11", "gpio10", "can1", "can0",
+					     "qspi_mod", "gpio9", "gpio8",
+					     "i2c5", "iic3", "i2c4", "i2c3",
+					     "i2c2", "i2c1", "i2c0";
+		};
+		mstp10_clks: mstp10_clks at e6150998 {
+			compatible = "renesas,r8a7792-mstp-clocks",
+				     "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
+			clocks = <&p_clk>, <&p_clk>, <&p_clk>;
+			#clock-cells = <1>;
+			clock-indices = <
+				R8A7792_CLK_SSI_ALL
+				R8A7792_CLK_SSI4 R8A7792_CLK_SSI3
+			>;
+			clock-output-names = "ssi", "ssi4", "ssi3";
+		};
+	};
+};



From sergei.shtylyov at cogentembedded.com  Tue May 31 15:25:24 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Wed, 01 Jun 2016 01:25:24 +0300
Subject: [PATCH 08/13] ARM: dts: r8a7792: add SYS-DMAC support
In-Reply-To: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
Message-ID: <5621267.GpvUaW18zI@wasted.cogentembedded.com>

Describe SYS-DMAC0/1 in the R8A7792 device tree.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
 arch/arm/boot/dts/r8a7792.dtsi |   60 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

Index: renesas/arch/arm/boot/dts/r8a7792.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7792.dtsi
+++ renesas/arch/arm/boot/dts/r8a7792.dtsi
@@ -80,6 +80,66 @@
 		#power-domain-cells = <1>;
 	};
 
+	dmac0: dma-controller at e6700000 {
+		compatible = "renesas,dmac-r8a7792", "renesas,rcar-dmac";
+		reg = <0 0xe6700000 0 0x20000>;
+		interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "error",
+				  "ch0", "ch1", "ch2", "ch3", "ch4", "ch5",
+				  "ch6", "ch7", "ch8", "ch9", "ch10", "ch11",
+				  "ch12", "ch13", "ch14";
+		clocks = <&mstp2_clks R8A7792_CLK_SYS_DMAC0>;
+		clock-names = "fck";
+		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+		#dma-cells = <1>;
+		dma-channels = <15>;
+	};
+
+	dmac1: dma-controller at e6720000 {
+		compatible = "renesas,dmac-r8a7792", "renesas,rcar-dmac";
+		reg = <0 0xe6720000 0 0x20000>;
+		interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "error",
+				  "ch0", "ch1", "ch2", "ch3", "ch4", "ch5",
+				  "ch6", "ch7",	"ch8", "ch9", "ch10", "ch11",
+				  "ch12", "ch13", "ch14";
+		clocks = <&mstp2_clks R8A7792_CLK_SYS_DMAC1>;
+		clock-names = "fck";
+		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+		#dma-cells = <1>;
+		dma-channels = <15>;
+	};
+
 	clocks {
 		#address-cells = <2>;
 		#size-cells = <2>;



From sergei.shtylyov at cogentembedded.com  Tue May 31 15:26:56 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Wed, 01 Jun 2016 01:26:56 +0300
Subject: [PATCH 09/13] ARM: dts: r8a7792: add [H]SCIF support
In-Reply-To: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
Message-ID: <1493287.pGnW6U6caN@wasted.cogentembedded.com>

Describe [H]SCIFs in the R8A7792 device tree.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
 arch/arm/boot/dts/r8a7792.dtsi |   90 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

Index: renesas/arch/arm/boot/dts/r8a7792.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7792.dtsi
+++ renesas/arch/arm/boot/dts/r8a7792.dtsi
@@ -140,6 +140,96 @@
 		dma-channels = <15>;
 	};
 
+	scif0: serial at e6e60000 {
+		compatible = "renesas,scif-r8a7792", "renesas,rcar-gen2-scif",
+			     "renesas,scif";
+		reg = <0 0xe6e60000 0 64>;
+		interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7792_CLK_SCIF0>, <&zs_clk>,
+			 <&scif_clk>;
+		clock-names = "fck", "brg_int", "scif_clk";
+		dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+		       <&dmac1 0x29>, <&dmac1 0x2a>;
+		dma-names = "tx", "rx", "tx", "rx";
+		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
+	scif1: serial at e6e68000 {
+		compatible = "renesas,scif-r8a7792", "renesas,rcar-gen2-scif",
+			     "renesas,scif";
+		reg = <0 0xe6e68000 0 64>;
+		interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7792_CLK_SCIF1>, <&zs_clk>,
+			 <&scif_clk>;
+		clock-names = "fck", "brg_int", "scif_clk";
+		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+		       <&dmac1 0x2d>, <&dmac1 0x2e>;
+		dma-names = "tx", "rx", "tx", "rx";
+		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
+	scif2: serial at e6e58000 {
+		compatible = "renesas,scif-r8a7792", "renesas,rcar-gen2-scif",
+			     "renesas,scif";
+		reg = <0 0xe6e58000 0 64>;
+		interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7792_CLK_SCIF2>, <&zs_clk>,
+			 <&scif_clk>;
+		clock-names = "fck", "brg_int", "scif_clk";
+		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+		       <&dmac1 0x2b>, <&dmac1 0x2c>;
+		dma-names = "tx", "rx", "tx", "rx";
+		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
+	scif3: serial at e6ea8000 {
+		compatible = "renesas,scif-r8a7792", "renesas,rcar-gen2-scif",
+			     "renesas,scif";
+		reg = <0 0xe6ea8000 0 64>;
+		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7792_CLK_SCIF3>, <&zs_clk>,
+			 <&scif_clk>;
+		clock-names = "fck", "brg_int", "scif_clk";
+		dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
+		       <&dmac1 0x2f>, <&dmac1 0x30>;
+		dma-names = "tx", "rx", "tx", "rx";
+		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
+	hscif0: serial at e62c0000 {
+		compatible = "renesas,hscif-r8a7792", "renesas,rcar-gen2-hscif",
+			     "renesas,hscif";
+		reg = <0 0xe62c0000 0 96>;
+		interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7792_CLK_HSCIF0>, <&zs_clk>,
+			 <&scif_clk>;
+		clock-names = "fck", "brg_int", "scif_clk";
+		dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+		       <&dmac1 0x39>, <&dmac1 0x3a>;
+		dma-names = "tx", "rx", "tx", "rx";
+		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
+	hscif1: serial at e62c8000 {
+		compatible = "renesas,hscif-r8a7792", "renesas,rcar-gen2-hscif",
+			     "renesas,hscif";
+		reg = <0 0xe62c8000 0 96>;
+		interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp7_clks R8A7792_CLK_HSCIF1>, <&zs_clk>,
+			 <&scif_clk>;
+		clock-names = "fck", "brg_int", "scif_clk";
+		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+		       <&dmac1 0x4d>, <&dmac1 0x4e>;
+		dma-names = "tx", "rx", "tx", "rx";
+		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
 	clocks {
 		#address-cells = <2>;
 		#size-cells = <2>;



From sergei.shtylyov at cogentembedded.com  Tue May 31 15:29:05 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Wed, 01 Jun 2016 01:29:05 +0300
Subject: [PATCH 10/13] ARM: dts: r8a7792: add IRQC support
In-Reply-To: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
Message-ID: <3573091.BUvyGW3hVt@wasted.cogentembedded.com>

Describe the IRQC interrupt controller in the R8A7792 device tree.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
 arch/arm/boot/dts/r8a7792.dtsi |   13 +++++++++++++
 1 file changed, 13 insertions(+)

Index: renesas/arch/arm/boot/dts/r8a7792.dtsi
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7792.dtsi
+++ renesas/arch/arm/boot/dts/r8a7792.dtsi
@@ -62,6 +62,19 @@
 			      IRQ_TYPE_LEVEL_HIGH)>;
 	};
 
+	irqc: interrupt-controller at e61c0000 {
+		compatible = "renesas,irqc-r8a7792", "renesas,irqc";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0 0xe61c0000 0 0x200>;
+		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp4_clks R8A7792_CLK_IRQC>;
+		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		interrupts = <GIC_PPI 13



From sergei.shtylyov at cogentembedded.com  Tue May 31 15:32:35 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Wed, 01 Jun 2016 01:32:35 +0300
Subject: [PATCH 12/13] ARM: dts: blanche: initial device tree
In-Reply-To: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
Message-ID: <1923946.Jvi0TDUXFC@wasted.cogentembedded.com>

Add the initial device  tree for the R8A7792 SoC based Blanche board.
The board has 2 debug serial ports: SCIF0 and SCIF3; include support for
them,  so that  the serial console  can  work.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
 arch/arm/boot/dts/Makefile            |    1 
 arch/arm/boot/dts/r8a7792-blanche.dts |   44 ++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+)

Index: renesas/arch/arm/boot/dts/Makefile
===================================================================
--- renesas.orig/arch/arm/boot/dts/Makefile
+++ renesas/arch/arm/boot/dts/Makefile
@@ -638,6 +638,7 @@ dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += \
 	r8a7790-lager.dtb \
 	r8a7791-koelsch.dtb \
 	r8a7791-porter.dtb \
+	r8a7792-blanche.dtb \
 	r8a7793-gose.dtb \
 	r8a7794-alt.dtb \
 	r8a7794-silk.dtb \
Index: renesas/arch/arm/boot/dts/r8a7792-blanche.dts
===================================================================
--- /dev/null
+++ renesas/arch/arm/boot/dts/r8a7792-blanche.dts
@@ -0,0 +1,44 @@
+/*
+ * Device Tree Source for the Blanche board
+ *
+ * Copyright (C) 2016 Cogent Embedded, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+#include "r8a7792.dtsi"
+
+/ {
+	model = "Blanche";
+	compatible = "renesas,blanche", "renesas,r8a7792";
+
+	aliases {
+		serial0 = &scif0;
+		serial1 = &scif3;
+	};
+
+	chosen {
+		bootargs = "ignore_loglevel";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory at 40000000 {
+		device_type = "memory";
+		reg = <0 0x40000000 0 0x40000000>;
+	};
+};
+
+&extal_clk {
+	clock-frequency = <20000000>;
+};
+
+&scif0 {
+	status = "okay";
+};
+
+&scif3 {
+	status = "okay";
+};



From sergei.shtylyov at cogentembedded.com  Tue May 31 15:33:49 2016
From: sergei.shtylyov at cogentembedded.com (Sergei Shtylyov)
Date: Wed, 01 Jun 2016 01:33:49 +0300
Subject: [PATCH 13/13] ARM: dts: blanche: add Ethernet support
In-Reply-To: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
Message-ID: <1669958.qjJ7i3NBPv@wasted.cogentembedded.com>

R8A7792  SoC  doesn't have the EtherMAC core, so SMSC  LAN89218  Ethernet
chip was used instead on the Blanche board; this chip  is compatible with
SMSC LAN9115  for  which there's a (device tree aware) driver. Describe
the  chip in  the  Blanche device tree;  enable DHCP and NFS root in the
kernel command line for the kernel booting.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

---
 arch/arm/boot/dts/r8a7792-blanche.dts |   23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

Index: renesas/arch/arm/boot/dts/r8a7792-blanche.dts
===================================================================
--- renesas.orig/arch/arm/boot/dts/r8a7792-blanche.dts
+++ renesas/arch/arm/boot/dts/r8a7792-blanche.dts
@@ -21,7 +21,7 @@
 	};
 
 	chosen {
-		bootargs = "ignore_loglevel";
+		bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
 		stdout-path = "serial0:115200n8";
 	};
 
@@ -29,6 +29,27 @@
 		device_type = "memory";
 		reg = <0 0x40000000 0 0x40000000>;
 	};
+
+	d3_3v: regulator-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "D3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	ethernet at 18000000 {
+		compatible = "smsc,lan89218", "smsc,lan9115";
+		reg = <0 0x18000000 0 0x100>;
+		phy-mode = "mii";
+		interrupt-parent = <&irqc>;
+		interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+		smsc,irq-push-pull;
+		reg-io-width = <4>;
+		vddvario-supply = <&d3_3v>;
+		vdd33a-supply = <&d3_3v>;
+	};
 };
 
 &extal_clk {



From sgoel at codeaurora.org  Tue May 31 16:30:28 2016
From: sgoel at codeaurora.org (Goel, Sameer)
Date: Tue, 31 May 2016 17:30:28 -0600
Subject: [PATCH v3] arm64: Implement optimised IP checksum helpers
In-Reply-To: <4cef631ae5ff455d080cb17c8e0fa918c9a5c067.1464714040.git.robin.murphy@arm.com>
References: <ba9cf5bf84b8adc766f7f7511dda8cb501cd4101.1464693619.git.robin.murphy@arm.com>
 <4cef631ae5ff455d080cb17c8e0fa918c9a5c067.1464714040.git.robin.murphy@arm.com>
Message-ID: <7d5e45a9-6e48-3f67-c633-77a3d50d71e8@codeaurora.org>

Thanks for the arm64 checksum file. I saw a 4 fold speedup when 
calculating checksum for a 20 byte buffer on my test platform.

Thanks,
Sameer

On 5/31/2016 11:04 AM, Robin Murphy wrote:
> AArch64 is capable of 128-bit memory accesses without alignment
> restrictions, which makes it both possible and highly practical to slurp
> up a typical 20-byte IP header in just 2 loads. Implement our own
> version of ip_fast_checksum() to take advantage of that, resulting in
> considerably fewer instructions and memory accesses than the generic
> version. We can also get more optimal code generation for csum_fold() by
> defining it a slightly different way round from the generic version, so
> throw that into the mix too.
>
> Suggested-by: Luke Starrett <luke.starrett at broadcom.com>
> Acked-by: Luke Starrett <luke.starrett at broadcom.com>
> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
> ---
>
> v3: Don't generate generic header [James]
> v2: Include types.h, add Luke's ack
>
>  arch/arm64/include/asm/Kbuild     |  1 -
>  arch/arm64/include/asm/checksum.h | 51 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 51 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm64/include/asm/checksum.h
>
> diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
> index cff532a6744e..f43d2c44c765 100644
> --- a/arch/arm64/include/asm/Kbuild
> +++ b/arch/arm64/include/asm/Kbuild
> @@ -1,6 +1,5 @@
>  generic-y += bug.h
>  generic-y += bugs.h
> -generic-y += checksum.h
>  generic-y += clkdev.h
>  generic-y += cputime.h
>  generic-y += current.h
> diff --git a/arch/arm64/include/asm/checksum.h b/arch/arm64/include/asm/checksum.h
> new file mode 100644
> index 000000000000..09f65339d66d
> --- /dev/null
> +++ b/arch/arm64/include/asm/checksum.h
> @@ -0,0 +1,51 @@
> +/*
> + * Copyright (C) 2016 ARM 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef __ASM_CHECKSUM_H
> +#define __ASM_CHECKSUM_H
> +
> +#include <linux/types.h>
> +
> +static inline __sum16 csum_fold(__wsum csum)
> +{
> +	u32 sum = (__force u32)csum;
> +	sum += (sum >> 16) | (sum << 16);
> +	return ~(__force __sum16)(sum >> 16);
> +}
> +#define csum_fold csum_fold
> +
> +static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
> +{
> +	__uint128_t tmp;
> +	u64 sum;
> +
> +	tmp = *(const __uint128_t *)iph;
> +	iph += 16;
> +	ihl -= 4;
> +	tmp += ((tmp >> 64) | (tmp << 64));
> +	sum = tmp >> 64;
> +	do {
> +		sum += *(const u32 *)iph;
> +		iph += 4;
> +	} while (--ihl);
> +
> +	sum += ((sum >> 32) | (sum << 32));
> +	return csum_fold(sum >> 32);
> +}
> +#define ip_fast_csum ip_fast_csum
> +
> +#include <asm-generic/checksum.h>
> +
> +#endif	/* __ASM_CHECKSUM_H */
>

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


From isubramanian at apm.com  Tue May 31 16:44:01 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Tue, 31 May 2016 16:44:01 -0700
Subject: [PATCH v1 5/6] dtb: xgene: Remove clock nodes
In-Reply-To: <574BECE8.2050307@gmail.com>
References: <1464333768-26150-1-git-send-email-isubramanian@apm.com>
 <1464333768-26150-6-git-send-email-isubramanian@apm.com>
 <574BECE8.2050307@gmail.com>
Message-ID: <CAKh23FmM3Dfo+XQT++b0y0ETQJMgjngdxCcDxhLBRc4UVsrnAA@mail.gmail.com>

On Mon, May 30, 2016 at 12:34 AM, Matthias Brugger
<matthias.bgg at gmail.com> wrote:
>
>
> On 27/05/16 09:22, Iyappan Subramanian wrote:
>>
>> Since the MDIO will be responsible for clock reset, removing the clock
>> nodes from shadowcat xge0 and storm sgenet1.
>>
>> Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
>> Tested-by: Fushen Chen <fchen at apm.com>
>> Tested-by: Toan Le <toanle at apm.com>
>> ---
>>   arch/arm64/boot/dts/apm/apm-shadowcat.dtsi | 12 ------------
>>   arch/arm64/boot/dts/apm/apm-storm.dtsi     | 18 ++++--------------
>>   2 files changed, 4 insertions(+), 26 deletions(-)
>>
>> diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
>> b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
>> index 8106957..f27563d 100644
>> --- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
>> +++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
>> @@ -299,17 +299,6 @@
>>                                 clock-output-names = "pcie1clk";
>>                         };
>>
>> -                       xge0clk: xge0clk at 1f61c000 {
>> -                               compatible = "apm,xgene-device-clock";
>> -                               #clock-cells = <1>;
>> -                               clocks = <&socplldiv2 0>;
>> -                               reg = <0x0 0x1f61c000 0x0 0x1000>;
>> -                               reg-names = "csr-reg";
>> -                               enable-mask = <0x3>;
>> -                               csr-mask = <0x3>;
>> -                               clock-output-names = "xge0clk";
>> -                       };
>> -
>
>
> mdio at 0x1f610000 has xge0clk as input (patch 4), so deleting the node here
> will break the device tree. I suppose the mdio consumes the menetclk as in
> apm-storm.dtsi.

I added back xge0clk.

>
> Regards,
> Matthias
>
>
>>                         xge1clk: xge1clk at 1f62c000 {
>>                                 compatible = "apm,xgene-device-clock";
>>                                 #clock-cells = <1>;
>> @@ -643,7 +632,6 @@
>>                         interrupts = <0 96 4>,
>>                                      <0 97 4>;
>>                         dma-coherent;
>> -                       clocks = <&xge0clk 0>;
>>                         local-mac-address = [00 01 73 00 00 01];
>>                         phy-connection-type = "sgmii";
>>                         phy-handle = <&sgenet0phy>;
>> diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi
>> b/arch/arm64/boot/dts/apm/apm-storm.dtsi
>> index 18f694ea..f631fe4 100644
>> --- a/arch/arm64/boot/dts/apm/apm-storm.dtsi
>> +++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi
>> @@ -237,20 +237,11 @@
>>                                 clocks = <&socplldiv2 0>;
>>                                 reg = <0x0 0x1f21c000 0x0 0x1000>;
>>                                 reg-names = "csr-reg";
>> -                               csr-mask = <0x3>;
>> +                               csr-mask = <0xa>;
>> +                               enable-mask = <0xf>;
>>                                 clock-output-names = "sge0clk";
>>                         };
>>
>> -                       sge1clk: sge1clk at 1f21c000 {
>> -                               compatible = "apm,xgene-device-clock";
>> -                               #clock-cells = <1>;
>> -                               clocks = <&socplldiv2 0>;
>> -                               reg = <0x0 0x1f21c000 0x0 0x1000>;
>> -                               reg-names = "csr-reg";
>> -                               csr-mask = <0xc>;
>> -                               clock-output-names = "sge1clk";
>> -                       };
>> -
>>                         xge0clk: xge0clk at 1f61c000 {
>>                                 compatible = "apm,xgene-device-clock";
>>                                 #clock-cells = <1>;
>> @@ -938,9 +929,9 @@
>>                         reg-names = "enet_csr", "ring_csr", "ring_cmd";
>>                         interrupts = <0x0 0x3c 0x4>;
>>                         dma-coherent;
>> -                       clocks = <&menetclk 0>;
>>                         /* mac address will be overwritten by the
>> bootloader */
>>                         local-mac-address = [00 00 00 00 00 00];
>> +                       clocks = <&menetclk 0>;
>>                         phy-connection-type = "rgmii";
>>                         phy-handle = <&menetphy>;
>>                 };
>> @@ -955,8 +946,8 @@
>>                         interrupts = <0x0 0xA0 0x4>,
>>                                      <0x0 0xA1 0x4>;
>>                         dma-coherent;
>> -                       clocks = <&sge0clk 0>;
>>                         local-mac-address = [00 00 00 00 00 00];
>> +                       clocks = <&sge0clk 0>;
>>                         phy-connection-type = "sgmii";
>>                         phy-handle = <&sgenet0phy>;
>>                 };
>> @@ -972,7 +963,6 @@
>>                                      <0x0 0xAD 0x4>;
>>                         port-id = <1>;
>>                         dma-coherent;
>> -                       clocks = <&sge1clk 0>;
>>                         local-mac-address = [00 00 00 00 00 00];
>>                         phy-connection-type = "sgmii";
>>                         phy-handle = <&sgenet1phy>;
>>
>


From johnyoun at synopsys.com  Tue May 31 16:55:01 2016
From: johnyoun at synopsys.com (John Youn)
Date: Tue, 31 May 2016 16:55:01 -0700
Subject: [PATCH v2] reset: Return -ENOTSUPP when not configured
Message-ID: <2b8732d98087e52edec39ec83a063912fcc23962.1464738402.git.johnyoun@synopsys.com>

Prior to commit 6c96f05c8bb8 ("reset: Make [of_]reset_control_get[_foo]
functions wrappers"), the "optional" functions returned -ENOTSUPP when
CONFIG_RESET_CONTROLLER was not set.

Revert back to the old behavior by changing the new
__devm_reset_control_get() and __of_reset_control_get() functions to
return ERR_PTR(-ENOTSUPP) when compiled without CONFIG_RESET_CONTROLLER.

Otherwise they will return -EINVAL causing users to think that an error
occurred when CONFIG_RESET_CONTROLLER is not set.

Fixes: 6c96f05c8bb8 ("reset: Make [of_]reset_control_get[_foo] functions wrappers")
Signed-off-by: John Youn <johnyoun at synopsys.com>
---

Hi Philipp,

Here are the changes as discussed previously. It just returns
-ENOTSUPP directly when not configured. Tested and works with DWC2
driver with Dinh's patch that adds the reset controller, using a
configuration with no reset controller configured.

v2:
* Return ERR_PTR(-ENOTSUPP) directly.


 include/linux/reset.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/reset.h b/include/linux/reset.h
index ec0306ce..067db57 100644
--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -71,14 +71,14 @@ static inline struct reset_control *__of_reset_control_get(
 					struct device_node *node,
 					const char *id, int index, int shared)
 {
-	return ERR_PTR(-EINVAL);
+	return ERR_PTR(-ENOTSUPP);
 }
 
 static inline struct reset_control *__devm_reset_control_get(
 					struct device *dev,
 					const char *id, int index, int shared)
 {
-	return ERR_PTR(-EINVAL);
+	return ERR_PTR(-ENOTSUPP);
 }
 
 #endif /* CONFIG_RESET_CONTROLLER */
-- 
2.8.2



From isubramanian at apm.com  Tue May 31 17:10:35 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Tue, 31 May 2016 17:10:35 -0700
Subject: [PATCH v2 0/5] drivers: net: xgene: Fix 1G hot-plug and module support
Message-ID: <1464739840-21971-1-git-send-email-isubramanian@apm.com>

This patchset addresses the following issues,

1. hot-plug issue on the SGMII 1G interface
	- by adding a driver for MDIO management
2. fixes the kernel crash when the driver loaded as an kernel module
	- by fixing hardware cleanups and rearrange kernel API calls

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Matthias Brugger <mbrugger at suse.com>
---

v2: Address review comments from v1
	- Fixed patch 1 compilation error
	- Fixed mdio at 1f610000 xge0clk reference
	- Squashed dtb patches
	- Added PORT_OFFSET macro

v1:
	- Initial version
---

Iyappan Subramanian (5):
  drivers: net: xgene: MAC and PHY configuration changes
  drivers: net: xgene: Backward compatibility with older firmware
  drivers: net: phy: Add MDIO driver
  dtb: xgene: Add MDIO node
  drivers: net: xgene: Fix module load/unload crash

 arch/arm64/boot/dts/apm/apm-merlin.dts            |   9 +
 arch/arm64/boot/dts/apm/apm-mustang.dts           |  12 +
 arch/arm64/boot/dts/apm/apm-shadowcat.dtsi        |  11 +
 arch/arm64/boot/dts/apm/apm-storm.dtsi            |  38 +-
 drivers/net/ethernet/apm/xgene/Kconfig            |   1 +
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    | 241 ++++++----
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    |  19 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 325 ++++++++-----
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |  36 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 191 +++++++-
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h |   8 +
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c |  66 ++-
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h |   4 +
 drivers/net/phy/Kconfig                           |   7 +
 drivers/net/phy/Makefile                          |   1 +
 drivers/net/phy/mdio-xgene.c                      | 531 ++++++++++++++++++++++
 drivers/net/phy/mdio-xgene.h                      | 140 ++++++
 17 files changed, 1373 insertions(+), 267 deletions(-)
 create mode 100644 drivers/net/phy/mdio-xgene.c
 create mode 100644 drivers/net/phy/mdio-xgene.h

-- 
1.9.1



From isubramanian at apm.com  Tue May 31 17:10:36 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Tue, 31 May 2016 17:10:36 -0700
Subject: [PATCH v2 1/5] drivers: net: xgene: MAC and PHY configuration changes
In-Reply-To: <1464739840-21971-1-git-send-email-isubramanian@apm.com>
References: <1464739840-21971-1-git-send-email-isubramanian@apm.com>
Message-ID: <1464739840-21971-2-git-send-email-isubramanian@apm.com>

This patch fixes MAC configuration to support 10/100GbE for SGMII and
link_state call back. It also sets pdata->mdio_driver flag based on
ethernet mdio subnode and prepare for MDIO driver support.

In summary, following are the changes,

- Added set_speed function pointer in mac_ops
- Changed link_state to call the set_speed
- Add 10/100 support for SGMII based 1G
- Fixed mac_init for 1G

- Call mac_ops rx_enable/disable and tx_enable/disable function pointers
- Add acpi_phy_find_device to find PHY using phy-handle reference object
- Changing phy_start and phy_stop calls based on phy_dev object existence
- Calling phy_connect based on pdata->mdio_driver flag

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Fushen Chen <fchen at apm.com>
Tested-by: Toan Le <toanle at apm.com>
Tested-by: Matthias Brugger <mbrugger at suse.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    | 190 +++++++++++++---------
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    |   5 +
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  |  41 +++--
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |   2 +
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c | 106 +++++++++++-
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h |   8 +
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h |   4 +
 7 files changed, 259 insertions(+), 97 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 2f5638f..5d6d14b 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -512,14 +512,11 @@ static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata)
 #endif
 }
 
-static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
+static void xgene_gmac_set_speed(struct xgene_enet_pdata *pdata)
 {
 	struct device *dev = &pdata->pdev->dev;
-	u32 value, mc2;
-	u32 intf_ctl, rgmii;
-	u32 icm0, icm2;
-
-	xgene_gmac_reset(pdata);
+	u32 icm0, icm2, mc2;
+	u32 intf_ctl, rgmii, value;
 
 	xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0);
 	xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2);
@@ -564,7 +561,18 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
 	mc2 |= FULL_DUPLEX2 | PAD_CRC;
 	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2);
 	xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl);
+	xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
+	xgene_enet_configure_clock(pdata);
+
+	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, icm0);
+	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2);
+}
 
+static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
+{
+	u32 value;
+
+	xgene_gmac_set_speed(pdata);
 	xgene_gmac_set_mac_addr(pdata);
 
 	/* Adjust MDC clock frequency */
@@ -579,15 +587,10 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
 
 	/* Rtype should be copied from FP */
 	xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0);
-	xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii);
-	xgene_enet_configure_clock(pdata);
 
 	/* Rx-Tx traffic resume */
 	xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
 
-	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, icm0);
-	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2);
-
 	xgene_enet_rd_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, &value);
 	value &= ~TX_DV_GATE_EN0;
 	value &= ~RX_DV_GATE_EN0;
@@ -671,25 +674,12 @@ bool xgene_ring_mgr_init(struct xgene_enet_pdata *p)
 
 static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
 {
-	u32 val;
-
 	if (!xgene_ring_mgr_init(pdata))
 		return -ENODEV;
 
-	if (!IS_ERR(pdata->clk)) {
-		clk_prepare_enable(pdata->clk);
-		clk_disable_unprepare(pdata->clk);
-		clk_prepare_enable(pdata->clk);
-		xgene_enet_ecc_init(pdata);
-	}
+	xgene_enet_ecc_init(pdata);
 	xgene_enet_config_ring_if_assoc(pdata);
 
-	/* Enable auto-incr for scanning */
-	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &val);
-	val |= SCAN_AUTO_INCR;
-	MGMT_CLOCK_SEL_SET(&val, 1);
-	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, val);
-
 	return 0;
 }
 
@@ -724,29 +714,49 @@ static int xgene_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
 static void xgene_enet_adjust_link(struct net_device *ndev)
 {
 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	const struct xgene_mac_ops *mac_ops = pdata->mac_ops;
 	struct phy_device *phydev = pdata->phy_dev;
 
 	if (phydev->link) {
 		if (pdata->phy_speed != phydev->speed) {
 			pdata->phy_speed = phydev->speed;
-			xgene_gmac_init(pdata);
-			xgene_gmac_rx_enable(pdata);
-			xgene_gmac_tx_enable(pdata);
+			mac_ops->set_speed(pdata);
+			mac_ops->rx_enable(pdata);
+			mac_ops->tx_enable(pdata);
 			phy_print_status(phydev);
 		}
 	} else {
-		xgene_gmac_rx_disable(pdata);
-		xgene_gmac_tx_disable(pdata);
+		mac_ops->rx_disable(pdata);
+		mac_ops->tx_disable(pdata);
 		pdata->phy_speed = SPEED_UNKNOWN;
 		phy_print_status(phydev);
 	}
 }
 
-static int xgene_enet_phy_connect(struct net_device *ndev)
+#ifdef CONFIG_ACPI
+static struct acpi_device *acpi_phy_find_device(struct device *dev)
+{
+	struct acpi_reference_args args;
+	struct fwnode_handle *fw_node;
+	int status;
+
+	fw_node = acpi_fwnode_handle(ACPI_COMPANION(dev));
+	status = acpi_node_get_property_reference(fw_node, "phy-handle", 0,
+						  &args);
+	if (ACPI_FAILURE(status)) {
+		dev_dbg(dev, "No matching phy in ACPI table\n");
+		return NULL;
+	}
+
+	return args.adev;
+}
+#endif
+
+int xgene_enet_phy_connect(struct net_device *ndev)
 {
 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
 	struct device_node *phy_np;
-	struct phy_device *phy_dev;
+	struct phy_device *phy_dev = NULL;
 	struct device *dev = &pdata->pdev->dev;
 
 	if (dev->of_node) {
@@ -756,23 +766,25 @@ static int xgene_enet_phy_connect(struct net_device *ndev)
 			return -ENODEV;
 		}
 
-		phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link,
-					 0, pdata->phy_mode);
-		if (!phy_dev) {
-			netdev_err(ndev, "Could not connect to PHY\n");
-			return -ENODEV;
-		}
-
-		pdata->phy_dev = phy_dev;
+		pdata->phy_dev = of_phy_find_device(phy_np);
 	} else {
-		phy_dev = pdata->phy_dev;
+#ifdef CONFIG_ACPI
+		if (pdata->mdio_driver) {
+			struct acpi_device *adev;
 
-		if (!phy_dev ||
-		    phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
-				       pdata->phy_mode)) {
-			netdev_err(ndev, "Could not connect to PHY\n");
-			return  -ENODEV;
+			adev = acpi_phy_find_device(dev);
+			if (adev)
+				pdata->phy_dev =  adev->driver_data;
 		}
+#endif
+	}
+
+	phy_dev = pdata->phy_dev;
+	if (!phy_dev ||
+	    phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
+			       pdata->phy_mode)) {
+		netdev_err(ndev, "Could not connect to PHY\n");
+		return  -ENODEV;
 	}
 
 	pdata->phy_speed = SPEED_UNKNOWN;
@@ -788,12 +800,9 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
 				  struct mii_bus *mdio)
 {
 	struct device *dev = &pdata->pdev->dev;
-	struct net_device *ndev = pdata->ndev;
-	struct phy_device *phy;
-	struct device_node *child_np;
 	struct device_node *mdio_np = NULL;
-	int ret;
-	u32 phy_id;
+	struct device_node *child_np;
+	u32 phyid;
 
 	if (dev->of_node) {
 		for_each_child_of_node(dev->of_node, child_np) {
@@ -805,38 +814,50 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
 		}
 
 		if (!mdio_np) {
-			netdev_dbg(ndev, "No mdio node in the dts\n");
-			return -ENXIO;
+			mdiobus_free(mdio);
+			return 0;
 		}
 
+		pdata->mdio_driver = false;
+
 		return of_mdiobus_register(mdio, mdio_np);
-	}
+	} else {
+#ifdef CONFIG_ACPI
+		struct phy_device *phy;
+		int ret;
 
-	/* Mask out all PHYs from auto probing. */
-	mdio->phy_mask = ~0;
+		if (pdata->mdio_driver) {
+			mdiobus_free(mdio);
+			return 0;
+		}
 
-	/* Register the MDIO bus */
-	ret = mdiobus_register(mdio);
-	if (ret)
-		return ret;
+		/* Mask out all PHYs from auto probing. */
+		mdio->phy_mask = ~0;
 
-	ret = device_property_read_u32(dev, "phy-channel", &phy_id);
-	if (ret)
-		ret = device_property_read_u32(dev, "phy-addr", &phy_id);
-	if (ret)
-		return -EINVAL;
+		/* Register the MDIO bus */
+		ret = mdiobus_register(mdio);
+		if (ret)
+			return ret;
 
-	phy = get_phy_device(mdio, phy_id, false);
-	if (IS_ERR(phy))
-		return -EIO;
+		ret = device_property_read_u32(dev, "phy-channel", &phyid);
+		if (ret)
+			ret = device_property_read_u32(dev, "phy-addr", &phyid);
+		if (ret)
+			return -EINVAL;
 
-	ret = phy_device_register(phy);
-	if (ret)
-		phy_device_free(phy);
-	else
-		pdata->phy_dev = phy;
+		phy = get_phy_device(mdio, phyid, false);
+		if (IS_ERR(phy))
+			return -EIO;
 
-	return ret;
+		ret = phy_device_register(phy);
+		if (ret)
+			phy_device_free(phy);
+		else
+			pdata->phy_dev = phy;
+
+		return ret;
+#endif
+	}
 }
 
 int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
@@ -861,7 +882,13 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
 	ret = xgene_mdiobus_register(pdata, mdio_bus);
 	if (ret) {
 		netdev_err(ndev, "Failed to register MDIO bus\n");
+		if (mdio_bus->state == MDIOBUS_REGISTERED)
+			mdiobus_unregister(pdata->mdio_bus);
 		mdiobus_free(mdio_bus);
+		if (pdata->mdio_driver) {
+			ret = xgene_enet_phy_connect(ndev);
+			return 0;
+		}
 		return ret;
 	}
 	pdata->mdio_bus = mdio_bus;
@@ -873,14 +900,22 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
 	return ret;
 }
 
+void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata)
+{
+	if (pdata->phy_dev)
+		phy_disconnect(pdata->phy_dev);
+}
+
 void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
 {
 	if (pdata->phy_dev)
 		phy_disconnect(pdata->phy_dev);
 
-	mdiobus_unregister(pdata->mdio_bus);
-	mdiobus_free(pdata->mdio_bus);
-	pdata->mdio_bus = NULL;
+	if (!pdata->mdio_driver) {
+		mdiobus_unregister(pdata->mdio_bus);
+		mdiobus_free(pdata->mdio_bus);
+		pdata->mdio_bus = NULL;
+	}
 }
 
 const struct xgene_mac_ops xgene_gmac_ops = {
@@ -890,6 +925,7 @@ const struct xgene_mac_ops xgene_gmac_ops = {
 	.tx_enable = xgene_gmac_tx_enable,
 	.rx_disable = xgene_gmac_rx_disable,
 	.tx_disable = xgene_gmac_tx_disable,
+	.set_speed = xgene_gmac_set_speed,
 	.set_mac_addr = xgene_gmac_set_mac_addr,
 };
 
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 45220be..5540db9 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -104,6 +104,7 @@ enum xgene_enet_rm {
 #define RECOMBBUF		BIT(27)
 
 #define MAC_OFFSET			0x30
+#define PORT_OFFSET			0x4
 
 #define BLOCK_ETH_CSR_OFFSET		0x2000
 #define BLOCK_ETH_CLE_CSR_OFFSET	0x6000
@@ -160,7 +161,9 @@ enum xgene_enet_rm {
 #define CFG_CLE_DSTQID0(val)		(val & GENMASK(11, 0))
 #define CFG_CLE_FPSEL0(val)		((val << 16) & GENMASK(19, 16))
 #define ICM_CONFIG0_REG_0_ADDR		0x0400
+#define ICM_CONFIG0_REG_1_ADDR		0x0408
 #define ICM_CONFIG2_REG_0_ADDR		0x0410
+#define ICM_CONFIG2_REG_1_ADDR		0x0414
 #define RX_DV_GATE_REG_0_ADDR		0x05fc
 #define TX_DV_GATE_EN0			BIT(2)
 #define RX_DV_GATE_EN0			BIT(1)
@@ -347,6 +350,8 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
 int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
 void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
 bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);
+int xgene_enet_phy_connect(struct net_device *ndev);
+void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata);
 
 extern const struct xgene_mac_ops xgene_gmac_ops;
 extern const struct xgene_port_ops xgene_gport_ops;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index d208b17..d451e5d 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -727,11 +727,12 @@ static int xgene_enet_open(struct net_device *ndev)
 	ret = xgene_enet_register_irq(ndev);
 	if (ret)
 		return ret;
-
-	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
+	if (pdata->phy_dev) {
 		phy_start(pdata->phy_dev);
-	else
+	} else {
 		schedule_delayed_work(&pdata->link_work, PHY_POLL_LINK_OFF);
+		netif_carrier_off(ndev);
+	}
 
 	netif_start_queue(ndev);
 
@@ -746,7 +747,7 @@ static int xgene_enet_close(struct net_device *ndev)
 
 	netif_stop_queue(ndev);
 
-	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
+	if (pdata->phy_dev)
 		phy_stop(pdata->phy_dev);
 	else
 		cancel_delayed_work_sync(&pdata->link_work);
@@ -1291,6 +1292,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
 	struct resource *res;
 	void __iomem *base_addr;
 	u32 offset;
+	const char *ph;
 	int ret = 0;
 
 	pdev = pdata->pdev;
@@ -1368,13 +1370,18 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
 	if (ret)
 		return ret;
 
+	ret = device_property_read_string(dev, "phy-handle", &ph);
+	if (!ret)
+		pdata->mdio_driver = true;
+
 	pdata->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(pdata->clk)) {
 		/* Firmware may have set up the clock already. */
 		dev_info(dev, "clocks have been setup already\n");
 	}
 
-	if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
+	if ((pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) &&
+	    (pdata->enet_id == XGENE_ENET1))
 		base_addr = pdata->base_addr - (pdata->port_id * MAC_OFFSET);
 	else
 		base_addr = pdata->base_addr;
@@ -1577,7 +1584,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
 	struct net_device *ndev;
 	struct xgene_enet_pdata *pdata;
 	struct device *dev = &pdev->dev;
-	const struct xgene_mac_ops *mac_ops;
+	void (*link_state)(struct work_struct *);
 	const struct of_device_id *of_id;
 	int ret;
 
@@ -1603,15 +1610,18 @@ static int xgene_enet_probe(struct platform_device *pdev)
 	if (of_id) {
 		pdata->enet_id = (enum xgene_enet_id)of_id->data;
 	}
-#ifdef CONFIG_ACPI
 	else {
+#ifdef CONFIG_ACPI
 		const struct acpi_device_id *acpi_id;
+		enum xgene_enet_id enet_id;
 
 		acpi_id = acpi_match_device(xgene_enet_acpi_match, &pdev->dev);
-		if (acpi_id)
-			pdata->enet_id = (enum xgene_enet_id) acpi_id->driver_data;
-	}
+		if (acpi_id) {
+			enet_id = (enum xgene_enet_id)acpi_id->driver_data;
+			pdata->enet_id = enet_id;
+		}
 #endif
+	}
 	if (!pdata->enet_id) {
 		free_netdev(ndev);
 		return -ENODEV;
@@ -1645,13 +1655,18 @@ static int xgene_enet_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_netdev;
 
-	mac_ops = pdata->mac_ops;
+	link_state = pdata->mac_ops->link_state;
 	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
 		ret = xgene_enet_mdio_config(pdata);
 		if (ret)
 			goto err_netdev;
+	} else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
+		if (pdata->mdio_driver)
+			ret = xgene_enet_phy_connect(ndev);
+		else
+			INIT_DELAYED_WORK(&pdata->link_work, link_state);
 	} else {
-		INIT_DELAYED_WORK(&pdata->link_work, mac_ops->link_state);
+		INIT_DELAYED_WORK(&pdata->link_work, link_state);
 	}
 
 	xgene_enet_napi_add(pdata);
@@ -1679,6 +1694,8 @@ static int xgene_enet_remove(struct platform_device *pdev)
 	xgene_enet_napi_del(pdata);
 	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
 		xgene_enet_mdio_remove(pdata);
+	else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII)
+		xgene_enet_phy_disconnect(pdata);
 	unregister_netdev(ndev);
 	xgene_enet_delete_desc_rings(pdata);
 	pdata->port_ops->shutdown(pdata);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 092fbec..0fe1a96 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -140,6 +140,7 @@ struct xgene_mac_ops {
 	void (*rx_enable)(struct xgene_enet_pdata *pdata);
 	void (*tx_disable)(struct xgene_enet_pdata *pdata);
 	void (*rx_disable)(struct xgene_enet_pdata *pdata);
+	void (*set_speed)(struct xgene_enet_pdata *pdata);
 	void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
 	void (*set_mss)(struct xgene_enet_pdata *pdata);
 	void (*link_state)(struct work_struct *work);
@@ -211,6 +212,7 @@ struct xgene_enet_pdata {
 	u32 mss;
 	u8 tx_delay;
 	u8 rx_delay;
+	bool mdio_driver;
 };
 
 struct xgene_indirect_ctl {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index 7847551..a7a6c05 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -28,6 +28,12 @@ static void xgene_enet_wr_csr(struct xgene_enet_pdata *p, u32 offset, u32 val)
 	iowrite32(val, p->eth_csr_addr + offset);
 }
 
+static void xgene_enet_wr_clkrst_csr(struct xgene_enet_pdata *p, u32 offset,
+				     u32 val)
+{
+	iowrite32(val, p->base_addr + offset);
+}
+
 static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *p,
 				  u32 offset, u32 val)
 {
@@ -93,6 +99,11 @@ static u32 xgene_enet_rd_diag_csr(struct xgene_enet_pdata *p, u32 offset)
 	return ioread32(p->eth_diag_csr_addr + offset);
 }
 
+static u32 xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *p, u32 offset)
+{
+	return ioread32(p->mcx_mac_csr_addr + offset);
+}
+
 static u32 xgene_enet_rd_indirect(struct xgene_indirect_ctl *ctl, u32 rd_addr)
 {
 	u32 rd_data;
@@ -229,21 +240,97 @@ static u32 xgene_enet_link_status(struct xgene_enet_pdata *p)
 
 	data = xgene_mii_phy_read(p, INT_PHY_ADDR,
 				  SGMII_BASE_PAGE_ABILITY_ADDR >> 2);
+	if (LINK_SPEED(data) == PHY_SPEED_1000)
+		p->phy_speed = SPEED_1000;
+	else if (LINK_SPEED(data) == PHY_SPEED_100)
+		p->phy_speed = SPEED_100;
+	else
+		p->phy_speed = SPEED_10;
 
 	return data & LINK_UP;
 }
 
+static void xgene_sgmac_set_speed(struct xgene_enet_pdata *p)
+{
+	u32 icm0_addr, icm2_addr, debug_addr;
+	u32 icm0, icm2, intf_ctl;
+	u32 mc2, value;
+
+	if (p->phy_speed != SPEED_UNKNOWN) {
+		value = xgene_mii_phy_read(p, INT_PHY_ADDR,
+					   SGMII_BASE_PAGE_ABILITY_ADDR >> 2);
+		if (!(value & LINK_UP)) {
+			xgene_mii_phy_write(p, INT_PHY_ADDR,
+					    SGMII_TBI_CONTROL_ADDR >> 2,
+					    0x8000);
+			xgene_mii_phy_write(p, INT_PHY_ADDR,
+					    SGMII_TBI_CONTROL_ADDR >> 2, 0x0);
+		}
+	}
+
+	if (p->enet_id == XGENE_ENET1) {
+		icm0_addr = (!p->port_id) ?
+			ICM_CONFIG0_REG_0_ADDR : ICM_CONFIG0_REG_1_ADDR;
+		icm2_addr = (!p->port_id) ?
+			ICM_CONFIG2_REG_0_ADDR : ICM_CONFIG2_REG_1_ADDR;
+		debug_addr = DEBUG_REG_ADDR;
+	} else {
+		icm0_addr = XG_MCX_ICM_CONFIG0_REG_0_ADDR;
+		icm2_addr = XG_MCX_ICM_CONFIG2_REG_0_ADDR;
+		debug_addr = XG_DEBUG_REG_ADDR;
+	}
+
+	icm0 = xgene_enet_rd_mcx_csr(p, icm0_addr);
+	icm2 = xgene_enet_rd_mcx_csr(p, icm2_addr);
+	mc2 = xgene_enet_rd_mac(p, MAC_CONFIG_2_ADDR);
+	intf_ctl = xgene_enet_rd_mac(p, INTERFACE_CONTROL_ADDR);
+
+	switch (p->phy_speed) {
+	case SPEED_10:
+		ENET_INTERFACE_MODE2_SET(&mc2, 1);
+		intf_ctl &= ~(ENET_LHD_MODE | ENET_GHD_MODE);
+		CFG_MACMODE_SET(&icm0, 0);
+		CFG_WAITASYNCRD_SET(&icm2, 500);
+		break;
+	case SPEED_100:
+		ENET_INTERFACE_MODE2_SET(&mc2, 1);
+		intf_ctl &= ~ENET_GHD_MODE;
+		intf_ctl |= ENET_LHD_MODE;
+		CFG_MACMODE_SET(&icm0, 1);
+		CFG_WAITASYNCRD_SET(&icm2, 80);
+		break;
+	default:
+		ENET_INTERFACE_MODE2_SET(&mc2, 2);
+		intf_ctl &= ~ENET_LHD_MODE;
+		intf_ctl |= ENET_GHD_MODE;
+		CFG_MACMODE_SET(&icm0, 2);
+		CFG_WAITASYNCRD_SET(&icm2, 16);
+		value = xgene_enet_rd_csr(p, debug_addr);
+		value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX;
+		xgene_enet_wr_csr(p, debug_addr, value);
+		break;
+	}
+
+	mc2 |= FULL_DUPLEX2 | PAD_CRC;
+	xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, mc2);
+	xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, intf_ctl);
+	xgene_enet_wr_mcx_csr(p, icm0_addr, icm0);
+	xgene_enet_wr_mcx_csr(p, icm2_addr, icm2);
+}
+
 static void xgene_sgmac_init(struct xgene_enet_pdata *p)
 {
 	u32 data, loop = 10;
-	u32 offset = p->port_id * 4;
+	u32 offset = 0;
 	u32 enet_spare_cfg_reg, rsif_config_reg;
 	u32 cfg_bypass_reg, rx_dv_gate_reg;
 
 	xgene_sgmac_reset(p);
 
 	/* Enable auto-negotiation */
-	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x1000);
+	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2,
+			    0x8000);
+	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x9000);
 	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2, 0);
 
 	while (loop--) {
@@ -256,16 +343,14 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
 	if (!(data & AUTO_NEG_COMPLETE) || !(data & LINK_STATUS))
 		netdev_err(p->ndev, "Auto-negotiation failed\n");
 
-	data = xgene_enet_rd_mac(p, MAC_CONFIG_2_ADDR);
-	ENET_INTERFACE_MODE2_SET(&data, 2);
-	xgene_enet_wr_mac(p, MAC_CONFIG_2_ADDR, data | FULL_DUPLEX2);
-	xgene_enet_wr_mac(p, INTERFACE_CONTROL_ADDR, ENET_GHD_MODE);
+	xgene_sgmac_set_speed(p);
 
 	if (p->enet_id == XGENE_ENET1) {
 		enet_spare_cfg_reg = ENET_SPARE_CFG_REG_ADDR;
 		rsif_config_reg = RSIF_CONFIG_REG_ADDR;
 		cfg_bypass_reg = CFG_BYPASS_ADDR;
 		rx_dv_gate_reg = SG_RX_DV_GATE_REG_0_ADDR;
+		offset = p->port_id * PORT_OFFSET;
 	} else {
 		enet_spare_cfg_reg = XG_ENET_SPARE_CFG_REG_ADDR;
 		rsif_config_reg = XG_RSIF_CONFIG_REG_ADDR;
@@ -334,6 +419,9 @@ static int xgene_enet_reset(struct xgene_enet_pdata *p)
 	if (!xgene_ring_mgr_init(p))
 		return -ENODEV;
 
+	if (p->enet_id == XGENE_ENET2)
+		xgene_enet_wr_clkrst_csr(p, XGENET_CONFIG_REG_ADDR, SGMII_EN);
+
 	if (!IS_ERR(p->clk)) {
 		clk_prepare_enable(p->clk);
 		clk_disable_unprepare(p->clk);
@@ -386,10 +474,11 @@ static void xgene_enet_link_state(struct work_struct *work)
 	if (link) {
 		if (!netif_carrier_ok(ndev)) {
 			netif_carrier_on(ndev);
-			xgene_sgmac_init(p);
+			xgene_sgmac_set_speed(p);
 			xgene_sgmac_rx_enable(p);
 			xgene_sgmac_tx_enable(p);
-			netdev_info(ndev, "Link is Up - 1Gbps\n");
+			netdev_info(ndev, "Link is Up - %dMbps\n",
+				    p->phy_speed);
 		}
 		poll_interval = PHY_POLL_LINK_ON;
 	} else {
@@ -412,6 +501,7 @@ const struct xgene_mac_ops xgene_sgmac_ops = {
 	.tx_enable	= xgene_sgmac_tx_enable,
 	.rx_disable	= xgene_sgmac_rx_disable,
 	.tx_disable	= xgene_sgmac_tx_disable,
+	.set_speed	= xgene_sgmac_set_speed,
 	.set_mac_addr	= xgene_sgmac_set_mac_addr,
 	.link_state	= xgene_enet_link_state
 };
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
index 002df5a..3d0ba37 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.h
@@ -24,6 +24,7 @@
 #define PHY_ADDR(src)		(((src)<<8) & GENMASK(12, 8))
 #define REG_ADDR(src)		((src) & GENMASK(4, 0))
 #define PHY_CONTROL(src)	((src) & GENMASK(15, 0))
+#define LINK_SPEED(src)		(((src) & GENMASK(11, 10)) >> 10)
 #define INT_PHY_ADDR			0x1e
 #define SGMII_TBI_CONTROL_ADDR		0x44
 #define SGMII_CONTROL_ADDR		0x00
@@ -34,6 +35,13 @@
 #define LINK_UP				BIT(15)
 #define MPA_IDLE_WITH_QMI_EMPTY		BIT(12)
 #define SG_RX_DV_GATE_REG_0_ADDR	0x05fc
+#define SGMII_EN			0x1
+
+enum xgene_phy_speed {
+	PHY_SPEED_10,
+	PHY_SPEED_100,
+	PHY_SPEED_1000
+};
 
 extern const struct xgene_mac_ops xgene_sgmac_ops;
 extern const struct xgene_port_ops xgene_sgport_ops;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
index 0a2dca8..aba4c19 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
@@ -65,9 +65,13 @@
 #define XG_CFG_LINK_AGGR_RESUME_0_ADDR	0x0214
 #define XG_LINK_STATUS_ADDR		0x0228
 #define XG_TSIF_MSS_REG0_ADDR		0x02a4
+#define XG_DEBUG_REG_ADDR		0x0400
 #define XG_ENET_SPARE_CFG_REG_ADDR	0x040c
 #define XG_ENET_SPARE_CFG_REG_1_ADDR	0x0410
 #define XGENET_RX_DV_GATE_REG_0_ADDR	0x0804
+#define XG_MCX_ECM_CONFIG0_REG_0_ADDR	0x0070
+#define XG_MCX_ICM_CONFIG0_REG_0_ADDR	0x00e0
+#define XG_MCX_ICM_CONFIG2_REG_0_ADDR	0x00e8
 
 extern const struct xgene_mac_ops xgene_xgmac_ops;
 extern const struct xgene_port_ops xgene_xgport_ops;
-- 
1.9.1



From isubramanian at apm.com  Tue May 31 17:10:39 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Tue, 31 May 2016 17:10:39 -0700
Subject: [PATCH v2 4/5] dtb: xgene: Add MDIO node
In-Reply-To: <1464739840-21971-1-git-send-email-isubramanian@apm.com>
References: <1464739840-21971-1-git-send-email-isubramanian@apm.com>
Message-ID: <1464739840-21971-5-git-send-email-isubramanian@apm.com>

Added mdio node for mdio driver.  Also added phy-handle
reference to the ethernet nodes.

Removed unused mdio subnode within storm menet ethernet node.
Removed unused clock node from storm sgenet1.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Fushen Chen <fchen at apm.com>
Tested-by: Toan Le <toanle at apm.com>
Tested-by: Matthias Brugger <mbrugger at suse.com>
---
 arch/arm64/boot/dts/apm/apm-merlin.dts     |  9 +++++++
 arch/arm64/boot/dts/apm/apm-mustang.dts    | 12 ++++++++++
 arch/arm64/boot/dts/apm/apm-shadowcat.dtsi | 11 +++++++++
 arch/arm64/boot/dts/apm/apm-storm.dtsi     | 38 +++++++++++-------------------
 4 files changed, 46 insertions(+), 24 deletions(-)

diff --git a/arch/arm64/boot/dts/apm/apm-merlin.dts b/arch/arm64/boot/dts/apm/apm-merlin.dts
index 387c6a8..c765f26 100644
--- a/arch/arm64/boot/dts/apm/apm-merlin.dts
+++ b/arch/arm64/boot/dts/apm/apm-merlin.dts
@@ -83,3 +83,12 @@
 		status = "ok";
 	};
 };
+
+&mdio {
+	sgenet0phy: phy at 3 {
+		reg = <0x0>;
+	};
+	sgenet1phy: phy at 2 {
+		reg = <0x2>;
+	};
+};
diff --git a/arch/arm64/boot/dts/apm/apm-mustang.dts b/arch/arm64/boot/dts/apm/apm-mustang.dts
index 44db32e..c4e2bc4 100644
--- a/arch/arm64/boot/dts/apm/apm-mustang.dts
+++ b/arch/arm64/boot/dts/apm/apm-mustang.dts
@@ -79,3 +79,15 @@
 &mmc0 {
 	status = "ok";
 };
+
+&mdio {
+	menetphy: phy at 3 {
+		reg = <0x3>;
+	};
+	sgenet0phy: phy at 4 {
+		reg = <0x4>;
+	};
+	sgenet1phy: phy at 5 {
+		reg = <0x5>;
+	};
+};
diff --git a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
index c569f76..17333fa 100644
--- a/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
@@ -625,6 +625,15 @@
 			apm,irq-start = <8>;
 		};
 
+		mdio: mdio at 0x1f610000 {
+			compatible = "apm,xgene-mdio-sgmii";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x1f610000 0x0 0x100>,
+			      <0x0 0X1f61d000 0x0 0X100>;
+			clocks = <&xge0clk 0>;
+		};
+
 		sgenet0: ethernet at 1f610000 {
 			compatible = "apm,xgene2-sgenet";
 			status = "disabled";
@@ -637,6 +646,7 @@
 			clocks = <&xge0clk 0>;
 			local-mac-address = [00 01 73 00 00 01];
 			phy-connection-type = "sgmii";
+			phy-handle = <&sgenet0phy>;
 		};
 
 		xgenet1: ethernet at 1f620000 {
@@ -659,6 +669,7 @@
 			clocks = <&xge1clk 0>;
 			local-mac-address = [00 01 73 00 00 02];
 			phy-connection-type = "xgmii";
+			phy-handle = <&sgenet1phy>;
 		};
 
 		rng: rng at 10520000 {
diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi
index 5147d76..f631fe4 100644
--- a/arch/arm64/boot/dts/apm/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi
@@ -237,20 +237,11 @@
 				clocks = <&socplldiv2 0>;
 				reg = <0x0 0x1f21c000 0x0 0x1000>;
 				reg-names = "csr-reg";
-				csr-mask = <0x3>;
+				csr-mask = <0xa>;
+				enable-mask = <0xf>;
 				clock-output-names = "sge0clk";
 			};
 
-			sge1clk: sge1clk at 1f21c000 {
-				compatible = "apm,xgene-device-clock";
-				#clock-cells = <1>;
-				clocks = <&socplldiv2 0>;
-				reg = <0x0 0x1f21c000 0x0 0x1000>;
-				reg-names = "csr-reg";
-				csr-mask = <0xc>;
-				clock-output-names = "sge1clk";
-			};
-
 			xge0clk: xge0clk at 1f61c000 {
 				compatible = "apm,xgene-device-clock";
 				#clock-cells = <1>;
@@ -921,6 +912,14 @@
 			clocks = <&rtcclk 0>;
 		};
 
+		mdio: mdio at 0x17020000 {
+			compatible = "apm,xgene-mdio-rgmii";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x17020000 0x0 0xd100>;
+			clocks = <&menetclk 0>;
+		};
+
 		menet: ethernet at 17020000 {
 			compatible = "apm,xgene-enet";
 			status = "disabled";
@@ -930,21 +929,11 @@
 			reg-names = "enet_csr", "ring_csr", "ring_cmd";
 			interrupts = <0x0 0x3c 0x4>;
 			dma-coherent;
-			clocks = <&menetclk 0>;
 			/* mac address will be overwritten by the bootloader */
 			local-mac-address = [00 00 00 00 00 00];
+			clocks = <&menetclk 0>;
 			phy-connection-type = "rgmii";
 			phy-handle = <&menetphy>;
-			mdio {
-				compatible = "apm,xgene-mdio";
-				#address-cells = <1>;
-				#size-cells = <0>;
-				menetphy: menetphy at 3 {
-					compatible = "ethernet-phy-id001c.c915";
-					reg = <0x3>;
-				};
-
-			};
 		};
 
 		sgenet0: ethernet at 1f210000 {
@@ -957,9 +946,10 @@
 			interrupts = <0x0 0xA0 0x4>,
 				     <0x0 0xA1 0x4>;
 			dma-coherent;
-			clocks = <&sge0clk 0>;
 			local-mac-address = [00 00 00 00 00 00];
+			clocks = <&sge0clk 0>;
 			phy-connection-type = "sgmii";
+			phy-handle = <&sgenet0phy>;
 		};
 
 		sgenet1: ethernet at 1f210030 {
@@ -973,9 +963,9 @@
 				     <0x0 0xAD 0x4>;
 			port-id = <1>;
 			dma-coherent;
-			clocks = <&sge1clk 0>;
 			local-mac-address = [00 00 00 00 00 00];
 			phy-connection-type = "sgmii";
+			phy-handle = <&sgenet1phy>;
 		};
 
 		xgenet: ethernet at 1f610000 {
-- 
1.9.1



From isubramanian at apm.com  Tue May 31 17:10:37 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Tue, 31 May 2016 17:10:37 -0700
Subject: [PATCH v2 2/5] drivers: net: xgene: Backward compatibility with older
 firmware
In-Reply-To: <1464739840-21971-1-git-send-email-isubramanian@apm.com>
References: <1464739840-21971-1-git-send-email-isubramanian@apm.com>
Message-ID: <1464739840-21971-3-git-send-email-isubramanian@apm.com>

This patch looks for CONFIG_MDIO_XGENE and based on phy-handle DT/ACPI
fields, sets the mdio_driver flag.  The rest of the driver uses the
this flag for any MDIO management, in the case of backward compatibility.
Also, some code clean up done around mdio configuration/remove.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Fushen Chen <fchen at apm.com>
Tested-by: Toan Le <toanle at apm.com>
Tested-by: Matthias Brugger <mbrugger at suse.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    |  60 +++-----
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 165 +++++++++++++++-------
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |   2 +
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c |  13 +-
 4 files changed, 148 insertions(+), 92 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 5d6d14b..38d6ee4 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -476,9 +476,13 @@ static void xgene_gmac_reset(struct xgene_enet_pdata *pdata)
 static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata)
 {
 	struct device *dev = &pdata->pdev->dev;
+	struct clk *parent;
 
 	if (dev->of_node) {
-		struct clk *parent = clk_get_parent(pdata->clk);
+		if (IS_ERR(pdata->clk))
+			return;
+
+		parent = clk_get_parent(pdata->clk);
 
 		switch (pdata->phy_speed) {
 		case SPEED_10:
@@ -572,6 +576,9 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
 {
 	u32 value;
 
+	if (!pdata->mdio_driver)
+		xgene_gmac_reset(pdata);
+
 	xgene_gmac_set_speed(pdata);
 	xgene_gmac_set_mac_addr(pdata);
 
@@ -677,7 +684,14 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
 	if (!xgene_ring_mgr_init(pdata))
 		return -ENODEV;
 
-	xgene_enet_ecc_init(pdata);
+	if (!pdata->mdio_driver) {
+		if (!IS_ERR(pdata->clk)) {
+			clk_prepare_enable(pdata->clk);
+			clk_disable_unprepare(pdata->clk);
+			clk_prepare_enable(pdata->clk);
+			xgene_enet_ecc_init(pdata);
+		}
+	}
 	xgene_enet_config_ring_if_assoc(pdata);
 
 	return 0;
@@ -800,27 +814,9 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
 				  struct mii_bus *mdio)
 {
 	struct device *dev = &pdata->pdev->dev;
-	struct device_node *mdio_np = NULL;
-	struct device_node *child_np;
-	u32 phyid;
 
 	if (dev->of_node) {
-		for_each_child_of_node(dev->of_node, child_np) {
-			if (of_device_is_compatible(child_np,
-						    "apm,xgene-mdio")) {
-				mdio_np = child_np;
-				break;
-			}
-		}
-
-		if (!mdio_np) {
-			mdiobus_free(mdio);
-			return 0;
-		}
-
-		pdata->mdio_driver = false;
-
-		return of_mdiobus_register(mdio, mdio_np);
+		return of_mdiobus_register(mdio, pdata->mdio_np);
 	} else {
 #ifdef CONFIG_ACPI
 		struct phy_device *phy;
@@ -839,13 +835,7 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
 		if (ret)
 			return ret;
 
-		ret = device_property_read_u32(dev, "phy-channel", &phyid);
-		if (ret)
-			ret = device_property_read_u32(dev, "phy-addr", &phyid);
-		if (ret)
-			return -EINVAL;
-
-		phy = get_phy_device(mdio, phyid, false);
+		phy = get_phy_device(mdio, pdata->phy_id, false);
 		if (IS_ERR(phy))
 			return -EIO;
 
@@ -858,6 +848,8 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
 		return ret;
 #endif
 	}
+
+	return 0;
 }
 
 int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
@@ -885,10 +877,6 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
 		if (mdio_bus->state == MDIOBUS_REGISTERED)
 			mdiobus_unregister(pdata->mdio_bus);
 		mdiobus_free(mdio_bus);
-		if (pdata->mdio_driver) {
-			ret = xgene_enet_phy_connect(ndev);
-			return 0;
-		}
 		return ret;
 	}
 	pdata->mdio_bus = mdio_bus;
@@ -911,11 +899,9 @@ void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
 	if (pdata->phy_dev)
 		phy_disconnect(pdata->phy_dev);
 
-	if (!pdata->mdio_driver) {
-		mdiobus_unregister(pdata->mdio_bus);
-		mdiobus_free(pdata->mdio_bus);
-		pdata->mdio_bus = NULL;
-	}
+	mdiobus_unregister(pdata->mdio_bus);
+	mdiobus_free(pdata->mdio_bus);
+	pdata->mdio_bus = NULL;
 }
 
 const struct xgene_mac_ops xgene_gmac_ops = {
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index d451e5d..c31ea56 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1182,31 +1182,27 @@ static const struct net_device_ops xgene_ndev_ops = {
 
 #ifdef CONFIG_ACPI
 static void xgene_get_port_id_acpi(struct device *dev,
-				  struct xgene_enet_pdata *pdata)
+				   struct xgene_enet_pdata *pdata)
 {
 	acpi_status status;
 	u64 temp;
 
 	status = acpi_evaluate_integer(ACPI_HANDLE(dev), "_SUN", NULL, &temp);
-	if (ACPI_FAILURE(status)) {
+	if (ACPI_FAILURE(status))
 		pdata->port_id = 0;
-	} else {
+	else
 		pdata->port_id = temp;
-	}
-
-	return;
 }
 #endif
 
-static void xgene_get_port_id_dt(struct device *dev, struct xgene_enet_pdata *pdata)
+static void xgene_get_port_id_dt(struct device *dev,
+				 struct xgene_enet_pdata *pdata)
 {
 	u32 id = 0;
 
 	of_property_read_u32(dev->of_node, "port-id", &id);
 
 	pdata->port_id = id & BIT(0);
-
-	return;
 }
 
 static int xgene_get_tx_delay(struct xgene_enet_pdata *pdata)
@@ -1284,6 +1280,86 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata)
 	return 0;
 }
 
+static int xgene_enet_check_phy_handle(struct xgene_enet_pdata *pdata)
+{
+	struct device *dev = &pdata->pdev->dev;
+	int ret, phy_id, phy_mode = pdata->phy_mode;
+	struct device_node *mdio_np = NULL;
+	const char *ph;
+#ifdef CONFIG_ACPI
+	struct acpi_reference_args args;
+	struct fwnode_handle *fw_node;
+#endif
+
+	if (!IS_ENABLED(CONFIG_MDIO_XGENE))
+		return 0;
+
+	if (dev->of_node) {
+		ret = device_property_read_string(dev, "phy-handle", &ph);
+
+		if (phy_mode == PHY_INTERFACE_MODE_RGMII) {
+			if (ret) {
+				dev_err(dev, "Unable to get phy-handle\n");
+				return ret;
+			}
+
+			mdio_np = of_find_compatible_node(dev->of_node, NULL,
+							  "apm,xgene-mdio");
+			if (!mdio_np)
+				pdata->mdio_driver = true;
+			else
+				pdata->mdio_np = mdio_np;
+		} else {
+			if (!ret)
+				pdata->mdio_driver = true;
+		}
+	} else {
+#ifdef CONFIG_ACPI
+		fw_node = acpi_fwnode_handle(ACPI_COMPANION(dev));
+		ret = acpi_node_get_property_reference(fw_node, "mboxes", 0,
+						       &args);
+		if (!ACPI_FAILURE(ret)) {
+			pdata->mdio_driver = true;
+			pdata->phy_dev =  args.adev->driver_data;
+		} else {
+			ret = device_property_read_u32(dev, "phy-channel",
+						       &phy_id);
+			if (ret) {
+				ret = device_property_read_u32(dev, "phy-addr",
+							       &phy_id);
+			}
+
+			if (!ret)
+				pdata->phy_id = phy_id;
+		}
+#endif
+	}
+
+	return 0;
+}
+
+static int xgene_enet_get_clk(struct xgene_enet_pdata *pdata)
+{
+	struct device *dev = &pdata->pdev->dev;
+
+	if (!dev->of_node)
+		return 0;
+
+	pdata->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(pdata->clk)) {
+		if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+			dev_err(dev, "Unable to get clock\n");
+			return -ENODEV;
+		} else {
+			/* Firmware may have set up the clock already. */
+			dev_info(dev, "clocks have been setup already\n");
+			pdata->clk = NULL;
+		}
+	}
+
+	return 0;
+}
+
 static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
 {
 	struct platform_device *pdev;
@@ -1292,7 +1368,6 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
 	struct resource *res;
 	void __iomem *base_addr;
 	u32 offset;
-	const char *ph;
 	int ret = 0;
 
 	pdev = pdata->pdev;
@@ -1370,15 +1445,13 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
 	if (ret)
 		return ret;
 
-	ret = device_property_read_string(dev, "phy-handle", &ph);
-	if (!ret)
-		pdata->mdio_driver = true;
+	ret = xgene_enet_check_phy_handle(pdata);
+	if (ret)
+		return ret;
 
-	pdata->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(pdata->clk)) {
-		/* Firmware may have set up the clock already. */
-		dev_info(dev, "clocks have been setup already\n");
-	}
+	ret = xgene_enet_get_clk(pdata);
+	if (ret)
+		return ret;
 
 	if ((pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) &&
 	    (pdata->enet_id == XGENE_ENET1))
@@ -1434,8 +1507,6 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
 		}
 	}
 
-	dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
-	buf_pool = pdata->rx_ring[0]->buf_pool;
 	if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
 		/* Initialize and Enable  PreClassifier Tree */
 		enet_cle->max_nodes = 512;
@@ -1451,9 +1522,12 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
 			return ret;
 		}
 	} else {
+		dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
+		buf_pool = pdata->rx_ring[0]->buf_pool;
 		pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
 	}
 
+	pdata->phy_speed = SPEED_UNKNOWN;
 	pdata->mac_ops->init(pdata);
 
 	return ret;
@@ -1563,22 +1637,6 @@ static void xgene_enet_napi_add(struct xgene_enet_pdata *pdata)
 	}
 }
 
-static void xgene_enet_napi_del(struct xgene_enet_pdata *pdata)
-{
-	struct napi_struct *napi;
-	int i;
-
-	for (i = 0; i < pdata->rxq_cnt; i++) {
-		napi = &pdata->rx_ring[i]->napi;
-		netif_napi_del(napi);
-	}
-
-	for (i = 0; i < pdata->cq_cnt; i++) {
-		napi = &pdata->tx_ring[i]->cp_ring->napi;
-		netif_napi_del(napi);
-	}
-}
-
 static int xgene_enet_probe(struct platform_device *pdev)
 {
 	struct net_device *ndev;
@@ -1609,8 +1667,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
 	of_id = of_match_device(xgene_enet_of_match, &pdev->dev);
 	if (of_id) {
 		pdata->enet_id = (enum xgene_enet_id)of_id->data;
-	}
-	else {
+	} else {
 #ifdef CONFIG_ACPI
 		const struct acpi_device_id *acpi_id;
 		enum xgene_enet_id enet_id;
@@ -1622,6 +1679,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
 		}
 #endif
 	}
+
 	if (!pdata->enet_id) {
 		free_netdev(ndev);
 		return -ENODEV;
@@ -1656,23 +1714,25 @@ static int xgene_enet_probe(struct platform_device *pdev)
 		goto err_netdev;
 
 	link_state = pdata->mac_ops->link_state;
-	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
-		ret = xgene_enet_mdio_config(pdata);
-		if (ret)
-			goto err_netdev;
-	} else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
+	ret = 0;
+	if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
+		INIT_DELAYED_WORK(&pdata->link_work, link_state);
+	} else {
 		if (pdata->mdio_driver)
 			ret = xgene_enet_phy_connect(ndev);
+		else if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
+			ret = xgene_enet_mdio_config(pdata);
 		else
 			INIT_DELAYED_WORK(&pdata->link_work, link_state);
-	} else {
-		INIT_DELAYED_WORK(&pdata->link_work, link_state);
 	}
+	if (ret)
+		goto err;
 
 	xgene_enet_napi_add(pdata);
 	return 0;
 err_netdev:
-	unregister_netdev(ndev);
+	if (ndev->reg_state == NETREG_REGISTERED)
+		unregister_netdev(ndev);
 err:
 	free_netdev(ndev);
 	return ret;
@@ -1691,11 +1751,16 @@ static int xgene_enet_remove(struct platform_device *pdev)
 	mac_ops->rx_disable(pdata);
 	mac_ops->tx_disable(pdata);
 
-	xgene_enet_napi_del(pdata);
-	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
-		xgene_enet_mdio_remove(pdata);
-	else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII)
+	rtnl_lock();
+	if (netif_running(ndev))
+		dev_close(ndev);
+	rtnl_unlock();
+
+	if (pdata->mdio_driver)
 		xgene_enet_phy_disconnect(pdata);
+	else if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
+		xgene_enet_mdio_remove(pdata);
+
 	unregister_netdev(ndev);
 	xgene_enet_delete_desc_rings(pdata);
 	pdata->port_ops->shutdown(pdata);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index 0fe1a96..c2804c2 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -212,6 +212,8 @@ struct xgene_enet_pdata {
 	u32 mss;
 	u8 tx_delay;
 	u8 rx_delay;
+	struct device_node *mdio_np;
+	int phy_id;
 	bool mdio_driver;
 };
 
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index a7a6c05..ae93dc2 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -257,9 +257,7 @@ static void xgene_sgmac_set_speed(struct xgene_enet_pdata *p)
 	u32 mc2, value;
 
 	if (p->phy_speed != SPEED_UNKNOWN) {
-		value = xgene_mii_phy_read(p, INT_PHY_ADDR,
-					   SGMII_BASE_PAGE_ABILITY_ADDR >> 2);
-		if (!(value & LINK_UP)) {
+		if (!xgene_enet_link_status(p)) {
 			xgene_mii_phy_write(p, INT_PHY_ADDR,
 					    SGMII_TBI_CONTROL_ADDR >> 2,
 					    0x8000);
@@ -325,7 +323,8 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
 	u32 enet_spare_cfg_reg, rsif_config_reg;
 	u32 cfg_bypass_reg, rx_dv_gate_reg;
 
-	xgene_sgmac_reset(p);
+	if (!(p->enet_id == XGENE_ENET2 && p->mdio_driver))
+		xgene_sgmac_reset(p);
 
 	/* Enable auto-negotiation */
 	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2,
@@ -416,6 +415,8 @@ static void xgene_sgmac_tx_disable(struct xgene_enet_pdata *p)
 
 static int xgene_enet_reset(struct xgene_enet_pdata *p)
 {
+	int ret;
+
 	if (!xgene_ring_mgr_init(p))
 		return -ENODEV;
 
@@ -428,7 +429,9 @@ static int xgene_enet_reset(struct xgene_enet_pdata *p)
 		clk_prepare_enable(p->clk);
 	}
 
-	xgene_enet_ecc_init(p);
+	ret = xgene_enet_ecc_init(p);
+	if (ret)
+		return ret;
 	xgene_enet_config_ring_if_assoc(p);
 
 	return 0;
-- 
1.9.1



From isubramanian at apm.com  Tue May 31 17:10:38 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Tue, 31 May 2016 17:10:38 -0700
Subject: [PATCH v2 3/5] drivers: net: phy: Add MDIO driver
In-Reply-To: <1464739840-21971-1-git-send-email-isubramanian@apm.com>
References: <1464739840-21971-1-git-send-email-isubramanian@apm.com>
Message-ID: <1464739840-21971-4-git-send-email-isubramanian@apm.com>

Currently, SGMII based 1G rely on the hardware registers for link state
and sometimes it's not reliable.  To get most accurate link state, this
interface has to use the MDIO bus to poll the PHY.

In X-Gene SoC, MDIO bus is shared across RGMII and SGMII based 1G
interfaces, so adding this driver to manage MDIO bus.  This driver
registers the mdio bus and registers the PHYs connected to it.

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Fushen Chen <fchen at apm.com>
Tested-by: Toan Le <toanle at apm.com>
Tested-by: Matthias Brugger <mbrugger at suse.com>
---
 drivers/net/ethernet/apm/xgene/Kconfig |   1 +
 drivers/net/phy/Kconfig                |   7 +
 drivers/net/phy/Makefile               |   1 +
 drivers/net/phy/mdio-xgene.c           | 531 +++++++++++++++++++++++++++++++++
 drivers/net/phy/mdio-xgene.h           | 140 +++++++++
 5 files changed, 680 insertions(+)
 create mode 100644 drivers/net/phy/mdio-xgene.c
 create mode 100644 drivers/net/phy/mdio-xgene.h

diff --git a/drivers/net/ethernet/apm/xgene/Kconfig b/drivers/net/ethernet/apm/xgene/Kconfig
index 19e38af..300e3b5 100644
--- a/drivers/net/ethernet/apm/xgene/Kconfig
+++ b/drivers/net/ethernet/apm/xgene/Kconfig
@@ -3,6 +3,7 @@ config NET_XGENE
 	depends on HAS_DMA
 	depends on ARCH_XGENE || COMPILE_TEST
 	select PHYLIB
+	select MDIO_XGENE
 	help
 	  This is the Ethernet driver for the on-chip ethernet interface on the
 	  APM X-Gene SoC.
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 6dad9a9..193f418 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -271,6 +271,13 @@ config MDIO_BCM_IPROC
 	  This module provides a driver for the MDIO busses found in the
 	  Broadcom iProc SoC's.
 
+config MDIO_XGENE
+       tristate "APM X-Gene SoC MDIO bus controller"
+       help
+         This module provides a driver for the MDIO busses found in the
+         APM X-Gene SoC's.
+
+
 endif # PHYLIB
 
 config MICREL_KS8995MA
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index fcdbb92..9cbd2af 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -44,3 +44,4 @@ obj-$(CONFIG_MDIO_MOXART)	+= mdio-moxart.o
 obj-$(CONFIG_MDIO_BCM_UNIMAC)	+= mdio-bcm-unimac.o
 obj-$(CONFIG_MICROCHIP_PHY)	+= microchip.o
 obj-$(CONFIG_MDIO_BCM_IPROC)	+= mdio-bcm-iproc.o
+obj-$(CONFIG_MDIO_XGENE)	+= mdio-xgene.o
diff --git a/drivers/net/phy/mdio-xgene.c b/drivers/net/phy/mdio-xgene.c
new file mode 100644
index 0000000..bd07fd9
--- /dev/null
+++ b/drivers/net/phy/mdio-xgene.c
@@ -0,0 +1,531 @@
+/* Applied Micro X-Gene SoC MDIO Driver
+ *
+ * Copyright (c) 2016, Applied Micro Circuits Corporation
+ * Author: Iyappan Subramanian <isubramanian at apm.com>
+ *
+ * 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.
+ *
+ * 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/acpi.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/efi.h>
+#include <linux/if_vlan.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/of_mdio.h>
+#include <linux/prefetch.h>
+#include <linux/phy.h>
+#include <net/ip.h>
+#include "mdio-xgene.h"
+
+static bool xgene_mdio_status;
+
+static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
+				   void __iomem *cmd, void __iomem *cmd_done,
+				   u32 rd_addr, u32 *rd_data)
+{
+	u32 done;
+	u8 wait = 10;
+
+	iowrite32(rd_addr, addr);
+	iowrite32(XGENE_ENET_RD_CMD, cmd);
+
+	/* wait for read command to complete */
+	while (!(done = ioread32(cmd_done)) && wait--)
+		udelay(1);
+
+	if (!done)
+		return false;
+
+	*rd_data = ioread32(rd);
+	iowrite32(0, cmd);
+
+	return true;
+}
+
+static void xgene_enet_rd_mcx_mac(struct xgene_mdio_pdata *pdata,
+				  u32 rd_addr, u32 *rd_data)
+{
+	void __iomem *addr, *rd, *cmd, *cmd_done;
+
+	addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET;
+	rd = pdata->mac_csr_addr + MAC_READ_REG_OFFSET;
+	cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET;
+	cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+	if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
+		dev_err(pdata->dev, "MCX mac read failed, addr: 0x%04x\n",
+			rd_addr);
+}
+
+static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr,
+				   void __iomem *cmd, void __iomem *cmd_done,
+				   u32 wr_addr, u32 wr_data)
+{
+	u32 done;
+	u8 wait = 10;
+
+	iowrite32(wr_addr, addr);
+	iowrite32(wr_data, wr);
+	iowrite32(XGENE_ENET_WR_CMD, cmd);
+
+	/* wait for write command to complete */
+	while (!(done = ioread32(cmd_done)) && wait--)
+		udelay(1);
+
+	if (!done)
+		return false;
+
+	iowrite32(0, cmd);
+
+	return true;
+}
+
+static void xgene_enet_wr_mcx_mac(struct xgene_mdio_pdata *pdata,
+				  u32 wr_addr, u32 wr_data)
+{
+	void __iomem *addr, *wr, *cmd, *cmd_done;
+
+	addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET;
+	wr = pdata->mac_csr_addr + MAC_WRITE_REG_OFFSET;
+	cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET;
+	cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET;
+
+	if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data))
+		dev_err(pdata->dev, "MCX mac write failed, addr: 0x%04x\n",
+			wr_addr);
+}
+
+static int xgene_mii_phy_read(struct xgene_mdio_pdata *pdata,
+			      u8 phy_id, u32 reg)
+{
+	u32 data, done;
+	u8 wait = 10;
+
+	data = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, data);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK);
+	do {
+		usleep_range(5, 10);
+		xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done);
+	} while ((done & BUSY_MASK) && wait--);
+
+	if (done & BUSY_MASK) {
+		dev_err(pdata->dev, "MII_MGMT read failed\n");
+		return -EBUSY;
+	}
+
+	xgene_enet_rd_mcx_mac(pdata, MII_MGMT_STATUS_ADDR, &data);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, 0);
+
+	return data;
+}
+
+static int xgene_mii_phy_write(struct xgene_mdio_pdata *pdata, int phy_id,
+			       u32 reg, u16 data)
+{
+	u32 val, done;
+	u8 wait = 10;
+
+	val = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg);
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, val);
+
+	xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONTROL_ADDR, data);
+	do {
+		usleep_range(5, 10);
+		xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done);
+	} while ((done & BUSY_MASK) && wait--);
+
+	if (done & BUSY_MASK) {
+		dev_err(pdata->dev, "MII_MGMT write failed\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int xgene_mdio_rgmii_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	struct xgene_mdio_pdata *pdata = bus->priv;
+	u32 val;
+
+	val = xgene_mii_phy_read(pdata, mii_id, regnum);
+	dev_dbg(pdata->dev, "MDIO read: bus=%d reg=%d val=0x%x\n",
+		mii_id, regnum, val);
+
+	return val;
+}
+
+static int xgene_mdio_rgmii_write(struct mii_bus *bus, int mii_id, int regnum,
+				  u16 val)
+{
+	struct xgene_mdio_pdata *pdata = bus->priv;
+
+	dev_dbg(pdata->dev, "MDIO write: bus=%d reg=%d val=0x%x\n",
+		mii_id, regnum, val);
+
+	return xgene_mii_phy_write(pdata, mii_id, regnum, val);
+}
+
+static u32 xgene_menet_rd_diag_csr(struct xgene_mdio_pdata *pdata,
+				   u32 offset)
+{
+	return ioread32(pdata->diag_csr_addr + offset);
+}
+
+static void xgene_menet_wr_diag_csr(struct xgene_mdio_pdata *pdata,
+				    u32 offset, u32 val)
+{
+	iowrite32(val, pdata->diag_csr_addr + offset);
+}
+
+static int xgene_enet_ecc_init(struct xgene_mdio_pdata *pdata)
+{
+	u32 data;
+	u8 wait = 10;
+
+	xgene_menet_wr_diag_csr(pdata, MENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0);
+	do {
+		usleep_range(100, 110);
+		data = xgene_menet_rd_diag_csr(pdata, MENET_BLOCK_MEM_RDY_ADDR);
+	} while ((data != 0xffffffff) && wait--);
+
+	if (data != 0xffffffff) {
+		dev_err(pdata->dev, "Failed to release memory from shutdown\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void xgene_gmac_reset(struct xgene_mdio_pdata *pdata)
+{
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET);
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0);
+}
+
+static int xgene_mdio_reset(struct xgene_mdio_pdata *pdata)
+{
+	int ret;
+
+	if (pdata->mdio_id == XGENE_MDIO_RGMII) {
+		if (pdata->dev->of_node) {
+			clk_prepare_enable(pdata->clk);
+			clk_disable_unprepare(pdata->clk);
+			clk_prepare_enable(pdata->clk);
+		} else {
+#ifdef CONFIG_ACPI
+			acpi_evaluate_object(ACPI_HANDLE(pdata->dev),
+					     "_RST", NULL, NULL);
+#endif
+		}
+	} else {
+#ifdef CONFIG_ACPI
+		acpi_evaluate_object(ACPI_HANDLE(pdata->dev),
+				     "_RST", NULL, NULL);
+#endif
+	}
+
+	ret = xgene_enet_ecc_init(pdata);
+	if (ret)
+		return ret;
+	xgene_gmac_reset(pdata);
+
+	return 0;
+}
+
+static void xgene_enet_rd_mdio_csr(struct xgene_mdio_pdata  *pdata,
+				   u32 offset, u32 *val)
+{
+	void __iomem *addr = pdata->mdio_csr_addr  + offset;
+
+	*val = ioread32(addr);
+}
+
+static void xgene_enet_wr_mdio_csr(struct xgene_mdio_pdata *pdata,
+				   u32 offset, u32 val)
+{
+	void __iomem *addr = pdata->mdio_csr_addr  + offset;
+
+	iowrite32(val, addr);
+}
+
+static int xgene_xfimii_phy_write(struct xgene_mdio_pdata *pdata, int phy_id,
+				  u32 reg, u16 data)
+{
+	int timeout = 100;
+	u32 status, val;
+
+	val = SET_VAL(HSTPHYADX, phy_id) | SET_VAL(HSTREGADX, reg) |
+	      SET_VAL(HSTMIIMWRDAT, data);
+	xgene_enet_wr_mdio_csr(pdata, MIIM_FIELD_ADDR, data);
+
+	val = HSTLDCMD | SET_VAL(HSTMIIMCMD, MIIM_CMD_LEGACY_WRITE);
+	xgene_enet_wr_mdio_csr(pdata, MIIM_COMMAND_ADDR, val);
+
+	do {
+		usleep_range(5, 10);
+		xgene_enet_rd_mdio_csr(pdata, MIIM_INDICATOR_ADDR, &status);
+	} while ((status & BUSY_MASK) && timeout--);
+
+	xgene_enet_wr_mdio_csr(pdata, MIIM_COMMAND_ADDR, 0);
+	return 0;
+}
+
+static int xgene_xfimii_phy_read(struct xgene_mdio_pdata *pdata,
+				 u8 phy_id, u32 reg)
+{
+	u32 data, status, val;
+	int timeout = 100;
+
+	val = SET_VAL(HSTPHYADX, phy_id) | SET_VAL(HSTREGADX, reg);
+	xgene_enet_wr_mdio_csr(pdata, MIIM_FIELD_ADDR, val);
+
+	val = HSTLDCMD | SET_VAL(HSTMIIMCMD, MIIM_CMD_LEGACY_READ);
+	xgene_enet_wr_mdio_csr(pdata, MIIM_COMMAND_ADDR, val);
+
+	do {
+		usleep_range(5, 10);
+		xgene_enet_rd_mdio_csr(pdata, MIIM_INDICATOR_ADDR, &status);
+	} while ((status & BUSY_MASK) && timeout--);
+
+	if (status & BUSY_MASK) {
+		dev_err(pdata->dev, "XGENET_MII_MGMT write failed\n");
+		return -EBUSY;
+	}
+	xgene_enet_rd_mdio_csr(pdata, MIIMRD_FIELD_ADDR, &data);
+	xgene_enet_wr_mdio_csr(pdata, MIIM_COMMAND_ADDR, 0);
+
+	return data;
+}
+
+static int xgene_xfi_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+	struct xgene_mdio_pdata  *pdata = bus->priv;
+	u32 val;
+
+	dev_dbg(pdata->dev, "MDIO read: bus=%d reg=%d val=0x%x\n",
+		mii_id, regnum, val);
+	val = xgene_xfimii_phy_read(pdata, mii_id, regnum);
+
+	return val;
+}
+
+static int xgene_xfi_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+				u16 val)
+{
+	struct xgene_mdio_pdata *pdata = bus->priv;
+
+	dev_dbg(pdata->dev, "MDIO write: bus=%d reg=%d val=0x%x\n",
+		mii_id, regnum, val);
+
+	return xgene_xfimii_phy_write(pdata, mii_id, regnum, val);
+}
+
+#ifdef CONFIG_ACPI
+static acpi_status acpi_register_phy(acpi_handle handle, u32 lvl,
+				     void *context, void **ret)
+{
+	struct mii_bus *mdio = context;
+	struct acpi_device *adev;
+	struct phy_device *phy_dev;
+	const union acpi_object *obj;
+	u32 phy_addr;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
+
+	if (acpi_dev_get_property(adev, "phy-channel", ACPI_TYPE_INTEGER, &obj))
+		return AE_OK;
+	phy_addr = obj->integer.value;
+
+	phy_dev = get_phy_device(mdio, phy_addr, false);
+	adev->driver_data = phy_dev;
+	if (!phy_dev || IS_ERR(phy_dev))
+		return AE_OK;
+
+	if (phy_device_register(phy_dev))
+		phy_device_free(phy_dev);
+
+	return AE_OK;
+}
+#endif
+
+bool xgene_mdio_probe_successful(void)
+{
+	return xgene_mdio_status;
+}
+EXPORT_SYMBOL(xgene_mdio_probe_successful);
+
+static int xgene_mdio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mii_bus *mdio_bus;
+	const struct of_device_id *of_id;
+	struct resource *res;
+	struct xgene_mdio_pdata *pdata;
+	void __iomem *csr_addr;
+	int mdio_id = 0, ret = 0;
+
+	of_id = of_match_device(xgene_mdio_of_match, &pdev->dev);
+	if (of_id) {
+		mdio_id = (enum xgene_mdio_id)of_id->data;
+	} else {
+#ifdef CONFIG_ACPI
+		const struct acpi_device_id *acpi_id;
+
+		acpi_id = acpi_match_device(xgene_mdio_acpi_match, &pdev->dev);
+		if (acpi_id)
+			mdio_id = (enum xgene_mdio_id)acpi_id->driver_data;
+#endif
+	}
+
+	if (!mdio_id)
+		return -ENODEV;
+
+	pdata = devm_kzalloc(dev, sizeof(struct xgene_mdio_pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+	pdata->mdio_id = mdio_id;
+	pdata->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "Resource mac_ind_csr not defined\n");
+		return -ENODEV;
+	}
+
+	csr_addr = devm_ioremap(dev, res->start, resource_size(res));
+	if (!csr_addr) {
+		dev_err(dev, "Unable to retrieve mac CSR region\n");
+		return -ENOMEM;
+	}
+	pdata->mac_csr_addr = csr_addr;
+	pdata->mdio_csr_addr = csr_addr + BLOCK_XG_MDIO_CSR_OFFSET;
+	pdata->diag_csr_addr = csr_addr + BLOCK_DIAG_CSR_OFFSET;
+
+	if (dev->of_node) {
+		pdata->clk = devm_clk_get(dev, NULL);
+		if (IS_ERR(pdata->clk)) {
+			dev_err(dev, "Unable to retrieve clk\n");
+			return -ENODEV;
+		}
+	}
+
+	ret = xgene_mdio_reset(pdata);
+	if (ret)
+		return ret;
+
+	mdio_bus = mdiobus_alloc();
+	if (!mdio_bus)
+		return -ENOMEM;
+
+	mdio_bus->name = "APM X-Gene MDIO bus";
+	snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%d", "xgene-mii",
+		 mdio_id);
+
+	if (mdio_id == XGENE_MDIO_RGMII) {
+		mdio_bus->read = xgene_mdio_rgmii_read;
+		mdio_bus->write = xgene_mdio_rgmii_write;
+	} else {
+		mdio_bus->read = xgene_xfi_mdio_read;
+		mdio_bus->write = xgene_xfi_mdio_write;
+	}
+
+	mdio_bus->priv = pdata;
+	mdio_bus->parent = dev;
+	platform_set_drvdata(pdev, mdio_bus);
+
+	if (dev->of_node) {
+		ret = of_mdiobus_register(mdio_bus, dev->of_node);
+	} else {
+#ifdef CONFIG_ACPI
+		/* Mask out all PHYs from auto probing. */
+		mdio_bus->phy_mask = ~0;
+		ret = mdiobus_register(mdio_bus);
+		if (ret)
+			goto out;
+
+		acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_HANDLE(dev), 1,
+				    acpi_register_phy, NULL, mdio_bus, NULL);
+#endif
+	}
+
+	if (ret)
+		goto out;
+
+	xgene_mdio_status = true;
+
+	return 0;
+out:
+	if (mdio_bus->state == MDIOBUS_REGISTERED)
+		mdiobus_unregister(mdio_bus);
+	mdiobus_free(mdio_bus);
+
+	return ret;
+}
+
+static int xgene_mdio_remove(struct platform_device *pdev)
+{
+	struct mii_bus *mdio_bus = platform_get_drvdata(pdev);
+
+	mdiobus_unregister(mdio_bus);
+	mdiobus_free(mdio_bus);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id xgene_mdio_of_match[] = {
+	{
+		.compatible = "apm,xgene-mdio-rgmii",
+		.data = (void *)XGENE_MDIO_RGMII
+	},
+	{
+		.compatible = "apm,xgene-mdio-xfi",
+		.data = (void *)XGENE_MDIO_XFI},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, xgene_mdio_of_match);
+#endif
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id xgene_mdio_acpi_match[] = {
+	{ "APMC0D65", XGENE_MDIO_RGMII },
+	{ "APMC0D66", XGENE_MDIO_XFI },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(acpi, xgene_mdio_acpi_match);
+#endif
+
+static struct platform_driver xgene_mdio_driver = {
+	.driver = {
+		.name = "xgene-mdio",
+		.of_match_table = of_match_ptr(xgene_mdio_of_match),
+		.acpi_match_table = ACPI_PTR(xgene_mdio_acpi_match),
+	},
+	.probe = xgene_mdio_probe,
+	.remove = xgene_mdio_remove,
+};
+
+module_platform_driver(xgene_mdio_driver);
+
+MODULE_DESCRIPTION("APM X-Gene SoC MDIO driver");
+MODULE_AUTHOR("Iyappan Subramanian <isubramanian at apm.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/mdio-xgene.h b/drivers/net/phy/mdio-xgene.h
new file mode 100644
index 0000000..08b4323
--- /dev/null
+++ b/drivers/net/phy/mdio-xgene.h
@@ -0,0 +1,140 @@
+/* Applied Micro X-Gene SoC MDIO Driver
+ *
+ * Copyright (c) 2016, Applied Micro Circuits Corporation
+ * Author: Iyappan Subramanian <isubramanian at apm.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MDIO_XGENE_H__
+#define __MDIO_XGENE_H__
+
+#define BLOCK_XG_MDIO_CSR_OFFSET	0x5000
+#define BLOCK_DIAG_CSR_OFFSET		0xd000
+#define XGENET_CONFIG_REG_ADDR		0x20
+
+#define MAC_ADDR_REG_OFFSET		0x00
+#define MAC_COMMAND_REG_OFFSET		0x04
+#define MAC_WRITE_REG_OFFSET		0x08
+#define MAC_READ_REG_OFFSET		0x0c
+#define MAC_COMMAND_DONE_REG_OFFSET	0x10
+
+#define CLKEN_OFFSET			0x08
+#define SRST_OFFSET			0x00
+
+#define MENET_CFG_MEM_RAM_SHUTDOWN_ADDR	0x70
+#define MENET_BLOCK_MEM_RDY_ADDR	0x74
+
+#define MAC_CONFIG_1_ADDR		0x00
+#define MII_MGMT_COMMAND_ADDR		0x24
+#define MII_MGMT_ADDRESS_ADDR		0x28
+#define MII_MGMT_CONTROL_ADDR		0x2c
+#define MII_MGMT_STATUS_ADDR		0x30
+#define MII_MGMT_INDICATORS_ADDR	0x34
+#define SOFT_RESET			BIT(31)
+
+#define MII_MGMT_CONFIG_ADDR            0x20
+#define MII_MGMT_COMMAND_ADDR           0x24
+#define MII_MGMT_ADDRESS_ADDR           0x28
+#define MII_MGMT_CONTROL_ADDR           0x2c
+#define MII_MGMT_STATUS_ADDR            0x30
+#define MII_MGMT_INDICATORS_ADDR        0x34
+
+#define MIIM_COMMAND_ADDR               0x20
+#define MIIM_FIELD_ADDR                 0x24
+#define MIIM_CONFIGURATION_ADDR         0x28
+#define MIIM_LINKFAILVECTOR_ADDR        0x2c
+#define MIIM_INDICATOR_ADDR             0x30
+#define MIIMRD_FIELD_ADDR               0x34
+
+#define MDIO_CSR_OFFSET			0x5000
+
+#define REG_ADDR_POS			0
+#define REG_ADDR_LEN			5
+#define PHY_ADDR_POS			8
+#define PHY_ADDR_LEN			5
+
+#define HSTMIIMWRDAT_POS		0
+#define HSTMIIMWRDAT_LEN		16
+#define HSTPHYADX_POS			23
+#define HSTPHYADX_LEN			5
+#define HSTREGADX_POS			18
+#define HSTREGADX_LEN			5
+#define HSTLDCMD			BIT(3)
+#define HSTMIIMCMD_POS			0
+#define HSTMIIMCMD_LEN			3
+
+#define BUSY_MASK			BIT(0)
+#define READ_CYCLE_MASK			BIT(0)
+
+enum xgene_enet_cmd {
+	XGENE_ENET_WR_CMD = BIT(31),
+	XGENE_ENET_RD_CMD = BIT(30)
+};
+
+enum {
+	MIIM_CMD_IDLE,
+	MIIM_CMD_LEGACY_WRITE,
+	MIIM_CMD_LEGACY_READ,
+};
+
+enum xgene_mdio_id {
+	XGENE_MDIO_RGMII = 1,
+	XGENE_MDIO_XFI
+};
+
+struct xgene_mdio_pdata {
+	struct clk *clk;
+	struct device *dev;
+	void __iomem *mac_csr_addr;
+	void __iomem *diag_csr_addr;
+	void __iomem *mdio_csr_addr;
+	int mdio_id;
+};
+
+/* Set the specified value into a bit-field defined by its starting position
+ * and length within a single u64.
+ */
+static inline u64 xgene_enet_set_field_value(int pos, int len, u64 val)
+{
+	return (val & ((1ULL << len) - 1)) << pos;
+}
+
+#define SET_VAL(field, val) \
+		xgene_enet_set_field_value(field ## _POS, field ## _LEN, val)
+
+#define SET_BIT(field) \
+		xgene_enet_set_field_value(field ## _POS, 1, 1)
+
+/* Get the value from a bit-field defined by its starting position
+ * and length within the specified u64.
+ */
+static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src)
+{
+	return (src >> pos) & ((1ULL << len) - 1);
+}
+
+#define GET_VAL(field, src) \
+		xgene_enet_get_field_value(field ## _POS, field ## _LEN, src)
+
+#define GET_BIT(field, src) \
+		xgene_enet_get_field_value(field ## _POS, 1, src)
+
+static const struct of_device_id xgene_mdio_of_match[];
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id xgene_mdio_acpi_match[];
+#endif
+bool xgene_mdio_probe_successful(void);
+
+#endif  /* __MDIO_XGENE_H__ */
-- 
1.9.1



From isubramanian at apm.com  Tue May 31 17:10:40 2016
From: isubramanian at apm.com (Iyappan Subramanian)
Date: Tue, 31 May 2016 17:10:40 -0700
Subject: [PATCH v2 5/5] drivers: net: xgene: Fix module load/unload crash
In-Reply-To: <1464739840-21971-1-git-send-email-isubramanian@apm.com>
References: <1464739840-21971-1-git-send-email-isubramanian@apm.com>
Message-ID: <1464739840-21971-6-git-send-email-isubramanian@apm.com>

When the driver is configured as kernel module and when it gets unloaded
and reloaded, kernel crash was observed, due to incomplete hardware
cleanup.  This patch addresses this issue with the following changes,

- Reordered mac enable and disable
- Added hardware prefetch buffer cleanup
- Added Tx completion ring free
- Fixed delete bufpool
- Moved down delete_desc_rings after ring cleanup

- Moved regsiter_netdev call after hardware is ready
- deleted napi_del function call, since it's called by free_netdev
- Calling netif_tx_start_queues and netif_tx_stop_queues
- correcting setting irq_name before calling request_irq.
- Calling dev_close() within remove
- Added shutdown callback
- Changed to use dmam_ APIs

Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
Tested-by: Fushen Chen <fchen at apm.com>
Tested-by: Toan Le <toanle at apm.com>
Tested-by: Matthias Brugger <mbrugger at suse.com>
---
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c    |  71 +++++++-
 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h    |  14 +-
 drivers/net/ethernet/apm/xgene/xgene_enet_main.c  | 199 +++++++++++++---------
 drivers/net/ethernet/apm/xgene/xgene_enet_main.h  |  32 +---
 drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c |  90 ++++++++--
 drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c |  66 ++++++-
 6 files changed, 329 insertions(+), 143 deletions(-)

diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index 38d6ee4..8e3827f 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -684,21 +684,75 @@ static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
 	if (!xgene_ring_mgr_init(pdata))
 		return -ENODEV;
 
-	if (!pdata->mdio_driver) {
-		if (!IS_ERR(pdata->clk)) {
-			clk_prepare_enable(pdata->clk);
-			clk_disable_unprepare(pdata->clk);
-			clk_prepare_enable(pdata->clk);
-			xgene_enet_ecc_init(pdata);
+	if (pdata->mdio_driver) {
+		xgene_enet_config_ring_if_assoc(pdata);
+		return 0;
+	}
+	if (!IS_ERR(pdata->clk)) {
+		clk_prepare_enable(pdata->clk);
+		clk_disable_unprepare(pdata->clk);
+		clk_prepare_enable(pdata->clk);
+	} else {
+#ifdef CONFIG_ACPI
+		if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev), "_RST")) {
+			acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev),
+					     "_RST", NULL, NULL);
+		} else if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev),
+					 "_INI")) {
+			acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev),
+					     "_INI", NULL, NULL);
 		}
+#endif
 	}
+
+	xgene_enet_ecc_init(pdata);
 	xgene_enet_config_ring_if_assoc(pdata);
 
 	return 0;
 }
 
+static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
+			     struct xgene_enet_desc_ring *ring)
+{
+	u32 addr, val, data;
+
+	val = xgene_enet_ring_bufnum(ring->id);
+
+	if (xgene_enet_is_bufpool(ring->id)) {
+		addr = ENET_CFGSSQMIFPRESET_ADDR;
+		data = BIT(val - 0x20);
+	} else {
+		addr = ENET_CFGSSQMIWQRESET_ADDR;
+		data = BIT(val);
+	}
+
+	xgene_enet_wr_ring_if(pdata, addr, data);
+}
+
 static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
 {
+	struct xgene_enet_desc_ring *ring;
+	u32 pb, val;
+	int i;
+
+	pb = 0;
+	for (i = 0; i < pdata->rxq_cnt; i++) {
+		ring = pdata->rx_ring[i]->buf_pool;
+
+		val = xgene_enet_ring_bufnum(ring->id);
+		pb |= BIT(val - 0x20);
+	}
+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
+
+	pb = 0;
+	for (i = 0; i < pdata->txq_cnt; i++) {
+		ring = pdata->tx_ring[i];
+
+		val = xgene_enet_ring_bufnum(ring->id);
+		pb |= BIT(val);
+	}
+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
+
 	if (!IS_ERR(pdata->clk))
 		clk_disable_unprepare(pdata->clk);
 }
@@ -748,7 +802,7 @@ static void xgene_enet_adjust_link(struct net_device *ndev)
 }
 
 #ifdef CONFIG_ACPI
-static struct acpi_device *acpi_phy_find_device(struct device *dev)
+struct acpi_device *acpi_phy_find_device(struct device *dev)
 {
 	struct acpi_reference_args args;
 	struct fwnode_handle *fw_node;
@@ -869,7 +923,7 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
 		 ndev->name);
 
 	mdio_bus->priv = pdata;
-	mdio_bus->parent = &ndev->dev;
+	mdio_bus->parent = &pdata->pdev->dev;
 
 	ret = xgene_mdiobus_register(pdata, mdio_bus);
 	if (ret) {
@@ -917,6 +971,7 @@ const struct xgene_mac_ops xgene_gmac_ops = {
 
 const struct xgene_port_ops xgene_gport_ops = {
 	.reset = xgene_enet_reset,
+	.clear = xgene_enet_clear,
 	.cle_bypass = xgene_enet_cle_bypass,
 	.shutdown = xgene_gport_shutdown,
 };
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
index 5540db9..c656a1c 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
@@ -113,9 +113,13 @@ enum xgene_enet_rm {
 #define BLOCK_ETH_DIAG_CSR_OFFSET	0xD000
 #define BLOCK_ETH_MAC_OFFSET		0x0000
 #define BLOCK_ETH_MAC_CSR_OFFSET	0x2800
+#define BLOCK_ETH_CLKRST_SRST_OFFSET	0xa000
+#define BLOCK_ETH_CLKRST_CLKEN_OFFSET	0xa008
 
 #define CLKEN_ADDR			0xc208
 #define SRST_ADDR			0xc200
+#define XGENE_CLKEN_ADDR		0xa008
+#define XGENE_SRST_ADDR			0xa000
 
 #define MAC_ADDR_REG_OFFSET		0x00
 #define MAC_COMMAND_REG_OFFSET		0x04
@@ -168,6 +172,8 @@ enum xgene_enet_rm {
 #define TX_DV_GATE_EN0			BIT(2)
 #define RX_DV_GATE_EN0			BIT(1)
 #define RESUME_RX0			BIT(0)
+#define ENET_CFGSSQMIFPRESET_ADDR		0x14
+#define ENET_CFGSSQMIWQRESET_ADDR		0x1c
 #define ENET_CFGSSQMIWQASSOC_ADDR		0xe0
 #define ENET_CFGSSQMIFPQASSOC_ADDR		0xdc
 #define ENET_CFGSSQMIQMLITEFPQASSOC_ADDR	0xf0
@@ -300,11 +306,6 @@ enum xgene_enet_ring_bufnum {
 	RING_BUFNUM_INVALID
 };
 
-enum xgene_enet_cmd {
-	XGENE_ENET_WR_CMD = BIT(31),
-	XGENE_ENET_RD_CMD = BIT(30)
-};
-
 enum xgene_enet_err_code {
 	HBF_READ_DATA = 3,
 	HBF_LL_READ = 4,
@@ -352,6 +353,9 @@ void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
 bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);
 int xgene_enet_phy_connect(struct net_device *ndev);
 void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata);
+#ifdef CONFIG_ACPI
+struct acpi_device *acpi_phy_find_device(struct device *dev);
+#endif
 
 extern const struct xgene_mac_ops xgene_gmac_ops;
 extern const struct xgene_port_ops xgene_gport_ops;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index c31ea56..75da192 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -102,25 +102,13 @@ static u8 xgene_enet_hdr_len(const void *data)
 
 static void xgene_enet_delete_bufpool(struct xgene_enet_desc_ring *buf_pool)
 {
-	struct xgene_enet_pdata *pdata = netdev_priv(buf_pool->ndev);
-	struct xgene_enet_raw_desc16 *raw_desc;
-	u32 slots = buf_pool->slots - 1;
-	u32 tail = buf_pool->tail;
-	u32 userinfo;
-	int i, len;
-
-	len = pdata->ring_ops->len(buf_pool);
-	for (i = 0; i < len; i++) {
-		tail = (tail - 1) & slots;
-		raw_desc = &buf_pool->raw_desc16[tail];
+	int i;
 
-		/* Hardware stores descriptor in little endian format */
-		userinfo = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
-		dev_kfree_skb_any(buf_pool->rx_skb[userinfo]);
+	/* Free up the buffers held by hardware */
+	for (i = 0; i < buf_pool->slots; i++) {
+		if (buf_pool->rx_skb[i])
+			dev_kfree_skb_any(buf_pool->rx_skb[i]);
 	}
-
-	pdata->ring_ops->wr_cmd(buf_pool, -len);
-	buf_pool->tail = tail;
 }
 
 static irqreturn_t xgene_enet_rx_irq(const int irq, void *data)
@@ -481,6 +469,7 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
 			 XGENE_ENET_MAX_MTU, DMA_FROM_DEVICE);
 	skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
 	skb = buf_pool->rx_skb[skb_index];
+	buf_pool->rx_skb[skb_index] = NULL;
 
 	/* checking for error */
 	status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) ||
@@ -619,6 +608,30 @@ static void xgene_enet_timeout(struct net_device *ndev)
 	}
 }
 
+static void xgene_enet_set_irq_name(struct net_device *ndev)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct xgene_enet_desc_ring *ring;
+	int i;
+
+	for (i = 0; i < pdata->rxq_cnt; i++) {
+		ring = pdata->rx_ring[i];
+		if (!pdata->cq_cnt) {
+			snprintf(ring->irq_name, IRQ_ID_SIZE, "%s-rx-txc",
+				 ndev->name);
+		} else {
+			snprintf(ring->irq_name, IRQ_ID_SIZE, "%s-rx-%d",
+				 ndev->name, i);
+		}
+	}
+
+	for (i = 0; i < pdata->cq_cnt; i++) {
+		ring = pdata->tx_ring[i]->cp_ring;
+		snprintf(ring->irq_name, IRQ_ID_SIZE, "%s-txc-%d",
+			 ndev->name, i);
+	}
+}
+
 static int xgene_enet_register_irq(struct net_device *ndev)
 {
 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
@@ -626,6 +639,7 @@ static int xgene_enet_register_irq(struct net_device *ndev)
 	struct xgene_enet_desc_ring *ring;
 	int ret = 0, i;
 
+	xgene_enet_set_irq_name(ndev);
 	for (i = 0; i < pdata->rxq_cnt; i++) {
 		ring = pdata->rx_ring[i];
 		irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
@@ -720,9 +734,6 @@ static int xgene_enet_open(struct net_device *ndev)
 	if (ret)
 		return ret;
 
-	mac_ops->tx_enable(pdata);
-	mac_ops->rx_enable(pdata);
-
 	xgene_enet_napi_enable(pdata);
 	ret = xgene_enet_register_irq(ndev);
 	if (ret)
@@ -734,7 +745,9 @@ static int xgene_enet_open(struct net_device *ndev)
 		netif_carrier_off(ndev);
 	}
 
-	netif_start_queue(ndev);
+	mac_ops->tx_enable(pdata);
+	mac_ops->rx_enable(pdata);
+	netif_tx_start_all_queues(ndev);
 
 	return ret;
 }
@@ -745,17 +758,17 @@ static int xgene_enet_close(struct net_device *ndev)
 	const struct xgene_mac_ops *mac_ops = pdata->mac_ops;
 	int i;
 
-	netif_stop_queue(ndev);
+	netif_tx_stop_all_queues(ndev);
+	mac_ops->tx_disable(pdata);
+	mac_ops->rx_disable(pdata);
 
 	if (pdata->phy_dev)
 		phy_stop(pdata->phy_dev);
 	else
 		cancel_delayed_work_sync(&pdata->link_work);
 
-	mac_ops->tx_disable(pdata);
-	mac_ops->rx_disable(pdata);
-
 	xgene_enet_free_irq(ndev);
+	netif_carrier_off(ndev);
 	xgene_enet_napi_disable(pdata);
 	for (i = 0; i < pdata->rxq_cnt; i++)
 		xgene_enet_process_ring(pdata->rx_ring[i], -1);
@@ -772,7 +785,7 @@ static void xgene_enet_delete_ring(struct xgene_enet_desc_ring *ring)
 	dev = ndev_to_dev(ring->ndev);
 
 	pdata->ring_ops->clear(ring);
-	dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
+	dmam_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
 }
 
 static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
@@ -785,6 +798,9 @@ static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
 		ring = pdata->tx_ring[i];
 		if (ring) {
 			xgene_enet_delete_ring(ring);
+			pdata->port_ops->clear(pdata, ring);
+			if (pdata->cq_cnt)
+				xgene_enet_delete_ring(ring->cp_ring);
 			pdata->tx_ring[i] = NULL;
 		}
 	}
@@ -795,6 +811,7 @@ static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
 			buf_pool = ring->buf_pool;
 			xgene_enet_delete_bufpool(buf_pool);
 			xgene_enet_delete_ring(buf_pool);
+			pdata->port_ops->clear(pdata, buf_pool);
 			xgene_enet_delete_ring(ring);
 			pdata->rx_ring[i] = NULL;
 		}
@@ -843,7 +860,7 @@ static void xgene_enet_free_desc_ring(struct xgene_enet_desc_ring *ring)
 
 	if (ring->desc_addr) {
 		pdata->ring_ops->clear(ring);
-		dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
+		dmam_free_coherent(dev, ring->size, ring->desc_addr, ring->dma);
 	}
 	devm_kfree(dev, ring);
 }
@@ -920,8 +937,8 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
 	ring->cfgsize = cfgsize;
 	ring->id = ring_id;
 
-	ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma,
-					      GFP_KERNEL);
+	ring->desc_addr = dmam_alloc_coherent(dev, size, &ring->dma,
+					GFP_KERNEL | __GFP_ZERO);
 	if (!ring->desc_addr) {
 		devm_kfree(dev, ring);
 		return NULL;
@@ -929,11 +946,12 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
 	ring->size = size;
 
 	if (is_irq_mbox_required(pdata, ring)) {
-		ring->irq_mbox_addr = dma_zalloc_coherent(dev, INTR_MBOX_SIZE,
-				&ring->irq_mbox_dma, GFP_KERNEL);
+		ring->irq_mbox_addr = dmam_alloc_coherent(dev, INTR_MBOX_SIZE,
+					&ring->irq_mbox_dma,
+					GFP_KERNEL | __GFP_ZERO);
 		if (!ring->irq_mbox_addr) {
-			dma_free_coherent(dev, size, ring->desc_addr,
-					  ring->dma);
+			dmam_free_coherent(dev, size, ring->desc_addr,
+					   ring->dma);
 			devm_kfree(dev, ring);
 			return NULL;
 		}
@@ -1028,13 +1046,6 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
 		rx_ring->nbufpool = NUM_BUFPOOL;
 		rx_ring->buf_pool = buf_pool;
 		rx_ring->irq = pdata->irqs[i];
-		if (!pdata->cq_cnt) {
-			snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx-txc",
-				 ndev->name);
-		} else {
-			snprintf(rx_ring->irq_name, IRQ_ID_SIZE, "%s-rx%d",
-				 ndev->name, i);
-		}
 		buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots,
 						sizeof(struct sk_buff *),
 						GFP_KERNEL);
@@ -1061,9 +1072,9 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
 		}
 
 		size = (tx_ring->slots / 2) * sizeof(__le64) * MAX_EXP_BUFFS;
-		tx_ring->exp_bufs = dma_zalloc_coherent(dev, size,
-							&dma_exp_bufs,
-							GFP_KERNEL);
+		tx_ring->exp_bufs = dmam_alloc_coherent(dev, size,
+					&dma_exp_bufs,
+					GFP_KERNEL | __GFP_ZERO);
 		if (!tx_ring->exp_bufs) {
 			ret = -ENOMEM;
 			goto err;
@@ -1087,8 +1098,6 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
 
 			cp_ring->irq = pdata->irqs[pdata->rxq_cnt + i];
 			cp_ring->index = i;
-			snprintf(cp_ring->irq_name, IRQ_ID_SIZE, "%s-txc%d",
-				 ndev->name, i);
 		}
 
 		cp_ring->cp_skb = devm_kcalloc(dev, tx_ring->slots,
@@ -1283,56 +1292,68 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata)
 static int xgene_enet_check_phy_handle(struct xgene_enet_pdata *pdata)
 {
 	struct device *dev = &pdata->pdev->dev;
-	int ret, phy_id, phy_mode = pdata->phy_mode;
-	struct device_node *mdio_np = NULL;
+	struct device_node *mdio_np;
+	bool mdio_probe_done;
 	const char *ph;
-#ifdef CONFIG_ACPI
-	struct acpi_reference_args args;
-	struct fwnode_handle *fw_node;
-#endif
+	u32 phy_id;
+	int ret;
+
+	if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII)
+		return 0;
 
 	if (!IS_ENABLED(CONFIG_MDIO_XGENE))
 		return 0;
 
-	if (dev->of_node) {
-		ret = device_property_read_string(dev, "phy-handle", &ph);
+	mdio_probe_done = xgene_mdio_probe_successful();
 
-		if (phy_mode == PHY_INTERFACE_MODE_RGMII) {
+	if (mdio_probe_done) {
+		if (dev->of_node) {
+			ret = device_property_read_string(dev, "phy-handle",
+							  &ph);
 			if (ret) {
-				dev_err(dev, "Unable to get phy-handle\n");
+				dev_err(dev, "Unable to find phy-handle\n");
 				return ret;
 			}
+		} else {
+#ifdef CONFIG_ACPI
+			ret = device_property_present(dev, "phy-handle");
+			if (!ret) {
+				dev_err(dev, "Unable to find phy-handle\n");
+				return -1;
+			}
+#endif
+		}
+
+		pdata->mdio_driver = true;
+	} else {
+		if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII)
+			return 0;
 
+		if (dev->of_node) {
 			mdio_np = of_find_compatible_node(dev->of_node, NULL,
 							  "apm,xgene-mdio");
-			if (!mdio_np)
-				pdata->mdio_driver = true;
-			else
-				pdata->mdio_np = mdio_np;
+			if (!mdio_np) {
+				dev_err(dev, "No mdio node in the dts\n");
+				return -ENXIO;
+			}
+
+			pdata->mdio_np = mdio_np;
+			return 0;
 		} else {
-			if (!ret)
-				pdata->mdio_driver = true;
-		}
-	} else {
 #ifdef CONFIG_ACPI
-		fw_node = acpi_fwnode_handle(ACPI_COMPANION(dev));
-		ret = acpi_node_get_property_reference(fw_node, "mboxes", 0,
-						       &args);
-		if (!ACPI_FAILURE(ret)) {
-			pdata->mdio_driver = true;
-			pdata->phy_dev =  args.adev->driver_data;
-		} else {
 			ret = device_property_read_u32(dev, "phy-channel",
 						       &phy_id);
-			if (ret) {
+			if (ret)
 				ret = device_property_read_u32(dev, "phy-addr",
-							       &phy_id);
+								    &phy_id);
+			if (ret) {
+				dev_err(dev, "Unable to get phy-channel or phy-addr\n");
+				return -EINVAL;
 			}
 
-			if (!ret)
-				pdata->phy_id = phy_id;
-		}
+			pdata->phy_id = phy_id;
 #endif
+		}
 	}
 
 	return 0;
@@ -1703,12 +1724,6 @@ static int xgene_enet_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-	ret = register_netdev(ndev);
-	if (ret) {
-		netdev_err(ndev, "Failed to register netdev\n");
-		goto err;
-	}
-
 	ret = xgene_enet_init_hw(pdata);
 	if (ret)
 		goto err_netdev;
@@ -1729,6 +1744,11 @@ static int xgene_enet_probe(struct platform_device *pdev)
 		goto err;
 
 	xgene_enet_napi_add(pdata);
+	ret = register_netdev(ndev);
+	if (ret) {
+		netdev_err(ndev, "Failed to register netdev\n");
+		goto err;
+	}
 	return 0;
 err_netdev:
 	if (ndev->reg_state == NETREG_REGISTERED)
@@ -1762,13 +1782,27 @@ static int xgene_enet_remove(struct platform_device *pdev)
 		xgene_enet_mdio_remove(pdata);
 
 	unregister_netdev(ndev);
-	xgene_enet_delete_desc_rings(pdata);
 	pdata->port_ops->shutdown(pdata);
+	xgene_enet_delete_desc_rings(pdata);
 	free_netdev(ndev);
 
 	return 0;
 }
 
+static void xgene_enet_shutdown(struct platform_device *pdev)
+{
+	struct xgene_enet_pdata *pdata;
+
+	pdata = platform_get_drvdata(pdev);
+	if (!pdata)
+		return;
+
+	if (!pdata->ndev)
+		return;
+
+	xgene_enet_remove(pdev);
+}
+
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id xgene_enet_acpi_match[] = {
 	{ "APMC0D05", XGENE_ENET1},
@@ -1803,6 +1837,7 @@ static struct platform_driver xgene_enet_driver = {
 	},
 	.probe = xgene_enet_probe,
 	.remove = xgene_enet_remove,
+	.shutdown = xgene_enet_shutdown,
 };
 
 module_platform_driver(xgene_enet_driver);
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
index c2804c2..9975105 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -38,6 +38,7 @@
 #include "xgene_enet_hw.h"
 #include "xgene_enet_cle.h"
 #include "xgene_enet_ring2.h"
+#include "../../../phy/mdio-xgene.h"
 
 #define XGENE_DRV_VERSION	"v1.0"
 #define XGENE_ENET_MAX_MTU	1536
@@ -103,6 +104,7 @@ struct xgene_enet_desc_ring {
 	void __iomem *cmd_base;
 	void __iomem *cmd;
 	dma_addr_t dma;
+	dma_addr_t dma_exp_bufs;
 	dma_addr_t irq_mbox_dma;
 	void *irq_mbox_addr;
 	u16 dst_ring_num;
@@ -148,6 +150,8 @@ struct xgene_mac_ops {
 
 struct xgene_port_ops {
 	int (*reset)(struct xgene_enet_pdata *pdata);
+	void (*clear)(struct xgene_enet_pdata *pdata,
+		      struct xgene_enet_desc_ring *ring);
 	void (*cle_bypass)(struct xgene_enet_pdata *pdata,
 			   u32 dst_ring_num, u16 bufpool_id);
 	void (*shutdown)(struct xgene_enet_pdata *pdata);
@@ -224,34 +228,6 @@ struct xgene_indirect_ctl {
 	void __iomem *cmd_done;
 };
 
-/* Set the specified value into a bit-field defined by its starting position
- * and length within a single u64.
- */
-static inline u64 xgene_enet_set_field_value(int pos, int len, u64 val)
-{
-	return (val & ((1ULL << len) - 1)) << pos;
-}
-
-#define SET_VAL(field, val) \
-		xgene_enet_set_field_value(field ## _POS, field ## _LEN, val)
-
-#define SET_BIT(field) \
-		xgene_enet_set_field_value(field ## _POS, 1, 1)
-
-/* Get the value from a bit-field defined by its starting position
- * and length within the specified u64.
- */
-static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src)
-{
-	return (src >> pos) & ((1ULL << len) - 1);
-}
-
-#define GET_VAL(field, src) \
-		xgene_enet_get_field_value(field ## _POS, field ## _LEN, src)
-
-#define GET_BIT(field, src) \
-		xgene_enet_get_field_value(field ## _POS, 1, src)
-
 static inline struct device *ndev_to_dev(struct net_device *ndev)
 {
 	return ndev->dev.parent;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
index ae93dc2..24725fa 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
@@ -143,9 +143,18 @@ static u32 xgene_enet_rd_mac(struct xgene_enet_pdata *p, u32 rd_addr)
 static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
 {
 	struct net_device *ndev = p->ndev;
-	u32 data;
+	u32 data, shutdown;
 	int i = 0;
 
+	shutdown = xgene_enet_rd_diag_csr(p, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR);
+	data = xgene_enet_rd_diag_csr(p, ENET_BLOCK_MEM_RDY_ADDR);
+
+	if (!shutdown && data == ~0U) {
+		netdev_dbg(ndev, "+ ecc_init called before, shutdown: %08x mem_ready: %08x\n",
+			   shutdown, data);
+		return 0;
+	}
+
 	xgene_enet_wr_diag_csr(p, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0);
 	do {
 		usleep_range(100, 110);
@@ -327,9 +336,10 @@ static void xgene_sgmac_init(struct xgene_enet_pdata *p)
 		xgene_sgmac_reset(p);
 
 	/* Enable auto-negotiation */
+	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x1000);
 	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2,
 			    0x8000);
-	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x9000);
+	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_CONTROL_ADDR >> 2, 0x9140);
 	xgene_mii_phy_write(p, INT_PHY_ADDR, SGMII_TBI_CONTROL_ADDR >> 2, 0);
 
 	while (loop--) {
@@ -415,24 +425,40 @@ static void xgene_sgmac_tx_disable(struct xgene_enet_pdata *p)
 
 static int xgene_enet_reset(struct xgene_enet_pdata *p)
 {
-	int ret;
+	struct device *dev = &p->pdev->dev;
 
 	if (!xgene_ring_mgr_init(p))
 		return -ENODEV;
 
+	if (p->mdio_driver && p->enet_id == XGENE_ENET2) {
+		xgene_enet_config_ring_if_assoc(p);
+		return 0;
+	}
+
 	if (p->enet_id == XGENE_ENET2)
 		xgene_enet_wr_clkrst_csr(p, XGENET_CONFIG_REG_ADDR, SGMII_EN);
 
-	if (!IS_ERR(p->clk)) {
-		clk_prepare_enable(p->clk);
-		clk_disable_unprepare(p->clk);
-		clk_prepare_enable(p->clk);
+	if (dev->of_node) {
+		if (!IS_ERR(p->clk)) {
+			clk_prepare_enable(p->clk);
+			clk_disable_unprepare(p->clk);
+			clk_prepare_enable(p->clk);
+		}
+	} else {
+#ifdef CONFIG_ACPI
+		if (acpi_has_method(ACPI_HANDLE(&p->pdev->dev), "_RST"))
+			acpi_evaluate_object(ACPI_HANDLE(&p->pdev->dev),
+					     "_RST", NULL, NULL);
+		else if (acpi_has_method(ACPI_HANDLE(&p->pdev->dev), "_INI"))
+			acpi_evaluate_object(ACPI_HANDLE(&p->pdev->dev),
+					     "_INI", NULL, NULL);
+#endif
 	}
 
-	ret = xgene_enet_ecc_init(p);
-	if (ret)
-		return ret;
-	xgene_enet_config_ring_if_assoc(p);
+	if (!p->port_id) {
+		xgene_enet_ecc_init(p);
+		xgene_enet_config_ring_if_assoc(p);
+	}
 
 	return 0;
 }
@@ -460,10 +486,47 @@ static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
 	xgene_enet_wr_csr(p, cle_bypass_reg1 + offset, data);
 }
 
+static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
+			     struct xgene_enet_desc_ring *ring)
+{
+	u32 addr, val, data;
+
+	val = xgene_enet_ring_bufnum(ring->id);
+
+	if (xgene_enet_is_bufpool(ring->id)) {
+		addr = ENET_CFGSSQMIFPRESET_ADDR;
+		data = BIT(val - 0x20);
+	} else {
+		addr = ENET_CFGSSQMIWQRESET_ADDR;
+		data = BIT(val);
+	}
+
+	xgene_enet_wr_ring_if(pdata, addr, data);
+}
+
 static void xgene_enet_shutdown(struct xgene_enet_pdata *p)
 {
-	if (!IS_ERR(p->clk))
-		clk_disable_unprepare(p->clk);
+	struct xgene_enet_desc_ring *ring;
+	u32 pb, val;
+	int i;
+
+	pb = 0;
+	for (i = 0; i < p->rxq_cnt; i++) {
+		ring = p->rx_ring[i]->buf_pool;
+
+		val = xgene_enet_ring_bufnum(ring->id);
+		pb |= BIT(val - 0x20);
+	}
+	xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPRESET_ADDR, pb);
+
+	pb = 0;
+	for (i = 0; i < p->txq_cnt; i++) {
+		ring = p->tx_ring[i];
+
+		val = xgene_enet_ring_bufnum(ring->id);
+		pb |= BIT(val);
+	}
+	xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQRESET_ADDR, pb);
 }
 
 static void xgene_enet_link_state(struct work_struct *work)
@@ -511,6 +574,7 @@ const struct xgene_mac_ops xgene_sgmac_ops = {
 
 const struct xgene_port_ops xgene_sgport_ops = {
 	.reset		= xgene_enet_reset,
+	.clear		= xgene_enet_clear,
 	.cle_bypass	= xgene_enet_cle_bypass,
 	.shutdown	= xgene_enet_shutdown
 };
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
index ba030dc..925dc45 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
@@ -258,15 +258,29 @@ static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata)
 
 static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
 {
+	struct device *dev = &pdata->pdev->dev;
+
 	if (!xgene_ring_mgr_init(pdata))
 		return -ENODEV;
 
-	if (!IS_ERR(pdata->clk)) {
-		clk_prepare_enable(pdata->clk);
-		clk_disable_unprepare(pdata->clk);
-		clk_prepare_enable(pdata->clk);
+	if (dev->of_node) {
+		if (!IS_ERR(pdata->clk)) {
+			clk_prepare_enable(pdata->clk);
+			clk_disable_unprepare(pdata->clk);
+			clk_prepare_enable(pdata->clk);
+		}
+	} else {
+#ifdef CONFIG_ACPI
+		if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev), "_RST")) {
+			acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev),
+					     "_RST", NULL, NULL);
+		} else if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev),
+					   "_INI")) {
+			acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev),
+					     "_INI", NULL, NULL);
+		}
+#endif
 	}
-
 	xgene_enet_ecc_init(pdata);
 	xgene_enet_config_ring_if_assoc(pdata);
 
@@ -292,8 +306,45 @@ static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
 
 static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
 {
-	if (!IS_ERR(pdata->clk))
-		clk_disable_unprepare(pdata->clk);
+	struct xgene_enet_desc_ring *ring;
+	u32 pb, val;
+	int i;
+
+	pb = 0;
+	for (i = 0; i < pdata->rxq_cnt; i++) {
+		ring = pdata->rx_ring[i]->buf_pool;
+
+		val = xgene_enet_ring_bufnum(ring->id);
+		pb |= BIT(val - 0x20);
+	}
+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
+
+	pb = 0;
+	for (i = 0; i < pdata->txq_cnt; i++) {
+		ring = pdata->tx_ring[i];
+
+		val = xgene_enet_ring_bufnum(ring->id);
+		pb |= BIT(val);
+	}
+	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
+}
+
+static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
+			     struct xgene_enet_desc_ring *ring)
+{
+	u32 addr, val, data;
+
+	val = xgene_enet_ring_bufnum(ring->id);
+
+	if (xgene_enet_is_bufpool(ring->id)) {
+		addr = ENET_CFGSSQMIFPRESET_ADDR;
+		data = BIT(val - 0x20);
+	} else {
+		addr = ENET_CFGSSQMIWQRESET_ADDR;
+		data = BIT(val);
+	}
+
+	xgene_enet_wr_ring_if(pdata, addr, data);
 }
 
 static void xgene_enet_link_state(struct work_struct *work)
@@ -340,6 +391,7 @@ const struct xgene_mac_ops xgene_xgmac_ops = {
 
 const struct xgene_port_ops xgene_xgport_ops = {
 	.reset = xgene_enet_reset,
+	.clear = xgene_enet_clear,
 	.cle_bypass = xgene_enet_xgcle_bypass,
 	.shutdown = xgene_enet_shutdown,
 };
-- 
1.9.1



From horms at verge.net.au  Tue May 31 17:25:53 2016
From: horms at verge.net.au (Simon Horman)
Date: Wed, 1 Jun 2016 09:25:53 +0900
Subject: [PATCH 04/13] ARM: shmobile: r8a7792: basic SoC support
In-Reply-To: <2352834.cNFKgiQiVO@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
 <2352834.cNFKgiQiVO@wasted.cogentembedded.com>
Message-ID: <20160601002553.GC20527@verge.net.au>

On Wed, Jun 01, 2016 at 01:18:22AM +0300, Sergei Shtylyov wrote:
> Add minimal support for the R-Car V2H (R8A7792) SoC.
> 
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

Acked-by: Simon Horman <horms+renesas at verge.net.au>



From zyw at rock-chips.com  Tue May 31 17:35:09 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Wed, 1 Jun 2016 08:35:09 +0800
Subject: [PATCH 1/6] phy: Add USB Type-C PHY driver for rk3399
In-Reply-To: <CAD=FV=V1qX_YTTygsz=v+p6BdG8VZcu8np2nDvm1NiJHDnf==g@mail.gmail.com>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
 <1464328939-8073-2-git-send-email-zyw@rock-chips.com>
 <CAD=FV=V1qX_YTTygsz=v+p6BdG8VZcu8np2nDvm1NiJHDnf==g@mail.gmail.com>
Message-ID: <574E2DBD.8000900@rock-chips.com>

Hi Doug

Thanks for your review, I will modified them in next version(v1)
and with Guenter Roeck's comments in:
https://chromium-review.googlesource.com/#/c/348154/



On 06/01/2016 05:35 AM, Doug Anderson wrote:
> Chris,
>
> On Thu, May 26, 2016 at 11:02 PM, Chris Zhong <zyw at rock-chips.com> wrote:
>> Add a PHY provider driver for the rk3399 SoC Type-c PHY. The USB
>> Type-C PHY is designed to support the USB3 and DP applications. The
>> PHY basically has two main components: USB3 and DisplyPort. USB3
>> operates in SuperSpeed mode and the DP can operate at RBR, HBR and
>> HBR2 data rates.
>>
>> Signed-off-by: Chris Zhong <zyw at rock-chips.com>
>> ---
>>
>>   drivers/phy/Kconfig              |   7 +
>>   drivers/phy/Makefile             |   1 +
>>   drivers/phy/phy-rockchip-typec.c | 823 +++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 831 insertions(+)
> This is a bit of a superficial review.  Hopefully we can find someone
> to do something more thorough.I
>
>
>>   create mode 100644 drivers/phy/phy-rockchip-typec.c
>>
>> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
>> index 26566db..dc388a3d 100644
>> --- a/drivers/phy/Kconfig
>> +++ b/drivers/phy/Kconfig
>> @@ -351,6 +351,13 @@ config PHY_ROCKCHIP_DP
>>          help
>>            Enable this to support the Rockchip Display Port PHY.
>>
>> +config PHY_ROCKCHIP_TYPEC
>> +       tristate "Rockchip TYPEC PHY Driver"
>> +       depends on ARCH_ROCKCHIP && OF
>> +       select GENERIC_PHY
>> +       help
>> +         Enable this to support the Rockchip USB TYPEC PHY.
>> +
>>   config PHY_ST_SPEAR1310_MIPHY
>>          tristate "ST SPEAR1310-MIPHY driver"
>>          select GENERIC_PHY
>> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
>> index 24596a9..91fa413 100644
>> --- a/drivers/phy/Makefile
>> +++ b/drivers/phy/Makefile
>> @@ -39,6 +39,7 @@ obj-$(CONFIG_PHY_QCOM_APQ8064_SATA)   += phy-qcom-apq8064-sata.o
>>   obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
>>   obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o
>>   obj-$(CONFIG_PHY_ROCKCHIP_DP)          += phy-rockchip-dp.o
>> +obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
>>   obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)    += phy-qcom-ipq806x-sata.o
>>   obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY)   += phy-spear1310-miphy.o
>>   obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY)   += phy-spear1340-miphy.o
>> diff --git a/drivers/phy/phy-rockchip-typec.c b/drivers/phy/phy-rockchip-typec.c
>> new file mode 100644
>> index 0000000..6609cfb
>> --- /dev/null
>> +++ b/drivers/phy/phy-rockchip-typec.c
>> @@ -0,0 +1,823 @@
>> +/*
>> + * Rockchip usb3 PHY driver
>> + *
>> + * Copyright (C) 2016 Kever Yang <kever.yang at rock-chips.com>
>> + *                    Chris Zhong <zyw at rock-chips.com>
>> + * Copyright (C) 2016 ROCKCHIP, Inc.
>> + *
>> + * 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.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/iopoll.h>p
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/mutex.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/phy/phy.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/reset.h>
>> +#include <linux/regmap.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/delay.h>
>> +#include <linux/phy/phy-rockchip-typec.h>
>> +
>> +#define ADDR_ADJ                       2
>> +#define CMN_SSM_BANDGAP                        (0x21 << ADDR_ADJ)
>> +#define CMN_SSM_BIAS                   (0x22 << ADDR_ADJ)
>> +#define CMN_PLLSM0_PLLEN               (0x29 << ADDR_ADJ)
>> +#define CMN_PLLSM0_PLLPRE              (0x2a << ADDR_ADJ)
>> +#define CMN_PLLSM0_PLLVREF             (0x2b << ADDR_ADJ)
>> +#define CMN_PLLSM0_PLLLOCK             (0x2c << ADDR_ADJ)
>> +#define CMN_PLLSM1_PLLEN               (0x31 << ADDR_ADJ)
>> +#define CMN_PLLSM1_PLLPRE              (0x32 << ADDR_ADJ)
>> +#define CMN_PLLSM1_PLLVREF             (0x33 << ADDR_ADJ)
>> +#define CMN_PLLSM1_PLLLOCK             (0x34 << ADDR_ADJ)
>> +#define CMN_PLLSM1_USER_DEF_CTRL       (0x37 << ADDR_ADJ)
>> +#define CMN_ICAL_OVRD                  (0xc1 << ADDR_ADJ)
>> +#define CMN_PLL0_VCOCAL_OVRD           (0x83 << ADDR_ADJ)
>> +#define CMN_PLL0_VCOCAL_INIT           (0x84 << ADDR_ADJ)
>> +#define CMN_PLL0_VCOCAL_ITER           (0x85 << ADDR_ADJ)
>> +#define CMN_PLL0_LOCK_REFCNT_START     (0x90 << ADDR_ADJ)
>> +#define CMN_PLL0_LOCK_PLLCNT_START     (0x92 << ADDR_ADJ)
>> +#define CMN_PLL0_LOCK_PLLCNT_THR       (0x93 << ADDR_ADJ)
>> +#define CMN_PLL0_INTDIV                        (0x94 << ADDR_ADJ)
>> +#define CMN_PLL0_FRACDIV               (0x95 << ADDR_ADJ)
>> +#define CMN_PLL0_HIGH_THR              (0x96 << ADDR_ADJ)
>> +#define CMN_PLL0_DSM_DIAG              (0x97 << ADDR_ADJ)
>> +#define CMN_PLL0_SS_CTRL1              (0x98 << ADDR_ADJ)
>> +#define CMN_PLL0_SS_CTRL2              (0x99 << ADDR_ADJ)
>> +#define CMN_PLL1_VCOCAL_START          (0xa1 << ADDR_ADJ)
>> +#define CMN_PLL1_VCOCAL_OVRD           (0xa3 << ADDR_ADJ)
>> +#define CMN_PLL1_VCOCAL_INIT           (0xa4 << ADDR_ADJ)
>> +#define CMN_PLL1_VCOCAL_ITER           (0xa5 << ADDR_ADJ)
>> +#define CMN_PLL1_LOCK_REFCNT_START     (0xb0 << ADDR_ADJ)
>> +#define CMN_PLL1_LOCK_PLLCNT_START     (0xb2 << ADDR_ADJ)
>> +#define CMN_PLL1_LOCK_PLLCNT_THR       (0xb3 << ADDR_ADJ)
>> +#define CMN_PLL1_INTDIV                        (0xb4 << ADDR_ADJ)
>> +#define CMN_PLL1_FRACDIV               (0xb5 << ADDR_ADJ)
>> +#define CMN_PLL1_HIGH_THR              (0xb6 << ADDR_ADJ)
>> +#define CMN_PLL1_DSM_DIAG              (0xb7 << ADDR_ADJ)
>> +#define CMN_PLL1_SS_CTRL1              (0xb8 << ADDR_ADJ)
>> +#define CMN_PLL1_SS_CTRL2              (0xb9 << ADDR_ADJ)
>> +#define CMN_RXCAL_OVRD                 (0xd1 << ADDR_ADJ)
>> +#define CMN_TXPUCAL_CTRL               (0xe0 << ADDR_ADJ)
>> +#define CMN_TXPUCAL_OVRD               (0xe1 << ADDR_ADJ)
>> +#define CMN_TXPDCAL_OVRD               (0xf1 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL0_FBH_OVRD         (0x1c0 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL0_FBL_OVRD         (0x1c1 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL0_OVRD             (0x1c2 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL0_V2I_TUNE         (0x1c5 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL0_CP_TUNE          (0x1c6 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL0_LF_PROG          (0x1c7 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL1_FBH_OVRD         (0x1d0 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL1_FBL_OVRD         (0x1d1 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL1_OVRD             (0x1d2 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL1_V2I_TUNE         (0x1d5 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL1_CP_TUNE          (0x1d6 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL1_LF_PROG          (0x1d7 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL1_PTATIS_TUNE1     (0x1d8 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL1_PTATIS_TUNE2     (0x1d9 << ADDR_ADJ)
>> +#define CMN_DIAG_PLL1_INCLK_CTRL       (0x1da << ADDR_ADJ)
>> +#define CMN_DIAG_HSCLK_SEL             (0x1e0 << ADDR_ADJ)
>> +
>> +#define XCVR_PSM_RCTRL(n)              ((0x4001 | (n << 9)) << ADDR_ADJ)
>> +#define XCVR_PSM_CAL_TMR(n)            ((0x4002 | (n << 9)) << ADDR_ADJ)
>> +#define XCVR_PSM_A0IN_TMR(n)           ((0x4003 | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_CAL_SCLR_MULT(n)       ((0x4047 | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_CPOST_MULT_00(n)       ((0x404c | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_CPOST_MULT_01(n)       ((0x404d | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_CPOST_MULT_10(n)       ((0x404e | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_CPOST_MULT_11(n)       ((0x404f | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_MGNFS_MULT_000(n)      ((0x4050 | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_MGNFS_MULT_001(n)      ((0x4051 | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_MGNFS_MULT_010(n)      ((0x4052 | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_MGNFS_MULT_011(n)      ((0x4053 | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_MGNFS_MULT_100(n)      ((0x4054 | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_MGNFS_MULT_101(n)      ((0x4055 | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_MGNFS_MULT_110(n)      ((0x4056 | (n << 9)) << ADDR_ADJ)
>> +#define TX_TXCC_MGNFS_MULT_111(n)      ((0x4057 | (n << 9)) << ADDR_ADJ)
>> +#define XCVR_DIAG_PLLDRC_CTRL(n)       ((0x40e0 | (n << 9)) << ADDR_ADJ)
>> +#define XCVR_DIAG_BIDI_CTRL(n)         ((0x40e8 | (n << 9)) << ADDR_ADJ)
>> +#define XCVR_DIAG_LANE_FCM_EN_MGN(n)   ((0x40f2 | (n << 9)) << ADDR_ADJ)
>> +#define TX_PSC_A0(n)                   ((0x4100 | (n << 9)) << ADDR_ADJ)
>> +#define TX_PSC_A1(n)                   ((0x4101 | (n << 9)) << ADDR_ADJ)
>> +#define TX_PSC_A2(n)                   ((0x4102 | (n << 9)) << ADDR_ADJ)
>> +#define TX_PSC_A3(n)                   ((0x4103 | (n << 9)) << ADDR_ADJ)
>> +#define TX_RCVDET_CTRL(n)              ((0x4120 | (n << 9)) << ADDR_ADJ)
>> +#define TX_RCVDET_EN_TMR(n)            ((0x4122 | (n << 9)) << ADDR_ADJ)
>> +#define TX_RCVDET_ST_TMR(n)            ((0x4123 | (n << 9)) << ADDR_ADJ)
>> +#define TX_DIAG_TX_DRV(n)              ((0x41e1 | (n << 9)) << ADDR_ADJ)
>> +#define TX_DIAG_BGREF_PREDRV_DELAY     (0x41e7 << ADDR_ADJ)
>> +#define TX_ANA_CTRL_REG_1              (0x5020 << ADDR_ADJ)
>> +#define TX_ANA_CTRL_REG_2              (0x5021 << ADDR_ADJ)
>> +#define TXDA_COEFF_CALC_CTRL           (0x5022 << ADDR_ADJ)
>> +#define TX_DIG_CTRL_REG_2              (0x5024 << ADDR_ADJ)
>> +#define TXDA_CYA_AUXDA_CYA             (0x5025 << ADDR_ADJ)
>> +#define TX_ANA_CTRL_REG_3              (0x5026 << ADDR_ADJ)
>> +#define TX_ANA_CTRL_REG_4              (0x5027 << ADDR_ADJ)
>> +#define TX_ANA_CTRL_REG_5              (0x5029 << ADDR_ADJ)
>> +
>> +#define RX_PSC_A0(n)                   ((0x8000 | (n << 9)) << ADDR_ADJ)
>> +#define RX_PSC_A1(n)                   ((0x8001 | (n << 9)) << ADDR_ADJ)
>> +#define RX_PSC_A2(n)                   ((0x8002 | (n << 9)) << ADDR_ADJ)
>> +#define RX_PSC_A3(n)                   ((0x8003 | (n << 9)) << ADDR_ADJ)
>> +#define RX_PSC_CAL(n)                  ((0x8006 | (n << 9)) << ADDR_ADJ)
>> +#define RX_PSC_RDY(n)                  ((0x8007 | (n << 9)) << ADDR_ADJ)
>> +#define RX_IQPI_ILL_CAL_OVRD           (0x8023 << ADDR_ADJ)
>> +#define RX_EPI_ILL_CAL_OVRD            (0x8033 << ADDR_ADJ)
>> +#define RX_SDCAL0_OVRD                 (0x8041 << ADDR_ADJ)
>> +#define RX_SDCAL1_OVRD                 (0x8049 << ADDR_ADJ)
>> +#define RX_SLC_INIT                    (0x806d << ADDR_ADJ)
>> +#define RX_SLC_RUN                     (0x806e << ADDR_ADJ)
>> +#define RX_CDRLF_CNFG2                 (0x8081 << ADDR_ADJ)
>> +#define RX_SIGDET_HL_FILT_TMR(n)       ((0x8090 | (n << 9)) << ADDR_ADJ)
>> +#define RX_SLC_IOP0_OVRD               (0x8101 << ADDR_ADJ)
>> +#define RX_SLC_IOP1_OVRD               (0x8105 << ADDR_ADJ)
>> +#define RX_SLC_QOP0_OVRD               (0x8109 << ADDR_ADJ)
>> +#define RX_SLC_QOP1_OVRD               (0x810d << ADDR_ADJ)
>> +#define RX_SLC_EOP0_OVRD               (0x8111 << ADDR_ADJ)
>> +#define RX_SLC_EOP1_OVRD               (0x8115 << ADDR_ADJ)
>> +#define RX_SLC_ION0_OVRD               (0x8119 << ADDR_ADJ)
>> +#define RX_SLC_ION1_OVRD               (0x811d << ADDR_ADJ)
>> +#define RX_SLC_QON0_OVRD               (0x8121 << ADDR_ADJ)
>> +#define RX_SLC_QON1_OVRD               (0x8125 << ADDR_ADJ)
>> +#define RX_SLC_EON0_OVRD               (0x8129 << ADDR_ADJ)
>> +#define RX_SLC_EON1_OVRD               (0x812d << ADDR_ADJ)
>> +#define RX_SLC_IEP0_OVRD               (0x8131 << ADDR_ADJ)
>> +#define RX_SLC_IEP1_OVRD               (0x8135 << ADDR_ADJ)
>> +#define RX_SLC_QEP0_OVRD               (0x8139 << ADDR_ADJ)
>> +#define RX_SLC_QEP1_OVRD               (0x813d << ADDR_ADJ)
>> +#define RX_SLC_EEP0_OVRD               (0x8141 << ADDR_ADJ)
>> +#define RX_SLC_EEP1_OVRD               (0x8145 << ADDR_ADJ)
>> +#define RX_SLC_IEN0_OVRD               (0x8149 << ADDR_ADJ)
>> +#define RX_SLC_IEN1_OVRD               (0x814d << ADDR_ADJ)
>> +#define RX_SLC_QEN0_OVRD               (0x8151 << ADDR_ADJ)
>> +#define RX_SLC_QEN1_OVRD               (0x8155 << ADDR_ADJ)
>> +#define RX_SLC_EEN0_OVRD               (0x8159 << ADDR_ADJ)
>> +#define RX_SLC_EEN1_OVRD               (0x815d << ADDR_ADJ)
>> +#define RX_DIAG_SIGDET_TUNE(n)         ((0x81dc | (n << 9)) << ADDR_ADJ)
>> +#define RX_DIAG_SC2C_DELAY             (0x81e1 << ADDR_ADJ)
>> +
>> +#define PMA_LANE_CFG                   (0xc000 << ADDR_ADJ)
>> +#define PIPE_CMN_CTRL1                 (0xc001 << ADDR_ADJ)
>> +#define PIPE_CMN_CTRL2                 (0xc002 << ADDR_ADJ)
>> +#define PIPE_COM_LOCK_CFG1             (0xc003 << ADDR_ADJ)
>> +#define PIPE_COM_LOCK_CFG2             (0xc004 << ADDR_ADJ)
>> +#define PIPE_RCV_DET_INH               (0xc005 << ADDR_ADJ)
>> +#define DP_MODE_CTL                    (0xc008 << ADDR_ADJ)
>> +#define DP_CLK_CTL                     (0xc009 << ADDR_ADJ)
>> +#define STS                            (0xc00F << ADDR_ADJ)
>> +#define PHY_ISO_CMN_CTRL               (0xc010 << ADDR_ADJ)
>> +#define PHY_DP_TX_CTL                  (0xc408 << ADDR_ADJ)
>> +#define PMA_CMN_CTRL1                  (0xc800 << ADDR_ADJ)
>> +#define PHY_PMA_ISO_CMN_CTRL           (0xc810 << ADDR_ADJ)
>> +#define PHY_ISOLATION_CTRL             (0xc81f << ADDR_ADJ)
>> +#define PHY_PMA_ISO_XCVR_CTRL(n)       ((0xcc11 | (n << 6)) << ADDR_ADJ)
>> +#define PHY_PMA_ISO_LINK_MODE(n)       ((0xcc12 | (n << 6)) << ADDR_ADJ)
>> +#define PHY_PMA_ISO_PWRST_CTRL(n)      ((0xcc13 | (n << 6)) << ADDR_ADJ)
>> +#define PHY_PMA_ISO_TX_DATA_LO(n)      ((0xcc14 | (n << 6)) << ADDR_ADJ)
>> +#define PHY_PMA_ISO_TX_DATA_HI(n)      ((0xcc15 | (n << 6)) << ADDR_ADJ)
>> +#define PHY_PMA_ISO_RX_DATA_LO(n)      ((0xcc16 | (n << 6)) << ADDR_ADJ)
>> +#define PHY_PMA_ISO_RX_DATA_HI(n)      ((0xcc17 | (n << 6)) << ADDR_ADJ)
>> +#define TX_BIST_CTRL(n)                        ((0x4140 | (n << 9)) << ADDR_ADJ)
>> +#define TX_BIST_UDDWR(n)               ((0x4141 | (n << 9)) << ADDR_ADJ)
>> +
>> +#define GRF_SOC_CON26                  0x6268
>> +#define UPHY_DP_SEL                    BIT(3)
>> +#define UPHY_DP_SEL_MASK               BIT(19)
>> +#define DPTX_HDP_SEL                   (3 << 12)
>> +#define DPTX_HDP_SEL_MASK              (3 << 28)
>> +
>> +#define PHY_MODE_SET_TIMEOUT           1000000
>> +
>> +#define        MODE_DISCONNECT                 1
>> +#define        MODE_UFP                        2
>> +#define        MODE_DFP_USBONLY                3
>> +#define        MODE_DFP_DPONLY                 4
>> +#define        MODE_DFP_USB3DP                 5
>> +#define        MODE_DFP_USB2DP                 6
>> +
>> +#define PARSE_GRF_REG(TYPE) { \
>> +       if (of_find_property(np, "rockchip,usb3phy_"#TYPE, &len)) { \
>> +               len /= sizeof(u32);\
>> +               ret = of_property_read_u32_array(np, "rockchip,usb3phy_" #TYPE,\
>> +                                                array, len); \
>> +               exregs->usb3phy_##TYPE = array[0]; \
>> +               exregs->usb3phy_##TYPE##_shift = array[1]; \
>> +               exregs->usb3phy_##TYPE##_mask = array[2]; \
>> +               pr_info("%s property found %s, %x, %d, %d\n", __func__, \
>> +                       "rockchip,usb3phy_"#TYPE, \
>> +                       array[0], array[1], array[2]); \
>> +       } else { \
>> +               pr_info("%s property not found %s\n", __func__, \
>> +                       "rockchip,usb3phy_" #TYPE); \
>> +       } \
>> +}
>> +
>> +struct rockchip_typec_phy *rockchip_tcphy;
> Unused global?
>
>> +
>> +static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy,
>> +                         unsigned int num_lanes)
>> +{
>> +       unsigned int i;()?
>> +
>> +       writel(0x830, tcphy->base + PMA_CMN_CTRL1);
>> +       for (i = 0; i < num_lanes; i++) {
>> +               writel(0x90, tcphy->base + XCVR_DIAG_LANE_FCM_EN_MGN(i));
>> +               writel(0x960, tcphy->base + TX_RCVDET_EN_TMR(i));
>> +               writel(0x30, tcphy->base + TX_RCVDET_ST_TMR(i));
> Would it be too much to ask to get more details about all these magic values?
>
>> +       }
>> +}
>> +
>> +static void tcphy_cfg_usb_pll(struct rockchip_typec_phy *tcphy)
>> +{
>> +       unsigned int rdata;
>> +
>> +       rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
>> +       writel(rdata & 0xfffc, tcphy->base + CMN_DIAG_HSCLK_SEL);
>> +       writel(0xf0, tcphy->base + CMN_PLL0_VCOCAL_INIT);
>> +       writel(0x18, tcphy->base + CMN_PLL0_VCOCAL_ITER);
>> +       writel(0xd0, tcphy->base + CMN_PLL0_INTDIV);
>> +       writel(0x4a4a, tcphy->base + CMN_PLL0_FRACDIV);
>> +       writel(0x34, tcphy->base + CMN_PLL0_HIGH_THR);
>> +       writel(0x1ee, tcphy->base + CMN_PLL0_SS_CTRL1);
>> +       writel(0x7f03, tcphy->base + CMN_PLL0_SS_CTRL2);
>> +       writel(0x20, tcphy->base + CMN_PLL0_DSM_DIAG);
>> +       writel(0, tcphy->base + CMN_DIAG_PLL0_OVRD);
>> +       writel(0, tcphy->base + CMN_DIAG_PLL0_FBH_OVRD);
>> +       writel(0, tcphy->base + CMN_DIAG_PLL0_FBL_OVRD);
>> +       writel(0x7, tcphy->base + CMN_DIAG_PLL0_V2I_TUNE);
>> +       writel(0x45, tcphy->base + CMN_DIAG_PLL0_CP_TUNE);
>> +       writel(0x8, tcphy->base + CMN_DIAG_PLL0_LF_PROG);
>> +}
>> +
>> +static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy)
>> +{
>> +       unsigned int rdata;
>> +
>> +       writel(0x2405, tcphy->base + DP_CLK_CTL);
>> +
>> +       rdata = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
>> +       rdata = (rdata & 0xffcf) | 0x30;
>> +       writel(rdata, tcphy->base + CMN_DIAG_HSCLK_SEL);
>> +       writel(0xf0, tcphy->base + CMN_PLL1_VCOCAL_INIT);
>> +       writel(0x18, tcphy->base + CMN_PLL1_VCOCAL_ITER);
>> +       writel(0x30b9, tcphy->base + CMN_PLL1_VCOCAL_START);
>> +       writel(0x21c, tcphy->base + CMN_PLL1_INTDIV);
>> +       writel(0, tcphy->base + CMN_PLL1_FRACDIV);
>> +       writel(0x5, tcphy->base + CMN_PLL1_HIGH_THR);
>> +       writel(0x35, tcphy->base + CMN_PLL1_SS_CTRL1);
>> +       writel(0x7f1e, tcphy->base + CMN_PLL1_SS_CTRL2);
>> +       writel(0x20, tcphy->base + CMN_PLL1_DSM_DIAG);
>> +       writel(0, tcphy->base + CMN_PLLSM1_USER_DEF_CTRL);
>> +       writel(0, tcphy->base + CMN_DIAG_PLL1_OVRD);
>> +       writel(0, tcphy->base + CMN_DIAG_PLL1_FBH_OVRD);
>> +       writel(0, tcphy->base + CMN_DIAG_PLL1_FBL_OVRD);
>> +       writel(0x6, tcphy->base + CMN_DIAG_PLL1_V2I_TUNE);
>> +       writel(0x45, tcphy->base + CMN_DIAG_PLL1_CP_TUNE);
>> +       writel(0x8, tcphy->base + CMN_DIAG_PLL1_LF_PROG);
>> +       writel(0x100, tcphy->base + CMN_DIAG_PLL1_PTATIS_TUNE1);
>> +       writel(0x7, tcphy->base + CMN_DIAG_PLL1_PTATIS_TUNE2);
>> +       writel(0x4, tcphy->base + CMN_DIAG_PLL1_INCLK_CTRL);
>> +}
>> +
>> +static void tcphy_tx_usb_cfg_lane(struct rockchip_typec_phy *tcphy,
>> +                                 unsigned int lane)
>> +{
>> +       writel(0x7799, tcphy->base + TX_PSC_A0(lane));
>> +       writel(0x7798, tcphy->base + TX_PSC_A1(lane));
>> +       writel(0x5098, tcphy->base + TX_PSC_A2(lane));
>> +       writel(0x5098, tcphy->base + TX_PSC_A3(lane));
>> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
>> +       writel(0xbf, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
>> +}
>> +
>> +static void tcphy_rx_usb_cfg_lane(struct rockchip_typec_phy *tcphy,
>> +                                 unsigned int lane)
>> +{
>> +       writel(0xa6fd, tcphy->base + RX_PSC_A0(lane));
>> +       writel(0xa6fd, tcphy->base + RX_PSC_A1(lane));
>> +       writel(0xa410, tcphy->base + RX_PSC_A2(lane));
>> +       writel(0x2410, tcphy->base + RX_PSC_A3(lane));
>> +       writel(0x23ff, tcphy->base + RX_PSC_CAL(lane));
>> +       writel(0x13, tcphy->base + RX_SIGDET_HL_FILT_TMR(lane));
>> +       writel(0x1004, tcphy->base + RX_DIAG_SIGDET_TUNE(lane));
>> +       writel(0x2010, tcphy->base + RX_PSC_RDY(lane));
>> +       writel(0xfb, tcphy->base + XCVR_DIAG_BIDI_CTRL(lane));
>> +}
>> +
>> +static void tcphy_dp_cfg_lane(struct rockchip_typec_phy *tcphy,
>> +                             unsigned int lane)
>> +{
>> +       unsigned int rdata;
>> +
>> +       writel(0xbefc, tcphy->base + XCVR_PSM_RCTRL(lane));
>> +       writel(0x6799, tcphy->base + TX_PSC_A0(lane));
>> +       writel(0x6798, tcphy->base + TX_PSC_A1(lane));
>> +       writel(0x98, tcphy->base + TX_PSC_A2(lane));
>> +       writel(0x98, tcphy->base + TX_PSC_A3(lane));
>> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_000(lane));
>> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_001(lane));
>> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_010(lane));
>> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_011(lane));
>> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_100(lane));
>> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_101(lane));
>> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_110(lane));
>> +       writel(0, tcphy->base + TX_TXCC_MGNFS_MULT_111(lane));
>> +
>> +       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_10(lane));
>> +       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_01(lane));
>> +       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_00(lane));
>> +       writel(0, tcphy->base + TX_TXCC_CPOST_MULT_11(lane));
>> +
>> +       writel(0x128, tcphy->base + TX_TXCC_CAL_SCLR_MULT(lane));
>> +       writel(0x700, tcphy->base + TX_DIAG_TX_DRV(lane));
>> +
>> +       rdata = readl(tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
>> +       rdata = (rdata & 0x8fff) | 0x6000;
>> +       writel(rdata, tcphy->base + XCVR_DIAG_PLLDRC_CTRL(lane));
>> +}
>> +
>> +static void tcphy_cfg_pin_assign(struct rockchip_typec_phy *tcphy)
>> +{
>> +       switch (tcphy->map) {
>> +       case PIN_MAP_A:
>> +               writel(0x19d5, tcphy->base + PMA_LANE_CFG);
>> +               break;
>> +       case PIN_MAP_B:
>> +               writel(0x1500, tcphy->base + PMA_LANE_CFG);
>> +               break;
>> +       case PIN_MAP_C:
>> +       case PIN_MAP_E:
>> +               writel(0x51d9, tcphy->base + PMA_LANE_CFG);
>> +               break;
>> +       case PIN_MAP_D:
>> +       case PIN_MAP_F:
>> +               writel(0x5100, tcphy->base + PMA_LANE_CFG);
>> +               break;
>> +       };
>> +}
>> +
>> +static void tcphy_cfg_lanes(struct rockchip_typec_phy *tcphy,
>> +                           unsigned int link_cfg)
>> +{
>> +       unsigned int i;
>> +
>> +       /* PMA lane configuration DP or USB3 */
>> +       for (i = 0; i < 4; i++) {
>> +               if ((link_cfg >> i) & 0x1) {
>> +                       tcphy_dp_cfg_lane(tcphy, i);
>> +               } else {
>> +                       /*
>> +                        * lan0 TX and lan1 RX for USB3 Normal direction
>> +                        * lan3 TX and lan2 RX for USB3 Flip direction
>> +                        */
>> +                       if ((i == 0) | (i == 3))
>> +                               tcphy_tx_usb_cfg_lane(tcphy, i);
>> +                       else
>> +                               tcphy_rx_usb_cfg_lane(tcphy, i);
>> +               }
>> +       }
>> +}
>> +
>> +static void tcphy_cfg_flip_set(struct rockchip_typec_phy *tcphy)
>> +{
>> +       regmap_write(tcphy->grf_regs,
>> +                    tcphy->exregs.usb3phy_con0,
>> +                    tcphy->flip | BIT(16));
>> +
>> +       tcphy_cfg_24m(tcphy, 0x4);
>> +
>> +       if (tcphy->mode == MODE_UFP ||
>> +           tcphy->mode == MODE_DFP_USBONLY ||
>> +           tcphy->mode == MODE_DFP_USB3DP)
>> +               tcphy_cfg_usb_pll(tcphy);
>> +
>> +       if (tcphy->mode == MODE_DFP_DPONLY ||
>> +           tcphy->mode == MODE_DFP_USB2DP ||
>> +           tcphy->mode == MODE_DFP_USB3DP)
>> +               tcphy_cfg_dp_pll(tcphy);
>> +
>> +       if (tcphy->mode == MODE_DFP_DPONLY || tcphy->mode == MODE_DFP_USB2DP)
>> +               tcphy_cfg_lanes(tcphy, 0xf);
>> +       else if (tcphy->flip)
>> +               tcphy_cfg_lanes(tcphy, 0x3);
>> +       else
>> +               tcphy_cfg_lanes(tcphy, 0xc);
>> +}
>> +
>> +static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
>> +{
>> +       int rdata, rdata2, val;
>> +
>> +       rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
>> +       rdata2 = readl(tcphy->base + CMN_TXPUCAL_CTRL);
>> +
>> +       rdata = rdata & 0xdfff;
>> +       writel(rdata, tcphy->base + TX_ANA_CTRL_REG_1);
>> +
>> +       rdata = readl(tcphy->base + TX_DIG_CTRL_REG_2);
>> +       rdata = rdata & 0xffc0;
>> +       rdata2 = rdata2 & 0x3f;
>> +       rdata  = rdata | rdata2;
>> +       writel(rdata, tcphy->base + TX_DIG_CTRL_REG_2);
>> +       usleep_range(1000, 2000);
> nit: this is at init time and will be run once.  Power savings of
> trying to group wakeups will be minimal or none.  Last I looked
> usleep_range() nearly always takes the longer of the two times unless
> it happens to wake up anyway.  Make the range smaller and boot time
> will be 1ms faster.  Try usleep_range(1000, 1050).
>
>> +
>> +       rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
>> +       rdata = rdata | 0x2000;
>> +       writel(rdata, tcphy->base + TX_ANA_CTRL_REG_1);
>> +
>> +       usleep_range(150, 200);
>> +
>> +       writel(0, tcphy->base + PHY_DP_TX_CTL);
>> +       writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2);
>> +       writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2);
>> +       writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
>> +       writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1);
>> +       writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1);
>> +       writel(0x30C, tcphy->base + TX_ANA_CTRL_REG_2);
>> +       writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
>> +       writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4);
>> +       writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1);
>> +       writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1);
>> +       writel(0x30d, tcphy->base + TX_ANA_CTRL_REG_2);
>> +       writel(0x30f, tcphy->base + TX_ANA_CTRL_REG_2);
>> +
>> +       if (tcphy->flip)
>> +               writel(0xa078, tcphy->base + TX_ANA_CTRL_REG_1);
>> +       else
>> +               writel(0xb078, tcphy->base + TX_ANA_CTRL_REG_1);
>> +
>> +       writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2);
>> +       writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
>> +       writel(0, tcphy->base + TX_ANA_CTRL_REG_4);
>> +       writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
>> +       writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL);
>> +       writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA);
>> +
>> +       val = readl(tcphy->base + TX_DIG_CTRL_REG_2);
>> +       val |= BIT(15);
>> +       writel(val, tcphy->base + TX_DIG_CTRL_REG_2);
>> +}
>> +
>> +static void tcphy_dp_hpd(struct rockchip_typec_phy *tcphy,
>> +                        u8 mode)
>> +{
>> +       /* force hpd */
>> +       if (mode)
>> +               regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
>> +                            DPTX_HDP_SEL_MASK | DPTX_HDP_SEL);
>> +       else
>> +               regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
>> +                            DPTX_HDP_SEL_MASK);
>> +}
>> +
>> +static int tcphy_usb3_init(struct rockchip_typec_phy *tcphy)
>> +{
>> +       int timeout = 0;
>> +       int ret, val;
>> +
>> +       /*wait TCPHY for pipe ready */
>> +       while (1) {
>> +               ret = regmap_read(tcphy->grf_regs,
>> +                                 tcphy->exregs.usb3phy_status0, &val);
>> +               val >>= tcphy->exregs.usb3phy_status0_shift;
>> +               if ((val & 0x1) == 0)
>> +                       break;
>> +
>> +               timeout++;
>> +               if (timeout > 1000) {
>> +                       pr_warn("%s wait pipe ready timerout!\n", __func__);
>> +                       break;
>> +               }
>> +               usleep_range(10, 20);
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int tcphy_dp_init(struct rockchip_typec_phy *tcphy)
>> +{
>> +       int ret, val;
>> +
>> +       ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
>> +                                val, val & BIT(6), 1000, PHY_MODE_SET_TIMEOUT);
>> +       if (ret < 0) {
>> +               dev_err(tcphy->dev, "failed to wait TCPHY for DP ready\n");
>> +               return -EBUSY;
>> +       }
>> +
>> +       tcphy_dp_aux_calibration(tcphy);
>> +
>> +       if (tcphy->mode == MODE_DFP_USB3DP)
>> +               writel(0xc101, tcphy->base + DP_MODE_CTL);
>> +       else
>> +               writel(0x0101, tcphy->base + DP_MODE_CTL);
>> +
>> +       ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
>> +                                val, val & BIT(4), 1000, PHY_MODE_SET_TIMEOUT);
>> +       if (ret < 0) {
>> +               dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
>> +               return -EBUSY;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int tcphy_phy_init(struct rockchip_typec_phy *tcphy)
>> +{
>> +       int ret;
>> +       int timeout = 0;
>> +
>> +       ret = clk_prepare_enable(tcphy->clk_core);
>> +       if (ret) {
>> +               dev_err(tcphy->dev, "Failed to prepare_enable core clock\n");
>> +               return ret;
>> +       }
>> +
>> +       ret = clk_prepare_enable(tcphy->clk_ref);
>> +       if (ret) {
>> +               dev_err(tcphy->dev, "Failed to prepare_enable ref clock\n");
>> +               return ret;
>> +       }
>> +
>> +       /* select external psm clock */
>> +       regmap_write(tcphy->grf_regs, tcphy->exregs.usb3phy_con2,
>> +                    BIT(14) | BIT(30));
>> +       regmap_write(tcphy->grf_regs, tcphy->exregs.usb3phy_con0, BIT(19));
>> +
>> +       reset_control_assert(tcphy->phy_rst);
>> +       reset_control_assert(tcphy->pipe_rst);
>> +       reset_control_assert(tcphy->uphy_rst);
>> +
>> +       if (tcphy->num == TYPEC_PHY0)
>> +               regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
>> +                            UPHY_DP_SEL_MASK);
>> +       else
>> +               regmap_write(tcphy->grf_regs, GRF_SOC_CON26,
>> +                            UPHY_DP_SEL_MASK | UPHY_DP_SEL);
>> +
>> +       reset_control_deassert(tcphy->uphy_rst);
>> +
>> +       tcphy_cfg_flip_set(tcphy);
>> +
>> +       tcphy_cfg_pin_assign(tcphy);
>> +
>> +       if (tcphy->mode == MODE_DFP_USB3DP)
>> +               writel(0xc104, tcphy->base + DP_MODE_CTL);
>> +       else if ((tcphy->mode == MODE_DFP_DPONLY) ||
>> +                (tcphy->mode == MODE_DFP_USB2DP))
>> +               writel(0x0104, tcphy->base + DP_MODE_CTL);
>> +
>> +       reset_control_deassert(tcphy->phy_rst);
>> +
>> +       while (!(readl(tcphy->base + PMA_CMN_CTRL1) & 1)) {
>> +               timeout++;
>> +               if (timeout > 1000)
>> +                       break;
>> +               usleep_range(10, 20);
>> +       }
>> +
>> +       reset_control_deassert(tcphy->pipe_rst);
>> +
>> +       return 0;
>> +}
>> +
>> +static int tcphy_phy_deinit(struct rockchip_typec_phy *tcphy)
>> +{
>> +       clk_disable_unprepare(tcphy->clk_core);
>> +       clk_disable_unprepare(tcphy->clk_ref);
>> +
>> +       return 0;
>> +}
>> +
>> +int tcphy_register_notifier(struct phy *_phy, struct notifier_block *nb)
> Is there a reason this isn't static?
>
>> +{
>> +       struct rockchip_typec_phy *tcphy = phy_get_drvdata(_phy);
>> +
>> +       return atomic_notifier_chain_register(&tcphy->notifier, nb);
>> +}
>> +
>> +void tcphy_unregister_notifier(struct phy *_phy,
>> +                              struct notifier_block *nb)
> Is there a reason this isn't static?
>
>> +{
>> +       struct rockchip_typec_phy *tcphy = phy_get_drvdata(_phy);
>> +
>> +       atomic_notifier_chain_unregister(&tcphy->notifier, nb);
>> +}
>> +
>> +void tcphy_notifier_call_chain(struct rockchip_typec_phy *x,
>> +                              unsigned long val, void *v)
>> +{
>> +       atomic_notifier_call_chain(&x->notifier, val, v);
>> +}
>> +EXPORT_SYMBOL_GPL(tcphy_notifier_call_chain);
>> +
>> +static int tcphy_pd_event(struct notifier_block *nb,
>> +                         unsigned long event, void *priv)
>> +{
>> +       struct rockchip_typec_phy *tcphy;
>> +       int value = *(int *)priv;
>> +       u8 is_dp, dfp;
>> +
>> +       tcphy = container_of(nb, struct rockchip_typec_phy, event_nb);
>> +       if (IS_ERR_OR_NULL(tcphy)) {
>> +               pr_err("initialization issue");
>> +               return -1;
>> +       }
>> +
>> +       tcphy->flip = GET_FLIP(value);
>> +       dfp = GET_DFP(value);
>> +       is_dp = GET_DP(value);
>> +       tcphy->map = GET_PIN_MAP(value);
>> +
>> +       if (event == 0) {
>> +               if (tcphy->mode == MODE_DISCONNECT)
>> +                       return 0;
>> +               tcphy->mode = MODE_DISCONNECT;
>> +       } else if (is_dp) {
>> +               if (tcphy->map & (PIN_MAP_B | PIN_MAP_D | PIN_MAP_F))
>> +                       tcphy->mode = MODE_DFP_USB3DP;
>> +               else
>> +                       tcphy->mode = MODE_DFP_DPONLY;
>> +       } else if (dfp) {
>> +               tcphy->mode = MODE_DFP_USBONLY;
>> +       } else {
>> +               tcphy->mode = MODE_UFP;
>> +       }
>> +
>> +       schedule_delayed_work_on(0, &tcphy->event_wq, 0);
>> +
>> +       return 0;
>> +}
>> +
>> +static void tcphy_event_wq(struct work_struct *work)
>> +{
>> +       struct rockchip_typec_phy *tcphy;
>> +
>> +       tcphy = container_of(work, struct rockchip_typec_phy, event_wq.work);
>> +       if (IS_ERR_OR_NULL(tcphy)) {
>> +               pr_err("initialization issue");
>> +               return;
>> +       }
>> +
>> +       switch (tcphy->mode) {
>> +       case MODE_DISCONNECT:
>> +               /* phy enter low power mode */
>> +               tcphy_phy_deinit(tcphy);
>> +               tcphy_dp_hpd(tcphy, 0);
>> +               break;
>> +       case MODE_UFP:
>> +               tcphy_phy_init(tcphy);
>> +               tcphy_usb3_init(tcphy);
>> +               tcphy_dp_hpd(tcphy, 0);
>> +               break;
>> +       case MODE_DFP_USBONLY:
>> +               tcphy_phy_init(tcphy);
>> +               tcphy_usb3_init(tcphy);
>> +               tcphy_dp_hpd(tcphy, 0);
>> +               break;
>> +       case MODE_DFP_DPONLY:
>> +       case MODE_DFP_USB2DP:
>> +               tcphy_phy_init(tcphy);
>> +               tcphy_dp_init(tcphy);
>> +               tcphy_dp_hpd(tcphy, 1);
>> +               break;
>> +       case MODE_DFP_USB3DP:
>> +               tcphy_phy_init(tcphy);
>> +               tcphy_usb3_init(tcphy);
>> +               tcphy_dp_init(tcphy);
>> +               tcphy_dp_hpd(tcphy, 1);
>> +               break;
>> +       }
>> +}
>> +
>> +int tcphy_parse_reg(struct rockchip_typec_phy *tcphy, struct device *dev)
>> +{
>> +       struct tcphy_grf_reg *exregs = &tcphy->exregs;
>> +       struct device_node *np = dev->of_node;
>> +       u32 len = 0, array[3];
>> +       int ret = 0;
>> +
>> +       PARSE_GRF_REG(con0);
>> +       PARSE_GRF_REG(con1);
>> +       PARSE_GRF_REG(con2);
>> +       PARSE_GRF_REG(status0);
>> +       PARSE_GRF_REG(status1);
>> +       return ret;
>> +}
>> +
>> +static int rockchip_typec_phy_probe(struct platform_device *pdev)
>> +{
>> +       struct device *dev = &pdev->dev;
>> +       struct rockchip_typec_phy *tcphy;
>> +       struct resource *res;
>> +       struct phy_provider *phy_provider;
>> +
>> +       tcphy = devm_kzalloc(dev, sizeof(*tcphy), GFP_KERNEL);
>> +       if (!tcphy)
>> +               return -ENOMEM;
>> +
>> +       tcphy->dev = dev;
>> +       platform_set_drvdata(pdev, tcphy);
>> +
>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       tcphy->base = devm_ioremap_resource(dev, res);
>> +       if (IS_ERR(tcphy->base)) {
>> +               dev_err(dev, "failed to remap phy regs\n");
>> +               return PTR_ERR(tcphy->base);
>> +       }
>> +       tcphy->grf_regs = syscon_regmap_lookup_by_phandle(dev->of_node,
>> +                                                       "rockchip,grf");
>> +       if (IS_ERR(tcphy->grf_regs)) {
>> +               dev_err(dev, "%s: could not find grf dt node\n", __func__);
>> +               return PTR_ERR(tcphy->grf_regs);
>> +       }
>> +
>> +       tcphy->clk_core = of_clk_get_by_name(dev->of_node, "tcpdcore");
>> +       if (IS_ERR(tcphy->clk_core)) {
>> +               dev_err(dev, "%s: could not get uphy core clock\n", __func__);
> nit: No real need for __func__.  That's useful to add in when you
> don't have a "dev" pointer and need a "pr_err" to show something that
> will help the user find the right line of code.
>
>> +               tcphy->clk_core = NULL;
> So is tcpdcore optional or required?  Bindings doc says "required" and
> the "dev_err" above implies required.  ...but then you don't return an
> error code.  That makes it optional.  ...but then you use it
> unconditional elsewhere in this file.  That makes it required.
>
> Summary: return an error here, don't just set to NULL.
>
>> +       }
>> +
>> +       tcphy->clk_ref = of_clk_get_by_name(dev->of_node, "tcpdphy_ref");
>> +       if (IS_ERR(tcphy->clk_core)) {
>> +               dev_err(dev, "%s: could not get uphy ref clock\n", __func__);
>> +               tcphy->clk_core = NULL;
> "if" test and NULL assignment are for wrong variables.
>
>> +       }
>> +
>> +       tcphy->phy_rst = devm_reset_control_get(dev, "tcphy_rst");
>> +       if (IS_ERR(tcphy->phy_rst)) {
>> +               dev_err(dev, "no phy_rst reset control found\n");
>> +               return PTR_ERR(tcphy->phy_rst);
>> +       }
>> +
>> +       tcphy->pipe_rst = devm_reset_control_get(dev, "tcphy_pipe_rst");
>> +       if (IS_ERR(tcphy->pipe_rst)) {
>> +               dev_err(dev, "no pipe_rst reset control found\n");
>> +               return PTR_ERR(tcphy->pipe_rst);
>> +       }
>> +
>> +       tcphy->uphy_rst = devm_reset_control_get(dev, "uphy_tcphy_rst");
>> +       if (IS_ERR(tcphy->uphy_rst)) {
>> +               dev_err(dev, "no uphy_rst reset control found\n");
>> +               return PTR_ERR(tcphy->uphy_rst);
>> +       }
>> +
>> +       tcphy_parse_reg(tcphy, dev);
>> +       tcphy->mode = MODE_DISCONNECT;
>> +
>> +       tcphy->phy = devm_phy_create(dev, NULL, NULL);
>> +
>> +       phy_set_drvdata(tcphy->phy, tcphy);
>> +
>> +       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
>> +
>> +       /* register notifier for PD event */
>> +       ATOMIC_INIT_NOTIFIER_HEAD(&tcphy->notifier);
>> +       tcphy->event_nb.notifier_call = tcphy_pd_event;
>> +       INIT_DELAYED_WORK(&tcphy->event_wq, tcphy_event_wq);
>> +       tcphy_register_notifier(tcphy->phy, &tcphy->event_nb);
>> +
>> +       return PTR_ERR_OR_ZERO(phy_provider);
>> +}
>> +
>> +static int rockchip_typec_phy_remove(struct platform_device *pdev)
>> +{
>> +       return 0;
>> +}
> I believe that if you've got an empty remove function you can just remove it.
>
> ...but doesn't remove need to call tcphy_unregister_notifier?
>
>
>> +
>> +static const struct of_device_id rockchip_typec_phy_dt_ids[] = {
>> +       { .compatible = "rockchip,rk3399-typec-phy", },
>> +       {}
>> +};
>> +
>> +MODULE_DEVICE_TABLE(of, rockchip_typec_phy_dt_ids);
>> +
>> +static struct platform_driver rockchip_typec_phy_driver = {
>> +       .probe          = rockchip_typec_phy_probe,
>> +       .remove         = rockchip_typec_phy_remove,
>> +       .driver         = {
>> +               .name   = "rockchip-typec-phy",
>> +               .of_match_table = rockchip_typec_phy_dt_ids,
>> +       },
>> +};
>> +
>> +module_platform_driver(rockchip_typec_phy_driver);
>> +
>> +MODULE_AUTHOR("Kever Yang<kever.yang at rock-chips.com>");
> nit: space before "<"
>
>> +MODULE_AUTHOR("Chris Zhong<zyw at rock-chips.com>");
>> +MODULE_DESCRIPTION("Rockchip USB TYPE-C PHY driver");
>> +MODULE_LICENSE("GPL v2");
>> --
>> 2.6.3
>>
>
>




From zyw at rock-chips.com  Tue May 31 17:43:34 2016
From: zyw at rock-chips.com (Chris Zhong)
Date: Wed, 1 Jun 2016 08:43:34 +0800
Subject: [PATCH 2/6] Documentation: bindings: add dt doc for Rockchip USB
 Type-C PHY
In-Reply-To: <CAD=FV=W9iFXX_BfORP-9=8tnu9Ea_f2k1wK_T2j=ZAVA9cFSwg@mail.gmail.com>
References: <1464328939-8073-1-git-send-email-zyw@rock-chips.com>
 <1464328939-8073-3-git-send-email-zyw@rock-chips.com>
 <2812026.ptEv4ktvbn@phil> <5748094F.6030204@rock-chips.com>
 <CAD=FV=W9iFXX_BfORP-9=8tnu9Ea_f2k1wK_T2j=ZAVA9cFSwg@mail.gmail.com>
Message-ID: <574E2FB6.6010008@rock-chips.com>



On 06/01/2016 03:57 AM, Doug Anderson wrote:
> Chris,
>
> On Fri, May 27, 2016 at 1:46 AM, Chris Zhong <zyw at rock-chips.com> wrote:
>> Hi Heiko
>>
>>
>> On 05/27/2016 04:29 PM, Heiko Stuebner wrote:
>>> Hi Chris,
>>>
>>> Am Freitag, 27. Mai 2016, 14:02:15 schrieb Chris Zhong:
>>>> This patch adds a binding that describes the Rockchip USB Type-C PHY
>>>> for rk3399.
>>>>
>>>> Signed-off-by: Chris Zhong <zyw at rock-chips.com>
>>>> ---
>>>>
>>>>    .../devicetree/bindings/phy/phy-rockchip-typec.txt | 55
>>>> ++++++++++++++++++++++ 1 file changed, 55 insertions(+)
>>>>    create mode 100644
>>>> Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
>>>> b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt new file
>>>> mode 100644
>>>> index 0000000..402f667
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
>>>> @@ -0,0 +1,55 @@
>>>> +ROCKCHIP type-c PHY
>>>> +
>>>> +Required properties:
>>>> + - compatible: should be "rockchip,rk3399-typec-phy"
>>>> + - reg : Address and length of the usb phy control register set
>>>> + - rockchip,grf : phandle to the syscon managing the "general
>>>> +   register files"
>>>> + - clocks : phandle + clock specifier for the phy clocks
>>>> + - clock-names: string, clock name, must be "tcpdcore", "tcpdphy_ref";
>>>> + - resets : a list of phandle + reset specifier pairs
>>>> + - reset-names : string reset name, must be:
>>>> +                "tcphy_rst", "tcphy_pipe_rst", "uphy_tcphy_rst"
> In other contexts I believe Heiko has requested that a suffix like
> "_rst" not be present in the names of reset signals.  We already know
> that this is a list of reset names so the "_rst" is redundant.
Yes, "_rst" is redundant.I will remove it next version.
>
>>>> + - #phy-cells: Must be 0.  See ./phy-bindings.txt for details.
>>>> + - rockchip,usb3phy*: phy registers embed in grf
>>>> +
>>>> +Example:
>>>> +       tcphy0: phy at ff7c0000 {
>>>> +               compatible = "rockchip,rk3399-typec-phy";
>>>> +               reg = <0x0 0xff7c0000 0x0 0x40000>;
>>>> +               #phy-cells = <0>;
>>>> +               rockchip,grf = <&grf>;
>>>> +               clocks = <&cru SCLK_UPHY0_TCPDCORE>,
>>>> +                        <&cru SCLK_UPHY0_TCPDPHY_REF>;
>>>> +               clock-names = "tcpdcore", "tcpdphy_ref";
>>>> +               resets = <&cru SRST_UPHY0>,
>>>> +                        <&cru SRST_UPHY0_PIPE_L00>,
>>>> +                        <&cru SRST_P_UPHY0_TCPHY>;
>>>> +               reset-names = "tcphy_rst", "tcphy_pipe_rst",
>>>> "uphy_tcphy_rst";
>>>> +               rockchip,usb3phy_con0 = <0x0e580 0 16>;
>>>> +               rockchip,usb3phy_con1 = <0x0e584 0 16>;
>>>> +               rockchip,usb3phy_con2 = <0x0e588 0 16>;
>>>> +               rockchip,usb3phy_status0 = <0x0e5c0 0 13>;
>>>> +               rockchip,usb3phy_status1 = <0x0e5c4 0 12>;
>>> please embedded this register data in the driver instead (not in the
>>> devicetree), matched against the compatible value.
>>> See Frank's usb2phy driver for reference if needed.
>> Okay, I will move them to driver file next version, Thanks.
> Just making sure: I saw a RESEND of your original version get posted,
> but nothing that addresses Heiko's comments, right?
>
> Also: note that bindings should be sent in the patch _before_ the
> code.  So instead of:
>    [1] phy: Add USB Type-C PHY driver for rk3399
>    [2] Documentation: bindings: add dt doc for Rockchip USB Type-C PHY
>    [3] drm/rockchip: vop: add cdn DP support for rk3399
>    [4] Documentation: bindings: add dt documentation for cdn DP controller
>
> You should have:
>    [1] Documentation: bindings: add dt doc for Rockchip USB Type-C PHY
>    [2] phy: Add USB Type-C PHY driver for rk3399
>    [3] Documentation: bindings: add dt documentation for cdn DP controller
>    [4] drm/rockchip: vop: add cdn DP support for rk3399
The first patch is lack of a header file, so I resend the patches, and 
did not change anything, I will do them in V1 version.
And I will change the  sequence of patches, Thanks for your comments.


>
> -Doug
>
>
>




From horms at verge.net.au  Tue May 31 17:57:51 2016
From: horms at verge.net.au (Simon Horman)
Date: Wed, 1 Jun 2016 09:57:51 +0900
Subject: [PATCH 07/13] ARM: dts: r8a7792: initial SoC device tree
In-Reply-To: <2539026.OyU5nvpxa6@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
 <2539026.OyU5nvpxa6@wasted.cogentembedded.com>
Message-ID: <20160601005751.GG20527@verge.net.au>

On Wed, Jun 01, 2016 at 01:24:21AM +0300, Sergei Shtylyov wrote:
> The initial R8A7792 SoC device tree including 2 CPU cores, GIC, timer, SYSC,
> and the required  clock descriptions.
> 
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

This is rather large for an initial DTSI. Did you give any consideration
to splitting it up: e.g. only providing what is needed to get to a serial
console?

With regards to SMP. Have you checked to make sure CPU hotplug works
on all CPUs? And that the system behaves sanely on suspend/resume.
If it is not possible to verify this at this stage then I would recommend
only enabling one CPU at this stage.


From horms at verge.net.au  Tue May 31 18:03:00 2016
From: horms at verge.net.au (Simon Horman)
Date: Wed, 1 Jun 2016 10:03:00 +0900
Subject: [PATCH 08/13] ARM: dts: r8a7792: add SYS-DMAC support
In-Reply-To: <5621267.GpvUaW18zI@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
 <5621267.GpvUaW18zI@wasted.cogentembedded.com>
Message-ID: <20160601010300.GH20527@verge.net.au>

On Wed, Jun 01, 2016 at 01:25:24AM +0300, Sergei Shtylyov wrote:
> Describe SYS-DMAC0/1 in the R8A7792 device tree.
> 
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

Acked-by: Simon Horman <horms+renesas at verge.net.au>



From thunder.leizhen at huawei.com  Tue May 31 18:05:02 2016
From: thunder.leizhen at huawei.com (Leizhen (ThunderTown))
Date: Wed, 1 Jun 2016 09:05:02 +0800
Subject: [PATCH v2 5/5] arm64/numa: avoid inconsistent information to be
 printed
In-Reply-To: <574D751D.9020901@huawei.com>
References: <1464427377-12712-1-git-send-email-thunder.leizhen@huawei.com>
 <1464427377-12712-6-git-send-email-thunder.leizhen@huawei.com>
 <574D543A.2090406@suse.com> <574D751D.9020901@huawei.com>
Message-ID: <574E34BE.5040204@huawei.com>



On 2016/5/31 19:27, Leizhen (ThunderTown) wrote:
> 
> 
> On 2016/5/31 17:07, Matthias Brugger wrote:
>>
>>
>> On 28/05/16 11:22, Zhen Lei wrote:
>>> numa_init(of_numa_init) may returned error because of numa configuration
>>> error. So "No NUMA configuration found" is inaccurate. In fact, specific
>>> configuration error information should be immediately printed by the
>>> testing branch.
>>>
>>> Signed-off-by: Zhen Lei <thunder.leizhen at huawei.com>
>>> ---
>>
>> Which kernel version is this patch based on?
> 
> Base on mainline(git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git), I git pulled about 3-5 days ago, the last commit-id is dc03c0f.
> 
> And thess patches base on https://lkml.org/lkml/2016/5/24/679 series(acpi numa) as David Daney's requirement.
> 
>>
>> Regards,
>> Matthias
>>
>>>   arch/arm64/mm/numa.c | 6 +++---
>>>   drivers/of/of_numa.c | 7 +++----
>>>   2 files changed, 6 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
>>> index 2601660..1b9622c 100644
>>> --- a/arch/arm64/mm/numa.c
>>> +++ b/arch/arm64/mm/numa.c
>>> @@ -338,8 +338,10 @@ static int __init numa_init(int (*init_func)(void))
>>>       if (ret < 0)
>>>           return ret;
>>>
>>> -    if (nodes_empty(numa_nodes_parsed))
>>> +    if (nodes_empty(numa_nodes_parsed)) {
>>> +        pr_info("No NUMA configuration found\n");
>>>           return -EINVAL;
>>> +    }
>>>
>>>       ret = numa_register_nodes();
>>>       if (ret < 0)
>>> @@ -370,8 +372,6 @@ static int __init dummy_numa_init(void)
>>>
>>>       if (numa_off)
>>>           pr_info("NUMA disabled\n"); /* Forced off on command line. */
>>> -    else
>>> -        pr_info("No NUMA configuration found\n");
>>>       pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
>>>              0LLU, PFN_PHYS(max_pfn) - 1);
>>>
>>> diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c
>>> index fb62307..3157130 100644
>>> --- a/drivers/of/of_numa.c
>>> +++ b/drivers/of/of_numa.c
>>> @@ -63,7 +63,7 @@ static int __init of_numa_parse_memory_nodes(void)
>>>       struct device_node *np = NULL;
>>>       struct resource rsrc;
>>>       u32 nid;
>>> -    int i, r = 0;
>>> +    int i, r;
>>>
>>>       for_each_node_by_type(np, "memory") {
>>>           r = of_property_read_u32(np, "numa-node-id", &nid);
>>> @@ -81,12 +81,11 @@ static int __init of_numa_parse_memory_nodes(void)
>>>           if (!i || r) {
>>>               of_node_put(np);
>>>               pr_err("NUMA: bad property in memory node\n");
>>> -            r = r ? : -EINVAL;
>>> -            break;
>>> +            return r ? : -EINVAL;
>>>           }
>>>       }
>>>
>>> -    return r;
>>> +    return 0;
>>>   }
>>>
>>
>> Well this is fixing changes you introduced in this patch-set. Any reason this is not part of patch 2?
> 
> Because they fixed two different problems.

Hi, Matthias

I thougth it again on my way home yesterday. Yeah, you're right, move this part to patch 2, will make these two
patches looks more well. I put it here before, because for "No numa configuration" case, it originally returns error
code, so that it can not walk to "if (nodes_empty(numa_nodes_parsed))".

	ret = init_func();
	if (ret < 0)
		return ret;

   -    if (nodes_empty(numa_nodes_parsed))
   +    if (nodes_empty(numa_nodes_parsed)) {
   +        pr_info("No NUMA configuration found\n");
       		return -EINVAL;
   +    }

Regards,
Zhen Lei

> 
>>
>>>   static int __init of_numa_parse_distance_map_v1(struct device_node *map)
>>> -- 
>>> 2.5.0
>>>
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>
>>
>> .
>>



From andrew at lunn.ch  Tue May 31 18:11:48 2016
From: andrew at lunn.ch (Andrew Lunn)
Date: Wed, 1 Jun 2016 03:11:48 +0200
Subject: [PATCH v2 3/5] drivers: net: phy: Add MDIO driver
In-Reply-To: <1464739840-21971-4-git-send-email-isubramanian@apm.com>
References: <1464739840-21971-1-git-send-email-isubramanian@apm.com>
 <1464739840-21971-4-git-send-email-isubramanian@apm.com>
Message-ID: <20160601011148.GD31982@lunn.ch>

On Tue, May 31, 2016 at 05:10:38PM -0700, Iyappan Subramanian wrote:
> +static int xgene_mdio_reset(struct xgene_mdio_pdata *pdata)
> +{
> +	int ret;
> +
> +	if (pdata->mdio_id == XGENE_MDIO_RGMII) {
> +		if (pdata->dev->of_node) {
> +			clk_prepare_enable(pdata->clk);
> +			clk_disable_unprepare(pdata->clk);
> +			clk_prepare_enable(pdata->clk);

Hi Iyappan

Is that a workaround for a hardware problem? If so, i would suggest
adding a comment, to stop people submitting a patch simplifying it.


> +static int xgene_mdio_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct mii_bus *mdio_bus;
> +	const struct of_device_id *of_id;
> +	struct resource *res;
> +	struct xgene_mdio_pdata *pdata;
> +	void __iomem *csr_addr;
> +	int mdio_id = 0, ret = 0;
> +


> +	of_id = of_match_device(xgene_mdio_of_match, &pdev->dev);
> +	if (mdio_id == XGENE_MDIO_RGMII) {
> +		mdio_bus->read = xgene_mdio_rgmii_read;
> +		mdio_bus->write = xgene_mdio_rgmii_write;
> +	} else {
> +		mdio_bus->read = xgene_xfi_mdio_read;
> +		mdio_bus->write = xgene_xfi_mdio_write;
> +	}

> +static const struct of_device_id xgene_mdio_of_match[] = {
> +	{
> +		.compatible = "apm,xgene-mdio-rgmii",
> +		.data = (void *)XGENE_MDIO_RGMII
> +	},
> +	{
> +		.compatible = "apm,xgene-mdio-xfi",
> +		.data = (void *)XGENE_MDIO_XFI},
> +	{},
> +};


This all makes me think you should have two separate MDIO drivers, one
for each compatible string. There is not that much shared code.

    Andrew


From horms at verge.net.au  Tue May 31 18:13:49 2016
From: horms at verge.net.au (Simon Horman)
Date: Wed, 1 Jun 2016 10:13:49 +0900
Subject: [PATCH 09/13] ARM: dts: r8a7792: add [H]SCIF support
In-Reply-To: <1493287.pGnW6U6caN@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
 <1493287.pGnW6U6caN@wasted.cogentembedded.com>
Message-ID: <20160601011348.GI20527@verge.net.au>

On Wed, Jun 01, 2016 at 01:26:56AM +0300, Sergei Shtylyov wrote:
> Describe [H]SCIFs in the R8A7792 device tree.
> 
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

This looks correct to me.

I am wondering if you have been able to confirm DMA operation of the
devices enabled later on in the series.

> 
> ---
>  arch/arm/boot/dts/r8a7792.dtsi |   90 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 90 insertions(+)
> 
> Index: renesas/arch/arm/boot/dts/r8a7792.dtsi
> ===================================================================
> --- renesas.orig/arch/arm/boot/dts/r8a7792.dtsi
> +++ renesas/arch/arm/boot/dts/r8a7792.dtsi
> @@ -140,6 +140,96 @@
>  		dma-channels = <15>;
>  	};
>  
> +	scif0: serial at e6e60000 {
> +		compatible = "renesas,scif-r8a7792", "renesas,rcar-gen2-scif",
> +			     "renesas,scif";
> +		reg = <0 0xe6e60000 0 64>;
> +		interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&mstp7_clks R8A7792_CLK_SCIF0>, <&zs_clk>,
> +			 <&scif_clk>;
> +		clock-names = "fck", "brg_int", "scif_clk";
> +		dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
> +		       <&dmac1 0x29>, <&dmac1 0x2a>;
> +		dma-names = "tx", "rx", "tx", "rx";
> +		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
> +		status = "disabled";
> +	};
> +
> +	scif1: serial at e6e68000 {
> +		compatible = "renesas,scif-r8a7792", "renesas,rcar-gen2-scif",
> +			     "renesas,scif";
> +		reg = <0 0xe6e68000 0 64>;
> +		interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&mstp7_clks R8A7792_CLK_SCIF1>, <&zs_clk>,
> +			 <&scif_clk>;
> +		clock-names = "fck", "brg_int", "scif_clk";
> +		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
> +		       <&dmac1 0x2d>, <&dmac1 0x2e>;
> +		dma-names = "tx", "rx", "tx", "rx";
> +		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
> +		status = "disabled";
> +	};
> +
> +	scif2: serial at e6e58000 {
> +		compatible = "renesas,scif-r8a7792", "renesas,rcar-gen2-scif",
> +			     "renesas,scif";
> +		reg = <0 0xe6e58000 0 64>;
> +		interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&mstp7_clks R8A7792_CLK_SCIF2>, <&zs_clk>,
> +			 <&scif_clk>;
> +		clock-names = "fck", "brg_int", "scif_clk";
> +		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
> +		       <&dmac1 0x2b>, <&dmac1 0x2c>;
> +		dma-names = "tx", "rx", "tx", "rx";
> +		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
> +		status = "disabled";
> +	};
> +
> +	scif3: serial at e6ea8000 {
> +		compatible = "renesas,scif-r8a7792", "renesas,rcar-gen2-scif",
> +			     "renesas,scif";
> +		reg = <0 0xe6ea8000 0 64>;
> +		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&mstp7_clks R8A7792_CLK_SCIF3>, <&zs_clk>,
> +			 <&scif_clk>;
> +		clock-names = "fck", "brg_int", "scif_clk";
> +		dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
> +		       <&dmac1 0x2f>, <&dmac1 0x30>;
> +		dma-names = "tx", "rx", "tx", "rx";
> +		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
> +		status = "disabled";
> +	};
> +
> +	hscif0: serial at e62c0000 {
> +		compatible = "renesas,hscif-r8a7792", "renesas,rcar-gen2-hscif",
> +			     "renesas,hscif";
> +		reg = <0 0xe62c0000 0 96>;
> +		interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&mstp7_clks R8A7792_CLK_HSCIF0>, <&zs_clk>,
> +			 <&scif_clk>;
> +		clock-names = "fck", "brg_int", "scif_clk";
> +		dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
> +		       <&dmac1 0x39>, <&dmac1 0x3a>;
> +		dma-names = "tx", "rx", "tx", "rx";
> +		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
> +		status = "disabled";
> +	};
> +
> +	hscif1: serial at e62c8000 {
> +		compatible = "renesas,hscif-r8a7792", "renesas,rcar-gen2-hscif",
> +			     "renesas,hscif";
> +		reg = <0 0xe62c8000 0 96>;
> +		interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&mstp7_clks R8A7792_CLK_HSCIF1>, <&zs_clk>,
> +			 <&scif_clk>;
> +		clock-names = "fck", "brg_int", "scif_clk";
> +		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
> +		       <&dmac1 0x4d>, <&dmac1 0x4e>;
> +		dma-names = "tx", "rx", "tx", "rx";
> +		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
> +		status = "disabled";
> +	};
> +
>  	clocks {
>  		#address-cells = <2>;
>  		#size-cells = <2>;
> 


From horms at verge.net.au  Tue May 31 18:18:13 2016
From: horms at verge.net.au (Simon Horman)
Date: Wed, 1 Jun 2016 10:18:13 +0900
Subject: [PATCH 10/13] ARM: dts: r8a7792: add IRQC support
In-Reply-To: <3573091.BUvyGW3hVt@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
 <3573091.BUvyGW3hVt@wasted.cogentembedded.com>
Message-ID: <20160601011813.GJ20527@verge.net.au>

On Wed, Jun 01, 2016 at 01:29:05AM +0300, Sergei Shtylyov wrote:
> Describe the IRQC interrupt controller in the R8A7792 device tree.
> 
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>
> 
> ---
>  arch/arm/boot/dts/r8a7792.dtsi |   13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> Index: renesas/arch/arm/boot/dts/r8a7792.dtsi
> ===================================================================
> --- renesas.orig/arch/arm/boot/dts/r8a7792.dtsi
> +++ renesas/arch/arm/boot/dts/r8a7792.dtsi
> @@ -62,6 +62,19 @@
>  			      IRQ_TYPE_LEVEL_HIGH)>;
>  	};
>  
> +	irqc: interrupt-controller at e61c0000 {

Could you consider using irqc0 as the node name for consistency with the
DT of other R-Car Gen2 SoCs?

What follows looks correct to me.

> +		compatible = "renesas,irqc-r8a7792", "renesas,irqc";
> +		#interrupt-cells = <2>;
> +		interrupt-controller;
> +		reg = <0 0xe61c0000 0 0x200>;
> +		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
> +			     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&mstp4_clks R8A7792_CLK_IRQC>;
> +		power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
> +	};
> +
>  	timer {
>  		compatible = "arm,armv7-timer";
>  		interrupts = <GIC_PPI 13
> 


From horms at verge.net.au  Tue May 31 18:21:53 2016
From: horms at verge.net.au (Simon Horman)
Date: Wed, 1 Jun 2016 10:21:53 +0900
Subject: [PATCH 12/13] ARM: dts: blanche: initial device tree
In-Reply-To: <1923946.Jvi0TDUXFC@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
 <1923946.Jvi0TDUXFC@wasted.cogentembedded.com>
Message-ID: <20160601012153.GK20527@verge.net.au>

On Wed, Jun 01, 2016 at 01:32:35AM +0300, Sergei Shtylyov wrote:
> Add the initial device  tree for the R8A7792 SoC based Blanche board.
> The board has 2 debug serial ports: SCIF0 and SCIF3; include support for
> them,  so that  the serial console  can  work.
> 
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

At this time I do not have access to documentation or hardware for this
board. So I am relying on you to test this and make sure it complies
with the spec.

What you have looks reasonable to me:

Acked-by: Simon Horman <horms+renesas at verge.net.au>


From horms at verge.net.au  Tue May 31 18:24:51 2016
From: horms at verge.net.au (Simon Horman)
Date: Wed, 1 Jun 2016 10:24:51 +0900
Subject: [PATCH 13/13] ARM: dts: blanche: add Ethernet support
In-Reply-To: <1669958.qjJ7i3NBPv@wasted.cogentembedded.com>
References: <13205049.n7pM8utpHF@wasted.cogentembedded.com>
 <1669958.qjJ7i3NBPv@wasted.cogentembedded.com>
Message-ID: <20160601012451.GL20527@verge.net.au>

On Wed, Jun 01, 2016 at 01:33:49AM +0300, Sergei Shtylyov wrote:
> R8A7792  SoC  doesn't have the EtherMAC core, so SMSC  LAN89218  Ethernet
> chip was used instead on the Blanche board; this chip  is compatible with
> SMSC LAN9115  for  which there's a (device tree aware) driver. Describe
> the  chip in  the  Blanche device tree;  enable DHCP and NFS root in the
> kernel command line for the kernel booting.
> 
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov at cogentembedded.com>

At this time I do not have access to documentation or hardware for this
board. So I am relying on you to test this and make sure it complies
with the spec.

What you have looks reasonable to me:

Acked-by: Simon Horman <horms+renesas at verge.net.au>


From jh80.chung at samsung.com  Tue May 31 18:25:05 2016
From: jh80.chung at samsung.com (Jaehoon Chung)
Date: Wed, 01 Jun 2016 10:25:05 +0900
Subject: [PATCH 1/3] mmc: fix mmc mode selection for HS-DDR and higher
In-Reply-To: <1464505484-3661-2-git-send-email-wens@csie.org>
References: <1464505484-3661-1-git-send-email-wens@csie.org>
 <CGME20160529070454epcas1p4cf3be0deda6773296b516e7d25a4188e@epcas1p4.samsung.com>
 <1464505484-3661-2-git-send-email-wens@csie.org>
Message-ID: <574E3971.30202@samsung.com>

On 05/29/2016 04:04 PM, Chen-Yu Tsai wrote:
> When IS_ERR_VALUE was removed from the mmc core code, it was replaced
> with a simple not-zero check. This does not work, as the value checked
> is the return value for mmc_select_bus_width, which returns the set
> bit width on success. This made eMMC modes higher than HS-DDR unusable.
> 
> Fix this by checking for a positive return value instead.
> 
> Fixes: 287980e49ffc ("remove lots of IS_ERR_VALUE abuses")
> Cc: Arnd Bergmann <arnd at arndb.de>
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>

Acked-by: Jaehoon Chung <jh80.chung at samsung.com>

Best Regards,
Jaehoon Chung

> ---
>  drivers/mmc/core/mmc.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index c984321d1881..aafb73d080ca 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -1276,7 +1276,7 @@ static int mmc_select_hs200(struct mmc_card *card)
>  	 * switch to HS200 mode if bus width is set successfully.
>  	 */
>  	err = mmc_select_bus_width(card);
> -	if (!err) {
> +	if (err > 0) {
>  		val = EXT_CSD_TIMING_HS200 |
>  		      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
>  		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> @@ -1583,7 +1583,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
>  	} else if (mmc_card_hs(card)) {
>  		/* Select the desired bus width optionally */
>  		err = mmc_select_bus_width(card);
> -		if (!err) {
> +		if (err > 0) {
>  			err = mmc_select_hs_ddr(card);
>  			if (err)
>  				goto free_card;
> 



From ttnguyen at apm.com  Tue May 31 18:25:56 2016
From: ttnguyen at apm.com (Tai Tri Nguyen)
Date: Tue, 31 May 2016 18:25:56 -0700
Subject: [PATCH v2 2/4] Documentation: Add documentation for APM X-Gene
 SoC PMU DTS binding
In-Reply-To: <CACgAJHwtb0hNs0JWOrpyF=_fRVvUi2QG4q7qohgCw4SjxqtX6A@mail.gmail.com>
References: <1460510547-17611-1-git-send-email-ttnguyen@apm.com>
 <1460510547-17611-3-git-send-email-ttnguyen@apm.com>
 <20160418170009.GA15338@rob-hp-laptop>
 <CACgAJHyBbO_LXwtfNVK1f=dY3v1Jfxwxq1dw98EZ0aYdhjPpAg@mail.gmail.com>
 <20160420113121.GE2514@arm.com>
 <20160502205648.GA7374@rob-hp-laptop>
 <CACgAJHyT31DuVNoyRQZVKjv=zM5Fc-EY0gy=y=pHHrBTT+1Xow@mail.gmail.com>
 <20160531165630.GE4254@leverpostej>
 <CACgAJHwtb0hNs0JWOrpyF=_fRVvUi2QG4q7qohgCw4SjxqtX6A@mail.gmail.com>
Message-ID: <CACgAJHxMCa2Hp_A8YnHmmVrHGd3yLhFs2k33MN6OHRUmZ7Y_Wg@mail.gmail.com>

Hi Mark,

On Tue, May 31, 2016 at 10:17 AM, Tai Tri Nguyen <ttnguyen at apm.com> wrote:
> Hi Mark,
>
> On Tue, May 31, 2016 at 9:56 AM, Mark Rutland <mark.rutland at arm.com> wrote:
>> On Mon, May 02, 2016 at 02:46:05PM -0700, Tai Tri Nguyen wrote:
>>> Hi Rob,
>>>
>>> On Mon, May 2, 2016 at 1:56 PM, Rob Herring <robh at kernel.org> wrote:
>>> > On Wed, Apr 20, 2016 at 12:31:22PM +0100, Will Deacon wrote:
>>> >> On Mon, Apr 18, 2016 at 01:04:53PM -0700, Tai Tri Nguyen wrote:
>>> >> > >> +Required properties for MCB subnode:
>>> >> > >> +- compatible         : Shall be "apm,xgene-pmu-mcb".
>>> >> > >> +- reg                        : First resource shall be the MCB PMU resource.
>>> >> > >> +- index                      : Instance number of the MCB PMU.
>>> >> > >> +
>>> >> > >> +Required properties for MC subnode:
>>> >> > >> +- compatible         : Shall be "apm,xgene-pmu-mc".
>>> >> > >> +- reg                        : First resource shall be the MC PMU resource.
>>> >> > >> +- index                      : Instance number of the MC PMU.
>>> >> > >
>>> >> > > Don't use indexes. You probably need phandles to the nodes these are
>>> >> > > related to.
>>> >> > >
>>> >> > > How many variations of child nodes do you expect to have? 2, 10, 50? You
>>> >> > > might want to just collapse all this down to a single node and put this
>>> >> > > information in the driver if it is fixed for each SoC and there's only a
>>> >> > > handful.
>>> >> > >
>>> >> >
>>> >> > For each kind of PMU, for example memory controller PMU, I expect to
>>> >> > have the number of instances up to 8.
>>> >> > They are actually all independent PMU nodes and have their own CSR memory bases.
>>> >> > The indexes are used for exposing the devices to perf user only. It
>>> >> > doesn't have an impact on the programming model.
>>> >> > Mark also had the same concern.
>>> >>
>>> >> Regardless, I'll need an ack from Rob or Mark before I can merge this.
>>> >
>>> > I still have a concern with this. Needing an index to expose to the user
>>> > is generally not a valid reason. That's OS specific and therefore
>>> > doesn't belong in DT.
>>> >
>>> > Rob
>>>
>>> I can use device name here. However, the perf event names will be
>>> different between DT and ACPI which I want to avoid.
>>> And the names don't look good at all.
>>> Also, specifically for MC and MCB PMUs, the indexes are compared
>>> against the active MC/MCB mask to find out whether they are populated
>>> or not.
>>> Without using the index property, I will also need a mapping function
>>> of physical device addresses and their physical ids.
>>
>> What's wrong with using ${device}.{physical_address} as the PMU name?
>> That would be unique and consistent regardless of the firmware, no
>> mapping nor index property necessary.
>>
>> That's sufficient for any user already familiar with the topology, a
>> familiarity you seem to be assuming regardless by not explicitly
>> describing the topology in the DT.
>>
>> Thanks,
>> Mark.
>
> Okay. I'll do fix it for the next patches.
>
> Thanks,
> --
> Tai

I'm facing a problem after removing the index for MCU and MC sub-nodes.
The MCUs and MCs aren't always enabled depending on how DRAM DIMMs are
installed on the system.
I still need a way to associate the MCU with its indicator bit in the
enable mask retrieved from CSR.
For MC and MCB nodes only, can I introduce an "enable-mask" field?
For example:
"
pmucmcb at 7e710000 {
        compatible = "apm,xgene-pmu-mcb";
        reg = <0x0 0x7e710000 0x0 0x1000>;
        enable-mask = <0x00000001>;
};

pmucmcb at 7e730000 {
        compatible = "apm,xgene-pmu-mcb";
        reg = <0x0 0x7e730000 0x0 0x1000>;
        enable-mask = <0x00000002>;
};
"
Or can you please give a suggestion how I can fix it?

Thanks,
-- 
Tai


From herbert at gondor.apana.org.au  Tue May 31 18:28:17 2016
From: herbert at gondor.apana.org.au (Herbert Xu)
Date: Wed, 1 Jun 2016 09:28:17 +0800
Subject: [PATCH v2 0/4] hw rng support for NSP SoC
In-Reply-To: <574DC553.4030009@gmail.com>
References: <1464343841-29504-1-git-send-email-yendapally.reddy@broadcom.com>
 <20160531101934.GM15376@gondor.apana.org.au>
 <574DC553.4030009@gmail.com>
Message-ID: <20160601012817.GB30653@gondor.apana.org.au>

On Tue, May 31, 2016 at 10:09:39AM -0700, Florian Fainelli wrote:
>
> FYI, ARM Device Tree patches usually go via ARM SoC pull requests, so it
> is best if this is planned in advance. Can you make sure you document
> that there could be a merge conflict in your pull request to Linus?

Sure I can do that.

Thanks,
-- 
Email: Herbert Xu <herbert at gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt


From chanho.min at lge.com  Tue May 31 18:39:59 2016
From: chanho.min at lge.com (Chanho Min)
Date: Wed, 1 Jun 2016 10:39:59 +0900
Subject: [PATCH 2/2] arm64: defconfig: Enable Cadence MACB/GEM support
In-Reply-To: <1464745199-19186-1-git-send-email-chanho.min@lge.com>
References: <1464745199-19186-1-git-send-email-chanho.min@lge.com>
Message-ID: <1464745199-19186-2-git-send-email-chanho.min@lge.com>

This patch enables the cadence MACB/GEM support that is needed
by lg1k SoCs.

Signed-off-by: Chanho Min <chanho.min at lge.com>
---
 arch/arm64/configs/defconfig |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index fd2d74d..4edbbac 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -120,6 +120,7 @@ CONFIG_TUN=y
 CONFIG_VIRTIO_NET=y
 CONFIG_AMD_XGBE=y
 CONFIG_NET_XGENE=y
+CONFIG_MACB=y
 CONFIG_E1000E=y
 CONFIG_IGB=y
 CONFIG_IGBVF=y
-- 
1.7.9.5



From chanho.min at lge.com  Tue May 31 18:39:58 2016
From: chanho.min at lge.com (Chanho Min)
Date: Wed, 1 Jun 2016 10:39:58 +0900
Subject: [PATCH 1/2] arm64: dts: Add dts files for LG Electronics's lg1313 SoC
Message-ID: <1464745199-19186-1-git-send-email-chanho.min@lge.com>

Add dtsi file to support lg1313 SoC which based on Cortex-A53.
Also add dts file to support lg1312 reference board which based
on lg1313 SoC.

Signed-off-by: Chanho Min <chanho.min at lge.com>
---
 arch/arm64/boot/dts/lg/Makefile       |    1 +
 arch/arm64/boot/dts/lg/lg1313-ref.dts |   36 ++++
 arch/arm64/boot/dts/lg/lg1313.dtsi    |  351 +++++++++++++++++++++++++++++++++
 3 files changed, 388 insertions(+)
 create mode 100644 arch/arm64/boot/dts/lg/lg1313-ref.dts
 create mode 100644 arch/arm64/boot/dts/lg/lg1313.dtsi

diff --git a/arch/arm64/boot/dts/lg/Makefile b/arch/arm64/boot/dts/lg/Makefile
index b0cc649..5c7b54c1 100644
--- a/arch/arm64/boot/dts/lg/Makefile
+++ b/arch/arm64/boot/dts/lg/Makefile
@@ -1,4 +1,5 @@
 dtb-$(CONFIG_ARCH_LG1K) += lg1312-ref.dtb
+dtb-$(CONFIG_ARCH_LG1K) += lg1313-ref.dtb
 
 always		:= $(dtb-y)
 subdir-y	:= $(dts-dirs)
diff --git a/arch/arm64/boot/dts/lg/lg1313-ref.dts b/arch/arm64/boot/dts/lg/lg1313-ref.dts
new file mode 100644
index 0000000..df0ece4
--- /dev/null
+++ b/arch/arm64/boot/dts/lg/lg1313-ref.dts
@@ -0,0 +1,36 @@
+/*
+ * dts file for lg1313 Reference Board.
+ *
+ * Copyright (C) 2016, LG Electronics
+ */
+
+/dts-v1/;
+
+#include "lg1313.dtsi"
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <1>;
+
+	model = "LG Electronics, DTV SoC LG1313 Reference Board";
+	compatible = "lge,lg1313-ref", "lge,lg1313";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x00000000 0x20000000>;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/lg/lg1313.dtsi b/arch/arm64/boot/dts/lg/lg1313.dtsi
new file mode 100644
index 0000000..e703e11
--- /dev/null
+++ b/arch/arm64/boot/dts/lg/lg1313.dtsi
@@ -0,0 +1,351 @@
+/*
+ * dts file for lg1313 SoC
+ *
+ * Copyright (C) 2016, LG Electronics
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	compatible = "lge,lg1313";
+	interrupt-parent = <&gic>;
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x0>;
+			next-level-cache = <&L2_0>;
+		};
+		cpu1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+			next-level-cache = <&L2_0>;
+		};
+		cpu2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+			next-level-cache = <&L2_0>;
+		};
+		cpu3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+			next-level-cache = <&L2_0>;
+		};
+		L2_0: l2-cache0 {
+			compatible = "cache";
+		};
+	};
+
+	psci {
+		compatible  = "arm,psci-0.2", "arm,psci";
+		method = "smc";
+		cpu_suspend = <0x84000001>;
+		cpu_off = <0x84000002>;
+		cpu_on = <0x84000003>;
+	};
+
+	gic: interrupt-controller at c0001000 {
+		#interrupt-cells = <3>;
+		compatible = "arm,gic-400";
+		interrupt-controller;
+		reg = <0x0 0xc0001000 0x1000>,
+		      <0x0 0xc0002000 0x2000>,
+		      <0x0 0xc0004000 0x2000>,
+		      <0x0 0xc0006000 0x2000>;
+	};
+
+	pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>,
+				     <&cpu1>,
+				     <&cpu2>,
+				     <&cpu3>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(0x0f) |
+			      IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_RAW(0x0f) |
+			      IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_RAW(0x0f) |
+			      IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_RAW(0x0f) |
+			      IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	clk_bus: clk_bus {
+		#clock-cells = <0>;
+
+		compatible = "fixed-clock";
+		clock-frequency = <198000000>;
+		clock-output-names = "BUSCLK";
+	};
+
+	soc {
+		#address-cells = <2>;
+		#size-cells = <1>;
+
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		ranges;
+
+		eth0: ethernet at c3700000 {
+			compatible = "cdns,gem";
+			reg = <0x0 0xc3700000 0x1000>;
+			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>, <&clk_bus>;
+			clock-names = "hclk", "pclk";
+			phy-mode = "rmii";
+			/* Filled in by boot */
+			mac-address = [ 00 00 00 00 00 00 ];
+		};
+	};
+
+	amba {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		#interrupts-cells = <3>;
+
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		ranges;
+
+		timers: timer at fd100000 {
+			compatible = "arm,sp804";
+			reg = <0x0 0xfd100000 0x1000>;
+			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		wdog: watchdog at fd200000 {
+			compatible = "arm,sp805", "arm,primecell";
+			reg = <0x0 0xfd200000 0x1000>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		uart0: serial at fe000000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0xfe000000 0x1000>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		uart1: serial at fe100000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0xfe100000 0x1000>;
+			interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		uart2: serial at fe200000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0xfe200000 0x1000>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		spi0: ssp at fe800000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x0 0xfe800000 0x1000>;
+			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		spi1: ssp at fe900000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x0 0xfe900000 0x1000>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		dmac0: dma at c1128000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x0 0xc1128000 0x1000>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		gpio0: gpio at fd400000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd400000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio1: gpio at fd410000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd410000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio2: gpio at fd420000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd420000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio3: gpio at fd430000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd430000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		gpio4: gpio at fd440000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd440000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio5: gpio at fd450000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd450000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio6: gpio at fd460000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd460000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio7: gpio at fd470000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd470000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio8: gpio at fd480000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd480000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio9: gpio at fd490000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd490000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio10: gpio at fd4a0000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd4a0000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio11: gpio at fd4b0000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd4b0000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		gpio12: gpio at fd4c0000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd4c0000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio13: gpio at fd4d0000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd4d0000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio14: gpio at fd4e0000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd4e0000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio15: gpio at fd4f0000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd4f0000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio16: gpio at fd500000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd500000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio17: gpio at fd510000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd510000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+	};
+};
-- 
1.7.9.5



From huangtao at rock-chips.com  Tue May 31 18:58:08 2016
From: huangtao at rock-chips.com (Huang, Tao)
Date: Wed, 1 Jun 2016 09:58:08 +0800
Subject: [PATCH 4/5] clocksource: rockchip: add support for rk3399 SoC
In-Reply-To: <574D9A66.4090209@linaro.org>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
 <1464169802-6033-5-git-send-email-wxt@rock-chips.com>
 <574CCCB4.1030001@linaro.org> <574D95AF.2020905@rock-chips.com>
 <574D9A66.4090209@linaro.org>
Message-ID: <574E4130.8090600@rock-chips.com>

Hi Daniel:
On 2016?05?31? 22:06, Daniel Lezcano wrote:
>>
>> @@ -46,15 +48,20 @@ static inline void __iomem *rk_base(struct
>> clock_event_device *ce)
>>   	return rk_timer(ce)->base;
>>   }
>>
>> +static inline void __iomem *rk_ctrl(struct clock_event_device *ce)
>> +{
>> +	return rk_timer(ce)->base + rk_timer(ce)->ctrl;
> 
> You can do a small optimization by pre-computing 'ctrl' at init time, so 
> no need to do this addition each time.

I understand what you mean, please see comment below.
And even we use ctrl as pointer, we still will get addition LDR other
then ADD.
This is disassemble code before:
   0:	f9408021 	ldr	x1, [x1,#256]
   4:	52800003 	mov	w3, #0x0
   8:	91004022 	add	x2, x1, #0x10
   c:	b9000043 	str	w3, [x2]
This is disassemble code after change:
   0:	52800003 	mov	w3, #0x0
   4:	f9408422 	ldr	x2, [x1,#264]
   8:	b9000043 	str	w3, [x2]
   c:	f9408021 	ldr	x1, [x1,#256]
Of course we can assume cache hit.

> 
>> +}
>> +
>>   static inline void rk_timer_disable(struct clock_event_device *ce)
>>   {
>> -	writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_CONTROL_REG);
>> +	writel_relaxed(TIMER_DISABLE, rk_ctrl(ce));
>>   }
>>
>>   static inline void rk_timer_enable(struct clock_event_device *ce, u32
>> flags)
>>   {
>>   	writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags,
>> -		       rk_base(ce) + TIMER_CONTROL_REG);
>> +		       rk_ctrl(ce));
>>   }
>>
>>   static void rk_timer_update_counter(unsigned long cycles,
>> @@ -179,4 +186,19 @@ out_unmap:
>>   	iounmap(bc_timer.base);
>>   }
>>
>> -CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init);
>> +static void __init rk3288_timer_init(struct device_node *np)
>> +{
>> +	bc_timer.ctrl = TIMER_CONTROL_REG3288;
>> +	rk_timer_init(np);
> 
> 	rk_timer_init(np);
> 	bc_timer.ctrl = bc_timer.base + TIMER_CONTROL_REG3288;

No. It's not such simple. You will access null pointer when
rk_timer_init, if we keep rk_timer_disable call in init or after
request_irq/clockevents_config_and_register and interrupt happen
immediately.

So the code maybe:
static void __init rk3288_timer_init(struct device_node *np)
{
	bc_timer.base = of_iomap(np, 0);
	if (!bc_timer.base) {
		pr_err("Failed to get base address for '%s'\n", TIMER_NAME);
		return;
	}
	bc_timer.ctrl = bc_timer.base + TIMER_CONTROL_REG3288;
	rk_imter_init(np); // of course remove of_iomap from init.

Is this what you want?



From wens at csie.org  Tue May 31 19:03:42 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed, 1 Jun 2016 10:03:42 +0800
Subject: [PATCH resend v2 1/6] regulator: axp20x: support AXP809 variant
In-Reply-To: <20160531173647.GJ29837@sirena.org.uk>
References: <1464711804-19256-1-git-send-email-wens@csie.org>
 <1464711804-19256-2-git-send-email-wens@csie.org>
 <20160531173647.GJ29837@sirena.org.uk>
Message-ID: <CAGb2v67eVjNnON1pAPKMSMgq83sk6u7Q53qDs0dTEbhyTAR_gA@mail.gmail.com>

On Wed, Jun 1, 2016 at 1:36 AM, Mark Brown <broonie at kernel.org> wrote:
> On Wed, Jun 01, 2016 at 12:23:19AM +0800, Chen-Yu Tsai wrote:
>> The X-Powers AXP809 PMIC has a similar set of regulators as the AXP221,
>> though a few LDOs were removed, and a new switch output added. Like the
>> AXP221, AXP809 also has DC1SW and DC5LDO, which are internally chained
>> to DCDC1 and DCDC5, respectively.
>>
>> Add support for this new variant. Also remove the "axp22x_" prefix from
>> DC1SW/DC5LDO supply handling code, as the AXP809 uses it as well.
>>
>> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
>> ---
>
> Please preserve tags when people review things.  Why wasn't this applied
> when I originally reviewed it?

The mfd patches this one depended on were pushed around a week before
the merge window, about a month after you reviewed, merged, then backed
out this patch. There was no immutable branch either.

I thought it best to wait a cycle instead of rushing in a patch at the
last minute.

Regards
ChenYu


From huangtao at rock-chips.com  Tue May 31 19:30:36 2016
From: huangtao at rock-chips.com (Huang, Tao)
Date: Wed, 1 Jun 2016 10:30:36 +0800
Subject: [PATCH 2/5] clocksource: rockchip: remove unnecessary clear irq
 before request_irq
In-Reply-To: <CAD=FV=U5zqU0CMeg1dDTYHrRqWAxTQO_xk2T7p09GJuj-Fn9Gw@mail.gmail.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
 <1464169802-6033-3-git-send-email-wxt@rock-chips.com>
 <574CC839.60608@linaro.org>
 <CAD=FV=U5zqU0CMeg1dDTYHrRqWAxTQO_xk2T7p09GJuj-Fn9Gw@mail.gmail.com>
Message-ID: <574E48CC.1040004@rock-chips.com>

Hi Doug:
On 2016?06?01? 01:03, Doug Anderson wrote:
> Hi,
> 
> On Mon, May 30, 2016 at 4:09 PM, Daniel Lezcano
> <daniel.lezcano at linaro.org> wrote:
>> On 05/25/2016 11:49 AM, Caesar Wang wrote:
>>>
>>> From: Huang Tao <huangtao at rock-chips.com>
>>>
>>> rk_timer_interrupt_clear and rk_timer_disable is unnecessary before
>>> request_irq. Timer should keep disabled before booting Linux.
>>
>>
>> That's true in the perfect world :/ Some version has u-boot letting the
>> timer with irq enabled, therefore as soon as request_irq is done, an irq
>> fires and leads to a kernel panic.
>>
>> On the other side, this timer is not used on the other rockchip version than
>> rk3399 because of no need of a broadcast timer, so removing these two lines
>> may be acceptable.
>>
>> Can try the changes with another board, eg rk3288 (and forcing to use this
>> timer). Can you do the test and confirm it does not break with different
>> version of u-boot ?
> 
> Actually, I'm not even sure that's true in a perfect world.  ;)  There
> are two main problems that might be lurking here:
> 
> 1. On exynos5 devices I've worked with, the private timer (MCT)
> actually shared the same physical counter with the ARM Architected
> Timer.  IIRC stopping or resetting the MCT had the effect of stopping
> / resetting the Arch Timer.  Is it the same for you?  As I understand
> it the Arch Timer isn't supposed to ever be stopped or reset.  If
> firmware left the timer stopped and the kernel happened to be compiled
> without support for the Rockchip timer (but had the Arch Timers) then
> things would be very broken.  Also the early kernel boot might be
> broken if the Arch Timer inits before the Rockchip timer.
> 
> NOTE: If your timer and the Arch Timer are totally separate then point
> #1 is not important.

We never use the timer which provide clock source of arch timer as
clockevent timer. If we do such stupid thing, when rk timer disabled,
the arch timer will stop too. Generally, we use this special timer as
clocksouce or never touch it again when it is running.

> 
> 
> 2. Historically in Chrome OS there's been an unofficial agreement that
> the firmware would start its high speed timer as soon as possible at
> bootup and that this could be used to (roughly) measure the time
> between the start of firmware and the start of the kernel.  That means
> that the kernel was expecting the timer to actually be running when it
> started up.  Yup, this is a bit of a hack and I'm not sure it's
> terribly well documented, but it does provide a reason that firmware
> might have left the timer running.

Why you chose the timer shared with Linux kernel, there are so many
timer? I think loader should do the right thing, uninit the resources
when it boot the kernel. I believe this code is lagacy from very old
chip such as rk2908 which is Cortex-A8. There are not arch timer, so the
loader may keep the timer running when enter kernel. Any way, if we
adopt the code suggested by Daniel, it is safe to keep the code.



From dianders at chromium.org  Tue May 31 19:36:55 2016
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 31 May 2016 19:36:55 -0700
Subject: [PATCH 2/5] clocksource: rockchip: remove unnecessary clear irq
 before request_irq
In-Reply-To: <574E48CC.1040004@rock-chips.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
 <1464169802-6033-3-git-send-email-wxt@rock-chips.com>
 <574CC839.60608@linaro.org>
 <CAD=FV=U5zqU0CMeg1dDTYHrRqWAxTQO_xk2T7p09GJuj-Fn9Gw@mail.gmail.com>
 <574E48CC.1040004@rock-chips.com>
Message-ID: <CAD=FV=WA6OaOTM07+qxDJOW_TMsG06eAYwq5p5L_hw7PKd5MwA@mail.gmail.com>

Hi,

On Tue, May 31, 2016 at 7:30 PM, Huang, Tao <huangtao at rock-chips.com> wrote:
>> Actually, I'm not even sure that's true in a perfect world.  ;)  There
>> are two main problems that might be lurking here:
>>
>> 1. On exynos5 devices I've worked with, the private timer (MCT)
>> actually shared the same physical counter with the ARM Architected
>> Timer.  IIRC stopping or resetting the MCT had the effect of stopping
>> / resetting the Arch Timer.  Is it the same for you?  As I understand
>> it the Arch Timer isn't supposed to ever be stopped or reset.  If
>> firmware left the timer stopped and the kernel happened to be compiled
>> without support for the Rockchip timer (but had the Arch Timers) then
>> things would be very broken.  Also the early kernel boot might be
>> broken if the Arch Timer inits before the Rockchip timer.
>>
>> NOTE: If your timer and the Arch Timer are totally separate then point
>> #1 is not important.
>
> We never use the timer which provide clock source of arch timer as
> clockevent timer. If we do such stupid thing, when rk timer disabled,
> the arch timer will stop too. Generally, we use this special timer as
> clocksouce or never touch it again when it is running.

Ah, OK.  :)  I didn't go through and review / test the code.  I just
wanted to make sure we weren't going to run into the same bug I
remember running into before.  ;)


>> 2. Historically in Chrome OS there's been an unofficial agreement that
>> the firmware would start its high speed timer as soon as possible at
>> bootup and that this could be used to (roughly) measure the time
>> between the start of firmware and the start of the kernel.  That means
>> that the kernel was expecting the timer to actually be running when it
>> started up.  Yup, this is a bit of a hack and I'm not sure it's
>> terribly well documented, but it does provide a reason that firmware
>> might have left the timer running.
>
> Why you chose the timer shared with Linux kernel, there are so many
> timer? I think loader should do the right thing, uninit the resources
> when it boot the kernel. I believe this code is lagacy from very old
> chip such as rk2908 which is Cortex-A8. There are not arch timer, so the
> loader may keep the timer running when enter kernel. Any way, if we
> adopt the code suggested by Daniel, it is safe to keep the code.

If this is a separate / distinct timer than the main clocksource
timer, then you can ignore my comments.  ;)

...but obviously the comments from Daniel are much more important to
address and it sounds like you're all set for doing that.  :)

-Doug


From shawn.lin at rock-chips.com  Tue May 31 19:36:51 2016
From: shawn.lin at rock-chips.com (Shawn Lin)
Date: Wed, 1 Jun 2016 10:36:51 +0800
Subject: [PATCH 1/3] mmc: fix mmc mode selection for HS-DDR and higher
In-Reply-To: <1464505484-3661-2-git-send-email-wens@csie.org>
References: <1464505484-3661-1-git-send-email-wens@csie.org>
 <1464505484-3661-2-git-send-email-wens@csie.org>
Message-ID: <472b6b94-a773-e4cd-07c0-4b184a840f87@rock-chips.com>

On 2016/5/29 15:04, Chen-Yu Tsai wrote:
> When IS_ERR_VALUE was removed from the mmc core code, it was replaced
> with a simple not-zero check. This does not work, as the value checked
> is the return value for mmc_select_bus_width, which returns the set
> bit width on success. This made eMMC modes higher than HS-DDR unusable.
>
> Fix this by checking for a positive return value instead.

Reviewed-by: Shawn Lin <shawn.lin at rock-chips.com>

>
> Fixes: 287980e49ffc ("remove lots of IS_ERR_VALUE abuses")
> Cc: Arnd Bergmann <arnd at arndb.de>
> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
> ---
>  drivers/mmc/core/mmc.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index c984321d1881..aafb73d080ca 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -1276,7 +1276,7 @@ static int mmc_select_hs200(struct mmc_card *card)
>  	 * switch to HS200 mode if bus width is set successfully.
>  	 */
>  	err = mmc_select_bus_width(card);
> -	if (!err) {
> +	if (err > 0) {
>  		val = EXT_CSD_TIMING_HS200 |
>  		      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
>  		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> @@ -1583,7 +1583,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
>  	} else if (mmc_card_hs(card)) {
>  		/* Select the desired bus width optionally */
>  		err = mmc_select_bus_width(card);
> -		if (!err) {
> +		if (err > 0) {
>  			err = mmc_select_hs_ddr(card);
>  			if (err)
>  				goto free_card;
>


-- 
Best Regards
Shawn Lin



From shijie.huang at arm.com  Tue May 31 19:39:42 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Wed, 1 Jun 2016 10:39:42 +0800
Subject: [PATCH 2/2] arm64: mm: dump: log span level
In-Reply-To: <1464702542-24394-3-git-send-email-mark.rutland@arm.com>
References: <1464702542-24394-1-git-send-email-mark.rutland@arm.com>
 <1464702542-24394-3-git-send-email-mark.rutland@arm.com>
Message-ID: <20160601023940.GA14411@sha-win-210.asiapac.arm.com>

On Tue, May 31, 2016 at 02:49:02PM +0100, Mark Rutland wrote:
> The page table dump code logs spans of entries at the same level
> (pgd/pud/pmd/pte) which have the same attributes. While we log the
> (decoded) attributes, we don't log the level, which leaves the output
> ambiguous and/or confusing in some cases.
>
> For example:
>
> 0xffff800800000000-0xffff800980000000           6G       RW NX SHD AF        BLK UXN MEM/NORMAL
>
> If using 4K pages, this may describe a span of 6 1G block entries at the
> PGD/PUD level, or 3072 2M block entries at the PMD level.
>
> This patch adds the page table level to each output line, removing this
> ambiguity. For the example above, this will produce:
>
> 0xffffffc800000000-0xffffffc980000000           6G PUD       RW NX SHD AF        BLK UXN MEM/NORMAL
>
> When 3 level tables are in use, and we use the asm-generic/nopud.h
> definitions, the dump code treats each entry in the PGD as a 1 element
> table at the PUD level, and logs spans as being PUDs, which can be
> confusing. To counteract this, the "PUD" mnemonic is replaced with "PGD"
> when CONFIG_PGTABLE_LEVELS <= 3. Likewise for "PMD" when
> CONFIG_PGTABLE_LEVELS <= 2.
>
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Huang Shijie <shijie.huang at arm.com>
Tested-by: Huang Shijie <shijie.huang at arm.com>

thanks
Huang Shijie
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.



From luoyi.ly at gmail.com  Tue May 31 19:40:18 2016
From: luoyi.ly at gmail.com (luoyi)
Date: Wed, 1 Jun 2016 10:40:18 +0800
Subject: [linux-sunxi] Re: [PATCH] ARM: dts: sun7i: Add dts file for
 Bananapi M1 Plus board
In-Reply-To: <20160531170957.GM4908@lukather>
References: <20160530123013.11575-1-luoyi.ly@gmail.com>
 <20160530194340.GE4908@lukather> <574CA1ED.8050007@web.de>
 <20160531170957.GM4908@lukather>
Message-ID: <CAFfxPQss6M4dR_=fPCamZ08A3gPyC0523f+qFTYm1e16O4t_KQ@mail.gmail.com>

This is the new version of the patch.  and I think maybe every board
should have their own dtb files. and we can you some cpp  macro tricks
to merge their coressponding dts file.

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index e06a5ab..fde407f 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -685,6 +685,7 @@ dtb-$(CONFIG_MACH_SUN6I) += \
     sun6i-a31s-yones-toptech-bs1078-v2.dtb
 dtb-$(CONFIG_MACH_SUN7I) += \
     sun7i-a20-bananapi.dtb \
+    sun7i-a20-bananapi-m1-plus.dtb \
     sun7i-a20-bananapro.dtb \
     sun7i-a20-cubieboard2.dtb \
     sun7i-a20-cubietruck.dtb \
diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
new file mode 100644
index 0000000..548ed31
--- /dev/null
+++ b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2016 Luo Yi <luoyi.ly at gmail.com>
+ *
+ * Thanks to the original work by Hans de Goede <hdegoede at redhat.com>
+ *
+ * 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 "sun7i-a20.dtsi"
+#include "sunxi-common-regulators.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+    model = "Banana Pi BPI-M1-Plus";
+    compatible = "sinovoip,bpi-m1-plus", "allwinner,sun7i-a20";
+
+    aliases {
+        serial0 = &uart0;
+    };
+
+    chosen {
+        stdout-path = "serial0:115200n8";
+    };
+
+    leds {
+        compatible = "gpio-leds";
+        pinctrl-names = "default";
+        pinctrl-0 = <&led_pins_bananapi>;
+
+        green {
+            label = "bananapi:green:usr";
+            gpios = <&pio 7 24 GPIO_ACTIVE_HIGH>;
+        };
+
+        red {
+            label = "bananapi:red:usr";
+            gpios = <&pio 7 25 GPIO_ACTIVE_HIGH>;
+            linux,default-trigger = "default-on";
+        };
+
+    };
+
+    mmc3_pwrseq: mmc3_pwrseq {
+        compatible = "mmc-pwrseq-simple";
+        pinctrl-names = "default";
+        pinctrl-0 = <&mmc3_pwrseq_pin_bananapim1plus>;
+        reset-gpios = <&pio 7 22 GPIO_ACTIVE_LOW>; /* PH22 WL-PMU-EN */
+    };
+
+    reg_gmac_3v3: gmac-3v3 {
+        compatible = "regulator-fixed";
+        pinctrl-names = "default";
+        pinctrl-0 = <&gmac_power_pin_bananapi>;
+        regulator-name = "gmac-3v3";
+        regulator-min-microvolt = <3300000>;
+        regulator-max-microvolt = <3300000>;
+        startup-delay-us = <100000>;
+        enable-active-high;
+        gpio = <&pio 7 23 GPIO_ACTIVE_HIGH>;
+    };
+
+};
+
+&ahci {
+    status = "okay";
+};
+
+&codec {
+    status = "okay";
+};
+
+&ehci0 {
+    status = "okay";
+};
+
+&ehci1 {
+    status = "okay";
+};
+
+&gmac {
+    pinctrl-names = "default";
+    pinctrl-0 = <&gmac_pins_rgmii_a>;
+    phy = <&phy1>;
+    phy-mode = "rgmii";
+    phy-supply = <&reg_gmac_3v3>;
+    status = "okay";
+
+    phy1: ethernet-phy at 1 {
+        reg = <1>;
+    };
+};
+
+&i2c0 {
+    pinctrl-names = "default";
+    pinctrl-0 = <&i2c0_pins_a>;
+    status = "okay";
+
+    axp209: pmic at 34 {
+        compatible = "x-powers,axp209";
+        reg = <0x34>;
+        interrupt-parent = <&nmi_intc>;
+        interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+        interrupt-controller;
+        #interrupt-cells = <1>;
+    };
+};
+
+&ir0 {
+    pinctrl-names = "default";
+    pinctrl-0 = <&ir0_rx_pins_a>;
+    status = "okay";
+};
+
+&mmc0 {
+    pinctrl-names = "default";
+    pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bananapi>;
+    vmmc-supply = <&reg_vcc3v3>;
+    bus-width = <4>;
+    cd-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */
+    cd-inverted;
+    status = "okay";
+};
+
+&mmc3 {
+
+    #address-cells = <1>;
+    #size-cells = <0>;
+    pinctrl-names = "default";
+    pinctrl-0 = <&mmc3_pins_a>;
+    vmmc-supply = <&reg_vcc3v3>;
+    mmc-pwrseq = <&mmc3_pwrseq>;
+    bus-width = <4>;
+    non-removable;
+    enable-sdio-wakeup;
+    status = "okay";
+
+    brcmf: bcrmf at 1 {
+        reg = <1>;
+        compatible = "brcm,bcm4329-fmac";
+        interrupt-parent = <&pio>;
+        interrupts = <7 15 IRQ_TYPE_LEVEL_LOW>;
+        interrupt-names = "host-wake";
+    };
+
+};
+
+&mmc3_pins_a {
+    /* AP6210 requires pull-up */
+    allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+};
+
+&ohci0 {
+    status = "okay";
+};
+
+&ohci1 {
+    status = "okay";
+};
+
+&pio {
+    gmac_power_pin_bananapi: gmac_power_pin at 0 {
+        allwinner,pins = "PH23";
+        allwinner,function = "gpio_out";
+        allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+        allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+    };
+
+    led_pins_bananapi: led_pins at 0 {
+        allwinner,pins = "PH24", "PG2";
+        allwinner,function = "gpio_out";
+        allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+        allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+    };
+
+    mmc0_cd_pin_bananapi: mmc0_cd_pin at 0 {
+        allwinner,pins = "PH10";
+        allwinner,function = "gpio_in";
+        allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+        allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+    };
+
+    mmc3_pwrseq_pin_bananapim1plus: mmc3_pwrseq_pin at 0 {
+        allwinner,pins = "PH22";
+        allwinner,function = "gpio_out";
+        allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+        allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+    };
+
+    usb1_vbus_pin_bananapi: usb1_vbus_pin at 0 {
+        allwinner,pins = "PH0";
+        allwinner,function = "gpio_out";
+        allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+        allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+    };
+
+    usb2_vbus_pin_bananapi: usb2_vbus_pin at 0 {
+        allwinner,pins = "PH1";
+        allwinner,function = "gpio_out";
+        allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+        allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+    };
+
+};
+
+&reg_usb1_vbus {
+    pinctrl-0 = <&usb1_vbus_pin_bananapi>;
+    gpio = <&pio 7 0 GPIO_ACTIVE_HIGH>; /* PH0 */
+    status = "okay";
+};
+
+&reg_usb2_vbus {
+    pinctrl-0 = <&usb2_vbus_pin_bananapi>;
+    gpio = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
+    status = "okay";
+};
+
+&uart0 {
+    pinctrl-names = "default";
+    pinctrl-0 = <&uart0_pins_a>;
+    status = "okay";
+};
+
+&usbphy {
+    usb1_vbus-supply = <&reg_usb1_vbus>;
+    usb2_vbus-supply = <&reg_usb2_vbus>;
+    status = "okay";
+};

2016-06-01 1:09 GMT+08:00 Maxime Ripard <maxime.ripard at free-electrons.com>:
> On Mon, May 30, 2016 at 10:26:21PM +0200, Bernhard Nortmann wrote:
>> Am 30.05.2016 um 21:43 schrieb Maxime Ripard:
>> >Hi,
>> >
>> >On Mon, May 30, 2016 at 08:30:13PM +0800, luoyi.ly at gmail.com wrote:
>> >>From: luoyi <luoyi.ly at gmail.com>
>> >>
>> >>Add support for the Bananapi M1 Plus A20 development board from sinovoip.com.cn .
>> >>This board features 1G RAM, 2 USB A receptacles, 1 micro USB receptacle for
>> >>OTG, 1 micro USB receptacle for power, HDMI, sata, Gbit ethernet, ir receiver,
>> >>3.5 mm jack for stero sound out, on board microphone, 40 gpio pins and sdio wifi.
>> >What is the difference between the M1+ and the M1?
>>
>> The M1+ is an updated version of the original Banana Pi. If you're
>> interested in the details, have a look at
>> http://linux-sunxi.org/Banana_Pi#Variants .  "BPi-M1+" is SinoVoip's
>> counterpart of LeMaker's "Banana Pro", for which a .dts already
>> exists. Judging from .fex files, only a single pin assignment seems
>> to differ between the two (audio_pa_ctrl, PH26 vs. PH15).
>
> Gee, that's confusing :)
>
> I guess we should just include the banana pro DTB and change that pin
> (and the i2s pins Luo was mentionning).
>
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com


From wens at csie.org  Tue May 31 19:45:51 2016
From: wens at csie.org (Chen-Yu Tsai)
Date: Wed, 1 Jun 2016 10:45:51 +0800
Subject: [PATCH resend v2 5/6] ARM: dts: sun9i: a80-optimus: Disable dummy
 regulators vcc3v0, vcc3v3, vcc5v0
In-Reply-To: <20160531190113.GO4908@lukather>
References: <1464711804-19256-1-git-send-email-wens@csie.org>
 <1464711804-19256-6-git-send-email-wens@csie.org>
 <20160531190113.GO4908@lukather>
Message-ID: <CAGb2v65_kAtrOW_G51Tn1urroXVuo=AqzX66zm7Ewsyw_AJdvA@mail.gmail.com>

On Wed, Jun 1, 2016 at 3:01 AM, Maxime Ripard
<maxime.ripard at free-electrons.com> wrote:
> Hi,
>
> On Wed, Jun 01, 2016 at 12:23:23AM +0800, Chen-Yu Tsai wrote:
>> These 3 regulators are provided in sunxi-common-regulators.dtsi.
>> 3.0V/3.3V and 5.0V are commonly used voltages in Allwinner devices.
>> These dummy regulators provide a stand-in when bindings that require
>> one, but the real regulator is not supported yet.
>>
>> Since these are no longer needed, we can disable them.
>>
>> Signed-off-by: Chen-Yu Tsai <wens at csie.org>
>> ---
>>  arch/arm/boot/dts/sun9i-a80-optimus.dts | 12 ++++++++++++
>>  1 file changed, 12 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts
>> index 6cfc02194035..991337d1d6f1 100644
>> --- a/arch/arm/boot/dts/sun9i-a80-optimus.dts
>> +++ b/arch/arm/boot/dts/sun9i-a80-optimus.dts
>> @@ -322,6 +322,18 @@
>>
>>  #include "axp809.dtsi"
>>
>> +&reg_vcc3v0 {
>> +     status = "disabled";
>> +};
>> +
>> +&reg_vcc3v3 {
>> +     status = "disabled";
>> +};
>> +
>> +&reg_vcc5v0 {
>> +     status = "disabled";
>> +};
>> +
>
> Why not remove the include entirely?

reg_usb1_vbus is still used. Or I could just copy it and
get rid of the include.

ChenYu


From shijie.huang at arm.com  Tue May 31 20:01:35 2016
From: shijie.huang at arm.com (Huang Shijie)
Date: Wed, 1 Jun 2016 11:01:35 +0800
Subject: [PATCH 1/2] arm64: mm: dump: make page table dumping reusable
In-Reply-To: <1464702542-24394-2-git-send-email-mark.rutland@arm.com>
References: <1464702542-24394-1-git-send-email-mark.rutland@arm.com>
 <1464702542-24394-2-git-send-email-mark.rutland@arm.com>
Message-ID: <20160601030133.GB14411@sha-win-210.asiapac.arm.com>

On Tue, May 31, 2016 at 02:49:01PM +0100, Mark Rutland wrote:
> For debugging purposes, it would be nice if we could export page tables
> other than the swapper_pg_dir to userspace. To enable this, this patch
> refactors the arm64 page table dumping code such that multiple tables
> may be registered with the framework, and exported under debugfs.
>
> Signed-off-by: Mark Rutland <mark.rutland at arm.com>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
> Cc: Catalin Marinas <catalin.marinas at arm.com>
> Cc: Laura Abbott <labbott at fedoraproject.org>
> Cc: Will Deacon <will.deacon at arm.com>
> ---
>  arch/arm64/include/asm/ptdump.h | 44 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm64/mm/dump.c            | 32 +++++++++++++++++++-----------
>  2 files changed, 64 insertions(+), 12 deletions(-)
>  create mode 100644 arch/arm64/include/asm/ptdump.h
>
> diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
> new file mode 100644
> index 0000000..07b8ed0
> --- /dev/null
> +++ b/arch/arm64/include/asm/ptdump.h
> @@ -0,0 +1,44 @@
> +/*
> + * Copyright (C) 2014 ARM 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.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef __ASM_PTDUMP_H
> +#define __ASM_PTDUMP_H
> +
> +#ifdef CONFIG_ARM64_PTDUMP
> +
> +#include <linux/mm_types.h>
> +
> +struct addr_marker {
> +     unsigned long start_address;
> +     char *name;
> +};
> +
> +struct ptdump_info {
> +     struct mm_struct                *mm;
> +     const struct addr_marker        *markers;
> +     unsigned long                   base_addr;
> +     unsigned long                   max_addr;
> +};
> +
> +int ptdump_register(struct ptdump_info *info, const char *name);
Since we export this to other page tables,  I guess the @base_addr in the ptdump_info{} may not equal to
the VA_START. But the current dump.c does _NOT_ use the @start address been
passed in, it use the 0 as the start address for the walk_pgd/walk_pud/walk_pmd/walk_pte.
It is wrong in logic, since the start address is VA_START, the code gets
the right result coincidentally.

thanks
Huang Shijie
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.



From yangyingliang at huawei.com  Tue May 31 20:05:58 2016
From: yangyingliang at huawei.com (Yang Yingliang)
Date: Wed, 1 Jun 2016 11:05:58 +0800
Subject: [RFC PATCH 0/4] arm64: vdso: check whether the params is invalid
 address
Message-ID: <1464750362-14188-1-git-send-email-yangyingliang@huawei.com>

The params of gettimeofday(), clock_gettime() and clock_getres()
is not checked. This will cause segment faults when the address is
invalid. 
E.g. gettimeofday(-1, -1);
     clock_gettime(0, -1);
     clock_getres(0, -1);
This patchset add a macro and use it to check the validation of these
pointer params.


Yang Yingliang (4):
  arm64: vdso: introdce a macro for checking the address
  arm64: vdso: check whether the params of gettimeofday() is valid
  arm64: vdso: check whether the tp pointer is valid in clock_gettime()
  arm64: vdso: check whether the res pointer is valid in clock_getres()

 arch/arm64/kernel/asm-offsets.c       |  3 ++
 arch/arm64/kernel/vdso/gettimeofday.S | 71 +++++++++++++++++++++++++++++------
 2 files changed, 62 insertions(+), 12 deletions(-)

-- 
2.5.0




From yangyingliang at huawei.com  Tue May 31 20:06:01 2016
From: yangyingliang at huawei.com (Yang Yingliang)
Date: Wed, 1 Jun 2016 11:06:01 +0800
Subject: [RFC PATCH 3/4] arm64: vdso: check whether the tp pointer is valid in
 clock_gettime()
In-Reply-To: <1464750362-14188-1-git-send-email-yangyingliang@huawei.com>
References: <1464750362-14188-1-git-send-email-yangyingliang@huawei.com>
Message-ID: <1464750362-14188-4-git-send-email-yangyingliang@huawei.com>

Use RANGE_OK to check whether the tp pointer is valid. Returns
-EINVAL if the tp pointer is NULL, returns -EFAULT if it's invalid,
otherwise return 0.

Signed-off-by: Yang Yingliang <yangyingliang at huawei.com>
---
 arch/arm64/kernel/vdso/gettimeofday.S | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index 43ec321..1e377ac 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -118,6 +118,9 @@ ENDPROC(__kernel_gettimeofday)
 /* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */
 ENTRY(__kernel_clock_gettime)
 	.cfi_startproc
+	cbz	x1, 7f
+	RANGE_OK(1, #TSPEC_SZ)
+	cbz     x4, 8f
 	cmp	w0, #CLOCK_REALTIME
 	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
 	b.ne	2f
@@ -128,7 +131,7 @@ ENTRY(__kernel_clock_gettime)
 	/* Get kernel timespec. */
 	adr	vdso_data, _vdso_data
 1:	seqcnt_acquire
-	cbnz	use_syscall, 7f
+	cbnz	use_syscall, 9f
 
 	bl	__do_get_tspec
 	seqcnt_check w9, 1b
@@ -148,7 +151,7 @@ ENTRY(__kernel_clock_gettime)
 2:
 	cmp	w0, #CLOCK_REALTIME_COARSE
 	ccmp	w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne
-	b.ne	8f
+	b.ne	10f
 
 	/* xtime_coarse_nsec is already right-shifted */
 	mov	x12, #0
@@ -192,9 +195,15 @@ ENTRY(__kernel_clock_gettime)
 	stp	x10, x11, [x1, #TSPEC_TV_SEC]
 	mov	x0, xzr
 	ret
-7:
+7:	/* tp is NULL */
+	mov	x0, #-EINVAL
+	ret
+8:	/* tp is invalid */
+	mov	x0, #-EFAULT
+	ret
+9:
 	mov	x30, x2
-8:	/* Syscall fallback. */
+10:	/* Syscall fallback. */
 	mov	x8, #__NR_clock_gettime
 	svc	#0
 	ret
-- 
2.5.0




From yangyingliang at huawei.com  Tue May 31 20:05:59 2016
From: yangyingliang at huawei.com (Yang Yingliang)
Date: Wed, 1 Jun 2016 11:05:59 +0800
Subject: [RFC PATCH 1/4] arm64: vdso: introdce a macro for checking the address
In-Reply-To: <1464750362-14188-1-git-send-email-yangyingliang@huawei.com>
References: <1464750362-14188-1-git-send-email-yangyingliang@huawei.com>
Message-ID: <1464750362-14188-2-git-send-email-yangyingliang@huawei.com>

Add a RANGE_OK macro for validation checking of the
address given by user.

Signed-off-by: Yang Yingliang <yangyingliang at huawei.com>
---
 arch/arm64/kernel/asm-offsets.c       |  3 +++
 arch/arm64/kernel/vdso/gettimeofday.S | 21 +++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 574081f..b72c2df 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -98,11 +98,14 @@ int main(void)
   BLANK();
   DEFINE(TVAL_TV_SEC,		offsetof(struct timeval, tv_sec));
   DEFINE(TVAL_TV_USEC,		offsetof(struct timeval, tv_usec));
+  DEFINE(TVAL_SZ,		sizeof(struct timeval));
   DEFINE(TSPEC_TV_SEC,		offsetof(struct timespec, tv_sec));
   DEFINE(TSPEC_TV_NSEC,		offsetof(struct timespec, tv_nsec));
+  DEFINE(TSPEC_SZ,		sizeof(struct timespec));
   BLANK();
   DEFINE(TZ_MINWEST,		offsetof(struct timezone, tz_minuteswest));
   DEFINE(TZ_DSTTIME,		offsetof(struct timezone, tz_dsttime));
+  DEFINE(TZ_SZ,			sizeof(struct timezone));
   BLANK();
 #ifdef CONFIG_KVM_ARM_HOST
   DEFINE(VCPU_CONTEXT,		offsetof(struct kvm_vcpu, arch.ctxt));
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index efa79e8..05ccaca 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -21,10 +21,31 @@
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/unistd.h>
+#include <asm/memory.h>
 
 #define NSEC_PER_SEC_LO16	0xca00
 #define NSEC_PER_SEC_HI16	0x3b9a
 
+#define USER_DS		TASK_SIZE_64
+/*
+ * Test whether a block of memory is a valid user space address.
+ * Returns 1 if the range is valid, 0 otherwise.
+ *
+ * This is equivalent to the following test:
+ * (u65)addr + (u65)size <= USER_DS
+ *
+ * This needs 65-bit arithmetic.
+ *
+ * x##n - addr
+ * sz - size
+ * x3 - USER_DS
+ * x4 - return value
+ */
+#define RANGE_OK(n, sz)	mov	x3, #USER_DS;		\
+			adds	x4, x##n, sz;		\
+			ccmp	x4, x3, #0x2, cc;	\
+			cset	x4, ls
+
 vdso_data	.req	x6
 use_syscall	.req	w7
 seqcnt		.req	w8
-- 
2.5.0




From yangyingliang at huawei.com  Tue May 31 20:06:02 2016
From: yangyingliang at huawei.com (Yang Yingliang)
Date: Wed, 1 Jun 2016 11:06:02 +0800
Subject: [RFC PATCH 4/4] arm64: vdso: check whether the res pointer is valid
 in clock_getres()
In-Reply-To: <1464750362-14188-1-git-send-email-yangyingliang@huawei.com>
References: <1464750362-14188-1-git-send-email-yangyingliang@huawei.com>
Message-ID: <1464750362-14188-5-git-send-email-yangyingliang@huawei.com>

Use RANGE_OK to check whether the res pointer is valid. Returns
-EINVAL if the it's NULL, returns -EFAULT if it's invalid, otherwise
return 0.

Signed-off-by: Yang Yingliang <yangyingliang at huawei.com>
---
 arch/arm64/kernel/vdso/gettimeofday.S | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index 1e377ac..d7e4341 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -217,28 +217,36 @@ ENTRY(__kernel_clock_getres)
 	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
 	b.ne	1f
 
-	ldr	x2, 5f
+	ldr	x2, 6f
 	b	2f
 1:
 	cmp	w0, #CLOCK_REALTIME_COARSE
 	ccmp	w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne
-	b.ne	4f
-	ldr	x2, 6f
+	b.ne	5f
+	ldr	x2, 7f
 2:
 	cbz	w1, 3f
+	RANGE_OK(1, #TSPEC_SZ)
+	cbz	x4, 4f
 	stp	xzr, x2, [x1]
+	mov     w0, wzr
+	ret
 
 3:	/* res == NULL. */
-	mov	w0, wzr
+	mov	x0, #-EINVAL
 	ret
 
-4:	/* Syscall fallback. */
+4:	/* res is invalid. */
+	mov	x0, #-EFAULT
+	ret
+
+5:	/* Syscall fallback. */
 	mov	x8, #__NR_clock_getres
 	svc	#0
 	ret
-5:
-	.quad	CLOCK_REALTIME_RES
 6:
+	.quad	CLOCK_REALTIME_RES
+7:
 	.quad	CLOCK_COARSE_RES
 	.cfi_endproc
 ENDPROC(__kernel_clock_getres)
-- 
2.5.0




From yangyingliang at huawei.com  Tue May 31 20:06:00 2016
From: yangyingliang at huawei.com (Yang Yingliang)
Date: Wed, 1 Jun 2016 11:06:00 +0800
Subject: [RFC PATCH 2/4] arm64: vdso: check whether the params of
 gettimeofday() is valid
In-Reply-To: <1464750362-14188-1-git-send-email-yangyingliang@huawei.com>
References: <1464750362-14188-1-git-send-email-yangyingliang@huawei.com>
Message-ID: <1464750362-14188-3-git-send-email-yangyingliang@huawei.com>

When the params of gettimeofday() is an invalid addr(E.g.
gettimeofday(-1, -1)), it will get segment fault. To avoid
this fault, use RANGE_OK to test whether a block of memory
is valid. Returns -EFAULT if the range is invalid, 0 otherwise.

Signed-off-by: Yang Yingliang <yangyingliang at huawei.com>
---
 arch/arm64/kernel/vdso/gettimeofday.S | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index 05ccaca..43ec321 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -22,6 +22,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 #include <asm/memory.h>
+#include <asm-generic/errno-base.h>
 
 #define NSEC_PER_SEC_LO16	0xca00
 #define NSEC_PER_SEC_HI16	0x3b9a
@@ -78,10 +79,12 @@ ENTRY(__kernel_gettimeofday)
 	/* Acquire the sequence counter and get the timespec. */
 	adr	vdso_data, _vdso_data
 1:	seqcnt_acquire
-	cbnz	use_syscall, 4f
+	cbnz	use_syscall, 5f
 
 	/* If tv is NULL, skip to the timezone code. */
 	cbz	x0, 2f
+	RANGE_OK(0, #TVAL_SZ)
+	cbz	x4, 4f
 	bl	__do_get_tspec
 	seqcnt_check w9, 1b
 
@@ -93,12 +96,18 @@ ENTRY(__kernel_gettimeofday)
 2:
 	/* If tz is NULL, return 0. */
 	cbz	x1, 3f
+	RANGE_OK(1, #TZ_SZ)
+	cbz	x4, 4f
 	ldp	w4, w5, [vdso_data, #VDSO_TZ_MINWEST]
 	stp	w4, w5, [x1, #TZ_MINWEST]
 3:
 	mov	x0, xzr
 	ret	x2
 4:
+	/* tz is invalid */
+	mov	x0, #-EFAULT
+	ret	x2
+5:
 	/* Syscall fallback. */
 	mov	x8, #__NR_gettimeofday
 	svc	#0
-- 
2.5.0




From magnus.damm at gmail.com  Tue May 31 20:17:29 2016
From: magnus.damm at gmail.com (Magnus Damm)
Date: Wed, 1 Jun 2016 12:17:29 +0900
Subject: [RFC 0/4] ARM: dts: r8a7790: lager: use demuxer for I2C
In-Reply-To: <1464665528-11398-1-git-send-email-horms+renesas@verge.net.au>
References: <1464665528-11398-1-git-send-email-horms+renesas@verge.net.au>
Message-ID: <CANqRtoTRRNQGk-gy1NrQhXNB0fzvkHDxwJGxyQHTYAgHUXm9ZA@mail.gmail.com>

Hi Simon,

On Tue, May 31, 2016 at 12:32 PM, Simon Horman
<horms+renesas at verge.net.au> wrote:
> the intention of this series is to extend use of the demuxer for I2C
> on the lager/r8a7790 to cover all I2C IP blocks.
>
> This is based on work by Wolfram Sang.
>
> I have not included GPIO in the demux configuration. This is in keeping
> with the existing usage for IIC0/I2C0.

Thanks for your efforts! Can you please include GPIO support in next
version? This way we should in the future be able to use
distro-kernels out of the box that may only have GPIO bitbang support
enabled.

Cheers,

/ magnus


From wenyou.yang at atmel.com  Tue May 31 21:29:58 2016
From: wenyou.yang at atmel.com (Wenyou Yang)
Date: Wed, 1 Jun 2016 12:29:58 +0800
Subject: [PATCH v2 0/2] ARM: ohci-at91: Add support to forcibly suspend ports
 while sleep
Message-ID: <1464755400-6825-1-git-send-email-wenyou.yang@atmel.com>

To save the power consumption, add a new compatible to support forcibly
suspend the USB PORTA/B/C via OHCI Interrupt Configuration SFR Register.

Changes in v2:
 - Add compatible to support forcibly suspend the ports.
 - Add soc/at91/at91_sfr.h to accommodate the defines.
 - Add error checking for .sfr_regmap.
 - Remove unnecessary regmap_read() statement.
 - Use the new compatible for ohci-node.

Wenyou Yang (2):
  usb: ohci-at91: Forcibly suspend ports while USB suspend
  ARM: at91/dt: sama5d2: Use new compatible for ohci node

 .../devicetree/bindings/usb/atmel-usb.txt          |  5 +-
 arch/arm/boot/dts/sama5d2.dtsi                     |  2 +-
 drivers/usb/host/ohci-at91.c                       | 80 +++++++++++++++++++++-
 include/soc/at91/at91_sfr.h                        | 29 ++++++++
 4 files changed, 112 insertions(+), 4 deletions(-)
 create mode 100644 include/soc/at91/at91_sfr.h

-- 
2.7.4



From wenyou.yang at atmel.com  Tue May 31 21:29:59 2016
From: wenyou.yang at atmel.com (Wenyou Yang)
Date: Wed, 1 Jun 2016 12:29:59 +0800
Subject: [PATCH v2 1/2] usb: ohci-at91: Forcibly suspend ports while USB
 suspend
In-Reply-To: <1464755400-6825-1-git-send-email-wenyou.yang@atmel.com>
References: <1464755400-6825-1-git-send-email-wenyou.yang@atmel.com>
Message-ID: <1464755400-6825-2-git-send-email-wenyou.yang@atmel.com>

In order to the save power consumption, as a workaround, suspend
forcibly the USB PORTA/B/C via set the SUSPEND_A/B/C bits of OHCI
Interrupt Configuration Register in the SFRs while OHCI USB suspend.

This suspend operation must be done before the USB clock is disabled,
resume after the USB clock is enabled.

Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
---

Changes in v2:
 - Add compatible to support forcibly suspend the ports.
 - Add soc/at91/at91_sfr.h to accommodate the defines.
 - Add error checking for .sfr_regmap.
 - Remove unnecessary regmap_read() statement.

 .../devicetree/bindings/usb/atmel-usb.txt          |  5 +-
 drivers/usb/host/ohci-at91.c                       | 80 +++++++++++++++++++++-
 include/soc/at91/at91_sfr.h                        | 29 ++++++++
 3 files changed, 111 insertions(+), 3 deletions(-)
 create mode 100644 include/soc/at91/at91_sfr.h

diff --git a/Documentation/devicetree/bindings/usb/atmel-usb.txt b/Documentation/devicetree/bindings/usb/atmel-usb.txt
index 5883b73..3e3e58a 100644
--- a/Documentation/devicetree/bindings/usb/atmel-usb.txt
+++ b/Documentation/devicetree/bindings/usb/atmel-usb.txt
@@ -3,8 +3,9 @@ Atmel SOC USB controllers
 OHCI
 
 Required properties:
- - compatible: Should be "atmel,at91rm9200-ohci" for USB controllers
-   used in host mode.
+ - compatible: Should be one of the following
+	       "atmel,at91rm9200-ohci" for USB controllers used in host mode.
+	       "atmel,sama5d2-ohci" for SAMA5D2 which can force to suspend.
  - reg: Address and length of the register set for the device
  - interrupts: Should contain ehci interrupt
  - clocks: Should reference the peripheral, host and system clocks
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index d177372..54e8feb 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -21,8 +21,11 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
+#include <soc/at91/at91_sfr.h>
 
 #include "ohci.h"
 
@@ -45,12 +48,18 @@ struct at91_usbh_data {
 	u8 overcurrent_changed[AT91_MAX_USBH_PORTS];
 };
 
+struct ohci_at91_caps {
+	bool suspend_ctrl;
+};
+
 struct ohci_at91_priv {
 	struct clk *iclk;
 	struct clk *fclk;
 	struct clk *hclk;
 	bool clocked;
 	bool wakeup;		/* Saved wake-up state for resume */
+	const struct ohci_at91_caps *caps;
+	struct regmap *sfr_regmap;
 };
 /* interface and function clocks; sometimes also an AHB clock */
 
@@ -132,6 +141,17 @@ static void at91_stop_hc(struct platform_device *pdev)
 
 /*-------------------------------------------------------------------------*/
 
+struct regmap *at91_dt_syscon_sfr(void)
+{
+	struct regmap *regmap;
+
+	regmap = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
+	if (IS_ERR(regmap))
+		regmap = NULL;
+
+	return regmap;
+}
+
 static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
 
 /* configure so an HC device and id are always provided */
@@ -197,6 +217,17 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
 		goto err;
 	}
 
+	ohci_at91->caps = (const struct ohci_at91_caps *)
+			  of_device_get_match_data(&pdev->dev);
+	if (!ohci_at91->caps)
+		return -ENODEV;
+
+	if (ohci_at91->caps->suspend_ctrl) {
+		ohci_at91->sfr_regmap = at91_dt_syscon_sfr();
+		if (!ohci_at91->sfr_regmap)
+			dev_warn(dev, "failed to find sfr node\n");
+	}
+
 	board = hcd->self.controller->platform_data;
 	ohci = hcd_to_ohci(hcd);
 	ohci->num_ports = board->ports;
@@ -440,8 +471,17 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static const struct ohci_at91_caps at91rm9200_caps = {
+	.suspend_ctrl = false,
+};
+
+static const struct ohci_at91_caps sama5d2_caps = {
+	.suspend_ctrl = true,
+};
+
 static const struct of_device_id at91_ohci_dt_ids[] = {
-	{ .compatible = "atmel,at91rm9200-ohci" },
+	{ .compatible = "atmel,at91rm9200-ohci", .data = &at91rm9200_caps },
+	{ .compatible = "atmel,sama5d2-ohci", .data = &sama5d2_caps },
 	{ /* sentinel */ }
 };
 
@@ -581,6 +621,38 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static int ohci_at91_port_ctrl(struct regmap *regmap, bool enable)
+{
+	u32 regval;
+	int ret;
+
+	if (!regmap)
+		return -EINVAL;
+
+	ret = regmap_read(regmap, SFR_OHCIICR, &regval);
+	if (ret)
+		return ret;
+
+	if (enable)
+		regval &= ~SFR_OHCIICR_USB_SUSPEND;
+	else
+		regval |= SFR_OHCIICR_USB_SUSPEND;
+
+	regmap_write(regmap, SFR_OHCIICR, regval);
+
+	return 0;
+}
+
+static int ohci_at91_port_suspend(struct regmap *regmap)
+{
+	return ohci_at91_port_ctrl(regmap, false);
+}
+
+static int ohci_at91_port_resume(struct regmap *regmap)
+{
+	return ohci_at91_port_ctrl(regmap, true);
+}
+
 static int __maybe_unused
 ohci_hcd_at91_drv_suspend(struct device *dev)
 {
@@ -618,6 +690,9 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
 		ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
 		ohci->rh_state = OHCI_RH_HALTED;
 
+		if (ohci_at91->caps->suspend_ctrl)
+			ohci_at91_port_suspend(ohci_at91->sfr_regmap);
+
 		/* flush the writes */
 		(void) ohci_readl (ohci, &ohci->regs->control);
 		at91_stop_clock(ohci_at91);
@@ -637,6 +712,9 @@ ohci_hcd_at91_drv_resume(struct device *dev)
 
 	at91_start_clock(ohci_at91);
 
+	if (ohci_at91->caps->suspend_ctrl)
+		ohci_at91_port_resume(ohci_at91->sfr_regmap);
+
 	ohci_resume(hcd, false);
 	return 0;
 }
diff --git a/include/soc/at91/at91_sfr.h b/include/soc/at91/at91_sfr.h
new file mode 100644
index 0000000..04a3a1e
--- /dev/null
+++ b/include/soc/at91/at91_sfr.h
@@ -0,0 +1,29 @@
+/*
+ * Header file for the Atmel DDR/SDR SDRAM Controller
+ *
+ * Copyright (C) 2016 Atmel Corporation
+ *
+ * Author: Wenyou Yang <wenyou.yang at atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __AT91_SFR_H__
+#define __AT91_SFR_H__
+
+#define SFR_DDRCFG		0x04	/* DDR Configuration Register */
+/* 0x08 ~ 0x0c: Reserved */
+#define SFR_OHCIICR		0x10	/* OHCI Interrupt Configuration Register */
+#define SFR_OHCIISR		0x14	/* OHCI Interrupt Status Register */
+
+#define SFR_OHCIICR_SUSPEND_A	BIT(8)
+#define SFR_OHCIICR_SUSPEND_B	BIT(9)
+#define SFR_OHCIICR_SUSPEND_C	BIT(10)
+
+#define SFR_OHCIICR_USB_SUSPEND	(SFR_OHCIICR_SUSPEND_A | \
+				 SFR_OHCIICR_SUSPEND_B | \
+				 SFR_OHCIICR_SUSPEND_C)
+
+#endif
-- 
2.7.4



From wenyou.yang at atmel.com  Tue May 31 21:30:00 2016
From: wenyou.yang at atmel.com (Wenyou Yang)
Date: Wed, 1 Jun 2016 12:30:00 +0800
Subject: [PATCH v2 2/2] ARM: at91/dt: sama5d2: Use new compatible for ohci node
In-Reply-To: <1464755400-6825-1-git-send-email-wenyou.yang@atmel.com>
References: <1464755400-6825-1-git-send-email-wenyou.yang@atmel.com>
Message-ID: <1464755400-6825-3-git-send-email-wenyou.yang@atmel.com>

Use compatible "atmel,sama5d2-ohci" to be capable of suspending
ports while sleep to save the power consumption.

Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
---

Changes in v2:
 - Use the new compatible for ohci-node.

 arch/arm/boot/dts/sama5d2.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 78996bd..03d6724 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -232,7 +232,7 @@
 		};
 
 		usb1: ohci at 00400000 {
-			compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+			compatible = "atmel,sama5d2-ohci", "usb-ohci";
 			reg = <0x00400000 0x100000>;
 			interrupts = <41 IRQ_TYPE_LEVEL_HIGH 2>;
 			clocks = <&uhphs_clk>, <&uhphs_clk>, <&uhpck>;
-- 
2.7.4



From sajjan.linux at gmail.com  Tue May 31 22:14:22 2016
From: sajjan.linux at gmail.com (Vikas Sajjan)
Date: Wed, 1 Jun 2016 10:44:22 +0530
Subject: [Devel] [PATCH] Add support to parse RASF Table
In-Reply-To: <94F2FBAB4432B54E8AACC7DFDE6C92E37E488955@ORSMSX110.amr.corp.intel.com>
References: <1462796276-3987-1-git-send-email-nagendra.k-v@hpe.com>
 <TU4PR84MB0079FF2412932840DBE794C0C2770@TU4PR84MB0079.NAMPRD84.PROD.OUTLOOK.COM>
 <TU4PR84MB004598D95417F3C00FC6BFC7D9460@TU4PR84MB0045.NAMPRD84.PROD.OUTLOOK.COM>
 <94F2FBAB4432B54E8AACC7DFDE6C92E37E488955@ORSMSX110.amr.corp.intel.com>
Message-ID: <CAGm_ybi+n-oeH=t2PVRipBNHoeGvzhjjaEASkWMg8_K2VnD2Fg@mail.gmail.com>

On Tue, May 31, 2016 at 7:46 PM, Moore, Robert <robert.moore at intel.com> wrote:
> Sorry for the delay.
> Yes, this looks like we can take this.

Thank you.


> Bob
>
>
>> -----Original Message-----
>> From: Sajjan, Vikas C [mailto:vikas.cha.sajjan at hpe.com]
>> Sent: Monday, May 30, 2016 9:57 PM
>> To: Moore, Robert
>> Cc: Lakshminarasimha, Sunil Vishwanathpur; rjw at rjwysocki.net;
>> devel at acpica.org; linux-acpi at vger.kernel.org; K V, Nagendra; linaro-
>> acpi at lists.linaro.org; linux-arm-kernel at lists.infradead.org
>> Subject: RE: [PATCH] Add support to parse RASF Table
>>
>> Hi Bob,
>>
>> Any thoughts on this patch
>>
>> Regards
>> Vikas Sajjan
>>
>> -----Original Message-----
>> From: K V, Nagendra
>> Sent: Monday, May 16, 2016 2:05 PM
>> To: robert.moore at intel.com
>> Cc: Sajjan, Vikas C <vikas.cha.sajjan at hpe.com>; Lakshminarasimha, Sunil
>> Vishwanathpur <sunil.vl at hpe.com>; devel at acpica.org; linux-
>> acpi at vger.kernel.org
>> Subject: RE: [PATCH] Add support to parse RASF Table
>>
>> Bob,
>>
>> Did you get chance to look into this?
>>
>> Regards
>> Nagendra
>>
>> -----Original Message-----
>> From: K V, Nagendra
>> Sent: Monday, May 09, 2016 5:48 PM
>> To: robert.moore at intel.com
>> Cc: Sajjan, Vikas C <vikas.cha.sajjan at hpe.com>; Lakshminarasimha, Sunil
>> Vishwanathpur <sunil.vl at hpe.com>; devel at acpica.org; K V, Nagendra
>> <nagendra.k-v at hpe.com>
>> Subject: [PATCH] Add support to parse RASF Table
>>
>> This patch adds support to parse RASF table. Currently RASF table is not
>> being recognized.
>> ---
>>  source/common/ahtable.c      |  1 +
>>  source/common/dmtable.c      |  7 +++++++
>>  source/common/dmtbinfo.c     | 13 +++++++++++++
>>  source/compiler/dtcompiler.h |  1 +
>>  source/compiler/dttemplate.h | 11 +++++++++++
>>  source/compiler/dtutils.c    |  5 +++++
>>  source/include/acdisasm.h    |  2 ++
>>  7 files changed, 40 insertions(+)
>>
>> diff --git a/source/common/ahtable.c b/source/common/ahtable.c index
>> 021ae33..59ddc83 100644
>> --- a/source/common/ahtable.c
>> +++ b/source/common/ahtable.c
>> @@ -196,6 +196,7 @@ const AH_TABLE      AcpiSupportedTables[] =
>>      {ACPI_SIG_NFIT, "NVDIMM Firmware Interface Table"},
>>      {ACPI_SIG_PCCT, "Platform Communications Channel Table"},
>>      {ACPI_SIG_PMTT, "Platform Memory Topology Table"},
>> +    {ACPI_SIG_RASF, "RAS Features Table"},
>>      {ACPI_RSDP_NAME,"Root System Description Pointer"},
>>      {ACPI_SIG_RSDT, "Root System Description Table"},
>>      {ACPI_SIG_S3PT, "S3 Performance Table"}, diff --git
>> a/source/common/dmtable.c b/source/common/dmtable.c index 51d91f8..321407c
>> 100644
>> --- a/source/common/dmtable.c
>> +++ b/source/common/dmtable.c
>> @@ -430,6 +430,7 @@ const ACPI_DMTABLE_DATA     AcpiDmTableData[] =
>>      {ACPI_SIG_NFIT, AcpiDmTableInfoNfit,    AcpiDmDumpNfit,
>> DtCompileNfit,  TemplateNfit},
>>      {ACPI_SIG_PCCT, AcpiDmTableInfoPcct,    AcpiDmDumpPcct,
>> DtCompilePcct,  TemplatePcct},
>>      {ACPI_SIG_PMTT, NULL,                   AcpiDmDumpPmtt,
>> DtCompilePmtt,  TemplatePmtt},
>> +    {ACPI_SIG_RASF, AcpiDmTableInfoRasf,    NULL,           NULL,
>> TemplateRasf},
>>      {ACPI_SIG_RSDT, NULL,                   AcpiDmDumpRsdt,
>> DtCompileRsdt,  TemplateRsdt},
>>      {ACPI_SIG_S3PT, NULL,                   NULL,           NULL,
>> TemplateS3pt},
>>      {ACPI_SIG_SBST, AcpiDmTableInfoSbst,    NULL,           NULL,
>> TemplateSbst},
>> @@ -916,6 +917,11 @@ AcpiDmDumpTable (
>>              ByteLength = 10;
>>              break;
>>
>> +        case ACPI_DMT_RASF:
>> +
>> +            ByteLength = 12;
>> +            break;
>> +
>>          case ACPI_DMT_BUF16:
>>          case ACPI_DMT_UUID:
>>
>> @@ -1048,6 +1054,7 @@ AcpiDmDumpTable (
>>
>>          /* Integer Data Types */
>>
>> +        case ACPI_DMT_RASF:
>>          case ACPI_DMT_UINT8:
>>          case ACPI_DMT_UINT16:
>>          case ACPI_DMT_UINT24:
>> diff --git a/source/common/dmtbinfo.c b/source/common/dmtbinfo.c index
>> 5520da2..3896b69 100644
>> --- a/source/common/dmtbinfo.c
>> +++ b/source/common/dmtbinfo.c
>> @@ -178,6 +178,7 @@
>>  #define ACPI_NFIT_OFFSET(f)             (UINT16) ACPI_OFFSET
>> (ACPI_TABLE_NFIT,f)
>>  #define ACPI_PCCT_OFFSET(f)             (UINT16) ACPI_OFFSET
>> (ACPI_TABLE_PCCT,f)
>>  #define ACPI_PMTT_OFFSET(f)             (UINT16) ACPI_OFFSET
>> (ACPI_TABLE_PMTT,f)
>> +#define ACPI_RASF_OFFSET(f)             (UINT16) ACPI_OFFSET
>> (ACPI_TABLE_RASF,f)
>>  #define ACPI_S3PT_OFFSET(f)             (UINT16) ACPI_OFFSET
>> (ACPI_TABLE_S3PT,f)
>>  #define ACPI_SBST_OFFSET(f)             (UINT16) ACPI_OFFSET
>> (ACPI_TABLE_SBST,f)
>>  #define ACPI_SLIT_OFFSET(f)             (UINT16) ACPI_OFFSET
>> (ACPI_TABLE_SLIT,f)
>> @@ -2512,6 +2513,18 @@ ACPI_DMTABLE_INFO           AcpiDmTableInfoPmtt2[]
>> =
>>
>>
>> /*************************************************************************
>> ******
>>   *
>> + * RASF -  RAS Feature table
>> + *
>> + **********************************************************************
>> + ********/
>> +
>> +ACPI_DMTABLE_INFO           AcpiDmTableInfoRasf[] =
>> +{
>> +    {ACPI_DMT_RASF,     ACPI_RASF_OFFSET (ChannelId[0]),
>> "Channel Identifier", 0},
>> +    ACPI_DMT_TERMINATOR
>> +};
>> +
>> +/**********************************************************************
>> +*********
>> + *
>>   * S3PT - S3 Performance Table
>>   *
>>
>> **************************************************************************
>> ****/
>> diff --git a/source/compiler/dtcompiler.h b/source/compiler/dtcompiler.h
>> index eb85ddc..1072f52 100644
>> --- a/source/compiler/dtcompiler.h
>> +++ b/source/compiler/dtcompiler.h
>> @@ -681,6 +681,7 @@ extern const unsigned char  TemplateMtmr[];  extern
>> const unsigned char  TemplateNfit[];  extern const unsigned char
>> TemplatePcct[];  extern const unsigned char  TemplatePmtt[];
>> +extern const unsigned char  TemplateRasf[];
>>  extern const unsigned char  TemplateRsdt[];  extern const unsigned char
>> TemplateS3pt[];  extern const unsigned char  TemplateSbst[]; diff --git
>> a/source/compiler/dttemplate.h b/source/compiler/dttemplate.h index
>> e420ec4..d17b2af 100644
>> --- a/source/compiler/dttemplate.h
>> +++ b/source/compiler/dttemplate.h
>> @@ -978,6 +978,17 @@ const unsigned char TemplatePmtt[] =
>>      0x00,0x00,0x00,0x00                       /* 000000B0    "...."
>> */
>>  };
>>
>> +const unsigned char TemplateRasf[] =
>> +{
>> +    0x42,0x45,0x52,0x54,0x30,0x00,0x00,0x00,  /* 00000000    "RASF0..."
>> */
>> +    0x01,0x15,0x49,0x4E,0x54,0x45,0x4C,0x20,  /* 00000008    "..INTEL "
>> */
>> +    0x54,0x45,0x4D,0x50,0x4C,0x41,0x54,0x45,  /* 00000010    "TEMPLATE"
>> */
>> +    0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL"
>> */
>> +    0x28,0x05,0x10,0x20,0x00,0x00,0x00,0x00,  /* 00000020    "(.. ...."
>> */
>> +    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000028    "........"
>> */
>> +    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00   /* 00000030    "........"
>> */
>> +};
>> +
>>  const unsigned char TemplateRsdp[] =
>>  {
>>      0x52,0x53,0x44,0x20,0x50,0x54,0x52,0x20,  /* 00000000    "RSD PTR "
>> */
>> diff --git a/source/compiler/dtutils.c b/source/compiler/dtutils.c index
>> 6ca418c..774db8b 100644
>> --- a/source/compiler/dtutils.c
>> +++ b/source/compiler/dtutils.c
>> @@ -688,6 +688,11 @@ DtGetFieldLength (
>>          ByteLength = 10;
>>          break;
>>
>> +    case ACPI_DMT_RASF:
>> +
>> +        ByteLength = 12;
>> +        break;
>> +
>>      case ACPI_DMT_BUF16:
>>      case ACPI_DMT_UUID:
>>
>> diff --git a/source/include/acdisasm.h b/source/include/acdisasm.h index
>> ba8f274..d59e4d9 100644
>> --- a/source/include/acdisasm.h
>> +++ b/source/include/acdisasm.h
>> @@ -227,6 +227,7 @@ typedef enum
>>      ACPI_DMT_NFIT,
>>      ACPI_DMT_PCCT,
>>      ACPI_DMT_PMTT,
>> +    ACPI_DMT_RASF,
>>      ACPI_DMT_SLIC,
>>      ACPI_DMT_SRAT,
>>
>> @@ -458,6 +459,7 @@ extern ACPI_DMTABLE_INFO
>> AcpiDmTableInfoPcctHdr[];
>>  extern ACPI_DMTABLE_INFO        AcpiDmTableInfoPcct0[];
>>  extern ACPI_DMTABLE_INFO        AcpiDmTableInfoPcct1[];
>>  extern ACPI_DMTABLE_INFO        AcpiDmTableInfoPcct2[];
>> +extern ACPI_DMTABLE_INFO        AcpiDmTableInfoRasf[];
>>  extern ACPI_DMTABLE_INFO        AcpiDmTableInfoRsdp1[];
>>  extern ACPI_DMTABLE_INFO        AcpiDmTableInfoRsdp2[];
>>  extern ACPI_DMTABLE_INFO        AcpiDmTableInfoS3pt[];
>> --
>> 2.5.0
>>
>
> _______________________________________________
> Devel mailing list
> Devel at acpica.org
> https://lists.acpica.org/mailman/listinfo/devel


From dave.long at linaro.org  Tue May 31 22:15:41 2016
From: dave.long at linaro.org (David Long)
Date: Wed, 1 Jun 2016 01:15:41 -0400
Subject: [PATCH v12 05/10] arm64: Kprobes with single stepping support
In-Reply-To: <20160517091009.GA5082@sha-win-210.asiapac.arm.com>
References: <1461783185-9056-1-git-send-email-dave.long@linaro.org>
 <1461783185-9056-6-git-send-email-dave.long@linaro.org>
 <20160517091009.GA5082@sha-win-210.asiapac.arm.com>
Message-ID: <574E6F7D.1040902@linaro.org>

On 05/17/2016 05:10 AM, Huang Shijie wrote:
> On Wed, Apr 27, 2016 at 02:53:00PM -0400, David Long wrote:
>> From: Sandeepa Prabhu <sandeepa.s.prabhu at gmail.com>
>> +
>> +static bool __kprobes aarch64_insn_is_steppable(u32 insn)
>
> Could we add more comment for this function? In the comment, we can tell
> that which type of instructions are steppable, which are not.
>
>> +{
>> +	if (aarch64_get_insn_class(insn) == AARCH64_INSN_CLS_BR_SYS) {
>> +		if (aarch64_insn_is_branch(insn) ||
>> +		    aarch64_insn_is_msr_imm(insn) ||
>> +		    aarch64_insn_is_msr_reg(insn) ||
>> +		    aarch64_insn_is_exception(insn))
>> +			return false;
>> +
>> +		if (aarch64_insn_is_mrs(insn))
>> +			return aarch64_insn_extract_system_reg(insn)
>> +			     != AARCH64_INSN_SPCLREG_DAIF;
>> +
>> +		if (aarch64_insn_is_hint(insn))
>> +			return aarch64_insn_is_nop(insn);
>> +
>> +		return true;
>> +	}
>> +
>> +	if (aarch64_insn_uses_literal(insn) ||
>> +	    aarch64_insn_is_exclusive(insn))
>> +		return false;
>> +
>> +	return true;
>
> Thanks
> Huang Shijie
>

I did add a comment to this for the next version of the patch.

-dl



From k.kozlowski at samsung.com  Tue May 31 22:36:42 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 01 Jun 2016 07:36:42 +0200
Subject: [RFC v2] dma-mapping: Use unsigned long for dma_attrs
In-Reply-To: <20160531170420.GB25366@infradead.org>
References: <1464609246-6948-1-git-send-email-k.kozlowski@samsung.com>
 <1464609246-6948-2-git-send-email-k.kozlowski@samsung.com>
 <20160531170420.GB25366@infradead.org>
Message-ID: <574E746A.2030806@samsung.com>

On 05/31/2016 07:04 PM, Christoph Hellwig wrote:
> On Mon, May 30, 2016 at 01:54:06PM +0200, Krzysztof Kozlowski wrote:
>> The dma-mapping core and the implementations do not change the
>> DMA attributes passed by pointer.  Thus the pointer can point to const
>> data.  However the attributes do not have to be a bitfield. Instead
>> unsigned long will do fine:
>>
>> 1. This is just simpler.  Both in terms of reading the code and setting
>>    attributes.  Instead of initializing local attributes on the stack and
>>    passing pointer to it to dma_set_attr(), just set the bits.
>>
>> 2. It brings safeness and checking for const correctness because the
>>    attributes are passed by value.
>>
>> Please have in mind that this is RFC, not finished yet.  Only ARM and
>> ARM64 are fixed (and not everywhere).
>> However other API users also have to be converted which is quite
>> intrusive.  I would rather avoid it until the overall approach is
>> accepted.
> 
> This looks great!  Please continue doing the full conversion.
> 
>> +/**
>> + * List of possible attributes associated with a DMA mapping. The semantics
>> + * of each attribute should be defined in Documentation/DMA-attributes.txt.
>> + */
>> +#define DMA_ATTR_WRITE_BARRIER		BIT(1)
>> +#define DMA_ATTR_WEAK_ORDERING		BIT(2)
>> +#define DMA_ATTR_WRITE_COMBINE		BIT(3)
>> +#define DMA_ATTR_NON_CONSISTENT		BIT(4)
>> +#define DMA_ATTR_NO_KERNEL_MAPPING	BIT(5)
>> +#define DMA_ATTR_SKIP_CPU_SYNC		BIT(6)
>> +#define DMA_ATTR_FORCE_CONTIGUOUS	BIT(7)
>> +#define DMA_ATTR_ALLOC_SINGLE_PAGES	BIT(8)
> 
> No really for this patch, but I would much prefer to document them next
> to the code in the long run.  Also I really think these BIT() macros
> are a distraction compared to the (1 << N) notation.

Not much difference to me but maybe plain number:
...	0x01u
...	0x02u
?

> 
>> +/**
>> + * dma_get_attr - check for a specific attribute
>> + * @attr: attribute to look for
>> + * @attrs: attributes to check within
>> + */
>> +static inline bool dma_get_attr(unsigned long attr, unsigned long attrs)
>> +{
>> +	return !!(attr & attrs);
>> +}
> 
> I'd just kill this helper, much easier to simply open code it in the
> caller.

Keeping it for now helps reducing the number of changes in the patch.
The patch will be quite big as it has to replace all the uses atomically.

I can get rid of the helper in consecutive patch.

Best regards,
Krzysztof




From hotran at apm.com  Tue May 31 23:00:05 2016
From: hotran at apm.com (Hoan Tran)
Date: Tue, 31 May 2016 23:00:05 -0700
Subject: [2/3] hwmon: xgene: Adds hwmon driver
In-Reply-To: <20160530052507.GA25641@roeck-us.net>
References: <1463415447-29903-3-git-send-email-hotran@apm.com>
 <20160530052507.GA25641@roeck-us.net>
Message-ID: <CAFHUOYzWj_PbbpzCW5CjO7d3uc7x2h8UvHrYmDoKyttNQVDDZA@mail.gmail.com>

Hi Guenter,

Thanks for your review !

On Sun, May 29, 2016 at 10:25 PM, Guenter Roeck <linux at roeck-us.net> wrote:
> On Mon, May 16, 2016 at 09:17:26AM -0700, hotran wrote:
>> This patch adds hardware temperature and power reading support for
>> APM X-Gene SoC's using the mailbox communication interface.
>>
> Please drop the "'".

Yes, will remove it.

>
>>
>> Signed-off-by: Hoan Tran <hotran at apm.com>
>> ---
>>  Documentation/hwmon/xgene-hwmon |  32 ++
>>  drivers/hwmon/Kconfig           |   7 +
>>  drivers/hwmon/Makefile          |   1 +
>>  drivers/hwmon/xgene-hwmon.c     | 801 ++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 841 insertions(+)
>>  create mode 100644 Documentation/hwmon/xgene-hwmon
>>  create mode 100644 drivers/hwmon/xgene-hwmon.c
>>
>> diff --git a/Documentation/hwmon/xgene-hwmon b/Documentation/hwmon/xgene-hwmon
>> new file mode 100644
>> index 0000000..040a7f2
>> --- /dev/null
>> +++ b/Documentation/hwmon/xgene-hwmon
>> @@ -0,0 +1,32 @@
>> +Kernel driver xgene-hwmon
>> +========================
>> +
>> +Supported chips:
>> + * APM X-Gene SoC
>> +
>> +Description
>> +-----------
>> +
>> +This driver adds hardware temperature and power reading support for
>> +APM X-Gene SoC's using the mailbox communication interface.
>>
> No "'".

Yes,

>>
>> +For device tree, it is the standard DT mailbox.
>> +For ACPI, it is the PCC mailbox.
>> +
>> +The following sensors are supported
>> +
>> +  * Temperature
>> +    - SoC on-die temperature in milli-degree
>> +    - Alarm when high/over temperature occurs
>> +  * Power
>> +    - CPU power in uW
>> +    - IO power in uW
>> +    - CPU and IO power in uW
>> +
>> +sysfs-Interface
>> +---------------
>> +
>> +temp1_input - SoC on-die temperature (milli-degree C)
>> +temp1_critical_alarm - An 1 would indicates on-die temperature exceeded threshold
>> +power1_input - CPU power in (uW)
>> +power2_input - IO power in (uW)
>> +power3_input - CPU and IO power in (uW)
>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>> index 5c2d13a..91c3056 100644
>> --- a/drivers/hwmon/Kconfig
>> +++ b/drivers/hwmon/Kconfig
>> @@ -1776,6 +1776,13 @@ config SENSORS_ULTRA45
>>         This driver provides support for the Ultra45 workstation environmental
>>         sensors.
>>
>> +config SENSORS_XGENE
>> +     tristate "APM X-Gene SoC hardware monitoring driver"
>> +     depends on XGENE_SLIMPRO_MBOX || PCC
>> +     help
>> +       If you say yes here you get support for the temperature
>> +       and power sensors for APM X-Gene SoC.
>> +
>>  if ACPI
>>
>>  comment "ACPI drivers"
>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>> index 58cc3ac..668d0f1 100644
>> --- a/drivers/hwmon/Makefile
>> +++ b/drivers/hwmon/Makefile
>> @@ -161,6 +161,7 @@ obj-$(CONFIG_SENSORS_W83L785TS)   += w83l785ts.o
>>  obj-$(CONFIG_SENSORS_W83L786NG)      += w83l786ng.o
>>  obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
>>  obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
>> +obj-$(CONFIG_SENSORS_XGENE)  += xgene-hwmon.o
>>
>>  obj-$(CONFIG_PMBUS)          += pmbus/
>>
>> diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c
>> new file mode 100644
>> index 0000000..bc4ad29
>> --- /dev/null
>> +++ b/drivers/hwmon/xgene-hwmon.c
>> @@ -0,0 +1,801 @@
>> +/*
>> + * APM X-Gene SoC Hardware Monitoring Driver
>> + *
>> + * Copyright (c) 2016, Applied Micro Circuits Corporation
>> + * Author: Loc Ho <lho at apm.com>
>> + *         Hoan Tran <hotran at apm.com>
>> + *
>> + * 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.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
>> + *
>> + * This driver provides the following features:
>> + *  - Retrieve CPU's total power (uW)
>> + *  - Retrieve IO's total power (uW)
>
> Please drop the "'s".

Yes,

>
>> + *  - Retrieve SoC total power (uW)
>> + *  - Retrieve SoC temperature (milli-degree C) and alarm
>> + */
>> +#include <linux/acpi.h>
>> +#include <linux/dma-mapping.h>
>> +#include <linux/hwmon.h>
>> +#include <linux/hwmon-sysfs.h>
>> +#include <linux/kfifo.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/mailbox_client.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <acpi/cppc_acpi.h>
>> +
>> +/* SLIMpro message defines */
>> +#define SLIMPRO_MSG_TYPE_DBG_ID              0
>> +#define SLIMPRO_MSG_TYPE_ERR_ID              7
>> +#define SLIMPRO_MSG_TYPE_PWRMGMT_ID  9
>> +
>> +#define SLIMPRO_MSG_TYPE(v)          (((v) & 0xF0000000) >> 28)
>> +#define SLIMPRO_MSG_TYPE_SET(v)              (((v) << 28) & 0xF0000000)
>> +#define SLIMPRO_MSG_SUBTYPE(v)               (((v) & 0x0F000000) >> 24)
>> +#define SLIMPRO_MSG_SUBTYPE_SET(v)   (((v) << 24) & 0x0F000000)
>> +
>> +#define SLIMPRO_DBG_SUBTYPE_SENSOR_READ      4
>> +#define SLIMPRO_SENSOR_READ_MSG              0x04FFE902
>> +#define SLIMPRO_SENSOR_READ_ENCODE_ADDR(a) \
>> +     ((a) & 0x000FFFFF)
>> +#define PMD_PWR_MW_REG                       0x26
>> +#define SOC_PWR_REG                  0x21
>> +#define SOC_TEMP_REG                 0x10
>> +
>> +#define SLIMPRO_PWRMGMT_SUBTYPE_TPC  1
>> +#define SLIMPRO_TPC_ALARM            2
>> +#define SLIMPRO_TPC_GET_ALARM                3
>> +#define SLIMPRO_TPC_CMD(v)           (((v) & 0x00FF0000) >> 16)
>> +#define SLIMPRO_TPC_CMD_SET(v)               (((v) << 16) & 0x00FF0000)
>> +#define SLIMPRO_TPC_ENCODE_MSG(hndl, cmd, type) \
>> +     (SLIMPRO_MSG_TYPE_SET(SLIMPRO_MSG_TYPE_PWRMGMT_ID) | \
>> +     SLIMPRO_MSG_SUBTYPE_SET(hndl) | \
>> +     SLIMPRO_TPC_CMD_SET(cmd) | \
>> +     type)
>> +
>
> Do you _have_ to use such long defines ? This causes lots of "line too long"
> checkpatch warnings, which would really be easy to avoid with shorter defines.

Ok, I'll shorten these defines.

>
>> +/* PCC defines */
>> +#define SLIMPRO_MSG_PCC_SUBSPACE     7
>> +#define PCC_SIGNATURE_MASK           0x50424300
>> +#define PCCC_GENERATE_DB_INT         BIT(15)
>> +#define PCCS_CMD_COMPLETE            BIT(0)
>> +#define PCCS_SCI_DOORBEL             BIT(1)
>> +#define PCCS_PLATFORM_NOTIFICATION   BIT(3)
>> +/*
>> + * Arbitrary retries in case the remote processor is slow to respond
>> + * to PCC commands
>> + */
>> +#define PCC_NUM_RETRIES                      500
>> +
>> +#define ASYNC_MSG_FIFO_SIZE          16
>> +#define MBOX_HWMON_INDEX             0
>> +#define MBOX_OP_TIMEOUTMS            1000
>> +
>> +#define SOC_TEMP                     0
>> +#define CPU_POWER                    0
>> +#define IO_POWER                     1
>> +#define SOC_POWER                    2
>> +
>
> Are those random defines, to be used for index values ?
> If so, how about enums ?

Yes, will move them into an enum.

>
>> +#define WATT_TO_mWATT(x)             ((x) * 1000)
>> +#define mWATT_TO_uWATT(x)            ((x) * 1000)
>> +#define WATT_TO_uWATT(x)             ((x) * 1000000)
>> +#define CELSIUS_TO_mCELSIUS(x)               ((x) * 1000)
>> +
>> +#define to_xgene_hwmon_dev(cl)               \
>> +     container_of(cl, struct xgene_hwmon_dev, mbox_client)
>> +
>> +struct slimpro_resp_msg {
>> +     u32 msg;
>> +     u32 param1;
>> +     u32 param2;
>> +} __packed;
>> +
>> +struct xgene_hwmon_dev {
>> +     struct device           *dev;
>> +     struct mbox_chan        *mbox_chan;
>> +     struct mbox_client      mbox_client;
>> +
>> +     spinlock_t              lock;
>> +     struct completion       rd_complete;
>> +     int                     resp_pending;
>> +     struct slimpro_resp_msg sync_msg;
>> +
>> +     struct work_struct      workq;
>> +     struct kfifo_rec_ptr_1  async_msg_fifo;
>> +
>> +     struct device           *hwmon_dev;
>> +     bool                    temp_critical_alarm;
>> +
>> +     phys_addr_t             comm_base_addr;
>> +     void                    *pcc_comm_addr;
>> +     u64                     usecs_lat;
>> +};
>> +
>> +/*
>> + * This function tests and clears a bitmask then returns its old value
>> + */
>> +static u16 xgene_word_tst_and_clr(u16 *addr, u16 mask)
>> +{
>> +     u16 ret, val;
>> +
>> +     val = readw_relaxed(addr);
>> +     ret = val & mask;
>> +     val &= ~mask;
>> +     writew_relaxed(val, addr);
>> +
>> +     return ret;
>> +}
>> +
>> +static int xgene_hwmon_pcc_rd(struct xgene_hwmon_dev *ctx, u32 *msg)
>> +{
>> +     struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr;
>> +     void *ptr = generic_comm_base + 1;
>> +     unsigned long flags;
>> +     u16 val;
>> +     int rc;
>> +
>> +     spin_lock_irqsave(&ctx->lock, flags);
>> +     if (ctx->resp_pending) {
>> +             spin_unlock_irqrestore(&ctx->lock, flags);
>> +             return -EAGAIN;
>> +     }
>> +
>> +     init_completion(&ctx->rd_complete);
>> +     ctx->resp_pending = true;
>> +
>> +     /* Write signature for subspace */
>> +     writel_relaxed(PCC_SIGNATURE_MASK | SLIMPRO_MSG_PCC_SUBSPACE,
>> +                    &generic_comm_base->signature);
>> +
>> +     /* Write to the shared command region */
>> +     writew_relaxed(SLIMPRO_MSG_TYPE(msg[0]) | PCCC_GENERATE_DB_INT,
>> +                    &generic_comm_base->command);
>> +
>> +     /* Flip CMD COMPLETE bit */
>> +     val = readw_relaxed(&generic_comm_base->status);
>> +     val &= ~PCCS_CMD_COMPLETE;
>> +     writew_relaxed(val, &generic_comm_base->status);
>> +
>> +     /* Copy the message to the PCC comm space */
>> +     memcpy(ptr, msg, sizeof(struct slimpro_resp_msg));
>> +
>> +     /* Ring the doorbell */
>> +     rc = mbox_send_message(ctx->mbox_chan, msg);
>> +     if (rc < 0) {
>> +             dev_err(ctx->dev, "Mailbox send error %d\n", rc);
>> +             goto err;
>> +     }
>> +     spin_unlock_irqrestore(&ctx->lock, flags);
>> +     if (!wait_for_completion_timeout(&ctx->rd_complete,
>> +                                      usecs_to_jiffies(ctx->usecs_lat))) {
>> +             spin_lock_irqsave(&ctx->lock, flags);
>> +             dev_err(ctx->dev, "Mailbox operation timed out\n");
>> +             rc = -EIO;
>
>         -ETIMEDOUT ?

OK

>
>> +             goto err;
>> +     }
>> +     spin_lock_irqsave(&ctx->lock, flags);
>> +
>> +     /* Check for invalid data or no device */
>> +     if (SLIMPRO_MSG_TYPE(ctx->sync_msg.msg) == SLIMPRO_MSG_TYPE_ERR_ID ||
>> +         ctx->sync_msg.msg == 0xffffffff) {
>> +             rc = -ENODEV;
>
> Two different errors ?

Yes, will fix it

>
>> +             goto err;
>> +     }
>> +
>> +     msg[0] = ctx->sync_msg.msg;
>> +     msg[1] = ctx->sync_msg.param1;
>> +     msg[2] = ctx->sync_msg.param2;
>> +
>> +err:
>> +     mbox_chan_txdone(ctx->mbox_chan, 0);
>> +     ctx->resp_pending = false;
>> +     spin_unlock_irqrestore(&ctx->lock, flags);
>> +     return rc;
>> +}
>> +
>> +static int xgene_hwmon_rd(struct xgene_hwmon_dev *ctx, u32 *msg)
>> +{
>> +     unsigned long flags;
>> +     int rc;
>> +
>> +     spin_lock_irqsave(&ctx->lock, flags);
>> +     if (ctx->resp_pending) {
>> +             spin_unlock_irqrestore(&ctx->lock, flags);
>> +             return -EAGAIN;
>> +     }
>> +
>> +     init_completion(&ctx->rd_complete);
>> +     ctx->resp_pending = true;
>> +     rc = mbox_send_message(ctx->mbox_chan, msg);
>> +     if (rc < 0) {
>> +             dev_err(ctx->dev, "Mailbox send error %d\n", rc);
>> +             goto err;
>> +     }
>> +     spin_unlock_irqrestore(&ctx->lock, flags);
>> +
>> +     if (!wait_for_completion_timeout(&ctx->rd_complete,
>> +                                      msecs_to_jiffies(MBOX_OP_TIMEOUTMS))) {
>> +             spin_lock_irqsave(&ctx->lock, flags);
>> +             dev_err(ctx->dev, "Mailbox operation timed out\n");
>> +             rc = -EIO;
>
>         -ETIMEDOUT ?

OK

>
>> +             goto err;
>> +     }
>> +     spin_lock_irqsave(&ctx->lock, flags);
>> +
>> +     /* Check for invalid data or no device */
>> +     if (SLIMPRO_MSG_TYPE(ctx->sync_msg.msg) == SLIMPRO_MSG_TYPE_ERR_ID ||
>> +         ctx->sync_msg.msg == 0xffffffff) {
>> +             rc = -ENODEV;
>
> Isn't that two different errors ?

Will fix it.

>
>> +             goto err;
>> +     }
>> +
>> +     msg[0] = ctx->sync_msg.msg;
>> +     msg[1] = ctx->sync_msg.param1;
>> +     msg[2] = ctx->sync_msg.param2;
>> +
>> +err:
>> +     ctx->resp_pending = false;
>> +     spin_unlock_irqrestore(&ctx->lock, flags);
>> +     return rc;
>> +}
>> +
>> +static int xgene_hwmon_reg_map_rd(struct xgene_hwmon_dev *ctx, u32 addr,
>> +                               u32 *data)
>> +{
>> +     u32 msg[3];
>> +     int rc;
>> +
>> +     msg[0] = SLIMPRO_SENSOR_READ_MSG;
>> +     msg[1] = SLIMPRO_SENSOR_READ_ENCODE_ADDR(addr);
>> +     msg[2] = 0;
>> +
> Does the msg endianness always match the CPU endianness ?
> Probably yes, just want to make sure.

For DT, SLIMpro mailbox controller will take care of endianness.
For ACPI, maybe I missed it, it should be corrected when PCC writes
message into shared memory. Thanks

>
>> +     if (ACPI_COMPANION(ctx->dev))
>> +             rc = xgene_hwmon_pcc_rd(ctx, msg);
>> +     else
>> +             rc = xgene_hwmon_rd(ctx, msg);
>> +     if (rc < 0) {
>> +             /* To support compatibility with firmware, return 0 */
>> +             dev_err(ctx->dev, "SLIMpro register 0x%02X read error %d\n",
>> +                     addr, rc);
>
> Is this error mesage necessary ?

Will remove it.

>
>> +             *data = 0;
>> +             return rc;
>> +     }
>> +     *data = msg[1];
>> +
>> +     return rc;
>> +}
>> +
>> +static int xgene_hwmon_get_notification_msg(struct xgene_hwmon_dev *ctx,
>> +                                         u32 *amsg)
>> +{
>> +     u32 msg[3];
>> +     int rc;
>> +
>> +     msg[0] = SLIMPRO_TPC_ENCODE_MSG(SLIMPRO_PWRMGMT_SUBTYPE_TPC,
>> +                                     SLIMPRO_TPC_GET_ALARM, 0);
>> +     msg[1] = 0;
>> +     msg[2] = 0;
>> +
>> +     rc = xgene_hwmon_pcc_rd(ctx, msg);
>> +     if (rc < 0) {
>> +             dev_err(ctx->dev, "PCC Alarm read error %d\n", rc);
>
> Is this error message necessary ?

Will remove it.

>
>> +             return rc;
>> +     }
>> +     amsg[0] = msg[0];
>> +     amsg[1] = msg[1];
>> +     amsg[2] = msg[2];
>> +
>> +     return rc;
>> +}
>> +
>> +static int xgene_hwmon_get_cpu_pwr(struct xgene_hwmon_dev *ctx, u32 *val)
>> +{
>> +     return xgene_hwmon_reg_map_rd(ctx, PMD_PWR_MW_REG, val);
>> +}
>> +
>> +static int xgene_hwmon_get_io_pwr(struct xgene_hwmon_dev *ctx, u32 *val)
>> +{
>> +     return xgene_hwmon_reg_map_rd(ctx, SOC_PWR_REG, val);
>> +}
>> +
>> +static int xgene_hwmon_get_soc_power(struct xgene_hwmon_dev *ctx, u32 *val)
>> +{
>> +     u32 pmd_vrm_power;
>> +     u32 io_vrm_power;
>> +     int rc;
>> +
>> +     rc = xgene_hwmon_get_cpu_pwr(ctx, &pmd_vrm_power);
>> +     if (rc < 0)
>> +             return rc;
>> +
>> +     rc = xgene_hwmon_get_io_pwr(ctx, &io_vrm_power);
>> +     if (rc < 0)
>> +             return rc;
>> +
>> +     *val = pmd_vrm_power + WATT_TO_mWATT(io_vrm_power);
>> +
>
> So the SoC power is just adding CPU and IO power, ie it reports the sum
> of both ?  Please drop. Such calculations should be done in user space
> if wanted.

Ok, will drop this SoC power.

>
>> +     return 0;
>> +}
>> +
>> +static int xgene_hwmon_get_temp(struct xgene_hwmon_dev *ctx, u32 *val)
>> +{
>> +     return xgene_hwmon_reg_map_rd(ctx, SOC_TEMP_REG, val);
>> +}
>> +
>> +/*
>> + * Sensor temperature/power functions
>> + */
>> +static const char * const sensor_temp_input_names[] = {
>> +     [SOC_TEMP] = "SoC Temperature",
>> +};
>> +
>> +static const char * const sensor_pwr_input_names[] = {
>> +     [CPU_POWER] = "CPU's power",
>> +     [IO_POWER] = "IO's power",
>
> Please drop the "'s".

Ok,

>
>> +     [SOC_POWER] = "SoC power"
>> +};
>> +
>> +static ssize_t xgene_hwmon_show_name(struct device *dev,
>> +                                  struct device_attribute *attr, char *buf)
>> +{
>> +     return snprintf(buf, PAGE_SIZE, "APM X-Gene\n");
>> +}
>> +
>> +static ssize_t xgene_hwmon_show_temp(struct device *dev,
>> +                                  struct device_attribute *attr,
>> +                                  char *buf)
>> +{
>> +     struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
>> +     u32 val;
>> +     int rc;
>> +
>> +     rc = xgene_hwmon_get_temp(ctx, &val);
>> +     if (rc < 0)
>> +             return rc;
>> +
>> +     val = CELSIUS_TO_mCELSIUS(val);
>> +
>> +     return snprintf(buf, PAGE_SIZE, "%d\n", val);
>
> val is u32 (is it reported by the chip as unsigned ?)

It also give a negative temp. I'll fix it

>
>> +}
>> +
>> +static ssize_t xgene_hwmon_show_temp_label(struct device *dev,
>> +                                        struct device_attribute *attr,
>> +                                        char *buf)
>> +{
>> +     int channel = to_sensor_dev_attr(attr)->index - 1;
>> +
>> +     return snprintf(buf, PAGE_SIZE, "%s\n",
>> +                     sensor_temp_input_names[channel]);
>> +}
>> +
>> +static ssize_t xgene_hwmon_show_temp_critical_alarm(struct device *dev,
>> +                                                 struct device_attribute *devattr,
>> +                                                 char *buf)
>> +{
>> +     struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
>> +
>> +     return snprintf(buf, PAGE_SIZE, "%d\n", ctx->temp_critical_alarm);
>> +}
>> +
>> +static ssize_t xgene_hwmon_show_pwr_label(struct device *dev,
>> +                                       struct device_attribute *attr,
>> +                                       char *buf)
>> +{
>> +     int channel = to_sensor_dev_attr(attr)->index - 1;
>> +
>> +     return snprintf(buf, PAGE_SIZE, "%s\n",
>> +                     sensor_pwr_input_names[channel]);
>> +}
>> +
>> +static ssize_t xgene_hwmon_show_pwr(struct device *dev,
>> +                                 struct device_attribute *attr,
>> +                                 char *buf)
>> +{
>> +     struct xgene_hwmon_dev *ctx = dev_get_drvdata(dev);
>> +     int channel = to_sensor_dev_attr(attr)->index - 1;
>> +     u32 val;
>> +     int rc;
>> +
>> +     switch (channel) {
>> +     case CPU_POWER:
>> +             rc = xgene_hwmon_get_cpu_pwr(ctx, &val);
>> +             break;
>> +     case IO_POWER:
>> +             rc = xgene_hwmon_get_io_pwr(ctx, &val);
>> +             break;
>> +     case SOC_POWER:
>> +             rc = xgene_hwmon_get_soc_power(ctx, &val);
>> +             break;
>
> Those are not the index values specified. Please use those constants
> in the attribute declaration.
>
> Overall, it would probably be easier to just have two separate
> functions for CPU an IO power.

Yes, I'll use separate functions.

>
>> +     default:
>> +             rc = -EINVAL;
>> +             break;
>> +     }
>> +     if (rc < 0)
>> +             return rc;
>> +
>> +     if (channel == IO_POWER)
>> +             val = WATT_TO_uWATT(val);
>
> What is the maximum possible reported IO power ? I understand that
> the maximum supported value with the current code is 4,294 kW, but
> if the hardware can report more than that it would be prudent to
> use an unsigned long for the value.

This is the power of internal SoC and it could not exceed this number

>
>> +     else
>> +             val = mWATT_TO_uWATT(val);
>> +
>> +     return snprintf(buf, PAGE_SIZE, "%d\n", val);
>
> val is u32.

Yes, change to %u.

>
>> +}
>> +
>> +/* Chip name, required by hwmon */
>> +static DEVICE_ATTR(name, S_IRUGO, xgene_hwmon_show_name, NULL);
>> +
>
> Unnecesary - see below.
>
>> +#define SENSOR_ATTR_TEMP(index) \
>> +     static SENSOR_DEVICE_ATTR(temp##index##_label, S_IRUGO, \
>> +                               xgene_hwmon_show_temp_label, NULL, index); \
>> +     static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, \
>> +                               xgene_hwmon_show_temp, NULL, index); \
>> +     static SENSOR_DEVICE_ATTR(temp##index##_critical_alarm, S_IRUGO, \
>> +                               xgene_hwmon_show_temp_critical_alarm, NULL, \
>> +                               index);
>> +#define SENSOR_ATTR_PWR(index) \
>> +     static SENSOR_DEVICE_ATTR(power##index##_label, S_IRUGO, \
>> +                               xgene_hwmon_show_pwr_label, NULL, index); \
>> +     static SENSOR_DEVICE_ATTR(power##index##_input, S_IRUGO, \
>> +                               xgene_hwmon_show_pwr, NULL, index);
>> +
>> +#define APM_TEMP_SENSOR_ATTR(index) \
>> +     &sensor_dev_attr_temp##index##_input.dev_attr.attr, \
>> +     &sensor_dev_attr_temp##index##_label.dev_attr.attr, \
>> +     &sensor_dev_attr_temp##index##_critical_alarm.dev_attr.attr
>> +#define APM_PWR_SENSOR_ATTR(index) \
>> +     &sensor_dev_attr_power##index##_input.dev_attr.attr, \
>> +     &sensor_dev_attr_power##index##_label.dev_attr.attr
>> +
>> +SENSOR_ATTR_TEMP(1); /* SoC temperature */
>> +SENSOR_ATTR_PWR(1);  /* CPU power */
>> +SENSOR_ATTR_PWR(2);  /* IO power */
>> +SENSOR_ATTR_PWR(3);  /* SoC power */
>> +
>> +static struct attribute *xgene_hwmon_attributes[] = {
>> +     &dev_attr_name.attr,
>> +     APM_TEMP_SENSOR_ATTR(1),
>> +     APM_PWR_SENSOR_ATTR(1),
>> +     APM_PWR_SENSOR_ATTR(2),
>> +     APM_PWR_SENSOR_ATTR(3),
>
> Please drop the macros and write explicit code.
>
> 'index' values are always accessed with '- 1'. Please start the index with 0
> and drop the '- 1'.

Ok, change to an explicit code.

>
>> +     NULL,
>> +};
>> +
>> +static const struct attribute_group xgene_hwmon_attr_group = {
>> +     .attrs  = xgene_hwmon_attributes,
>> +};
>> +
>> +static int xgene_hwmon_tpc_alarm(struct xgene_hwmon_dev *ctx,
>> +                              struct slimpro_resp_msg *amsg)
>> +{
>> +     char name[40];
>> +
>> +     ctx->temp_critical_alarm = amsg->param2 ? true : false;
>> +     snprintf(name, sizeof(name), "temp%d_critical_alarm", SOC_TEMP + 1);
>> +     sysfs_notify(&ctx->dev->kobj, NULL, name);
>> +     dev_alert(ctx->dev, "SoC temperature alarm at %d degree\n",
>> +               amsg->param1);
>
> Please drop this message. That is what the notification is for.
> User space can then decide if it wants to log or not.
>

Ok

>> +     return 0;
>> +}
>> +
>> +static void xgene_hwmon_process_pwrmsg(struct xgene_hwmon_dev *ctx,
>> +                                    struct slimpro_resp_msg *amsg)
>> +{
>> +     switch (SLIMPRO_MSG_SUBTYPE(amsg->msg)) {
>> +     case SLIMPRO_PWRMGMT_SUBTYPE_TPC:
>> +             switch (SLIMPRO_TPC_CMD(amsg->msg)) {
>> +             case SLIMPRO_TPC_ALARM:
>> +                     xgene_hwmon_tpc_alarm(ctx, amsg);
>> +                     break;
>> +             default:
>> +                     dev_warn(ctx->dev,
>> +                              "Un-supported TPC message received 0x%08X\n",
>> +                              amsg->msg);
>> +                     break;
>> +             }
>> +             break;
>> +     default:
>> +             dev_warn(ctx->dev, "Un-supported message received 0x%08X\n",
>> +                      amsg->msg);
>
> Are those messages necessary ? Can they clog the log ?

Will remove it.

>
>> +             break;
>> +     }
>> +}
>> +
>> +/*
>> + * This function is called to process async work queue
>> + */
>> +static void xgene_hwmon_evt_work(struct work_struct *work)
>> +{
>> +     struct slimpro_resp_msg amsg;
>> +     struct xgene_hwmon_dev *ctx;
>> +     int ret;
>> +
>> +     ctx = container_of(work, struct xgene_hwmon_dev, workq);
>> +     while (kfifo_out_spinlocked(&ctx->async_msg_fifo, &amsg,
>> +                                 sizeof(struct slimpro_resp_msg),
>> +                                 &ctx->lock)) {
>> +             /*
>> +              * If PCC, send a consumer command to Platform to get info
>> +              * If Slimpro Mailbox, get message from specific FIFO
>> +              */
>> +             if (ACPI_COMPANION(ctx->dev)) {
>> +                     ret = xgene_hwmon_get_notification_msg(ctx,
>> +                                                            (u32 *)&amsg);
>> +                     if (ret < 0)
>> +                             continue;
>> +             }
>> +             switch (SLIMPRO_MSG_TYPE(amsg.msg)) {
>> +             case SLIMPRO_MSG_TYPE_PWRMGMT_ID:
>> +                     xgene_hwmon_process_pwrmsg(ctx, &amsg);
>> +                     break;
>> +             default:
>> +                     dev_warn(ctx->dev,
>> +                              "Invalid mailbox msg received 0x%08X 0x%08X 0x%08X\n",
>> +                              amsg.msg, amsg.param1, amsg.param2);
>
> Is this message necessary ? I am concerned about the logging noise it might
> create.

Will remove it.

>
>> +                     break;
>> +             }
>> +     }
>> +}
>> +
>> +/*
>> + * This function is called when the SLIMpro/PCC Mailbox received a message
>> + */
>> +static void xgene_hwmon_rx_cb(struct mbox_client *cl, void *msg)
>> +{
>> +     struct xgene_hwmon_dev *ctx = to_xgene_hwmon_dev(cl);
>> +     struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr;
>> +     struct slimpro_resp_msg amsg;
>> +
>> +     /* If PCC mailbox controller, get msg from shared memory */
>> +     if (ACPI_COMPANION(ctx->dev)) {
>> +             msg = generic_comm_base + 1;
>> +             /* Check if platform sends interrupt */
>> +             if (!xgene_word_tst_and_clr(&generic_comm_base->status,
>> +                                         PCCS_SCI_DOORBEL))
>> +                     return;
>> +     }
>> +
>> +     /*
>> +      * Response message format:
>> +      * msg[0] is the return code of the operation
>> +      * msg[1] is the first parameter word
>> +      * msg[2] is the second parameter word
>> +      *
>> +      * As message only supports dword size, just assign it.
>> +      */
>> +
>> +     /* Check for sync query */
>> +     if (ctx->resp_pending &&
>> +         ((SLIMPRO_MSG_TYPE(((u32 *) msg)[0]) == SLIMPRO_MSG_TYPE_ERR_ID) ||
>> +          (SLIMPRO_MSG_TYPE(((u32 *) msg)[0]) == SLIMPRO_MSG_TYPE_DBG_ID &&
>> +           SLIMPRO_MSG_SUBTYPE(((u32 *) msg)[0]) == SLIMPRO_DBG_SUBTYPE_SENSOR_READ) ||
>> +          (SLIMPRO_MSG_TYPE(((u32 *) msg)[0]) == SLIMPRO_MSG_TYPE_PWRMGMT_ID &&
>> +           SLIMPRO_MSG_SUBTYPE(((u32 *) msg)[0]) == SLIMPRO_PWRMGMT_SUBTYPE_TPC &&
>> +           SLIMPRO_TPC_CMD(((u32 *) msg)[0]) == SLIMPRO_TPC_ALARM))) {
>> +             if (ACPI_COMPANION(ctx->dev)) {
>> +                     /* Check if platform completes command */
>> +                     if (!xgene_word_tst_and_clr(&generic_comm_base->status,
>> +                                                 PCCS_CMD_COMPLETE))
>> +                             goto notify;
>
> How about reversing the logic here and dropping the goto ?

OK,

>
> Overall, I have to say that the code is quite complex due to the repeated
> checks for ACPI. I am close to suggest having two separate drivers,
> one for ACPI and one for non-ACPI. Any chance to separate ACPI vs. non-ACPI
> code a bit better ?

How about create separate rx_cb functions for ACPI and non-ACPI ?
As almost functions are the same between ACPI and non-ACPI, I thought
keep the same driver is still OK, isn't it ?

>
>> +             }
>> +             ctx->sync_msg.msg = ((u32 *) msg)[0];
>> +             ctx->sync_msg.param1 = ((u32 *) msg)[1];
>> +             ctx->sync_msg.param2 = ((u32 *) msg)[2];
>> +
>> +             /* Operation waiting for response */
>> +             complete(&ctx->rd_complete);
>> +
>> +             return;
>> +     }
>> +
>> +     /*
>> +      * If PCC, platform notifies interrupt to OSPM.
>> +      * OPSM schedules a consumer command to get this information
>> +      * in a workqueue. Platform must wait until OSPM has issued
>> +      * a consumer command that serves this notification.
>> +      */
>> +notify:
>> +     if (ACPI_COMPANION(ctx->dev)) {
>> +             /* Check and clear Platform Notification bit */
>> +             if (!xgene_word_tst_and_clr(&generic_comm_base->status,
>> +                                         PCCS_PLATFORM_NOTIFICATION))
>> +                     return;
>> +     } else {
>> +             amsg.msg   = ((u32 *) msg)[0];
>> +             amsg.param1 = ((u32 *) msg)[1];
>> +             amsg.param2 = ((u32 *) msg)[2];
>> +     }
>> +
>> +     /* Enqueue to the FIFO */
>> +     kfifo_in_spinlocked(&ctx->async_msg_fifo, &amsg,
>> +                         sizeof(struct slimpro_resp_msg), &ctx->lock);
>> +     /* Schedule the bottom handler */
>> +     schedule_work(&ctx->workq);
>> +}
>> +
>> +static void xgene_hwmon_tx_done(struct mbox_client *cl, void *msg, int ret)
>> +{
>> +     if (ret) {
>> +             dev_dbg(cl->dev, "TX did not complete: CMD sent:%x, ret:%d\n",
>> +                     *(u16 *) msg, ret);
>> +     } else {
>> +             dev_dbg(cl->dev, "TX completed. CMD sent:%x, ret:%d\n",
>> +                     *(u16 *) msg, ret);
>> +     }
>> +}
>> +
>> +static int __init xgene_hwmon_probe(struct platform_device *pdev)
>> +{
>> +     struct xgene_hwmon_dev *ctx;
>> +     struct mbox_client *cl;
>> +     int rc;
>> +
>> +     ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
>> +     if (!ctx)
>> +             return -ENOMEM;
>> +
>> +     ctx->dev = &pdev->dev;
>> +     platform_set_drvdata(pdev, ctx);
>> +     cl = &ctx->mbox_client;
>> +
>> +     /* Request mailbox channel */
>> +     cl->dev = &pdev->dev;
>> +     cl->rx_callback = xgene_hwmon_rx_cb;
>> +     cl->tx_done = xgene_hwmon_tx_done;
>> +     cl->tx_block = false;
>> +     cl->tx_tout = MBOX_OP_TIMEOUTMS;
>> +     cl->knows_txdone = false;
>> +     if (!ACPI_COMPANION(cl->dev)) {
>> +             ctx->mbox_chan = mbox_request_channel(cl, MBOX_HWMON_INDEX);
>> +             if (IS_ERR(ctx->mbox_chan)) {
>> +                     dev_err(&pdev->dev,
>> +                             "SLIMpro mailbox channel request failed\n");
>> +                     return PTR_ERR(ctx->mbox_chan);
>> +             }
>> +     } else {
>> +             struct acpi_pcct_hw_reduced *cppc_ss;
>> +
>> +             ctx->mbox_chan =
>> +                     pcc_mbox_request_channel(cl, SLIMPRO_MSG_PCC_SUBSPACE);
>> +             if (IS_ERR(ctx->mbox_chan)) {
>> +                     dev_err(&pdev->dev,
>> +                             "PPC channel request failed\n");
>> +                     return PTR_ERR(ctx->mbox_chan);
>> +             }
>> +
>> +             /*
>> +              * The PCC mailbox controller driver should
>> +              * have parsed the PCCT (global table of all
>> +              * PCC channels) and stored pointers to the
>> +              * subspace communication region in con_priv.
>> +              */
>> +             cppc_ss = ctx->mbox_chan->con_priv;
>> +             if (!cppc_ss) {
>> +                     dev_err(&pdev->dev, "PPC subspace not found\n");
>> +                     rc = -ENODEV;
>> +                     goto out_mbox_free;
>> +             }
>> +
>> +             if (!ctx->mbox_chan->mbox->txdone_irq) {
>> +                     dev_err(&pdev->dev, "PCC IRQ not supported\n");
>> +                     rc = -ENODEV;
>> +                     goto out_mbox_free;
>> +             }
>> +
>> +             /*
>> +              * This is the shared communication region
>> +              * for the OS and Platform to communicate over.
>> +              */
>> +             ctx->comm_base_addr = cppc_ss->base_address;
>> +             if (ctx->comm_base_addr) {
>> +                     ctx->pcc_comm_addr =
>> +                                     acpi_os_ioremap(ctx->comm_base_addr,
>> +                                                     cppc_ss->length);
>> +             } else {
>> +                     dev_err(&pdev->dev, "Failed to get PCC comm region\n");
>> +                     rc = -ENODEV;
>> +                     goto out_mbox_free;
>> +             }
>> +
>> +             if (!ctx->pcc_comm_addr) {
>> +                     dev_err(&pdev->dev,
>> +                             "Failed to ioremap PCC comm region\n");
>> +                     rc = -ENOMEM;
>> +                     goto out_mbox_free;
>> +             }
>> +
>> +             /*
>> +              * cppc_ss->latency is just a Nominal value. In reality
>> +              * the remote processor could be much slower to reply.
>> +              * So add an arbitrary amount of wait on top of Nominal.
>> +              */
>> +             ctx->usecs_lat = PCC_NUM_RETRIES * cppc_ss->latency;
>> +     }
>> +
>> +     spin_lock_init(&ctx->lock);
>> +
>> +     rc = kfifo_alloc(&ctx->async_msg_fifo,
>> +                      sizeof(struct slimpro_resp_msg) * ASYNC_MSG_FIFO_SIZE,
>> +                      GFP_KERNEL);
>> +     if (rc)
>> +             goto out_mbox_free;
>> +
>> +     INIT_WORK(&ctx->workq, xgene_hwmon_evt_work);
>> +
>> +     /* Hook up sysfs for sensor monitor */
>> +     rc = sysfs_create_group(&pdev->dev.kobj, &xgene_hwmon_attr_group);
>> +     if (rc) {
>> +             dev_err(&pdev->dev, "Fail to create sysfs\n");
>> +             goto out_kfifo_free;
>> +     }
>> +
>> +     ctx->hwmon_dev = hwmon_device_register(ctx->dev);
>> +     if (IS_ERR(ctx->hwmon_dev)) {
>> +             dev_err(&pdev->dev, "Failed to register HW monitor device\n");
>> +             rc = PTR_ERR(ctx->hwmon_dev);
>> +             goto out;
>> +     }
>
> Please use hwmon_device_register_with_groups().

OK,

Thanks and Regards
Hoan
>
>> +
>> +     dev_info(&pdev->dev, "APM X-Gene SoC HW monitor driver registered\n");
>> +
>> +     return rc;
>> +
>> +out:
>> +     sysfs_remove_group(&pdev->dev.kobj, &xgene_hwmon_attr_group);
>> +out_kfifo_free:
>> +     kfifo_free(&ctx->async_msg_fifo);
>> +out_mbox_free:
>> +     mbox_free_channel(ctx->mbox_chan);
>> +
>> +     return rc;
>> +}
>> +
>> +static int xgene_hwmon_remove(struct platform_device *pdev)
>> +{
>> +     struct xgene_hwmon_dev *ctx = platform_get_drvdata(pdev);
>> +
>> +     hwmon_device_unregister(ctx->hwmon_dev);
>> +     sysfs_remove_group(&pdev->dev.kobj, &xgene_hwmon_attr_group);
>> +     kfifo_free(&ctx->async_msg_fifo);
>> +     mbox_free_channel(ctx->mbox_chan);
>> +
>> +     return 0;
>> +}
>> +
>> +#ifdef CONFIG_ACPI
>> +static const struct acpi_device_id xgene_hwmon_acpi_match[] = {
>> +     {"APMC0D29", 0},
>> +     {},
>> +};
>> +MODULE_DEVICE_TABLE(acpi, xgene_hwmon_acpi_match);
>> +#endif
>> +
>> +static const struct of_device_id xgene_hwmon_of_match[] = {
>> +     {.compatible = "apm,xgene-slimpro-hwmon"},
>> +     {}
>> +};
>> +MODULE_DEVICE_TABLE(of, xgene_hwmon_of_match);
>> +
>> +static struct platform_driver xgene_hwmon_driver __refdata = {
>> +     .probe = xgene_hwmon_probe,
>> +     .remove = xgene_hwmon_remove,
>> +     .driver = {
>> +             .name = "xgene-slimpro-hwmon",
>> +             .of_match_table = xgene_hwmon_of_match,
>> +             .acpi_match_table = ACPI_PTR(xgene_hwmon_acpi_match),
>> +     },
>> +};
>> +module_platform_driver(xgene_hwmon_driver);
>> +
>> +MODULE_DESCRIPTION("APM X-Gene SoC hardware monitor");
>> +MODULE_LICENSE("GPL");


From wangkefeng.wang at huawei.com  Tue May 31 23:06:15 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:06:15 +0800
Subject: [PATCH v2] of: iommu: make of_iommu_init() postcore_initcall_sync
Message-ID: <1464761175-22677-1-git-send-email-wangkefeng.wang@huawei.com>

The of_iommu_init() is called multiple times by arch code,
make it postcore_initcall_sync, then we can drop relevant
calls fully.

Note, the IOMMUs should have a chance to perform some basic
initialisation before we start adding masters to them. So
postcore_initcall_sync is good choice, it ensures of_iommu_init()
called before of_platform_populate.

Acked-by: Rich Felker <dalias at libc.org>
Tested-by: Marek Szyprowski <m.szyprowski at samsung.com>
Cc: Arnd Bergmann <arnd at arndb.de>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Marek Szyprowski <m.szyprowski at samsung.com>
Cc: Rich Felker <dalias at libc.org>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Robin Murphy <robin.murphy at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---

Change since v1:
- Rebase to v4.7-rc1
- Add ack/test

 arch/arm/kernel/setup.c     | 2 --
 arch/arm64/kernel/setup.c   | 2 --
 arch/sh/boards/of-generic.c | 2 --
 drivers/iommu/of_iommu.c    | 5 ++++-
 include/linux/of_iommu.h    | 2 --
 5 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 7b53500..7e455339 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -19,7 +19,6 @@
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
 #include <linux/screen_info.h>
-#include <linux/of_iommu.h>
 #include <linux/of_platform.h>
 #include <linux/init.h>
 #include <linux/kexec.h>
@@ -903,7 +902,6 @@ static int __init customize_machine(void)
 	 * machine from the device tree, if no callback is provided,
 	 * otherwise we would always need an init_machine callback.
 	 */
-	of_iommu_init();
 	if (machine_desc->init_machine)
 		machine_desc->init_machine();
 #ifdef CONFIG_OF
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 3279def..8412520 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -39,7 +39,6 @@
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
 #include <linux/memblock.h>
-#include <linux/of_iommu.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 #include <linux/efi.h>
@@ -305,7 +304,6 @@ void __init setup_arch(char **cmdline_p)
 static int __init arm64_device_init(void)
 {
 	if (of_have_populated_dt()) {
-		of_iommu_init();
 		of_platform_populate(NULL, of_default_bus_match_table,
 				     NULL, NULL);
 	} else if (acpi_disabled) {
diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c
index bf3a166..b4d4313 100644
--- a/arch/sh/boards/of-generic.c
+++ b/arch/sh/boards/of-generic.c
@@ -11,7 +11,6 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_fdt.h>
-#include <linux/of_iommu.h>
 #include <linux/clocksource.h>
 #include <linux/irqchip.h>
 #include <linux/clk-provider.h>
@@ -185,7 +184,6 @@ static int __init sh_of_device_init(void)
 {
 	pr_info("SH generic board support: populating platform devices\n");
 	if (of_have_populated_dt()) {
-		of_iommu_init();
 		of_platform_populate(NULL, of_default_bus_match_table,
 				     NULL, NULL);
 	} else {
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index af499ae..57f23ea 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -174,7 +174,7 @@ err_put_node:
 	return NULL;
 }
 
-void __init of_iommu_init(void)
+static int __init of_iommu_init(void)
 {
 	struct device_node *np;
 	const struct of_device_id *match, *matches = &__iommu_of_table;
@@ -186,4 +186,7 @@ void __init of_iommu_init(void)
 			pr_err("Failed to initialise IOMMU %s\n",
 				of_node_full_name(np));
 	}
+
+	return 0;
 }
+postcore_initcall_sync(of_iommu_init);
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index bd02b44..e80b9c7 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -11,7 +11,6 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
 			     int index, unsigned long *busno, dma_addr_t *addr,
 			     size_t *size);
 
-extern void of_iommu_init(void);
 extern const struct iommu_ops *of_iommu_configure(struct device *dev,
 					struct device_node *master_np);
 
@@ -24,7 +23,6 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
 	return -EINVAL;
 }
 
-static inline void of_iommu_init(void) { }
 static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
 					 struct device_node *master_np)
 {
-- 
1.7.12.4



From k.kozlowski at samsung.com  Tue May 31 23:08:11 2016
From: k.kozlowski at samsung.com (Krzysztof Kozlowski)
Date: Wed, 01 Jun 2016 08:08:11 +0200
Subject: [RFC v2] dma-mapping: Use unsigned long for dma_attrs
In-Reply-To: <20160531181533.GD11300@char.us.oracle.com>
References: <1464609246-6948-1-git-send-email-k.kozlowski@samsung.com>
 <1464609246-6948-2-git-send-email-k.kozlowski@samsung.com>
 <20160531181533.GD11300@char.us.oracle.com>
Message-ID: <574E7BCB.6040505@samsung.com>

On 05/31/2016 08:15 PM, Konrad Rzeszutek Wilk wrote:
> On Mon, May 30, 2016 at 01:54:06PM +0200, Krzysztof Kozlowski wrote:
>> The dma-mapping core and the implementations do not change the
>> DMA attributes passed by pointer.  Thus the pointer can point to const
>> data.  However the attributes do not have to be a bitfield. Instead
>> unsigned long will do fine:
>>
>> 1. This is just simpler.  Both in terms of reading the code and setting
>>    attributes.  Instead of initializing local attributes on the stack and
>>    passing pointer to it to dma_set_attr(), just set the bits.
>>
>> 2. It brings safeness and checking for const correctness because the
>>    attributes are passed by value.
> 
> 
> .. why not go the next step a do an enum? Perhaps that should be mentioned
> as part of the description?

These are additive flags so to me this would look a little bit weird:
enum dma_attr {
	DMA_ATTR_WRITE_BARRIER	= 0x1,
	DMA_ATTR_WEAK_ORDERING	= 0x2,
	DMA_ATTR_WRITE_COMBINE	= 0x4,
	DMA_ATTR_NON_CONSISTENT	= 0x8,
	...
}

It doesn't really look like enumeration.

Best regards,
Krzysztof


From daniel.lezcano at linaro.org  Tue May 31 23:16:41 2016
From: daniel.lezcano at linaro.org (Daniel Lezcano)
Date: Wed, 1 Jun 2016 08:16:41 +0200
Subject: [PATCH 4/5] clocksource: rockchip: add support for rk3399 SoC
In-Reply-To: <574E4130.8090600@rock-chips.com>
References: <1464169802-6033-1-git-send-email-wxt@rock-chips.com>
 <1464169802-6033-5-git-send-email-wxt@rock-chips.com>
 <574CCCB4.1030001@linaro.org> <574D95AF.2020905@rock-chips.com>
 <574D9A66.4090209@linaro.org> <574E4130.8090600@rock-chips.com>
Message-ID: <574E7DC9.4000102@linaro.org>

On 06/01/2016 03:58 AM, Huang, Tao wrote:
> Hi Daniel:
> On 2016?05?31? 22:06, Daniel Lezcano wrote:

[ ... ]

>>> -CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init);
>>> +static void __init rk3288_timer_init(struct device_node *np)
>>> +{
>>> +	bc_timer.ctrl = TIMER_CONTROL_REG3288;
>>> +	rk_timer_init(np);
>>
>> 	rk_timer_init(np);
>> 	bc_timer.ctrl = bc_timer.base + TIMER_CONTROL_REG3288;
>
> No. It's not such simple. You will access null pointer when
> rk_timer_init, if we keep rk_timer_disable call in init or after
> request_irq/clockevents_config_and_register and interrupt happen
> immediately.
>
> So the code maybe:
> static void __init rk3288_timer_init(struct device_node *np)
> {
> 	bc_timer.base = of_iomap(np, 0);
> 	if (!bc_timer.base) {
> 		pr_err("Failed to get base address for '%s'\n", TIMER_NAME);
> 		return;
> 	}
> 	bc_timer.ctrl = bc_timer.base + TIMER_CONTROL_REG3288;
> 	rk_imter_init(np); // of course remove of_iomap from init.
>
> Is this what you want?

Not necessarily. There are plenty of variants.

eg. rk_timer_init(np, TIMER_CONTROL_REG3288);



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

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



From p.zabel at pengutronix.de  Tue May 31 23:27:33 2016
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Wed, 01 Jun 2016 08:27:33 +0200
Subject: [PATCH v2] reset: Return -ENOTSUPP when not configured
In-Reply-To: <2b8732d98087e52edec39ec83a063912fcc23962.1464738402.git.johnyoun@synopsys.com>
References: <2b8732d98087e52edec39ec83a063912fcc23962.1464738402.git.johnyoun@synopsys.com>
Message-ID: <1464762453.3522.0.camel@pengutronix.de>

Hi John,

Am Dienstag, den 31.05.2016, 16:55 -0700 schrieb John Youn:
> Prior to commit 6c96f05c8bb8 ("reset: Make [of_]reset_control_get[_foo]
> functions wrappers"), the "optional" functions returned -ENOTSUPP when
> CONFIG_RESET_CONTROLLER was not set.
> 
> Revert back to the old behavior by changing the new
> __devm_reset_control_get() and __of_reset_control_get() functions to
> return ERR_PTR(-ENOTSUPP) when compiled without CONFIG_RESET_CONTROLLER.
> 
> Otherwise they will return -EINVAL causing users to think that an error
> occurred when CONFIG_RESET_CONTROLLER is not set.
> 
> Fixes: 6c96f05c8bb8 ("reset: Make [of_]reset_control_get[_foo] functions wrappers")
> Signed-off-by: John Youn <johnyoun at synopsys.com>
> ---
> 
> Hi Philipp,
> 
> Here are the changes as discussed previously. It just returns
> -ENOTSUPP directly when not configured. Tested and works with DWC2
> driver with Dinh's patch that adds the reset controller, using a
> configuration with no reset controller configured.

Thank you, I've applied the patch to my reset/next branch.

regards
Philipp



From yamada.masahiro at socionext.com  Tue May 31 23:30:03 2016
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Wed, 1 Jun 2016 15:30:03 +0900
Subject: [PATCH] ARM: uniphier: drop code for old DT binding
In-Reply-To: <4992506.m4GEHIOqdc@wuerfel>
References: <1464682628-12163-1-git-send-email-yamada.masahiro@socionext.com>
 <4992506.m4GEHIOqdc@wuerfel>
Message-ID: <CAK7LNAT0n=VdfOmZ0dHaoVbD9jEsa16tY__9sVkuuuStMYA7WA@mail.gmail.com>

Hi Arnd.

2016-05-31 18:21 GMT+09:00 Arnd Bergmann <arnd at arndb.de>:
> On Tuesday, May 31, 2016 5:17:08 PM CEST Masahiro Yamada wrote:
>> Commit 307d40c56b0c ("ARM: uniphier: rework SMP code to support new
>> System Bus binding") added a new DT binding for SMP code, but still
>> kept old code for the backward compatibility.
>>
>> Linux 4.6 was out with both bindings supported, so it should not
>> hurt to drop the old code now.
>>
>> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
>>
>
> That explanation is in general not sufficient. Are you sure that
> nobody is shipping a machine with their own dts file that is not
> merged upstream, and that there are no bootloaders that have a
> hardcoded dtb file that we need to support indefinitely?
>

I have to confess that almost no one (except me) uses this upstreamed
code directly.
It can boot, but it is almost useless for practical uses (at least for
production level)
because it still lacks lots of drivers.

Our products based on ARM 32bit SoCs were shipped with old kernel
(without device tree) that were never upstreamed.

Socionext is now trying to change the development procedure
and the situation will be much better for ARM64 SoC products; it will be
more community-based development, although they are not shipped yet.

So, the answer is,  nobody is shipping ARM32 products using this upstream code.
Device Tree is not used in the first place.
(But, I still believe I should keep upstreaming.)


-- 
Best Regards
Masahiro Yamada


From wangkefeng.wang at huawei.com  Tue May 31 23:42:19 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:42:19 +0800
Subject: [PATCH] drivers: char: mem: Check {read,write}_kmem() addresses
In-Reply-To: <574D9448.7080206@arm.com>
References: <5e293c103f0a86f512d71f17091a55e9746e711f.1464698496.git.robin.murphy@arm.com>
 <20160531130821.GV19428@n2100.arm.linux.org.uk> <574D9448.7080206@arm.com>
Message-ID: <574E83CB.5040404@huawei.com>



On 2016/5/31 21:40, Robin Murphy wrote:
> On 31/05/16 14:08, Russell King - ARM Linux wrote:
>> On Tue, May 31, 2016 at 01:52:45PM +0100, Robin Murphy wrote:
>>> Arriving at read_kmem() with an offset representing a bogus kernel
>>> address (e.g. 0 from a simple "cat /dev/kmem") leads to copy_to_user
>>> faulting on the kernel-space read.
>>>
>>> x86_64 happens to get away with this since the optimised implementation
>>> uses "rep movs*", thus the user write (which is allowed to fault) and
>>> the kernel read are the same instruction, the kernel-side fault falls
>>> into the userspace fixup handler and a chain of events transpires
>>> leading to returning the expected -EFAULT. On other architectures,
>>> though, the read is not covered by the fixup entry for the write, and we
>>> get a straightforward "Unable to hande kernel paging request..." dump.
>>>
>>> The more typical use-case of mmap_kmem() already validates the address
>>> with pfn_valid() as one might expect, so let's make that consistent
>>> across {read,write}_kem() too.
>>>
>>> Reported-by: Kefeng Wang <wangkefeng.wang at huawei.com>
>>> Signed-off-by: Robin Murphy <robin.murphy at arm.com>
>>> ---
>>>
>>> I'm not sure if this warrants going to stable or not, as it's really
>>> just making an existing failure case more graceful and less confusing.
>>
>> Returning -EFAULT because the kernel-side address (iow, file offset) is
>> invalid is not particularly nice:
>>
>> NAME
>>         read - read from a file descriptor
>>
>> ERRORS
>>         EFAULT buf is outside your accessible address space.
>>
>> Latest POSIX has:
>>
>> ENXIO
>>     A request was made of a nonexistent device, or the
>>     request was outside the capabilities of the device.
>>
>> which to me looks like a better error code to return, as file offsets
>> which are not valid can be interpreted as being "outside the
>> capabilities of the device".  EFAULT has always on Linux meant that
>> the user passed an invalid userspace buffer.
> 
> Good point - seems I failed to twig that the error code in the x86 case is still effectively falling out of the "fault with the user address" path. ENXIO indeed sounds more reasonable, thanks.

Hi Robin, thanks for you fix, return -EIO like mmap_kmem() is better to me.

BRs,
Kefeng


> 
> Robin.
> 
> .
> 



From wangkefeng.wang at huawei.com  Tue May 31 23:52:54 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:52:54 +0800
Subject: [PATCH v5 01/18] of/platform: Add common method to populate default
 bus
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-2-git-send-email-wangkefeng.wang@huawei.com>

The arch code calls of_platform_populate() with default match table
when it wants to populate default bus.

This patch introduce a new of_platform_default_populate_init() and make it
arch_initcall_sync(it should be later than some iommu configration, eg,
of_iommu_init() and swiotlb_late_init in arm64), then we can finish above
job in common method.

In order to avoid the default bus being populated twice, simply checking
the flag of bus node whether has be set OF_POPULATED_BUS or not.

After that, we can safely remove the caller in arch code.

Btw, add debug print in of_platform_populate(), and use __func__ to
print function's name of of_platform_bus_create().

Cc: Rob Herring <robh+dt at kernel.org>
Cc: Frank Rowand <frowand.list at gmail.com>
Cc: Grant Likely <grant.likely at linaro.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/of/platform.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 16e8daf..c559ef8 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -363,6 +363,12 @@ static int of_platform_bus_create(struct device_node *bus,
 		return 0;
 	}
 
+	if (of_node_check_flag(bus, OF_POPULATED_BUS)) {
+		pr_debug("%s() - skipping %s, already populated\n",
+			__func__, bus->full_name);
+		return 0;
+	}
+
 	auxdata = of_dev_lookup(lookup, bus);
 	if (auxdata) {
 		bus_id = auxdata->name;
@@ -414,7 +420,7 @@ int of_platform_bus_probe(struct device_node *root,
 	if (!root)
 		return -EINVAL;
 
-	pr_debug("of_platform_bus_probe()\n");
+	pr_debug("%s()\n", __func__);
 	pr_debug(" starting at: %s\n", root->full_name);
 
 	/* Do a self check of bus type, if there's a match, create children */
@@ -466,6 +472,9 @@ int of_platform_populate(struct device_node *root,
 	if (!root)
 		return -EINVAL;
 
+	pr_debug("%s()\n", __func__);
+	pr_debug(" starting at: %s\n", root->full_name);
+
 	for_each_child_of_node(root, child) {
 		rc = of_platform_bus_create(child, matches, lookup, parent, true);
 		if (rc) {
@@ -489,6 +498,15 @@ int of_platform_default_populate(struct device_node *root,
 }
 EXPORT_SYMBOL_GPL(of_platform_default_populate);
 
+static int __init of_platform_default_populate_init(void)
+{
+	if (of_have_populated_dt())
+		of_platform_default_populate(NULL, NULL, NULL);
+
+	return 0;
+}
+arch_initcall_sync(of_platform_default_populate_init);
+
 static int of_platform_device_destroy(struct device *dev, void *data)
 {
 	/* Do not touch devices not populated from the device tree */
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:52:53 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:52:53 +0800
Subject: [PATCH v5 00/18] Cleanup for populate default bus
Message-ID: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>

This cleanup patchset cantains two parts.

Firstly, introduce a new way to populate the default bus, then, we can
drop unnecessary calls from the arch code, and do the same thing for
of_iommu_init() in [1].

Secondly, use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with default
match table, After that, it is possible for driver code build as a module,
and no need to export of_default_bus_match_table anymore.

This patchset is based on Linux 4.7-rc1, and only test in arm/arm64 qemu
with defconfig.

Changes since v4:
- Rebase to v4.7-rc1
- Remove pointless msg when acpi_disabled, sugguested by Rob Herring

Changes since v3:
- Get rid of by making of_platform_populate callable multiple times,
  sugguested by Rob Herring

Changes since v2:
- Add more acks
- Update based on v4.6-rc2, of-generic.c in sh and board-artpec6.c in arm
  are considered

Changes since v1:
- Add ack, test and review
- Remove v1 patch 14/15, the similar patch has posted and applied,
  see https://patchwork.kernel.org/patch/8096991/

v1:
- https://lkml.org/lkml/2016/1/26/1123

[1]: 
- v1: https://lkml.org/lkml/2016/4/23/31
- v2: https://lkml.org/lkml/2016/6/1/43

Kefeng Wang (18):
  of/platform: Add common method to populate default bus
  arc: Remove unnecessary of_platform_populate with default match table
  arm: Remove unnecessary of_platform_populate with default match table
  arm64: Remove unnecessary of_platform_populate with default match
    table
  c6x: Remove unnecessary of_platform_populate with default match table
  cris: Remove unnecessary of_platform_populate with default match
    table
  metag: Remove unnecessary of_platform_populate with default match
    table
  mips: Remove unnecessary of_platform_populate with default match
    table
  nios2: Remove unnecessary of_platform_populate with default match
    table
  sh: Remove unnecessary of_platform_populate with default match table
  xtensa: Remove unnecessary of_platform_populate with default match
    table
  arm: use of_platform_default_populate() to populate
  mips: use of_platform_default_populate() to populate default bus
  bus: imx-weim: use of_platform_default_populate() to populate default
    bus
  bus: uniphier-system-bus: use of_platform_default_populate() to
    populate default bus
  memory: omap-gpmc: use of_platform_default_populate() to populate
    default bus
  of: unittest: use of_platform_default_populate() to populate default
    bus
  Revert "of/platform: export of_default_bus_match_table"

 arch/arc/kernel/setup.c                  |  7 -------
 arch/arm/kernel/setup.c                  |  6 +-----
 arch/arm/mach-artpec/board-artpec6.c     |  3 ---
 arch/arm/mach-at91/at91rm9200.c          |  2 +-
 arch/arm/mach-at91/at91sam9.c            |  2 +-
 arch/arm/mach-at91/sama5.c               |  2 +-
 arch/arm/mach-bcm/board_bcm21664.c       |  2 --
 arch/arm/mach-bcm/board_bcm281xx.c       |  2 --
 arch/arm/mach-bcm/board_bcm2835.c        | 10 ----------
 arch/arm/mach-cns3xxx/core.c             |  3 +--
 arch/arm/mach-exynos/exynos.c            |  3 ---
 arch/arm/mach-highbank/highbank.c        |  3 ---
 arch/arm/mach-imx/mach-imx51.c           |  2 --
 arch/arm/mach-imx/mach-imx53.c           |  2 --
 arch/arm/mach-imx/mach-imx6q.c           |  2 +-
 arch/arm/mach-imx/mach-imx6sl.c          |  2 +-
 arch/arm/mach-imx/mach-imx6sx.c          |  2 +-
 arch/arm/mach-imx/mach-imx6ul.c          |  1 -
 arch/arm/mach-imx/mach-imx7d.c           |  1 -
 arch/arm/mach-integrator/integrator_ap.c |  3 +--
 arch/arm/mach-integrator/integrator_cp.c |  3 +--
 arch/arm/mach-keystone/keystone.c        |  1 -
 arch/arm/mach-lpc32xx/phy3250.c          |  3 +--
 arch/arm/mach-mvebu/board-v7.c           |  3 ---
 arch/arm/mach-mvebu/dove.c               |  2 --
 arch/arm/mach-mvebu/kirkwood.c           |  2 +-
 arch/arm/mach-mxs/mach-mxs.c             |  3 +--
 arch/arm/mach-nspire/nspire.c            |  3 +--
 arch/arm/mach-orion5x/board-dt.c         |  3 +--
 arch/arm/mach-picoxcell/common.c         |  2 --
 arch/arm/mach-rockchip/rockchip.c        |  1 -
 arch/arm/mach-s3c24xx/mach-s3c2416-dt.c  |  2 --
 arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c  |  3 ---
 arch/arm/mach-shmobile/setup-r8a7740.c   |  3 ---
 arch/arm/mach-shmobile/setup-sh73a0.c    |  2 --
 arch/arm/mach-spear/spear1310.c          |  2 --
 arch/arm/mach-spear/spear1340.c          |  1 -
 arch/arm/mach-spear/spear300.c           |  3 +--
 arch/arm/mach-spear/spear310.c           |  3 +--
 arch/arm/mach-spear/spear320.c           |  3 +--
 arch/arm/mach-spear/spear6xx.c           |  3 +--
 arch/arm/mach-tegra/tegra.c              |  2 +-
 arch/arm/mach-u300/core.c                |  3 +--
 arch/arm/mach-versatile/versatile_dt.c   |  3 +--
 arch/arm/mach-vt8500/vt8500.c            |  3 ---
 arch/arm/mach-zynq/common.c              |  2 +-
 arch/arm64/kernel/setup.c                | 13 -------------
 arch/c6x/platforms/Makefile              |  2 +-
 arch/c6x/platforms/platform.c            | 17 -----------------
 arch/cris/kernel/setup.c                 |  8 --------
 arch/metag/kernel/setup.c                |  5 +----
 arch/mips/ath79/setup.c                  |  3 ---
 arch/mips/jz4740/setup.c                 |  8 --------
 arch/mips/mti-sead3/sead3-setup.c        |  8 --------
 arch/mips/pic32/pic32mzda/init.c         |  3 +--
 arch/mips/pistachio/init.c               | 13 -------------
 arch/mips/xilfpga/init.c                 | 13 -------------
 arch/nios2/platform/platform.c           |  4 +---
 arch/sh/boards/of-generic.c              | 14 --------------
 arch/xtensa/kernel/setup.c               | 11 -----------
 arch/xtensa/kernel/time.c                |  2 ++
 drivers/bus/imx-weim.c                   |  5 ++---
 drivers/bus/uniphier-system-bus.c        |  3 +--
 drivers/memory/omap-gpmc.c               |  3 +--
 drivers/of/platform.c                    | 21 +++++++++++++++++++--
 drivers/of/unittest.c                    |  5 ++---
 66 files changed, 54 insertions(+), 231 deletions(-)
 delete mode 100644 arch/c6x/platforms/platform.c

-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:53:08 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:53:08 +0800
Subject: [PATCH v5 15/18] bus: uniphier-system-bus: use
 of_platform_default_populate() to populate default bus
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-16-git-send-email-wangkefeng.wang@huawei.com>

Use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with
the default match table.

Acked-by: Masahiro Yamada <yamada.masahiro at socionext.com>
Cc: Masahiro Yamada <yamada.masahiro at socionext.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/bus/uniphier-system-bus.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/bus/uniphier-system-bus.c b/drivers/bus/uniphier-system-bus.c
index 350b730..1e6e0269 100644
--- a/drivers/bus/uniphier-system-bus.c
+++ b/drivers/bus/uniphier-system-bus.c
@@ -257,8 +257,7 @@ static int uniphier_system_bus_probe(struct platform_device *pdev)
 	uniphier_system_bus_set_reg(priv);
 
 	/* Now, the bus is configured.  Populate platform_devices below it */
-	return of_platform_populate(dev->of_node, of_default_bus_match_table,
-				    NULL, dev);
+	return of_platform_default_populate(dev->of_node, NULL, dev);
 }
 
 static const struct of_device_id uniphier_system_bus_match[] = {
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:53:00 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:53:00 +0800
Subject: [PATCH v5 07/18] metag: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-8-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers of
of_platform_populate with default match table.

Cc: James Hogan <james.hogan at imgtec.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/metag/kernel/setup.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/arch/metag/kernel/setup.c b/arch/metag/kernel/setup.c
index 31cf53d..1166f1f 100644
--- a/arch/metag/kernel/setup.c
+++ b/arch/metag/kernel/setup.c
@@ -20,7 +20,6 @@
 #include <linux/memblock.h>
 #include <linux/mm.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <linux/pfn.h>
 #include <linux/root_dev.h>
 #include <linux/sched.h>
@@ -414,9 +413,7 @@ static int __init customize_machine(void)
 	/* customizes platform devices, or adds new ones */
 	if (machine_desc->init_machine)
 		machine_desc->init_machine();
-	else
-		of_platform_populate(NULL, of_default_bus_match_table, NULL,
-				     NULL);
+
 	return 0;
 }
 arch_initcall(customize_machine);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:53:11 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:53:11 +0800
Subject: [PATCH v5 18/18] Revert "of/platform: export
 of_default_bus_match_table"
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-19-git-send-email-wangkefeng.wang@huawei.com>

This reverts commit b80443c2211c7daaabd20fbbe9e7beb3fa3408e0.

After covering to use helper of_platform_default_populate() to populate
the default bus, no need to export of_default_bus_match_table anymore.

Reviewed-by: Masahiro Yamada <yamada.masahiro at socionext.com>
Cc: Masahiro Yamada <yamada.masahiro at socionext.com>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Frank Rowand <frowand.list at gmail.com>
Cc: Grant Likely <grant.likely at linaro.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/of/platform.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index c559ef8..153dbe1 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -31,7 +31,6 @@ const struct of_device_id of_default_bus_match_table[] = {
 #endif /* CONFIG_ARM_AMBA */
 	{} /* Empty terminated list */
 };
-EXPORT_SYMBOL(of_default_bus_match_table);
 
 static int of_dev_node_match(struct device *dev, void *data)
 {
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:52:58 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:52:58 +0800
Subject: [PATCH v5 05/18] c6x: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-6-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers of
of_platform_populate with default match table.

Cc: Mikael Starvik <starvik at axis.com>
Cc: Jesper Nilsson <jesper.nilsson at axis.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/c6x/platforms/Makefile   |  2 +-
 arch/c6x/platforms/platform.c | 17 -----------------
 2 files changed, 1 insertion(+), 18 deletions(-)
 delete mode 100644 arch/c6x/platforms/platform.c

diff --git a/arch/c6x/platforms/Makefile b/arch/c6x/platforms/Makefile
index 9a95b9b..5f7d934 100644
--- a/arch/c6x/platforms/Makefile
+++ b/arch/c6x/platforms/Makefile
@@ -4,7 +4,7 @@
 # Copyright 2010, 2011 Texas Instruments Incorporated
 #
 
-obj-y = platform.o cache.o megamod-pic.o pll.o plldata.o timer64.o
+obj-y = cache.o megamod-pic.o pll.o plldata.o timer64.o
 obj-y += dscr.o
 
 # SoC objects
diff --git a/arch/c6x/platforms/platform.c b/arch/c6x/platforms/platform.c
deleted file mode 100644
index 26c1a35..0000000
--- a/arch/c6x/platforms/platform.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2011 Texas Instruments Incorporated
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#include <linux/init.h>
-#include <linux/of_platform.h>
-
-static int __init c6x_device_probe(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	return 0;
-}
-core_initcall(c6x_device_probe);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:52:59 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:52:59 +0800
Subject: [PATCH v5 06/18] cris: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-7-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers of
of_platform_populate with default match table.

Acked-by: Jesper Nilsson <jesper.nilsson at axis.com>
Cc: Mikael Starvik <starvik at axis.com>
Cc: Jesper Nilsson <jesper.nilsson at axis.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/cris/kernel/setup.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index bb12aa9..4b4853d 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -21,7 +21,6 @@
 #include <linux/cpu.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <asm/setup.h>
 #include <arch/system.h>
 
@@ -212,10 +211,3 @@ static int __init topology_init(void)
 }
 
 subsys_initcall(topology_init);
-
-static int __init cris_of_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	return 0;
-}
-core_initcall(cris_of_init);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:53:01 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:53:01 +0800
Subject: [PATCH v5 08/18] mips: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-9-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers of
of_platform_populate with default match table.

Cc: Ralf Baechle <ralf at linux-mips.org>
Cc: Alban Bedel <albeu at free.fr>
Cc: Paul Burton <paul.burton at imgtec.com>
Cc: James Hogan <james.hogan at imgtec.com>
Cc: Joshua Henderson <joshua.henderson at microchip.com>
Cc: Zubair Lutfullah Kakakhel <Zubair.Kakakhel at imgtec.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/mips/ath79/setup.c           |  3 ---
 arch/mips/jz4740/setup.c          |  8 --------
 arch/mips/mti-sead3/sead3-setup.c |  8 --------
 arch/mips/pistachio/init.c        | 13 -------------
 arch/mips/xilfpga/init.c          | 13 -------------
 5 files changed, 45 deletions(-)

diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index 7adab18..8887eb1 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -17,8 +17,6 @@
 #include <linux/bootmem.h>
 #include <linux/err.h>
 #include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/of_platform.h>
 #include <linux/of_fdt.h>
 
 #include <asm/bootinfo.h>
@@ -285,7 +283,6 @@ void __init plat_time_init(void)
 
 static int __init ath79_setup(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	if  (mips_machtype == ATH79_MACH_GENERIC_OF)
 		return 0;
 
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index 510fc0d..0914ef7 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -20,7 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/libfdt.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 
 #include <asm/bootinfo.h>
 #include <asm/prom.h>
@@ -74,13 +73,6 @@ void __init device_tree_init(void)
 	unflatten_and_copy_device_tree();
 }
 
-static int __init populate_machine(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	return 0;
-}
-arch_initcall(populate_machine);
-
 const char *get_system_type(void)
 {
 	if (config_enabled(CONFIG_MACH_JZ4780))
diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c
index 9f2f9b2..edfcaf0 100644
--- a/arch/mips/mti-sead3/sead3-setup.c
+++ b/arch/mips/mti-sead3/sead3-setup.c
@@ -8,7 +8,6 @@
  */
 #include <linux/init.h>
 #include <linux/libfdt.h>
-#include <linux/of_platform.h>
 #include <linux/of_fdt.h>
 
 #include <asm/prom.h>
@@ -107,10 +106,3 @@ void __init device_tree_init(void)
 
 	unflatten_and_copy_device_tree();
 }
-
-static int __init customize_machine(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	return 0;
-}
-arch_initcall(customize_machine);
diff --git a/arch/mips/pistachio/init.c b/arch/mips/pistachio/init.c
index ab79828..c50a670 100644
--- a/arch/mips/pistachio/init.c
+++ b/arch/mips/pistachio/init.c
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 
 #include <asm/cacheflush.h>
 #include <asm/dma-coherence.h>
@@ -159,15 +158,3 @@ void __init device_tree_init(void)
 
 	unflatten_and_copy_device_tree();
 }
-
-static int __init plat_of_setup(void)
-{
-	if (!of_have_populated_dt())
-		panic("Device tree not present");
-
-	if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL))
-		panic("Failed to populate DT");
-
-	return 0;
-}
-arch_initcall(plat_of_setup);
diff --git a/arch/mips/xilfpga/init.c b/arch/mips/xilfpga/init.c
index ce2aee2..602e384 100644
--- a/arch/mips/xilfpga/init.c
+++ b/arch/mips/xilfpga/init.c
@@ -10,7 +10,6 @@
  */
 
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 
 #include <asm/prom.h>
 
@@ -43,15 +42,3 @@ void __init device_tree_init(void)
 
 	unflatten_and_copy_device_tree();
 }
-
-static int __init plat_of_setup(void)
-{
-	if (!of_have_populated_dt())
-		panic("Device tree not present");
-
-	if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL))
-		panic("Failed to populate DT");
-
-	return 0;
-}
-arch_initcall(plat_of_setup);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:52:57 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:52:57 +0800
Subject: [PATCH v5 04/18] arm64: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-5-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers of
of_platform_populate with default match table.

Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Will Deacon <will.deacon at arm.com>
Cc: Arnd Bergmann <arnd at arndb.de>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/arm64/kernel/setup.c | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 8412520..c907e2f 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -40,7 +40,6 @@
 #include <linux/proc_fs.h>
 #include <linux/memblock.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <linux/efi.h>
 #include <linux/psci.h>
 
@@ -301,18 +300,6 @@ void __init setup_arch(char **cmdline_p)
 	}
 }
 
-static int __init arm64_device_init(void)
-{
-	if (of_have_populated_dt()) {
-		of_platform_populate(NULL, of_default_bus_match_table,
-				     NULL, NULL);
-	} else if (acpi_disabled) {
-		pr_crit("Device tree not populated\n");
-	}
-	return 0;
-}
-arch_initcall_sync(arm64_device_init);
-
 static int __init topology_init(void)
 {
 	int i;
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:53:10 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:53:10 +0800
Subject: [PATCH v5 17/18] of: unittest: use of_platform_default_populate() to
 populate default bus
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-18-git-send-email-wangkefeng.wang@huawei.com>

Use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with
the default match table.

Cc: Rob Herring <robh+dt at kernel.org>
Cc: Frank Rowand <frowand.list at gmail.com>
Cc: Grant Likely <grant.likely at linaro.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/of/unittest.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index f34ed93..53c83d6 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -771,7 +771,7 @@ static void __init of_unittest_platform_populate(void)
 	};
 
 	np = of_find_node_by_path("/testcase-data");
-	of_platform_populate(np, of_default_bus_match_table, NULL, NULL);
+	of_platform_default_populate(np, NULL, NULL);
 
 	/* Test that a missing irq domain returns -EPROBE_DEFER */
 	np = of_find_node_by_path("/testcase-data/testcase-device1");
@@ -1871,8 +1871,7 @@ static void __init of_unittest_overlay(void)
 		goto out;
 	}
 
-	ret = of_platform_populate(bus_np, of_default_bus_match_table,
-			NULL, NULL);
+	ret = of_platform_default_populate(bus_np, NULL, NULL);
 	if (ret != 0) {
 		unittest(0, "could not populate bus @ \"%s\"\n", bus_path);
 		goto out;
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:52:55 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:52:55 +0800
Subject: [PATCH v5 02/18] arc: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-3-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers of
of_platform_populate with default match table.

Acked-by: Vineet Gupta <vgupta at synopsys.com>
Cc: Vineet Gupta <vgupta at synopsys.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/arc/kernel/setup.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index f63b8bf..59053c1 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/cpu.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <linux/cache.h>
 #include <asm/sections.h>
 #include <asm/arcregs.h>
@@ -435,12 +434,6 @@ void __init setup_arch(char **cmdline_p)
 
 static int __init customize_machine(void)
 {
-	/*
-	 * Traverses flattened DeviceTree - registering platform devices
-	 * (if any) complete with their resources
-	 */
-	of_platform_default_populate(NULL, NULL, NULL);
-
 	if (machine_desc->init_machine)
 		machine_desc->init_machine();
 
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:52:56 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:52:56 +0800
Subject: [PATCH v5 03/18] arm: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-4-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers of
of_platform_populate with default match table.

Acked-by: Viresh Kumar <viresh.kumar at linaro.org>
Cc: Nicolas Ferre <nicolas.ferre at atmel.com>
Cc: Ray Jui <rjui at broadcom.com>
Cc: Lee Jones <lee at kernel.org>
Cc: Krzysztof Halasa <khalasa at piap.pl>
Cc: Kukjin Kim <kgene at kernel.org>
Cc: Rob Herring <robh at kernel.org>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Santosh Shilimkar <ssantosh at kernel.org>
Cc: Roland Stigge <stigge at antcom.de>
Cc: Jason Cooper <jason at lakedaemon.net>
Cc: Haojian Zhuang <haojian.zhuang at gmail.com>
Cc: Heiko Stuebner <heiko at sntech.de>
Cc: Viresh Kumar <vireshk at kernel.org>
Cc: Shiraz Hashim <shiraz.linux.kernel at gmail.com>
Cc: Tony Prisk <linux at prisktech.co.nz>
Cc: Arnd Bergmann <arnd at arndb.de>
Cc: Russell King <linux at arm.linux.org.uk>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/arm/kernel/setup.c                 |  6 +-----
 arch/arm/mach-artpec/board-artpec6.c    |  3 ---
 arch/arm/mach-bcm/board_bcm21664.c      |  2 --
 arch/arm/mach-bcm/board_bcm281xx.c      |  2 --
 arch/arm/mach-bcm/board_bcm2835.c       | 10 ----------
 arch/arm/mach-exynos/exynos.c           |  3 ---
 arch/arm/mach-highbank/highbank.c       |  3 ---
 arch/arm/mach-imx/mach-imx51.c          |  2 --
 arch/arm/mach-imx/mach-imx53.c          |  2 --
 arch/arm/mach-imx/mach-imx6ul.c         |  1 -
 arch/arm/mach-imx/mach-imx7d.c          |  1 -
 arch/arm/mach-keystone/keystone.c       |  1 -
 arch/arm/mach-mvebu/board-v7.c          |  3 ---
 arch/arm/mach-mvebu/dove.c              |  2 --
 arch/arm/mach-picoxcell/common.c        |  2 --
 arch/arm/mach-rockchip/rockchip.c       |  1 -
 arch/arm/mach-s3c24xx/mach-s3c2416-dt.c |  2 --
 arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c |  3 ---
 arch/arm/mach-shmobile/setup-r8a7740.c  |  3 ---
 arch/arm/mach-shmobile/setup-sh73a0.c   |  2 --
 arch/arm/mach-spear/spear1310.c         |  2 --
 arch/arm/mach-spear/spear1340.c         |  1 -
 arch/arm/mach-vt8500/vt8500.c           |  3 ---
 23 files changed, 1 insertion(+), 59 deletions(-)

diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 7e455339..2273acb 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -904,11 +904,7 @@ static int __init customize_machine(void)
 	 */
 	if (machine_desc->init_machine)
 		machine_desc->init_machine();
-#ifdef CONFIG_OF
-	else
-		of_platform_populate(NULL, of_default_bus_match_table,
-					NULL, NULL);
-#endif
+
 	return 0;
 }
 arch_initcall(customize_machine);
diff --git a/arch/arm/mach-artpec/board-artpec6.c b/arch/arm/mach-artpec/board-artpec6.c
index 71513df..a0b1979 100644
--- a/arch/arm/mach-artpec/board-artpec6.c
+++ b/arch/arm/mach-artpec/board-artpec6.c
@@ -13,7 +13,6 @@
 #include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic.h>
 #include <linux/mfd/syscon.h>
-#include <linux/of_platform.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk-provider.h>
@@ -44,8 +43,6 @@ static void __init artpec6_init_machine(void)
 		regmap_write(regmap, ARTPEC6_DMACFG_REGNUM,
 			     ARTPEC6_DMACFG_UARTS_BURST);
 	};
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static void artpec6_l2c310_write_sec(unsigned long val, unsigned reg)
diff --git a/arch/arm/mach-bcm/board_bcm21664.c b/arch/arm/mach-bcm/board_bcm21664.c
index 82ad568..0d7034c 100644
--- a/arch/arm/mach-bcm/board_bcm21664.c
+++ b/arch/arm/mach-bcm/board_bcm21664.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/of_address.h>
-#include <linux/of_platform.h>
 #include <linux/io.h>
 
 #include <asm/mach/arch.h>
@@ -60,7 +59,6 @@ static void bcm21664_restart(enum reboot_mode mode, const char *cmd)
 
 static void __init bcm21664_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	kona_l2_cache_init();
 }
 
diff --git a/arch/arm/mach-bcm/board_bcm281xx.c b/arch/arm/mach-bcm/board_bcm281xx.c
index 2e367bd..b81bb38 100644
--- a/arch/arm/mach-bcm/board_bcm281xx.c
+++ b/arch/arm/mach-bcm/board_bcm281xx.c
@@ -13,7 +13,6 @@
 
 #include <linux/clocksource.h>
 #include <linux/of_address.h>
-#include <linux/of_platform.h>
 
 #include <asm/mach/arch.h>
 
@@ -58,7 +57,6 @@ static void bcm281xx_restart(enum reboot_mode mode, const char *cmd)
 
 static void __init bcm281xx_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	kona_l2_cache_init();
 }
 
diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c
index 834d676..0c1edfc 100644
--- a/arch/arm/mach-bcm/board_bcm2835.c
+++ b/arch/arm/mach-bcm/board_bcm2835.c
@@ -15,7 +15,6 @@
 #include <linux/init.h>
 #include <linux/irqchip.h>
 #include <linux/of_address.h>
-#include <linux/of_platform.h>
 #include <linux/clk/bcm2835.h>
 
 #include <asm/mach/arch.h>
@@ -23,16 +22,7 @@
 
 static void __init bcm2835_init(void)
 {
-	int ret;
-
 	bcm2835_init_clocks();
-
-	ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
-				   NULL);
-	if (ret) {
-		pr_err("of_platform_populate failed: %d\n", ret);
-		BUG();
-	}
 }
 
 static const char * const bcm2835_compat[] = {
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 52ccf24..dea410a 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -14,7 +14,6 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/irqchip.h>
 #include <linux/soc/samsung/exynos-regs-pmu.h>
@@ -217,8 +216,6 @@ static void __init exynos_dt_machine_init(void)
 	    of_machine_is_compatible("samsung,exynos3250") ||
 	    of_machine_is_compatible("samsung,exynos5250"))
 		platform_device_register(&exynos_cpuidle);
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static char const *const exynos_dt_compat[] __initconst = {
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index 6050a14..07f6098 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -23,7 +23,6 @@
 #include <linux/pl320-ipc.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
-#include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/reboot.h>
 #include <linux/amba/bus.h>
@@ -163,8 +162,6 @@ static void __init highbank_init(void)
 
 	pl320_ipc_register_notifier(&hb_keys_nb);
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-
 	if (psci_ops.cpu_suspend)
 		platform_device_register(&highbank_cpuidle_device);
 }
diff --git a/arch/arm/mach-imx/mach-imx51.c b/arch/arm/mach-imx/mach-imx51.c
index 10a82a4..ec64de6 100644
--- a/arch/arm/mach-imx/mach-imx51.c
+++ b/arch/arm/mach-imx/mach-imx51.c
@@ -52,8 +52,6 @@ static void __init imx51_dt_init(void)
 {
 	imx51_ipu_mipi_setup();
 	imx_src_init();
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static void __init imx51_init_late(void)
diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c
index 18b5c5c13..68aec23 100644
--- a/arch/arm/mach-imx/mach-imx53.c
+++ b/arch/arm/mach-imx/mach-imx53.c
@@ -32,8 +32,6 @@ static void __init imx53_dt_init(void)
 {
 	imx_src_init();
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-
 	imx_aips_allow_unprivileged_access("fsl,imx53-aipstz");
 }
 
diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c
index a38b16b..4078b1c 100644
--- a/arch/arm/mach-imx/mach-imx6ul.c
+++ b/arch/arm/mach-imx/mach-imx6ul.c
@@ -64,7 +64,6 @@ static void __init imx6ul_init_machine(void)
 	if (parent == NULL)
 		pr_warn("failed to initialize soc device\n");
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	imx6ul_enet_init();
 	imx_anatop_init();
 	imx6ul_pm_init();
diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c
index b450f52..f388e6b 100644
--- a/arch/arm/mach-imx/mach-imx7d.c
+++ b/arch/arm/mach-imx/mach-imx7d.c
@@ -93,7 +93,6 @@ static void __init imx7d_init_machine(void)
 	if (parent == NULL)
 		pr_warn("failed to initialize soc device\n");
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	imx_anatop_init();
 	imx7d_enet_init();
 }
diff --git a/arch/arm/mach-keystone/keystone.c b/arch/arm/mach-keystone/keystone.c
index a33a296..84613ab 100644
--- a/arch/arm/mach-keystone/keystone.c
+++ b/arch/arm/mach-keystone/keystone.c
@@ -60,7 +60,6 @@ static void __init keystone_init(void)
 		bus_register_notifier(&platform_bus_type, &platform_nb);
 	}
 	keystone_pm_runtime_init();
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static long long __init keystone_pv_fixup(void)
diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
index 1648edd..ccca951 100644
--- a/arch/arm/mach-mvebu/board-v7.c
+++ b/arch/arm/mach-mvebu/board-v7.c
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <linux/io.h>
 #include <linux/clocksource.h>
 #include <linux/dma-mapping.h>
@@ -144,8 +143,6 @@ static void __init mvebu_dt_init(void)
 {
 	if (of_machine_is_compatible("marvell,armadaxp"))
 		i2c_quirk();
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char * const armada_370_xp_dt_compat[] __initconst = {
diff --git a/arch/arm/mach-mvebu/dove.c b/arch/arm/mach-mvebu/dove.c
index 1aebb82..d076c57 100644
--- a/arch/arm/mach-mvebu/dove.c
+++ b/arch/arm/mach-mvebu/dove.c
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/mbus.h>
 #include <linux/of.h>
-#include <linux/of_platform.h>
 #include <linux/soc/dove/pmu.h>
 #include <asm/hardware/cache-tauros2.h>
 #include <asm/mach/arch.h>
@@ -26,7 +25,6 @@ static void __init dove_init(void)
 #endif
 	BUG_ON(mvebu_mbus_dt_init(false));
 	dove_init_pmu();
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char * const dove_dt_compat[] __initconst = {
diff --git a/arch/arm/mach-picoxcell/common.c b/arch/arm/mach-picoxcell/common.c
index ec79fea..4e3d6d5 100644
--- a/arch/arm/mach-picoxcell/common.c
+++ b/arch/arm/mach-picoxcell/common.c
@@ -10,7 +10,6 @@
 #include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/of_platform.h>
 #include <linux/reboot.h>
 
 #include <asm/mach/arch.h>
@@ -54,7 +53,6 @@ static void __init picoxcell_map_io(void)
 
 static void __init picoxcell_init_machine(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	picoxcell_setup_restart();
 }
 
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index beb71da..a7ab9ec 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -73,7 +73,6 @@ static void __init rockchip_timer_init(void)
 static void __init rockchip_dt_init(void)
 {
 	rockchip_suspend_init();
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char * const rockchip_board_dt_compat[] = {
diff --git a/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c b/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c
index 5f028ff..c83c076 100644
--- a/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c
+++ b/arch/arm/mach-s3c24xx/mach-s3c2416-dt.c
@@ -17,7 +17,6 @@
 
 #include <linux/clocksource.h>
 #include <linux/irqchip.h>
-#include <linux/of_platform.h>
 #include <linux/serial_s3c.h>
 
 #include <asm/mach/arch.h>
@@ -35,7 +34,6 @@ static void __init s3c2416_dt_map_io(void)
 
 static void __init s3c2416_dt_machine_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	s3c_pm_init();
 }
 
diff --git a/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c b/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
index bbf74ed..5bf9afa 100644
--- a/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
+++ b/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
@@ -8,8 +8,6 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/of_platform.h>
-
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
@@ -48,7 +46,6 @@ static void __init s3c64xx_dt_map_io(void)
 static void __init s3c64xx_dt_init_machine(void)
 {
 	samsung_wdt_reset_of_init();
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static void s3c64xx_dt_restart(enum reboot_mode mode, const char *cmd)
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index db6dbfb..3849eef 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -18,7 +18,6 @@
 #include <linux/io.h>
 #include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic.h>
-#include <linux/of_platform.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
@@ -77,8 +76,6 @@ static void __init r8a7740_init_irq_of(void)
 static void __init r8a7740_generic_init(void)
 {
 	r8a7740_meram_workaround();
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char *const r8a7740_boards_compat_dt[] __initconst = {
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index 99a2004..a25ff18 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/of_platform.h>
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/io.h>
@@ -55,7 +54,6 @@ static void __init sh73a0_generic_init(void)
 	/* Shared attribute override enable, 64K*8way */
 	l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
 #endif
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char *const sh73a0_boards_compat_dt[] __initconst = {
diff --git a/arch/arm/mach-spear/spear1310.c b/arch/arm/mach-spear/spear1310.c
index cd5d375..a7d4f13 100644
--- a/arch/arm/mach-spear/spear1310.c
+++ b/arch/arm/mach-spear/spear1310.c
@@ -14,7 +14,6 @@
 #define pr_fmt(fmt) "SPEAr1310: " fmt
 
 #include <linux/amba/pl022.h>
-#include <linux/of_platform.h>
 #include <linux/pata_arasan_cf_data.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -27,7 +26,6 @@
 
 static void __init spear1310_dt_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	platform_device_register_simple("spear-cpufreq", -1, NULL, 0);
 }
 
diff --git a/arch/arm/mach-spear/spear1340.c b/arch/arm/mach-spear/spear1340.c
index 94594d5..a212af9 100644
--- a/arch/arm/mach-spear/spear1340.c
+++ b/arch/arm/mach-spear/spear1340.c
@@ -19,7 +19,6 @@
 
 static void __init spear1340_dt_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	platform_device_register_simple("spear-cpufreq", -1, NULL, 0);
 }
 
diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c
index 3bc0dc9..773c04f 100644
--- a/arch/arm/mach-vt8500/vt8500.c
+++ b/arch/arm/mach-vt8500/vt8500.c
@@ -30,7 +30,6 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <linux/of_platform.h>
 
 #define LEGACY_GPIO_BASE	0xD8110000
 #define LEGACY_PMC_BASE		0xD8130000
@@ -158,8 +157,6 @@ static void __init vt8500_init(void)
 		pm_power_off = &vt8500_power_off;
 	else
 		pr_err("%s: PMC Hibernation register could not be remapped, not enabling power off!\n", __func__);
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char * const vt8500_dt_compat[] = {
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:53:09 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:53:09 +0800
Subject: [PATCH v5 16/18] memory: omap-gpmc: use
 of_platform_default_populate() to populate default bus
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-17-git-send-email-wangkefeng.wang@huawei.com>

Use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with
the default match table.

Acked-by: Roger Quadros <rogerq at ti.com>
Cc: Roger Quadros <rogerq at ti.com>
Cc: Tony Lindgren <tony at atomide.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/memory/omap-gpmc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index af4884b..4b1913a 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -2134,8 +2134,7 @@ no_timings:
 	/* is child a common bus? */
 	if (of_match_node(of_default_bus_match_table, child))
 		/* create children and other common bus children */
-		if (of_platform_populate(child, of_default_bus_match_table,
-					 NULL, &pdev->dev))
+		if (of_platform_default_populate(child, NULL, &pdev->dev))
 			goto err_child_fail;
 
 	return 0;
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:53:06 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:53:06 +0800
Subject: [PATCH v5 13/18] mips: use of_platform_default_populate() to populate
 default bus
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-14-git-send-email-wangkefeng.wang@huawei.com>

Use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with
the default match table.

Cc: Joshua Henderson <joshua.henderson at microchip.com>
Cc: Ralf Baechle <ralf at linux-mips.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/mips/pic32/pic32mzda/init.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/mips/pic32/pic32mzda/init.c b/arch/mips/pic32/pic32mzda/init.c
index 775ff90..77ecf32 100644
--- a/arch/mips/pic32/pic32mzda/init.c
+++ b/arch/mips/pic32/pic32mzda/init.c
@@ -147,8 +147,7 @@ static int __init plat_of_setup(void)
 		panic("Device tree not present");
 
 	pic32_of_prepare_platform_data(pic32_auxdata_lookup);
-	if (of_platform_populate(NULL, of_default_bus_match_table,
-				 pic32_auxdata_lookup, NULL))
+	if (of_platform_default_populate(NULL, pic32_auxdata_lookup, NULL))
 		panic("Failed to populate DT");
 
 	return 0;
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:53:05 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:53:05 +0800
Subject: [PATCH v5 12/18] arm: use of_platform_default_populate() to populate
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-13-git-send-email-wangkefeng.wang@huawei.com>

Use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with
the default match table.

Acked-by: Viresh Kumar <viresh.kumar at linaro.org>
Acked-by: Nicolas Ferre <nicolas.ferre at atmel.com>
Cc: Nicolas Ferre <nicolas.ferre at atmel.com>
Cc: Krzysztof Halasa <khalasa at piap.pl>
Cc: Sekhar Nori <nsekhar at ti.com>
Cc: Shawn Guo <shawnguo at kernel.org>
Cc: Russell King <linux at arm.linux.org.uk>
Cc: Roland Stigge <stigge at antcom.de>
Cc: Jason Cooper <jason at lakedaemon.net>
Cc: Ray Jui <rjui at broadcom.com>
Cc: Viresh Kumar <vireshk at kernel.org>
Cc: Stephen Warren <swarren at wwwdotorg.org>
Cc: Rob Herring <robh at kernel.org>
Cc: Michal Simek <michal.simek at xilinx.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/arm/mach-at91/at91rm9200.c          | 2 +-
 arch/arm/mach-at91/at91sam9.c            | 2 +-
 arch/arm/mach-at91/sama5.c               | 2 +-
 arch/arm/mach-cns3xxx/core.c             | 3 +--
 arch/arm/mach-imx/mach-imx6q.c           | 2 +-
 arch/arm/mach-imx/mach-imx6sl.c          | 2 +-
 arch/arm/mach-imx/mach-imx6sx.c          | 2 +-
 arch/arm/mach-integrator/integrator_ap.c | 3 +--
 arch/arm/mach-integrator/integrator_cp.c | 3 +--
 arch/arm/mach-lpc32xx/phy3250.c          | 3 +--
 arch/arm/mach-mvebu/kirkwood.c           | 2 +-
 arch/arm/mach-mxs/mach-mxs.c             | 3 +--
 arch/arm/mach-nspire/nspire.c            | 3 +--
 arch/arm/mach-orion5x/board-dt.c         | 3 +--
 arch/arm/mach-spear/spear300.c           | 3 +--
 arch/arm/mach-spear/spear310.c           | 3 +--
 arch/arm/mach-spear/spear320.c           | 3 +--
 arch/arm/mach-spear/spear6xx.c           | 3 +--
 arch/arm/mach-tegra/tegra.c              | 2 +-
 arch/arm/mach-u300/core.c                | 3 +--
 arch/arm/mach-versatile/versatile_dt.c   | 3 +--
 arch/arm/mach-zynq/common.c              | 2 +-
 22 files changed, 22 insertions(+), 35 deletions(-)

diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index 63b4fa2..d068ec3 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -30,7 +30,7 @@ static void __init at91rm9200_dt_device_init(void)
 	if (soc != NULL)
 		soc_dev = soc_device_to_device(soc);
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev);
+	of_platform_default_populate(NULL, NULL, soc_dev);
 
 	at91rm9200_pm_init();
 }
diff --git a/arch/arm/mach-at91/at91sam9.c b/arch/arm/mach-at91/at91sam9.c
index cada2a6..ba28e9c 100644
--- a/arch/arm/mach-at91/at91sam9.c
+++ b/arch/arm/mach-at91/at91sam9.c
@@ -61,7 +61,7 @@ static void __init at91sam9_common_init(void)
 	if (soc != NULL)
 		soc_dev = soc_device_to_device(soc);
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev);
+	of_platform_default_populate(NULL, NULL, soc_dev);
 }
 
 static void __init at91sam9_dt_device_init(void)
diff --git a/arch/arm/mach-at91/sama5.c b/arch/arm/mach-at91/sama5.c
index 922b85f..b272c45 100644
--- a/arch/arm/mach-at91/sama5.c
+++ b/arch/arm/mach-at91/sama5.c
@@ -68,7 +68,7 @@ static void __init sama5_dt_device_init(void)
 	if (soc != NULL)
 		soc_dev = soc_device_to_device(soc);
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev);
+	of_platform_default_populate(NULL, NULL, soc_dev);
 	sama5_pm_init();
 }
 
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index 9b1dc22..03da381 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -395,8 +395,7 @@ static void __init cns3xxx_init(void)
 
 	pm_power_off = cns3xxx_power_off;
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-                        cns3xxx_auxdata, NULL);
+	of_platform_default_populate(NULL, cns3xxx_auxdata, NULL);
 }
 
 static const char *const cns3xxx_dt_compat[] __initconst = {
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index cb27d56..e394070 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -278,7 +278,7 @@ static void __init imx6q_init_machine(void)
 
 	imx6q_enet_phy_init();
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+	of_platform_default_populate(NULL, NULL, parent);
 
 	imx_anatop_init();
 	cpu_is_imx6q() ?  imx6q_pm_init() : imx6dl_pm_init();
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index 3003263..37ae87d 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -52,7 +52,7 @@ static void __init imx6sl_init_machine(void)
 	if (parent == NULL)
 		pr_warn("failed to initialize soc device\n");
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+	of_platform_default_populate(NULL, NULL, parent);
 
 	imx6sl_fec_init();
 	imx_anatop_init();
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 6a0b061..107cfc1 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -72,7 +72,7 @@ static void __init imx6sx_init_machine(void)
 	if (parent == NULL)
 		pr_warn("failed to initialize soc device\n");
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+	of_platform_default_populate(NULL, NULL, parent);
 
 	imx6sx_enet_init();
 	imx_anatop_init();
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 2b118f2..c7bb832 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -240,8 +240,7 @@ static void __init ap_init_of(void)
 	if (!ebi_base)
 		return;
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			ap_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, ap_auxdata_lookup, NULL);
 
 	sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
 	for (i = 0; i < 4; i++) {
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 6f6b051..8252983 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -231,8 +231,7 @@ static void __init intcp_init_of(void)
 	if (!intcp_con_base)
 		return;
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     intcp_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, intcp_auxdata_lookup, NULL);
 }
 
 static const char * intcp_dt_board_compat[] = {
diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c
index 81265e8..0e4cbbe 100644
--- a/arch/arm/mach-lpc32xx/phy3250.c
+++ b/arch/arm/mach-lpc32xx/phy3250.c
@@ -191,8 +191,7 @@ static void __init lpc3250_machine_init(void)
 		LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN,
 		LPC32XX_CLKPWR_TEST_CLK_SEL);
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     lpc32xx_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, lpc32xx_auxdata_lookup, NULL);
 }
 
 static const char *const lpc32xx_dt_compat[] __initconst = {
diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c
index f9d8e1e..8f459ee 100644
--- a/arch/arm/mach-mvebu/kirkwood.c
+++ b/arch/arm/mach-mvebu/kirkwood.c
@@ -179,7 +179,7 @@ static void __init kirkwood_dt_init(void)
 	kirkwood_pm_init();
 	kirkwood_dt_eth_fixup();
 
-	of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL);
+	of_platform_default_populate(NULL, auxdata, NULL);
 }
 
 static const char * const kirkwood_dt_board_compat[] __initconst = {
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index f1ea470..0b7fe74 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -498,8 +498,7 @@ static void __init mxs_machine_init(void)
 	else if (of_machine_is_compatible("msr,m28cu3"))
 		m28cu3_init();
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     NULL, parent);
+	of_platform_default_populate(NULL, NULL, parent);
 
 	mxs_restart_init();
 
diff --git a/arch/arm/mach-nspire/nspire.c b/arch/arm/mach-nspire/nspire.c
index 34c2a1b3..f0808fc 100644
--- a/arch/arm/mach-nspire/nspire.c
+++ b/arch/arm/mach-nspire/nspire.c
@@ -57,8 +57,7 @@ static struct of_dev_auxdata nspire_auxdata[] __initdata = {
 
 static void __init nspire_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-			nspire_auxdata, NULL);
+	of_platform_default_populate(NULL, nspire_auxdata, NULL);
 }
 
 static void nspire_restart(enum reboot_mode mode, const char *cmd)
diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c
index 6f4c2c4..3d36f1d 100644
--- a/arch/arm/mach-orion5x/board-dt.c
+++ b/arch/arm/mach-orion5x/board-dt.c
@@ -63,8 +63,7 @@ static void __init orion5x_dt_init(void)
 	if (of_machine_is_compatible("maxtor,shared-storage-2"))
 		mss2_init();
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     orion5x_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, orion5x_auxdata_lookup, NULL);
 }
 
 static const char *orion5x_dt_compat[] = {
diff --git a/arch/arm/mach-spear/spear300.c b/arch/arm/mach-spear/spear300.c
index 5b32edd..325b895 100644
--- a/arch/arm/mach-spear/spear300.c
+++ b/arch/arm/mach-spear/spear300.c
@@ -194,8 +194,7 @@ static void __init spear300_dt_init(void)
 	pl080_plat_data.slave_channels = spear300_dma_info;
 	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear300_dma_info);
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear300_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, spear300_auxdata_lookup, NULL);
 }
 
 static const char * const spear300_dt_board_compat[] = {
diff --git a/arch/arm/mach-spear/spear310.c b/arch/arm/mach-spear/spear310.c
index 86a44ac..59e173d 100644
--- a/arch/arm/mach-spear/spear310.c
+++ b/arch/arm/mach-spear/spear310.c
@@ -236,8 +236,7 @@ static void __init spear310_dt_init(void)
 	pl080_plat_data.slave_channels = spear310_dma_info;
 	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear310_dma_info);
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear310_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, spear310_auxdata_lookup, NULL);
 }
 
 static const char * const spear310_dt_board_compat[] = {
diff --git a/arch/arm/mach-spear/spear320.c b/arch/arm/mach-spear/spear320.c
index d45d751..0958f68 100644
--- a/arch/arm/mach-spear/spear320.c
+++ b/arch/arm/mach-spear/spear320.c
@@ -240,8 +240,7 @@ static void __init spear320_dt_init(void)
 	pl080_plat_data.slave_channels = spear320_dma_info;
 	pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear320_dma_info);
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear320_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, spear320_auxdata_lookup, NULL);
 }
 
 static const char * const spear320_dt_board_compat[] = {
diff --git a/arch/arm/mach-spear/spear6xx.c b/arch/arm/mach-spear/spear6xx.c
index da26fa5b..ccf3573 100644
--- a/arch/arm/mach-spear/spear6xx.c
+++ b/arch/arm/mach-spear/spear6xx.c
@@ -411,8 +411,7 @@ struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
 
 static void __init spear600_dt_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-			spear6xx_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, spear6xx_auxdata_lookup, NULL);
 }
 
 static const char *spear600_dt_board_compat[] = {
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index 2378fa56..6745a65 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -115,7 +115,7 @@ static void __init tegra_dt_init(void)
 	 * devices
 	 */
 out:
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+	of_platform_default_populate(NULL, NULL, parent);
 }
 
 static void __init paz00_init(void)
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index 546338b..a4910ea 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -391,8 +391,7 @@ static void __init u300_init_machine_dt(void)
 	pinctrl_register_mappings(u300_pinmux_map,
 				  ARRAY_SIZE(u300_pinmux_map));
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			u300_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, u300_auxdata_lookup, NULL);
 
 	/* Enable SEMI self refresh */
 	val = readw(syscon_base + U300_SYSCON_SMCR) |
diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c
index d643b92..3c8d39c 100644
--- a/arch/arm/mach-versatile/versatile_dt.c
+++ b/arch/arm/mach-versatile/versatile_dt.c
@@ -344,8 +344,7 @@ static void __init versatile_dt_init(void)
 
 	versatile_dt_pci_init();
 
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     versatile_auxdata_lookup, NULL);
+	of_platform_default_populate(NULL, versatile_auxdata_lookup, NULL);
 }
 
 static const char *const versatile_dt_match[] __initconst = {
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index da876d2..d12002c 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -141,7 +141,7 @@ out:
 	 * Finished with the static registrations now; fill in the missing
 	 * devices
 	 */
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+	of_platform_default_populate(NULL, NULL, parent);
 
 	platform_device_register(&zynq_cpuidle_device);
 }
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:53:03 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:53:03 +0800
Subject: [PATCH v5 10/18] sh: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-11-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers of
of_platform_populate with default match table.

Cc: Yoshinori Sato <ysato at users.sourceforge.jp>
Cc: Rich Felker <dalias at libc.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/sh/boards/of-generic.c | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c
index b4d4313..911ffb9 100644
--- a/arch/sh/boards/of-generic.c
+++ b/arch/sh/boards/of-generic.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/of.h>
-#include <linux/of_platform.h>
 #include <linux/of_fdt.h>
 #include <linux/clocksource.h>
 #include <linux/irqchip.h>
@@ -179,16 +178,3 @@ void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
 void __init plat_irq_setup(void)
 {
 }
-
-static int __init sh_of_device_init(void)
-{
-	pr_info("SH generic board support: populating platform devices\n");
-	if (of_have_populated_dt()) {
-		of_platform_populate(NULL, of_default_bus_match_table,
-				     NULL, NULL);
-	} else {
-		pr_crit("Device tree not populated\n");
-	}
-	return 0;
-}
-arch_initcall_sync(sh_of_device_init);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:53:04 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:53:04 +0800
Subject: [PATCH v5 11/18] xtensa: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-12-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers of
of_platform_populate with default match table.

Move of_clk_init() into time_init(), then drop xtensa_device_probe() fully.

Cc: Chris Zankel <chris at zankel.net>
Cc: Max Filippov <jcmvbkbc at gmail.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/xtensa/kernel/setup.c | 11 -----------
 arch/xtensa/kernel/time.c  |  2 ++
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 9735691..18af563 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -22,10 +22,8 @@
 #include <linux/bootmem.h>
 #include <linux/kernel.h>
 #include <linux/percpu.h>
-#include <linux/clk-provider.h>
 #include <linux/cpu.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
 # include <linux/console.h>
@@ -252,15 +250,6 @@ void __init early_init_devtree(void *params)
 		strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 }
 
-static int __init xtensa_device_probe(void)
-{
-	of_clk_init(NULL);
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	return 0;
-}
-
-device_initcall(xtensa_device_probe);
-
 #endif /* CONFIG_OF */
 
 /*
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index b9ad9fe..6ec73c9 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -15,6 +15,7 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/time.h>
+#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
@@ -148,6 +149,7 @@ void __init time_init(void)
 	local_timer_setup(0);
 	setup_irq(this_cpu_ptr(&ccount_timer)->evt.irq, &timer_irqaction);
 	sched_clock_register(ccount_sched_clock_read, 32, ccount_freq);
+	of_clk_init(NULL);
 	clocksource_probe();
 }
 
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:53:02 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:53:02 +0800
Subject: [PATCH v5 09/18] nios2: Remove unnecessary of_platform_populate with
 default match table
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-10-git-send-email-wangkefeng.wang@huawei.com>

After patch "of/platform: Add common method to populate default bus",
it is possible for arch code to remove unnecessary callers of
of_platform_populate with default match table.

Cc: Ley Foon Tan <lftan at altera.com>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 arch/nios2/platform/platform.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/arch/nios2/platform/platform.c b/arch/nios2/platform/platform.c
index d478773..2a35154 100644
--- a/arch/nios2/platform/platform.c
+++ b/arch/nios2/platform/platform.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
 #include <linux/err.h>
@@ -39,8 +38,7 @@ static int __init nios2_soc_device_init(void)
 		}
 	}
 
-	return of_platform_populate(NULL, of_default_bus_match_table,
-		NULL, NULL);
+	return 0;
 }
 
 device_initcall(nios2_soc_device_init);
-- 
1.7.12.4



From wangkefeng.wang at huawei.com  Tue May 31 23:53:07 2016
From: wangkefeng.wang at huawei.com (Kefeng Wang)
Date: Wed, 1 Jun 2016 14:53:07 +0800
Subject: [PATCH v5 14/18] bus: imx-weim: use of_platform_default_populate() to
 populate default bus
In-Reply-To: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
References: <1464763991-26634-1-git-send-email-wangkefeng.wang@huawei.com>
Message-ID: <1464763991-26634-15-git-send-email-wangkefeng.wang@huawei.com>

Use helper of_platform_default_populate() in linux/of_platform
when possible, instead of calling of_platform_populate() with
the default match table.

Acked-by: Shawn Guo <shawn.guo at linaro.org>
Cc: Signed-off-by: Huang Shijie <b32955 at freescale.com>
Cc: Shawn Guo <shawn.guo at linaro.org>
Signed-off-by: Kefeng Wang <wangkefeng.wang at huawei.com>
---
 drivers/bus/imx-weim.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index 1827fc4..4bd361d 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -163,9 +163,8 @@ static int __init weim_parse_dt(struct platform_device *pdev,
 	}
 
 	if (have_child)
-		ret = of_platform_populate(pdev->dev.of_node,
-				   of_default_bus_match_table,
-				   NULL, &pdev->dev);
+		ret = of_platform_default_populate(pdev->dev.of_node,
+						   NULL, &pdev->dev);
 	if (ret)
 		dev_err(&pdev->dev, "%s fail to create devices.\n",
 			pdev->dev.of_node->full_name);
-- 
1.7.12.4



